pax_global_header00006660000000000000000000000064126571332200014513gustar00rootroot0000000000000052 comment=95adafc428b5b4be0ddd4d43a7b96658390388bc systemd-229/000077500000000000000000000000001265713322000130615ustar00rootroot00000000000000systemd-229/.dir-locals.el000066400000000000000000000016471265713322000155220ustar00rootroot00000000000000; Sets emacs variables based on mode. ; A list of (major-mode . ((var1 . value1) (var2 . value2))) ; Mode can be nil, which gives default values. ; Note that we set a line width of 119 for .c and XML files, but for everything ; else (such as journal catalog files, unit files, README files) we stick to a ; more conservative 79 characters. ; NOTE: If you update this file make sure to update .vimrc and .editorconfig, ; too. ((nil . ((indent-tabs-mode . nil) (tab-width . 8) (fill-column . 79))) (c-mode . ((fill-column . 119) (c-basic-offset . 8) (eval . (c-set-offset 'substatement-open 0)) (eval . (c-set-offset 'statement-case-open 0)) (eval . (c-set-offset 'case-label 0)) (eval . (c-set-offset 'arglist-intro '++)) (eval . (c-set-offset 'arglist-close 0)))) (nxml-mode . ((nxml-child-indent . 2) (fill-column . 119)))) systemd-229/.editorconfig000066400000000000000000000007331265713322000155410ustar00rootroot00000000000000# EditorConfig configuration for systemd # http://EditorConfig.org # NOTE: If you update this file make sure to update .dir-locals.el and .vimrc, # too. # Top-most EditorConfig file root = true # Unix-style newlines with a newline ending every file, utf-8 charset [*] end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true charset = utf-8 # Match config files, set indent to spaces with width of eight [*.{c,h}] indent_style = space indent_size = 8 systemd-229/.gitattributes000066400000000000000000000000571265713322000157560ustar00rootroot00000000000000*.[ch] whitespace=tab-in-indent,trailing-space systemd-229/.gitignore000066400000000000000000000111131265713322000150460ustar00rootroot00000000000000*.a *.cache *.la *.lo *.log *.o *.plist *.pyc *.stamp *.swp *.trs *~ .config.args .deps/ .dirstamp .libs/ /*.gcda /*.gcno /*.tar.bz2 /*.tar.gz /*.tar.xz /GPATH /GRTAGS /GSYMS /GTAGS /Makefile /TAGS /ata_id /bootctl /build-aux /busctl /cdrom_id /collect /coredumpctl /coverage/ /defined /exported /exported-* /hostnamectl /install-tree /journalctl /libsystemd-*.c /libtool /linuxx64.efi.stub /localectl /loginctl /machinectl /mtd_probe /networkctl /scsi_id /systemadm /systemctl /systemd /systemd-ac-power /systemd-activate /systemd-analyze /systemd-ask-password /systemd-backlight /systemd-binfmt /systemd-bootchart /systemd-bootx64.efi /systemd-bus-proxyd /systemd-cat /systemd-cgls /systemd-cgroups-agent /systemd-cgtop /systemd-coredump /systemd-cryptsetup /systemd-cryptsetup-generator /systemd-dbus1-generator /systemd-debug-generator /systemd-delta /systemd-detect-virt /systemd-escape /systemd-export /systemd-firstboot /systemd-fsck /systemd-fstab-generator /systemd-getty-generator /systemd-gnome-ask-password-agent /systemd-gpt-auto-generator /systemd-hibernate-resume /systemd-hibernate-resume-generator /systemd-hostnamed /systemd-hwdb /systemd-import /systemd-importd /systemd-inhibit /systemd-initctl /systemd-journal-gatewayd /systemd-journal-remote /systemd-journal-upload /systemd-journald /systemd-kmsg-syslogd /systemd-localed /systemd-logind /systemd-machine-id-setup /systemd-machined /systemd-modules-load /systemd-networkd /systemd-networkd-wait-online /systemd-notify /systemd-nspawn /systemd-path /systemd-pull /systemd-quotacheck /systemd-random-seed /systemd-rc-local-generator /systemd-remount-api-vfs /systemd-remount-fs /systemd-reply-password /systemd-resolve /systemd-resolved /systemd-rfkill /systemd-run /systemd-shutdown /systemd-sleep /systemd-socket-proxyd /systemd-stdio-bridge /systemd-sysctl /systemd-system-update-generator /systemd-sysusers /systemd-sysv-generator /systemd-timedated /systemd-timesyncd /systemd-tmpfiles /systemd-tty-ask-password-agent /systemd-uaccess /systemd-udevd /systemd-update-done /systemd-update-utmp /systemd-user-sessions /systemd-vconsole-setup /tags /test-acd /test-acl-util /test-af-list /test-architecture /test-arphrd-list /test-ask-password-api /test-async /test-audit-type /test-barrier /test-bitmap /test-boot-timestamp /test-btrfs /test-bus-benchmark /test-bus-chat /test-bus-cleanup /test-bus-creds /test-bus-error /test-bus-gvariant /test-bus-introspect /test-bus-kernel /test-bus-kernel-bloom /test-bus-marshal /test-bus-match /test-bus-objects /test-bus-policy /test-bus-proxy /test-bus-server /test-bus-signature /test-bus-zero-copy /test-calendarspec /test-cap-list /test-capability /test-catalog /test-cgroup /test-cgroup-mask /test-cgroup-util /test-compress /test-compress-benchmark /test-condition /test-conf-files /test-conf-parser /test-copy /test-coredump-vacuum /test-daemon /test-date /test-device-nodes /test-dnssec-complex /test-dhcp-client /test-dhcp-option /test-dhcp-server /test-dhcp6-client /test-dns-domain /test-dnssec /test-efi-disk.img /test-ellipsize /test-engine /test-env-replace /test-event /test-execute /test-extract-word /test-fdset /test-fileio /test-firewall-util /test-fstab-util /test-hashmap /test-hostname /test-hostname-util /test-id128 /test-inhibit /test-install /test-install-root /test-ipcrm /test-ipv4ll /test-ipv4ll-manual /test-job-type /test-journal /test-journal-enum /test-journal-flush /test-journal-init /test-journal-interleaving /test-journal-match /test-journal-send /test-journal-stream /test-journal-syslog /test-journal-verify /test-json /test-libsystemd-sym* /test-libudev /test-libudev-sym* /test-list /test-lldp /test-local-addresses /test-locale-util /test-log /test-login /test-login-shared /test-login-tables /test-loopback /test-machine-tables /test-mmap-cache /test-namespace /test-ndisc-rs /test-netlink /test-netlink-manual /test-network /test-network-tables /test-ns /test-parse-util /test-path /test-path-lookup /test-path-util /test-prioq /test-process-util /test-pty /test-qcow2 /test-ratelimit /test-rbtree /test-replace-var /test-resolve /test-resolve-tables /test-ring /test-rlimit-util /test-sched-prio /test-set /test-sigbus /test-signal-util /test-siphash24 /test-sleep /test-socket-util /test-ssd /test-strbuf /test-string-util /test-strip-tab-ansi /test-strv /test-strxcpyx /test-tables /test-terminal-util /test-time /test-tmpfiles /test-udev /test-uid-range /test-unaligned /test-unit-file /test-unit-name /test-user-util /test-utf8 /test-util /test-verbs /test-watchdog /test-xml /timedatectl /udevadm /undefined /v4l_id Makefile.in __pycache__/ aclocal.m4 config.h config.h.in config.log config.status configure stamp-* systemd-229/.mailmap000066400000000000000000000065351265713322000145130ustar00rootroot00000000000000Kay Sievers Kay Sievers Kay Sievers Kay Sievers Kay Sievers Kay Sievers Greg Kroah-Hartman Greg Kroah-Hartman Greg Kroah-Hartman Greg Kroah-Hartman Greg Kroah-Hartman Greg Kroah-Hartman Harald Hoyer David Zeuthen David Zeuthen David Zeuthen Hannes Reinecke Scott James Remnant Scott James Remnant Alan Jenkins Alan Jenkins Marco d'Itri Robert Gerus Robert "arachnist" Gerus Fabiano Fidêncio Fabiano Fidencio Martin Pitt Martin Pitt Daniel J Walsh Dave Reisner Diego Elio Pettenò Daniel Elstner Frederic Crozat Ian Campbell Jerone Young Luis Felipe Strano Moraes Mario Limonciello Matthias Clasen Michal Soltys Piter PUNK Richard Hughes Robby Workman Shawn Landden Simon Peeters Tobias Klauser Miklos Vajna William Jon McCann Yin Kangkai Zbigniew Jędrzejewski-Szmek Lennart Poettering Ananth N Mavinakayanahalli Ananth N Mavinakayanahalli Ted Ts'o Tobias Klauser Tobias Klauser Tobias Klauser Tobias Klauser Patrick Mansfield Christophe Varoqui Daniel Stekloff Michael Buesch Olaf Hering Robert Love Arnd Bergmann Tom Rini Paul Mundt Atul Sabharwal Daniel Machon systemd-229/.travis.yml000066400000000000000000000011501265713322000151670ustar00rootroot00000000000000language: c compiler: - gcc before_install: - sudo apt-get update -qq - sudo apt-get install autotools-dev automake autoconf libtool libdbus-1-dev libcap-dev libblkid-dev libmount-dev libpam-dev libcryptsetup-dev libaudit-dev libacl1-dev libattr1-dev libselinux-dev liblzma-dev libgcrypt-dev libqrencode-dev libmicrohttpd-dev gperf python2.7-dev script: ./autogen.sh && ./configure && make V=1 && sudo ./systemd-machine-id-setup && make check && make distcheck after_failure: cat test-suite.log notifications: irc: channels: - "irc.freenode.org#systemd" on_success: change on_failure: always systemd-229/.vimrc000066400000000000000000000013321265713322000142010ustar00rootroot00000000000000" 'set exrc' in ~/.vimrc will read .vimrc from the current directory " Warning: Enabling exrc is dangerous! You can do nearly everything from a " vimrc configuration file, including write operations and shell execution. " You should consider setting 'set secure' as well, which is highly " recommended! " Note that we set a line width of 119 for .c and XML files, but for everything " else (such as journal catalog files, unit files, README files) we stick to a " more conservative 79 characters. " NOTE: If you update this file make sure to update .dir-locals.el and " .editorconfig, too. set tabstop=8 set shiftwidth=8 set expandtab set makeprg=GCC_COLORS=\ make set tw=79 au FileType xml set tw=119 au FileType c set tw=119 systemd-229/.ycm_extra_conf.py000066400000000000000000000030171265713322000165120ustar00rootroot00000000000000import itertools import os import subprocess def GetFlagsFromMakefile(varname): return subprocess.check_output([ "make", "-s", "print-%s" % varname]).decode().split() def Flatten(lists): return list(itertools.chain.from_iterable(lists)) def DirectoryOfThisScript(): return os.path.dirname(os.path.abspath(__file__)) def MakeRelativePathsInFlagsAbsolute(flags, working_directory): if not working_directory: return flags new_flags = [] make_next_absolute = False path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] for flag in flags: new_flag = flag if make_next_absolute: make_next_absolute = False if not flag.startswith('/'): new_flag = os.path.join(working_directory, flag) for path_flag in path_flags: if flag == path_flag: make_next_absolute = True break if flag.startswith(path_flag): path = flag[ len(path_flag): ] new_flag = path_flag + os.path.join(working_directory, path) break if new_flag: new_flags.append(new_flag) return new_flags def FlagsForFile(filename): relative_to = DirectoryOfThisScript() return { 'flags': MakeRelativePathsInFlagsAbsolute(flags, relative_to), 'do_cache': True } flags = Flatten(map(GetFlagsFromMakefile, [ 'AM_CPPFLAGS', 'CPPFLAGS', 'AM_CFLAGS', 'CFLAGS', ])) # these flags cause crashes in libclang, so remove them flags.remove('-Wlogical-op') flags.remove('-Wsuggest-attribute=noreturn') flags.remove('-Wdate-time') # vim: set et ts=2 sw=2: systemd-229/CODING_STYLE000066400000000000000000000374701265713322000147420ustar00rootroot00000000000000- 8ch indent, no tabs, except for files in man/ which are 2ch indent, and still no tabs - We prefer /* comments */ over // comments, please. This is not C++, after all. (Yes we know that C99 supports both kinds of comments, but still, please!) - Don't break code lines too eagerly. We do *not* force line breaks at 80ch, all of today's screens should be much larger than that. But then again, don't overdo it, ~119ch should be enough really. - Variables and functions *must* be static, unless they have a prototype, and are supposed to be exported. - structs in MixedCase (with exceptions, such as public API structs), variables + functions in lower_case. - The destructors always unregister the object from the next bigger object, not the other way around - To minimize strict aliasing violations, we prefer unions over casting - For robustness reasons, destructors should be able to destruct half-initialized objects, too - Error codes are returned as negative Exxx. e.g. return -EINVAL. There are some exceptions: for constructors, it is OK to return NULL on OOM. For lookup functions, NULL is fine too for "not found". Be strict with this. When you write a function that can fail due to more than one cause, it *really* should have "int" as return value for the error code. - Do not bother with error checking whether writing to stdout/stderr worked. - Do not log errors from "library" code, only do so from "main program" code. (With one exception: it is OK to log with DEBUG level from any code, with the exception of maybe inner loops). - Always check OOM. There is no excuse. In program code, you can use "log_oom()" for then printing a short message, but not in "library" code. - Do not issue NSS requests (that includes user name and host name lookups) from PID 1 as this might trigger deadlocks when those lookups involve synchronously talking to services that we would need to start up - Do not synchronously talk to any other service from PID 1, due to risk of deadlocks - Avoid fixed-size string buffers, unless you really know the maximum size and that maximum size is small. They are a source of errors, since they possibly result in truncated strings. It is often nicer to use dynamic memory, alloca() or VLAs. If you do allocate fixed-size strings on the stack, then it is probably only OK if you either use a maximum size such as LINE_MAX, or count in detail the maximum size a string can have. (DECIMAL_STR_MAX and DECIMAL_STR_WIDTH macros are your friends for this!) Or in other words, if you use "char buf[256]" then you are likely doing something wrong! - Stay uniform. For example, always use "usec_t" for time values. Do not mix usec and msec, and usec and whatnot. - Make use of _cleanup_free_ and friends. It makes your code much nicer to read! - Be exceptionally careful when formatting and parsing floating point numbers. Their syntax is locale dependent (i.e. "5.000" in en_US is generally understood as 5, while on de_DE as 5000.). - Try to use this: void foo() { } instead of this: void foo() { } But it is OK if you do not. - Single-line "if" blocks should not be enclosed in {}. Use this: if (foobar) waldo(); instead of this: if (foobar) { waldo(); } - Do not write "foo ()", write "foo()". - Please use streq() and strneq() instead of strcmp(), strncmp() where applicable. - Please do not allocate variables on the stack in the middle of code, even if C99 allows it. Wrong: { a = 5; int b; b = a; } Right: { int b; a = 5; b = a; } - Unless you allocate an array, "double" is always the better choice than "float". Processors speak "double" natively anyway, so this is no speed benefit, and on calls like printf() "float"s get promoted to "double"s anyway, so there is no point. - Do not mix function invocations with variable definitions in one line. Wrong: { int a = foobar(); uint64_t x = 7; } Right: { int a; uint64_t x = 7; a = foobar(); } - Use "goto" for cleaning up, and only use it for that. i.e. you may only jump to the end of a function, and little else. Never jump backwards! - Think about the types you use. If a value cannot sensibly be negative, do not use "int", but use "unsigned". - Use "char" only for actual characters. Use "uint8_t" or "int8_t" when you actually mean a byte-sized signed or unsigned integers. When referring to a generic byte, we generally prefer the unsigned variant "uint8_t". Do not use types based on "short". They *never* make sense. Use ints, longs, long longs, all in unsigned+signed fashion, and the fixed size types uint8_t/uint16_t/uint32_t/uint64_t/int8_t/int16_t/int32_t and so on, as well as size_t, but nothing else. Do not use kernel types like u32 and so on, leave that to the kernel. - Public API calls (i.e. functions exported by our shared libraries) must be marked "_public_" and need to be prefixed with "sd_". No other functions should be prefixed like that. - In public API calls, you *must* validate all your input arguments for programming error with assert_return() and return a sensible return code. In all other calls, it is recommended to check for programming errors with a more brutal assert(). We are more forgiving to public users then for ourselves! Note that assert() and assert_return() really only should be used for detecting programming errors, not for runtime errors. assert() and assert_return() by usage of _likely_() inform the compiler that he should not expect these checks to fail, and they inform fellow programmers about the expected validity and range of parameters. - Never use strtol(), atoi() and similar calls. Use safe_atoli(), safe_atou32() and suchlike instead. They are much nicer to use in most cases and correctly check for parsing errors. - For every function you add, think about whether it is a "logging" function or a "non-logging" function. "Logging" functions do logging on their own, "non-logging" function never log on their own and expect their callers to log. All functions in "library" code, i.e. in src/shared/ and suchlike must be "non-logging". Every time a "logging" function calls a "non-logging" function, it should log about the resulting errors. If a "logging" function calls another "logging" function, then it should not generate log messages, so that log messages are not generated twice for the same errors. - Avoid static variables, except for caches and very few other cases. Think about thread-safety! While most of our code is never used in threaded environments, at least the library code should make sure it works correctly in them. Instead of doing a lot of locking for that, we tend to prefer using TLS to do per-thread caching (which only works for small, fixed-size cache objects), or we disable caching for any thread that is not the main thread. Use is_main_thread() to detect whether the calling thread is the main thread. - Command line option parsing: - Do not print full help() on error, be specific about the error. - Do not print messages to stdout on error. - Do not POSIX_ME_HARDER unless necessary, i.e. avoid "+" in option string. - Do not write functions that clobber call-by-reference variables on failure. Use temporary variables for these cases and change the passed in variables only on success. - When you allocate a file descriptor, it should be made O_CLOEXEC right from the beginning, as none of our files should leak to forked binaries by default. Hence, whenever you open a file, O_CLOEXEC must be specified, right from the beginning. This also applies to sockets. Effectively this means that all invocations to: a) open() must get O_CLOEXEC passed b) socket() and socketpair() must get SOCK_CLOEXEC passed c) recvmsg() must get MSG_CMSG_CLOEXEC set d) F_DUPFD_CLOEXEC should be used instead of F_DUPFD, and so on - We never use the POSIX version of basename() (which glibc defines it in libgen.h), only the GNU version (which glibc defines in string.h). The only reason to include libgen.h is because dirname() is needed. Everytime you need that please immediately undefine basename(), and add a comment about it, so that no code ever ends up using the POSIX version! - Use the bool type for booleans, not integers. One exception: in public headers (i.e those in src/systemd/sd-*.h) use integers after all, as "bool" is C99 and in our public APIs we try to stick to C89 (with a few extension). - When you invoke certain calls like unlink(), or mkdir_p() and you know it is safe to ignore the error it might return (because a later call would detect the failure anyway, or because the error is in an error path and you thus couldn't do anything about it anyway), then make this clear by casting the invocation explicitly to (void). Code checks like Coverity understand that, and will not complain about ignored error codes. Hence, please use this: (void) unlink("/foo/bar/baz"); instead of just this: unlink("/foo/bar/baz"); - Don't invoke exit(), ever. It is not replacement for proper error handling. Please escalate errors up your call chain, and use normal "return" to exit from the main function of a process. If you fork()ed off a child process, please use _exit() instead of exit(), so that the exit handlers are not run. - Please never use dup(). Use fcntl(fd, F_DUPFD_CLOEXEC, 3) instead. For two reason: first, you want O_CLOEXEC set on the new fd (see above). Second, dup() will happily duplicate your fd as 0, 1, 2, i.e. stdin, stdout, stderr, should those fds be closed. Given the special semantics of those fds, it's probably a good idea to avoid them. F_DUPFD_CLOEXEC with "3" as parameter avoids them. - When you define a destructor or unref() call for an object, please accept a NULL object and simply treat this as NOP. This is similar to how libc free() works, which accepts NULL pointers and becomes a NOP for them. By following this scheme a lot of if checks can be removed before invoking your destructor, which makes the code substantially more readable and robust. - Related to this: when you define a destructor or unref() call for an object, please make it return the same type it takes and always return NULL from it. This allows writing code like this: p = foobar_unref(p); which will always work regardless if p is initialized or not, and guarantees that p is NULL afterwards, all in just one line. - Use alloca(), but never forget that it is not OK to invoke alloca() within a loop or within function call parameters. alloca() memory is released at the end of a function, and not at the end of a {} block. Thus, if you invoke it in a loop, you keep increasing the stack pointer without ever releasing memory again. (VLAs have better behaviour in this case, so consider using them as an alternative.) Regarding not using alloca() within function parameters, see the BUGS section of the alloca(3) man page. - Use memzero() or even better zero() instead of memset(..., 0, ...) - Instead of using memzero()/memset() to initialize structs allocated on the stack, please try to use c99 structure initializers. It's short, prettier and actually even faster at execution. Hence: struct foobar t = { .foo = 7, .bar = "bazz", }; instead of: struct foobar t; zero(t); t.foo = 7; t.bar = "bazz"; - When returning a return code from main(), please preferably use EXIT_FAILURE and EXIT_SUCCESS as defined by libc. - The order in which header files are included doesn't matter too much. systemd-internal headers must not rely on an include order, so it is safe to include them in any order possible. However, to not clutter global includes, and to make sure internal definitions will not affect global headers, please always include the headers of external components first (these are all headers enclosed in <>), followed by our own exported headers (usually everything that's prefixed by "sd-"), and then followed by internal headers. Furthermore, in all three groups, order all includes alphabetically so duplicate includes can easily be detected. - To implement an endless loop, use "for (;;)" rather than "while (1)". The latter is a bit ugly anyway, since you probably really meant "while (true)"... To avoid the discussion what the right always-true expression for an infinite while() loop is our recommendation is to simply write it without any such expression by using "for (;;)". - Never use the "off_t" type, and particularly avoid it in public APIs. It's really weirdly defined, as it usually is 64bit and we don't support it any other way, but it could in theory also be 32bit. Which one it is depends on a compiler switch chosen by the compiled program, which hence corrupts APIs using it unless they can also follow the program's choice. Moreover, in systemd we should parse values the same way on all architectures and cannot expose off_t values over D-Bus. To avoid any confusion regarding conversion and ABIs, always use simply uint64_t directly. - Commit message subject lines should be prefixed with an appropriate component name of some kind. For example "journal: ", "nspawn: " and so on. - Do not use "Signed-Off-By:" in your commit messages. That's a kernel thing we don't do in the systemd project. - Avoid leaving long-running child processes around, i.e. fork()s that are not followed quickly by an execv() in the child. Resource management is unclear in this case, and memory CoW will result in unexpected penalties in the parent much much later on. - Don't block execution for arbitrary amounts of time using usleep() or a similar call, unless you really know what you do. Just "giving something some time", or so is a lazy excuse. Always wait for the proper event, instead of doing time-based poll loops. - To determine the length of a constant string "foo", don't bother with sizeof("foo")-1, please use strlen("foo") directly. gcc knows strlen() anyway and turns it into a constant expression if possible. - If you want to concatenate two or more strings, consider using strjoin() rather than asprintf(), as the latter is a lot slower. This matters particularly in inner loops. - Please avoid using global variables as much as you can. And if you do use them make sure they are static at least, instead of exported. Especially in library-like code it is important to avoid global variables. Why are global variables bad? They usually hinder generic reusability of code (since they break in threaded programs, and usually would require locking there), and as the code using them has side-effects make programs intransparent. That said, there are many cases where they explicitly make a lot of sense, and are OK to use. For example, the log level and target in log.c is stored in a global variable, and that's OK and probably expected by most. Also in many cases we cache data in global variables. If you add more caches like this, please be careful however, and think about threading. Only use static variables if you are sure that thread-safety doesn't matter in your case. Alternatively consider using TLS, which is pretty easy to use with gcc's "thread_local" concept. It's also OK to store data that is inherently global in global variables, for example data parsed from command lines, see below. - If you parse a command line, and want to store the parsed parameters in global variables, please consider prefixing their names with "arg_". We have been following this naming rule in most of our tools, and we should continue to do so, as it makes it easy to identify command line parameter variables, and makes it clear why it is OK that they are global variables. systemd-229/CONTRIBUTING.md000066400000000000000000000040701265713322000153130ustar00rootroot00000000000000# Contributing We welcome contributions from everyone. However, please follow the following guidelines when posting a GitHub Pull Request or filing a GitHub Issue on the systemd project: ## Filing Issues * We use GitHub Issues **exclusively** for tracking **bugs** and **feature** **requests** of systemd. If you are looking for help, please contact our [mailing list](http://lists.freedesktop.org/mailman/listinfo/systemd-devel) instead. * We only track bugs in the **two** **most** **recently** **released** **versions** of systemd in the GitHub Issue tracker. If you are using an older version of systemd, please contact your distribution's bug tracker instead. * When filing an issue, specify the **systemd** **version** you are experiencing the issue with. Also, indicate which **distribution** you are using. * Please include an explanation how to reproduce the issue you are pointing out. Following these guidelines makes it easier for us to process your issue, and ensures we won't close your issue right-away for being misfiled. ## Posting Pull Requests * Make sure to post PRs only relative to a very recent git master. * Follow our [Coding Style](https://raw.githubusercontent.com/systemd/systemd/master/CODING_STYLE) when contributing code. This is a requirement for all code we merge. * Make sure to run "make check" locally, before posting your PR. We use a CI system, meaning we don't even look at your PR, if the build and tests don't pass. * If you need to update the code in an existing PR, please consider opening a new PR (mentioning in it which old PR it replaces) and closing the old PR. This is much preferable over force-pushing a new patch set into the PR's branch, as commit comments aren't lost that way. That said, we don't follow this rule ourselves quite often, hence this is really just a say as we say, not say as we do... ## Final Words We'd like to apologize in advance if we are not able to process and reply to your issue or PR right-away. We have a lot of work to do, but we are trying our best! Thank you very much for your contributions! systemd-229/DISTRO_PORTING000066400000000000000000000042031265713322000152110ustar00rootroot00000000000000Porting systemd To New Distributions HOWTO: You need to make the follow changes to adapt systemd to your distribution: 1) Find the right configure parameters for: --with-rootprefix= --with-sysvinit-path= --with-sysvrcnd-path= --with-rc-local-script-path-start= --with-rc-local-script-path-stop= --with-kbd-loadkeys= --with-kbd-setfont= --with-tty-gid= --with-ntp-servers= 2) Try it out. Play around (as an ordinary user) with '/usr/lib/systemd/systemd --test --system' for a test run of systemd without booting. This will read the unit files and print the initial transaction it would execute during boot-up. This will also inform you about ordering loops and suchlike NTP POOL: By default, timesyncd uses the Google NTP servers time[1-4].google.com. They serve time that is not standards compliant, and can be up to .5s off. Google does not officially support these servers for the broader audience. Distributions and vendors really should not ship OSes or devices with these NTP servers configured. Instead, please register your own vendor pool at ntp.org and make it the built-in default by passing --with-ntp-servers= to configure. Registering vendor pools is free: http://www.pool.ntp.org/en/vendors.html Again, if you ship your software or device with the default NTP servers, then you will get served wrong time, and will rely on services that might not be supported for long. CONTRIBUTING UPSTREAM: We generally do no longer accept distribution-specific patches to systemd upstream. If you have to make changes to systemd's source code to make it work on your distribution, unless your code is generic enough to be generally useful, we are unlikely to merge it. Please always consider adopting the upstream defaults. If that is not possible, please maintain the relevant patches downstream. Thank you for understanding. systemd-229/LICENSE.GPL2000066400000000000000000000431031265713322000145720ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. systemd-229/LICENSE.LGPL2.1000066400000000000000000000636421265713322000150570ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! systemd-229/Makefile-man.am000066400000000000000000002432671265713322000157040ustar00rootroot00000000000000# Do not edit. Generated by make-man-rules.py. # To regenerate: # 1. Create, update, or remove source .xml files in man/ # 2. Run 'make update-man-list' # 3. Run 'make man' to generate manpages # # To make a man page conditional on a configure switch add # attribute conditional="ENABLE_WHAT" or conditional="WITH_WHAT" # to element. MANPAGES += \ man/bootup.7 \ man/busctl.1 \ man/daemon.7 \ man/file-hierarchy.7 \ man/halt.8 \ man/hostname.5 \ man/journalctl.1 \ man/journald.conf.5 \ man/kernel-command-line.7 \ man/kernel-install.8 \ man/libudev.3 \ man/locale.conf.5 \ man/localtime.5 \ man/machine-id.5 \ man/machine-info.5 \ man/os-release.5 \ man/sd-bus-errors.3 \ man/sd-bus.3 \ man/sd-daemon.3 \ man/sd-event.3 \ man/sd-id128.3 \ man/sd-journal.3 \ man/sd_booted.3 \ man/sd_bus_creds_get_pid.3 \ man/sd_bus_creds_new_from_pid.3 \ man/sd_bus_default.3 \ man/sd_bus_error.3 \ man/sd_bus_error_add_map.3 \ man/sd_bus_message_append.3 \ man/sd_bus_message_append_array.3 \ man/sd_bus_message_append_basic.3 \ man/sd_bus_message_append_string_memfd.3 \ man/sd_bus_message_append_strv.3 \ man/sd_bus_message_get_cookie.3 \ man/sd_bus_message_get_monotonic_usec.3 \ man/sd_bus_negotiate_fds.3 \ man/sd_bus_new.3 \ man/sd_bus_path_encode.3 \ man/sd_bus_request_name.3 \ man/sd_event_add_child.3 \ man/sd_event_add_defer.3 \ man/sd_event_add_io.3 \ man/sd_event_add_signal.3 \ man/sd_event_add_time.3 \ man/sd_event_exit.3 \ man/sd_event_get_fd.3 \ man/sd_event_new.3 \ man/sd_event_now.3 \ man/sd_event_run.3 \ man/sd_event_set_watchdog.3 \ man/sd_event_source_get_event.3 \ man/sd_event_source_get_pending.3 \ man/sd_event_source_set_description.3 \ man/sd_event_source_set_enabled.3 \ man/sd_event_source_set_prepare.3 \ man/sd_event_source_set_priority.3 \ man/sd_event_source_set_userdata.3 \ man/sd_event_source_unref.3 \ man/sd_event_wait.3 \ man/sd_id128_get_machine.3 \ man/sd_id128_randomize.3 \ man/sd_id128_to_string.3 \ man/sd_is_fifo.3 \ man/sd_journal_add_match.3 \ man/sd_journal_enumerate_fields.3 \ man/sd_journal_get_catalog.3 \ man/sd_journal_get_cursor.3 \ man/sd_journal_get_cutoff_realtime_usec.3 \ man/sd_journal_get_data.3 \ man/sd_journal_get_fd.3 \ man/sd_journal_get_realtime_usec.3 \ man/sd_journal_get_usage.3 \ man/sd_journal_has_runtime_files.3 \ man/sd_journal_next.3 \ man/sd_journal_open.3 \ man/sd_journal_print.3 \ man/sd_journal_query_unique.3 \ man/sd_journal_seek_head.3 \ man/sd_journal_stream_fd.3 \ man/sd_listen_fds.3 \ man/sd_machine_get_class.3 \ man/sd_notify.3 \ man/sd_watchdog_enabled.3 \ man/shutdown.8 \ man/sysctl.d.5 \ man/systemctl.1 \ man/systemd-activate.8 \ man/systemd-analyze.1 \ man/systemd-ask-password-console.service.8 \ man/systemd-ask-password.1 \ man/systemd-bus-proxyd.8 \ man/systemd-bus-proxyd.service.8 \ man/systemd-cat.1 \ man/systemd-cgls.1 \ man/systemd-cgtop.1 \ man/systemd-debug-generator.8 \ man/systemd-delta.1 \ man/systemd-detect-virt.1 \ man/systemd-escape.1 \ man/systemd-fsck@.service.8 \ man/systemd-fstab-generator.8 \ man/systemd-getty-generator.8 \ man/systemd-gpt-auto-generator.8 \ man/systemd-halt.service.8 \ man/systemd-hibernate-resume-generator.8 \ man/systemd-hibernate-resume@.service.8 \ man/systemd-inhibit.1 \ man/systemd-initctl.service.8 \ man/systemd-journald.service.8 \ man/systemd-machine-id-commit.service.8 \ man/systemd-machine-id-setup.1 \ man/systemd-notify.1 \ man/systemd-nspawn.1 \ man/systemd-path.1 \ man/systemd-remount-fs.service.8 \ man/systemd-resolve.1 \ man/systemd-run.1 \ man/systemd-sleep.conf.5 \ man/systemd-socket-proxyd.8 \ man/systemd-suspend.service.8 \ man/systemd-sysctl.service.8 \ man/systemd-system-update-generator.8 \ man/systemd-system.conf.5 \ man/systemd-sysusers.8 \ man/systemd-tmpfiles.8 \ man/systemd-tty-ask-password-agent.1 \ man/systemd-udevd.service.8 \ man/systemd-update-done.service.8 \ man/systemd.1 \ man/systemd.automount.5 \ man/systemd.device.5 \ man/systemd.exec.5 \ man/systemd.generator.7 \ man/systemd.journal-fields.7 \ man/systemd.kill.5 \ man/systemd.link.5 \ man/systemd.mount.5 \ man/systemd.nspawn.5 \ man/systemd.path.5 \ man/systemd.preset.5 \ man/systemd.resource-control.5 \ man/systemd.scope.5 \ man/systemd.service.5 \ man/systemd.slice.5 \ man/systemd.socket.5 \ man/systemd.special.7 \ man/systemd.swap.5 \ man/systemd.target.5 \ man/systemd.time.7 \ man/systemd.timer.5 \ man/systemd.unit.5 \ man/telinit.8 \ man/tmpfiles.d.5 \ man/udev.7 \ man/udev.conf.5 \ man/udev_device_get_syspath.3 \ man/udev_device_has_tag.3 \ man/udev_device_new_from_syspath.3 \ man/udev_enumerate_add_match_subsystem.3 \ man/udev_enumerate_new.3 \ man/udev_enumerate_scan_devices.3 \ man/udev_list_entry.3 \ man/udev_monitor_filter_update.3 \ man/udev_monitor_new_from_netlink.3 \ man/udev_monitor_receive_device.3 \ man/udev_new.3 \ man/udevadm.8 MANPAGES_ALIAS += \ man/SD_ALERT.3 \ man/SD_BUS_ERROR_ACCESS_DENIED.3 \ man/SD_BUS_ERROR_ADDRESS_IN_USE.3 \ man/SD_BUS_ERROR_AUTH_FAILED.3 \ man/SD_BUS_ERROR_BAD_ADDRESS.3 \ man/SD_BUS_ERROR_DISCONNECTED.3 \ man/SD_BUS_ERROR_END.3 \ man/SD_BUS_ERROR_FAILED.3 \ man/SD_BUS_ERROR_FILE_EXISTS.3 \ man/SD_BUS_ERROR_FILE_NOT_FOUND.3 \ man/SD_BUS_ERROR_INCONSISTENT_MESSAGE.3 \ man/SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED.3 \ man/SD_BUS_ERROR_INVALID_ARGS.3 \ man/SD_BUS_ERROR_INVALID_SIGNATURE.3 \ man/SD_BUS_ERROR_IO_ERROR.3 \ man/SD_BUS_ERROR_LIMITS_EXCEEDED.3 \ man/SD_BUS_ERROR_MAKE_CONST.3 \ man/SD_BUS_ERROR_MAP.3 \ man/SD_BUS_ERROR_MATCH_RULE_INVALID.3 \ man/SD_BUS_ERROR_MATCH_RULE_NOT_FOUND.3 \ man/SD_BUS_ERROR_NAME_HAS_NO_OWNER.3 \ man/SD_BUS_ERROR_NOT_SUPPORTED.3 \ man/SD_BUS_ERROR_NO_MEMORY.3 \ man/SD_BUS_ERROR_NO_NETWORK.3 \ man/SD_BUS_ERROR_NO_REPLY.3 \ man/SD_BUS_ERROR_NO_SERVER.3 \ man/SD_BUS_ERROR_NULL.3 \ man/SD_BUS_ERROR_PROPERTY_READ_ONLY.3 \ man/SD_BUS_ERROR_SERVICE_UNKNOWN.3 \ man/SD_BUS_ERROR_TIMEOUT.3 \ man/SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN.3 \ man/SD_BUS_ERROR_UNKNOWN_INTERFACE.3 \ man/SD_BUS_ERROR_UNKNOWN_METHOD.3 \ man/SD_BUS_ERROR_UNKNOWN_OBJECT.3 \ man/SD_BUS_ERROR_UNKNOWN_PROPERTY.3 \ man/SD_CRIT.3 \ man/SD_DEBUG.3 \ man/SD_EMERG.3 \ man/SD_ERR.3 \ man/SD_EVENT_ARMED.3 \ man/SD_EVENT_EXITING.3 \ man/SD_EVENT_FINISHED.3 \ man/SD_EVENT_INITIAL.3 \ man/SD_EVENT_OFF.3 \ man/SD_EVENT_ON.3 \ man/SD_EVENT_ONESHOT.3 \ man/SD_EVENT_PENDING.3 \ man/SD_EVENT_PREPARING.3 \ man/SD_EVENT_PRIORITY_IDLE.3 \ man/SD_EVENT_PRIORITY_IMPORTANT.3 \ man/SD_EVENT_PRIORITY_NORMAL.3 \ man/SD_EVENT_RUNNING.3 \ man/SD_ID128_CONST_STR.3 \ man/SD_ID128_FORMAT_STR.3 \ man/SD_ID128_FORMAT_VAL.3 \ man/SD_ID128_MAKE.3 \ man/SD_INFO.3 \ man/SD_JOURNAL_APPEND.3 \ man/SD_JOURNAL_CURRENT_USER.3 \ man/SD_JOURNAL_FOREACH.3 \ man/SD_JOURNAL_FOREACH_BACKWARDS.3 \ man/SD_JOURNAL_FOREACH_DATA.3 \ man/SD_JOURNAL_FOREACH_FIELD.3 \ man/SD_JOURNAL_FOREACH_UNIQUE.3 \ man/SD_JOURNAL_INVALIDATE.3 \ man/SD_JOURNAL_LOCAL_ONLY.3 \ man/SD_JOURNAL_NOP.3 \ man/SD_JOURNAL_RUNTIME_ONLY.3 \ man/SD_JOURNAL_SUPPRESS_LOCATION.3 \ man/SD_JOURNAL_SYSTEM.3 \ man/SD_LISTEN_FDS_START.3 \ man/SD_NOTICE.3 \ man/SD_WARNING.3 \ man/init.1 \ man/journald.conf.d.5 \ man/poweroff.8 \ man/reboot.8 \ man/sd_bus_creds_get_audit_login_uid.3 \ man/sd_bus_creds_get_audit_session_id.3 \ man/sd_bus_creds_get_augmented_mask.3 \ man/sd_bus_creds_get_cgroup.3 \ man/sd_bus_creds_get_cmdline.3 \ man/sd_bus_creds_get_comm.3 \ man/sd_bus_creds_get_description.3 \ man/sd_bus_creds_get_egid.3 \ man/sd_bus_creds_get_euid.3 \ man/sd_bus_creds_get_exe.3 \ man/sd_bus_creds_get_fsgid.3 \ man/sd_bus_creds_get_fsuid.3 \ man/sd_bus_creds_get_gid.3 \ man/sd_bus_creds_get_mask.3 \ man/sd_bus_creds_get_owner_uid.3 \ man/sd_bus_creds_get_ppid.3 \ man/sd_bus_creds_get_selinux_context.3 \ man/sd_bus_creds_get_session.3 \ man/sd_bus_creds_get_sgid.3 \ man/sd_bus_creds_get_slice.3 \ man/sd_bus_creds_get_suid.3 \ man/sd_bus_creds_get_supplementary_gids.3 \ man/sd_bus_creds_get_tid.3 \ man/sd_bus_creds_get_tid_comm.3 \ man/sd_bus_creds_get_tty.3 \ man/sd_bus_creds_get_uid.3 \ man/sd_bus_creds_get_unique_name.3 \ man/sd_bus_creds_get_unit.3 \ man/sd_bus_creds_get_user_slice.3 \ man/sd_bus_creds_get_user_unit.3 \ man/sd_bus_creds_get_well_known_names.3 \ man/sd_bus_creds_has_bounding_cap.3 \ man/sd_bus_creds_has_effective_cap.3 \ man/sd_bus_creds_has_inheritable_cap.3 \ man/sd_bus_creds_has_permitted_cap.3 \ man/sd_bus_creds_ref.3 \ man/sd_bus_creds_unref.3 \ man/sd_bus_creds_unrefp.3 \ man/sd_bus_default_system.3 \ man/sd_bus_default_user.3 \ man/sd_bus_error_copy.3 \ man/sd_bus_error_free.3 \ man/sd_bus_error_get_errno.3 \ man/sd_bus_error_has_name.3 \ man/sd_bus_error_is_set.3 \ man/sd_bus_error_map.3 \ man/sd_bus_error_set.3 \ man/sd_bus_error_set_const.3 \ man/sd_bus_error_set_errno.3 \ man/sd_bus_error_set_errnof.3 \ man/sd_bus_error_set_errnofv.3 \ man/sd_bus_error_setf.3 \ man/sd_bus_message_append_array_iovec.3 \ man/sd_bus_message_append_array_memfd.3 \ man/sd_bus_message_append_array_space.3 \ man/sd_bus_message_append_string_iovec.3 \ man/sd_bus_message_append_string_space.3 \ man/sd_bus_message_get_realtime_usec.3 \ man/sd_bus_message_get_reply_cookie.3 \ man/sd_bus_message_get_seqnum.3 \ man/sd_bus_negotiate_creds.3 \ man/sd_bus_negotiate_timestamp.3 \ man/sd_bus_open.3 \ man/sd_bus_open_system.3 \ man/sd_bus_open_system_machine.3 \ man/sd_bus_open_system_remote.3 \ man/sd_bus_open_user.3 \ man/sd_bus_path_decode.3 \ man/sd_bus_path_decode_many.3 \ man/sd_bus_path_encode_many.3 \ man/sd_bus_ref.3 \ man/sd_bus_release_name.3 \ man/sd_bus_unref.3 \ man/sd_bus_unrefp.3 \ man/sd_event.3 \ man/sd_event_add_exit.3 \ man/sd_event_add_post.3 \ man/sd_event_child_handler_t.3 \ man/sd_event_default.3 \ man/sd_event_dispatch.3 \ man/sd_event_get_exit_code.3 \ man/sd_event_get_state.3 \ man/sd_event_get_tid.3 \ man/sd_event_get_watchdog.3 \ man/sd_event_handler_t.3 \ man/sd_event_io_handler_t.3 \ man/sd_event_loop.3 \ man/sd_event_prepare.3 \ man/sd_event_ref.3 \ man/sd_event_signal_handler_t.3 \ man/sd_event_source.3 \ man/sd_event_source_get_child_pid.3 \ man/sd_event_source_get_description.3 \ man/sd_event_source_get_enabled.3 \ man/sd_event_source_get_io_events.3 \ man/sd_event_source_get_io_fd.3 \ man/sd_event_source_get_io_revents.3 \ man/sd_event_source_get_priority.3 \ man/sd_event_source_get_signal.3 \ man/sd_event_source_get_time.3 \ man/sd_event_source_get_time_accuracy.3 \ man/sd_event_source_get_time_clock.3 \ man/sd_event_source_get_userdata.3 \ man/sd_event_source_ref.3 \ man/sd_event_source_set_io_events.3 \ man/sd_event_source_set_io_fd.3 \ man/sd_event_source_set_time.3 \ man/sd_event_source_set_time_accuracy.3 \ man/sd_event_source_unrefp.3 \ man/sd_event_time_handler_t.3 \ man/sd_event_unref.3 \ man/sd_event_unrefp.3 \ man/sd_id128_equal.3 \ man/sd_id128_from_string.3 \ man/sd_id128_get_boot.3 \ man/sd_id128_t.3 \ man/sd_is_mq.3 \ man/sd_is_socket.3 \ man/sd_is_socket_inet.3 \ man/sd_is_socket_unix.3 \ man/sd_is_special.3 \ man/sd_journal.3 \ man/sd_journal_add_conjunction.3 \ man/sd_journal_add_disjunction.3 \ man/sd_journal_close.3 \ man/sd_journal_enumerate_data.3 \ man/sd_journal_enumerate_unique.3 \ man/sd_journal_flush_matches.3 \ man/sd_journal_get_catalog_for_message_id.3 \ man/sd_journal_get_cutoff_monotonic_usec.3 \ man/sd_journal_get_data_threshold.3 \ man/sd_journal_get_events.3 \ man/sd_journal_get_monotonic_usec.3 \ man/sd_journal_get_timeout.3 \ man/sd_journal_has_persistent_files.3 \ man/sd_journal_next_skip.3 \ man/sd_journal_open_container.3 \ man/sd_journal_open_directory.3 \ man/sd_journal_open_files.3 \ man/sd_journal_perror.3 \ man/sd_journal_previous.3 \ man/sd_journal_previous_skip.3 \ man/sd_journal_printv.3 \ man/sd_journal_process.3 \ man/sd_journal_reliable_fd.3 \ man/sd_journal_restart_data.3 \ man/sd_journal_restart_fields.3 \ man/sd_journal_restart_unique.3 \ man/sd_journal_seek_cursor.3 \ man/sd_journal_seek_monotonic_usec.3 \ man/sd_journal_seek_realtime_usec.3 \ man/sd_journal_seek_tail.3 \ man/sd_journal_send.3 \ man/sd_journal_sendv.3 \ man/sd_journal_set_data_threshold.3 \ man/sd_journal_test_cursor.3 \ man/sd_journal_wait.3 \ man/sd_listen_fds_with_names.3 \ man/sd_machine_get_ifindices.3 \ man/sd_notifyf.3 \ man/sd_pid_notify.3 \ man/sd_pid_notify_with_fds.3 \ man/sd_pid_notifyf.3 \ man/sleep.conf.d.5 \ man/system.conf.d.5 \ man/systemd-ask-password-console.path.8 \ man/systemd-ask-password-wall.path.8 \ man/systemd-ask-password-wall.service.8 \ man/systemd-bus-proxyd.socket.8 \ man/systemd-fsck-root.service.8 \ man/systemd-fsck.8 \ man/systemd-hibernate-resume.8 \ man/systemd-hibernate.service.8 \ man/systemd-hybrid-sleep.service.8 \ man/systemd-initctl.8 \ man/systemd-initctl.socket.8 \ man/systemd-journald-audit.socket.8 \ man/systemd-journald-dev-log.socket.8 \ man/systemd-journald.8 \ man/systemd-journald.socket.8 \ man/systemd-kexec.service.8 \ man/systemd-poweroff.service.8 \ man/systemd-reboot.service.8 \ man/systemd-remount-fs.8 \ man/systemd-shutdown.8 \ man/systemd-sleep.8 \ man/systemd-sysctl.8 \ man/systemd-sysusers.service.8 \ man/systemd-tmpfiles-clean.service.8 \ man/systemd-tmpfiles-clean.timer.8 \ man/systemd-tmpfiles-setup-dev.service.8 \ man/systemd-tmpfiles-setup.service.8 \ man/systemd-udevd-control.socket.8 \ man/systemd-udevd-kernel.socket.8 \ man/systemd-udevd.8 \ man/systemd-update-done.8 \ man/systemd-user.conf.5 \ man/udev_device_get_action.3 \ man/udev_device_get_devlinks_list_entry.3 \ man/udev_device_get_devnode.3 \ man/udev_device_get_devnum.3 \ man/udev_device_get_devpath.3 \ man/udev_device_get_devtype.3 \ man/udev_device_get_driver.3 \ man/udev_device_get_is_initialized.3 \ man/udev_device_get_parent.3 \ man/udev_device_get_parent_with_subsystem_devtype.3 \ man/udev_device_get_properties_list_entry.3 \ man/udev_device_get_property_value.3 \ man/udev_device_get_subsystem.3 \ man/udev_device_get_sysattr_list_entry.3 \ man/udev_device_get_sysattr_value.3 \ man/udev_device_get_sysname.3 \ man/udev_device_get_sysnum.3 \ man/udev_device_get_tags_list_entry.3 \ man/udev_device_get_udev.3 \ man/udev_device_new_from_device_id.3 \ man/udev_device_new_from_devnum.3 \ man/udev_device_new_from_environment.3 \ man/udev_device_new_from_subsystem_sysname.3 \ man/udev_device_ref.3 \ man/udev_device_set_sysattr_value.3 \ man/udev_device_unref.3 \ man/udev_enumerate_add_match_is_initialized.3 \ man/udev_enumerate_add_match_parent.3 \ man/udev_enumerate_add_match_property.3 \ man/udev_enumerate_add_match_sysattr.3 \ man/udev_enumerate_add_match_sysname.3 \ man/udev_enumerate_add_match_tag.3 \ man/udev_enumerate_add_nomatch_subsystem.3 \ man/udev_enumerate_add_nomatch_sysattr.3 \ man/udev_enumerate_add_syspath.3 \ man/udev_enumerate_get_list_entry.3 \ man/udev_enumerate_get_udev.3 \ man/udev_enumerate_ref.3 \ man/udev_enumerate_scan_subsystems.3 \ man/udev_enumerate_unref.3 \ man/udev_list_entry_get_by_name.3 \ man/udev_list_entry_get_name.3 \ man/udev_list_entry_get_next.3 \ man/udev_list_entry_get_value.3 \ man/udev_monitor_enable_receiving.3 \ man/udev_monitor_filter_add_match_subsystem_devtype.3 \ man/udev_monitor_filter_add_match_tag.3 \ man/udev_monitor_filter_remove.3 \ man/udev_monitor_get_fd.3 \ man/udev_monitor_get_udev.3 \ man/udev_monitor_ref.3 \ man/udev_monitor_set_receive_buffer_size.3 \ man/udev_monitor_unref.3 \ man/udev_ref.3 \ man/udev_unref.3 \ man/user.conf.d.5 man/SD_ALERT.3: man/sd-daemon.3 man/SD_BUS_ERROR_ACCESS_DENIED.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_ADDRESS_IN_USE.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_AUTH_FAILED.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_BAD_ADDRESS.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_DISCONNECTED.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_END.3: man/sd_bus_error_add_map.3 man/SD_BUS_ERROR_FAILED.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_FILE_EXISTS.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_FILE_NOT_FOUND.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_INCONSISTENT_MESSAGE.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_INVALID_ARGS.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_INVALID_SIGNATURE.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_IO_ERROR.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_LIMITS_EXCEEDED.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_MAKE_CONST.3: man/sd_bus_error.3 man/SD_BUS_ERROR_MAP.3: man/sd_bus_error_add_map.3 man/SD_BUS_ERROR_MATCH_RULE_INVALID.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_MATCH_RULE_NOT_FOUND.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_NAME_HAS_NO_OWNER.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_NOT_SUPPORTED.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_NO_MEMORY.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_NO_NETWORK.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_NO_REPLY.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_NO_SERVER.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_NULL.3: man/sd_bus_error.3 man/SD_BUS_ERROR_PROPERTY_READ_ONLY.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_SERVICE_UNKNOWN.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_TIMEOUT.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_UNKNOWN_INTERFACE.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_UNKNOWN_METHOD.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_UNKNOWN_OBJECT.3: man/sd-bus-errors.3 man/SD_BUS_ERROR_UNKNOWN_PROPERTY.3: man/sd-bus-errors.3 man/SD_CRIT.3: man/sd-daemon.3 man/SD_DEBUG.3: man/sd-daemon.3 man/SD_EMERG.3: man/sd-daemon.3 man/SD_ERR.3: man/sd-daemon.3 man/SD_EVENT_ARMED.3: man/sd_event_wait.3 man/SD_EVENT_EXITING.3: man/sd_event_wait.3 man/SD_EVENT_FINISHED.3: man/sd_event_wait.3 man/SD_EVENT_INITIAL.3: man/sd_event_wait.3 man/SD_EVENT_OFF.3: man/sd_event_source_set_enabled.3 man/SD_EVENT_ON.3: man/sd_event_source_set_enabled.3 man/SD_EVENT_ONESHOT.3: man/sd_event_source_set_enabled.3 man/SD_EVENT_PENDING.3: man/sd_event_wait.3 man/SD_EVENT_PREPARING.3: man/sd_event_wait.3 man/SD_EVENT_PRIORITY_IDLE.3: man/sd_event_source_set_priority.3 man/SD_EVENT_PRIORITY_IMPORTANT.3: man/sd_event_source_set_priority.3 man/SD_EVENT_PRIORITY_NORMAL.3: man/sd_event_source_set_priority.3 man/SD_EVENT_RUNNING.3: man/sd_event_wait.3 man/SD_ID128_CONST_STR.3: man/sd-id128.3 man/SD_ID128_FORMAT_STR.3: man/sd-id128.3 man/SD_ID128_FORMAT_VAL.3: man/sd-id128.3 man/SD_ID128_MAKE.3: man/sd-id128.3 man/SD_INFO.3: man/sd-daemon.3 man/SD_JOURNAL_APPEND.3: man/sd_journal_get_fd.3 man/SD_JOURNAL_CURRENT_USER.3: man/sd_journal_open.3 man/SD_JOURNAL_FOREACH.3: man/sd_journal_next.3 man/SD_JOURNAL_FOREACH_BACKWARDS.3: man/sd_journal_next.3 man/SD_JOURNAL_FOREACH_DATA.3: man/sd_journal_get_data.3 man/SD_JOURNAL_FOREACH_FIELD.3: man/sd_journal_enumerate_fields.3 man/SD_JOURNAL_FOREACH_UNIQUE.3: man/sd_journal_query_unique.3 man/SD_JOURNAL_INVALIDATE.3: man/sd_journal_get_fd.3 man/SD_JOURNAL_LOCAL_ONLY.3: man/sd_journal_open.3 man/SD_JOURNAL_NOP.3: man/sd_journal_get_fd.3 man/SD_JOURNAL_RUNTIME_ONLY.3: man/sd_journal_open.3 man/SD_JOURNAL_SUPPRESS_LOCATION.3: man/sd_journal_print.3 man/SD_JOURNAL_SYSTEM.3: man/sd_journal_open.3 man/SD_LISTEN_FDS_START.3: man/sd_listen_fds.3 man/SD_NOTICE.3: man/sd-daemon.3 man/SD_WARNING.3: man/sd-daemon.3 man/init.1: man/systemd.1 man/journald.conf.d.5: man/journald.conf.5 man/poweroff.8: man/halt.8 man/reboot.8: man/halt.8 man/sd_bus_creds_get_audit_login_uid.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_audit_session_id.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_augmented_mask.3: man/sd_bus_creds_new_from_pid.3 man/sd_bus_creds_get_cgroup.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_cmdline.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_comm.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_description.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_egid.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_euid.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_exe.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_fsgid.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_fsuid.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_gid.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_mask.3: man/sd_bus_creds_new_from_pid.3 man/sd_bus_creds_get_owner_uid.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_ppid.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_selinux_context.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_session.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_sgid.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_slice.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_suid.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_supplementary_gids.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_tid.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_tid_comm.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_tty.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_uid.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_unique_name.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_unit.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_user_slice.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_user_unit.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_get_well_known_names.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_has_bounding_cap.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_has_effective_cap.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_has_inheritable_cap.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_has_permitted_cap.3: man/sd_bus_creds_get_pid.3 man/sd_bus_creds_ref.3: man/sd_bus_creds_new_from_pid.3 man/sd_bus_creds_unref.3: man/sd_bus_creds_new_from_pid.3 man/sd_bus_creds_unrefp.3: man/sd_bus_creds_new_from_pid.3 man/sd_bus_default_system.3: man/sd_bus_default.3 man/sd_bus_default_user.3: man/sd_bus_default.3 man/sd_bus_error_copy.3: man/sd_bus_error.3 man/sd_bus_error_free.3: man/sd_bus_error.3 man/sd_bus_error_get_errno.3: man/sd_bus_error.3 man/sd_bus_error_has_name.3: man/sd_bus_error.3 man/sd_bus_error_is_set.3: man/sd_bus_error.3 man/sd_bus_error_map.3: man/sd_bus_error_add_map.3 man/sd_bus_error_set.3: man/sd_bus_error.3 man/sd_bus_error_set_const.3: man/sd_bus_error.3 man/sd_bus_error_set_errno.3: man/sd_bus_error.3 man/sd_bus_error_set_errnof.3: man/sd_bus_error.3 man/sd_bus_error_set_errnofv.3: man/sd_bus_error.3 man/sd_bus_error_setf.3: man/sd_bus_error.3 man/sd_bus_message_append_array_iovec.3: man/sd_bus_message_append_array.3 man/sd_bus_message_append_array_memfd.3: man/sd_bus_message_append_array.3 man/sd_bus_message_append_array_space.3: man/sd_bus_message_append_array.3 man/sd_bus_message_append_string_iovec.3: man/sd_bus_message_append_string_memfd.3 man/sd_bus_message_append_string_space.3: man/sd_bus_message_append_string_memfd.3 man/sd_bus_message_get_realtime_usec.3: man/sd_bus_message_get_monotonic_usec.3 man/sd_bus_message_get_reply_cookie.3: man/sd_bus_message_get_cookie.3 man/sd_bus_message_get_seqnum.3: man/sd_bus_message_get_monotonic_usec.3 man/sd_bus_negotiate_creds.3: man/sd_bus_negotiate_fds.3 man/sd_bus_negotiate_timestamp.3: man/sd_bus_negotiate_fds.3 man/sd_bus_open.3: man/sd_bus_default.3 man/sd_bus_open_system.3: man/sd_bus_default.3 man/sd_bus_open_system_machine.3: man/sd_bus_default.3 man/sd_bus_open_system_remote.3: man/sd_bus_default.3 man/sd_bus_open_user.3: man/sd_bus_default.3 man/sd_bus_path_decode.3: man/sd_bus_path_encode.3 man/sd_bus_path_decode_many.3: man/sd_bus_path_encode.3 man/sd_bus_path_encode_many.3: man/sd_bus_path_encode.3 man/sd_bus_ref.3: man/sd_bus_new.3 man/sd_bus_release_name.3: man/sd_bus_request_name.3 man/sd_bus_unref.3: man/sd_bus_new.3 man/sd_bus_unrefp.3: man/sd_bus_new.3 man/sd_event.3: man/sd_event_new.3 man/sd_event_add_exit.3: man/sd_event_add_defer.3 man/sd_event_add_post.3: man/sd_event_add_defer.3 man/sd_event_child_handler_t.3: man/sd_event_add_child.3 man/sd_event_default.3: man/sd_event_new.3 man/sd_event_dispatch.3: man/sd_event_wait.3 man/sd_event_get_exit_code.3: man/sd_event_exit.3 man/sd_event_get_state.3: man/sd_event_wait.3 man/sd_event_get_tid.3: man/sd_event_new.3 man/sd_event_get_watchdog.3: man/sd_event_set_watchdog.3 man/sd_event_handler_t.3: man/sd_event_add_defer.3 man/sd_event_io_handler_t.3: man/sd_event_add_io.3 man/sd_event_loop.3: man/sd_event_run.3 man/sd_event_prepare.3: man/sd_event_wait.3 man/sd_event_ref.3: man/sd_event_new.3 man/sd_event_signal_handler_t.3: man/sd_event_add_signal.3 man/sd_event_source.3: man/sd_event_add_io.3 man/sd_event_source_get_child_pid.3: man/sd_event_add_child.3 man/sd_event_source_get_description.3: man/sd_event_source_set_description.3 man/sd_event_source_get_enabled.3: man/sd_event_source_set_enabled.3 man/sd_event_source_get_io_events.3: man/sd_event_add_io.3 man/sd_event_source_get_io_fd.3: man/sd_event_add_io.3 man/sd_event_source_get_io_revents.3: man/sd_event_add_io.3 man/sd_event_source_get_priority.3: man/sd_event_source_set_priority.3 man/sd_event_source_get_signal.3: man/sd_event_add_signal.3 man/sd_event_source_get_time.3: man/sd_event_add_time.3 man/sd_event_source_get_time_accuracy.3: man/sd_event_add_time.3 man/sd_event_source_get_time_clock.3: man/sd_event_add_time.3 man/sd_event_source_get_userdata.3: man/sd_event_source_set_userdata.3 man/sd_event_source_ref.3: man/sd_event_source_unref.3 man/sd_event_source_set_io_events.3: man/sd_event_add_io.3 man/sd_event_source_set_io_fd.3: man/sd_event_add_io.3 man/sd_event_source_set_time.3: man/sd_event_add_time.3 man/sd_event_source_set_time_accuracy.3: man/sd_event_add_time.3 man/sd_event_source_unrefp.3: man/sd_event_source_unref.3 man/sd_event_time_handler_t.3: man/sd_event_add_time.3 man/sd_event_unref.3: man/sd_event_new.3 man/sd_event_unrefp.3: man/sd_event_new.3 man/sd_id128_equal.3: man/sd-id128.3 man/sd_id128_from_string.3: man/sd_id128_to_string.3 man/sd_id128_get_boot.3: man/sd_id128_get_machine.3 man/sd_id128_t.3: man/sd-id128.3 man/sd_is_mq.3: man/sd_is_fifo.3 man/sd_is_socket.3: man/sd_is_fifo.3 man/sd_is_socket_inet.3: man/sd_is_fifo.3 man/sd_is_socket_unix.3: man/sd_is_fifo.3 man/sd_is_special.3: man/sd_is_fifo.3 man/sd_journal.3: man/sd_journal_open.3 man/sd_journal_add_conjunction.3: man/sd_journal_add_match.3 man/sd_journal_add_disjunction.3: man/sd_journal_add_match.3 man/sd_journal_close.3: man/sd_journal_open.3 man/sd_journal_enumerate_data.3: man/sd_journal_get_data.3 man/sd_journal_enumerate_unique.3: man/sd_journal_query_unique.3 man/sd_journal_flush_matches.3: man/sd_journal_add_match.3 man/sd_journal_get_catalog_for_message_id.3: man/sd_journal_get_catalog.3 man/sd_journal_get_cutoff_monotonic_usec.3: man/sd_journal_get_cutoff_realtime_usec.3 man/sd_journal_get_data_threshold.3: man/sd_journal_get_data.3 man/sd_journal_get_events.3: man/sd_journal_get_fd.3 man/sd_journal_get_monotonic_usec.3: man/sd_journal_get_realtime_usec.3 man/sd_journal_get_timeout.3: man/sd_journal_get_fd.3 man/sd_journal_has_persistent_files.3: man/sd_journal_has_runtime_files.3 man/sd_journal_next_skip.3: man/sd_journal_next.3 man/sd_journal_open_container.3: man/sd_journal_open.3 man/sd_journal_open_directory.3: man/sd_journal_open.3 man/sd_journal_open_files.3: man/sd_journal_open.3 man/sd_journal_perror.3: man/sd_journal_print.3 man/sd_journal_previous.3: man/sd_journal_next.3 man/sd_journal_previous_skip.3: man/sd_journal_next.3 man/sd_journal_printv.3: man/sd_journal_print.3 man/sd_journal_process.3: man/sd_journal_get_fd.3 man/sd_journal_reliable_fd.3: man/sd_journal_get_fd.3 man/sd_journal_restart_data.3: man/sd_journal_get_data.3 man/sd_journal_restart_fields.3: man/sd_journal_enumerate_fields.3 man/sd_journal_restart_unique.3: man/sd_journal_query_unique.3 man/sd_journal_seek_cursor.3: man/sd_journal_seek_head.3 man/sd_journal_seek_monotonic_usec.3: man/sd_journal_seek_head.3 man/sd_journal_seek_realtime_usec.3: man/sd_journal_seek_head.3 man/sd_journal_seek_tail.3: man/sd_journal_seek_head.3 man/sd_journal_send.3: man/sd_journal_print.3 man/sd_journal_sendv.3: man/sd_journal_print.3 man/sd_journal_set_data_threshold.3: man/sd_journal_get_data.3 man/sd_journal_test_cursor.3: man/sd_journal_get_cursor.3 man/sd_journal_wait.3: man/sd_journal_get_fd.3 man/sd_listen_fds_with_names.3: man/sd_listen_fds.3 man/sd_machine_get_ifindices.3: man/sd_machine_get_class.3 man/sd_notifyf.3: man/sd_notify.3 man/sd_pid_notify.3: man/sd_notify.3 man/sd_pid_notify_with_fds.3: man/sd_notify.3 man/sd_pid_notifyf.3: man/sd_notify.3 man/sleep.conf.d.5: man/systemd-sleep.conf.5 man/system.conf.d.5: man/systemd-system.conf.5 man/systemd-ask-password-console.path.8: man/systemd-ask-password-console.service.8 man/systemd-ask-password-wall.path.8: man/systemd-ask-password-console.service.8 man/systemd-ask-password-wall.service.8: man/systemd-ask-password-console.service.8 man/systemd-bus-proxyd.socket.8: man/systemd-bus-proxyd.service.8 man/systemd-fsck-root.service.8: man/systemd-fsck@.service.8 man/systemd-fsck.8: man/systemd-fsck@.service.8 man/systemd-hibernate-resume.8: man/systemd-hibernate-resume@.service.8 man/systemd-hibernate.service.8: man/systemd-suspend.service.8 man/systemd-hybrid-sleep.service.8: man/systemd-suspend.service.8 man/systemd-initctl.8: man/systemd-initctl.service.8 man/systemd-initctl.socket.8: man/systemd-initctl.service.8 man/systemd-journald-audit.socket.8: man/systemd-journald.service.8 man/systemd-journald-dev-log.socket.8: man/systemd-journald.service.8 man/systemd-journald.8: man/systemd-journald.service.8 man/systemd-journald.socket.8: man/systemd-journald.service.8 man/systemd-kexec.service.8: man/systemd-halt.service.8 man/systemd-poweroff.service.8: man/systemd-halt.service.8 man/systemd-reboot.service.8: man/systemd-halt.service.8 man/systemd-remount-fs.8: man/systemd-remount-fs.service.8 man/systemd-shutdown.8: man/systemd-halt.service.8 man/systemd-sleep.8: man/systemd-suspend.service.8 man/systemd-sysctl.8: man/systemd-sysctl.service.8 man/systemd-sysusers.service.8: man/systemd-sysusers.8 man/systemd-tmpfiles-clean.service.8: man/systemd-tmpfiles.8 man/systemd-tmpfiles-clean.timer.8: man/systemd-tmpfiles.8 man/systemd-tmpfiles-setup-dev.service.8: man/systemd-tmpfiles.8 man/systemd-tmpfiles-setup.service.8: man/systemd-tmpfiles.8 man/systemd-udevd-control.socket.8: man/systemd-udevd.service.8 man/systemd-udevd-kernel.socket.8: man/systemd-udevd.service.8 man/systemd-udevd.8: man/systemd-udevd.service.8 man/systemd-update-done.8: man/systemd-update-done.service.8 man/systemd-user.conf.5: man/systemd-system.conf.5 man/udev_device_get_action.3: man/udev_device_get_syspath.3 man/udev_device_get_devlinks_list_entry.3: man/udev_device_has_tag.3 man/udev_device_get_devnode.3: man/udev_device_get_syspath.3 man/udev_device_get_devnum.3: man/udev_device_get_syspath.3 man/udev_device_get_devpath.3: man/udev_device_get_syspath.3 man/udev_device_get_devtype.3: man/udev_device_get_syspath.3 man/udev_device_get_driver.3: man/udev_device_get_syspath.3 man/udev_device_get_is_initialized.3: man/udev_device_get_syspath.3 man/udev_device_get_parent.3: man/udev_device_get_syspath.3 man/udev_device_get_parent_with_subsystem_devtype.3: man/udev_device_get_syspath.3 man/udev_device_get_properties_list_entry.3: man/udev_device_has_tag.3 man/udev_device_get_property_value.3: man/udev_device_has_tag.3 man/udev_device_get_subsystem.3: man/udev_device_get_syspath.3 man/udev_device_get_sysattr_list_entry.3: man/udev_device_has_tag.3 man/udev_device_get_sysattr_value.3: man/udev_device_has_tag.3 man/udev_device_get_sysname.3: man/udev_device_get_syspath.3 man/udev_device_get_sysnum.3: man/udev_device_get_syspath.3 man/udev_device_get_tags_list_entry.3: man/udev_device_has_tag.3 man/udev_device_get_udev.3: man/udev_device_get_syspath.3 man/udev_device_new_from_device_id.3: man/udev_device_new_from_syspath.3 man/udev_device_new_from_devnum.3: man/udev_device_new_from_syspath.3 man/udev_device_new_from_environment.3: man/udev_device_new_from_syspath.3 man/udev_device_new_from_subsystem_sysname.3: man/udev_device_new_from_syspath.3 man/udev_device_ref.3: man/udev_device_new_from_syspath.3 man/udev_device_set_sysattr_value.3: man/udev_device_has_tag.3 man/udev_device_unref.3: man/udev_device_new_from_syspath.3 man/udev_enumerate_add_match_is_initialized.3: man/udev_enumerate_add_match_subsystem.3 man/udev_enumerate_add_match_parent.3: man/udev_enumerate_add_match_subsystem.3 man/udev_enumerate_add_match_property.3: man/udev_enumerate_add_match_subsystem.3 man/udev_enumerate_add_match_sysattr.3: man/udev_enumerate_add_match_subsystem.3 man/udev_enumerate_add_match_sysname.3: man/udev_enumerate_add_match_subsystem.3 man/udev_enumerate_add_match_tag.3: man/udev_enumerate_add_match_subsystem.3 man/udev_enumerate_add_nomatch_subsystem.3: man/udev_enumerate_add_match_subsystem.3 man/udev_enumerate_add_nomatch_sysattr.3: man/udev_enumerate_add_match_subsystem.3 man/udev_enumerate_add_syspath.3: man/udev_enumerate_scan_devices.3 man/udev_enumerate_get_list_entry.3: man/udev_enumerate_scan_devices.3 man/udev_enumerate_get_udev.3: man/udev_enumerate_scan_devices.3 man/udev_enumerate_ref.3: man/udev_enumerate_new.3 man/udev_enumerate_scan_subsystems.3: man/udev_enumerate_scan_devices.3 man/udev_enumerate_unref.3: man/udev_enumerate_new.3 man/udev_list_entry_get_by_name.3: man/udev_list_entry.3 man/udev_list_entry_get_name.3: man/udev_list_entry.3 man/udev_list_entry_get_next.3: man/udev_list_entry.3 man/udev_list_entry_get_value.3: man/udev_list_entry.3 man/udev_monitor_enable_receiving.3: man/udev_monitor_receive_device.3 man/udev_monitor_filter_add_match_subsystem_devtype.3: man/udev_monitor_filter_update.3 man/udev_monitor_filter_add_match_tag.3: man/udev_monitor_filter_update.3 man/udev_monitor_filter_remove.3: man/udev_monitor_filter_update.3 man/udev_monitor_get_fd.3: man/udev_monitor_receive_device.3 man/udev_monitor_get_udev.3: man/udev_monitor_receive_device.3 man/udev_monitor_ref.3: man/udev_monitor_new_from_netlink.3 man/udev_monitor_set_receive_buffer_size.3: man/udev_monitor_receive_device.3 man/udev_monitor_unref.3: man/udev_monitor_new_from_netlink.3 man/udev_ref.3: man/udev_new.3 man/udev_unref.3: man/udev_new.3 man/user.conf.d.5: man/systemd-system.conf.5 man/SD_ALERT.html: man/sd-daemon.html $(html-alias) man/SD_BUS_ERROR_ACCESS_DENIED.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_ADDRESS_IN_USE.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_AUTH_FAILED.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_BAD_ADDRESS.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_DISCONNECTED.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_END.html: man/sd_bus_error_add_map.html $(html-alias) man/SD_BUS_ERROR_FAILED.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_FILE_EXISTS.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_FILE_NOT_FOUND.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_INCONSISTENT_MESSAGE.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_INVALID_ARGS.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_INVALID_SIGNATURE.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_IO_ERROR.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_LIMITS_EXCEEDED.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_MAKE_CONST.html: man/sd_bus_error.html $(html-alias) man/SD_BUS_ERROR_MAP.html: man/sd_bus_error_add_map.html $(html-alias) man/SD_BUS_ERROR_MATCH_RULE_INVALID.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_MATCH_RULE_NOT_FOUND.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_NAME_HAS_NO_OWNER.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_NOT_SUPPORTED.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_NO_MEMORY.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_NO_NETWORK.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_NO_REPLY.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_NO_SERVER.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_NULL.html: man/sd_bus_error.html $(html-alias) man/SD_BUS_ERROR_PROPERTY_READ_ONLY.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_SERVICE_UNKNOWN.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_TIMEOUT.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_UNKNOWN_INTERFACE.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_UNKNOWN_METHOD.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_UNKNOWN_OBJECT.html: man/sd-bus-errors.html $(html-alias) man/SD_BUS_ERROR_UNKNOWN_PROPERTY.html: man/sd-bus-errors.html $(html-alias) man/SD_CRIT.html: man/sd-daemon.html $(html-alias) man/SD_DEBUG.html: man/sd-daemon.html $(html-alias) man/SD_EMERG.html: man/sd-daemon.html $(html-alias) man/SD_ERR.html: man/sd-daemon.html $(html-alias) man/SD_EVENT_ARMED.html: man/sd_event_wait.html $(html-alias) man/SD_EVENT_EXITING.html: man/sd_event_wait.html $(html-alias) man/SD_EVENT_FINISHED.html: man/sd_event_wait.html $(html-alias) man/SD_EVENT_INITIAL.html: man/sd_event_wait.html $(html-alias) man/SD_EVENT_OFF.html: man/sd_event_source_set_enabled.html $(html-alias) man/SD_EVENT_ON.html: man/sd_event_source_set_enabled.html $(html-alias) man/SD_EVENT_ONESHOT.html: man/sd_event_source_set_enabled.html $(html-alias) man/SD_EVENT_PENDING.html: man/sd_event_wait.html $(html-alias) man/SD_EVENT_PREPARING.html: man/sd_event_wait.html $(html-alias) man/SD_EVENT_PRIORITY_IDLE.html: man/sd_event_source_set_priority.html $(html-alias) man/SD_EVENT_PRIORITY_IMPORTANT.html: man/sd_event_source_set_priority.html $(html-alias) man/SD_EVENT_PRIORITY_NORMAL.html: man/sd_event_source_set_priority.html $(html-alias) man/SD_EVENT_RUNNING.html: man/sd_event_wait.html $(html-alias) man/SD_ID128_CONST_STR.html: man/sd-id128.html $(html-alias) man/SD_ID128_FORMAT_STR.html: man/sd-id128.html $(html-alias) man/SD_ID128_FORMAT_VAL.html: man/sd-id128.html $(html-alias) man/SD_ID128_MAKE.html: man/sd-id128.html $(html-alias) man/SD_INFO.html: man/sd-daemon.html $(html-alias) man/SD_JOURNAL_APPEND.html: man/sd_journal_get_fd.html $(html-alias) man/SD_JOURNAL_CURRENT_USER.html: man/sd_journal_open.html $(html-alias) man/SD_JOURNAL_FOREACH.html: man/sd_journal_next.html $(html-alias) man/SD_JOURNAL_FOREACH_BACKWARDS.html: man/sd_journal_next.html $(html-alias) man/SD_JOURNAL_FOREACH_DATA.html: man/sd_journal_get_data.html $(html-alias) man/SD_JOURNAL_FOREACH_FIELD.html: man/sd_journal_enumerate_fields.html $(html-alias) man/SD_JOURNAL_FOREACH_UNIQUE.html: man/sd_journal_query_unique.html $(html-alias) man/SD_JOURNAL_INVALIDATE.html: man/sd_journal_get_fd.html $(html-alias) man/SD_JOURNAL_LOCAL_ONLY.html: man/sd_journal_open.html $(html-alias) man/SD_JOURNAL_NOP.html: man/sd_journal_get_fd.html $(html-alias) man/SD_JOURNAL_RUNTIME_ONLY.html: man/sd_journal_open.html $(html-alias) man/SD_JOURNAL_SUPPRESS_LOCATION.html: man/sd_journal_print.html $(html-alias) man/SD_JOURNAL_SYSTEM.html: man/sd_journal_open.html $(html-alias) man/SD_LISTEN_FDS_START.html: man/sd_listen_fds.html $(html-alias) man/SD_NOTICE.html: man/sd-daemon.html $(html-alias) man/SD_WARNING.html: man/sd-daemon.html $(html-alias) man/init.html: man/systemd.html $(html-alias) man/journald.conf.d.html: man/journald.conf.html $(html-alias) man/poweroff.html: man/halt.html $(html-alias) man/reboot.html: man/halt.html $(html-alias) man/sd_bus_creds_get_audit_login_uid.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_audit_session_id.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_augmented_mask.html: man/sd_bus_creds_new_from_pid.html $(html-alias) man/sd_bus_creds_get_cgroup.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_cmdline.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_comm.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_description.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_egid.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_euid.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_exe.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_fsgid.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_fsuid.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_gid.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_mask.html: man/sd_bus_creds_new_from_pid.html $(html-alias) man/sd_bus_creds_get_owner_uid.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_ppid.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_selinux_context.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_session.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_sgid.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_slice.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_suid.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_supplementary_gids.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_tid.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_tid_comm.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_tty.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_uid.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_unique_name.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_unit.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_user_slice.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_user_unit.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_get_well_known_names.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_has_bounding_cap.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_has_effective_cap.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_has_inheritable_cap.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_has_permitted_cap.html: man/sd_bus_creds_get_pid.html $(html-alias) man/sd_bus_creds_ref.html: man/sd_bus_creds_new_from_pid.html $(html-alias) man/sd_bus_creds_unref.html: man/sd_bus_creds_new_from_pid.html $(html-alias) man/sd_bus_creds_unrefp.html: man/sd_bus_creds_new_from_pid.html $(html-alias) man/sd_bus_default_system.html: man/sd_bus_default.html $(html-alias) man/sd_bus_default_user.html: man/sd_bus_default.html $(html-alias) man/sd_bus_error_copy.html: man/sd_bus_error.html $(html-alias) man/sd_bus_error_free.html: man/sd_bus_error.html $(html-alias) man/sd_bus_error_get_errno.html: man/sd_bus_error.html $(html-alias) man/sd_bus_error_has_name.html: man/sd_bus_error.html $(html-alias) man/sd_bus_error_is_set.html: man/sd_bus_error.html $(html-alias) man/sd_bus_error_map.html: man/sd_bus_error_add_map.html $(html-alias) man/sd_bus_error_set.html: man/sd_bus_error.html $(html-alias) man/sd_bus_error_set_const.html: man/sd_bus_error.html $(html-alias) man/sd_bus_error_set_errno.html: man/sd_bus_error.html $(html-alias) man/sd_bus_error_set_errnof.html: man/sd_bus_error.html $(html-alias) man/sd_bus_error_set_errnofv.html: man/sd_bus_error.html $(html-alias) man/sd_bus_error_setf.html: man/sd_bus_error.html $(html-alias) man/sd_bus_message_append_array_iovec.html: man/sd_bus_message_append_array.html $(html-alias) man/sd_bus_message_append_array_memfd.html: man/sd_bus_message_append_array.html $(html-alias) man/sd_bus_message_append_array_space.html: man/sd_bus_message_append_array.html $(html-alias) man/sd_bus_message_append_string_iovec.html: man/sd_bus_message_append_string_memfd.html $(html-alias) man/sd_bus_message_append_string_space.html: man/sd_bus_message_append_string_memfd.html $(html-alias) man/sd_bus_message_get_realtime_usec.html: man/sd_bus_message_get_monotonic_usec.html $(html-alias) man/sd_bus_message_get_reply_cookie.html: man/sd_bus_message_get_cookie.html $(html-alias) man/sd_bus_message_get_seqnum.html: man/sd_bus_message_get_monotonic_usec.html $(html-alias) man/sd_bus_negotiate_creds.html: man/sd_bus_negotiate_fds.html $(html-alias) man/sd_bus_negotiate_timestamp.html: man/sd_bus_negotiate_fds.html $(html-alias) man/sd_bus_open.html: man/sd_bus_default.html $(html-alias) man/sd_bus_open_system.html: man/sd_bus_default.html $(html-alias) man/sd_bus_open_system_machine.html: man/sd_bus_default.html $(html-alias) man/sd_bus_open_system_remote.html: man/sd_bus_default.html $(html-alias) man/sd_bus_open_user.html: man/sd_bus_default.html $(html-alias) man/sd_bus_path_decode.html: man/sd_bus_path_encode.html $(html-alias) man/sd_bus_path_decode_many.html: man/sd_bus_path_encode.html $(html-alias) man/sd_bus_path_encode_many.html: man/sd_bus_path_encode.html $(html-alias) man/sd_bus_ref.html: man/sd_bus_new.html $(html-alias) man/sd_bus_release_name.html: man/sd_bus_request_name.html $(html-alias) man/sd_bus_unref.html: man/sd_bus_new.html $(html-alias) man/sd_bus_unrefp.html: man/sd_bus_new.html $(html-alias) man/sd_event.html: man/sd_event_new.html $(html-alias) man/sd_event_add_exit.html: man/sd_event_add_defer.html $(html-alias) man/sd_event_add_post.html: man/sd_event_add_defer.html $(html-alias) man/sd_event_child_handler_t.html: man/sd_event_add_child.html $(html-alias) man/sd_event_default.html: man/sd_event_new.html $(html-alias) man/sd_event_dispatch.html: man/sd_event_wait.html $(html-alias) man/sd_event_get_exit_code.html: man/sd_event_exit.html $(html-alias) man/sd_event_get_state.html: man/sd_event_wait.html $(html-alias) man/sd_event_get_tid.html: man/sd_event_new.html $(html-alias) man/sd_event_get_watchdog.html: man/sd_event_set_watchdog.html $(html-alias) man/sd_event_handler_t.html: man/sd_event_add_defer.html $(html-alias) man/sd_event_io_handler_t.html: man/sd_event_add_io.html $(html-alias) man/sd_event_loop.html: man/sd_event_run.html $(html-alias) man/sd_event_prepare.html: man/sd_event_wait.html $(html-alias) man/sd_event_ref.html: man/sd_event_new.html $(html-alias) man/sd_event_signal_handler_t.html: man/sd_event_add_signal.html $(html-alias) man/sd_event_source.html: man/sd_event_add_io.html $(html-alias) man/sd_event_source_get_child_pid.html: man/sd_event_add_child.html $(html-alias) man/sd_event_source_get_description.html: man/sd_event_source_set_description.html $(html-alias) man/sd_event_source_get_enabled.html: man/sd_event_source_set_enabled.html $(html-alias) man/sd_event_source_get_io_events.html: man/sd_event_add_io.html $(html-alias) man/sd_event_source_get_io_fd.html: man/sd_event_add_io.html $(html-alias) man/sd_event_source_get_io_revents.html: man/sd_event_add_io.html $(html-alias) man/sd_event_source_get_priority.html: man/sd_event_source_set_priority.html $(html-alias) man/sd_event_source_get_signal.html: man/sd_event_add_signal.html $(html-alias) man/sd_event_source_get_time.html: man/sd_event_add_time.html $(html-alias) man/sd_event_source_get_time_accuracy.html: man/sd_event_add_time.html $(html-alias) man/sd_event_source_get_time_clock.html: man/sd_event_add_time.html $(html-alias) man/sd_event_source_get_userdata.html: man/sd_event_source_set_userdata.html $(html-alias) man/sd_event_source_ref.html: man/sd_event_source_unref.html $(html-alias) man/sd_event_source_set_io_events.html: man/sd_event_add_io.html $(html-alias) man/sd_event_source_set_io_fd.html: man/sd_event_add_io.html $(html-alias) man/sd_event_source_set_time.html: man/sd_event_add_time.html $(html-alias) man/sd_event_source_set_time_accuracy.html: man/sd_event_add_time.html $(html-alias) man/sd_event_source_unrefp.html: man/sd_event_source_unref.html $(html-alias) man/sd_event_time_handler_t.html: man/sd_event_add_time.html $(html-alias) man/sd_event_unref.html: man/sd_event_new.html $(html-alias) man/sd_event_unrefp.html: man/sd_event_new.html $(html-alias) man/sd_id128_equal.html: man/sd-id128.html $(html-alias) man/sd_id128_from_string.html: man/sd_id128_to_string.html $(html-alias) man/sd_id128_get_boot.html: man/sd_id128_get_machine.html $(html-alias) man/sd_id128_t.html: man/sd-id128.html $(html-alias) man/sd_is_mq.html: man/sd_is_fifo.html $(html-alias) man/sd_is_socket.html: man/sd_is_fifo.html $(html-alias) man/sd_is_socket_inet.html: man/sd_is_fifo.html $(html-alias) man/sd_is_socket_unix.html: man/sd_is_fifo.html $(html-alias) man/sd_is_special.html: man/sd_is_fifo.html $(html-alias) man/sd_journal.html: man/sd_journal_open.html $(html-alias) man/sd_journal_add_conjunction.html: man/sd_journal_add_match.html $(html-alias) man/sd_journal_add_disjunction.html: man/sd_journal_add_match.html $(html-alias) man/sd_journal_close.html: man/sd_journal_open.html $(html-alias) man/sd_journal_enumerate_data.html: man/sd_journal_get_data.html $(html-alias) man/sd_journal_enumerate_unique.html: man/sd_journal_query_unique.html $(html-alias) man/sd_journal_flush_matches.html: man/sd_journal_add_match.html $(html-alias) man/sd_journal_get_catalog_for_message_id.html: man/sd_journal_get_catalog.html $(html-alias) man/sd_journal_get_cutoff_monotonic_usec.html: man/sd_journal_get_cutoff_realtime_usec.html $(html-alias) man/sd_journal_get_data_threshold.html: man/sd_journal_get_data.html $(html-alias) man/sd_journal_get_events.html: man/sd_journal_get_fd.html $(html-alias) man/sd_journal_get_monotonic_usec.html: man/sd_journal_get_realtime_usec.html $(html-alias) man/sd_journal_get_timeout.html: man/sd_journal_get_fd.html $(html-alias) man/sd_journal_has_persistent_files.html: man/sd_journal_has_runtime_files.html $(html-alias) man/sd_journal_next_skip.html: man/sd_journal_next.html $(html-alias) man/sd_journal_open_container.html: man/sd_journal_open.html $(html-alias) man/sd_journal_open_directory.html: man/sd_journal_open.html $(html-alias) man/sd_journal_open_files.html: man/sd_journal_open.html $(html-alias) man/sd_journal_perror.html: man/sd_journal_print.html $(html-alias) man/sd_journal_previous.html: man/sd_journal_next.html $(html-alias) man/sd_journal_previous_skip.html: man/sd_journal_next.html $(html-alias) man/sd_journal_printv.html: man/sd_journal_print.html $(html-alias) man/sd_journal_process.html: man/sd_journal_get_fd.html $(html-alias) man/sd_journal_reliable_fd.html: man/sd_journal_get_fd.html $(html-alias) man/sd_journal_restart_data.html: man/sd_journal_get_data.html $(html-alias) man/sd_journal_restart_fields.html: man/sd_journal_enumerate_fields.html $(html-alias) man/sd_journal_restart_unique.html: man/sd_journal_query_unique.html $(html-alias) man/sd_journal_seek_cursor.html: man/sd_journal_seek_head.html $(html-alias) man/sd_journal_seek_monotonic_usec.html: man/sd_journal_seek_head.html $(html-alias) man/sd_journal_seek_realtime_usec.html: man/sd_journal_seek_head.html $(html-alias) man/sd_journal_seek_tail.html: man/sd_journal_seek_head.html $(html-alias) man/sd_journal_send.html: man/sd_journal_print.html $(html-alias) man/sd_journal_sendv.html: man/sd_journal_print.html $(html-alias) man/sd_journal_set_data_threshold.html: man/sd_journal_get_data.html $(html-alias) man/sd_journal_test_cursor.html: man/sd_journal_get_cursor.html $(html-alias) man/sd_journal_wait.html: man/sd_journal_get_fd.html $(html-alias) man/sd_listen_fds_with_names.html: man/sd_listen_fds.html $(html-alias) man/sd_machine_get_ifindices.html: man/sd_machine_get_class.html $(html-alias) man/sd_notifyf.html: man/sd_notify.html $(html-alias) man/sd_pid_notify.html: man/sd_notify.html $(html-alias) man/sd_pid_notify_with_fds.html: man/sd_notify.html $(html-alias) man/sd_pid_notifyf.html: man/sd_notify.html $(html-alias) man/sleep.conf.d.html: man/systemd-sleep.conf.html $(html-alias) man/system.conf.d.html: man/systemd-system.conf.html $(html-alias) man/systemd-ask-password-console.path.html: man/systemd-ask-password-console.service.html $(html-alias) man/systemd-ask-password-wall.path.html: man/systemd-ask-password-console.service.html $(html-alias) man/systemd-ask-password-wall.service.html: man/systemd-ask-password-console.service.html $(html-alias) man/systemd-bus-proxyd.socket.html: man/systemd-bus-proxyd.service.html $(html-alias) man/systemd-fsck-root.service.html: man/systemd-fsck@.service.html $(html-alias) man/systemd-fsck.html: man/systemd-fsck@.service.html $(html-alias) man/systemd-hibernate-resume.html: man/systemd-hibernate-resume@.service.html $(html-alias) man/systemd-hibernate.service.html: man/systemd-suspend.service.html $(html-alias) man/systemd-hybrid-sleep.service.html: man/systemd-suspend.service.html $(html-alias) man/systemd-initctl.html: man/systemd-initctl.service.html $(html-alias) man/systemd-initctl.socket.html: man/systemd-initctl.service.html $(html-alias) man/systemd-journald-audit.socket.html: man/systemd-journald.service.html $(html-alias) man/systemd-journald-dev-log.socket.html: man/systemd-journald.service.html $(html-alias) man/systemd-journald.html: man/systemd-journald.service.html $(html-alias) man/systemd-journald.socket.html: man/systemd-journald.service.html $(html-alias) man/systemd-kexec.service.html: man/systemd-halt.service.html $(html-alias) man/systemd-poweroff.service.html: man/systemd-halt.service.html $(html-alias) man/systemd-reboot.service.html: man/systemd-halt.service.html $(html-alias) man/systemd-remount-fs.html: man/systemd-remount-fs.service.html $(html-alias) man/systemd-shutdown.html: man/systemd-halt.service.html $(html-alias) man/systemd-sleep.html: man/systemd-suspend.service.html $(html-alias) man/systemd-sysctl.html: man/systemd-sysctl.service.html $(html-alias) man/systemd-sysusers.service.html: man/systemd-sysusers.html $(html-alias) man/systemd-tmpfiles-clean.service.html: man/systemd-tmpfiles.html $(html-alias) man/systemd-tmpfiles-clean.timer.html: man/systemd-tmpfiles.html $(html-alias) man/systemd-tmpfiles-setup-dev.service.html: man/systemd-tmpfiles.html $(html-alias) man/systemd-tmpfiles-setup.service.html: man/systemd-tmpfiles.html $(html-alias) man/systemd-udevd-control.socket.html: man/systemd-udevd.service.html $(html-alias) man/systemd-udevd-kernel.socket.html: man/systemd-udevd.service.html $(html-alias) man/systemd-udevd.html: man/systemd-udevd.service.html $(html-alias) man/systemd-update-done.html: man/systemd-update-done.service.html $(html-alias) man/systemd-user.conf.html: man/systemd-system.conf.html $(html-alias) man/udev_device_get_action.html: man/udev_device_get_syspath.html $(html-alias) man/udev_device_get_devlinks_list_entry.html: man/udev_device_has_tag.html $(html-alias) man/udev_device_get_devnode.html: man/udev_device_get_syspath.html $(html-alias) man/udev_device_get_devnum.html: man/udev_device_get_syspath.html $(html-alias) man/udev_device_get_devpath.html: man/udev_device_get_syspath.html $(html-alias) man/udev_device_get_devtype.html: man/udev_device_get_syspath.html $(html-alias) man/udev_device_get_driver.html: man/udev_device_get_syspath.html $(html-alias) man/udev_device_get_is_initialized.html: man/udev_device_get_syspath.html $(html-alias) man/udev_device_get_parent.html: man/udev_device_get_syspath.html $(html-alias) man/udev_device_get_parent_with_subsystem_devtype.html: man/udev_device_get_syspath.html $(html-alias) man/udev_device_get_properties_list_entry.html: man/udev_device_has_tag.html $(html-alias) man/udev_device_get_property_value.html: man/udev_device_has_tag.html $(html-alias) man/udev_device_get_subsystem.html: man/udev_device_get_syspath.html $(html-alias) man/udev_device_get_sysattr_list_entry.html: man/udev_device_has_tag.html $(html-alias) man/udev_device_get_sysattr_value.html: man/udev_device_has_tag.html $(html-alias) man/udev_device_get_sysname.html: man/udev_device_get_syspath.html $(html-alias) man/udev_device_get_sysnum.html: man/udev_device_get_syspath.html $(html-alias) man/udev_device_get_tags_list_entry.html: man/udev_device_has_tag.html $(html-alias) man/udev_device_get_udev.html: man/udev_device_get_syspath.html $(html-alias) man/udev_device_new_from_device_id.html: man/udev_device_new_from_syspath.html $(html-alias) man/udev_device_new_from_devnum.html: man/udev_device_new_from_syspath.html $(html-alias) man/udev_device_new_from_environment.html: man/udev_device_new_from_syspath.html $(html-alias) man/udev_device_new_from_subsystem_sysname.html: man/udev_device_new_from_syspath.html $(html-alias) man/udev_device_ref.html: man/udev_device_new_from_syspath.html $(html-alias) man/udev_device_set_sysattr_value.html: man/udev_device_has_tag.html $(html-alias) man/udev_device_unref.html: man/udev_device_new_from_syspath.html $(html-alias) man/udev_enumerate_add_match_is_initialized.html: man/udev_enumerate_add_match_subsystem.html $(html-alias) man/udev_enumerate_add_match_parent.html: man/udev_enumerate_add_match_subsystem.html $(html-alias) man/udev_enumerate_add_match_property.html: man/udev_enumerate_add_match_subsystem.html $(html-alias) man/udev_enumerate_add_match_sysattr.html: man/udev_enumerate_add_match_subsystem.html $(html-alias) man/udev_enumerate_add_match_sysname.html: man/udev_enumerate_add_match_subsystem.html $(html-alias) man/udev_enumerate_add_match_tag.html: man/udev_enumerate_add_match_subsystem.html $(html-alias) man/udev_enumerate_add_nomatch_subsystem.html: man/udev_enumerate_add_match_subsystem.html $(html-alias) man/udev_enumerate_add_nomatch_sysattr.html: man/udev_enumerate_add_match_subsystem.html $(html-alias) man/udev_enumerate_add_syspath.html: man/udev_enumerate_scan_devices.html $(html-alias) man/udev_enumerate_get_list_entry.html: man/udev_enumerate_scan_devices.html $(html-alias) man/udev_enumerate_get_udev.html: man/udev_enumerate_scan_devices.html $(html-alias) man/udev_enumerate_ref.html: man/udev_enumerate_new.html $(html-alias) man/udev_enumerate_scan_subsystems.html: man/udev_enumerate_scan_devices.html $(html-alias) man/udev_enumerate_unref.html: man/udev_enumerate_new.html $(html-alias) man/udev_list_entry_get_by_name.html: man/udev_list_entry.html $(html-alias) man/udev_list_entry_get_name.html: man/udev_list_entry.html $(html-alias) man/udev_list_entry_get_next.html: man/udev_list_entry.html $(html-alias) man/udev_list_entry_get_value.html: man/udev_list_entry.html $(html-alias) man/udev_monitor_enable_receiving.html: man/udev_monitor_receive_device.html $(html-alias) man/udev_monitor_filter_add_match_subsystem_devtype.html: man/udev_monitor_filter_update.html $(html-alias) man/udev_monitor_filter_add_match_tag.html: man/udev_monitor_filter_update.html $(html-alias) man/udev_monitor_filter_remove.html: man/udev_monitor_filter_update.html $(html-alias) man/udev_monitor_get_fd.html: man/udev_monitor_receive_device.html $(html-alias) man/udev_monitor_get_udev.html: man/udev_monitor_receive_device.html $(html-alias) man/udev_monitor_ref.html: man/udev_monitor_new_from_netlink.html $(html-alias) man/udev_monitor_set_receive_buffer_size.html: man/udev_monitor_receive_device.html $(html-alias) man/udev_monitor_unref.html: man/udev_monitor_new_from_netlink.html $(html-alias) man/udev_ref.html: man/udev_new.html $(html-alias) man/udev_unref.html: man/udev_new.html $(html-alias) man/user.conf.d.html: man/systemd-system.conf.html $(html-alias) if ENABLE_BACKLIGHT MANPAGES += \ man/systemd-backlight@.service.8 MANPAGES_ALIAS += \ man/systemd-backlight.8 man/systemd-backlight.8: man/systemd-backlight@.service.8 man/systemd-backlight.html: man/systemd-backlight@.service.html $(html-alias) endif if ENABLE_BINFMT MANPAGES += \ man/binfmt.d.5 \ man/systemd-binfmt.service.8 MANPAGES_ALIAS += \ man/systemd-binfmt.8 man/systemd-binfmt.8: man/systemd-binfmt.service.8 man/systemd-binfmt.html: man/systemd-binfmt.service.html $(html-alias) endif if ENABLE_BOOTCHART MANPAGES += \ man/bootchart.conf.5 \ man/systemd-bootchart.1 MANPAGES_ALIAS += \ man/bootchart.conf.d.5 man/bootchart.conf.d.5: man/bootchart.conf.5 man/bootchart.conf.d.html: man/bootchart.conf.html $(html-alias) endif if ENABLE_COREDUMP MANPAGES += \ man/coredump.conf.5 \ man/coredumpctl.1 \ man/systemd-coredump.8 MANPAGES_ALIAS += \ man/coredump.conf.d.5 man/coredump.conf.d.5: man/coredump.conf.5 man/coredump.conf.d.html: man/coredump.conf.html $(html-alias) endif if ENABLE_EFI MANPAGES += \ man/bootctl.1 MANPAGES_ALIAS += \ # endif if ENABLE_FIRSTBOOT MANPAGES += \ man/systemd-firstboot.1 MANPAGES_ALIAS += \ man/systemd-firstboot.service.1 man/systemd-firstboot.service.1: man/systemd-firstboot.1 man/systemd-firstboot.service.html: man/systemd-firstboot.html $(html-alias) endif if ENABLE_HOSTNAMED MANPAGES += \ man/hostnamectl.1 \ man/systemd-hostnamed.service.8 MANPAGES_ALIAS += \ man/systemd-hostnamed.8 man/systemd-hostnamed.8: man/systemd-hostnamed.service.8 man/systemd-hostnamed.html: man/systemd-hostnamed.service.html $(html-alias) endif if ENABLE_HWDB MANPAGES += \ man/hwdb.7 \ man/systemd-hwdb.8 MANPAGES_ALIAS += \ # endif if ENABLE_LOCALED MANPAGES += \ man/localectl.1 \ man/systemd-localed.service.8 MANPAGES_ALIAS += \ man/systemd-localed.8 man/systemd-localed.8: man/systemd-localed.service.8 man/systemd-localed.html: man/systemd-localed.service.html $(html-alias) endif if ENABLE_LOGIND MANPAGES += \ man/loginctl.1 \ man/logind.conf.5 \ man/systemd-logind.service.8 MANPAGES_ALIAS += \ man/logind.conf.d.5 \ man/systemd-logind.8 man/logind.conf.d.5: man/logind.conf.5 man/systemd-logind.8: man/systemd-logind.service.8 man/logind.conf.d.html: man/logind.conf.html $(html-alias) man/systemd-logind.html: man/systemd-logind.service.html $(html-alias) endif if ENABLE_MACHINED MANPAGES += \ man/machinectl.1 \ man/nss-mymachines.8 \ man/systemd-machined.service.8 MANPAGES_ALIAS += \ man/libnss_mymachines.so.2.8 \ man/systemd-machined.8 man/libnss_mymachines.so.2.8: man/nss-mymachines.8 man/systemd-machined.8: man/systemd-machined.service.8 man/libnss_mymachines.so.2.html: man/nss-mymachines.html $(html-alias) man/systemd-machined.html: man/systemd-machined.service.html $(html-alias) endif if ENABLE_NETWORKD MANPAGES += \ man/networkctl.1 \ man/systemd-networkd-wait-online.service.8 \ man/systemd-networkd.service.8 \ man/systemd.netdev.5 \ man/systemd.network.5 MANPAGES_ALIAS += \ man/systemd-networkd-wait-online.8 \ man/systemd-networkd.8 man/systemd-networkd-wait-online.8: man/systemd-networkd-wait-online.service.8 man/systemd-networkd.8: man/systemd-networkd.service.8 man/systemd-networkd-wait-online.html: man/systemd-networkd-wait-online.service.html $(html-alias) man/systemd-networkd.html: man/systemd-networkd.service.html $(html-alias) endif if ENABLE_QUOTACHECK MANPAGES += \ man/systemd-quotacheck.service.8 MANPAGES_ALIAS += \ man/systemd-quotacheck.8 man/systemd-quotacheck.8: man/systemd-quotacheck.service.8 man/systemd-quotacheck.html: man/systemd-quotacheck.service.html $(html-alias) endif if ENABLE_RANDOMSEED MANPAGES += \ man/systemd-random-seed.service.8 MANPAGES_ALIAS += \ man/systemd-random-seed.8 man/systemd-random-seed.8: man/systemd-random-seed.service.8 man/systemd-random-seed.html: man/systemd-random-seed.service.html $(html-alias) endif if ENABLE_RESOLVED MANPAGES += \ man/dnssec-trust-anchors.d.5 \ man/nss-resolve.8 \ man/resolved.conf.5 \ man/systemd-resolved.service.8 MANPAGES_ALIAS += \ man/libnss_resolve.so.2.8 \ man/resolved.conf.d.5 \ man/systemd-resolved.8 \ man/systemd.negative.5 \ man/systemd.positive.5 man/libnss_resolve.so.2.8: man/nss-resolve.8 man/resolved.conf.d.5: man/resolved.conf.5 man/systemd-resolved.8: man/systemd-resolved.service.8 man/systemd.negative.5: man/dnssec-trust-anchors.d.5 man/systemd.positive.5: man/dnssec-trust-anchors.d.5 man/libnss_resolve.so.2.html: man/nss-resolve.html $(html-alias) man/resolved.conf.d.html: man/resolved.conf.html $(html-alias) man/systemd-resolved.html: man/systemd-resolved.service.html $(html-alias) man/systemd.negative.html: man/dnssec-trust-anchors.d.html $(html-alias) man/systemd.positive.html: man/dnssec-trust-anchors.d.html $(html-alias) endif if ENABLE_RFKILL MANPAGES += \ man/systemd-rfkill.service.8 MANPAGES_ALIAS += \ man/systemd-rfkill.8 \ man/systemd-rfkill.socket.8 man/systemd-rfkill.8: man/systemd-rfkill.service.8 man/systemd-rfkill.socket.8: man/systemd-rfkill.service.8 man/systemd-rfkill.html: man/systemd-rfkill.service.html $(html-alias) man/systemd-rfkill.socket.html: man/systemd-rfkill.service.html $(html-alias) endif if ENABLE_SYSUSERS MANPAGES += \ man/sysusers.d.5 MANPAGES_ALIAS += \ # endif if ENABLE_TIMEDATED MANPAGES += \ man/systemd-timedated.service.8 \ man/timedatectl.1 MANPAGES_ALIAS += \ man/systemd-timedated.8 man/systemd-timedated.8: man/systemd-timedated.service.8 man/systemd-timedated.html: man/systemd-timedated.service.html $(html-alias) endif if ENABLE_TIMESYNCD MANPAGES += \ man/systemd-timesyncd.service.8 \ man/timesyncd.conf.5 MANPAGES_ALIAS += \ man/systemd-timesyncd.8 \ man/timesyncd.conf.d.5 man/systemd-timesyncd.8: man/systemd-timesyncd.service.8 man/timesyncd.conf.d.5: man/timesyncd.conf.5 man/systemd-timesyncd.html: man/systemd-timesyncd.service.html $(html-alias) man/timesyncd.conf.d.html: man/timesyncd.conf.html $(html-alias) endif if ENABLE_VCONSOLE MANPAGES += \ man/systemd-vconsole-setup.service.8 \ man/vconsole.conf.5 MANPAGES_ALIAS += \ man/systemd-vconsole-setup.8 man/systemd-vconsole-setup.8: man/systemd-vconsole-setup.service.8 man/systemd-vconsole-setup.html: man/systemd-vconsole-setup.service.html $(html-alias) endif if HAVE_KMOD MANPAGES += \ man/modules-load.d.5 \ man/systemd-modules-load.service.8 MANPAGES_ALIAS += \ man/systemd-modules-load.8 man/systemd-modules-load.8: man/systemd-modules-load.service.8 man/systemd-modules-load.html: man/systemd-modules-load.service.html $(html-alias) endif if HAVE_LIBCRYPTSETUP MANPAGES += \ man/crypttab.5 \ man/systemd-cryptsetup-generator.8 \ man/systemd-cryptsetup@.service.8 MANPAGES_ALIAS += \ man/systemd-cryptsetup.8 man/systemd-cryptsetup.8: man/systemd-cryptsetup@.service.8 man/systemd-cryptsetup.html: man/systemd-cryptsetup@.service.html $(html-alias) endif if HAVE_MICROHTTPD MANPAGES += \ man/journal-remote.conf.5 \ man/systemd-journal-gatewayd.service.8 \ man/systemd-journal-remote.8 \ man/systemd-journal-upload.8 MANPAGES_ALIAS += \ man/journal-remote.conf.d.5 \ man/systemd-journal-gatewayd.8 \ man/systemd-journal-gatewayd.socket.8 man/journal-remote.conf.d.5: man/journal-remote.conf.5 man/systemd-journal-gatewayd.8: man/systemd-journal-gatewayd.service.8 man/systemd-journal-gatewayd.socket.8: man/systemd-journal-gatewayd.service.8 man/journal-remote.conf.d.html: man/journal-remote.conf.html $(html-alias) man/systemd-journal-gatewayd.html: man/systemd-journal-gatewayd.service.html $(html-alias) man/systemd-journal-gatewayd.socket.html: man/systemd-journal-gatewayd.service.html $(html-alias) endif if HAVE_MYHOSTNAME MANPAGES += \ man/nss-myhostname.8 MANPAGES_ALIAS += \ man/libnss_myhostname.so.2.8 man/libnss_myhostname.so.2.8: man/nss-myhostname.8 man/libnss_myhostname.so.2.html: man/nss-myhostname.html $(html-alias) endif if HAVE_PAM MANPAGES += \ man/pam_systemd.8 \ man/sd-login.3 \ man/sd_get_seats.3 \ man/sd_login_monitor_new.3 \ man/sd_pid_get_session.3 \ man/sd_seat_get_active.3 \ man/sd_session_is_active.3 \ man/sd_uid_get_state.3 \ man/systemd-user-sessions.service.8 MANPAGES_ALIAS += \ man/sd_get_machine_names.3 \ man/sd_get_sessions.3 \ man/sd_get_uids.3 \ man/sd_login_monitor.3 \ man/sd_login_monitor_flush.3 \ man/sd_login_monitor_get_events.3 \ man/sd_login_monitor_get_fd.3 \ man/sd_login_monitor_get_timeout.3 \ man/sd_login_monitor_unref.3 \ man/sd_login_monitor_unrefp.3 \ man/sd_peer_get_cgroup.3 \ man/sd_peer_get_machine_name.3 \ man/sd_peer_get_owner_uid.3 \ man/sd_peer_get_session.3 \ man/sd_peer_get_slice.3 \ man/sd_peer_get_unit.3 \ man/sd_peer_get_user_slice.3 \ man/sd_peer_get_user_unit.3 \ man/sd_pid_get_cgroup.3 \ man/sd_pid_get_machine_name.3 \ man/sd_pid_get_owner_uid.3 \ man/sd_pid_get_slice.3 \ man/sd_pid_get_unit.3 \ man/sd_pid_get_user_slice.3 \ man/sd_pid_get_user_unit.3 \ man/sd_seat_can_graphical.3 \ man/sd_seat_can_multi_session.3 \ man/sd_seat_can_tty.3 \ man/sd_seat_get_sessions.3 \ man/sd_session_get_class.3 \ man/sd_session_get_desktop.3 \ man/sd_session_get_display.3 \ man/sd_session_get_remote_host.3 \ man/sd_session_get_remote_user.3 \ man/sd_session_get_seat.3 \ man/sd_session_get_service.3 \ man/sd_session_get_state.3 \ man/sd_session_get_tty.3 \ man/sd_session_get_type.3 \ man/sd_session_get_uid.3 \ man/sd_session_get_vt.3 \ man/sd_session_is_remote.3 \ man/sd_uid_get_display.3 \ man/sd_uid_get_seats.3 \ man/sd_uid_get_sessions.3 \ man/sd_uid_is_on_seat.3 \ man/systemd-user-sessions.8 man/sd_get_machine_names.3: man/sd_get_seats.3 man/sd_get_sessions.3: man/sd_get_seats.3 man/sd_get_uids.3: man/sd_get_seats.3 man/sd_login_monitor.3: man/sd_login_monitor_new.3 man/sd_login_monitor_flush.3: man/sd_login_monitor_new.3 man/sd_login_monitor_get_events.3: man/sd_login_monitor_new.3 man/sd_login_monitor_get_fd.3: man/sd_login_monitor_new.3 man/sd_login_monitor_get_timeout.3: man/sd_login_monitor_new.3 man/sd_login_monitor_unref.3: man/sd_login_monitor_new.3 man/sd_login_monitor_unrefp.3: man/sd_login_monitor_new.3 man/sd_peer_get_cgroup.3: man/sd_pid_get_session.3 man/sd_peer_get_machine_name.3: man/sd_pid_get_session.3 man/sd_peer_get_owner_uid.3: man/sd_pid_get_session.3 man/sd_peer_get_session.3: man/sd_pid_get_session.3 man/sd_peer_get_slice.3: man/sd_pid_get_session.3 man/sd_peer_get_unit.3: man/sd_pid_get_session.3 man/sd_peer_get_user_slice.3: man/sd_pid_get_session.3 man/sd_peer_get_user_unit.3: man/sd_pid_get_session.3 man/sd_pid_get_cgroup.3: man/sd_pid_get_session.3 man/sd_pid_get_machine_name.3: man/sd_pid_get_session.3 man/sd_pid_get_owner_uid.3: man/sd_pid_get_session.3 man/sd_pid_get_slice.3: man/sd_pid_get_session.3 man/sd_pid_get_unit.3: man/sd_pid_get_session.3 man/sd_pid_get_user_slice.3: man/sd_pid_get_session.3 man/sd_pid_get_user_unit.3: man/sd_pid_get_session.3 man/sd_seat_can_graphical.3: man/sd_seat_get_active.3 man/sd_seat_can_multi_session.3: man/sd_seat_get_active.3 man/sd_seat_can_tty.3: man/sd_seat_get_active.3 man/sd_seat_get_sessions.3: man/sd_seat_get_active.3 man/sd_session_get_class.3: man/sd_session_is_active.3 man/sd_session_get_desktop.3: man/sd_session_is_active.3 man/sd_session_get_display.3: man/sd_session_is_active.3 man/sd_session_get_remote_host.3: man/sd_session_is_active.3 man/sd_session_get_remote_user.3: man/sd_session_is_active.3 man/sd_session_get_seat.3: man/sd_session_is_active.3 man/sd_session_get_service.3: man/sd_session_is_active.3 man/sd_session_get_state.3: man/sd_session_is_active.3 man/sd_session_get_tty.3: man/sd_session_is_active.3 man/sd_session_get_type.3: man/sd_session_is_active.3 man/sd_session_get_uid.3: man/sd_session_is_active.3 man/sd_session_get_vt.3: man/sd_session_is_active.3 man/sd_session_is_remote.3: man/sd_session_is_active.3 man/sd_uid_get_display.3: man/sd_uid_get_state.3 man/sd_uid_get_seats.3: man/sd_uid_get_state.3 man/sd_uid_get_sessions.3: man/sd_uid_get_state.3 man/sd_uid_is_on_seat.3: man/sd_uid_get_state.3 man/systemd-user-sessions.8: man/systemd-user-sessions.service.8 man/sd_get_machine_names.html: man/sd_get_seats.html $(html-alias) man/sd_get_sessions.html: man/sd_get_seats.html $(html-alias) man/sd_get_uids.html: man/sd_get_seats.html $(html-alias) man/sd_login_monitor.html: man/sd_login_monitor_new.html $(html-alias) man/sd_login_monitor_flush.html: man/sd_login_monitor_new.html $(html-alias) man/sd_login_monitor_get_events.html: man/sd_login_monitor_new.html $(html-alias) man/sd_login_monitor_get_fd.html: man/sd_login_monitor_new.html $(html-alias) man/sd_login_monitor_get_timeout.html: man/sd_login_monitor_new.html $(html-alias) man/sd_login_monitor_unref.html: man/sd_login_monitor_new.html $(html-alias) man/sd_login_monitor_unrefp.html: man/sd_login_monitor_new.html $(html-alias) man/sd_peer_get_cgroup.html: man/sd_pid_get_session.html $(html-alias) man/sd_peer_get_machine_name.html: man/sd_pid_get_session.html $(html-alias) man/sd_peer_get_owner_uid.html: man/sd_pid_get_session.html $(html-alias) man/sd_peer_get_session.html: man/sd_pid_get_session.html $(html-alias) man/sd_peer_get_slice.html: man/sd_pid_get_session.html $(html-alias) man/sd_peer_get_unit.html: man/sd_pid_get_session.html $(html-alias) man/sd_peer_get_user_slice.html: man/sd_pid_get_session.html $(html-alias) man/sd_peer_get_user_unit.html: man/sd_pid_get_session.html $(html-alias) man/sd_pid_get_cgroup.html: man/sd_pid_get_session.html $(html-alias) man/sd_pid_get_machine_name.html: man/sd_pid_get_session.html $(html-alias) man/sd_pid_get_owner_uid.html: man/sd_pid_get_session.html $(html-alias) man/sd_pid_get_slice.html: man/sd_pid_get_session.html $(html-alias) man/sd_pid_get_unit.html: man/sd_pid_get_session.html $(html-alias) man/sd_pid_get_user_slice.html: man/sd_pid_get_session.html $(html-alias) man/sd_pid_get_user_unit.html: man/sd_pid_get_session.html $(html-alias) man/sd_seat_can_graphical.html: man/sd_seat_get_active.html $(html-alias) man/sd_seat_can_multi_session.html: man/sd_seat_get_active.html $(html-alias) man/sd_seat_can_tty.html: man/sd_seat_get_active.html $(html-alias) man/sd_seat_get_sessions.html: man/sd_seat_get_active.html $(html-alias) man/sd_session_get_class.html: man/sd_session_is_active.html $(html-alias) man/sd_session_get_desktop.html: man/sd_session_is_active.html $(html-alias) man/sd_session_get_display.html: man/sd_session_is_active.html $(html-alias) man/sd_session_get_remote_host.html: man/sd_session_is_active.html $(html-alias) man/sd_session_get_remote_user.html: man/sd_session_is_active.html $(html-alias) man/sd_session_get_seat.html: man/sd_session_is_active.html $(html-alias) man/sd_session_get_service.html: man/sd_session_is_active.html $(html-alias) man/sd_session_get_state.html: man/sd_session_is_active.html $(html-alias) man/sd_session_get_tty.html: man/sd_session_is_active.html $(html-alias) man/sd_session_get_type.html: man/sd_session_is_active.html $(html-alias) man/sd_session_get_uid.html: man/sd_session_is_active.html $(html-alias) man/sd_session_get_vt.html: man/sd_session_is_active.html $(html-alias) man/sd_session_is_remote.html: man/sd_session_is_active.html $(html-alias) man/sd_uid_get_display.html: man/sd_uid_get_state.html $(html-alias) man/sd_uid_get_seats.html: man/sd_uid_get_state.html $(html-alias) man/sd_uid_get_sessions.html: man/sd_uid_get_state.html $(html-alias) man/sd_uid_is_on_seat.html: man/sd_uid_get_state.html $(html-alias) man/systemd-user-sessions.html: man/systemd-user-sessions.service.html $(html-alias) endif if HAVE_PYTHON MANPAGES += \ man/systemd.directives.7 \ man/systemd.index.7 MANPAGES_ALIAS += \ # endif if HAVE_SYSV_COMPAT MANPAGES += \ man/systemd-sysv-generator.8 MANPAGES_ALIAS += \ # endif if HAVE_UTMP MANPAGES += \ man/runlevel.8 \ man/systemd-update-utmp.service.8 MANPAGES_ALIAS += \ man/systemd-update-utmp-runlevel.service.8 \ man/systemd-update-utmp.8 man/systemd-update-utmp-runlevel.service.8: man/systemd-update-utmp.service.8 man/systemd-update-utmp.8: man/systemd-update-utmp.service.8 man/systemd-update-utmp-runlevel.service.html: man/systemd-update-utmp.service.html $(html-alias) man/systemd-update-utmp.html: man/systemd-update-utmp.service.html $(html-alias) endif # Really, do not edit this file. EXTRA_DIST += \ man/binfmt.d.xml \ man/bootchart.conf.xml \ man/bootctl.xml \ man/bootup.xml \ man/busctl.xml \ man/coredump.conf.xml \ man/coredumpctl.xml \ man/crypttab.xml \ man/daemon.xml \ man/dnssec-trust-anchors.d.xml \ man/file-hierarchy.xml \ man/halt.xml \ man/hostname.xml \ man/hostnamectl.xml \ man/hwdb.xml \ man/journal-remote.conf.xml \ man/journalctl.xml \ man/journald.conf.xml \ man/kernel-command-line.xml \ man/kernel-install.xml \ man/less-variables.xml \ man/libsystemd-pkgconfig.xml \ man/libudev.xml \ man/locale.conf.xml \ man/localectl.xml \ man/localtime.xml \ man/loginctl.xml \ man/logind.conf.xml \ man/machine-id.xml \ man/machine-info.xml \ man/machinectl.xml \ man/modules-load.d.xml \ man/networkctl.xml \ man/nss-myhostname.xml \ man/nss-mymachines.xml \ man/nss-resolve.xml \ man/os-release.xml \ man/pam_systemd.xml \ man/resolved.conf.xml \ man/runlevel.xml \ man/sd-bus-errors.xml \ man/sd-bus.xml \ man/sd-daemon.xml \ man/sd-event.xml \ man/sd-id128.xml \ man/sd-journal.xml \ man/sd-login.xml \ man/sd_booted.xml \ man/sd_bus_creds_get_pid.xml \ man/sd_bus_creds_new_from_pid.xml \ man/sd_bus_default.xml \ man/sd_bus_error.xml \ man/sd_bus_error_add_map.xml \ man/sd_bus_message_append.xml \ man/sd_bus_message_append_array.xml \ man/sd_bus_message_append_basic.xml \ man/sd_bus_message_append_string_memfd.xml \ man/sd_bus_message_append_strv.xml \ man/sd_bus_message_get_cookie.xml \ man/sd_bus_message_get_monotonic_usec.xml \ man/sd_bus_negotiate_fds.xml \ man/sd_bus_new.xml \ man/sd_bus_path_encode.xml \ man/sd_bus_request_name.xml \ man/sd_event_add_child.xml \ man/sd_event_add_defer.xml \ man/sd_event_add_io.xml \ man/sd_event_add_signal.xml \ man/sd_event_add_time.xml \ man/sd_event_exit.xml \ man/sd_event_get_fd.xml \ man/sd_event_new.xml \ man/sd_event_now.xml \ man/sd_event_run.xml \ man/sd_event_set_watchdog.xml \ man/sd_event_source_get_event.xml \ man/sd_event_source_get_pending.xml \ man/sd_event_source_set_description.xml \ man/sd_event_source_set_enabled.xml \ man/sd_event_source_set_prepare.xml \ man/sd_event_source_set_priority.xml \ man/sd_event_source_set_userdata.xml \ man/sd_event_source_unref.xml \ man/sd_event_wait.xml \ man/sd_get_seats.xml \ man/sd_id128_get_machine.xml \ man/sd_id128_randomize.xml \ man/sd_id128_to_string.xml \ man/sd_is_fifo.xml \ man/sd_journal_add_match.xml \ man/sd_journal_enumerate_fields.xml \ man/sd_journal_get_catalog.xml \ man/sd_journal_get_cursor.xml \ man/sd_journal_get_cutoff_realtime_usec.xml \ man/sd_journal_get_data.xml \ man/sd_journal_get_fd.xml \ man/sd_journal_get_realtime_usec.xml \ man/sd_journal_get_usage.xml \ man/sd_journal_has_runtime_files.xml \ man/sd_journal_next.xml \ man/sd_journal_open.xml \ man/sd_journal_print.xml \ man/sd_journal_query_unique.xml \ man/sd_journal_seek_head.xml \ man/sd_journal_stream_fd.xml \ man/sd_listen_fds.xml \ man/sd_login_monitor_new.xml \ man/sd_machine_get_class.xml \ man/sd_notify.xml \ man/sd_pid_get_session.xml \ man/sd_seat_get_active.xml \ man/sd_session_is_active.xml \ man/sd_uid_get_state.xml \ man/sd_watchdog_enabled.xml \ man/shutdown.xml \ man/standard-conf.xml \ man/standard-options.xml \ man/sysctl.d.xml \ man/systemctl.xml \ man/systemd-activate.xml \ man/systemd-analyze.xml \ man/systemd-ask-password-console.service.xml \ man/systemd-ask-password.xml \ man/systemd-backlight@.service.xml \ man/systemd-binfmt.service.xml \ man/systemd-bootchart.xml \ man/systemd-bus-proxyd.service.xml \ man/systemd-bus-proxyd.xml \ man/systemd-cat.xml \ man/systemd-cgls.xml \ man/systemd-cgtop.xml \ man/systemd-coredump.xml \ man/systemd-cryptsetup-generator.xml \ man/systemd-cryptsetup@.service.xml \ man/systemd-debug-generator.xml \ man/systemd-delta.xml \ man/systemd-detect-virt.xml \ man/systemd-escape.xml \ man/systemd-firstboot.xml \ man/systemd-fsck@.service.xml \ man/systemd-fstab-generator.xml \ man/systemd-getty-generator.xml \ man/systemd-gpt-auto-generator.xml \ man/systemd-halt.service.xml \ man/systemd-hibernate-resume-generator.xml \ man/systemd-hibernate-resume@.service.xml \ man/systemd-hostnamed.service.xml \ man/systemd-hwdb.xml \ man/systemd-inhibit.xml \ man/systemd-initctl.service.xml \ man/systemd-journal-gatewayd.service.xml \ man/systemd-journal-remote.xml \ man/systemd-journal-upload.xml \ man/systemd-journald.service.xml \ man/systemd-localed.service.xml \ man/systemd-logind.service.xml \ man/systemd-machine-id-commit.service.xml \ man/systemd-machine-id-setup.xml \ man/systemd-machined.service.xml \ man/systemd-modules-load.service.xml \ man/systemd-networkd-wait-online.service.xml \ man/systemd-networkd.service.xml \ man/systemd-notify.xml \ man/systemd-nspawn.xml \ man/systemd-path.xml \ man/systemd-quotacheck.service.xml \ man/systemd-random-seed.service.xml \ man/systemd-remount-fs.service.xml \ man/systemd-resolve.xml \ man/systemd-resolved.service.xml \ man/systemd-rfkill.service.xml \ man/systemd-run.xml \ man/systemd-sleep.conf.xml \ man/systemd-socket-proxyd.xml \ man/systemd-suspend.service.xml \ man/systemd-sysctl.service.xml \ man/systemd-system-update-generator.xml \ man/systemd-system.conf.xml \ man/systemd-sysusers.xml \ man/systemd-sysv-generator.xml \ man/systemd-timedated.service.xml \ man/systemd-timesyncd.service.xml \ man/systemd-tmpfiles.xml \ man/systemd-tty-ask-password-agent.xml \ man/systemd-udevd.service.xml \ man/systemd-update-done.service.xml \ man/systemd-update-utmp.service.xml \ man/systemd-user-sessions.service.xml \ man/systemd-vconsole-setup.service.xml \ man/systemd.automount.xml \ man/systemd.device.xml \ man/systemd.exec.xml \ man/systemd.generator.xml \ man/systemd.journal-fields.xml \ man/systemd.kill.xml \ man/systemd.link.xml \ man/systemd.mount.xml \ man/systemd.netdev.xml \ man/systemd.network.xml \ man/systemd.nspawn.xml \ man/systemd.path.xml \ man/systemd.preset.xml \ man/systemd.resource-control.xml \ man/systemd.scope.xml \ man/systemd.service.xml \ man/systemd.slice.xml \ man/systemd.socket.xml \ man/systemd.special.xml \ man/systemd.swap.xml \ man/systemd.target.xml \ man/systemd.time.xml \ man/systemd.timer.xml \ man/systemd.unit.xml \ man/systemd.xml \ man/sysusers.d.xml \ man/telinit.xml \ man/timedatectl.xml \ man/timesyncd.conf.xml \ man/tmpfiles.d.xml \ man/udev.conf.xml \ man/udev.xml \ man/udev_device_get_syspath.xml \ man/udev_device_has_tag.xml \ man/udev_device_new_from_syspath.xml \ man/udev_enumerate_add_match_subsystem.xml \ man/udev_enumerate_new.xml \ man/udev_enumerate_scan_devices.xml \ man/udev_list_entry.xml \ man/udev_monitor_filter_update.xml \ man/udev_monitor_new_from_netlink.xml \ man/udev_monitor_receive_device.xml \ man/udev_new.xml \ man/udevadm.xml \ man/user-system-options.xml \ man/vconsole.conf.xml systemd-229/Makefile.am000066400000000000000000004703751265713322000151350ustar00rootroot00000000000000# -*- Mode: makefile; indent-tabs-mode: t -*- # # This file is part of systemd. # # Copyright 2010-2012 Lennart Poettering # Copyright 2010-2012 Kay Sievers # Copyright 2013 Zbigniew Jędrzejewski-Szmek # Copyright 2013 David Strauss # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} AM_MAKEFLAGS = --no-print-directory AUTOMAKE_OPTIONS = color-tests parallel-tests GCC_COLORS ?= 'ooh, shiny!' export GCC_COLORS SUBDIRS = . po # remove targets if the command fails .DELETE_ON_ERROR: # keep intermediate files .SECONDARY: # Keep the test-suite.log .PRECIOUS: $(TEST_SUITE_LOG) Makefile LIBUDEV_CURRENT=7 LIBUDEV_REVISION=4 LIBUDEV_AGE=6 LIBSYSTEMD_CURRENT=14 LIBSYSTEMD_REVISION=0 LIBSYSTEMD_AGE=14 # The following four libraries only exist for compatibility reasons, # their version info should not be bumped anymore LIBSYSTEMD_LOGIN_CURRENT=9 LIBSYSTEMD_LOGIN_REVISION=3 LIBSYSTEMD_LOGIN_AGE=9 LIBSYSTEMD_DAEMON_CURRENT=0 LIBSYSTEMD_DAEMON_REVISION=12 LIBSYSTEMD_DAEMON_AGE=0 LIBSYSTEMD_ID128_CURRENT=0 LIBSYSTEMD_ID128_REVISION=28 LIBSYSTEMD_ID128_AGE=0 LIBSYSTEMD_JOURNAL_CURRENT=11 LIBSYSTEMD_JOURNAL_REVISION=5 LIBSYSTEMD_JOURNAL_AGE=11 # Dirs of external packages dbuspolicydir=@dbuspolicydir@ dbussessionservicedir=@dbussessionservicedir@ dbussystemservicedir=@dbussystemservicedir@ pamlibdir=@pamlibdir@ pamconfdir=@pamconfdir@ pkgconfigdatadir=$(datadir)/pkgconfig pkgconfiglibdir=$(libdir)/pkgconfig polkitpolicydir=$(datadir)/polkit-1/actions bashcompletiondir=@bashcompletiondir@ zshcompletiondir=@zshcompletiondir@ rpmmacrosdir=$(prefix)/lib/rpm/macros.d sysvinitdir=$(SYSTEM_SYSVINIT_PATH) sysvrcnddir=$(SYSTEM_SYSVRCND_PATH) varlogdir=$(localstatedir)/log systemdstatedir=$(localstatedir)/lib/systemd catalogstatedir=$(systemdstatedir)/catalog xinitrcdir=$(sysconfdir)/X11/xinit/xinitrc.d # Our own, non-special dirs pkgsysconfdir=$(sysconfdir)/systemd userunitdir=$(prefix)/lib/systemd/user userpresetdir=$(prefix)/lib/systemd/user-preset tmpfilesdir=$(prefix)/lib/tmpfiles.d sysusersdir=$(prefix)/lib/sysusers.d sysctldir=$(prefix)/lib/sysctl.d binfmtdir=$(prefix)/lib/binfmt.d modulesloaddir=$(prefix)/lib/modules-load.d networkdir=$(rootprefix)/lib/systemd/network pkgincludedir=$(includedir)/systemd systemgeneratordir=$(rootlibexecdir)/system-generators usergeneratordir=$(prefix)/lib/systemd/user-generators systemshutdowndir=$(rootlibexecdir)/system-shutdown systemsleepdir=$(rootlibexecdir)/system-sleep systemunitdir=$(rootprefix)/lib/systemd/system systempresetdir=$(rootprefix)/lib/systemd/system-preset udevlibexecdir=$(rootprefix)/lib/udev udevhomedir=$(udevlibexecdir) udevrulesdir=$(udevlibexecdir)/rules.d udevhwdbdir=$(udevlibexecdir)/hwdb.d catalogdir=$(prefix)/lib/systemd/catalog kernelinstalldir = $(prefix)/lib/kernel/install.d factory_etcdir = $(datadir)/factory/etc factory_pamdir = $(datadir)/factory/etc/pam.d bootlibdir = $(prefix)/lib/systemd/boot/efi # And these are the special ones for / rootprefix=@rootprefix@ rootbindir=$(rootprefix)/bin rootlibexecdir=$(rootprefix)/lib/systemd EXTRA_DIST = BUILT_SOURCES = INSTALL_EXEC_HOOKS = UNINSTALL_EXEC_HOOKS = INSTALL_DATA_HOOKS = UNINSTALL_DATA_HOOKS = DISTCLEAN_LOCAL_HOOKS = CLEAN_LOCAL_HOOKS = pkginclude_HEADERS = noinst_LTLIBRARIES = lib_LTLIBRARIES = include_HEADERS = noinst_DATA = pkgconfigdata_DATA = pkgconfiglib_DATA = polkitpolicy_in_in_files = polkitpolicy_in_files = polkitpolicy_files = dist_udevrules_DATA = nodist_udevrules_DATA = dist_pkgsysconf_DATA = nodist_pkgsysconf_DATA = dist_dbuspolicy_DATA = dist_dbussystemservice_DATA = dist_systemunit_DATA_busnames = dist_sysusers_DATA = check_PROGRAMS = check_DATA = tests= manual_tests = TEST_EXTENSIONS = .py PY_LOG_COMPILER = $(PYTHON) DISABLE_HARD_ERRORS = yes if ENABLE_TESTS noinst_PROGRAMS = $(manual_tests) $(tests) TESTS = $(tests) else noinst_PROGRAMS = TESTS = endif if ENABLE_BASH_COMPLETION dist_bashcompletion_DATA = $(dist_bashcompletion_data) nodist_bashcompletion_DATA = $(nodist_bashcompletion_data) endif if ENABLE_ZSH_COMPLETION dist_zshcompletion_DATA = $(dist_zshcompletion_data) nodist_zshcompletion_DATA = $(nodist_zshcompletion_data) endif udevlibexec_PROGRAMS = gperf_gperf_sources = in_files = $(filter %.in,$(EXTRA_DIST)) in_in_files = $(filter %.in.in, $(in_files)) m4_files = $(filter %.m4,$(EXTRA_DIST) $(in_files:.m4.in=.m4)) CLEANFILES = $(BUILT_SOURCES) \ $(pkgconfigdata_DATA) \ $(pkgconfiglib_DATA) \ $(nodist_bashcompletion_data) \ $(nodist_zshcompletion_data) \ $(in_files:.in=) $(in_in_files:.in.in=) \ $(m4_files:.m4=) .PHONY: $(INSTALL_EXEC_HOOKS) $(UNINSTALL_EXEC_HOOKS) \ $(INSTALL_DATA_HOOKS) $(UNINSTALL_DATA_HOOKS) \ $(DISTCLEAN_LOCAL_HOOKS) $(CLEAN_LOCAL_HOOKS) AM_CPPFLAGS = \ -include $(top_builddir)/config.h \ -DPKGSYSCONFDIR=\"$(pkgsysconfdir)\" \ -DSYSTEM_CONFIG_UNIT_PATH=\"$(pkgsysconfdir)/system\" \ -DSYSTEM_DATA_UNIT_PATH=\"$(systemunitdir)\" \ -DSYSTEM_SYSVINIT_PATH=\"$(SYSTEM_SYSVINIT_PATH)\" \ -DSYSTEM_SYSVRCND_PATH=\"$(SYSTEM_SYSVRCND_PATH)\" \ -DUSER_CONFIG_UNIT_PATH=\"$(pkgsysconfdir)/user\" \ -DUSER_DATA_UNIT_PATH=\"$(userunitdir)\" \ -DCERTIFICATE_ROOT=\"$(CERTIFICATEROOT)\" \ -DCATALOG_DATABASE=\"$(catalogstatedir)/database\" \ -DSYSTEMD_CGROUP_AGENT_PATH=\"$(rootlibexecdir)/systemd-cgroups-agent\" \ -DSYSTEMD_BINARY_PATH=\"$(rootlibexecdir)/systemd\" \ -DSYSTEMD_FSCK_PATH=\"$(rootlibexecdir)/systemd-fsck\" \ -DSYSTEMD_SHUTDOWN_BINARY_PATH=\"$(rootlibexecdir)/systemd-shutdown\" \ -DSYSTEMD_SLEEP_BINARY_PATH=\"$(rootlibexecdir)/systemd-sleep\" \ -DSYSTEMCTL_BINARY_PATH=\"$(rootbindir)/systemctl\" \ -DSYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH=\"$(rootbindir)/systemd-tty-ask-password-agent\" \ -DSYSTEMD_STDIO_BRIDGE_BINARY_PATH=\"$(bindir)/systemd-stdio-bridge\" \ -DROOTPREFIX=\"$(rootprefix)\" \ -DRANDOM_SEED_DIR=\"$(localstatedir)/lib/systemd/\" \ -DRANDOM_SEED=\"$(localstatedir)/lib/systemd/random-seed\" \ -DSYSTEMD_CRYPTSETUP_PATH=\"$(rootlibexecdir)/systemd-cryptsetup\" \ -DSYSTEM_GENERATOR_PATH=\"$(systemgeneratordir)\" \ -DUSER_GENERATOR_PATH=\"$(usergeneratordir)\" \ -DSYSTEM_SHUTDOWN_PATH=\"$(systemshutdowndir)\" \ -DSYSTEM_SLEEP_PATH=\"$(systemsleepdir)\" \ -DSYSTEMD_KBD_MODEL_MAP=\"$(pkgdatadir)/kbd-model-map\" \ -DSYSTEMD_LANGUAGE_FALLBACK_MAP=\"$(pkgdatadir)/language-fallback-map\" \ -DUDEVLIBEXECDIR=\"$(udevlibexecdir)\" \ -DPOLKIT_AGENT_BINARY_PATH=\"$(bindir)/pkttyagent\" \ -DQUOTACHECK=\"$(QUOTACHECK)\" \ -DKEXEC=\"$(KEXEC)\" \ -DMOUNT_PATH=\"$(MOUNT_PATH)\" \ -DUMOUNT_PATH=\"$(UMOUNT_PATH)\" \ -DLIBDIR=\"$(libdir)\" \ -DROOTLIBDIR=\"$(rootlibdir)\" \ -DROOTLIBEXECDIR=\"$(rootlibexecdir)\" \ -DTEST_DIR=\"$(abs_top_srcdir)/test\" \ -I $(top_srcdir)/src \ -I $(top_builddir)/src/basic \ -I $(top_srcdir)/src/basic \ -I $(top_srcdir)/src/shared \ -I $(top_builddir)/src/shared \ -I $(top_srcdir)/src/network \ -I $(top_srcdir)/src/login \ -I $(top_srcdir)/src/journal \ -I $(top_builddir)/src/journal \ -I $(top_srcdir)/src/timedate \ -I $(top_srcdir)/src/timesync \ -I $(top_srcdir)/src/nspawn \ -I $(top_srcdir)/src/resolve \ -I $(top_builddir)/src/resolve \ -I $(top_srcdir)/src/systemd \ -I $(top_builddir)/src/core \ -I $(top_srcdir)/src/core \ -I $(top_srcdir)/src/libudev \ -I $(top_srcdir)/src/udev \ -I $(top_srcdir)/src/udev/net \ -I $(top_builddir)/src/udev \ -I $(top_srcdir)/src/libsystemd/sd-bus \ -I $(top_srcdir)/src/libsystemd/sd-event \ -I $(top_srcdir)/src/libsystemd/sd-login \ -I $(top_srcdir)/src/libsystemd/sd-netlink \ -I $(top_srcdir)/src/libsystemd/sd-network \ -I $(top_srcdir)/src/libsystemd/sd-hwdb \ -I $(top_srcdir)/src/libsystemd/sd-device \ -I $(top_srcdir)/src/libsystemd-network \ $(OUR_CPPFLAGS) AM_CFLAGS = $(OUR_CFLAGS) AM_LDFLAGS = $(OUR_LDFLAGS) # ------------------------------------------------------------------------------ define move-to-rootlibdir if test "$(libdir)" != "$(rootlibdir)"; then \ $(MKDIR_P) $(DESTDIR)$(rootlibdir) && \ so_img_name=$$(readlink $(DESTDIR)$(libdir)/$$libname) && \ rm -f $(DESTDIR)$(libdir)/$$libname && \ $(LN_S) --relative -f $(DESTDIR)$(rootlibdir)/$$so_img_name $(DESTDIR)$(libdir)/$$libname && \ mv $(DESTDIR)$(libdir)/$$libname.* $(DESTDIR)$(rootlibdir); \ fi endef INSTALL_DIRS = SHUTDOWN_TARGET_WANTS = LOCAL_FS_TARGET_WANTS = MULTI_USER_TARGET_WANTS = GRAPHICAL_TARGET_WANTS = RESCUE_TARGET_WANTS = SYSINIT_TARGET_WANTS = SOCKETS_TARGET_WANTS = BUSNAMES_TARGET_WANTS = TIMERS_TARGET_WANTS = USER_SOCKETS_TARGET_WANTS = USER_DEFAULT_TARGET_WANTS = USER_BUSNAMES_TARGET_WANTS = SYSTEM_UNIT_ALIASES = USER_UNIT_ALIASES = GENERAL_ALIASES = install-target-wants-hook: what="$(SHUTDOWN_TARGET_WANTS)" && wants=shutdown.target && dir=$(systemunitdir) && $(add-wants) what="$(LOCAL_FS_TARGET_WANTS)" && wants=local-fs.target && dir=$(systemunitdir) && $(add-wants) what="$(MULTI_USER_TARGET_WANTS)" && wants=multi-user.target && dir=$(systemunitdir) && $(add-wants) what="$(GRAPHICAL_TARGET_WANTS)" && wants=graphical.target && dir=$(systemunitdir) && $(add-wants) what="$(RESCUE_TARGET_WANTS)" && wants=rescue.target && dir=$(systemunitdir) && $(add-wants) what="$(SYSINIT_TARGET_WANTS)" && wants=sysinit.target && dir=$(systemunitdir) && $(add-wants) what="$(SOCKETS_TARGET_WANTS)" && wants=sockets.target && dir=$(systemunitdir) && $(add-wants) what="$(TIMERS_TARGET_WANTS)" && wants=timers.target && dir=$(systemunitdir) && $(add-wants) what="$(SLICES_TARGET_WANTS)" && wants=slices.target && dir=$(systemunitdir) && $(add-wants) what="$(USER_SOCKETS_TARGET_WANTS)" && wants=sockets.target && dir=$(userunitdir) && $(add-wants) what="$(USER_DEFAULT_TARGET_WANTS)" && wants=default.target && dir=$(userunitdir) && $(add-wants) install-busnames-target-wants-hook: what="$(BUSNAMES_TARGET_WANTS)" && wants=busnames.target && dir=$(systemunitdir) && $(add-wants) what="$(USER_BUSNAMES_TARGET_WANTS)" && wants=busnames.target && dir=$(userunitdir) && $(add-wants) define add-wants [ -z "$$what" ] || ( \ dir=$(DESTDIR)$$dir/$$wants.wants && \ $(MKDIR_P) -m 0755 $$dir && \ cd $$dir && \ rm -f $$what && \ for i in $$what; do $(LN_S) ../$$i . || exit $$? ; done ) endef install-directories-hook: $(MKDIR_P) $(addprefix $(DESTDIR),$(INSTALL_DIRS)) install-aliases-hook: set -- $(SYSTEM_UNIT_ALIASES) && \ dir=$(systemunitdir) && $(install-aliases) set -- $(USER_UNIT_ALIASES) && \ dir=$(userunitdir) && $(install-relative-aliases) set -- $(GENERAL_ALIASES) && \ dir= && $(install-relative-aliases) define install-aliases while [ -n "$$1" ]; do \ $(MKDIR_P) `dirname $(DESTDIR)$$dir/$$2` && \ rm -f $(DESTDIR)$$dir/$$2 && \ $(LN_S) $$1 $(DESTDIR)$$dir/$$2 && \ shift 2 || exit $$?; \ done endef define install-relative-aliases while [ -n "$$1" ]; do \ $(MKDIR_P) `dirname $(DESTDIR)$$dir/$$2` && \ rm -f $(DESTDIR)$$dir/$$2 && \ $(LN_S) --relative $(DESTDIR)$$1 $(DESTDIR)$$dir/$$2 && \ shift 2 || exit $$?; \ done endef install-touch-usr-hook: touch -c $(DESTDIR)/$(prefix) INSTALL_EXEC_HOOKS += \ install-target-wants-hook \ install-directories-hook \ install-aliases-hook \ install-touch-usr-hook INSTALL_EXEC_HOOKS += \ install-busnames-target-wants-hook # ------------------------------------------------------------------------------ AM_V_M4 = $(AM_V_M4_$(V)) AM_V_M4_ = $(AM_V_M4_$(AM_DEFAULT_VERBOSITY)) AM_V_M4_0 = @echo " M4 " $@; AM_V_XSLT = $(AM_V_XSLT_$(V)) AM_V_XSLT_ = $(AM_V_XSLT_$(AM_DEFAULT_VERBOSITY)) AM_V_XSLT_0 = @echo " XSLT " $@; AM_V_GPERF = $(AM_V_GPERF_$(V)) AM_V_GPERF_ = $(AM_V_GPERF_$(AM_DEFAULT_VERBOSITY)) AM_V_GPERF_0 = @echo " GPERF " $@; AM_V_LN = $(AM_V_LN_$(V)) AM_V_LN_ = $(AM_V_LN_$(AM_DEFAULT_VERBOSITY)) AM_V_LN_0 = @echo " LN " $@; AM_V_RM = $(AM_V_RM_$(V)) AM_V_RM_ = $(AM_V_RM_$(AM_DEFAULT_VERBOSITY)) AM_V_RM_0 = @echo " RM " $@; # ------------------------------------------------------------------------------ rootbin_PROGRAMS = \ systemctl \ systemd-notify \ systemd-ask-password \ systemd-tty-ask-password-agent \ systemd-machine-id-setup \ systemd-escape bin_PROGRAMS = \ systemd-cgls \ systemd-cgtop \ systemd-nspawn \ systemd-detect-virt \ systemd-delta \ systemd-analyze \ systemd-run \ systemd-stdio-bridge \ systemd-path dist_bin_SCRIPTS = \ src/kernel-install/kernel-install dist_kernelinstall_SCRIPTS = \ src/kernel-install/50-depmod.install \ src/kernel-install/90-loaderentry.install rootlibexec_PROGRAMS = \ systemd \ systemd-cgroups-agent \ systemd-initctl \ systemd-shutdown \ systemd-remount-fs \ systemd-reply-password \ systemd-fsck \ systemd-ac-power \ systemd-sysctl \ systemd-sleep \ systemd-bus-proxyd \ systemd-socket-proxyd \ systemd-update-done if HAVE_UTMP rootlibexec_PROGRAMS += \ systemd-update-utmp endif systemgenerator_PROGRAMS = \ systemd-getty-generator \ systemd-fstab-generator \ systemd-system-update-generator \ systemd-debug-generator dist_bashcompletion_data = \ shell-completion/bash/busctl \ shell-completion/bash/journalctl \ shell-completion/bash/systemd-analyze \ shell-completion/bash/systemd-cat \ shell-completion/bash/systemd-cgls \ shell-completion/bash/systemd-cgtop \ shell-completion/bash/systemd-delta \ shell-completion/bash/systemd-detect-virt \ shell-completion/bash/systemd-nspawn \ shell-completion/bash/systemd-path \ shell-completion/bash/systemd-run \ shell-completion/bash/udevadm \ shell-completion/bash/kernel-install nodist_bashcompletion_data = \ shell-completion/bash/systemctl dist_zshcompletion_data = \ shell-completion/zsh/_busctl \ shell-completion/zsh/_journalctl \ shell-completion/zsh/_udevadm \ shell-completion/zsh/_kernel-install \ shell-completion/zsh/_systemd-nspawn \ shell-completion/zsh/_systemd-analyze \ shell-completion/zsh/_systemd-run \ shell-completion/zsh/_sd_hosts_or_user_at_host \ shell-completion/zsh/_sd_outputmodes \ shell-completion/zsh/_sd_unit_files \ shell-completion/zsh/_systemd-delta \ shell-completion/zsh/_systemd nodist_zshcompletion_data = \ shell-completion/zsh/_systemctl EXTRA_DIST += \ shell-completion/bash/systemctl.in \ shell-completion/zsh/_systemctl.in dist_sysctl_DATA = \ sysctl.d/50-default.conf dist_systemunit_DATA = \ units/graphical.target \ units/multi-user.target \ units/emergency.target \ units/sysinit.target \ units/basic.target \ units/getty.target \ units/halt.target \ units/kexec.target \ units/exit.target \ units/local-fs.target \ units/local-fs-pre.target \ units/initrd.target \ units/initrd-fs.target \ units/initrd-root-fs.target \ units/remote-fs.target \ units/remote-fs-pre.target \ units/network.target \ units/network-pre.target \ units/network-online.target \ units/nss-lookup.target \ units/nss-user-lookup.target \ units/poweroff.target \ units/reboot.target \ units/rescue.target \ units/rpcbind.target \ units/time-sync.target \ units/shutdown.target \ units/final.target \ units/umount.target \ units/sigpwr.target \ units/sleep.target \ units/sockets.target \ units/timers.target \ units/paths.target \ units/suspend.target \ units/swap.target \ units/slices.target \ units/system.slice \ units/x-.slice \ units/systemd-initctl.socket \ units/syslog.socket \ units/dev-hugepages.mount \ units/dev-mqueue.mount \ units/sys-kernel-config.mount \ units/sys-kernel-debug.mount \ units/sys-fs-fuse-connections.mount \ units/tmp.mount \ units/var-lib-machines.mount \ units/printer.target \ units/sound.target \ units/bluetooth.target \ units/smartcard.target \ units/systemd-ask-password-wall.path \ units/systemd-ask-password-console.path \ units/systemd-udevd-control.socket \ units/systemd-udevd-kernel.socket \ units/system-update.target \ units/initrd-switch-root.target \ units/machines.target dist_systemunit_DATA += \ $(dist_systemunit_DATA_busnames) dist_systemunit_DATA_busnames += \ units/busnames.target nodist_systemunit_DATA = \ units/getty@.service \ units/serial-getty@.service \ units/console-shell.service \ units/console-getty.service \ units/container-getty@.service \ units/systemd-initctl.service \ units/systemd-remount-fs.service \ units/systemd-ask-password-wall.service \ units/systemd-ask-password-console.service \ units/systemd-sysctl.service \ units/emergency.service \ units/rescue.service \ units/user@.service \ units/systemd-suspend.service \ units/systemd-halt.service \ units/systemd-poweroff.service \ units/systemd-reboot.service \ units/systemd-kexec.service \ units/systemd-exit.service \ units/systemd-fsck@.service \ units/systemd-fsck-root.service \ units/systemd-machine-id-commit.service \ units/systemd-udevd.service \ units/systemd-udev-trigger.service \ units/systemd-udev-settle.service \ units/systemd-hwdb-update.service \ units/debug-shell.service \ units/initrd-parse-etc.service \ units/initrd-cleanup.service \ units/initrd-udevadm-cleanup-db.service \ units/initrd-switch-root.service \ units/systemd-nspawn@.service \ units/systemd-update-done.service if HAVE_UTMP nodist_systemunit_DATA += \ units/systemd-update-utmp.service \ units/systemd-update-utmp-runlevel.service endif dist_userunit_DATA = \ units/user/basic.target \ units/user/default.target \ units/user/exit.target nodist_userunit_DATA = \ units/user/systemd-exit.service dist_systempreset_DATA = \ system-preset/90-systemd.preset EXTRA_DIST += \ units/getty@.service.m4 \ units/serial-getty@.service.m4 \ units/console-shell.service.m4.in \ units/console-getty.service.m4.in \ units/container-getty@.service.m4.in \ units/rescue.service.in \ units/systemd-initctl.service.in \ units/systemd-remount-fs.service.in \ units/systemd-update-utmp.service.in \ units/systemd-update-utmp-runlevel.service.in \ units/systemd-ask-password-wall.service.in \ units/systemd-ask-password-console.service.in \ units/systemd-sysctl.service.in \ units/emergency.service.in \ units/systemd-halt.service.in \ units/systemd-poweroff.service.in \ units/systemd-reboot.service.in \ units/systemd-kexec.service.in \ units/systemd-exit.service.in \ units/user/systemd-exit.service.in \ units/systemd-fsck@.service.in \ units/systemd-fsck-root.service.in \ units/systemd-machine-id-commit.service.in \ units/user@.service.m4.in \ units/debug-shell.service.in \ units/systemd-suspend.service.in \ units/quotaon.service.in \ units/initrd-parse-etc.service.in \ units/initrd-cleanup.service.in \ units/initrd-udevadm-cleanup-db.service.in \ units/initrd-switch-root.service.in \ units/systemd-nspawn@.service.in \ units/systemd-update-done.service.in \ units/tmp.mount.m4 if HAVE_SYSV_COMPAT nodist_systemunit_DATA += \ units/rc-local.service \ units/halt-local.service systemgenerator_PROGRAMS += \ systemd-sysv-generator \ systemd-rc-local-generator endif EXTRA_DIST += \ src/systemctl/systemd-sysv-install.SKELETON \ units/rc-local.service.in \ units/halt-local.service.in # automake is broken and can't handle files with a dash in front # http://debbugs.gnu.org/cgi/bugreport.cgi?bug=14728#8 units-install-hook: mv $(DESTDIR)$(systemunitdir)/x-.slice $(DESTDIR)/$(systemunitdir)/-.slice units-uninstall-hook: rm -f $(DESTDIR)/$(systemunitdir)/-.slice INSTALL_DATA_HOOKS += units-install-hook UNINSTALL_DATA_HOOKS += units-uninstall-hook dist_doc_DATA = \ README \ NEWS \ CODING_STYLE \ LICENSE.LGPL2.1 \ LICENSE.GPL2 \ DISTRO_PORTING \ src/libsystemd/sd-bus/PORTING-DBUS1 \ src/libsystemd/sd-bus/DIFFERENCES \ src/libsystemd/sd-bus/GVARIANT-SERIALIZATION EXTRA_DIST += \ README.md \ autogen.sh \ .dir-locals.el \ .editorconfig \ .vimrc \ .ycm_extra_conf.py \ .travis.yml \ .mailmap @INTLTOOL_POLICY_RULE@ # ------------------------------------------------------------------------------ MANPAGES = MANPAGES_ALIAS = include Makefile-man.am .PHONY: man update-man-list man: $(MANPAGES) $(MANPAGES_ALIAS) $(HTML_FILES) $(HTML_ALIAS) XML_FILES = \ ${patsubst %.1,%.xml,${patsubst %.3,%.xml,${patsubst %.5,%.xml,${patsubst %.7,%.xml,${patsubst %.8,%.xml,$(MANPAGES)}}}}} HTML_FILES = \ ${XML_FILES:.xml=.html} HTML_ALIAS = \ ${patsubst %.1,%.html,${patsubst %.3,%.html,${patsubst %.5,%.html,${patsubst %.7,%.html,${patsubst %.8,%.html,$(MANPAGES_ALIAS)}}}}} if ENABLE_MANPAGES man_MANS = \ $(MANPAGES) \ $(MANPAGES_ALIAS) noinst_DATA += \ $(HTML_FILES) \ $(HTML_ALIAS) \ docs/html/man endif CLEANFILES += \ $(man_MANS) \ $(HTML_FILES) \ $(HTML_ALIAS) \ docs/html/man docs/html/man: $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_LN)$(LN_S) -f ../../man $@ man/index.html: man/systemd.index.html $(AM_V_LN)$(LN_S) -f systemd.index.html $@ if HAVE_PYTHON noinst_DATA += \ man/index.html endif CLEANFILES += \ man/index.html XML_GLOB = $(wildcard $(top_srcdir)/man/*.xml) NON_INDEX_XML_FILES = $(filter-out man/systemd.index.xml,$(XML_FILES)) SOURCE_XML_FILES = ${patsubst %,$(top_srcdir)/%,$(filter-out man/systemd.directives.xml,$(NON_INDEX_XML_FILES))} # This target should only be run manually. It recreates Makefile-man.am # file in the source directory based on all man/*.xml files. Run it after # adding, removing, or changing the conditional in a man page. update-man-list: $(top_srcdir)/tools/make-man-rules.py $(XML_GLOB) man/custom-entities.ent $(AM_V_GEN)$(PYTHON) $< $(XML_GLOB) > $(top_srcdir)/Makefile-man.tmp $(AM_V_at)mv $(top_srcdir)/Makefile-man.tmp $(top_srcdir)/Makefile-man.am @echo "Makefile-man.am has been regenerated" man/systemd.index.xml: $(top_srcdir)/tools/make-man-index.py $(NON_INDEX_XML_FILES) $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(PYTHON) $< $@ $(filter-out $<,$^) man/systemd.directives.xml: $(top_srcdir)/tools/make-directive-index.py man/custom-entities.ent $(SOURCE_XML_FILES) $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(PYTHON) $< $@ $(SOURCE_XML_FILES) CLEANFILES += \ man/systemd.index.xml \ man/systemd.directives.xml EXTRA_DIST += \ $(filter-out man/systemd.directives.xml man/systemd.index.xml,$(XML_FILES)) \ tools/make-man-index.py \ tools/make-man-rules.py \ tools/make-directive-index.py \ tools/xml_helper.py \ man/glib-event-glue.c # ------------------------------------------------------------------------------ noinst_LTLIBRARIES += \ libbasic.la libbasic_la_SOURCES = \ src/basic/missing.h \ src/basic/capability-util.c \ src/basic/capability-util.h \ src/basic/c-rbtree.c \ src/basic/c-rbtree.h \ src/basic/conf-files.c \ src/basic/conf-files.h \ src/basic/stdio-util.h \ src/basic/hostname-util.h \ src/basic/hostname-util.c \ src/basic/unit-name.c \ src/basic/unit-name.h \ src/basic/ioprio.h \ src/basic/securebits.h \ src/basic/special.h \ src/basic/list.h \ src/basic/unaligned.h \ src/basic/macro.h \ src/basic/def.h \ src/basic/sparse-endian.h \ src/basic/refcnt.h \ src/basic/util.c \ src/basic/util.h \ src/basic/io-util.c \ src/basic/io-util.h \ src/basic/string-util.c \ src/basic/string-util.h \ src/basic/fd-util.c \ src/basic/fd-util.h \ src/basic/parse-util.c \ src/basic/parse-util.h \ src/basic/user-util.c \ src/basic/user-util.h \ src/basic/rlimit-util.c \ src/basic/rlimit-util.h \ src/basic/dirent-util.c \ src/basic/dirent-util.h \ src/basic/xattr-util.c \ src/basic/xattr-util.h \ src/basic/chattr-util.c \ src/basic/chattr-util.h \ src/basic/proc-cmdline.c \ src/basic/proc-cmdline.h \ src/basic/fs-util.c \ src/basic/fs-util.h \ src/basic/syslog-util.c \ src/basic/syslog-util.h \ src/basic/stat-util.c \ src/basic/stat-util.h \ src/basic/mount-util.c \ src/basic/mount-util.h \ src/basic/hexdecoct.c \ src/basic/hexdecoct.h \ src/basic/glob-util.h \ src/basic/glob-util.c \ src/basic/extract-word.c \ src/basic/extract-word.h \ src/basic/escape.c \ src/basic/escape.h \ src/basic/cpu-set-util.c \ src/basic/cpu-set-util.h \ src/basic/lockfile-util.c \ src/basic/lockfile-util.h \ src/basic/path-util.c \ src/basic/path-util.h \ src/basic/time-util.c \ src/basic/time-util.h \ src/basic/locale-util.c \ src/basic/locale-util.h \ src/basic/umask-util.h \ src/basic/signal-util.c \ src/basic/signal-util.h \ src/basic/string-table.c \ src/basic/string-table.h \ src/basic/mempool.c \ src/basic/mempool.h \ src/basic/hashmap.c \ src/basic/hashmap.h \ src/basic/hash-funcs.c \ src/basic/hash-funcs.h \ src/basic/siphash24.c \ src/basic/siphash24.h \ src/basic/set.h \ src/basic/ordered-set.h \ src/basic/ordered-set.c \ src/basic/bitmap.c \ src/basic/bitmap.h \ src/basic/fdset.c \ src/basic/fdset.h \ src/basic/prioq.c \ src/basic/prioq.h \ src/basic/web-util.c \ src/basic/web-util.h \ src/basic/strv.c \ src/basic/strv.h \ src/basic/env-util.c \ src/basic/env-util.h \ src/basic/strbuf.c \ src/basic/strbuf.h \ src/basic/strxcpyx.c \ src/basic/strxcpyx.h \ src/basic/log.c \ src/basic/log.h \ src/basic/bus-label.c \ src/basic/bus-label.h \ src/basic/ratelimit.h \ src/basic/ratelimit.c \ src/basic/exit-status.c \ src/basic/exit-status.h \ src/basic/virt.c \ src/basic/virt.h \ src/basic/smack-util.c \ src/basic/smack-util.h \ src/basic/device-nodes.c \ src/basic/device-nodes.h \ src/basic/utf8.c \ src/basic/utf8.h \ src/basic/gunicode.c \ src/basic/gunicode.h \ src/basic/socket-util.c \ src/basic/socket-util.h \ src/basic/in-addr-util.c \ src/basic/in-addr-util.h \ src/basic/ether-addr-util.h \ src/basic/ether-addr-util.c \ src/basic/replace-var.c \ src/basic/replace-var.h \ src/basic/clock-util.c \ src/basic/clock-util.h \ src/basic/calendarspec.c \ src/basic/calendarspec.h \ src/basic/fileio.c \ src/basic/fileio.h \ src/basic/MurmurHash2.c \ src/basic/MurmurHash2.h \ src/basic/mkdir.c \ src/basic/mkdir.h \ src/basic/cgroup-util.c \ src/basic/cgroup-util.h \ src/basic/errno-list.c \ src/basic/errno-list.h \ src/basic/af-list.c \ src/basic/af-list.h \ src/basic/arphrd-list.c \ src/basic/arphrd-list.h \ src/basic/terminal-util.c \ src/basic/terminal-util.h \ src/basic/login-util.h \ src/basic/login-util.c \ src/basic/cap-list.c \ src/basic/cap-list.h \ src/basic/audit-util.c \ src/basic/audit-util.h \ src/basic/xml.c \ src/basic/xml.h \ src/basic/json.c \ src/basic/json.h \ src/basic/barrier.c \ src/basic/barrier.h \ src/basic/async.c \ src/basic/async.h \ src/basic/memfd-util.c \ src/basic/memfd-util.h \ src/basic/process-util.c \ src/basic/process-util.h \ src/basic/random-util.c \ src/basic/random-util.h \ src/basic/verbs.c \ src/basic/verbs.h \ src/basic/sigbus.c \ src/basic/sigbus.h \ src/basic/build.h \ src/basic/socket-label.c \ src/basic/label.c \ src/basic/label.h \ src/basic/btrfs-util.c \ src/basic/btrfs-util.h \ src/basic/btrfs-ctree.h \ src/basic/selinux-util.c \ src/basic/selinux-util.h \ src/basic/mkdir-label.c \ src/basic/fileio-label.c \ src/basic/fileio-label.h \ src/basic/rm-rf.c \ src/basic/rm-rf.h \ src/basic/copy.c \ src/basic/copy.h \ src/basic/alloc-util.h \ src/basic/alloc-util.c \ src/basic/formats-util.h \ src/basic/nss-util.h nodist_libbasic_la_SOURCES = \ src/basic/errno-from-name.h \ src/basic/errno-to-name.h \ src/basic/af-from-name.h \ src/basic/af-to-name.h \ src/basic/arphrd-from-name.h \ src/basic/arphrd-to-name.h \ src/basic/cap-from-name.h \ src/basic/cap-to-name.h libbasic_la_CFLAGS = \ $(AM_CFLAGS) \ $(SELINUX_CFLAGS) \ $(CAP_CFLAGS) \ -pthread libbasic_la_LIBADD = \ $(SELINUX_LIBS) \ $(CAP_LIBS) \ -lrt \ -lm # ----------------------------------------------------------------------------- noinst_LTLIBRARIES += \ libshared.la libshared_la_SOURCES = \ src/shared/output-mode.h \ src/shared/gpt.h \ src/shared/udev-util.h \ src/shared/linux/auto_dev-ioctl.h \ src/shared/initreq.h \ src/shared/dns-domain.c \ src/shared/dns-domain.h \ src/shared/architecture.c \ src/shared/architecture.h \ src/shared/efivars.c \ src/shared/efivars.h \ src/shared/fstab-util.c \ src/shared/fstab-util.h \ src/shared/sleep-config.c \ src/shared/sleep-config.h \ src/shared/conf-parser.c \ src/shared/conf-parser.h \ src/shared/pager.c \ src/shared/pager.h \ src/shared/spawn-polkit-agent.c \ src/shared/spawn-polkit-agent.h \ src/shared/apparmor-util.c \ src/shared/apparmor-util.h \ src/shared/ima-util.c \ src/shared/ima-util.h \ src/shared/ptyfwd.c \ src/shared/ptyfwd.h \ src/shared/base-filesystem.c \ src/shared/base-filesystem.h \ src/shared/uid-range.c \ src/shared/uid-range.h \ src/shared/install.c \ src/shared/install.h \ src/shared/install-printf.c \ src/shared/install-printf.h \ src/shared/path-lookup.c \ src/shared/path-lookup.h \ src/shared/specifier.c \ src/shared/specifier.h \ src/shared/dev-setup.c \ src/shared/dev-setup.h \ src/shared/dropin.c \ src/shared/dropin.h \ src/shared/condition.c \ src/shared/condition.h \ src/shared/clean-ipc.c \ src/shared/clean-ipc.h \ src/shared/generator.h \ src/shared/generator.c \ src/shared/acpi-fpdt.h \ src/shared/acpi-fpdt.c \ src/shared/boot-timestamps.h \ src/shared/boot-timestamps.c \ src/shared/cgroup-show.c \ src/shared/cgroup-show.h \ src/shared/utmp-wtmp.h \ src/shared/watchdog.c \ src/shared/watchdog.h \ src/shared/spawn-ask-password-agent.c \ src/shared/spawn-ask-password-agent.h \ src/shared/ask-password-api.c \ src/shared/ask-password-api.h \ src/shared/switch-root.h \ src/shared/switch-root.c \ src/shared/import-util.c \ src/shared/import-util.h \ src/shared/sysctl-util.c \ src/shared/sysctl-util.h \ src/shared/bus-util.c \ src/shared/bus-util.h \ src/shared/logs-show.c \ src/shared/logs-show.h \ src/shared/machine-image.c \ src/shared/machine-image.h \ src/shared/machine-pool.c \ src/shared/machine-pool.h \ src/shared/resolve-util.c \ src/shared/resolve-util.h if HAVE_UTMP libshared_la_SOURCES += \ src/shared/utmp-wtmp.c endif if HAVE_SECCOMP libshared_la_SOURCES += \ src/shared/seccomp-util.h \ src/shared/seccomp-util.c endif if HAVE_ACL libshared_la_SOURCES += \ src/shared/acl-util.c \ src/shared/acl-util.h endif libshared_la_CFLAGS = \ $(AM_CFLAGS) \ $(ACL_CFLAGS) \ $(LIBIDN_CFLAGS) \ $(SECCOMP_CFLAGS) libshared_la_LIBADD = \ libsystemd-internal.la \ libsystemd-journal-internal.la \ libudev-internal.la \ $(ACL_LIBS) \ $(LIBIDN_LIBS) \ $(SECCOMP_LIBS) # ----------------------------------------------------------------------------- if HAVE_LIBIPTC noinst_LTLIBRARIES += \ libfirewall.la libfirewall_la_SOURCES = \ src/shared/firewall-util.h \ src/shared/firewall-util.c libfirewall_la_CFLAGS = \ $(AM_CFLAGS) \ $(LIBIPTC_CFLAGS) libfirewall_la_LIBADD = \ $(LIBIPTC_LIBS) endif # ----------------------------------------------------------------------------- if ENABLE_LDCONFIG dist_systemunit_DATA += \ units/ldconfig.service SYSINIT_TARGET_WANTS += \ ldconfig.service endif # ------------------------------------------------------------------------------ noinst_LTLIBRARIES += \ libcore.la libcore_la_SOURCES = \ src/core/unit.c \ src/core/unit.h \ src/core/unit-printf.c \ src/core/unit-printf.h \ src/core/job.c \ src/core/job.h \ src/core/manager.c \ src/core/manager.h \ src/core/transaction.c \ src/core/transaction.h \ src/core/load-fragment.c \ src/core/load-fragment.h \ src/core/service.c \ src/core/service.h \ src/core/socket.c \ src/core/socket.h \ src/core/busname.c \ src/core/busname.h \ src/core/bus-endpoint.c \ src/core/bus-endpoint.h \ src/core/bus-policy.c \ src/core/bus-policy.h \ src/core/target.c \ src/core/target.h \ src/core/device.c \ src/core/device.h \ src/core/mount.c \ src/core/mount.h \ src/core/automount.c \ src/core/automount.h \ src/core/swap.c \ src/core/swap.h \ src/core/timer.c \ src/core/timer.h \ src/core/path.c \ src/core/path.h \ src/core/slice.c \ src/core/slice.h \ src/core/scope.c \ src/core/scope.h \ src/core/load-dropin.c \ src/core/load-dropin.h \ src/core/execute.c \ src/core/execute.h \ src/core/kill.c \ src/core/kill.h \ src/core/dbus.c \ src/core/dbus.h \ src/core/dbus-manager.c \ src/core/dbus-manager.h \ src/core/dbus-unit.c \ src/core/dbus-unit.h \ src/core/dbus-job.c \ src/core/dbus-job.h \ src/core/dbus-service.c \ src/core/dbus-service.h \ src/core/dbus-socket.c \ src/core/dbus-socket.h \ src/core/dbus-busname.c \ src/core/dbus-busname.h \ src/core/dbus-target.c \ src/core/dbus-target.h \ src/core/dbus-device.c \ src/core/dbus-device.h \ src/core/dbus-mount.c \ src/core/dbus-mount.h \ src/core/dbus-automount.c \ src/core/dbus-automount.h \ src/core/dbus-swap.c \ src/core/dbus-swap.h \ src/core/dbus-timer.c \ src/core/dbus-timer.h \ src/core/dbus-path.c \ src/core/dbus-path.h \ src/core/dbus-slice.c \ src/core/dbus-slice.h \ src/core/dbus-scope.c \ src/core/dbus-scope.h \ src/core/dbus-execute.c \ src/core/dbus-execute.h \ src/core/dbus-kill.c \ src/core/dbus-kill.h \ src/core/dbus-cgroup.c \ src/core/dbus-cgroup.h \ src/core/cgroup.c \ src/core/cgroup.h \ src/core/selinux-access.c \ src/core/selinux-access.h \ src/core/selinux-setup.c \ src/core/selinux-setup.h \ src/core/smack-setup.c \ src/core/smack-setup.h \ src/core/ima-setup.c \ src/core/ima-setup.h \ src/core/locale-setup.h \ src/core/locale-setup.c \ src/core/hostname-setup.c \ src/core/hostname-setup.h \ src/core/machine-id-setup.c \ src/core/machine-id-setup.h \ src/core/mount-setup.c \ src/core/mount-setup.h \ src/core/kmod-setup.c \ src/core/kmod-setup.h \ src/core/loopback-setup.h \ src/core/loopback-setup.c \ src/core/namespace.c \ src/core/namespace.h \ src/core/killall.h \ src/core/killall.c \ src/core/audit-fd.c \ src/core/audit-fd.h \ src/core/show-status.c \ src/core/show-status.h \ src/core/failure-action.c \ src/core/failure-action.h nodist_libcore_la_SOURCES = \ src/core/load-fragment-gperf.c \ src/core/load-fragment-gperf-nulstr.c libcore_la_CFLAGS = \ $(AM_CFLAGS) \ $(PAM_CFLAGS) \ $(AUDIT_CFLAGS) \ $(KMOD_CFLAGS) \ $(APPARMOR_CFLAGS) \ $(MOUNT_CFLAGS) \ $(SECCOMP_CFLAGS) libcore_la_LIBADD = \ libshared.la \ $(PAM_LIBS) \ $(AUDIT_LIBS) \ $(KMOD_LIBS) \ $(APPARMOR_LIBS) \ $(MOUNT_LIBS) src/core/load-fragment-gperf-nulstr.c: src/core/load-fragment-gperf.gperf $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(AWK) 'BEGIN{ keywords=0 ; FS="," ; print "extern const char load_fragment_gperf_nulstr[];" ; print "const char load_fragment_gperf_nulstr[] ="} ; keyword==1 { print "\"" $$1 "\\0\"" } ; /%%/ { keyword=1} ; END { print ";" }' < $< > $@ gperf_gperf_m4_sources = \ src/core/load-fragment-gperf.gperf.m4 gperf_txt_sources = \ src/basic/errno-list.txt \ src/basic/af-list.txt \ src/basic/arphrd-list.txt \ src/basic/cap-list.txt BUILT_SOURCES += \ $(gperf_gperf_m4_sources:-gperf.gperf.m4=-gperf.c) \ $(gperf_gperf_m4_sources:-gperf.gperf.m4=-gperf-nulstr.c) \ $(gperf_gperf_sources:-gperf.gperf=-gperf.c) \ $(gperf_txt_sources:-list.txt=-from-name.h) \ $(filter-out %keyboard-keys-to-name.h,$(gperf_txt_sources:-list.txt=-to-name.h)) CLEANFILES += \ $(gperf_txt_sources:-list.txt=-from-name.gperf) DISTCLEANFILES = \ $(gperf_txt_sources) EXTRA_DIST += \ $(gperf_gperf_m4_sources) \ $(gperf_gperf_sources) CLEANFILES += \ $(gperf_txt_sources) %-from-name.gperf: %-list.txt $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(AWK) 'BEGIN{ print "struct $(notdir $*)_name { const char* name; int id; };"; print "%null-strings"; print "%%";} { printf "%s, %s\n", $$1, $$1 }' <$< >$@ %-from-name.h: %-from-name.gperf $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GPERF)$(GPERF) -L ANSI-C -t --ignore-case -N lookup_$(notdir $*) -H hash_$(notdir $*)_name -p -C <$< >$@ src/basic/errno-list.txt: $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include errno.h - $@ src/basic/errno-to-name.h: src/basic/errno-list.txt $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(AWK) 'BEGIN{ print "static const char* const errno_names[] = { "} !/EDEADLOCK/ && !/EWOULDBLOCK/ && !/ENOTSUP/ { printf "[%s] = \"%s\",\n", $$1, $$1 } END{print "};"}' <$< >$@ src/basic/af-list.txt: $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include sys/socket.h - $@ src/basic/af-to-name.h: src/basic/af-list.txt $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(AWK) 'BEGIN{ print "static const char* const af_names[] = { "} !/AF_FILE/ && !/AF_ROUTE/ && !/AF_LOCAL/ { printf "[%s] = \"%s\",\n", $$1, $$1 } END{print "};"}' <$< >$@ src/basic/arphrd-list.txt: $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include net/if_arp.h - $@ src/basic/arphrd-to-name.h: src/basic/arphrd-list.txt $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(AWK) 'BEGIN{ print "static const char* const arphrd_names[] = { "} !/CISCO/ { printf "[ARPHRD_%s] = \"%s\",\n", $$1, $$1 } END{print "};"}' <$< >$@ src/basic/arphrd-from-name.gperf: src/basic/arphrd-list.txt $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(AWK) 'BEGIN{ print "struct arphrd_name { const char* name; int id; };"; print "%null-strings"; print "%%";} { printf "%s, ARPHRD_%s\n", $$1, $$1 }' <$< >$@ src/basic/cap-list.txt: $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include linux/capability.h -include missing.h - $@ src/basic/cap-to-name.h: src/basic/cap-list.txt $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(AWK) 'BEGIN{ print "static const char* const capability_names[] = { "} { printf "[%s] = \"%s\",\n", $$1, tolower($$1) } END{print "};"}' <$< >$@ src/basic/cap-from-name.gperf: src/basic/cap-list.txt $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(AWK) 'BEGIN{ print "struct capability_name { const char* name; int id; };"; print "%null-strings"; print "%%";} { printf "%s, %s\n", $$1, $$1 }' <$< >$@ src/basic/cap-from-name.h: src/basic/cap-from-name.gperf $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GPERF)$(GPERF) -L ANSI-C -t --ignore-case -N lookup_capability -H hash_capability_name -p -C <$< >$@ audit_list_includes = -include linux/audit.h -include missing.h if HAVE_AUDIT audit_list_includes += -include libaudit.h endif src/journal/audit_type-list.txt: $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM $(audit_list_includes) - $@ src/journal/audit_type-to-name.h: src/journal/audit_type-list.txt $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(AWK) 'BEGIN{ print "const char *audit_type_to_string(int type) {\n\tswitch(type) {" } {printf " case AUDIT_%s: return \"%s\";\n", $$1, $$1 } END{ print " default: return NULL;\n\t}\n}\n" }' <$< >$@ src/resolve/dns_type-list.txt: src/resolve/dns-type.h $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(SED) -n -r 's/.* DNS_TYPE_(\w+).*/\1/p' <$< >$@ src/resolve/dns_type-to-name.h: src/resolve/dns_type-list.txt $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(AWK) 'BEGIN{ print "const char *dns_type_to_string(int type) {\n\tswitch(type) {" } {printf " case DNS_TYPE_%s: return ", $$1; sub(/_/, "-"); printf "\"%s\";\n", $$1 } END{ print " default: return NULL;\n\t}\n}\n" }' <$< >$@ src/resolve/dns_type-from-name.gperf: src/resolve/dns_type-list.txt $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(AWK) 'BEGIN{ print "struct dns_type_name { const char* name; int id; };"; print "%null-strings"; print "%%";} { s=$$1; sub(/_/, "-", s); printf "%s, ", $$s; printf "DNS_TYPE_%s\n", $$1 }' <$< >$@ # ------------------------------------------------------------------------------ systemd_SOURCES = \ src/core/main.c systemd_CFLAGS = \ $(AM_CFLAGS) \ $(SECCOMP_CFLAGS) \ $(MOUNT_CFLAGS) systemd_LDADD = \ libcore.la dist_pkgsysconf_DATA += \ src/core/system.conf \ src/core/user.conf dist_dbuspolicy_DATA += \ src/core/org.freedesktop.systemd1.conf dist_dbussystemservice_DATA += \ src/core/org.freedesktop.systemd1.service polkitpolicy_in_in_files += \ src/core/org.freedesktop.systemd1.policy.in.in pkgconfigdata_DATA += \ src/core/systemd.pc nodist_rpmmacros_DATA = \ src/core/macros.systemd EXTRA_DIST += \ src/core/systemd.pc.in \ src/core/macros.systemd.in \ src/core/triggers.systemd.in # ------------------------------------------------------------------------------ manual_tests += \ test-ns \ test-loopback \ test-hostname \ test-daemon \ test-cgroup \ test-install \ test-watchdog \ test-log \ test-ipcrm \ test-btrfs \ test-acd \ test-ipv4ll-manual \ test-ask-password-api if HAVE_LIBIPTC manual_tests += \ test-firewall-util endif if HAVE_KMOD manual_tests += \ test-netlink-manual endif tests += \ test-engine \ test-cgroup-mask \ test-job-type \ test-env-replace \ test-strbuf \ test-strv \ test-path \ test-path-util \ test-strxcpyx \ test-siphash24 \ test-unit-name \ test-unit-file \ test-utf8 \ test-ellipsize \ test-util \ test-string-util \ test-extract-word \ test-parse-util \ test-user-util \ test-hostname-util \ test-process-util \ test-terminal-util \ test-path-lookup \ test-barrier \ test-tmpfiles \ test-namespace \ test-date \ test-sleep \ test-replace-var \ test-sched-prio \ test-calendarspec \ test-strip-tab-ansi \ test-cgroup-util \ test-fstab-util \ test-prioq \ test-fileio \ test-time \ test-hashmap \ test-set \ test-bitmap \ test-list \ test-unaligned \ test-tables \ test-device-nodes \ test-xml \ test-json \ test-architecture \ test-socket-util \ test-fdset \ test-conf-files \ test-conf-parser \ test-capability \ test-async \ test-ratelimit \ test-condition \ test-uid-range \ test-bus-policy \ test-locale-util \ test-execute \ test-copy \ test-cap-list \ test-sigbus \ test-rbtree \ test-verbs \ test-af-list \ test-arphrd-list \ test-dns-domain \ test-resolve-tables \ test-install-root \ test-rlimit-util \ test-signal-util if HAVE_ACL tests += \ test-acl-util endif EXTRA_DIST += \ test/a.service \ test/basic.target \ test/b.service \ test/c.service \ test/daughter.service \ test/d.service \ test/end.service \ test/e.service \ test/f.service \ test/grandchild.service \ test/g.service \ test/hello-after-sleep.target \ test/hello.service \ test/h.service \ test/parent-deep.slice \ test/parent.slice \ test/sched_idle_bad.service \ test/sched_idle_ok.service \ test/sched_rr_bad.service \ test/sched_rr_change.service \ test/sched_rr_ok.service \ test/shutdown.target \ test/sleep.service \ test/sockets.target \ test/son.service \ test/sysinit.target \ test/testsuite.target \ test/timers.target \ test/unstoppable.service \ test/test-path/paths.target \ test/test-path/basic.target \ test/test-path/sysinit.target \ test/test-path/path-changed.service \ test/test-path/path-directorynotempty.service \ test/test-path/path-existsglob.service \ test/test-path/path-exists.service \ test/test-path/path-makedirectory.service \ test/test-path/path-modified.service \ test/test-path/path-mycustomunit.service \ test/test-path/path-service.service \ test/test-path/path-changed.path \ test/test-path/path-directorynotempty.path \ test/test-path/path-existsglob.path \ test/test-path/path-exists.path \ test/test-path/path-makedirectory.path \ test/test-path/path-modified.path \ test/test-path/path-unit.path \ test/test-execute/exec-environment-empty.service \ test/test-execute/exec-environment-multiple.service \ test/test-execute/exec-environment.service \ test/test-execute/exec-passenvironment-absent.service \ test/test-execute/exec-passenvironment-empty.service \ test/test-execute/exec-passenvironment-repeated.service \ test/test-execute/exec-passenvironment.service \ test/test-execute/exec-group.service \ test/test-execute/exec-ignoresigpipe-no.service \ test/test-execute/exec-ignoresigpipe-yes.service \ test/test-execute/exec-personality-x86-64.service \ test/test-execute/exec-personality-x86.service \ test/test-execute/exec-personality-s390.service \ test/test-execute/exec-privatedevices-no.service \ test/test-execute/exec-privatedevices-yes.service \ test/test-execute/exec-privatetmp-no.service \ test/test-execute/exec-privatetmp-yes.service \ test/test-execute/exec-systemcallerrornumber.service \ test/test-execute/exec-systemcallfilter-failing2.service \ test/test-execute/exec-systemcallfilter-failing.service \ test/test-execute/exec-systemcallfilter-not-failing2.service \ test/test-execute/exec-systemcallfilter-not-failing.service \ test/test-execute/exec-user.service \ test/test-execute/exec-workingdirectory.service \ test/test-execute/exec-umask-0177.service \ test/test-execute/exec-umask-default.service \ test/test-execute/exec-privatenetwork-yes.service \ test/test-execute/exec-environmentfile.service \ test/test-execute/exec-oomscoreadjust-positive.service \ test/test-execute/exec-oomscoreadjust-negative.service \ test/test-execute/exec-ioschedulingclass-best-effort.service \ test/test-execute/exec-ioschedulingclass-idle.service \ test/test-execute/exec-ioschedulingclass-none.service \ test/test-execute/exec-ioschedulingclass-realtime.service \ test/test-execute/exec-capabilityboundingset-invert.service \ test/test-execute/exec-capabilityboundingset-merge.service \ test/test-execute/exec-capabilityboundingset-reset.service \ test/test-execute/exec-capabilityboundingset-simple.service \ test/bus-policy/hello.conf \ test/bus-policy/methods.conf \ test/bus-policy/ownerships.conf \ test/bus-policy/signals.conf \ test/bus-policy/check-own-rules.conf \ test/bus-policy/many-rules.conf \ test/bus-policy/test.conf EXTRA_DIST += \ src/test/test-helper.h test_device_nodes_SOURCES = \ src/test/test-device-nodes.c test_device_nodes_LDADD = \ libshared.la test_engine_SOURCES = \ src/test/test-engine.c test_engine_CFLAGS = \ $(AM_CFLAGS) \ $(SECCOMP_CFLAGS) \ $(MOUNT_CFLAGS) test_engine_LDADD = \ libcore.la test_job_type_SOURCES = \ src/test/test-job-type.c test_job_type_CFLAGS = \ $(AM_CFLAGS) \ $(SECCOMP_CFLAGS) \ $(MOUNT_CFLAGS) test_job_type_LDADD = \ libcore.la test_ns_SOURCES = \ src/test/test-ns.c test_ns_CFLAGS = \ $(AM_CFLAGS) \ $(SECCOMP_CFLAGS) test_ns_LDADD = \ libcore.la test_loopback_SOURCES = \ src/test/test-loopback.c test_loopback_LDADD = \ libcore.la test_hostname_SOURCES = \ src/test/test-hostname.c test_hostname_LDADD = \ libcore.la test_dns_domain_SOURCES = \ src/test/test-dns-domain.c test_dns_domain_LDADD = \ libsystemd-network.la \ libshared.la test_resolve_tables_SOURCES = \ src/resolve/test-resolve-tables.c \ src/shared/test-tables.h \ src/resolve/dns-type.c \ src/resolve/dns-type.h \ src/resolve/dns_type-from-name.h \ src/resolve/dns_type-to-name.h test_resolve_tables_LDADD = \ libshared.la if ENABLE_EFI manual_tests += \ test-boot-timestamp test_boot_timestamp_SOURCES = \ src/test/test-boot-timestamps.c test_boot_timestamp_LDADD = \ libshared.la endif test_unit_name_SOURCES = \ src/test/test-unit-name.c test_unit_name_CFLAGS = \ $(AM_CFLAGS) \ $(SECCOMP_CFLAGS) \ $(MOUNT_CFLAGS) test_unit_name_LDADD = \ libcore.la test_unit_file_SOURCES = \ src/test/test-unit-file.c test_unit_file_CFLAGS = \ $(AM_CFLAGS) \ $(SECCOMP_CFLAGS) \ $(MOUNT_CFLAGS) test_unit_file_LDADD = \ libcore.la test_utf8_SOURCES = \ src/test/test-utf8.c test_utf8_LDADD = \ libshared.la test_capability_SOURCES = \ src/test/test-capability.c test_capability_LDADD = \ libshared.la test_async_SOURCES = \ src/test/test-async.c test_async_LDADD = \ libshared.la test_locale_util_SOURCES = \ src/test/test-locale-util.c test_locale_util_LDADD = \ libshared.la test_copy_SOURCES = \ src/test/test-copy.c test_copy_LDADD = \ libshared.la test_sigbus_SOURCES = \ src/test/test-sigbus.c test_sigbus_LDADD = \ libshared.la test_rbtree_SOURCES = \ src/test/test-rbtree.c test_rbtree_LDADD = \ libshared.la test_condition_SOURCES = \ src/test/test-condition.c test_condition_LDADD = \ libshared.la test_fdset_SOURCES = \ src/test/test-fdset.c test_fdset_LDADD = \ libshared.la test_fstab_util_SOURCES = \ src/test/test-fstab-util.c test_fstab_util_LDADD = \ libshared.la test_ratelimit_SOURCES = \ src/test/test-ratelimit.c test_ratelimit_LDADD = \ libshared.la test_util_SOURCES = \ src/test/test-util.c test_util_LDADD = \ libshared.la test_string_util_SOURCES = \ src/test/test-string-util.c test_string_util_LDADD = \ libshared.la test_extract_word_SOURCES = \ src/test/test-extract-word.c test_extract_word_LDADD = \ libshared.la test_parse_util_SOURCES = \ src/test/test-parse-util.c test_parse_util_LDADD = \ libshared.la test_user_util_SOURCES = \ src/test/test-user-util.c test_user_util_LDADD = \ libshared.la test_hostname_util_SOURCES = \ src/test/test-hostname-util.c test_hostname_util_LDADD = \ libshared.la test_process_util_SOURCES = \ src/test/test-process-util.c test_process_util_LDADD = \ libshared.la test_terminal_util_SOURCES = \ src/test/test-terminal-util.c test_terminal_util_LDADD = \ libshared.la test_path_lookup_SOURCES = \ src/test/test-path-lookup.c test_path_lookup_LDADD = \ libshared.la test_uid_range_SOURCES = \ src/test/test-uid-range.c test_uid_range_LDADD = \ libshared.la test_cap_list_SOURCES = \ src/test/test-cap-list.c test_cap_list_LDADD = \ libshared.la test_socket_util_SOURCES = \ src/test/test-socket-util.c test_socket_util_LDADD = \ libshared.la test_barrier_SOURCES = \ src/test/test-barrier.c test_barrier_LDADD = \ libshared.la test_tmpfiles_SOURCES = \ src/test/test-tmpfiles.c test_tmpfiles_LDADD = \ libshared.la test_namespace_SOURCES = \ src/test/test-namespace.c test_verbs_SOURCES = \ src/test/test-verbs.c test_verbs_LDADD = \ libshared.la test_install_root_SOURCES = \ src/test/test-install-root.c test_install_root_LDADD = \ libshared.la test_acl_util_SOURCES = \ src/test/test-acl-util.c test_acl_util_LDADD = \ libshared.la test_namespace_LDADD = \ libcore.la test_rlimit_util_SOURCES = \ src/test/test-rlimit-util.c test_rlimit_util_LDADD = \ libshared.la test_ask_password_api_SOURCES = \ src/test/test-ask-password-api.c test_ask_password_api_LDADD = \ libshared.la test_signal_util_SOURCES = \ src/test/test-signal-util.c test_signal_util_LDADD = \ libshared.la BUILT_SOURCES += \ src/test/test-hashmap-ordered.c src/test/test-hashmap-ordered.c: src/test/test-hashmap-plain.c $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(AWK) 'BEGIN { print "/* GENERATED FILE */\n#define ORDERED" } \ { if (!match($$0, "^#include")) \ gsub(/hashmap/, "ordered_hashmap"); \ gsub(/HASHMAP/, "ORDERED_HASHMAP"); \ gsub(/Hashmap/, "OrderedHashmap"); \ print }' <$< >$@ nodist_test_hashmap_SOURCES = \ src/test/test-hashmap-ordered.c test_hashmap_SOURCES = \ src/test/test-hashmap.c \ src/test/test-hashmap-plain.c test_hashmap_LDADD = \ libshared.la test_set_SOURCES = \ src/test/test-set.c test_set_LDADD = \ libshared.la test_bitmap_SOURCES = \ src/test/test-bitmap.c test_bitmap_LDADD = \ libshared.la test_xml_SOURCES = \ src/test/test-xml.c test_xml_LDADD = \ libshared.la test_json_SOURCES = \ src/test/test-json.c test_json_LDADD = \ libshared.la test_list_SOURCES = \ src/test/test-list.c test_list_LDADD = \ libshared.la test_unaligned_LDADD = \ libshared.la test_unaligned_SOURCES = \ src/test/test-unaligned.c test_tables_SOURCES = \ src/test/test-tables.c \ src/shared/test-tables.h \ src/bus-proxyd/bus-xml-policy.c \ src/bus-proxyd/bus-xml-policy.h \ src/journal/journald-server.c \ src/journal/journald-server.h test_tables_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/src/bus-proxyd test_tables_CFLAGS = \ $(AM_CFLAGS) \ $(SECCOMP_CFLAGS) \ $(MOUNT_CFLAGS) test_tables_LDADD = \ libjournal-core.la \ libcore.la \ libudev-core.la test_prioq_SOURCES = \ src/test/test-prioq.c test_prioq_LDADD = \ libshared.la test_fileio_SOURCES = \ src/test/test-fileio.c test_fileio_LDADD = \ libshared.la test_time_SOURCES = \ src/test/test-time.c test_time_LDADD = \ libshared.la test_architecture_SOURCES = \ src/test/test-architecture.c test_architecture_LDADD = \ libshared.la test_log_SOURCES = \ src/test/test-log.c test_log_LDADD = \ libshared.la test_ipcrm_SOURCES = \ src/test/test-ipcrm.c test_ipcrm_LDADD = \ libshared.la test_btrfs_SOURCES = \ src/test/test-btrfs.c test_btrfs_LDADD = \ libshared.la if HAVE_LIBIPTC test_firewall_util_SOURCES = \ src/test/test-firewall-util.c test_firewall_util_CFLAGS = \ $(AM_CFLAGS) \ $(LIBIPTC_CFLAGS) test_firewall_util_LDADD = \ libfirewall.la \ libshared.la \ $(LIBIPTC_LIBS) endif test_netlink_manual_SOURCES = \ src/test/test-netlink-manual.c test_netlink_manual_CFLAGS = \ $(AM_CFLAGS) \ $(KMOD_CFLAGS) test_netlink_manual_LDADD = \ libshared.la \ $(KMOD_LIBS) test_ellipsize_SOURCES = \ src/test/test-ellipsize.c test_ellipsize_LDADD = \ libshared.la test_date_SOURCES = \ src/test/test-date.c test_date_LDADD = \ libshared.la test_sleep_SOURCES = \ src/test/test-sleep.c test_sleep_LDADD = \ libcore.la test_replace_var_SOURCES = \ src/test/test-replace-var.c test_replace_var_LDADD = \ libshared.la test_calendarspec_SOURCES = \ src/test/test-calendarspec.c test_calendarspec_LDADD = \ libshared.la test_strip_tab_ansi_SOURCES = \ src/test/test-strip-tab-ansi.c test_strip_tab_ansi_LDADD = \ libshared.la test_daemon_SOURCES = \ src/test/test-daemon.c test_daemon_LDADD = \ libshared.la test_cgroup_SOURCES = \ src/test/test-cgroup.c test_cgroup_LDADD = \ libshared.la test_cgroup_mask_SOURCES = \ src/test/test-cgroup-mask.c test_cgroup_mask_CPPFLAGS = \ $(AM_CPPFLAGS) \ $(MOUNT_CFLAGS) test_cgroup_mask_CFLAGS = \ $(AM_CFLAGS) \ $(SECCOMP_CFLAGS) test_cgroup_mask_LDADD = \ libcore.la test_cgroup_util_SOURCES = \ src/test/test-cgroup-util.c test_cgroup_util_LDADD = \ libshared.la test_env_replace_SOURCES = \ src/test/test-env-replace.c test_env_replace_LDADD = \ libshared.la test_strbuf_SOURCES = \ src/test/test-strbuf.c test_strbuf_LDADD = \ libshared.la test_strv_SOURCES = \ src/test/test-strv.c test_strv_LDADD = \ libshared.la test_path_util_SOURCES = \ src/test/test-path-util.c test_path_util_LDADD = \ libshared.la test_path_SOURCES = \ src/test/test-path.c test_path_CFLAGS = \ $(AM_CFLAGS) \ $(MOUNT_CFLAGS) test_path_LDADD = \ libcore.la test_execute_SOURCES = \ src/test/test-execute.c test_execute_CFLAGS = \ $(AM_CFLAGS) \ $(MOUNT_CFLAGS) test_execute_LDADD = \ libcore.la test_siphash24_SOURCES = \ src/test/test-siphash24.c test_siphash24_LDADD = \ libshared.la test_strxcpyx_SOURCES = \ src/test/test-strxcpyx.c test_strxcpyx_LDADD = \ libshared.la test_install_SOURCES = \ src/test/test-install.c test_install_LDADD = \ libshared.la test_watchdog_SOURCES = \ src/test/test-watchdog.c test_watchdog_LDADD = \ libshared.la test_sched_prio_SOURCES = \ src/test/test-sched-prio.c test_sched_prio_CPPFLAGS = \ $(AM_CPPFLAGS) \ $(MOUNT_CFLAGS) test_sched_prio_CFLAGS = \ $(AM_CFLAGS) \ $(SECCOMP_CFLAGS) test_sched_prio_LDADD = \ libcore.la test_conf_files_SOURCES = \ src/test/test-conf-files.c test_conf_files_LDADD = \ libshared.la test_conf_parser_SOURCES = \ src/test/test-conf-parser.c test_conf_parser_LDADD = \ libshared.la test_bus_policy_SOURCES = \ src/bus-proxyd/test-bus-xml-policy.c test_bus_policy_LDADD = \ libbus-proxy-core.la \ libshared.la test_af_list_SOURCES = \ src/test/test-af-list.c test_af_list_LDADD = \ libbasic.la test_arphrd_list_SOURCES = \ src/test/test-arphrd-list.c test_arphrd_list_LDADD = \ libbasic.la # ------------------------------------------------------------------------------ ## .PHONY so it always rebuilds it .PHONY: coverage lcov-run lcov-report coverage-sync # run lcov from scratch, always coverage: all $(MAKE) lcov-run $(MAKE) lcov-report coverage_dir = coverage coverage_opts = --base-directory $(srcdir) --directory $(builddir) --rc 'geninfo_adjust_src_path=$(abspath $(srcdir))=>$(abspath $(builddir))' if ENABLE_COVERAGE # reset run coverage tests lcov-run: @rm -rf $(coverage_dir) lcov $(coverage_opts) --zerocounters -$(MAKE) check # generate report based on current coverage data lcov-report: $(MKDIR_P) $(coverage_dir) lcov $(coverage_opts) --compat-libtool --capture --no-external \ | sed 's|$(abspath $(builddir))|$(abspath $(srcdir))|' > $(coverage_dir)/.lcov.info lcov --remove $(coverage_dir)/.lcov.info --output-file $(coverage_dir)/.lcov-clean.info 'test-*' genhtml -t "systemd test coverage" -o $(coverage_dir) $(coverage_dir)/.lcov-clean.info @echo "Coverage report generated in $(abs_builddir)/$(coverage_dir)/index.html" # lcov doesn't work properly with vpath builds, make sure that bad # output is not uploaded by mistake. coverage-sync: coverage test "$(builddir)" = "$(srcdir)" rsync -rlv --delete --omit-dir-times coverage/ $(www_target)/coverage else lcov-run lcov-report: echo "Need to reconfigure with --enable-coverage" endif # ------------------------------------------------------------------------------ systemd_analyze_SOURCES = \ src/analyze/analyze.c \ src/analyze/analyze-verify.c \ src/analyze/analyze-verify.h systemd_analyze_CFLAGS = \ $(AM_CFLAGS) \ $(SECCOMP_CFLAGS) \ $(MOUNT_CFLAGS) systemd_analyze_LDADD = \ libcore.la # ------------------------------------------------------------------------------ systemd_initctl_SOURCES = \ src/initctl/initctl.c systemd_initctl_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_update_utmp_SOURCES = \ src/update-utmp/update-utmp.c systemd_update_utmp_CFLAGS = \ $(AM_CFLAGS) \ $(AUDIT_CFLAGS) systemd_update_utmp_LDADD = \ libshared.la \ $(AUDIT_LIBS) # ------------------------------------------------------------------------------ systemd_update_done_SOURCES = \ src/update-done/update-done.c systemd_update_done_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_shutdown_SOURCES = \ src/core/umount.c \ src/core/umount.h \ src/core/shutdown.c \ src/core/mount-setup.c \ src/core/mount-setup.h \ src/core/killall.h \ src/core/killall.c systemd_shutdown_LDADD = \ libshared.la # ------------------------------------------------------------------------------ if HAVE_KMOD systemd_modules_load_SOURCES = \ src/modules-load/modules-load.c systemd_modules_load_CFLAGS = \ $(AM_CFLAGS) \ $(KMOD_CFLAGS) systemd_modules_load_LDADD = \ libshared.la \ $(KMOD_LIBS) rootlibexec_PROGRAMS += \ systemd-modules-load nodist_systemunit_DATA += \ units/systemd-modules-load.service SYSINIT_TARGET_WANTS += \ systemd-modules-load.service if ENABLE_TMPFILES nodist_systemunit_DATA += \ units/kmod-static-nodes.service SYSINIT_TARGET_WANTS += \ kmod-static-nodes.service endif endif EXTRA_DIST += \ units/systemd-modules-load.service.in \ units/kmod-static-nodes.service.in # ------------------------------------------------------------------------------ if ENABLE_TMPFILES systemd_tmpfiles_SOURCES = \ src/tmpfiles/tmpfiles.c systemd_tmpfiles_LDADD = \ libshared.la rootbin_PROGRAMS += \ systemd-tmpfiles dist_systemunit_DATA += \ units/systemd-tmpfiles-clean.timer nodist_systemunit_DATA += \ units/systemd-tmpfiles-setup-dev.service \ units/systemd-tmpfiles-setup.service \ units/systemd-tmpfiles-clean.service nodist_tmpfiles_DATA = \ tmpfiles.d/systemd.conf \ tmpfiles.d/etc.conf dist_tmpfiles_DATA = \ tmpfiles.d/systemd-nologin.conf \ tmpfiles.d/tmp.conf \ tmpfiles.d/x11.conf \ tmpfiles.d/var.conf \ tmpfiles.d/home.conf \ tmpfiles.d/systemd-nspawn.conf \ tmpfiles.d/journal-nocow.conf if HAVE_SYSV_COMPAT dist_tmpfiles_DATA += \ tmpfiles.d/legacy.conf endif SYSINIT_TARGET_WANTS += \ systemd-tmpfiles-setup-dev.service \ systemd-tmpfiles-setup.service dist_zshcompletion_data += \ shell-completion/zsh/_systemd-tmpfiles TIMERS_TARGET_WANTS += \ systemd-tmpfiles-clean.timer INSTALL_DIRS += \ $(tmpfilesdir) \ $(sysconfdir)/tmpfiles.d endif EXTRA_DIST += \ tmpfiles.d/systemd.conf.m4 \ tmpfiles.d/etc.conf.m4 \ units/systemd-tmpfiles-setup-dev.service.in \ units/systemd-tmpfiles-setup.service.in \ units/systemd-tmpfiles-clean.service.in # ------------------------------------------------------------------------------ if ENABLE_SYSUSERS systemd_sysusers_SOURCES = \ src/sysusers/sysusers.c systemd_sysusers_LDADD = \ libshared.la rootbin_PROGRAMS += \ systemd-sysusers nodist_systemunit_DATA += \ units/systemd-sysusers.service SYSINIT_TARGET_WANTS += \ systemd-sysusers.service nodist_sysusers_DATA = \ sysusers.d/systemd.conf \ sysusers.d/basic.conf if HAVE_REMOTE nodist_sysusers_DATA += \ sysusers.d/systemd-remote.conf endif INSTALL_DIRS += \ $(sysusersdir) endif EXTRA_DIST += \ units/systemd-sysusers.service.in \ sysusers.d/systemd.conf.m4 \ sysusers.d/systemd-remote.conf.m4 \ sysusers.d/basic.conf.in # ------------------------------------------------------------------------------ dist_factory_etc_DATA = \ factory/etc/nsswitch.conf if HAVE_PAM dist_factory_pam_DATA = \ factory/etc/pam.d/system-auth \ factory/etc/pam.d/other endif # ------------------------------------------------------------------------------ if ENABLE_FIRSTBOOT systemd_firstboot_SOURCES = \ src/firstboot/firstboot.c systemd_firstboot_LDADD = \ libshared.la \ -lcrypt rootbin_PROGRAMS += \ systemd-firstboot nodist_systemunit_DATA += \ units/systemd-firstboot.service SYSINIT_TARGET_WANTS += \ systemd-firstboot.service endif EXTRA_DIST += \ units/systemd-firstboot.service.in # ------------------------------------------------------------------------------ systemd_machine_id_setup_SOURCES = \ src/machine-id-setup/machine-id-setup-main.c \ src/core/machine-id-setup.c \ src/core/machine-id-setup.h systemd_machine_id_setup_LDADD = \ libshared.la SYSINIT_TARGET_WANTS += \ systemd-machine-id-commit.service # ------------------------------------------------------------------------------ systemd_sysctl_SOURCES = \ src/sysctl/sysctl.c systemd_sysctl_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_sleep_SOURCES = \ src/sleep/sleep.c systemd_sleep_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_fsck_SOURCES = \ src/fsck/fsck.c systemd_fsck_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_ac_power_SOURCES = \ src/ac-power/ac-power.c systemd_ac_power_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_detect_virt_SOURCES = \ src/detect-virt/detect-virt.c systemd_detect_virt_LDADD = \ libshared.la INSTALL_EXEC_HOOKS += \ systemd-detect-virt-install-hook # ------------------------------------------------------------------------------ systemd_delta_SOURCES = \ src/delta/delta.c systemd_delta_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_getty_generator_SOURCES = \ src/getty-generator/getty-generator.c systemd_getty_generator_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_debug_generator_SOURCES = \ src/debug-generator/debug-generator.c systemd_debug_generator_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_fstab_generator_SOURCES = \ src/fstab-generator/fstab-generator.c \ src/core/mount-setup.c systemd_fstab_generator_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_system_update_generator_SOURCES = \ src/system-update-generator/system-update-generator.c systemd_system_update_generator_LDADD = \ libshared.la # ------------------------------------------------------------------------------ if ENABLE_HIBERNATE systemgenerator_PROGRAMS += \ systemd-hibernate-resume-generator rootlibexec_PROGRAMS += \ systemd-hibernate-resume systemd_hibernate_resume_SOURCES = \ src/hibernate-resume/hibernate-resume.c systemd_hibernate_resume_LDADD = \ libshared.la systemd_hibernate_resume_generator_SOURCES = \ src/hibernate-resume/hibernate-resume-generator.c systemd_hibernate_resume_generator_LDADD = \ libshared.la dist_systemunit_DATA += \ units/hibernate.target \ units/hybrid-sleep.target nodist_systemunit_DATA += \ units/systemd-hibernate.service \ units/systemd-hibernate-resume@.service \ units/systemd-hybrid-sleep.service endif EXTRA_DIST += \ units/systemd-hibernate.service.in \ units/systemd-hibernate-resume@.service.in \ units/systemd-hybrid-sleep.service.in # ------------------------------------------------------------------------------ if ENABLE_EFI if HAVE_BLKID bootctl_SOURCES = \ src/boot/bootctl.c bootctl_CPPFLAGS = \ $(AM_CPPFLAGS) \ -DEFI_MACHINE_TYPE_NAME=\"$(EFI_MACHINE_TYPE_NAME)\" \ -DBOOTLIBDIR=\"$(bootlibdir)\" bootctl_CFLAGS = \ $(AM_CFLAGS) \ $(BLKID_CFLAGS) bootctl_LDADD = \ libshared.la \ $(BLKID_LIBS) bin_PROGRAMS += \ bootctl dist_bashcompletion_data += \ shell-completion/bash/bootctl dist_zshcompletion_data += \ shell-completion/zsh/_bootctl endif # ------------------------------------------------------------------------------ if HAVE_GNUEFI efi_cppflags = \ $(EFI_CPPFLAGS) \ -I$(top_builddir) -include config.h \ -I$(EFI_INC_DIR)/efi \ -I$(EFI_INC_DIR)/efi/$(EFI_ARCH) \ -DEFI_MACHINE_TYPE_NAME=\"$(EFI_MACHINE_TYPE_NAME)\" efi_cflags = \ $(EFI_CFLAGS) \ -Wall \ -Wextra \ -std=gnu90 \ -nostdinc \ -ggdb -O0 \ -fpic \ -fshort-wchar \ -nostdinc \ -ffreestanding \ -fno-strict-aliasing \ -fno-stack-protector \ -Wsign-compare \ -Wno-missing-field-initializers if ARCH_X86_64 efi_cflags += \ -mno-red-zone \ -mno-sse \ -mno-mmx \ -DEFI_FUNCTION_WRAPPER \ -DGNU_EFI_USE_MS_ABI endif if ARCH_IA32 efi_cflags += \ -mno-sse \ -mno-mmx endif efi_ldflags = \ $(EFI_LDFLAGS) \ -T $(EFI_LDS_DIR)/elf_$(EFI_ARCH)_efi.lds \ -shared \ -Bsymbolic \ -nostdlib \ -znocombreloc \ -L $(EFI_LIB_DIR) \ $(EFI_LDS_DIR)/crt0-efi-$(EFI_ARCH).o # Aarch64 and ARM32 don't have an EFI capable objcopy. Use 'binary' instead, # and add required symbols manually. if ARCH_AARCH64 efi_ldflags += --defsym=EFI_SUBSYSTEM=0xa EFI_FORMAT = -O binary else EFI_FORMAT = --target=efi-app-$(EFI_ARCH) endif endif endif # ------------------------------------------------------------------------------ systemd_boot_headers = \ src/boot/efi/util.h \ src/boot/efi/console.h \ src/boot/efi/graphics.h \ src/boot/efi/pefile.h \ src/boot/efi/disk.h systemd_boot_sources = \ src/boot/efi/util.c \ src/boot/efi/console.c \ src/boot/efi/graphics.c \ src/boot/efi/pefile.c \ src/boot/efi/disk.c \ src/boot/efi/boot.c EXTRA_DIST += $(systemd_boot_sources) $(systemd_boot_headers) systemd_boot_objects = $(addprefix $(top_builddir)/,$(systemd_boot_sources:.c=.o)) systemd_boot_solib = $(top_builddir)/src/boot/efi/systemd_boot.so systemd_boot = systemd-boot$(EFI_MACHINE_TYPE_NAME).efi if ENABLE_EFI if HAVE_GNUEFI bootlib_DATA = $(systemd_boot) $(top_builddir)/src/boot/efi/%.o: $(top_srcdir)/src/boot/efi/%.c $(addprefix $(top_srcdir)/,$(systemd_boot_headers)) @$(MKDIR_P) $(top_builddir)/src/boot/efi/ $(AM_V_CC)$(EFI_CC) $(efi_cppflags) $(efi_cflags) -c $< -o $@ $(systemd_boot_solib): $(systemd_boot_objects) $(AM_V_CCLD)$(LD) $(efi_ldflags) $(systemd_boot_objects) \ -o $@ -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name); \ nm -D -u $@ | grep ' U ' && exit 1 || : $(systemd_boot): $(systemd_boot_solib) $(AM_V_GEN)$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic \ -j .dynsym -j .rel -j .rela -j .reloc $(EFI_FORMAT) $< $@ endif endif CLEANFILES += $(systemd_boot_objects) $(systemd_boot_solib) $(systemd_boot) # ------------------------------------------------------------------------------ stub_headers = \ src/boot/efi/util.h \ src/boot/efi/pefile.h \ src/boot/efi/disk.h \ src/boot/efi/graphics.h \ src/boot/efi/splash.h \ src/boot/efi/linux.h stub_sources = \ src/boot/efi/util.c \ src/boot/efi/pefile.c \ src/boot/efi/disk.c \ src/boot/efi/graphics.c \ src/boot/efi/splash.c \ src/boot/efi/linux.c \ src/boot/efi/stub.c EXTRA_DIST += \ $(stub_sources) \ $(stub_headers) \ test/splash.bmp stub_objects = $(addprefix $(top_builddir)/,$(stub_sources:.c=.o)) stub_solib = $(top_builddir)/src/boot/efi/stub.so stub = linux$(EFI_MACHINE_TYPE_NAME).efi.stub if ENABLE_EFI if HAVE_GNUEFI bootlib_DATA += $(stub) $(top_builddir)/src/boot/efi/%.o: $(top_srcdir)/src/boot/efi/%.c $(addprefix $(top_srcdir)/,$(stub_headers)) @$(MKDIR_P) $(top_builddir)/src/boot/efi/ $(AM_V_CC)$(EFI_CC) $(efi_cppflags) $(efi_cflags) -c $< -o $@ $(stub_solib): $(stub_objects) $(AM_V_CCLD)$(LD) $(efi_ldflags) $(stub_objects) \ -o $@ -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name); \ nm -D -u $@ | grep ' U ' && exit 1 || : $(stub): $(stub_solib) $(AM_V_GEN)$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic \ -j .dynsym -j .rel -j .rela -j .reloc $(EFI_FORMAT) $< $@ endif endif CLEANFILES += $(stub_objects) $(stub_solib) $(stub) # ------------------------------------------------------------------------------ CLEANFILES += test-efi-disk.img test-efi-disk.img: $(systemd_boot) $(stub) test/test-efi-create-disk.sh $(AM_V_GEN)test/test-efi-create-disk.sh test-efi: test-efi-disk.img $(QEMU) -machine accel=kvm -m 1024 -bios $(QEMU_BIOS) -snapshot test-efi-disk.img EXTRA_DIST += test/test-efi-create-disk.sh # ------------------------------------------------------------------------------ if HAVE_BLKID systemgenerator_PROGRAMS += \ systemd-gpt-auto-generator systemd_gpt_auto_generator_SOURCES = \ src/gpt-auto-generator/gpt-auto-generator.c \ src/basic/blkid-util.h systemd_gpt_auto_generator_LDADD = \ libshared.la \ $(BLKID_LIBS) systemd_gpt_auto_generator_CFLAGS = \ $(AM_CFLAGS) \ $(BLKID_CFLAGS) endif # ------------------------------------------------------------------------------ systemgenerator_PROGRAMS += \ systemd-dbus1-generator systemd_dbus1_generator_SOURCES = \ src/dbus1-generator/dbus1-generator.c systemd_dbus1_generator_LDADD = \ libshared.la dbus1-generator-install-hook: $(AM_V_at)$(MKDIR_P) $(DESTDIR)$(usergeneratordir) $(AM_V_RM)rm -f $(DESTDIR)$(usergeneratordir)/systemd-dbus1-generator $(AM_V_LN)$(LN_S) --relative -f $(DESTDIR)$(systemgeneratordir)/systemd-dbus1-generator $(DESTDIR)$(usergeneratordir)/systemd-dbus1-generator dbus1-generator-uninstall-hook: rm -f $(DESTDIR)$(usergeneratordir)/systemd-dbus1-generator dist_xinitrc_SCRIPTS = \ xorg/50-systemd-user.sh INSTALL_EXEC_HOOKS += dbus1-generator-install-hook UNINSTALL_EXEC_HOOKS += dbus1-generator-uninstall-hook # ------------------------------------------------------------------------------ systemd_sysv_generator_SOURCES = \ src/sysv-generator/sysv-generator.c systemd_sysv_generator_LDADD = \ libcore.la # ------------------------------------------------------------------------------ systemd_rc_local_generator_SOURCES = \ src/rc-local-generator/rc-local-generator.c systemd_rc_local_generator_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_remount_fs_SOURCES = \ src/remount-fs/remount-fs.c \ src/core/mount-setup.c \ src/core/mount-setup.h systemd_remount_fs_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_cgroups_agent_SOURCES = \ src/cgroups-agent/cgroups-agent.c systemd_cgroups_agent_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_escape_SOURCES = \ src/escape/escape.c systemd_escape_LDADD = \ libshared.la # ----------------------------------------------------------------------------- systemctl_SOURCES = \ src/systemctl/systemctl.c systemctl_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_notify_SOURCES = \ src/notify/notify.c systemd_notify_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_path_SOURCES = \ src/path/path.c systemd_path_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_ask_password_SOURCES = \ src/ask-password/ask-password.c systemd_ask_password_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_reply_password_SOURCES = \ src/reply-password/reply-password.c systemd_reply_password_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_cgls_SOURCES = \ src/cgls/cgls.c systemd_cgls_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_cgtop_SOURCES = \ src/cgtop/cgtop.c systemd_cgtop_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_nspawn_SOURCES = \ src/nspawn/nspawn.c \ src/nspawn/nspawn-settings.c \ src/nspawn/nspawn-settings.h \ src/nspawn/nspawn-mount.c \ src/nspawn/nspawn-mount.h \ src/nspawn/nspawn-network.c \ src/nspawn/nspawn-network.h \ src/nspawn/nspawn-expose-ports.c \ src/nspawn/nspawn-expose-ports.h \ src/nspawn/nspawn-cgroup.c \ src/nspawn/nspawn-cgroup.h \ src/nspawn/nspawn-register.c \ src/nspawn/nspawn-register.h \ src/nspawn/nspawn-setuid.c \ src/nspawn/nspawn-setuid.h \ src/nspawn/nspawn-stub-pid1.c \ src/nspawn/nspawn-stub-pid1.h \ src/core/mount-setup.c \ src/core/mount-setup.h \ src/core/loopback-setup.c \ src/core/loopback-setup.h nodist_systemd_nspawn_SOURCES = \ src/nspawn/nspawn-gperf.c gperf_gperf_sources += \ src/nspawn/nspawn-gperf.gperf systemd_nspawn_CFLAGS = \ $(AM_CFLAGS) \ $(BLKID_CFLAGS) \ $(SECCOMP_CFLAGS) systemd_nspawn_LDADD = \ libshared.la \ $(BLKID_LIBS) if HAVE_LIBIPTC systemd_nspawn_LDADD += \ libfirewall.la endif # ------------------------------------------------------------------------------ systemd_run_SOURCES = \ src/run/run.c systemd_run_LDADD = \ libshared.la # ------------------------------------------------------------------------------ noinst_LTLIBRARIES += \ libbus-proxy-core.la libbus_proxy_core_la_SOURCES = \ src/bus-proxyd/bus-xml-policy.c \ src/bus-proxyd/bus-xml-policy.h \ src/bus-proxyd/driver.c \ src/bus-proxyd/driver.h \ src/bus-proxyd/proxy.c \ src/bus-proxyd/proxy.h \ src/bus-proxyd/synthesize.c \ src/bus-proxyd/synthesize.h libbus_proxy_core_la_LIBADD = \ libshared.la systemd_bus_proxyd_SOURCES = \ src/bus-proxyd/bus-proxyd.c systemd_bus_proxyd_LDADD = \ libbus-proxy-core.la \ libshared.la systemd_stdio_bridge_SOURCES = \ src/bus-proxyd/stdio-bridge.c systemd_stdio_bridge_LDADD = \ libbus-proxy-core.la \ libshared.la nodist_systemunit_DATA += \ units/systemd-bus-proxyd.service dist_systemunit_DATA += \ units/systemd-bus-proxyd.socket nodist_userunit_DATA += \ units/user/systemd-bus-proxyd.service dist_userunit_DATA += \ units/user/systemd-bus-proxyd.socket EXTRA_DIST += \ units/systemd-bus-proxyd.service.m4.in \ units/user/systemd-bus-proxyd.service.in if HAVE_SMACK bus-proxyd-set-cap-hook: -$(SETCAP) cap_mac_admin+ei $(DESTDIR)$(rootlibexecdir)/systemd-bus-proxyd INSTALL_EXEC_HOOKS += bus-proxyd-set-cap-hook endif # ------------------------------------------------------------------------------ systemd_tty_ask_password_agent_SOURCES = \ src/tty-ask-password-agent/tty-ask-password-agent.c systemd_tty_ask_password_agent_LDADD = \ libshared.la # ------------------------------------------------------------------------------ libsystemd_internal_la_SOURCES = \ src/systemd/sd-bus.h \ src/systemd/sd-bus-protocol.h \ src/systemd/sd-bus-vtable.h \ src/systemd/sd-utf8.h \ src/systemd/sd-event.h \ src/systemd/sd-netlink.h \ src/systemd/sd-resolve.h \ src/systemd/sd-login.h \ src/systemd/sd-id128.h \ src/systemd/sd-daemon.h \ src/systemd/sd-path.h \ src/systemd/sd-network.h \ src/systemd/sd-hwdb.h \ src/systemd/sd-device.h \ src/libsystemd/libsystemd.sym \ src/libsystemd/sd-bus/sd-bus.c \ src/libsystemd/sd-bus/bus-control.c \ src/libsystemd/sd-bus/bus-control.h \ src/libsystemd/sd-bus/bus-error.c \ src/libsystemd/sd-bus/bus-error.h \ src/libsystemd/sd-bus/bus-common-errors.h \ src/libsystemd/sd-bus/bus-common-errors.c \ src/libsystemd/sd-bus/bus-internal.c \ src/libsystemd/sd-bus/bus-internal.h \ src/libsystemd/sd-bus/bus-socket.c \ src/libsystemd/sd-bus/bus-socket.h \ src/libsystemd/sd-bus/bus-kernel.c \ src/libsystemd/sd-bus/bus-kernel.h \ src/libsystemd/sd-bus/bus-container.c \ src/libsystemd/sd-bus/bus-container.h \ src/libsystemd/sd-bus/bus-message.c \ src/libsystemd/sd-bus/bus-message.h \ src/libsystemd/sd-bus/bus-creds.c \ src/libsystemd/sd-bus/bus-creds.h \ src/libsystemd/sd-bus/bus-signature.c \ src/libsystemd/sd-bus/bus-signature.h \ src/libsystemd/sd-bus/bus-type.c \ src/libsystemd/sd-bus/bus-type.h \ src/libsystemd/sd-bus/bus-match.c \ src/libsystemd/sd-bus/bus-match.h \ src/libsystemd/sd-bus/bus-bloom.c \ src/libsystemd/sd-bus/bus-bloom.h \ src/libsystemd/sd-bus/bus-introspect.c \ src/libsystemd/sd-bus/bus-introspect.h \ src/libsystemd/sd-bus/bus-objects.c \ src/libsystemd/sd-bus/bus-objects.h \ src/libsystemd/sd-bus/bus-gvariant.c \ src/libsystemd/sd-bus/bus-gvariant.h \ src/libsystemd/sd-bus/bus-convenience.c \ src/libsystemd/sd-bus/bus-track.c \ src/libsystemd/sd-bus/bus-track.h \ src/libsystemd/sd-bus/bus-slot.c \ src/libsystemd/sd-bus/bus-slot.h \ src/libsystemd/sd-bus/bus-protocol.h \ src/libsystemd/sd-bus/kdbus.h \ src/libsystemd/sd-bus/bus-dump.c \ src/libsystemd/sd-bus/bus-dump.h \ src/libsystemd/sd-utf8/sd-utf8.c \ src/libsystemd/sd-event/sd-event.c \ src/libsystemd/sd-netlink/sd-netlink.c \ src/libsystemd/sd-netlink/netlink-internal.h \ src/libsystemd/sd-netlink/netlink-message.c \ src/libsystemd/sd-netlink/netlink-socket.c \ src/libsystemd/sd-netlink/rtnl-message.c \ src/libsystemd/sd-netlink/netlink-types.h \ src/libsystemd/sd-netlink/netlink-types.c \ src/libsystemd/sd-netlink/netlink-util.h \ src/libsystemd/sd-netlink/netlink-util.c \ src/libsystemd/sd-netlink/local-addresses.h \ src/libsystemd/sd-netlink/local-addresses.c \ src/libsystemd/sd-id128/sd-id128.c \ src/libsystemd/sd-daemon/sd-daemon.c \ src/libsystemd/sd-login/sd-login.c \ src/libsystemd/sd-path/sd-path.c \ src/libsystemd/sd-network/sd-network.c \ src/libsystemd/sd-network/network-util.h \ src/libsystemd/sd-network/network-util.c \ src/libsystemd/sd-hwdb/sd-hwdb.c \ src/libsystemd/sd-hwdb/hwdb-util.h \ src/libsystemd/sd-hwdb/hwdb-internal.h \ src/libsystemd/sd-device/device-internal.h \ src/libsystemd/sd-device/device-util.h \ src/libsystemd/sd-device/device-enumerator.c \ src/libsystemd/sd-device/device-enumerator-private.h \ src/libsystemd/sd-device/sd-device.c \ src/libsystemd/sd-device/device-private.c \ src/libsystemd/sd-device/device-private.h \ src/libsystemd/sd-resolve/sd-resolve.c libsystemd_internal_la_LIBADD = \ libbasic.la \ -lresolv noinst_LTLIBRARIES += \ libsystemd-internal.la EXTRA_DIST += \ src/libsystemd/libsystemd.pc.in \ src/libsystemd/sd-bus/DIFFERENCES \ src/libsystemd/sd-bus/GVARIANT-SERIALIZATION libsystemd_la_SOURCES = \ $(libsystemd_internal_la_SOURCES) \ $(libsystemd_journal_internal_la_SOURCES) nodist_libsystemd_la_SOURCES = \ $(nodist_libsystemd_internal_la_SOURCES) libsystemd_la_CFLAGS = \ $(libsystemd_internal_la_CFLAGS) \ $(libsystemd_journal_internal_la_CFLAGS) libsystemd_la_LDFLAGS = \ $(AM_LDFLAGS) \ -version-info $(LIBSYSTEMD_CURRENT):$(LIBSYSTEMD_REVISION):$(LIBSYSTEMD_AGE) \ -Wl,--version-script=$(top_srcdir)/src/libsystemd/libsystemd.sym libsystemd_la_LIBADD = \ $(libsystemd_internal_la_LIBADD) \ $(libsystemd_journal_internal_la_LIBADD) libsystemd-install-hook: libname=libsystemd.so && $(move-to-rootlibdir) libsystemd-uninstall-hook: rm -f $(DESTDIR)$(rootlibdir)/libsystemd.so* INSTALL_EXEC_HOOKS += libsystemd-install-hook UNINSTALL_EXEC_HOOKS += libsystemd-uninstall-hook pkgconfiglib_DATA += \ src/libsystemd/libsystemd.pc pkginclude_HEADERS += \ src/systemd/sd-bus.h \ src/systemd/sd-bus-protocol.h \ src/systemd/sd-bus-vtable.h \ src/systemd/sd-event.h \ src/systemd/sd-login.h \ src/systemd/sd-id128.h \ src/systemd/sd-daemon.h lib_LTLIBRARIES += \ libsystemd.la tests += \ test-bus-marshal \ test-bus-signature \ test-bus-benchmark \ test-bus-chat \ test-bus-cleanup \ test-bus-server \ test-bus-match \ test-bus-proxy \ test-bus-kernel \ test-bus-kernel-bloom \ test-bus-zero-copy \ test-bus-introspect \ test-bus-objects \ test-bus-error \ test-bus-creds \ test-bus-gvariant \ test-event \ test-netlink \ test-local-addresses \ test-resolve bin_PROGRAMS += \ busctl test_bus_marshal_SOURCES = \ src/libsystemd/sd-bus/test-bus-marshal.c test_bus_marshal_LDADD = \ libshared.la \ $(GLIB_LIBS) \ $(DBUS_LIBS) test_bus_marshal_CFLAGS = \ $(AM_CFLAGS) \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) test_bus_signature_SOURCES = \ src/libsystemd/sd-bus/test-bus-signature.c test_bus_signature_LDADD = \ libshared.la test_bus_chat_SOURCES = \ src/libsystemd/sd-bus/test-bus-chat.c test_bus_chat_LDADD = \ libshared.la test_bus_cleanup_SOURCES = \ src/libsystemd/sd-bus/test-bus-cleanup.c test_bus_cleanup_CFLAGS = \ $(AM_CFLAGS) \ $(SECCOMP_CFLAGS) test_bus_cleanup_LDADD = \ libshared.la test_bus_server_SOURCES = \ src/libsystemd/sd-bus/test-bus-server.c test_bus_server_LDADD = \ libshared.la test_bus_objects_SOURCES = \ src/libsystemd/sd-bus/test-bus-objects.c test_bus_objects_LDADD = \ libshared.la test_bus_error_SOURCES = \ src/libsystemd/sd-bus/test-bus-error.c test_bus_error_LDADD = \ libshared.la test_bus_gvariant_SOURCES = \ src/libsystemd/sd-bus/test-bus-gvariant.c test_bus_gvariant_LDADD = \ libshared.la \ $(GLIB_LIBS) test_bus_gvariant_CFLAGS = \ $(AM_CFLAGS) \ $(GLIB_CFLAGS) test_bus_creds_SOURCES = \ src/libsystemd/sd-bus/test-bus-creds.c test_bus_creds_LDADD = \ libshared.la test_bus_match_SOURCES = \ src/libsystemd/sd-bus/test-bus-match.c test_bus_match_LDADD = \ libshared.la test_bus_proxy_SOURCES = \ src/libsystemd/sd-bus/test-bus-proxy.c test_bus_proxy_LDADD = \ libshared.la test_bus_kernel_SOURCES = \ src/libsystemd/sd-bus/test-bus-kernel.c test_bus_kernel_LDADD = \ libshared.la test_bus_kernel_bloom_SOURCES = \ src/libsystemd/sd-bus/test-bus-kernel-bloom.c test_bus_kernel_bloom_LDADD = \ libshared.la test_bus_benchmark_SOURCES = \ src/libsystemd/sd-bus/test-bus-benchmark.c test_bus_benchmark_LDADD = \ libshared.la test_bus_zero_copy_SOURCES = \ src/libsystemd/sd-bus/test-bus-zero-copy.c test_bus_zero_copy_LDADD = \ libshared.la test_bus_introspect_SOURCES = \ src/libsystemd/sd-bus/test-bus-introspect.c test_bus_introspect_LDADD = \ libshared.la test_event_SOURCES = \ src/libsystemd/sd-event/test-event.c test_event_LDADD = \ libshared.la test_netlink_SOURCES = \ src/libsystemd/sd-netlink/test-netlink.c test_netlink_LDADD = \ libshared.la test_local_addresses_SOURCES = \ src/libsystemd/sd-netlink/test-local-addresses.c test_local_addresses_LDADD = \ libshared.la test_resolve_SOURCES = \ src/libsystemd/sd-resolve/test-resolve.c test_resolve_LDADD = \ libshared.la busctl_SOURCES = \ src/libsystemd/sd-bus/busctl.c \ src/libsystemd/sd-bus/busctl-introspect.c \ src/libsystemd/sd-bus/busctl-introspect.h busctl_LDADD = \ libshared.la # ------------------------------------------------------------------------------ noinst_LTLIBRARIES += \ libsystemd-network.la libsystemd_network_la_CFLAGS = \ $(AM_CFLAGS) \ $(KMOD_CFLAGS) libsystemd_network_la_SOURCES = \ src/systemd/sd-dhcp-client.h \ src/systemd/sd-dhcp-server.h \ src/systemd/sd-dhcp-lease.h \ src/systemd/sd-ipv4ll.h \ src/systemd/sd-ipv4acd.h \ src/systemd/sd-ndisc.h \ src/systemd/sd-dhcp6-client.h \ src/systemd/sd-dhcp6-lease.h \ src/systemd/sd-lldp.h \ src/libsystemd-network/sd-dhcp-client.c \ src/libsystemd-network/sd-dhcp-server.c \ src/libsystemd-network/dhcp-network.c \ src/libsystemd-network/dhcp-option.c \ src/libsystemd-network/dhcp-packet.c \ src/libsystemd-network/dhcp-internal.h \ src/libsystemd-network/dhcp-server-internal.h \ src/libsystemd-network/dhcp-protocol.h \ src/libsystemd-network/dhcp-lease-internal.h \ src/libsystemd-network/sd-dhcp-lease.c \ src/libsystemd-network/sd-ipv4ll.c \ src/libsystemd-network/sd-ipv4acd.c \ src/libsystemd-network/arp-util.h \ src/libsystemd-network/arp-util.c \ src/libsystemd-network/network-internal.c \ src/libsystemd-network/network-internal.h \ src/libsystemd-network/sd-ndisc.c \ src/libsystemd-network/icmp6-util.h \ src/libsystemd-network/icmp6-util.c \ src/libsystemd-network/sd-dhcp6-client.c \ src/libsystemd-network/dhcp6-internal.h \ src/libsystemd-network/dhcp6-protocol.h \ src/libsystemd-network/dhcp6-network.c \ src/libsystemd-network/dhcp6-option.c \ src/libsystemd-network/dhcp6-lease-internal.h \ src/libsystemd-network/sd-dhcp6-lease.c \ src/libsystemd-network/dhcp-identifier.h \ src/libsystemd-network/dhcp-identifier.c \ src/libsystemd-network/lldp.h \ src/libsystemd-network/lldp-tlv.h \ src/libsystemd-network/lldp-tlv.c \ src/libsystemd-network/lldp-network.h \ src/libsystemd-network/lldp-network.c \ src/libsystemd-network/lldp-port.h \ src/libsystemd-network/lldp-port.c \ src/libsystemd-network/lldp-internal.h \ src/libsystemd-network/lldp-internal.c \ src/libsystemd-network/sd-lldp.c libsystemd_network_la_LIBADD = \ $(KMOD_LIBS) test_dhcp_option_SOURCES = \ src/libsystemd-network/dhcp-protocol.h \ src/libsystemd-network/dhcp-internal.h \ src/libsystemd-network/test-dhcp-option.c test_dhcp_option_LDADD = \ libsystemd-network.la \ libshared.la test_dhcp_client_SOURCES = \ src/systemd/sd-dhcp-client.h \ src/libsystemd-network/dhcp-protocol.h \ src/libsystemd-network/dhcp-internal.h \ src/libsystemd-network/test-dhcp-client.c test_dhcp_client_LDADD = \ libsystemd-network.la \ libshared.la test_dhcp_server_SOURCES = \ src/libsystemd-network/test-dhcp-server.c test_dhcp_server_LDADD = \ libsystemd-network.la \ libshared.la test_ipv4ll_SOURCES = \ src/systemd/sd-ipv4ll.h \ src/libsystemd-network/arp-util.h \ src/libsystemd-network/test-ipv4ll.c test_ipv4ll_LDADD = \ libsystemd-network.la \ libshared.la test_ipv4ll_manual_SOURCES = \ src/systemd/sd-ipv4ll.h \ src/libsystemd-network/test-ipv4ll-manual.c test_ipv4ll_manual_LDADD = \ libsystemd-network.la \ libshared.la test_acd_SOURCES = \ src/systemd/sd-ipv4acd.h \ src/libsystemd-network/test-acd.c test_acd_LDADD = \ libsystemd-network.la \ libshared.la test_ndisc_rs_SOURCES = \ src/systemd/sd-dhcp6-client.h \ src/systemd/sd-ndisc.h \ src/libsystemd-network/icmp6-util.h \ src/libsystemd-network/test-ndisc-rs.c \ src/libsystemd-network/dhcp-identifier.h \ src/libsystemd-network/dhcp-identifier.c test_ndisc_rs_LDADD = \ libsystemd-network.la \ libudev.la \ libshared.la test_dhcp6_client_SOURCES = \ src/systemd/sd-dhcp6-client.h \ src/libsystemd-network/dhcp6-internal.h \ src/libsystemd-network/test-dhcp6-client.c \ src/libsystemd-network/dhcp-identifier.h \ src/libsystemd-network/dhcp-identifier.c test_dhcp6_client_LDADD = \ libsystemd-network.la \ libudev.la \ libshared.la test_lldp_SOURCES = \ src/libsystemd-network/lldp.h \ src/libsystemd-network/lldp-tlv.h \ src/libsystemd-network/lldp-tlv.c \ src/libsystemd-network/test-lldp.c test_lldp_LDADD = \ libsystemd-network.la \ libshared.la tests += \ test-dhcp-option \ test-dhcp-client \ test-dhcp-server \ test-ipv4ll \ test-ndisc-rs \ test-dhcp6-client \ test-lldp # ------------------------------------------------------------------------------ include_HEADERS += \ src/libudev/libudev.h lib_LTLIBRARIES += \ libudev.la libudev_la_SOURCES =\ src/libudev/libudev.sym \ src/libudev/libudev-private.h \ src/libudev/libudev-device-internal.h \ src/libudev/libudev.c \ src/libudev/libudev-list.c \ src/libudev/libudev-util.c \ src/libudev/libudev-device.c \ src/libudev/libudev-device-private.c \ src/libudev/libudev-enumerate.c \ src/libudev/libudev-monitor.c \ src/libudev/libudev-queue.c \ src/libudev/libudev-hwdb.c libudev_la_LDFLAGS = \ $(AM_LDFLAGS) \ -version-info $(LIBUDEV_CURRENT):$(LIBUDEV_REVISION):$(LIBUDEV_AGE) \ -Wl,--version-script=$(top_srcdir)/src/libudev/libudev.sym libudev_la_LIBADD = \ libsystemd-internal.la pkgconfiglib_DATA += \ src/libudev/libudev.pc EXTRA_DIST += \ src/libudev/libudev.pc.in # move lib from $(libdir) to $(rootlibdir) and update devel link, if needed libudev-install-hook: libname=libudev.so && $(move-to-rootlibdir) libudev-uninstall-hook: rm -f $(DESTDIR)$(rootlibdir)/libudev.so* INSTALL_EXEC_HOOKS += libudev-install-hook UNINSTALL_EXEC_HOOKS += libudev-uninstall-hook # ------------------------------------------------------------------------------ noinst_LTLIBRARIES += \ libudev-internal.la libudev_internal_la_SOURCES =\ $(libudev_la_SOURCES) # ------------------------------------------------------------------------------ INSTALL_DIRS += \ $(sysconfdir)/udev/rules.d dist_network_DATA = \ network/99-default.link \ network/80-container-host0.network \ network/80-container-ve.network dist_udevrules_DATA += \ rules/50-udev-default.rules \ rules/60-block.rules \ rules/60-drm.rules \ rules/60-evdev.rules \ rules/60-persistent-storage-tape.rules \ rules/60-persistent-input.rules \ rules/60-persistent-alsa.rules \ rules/60-persistent-storage.rules \ rules/60-serial.rules \ rules/64-btrfs.rules \ rules/70-mouse.rules \ rules/75-net-description.rules \ rules/78-sound-card.rules \ rules/80-net-setup-link.rules nodist_udevrules_DATA += \ rules/99-systemd.rules udevconfdir = $(sysconfdir)/udev dist_udevconf_DATA = \ src/udev/udev.conf pkgconfigdata_DATA += \ src/udev/udev.pc EXTRA_DIST += \ rules/99-systemd.rules.in \ src/udev/udev.pc.in EXTRA_DIST += \ units/systemd-udevd.service.in \ units/systemd-udev-trigger.service.in \ units/systemd-udev-settle.service.in SOCKETS_TARGET_WANTS += \ systemd-udevd-control.socket \ systemd-udevd-kernel.socket SYSINIT_TARGET_WANTS += \ systemd-udevd.service \ systemd-udev-trigger.service rootbin_PROGRAMS += \ udevadm rootlibexec_PROGRAMS += \ systemd-udevd noinst_LTLIBRARIES += \ libudev-core.la src/udev/keyboard-keys-list.txt: $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include linux/input.h - < /dev/null | $(AWK) '/^#define[ \t]+KEY_[^ ]+[ \t]+[0-9K]/ { if ($$2 != "KEY_MAX") { print $$2 } }' > $@ src/udev/keyboard-keys-from-name.gperf: src/udev/keyboard-keys-list.txt $(AM_V_GEN)$(AWK) 'BEGIN{ print "struct key { const char* name; unsigned short id; };"; print "%null-strings"; print "%%";} { print tolower(substr($$1 ,5)) ", " $$1 }' < $< > $@ src/udev/keyboard-keys-from-name.h: src/udev/keyboard-keys-from-name.gperf $(AM_V_GPERF)$(GPERF) -L ANSI-C -t -N keyboard_lookup_key -H hash_key_name -p -C < $< > $@ gperf_txt_sources += \ src/udev/keyboard-keys-list.txt libudev_core_la_SOURCES = \ src/udev/udev.h \ src/udev/udev-event.c \ src/udev/udev-watch.c \ src/udev/udev-node.c \ src/udev/udev-rules.c \ src/udev/udev-ctrl.c \ src/udev/udev-builtin.c \ src/udev/udev-builtin-btrfs.c \ src/udev/udev-builtin-hwdb.c \ src/udev/udev-builtin-input_id.c \ src/udev/udev-builtin-keyboard.c \ src/udev/udev-builtin-net_id.c \ src/udev/udev-builtin-net_setup_link.c \ src/udev/udev-builtin-path_id.c \ src/udev/udev-builtin-usb_id.c \ src/udev/net/link-config.h \ src/udev/net/link-config.c \ src/udev/net/ethtool-util.h \ src/udev/net/ethtool-util.c nodist_libudev_core_la_SOURCES = \ src/udev/keyboard-keys-from-name.h \ src/udev/net/link-config-gperf.c gperf_gperf_sources += \ src/udev/net/link-config-gperf.gperf libudev_core_la_CFLAGS = \ $(AM_CFLAGS) \ $(BLKID_CFLAGS) \ $(KMOD_CFLAGS) libudev_core_la_LIBADD = \ libsystemd-network.la \ libshared.la \ $(BLKID_LIBS) \ $(KMOD_LIBS) if HAVE_KMOD libudev_core_la_SOURCES += \ src/udev/udev-builtin-kmod.c dist_udevrules_DATA += \ rules/80-drivers.rules endif if HAVE_BLKID libudev_core_la_SOURCES += \ src/udev/udev-builtin-blkid.c endif if HAVE_ACL libudev_core_la_SOURCES += \ src/udev/udev-builtin-uaccess.c \ src/login/logind-acl.c \ src/libsystemd/sd-login/sd-login.c \ src/systemd/sd-login.h endif systemd_udevd_SOURCES = \ src/udev/udevd.c systemd_udevd_LDADD = \ libudev-core.la udevadm_SOURCES = \ src/udev/udevadm.c \ src/udev/udevadm-info.c \ src/udev/udevadm-control.c \ src/udev/udevadm-monitor.c \ src/udev/udevadm-hwdb.c \ src/udev/udevadm-settle.c \ src/udev/udevadm-trigger.c \ src/udev/udevadm-test.c \ src/udev/udevadm-test-builtin.c \ src/udev/udevadm-util.c \ src/udev/udevadm-util.h udevadm_LDADD = \ libudev-core.la # ------------------------------------------------------------------------------ if ENABLE_HWDB INSTALL_DIRS += \ $(sysconfdir)/udev/hwdb.d systemd_hwdb_SOURCES = \ src/libsystemd/sd-hwdb/hwdb-internal.h \ src/hwdb/hwdb.c systemd_hwdb_LDADD = \ libshared.la rootbin_PROGRAMS += \ systemd-hwdb dist_udevhwdb_DATA = \ hwdb/20-pci-vendor-model.hwdb \ hwdb/20-pci-classes.hwdb \ hwdb/20-usb-vendor-model.hwdb \ hwdb/20-usb-classes.hwdb \ hwdb/20-sdio-vendor-model.hwdb \ hwdb/20-sdio-classes.hwdb \ hwdb/20-bluetooth-vendor-product.hwdb \ hwdb/20-acpi-vendor.hwdb \ hwdb/20-OUI.hwdb \ hwdb/20-net-ifname.hwdb \ hwdb/60-evdev.hwdb \ hwdb/60-keyboard.hwdb \ hwdb/70-mouse.hwdb \ hwdb/70-pointingstick.hwdb SYSINIT_TARGET_WANTS += \ systemd-hwdb-update.service # Update hwdb on installation. Do not bother if installing # in DESTDIR, since this is likely for packaging purposes. hwdb-update-hook: -test -n "$(DESTDIR)" || $(rootbindir)/systemd-hwdb update INSTALL_DATA_HOOKS += \ hwdb-update-hook hwdb-remove-hook: -test -n "$(DESTDIR)" || rm -f /etc/udev/hwdb.bin endif EXTRA_DIST += \ units/systemd-hwdb-update.service.in \ hwdb/ids-update.pl \ hwdb/sdio.ids # ------------------------------------------------------------------------------ if ENABLE_TESTS TESTS += \ test/udev-test.pl if HAVE_PYTHON TESTS += \ test/rule-syntax-check.py if HAVE_SYSV_COMPAT TESTS += \ test/sysv-generator-test.py endif endif endif manual_tests += \ test-libudev \ test-udev test_libudev_SOURCES = \ src/test/test-libudev.c test_libudev_LDADD = \ libshared.la test_udev_SOURCES = \ src/test/test-udev.c test_udev_LDADD = \ libudev-core.la \ $(BLKID_LIBS) \ $(KMOD_LIBS) if ENABLE_TESTS check_DATA += \ test/sys endif # packed sysfs test tree test/sys: $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)tar -C test/ -xJf $(top_srcdir)/test/sys.tar.xz test-sys-distclean: -rm -rf test/sys DISTCLEAN_LOCAL_HOOKS += test-sys-distclean EXTRA_DIST += \ test/sys.tar.xz \ test/udev-test.pl \ test/rule-syntax-check.py \ test/sysv-generator-test.py \ test/mocks/fsck # ------------------------------------------------------------------------------ ata_id_SOURCES = \ src/udev/ata_id/ata_id.c ata_id_LDADD = \ libshared.la udevlibexec_PROGRAMS += \ ata_id # ------------------------------------------------------------------------------ cdrom_id_SOURCES = \ src/udev/cdrom_id/cdrom_id.c cdrom_id_LDADD = \ libshared.la udevlibexec_PROGRAMS += \ cdrom_id dist_udevrules_DATA += \ rules/60-cdrom_id.rules # ------------------------------------------------------------------------------ collect_SOURCES = \ src/udev/collect/collect.c collect_LDADD = \ libshared.la udevlibexec_PROGRAMS += \ collect # ------------------------------------------------------------------------------ scsi_id_SOURCES =\ src/udev/scsi_id/scsi_id.c \ src/udev/scsi_id/scsi_serial.c \ src/udev/scsi_id/scsi.h \ src/udev/scsi_id/scsi_id.h scsi_id_LDADD = \ libshared.la udevlibexec_PROGRAMS += \ scsi_id EXTRA_DIST += \ src/udev/scsi_id/README # ------------------------------------------------------------------------------ v4l_id_SOURCES = \ src/udev/v4l_id/v4l_id.c v4l_id_LDADD = \ libshared.la udevlibexec_PROGRAMS += \ v4l_id dist_udevrules_DATA += \ rules/60-persistent-v4l.rules # ------------------------------------------------------------------------------ mtd_probe_SOURCES = \ src/udev/mtd_probe/mtd_probe.c \ src/udev/mtd_probe/mtd_probe.h \ src/udev/mtd_probe/probe_smartmedia.c dist_udevrules_DATA += \ rules/75-probe_mtd.rules udevlibexec_PROGRAMS += \ mtd_probe # ------------------------------------------------------------------------------ test_id128_SOURCES = \ src/test/test-id128.c test_id128_LDADD = \ libshared.la tests += \ test-id128 # ------------------------------------------------------------------------------ rootlibexec_PROGRAMS += \ systemd-activate systemd_activate_SOURCES = \ src/activate/activate.c systemd_activate_LDADD = \ libshared.la # ------------------------------------------------------------------------------ systemd_journald_SOURCES = \ src/journal/journald.c \ src/journal/journald-server.h systemd_journald_LDADD = \ libjournal-core.la \ libshared.la systemd_cat_SOURCES = \ src/journal/cat.c systemd_cat_LDADD = \ libjournal-core.la if HAVE_MICROHTTPD rootlibexec_PROGRAMS += \ systemd-journal-remote systemd_journal_remote_SOURCES = \ src/journal-remote/journal-remote-parse.h \ src/journal-remote/journal-remote-parse.c \ src/journal-remote/journal-remote-write.h \ src/journal-remote/journal-remote-write.c \ src/journal-remote/journal-remote.h \ src/journal-remote/journal-remote.c systemd_journal_remote_LDADD = \ libjournal-core.la systemd_journal_remote_SOURCES += \ src/journal-remote/microhttpd-util.h \ src/journal-remote/microhttpd-util.c systemd_journal_remote_CFLAGS = \ $(AM_CFLAGS) \ $(MICROHTTPD_CFLAGS) systemd_journal_remote_LDADD += \ $(MICROHTTPD_LIBS) if ENABLE_TMPFILES dist_tmpfiles_DATA += \ tmpfiles.d/systemd-remote.conf endif if HAVE_GNUTLS systemd_journal_remote_LDADD += \ $(GNUTLS_LIBS) endif # systemd-journal-remote make sense mostly with full crypto stack dist_systemunit_DATA += \ units/systemd-journal-remote.socket nodist_systemunit_DATA += \ units/systemd-journal-remote.service journal-remote-install-hook: journal-install-hook -$(MKDIR_P) $(DESTDIR)/var/log/journal/remote -chown 0:0 $(DESTDIR)/var/log/journal/remote -chmod 755 $(DESTDIR)/var/log/journal/remote INSTALL_EXEC_HOOKS += journal-remote-install-hook nodist_pkgsysconf_DATA += \ src/journal-remote/journal-remote.conf EXTRA_DIST += \ units/systemd-journal-remote.service.in \ src/journal-remote/journal-remote.conf.in \ src/journal-remote/log-generator.py endif if HAVE_LIBCURL rootlibexec_PROGRAMS += \ systemd-journal-upload systemd_journal_upload_SOURCES = \ src/journal-remote/journal-upload.h \ src/journal-remote/journal-upload.c \ src/journal-remote/journal-upload-journal.c systemd_journal_upload_CFLAGS = \ $(AM_CFLAGS) \ $(LIBCURL_CFLAGS) systemd_journal_upload_LDADD = \ libshared.la \ $(LIBCURL_LIBS) nodist_systemunit_DATA += \ units/systemd-journal-upload.service nodist_pkgsysconf_DATA += \ src/journal-remote/journal-upload.conf endif EXTRA_DIST += \ units/systemd-journal-upload.service.in \ src/journal-remote/journal-upload.conf.in # using _CFLAGS = in the conditional below would suppress AM_CFLAGS journalctl_CFLAGS = \ $(AM_CFLAGS) journalctl_SOURCES = \ src/journal/journalctl.c journalctl_LDADD = \ libshared.la \ libudev-core.la if HAVE_QRENCODE journalctl_SOURCES += \ src/journal/journal-qrcode.c \ src/journal/journal-qrcode.h journalctl_CFLAGS += \ $(QRENCODE_CFLAGS) journalctl_LDADD += \ $(QRENCODE_LIBS) endif test_journal_SOURCES = \ src/journal/test-journal.c test_journal_LDADD = \ libjournal-core.la test_journal_send_SOURCES = \ src/journal/test-journal-send.c test_journal_send_LDADD = \ libjournal-core.la test_journal_syslog_SOURCES = \ src/journal/test-journal-syslog.c test_journal_syslog_LDADD = \ libjournal-core.la test_journal_match_SOURCES = \ src/journal/test-journal-match.c test_journal_match_LDADD = \ libjournal-core.la test_journal_enum_SOURCES = \ src/journal/test-journal-enum.c test_journal_enum_LDADD = \ libjournal-core.la test_journal_stream_SOURCES = \ src/journal/test-journal-stream.c test_journal_stream_LDADD = \ libjournal-core.la test_journal_flush_SOURCES = \ src/journal/test-journal-flush.c test_journal_flush_LDADD = \ libjournal-core.la test_journal_init_SOURCES = \ src/journal/test-journal-init.c test_journal_init_LDADD = \ libjournal-core.la test_journal_verify_SOURCES = \ src/journal/test-journal-verify.c test_journal_verify_LDADD = \ libjournal-core.la test_journal_interleaving_SOURCES = \ src/journal/test-journal-interleaving.c test_journal_interleaving_LDADD = \ libjournal-core.la test_mmap_cache_SOURCES = \ src/journal/test-mmap-cache.c test_mmap_cache_LDADD = \ libjournal-core.la test_catalog_SOURCES = \ src/journal/test-catalog.c test_catalog_CPPFLAGS = \ $(AM_CPPFLAGS) \ -DCATALOG_DIR=\"$(abs_top_srcdir)/catalog\" test_catalog_LDADD = \ libjournal-core.la test_compress_SOURCES = \ src/journal/test-compress.c test_compress_LDADD = \ libshared.la test_compress_benchmark_SOURCES = \ src/journal/test-compress-benchmark.c test_compress_benchmark_LDADD = \ libshared.la test_audit_type_SOURCES = \ src/journal/test-audit-type.c test_audit_type_LDADD = \ libjournal-core.la libjournal_core_la_SOURCES = \ src/journal/journald-kmsg.c \ src/journal/journald-kmsg.h \ src/journal/journald-syslog.c \ src/journal/journald-syslog.h \ src/journal/journald-stream.c \ src/journal/journald-stream.h \ src/journal/journald-server.c \ src/journal/journald-server.h \ src/journal/journald-console.c \ src/journal/journald-console.h \ src/journal/journald-wall.c \ src/journal/journald-wall.h \ src/journal/journald-native.c \ src/journal/journald-native.h \ src/journal/journald-audit.c \ src/journal/journald-audit.h \ src/journal/journald-rate-limit.c \ src/journal/journald-rate-limit.h \ src/journal/journal-internal.h nodist_libjournal_core_la_SOURCES = \ src/journal/journald-gperf.c libjournal_core_la_LIBADD = \ libshared.la noinst_LTLIBRARIES += \ libjournal-core.la journal-install-hook: -$(MKDIR_P) $(DESTDIR)/var/log/journal -chown 0:0 $(DESTDIR)/var/log/journal -chmod 755 $(DESTDIR)/var/log/journal -setfacl -nm g:adm:rx,d:g:adm:rx $(DESTDIR)/var/log/journal/ -setfacl -nm g:wheel:rx,d:g:wheel:rx $(DESTDIR)/var/log/journal/ journal-uninstall-hook: -rmdir $(DESTDIR)/var/log/journal/remote -rmdir $(DESTDIR)/var/log/journal/ INSTALL_EXEC_HOOKS += journal-install-hook UNINSTALL_EXEC_HOOKS += journal-uninstall-hook # ------------------------------------------------------------------------------ # Update catalog on installation. Do not bother if installing # in DESTDIR, since this is likely for packaging purposes. catalog-update-hook: -test -n "$(DESTDIR)" || $(rootbindir)/journalctl --update-catalog INSTALL_DATA_HOOKS += \ catalog-update-hook catalog-remove-hook: -test -n "$(DESTDIR)" || rm -f $(catalogstatedir)/database UNINSTALL_DATA_HOOKS += \ catalog-remove-hook manual_tests += \ test-journal-enum tests += \ test-journal \ test-journal-send \ test-journal-syslog \ test-journal-match \ test-journal-stream \ test-journal-init \ test-journal-verify \ test-journal-interleaving \ test-journal-flush \ test-mmap-cache \ test-catalog \ test-audit-type if HAVE_COMPRESSION tests += \ test-compress \ test-compress-benchmark endif pkginclude_HEADERS += \ src/systemd/sd-journal.h \ src/systemd/sd-messages.h \ src/systemd/_sd-common.h libsystemd_journal_internal_la_SOURCES = \ src/journal/sd-journal.c \ src/systemd/sd-journal.h \ src/systemd/_sd-common.h \ src/journal/journal-file.c \ src/journal/journal-file.h \ src/journal/journal-vacuum.c \ src/journal/journal-vacuum.h \ src/journal/journal-verify.c \ src/journal/journal-verify.h \ src/journal/lookup3.c \ src/journal/lookup3.h \ src/journal/journal-send.c \ src/journal/journal-def.h \ src/journal/compress.h \ src/journal/catalog.c \ src/journal/catalog.h \ src/journal/mmap-cache.c \ src/journal/mmap-cache.h \ src/journal/compress.c \ src/journal/audit-type.h \ src/journal/audit-type.c nodist_libsystemd_journal_internal_la_SOURCES = \ src/journal/audit_type-to-name.h gperf_txt_sources += \ src/journal/audit_type-list.txt # using _CFLAGS = in the conditional below would suppress AM_CFLAGS libsystemd_journal_internal_la_CFLAGS = \ $(AM_CFLAGS) libsystemd_journal_internal_la_LIBADD = if HAVE_XZ libsystemd_journal_internal_la_CFLAGS += \ $(XZ_CFLAGS) libsystemd_journal_internal_la_LIBADD += \ $(XZ_LIBS) endif if HAVE_LZ4 libsystemd_journal_internal_la_LIBADD += \ -llz4 endif if HAVE_GCRYPT libsystemd_journal_internal_la_SOURCES += \ src/journal/journal-authenticate.c \ src/journal/journal-authenticate.h \ src/journal/fsprg.c \ src/journal/fsprg.h libsystemd_journal_internal_la_LIBADD += \ $(GCRYPT_LIBS) # fsprg.c is a drop-in file using void pointer arithmetic libsystemd_journal_internal_la_CFLAGS += \ $(GCRYPT_CFLAGS) \ -Wno-pointer-arith endif noinst_LTLIBRARIES += \ libsystemd-journal-internal.la rootlibexec_PROGRAMS += \ systemd-journald rootbin_PROGRAMS += \ journalctl bin_PROGRAMS += \ systemd-cat dist_systemunit_DATA += \ units/systemd-journald.socket \ units/systemd-journald-dev-log.socket \ units/systemd-journald-audit.socket nodist_systemunit_DATA += \ units/systemd-journald.service \ units/systemd-journal-flush.service \ units/systemd-journal-catalog-update.service dist_pkgsysconf_DATA += \ src/journal/journald.conf dist_catalog_DATA = \ catalog/systemd.be.catalog \ catalog/systemd.be@latin.catalog \ catalog/systemd.fr.catalog \ catalog/systemd.it.catalog \ catalog/systemd.pl.catalog \ catalog/systemd.pt_BR.catalog \ catalog/systemd.ru.catalog \ catalog/systemd.zh_CN.catalog \ catalog/systemd.zh_TW.catalog \ catalog/systemd.catalog SOCKETS_TARGET_WANTS += \ systemd-journald.socket \ systemd-journald-dev-log.socket \ systemd-journald-audit.socket SYSINIT_TARGET_WANTS += \ systemd-journald.service \ systemd-journal-flush.service \ systemd-journal-catalog-update.service EXTRA_DIST += \ units/systemd-journald.service.in \ units/systemd-journal-flush.service.in \ units/systemd-journal-catalog-update.service.in gperf_gperf_sources += \ src/journal/journald-gperf.gperf # ------------------------------------------------------------------------------ if HAVE_MICROHTTPD gatewayddocumentrootdir=$(pkgdatadir)/gatewayd rootlibexec_PROGRAMS += \ systemd-journal-gatewayd systemd_journal_gatewayd_SOURCES = \ src/journal-remote/journal-gatewayd.c \ src/journal-remote/microhttpd-util.h \ src/journal-remote/microhttpd-util.c systemd_journal_gatewayd_LDADD = \ libshared.la \ $(MICROHTTPD_LIBS) if HAVE_GNUTLS systemd_journal_gatewayd_LDADD += \ $(GNUTLS_LIBS) endif systemd_journal_gatewayd_CFLAGS = \ $(AM_CFLAGS) \ $(MICROHTTPD_CFLAGS) systemd_journal_gatewayd_CPPFLAGS = \ $(AM_CPPFLAGS) \ -DDOCUMENT_ROOT=\"$(gatewayddocumentrootdir)\" dist_systemunit_DATA += \ units/systemd-journal-gatewayd.socket nodist_systemunit_DATA += \ units/systemd-journal-gatewayd.service dist_gatewayddocumentroot_DATA = \ src/journal-remote/browse.html endif EXTRA_DIST += \ units/systemd-journal-gatewayd.service.in # ------------------------------------------------------------------------------ systemd_socket_proxyd_SOURCES = \ src/socket-proxy/socket-proxyd.c systemd_socket_proxyd_LDADD = \ libshared.la # ------------------------------------------------------------------------------ if ENABLE_COREDUMP systemd_coredump_SOURCES = \ src/coredump/coredump.c \ src/coredump/coredump-vacuum.c \ src/coredump/coredump-vacuum.h systemd_coredump_LDADD = \ libshared.la if HAVE_ELFUTILS systemd_coredump_SOURCES += \ src/coredump/stacktrace.c \ src/coredump/stacktrace.h systemd_coredump_LDADD += \ $(ELFUTILS_LIBS) endif nodist_systemunit_DATA += \ units/systemd-coredump@.service dist_systemunit_DATA += \ units/systemd-coredump.socket SOCKETS_TARGET_WANTS += \ systemd-coredump.socket rootlibexec_PROGRAMS += \ systemd-coredump dist_pkgsysconf_DATA += \ src/coredump/coredump.conf coredumpctl_SOURCES = \ src/coredump/coredumpctl.c coredumpctl_LDADD = \ libshared.la bin_PROGRAMS += \ coredumpctl manual_tests += \ test-coredump-vacuum test_coredump_vacuum_SOURCES = \ src/coredump/test-coredump-vacuum.c \ src/coredump/coredump-vacuum.c \ src/coredump/coredump-vacuum.h test_coredump_vacuum_LDADD = \ libshared.la dist_bashcompletion_data += \ shell-completion/bash/coredumpctl dist_zshcompletion_data += \ shell-completion/zsh/_coredumpctl nodist_sysctl_DATA = \ sysctl.d/50-coredump.conf CLEANFILES += \ sysctl.d/50-coredump.conf endif EXTRA_DIST += \ sysctl.d/50-coredump.conf.in \ units/systemd-coredump@.service.in # ------------------------------------------------------------------------------ if ENABLE_BINFMT systemd_binfmt_SOURCES = \ src/binfmt/binfmt.c systemd_binfmt_LDADD = \ libshared.la rootlibexec_PROGRAMS += \ systemd-binfmt dist_systemunit_DATA += \ units/proc-sys-fs-binfmt_misc.automount \ units/proc-sys-fs-binfmt_misc.mount nodist_systemunit_DATA += \ units/systemd-binfmt.service INSTALL_DIRS += \ $(prefix)/lib/binfmt.d \ $(sysconfdir)/binfmt.d SYSINIT_TARGET_WANTS += \ systemd-binfmt.service \ proc-sys-fs-binfmt_misc.automount endif EXTRA_DIST += \ units/systemd-binfmt.service.in # ------------------------------------------------------------------------------ if ENABLE_VCONSOLE systemd_vconsole_setup_SOURCES = \ src/vconsole/vconsole-setup.c systemd_vconsole_setup_LDADD = \ libshared.la rootlibexec_PROGRAMS += \ systemd-vconsole-setup nodist_udevrules_DATA += \ src/vconsole/90-vconsole.rules nodist_systemunit_DATA += \ units/systemd-vconsole-setup.service SYSINIT_TARGET_WANTS += \ systemd-vconsole-setup.service endif EXTRA_DIST += \ src/vconsole/90-vconsole.rules.in \ units/systemd-vconsole-setup.service.in # ------------------------------------------------------------------------------ if ENABLE_BOOTCHART systemd_bootchart_SOURCES = \ src/bootchart/bootchart.c \ src/bootchart/bootchart.h \ src/bootchart/store.c \ src/bootchart/store.h \ src/bootchart/svg.c \ src/bootchart/svg.h systemd_bootchart_LDADD = \ libshared.la rootlibexec_PROGRAMS += \ systemd-bootchart dist_pkgsysconf_DATA += \ src/bootchart/bootchart.conf nodist_systemunit_DATA += \ units/systemd-bootchart.service endif EXTRA_DIST += \ units/systemd-bootchart.service.in # ------------------------------------------------------------------------------ if ENABLE_QUOTACHECK rootlibexec_PROGRAMS += \ systemd-quotacheck nodist_systemunit_DATA += \ units/systemd-quotacheck.service systemd_quotacheck_SOURCES = \ src/quotacheck/quotacheck.c systemd_quotacheck_LDADD = \ libshared.la endif EXTRA_DIST += \ units/systemd-quotacheck.service.in nodist_systemunit_DATA += \ units/quotaon.service # ------------------------------------------------------------------------------ if ENABLE_RANDOMSEED rootlibexec_PROGRAMS += \ systemd-random-seed nodist_systemunit_DATA += \ units/systemd-random-seed.service systemd_random_seed_SOURCES = \ src/random-seed/random-seed.c systemd_random_seed_LDADD = \ libshared.la SYSINIT_TARGET_WANTS += \ systemd-random-seed.service endif EXTRA_DIST += \ units/systemd-random-seed.service.in # ------------------------------------------------------------------------------ if ENABLE_BACKLIGHT rootlibexec_PROGRAMS += \ systemd-backlight nodist_systemunit_DATA += \ units/systemd-backlight@.service systemd_backlight_SOURCES = \ src/backlight/backlight.c systemd_backlight_LDADD = \ libshared.la endif EXTRA_DIST += \ units/systemd-backlight@.service.in # ------------------------------------------------------------------------------ if ENABLE_RFKILL rootlibexec_PROGRAMS += \ systemd-rfkill nodist_systemunit_DATA += \ units/systemd-rfkill.service dist_systemunit_DATA += \ units/systemd-rfkill.socket systemd_rfkill_SOURCES = \ src/rfkill/rfkill.c systemd_rfkill_LDADD = \ libshared.la endif EXTRA_DIST += \ units/systemd-rfkill.service.in # ------------------------------------------------------------------------------ if HAVE_LIBCRYPTSETUP rootlibexec_PROGRAMS += \ systemd-cryptsetup systemgenerator_PROGRAMS += \ systemd-cryptsetup-generator dist_systemunit_DATA += \ units/cryptsetup.target \ units/cryptsetup-pre.target systemd_cryptsetup_SOURCES = \ src/cryptsetup/cryptsetup.c systemd_cryptsetup_CFLAGS = \ $(AM_CFLAGS) \ $(LIBCRYPTSETUP_CFLAGS) systemd_cryptsetup_LDADD = \ libshared.la \ $(LIBCRYPTSETUP_LIBS) systemd_cryptsetup_generator_SOURCES = \ src/cryptsetup/cryptsetup-generator.c systemd_cryptsetup_generator_LDADD = \ libshared.la SYSINIT_TARGET_WANTS += \ cryptsetup.target endif # ------------------------------------------------------------------------------ if ENABLE_HOSTNAMED systemd_hostnamed_SOURCES = \ src/hostname/hostnamed.c systemd_hostnamed_LDADD = \ libshared.la rootlibexec_PROGRAMS += \ systemd-hostnamed nodist_systemunit_DATA += \ units/systemd-hostnamed.service dist_systemunit_DATA_busnames += \ units/org.freedesktop.hostname1.busname dist_dbuspolicy_DATA += \ src/hostname/org.freedesktop.hostname1.conf dist_dbussystemservice_DATA += \ src/hostname/org.freedesktop.hostname1.service polkitpolicy_files += \ src/hostname/org.freedesktop.hostname1.policy SYSTEM_UNIT_ALIASES += \ systemd-hostnamed.service dbus-org.freedesktop.hostname1.service BUSNAMES_TARGET_WANTS += \ org.freedesktop.hostname1.busname hostnamectl_SOURCES = \ src/hostname/hostnamectl.c hostnamectl_LDADD = \ libshared.la bin_PROGRAMS += \ hostnamectl dist_bashcompletion_data += \ shell-completion/bash/hostnamectl dist_zshcompletion_data += \ shell-completion/zsh/_hostnamectl endif polkitpolicy_in_files += \ src/hostname/org.freedesktop.hostname1.policy.in EXTRA_DIST += \ units/systemd-hostnamed.service.in # ------------------------------------------------------------------------------ dist_systemunit_DATA_busnames += \ units/org.freedesktop.systemd1.busname BUSNAMES_TARGET_WANTS += \ org.freedesktop.systemd1.busname # ------------------------------------------------------------------------------ if ENABLE_LOCALED systemd_localed_SOURCES = \ src/locale/localed.c systemd_localed_LDADD = \ libshared.la \ $(XKBCOMMON_LIBS) systemd_localed_CFLAGS = \ $(AM_CFLAGS) \ $(XKBCOMMON_CFLAGS) nodist_systemunit_DATA += \ units/systemd-localed.service dist_systemunit_DATA_busnames += \ units/org.freedesktop.locale1.busname rootlibexec_PROGRAMS += \ systemd-localed dist_dbuspolicy_DATA += \ src/locale/org.freedesktop.locale1.conf dist_dbussystemservice_DATA += \ src/locale/org.freedesktop.locale1.service polkitpolicy_files += \ src/locale/org.freedesktop.locale1.policy SYSTEM_UNIT_ALIASES += \ systemd-localed.service dbus-org.freedesktop.locale1.service BUSNAMES_TARGET_WANTS += \ org.freedesktop.locale1.busname dist_pkgdata_DATA = \ src/locale/kbd-model-map \ src/locale/language-fallback-map localectl_SOURCES = \ src/locale/localectl.c localectl_LDADD = \ libshared.la bin_PROGRAMS += \ localectl dist_bashcompletion_data += \ shell-completion/bash/localectl dist_zshcompletion_data += \ shell-completion/zsh/_localectl endif .PHONY: update-kbd-model-map polkitpolicy_in_files += \ src/locale/org.freedesktop.locale1.policy.in EXTRA_DIST += \ units/systemd-localed.service.in # ------------------------------------------------------------------------------ if ENABLE_TIMEDATED systemd_timedated_SOURCES = \ src/timedate/timedated.c systemd_timedated_LDADD = \ libshared.la rootlibexec_PROGRAMS += \ systemd-timedated dist_dbussystemservice_DATA += \ src/timedate/org.freedesktop.timedate1.service dist_dbuspolicy_DATA += \ src/timedate/org.freedesktop.timedate1.conf nodist_systemunit_DATA += \ units/systemd-timedated.service dist_systemunit_DATA_busnames += \ units/org.freedesktop.timedate1.busname polkitpolicy_files += \ src/timedate/org.freedesktop.timedate1.policy SYSTEM_UNIT_ALIASES += \ systemd-timedated.service dbus-org.freedesktop.timedate1.service BUSNAMES_TARGET_WANTS += \ org.freedesktop.timedate1.busname timedatectl_SOURCES = \ src/timedate/timedatectl.c timedatectl_LDADD = \ libshared.la bin_PROGRAMS += \ timedatectl dist_bashcompletion_data += \ shell-completion/bash/timedatectl dist_zshcompletion_data += \ shell-completion/zsh/_timedatectl endif polkitpolicy_in_files += \ src/timedate/org.freedesktop.timedate1.policy.in EXTRA_DIST += \ units/systemd-timedated.service.in # ------------------------------------------------------------------------------ if ENABLE_TIMESYNCD systemd_timesyncd_SOURCES = \ src/timesync/timesyncd.c \ src/timesync/timesyncd-manager.c \ src/timesync/timesyncd-manager.h \ src/timesync/timesyncd-conf.c \ src/timesync/timesyncd-conf.h \ src/timesync/timesyncd-server.c \ src/timesync/timesyncd-server.h nodist_systemd_timesyncd_SOURCES = \ src/timesync/timesyncd-gperf.c systemd_timesyncd_LDADD = \ libsystemd-network.la \ libshared.la rootlibexec_PROGRAMS += \ systemd-timesyncd nodist_systemunit_DATA += \ units/systemd-timesyncd.service GENERAL_ALIASES += \ $(systemunitdir)/systemd-timesyncd.service $(pkgsysconfdir)/system/sysinit.target.wants/systemd-timesyncd.service nodist_pkgsysconf_DATA += \ src/timesync/timesyncd.conf endif gperf_gperf_sources += \ src/timesync/timesyncd-gperf.gperf EXTRA_DIST += \ units/systemd-timesyncd.service.in \ src/timesync/timesyncd.conf.in # ------------------------------------------------------------------------------ if HAVE_MYHOSTNAME libnss_myhostname_la_SOURCES = \ src/nss-myhostname/nss-myhostname.sym \ src/nss-myhostname/nss-myhostname.c libnss_myhostname_la_LDFLAGS = \ $(AM_LDFLAGS) \ -module \ -export-dynamic \ -avoid-version \ -shared \ -shrext .so.2 \ -Wl,--version-script=$(top_srcdir)/src/nss-myhostname/nss-myhostname.sym libnss_myhostname_la_LIBADD = \ libsystemd-internal.la lib_LTLIBRARIES += \ libnss_myhostname.la endif # ------------------------------------------------------------------------------ if ENABLE_MACHINED systemd_machined_SOURCES = \ src/machine/machined.c \ src/machine/machined.h systemd_machined_LDADD = \ libmachine-core.la rootlibexec_PROGRAMS += \ systemd-machined libmachine_core_la_SOURCES = \ src/machine/machine.c \ src/machine/machine.h \ src/machine/machined-dbus.c \ src/machine/machine-dbus.c \ src/machine/machine-dbus.h \ src/machine/image-dbus.c \ src/machine/image-dbus.h libmachine_core_la_LIBADD = \ libshared.la noinst_LTLIBRARIES += \ libmachine-core.la machinectl_SOURCES = \ src/machine/machinectl.c machinectl_LDADD = \ libshared.la rootbin_PROGRAMS += \ machinectl test_machine_tables_SOURCES = \ src/machine/test-machine-tables.c test_machine_tables_LDADD = \ libmachine-core.la tests += \ test-machine-tables nodist_systemunit_DATA += \ units/systemd-machined.service dist_systemunit_DATA += \ units/machine.slice dist_systemunit_DATA_busnames += \ units/org.freedesktop.machine1.busname dist_dbussystemservice_DATA += \ src/machine/org.freedesktop.machine1.service dist_dbuspolicy_DATA += \ src/machine/org.freedesktop.machine1.conf polkitpolicy_files += \ src/machine/org.freedesktop.machine1.policy dist_bashcompletion_data += \ shell-completion/bash/machinectl dist_zshcompletion_data += \ shell-completion/zsh/_machinectl \ shell-completion/zsh/_sd_machines SYSTEM_UNIT_ALIASES += \ systemd-machined.service dbus-org.freedesktop.machine1.service BUSNAMES_TARGET_WANTS += \ org.freedesktop.machine1.busname libnss_mymachines_la_SOURCES = \ src/nss-mymachines/nss-mymachines.sym \ src/nss-mymachines/nss-mymachines.c libnss_mymachines_la_LDFLAGS = \ $(AM_LDFLAGS) \ -module \ -export-dynamic \ -avoid-version \ -shared \ -shrext .so.2 \ -Wl,--version-script=$(top_srcdir)/src/nss-mymachines/nss-mymachines.sym libnss_mymachines_la_LIBADD = \ libsystemd-internal.la lib_LTLIBRARIES += \ libnss_mymachines.la endif polkitpolicy_in_files += \ src/machine/org.freedesktop.machine1.policy.in EXTRA_DIST += \ units/systemd-machined.service.in # ------------------------------------------------------------------------------ if ENABLE_IMPORTD if HAVE_LIBCURL if HAVE_XZ if HAVE_ZLIB if HAVE_BZIP2 if HAVE_GCRYPT rootlibexec_PROGRAMS += \ systemd-importd \ systemd-pull \ systemd-import \ systemd-export systemd_importd_SOURCES = \ src/import/importd.c systemd_importd_CFLAGS = \ $(AM_CFLAGS) \ -D SYSTEMD_PULL_PATH=\"$(rootlibexecdir)/systemd-pull\" \ -D SYSTEMD_IMPORT_PATH=\"$(rootlibexecdir)/systemd-import\" \ -D SYSTEMD_EXPORT_PATH=\"$(rootlibexecdir)/systemd-export\" systemd_importd_LDADD = \ libshared.la systemd_pull_SOURCES = \ src/import/pull.c \ src/import/pull-raw.c \ src/import/pull-raw.h \ src/import/pull-tar.c \ src/import/pull-tar.h \ src/import/pull-job.c \ src/import/pull-job.h \ src/import/pull-common.c \ src/import/pull-common.h \ src/import/import-common.c \ src/import/import-common.h \ src/import/import-compress.c \ src/import/import-compress.h \ src/import/curl-util.c \ src/import/curl-util.h \ src/import/aufs-util.c \ src/import/aufs-util.h \ src/import/qcow2-util.c \ src/import/qcow2-util.h systemd_pull_CFLAGS = \ $(AM_CFLAGS) \ $(LIBCURL_CFLAGS) \ $(XZ_CFLAGS) \ $(ZLIB_CFLAGS) \ $(GCRYPT_CFLAGS) \ -D VENDOR_KEYRING_PATH=\"$(rootlibexecdir)/import-pubring.gpg\" \ -D USER_KEYRING_PATH=\"$(pkgsysconfdir)/import-pubring.gpg\" systemd_pull_LDADD = \ libshared.la \ $(LIBCURL_LIBS) \ $(XZ_LIBS) \ $(ZLIB_LIBS) \ -lbz2 \ $(GCRYPT_LIBS) systemd_import_SOURCES = \ src/import/import.c \ src/import/import-raw.c \ src/import/import-raw.h \ src/import/import-tar.c \ src/import/import-tar.h \ src/import/import-common.c \ src/import/import-common.h \ src/import/import-compress.c \ src/import/import-compress.h \ src/import/qcow2-util.c \ src/import/qcow2-util.h systemd_import_CFLAGS = \ $(AM_CFLAGS) \ $(XZ_CFLAGS) \ $(ZLIB_CFLAGS) systemd_import_LDADD = \ libshared.la \ $(XZ_LIBS) \ $(ZLIB_LIBS) \ -lbz2 systemd_export_SOURCES = \ src/import/export.c \ src/import/export-tar.c \ src/import/export-tar.h \ src/import/export-raw.c \ src/import/export-raw.h \ src/import/import-common.c \ src/import/import-common.h \ src/import/import-compress.c \ src/import/import-compress.h systemd_export_CFLAGS = \ $(AM_CFLAGS) \ $(XZ_CFLAGS) \ $(ZLIB_CFLAGS) systemd_export_LDADD = \ libshared.la \ $(XZ_LIBS) \ $(ZLIB_LIBS) \ -lbz2 dist_rootlibexec_DATA = \ src/import/import-pubring.gpg nodist_systemunit_DATA += \ units/systemd-importd.service dist_systemunit_DATA_busnames += \ units/org.freedesktop.import1.busname BUSNAMES_TARGET_WANTS += \ org.freedesktop.import1.busname SYSTEM_UNIT_ALIASES += \ systemd-importd.service dbus-org.freedesktop.import1.service dist_dbussystemservice_DATA += \ src/import/org.freedesktop.import1.service dist_dbuspolicy_DATA += \ src/import/org.freedesktop.import1.conf polkitpolicy_files += \ src/import/org.freedesktop.import1.policy manual_tests += \ test-qcow2 test_qcow2_SOURCES = \ src/import/test-qcow2.c \ src/import/qcow2-util.c \ src/import/qcow2-util.h test_qcow2_CFLAGS = \ $(AM_CFLAGS) \ $(ZLIB_CFLAGS) test_qcow2_LDADD = \ libshared.la \ $(ZLIB_LIBS) endif endif endif endif endif endif polkitpolicy_in_files += \ src/import/org.freedesktop.import1.policy.in EXTRA_DIST += \ units/systemd-importd.service.in # ------------------------------------------------------------------------------ if ENABLE_RESOLVED systemd_resolved_SOURCES = \ src/resolve/resolved.c \ src/resolve/resolved-manager.c \ src/resolve/resolved-manager.h \ src/resolve/resolved-conf.c \ src/resolve/resolved-conf.h \ src/resolve/resolved-resolv-conf.c \ src/resolve/resolved-resolv-conf.h \ src/resolve/resolved-bus.c \ src/resolve/resolved-bus.h \ src/resolve/resolved-link.h \ src/resolve/resolved-link.c \ src/resolve/resolved-link-bus.c \ src/resolve/resolved-link-bus.h \ src/resolve/resolved-llmnr.h \ src/resolve/resolved-llmnr.c \ src/resolve/resolved-mdns.h \ src/resolve/resolved-mdns.c \ src/resolve/resolved-def.h \ src/resolve/resolved-dns-rr.h \ src/resolve/resolved-dns-rr.c \ src/resolve/resolved-dns-question.h \ src/resolve/resolved-dns-question.c \ src/resolve/resolved-dns-answer.h \ src/resolve/resolved-dns-answer.c \ src/resolve/resolved-dns-packet.h \ src/resolve/resolved-dns-packet.c \ src/resolve/resolved-dns-query.h \ src/resolve/resolved-dns-query.c \ src/resolve/resolved-dns-synthesize.h \ src/resolve/resolved-dns-synthesize.c \ src/resolve/resolved-dns-transaction.h \ src/resolve/resolved-dns-transaction.c \ src/resolve/resolved-dns-scope.h \ src/resolve/resolved-dns-scope.c \ src/resolve/resolved-dns-server.h \ src/resolve/resolved-dns-server.c \ src/resolve/resolved-dns-search-domain.h \ src/resolve/resolved-dns-search-domain.c \ src/resolve/resolved-dns-cache.h \ src/resolve/resolved-dns-cache.c \ src/resolve/resolved-dns-zone.h \ src/resolve/resolved-dns-zone.c \ src/resolve/resolved-dns-stream.h \ src/resolve/resolved-dns-stream.c \ src/resolve/resolved-dns-dnssec.h \ src/resolve/resolved-dns-dnssec.c \ src/resolve/resolved-dns-trust-anchor.h \ src/resolve/resolved-dns-trust-anchor.c \ src/resolve/resolved-etc-hosts.h \ src/resolve/resolved-etc-hosts.c \ src/resolve/dns-type.c \ src/resolve/dns-type.h nodist_systemd_resolved_SOURCES = \ src/resolve/dns_type-from-name.h \ src/resolve/dns_type-to-name.h \ src/resolve/resolved-gperf.c systemd_resolved_LDADD = \ libsystemd-network.la \ libshared.la rootlibexec_PROGRAMS += \ systemd-resolved nodist_systemunit_DATA += \ units/systemd-resolved.service dist_systemunit_DATA_busnames += \ units/org.freedesktop.resolve1.busname dist_dbuspolicy_DATA += \ src/resolve/org.freedesktop.resolve1.conf dist_dbussystemservice_DATA += \ src/resolve/org.freedesktop.resolve1.service SYSTEM_UNIT_ALIASES += \ systemd-resolved.service dbus-org.freedesktop.resolve1.service BUSNAMES_TARGET_WANTS += \ org.freedesktop.resolve1.busname GENERAL_ALIASES += \ $(systemunitdir)/systemd-resolved.service $(pkgsysconfdir)/system/multi-user.target.wants/systemd-resolved.service nodist_pkgsysconf_DATA += \ src/resolve/resolved.conf libnss_resolve_la_SOURCES = \ src/nss-resolve/nss-resolve.sym \ src/nss-resolve/nss-resolve.c libnss_resolve_la_LDFLAGS = \ $(AM_LDFLAGS) \ -module \ -export-dynamic \ -avoid-version \ -shared \ -shrext .so.2 \ -Wl,--version-script=$(top_srcdir)/src/nss-resolve/nss-resolve.sym libnss_resolve_la_LIBADD = \ libsystemd-internal.la \ -ldl lib_LTLIBRARIES += \ libnss_resolve.la systemd_resolve_SOURCES = \ src/resolve/resolve-tool.c \ src/resolve/resolved-dns-dnssec.c \ src/resolve/resolved-dns-dnssec.h \ src/resolve/resolved-dns-packet.c \ src/resolve/resolved-dns-packet.h \ src/resolve/resolved-dns-rr.c \ src/resolve/resolved-dns-rr.h \ src/resolve/resolved-dns-answer.c \ src/resolve/resolved-dns-answer.h \ src/resolve/resolved-dns-question.c \ src/resolve/resolved-dns-question.h \ src/resolve/dns-type.c \ src/resolve/dns-type.h nodist_systemd_resolve_SOURCES = \ src/resolve/dns_type-from-name.h \ src/resolve/dns_type-to-name.h systemd_resolve_LDADD = \ libshared.la bin_PROGRAMS += \ systemd-resolve tests += \ test-dns-domain \ test-dnssec manual_tests += \ test-dnssec-complex test_dnssec_SOURCES = \ src/resolve/test-dnssec.c \ src/resolve/resolved-dns-packet.c \ src/resolve/resolved-dns-packet.h \ src/resolve/resolved-dns-rr.c \ src/resolve/resolved-dns-rr.h \ src/resolve/resolved-dns-answer.c \ src/resolve/resolved-dns-answer.h \ src/resolve/resolved-dns-question.c \ src/resolve/resolved-dns-question.h \ src/resolve/resolved-dns-dnssec.c \ src/resolve/resolved-dns-dnssec.h \ src/resolve/dns-type.c \ src/resolve/dns-type.h test_dnssec_LDADD = \ libshared.la test_dnssec_complex_SOURCES = \ src/resolve/test-dnssec-complex.c \ src/resolve/dns-type.c \ src/resolve/dns-type.h test_dnssec_complex_LDADD = \ libshared.la endif gperf_txt_sources += \ src/resolve/dns_type-list.txt gperf_gperf_sources += \ src/resolve/resolved-gperf.gperf EXTRA_DIST += \ units/systemd-resolved.service.m4.in \ src/resolve/resolved.conf.in # ------------------------------------------------------------------------------ if ENABLE_NETWORKD rootlibexec_PROGRAMS += \ systemd-networkd systemd_networkd_SOURCES = \ src/network/networkd.c systemd_networkd_LDADD = \ libnetworkd-core.la if HAVE_LIBIPTC systemd_networkd_LDADD += \ libfirewall.la endif noinst_LTLIBRARIES += \ libnetworkd-core.la libnetworkd_core_la_CFLAGS = \ $(AM_CFLAGS) libnetworkd_core_la_SOURCES = \ src/libsystemd-network/network-internal.h \ src/network/networkd.h \ src/network/networkd-link.h \ src/network/networkd-link.c \ src/network/networkd-netdev.h \ src/network/networkd-netdev.c \ src/network/networkd-netdev-tunnel.h \ src/network/networkd-netdev-tunnel.c \ src/network/networkd-netdev-veth.h \ src/network/networkd-netdev-veth.c \ src/network/networkd-netdev-vxlan.h \ src/network/networkd-netdev-vxlan.c \ src/network/networkd-netdev-vlan.h \ src/network/networkd-netdev-vlan.c \ src/network/networkd-netdev-macvlan.h \ src/network/networkd-netdev-macvlan.c \ src/network/networkd-netdev-ipvlan.h \ src/network/networkd-netdev-ipvlan.c \ src/network/networkd-netdev-dummy.h \ src/network/networkd-netdev-dummy.c \ src/network/networkd-netdev-tuntap.h \ src/network/networkd-netdev-tuntap.c \ src/network/networkd-netdev-bond.h \ src/network/networkd-netdev-bond.c \ src/network/networkd-netdev-bridge.h \ src/network/networkd-netdev-bridge.c \ src/network/networkd-link-bus.c \ src/network/networkd-ipv4ll.c \ src/network/networkd-dhcp4.c \ src/network/networkd-dhcp6.c \ src/network/networkd-ndisc.c \ src/network/networkd-network.h \ src/network/networkd-network.c \ src/network/networkd-network-bus.c \ src/network/networkd-address.h \ src/network/networkd-address.c \ src/network/networkd-route.h \ src/network/networkd-route.c \ src/network/networkd-manager.c \ src/network/networkd-manager-bus.c \ src/network/networkd-fdb.h \ src/network/networkd-fdb.c \ src/network/networkd-address-pool.h \ src/network/networkd-address-pool.c \ src/network/networkd-util.h \ src/network/networkd-util.c nodist_libnetworkd_core_la_SOURCES = \ src/network/networkd-network-gperf.c \ src/network/networkd-netdev-gperf.c libnetworkd_core_la_LIBADD = \ libsystemd-network.la \ libshared.la rootlibexec_PROGRAMS += \ systemd-networkd-wait-online systemd_networkd_wait_online_CFLAGS = \ $(AM_CFLAGS) systemd_networkd_wait_online_SOURCES = \ src/libsystemd-network/network-internal.h \ src/network/networkd-wait-online.h \ src/network/networkd-wait-online-link.h \ src/network/networkd-wait-online.c \ src/network/networkd-wait-online-manager.c \ src/network/networkd-wait-online-link.c systemd_networkd_wait_online_LDADD = \ libsystemd-network.la \ libshared.la rootbin_PROGRAMS += \ networkctl networkctl_SOURCES = \ src/network/networkctl.c networkctl_LDADD = \ libshared.la \ libsystemd-network.la dist_bashcompletion_data += \ shell-completion/bash/networkctl test_network_SOURCES = \ src/network/test-network.c test_network_LDADD = \ libnetworkd-core.la if HAVE_LIBIPTC test_network_LDADD += \ libfirewall.la endif test_network_tables_SOURCES = \ src/network/test-network-tables.c \ src/shared/test-tables.h test_network_tables_LDADD = \ libnetworkd-core.la \ libudev-core.la if HAVE_LIBIPTC test_network_tables_LDADD += \ libfirewall.la endif tests += \ test-network \ test-network-tables dist_systemunit_DATA += \ units/systemd-networkd.socket nodist_systemunit_DATA += \ units/systemd-networkd.service \ units/systemd-networkd-wait-online.service dist_systemunit_DATA_busnames += \ units/org.freedesktop.network1.busname dist_dbussystemservice_DATA += \ src/network/org.freedesktop.network1.service dist_dbuspolicy_DATA += \ src/network/org.freedesktop.network1.conf GENERAL_ALIASES += \ $(systemunitdir)/systemd-networkd.socket $(pkgsysconfdir)/system/sockets.target.wants/systemd-networkd.socket \ $(systemunitdir)/systemd-networkd.service $(pkgsysconfdir)/system/multi-user.target.wants/systemd-networkd.service \ $(systemunitdir)/systemd-networkd-wait-online.service $(pkgsysconfdir)/system/network-online.target.wants/systemd-networkd-wait-online.service SYSTEM_UNIT_ALIASES += \ systemd-networkd.service dbus-org.freedesktop.network1.service BUSNAMES_TARGET_WANTS += \ org.freedesktop.network1.busname endif gperf_gperf_sources += \ src/network/networkd-network-gperf.gperf \ src/network/networkd-netdev-gperf.gperf EXTRA_DIST += \ units/systemd-networkd.service.m4.in \ units/systemd-networkd-wait-online.service.in \ test/networkd-test.py # ------------------------------------------------------------------------------ if ENABLE_LOGIND systemd_logind_SOURCES = \ src/login/logind.c \ src/login/logind.h nodist_systemd_logind_SOURCES = \ src/login/logind-gperf.c systemd_logind_LDADD = \ liblogind-core.la liblogind_core_la_SOURCES = \ src/login/logind-core.c \ src/login/logind-device.c \ src/login/logind-device.h \ src/login/logind-button.c \ src/login/logind-button.h \ src/login/logind-action.c \ src/login/logind-action.h \ src/login/logind-seat.c \ src/login/logind-seat.h \ src/login/logind-session.c \ src/login/logind-session.h \ src/login/logind-session-device.c \ src/login/logind-session-device.h \ src/login/logind-user.c \ src/login/logind-user.h \ src/login/logind-inhibit.c \ src/login/logind-inhibit.h \ src/login/logind-dbus.c \ src/login/logind-session-dbus.c \ src/login/logind-seat-dbus.c \ src/login/logind-user-dbus.c \ src/login/logind-utmp.c \ src/login/logind-acl.h liblogind_core_la_LIBADD = \ libshared.la if HAVE_ACL liblogind_core_la_SOURCES += \ src/login/logind-acl.c endif noinst_LTLIBRARIES += \ liblogind-core.la rootlibexec_PROGRAMS += \ systemd-logind loginctl_SOURCES = \ src/login/loginctl.c \ src/login/sysfs-show.h \ src/login/sysfs-show.c loginctl_LDADD = \ libshared.la rootbin_PROGRAMS += \ loginctl dist_bashcompletion_data += \ shell-completion/bash/loginctl dist_zshcompletion_data += \ shell-completion/zsh/_loginctl \ shell-completion/zsh/_systemd-inhibit systemd_inhibit_SOURCES = \ src/login/inhibit.c systemd_inhibit_LDADD = \ libshared.la rootbin_PROGRAMS += \ systemd-inhibit test_login_SOURCES = \ src/libsystemd/sd-login/test-login.c test_login_LDADD = \ libshared.la test_login_shared_SOURCES = \ src/login/test-login-shared.c test_login_shared_LDADD = \ libshared.la test_inhibit_SOURCES = \ src/login/test-inhibit.c test_inhibit_LDADD = \ libshared.la test_login_tables_SOURCES = \ src/login/test-login-tables.c test_login_tables_LDADD = \ liblogind-core.la manual_tests += \ test-login \ test-inhibit tests += \ test-login-tables \ test-login-shared if HAVE_PAM pam_systemd_la_SOURCES = \ src/login/pam_systemd.sym \ src/login/pam_systemd.c pam_systemd_la_CFLAGS = \ $(AM_CFLAGS) \ $(PAM_CFLAGS) pam_systemd_la_LDFLAGS = \ $(AM_LDFLAGS) \ -module \ -export-dynamic \ -avoid-version \ -shared \ -Wl,--version-script=$(top_srcdir)/src/login/pam_systemd.sym pam_systemd_la_LIBADD = \ libshared.la \ $(PAM_LIBS) pamlib_LTLIBRARIES = \ pam_systemd.la dist_pamconf_DATA = \ src/login/systemd-user EXTRA_DIST += \ src/login/systemd-user.m4 endif nodist_systemunit_DATA += \ units/systemd-logind.service dist_systemunit_DATA += \ units/user.slice dist_systemunit_DATA_busnames += \ units/org.freedesktop.login1.busname dist_dbussystemservice_DATA += \ src/login/org.freedesktop.login1.service dist_dbuspolicy_DATA += \ src/login/org.freedesktop.login1.conf dist_pkgsysconf_DATA += \ src/login/logind.conf polkitpolicy_files += \ src/login/org.freedesktop.login1.policy INSTALL_DIRS += \ $(systemdstatedir) MULTI_USER_TARGET_WANTS += \ systemd-logind.service SYSTEM_UNIT_ALIASES += \ systemd-logind.service dbus-org.freedesktop.login1.service BUSNAMES_TARGET_WANTS += \ org.freedesktop.login1.busname dist_udevrules_DATA += \ src/login/70-uaccess.rules \ src/login/70-power-switch.rules nodist_udevrules_DATA += \ src/login/71-seat.rules \ src/login/73-seat-late.rules endif polkitpolicy_in_files += \ src/login/org.freedesktop.login1.policy.in gperf_gperf_sources += \ src/login/logind-gperf.gperf EXTRA_DIST += \ src/login/71-seat.rules.in \ src/login/73-seat-late.rules.in \ units/systemd-logind.service.in # ------------------------------------------------------------------------------ if HAVE_PAM systemd_user_sessions_SOURCES = \ src/user-sessions/user-sessions.c systemd_user_sessions_LDADD = \ libshared.la rootlibexec_PROGRAMS += \ systemd-user-sessions nodist_systemunit_DATA += \ units/systemd-user-sessions.service MULTI_USER_TARGET_WANTS += \ systemd-user-sessions.service endif EXTRA_DIST += \ units/systemd-user-sessions.service.in # ------------------------------------------------------------------------------ EXTRA_DIST += \ test/Makefile \ test/README.testsuite \ test/TEST-01-BASIC \ test/TEST-01-BASIC/Makefile \ test/TEST-01-BASIC/test.sh \ test/TEST-02-CRYPTSETUP \ test/TEST-02-CRYPTSETUP/Makefile \ test/TEST-02-CRYPTSETUP/test.sh \ test/TEST-03-JOBS \ test/TEST-03-JOBS/Makefile \ test/TEST-03-JOBS/test-jobs.sh \ test/TEST-03-JOBS/test.sh \ test/TEST-04-JOURNAL/Makefile \ test/TEST-04-JOURNAL/test-journal.sh \ test/TEST-04-JOURNAL/test.sh \ test/TEST-05-RLIMITS/Makefile \ test/TEST-05-RLIMITS/test-rlimits.sh \ test/TEST-05-RLIMITS/test.sh \ test/TEST-06-SELINUX/Makefile \ test/TEST-06-SELINUX/test-selinux-checks.sh \ test/TEST-06-SELINUX/test.sh \ test/TEST-06-SELINUX/systemd_test.te \ test/TEST-06-SELINUX/systemd_test.if \ test/TEST-07-ISSUE-1981/Makefile \ test/TEST-07-ISSUE-1981/test-segfault.sh \ test/TEST-07-ISSUE-1981/test.sh \ test/test-functions EXTRA_DIST += \ test/loopy2.service \ test/loopy3.service \ test/loopy4.service \ test/loopy.service \ test/loopy.service.d \ test/loopy.service.d/compat.conf # ------------------------------------------------------------------------------ if ENABLE_COMPAT_LIBS libsystemd-%.c: src/compat-libs/libsystemd-%.sym $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GEN)sed -r -n 's/^ +(sd_.*);/obsolete_lib(\1,$(notdir $(basename $<)));/p' <$< >$@ BUILT_SOURCES += \ libsystemd-journal.c \ libsystemd-login.c \ libsystemd-id128.c \ libsystemd-daemon.c nodist_libsystemd_journal_la_SOURCES = \ libsystemd-journal.c libsystemd_journal_la_SOURCES = \ src/compat-libs/libsystemd-journal.sym libsystemd_journal_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -imacros$(top_srcdir)/src/compat-libs/linkwarning.h libsystemd_journal_la_LDFLAGS = \ $(AM_LDFLAGS) \ -version-info $(LIBSYSTEMD_JOURNAL_CURRENT):$(LIBSYSTEMD_JOURNAL_REVISION):$(LIBSYSTEMD_JOURNAL_AGE) \ -Wl,--version-script=$(top_srcdir)/src/compat-libs/libsystemd-journal.sym libsystemd_journal_la_LIBADD = \ libsystemd-journal-internal.la \ libsystemd-internal.la nodist_libsystemd_login_la_SOURCES = \ libsystemd-login.c libsystemd_login_la_SOURCES = \ src/compat-libs/libsystemd-login.sym libsystemd_login_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -imacros$(top_srcdir)/src/compat-libs/linkwarning.h libsystemd_login_la_LDFLAGS = \ $(AM_LDFLAGS) \ -version-info $(LIBSYSTEMD_LOGIN_CURRENT):$(LIBSYSTEMD_LOGIN_REVISION):$(LIBSYSTEMD_LOGIN_AGE) \ -Wl,--version-script=$(top_srcdir)/src/compat-libs/libsystemd-login.sym libsystemd_login_la_LIBADD = \ libsystemd-internal.la nodist_libsystemd_id128_la_SOURCES = \ libsystemd-id128.c libsystemd_id128_la_SOURCES = \ src/compat-libs/libsystemd-id128.sym libsystemd_id128_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -imacros$(top_srcdir)/src/compat-libs/linkwarning.h libsystemd_id128_la_LDFLAGS = \ $(AM_LDFLAGS) \ -version-info $(LIBSYSTEMD_ID128_CURRENT):$(LIBSYSTEMD_ID128_REVISION):$(LIBSYSTEMD_ID128_AGE) \ -Wl,--version-script=$(top_srcdir)/src/compat-libs/libsystemd-id128.sym libsystemd_id128_la_LIBADD = \ libsystemd-internal.la nodist_libsystemd_daemon_la_SOURCES = \ libsystemd-daemon.c libsystemd_daemon_la_SOURCES = \ src/compat-libs/libsystemd-daemon.sym libsystemd_daemon_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -imacros$(top_srcdir)/src/compat-libs/linkwarning.h libsystemd_daemon_la_LDFLAGS = \ $(AM_LDFLAGS) \ -version-info $(LIBSYSTEMD_DAEMON_CURRENT):$(LIBSYSTEMD_DAEMON_REVISION):$(LIBSYSTEMD_DAEMON_AGE) \ -Wl,--version-script=$(top_srcdir)/src/compat-libs/libsystemd-daemon.sym libsystemd_daemon_la_LIBADD = \ libsystemd-internal.la lib_LTLIBRARIES += \ libsystemd-journal.la \ libsystemd-login.la \ libsystemd-id128.la \ libsystemd-daemon.la pkgconfiglib_DATA += \ src/compat-libs/libsystemd-journal.pc \ src/compat-libs/libsystemd-login.pc \ src/compat-libs/libsystemd-id128.pc \ src/compat-libs/libsystemd-daemon.pc # move lib from $(libdir) to $(rootlibdir) and update devel link, if needed compat-lib-install-hook: libname=libsystemd-login.so && $(move-to-rootlibdir) libname=libsystemd-journal.so && $(move-to-rootlibdir) libname=libsystemd-id128.so && $(move-to-rootlibdir) libname=libsystemd-daemon.so && $(move-to-rootlibdir) compat-lib-uninstall-hook: rm -f $(DESTDIR)$(rootlibdir)/libsystemd-login.so* rm -f $(DESTDIR)$(rootlibdir)/libsystemd-journal.so* rm -f $(DESTDIR)$(rootlibdir)/libsystemd-id128.so* rm -f $(DESTDIR)$(rootlibdir)/libsystemd-daemon.so* INSTALL_EXEC_HOOKS += compat-lib-install-hook UNINSTALL_EXEC_HOOKS += compat-lib-uninstall-hook endif EXTRA_DIST += \ src/compat-libs/linkwarning.h \ src/compat-libs/libsystemd-journal.pc.in \ src/compat-libs/libsystemd-login.pc.in \ src/compat-libs/libsystemd-id128.pc.in \ src/compat-libs/libsystemd-daemon.pc.in # ------------------------------------------------------------------------------ substitutions = \ '|rootlibexecdir=$(rootlibexecdir)|' \ '|rootbindir=$(rootbindir)|' \ '|bindir=$(bindir)|' \ '|SYSTEMCTL=$(rootbindir)/systemctl|' \ '|SYSTEMD_NOTIFY=$(rootbindir)/systemd-notify|' \ '|pkgsysconfdir=$(pkgsysconfdir)|' \ '|SYSTEM_CONFIG_UNIT_PATH=$(pkgsysconfdir)/system|' \ '|USER_CONFIG_UNIT_PATH=$(pkgsysconfdir)/user|' \ '|pkgdatadir=$(pkgdatadir)|' \ '|systemunitdir=$(systemunitdir)|' \ '|userunitdir=$(userunitdir)|' \ '|systempresetdir=$(systempresetdir)|' \ '|userpresetdir=$(userpresetdir)|' \ '|udevhwdbdir=$(udevhwdbdir)|' \ '|udevrulesdir=$(udevrulesdir)|' \ '|catalogdir=$(catalogdir)|' \ '|tmpfilesdir=$(tmpfilesdir)|' \ '|sysusersdir=$(sysusersdir)|' \ '|sysctldir=$(sysctldir)|' \ '|systemgeneratordir=$(systemgeneratordir)|' \ '|usergeneratordir=$(usergeneratordir)|' \ '|CERTIFICATEROOT=$(CERTIFICATEROOT)|' \ '|PACKAGE_VERSION=$(PACKAGE_VERSION)|' \ '|PACKAGE_NAME=$(PACKAGE_NAME)|' \ '|PACKAGE_URL=$(PACKAGE_URL)|' \ '|RANDOM_SEED_DIR=$(localstatedir)/lib/systemd/|' \ '|RANDOM_SEED=$(localstatedir)/lib/systemd/random-seed|' \ '|prefix=$(prefix)|' \ '|exec_prefix=$(exec_prefix)|' \ '|libdir=$(libdir)|' \ '|includedir=$(includedir)|' \ '|VERSION=$(VERSION)|' \ '|rootprefix=$(rootprefix)|' \ '|udevlibexecdir=$(udevlibexecdir)|' \ '|SUSHELL=$(SUSHELL)|' \ '|SULOGIN=$(SULOGIN)|' \ '|DEBUGTTY=$(DEBUGTTY)|' \ '|KILL=$(KILL)|' \ '|KMOD=$(KMOD)|' \ '|MOUNT_PATH=$(MOUNT_PATH)|' \ '|UMOUNT_PATH=$(UMOUNT_PATH)|' \ '|MKDIR_P=$(MKDIR_P)|' \ '|QUOTAON=$(QUOTAON)|' \ '|QUOTACHECK=$(QUOTACHECK)|' \ '|SYSTEM_SYSVINIT_PATH=$(sysvinitdir)|' \ '|VARLOGDIR=$(varlogdir)|' \ '|RC_LOCAL_SCRIPT_PATH_START=$(RC_LOCAL_SCRIPT_PATH_START)|' \ '|RC_LOCAL_SCRIPT_PATH_STOP=$(RC_LOCAL_SCRIPT_PATH_STOP)|' \ '|PYTHON=$(PYTHON)|' \ '|NTP_SERVERS=$(NTP_SERVERS)|' \ '|DNS_SERVERS=$(DNS_SERVERS)|' \ '|systemuidmax=$(SYSTEM_UID_MAX)|' \ '|systemgidmax=$(SYSTEM_GID_MAX)|' \ '|TTY_GID=$(TTY_GID)|' \ '|systemsleepdir=$(systemsleepdir)|' \ '|systemshutdowndir=$(systemshutdowndir)|' \ '|binfmtdir=$(binfmtdir)|' \ '|modulesloaddir=$(modulesloaddir)|' SED_PROCESS = \ $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \ $(SED) $(subst '|,-e 's|@,$(subst =,\@|,$(subst |',|g',$(substitutions)))) \ < $< > $@ units/%: units/%.in $(SED_PROCESS) man/%: man/%.in $(SED_PROCESS) sysctl.d/%: sysctl.d/%.in $(SED_PROCESS) %.pc: %.pc.in $(SED_PROCESS) %.conf: %.conf.in $(SED_PROCESS) src/core/%.systemd: src/core/%.systemd.in $(SED_PROCESS) src/%.policy.in: src/%.policy.in.in $(SED_PROCESS) shell-completion/%: shell-completion/%.in $(SED_PROCESS) %.rules: %.rules.in $(SED_PROCESS) %.conf: %.conf.in $(SED_PROCESS) %.sh: %.sh.in $(SED_PROCESS) $(AM_V_GEN)chmod +x $@ src/%.c: src/%.gperf $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_GPERF)$(GPERF) < $< > $@ src/%: src/%.m4 $(top_builddir)/config.status $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_M4)$(M4) -P $(M4_DEFINES) < $< > $@ sysusers.d/%: sysusers.d/%.m4 $(top_builddir)/config.status $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_M4)$(M4) -P $(M4_DEFINES) < $< > $@ tmpfiles.d/%: tmpfiles.d/%.m4 $(top_builddir)/config.status $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_M4)$(M4) -P $(M4_DEFINES) < $< > $@ units/%: units/%.m4 $(top_builddir)/config.status $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_M4)$(M4) -P $(M4_DEFINES) -DFOR_SYSTEM=1 < $< > $@ units/user/%: units/user/%.m4 $(top_builddir)/config.status $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_M4)$(M4) -P $(M4_DEFINES) -DFOR_USER=1 < $< > $@ if ENABLE_POLKIT nodist_polkitpolicy_DATA = \ $(polkitpolicy_files) \ $(polkitpolicy_in_in_files:.policy.in.in=.policy) endif EXTRA_DIST += \ $(polkitpolicy_in_files) \ $(polkitpolicy_in_in_files) # ------------------------------------------------------------------------------ man/custom-entities.ent: configure.ac $(AM_V_GEN)$(MKDIR_P) $(dir $@) $(AM_V_GEN)(echo '' && \ printf '$(subst '|,\n,$(substitutions))))') \ > $@ # ' CLEANFILES += \ man/custom-entities.ent XSLTPROC_FLAGS = \ --nonet \ --xinclude \ --stringparam man.output.quietly 1 \ --stringparam funcsynopsis.style ansi \ --stringparam man.authors.section.enabled 0 \ --stringparam man.copyright.section.enabled 0 \ --stringparam systemd.version $(VERSION) \ --path '$(builddir)/man:$(srcdir)/man' XSLT = $(if $(XSLTPROC), $(XSLTPROC), xsltproc) XSLTPROC_PROCESS_MAN = \ $(AM_V_XSLT)$(XSLT) -o $@ $(XSLTPROC_FLAGS) $(srcdir)/man/custom-man.xsl $< XSLTPROC_PROCESS_HTML = \ $(AM_V_XSLT)$(XSLT) -o $@ $(XSLTPROC_FLAGS) $(srcdir)/man/custom-html.xsl $< man/%.1: man/%.xml man/custom-man.xsl man/custom-entities.ent $(XSLTPROC_PROCESS_MAN) man/%.3: man/%.xml man/custom-man.xsl man/custom-entities.ent $(XSLTPROC_PROCESS_MAN) man/%.5: man/%.xml man/custom-man.xsl man/custom-entities.ent $(XSLTPROC_PROCESS_MAN) man/%.7: man/%.xml man/custom-man.xsl man/custom-entities.ent $(XSLTPROC_PROCESS_MAN) man/%.8: man/%.xml man/custom-man.xsl man/custom-entities.ent $(XSLTPROC_PROCESS_MAN) man/%.html: man/%.xml man/custom-html.xsl man/custom-entities.ent $(XSLTPROC_PROCESS_HTML) define html-alias $(AM_V_LN)$(LN_S) -f $(notdir $<) $@ endef EXTRA_DIST += \ man/custom-html.xsl \ man/custom-man.xsl # ------------------------------------------------------------------------------ if HAVE_SYSV_COMPAT sysvinit_DATA = \ docs/sysvinit/README varlog_DATA = \ docs/var-log/README docs/sysvinit/README: docs/sysvinit/README.in $(SED_PROCESS) docs/var-log/README: docs/var-log/README.in $(SED_PROCESS) CLEANFILES += \ docs/sysvinit/README \ docs/var-log/README endif EXTRA_DIST += \ docs/sysvinit/README.in \ docs/var-log/README.in SOCKETS_TARGET_WANTS += \ systemd-initctl.socket if HAVE_UTMP if HAVE_SYSV_COMPAT MULTI_USER_TARGET_WANTS += \ systemd-update-utmp-runlevel.service GRAPHICAL_TARGET_WANTS += \ systemd-update-utmp-runlevel.service RESCUE_TARGET_WANTS += \ systemd-update-utmp-runlevel.service endif SYSINIT_TARGET_WANTS += \ systemd-update-utmp.service endif SYSINIT_TARGET_WANTS += \ systemd-update-done.service LOCAL_FS_TARGET_WANTS += \ systemd-remount-fs.service \ tmp.mount \ var-lib-machines.mount MULTI_USER_TARGET_WANTS += \ getty.target \ systemd-ask-password-wall.path SYSINIT_TARGET_WANTS += \ dev-hugepages.mount \ dev-mqueue.mount \ sys-kernel-config.mount \ sys-kernel-debug.mount \ sys-fs-fuse-connections.mount \ systemd-sysctl.service \ systemd-ask-password-console.path if HAVE_SYSV_COMPAT SYSTEM_UNIT_ALIASES += \ poweroff.target runlevel0.target \ rescue.target runlevel1.target \ multi-user.target runlevel2.target \ multi-user.target runlevel3.target \ multi-user.target runlevel4.target \ graphical.target runlevel5.target \ reboot.target runlevel6.target endif SYSTEM_UNIT_ALIASES += \ graphical.target default.target \ reboot.target ctrl-alt-del.target \ getty@.service autovt@.service USER_UNIT_ALIASES += \ $(systemunitdir)/shutdown.target shutdown.target \ $(systemunitdir)/sockets.target sockets.target \ $(systemunitdir)/timers.target timers.target \ $(systemunitdir)/paths.target paths.target \ $(systemunitdir)/bluetooth.target bluetooth.target \ $(systemunitdir)/printer.target printer.target \ $(systemunitdir)/sound.target sound.target \ $(systemunitdir)/smartcard.target smartcard.target USER_UNIT_ALIASES += \ $(systemunitdir)/busnames.target busnames.target GENERAL_ALIASES += \ $(systemunitdir)/remote-fs.target $(pkgsysconfdir)/system/multi-user.target.wants/remote-fs.target \ $(systemunitdir)/getty@.service $(pkgsysconfdir)/system/getty.target.wants/getty@tty1.service \ $(pkgsysconfdir)/user $(sysconfdir)/xdg/systemd/user \ $(dbussystemservicedir)/org.freedesktop.systemd1.service $(dbussessionservicedir)/org.freedesktop.systemd1.service if HAVE_SYSV_COMPAT INSTALL_DIRS += \ $(systemunitdir)/runlevel1.target.wants \ $(systemunitdir)/runlevel2.target.wants \ $(systemunitdir)/runlevel3.target.wants \ $(systemunitdir)/runlevel4.target.wants \ $(systemunitdir)/runlevel5.target.wants endif INSTALL_DIRS += \ $(prefix)/lib/modules-load.d \ $(sysconfdir)/modules-load.d \ $(prefix)/lib/systemd/network \ $(sysconfdir)/systemd/network \ $(prefix)/lib/sysctl.d \ $(sysconfdir)/sysctl.d \ $(prefix)/lib/kernel/install.d \ $(sysconfdir)/kernel/install.d \ $(systemshutdowndir) \ $(systemsleepdir) \ $(systemgeneratordir) \ $(usergeneratordir) \ \ $(userunitdir) \ $(pkgsysconfdir)/system \ $(pkgsysconfdir)/system/multi-user.target.wants \ $(pkgsysconfdir)/system/getty.target.wants \ $(pkgsysconfdir)/user \ $(dbussessionservicedir) \ $(sysconfdir)/xdg/systemd install-exec-hook: $(INSTALL_EXEC_HOOKS) uninstall-hook: $(UNINSTALL_DATA_HOOKS) $(UNINSTALL_EXEC_HOOKS) install-data-hook: $(INSTALL_DATA_HOOKS) distclean-local: $(DISTCLEAN_LOCAL_HOOKS) clean-local: $(CLEAN_LOCAL_HOOKS) rm -rf $(abs_srcdir)/install-tree rm -f $(abs_srcdir)/hwdb/usb.ids $(abs_srcdir)/hwdb/pci.ids $(abs_srcdir)/hwdb/oui.txt \ $(abs_srcdir)/hwdb/iab.txt DISTCHECK_CONFIGURE_FLAGS = \ --with-dbuspolicydir=$$dc_install_base/$(dbuspolicydir) \ --with-dbussessionservicedir=$$dc_install_base/$(dbussessionservicedir) \ --with-dbussystemservicedir=$$dc_install_base/$(dbussystemservicedir) \ --with-bashcompletiondir=$$dc_install_base/$(bashcompletiondir) \ --with-zshcompletiondir=$$dc_install_base/$(zshcompletiondir) \ --with-pamlibdir=$$dc_install_base/$(pamlibdir) \ --with-pamconfdir=$$dc_install_base/$(pamconfdir) \ --with-rootprefix=$$dc_install_base \ --enable-compat-libs if HAVE_SYSV_COMPAT DISTCHECK_CONFIGURE_FLAGS += \ --with-sysvinit-path=$$dc_install_base/$(sysvinitdir) \ --with-sysvrcnd-path=$$dc_install_base/$(sysvrcnddir) else DISTCHECK_CONFIGURE_FLAGS += \ --with-sysvinit-path= \ --with-sysvrcnd-path= endif if ENABLE_SPLIT_USR DISTCHECK_CONFIGURE_FLAGS += \ --enable-split-usr else DISTCHECK_CONFIGURE_FLAGS += \ --disable-split-usr endif .PHONY: dist-check-help dist-check-help: $(rootbin_PROGRAMS) $(bin_PROGRAMS) for i in $(abspath $^); do \ if $$i --help | grep -v 'default:' | grep -E -q '.{80}.' ; then \ echo "$(basename $$i) --help output is too wide:"; \ $$i --help | awk 'length > 80' | grep -E --color=yes '.{80}'; \ exit 1; \ fi; done .PHONY: hwdb-update hwdb-update: ( cd $(top_srcdir)/hwdb && \ wget -O usb.ids 'http://www.linux-usb.org/usb.ids' && \ wget -O pci.ids 'http://pci-ids.ucw.cz/v2.2/pci.ids' && \ wget -O ma-large.txt 'http://standards.ieee.org/develop/regauth/oui/oui.txt' && \ wget -O ma-medium.txt 'http://standards.ieee.org/develop/regauth/oui28/mam.txt' && \ wget -O ma-small.txt 'http://standards.ieee.org/develop/regauth/oui36/oui36.txt' && \ ./ids-update.pl ) .PHONY: built-sources built-sources: $(BUILT_SOURCES) .PHONY: git-tag git-tag: git tag -s "v$(VERSION)" -m "systemd $(VERSION)" .PHONY: git-tar git-tar: git archive --format=tar --prefix=systemd-$(VERSION)/ HEAD | gzip > systemd-$(VERSION).tar.gz www_target = www.freedesktop.org:/srv/www.freedesktop.org/www/software/systemd .PHONY: doc-sync doc-sync: all rsync -rlv --delete-excluded --include="*.html" --exclude="*" --omit-dir-times man/ $(www_target)/man/ .PHONY: install-tree install-tree: all rm -rf $(abs_srcdir)/install-tree $(MAKE) install DESTDIR=$(abs_srcdir)/install-tree tree $(abs_srcdir)/install-tree # Let's run all tests of the test suite, but under valgrind. Let's # exclude perl/python/shell scripts we have in there .PHONY: valgrind-tests valgrind-tests: $(TESTS) $(AM_V_GEN)for f in $(filter-out %.pl %.py, $^); do \ if file $$f | grep -q shell; then \ echo -e "$${x}Skipping non-binary $$f"; else \ echo -e "$${x}Running $$f"; \ $(LIBTOOL) --mode=execute valgrind -q --leak-check=full --max-stackframe=5242880 --error-exitcode=55 $(builddir)/$$f ; fi; \ x="\n\n"; \ done exported-%: % $(AM_V_GEN)$(NM) -g --defined-only $(builddir)/.libs/$(<:.la=.so) 2>&1 /dev/null | grep " T " | cut -d" " -f3 > $@ exported: $(addprefix exported-, $(lib_LTLIBRARIES)) $(AM_V_GEN)sort -u $^ > $@ .PHONY: check-api-docs check-api-docs: exported man $(AM_V_GEN)for symbol in `cat exported` ; do \ if test -f $(builddir)/man/$$symbol.html ; then \ echo " Symbol $$symbol() is documented." ; \ else \ echo "‣ Symbol $$symbol() lacks documentation." ; \ fi ; \ done OBJECT_VARIABLES:=$(filter %_OBJECTS,$(.VARIABLES)) ALL_OBJECTS:=$(foreach v,$(OBJECT_VARIABLES),$($(v))) undefined defined: $(ALL_OBJECTS) $(AM_V_GEN)for f in $(ALL_OBJECTS) ; do \ $(NM) -g --$@-only `echo $(builddir)/"$$f" | sed -e 's,\([^/]*\).lo$$,.libs/\1.o,'` ; \ done | cut -c 20- | cut -d @ -f 1 | sort -u > $@ CLEANFILES += \ defined \ undefined .PHONY: check-api-unused check-api-unused: defined undefined exported ( cat exported undefined ) | sort -u | diff -u - defined | grep ^+ | grep -v ^+++ | cut -c2- .PHONY: check-includes check-includes: $(top_srcdir)/tools/check-includes.pl $(AM_V_GEN) find * -name '*.[hcS]' -type f -print | sort -u \ | xargs $(top_srcdir)/tools/check-includes.pl EXTRA_DIST += \ $(top_srcdir)/tools/check-includes.pl # Stupid test that everything purported to be exported really is define generate-sym-test $(AM_V_at)$(MKDIR_P) $(dir $@) $(AM_V_at)printf '#include \n' > $@ $(AM_V_at)printf '#include "%s"\n' $(notdir $(filter %.h, $^)) >> $@ $(AM_V_at)printf 'void* functions[] = {\n' >> $@ $(AM_V_GEN)sed -r -n 's/^ +([a-zA-Z0-9_]+);/\1,/p' $< >> $@ $(AM_V_at)printf '};\nint main(void) {\n' >> $@ $(AM_V_at)printf 'unsigned i; for (i=0;i> $@ $(AM_V_at)printf 'return 0; }\n' >> $@ endef test-libsystemd-sym.c: \ $(top_builddir)/src/libsystemd/libsystemd.sym \ src/systemd/sd-journal.h \ src/systemd/sd-daemon.h \ src/systemd/sd-login.h \ src/systemd/sd-bus.h \ src/systemd/sd-utf8.h \ src/systemd/sd-resolve.h \ src/systemd/sd-path.h \ src/systemd/sd-event.h $(generate-sym-test) test-libudev-sym.c: \ src/libudev/libudev.sym \ src/udev/udev.h $(generate-sym-test) nodist_test_libsystemd_sym_SOURCES = \ test-libsystemd-sym.c test_libsystemd_sym_LDADD = \ libsystemd.la nodist_test_libudev_sym_SOURCES = \ test-libudev-sym.c test_libudev_sym_CFLAGS = \ $(AM_CFLAGS) \ -Wno-deprecated-declarations test_libudev_sym_LDADD = \ libudev.la BUILT_SOURCES += \ test-libsystemd-sym.c \ test-libudev-sym.c CLEANFILES += \ test-libsystemd-sym.c \ test-libudev-sym.c tests += \ test-libsystemd-sym \ test-libudev-sym .PHONY: cppcheck cppcheck: cppcheck --enable=all -q $(top_srcdir) # Used to extract compile flags for YCM. print-%: @echo $($*) git-contrib: @git shortlog -s `git describe --abbrev=0`.. | cut -c8- | awk '{ print $$0 "," }' | sort -u EXTRA_DIST += \ tools/gdb-sd_dump_hashmaps.py list-keys: gpg --verbose --no-options --no-default-keyring --no-auto-key-locate --batch --trust-model=always --keyring=$(srcdir)/src/import/import-pubring.gpg --list-keys add-key: gpg --verbose --no-options --no-default-keyring --no-auto-key-locate --batch --trust-model=always --keyring=$(srcdir)/src/import/import-pubring.gpg --import - systemd-229/NEWS000066400000000000000000011102221265713322000135570ustar00rootroot00000000000000systemd System and Service Manager CHANGES WITH 229: * The systemd-resolved DNS resolver service has gained a substantial set of new features, most prominently it may now act as a DNSSEC validating stub resolver. DNSSEC mode is currently turned off by default, but it is expected that this is turned on by default in one of the next releases. For now, we invite everybody to test the DNSSEC logic by setting DNSSEC=allow-downgrade in /etc/systemd/resolved.conf. The service also gained a full set of D-Bus interfaces, including calls to configure DNS and DNSSEC settings per link (for consumption by external network management software). systemd-resolved (and systemd-networkd along with it) now know to distinguish between "search" and "routing" domains. The former are used to qualify single-label names, the latter are purely used for routing lookups within certain domains to specific links. resolved will now also synthesize RRs for all entries from /etc/hosts. * The systemd-resolve tool (which is a client utility for systemd-resolved, and previously experimental) has been improved considerably and is now fully supported and documented. Hence it has moved from /usr/lib/systemd to /usr/bin. * /dev/disk/by-path/ symlink support has been (re-)added for virtio devices. * The coredump collection logic has been reworked: when a coredump is collected it is now written to disk, compressed and processed (including stacktrace extraction) from a new instantiated service systemd-coredump@.service, instead of directly from the /proc/sys/kernel/core_pattern hook we provide. This is beneficial as processing large coredumps can take up a substantial amount of resources and time, and this previously happened entirely outside of systemd's service supervision. With the new logic the core_pattern hook only does minimal metadata collection before passing off control to the new instantiated service, which is configured with a time limit, a nice level and other settings to minimize negative impact on the rest of the system. Also note that the new logic will honour the RLIMIT_CORE setting of the crashed process, which now allows users and processes to turn off coredumping for their processes by setting this limit. * The RLIMIT_CORE resource limit now defaults to "unlimited" for PID 1 and all forked processes by default. Previously, PID 1 would leave the setting at "0" for all processes, as set by the kernel. Note that the resource limit traditionally has no effect on the generated coredumps on the system if the /proc/sys/kernel/core_pattern hook logic is used. Since the limit is now honoured (see above) its default has been changed so that the coredumping logic is enabled by default for all processes, while allowing specific opt-out. * When the stacktrace is extracted from processes of system users, this is now done as "systemd-coredump" user, in order to sandbox this potentially security sensitive parsing operation. (Note that when processing coredumps of normal users this is done under the user ID of process that crashed, as before.) Packagers should take notice that it is now necessary to create the "systemd-coredump" system user and group at package installation time. * The systemd-activate socket activation testing tool gained support for SOCK_DGRAM and SOCK_SEQPACKET sockets using the new --datagram and --seqpacket switches. It also has been extended to support both new-style and inetd-style file descriptor passing. Use the new --inetd switch to request inetd-style file descriptor passing. * Most systemd tools now honor a new $SYSTEMD_COLORS environment variable, which takes a boolean value. If set to false, ANSI color output is disabled in the tools even when run on a terminal that supports it. * The VXLAN support in networkd now supports two new settings DestinationPort= and PortRange=. * A new systemd.machine_id= kernel command line switch has been added, that may be used to set the machine ID in /etc/machine-id if it is not initialized yet. This command line option has no effect if the file is already initialized. * systemd-nspawn gained a new --as-pid2 switch that invokes any specified command line as PID 2 rather than PID 1 in the container. In this mode PID 1 will be a minimal stub init process that implements the special POSIX and Linux semantics of PID 1 regarding signal and child process management. Note that this stub init process is implemented in nspawn itself and requires no support from the container image. This new logic is useful to support running arbitrary command lines in the container, as normal processes are generally not prepared to run as PID 1. * systemd-nspawn gained a new --chdir= switch for setting the current working directory for the process started in the container. * "journalctl /dev/sda" will now output all kernel log messages from the specified device, in addition to all devices that are parents of it. This should make log output about devices pretty useful, as long as kernel drivers attach enough metadata to the log messages. (The usual SATA drivers do.) * The sd-journal API gained two new calls sd_journal_has_runtime_files() and sd_journal_has_persistent_files() that report whether log data from /run or /var has been found. * journalctl gained a new switch "--fields" that prints all journal record field names currently in use in the journal. This is backed by two new sd-journal API calls sd_journal_enumerate_fields() and sd_journal_restart_fields(). * Most configurable timeouts in systemd now expect an argument of "infinity" to turn them off, instead of "0" as before. The semantics from now on is that a timeout of "0" means "now", and "infinity" means "never". To maintain backwards compatibility, "0" continues to turn off previously existing timeout settings. * "systemctl reload-or-try-restart" has been renamed to "systemctl try-reload-or-restart" to clarify what it actually does: the "try" logic applies to both reloading and restarting, not just restarting. The old name continues to be accepted for compatibility. * On boot-up, when PID 1 detects that the system clock is behind the release date of the systemd version in use, the clock is now set to the latter. Previously, this was already done in timesyncd, in order to avoid running with clocks set to the various clock epochs such as 1902, 1938 or 1970. With this change the logic is now done in PID 1 in addition to timesyncd during early boot-up, so that it is enforced before the first process is spawned by systemd. Note that the logic in timesyncd remains, as it is more comprehensive and ensures montonic clocks by maintaining a persistant timestamp file in /var. Since /var is generally not available in earliest boot or the initrd, this part of the logic remains in timesyncd, and is not done by PID 1. * Support for tweaking details in net_cls.class_id through the NetClass= configuration directive has been removed, as the kernel people have decided to deprecate that controller in cgroup v2. Userspace tools such as nftables are moving over to setting rules that are specific to the full cgroup path of a task, which obsoletes these controllers anyway. The NetClass= directive is kept around for legacy compatibility reasons. For a more in-depth description of the kernel change, please refer to the respective upstream commit: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=bd1060a1d671 * A new service setting RuntimeMaxSec= has been added that may be used to specify a maximum runtime for a service. If the timeout is hit, the service is terminated and put into a failure state. * A new service setting AmbientCapabilities= has been added. It allows configuration of additional Linux process capabilities that are passed to the activated processes. This is only available on very recent kernels. * The process resource limit settings in service units may now be used to configure hard and soft limits individually. * The various libsystemd APIs such as sd-bus or sd-event now publicly expose support for gcc's __attribute__((cleanup())) C extension. Specifically, for many object destructor functions alternative versions whose names are suffixed with "p" have been added, which take a pointer to a pointer to the object to destroy, instead of just a pointer to the object itself. This is useful because these destructor functions may be used directly as parameters to the cleanup construct. Internally, systemd has been a heavy user of the GCC extension since a long time, and with this change similar support is now available to consumers of the library outside of systemd. Note that by using this extension in your sources compatibility with old and strictly ANSI compatible C compilers is lost. However, any gcc or LLVM version of recent years have supported this extension. * Timer units gained support for a new setting RandomizedDelaySec= that allows configuring some additional randomized delay to the configured time. This is useful to spread out timer events to avoid load peaks in clusters or larger setups. * Calendar time specifications now support sub-second accuracy. * Socket units now support listening on SCTP and UDP-lite protocol sockets. * The sd-event API now comes with a full set of man pages. * Older versions of systemd contained experimental support for compressing journal files and coredumps with the LZ4 compressor that was not compatible with the lz4 binary (due to API limitations of the lz4 library). This support has been removed; only support for files compatible with the lz4 binary remains. This LZ4 logic is now officially supported and no longer considered experimental. * The dkr image import logic has been removed again from importd. dkr's micro-services focus doesn't fit into the machine image focus of importd, and quickly got out of date with the upstream dkr API. * Creation of the /run/lock/lockdev/ directory was dropped from tmpfiles.d/legacy.conf. Better locking mechanisms like flock() have been available for many years. If you still need this, you need to create your own tmpfiles.d config file with: d /run/lock/lockdev 0775 root lock - Contributions from: Abdo Roig-Maranges, Alban Crequy, Aleksander Adamowski, Alexander Kuleshov, Andreas Pokorny, Andrei Borzenkov, Andrew Wilcox, Arthur Clement, Beniamino Galvani, Casey Schaufler, Chris Atkinson, Chris Mayo, Christian Hesse, Damjan Georgievski, Dan Dedrick, Daniele Medri, Daniel J Walsh, Daniel Korostil, Daniel Mack, David Herrmann, Dimitri John Ledkov, Dominik Hannen, Douglas Christman, Evgeny Vereshchagin, Filipe Brandenburger, Franck Bui, Gabor Kelemen, Harald Hoyer, Hayden Walles, Helmut Grohne, Henrik Kaare Poulsen, Hristo Venev, Hui Wang, Indrajit Raychaudhuri, Ismo Puustinen, Jakub Wilk, Jan Alexander Steffens (heftig), Jan Engelhardt, Jan Synacek, Joost Bremmer, Jorgen Schaefer, Karel Zak, Klearchos Chaloulos, lc85446, Lennart Poettering, Lukas Nykryn, Mantas Mikulėnas, Marcel Holtmann, Martin Pitt, Michael Biebl, Michael Olbrich, Michael Scherer, Michał Górny, Michal Sekletar, Nicolas Cornu, Nicolas Iooss, Nils Carlson, nmartensen, nnz1024, Patrick Ohly, Peter Hutterer, Phillip Sz, Ronny Chevalier, Samu Kallio, Shawn Landden, Stef Walter, Susant Sahani, Sylvain Plantefève, Tadej Janež, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Torstein Husebø, Umut Tezduyar Lindskog, Vito Caputo, WaLyong Cho, Yu Watanabe, Zbigniew Jędrzejewski-Szmek -- Berlin, 2016-02-11 CHANGES WITH 228: * A number of properties previously only settable in unit files are now also available as properties to set when creating transient units programmatically via the bus, as it is exposed with systemd-run's --property= setting. Specifically, these are: SyslogIdentifier=, SyslogLevelPrefix=, TimerSlackNSec=, OOMScoreAdjust=, EnvironmentFile=, ReadWriteDirectories=, ReadOnlyDirectories=, InaccessibleDirectories=, ProtectSystem=, ProtectHome=, RuntimeDirectory=. * When creating transient services via the bus API it is now possible to pass in a set of file descriptors to use as STDIN/STDOUT/STDERR for the invoked process. * Slice units may now be created transiently via the bus APIs, similar to the way service and scope units may already be created transiently. * Wherever systemd expects a calendar timestamp specification (like in journalctl's --since= and --until= switches) UTC timestamps are now supported. Timestamps suffixed with "UTC" are now considered to be in Universal Time Coordinated instead of the local timezone. Also, timestamps may now optionally be specified with sub-second accuracy. Both of these additions also apply to recurring calendar event specification, such as OnCalendar= in timer units. * journalctl gained a new "--sync" switch that asks the journal daemon to write all so far unwritten log messages to disk and sync the files, before returning. * systemd-tmpfiles learned two new line types "q" and "Q" that operate like "v", but also set up a basic btrfs quota hierarchy when used on a btrfs file system with quota enabled. * tmpfiles' "v", "q" and "Q" will now create a plain directory instead of a subvolume (even on a btrfs file system) if the root directory is a plain directory, and not a subvolume. This should simplify things with certain chroot() environments which are not aware of the concept of btrfs subvolumes. * systemd-detect-virt gained a new --chroot switch to detect whether execution takes place in a chroot() environment. * CPUAffinity= now takes CPU index ranges in addition to individual indexes. * The various memory-related resource limit settings (such as LimitAS=) now understand the usual K, M, G, ... suffixes to the base of 1024 (IEC). Similar, the time-related resource limit settings understand the usual min, h, day, ... suffixes now. * There's a new system.conf setting DefaultTasksMax= to control the default TasksMax= setting for services and scopes running on the system. (TasksMax= is the primary setting that exposes the "pids" cgroup controller on systemd and was introduced in the previous systemd release.) The setting now defaults to 512, which means services that are not explicitly configured otherwise will only be able to create 512 processes or threads at maximum, from this version on. Note that this means that thread- or process-heavy services might need to be reconfigured to set TasksMax= to a higher value. It is sufficient to set TasksMax= in these specific unit files to a higher value, or even "infinity". Similar, there's now a logind.conf setting UserTasksMax= that defaults to 4096 and limits the total number of processes or tasks each user may own concurrently. nspawn containers also have the TasksMax= value set by default now, to 8192. Note that all of this only has an effect if the "pids" cgroup controller is enabled in the kernel. The general benefit of these changes should be a more robust and safer system, that provides a certain amount of per-service fork() bomb protection. * systemd-nspawn gained the new --network-veth-extra= switch to define additional and arbitrarily-named virtual Ethernet links between the host and the container. * A new service execution setting PassEnvironment= has been added that allows importing select environment variables from PID1's environment block into the environment block of the service. * Timer units gained support for a new RemainAfterElapse= setting which takes a boolean argument. It defaults on on, exposing behaviour unchanged to previous releases. If set to off, timer units are unloaded after they elapsed if they cannot elapse again. This is particularly useful for transient timer units, which shall not stay around longer than until they first elapse. * systemd will now bump the net.unix.max_dgram_qlen to 512 by default now (the kernel default is 16). This is beneficial for avoiding blocking on AF_UNIX/SOCK_DGRAM sockets since it allows substantially larger numbers of queued datagrams. This should increase the capability of systemd to parallelize boot-up, as logging and sd_notify() are unlikely to stall execution anymore. If you need to change the value from the new defaults, use the usual sysctl.d/ snippets. * The compression framing format used by the journal or coredump processing has changed to be in line with what the official LZ4 tools generate. LZ4 compression support in systemd was considered unsupported previously, as the format was not compatible with the normal tools. With this release this has changed now, and it is hence safe for downstream distributions to turn it on. While not compressing as well as the XZ, LZ4 is substantially faster, which makes it a good default choice for the compression logic in the journal and in coredump handling. * Any reference to /etc/mtab has been dropped from systemd. The file has been obsolete since a while, but systemd refused to work on systems where it was incorrectly set up (it should be a symlink or non-existent). Please make sure to update to util-linux 2.27.1 or newer in conjunction with this systemd release, which also drops any reference to /etc/mtab. If you maintain a distribution make sure that no software you package still references it, as this is a likely source of bugs. There's also a glibc bug pending, asking for removal of any reference to this obsolete file: https://sourceware.org/bugzilla/show_bug.cgi?id=19108 * Support for the ".snapshot" unit type has been removed. This feature turned out to be little useful and little used, and has now been removed from the core and from systemctl. * The dependency types RequiresOverridable= and RequisiteOverridable= have been removed from systemd. They have been used only very sparingly to our knowledge and other options that provide a similar effect (such as systemctl --mode=ignore-dependencies) are much more useful and commonly used. Moreover, they were only half-way implemented as the option to control behaviour regarding these dependencies was never added to systemctl. By removing these dependency types the execution engine becomes a bit simpler. Unit files that use these dependencies should be changed to use the non-Overridable dependency types instead. In fact, when parsing unit files with these options, that's what systemd will automatically convert them too, but it will also warn, asking users to fix the unit files accordingly. Removal of these dependency types should only affect a negligible number of unit files in the wild. * Behaviour of networkd's IPForward= option changed (again). It will no longer maintain a per-interface setting, but propagate one way from interfaces where this is enabled to the global kernel setting. The global setting will be enabled when requested by a network that is set up, but never be disabled again. This change was made to make sure IPv4 and IPv6 behaviour regarding packet forwarding is similar (as the Linux IPv6 stack does not support per-interface control of this setting) and to minimize surprises. * In unit files the behaviour of %u, %U, %h, %s has changed. These specifiers will now unconditionally resolve to the various user database fields of the user that the systemd instance is running as, instead of the user configured in the specific unit via User=. Note that this effectively doesn't change much, as resolving of these specifiers was already turned off in the --system instance of systemd, as we cannot do NSS lookups from PID 1. In the --user instance of systemd these specifiers where correctly resolved, but hardly made any sense, since the user instance lacks privileges to do user switches anyway, and User= is hence useless. Morever, even in the --user instance of systemd behaviour was awkward as it would only take settings from User= assignment placed before the specifier into account. In order to unify and simplify the logic around this the specifiers will now always resolve to the credentials of the user invoking the manager (which in case of PID 1 is the root user). Contributions from: Andrew Jones, Beniamino Galvani, Boyuan Yang, Daniel Machon, Daniel Mack, David Herrmann, David Reynolds, David Strauss, Dongsu Park, Evgeny Vereshchagin, Felipe Sateler, Filipe Brandenburger, Franck Bui, Hristo Venev, Iago López Galeiras, Jan Engelhardt, Jan Janssen, Jan Synacek, Jesus Ornelas Aguayo, Karel Zak, kayrus, Kay Sievers, Lennart Poettering, Liu Yuan Yuan, Mantas Mikulėnas, Marcel Holtmann, Marcin Bachry, Marcos Alano, Marcos Mello, Mark Theunissen, Martin Pitt, Michael Marineau, Michael Olbrich, Michal Schmidt, Michal Sekletar, Mirco Tischler, Nick Owens, Nicolas Cornu, Patrik Flykt, Peter Hutterer, reverendhomer, Ronny Chevalier, Sangjung Woo, Seong-ho Cho, Shawn Landden, Susant Sahani, Thomas Haller, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Torstein Husebø, Vito Caputo, Zbigniew Jędrzejewski-Szmek -- Berlin, 2015-11-18 CHANGES WITH 227: * systemd now depends on util-linux v2.27. More specifically, the newly added mount monitor feature in libmount now replaces systemd's former own implementation. * libmount mandates /etc/mtab not to be regular file, and systemd now enforces this condition at early boot. /etc/mtab has been deprecated and warned about for a very long time, so systems running systemd should already have stopped having this file around as anything else than a symlink to /proc/self/mounts. * Support for the "pids" cgroup controller has been added. It allows accounting the number of tasks in a cgroup and enforcing limits on it. This adds two new setting TasksAccounting= and TasksMax= to each unit, as well as a global option DefaultTasksAccounting=. * Support for the "net_cls" cgroup controller has been added. It allows assigning a net class ID to each task in the cgroup, which can then be used in firewall rules and traffic shaping configurations. Note that the kernel netfilter net class code does not currently work reliably for ingress packets on unestablished sockets. This adds a new config directive called NetClass= to CGroup enabled units. Allowed values are positive numbers for fixed assignments and "auto" for picking a free value automatically. * 'systemctl is-system-running' now returns 'offline' if the system is not booted with systemd. This command can now be used as a substitute for 'systemd-notify --booted'. * Watchdog timeouts have been increased to 3 minutes for all in-tree service files. Apparently, disk IO issues are more frequent than we hoped, and user reported >1 minute waiting for disk IO. * 'machine-id-commit' functionality has been merged into 'machine-id-setup --commit'. The separate binary has been removed. * The WorkingDirectory= directive in unit files may now be set to the special value '~'. In this case, the working directory is set to the home directory of the user configured in User=. * "machinectl shell" will now open the shell in the home directory of the selected user by default. * The CrashChVT= configuration file setting is renamed to CrashChangeVT=, following our usual logic of not abbreviating unnecessarily. The old directive is still supported for compat reasons. Also, this directive now takes an integer value between 1 and 63, or a boolean value. The formerly supported '-1' value for disabling stays around for compat reasons. * The PrivateTmp=, PrivateDevices=, PrivateNetwork=, NoNewPrivileges=, TTYPath=, WorkingDirectory= and RootDirectory= properties can now be set for transient units. * The systemd-analyze tool gained a new "set-log-target" verb to change the logging target the system manager logs to dynamically during runtime. This is similar to how "systemd-analyze set-log-level" already changes the log level. * In nspawn /sys is now mounted as tmpfs, with only a selected set of subdirectories mounted in from the real sysfs. This enhances security slightly, and is useful for ensuring user namespaces work correctly. * Support for USB FunctionFS activation has been added. This allows implementation of USB gadget services that are activated as soon as they are requested, so that they don't have to run continously, similar to classic socket activation. * The "systemctl exit" command now optionally takes an additional parameter that sets the exit code to return from the systemd manager when exiting. This is only relevant when running the systemd user instance, or when running the system instance in a container. * sd-bus gained the new API calls sd_bus_path_encode_many() and sd_bus_path_decode_many() that allow easy encoding and decoding of multiple identifier strings inside a D-Bus object path. Another new call sd_bus_default_flush_close() has been added to flush and close per-thread default connections. * systemd-cgtop gained support for a -M/--machine= switch to show the control groups within a certain container only. * "systemctl kill" gained support for an optional --fail switch. If specified the requested operation will fail of no processes have been killed, because the unit had no processes attached, or similar. * A new systemd.crash_reboot=1 kernel command line option has been added that triggers a reboot after crashing. This can also be set through CrashReboot= in systemd.conf. * The RuntimeDirectory= setting now understands unit specifiers like %i or %f. * A new (still internal) libary API sd-ipv4acd has been added, that implements address conflict detection for IPv4. It's based on code from sd-ipv4ll, and will be useful for detecting DHCP address conflicts. * File descriptors passed during socket activation may now be named. A new API sd_listen_fds_with_names() is added to access the names. The default names may be overridden, either in the .socket file using the FileDescriptorName= parameter, or by passing FDNAME= when storing the file descriptors using sd_notify(). * systemd-networkd gained support for: - Setting the IPv6 Router Advertisment settings via IPv6AcceptRouterAdvertisements= in .network files. - Configuring the HelloTimeSec=, MaxAgeSec= and ForwardDelaySec= bridge parameters in .netdev files. - Configuring PreferredSource= for static routes in .network files. * The "ask-password" framework used to query for LUKS harddisk passwords or SSL passwords during boot gained support for caching passwords in the kernel keyring, if it is available. This makes sure that the user only has to type in a passphrase once if there are multiple objects to unlock with the same one. Previously, such password caching was available only when Plymouth was used; this moves the caching logic into the systemd codebase itself. The "systemd-ask-password" utility gained a new --keyname= switch to control which kernel keyring key to use for caching a password in. This functionality is also useful for enabling display managers such as gdm to automatically unlock the user's GNOME keyring if its passphrase, the user's password and the harddisk password are the same, if gdm-autologin is used. * When downloading tar or raw images using "machinectl pull-tar" or "machinectl pull-raw", a matching ".nspawn" file is now also downloaded, if it is available and stored next to the image file. * Units of type ".socket" gained a new boolean setting Writable= which is only useful in conjunction with ListenSpecial=. If true, enables opening the specified special file in O_RDWR mode rather than O_RDONLY mode. * systemd-rfkill has been reworked to become a singleton service that is activated through /dev/rfkill on each rfkill state change and saves the settings to disk. This way, systemd-rfkill is now compatible with devices that exist only intermittendly, and even restores state if the previous system shutdown was abrupt rather than clean. * The journal daemon gained support for vacuuming old journal files controlled by the number of files that shall remain, in addition to the already existing control by size and by date. This is useful as journal interleaving performance degrades with too many seperate journal files, and allows putting an effective limit on them. The new setting defaults to 100, but this may be changed by setting SystemMaxFiles= and RuntimeMaxFiles= in journald.conf. Also, the "journalctl" tool gained the new --vacuum-files= switch to manually vacuum journal files to leave only the specified number of files in place. * udev will now create /dev/disk/by-path links for ATA devices on kernels where that is supported. * Galician, Serbian, Turkish and Korean translations were added. Contributions from: Aaro Koskinen, Alban Crequy, Beniamino Galvani, Benjamin Robin, Branislav Blaskovic, Chen-Han Hsiao (Stanley), Daniel Buch, Daniel Machon, Daniel Mack, David Herrmann, David Milburn, doubleodoug, Evgeny Vereshchagin, Felipe Franciosi, Filipe Brandenburger, Fran Dieguez, Gabriel de Perthuis, Georg Müller, Hans de Goede, Hendrik Brueckner, Ivan Shapovalov, Jacob Keller, Jan Engelhardt, Jan Janssen, Jan Synacek, Jens Kuske, Karel Zak, Kay Sievers, Krzesimir Nowak, Krzysztof Kotlenga, Lars Uebernickel, Lennart Poettering, Lukas Nykryn, Łukasz Stelmach, Maciej Wereski, Marcel Holtmann, Marius Thesing, Martin Pitt, Michael Biebl, Michael Gebetsroither, Michal Schmidt, Michal Sekletar, Mike Gilbert, Muhammet Kara, nazgul77, Nicolas Cornu, NoXPhasma, Olof Johansson, Patrik Flykt, Pawel Szewczyk, reverendhomer, Ronny Chevalier, Sangjung Woo, Seong-ho Cho, Susant Sahani, Sylvain Plantefève, Thomas Haller, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Tom Lyon, Viktar Vauchkevich, Zbigniew Jędrzejewski-Szmek, Марко М. Костић -- Berlin, 2015-10-07 CHANGES WITH 226: * The DHCP implementation of systemd-networkd gained a set of new features: - The DHCP server now supports emitting DNS and NTP information. It may be enabled and configured via EmitDNS=, DNS=, EmitNTP=, and NTP=. If transmission of DNS and NTP information is enabled, but no servers are configured, the corresponding uplink information (if there is any) is propagated. - Server and client now support transmission and reception of timezone information. It can be configured via the newly introduced network options UseTimezone=, EmitTimezone=, and Timezone=. Transmission of timezone information is enabled between host and containers by default now: the container will change its local timezone to what the host has set. - Lease timeouts can now be configured via MaxLeaseTimeSec= and DefaultLeaseTimeSec=. - The DHCP server improved on the stability of leases. Clients are more likely to get the same lease information back, even if the server loses state. - The DHCP server supports two new configuration options to control the lease address pool metrics, PoolOffset= and PoolSize=. * The encapsulation limit of tunnels in systemd-networkd may now be configured via 'EncapsulationLimit='. It allows modifying the maximum additional levels of encapsulation that are permitted to be prepended to a packet. * systemd now supports the concept of user buses replacing session buses, if used with dbus-1.10 (and enabled via dbus --enable-user-session). It previously only supported this on kdbus-enabled systems, and this release expands this to 'dbus-daemon' systems. * systemd-networkd now supports predictable interface names for virtio devices. * systemd now optionally supports the new Linux kernel "unified" control group hierarchy. If enabled via the kernel command-line option 'systemd.unified_cgroup_hierarchy=1', systemd will try to mount the unified cgroup hierarchy directly on /sys/fs/cgroup. If not enabled, or not available, systemd will fall back to the legacy cgroup hierarchy setup, as before. Host system and containers can mix and match legacy and unified hierarchies as they wish. nspawn understands the $UNIFIED_CROUP_HIERARCHY environment variable to individually select the hierarchy to use for executed containers. By default, nspawn will use the unified hierarchy for the containers if the host uses the unified hierarchy, and the legacy hierarchy otherwise. Please note that at this point the unified hierarchy is an experimental kernel feature and is likely to change in one of the next kernel releases. Therefore, it should not be enabled by default in downstream distributions yet. The minimum required kernel version for the unified hierarchy to work is 4.2. Note that when the unified hierarchy is used for the first time delegated access to controllers is safe. Because of this systemd-nspawn containers will get access to controllers now, as will systemd user sessions. This means containers and user sessions may now manage their own resources, partitioning up what the system grants them. * A new special scope unit "init.scope" has been introduced that encapsulates PID 1 of the system. It may be used to determine resource usage and enforce resource limits on PID 1 itself. PID 1 hence moved out of the root of the control group tree. * The cgtop tool gained support for filtering out kernel threads when counting tasks in a control group. Also, the count of processes is now recursively summed up by default. Two options -k and --recursive= have been added to revert to old behaviour. The tool has also been updated to work correctly in containers now. * systemd-nspawn's --bind= and --bind-ro= options have been extended to allow creation of non-recursive bind mounts. * libsystemd gained two new calls sd_pid_get_cgroup() and sd_peer_get_cgroup() which return the control group path of a process or peer of a connected AF_UNIX socket. This function call is particularly useful when implementing delegated subtrees support in the control group hierarchy. * The "sd-event" event loop API of libsystemd now supports correct dequeuing of real-time signals, without losing signal events. * When systemd requests a PolicyKit decision when managing units it will now add additional fields to the request, including unit name and desired operation. This enables more powerful PolicyKit policies, that make decisions depending on these parameters. * nspawn learnt support for .nspawn settings files, that may accompany the image files or directories of containers, and may contain additional settings for the container. This is an alternative to configuring container parameters via the nspawn command line. Contributions from: Cristian Rodríguez, Daniel Mack, David Herrmann, Eugene Yakubovich, Evgeny Vereshchagin, Filipe Brandenburger, Hans de Goede, Jan Alexander Steffens, Jan Synacek, Kay Sievers, Lennart Poettering, Mangix, Marcel Holtmann, Martin Pitt, Michael Biebl, Michael Chapman, Michal Sekletar, Peter Hutterer, Piotr Drąg, reverendhomer, Robin Hack, Susant Sahani, Sylvain Pasche, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Torstein Husebø -- Berlin, 2015-09-08 CHANGES WITH 225: * machinectl gained a new verb 'shell' which opens a fresh shell on the target container or the host. It is similar to the existing 'login' command of machinectl, but spawns the shell directly without prompting for username or password. The pseudo machine '.host' now refers to the local host and is used by default. Hence, 'machinectl shell' can be used as replacement for 'su -' which spawns a session as a fresh systemd unit in a way that is fully isolated from the originating session. * systemd-networkd learned to cope with private-zone DHCP options and allows other programs to query the values. * SELinux access control when enabling/disabling units is no longer enforced with this release. The previous implementation was incorrect, and a new corrected implementation is not yet available. As unit file operations are still protected via PolicyKit and D-Bus policy this is not a security problem. Yet, distributions which care about optimal SELinux support should probably not stabilize on this release. * sd-bus gained support for matches of type "arg0has=", that test for membership of strings in string arrays sent in bus messages. * systemd-resolved now dumps the contents of its DNS and LLMNR caches to the logs on reception of the SIGUSR1 signal. This is useful to debug DNS behaviour. * The coredumpctl tool gained a new --directory= option to operate on journal files in a specific directory. * "systemctl reboot" and related commands gained a new "--message=" option which may be used to set a free-text wall message when shutting down or rebooting the system. This message is also logged, which is useful for figuring out the reason for a reboot or shutdown a posteriori. * The "systemd-resolve-host" tool's -i switch now takes network interface numbers as alternative to interface names. * A new unit file setting for services has been introduced: UtmpMode= allows configuration of how precisely systemd handles utmp and wtmp entries for the service if this is enabled. This allows writing services that appear similar to user sessions in the output of the "w", "who", "last" and "lastlog" tools. * systemd-resolved will now locally synthesize DNS resource records for the "localhost" and "gateway" domains as well as the local hostname. This should ensure that clients querying RRs via resolved will get similar results as those going via NSS, if nss-myhostname is enabled. Contributions from: Alastair Hughes, Alex Crawford, Daniel Mack, David Herrmann, Dimitri John Ledkov, Eric Kostrowski, Evgeny Vereshchagin, Felipe Sateler, HATAYAMA Daisuke, Jan Pokorný, Jan Synacek, Johnny Robeson, Karel Zak, Kay Sievers, Kefeng Wang, Lennart Poettering, Major Hayden, Marcel Holtmann, Markus Elfring, Martin Mikkelsen, Martin Pitt, Matt Turner, Maxim Mikityanskiy, Michael Biebl, Namhyung Kim, Nicolas Cornu, Owen W. Taylor, Patrik Flykt, Peter Hutterer, reverendhomer, Richard Maw, Ronny Chevalier, Seth Jennings, Stef Walter, Susant Sahani, Thomas Blume, Thomas Hindoe Paaboel Andersen, Thomas Meyer, Tom Gundersen, Vincent Batts, WaLyong Cho, Zbigniew Jędrzejewski-Szmek -- Berlin, 2015-08-27 CHANGES WITH 224: * The systemd-efi-boot-generator functionality was merged into systemd-gpt-auto-generator. * systemd-networkd now supports Group Policy for vxlan devices. It can be enabled via the new boolean configuration option called 'GroupPolicyExtension='. Contributions from: Andreas Kempf, Christian Hesse, Daniel Mack, David Herrmann, Herman Fries, Johannes Nixdorf, Kay Sievers, Lennart Poettering, Peter Hutterer, Susant Sahani, Tom Gundersen -- Berlin, 2015-07-31 CHANGES WITH 223: * The python-systemd code has been removed from the systemd repository. A new repository has been created which accommodates the code from now on, and we kindly ask distributions to create a separate package for this: https://github.com/systemd/python-systemd * The systemd daemon will now reload its main configuration (/etc/systemd/system.conf) on daemon-reload. * sd-dhcp now exposes vendor specific extensions via sd_dhcp_lease_get_vendor_specific(). * systemd-networkd gained a number of new configuration options. - A new boolean configuration option for TAP devices called 'VNetHeader='. If set, the IFF_VNET_HDR flag is set for the device, thus allowing to send and receive GSO packets. - A new tunnel configuration option called 'CopyDSCP='. If enabled, the DSCP field of ip6 tunnels is copied into the decapsulated packet. - A set of boolean bridge configuration options were added. 'UseBPDU=', 'HairPin=', 'FastLeave=', 'AllowPortToBeRoot=', and 'UnicastFlood=' are now parsed by networkd and applied to the respective bridge link device via the respective IFLA_BRPORT_* netlink attribute. - A new string configuration option to override the hostname sent to a DHCP server, called 'Hostname='. If set and 'SendHostname=' is true, networkd will use the configured hostname instead of the system hostname when sending DHCP requests. - A new tunnel configuration option called 'IPv6FlowLabel='. If set, networkd will configure the IPv6 flow-label of the tunnel device according to RFC2460. - The 'macvtap' virtual network devices are now supported, similar to the already supported 'macvlan' devices. * systemd-resolved now implements RFC5452 to improve resilience against cache poisoning. Additionally, source port randomization is enabled by default to further protect against DNS spoofing attacks. * nss-mymachines now supports translating UIDs and GIDs of running containers with user-namespaces enabled. If a container 'foo' translates a host uid 'UID' to the container uid 'TUID', then nss-mymachines will also map uid 'UID' to/from username 'vu-foo-TUID' (with 'foo' and 'TUID' replaced accordingly). Similarly, groups are mapped as 'vg-foo-TGID'. Contributions from: Beniamino Galvani, cee1, Christian Hesse, Daniel Buch, Daniel Mack, daurnimator, David Herrmann, Dimitri John Ledkov, HATAYAMA Daisuke, Ivan Shapovalov, Jan Alexander Steffens (heftig), Johan Ouwerkerk, Jose Carlos Venegas Munoz, Karel Zak, Kay Sievers, Lennart Poettering, Lidong Zhong, Martin Pitt, Michael Biebl, Michael Olbrich, Michal Schmidt, Michal Sekletar, Mike Gilbert, Namhyung Kim, Nick Owens, Peter Hutterer, Richard Maw, Steven Allen, Sungbae Yoo, Susant Sahani, Thomas Blume, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Torstein Husebø, Umut Tezduyar Lindskog, Vito Caputo, Vivenzio Pagliari, Zbigniew Jędrzejewski-Szmek -- Berlin, 2015-07-29 CHANGES WITH 222: * udev does not longer support the WAIT_FOR_SYSFS= key in udev rules. There are no known issues with current sysfs, and udev does not need or should be used to work around such bugs. * udev does no longer enable USB HID power management. Several reports indicate, that some devices cannot handle that setting. * The udev accelerometer helper was removed. The functionality is now fully included in iio-sensor-proxy. But this means, older iio-sensor-proxy versions will no longer provide accelerometer/orientation data with this systemd version. Please upgrade iio-sensor-proxy to version 1.0. * networkd gained a new configuration option IPv6PrivacyExtensions= which enables IPv6 privacy extensions (RFC 4941, "Privacy Extensions for Stateless Address") on selected networks. * For the sake of fewer build-time dependencies and less code in the main repository, the python bindings are about to be removed in the next release. A new repository has been created which accommodates the code from now on, and we kindly ask distributions to create a separate package for this. The removal will take place in v223. https://github.com/systemd/python-systemd Contributions from: Abdo Roig-Maranges, Andrew Eikum, Bastien Nocera, Cédric Delmas, Christian Hesse, Christos Trochalakis, Daniel Mack, daurnimator, David Herrmann, Dimitri John Ledkov, Eric Biggers, Eric Cook, Felipe Sateler, Geert Jansen, Gerd Hoffmann, Gianpaolo Macario, Greg Kroah-Hartman, Iago López Galeiras, Jan Alexander Steffens (heftig), Jan Engelhardt, Jay Strict, Kay Sievers, Lennart Poettering, Markus Knetschke, Martin Pitt, Michael Biebl, Michael Marineau, Michal Sekletar, Miguel Bernal Marin, Peter Hutterer, Richard Maw, rinrinne, Susant Sahani, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Torstein Husebø, Vedran Miletić, WaLyong Cho, Zbigniew Jędrzejewski-Szmek -- Berlin, 2015-07-07 CHANGES WITH 221: * The sd-bus.h and sd-event.h APIs have now been declared stable and have been added to the official interface of libsystemd.so. sd-bus implements an alternative D-Bus client library, that is relatively easy to use, very efficient and supports both classic D-Bus as well as kdbus as transport backend. sd-event is a generic event loop abstraction that is built around Linux epoll, but adds features such as event prioritization or efficient timer handling. Both APIs are good choices for C programs looking for a bus and/or event loop implementation that is minimal and does not have to be portable to other kernels. * kdbus support is no longer compile-time optional. It is now always built-in. However, it can still be disabled at runtime using the kdbus=0 kernel command line setting, and that setting may be changed to default to off, by specifying --disable-kdbus at build-time. Note though that the kernel command line setting has no effect if the kdbus.ko kernel module is not installed, in which case kdbus is (obviously) also disabled. We encourage all downstream distributions to begin testing kdbus by adding it to the kernel images in the development distributions, and leaving kdbus support in systemd enabled. * The minimal required util-linux version has been bumped to 2.26. * Support for chkconfig (--enable-chkconfig) was removed in favor of calling an abstraction tool /lib/systemd/systemd-sysv-install. This needs to be implemented for your distribution. See "SYSV INIT.D SCRIPTS" in README for details. * If there's a systemd unit and a SysV init script for the same service name, and the user executes "systemctl enable" for it (or a related call), then this will now enable both (or execute the related operation on both), not just the unit. * The libudev API documentation has been converted from gtkdoc into man pages. * gudev has been removed from the systemd tree, it is now an external project. * The systemd-cgtop tool learnt a new --raw switch to generate "raw" (machine parsable) output. * networkd's IPForwarding= .network file setting learnt the new setting "kernel", which ensures that networkd does not change the IP forwarding sysctl from the default kernel state. * The systemd-logind bus API now exposes a new boolean property "Docked" that reports whether logind considers the system "docked", i.e. connected to a docking station or not. Contributions from: Alex Crawford, Andreas Pokorny, Andrei Borzenkov, Charles Duffy, Colin Guthrie, Cristian Rodríguez, Daniele Medri, Daniel Hahler, Daniel Mack, David Herrmann, David Mohr, Dimitri John Ledkov, Djalal Harouni, dslul, Ed Swierk, Eric Cook, Filipe Brandenburger, Gianpaolo Macario, Harald Hoyer, Iago López Galeiras, Igor Vuk, Jan Synacek, Jason Pleau, Jason S. McMullan, Jean Delvare, Jeff Huang, Jonathan Boulle, Karel Zak, Kay Sievers, kloun, Lennart Poettering, Marc-Antoine Perennou, Marcel Holtmann, Mario Limonciello, Martin Pitt, Michael Biebl, Michael Olbrich, Michal Schmidt, Mike Gilbert, Nick Owens, Pablo Lezaeta Reyes, Patrick Donnelly, Pavel Odvody, Peter Hutterer, Philip Withnall, Ronny Chevalier, Simon McVittie, Susant Sahani, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Torstein Husebø, Umut Tezduyar Lindskog, Viktar Vauchkevich, Werner Fink, Zbigniew Jędrzejewski-Szmek -- Berlin, 2015-06-19 CHANGES WITH 220: * The gudev library has been extracted into a separate repository available at: https://git.gnome.org/browse/libgudev/ It is now managed as part of the Gnome project. Distributions are recommended to pass --disable-gudev to systemd and use gudev from the Gnome project instead. gudev is still included in systemd, for now. It will be removed soon, though. Please also see the announcement-thread on systemd-devel: http://lists.freedesktop.org/archives/systemd-devel/2015-May/032070.html * systemd now exposes a CPUUsageNSec= property for each service unit on the bus, that contains the overall consumed CPU time of a service (the sum of what each process of the service consumed). This value is only available if CPUAccounting= is turned on for a service, and is then shown in the "systemctl status" output. * Support for configuring alternative mappings of the old SysV runlevels to systemd targets has been removed. They are now hardcoded in a way that runlevels 2, 3, 4 all map to multi-user.target and 5 to graphical.target (which previously was already the default behaviour). * The auto-mounter logic gained support for mount point expiry, using a new TimeoutIdleSec= setting in .automount units. (Also available as x-systemd.idle-timeout= in /etc/fstab). * The EFI System Partition (ESP) as mounted to /boot by systemd-efi-boot-generator will now be unmounted automatically after 2 minutes of not being used. This should minimize the risk of ESP corruptions. * New /etc/fstab options x-systemd.requires= and x-systemd.requires-mounts-for= are now supported to express additional dependencies for mounts. This is useful for journalling file systems that support external journal devices or overlay file systems that require underlying file systems to be mounted. * systemd does not support direct live-upgrades (via systemctl daemon-reexec) from versions older than v44 anymore. As no distribution we are aware of shipped such old versions in a stable release this should not be problematic. * When systemd forks off a new per-connection service instance it will now set the $REMOTE_ADDR environment variable to the remote IP address, and $REMOTE_PORT environment variable to the remote IP port. This behaviour is similar to the corresponding environment variables defined by CGI. * systemd-networkd gained support for uplink failure detection. The BindCarrier= option allows binding interface configuration dynamically to the link sense of other interfaces. This is useful to achieve behaviour like in network switches. * systemd-networkd gained support for configuring the DHCP client identifier to use when requesting leases. * systemd-networkd now has a per-network UseNTP= option to configure whether NTP server information acquired via DHCP is passed on to services like systemd-timesyncd. * systemd-networkd gained support for vti6 tunnels. * Note that systemd-networkd manages the sysctl variable /proc/sys/net/ipv[46]/conf/*/forwarding for each interface it is configured for since v219. The variable controls IP forwarding, and is a per-interface alternative to the global /proc/sys/net/ipv[46]/ip_forward. This setting is configurable in the IPForward= option, which defaults to "no". This means if networkd is used for an interface it is no longer sufficient to set the global sysctl option to turn on IP forwarding! Instead, the .network file option IPForward= needs to be turned on! Note that the implementation of this behaviour was broken in v219 and has been fixed in v220. * Many bonding and vxlan options are now configurable in systemd-networkd. * systemd-nspawn gained a new --property= setting to set unit properties for the container scope. This is useful for setting resource parameters (e.g "CPUShares=500") on containers started from the command line. * systemd-nspawn gained a new --private-users= switch to make use of user namespacing available on recent Linux kernels. * systemd-nspawn may now be called as part of a shell pipeline in which case the pipes used for stdin and stdout are passed directly to the process invoked in the container, without indirection via a pseudo tty. * systemd-nspawn gained a new switch to control the UNIX signal to use when killing the init process of the container when shutting down. * systemd-nspawn gained a new --overlay= switch for mounting overlay file systems into the container using the new kernel overlayfs support. * When a container image is imported via systemd-importd and the host file system is not btrfs, a loopback block device file is created in /var/lib/machines.raw with a btrfs file system inside. It is then mounted to /var/lib/machines to enable btrfs features for container management. The loopback file and btrfs file system is grown as needed when container images are imported via systemd-importd. * systemd-machined/systemd-importd gained support for btrfs quota, to enforce container disk space limits on disk. This is exposed in "machinectl set-limit". * systemd-importd now can import containers from local .tar, .raw and .qcow2 images, and export them to .tar and .raw. It can also import dkr v2 images now from the network (on top of v1 as before). * systemd-importd gained support for verifying downloaded images with gpg2 (previously only gpg1 was supported). * systemd-machined, systemd-logind, systemd: most bus calls are now accessible to unprivileged processes via PolicyKit. Also, systemd-logind will now allow users to kill their own sessions without further privileges or authorization. * systemd-shutdownd has been removed. This service was previously responsible for implementing scheduled shutdowns as exposed in /usr/bin/shutdown's time parameter. This functionality has now been moved into systemd-logind and is accessible via a bus interface. * "systemctl reboot" gained a new switch --firmware-setup that can be used to reboot into the EFI firmware setup, if that is available. systemd-logind now exposes an API on the bus to trigger such reboots, in case graphical desktop UIs want to cover this functionality. * "systemctl enable", "systemctl disable" and "systemctl mask" now support a new "--now" switch. If specified the units that are enabled will also be started, and the ones disabled/masked also stopped. * The Gummiboot EFI boot loader tool has been merged into systemd, and renamed to "systemd-boot". The bootctl tool has been updated to support systemd-boot. * An EFI kernel stub has been added that may be used to create kernel EFI binaries that contain not only the actual kernel, but also an initrd, boot splash, command line and OS release information. This combined binary can then be signed as a single image, so that the firmware can verify it all in one step. systemd-boot has special support for EFI binaries created like this and can extract OS release information from them and show them in the boot menu. This functionality is useful to implement cryptographically verified boot schemes. * Optional support has been added to systemd-fsck to pass fsck's progress report to an AF_UNIX socket in the file system. * udev will no longer create device symlinks for all block devices by default. A blacklist for excluding special block devices from this logic has been turned into a whitelist that requires picking block devices explicitly that require device symlinks. * A new (currently still internal) API sd-device.h has been added to libsystemd. This modernized API is supposed to replace libudev eventually. In fact, already much of libudev is now just a wrapper around sd-device.h. * A new hwdb database for storing metadata about pointing stick devices has been added. * systemd-tmpfiles gained support for setting file attributes similar to the "chattr" tool with new 'h' and 'H' lines. * systemd-journald will no longer unconditionally set the btrfs NOCOW flag on new journal files. This is instead done with tmpfiles snippet using the new 'h' line type. This allows easy disabling of this logic, by masking the journal-nocow.conf tmpfiles file. * systemd-journald will now translate audit message types to human readable identifiers when writing them to the journal. This should improve readability of audit messages. * The LUKS logic gained support for the offset= and skip= options in /etc/crypttab, as previously implemented by Debian. * /usr/lib/os-release gained a new optional field VARIANT= for distributions that support multiple variants (such as a desktop edition, a server edition, ...) Contributions from: Aaro Koskinen, Adam Goode, Alban Crequy, Alberto Fanjul Alonso, Alexander Sverdlin, Alex Puchades, Alin Rauta, Alison Chaiken, Andrew Jones, Arend van Spriel, Benedikt Morbach, Benjamin Franzke, Benjamin Tissoires, Blaž Tomažič, Chris Morgan, Chris Morin, Colin Walters, Cristian Rodríguez, Daniel Buch, Daniel Drake, Daniele Medri, Daniel Mack, Daniel Mustieles, daurnimator, Davide Bettio, David Herrmann, David Strauss, Didier Roche, Dimitri John Ledkov, Eric Cook, Gavin Li, Goffredo Baroncelli, Hannes Reinecke, Hans de Goede, Hans-Peter Deifel, Harald Hoyer, Iago López Galeiras, Ivan Shapovalov, Jan Engelhardt, Jan Janssen, Jan Pazdziora, Jan Synacek, Jasper St. Pierre, Jay Faulkner, John Paul Adrian Glaubitz, Jonathon Gilbert, Karel Zak, Kay Sievers, Koen Kooi, Lennart Poettering, Lubomir Rintel, Lucas De Marchi, Lukas Nykryn, Lukas Rusak, Lukasz Skalski, Łukasz Stelmach, Mantas Mikulėnas, Marc-Antoine Perennou, Marcel Holtmann, Martin Pitt, Mathieu Chevrier, Matthew Garrett, Michael Biebl, Michael Marineau, Michael Olbrich, Michal Schmidt, Michal Sekletar, Mirco Tischler, Nir Soffer, Patrik Flykt, Pavel Odvody, Peter Hutterer, Peter Lemenkov, Peter Waller, Piotr Drąg, Raul Gutierrez S, Richard Maw, Ronny Chevalier, Ross Burton, Sebastian Rasmussen, Sergey Ptashnick, Seth Jennings, Shawn Landden, Simon Farnsworth, Stefan Junker, Stephen Gallagher, Susant Sahani, Sylvain Plantefève, Thomas Haller, Thomas Hindoe Paaboel Andersen, Tobias Hunger, Tom Gundersen, Torstein Husebø, Umut Tezduyar Lindskog, Will Woods, Zachary Cook, Zbigniew Jędrzejewski-Szmek -- Berlin, 2015-05-22 CHANGES WITH 219: * Introduce a new API "sd-hwdb.h" for querying the hardware metadata database. With this minimal interface one can query and enumerate the udev hwdb, decoupled from the old libudev library. libudev's interface for this is now only a wrapper around sd-hwdb. A new tool systemd-hwdb has been added to interface with and update the database. * When any of systemd's tools copies files (for example due to tmpfiles' C lines) a btrfs reflink will attempted first, before bytewise copying is done. * systemd-nspawn gained a new --ephemeral switch. When specified a btrfs snapshot is taken of the container's root directory, and immediately removed when the container terminates again. Thus, a container can be started whose changes never alter the container's root directory, and are lost on container termination. This switch can also be used for starting a container off the root file system of the host without affecting the host OS. This switch is only available on btrfs file systems. * systemd-nspawn gained a new --template= switch. It takes the path to a container tree to use as template for the tree specified via --directory=, should that directory be missing. This allows instantiating containers dynamically, on first run. This switch is only available on btrfs file systems. * When a .mount unit refers to a mount point on which multiple mounts are stacked, and the .mount unit is stopped all of the stacked mount points will now be unmounted until no mount point remains. * systemd now has an explicit notion of supported and unsupported unit types. Jobs enqueued for unsupported unit types will now fail with an "unsupported" error code. More specifically .swap, .automount and .device units are not supported in containers, .busname units are not supported on non-kdbus systems. .swap and .automount are also not supported if their respective kernel compile time options are disabled. * machinectl gained support for two new "copy-from" and "copy-to" commands for copying files from a running container to the host or vice versa. * machinectl gained support for a new "bind" command to bind mount host directories into local containers. This is currently only supported for nspawn containers. * networkd gained support for configuring bridge forwarding database entries (fdb) from .network files. * A new tiny daemon "systemd-importd" has been added that can download container images in tar, raw, qcow2 or dkr formats, and make them available locally in /var/lib/machines, so that they can run as nspawn containers. The daemon can GPG verify the downloads (not supported for dkr, since it has no provisions for verifying downloads). It will transparently decompress bz2, xz, gzip compressed downloads if necessary, and restore sparse files on disk. The daemon uses privilege separation to ensure the actual download logic runs with fewer privileges than the daemon itself. machinectl has gained new commands "pull-tar", "pull-raw" and "pull-dkr" to make the functionality of importd available to the user. With this in place the Fedora and Ubuntu "Cloud" images can be downloaded and booted as containers unmodified (the Fedora images lack the appropriate GPG signature files currently, so they cannot be verified, but this will change soon, hopefully). Note that downloading images is currently only fully supported on btrfs. * machinectl is now able to list container images found in /var/lib/machines, along with some metadata about sizes of disk and similar. If the directory is located on btrfs and quota is enabled, this includes quota display. A new command "image-status" has been added that shows additional information about images. * machinectl is now able to clone container images efficiently, if the underlying file system (btrfs) supports it, with the new "machinectl list-images" command. It also gained commands for renaming and removing images, as well as marking them read-only or read-write (supported also on legacy file systems). * networkd gained support for collecting LLDP network announcements, from hardware that supports this. This is shown in networkctl output. * systemd-run gained support for a new -t (--pty) switch for invoking a binary on a pty whose input and output is connected to the invoking terminal. This allows executing processes as system services while interactively communicating with them via the terminal. Most interestingly this is supported across container boundaries. Invoking "systemd-run -t /bin/bash" is an alternative to running a full login session, the difference being that the former will not register a session, nor go through the PAM session setup. * tmpfiles gained support for a new "v" line type for creating btrfs subvolumes. If the underlying file system is a legacy file system, this automatically degrades to creating a normal directory. Among others /var/lib/machines is now created like this at boot, should it be missing. * The directory /var/lib/containers/ has been deprecated and been replaced by /var/lib/machines. The term "machines" has been used in the systemd context as generic term for both VMs and containers, and hence appears more appropriate for this, as the directory can also contain raw images bootable via qemu/kvm. * systemd-nspawn when invoked with -M but without --directory= or --image= is now capable of searching for the container root directory, subvolume or disk image automatically, in /var/lib/machines. systemd-nspawn@.service has been updated to make use of this, thus allowing it to be used for raw disk images, too. * A new machines.target unit has been introduced that is supposed to group all containers/VMs invoked as services on the system. systemd-nspawn@.service has been updated to integrate with that. * machinectl gained a new "start" command, for invoking a container as a service. "machinectl start foo" is mostly equivalent to "systemctl start systemd-nspawn@foo.service", but handles escaping in a nicer way. * systemd-nspawn will now mount most of the cgroupfs tree read-only into each container, with the exception of the container's own subtree in the name=systemd hierarchy. * journald now sets the special FS_NOCOW file flag for its journal files. This should improve performance on btrfs, by avoiding heavy fragmentation when journald's write-pattern is used on COW file systems. It degrades btrfs' data integrity guarantees for the files to the same levels as for ext3/ext4 however. This should be OK though as journald does its own data integrity checks and all its objects are checksummed on disk. Also, journald should handle btrfs disk full events a lot more gracefully now, by processing SIGBUS errors, and not relying on fallocate() anymore. * When journald detects that journal files it is writing to have been deleted it will immediately start new journal files. * systemd now provides a way to store file descriptors per-service in PID 1.This is useful for daemons to ensure that fds they require are not lost during a daemon restart. The fds are passed to the daemon on the next invocation in the same way socket activation fds are passed. This is now used by journald to ensure that the various sockets connected to all the system's stdout/stderr are not lost when journald is restarted. File descriptors may be stored in PID 1 via the sd_pid_notify_with_fds() API, an extension to sd_notify(). Note that a limit is enforced on the number of fds a service can store in PID 1, and it defaults to 0, so that no fds may be stored, unless this is explicitly turned on. * The default TERM variable to use for units connected to a terminal, when no other value is explicitly is set is now vt220 rather than vt102. This should be fairly safe still, but allows PgUp/PgDn work. * The /etc/crypttab option header= as known from Debian is now supported. * "loginctl user-status" and "loginctl session-status" will now show the last 10 lines of log messages of the user/session following the status output. Similar, "machinectl status" will show the last 10 log lines associated with a virtual machine or container service. (Note that this is usually not the log messages done in the VM/container itself, but simply what the container manager logs. For nspawn this includes all console output however.) * "loginctl session-status" without further argument will now show the status of the session of the caller. Similar, "lock-session", "unlock-session", "activate", "enable-linger", "disable-linger" may now be called without session/user parameter in which case they apply to the caller's session/user. * An X11 session scriptlet is now shipped that uploads $DISPLAY and $XAUTHORITY into the environment of the systemd --user daemon if a session begins. This should improve compatibility with X11 enabled applications run as systemd user services. * Generators are now subject to masking via /etc and /run, the same way as unit files. * networkd .network files gained support for configuring per-link IPv4/IPv6 packet forwarding as well as IPv4 masquerading. This is by default turned on for veth links to containers, as registered by systemd-nspawn. This means that nspawn containers run with --network-veth will now get automatic routed access to the host's networks without any further configuration or setup, as long as networkd runs on the host. * systemd-nspawn gained the --port= (-p) switch to expose TCP or UDP posts of a container on the host. With this in place it is possible to run containers with private veth links (--network-veth), and have their functionality exposed on the host as if their services were running directly on the host. * systemd-nspawn's --network-veth switch now gained a short version "-n", since with the changes above it is now truly useful out-of-the-box. The systemd-nspawn@.service has been updated to make use of it too by default. * systemd-nspawn will now maintain a per-image R/W lock, to ensure that the same image is not started more than once writable. (It's OK to run an image multiple times simultaneously in read-only mode.) * systemd-nspawn's --image= option is now capable of dissecting and booting MBR and GPT disk images that contain only a single active Linux partition. Previously it supported only GPT disk images with proper GPT type IDs. This allows running cloud images from major distributions directly with systemd-nspawn, without modification. * In addition to collecting mouse dpi data in the udev hardware database, there's now support for collecting angle information for mouse scroll wheels. The database is supposed to guarantee similar scrolling behavior on mice that it knows about. There's also support for collecting information about Touchpad types. * udev's input_id built-in will now also collect touch screen dimension data and attach it to probed devices. * /etc/os-release gained support for a Distribution Privacy Policy link field. * networkd gained support for creating "ipvlan", "gretap", "ip6gre", "ip6gretap" and "ip6tnl" network devices. * systemd-tmpfiles gained support for "a" lines for setting ACLs on files. * systemd-nspawn will now mount /tmp in the container to tmpfs, automatically. * systemd now exposes the memory.usage_in_bytes cgroup attribute and shows it for each service in the "systemctl status" output, if available. * When the user presses Ctrl-Alt-Del more than 7x within 2s an immediate reboot is triggered. This useful if shutdown is hung and is unable to complete, to expedite the operation. Note that this kind of reboot will still unmount all file systems, and hence should not result in fsck being run on next reboot. * A .device unit for an optical block device will now be considered active only when a medium is in the drive. Also, mount units are now bound to their backing devices thus triggering automatic unmounting when devices become unavailable. With this in place systemd will now automatically unmount left-over mounts when a CD-ROM is ejected or an USB stick is yanked from the system. * networkd-wait-online now has support for waiting for specific interfaces only (with globbing), and for giving up after a configurable timeout. * networkd now exits when idle. It will be automatically restarted as soon as interfaces show up, are removed or change state. networkd will stay around as long as there is at least one DHCP state machine or similar around, that keep it non-idle. * networkd may now configure IPv6 link-local addressing in addition to IPv4 link-local addressing. * The IPv6 "token" for use in SLAAC may now be configured for each .network interface in networkd. * Routes configured with networkd may now be assigned a scope in .network files. * networkd's [Match] sections now support globbing and lists of multiple space-separated matches per item. Contributions from: Alban Crequy, Alin Rauta, Andrey Chaser, Bastien Nocera, Bruno Bottazzini, Carlos Garnacho, Carlos Morata Castillo, Chris Atkinson, Chris J. Arges, Christian Kirbach, Christian Seiler, Christoph Brill, Colin Guthrie, Colin Walters, Cristian Rodríguez, Daniele Medri, Daniel Mack, Dave Reisner, David Herrmann, Djalal Harouni, Erik Auerswald, Filipe Brandenburger, Frank Theile, Gabor Kelemen, Gabriel de Perthuis, Harald Hoyer, Hui Wang, Ivan Shapovalov, Jan Engelhardt, Jan Synacek, Jay Faulkner, Johannes Hölzl, Jonas Ådahl, Jonathan Boulle, Josef Andersson, Kay Sievers, Ken Werner, Lennart Poettering, Lucas De Marchi, Lukas Märdian, Lukas Nykryn, Lukasz Skalski, Luke Shumaker, Mantas Mikulėnas, Manuel Mendez, Marcel Holtmann, Marc Schmitzer, Marko Myllynen, Martin Pitt, Maxim Mikityanskiy, Michael Biebl, Michael Marineau, Michael Olbrich, Michal Schmidt, Mindaugas Baranauskas, Moez Bouhlel, Naveen Kumar, Patrik Flykt, Paul Martin, Peter Hutterer, Peter Mattern, Philippe De Swert, Piotr Drąg, Rafael Ferreira, Rami Rosen, Robert Milasan, Ronny Chevalier, Sangjung Woo, Sebastien Bacher, Sergey Ptashnick, Shawn Landden, Stéphane Graber, Susant Sahani, Sylvain Plantefève, Thomas Hindoe Paaboel Andersen, Tim JP, Tom Gundersen, Topi Miettinen, Torstein Husebø, Umut Tezduyar Lindskog, Veres Lajos, Vincent Batts, WaLyong Cho, Wieland Hoffmann, Zbigniew Jędrzejewski-Szmek -- Berlin, 2015-02-16 CHANGES WITH 218: * When querying unit file enablement status (for example via "systemctl is-enabled"), a new state "indirect" is now known which indicates that a unit might not be enabled itself, but another unit listed in its Also= setting might be. * Similar to the various existing ConditionXYZ= settings for units, there are now matching AssertXYZ= settings. While failing conditions cause a unit to be skipped, but its job to succeed, failing assertions declared like this will cause a unit start operation and its job to fail. * hostnamed now knows a new chassis type "embedded". * systemctl gained a new "edit" command. When used on a unit file, this allows extending unit files with .d/ drop-in configuration snippets or editing the full file (after copying it from /usr/lib to /etc). This will invoke the user's editor (as configured with $EDITOR), and reload the modified configuration after editing. * "systemctl status" now shows the suggested enablement state for a unit, as declared in the (usually vendor-supplied) system preset files. * nss-myhostname will now resolve the single-label host name "gateway" to the locally configured default IP routing gateways, ordered by their metrics. This assigns a stable name to the used gateways, regardless which ones are currently configured. Note that the name will only be resolved after all other name sources (if nss-myhostname is configured properly) and should hence not negatively impact systems that use the single-label host name "gateway" in other contexts. * systemd-inhibit now allows filtering by mode when listing inhibitors. * Scope and service units gained a new "Delegate" boolean property, which, when set, allows processes running inside the unit to further partition resources. This is primarily useful for systemd user instances as well as container managers. * journald will now pick up audit messages directly from the kernel, and log them like any other log message. The audit fields are split up and fully indexed. This means that journalctl in many ways is now a (nicer!) alternative to ausearch, the traditional audit client. Note that this implements only a minimal audit client. If you want the special audit modes like reboot-on-log-overflow, please use the traditional auditd instead, which can be used in parallel to journald. * The ConditionSecurity= unit file option now understands the special string "audit" to check whether auditing is available. * journalctl gained two new commands --vacuum-size= and --vacuum-time= to delete old journal files until the remaining ones take up no more than the specified size on disk, or are not older than the specified time. * A new, native PPPoE library has been added to sd-network, systemd's library of light-weight networking protocols. This library will be used in a future version of networkd to enable PPPoE communication without an external pppd daemon. * The busctl tool now understands a new "capture" verb that works similar to "monitor", but writes a packet capture trace to STDOUT that can be redirected to a file which is compatible with libcap's capture file format. This can then be loaded in Wireshark and similar tools to inspect bus communication. * The busctl tool now understands a new "tree" verb that shows the object trees of a specific service on the bus, or of all services. * The busctl tool now understands a new "introspect" verb that shows all interfaces and members of objects on the bus, including their signature and values. This is particularly useful to get more information about bus objects shown by the new "busctl tree" command. * The busctl tool now understands new verbs "call", "set-property" and "get-property" for invoking bus method calls, setting and getting bus object properties in a friendly way. * busctl gained a new --augment-creds= argument that controls whether the tool shall augment credential information it gets from the bus with data from /proc, in a possibly race-ful way. * nspawn's --link-journal= switch gained two new values "try-guest" and "try-host" that work like "guest" and "host", but do not fail if the host has no persistent journalling enabled. -j is now equivalent to --link-journal=try-guest. * macvlan network devices created by nspawn will now have stable MAC addresses. * A new SmackProcessLabel= unit setting has been added, which controls the SMACK security label processes forked off by the respective unit shall use. * If compiled with --enable-xkbcommon, systemd-localed will verify x11 keymap settings by compiling the given keymap. It will spew out warnings if the compilation fails. This requires libxkbcommon to be installed. * When a coredump is collected, a larger number of metadata fields is now collected and included in the journal records created for it. More specifically, control group membership, environment variables, memory maps, working directory, chroot directory, /proc/$PID/status, and a list of open file descriptors is now stored in the log entry. * The udev hwdb now contains DPI information for mice. For details see: http://who-t.blogspot.de/2014/12/building-a-dpi-database-for-mice.html * All systemd programs that read standalone configuration files in /etc now also support a corresponding series of .conf.d configuration directories in /etc/, /run/, /usr/local/lib/, /usr/lib/, and (if configured with --enable-split-usr) /lib/. In particular, the following configuration files now have corresponding configuration directories: system.conf user.conf, logind.conf, journald.conf, sleep.conf, bootchart.conf, coredump.conf, resolved.conf, timesyncd.conf, journal-remote.conf, and journal-upload.conf. Note that distributions should use the configuration directories in /usr/lib/; the directories in /etc/ are reserved for the system administrator. * systemd-rfkill will no longer take the rfkill device name into account when storing rfkill state on disk, as the name might be dynamically assigned and not stable. Instead, the ID_PATH udev variable combined with the rfkill type (wlan, bluetooth, ...) is used. * A new service systemd-machine-id-commit.service has been added. When used on systems where /etc is read-only during boot, and /etc/machine-id is not initialized (but an empty file), this service will copy the temporary machine ID created as replacement into /etc after the system is fully booted up. This is useful for systems that are freshly installed with a non-initialized machine ID, but should get a fixed machine ID for subsequent boots. * networkd's .netdev files now provide a large set of configuration parameters for VXLAN devices. Similarly, the bridge port cost parameter is now configurable in .network files. There's also new support for configuring IP source routing. networkd .link files gained support for a new OriginalName= match that is useful to match against the original interface name the kernel assigned. .network files may include MTU= and MACAddress= fields for altering the MTU and MAC address while being connected to a specific network interface. * The LUKS logic gained supported for configuring UUID-specific key files. There's also new support for naming LUKS device from the kernel command line, using the new luks.name= argument. * Timer units may now be transiently created via the bus API (this was previously already available for scope and service units). In addition it is now possible to create multiple transient units at the same time with a single bus call. The "systemd-run" tool has been updated to make use of this for running commands on a specified time, in at(1)-style. * tmpfiles gained support for "t" lines, for assigning extended attributes to files. Among other uses this may be used to assign SMACK labels to files. Contributions from: Alin Rauta, Alison Chaiken, Andrej Manduch, Bastien Nocera, Chris Atkinson, Chris Leech, Chris Mayo, Colin Guthrie, Colin Walters, Cristian Rodríguez, Daniele Medri, Daniel Mack, Dan Williams, Dan Winship, Dave Reisner, David Herrmann, Didier Roche, Felipe Sateler, Gavin Li, Hans de Goede, Harald Hoyer, Iago López Galeiras, Ivan Shapovalov, Jakub Filak, Jan Janssen, Jan Synacek, Joe Lawrence, Josh Triplett, Kay Sievers, Lennart Poettering, Lukas Nykryn, Łukasz Stelmach, Maciej Wereski, Mantas Mikulėnas, Marcel Holtmann, Martin Pitt, Maurizio Lombardi, Michael Biebl, Michael Chapman, Michael Marineau, Michal Schmidt, Michal Sekletar, Olivier Brunel, Patrik Flykt, Peter Hutterer, Przemyslaw Kedzierski, Rami Rosen, Ray Strode, Richard Schütz, Richard W.M. Jones, Ronny Chevalier, Ross Lagerwall, Sean Young, Stanisław Pitucha, Susant Sahani, Thomas Haller, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Torstein Husebø, Umut Tezduyar Lindskog, Vicente Olivert Riera, WaLyong Cho, Wesley Dawson, Zbigniew Jędrzejewski-Szmek -- Berlin, 2014-12-10 CHANGES WITH 217: * journalctl gained the new options -t/--identifier= to match on the syslog identifier (aka "tag"), as well as --utc to show log timestamps in the UTC timezone. journalctl now also accepts -n/--lines=all to disable line capping in a pager. * journalctl gained a new switch, --flush, that synchronously flushes logs from /run/log/journal to /var/log/journal if persistent storage is enabled. systemd-journal-flush.service now waits until the operation is complete. * Services can notify the manager before they start a reload (by sending RELOADING=1) or shutdown (by sending STOPPING=1). This allows the manager to track and show the internal state of daemons and closes a race condition when the process is still running but has closed its D-Bus connection. * Services with Type=oneshot do not have to have any ExecStart commands anymore. * User units are now loaded also from $XDG_RUNTIME_DIR/systemd/user/. This is similar to the /run/systemd/user directory that was already previously supported, but is under the control of the user. * Job timeouts (i.e. time-outs on the time a job that is queued stays in the run queue) can now optionally result in immediate reboot or power-off actions (JobTimeoutAction= and JobTimeoutRebootArgument=). This is useful on ".target" units, to limit the maximum time a target remains undispatched in the run queue, and to trigger an emergency operation in such a case. This is now used by default to turn off the system if boot-up (as defined by everything in basic.target) hangs and does not complete for at least 15min. Also, if power-off or reboot hang for at least 30min an immediate power-off/reboot operation is triggered. This functionality is particularly useful to increase reliability on embedded devices, but also on laptops which might accidentally get powered on when carried in a backpack and whose boot stays stuck in a hard disk encryption passphrase question. * systemd-logind can be configured to also handle lid switch events even when the machine is docked or multiple displays are attached (HandleLidSwitchDocked= option). * A helper binary and a service have been added which can be used to resume from hibernation in the initramfs. A generator will parse the resume= option on the kernel command line to trigger resume. * A user console daemon systemd-consoled has been added. Currently, it is a preview, and will so far open a single terminal on each session of the user marked as Desktop=systemd-console. * Route metrics can be specified for DHCP routes added by systemd-networkd. * The SELinux context of socket-activated services can be set from the information provided by the networking stack (SELinuxContextFromNet= option). * Userspace firmware loading support has been removed and the minimum supported kernel version is thus bumped to 3.7. * Timeout for udev workers has been increased from 1 to 3 minutes, but a warning will be printed after 1 minute to help diagnose kernel modules that take a long time to load. * Udev rules can now remove tags on devices with TAG-="foobar". * systemd's readahead implementation has been removed. In many circumstances it didn't give expected benefits even for rotational disk drives and was becoming less relevant in the age of SSDs. As none of the developers has been using rotating media anymore, and nobody stepped up to actively maintain this component of systemd it has now been removed. * Swap units can use Options= to specify discard options. Discard options specified for swaps in /etc/fstab are now respected. * Docker containers are now detected as a separate type of virtualization. * The Password Agent protocol gained support for queries where the user input is shown, useful e.g. for user names. systemd-ask-password gained a new --echo option to turn that on. * The default sysctl.d/ snippets will now set: net.core.default_qdisc = fq_codel This selects Fair Queuing Controlled Delay as the default queuing discipline for network interfaces. fq_codel helps fight the network bufferbloat problem. It is believed to be a good default with no tuning required for most workloads. Downstream distributions may override this choice. On 10Gbit servers that do not do forwarding, "fq" may perform better. Systems without a good clocksource should use "pfifo_fast". * If kdbus is enabled during build a new option BusPolicy= is available for service units, that allows locking all service processes into a stricter bus policy, in order to limit access to various bus services, or even hide most of them from the service's view entirely. * networkctl will now show the .network and .link file networkd has applied to a specific interface. * sd-login gained a new API call sd_session_get_desktop() to query which desktop environment has been selected for a session. * UNIX utmp support is now compile-time optional to support legacy-free systems. * systemctl gained two new commands "add-wants" and "add-requires" for pulling in units from specific targets easily. * If the word "rescue" is specified on the kernel command line the system will now boot into rescue mode (aka rescue.target), which was previously available only by specifying "1" or "systemd.unit=rescue.target" on the kernel command line. This new kernel command line option nicely mirrors the already existing "emergency" kernel command line option. * New kernel command line options mount.usr=, mount.usrflags=, mount.usrfstype= have been added that match root=, rootflags=, rootfstype= but allow mounting a specific file system to /usr. * The $NOTIFY_SOCKET is now also passed to control processes of services, not only the main process. * This version reenables support for fsck's -l switch. This means at least version v2.25 of util-linux is required for operation, otherwise dead-locks on device nodes may occur. Again: you need to update util-linux to at least v2.25 when updating systemd to v217. * The "multi-seat-x" tool has been removed from systemd, as its functionality has been integrated into X servers 1.16, and the tool is hence redundant. It is recommended to update display managers invoking this tool to simply invoke X directly from now on, again. * Support for the new ALLOW_INTERACTIVE_AUTHORIZATION D-Bus message flag has been added for all of systemd's PolicyKit authenticated method calls has been added. In particular this now allows optional interactive authorization via PolicyKit for many of PID1's privileged operations such as unit file enabling and disabling. * "udevadm hwdb --update" learnt a new switch "--usr" for placing the rebuilt hardware database in /usr instead of /etc. When used only hardware database entries stored in /usr will be used, and any user database entries in /etc are ignored. This functionality is useful for vendors to ship a pre-built database on systems where local configuration is unnecessary or unlikely. * Calendar time specifications in .timer units now also understand the strings "semi-annually", "quarterly" and "minutely" as shortcuts (in addition to the preexisting "anually", "hourly", ...). * systemd-tmpfiles will now correctly create files in /dev at boot which are marked for creation only at boot. It is recommended to always create static device nodes with 'c!' and 'b!', so that they are created only at boot and not overwritten at runtime. * When the watchdog logic is used for a service (WatchdogSec=) and the watchdog timeout is hit the service will now be terminated with SIGABRT (instead of just SIGTERM), in order to make sure a proper coredump and backtrace is generated. This ensures that hanging services will result in similar coredump/backtrace behaviour as services that hit a segmentation fault. Contributions from: Andreas Henriksson, Andrei Borzenkov, Angus Gibson, Ansgar Burchardt, Ben Wolsieffer, Brandon L. Black, Christian Hesse, Cristian Rodríguez, Daniel Buch, Daniele Medri, Daniel Mack, Dan Williams, Dave Reisner, David Herrmann, David Sommerseth, David Strauss, Emil Renner Berthing, Eric Cook, Evangelos Foutras, Filipe Brandenburger, Gustavo Sverzut Barbieri, Hans de Goede, Harald Hoyer, Hristo Venev, Hugo Grostabussiat, Ivan Shapovalov, Jan Janssen, Jan Synacek, Jonathan Liu, Juho Son, Karel Zak, Kay Sievers, Klaus Purer, Koen Kooi, Lennart Poettering, Lukas Nykryn, Lukasz Skalski, Łukasz Stelmach, Mantas Mikulėnas, Marcel Holtmann, Marius Tessmann, Marko Myllynen, Martin Pitt, Michael Biebl, Michael Marineau, Michael Olbrich, Michael Scherer, Michal Schmidt, Michal Sekletar, Miroslav Lichvar, Patrik Flykt, Philippe De Swert, Piotr Drąg, Rahul Sundaram, Richard Weinberger, Robert Milasan, Ronny Chevalier, Ruben Kerkhof, Santiago Vila, Sergey Ptashnick, Simon McVittie, Sjoerd Simons, Stefan Brüns, Steven Allen, Steven Noonan, Susant Sahani, Sylvain Plantefève, Thomas Hindoe Paaboel Andersen, Timofey Titovets, Tobias Hunger, Tom Gundersen, Torstein Husebø, Umut Tezduyar Lindskog, WaLyong Cho, Zbigniew Jędrzejewski-Szmek -- Berlin, 2014-10-28 CHANGES WITH 216: * timedated no longer reads NTP implementation unit names from /usr/lib/systemd/ntp-units.d/*.list. Alternative NTP implementations should add a Conflicts=systemd-timesyncd.service to their unit files to take over and replace systemd's NTP default functionality. * systemd-sysusers gained a new line type "r" for configuring which UID/GID ranges to allocate system users/groups from. Lines of type "u" may now add an additional column that specifies the home directory for the system user to be created. Also, systemd-sysusers may now optionally read user information from STDIN instead of a file. This is useful for invoking it from RPM preinst scriptlets that need to create users before the first RPM file is installed since these files might need to be owned by them. A new %sysusers_create_inline RPM macro has been introduced to do just that. systemd-sysusers now updates the shadow files as well as the user/group databases, which should enhance compatibility with certain tools like grpck. * A number of bus APIs of PID 1 now optionally consult PolicyKit to permit access for otherwise unprivileged clients under certain conditions. Note that this currently doesn't support interactive authentication yet, but this is expected to be added eventually, too. * /etc/machine-info now has new fields for configuring the deployment environment of the machine, as well as the location of the machine. hostnamectl has been updated with new command to update these fields. * systemd-timesyncd has been updated to automatically acquire NTP server information from systemd-networkd, which might have been discovered via DHCP. * systemd-resolved now includes a caching DNS stub resolver and a complete LLMNR name resolution implementation. A new NSS module "nss-resolve" has been added which can be used instead of glibc's own "nss-dns" to resolve hostnames via systemd-resolved. Hostnames, addresses and arbitrary RRs may be resolved via systemd-resolved D-Bus APIs. In contrast to the glibc internal resolver systemd-resolved is aware of multi-homed system, and keeps DNS server and caches separate and per-interface. Queries are sent simultaneously on all interfaces that have DNS servers configured, in order to properly handle VPNs and local LANs which might resolve separate sets of domain names. systemd-resolved may acquire DNS server information from systemd-networkd automatically, which in turn might have discovered them via DHCP. A tool "systemd-resolve-host" has been added that may be used to query the DNS logic in resolved. systemd-resolved implements IDNA and automatically uses IDNA or UTF-8 encoding depending on whether classic DNS or LLMNR is used as transport. In the next releases we intend to add a DNSSEC and mDNS/DNS-SD implementation to systemd-resolved. * A new NSS module nss-mymachines has been added, that automatically resolves the names of all local registered containers to their respective IP addresses. * A new client tool "networkctl" for systemd-networkd has been added. It currently is entirely passive and will query networking configuration from udev, rtnetlink and networkd, and present it to the user in a very friendly way. Eventually, we hope to extend it to become a full control utility for networkd. * .socket units gained a new DeferAcceptSec= setting that controls the kernels' TCP_DEFER_ACCEPT sockopt for TCP. Similarly, support for controlling TCP keep-alive settings has been added (KeepAliveTimeSec=, KeepAliveIntervalSec=, KeepAliveProbes=). Also, support for turning off Nagle's algorithm on TCP has been added (NoDelay=). * logind learned a new session type "web", for use in projects like Cockpit which register web clients as PAM sessions. * timer units with at least one OnCalendar= setting will now be started only after timer-sync.target has been reached. This way they will not elapse before the system clock has been corrected by a local NTP client or similar. This is particular useful on RTC-less embedded machines, that come up with an invalid system clock. * systemd-nspawn's --network-veth= switch should now result in stable MAC addresses for both the outer and the inner side of the link. * systemd-nspawn gained a new --volatile= switch for running container instances with /etc or /var unpopulated. * The kdbus client code has been updated to use the new Linux 3.17 memfd subsystem instead of the old kdbus-specific one. * systemd-networkd's DHCP client and server now support FORCERENEW. There are also new configuration options to configure the vendor client identifier and broadcast mode for DHCP. * systemd will no longer inform the kernel about the current timezone, as this is necessarily incorrect and racy as the kernel has no understanding of DST and similar concepts. This hence means FAT timestamps will be always considered UTC, similar to what Android is already doing. Also, when the RTC is configured to the local time (rather than UTC) systemd will never synchronize back to it, as this might confuse Windows at a later boot. * systemd-analyze gained a new command "verify" for offline validation of unit files. * systemd-networkd gained support for a couple of additional settings for bonding networking setups. Also, the metric for statically configured routes may now be configured. For network interfaces where this is appropriate the peer IP address may now be configured. * systemd-networkd's DHCP client will no longer request broadcasting by default, as this tripped up some networks. For hardware where broadcast is required the feature should be switched back on using RequestBroadcast=yes. * systemd-networkd will now set up IPv4LL addresses (when enabled) even if DHCP is configured successfully. * udev will now default to respect network device names given by the kernel when the kernel indicates that these are predictable. This behavior can be tweaked by changing NamePolicy= in the relevant .link file. * A new library systemd-terminal has been added that implements full TTY stream parsing and rendering. This library is supposed to be used later on for implementing a full userspace VT subsystem, replacing the current kernel implementation. * A new tool systemd-journal-upload has been added to push journal data to a remote system running systemd-journal-remote. * journald will no longer forward all local data to another running syslog daemon. This change has been made because rsyslog (which appears to be the most commonly used syslog implementation these days) no longer makes use of this, and instead pulls the data out of the journal on its own. Since forwarding the messages to a non-existent syslog server is more expensive than we assumed we have now turned this off. If you run a syslog server that is not a recent rsyslog version, you have to turn this option on again (ForwardToSyslog= in journald.conf). * journald now optionally supports the LZ4 compressor for larger journal fields. This compressor should perform much better than XZ which was the previous default. * machinectl now shows the IP addresses of local containers, if it knows them, plus the interface name of the container. * A new tool "systemd-escape" has been added that makes it easy to escape strings to build unit names and similar. * sd_notify() messages may now include a new ERRNO= field which is parsed and collected by systemd and shown among the "systemctl status" output for a service. * A new component "systemd-firstboot" has been added that queries the most basic systemd information (timezone, hostname, root password) interactively on first boot. Alternatively it may also be used to provision these things offline on OS images installed into directories. * The default sysctl.d/ snippets will now set net.ipv4.conf.default.promote_secondaries=1 This has the benefit of no flushing secondary IP addresses when primary addresses are removed. Contributions from: Ansgar Burchardt, Bastien Nocera, Colin Walters, Dan Dedrick, Daniel Buch, Daniel Korostil, Daniel Mack, Dan Williams, Dave Reisner, David Herrmann, Denis Kenzior, Eelco Dolstra, Eric Cook, Hannes Reinecke, Harald Hoyer, Hong Shick Pak, Hui Wang, Jean-André Santoni, Jóhann B. Guðmundsson, Jon Severinsson, Karel Zak, Kay Sievers, Kevin Wells, Lennart Poettering, Lukas Nykryn, Mantas Mikulėnas, Marc-Antoine Perennou, Martin Pitt, Michael Biebl, Michael Marineau, Michael Olbrich, Michal Schmidt, Michal Sekletar, Miguel Angel Ajo, Mike Gilbert, Olivier Brunel, Robert Schiele, Ronny Chevalier, Simon McVittie, Sjoerd Simons, Stef Walter, Steven Noonan, Susant Sahani, Tanu Kaskinen, Thomas Blume, Thomas Hindoe Paaboel Andersen, Timofey Titovets, Tobias Geerinckx-Rice, Tomasz Torcz, Tom Gundersen, Umut Tezduyar Lindskog, Zbigniew Jędrzejewski-Szmek -- Berlin, 2014-08-19 CHANGES WITH 215: * A new tool systemd-sysusers has been added. This tool creates system users and groups in /etc/passwd and /etc/group, based on static declarative system user/group definitions in /usr/lib/sysusers.d/. This is useful to enable factory resets and volatile systems that boot up with an empty /etc directory, and thus need system users and groups created during early boot. systemd now also ships with two default sysusers.d/ files for the most basic users and groups systemd and the core operating system require. * A new tmpfiles snippet has been added that rebuilds the essential files in /etc on boot, should they be missing. * A directive for ensuring automatic clean-up of /var/cache/man/ has been removed from the default configuration. This line should now be shipped by the man implementation. The necessary change has been made to the man-db implementation. Note that you need to update your man implementation to one that ships this line, otherwise no automatic clean-up of /var/cache/man will take place. * A new condition ConditionNeedsUpdate= has been added that may conditionalize services to only run when /etc or /var are "older" than the vendor operating system resources in /usr. This is useful for reconstructing or updating /etc after an offline update of /usr or a factory reset, on the next reboot. Services that want to run once after such an update or reset should use this condition and order themselves before the new systemd-update-done.service, which will mark the two directories as fully updated. A number of service files have been added making use of this, to rebuild the udev hardware database, the journald message catalog and dynamic loader cache (ldconfig). The systemd-sysusers tool described above also makes use of this now. With this in place it is now possible to start up a minimal operating system with /etc empty cleanly. For more information on the concepts involved see this recent blog story: http://0pointer.de/blog/projects/stateless.html * A new system group "input" has been introduced, and all input device nodes get this group assigned. This is useful for system-level software to get access to input devices. It complements what is already done for "audio" and "video". * systemd-networkd learnt minimal DHCPv4 server support in addition to the existing DHCPv4 client support. It also learnt DHCPv6 client and IPv6 Router Solicitation client support. The DHCPv4 client gained support for static routes passed in from the server. Note that the [DHCPv4] section known in older systemd-networkd versions has been renamed to [DHCP] and is now also used by the DHCPv6 client. Existing .network files using settings of this section should be updated, though compatibility is maintained. Optionally, the client hostname may now be sent to the DHCP server. * networkd gained support for vxlan virtual networks as well as tun/tap and dummy devices. * networkd gained support for automatic allocation of address ranges for interfaces from a system-wide pool of addresses. This is useful for dynamically managing a large number of interfaces with a single network configuration file. In particular this is useful to easily assign appropriate IP addresses to the veth links of a large number of nspawn instances. * RPM macros for processing sysusers, sysctl and binfmt drop-in snippets at package installation time have been added. * The /etc/os-release file should now be placed in /usr/lib/os-release. The old location is automatically created as symlink. /usr/lib is the more appropriate location of this file, since it shall actually describe the vendor operating system shipped in /usr, and not the configuration stored in /etc. * .mount units gained a new boolean SloppyOptions= setting that maps to mount(8)'s -s option which enables permissive parsing of unknown mount options. * tmpfiles learnt a new "L+" directive which creates a symlink but (unlike "L") deletes a pre-existing file first, should it already exist and not already be the correct symlink. Similarly, "b+", "c+" and "p+" directives have been added as well, which create block and character devices, as well as fifos in the filesystem, possibly removing any pre-existing files of different types. * For tmpfiles' "L", "L+", "C" and "C+" directives the final 'argument' field (which so far specified the source to symlink/copy the files from) is now optional. If omitted the same file os copied from /usr/share/factory/ suffixed by the full destination path. This is useful for populating /etc with essential files, by copying them from vendor defaults shipped in /usr/share/factory/etc. * A new command "systemctl preset-all" has been added that applies the service preset settings to all installed unit files. A new switch --preset-mode= has been added that controls whether only enable or only disable operations shall be executed. * A new command "systemctl is-system-running" has been added that allows checking the overall state of the system, for example whether it is fully up and running. * When the system boots up with an empty /etc, the equivalent to "systemctl preset-all" is executed during early boot, to make sure all default services are enabled after a factory reset. * systemd now contains a minimal preset file that enables the most basic services systemd ships by default. * Unit files' [Install] section gained a new DefaultInstance= field for defining the default instance to create if a template unit is enabled with no instance specified. * A new passive target cryptsetup-pre.target has been added that may be used by services that need to make they run and finish before the first LUKS cryptographic device is set up. * The /dev/loop-control and /dev/btrfs-control device nodes are now owned by the "disk" group by default, opening up access to this group. * systemd-coredump will now automatically generate a stack trace of all core dumps taking place on the system, based on elfutils' libdw library. This stack trace is logged to the journal. * systemd-coredump may now optionally store coredumps directly on disk (in /var/lib/systemd/coredump, possibly compressed), instead of storing them unconditionally in the journal. This mode is the new default. A new configuration file /etc/systemd/coredump.conf has been added to configure this and other parameters of systemd-coredump. * coredumpctl gained a new "info" verb to show details about a specific coredump. A new switch "-1" has also been added that makes sure to only show information about the most recent entry instead of all entries. Also, as the tool is generally useful now the "systemd-" prefix of the binary name has been removed. Distributions that want to maintain compatibility with the old name should add a symlink from the old name to the new name. * journald's SplitMode= now defaults to "uid". This makes sure that unprivileged users can access their own coredumps with coredumpctl without restrictions. * New kernel command line options "systemd.wants=" (for pulling an additional unit during boot), "systemd.mask=" (for masking a specific unit for the boot), and "systemd.debug-shell" (for enabling the debug shell on tty9) have been added. This is implemented in the new generator "systemd-debug-generator". * systemd-nspawn will now by default filter a couple of syscalls for containers, among them those required for kernel module loading, direct x86 IO port access, swap management, and kexec. Most importantly though open_by_handle_at() is now prohibited for containers, closing a hole similar to a recently discussed vulnerability in docker regarding access to files on file hierarchies the container should normally not have access to. Note that, for nspawn, we generally make no security claims anyway (and this is explicitly documented in the man page), so this is just a fix for one of the most obvious problems. * A new man page file-hierarchy(7) has been added that contains a minimized, modernized version of the file system layout systemd expects, similar in style to the FHS specification or hier(5). A new tool systemd-path(1) has been added to query many of these paths for the local machine and user. * Automatic time-based clean-up of $XDG_RUNTIME_DIR is no longer done. Since the directory now has a per-user size limit, and is cleaned on logout this appears unnecessary, in particular since this now brings the lifecycle of this directory closer in line with how IPC objects are handled. * systemd.pc now exports a number of additional directories, including $libdir (which is useful to identify the library path for the primary architecture of the system), and a couple of drop-in directories. * udev's predictable network interface names now use the dev_port sysfs attribute, introduced in linux 3.15 instead of dev_id to distinguish between ports of the same PCI function. dev_id should only be used for ports using the same HW address, hence the need for dev_port. * machined has been updated to export the OS version of a container (read from /etc/os-release and /usr/lib/os-release) on the bus. This is now shown in "machinectl status" for a machine. * A new service setting RestartForceExitStatus= has been added. If configured to a set of exit signals or process return values, the service will be restarted when the main daemon process exits with any of them, regardless of the Restart= setting. * systemctl's -H switch for connecting to remote systemd machines has been extended so that it may be used to directly connect to a specific container on the host. "systemctl -H root@foobar:waldi" will now connect as user "root" to host "foobar", and then proceed directly to the container named "waldi". Note that currently you have to authenticate as user "root" for this to work, as entering containers is a privileged operation. Contributions from: Andreas Henriksson, Benjamin Steinwender, Carl Schaefer, Christian Hesse, Colin Ian King, Cristian Rodríguez, Daniel Mack, Dave Reisner, David Herrmann, Eugene Yakubovich, Filipe Brandenburger, Frederic Crozat, Hristo Venev, Jan Engelhardt, Jonathan Boulle, Kay Sievers, Lennart Poettering, Luke Shumaker, Mantas Mikulėnas, Marc-Antoine Perennou, Marcel Holtmann, Michael Marineau, Michael Olbrich, Michał Bartoszkiewicz, Michal Sekletar, Patrik Flykt, Ronan Le Martret, Ronny Chevalier, Ruediger Oertel, Steven Noonan, Susant Sahani, Thadeu Lima de Souza Cascardo, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Tom Hirst, Umut Tezduyar Lindskog, Uoti Urpala, Zbigniew Jędrzejewski-Szmek -- Berlin, 2014-07-03 CHANGES WITH 214: * As an experimental feature, udev now tries to lock the disk device node (flock(LOCK_SH|LOCK_NB)) while it executes events for the disk or any of its partitions. Applications like partitioning programs can lock the disk device node (flock(LOCK_EX)) and claim temporary device ownership that way; udev will entirely skip all event handling for this disk and its partitions. If the disk was opened for writing, the close will trigger a partition table rescan in udev's "watch" facility, and if needed synthesize "change" events for the disk and all its partitions. This is now unconditionally enabled, and if it turns out to cause major problems, we might turn it on only for specific devices, or might need to disable it entirely. Device Mapper devices are excluded from this logic. * We temporarily dropped the "-l" switch for fsck invocations, since they collide with the flock() logic above. util-linux upstream has been changed already to avoid this conflict, and we will readd "-l" as soon as util-linux with this change has been released. * The dependency on libattr has been removed. Since a long time, the extended attribute calls have moved to glibc, and libattr is thus unnecessary. * Virtualization detection works without priviliges now. This means the systemd-detect-virt binary no longer requires CAP_SYS_PTRACE file capabilities, and our daemons can run with fewer privileges. * systemd-networkd now runs under its own "systemd-network" user. It retains the CAP_NET_ADMIN, CAP_NET_BIND_SERVICE, CAP_NET_BROADCAST, CAP_NET_RAW capabilities though, but loses the ability to write to files owned by root this way. * Similarly, systemd-resolved now runs under its own "systemd-resolve" user with no capabilities remaining. * Similarly, systemd-bus-proxyd now runs under its own "systemd-bus-proxy" user with only CAP_IPC_OWNER remaining. * systemd-networkd gained support for setting up "veth" virtual Ethernet devices for container connectivity, as well as GRE and VTI tunnels. * systemd-networkd will no longer automatically attempt to manually load kernel modules necessary for certain tunnel transports. Instead, it is assumed the kernel loads them automatically when required. This only works correctly on very new kernels. On older kernels, please consider adding the kernel modules to /etc/modules-load.d/ as a work-around. * The resolv.conf file systemd-resolved generates has been moved to /run/systemd/resolve/. If you have a symlink from /etc/resolv.conf, it might be necessary to correct it. * Two new service settings, ProtectHome= and ProtectSystem=, have been added. When enabled, they will make the user data (such as /home) inaccessible or read-only and the system (such as /usr) read-only, for specific services. This allows very light-weight per-service sandboxing to avoid modifications of user data or system files from services. These two new switches have been enabled for all of systemd's long-running services, where appropriate. * Socket units gained new SocketUser= and SocketGroup= settings to set the owner user and group of AF_UNIX sockets and FIFOs in the file system. * Socket units gained a new RemoveOnStop= setting. If enabled, all FIFOS and sockets in the file system will be removed when the specific socket unit is stopped. * Socket units gained a new Symlinks= setting. It takes a list of symlinks to create to file system sockets or FIFOs created by the specific Unix sockets. This is useful to manage symlinks to socket nodes with the same life-cycle as the socket itself. * The /dev/log socket and /dev/initctl FIFO have been moved to /run, and have been replaced by symlinks. This allows connecting to these facilities even if PrivateDevices=yes is used for a service (which makes /dev/log itself unavailable, but /run is left). This also has the benefit of ensuring that /dev only contains device nodes, directories and symlinks, and nothing else. * sd-daemon gained two new calls sd_pid_notify() and sd_pid_notifyf(). They are similar to sd_notify() and sd_notifyf(), but allow overriding of the source PID of notification messages if permissions permit this. This is useful to send notify messages on behalf of a different process (for example, the parent process). The systemd-notify tool has been updated to make use of this when sending messages (so that notification messages now originate from the shell script invoking systemd-notify and not the systemd-notify process itself. This should minimize a race where systemd fails to associate notification messages to services when the originating process already vanished. * A new "on-abnormal" setting for Restart= has been added. If set, it will result in automatic restarts on all "abnormal" reasons for a process to exit, which includes unclean signals, core dumps, timeouts and watchdog timeouts, but does not include clean and unclean exit codes or clean signals. Restart=on-abnormal is an alternative for Restart=on-failure for services that shall be able to terminate and avoid restarts on certain errors, by indicating so with an unclean exit code. Restart=on-failure or Restart=on-abnormal is now the recommended setting for all long-running services. * If the InaccessibleDirectories= service setting points to a mount point (or if there are any submounts contained within it), it is now attempted to completely unmount it, to make the file systems truly unavailable for the respective service. * The ReadOnlyDirectories= service setting and systemd-nspawn's --read-only parameter are now recursively applied to all submounts, too. * Mount units may now be created transiently via the bus APIs. * The support for SysV and LSB init scripts has been removed from the systemd daemon itself. Instead, it is now implemented as a generator that creates native systemd units from these scripts when needed. This enables us to remove a substantial amount of legacy code from PID 1, following the fact that many distributions only ship a very small number of LSB/SysV init scripts nowadays. * Privileged Xen (dom0) domains are not considered virtualization anymore by the virtualization detection logic. After all, they generally have unrestricted access to the hardware and usually are used to manage the unprivileged (domU) domains. * systemd-tmpfiles gained a new "C" line type, for copying files or entire directories. * systemd-tmpfiles "m" lines are now fully equivalent to "z" lines. So far, they have been non-globbing versions of the latter, and have thus been redundant. In future, it is recommended to only use "z". "m" has hence been removed from the documentation, even though it stays supported. * A tmpfiles snippet to recreate the most basic structure in /var has been added. This is enough to create the /var/run → /run symlink and create a couple of structural directories. This allows systems to boot up with an empty or volatile /var. Of course, while with this change, the core OS now is capable with dealing with a volatile /var, not all user services are ready for it. However, we hope that sooner or later, many service daemons will be changed upstream so that they are able to automatically create their necessary directories in /var at boot, should they be missing. This is the first step to allow state-less systems that only require the vendor image for /usr to boot. * systemd-nspawn has gained a new --tmpfs= switch to mount an empty tmpfs instance to a specific directory. This is particularly useful for making use of the automatic reconstruction of /var (see above), by passing --tmpfs=/var. * Access modes specified in tmpfiles snippets may now be prefixed with "~", which indicates that they shall be masked by whether the existing file or directory is currently writable, readable or executable at all. Also, if specified, the sgid/suid/sticky bits will be masked for all non-directories. * A new passive target unit "network-pre.target" has been added which is useful for services that shall run before any network is configured, for example firewall scripts. * The "floppy" group that previously owned the /dev/fd* devices is no longer used. The "disk" group is now used instead. Distributions should probably deprecate usage of this group. Contributions from: Camilo Aguilar, Christian Hesse, Colin Ian King, Cristian Rodríguez, Daniel Buch, Dave Reisner, David Strauss, Denis Tikhomirov, John, Jonathan Liu, Kay Sievers, Lennart Poettering, Mantas Mikulėnas, Mark Eichin, Ronny Chevalier, Susant Sahani, Thomas Blume, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Umut Tezduyar Lindskog, Zbigniew Jędrzejewski-Szmek -- Berlin, 2014-06-11 CHANGES WITH 213: * A new "systemd-timesyncd" daemon has been added for synchronizing the system clock across the network. It implements an SNTP client. In contrast to NTP implementations such as chrony or the NTP reference server, this only implements a client side, and does not bother with the full NTP complexity, focusing only on querying time from one remote server and synchronizing the local clock to it. Unless you intend to serve NTP to networked clients or want to connect to local hardware clocks, this simple NTP client should be more than appropriate for most installations. The daemon runs with minimal privileges, and has been hooked up with networkd to only operate when network connectivity is available. The daemon saves the current clock to disk every time a new NTP sync has been acquired, and uses this to possibly correct the system clock early at bootup, in order to accommodate for systems that lack an RTC such as the Raspberry Pi and embedded devices, and to make sure that time monotonically progresses on these systems, even if it is not always correct. To make use of this daemon, a new system user and group "systemd-timesync" needs to be created on installation of systemd. * The queue "seqnum" interface of libudev has been disabled, as it was generally incompatible with device namespacing as sequence numbers of devices go "missing" if the devices are part of a different namespace. * "systemctl list-timers" and "systemctl list-sockets" gained a --recursive switch for showing units of these types also for all local containers, similar in style to the already supported --recursive switch for "systemctl list-units". * A new RebootArgument= setting has been added for service units, which may be used to specify a kernel reboot argument to use when triggering reboots with StartLimitAction=. * A new FailureAction= setting has been added for service units which may be used to specify an operation to trigger when a service fails. This works similarly to StartLimitAction=, but unlike it, controls what is done immediately rather than only after several attempts to restart the service in question. * hostnamed got updated to also expose the kernel name, release, and version on the bus. This is useful for executing commands like hostnamectl with the -H switch. systemd-analyze makes use of this to properly display details when running non-locally. * The bootchart tool can now show cgroup information in the graphs it generates. * The CFS CPU quota cgroup attribute is now exposed for services. The new CPUQuota= switch has been added for this which takes a percentage value. Setting this will have the result that a service may never get more CPU time than the specified percentage, even if the machine is otherwise idle. * systemd-networkd learned IPIP and SIT tunnel support. * LSB init scripts exposing a dependency on $network will now get a dependency on network-online.target rather than simply network.target. This should bring LSB handling closer to what it was on SysV systems. * A new fsck.repair= kernel option has been added to control how fsck shall deal with unclean file systems at boot. * The (.ini) configuration file parser will now silently ignore sections whose name begins with "X-". This may be used to maintain application-specific extension sections in unit files. * machined gained a new API to query the IP addresses of registered containers. "machinectl status" has been updated to show these addresses in its output. * A new call sd_uid_get_display() has been added to the sd-login APIs for querying the "primary" session of a user. The "primary" session of the user is elected from the user's sessions and generally a graphical session is preferred over a text one. * A minimal systemd-resolved daemon has been added. It currently simply acts as a companion to systemd-networkd and manages resolv.conf based on per-interface DNS configuration, possibly supplied via DHCP. In the long run we hope to extend this into a local DNSSEC enabled DNS and mDNS cache. * The systemd-networkd-wait-online tool is now enabled by default. It will delay network-online.target until a network connection has been configured. The tool primarily integrates with networkd, but will also make a best effort to make sense of network configuration performed in some other way. * Two new service options StartupCPUShares= and StartupBlockIOWeight= have been added that work similarly to CPUShares= and BlockIOWeight= however only apply during system startup. This is useful to prioritize certain services differently during bootup than during normal runtime. * hostnamed has been changed to prefer the statically configured hostname in /etc/hostname (unless set to 'localhost' or empty) over any dynamic one supplied by dhcp. With this change, the rules for picking the hostname match more closely the rules of other configuration settings where the local administrator's configuration in /etc always overrides any other settings. Contributions fron: Ali H. Caliskan, Alison Chaiken, Bas van den Berg, Brandon Philips, Cristian Rodríguez, Daniel Buch, Dan Kilman, Dave Reisner, David Härdeman, David Herrmann, David Strauss, Dimitris Spingos, Djalal Harouni, Eelco Dolstra, Evan Nemerson, Florian Albrechtskirchinger, Greg Kroah-Hartman, Harald Hoyer, Holger Hans Peter Freyther, Jan Engelhardt, Jani Nikula, Jason St. John, Jeffrey Clark, Jonathan Boulle, Kay Sievers, Lennart Poettering, Lukas Nykryn, Lukasz Skalski, Łukasz Stelmach, Mantas Mikulėnas, Marcel Holtmann, Martin Pitt, Matthew Monaco, Michael Marineau, Michael Olbrich, Michal Sekletar, Mike Gilbert, Nis Martensen, Patrik Flykt, Philip Lorenz, poma, Ray Strode, Reyad Attiyat, Robert Milasan, Scott Thrasher, Stef Walter, Steven Siloti, Susant Sahani, Tanu Kaskinen, Thomas Bächler, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Umut Tezduyar Lindskog, WaLyong Cho, Will Woods, Zbigniew Jędrzejewski-Szmek -- Beijing, 2014-05-28 CHANGES WITH 212: * When restoring the screen brightness at boot, stay away from the darkest setting or from the lowest 5% of the available range, depending on which is the larger value of both. This should effectively protect the user from rebooting into a black screen, should the brightness have been set to minimum by accident. * sd-login gained a new sd_machine_get_class() call to determine the class ("vm" or "container") of a machine registered with machined. * sd-login gained new calls sd_peer_get_{session,owner_uid,unit,user_unit,slice,machine_name}(), to query the identity of the peer of a local AF_UNIX connection. They operate similarly to their sd_pid_get_xyz() counterparts. * PID 1 will now maintain a system-wide system state engine with the states "starting", "running", "degraded", "maintenance", "stopping". These states are bound to system startup, normal runtime, runtime with at least one failed service, rescue/emergency mode and system shutdown. This state is shown in the "systemctl status" output when no unit name is passed. It is useful to determine system state, in particularly when doing so for many systems or containers at once. * A new command "list-machines" has been added to "systemctl" that lists all local OS containers and shows their system state (see above), if systemd runs inside of them. * systemctl gained a new "-r" switch to recursively enumerate units on all local containers, when used with the "list-unit" command (which is the default one that is executed when no parameters are specified). * The GPT automatic partition discovery logic will now honour two GPT partition flags: one may be set on a partition to cause it to be mounted read-only, and the other may be set on a partition to ignore it during automatic discovery. * Two new GPT type UUIDs have been added for automatic root partition discovery, for 32-bit and 64-bit ARM. This is not particularly useful for discovering the root directory on these architectures during bare-metal boots (since UEFI is not common there), but still very useful to allow booting of ARM disk images in nspawn with the -i option. * MAC addresses of interfaces created with nspawn's --network-interface= switch will now be generated from the machine name, and thus be stable between multiple invocations of the container. * logind will now automatically remove all IPC objects owned by a user if she or he fully logs out. This makes sure that users who are logged out cannot continue to consume IPC resources. This covers SysV memory, semaphores and message queues as well as POSIX shared memory and message queues. Traditionally, SysV and POSIX IPC had no life-cycle limits. With this functionality, that is corrected. This may be turned off by using the RemoveIPC= switch of logind.conf. * The systemd-machine-id-setup and tmpfiles tools gained a --root= switch to operate on a specific root directory, instead of /. * journald can now forward logged messages to the TTYs of all logged in users ("wall"). This is the default for all emergency messages now. * A new tool systemd-journal-remote has been added to stream journal log messages across the network. * /sys/fs/cgroup/ is now mounted read-only after all cgroup controller trees are mounted into it. Note that the directories mounted beneath it are not read-only. This is a security measure and is particularly useful because glibc actually includes a search logic to pick any tmpfs it can find to implement shm_open() if /dev/shm is not available (which it might very well be in namespaced setups). * machinectl gained a new "poweroff" command to cleanly power down a local OS container. * The PrivateDevices= unit file setting will now also drop the CAP_MKNOD capability from the capability bound set, and imply DevicePolicy=closed. * PrivateDevices=, PrivateNetwork= and PrivateTmp= is now used comprehensively on all long-running systemd services where this is appropriate. * systemd-udevd will now run in a disassociated mount namespace. To mount directories from udev rules, make sure to pull in mount units via SYSTEMD_WANTS properties. * The kdbus support gained support for uploading policy into the kernel. sd-bus gained support for creating "monitoring" connections that can eavesdrop into all bus communication for debugging purposes. * Timestamps may now be specified in seconds since the UNIX epoch Jan 1st, 1970 by specifying "@" followed by the value in seconds. * Native tcpwrap support in systemd has been removed. tcpwrap is old code, not really maintained anymore and has serious shortcomings, and better options such as firewalls exist. For setups that require tcpwrap usage, please consider invoking your socket-activated service via tcpd, like on traditional inetd. * A new system.conf configuration option DefaultTimerAccuracySec= has been added that controls the default AccuracySec= setting of .timer units. * Timer units gained a new WakeSystem= switch. If enabled, timers configured this way will cause the system to resume from system suspend (if the system supports that, which most do these days). * Timer units gained a new Persistent= switch. If enabled, timers configured this way will save to disk when they have been last triggered. This information is then used on next reboot to possible execute overdue timer events, that could not take place because the system was powered off. This enables simple anacron-like behaviour for timer units. * systemctl's "list-timers" will now also list the time a timer unit was last triggered in addition to the next time it will be triggered. * systemd-networkd will now assign predictable IPv4LL addresses to its local interfaces. Contributions from: Brandon Philips, Daniel Buch, Daniel Mack, Dave Reisner, David Herrmann, Gerd Hoffmann, Greg Kroah-Hartman, Hendrik Brueckner, Jason St. John, Josh Triplett, Kay Sievers, Lennart Poettering, Marc-Antoine Perennou, Michael Marineau, Michael Olbrich, Miklos Vajna, Patrik Flykt, poma, Sebastian Thorarensen, Thomas Bächler, Thomas Hindoe Paaboel Andersen, Tomasz Torcz, Tom Gundersen, Umut Tezduyar Lindskog, Wieland Hoffmann, Zbigniew Jędrzejewski-Szmek -- Berlin, 2014-03-25 CHANGES WITH 211: * A new unit file setting RestrictAddressFamilies= has been added to restrict which socket address families unit processes gain access to. This takes address family names like "AF_INET" or "AF_UNIX", and is useful to minimize the attack surface of services via exotic protocol stacks. This is built on seccomp system call filters. * Two new unit file settings RuntimeDirectory= and RuntimeDirectoryMode= have been added that may be used to manage a per-daemon runtime directories below /run. This is an alternative for setting up directory permissions with tmpfiles snippets, and has the advantage that the runtime directory's lifetime is bound to the daemon runtime and that the daemon starts up with an empty directory each time. This is particularly useful when writing services that drop privileges using the User= or Group= setting. * The DeviceAllow= unit setting now supports globbing for matching against device group names. * The systemd configuration file system.conf gained new settings DefaultCPUAccounting=, DefaultBlockIOAccounting=, DefaultMemoryAccounting= to globally turn on/off accounting for specific resources (cgroups) for all units. These settings may still be overridden individually in each unit though. * systemd-gpt-auto-generator is now able to discover /srv and root partitions in addition to /home and swap partitions. It also supports LUKS-encrypted partitions now. With this in place, automatic discovery of partitions to mount following the Discoverable Partitions Specification (http://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec) is now a lot more complete. This allows booting without /etc/fstab and without root= on the kernel command line on systems prepared appropriately. * systemd-nspawn gained a new --image= switch which allows booting up disk images and Linux installations on any block device that follow the Discoverable Partitions Specification (see above). This means that installations made with appropriately updated installers may now be started and deployed using container managers, completely unmodified. (We hope that libvirt-lxc will add support for this feature soon, too.) * systemd-nspawn gained a new --network-macvlan= setting to set up a private macvlan interface for the container. Similarly, systemd-networkd gained a new Kind=macvlan setting in .netdev files. * systemd-networkd now supports configuring local addresses using IPv4LL. * A new tool systemd-network-wait-online has been added to synchronously wait for network connectivity using systemd-networkd. * The sd-bus.h bus API gained a new sd_bus_track object for tracking the life-cycle of bus peers. Note that sd-bus.h is still not a public API though (unless you specify --enable-kdbus on the configure command line, which however voids your warranty and you get no API stability guarantee). * The $XDG_RUNTIME_DIR runtime directories for each user are now individual tmpfs instances, which has the benefit of introducing separate pools for each user, with individual size limits, and thus making sure that unprivileged clients can no longer negatively impact the system or other users by filling up their $XDG_RUNTIME_DIR. A new logind.conf setting RuntimeDirectorySize= has been introduced that allows controlling the default size limit for all users. It defaults to 10% of the available physical memory. This is no replacement for quotas on tmpfs though (which the kernel still does not support), as /dev/shm and /tmp are still shared resources used by both the system and unprivileged users. * logind will now automatically turn off automatic suspending on laptop lid close when more than one display is connected. This was previously expected to be implemented individually in desktop environments (such as GNOME), however has been added to logind now, in order to fix a boot-time race where a desktop environment might not have been started yet and thus not been able to take an inhibitor lock at the time where logind already suspends the system due to a closed lid. * logind will now wait at least 30s after each system suspend/resume cycle, and 3min after system boot before suspending the system due to a closed laptop lid. This should give USB docking stations and similar enough time to be probed and configured after system resume and boot in order to then act as suspend blocker. * systemd-run gained a new --property= setting which allows initialization of resource control properties (and others) for the created scope or service unit. Example: "systemd-run --property=BlockIOWeight=10 updatedb" may be used to run updatedb at a low block IO scheduling weight. * systemd-run's --uid=, --gid=, --setenv=, --setenv= switches now also work in --scope mode. * When systemd is compiled with kdbus support, basic support for enforced policies is now in place. (Note that enabling kdbus still voids your warranty and no API compatibility promises are made.) Contributions from: Andrey Borzenkov, Ansgar Burchardt, Armin K., Daniel Mack, Dave Reisner, David Herrmann, Djalal Harouni, Harald Hoyer, Henrik Grindal Bakken, Jasper St. Pierre, Kay Sievers, Kieran Clancy, Lennart Poettering, Lukas Nykryn, Mantas Mikulėnas, Marcel Holtmann, Mark Oteiza, Martin Pitt, Mike Gilbert, Peter Rajnoha, poma, Samuli Suominen, Stef Walter, Susant Sahani, Tero Roponen, Thomas Andersen, Thomas Bächler, Thomas Hindoe Paaboel Andersen, Tomasz Torcz, Tom Gundersen, Umut Tezduyar Lindskog, Uoti Urpala, Zachary Cook, Zbigniew Jędrzejewski-Szmek -- Berlin, 2014-03-12 CHANGES WITH 210: * systemd will now relabel /dev after loading the SMACK policy according to SMACK rules. * A new unit file option AppArmorProfile= has been added to set the AppArmor profile for the processes of a unit. * A new condition check ConditionArchitecture= has been added to conditionalize units based on the system architecture, as reported by uname()'s "machine" field. * systemd-networkd now supports matching on the system virtualization, architecture, kernel command line, host name and machine ID. * logind is now a lot more aggressive when suspending the machine due to a closed laptop lid. Instead of acting only on the lid close action, it will continuously watch the lid status and act on it. This is useful for laptops where the power button is on the outside of the chassis so that it can be reached without opening the lid (such as the Lenovo Yoga). On those machines, logind will now immediately re-suspend the machine if the power button has been accidentally pressed while the laptop was suspended and in a backpack or similar. * logind will now watch SW_DOCK switches and inhibit reaction to the lid switch if it is pressed. This means that logind will not suspend the machine anymore if the lid is closed and the system is docked, if the laptop supports SW_DOCK notifications via the input layer. Note that ACPI docking stations do not generate this currently. Also note that this logic is usually not fully sufficient and Desktop Environments should take a lid switch inhibitor lock when an external display is connected, as systemd will not watch this on its own. * nspawn will now make use of the devices cgroup controller by default, and only permit creation of and access to the usual API device nodes like /dev/null or /dev/random, as well as access to (but not creation of) the pty devices. * We will now ship a default .network file for systemd-networkd that automatically configures DHCP for network interfaces created by nspawn's --network-veth or --network-bridge= switches. * systemd will now understand the usual M, K, G, T suffixes according to SI conventions (i.e. to the base 1000) when referring to throughput and hardware metrics. It will stay with IEC conventions (i.e. to the base 1024) for software metrics, according to what is customary according to Wikipedia. We explicitly document which base applies for each configuration option. * The DeviceAllow= setting in unit files now supports a syntax to whitelist an entire group of devices node majors at once, based on the /proc/devices listing. For example, with the string "char-pts", it is now possible to whitelist all current and future pseudo-TTYs at once. * sd-event learned a new "post" event source. Event sources of this type are triggered by the dispatching of any event source of a type that is not "post". This is useful for implementing clean-up and check event sources that are triggered by other work being done in the program. * systemd-networkd is no longer statically enabled, but uses the usual [Install] sections so that it can be enabled/disabled using systemctl. It still is enabled by default however. * When creating a veth interface pair with systemd-nspawn, the host side will now be prefixed with "vb-" if --network-bridge= is used, and with "ve-" if --network-veth is used. This way, it is easy to distinguish these cases on the host, for example to apply different configuration to them with systemd-networkd. * The compatibility libraries for libsystemd-journal.so, libsystem-id128.so, libsystemd-login.so and libsystemd-daemon.so do not make use of IFUNC anymore. Instead, we now build libsystemd.so multiple times under these alternative names. This means that the footprint is drastically increased, but given that these are transitional compatibility libraries, this should not matter much. This change has been made necessary to support the ARM platform for these compatibility libraries, as the ARM toolchain is not really at the same level as the toolchain for other architectures like x86 and does not support IFUNC. Please make sure to use --enable-compat-libs only during a transitional period! Contributions from: Andreas Fuchs, Armin K., Colin Walters, Daniel Mack, Dave Reisner, David Herrmann, Djalal Harouni, Holger Schurig, Jason A. Donenfeld, Jason St. John, Jasper St. Pierre, Kay Sievers, Lennart Poettering, Łukasz Stelmach, Marcel Holtmann, Michael Scherer, Michal Sekletar, Mike Gilbert, Samuli Suominen, Thomas Bächler, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Umut Tezduyar Lindskog, Zbigniew Jędrzejewski-Szmek -- Berlin, 2014-02-24 CHANGES WITH 209: * A new component "systemd-networkd" has been added that can be used to configure local network interfaces statically or via DHCP. It is capable of bringing up bridges, VLANs, and bonding. Currently, no hook-ups for interactive network configuration are provided. Use this for your initrd, container, embedded, or server setup if you need a simple, yet powerful, network configuration solution. This configuration subsystem is quite nifty, as it allows wildcard hotplug matching in interfaces. For example, with a single configuration snippet, you can configure that all Ethernet interfaces showing up are automatically added to a bridge, or similar. It supports link-sensing and more. * A new tool "systemd-socket-proxyd" has been added which can act as a bidirectional proxy for TCP sockets. This is useful for adding socket activation support to services that do not actually support socket activation, including virtual machines and the like. * Add a new tool to save/restore rfkill state on shutdown/boot. * Save/restore state of keyboard backlights in addition to display backlights on shutdown/boot. * udev learned a new SECLABEL{} construct to label device nodes with a specific security label when they appear. For now, only SECLABEL{selinux} is supported, but the syntax is prepared for additional security frameworks. * udev gained a new scheme to configure link-level attributes from files in /etc/systemd/network/*.link. These files can match against MAC address, device path, driver name and type, and will apply attributes like the naming policy, link speed, MTU, duplex settings, Wake-on-LAN settings, MAC address, MAC address assignment policy (randomized, ...). * The configuration of network interface naming rules for "permanent interface names" has changed: a new NamePolicy= setting in the [Link] section of .link files determines the priority of possible naming schemes (onboard, slot, MAC, path). The default value of this setting is determined by /usr/lib/net/links/99-default.link. Old 80-net-name-slot.rules udev configuration file has been removed, so local configuration overriding this file should be adapated to override 99-default.link instead. * When the User= switch is used in a unit file, also initialize $SHELL= based on the user database entry. * systemd no longer depends on libdbus. All communication is now done with sd-bus, systemd's low-level bus library implementation. * kdbus support has been added to PID 1 itself. When kdbus is enabled, this causes PID 1 to set up the system bus and enable support for a new ".busname" unit type that encapsulates bus name activation on kdbus. It works a little bit like ".socket" units, except for bus names. A new generator has been added that converts classic dbus1 service activation files automatically into native systemd .busname and .service units. * sd-bus: add a light-weight vtable implementation that allows defining objects on the bus with a simple static const vtable array of its methods, signals and properties. * systemd will not generate or install static dbus introspection data anymore to /usr/share/dbus-1/interfaces, as the precise format of these files is unclear, and nothing makes use of it. * A proxy daemon is now provided to proxy clients connecting via classic D-Bus AF_UNIX sockets to kdbus, to provide full compatibility with classic D-Bus. * A bus driver implementation has been added that supports the classic D-Bus bus driver calls on kdbus, also for compatibility purposes. * A new API "sd-event.h" has been added that implements a minimal event loop API built around epoll. It provides a couple of features that direct epoll usage is lacking: prioritization of events, scales to large numbers of timer events, per-event timer slack (accuracy), system-wide coalescing of timer events, exit handlers, watchdog supervision support using systemd's sd_notify() API, child process handling. * A new API "sd-rntl.h" has been added that provides an API around the route netlink interface of the kernel, similar in style to "sd-bus.h". * A new API "sd-dhcp-client.h" has been added that provides a small DHCPv4 client-side implementation. This is used by "systemd-networkd". * There is a new kernel command line option "systemd.restore_state=0|1". When set to "0", none of the systemd tools will restore saved runtime state to hardware devices. More specifically, the rfkill and backlight states are not restored. * The FsckPassNo= compatibility option in mount/service units has been removed. The fstab generator will now add the necessary dependencies automatically, and does not require PID1's support for that anymore. * journalctl gained a new switch, --list-boots, that lists recent boots with their times and boot IDs. * The various tools like systemctl, loginctl, timedatectl, busctl, systemd-run, ... have gained a new switch "-M" to connect to a specific, local OS container (as direct connection, without requiring SSH). This works on any container that is registered with machined, such as those created by libvirt-lxc or nspawn. * systemd-run and systemd-analyze also gained support for "-H" to connect to remote hosts via SSH. This is particularly useful for systemd-run because it enables queuing of jobs onto remote systems. * machinectl gained a new command "login" to open a getty login in any local container. This works with any container that is registered with machined (such as those created by libvirt-lxc or nspawn), and which runs systemd inside. * machinectl gained a new "reboot" command that may be used to trigger a reboot on a specific container that is registered with machined. This works on any container that runs an init system of some kind. * systemctl gained a new "list-timers" command to print a nice listing of installed timer units with the times they elapse next. * Alternative reboot() parameters may now be specified on the "systemctl reboot" command line and are passed to the reboot() system call. * systemctl gained a new --job-mode= switch to configure the mode to queue a job with. This is a more generic version of --fail, --irreversible, and --ignore-dependencies, which are still available but not advertised anymore. * /etc/systemd/system.conf gained new settings to configure various default timeouts of units, as well as the default start limit interval and burst. These may still be overridden within each Unit. * PID1 will now export on the bus profile data of the security policy upload process (such as the SELinux policy upload to the kernel). * journald: when forwarding logs to the console, include timestamps (following the setting in /sys/module/printk/parameters/time). * OnCalendar= in timer units now understands the special strings "yearly" and "annually". (Both are equivalent) * The accuracy of timer units is now configurable with the new AccuracySec= setting. It defaults to 1min. * A new dependency type JoinsNamespaceOf= has been added that allows running two services within the same /tmp and network namespace, if PrivateNetwork= or PrivateTmp= are used. * A new command "cat" has been added to systemctl. It outputs the original unit file of a unit, and concatenates the contents of additional "drop-in" unit file snippets, so that the full configuration is shown. * systemctl now supports globbing on the various "list-xyz" commands, like "list-units" or "list-sockets", as well as on those commands which take multiple unit names. * journalctl's --unit= switch gained support for globbing. * All systemd daemons now make use of the watchdog logic so that systemd automatically notices when they hang. * If the $container_ttys environment variable is set, getty-generator will automatically spawn a getty for each listed tty. This is useful for container managers to request login gettys to be spawned on as many ttys as needed. * %h, %s, %U specifier support is not available anymore when used in unit files for PID 1. This is because NSS calls are not safe from PID 1. They stay available for --user instances of systemd, and as special case for the root user. * loginctl gained a new "--no-legend" switch to turn off output of the legend text. * The "sd-login.h" API gained three new calls: sd_session_is_remote(), sd_session_get_remote_user(), sd_session_get_remote_host() to query information about remote sessions. * The udev hardware database now also carries vendor/product information of SDIO devices. * The "sd-daemon.h" API gained a new sd_watchdog_enabled() to determine whether watchdog notifications are requested by the system manager. * Socket-activated per-connection services now include a short description of the connection parameters in the description. * tmpfiles gained a new "--boot" option. When this is not used, only lines where the command character is not suffixed with "!" are executed. When this option is specified, those options are executed too. This partitions tmpfiles directives into those that can be safely executed at any time, and those which should be run only at boot (for example, a line that creates /run/nologin). * A new API "sd-resolve.h" has been added which provides a simple asynchronous wrapper around glibc NSS host name resolution calls, such as getaddrinfo(). In contrast to glibc's getaddrinfo_a(), it does not use signals. In contrast to most other asynchronous name resolution libraries, this one does not reimplement DNS, but reuses NSS, so that alternate host name resolution systems continue to work, such as mDNS, LDAP, etc. This API is based on libasyncns, but it has been cleaned up for inclusion in systemd. * The APIs "sd-journal.h", "sd-login.h", "sd-id128.h", "sd-daemon.h" are no longer found in individual libraries libsystemd-journal.so, libsystemd-login.so, libsystemd-id128.so, libsystemd-daemon.so. Instead, we have merged them into a single library, libsystemd.so, which provides all symbols. The reason for this is cyclic dependencies, as these libraries tend to use each other's symbols. So far, we have managed to workaround that by linking a copy of a good part of our code into each of these libraries again and again, which, however, makes certain things hard to do, like sharing static variables. Also, it substantially increases footprint. With this change, there is only one library for the basic APIs systemd provides. Also, "sd-bus.h", "sd-memfd.h", "sd-event.h", "sd-rtnl.h", "sd-resolve.h", "sd-utf8.h" are found in this library as well, however are subject to the --enable-kdbus switch (see below). Note that "sd-dhcp-client.h" is not part of this library (this is because it only consumes, never provides, services of/to other APIs). To make the transition easy from the separate libraries to the unified one, we provide the --enable-compat-libs compile-time switch which will generate stub libraries that are compatible with the old ones but redirect all calls to the new one. * All of the kdbus logic and the new APIs "sd-bus.h", "sd-memfd.h", "sd-event.h", "sd-rtnl.h", "sd-resolve.h", and "sd-utf8.h" are compile-time optional via the "--enable-kdbus" switch, and they are not compiled in by default. To make use of kdbus, you have to explicitly enable the switch. Note however, that neither the kernel nor the userspace API for all of this is considered stable yet. We want to maintain the freedom to still change the APIs for now. By specifying this build-time switch, you acknowledge that you are aware of the instability of the current APIs. * Also, note that while kdbus is pretty much complete, it lacks one thing: proper policy support. This means you can build a fully working system with all features; however, it will be highly insecure. Policy support will be added in one of the next releases, at the same time that we will declare the APIs stable. * When the kernel command line argument "kdbus" is specified, systemd will automatically load the kdbus.ko kernel module. At this stage of development, it is only useful for testing kdbus and should not be used in production. Note: if "--enable-kdbus" is specified, and the kdbus.ko kernel module is available, and "kdbus" is added to the kernel command line, the entire system runs with kdbus instead of dbus-daemon, with the above mentioned problem of missing the system policy enforcement. Also a future version of kdbus.ko or a newer systemd will not be compatible with each other, and will unlikely be able to boot the machine if only one of them is updated. * systemctl gained a new "import-environment" command which uploads the caller's environment (or parts thereof) into the service manager so that it is inherited by services started by the manager. This is useful to upload variables like $DISPLAY into the user service manager. * A new PrivateDevices= switch has been added to service units which allows running a service with a namespaced /dev directory that does not contain any device nodes for physical devices. More specifically, it only includes devices such as /dev/null, /dev/urandom, and /dev/zero which are API entry points. * logind has been extended to support behaviour like VT switching on seats that do not support a VT. This makes multi-session available on seats that are not the first seat (seat0), and on systems where kernel support for VTs has been disabled at compile-time. * If a process holds a delay lock for system sleep or shutdown and fails to release it in time, we will now log its identity. This makes it easier to identify processes that cause slow suspends or power-offs. * When parsing /etc/crypttab, support for a new key-slot= option as supported by Debian is added. It allows indicating which LUKS slot to use on disk, speeding up key loading. * The sd_journald_sendv() API call has been checked and officially declared to be async-signal-safe so that it may be invoked from signal handlers for logging purposes. * Boot-time status output is now enabled automatically after a short timeout if boot does not progress, in order to give the user an indication what she or he is waiting for. * The boot-time output has been improved to show how much time remains until jobs expire. * The KillMode= switch in service units gained a new possible value "mixed". If set, and the unit is shut down, then the initial SIGTERM signal is sent only to the main daemon process, while the following SIGKILL signal is sent to all remaining processes of the service. * When a scope unit is registered, a new property "Controller" may be set. If set to a valid bus name, systemd will send a RequestStop() signal to this name when it would like to shut down the scope. This may be used to hook manager logic into the shutdown logic of scope units. Also, scope units may now be put in a special "abandoned" state, in which case the manager process which created them takes no further responsibilities for it. * When reading unit files, systemd will now verify the access mode of these files, and warn about certain suspicious combinations. This has been added to make it easier to track down packaging bugs where unit files are marked executable or world-writable. * systemd-nspawn gained a new "--setenv=" switch to set container-wide environment variables. The similar option in systemd-activate was renamed from "--environment=" to "--setenv=" for consistency. * systemd-nspawn has been updated to create a new kdbus domain for each container that is invoked, thus allowing each container to have its own set of system and user buses, independent of the host. * systemd-nspawn gained a new --drop-capability= switch to run the container with less capabilities than the default. Both --drop-capability= and --capability= now take the special string "all" for dropping or keeping all capabilities. * systemd-nspawn gained new switches for executing containers with specific SELinux labels set. * systemd-nspawn gained a new --quiet switch to not generate any additional output but the container's own console output. * systemd-nspawn gained a new --share-system switch to run a container without PID namespacing enabled. * systemd-nspawn gained a new --register= switch to control whether the container is registered with systemd-machined or not. This is useful for containers that do not run full OS images, but only specific apps. * systemd-nspawn gained a new --keep-unit which may be used when invoked as the only program from a service unit, and results in registration of the unit service itself in systemd-machined, instead of a newly opened scope unit. * systemd-nspawn gained a new --network-interface= switch for moving arbitrary interfaces to the container. The new --network-veth switch creates a virtual Ethernet connection between host and container. The new --network-bridge= switch then allows assigning the host side of this virtual Ethernet connection to a bridge device. * systemd-nspawn gained a new --personality= switch for setting the kernel personality for the container. This is useful when running a 32-bit container on a 64-bit host. A similar option Personality= is now also available for service units to use. * logind will now also track a "Desktop" identifier for each session which encodes the desktop environment of it. This is useful for desktop environments that want to identify multiple running sessions of itself easily. * A new SELinuxContext= setting for service units has been added that allows setting a specific SELinux execution context for a service. * Most systemd client tools will now honour $SYSTEMD_LESS for settings of the "less" pager. By default, these tools will override $LESS to allow certain operations to work, such as jump-to-the-end. With $SYSTEMD_LESS, it is possible to influence this logic. * systemd's "seccomp" hook-up has been changed to make use of the libseccomp library instead of using its own implementation. This has benefits for portability among other things. * For usage together with SystemCallFilter=, a new SystemCallErrorNumber= setting has been introduced that allows configuration of a system error number to be returned on filtered system calls, instead of immediately killing the process. Also, SystemCallArchitectures= has been added to limit access to system calls of a particular architecture (in order to turn off support for unused secondary architectures). There is also a global SystemCallArchitectures= setting in system.conf now to turn off support for non-native system calls system-wide. * systemd requires a kernel with a working name_to_handle_at(), please see the kernel config requirements in the README file. Contributions from: Adam Williamson, Alex Jia, Anatol Pomozov, Ansgar Burchardt, AppleBloom, Auke Kok, Bastien Nocera, Chengwei Yang, Christian Seiler, Colin Guthrie, Colin Walters, Cristian Rodríguez, Daniel Buch, Daniele Medri, Daniel J Walsh, Daniel Mack, Dan McGee, Dave Reisner, David Coppa, David Herrmann, David Strauss, Djalal Harouni, Dmitry Pisklov, Elia Pinto, Florian Weimer, George McCollister, Goffredo Baroncelli, Greg Kroah-Hartman, Hendrik Brueckner, Igor Zhbanov, Jan Engelhardt, Jan Janssen, Jason A. Donenfeld, Jason St. John, Jasper St. Pierre, Jóhann B. Guðmundsson, Jose Ignacio Naranjo, Karel Zak, Kay Sievers, Kristian Høgsberg, Lennart Poettering, Lubomir Rintel, Lukas Nykryn, Lukasz Skalski, Łukasz Stelmach, Luke Shumaker, Mantas Mikulėnas, Marc-Antoine Perennou, Marcel Holtmann, Marcos Felipe Rasia de Mello, Marko Myllynen, Martin Pitt, Matthew Monaco, Michael Marineau, Michael Scherer, Michał Górny, Michal Sekletar, Michele Curti, Oleksii Shevchuk, Olivier Brunel, Patrik Flykt, Pavel Holica, Raudi, Richard Marko, Ronny Chevalier, Sébastien Luttringer, Sergey Ptashnick, Shawn Landden, Simon Peeters, Stefan Beller, Susant Sahani, Sylvain Plantefeve, Sylvia Else, Tero Roponen, Thomas Bächler, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Umut Tezduyar Lindskog, Unai Uribarri, Václav Pavlín, Vincent Batts, WaLyong Cho, William Giokas, Yang Zhiyong, Yin Kangkai, Yuxuan Shui, Zbigniew Jędrzejewski-Szmek -- Berlin, 2014-02-20 CHANGES WITH 208: * logind has gained support for facilitating privileged input and drm device access for unprivileged clients. This work is useful to allow Wayland display servers (and similar programs, such as kmscon) to run under the user's ID and access input and drm devices which are normally protected. When this is used (and the kernel is new enough) logind will "mute" IO on the file descriptors passed to Wayland as long as it is in the background and "unmute" it if it returns into the foreground. This allows secure session switching without allowing background sessions to eavesdrop on input and display data. This also introduces session switching support if VT support is turned off in the kernel, and on seats that are not seat0. * A new kernel command line option luks.options= is understood now which allows specifying LUKS options for usage for LUKS encrypted partitions specified with luks.uuid=. * tmpfiles.d(5) snippets may now use specifier expansion in path names. More specifically %m, %b, %H, %v, are now replaced by the local machine id, boot id, hostname, and kernel version number. * A new tmpfiles.d(5) command "m" has been introduced which may be used to change the owner/group/access mode of a file or directory if it exists, but do nothing if it does not. * This release removes high-level support for the MemorySoftLimit= cgroup setting. The underlying kernel cgroup attribute memory.soft_limit= is currently badly designed and likely to be removed from the kernel API in its current form, hence we should not expose it for now. * The memory.use_hierarchy cgroup attribute is now enabled for all cgroups systemd creates in the memory cgroup hierarchy. This option is likely to be come the built-in default in the kernel anyway, and the non-hierarchical mode never made much sense in the intrinsically hierarchical cgroup system. * A new field _SYSTEMD_SLICE= is logged along with all journal messages containing the slice a message was generated from. This is useful to allow easy per-customer filtering of logs among other things. * systemd-journald will no longer adjust the group of journal files it creates to the "systemd-journal" group. Instead we rely on the journal directory to be owned by the "systemd-journal" group, and its setgid bit set, so that the kernel file system layer will automatically enforce that journal files inherit this group assignment. The reason for this change is that we cannot allow NSS look-ups from journald which would be necessary to resolve "systemd-journal" to a numeric GID, because this might create deadlocks if NSS involves synchronous queries to other daemons (such as nscd, or sssd) which in turn are logging clients of journald and might block on it, which would then dead lock. A tmpfiles.d(5) snippet included in systemd will make sure the setgid bit and group are properly set on the journal directory if it exists on every boot. However, we recommend adjusting it manually after upgrades too (or from RPM scriptlets), so that the change is not delayed until next reboot. * Backlight and random seed files in /var/lib/ have moved into the /var/lib/systemd/ directory, in order to centralize all systemd generated files in one directory. * Boot time performance measurements (as displayed by "systemd-analyze" for example) will now read ACPI 5.0 FPDT performance information if that's available to determine how much time BIOS and boot loader initialization required. With a sufficiently new BIOS you hence no longer need to boot with Gummiboot to get access to such information. Contributions from: Andrey Borzenkov, Chen Jie, Colin Walters, Cristian Rodríguez, Dave Reisner, David Herrmann, David Mackey, David Strauss, Eelco Dolstra, Evan Callicoat, Gao feng, Harald Hoyer, Jimmie Tauriainen, Kay Sievers, Lennart Poettering, Lukas Nykryn, Mantas Mikulėnas, Martin Pitt, Michael Scherer, Michał Górny, Mike Gilbert, Patrick McCarty, Sebastian Ott, Tom Gundersen, Zbigniew Jędrzejewski-Szmek -- Berlin, 2013-10-02 CHANGES WITH 207: * The Restart= option for services now understands a new on-watchdog setting, which will restart the service automatically if the service stops sending out watchdog keep alive messages (as configured with WatchdogSec=). * The getty generator (which is responsible for bringing up a getty on configured serial consoles) will no longer only start a getty on the primary kernel console but on all others, too. This makes the order in which console= is specified on the kernel command line less important. * libsystemd-logind gained a new sd_session_get_vt() call to retrieve the VT number of a session. * If the option "tries=0" is set for an entry of /etc/crypttab its passphrase is queried indefinitely instead of any maximum number of tries. * If a service with a configure PID file terminates its PID file will now be removed automatically if it still exists afterwards. This should put an end to stale PID files. * systemd-run will now also take relative binary path names for execution and no longer insists on absolute paths. * InaccessibleDirectories= and ReadOnlyDirectories= now take paths that are optionally prefixed with "-" to indicate that it should not be considered a failure if they do not exist. * journalctl -o (and similar commands) now understands a new output mode "short-precise", it is similar to "short" but shows timestamps with usec accuracy. * The option "discard" (as known from Debian) is now synonymous to "allow-discards" in /etc/crypttab. In fact, "discard" is preferred now (since it is easier to remember and type). * Some licensing clean-ups were made, so that more code is now LGPL-2.1 licensed than before. * A minimal tool to save/restore the display backlight brightness across reboots has been added. It will store the backlight setting as late as possible at shutdown, and restore it as early as possible during reboot. * A logic to automatically discover and enable home and swap partitions on GPT disks has been added. With this in place /etc/fstab becomes optional for many setups as systemd can discover certain partitions located on the root disk automatically. Home partitions are recognized under their GPT type ID 933ac7e12eb44f13b8440e14e2aef915. Swap partitions are recognized under their GPT type ID 0657fd6da4ab43c484e50933c84b4f4f. * systemd will no longer pass any environment from the kernel or initrd to system services. If you want to set an environment for all services, do so via the kernel command line systemd.setenv= assignment. * The systemd-sysctl tool no longer natively reads the file /etc/sysctl.conf. If desired, the file should be symlinked from /etc/sysctl.d/99-sysctl.conf. Apart from providing legacy support by a symlink rather than built-in code, it also makes the otherwise hidden order of application of the different files visible. (Note that this partly reverts to a pre-198 application order of sysctl knobs!) * The "systemctl set-log-level" and "systemctl dump" commands have been moved to systemd-analyze. * systemd-run learned the new --remain-after-exit switch, which causes the scope unit not to be cleaned up automatically after the process terminated. * tmpfiles learned a new --exclude-prefix= switch to exclude certain paths from operation. * journald will now automatically flush all messages to disk as soon as a message at the log level CRIT, ALERT or EMERG is received. Contributions from: Andrew Cook, Brandon Philips, Christian Hesse, Christoph Junghans, Colin Walters, Daniel Schaal, Daniel Wallace, Dave Reisner, David Herrmann, Gao feng, George McCollister, Giovanni Campagna, Hannes Reinecke, Harald Hoyer, Herczeg Zsolt, Holger Hans Peter Freyther, Jan Engelhardt, Jesper Larsen, Kay Sievers, Khem Raj, Lennart Poettering, Lukas Nykryn, Maciej Wereski, Mantas Mikulėnas, Marcel Holtmann, Martin Pitt, Michael Biebl, Michael Marineau, Michael Scherer, Michael Stapelberg, Michal Sekletar, Michał Górny, Olivier Brunel, Ondrej Balaz, Ronny Chevalier, Shawn Landden, Steven Hiscocks, Thomas Bächler, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Umut Tezduyar, WANG Chao, William Giokas, Zbigniew Jędrzejewski-Szmek -- Berlin, 2013-09-13 CHANGES WITH 206: * The documentation has been updated to cover the various new concepts introduced with 205. * Unit files now understand the new %v specifier which resolves to the kernel version string as returned by "uname -r". * systemctl now supports filtering the unit list output by load state, active state and sub state, using the new --state= parameter. * "systemctl status" will now show the results of the condition checks (like ConditionPathExists= and similar) of the last start attempts of the unit. They are also logged to the journal. * "journalctl -b" may now be used to look for boot output of a specific boot. Try "journalctl -b -1" for the previous boot, but the syntax is substantially more powerful. * "journalctl --show-cursor" has been added which prints the cursor string the last shown log line. This may then be used with the new "journalctl --after-cursor=" switch to continue browsing logs from that point on. * "journalctl --force" may now be used to force regeneration of an FSS key. * Creation of "dead" device nodes has been moved from udev into kmod and tmpfiles. Previously, udev would read the kmod databases to pre-generate dead device nodes based on meta information contained in kernel modules, so that these would be auto-loaded on access rather then at boot. As this does not really have much to do with the exposing actual kernel devices to userspace this has always been slightly alien in the udev codebase. Following the new scheme kmod will now generate a runtime snippet for tmpfiles from the module meta information and it now is tmpfiles' job to the create the nodes. This also allows overriding access and other parameters for the nodes using the usual tmpfiles facilities. As side effect this allows us to remove the CAP_SYS_MKNOD capability bit from udevd entirely. * logind's device ACLs may now be applied to these "dead" devices nodes too, thus finally allowing managed access to devices such as /dev/snd/sequencer whithout loading the backing module right-away. * A new RPM macro has been added that may be used to apply tmpfiles configuration during package installation. * systemd-detect-virt and ConditionVirtualization= now can detect User-Mode-Linux machines (UML). * journald will now implicitly log the effective capabilities set of processes in the message metadata. * systemd-cryptsetup has gained support for TrueCrypt volumes. * The initrd interface has been simplified (more specifically, support for passing performance data via environment variables and fsck results via files in /run has been removed). These features were non-essential, and are nowadays available in a much nicer way by having systemd in the initrd serialize its state and have the hosts systemd deserialize it again. * The udev "keymap" data files and tools to apply keyboard specific mappings of scan to key codes, and force-release scan code lists have been entirely replaced by a udev "keyboard" builtin and a hwdb data file. * systemd will now honour the kernel's "quiet" command line argument also during late shutdown, resulting in a completely silent shutdown when used. * There's now an option to control the SO_REUSEPORT socket option in .socket units. * Instance units will now automatically get a per-template subslice of system.slice unless something else is explicitly configured. For example, instances of sshd@.service will now implicitly be placed in system-sshd.slice rather than system.slice as before. * Test coverage support may now be enabled at build time. Contributions from: Dave Reisner, Frederic Crozat, Harald Hoyer, Holger Hans Peter Freyther, Jan Engelhardt, Jan Janssen, Jason St. John, Jesper Larsen, Kay Sievers, Lennart Poettering, Lukas Nykryn, Maciej Wereski, Martin Pitt, Michael Olbrich, Ramkumar Ramachandra, Ross Lagerwall, Shawn Landden, Thomas H.P. Andersen, Tom Gundersen, Tomasz Torcz, William Giokas, Zbigniew Jędrzejewski-Szmek -- Berlin, 2013-07-23 CHANGES WITH 205: * Two new unit types have been introduced: Scope units are very similar to service units, however, are created out of pre-existing processes -- instead of PID 1 forking off the processes. By using scope units it is possible for system services and applications to group their own child processes (worker processes) in a powerful way which then maybe used to organize them, or kill them together, or apply resource limits on them. Slice units may be used to partition system resources in an hierarchical fashion and then assign other units to them. By default there are now three slices: system.slice (for all system services), user.slice (for all user sessions), machine.slice (for VMs and containers). Slices and scopes have been introduced primarily in context of the work to move cgroup handling to a single-writer scheme, where only PID 1 creates/removes/manages cgroups. * There's a new concept of "transient" units. In contrast to normal units these units are created via an API at runtime, not from configuration from disk. More specifically this means it is now possible to run arbitrary programs as independent services, with all execution parameters passed in via bus APIs rather than read from disk. Transient units make systemd substantially more dynamic then it ever was, and useful as a general batch manager. * logind has been updated to make use of scope and slice units for managing user sessions. As a user logs in he will get his own private slice unit, to which all sessions are added as scope units. We also added support for automatically adding an instance of user@.service for the user into the slice. Effectively logind will no longer create cgroup hierarchies on its own now, it will defer entirely to PID 1 for this by means of scope, service and slice units. Since user sessions this way become entities managed by PID 1 the output of "systemctl" is now a lot more comprehensive. * A new mini-daemon "systemd-machined" has been added which may be used by virtualization managers to register local VMs/containers. nspawn has been updated accordingly, and libvirt will be updated shortly. machined will collect a bit of meta information about the VMs/containers, and assign them their own scope unit (see above). The collected meta-data is then made available via the "machinectl" tool, and exposed in "ps" and similar tools. machined/machinectl is compile-time optional. * As discussed earlier, the low-level cgroup configuration options ControlGroup=, ControlGroupModify=, ControlGroupPersistent=, ControlGroupAttribute= have been removed. Please use high-level attribute settings instead as well as slice units. * A new bus call SetUnitProperties() has been added to alter various runtime parameters of a unit. This is primarily useful to alter cgroup parameters dynamically in a nice way, but will be extended later on to make more properties modifiable at runtime. systemctl gained a new set-properties command that wraps this call. * A new tool "systemd-run" has been added which can be used to run arbitrary command lines as transient services or scopes, while configuring a number of settings via the command line. This tool is currently very basic, however already very useful. We plan to extend this tool to even allow queuing of execution jobs with time triggers from the command line, similar in fashion to "at". * nspawn will now inform the user explicitly that kernels with audit enabled break containers, and suggest the user to turn off audit. * Support for detecting the IMA and AppArmor security frameworks with ConditionSecurity= has been added. * journalctl gained a new "-k" switch for showing only kernel messages, mimicking dmesg output; in addition to "--user" and "--system" switches for showing only user's own logs and system logs. * systemd-delta can now show information about drop-in snippets extending unit files. * libsystemd-bus has been substantially updated but is still not available as public API. * systemd will now look for the "debug" argument on the kernel command line and enable debug logging, similar to what "systemd.log_level=debug" already did before. * "systemctl set-default", "systemctl get-default" has been added to configure the default.target symlink, which controls what to boot into by default. * "systemctl set-log-level" has been added as a convenient way to raise and lower systemd logging threshold. * "systemd-analyze plot" will now show the time the various generators needed for execution, as well as information about the unit file loading. * libsystemd-journal gained a new sd_journal_open_files() call for opening specific journal files. journactl also gained a new switch to expose this new functionality. Previously we only supported opening all files from a directory, or all files from the system, as opening individual files only is racy due to journal file rotation. * systemd gained the new DefaultEnvironment= setting in /etc/systemd/system.conf to set environment variables for all services. * If a privileged process logs a journal message with the OBJECT_PID= field set, then journald will automatically augment this with additional OBJECT_UID=, OBJECT_GID=, OBJECT_COMM=, OBJECT_EXE=, ... fields. This is useful if system services want to log events about specific client processes. journactl/systemctl has been updated to make use of this information if all log messages regarding a specific unit is requested. Contributions from: Auke Kok, Chengwei Yang, Colin Walters, Cristian Rodríguez, Daniel Albers, Daniel Wallace, Dave Reisner, David Coppa, David King, David Strauss, Eelco Dolstra, Gabriel de Perthuis, Harald Hoyer, Jan Alexander Steffens, Jan Engelhardt, Jan Janssen, Jason St. John, Johan Heikkilä, Karel Zak, Karol Lewandowski, Kay Sievers, Lennart Poettering, Lukas Nykryn, Mantas Mikulėnas, Marius Vollmer, Martin Pitt, Michael Biebl, Michael Olbrich, Michael Tremer, Michal Schmidt, Michał Bartoszkiewicz, Nirbheek Chauhan, Pierre Neidhardt, Ross Burton, Ross Lagerwall, Sean McGovern, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Umut Tezduyar, Václav Pavlín, Zachary Cook, Zbigniew Jędrzejewski-Szmek, Łukasz Stelmach, 장동준 CHANGES WITH 204: * The Python bindings gained some minimal support for the APIs exposed by libsystemd-logind. * ConditionSecurity= gained support for detecting SMACK. Since this condition already supports SELinux and AppArmor we only miss IMA for this. Patches welcome! Contributions from: Karol Lewandowski, Lennart Poettering, Zbigniew Jędrzejewski-Szmek CHANGES WITH 203: * systemd-nspawn will now create /etc/resolv.conf if necessary, before bind-mounting the host's file onto it. * systemd-nspawn will now store meta information about a container on the container's cgroup as extended attribute fields, including the root directory. * The cgroup hierarchy has been reworked in many ways. All objects any of the components systemd creates in the cgroup tree are now suffixed. More specifically, user sessions are now placed in cgroups suffixed with ".session", users in cgroups suffixed with ".user", and nspawn containers in cgroups suffixed with ".nspawn". Furthermore, all cgroup names are now escaped in a simple scheme to avoid collision of userspace object names with kernel filenames. This work is preparation for making these objects relocatable in the cgroup tree, in order to allow easy resource partitioning of these objects without causing naming conflicts. * systemctl list-dependencies gained the new switches --plain, --reverse, --after and --before. * systemd-inhibit now shows the process name of processes that have taken an inhibitor lock. * nss-myhostname will now also resolve "localhost" implicitly. This makes /etc/hosts an optional file and nicely handles that on IPv6 ::1 maps to both "localhost" and the local hostname. * libsystemd-logind.so gained a new call sd_get_machine_names() to enumerate running containers and VMs (currently only supported by very new libvirt and nspawn). sd_login_monitor can now be used to watch VMs/containers coming and going. * .include is not allowed recursively anymore, and only in unit files. Usually it is better to use drop-in snippets in .d/*.conf anyway, as introduced with systemd 198. * systemd-analyze gained a new "critical-chain" command that determines the slowest chain of units run during system boot-up. It is very useful for tracking down where optimizing boot time is the most beneficial. * systemd will no longer allow manipulating service paths in the name=systemd:/system cgroup tree using ControlGroup= in units. (But is still fine with it in all other dirs.) * There's a new systemd-nspawn@.service service file that may be used to easily run nspawn containers as system services. With the container's root directory in /var/lib/container/foobar it is now sufficient to run "systemctl start systemd-nspawn@foobar.service" to boot it. * systemd-cgls gained a new parameter "--machine" to list only the processes within a certain container. * ConditionSecurity= now can check for "apparmor". We still are lacking checks for SMACK and IMA for this condition check though. Patches welcome! * A new configuration file /etc/systemd/sleep.conf has been added that may be used to configure which kernel operation systemd is supposed to execute when "suspend", "hibernate" or "hybrid-sleep" is requested. This makes the new kernel "freeze" state accessible to the user. * ENV{SYSTEMD_WANTS} in udev rules will now implicitly escape the passed argument if applicable. Contributions from: Auke Kok, Colin Guthrie, Colin Walters, Cristian Rodríguez, Daniel Buch, Daniel Wallace, Dave Reisner, Evangelos Foutras, Greg Kroah-Hartman, Harald Hoyer, Josh Triplett, Kay Sievers, Lennart Poettering, Lukas Nykryn, MUNEDA Takahiro, Mantas Mikulėnas, Mirco Tischler, Nathaniel Chen, Nirbheek Chauhan, Ronny Chevalier, Ross Lagerwall, Tom Gundersen, Umut Tezduyar, Ville Skyttä, Zbigniew Jędrzejewski-Szmek CHANGES WITH 202: * The output of 'systemctl list-jobs' got some polishing. The '--type=' argument may now be passed more than once. A new command 'systemctl list-sockets' has been added which shows a list of kernel sockets systemd is listening on with the socket units they belong to, plus the units these socket units activate. * The experimental libsystemd-bus library got substantial updates to work in conjunction with the (also experimental) kdbus kernel project. It works well enough to exchange messages with some sophistication. Note that kdbus is not ready yet, and the library is mostly an elaborate test case for now, and not installable. * systemd gained a new unit 'systemd-static-nodes.service' that generates static device nodes earlier during boot, and can run in conjunction with udev. * libsystemd-login gained a new call sd_pid_get_user_unit() to retrieve the user systemd unit a process is running in. This is useful for systems where systemd is used as session manager. * systemd-nspawn now places all containers in the new /machine top-level cgroup directory in the name=systemd hierarchy. libvirt will soon do the same, so that we get a uniform separation of /system, /user and /machine for system services, user processes and containers/virtual machines. This new cgroup hierarchy is also useful to stick stable names to specific container instances, which can be recognized later this way (this name may be controlled via systemd-nspawn's new -M switch). libsystemd-login also gained a new call sd_pid_get_machine_name() to retrieve the name of the container/VM a specific process belongs to. * bootchart can now store its data in the journal. * libsystemd-journal gained a new call sd_journal_add_conjunction() for AND expressions to the matching logic. This can be used to express more complex logical expressions. * journactl can now take multiple --unit= and --user-unit= switches. * The cryptsetup logic now understands the "luks.key=" kernel command line switch for specifying a file to read the decryption key from. Also, if a configured key file is not found the tool will now automatically fall back to prompting the user. * Python systemd.journal module was updated to wrap recently added functions from libsystemd-journal. The interface was changed to bring the low level interface in s.j._Reader closer to the C API, and the high level interface in s.j.Reader was updated to wrap and convert all data about an entry. Contributions from: Anatol Pomozov, Auke Kok, Harald Hoyer, Henrik Grindal Bakken, Josh Triplett, Kay Sievers, Lennart Poettering, Lukas Nykryn, Mantas Mikulėnas Marius Vollmer, Martin Jansa, Martin Pitt, Michael Biebl, Michal Schmidt, Mirco Tischler, Pali Rohar, Simon Peeters, Steven Hiscocks, Tom Gundersen, Zbigniew Jędrzejewski-Szmek CHANGES WITH 201: * journalctl --update-catalog now understands a new --root= option to operate on catalogs found in a different root directory. * During shutdown after systemd has terminated all running services a final killing loop kills all remaining left-over processes. We will now print the name of these processes when we send SIGKILL to them, since this usually indicates a problem. * If /etc/crypttab refers to password files stored on configured mount points automatic dependencies will now be generated to ensure the specific mount is established first before the key file is attempted to be read. * 'systemctl status' will now show information about the network sockets a socket unit is listening on. * 'systemctl status' will also shown information about any drop-in configuration file for units. (Drop-In configuration files in this context are files such as /etc/systemd/systemd/foobar.service.d/*.conf) * systemd-cgtop now optionally shows summed up CPU times of cgroups. Press '%' while running cgtop to switch between percentage and absolute mode. This is useful to determine which cgroups use up the most CPU time over the entire runtime of the system. systemd-cgtop has also been updated to be 'pipeable' for processing with further shell tools. * 'hostnamectl set-hostname' will now allow setting of FQDN hostnames. * The formatting and parsing of time span values has been changed. The parser now understands fractional expressions such as "5.5h". The formatter will now output fractional expressions for all time spans under 1min, i.e. "5.123456s" rather than "5s 123ms 456us". For time spans under 1s millisecond values are shown, for those under 1ms microsecond values are shown. This should greatly improve all time-related output of systemd. * libsystemd-login and libsystemd-journal gained new functions for querying the poll() events mask and poll() timeout value for integration into arbitrary event loops. * localectl gained the ability to list available X11 keymaps (models, layouts, variants, options). * 'systemd-analyze dot' gained the ability to filter for specific units via shell-style globs, to create smaller, more useful graphs. I.e. it is now possible to create simple graphs of all the dependencies between only target units, or of all units that Avahi has dependencies with. Contributions from: Cristian Rodríguez, Dr. Tilmann Bubeck, Harald Hoyer, Holger Hans Peter Freyther, Kay Sievers, Kelly Anderson, Koen Kooi, Lennart Poettering, Maksim Melnikau, Marc-Antoine Perennou, Marius Vollmer, Martin Pitt, Michal Schmidt, Oleksii Shevchuk, Ronny Chevalier, Simon McVittie, Steven Hiscocks, Thomas Weißschuh, Umut Tezduyar, Václav Pavlín, Zbigniew Jędrzejewski-Szmek, Łukasz Stelmach CHANGES WITH 200: * The boot-time readahead implementation for rotating media will now read the read-ahead data in multiple passes which consist of all read requests made in equidistant time intervals. This means instead of strictly reading read-ahead data in its physical order on disk we now try to find a middle ground between physical and access time order. * /etc/os-release files gained a new BUILD_ID= field for usage on operating systems that provide continuous builds of OS images. Contributions from: Auke Kok, Eelco Dolstra, Kay Sievers, Lennart Poettering, Lukas Nykryn, Martin Pitt, Václav Pavlín William Douglas, Zbigniew Jędrzejewski-Szmek CHANGES WITH 199: * systemd-python gained an API exposing libsystemd-daemon. * The SMACK setup logic gained support for uploading CIPSO security policy. * Behaviour of PrivateTmp=, ReadWriteDirectories=, ReadOnlyDirectories= and InaccessibleDirectories= has changed. The private /tmp and /var/tmp directories are now shared by all processes of a service (which means ExecStartPre= may now leave data in /tmp that ExecStart= of the same service can still access). When a service is stopped its temporary directories are immediately deleted (normal clean-up with tmpfiles is still done in addition to this though). * By default, systemd will now set a couple of sysctl variables in the kernel: the safe sysrq options are turned on, IP route verification is turned on, and source routing disabled. The recently added hardlink and softlink protection of the kernel is turned on. These settings should be reasonably safe, and good defaults for all new systems. * The predictable network naming logic may now be turned off with a new kernel command line switch: net.ifnames=0. * A new libsystemd-bus module has been added that implements a pretty complete D-Bus client library. For details see: http://lists.freedesktop.org/archives/systemd-devel/2013-March/009797.html * journald will now explicitly flush the journal files to disk at the latest 5min after each write. The file will then also be marked offline until the next write. This should increase reliability in case of a crash. The synchronization delay can be configured via SyncIntervalSec= in journald.conf. * There's a new remote-fs-setup.target unit that can be used to pull in specific services when at least one remote file system is to be mounted. * There are new targets timers.target and paths.target as canonical targets to pull user timer and path units in from. This complements sockets.target with a similar purpose for socket units. * libudev gained a new call udev_device_set_attribute_value() to set sysfs attributes of a device. * The udev daemon now sets the default number of worker processes executed in parallel based on the number of available CPUs instead of the amount of available RAM. This is supposed to provide a more reliable default and limit a too aggressive paralellism for setups with 1000s of devices connected. Contributions from: Auke Kok, Colin Walters, Cristian Rodríguez, Daniel Buch, Dave Reisner, Frederic Crozat, Hannes Reinecke, Harald Hoyer, Jan Alexander Steffens, Jan Engelhardt, Josh Triplett, Kay Sievers, Lennart Poettering, Mantas Mikulėnas, Martin Pitt, Mathieu Bridon, Michael Biebl, Michal Schmidt, Michal Sekletar, Miklos Vajna, Nathaniel Chen, Oleksii Shevchuk, Ozan Çağlayan, Thomas Hindoe Paaboel Andersen, Tollef Fog Heen, Tom Gundersen, Umut Tezduyar, Zbigniew Jędrzejewski-Szmek CHANGES WITH 198: * Configuration of unit files may now be extended via drop-in files without having to edit/override the unit files themselves. More specifically, if the administrator wants to change one value for a service file foobar.service he can now do so by dropping in a configuration snippet into /etc/systemd/system/foobar.service.d/*.conf. The unit logic will load all these snippets and apply them on top of the main unit configuration file, possibly extending or overriding its settings. Using these drop-in snippets is generally nicer than the two earlier options for changing unit files locally: copying the files from /usr/lib/systemd/system/ to /etc/systemd/system/ and editing them there; or creating a new file in /etc/systemd/system/ that incorporates the original one via ".include". Drop-in snippets into these .d/ directories can be placed in any directory systemd looks for units in, and the usual overriding semantics between /usr/lib, /etc and /run apply for them too. * Most unit file settings which take lists of items can now be reset by assigning the empty string to them. For example, normally, settings such as Environment=FOO=BAR append a new environment variable assignment to the environment block, each time they are used. By assigning Environment= the empty string the environment block can be reset to empty. This is particularly useful with the .d/*.conf drop-in snippets mentioned above, since this adds the ability to reset list settings from vendor unit files via these drop-ins. * systemctl gained a new "list-dependencies" command for listing the dependencies of a unit recursively. * Inhibitors are now honored and listed by "systemctl suspend", "systemctl poweroff" (and similar) too, not only GNOME. These commands will also list active sessions by other users. * Resource limits (as exposed by the various control group controllers) can now be controlled dynamically at runtime for all units. More specifically, you can now use a command like "systemctl set-cgroup-attr foobar.service cpu.shares 2000" to alter the CPU shares a specific service gets. These settings are stored persistently on disk, and thus allow the administrator to easily adjust the resource usage of services with a few simple commands. This dynamic resource management logic is also available to other programs via the bus. Almost any kernel cgroup attribute and controller is supported. * systemd-vconsole-setup will now copy all font settings to all allocated VTs, where it previously applied them only to the foreground VT. * libsystemd-login gained the new sd_session_get_tty() API call. * This release drops support for a few legacy or distribution-specific LSB facility names when parsing init scripts: $x-display-manager, $mail-transfer-agent, $mail-transport-agent, $mail-transfer-agent, $smtp, $null. Also, the mail-transfer-agent.target unit backing this has been removed. Distributions which want to retain compatibility with this should carry the burden for supporting this themselves and patch support for these back in, if they really need to. Also, the facilities $syslog and $local_fs are now ignored, since systemd does not support early-boot LSB init scripts anymore, and these facilities are implied anyway for normal services. syslog.target has also been removed. * There are new bus calls on PID1's Manager object for cancelling jobs, and removing snapshot units. Previously, both calls were only available on the Job and Snapshot objects themselves. * systemd-journal-gatewayd gained SSL support. * The various "environment" files, such as /etc/locale.conf now support continuation lines with a backslash ("\") as last character in the line, similarly in style (but different) to how this is supported in shells. * For normal user processes the _SYSTEMD_USER_UNIT= field is now implicitly appended to every log entry logged. systemctl has been updated to filter by this field when operating on a user systemd instance. * nspawn will now implicitly add the CAP_AUDIT_WRITE and CAP_AUDIT_CONTROL capabilities to the capabilities set for the container. This makes it easier to boot unmodified Fedora systems in a container, which however still requires audit=0 to be passed on the kernel command line. Auditing in kernel and userspace is unfortunately still too broken in context of containers, hence we recommend compiling it out of the kernel or using audit=0. Hopefully this will be fixed one day for good in the kernel. * nspawn gained the new --bind= and --bind-ro= parameters to bind mount specific directories from the host into the container. * nspawn will now mount its own devpts file system instance into the container, in order not to leak pty devices from the host into the container. * systemd will now read the firmware boot time performance information from the EFI variables, if the used boot loader supports this, and takes it into account for boot performance analysis via "systemd-analyze". This is currently supported only in conjunction with Gummiboot, but could be supported by other boot loaders too. For details see: http://www.freedesktop.org/wiki/Software/systemd/BootLoaderInterface * A new generator has been added that automatically mounts the EFI System Partition (ESP) to /boot, if that directory exists, is empty, and no other file system has been configured to be mounted there. * logind will now send out PrepareForSleep(false) out unconditionally, after coming back from suspend. This may be used by applications as asynchronous notification for system resume events. * "systemctl unlock-sessions" has been added, that allows unlocking the screens of all user sessions at once, similar to how "systemctl lock-sessions" already locked all users sessions. This is backed by a new D-Bus call UnlockSessions(). * "loginctl seat-status" will now show the master device of a seat. (i.e. the device of a seat that needs to be around for the seat to be considered available, usually the graphics card). * tmpfiles gained a new "X" line type, that allows configuration of files and directories (with wildcards) that shall be excluded from automatic cleanup ("aging"). * udev default rules set the device node permissions now only at "add" events, and do not change them any longer with a later "change" event. * The log messages for lid events and power/sleep keypresses now carry a message ID. * We now have a substantially larger unit test suite, but this continues to be work in progress. * udevadm hwdb gained a new --root= parameter to change the root directory to operate relative to. * logind will now issue a background sync() request to the kernel early at shutdown, so that dirty buffers are flushed to disk early instead of at the last moment, in order to optimize shutdown times a little. * A new bootctl tool has been added that is an interface for certain boot loader operations. This is currently a preview and is likely to be extended into a small mechanism daemon like timedated, localed, hostnamed, and can be used by graphical UIs to enumerate available boot options, and request boot into firmware operations. * systemd-bootchart has been relicensed to LGPLv2.1+ to match the rest of the package. It also has been updated to work correctly in initrds. * Policykit previously has been runtime optional, and is now also compile time optional via a configure switch. * systemd-analyze has been reimplemented in C. Also "systemctl dot" has moved into systemd-analyze. * "systemctl status" with no further parameters will now print the status of all active or failed units. * Operations such as "systemctl start" can now be executed with a new mode "--irreversible" which may be used to queue operations that cannot accidentally be reversed by a later job queuing. This is by default used to make shutdown requests more robust. * The Python API of systemd now gained a new module for reading journal files. * A new tool kernel-install has been added that can install kernel images according to the Boot Loader Specification: http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec * Boot time console output has been improved to provide animated boot time output for hanging jobs. * A new tool systemd-activate has been added which can be used to test socket activation with, directly from the command line. This should make it much easier to test and debug socket activation in daemons. * journalctl gained a new "--reverse" (or -r) option to show journal output in reverse order (i.e. newest line first). * journalctl gained a new "--pager-end" (or -e) option to jump to immediately jump to the end of the journal in the pager. This is only supported in conjunction with "less". * journalctl gained a new "--user-unit=" option, that works similarly to "--unit=" but filters for user units rather than system units. * A number of unit files to ease adoption of systemd in initrds has been added. This moves some minimal logic from the various initrd implementations into systemd proper. * The journal files are now owned by a new group "systemd-journal", which exists specifically to allow access to the journal, and nothing else. Previously, we used the "adm" group for that, which however possibly covers more than just journal/log file access. This new group is now already used by systemd-journal-gatewayd to ensure this daemon gets access to the journal files and as little else as possible. Note that "make install" will also set FS ACLs up for /var/log/journal to give "adm" and "wheel" read access to it, in addition to "systemd-journal" which owns the journal files. We recommend that packaging scripts also add read access to "adm" + "wheel" to /var/log/journal, and all existing/future journal files. To normal users and administrators little changes, however packagers need to ensure to create the "systemd-journal" system group at package installation time. * The systemd-journal-gatewayd now runs as unprivileged user systemd-journal-gateway:systemd-journal-gateway. Packaging scripts need to create these system user/group at installation time. * timedated now exposes a new boolean property CanNTP that indicates whether a local NTP service is available or not. * systemd-detect-virt will now also detect xen PVs * The pstore file system is now mounted by default, if it is available. * In addition to the SELinux and IMA policies we will now also load SMACK policies at early boot. Contributions from: Adel Gadllah, Aleksander Morgado, Auke Kok, Ayan George, Bastien Nocera, Colin Walters, Daniel Buch, Daniel Wallace, Dave Reisner, David Herrmann, David Strauss, Eelco Dolstra, Enrico Scholz, Frederic Crozat, Harald Hoyer, Jan Janssen, Jonathan Callen, Kay Sievers, Lennart Poettering, Lukas Nykryn, Mantas Mikulėnas, Marc-Antoine Perennou, Martin Pitt, Mauro Dreissig, Max F. Albrecht, Michael Biebl, Michael Olbrich, Michal Schmidt, Michal Sekletar, Michal Vyskocil, Michał Bartoszkiewicz, Mirco Tischler, Nathaniel Chen, Nestor Ovroy, Oleksii Shevchuk, Paul W. Frields, Piotr Drąg, Rob Clark, Ryan Lortie, Simon McVittie, Simon Peeters, Steven Hiscocks, Thomas Hindoe Paaboel Andersen, Tollef Fog Heen, Tom Gundersen, Umut Tezduyar, William Giokas, Zbigniew Jędrzejewski-Szmek, Zeeshan Ali (Khattak) CHANGES WITH 197: * Timer units now support calendar time events in addition to monotonic time events. That means you can now trigger a unit based on a calendar time specification such as "Thu,Fri 2013-*-1,5 11:12:13" which refers to 11:12:13 of the first or fifth day of any month of the year 2013, given that it is a thursday or friday. This brings timer event support considerably closer to cron's capabilities. For details on the supported calendar time specification language see systemd.time(7). * udev now supports a number of different naming policies for network interfaces for predictable names, and a combination of these policies is now the default. Please see this wiki document for details: http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames * Auke Kok's bootchart implementation has been added to the systemd tree. It is an optional component that can graph the boot in quite some detail. It is one of the best bootchart implementations around and minimal in its code and dependencies. * nss-myhostname has been integrated into the systemd source tree. nss-myhostname guarantees that the local hostname always stays resolvable via NSS. It has been a weak requirement of systemd-hostnamed since a long time, and since its code is actually trivial we decided to just include it in systemd's source tree. It can be turned off with a configure switch. * The read-ahead logic is now capable of properly detecting whether a btrfs file system is on SSD or rotating media, in order to optimize the read-ahead scheme. Previously, it was only capable of detecting this on traditional file systems such as ext4. * In udev, additional device properties are now read from the IAB in addition to the OUI database. Also, Bluetooth company identities are attached to the devices as well. * In service files %U may be used as specifier that is replaced by the configured user name of the service. * nspawn may now be invoked without a controlling TTY. This makes it suitable for invocation as its own service. This may be used to set up a simple containerized server system using only core OS tools. * systemd and nspawn can now accept socket file descriptors when they are started for socket activation. This enables implementation of socket activated nspawn containers. i.e. think about autospawning an entire OS image when the first SSH or HTTP connection is received. We expect that similar functionality will also be added to libvirt-lxc eventually. * journalctl will now suppress ANSI color codes when presenting log data. * systemctl will no longer show control group information for a unit if a the control group is empty anyway. * logind can now automatically suspend/hibernate/shutdown the system on idle. * /etc/machine-info and hostnamed now also expose the chassis type of the system. This can be used to determine whether the local system is a laptop, desktop, handset or tablet. This information may either be configured by the user/vendor or is automatically determined from ACPI and DMI information if possible. * A number of PolicyKit actions are now bound together with "imply" rules. This should simplify creating UIs because many actions will now authenticate similar ones as well. * Unit files learnt a new condition ConditionACPower= which may be used to conditionalize a unit depending on whether an AC power source is connected or not, of whether the system is running on battery power. * systemctl gained a new "is-failed" verb that may be used in shell scripts and suchlike to check whether a specific unit is in the "failed" state. * The EnvironmentFile= setting in unit files now supports file globbing, and can hence be used to easily read a number of environment files at once. * systemd will no longer detect and recognize specific distributions. All distribution-specific #ifdeffery has been removed, systemd is now fully generic and distribution-agnostic. Effectively, not too much is lost as a lot of the code is still accessible via explicit configure switches. However, support for some distribution specific legacy configuration file formats has been dropped. We recommend distributions to simply adopt the configuration files everybody else uses now and convert the old configuration from packaging scripts. Most distributions already did that. If that's not possible or desirable, distributions are welcome to forward port the specific pieces of code locally from the git history. * When logging a message about a unit systemd will now always log the unit name in the message meta data. * localectl will now also discover system locale data that is not stored in locale archives, but directly unpacked. * logind will no longer unconditionally use framebuffer devices as seat masters, i.e. as devices that are required to be existing before a seat is considered preset. Instead, it will now look for all devices that are tagged as "seat-master" in udev. By default, framebuffer devices will be marked as such, but depending on local systems, other devices might be marked as well. This may be used to integrate graphics cards using closed source drivers (such as NVidia ones) more nicely into logind. Note however, that we recommend using the open source NVidia drivers instead, and no udev rules for the closed-source drivers will be shipped from us upstream. Contributions from: Adam Williamson, Alessandro Crismani, Auke Kok, Colin Walters, Daniel Wallace, Dave Reisner, David Herrmann, David Strauss, Dimitrios Apostolou, Eelco Dolstra, Eric Benoit, Giovanni Campagna, Hannes Reinecke, Henrik Grindal Bakken, Hermann Gausterer, Kay Sievers, Lennart Poettering, Lukas Nykryn, Mantas Mikulėnas, Marcel Holtmann, Martin Pitt, Matthew Monaco, Michael Biebl, Michael Terry, Michal Schmidt, Michal Sekletar, Michał Bartoszkiewicz, Oleg Samarin, Pekka Lundstrom, Philip Nilsson, Ramkumar Ramachandra, Richard Yao, Robert Millan, Sami Kerola, Shawn Landden, Thomas Hindoe Paaboel Andersen, Thomas Jarosch, Tollef Fog Heen, Tom Gundersen, Umut Tezduyar, Zbigniew Jędrzejewski-Szmek CHANGES WITH 196: * udev gained support for loading additional device properties from an indexed database that is keyed by vendor/product IDs and similar device identifiers. For the beginning this "hwdb" is populated with data from the well-known PCI and USB database, but also includes PNP, ACPI and OID data. In the longer run this indexed database shall grow into becoming the one central database for non-essential userspace device metadata. Previously, data from the PCI/USB database was only attached to select devices, since the lookup was a relatively expensive operation due to O(n) time complexity (with n being the number of entries in the database). Since this is now O(1), we decided to add in this data for all devices where this is available, by default. Note that the indexed database needs to be rebuilt when new data files are installed. To achieve this you need to update your packaging scripts to invoke "udevadm hwdb --update" after installation of hwdb data files. For RPM-based distributions we introduced the new %udev_hwdb_update macro for this purpose. * The Journal gained support for the "Message Catalog", an indexed database to link up additional information with journal entries. For further details please check: http://www.freedesktop.org/wiki/Software/systemd/catalog The indexed message catalog database also needs to be rebuilt after installation of message catalog files. Use "journalctl --update-catalog" for this. For RPM-based distributions we introduced the %journal_catalog_update macro for this purpose. * The Python Journal bindings gained support for the standard Python logging framework. * The Journal API gained new functions for checking whether the underlying file system of a journal file is capable of properly reporting file change notifications, or whether applications that want to reflect journal changes "live" need to recheck journal files continuously in appropriate time intervals. * It is now possible to set the "age" field for tmpfiles entries to 0, indicating that files matching this entry shall always be removed when the directories are cleaned up. * coredumpctl gained a new "gdb" verb which invokes gdb right-away on the selected coredump. * There's now support for "hybrid sleep" on kernels that support this, in addition to "suspend" and "hibernate". Use "systemctl hybrid-sleep" to make use of this. * logind's HandleSuspendKey= setting (and related settings) now gained support for a new "lock" setting to simply request the screen lock on all local sessions, instead of actually executing a suspend or hibernation. * systemd will now mount the EFI variables file system by default. * Socket units now gained support for configuration of the SMACK security label. * timedatectl will now output the time of the last and next daylight saving change. * We dropped support for various legacy and distro-specific concepts, such as insserv, early-boot SysV services (i.e. those for non-standard runlevels such as 'b' or 'S') or ArchLinux /etc/rc.conf support. We recommend the distributions who still need support this to either continue to maintain the necessary patches downstream, or find a different solution. (Talk to us if you have questions!) * Various systemd components will now bypass PolicyKit checks for root and otherwise handle properly if PolicyKit is not found to be around. This should fix most issues for PolicyKit-less systems. Quite frankly this should have been this way since day one. It is absolutely our intention to make systemd work fine on PolicyKit-less systems, and we consider it a bug if something does not work as it should if PolicyKit is not around. * For embedded systems it is now possible to build udev and systemd without blkid and/or kmod support. * "systemctl switch-root" is now capable of switching root more than once. I.e. in addition to transitions from the initrd to the host OS it is now possible to transition to further OS images from the host. This is useful to implement offline updating tools. * Various other additions have been made to the RPM macros shipped with systemd. Use %udev_rules_update() after installing new udev rules files. %_udevhwdbdir, %_udevrulesdir, %_journalcatalogdir, %_tmpfilesdir, %_sysctldir are now available which resolve to the right directories for packages to place various data files in. * journalctl gained the new --full switch (in addition to --all, to disable ellipsation for long messages. Contributions from: Anders Olofsson, Auke Kok, Ben Boeckel, Colin Walters, Cosimo Cecchi, Daniel Wallace, Dave Reisner, Eelco Dolstra, Holger Hans Peter Freyther, Kay Sievers, Chun-Yi Lee, Lekensteyn, Lennart Poettering, Mantas Mikulėnas, Marti Raudsepp, Martin Pitt, Mauro Dreissig, Michael Biebl, Michal Schmidt, Michal Sekletar, Miklos Vajna, Nis Martensen, Oleksii Shevchuk, Olivier Brunel, Ramkumar Ramachandra, Thomas Bächler, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Tony Camuso, Umut Tezduyar, Zbigniew Jędrzejewski-Szmek CHANGES WITH 195: * journalctl gained new --since= and --until= switches to filter by time. It also now supports nice filtering for units via --unit=/-u. * Type=oneshot services may use ExecReload= and do the right thing. * The journal daemon now supports time-based rotation and vacuuming, in addition to the usual disk-space based rotation. * The journal will now index the available field values for each field name. This enables clients to show pretty drop downs of available match values when filtering. The bash completion of journalctl has been updated accordingly. journalctl gained a new switch -F to list all values a certain field takes in the journal database. * More service events are now written as structured messages to the journal, and made recognizable via message IDs. * The timedated, localed and hostnamed mini-services which previously only provided support for changing time, locale and hostname settings from graphical DEs such as GNOME now also have a minimal (but very useful) text-based client utility each. This is probably the nicest way to changing these settings from the command line now, especially since it lists available options and is fully integrated with bash completion. * There's now a new tool "systemd-coredumpctl" to list and extract coredumps from the journal. * We now install a README each in /var/log/ and /etc/rc.d/init.d explaining where the system logs and init scripts went. This hopefully should help folks who go to that dirs and look into the otherwise now empty void and scratch their heads. * When user-services are invoked (by systemd --user) the $MANAGERPID env var is set to the PID of systemd. * SIGRTMIN+24 when sent to a --user instance will now result in immediate termination of systemd. * gatewayd received numerous feature additions such as a "follow" mode, for live syncing and filtering. * browse.html now allows filtering and showing detailed information on specific entries. Keyboard navigation and mouse screen support has been added. * gatewayd/journalctl now supports HTML5/JSON Server-Sent-Events as output. * The SysV init script compatibility logic will now heuristically determine whether a script supports the "reload" verb, and only then make this available as "systemctl reload". * "systemctl status --follow" has been removed, use "journalctl -u" instead. * journald.conf's RuntimeMinSize=, PersistentMinSize= settings have been removed since they are hardly useful to be configured. * And I'd like to take the opportunity to specifically mention Zbigniew for his great contributions. Zbigniew, you rock! Contributions from: Andrew Eikum, Christian Hesse, Colin Guthrie, Daniel J Walsh, Dave Reisner, Eelco Dolstra, Ferenc Wágner, Kay Sievers, Lennart Poettering, Lukas Nykryn, Mantas Mikulėnas, Martin Mikkelsen, Martin Pitt, Michael Olbrich, Michael Stapelberg, Michal Schmidt, Sebastian Ott, Thomas Bächler, Umut Tezduyar, Will Woods, Wulf C. Krueger, Zbigniew Jędrzejewski-Szmek, Сковорода Никита Андреевич CHANGES WITH 194: * If /etc/vconsole.conf is non-existent or empty we will no longer load any console font or key map at boot by default. Instead the kernel defaults will be left intact. This is definitely the right thing to do, as no configuration should mean no configuration, and hard-coding font names that are different on all archs is probably a bad idea. Also, the kernel default key map and font should be good enough for most cases anyway, and mostly identical to the userspace fonts/key maps we previously overloaded them with. If distributions want to continue to default to a non-kernel font or key map they should ship a default /etc/vconsole.conf with the appropriate contents. Contributions from: Colin Walters, Daniel J Walsh, Dave Reisner, Kay Sievers, Lennart Poettering, Lukas Nykryn, Tollef Fog Heen, Tom Gundersen, Zbigniew Jędrzejewski-Szmek CHANGES WITH 193: * journalctl gained a new --cursor= switch to show entries starting from the specified location in the journal. * We now enforce a size limit on journal entry fields exported with "-o json" in journalctl. Fields larger than 4K will be assigned null. This can be turned off with --all. * An (optional) journal gateway daemon is now available as "systemd-journal-gatewayd.service". This service provides access to the journal via HTTP and JSON. This functionality will be used to implement live log synchronization in both pull and push modes, but has various other users too, such as easy log access for debugging of embedded devices. Right now it is already useful to retrieve the journal via HTTP: # systemctl start systemd-journal-gatewayd.service # wget http://localhost:19531/entries This will download the journal contents in a /var/log/messages compatible format. The same as JSON: # curl -H"Accept: application/json" http://localhost:19531/entries This service is also accessible via a web browser where a single static HTML5 app is served that uses the JSON logic to enable the user to do some basic browsing of the journal. This will be extended later on. Here's an example screenshot of this app in its current state: http://0pointer.de/public/journal-gatewayd Contributions from: Kay Sievers, Lennart Poettering, Robert Milasan, Tom Gundersen CHANGES WITH 192: * The bash completion logic is now available for journalctl too. * We do not mount the "cpuset" controller anymore together with "cpu" and "cpuacct", as "cpuset" groups generally cannot be started if no parameters are assigned to it. "cpuset" hence broke code that assumed it it could create "cpu" groups and just start them. * journalctl -f will now subscribe to terminal size changes, and line break accordingly. Contributions from: Dave Reisner, Kay Sievers, Lennart Poettering, Lukas Nykrynm, Mirco Tischler, Václav Pavlín CHANGES WITH 191: * nspawn will now create a symlink /etc/localtime in the container environment, copying the host's timezone setting. Previously this has been done via a bind mount, but since symlinks cannot be bind mounted this has now been changed to create/update the appropriate symlink. * journalctl -n's line number argument is now optional, and will default to 10 if omitted. * journald will now log the maximum size the journal files may take up on disk. This is particularly useful if the default built-in logic of determining this parameter from the file system size is used. Use "systemctl status systemd-journald.service" to see this information. * The multi-seat X wrapper tool has been stripped down. As X is now capable of enumerating graphics devices via udev in a seat-aware way the wrapper is not strictly necessary anymore. A stripped down temporary stop-gap is still shipped until the upstream display managers have been updated to fully support the new X logic. Expect this wrapper to be removed entirely in one of the next releases. * HandleSleepKey= in logind.conf has been split up into HandleSuspendKey= and HandleHibernateKey=. The old setting is not available anymore. X11 and the kernel are distinguishing between these keys and we should too. This also means the inhibition lock for these keys has been split into two. Contributions from: Dave Airlie, Eelco Dolstra, Lennart Poettering, Lukas Nykryn, Václav Pavlín CHANGES WITH 190: * Whenever a unit changes state we will now log this to the journal and show along the unit's own log output in "systemctl status". * ConditionPathIsMountPoint= can now properly detect bind mount points too. (Previously, a bind mount of one file system to another place in the same file system could not be detected as mount, since they shared struct stat's st_dev field.) * We will now mount the cgroup controllers cpu, cpuacct, cpuset and the controllers net_cls, net_prio together by default. * nspawn containers will now have a virtualized boot ID. (i.e. /proc/sys/kernel/random/boot_id is now mounted over with a randomized ID at container initialization). This has the effect of making "journalctl -b" do the right thing in a container. * The JSON output journal serialization has been updated not to generate "endless" list objects anymore, but rather one JSON object per line. This is more in line how most JSON parsers expect JSON objects. The new output mode "json-pretty" has been added to provide similar output, but neatly aligned for readability by humans. * We dropped all explicit sync() invocations in the shutdown code. The kernel does this implicitly anyway in the kernel reboot() syscall. halt(8)'s -n option is now a compatibility no-op. * We now support virtualized reboot() in containers, as supported by newer kernels. We will fall back to exit() if CAP_SYS_REBOOT is not available to the container. Also, nspawn makes use of this now and will actually reboot the container if the containerized OS asks for that. * journalctl will only show local log output by default now. Use --merge (-m) to show remote log output, too. * libsystemd-journal gained the new sd_journal_get_usage() call to determine the current disk usage of all journal files. This is exposed in the new "journalctl --disk-usage" command. * journald gained a new configuration setting SplitMode= in journald.conf which may be used to control how user journals are split off. See journald.conf(5) for details. * A new condition type ConditionFileNotEmpty= has been added. * tmpfiles' "w" lines now support file globbing, to write multiple files at once. * We added Python bindings for the journal submission APIs. More Python APIs for a number of selected APIs will likely follow. Note that we intend to add native bindings only for the Python language, as we consider it common enough to deserve bindings shipped within systemd. There are various projects outside of systemd that provide bindings for languages such as PHP or Lua. * Many conditions will now resolve specifiers such as %i. In addition, PathChanged= and related directives of .path units now support specifiers as well. * There's now a new RPM macro definition for the system preset dir: %_presetdir. * journald will now warn if it ca not forward a message to the syslog daemon because its socket is full. * timedated will no longer write or process /etc/timezone, except on Debian. As we do not support late mounted /usr anymore /etc/localtime always being a symlink is now safe, and hence the information in /etc/timezone is not necessary anymore. * logind will now always reserve one VT for a text getty (VT6 by default). Previously if more than 6 X sessions where started they took up all the VTs with auto-spawned gettys, so that no text gettys were available anymore. * udev will now automatically inform the btrfs kernel logic about btrfs RAID components showing up. This should make simple hotplug based btrfs RAID assembly work. * PID 1 will now increase its RLIMIT_NOFILE to 64K by default (but not for its children which will stay at the kernel default). This should allow setups with a lot more listening sockets. * systemd will now always pass the configured timezone to the kernel at boot. timedated will do the same when the timezone is changed. * logind's inhibition logic has been updated. By default, logind will now handle the lid switch, the power and sleep keys all the time, even in graphical sessions. If DEs want to handle these events on their own they should take the new handle-power-key, handle-sleep-key and handle-lid-switch inhibitors during their runtime. A simple way to achieve that is to invoke the DE wrapped in an invocation of: systemd-inhibit --what=handle-power-key:handle-sleep-key:handle-lid-switch ... * Access to unit operations is now checked via SELinux taking the unit file label and client process label into account. * systemd will now notify the administrator in the journal when he over-mounts a non-empty directory. * There are new specifiers that are resolved in unit files, for the host name (%H), the machine ID (%m) and the boot ID (%b). Contributions from: Allin Cottrell, Auke Kok, Brandon Philips, Colin Guthrie, Colin Walters, Daniel J Walsh, Dave Reisner, Eelco Dolstra, Jan Engelhardt, Kay Sievers, Lennart Poettering, Lucas De Marchi, Lukas Nykryn, Mantas Mikulėnas, Martin Pitt, Matthias Clasen, Michael Olbrich, Pierre Schmitz, Shawn Landden, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Václav Pavlín, Yin Kangkai, Zbigniew Jędrzejewski-Szmek CHANGES WITH 189: * Support for reading structured kernel messages from /dev/kmsg has now been added and is enabled by default. * Support for reading kernel messages from /proc/kmsg has now been removed. If you want kernel messages in the journal make sure to run a recent kernel (>= 3.5) that supports reading structured messages from /dev/kmsg (see above). /proc/kmsg is now exclusive property of classic syslog daemons again. * The libudev API gained the new udev_device_new_from_device_id() call. * The logic for file system namespace (ReadOnlyDirectory=, ReadWriteDirectoy=, PrivateTmp=) has been reworked not to require pivot_root() anymore. This means fewer temporary directories are created below /tmp for this feature. * nspawn containers will now see and receive all submounts made on the host OS below the root file system of the container. * Forward Secure Sealing is now supported for Journal files, which provide cryptographical sealing of journal files so that attackers cannot alter log history anymore without this being detectable. Lennart will soon post a blog story about this explaining it in more detail. * There are two new service settings RestartPreventExitStatus= and SuccessExitStatus= which allow configuration of exit status (exit code or signal) which will be excepted from the restart logic, resp. consider successful. * journalctl gained the new --verify switch that can be used to check the integrity of the structure of journal files and (if Forward Secure Sealing is enabled) the contents of journal files. * nspawn containers will now be run with /dev/stdin, /dev/fd/ and similar symlinks pre-created. This makes running shells as container init process a lot more fun. * The fstab support can now handle PARTUUID= and PARTLABEL= entries. * A new ConditionHost= condition has been added to match against the hostname (with globs) and machine ID. This is useful for clusters where a single OS image is used to provision a large number of hosts which shall run slightly different sets of services. * Services which hit the restart limit will now be placed in a failure state. Contributions from: Bertram Poettering, Dave Reisner, Huang Hang, Kay Sievers, Lennart Poettering, Lukas Nykryn, Martin Pitt, Simon Peeters, Zbigniew Jędrzejewski-Szmek CHANGES WITH 188: * When running in --user mode systemd will now become a subreaper (PR_SET_CHILD_SUBREAPER). This should make the ps tree a lot more organized. * A new PartOf= unit dependency type has been introduced that may be used to group services in a natural way. * "systemctl enable" may now be used to enable instances of services. * journalctl now prints error log levels in red, and warning/notice log levels in bright white. It also supports filtering by log level now. * cgtop gained a new -n switch (similar to top), to configure the maximum number of iterations to run for. It also gained -b, to run in batch mode (accepting no input). * The suffix ".service" may now be omitted on most systemctl command lines involving service unit names. * There's a new bus call in logind to lock all sessions, as well as a loginctl verb for it "lock-sessions". * libsystemd-logind.so gained a new call sd_journal_perror() that works similar to libc perror() but logs to the journal and encodes structured information about the error number. * /etc/crypttab entries now understand the new keyfile-size= option. * shutdown(8) now can send a (configurable) wall message when a shutdown is cancelled. * The mount propagation mode for the root file system will now default to "shared", which is useful to make containers work nicely out-of-the-box so that they receive new mounts from the host. This can be undone locally by running "mount --make-rprivate /" if needed. * The prefdm.service file has been removed. Distributions should maintain this unit downstream if they intend to keep it around. However, we recommend writing normal unit files for display managers instead. * Since systemd is a crucial part of the OS we will now default to a number of compiler switches that improve security (hardening) such as read-only relocations, stack protection, and suchlike. * The TimeoutSec= setting for services is now split into TimeoutStartSec= and TimeoutStopSec= to allow configuration of individual time outs for the start and the stop phase of the service. Contributions from: Artur Zaprzala, Arvydas Sidorenko, Auke Kok, Bryan Kadzban, Dave Reisner, David Strauss, Harald Hoyer, Jim Meyering, Kay Sievers, Lennart Poettering, Mantas Mikulėnas, Martin Pitt, Michal Schmidt, Michal Sekletar, Peter Alfredsen, Shawn Landden, Simon Peeters, Terence Honles, Tom Gundersen, Zbigniew Jędrzejewski-Szmek CHANGES WITH 187: * The journal and id128 C APIs are now fully documented as man pages. * Extra safety checks have been added when transitioning from the initial RAM disk to the main system to avoid accidental data loss. * /etc/crypttab entries now understand the new keyfile-offset= option. * systemctl -t can now be used to filter by unit load state. * The journal C API gained the new sd_journal_wait() call to make writing synchronous journal clients easier. * journalctl gained the new -D switch to show journals from a specific directory. * journalctl now displays a special marker between log messages of two different boots. * The journal is now explicitly flushed to /var via a service systemd-journal-flush.service, rather than implicitly simply by seeing /var/log/journal to be writable. * journalctl (and the journal C APIs) can now match for much more complex expressions, with alternatives and disjunctions. * When transitioning from the initial RAM disk to the main system we will now kill all processes in a killing spree to ensure no processes stay around by accident. * Three new specifiers may be used in unit files: %u, %h, %s resolve to the user name, user home directory resp. user shell. This is useful for running systemd user instances. * We now automatically rotate journal files if their data object hash table gets a fill level > 75%. We also size the hash table based on the configured maximum file size. This together should lower hash collisions drastically and thus speed things up a bit. * journalctl gained the new "--header" switch to introspect header data of journal files. * A new setting SystemCallFilters= has been added to services which may be used to apply blacklists or whitelists to system calls. This is based on SECCOMP Mode 2 of Linux 3.5. * nspawn gained a new --link-journal= switch (and quicker: -j) to link the container journal with the host. This makes it very easy to centralize log viewing on the host for all guests while still keeping the journal files separated. * Many bugfixes and optimizations Contributions from: Auke Kok, Eelco Dolstra, Harald Hoyer, Kay Sievers, Lennart Poettering, Malte Starostik, Paul Menzel, Rex Tsai, Shawn Landden, Tom Gundersen, Ville Skyttä, Zbigniew Jędrzejewski-Szmek CHANGES WITH 186: * Several tools now understand kernel command line arguments, which are only read when run in an initial RAM disk. They usually follow closely their normal counterparts, but are prefixed with rd. * There's a new tool to analyze the readahead files that are automatically generated at boot. Use: /usr/lib/systemd/systemd-readahead analyze /.readahead * We now provide an early debug shell on tty9 if this enabled. Use: systemctl enable debug-shell.service * All plymouth related units have been moved into the Plymouth package. Please make sure to upgrade your Plymouth version as well. * systemd-tmpfiles now supports getting passed the basename of a configuration file only, in which case it will look for it in all appropriate directories automatically. * udevadm info now takes a /dev or /sys path as argument, and does the right thing. Example: udevadm info /dev/sda udevadm info /sys/class/block/sda * systemctl now prints a warning if a unit is stopped but a unit that might trigger it continues to run. Example: a service is stopped but the socket that activates it is left running. * "systemctl status" will now mention if the log output was shortened due to rotation since a service has been started. * The journal API now exposes functions to determine the "cutoff" times due to rotation. * journald now understands SIGUSR1 and SIGUSR2 for triggering immediately flushing of runtime logs to /var if possible, resp. for triggering immediate rotation of the journal files. * It is now considered an error if a service is attempted to be stopped that is not loaded. * XDG_RUNTIME_DIR now uses numeric UIDs instead of usernames. * systemd-analyze now supports Python 3 * tmpfiles now supports cleaning up directories via aging where the first level dirs are always kept around but directories beneath it automatically aged. This is enabled by prefixing the age field with '~'. * Seat objects now expose CanGraphical, CanTTY properties which is required to deal with very fast bootups where the display manager might be running before the graphics drivers completed initialization. * Seat objects now expose a State property. * We now include RPM macros for service enabling/disabling based on the preset logic. We recommend RPM based distributions to make use of these macros if possible. This makes it simpler to reuse RPM spec files across distributions. * We now make sure that the collected systemd unit name is always valid when services log to the journal via STDOUT/STDERR. * There's a new man page kernel-command-line(7) detailing all command line options we understand. * The fstab generator may now be disabled at boot by passing fstab=0 on the kernel command line. * A new kernel command line option modules-load= is now understood to load a specific kernel module statically, early at boot. * Unit names specified on the systemctl command line are now automatically escaped as needed. Also, if file system or device paths are specified they are automatically turned into the appropriate mount or device unit names. Example: systemctl status /home systemctl status /dev/sda * The SysVConsole= configuration option has been removed from system.conf parsing. * The SysV search path is no longer exported on the D-Bus Manager object. * The Names= option is been removed from unit file parsing. * There's a new man page bootup(7) detailing the boot process. * Every unit and every generator we ship with systemd now comes with full documentation. The self-explanatory boot is complete. * A couple of services gained "systemd-" prefixes in their name if they wrap systemd code, rather than only external code. Among them fsck@.service which is now systemd-fsck@.service. * The HaveWatchdog property has been removed from the D-Bus Manager object. * systemd.confirm_spawn= on the kernel command line should now work sensibly. * There's a new man page crypttab(5) which details all options we actually understand. * systemd-nspawn gained a new --capability= switch to pass additional capabilities to the container. * timedated will now read known NTP implementation unit names from /usr/lib/systemd/ntp-units.d/*.list, systemd-timedated-ntp.target has been removed. * journalctl gained a new switch "-b" that lists log data of the current boot only. * The notify socket is in the abstract namespace again, in order to support daemons which chroot() at start-up. * There is a new Storage= configuration option for journald which allows configuration of where log data should go. This also provides a way to disable journal logging entirely, so that data collected is only forwarded to the console, the kernel log buffer or another syslog implementation. * Many bugfixes and optimizations Contributions from: Auke Kok, Colin Guthrie, Dave Reisner, David Strauss, Eelco Dolstra, Kay Sievers, Lennart Poettering, Lukas Nykryn, Michal Schmidt, Michal Sekletar, Paul Menzel, Shawn Landden, Tom Gundersen CHANGES WITH 185: * "systemctl help " now shows the man page if one is available. * Several new man pages have been added. * MaxLevelStore=, MaxLevelSyslog=, MaxLevelKMsg=, MaxLevelConsole= can now be specified in journald.conf. These options allow reducing the amount of data stored on disk or forwarded by the log level. * TimerSlackNSec= can now be specified in system.conf for PID1. This allows system-wide power savings. Contributions from: Dave Reisner, Kay Sievers, Lauri Kasanen, Lennart Poettering, Malte Starostik, Marc-Antoine Perennou, Matthias Clasen CHANGES WITH 184: * logind is now capable of (optionally) handling power and sleep keys as well as the lid switch. * journalctl now understands the syntax "journalctl /usr/bin/avahi-daemon" to get all log output of a specific daemon. * CapabilityBoundingSet= in system.conf now also influences the capability bound set of usermode helpers of the kernel. Contributions from: Daniel Drake, Daniel J. Walsh, Gert Michael Kulyk, Harald Hoyer, Jean Delvare, Kay Sievers, Lennart Poettering, Matthew Garrett, Matthias Clasen, Paul Menzel, Shawn Landden, Tero Roponen, Tom Gundersen CHANGES WITH 183: * Note that we skipped 139 releases here in order to set the new version to something that is greater than both udev's and systemd's most recent version number. * udev: all udev sources are merged into the systemd source tree now. All future udev development will happen in the systemd tree. It is still fully supported to use the udev daemon and tools without systemd running, like in initramfs or other init systems. Building udev though, will require the *build* of the systemd tree, but udev can be properly *run* without systemd. * udev: /lib/udev/devices/ are not read anymore; systemd-tmpfiles should be used to create dead device nodes as workarounds for broken subsystems. * udev: RUN+="socket:..." and udev_monitor_new_from_socket() is no longer supported. udev_monitor_new_from_netlink() needs to be used to subscribe to events. * udev: when udevd is started by systemd, processes which are left behind by forking them off of udev rules, are unconditionally cleaned up and killed now after the event handling has finished. Services or daemons must be started as systemd services. Services can be pulled-in by udev to get started, but they can no longer be directly forked by udev rules. * udev: the daemon binary is called systemd-udevd now and installed in /usr/lib/systemd/. Standalone builds or non-systemd systems need to adapt to that, create symlink, or rename the binary after building it. * libudev no longer provides these symbols: udev_monitor_from_socket() udev_queue_get_failed_list_entry() udev_get_{dev,sys,run}_path() The versions number was bumped and symbol versioning introduced. * systemd-loginctl and systemd-journalctl have been renamed to loginctl and journalctl to match systemctl. * The config files: /etc/systemd/systemd-logind.conf and /etc/systemd/systemd-journald.conf have been renamed to logind.conf and journald.conf. Package updates should rename the files to the new names on upgrade. * For almost all files the license is now LGPL2.1+, changed from the previous GPL2.0+. Exceptions are some minor stuff of udev (which will be changed to LGPL2.1 eventually, too), and the MIT licensed sd-daemon.[ch] library that is suitable to be used as drop-in files. * systemd and logind now handle system sleep states, in particular suspending and hibernating. * logind now implements a sleep/shutdown/idle inhibiting logic suitable for a variety of uses. Soonishly Lennart will blog about this in more detail. * var-run.mount and var-lock.mount are no longer provided (which prevously bind mounted these directories to their new places). Distributions which have not converted these directories to symlinks should consider stealing these files from git history and add them downstream. * We introduced the Documentation= field for units and added this to all our shipped units. This is useful to make it easier to explore the boot and the purpose of the various units. * All smaller setup units (such as systemd-vconsole-setup.service) now detect properly if they are run in a container and are skipped when appropriate. This guarantees an entirely noise-free boot in Linux container environments such as systemd-nspawn. * A framework for implementing offline system updates is now integrated, for details see: http://freedesktop.org/wiki/Software/systemd/SystemUpdates * A new service type Type=idle is available now which helps us avoiding ugly interleaving of getty output and boot status messages. * There's now a system-wide CapabilityBoundingSet= option to globally reduce the set of capabilities for the system. This is useful to drop CAP_SYS_MKNOD, CAP_SYS_RAWIO, CAP_NET_RAW, CAP_SYS_MODULE, CAP_SYS_TIME, CAP_SYS_PTRACE or even CAP_NET_ADMIN system-wide for secure systems. * There are now system-wide DefaultLimitXXX= options to globally change the defaults of the various resource limits for all units started by PID 1. * Harald Hoyer's systemd test suite has been integrated into systemd which allows easy testing of systemd builds in qemu and nspawn. (This is really awesome! Ask us for details!) * The fstab parser is now implemented as generator, not inside of PID 1 anymore. * systemctl will now warn you if .mount units generated from /etc/fstab are out of date due to changes in fstab that have not been read by systemd yet. * systemd is now suitable for usage in initrds. Dracut has already been updated to make use of this. With this in place initrds get a slight bit faster but primarily are much easier to introspect and debug since "systemctl status" in the host system can be used to introspect initrd services, and the journal from the initrd is kept around too. * systemd-delta has been added, a tool to explore differences between user/admin configuration and vendor defaults. * PrivateTmp= now affects both /tmp and /var/tmp. * Boot time status messages are now much prettier and feature proper english language. Booting up systemd has never been so sexy. * Read-ahead pack files now include the inode number of all files to pre-cache. When the inode changes the pre-caching is not attempted. This should be nicer to deal with updated packages which might result in changes of read-ahead patterns. * We now temporaritly lower the kernel's read_ahead_kb variable when collecting read-ahead data to ensure the kernel's built-in read-ahead does not add noise to our measurements of necessary blocks to pre-cache. * There's now RequiresMountsFor= to add automatic dependencies for all mounts necessary for a specific file system path. * MountAuto= and SwapAuto= have been removed from system.conf. Mounting file systems at boot has to take place in systemd now. * nspawn now learned a new switch --uuid= to set the machine ID on the command line. * nspawn now learned the -b switch to automatically search for an init system. * vt102 is now the default TERM for serial TTYs, upgraded from vt100. * systemd-logind now works on VT-less systems. * The build tree has been reorganized. The individual components now have directories of their own. * A new condition type ConditionPathIsReadWrite= is now available. * nspawn learned the new -C switch to create cgroups for the container in other hierarchies. * We now have support for hardware watchdogs, configurable in system.conf. * The scheduled shutdown logic now has a public API. * We now mount /tmp as tmpfs by default, but this can be masked and /etc/fstab can override it. * Since udisks does not make use of /media anymore we are not mounting a tmpfs on it anymore. * journalctl gained a new --local switch to only interleave locally generated journal files. * We can now load the IMA policy at boot automatically. * The GTK tools have been split off into a systemd-ui. Contributions from: Andreas Schwab, Auke Kok, Ayan George, Colin Guthrie, Daniel Mack, Dave Reisner, David Ward, Elan Ruusamäe, Frederic Crozat, Gergely Nagy, Guillermo Vidal, Hannes Reinecke, Harald Hoyer, Javier Jardón, Kay Sievers, Lennart Poettering, Lucas De Marchi, Léo Gillot-Lamure, Marc-Antoine Perennou, Martin Pitt, Matthew Monaco, Maxim A. Mikityanskiy, Michael Biebl, Michael Olbrich, Michal Schmidt, Nis Martensen, Patrick McCarty, Roberto Sassu, Shawn Landden, Sjoerd Simons, Sven Anders, Tollef Fog Heen, Tom Gundersen CHANGES WITH 44: * This is mostly a bugfix release * Support optional initialization of the machine ID from the KVM or container configured UUID. * Support immediate reboots with "systemctl reboot -ff" * Show /etc/os-release data in systemd-analyze output * Many bugfixes for the journal, including endianness fixes and ensuring that disk space enforcement works * sd-login.h is C++ comptaible again * Extend the /etc/os-release format on request of the Debian folks * We now refuse non-UTF8 strings used in various configuration and unit files. This is done to ensure we do not pass invalid data over D-Bus or expose it elsewhere. * Register Mimo USB Screens as suitable for automatic seat configuration * Read SELinux client context from journal clients in a race free fashion * Reorder configuration file lookup order. /etc now always overrides /run in order to allow the administrator to always and unconditionally override vendor-supplied or automatically generated data. * The various user visible bits of the journal now have man pages. We still lack man pages for the journal API calls however. * We now ship all man pages in HTML format again in the tarball. Contributions from: Dave Reisner, Dirk Eibach, Frederic Crozat, Harald Hoyer, Kay Sievers, Lennart Poettering, Marti Raudsepp, Michal Schmidt, Shawn Landden, Tero Roponen, Thierry Reding CHANGES WITH 43: * This is mostly a bugfix release * systems lacking /etc/os-release are no longer supported. * Various functionality updates to libsystemd-login.so * Track class of PAM logins to distinguish greeters from normal user logins. Contributions from: Kay Sievers, Lennart Poettering, Michael Biebl CHANGES WITH 42: * This is an important bugfix release for v41. * Building man pages is now optional which should be useful for those building systemd from git but unwilling to install xsltproc. * Watchdog support for supervising services is now usable. In a future release support for hardware watchdogs (i.e. /dev/watchdog) will be added building on this. * Service start rate limiting is now configurable and can be turned off per service. When a start rate limit is hit a reboot can automatically be triggered. * New CanReboot(), CanPowerOff() bus calls in systemd-logind. Contributions from: Benjamin Franzke, Bill Nottingham, Frederic Crozat, Lennart Poettering, Michael Olbrich, Michal Schmidt, Michał Górny, Piotr Drąg CHANGES WITH 41: * The systemd binary is installed /usr/lib/systemd/systemd now; An existing /sbin/init symlink needs to be adapted with the package update. * The code that loads kernel modules has been ported to invoke libkmod directly, instead of modprobe. This means we do not support systems with module-init-tools anymore. * Watchdog support is now already useful, but still not complete. * A new kernel command line option systemd.setenv= is understood to set system wide environment variables dynamically at boot. * We now limit the set of capabilities of systemd-journald. * We now set SIGPIPE to ignore by default, since it only is useful in shell pipelines, and has little use in general code. This can be disabled with IgnoreSIPIPE=no in unit files. Contributions from: Benjamin Franzke, Kay Sievers, Lennart Poettering, Michael Olbrich, Michal Schmidt, Tom Gundersen, William Douglas CHANGES WITH 40: * This is mostly a bugfix release * We now expose the reason why a service failed in the "Result" D-Bus property. * Rudimentary service watchdog support (will be completed over the next few releases.) * When systemd forks off in order execute some service we will now immediately changes its argv[0] to reflect which process it will execute. This is useful to minimize the time window with a generic argv[0], which makes bootcharts more useful Contributions from: Alvaro Soliverez, Chris Paulson-Ellis, Kay Sievers, Lennart Poettering, Michael Olbrich, Michal Schmidt, Mike Kazantsev, Ray Strode CHANGES WITH 39: * This is mostly a test release, but incorporates many bugfixes. * New systemd-cgtop tool to show control groups by their resource usage. * Linking against libacl for ACLs is optional again. If disabled, support tracking device access for active logins goes becomes unavailable, and so does access to the user journals by the respective users. * If a group "adm" exists, journal files are automatically owned by them, thus allow members of this group full access to the system journal as well as all user journals. * The journal now stores the SELinux context of the logging client for all entries. * Add C++ inclusion guards to all public headers * New output mode "cat" in the journal to print only text messages, without any meta data like date or time. * Include tiny X server wrapper as a temporary stop-gap to teach XOrg udev display enumeration. This is used by display managers such as gdm, and will go away as soon as XOrg learned native udev hotplugging for display devices. * Add new systemd-cat tool for executing arbitrary programs with STDERR/STDOUT connected to the journal. Can also act as BSD logger replacement, and does so by default. * Optionally store all locally generated coredumps in the journal along with meta data. * systemd-tmpfiles learnt four new commands: n, L, c, b, for writing short strings to files (for usage for /sys), and for creating symlinks, character and block device nodes. * New unit file option ControlGroupPersistent= to make cgroups persistent, following the mechanisms outlined in http://www.freedesktop.org/wiki/Software/systemd/PaxControlGroups * Support multiple local RTCs in a sane way * No longer monopolize IO when replaying readahead data on rotating disks, since we might starve non-file-system IO to death, since fanotify() will not see accesses done by blkid, or fsck. * Do not show kernel threads in systemd-cgls anymore, unless requested with new -k switch. Contributions from: Dan Horák, Kay Sievers, Lennart Poettering, Michal Schmidt CHANGES WITH 38: * This is mostly a test release, but incorporates many bugfixes. * The git repository moved to: git://anongit.freedesktop.org/systemd/systemd ssh://git.freedesktop.org/git/systemd/systemd * First release with the journal http://0pointer.de/blog/projects/the-journal.html * The journal replaces both systemd-kmsg-syslogd and systemd-stdout-bridge. * New sd_pid_get_unit() API call in libsystemd-logind * Many systemadm clean-ups * Introduce remote-fs-pre.target which is ordered before all remote mounts and may be used to start services before all remote mounts. * Added Mageia support * Add bash completion for systemd-loginctl * Actively monitor PID file creation for daemons which exit in the parent process before having finished writing the PID file in the daemon process. Daemons which do this need to be fixed (i.e. PID file creation must have finished before the parent exits), but we now react a bit more gracefully to them. * Add colourful boot output, mimicking the well-known output of existing distributions. * New option PassCredentials= for socket units, for compatibility with a recent kernel ABI breakage. * /etc/rc.local is now hooked in via a generator binary, and thus will no longer act as synchronization point during boot. * systemctl list-unit-files now supports --root=. * systemd-tmpfiles now understands two new commands: z, Z for relabelling files according to the SELinux database. This is useful to apply SELinux labels to specific files in /sys, among other things. * Output of SysV services is now forwarded to both the console and the journal by default, not only just the console. * New man pages for all APIs from libsystemd-login. * The build tree got reorganized and a the build system is a lot more modular allowing embedded setups to specifically select the components of systemd they are interested in. * Support for Linux systems lacking the kernel VT subsystem is restored. * configure's --with-rootdir= got renamed to --with-rootprefix= to follow the naming used by udev and kmod * Unless specified otherwise we will now install to /usr instead of /usr/local by default. * Processes with '@' in argv[0][0] are now excluded from the final shut-down killing spree, following the logic explained in: http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons * All processes remaining in a service cgroup when we enter the START or START_PRE states are now killed with SIGKILL. That means it is no longer possible to spawn background processes from ExecStart= lines (which was never supported anyway, and bad style). * New PropagateReloadTo=/PropagateReloadFrom= options to bind reloading of units together. Contributions from: Bill Nottingham, Daniel J. Walsh, Dave Reisner, Dexter Morgan, Gregs Gregs, Jonathan Nieder, Kay Sievers, Lennart Poettering, Michael Biebl, Michal Schmidt, Michał Górny, Ran Benita, Thomas Jarosch, Tim Waugh, Tollef Fog Heen, Tom Gundersen, Zbigniew Jędrzejewski-Szmek systemd-229/README000066400000000000000000000244071265713322000137500ustar00rootroot00000000000000systemd System and Service Manager DETAILS: http://0pointer.de/blog/projects/systemd.html WEB SITE: http://www.freedesktop.org/wiki/Software/systemd GIT: git@github.com:systemd/systemd.git https://github.com/systemd/systemd.git GITWEB: https://github.com/systemd/systemd MAILING LIST: http://lists.freedesktop.org/mailman/listinfo/systemd-devel IRC: #systemd on irc.freenode.org BUG REPORTS: https://github.com/systemd/systemd/issues AUTHOR: Lennart Poettering Kay Sievers ...and many others LICENSE: LGPLv2.1+ for all code - except src/basic/MurmurHash2.c which is Public Domain - except src/basic/siphash24.c which is CC0 Public Domain - except src/journal/lookup3.c which is Public Domain - except src/udev/* which is (currently still) GPLv2, GPLv2+ REQUIREMENTS: Linux kernel >= 3.11 Linux kernel >= 4.2 for unified cgroup hierarchy support Kernel Config Options: CONFIG_DEVTMPFS CONFIG_CGROUPS (it is OK to disable all controllers) CONFIG_INOTIFY_USER CONFIG_SIGNALFD CONFIG_TIMERFD CONFIG_EPOLL CONFIG_NET CONFIG_SYSFS CONFIG_PROC_FS CONFIG_FHANDLE (libudev, mount and bind mount handling) udev will fail to work with the legacy sysfs layout: CONFIG_SYSFS_DEPRECATED=n Legacy hotplug slows down the system and confuses udev: CONFIG_UEVENT_HELPER_PATH="" Userspace firmware loading is not supported and should be disabled in the kernel: CONFIG_FW_LOADER_USER_HELPER=n Some udev rules and virtualization detection relies on it: CONFIG_DMIID Support for some SCSI devices serial number retrieval, to create additional symlinks in /dev/disk/ and /dev/tape: CONFIG_BLK_DEV_BSG Required for PrivateNetwork and PrivateDevices in service units: CONFIG_NET_NS CONFIG_DEVPTS_MULTIPLE_INSTANCES Note that systemd-localed.service and other systemd units use PrivateNetwork and PrivateDevices so this is effectively required. Optional but strongly recommended: CONFIG_IPV6 CONFIG_AUTOFS4_FS CONFIG_TMPFS_XATTR CONFIG_{TMPFS,EXT4,XFS,BTRFS_FS,...}_POSIX_ACL CONFIG_SECCOMP CONFIG_CHECKPOINT_RESTORE (for the kcmp() syscall) Required for CPUShares= in resource control unit settings CONFIG_CGROUP_SCHED CONFIG_FAIR_GROUP_SCHED Required for CPUQuota= in resource control unit settings CONFIG_CFS_BANDWIDTH For systemd-bootchart, several proc debug interfaces are required: CONFIG_SCHEDSTATS CONFIG_SCHED_DEBUG For UEFI systems: CONFIG_EFIVAR_FS CONFIG_EFI_PARTITION We recommend to turn off Real-Time group scheduling in the kernel when using systemd. RT group scheduling effectively makes RT scheduling unavailable for most userspace, since it requires explicit assignment of RT budgets to each unit whose processes making use of RT. As there's no sensible way to assign these budgets automatically this cannot really be fixed, and it's best to disable group scheduling hence. CONFIG_RT_GROUP_SCHED=n Note that kernel auditing is broken when used with systemd's container code. When using systemd in conjunction with containers, please make sure to either turn off auditing at runtime using the kernel command line option "audit=0", or turn it off at kernel compile time using: CONFIG_AUDIT=n If systemd is compiled with libseccomp support on architectures which do not use socketcall() and where seccomp is supported (this effectively means x86-64 and ARM, but excludes 32-bit x86!), then nspawn will now install a work-around seccomp filter that makes containers boot even with audit being enabled. This works correctly only on kernels 3.14 and newer though. TL;DR: turn audit off, still. glibc >= 2.16 libcap libmount >= 2.27.1 (from util-linux) libseccomp >= 1.0.0 (optional) libblkid >= 2.24 (from util-linux) (optional) libkmod >= 15 (optional) PAM >= 1.1.2 (optional) libcryptsetup (optional) libaudit (optional) libacl (optional) libselinux (optional) liblzma (optional) liblz4 >= 119 (optional) libgcrypt (optional) libqrencode (optional) libmicrohttpd (optional) libpython (optional) libidn (optional) elfutils >= 158 (optional) make, gcc, and similar tools During runtime, you need the following additional dependencies: util-linux >= v2.27.1 required dbus >= 1.4.0 (strictly speaking optional, but recommended) dracut (optional) PolicyKit (optional) When building from git, the following tools are needed: pkg-config docbook-xsl xsltproc automake autoconf libtool intltool gperf python (optional) python-lxml (optional, but required to build the indices) The build system is initialized with ./autogen.sh. A tar ball can be created with: git archive --format=tar --prefix=systemd-222/ v222 | xz > systemd-222.tar.xz When systemd-hostnamed is used, it is strongly recommended to install nss-myhostname to ensure that, in a world of dynamically changing hostnames, the hostname stays resolvable under all circumstances. In fact, systemd-hostnamed will warn if nss-myhostname is not installed. USERS AND GROUPS: Default udev rules use the following standard system group names, which need to be resolvable by getgrnam() at any time, even in the very early boot stages, where no other databases and network are available: audio, cdrom, dialout, disk, input, kmem, lp, tape, tty, video During runtime, the journal daemon requires the "systemd-journal" system group to exist. New journal files will be readable by this group (but not writable), which may be used to grant specific users read access. In addition, system groups "wheel" and "adm" will be given read-only access to journal files using systemd-tmpfiles.service. The journal gateway daemon requires the "systemd-journal-gateway" system user and group to exist. During execution this network facing service will drop privileges and assume this uid/gid for security reasons. Similarly, the NTP daemon requires the "systemd-timesync" system user and group to exist. Similarly, the network management daemon requires the "systemd-network" system user and group to exist. Similarly, the name resolution daemon requires the "systemd-resolve" system user and group to exist. Similarly, the kdbus dbus1 proxy daemon requires the "systemd-bus-proxy" system user and group to exist. Similarly, the coredump support requires the "systemd-coredump" system user and group to exist. NSS: systemd ships with three NSS modules: nss-myhostname resolves the local hostname to locally configured IP addresses, as well as "localhost" to 127.0.0.1/::1. nss-resolve enables DNS resolution via the systemd-resolved DNS/LLMNR caching stub resolver "systemd-resolved". nss-mymachines enables resolution of all local containers registered with machined to their respective IP addresses. To make use of these NSS modules, please add them to the "hosts: " line in /etc/nsswitch.conf. The "resolve" module should replace the glibc "dns" module in this file. The three modules should be used in the following order: hosts: files mymachines resolve myhostname SYSV INIT.D SCRIPTS: When calling "systemctl enable/disable/is-enabled" on a unit which is a SysV init.d script, it calls /usr/lib/systemd/systemd-sysv-install; this needs to translate the action into the distribution specific mechanism such as chkconfig or update-rc.d. Packagers need to provide this script if you need this functionality (you don't if you disabled SysV init support). Please see src/systemctl/systemd-sysv-install.SKELETON for how this needs to look like, and provide an implementation at the marked places. WARNINGS: systemd will warn you during boot if /usr is on a different file system than /. While in systemd itself very little will break if /usr is on a separate partition, many of its dependencies very likely will break sooner or later in one form or another. For example, udev rules tend to refer to binaries in /usr, binaries that link to libraries in /usr or binaries that refer to data files in /usr. Since these breakages are not always directly visible, systemd will warn about this, since this kind of file system setup is not really supported anymore by the basic set of Linux OS components. systemd requires that the /run mount point exists. systemd also requires that /var/run is a symlink to /run. For more information on this issue consult http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken To run systemd under valgrind, compile with VALGRIND defined (e.g. ./configure CPPFLAGS='... -DVALGRIND=1'). Otherwise, false positives will be triggered by code which violates some rules but is actually safe. Currently, systemd-timesyncd defaults to use the Google NTP servers if not specified otherwise at configure time. You really should not ship an OS or device with this default setting. See DISTRO_PORTING for details. ENGINEERING AND CONSULTING SERVICES: Kinvolk (https://kinvolk.io) offers professional engineering and consulting services for systemd. Please contact Chris Kühl for more information. systemd-229/README.md000066400000000000000000000021211265713322000143340ustar00rootroot00000000000000# systemd - System and Service Manager [![Build Status](https://semaphoreci.com/api/v1/projects/28a5a3ca-3c56-4078-8b5e-7ed6ef912e14/443470/shields_badge.svg)](https://semaphoreci.com/systemd/systemd)
[![Coverity Scan Status](https://scan.coverity.com/projects/350/badge.svg)](https://scan.coverity.com/projects/350) ## Details General information about systemd can be found in the [systemd Wiki](http://www.freedesktop.org/wiki/Software/systemd). Information about build requirements are provided in the [README file](../master/README). Consult our [NEWS file](../master/NEWS) for information about what's new in the most recent systemd versions. Please see our [Contribution Guidelines](../master/CONTRIBUTING.md) for more information about filing GitHub Issues and posting GitHub Pull Requests. When preparing patches for systemd, please follow our [Coding Style Guidelines](../master/CODING_STYLE). If you are looking for support, please contact our [mailing list](http://lists.freedesktop.org/mailman/listinfo/systemd-devel) or join our [IRC channel](irc://irc.freenode.org/%23systemd). systemd-229/TODO000066400000000000000000001231051265713322000135530ustar00rootroot00000000000000Bugfixes: * Should systemctl status \* work on all unit types, not just .service? * Dangling symlinks of .automount unit files in .wants/ directories, set up automount points even when the original .automount file did not exist anymore. Only the .mount unit was still around. * ExecStart with unicode characters fails in strv_split_extract: [Service] Environment=ONE='one' "TWO='two two' too" THREE= ExecStart=/bin/python3 -c 'import sys;print(sys.argv)' $ONE $TWO $THREE * When systemctl --host is used, underlying ssh connection can remain open. bus_close does not kill children? External: * Fedora: add an rpmlint check that verifies that all unit files in the RPM are listed in %systemd_post macros. * wiki: update journal format documentation for lz4 additions Janitorial Clean-ups: * code cleanup: retire FOREACH_WORD_QUOTED, port to extract_first_word() loops instead * replace manual readdir() loops with FOREACH_DIRENT or FOREACH_DIRENT_ALL * Get rid of the last strerror() invocations in favour of %m and strerror_r() * Rearrange tests so that the various test-xyz.c match a specific src/basic/xyz.c again Features: * delay activation of logind until somebody logs in, or when /dev/tty0 pulls it in or lingering is on (so that containers don't bother with it until PAM is used). also exit-on-idle * cache sd_event_now() result from before the first iteration... * remove Capabilities=, after all AmbientCapabilities= and CapabilityBoundingSet= should be enough. * support for the new copy_file_range() syscall * add systemctl stop --job-mode=triggering that follows TRIGGERED_BY deps and adds them to the same transaction * Maybe add a way how users can "pin" units into memory, so that they are not subject to automatic GC? * PID1: find a way how we can reload unit file configuration for specific units only, without reloading the whole of systemd * add an explicit parser for LimitNICE= and LimitRTPRIO= that verifies the specified range and generates sane error messages for incorrect specifications. Also, for LimitNICE= maybe introduce a syntax such as "+5" or "-7" in order to make the limits more readable as they are otherwise shifted by 20. * do something about "/control" subcgroups in the unified cgroup hierarchy * when we detect that there are waiting jobs but no running jobs, do something * push CPUAffinity= also into the "cpuset" cgroup controller (only after the cpuset controller got ported to the unified hierarchy) * add a new command "systemctl revert" or so, that removes all dropin snippets in /run and /etc, and all unit files with counterparts in /usr, and thus undoes what "systemctl set-property" and "systemctl edit" create. Maybe even add "systemctl revert -a" to do this for all units. * PID 1 should send out sd_notify("WATCHDOG=1") messages (for usage in the --user mode, and when run via nspawn) * consider throwing a warning if a service declares it wants to be "Before=" a .device unit. * there's probably something wrong with having user mounts below /sys, as we have for debugfs. for exmaple, src/core/mount.c handles mounts prefixed with /sys generally special. http://lists.freedesktop.org/archives/systemd-devel/2015-June/032962.html * man: document that unless you use StandardError=null the shell >/dev/stderr won't work in shell scripts in services * install: include generator dirs in unit file search paths * rework C11 utf8.[ch] to use char32_t instead of uint32_t when referring to unicode chars, to make things more expressive. * fstab-generator: default to tmpfs-as-root if only usr= is specified on the kernel cmdline * docs: bring http://www.freedesktop.org/wiki/Software/systemd/MyServiceCantGetRealtime up to date * mounting and unmounting mount points manually with different source devices will result in collected collected on all devices used. http://lists.freedesktop.org/archives/systemd-devel/2015-April/030225.html * add a job mode that will fail if a transaction would mean stopping running units. Use this in timedated to manage the NTP service state. http://lists.freedesktop.org/archives/systemd-devel/2015-April/030229.html * Maybe add support for the equivalent of "ethtool advertise" to .link files? http://lists.freedesktop.org/archives/systemd-devel/2015-April/030112.html * The udev blkid built-in should expose a property that reflects whether media was sensed in USB CF/SD card readers. This should then be used to control SYSTEMD_READY=1/0 so that USB card readers aren't picked up by systemd unless they contain a medium. This would mirror the behaviour we already have for CD drives. * networkd/udev: implement SR_IOV configuration in .link files: http://lists.freedesktop.org/archives/systemd-devel/2015-January/027451.html * Rework systemctl's GetAll property parsing to use the generic bus_map_all_properties() API * implement a per-service firewall based on net_cls * Port various tools to make use of verbs.[ch], where applicable * hostnamectl: show root image uuid * sysfs set api in libudev is not const * Find a solution for SMACK capabilities stuff: http://lists.freedesktop.org/archives/systemd-devel/2014-December/026188.html * "systemctl preset-all" should probably order the unit files it operates on lexicographically before starting to work, in order to ensure deterministic behaviour if two unit files conflict (like DMs do, for example) * synchronize console access with BSD locks: http://lists.freedesktop.org/archives/systemd-devel/2014-October/024582.html * as soon as we have kdbus, and sender timestamps, revisit coalescing multiple parallel daemon reloads: http://lists.freedesktop.org/archives/systemd-devel/2014-December/025862.html * the install state probably shouldn't get confused by generated units, think dbus1/kdbus compat! * in systemctl list-unit-files: show the install value the presets would suggest for a service in a third column * figure out when we can use the coarse timers * add "systemctl start -v foobar.service" that shows logs of a service while the start command runs. This is non-trivial to do without races though, since we should flush out all journal messages before returning from the "systemctl stop". * firstboot: make it useful to be run immediately after yum --installroot to set up a machine. (most specifically, make --copy-root-password work even if /etc/passwd already exists * add infrastructure to allocate dynamic/transient users and UID ranges, for use in user-namespaced containers, per-seat gdm login screens and gdm guest sessions * maybe add support for specifier expansion in user.conf, specifically DefaultEnvironment= * introduce systemd-timesync-wait.service or so to sync on an NTP fix? * systemd --user should issue sd_notify() upon reaching basic.target, not on becoming idle * consider showing the unit names during boot up in the status output, not just the unit descriptions * maybe allow timer units with an empty Units= setting, so that they can be used for resuming the system but nothing else. * what to do about udev db binary stability for apps? (raw access is not an option) * maybe provide an API to allow migration of foreign PIDs into existing scopes. * man: maybe use the word "inspect" rather than "introspect"? * systemctl: if some operation fails, show log output? * systemctl edit: - allow creation of units from scratch - use equvalent of cat() to insert existing config as a comment, prepended with #. Upon editor exit, lines with one # are removed, lines with two # are left with one #, etc. * exponential backoff in timesyncd when we cannot reach a server * timesyncd: add ugly bus calls to set NTP servers per-interface, for usage by NM * extract_many_words() should probably be used by a lot of code that currently uses FOREACH_WORD and friends. For example, most conf parsing callbacks should use it. * merge ~/.local/share and ~/.local/lib into one similar /usr/lib and /usr/share.... * systemd.show_status= should probably have a mode where only failed units are shown. * add systemd.abort_on_kill or some other such flag to send SIGABRT instead of SIGKILL (throughout the codebase, not only PID1) * resolved: - mDNS/DNS-SD - service registration - service/domain/types browsing - avahi compat - DNS-SD service registration from socket units - resolved should optionally register additional per-interface LLMNR names, so that for the container case we can establish the same name (maybe "host") for referencing the server, everywhere. - enable DNSSEC by default - allow clients to request DNSSEC for a single lookup even if DNSSEC is off (?) * refcounting in sd-resolve is borked * Add a new verb "systemctl top" * add new gpt type for btrfs volumes * support empty /etc boots nicely: - nspawn/gpt-generator: introduce new gpt partition type for /usr - fstab-generator: support systemd.volatile=yes|no|state on the kernel cmdline, too, similar to nspawn's --volatile= * generator that automatically discovers btrfs subvolumes, identifies their purpose based on some xattr on them. * a way for container managers to turn off getty starting via $container_headless= or so... * figure out a nice way how we can let the admin know what child/sibling unit causes cgroup membership for a specific unit * mount_cgroup_controllers(): symlinks need to get the label applied * For timer units: add some mechanisms so that timer units that trigger immediately on boot do not have the services they run added to the initial transaction and thus confuse Type=idle. * Run most system services with cgroupfs read-only and procfs with a more secure mode (doesn't work, since the hidepid= option is per-pid-namespace, not per-mount) * add bus api to query unit file's X fields. * gpt-auto-generator: - Support LUKS for root devices - Define new partition type for encrypted swap? Support probed LUKS for encrypted swap? - Make /home automount rather than mount? * add generator that pulls in systemd-network from containers when CAP_NET_ADMIN is set, more than the loopback device is defined, even when it is otherwise off * MessageQueueMessageSize= and RLimitFSIZE= (and suchlike) should use parse_iec_size(). * "busctl status" works only as root on dbus1, since we cannot read /proc/$PID/exe * implement Distribute= in socket units to allow running multiple service instances processing the listening socket, and open this up for ReusePort= * socket units: support creating sockets in different namespace, opening it up for JoinsNamespaceOf=. This would require to fork off a tiny process that joins the namespace and creates/binds the socket and passes this back to PID1 via SCM_RIGHTS. This also could be used to allow Chown/chgrp on sockets without requiring NSS in PID 1. * New service property: maximum CPU and wallclock runtime for a service * introduce bus call FreezeUnit(s, b), as well as "systemctl freeze $UNIT" and "systemctl thaw $UNIT" as wrappers around this. The calls should SIGSTOP all unit processes in a loop until all processes of it are fully stopped. This can later be used for app management by desktop UIs such as gnome-shell to freeze apps that are not visible on screen, not unlike how job control works on the shell * cgroups: - implement per-slice CPUFairScheduling=1 switch - handle jointly mounted controllers correctly - introduce high-level settings for RT budget, swappiness - how to reset dynamically changed unit cgroup attributes sanely? - when reloading configuration, apply new cgroup configuration - when recursively showing the cgroup hierarchy, optionally also show the hierarchies of child processes * transient units: - add field to transient units that indicate whether systemd or somebody else saves/restores its settings, for integration with libvirt - ensure scope units may be started only a single time * Automatically configure swap partition to use for hibernation by looking for largest swap partition on the root disk? * when we detect low battery and no AC on boot, show pretty splash and refuse boot * libsystemd-journal, libsystemd-login, libudev: add calls to easily attach these objects to sd-event event loops * be more careful what we export on the bus as (usec_t) 0 and (usec_t) -1 * unify dispatch table in systemctl_main() and friends * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it * After coming back from hibernation reset hibernation swap partition using the /dev/snapshot ioctl APIs * If we try to find a unit via a dangling symlink, generate a clean error. Currently, we just ignore it and read the unit from the search path anyway. * refuse boot if /etc/os-release is missing or /etc/machine-id cannot be set up * btrfs raid assembly: some .device jobs stay stuck in the queue * make sure gdm does not use multi-user-x but the new default X configuration file, and then remove multi-user-x from systemd * man: the documentation of Restart= currently is very misleading and suggests the tools from ExecStartPre= might get restarted. * load .d/*.conf dropins for device units * allow implementation of InaccessibleDirectories=/ plus ReadOnlyDirectories=... for whitelisting files for a service. * sd-bus: - EBADSLT handling - GetAllProperties() on a non-existing object does not result in a failure currently - kdbus: process fd=-1 for incoming msgs - port to sd-resolve for connecting to TCP dbus servers - kdbus: maybe add controlling tty metadata fields - see if we can introduce a new sd_bus_get_owner_machine_id() call to retrieve the machine ID of the machine of the bus itself - when kdbus does not take our message without memfds, try again with memfds - see if we can drop more message validation on the sending side - add API to clone sd_bus_message objects - make AddMatch calls on dbus1 transports async? - kdbus: matches against source or destination pids for an "strace -p"-like feel. Problem: The PID info needs to be available in userspace too... - longer term: priority inheritance - dbus spec updates: - kdbus mapping - NameLost/NameAcquired obsolete - GVariant - path escaping - update systemd.special(7) to mention that dbus.socket is only about the compatibility socket now - test bloom filter generation indexes - bus-proxy: when passing messages from kdbus, make sure we properly handle the case where a large number of fds is appended that we cannot pass into sendmsg() of the AF_UNIX sokcet (which only accepts 253 messages) - kdbus: introduce a concept of "send-only" connections - kdbus: add counter for refused unicast messages that is passed out via the RECV ioctl. SImilar to the counter for dropped multicast messages we already have. * sd-event - allow multiple signal handlers per signal? - document chaining of signal handler for SIGCHLD and child handlers - define more intervals where we will shift wakeup intervals around in, 1h, 6h, 24h, ... - generate a failure of a default event loop is executed out-of-thread - maybe add support for inotify events * investigate endianness issues of UUID vs. GUID * dbus: when a unit failed to load (i.e. is in UNIT_ERROR state), we should be able to safely try another attempt when the bus call LoadUnit() is invoked. * add a pam module that passes the hdd passphrase into the PAM stack and then expires it, for usage by gdm auto-login. * add a pam module that on password changes updates any LUKS slot where the password matches * maybe add a generator that looks for "systemd.run=" on the kernel cmdline for container usercases... * cgtop: make cgtop useful in a container * test/: - add 'set -e' to scripts in test/ - make stuff in test/ work with separate output dir * seems that when we follow symlinks to units we prefer the symlink destination path over /etc and /usr. We should not do that. Instead /etc should always override /run+/usr and also any symlink destination. * when isolating, try to figure out a way how we implicitly can order all units we stop before the isolating unit... * teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) * BootLoaderSpec: Clarify that the kernel has to be in $BOOT. Clarify that the boot loader should be installed to the ESP. Define a way how an installer can figure out whether a BLS compliant boot loader is installed. * think about requeuing jobs when daemon-reload is issued? usecase: the initrd issues a reload after fstab from the host is accessible and we might want to requeue the mounts local-fs acquired through that automatically. * systemd-inhibit: make taking delay locks useful: support sending SIGINT or SIGTERM on PrepareForSleep() * remove any syslog support from log.c -- we probably cannot do this before split-off udev is gone for good * shutdown logging: store to EFI var, and store to USB stick? * think about window-manager-run-as-user-service problem: exit 0 → activate shutdown.target; exit != 0 → restart service * merge unit_kill_common() and unit_kill_context() * introduce ExecCondition= in services * EFI: - honor language efi variables for default language selection (if there are any?) - honor timezone efi variables for default timezone selection (if there are any?) - change bootctl to be backed by systemd-bootd to control temporary and persistent default boot goal plus efi variables * maybe do not install getty@tty1.service symlink in /etc but in /usr? * print a nicer explanation if people use variable/specifier expansion in ExecStart= for the first word * mount: turn dependency information from /proc/self/mountinfo into dependency information between systemd units. * logind: - logind: optionally, ignore idle-hint logic for autosuspend, block suspend as long as a session is around - When we update the kernel all kind of hibernation should be prohibited until shutdown/reboot - logind: wakelock/opportunistic suspend support - Add pretty name for seats in logind - logind: allow showing logout dialog from system? - we should probably handle SIGTERM/SIGINT to not leave dot files around, just in case - session scopes/user unit: add RequiresMountsFor for the home directory of the user - add Suspend() bus calls which take timestamps to fix double suspend issues when somebody hits suspend and closes laptop quickly. - if pam_systemd is invoked by su from a process that is outside of a any session we should probably just become a NOP, since that's usually not a real user session but just some system code that just needs setuid(). - logind: make the Suspend()/Hibernate() bus calls wait for the for the job to be completed. before returning, so that clients can wait for "systemctl suspend" to finish to know when the suspending is complete. - logind: when the power button is pressed short, just popup a logout dialog. If it is pressed for 1s, do the usual shutdown. Inspiration are Macs here. - expose "Locked" property on logind sesison objects - given that logind now lets PID 1 do all nasty work, we can probably reduce the capability set it retains substantially. (we need CAP_SYS_ADMIN for drmSetMaster(), so maybe not worth it) - expose orientation sensors and tablet mode through logind - maybe allow configuration of the StopTimeout for session scopes - rename session scope so that it includes the UID. THat way the session scope can be arranged freely in slices and we don't have make assumptions about their slice anymore. - follow PropertiesChanged state more closely, to deal with quick logouts and relogins * exec: when deinitializating a tty device fix the perms and group, too, not only when initializing. Set access mode/gid to 0620/tty. * service: watchdog logic: for testing purposes allow ping, but do not require pong * journal: - consider introducing implicit _TTY= + _PPID= + _EUID= + _EGID= + _FSUID= + _FSGID= fields - import and delete pstore filesystem content at startup - journald: also get thread ID from client, plus thread name - journal: when waiting for journal additions in the client always sleep at least 1s or so, in order to minimize wakeups - add API to close/reopen/get fd for journal client fd in libsystemd-journal. - fallback to /dev/log based logging in libsystemd-journal, if we cannot log natively? - declare the local journal protocol stable in the wiki interface chart - sd-journal: speed up sd_journal_get_data() with transparent hash table in bg - journald: when dropping msgs due to ratelimit make sure to write "dropped %u messages" not only when we are about to print the next message that works, but alraedy after a short tiemout - check if we can make journalctl by default use --follow mode inside of less if called without args? - maybe add API to send pairs of iovecs via sd_journal_send - journal: when writing journal auto-rotate if time jumps backwards - journal: add a setgid "systemd-journal" utility to invoke from libsystemd-journal, which passes fds via STDOUT and does PK access - journactl: support negative filtering, i.e. FOOBAR!="waldo", and !FOOBAR for events without FOOBAR. - journal: store timestamp of journal_file_set_offline() int he header, so it is possible to display when the file was last synced. - journal-send.c, log.c: when the log socket is clogged, and we drop, count this and write a message about this when it gets unclogged again. - journal: find a way to allow dropping history early, based on priority, other rules - journal: When used on NFS, check payload hashes - journald: add kernel cmdline option to disable ratelimiting for debug purposes - refuse taking lower-case variable names in sd_journal_send() and friends. - journald: we currently rotate only after MaxUse+MaxFilesize has been reached. - journal: deal nicely with byte-by-byte copied files, especially regards header - journal: sanely deal with entries which are larger than the individual file size, but where the components would fit - Replace utmp, wtmp, btmp, and lastlog completely with journal - journalctl: instead --after-cursor= maybe have a --cursor=XYZ+1 syntax? - when a kernel driver logs in a tight loop, we should ratelimit that too. - journald: optionally, log debug messages to /run but everything else to /var - journald: when we drop syslog messages because the syslog socket is full, make sure to write how many messages are lost as first thing to syslog when it works again. - journald: make sure ratelimit is actually really per-service with the new cgroup changes - change systemd-journal-flush into a service that stays around during boot, and causes the journal to be moved back to /run on shutdown, so that we do not keep /var busy. This needs to happen synchronously, hence doing this via signals is not going to work. - optionally support running journald from the command line for testing purposes in external projects - journald: allow per-priority and per-service retention times when rotating/vacuuming - journald: make use of uid-range.h to managed uid ranges to split journals in. - journalctl: add the ability to look for the most recent process of a binary. journalctl /usr/bin/X11 --pid=-1 or so... - improve journalctl performance by loading journal files lazily. Encode just enough information in the file name, so that we do not have to open it to know that it is not interesting for us, for the most common operations. - journal-or-kmsg is currently broken? See reverted commit 4a01181e460686d8b4a543b1dfa7f77c9e3c5ab8. - man: document that corrupted journal files is nothing to act on - rework journald sigbus stuff to use mutex - Set RLIMIT_NPROC for systemd-journal-xyz, and all other of our services that run under their own user ids, and use User= (but only in a world where userns is ubiquitous since otherwise we cannot invoke those daemons on the host AND in a container anymore). Also, if LimitNPROC= is used without User= we should warn and refuse operation. - journalctl --verify: don't show files that are currently being written to as FAIL, but instead show that their are being written to. - add journalctl -H that talks via ssh to a remote peer and passes through binary logs data - change journalctl -M to acquire fd to journal directory via machined, and then operate on that via openat() instead of absolute paths - add a version of --merge which also merges /var/log/journal/remote - log accumulated resource usage after each service invocation - journalctl: -m should access container journals directly by enumerating them via machined, and also watch containers coming and going. Benefit: nspawn --ephemeral would start working nicely with the journal. - assign MESSAGE_ID to log messages about failed services * document: - document that deps in [Unit] sections ignore Alias= fields in [Install] units of other units, unless those units are disabled - man: clarify that time-sync.target is not only sysv compat but also useful otherwise. Same for similar targets - document the exit codes when services fail before they are exec()ed - document that service reload may be implemented as service reexec - document in wiki how to map ical recurrence events to systemd timer unit calendar specifications - add a man page containing packaging guidelines and recommending usage of things like Documentation=, PrivateTmp=, PrivateNetwork= and ReadOnlyDirectories=/etc /usr. - document systemd-journal-flush.service properly - documentation: recommend to connect the timer units of a service to the service via Also= in [Install] - man: document the very specific env the shutdown drop-in tools live in - man: add more examples to man pages - man: maybe sort directives in man pages, and take sections from --help and apply them to man too * systemctl: - systemctl list-jobs - show dependencies - add systemctl switch to dump transaction without executing it - Add a verbose mode to "systemctl start" and friends that explains what is being done or not done - "systemctl disable" on a static unit prints no message and does nothing. "systemctl enable" does nothing, and gives a bad message about it. Should fix both to print nice actionable messages. - print nice message from systemctl --failed if there are no entries shown, and hook that into ExecStartPre of rescue.service/emergency.service - add new command to systemctl: "systemctl system-reexec" which reexecs as many daemons as virtually possible - systemctl enable: fail if target to alias into does not exist? maybe show how many units are enabled afterwards? - systemctl: "Journal has been rotated since unit was started." message is misleading - better error message if you run systemctl without systemd running - systemctl status output should should include list of triggering units and their status * unit install: - "systemctl mask" should find all names by which a unit is accessible (i.e. by scanning for symlinks to it) and link them all to /dev/null - systemctl list-unit-files should list generated files (and probably with a new state "generated" for them, or so) * timer units: - timer units should get the ability to trigger when: o CLOCK_REALTIME makes jumps (TFD_TIMER_CANCEL_ON_SET) o DST changes - Support 2012-02~4 as syntax for specifying the fourth to last day of the month. - calendarspec: support value ranges with ".." notation. Example: 2013-4..8-1 - Modulate timer frequency based on battery state * add libsystemd-password or so to query passwords during boot using the password agent logic * clean up date formatting and parsing so that all absolute/relative timestamps we format can also be parsed * on shutdown: move utmp, wall, audit logic all into PID 1 (or logind?), get rid of systemd-update-utmp-runlevel * make repeated alt-ctrl-del presses printing a dump, or even force a reboot without waiting for the timeout * hostnamed: before returning information from /etc/machine-info.conf check the modification data and reread. Similar for localed, ... * currently x-systemd.timeout is lost in the initrd, since crypttab is copied into dracut, but fstab is not * nspawn: - to allow "linking" of nspawn containers, extend --network-bridge= so that it can dynamically create bridge interfaces that are refcounted by the containers on them. For each group of containers to link together - refuses to boot containers without /etc/machine-id (OK?), and with empty /etc/machine-id (not OK). - nspawn -x should support ephemeral instances of gpt images - emulate /dev/kmsg using CUSE and turn off the syslog syscall with seccomp. That should provide us with a useful log buffer that systemd can log to during early boot, and disconnect container logs from the kernel's logs. - as soon as networkd has a bus interface, hook up --network-interface=, --network-bridge= with networkd, to trigger netdev creation should an interface be missing - don't copy /etc/resolv.conf from host into container unless we are in shared-network mode - a nice way to boot up without machine id set, so that it is set at boot automatically for supporting --ephemeral. Maybe hash the host machine id together with the machine name to generate the machine id for the container - fix logic always print a final newline on output. https://github.com/systemd/systemd/pull/272#issuecomment-113153176 - should optionally support receiving WATCHDOG=1 messages from its payload PID 1... - should send out sd_notify("WATCHDOG=1") messages - optionally automatically add FORWARD rules to iptables whenever nspawn is running, remove them when shut down. - add a logic for cleaning up read-only, hidden container images in /var/lib/machines that are not ancestors of any non-hidden containers - Improve error message when --bind= is used on a non-existing source directory - maybe make copying of /etc/resolv.conf optional, and skip it if --read-only is used * machined: - "machinectl list" should probably show columns for OS version and IP addresses - add an API so that libvirt-lxc can inform us about network interfaces being removed or added to an existing machine - "machinectl migrate" or similar to copy a container from or to a difference host, via ssh - introduce systemd-nspawn-ephemeral@.service, and hook it into "machinectl start" with a new --ephemeral switch - "machinectl status" should also show internal logs of the container in question - "machinectl list-images" should show os-release data, as well as machine-info data (including deployment level) - "machinectl history" - "machinectl diff" - "machinectl commit" that takes a writable snapshot of a tree, invokes a shell in it, and marks it read-only after use * importd: - generate a nice warning if mkfs.btrfs is missing * cryptsetup: - cryptsetup-generator: allow specification of passwords in crypttab itself - move cryptsetup key caching into kernel keyctl? https://bugs.freedesktop.org/show_bug.cgi?id=54982 - support rd.luks.allow-discards= kernel cmdline params in cryptsetup generator * hw watchdog: optionally try to use the preset watchdog timeout instead of always overriding it https://bugs.freedesktop.org/show_bug.cgi?id=54712 * create /sbin/init symlinks from the build system * MountFlags=shared acts as MountFlags=slave right now. * properly handle loop back mounts via fstab, especially regards to fsck/passno * initialize the hostname from the fs label of /, if /etc/hostname does not exist? * rename "userspace" to "core-os" * udev: - move to LGPL - kill scsi_id - add trigger --subsystem-match=usb/usb_device device - reimport udev db after MOVE events for devices without dev_t * when a service has the same env var set twice we actually store it twice and return that in systemctl show -p... We should only show the last setting * There's currently no way to cancel fsck (used to be possible via C-c or c on the console) * add option to sockets to avoid activation. Instead just drop packets/connections, see http://cyberelk.net/tim/2012/02/15/portreserve-systemd-solution/ * coredump: - save coredump in Windows/Mozilla minidump format - move PID 1 segfaults to /var/lib/systemd/coredump? * support crash reporting operation modes (https://live.gnome.org/GnomeOS/Design/Whiteboards/ProblemReporting) * default to actual 32-bit PIDs, via /proc/sys/kernel/pid_max * be able to specify a forced restart of service A where service B depends on, in case B needs to be auto-respawned? * tmpfiles: - apply "x" on "D" too (see patch from William Douglas) - replace F with f+. - instead of ignoring unknown fields, reject them. - creating new directories/subvolumes/fifos/device nodes should not follow symlinks. None of the other adjustment or creation calls follow symlinks. * make sure systemd-ask-password-wall does not shutdown systemd-ask-password-console too early * verify that the AF_UNIX sockets of a service in the fs still exist when we start a service in order to avoid confusion when a user assumes starting a service is enough to make it accessible * Make it possible to set the keymap independently from the font on the kernel cmdline. Right now setting one resets also the other. * and a dbus call to generate target from current state * write blog stories about: - hwdb: what belongs into it, lsusb - enabling dbus services - status update - how to make changes to sysctl and sysfs attributes - remote access - how to pass throw-away units to systemd, or dynamically change properties of existing units - testing with Harald's awesome test kit - auto-restart - how to develop against journal browsing APIs - the journal HTTP iface - non-cgroup resource management - dynamic resource management with cgroups - refreshed, longer missions statement - calendar time events - init=/bin/sh vs. "emergency" mode, vs. "rescue" mode, vs. "multi-user" mode, vs. "graphical" mode, and the debug shell - how to create your own target - instantiated apache, dovecot and so on - hooking a script into various stages of shutdown/rearly booot * investigate whether the gnome pty helper should be moved into systemd, to provide cgroup support. * dot output for --test showing the 'initial transaction' * fingerprint.target, wireless.target, gps.target, netdevice.target * pid1: - .timer units should optionally support CLOCK_BOOTTIME in addition to CLOCK_MONOTONIC - When logging about multiple units (stopping BoundTo units, conflicts, etc.), log both units as UNIT=, so that journalctl -u triggers on both. - generate better errors when people try to set transient properties that are not supported... http://lists.freedesktop.org/archives/systemd-devel/2015-February/028076.html - maybe introduce WantsMountsFor=? Usecase: http://lists.freedesktop.org/archives/systemd-devel/2015-January/027729.html - recreate systemd's D-Bus private socket file on SIGUSR2 - GC unreferenced jobs (such as .device jobs) - move PAM code into its own binary - when we automatically restart a service, ensure we restart its rdeps, too. - for services: do not set $HOME in services unless requested - hide PAM options in fragment parser when compile time disabled - Support --test based on current system state - If we show an error about a unit (such as not showing up) and it has no Description string, then show a description string generated form the reverse of unit_name_mangle(). - after deserializing sockets in socket.c we should reapply sockopts and things - drop PID 1 reloading, only do reexecing (difficult: Reload() currently is properly synchronous, Reexec() is weird, because we cannot delay the response properly until we are back, so instead of being properly synchronous we just keep open the fd and close it when done. That means clients do not get a successful method reply, but much rather a disconnect on success. - when breaking cycles drop sysv services first, then services from /run, then from /etc, then from /usr - when a bus name of a service disappears from the bus make sure to queue further activation requests * unit files: - allow port=0 in .socket units - maybe introduce ExecRestartPre= - add ReloadSignal= for configuring a reload signal to use - implement Register= switch in .socket units to enable registration in Avahi, RPC and other socket registration services. - allow Type=simple with PIDFile= https://bugzilla.redhat.com/show_bug.cgi?id=723942 - allow writing multiple conditions in unit files on one line - load-fragment: when loading a unit file via a chain of symlinks verify that it is not masked via any of the names traversed. - introduce Type=pid-file - ExecOnFailure=/usr/bin/foo - introduce mix of BindTo and Requisite - add a concept of RemainAfterExit= to scope units - Set NoNewPrivileges= on all of our own services, where that makes sense - Allow multiple ExecStart= for all Type= settings, so that we can cover rescue.service nicely - consider adding RuntimeDirectoryUser= + RuntimeDirectoryGroup= * systemd-python: - figure out a simple way to wait for journal events in a way that works with ^C - add documentation to systemd.daemon * bootchart: - plot per-process IO utilization - group processes based on service association (cgroups) - document initcall_debug - kernel cmdline "bootchart" option for simplicity? * udev-link-config: - Make sure ID_PATH is always exported and complete for network devices where possible, so we can safely rely on Path= matching - check MTUBytes parsing (expecting size_t but we are using unsigned) * sd-rtnl: - add support for more attribute types - inbuilt piping support (essentially degenerate async)? see loopback-setup.c and other places * networkd: - add more keys to [Route] and [Address] sections - add support for more DHCPv4 options (and, longer term, other kinds of dynamic config) - add proper initrd support (in particular generate .network/.link files based on /proc/cmdline) - add reduced [Link] support to .network files - add Scope= parsing option for [Network] - properly handle routerless dhcp leases - add more attribute support for SIT tunnel - work with non-Ethernet devices - add support for more bond options - dhcp: do we allow configuring dhcp routes on interfaces that are not the one we got the dhcp info from? - add LLDP client side support - the DHCP lease data (such as NTP/DNS) is still made available when a carrier is lost on a link. It should be removed instantly. - expose in the API the following bits: - option 15, domain name and/or option 119, search list - option 12, host name and/or option 81, fqdn - option 123, 144, geolocation - option 252, configure http proxy (PAC/wpad) - provide a way to define a per-network interface default metric value for all routes to it. possibly a second default for DHCP routes. - allow Name= to be specified repeatedly in the [Match] section. Maybe also support Name=foo*|bar*|baz ? - duplicate address check for static IPs (like ARPCHECK in network-scripts) - allow DUID/IAID to be customized, see issue #394. - support configuration option for TSO (tcp segmentation offload) - whenever uplink info changes, make DHCP server send out FORCERENEW * networkd-wait-online: - make operstates to wait for configurable? * dhcp: - figure out how much we can increase Maximum Message Size - support RFC4702 (pass FQDN) * dhcp6: - add functions to set previously stored IPv6 addresses on startup and get them at shutdown; store them in client->ia_na - write more test cases - implement reconfigure support, see 5.3., 15.11. and 22.20. - implement support for temporary adressess (IA_TA) - implement dhcpv6 authentication - investigate the usefulness of Confirm messages; i.e. are there any situations where the link changes without any loss in carrier detection or interface down - some servers don't do rapid commit without a filled in IA_NA, verify this behavior External: * dbus: - natively watch for dbus-*.service symlinks (PENDING) - teach dbus to activate all services it finds in /etc/systemd/services/org-*.service * fix alsa mixer restore to not print error when no config is stored * make cryptsetup lower --iter-time * patch kernel for xattr support in /dev, /proc/, /sys? * kernel: add device_type = "fb", "fbcon" to class "graphics" * drop accountsservice's StandardOutput=syslog and Type=dbus fields * dbus: in fedora, make /var/lib/dbus/machine-id a symlink to /etc/machine-id * /usr/bin/service should actually show the new command line * fedora: suggest auto-restart on failure, but not on success and not on coredump. also, ask people to think about changing the start limit logic. Also point people to RestartPreventExitStatus=, SuccessExitStatus= * fedora: F20: go timer units all the way, leave cron.daily for cron * neither pkexec nor sudo initialize environ[] from the PAM environment? * fedora: update policy to declare access mode and ownership of unit files to root:root 0644, and add an rpmlint check for it * register catalog database signature as file magic * zsh shell completion: - - should complete options, but currently does not - systemctl add-wants,add-requires Regularly: * look for close() vs. close_nointr() vs. close_nointr_nofail() * check for strerror(r) instead of strerror(-r) * Use PR_SET_PROCTITLE_AREA if it becomes available in the kernel * pahole * set_put(), hashmap_put() return values check. i.e. == 0 does not free()! * use secure_getenv() instead of getenv() where appropriate * link up selected blog stories from man pages and unit files Documentation= fields systemd-229/autogen.sh000077500000000000000000000050671265713322000150720ustar00rootroot00000000000000#!/bin/sh # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . set -e oldpwd=$(pwd) topdir=$(dirname $0) cd $topdir if [ -f .git/hooks/pre-commit.sample ] && [ ! -f .git/hooks/pre-commit ]; then # This part is allowed to fail cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \ chmod +x .git/hooks/pre-commit && \ echo "Activated pre-commit hook." || : fi intltoolize --force --automake autoreconf --force --install --symlink libdir() { echo $(cd "$1/$(gcc -print-multi-os-directory)"; pwd) } args="\ --sysconfdir=/etc \ --localstatedir=/var \ --libdir=$(libdir /usr/lib) \ " if [ -f "$topdir/.config.args" ]; then args="$args $(cat $topdir/.config.args)" fi if [ ! -L /bin ]; then args="$args \ --with-rootprefix=/ \ --with-rootlibdir=$(libdir /lib) \ " fi cd $oldpwd if [ "x$1" = "xc" ]; then $topdir/configure CFLAGS='-g -O0 -ftrapv' --enable-compat-libs --enable-kdbus $args make clean elif [ "x$1" = "xg" ]; then $topdir/configure CFLAGS='-g -Og -ftrapv' --enable-compat-libs --enable-kdbus $args make clean elif [ "x$1" = "xa" ]; then $topdir/configure CFLAGS='-g -O0 -Wsuggest-attribute=pure -Wsuggest-attribute=const -ftrapv' --enable-compat-libs --enable-kdbus $args make clean elif [ "x$1" = "xl" ]; then $topdir/configure CC=clang CFLAGS='-g -O0 -ftrapv' --enable-compat-libs --enable-kdbus $args make clean elif [ "x$1" = "xs" ]; then scan-build $topdir/configure CFLAGS='-std=gnu99 -g -O0 -ftrapv' --enable-kdbus $args scan-build make else echo echo "----------------------------------------------------------------" echo "Initialized build system. For a common configuration please run:" echo "----------------------------------------------------------------" echo echo "$topdir/configure CFLAGS='-g -O0 -ftrapv' --enable-compat-libs --enable-kdbus $args" echo fi systemd-229/catalog/000077500000000000000000000000001265713322000144735ustar00rootroot00000000000000systemd-229/catalog/Makefile000077700000000000000000000000001265713322000205702../src/Makefileustar00rootroot00000000000000systemd-229/catalog/systemd.be.catalog000066400000000000000000000262271265713322000201150ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2012 Lennart Poettering # Copyright 2015 Viktar Vaŭčkievič # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Message catalog for systemd's own messages # Belarusian translation # The catalog format is documented on # Фармат каталога апісаны на старонцы # http://www.freedesktop.org/wiki/Software/systemd/catalog # For an explanation why we do all this, see https://xkcd.com/1024/ -- f77379a8490b408bbe5f6940505a777b Subject: Сэрвіс журналявання запусціўся Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Працэс сістэмнага журналявання запусціўся, адкрыў файлы для запісу і гатовы апрацоўваць запыты. -- d93fb3c9c24d451a97cea615ce59c00b Subject: Сэрвіс журналявання спыніўся Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Працэс сістэмнага журналявання спыніўся і закрыў усе файлы. -- a596d6fe7bfa4994828e72309e95d61e Subject: Паведамленні з сэрвісу адкінуты Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) Сэрвіс адправіў занадта штат паведамленняў за кароткі прамежак часу. Частка паведамленняў была адкінута. Майце на ўвазе, што былі адкінуты паведамлення толькі гэтага сэрвісу. Паведамленні іншых сэрвісаў засталіся. Мяжа, пасля якой паведамленні будуць адкінуты, наладжваецца з дапамогай RateLimitInterval= і RateLimitBurst= у файле /etc/systemd/journald.conf. Глядзіце journald.conf(5) для дэталей. -- e9bf28e6e834481bb6f48f548ad13606 Subject: Паведамленні страчаны Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Паведамленні ядра былі страчаны, так як сістэма журналявання не паспела іх апрацаваць. -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: Працэс @COREDUMP_PID@ (@COREDUMP_COMM@) скінуў дамп памяці Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) Працэс @COREDUMP_PID@ (@COREDUMP_COMM@) разбіўся і скінуў дамп памяці. Звычайна гэта сведчыць аб памылцы ў праграмным кодзе. Рэкамендуецца паведаміць аб гэтым распрацоўнікам. -- 8d45620c1a4348dbb17410da57c60c66 Subject: Новая сесія № @SESSION_ID@ створана для карыстальніка @USER_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Новая сесія з № @SESSION_ID@ створана для карыстальніка @USER_ID@. Лідар гэтай сесіі пад № @LEADER@. -- 3354939424b4456d9802ca8333ed424a Subject: Сесія № @SESSION_ID@ спынена Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Сесія № @SESSION_ID@ спынена. -- fcbefc5da23d428093f97c82a9290f7b Subject: Даступна новае працоўнае месца № @SEAT_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Новае працоўнае месца № @SEAT_ID@ наладжана і даступна для выкарыстання. -- e7852bfe46784ed0accde04bc864c2d5 Subject: Працоўнае месца № @SEAT_ID@ выдалена Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Працоўнае месца № @SEAT_ID@ выдалена і больш не даступна. -- c7a787079b354eaaa9e77b371893cd27 Subject: Час зменены Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Сістэмны гадзіннік зменены на @REALTIME@ мікрасекунд ад 1 студзеня 1970. -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: Часавы пояс зменены на @TIMEZONE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Сістэмны часавы пояс зменены на @TIMEZONE@. -- b07a249cd024414a82dd00cd181378ff Subject: Запуск сістэмы завяршыўся Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Усе сістэмныя сэрвісы, неабходныя для загрузкі сістэмы, паспяхова запусціліся. Майце на ўвазе, што гэта не значыць, што машына нічога не робіць. Магчыма, некаторыя сэрвісы яшчэ ініцыялізіруюцца. На запуск ядра спатрэбілася @KERNEL_USEC@ мікрасекунд. На запуск пачатковага RAM-дыска спатрэбілася @INITRD_USEC@ мікрасекунд. На запуск сістэмных сэрвісаў спатрэбілася @USERSPACE_USEC@ мікрасекунд. -- 6bbd95ee977941e497c48be27c254128 Subject: Сістэма перайшла ў стан сну @SLEEP@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Цяпер сістэма перайшла у стан сну @SLEEP@. -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: Сістэма выйшла са стана сну @SLEEP@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Цяпер сістэма выйшла са стана сну @SLEEP@. -- 98268866d1d54a499c4e98921d93bc40 Subject: Сістэма завяршае работу Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Пачаўся працэс выключэння сістэмы. Спыняюцца ўсе сістэмныя сэрвісы і дэмантуюцца файлавыя сістэмы. -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: Юніт @UNIT@ запускаецца Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Пачаўся працэс запуску юніта @UNIT@. -- 39f53479d3a045ac8e11786248231fbf Subject: Юніт @UNIT@ запусціўся Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Працэс запуску юніта @UNIT@ завершаны. Вынік: @RESULT@. -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: Юніт @UNIT@ спыняецца Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Пачаўся працэс спынення юніта @UNIT@. -- 9d1aaa27d60140bd96365438aad20286 Subject: Юніт @UNIT@ спынены Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Працэс спынення юніта @UNIT@ завершаны. -- be02cf6855d2428ba40df7e9d022f03d Subject: Збой юніта @UNIT@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Збой юніта @UNIT@. Вынік: @RESULT@. -- d34d037fff1847e6ae669a370e694725 Subject: Юніт @UNIT@ перачытвае сваю канфігурацыю Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Юніт @UNIT@ пачаў перачытваць сваю канфігурацыю. -- 7b05ebc668384222baa8881179cfda54 Subject: Юніт @UNIT@ перачытаў сваю канфігурацыю Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Юніт @UNIT@ перачытаў сваю канфігурацыю. Вынік: @RESULT@. -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: Працэс @EXECUTABLE@ не можа быць выкананы Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Працэс @EXECUTABLE@ не можа быць выкананы ў выніку збою. Ён вярнуў памылку нумар @ERRNO@. -- 0027229ca0644181a76c4e92458afa2e Sibject: Адно ці больш паведамленняў не былі накіраваны ў syslog Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Адно ці больш паведамленняў не былі накіраваны ў syslog сэрвіс, які выконваецца паралельна з journald. Звычайна гэта значыць, што рэалізацыя syslog не паспявае апрацаваць паведамленні з неабходнай хуткасцю. -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: Кропка мантавання не пустая Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Каталог @WHERE@ указаны як кропка мантавання (другое поле ў /etc/fstab ці Where= поле ў файле юніта systemd) і не пусты. Гэта не перашкаджае мантаванню, але існуючыя ў ім файлы будуць недаступны. Для доступу да іх, калі ласка, змантуйце гэтую файлавую сістэму ў іншае месца. -- 24d8d4452573402496068381a6312df2 Subject: Віртуальная машына або кантэйнер запусціўся Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Віртуальная машына @NAME@ з лідарам № @LEADER@ запусцілася і гатова для выкарыстання. -- 58432bd3bace477cb514b56381b8a758 Subject: Віртуальная машына або кантэйнер спынены Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Віртуальная машына @NAME@ з лідарам № @LEADER@ спынена. systemd-229/catalog/systemd.be@latin.catalog000066400000000000000000000217411265713322000212410ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2012 Lennart Poettering # Copyright 2015 Viktar Vaŭčkievič # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Message catalog for systemd's own messages # Belarusian Latin translation # The catalog format is documented on # Farmat kataloha apisany na staroncy # http://www.freedesktop.org/wiki/Software/systemd/catalog # For an explanation why we do all this, see https://xkcd.com/1024/ -- f77379a8490b408bbe5f6940505a777b Subject: Servis žurnaliavannia zapusciŭsia Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Praces sistemnaha žurnaliavannia zapusciŭsia, adkryŭ fajly dlia zapisu i hatovy apracoŭvać zapyty. -- d93fb3c9c24d451a97cea615ce59c00b Subject: Servis žurnaliavannia spyniŭsia Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Praces sistemnaha žurnaliavannia spyniŭsia i zakryŭ usie fajly. -- a596d6fe7bfa4994828e72309e95d61e Subject: Paviedamlienni z servisu adkinuty Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) Servis adpraviŭ zanadta štat paviedamlienniaŭ za karotki pramiežak času. Častka paviedamlienniaŭ byla adkinuta. Majcie na ŭvazie, što byli adkinuty paviedamliennia toĺki hetaha servisu. Paviedamlienni inšych servisaŭ zastalisia. Miaža, paslia jakoj paviedamlienni buduć adkinuty, naladžvajecca z dapamohaj RateLimitInterval= i RateLimitBurst= u fajlie /etc/systemd/journald.conf. Hliadzicie journald.conf(5) dlia detaliej. -- e9bf28e6e834481bb6f48f548ad13606 Subject: Paviedamlienni stračany Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Paviedamlienni jadra byli stračany, tak jak sistema žurnaliavannia nie paspiela ich apracavać. -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: Praces @COREDUMP_PID@ (@COREDUMP_COMM@) skinuŭ damp pamiaci Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) Praces @COREDUMP_PID@ (@COREDUMP_COMM@) razbiŭsia i skinuŭ damp pamiaci. Zvyčajna heta sviedčyć ab pamylcy ŭ prahramnym kodzie. Rekamiendujecca paviedamić ab hetym raspracoŭnikam. -- 8d45620c1a4348dbb17410da57c60c66 Subject: Novaja siesija № @SESSION_ID@ stvorana dlia karystaĺnika @USER_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Novaja siesija z № @SESSION_ID@ stvorana dlia karystaĺnika @USER_ID@. Lidar hetaj siesii pad № @LEADER@. -- 3354939424b4456d9802ca8333ed424a Subject: Siesija № @SESSION_ID@ spyniena Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Siesija № @SESSION_ID@ spyniena. -- fcbefc5da23d428093f97c82a9290f7b Subject: Dastupna novaje pracoŭnaje miesca № @SEAT_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Novaje pracoŭnaje miesca № @SEAT_ID@ naladžana i dastupna dlia vykarystannia. -- e7852bfe46784ed0accde04bc864c2d5 Subject: Pracoŭnaje miesca № @SEAT_ID@ vydaliena Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Pracoŭnaje miesca № @SEAT_ID@ vydaliena i boĺš nie dastupna. -- c7a787079b354eaaa9e77b371893cd27 Subject: Čas zmienieny Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Sistemny hadzinnik zmienieny na @REALTIME@ mikrasiekund ad 1 studzienia 1970. -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: Časavy pojas zmienieny na @TIMEZONE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Sistemny časavy pojas zmienieny na @TIMEZONE@. -- b07a249cd024414a82dd00cd181378ff Subject: Zapusk sistemy zaviaršyŭsia Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Usie sistemnyja servisy, nieabchodnyja dlia zahruzki sistemy, paspiachova zapuscilisia. Majcie na ŭvazie, što heta nie značyć, što mašyna ničoha nie robić. Mahčyma, niekatoryja servisy jašče inicyjalizirujucca. Na zapusk jadra spatrebilasia @KERNEL_USEC@ mikrasiekund. Na zapusk pačatkovaha RAM-dyska spatrebilasia @INITRD_USEC@ mikrasiekund. Na zapusk sistemnych servisaŭ spatrebilasia @USERSPACE_USEC@ mikrasiekund. -- 6bbd95ee977941e497c48be27c254128 Subject: Sistema pierajšla ŭ stan snu @SLEEP@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Ciapier sistema pierajšla u stan snu @SLEEP@. -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: Sistema vyjšla sa stana snu @SLEEP@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Ciapier sistema vyjšla sa stana snu @SLEEP@. -- 98268866d1d54a499c4e98921d93bc40 Subject: Sistema zaviaršaje rabotu Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Pačaŭsia praces vykliučennia sistemy. Spyniajucca ŭsie sistemnyja servisy i demantujucca fajlavyja sistemy. -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: Junit @UNIT@ zapuskajecca Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Pačaŭsia praces zapusku junita @UNIT@. -- 39f53479d3a045ac8e11786248231fbf Subject: Junit @UNIT@ zapusciŭsia Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Praces zapusku junita @UNIT@ zavieršany. Vynik: @RESULT@. -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: Junit @UNIT@ spyniajecca Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Pačaŭsia praces spyniennia junita @UNIT@. -- 9d1aaa27d60140bd96365438aad20286 Subject: Junit @UNIT@ spynieny Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Praces spyniennia junita @UNIT@ zavieršany. -- be02cf6855d2428ba40df7e9d022f03d Subject: Zboj junita @UNIT@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Zboj junita @UNIT@. Vynik: @RESULT@. -- d34d037fff1847e6ae669a370e694725 Subject: Junit @UNIT@ pieračytvaje svaju kanfihuracyju Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Junit @UNIT@ pačaŭ pieračytvać svaju kanfihuracyju. -- 7b05ebc668384222baa8881179cfda54 Subject: Junit @UNIT@ pieračytaŭ svaju kanfihuracyju Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Junit @UNIT@ pieračytaŭ svaju kanfihuracyju. Vynik: @RESULT@. -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: Praces @EXECUTABLE@ nie moža być vykanany Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Praces @EXECUTABLE@ nie moža być vykanany ŭ vyniku zboju. Jon viarnuŭ pamylku numar @ERRNO@. -- 0027229ca0644181a76c4e92458afa2e Sibject: Adno ci boĺš paviedamlienniaŭ nie byli nakiravany ŭ syslog Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Adno ci boĺš paviedamlienniaŭ nie byli nakiravany ŭ syslog servis, jaki vykonvajecca paralieĺna z journald. Zvyčajna heta značyć, što realizacyja syslog nie paspiavaje apracavać paviedamlienni z nieabchodnaj chutkasciu. -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: Kropka mantavannia nie pustaja Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Kataloh @WHERE@ ukazany jak kropka mantavannia (druhoje polie ŭ /etc/fstab ci Where= polie ŭ fajlie junita systemd) i nie pusty. Heta nie pieraškadžaje mantavanniu, alie isnujučyja ŭ im fajly buduć niedastupny. Dlia dostupu da ich, kali laska, zmantujcie hetuju fajlavuju sistemu ŭ inšaje miesca. -- 24d8d4452573402496068381a6312df2 Subject: Virtuaĺnaja mašyna abo kantejnier zapusciŭsia Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Virtuaĺnaja mašyna @NAME@ z lidaram № @LEADER@ zapuscilasia i hatova dlia vykarystannia. -- 58432bd3bace477cb514b56381b8a758 Subject: Virtuaĺnaja mašyna abo kantejnier spynieny Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Virtuaĺnaja mašyna @NAME@ z lidaram № @LEADER@ spyniena. systemd-229/catalog/systemd.catalog000066400000000000000000000300601265713322000175160ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2012 Lennart Poettering # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Message catalog for systemd's own messages # The catalog format is documented on # http://www.freedesktop.org/wiki/Software/systemd/catalog # For an explanation why we do all this, see https://xkcd.com/1024/ -- f77379a8490b408bbe5f6940505a777b Subject: The journal has been started Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel The system journal process has started up, opened the journal files for writing and is now ready to process requests. -- d93fb3c9c24d451a97cea615ce59c00b Subject: The journal has been stopped Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel The system journal process has shut down and closed all currently active journal files. -- ec387f577b844b8fa948f33cad9a75e6 Subject: Disk space used by the journal Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @JOURNAL_NAME@ (@JOURNAL_PATH@) is currently using @CURRENT_USE_PRETTY@. Maximum allowed usage is set to @MAX_USE_PRETTY@. Leaving at least @DISK_KEEP_FREE_PRETTY@ free (of currently available @DISK_AVAILABLE_PRETTY@ of disk space). Enforced usage limit is thus @LIMIT_PRETTY@, of which @AVAILABLE_PRETTY@ are still available. The limits controlling how much disk space is used by the journal may be configured with SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=, RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= settings in /etc/systemd/journald.conf. See journald.conf(5) for details. -- a596d6fe7bfa4994828e72309e95d61e Subject: Messages from a service have been suppressed Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) A service has logged too many messages within a time period. Messages from the service have been dropped. Note that only messages from the service in question have been dropped, other services' messages are unaffected. The limits controlling when messages are dropped may be configured with RateLimitInterval= and RateLimitBurst= in /etc/systemd/journald.conf. See journald.conf(5) for details. -- e9bf28e6e834481bb6f48f548ad13606 Subject: Journal messages have been missed Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Kernel messages have been lost as the journal system has been unable to process them quickly enough. -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: Process @COREDUMP_PID@ (@COREDUMP_COMM@) dumped core Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) Process @COREDUMP_PID@ (@COREDUMP_COMM@) crashed and dumped core. This usually indicates a programming error in the crashing program and should be reported to its vendor as a bug. -- fc2e22bc6ee647b6b90729ab34a250b1 de Subject: Speicherabbild für Prozess @COREDUMP_PID@ (@COREDUMP_COMM) generiert Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) Prozess @COREDUMP_PID@ (@COREDUMP_COMM@) ist abgebrochen worden und ein Speicherabbild wurde generiert. Üblicherweise ist dies ein Hinweis auf einen Programmfehler und sollte als Fehler dem jeweiligen Hersteller gemeldet werden. -- 8d45620c1a4348dbb17410da57c60c66 Subject: A new session @SESSION_ID@ has been created for user @USER_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat A new session with the ID @SESSION_ID@ has been created for the user @USER_ID@. The leading process of the session is @LEADER@. -- 3354939424b4456d9802ca8333ed424a Subject: Session @SESSION_ID@ has been terminated Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat A session with the ID @SESSION_ID@ has been terminated. -- fcbefc5da23d428093f97c82a9290f7b Subject: A new seat @SEAT_ID@ is now available Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat A new seat @SEAT_ID@ has been configured and is now available. -- e7852bfe46784ed0accde04bc864c2d5 Subject: Seat @SEAT_ID@ has now been removed Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat A seat @SEAT_ID@ has been removed and is no longer available. -- c7a787079b354eaaa9e77b371893cd27 Subject: Time change Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel The system clock has been changed to @REALTIME@ microseconds after January 1st, 1970. -- c7a787079b354eaaa9e77b371893cd27 de Subject: Zeitänderung Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Die System-Zeit wurde geändert auf @REALTIME@ Mikrosekunden nach dem 1. Januar 1970. -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: Time zone change to @TIMEZONE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel The system timezone has been changed to @TIMEZONE@. -- b07a249cd024414a82dd00cd181378ff Subject: System start-up is now complete Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel All system services necessary queued for starting at boot have been successfully started. Note that this does not mean that the machine is now idle as services might still be busy with completing start-up. Kernel start-up required @KERNEL_USEC@ microseconds. Initial RAM disk start-up required @INITRD_USEC@ microseconds. Userspace start-up required @USERSPACE_USEC@ microseconds. -- 6bbd95ee977941e497c48be27c254128 Subject: System sleep state @SLEEP@ entered Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel The system has now entered the @SLEEP@ sleep state. -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: System sleep state @SLEEP@ left Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel The system has now left the @SLEEP@ sleep state. -- 98268866d1d54a499c4e98921d93bc40 Subject: System shutdown initiated Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Systemd shutdown has been initiated. The shutdown has now begun and all system services are terminated and all file systems unmounted. -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: Unit @UNIT@ has begun start-up Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Unit @UNIT@ has begun starting up. -- 39f53479d3a045ac8e11786248231fbf Subject: Unit @UNIT@ has finished start-up Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Unit @UNIT@ has finished starting up. The start-up result is @RESULT@. -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: Unit @UNIT@ has begun shutting down Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Unit @UNIT@ has begun shutting down. -- 9d1aaa27d60140bd96365438aad20286 Subject: Unit @UNIT@ has finished shutting down Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Unit @UNIT@ has finished shutting down. -- be02cf6855d2428ba40df7e9d022f03d Subject: Unit @UNIT@ has failed Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Unit @UNIT@ has failed. The result is @RESULT@. -- d34d037fff1847e6ae669a370e694725 Subject: Unit @UNIT@ has begun reloading its configuration Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Unit @UNIT@ has begun reloading its configuration -- 7b05ebc668384222baa8881179cfda54 Subject: Unit @UNIT@ has finished reloading its configuration Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Unit @UNIT@ has finished reloading its configuration The result is @RESULT@. -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: Process @EXECUTABLE@ could not be executed Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel The process @EXECUTABLE@ could not be executed and failed. The error number returned by this process is @ERRNO@. -- 0027229ca0644181a76c4e92458afa2e Subject: One or more messages could not be forwarded to syslog Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel One or more messages could not be forwarded to the syslog service running side-by-side with journald. This usually indicates that the syslog implementation has not been able to keep up with the speed of messages queued. -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: Mount point is not empty Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel The directory @WHERE@ is specified as the mount point (second field in /etc/fstab or Where= field in systemd unit file) and is not empty. This does not interfere with mounting, but the pre-exisiting files in this directory become inaccessible. To see those over-mounted files, please manually mount the underlying file system to a secondary location. -- 24d8d4452573402496068381a6312df2 Subject: A virtual machine or container has been started Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel The virtual machine @NAME@ with its leader PID @LEADER@ has been started is now ready to use. -- 58432bd3bace477cb514b56381b8a758 Subject: A virtual machine or container has been terminated Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel The virtual machine @NAME@ with its leader PID @LEADER@ has been shut down. -- 36db2dfa5a9045e1bd4af5f93e1cf057 Subject: DNSSEC mode has been turned off, as server doesn't support it Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:systemd-resolved.service(8) resolved.conf(5) The resolver service (systemd-resolved.service) has detected that the configured DNS server does not support DNSSEC, and DNSSEC validation has been turned off as result. This event will take place if DNSSEC=allow-downgrade is configured in resolved.conf and the configured DNS server is incompatible with DNSSEC. Note that using this mode permits DNSSEC downgrade attacks, as an attacker might be able turn off DNSSEC validation on the system by inserting DNS replies in the communication channel that result in a downgrade like this. This event might be indication that the DNS server is indeed incompatible with DNSSEC or that an attacker has successfully managed to stage such a downgrade attack. -- 1675d7f172174098b1108bf8c7dc8f5d Subject: DNSSEC validation failed Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:systemd-resolved.service(8) A DNS query or resource record set failed DNSSEC validation. This is usually indication that the communication channel used was tampered with. -- 4d4408cfd0d144859184d1e65d7c8a65 Subject: A DNSSEC trust anchor has been revoked Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:systemd-resolved.service(8) A DNSSEC trust anchor has been revoked. A new trust anchor has to be configured, or the operating system needs to be updated, to provide an updated DNSSEC trust anchor. systemd-229/catalog/systemd.da.catalog000066400000000000000000000221601265713322000201030ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2012 Lennart Poettering # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Message catalog for systemd's own messages # Danish translation # The catalog format is documented on # http://www.freedesktop.org/wiki/Software/systemd/catalog # For an explanation why we do all this, see https://xkcd.com/1024/ -- f77379a8490b408bbe5f6940505a777b Subject: Journalen er blevet startet Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel System-journal processen har startet op, åbnet journal filerne for tilskrivning og er nu klar til at modtage anmodninger. -- d93fb3c9c24d451a97cea615ce59c00b Subject: Journalen er blevet stoppet Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel System-journal processen er stoppet og har lukket alle aktive journal filer. -- a596d6fe7bfa4994828e72309e95d61e Subject: Beskeder fra en service er blevet undertrykt Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) En service har logget for mange beskeder inden for en given tidsperiode. Beskeder fra omtalte service er blevet smidt væk. Kun beskeder fra omtalte service er smidt væk. Beskeder fra andre services er ikke påvirket. Grænsen for hvornår beskeder bliver smidt væk kan konfigureres med RateLimitInterval= og RateLimitBurst= i /etc/systemd/journald.conf. Se journald.conf(5) for detaljer herom. -- e9bf28e6e834481bb6f48f548ad13606 Subject: Journal beskeder er gået tabt Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Kernel beskeder er gået tabt da journal systemet ikke har været i stand til at håndtere dem hurtigt nok. -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: Fejl-fil genereret for process @COREDUMP_PID@ (@COREDUMP_COMM@) Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) Process @COREDUMP_PID@ (@COREDUMP_COMM@) har lukket ned og genereret en fejl-fil. Dette indikerer som regel en programmeringsfejl i det nedlukkede program og burde blive reporteret som en bug til folkene bag -- 8d45620c1a4348dbb17410da57c60c66 Subject: En ny session @SESSION_ID@ er blevet lavet for bruger @USER_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat En ny session med ID @SESSION_ID@ er blevet lavet for brugeren @USER_ID@. Den ledende process for sessionen er @LEADER@. -- 3354939424b4456d9802ca8333ed424a Subject: Session @SESSION_ID@ er blevet lukket ned Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat En session med ID @SESSION_ID@ er blevet lukket ned. -- fcbefc5da23d428093f97c82a9290f7b Subject: En ny arbejdsstation $SEAT_ID@ er nu tilgængelig Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat En ny arbejdsstation @SEAT_ID@ er blevet konfigureret og er nu tilgængelig. -- e7852bfe46784ed0accde04bc864c2d5 Subject: Arbejdsstation @SEAT_ID@ er nu blevet fjernet Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat En arbejdsstation @SEAT_ID@ er blevet fjernet og er ikke længere tilgængelig. -- c7a787079b354eaaa9e77b371893cd27 Subject: Tidsændring Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Systemtiden er blevet ændret til @REALTIME@ mikrosekunder efter d. 1. Januar 1970. -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: Tidszoneændring til @TIMEZONE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Tidszonen for systemet er blevet ændret til @TIMEZONE@. -- b07a249cd024414a82dd00cd181378ff Subject: Opstart af systemet er nu fuldført Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Alle system services i kø til at køre ved opstart, er blevet startet med success. Bemærk at dette ikke betyder at maskinen er i dvale, da services stadig kan være i gang med at færdiggøre deres opstart. Opstart af kernel tog @KERNEL_USEC@ mikrosekunder. Opstart af initrd tog @INITRD_USEC@ mikrosekunder. Opstart af userspace tog @USERSPACE_USEC@ mikrosekunder. -- 6bbd95ee977941e497c48be27c254128 Subject: System slumretilstand @SLEEP@ trådt i kraft Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel System er nu gået i @SLEEP@ slumretilstand. -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: System slumretilstand @SLEEP@ forladt Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Systemet har nu forladt @SLEEP@ slumretilstand. -- 98268866d1d54a499c4e98921d93bc40 Subject: Systemnedlukning påbegyndt Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Systemnedlukning er blevet påbegyndt. Nedlukningen er nu begyndt og alle system services er blevet afbrudt og alle filsystemer afmonteret. -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: Enhed @UNIT@ har påbegyndt opstart Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Enhed @UNIT@ er begyndt at starte op. -- 39f53479d3a045ac8e11786248231fbf Subject: Enhed @UNIT har færdiggjort opstart Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Enhed @UNIT@ er færdig med at starte op. Resultat for opstart er @RESULT@. -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: Enhed @UNIT@ har påbegyndt nedlukning Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Enhed @UNIT@ har påbegyndt nedlukning. -- 9d1aaa27d60140bd96365438aad20286 Subject: Enhed @UNIT@ har færdiggjort nedlukning Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Enhed @UNIT@ har færdiggjort nedlukning. -- be02cf6855d2428ba40df7e9d022f03d Subject: Enhed @UNIT@ har fejlet Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Enhed @UNIT@ har fejlet. Resultatet er @RESULT@ -- d34d037fff1847e6ae669a370e694725 Subject: Enhed @UNIT@ har påbegyndt genindlæsning af sin konfiguration Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Enhed @UNIT@ er begyndt at genindlæse sin konfiguration -- 7b05ebc668384222baa8881179cfda54 Subject: Enhed @UNIT@ har færdiggjort genindlæsning af sin konfiguration Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Enhed @UNIT@ er færdig med at genindlæse sin konfiguration Resultatet er: @RESULT@. -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: Process @EXECUTABLE@ kunne ikke eksekveres Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Processen @EXECUTABLE@ kunne ikke eksekveres og fejlede. Processens returnerede fejlkode er @ERRNO@. -- 0027229ca0644181a76c4e92458afa2e Subject: Èn eller flere beskeder kunne ikke videresendes til syslog Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Èn eller flere beskeder kunne ikke videresendes til syslog servicen der kører side-om-side med journald. Dette indikerer typisk at syslog implementationen ikke har kunnet følge med mængden af ventende beskeder. -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: Monteringspunkt er ikke tomt Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Folderen @WHERE@ er specificeret som monteringspunkt (andet felt i /etc/fstab eller Where= feltet i systemd enhedsfil) men er ikke tom. Dette forstyrrer ikke monteringen, men de pre-eksisterende filer i folderen bliver utilgængelige. For at se de over-monterede filer; montér det underlæggende filsystem til en anden lokation. -- 24d8d4452573402496068381a6312df2 Subject: En virtuel maskine eller container er blevet startet Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Den virtuelle maskine @NAME@ med dens leder PID @LEADER@ er blevet startet og er klar til brug. -- 58432bd3bace477cb514b56381b8a758 Subject: En virtuel maskine eller container er blevet afbrudt Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Den virtuelle maskine @NAME@ med dens leder PID @LEADER@ er blevet nedlukket. systemd-229/catalog/systemd.fr.catalog000066400000000000000000000236511265713322000201340ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2012 Lennart Poettering # Copyright 2013-2015 Sylvain Plantefève # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Message catalog for systemd's own messages # French translation # Le format du catalogue de messages est décrit (en anglais) içi : # http://www.freedesktop.org/wiki/Software/systemd/catalog -- f77379a8490b408bbe5f6940505a777b Subject: Le journal a été démarré Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Le processus du journal système a démarré, ouvert ses fichiers en écriture et est prêt à traiter les requêtes. -- d93fb3c9c24d451a97cea615ce59c00b Subject: Le journal a été arrêté Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Le processus du journal système a été arrêté et tous ses fichiers actifs ont été fermés. -- a596d6fe7bfa4994828e72309e95d61e Subject: Des messages d'un service ont été supprimés Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) Un service a essayé d'enregistrer un trop grand nombre de messages sur un intervalle de temps donné. Des messages de ce service ont été évincés. Notez que seuls des messages de ce service ont été évincés, les messages des autres services ne sont pas affectés. Les limites définissant ce comportement peuvent être configurées avec les paramètres RateLimitInterval= et RateLimitBurst= dans le fichier /etc/systemd/journald.conf. Voir journald.conf(5) pour plus de détails. -- e9bf28e6e834481bb6f48f548ad13606 Subject: Des messages du journal ont été manqués Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Des messages du noyau ont été manqués car le journal système n'a pas été capable de les traiter suffisamment vite. -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: Le processus @COREDUMP_PID@ (@COREDUMP_COMM@) a généré un fichier « core » Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) Le processus @COREDUMP_PID@ (@COREDUMP_COMM@) a planté et généré un fichier « core ». Cela indique généralement une erreur de programmation dans le programme incriminé, et cela devrait être notifié à son concepteur comme un défaut (bug). -- 8d45620c1a4348dbb17410da57c60c66 Subject: Une nouvelle session @SESSION_ID@ a été créée pour l'utilisateur @USER_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Une nouvelle session a été créée pour l'utilisateur @USER_ID@ avec l'identifiant (ID) @SESSION_ID@. Le processus maître de la session est @LEADER@. -- 3354939424b4456d9802ca8333ed424a Subject: La session @SESSION_ID@ s'est terminée Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat La session d'identifiant (ID) @SESSION_ID@ s'est terminée. -- fcbefc5da23d428093f97c82a9290f7b Subject: Un nouveau poste (seat) @SEAT_ID@ est disponible Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Un nouveau poste (seat) @SEAT_ID@ a été configuré et est maintenant disponible. -- e7852bfe46784ed0accde04bc864c2d5 Subject: Le poste (seat) @SEAT_ID@ a été retiré Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Le poste (seat) @SEAT_ID@ a été retiré et n'est plus disponible. -- c7a787079b354eaaa9e77b371893cd27 Subject: Changement d'heure Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'horloge système a été modifiée et positionnée à @REALTIME@ microsecondes après le 1er janvier 1970. -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: Fuseau horaire modifié en @TIMEZONE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Le fuseau horaire du système a été modifié et positionné à @TIMEZONE@. -- b07a249cd024414a82dd00cd181378ff Subject: Le démarrage du système est terminé Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Tous les services nécessaires au démarrage du système ont été lancés avec succès. Notez que cela ne signifie pas que le système est maintenant au repos, car des services peuvent encore être en train de terminer leur démarrage. Le chargement du noyau a nécessité @KERNEL_USEC@ microsecondes. Le chargement du « RAM disk » initial a nécessité @INITRD_USEC@ microsecondes. Le chargement de l'espace utilisateur a nécessité @USERSPACE_USEC@ microsecondes. -- 6bbd95ee977941e497c48be27c254128 Subject: Le système entre dans l'état de repos (sleep state) @SLEEP@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Le système est maintenant à l'état de repos (sleep state) @SLEEP@. -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: Le système sorti de l'état de repos (sleep state) @SLEEP@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Le système est maintenant sorti de l'état de repos (sleep state) @SLEEP@. -- 98268866d1d54a499c4e98921d93bc40 Subject: Arrêt du système amorcé Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'arrêt du système a été amorcé. L'arrêt a maintenant commencé, tous les services du système sont terminés et tous les systèmes de fichiers sont démontés. -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: L'unité (unit) @UNIT@ a commencé à démarrer Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unité (unit) @UNIT@ a commencé à démarrer. -- 39f53479d3a045ac8e11786248231fbf Subject: L'unité (unit) @UNIT@ a terminé son démarrage Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unité (unit) @UNIT@ a terminé son démarrage, avec le résultat @RESULT@. -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: L'unité (unit) @UNIT@ a commencé à s'arrêter Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unité (unit) @UNIT@ a commencé à s'arrêter. -- 9d1aaa27d60140bd96365438aad20286 Subject: L'unité (unit) @UNIT@ a terminé son arrêt Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unité (unit) @UNIT@ a terminé son arrêt. -- be02cf6855d2428ba40df7e9d022f03d Subject: L'unité (unit) @UNIT@ a échoué Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unité (unit) @UNIT@ a échoué, avec le résultat @RESULT@. -- d34d037fff1847e6ae669a370e694725 Subject: L'unité (unit) @UNIT@ a commencé à recharger sa configuration Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unité (unit) @UNIT@ a commencé à recharger sa configuration. -- 7b05ebc668384222baa8881179cfda54 Subject: L'unité (unit) @UNIT@ a terminé de recharger configuration Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unité (unit) @UNIT@ a terminé de recharger configuration, avec le résultat @RESULT@. -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: Le processus @EXECUTABLE@ n'a pas pu être exécuté Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Le processus @EXECUTABLE@ n'a pas pu être exécuté, et a donc échoué. Le code d'erreur renvoyé est @ERRNO@. -- 0027229ca0644181a76c4e92458afa2e Subject: Un ou plusieurs messages n'ont pas pu être transmis à syslog Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Un ou plusieurs messages n'ont pas pu être transmis au service syslog s'exécutant conjointement avec journald. Cela indique généralement que l'implémentation de syslog utilisée n'a pas été capable de suivre la cadence du flux de messages. -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: Le point de montage n'est pas vide Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Le répertoire @WHERE@ est spécifié comme point de montage (second champ du fichier /etc/fstab, ou champ Where= dans une unité (unit) systemd) et n'est pas vide. Cela ne perturbe pas le montage du système de fichiers, mais les fichiers préalablement présents dans ce répertoire sont devenus inaccessibles. Pour atteindre ces fichiers, veuillez monter manuellement le système de fichiers sous-jacent à un autre emplacement. -- 24d8d4452573402496068381a6312df2 Subject: Une machine virtuelle ou un conteneur (container) a été démarré Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel La machine virtuelle @NAME@ a été démarrée avec le PID maître @LEADER@, et est maintenant prête à l'emploi. -- 58432bd3bace477cb514b56381b8a758 Subject: Une machine virtuelle ou un conteneur (container) a été arrêté Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel La machine virtuelle @NAME@ avec le PID maître @LEADER@ a été arrêtée. systemd-229/catalog/systemd.hu.catalog000066400000000000000000000230021265713322000201270ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2012 Lennart Poettering # Copyright 2016 Gabor Kelemen # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Message catalog for systemd's own messages # The catalog format is documented on # http://www.freedesktop.org/wiki/Software/systemd/catalog # For an explanation why we do all this, see https://xkcd.com/1024/ -- f77379a8490b408bbe5f6940505a777b Subject: A napló elindult Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A rendszernapló folyamat elindult, megnyitotta írásra a naplófájlokat, és most készen áll kérések feldolgozására. -- d93fb3c9c24d451a97cea615ce59c00b Subject: A napló leállt Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A rendszernapló folyamat leállt, és bezárt minden jelenleg aktív naplófájlt. -- a596d6fe7bfa4994828e72309e95d61e Subject: Egy szolgáltatás üzenetei elnémítva Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) Egy szolgáltatás túl sok üzenetet naplózott adott idő alatt. A szolgáltatástól származó üzenetek eldobásra kerültek. Ne feledje, hogy csak a kérdéses szolgáltatás üzenetei kerültek eldobásra, más szolgáltatások üzeneteit ez nem befolyásolja. Az üzenetek eldobását vezérlő korlátok az /etc/systemd/journald.conf RateLimitInterval= és RateLimitBurst= beállításaival adhatók meg. Részletekért lásd a journald.conf(5) man oldalt. -- e9bf28e6e834481bb6f48f548ad13606 Subject: Naplóüzenetek vesztek el Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Kernelüzenetek vesztek el, mert a naplózó rendszer nem tudta elég gyorsan feldolgozni azokat. -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: Egy folyamat összeomlott: @COREDUMP_PID@ (@COREDUMP_COMM@) Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) Ez a folyamat: @COREDUMP_PID@ (@COREDUMP_COMM@) összeomlott, és core fájlt írt ki. Ez általában programozási hibát jelez az összeomló programban, és a szállítója felé kell bejelenteni. -- 8d45620c1a4348dbb17410da57c60c66 Subject: Új munkamenet (@SESSION_ID@) létrehozva, felhasználója: @USER_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Létrejött egy új munkamenet @SESSION_ID@ azonosítóval ezen felhasználóhoz: @USER_ID@. A munkamenet vezető folyamata: @LEADER@. -- 3354939424b4456d9802ca8333ed424a Subject: Munkamenet (@SESSION_ID@) befejezve Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat A következő azonosítójú munkamenet befejeződött: @SESSION_ID@. -- fcbefc5da23d428093f97c82a9290f7b Subject: Elérhető egy új munkaállomás: @SEAT_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Beállításra kerül és használható egy új munkaállomás: @SEAT_ID@. -- e7852bfe46784ed0accde04bc864c2d5 Subject: A munkaállomás eltávolítva: @SEAT_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat A munkaállomás el lett távolítva, és már nem érhető el: @SEAT_ID@ -- c7a787079b354eaaa9e77b371893cd27 Subject: Időmódosítás Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A rendszeróra beállítva @REALTIME@ ezredmásodpercre 1970. január 1. után. -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: Időzóna-módosítás erre: @TIMEZONE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A rendszer időzónája módosítva lett erre: @TIMEZONE@. -- b07a249cd024414a82dd00cd181378ff Subject: A rendszer indítása kész Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A rendszerindításkor szükséges indításhoz sorba állított összes rendszerszolgáltatás elindult. Ne feledje, hogy ez nem jelenti, hogy a gép üresjáratban van, mivel egyes szolgáltatások még az indítás befejezésével lehetnek elfoglalva. A kernel indítása @KERNEL_USEC@ ezredmásodpercet igényelt. A kiinduló RAM lemez indítása @INITRD_USEC@ ezredmásodpercet igényelt. A felhasználói programok indítása @USERSPACE_USEC@ ezredmásodpercet igényelt. -- 6bbd95ee977941e497c48be27c254128 Subject: A rendszer „@SLEEP@” alvási állapotba lépett Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A rendszer belépett ebbe az alvási állapotba: @SLEEP@. -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: A rendszer „@SLEEP@” alvási állapotból kilépett Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A rendszer kilépett ebből az alvási állapotból: @SLEEP@. -- 98268866d1d54a499c4e98921d93bc40 Subject: Rendszer leállítása kezdeményezve Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A systemd leállítása kezdeményezve. A leállítás megkezdődött, minden rendszerszolgáltatás befejeződik, minden fájlrendszer leválasztásra kerül. -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: A(z) @UNIT@ egység indítása megkezdődött Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A(z) @UNIT@ egység megkezdte az indulást. -- 39f53479d3a045ac8e11786248231fbf Subject: A(z) @UNIT@ egység befejezte az indulást Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A(z) @UNIT@ egység befejezte az indulást Az indítás eredménye: @RESULT@. -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: A(z) @UNIT@ egység megkezdte a leállást Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A(z) @UNIT@ egység megkezdte a leállást. -- 9d1aaa27d60140bd96365438aad20286 Subject: A(z) @UNIT@ egység befejezte a leállást Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A(z) @UNIT@ egység befejezte a leállást. -- be02cf6855d2428ba40df7e9d022f03d Subject: A(z) @UNIT@ egység hibát jelzett Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A(z) @UNIT@ egység hibát jelzett. Az eredmény: @RESULT@. -- d34d037fff1847e6ae669a370e694725 Subject: A(z) @UNIT@ egység megkezdte a beállításainak újratöltését Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A(z) @UNIT@ egység megkezdte a beállításainak újratöltését. -- 7b05ebc668384222baa8881179cfda54 Subject: A(z) @UNIT@ egység befejezte a beállításainak újratöltését Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A(z) @UNIT@ egység befejezte a beállításainak újratöltését. Az eredmény: @RESULT@. -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: A folyamat végrehajtása sikertelen: @EXECUTABLE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A folyamat végrehajtása sikertelen volt, és hibát jelzett: @EXECUTABLE@. A folyamat által visszaadott hibaszám: @ERRNO@. -- 0027229ca0644181a76c4e92458afa2e Subject: Legalább egy üzenet nem továbbítható a rendszernaplónak Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Legalább egy üzenet nem volt továbbítható a journald-vel párhuzamosan futó syslog szolgáltatásnak. Ez általában azt jelenti, hogy a syslog megvalósítás nem volt képes lépést tartani a sorba állított üzenetek sebességével. -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: A csatolási pont nem üres Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A csatolási pontként megadott @WHERE@ könyvtár (második mező az /etc/fstab fájlban, vagy a Where= sor a systemd egységfájlban) nem üres. Ez nem akadályozza meg a csatolást, de a könyvtárban már meglévő fájlok elérhetetlenné válnak. A fájlok láthatóvá tételéhez csatolja az azokat tartalmazó fájlrendszert egy másodlagos helyre. -- 24d8d4452573402496068381a6312df2 Subject: Egy virtuális gép vagy konténer elindult Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A(z) @NAME@ nevű virtuális gép (vezető PID: @LEADER@) elindult, és használatra kész. -- 58432bd3bace477cb514b56381b8a758 Subject: Egy virtuális gép vagy konténer befejeződött Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A(z) @NAME@ nevű virtuális gép (vezető PID: @LEADER@) leállt. systemd-229/catalog/systemd.it.catalog000066400000000000000000000222321265713322000201330ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2013 Daniele Medri # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Message catalog for systemd's own messages -- f77379a8490b408bbe5f6940505a777b Subject: Il registro è stato avviato Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Il processo relativo al registro di sistema è stato avviato, ha aperto i file in scrittura ed è ora pronto a gestire richieste. -- d93fb3c9c24d451a97cea615ce59c00b Subject: Il registro è stato terminato Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Il processo relativo al registro di sistema è stato terminato e ha chiuso tutti i file attivi. -- a596d6fe7bfa4994828e72309e95d61e Subject: I messaggi di un servizio sono stati soppressi Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) Un servizio ha registrato troppi messaggi in un dato periodo di tempo. I messaggi del servizio sono stati eliminati. Solo i messaggi del servizio indicato sono stati eliminati, i messaggi degli altri servizi rimangono invariati. I limiti oltre i quali i messaggi si eliminano si configurano con RateLimitInterval= e RateLimitBurst= in /etc/systemd/journald.conf. Vedi journald.conf(5) per maggiori informazioni. -- e9bf28e6e834481bb6f48f548ad13606 Subject: I messaggi di un servizio sono stati perduti Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel I messaggi del kernel sono stati perduti perché, il registro di sistema non è stato in grado di gestirli abbastanza velocemente. -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: Il processo @COREDUMP_PID@ (@COREDUMP_COMM@) ha generato un dump. Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) Il processo @COREDUMP_PID@ (@COREDUMP_COMM@) si è bloccato generando un dump. Questo di solito capita per un errore di programmazione nell'applicazione e dovrebbe essere segnalato al vendor come un bug. -- 8d45620c1a4348dbb17410da57c60c66 Subject: La nuova sessione @SESSION_ID@ è stata creata per l'utente @USER_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Una nuova sessione con ID @SESSION_ID@ è stata creata per l'utente @USER_ID@. Il processo primario della sessione è @LEADER@. -- 3354939424b4456d9802ca8333ed424a Subject: La sessione @SESSION_ID@ è terminata Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat La sessione con ID @SESSION_ID@ è terminata. -- fcbefc5da23d428093f97c82a9290f7b Subject: La nuova postazione @SEAT_ID@ è ora disponibile Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat La nuova postazione @SEAT_ID@ è stata configurata ed è ora disponibile. -- e7852bfe46784ed0accde04bc864c2d5 Subject: La postazione @SEAT_ID@ è stata rimossa Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat La postazione @SEAT_ID@ è stata rimossa e non è più disponibile. -- c7a787079b354eaaa9e77b371893cd27 Subject: Cambio d'orario Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'orologio di sistema è cambiato in @REALTIME@ microsecondi dal 1 gennaio, 1970. -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: Il fuso orario è cambiato in @TIMEZONE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Il fuso orario di sistema è cambiato in @TIMEZONE@. -- b07a249cd024414a82dd00cd181378ff Subject: Avvio del sistema completato. Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Tutti i servizi di sistema richiesti per la fase di avvio sono stati eseguiti con successo. Nota che la macchina potrebbe non essere ancora pronta in quanto i servizi attivati sono in fase di completamento. L'avvio del kernel ha richiesto @KERNEL_USEC@ microsecondi. L'avvio del disco RAM ha richiesto @INITRD_USEC@ microsecondi. L'avvio dello userspace ha richiesto @USERSPACE_USEC@ microsecondi. -- 6bbd95ee977941e497c48be27c254128 Subject: Il sistema è entrato in fase di pausa @SLEEP@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Il sistema è entrato nello stato di pausa @SLEEP@. -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: Il sistema è uscito dalla fase di pausa @SLEEP@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Il sistema è uscito dallo stato di pausa @SLEEP@. -- 98268866d1d54a499c4e98921d93bc40 Subject: Il sistema è in fase di spegnimento Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Systemd è in fase di spegnimento. Tutti i servizi di sistema saranno terminati e tutti i file systems smontati. -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: L'unità @UNIT@ inizia la fase di avvio Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unità @UNIT@ ha iniziato la fase di avvio. -- 39f53479d3a045ac8e11786248231fbf Subject: L'unità @UNIT@ termina la fase di avvio Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unità @UNIT@ ha terminato la fase di avvio. La fase di avvio è @RESULT@. -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: L'unità @UNIT@ inizia la fase di spegnimento Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unità @UNIT@ ha iniziato la fase di spegnimento. -- 9d1aaa27d60140bd96365438aad20286 Subject: L'unità @UNIT@ termina la fase di spegnimento Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unità @UNIT@ ha terminato la fase di spegnimento. -- be02cf6855d2428ba40df7e9d022f03d Subject: L'unità @UNIT@ è fallita Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unità @UNIT@ è fallita. Il risultato è @RESULT@. -- d34d037fff1847e6ae669a370e694725 Subject: L'unità @UNIT@ inizia a caricare la propria configurazione Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unità @UNIT@ è iniziata ricaricando la propria configurazione -- 7b05ebc668384222baa8881179cfda54 Subject: L'unità @UNIT@ termina il caricamento della propria configurazione Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel L'unità @UNIT@ è terminata ricaricando la propria configurazione Il risultato è @RESULT@. -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: Il processo @EXECUTABLE@ non può essere eseguito Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Il processo @EXECUTABLE@ non può essere eseguito e termina. Il numero di errore restituito durante l'esecuzione del processo è @ERRNO@. -- 0027229ca0644181a76c4e92458afa2e Subject: Uno o più messaggi non possono essere inoltrati a syslog Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Uno o più messaggi non possono essere inviati al servizio syslog eseguito in parallelo a journald. Questo di solito capita perché, l'implementazione di syslog non sta al passo con la velocità dei messaggi accodati. -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: Il punto di montaggio non è vuoto Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel La directory @WHERE@ è specificata come punto di montaggio (secondo campo in /etc/fstab o nel campo Where= del file unità di systemd) e non è vuoto. Questo non interferisce con il montaggio, ma i file pre-esistenti in questa directory diventano inaccessibili. Per visualizzare i file, si suggerisce di montare manualmente il file system indicato in una posizione secondaria. -- 24d8d4452573402496068381a6312df2 Subject: Avviata macchina virtuale o container Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel La macchina virtuale @NAME@ con PID primario @LEADER@ è stata avviata ed è pronta all'uso. -- 58432bd3bace477cb514b56381b8a758 Subject: Terminata macchina virtuale o container Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel La macchina virtuale @NAME@ con PID primario @LEADER@ è stata spenta. systemd-229/catalog/systemd.ko.catalog000066400000000000000000000231061265713322000201310ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2012 Lennart Poettering # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Message catalog for systemd's own messages # Korean translation # The catalog format is documented on # http://www.freedesktop.org/wiki/Software/systemd/catalog # For an explanation why we do all this, see https://xkcd.com/1024/ # # Translator : # Seong-ho Cho , 2015. -- f77379a8490b408bbe5f6940505a777b Subject: 저널 시작 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 시스템 저널 프로세스를 시작했고 기록목적으로 저널 파일을 열었으며, 프로세스 요청을 기다리고 있습니다. -- d93fb3c9c24d451a97cea615ce59c00b Subject: 저널 멈춤 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 시스템 저널 프로세스를 껐고 현재 활성화 중인 저널 파일을 모두 닫았습니다. -- a596d6fe7bfa4994828e72309e95d61e Subject: 서비스의 메시지를 거절함 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) 일정 시간동안 서비스에서 너무 많은 메시지를 기록했습니다. 서비스에서 오는 메시지를 거절했습니다. 의문점이 있는 서비스로부터 오는 메시지만 거절했음을 참고하십시오 다른 서비스의 메시지에는 영향을 주지 않습니다. 메시지 거절 제어 제한 값은 /etc/systemd/journald.conf 의 RateLimitInterval= 변수와 RateLimitBurst= 변수로 설정합니다. 자세한 내용은 ournald.conf(5)를 살펴보십시오. -- e9bf28e6e834481bb6f48f548ad13606 Subject: 저널 메시지 놓침 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 저널 시스템에서 커널 메시지를 충분히 빠르게 처리할 수 없어 커널 메시지를 잃었습니다. -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: 프로세스 @COREDUMP_PID@번 코어 덤프(@COREDUMP_COMM@) 생성함 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) 프로세스 @COREDUMP_PID@번 (@COREDUMP_COMM@)이 비정상적으로 끝나 코어 덤프를 생성했습니다. 보통 비정상 종료 관리 프로그램에서 프로그래밍 오류를 나타내며, 제작자에게 버그로 보고해야합니다. -- 8d45620c1a4348dbb17410da57c60c66 Subject: @USER_ID@ 사용자의 새 @SESSION_ID@ 세션 만듦 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat @USER_ID@ 사용자의 새 @SESSION_ID@ 세션을 만들었습니다. 이 세션의 관리 프로세스는 @LEADER@ 입니다. -- 3354939424b4456d9802ca8333ed424a Subject: @SESSION_ID@ 세션 마침 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat @SESSION_ID@ 세션을 끝냈습니다. -- fcbefc5da23d428093f97c82a9290f7b Subject: 새 @SEAT_ID@ 시트 사용할 수 있음 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat 새 @SEAT_ID@ 시트를 설정했고 사용할 수 있습니다. -- e7852bfe46784ed0accde04bc864c2d5 Subject: @SEAT_ID@ 시트 제거함 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat @SEAT_ID@ 시트를 제거했으며 더이상 사용할 수 없습니다. -- c7a787079b354eaaa9e77b371893cd27 Subject: 시간 바꿈 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 시스템 시계를 1970년 1월 1일 이후로 @REALTIME@ 마이크로초 지난 값으로 설정했습니다. -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: @TIMEZONE@ 시간대로 시간대 바꿈 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 시스템 시간대를 @TIMEZONE@ 시간대로 바꾸었습니다. -- b07a249cd024414a82dd00cd181378ff Subject: 시스템 시동 마침 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 부팅 과정에 시작하려고 준비한 모든 시스템 서비스를 성공적으로 시작했습니다. 머신이 서비스처럼 대기중이라는 의미는 아니며 지동을 완전히 마칠 때까지 사용중일 수도 있는 점 참고하십시오. 커널 시동에 @KERNEL_USEC@ 마이크로초가 걸립니다. 초기 램 디스크 시동에 @INITRD_USEC@ 마이크로초가 걸립니다. 사용자 영역 시동에 @USERSPACE_USEC@ 마이크로초가 걸립니다. -- 6bbd95ee977941e497c48be27c254128 Subject: @SLEEP@ 대기 상태 진입 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @SLEEP@ 대기 상태로 진입했습니다. -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: @SLEEP@ 대기 상태 마침 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @SLEEP@ 대기 상태를 마쳤습니다. -- 98268866d1d54a499c4e98921d93bc40 Subject: 컴퓨터 끄기 시작 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 컴퓨터 끄기 동작을 시작했습니다. 모든 시스템 동작을 멈추고 모든 파일 시스템의 마운트를 해제합니다. -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: @UNIT@ 유닛 시작 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 유닛을 시작했습니다. -- 39f53479d3a045ac8e11786248231fbf Subject: @UNIT@ 유닛 시동 마침 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 유닛 시동을 마쳤습니다. 시동 결과는 @RESULT@ 입니다. -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: @UNIT@ 유닛 끝내기 동작 시작 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 유닛 끝내기 동작을 시작했습니다. -- 9d1aaa27d60140bd96365438aad20286 Subject: @UNIT@ 유닛 끝내기 동작 마침 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 유닛 끝내기 동작을 마쳤습니다. -- be02cf6855d2428ba40df7e9d022f03d Subject: @UNIT@ 유닛 동작 실패 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 유닛 동작에 실패했습니다. 결과는 @RESULT@ 입니다. -- d34d037fff1847e6ae669a370e694725 Subject: @UNIT@ 유닛 설정 다시 읽기 시작 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 유닛의 설정 다시 읽기를 시작했습니다 -- 7b05ebc668384222baa8881179cfda54 Subject: @UNIT@ 유닛 설정 다시 읽기 완료 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 유닛의 설정 다시 읽기 동작을 끝냈습니다. 결과는 @RESULT@ 입니다. -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: @EXECUTABLE@ 프로세스 시작할 수 없음 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @EXECUTABLE@ 프로세스를 시작할 수 없어 실행에 실패했습니다. 이 프로세스에서 반환한 오류 번호는 @ERRNO@번 입니다. -- 0027229ca0644181a76c4e92458afa2e Subject: 하나 이상의 메시지를 syslog에 전달할 수 없음 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel journald 서비스와 동시에 실행중인 syslog 서비스에 하나 이상의 메시지를 전달할 수 없습니다. 보통 순차적으로 오는 메시지의 속도를 syslog 구현체가 따라가지 못함을 의미합니다. -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: 마운트 지점 비어있지 않음 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @WHERE@ 디렉터리를 마운트 지점으로 지정했으며 (/etc/fstab 파일의 두번째 필드 또는 systemd 유닛 파일의 Where= 필드) 비어있지 않습니다. 마운트 과정에 방해가 되진 않지만 이전에 이 디렉터리에 존재하는 파일에 접근할 수 없게 됩니다. 중복으로 마운트한 파일을 보려면, 근본 파일 시스템의 다음 위치에 직접 마운트하십시오. -- 24d8d4452573402496068381a6312df2 Subject: 가상 머신 또는 컨테이너 시작 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @LEADER@ 프로세스 ID로 동작하는 @NAME@ 가상 머신을 시작했으며, 이제부터 사용할 수 있습니다. -- 58432bd3bace477cb514b56381b8a758 Subject: 가상 머신 또는 컨테이너 마침 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @LEADER@ 프로세스 ID로 동작하는 @NAME@ 가상 머신을 껐습니다. systemd-229/catalog/systemd.pl.catalog000066400000000000000000000224531265713322000201370ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2012 Lennart Poettering # Copyright 2014, 2015 Piotr Drąg # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Message catalog for systemd's own messages # Polish translation # The catalog format is documented on # http://www.freedesktop.org/wiki/Software/systemd/catalog # For an explanation why we do all this, see https://xkcd.com/1024/ -- f77379a8490b408bbe5f6940505a777b Subject: Uruchomiono dziennik Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Systemowy proces dziennika został uruchomiony, otworzył pliki dziennika do zapisu i jest gotowy do przetwarzania żądań. -- d93fb3c9c24d451a97cea615ce59c00b Subject: Zatrzymano dziennik Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Systemowy proces dziennika został wyłączony i zamknął wszystkie obecnie aktywne pliki dziennika. -- a596d6fe7bfa4994828e72309e95d61e Subject: Ograniczono komunikaty z usługi Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) Usługa zapisała za dużo komunikatów w określonym czasie. Komunikaty z usługi zostały pominięte. Proszę zauważyć, że tylko komunikaty z danej usługi zostały pominięte. Nie ma to wpływu na komunikaty innych usług. Ograniczenia kontrolujące pomijanie komunikatów mogą być konfigurowane za pomocą opcji RateLimitInterval= i RateLimitBurst= w pliku /etc/systemd/journald.conf. Strona journald.conf(5) zawiera więcej informacji. -- e9bf28e6e834481bb6f48f548ad13606 Subject: Utracono komunikaty dziennika Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Komunikaty jądra zostały utracone, ponieważ system dziennika nie mógł przetworzyć ich odpowiednio szybko. -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: Proces @COREDUMP_PID@ (@COREDUMP_COMM@) zrzucił plik core Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) Proces @COREDUMP_PID@ (@COREDUMP_COMM@) uległ awarii i zrzucił plik core. Zwykle wskazuje to na błąd programistyczny w danym programie i powinno zostać zgłoszone jego producentowi jako błąd. -- 8d45620c1a4348dbb17410da57c60c66 Subject: Utworzono nową sesję @SESSION_ID@ dla użytkownika @USER_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Nowa sesja o identyfikatorze @SESSION_ID@ została utworzona dla użytkownika @USER_ID@. Proces prowadzący sesji: @LEADER@. -- 3354939424b4456d9802ca8333ed424a Subject: Zakończono sesję @SESSION_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Sesja o identyfikatorze @SESSION_ID@ została zakończona. -- fcbefc5da23d428093f97c82a9290f7b Subject: Dostępne jest nowe stanowisko @SEAT_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Nowe stanowisko @SEAT_ID@ zostało skonfigurowane i jest teraz dostępne. -- e7852bfe46784ed0accde04bc864c2d5 Subject: Usunięto stanowisko @SEAT_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Stanowisko @SEAT_ID@ zostało usunięte i nie jest już dostępne. -- c7a787079b354eaaa9e77b371893cd27 Subject: Zmiana czasu Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Zegar systemowy został zmieniony na @REALTIME@ μs po 1 stycznia 1970. -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: Zmiana strefy czasowej na @TIMEZONE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Systemowa strefa czasowa została zmieniona na @TIMEZONE@. -- b07a249cd024414a82dd00cd181378ff Subject: Ukończono uruchamianie systemu Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Wszystkie usługi systemowe obowiązkowo zakolejkowane do włączenia podczas uruchamiania systemu zostały pomyślnie uruchomione. Proszę zauważyć, że nie oznacza to, że komputer jest bezczynny, jako że usługi mogą wciąż kończyć proces uruchamiania. Uruchamianie jądra zajęło @KERNEL_USEC@ μs. Uruchamianie początkowego dysku RAM zajęło @INITRD_USEC@ μs. Uruchamianie przestrzeni użytkownika zajęło @USERSPACE_USEC@ μs. -- 6bbd95ee977941e497c48be27c254128 Subject: Przejście do stanu uśpienia @SLEEP@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel System przeszedł do stanu uśpienia @SLEEP@. -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: Wyjście ze stanu uśpienia @SLEEP@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel System wyszedł ze stanu uśpienia @SLEEP@. -- 98268866d1d54a499c4e98921d93bc40 Subject: Zainicjowano wyłączenie systemu Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Zainicjowano wyłączenie systemd. Wyłączenie zostało rozpoczęte i wszystkie usługi systemowe zostały zakończone, a wszystkie systemy plików odmontowane. -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: Rozpoczęto uruchamianie jednostki @UNIT@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Jednostka @UNIT@ rozpoczęła uruchamianie. -- 39f53479d3a045ac8e11786248231fbf Subject: Ukończono uruchamianie jednostki @UNIT@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Jednostka @UNIT@ ukończyła uruchamianie. Wynik uruchamiania: @RESULT@. -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: Rozpoczęto wyłączanie jednostki @UNIT@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Jednostka @UNIT@ rozpoczęła wyłączanie. -- 9d1aaa27d60140bd96365438aad20286 Subject: Ukończono wyłączanie jednostki @UNIT@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Jednostka @UNIT@ ukończyła wyłączanie. -- be02cf6855d2428ba40df7e9d022f03d Subject: Jednostka @UNIT@ się nie powiodła Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Jednostka @UNIT@ się nie powiodła. Wynik: @RESULT@. -- d34d037fff1847e6ae669a370e694725 Subject: Rozpoczęto ponowne wczytywanie konfiguracji jednostki @UNIT@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Jednostka @UNIT@ rozpoczęła ponowne wczytywanie swojej konfiguracji. -- 7b05ebc668384222baa8881179cfda54 Subject: Ukończono ponowne wczytywanie konfiguracji jednostki @UNIT@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Jednostka @UNIT@ ukończyła ponowne wczytywanie swojej konfiguracji. Wynik: @RESULT@. -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: Nie można wykonać procesu @EXECUTABLE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Proces @EXECUTABLE@ nie mógł zostać wykonany i się nie powiódł. Numer błędu zwrócony przez ten proces: @ERRNO@. -- 0027229ca0644181a76c4e92458afa2e Subject: Nie można przekazać jednego lub więcej komunikatów do syslog Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Jeden lub więcej komunikatów nie może zostać przekazanych do usługi syslog uruchomionej obok journald. Zwykle oznacza to, że implementacja syslog nie jest w stanie nadążyć za prędkością kolejki komunikatów. -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: Punkt montowania nie jest pusty Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Katalog @WHERE@ został podany jako punkt montowania (drugie pole w pliku /etc/fstab lub pole Where= w pliku jednostki systemd) i nie jest pusty. Nie wpływa to na montowanie, ale wcześniej istniejące pliki w tym katalogu stają się niedostępne. Aby zobaczyć te pliki, proszę ręcznie zamontować system plików w innym położeniu. -- 24d8d4452573402496068381a6312df2 Subject: Uruchomiono maszynę wirtualną lub kontener Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Maszyna wirtualna @NAME@ (PID prowadzący @LEADER@) została uruchomiona i jest gotowa do użycia. -- 58432bd3bace477cb514b56381b8a758 Subject: Zakończono maszynę wirtualną lub kontener Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Maszyna wirtualna @NAME@ (PID prowadzący @LEADER@) została wyłączona. systemd-229/catalog/systemd.pt_BR.catalog000066400000000000000000000230301265713322000205220ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2012 Lennart Poettering # Copyright 2015 Rafael Ferreira (translation) # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Catálogo de mensagens para as mensagens do próprio systemd # O formato do catálogo está documentado em # http://www.freedesktop.org/wiki/Software/systemd/catalog # Para uma explicação do porquê de fazermos tudo isso, veja # https://xkcd.com/1024/ -- f77379a8490b408bbe5f6940505a777b Subject: O jornal foi inciado Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel O processo jornal do sistema foi iniciado, arquivos foram abertos e está pronto para processar requisições. -- d93fb3c9c24d451a97cea615ce59c00b Subject: O jornal foi interrompido Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel O processo do jornal do sistema foi desligado e todos os arquivos de jornal do sistema foram fechados. -- a596d6fe7bfa4994828e72309e95d61e Subject: Mensagens de um serviço foram suprimidas Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) Um serviço registrou no log um número excessivo de mensagens dentro de um período de tempo. Mensagens do serviço foram descartadas. Note que apenas mensagens de um serviço em questão foram descartadas; outras mensagens dos serviços não foram afetadas. Os controles de limites de quando as mensagens são descartadas pode ser configurado com RateLimitInterval= e RateLimitBurst= no /etc/systemd/journald.conf. Veja journald.conf(5) para detalhes. -- e9bf28e6e834481bb6f48f548ad13606 Subject: Mensagens do jornal foram perdidas Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Mensagens do kernel foram perdidas pois o sistema do jornal não pôde processá-las em velocidade suficiente para a demanda. -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: Processo @COREDUMP_PID@ (@COREDUMP_COMM@) despejou núcleo Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) Processo @COREDUMP_PID@ (@COREDUMP_COMM@) travou e despejou o núcleo. Isso normalmente indica um erro de programação no programa que travou e deveria ser relatado para seu fabricante como um erro. -- 8d45620c1a4348dbb17410da57c60c66 Subject: A nova sessão @SESSION_ID@ foi criada para usuário o @USER_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Uma nova sessão com o ID @SESSION_ID@ foi criada para o usuário @USER_ID@. O processo originador da sessão é @LEADER@. -- 3354939424b4456d9802ca8333ed424a Subject: Sessão @SESSION_ID@ foi terminada Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Um sessão com o ID @SESSION_ID@ foi terminada. -- fcbefc5da23d428093f97c82a9290f7b Subject: Um novo seat @SEAT_ID@ está disponível Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Um novo seat @SEAT_ID@ foi configurado e está disponível. -- e7852bfe46784ed0accde04bc864c2d5 Subject: Seat @SEAT_ID@ foi removido agora Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Um seat @SEAT_ID@ foi removido e não está mais disponível. -- c7a787079b354eaaa9e77b371893cd27 Subject: Time change Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel O relógio do sistema foi alterado para @REALTIME@ microssegundos após 1º de janeiro de 1970. -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: Fuso horário alterado para @TIMEZONE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel O fuso horário do sistema foi alterado para @TIMEZONE@. -- b07a249cd024414a82dd00cd181378ff Subject: Inicialização do sistema foi concluída Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Todos os serviços do sistema necessários que estão enfileirados para executar na inicialização do sistema, foram iniciados com sucesso. Note que isso não significa que a máquina está ociosa, pois os serviços podem ainda estar ocupados com a inicialização completa. Inicialização do kernel precisou @KERNEL_USEC@ microssegundos. Disco de RAM inicial precisou de @INITRD_USEC@ microssegundos. Inicialização do espaço do usuário precisou de @USERSPACE_USEC@ microssegundos. -- 6bbd95ee977941e497c48be27c254128 Subject: Estado de suspensão do sistema @SLEEP@ iniciado Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel O sistema entrou agora no estado de suspensão @SLEEP@. -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: Estado de suspensão do sistema @SLEEP@ finalizado Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel O sistema saiu agora do estado de suspensão @SLEEP@. -- 98268866d1d54a499c4e98921d93bc40 Subject: Desligamento do sistema iniciado Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Desligamento do sistema foi inicializado. O desligamento se iniciou e todos os serviços do sistema foram terminados e todos os sistemas desmontados. -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: Unidade @UNIT@ sendo iniciado Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A unidade @UNIT@ está sendo iniciada. -- 39f53479d3a045ac8e11786248231fbf Subject: Unidade @UNIT@ concluiu a inicialização Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A unidade @UNIT@ concluiu a inicialização. The start-up result is @RESULT@. -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: Unidade @UNIT@ sendo desligado Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A unidade @UNIT@ está sendo desligada. -- 9d1aaa27d60140bd96365438aad20286 Subject: A unidade @UNIT@ concluiu o desligamento Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A unidade @UNIT@ concluiu o desligamento. -- be02cf6855d2428ba40df7e9d022f03d Subject: A unidade @UNIT@ falhou Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A unidade @UNIT@ falhou. O resultado é @RESULT@. -- d34d037fff1847e6ae669a370e694725 Subject: Unidade @UNIT@ iniciou recarregamento de sua configuração Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A unidade @UNIT@ iniciou o recarregamento de sua configuração. -- 7b05ebc668384222baa8881179cfda54 Subject: Unidade @UNIT@ concluiu recarregamento de sua configuração Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A unidade @UNIT@ concluiu o recarregamento de sua configuração. O resultado é @RESULT@. -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: Processo @EXECUTABLE@ não pôde ser executado Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel O processo @EXECUTABLE@ não pôde ser executado e falhou. O número de erro retornado por este processo é @ERRNO@. -- 0027229ca0644181a76c4e92458afa2e Subject: Uma ou mais mensagens não puderam ser encaminhadas para o syslog Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Uma ou mais mensagens não puderam ser encaminhadas para o serviço do syslog em execução paralela ao journald. Isso normalmente indica que a implementação do syslog não foi capaz de se manter com a velocidade das mensagens enfileiradas. -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: Ponto de montagem não está vazio Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel O diretório @WHERE@ está especificado como ponto de montagem (o segundo campo no /etc/fstab ou campo Where= no arquivo de unidade do systemd) e não está vazio. Isso não interfere com a montagem, mas os arquivos pré-existentes neste diretório se tornaram inacessívels. Para ver aqueles arquivos, sobre os quais foi realizada a montagem, por favor monte manualmente o sistema de arquivos subjacente para uma localização secundária. -- 24d8d4452573402496068381a6312df2 Subject: Uma máquina virtual ou contêiner foi iniciado Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A máquina virtual @NAME@ com seu PID @LEADER@ incial foi iniciada e está pronto para ser usad. -- 58432bd3bace477cb514b56381b8a758 Subject: Uma máquina virtual ou contêiner foi terminado Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel A máquina virtual @NAME@ com seu PID @LEADER@ incial foi desligada. systemd-229/catalog/systemd.ru.catalog000066400000000000000000000431371265713322000201540ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2012 Lennart Poettering # Copyright 2013-2016 Sergey Ptashnick # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Message catalog for systemd's own messages # Russian translation # Формат каталога сообщений описан по ссылке # http://www.freedesktop.org/wiki/Software/systemd/catalog # Перед каждым элементом в комментарии указан Subject исходного # сообщения (на английском). # Subject: The Journal has been started -- f77379a8490b408bbe5f6940505a777b Subject: Запущена служба журналирования Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Процесс, отвечающий за журналирование системных событий, успешно запустился, открыл для записи файлы журнала, и готов обрабатывать запросы. # Subject: The Journal has been stopped -- d93fb3c9c24d451a97cea615ce59c00b Subject: Служба журналирования остановлена Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Процесс, отвечающий за журналирование системных событий, завершил работу и закрыл все свои файлы. # Subject: Disk space used by the journal -- ec387f577b844b8fa948f33cad9a75e6 Subject: Место на диске, занятое журналом Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @JOURNAL_NAME@ (@JOURNAL_PATH@) сейчас занимает @CURRENT_USE_PRETTY@. Максимальный разрешенный размер составляет @MAX_USE_PRETTY@. Оставляем свободными как минимум @DISK_KEEP_FREE_PRETTY@ (сейчас на диске свободно @DISK_AVAILABLE_PRETTY@). Таким образом, предел использования составляет @LIMIT_PRETTY@, из которых @AVAILABLE_PRETTY@ пока свободно. Ограничения на размер журнала настраиваются при помощи параметров SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=, RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= в файле /etc/systemd/journald.conf. Более подробные сведения вы можете получить на справочной странице journald.conf(5). # Subject: Messages from a service have been suppressed -- a596d6fe7bfa4994828e72309e95d61e Subject: Часть сообщений от службы пропущена Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) Служба отправила слишком много сообщений за короткий промежуток времени. Часть сообщений была пропущена. Обратите внимание, что были пропущены сообщения только от этой службы, сообщения других служб не затронуты. Предел, после которого служба журнала начинает игнорировать сообщения, настраивается параметрами RateLimitInterval= и RateLimitBurst= в файле /etc/systemd/journald.conf. Подробности смотрите на странице руководства journald.conf(5). # Subject: Journal messages have been missed -- e9bf28e6e834481bb6f48f548ad13606 Subject: Часть сообщений ядра пропущена Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Часть сообщений, поступивших от ядра, была потеряна, так как служба журналирования не успела их обработать. # Subject: Process @COREDUMP_PID@ (@COREDUMP_COMM@) dumped core -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: Процесс @COREDUMP_PID@ (@COREDUMP_COMM@) сбросил дамп памяти Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) Процесс @COREDUMP_PID@ (@COREDUMP_COMM@) завершился из-за критической ошибки. Записан дамп памяти. Вероятно, это произошло из-за ошибки, допущенной в коде программы. Рекомендуется сообщить её разработчикам о возникшей проблеме. # Subject: A new session @SESSION_ID@ has been created for user @USER_ID@ -- 8d45620c1a4348dbb17410da57c60c66 Subject: Для пользователя @USER_ID@ создан новый сеанс @SESSION_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Для пользователя @USER_ID@ создан новый сеанс с идентификатором @SESSION_ID@. Главный процесс нового сеанса имеет индентификатор @LEADER@. # Subject: A session @SESSION_ID@ has been terminated -- 3354939424b4456d9802ca8333ed424a Subject: Сеанс @SESSION_ID@ завершен Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Сеанс с идентификатором @SESSION_ID@ завершился. # Subject: A new seat @SEAT_ID@ is now available -- fcbefc5da23d428093f97c82a9290f7b Subject: Добавлено новое рабочее место @SEAT_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Новое рабочее место (seat) @SEAT_ID@ полностью настроено и готово к использованию. # Subject: A seat @SEAT_ID@ has now been removed -- e7852bfe46784ed0accde04bc864c2d5 Subject: Рабочее место @SEAT_ID@ отключено Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Рабочее место (seat) @SEAT_ID@ было отключено. # Subject: Time change -- c7a787079b354eaaa9e77b371893cd27 Subject: Переведены системные часы Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Системные часы были переведены. Сейчас они показывают @REALTIME@ микросекунд с момента 00:00:00 1 января 1970 года. # Subject: Time zone change to @TIMEZONE@ -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: Часовой пояс изменен на @TIMEZONE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Системный часовой пояс был изменен. Новое значение: @TIMEZONE@. # Subject: System start-up is now complete -- b07a249cd024414a82dd00cd181378ff Subject: Запуск системы завершен Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Все системные службы, запуск которых предписан настройками, были запущены. Впрочем, это ещё не означает, что система в данный момент ничем не занята, так как некоторые службы могут продолжать инициализацию даже после того, как отчитались о своем запуске. Запуск ядра занял @KERNEL_USEC@ микросекунд. Процессы начального RAM-диска (initrd) отработали за @INITRD_USEC@ микросекунд. Запуск системных служб занял @USERSPACE_USEC@ микросекунд. # Subject: System sleep state @SLEEP@ entered -- 6bbd95ee977941e497c48be27c254128 Subject: Система перешла в состояние сна (@SLEEP@) Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Система была переведена в состояние сна (@SLEEP@). # Subject: System sleep state @SLEEP@ left -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: Система вышла из состояния сна (@SLEEP@) Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Система была выведена из состояния сна (@SLEEP@). # Subject: System shutdown initiated -- 98268866d1d54a499c4e98921d93bc40 Subject: Подготовка системы к выключению Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Начат процесс подготовки к выключению компьютера. Останавливаются все системные службы, отмонтируются все файловые системы. # Subject: Unit @UNIT@ has begun with start-up -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: Начинается запуск юнита @UNIT@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Начат процесс запуска юнита @UNIT@. # Subject: Unit @UNIT@ has finished start-up -- 39f53479d3a045ac8e11786248231fbf Subject: Запуск юнита @UNIT@ завершен Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Процесс запуска юнита @UNIT@ был завершен. Результат: @RESULT@. # Subject: Unit @UNIT@ has begun shutting down -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: Начинается остановка юнита @UNIT@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Начат процесс остановки юнита @UNIT@. # Subject: Unit @UNIT@ has finished shutting down -- 9d1aaa27d60140bd96365438aad20286 Subject: Завершена остановка юнита @UNIT@. Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Процесс остановки юнита @UNIT@ был завершен. # Subject: Unit @UNIT@ has failed -- be02cf6855d2428ba40df7e9d022f03d Subject: Ошибка юнита @UNIT@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Произошел сбой юнита @UNIT@. Результат: @RESULT@. # Subject: Unit @UNIT@ has begun with reloading its configuration -- d34d037fff1847e6ae669a370e694725 Subject: Юнит @UNIT@ начал перечитывать свои настройки Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Юнит @UNIT@ начал процесс перечитывания своей конфигурации. # Subject: Unit @UNIT@ has finished reloading its configuration -- 7b05ebc668384222baa8881179cfda54 Subject: Юнит @UNIT@ завершил перечитывание своих настроек Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Юнит @UNIT@ завершил процесс перечитывания своей конфигурации. Результат: @RESULT@. # Subject: Process @EXECUTABLE@ could not be executed -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: Не удалось запустить процесс @EXECUTABLE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Сбой: не удалось запустить процесс @EXECUTABLE@. Код ошибки: @ERRNO@. # Subject: One or more messages could not be forwarded to syslog -- 0027229ca0644181a76c4e92458afa2e Subject: Часть сообщений не удалось передать процессу syslog Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Не удалось передать некоторые сообщения демону системного лога (syslog), дублирующему работу службы системного журнала. Скорее всего, причина в том, что используемая реализация syslog не успевает обрабатывать сообщения с достаточной скоростью. # Subject: Mount point is not empty -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: Каталог, являющийся точкой монтирования, не пуст Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Каталог @WHERE@, который был указан в качестве точки монтирования (во втором столбце файла /etc/fstab, либо в параметре Where= файла конфигурации юнита), не является пустым. Это никак не мешает монтированию, однако ранее находившиеся в нем файлы будут недоступны. Чтобы получить к ним доступ, вы можете вручную перемонтировать эту файловую систему в другую точку. # Subject: A virtual machine or container has been started -- 24d8d4452573402496068381a6312df2 Subject: Запущена виртуальная машина/контейнер Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Виртуальная машина @NAME@ (идентификатор главного процесса: @LEADER@) запущена и готова к работе. # Subject: A virtual machine or container has been terminated -- 58432bd3bace477cb514b56381b8a758 Subject: Остановлена виртуальная машина/контейнер Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Виртуальная машина @NAME@ (идентификатор главного процесса: @LEADER@) выключена. # Subject: DNSSEC mode has been turned off, as server doesn't support it -- 36db2dfa5a9045e1bd4af5f93e1cf057 Subject: Механизм DNSSEC был отключен, так как DNS-сервер его не поддерживает Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:systemd-resolved.service(8) resolved.conf(5) Служба разрешения имен хостов (systemd-resolved.service) определила, что указанный в настойках DNS-сервер не поддерживает технологию DNSSEC, и автоматически отключила DNSSEC-проверки. Данное событие возникает, если в файле resolved.conf указан параметр DNSSEC=allow-downgrade, и вышестоящий DNS-сервер не поддерживает DNSSEC. Обратите внимание, что режим allow-downgrade допускает возможность атаки "DNSSEC downgrade", в ходе которой атакующий хакер блокирует проверки DNSSEC путем отправки ложных сообщений от имени DNS-сервера. Возникновение данного события может свидетельствовать как о том, что ваш DNS-сервер не поддерживает DNSSEC, так и о том, что некий хакер успешно провел против вас атаку, направленную на блокировку DNSSEC-проверок. # Subject: DNSSEC validation failed -- 1675d7f172174098b1108bf8c7dc8f5d Subject: Проверка DNSSEC провалена Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:systemd-resolved.service(8) DNS-запрос или отдельная ресурсная запись не прошла проверку DNSSEC. Как правило, это свидетельствует о постороннем вмешательстве в канал связи. # Subject: A DNSSEC trust anchor has been revoked -- 4d4408cfd0d144859184d1e65d7c8a65 Subject: Открытый ключ DNSSEC был отозван Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:systemd-resolved.service(8) Открытый ключ (trust ahcnor) DNSSEC был отозван. Необходимо настроить новый открытый ключ, либо обновить систему, чтобы получить обновленный открытый ключ. systemd-229/catalog/systemd.sr.catalog000066400000000000000000000274531265713322000201550ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2012 Lennart Poettering # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Message catalog for systemd's own messages # Serbian translation # Формат каталога је документован на # http://www.freedesktop.org/wiki/Software/systemd/catalog # Да бисте видели зашто ово радимо, погледајте https://xkcd.com/1024/ -- f77379a8490b408bbe5f6940505a777b Subject: Журнал је покренут Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Системски журналски процес се покренуо, отворио журналске датотеке за упис и спреман је за обраду захтева. -- d93fb3c9c24d451a97cea615ce59c00b Subject: Журнал је заустављен Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Системски журналски процес се зауставио и затворио све тренутно отворене журналске датотеке. -- a596d6fe7bfa4994828e72309e95d61e Subject: Поруке од услуге су утишане Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) Услуга је уписала сувише порука за једно време. Поруке од услуге су одбачене. Знајте да су само поруке од ове услуге одбачене, друге услуге нису захваћене овим. Ограничења која подешавају начин на који се поруке одбацују се могу подесити помоћу „RateLimitInterval=“ и „RateLimitBurst=“ параметара унутар датотеке /etc/systemd/journald.conf. Погледајте journald.conf(5) за појединости. -- e9bf28e6e834481bb6f48f548ad13606 Subject: Журналске поруке су изгубљене Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Поруке кернела су изгубљене јер журналски систем није могао да их обради довољно брзо. -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: Процес @COREDUMP_PID@ (@COREDUMP_COMM@) је избацио своје језгро Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) Процес @COREDUMP_PID@ (@COREDUMP_COMM@) је пао и избацио своје језгро. Ово обично значи да постоји грешка у програму који је пао и ова грешка треба да се пријави продавцу. -- 8d45620c1a4348dbb17410da57c60c66 Subject: Нова сесија @SESSION_ID@ је направљена за корисника @USER_ID@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Нова сесија са ИБ-ом @SESSION_ID@ је направљена за корисника @USER_ID@. Водећи процес сесије је @LEADER@. -- 3354939424b4456d9802ca8333ed424a Subject: Сесија @SESSION_ID@ је окончана Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Сесија са ИБ-ом @SESSION_ID@ је окончана. -- fcbefc5da23d428093f97c82a9290f7b Subject: Ново седиште @SEAT_ID@ је сада доступно Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Ново седиште @SEAT_ID@ је исподешавано и сада је доступно. -- e7852bfe46784ed0accde04bc864c2d5 Subject: Седиште @SEAT_ID@ је сада уклоњено Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat Седиште @SEAT_ID@ је сада уклоњено и више није доступно. -- c7a787079b354eaaa9e77b371893cd27 Subject: Време је промењено Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Системски сат је сада подешен на @REALTIME@ микросекунде након 1. јануара 1970. године. -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: Временска зона је промењена на @TIMEZONE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Временска зона је промењена на @TIMEZONE@. -- b07a249cd024414a82dd00cd181378ff Subject: Подизање система је сада готово Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Све системске услуге које су заказане за подизање су успешно покренуте. Знајте да ово не значи да је машина сада беспослена јер услуге могу и даље бити заузете завршавањем покретања система. Подизање кернела је трајало @KERNEL_USEC@ микросекунде. Подизање почетног РАМ диска је трајало @INITRD_USEC@ микросекунде. Подизање корисничких програма је трајало @USERSPACE_USEC@ микросекунде. -- 6bbd95ee977941e497c48be27c254128 Subject: Системско стање спавања @SLEEP@ започето Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Систем је сада ушао у @SLEEP@ стање спавања. -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: Системско стање спавања @SLEEP@ напуштено Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Систем је изашао из @SLEEP@ стања спавања. -- 98268866d1d54a499c4e98921d93bc40 Subject: Гашење система започето Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Систем-де гашење је започето. Гашење је сада почело и све системске услуге су окончане и сви системи датотека откачени. -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: Јединица @UNIT@ је почела са покретањем Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Јединица @UNIT@ је почела са покретањем. -- 39f53479d3a045ac8e11786248231fbf Subject: Јединица @UNIT@ је завршила са покретањем Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Јединица @UNIT@ је завршила са покретањем. Исход покретања је @RESULT@. -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: Јединица @UNIT@ је почела са гашењем Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Јединица @UNIT@ је почела са гашењем. -- 9d1aaa27d60140bd96365438aad20286 Subject: Јединица @UNIT@ је завршила са гашењем Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Јединица @UNIT@ је завршила са гашењем. -- be02cf6855d2428ba40df7e9d022f03d Subject: Јединица @UNIT@ је пукла Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Јединица @UNIT@ је пукла. Исход је @RESULT@. -- d34d037fff1847e6ae669a370e694725 Subject: Јединица @UNIT@ је почела са поновним учитавањем свог подешавања Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Јединица @UNIT@ је почела са поновним учитавањем свог подешавања -- 7b05ebc668384222baa8881179cfda54 Subject: Јединица @UNIT@ је завршила са поновним учитавањем свог подешавања Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Јединица @UNIT@ је завршила са поновним учитавањем свог подешавања Исход је @RESULT@. -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: Процес @EXECUTABLE@ није могао бити извршен Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Процес @EXECUTABLE@ није могао бити извршен и пукао је. Овај процес је вратио број грешке @ERRNO@. -- 0027229ca0644181a76c4e92458afa2e Subject: Једна или више порука није могло бити прослеђено системском записнику Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Једна или више порука није могло бити прослеђено „syslog“ услузи која ради упоредно са журнал-деом. Ово обично значи да спроведена „syslog“ услуга није могла да издржи брзину свих надолазећих порука у реду. -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: Тачка качења није празна Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Директоријум @WHERE@ је наведен као тачка качења (друго поље у /etc/fstab датотеци или у „Where=“ пољу систем-де јединичне датотеке) и он није празан. Ово не утиче на качење али ће већ постојеће датотеке у овом директоријуму постати недоступне. Да бисте видели ове недоступне датотеке, ручно прикачите основни систем датотека у другу путању. -- 24d8d4452573402496068381a6312df2 Subject: Виртуелна машина или контејнер је покренут(а) Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Виртуелна машина @NAME@ са водећим ПИБ-ом @LEADER@ је покренута и сада је спремна за коришћење. -- 58432bd3bace477cb514b56381b8a758 Subject: Виртуелна машина или контејнер је окончан(а) Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Виртуелна машина @NAME@ са водећим ПИБ-ом @LEADER@ је угашена. systemd-229/catalog/systemd.zh_CN.catalog000066400000000000000000000210371265713322000205220ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2012 Lennart Poettering # Copyright 2015 Boyuan Yang # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Message catalog for systemd's own messages # Simplified Chinese translation # 本 catalog 文档格式被记载在 # http://www.freedesktop.org/wiki/Software/systemd/catalog # 如需了解我们为什么做这些工作,请见 https://xkcd.com/1024/ -- f77379a8490b408bbe5f6940505a777b Subject: 日志已开始 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 系统日志进程已启动,已打开供写入的日志文件并准备好处理请求。 -- d93fb3c9c24d451a97cea615ce59c00b Subject: 日志已停止 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 系统日志进程已终止,并已关闭所有当前活动的日志文件。 -- a596d6fe7bfa4994828e72309e95d61e Subject: 由某个服务而来的消息已被抑制 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) 某个服务在一个时间周期内记录了太多消息。 从该服务而来的消息已被丢弃。 请注意只有由有问题的服务传来的消息被丢弃, 其它服务的消息不受影响。 可以在 /etc/systemd/journald.conf 中设定 RateLimitInterval= 以及 RateLimitBurst = 的值以控制丢弃信息的限制。 请参见 journald.conf(5) 以了解详情。 -- e9bf28e6e834481bb6f48f548ad13606 Subject: 日志消息已遗失 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 因日志系统对内核消息的处理速度不够快, 部分信息已经遗失。 -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: 进程 @COREDUMP_PID@ (@COREDUMP_COMM@) 核心已转储 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) 进程 @COREDUMP_PID@ (@COREDUMP_COMM@) 已崩溃并进行核心转储。 这通常意味着崩溃程序中存在编程错误,并应当将此错误向其开发者报告。 -- 8d45620c1a4348dbb17410da57c60c66 Subject: 一个新会话 @SESSION_ID@ 已为用户 @USER_ID@ 建立 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat 一个 ID 为 @SESSION_ID@ 的新会话已为用户 @USER_ID@ 建立。 该会话的首进程为 @LEADER@。 -- 3354939424b4456d9802ca8333ed424a Subject: 会话 @SESSION_ID@ 已终止 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat 一个 ID 为 @SESSION_ID@ 的会话已终止。 -- fcbefc5da23d428093f97c82a9290f7b Subject: 一个新的座位 @SEAT_ID@ 可用 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat 一个新的座位 @SEAT_ID@ 已被配置并已可用。 -- e7852bfe46784ed0accde04bc864c2d5 Subject: 座位 @SEAT_ID@ 已被移除 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat 座位 @SEAT_ID@ 已被移除并不再可用。 -- c7a787079b354eaaa9e77b371893cd27 Subject: 时间已变更 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 系统时钟已变更为1970年1月1日后 @REALTIME@ 微秒。 -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: 时区变更为 @TIMEZONE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 系统时区已变更为 @TIMEZONE@。 -- b07a249cd024414a82dd00cd181378ff Subject: 系统启动已完成 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 所有系统启动时需要的系统服务均已成功启动。 请注意这并不代表现在机器已经空闲,因为某些服务可能仍处于完成启动的过程中。 内核启动使用了 @KERNEL_USEC@ 毫秒。 初始内存盘启动使用了 @INITRD_USEC@ 毫秒。 用户空间启动使用了 @USERSPACE_USEC@ 毫秒。 -- 6bbd95ee977941e497c48be27c254128 Subject: 系统已进入 @SLEEP@ 睡眠状态 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-deve 系统现已进入 @SLEEP@ 睡眠状态。 -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: 系统已离开 @SLEEP@ 睡眠状态 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 系统现已离开 @SLEEP@ 睡眠状态。 -- 98268866d1d54a499c4e98921d93bc40 Subject: 系统关机已开始 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 系统关机操作已初始化。 关机已开始,所有系统服务均已结束,所有文件系统已卸载。 -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: @UNIT@ 单元已开始启动 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 单元已开始启动。 -- 39f53479d3a045ac8e11786248231fbf Subject: @UNIT@ 单元已结束启动 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 单元已结束启动。 启动结果为“@RESULT@”。 -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: @UNIT@ 单元已开始停止操作 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 单元已开始停止操作。 -- 9d1aaa27d60140bd96365438aad20286 Subject: @UNIT@ 单元已结束停止操作 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 单元已结束停止操作。 -- be02cf6855d2428ba40df7e9d022f03d Subject: @UNIT@ 单元已失败 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 单元已失败。 结果为“@RESULT@”。 -- d34d037fff1847e6ae669a370e694725 Subject: @UNIT@ 单元已开始重新载入其配置 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 单元已开始重新载入其配置。 -- 7b05ebc668384222baa8881179cfda54 Subject: @UNIT@ 单元已结束配置重载入 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel @UNIT@ 单元已结束配置重载入操作。 结果为“@RESULT@”。 -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: 进程 @EXECUTABLE@ 无法执行 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 进程 @EXECUTABLE@ 无法被执行并已失败。 该进程返回的错误代码为 @ERRNO@。 -- 0027229ca0644181a76c4e92458afa2e Subject: 一个或更多消息无法被转发至 syslog Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 有一条或更多的消息无法被转发至与 journald 同时运行的 syslog 服务。 这通常意味着 syslog 实现无法跟上队列中消息进入的速度。 -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: 挂载点不为空 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 目录 @WHERE@ 被指定为挂载点(即 /etc/fstab 文件的第二栏,或 systemd 单元 文件的 Where= 字段),且该目录非空。 这并不会影响挂载行为,但该目录中先前已存在的文件将无法被访问。 如需查看这些文件,请手动将其下的文件系统挂载到另一个位置。 -- 24d8d4452573402496068381a6312df2 Subject: 一个虚拟机或容器已启动 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 虚拟机 @NAME@,以及其首进程 PID @LEADER@,已被启动并可被使用。 -- 58432bd3bace477cb514b56381b8a758 Subject: 一个虚拟机或容器已被终止 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 虚拟机 @NAME@,以及其首进程 PID @LEADER@,已被关闭并停止。 systemd-229/catalog/systemd.zh_TW.catalog000066400000000000000000000207671265713322000205650ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2012 Lennart Poettering # Copyright 2015 Jeff Huang # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # Message catalog for systemd's own messages # Traditional Chinese translation # Catalog 的格式記錄於 # http://www.freedesktop.org/wiki/Software/systemd/catalog # For an explanation why we do all this, see https://xkcd.com/1024/ -- f77379a8490b408bbe5f6940505a777b Subject: 日誌已開始 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 系統日誌行程已啟動,已開啟日誌 檔案供寫入並準備好對行程的要求做出回應。 -- d93fb3c9c24d451a97cea615ce59c00b Subject: 日誌已停止 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 系統日誌行程已關閉,且關閉所有目前 活躍的日誌檔案。 -- a596d6fe7bfa4994828e72309e95d61e Subject: 從服務而來的訊息已被抑制 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:journald.conf(5) 有一個服務在一個時間週期內記錄了太多訊息。 從該服務而來的訊息已被丟棄。 注意,只有有問題的服務之訊息被丟棄, 其他服務的訊息則不受影響。 可以在 /etc/systemd/journald.conf 中設定 RateLimitInterval= 以及 RateLimitBurst= 來控制當訊息要開始被丟棄時的限制。參見 journald.conf(5) 以獲得更多資訊。 -- e9bf28e6e834481bb6f48f548ad13606 Subject: 日誌訊息已遺失 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 因日誌系統對核心訊息的處理不夠快速, 部份訊息已遺失。 -- fc2e22bc6ee647b6b90729ab34a250b1 Subject: 行程 @COREDUMP_PID@ (@COREDUMP_COMM@) 核心傾印 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: man:core(5) 行程 @COREDUMP_PID@ (@COREDUMP_COMM@) 當掉並核心傾印。 這通常代表了在當掉的程式中的一個程式錯誤 並需要回報錯誤給其開發者。 -- 8d45620c1a4348dbb17410da57c60c66 Subject: 新的工作階段 @SESSION_ID@ 已為使用者 @USER_ID@ 建立 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat 一個新的工作階段,ID @SESSION_ID@ 已為使用者 @USER_ID@ 建立。 這個工作階段的領導行程為 @LEADER@。 -- 3354939424b4456d9802ca8333ed424a Subject: 工作階段 @SESSION_ID@ 已結束 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat 一個工作階段,ID @SESSION_ID@ 已結束。 -- fcbefc5da23d428093f97c82a9290f7b Subject: 新的座位 @SEAT_ID@ 可用 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat 一個新的座位 @SEAT_ID@ 已被設定且現在可用。 -- e7852bfe46784ed0accde04bc864c2d5 Subject: 座位 @SEAT_ID@ 已被移除 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat 座位 @SEAT_ID@ 已被移除且不再可用。 -- c7a787079b354eaaa9e77b371893cd27 Subject: 時間變更 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 系統時間已變更為1970年1月1日後 @REALTIME@ 微秒。 -- 45f82f4aef7a4bbf942ce861d1f20990 Subject: 時區變更為 @TIMEZONE@ Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 系統時區已變更為 @TIMEZONE@。 -- b07a249cd024414a82dd00cd181378ff Subject: 系統啟動已完成 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 所有開機所必要的系統服務都已成功啟動。 注意這並不代表這臺機器有空閒的時間 可以服務,可能仍忙於完成啟動。 核心啟動需要 @KERNEL_USEC@ 微秒。 初始 RAM 磁碟啟動需要 @INITRD_USEC@ 微秒。 使用者空間啟動需要 @USERSPACE_USEC@ 微秒。 -- 6bbd95ee977941e497c48be27c254128 Subject: 系統進入 @SLEEP@ 睡眠狀態 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 系統現在已進入 @SLEEP@ 睡眠狀態。 -- 8811e6df2a8e40f58a94cea26f8ebf14 Subject: 系統離開 @SLEEP@ 睡眠狀態 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 系統現在已離開 @SLEEP@ 睡眠狀態。 -- 98268866d1d54a499c4e98921d93bc40 Subject: 系統關機開始 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel Systemd 關閉已經開始。關閉已開始且所有系統服務 都已結束,所有的檔案系統也都已被卸載。 -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: 單位 @UNIT@ 已開始啟動 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 單位 @UNIT@ 已開始啟動。 -- 39f53479d3a045ac8e11786248231fbf Subject: 單位 @UNIT@ 啟動已結束 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 單位 @UNIT@ 啟動已結束。 啟動結果為 @RESULT@。 -- de5b426a63be47a7b6ac3eaac82e2f6f Subject: 單位 @UNIT@ 已開始關閉 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 單位 @UNIT@ 已開始關閉。 -- 9d1aaa27d60140bd96365438aad20286 Subject: 單位 @UNIT@ 已關閉結束 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 單位 @UNIT@ 已關閉結束。 -- be02cf6855d2428ba40df7e9d022f03d Subject: 單位 @UNIT@ 已失敗 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 單位 @UNIT@ 已失敗。 結果為 @RESULT@。 -- d34d037fff1847e6ae669a370e694725 Subject: 單位 @UNIT@ 已開始重新載入其設定 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 單位 @UNIT@ 已開始重新載入其設定 -- 7b05ebc668384222baa8881179cfda54 Subject: 單位 @UNIT@ 已結束重新載入其設定 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 單位 @UNIT@ 已結束重新載入其設定 結果為 @RESULT@。 -- 641257651c1b4ec9a8624d7a40a9e1e7 Subject: 行程 @EXECUTABLE@ 無法執行 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 行程 @EXECUTABLE@ 無法執行且失敗。 由該行程所回傳的錯誤碼為 @ERRNO@。 -- 0027229ca0644181a76c4e92458afa2e Subject: 一個或更多訊息無法被轉發到 syslog Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 一個或更多訊息無法被轉發到 syslog 服務 以及並行執行的 journald。這通常代表著 syslog 實作並無未跟上佇列中訊息 的速度。 -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: 掛載點不為空 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 目錄 @WHERE@ 被指定為掛載點(在 /etc/fstab 中的 第二欄或是在 systemd 單位檔案中的 Where= 欄位)且其不為空。 這並不會干擾掛載,但在此目錄中已存在的檔案 會變成無法存取的狀態。要檢視這些 over-mounted 的檔案, 請手動掛載下面的檔案系統到次要 位置。 -- 24d8d4452573402496068381a6312df2 Subject: 虛擬機器或容器已啟動 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 虛擬機器 @NAME@ 包含它的領導 PID @LEADER@ 現在 已經開始並已經可以使用。 -- 58432bd3bace477cb514b56381b8a758 Subject: 虛擬機器或容器已結束 Defined-By: systemd Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel 虛擬機器 @NAME@ 包含它的領導 PID @LEADER@ 已經 關閉。 systemd-229/coccinelle/000077500000000000000000000000001265713322000151615ustar00rootroot00000000000000systemd-229/coccinelle/empty-if.cocci000066400000000000000000000006131265713322000177150ustar00rootroot00000000000000@@ expression e, f, g, h, i, j; statement s, t; @@ ( if (e) { ( if (h) s | if (h) s else t | while (h) s | for (h; i; j) s ) } | while (e) { ( if (h) s | if (h) s else t | while (h) s | for (h; i; j) s ) } | for (e; f; g) { ( if (h) s | if (h) s else t | while (h) s | for (h; i; j) s ) } | - if (e) { + if (e) s - } | - while (e) { + while (e) s - } | - for (e; f; g) { + for (e; f; g) s - } ) systemd-229/coccinelle/errno.cocci000066400000000000000000000012631265713322000173120ustar00rootroot00000000000000@@ identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; local idexpression r; expression e; @@ - r = -e; + r = log_LEVEL_errno(e, ...); @@ identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; local idexpression r; expression e; @@ + r = log_LEVEL_errno(e, ...); - r = -e; @@ identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; local idexpression r; expression e; @@ - r = + return log_LEVEL_errno(e, ...); - return r; @@ identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; expression e; @@ + return log_LEVEL_errno(e, ...); - return -e; systemd-229/coccinelle/hashmap_free.cocci000066400000000000000000000012221265713322000206020ustar00rootroot00000000000000@@ expression p; @@ - set_free(p); - p = NULL; + p = set_free(p); @@ expression p; @@ - if (p) - set_free(p); - p = NULL; + p = set_free(p); @@ expression p; @@ - if (p) { - set_free(p); - p = NULL; - } + p = set_free(p); @@ expression p; @@ - if (p) - set_free(p); + set_free(p); @@ expression p; @@ - hashmap_free(p); - p = NULL; + p = hashmap_free(p); @@ expression p; @@ - if (p) - hashmap_free(p); - p = NULL; + p = hashmap_free(p); @@ expression p; @@ - if (p) { - hashmap_free(p); - p = NULL; - } + p = hashmap_free(p); @@ expression p; @@ - if (p) - hashmap_free(p); + hashmap_free(p); systemd-229/coccinelle/mfree.cocci000066400000000000000000000000731265713322000172610ustar00rootroot00000000000000@@ expression p; @@ - free(p); - p = NULL; + p = mfree(p); systemd-229/coccinelle/no-if-assignments.cocci000066400000000000000000000003101265713322000215160ustar00rootroot00000000000000@@ expression p, q; identifier r; statement s; @@ - if ((r = q) < p) - s + r = q; + if (r < p) + s @@ expression p, q; identifier r; statement s; @@ - if ((r = q) >= p) - s + r = q; + if (r >= p) + s systemd-229/coccinelle/safe_close-no-if.cocci000066400000000000000000000001301265713322000212660ustar00rootroot00000000000000@@ expression fd; @@ - if (fd >= 0) { - fd = safe_close(fd); - } + fd = safe_close(fd); systemd-229/coccinelle/safe_close.cocci000066400000000000000000000003301265713322000202620ustar00rootroot00000000000000@@ expression fd; @@ - close(fd); - fd = -1; + fd = safe_close(fd); @@ expression fd; @@ - close_nointr(fd); - fd = -1; + fd = safe_close(fd); @@ expression fd; @@ - safe_close(fd); - fd = -1; + fd = safe_close(fd); systemd-229/coccinelle/safe_closedir.cocci000066400000000000000000000005151265713322000207660ustar00rootroot00000000000000@@ expression p; @@ - if (p) { - closedir(p); - p = NULL; - } + p = safe_closedir(p); @@ expression p; @@ - if (p) - closedir(p); - p = NULL; + p = safe_closedir(p); @@ expression p; @@ - closedir(p); - p = NULL; + p = safe_closedir(p); @@ expression p; @@ - if (p) - closedir(p); + safe_closedir(p); systemd-229/coccinelle/safe_fclose.cocci000066400000000000000000000004751265713322000204420ustar00rootroot00000000000000@@ expression p; @@ - if (p) { - fclose(p); - p = NULL; - } + p = safe_fclose(p); @@ expression p; @@ - if (p) - fclose(p); - p = NULL; + p = safe_fclose(p); @@ expression p; @@ - fclose(p); - p = NULL; + p = safe_fclose(p); @@ expression p; @@ - if (p) - fclose(p); + safe_fclose(p); systemd-229/coccinelle/strempty.cocci000066400000000000000000000001331265713322000200470ustar00rootroot00000000000000@@ expression s; @@ - s ?: "" + strempty(s) @@ expression s; @@ - s ? s : "" + strempty(s) systemd-229/coccinelle/strv_free.cocci000066400000000000000000000005011265713322000201560ustar00rootroot00000000000000@@ expression p; @@ - strv_free(p); - p = NULL; + p = strv_free(p); @@ expression p; @@ - if (p) - strv_free(p); - p = NULL; + p = strv_free(p); @@ expression p; @@ - if (p) { - strv_free(p); - p = NULL; - } + p = strv_free(p); @@ expression p; @@ - if (p) - strv_free(p); + strv_free(p); systemd-229/coccinelle/while-true.cocci000066400000000000000000000001331265713322000202450ustar00rootroot00000000000000@@ statement s; @@ - while (true) + for (;;) s @@ statement s; @@ - while (1) + for (;;) s systemd-229/coccinelle/xsprintf.cocci000066400000000000000000000001641265713322000200410ustar00rootroot00000000000000@@ expression e, fmt; expression list vaargs; @@ - snprintf(e, sizeof(e), fmt, vaargs); + xsprintf(e, fmt, vaargs); systemd-229/configure.ac000066400000000000000000002021221265713322000153460ustar00rootroot00000000000000# # This file is part of systemd. # # Copyright 2010-2012 Lennart Poettering # Copyright 2010-2012 Kay Sievers # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . AC_PREREQ([2.64]) AC_INIT([systemd], [229], [http://github.com/systemd/systemd/issues], [systemd], [http://www.freedesktop.org/wiki/Software/systemd]) AC_CONFIG_SRCDIR([src/core/main.c]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_AUX_DIR([build-aux]) AC_USE_SYSTEM_EXTENSIONS AC_SYS_LARGEFILE AC_PREFIX_DEFAULT([/usr]) AM_MAINTAINER_MODE([enable]) AM_INIT_AUTOMAKE([foreign 1.11 -Wall -Wno-portability silent-rules tar-pax no-dist-gzip dist-xz subdir-objects parallel-tests]) AM_SILENT_RULES([yes]) AC_CANONICAL_HOST AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.]) AC_PROG_CC_C99 AX_COMPILER_VENDOR AS_IF([test "x$ax_cv_c_compiler_vendor" = "xgnu"], [ AC_CHECK_TOOLS([AR], [gcc-ar ar], [:]) AC_CHECK_TOOLS([NM], [gcc-nm nm], [:]) AC_CHECK_TOOLS([RANLIB], [gcc-ranlib ranlib], [:]) ]) LT_PREREQ(2.2) LT_INIT([disable-static]) AS_IF([test "x$enable_static" = "xyes"], [AC_MSG_ERROR([--enable-static is not supported by systemd])]) AS_IF([test "x$enable_largefile" = "xno"], [AC_MSG_ERROR([--disable-largefile is not supported by systemd])]) SET_ARCH(X86_64, x86_64*) SET_ARCH(IA32, i*86*) SET_ARCH(MIPS, mips*) SET_ARCH(AARCH64, aarch64*) # i18n stuff for the PolicyKit policy files, heck whether intltool can be found, disable NLS otherwise AC_CHECK_PROG(intltool_found, [intltool-merge], [yes], [no]) AS_IF([test x"$intltool_found" != xyes], [AS_IF([test x"$enable_nls" = xyes], [AC_MSG_ERROR([--enable-nls requested but intltool not found])], [AS_IF([test x"$enable_nls" != xno], [AC_MSG_WARN([*** Disabling NLS support because intltool was not found]) enable_nls=no]) ]) ]) AM_NLS AS_IF([test x"$enable_nls" != xno -o "x$enable_polkit" != xno], [ # intltoolize greps for '^(AC|IT)_PROG_INTLTOOL', so it needs to be on its own line IT_PROG_INTLTOOL([0.40.0]) ]) AS_IF([test -z "$INTLTOOL_POLICY_RULE"], [ # If intltool is not available, provide a dummy rule to fail generation of %.policy files with a meaningful error message INTLTOOL_POLICY_RULE='%.policy: %.policy.in ; @echo " ITMRG " $@ && echo "*** intltool support required to build target $@" && false' AC_SUBST(INTLTOOL_POLICY_RULE) ]) GETTEXT_PACKAGE=systemd AC_SUBST(GETTEXT_PACKAGE) AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [systemd]) AC_PROG_MKDIR_P AC_PROG_LN_S AC_PROG_SED AC_PROG_GREP AC_PROG_AWK AC_PATH_PROG([M4], [m4]) AC_PATH_PROG([QUOTAON], [quotaon], [/usr/sbin/quotaon], [$PATH:/usr/sbin:/sbin]) AC_PATH_PROG([QUOTACHECK], [quotacheck], [/usr/sbin/quotacheck], [$PATH:/usr/sbin:/sbin]) AC_PATH_PROG([SETCAP], [setcap], [/usr/sbin/setcap], [$PATH:/usr/sbin:/sbin]) AC_PATH_PROG([KILL], [kill], [/usr/bin/kill], [$PATH:/usr/sbin:/sbin]) AC_PATH_PROG([KMOD], [kmod], [/usr/bin/kmod], [$PATH:/usr/sbin:/sbin]) AC_PATH_PROG([KEXEC], [kexec], [/usr/sbin/kexec], [$PATH:/usr/sbin:/sbin]) AC_PATH_PROG([SULOGIN], [sulogin], [/usr/sbin/sulogin], [$PATH:/usr/sbin:/sbin]) AC_PATH_PROG([MOUNT_PATH], [mount], [/usr/bin/mount], [$PATH:/usr/sbin:/sbin]) AC_PATH_PROG([UMOUNT_PATH], [umount], [/usr/bin/umount], [$PATH:/usr/sbin:/sbin]) AS_IF([! ln --relative --help > /dev/null 2>&1], [AC_MSG_ERROR([*** ln doesn't support --relative ***])]) M4_DEFINES= AC_CHECK_TOOL(OBJCOPY, objcopy) AC_CHECK_TOOL(STRINGS, strings) AC_CHECK_TOOL(GPERF, gperf) if test -z "$GPERF" ; then AC_MSG_ERROR([*** gperf not found]) fi # ------------------------------------------------------------------------------ address_sanitizer_cflags= address_sanitizer_cppflags= address_sanitizer_ldflags= AC_ARG_ENABLE(address-sanitizer, AS_HELP_STRING([--enable-address-sanitizer], [enable -fsanitize=address])) AS_IF([test "x$enable_address_sanitizer" = "xyes"], [ CC_CHECK_FLAG_APPEND([with_as_cflags], [CFLAGS], [-fsanitize=address]) AS_IF([test -z "$with_as_cflags"], [AC_MSG_ERROR([*** -fsanitize=address is not supported])]) address_sanitizer_cflags="$with_as_cflags -fno-omit-frame-pointer -DVALGRIND=1" address_sanitizer_cppflags="-DVALGRIND=1" address_sanitizer_ldflags="-Wc,-fsanitize=address" ]) undefined_sanitizer_cflags= undefined_sanitizer_cppflags= undefined_sanitizer_ldflags= AC_ARG_ENABLE(undefined-sanitizer, AS_HELP_STRING([--enable-undefined-sanitizer], [enable -fsanitize=undefined])) AS_IF([test "x$enable_undefined_sanitizer" = "xyes"], [ CC_CHECK_FLAG_APPEND([with_us_cflags], [CFLAGS], [-fsanitize=undefined]) AS_IF([test -z "$with_us_cflags"], [AC_MSG_ERROR([*** -fsanitize=undefined is not supported])]) undefined_sanitizer_cflags="$with_us_cflags -fno-omit-frame-pointer -DVALGRIND=1" undefined_sanitizer_cppflags="-DVALGRIND=1" undefined_sanitizer_ldflags="-Wc,-fsanitize=undefined" ]) sanitizer_cflags="$address_sanitizer_cflags $undefined_sanitizer_cflags" sanitizer_cppflags="$address_sanitizer_cppflags $undefined_sanitizer_cppflags" sanitizer_ldflags="$address_sanitizer_ldflags $undefined_sanitizer_ldflags" CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\ -pipe \ -Wall \ -Wextra \ -Wundef \ "-Wformat=2 -Wformat-security -Wformat-nonliteral" \ -Wlogical-op \ -Wmissing-include-dirs \ -Wold-style-definition \ -Wpointer-arith \ -Winit-self \ -Wdeclaration-after-statement \ -Wfloat-equal \ -Wsuggest-attribute=noreturn \ -Werror=missing-prototypes \ -Werror=implicit-function-declaration \ -Werror=missing-declarations \ -Werror=return-type \ -Wstrict-prototypes \ -Wredundant-decls \ -Wmissing-noreturn \ -Wshadow \ -Wendif-labels \ -Wstrict-aliasing=2 \ -Wwrite-strings \ -Wno-unused-parameter \ -Wno-missing-field-initializers \ -Wno-unused-result \ -Wno-format-signedness \ -Werror=overflow \ -Wdate-time \ -Wnested-externs \ -ffast-math \ -fno-common \ -fdiagnostics-show-option \ -fno-strict-aliasing \ -fvisibility=hidden \ -fstack-protector \ -fstack-protector-strong \ -fPIE \ --param=ssp-buffer-size=4]) CC_CHECK_FLAG_APPEND([with_cflags], [CFLAGS], [-Werror=shadow], [ #include #include typedef uint64_t usec_t; usec_t now(clockid_t clock); int main(void) { struct timespec now; return 0; } ]) AS_CASE([$CC], [*clang*], [CC_CHECK_FLAGS_APPEND([with_cppflags], [CPPFLAGS], [\ -Wno-typedef-redefinition \ -Wno-gnu-variable-sized-type-not-at-end \ ])]) AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*], [CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\ -flto])], [AC_MSG_RESULT([skipping -flto, optimization not enabled])]) AC_SUBST([OUR_CFLAGS], "$with_cflags $sanitizer_cflags") AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*], [CC_CHECK_FLAGS_APPEND([with_cppflags], [CPPFLAGS], [\ -Wp,-D_FORTIFY_SOURCE=2])], [AC_MSG_RESULT([skipping -D_FORTIFY_SOURCE, optimization not enabled])]) AC_SUBST([OUR_CPPFLAGS], "$with_cppflags $sanitizer_cppflags") AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*], [CC_CHECK_FLAGS_APPEND([with_ldflags], [LDFLAGS], [\ -Wl,--gc-sections])], [AC_MSG_RESULT([skipping --gc-sections, optimization not enabled])]) AC_SUBST([OUR_CFLAGS], "$with_ldflags $sanitizer_cflags") AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*], [CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\ -ffunction-sections -fdata-sections])], [AC_MSG_RESULT([skipping -ffunction/data-section, optimization not enabled])]) AC_SUBST([OUR_CFLAGS], "$with_cflags $sanitizer_cflags") CC_CHECK_FLAGS_APPEND([with_ldflags], [LDFLAGS], [\ -Wl,--as-needed \ -Wl,--no-undefined \ -Wl,-z,relro \ -Wl,-z,now \ -pie \ -Wl,-fuse-ld=gold]) AC_SUBST([OUR_LDFLAGS], "$with_ldflags $sanitizer_ldflags") AC_CHECK_SIZEOF(pid_t) AC_CHECK_SIZEOF(uid_t) AC_CHECK_SIZEOF(gid_t) AC_CHECK_SIZEOF(time_t) AC_CHECK_SIZEOF(dev_t) AC_CHECK_SIZEOF(rlim_t,,[ #include #include ]) # ------------------------------------------------------------------------------ # we use python to build the man page index have_python=no AC_ARG_WITH([python], [AS_HELP_STRING([--without-python], [Disable building the man page index and systemd-python (default: test)])]) have_lxml=no AS_IF([test "x$with_python" != "xno"], [ AM_PATH_PYTHON(,, [:]) AS_IF([test "x$PYTHON" != "x:"], [ AC_MSG_CHECKING([for python lxml module]) AS_IF(["$PYTHON" -c 'import lxml' 2>/dev/null], [have_lxml=yes]) AC_MSG_RESULT([$have_lxml]) AS_IF([test "x$have_lxml" = "xyes"], [have_python=yes], [AC_MSG_WARN([*** python support requires python-lxml module installed])]) ]) ]) AS_IF([test "$have_python" != "yes"], [ AS_IF([test "$with_python" = "yes"], [AC_MSG_ERROR([*** python support requested but python support not found])]) AS_IF([test "$with_python" != "no"], [AC_MSG_WARN([*** python support not found, some documentation cannot be built])]) ]) AM_CONDITIONAL([HAVE_PYTHON], [test "x$have_python" = "xyes"]) # ------------------------------------------------------------------------------ AC_CHECK_HEADERS([sys/capability.h], [], [AC_MSG_ERROR([*** POSIX caps headers not found])]) AC_CHECK_HEADERS([linux/btrfs.h], [], []) AC_CHECK_HEADERS([linux/memfd.h], [], []) # unconditionally pull-in librt with old glibc versions AC_SEARCH_LIBS([clock_gettime], [rt], [], []) save_LIBS="$LIBS" LIBS= AC_SEARCH_LIBS([cap_init], [cap], [], [AC_MSG_ERROR([*** POSIX caps library not found])]) CAP_LIBS="$LIBS" LIBS="$save_LIBS" AC_SUBST(CAP_LIBS) AC_CHECK_FUNCS([memfd_create]) AC_CHECK_FUNCS([__secure_getenv secure_getenv]) AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at, setns, getrandom, renameat2, kcmp, keyctl, key_serial_t, char16_t, char32_t, LO_FLAGS_PARTSCAN], [], [], [[ #include #include #include #include #include #include #include ]]) AC_CHECK_DECLS([IFLA_INET6_ADDR_GEN_MODE, IFLA_MACVLAN_FLAGS, IFLA_IPVLAN_MODE, IFLA_VTI_REMOTE, IFLA_PHYS_PORT_ID, IFLA_BOND_AD_INFO, IFLA_VLAN_PROTOCOL, IFLA_VXLAN_REMCSUM_NOPARTIAL, IFLA_IPTUN_ENCAP_DPORT, IFLA_GRE_ENCAP_DPORT, IFLA_BRIDGE_VLAN_INFO, IFLA_BRPORT_LEARNING_SYNC, IFLA_BR_PRIORITY, NDA_IFINDEX, IFA_FLAGS], [], [], [[ #include #include #include #include #include #include #include #include #include #include #include ]]) # This makes sure pkg.m4 is available. m4_pattern_forbid([^_?PKG_[A-Z_]+$],[*** pkg.m4 missing, please install pkg-config]) # ------------------------------------------------------------------------------ have_dbus=no AC_ARG_ENABLE(dbus, AS_HELP_STRING([--disable-dbus], [disable usage of dbus-1 in tests])) AS_IF([test "x$enable_dbus" != "xno"], [ PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.3.2], [AC_DEFINE(HAVE_DBUS, 1, [Define if dbus-1 library is available]) have_dbus=yes], [have_dbus=no]) AS_IF([test "x$have_dbus" = "xno" -a "x$enable_dbus" = "xyes"], [AC_MSG_ERROR([*** dbus-1 support requested but libraries not found])])]) AM_CONDITIONAL(HAVE_DBUS, [test "$have_dbus" = "yes"]) # ------------------------------------------------------------------------------ have_utmp=yes AC_ARG_ENABLE([utmp], AS_HELP_STRING([--disable-utmp], [disable utmp/wtmp log handling]), AS_CASE("x${enableval}", [xyes], [have_utmp=yes], [xno], [have_utmp=no], AC_MSG_ERROR(bad value ${enableval} for --enable-utmp))) AS_IF([test "x$have_utmp" = "xyes"], [AC_DEFINE(HAVE_UTMP, 1, [Define if utmp/wtmp support is enabled])]) AM_CONDITIONAL([HAVE_UTMP], [test "x$have_utmp" = "xyes"]) # ------------------------------------------------------------------------------ have_compat_libs=no AC_ARG_ENABLE([compat_libs], AS_HELP_STRING([--enable-compat-libs],[Enable creation of compatibility libraries]), [case "${enableval}" in yes) have_compat_libs=yes ;; no) have_compat_libs=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-compat-libs) ;; esac], [have_compat_libs=no]) AM_CONDITIONAL([ENABLE_COMPAT_LIBS], [test "$have_compat_libs" = "yes"]) # ------------------------------------------------------------------------------ have_coverage=no AC_ARG_ENABLE(coverage, AS_HELP_STRING([--enable-coverage], [enable test coverage])) if test "x$enable_coverage" = "xyes" ; then AC_CHECK_PROG(lcov_found, [lcov], [yes], [no]) if test "x$lcov_found" = xno ; then AC_MSG_ERROR([*** lcov support requested but the program was not found]) else lcov_version_major="`lcov --version | cut -d ' ' -f 4 | cut -d '.' -f 1`" lcov_version_minor="`lcov --version | cut -d ' ' -f 4 | cut -d '.' -f 2`" if test "$lcov_version_major" -eq 1 -a "$lcov_version_minor" -lt 10; then AC_MSG_ERROR([*** lcov version is too old. 1.10 required]) else have_coverage=yes CC_CHECK_FLAGS_APPEND([with_coverage_cflags], [CFLAGS], [\ -fprofile-arcs \ -ftest-coverage]) AC_SUBST([OUR_CFLAGS], "$with_cflags $with_coverage_cflags") fi fi fi AM_CONDITIONAL(ENABLE_COVERAGE, [test "$have_coverage" = "yes"]) # ------------------------------------------------------------------------------ have_kmod=no AC_ARG_ENABLE(kmod, AS_HELP_STRING([--disable-kmod], [disable loadable modules support])) if test "x$enable_kmod" != "xno"; then PKG_CHECK_EXISTS([ libkmod ], have_kmod=yes, have_kmod=no) if test "x$have_kmod" = "xyes"; then PKG_CHECK_MODULES(KMOD, [ libkmod >= 15 ], [AC_DEFINE(HAVE_KMOD, 1, [Define if kmod is available])], AC_MSG_ERROR([*** kmod version >= 15 not found])) fi if test "x$have_kmod" = xno -a "x$enable_kmod" = xyes; then AC_MSG_ERROR([*** kmod support requested, but libraries not found]) fi fi AM_CONDITIONAL(HAVE_KMOD, [test "$have_kmod" = "yes"]) # ------------------------------------------------------------------------------ have_xkbcommon=no AC_ARG_ENABLE(xkbcommon, AS_HELP_STRING([--disable-xkbcommon], [disable xkbcommon keymap support])) if test "x$enable_xkbcommon" != "xno"; then PKG_CHECK_MODULES(XKBCOMMON, [ xkbcommon >= 0.3.0 ], [AC_DEFINE(HAVE_XKBCOMMON, 1, [Define if libxkbcommon is available]) have_xkbcommon=yes], have_xkbcommon=no) if test "x$have_xkbcommon" = xno -a "x$enable_xkbcommon" = xyes; then AC_MSG_ERROR([*** xkbcommon support requested but libraries not found]) fi fi AM_CONDITIONAL(HAVE_XKBCOMMON, [test "$have_xkbcommon" = "yes"]) # ------------------------------------------------------------------------------ have_blkid=no AC_ARG_ENABLE(blkid, AS_HELP_STRING([--disable-blkid], [disable blkid support])) if test "x$enable_blkid" != "xno"; then PKG_CHECK_MODULES(BLKID, [ blkid >= 2.24 ], [AC_DEFINE(HAVE_BLKID, 1, [Define if blkid is available]) have_blkid=yes], have_blkid=no) if test "x$have_blkid" = xno -a "x$enable_blkid" = xyes; then AC_MSG_ERROR([*** blkid support requested but libraries not found]) fi fi AM_CONDITIONAL(HAVE_BLKID, [test "$have_blkid" = "yes"]) # ------------------------------------------------------------------------------ have_libmount=no PKG_CHECK_MODULES(MOUNT, [ mount >= 2.27 ], [AC_DEFINE(HAVE_LIBMOUNT, 1, [Define if libmount is available]) have_libmount=yes], have_libmount=no) if test "x$have_libmount" = xno; then AC_MSG_ERROR([*** libmount support required but libraries not found]) fi AM_CONDITIONAL(HAVE_LIBMOUNT, [test "$have_libmount" = "yes"]) # ------------------------------------------------------------------------------ have_seccomp=no AC_ARG_ENABLE(seccomp, AS_HELP_STRING([--disable-seccomp], [Disable optional SECCOMP support])) if test "x$enable_seccomp" != "xno"; then PKG_CHECK_MODULES(SECCOMP, [libseccomp >= 1.0.0], [AC_DEFINE(HAVE_SECCOMP, 1, [Define if seccomp is available]) have_seccomp=yes M4_DEFINES="$M4_DEFINES -DHAVE_SECCOMP"], [have_seccomp=no]) if test "x$have_seccomp" = "xno" -a "x$enable_seccomp" = "xyes"; then AC_MSG_ERROR([*** seccomp support requested but libraries not found]) fi fi AM_CONDITIONAL(HAVE_SECCOMP, [test "$have_seccomp" = "yes"]) # ------------------------------------------------------------------------------ have_ima=yes AC_ARG_ENABLE([ima], AS_HELP_STRING([--disable-ima],[Disable optional IMA support]), [case "${enableval}" in yes) have_ima=yes ;; no) have_ima=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-ima) ;; esac], [have_ima=yes]) if test "x${have_ima}" != xno ; then AC_DEFINE(HAVE_IMA, 1, [Define if IMA is available]) fi # ------------------------------------------------------------------------------ have_selinux=no AC_ARG_ENABLE(selinux, AS_HELP_STRING([--disable-selinux], [Disable optional SELINUX support])) if test "x$enable_selinux" != "xno"; then PKG_CHECK_MODULES([SELINUX], [libselinux >= 2.1.9], [AC_DEFINE(HAVE_SELINUX, 1, [Define if SELinux is available]) have_selinux=yes M4_DEFINES="$M4_DEFINES -DHAVE_SELINUX"], [have_selinux=no]) if test "x$have_selinux" = xno -a "x$enable_selinux" = xyes; then AC_MSG_ERROR([*** SELinux support requested but libraries not found]) fi fi AM_CONDITIONAL(HAVE_SELINUX, [test "$have_selinux" = "yes"]) have_apparmor=no AC_ARG_ENABLE(apparmor, AS_HELP_STRING([--disable-apparmor], [Disable optional AppArmor support])) if test "x$enable_apparmor" != "xno"; then PKG_CHECK_MODULES([APPARMOR], [libapparmor], [AC_DEFINE(HAVE_APPARMOR, 1, [Define if AppArmor is available]) have_apparmor=yes M4_DEFINES="$M4_DEFINES -DHAVE_APPARMOR"], [have_apparmor=no]) if test "x$have_apparmor" = xno -a "x$enable_apparmor" = xyes; then AC_MSG_ERROR([*** AppArmor support requested but libraries not found]) fi fi AM_CONDITIONAL(HAVE_APPARMOR, [test "$have_apparmor" = "yes"]) AC_ARG_WITH(debug-shell, AS_HELP_STRING([--with-debug-shell=PATH], [Path to debug shell binary]), [SUSHELL="$withval"],[ AS_IF([test "x${have_selinux}" != "xno"], [SUSHELL="/sbin/sushell"] , [SUSHELL="/bin/sh"])]) AC_SUBST(SUSHELL) AC_ARG_WITH([debug-tty], AS_HELP_STRING([--with-debug-tty=PATH], [Specify the tty device for debug shell]), [DEBUGTTY="$withval"], [DEBUGTTY=/dev/tty9]) AC_SUBST(DEBUGTTY) AC_ARG_WITH([certificate-root], AS_HELP_STRING([--with-certificate-root=PATH], [Specify the prefix for TLS certificates [/etc/ssl]]), [CERTIFICATEROOT="$withval"], [CERTIFICATEROOT="/etc/ssl"]) AC_SUBST(CERTIFICATEROOT) # ------------------------------------------------------------------------------ have_xz=no AC_ARG_ENABLE(xz, AS_HELP_STRING([--disable-xz], [Disable optional XZ support])) AS_IF([test "x$enable_xz" != "xno"], [ PKG_CHECK_MODULES(XZ, [ liblzma ], [AC_DEFINE(HAVE_XZ, 1, [Define if XZ is available]) have_xz=yes], have_xz=no) AS_IF([test "x$have_xz" = xno -a "x$enable_xz" = xyes], [AC_MSG_ERROR([*** XZ support requested but libraries not found])]) ]) AM_CONDITIONAL(HAVE_XZ, [test "$have_xz" = "yes"]) # ------------------------------------------------------------------------------ have_zlib=no AC_ARG_ENABLE(zlib, AS_HELP_STRING([--disable-zlib], [Disable optional ZLIB support])) AS_IF([test "x$enable_zlib" != "xno"], [ PKG_CHECK_MODULES(ZLIB, [ zlib ], [AC_DEFINE(HAVE_ZLIB, 1, [Define if ZLIB is available]) have_zlib=yes], have_zlib=no) AS_IF([test "x$have_zlib" = xno -a "x$enable_zlib" = xyes], [AC_MSG_ERROR([*** ZLIB support requested but libraries not found])]) ]) AM_CONDITIONAL(HAVE_ZLIB, [test "$have_zlib" = "yes"]) # ------------------------------------------------------------------------------ have_bzip2=no AC_ARG_ENABLE(bzip2, AS_HELP_STRING([--enable-bzip2], [Enable optional BZIP2 support])) AS_IF([test "x$enable_bzip2" != "xno"], [ AC_CHECK_HEADERS(bzlib.h, [AC_DEFINE(HAVE_BZIP2, 1, [Define if BZIP2 is available]) have_bzip2=yes], [AS_IF([test "x$enable_bzip2" = xyes], [AC_MSG_ERROR([*** BZIP2 support requested but headers not found])])] ) ]) AM_CONDITIONAL(HAVE_BZIP2, [test "$have_bzip2" = "yes"]) # ------------------------------------------------------------------------------ have_lz4=no AC_ARG_ENABLE(lz4, AS_HELP_STRING([--disable-lz4], [Disable optional LZ4 support])) AS_IF([test "x$enable_lz4" != "xno"], [ PKG_CHECK_MODULES(LZ4, [ liblz4 >= 125 ], [AC_DEFINE(HAVE_LZ4, 1, [Define in LZ4 is available]) have_lz4=yes], have_lz4=no) AS_IF([test "x$have_lz4" = xno -a "x$enable_lz4" = xyes], [AC_MSG_ERROR([*** LZ4 support requested but libraries not found])]) ]) AM_CONDITIONAL(HAVE_LZ4, [test "$have_lz4" = "yes"]) AM_CONDITIONAL(HAVE_COMPRESSION, [test "$have_xz" = "yes" -o "$have_lz4" = "yes"]) # ------------------------------------------------------------------------------ AC_ARG_ENABLE([pam], AS_HELP_STRING([--disable-pam],[Disable optional PAM support]), [case "${enableval}" in yes) have_pam=yes ;; no) have_pam=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-pam) ;; esac], [have_pam=auto]) if test "x${have_pam}" != xno ; then AC_CHECK_HEADERS( [security/pam_modules.h security/pam_modutil.h security/pam_ext.h], [have_pam=yes], [if test "x$have_pam" = xyes ; then AC_MSG_ERROR([*** PAM headers not found.]) fi]) AC_CHECK_LIB( [pam], [pam_syslog], [have_pam=yes], [if test "x$have_pam" = xyes ; then AC_MSG_ERROR([*** libpam not found.]) fi]) if test "x$have_pam" = xyes ; then PAM_LIBS="-lpam -lpam_misc" AC_DEFINE(HAVE_PAM, 1, [PAM available]) M4_DEFINES="$M4_DEFINES -DHAVE_PAM" else have_pam=no fi else PAM_LIBS= fi AC_SUBST(PAM_LIBS) AM_CONDITIONAL([HAVE_PAM], [test "x$have_pam" != xno]) # ------------------------------------------------------------------------------ AC_ARG_ENABLE([acl], AS_HELP_STRING([--disable-acl],[Disable optional ACL support]), [case "${enableval}" in yes) have_acl=yes ;; no) have_acl=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-acl) ;; esac], [have_acl=auto]) if test "x${have_acl}" != xno ; then AC_CHECK_HEADERS( [sys/acl.h acl/libacl.h], [have_acl=yes], [if test "x$have_acl" = xyes ; then AC_MSG_ERROR([*** ACL headers not found.]) fi]) AC_CHECK_LIB( [acl], [acl_get_file], [have_acl=yes], [if test "x$have_acl" = xyes ; then AC_MSG_ERROR([*** libacl not found.]) fi]) if test "x$have_acl" = xyes ; then ACL_LIBS="-lacl" AC_DEFINE(HAVE_ACL, 1, [ACL available]) M4_DEFINES="$M4_DEFINES -DHAVE_ACL" else have_acl=no fi else ACL_LIBS= fi AC_SUBST(ACL_LIBS) AM_CONDITIONAL([HAVE_ACL], [test "x$have_acl" != xno]) # ------------------------------------------------------------------------------ AC_ARG_ENABLE([smack], AS_HELP_STRING([--disable-smack],[Disable optional SMACK support]), [case "${enableval}" in yes) have_smack=yes ;; no) have_smack=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-smack) ;; esac], [have_smack=auto]) if test "x${have_smack}" != xno; then AC_DEFINE(HAVE_SMACK, 1, [Define if SMACK is available]) M4_DEFINES="$M4_DEFINES -DHAVE_SMACK" have_smack=yes fi AM_CONDITIONAL([HAVE_SMACK], [test "x$have_smack" = "xyes"]) have_smack_run_label=no AC_ARG_WITH(smack-run-label, AS_HELP_STRING([--with-smack-run-label=STRING], [run systemd --system itself with a specific SMACK label]), [AC_DEFINE_UNQUOTED(SMACK_RUN_LABEL, ["$withval"], [Run systemd itself with SMACK label]) have_smack_run_label=yes], []) if test "x${have_smack_run_label}" = xyes; then M4_DEFINES="$M4_DEFINES -DHAVE_SMACK_RUN_LABEL" fi AC_ARG_WITH(smack-default-process-label, AS_HELP_STRING([--with-smack-default-process-label=STRING], [default SMACK label for executed processes]), [AC_DEFINE_UNQUOTED(SMACK_DEFAULT_PROCESS_LABEL, ["$withval"], [Default SMACK label for executed processes])], []) # ------------------------------------------------------------------------------ AC_ARG_ENABLE([gcrypt], AS_HELP_STRING([--disable-gcrypt],[Disable optional GCRYPT support]), [case "${enableval}" in yes) have_gcrypt=yes ;; no) have_gcrypt=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-gcrypt) ;; esac], [have_gcrypt=auto]) if test "x${have_gcrypt}" != xno ; then m4_define([AM_PATH_LIBGCRYPT_FAIL], [{ test "x$have_gcrypt" != xyes || AC_MSG_ERROR([*** GCRYPT/GPG-ERROR headers not found.]); }] ) m4_ifdef([AM_PATH_LIBGCRYPT], [AM_PATH_LIBGCRYPT( [1.4.5], [have_gcrypt=yes], dnl If we have the gcrypt m4 macros, but don't have dnl gcrypt, throw an error if gcrypt is explicitly dnl requested. [AM_PATH_LIBGCRYPT_FAIL] )], dnl If we don't have the gcrypt m4 macros, but build with dnl gcrypt explicitly requested, throw an error. [AM_PATH_LIBGCRYPT_FAIL] ) have_gpg_error=no m4_ifdef([AM_PATH_GPG_ERROR], [AM_PATH_GPG_ERROR( [1.12], [have_gpg_error=yes], [AM_PATH_LIBGCRYPT_FAIL] )], [AM_PATH_LIBGCRYPT_FAIL] ) if test "x$have_gcrypt" = xyes -a "x$have_gpg_error" = xyes ; then GCRYPT_LIBS="$LIBGCRYPT_LIBS $GPG_ERROR_LIBS" GCRYPT_CFLAGS="$LIBGCRYPT_CFLAGS $GPG_ERROR_CFLAGS" AC_DEFINE(HAVE_GCRYPT, 1, [GCRYPT available]) else have_gcrypt=no have_gpg_error=no fi else GCRYPT_LIBS= GCRYPT_CFLAGS= fi AC_SUBST(GCRYPT_LIBS) AC_SUBST(GCRYPT_CFLAGS) AM_CONDITIONAL([HAVE_GCRYPT], [test "x$have_gcrypt" != xno]) # ------------------------------------------------------------------------------ AC_ARG_ENABLE([audit], AS_HELP_STRING([--disable-audit],[Disable optional AUDIT support]), [case "${enableval}" in yes) have_audit=yes ;; no) have_audit=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-audit) ;; esac], [have_audit=auto]) if test "x${have_audit}" != xno ; then AC_CHECK_HEADERS( [libaudit.h], [have_audit=yes], [if test "x$have_audit" = xyes ; then AC_MSG_ERROR([*** AUDIT headers not found.]) fi]) AC_CHECK_LIB( [audit], [audit_open], [have_audit=yes], [if test "x$have_audit" = xyes ; then AC_MSG_ERROR([*** libaudit not found.]) fi]) if test "x$have_audit" = xyes ; then AUDIT_LIBS="-laudit" AC_DEFINE(HAVE_AUDIT, 1, [AUDIT available]) else have_audit=no fi else AUDIT_LIBS= fi AC_SUBST(AUDIT_LIBS) AM_CONDITIONAL([HAVE_AUDIT], [test "x$have_audit" != xno]) # ------------------------------------------------------------------------------ AC_ARG_ENABLE([elfutils], AS_HELP_STRING([--disable-elfutils],[Disable optional ELFUTILS support]), [case "${enableval}" in yes) have_elfutils=yes ;; no) have_elfutils=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-elfutils) ;; esac], [have_elfutils=auto]) if test "x${have_elfutils}" != xno ; then AC_CHECK_HEADERS( [elfutils/libdwfl.h], [], [if test "x$have_elfutils" = xyes ; then AC_MSG_ERROR([*** ELFUTILS headers not found.]) fi]) AC_CHECK_LIB( [dw], [dwfl_core_file_attach], [have_elfutils=yes], [if test "x$have_elfutils" = xyes ; then AC_MSG_ERROR([*** ELFUTILS >= 158 is required.]) fi]) if test "x$have_elfutils" = xyes ; then ELFUTILS_LIBS="-lelf -ldw" AC_DEFINE(HAVE_ELFUTILS, 1, [ELFUTILS available]) else have_elfutils=no fi else ELFUTILS_LIBS= fi AC_SUBST(ELFUTILS_LIBS) AM_CONDITIONAL(HAVE_ELFUTILS, [test "$have_elfutils" = "yes"]) # ------------------------------------------------------------------------------ have_libcryptsetup=no AC_ARG_ENABLE(libcryptsetup, AS_HELP_STRING([--disable-libcryptsetup], [disable libcryptsetup tools])) if test "x$enable_libcryptsetup" != "xno"; then PKG_CHECK_MODULES(LIBCRYPTSETUP, [ libcryptsetup >= 1.6.0 ], [AC_DEFINE(HAVE_LIBCRYPTSETUP, 1, [Define if libcryptsetup is available]) have_libcryptsetup=yes], have_libcryptsetup=no) if test "x$have_libcryptsetup" = xno -a "x$enable_libcryptsetup" = xyes; then AC_MSG_ERROR([*** libcryptsetup support requested but libraries not found]) fi fi AM_CONDITIONAL(HAVE_LIBCRYPTSETUP, [test "$have_libcryptsetup" = "yes"]) # ------------------------------------------------------------------------------ have_qrencode=no AC_ARG_ENABLE(qrencode, AS_HELP_STRING([--disable-qrencode], [disable qrencode support])) if test "x$enable_qrencode" != "xno"; then PKG_CHECK_MODULES(QRENCODE, [ libqrencode ], [AC_DEFINE(HAVE_QRENCODE, 1, [Define if qrencode is available]) have_qrencode=yes], have_qrencode=no) if test "x$have_qrencode" = xno -a "x$enable_qrencode" = xyes; then AC_MSG_ERROR([*** qrencode support requested but libraries not found]) fi fi AM_CONDITIONAL(HAVE_QRENCODE, [test "$have_qrencode" = "yes"]) # ------------------------------------------------------------------------------ have_gnutls=no AC_ARG_ENABLE(gnutls, AS_HELP_STRING([--disable-gnutls], [disable gnutls support])) if test "x$enable_gnutls" != "xno"; then PKG_CHECK_MODULES(GNUTLS, [gnutls >= 3.1.4], [AC_DEFINE(HAVE_GNUTLS, 1, [Define if gnutls is available]) have_gnutls=yes], have_gnutls=no) if test "x$have_gnutls" = xno -a "x$enable_gnutls" = xyes; then AC_MSG_ERROR([*** gnutls support requested but libraries not found]) fi fi AM_CONDITIONAL(HAVE_GNUTLS, [test "$have_gnutls" = "yes"]) # ------------------------------------------------------------------------------ have_microhttpd=no AC_ARG_ENABLE(microhttpd, AS_HELP_STRING([--disable-microhttpd], [disable microhttpd support])) if test "x$enable_microhttpd" != "xno"; then PKG_CHECK_MODULES(MICROHTTPD, [libmicrohttpd >= 0.9.33], [AC_DEFINE(HAVE_MICROHTTPD, 1, [Define if microhttpd is available]) have_microhttpd=yes M4_DEFINES="$M4_DEFINES -DHAVE_MICROHTTPD"], [have_microhttpd=no]) if test "x$have_microhttpd" = xno -a "x$enable_microhttpd" = xyes; then AC_MSG_ERROR([*** microhttpd support requested but libraries not found]) fi fi AM_CONDITIONAL(HAVE_MICROHTTPD, [test "$have_microhttpd" = "yes"]) # ------------------------------------------------------------------------------ have_libcurl=no AC_ARG_ENABLE(libcurl, AS_HELP_STRING([--disable-libcurl], [disable libcurl support])) if test "x$enable_libcurl" != "xno"; then PKG_CHECK_MODULES(LIBCURL, [libcurl], [AC_DEFINE(HAVE_LIBCURL, 1, [Define if libcurl is available]) have_libcurl=yes M4_DEFINES="$M4_DEFINES -DHAVE_LIBCURL"], [have_libcurl=no]) if test "x$have_libcurl" = xno -a "x$enable_libcurl" = xyes; then AC_MSG_ERROR([*** libcurl support requested but libraries not found]) fi fi AM_CONDITIONAL(HAVE_LIBCURL, [test "$have_libcurl" = "yes"]) # ------------------------------------------------------------------------------ AM_CONDITIONAL(HAVE_REMOTE, [test "$have_microhttpd" = "yes" -o "$have_libcurl" = "yes"]) # ------------------------------------------------------------------------------ have_libidn=no AC_ARG_ENABLE(libidn, AS_HELP_STRING([--disable-libidn], [Disable optional LIBIDN support])) if test "x$enable_libidn" != "xno"; then PKG_CHECK_MODULES(LIBIDN, [libidn], [AC_DEFINE(HAVE_LIBIDN, 1, [Define if libidn is available]) have_libidn=yes M4_DEFINES="$M4_DEFINES -DHAVE_LIBIDN"], [have_libidn=no]) if test "x$have_libidn" = "xno" -a "x$enable_libidn" = "xyes"; then AC_MSG_ERROR([*** libidn support requested but libraries not found]) fi fi AM_CONDITIONAL(HAVE_LIBIDN, [test "$have_libidn" = "yes"]) # ------------------------------------------------------------------------------ have_libiptc=no AC_ARG_ENABLE(libiptc, AS_HELP_STRING([--disable-libiptc], [Disable optional LIBIPTC support])) if test "x$enable_libiptc" != "xno"; then PKG_CHECK_MODULES(LIBIPTC, [libiptc], [AC_DEFINE(HAVE_LIBIPTC, 1, [Define if libiptc is available]) have_libiptc=yes M4_DEFINES="$M4_DEFINES -DHAVE_LIBIPTC"], [have_libiptc=no]) if test "x$have_libiptc" = "xno" -a "x$enable_libiptc" = "xyes"; then AC_MSG_ERROR([*** libiptc support requested but libraries not found]) fi fi AM_CONDITIONAL(HAVE_LIBIPTC, [test "$have_libiptc" = "yes"]) # ------------------------------------------------------------------------------ have_binfmt=no AC_ARG_ENABLE(binfmt, AS_HELP_STRING([--disable-binfmt], [disable binfmt tool])) if test "x$enable_binfmt" != "xno"; then have_binfmt=yes fi AM_CONDITIONAL(ENABLE_BINFMT, [test "$have_binfmt" = "yes"]) # ------------------------------------------------------------------------------ have_vconsole=no AC_ARG_ENABLE(vconsole, AS_HELP_STRING([--disable-vconsole], [disable vconsole tool])) if test "x$enable_vconsole" != "xno"; then have_vconsole=yes fi AM_CONDITIONAL(ENABLE_VCONSOLE, [test "$have_vconsole" = "yes"]) # ------------------------------------------------------------------------------ have_bootchart=no AC_ARG_ENABLE(bootchart, AS_HELP_STRING([--disable-bootchart], [disable bootchart tool])) if test "x$enable_bootchart" != "xno"; then have_bootchart=yes fi AM_CONDITIONAL(ENABLE_BOOTCHART, [test "$have_bootchart" = "yes"]) # ------------------------------------------------------------------------------ have_quotacheck=no AC_ARG_ENABLE(quotacheck, AS_HELP_STRING([--disable-quotacheck], [disable quotacheck tools])) if test "x$enable_quotacheck" != "xno"; then have_quotacheck=yes fi AM_CONDITIONAL(ENABLE_QUOTACHECK, [test "$have_quotacheck" = "yes"]) # ------------------------------------------------------------------------------ have_tmpfiles=no AC_ARG_ENABLE(tmpfiles, AS_HELP_STRING([--disable-tmpfiles], [disable tmpfiles support])) if test "x$enable_tmpfiles" != "xno"; then have_tmpfiles=yes fi AM_CONDITIONAL(ENABLE_TMPFILES, [test "$have_tmpfiles" = "yes"]) # ------------------------------------------------------------------------------ have_sysusers=no AC_ARG_ENABLE(sysusers, AS_HELP_STRING([--disable-sysusers], [disable sysusers support])) if test "x$enable_sysusers" != "xno"; then have_sysusers=yes fi AM_CONDITIONAL(ENABLE_SYSUSERS, [test "$have_sysusers" = "yes"]) # ------------------------------------------------------------------------------ have_firstboot=no AC_ARG_ENABLE(firstboot, AS_HELP_STRING([--disable-firstboot], [disable firstboot support])) if test "x$enable_firstboot" != "xno"; then have_firstboot=yes fi AM_CONDITIONAL(ENABLE_FIRSTBOOT, [test "$have_firstboot" = "yes"]) # ------------------------------------------------------------------------------ have_randomseed=no AC_ARG_ENABLE(randomseed, AS_HELP_STRING([--disable-randomseed], [disable randomseed tools])) if test "x$enable_randomseed" != "xno"; then have_randomseed=yes fi AM_CONDITIONAL(ENABLE_RANDOMSEED, [test "$have_randomseed" = "yes"]) # ------------------------------------------------------------------------------ have_backlight=no AC_ARG_ENABLE(backlight, AS_HELP_STRING([--disable-backlight], [disable backlight tools])) if test "x$enable_backlight" != "xno"; then have_backlight=yes fi AM_CONDITIONAL(ENABLE_BACKLIGHT, [test "$have_backlight" = "yes"]) # ------------------------------------------------------------------------------ have_rfkill=no AC_ARG_ENABLE(rfkill, AS_HELP_STRING([--disable-rfkill], [disable rfkill tools])) if test "x$enable_rfkill" != "xno"; then have_rfkill=yes fi AM_CONDITIONAL(ENABLE_RFKILL, [test "$have_rfkill" = "yes"]) # ------------------------------------------------------------------------------ have_logind=no AC_ARG_ENABLE(logind, AS_HELP_STRING([--disable-logind], [disable login daemon])) if test "x$enable_logind" != "xno"; then have_logind=yes fi AM_CONDITIONAL(ENABLE_LOGIND, [test "$have_logind" = "yes"]) AS_IF([test "$have_logind" = "yes"], [ AC_DEFINE(HAVE_LOGIND, [1], [Logind support available]) ]) # ------------------------------------------------------------------------------ have_machined=no AC_ARG_ENABLE(machined, AS_HELP_STRING([--disable-machined], [disable machine daemon])) if test "x$enable_machined" != "xno"; then have_machined=yes fi AM_CONDITIONAL(ENABLE_MACHINED, [test "$have_machined" = "yes"]) AS_IF([test "$have_machined" = "yes"], [ AC_DEFINE(HAVE_MACHINED, [1], [Machined support available]) ]) # ------------------------------------------------------------------------------ have_importd=no AC_ARG_ENABLE(importd, AS_HELP_STRING([--disable-importd], [disable import daemon])) if test "x$enable_importd" != "xno"; then have_importd=yes fi AM_CONDITIONAL(ENABLE_IMPORTD, [test "$have_importd" = "yes"]) AS_IF([test "$have_importd" = "yes"], [ AC_DEFINE(HAVE_IMPORTD, [1], [Importd support available]) ]) # ------------------------------------------------------------------------------ have_hostnamed=no AC_ARG_ENABLE(hostnamed, AS_HELP_STRING([--disable-hostnamed], [disable hostname daemon])) if test "x$enable_hostnamed" != "xno"; then have_hostnamed=yes fi AM_CONDITIONAL(ENABLE_HOSTNAMED, [test "$have_hostnamed" = "yes"]) # ------------------------------------------------------------------------------ have_timedated=no AC_ARG_ENABLE(timedated, AS_HELP_STRING([--disable-timedated], [disable timedate daemon])) if test "x$enable_timedated" != "xno"; then have_timedated=yes fi AM_CONDITIONAL(ENABLE_TIMEDATED, [test "$have_timedated" = "yes"]) # ------------------------------------------------------------------------------ have_timesyncd=no AC_ARG_ENABLE(timesyncd, AS_HELP_STRING([--disable-timesyncd], [disable timesync daemon])) if test "x$enable_timesyncd" != "xno"; then have_timesyncd=yes M4_DEFINES="$M4_DEFINES -DENABLE_TIMESYNCD" fi AM_CONDITIONAL(ENABLE_TIMESYNCD, [test "$have_timesyncd" = "yes"]) AC_ARG_WITH(ntp-servers, AS_HELP_STRING([--with-ntp-servers=NTPSERVERS], [Space-separated list of default NTP servers]), [NTP_SERVERS="$withval"], [NTP_SERVERS="time1.google.com time2.google.com time3.google.com time4.google.com" AC_MSG_WARN([*** Using Google NTP servers. Do not ship OSes or devices with these default settings. See DISTRO_PORTING for details!])]) AC_DEFINE_UNQUOTED(NTP_SERVERS, ["$NTP_SERVERS"], [Default NTP Servers]) AC_SUBST(NTP_SERVERS) AC_ARG_WITH(time-epoch, AS_HELP_STRING([--with-time-epoch=SECONDS], [Time epoch for time clients]), [TIME_EPOCH="$withval"], [TIME_EPOCH="`stat -c %Y ${srcdir}/NEWS 2>/dev/null || echo 0`"]) AC_DEFINE_UNQUOTED(TIME_EPOCH, [$TIME_EPOCH], [Time Epoch]) # ------------------------------------------------------------------------------ AC_ARG_WITH(system-uid-max, AS_HELP_STRING([--with-system-uid-max=UID] [Maximum UID for system users]), [SYSTEM_UID_MAX="$withval"], [SYSTEM_UID_MAX="`awk 'BEGIN { uid=999 } /^\s*SYS_UID_MAX\s+/ { uid=$2 } END { print uid }' /etc/login.defs 2>/dev/null || echo 999`"]) AC_DEFINE_UNQUOTED(SYSTEM_UID_MAX, [$SYSTEM_UID_MAX], [Maximum System UID]) AC_SUBST(SYSTEM_UID_MAX) # ------------------------------------------------------------------------------ AC_ARG_WITH(system-gid-max, AS_HELP_STRING([--with-system-gid-max=GID] [Maximum GID for system groups]), [SYSTEM_GID_MAX="$withval"], [SYSTEM_GID_MAX="`awk 'BEGIN { gid=999 } /^\s*SYS_GID_MAX\s+/ { gid=$2 } END { print gid }' /etc/login.defs 2>/dev/null || echo 999`"]) AC_DEFINE_UNQUOTED(SYSTEM_GID_MAX, [$SYSTEM_GID_MAX], [Maximum System GID]) AC_SUBST(SYSTEM_GID_MAX) # ------------------------------------------------------------------------------ have_localed=no AC_ARG_ENABLE(localed, AS_HELP_STRING([--disable-localed], [disable locale daemon])) if test "x$enable_localed" != "xno"; then have_localed=yes fi AM_CONDITIONAL(ENABLE_LOCALED, [test "$have_localed" = "yes"]) # ------------------------------------------------------------------------------ have_coredump=no AC_ARG_ENABLE(coredump, AS_HELP_STRING([--disable-coredump], [disable coredump hook])) if test "x$enable_coredump" != "xno"; then have_coredump=yes M4_DEFINES="$M4_DEFINES -DENABLE_COREDUMP" fi AM_CONDITIONAL(ENABLE_COREDUMP, [test "$have_coredump" = "yes"]) # ------------------------------------------------------------------------------ have_polkit=no AC_ARG_ENABLE(polkit, AS_HELP_STRING([--disable-polkit], [disable PolicyKit support])) if test "x$enable_polkit" != "xno"; then AC_DEFINE(ENABLE_POLKIT, 1, [Define if PolicyKit support is to be enabled]) have_polkit=yes fi AM_CONDITIONAL(ENABLE_POLKIT, [test "x$have_polkit" = "xyes"]) # ------------------------------------------------------------------------------ have_resolved=no AC_ARG_ENABLE(resolved, AS_HELP_STRING([--disable-resolved], [disable resolve daemon])) AS_IF([test "x$enable_resolved" != "xno"], [ AC_CHECK_LIB([dl], [dlsym], [true], [AC_MSG_ERROR([*** Dynamic linking loader library not found])]) have_resolved=yes M4_DEFINES="$M4_DEFINES -DENABLE_RESOLVED" ]) AM_CONDITIONAL(ENABLE_RESOLVED, [test "$have_resolved" = "yes"]) AC_ARG_WITH(dns-servers, AS_HELP_STRING([--with-dns-servers=DNSSERVERS], [Space-separated list of default DNS servers]), [DNS_SERVERS="$withval"], [DNS_SERVERS="8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844"]) AC_DEFINE_UNQUOTED(DNS_SERVERS, ["$DNS_SERVERS"], [Default DNS Servers]) AC_SUBST(DNS_SERVERS) # ------------------------------------------------------------------------------ have_networkd=no AC_ARG_ENABLE(networkd, AS_HELP_STRING([--disable-networkd], [disable networkd])) AS_IF([test "x$enable_networkd" != "xno"], [ AC_DEFINE(ENABLE_NETWORKD, 1, [Define if networkd support is to be enabled]) have_networkd=yes M4_DEFINES="$M4_DEFINES -DENABLE_NETWORKD" ]) AM_CONDITIONAL(ENABLE_NETWORKD, [test "x$have_networkd" = "xyes"]) # ------------------------------------------------------------------------------ have_efi=no AC_ARG_ENABLE(efi, AS_HELP_STRING([--disable-efi], [disable EFI support])) if test "x$enable_efi" != "xno"; then AC_DEFINE(ENABLE_EFI, 1, [Define if EFI support is to be enabled]) have_efi=yes fi AM_CONDITIONAL(ENABLE_EFI, [test "x$have_efi" = "xyes"]) # ------------------------------------------------------------------------------ AC_CHECK_TOOL(EFI_CC, gcc) EFI_ARCH=`echo $host | sed "s/\(-\).*$//"` AM_COND_IF(ARCH_IA32, [ EFI_ARCH=ia32 EFI_MACHINE_TYPE_NAME=ia32]) AM_COND_IF(ARCH_X86_64, [ EFI_MACHINE_TYPE_NAME=x64]) AM_COND_IF(ARCH_AARCH64, [ EFI_MACHINE_TYPE_NAME=aa64]) AC_SUBST([EFI_ARCH]) AC_SUBST([EFI_MACHINE_TYPE_NAME]) have_gnuefi=no AC_ARG_ENABLE(gnuefi, AS_HELP_STRING([--enable-gnuefi], [Enable optional gnuefi support])) AS_IF([test "x$enable_gnuefi" != "xno"], [ AC_CHECK_HEADERS(efi/${EFI_ARCH}/efibind.h, [AC_DEFINE(HAVE_GNUEFI, 1, [Define if gnuefi is available]) have_gnuefi=yes], [AS_IF([test "x$enable_gnuefi" = xyes], [AC_MSG_ERROR([*** gnuefi support requested but headers not found])]) ]) efiroot=$(echo $(cd /usr/lib/$(${EFI_CC} -print-multi-os-directory); pwd)) EFI_LIB_DIR="$efiroot" AC_ARG_WITH(efi-libdir, AS_HELP_STRING([--with-efi-libdir=PATH], [Path to EFI lib directory]), [EFI_LIB_DIR="$withval"], [EFI_LIB_DIR="$efiroot"] ) AC_SUBST([EFI_LIB_DIR]) have_efi_lds=no AC_ARG_WITH(efi-ldsdir, AS_HELP_STRING([--with-efi-ldsdir=PATH], [Path to EFI lds directory]), [EFI_LDS_DIR="$withval" && AS_IF([test -f "${EFI_LDS_DIR}/elf_${EFI_ARCH}_efi.lds"], [have_efi_lds=yes])], [AS_FOR([DIR], [EFI_LDS_DIR], ["${EFI_LIB_DIR}/gnuefi" "${EFI_LIB_DIR}"], [AS_IF([test -f "${EFI_LDS_DIR}/elf_${EFI_ARCH}_efi.lds"], [have_efi_lds=yes && break])])]) AS_IF([test "x$have_efi_lds" = xyes], [AC_SUBST([EFI_LDS_DIR])], [AS_IF([test "x$enable_gnuefi" = xyes], [AC_MSG_ERROR([*** gnuefi support requested but files not found])], [have_gnuefi=no])]) AC_ARG_WITH(efi-includedir, AS_HELP_STRING([--with-efi-includedir=PATH], [Path to EFI include directory]), [EFI_INC_DIR="$withval"], [EFI_INC_DIR="/usr/include"] ) AC_SUBST([EFI_INC_DIR]) ]) AM_CONDITIONAL(HAVE_GNUEFI, [test "x$have_gnuefi" = xyes]) # ------------------------------------------------------------------------------ have_kdbus=no AC_ARG_ENABLE(kdbus, AS_HELP_STRING([--disable-kdbus], [do not connect to kdbus by default])) if test "x$enable_kdbus" != "xno"; then AC_DEFINE(ENABLE_KDBUS, 1, [Define if kdbus is to be connected to by default]) have_kdbus=yes M4_DEFINES="$M4_DEFINES -DENABLE_KDBUS" fi AM_CONDITIONAL(ENABLE_KDBUS, [test "$have_kdbus" = "yes"]) # ------------------------------------------------------------------------------ AC_ARG_WITH(rc-local-script-path-start, AS_HELP_STRING([--with-rc-local-script-path-start=PATH], [Path to /etc/rc.local]), [RC_LOCAL_SCRIPT_PATH_START="$withval"], [RC_LOCAL_SCRIPT_PATH_START="/etc/rc.local"]) AC_ARG_WITH(rc-local-script-path-stop, AS_HELP_STRING([--with-rc-local-script-path-stop=PATH], [Path to /usr/sbin/halt.local]), [RC_LOCAL_SCRIPT_PATH_STOP="$withval"], [RC_LOCAL_SCRIPT_PATH_STOP="/usr/sbin/halt.local"]) AC_DEFINE_UNQUOTED(RC_LOCAL_SCRIPT_PATH_START, ["$RC_LOCAL_SCRIPT_PATH_START"], [Path of /etc/rc.local script]) AC_DEFINE_UNQUOTED(RC_LOCAL_SCRIPT_PATH_STOP, ["$RC_LOCAL_SCRIPT_PATH_STOP"], [Path of /usr/sbin/halt.local script]) AC_SUBST(RC_LOCAL_SCRIPT_PATH_START) AC_SUBST(RC_LOCAL_SCRIPT_PATH_STOP) # ------------------------------------------------------------------------------ AC_ARG_WITH(kbd-loadkeys, AS_HELP_STRING([--with-kbd-loadkeys=PATH], [Path to loadkeys]), [KBD_LOADKEYS="$withval"], [KBD_LOADKEYS="/usr/bin/loadkeys"]) AC_ARG_WITH(kbd-setfont, AS_HELP_STRING([--with-kbd-setfont=PATH], [Path to setfont]), [KBD_SETFONT="$withval"], [KBD_SETFONT="/usr/bin/setfont"]) AC_DEFINE_UNQUOTED(KBD_LOADKEYS, ["$KBD_LOADKEYS"], [Path of loadkeys]) AC_DEFINE_UNQUOTED(KBD_SETFONT, ["$KBD_SETFONT"], [Path of setfont]) AC_SUBST(KBD_LOADKEYS) AC_SUBST(KBD_SETFONT) AC_ARG_WITH(telinit, AS_HELP_STRING([--with-telinit=PATH], [Path to telinit]), [TELINIT="$withval"], [TELINIT="/lib/sysvinit/telinit"]) AC_DEFINE_UNQUOTED(TELINIT, ["$TELINIT"], [Path to telinit]) AC_SUBST(TELINIT) AC_CHECK_HEADERS_ONCE([valgrind/memcheck.h valgrind/valgrind.h]) # ------------------------------------------------------------------------------ have_myhostname=no AC_ARG_ENABLE(myhostname, AS_HELP_STRING([--disable-myhostname], [disable nss-myhostname support])) if test "x$enable_myhostname" != "xno"; then AC_HEADER_STDC AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h nss.h sys/ioctl.h sys/auxv.h]) AC_C_CONST AC_TYPE_SIZE_T AC_HEADER_TIME AC_FUNC_SELECT_ARGTYPES AC_CHECK_FUNCS([gethostbyaddr gethostbyname gettimeofday inet_ntoa memset select socket strcspn strdup strerror strncasecmp strcasecmp strspn]) have_myhostname=yes fi AM_CONDITIONAL(HAVE_MYHOSTNAME, [test "$have_myhostname" = "yes"]) # ------------------------------------------------------------------------------ AC_ARG_ENABLE(hwdb, [AC_HELP_STRING([--disable-hwdb], [disable hardware database support])], enable_hwdb=$enableval, enable_hwdb=yes) AM_CONDITIONAL(ENABLE_HWDB, [test x$enable_hwdb = xyes]) # ------------------------------------------------------------------------------ have_manpages=no AC_ARG_ENABLE(manpages, AS_HELP_STRING([--disable-manpages], [disable manpages])) AC_PATH_PROG([XSLTPROC], [xsltproc]) AS_IF([test "x$enable_manpages" != xno], [ have_manpages=yes AS_IF([test -z "$XSLTPROC"], AC_MSG_ERROR([*** xsltproc is required for man pages])) ]) AM_CONDITIONAL(ENABLE_MANPAGES, [test "x$have_manpages" = "xyes"]) # ------------------------------------------------------------------------------ AC_ARG_ENABLE(hibernate, [AC_HELP_STRING([--disable-hibernate], [disable hibernation support])], enable_hibernate=$enableval, enable_hibernate=yes) AM_CONDITIONAL(ENABLE_HIBERNATE, [test x$enable_hibernate = xyes]) # ------------------------------------------------------------------------------ AC_ARG_ENABLE(ldconfig, [AC_HELP_STRING([--disable-ldconfig], [disable ldconfig])], enable_ldconfig=$enableval, enable_ldconfig=yes) AM_CONDITIONAL(ENABLE_LDCONFIG, [test x$enable_ldconfig = xyes]) # ------------------------------------------------------------------------------ # Location of the init scripts as mandated by LSB SYSTEM_SYSVINIT_PATH=/etc/init.d SYSTEM_SYSVRCND_PATH=/etc/rc.d AC_ARG_WITH([sysvinit-path], [AS_HELP_STRING([--with-sysvinit-path=PATH], [Specify the path to where the SysV init scripts are located])], [SYSTEM_SYSVINIT_PATH="$withval"], []) AC_ARG_WITH([sysvrcnd-path], [AS_HELP_STRING([--with-sysvrcnd-path=PATH], [Specify the path to the base directory for the SysV rcN.d directories])], [SYSTEM_SYSVRCND_PATH="$withval"], []) if test "x${SYSTEM_SYSVINIT_PATH}" != "x" -a "x${SYSTEM_SYSVRCND_PATH}" != "x"; then AC_DEFINE(HAVE_SYSV_COMPAT, [], [SysV init scripts and rcN.d links are supported.]) SYSTEM_SYSV_COMPAT="yes" M4_DEFINES="$M4_DEFINES -DHAVE_SYSV_COMPAT" elif test "x${SYSTEM_SYSVINIT_PATH}" != "x" -o "x${SYSTEM_SYSVRCND_PATH}" != "x"; then AC_MSG_ERROR([*** You need both --with-sysvinit-path=PATH and --with-sysvrcnd-path=PATH to enable SysV compatibility support, or both empty to disable it.]) else SYSTEM_SYSV_COMPAT="no" fi AC_SUBST(SYSTEM_SYSVINIT_PATH) AC_SUBST(SYSTEM_SYSVRCND_PATH) AC_SUBST(M4_DEFINES) AM_CONDITIONAL(HAVE_SYSV_COMPAT, test "$SYSTEM_SYSV_COMPAT" = "yes") AC_ARG_WITH([tty-gid], [AS_HELP_STRING([--with-tty-gid=GID], [Specify the numeric GID of the 'tty' group])], [TTY_GID="$withval"], [TTY_GID="5"]) AC_DEFINE_UNQUOTED(TTY_GID, [$TTY_GID], [GID of the 'tty' group]) AC_SUBST(TTY_GID) AC_ARG_WITH([dbuspolicydir], AS_HELP_STRING([--with-dbuspolicydir=DIR], [D-Bus policy directory]), [], [with_dbuspolicydir=${sysconfdir}/dbus-1/system.d]) AX_NORMALIZE_PATH([with_dbuspolicydir]) AC_ARG_WITH([dbussessionservicedir], AS_HELP_STRING([--with-dbussessionservicedir=DIR], [D-Bus session service directory]), [], [with_dbussessionservicedir=${datadir}/dbus-1/services]) AX_NORMALIZE_PATH([with_dbussessionservicedir]) AC_ARG_WITH([dbussystemservicedir], AS_HELP_STRING([--with-dbussystemservicedir=DIR], [D-Bus system service directory]), [], [with_dbussystemservicedir=${datadir}/dbus-1/system-services]) AX_NORMALIZE_PATH([with_dbussystemservicedir]) AC_ARG_WITH([bashcompletiondir], AS_HELP_STRING([--with-bashcompletiondir=DIR], [Bash completions directory]), [], [AS_IF([$($PKG_CONFIG --exists bash-completion)], [ with_bashcompletiondir=$($PKG_CONFIG --variable=completionsdir bash-completion) ] , [ with_bashcompletiondir=${datadir}/bash-completion/completions ])]) AM_CONDITIONAL(ENABLE_BASH_COMPLETION, [test "$with_bashcompletiondir" != "no"]) AX_NORMALIZE_PATH([with_bashcompletiondir]) AC_ARG_WITH([zshcompletiondir], AS_HELP_STRING([--with-zshcompletiondir=DIR], [Zsh completions directory]), [], [with_zshcompletiondir=${datadir}/zsh/site-functions]) AM_CONDITIONAL(ENABLE_ZSH_COMPLETION, [test "$with_zshcompletiondir" != "no"]) AX_NORMALIZE_PATH([with_zshcompletiondir]) AC_ARG_WITH([rootprefix], AS_HELP_STRING([--with-rootprefix=DIR], [rootfs directory prefix for config files and kernel modules]), [], [with_rootprefix=${ac_default_prefix}]) # --with-rootprefix= (empty) should default to "/" but AX_NORMALIZE_PATH # defaults those to ".", solve that here for now until we can find a suitable # fix for AX_NORMALIZE_PATH upstream at autoconf-archive. # See: https://github.com/systemd/systemd/issues/54 if test "x${with_rootprefix}" = "x"; then with_rootprefix="/" fi AX_NORMALIZE_PATH([with_rootprefix]) AC_ARG_WITH([rootlibdir], AS_HELP_STRING([--with-rootlibdir=DIR], [Root directory for libraries necessary for boot]), [], [with_rootlibdir=${libdir}]) AX_NORMALIZE_PATH([with_rootlibdir]) AC_ARG_WITH([pamlibdir], AS_HELP_STRING([--with-pamlibdir=DIR], [Directory for PAM modules]), [], [with_pamlibdir=${with_rootlibdir}/security]) AX_NORMALIZE_PATH([with_pamlibdir]) AC_ARG_WITH([pamconfdir], AS_HELP_STRING([--with-pamconfdir=DIR], [Directory for PAM configuration]), [], [with_pamconfdir=${sysconfdir}/pam.d]) AX_NORMALIZE_PATH([with_pamconfdir]) AC_ARG_ENABLE([split-usr], AS_HELP_STRING([--enable-split-usr], [Assume that /bin, /sbin aren\'t symlinks into /usr]), [], [AS_IF([test "x${ac_default_prefix}" != "x${with_rootprefix}"], [ enable_split_usr=yes ], [ enable_split_usr=no ])]) AS_IF([test "x${enable_split_usr}" = "xyes"], [ AC_DEFINE(HAVE_SPLIT_USR, 1, [Define if /bin, /sbin aren't symlinks into /usr]) ]) AM_CONDITIONAL(ENABLE_SPLIT_USR, [test "x${enable_split_usr}" = "xyes"]) # work around intltool-update issues during 'make distcheck' AS_IF([test "x$0" != "x./configure"], [ AC_SUBST([INTLTOOL_UPDATE], [/bin/true]) ]) # QEMU and OVMF UEFI firmware AS_IF([test x"$cross_compiling" = "xyes"], [], [ AC_PATH_PROG([QEMU], [qemu-system-x86_64]) AC_CHECK_FILE([/usr/share/qemu/bios-ovmf.bin], [QEMU_BIOS=/usr/share/qemu/bios-ovmf.bin], [AC_CHECK_FILE([/usr/share/qemu-ovmf/bios.bin], [QEMU_BIOS=/usr/share/qemu-ovmf/bios.bin])]) AC_SUBST([QEMU_BIOS]) ]) AC_ARG_ENABLE(tests, [AC_HELP_STRING([--disable-tests], [disable tests])], enable_tests=$enableval, enable_tests=yes) AM_CONDITIONAL(ENABLE_TESTS, [test x$enable_tests = xyes]) AC_ARG_ENABLE(debug, [AC_HELP_STRING([--enable-debug@<:@=LIST@:>@], [enable extra debugging (hashmap,mmap-cache)])], [if test "x$enableval" = "xyes"; then enableval="hashmap,mmap-cache" fi saved_ifs="$IFS" IFS="$IFS$PATH_SEPARATOR," for name in $enableval; do case $name in hashmap) enable_debug_hashmap=yes ;; mmap-cache) enable_debug_mmap_cache=yes ;; esac done IFS="$saved_ifs"],[]) enable_debug="" AS_IF([test x$enable_debug_hashmap = xyes], [ AC_DEFINE(ENABLE_DEBUG_HASHMAP, 1, [Define if hashmap debugging is to be enabled]) enable_debug="hashmap $enable_debug" ]) AS_IF([test x$enable_debug_mmap_cache = xyes], [ AC_DEFINE(ENABLE_DEBUG_MMAP_CACHE, 1, [Define if mmap cache debugging is to be enabled]) enable_debug="mmap-cache $enable_debug" ]) test -z "$enable_debug" && enable_debug="none" AC_SUBST([dbuspolicydir], [$with_dbuspolicydir]) AC_SUBST([dbussessionservicedir], [$with_dbussessionservicedir]) AC_SUBST([dbussystemservicedir], [$with_dbussystemservicedir]) AC_SUBST([bashcompletiondir], [$with_bashcompletiondir]) AC_SUBST([zshcompletiondir], [$with_zshcompletiondir]) AC_SUBST([pamlibdir], [$with_pamlibdir]) AC_SUBST([pamconfdir], [$with_pamconfdir]) AC_SUBST([rootprefix], [$with_rootprefix]) AC_SUBST([rootlibdir], [$with_rootlibdir]) AC_CONFIG_FILES([ Makefile po/Makefile.in ]) AC_OUTPUT AC_MSG_RESULT([ $PACKAGE_NAME $VERSION libcryptsetup: ${have_libcryptsetup} PAM: ${have_pam} AUDIT: ${have_audit} IMA: ${have_ima} AppArmor: ${have_apparmor} SELinux: ${have_selinux} SECCOMP: ${have_seccomp} SMACK: ${have_smack} ZLIB: ${have_zlib} XZ: ${have_xz} LZ4: ${have_lz4} BZIP2: ${have_bzip2} ACL: ${have_acl} GCRYPT: ${have_gcrypt} QRENCODE: ${have_qrencode} MICROHTTPD: ${have_microhttpd} GNUTLS: ${have_gnutls} libcurl: ${have_libcurl} libidn: ${have_libidn} libiptc: ${have_libiptc} ELFUTILS: ${have_elfutils} binfmt: ${have_binfmt} vconsole: ${have_vconsole} bootchart: ${have_bootchart} quotacheck: ${have_quotacheck} tmpfiles: ${have_tmpfiles} sysusers: ${have_sysusers} firstboot: ${have_firstboot} randomseed: ${have_randomseed} backlight: ${have_backlight} rfkill: ${have_rfkill} logind: ${have_logind} machined: ${have_machined} importd: ${have_importd} hostnamed: ${have_hostnamed} timedated: ${have_timedated} timesyncd: ${have_timesyncd} default NTP servers: ${NTP_SERVERS} time epoch: ${TIME_EPOCH} localed: ${have_localed} networkd: ${have_networkd} resolved: ${have_resolved} default DNS servers: ${DNS_SERVERS} coredump: ${have_coredump} polkit: ${have_polkit} efi: ${have_efi} gnuefi: ${have_gnuefi} efi arch: ${EFI_ARCH} EFI machine type: ${EFI_MACHINE_TYPE_NAME} EFI CC ${EFI_CC} EFI libdir: ${EFI_LIB_DIR} EFI ldsdir: ${EFI_LDS_DIR} EFI includedir: ${EFI_INC_DIR} kmod: ${have_kmod} xkbcommon: ${have_xkbcommon} blkid: ${have_blkid} libmount: ${have_libmount} dbus: ${have_dbus} nss-myhostname: ${have_myhostname} hwdb: ${enable_hwdb} kdbus: ${have_kdbus} Python: ${have_python} man pages: ${have_manpages} test coverage: ${have_coverage} Split /usr: ${enable_split_usr} SysV compatibility: ${SYSTEM_SYSV_COMPAT} compatibility libraries: ${have_compat_libs} utmp/wtmp support: ${have_utmp} ldconfig support: ${enable_ldconfig} hibernate support: ${enable_hibernate} extra debugging: ${enable_debug} prefix: ${prefix} rootprefix: ${with_rootprefix} sysconf dir: ${sysconfdir} datarootdir: ${datarootdir} includedir: ${includedir} lib dir: ${libdir} rootlib dir: ${with_rootlibdir} SysV init scripts: ${SYSTEM_SYSVINIT_PATH} SysV rc?.d directories: ${SYSTEM_SYSVRCND_PATH} Build Python: ${PYTHON} PAM modules dir: ${with_pamlibdir} PAM configuration dir: ${with_pamconfdir} D-Bus policy dir: ${with_dbuspolicydir} D-Bus session dir: ${with_dbussessionservicedir} D-Bus system dir: ${with_dbussystemservicedir} Bash completions dir: ${with_bashcompletiondir} Zsh completions dir: ${with_zshcompletiondir} Extra start script: ${RC_LOCAL_SCRIPT_PATH_START} Extra stop script: ${RC_LOCAL_SCRIPT_PATH_STOP} Debug shell: ${SUSHELL} @ ${DEBUGTTY} TTY GID: ${TTY_GID} Maximum System UID: ${SYSTEM_UID_MAX} Maximum System GID: ${SYSTEM_GID_MAX} Certificate root: ${CERTIFICATEROOT} CFLAGS: ${OUR_CFLAGS} ${CFLAGS} CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS} LDFLAGS: ${OUR_LDFLAGS} ${LDFLAGS} ]) systemd-229/docs/000077500000000000000000000000001265713322000140115ustar00rootroot00000000000000systemd-229/docs/.gitignore000066400000000000000000000000061265713322000157750ustar00rootroot00000000000000/html systemd-229/docs/Makefile000077700000000000000000000000001265713322000201062../src/Makefileustar00rootroot00000000000000systemd-229/docs/sysvinit/000077500000000000000000000000001265713322000157015ustar00rootroot00000000000000systemd-229/docs/sysvinit/.gitignore000066400000000000000000000000101265713322000176600ustar00rootroot00000000000000/README systemd-229/docs/sysvinit/Makefile000077700000000000000000000000001265713322000222112../../src/Makefileustar00rootroot00000000000000systemd-229/docs/sysvinit/README.in000066400000000000000000000022241265713322000171660ustar00rootroot00000000000000You are looking for the traditional init scripts in @SYSTEM_SYSVINIT_PATH@, and they are gone? Here's an explanation on what's going on: You are running a systemd-based OS where traditional init scripts have been replaced by native systemd services files. Service files provide very similar functionality to init scripts. To make use of service files simply invoke "systemctl", which will output a list of all currently running services (and other units). Use "systemctl list-unit-files" to get a listing of all known unit files, including stopped, disabled and masked ones. Use "systemctl start foobar.service" and "systemctl stop foobar.service" to start or stop a service, respectively. For further details, please refer to systemctl(1). Note that traditional init scripts continue to function on a systemd system. An init script @SYSTEM_SYSVINIT_PATH@/foobar is implicitly mapped into a service unit foobar.service during system initialization. Thank you! Further reading: man:systemctl(1) man:systemd(1) http://0pointer.de/blog/projects/systemd-for-admins-3.html http://www.freedesktop.org/wiki/Software/systemd/Incompatibilities systemd-229/docs/var-log/000077500000000000000000000000001265713322000153605ustar00rootroot00000000000000systemd-229/docs/var-log/.gitignore000066400000000000000000000000101265713322000173370ustar00rootroot00000000000000/README systemd-229/docs/var-log/Makefile000077700000000000000000000000001265713322000216702../../src/Makefileustar00rootroot00000000000000systemd-229/docs/var-log/README.in000066400000000000000000000020261265713322000166450ustar00rootroot00000000000000You are looking for the traditional text log files in @VARLOGDIR@, and they are gone? Here's an explanation on what's going on: You are running a systemd-based OS where traditional syslog has been replaced with the Journal. The journal stores the same (and more) information as classic syslog. To make use of the journal and access the collected log data simply invoke "journalctl", which will output the logs in the identical text-based format the syslog files in @VARLOGDIR@ used to be. For further details, please refer to journalctl(1). Alternatively, consider installing one of the traditional syslog implementations available for your distribution, which will generate the classic log files for you. Syslog implementations such as syslog-ng or rsyslog may be installed side-by-side with the journal and will continue to function the way they always did. Thank you! Further reading: man:journalctl(1) man:systemd-journald.service(8) man:journald.conf(5) http://0pointer.de/blog/projects/the-journal.html systemd-229/factory/000077500000000000000000000000001265713322000145305ustar00rootroot00000000000000systemd-229/factory/etc/000077500000000000000000000000001265713322000153035ustar00rootroot00000000000000systemd-229/factory/etc/nsswitch.conf000066400000000000000000000001671265713322000200200ustar00rootroot00000000000000# This file is part of systemd. passwd: files shadow: files group: files hosts: files mymachines resolve myhostname systemd-229/factory/etc/pam.d/000077500000000000000000000000001265713322000163025ustar00rootroot00000000000000systemd-229/factory/etc/pam.d/other000066400000000000000000000002251265713322000173450ustar00rootroot00000000000000# This file is part of systemd. auth include system-auth account include system-auth password include system-auth session include system-auth systemd-229/factory/etc/pam.d/system-auth000066400000000000000000000005241265713322000205110ustar00rootroot00000000000000# This file is part of systemd. auth sufficient pam_unix.so nullok try_first_pass account required pam_nologin.so account sufficient pam_unix.so password sufficient pam_unix.so nullok sha512 shadow try_first_pass try_authtok -session optional pam_loginuid.so -session optional pam_systemd.so session sufficient pam_unix.so systemd-229/hwdb/000077500000000000000000000000001265713322000140055ustar00rootroot00000000000000systemd-229/hwdb/.gitignore000066400000000000000000000000751265713322000157770ustar00rootroot00000000000000/pci.ids /usb.ids /ma-large.txt /ma-medium.txt /ma-small.txt systemd-229/hwdb/20-OUI.hwdb000066400000000000000000051442201265713322000155360ustar00rootroot00000000000000# This file is part of systemd. # # Data imported from: # https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-L&format=txt # https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-M&format=txt # https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-S&format=txt OUI:70B3D5913* ID_OUI_FROM_DATABASE=Shenzhen Riitek Technology Co.,Ltd OUI:70B3D588A* ID_OUI_FROM_DATABASE=Perceptics, LLC OUI:70B3D5FFE* ID_OUI_FROM_DATABASE=Private OUI:70B3D5001* ID_OUI_FROM_DATABASE=SOREDI touch systems GmbH OUI:70B3D5D70* ID_OUI_FROM_DATABASE=Rational Production srl Unipersonale OUI:70B3D5426* ID_OUI_FROM_DATABASE=Zehnder Group Nederland OUI:70B3D5266* ID_OUI_FROM_DATABASE=Spectra Displays Ltd OUI:70B3D5D38* ID_OUI_FROM_DATABASE=Vista Research, Inc. OUI:70B3D5996* ID_OUI_FROM_DATABASE=XpertSea Solutions inc. OUI:70B3D5605* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D516E* ID_OUI_FROM_DATABASE=Jemac Sweden AB OUI:70B3D5671* ID_OUI_FROM_DATABASE=Sea Shell Corporation OUI:70B3D57EC* ID_OUI_FROM_DATABASE=GRIDSMART Technologies OUI:70B3D5AF9* ID_OUI_FROM_DATABASE=Critical Link LLC OUI:70B3D5D59* ID_OUI_FROM_DATABASE=WyreStorm Technologies Ltd OUI:70B3D5A3C* ID_OUI_FROM_DATABASE=Wave Music Ltd OUI:70B3D5FC1* ID_OUI_FROM_DATABASE=InDiCor OUI:70B3D5BB2* ID_OUI_FROM_DATABASE=Mettler Toledo Hi-Speed OUI:70B3D514F* ID_OUI_FROM_DATABASE=Mobile Devices Unlimited OUI:70B3D5891* ID_OUI_FROM_DATABASE=neocontrol soluções em automação OUI:70B3D501E* ID_OUI_FROM_DATABASE=ePOINT Embedded Computing Limited OUI:70B3D5C9D* ID_OUI_FROM_DATABASE=APG Cash Drawer OUI:70B3D534C* ID_OUI_FROM_DATABASE=GLT Exports Ltd OUI:70B3D5B51* ID_OUI_FROM_DATABASE=Critical Link LLC OUI:70B3D5D29* ID_OUI_FROM_DATABASE=Sportzcast OUI:70B3D513B* ID_OUI_FROM_DATABASE=Sienna Corporation OUI:70B3D537F* ID_OUI_FROM_DATABASE=IDS Innomic GmbH OUI:70B3D5694* ID_OUI_FROM_DATABASE=MoviTHERM OUI:70B3D5B28* ID_OUI_FROM_DATABASE=HUSTY M.Styczen J.Hupert sp.j. OUI:70B3D514E* ID_OUI_FROM_DATABASE=Innosonix GmbH OUI:70B3D5185* ID_OUI_FROM_DATABASE=R&D Gran-System-S LLC OUI:70B3D55B1* ID_OUI_FROM_DATABASE=EPD Electronics OUI:70B3D5EAE* ID_OUI_FROM_DATABASE=Orlaco Products B.V. OUI:70B3D5066* ID_OUI_FROM_DATABASE=North Pole Engineering, Inc. OUI:70B3D557D* ID_OUI_FROM_DATABASE=WICOM1 GmbH OUI:70B3D5E77* ID_OUI_FROM_DATABASE=OPTIX JSC OUI:70B3D5740* ID_OUI_FROM_DATABASE=Prisma Telecom Testing Srl OUI:70B3D584E* ID_OUI_FROM_DATABASE=Chromalox, Inc. OUI:70B3D5817* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D543B* ID_OUI_FROM_DATABASE=Kalycito Infotech Private Limited OUI:70B3D5C88* ID_OUI_FROM_DATABASE=SINED srl OUI:70B3D5CD6* ID_OUI_FROM_DATABASE=VideoRay LLC OUI:70B3D5A1D* ID_OUI_FROM_DATABASE=Fluid Components International OUI:70B3D5079* ID_OUI_FROM_DATABASE=CheckBill Co,Ltd. OUI:70B3D58FF* ID_OUI_FROM_DATABASE=IMST GmbH OUI:70B3D5DC0* ID_OUI_FROM_DATABASE=ATEME OUI:70B3D5F79* ID_OUI_FROM_DATABASE=Firehose Labs, Inc. OUI:70B3D5404* ID_OUI_FROM_DATABASE=RANIX,Inc. OUI:70B3D552D* ID_OUI_FROM_DATABASE=Tanaka Electric Industry Co., Ltd. OUI:70B3D5BE5* ID_OUI_FROM_DATABASE=Pantec Engineering AG OUI:70B3D5D90* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D545F* ID_OUI_FROM_DATABASE=Cloud4Wi OUI:70B3D535E* ID_OUI_FROM_DATABASE=EIDOS s.p.a. OUI:70B3D5F96* ID_OUI_FROM_DATABASE=Ecologicsense OUI:70B3D50D8* ID_OUI_FROM_DATABASE=Laser Imagineering GmbH OUI:70B3D57E4* ID_OUI_FROM_DATABASE=C21 Systems Ltd OUI:70B3D5995* ID_OUI_FROM_DATABASE=LayTec AG OUI:70B3D5957* ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG OUI:70B3D54DD* ID_OUI_FROM_DATABASE=Road-iQ, LLC OUI:70B3D5FBA* ID_OUI_FROM_DATABASE=Apogee Applied Research, Inc. OUI:70B3D563B* ID_OUI_FROM_DATABASE=Lazer Safe Pty Ltd OUI:70B3D56D1* ID_OUI_FROM_DATABASE=Visual Engineering Technologies Ltd OUI:70B3D50DF* ID_OUI_FROM_DATABASE=B.E.A. sa OUI:70B3D5342* ID_OUI_FROM_DATABASE=Solectrix OUI:70B3D5E20* ID_OUI_FROM_DATABASE=Signature Control Systems, LLC. OUI:70B3D5538* ID_OUI_FROM_DATABASE=sydetion UG (h.b.) OUI:70B3D52DC* ID_OUI_FROM_DATABASE=Bolide Technology Group, Inc. OUI:70B3D5B85* ID_OUI_FROM_DATABASE=Fenotech Inc. OUI:70B3D52EE* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D51E5* ID_OUI_FROM_DATABASE=VendNovation LLC OUI:70B3D5FE7* ID_OUI_FROM_DATABASE=VEILUX INC. OUI:70B3D508F* ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH OUI:70B3D5E55* ID_OUI_FROM_DATABASE=BELT S.r.l. OUI:70B3D588F* ID_OUI_FROM_DATABASE=Quaesta Instruments, LLC OUI:70B3D5835* ID_OUI_FROM_DATABASE=CommBox P/L OUI:70B3D5730* ID_OUI_FROM_DATABASE=Videogenix OUI:70B3D55A9* ID_OUI_FROM_DATABASE=Bunka Shutter Co., Ltd. OUI:70B3D5714* ID_OUI_FROM_DATABASE=Alturna Networks OUI:70B3D52A7* ID_OUI_FROM_DATABASE=Plasmability, LLC OUI:70B3D5D7A* ID_OUI_FROM_DATABASE=Speedifi Inc OUI:70B3D5737* ID_OUI_FROM_DATABASE=SD Biosensor OUI:70B3D56DA* ID_OUI_FROM_DATABASE=Enovative Networks, Inc. OUI:70B3D50D7* ID_OUI_FROM_DATABASE=Russian Telecom Equipment Company OUI:70B3D546F* ID_OUI_FROM_DATABASE=serva transport systems GmbH OUI:70B3D5A00* ID_OUI_FROM_DATABASE=ATX NETWORKS LTD OUI:70B3D51AF* ID_OUI_FROM_DATABASE=Teenage Engineering AB OUI:70B3D55C8* ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd OUI:70B3D5D9C* ID_OUI_FROM_DATABASE=Subinitial LLC OUI:70B3D5923* ID_OUI_FROM_DATABASE=eumig industrie-tv GmbH OUI:70B3D578B* ID_OUI_FROM_DATABASE=Jingtu Printing Systems Co., Ltd OUI:70B3D54BB* ID_OUI_FROM_DATABASE=Plazma-T OUI:70B3D5DF2* ID_OUI_FROM_DATABASE=AML OUI:70B3D5CB8* ID_OUI_FROM_DATABASE=Verti Tecnologia OUI:70B3D5A97* ID_OUI_FROM_DATABASE=Bizwerks, LLC OUI:70B3D5417* ID_OUI_FROM_DATABASE=Figment Design Laboratories OUI:70B3D5CF6* ID_OUI_FROM_DATABASE=Tornado Modular Systems OUI:70B3D5186* ID_OUI_FROM_DATABASE=Rohde&Schwarz Topex OUI:70B3D591E* ID_OUI_FROM_DATABASE=Creotech Instruments S.A. OUI:70B3D5775* ID_OUI_FROM_DATABASE=Sonel S.A. OUI:70B3D55FD* ID_OUI_FROM_DATABASE=Windar Photonics OUI:70B3D5078* ID_OUI_FROM_DATABASE=OrbiWise SA OUI:70B3D5B78* ID_OUI_FROM_DATABASE=HOERMANN GmbH OUI:70B3D5D61* ID_OUI_FROM_DATABASE=VITEC OUI:70B3D5F78* ID_OUI_FROM_DATABASE=Manvish eTech Pvt. Ltd. OUI:70B3D5146* ID_OUI_FROM_DATABASE=3City Electronics OUI:70B3D515F* ID_OUI_FROM_DATABASE=SAVRONİK ELEKTRONİK OUI:70B3D54DC* ID_OUI_FROM_DATABASE=JK DEVICE CORPORATION OUI:70B3D5341* ID_OUI_FROM_DATABASE=Vtron Pty Ltd OUI:70B3D5875* ID_OUI_FROM_DATABASE=Peek Traffic OUI:70B3D56A5* ID_OUI_FROM_DATABASE=Akenori PTE LTD OUI:70B3D56E0* ID_OUI_FROM_DATABASE=ABB SPA - DMPC OUI:70B3D5C5B* ID_OUI_FROM_DATABASE=ACD Elektronik GmbH OUI:70B3D5030* ID_OUI_FROM_DATABASE=Tresent Technologies OUI:70B3D57CD* ID_OUI_FROM_DATABASE=Molekuler Goruntuleme A.S. OUI:70B3D55EA* ID_OUI_FROM_DATABASE=KYS,INC OUI:70B3D57B3* ID_OUI_FROM_DATABASE=BroadSoft Inc OUI:70B3D5C39* ID_OUI_FROM_DATABASE=MeshWorks Wireless Oy OUI:70B3D5660* ID_OUI_FROM_DATABASE=Smart Service Technologies CO., LTD OUI:70B3D5EFE* ID_OUI_FROM_DATABASE=MEIDEN SYSTEM SOLUTIONS OUI:70B3D5C60* ID_OUI_FROM_DATABASE=Aircell Inc OUI:70B3D565A* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D5C03* ID_OUI_FROM_DATABASE=XAVi Technologies Corp. OUI:70B3D50FF* ID_OUI_FROM_DATABASE=INTERNET PROTOCOLO LOGICA SL OUI:70B3D5502* ID_OUI_FROM_DATABASE=Glidewell Laboratories OUI:70B3D56F8* ID_OUI_FROM_DATABASE=SENSEON Corporation OUI:70B3D535D* ID_OUI_FROM_DATABASE=Fresh Idea Factory BV OUI:70B3D5344* ID_OUI_FROM_DATABASE=IHI Inspection & Instrumentation Co., Ltd. OUI:70B3D53DB* ID_OUI_FROM_DATABASE=KST technology OUI:70B3D54CD* ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L. OUI:70B3D522E* ID_OUI_FROM_DATABASE=Private OUI:70B3D5EA3* ID_OUI_FROM_DATABASE=Gridless Power Corperation OUI:70B3D5A5A* ID_OUI_FROM_DATABASE=RCS Energy Management Ltd OUI:70B3D513A* ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH OUI:70B3D575D* ID_OUI_FROM_DATABASE=Nanjing Magewell Electronics Co., Ltd. OUI:70B3D50EC* ID_OUI_FROM_DATABASE=ACS MOTION CONTROL OUI:70B3D51F5* ID_OUI_FROM_DATABASE=Martec S.p.A. OUI:70B3D522B* ID_OUI_FROM_DATABASE=VITEC OUI:70B3D5708* ID_OUI_FROM_DATABASE=IBM Research GmbH OUI:70B3D5C81* ID_OUI_FROM_DATABASE=DSP DESIGN OUI:70B3D5FA1* ID_OUI_FROM_DATABASE=BBI Engineering, Inc. OUI:70B3D560C* ID_OUI_FROM_DATABASE=IST ElektronikgesmbH OUI:70B3D5936* ID_OUI_FROM_DATABASE=FARO TECHNOLOGIES, INC. OUI:70B3D5EF2* ID_OUI_FROM_DATABASE=Kongsberg Intergrated Tactical Systems OUI:70B3D5C58* ID_OUI_FROM_DATABASE=RMI Laser LLC OUI:70B3D5507* ID_OUI_FROM_DATABASE=Human Oriented Technology, Inc. OUI:70B3D5BC6* ID_OUI_FROM_DATABASE=Hatteland Display AS OUI:70B3D555D* ID_OUI_FROM_DATABASE=LunaNexus Inc OUI:70B3D5DF3* ID_OUI_FROM_DATABASE=SPC Bioclinicum OUI:70B3D5CF1* ID_OUI_FROM_DATABASE=LightDec GmbH & Co. KG OUI:70B3D58DC* ID_OUI_FROM_DATABASE=Niveo International BV OUI:70B3D5D1E* ID_OUI_FROM_DATABASE=Houston Radar LLC OUI:70B3D554D* ID_OUI_FROM_DATABASE=Qingdao Haitian Weiye Automation Control System Co., Ltd OUI:70B3D5A15* ID_OUI_FROM_DATABASE=Intercore GmbH OUI:70B3D545E* ID_OUI_FROM_DATABASE=eSOL Co.,Ltd. OUI:70B3D5B88* ID_OUI_FROM_DATABASE=ARP Corporation OUI:70B3D5BBE* ID_OUI_FROM_DATABASE=Sunrise Systems Electronics Co. Inc. OUI:70B3D5CBC* ID_OUI_FROM_DATABASE=Procon Electronics Pty Ltd OUI:70B3D52DA* ID_OUI_FROM_DATABASE=Skywave Networks Private Limited OUI:70B3D5B08* ID_OUI_FROM_DATABASE=Secuinfo Co. Ltd OUI:70B3D533C* ID_OUI_FROM_DATABASE=Videri Inc. OUI:70B3D53E5* ID_OUI_FROM_DATABASE=ATEME OUI:70B3D5FC5* ID_OUI_FROM_DATABASE=Eltwin A/S OUI:70B3D5ECF* ID_OUI_FROM_DATABASE=Ipitek OUI:70B3D5099* ID_OUI_FROM_DATABASE=Schwer+Kopka GmbH OUI:70B3D57E7* ID_OUI_FROM_DATABASE=Atessa, Inc. OUI:70B3D539B* ID_OUI_FROM_DATABASE=IROC AB OUI:70B3D53CE* ID_OUI_FROM_DATABASE=Aditec GmbH OUI:70B3D5190* ID_OUI_FROM_DATABASE=Fantom Wireless, Inc. OUI:70B3D56B6* ID_OUI_FROM_DATABASE=INRADIOS GmbH OUI:70B3D529D* ID_OUI_FROM_DATABASE=XTech2 SIA OUI:70B3D5814* ID_OUI_FROM_DATABASE=Ingenieurbuero SOMTRONIK OUI:70B3D542F* ID_OUI_FROM_DATABASE=SINTOKOGIO, LTD OUI:70B3D5702* ID_OUI_FROM_DATABASE=Sensor Highway Ltd OUI:70B3D50E0* ID_OUI_FROM_DATABASE=PLCiS OUI:70B3D5EDC* ID_OUI_FROM_DATABASE=J.D. Koftinoff Software, Ltd. OUI:001BC50C9* ID_OUI_FROM_DATABASE=UAB Kitron OUI:001BC50C8* ID_OUI_FROM_DATABASE=Dialine OUI:70B3D551E* ID_OUI_FROM_DATABASE=Fundación Cardiovascular de Colombia OUI:70B3D5EB0* ID_OUI_FROM_DATABASE=Nautel Limted OUI:70B3D5625* ID_OUI_FROM_DATABASE=VX Instruments GmbH OUI:70B3D5D86* ID_OUI_FROM_DATABASE=WPGSYS Pte Ltd OUI:70B3D54C8* ID_OUI_FROM_DATABASE=Hosokawa Micron Powder Systems OUI:001BC50B4* ID_OUI_FROM_DATABASE=COBAN SRL OUI:001BC50AE* ID_OUI_FROM_DATABASE=Techlan Reti s.r.l. OUI:001BC50C2* ID_OUI_FROM_DATABASE=TechSolutions A/S OUI:001BC50BF* ID_OUI_FROM_DATABASE=TN Core Co.,Ltd. OUI:001BC50BE* ID_OUI_FROM_DATABASE=YESpay International Ltd OUI:001BC50B9* ID_OUI_FROM_DATABASE=Denki Kogyo Company, Limited OUI:001BC50B8* ID_OUI_FROM_DATABASE=Private OUI:001BC50B5* ID_OUI_FROM_DATABASE=Exibea AB OUI:001BC50C3* ID_OUI_FROM_DATABASE=inomatic GmbH OUI:001BC50AF* ID_OUI_FROM_DATABASE=Enerwise Solutions Ltd. OUI:001BC50A5* ID_OUI_FROM_DATABASE=Tesla Controls OUI:001BC50A0* ID_OUI_FROM_DATABASE=HomerSoft sp. z o.o. OUI:001BC509F* ID_OUI_FROM_DATABASE=ENTE Sp. z o.o. OUI:001BC50AB* ID_OUI_FROM_DATABASE=Private OUI:001BC50AA* ID_OUI_FROM_DATABASE=Senceive Ltd OUI:001BC50A4* ID_OUI_FROM_DATABASE=RADMOR S.A. OUI:001BC509A* ID_OUI_FROM_DATABASE=Shenzhen Guang Lian Zhi Tong Limited OUI:001BC5099* ID_OUI_FROM_DATABASE=UAB Kitron OUI:001BC5098* ID_OUI_FROM_DATABASE=Cubic Systems, Inc. OUI:001BC5096* ID_OUI_FROM_DATABASE=Sanstreak Corp. OUI:001BC5095* ID_OUI_FROM_DATABASE=PREVAC sp. z o.o. OUI:001BC508F* ID_OUI_FROM_DATABASE=Unilever R&D OUI:001BC508E* ID_OUI_FROM_DATABASE=TrendPoint Systems OUI:001BC508B* ID_OUI_FROM_DATABASE=Nistica OUI:001BC508C* ID_OUI_FROM_DATABASE=Triax A/S OUI:001BC5090* ID_OUI_FROM_DATABASE=Seven Solutions S.L OUI:001BC507D* ID_OUI_FROM_DATABASE=Greatcom AG OUI:001BC5079* ID_OUI_FROM_DATABASE=HPI High Pressure Instrumentation GmbH OUI:001BC5083* ID_OUI_FROM_DATABASE=DIWEL OUI:001BC5065* ID_OUI_FROM_DATABASE=Plair Media Inc. OUI:001BC506F* ID_OUI_FROM_DATABASE=LLC Emzior OUI:001BC5073* ID_OUI_FROM_DATABASE=tado GmbH OUI:001BC5069* ID_OUI_FROM_DATABASE=Datasat Digital Entertainment OUI:001BC5051* ID_OUI_FROM_DATABASE=QQ Navigation AB OUI:001BC505F* ID_OUI_FROM_DATABASE=Klingenthaler Musikelektronik GmbH OUI:001BC505B* ID_OUI_FROM_DATABASE=konzeptpark GmbH OUI:001BC5055* ID_OUI_FROM_DATABASE=LUMIPLAN TRANSPORT OUI:001BC5047* ID_OUI_FROM_DATABASE=PT. Amanindo Nusapadu OUI:001BC504B* ID_OUI_FROM_DATABASE=Silicon Controls OUI:001BC5041* ID_OUI_FROM_DATABASE=DesignA Electronics Limited OUI:001BC503D* ID_OUI_FROM_DATABASE=rioxo GmbH OUI:001BC503C* ID_OUI_FROM_DATABASE=Xiphos Systems Corp. OUI:001BC5037* ID_OUI_FROM_DATABASE=ITW Reyflex North America OUI:001BC5033* ID_OUI_FROM_DATABASE=JE Suunnittelu Oy OUI:001BC5032* ID_OUI_FROM_DATABASE=Osborne Coinage Co OUI:001BC5036* ID_OUI_FROM_DATABASE=LOMAR SRL OUI:001BC5035* ID_OUI_FROM_DATABASE=RTLS Ltd. OUI:001BC502D* ID_OUI_FROM_DATABASE=DDTRONIK Dariusz Dowgiert OUI:001BC502C* ID_OUI_FROM_DATABASE=Care Everywhere LLC OUI:001BC502B* ID_OUI_FROM_DATABASE=Saturn South Pty Ltd OUI:001BC5029* ID_OUI_FROM_DATABASE=2 FRANCE MARINE OUI:001BC5028* ID_OUI_FROM_DATABASE=STECHWIN.CO.LTD. OUI:001BC5017* ID_OUI_FROM_DATABASE=cPacket Networks OUI:001BC500E* ID_OUI_FROM_DATABASE=Vigor Electric Corp OUI:001BC5013* ID_OUI_FROM_DATABASE=Zamir Recognition Systems Ltd. OUI:001BC5014* ID_OUI_FROM_DATABASE=Private OUI:001BC5009* ID_OUI_FROM_DATABASE=Solomon Systech Pte Ltd OUI:001BC500A* ID_OUI_FROM_DATABASE=Mercury HMI Ltd OUI:001BC500D* ID_OUI_FROM_DATABASE=Advanced Scientific Concepts, Inc. OUI:001BC5004* ID_OUI_FROM_DATABASE=Intellvisions Software Ltd OUI:001BC5003* ID_OUI_FROM_DATABASE=MicroSigns Technologies Inc OUI:001BC5000* ID_OUI_FROM_DATABASE=Converging Systems Inc. OUI:70B3D541A* ID_OUI_FROM_DATABASE=HYOSUNG Power & Industrial Systems OUI:70B3D5BAB* ID_OUI_FROM_DATABASE=Axotec Technologies GmbH OUI:70B3D569E* ID_OUI_FROM_DATABASE=PTYPE Co., LTD. OUI:70B3D575C* ID_OUI_FROM_DATABASE=UPM Technology, Inc OUI:70B3D5124* ID_OUI_FROM_DATABASE=Forschungs- und Transferzentrum Leipzig e.V. OUI:70B3D5F6D* ID_OUI_FROM_DATABASE=Qowisio OUI:70B3D5578* ID_OUI_FROM_DATABASE=IMAGE TECH CO.,LTD OUI:70B3D5187* ID_OUI_FROM_DATABASE=Elektronik & Präzisionsbau Saalfeld GmbH OUI:70B3D50EE* ID_OUI_FROM_DATABASE=Picture Elements, Inc. OUI:70B3D528A* ID_OUI_FROM_DATABASE=Transit Solutions, LLC. OUI:70B3D55A0* ID_OUI_FROM_DATABASE=Ascon Tecnologic S.r.l. OUI:70B3D5A6F* ID_OUI_FROM_DATABASE=8Cups OUI:70B3D5929* ID_OUI_FROM_DATABASE=OutSys OUI:70B3D5120* ID_OUI_FROM_DATABASE=GSP Sprachtechnologie GmbH OUI:70B3D523E* ID_OUI_FROM_DATABASE=Tornado Modular Systems OUI:70B3D5EA2* ID_OUI_FROM_DATABASE=Transportal Solutions Ltd OUI:70B3D545D* ID_OUI_FROM_DATABASE=Sensapex Oy OUI:70B3D58B0* ID_OUI_FROM_DATABASE=IES S.r.l. OUI:70B3D5FB6* ID_OUI_FROM_DATABASE=KRONOTECH SRL OUI:70B3D5EB7* ID_OUI_FROM_DATABASE=Skreens OUI:70B3D538F* ID_OUI_FROM_DATABASE=Sorynorydotcom Inc OUI:70B3D57E9* ID_OUI_FROM_DATABASE=Mecsel Oy OUI:70B3D506C* ID_OUI_FROM_DATABASE=AppTek OUI:70B3D5818* ID_OUI_FROM_DATABASE=CRDE OUI:70B3D5895* ID_OUI_FROM_DATABASE=Integrated Control Corp. OUI:70B3D5232* ID_OUI_FROM_DATABASE=UCONSYS OUI:70B3D501A* ID_OUI_FROM_DATABASE=Cubro Acronet GesmbH OUI:70B3D537B* ID_OUI_FROM_DATABASE=Power Ltd. OUI:70B3D5FCC* ID_OUI_FROM_DATABASE=DIgSILENT GmbH OUI:70B3D5FD8* ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme OUI:70B3D576B* ID_OUI_FROM_DATABASE=EMPELOR GmbH OUI:70B3D50B8* ID_OUI_FROM_DATABASE=Lucas-Nülle GmbH OUI:70B3D5FEB* ID_OUI_FROM_DATABASE=Les distributions Multi-Secure incorporee OUI:70B3D5658* ID_OUI_FROM_DATABASE=emperor brands OUI:70B3D53A9* ID_OUI_FROM_DATABASE=Vivalnk OUI:001BC5087* ID_OUI_FROM_DATABASE=Onnet Technologies and Innovations LLC OUI:70B3D5720* ID_OUI_FROM_DATABASE=Private OUI:70B3D5D60* ID_OUI_FROM_DATABASE=Flintab AB OUI:70B3D51B4* ID_OUI_FROM_DATABASE=5nines OUI:70B3D5522* ID_OUI_FROM_DATABASE=Syncopated Engineering Inc OUI:70B3D578E* ID_OUI_FROM_DATABASE=effectas GmbH OUI:70B3D5CC1* ID_OUI_FROM_DATABASE=BEEcube Inc. OUI:70B3D59D4* ID_OUI_FROM_DATABASE=Transas Marine Limited OUI:70B3D5AE2* ID_OUI_FROM_DATABASE=Transas Marine Limited OUI:001BC5015* ID_OUI_FROM_DATABASE=Private OUI:70B3D5476* ID_OUI_FROM_DATABASE=FR-Team International SA OUI:70B3D5326* ID_OUI_FROM_DATABASE=NEMEUS-SAS OUI:70B3D5FE6* ID_OUI_FROM_DATABASE=SHIZUKI ELECTRIC CO.,INC OUI:70B3D5943* ID_OUI_FROM_DATABASE=Abbott Medical Optics Inc. OUI:70B3D5AE0* ID_OUI_FROM_DATABASE=AnyComm.Co.,Ltd. OUI:70B3D52B3* ID_OUI_FROM_DATABASE=HAS co.,ltd. OUI:70B3D511D* ID_OUI_FROM_DATABASE=Texka Labs OUI:70B3D5D5A* ID_OUI_FROM_DATABASE=WyreStorm Technologies Ltd OUI:70B3D5CB6* ID_OUI_FROM_DATABASE=Kuebrich Ingeniergesellschaft mbh & Co. KG OUI:70B3D50BE* ID_OUI_FROM_DATABASE=ChamSys Ltd OUI:70B3D51E0* ID_OUI_FROM_DATABASE=TOPROOTTechnology Corp. Ltd. OUI:70B3D50C8* ID_OUI_FROM_DATABASE=Fin Robotics Inc OUI:70B3D574A* ID_OUI_FROM_DATABASE=Mettler Toledo Hi-Speed OUI:70B3D539D* ID_OUI_FROM_DATABASE=Comark Interactive Solutions OUI:70B3D5D07* ID_OUI_FROM_DATABASE=Waversa Systems OUI:70B3D54D1* ID_OUI_FROM_DATABASE=Contraves Advanced Devices Sdn. Bhd. OUI:70B3D5771* ID_OUI_FROM_DATABASE=Apator Miitors ApS OUI:70B3D5CA9* ID_OUI_FROM_DATABASE=Nxcontrol system Co., Ltd. OUI:70B3D5EDF* ID_OUI_FROM_DATABASE=GridNavigator OUI:70B3D520A* ID_OUI_FROM_DATABASE=Golden Grid Systems OUI:70B3D5517* ID_OUI_FROM_DATABASE=ISPHER OUI:70B3D5140* ID_OUI_FROM_DATABASE=Virta Laboratories, Inc. OUI:70B3D59F0* ID_OUI_FROM_DATABASE=FUJICOM Co.,Ltd. OUI:70B3D576F* ID_OUI_FROM_DATABASE=OTI LTD OUI:70B3D54EB* ID_OUI_FROM_DATABASE=INFOSOFT DIGITAL DESIGN & SERVICES PRIVATE LIMITED OUI:70B3D5D12* ID_OUI_FROM_DATABASE=FIDELTRONIK POLAND SP. Z O.O. OUI:70B3D58F0* ID_OUI_FROM_DATABASE=ERAESEEDS co.,ltd. OUI:70B3D5EE5* ID_OUI_FROM_DATABASE=Beijing Hzhytech Technology Co.Ltd OUI:70B3D5BED* ID_OUI_FROM_DATABASE=Itrinegy Ltd. OUI:70B3D5AF5* ID_OUI_FROM_DATABASE=Net And Print Inc. OUI:70B3D564A* ID_OUI_FROM_DATABASE=Netbric Technology Co.,Ltd. OUI:70B3D5ECA* ID_OUI_FROM_DATABASE=Transtronic AB OUI:70B3D5852* ID_OUI_FROM_DATABASE=NetBoxSC, LLC OUI:70B3D5E76* ID_OUI_FROM_DATABASE=Dorsett Technologies, Inc. OUI:70B3D5172* ID_OUI_FROM_DATABASE=LumiGrow, Inc OUI:70B3D58A4* ID_OUI_FROM_DATABASE=Phyton, Inc. Microsystems and Development Tools OUI:70B3D5166* ID_OUI_FROM_DATABASE=SERIAL IMAGE INC. OUI:70B3D5E59* ID_OUI_FROM_DATABASE=FRACARRO SPA OUI:70B3D576D* ID_OUI_FROM_DATABASE=Trimble OUI:70B3D5F73* ID_OUI_FROM_DATABASE=ASL Holdings OUI:70B3D5D0E* ID_OUI_FROM_DATABASE=Beijing Aumiwalker technology CO.,LTD OUI:70B3D5827* ID_OUI_FROM_DATABASE=Metromatics Pty Ltd OUI:70B3D5F54* ID_OUI_FROM_DATABASE=Revolution Retail Systems OUI:70B3D5B91* ID_OUI_FROM_DATABASE=Dynetics, Inc. OUI:70B3D54DE* ID_OUI_FROM_DATABASE=Oso Technologies, Inc. OUI:70B3D57CE* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D5916* ID_OUI_FROM_DATABASE=Techno Mathematical Co.,Ltd OUI:70B3D5958* ID_OUI_FROM_DATABASE=pureLiFi Ltd OUI:70B3D54F4* ID_OUI_FROM_DATABASE=WiTagg, Inc OUI:70B3D5F4C* ID_OUI_FROM_DATABASE=Global Lightning Protection Services A(S OUI:70B3D5789* ID_OUI_FROM_DATABASE=SEMEX-EngCon GmbH OUI:70B3D5CFD* ID_OUI_FROM_DATABASE=iLOQ Oy OUI:70B3D5BAD* ID_OUI_FROM_DATABASE=Technik & Design GmbH OUI:70B3D5324* ID_OUI_FROM_DATABASE=Thales Nederland BV OUI:70B3D5935* ID_OUI_FROM_DATABASE=Sensor Developments OUI:70B3D5431* ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L. OUI:70B3D5C73* ID_OUI_FROM_DATABASE=C.D.N.CORPORATION OUI:70B3D5D80* ID_OUI_FROM_DATABASE=AMMT GmbH OUI:70B3D5D0A* ID_OUI_FROM_DATABASE=Private OUI:70B3D5CE3* ID_OUI_FROM_DATABASE=Dalcnet srl OUI:70B3D5AB5* ID_OUI_FROM_DATABASE=BroadSoft Inc OUI:70B3D59CA* ID_OUI_FROM_DATABASE=KOMSIS ELEKTRONIK SISTEMLERI SAN. TIC. LTD.STI OUI:70B3D50E6* ID_OUI_FROM_DATABASE=Nasdaq OUI:70B3D5087* ID_OUI_FROM_DATABASE=Tempus Fugit Consoles bvba OUI:70B3D57B7* ID_OUI_FROM_DATABASE=LSB - LA SALLE BLANCHE OUI:70B3D5E30* ID_OUI_FROM_DATABASE=QUISS AG OUI:70B3D5D2D* ID_OUI_FROM_DATABASE=Evolute Systems Private Limited OUI:70B3D5B35* ID_OUI_FROM_DATABASE=Rexxam Co.,Ltd. OUI:70B3D579B* ID_OUI_FROM_DATABASE=Soniclean Pty Ltd OUI:70B3D5F72* ID_OUI_FROM_DATABASE=Hanshin Electronics OUI:70B3D5AA8* ID_OUI_FROM_DATABASE=West-Com Nurse Call Systems, Inc. OUI:70B3D5DF6* ID_OUI_FROM_DATABASE=Tiab Limited OUI:70B3D53E3* ID_OUI_FROM_DATABASE=Head OUI:70B3D5285* ID_OUI_FROM_DATABASE=Bentec GmbH Drilling & Oilfield Systems OUI:70B3D544E* ID_OUI_FROM_DATABASE=Solace Systems Inc. OUI:70B3D513F* ID_OUI_FROM_DATABASE=Farmobile OUI:70B3D510C* ID_OUI_FROM_DATABASE=Vocality International OUI:70B3D5D48* ID_OUI_FROM_DATABASE=HEADROOM Broadcast GmbH OUI:70B3D599F* ID_OUI_FROM_DATABASE=Confed Holding B.V. OUI:70B3D5AE3* ID_OUI_FROM_DATABASE=Zhejiang Wellsun Electric Meter Co.,Ltd OUI:70B3D5BEF* ID_OUI_FROM_DATABASE=Sensortech Systems Inc. OUI:70B3D5B24* ID_OUI_FROM_DATABASE=Datasat Digital Entertainment OUI:70B3D50C1* ID_OUI_FROM_DATABASE=Nexus Technologies Pty Ltd OUI:70B3D5E6E* ID_OUI_FROM_DATABASE=Lieron BVBA OUI:70B3D501C* ID_OUI_FROM_DATABASE=Kumu Networks OUI:70B3D5799* ID_OUI_FROM_DATABASE=Vitec System Engineering Inc. OUI:70B3D5DE8* ID_OUI_FROM_DATABASE=Nation-E Ltd. OUI:70B3D583F* ID_OUI_FROM_DATABASE=Lumine Lighting Solutions Oy OUI:70B3D5E23* ID_OUI_FROM_DATABASE=Smith Meter, Inc. OUI:70B3D5A6E* ID_OUI_FROM_DATABASE=JSC Electrical Equipment Factory OUI:70B3D5F7E* ID_OUI_FROM_DATABASE=Alpha Elettronica s.r.l. OUI:70B3D541E* ID_OUI_FROM_DATABASE=Redler Computers OUI:70B3D5D0D* ID_OUI_FROM_DATABASE=Logiwaste AB OUI:70B3D5F2C* ID_OUI_FROM_DATABASE=Hengen Technologies GmbH OUI:70B3D5459* ID_OUI_FROM_DATABASE=Protium Technologies, Inc. OUI:70B3D5811* ID_OUI_FROM_DATABASE=CJSC «INTERSET» OUI:70B3D56ED* ID_OUI_FROM_DATABASE=Wiingtech International Co. LTD. OUI:70B3D5F39* ID_OUI_FROM_DATABASE=Zenros ApS OUI:70B3D5C56* ID_OUI_FROM_DATABASE=TELETASK OUI:70B3D5E58* ID_OUI_FROM_DATABASE=Thurlby Thandar Instruments LTD OUI:70B3D50AB* ID_OUI_FROM_DATABASE=KST technology OUI:70B3D5062* ID_OUI_FROM_DATABASE=RM Michaelides Software & Elektronik GmbH OUI:70B3D571E* ID_OUI_FROM_DATABASE=Motec Pty Ltd OUI:70B3D5FF3* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D58E0* ID_OUI_FROM_DATABASE=SOUDAX EQUIPEMENTS OUI:70B3D5412* ID_OUI_FROM_DATABASE=TATTILE SRL OUI:70B3D5E75* ID_OUI_FROM_DATABASE=Nke OUI:70B3D5DE7* ID_OUI_FROM_DATABASE=Innominds Software Private Limited OUI:70B3D51F4* ID_OUI_FROM_DATABASE=Hangzhou Woosiyuan Communication Co.,Ltd. OUI:70B3D5092* ID_OUI_FROM_DATABASE=inomed Medizintechnik GmbH OUI:70B3D51A1* ID_OUI_FROM_DATABASE=HMicro Inc OUI:70B3D5B8D* ID_OUI_FROM_DATABASE=JungwooEng Co., Ltd OUI:70B3D520C* ID_OUI_FROM_DATABASE=Siemens Healthcare Diagnostics OUI:70B3D5709* ID_OUI_FROM_DATABASE=AML OUI:70B3D5682* ID_OUI_FROM_DATABASE=Rosslare Enterprises Limited OUI:70B3D5986* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D50A4* ID_OUI_FROM_DATABASE=Communication Technology Ltd. OUI:70B3D5A99* ID_OUI_FROM_DATABASE=Bandelin electronic GmbH & Co. KG OUI:70B3D57EF* ID_OUI_FROM_DATABASE=CRAVIS CO., LIMITED OUI:70B3D5A62* ID_OUI_FROM_DATABASE=Environexus OUI:70B3D5E92* ID_OUI_FROM_DATABASE=FUJI DATA SYSTEM CO.,LTD. OUI:70B3D5C6D* ID_OUI_FROM_DATABASE=Cyviz AS OUI:70B3D5C43* ID_OUI_FROM_DATABASE=Future Skies OUI:70B3D5D4E* ID_OUI_FROM_DATABASE=FLSmidth OUI:70B3D51AC* ID_OUI_FROM_DATABASE=SVP Broadcast Microwave S.L. OUI:70B3D5090* ID_OUI_FROM_DATABASE=POWERCRAFT ELECTRONICS PVT. LTD. OUI:70B3D53F1* ID_OUI_FROM_DATABASE=Olympus NDT Canada OUI:70B3D59A7* ID_OUI_FROM_DATABASE=Honeywell OUI:70B3D5DC5* ID_OUI_FROM_DATABASE=Excel Medical Electronics LLC OUI:70B3D501D* ID_OUI_FROM_DATABASE=Weigl Elektronik & Mediaprojekte OUI:70B3D5F68* ID_OUI_FROM_DATABASE=AL ZAJEL MODERN TELECOMM OUI:70B3D5DEC* ID_OUI_FROM_DATABASE=Condev-Automation GmbH OUI:70B3D5564* ID_OUI_FROM_DATABASE=christmann informationstechnik + medien GmbH & Co. KG OUI:70B3D5E07* ID_OUI_FROM_DATABASE=Baader Planetarium GmbH OUI:70B3D528E* ID_OUI_FROM_DATABASE=TEX COMPUTER SRL OUI:70B3D5655* ID_OUI_FROM_DATABASE=AOT System GmbH OUI:70B3D5A2F* ID_OUI_FROM_DATABASE=Botek Systems AB OUI:70B3D5B15* ID_OUI_FROM_DATABASE=Eta Beta Srl OUI:70B3D5B2A* ID_OUI_FROM_DATABASE=Myro Control, LLC OUI:70B3D5FB0* ID_OUI_FROM_DATABASE=Rohde&Schwarz Topex SA OUI:70B3D5433* ID_OUI_FROM_DATABASE=Flexsolution APS OUI:70B3D5077* ID_OUI_FROM_DATABASE=InAccess Networks SA OUI:70B3D55E8* ID_OUI_FROM_DATABASE=VITEC OUI:70B3D50FB* ID_OUI_FROM_DATABASE=Cygnus LLC OUI:70B3D5DDD* ID_OUI_FROM_DATABASE=BIO RAD LABORATORIES OUI:70B3D554E* ID_OUI_FROM_DATABASE=RFL Electronics, Inc. OUI:70B3D5BBD* ID_OUI_FROM_DATABASE=Providius Corp OUI:70B3D5C78* ID_OUI_FROM_DATABASE=NETA Elektronik AS OUI:70B3D5BCA* ID_OUI_FROM_DATABASE=Deymed Diagnostic OUI:70B3D5EE4* ID_OUI_FROM_DATABASE=O-Net Automation Technology (Shenzhen)Limited OUI:70B3D55B5* ID_OUI_FROM_DATABASE=Lehigh Electric Products Co OUI:70B3D5B8C* ID_OUI_FROM_DATABASE=ePOINT Embedded Computing Limited OUI:70B3D540A* ID_OUI_FROM_DATABASE=Monroe Electronics, Inc. OUI:70B3D5109* ID_OUI_FROM_DATABASE=DITEST FAHRZEUGDIAGNOSE GMBH OUI:70B3D5F63* ID_OUI_FROM_DATABASE=Ars Products OUI:70B3D50AA* ID_OUI_FROM_DATABASE=Wanco Inc OUI:70B3D53ED* ID_OUI_FROM_DATABASE=Ultra Electronics Sonar System Division OUI:001BC50C1* ID_OUI_FROM_DATABASE=EREE Electronique OUI:001BC50C0* ID_OUI_FROM_DATABASE=Digital Loggers, Inc. OUI:001BC50C7* ID_OUI_FROM_DATABASE=WIZZILAB SAS OUI:001BC50B3* ID_OUI_FROM_DATABASE=FSM Solutions Limited OUI:001BC50BD* ID_OUI_FROM_DATABASE=Bridge Diagnostics, Inc. OUI:001BC50AD* ID_OUI_FROM_DATABASE=Tierra Japan Co.,Ltd OUI:001BC50A9* ID_OUI_FROM_DATABASE=Elektrometal SA OUI:001BC50B7* ID_OUI_FROM_DATABASE=Autelis, LLC OUI:001BC50A3* ID_OUI_FROM_DATABASE=P A Network Laboratory Co.,Ltd OUI:001BC50A1* ID_OUI_FROM_DATABASE=Hangzhou Zhiping Technology Co., Ltd. OUI:001BC5097* ID_OUI_FROM_DATABASE=Plexstar Inc. OUI:001BC5094* ID_OUI_FROM_DATABASE=reelyActive OUI:001BC509B* ID_OUI_FROM_DATABASE=YIK Corporation OUI:001BC509E* ID_OUI_FROM_DATABASE=K+K Messtechnik GmbH OUI:001BC508D* ID_OUI_FROM_DATABASE=EUREK SRL OUI:001BC5091* ID_OUI_FROM_DATABASE=3green ApS OUI:001BC508A* ID_OUI_FROM_DATABASE=Topicon OUI:001BC507C* ID_OUI_FROM_DATABASE=head OUI:001BC5078* ID_OUI_FROM_DATABASE=Donbass Soft Ltd and Co.KG OUI:001BC5082* ID_OUI_FROM_DATABASE=TGS Geophysical Company (UK) Limited OUI:001BC5085* ID_OUI_FROM_DATABASE=Oberon microsystems, Inc. OUI:001BC5086* ID_OUI_FROM_DATABASE=CAST Group of Companies Inc. OUI:001BC5064* ID_OUI_FROM_DATABASE=Enkora Oy Ltd OUI:001BC505E* ID_OUI_FROM_DATABASE=Ecomed-Complex OUI:001BC506E* ID_OUI_FROM_DATABASE=Two Dimensional Instruments, LLC OUI:001BC5068* ID_OUI_FROM_DATABASE=HCS KABLOLAMA SISTEMLERI SAN. ve TIC.A.S. OUI:001BC5072* ID_OUI_FROM_DATABASE=Ohio Semitronics, Inc. OUI:001BC505A* ID_OUI_FROM_DATABASE=POSTEC DATA SYSTEMS OUI:001BC504A* ID_OUI_FROM_DATABASE=Certis Technology International Pte Ltd OUI:001BC5054* ID_OUI_FROM_DATABASE=Private OUI:001BC5050* ID_OUI_FROM_DATABASE=TeliSwitch Solutions OUI:001BC5046* ID_OUI_FROM_DATABASE=Trans-European Research and Education Networking Association (TERENA) OUI:001BC5040* ID_OUI_FROM_DATABASE=OOO Actidata OUI:001BC503B* ID_OUI_FROM_DATABASE=Promixis, LLC OUI:001BC5034* ID_OUI_FROM_DATABASE=InterCEL Pty Ltd OUI:001BC5031* ID_OUI_FROM_DATABASE=ADIXEIN LIMITED OUI:001BC502A* ID_OUI_FROM_DATABASE=Analytical Instrument Systems, Inc. OUI:001BC5027* ID_OUI_FROM_DATABASE=CAMEA, spol. s r.o. OUI:001BC5023* ID_OUI_FROM_DATABASE=MAGO di Della Mora Walter OUI:001BC501F* ID_OUI_FROM_DATABASE=Saturn Solutions Ltd OUI:001BC5012* ID_OUI_FROM_DATABASE=Tokyo Cosmos Electric, Inc. OUI:001BC500F* ID_OUI_FROM_DATABASE=Simavita Pty Ltd OUI:001BC500B* ID_OUI_FROM_DATABASE=Private OUI:001BC500C* ID_OUI_FROM_DATABASE=Quantum Technology Sciences, Inc. OUI:001BC5008* ID_OUI_FROM_DATABASE=Dalaj Electro-Telecom OUI:001BC5005* ID_OUI_FROM_DATABASE=Private OUI:001BC5016* ID_OUI_FROM_DATABASE=Energotechnica OOO NPP Ltd OUI:001BC5002* ID_OUI_FROM_DATABASE=GORAMO - Janusz Gorecki OUI:001BC5019* ID_OUI_FROM_DATABASE=Dunlop Systems & Components OUI:70B3D5D81* ID_OUI_FROM_DATABASE=PDD Group Ltd OUI:70B3D5B7A* ID_OUI_FROM_DATABASE=MAHLE OUI:70B3D5AFE* ID_OUI_FROM_DATABASE=MESOTECHNIC OUI:70B3D5659* ID_OUI_FROM_DATABASE=E2G srl OUI:70B3D54A1* ID_OUI_FROM_DATABASE=Herholdt Controls srl OUI:70B3D5D1B* ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. OUI:70B3D5D9E* ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. OUI:70B3D5DB4* ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd OUI:70B3D5781* ID_OUI_FROM_DATABASE=Project Service S.a.s. OUI:70B3D5A72* ID_OUI_FROM_DATABASE=Business Marketers Group, Inc. OUI:70B3D533B* ID_OUI_FROM_DATABASE=Seal Shield, LLC OUI:70B3D5E49* ID_OUI_FROM_DATABASE=Kendrion Mechatronics Center GmbH OUI:70B3D5214* ID_OUI_FROM_DATABASE=signalparser OUI:70B3D53C6* ID_OUI_FROM_DATABASE=ACD Elekronik GmbH OUI:70B3D5384* ID_OUI_FROM_DATABASE=Sensohive Technologies OUI:70B3D5893* ID_OUI_FROM_DATABASE=Cubitech OUI:70B3D509E* ID_OUI_FROM_DATABASE=MobiPromo OUI:70B3D549E* ID_OUI_FROM_DATABASE=CAPTEMP, Lda OUI:70B3D54B6* ID_OUI_FROM_DATABASE=VEILUX INC. OUI:70B3D57CF* ID_OUI_FROM_DATABASE=ORCA Technologies, LLC OUI:70B3D55A3* ID_OUI_FROM_DATABASE=CT Company OUI:70B3D580A* ID_OUI_FROM_DATABASE=SENSING LABS OUI:70B3D5E45* ID_OUI_FROM_DATABASE=Momentum Data Systems OUI:70B3D5059* ID_OUI_FROM_DATABASE=Pro-Digital Projetos Eletronicos Ltda OUI:70B3D5091* ID_OUI_FROM_DATABASE=PROFITT Ltd OUI:70B3D5647* ID_OUI_FROM_DATABASE=KZTA OUI:70B3D56DF* ID_OUI_FROM_DATABASE=Mango DSP, Inc. OUI:70B3D5CBE* ID_OUI_FROM_DATABASE=Ensura Solutions BV OUI:70B3D5CAC* ID_OUI_FROM_DATABASE=CRDE OUI:70B3D58B9* ID_OUI_FROM_DATABASE=Toptech Systems, Inc. OUI:70B3D574E* ID_OUI_FROM_DATABASE=PushCorp, Inc. OUI:70B3D5FD2* ID_OUI_FROM_DATABASE=DALIAN LEVEAR ELECTRIC CO., LTD OUI:70B3D5F08* ID_OUI_FROM_DATABASE=Szabo Software & Engineering UK Ltd OUI:70B3D56A1* ID_OUI_FROM_DATABASE=GLIAL TECHNOLOGY OUI:70B3D5955* ID_OUI_FROM_DATABASE=Dynacard Co., Ltd. OUI:70B3D512B* ID_OUI_FROM_DATABASE=RIC Electronics OUI:70B3D517E* ID_OUI_FROM_DATABASE=OCULI VISION OUI:70B3D5046* ID_OUI_FROM_DATABASE=Shenzhen Rihuida Electronics Co,. Ltd OUI:70B3D5268* ID_OUI_FROM_DATABASE=Cardinal Scale Mfg Co OUI:70B3D5B7E* ID_OUI_FROM_DATABASE=Elbit Systems of America - Fort Worth Operations OUI:70B3D5DB5* ID_OUI_FROM_DATABASE=Xiamen Point Circle Technologh Co,ltd OUI:70B3D5429* ID_OUI_FROM_DATABASE=Redco Audio Inc OUI:70B3D52E7* ID_OUI_FROM_DATABASE=Atos spa OUI:70B3D5766* ID_OUI_FROM_DATABASE=Tirasoft Nederland OUI:70B3D517D* ID_OUI_FROM_DATABASE=Entech Electronics OUI:70B3D599A* ID_OUI_FROM_DATABASE=KEVIC. inc, OUI:70B3D502A* ID_OUI_FROM_DATABASE=BAE Systems Surface Ships Limited OUI:70B3D5DE2* ID_OUI_FROM_DATABASE=ACD Elekronik GmbH OUI:70B3D5FFF* ID_OUI_FROM_DATABASE=Private OUI:70B3D5494* ID_OUI_FROM_DATABASE=Schildknecht AG OUI:70B3D5BF2* ID_OUI_FROM_DATABASE=TWIN DEVELOPMENT OUI:70B3D5901* ID_OUI_FROM_DATABASE=ATS-CONVERS OUI:70B3D5654* ID_OUI_FROM_DATABASE=EMAC, Inc. OUI:70B3D5F6E* ID_OUI_FROM_DATABASE=Streambox Inc OUI:70B3D5D5B* ID_OUI_FROM_DATABASE=WyreStorm Technologies Ltd OUI:70B3D56CD* ID_OUI_FROM_DATABASE=NORTHBOUND NETWORKS PTY. LTD. OUI:70B3D5B7C* ID_OUI_FROM_DATABASE=Electronic Navigation Ltd OUI:70B3D5C92* ID_OUI_FROM_DATABASE=Unitro Fleischmann OUI:70B3D58A0* ID_OUI_FROM_DATABASE=DM RADIOCOM OUI:70B3D5081* ID_OUI_FROM_DATABASE=IST Technologies (SHENZHEN) Limited OUI:70B3D5C77* ID_OUI_FROM_DATABASE=Yönnet Akıllı Bina ve Otomasyon Sistemleri OUI:70B3D5D74* ID_OUI_FROM_DATABASE=Sandia National Laboratories OUI:70B3D5FCF* ID_OUI_FROM_DATABASE=Acc+Ess Ltd OUI:70B3D53C0* ID_OUI_FROM_DATABASE=DK-Technologies A/S OUI:70B3D52F6* ID_OUI_FROM_DATABASE=TATTILE SRL OUI:70B3D5364* ID_OUI_FROM_DATABASE=ADAMCZEWSKI elektronische Messtechnik GmbH OUI:70B3D548E* ID_OUI_FROM_DATABASE=Allim System Co,.Ltd. OUI:70B3D59ED* ID_OUI_FROM_DATABASE=Benchmark Electronics BV OUI:70B3D5774* ID_OUI_FROM_DATABASE=Micram Instruments Ltd OUI:70B3D576A* ID_OUI_FROM_DATABASE=Swiftnet SOC Ltd OUI:70B3D5D7E* ID_OUI_FROM_DATABASE=Triax A/S OUI:70B3D5061* ID_OUI_FROM_DATABASE=IntelliDesign Pty Ltd OUI:70B3D5383* ID_OUI_FROM_DATABASE=LPA Excil Electronics OUI:70B3D59F6* ID_OUI_FROM_DATABASE=Edgeware AB OUI:70B3D5E0F* ID_OUI_FROM_DATABASE=Vtron Pty Ltd OUI:70B3D5504* ID_OUI_FROM_DATABASE=Xsight Systems Ltd. OUI:70B3D52CE* ID_OUI_FROM_DATABASE=KDT OUI:70B3D5C07* ID_OUI_FROM_DATABASE=ARECO OUI:70B3D5DCA* ID_OUI_FROM_DATABASE=DSan Corporation OUI:70B3D525B* ID_OUI_FROM_DATABASE=GID Industrial OUI:70B3D5313* ID_OUI_FROM_DATABASE=DIEHL Controls OUI:70B3D5278* ID_OUI_FROM_DATABASE=Private OUI:70B3D5645* ID_OUI_FROM_DATABASE=Project Decibel, Inc. OUI:70B3D5377* ID_OUI_FROM_DATABASE=Monnit Corporation OUI:70B3D5A12* ID_OUI_FROM_DATABASE=QUERCUS TECHNOLOGIES, S.L. OUI:70B3D5B34* ID_OUI_FROM_DATABASE=Medtronic OUI:70B3D5303* ID_OUI_FROM_DATABASE=Fuchu Giken, Inc. OUI:70B3D56F9* ID_OUI_FROM_DATABASE=ENVItech s.r.o. OUI:70B3D5100* ID_OUI_FROM_DATABASE=Gupsy GmbH OUI:70B3D5C89* ID_OUI_FROM_DATABASE=ARD OUI:70B3D52E0* ID_OUI_FROM_DATABASE=Peter Huber OUI:70B3D5088* ID_OUI_FROM_DATABASE=OptiScan Biomedical Corp. OUI:70B3D5226* ID_OUI_FROM_DATABASE=Yaviar OUI:70B3D5D57* ID_OUI_FROM_DATABASE=TRIUMPH BOARD a.s. OUI:70B3D54DB* ID_OUI_FROM_DATABASE=Temperature@lert OUI:70B3D5343* ID_OUI_FROM_DATABASE=Elektro-System s.c. OUI:70B3D59F2* ID_OUI_FROM_DATABASE=Acorde Technologies OUI:70B3D5E3B* ID_OUI_FROM_DATABASE=ComNav Technology Ltd. OUI:70B3D5339* ID_OUI_FROM_DATABASE=Sierra Nevada Corporation OUI:70B3D5703* ID_OUI_FROM_DATABASE=StromIdee GmbH OUI:70B3D5E6D* ID_OUI_FROM_DATABASE=Domus S.C. OUI:70B3D5F00* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D57C3* ID_OUI_FROM_DATABASE=Flexim Security Oy OUI:70B3D53E4* ID_OUI_FROM_DATABASE=Neptec Technologies Corp. OUI:70B3D5595* ID_OUI_FROM_DATABASE=PLR Prueftechnik Linke und Ruehe GmbH OUI:70B3D5E36* ID_OUI_FROM_DATABASE=Guidance Navigation Limited OUI:70B3D5B47* ID_OUI_FROM_DATABASE=DSIT Solutions LTD OUI:70B3D52F1* ID_OUI_FROM_DATABASE=Inspike S.R.L. OUI:70B3D5AFB* ID_OUI_FROM_DATABASE=Shanghai Tianhe Automation Instrumentation Co., Ltd. OUI:70B3D5AD5* ID_OUI_FROM_DATABASE=Birdland Audio OUI:70B3D5F93* ID_OUI_FROM_DATABASE=Hella Gutmann Solutions GmbH OUI:70B3D5F01* ID_OUI_FROM_DATABASE=Software Systems Plus OUI:70B3D53E2* ID_OUI_FROM_DATABASE=AVI Pty Ltd OUI:70B3D5C2A* ID_OUI_FROM_DATABASE=Array Telepresence OUI:70B3D5F8E* ID_OUI_FROM_DATABASE=Isabellenhütte Heusler Gmbh &Co KG OUI:70B3D5FA2* ID_OUI_FROM_DATABASE=Sarokal Test Systems Oy OUI:70B3D5134* ID_OUI_FROM_DATABASE=Conjing Networks Inc. OUI:70B3D5208* ID_OUI_FROM_DATABASE=DSP DESIGN LTD OUI:70B3D5870* ID_OUI_FROM_DATABASE=bentrup Industriesteuerungen OUI:70B3D54D8* ID_OUI_FROM_DATABASE=Versilis Inc. OUI:70B3D5A26* ID_OUI_FROM_DATABASE=Hear Gear, Inc. OUI:70B3D5C87* ID_OUI_FROM_DATABASE=Siemens AG OUI:70B3D55FF* ID_OUI_FROM_DATABASE=Vaisala Oyj OUI:70B3D57AE* ID_OUI_FROM_DATABASE=Exi Flow Measurement Ltd OUI:70B3D54DF* ID_OUI_FROM_DATABASE=Nidec Avtron Automation Corp OUI:70B3D54AD* ID_OUI_FROM_DATABASE=GACI OUI:70B3D5932* ID_OUI_FROM_DATABASE=Rohde&Schwarz Topex SA OUI:70B3D5DF9* ID_OUI_FROM_DATABASE=Korea Plant Maintenance OUI:70B3D5BAE* ID_OUI_FROM_DATABASE=WARECUBE,INC OUI:70B3D5119* ID_OUI_FROM_DATABASE=Private OUI:70B3D5C85* ID_OUI_FROM_DATABASE=Solid State Disks Ltd OUI:70B3D5A44* ID_OUI_FROM_DATABASE=FSR Inc OUI:70B3D5347* ID_OUI_FROM_DATABASE=OAS Sweden AB OUI:70B3D5361* ID_OUI_FROM_DATABASE=Parent Power OUI:70B3D5FA4* ID_OUI_FROM_DATABASE=Energybox Limited OUI:70B3D5A2A* ID_OUI_FROM_DATABASE=Redwood Systems OUI:70B3D573E* ID_OUI_FROM_DATABASE=Trident RFID Pty Ltd OUI:70B3D565D* ID_OUI_FROM_DATABASE=GEGA ELECTRONIQUE OUI:70B3D59BD* ID_OUI_FROM_DATABASE=Signal Processing Devices Sweden AB OUI:70B3D5AA7* ID_OUI_FROM_DATABASE=ATEME OUI:70B3D520E* ID_OUI_FROM_DATABASE=Amrehn & Partner EDV-Service GmbH OUI:70B3D5E70* ID_OUI_FROM_DATABASE=DISK Multimedia s.r.o. OUI:70B3D5EAB* ID_OUI_FROM_DATABASE=APEN GROUP SpA (VAT IT08767740155) OUI:70B3D579E* ID_OUI_FROM_DATABASE=CW2. Gmbh & Co. KG OUI:70B3D5E7C* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D5EB1* ID_OUI_FROM_DATABASE=CP contech electronic GmbH OUI:70B3D5D97* ID_OUI_FROM_DATABASE=BRS Sistemas Eletronicos OUI:70B3D563A* ID_OUI_FROM_DATABASE=DAVE SRL OUI:70B3D5C9B* ID_OUI_FROM_DATABASE=Tieto Sweden AB OUI:70B3D54F0* ID_OUI_FROM_DATABASE=Li Seng Technology Ltd., OUI:70B3D5F92* ID_OUI_FROM_DATABASE=TechOne OUI:70B3D5D1F* ID_OUI_FROM_DATABASE=Embsec AB OUI:70B3D5796* ID_OUI_FROM_DATABASE=GAMPT mbH OUI:70B3D50A5* ID_OUI_FROM_DATABASE=FUELCELLPOWER OUI:70B3D5AB9* ID_OUI_FROM_DATABASE=Dynamic Controls OUI:70B3D5C25* ID_OUI_FROM_DATABASE=speedsignal GmbH OUI:70B3D56E4* ID_OUI_FROM_DATABASE=Institute of Power Engineering, Gdansk Division OUI:70B3D5D46* ID_OUI_FROM_DATABASE=Contineo s.r.o. OUI:70B3D5665* ID_OUI_FROM_DATABASE=CertUsus GmbH OUI:70B3D52CF* ID_OUI_FROM_DATABASE=MB Connect Line GmbH OUI:70B3D5A50* ID_OUI_FROM_DATABASE=LECIP CORPORATION OUI:70B3D5A4B* ID_OUI_FROM_DATABASE=McKay Brothers LLC OUI:70B3D55E4* ID_OUI_FROM_DATABASE=DSP DESIGN OUI:70B3D5DF0* ID_OUI_FROM_DATABASE=astozi consulting Tomasz Zieba OUI:70B3D5CF3* ID_OUI_FROM_DATABASE=Mesh Motion Inc OUI:70B3D539C* ID_OUI_FROM_DATABASE=General Dynamics C4 Systems OUI:70B3D50B3* ID_OUI_FROM_DATABASE=Reonix Automation OUI:70B3D534A* ID_OUI_FROM_DATABASE=PAVO TASARIM ÜRETİM TİC A.Ş. OUI:70B3D56E5* ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH OUI:70B3D58F5* ID_OUI_FROM_DATABASE=Stmovic OUI:70B3D5ABF* ID_OUI_FROM_DATABASE=AGR International OUI:70B3D5755* ID_OUI_FROM_DATABASE=LandmarkTech Systems Technology Co.,Ltd. OUI:70B3D5B3C* ID_OUI_FROM_DATABASE=DORLET SAU OUI:70B3D557B* ID_OUI_FROM_DATABASE=ELAMAKATO GmbH OUI:70B3D5A57* ID_OUI_FROM_DATABASE=PCSC OUI:70B3D58E1* ID_OUI_FROM_DATABASE=WoKa-Elektronik GmbH OUI:70B3D5BA4* ID_OUI_FROM_DATABASE=EIWA GIKEN INC. OUI:70B3D5F8C* ID_OUI_FROM_DATABASE=EUROPEAN ADVANCED TECHNOLOGIES OUI:70B3D585C* ID_OUI_FROM_DATABASE=Robot Pub Group OUI:70B3D5AFA* ID_OUI_FROM_DATABASE=Power Security Systems Ltd. OUI:70B3D53D9* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D577C* ID_OUI_FROM_DATABASE=HUSTY M.Styczen J.Hupert Sp.J. OUI:70B3D5CDE* ID_OUI_FROM_DATABASE=Multipure International OUI:70B3D5F2B* ID_OUI_FROM_DATABASE=SENSYS GmbH OUI:70B3D5731* ID_OUI_FROM_DATABASE=Phoniro Systems AB OUI:70B3D5941* ID_OUI_FROM_DATABASE=Triax A/S OUI:70B3D536D* ID_OUI_FROM_DATABASE=Cyberteam Sp z o o OUI:70B3D5B82* ID_OUI_FROM_DATABASE=Lookout Portable Security OUI:70B3D5220* ID_OUI_FROM_DATABASE=Private OUI:70B3D5D0C* ID_OUI_FROM_DATABASE=Connor Winfield LTD OUI:70B3D5CB7* ID_OUI_FROM_DATABASE=HKC Limited OUI:70B3D53E1* ID_OUI_FROM_DATABASE=Barnstormer Softworks OUI:70B3D596F* ID_OUI_FROM_DATABASE=4CAM GmbH OUI:70B3D58CE* ID_OUI_FROM_DATABASE=CORES Corporation OUI:70B3D523C* ID_OUI_FROM_DATABASE=Quasonix, LLC OUI:70B3D535F* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D579A* ID_OUI_FROM_DATABASE=Innerspec Technologies Inc. OUI:70B3D551D* ID_OUI_FROM_DATABASE=Tecnint HTE SRL OUI:70B3D561F* ID_OUI_FROM_DATABASE=Labotect Labor-Technik-Göttingen GmbH OUI:70B3D54C1* ID_OUI_FROM_DATABASE=QUERCUS TECHNOLOGIES, S. L. OUI:70B3D5A0E* ID_OUI_FROM_DATABASE=Vetaphone A/S OUI:70B3D55AA* ID_OUI_FROM_DATABASE=Chugoku Electric Manufacturing Co.,Inc OUI:70B3D52D4* ID_OUI_FROM_DATABASE=CT Company OUI:70B3D5C96* ID_OUI_FROM_DATABASE=UNI DIMENXI SDN BHD OUI:70B3D5E74* ID_OUI_FROM_DATABASE=Exfrontier Co., Ltd. OUI:70B3D5FD3* ID_OUI_FROM_DATABASE=AKIS technologies OUI:70B3D5E53* ID_OUI_FROM_DATABASE=MI INC. OUI:70B3D52F0* ID_OUI_FROM_DATABASE=Clock-O-Matic OUI:70B3D57A9* ID_OUI_FROM_DATABASE=adidas AG OUI:70B3D5AC8* ID_OUI_FROM_DATABASE=Heartland.Data Inc. OUI:70B3D5F2A* ID_OUI_FROM_DATABASE=WIBOND Informationssysteme GmbH OUI:70B3D52A5* ID_OUI_FROM_DATABASE=Taitotekniikka OUI:70B3D519C* ID_OUI_FROM_DATABASE=Kubu, Inc. OUI:70B3D503B* ID_OUI_FROM_DATABASE=SSL - Electrical Aerospace Ground Equipment Section OUI:70B3D5E9A* ID_OUI_FROM_DATABASE=Meta Computing Services, Corp OUI:70B3D5E26* ID_OUI_FROM_DATABASE=FEITIAN CO.,LTD. OUI:70B3D5E4C* ID_OUI_FROM_DATABASE=IAI-Israel Aerospace Industries MBT OUI:70B3D5A40* ID_OUI_FROM_DATABASE=STRACK LIFT AUTOMATION GmbH OUI:70B3D5016* ID_OUI_FROM_DATABASE=Guardian Controls International Ltd OUI:70B3D5A7A* ID_OUI_FROM_DATABASE=Fluid Management Technology OUI:70B3D5C6A* ID_OUI_FROM_DATABASE=Private OUI:70B3D5819* ID_OUI_FROM_DATABASE=«Intellect module» LLC OUI:70B3D5EF3* ID_OUI_FROM_DATABASE=octoScope OUI:70B3D59F4* ID_OUI_FROM_DATABASE=Tband srl OUI:70B3D535C* ID_OUI_FROM_DATABASE=ACS electronics srl OUI:70B3D528F* ID_OUI_FROM_DATABASE=Overline Systems OUI:70B3D5F38* ID_OUI_FROM_DATABASE=Scanvaegt Nordic A/S OUI:001BC50C5* ID_OUI_FROM_DATABASE=Gill Instruments Ltd OUI:70B3D5994* ID_OUI_FROM_DATABASE=KeFF Networks OUI:70B3D5B3D* ID_OUI_FROM_DATABASE=Inras GmbH OUI:001BC50BB* ID_OUI_FROM_DATABASE=Triax A/S OUI:001BC50B1* ID_OUI_FROM_DATABASE=Roslen Eco-Networking Products OUI:001BC50A7* ID_OUI_FROM_DATABASE=L.G.L. Electronics S.p.a. OUI:001BC509C* ID_OUI_FROM_DATABASE=S.I.C.E.S. srl OUI:001BC5092* ID_OUI_FROM_DATABASE=Arnouse Digital Devices, Corp. OUI:001BC5088* ID_OUI_FROM_DATABASE=UAB Kitron OUI:001BC5080* ID_OUI_FROM_DATABASE=LUMINO GmbH OUI:001BC5076* ID_OUI_FROM_DATABASE=PLAiR Media, Inc OUI:001BC506C* ID_OUI_FROM_DATABASE=Luxcon System Limited OUI:001BC505C* ID_OUI_FROM_DATABASE=Suretrak Global Pty Ltd OUI:001BC5062* ID_OUI_FROM_DATABASE=Sulaon Oy OUI:001BC5052* ID_OUI_FROM_DATABASE=Engineering Center ENERGOSERVICE OUI:001BC5058* ID_OUI_FROM_DATABASE=optiMEAS GmbH OUI:001BC5048* ID_OUI_FROM_DATABASE=XPossible Technologies Pte Ltd OUI:001BC504E* ID_OUI_FROM_DATABASE=Mitsubishi Electric India PVT. LTD OUI:001BC503E* ID_OUI_FROM_DATABASE=Daylight Solutions, Inc OUI:001BC5044* ID_OUI_FROM_DATABASE=ZAO "RADIUS Avtomatika" OUI:001BC5039* ID_OUI_FROM_DATABASE=EURESYS S.A. OUI:001BC502F* ID_OUI_FROM_DATABASE=Fibrain Co. Ltd. OUI:001BC5025* ID_OUI_FROM_DATABASE=andersen lighting GmbH OUI:001BC5020* ID_OUI_FROM_DATABASE=Momentum Data Systems OUI:001BC501D* ID_OUI_FROM_DATABASE=Rose + Herleth GbR OUI:001BC5021* ID_OUI_FROM_DATABASE=Openpeak, Inc OUI:001BC5010* ID_OUI_FROM_DATABASE=Softel SA de CV OUI:001BC5006* ID_OUI_FROM_DATABASE=TRIAX-HIRSCHMANN Multi-Media GmbH OUI:001BC501A* ID_OUI_FROM_DATABASE=ABA ELECTRONICS TECHNOLOGY CO.,LTD OUI:70B3D576E* ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. OUI:70B3D58F3* ID_OUI_FROM_DATABASE=TATTILE SRL OUI:70B3D5C7F* ID_OUI_FROM_DATABASE=TATTILE SRL OUI:70B3D55ED* ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG OUI:70B3D5AEA* ID_OUI_FROM_DATABASE=BBR Verkehrstechnik GmbH OUI:70B3D5EEE* ID_OUI_FROM_DATABASE=SOCIEDAD IBERICA DE CONSTRUCCIONES ELECTRICAS, S.A. (SICE) OUI:70B3D5794* ID_OUI_FROM_DATABASE=Shadin Avionics OUI:70B3D52EF* ID_OUI_FROM_DATABASE=IEM SA OUI:70B3D5B6D* ID_OUI_FROM_DATABASE=Movis OUI:70B3D5325* ID_OUI_FROM_DATABASE=BlueMark Innovations BV OUI:70B3D58B2* ID_OUI_FROM_DATABASE=NPF Modem, LLC OUI:70B3D53CC* ID_OUI_FROM_DATABASE=TerOpta Ltd OUI:70B3D55D1* ID_OUI_FROM_DATABASE=Software Motor Corp OUI:70B3D5A2E* ID_OUI_FROM_DATABASE=Kokam Co., Ltd OUI:70B3D58A6* ID_OUI_FROM_DATABASE=CRDE OUI:70B3D5FB5* ID_OUI_FROM_DATABASE=Orange Tree Technologies Ltd OUI:70B3D5E02* ID_OUI_FROM_DATABASE=YEHL & JORDAN LLC OUI:70B3D5F56* ID_OUI_FROM_DATABASE=VirtualHere Pty. Ltd. OUI:70B3D58BE* ID_OUI_FROM_DATABASE=Connoiseur Electronics Private Limited OUI:70B3D526B* ID_OUI_FROM_DATABASE=Sorama BV OUI:70B3D52FA* ID_OUI_FROM_DATABASE=Toray Medical Co.,Ltd OUI:70B3D5975* ID_OUI_FROM_DATABASE=Coester Automação Ltda OUI:70B3D513C* ID_OUI_FROM_DATABASE=Detec Systems Ltd OUI:70B3D5455* ID_OUI_FROM_DATABASE=Heartlandmicropayments OUI:70B3D5070* ID_OUI_FROM_DATABASE=Lumiplan Duhamel OUI:70B3D58D8* ID_OUI_FROM_DATABASE=VNG Corporation OUI:70B3D5392* ID_OUI_FROM_DATABASE=Contec DTx OUI:70B3D514D* ID_OUI_FROM_DATABASE=2-Observe OUI:70B3D5A9F* ID_OUI_FROM_DATABASE=Private OUI:70B3D59CB* ID_OUI_FROM_DATABASE=Alligator Communications OUI:70B3D5B67* ID_OUI_FROM_DATABASE=RedWave Labs Ltd OUI:70B3D5B93* ID_OUI_FROM_DATABASE=INTERNET PROTOCOLO LOGICA SL OUI:70B3D5B89* ID_OUI_FROM_DATABASE=IDA OUI:70B3D57E2* ID_OUI_FROM_DATABASE=Depro Électronique inc OUI:70B3D5772* ID_OUI_FROM_DATABASE=enModus OUI:70B3D53C5* ID_OUI_FROM_DATABASE=P4Q ELECTRONICS, S.L. OUI:70B3D5FE2* ID_OUI_FROM_DATABASE=Galileo Tıp Teknolojileri San. ve Tic. A.S. OUI:70B3D5C24* ID_OUI_FROM_DATABASE=Elbit Systems of America - Fort Worth Operations OUI:70B3D5AC6* ID_OUI_FROM_DATABASE=SMTC Corporation OUI:70B3D5028* ID_OUI_FROM_DATABASE=AT-Automation Technology GmbH OUI:70B3D50B9* ID_OUI_FROM_DATABASE=Easy Digital Concept OUI:70B3D5CF2* ID_OUI_FROM_DATABASE=tinnos OUI:70B3D59E0* ID_OUI_FROM_DATABASE=ES Industrial Systems Co., Ltd. OUI:70B3D566B* ID_OUI_FROM_DATABASE=Innitive B.V. OUI:70B3D58F6* ID_OUI_FROM_DATABASE=Dofuntech Co.,LTD. OUI:70B3D5A06* ID_OUI_FROM_DATABASE=Kopis Mobile LLC OUI:70B3D59F3* ID_OUI_FROM_DATABASE=IEEE Registration Authority OUI:70B3D5679* ID_OUI_FROM_DATABASE=EMAC, Inc. OUI:001BC5042* ID_OUI_FROM_DATABASE=ChamSys Ltd OUI:70B3D52F9* ID_OUI_FROM_DATABASE=CONSOSPY OUI:70B3D5BB8* ID_OUI_FROM_DATABASE=Al Kamel Systems S.L. OUI:70B3D5439* ID_OUI_FROM_DATABASE=TriLED OUI:70B3D5E48* ID_OUI_FROM_DATABASE=TDI. Co., LTD OUI:70B3D518D* ID_OUI_FROM_DATABASE=Foro Tel OUI:70B3D5A95* ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH OUI:70B3D5570* ID_OUI_FROM_DATABASE=Bayern Engineering GmbH & Co. KG OUI:70B3D5524* ID_OUI_FROM_DATABASE=Wuxi New Optical Communication Co.,Ltd. OUI:70B3D5DE0* ID_OUI_FROM_DATABASE=eCozy GmbH OUI:70B3D5C26* ID_OUI_FROM_DATABASE=Triple Play Communications OUI:70B3D591F* ID_OUI_FROM_DATABASE=JSC InformInvestGroup OUI:70B3D53E9* ID_OUI_FROM_DATABASE=APOLLO GIKEN Co.,Ltd. OUI:70B3D5773* ID_OUI_FROM_DATABASE=Rugged Science OUI:70B3D57AA* ID_OUI_FROM_DATABASE=Sadel S.p.A. OUI:70B3D56FB* ID_OUI_FROM_DATABASE=Shachihata Inc. OUI:70B3D5D73* ID_OUI_FROM_DATABASE=ERMINE Corporation OUI:70B3D5D3F* ID_OUI_FROM_DATABASE=GLOBALCOM ENGINEERING SPA OUI:70B3D5DF7* ID_OUI_FROM_DATABASE=Refecor Oy OUI:70B3D5152* ID_OUI_FROM_DATABASE=Xped Corporation Pty Ltd OUI:70B3D559D* ID_OUI_FROM_DATABASE=servicios de consultoria independiente S.L. OUI:70B3D5933* ID_OUI_FROM_DATABASE=SARL S@TIS OUI:70B3D504D* ID_OUI_FROM_DATABASE=Sicon srl OUI:70B3D57F2* ID_OUI_FROM_DATABASE=TCI OUI:70B3D5E4B* ID_OUI_FROM_DATABASE=DELTA OUI:70B3D52EA* ID_OUI_FROM_DATABASE=Schneider Electric Motion OUI:70B3D55FC* ID_OUI_FROM_DATABASE=SURTEC OUI:70B3D5328* ID_OUI_FROM_DATABASE=HIPODROMO DE AGUA CALIENTE SA CV OUI:70B3D5F85* ID_OUI_FROM_DATABASE=Solystic OUI:70B3D5A04* ID_OUI_FROM_DATABASE=Galea Electric S.L. OUI:70B3D56BE* ID_OUI_FROM_DATABASE=VANTAGE INTEGRATED SECURITY SOLUTIONS PVT LTD OUI:70B3D5A01* ID_OUI_FROM_DATABASE=FeldTech GmbH OUI:70B3D57C1* ID_OUI_FROM_DATABASE=Data Sciences International OUI:70B3D5903* ID_OUI_FROM_DATABASE=Cymtec Ltd OUI:70B3D51A0* ID_OUI_FROM_DATABASE=UFATECH LTD OUI:70B3D5EA4* ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. OUI:70B3D51AD* ID_OUI_FROM_DATABASE=Techworld Industries Ltd OUI:70B3D5866* ID_OUI_FROM_DATABASE=MEPS Realtime OUI:70B3D53D8* ID_OUI_FROM_DATABASE=Abitsoftware, Ltd. OUI:70B3D5F4D* ID_OUI_FROM_DATABASE=Honeywell International Inc. OUI:70B3D5230* ID_OUI_FROM_DATABASE=CT Company OUI:70B3D5FCD* ID_OUI_FROM_DATABASE=Engage Technologies OUI:70B3D507E* ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic CO., LTD OUI:70B3D5664* ID_OUI_FROM_DATABASE=Sankyo Intec co.,ltd OUI:70B3D54BA* ID_OUI_FROM_DATABASE=Sinftech LLC OUI:70B3D53FF* ID_OUI_FROM_DATABASE=Hydra Controls OUI:70B3D5470* ID_OUI_FROM_DATABASE=KITRON UAB OUI:70B3D552B* ID_OUI_FROM_DATABASE=GE Aviation Cheltenham OUI:70B3D587B* ID_OUI_FROM_DATABASE=Liquid Instruments Pty Ltd OUI:70B3D55B0* ID_OUI_FROM_DATABASE=Qxperts Italia S.r.l. OUI:70B3D5435* ID_OUI_FROM_DATABASE=Wuhan Xingtuxinke ELectronic Co.,Ltd OUI:70B3D50CD* ID_OUI_FROM_DATABASE=AML Oceanographic OUI:70B3D56E8* ID_OUI_FROM_DATABASE=BluWireless Technology Ltd OUI:70B3D56B3* ID_OUI_FROM_DATABASE=DuraComm Corporation OUI:70B3D5F36* ID_OUI_FROM_DATABASE=dinosys OUI:70B3D5AC9* ID_OUI_FROM_DATABASE=Trinity Solutions LLC OUI:70B3D50A6* ID_OUI_FROM_DATABASE=PA CONSULTING SERVICES OUI:70B3D5B8B* ID_OUI_FROM_DATABASE=Profound Medical Inc. OUI:70B3D51A5* ID_OUI_FROM_DATABASE=METRONIC APARATURA KONTROLNO - POMIAROWA OUI:70B3D5A1C* ID_OUI_FROM_DATABASE=MECA SYSTEM OUI:70B3D5AD6* ID_OUI_FROM_DATABASE=Lemonade Lab Inc OUI:70B3D5D87* ID_OUI_FROM_DATABASE=Zigen Corp OUI:70B3D5589* ID_OUI_FROM_DATABASE=Cityntel OU OUI:70B3D582E* ID_OUI_FROM_DATABASE=PlayAlive A/S OUI:70B3D500E* ID_OUI_FROM_DATABASE=Magosys Systems LTD OUI:70B3D5C3C* ID_OUI_FROM_DATABASE=PEEK TRAFFIC OUI:70B3D517F* ID_OUI_FROM_DATABASE=MB Connect Line GmbH OUI:70B3D5FE8* ID_OUI_FROM_DATABASE=PCME Ltd. OUI:70B3D5505* ID_OUI_FROM_DATABASE=MC2-Technologies OUI:70B3D5F2D* ID_OUI_FROM_DATABASE=ID Lock AS OUI:70B3D50DC* ID_OUI_FROM_DATABASE=Talleres de Escoriaza OUI:70B3D5AF3* ID_OUI_FROM_DATABASE=New Japan Radio Co., Ltd OUI:70B3D5500* ID_OUI_FROM_DATABASE=Mistral Solutions Pvt. LTD OUI:70B3D527D* ID_OUI_FROM_DATABASE=Telenor Connexion AB OUI:70B3D5B29* ID_OUI_FROM_DATABASE=WiViCom Co., Ltd. OUI:70B3D5ED5* ID_OUI_FROM_DATABASE=hangzhou battle link technology Co.,Ltd OUI:70B3D5E95* ID_OUI_FROM_DATABASE=BroadSoft Inc OUI:70B3D565B* ID_OUI_FROM_DATABASE=Roush OUI:70B3D5D7F* ID_OUI_FROM_DATABASE=ConectaIP Tecnologia S.L. OUI:70B3D53D2* ID_OUI_FROM_DATABASE=Imagine Inc. OUI:70B3D57A7* ID_OUI_FROM_DATABASE=Symbicon Ltd OUI:70B3D5D9B* ID_OUI_FROM_DATABASE=Russian Telecom Equipment Company OUI:70B3D5E4E* ID_OUI_FROM_DATABASE=Midfin Systems OUI:70B3D548C* ID_OUI_FROM_DATABASE=Integrated Systems Engineering, Inc. OUI:70B3D536C* ID_OUI_FROM_DATABASE=Sicon srl OUI:70B3D5FC6* ID_OUI_FROM_DATABASE=Tecnint HTE SRL OUI:70B3D52BE* ID_OUI_FROM_DATABASE=Coherent Logix, Inc. OUI:70B3D57F1* ID_OUI_FROM_DATABASE=AeroVision Avionics, Inc. OUI:70B3D57B8* ID_OUI_FROM_DATABASE=SerEnergy A/S OUI:70B3D5CCE* ID_OUI_FROM_DATABASE=Proconex 2010 Inc. OUI:70B3D5300* ID_OUI_FROM_DATABASE=Novo DR Ltd. OUI:70B3D5BD3* ID_OUI_FROM_DATABASE=FOTONA D.D. OUI:70B3D5600* ID_OUI_FROM_DATABASE=Stellwerk GmbH OUI:70B3D5421* ID_OUI_FROM_DATABASE=North Star Bestech Co., OUI:70B3D5C55* ID_OUI_FROM_DATABASE=Intelligent Energy Ltd OUI:70B3D5E28* ID_OUI_FROM_DATABASE=iotec GmbH OUI:70B3D56F3* ID_OUI_FROM_DATABASE=iungo OUI:70B3D5182* ID_OUI_FROM_DATABASE=Kitron UAB OUI:70B3D5820* ID_OUI_FROM_DATABASE=Becker Nachrichtentechnik GmbH OUI:70B3D5732* ID_OUI_FROM_DATABASE=TOFWERK AG OUI:70B3D5DAD* ID_OUI_FROM_DATABASE=General Dynamics C4 Systems OUI:70B3D507D* ID_OUI_FROM_DATABASE=PANORAMIC POWER OUI:70B3D5B9B* ID_OUI_FROM_DATABASE=Elektronik Art OUI:70B3D5327* ID_OUI_FROM_DATABASE=Seneco A/S OUI:70B3D5243* ID_OUI_FROM_DATABASE=Rohde&Schwarz Topex SA OUI:70B3D508E* ID_OUI_FROM_DATABASE=Beijing CONvision Technology Co.,Ltd OUI:70B3D5B8F* ID_OUI_FROM_DATABASE=Assembly Contracts Ltd OUI:70B3D55C5* ID_OUI_FROM_DATABASE=Haag-Streit AG OUI:70B3D5164* ID_OUI_FROM_DATABASE=Tokyo Drawing Ltd. OUI:70B3D59F1* ID_OUI_FROM_DATABASE=RFEL Ltd OUI:70B3D584A* ID_OUI_FROM_DATABASE=MOG Laboratories Pty Ltd OUI:70B3D59F5* ID_OUI_FROM_DATABASE=Vickers Electronics Ltd OUI:70B3D5FDE* ID_OUI_FROM_DATABASE=AERONAUTICAL & GENERAL INSTRUMENTS LTD. OUI:70B3D5104* ID_OUI_FROM_DATABASE=Plum sp. z o.o OUI:70B3D5C61* ID_OUI_FROM_DATABASE=JC HUNTER TECHNOLOGIES OUI:70B3D5A5B* ID_OUI_FROM_DATABASE=Christ Elektronik GmbH OUI:70B3D539A* ID_OUI_FROM_DATABASE=Videotrend srl OUI:70B3D5CE7* ID_OUI_FROM_DATABASE=June Automation Singapore Pte. Ltd. OUI:70B3D5EC1* ID_OUI_FROM_DATABASE=Xafax Nederland bv OUI:70B3D5A6D* ID_OUI_FROM_DATABASE=Metek Meteorologische Messtechnik GmbH OUI:70B3D53B8* ID_OUI_FROM_DATABASE=nVideon, Inc. OUI:70B3D5610* ID_OUI_FROM_DATABASE=POLVISION OUI:70B3D5ECE* ID_OUI_FROM_DATABASE=COMM-connect A/S OUI:70B3D53EF* ID_OUI_FROM_DATABASE=Vtron Pty Ltd OUI:70B3D5EB2* ID_OUI_FROM_DATABASE=Shooter Detection Systems OUI:70B3D5250* ID_OUI_FROM_DATABASE=Datum Electronics Limited OUI:70B3D5FDA* ID_OUI_FROM_DATABASE=ACD Elektronik GmbH OUI:70B3D56D9* ID_OUI_FROM_DATABASE=VECTARE Inc OUI:70B3D5BDA* ID_OUI_FROM_DATABASE=5-D Systems, Inc. OUI:70B3D5559* ID_OUI_FROM_DATABASE=Eagle Mountain Technology OUI:70B3D5AEE* ID_OUI_FROM_DATABASE=DiTEST Fahrzeugdiagnose GmbH OUI:70B3D5710* ID_OUI_FROM_DATABASE=Guardian Controls International Ltd OUI:70B3D5A0B* ID_OUI_FROM_DATABASE=ambiHome GmbH OUI:70B3D5204* ID_OUI_FROM_DATABASE=TWC OUI:70B3D583B* ID_OUI_FROM_DATABASE=Telefonix Incorporated OUI:70B3D5029* ID_OUI_FROM_DATABASE=Marimo electronics Co.,Ltd. OUI:70B3D5010* ID_OUI_FROM_DATABASE=Hanwa Electronic Ind.Co.,Ltd. OUI:70B3D586D* ID_OUI_FROM_DATABASE=Census Digital Incorporated OUI:70B3D560B* ID_OUI_FROM_DATABASE=Edgeware AB OUI:70B3D5ADD* ID_OUI_FROM_DATABASE=GHL Systems Berhad OUI:70B3D56F6* ID_OUI_FROM_DATABASE=Acco Brands Europe OUI:70B3D5D8F* ID_OUI_FROM_DATABASE=Molu Technology Inc., LTD. OUI:70B3D56F2* ID_OUI_FROM_DATABASE=P&C Micro's Pty Ltd OUI:70B3D543D* ID_OUI_FROM_DATABASE=Veryx Technologies Private Limited OUI:70B3D5AB7* ID_OUI_FROM_DATABASE=SIGLEAD INC OUI:70B3D5D47* ID_OUI_FROM_DATABASE=YotaScope Technologies Co., Ltd. OUI:70B3D580F* ID_OUI_FROM_DATABASE=Quickware Eng & Des LLC OUI:70B3D5F61* ID_OUI_FROM_DATABASE=Power Diagnostic Service OUI:70B3D50F0* ID_OUI_FROM_DATABASE=Avionica OUI:70B3D5E08* ID_OUI_FROM_DATABASE=Olssen OUI:70B3D5FD1* ID_OUI_FROM_DATABASE=RedRat Ltd OUI:70B3D5C8D* ID_OUI_FROM_DATABASE=KST technology OUI:70B3D5044* ID_OUI_FROM_DATABASE=Don Electronics Ltd OUI:70B3D55F0* ID_OUI_FROM_DATABASE=managee GmbH & Co KG OUI:70B3D5956* ID_OUI_FROM_DATABASE=AeroVision Avionics, Inc. OUI:70B3D5F62* ID_OUI_FROM_DATABASE=FRS GmbH & Co. KG OUI:70B3D50A9* ID_OUI_FROM_DATABASE=ProConnections, Inc. OUI:70B3D5EDD* ID_OUI_FROM_DATABASE=Solar Network & Partners OUI:70B3D53DE* ID_OUI_FROM_DATABASE=ELOMAC Elektronik GmbH OUI:70B3D5139* ID_OUI_FROM_DATABASE=Tunstall A/S OUI:70B3D5871* ID_OUI_FROM_DATABASE=Oso Technologies OUI:70B3D5AE9* ID_OUI_FROM_DATABASE=Cari Electronic OUI:70B3D5D8B* ID_OUI_FROM_DATABASE=Lenoxi Automation s.r.o. OUI:001BC50C4* ID_OUI_FROM_DATABASE=ELDES OUI:001BC50BA* ID_OUI_FROM_DATABASE=NT MICROSYSTEMS OUI:001BC50B0* ID_OUI_FROM_DATABASE=J-D.COM OUI:001BC50A6* ID_OUI_FROM_DATABASE=Balter Security GmbH OUI:001BC5075* ID_OUI_FROM_DATABASE=Kitron GmbH OUI:001BC5074* ID_OUI_FROM_DATABASE=Dynasthetics OUI:001BC507F* ID_OUI_FROM_DATABASE=Hitechlab Inc OUI:001BC507E* ID_OUI_FROM_DATABASE=Bio Molecular System Pty Ltd OUI:001BC506A* ID_OUI_FROM_DATABASE=IST GmbH OUI:001BC506B* ID_OUI_FROM_DATABASE=Verified Energy, LLC. OUI:001BC5061* ID_OUI_FROM_DATABASE=Scientific-Technical Center Epsilon Limited company OUI:001BC5060* ID_OUI_FROM_DATABASE=ENSTECH OUI:001BC504D* ID_OUI_FROM_DATABASE=eiraku electric corp. OUI:001BC504C* ID_OUI_FROM_DATABASE=Rhino Controls Ltd. OUI:001BC5057* ID_OUI_FROM_DATABASE=EREE Electronique OUI:001BC5056* ID_OUI_FROM_DATABASE=ThinKom Solutions, Inc OUI:001BC5043* ID_OUI_FROM_DATABASE=Coincident, Inc. OUI:001BC5038* ID_OUI_FROM_DATABASE=SEED International Ltd. OUI:001BC502E* ID_OUI_FROM_DATABASE=BETTINI SRL OUI:001BC5024* ID_OUI_FROM_DATABASE=ANNECY ELECTRONIQUE SAS OUI:001BC501B* ID_OUI_FROM_DATABASE=Commonwealth Scientific and Industrial Research Organisation OUI:001BC501C* ID_OUI_FROM_DATABASE=Coolit Systems, Inc. OUI:70B3D5C3B* ID_OUI_FROM_DATABASE=Vironova AB OUI:70B3D56A9* ID_OUI_FROM_DATABASE=OHMORI ELECTRIC INDUSTRIES CO.LTD OUI:70B3D552E* ID_OUI_FROM_DATABASE=Swissponic Sagl OUI:70B3D5551* ID_OUI_FROM_DATABASE=infrachip OUI:70B3D5323* ID_OUI_FROM_DATABASE=TATTILE SRL OUI:70B3D5054* ID_OUI_FROM_DATABASE=Groupeer Technologies OUI:70B3D5353* ID_OUI_FROM_DATABASE=Digital Outfit OUI:70B3D5F5B* ID_OUI_FROM_DATABASE=A.F.MENSAH, INC OUI:70B3D5A92* ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG OUI:70B3D5B39* ID_OUI_FROM_DATABASE=MB Connect Line GmbH OUI:70B3D51E3* ID_OUI_FROM_DATABASE=Hatel Elektronik LTD. STI. OUI:70B3D5CCA* ID_OUI_FROM_DATABASE=SIEMENS AS OUI:70B3D5EF6* ID_OUI_FROM_DATABASE=CHARGELIB OUI:70B3D5B02* ID_OUI_FROM_DATABASE=Nordic Automation Systems AS OUI:70B3D5B05* ID_OUI_FROM_DATABASE=E-PLUS TECHNOLOGY CO., LTD OUI:70B3D5847* ID_OUI_FROM_DATABASE=Ai-Lynx OUI:70B3D5148* ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L. OUI:70B3D5BFE* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D5261* ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC OUI:70B3D5618* ID_OUI_FROM_DATABASE=Motec Pty Ltd OUI:70B3D5892* ID_OUI_FROM_DATABASE=ABB OUI:70B3D59BA* ID_OUI_FROM_DATABASE=ATIM Radiocommunication OUI:70B3D54C4* ID_OUI_FROM_DATABASE=OOO Research and Production Center Computer Technologies OUI:70B3D59B3* ID_OUI_FROM_DATABASE=K&J Schmittschneider AG OUI:70B3D5747* ID_OUI_FROM_DATABASE=Eva Automation OUI:70B3D53F4* ID_OUI_FROM_DATABASE=Wincode Technology Co., Ltd. OUI:70B3D56E6* ID_OUI_FROM_DATABASE=Eleven Engineering Incorporated OUI:70B3D5E39* ID_OUI_FROM_DATABASE=Thinnect, Inc, OUI:70B3D5216* ID_OUI_FROM_DATABASE=FLEXTRONICS OUI:70B3D50FE* ID_OUI_FROM_DATABASE=Vocality International Ltd OUI:70B3D54B7* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D555C* ID_OUI_FROM_DATABASE=Saratoga Speed, Inc. OUI:70B3D5428* ID_OUI_FROM_DATABASE=Presentation Switchers, Inc. OUI:70B3D5C32* ID_OUI_FROM_DATABASE=INFRASAFE/ ADVANTOR SYSTEMS OUI:70B3D5592* ID_OUI_FROM_DATABASE=CRDE OUI:70B3D5F1A* ID_OUI_FROM_DATABASE=Sator Controls s.r.o. OUI:70B3D505A* ID_OUI_FROM_DATABASE=Uni Control System Sp. z o. o. OUI:70B3D59EF* ID_OUI_FROM_DATABASE=Cottonwood Creek Technologies, Inc. OUI:70B3D59EB* ID_OUI_FROM_DATABASE=Preston Industries dba PolyScience OUI:70B3D5A3B* ID_OUI_FROM_DATABASE=Grace Design/Lunatec LLC OUI:70B3D57A0* ID_OUI_FROM_DATABASE=Reactec Ltd OUI:70B3D529B* ID_OUI_FROM_DATABASE=DermaLumics S.L. OUI:70B3D5202* ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH OUI:70B3D5259* ID_OUI_FROM_DATABASE=Zebra Elektronik A.S. OUI:70B3D5FBE* ID_OUI_FROM_DATABASE=Hanbat National University OUI:70B3D5FE4* ID_OUI_FROM_DATABASE=CARE PVT LTD OUI:70B3D58B1* ID_OUI_FROM_DATABASE=M-Tech Innovations Limited OUI:70B3D5D34* ID_OUI_FROM_DATABASE=G-PHILOS CO.,LTD OUI:70B3D5528* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D5B81* ID_OUI_FROM_DATABASE=Instro Precision Limited OUI:70B3D5479* ID_OUI_FROM_DATABASE=LINEAGE POWER PVT. LTD. OUI:70B3D58AB* ID_OUI_FROM_DATABASE=EMAC, Inc. OUI:70B3D5729* ID_OUI_FROM_DATABASE=EMAC, Inc. OUI:70B3D5E93* ID_OUI_FROM_DATABASE=ECON Technology Co.Ltd OUI:70B3D5CF4* ID_OUI_FROM_DATABASE=Harbin Cheng Tian Technology Development Co., Ltd. OUI:70B3D54BD* ID_OUI_FROM_DATABASE=Boulder Amplifiers, Inc. OUI:70B3D545C* ID_OUI_FROM_DATABASE=AlyTech OUI:70B3D54B9* ID_OUI_FROM_DATABASE=SHEN ZHEN TTK TECHNOLOGY CO,LTD OUI:70B3D51C4* ID_OUI_FROM_DATABASE=Smeg S.p.A. OUI:70B3D5A59* ID_OUI_FROM_DATABASE=Muuntosähkö Oy - Trafox OUI:70B3D5D76* ID_OUI_FROM_DATABASE=attocube systems AG OUI:70B3D57E3* ID_OUI_FROM_DATABASE=RedLeaf Security OUI:70B3D583C* ID_OUI_FROM_DATABASE=Sinoembed OUI:70B3D57EB* ID_OUI_FROM_DATABASE=Xerox International Partners OUI:70B3D5F57* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D501F* ID_OUI_FROM_DATABASE=SPX Flow Technology BV OUI:70B3D5407* ID_OUI_FROM_DATABASE=IDOSENS OUI:70B3D5C01* ID_OUI_FROM_DATABASE=SmartGuard LLC OUI:70B3D57C8* ID_OUI_FROM_DATABASE=CRDE OUI:70B3D57B9* ID_OUI_FROM_DATABASE=QIAGEN Instruments AG OUI:70B3D5DD7* ID_OUI_FROM_DATABASE=DETECT Australia OUI:70B3D5DDF* ID_OUI_FROM_DATABASE=AeroVision Avionics, Inc. OUI:70B3D5BF1* ID_OUI_FROM_DATABASE=Flashnet SRL OUI:70B3D50C5* ID_OUI_FROM_DATABASE=Precitec Optronik GmbH OUI:70B3D5E35* ID_OUI_FROM_DATABASE=Nanospeed Technologies Limited OUI:70B3D55EE* ID_OUI_FROM_DATABASE=Mikrotron Mikrocomputer, Digital- und Analogtechnik GmbH OUI:70B3D5F11* ID_OUI_FROM_DATABASE=BroadSoft Inc OUI:70B3D5B3E* ID_OUI_FROM_DATABASE=Paradigm Communication Systems Ltd OUI:70B3D5161* ID_OUI_FROM_DATABASE=MB Connect Line GmbH OUI:70B3D5033* ID_OUI_FROM_DATABASE=Sailmon BV OUI:70B3D5D42* ID_OUI_FROM_DATABASE=DSP DESIGN OUI:70B3D5A56* ID_OUI_FROM_DATABASE=DORLET SAU OUI:70B3D5FDF* ID_OUI_FROM_DATABASE=NARA CONTROLS INC. OUI:70B3D5430* ID_OUI_FROM_DATABASE=Algodue Elettronica Srl OUI:70B3D55B6* ID_OUI_FROM_DATABASE=Ethical Lighting and Sensor Solutions Limited OUI:70B3D52EB* ID_OUI_FROM_DATABASE=BRNET CO.,LTD. OUI:70B3D5E7A* ID_OUI_FROM_DATABASE=ART SPA OUI:70B3D5A93* ID_OUI_FROM_DATABASE=Mes Communication Co., Ltd OUI:70B3D50FC* ID_OUI_FROM_DATABASE=vitalcare OUI:70B3D59C8* ID_OUI_FROM_DATABASE=Applied Systems Engineering, Inc. OUI:70B3D5D8C* ID_OUI_FROM_DATABASE=Damerell Design Limited (DCL) OUI:70B3D5FBB* ID_OUI_FROM_DATABASE=Vena Engineering Corporation OUI:70B3D5C21* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D5628* ID_OUI_FROM_DATABASE=MECT S.R.L. OUI:70B3D532F* ID_OUI_FROM_DATABASE=Movidius SRL OUI:70B3D59C9* ID_OUI_FROM_DATABASE=PK Sound OUI:70B3D5ADA* ID_OUI_FROM_DATABASE=Private OUI:70B3D5554* ID_OUI_FROM_DATABASE=Teletypes Manufacturing Plant OUI:70B3D5E0D* ID_OUI_FROM_DATABASE=Sigma Connectivity AB OUI:70B3D572D* ID_OUI_FROM_DATABASE=Kron Medidores OUI:70B3D5D8D* ID_OUI_FROM_DATABASE=Pullnet Technology,S.L. OUI:70B3D52BC* ID_OUI_FROM_DATABASE=EQUIPOS DE TELECOMUNICACIÓN OPTOELECTRÓNICOS, S.A. OUI:70B3D52D6* ID_OUI_FROM_DATABASE=Kvazar LLC OUI:70B3D5231* ID_OUI_FROM_DATABASE=DELTA TAU DATA SYSTEMS, INC. OUI:70B3D5823* ID_OUI_FROM_DATABASE=SP Controls OUI:70B3D580D* ID_OUI_FROM_DATABASE=Data Physics Corporation OUI:70B3D5336* ID_OUI_FROM_DATABASE=Synaccess Networks Inc. OUI:70B3D5A51* ID_OUI_FROM_DATABASE=RF Code OUI:70B3D57AF* ID_OUI_FROM_DATABASE=Hessware GmbH OUI:70B3D53F9* ID_OUI_FROM_DATABASE=Herrick Tech Labs OUI:70B3D54B1* ID_OUI_FROM_DATABASE=LACE LLC. OUI:70B3D5530* ID_OUI_FROM_DATABASE=iSiS-Ex Limited OUI:70B3D5A27* ID_OUI_FROM_DATABASE=HDL da Amazônia Industria Eletrônica Ltda OUI:70B3D565C* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D57AD* ID_OUI_FROM_DATABASE=Insitu Inc OUI:70B3D5E21* ID_OUI_FROM_DATABASE=LLVISION TECHNOLOGY CO.,LTD OUI:70B3D5583* ID_OUI_FROM_DATABASE=Ducommun Inc. OUI:70B3D5F1E* ID_OUI_FROM_DATABASE=ATX NETWORKS LTD OUI:70B3D59E7* ID_OUI_FROM_DATABASE=Xiamen Maxincom Technologies Co., Ltd. OUI:70B3D5472* ID_OUI_FROM_DATABASE=Quadio Devices Private Limited OUI:70B3D57A8* ID_OUI_FROM_DATABASE=dieEntwickler Elektronik GmbH OUI:70B3D503F* ID_OUI_FROM_DATABASE=Elesar Limited OUI:70B3D53D7* ID_OUI_FROM_DATABASE=Remote Sensing Solutions, Inc. OUI:70B3D5838* ID_OUI_FROM_DATABASE=Tofino OUI:70B3D51F3* ID_OUI_FROM_DATABASE=Smart Energy Code Company Limited OUI:70B3D56BB* ID_OUI_FROM_DATABASE=LUCEO OUI:70B3D5C5A* ID_OUI_FROM_DATABASE=Commsignia Ltd. OUI:70B3D59DB* ID_OUI_FROM_DATABASE=CAS Medical Systems, Inc OUI:70B3D5BDD* ID_OUI_FROM_DATABASE=CDR SRL OUI:70B3D5F5A* ID_OUI_FROM_DATABASE=HAMEG GmbH OUI:70B3D574C* ID_OUI_FROM_DATABASE=Kwant Controls BV OUI:70B3D56FA* ID_OUI_FROM_DATABASE=Dataforth Corporation OUI:70B3D5E90* ID_OUI_FROM_DATABASE=Getein Biotechnology Co.,ltd OUI:70B3D5C3F* ID_OUI_FROM_DATABASE=Code Blue Corporation OUI:70B3D5917* ID_OUI_FROM_DATABASE=KSJ Co.Ltd OUI:70B3D5EC6* ID_OUI_FROM_DATABASE=ESII OUI:70B3D518B* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D5849* ID_OUI_FROM_DATABASE=RF-Tuote Oy OUI:70B3D59D3* ID_OUI_FROM_DATABASE=Communication Technology Ltd. OUI:70B3D546B* ID_OUI_FROM_DATABASE=Airborne Engineering Limited OUI:70B3D5EFB* ID_OUI_FROM_DATABASE=PXM sp.k. OUI:70B3D5A81* ID_OUI_FROM_DATABASE=Sienda New Media Technologies GmbH OUI:70B3D5A1B* ID_OUI_FROM_DATABASE=Potter Electric Signal Co. OUI:70B3D5EAC* ID_OUI_FROM_DATABASE=Kentech Instruments Limited OUI:70B3D58AD* ID_OUI_FROM_DATABASE=Global Communications Technology LLC OUI:70B3D5C97* ID_OUI_FROM_DATABASE=CSINFOTEL OUI:70B3D5F10* ID_OUI_FROM_DATABASE=Riegl Laser Measurement Systems GmbH OUI:70B3D54AA* ID_OUI_FROM_DATABASE=Twoway Communications, Inc. OUI:70B3D55A2* ID_OUI_FROM_DATABASE=Wallner Automation GmbH OUI:70B3D5418* ID_OUI_FROM_DATABASE=DEV Systemtechnik GmbH& Co KG OUI:70B3D5D79* ID_OUI_FROM_DATABASE=GOMA ELETTRONICA SpA OUI:70B3D558E* ID_OUI_FROM_DATABASE=Veilux Inc. OUI:70B3D5181* ID_OUI_FROM_DATABASE=Task Sistemas OUI:70B3D5DCF* ID_OUI_FROM_DATABASE=KLS Netherlands B.V. OUI:70B3D5A25* ID_OUI_FROM_DATABASE=PulseTor LLC OUI:70B3D5296* ID_OUI_FROM_DATABASE=Rohde&Schwarz Topex SA OUI:70B3D5D3B* ID_OUI_FROM_DATABASE=NimbeLink Corp OUI:70B3D5882* ID_OUI_FROM_DATABASE=SIMON TECH, S.L. OUI:70B3D5959* ID_OUI_FROM_DATABASE=Zulex International Co.,Ltd. OUI:70B3D5CFF* ID_OUI_FROM_DATABASE=DTECH Labs, Inc. OUI:70B3D50C0* ID_OUI_FROM_DATABASE=Molu Technology Inc., LTD. OUI:70B3D53DF* ID_OUI_FROM_DATABASE=MultiDyne OUI:70B3D582C* ID_OUI_FROM_DATABASE=NELS Ltd. OUI:70B3D5501* ID_OUI_FROM_DATABASE=Peek Traffic OUI:70B3D5025* ID_OUI_FROM_DATABASE=Elsuhd Net Ltd Co. OUI:70B3D558F* ID_OUI_FROM_DATABASE=LSL systems OUI:70B3D5A55* ID_OUI_FROM_DATABASE=Embest Technology Co., Ltd OUI:70B3D5BE1* ID_OUI_FROM_DATABASE=FeCon GmbH OUI:70B3D526E* ID_OUI_FROM_DATABASE=HI-TECH SYSTEM Co. Ltd. OUI:70B3D55E9* ID_OUI_FROM_DATABASE=Zehetner-Elektronik GmbH OUI:70B3D5205* ID_OUI_FROM_DATABASE=Esource Srl OUI:70B3D5112* ID_OUI_FROM_DATABASE=DiTEST Fahrzeugdiagnose GmbH OUI:70B3D53DA* ID_OUI_FROM_DATABASE=Loop Labs, Inc. OUI:70B3D5FF5* ID_OUI_FROM_DATABASE=Prolan Process Control Co. OUI:70B3D52D5* ID_OUI_FROM_DATABASE=Teuco Guzzini OUI:70B3D544B* ID_OUI_FROM_DATABASE=Open System Solutions Limited OUI:70B3D5BEC* ID_OUI_FROM_DATABASE=Tokyo Communication Equipment MFG Co.,ltd. OUI:70B3D56D6* ID_OUI_FROM_DATABASE=KMtronic Ltd. OUI:70B3D557C* ID_OUI_FROM_DATABASE=Automata GmbH & Co. KG OUI:70B3D5DA1* ID_OUI_FROM_DATABASE=Qprel srl OUI:70B3D5097* ID_OUI_FROM_DATABASE=Avant Technologies OUI:70B3D505F* ID_OUI_FROM_DATABASE=UNISOR MULTISYSTEMS LTD OUI:70B3D548D* ID_OUI_FROM_DATABASE=OMEGA BILANCE SRL SOCIETA' UNIPERSONALE OUI:70B3D5E99* ID_OUI_FROM_DATABASE=Advitronics telecom bv OUI:70B3D5362* ID_OUI_FROM_DATABASE=Asiga OUI:70B3D5751* ID_OUI_FROM_DATABASE=GNF OUI:70B3D5587* ID_OUI_FROM_DATABASE=INCAA Computers OUI:70B3D5E27* ID_OUI_FROM_DATABASE=Woodside Electronics OUI:70B3D5B33* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D5346* ID_OUI_FROM_DATABASE=Ultamation Limited OUI:70B3D5052* ID_OUI_FROM_DATABASE=Sudo Premium Engineering OUI:70B3D5C27* ID_OUI_FROM_DATABASE=General Dynamics C4 Systems OUI:70B3D5F34* ID_OUI_FROM_DATABASE=MacGray Services OUI:70B3D5B16* ID_OUI_FROM_DATABASE=XI'AN SHENMING ELECTRON TECHNOLOGY CO.,LTD OUI:70B3D52FD* ID_OUI_FROM_DATABASE=Special Projects Group, Inc OUI:70B3D5305* ID_OUI_FROM_DATABASE=CAITRON Industrial Solutions GmbH OUI:70B3D5634* ID_OUI_FROM_DATABASE=idaqs Co.,Ltd. OUI:70B3D5CE9* ID_OUI_FROM_DATABASE=KINEMETRICS OUI:70B3D5B8A* ID_OUI_FROM_DATABASE=Nexus Tech. VN OUI:70B3D53A8* ID_OUI_FROM_DATABASE=JamHub Corp. OUI:70B3D5AA0* ID_OUI_FROM_DATABASE=Simple Works, Inc. OUI:70B3D5058* ID_OUI_FROM_DATABASE=Telink Semiconductor CO, Limtied, Taiwan OUI:70B3D5EFA* ID_OUI_FROM_DATABASE=NextEra Energy Resources, LLC OUI:70B3D595A* ID_OUI_FROM_DATABASE=Sigmann Elektronik GmbH OUI:70B3D52E3* ID_OUI_FROM_DATABASE=Meiknologic GmbH OUI:70B3D5ABC* ID_OUI_FROM_DATABASE=BKM-Micronic Richtfunkanlagen GmbH OUI:70B3D5E4A* ID_OUI_FROM_DATABASE=ICP NewTech Ltd OUI:70B3D5ECD* ID_OUI_FROM_DATABASE=SBS-Feintechnik GmbH & Co. KG OUI:70B3D5918* ID_OUI_FROM_DATABASE=Glova Rail A/S OUI:70B3D5308* ID_OUI_FROM_DATABASE=DSD MICROTECHNOLOGY,INC. OUI:70B3D56D3* ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH OUI:70B3D5908* ID_OUI_FROM_DATABASE=Accusonic OUI:70B3D5183* ID_OUI_FROM_DATABASE=Evco S.p.a. OUI:70B3D55A8* ID_OUI_FROM_DATABASE=Farmobile OUI:70B3D5C2C* ID_OUI_FROM_DATABASE=Dromont S.p.A. OUI:001BC50C6* ID_OUI_FROM_DATABASE=Connode OUI:70B3D53C2* ID_OUI_FROM_DATABASE=Cellular Specialties, Inc. OUI:70B3D5EF9* ID_OUI_FROM_DATABASE=Critical Link OUI:001BC50B2* ID_OUI_FROM_DATABASE=SKODA electric a.s. OUI:001BC50B6* ID_OUI_FROM_DATABASE=Veilux inc. OUI:001BC50AC* ID_OUI_FROM_DATABASE=AVnu Alliance OUI:001BC50BC* ID_OUI_FROM_DATABASE=kuwatec, Inc. OUI:001BC50A2* ID_OUI_FROM_DATABASE=Hettich Benelux OUI:001BC50A8* ID_OUI_FROM_DATABASE=Link Precision OUI:001BC509D* ID_OUI_FROM_DATABASE=Navitar Inc OUI:001BC5093* ID_OUI_FROM_DATABASE=Ambient Devices, Inc. OUI:001BC5081* ID_OUI_FROM_DATABASE=WonATech Co., Ltd. OUI:001BC5084* ID_OUI_FROM_DATABASE=Applied Innovations Research LLC OUI:001BC507B* ID_OUI_FROM_DATABASE=QCORE Medical OUI:001BC507A* ID_OUI_FROM_DATABASE=Servicios Electronicos Industriales Berbel s.l. OUI:001BC5089* ID_OUI_FROM_DATABASE=SIGNATURE CONTROL SYSTEMS, INC. OUI:001BC5077* ID_OUI_FROM_DATABASE=Momentum Data Systems OUI:001BC5063* ID_OUI_FROM_DATABASE=Check-It Solutions Inc OUI:001BC5070* ID_OUI_FROM_DATABASE=Siemens Industries, Inc, Retail & Commercial Systems OUI:001BC5071* ID_OUI_FROM_DATABASE=Center for E-Commerce Infrastructure Development, The University of Hong Kong OUI:001BC5067* ID_OUI_FROM_DATABASE=Embit srl OUI:001BC5066* ID_OUI_FROM_DATABASE=Manufacturas y transformados AB OUI:001BC506D* ID_OUI_FROM_DATABASE=TES Electronic Solutions (I) Pvt. Ltd. OUI:001BC504F* ID_OUI_FROM_DATABASE=Orbital Systems, Ltd. OUI:001BC505D* ID_OUI_FROM_DATABASE=JSC Prominform OUI:001BC5053* ID_OUI_FROM_DATABASE=Metrycom Communications Ltd OUI:001BC5059* ID_OUI_FROM_DATABASE=INPIXAL OUI:001BC5045* ID_OUI_FROM_DATABASE=Marvel Digital International Limited OUI:001BC5049* ID_OUI_FROM_DATABASE=EUROCONTROL S.p.A. OUI:001BC503F* ID_OUI_FROM_DATABASE=ELTRADE Ltd OUI:001BC503A* ID_OUI_FROM_DATABASE=MindMade Sp. z o.o. OUI:001BC5030* ID_OUI_FROM_DATABASE=OctoGate it Security Systems GmbH OUI:001BC5026* ID_OUI_FROM_DATABASE=DIMEP Sistemas OUI:001BC5022* ID_OUI_FROM_DATABASE=CJSC STC SIMOS OUI:001BC501E* ID_OUI_FROM_DATABASE=Private OUI:001BC5011* ID_OUI_FROM_DATABASE=OOO NPP Mera OUI:001BC5007* ID_OUI_FROM_DATABASE=Energy Aware Technology OUI:001BC5001* ID_OUI_FROM_DATABASE=OpenRB.com, Direct SIA OUI:70B3D56C7* ID_OUI_FROM_DATABASE=Becton Dickinson OUI:70B3D5CA8* ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. OUI:70B3D5609* ID_OUI_FROM_DATABASE=PBSI Group Limited OUI:70B3D5B40* ID_OUI_FROM_DATABASE=Wuhan Xingtuxinke ELectronic Co.,Ltd OUI:70B3D50D6* ID_OUI_FROM_DATABASE=TATTILE SRL OUI:70B3D5297* ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG OUI:70B3D5942* ID_OUI_FROM_DATABASE=TruTeq Devices (Pty) Ltd OUI:70B3D5F7B* ID_OUI_FROM_DATABASE=KST technology OUI:70B3D5B99* ID_OUI_FROM_DATABASE=DomoSafety S.A. OUI:70B3D5D51* ID_OUI_FROM_DATABASE=Azcom Technology S.r.l. OUI:70B3D5BA1* ID_OUI_FROM_DATABASE=Cathwell AS OUI:70B3D5286* ID_OUI_FROM_DATABASE=Pedax Danmark OUI:70B3D51A9* ID_OUI_FROM_DATABASE=OCEANIX INC. OUI:70B3D5733* ID_OUI_FROM_DATABASE=SA Instrumentation Limited OUI:70B3D5652* ID_OUI_FROM_DATABASE=Robert Bosch, LLC OUI:70B3D5F65* ID_OUI_FROM_DATABASE=MARKUS LABS OUI:70B3D5F2E* ID_OUI_FROM_DATABASE=Shanghai JCY Technology Company OUI:70B3D57F8* ID_OUI_FROM_DATABASE=Solvera Lynx d.d. OUI:70B3D55BE* ID_OUI_FROM_DATABASE=CASWA OUI:70B3D5F55* ID_OUI_FROM_DATABASE=Kohler Mira Ltd OUI:70B3D57ED* ID_OUI_FROM_DATABASE=The Things Network Foundation OUI:70B3D5A9D* ID_OUI_FROM_DATABASE=VITEC MULTIMEDIA OUI:70B3D51A8* ID_OUI_FROM_DATABASE=STC Rainbow Ltd. OUI:70B3D53CA* ID_OUI_FROM_DATABASE=TTI Ltd OUI:70B3D5E1C* ID_OUI_FROM_DATABASE=Xcenter AS OUI:70B3D5184* ID_OUI_FROM_DATABASE=XV360 Optical Information Systems Ltd. OUI:70B3D5B5C* ID_OUI_FROM_DATABASE=Prozess Technologie OUI:70B3D5AF4* ID_OUI_FROM_DATABASE=TATTILE SRL OUI:70B3D5531* ID_OUI_FROM_DATABASE=ATEME OUI:70B3D5BA7* ID_OUI_FROM_DATABASE=Digital Yacht Ltd OUI:70B3D51C7* ID_OUI_FROM_DATABASE=Hoshin Electronics Co., Ltd. OUI:70B3D528B* ID_OUI_FROM_DATABASE=Arnouse Digital Devices, Corp. OUI:70B3D5D94* ID_OUI_FROM_DATABASE=Dewetron GmbH OUI:70B3D5974* ID_OUI_FROM_DATABASE=Jireh Industries Ltd. OUI:70B3D5544* ID_OUI_FROM_DATABASE=Silicon Safe Ltd OUI:70B3D5EE1* ID_OUI_FROM_DATABASE=allora Factory BVBA OUI:70B3D5389* ID_OUI_FROM_DATABASE=Private OUI:70B3D5640* ID_OUI_FROM_DATABASE=Electronic Equipment Company Pvt. Ltd. OUI:70B3D5D65* ID_OUI_FROM_DATABASE=CRDE OUI:70B3D53C3* ID_OUI_FROM_DATABASE=AIMCO OUI:1C8776D* ID_OUI_FROM_DATABASE=Qivivo OUI:CC1BE0F* ID_OUI_FROM_DATABASE=Private OUI:1C87764* ID_OUI_FROM_DATABASE=RDP.RU OUI:1C87768* ID_OUI_FROM_DATABASE=Guangzhou Video-Star Electronics Co.,Ltd. OUI:D07650F* ID_OUI_FROM_DATABASE=Private OUI:F40E11F* ID_OUI_FROM_DATABASE=Private OUI:8439BE5* ID_OUI_FROM_DATABASE=Neat S.r.l. OUI:8439BE8* ID_OUI_FROM_DATABASE=Diamond Products LLC OUI:8439BE3* ID_OUI_FROM_DATABASE=ShenZhen Fudeyu Technology co.,Ltd OUI:1C88799* ID_OUI_FROM_DATABASE=Xingtera China Ltd OUI:40A36B5* ID_OUI_FROM_DATABASE=National Research Council of Canada OUI:1C87762* ID_OUI_FROM_DATABASE=Ibeo Automotive Systems GmbH OUI:40A36B6* ID_OUI_FROM_DATABASE=Bixi Systems Ltd. OUI:70886BB* ID_OUI_FROM_DATABASE=Beijing Strongleader Science & Technology Co., Ltd. OUI:800A805* ID_OUI_FROM_DATABASE=Shenzhen Zidoo Technology Co., Ltd. OUI:800A801* ID_OUI_FROM_DATABASE=Dongguan I-Chime electrinics Co.,Ltd OUI:1C21D17* ID_OUI_FROM_DATABASE=Soundtrack Your Brand Sweden AB OUI:DC4427C* ID_OUI_FROM_DATABASE=Pyrexx Technologies GmbH OUI:CC1BE0E* ID_OUI_FROM_DATABASE=Cassia Networks OUI:CC1BE02* ID_OUI_FROM_DATABASE=i-Trinetech Co.,Ltd. OUI:CC1BE05* ID_OUI_FROM_DATABASE=Earphone Connection, Ubc. OUI:A03E6B1* ID_OUI_FROM_DATABASE=Business Support Consultant Co.,Ltd OUI:C88ED19* ID_OUI_FROM_DATABASE=Focalcrest, Ltd. OUI:C88ED14* ID_OUI_FROM_DATABASE=Comlab AG OUI:A03E6BA* ID_OUI_FROM_DATABASE=Shenzhen Neostra Technology Co.Ltd OUI:78C2C0E* ID_OUI_FROM_DATABASE=Huwomobility OUI:78C2C01* ID_OUI_FROM_DATABASE=XRONOS-INC OUI:B437D1C* ID_OUI_FROM_DATABASE=NANJING PUTIAN TELECOMMUNICATIONS TECHNOLOGY CO.,LTD. OUI:B437D17* ID_OUI_FROM_DATABASE=GE Power Management OUI:DC44273* ID_OUI_FROM_DATABASE=General Microsystems Sdn Bhd OUI:78C2C08* ID_OUI_FROM_DATABASE=Beijing Coilabs technology co.,ltd OUI:78C2C05* ID_OUI_FROM_DATABASE=ShenZhen TuLing Robot CO.,LTD OUI:B0C5CAB* ID_OUI_FROM_DATABASE=RISECOMM (HK) TECHNOLOGY CO. LIMITED OUI:B0C5CA7* ID_OUI_FROM_DATABASE=Shenzhen KTC Technology CO.,LTD. OUI:B0C5CA2* ID_OUI_FROM_DATABASE=LOWOTEC GmbH OUI:807B855* ID_OUI_FROM_DATABASE=EFCO OUI:807B857* ID_OUI_FROM_DATABASE=Chendu Ningshui Technology Co.,Ltd OUI:807B850* ID_OUI_FROM_DATABASE=Shiroshita Industrial Co., Ltd. OUI:80E4DA3* ID_OUI_FROM_DATABASE=Beijing Gaokezhongtian Technology Co Ltd OUI:2CD1419* ID_OUI_FROM_DATABASE=Beijing Hexing Chuangxiang Technology Co., Ltd. OUI:1CCAE3D* ID_OUI_FROM_DATABASE=eSight Corporation OUI:1CCAE3C* ID_OUI_FROM_DATABASE=Gahdeung Elecom OUI:64FB81A* ID_OUI_FROM_DATABASE=Bronkhorst High-Tech BV OUI:64FB81D* ID_OUI_FROM_DATABASE=Dongyang unitech.co.ltd OUI:64FB816* ID_OUI_FROM_DATABASE=XIMO Communication Technology Co., Ltd OUI:64FB811* ID_OUI_FROM_DATABASE=Narrative AB OUI:549A111* ID_OUI_FROM_DATABASE=SpearX Inc. OUI:549A112* ID_OUI_FROM_DATABASE=Torrap Design Limited OUI:807B85C* ID_OUI_FROM_DATABASE=Ningbo Plus and Popscreens electronic Technology Co.,LTD OUI:1CCAE31* ID_OUI_FROM_DATABASE=PGA ELECTRONIC OUI:1CCAE30* ID_OUI_FROM_DATABASE=Private OUI:80E4DAC* ID_OUI_FROM_DATABASE=EVER Sp. z o.o. OUI:80E4DA7* ID_OUI_FROM_DATABASE=Shortcut Labs OUI:B437D13* ID_OUI_FROM_DATABASE=DIMTON CO.,LTD. OUI:B437D10* ID_OUI_FROM_DATABASE=Lezyne INC USA OUI:74F8DBB* ID_OUI_FROM_DATABASE=Capwave Technologies Inc OUI:885D904* ID_OUI_FROM_DATABASE=Wuhan Strong Electronics Co., Ltd OUI:549A11C* ID_OUI_FROM_DATABASE=Xi'an Hua Fan Technology Co.,Ltd. OUI:549A11B* ID_OUI_FROM_DATABASE=Elite Silicon Technology, Inc. OUI:74F8DB3* ID_OUI_FROM_DATABASE=InnoTrans Communications OUI:885D90D* ID_OUI_FROM_DATABASE=Hexaglobe OUI:885D909* ID_OUI_FROM_DATABASE=Gigatech R&D Corp. OUI:F802782* ID_OUI_FROM_DATABASE=Innodisk OUI:0CEFAFE* ID_OUI_FROM_DATABASE=Infinisource Inc. OUI:90C6822* ID_OUI_FROM_DATABASE=ekey biometric systems gmbh OUI:2C6A6FD* ID_OUI_FROM_DATABASE=Holjeron OUI:2C6A6F9* ID_OUI_FROM_DATABASE=Logic IO Aps OUI:2C6A6FA* ID_OUI_FROM_DATABASE=Wellntel, Inc. OUI:9802D8B* ID_OUI_FROM_DATABASE=HANSHIN MEDICAL CO., LTD. OUI:9802D87* ID_OUI_FROM_DATABASE=Ormazabal Protection&Automation OUI:0CEFAF8* ID_OUI_FROM_DATABASE=BSX Athletics OUI:0CEFAF5* ID_OUI_FROM_DATABASE=PREMIUM SA OUI:0CEFAF4* ID_OUI_FROM_DATABASE=Sentry360 OUI:A44F29C* ID_OUI_FROM_DATABASE=Shenzhen Huadoo Bright Group Limitied OUI:A0BB3E3* ID_OUI_FROM_DATABASE=WiteRiver Technology LLC OUI:28FD80D* ID_OUI_FROM_DATABASE=Grandway Technology (Shenzhen) Limited OUI:28FD80C* ID_OUI_FROM_DATABASE=Airbus Defence and Space Oy OUI:28FD809* ID_OUI_FROM_DATABASE=JINLITONG INTERNATIONAL CO.,LTD OUI:28FD802* ID_OUI_FROM_DATABASE=Zhixiang Technology Co., Ltd. OUI:A0BB3EA* ID_OUI_FROM_DATABASE=Filo SRL OUI:9802D82* ID_OUI_FROM_DATABASE=United Power Research Technology Corp. OUI:A0BB3E8* ID_OUI_FROM_DATABASE=AutarcTech GmbH OUI:A0BB3E4* ID_OUI_FROM_DATABASE=COMSYS Communications Systems Service GmbH OUI:90C682E* ID_OUI_FROM_DATABASE=Shanghai HuRong Communication Technology Development Co., Ltd. OUI:90C6829* ID_OUI_FROM_DATABASE=ACT OUI:F80278E* ID_OUI_FROM_DATABASE=Lit Technologies OUI:F80278B* ID_OUI_FROM_DATABASE=Rosemount Analytical OUI:F802787* ID_OUI_FROM_DATABASE=BETTINI SRL OUI:28FD803* ID_OUI_FROM_DATABASE=NUUO, Inc. OUI:E818635* ID_OUI_FROM_DATABASE=WETEK ELECTRONICS LIMITED OUI:E818632* ID_OUI_FROM_DATABASE=AVCON Information Technology Co.,Ltd OUI:B8D812D* ID_OUI_FROM_DATABASE=Lam Research OUI:B8D8126* ID_OUI_FROM_DATABASE=Vonger Electronic Technology Co.,Ltd. OUI:B8D8124* ID_OUI_FROM_DATABASE=V5 Technology Corporation OUI:74E14A6* ID_OUI_FROM_DATABASE=Emerging Technology (Holdings) Ltd. OUI:74E14A3* ID_OUI_FROM_DATABASE=emz-Hanauer GmbH & Co. KGaA OUI:E4956ED* ID_OUI_FROM_DATABASE=Shanghai Tieda Telecommunications Equipment Co.,LTD. OUI:D022122* ID_OUI_FROM_DATABASE=RHENAC Systems GmbH OUI:E81863D* ID_OUI_FROM_DATABASE=DIGITAL DYNAMICS, INC. OUI:E818639* ID_OUI_FROM_DATABASE=BSM Wireless Inc. OUI:D02212D* ID_OUI_FROM_DATABASE=SHENZHEN ZHONGXI SECURITY CO.,LTD OUI:E4956EA* ID_OUI_FROM_DATABASE=Red Point Positioning, Corp. OUI:E4956E4* ID_OUI_FROM_DATABASE=Guang Lian Zhi Tong Technology Limited OUI:B8D8120* ID_OUI_FROM_DATABASE=Glamo Inc. OUI:74E14AA* ID_OUI_FROM_DATABASE=AStar Design Service Technologies Co., Ltd. OUI:A44F297* ID_OUI_FROM_DATABASE=Protean Payment OUI:A44F290* ID_OUI_FROM_DATABASE=Dermalog Identification Systems GmbH OUI:3C39E7E* ID_OUI_FROM_DATABASE=MARPOSS SPA OUI:3C39E7C* ID_OUI_FROM_DATABASE=VANSTONE ELECTRONIC (BEIJING)CO,. LTD. OUI:3C39E72* ID_OUI_FROM_DATABASE=HomeWizard B.V. OUI:D022126* ID_OUI_FROM_DATABASE=URANO INDUSTRIA DE BALANCAS E EQUIPAMENTOS LTDA OUI:BC6641D* ID_OUI_FROM_DATABASE=UtilLighting Co.,Ltd. OUI:BC66419* ID_OUI_FROM_DATABASE=Shenzhen General Measure Technology Co., Ltd OUI:BC66416* ID_OUI_FROM_DATABASE=Intuitive Surgical, Inc OUI:BC34001* ID_OUI_FROM_DATABASE=IPLINK Technology Corp OUI:A43BFAE* ID_OUI_FROM_DATABASE=The Magstim Company Ltd. OUI:A43BFAA* ID_OUI_FROM_DATABASE=Plus One Japan Ltd. OUI:BC66411* ID_OUI_FROM_DATABASE=Global China Technology Limited OUI:B01F815* ID_OUI_FROM_DATABASE=SHENZHEN GRID TECHNOLOGY CO.,LTD OUI:B01F811* ID_OUI_FROM_DATABASE=Uvax Concepts OUI:F40E11E* ID_OUI_FROM_DATABASE=Elektronika Naglic d.o.o. OUI:F40E112* ID_OUI_FROM_DATABASE=Axel srl OUI:7C70BC9* ID_OUI_FROM_DATABASE=dogtra OUI:7C70BC5* ID_OUI_FROM_DATABASE=Canary Connect, Inc. OUI:141FBA7* ID_OUI_FROM_DATABASE=Wisnetworks Technologies Co., Ltd. OUI:7C70BCE* ID_OUI_FROM_DATABASE=HOPERUN MMAX DIGITAL PTE. LTD. OUI:7C70BC0* ID_OUI_FROM_DATABASE=Shanghai magcomm communication technology co ltd OUI:BC3400B* ID_OUI_FROM_DATABASE=FARO TECHNOLOGIES, INC. OUI:BC34007* ID_OUI_FROM_DATABASE=Q-PRODUCTS a. s. OUI:B01F81D* ID_OUI_FROM_DATABASE=TAIWAN Anjie Electronics Co.,Ltd. OUI:7419F87* ID_OUI_FROM_DATABASE=Broadanet S.T.M OUI:A43BFA7* ID_OUI_FROM_DATABASE=Deatronic srl OUI:A43BFA2* ID_OUI_FROM_DATABASE=Powell Industries OUI:D07650E* ID_OUI_FROM_DATABASE=Revox Inc. OUI:D07650A* ID_OUI_FROM_DATABASE=InventDesign OUI:D076503* ID_OUI_FROM_DATABASE=TAPKO Technologies GmbH OUI:1C87741* ID_OUI_FROM_DATABASE=SIGFOX OUI:1C87743* ID_OUI_FROM_DATABASE=Silora R&D OUI:3C39E7F* ID_OUI_FROM_DATABASE=Private OUI:E81863F* ID_OUI_FROM_DATABASE=Private OUI:90C682F* ID_OUI_FROM_DATABASE=Private OUI:9802D8F* ID_OUI_FROM_DATABASE=Private OUI:F80278F* ID_OUI_FROM_DATABASE=Private OUI:1C88795* ID_OUI_FROM_DATABASE=SHENZHENFREELINK ELECTRONIC CO.,LTD OUI:1CCAE3F* ID_OUI_FROM_DATABASE=Private OUI:1C8879C* ID_OUI_FROM_DATABASE=Accriva OUI:1C87799* ID_OUI_FROM_DATABASE=Istria soluciones de criptografia, S. A. OUI:1C87749* ID_OUI_FROM_DATABASE=Wide World Trade HK ltd. OUI:1C8774B* ID_OUI_FROM_DATABASE=HABEY USA Inc. OUI:1C88794* ID_OUI_FROM_DATABASE=Ultraflux OUI:1C88796* ID_OUI_FROM_DATABASE=Eolos IT Corp OUI:1C8774E* ID_OUI_FROM_DATABASE=Quest Integrity OUI:78CA834* ID_OUI_FROM_DATABASE=Pinhole (Beijing) Technology Co., Ltd. OUI:78CA83E* ID_OUI_FROM_DATABASE=Konecranes OUI:38B8EBB* ID_OUI_FROM_DATABASE=ExaScaler Inc. OUI:38FDFEC* ID_OUI_FROM_DATABASE=New Garden Co., Ltd. OUI:38FDFE5* ID_OUI_FROM_DATABASE=CaptiveAire Systems Inc. OUI:5CF2867* ID_OUI_FROM_DATABASE=Access IS OUI:5CF286C* ID_OUI_FROM_DATABASE=Sunpet Industries Limited OUI:5CF2862* ID_OUI_FROM_DATABASE=Shanghai Notion Information Technology CO.,LTD. OUI:5CF2866* ID_OUI_FROM_DATABASE=VPInstruments OUI:5CF286A* ID_OUI_FROM_DATABASE=Unfors Raysafe AB OUI:7C477C5* ID_OUI_FROM_DATABASE=Midwest Microwave Solutions OUI:5CF286E* ID_OUI_FROM_DATABASE=Daisen Electronic Industrial Co., Ltd. OUI:7C477C1* ID_OUI_FROM_DATABASE=Photosynth Inc. OUI:986D35A* ID_OUI_FROM_DATABASE=iWave Japan, Inc. OUI:986D357* ID_OUI_FROM_DATABASE=Zhejiang Hanshow Technology Co., Ltd. OUI:50FF99C* ID_OUI_FROM_DATABASE=Goetting KG OUI:50FF995* ID_OUI_FROM_DATABASE=Garrison Technology OUI:50FF997* ID_OUI_FROM_DATABASE=Honeywell International OUI:50FF99B* ID_OUI_FROM_DATABASE=Sichuan Dowlab Electronics Technology Co. Ltd OUI:E0B6F55* ID_OUI_FROM_DATABASE=Shenzhen Civicom Technology Co.,Limited OUI:E0B6F50* ID_OUI_FROM_DATABASE=BeSTAR Corporation OUI:E0B6F57* ID_OUI_FROM_DATABASE=Shenzhen Xrinda Technology Ltd OUI:E0B6F5B* ID_OUI_FROM_DATABASE=Moog Crossbow OUI:E0B6F5C* ID_OUI_FROM_DATABASE=funktel GmbH OUI:1C8776C* ID_OUI_FROM_DATABASE=Strone Technology OUI:1C87795* ID_OUI_FROM_DATABASE=BEIDIAN GROUP OUI:1C8779B* ID_OUI_FROM_DATABASE=Beijing Geedeen Technology Co., Ltd OUI:B01F81F* ID_OUI_FROM_DATABASE=Private OUI:0055DAF* ID_OUI_FROM_DATABASE=Private OUI:A43BFAF* ID_OUI_FROM_DATABASE=Private OUI:7C70BCF* ID_OUI_FROM_DATABASE=Private OUI:1C87794* ID_OUI_FROM_DATABASE=Novetta OUI:1C87792* ID_OUI_FROM_DATABASE=SMARTMOVT TECHNOLOGY Co., LTD OUI:1C87791* ID_OUI_FROM_DATABASE=A-GEAR COMPANY LIMITED OUI:8439BED* ID_OUI_FROM_DATABASE=Shenzhen Lidaxun Digital Technology Co.,Ltd OUI:8439BE9* ID_OUI_FROM_DATABASE=Guangdong SunMeng Information Technology Co. Ltd. OUI:8439BEC* ID_OUI_FROM_DATABASE=EDC Electronic Design Chemnitz GmbH OUI:8439BEA* ID_OUI_FROM_DATABASE=Emotiq s.r.l. OUI:40A36BA* ID_OUI_FROM_DATABASE=Embrionix Design Inc. OUI:8439BE4* ID_OUI_FROM_DATABASE=Shenzhen Ramos Digital Technology Co,.Ltd. OUI:40A36B4* ID_OUI_FROM_DATABASE=SKS-Kinkel Elektronik GmbH OUI:800A803* ID_OUI_FROM_DATABASE=Beijing VControl Technology Co., Ltd. OUI:A03E6BD* ID_OUI_FROM_DATABASE=Jining SmartCity Infotech Co.Ltd. OUI:C88ED1C* ID_OUI_FROM_DATABASE=Shanghai Bwave Technology Co.,Ltd OUI:C88ED1B* ID_OUI_FROM_DATABASE=Advanced Micro Controls Inc. OUI:C88ED16* ID_OUI_FROM_DATABASE=Shenyang Machine Tool(Group) Research & Design Institute Co., Ltd, Shanghai Branch OUI:CC1BE0B* ID_OUI_FROM_DATABASE=ART&CORE Inc OUI:CC1BE07* ID_OUI_FROM_DATABASE=Sichuan Dianjia network technology Co.Ltd. OUI:CC1BE00* ID_OUI_FROM_DATABASE=MICROTECH SYSTEM OUI:DC44270* ID_OUI_FROM_DATABASE=Suritel OUI:B0C5CAE* ID_OUI_FROM_DATABASE=Audio Elektronik İthalat İhracat San ve Tic A.Ş. OUI:B0C5CA9* ID_OUI_FROM_DATABASE=D&T Inc. OUI:C88ED10* ID_OUI_FROM_DATABASE=AISWORLD PRIVATE LIMITED OUI:C88ED12* ID_OUI_FROM_DATABASE=ROTRONIC AG OUI:1C21D16* ID_OUI_FROM_DATABASE=Wuhan TieChi Detection Technology Co., Ltd. OUI:DC44276* ID_OUI_FROM_DATABASE=EK-TEAM Elektronik- u. Kunststoff-Technik GmbH OUI:DC4427A* ID_OUI_FROM_DATABASE=Shanghai Huahong Integrated Circuit Co.,Ltd OUI:A03E6B8* ID_OUI_FROM_DATABASE=718th Research Institute of CSIC OUI:A03E6B3* ID_OUI_FROM_DATABASE=iLoda Solutions Limited OUI:B0C5CA4* ID_OUI_FROM_DATABASE=shanghai University Ding-Tech software Corp.,ltd OUI:78C2C0D* ID_OUI_FROM_DATABASE=KORF Inc. OUI:78C2C0A* ID_OUI_FROM_DATABASE=Ombitron, Inc. OUI:78C2C03* ID_OUI_FROM_DATABASE=Ningbo Sanxing Electric Co., Ltd. OUI:B437D1E* ID_OUI_FROM_DATABASE=Union Tecnologica Noxium S.L. OUI:B437D19* ID_OUI_FROM_DATABASE=Nanjing yuekong Intelligent Technology OUI:885D906* ID_OUI_FROM_DATABASE=Hi-Profile Achievement (M) Sdn Bhd OUI:885D900* ID_OUI_FROM_DATABASE=FOSHAN HUAGUO OPTICAL CO.,LTD OUI:74F8DB8* ID_OUI_FROM_DATABASE=Songam Syscom Co. LTD. OUI:74F8DB6* ID_OUI_FROM_DATABASE=Shenzhen Melon Electronics Co.,Ltd OUI:885D90B* ID_OUI_FROM_DATABASE=Premier Merchandises Limited OUI:B437D15* ID_OUI_FROM_DATABASE=Stratom, Inc. OUI:74F8DBC* ID_OUI_FROM_DATABASE=TBM CO., LTD. OUI:2C6A6F0* ID_OUI_FROM_DATABASE=Shanghai Shuncom Electronic Technology Co.,Ltd OUI:2C6A6F1* ID_OUI_FROM_DATABASE=ELKO EP, s.r.o. OUI:9802D8E* ID_OUI_FROM_DATABASE=Private OUI:549A11D* ID_OUI_FROM_DATABASE=Hangzhou duotin Technology Co., Ltd. OUI:549A11A* ID_OUI_FROM_DATABASE=VendNovation LLC OUI:549A113* ID_OUI_FROM_DATABASE=Royal Boon Edam International BV OUI:549A110* ID_OUI_FROM_DATABASE=Shenzhen Excera Technology Co.,Ltd. OUI:807B85E* ID_OUI_FROM_DATABASE=Mersen OUI:807B859* ID_OUI_FROM_DATABASE=SMART ELECTRONICS NZ LIMITED OUI:1CCAE32* ID_OUI_FROM_DATABASE=Insigma Inc OUI:80E4DAA* ID_OUI_FROM_DATABASE=Neutronics OUI:1CCAE3E* ID_OUI_FROM_DATABASE=Dabi Atlante S/A Industrias Medico Odontológicas OUI:1CCAE3B* ID_OUI_FROM_DATABASE=Dream Visions Co., LTD OUI:1CCAE3A* ID_OUI_FROM_DATABASE=SIREA OUI:2CD1418* ID_OUI_FROM_DATABASE=Minno LLC OUI:90C682B* ID_OUI_FROM_DATABASE=Lachmann & Rink GmbH OUI:80E4DA0* ID_OUI_FROM_DATABASE=Wheatstone Corporation OUI:64FB819* ID_OUI_FROM_DATABASE=hiQview Corporation OUI:64FB814* ID_OUI_FROM_DATABASE=Pricer AB OUI:90C6825* ID_OUI_FROM_DATABASE=S.A.E.T. S.R.L. OUI:90C6827* ID_OUI_FROM_DATABASE=Cinet Inc OUI:90C6820* ID_OUI_FROM_DATABASE=Shenzhen Lencotion Technology Co.,Ltd OUI:2C6A6FC* ID_OUI_FROM_DATABASE=Sensity Systems OUI:2C6A6FB* ID_OUI_FROM_DATABASE=Schneider Electric Korea OUI:2C6A6F8* ID_OUI_FROM_DATABASE=Milbank Manufacturing Co. OUI:807B853* ID_OUI_FROM_DATABASE=Zhuhai TOP Intelligence Electric Co., Ltd. OUI:A0BB3ED* ID_OUI_FROM_DATABASE=Shenzhen Talent Technology company limited OUI:9802D84* ID_OUI_FROM_DATABASE=Zedi, Inc. OUI:28FD808* ID_OUI_FROM_DATABASE=Jasco Products Company OUI:28FD801* ID_OUI_FROM_DATABASE=Galileo, Inc. OUI:2C265F8* ID_OUI_FROM_DATABASE=Itus Networks, LLC OUI:0CEFAF9* ID_OUI_FROM_DATABASE=Rotel OUI:0CEFAF6* ID_OUI_FROM_DATABASE=Firmware Design AS OUI:A44F299* ID_OUI_FROM_DATABASE=Certi Networks Sdn Bhd OUI:A44F293* ID_OUI_FROM_DATABASE=Comsel System Ltd OUI:A44F295* ID_OUI_FROM_DATABASE=Shanghai KuanYu Industrial Network Equipment Co.,Ltd OUI:100723E* ID_OUI_FROM_DATABASE=First Chair Acoustics Co., Ltd. OUI:1007234* ID_OUI_FROM_DATABASE=Audio Engineering Ltd. OUI:2C265F5* ID_OUI_FROM_DATABASE=Motec GmbH OUI:F802785* ID_OUI_FROM_DATABASE=Electric Objects OUI:A0BB3E0* ID_OUI_FROM_DATABASE=Link Labs OUI:28FD80B* ID_OUI_FROM_DATABASE=Poket Hardware GmbH OUI:3C39E73* ID_OUI_FROM_DATABASE=ELSA Japan Inc. OUI:E4956E8* ID_OUI_FROM_DATABASE=PT.MLWTelecom OUI:E4956E7* ID_OUI_FROM_DATABASE=NationalchipKorea OUI:E4956E2* ID_OUI_FROM_DATABASE=Shanghai Hoping Technology Co., Ltd. OUI:E4956E1* ID_OUI_FROM_DATABASE=Tband srl OUI:E818637* ID_OUI_FROM_DATABASE=Siliconcube OUI:E818630* ID_OUI_FROM_DATABASE=DigiMagus Technology (Shenzhen) Co., Ltd OUI:B8D8129* ID_OUI_FROM_DATABASE=Entotem LTD OUI:74E14AC* ID_OUI_FROM_DATABASE=Wuhan Shenghong Laser Projection Technology Co.,LTD OUI:B01F81E* ID_OUI_FROM_DATABASE=Advanced & Wise Technology Corp. OUI:B01F81A* ID_OUI_FROM_DATABASE=Steffens Systems GmbH OUI:D02212A* ID_OUI_FROM_DATABASE=GNS-GmbH OUI:D022129* ID_OUI_FROM_DATABASE=UAB "SALDA" OUI:D022124* ID_OUI_FROM_DATABASE=Viatron GmbH OUI:D022120* ID_OUI_FROM_DATABASE=Spirit IT B.V. OUI:E81863A* ID_OUI_FROM_DATABASE=JDM Mobile Internet Solution(Shanghai) Co., Ltd. OUI:BC66413* ID_OUI_FROM_DATABASE=Solectria Renewables, LLC OUI:58FCDB6* ID_OUI_FROM_DATABASE=Timex Group USA Inc OUI:58FCDB7* ID_OUI_FROM_DATABASE=Open Roads Consulting, Inc. OUI:BC6641B* ID_OUI_FROM_DATABASE=Sidus Novum Sp. z o. o. OUI:74E14A8* ID_OUI_FROM_DATABASE=aritec gmbh OUI:74E14A1* ID_OUI_FROM_DATABASE=Cerevo Inc. OUI:D07650C* ID_OUI_FROM_DATABASE=Electro-Motive Diesel OUI:D076507* ID_OUI_FROM_DATABASE=ENCORED Technologies, Inc. OUI:D076505* ID_OUI_FROM_DATABASE=Annapurna Labs OUI:141FBA6* ID_OUI_FROM_DATABASE=Thales Communications & Security SAS OUI:7C70BC2* ID_OUI_FROM_DATABASE=Digital Lumens OUI:BC3400E* ID_OUI_FROM_DATABASE=LLD Technology Ltd. OUI:BC3400D* ID_OUI_FROM_DATABASE=Hangzhou Linker Digital Technology Co., Ltd OUI:BC34009* ID_OUI_FROM_DATABASE=Shenzhen PHilorise Technical Limited OUI:A43BFA9* ID_OUI_FROM_DATABASE=SHEN ZHEN PASUN TECH CO.LTD. OUI:A43BFA5* ID_OUI_FROM_DATABASE=BOI Solutions OUI:A43BFA1* ID_OUI_FROM_DATABASE=Beijing Uniwill Science and Technology Co,Ltd OUI:D076501* ID_OUI_FROM_DATABASE=DAIKEN AUTOMACAO LTDA OUI:7419F8C* ID_OUI_FROM_DATABASE=Bach Icon ApS OUI:7C70BCC* ID_OUI_FROM_DATABASE=Lukup Media OUI:7C70BC6* ID_OUI_FROM_DATABASE=Bidgely OUI:F40E11B* ID_OUI_FROM_DATABASE=BRADAR INDUSTRIA SA OUI:F40E117* ID_OUI_FROM_DATABASE=Shenzhen Grandsun Electronic Co.,Ltd. OUI:F40E115* ID_OUI_FROM_DATABASE=E-SONG OUI:F40E110* ID_OUI_FROM_DATABASE=realphone technology co.,ltd OUI:BC34004* ID_OUI_FROM_DATABASE=Dexcel Design Pvt Ltd OUI:B01F818* ID_OUI_FROM_DATABASE=Technion Oy OUI:7419F8A* ID_OUI_FROM_DATABASE=Tanjarine OUI:7419F83* ID_OUI_FROM_DATABASE=Essential Trading Systems Corp OUI:7419F80* ID_OUI_FROM_DATABASE=Marmitek OUI:100723F* ID_OUI_FROM_DATABASE=Private OUI:D02212F* ID_OUI_FROM_DATABASE=Private OUI:B0C5CAF* ID_OUI_FROM_DATABASE=Private OUI:1C8779E* ID_OUI_FROM_DATABASE=ASSYSTEM France OUI:1C88791* ID_OUI_FROM_DATABASE=ANDRA Sp. z o.o. OUI:1C87744* ID_OUI_FROM_DATABASE=Weber Marking Systems GmbH OUI:1C8774C* ID_OUI_FROM_DATABASE=New Nordic Engineering OUI:1C88797* ID_OUI_FROM_DATABASE=Sensys Networks, Inc. OUI:1C8879B* ID_OUI_FROM_DATABASE=gekartel AG OUI:78CA836* ID_OUI_FROM_DATABASE=Nomiku OUI:78CA832* ID_OUI_FROM_DATABASE=APC OUI:78CA838* ID_OUI_FROM_DATABASE=IHM OUI:78CA839* ID_OUI_FROM_DATABASE=Louroe Electronics OUI:78CA83C* ID_OUI_FROM_DATABASE=Elanview Technology Co.,Ltd OUI:38B8EB8* ID_OUI_FROM_DATABASE=CeeNex Inc OUI:38B8EBD* ID_OUI_FROM_DATABASE=Yellowbrick Data, Inc. OUI:38B8EB6* ID_OUI_FROM_DATABASE=MATRIXSTREAM TECHNOLOGIES, INC. OUI:38B8EB2* ID_OUI_FROM_DATABASE=barox Kommunikation GmbH OUI:38B8EBC* ID_OUI_FROM_DATABASE=Ajax Systems Inc OUI:38B8EBE* ID_OUI_FROM_DATABASE=Wyres SAS OUI:38FDFE1* ID_OUI_FROM_DATABASE=WAYTONE (BEIIJNG) COMMUNICATIONS CO.,LTD OUI:38FDFEE* ID_OUI_FROM_DATABASE=iSmart electronic technology co.,LTD OUI:38FDFE8* ID_OUI_FROM_DATABASE=Indra Navia AS OUI:5CF2864* ID_OUI_FROM_DATABASE=CHIPSEN Co.,Ltd. OUI:5CF2868* ID_OUI_FROM_DATABASE=SHENZHEN HIVT TECHNOLOGY CO.,LTD OUI:7C477C9* ID_OUI_FROM_DATABASE=DaLian Cheering Tech Co.,Ltd OUI:7C477C0* ID_OUI_FROM_DATABASE=BungBungame Inc OUI:7C477C4* ID_OUI_FROM_DATABASE=RLC Electronics Systems OUI:7C477CE* ID_OUI_FROM_DATABASE=I-Convergence.com OUI:986D35D* ID_OUI_FROM_DATABASE=Praesideo B.V. OUI:986D358* ID_OUI_FROM_DATABASE=Beijing 3CAVI Tech Co.,Ltd OUI:986D350* ID_OUI_FROM_DATABASE=Shenzhen MALATA Mobile Communication Co.,LTD OUI:986D354* ID_OUI_FROM_DATABASE=blossom communications corp. OUI:50FF998* ID_OUI_FROM_DATABASE=Dolphin Concepts Limited OUI:50FF99D* ID_OUI_FROM_DATABASE=Shenzhen Haipengxin Electronic Co., Ltd. OUI:50FF993* ID_OUI_FROM_DATABASE=Yongjing Shanghai Electronic Science and Technology OUI:50FF992* ID_OUI_FROM_DATABASE=SHENZHEN KINGVT ELECTRONICS CO.,LTD OUI:E0B6F5A* ID_OUI_FROM_DATABASE=Folksam AB OUI:E0B6F54* ID_OUI_FROM_DATABASE=Agora OUI:E0B6F5E* ID_OUI_FROM_DATABASE=Advatek Lighting Pty Ltd OUI:1C87790* ID_OUI_FROM_DATABASE=Wurm GmbH & Co. KG Elektronische Systeme OUI:1C87797* ID_OUI_FROM_DATABASE=TASC Systems Inc. OUI:1C87796* ID_OUI_FROM_DATABASE=Shenzhen Shouxin Tongda Technology Co.,Ltd OUI:BC3400F* ID_OUI_FROM_DATABASE=Private OUI:1C87765* ID_OUI_FROM_DATABASE=Zhuhai MYZR Technology Co.,Ltd OUI:1C8779C* ID_OUI_FROM_DATABASE=AllThingsTalk OUI:7419F8F* ID_OUI_FROM_DATABASE=Private OUI:1C8776A* ID_OUI_FROM_DATABASE=Jiangsu ETERN COMMUNICATION Co.,ltd OUI:40A36B0* ID_OUI_FROM_DATABASE=Fin Robotics Inc OUI:8439BE2* ID_OUI_FROM_DATABASE=Cheng Du virtual world Technology Limited. OUI:1C87793* ID_OUI_FROM_DATABASE=Visual Land Inc. OUI:70886B9* ID_OUI_FROM_DATABASE=Shenzhen Coolhear Information Technology Co., Ltd. OUI:70886B4* ID_OUI_FROM_DATABASE=HORI CO., LTD. OUI:70886B5* ID_OUI_FROM_DATABASE=Chengdu Ophylink Communication Technology Ltd. OUI:70886B0* ID_OUI_FROM_DATABASE=Veracity UK Ltd OUI:70886BA* ID_OUI_FROM_DATABASE=RHXTune Technology Co.,Ltd OUI:70886BC* ID_OUI_FROM_DATABASE=MAX4G, Inc. OUI:800A804* ID_OUI_FROM_DATABASE=LLVISION TECHNOLOGY CO.,LTD OUI:1C21D1E* ID_OUI_FROM_DATABASE=p2-plus inc. OUI:1C21D1B* ID_OUI_FROM_DATABASE=Global Design Solutions Ltd OUI:1C21D14* ID_OUI_FROM_DATABASE=Scientific-Production Enterprise Dynamics OUI:A03E6B6* ID_OUI_FROM_DATABASE=Wuhan Rui Ying Tong Network Technology Co., Ltd(China) OUI:A03E6B5* ID_OUI_FROM_DATABASE=Friday Lab, UAB OUI:C88ED1E* ID_OUI_FROM_DATABASE=Aventics GmbH OUI:A03E6B0* ID_OUI_FROM_DATABASE=s&t embedded GmbH OUI:C88ED18* ID_OUI_FROM_DATABASE=Electronic Controls Design, Inc. OUI:1C21D11* ID_OUI_FROM_DATABASE=Ognios GmbH OUI:DC4427E* ID_OUI_FROM_DATABASE=VerifEye Technologies OUI:DC4427D* ID_OUI_FROM_DATABASE=Rohde&Schwarz Topex SA OUI:DC44278* ID_OUI_FROM_DATABASE=Wharton Electronics Ltd OUI:DC44274* ID_OUI_FROM_DATABASE=Nex Technologies PTY LTD OUI:0055DAE* ID_OUI_FROM_DATABASE=Victorsure Limited OUI:0055DA8* ID_OUI_FROM_DATABASE=BroadSoft, Inc. OUI:0055DA4* ID_OUI_FROM_DATABASE=Datapath Limited OUI:0055DA9* ID_OUI_FROM_DATABASE=Quantum Communication Technology Co., Ltd.,Anhui OUI:0055DA3* ID_OUI_FROM_DATABASE=Novexx Solutions GmbH OUI:B0C5CA6* ID_OUI_FROM_DATABASE=SunTech Medical, Inc. OUI:DC44272* ID_OUI_FROM_DATABASE=Skywave Technology Co,.Ltd. OUI:B0C5CAC* ID_OUI_FROM_DATABASE=XMetrics OUI:CC1BE0D* ID_OUI_FROM_DATABASE=NEWSTAR (HK) ELECTRONIC DEVELOPMENT LIMITED OUI:CC1BE09* ID_OUI_FROM_DATABASE=MobiStor Technology Inc. OUI:CC1BE04* ID_OUI_FROM_DATABASE=Laserworld (Switzerland) AG OUI:CC1BE03* ID_OUI_FROM_DATABASE=Shenzhen Vanstor Technology Co.,Ltd OUI:A03E6BB* ID_OUI_FROM_DATABASE=KoCoS Messtechnik AG OUI:B0C5CA1* ID_OUI_FROM_DATABASE=IVK-SAYANY OUI:74F8DB4* ID_OUI_FROM_DATABASE=WiFi Hotspots, SL OUI:74F8DB0* ID_OUI_FROM_DATABASE=Enercon Technologies OUI:885D90E* ID_OUI_FROM_DATABASE=Unitac Technology Limited OUI:885D90C* ID_OUI_FROM_DATABASE=iRoom GmbH OUI:78C2C04* ID_OUI_FROM_DATABASE=Ory Laboratory Co., Ltd. OUI:B437D1B* ID_OUI_FROM_DATABASE=NSI Co., Ltd. OUI:B437D16* ID_OUI_FROM_DATABASE=Yireh Auto Tech Co.,Ltd. OUI:B437D12* ID_OUI_FROM_DATABASE=Fibersystem AB OUI:B437D11* ID_OUI_FROM_DATABASE=Alturna Networks OUI:74F8DBE* ID_OUI_FROM_DATABASE=Bernard Krone Holding GmbH & Co. KG OUI:74F8DBA* ID_OUI_FROM_DATABASE=Ballard Technology Inc. OUI:885D908* ID_OUI_FROM_DATABASE=Creative Sensor Inc. OUI:885D902* ID_OUI_FROM_DATABASE=DAIDONG Industrial System Co., Ltd. OUI:78C2C0B* ID_OUI_FROM_DATABASE=Wan Chao An (Beijing) Technology Co., Ltd. OUI:78C2C07* ID_OUI_FROM_DATABASE=Guangzhou Hongcai Stage Equipment co.,ltd OUI:80E4DA8* ID_OUI_FROM_DATABASE=Krizer international Co,. Ltd. OUI:80E4DA4* ID_OUI_FROM_DATABASE=Beijing Yuantel Technolgy Co.,Ltd-Shenzhen Branch OUI:80E4DA2* ID_OUI_FROM_DATABASE=Thurlby Thandar Instruments LTD OUI:2CD141D* ID_OUI_FROM_DATABASE=Private OUI:2C6A6F6* ID_OUI_FROM_DATABASE=Beep, Inc. OUI:2C6A6F2* ID_OUI_FROM_DATABASE=NanChang LangJie Technology Co.,Ltd OUI:9802D8C* ID_OUI_FROM_DATABASE=AGV spa OUI:9802D88* ID_OUI_FROM_DATABASE=Simplo Technology Co.,LTD OUI:1CCAE35* ID_OUI_FROM_DATABASE=TengFeng OUI:80E4DAE* ID_OUI_FROM_DATABASE=Akenori PTE LTD OUI:807B85B* ID_OUI_FROM_DATABASE=Oliotalo Oy OUI:807B856* ID_OUI_FROM_DATABASE=Quickte Technology Co.,Ltd OUI:807B851* ID_OUI_FROM_DATABASE=Hangzhou Synway Information Engineering Co., Ltd OUI:549A119* ID_OUI_FROM_DATABASE=Alfen BV OUI:549A116* ID_OUI_FROM_DATABASE=Orient Direct, Inc. OUI:549A115* ID_OUI_FROM_DATABASE=Elotech Industrieelektronik GmbH OUI:64FB81C* ID_OUI_FROM_DATABASE=Bridgeport Instruments, LLC OUI:64FB81B* ID_OUI_FROM_DATABASE=Sichuan Haige Actec Communication Technology Co.,Ltd. OUI:64FB817* ID_OUI_FROM_DATABASE=Securosys SA OUI:2CD1416* ID_OUI_FROM_DATABASE=Bowei Technology Company Limited OUI:2CD1413* ID_OUI_FROM_DATABASE=AOptix Technologies, Inc OUI:2CD1410* ID_OUI_FROM_DATABASE=iCIRROUND Inc OUI:90C682D* ID_OUI_FROM_DATABASE=PowerShield Limited OUI:64FB810* ID_OUI_FROM_DATABASE=SHANGHAI SIMCOM LIMITED OUI:64FB812* ID_OUI_FROM_DATABASE=Seven Solutions S.L OUI:1CCAE38* ID_OUI_FROM_DATABASE=OxySec S.r.l. OUI:90C6828* ID_OUI_FROM_DATABASE=Teletek Electronics OUI:90C6823* ID_OUI_FROM_DATABASE=Innovative Electronic Technology OUI:2C265FD* ID_OUI_FROM_DATABASE=E Core Corporation OUI:2C265FA* ID_OUI_FROM_DATABASE=Polara Engineering OUI:2C265F7* ID_OUI_FROM_DATABASE=Coremate Technical Co., Ltd OUI:2C265F3* ID_OUI_FROM_DATABASE=shenzhen Clever Electronic Co., Ltd. OUI:2C265F0* ID_OUI_FROM_DATABASE=XIAMEN VORLINK IOT TECHNOLOGY CO.,LTD. OUI:F80278D* ID_OUI_FROM_DATABASE=Dueton Systems s.r.o. OUI:0CEFAF1* ID_OUI_FROM_DATABASE=Goerlitz AG OUI:A44F29B* ID_OUI_FROM_DATABASE=GUANGDONG REAL-DESIGN INTELLIGENT TECHNOLOGY CO.,LTD OUI:A44F296* ID_OUI_FROM_DATABASE=Selektro Power Inc OUI:A44F291* ID_OUI_FROM_DATABASE=Olssen B.V. OUI:9802D86* ID_OUI_FROM_DATABASE=Fritz Kuebler GmbH OUI:9802D81* ID_OUI_FROM_DATABASE=SHENZHEN ATEKO PHOTOELECTRICITY CO LTD OUI:A0BB3EB* ID_OUI_FROM_DATABASE=Beijing Techshino Technology Co., Ltd. OUI:A0BB3EE* ID_OUI_FROM_DATABASE=Messtechnik Sachs GmbH OUI:A0BB3E7* ID_OUI_FROM_DATABASE=SIMTEC Elektronik GmbH OUI:100723A* ID_OUI_FROM_DATABASE=TESSERA TECHNOLOGY INC. OUI:1007236* ID_OUI_FROM_DATABASE=ESTONE TECHNOLOGY INC OUI:1007233* ID_OUI_FROM_DATABASE=Tongfang computer co.Ltd. OUI:3C39E79* ID_OUI_FROM_DATABASE=Zone Controls AB OUI:3C39E76* ID_OUI_FROM_DATABASE=RO.VE.R. Laboratories S.p.A OUI:F802788* ID_OUI_FROM_DATABASE=EMBUX Technology Co., Ltd. OUI:F802783* ID_OUI_FROM_DATABASE=3Shape Holding A/S OUI:F802781* ID_OUI_FROM_DATABASE=Reason Tecnologia SA OUI:0CEFAFB* ID_OUI_FROM_DATABASE=Hubei Century Network Technology Co .Ltd OUI:A0BB3E2* ID_OUI_FROM_DATABASE=DirectOut GmbH OUI:28FD805* ID_OUI_FROM_DATABASE=Xiaocong Network Limited OUI:E81863C* ID_OUI_FROM_DATABASE=Shenzhen Hipad Telecommunication Technology Co.,Ltd OUI:58FCDB9* ID_OUI_FROM_DATABASE=Hi-Target Surveying Instrument Co., Ltd. OUI:58FCDB5* ID_OUI_FROM_DATABASE=Shenzhen Siecom Communication Technology Development Co.,Ltd. OUI:58FCDB2* ID_OUI_FROM_DATABASE=Beseye Cloud Security Co. Ltd. OUI:B01F81C* ID_OUI_FROM_DATABASE=Access Device Integrated Communications Corp. OUI:BC6641E* ID_OUI_FROM_DATABASE=Lucent Trans Electronics Co., Ltd OUI:BC66415* ID_OUI_FROM_DATABASE=Scientific Games OUI:E4956EC* ID_OUI_FROM_DATABASE=Shenzhen Arronna Telecom Co.,Ltd OUI:E4956EB* ID_OUI_FROM_DATABASE=iConservo Inc OUI:E4956E5* ID_OUI_FROM_DATABASE=ELAN SYSTEMS OUI:74E14A4* ID_OUI_FROM_DATABASE=open joint stock company YUG-SISTEMA plus OUI:E818634* ID_OUI_FROM_DATABASE=Guangzhou Tianyi Electronics Co., Ltd OUI:E818633* ID_OUI_FROM_DATABASE=DongGuan Pengxun Electronics Technology Co., Ltd. OUI:B8D812E* ID_OUI_FROM_DATABASE=ZheJiang FangTai Electirc Co., Ltd OUI:B8D812A* ID_OUI_FROM_DATABASE=Kiwigrid GmbH OUI:BC66410* ID_OUI_FROM_DATABASE=InSync Technology Ltd OUI:58FCDBC* ID_OUI_FROM_DATABASE=Excenon Mobile Technology Co., Ltd. OUI:1007230* ID_OUI_FROM_DATABASE=RippleTek Tech Ltd OUI:D02212C* ID_OUI_FROM_DATABASE=Xperio Labs Ltd. OUI:D022127* ID_OUI_FROM_DATABASE=Cliptech Industria e Comercio Ltda OUI:B8D8127* ID_OUI_FROM_DATABASE=Neuropace Inc. OUI:B8D8123* ID_OUI_FROM_DATABASE=iModesty Technology Corp. OUI:74E14AE* ID_OUI_FROM_DATABASE=Diamond Kinetics OUI:A43BFA6* ID_OUI_FROM_DATABASE=Recognition Systems LLC OUI:A43BFA3* ID_OUI_FROM_DATABASE=Circus World Displays Ltd OUI:7C70BC4* ID_OUI_FROM_DATABASE=K-Vision Technology (Shanghai), Ltd OUI:BC3400A* ID_OUI_FROM_DATABASE=AURALIC LIMITED OUI:B01F816* ID_OUI_FROM_DATABASE=COMOTA Co., Ltd. OUI:B01F812* ID_OUI_FROM_DATABASE=Private OUI:BC34006* ID_OUI_FROM_DATABASE=Cameron OUI:BC34002* ID_OUI_FROM_DATABASE=LifeSmart OUI:A43BFAD* ID_OUI_FROM_DATABASE=JSC “Component-ASU” OUI:F40E11D* ID_OUI_FROM_DATABASE=DXG Technology Corp. OUI:F40E119* ID_OUI_FROM_DATABASE=Sterna Security OUI:F40E113* ID_OUI_FROM_DATABASE=Shenzhen headsun technology OUI:141FBAE* ID_OUI_FROM_DATABASE=POS Systema LLC OUI:141FBAA* ID_OUI_FROM_DATABASE=Winsonic Electronics Co., Ltd. OUI:141FBA4* ID_OUI_FROM_DATABASE=BYZERO OUI:141FBA0* ID_OUI_FROM_DATABASE=Shenzhen Mining Technology Co.,Ltd. OUI:7C70BCA* ID_OUI_FROM_DATABASE=Ametek VIS OUI:7419F8E* ID_OUI_FROM_DATABASE=Volacomm Co., Ltd OUI:D076509* ID_OUI_FROM_DATABASE=Greenwave Scientific OUI:7419F88* ID_OUI_FROM_DATABASE=Quest Payment Systems OUI:7419F84* ID_OUI_FROM_DATABASE=Cloudvue Technologies Corporation OUI:C88ED1F* ID_OUI_FROM_DATABASE=Private OUI:DC4427F* ID_OUI_FROM_DATABASE=Private OUI:1C21D1F* ID_OUI_FROM_DATABASE=Private OUI:1C87742* ID_OUI_FROM_DATABASE=Nichigaku OUI:885D90F* ID_OUI_FROM_DATABASE=Private OUI:80E4DAF* ID_OUI_FROM_DATABASE=Private OUI:1C87747* ID_OUI_FROM_DATABASE=Ing Buero Ziegler OUI:1C88792* ID_OUI_FROM_DATABASE=Airsmart System Co.,Ltd OUI:1C8879D* ID_OUI_FROM_DATABASE=Beijing Raycores Technology Co.,Ltd OUI:78CA833* ID_OUI_FROM_DATABASE=Neofon GmbH OUI:78CA831* ID_OUI_FROM_DATABASE=Excelocity Inc. OUI:78CA837* ID_OUI_FROM_DATABASE=Beijing CarePulse Electronic Technology OUI:78CA83D* ID_OUI_FROM_DATABASE=Hubei Boyuan Zhijia Network Media Co. Ltd. OUI:38B8EB3* ID_OUI_FROM_DATABASE=Aina Wireless Inc OUI:38FDFE3* ID_OUI_FROM_DATABASE=Siemens AG, PG IE R&D OUI:38FDFED* ID_OUI_FROM_DATABASE=FUBA Automotive Electronics GmbH OUI:38FDFE7* ID_OUI_FROM_DATABASE=Rademacher Geraete-Elektronik GmbH OUI:38FDFE0* ID_OUI_FROM_DATABASE=Edge I&D Co., Ltd. OUI:5CF286B* ID_OUI_FROM_DATABASE=Itron UK Limited OUI:7C477C2* ID_OUI_FROM_DATABASE=POWERLAND LIMITED OUI:5CF286D* ID_OUI_FROM_DATABASE=BrightSky, LLC OUI:7C477CB* ID_OUI_FROM_DATABASE=Hangzhou Yiyitaidi Information Technology Co., Ltd. OUI:7C477C3* ID_OUI_FROM_DATABASE=EyeLock LLC OUI:986D351* ID_OUI_FROM_DATABASE=Shenzhen cositea electronics technology co.,LTD OUI:986D35C* ID_OUI_FROM_DATABASE=my-PV GmbH OUI:986D35E* ID_OUI_FROM_DATABASE=BAYCOM OPTO-ELECTRONICS TECHNOLGY CO., LTD. OUI:50FF994* ID_OUI_FROM_DATABASE=IPC Global OUI:50FF996* ID_OUI_FROM_DATABASE=LEGEND WINNER LIMITED OUI:50FF99A* ID_OUI_FROM_DATABASE=metraTec GmbH OUI:50FF99E* ID_OUI_FROM_DATABASE=Informa LLC OUI:E0B6F5D* ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED OUI:E0B6F53* ID_OUI_FROM_DATABASE=Huizhou GISUN Industrial CO. LTD OUI:1C8776B* ID_OUI_FROM_DATABASE=Hekatron Vertriebs GmbH OUI:1C8779A* ID_OUI_FROM_DATABASE=Hangzhou Xiaowen Intelligent Technology Co., Ltd. OUI:1C87798* ID_OUI_FROM_DATABASE=ZHEJIANG ITENAL TECHNOLOGY CO.,LTD OUI:1C87763* ID_OUI_FROM_DATABASE=Unjo AB OUI:58FCDBF* ID_OUI_FROM_DATABASE=Private OUI:A03E6BF* ID_OUI_FROM_DATABASE=Private OUI:1C87767* ID_OUI_FROM_DATABASE=Corporate Systems Engineering OUI:1C87760* ID_OUI_FROM_DATABASE=Dspread technology co.,ltd OUI:1C87769* ID_OUI_FROM_DATABASE=Tokyo Drawing Ltd. OUI:8439BE1* ID_OUI_FROM_DATABASE=Guangzhou Heygears Technology Ltd OUI:40A36B8* ID_OUI_FROM_DATABASE=SFT Co., Ltd. OUI:40A36B1* ID_OUI_FROM_DATABASE=TW-TeamWare OUI:40A36B3* ID_OUI_FROM_DATABASE=Omnitracs, LLC OUI:40A36BC* ID_OUI_FROM_DATABASE=Onion Corporation OUI:40A36BD* ID_OUI_FROM_DATABASE=FAOD Co.,Ltd. OUI:70886B6* ID_OUI_FROM_DATABASE=Church & Dwight Co., Inc. OUI:70886B8* ID_OUI_FROM_DATABASE=Cable Matters Inc. OUI:800A806* ID_OUI_FROM_DATABASE=Beijing Gooagoo Technical Service Co.,Ltd. OUI:800A802* ID_OUI_FROM_DATABASE=Sumitomo Wiring Systems, Ltd. OUI:0055DA5* ID_OUI_FROM_DATABASE=Nanoleaf OUI:0055DA6* ID_OUI_FROM_DATABASE=OOO DEKATRON OUI:0055DA7* ID_OUI_FROM_DATABASE=LUCISTECHNOLOGIES(SHANGHAI)CO.,LTD OUI:800A800* ID_OUI_FROM_DATABASE=Golana Technology (Shenzhen) Co., Ltd. OUI:CC1BE0A* ID_OUI_FROM_DATABASE=Matter Labs Pty Ltd OUI:CC1BE01* ID_OUI_FROM_DATABASE=Beijing Daotongtianxia Co.Ltd. OUI:CC1BE06* ID_OUI_FROM_DATABASE=IC RealTech OUI:A03E6BE* ID_OUI_FROM_DATABASE=Nanjing zhanyi software technology co., LTD OUI:A03E6B2* ID_OUI_FROM_DATABASE=Videx Electronics S.p.A. OUI:A03E6B9* ID_OUI_FROM_DATABASE=Incogniteam Ltd. OUI:B0C5CA8* ID_OUI_FROM_DATABASE=Astyx GmbH OUI:B0C5CAA* ID_OUI_FROM_DATABASE=TEM Mobile Limited OUI:DC4427B* ID_OUI_FROM_DATABASE=Nautilus Infotech CO., Ltd. OUI:DC44277* ID_OUI_FROM_DATABASE=EcoGuard AB OUI:C88ED1D* ID_OUI_FROM_DATABASE=PHOENIX ENGINEERING CORP. OUI:C88ED1A* ID_OUI_FROM_DATABASE=AP Sensing GmbH OUI:C88ED15* ID_OUI_FROM_DATABASE=Fibergate.Inc OUI:1C21D1C* ID_OUI_FROM_DATABASE=Private OUI:C88ED11* ID_OUI_FROM_DATABASE=German Pipe GmbH OUI:1C21D1D* ID_OUI_FROM_DATABASE=Liscotech System Co., Ltd. OUI:1C21D13* ID_OUI_FROM_DATABASE=Microview Science and Technology Co.,Ltd OUI:1C21D12* ID_OUI_FROM_DATABASE=Varaani Works Oy OUI:B0C5CA3* ID_OUI_FROM_DATABASE=abode systems, inc. OUI:78C2C02* ID_OUI_FROM_DATABASE=RONIX incorporated OUI:78C2C00* ID_OUI_FROM_DATABASE=Shenzhen ELI Technology co.,ltd OUI:B437D1D* ID_OUI_FROM_DATABASE=ZXY Sport Tracking OUI:74F8DB7* ID_OUI_FROM_DATABASE=Wuhan Tianyu Information Industry Co., Ltd. OUI:74F8DB2* ID_OUI_FROM_DATABASE=Shenzhen Ruishi Information Technology Co.,Ltd. OUI:885D90A* ID_OUI_FROM_DATABASE=Shenzhen Speedrun Technologies Co.,Ltd. OUI:78C2C09* ID_OUI_FROM_DATABASE=SES OUI:B437D18* ID_OUI_FROM_DATABASE=eInfochips Limited OUI:B437D14* ID_OUI_FROM_DATABASE=KOMSIS ELEKTRONIK SISTEMLERI SAN. TIC. LTD.STI OUI:885D901* ID_OUI_FROM_DATABASE=ShenZhen Yuyangsheng technology company LTD OUI:885D905* ID_OUI_FROM_DATABASE=Shenzhen JingHanDa Electronics Co.Ltd OUI:2CD1414* ID_OUI_FROM_DATABASE=Shanghai RW ELE&TEC CO.,LTD OUI:2CD1415* ID_OUI_FROM_DATABASE=ZENIC INC. OUI:90C682A* ID_OUI_FROM_DATABASE=Beijing Acorn Networks Corporation OUI:90C6826* ID_OUI_FROM_DATABASE=Nanjing Jiexi Technologies Co., Ltd. OUI:64FB81E* ID_OUI_FROM_DATABASE=ChengDu KeChuang LongXin Sci-tech Co.,Ltd OUI:64FB815* ID_OUI_FROM_DATABASE=Kay Schulze & Karsten Pohle GbR OUI:2C6A6FE* ID_OUI_FROM_DATABASE=EATON FHF Funke + Huster Fernsig GmbH OUI:90C6821* ID_OUI_FROM_DATABASE=Shenzhen Photon Broadband Technology CO., LTD OUI:2C6A6F4* ID_OUI_FROM_DATABASE=TINYCO OUI:2C6A6F5* ID_OUI_FROM_DATABASE=SHEN ZHEN SIS SCIENCE & TECHNOLOGY LTD. OUI:1CCAE36* ID_OUI_FROM_DATABASE=TOKAI RIKA CO., LTD. OUI:1CCAE37* ID_OUI_FROM_DATABASE=Bird Home Automation GmbH OUI:80E4DAB* ID_OUI_FROM_DATABASE=Nanjing LILO Technology Co. Ltd. OUI:80E4DAD* ID_OUI_FROM_DATABASE=Dalian Roiland Technology Co.,Ltd OUI:80E4DA6* ID_OUI_FROM_DATABASE=BroadMedia Co., Ltd. OUI:2CD141E* ID_OUI_FROM_DATABASE=CITA SMART SOLUTIONS LTD OUI:549A118* ID_OUI_FROM_DATABASE=Tite, Inc. OUI:549A117* ID_OUI_FROM_DATABASE=Niveo International BV OUI:807B85D* ID_OUI_FROM_DATABASE=Kaynes Technology India Pvt Ltd OUI:807B858* ID_OUI_FROM_DATABASE=IDair, LLC OUI:807B854* ID_OUI_FROM_DATABASE=Quantel USA, Inc. OUI:9802D8A* ID_OUI_FROM_DATABASE=HySecurity OUI:F802786* ID_OUI_FROM_DATABASE=Witium Co., Ltd OUI:0CEFAFD* ID_OUI_FROM_DATABASE=CJSC «Svyaz Engineering» OUI:0CEFAFC* ID_OUI_FROM_DATABASE=GainStrong Industry Co.,Ltd OUI:3C39E71* ID_OUI_FROM_DATABASE=BEWATEC Kommunikationstechnik GmbH OUI:1007239* ID_OUI_FROM_DATABASE=Wireless input technology Inc. OUI:3C39E70* ID_OUI_FROM_DATABASE=Hannstar Display Corp OUI:1007238* ID_OUI_FROM_DATABASE=Ion Professional Solutions OUI:1007237* ID_OUI_FROM_DATABASE=nanoTech Co., Ltd. OUI:D02212E* ID_OUI_FROM_DATABASE=u::Lux GmbH OUI:A44F298* ID_OUI_FROM_DATABASE=Innovations in Optics, Inc. OUI:A44F294* ID_OUI_FROM_DATABASE=DGC Access AB OUI:9802D83* ID_OUI_FROM_DATABASE=Grammer EiA Electronics nv OUI:A0BB3E9* ID_OUI_FROM_DATABASE=Sandal Plc OUI:A0BB3E5* ID_OUI_FROM_DATABASE=ManTech International Corporation OUI:3C39E7A* ID_OUI_FROM_DATABASE=iiM AG OUI:3C39E7B* ID_OUI_FROM_DATABASE=chipsguide technology Co.,LTD OUI:3C39E77* ID_OUI_FROM_DATABASE=Sensor to Image GmbH OUI:3C39E78* ID_OUI_FROM_DATABASE=Martem AS OUI:0CEFAF2* ID_OUI_FROM_DATABASE=LUMEL S.A. OUI:0CEFAF3* ID_OUI_FROM_DATABASE=Engineering Center ENERGOSERVICE OUI:A44F29D* ID_OUI_FROM_DATABASE=HALLIBURTON OUI:28FD804* ID_OUI_FROM_DATABASE=Digital Signal Corp OUI:2C265FB* ID_OUI_FROM_DATABASE=Rexgen Inc. OUI:2C265F6* ID_OUI_FROM_DATABASE=Appostar Technology Co. Ltd OUI:2C265F2* ID_OUI_FROM_DATABASE=Jiangsu JARI Technology Group Co., LTD OUI:2C265F1* ID_OUI_FROM_DATABASE=Griessbach OUI:F80278A* ID_OUI_FROM_DATABASE=Luxul Technology Inc OUI:28FD80E* ID_OUI_FROM_DATABASE=T-Radio AS OUI:74E14A7* ID_OUI_FROM_DATABASE=APM Technologies (DongGuan) Ltd OUI:74E14A2* ID_OUI_FROM_DATABASE=KLIMAT SOLEC Sp. z o.o. OUI:E4956EE* ID_OUI_FROM_DATABASE=Tacom Projetos Bilhetagem Inteligente ltda OUI:D022121* ID_OUI_FROM_DATABASE=AIM OUI:E81863E* ID_OUI_FROM_DATABASE=Acopian Technical Company OUI:E4956E0* ID_OUI_FROM_DATABASE=SMC Networks, Inc OUI:BC6641C* ID_OUI_FROM_DATABASE=Shenzhen Crave Communication Co.,ltd OUI:BC66417* ID_OUI_FROM_DATABASE=VSN Mobil OUI:BC66418* ID_OUI_FROM_DATABASE=Shenzhen Yaguang communication CO.,LTD OUI:D022125* ID_OUI_FROM_DATABASE=Shanghai Routech Co., Ltd OUI:B8D8121* ID_OUI_FROM_DATABASE=VOTEM OUI:74E14AB* ID_OUI_FROM_DATABASE=Loctek Visual Technology Corp. OUI:E4956E9* ID_OUI_FROM_DATABASE=eZeLink LLC OUI:E4956E3* ID_OUI_FROM_DATABASE=Shanghai DGE Co., Ltd OUI:E818636* ID_OUI_FROM_DATABASE=ARTECH SOLUTION CO.,LTD OUI:E818631* ID_OUI_FROM_DATABASE=clabsys OUI:B8D812C* ID_OUI_FROM_DATABASE=Yuwei Info&Tech Development Co.,Ltd OUI:B8D8125* ID_OUI_FROM_DATABASE=XIAMEN XINDECO LTD. OUI:BC66412* ID_OUI_FROM_DATABASE=Process-Electronic Sp. z o.o. OUI:58FCDBE* ID_OUI_FROM_DATABASE=Applied Device Technologies OUI:58FCDBB* ID_OUI_FROM_DATABASE=SWARCO TRAFFIC SYSTEMS GMBH OUI:58FCDBA* ID_OUI_FROM_DATABASE=Xmodus Systems GmbH OUI:58FCDB1* ID_OUI_FROM_DATABASE=Certis Technology International OUI:58FCDB4* ID_OUI_FROM_DATABASE=Inforce Computing Inc. OUI:58FCDB0* ID_OUI_FROM_DATABASE=Spang Power Electronics OUI:141FBAC* ID_OUI_FROM_DATABASE=Swiss Electronic (Shenzhen) Co., Ltd OUI:F40E111* ID_OUI_FROM_DATABASE=BEIJING DONGJIN AERO-TECH CO., LTD OUI:141FBAD* ID_OUI_FROM_DATABASE=AJIS(DALIAN)co.,LTD OUI:141FBA9* ID_OUI_FROM_DATABASE=Black Moth Technologies OUI:141FBA8* ID_OUI_FROM_DATABASE=Shenzhen CATIC Information Technology Industry Co.,Ltd OUI:141FBA3* ID_OUI_FROM_DATABASE=Private OUI:141FBA2* ID_OUI_FROM_DATABASE=Deutsche Energieversorgung GmbH OUI:D07650B* ID_OUI_FROM_DATABASE=PelKorea OUI:D076506* ID_OUI_FROM_DATABASE=Picobrew LLC OUI:7C70BCD* ID_OUI_FROM_DATABASE=mk-messtechnik GmbH OUI:7C70BC8* ID_OUI_FROM_DATABASE=Mennekes Elektrotechnik GmbH & Co. KG OUI:BC34000* ID_OUI_FROM_DATABASE=Redvision CCTV OUI:A43BFAB* ID_OUI_FROM_DATABASE=ALSTOM Strongwish (Shenzhen) Co., Ltd OUI:B01F810* ID_OUI_FROM_DATABASE=Dalian GigaTec Electronics Co.,Ltd OUI:F40E11A* ID_OUI_FROM_DATABASE=Kodpro Ltd. OUI:F40E116* ID_OUI_FROM_DATABASE=Alpha Design Technologies Pvt Ltd OUI:A43BFA8* ID_OUI_FROM_DATABASE=Alpwise OUI:D076502* ID_OUI_FROM_DATABASE=Happo Solutions Oy OUI:7419F8B* ID_OUI_FROM_DATABASE=IDEXX Laboratories, Inc OUI:B01F819* ID_OUI_FROM_DATABASE=CIDE Interactive OUI:B01F814* ID_OUI_FROM_DATABASE=SHENZHEN YIFANG DIGITAL TECHNOLOGY CO.,LTD. OUI:7C70BC1* ID_OUI_FROM_DATABASE=XD-GE Automation CO.,LTD OUI:BC3400C* ID_OUI_FROM_DATABASE=Parlay Labs dba Highfive OUI:BC34008* ID_OUI_FROM_DATABASE=MATICA TECHNOLOGIES AG OUI:7419F86* ID_OUI_FROM_DATABASE=Baudisch Electronic GmbH OUI:7419F82* ID_OUI_FROM_DATABASE=Symtop Instrument Co. OUI:1C88793* ID_OUI_FROM_DATABASE=Shenzhen Xiaoxi Technology Co., Ltd. OUI:B8D812F* ID_OUI_FROM_DATABASE=Private OUI:74E14AF* ID_OUI_FROM_DATABASE=Private OUI:BC6641F* ID_OUI_FROM_DATABASE=Private OUI:74F8DBF* ID_OUI_FROM_DATABASE=Private OUI:E4956EF* ID_OUI_FROM_DATABASE=Private OUI:64FB81F* ID_OUI_FROM_DATABASE=Private OUI:2C6A6FF* ID_OUI_FROM_DATABASE=Private OUI:2C265FF* ID_OUI_FROM_DATABASE=Private OUI:2CD141F* ID_OUI_FROM_DATABASE=Private OUI:A0BB3EF* ID_OUI_FROM_DATABASE=Private OUI:28FD80F* ID_OUI_FROM_DATABASE=Private OUI:1C88798* ID_OUI_FROM_DATABASE=Toshiba Toko meter systems co., LTD. OUI:1C8879A* ID_OUI_FROM_DATABASE=ITW-FEG OUI:1C8776E* ID_OUI_FROM_DATABASE=Artis GmbH OUI:1C88790* ID_OUI_FROM_DATABASE=Newps co.,ltd OUI:1C87745* ID_OUI_FROM_DATABASE=Xiaoxinge (Tangshan) Electronic Technology Co., Ltd. OUI:1C87748* ID_OUI_FROM_DATABASE=Surtec Industries, Inc OUI:1C8879E* ID_OUI_FROM_DATABASE=Orion Labs inc OUI:78CA83A* ID_OUI_FROM_DATABASE=Eksagate Elektronik Mühendislik ve Bilgisayar San. Tic. A.Ş. OUI:78CA83B* ID_OUI_FROM_DATABASE=Zhejiang Science Electronic Tech Co., Ltd OUI:78CA835* ID_OUI_FROM_DATABASE=Huatune Technology (Shanghai) Co., Ltd. OUI:38B8EB0* ID_OUI_FROM_DATABASE=Bumjin C&L Co., Ltd. OUI:38B8EB5* ID_OUI_FROM_DATABASE=Dojo-Labs Ltd OUI:38B8EB1* ID_OUI_FROM_DATABASE=1.A Connect GmbH OUI:38B8EBA* ID_OUI_FROM_DATABASE=SECAD SA OUI:38B8EB7* ID_OUI_FROM_DATABASE=Private OUI:38FDFE6* ID_OUI_FROM_DATABASE=Inspero Inc OUI:38FDFE2* ID_OUI_FROM_DATABASE=B.U.G.SST,Inc OUI:5CF2869* ID_OUI_FROM_DATABASE=Shenzhen VST Automotive Electronics Co., LTD OUI:7C477C7* ID_OUI_FROM_DATABASE=BlueSmart Technology Corporation OUI:7C477CA* ID_OUI_FROM_DATABASE=Dspread Technology (Beijing) Inc. OUI:7C477CC* ID_OUI_FROM_DATABASE=annapurnalabs OUI:986D356* ID_OUI_FROM_DATABASE=Vitronic Dr.-Ing. Stein Bildverarbeitungssysteme GmbH OUI:7C477C8* ID_OUI_FROM_DATABASE=Shenzhen Eunicum Electric Co.,Ltd. OUI:986D35B* ID_OUI_FROM_DATABASE=INTECH OUI:986D352* ID_OUI_FROM_DATABASE=SHENZHEN FISE TECHNOLOGY HOLDING CO.,LTD. OUI:50FF990* ID_OUI_FROM_DATABASE=Simicon OUI:50FF991* ID_OUI_FROM_DATABASE=Coyote Sytem OUI:50FF999* ID_OUI_FROM_DATABASE=Sea Eagle Optoelectronic Information Technology(Tianjin)co,Ltd OUI:E0B6F58* ID_OUI_FROM_DATABASE=Yuneec International(China)Co.,Ltd OUI:E0B6F52* ID_OUI_FROM_DATABASE=Shanghai- British Information Technology Co., Ltd OUI:E0B6F56* ID_OUI_FROM_DATABASE=POMCube Inc. OUI:2C265FC* ID_OUI_FROM_DATABASE=AATON DIGITAL OUI:6891D05* ID_OUI_FROM_DATABASE=NIPK Electron Co. OUI:1C87740* ID_OUI_FROM_DATABASE=Philips Personal Health Solutions OUI:1C87761* ID_OUI_FROM_DATABASE=EBS Sp. z o.o. OUI:1C8779D* ID_OUI_FROM_DATABASE=Shenzhen Innovaconn Systems Co.,Ltd OUI:141FBAF* ID_OUI_FROM_DATABASE=Private OUI:800A80F* ID_OUI_FROM_DATABASE=Private OUI:1C87766* ID_OUI_FROM_DATABASE=philandro Software GmbH OUI:8439BE0* ID_OUI_FROM_DATABASE=HINO ENGINEERING, INC OUI:40A36BB* ID_OUI_FROM_DATABASE=Amobile Intelligent Corp. OUI:8439BE6* ID_OUI_FROM_DATABASE=Shenzhen IP3 Century Intelligent Technology Co., Ltd OUI:8439BEB* ID_OUI_FROM_DATABASE=Shenzhen Horn Audio Co.,Ltd. OUI:40A36B7* ID_OUI_FROM_DATABASE=Pella Corporation OUI:40A36B2* ID_OUI_FROM_DATABASE=TOPROOTTechnology Corp. Ltd. OUI:40A36B9* ID_OUI_FROM_DATABASE=PH Technical Labs OUI:70886B2* ID_OUI_FROM_DATABASE=CVnet OUI:70886B1* ID_OUI_FROM_DATABASE=Bitfinder Inc OUI:0055DAC* ID_OUI_FROM_DATABASE=Donguan WideLink Communication Technology Co.,Ltd. OUI:0055DAD* ID_OUI_FROM_DATABASE=Arrow Electronics,Inc. OUI:0055DAA* ID_OUI_FROM_DATABASE=Speechlab OUI:0055DAB* ID_OUI_FROM_DATABASE=Interaxon Inc OUI:0055DA2* ID_OUI_FROM_DATABASE=Beijing Connected Information Technology Co.,Ltd. OUI:0055DA0* ID_OUI_FROM_DATABASE=Shinko Technos co.,ltd. OUI:0055DA1* ID_OUI_FROM_DATABASE=KoolPOS Inc. OUI:A03E6B7* ID_OUI_FROM_DATABASE=SinoGrid Software Systems Inc. OUI:C88ED17* ID_OUI_FROM_DATABASE=Ube, Inc. (dba Plum) OUI:A03E6BC* ID_OUI_FROM_DATABASE=Qunar.com OUI:A03E6B4* ID_OUI_FROM_DATABASE=Shenzhen Nufilo Inc. OUI:B0C5CAD* ID_OUI_FROM_DATABASE=Private OUI:C88ED13* ID_OUI_FROM_DATABASE=Linx Technologies OUI:1C21D19* ID_OUI_FROM_DATABASE=Dynojet Research OUI:1C21D1A* ID_OUI_FROM_DATABASE=LG CNS OUI:1C21D18* ID_OUI_FROM_DATABASE=Reliatronics Inc. OUI:1C21D15* ID_OUI_FROM_DATABASE=B-Scada Inc. OUI:1C21D10* ID_OUI_FROM_DATABASE=Toyo System CO.,LTD. OUI:CC1BE0C* ID_OUI_FROM_DATABASE=Guangzhou Southelectric Power Science Technology Development Co.,Ltd. OUI:CC1BE08* ID_OUI_FROM_DATABASE=MDT technologies GmbH OUI:DC44279* ID_OUI_FROM_DATABASE=Neusoft Corporation OUI:DC44275* ID_OUI_FROM_DATABASE=Century Audio, Inc. OUI:DC44271* ID_OUI_FROM_DATABASE=Tesla Motors, Inc OUI:78C2C0C* ID_OUI_FROM_DATABASE=Shanghai Hanyi Technologies Co,.Ltd. OUI:78C2C06* ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD OUI:B0C5CA0* ID_OUI_FROM_DATABASE=EM-Tech OUI:74F8DBD* ID_OUI_FROM_DATABASE=Simon Electric (China) Co.,ltd OUI:74F8DB9* ID_OUI_FROM_DATABASE=Avantree Corporation OUI:74F8DB5* ID_OUI_FROM_DATABASE=Provision-ISR OUI:74F8DB1* ID_OUI_FROM_DATABASE=GHL Advanced Technology GmbH & Co. KG OUI:B437D1A* ID_OUI_FROM_DATABASE=Axiomatic Technologies Corporation OUI:B0C5CA5* ID_OUI_FROM_DATABASE=SYSTOVI OUI:549A11E* ID_OUI_FROM_DATABASE=Beijing HTSmartech Co.,Ltd OUI:549A114* ID_OUI_FROM_DATABASE=eTauro LLC OUI:807B85A* ID_OUI_FROM_DATABASE=Interplan Co., Ltd. OUI:90C6824* ID_OUI_FROM_DATABASE=Neone, Inc. OUI:2C6A6F7* ID_OUI_FROM_DATABASE=SM DSP CO.,LTD. OUI:80E4DA5* ID_OUI_FROM_DATABASE=CAVALRY STORAGE INC OUI:80E4DA1* ID_OUI_FROM_DATABASE=Guangzhou Pinzhong Electronic Technology CO., LTD OUI:2CD141C* ID_OUI_FROM_DATABASE=PIN SHANG LED Co., LTD. OUI:2CD141A* ID_OUI_FROM_DATABASE=Fiberroad Technology Co., Ltd. OUI:2CD141B* ID_OUI_FROM_DATABASE=Resus Industries OUI:1CCAE33* ID_OUI_FROM_DATABASE=Shenzhen Smart Device Technology Co.,LTD OUI:1CCAE34* ID_OUI_FROM_DATABASE=Sunray Medical Apparatus Co.,Ltd. OUI:80E4DA9* ID_OUI_FROM_DATABASE=Elcus OUI:64FB813* ID_OUI_FROM_DATABASE=MOBILUS Inc. OUI:1CCAE39* ID_OUI_FROM_DATABASE=SHIN-YOSHA CORPORATION OUI:2CD1417* ID_OUI_FROM_DATABASE=XiaMen 35.com Technology Co,.Ltd. OUI:2CD1412* ID_OUI_FROM_DATABASE=IntelliLUM OUI:2CD1411* ID_OUI_FROM_DATABASE=Ezee Systems Limited OUI:90C682C* ID_OUI_FROM_DATABASE=Li Seng Technology Ltd. OUI:64FB818* ID_OUI_FROM_DATABASE=NPG Technology S.A. OUI:885D907* ID_OUI_FROM_DATABASE=Schmidt & Co.,(H.K.)Ltd. OUI:885D903* ID_OUI_FROM_DATABASE=CPAC Systems OUI:807B852* ID_OUI_FROM_DATABASE=Phoenix Co.,Ltd. OUI:0CEFAF7* ID_OUI_FROM_DATABASE=Syntrans AB OUI:A44F29E* ID_OUI_FROM_DATABASE=Neotech Systems Pvt. Ltd. OUI:0CEFAF0* ID_OUI_FROM_DATABASE=Assurelink OUI:2C265F9* ID_OUI_FROM_DATABASE=Brüel & Kjaer Vibro GmbH OUI:2C265F4* ID_OUI_FROM_DATABASE=GTA Electronics Co., Ltd. OUI:F80278C* ID_OUI_FROM_DATABASE=Technology Research, LLC OUI:F802789* ID_OUI_FROM_DATABASE=Beijing Redcdn Technology, Co., Ltd OUI:A44F29A* ID_OUI_FROM_DATABASE=HTD OUI:A44F292* ID_OUI_FROM_DATABASE=LUCEOR OUI:F802784* ID_OUI_FROM_DATABASE=CLARUS Korea Co., Ltd OUI:F802780* ID_OUI_FROM_DATABASE=Digatron Power Electronics GmbH OUI:0CEFAFA* ID_OUI_FROM_DATABASE=chengdu joyotime Technology Co., Ltd. OUI:9802D85* ID_OUI_FROM_DATABASE=EBI Ltd. OUI:9802D80* ID_OUI_FROM_DATABASE=Stoerk-Tronic, Stoerk GmbH & Co.KG OUI:A0BB3EC* ID_OUI_FROM_DATABASE=Ewig Industries Macao Commercial Offshore Ltd OUI:A0BB3E6* ID_OUI_FROM_DATABASE=Xiamen Kehua Hengsheng Co.,Ltd OUI:2C6A6F3* ID_OUI_FROM_DATABASE=Cloudproject Generation Srl OUI:9802D8D* ID_OUI_FROM_DATABASE=Promicon Elektronik GmbH + Co.KG OUI:9802D89* ID_OUI_FROM_DATABASE=Navroom Beijing, China OUI:A0BB3E1* ID_OUI_FROM_DATABASE=IVision Electronics Co.,Ltd OUI:28FD80A* ID_OUI_FROM_DATABASE=Apollo Digital (Taiwan) Ltd. OUI:28FD806* ID_OUI_FROM_DATABASE=Vigil Monitoring OUI:3C39E75* ID_OUI_FROM_DATABASE=Attrackting AG OUI:3C39E74* ID_OUI_FROM_DATABASE=University of British Columbia OUI:28FD807* ID_OUI_FROM_DATABASE=University of York OUI:28FD800* ID_OUI_FROM_DATABASE=Millcode OUI:2C265FE* ID_OUI_FROM_DATABASE=Hysentel Technology Co., Ltd OUI:B8D8128* ID_OUI_FROM_DATABASE=Visual Productions BV OUI:B8D8122* ID_OUI_FROM_DATABASE=IPM Sales and service Co.,Ltd. OUI:74E14AD* ID_OUI_FROM_DATABASE=Knog Pty Ltd OUI:74E14A9* ID_OUI_FROM_DATABASE=Kanto Aircraft Instrument Co., Ltd. OUI:BC66414* ID_OUI_FROM_DATABASE=ARGUS-SPECTRUM OUI:58FCDBD* ID_OUI_FROM_DATABASE=XIAMEN LEELEN TECHNOLOGY CO.,LTD OUI:58FCDB8* ID_OUI_FROM_DATABASE=Shanghai Qianjin Electronic Equipment Co. Ltd OUI:1007231* ID_OUI_FROM_DATABASE=Beijing Assem Technology Co., ltd OUI:D02212B* ID_OUI_FROM_DATABASE=Schleifenbauer Holding BV OUI:D022128* ID_OUI_FROM_DATABASE=Shenzhen SIC Technology. Co., Ltd. OUI:100723B* ID_OUI_FROM_DATABASE=Fujian Quanzhou Dong Ang Electronics Co., Ltd. OUI:100723C* ID_OUI_FROM_DATABASE=SHENZHEN XINFA ELECTRONIC CO.,LTD OUI:1007235* ID_OUI_FROM_DATABASE=BEIJING SOOALL INFORMATION TECHNOLOGY CO.,LTD OUI:1007232* ID_OUI_FROM_DATABASE=Diginet Control Systems Pty Ltd OUI:E4956E6* ID_OUI_FROM_DATABASE=SHENZHEN JOYETECH ELECTRONICS CO., LTD. OUI:B8D812B* ID_OUI_FROM_DATABASE=Docobo Limited OUI:BC6641A* ID_OUI_FROM_DATABASE=EBlink OUI:E81863B* ID_OUI_FROM_DATABASE=Protek Electronics Group Co.,LTD OUI:74E14A5* ID_OUI_FROM_DATABASE=UTU Oy OUI:74E14A0* ID_OUI_FROM_DATABASE=Altenburger Electronic GmbH OUI:F40E11C* ID_OUI_FROM_DATABASE=NIHON MEGA LOGIC CO.,LTD. OUI:F40E118* ID_OUI_FROM_DATABASE=Zeepro Inc. OUI:F40E114* ID_OUI_FROM_DATABASE=Dayang Technology Development Inc. OUI:141FBAB* ID_OUI_FROM_DATABASE=Newings Communication CO., LTD. OUI:141FBA5* ID_OUI_FROM_DATABASE=Inttelix Brasil Tecnologia e Sistemas Ltda OUI:A43BFAC* ID_OUI_FROM_DATABASE=SHANGHAI XIETONG TECHNOLOGY INC. OUI:A43BFA4* ID_OUI_FROM_DATABASE=Maxon Australia OUI:141FBA1* ID_OUI_FROM_DATABASE=GloQuad OUI:7C70BC7* ID_OUI_FROM_DATABASE=Nomad Digital Ltd. OUI:7C70BCB* ID_OUI_FROM_DATABASE=Tohan Engineering Corporation OUI:A43BFA0* ID_OUI_FROM_DATABASE=Chengdu Territory Technology Co.,Ltd OUI:D07650D* ID_OUI_FROM_DATABASE=tecnotron elekronik gmbh OUI:D076508* ID_OUI_FROM_DATABASE=Accumulate AB OUI:D076504* ID_OUI_FROM_DATABASE=Private OUI:58FCDB3* ID_OUI_FROM_DATABASE=Custom Biogenic Systems OUI:B01F81B* ID_OUI_FROM_DATABASE=Rademacher Geraete-Elektronik GmbH OUI:BC34005* ID_OUI_FROM_DATABASE=NDSL, Inc. OUI:BC34003* ID_OUI_FROM_DATABASE=Altronix Corporation OUI:B01F817* ID_OUI_FROM_DATABASE=Aether Services, Inc. OUI:B01F813* ID_OUI_FROM_DATABASE=Sound United OUI:7C70BC3* ID_OUI_FROM_DATABASE=FLEXIM GmbH OUI:7419F89* ID_OUI_FROM_DATABASE=Princip a.s. OUI:7419F85* ID_OUI_FROM_DATABASE=Starcor Beijing Co.,Limited OUI:D076500* ID_OUI_FROM_DATABASE=CentrAlert, Inc. OUI:7419F8D* ID_OUI_FROM_DATABASE=Ansjer Electronics Co., Ltd. OUI:7419F81* ID_OUI_FROM_DATABASE=Trend-tech Technology Co., Limited OUI:B437D1F* ID_OUI_FROM_DATABASE=Private OUI:A44F29F* ID_OUI_FROM_DATABASE=Private OUI:78C2C0F* ID_OUI_FROM_DATABASE=Private OUI:0CEFAFF* ID_OUI_FROM_DATABASE=Private OUI:807B85F* ID_OUI_FROM_DATABASE=Private OUI:549A11F* ID_OUI_FROM_DATABASE=Private OUI:1C8774D* ID_OUI_FROM_DATABASE=CLABER SPA OUI:1C87746* ID_OUI_FROM_DATABASE=Schawbel Technologies LLC OUI:1C8774A* ID_OUI_FROM_DATABASE=Nebbiolo Technologies OUI:78CA830* ID_OUI_FROM_DATABASE=DAINCUBE OUI:38B8EB4* ID_OUI_FROM_DATABASE=UMLOGICS OUI:38B8EB9* ID_OUI_FROM_DATABASE=NHS Sistemas de Energia OUI:38FDFEA* ID_OUI_FROM_DATABASE=Management Service Corporation OUI:38FDFEB* ID_OUI_FROM_DATABASE=Swedish Adrenaline AB OUI:38FDFE4* ID_OUI_FROM_DATABASE=New Telecom Solutions LLC OUI:38FDFE9* ID_OUI_FROM_DATABASE=OOO Group of Industrial Technologies OUI:5CF2860* ID_OUI_FROM_DATABASE=Hangzhou Signwei Electronics Technology Co., Ltd OUI:5CF2863* ID_OUI_FROM_DATABASE=beijing your wonderful control system technology co.,ltd OUI:5CF2865* ID_OUI_FROM_DATABASE=EUROIMMUN Medizinische Labordiagnostika AG OUI:5CF2861* ID_OUI_FROM_DATABASE=iSon Tech OUI:7C477C6* ID_OUI_FROM_DATABASE=Zerosystem LTD.Co OUI:7C477CD* ID_OUI_FROM_DATABASE=Speedifi Inc OUI:986D353* ID_OUI_FROM_DATABASE=DH Mechatronic AG OUI:986D359* ID_OUI_FROM_DATABASE=Private OUI:986D355* ID_OUI_FROM_DATABASE=PDAHL OUI:E0B6F59* ID_OUI_FROM_DATABASE=Motiveprime Consumer Electronics Pvt Ltd OUI:E0B6F51* ID_OUI_FROM_DATABASE=START TODAY CO.,LTD. OUI:E043DB* ID_OUI_FROM_DATABASE=Shenzhen ViewAt Technology Co.,Ltd. OUI:2405F5* ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. OUI:2C3033* ID_OUI_FROM_DATABASE=NETGEAR OUI:847E40* ID_OUI_FROM_DATABASE=Texas Instruments OUI:78C5E5* ID_OUI_FROM_DATABASE=Texas Instruments OUI:D494A1* ID_OUI_FROM_DATABASE=Texas Instruments OUI:3C3300* ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD OUI:3CD92B* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:9C8E99* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:B499BA* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:1CC1DE* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:3C3556* ID_OUI_FROM_DATABASE=Cognitec Systems GmbH OUI:0050BA* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:00179A* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:1CBDB9* ID_OUI_FROM_DATABASE=D-Link International OUI:9094E4* ID_OUI_FROM_DATABASE=D-Link International OUI:28107B* ID_OUI_FROM_DATABASE=D-Link International OUI:1C7EE5* ID_OUI_FROM_DATABASE=D-Link International OUI:C4A81D* ID_OUI_FROM_DATABASE=D-Link International OUI:18622C* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:7C03D8* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:E8F1B0* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:00F871* ID_OUI_FROM_DATABASE=DGS Denmark A/S OUI:D8543A* ID_OUI_FROM_DATABASE=Texas Instruments OUI:7C8EE4* ID_OUI_FROM_DATABASE=Texas Instruments OUI:BC0DA5* ID_OUI_FROM_DATABASE=Texas Instruments OUI:90D7EB* ID_OUI_FROM_DATABASE=Texas Instruments OUI:001832* ID_OUI_FROM_DATABASE=Texas Instruments OUI:20BB76* ID_OUI_FROM_DATABASE=COL GIOVANNI PAOLO SpA OUI:2C228B* ID_OUI_FROM_DATABASE=CTR SRL OUI:348AAE* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:C83E99* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0017E5* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0017EC* ID_OUI_FROM_DATABASE=Texas Instruments OUI:FC528D* ID_OUI_FROM_DATABASE=Technicolor CH USA OUI:BCEC23* ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD OUI:8CE748* ID_OUI_FROM_DATABASE=Private OUI:F09CE9* ID_OUI_FROM_DATABASE=Aerohive Networks Inc. OUI:C413E2* ID_OUI_FROM_DATABASE=Aerohive Networks Inc. OUI:AC06C7* ID_OUI_FROM_DATABASE=ServerNet S.r.l. OUI:04BF6D* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:CC46D6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:48AD08* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:2CAB00* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:00E0FC* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:24DF6A* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:009ACD* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:0050C2* ID_OUI_FROM_DATABASE=IEEE Registration Authority OUI:00CDFE* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:38F23E* ID_OUI_FROM_DATABASE=Microsoft Mobile Oy OUI:58AC78* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:907F61* ID_OUI_FROM_DATABASE=Chicony Electronics Co., Ltd. OUI:001DCE* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001DD4* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001DCD* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:CCA462* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:903EAB* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:28BC18* ID_OUI_FROM_DATABASE=SourcingOverseas Co. Ltd OUI:807ABF* ID_OUI_FROM_DATABASE=HTC Corporation OUI:409F87* ID_OUI_FROM_DATABASE=Jide Technology (Hong Kong) Limited OUI:544E45* ID_OUI_FROM_DATABASE=Private OUI:3C5AB4* ID_OUI_FROM_DATABASE=Google, Inc. OUI:001A11* ID_OUI_FROM_DATABASE=Google, Inc. OUI:D83C69* ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. OUI:74AC5F* ID_OUI_FROM_DATABASE=Qiku Internet Network Scientific (Shenzhen) Co., Ltd. OUI:18AF61* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:BC83A7* ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD OUI:14CFE2* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:900DCB* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:207355* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:C83FB4* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:E0B70A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:78719C* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:D40598* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:946269* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:8C7F3B* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:D039B3* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0000C5* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:3C36E4* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:00ACE0* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:000347* ID_OUI_FROM_DATABASE=Intel Corporation OUI:001175* ID_OUI_FROM_DATABASE=Intel Corporation OUI:0013E8* ID_OUI_FROM_DATABASE=Intel Corporate OUI:001302* ID_OUI_FROM_DATABASE=Intel Corporate OUI:E4F89C* ID_OUI_FROM_DATABASE=Intel Corporate OUI:A402B9* ID_OUI_FROM_DATABASE=Intel Corporate OUI:4C3488* ID_OUI_FROM_DATABASE=Intel Corporate OUI:000D0B* ID_OUI_FROM_DATABASE=BUFFALO.INC OUI:000740* ID_OUI_FROM_DATABASE=BUFFALO.INC OUI:0024A5* ID_OUI_FROM_DATABASE=BUFFALO.INC OUI:DCFB02* ID_OUI_FROM_DATABASE=BUFFALO.INC OUI:F4CE46* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001CC4* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0025B3* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001871* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:000BCD* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:000E7F* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:000F20* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:00110A* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001321* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001635* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0017A4* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:000802* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:90E7C4* ID_OUI_FROM_DATABASE=HTC Corporation OUI:00265E* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:00234E* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:00234D* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:74A78E* ID_OUI_FROM_DATABASE=zte corporation OUI:D860B0* ID_OUI_FROM_DATABASE=bioMérieux Italia S.p.A. OUI:8038BC* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:D440F0* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:64A651* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:E8CD2D* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:ACE215* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:EC233D* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:78F5FD* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:80B686* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:10C61F* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:8853D4* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:0C37DC* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:BC7670* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:24DBAC* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:BC3AEA* ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD OUI:E8BBA8* ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD OUI:0021E8* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:006057* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:0007D8* ID_OUI_FROM_DATABASE=Hitron Technologies. Inc OUI:0012F2* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:001BED* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:002438* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:84742A* ID_OUI_FROM_DATABASE=zte corporation OUI:681AB2* ID_OUI_FROM_DATABASE=zte corporation OUI:001C25* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:E005C5* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:A0F3C1* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:8C210A* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:EC172F* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:EC888F* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:14CF92* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:645601* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:14CC20* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:BC4699* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:0C45BA* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:847778* ID_OUI_FROM_DATABASE=Cochlear Limited OUI:0453D5* ID_OUI_FROM_DATABASE=Sysorex Global Holdings OUI:CC4463* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:6C72E7* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0016CF* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:4437E6* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:F4B7E2* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:083E8E* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:485AB6* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:CCA223* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:E8088B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:60E701* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:000883* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:C4346B* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:8CDCD4* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:3464A9* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:D4C9EF* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:A45D36* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:A0D3C1* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:40A8F0* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:6C3BE5* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:082E5F* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:28924A* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:10604B* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:308D99* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0030C1* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:FC3FDB* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:4CA161* ID_OUI_FROM_DATABASE=Rain Bird Corporation OUI:7C6193* ID_OUI_FROM_DATABASE=HTC Corporation OUI:001217* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:000C41* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:000F66* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:44E08E* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:185933* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:E448C7* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:24767D* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:2CABA4* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:0002C7* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:04766E* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:006B8E* ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd. OUI:AC853D* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:74882A* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:78D752* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:E0247F* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:00464B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:707BE8* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:548998* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:0819A6* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:3CF808* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:B41513* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:283152* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:DCD2FC* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:0012D2* ID_OUI_FROM_DATABASE=Texas Instruments OUI:080028* ID_OUI_FROM_DATABASE=Texas Instruments OUI:6CECEB* ID_OUI_FROM_DATABASE=Texas Instruments OUI:84EB18* ID_OUI_FROM_DATABASE=Texas Instruments OUI:D4F513* ID_OUI_FROM_DATABASE=Texas Instruments OUI:A0F6FD* ID_OUI_FROM_DATABASE=Texas Instruments OUI:209148* ID_OUI_FROM_DATABASE=Texas Instruments OUI:D0B5C2* ID_OUI_FROM_DATABASE=Texas Instruments OUI:F8A45F* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:8CBEBE* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:640980* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:98FAE3* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:185936* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:9C99A0* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:0003DD* ID_OUI_FROM_DATABASE=Comark Interactive Solutions OUI:00107B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00906D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0090BF* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:005080* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:D0E54D* ID_OUI_FROM_DATABASE=Pace plc OUI:FC8E7E* ID_OUI_FROM_DATABASE=Pace plc OUI:B4F2E8* ID_OUI_FROM_DATABASE=Pace plc OUI:7085C6* ID_OUI_FROM_DATABASE=Pace plc OUI:00E018* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:000C6E* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:001BFC* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:001E8C* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:0015F2* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:002354* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:001FC6* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:60182E* ID_OUI_FROM_DATABASE=ShenZhen Protruly Electronic Ltd co. OUI:F4CFE2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:501CBF* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:285FDB* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:404D8E* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:781DBA* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:001E10* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:B0ADAA* ID_OUI_FROM_DATABASE=Avaya Inc OUI:10CDAE* ID_OUI_FROM_DATABASE=Avaya Inc OUI:50CD22* ID_OUI_FROM_DATABASE=Avaya Inc OUI:FCA841* ID_OUI_FROM_DATABASE=Avaya Inc OUI:3CB15B* ID_OUI_FROM_DATABASE=Avaya Inc OUI:C8F406* ID_OUI_FROM_DATABASE=Avaya Inc OUI:2CF4C5* ID_OUI_FROM_DATABASE=Avaya Inc OUI:7038EE* ID_OUI_FROM_DATABASE=Avaya Inc OUI:88F031* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:508789* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:381C1A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:F40F1B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:BC671C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:A0ECF9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:D46D50* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:1CE85D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:C47295* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:A0554F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:84B802* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:BCC493* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001947* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:0022CE* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:F02929* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:ECE1A9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:7C69F6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:C08C60* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:C0255C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:885A92* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E4C722* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:C07BBC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:005094* ID_OUI_FROM_DATABASE=Pace plc OUI:0090F2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00173B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00400B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:006009* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:006047* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0006C1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00E014* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00E01E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:ACF2C5* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:CCC760* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:087402* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:285AEB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:28F076* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:84285A* ID_OUI_FROM_DATABASE=Saffron Solutions Inc OUI:80A1AB* ID_OUI_FROM_DATABASE=Intellisis OUI:CC79CF* ID_OUI_FROM_DATABASE=Shenzhen RF-LINK Elec&Technology Co.Ltd OUI:44D884* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:EC852F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:286ABA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:705681* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:7CD1C3* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F0DCE2* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:B065BD* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A82066* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:BC6778* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:68967B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:848506* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:B4F0AB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:10DDB1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:04F7E4* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:34C059* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F0D1A9* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F82793* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:ACFDEC* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D0E140* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F832E4* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:8C7C92* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:7831C1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F437B7* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:54AE27* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:6476BA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:84B153* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:783A84* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:2CBE08* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:24E314* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0010FF* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:34BDC8* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:54A274* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:5897BD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:046C9D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:60FEC5* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:00A040* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:BC3BAF* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:786C1C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:041552* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:38484C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:701124* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C86F1D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:685B35* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:380F4A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:3010E4* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:04DB56* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:881FA1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:04E536* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:109ADD* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:40A6D9* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:7CF05F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A4B197* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0C74C2* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:403004* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:4860BC* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:50EAD6* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:28E02C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:60C547* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:7C11BE* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:003EE1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:68D93C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:2CF0EE* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:84788B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:6C94F8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:703EAC* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C01ADA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:34363B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C81EE7* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:9CFC01* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:000D93* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:001CB3* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:64B9E8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:34159E* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:58B035* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F0B479* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:141357* ID_OUI_FROM_DATABASE=ATP Electronics, Inc. OUI:F44B2A* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:3C8CF8* ID_OUI_FROM_DATABASE=TRENDnet, Inc. OUI:78D6B2* ID_OUI_FROM_DATABASE=Toshiba OUI:C04A09* ID_OUI_FROM_DATABASE=Zhejiang Everbright Communication Equip. Co,. Ltd OUI:F00D5C* ID_OUI_FROM_DATABASE=JinQianMao Technology Co.,Ltd. OUI:2C081C* ID_OUI_FROM_DATABASE=OVH OUI:30E090* ID_OUI_FROM_DATABASE=Linctronix Ltd, OUI:70BF3E* ID_OUI_FROM_DATABASE=Charles River Laboratories OUI:D848EE* ID_OUI_FROM_DATABASE=Hangzhou Xueji Technology Co., Ltd. OUI:EC9BF3* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD. OUI:88947E* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:88C242* ID_OUI_FROM_DATABASE=Poynt Co. OUI:E8343E* ID_OUI_FROM_DATABASE=Beijing Infosec Technologies Co., LTD. OUI:A8474A* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:C4ADF1* ID_OUI_FROM_DATABASE=GOPEACE Inc. OUI:58F496* ID_OUI_FROM_DATABASE=Source Chain OUI:80B709* ID_OUI_FROM_DATABASE=Viptela, Inc OUI:1C60DE* ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. OUI:741865* ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co.,Ltd OUI:0084ED* ID_OUI_FROM_DATABASE=Private OUI:DCDC07* ID_OUI_FROM_DATABASE=TRP Systems BV OUI:080A4E* ID_OUI_FROM_DATABASE=Planet Bingo® — 3rd Rock Gaming® OUI:0C1A10* ID_OUI_FROM_DATABASE=Acoustic Stream OUI:E4A387* ID_OUI_FROM_DATABASE=Control Solutions LLC OUI:DC82F6* ID_OUI_FROM_DATABASE=iPort OUI:C49E41* ID_OUI_FROM_DATABASE=G24 Power Limited OUI:D03E5C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:C8A9FC* ID_OUI_FROM_DATABASE=Goyoo Networks Inc. OUI:C49FF3* ID_OUI_FROM_DATABASE=Mciao Technologies, Inc. OUI:80739F* ID_OUI_FROM_DATABASE=KYOCERA Corporation OUI:7C2BE1* ID_OUI_FROM_DATABASE=Shenzhen Ferex Electrical Co.,Ltd OUI:30FFF6* ID_OUI_FROM_DATABASE=HangZhou KuoHeng Technology Co.,ltd OUI:5853C0* ID_OUI_FROM_DATABASE=Beijing Guang Runtong Technology Development Company co.,Ltd OUI:5031AD* ID_OUI_FROM_DATABASE=ABB Global Industries and Services Private Limited OUI:30A243* ID_OUI_FROM_DATABASE=Shenzhen Prifox Innovation Technology Co., Ltd. OUI:2CA539* ID_OUI_FROM_DATABASE=Parallel Wireless, Inc OUI:FC335F* ID_OUI_FROM_DATABASE=Polyera OUI:FCC233* ID_OUI_FROM_DATABASE=Private OUI:645D92* ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD OUI:A8C87F* ID_OUI_FROM_DATABASE=Roqos, Inc. OUI:C025A2* ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. OUI:7853F2* ID_OUI_FROM_DATABASE=ROXTON Ltd. OUI:384C90* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:ACBC32* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:94BBAE* ID_OUI_FROM_DATABASE=Husqvarna AB OUI:AC8995* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:F898B9* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:D40AA9* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:1C497B* ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. OUI:2CCF58* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:54FF82* ID_OUI_FROM_DATABASE=Davit Solution co. OUI:D445E8* ID_OUI_FROM_DATABASE=Jiangxi Hongpai Technology Co., Ltd. OUI:847973* ID_OUI_FROM_DATABASE=Shanghai Baud Data Communication Co.,Ltd. OUI:906F18* ID_OUI_FROM_DATABASE=Private OUI:881B99* ID_OUI_FROM_DATABASE=SHENZHEN XIN FEI JIA ELECTRONIC CO. LTD. OUI:681295* ID_OUI_FROM_DATABASE=Lupine Lighting Systems GmbH OUI:649A12* ID_OUI_FROM_DATABASE=P2 Mobile Technologies Limited OUI:E4C2D1* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:DC3CF6* ID_OUI_FROM_DATABASE=Atomic Rules LLC OUI:441CA8* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:C4047B* ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd OUI:F895C7* ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) OUI:3C3178* ID_OUI_FROM_DATABASE=Qolsys Inc. OUI:F4573E* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:083A5C* ID_OUI_FROM_DATABASE=Junilab, Inc. OUI:E8377A* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:4CAE31* ID_OUI_FROM_DATABASE=ShengHai Electronics (Shenzhen) Ltd OUI:C80E14* ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH OUI:F0D657* ID_OUI_FROM_DATABASE=ECHOSENS OUI:24693E* ID_OUI_FROM_DATABASE=innodisk Corporation OUI:E48D8C* ID_OUI_FROM_DATABASE=Routerboard.com OUI:C0DC6A* ID_OUI_FROM_DATABASE=Qingdao Eastsoft Communication Technology Co.,LTD OUI:6459F8* ID_OUI_FROM_DATABASE=Vodafone Omnitel B.V. OUI:082CB0* ID_OUI_FROM_DATABASE=Network Instruments OUI:F0AB54* ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD. OUI:485073* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:3CA31A* ID_OUI_FROM_DATABASE=Oilfind International LLC OUI:ACFD93* ID_OUI_FROM_DATABASE=Weifang GoerTek Electronics Co., Ltd. OUI:A424DD* ID_OUI_FROM_DATABASE=Cambrionix Ltd OUI:88A2D7* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:D89A34* ID_OUI_FROM_DATABASE=Beijing SHENQI Technology Co., Ltd. OUI:1CADD1* ID_OUI_FROM_DATABASE=Bosung Electronics Co., Ltd. OUI:24E5AA* ID_OUI_FROM_DATABASE=Philips Oral Healthcare, Inc. OUI:741F4A* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:88CBA5* ID_OUI_FROM_DATABASE=Suzhou Torchstar Intelligent Technology Co.,Ltd OUI:184F32* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:20F41B* ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD OUI:046169* ID_OUI_FROM_DATABASE=MEDIA GLOBAL LINKS CO., LTD. OUI:AC562C* ID_OUI_FROM_DATABASE=LAVA INTERNATIONAL(H.K) LIMITED OUI:3CCE15* ID_OUI_FROM_DATABASE=Mercedes-Benz USA, LLC OUI:84DF19* ID_OUI_FROM_DATABASE=Chuango Security Technology Corporation OUI:3C4711* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:245BF0* ID_OUI_FROM_DATABASE=Liteon, Inc. OUI:FCFEC2* ID_OUI_FROM_DATABASE=Invensys Controls UK Limited OUI:E8F2E2* ID_OUI_FROM_DATABASE=LG Innotek OUI:AC676F* ID_OUI_FROM_DATABASE=Electrocompaniet A.S. OUI:4CB82C* ID_OUI_FROM_DATABASE=Cambridge Mobile Telematics, Inc. OUI:F0224E* ID_OUI_FROM_DATABASE=Esan electronic co. OUI:B0411D* ID_OUI_FROM_DATABASE=ITTIM Technologies OUI:7CB25C* ID_OUI_FROM_DATABASE=Acacia Communications OUI:78EB39* ID_OUI_FROM_DATABASE=Instituto Nacional de Tecnología Industrial OUI:7CC95A* ID_OUI_FROM_DATABASE=EMC OUI:ECEED8* ID_OUI_FROM_DATABASE=ZTLX Network Technology Co.,Ltd OUI:F85B9C* ID_OUI_FROM_DATABASE=SB SYSTEMS Co.,Ltd OUI:7CA237* ID_OUI_FROM_DATABASE=King Slide Technology CO., LTD. OUI:300EE3* ID_OUI_FROM_DATABASE=Aquantia Corporation OUI:847303* ID_OUI_FROM_DATABASE=Letv Mobile and Intelligent Information Technology (Beijing) Corporation Ltd. OUI:B0495F* ID_OUI_FROM_DATABASE=OMRON HEALTHCARE Co., Ltd. OUI:BC6E64* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:8C8B83* ID_OUI_FROM_DATABASE=Texas Instruments OUI:90A210* ID_OUI_FROM_DATABASE=United Telecoms Ltd OUI:F44713* ID_OUI_FROM_DATABASE=Leading Public Performance Co., Ltd. OUI:D4522A* ID_OUI_FROM_DATABASE=TangoWiFi.com OUI:B0ECE1* ID_OUI_FROM_DATABASE=Private OUI:407FE0* ID_OUI_FROM_DATABASE=Glory Star Technics (ShenZhen) Limited OUI:BC5C4C* ID_OUI_FROM_DATABASE=ELECOM CO.,LTD. OUI:6C5940* ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. OUI:6CA75F* ID_OUI_FROM_DATABASE=zte corporation OUI:C8C50E* ID_OUI_FROM_DATABASE=Shenzhen Primestone Network Technologies.Co., Ltd. OUI:9CBEE0* ID_OUI_FROM_DATABASE=Biosoundlab Co., Ltd. OUI:5C5B35* ID_OUI_FROM_DATABASE=Mist Systems, Inc. OUI:E807BF* ID_OUI_FROM_DATABASE=SHENZHEN BOOMTECH INDUSTRY CO.,LTD OUI:E8162B* ID_OUI_FROM_DATABASE=IDEO Security Co., Ltd. OUI:709F2D* ID_OUI_FROM_DATABASE=zte corporation OUI:5C6B4F* ID_OUI_FROM_DATABASE=Private OUI:ECE2FD* ID_OUI_FROM_DATABASE=SKG Electric Group(Thailand) Co., Ltd. OUI:88E603* ID_OUI_FROM_DATABASE=Avotek corporation OUI:0C4885* ID_OUI_FROM_DATABASE=LG Electronics OUI:74E28C* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:94F19E* ID_OUI_FROM_DATABASE=HUIZHOU MAORONG INTELLIGENT TECHNOLOGY CO.,LTD OUI:C4924C* ID_OUI_FROM_DATABASE=KEISOKUKI CENTER CO.,LTD. OUI:E4F939* ID_OUI_FROM_DATABASE=Minxon Hotel Technology INC. OUI:38C70A* ID_OUI_FROM_DATABASE=WiFiSong OUI:60E6BC* ID_OUI_FROM_DATABASE=Sino-Telecom Technology Co.,Ltd. OUI:3CCB7C* ID_OUI_FROM_DATABASE=TCT mobile ltd OUI:F09FC2* ID_OUI_FROM_DATABASE=Ubiquiti Networks, Inc. OUI:44D9E7* ID_OUI_FROM_DATABASE=Ubiquiti Networks, Inc. OUI:F8042E* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD. OUI:1CA532* ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd OUI:643AB1* ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD OUI:486EFB* ID_OUI_FROM_DATABASE=Davit System Technology Co., Ltd. OUI:340A22* ID_OUI_FROM_DATABASE=TOP-ACCESS ELECTRONICS CO LTD OUI:B008BF* ID_OUI_FROM_DATABASE=Vital Connect, Inc. OUI:7CF854* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:485415* ID_OUI_FROM_DATABASE=NET RULES TECNOLOGIA EIRELI OUI:70C76F* ID_OUI_FROM_DATABASE=INNO S OUI:C48E8F* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:704E66* ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD OUI:1008B1* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:409B0D* ID_OUI_FROM_DATABASE=Shenzhen Yourf Kwan Industrial Co., Ltd OUI:C40880* ID_OUI_FROM_DATABASE=Shenzhen UTEPO Tech Co., Ltd. OUI:94C038* ID_OUI_FROM_DATABASE=Tallac Networks OUI:801967* ID_OUI_FROM_DATABASE=Shanghai Reallytek Information Technology Co.,Ltd OUI:6836B5* ID_OUI_FROM_DATABASE=DriveScale, Inc. OUI:2CF7F1* ID_OUI_FROM_DATABASE=Seeed Technology Inc. OUI:F88479* ID_OUI_FROM_DATABASE=Yaojin Technology(Shenzhen)Co.,Ltd OUI:4C48DA* ID_OUI_FROM_DATABASE=Beijing Autelan Technology Co.,Ltd OUI:90179B* ID_OUI_FROM_DATABASE=Nanomegas OUI:3077CB* ID_OUI_FROM_DATABASE=Maike Industry(Shenzhen)CO.,LTD OUI:88C9D0* ID_OUI_FROM_DATABASE=LG Electronics OUI:3428F0* ID_OUI_FROM_DATABASE=ATN International Limited OUI:EC3C5A* ID_OUI_FROM_DATABASE=SHEN ZHEN HENG SHENG HUI DIGITAL TECHNOLOGY CO.,LTD OUI:8C0551* ID_OUI_FROM_DATABASE=Koubachi AG OUI:D88466* ID_OUI_FROM_DATABASE=Extreme Networks OUI:E887A3* ID_OUI_FROM_DATABASE=Loxley Public Company Limited OUI:10FACE* ID_OUI_FROM_DATABASE=Reacheng Communication Technology Co.,Ltd OUI:D8CB8A* ID_OUI_FROM_DATABASE=Micro-Star INTL CO., LTD. OUI:A8D0E3* ID_OUI_FROM_DATABASE=Systech Electronics Ltd. OUI:8463D6* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:78B3B9* ID_OUI_FROM_DATABASE=ShangHai sunup lighting CO.,LTD OUI:586AB1* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:F4EE14* ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. OUI:186571* ID_OUI_FROM_DATABASE=Top Victory Electronics (Taiwan) Co., Ltd. OUI:F8BC41* ID_OUI_FROM_DATABASE=Rosslare Enterprises Limited OUI:8486F3* ID_OUI_FROM_DATABASE=Greenvity Communications OUI:205CFA* ID_OUI_FROM_DATABASE=Yangzhou ChangLian Network Technology Co,ltd. OUI:8C18D9* ID_OUI_FROM_DATABASE=Shenzhen RF Technology Co., Ltd OUI:6099D1* ID_OUI_FROM_DATABASE=Vuzix / Lenovo OUI:38B1DB* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:34F6D2* ID_OUI_FROM_DATABASE=Panasonic Taiwan Co.,Ltd. OUI:DC2F03* ID_OUI_FROM_DATABASE=Step forward Group Co., Ltd. OUI:582136* ID_OUI_FROM_DATABASE=KMB systems, s.r.o. OUI:00AEFA* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:5CAAFD* ID_OUI_FROM_DATABASE=Sonos, Inc. OUI:8CDF9D* ID_OUI_FROM_DATABASE=NEC Corporation OUI:F8E903* ID_OUI_FROM_DATABASE=D-Link International OUI:F0B052* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:6828F6* ID_OUI_FROM_DATABASE=Vubiq Networks, Inc. OUI:44356F* ID_OUI_FROM_DATABASE=Neterix OUI:742EFC* ID_OUI_FROM_DATABASE=DirectPacket Research, Inc, OUI:20C06D* ID_OUI_FROM_DATABASE=SHENZHEN SPACETEK TECHNOLOGY CO.,LTD OUI:3CB792* ID_OUI_FROM_DATABASE=Hitachi Maxell, Ltd., Optronics Division OUI:7491BD* ID_OUI_FROM_DATABASE=Four systems Co.,Ltd. OUI:D43266* ID_OUI_FROM_DATABASE=Fike Corporation OUI:948E89* ID_OUI_FROM_DATABASE=INDUSTRIAS UNIDAS SA DE CV OUI:9405B6* ID_OUI_FROM_DATABASE=Liling FullRiver Electronics & Technology Ltd OUI:382C4A* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:74547D* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:D48F33* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:D84A87* ID_OUI_FROM_DATABASE=OI ELECTRIC CO.,LTD OUI:1CA2B1* ID_OUI_FROM_DATABASE=ruwido austria gmbh OUI:945493* ID_OUI_FROM_DATABASE=Rigado, LLC OUI:34B7FD* ID_OUI_FROM_DATABASE=Guangzhou Younghead Electronic Technology Co.,Ltd OUI:384B76* ID_OUI_FROM_DATABASE=AIRTAME ApS OUI:1C5216* ID_OUI_FROM_DATABASE=DONGGUAN HELE ELECTRONICS CO., LTD OUI:34029B* ID_OUI_FROM_DATABASE=CloudBerry Technologies Private Limited OUI:70AF25* ID_OUI_FROM_DATABASE=Nishiyama Industry Co.,LTD. OUI:B47C29* ID_OUI_FROM_DATABASE=Shenzhen Guzidi Technology Co.,Ltd OUI:2C1A31* ID_OUI_FROM_DATABASE=Electronics Company Limited OUI:6C198F* ID_OUI_FROM_DATABASE=D-Link International OUI:60C1CB* ID_OUI_FROM_DATABASE=Fujian Great Power PLC Equipment Co.,Ltd OUI:686E48* ID_OUI_FROM_DATABASE=Prophet Electronic Technology Corp.,Ltd OUI:30F7D7* ID_OUI_FROM_DATABASE=Thread Technology Co., Ltd OUI:3808FD* ID_OUI_FROM_DATABASE=Silca Spa OUI:7C2587* ID_OUI_FROM_DATABASE=chaowifi.com OUI:2012D5* ID_OUI_FROM_DATABASE=Scientech Materials Corporation OUI:DC3979* ID_OUI_FROM_DATABASE=Skyport Systems OUI:EC1D7F* ID_OUI_FROM_DATABASE=zte corporation OUI:AC11D3* ID_OUI_FROM_DATABASE=Suzhou HOTEK Video Technology Co. Ltd OUI:304225* ID_OUI_FROM_DATABASE=BURG-WÄCHTER KG OUI:1C4840* ID_OUI_FROM_DATABASE=IMS Messsysteme GmbH OUI:F42853* ID_OUI_FROM_DATABASE=Zioncom Electronics (Shenzhen) Ltd. OUI:3C46D8* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:6C0273* ID_OUI_FROM_DATABASE=Shenzhen Jin Yun Video Equipment Co., Ltd. OUI:2CFAA2* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:F0761C* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:F42833* ID_OUI_FROM_DATABASE=MMPC Inc. OUI:244F1D* ID_OUI_FROM_DATABASE=iRule LLC OUI:BC9CC5* ID_OUI_FROM_DATABASE=Beijing Huafei Technology Co., Ltd. OUI:505065* ID_OUI_FROM_DATABASE=TAKT Corporation OUI:D00AAB* ID_OUI_FROM_DATABASE=Yokogawa Digital Computer Corporation OUI:A4A4D3* ID_OUI_FROM_DATABASE=Bluebank Communication Technology Co.Ltd OUI:74F413* ID_OUI_FROM_DATABASE=Maxwell Forest OUI:34F0CA* ID_OUI_FROM_DATABASE=Shenzhen Linghangyuan Digital Technology Co.,Ltd. OUI:84183A* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:30B5F1* ID_OUI_FROM_DATABASE=Aitexin Technology Co., Ltd OUI:882950* ID_OUI_FROM_DATABASE=Dalian Netmoon Tech Develop Co.,Ltd OUI:08CD9B* ID_OUI_FROM_DATABASE=samtec automotive electronics & software GmbH OUI:28FCF6* ID_OUI_FROM_DATABASE=Shenzhen Xin KingBrand enterprises Co.,Ltd OUI:2C54CF* ID_OUI_FROM_DATABASE=LG Electronics OUI:4C26E7* ID_OUI_FROM_DATABASE=Welgate Co., Ltd. OUI:94D60E* ID_OUI_FROM_DATABASE=shenzhen yunmao information technologies co., ltd OUI:7C6AC3* ID_OUI_FROM_DATABASE=GatesAir, Inc OUI:D8E56D* ID_OUI_FROM_DATABASE=TCT Mobile Limited OUI:3CCD5A* ID_OUI_FROM_DATABASE=Technische Alternative GmbH OUI:604826* ID_OUI_FROM_DATABASE=Newbridge Technologies Int. Ltd. OUI:24D13F* ID_OUI_FROM_DATABASE=MEXUS CO.,LTD OUI:702C1F* ID_OUI_FROM_DATABASE=Wisol OUI:9CBD9D* ID_OUI_FROM_DATABASE=SkyDisk, Inc. OUI:74C621* ID_OUI_FROM_DATABASE=Zhejiang Hite Renewable Energy Co.,LTD OUI:44C306* ID_OUI_FROM_DATABASE=SIFROM Inc. OUI:54A31B* ID_OUI_FROM_DATABASE=Shenzhen Linkworld Technology Co,.LTD OUI:5CE7BF* ID_OUI_FROM_DATABASE=New Singularity International Technical Development Co.,Ltd OUI:1CEEE8* ID_OUI_FROM_DATABASE=Ilshin Elecom OUI:6C641A* ID_OUI_FROM_DATABASE=Penguin Computing OUI:E036E3* ID_OUI_FROM_DATABASE=Stage One International Co., Ltd. OUI:34DE34* ID_OUI_FROM_DATABASE=zte corporation OUI:34466F* ID_OUI_FROM_DATABASE=HiTEM Engineering OUI:2C39C1* ID_OUI_FROM_DATABASE=Ciena Corporation OUI:6C2C06* ID_OUI_FROM_DATABASE=OOO NPP Systemotechnika-NN OUI:54EE75* ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd. OUI:60812B* ID_OUI_FROM_DATABASE=Custom Control Concepts OUI:F86601* ID_OUI_FROM_DATABASE=Suzhou Chi-tek information technology Co., Ltd OUI:FC4AE9* ID_OUI_FROM_DATABASE=Castlenet Technology Inc. OUI:34E42A* ID_OUI_FROM_DATABASE=Automatic Bar Controls Inc. OUI:B87CF2* ID_OUI_FROM_DATABASE=Aerohive Networks Inc. OUI:20A787* ID_OUI_FROM_DATABASE=Bointec Taiwan Corporation Limited OUI:6CAAB3* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:A481EE* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:54C80F* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:D42122* ID_OUI_FROM_DATABASE=Sercomm Corporation OUI:EC1766* ID_OUI_FROM_DATABASE=Research Centre Module OUI:7CFF62* ID_OUI_FROM_DATABASE=Huizhou Super Electron Technology Co.,Ltd. OUI:A0D12A* ID_OUI_FROM_DATABASE=AXPRO Technology Inc. OUI:30C750* ID_OUI_FROM_DATABASE=MIC Technology Group OUI:442938* ID_OUI_FROM_DATABASE=NietZsche enterprise Co.Ltd. OUI:D881CE* ID_OUI_FROM_DATABASE=AHN INC. OUI:E0D31A* ID_OUI_FROM_DATABASE=EQUES Technology Co., Limited OUI:9C3EAA* ID_OUI_FROM_DATABASE=EnvyLogic Co.,Ltd. OUI:909864* ID_OUI_FROM_DATABASE=Impex-Sat GmbH&Co KG OUI:DCE578* ID_OUI_FROM_DATABASE=Experimental Factory of Scientific Engineering and Special Design Department OUI:949F3F* ID_OUI_FROM_DATABASE=Optek Digital Technology company limited OUI:987770* ID_OUI_FROM_DATABASE=Pep Digital Technology (Guangzhou) Co., Ltd OUI:4411C2* ID_OUI_FROM_DATABASE=Telegartner Karl Gartner GmbH OUI:9451BF* ID_OUI_FROM_DATABASE=Hyundai ESG OUI:4C7F62* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:841766* ID_OUI_FROM_DATABASE=Weifang GoerTek Electronics Co., Ltd OUI:F03FF8* ID_OUI_FROM_DATABASE=R L Drake OUI:B0C554* ID_OUI_FROM_DATABASE=D-Link International OUI:54D163* ID_OUI_FROM_DATABASE=MAX-TECH,INC OUI:E41218* ID_OUI_FROM_DATABASE=ShenZhen Rapoo Technology Co., Ltd. OUI:2C8A72* ID_OUI_FROM_DATABASE=HTC Corporation OUI:4486C1* ID_OUI_FROM_DATABASE=Siemens Low Voltage & Products OUI:C83168* ID_OUI_FROM_DATABASE=eZEX corporation OUI:843838* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD. OUI:F84A73* ID_OUI_FROM_DATABASE=EUMTECH CO., LTD OUI:880F10* ID_OUI_FROM_DATABASE=Huami Information Technology Co.,Ltd. OUI:24336C* ID_OUI_FROM_DATABASE=Private OUI:C46BB4* ID_OUI_FROM_DATABASE=myIDkey OUI:ECE512* ID_OUI_FROM_DATABASE=tado GmbH OUI:30918F* ID_OUI_FROM_DATABASE=Technicolor OUI:FC09F6* ID_OUI_FROM_DATABASE=GUANGDONG TONZE ELECTRIC CO.,LTD OUI:687848* ID_OUI_FROM_DATABASE=Westunitis Co., Ltd. OUI:A8B9B3* ID_OUI_FROM_DATABASE=ESSYS OUI:64B370* ID_OUI_FROM_DATABASE=PowerComm Solutions LLC OUI:D86595* ID_OUI_FROM_DATABASE=Toy's Myth Inc. OUI:C45006* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:D8DD5F* ID_OUI_FROM_DATABASE=BALMUDA Inc. OUI:88D962* ID_OUI_FROM_DATABASE=Canopus Systems US LLC OUI:24C848* ID_OUI_FROM_DATABASE=mywerk system GmbH OUI:805719* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B0DF3A* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:2C18AE* ID_OUI_FROM_DATABASE=Trend Electronics Co., Ltd. OUI:E097F2* ID_OUI_FROM_DATABASE=Atomax Inc. OUI:90F3B7* ID_OUI_FROM_DATABASE=Kirisun Communications Co., Ltd. OUI:DCAD9E* ID_OUI_FROM_DATABASE=GreenPriz OUI:B4827B* ID_OUI_FROM_DATABASE=AKG Acoustics GmbH OUI:908C44* ID_OUI_FROM_DATABASE=H.K ZONGMU TECHNOLOGY CO., LTD. OUI:0C473D* ID_OUI_FROM_DATABASE=Hitron Technologies. Inc OUI:4C5E0C* ID_OUI_FROM_DATABASE=Routerboard.com OUI:9CF8DB* ID_OUI_FROM_DATABASE=shenzhen eyunmei technology co,.ltd OUI:644214* ID_OUI_FROM_DATABASE=Swisscom Energy Solutions AG OUI:00E3B2* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:30D6C9* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:107BEF* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:8CCDA2* ID_OUI_FROM_DATABASE=ACTP, Inc. OUI:CC720F* ID_OUI_FROM_DATABASE=Viscount Systems Inc. OUI:906717* ID_OUI_FROM_DATABASE=Alphion India Private Limited OUI:24050F* ID_OUI_FROM_DATABASE=MTN Electronic Co. Ltd OUI:40B6B1* ID_OUI_FROM_DATABASE=SUNGSAM CO,.Ltd OUI:98FF6A* ID_OUI_FROM_DATABASE=OTEC(Shanghai)Technology Co.,Ltd. OUI:AC6BAC* ID_OUI_FROM_DATABASE=Jenny Science AG OUI:707C18* ID_OUI_FROM_DATABASE=ADATA Technology Co., Ltd OUI:FC4B1C* ID_OUI_FROM_DATABASE=INTERSENSOR S.R.L. OUI:1879A2* ID_OUI_FROM_DATABASE=GMJ ELECTRIC LIMITED OUI:E0C86A* ID_OUI_FROM_DATABASE=SHENZHEN TW-SCIE Co., Ltd OUI:80BAE6* ID_OUI_FROM_DATABASE=Neets OUI:3C18A0* ID_OUI_FROM_DATABASE=Luxshare Precision Industry Co.,Ltd. OUI:4CB81C* ID_OUI_FROM_DATABASE=SAM Electronics GmbH OUI:2C3731* ID_OUI_FROM_DATABASE=ShenZhen Yifang Digital Technology Co.,LTD OUI:041A04* ID_OUI_FROM_DATABASE=WaveIP OUI:50206B* ID_OUI_FROM_DATABASE=Emerson Climate Technologies Transportation Solutions OUI:C8EE75* ID_OUI_FROM_DATABASE=Pishion International Co. Ltd OUI:CC3429* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:407496* ID_OUI_FROM_DATABASE=aFUN TECHNOLOGY INC. OUI:18C8E7* ID_OUI_FROM_DATABASE=Shenzhen Hualistone Technology Co.,Ltd OUI:3CF748* ID_OUI_FROM_DATABASE=Shenzhen Linsn Technology Development Co.,Ltd OUI:9C039E* ID_OUI_FROM_DATABASE=Beijing Winchannel Software Technology Co., Ltd OUI:F8A963* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:48A2B7* ID_OUI_FROM_DATABASE=Kodofon JSC OUI:443C9C* ID_OUI_FROM_DATABASE=Pintsch Tiefenbach GmbH OUI:F81CE5* ID_OUI_FROM_DATABASE=Telefonbau Behnke GmbH OUI:BC2D98* ID_OUI_FROM_DATABASE=ThinGlobal LLC OUI:7C72E4* ID_OUI_FROM_DATABASE=Unikey Technologies OUI:8048A5* ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOM CO.,LTD OUI:181BEB* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:CC7498* ID_OUI_FROM_DATABASE=Filmetrics Inc. OUI:7C6AB3* ID_OUI_FROM_DATABASE=IBC TECHNOLOGIES INC. OUI:309BAD* ID_OUI_FROM_DATABASE=BBK Electronics Corp., Ltd., OUI:F0321A* ID_OUI_FROM_DATABASE=Mita-Teknik A/S OUI:4CD7B6* ID_OUI_FROM_DATABASE=Helmer Scientific OUI:746F3D* ID_OUI_FROM_DATABASE=Contec GmbH OUI:483D32* ID_OUI_FROM_DATABASE=Syscor Controls & Automation OUI:9031CD* ID_OUI_FROM_DATABASE=Onyx Healthcare Inc. OUI:A0E453* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:404A18* ID_OUI_FROM_DATABASE=Addrek Smart Solutions OUI:C4C0AE* ID_OUI_FROM_DATABASE=MIDORI ELECTRONIC CO., LTD. OUI:08FD0E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:78A873* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:54880E* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD. OUI:90837A* ID_OUI_FROM_DATABASE=General Electric Water & Process Technologies OUI:089758* ID_OUI_FROM_DATABASE=Shenzhen Strong Rising Electronics Co.,Ltd DongGuan Subsidiary OUI:B424E7* ID_OUI_FROM_DATABASE=Codetek Technology Co.,Ltd OUI:44EE30* ID_OUI_FROM_DATABASE=Budelmann Elektronik GmbH OUI:38DBBB* ID_OUI_FROM_DATABASE=Sunbow Telecom Co., Ltd. OUI:2493CA* ID_OUI_FROM_DATABASE=Voxtronic Technology Computer-Systeme GmbH OUI:688AB5* ID_OUI_FROM_DATABASE=EDP Servicos OUI:407A80* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:F06130* ID_OUI_FROM_DATABASE=Advantage Pharmacy Services, LLC OUI:D481CA* ID_OUI_FROM_DATABASE=iDevices, LLC OUI:B898F7* ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co,Ltd.ShenZhen OUI:C0F1C4* ID_OUI_FROM_DATABASE=Pacidal Corporation Ltd. OUI:D858D7* ID_OUI_FROM_DATABASE=CZ.NIC, z.s.p.o. OUI:BC307D* ID_OUI_FROM_DATABASE=Wistron Neweb Corp. OUI:10B713* ID_OUI_FROM_DATABASE=Private OUI:E8E770* ID_OUI_FROM_DATABASE=Warp9 Tech Design, Inc. OUI:78CA5E* ID_OUI_FROM_DATABASE=ELNO OUI:98FFD0* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:50A054* ID_OUI_FROM_DATABASE=Actineon OUI:48EE86* ID_OUI_FROM_DATABASE=UTStarcom (China) Co.,Ltd OUI:5056A8* ID_OUI_FROM_DATABASE=Jolla Ltd OUI:D09D0A* ID_OUI_FROM_DATABASE=LINKCOM OUI:C81479* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:54FB58* ID_OUI_FROM_DATABASE=WISEWARE, Lda OUI:A42940* ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd OUI:C0A0BB* ID_OUI_FROM_DATABASE=D-Link International OUI:28A1EB* ID_OUI_FROM_DATABASE=ETEK TECHNOLOGY (SHENZHEN) CO.,LTD OUI:4CCBF5* ID_OUI_FROM_DATABASE=zte corporation OUI:F0F5AE* ID_OUI_FROM_DATABASE=Adaptrum Inc. OUI:F42896* ID_OUI_FROM_DATABASE=SPECTO PAINEIS ELETRONICOS LTDA OUI:1C7B21* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:BC9680* ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd OUI:9C2840* ID_OUI_FROM_DATABASE=Discovery Technology,LTD.. OUI:F89FB8* ID_OUI_FROM_DATABASE=YAZAKI Energy System Corporation OUI:F037A1* ID_OUI_FROM_DATABASE=Huike Electronics (SHENZHEN) CO., LTD. OUI:6CD1B0* ID_OUI_FROM_DATABASE=WING SING ELECTRONICS HONG KONG LIMITED OUI:A4F522* ID_OUI_FROM_DATABASE=CHOFU SEISAKUSHO CO.,LTD OUI:7CE56B* ID_OUI_FROM_DATABASE=ESEN Optoelectronics Technology Co.,Ltd. OUI:CC4703* ID_OUI_FROM_DATABASE=Intercon Systems Co., Ltd. OUI:5C3327* ID_OUI_FROM_DATABASE=Spazio Italia srl OUI:BC8CCD* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co.,LTD. OUI:F85BC9* ID_OUI_FROM_DATABASE=M-Cube Spa OUI:8005DF* ID_OUI_FROM_DATABASE=Montage Technology Group Limited OUI:78E8B6* ID_OUI_FROM_DATABASE=zte corporation OUI:041B94* ID_OUI_FROM_DATABASE=Host Mobility AB OUI:CC2A80* ID_OUI_FROM_DATABASE=Micro-Biz intelligence solutions Co.,Ltd OUI:3859F8* ID_OUI_FROM_DATABASE=MindMade Sp. z o.o. OUI:F0728C* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:5C026A* ID_OUI_FROM_DATABASE=Applied Vision Corporation OUI:94350A* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:7CBD06* ID_OUI_FROM_DATABASE=AE REFUsol OUI:94BA56* ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd. OUI:2894AF* ID_OUI_FROM_DATABASE=Samhwa Telecom OUI:740EDB* ID_OUI_FROM_DATABASE=Optowiz Co., Ltd OUI:00A2FF* ID_OUI_FROM_DATABASE=abatec group AG OUI:D095C7* ID_OUI_FROM_DATABASE=Pantech Co., Ltd. OUI:D02C45* ID_OUI_FROM_DATABASE=littleBits Electronics, Inc. OUI:5027C7* ID_OUI_FROM_DATABASE=TECHNART Co.,Ltd OUI:248000* ID_OUI_FROM_DATABASE=Westcontrol AS OUI:F84A7F* ID_OUI_FROM_DATABASE=Innometriks Inc OUI:58639A* ID_OUI_FROM_DATABASE=TPL SYSTEMES OUI:0C9B13* ID_OUI_FROM_DATABASE=Shanghai Magic Mobile Telecommunication Co.Ltd. OUI:3C15EA* ID_OUI_FROM_DATABASE=TESCOM CO., LTD. OUI:B4CCE9* ID_OUI_FROM_DATABASE=PROSYST OUI:34A3BF* ID_OUI_FROM_DATABASE=Terewave. Inc. OUI:B0CE18* ID_OUI_FROM_DATABASE=Zhejiang shenghui lighting co.,Ltd OUI:503CC4* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:286D97* ID_OUI_FROM_DATABASE=SAMJIN Co., Ltd. OUI:ACE42E* ID_OUI_FROM_DATABASE=SK hynix OUI:08EF3B* ID_OUI_FROM_DATABASE=MCS Logic Inc. OUI:806C8B* ID_OUI_FROM_DATABASE=KAESER KOMPRESSOREN AG OUI:048C03* ID_OUI_FROM_DATABASE=ThinPAD Technology (Shenzhen)CO.,LTD OUI:84E629* ID_OUI_FROM_DATABASE=Bluwan SA OUI:34CD6D* ID_OUI_FROM_DATABASE=CommSky Technologies OUI:C47F51* ID_OUI_FROM_DATABASE=Inventek Systems OUI:E8D4E0* ID_OUI_FROM_DATABASE=Beijing BenyWave Technology Co., Ltd. OUI:3889DC* ID_OUI_FROM_DATABASE=Opticon Sensors Europe B.V. OUI:88124E* ID_OUI_FROM_DATABASE=Qualcomm Atheros OUI:681D64* ID_OUI_FROM_DATABASE=Sunwave Communications Co., Ltd OUI:F4CD90* ID_OUI_FROM_DATABASE=Vispiron Rotec GmbH OUI:400E85* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co.,LTD. OUI:E438F2* ID_OUI_FROM_DATABASE=Advantage Controls OUI:24C9A1* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:C8F386* ID_OUI_FROM_DATABASE=Shenzhen Xiaoniao Technology Co.,Ltd OUI:E8CE06* ID_OUI_FROM_DATABASE=SkyHawke Technologies, LLC. OUI:B0808C* ID_OUI_FROM_DATABASE=Laser Light Engines OUI:C419EC* ID_OUI_FROM_DATABASE=Qualisys AB OUI:981094* ID_OUI_FROM_DATABASE=Shenzhen Vsun communication technology Co.,ltd OUI:082719* ID_OUI_FROM_DATABASE=APS systems/electronic AG OUI:D4AC4E* ID_OUI_FROM_DATABASE=BODi rS, LLC OUI:B03850* ID_OUI_FROM_DATABASE=Nanjing CAS-ZDC IOT SYSTEM CO.,LTD OUI:C0DA74* ID_OUI_FROM_DATABASE=Hangzhou Sunyard Technology Co., Ltd. OUI:34A843* ID_OUI_FROM_DATABASE=KYOCERA Display Corporation OUI:6C5779* ID_OUI_FROM_DATABASE=Aclima, Inc. OUI:40BD9E* ID_OUI_FROM_DATABASE=Physio-Control, Inc OUI:BC79AD* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:581CBD* ID_OUI_FROM_DATABASE=Affinegy OUI:649C81* ID_OUI_FROM_DATABASE=Qualcomm iSkoot, Inc. OUI:F82BC8* ID_OUI_FROM_DATABASE=Jiangsu Switter Co., Ltd OUI:60C397* ID_OUI_FROM_DATABASE=2Wire Inc OUI:3065EC* ID_OUI_FROM_DATABASE=Wistron (ChongQing) OUI:5CA3EB* ID_OUI_FROM_DATABASE=Lokel s.r.o. OUI:04DF69* ID_OUI_FROM_DATABASE=Car Connectivity Consortium OUI:28DB81* ID_OUI_FROM_DATABASE=Shanghai Guao Electronic Technology Co., Ltd OUI:9CB793* ID_OUI_FROM_DATABASE=Creatcomm Technology Inc. OUI:C4438F* ID_OUI_FROM_DATABASE=LG Electronics OUI:A0B100* ID_OUI_FROM_DATABASE=ShenZhen Cando Electronics Co.,Ltd OUI:40560C* ID_OUI_FROM_DATABASE=In Home Displays Ltd OUI:9436E0* ID_OUI_FROM_DATABASE=Sichuan Bihong Broadcast & Television New Technologies Co.,Ltd OUI:D4D50D* ID_OUI_FROM_DATABASE=Southwest Microwave, Inc OUI:B8CD93* ID_OUI_FROM_DATABASE=Penetek, Inc OUI:D8FEE3* ID_OUI_FROM_DATABASE=D-Link International OUI:F8516D* ID_OUI_FROM_DATABASE=Denwa Technology Corp. OUI:1078CE* ID_OUI_FROM_DATABASE=Hanvit SI, Inc. OUI:D8DA52* ID_OUI_FROM_DATABASE=APATOR S.A. OUI:107A86* ID_OUI_FROM_DATABASE=U&U ENGINEERING INC. OUI:980D2E* ID_OUI_FROM_DATABASE=HTC Corporation OUI:842F75* ID_OUI_FROM_DATABASE=Innokas Group OUI:D4BF7F* ID_OUI_FROM_DATABASE=UPVEL OUI:5061D6* ID_OUI_FROM_DATABASE=Indu-Sol GmbH OUI:68EC62* ID_OUI_FROM_DATABASE=YODO Technology Corp. Ltd. OUI:10D542* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:A0821F* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:F07F0C* ID_OUI_FROM_DATABASE=Leopold Kostal GmbH &Co. KG OUI:5C22C4* ID_OUI_FROM_DATABASE=DAE EUN ELETRONICS CO., LTD OUI:08482C* ID_OUI_FROM_DATABASE=Raycore Taiwan Co., LTD. OUI:F4B381* ID_OUI_FROM_DATABASE=WindowMaster A/S OUI:74F102* ID_OUI_FROM_DATABASE=Beijing HCHCOM Technology Co., Ltd OUI:080EA8* ID_OUI_FROM_DATABASE=Velex s.r.l. OUI:041BBA* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:5C3C27* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:0086A0* ID_OUI_FROM_DATABASE=Private OUI:60FE1E* ID_OUI_FROM_DATABASE=China Palms Telecom.Ltd OUI:841E26* ID_OUI_FROM_DATABASE=KERNEL-I Co.,LTD OUI:349D90* ID_OUI_FROM_DATABASE=Heinzmann GmbH & CO. KG OUI:D4016D* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:FC1186* ID_OUI_FROM_DATABASE=Logic3 plc OUI:50CD32* ID_OUI_FROM_DATABASE=NanJing Chaoran Science & Technology Co.,Ltd. OUI:683EEC* ID_OUI_FROM_DATABASE=ERECA OUI:44619C* ID_OUI_FROM_DATABASE=FONsystem co. ltd. OUI:BCBAE1* ID_OUI_FROM_DATABASE=AREC Inc. OUI:18FA6F* ID_OUI_FROM_DATABASE=ISC applied systems corp OUI:9C9726* ID_OUI_FROM_DATABASE=Technicolor OUI:880905* ID_OUI_FROM_DATABASE=MTMCommunications OUI:C42628* ID_OUI_FROM_DATABASE=Airo Wireless OUI:745F00* ID_OUI_FROM_DATABASE=Samsung Semiconductor Inc. OUI:541FD5* ID_OUI_FROM_DATABASE=Advantage Electronics OUI:90FF79* ID_OUI_FROM_DATABASE=Metro Ethernet Forum OUI:E08177* ID_OUI_FROM_DATABASE=GreenBytes, Inc. OUI:48F230* ID_OUI_FROM_DATABASE=Ubizcore Co.,LTD OUI:B0C95B* ID_OUI_FROM_DATABASE=Beijing Symtech CO.,LTD OUI:881544* ID_OUI_FROM_DATABASE=Meraki, Inc. OUI:DCA989* ID_OUI_FROM_DATABASE=MACANDC OUI:C05E6F* ID_OUI_FROM_DATABASE=V. Stonkaus firma Kodinis Raktas OUI:6CD146* ID_OUI_FROM_DATABASE=Smartek d.o.o. OUI:E0C2B7* ID_OUI_FROM_DATABASE=Masimo Corporation OUI:F82EDB* ID_OUI_FROM_DATABASE=RTW GmbH & Co. KG OUI:60A44C* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:045FA7* ID_OUI_FROM_DATABASE=Shenzhen Yichen Technology Development Co.,LTD OUI:983F9F* ID_OUI_FROM_DATABASE=China SSJ (Suzhou) Network Technology Inc. OUI:F02329* ID_OUI_FROM_DATABASE=SHOWA DENKI CO.,LTD. OUI:6499A0* ID_OUI_FROM_DATABASE=AG Elektronik AB OUI:A80180* ID_OUI_FROM_DATABASE=IMAGO Technologies GmbH OUI:044CEF* ID_OUI_FROM_DATABASE=Fujian Sanao Technology Co.,Ltd OUI:DC1DD4* ID_OUI_FROM_DATABASE=Microstep-MIS spol. s r.o. OUI:E01877* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:149448* ID_OUI_FROM_DATABASE=BLU CASTLE S.A. OUI:40516C* ID_OUI_FROM_DATABASE=Grandex International Corporation OUI:D0D471* ID_OUI_FROM_DATABASE=MVTECH co., Ltd OUI:34ADE4* ID_OUI_FROM_DATABASE=Shanghai Chint Power Systems Co., Ltd. OUI:1853E0* ID_OUI_FROM_DATABASE=Hanyang Digitech Co.Ltd OUI:C4E032* ID_OUI_FROM_DATABASE=IEEE 1904.1 Working Group OUI:ACDBDA* ID_OUI_FROM_DATABASE=Shenzhen Geniatech Inc, Ltd OUI:A42C08* ID_OUI_FROM_DATABASE=Masterwork Automodules OUI:60B185* ID_OUI_FROM_DATABASE=ATH system OUI:504F94* ID_OUI_FROM_DATABASE=Loxone Electronics GmbH OUI:88329B* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co.,LTD. OUI:8C078C* ID_OUI_FROM_DATABASE=FLOW DATA INC OUI:8887DD* ID_OUI_FROM_DATABASE=DarbeeVision Inc. OUI:807B1E* ID_OUI_FROM_DATABASE=Corsair Components OUI:A0E25A* ID_OUI_FROM_DATABASE=Amicus SK, s.r.o. OUI:F87B62* ID_OUI_FROM_DATABASE=FASTWEL INTERNATIONAL CO., LTD. Taiwan Branch OUI:B49842* ID_OUI_FROM_DATABASE=zte corporation OUI:9C9C1D* ID_OUI_FROM_DATABASE=Starkey Labs Inc. OUI:90CC24* ID_OUI_FROM_DATABASE=Synaptics, Inc OUI:AC1702* ID_OUI_FROM_DATABASE=Fibar Group sp. z o.o. OUI:7898FD* ID_OUI_FROM_DATABASE=Q9 Networks Inc. OUI:3C57D5* ID_OUI_FROM_DATABASE=FiveCo OUI:4C2258* ID_OUI_FROM_DATABASE=cozybit, Inc. OUI:10EA59* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:34FA40* ID_OUI_FROM_DATABASE=Guangzhou Robustel Technologies Co., Limited OUI:181725* ID_OUI_FROM_DATABASE=Cameo Communications, Inc. OUI:E82E24* ID_OUI_FROM_DATABASE=Out of the Fog Research LLC OUI:1C52D6* ID_OUI_FROM_DATABASE=FLAT DISPLAY TECHNOLOGY CORPORATION OUI:40270B* ID_OUI_FROM_DATABASE=Mobileeco Co., Ltd OUI:ACE97F* ID_OUI_FROM_DATABASE=IoT Tech Limited OUI:301518* ID_OUI_FROM_DATABASE=Ubiquitous Communication Co. ltd. OUI:101248* ID_OUI_FROM_DATABASE=ITG, Inc. OUI:106FEF* ID_OUI_FROM_DATABASE=Ad-Sol Nissin Corp OUI:A036F0* ID_OUI_FROM_DATABASE=Comprehensive Power OUI:180CAC* ID_OUI_FROM_DATABASE=CANON INC. OUI:00DB1E* ID_OUI_FROM_DATABASE=Albedo Telecom SL OUI:74943D* ID_OUI_FROM_DATABASE=AgJunction OUI:0CDA41* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:080C0B* ID_OUI_FROM_DATABASE=SysMik GmbH Dresden OUI:C8FB26* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:7CC8AB* ID_OUI_FROM_DATABASE=Acro Associates, Inc. OUI:C4DA26* ID_OUI_FROM_DATABASE=NOBLEX SA OUI:1CC316* ID_OUI_FROM_DATABASE=MileSight Technology Co., Ltd. OUI:C4E7BE* ID_OUI_FROM_DATABASE=SCSpro Co.,Ltd OUI:105F49* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:0418D6* ID_OUI_FROM_DATABASE=Ubiquiti Networks OUI:4495FA* ID_OUI_FROM_DATABASE=Qingdao Santong Digital Technology Co.Ltd OUI:60F2EF* ID_OUI_FROM_DATABASE=VisionVera International Co., Ltd. OUI:B01266* ID_OUI_FROM_DATABASE=Futaba-Kikaku OUI:909DE0* ID_OUI_FROM_DATABASE=Newland Design + Assoc. Inc. OUI:64D814* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:6CE4CE* ID_OUI_FROM_DATABASE=Villiger Security Solutions AG OUI:30F33A* ID_OUI_FROM_DATABASE=+plugg srl OUI:58CF4B* ID_OUI_FROM_DATABASE=Lufkin Industries OUI:C4393A* ID_OUI_FROM_DATABASE=SMC Networks Inc OUI:C4017C* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:D45C70* ID_OUI_FROM_DATABASE=Wi-Fi Alliance OUI:08EBED* ID_OUI_FROM_DATABASE=World Elite Technology Co.,LTD OUI:60BC4C* ID_OUI_FROM_DATABASE=EWM Hightec Welding GmbH OUI:F41E26* ID_OUI_FROM_DATABASE=Simon-Kaloi Engineering OUI:840B2D* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS CO., LTD OUI:C44567* ID_OUI_FROM_DATABASE=SAMBON PRECISON and ELECTRONICS OUI:D0738E* ID_OUI_FROM_DATABASE=DONG OH PRECISION CO., LTD. OUI:E8718D* ID_OUI_FROM_DATABASE=Elsys Equipamentos Eletronicos Ltda OUI:3C83B5* ID_OUI_FROM_DATABASE=Advance Vision Electronics Co. Ltd. OUI:808287* ID_OUI_FROM_DATABASE=ATCOM Technology Co.Ltd. OUI:28A192* ID_OUI_FROM_DATABASE=GERP Solution OUI:A08C15* ID_OUI_FROM_DATABASE=Gerhard D. Wempe KG OUI:A02195* ID_OUI_FROM_DATABASE=Samsung Electronics Digital Imaging OUI:8CE081* ID_OUI_FROM_DATABASE=zte corporation OUI:485261* ID_OUI_FROM_DATABASE=SOREEL OUI:10FBF0* ID_OUI_FROM_DATABASE=KangSheng LTD. OUI:3C57BD* ID_OUI_FROM_DATABASE=Kessler Crane Inc. OUI:600F77* ID_OUI_FROM_DATABASE=SilverPlus, Inc OUI:6851B7* ID_OUI_FROM_DATABASE=PowerCloud Systems, Inc. OUI:A44E2D* ID_OUI_FROM_DATABASE=Adaptive Wireless Solutions, LLC OUI:3CC12C* ID_OUI_FROM_DATABASE=AES Corporation OUI:0CCDFB* ID_OUI_FROM_DATABASE=EDIC Systems Inc. OUI:3092F6* ID_OUI_FROM_DATABASE=SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD OUI:2CE2A8* ID_OUI_FROM_DATABASE=DeviceDesign OUI:B49DB4* ID_OUI_FROM_DATABASE=Axion Technologies Inc. OUI:D8182B* ID_OUI_FROM_DATABASE=Conti Temic Microelectronic GmbH OUI:304449* ID_OUI_FROM_DATABASE=PLATH GmbH OUI:94FD2E* ID_OUI_FROM_DATABASE=Shanghai Uniscope Technologies Co.,Ltd OUI:64A341* ID_OUI_FROM_DATABASE=Wonderlan (Beijing) Technology Co., Ltd. OUI:8CAE4C* ID_OUI_FROM_DATABASE=Plugable Technologies OUI:D8D5B9* ID_OUI_FROM_DATABASE=Rainforest Automation, Inc. OUI:C0A0E2* ID_OUI_FROM_DATABASE=Eden Innovations OUI:E8ABFA* ID_OUI_FROM_DATABASE=Shenzhen Reecam Tech.Ltd. OUI:58874C* ID_OUI_FROM_DATABASE=LITE-ON CLEAN ENERGY TECHNOLOGY CORP. OUI:E85BF0* ID_OUI_FROM_DATABASE=Imaging Diagnostics OUI:20DC93* ID_OUI_FROM_DATABASE=Cheetah Hi-Tech, Inc. OUI:7846C4* ID_OUI_FROM_DATABASE=DAEHAP HYPER-TECH OUI:0CD9C1* ID_OUI_FROM_DATABASE=Visteon Corporation OUI:68AB8A* ID_OUI_FROM_DATABASE=RF IDeas OUI:70E24C* ID_OUI_FROM_DATABASE=SAE IT-systems GmbH & Co. KG OUI:88615A* ID_OUI_FROM_DATABASE=Siano Mobile Silicon Ltd. OUI:30215B* ID_OUI_FROM_DATABASE=Shenzhen Ostar Display Electronic Co.,Ltd OUI:08D42B* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:DC028E* ID_OUI_FROM_DATABASE=zte corporation OUI:DCB058* ID_OUI_FROM_DATABASE=Bürkert Werke GmbH OUI:641C67* ID_OUI_FROM_DATABASE=DIGIBRAS INDUSTRIA DO BRASILS/A OUI:C8E1A7* ID_OUI_FROM_DATABASE=Vertu Corporation Limited OUI:88D7BC* ID_OUI_FROM_DATABASE=DEP Company OUI:F49466* ID_OUI_FROM_DATABASE=CountMax, ltd OUI:4CAB33* ID_OUI_FROM_DATABASE=KST technology OUI:5CE0F6* ID_OUI_FROM_DATABASE=NIC.br- Nucleo de Informacao e Coordenacao do Ponto BR OUI:00E666* ID_OUI_FROM_DATABASE=ARIMA Communications Corp. OUI:F8E4FB* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:5887E2* ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd. OUI:B4DFFA* ID_OUI_FROM_DATABASE=Litemax Electronics Inc. OUI:48F8B3* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:681CA2* ID_OUI_FROM_DATABASE=Rosewill Inc. OUI:7C092B* ID_OUI_FROM_DATABASE=Bekey A/S OUI:E892A4* ID_OUI_FROM_DATABASE=LG Electronics OUI:D808F5* ID_OUI_FROM_DATABASE=Arcadia Networks Co. Ltd. OUI:84DF0C* ID_OUI_FROM_DATABASE=NET2GRID BV OUI:3CB87A* ID_OUI_FROM_DATABASE=Private OUI:E425E9* ID_OUI_FROM_DATABASE=Color-Chip OUI:F44848* ID_OUI_FROM_DATABASE=Amscreen Group Ltd OUI:441319* ID_OUI_FROM_DATABASE=WKK TECHNOLOGY LTD. OUI:088F2C* ID_OUI_FROM_DATABASE=Hills Sound Vision & Lighting OUI:3C9F81* ID_OUI_FROM_DATABASE=Shenzhen CATIC Bit Communications Technology Co.,Ltd OUI:18339D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:642216* ID_OUI_FROM_DATABASE=Shandong Taixin Electronic co.,Ltd OUI:D43D7E* ID_OUI_FROM_DATABASE=Micro-Star Int'l Co, Ltd OUI:64517E* ID_OUI_FROM_DATABASE=LONG BEN (DONGGUAN) ELECTRONIC TECHNOLOGY CO.,LTD. OUI:A816B2* ID_OUI_FROM_DATABASE=LG Electronics OUI:18E2C2* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:0C57EB* ID_OUI_FROM_DATABASE=Mueller Systems OUI:48282F* ID_OUI_FROM_DATABASE=zte corporation OUI:745327* ID_OUI_FROM_DATABASE=COMMSEN CO., LIMITED OUI:E47185* ID_OUI_FROM_DATABASE=Securifi Ltd OUI:881036* ID_OUI_FROM_DATABASE=Panodic(ShenZhen) Electronics Limted OUI:18F87A* ID_OUI_FROM_DATABASE=i3 International Inc. OUI:142DF5* ID_OUI_FROM_DATABASE=Amphitech OUI:C08ADE* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:90F72F* ID_OUI_FROM_DATABASE=Phillips Machine & Welding Co., Inc. OUI:B45570* ID_OUI_FROM_DATABASE=Borea OUI:5C5015* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0CD2B5* ID_OUI_FROM_DATABASE=Binatone Telecommunication Pvt. Ltd OUI:1C62B8* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:4846F1* ID_OUI_FROM_DATABASE=Uros Oy OUI:1CD40C* ID_OUI_FROM_DATABASE=Kriwan Industrie-Elektronik GmbH OUI:747B7A* ID_OUI_FROM_DATABASE=ETH Inc. OUI:1C7C45* ID_OUI_FROM_DATABASE=Vitek Industrial Video Products, Inc. OUI:FC94E3* ID_OUI_FROM_DATABASE=Technicolor USA Inc. OUI:C8AE9C* ID_OUI_FROM_DATABASE=Shanghai TYD Elecronic Technology Co. Ltd OUI:A44C11* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:782544* ID_OUI_FROM_DATABASE=Omnima Limited OUI:D4DF57* ID_OUI_FROM_DATABASE=Alpinion Medical Systems OUI:5048EB* ID_OUI_FROM_DATABASE=BEIJING HAIHEJINSHENG NETWORK TECHNOLOGY CO. LTD. OUI:40AC8D* ID_OUI_FROM_DATABASE=Data Management, Inc. OUI:54466B* ID_OUI_FROM_DATABASE=Shenzhen CZTIC Electronic Technology Co., Ltd OUI:08EDB9* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:1C3477* ID_OUI_FROM_DATABASE=Innovation Wireless OUI:4423AA* ID_OUI_FROM_DATABASE=Farmage Co., Ltd. OUI:A0EF84* ID_OUI_FROM_DATABASE=Seine Image Int'l Co., Ltd OUI:AC7A42* ID_OUI_FROM_DATABASE=iConnectivity OUI:5869F9* ID_OUI_FROM_DATABASE=Fusion Transactive Ltd. OUI:B0C83F* ID_OUI_FROM_DATABASE=Jiangsu Cynray IOT Co., Ltd. OUI:CC14A6* ID_OUI_FROM_DATABASE=Yichun MyEnergy Domain, Inc OUI:98D686* ID_OUI_FROM_DATABASE=Chyi Lee industry Co., ltd. OUI:20443A* ID_OUI_FROM_DATABASE=Schneider Electric Asia Pacific Ltd OUI:28C914* ID_OUI_FROM_DATABASE=Taimag Corporation OUI:4C7897* ID_OUI_FROM_DATABASE=Arrowhead Alarm Products Ltd OUI:AC0A61* ID_OUI_FROM_DATABASE=Labor S.r.L. OUI:B482C5* ID_OUI_FROM_DATABASE=Relay2, Inc. OUI:60D1AA* ID_OUI_FROM_DATABASE=Vishal Telecommunications Pvt Ltd OUI:CCC104* ID_OUI_FROM_DATABASE=Applied Technical Systems OUI:709BA5* ID_OUI_FROM_DATABASE=Shenzhen Y&D Electronics Co.,LTD. OUI:EC42F0* ID_OUI_FROM_DATABASE=ADL Embedded Solutions, Inc. OUI:10BD18* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B0435D* ID_OUI_FROM_DATABASE=NuLEDs, Inc. OUI:A82BD6* ID_OUI_FROM_DATABASE=Shina System Co., Ltd OUI:8CC7AA* ID_OUI_FROM_DATABASE=Radinet Communications Inc. OUI:20014F* ID_OUI_FROM_DATABASE=Linea Research Ltd OUI:80D18B* ID_OUI_FROM_DATABASE=Hangzhou I'converge Technology Co.,Ltd OUI:B4A4B5* ID_OUI_FROM_DATABASE=Zen Eye Co.,Ltd OUI:489153* ID_OUI_FROM_DATABASE=Weinmann Geräte für Medizin GmbH + Co. KG OUI:549D85* ID_OUI_FROM_DATABASE=EnerAccess inc OUI:5CEE79* ID_OUI_FROM_DATABASE=Global Digitech Co LTD OUI:80F62E* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:9CE10E* ID_OUI_FROM_DATABASE=NCTech Ltd OUI:28F606* ID_OUI_FROM_DATABASE=Syes srl OUI:A0C3DE* ID_OUI_FROM_DATABASE=Triton Electronic Systems Ltd. OUI:AC3FA4* ID_OUI_FROM_DATABASE=TAIYO YUDEN CO.,LTD OUI:0C130B* ID_OUI_FROM_DATABASE=Uniqoteq Ltd. OUI:14CF8D* ID_OUI_FROM_DATABASE=OHSUNG ELECTRONICS CO., LTD. OUI:808698* ID_OUI_FROM_DATABASE=Netronics Technologies Inc. OUI:2C00F7* ID_OUI_FROM_DATABASE=XOS OUI:809393* ID_OUI_FROM_DATABASE=Xapt GmbH OUI:00DEFB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:90AC3F* ID_OUI_FROM_DATABASE=BrightSign LLC OUI:7CACB2* ID_OUI_FROM_DATABASE=Bosch Software Innovations GmbH OUI:0043FF* ID_OUI_FROM_DATABASE=KETRON S.R.L. OUI:745798* ID_OUI_FROM_DATABASE=TRUMPF Laser GmbH + Co. KG OUI:38E08E* ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation OUI:E4FA1D* ID_OUI_FROM_DATABASE=PAD Peripheral Advanced Design Inc. OUI:4C9E80* ID_OUI_FROM_DATABASE=KYOKKO ELECTRIC Co., Ltd. OUI:A826D9* ID_OUI_FROM_DATABASE=HTC Corporation OUI:F03A55* ID_OUI_FROM_DATABASE=Omega Elektronik AS OUI:24B88C* ID_OUI_FROM_DATABASE=Crenus Co.,Ltd. OUI:98BC57* ID_OUI_FROM_DATABASE=SVA TECHNOLOGIES CO.LTD OUI:98FE03* ID_OUI_FROM_DATABASE=Ericsson - North America OUI:F0EEBB* ID_OUI_FROM_DATABASE=VIPAR GmbH OUI:54D0ED* ID_OUI_FROM_DATABASE=AXIM Communications OUI:A49005* ID_OUI_FROM_DATABASE=CHINA GREATWALL COMPUTER SHENZHEN CO.,LTD OUI:3055ED* ID_OUI_FROM_DATABASE=Trex Network LLC OUI:D4A02A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0463E0* ID_OUI_FROM_DATABASE=Nome Oy OUI:BCA4E1* ID_OUI_FROM_DATABASE=Nabto OUI:900A3A* ID_OUI_FROM_DATABASE=PSG Plastic Service GmbH OUI:FC5B26* ID_OUI_FROM_DATABASE=MikroBits OUI:5CC213* ID_OUI_FROM_DATABASE=Fr. Sauter AG OUI:581D91* ID_OUI_FROM_DATABASE=Advanced Mobile Telecom co.,ltd. OUI:9CB008* ID_OUI_FROM_DATABASE=Ubiquitous Computing Technology Corporation OUI:00376D* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:E0EF25* ID_OUI_FROM_DATABASE=Lintes Technology Co., Ltd. OUI:CCEED9* ID_OUI_FROM_DATABASE=VAHLE DETO GmbH OUI:645EBE* ID_OUI_FROM_DATABASE=Yahoo! JAPAN OUI:CCC50A* ID_OUI_FROM_DATABASE=SHENZHEN DAJIAHAO TECHNOLOGY CO.,LTD OUI:D01AA7* ID_OUI_FROM_DATABASE=UniPrint OUI:B08E1A* ID_OUI_FROM_DATABASE=URadio Systems Co., Ltd OUI:40605A* ID_OUI_FROM_DATABASE=Hawkeye Tech Co. Ltd OUI:E05DA6* ID_OUI_FROM_DATABASE=Detlef Fink Elektronik & Softwareentwicklung OUI:0C7523* ID_OUI_FROM_DATABASE=BEIJING GEHUA CATV NETWORK CO.,LTD OUI:BC2C55* ID_OUI_FROM_DATABASE=Bear Flag Design, Inc. OUI:04F4BC* ID_OUI_FROM_DATABASE=Xena Networks OUI:608C2B* ID_OUI_FROM_DATABASE=Hanson Technology OUI:EC1120* ID_OUI_FROM_DATABASE=FloDesign Wind Turbine Corporation OUI:D0F73B* ID_OUI_FROM_DATABASE=Helmut Mauell GmbH OUI:C495A2* ID_OUI_FROM_DATABASE=SHENZHEN WEIJIU INDUSTRY AND TRADE DEVELOPMENT CO., LTD OUI:0C9E91* ID_OUI_FROM_DATABASE=Sankosha Corporation OUI:F48771* ID_OUI_FROM_DATABASE=Infoblox OUI:04F021* ID_OUI_FROM_DATABASE=Compex Systems Pte Ltd OUI:8823FE* ID_OUI_FROM_DATABASE=TTTech Computertechnik AG OUI:98AAD7* ID_OUI_FROM_DATABASE=BLUE WAVE NETWORKING CO LTD OUI:20107A* ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. OUI:502267* ID_OUI_FROM_DATABASE=PixeLINK OUI:9092B4* ID_OUI_FROM_DATABASE=Diehl BGT Defence GmbH & Co. KG OUI:806007* ID_OUI_FROM_DATABASE=RIM OUI:38A851* ID_OUI_FROM_DATABASE=Moog, Ing OUI:90185E* ID_OUI_FROM_DATABASE=Apex Tool Group GmbH & Co OHG OUI:14825B* ID_OUI_FROM_DATABASE=Hefei Radio Communication Technology Co., Ltd OUI:7CE9D3* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:8CC8CD* ID_OUI_FROM_DATABASE=Samsung Electronics Co., LTD OUI:649EF3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:34D09B* ID_OUI_FROM_DATABASE=MobilMAX Technology Inc. OUI:087572* ID_OUI_FROM_DATABASE=Obelux Oy OUI:9C1FDD* ID_OUI_FROM_DATABASE=Accupix Inc. OUI:506441* ID_OUI_FROM_DATABASE=Greenlee OUI:80946C* ID_OUI_FROM_DATABASE=TOKYO RADAR CORPORATION OUI:00FA3B* ID_OUI_FROM_DATABASE=CLOOS ELECTRONIC GMBH OUI:28CD1C* ID_OUI_FROM_DATABASE=Espotel Oy OUI:D824BD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:D878E5* ID_OUI_FROM_DATABASE=KUHN SA OUI:C49300* ID_OUI_FROM_DATABASE=8Devices OUI:4C3910* ID_OUI_FROM_DATABASE=Newtek Electronics co., Ltd. OUI:5866BA* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:5808FA* ID_OUI_FROM_DATABASE=Fiber Optic & telecommunication INC. OUI:7C94B2* ID_OUI_FROM_DATABASE=Philips Healthcare PCCI OUI:200505* ID_OUI_FROM_DATABASE=RADMAX COMMUNICATION PRIVATE LIMITED OUI:5848C0* ID_OUI_FROM_DATABASE=COFLEC OUI:C8F704* ID_OUI_FROM_DATABASE=Building Block Video OUI:C8AF40* ID_OUI_FROM_DATABASE=marco Systemanalyse und Entwicklung GmbH OUI:AC319D* ID_OUI_FROM_DATABASE=Shenzhen TG-NET Botone Technology Co.,Ltd. OUI:08D09F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:D0DFC7* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B81413* ID_OUI_FROM_DATABASE=Keen High Holding(HK) Ltd. OUI:2037BC* ID_OUI_FROM_DATABASE=Kuipers Electronic Engineering BV OUI:A887ED* ID_OUI_FROM_DATABASE=ARC Wireless LLC OUI:983571* ID_OUI_FROM_DATABASE=Sub10 Systems Ltd OUI:B05CE5* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:4813F3* ID_OUI_FROM_DATABASE=BBK Electronics Corp., Ltd. OUI:CC6BF1* ID_OUI_FROM_DATABASE=Sound Masking Inc. OUI:B82CA0* ID_OUI_FROM_DATABASE=Honeywell HomMed OUI:94AE61* ID_OUI_FROM_DATABASE=Alcatel Lucent OUI:7CA61D* ID_OUI_FROM_DATABASE=MHL, LLC OUI:5CCEAD* ID_OUI_FROM_DATABASE=CDYNE Corporation OUI:9CA3BA* ID_OUI_FROM_DATABASE=SAKURA Internet Inc. OUI:709756* ID_OUI_FROM_DATABASE=Happyelectronics Co.,Ltd OUI:D4206D* ID_OUI_FROM_DATABASE=HTC Corporation OUI:1866E3* ID_OUI_FROM_DATABASE=Veros Systems, Inc. OUI:00B338* ID_OUI_FROM_DATABASE=Kontron Design Manufacturing Services (M) Sdn. Bhd OUI:94DE0E* ID_OUI_FROM_DATABASE=SmartOptics AS OUI:A429B7* ID_OUI_FROM_DATABASE=bluesky OUI:700514* ID_OUI_FROM_DATABASE=LG Electronics OUI:7C6B33* ID_OUI_FROM_DATABASE=Tenyu Tech Co. Ltd. OUI:CCB8F1* ID_OUI_FROM_DATABASE=EAGLE KINGDOM TECHNOLOGIES LIMITED OUI:DC2E6A* ID_OUI_FROM_DATABASE=HCT. Co., Ltd. OUI:34255D* ID_OUI_FROM_DATABASE=Shenzhen Loadcom Technology Co.,Ltd OUI:1897FF* ID_OUI_FROM_DATABASE=TechFaith Wireless Technology Limited OUI:0CDFA4* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:8C8E76* ID_OUI_FROM_DATABASE=taskit GmbH OUI:B4D8DE* ID_OUI_FROM_DATABASE=iota Computing, Inc. OUI:54CDA7* ID_OUI_FROM_DATABASE=Fujian Shenzhou Electronic Co.,Ltd OUI:1000FD* ID_OUI_FROM_DATABASE=LaonPeople OUI:603553* ID_OUI_FROM_DATABASE=Buwon Technology OUI:B89BC9* ID_OUI_FROM_DATABASE=SMC Networks Inc OUI:48022A* ID_OUI_FROM_DATABASE=B-Link Electronic Limited OUI:48A6D2* ID_OUI_FROM_DATABASE=GJsun Optical Science and Tech Co.,Ltd. OUI:186D99* ID_OUI_FROM_DATABASE=Adanis Inc. OUI:047D7B* ID_OUI_FROM_DATABASE=Quanta Computer Inc. OUI:D44B5E* ID_OUI_FROM_DATABASE=TAIYO YUDEN CO., LTD. OUI:B40C25* ID_OUI_FROM_DATABASE=Palo Alto Networks OUI:40BF17* ID_OUI_FROM_DATABASE=Digistar Telecom. SA OUI:E4AFA1* ID_OUI_FROM_DATABASE=HES-SO OUI:58920D* ID_OUI_FROM_DATABASE=Kinetic Avionics Limited OUI:207600* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:84D32A* ID_OUI_FROM_DATABASE=IEEE 1905.1 OUI:F8E7B5* ID_OUI_FROM_DATABASE=µTech Tecnologia LTDA OUI:0462D7* ID_OUI_FROM_DATABASE=ALSTOM HYDRO FRANCE OUI:CCC8D7* ID_OUI_FROM_DATABASE=CIAS Elettronica srl OUI:64AE0C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:A446FA* ID_OUI_FROM_DATABASE=AmTRAN Video Corporation OUI:2804E0* ID_OUI_FROM_DATABASE=FERMAX ELECTRONICA S.A.U. OUI:FC01CD* ID_OUI_FROM_DATABASE=FUNDACION TEKNIKER OUI:88E7A6* ID_OUI_FROM_DATABASE=iKnowledge Integration Corp. OUI:98E79A* ID_OUI_FROM_DATABASE=Foxconn(NanJing) Communication Co.,Ltd. OUI:54F5B6* ID_OUI_FROM_DATABASE=ORIENTAL PACIFIC INTERNATIONAL LIMITED OUI:34A55D* ID_OUI_FROM_DATABASE=TECHNOSOFT INTERNATIONAL SRL OUI:D0C282* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:449CB5* ID_OUI_FROM_DATABASE=Alcomp, Inc OUI:E4D53D* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:24E6BA* ID_OUI_FROM_DATABASE=JSC Zavod im. Kozitsky OUI:8C8A6E* ID_OUI_FROM_DATABASE=ESTUN AUTOMATION TECHNOLOY CO., LTD OUI:E0ED1A* ID_OUI_FROM_DATABASE=vastriver Technology Co., Ltd OUI:C83B45* ID_OUI_FROM_DATABASE=JRI-Maxant OUI:685E6B* ID_OUI_FROM_DATABASE=PowerRay Co., Ltd. OUI:4C32D9* ID_OUI_FROM_DATABASE=M Rutty Holdings Pty. Ltd. OUI:50A733* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:603FC5* ID_OUI_FROM_DATABASE=COX CO., LTD OUI:182B05* ID_OUI_FROM_DATABASE=8D Technologies OUI:54A9D4* ID_OUI_FROM_DATABASE=Minibar Systems OUI:4861A3* ID_OUI_FROM_DATABASE=Concern Axion JSC OUI:D89685* ID_OUI_FROM_DATABASE=GoPro OUI:08A12B* ID_OUI_FROM_DATABASE=ShenZhen EZL Technology Co., Ltd OUI:94319B* ID_OUI_FROM_DATABASE=Alphatronics BV OUI:08FC52* ID_OUI_FROM_DATABASE=OpenXS BV OUI:205B5E* ID_OUI_FROM_DATABASE=Shenzhen Wonhe Technology Co., Ltd OUI:3CC99E* ID_OUI_FROM_DATABASE=Huiyang Technology Co., Ltd OUI:C8A1BA* ID_OUI_FROM_DATABASE=Neul Ltd OUI:AC02EF* ID_OUI_FROM_DATABASE=Comsis OUI:C43A9F* ID_OUI_FROM_DATABASE=Siconix Inc. OUI:0418B6* ID_OUI_FROM_DATABASE=Private OUI:D4024A* ID_OUI_FROM_DATABASE=Delphian Systems LLC OUI:84248D* ID_OUI_FROM_DATABASE=Zebra Technologies Inc OUI:24EC99* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:9463D1* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B8621F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B45CA4* ID_OUI_FROM_DATABASE=Thing-talk Wireless Communication Technologies Corporation Limited OUI:AC8ACD* ID_OUI_FROM_DATABASE=ROGER D.Wensker, G.Wensker sp.j. OUI:984246* ID_OUI_FROM_DATABASE=SOL INDUSTRY PTE., LTD OUI:28A574* ID_OUI_FROM_DATABASE=Miller Electric Mfg. Co. OUI:3826CD* ID_OUI_FROM_DATABASE=ANDTEK OUI:C436DA* ID_OUI_FROM_DATABASE=Rusteletech Ltd. OUI:00FC70* ID_OUI_FROM_DATABASE=Intrepid Control Systems, Inc. OUI:A4EE57* ID_OUI_FROM_DATABASE=SEIKO EPSON CORPORATION OUI:D0AFB6* ID_OUI_FROM_DATABASE=Linktop Technology Co., LTD OUI:444F5E* ID_OUI_FROM_DATABASE=Pan Studios Co.,Ltd. OUI:0C3956* ID_OUI_FROM_DATABASE=Observator instruments OUI:A49981* ID_OUI_FROM_DATABASE=FuJian Elite Power Tech CO.,LTD. OUI:B83A7B* ID_OUI_FROM_DATABASE=Worldplay (Canada) Inc. OUI:783F15* ID_OUI_FROM_DATABASE=EasySYNC Ltd. OUI:F4B549* ID_OUI_FROM_DATABASE=Yeastar Technology Co., Ltd. OUI:88B168* ID_OUI_FROM_DATABASE=Delta Control GmbH OUI:20B399* ID_OUI_FROM_DATABASE=Enterasys OUI:18B79E* ID_OUI_FROM_DATABASE=Invoxia OUI:147411* ID_OUI_FROM_DATABASE=RIM OUI:5C56ED* ID_OUI_FROM_DATABASE=3pleplay Electronics Private Limited OUI:0838A5* ID_OUI_FROM_DATABASE=Funkwerk plettac electronic GmbH OUI:BCCD45* ID_OUI_FROM_DATABASE=VOISMART OUI:78028F* ID_OUI_FROM_DATABASE=Adaptive Spectrum and Signal Alignment (ASSIA), Inc. OUI:D4A425* ID_OUI_FROM_DATABASE=SMAX Technology Co., Ltd. OUI:98F8DB* ID_OUI_FROM_DATABASE=Marini Impianti Industriali s.r.l. OUI:140708* ID_OUI_FROM_DATABASE=Private OUI:24C9DE* ID_OUI_FROM_DATABASE=Genoray OUI:605464* ID_OUI_FROM_DATABASE=Eyedro Green Solutions Inc. OUI:54055F* ID_OUI_FROM_DATABASE=Alcatel Lucent OUI:405539* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B8BEBF* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:38FEC5* ID_OUI_FROM_DATABASE=Ellips B.V. OUI:24C86E* ID_OUI_FROM_DATABASE=Chaney Instrument Co. OUI:D4D898* ID_OUI_FROM_DATABASE=Korea CNO Tech Co., Ltd OUI:04180F* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:5070E5* ID_OUI_FROM_DATABASE=He Shan World Fair Electronics Technology Limited OUI:28EE2C* ID_OUI_FROM_DATABASE=Frontline Test Equipment OUI:802275* ID_OUI_FROM_DATABASE=Beijing Beny Wave Technology Co Ltd OUI:BC8199* ID_OUI_FROM_DATABASE=BASIC Co.,Ltd. OUI:000726* ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co., Ltd. OUI:24470E* ID_OUI_FROM_DATABASE=PentronicAB OUI:A4DB2E* ID_OUI_FROM_DATABASE=Kingspan Environmental Ltd OUI:F44EFD* ID_OUI_FROM_DATABASE=Actions Semiconductor Co.,Ltd.(Cayman Islands) OUI:34BCA6* ID_OUI_FROM_DATABASE=Beijing Ding Qing Technology, Ltd. OUI:D4C1FC* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:48DCFB* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:CC051B* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:688470* ID_OUI_FROM_DATABASE=eSSys Co.,Ltd OUI:3CBDD8* ID_OUI_FROM_DATABASE=LG ELECTRONICS INC OUI:F08BFE* ID_OUI_FROM_DATABASE=COSTEL.,CO.LTD OUI:5435DF* ID_OUI_FROM_DATABASE=Symeo GmbH OUI:F43D80* ID_OUI_FROM_DATABASE=FAG Industrial Services GmbH OUI:D4F0B4* ID_OUI_FROM_DATABASE=Napco Security Technologies OUI:40B3FC* ID_OUI_FROM_DATABASE=Logital Co. Limited OUI:D05FCE* ID_OUI_FROM_DATABASE=Hitachi Data Systems OUI:8C82A8* ID_OUI_FROM_DATABASE=Insigma Technology Co.,Ltd OUI:3C2763* ID_OUI_FROM_DATABASE=SLE quality engineering GmbH & Co. KG OUI:A44B15* ID_OUI_FROM_DATABASE=Sun Cupid Technology (HK) LTD OUI:508ACB* ID_OUI_FROM_DATABASE=SHENZHEN MAXMADE TECHNOLOGY CO., LTD. OUI:7032D5* ID_OUI_FROM_DATABASE=Athena Wireless Communications Inc OUI:7CF0BA* ID_OUI_FROM_DATABASE=Linkwell Telesystems Pvt Ltd OUI:CCC62B* ID_OUI_FROM_DATABASE=Tri-Systems Corporation OUI:ACF97E* ID_OUI_FROM_DATABASE=ELESYS INC. OUI:4C7367* ID_OUI_FROM_DATABASE=Genius Bytes Software Solutions GmbH OUI:DC2B66* ID_OUI_FROM_DATABASE=InfoBLOCK S.A. de C.V. OUI:14F0C5* ID_OUI_FROM_DATABASE=Xtremio Ltd. OUI:C027B9* ID_OUI_FROM_DATABASE=Beijing National Railway Research & Design Institute of Signal & Communication Co., Ltd. OUI:70A41C* ID_OUI_FROM_DATABASE=Advanced Wireless Dynamics S.L. OUI:285132* ID_OUI_FROM_DATABASE=Shenzhen Prayfly Technology Co.,Ltd OUI:4C3B74* ID_OUI_FROM_DATABASE=VOGTEC(H.K.) Co., Ltd OUI:509772* ID_OUI_FROM_DATABASE=Westinghouse Digital OUI:D85D84* ID_OUI_FROM_DATABASE=CAx soft GmbH OUI:78A683* ID_OUI_FROM_DATABASE=Precidata OUI:BC6784* ID_OUI_FROM_DATABASE=Environics Oy OUI:B4E0CD* ID_OUI_FROM_DATABASE=Fusion-io, Inc OUI:50AF73* ID_OUI_FROM_DATABASE=Shenzhen Bitland Information Technology Co., Ltd. OUI:488E42* ID_OUI_FROM_DATABASE=DIGALOG GmbH OUI:286046* ID_OUI_FROM_DATABASE=Lantech Communications Global, Inc. OUI:A424B3* ID_OUI_FROM_DATABASE=FlatFrog Laboratories AB OUI:A4856B* ID_OUI_FROM_DATABASE=Q Electronics Ltd OUI:84EA99* ID_OUI_FROM_DATABASE=Vieworks OUI:DCCBA8* ID_OUI_FROM_DATABASE=Explora Technologies Inc OUI:58EECE* ID_OUI_FROM_DATABASE=Icon Time Systems OUI:90004E* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:A41BC0* ID_OUI_FROM_DATABASE=Fastec Imaging Corporation OUI:E01F0A* ID_OUI_FROM_DATABASE=Xslent Energy Technologies. LLC OUI:F40321* ID_OUI_FROM_DATABASE=BeNeXt B.V. OUI:00B033* ID_OUI_FROM_DATABASE=OAO Izhevskiy radiozavod OUI:707EDE* ID_OUI_FROM_DATABASE=NASTEC LTD. OUI:CCBE71* ID_OUI_FROM_DATABASE=OptiLogix BV OUI:D8B12A* ID_OUI_FROM_DATABASE=Panasonic Mobile Communications Co., Ltd. OUI:7CDD90* ID_OUI_FROM_DATABASE=Shenzhen Ogemray Technology Co., Ltd. OUI:C07E40* ID_OUI_FROM_DATABASE=SHENZHEN XDK COMMUNICATION EQUIPMENT CO.,LTD OUI:E44F29* ID_OUI_FROM_DATABASE=MA Lighting Technology GmbH OUI:6CAB4D* ID_OUI_FROM_DATABASE=Digital Payment Technologies OUI:60A10A* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:60DA23* ID_OUI_FROM_DATABASE=Estech Co.,Ltd OUI:C0F8DA* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:28F358* ID_OUI_FROM_DATABASE=2C - Trifonov & Co OUI:304C7E* ID_OUI_FROM_DATABASE=Panasonic Electric Works Automation Controls Techno Co.,Ltd. OUI:64D1A3* ID_OUI_FROM_DATABASE=Sitecom Europe BV OUI:3831AC* ID_OUI_FROM_DATABASE=WEG OUI:2C7ECF* ID_OUI_FROM_DATABASE=Onzo Ltd OUI:10E3C7* ID_OUI_FROM_DATABASE=Seohwa Telecom OUI:E84040* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0C8112* ID_OUI_FROM_DATABASE=Private OUI:3822D6* ID_OUI_FROM_DATABASE=H3C Technologies Co., Limited OUI:7C7D41* ID_OUI_FROM_DATABASE=Jinmuyu Electronics Co., Ltd. OUI:4C1480* ID_OUI_FROM_DATABASE=NOREGON SYSTEMS, INC OUI:8C71F8* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:A07591* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:60F673* ID_OUI_FROM_DATABASE=TERUMO CORPORATION OUI:E48AD5* ID_OUI_FROM_DATABASE=RF WINDOW CO., LTD. OUI:24F0FF* ID_OUI_FROM_DATABASE=GHT Co., Ltd. OUI:4C07C9* ID_OUI_FROM_DATABASE=COMPUTER OFFICE Co.,Ltd. OUI:40F4EC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:2872F0* ID_OUI_FROM_DATABASE=ATHENA OUI:9C807D* ID_OUI_FROM_DATABASE=SYSCABLE Korea Inc. OUI:180B52* ID_OUI_FROM_DATABASE=Nanotron Technologies GmbH OUI:64DE1C* ID_OUI_FROM_DATABASE=Kingnetic Pte Ltd OUI:540496* ID_OUI_FROM_DATABASE=Gigawave LTD OUI:C8C126* ID_OUI_FROM_DATABASE=ZPM Industria e Comercio Ltda OUI:041D10* ID_OUI_FROM_DATABASE=Dream Ware Inc. OUI:88DD79* ID_OUI_FROM_DATABASE=Voltaire OUI:4468AB* ID_OUI_FROM_DATABASE=JUIN COMPANY, LIMITED OUI:902E87* ID_OUI_FROM_DATABASE=LabJack OUI:C8208E* ID_OUI_FROM_DATABASE=Storagedata OUI:00B342* ID_OUI_FROM_DATABASE=MacroSAN Technologies Co., Ltd. OUI:4CB9C8* ID_OUI_FROM_DATABASE=CONET CO., LTD. OUI:0474A1* ID_OUI_FROM_DATABASE=Aligera Equipamentos Digitais Ltda OUI:1064E2* ID_OUI_FROM_DATABASE=ADFweb.com s.r.l. OUI:CC34D7* ID_OUI_FROM_DATABASE=GEWISS S.P.A. OUI:B4CFDB* ID_OUI_FROM_DATABASE=Shenzhen Jiuzhou Electric Co.,LTD OUI:C46354* ID_OUI_FROM_DATABASE=U-Raku, Inc. OUI:20FEDB* ID_OUI_FROM_DATABASE=M2M Solution S.A.S. OUI:405FBE* ID_OUI_FROM_DATABASE=RIM OUI:E05B70* ID_OUI_FROM_DATABASE=Innovid, Co., Ltd. OUI:043604* ID_OUI_FROM_DATABASE=Gyeyoung I&T OUI:50CE75* ID_OUI_FROM_DATABASE=Measy Electronics Ltd OUI:34F968* ID_OUI_FROM_DATABASE=ATEK Products, LLC OUI:D0D0FD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:706417* ID_OUI_FROM_DATABASE=ORBIS TECNOLOGIA ELECTRICA S.A. OUI:64FC8C* ID_OUI_FROM_DATABASE=Zonar Systems OUI:28ED58* ID_OUI_FROM_DATABASE=JAG Jakob AG OUI:9873C4* ID_OUI_FROM_DATABASE=Sage Electronic Engineering LLC OUI:B8797E* ID_OUI_FROM_DATABASE=Secure Meters (UK) Limited OUI:2005E8* ID_OUI_FROM_DATABASE=OOO InProMedia OUI:E0D10A* ID_OUI_FROM_DATABASE=Katoudenkikougyousyo co ltd OUI:1C0656* ID_OUI_FROM_DATABASE=IDY Corporation OUI:C44B44* ID_OUI_FROM_DATABASE=Omniprint Inc. OUI:6015C7* ID_OUI_FROM_DATABASE=IdaTech OUI:188ED5* ID_OUI_FROM_DATABASE=TP Vision Belgium N.V. - innovation site Brugge OUI:E81132* ID_OUI_FROM_DATABASE=Samsung Electronics CO., LTD OUI:8CE7B3* ID_OUI_FROM_DATABASE=Sonardyne International Ltd OUI:0034F1* ID_OUI_FROM_DATABASE=Radicom Research, Inc. OUI:A8B0AE* ID_OUI_FROM_DATABASE=LEONI OUI:60893C* ID_OUI_FROM_DATABASE=Thermo Fisher Scientific P.O.A. OUI:5C17D3* ID_OUI_FROM_DATABASE=LGE OUI:347877* ID_OUI_FROM_DATABASE=O-NET Communications(Shenzhen) Limited OUI:70A191* ID_OUI_FROM_DATABASE=Trendsetter Medical, LLC OUI:A49B13* ID_OUI_FROM_DATABASE=Burroughs Payment Systems, Inc. OUI:58BC27* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:34D2C4* ID_OUI_FROM_DATABASE=RENA GmbH Print Systeme OUI:4C0F6E* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:E0A670* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:E061B2* ID_OUI_FROM_DATABASE=HANGZHOU ZENOINTEL TECHNOLOGY CO., LTD OUI:4491DB* ID_OUI_FROM_DATABASE=Shanghai Huaqin Telecom Technology Co.,Ltd OUI:14D76E* ID_OUI_FROM_DATABASE=CONCH ELECTRONIC Co.,Ltd OUI:CC6B98* ID_OUI_FROM_DATABASE=Minetec Wireless Technologies OUI:C4CD45* ID_OUI_FROM_DATABASE=Beijing Boomsense Technology CO.,LTD. OUI:D0BB80* ID_OUI_FROM_DATABASE=SHL Telemedicine International Ltd. OUI:1C83B0* ID_OUI_FROM_DATABASE=Linked IP GmbH OUI:F065DD* ID_OUI_FROM_DATABASE=Primax Electronics Ltd. OUI:706582* ID_OUI_FROM_DATABASE=Suzhou Hanming Technologies Co., Ltd. OUI:94C7AF* ID_OUI_FROM_DATABASE=Raylios Technology OUI:6854F5* ID_OUI_FROM_DATABASE=enLighted Inc OUI:008C10* ID_OUI_FROM_DATABASE=Black Box Corp. OUI:20A2E7* ID_OUI_FROM_DATABASE=Lee-Dickens Ltd OUI:8CDD8D* ID_OUI_FROM_DATABASE=Wifly-City System Inc. OUI:EC98C1* ID_OUI_FROM_DATABASE=Beijing Risbo Network Technology Co.,Ltd OUI:ECC38A* ID_OUI_FROM_DATABASE=Accuenergy (CANADA) Inc OUI:D48FAA* ID_OUI_FROM_DATABASE=Sogecam Industrial, S.A. OUI:38A95F* ID_OUI_FROM_DATABASE=Actifio Inc OUI:A0DDE5* ID_OUI_FROM_DATABASE=SHARP Corporation OUI:94A7BC* ID_OUI_FROM_DATABASE=BodyMedia, Inc. OUI:6C9B02* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:84DB2F* ID_OUI_FROM_DATABASE=Sierra Wireless Inc OUI:A45055* ID_OUI_FROM_DATABASE=busware.de OUI:2CD2E7* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:C89383* ID_OUI_FROM_DATABASE=Embedded Automation, Inc. OUI:D49E6D* ID_OUI_FROM_DATABASE=Wuhan Zhongyuan Huadian Science & Technology Co., OUI:94F720* ID_OUI_FROM_DATABASE=Tianjin Deviser Electronics Instrument Co., Ltd OUI:5C6D20* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:E02A82* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. OUI:EC2368* ID_OUI_FROM_DATABASE=IntelliVoice Co.,Ltd. OUI:B45253* ID_OUI_FROM_DATABASE=Seagate Technology OUI:04DD4C* ID_OUI_FROM_DATABASE=Velocytech OUI:B4C810* ID_OUI_FROM_DATABASE=UMPI Elettronica OUI:38580C* ID_OUI_FROM_DATABASE=Panaccess Systems GmbH OUI:24AF54* ID_OUI_FROM_DATABASE=NEXGEN Mediatech Inc. OUI:F0F9F7* ID_OUI_FROM_DATABASE=IES GmbH & Co. KG OUI:CC0CDA* ID_OUI_FROM_DATABASE=Miljovakt AS OUI:C01242* ID_OUI_FROM_DATABASE=Alpha Security Products OUI:90507B* ID_OUI_FROM_DATABASE=Advanced PANMOBIL Systems GmbH & Co. KG OUI:00B5D6* ID_OUI_FROM_DATABASE=Omnibit Inc. OUI:F893F3* ID_OUI_FROM_DATABASE=VOLANS OUI:7C3E9D* ID_OUI_FROM_DATABASE=PATECH OUI:4C60D5* ID_OUI_FROM_DATABASE=airPointe of New Hampshire OUI:48F8E1* ID_OUI_FROM_DATABASE=Alcatel Lucent WT OUI:D45297* ID_OUI_FROM_DATABASE=nSTREAMS Technologies, Inc. OUI:78EC22* ID_OUI_FROM_DATABASE=Shanghai Qihui Telecom Technology Co., LTD OUI:F8D756* ID_OUI_FROM_DATABASE=Simm Tronic Limited OUI:E087B1* ID_OUI_FROM_DATABASE=Nata-Info Ltd. OUI:A8B1D4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:4CBAA3* ID_OUI_FROM_DATABASE=Bison Electronics Inc. OUI:EC7C74* ID_OUI_FROM_DATABASE=Justone Technologies Co., Ltd. OUI:3C1A79* ID_OUI_FROM_DATABASE=Huayuan Technology CO.,LTD OUI:30E48E* ID_OUI_FROM_DATABASE=Vodafone UK OUI:08512E* ID_OUI_FROM_DATABASE=Orion Diagnostica Oy OUI:9CF61A* ID_OUI_FROM_DATABASE=UTC Fire and Security OUI:80A1D7* ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co.,Ltd OUI:C802A6* ID_OUI_FROM_DATABASE=Beijing Newmine Technology OUI:C84C75* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:68EBAE* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:284C53* ID_OUI_FROM_DATABASE=Intune Networks OUI:102D96* ID_OUI_FROM_DATABASE=Looxcie Inc. OUI:3037A6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:ACEA6A* ID_OUI_FROM_DATABASE=GENIX INFOCOMM CO., LTD. OUI:7C2064* ID_OUI_FROM_DATABASE=Alcatel Lucent IPD OUI:5C35DA* ID_OUI_FROM_DATABASE=There Corporation Oy OUI:005218* ID_OUI_FROM_DATABASE=Wuxi Keboda Electron Co.Ltd OUI:C09134* ID_OUI_FROM_DATABASE=ProCurve Networking by HP OUI:F07BCB* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:08F2F4* ID_OUI_FROM_DATABASE=Net One Partners Co.,Ltd. OUI:68EFBD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:5CFF35* ID_OUI_FROM_DATABASE=Wistron Corporation OUI:183BD2* ID_OUI_FROM_DATABASE=BYD Precision Manufacture Company Ltd. OUI:F45595* ID_OUI_FROM_DATABASE=HENGBAO Corporation LTD. OUI:C08B6F* ID_OUI_FROM_DATABASE=S I Sistemas Inteligentes Eletrônicos Ltda OUI:BCA9D6* ID_OUI_FROM_DATABASE=Cyber-Rain, Inc. OUI:0CDDEF* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:80C63F* ID_OUI_FROM_DATABASE=Remec Broadband Wireless , LLC OUI:F09CBB* ID_OUI_FROM_DATABASE=RaonThink Inc. OUI:FCE23F* ID_OUI_FROM_DATABASE=CLAY PAKY SPA OUI:B0E39D* ID_OUI_FROM_DATABASE=CAT SYSTEM CO.,LTD. OUI:78A6BD* ID_OUI_FROM_DATABASE=DAEYEON Control&Instrument Co,.Ltd OUI:481249* ID_OUI_FROM_DATABASE=Luxcom Technologies Inc. OUI:B43DB2* ID_OUI_FROM_DATABASE=Degreane Horizon OUI:C4823F* ID_OUI_FROM_DATABASE=Fujian Newland Auto-ID Tech. Co,.Ltd. OUI:F4C795* ID_OUI_FROM_DATABASE=WEY Elektronik AG OUI:087695* ID_OUI_FROM_DATABASE=Auto Industrial Co., Ltd. OUI:ACCE8F* ID_OUI_FROM_DATABASE=HWA YAO TECHNOLOGIES CO., LTD OUI:042F56* ID_OUI_FROM_DATABASE=ATOCS (Shenzhen) LTD OUI:084E1C* ID_OUI_FROM_DATABASE=H2A Systems, LLC OUI:A4B121* ID_OUI_FROM_DATABASE=Arantia 2010 S.L. OUI:9889ED* ID_OUI_FROM_DATABASE=Anadem Information Inc. OUI:147373* ID_OUI_FROM_DATABASE=TUBITAK UEKAE OUI:982D56* ID_OUI_FROM_DATABASE=Resolution Audio OUI:00A2DA* ID_OUI_FROM_DATABASE=INAT GmbH OUI:6C3E9C* ID_OUI_FROM_DATABASE=KE Knestel Elektronik GmbH OUI:F89D0D* ID_OUI_FROM_DATABASE=Control Technology Inc. OUI:1010B6* ID_OUI_FROM_DATABASE=McCain Inc OUI:081FF3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:5CE286* ID_OUI_FROM_DATABASE=Nortel Networks OUI:2CCD27* ID_OUI_FROM_DATABASE=Precor Inc OUI:6C5E7A* ID_OUI_FROM_DATABASE=Ubiquitous Internet Telecom Co., Ltd OUI:D828C9* ID_OUI_FROM_DATABASE=General Electric Consumer and Industrial OUI:C86C1E* ID_OUI_FROM_DATABASE=Display Systems Ltd OUI:EC6C9F* ID_OUI_FROM_DATABASE=Chengdu Volans Technology CO.,LTD OUI:CCCC4E* ID_OUI_FROM_DATABASE=Sun Fountainhead USA. Corp OUI:60D30A* ID_OUI_FROM_DATABASE=Quatius Limited OUI:BC9DA5* ID_OUI_FROM_DATABASE=DASCOM Europe GmbH OUI:60D0A9* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:942E63* ID_OUI_FROM_DATABASE=Finsécur OUI:C8D2C1* ID_OUI_FROM_DATABASE=Jetlun (Shenzhen) Corporation OUI:F0BCC8* ID_OUI_FROM_DATABASE=MaxID (Pty) Ltd OUI:406186* ID_OUI_FROM_DATABASE=MICRO-STAR INT'L CO.,LTD OUI:74E537* ID_OUI_FROM_DATABASE=RADSPIN OUI:C417FE* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:7C08D9* ID_OUI_FROM_DATABASE=Shanghai B-Star Technology Co OUI:448E81* ID_OUI_FROM_DATABASE=VIG OUI:2046F9* ID_OUI_FROM_DATABASE=Advanced Network Devices (dba:AND) OUI:6CD68A* ID_OUI_FROM_DATABASE=LG Electronics Inc OUI:681FD8* ID_OUI_FROM_DATABASE=Advanced Telemetry OUI:0C8230* ID_OUI_FROM_DATABASE=SHENZHEN MAGNUS TECHNOLOGIES CO.,LTD OUI:049F81* ID_OUI_FROM_DATABASE=Netscout Systems, Inc. OUI:50934F* ID_OUI_FROM_DATABASE=Gradual Tecnologia Ltda. OUI:34EF8B* ID_OUI_FROM_DATABASE=NTT Communications Corporation OUI:38E98C* ID_OUI_FROM_DATABASE=Reco S.p.A. OUI:F02408* ID_OUI_FROM_DATABASE=Talaris (Sweden) AB OUI:A06986* ID_OUI_FROM_DATABASE=Wellav Technologies Ltd OUI:F02FD8* ID_OUI_FROM_DATABASE=Bi2-Vision OUI:C86CB6* ID_OUI_FROM_DATABASE=Optcom Co., Ltd. OUI:C45976* ID_OUI_FROM_DATABASE=Fugoo Coorporation OUI:B0C8AD* ID_OUI_FROM_DATABASE=People Power Company OUI:A8F274* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:A870A5* ID_OUI_FROM_DATABASE=UniComm Inc. OUI:80177D* ID_OUI_FROM_DATABASE=Nortel Networks OUI:E8DAAA* ID_OUI_FROM_DATABASE=VideoHome Technology Corp. OUI:647D81* ID_OUI_FROM_DATABASE=YOKOTA INDUSTRIAL CO,.LTD OUI:8891DD* ID_OUI_FROM_DATABASE=Racktivity OUI:C4198B* ID_OUI_FROM_DATABASE=Dominion Voting Systems Corporation OUI:C83A35* ID_OUI_FROM_DATABASE=Tenda Technology Co., Ltd. OUI:F4ACC1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:584CEE* ID_OUI_FROM_DATABASE=Digital One Technologies, Limited OUI:E064BB* ID_OUI_FROM_DATABASE=DigiView S.r.l. OUI:4C63EB* ID_OUI_FROM_DATABASE=Application Solutions (Electronics and Vision) Ltd OUI:C01E9B* ID_OUI_FROM_DATABASE=Pixavi AS OUI:64168D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:24D2CC* ID_OUI_FROM_DATABASE=SmartDrive Systems Inc. OUI:7C6C8F* ID_OUI_FROM_DATABASE=AMS NEVE LTD OUI:C4E17C* ID_OUI_FROM_DATABASE=U2S co. OUI:A8C222* ID_OUI_FROM_DATABASE=TM-Research Inc. OUI:50252B* ID_OUI_FROM_DATABASE=Nethra Imaging Incorporated OUI:A4DA3F* ID_OUI_FROM_DATABASE=Bionics Corp. OUI:9C4E8E* ID_OUI_FROM_DATABASE=ALT Systems Ltd OUI:448312* ID_OUI_FROM_DATABASE=Star-Net OUI:687924* ID_OUI_FROM_DATABASE=ELS-GmbH & Co. KG OUI:38BB23* ID_OUI_FROM_DATABASE=OzVision America LLC OUI:003A99* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:04C05B* ID_OUI_FROM_DATABASE=Tigo Energy OUI:5C1437* ID_OUI_FROM_DATABASE=Thyssenkrupp Aufzugswerke GmbH OUI:9C55B4* ID_OUI_FROM_DATABASE=I.S.E. S.r.l. OUI:DC2C26* ID_OUI_FROM_DATABASE=Iton Technology Limited OUI:4CC452* ID_OUI_FROM_DATABASE=Shang Hai Tyd. Electon Technology Ltd. OUI:F0C24C* ID_OUI_FROM_DATABASE=Zhejiang FeiYue Digital Technology Co., Ltd OUI:08184C* ID_OUI_FROM_DATABASE=A. S. Thomas, Inc. OUI:5CE223* ID_OUI_FROM_DATABASE=Delphin Technology AG OUI:FC6198* ID_OUI_FROM_DATABASE=NEC Personal Products, Ltd OUI:F871FE* ID_OUI_FROM_DATABASE=The Goldman Sachs Group, Inc. OUI:D8C3FB* ID_OUI_FROM_DATABASE=DETRACOM OUI:201257* ID_OUI_FROM_DATABASE=Most Lucky Trading Ltd OUI:2021A5* ID_OUI_FROM_DATABASE=LG Electronics Inc OUI:D49C28* ID_OUI_FROM_DATABASE=JayBird LLC OUI:A03A75* ID_OUI_FROM_DATABASE=PSS Belgium N.V. OUI:746B82* ID_OUI_FROM_DATABASE=MOVEK OUI:0C8411* ID_OUI_FROM_DATABASE=A.O. Smith Water Products OUI:F8E968* ID_OUI_FROM_DATABASE=Egker Kft. OUI:E8DFF2* ID_OUI_FROM_DATABASE=PRF Co., Ltd. OUI:006440* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:D0E40B* ID_OUI_FROM_DATABASE=Wearable Inc. OUI:AC867E* ID_OUI_FROM_DATABASE=Create New Technology (HK) Limited Company OUI:58F67B* ID_OUI_FROM_DATABASE=Xia Men UnionCore Technology LTD. OUI:A02EF3* ID_OUI_FROM_DATABASE=United Integrated Services Co., Led. OUI:A8CE90* ID_OUI_FROM_DATABASE=CVC OUI:00271F* ID_OUI_FROM_DATABASE=MIPRO Electronics Co., Ltd OUI:00271A* ID_OUI_FROM_DATABASE=Geenovo Technology Ltd. OUI:002714* ID_OUI_FROM_DATABASE=Grainmustards, Co,ltd. OUI:002717* ID_OUI_FROM_DATABASE=CE Digital(Zhenjiang)Co.,Ltd OUI:002708* ID_OUI_FROM_DATABASE=Nordiag ASA OUI:002701* ID_OUI_FROM_DATABASE=INCOstartec GmbH OUI:002702* ID_OUI_FROM_DATABASE=SolarEdge Technologies OUI:0026FB* ID_OUI_FROM_DATABASE=AirDio Wireless, Inc. OUI:0026F5* ID_OUI_FROM_DATABASE=XRPLUS Inc. OUI:002632* ID_OUI_FROM_DATABASE=Instrumentation Technologies d.d. OUI:00262D* ID_OUI_FROM_DATABASE=Wistron Corporation OUI:00262C* ID_OUI_FROM_DATABASE=IKT Advanced Technologies s.r.o. OUI:002626* ID_OUI_FROM_DATABASE=Geophysical Survey Systems, Inc. OUI:00261F* ID_OUI_FROM_DATABASE=SAE Magnetics (H.K.) Ltd. OUI:002620* ID_OUI_FROM_DATABASE=ISGUS GmbH OUI:00261A* ID_OUI_FROM_DATABASE=Femtocomm System Technology Corp. OUI:002613* ID_OUI_FROM_DATABASE=Engel Axil S.L. OUI:00260D* ID_OUI_FROM_DATABASE=Mercury Systems, Inc. OUI:0025D8* ID_OUI_FROM_DATABASE=KOREA MAINTENANCE OUI:0025CC* ID_OUI_FROM_DATABASE=Mobile Communications Korea Incorporated OUI:0025C5* ID_OUI_FROM_DATABASE=Star Link Communication Pvt. Ltd. OUI:0025C6* ID_OUI_FROM_DATABASE=kasercorp, ltd OUI:0025C0* ID_OUI_FROM_DATABASE=ZillionTV Corporation OUI:0025B4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0025B9* ID_OUI_FROM_DATABASE=Cypress Solutions Inc OUI:0025AD* ID_OUI_FROM_DATABASE=Manufacturing Resources International OUI:002600* ID_OUI_FROM_DATABASE=TEAC Australia Pty Ltd. OUI:002607* ID_OUI_FROM_DATABASE=Enabling Technology Pty Ltd OUI:0025FB* ID_OUI_FROM_DATABASE=Tunstall Healthcare A/S OUI:0025FA* ID_OUI_FROM_DATABASE=J&M Analytik AG OUI:0025F6* ID_OUI_FROM_DATABASE=netTALK.com, Inc. OUI:0025EF* ID_OUI_FROM_DATABASE=I-TEC Co., Ltd. OUI:0025E9* ID_OUI_FROM_DATABASE=i-mate Development, Inc. OUI:0025DF* ID_OUI_FROM_DATABASE=Private OUI:002690* ID_OUI_FROM_DATABASE=I DO IT OUI:00268A* ID_OUI_FROM_DATABASE=Terrier SC Ltd OUI:002689* ID_OUI_FROM_DATABASE=General Dynamics Robotic Systems OUI:002684* ID_OUI_FROM_DATABASE=KISAN SYSTEM OUI:002683* ID_OUI_FROM_DATABASE=Ajoho Enterprise Co., Ltd. OUI:00267D* ID_OUI_FROM_DATABASE=A-Max Technology Macao Commercial Offshore Company Limited OUI:002677* ID_OUI_FROM_DATABASE=DEIF A/S OUI:002671* ID_OUI_FROM_DATABASE=AUTOVISION Co., Ltd OUI:00266A* ID_OUI_FROM_DATABASE=ESSENSIUM NV OUI:0026EF* ID_OUI_FROM_DATABASE=Technology Advancement Group, Inc. OUI:0026E9* ID_OUI_FROM_DATABASE=SP Corp OUI:0026E2* ID_OUI_FROM_DATABASE=LG Electronics OUI:0026DC* ID_OUI_FROM_DATABASE=Optical Systems Design OUI:0026D6* ID_OUI_FROM_DATABASE=Ningbo Andy Optoelectronic Co., Ltd. OUI:0026CF* ID_OUI_FROM_DATABASE=DEKA R&D OUI:0026D0* ID_OUI_FROM_DATABASE=Semihalf OUI:0026CA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0026C9* ID_OUI_FROM_DATABASE=Proventix Systems, Inc. OUI:0026C3* ID_OUI_FROM_DATABASE=Insightek Corp. OUI:002664* ID_OUI_FROM_DATABASE=Core System Japan OUI:002658* ID_OUI_FROM_DATABASE=T-Platforms (Cyprus) Limited OUI:002645* ID_OUI_FROM_DATABASE=Circontrol S.A. OUI:00263F* ID_OUI_FROM_DATABASE=LIOS Technology GmbH OUI:002639* ID_OUI_FROM_DATABASE=T.M. Electronics, Inc. OUI:0026BD* ID_OUI_FROM_DATABASE=JTEC Card & Communication Co., Ltd. OUI:0026B3* ID_OUI_FROM_DATABASE=Thales Communications Inc OUI:0026AD* ID_OUI_FROM_DATABASE=Arada Systems, Inc. OUI:0026A9* ID_OUI_FROM_DATABASE=Strong Technologies Pty Ltd OUI:0026A3* ID_OUI_FROM_DATABASE=FQ Ingenieria Electronica S.A. OUI:00269C* ID_OUI_FROM_DATABASE=ITUS JAPAN CO. LTD OUI:002696* ID_OUI_FROM_DATABASE=NOOLIX Co., Ltd OUI:002484* ID_OUI_FROM_DATABASE=Bang and Olufsen Medicom a/s OUI:002486* ID_OUI_FROM_DATABASE=DesignArt Networks OUI:00247F* ID_OUI_FROM_DATABASE=Nortel Networks OUI:002478* ID_OUI_FROM_DATABASE=Mag Tech Electronics Co Limited OUI:002471* ID_OUI_FROM_DATABASE=Fusion MultiSystems dba Fusion-io OUI:002473* ID_OUI_FROM_DATABASE=3COM EUROPE LTD OUI:002460* ID_OUI_FROM_DATABASE=Giaval Science Development Co. Ltd. OUI:00245B* ID_OUI_FROM_DATABASE=RAIDON TECHNOLOGY, INC. OUI:00244E* ID_OUI_FROM_DATABASE=RadChips, Inc. OUI:002447* ID_OUI_FROM_DATABASE=Kaztek Systems OUI:002442* ID_OUI_FROM_DATABASE=Axona Limited OUI:00243D* ID_OUI_FROM_DATABASE=Emerson Appliance Motors and Controls OUI:002528* ID_OUI_FROM_DATABASE=Daido Signal Co., Ltd. OUI:002523* ID_OUI_FROM_DATABASE=OCP Inc. OUI:00251E* ID_OUI_FROM_DATABASE=ROTEL TECHNOLOGIES OUI:002519* ID_OUI_FROM_DATABASE=Viaas Inc OUI:002514* ID_OUI_FROM_DATABASE=PC Worth Int'l Co., Ltd. OUI:00250D* ID_OUI_FROM_DATABASE=GZT Telkom-Telmor sp. z o.o. OUI:002506* ID_OUI_FROM_DATABASE=A.I. ANTITACCHEGGIO ITALIA SRL OUI:002508* ID_OUI_FROM_DATABASE=Maquet Cardiopulmonary AG OUI:00257A* ID_OUI_FROM_DATABASE=CAMCO Produktions- und Vertriebs-GmbH für Beschallungs- und Beleuchtungsanlagen OUI:00257F* ID_OUI_FROM_DATABASE=CallTechSolution Co.,Ltd OUI:002573* ID_OUI_FROM_DATABASE=ST Electronics (Info-Security) Pte Ltd OUI:002567* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:00256E* ID_OUI_FROM_DATABASE=Van Breda B.V. OUI:00256D* ID_OUI_FROM_DATABASE=Broadband Forum OUI:002560* ID_OUI_FROM_DATABASE=Ibridge Networks & Communications Ltd. OUI:00255B* ID_OUI_FROM_DATABASE=CoachComm, LLC OUI:0024E2* ID_OUI_FROM_DATABASE=HASEGAWA ELECTRIC CO.,LTD. OUI:0024DB* ID_OUI_FROM_DATABASE=Alcohol Monitoring Systems OUI:0024CF* ID_OUI_FROM_DATABASE=Inscape Data Corporation OUI:0024C8* ID_OUI_FROM_DATABASE=Broadband Solutions Group OUI:0024C3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0024C0* ID_OUI_FROM_DATABASE=NTI COMODO INC OUI:0024B6* ID_OUI_FROM_DATABASE=Seagate Technology OUI:0024BB* ID_OUI_FROM_DATABASE=CENTRAL Corporation OUI:0024B1* ID_OUI_FROM_DATABASE=Coulomb Technologies OUI:0024AA* ID_OUI_FROM_DATABASE=Dycor Technologies Ltd. OUI:0024A3* ID_OUI_FROM_DATABASE=Sonim Technologies Inc OUI:00249E* ID_OUI_FROM_DATABASE=ADC-Elektronik GmbH OUI:00248B* ID_OUI_FROM_DATABASE=HYBUS CO., LTD. OUI:002492* ID_OUI_FROM_DATABASE=Motorola, Broadband Solutions Group OUI:002497* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002554* ID_OUI_FROM_DATABASE=Pixel8 Networks OUI:00254D* ID_OUI_FROM_DATABASE=Singapore Technologies Electronics Limited OUI:00254E* ID_OUI_FROM_DATABASE=Vertex Wireless Co., Ltd. OUI:002537* ID_OUI_FROM_DATABASE=Runcom Technologies Ltd. OUI:00253E* ID_OUI_FROM_DATABASE=Sensus Metering Systems OUI:002541* ID_OUI_FROM_DATABASE=Maquet Critical Care AB OUI:00252D* ID_OUI_FROM_DATABASE=Kiryung Electronics OUI:0025A6* ID_OUI_FROM_DATABASE=Central Network Solution Co., Ltd. OUI:0025A1* ID_OUI_FROM_DATABASE=Enalasys OUI:00259A* ID_OUI_FROM_DATABASE=CEStronics GmbH OUI:002593* ID_OUI_FROM_DATABASE=DatNet Informatikai Kft. OUI:002594* ID_OUI_FROM_DATABASE=Eurodesign BG LTD OUI:00258E* ID_OUI_FROM_DATABASE=The Weather Channel OUI:00258A* ID_OUI_FROM_DATABASE=Pole/Zero Corporation OUI:002589* ID_OUI_FROM_DATABASE=Hills Industries Limited OUI:002584* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002501* ID_OUI_FROM_DATABASE=JSC Supertel OUI:0024FA* ID_OUI_FROM_DATABASE=Hilger u. Kern GMBH OUI:0024F5* ID_OUI_FROM_DATABASE=NDS Surgical Imaging OUI:0024EE* ID_OUI_FROM_DATABASE=Wynmax Inc. OUI:0024E7* ID_OUI_FROM_DATABASE=Plaster Networks OUI:0023F2* ID_OUI_FROM_DATABASE=TVLogic OUI:0023E8* ID_OUI_FROM_DATABASE=Demco Corp. OUI:0023E1* ID_OUI_FROM_DATABASE=Cavena Image Products AB OUI:0023DC* ID_OUI_FROM_DATABASE=Benein, Inc OUI:0023DB* ID_OUI_FROM_DATABASE=saxnet gmbh OUI:0023C9* ID_OUI_FROM_DATABASE=Sichuan Tianyi Information Science & Technology Stock CO.,LTD OUI:0023CE* ID_OUI_FROM_DATABASE=KITA DENSHI CORPORATION OUI:0023D5* ID_OUI_FROM_DATABASE=WAREMA electronic GmbH OUI:002421* ID_OUI_FROM_DATABASE=MICRO-STAR INT'L CO., LTD. OUI:002414* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002415* ID_OUI_FROM_DATABASE=Magnetic Autocontrol GmbH OUI:00240F* ID_OUI_FROM_DATABASE=Ishii Tool & Engineering Corporation OUI:002408* ID_OUI_FROM_DATABASE=Pacific Biosciences OUI:002402* ID_OUI_FROM_DATABASE=Op-Tection GmbH OUI:0023FC* ID_OUI_FROM_DATABASE=Ultra Stereo Labs, Inc OUI:0023CF* ID_OUI_FROM_DATABASE=CUMMINS-ALLISON CORP. OUI:0023C2* ID_OUI_FROM_DATABASE=SAMSUNG Electronics. Co. LTD OUI:0023B6* ID_OUI_FROM_DATABASE=SECURITE COMMUNICATIONS / HONEYWELL OUI:0023BC* ID_OUI_FROM_DATABASE=EQ-SYS GmbH OUI:0023AA* ID_OUI_FROM_DATABASE=HFR, Inc. OUI:0023A9* ID_OUI_FROM_DATABASE=Beijing Detianquan Electromechanical Equipment Co., Ltd OUI:002341* ID_OUI_FROM_DATABASE=Siemens AB, Infrastructure & Cities, Building Technologies Division, IC BT SSP SP BA PR OUI:00233C* ID_OUI_FROM_DATABASE=Alflex OUI:00233B* ID_OUI_FROM_DATABASE=C-Matic Systems Ltd OUI:002335* ID_OUI_FROM_DATABASE=Linkflex Co.,Ltd OUI:00232D* ID_OUI_FROM_DATABASE=SandForce OUI:002328* ID_OUI_FROM_DATABASE=ALCON TELECOMMUNICATIONS CO., LTD. OUI:002321* ID_OUI_FROM_DATABASE=Avitech International Corp OUI:0022F8* ID_OUI_FROM_DATABASE=PIMA Electronic Systems Ltd. OUI:00231F* ID_OUI_FROM_DATABASE=Guangda Electronic & Telecommunication Technology Development Co., Ltd. OUI:0022E6* ID_OUI_FROM_DATABASE=Intelligent Data OUI:0022E0* ID_OUI_FROM_DATABASE=Atlantic Software Technologies S.r.L. OUI:0022DF* ID_OUI_FROM_DATABASE=TAMUZ Monitors OUI:0022DA* ID_OUI_FROM_DATABASE=ANATEK, LLC OUI:0022D3* ID_OUI_FROM_DATABASE=Hub-Tech OUI:0022CD* ID_OUI_FROM_DATABASE=Ared Technology Co., Ltd. OUI:0022C4* ID_OUI_FROM_DATABASE=epro GmbH OUI:0022C9* ID_OUI_FROM_DATABASE=Lenord, Bauer & Co GmbH OUI:0022BF* ID_OUI_FROM_DATABASE=SieAmp Group of Companies OUI:0022B9* ID_OUI_FROM_DATABASE=Analogix Seminconductor, Inc OUI:0022BA* ID_OUI_FROM_DATABASE=HUTH Elektronik Systeme GmbH OUI:00239D* ID_OUI_FROM_DATABASE=Mapower Electronics Co., Ltd OUI:002397* ID_OUI_FROM_DATABASE=Westell Technologies Inc. OUI:002392* ID_OUI_FROM_DATABASE=Proteus Industries Inc. OUI:00238D* ID_OUI_FROM_DATABASE=Techno Design Co., Ltd. OUI:002389* ID_OUI_FROM_DATABASE=HANGZHOU H3C Technologies Co., Ltd. OUI:002388* ID_OUI_FROM_DATABASE=V.T. Telematica S.p.a. OUI:002383* ID_OUI_FROM_DATABASE=InMage Systems Inc OUI:00237C* ID_OUI_FROM_DATABASE=NEOTION OUI:002324* ID_OUI_FROM_DATABASE=G-PRO COMPUTER OUI:002431* ID_OUI_FROM_DATABASE=Uni-v co.,ltd OUI:00241B* ID_OUI_FROM_DATABASE=iWOW Communications Pte Ltd OUI:002422* ID_OUI_FROM_DATABASE=Knapp Logistik Automation GmbH OUI:002427* ID_OUI_FROM_DATABASE=SSI COMPUTER CORP OUI:002373* ID_OUI_FROM_DATABASE=GridIron Systems, Inc. OUI:002367* ID_OUI_FROM_DATABASE=UniControls a.s. OUI:00236E* ID_OUI_FROM_DATABASE=Burster GmbH & Co KG OUI:00236D* ID_OUI_FROM_DATABASE=ResMed Ltd OUI:002360* ID_OUI_FROM_DATABASE=Lookit Technology Co., Ltd OUI:00235B* ID_OUI_FROM_DATABASE=Gulfstream OUI:002316* ID_OUI_FROM_DATABASE=KISAN ELECTRONICS CO OUI:00230F* ID_OUI_FROM_DATABASE=Hirsch Electronics Corporation OUI:00230A* ID_OUI_FROM_DATABASE=ARBURG GmbH & Co KG OUI:002309* ID_OUI_FROM_DATABASE=Janam Technologies LLC OUI:002303* ID_OUI_FROM_DATABASE=LITE-ON IT Corporation OUI:0022F2* ID_OUI_FROM_DATABASE=SunPower Corp OUI:0022ED* ID_OUI_FROM_DATABASE=TSI Power Corporation OUI:00228D* ID_OUI_FROM_DATABASE=GBS Laboratories LLC OUI:002287* ID_OUI_FROM_DATABASE=Titan Wireless LLC OUI:002288* ID_OUI_FROM_DATABASE=Sagrad, Inc. OUI:002281* ID_OUI_FROM_DATABASE=Daintree Networks Pty OUI:00227A* ID_OUI_FROM_DATABASE=Telecom Design OUI:00226B* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:002261* ID_OUI_FROM_DATABASE=Frontier Silicon Ltd OUI:00225D* ID_OUI_FROM_DATABASE=Digicable Network India Pvt. Ltd. OUI:00225C* ID_OUI_FROM_DATABASE=Multimedia & Communication Technology OUI:00216F* ID_OUI_FROM_DATABASE=SymCom, Inc. OUI:002169* ID_OUI_FROM_DATABASE=Prologix, LLC. OUI:002162* ID_OUI_FROM_DATABASE=Nortel OUI:002156* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002150* ID_OUI_FROM_DATABASE=EYEVIEW ELECTRONICS OUI:00214A* ID_OUI_FROM_DATABASE=Pixel Velocity, Inc OUI:0021A3* ID_OUI_FROM_DATABASE=Micromint OUI:002199* ID_OUI_FROM_DATABASE=Vacon Plc OUI:002195* ID_OUI_FROM_DATABASE=GWD Media Limited OUI:002194* ID_OUI_FROM_DATABASE=Ping Communication OUI:00218F* ID_OUI_FROM_DATABASE=Avantgarde Acoustic Lautsprechersysteme GmbH OUI:002188* ID_OUI_FROM_DATABASE=EMC Corporation OUI:002182* ID_OUI_FROM_DATABASE=SandLinks Systems, Ltd. OUI:002175* ID_OUI_FROM_DATABASE=Pacific Satellite International Ltd. OUI:00222A* ID_OUI_FROM_DATABASE=SoundEar A/S OUI:00221E* ID_OUI_FROM_DATABASE=Media Devices Co., Ltd. OUI:002225* ID_OUI_FROM_DATABASE=Thales Avionics Ltd OUI:002218* ID_OUI_FROM_DATABASE=Verivue Inc. OUI:002212* ID_OUI_FROM_DATABASE=CAI Networks, Inc. OUI:00220B* ID_OUI_FROM_DATABASE=National Source Coding Center OUI:002205* ID_OUI_FROM_DATABASE=WeLink Solutions, Inc. OUI:002206* ID_OUI_FROM_DATABASE=Cyberdyne Inc. OUI:0022B3* ID_OUI_FROM_DATABASE=Sei S.p.A. OUI:0022AC* ID_OUI_FROM_DATABASE=Hangzhou Siyuan Tech. Co., Ltd OUI:0022A7* ID_OUI_FROM_DATABASE=Tyco Electronics AMP GmbH OUI:0022A0* ID_OUI_FROM_DATABASE=Delphi Corporation OUI:00229A* ID_OUI_FROM_DATABASE=Lastar, Inc. OUI:002299* ID_OUI_FROM_DATABASE=SeaMicro Inc. OUI:002294* ID_OUI_FROM_DATABASE=Kyocera Corporation OUI:0021FA* ID_OUI_FROM_DATABASE=A4SP Technologies Ltd. OUI:0021F4* ID_OUI_FROM_DATABASE=INRange Systems, Inc OUI:0021ED* ID_OUI_FROM_DATABASE=Telegesis OUI:0021E7* ID_OUI_FROM_DATABASE=Informatics Services Corporation OUI:0021DB* ID_OUI_FROM_DATABASE=Santachi Video Technology (Shenzhen) Co., Ltd. OUI:0021E1* ID_OUI_FROM_DATABASE=Nortel Networks OUI:0021D5* ID_OUI_FROM_DATABASE=X2E GmbH OUI:0021DA* ID_OUI_FROM_DATABASE=Automation Products Group Inc. OUI:0021CE* ID_OUI_FROM_DATABASE=NTC-Metrotek OUI:0021C8* ID_OUI_FROM_DATABASE=LOHUIS Networks OUI:0021C2* ID_OUI_FROM_DATABASE=GL Communications Inc OUI:0021BB* ID_OUI_FROM_DATABASE=Riken Keiki Co., Ltd. OUI:0021B5* ID_OUI_FROM_DATABASE=Galvanic Ltd OUI:0021AF* ID_OUI_FROM_DATABASE=Radio Frequency Systems OUI:0021B6* ID_OUI_FROM_DATABASE=Triacta Power Technologies Inc. OUI:0021A9* ID_OUI_FROM_DATABASE=Mobilink Telecom Co.,Ltd OUI:0021A8* ID_OUI_FROM_DATABASE=Telephonics Corporation OUI:00210D* ID_OUI_FROM_DATABASE=SAMSIN INNOTEC OUI:002141* ID_OUI_FROM_DATABASE=RADLIVE OUI:002137* ID_OUI_FROM_DATABASE=Bay Controls, LLC OUI:00212D* ID_OUI_FROM_DATABASE=SCIMOLEX CORPORATION OUI:002133* ID_OUI_FROM_DATABASE=Building B, Inc OUI:002121* ID_OUI_FROM_DATABASE=VRmagic GmbH OUI:002126* ID_OUI_FROM_DATABASE=Shenzhen Torch Equipment Co., Ltd. OUI:002257* ID_OUI_FROM_DATABASE=3COM EUROPE LTD OUI:00224E* ID_OUI_FROM_DATABASE=SEEnergy Corp. OUI:002247* ID_OUI_FROM_DATABASE=DAC ENGINEERING CO., LTD. OUI:00223D* ID_OUI_FROM_DATABASE=JumpGen Systems, LLC OUI:002237* ID_OUI_FROM_DATABASE=Shinhint Group OUI:002238* ID_OUI_FROM_DATABASE=LOGIPLUS OUI:002231* ID_OUI_FROM_DATABASE=SMT&C Co., Ltd. OUI:00222B* ID_OUI_FROM_DATABASE=Nucomm, Inc. OUI:001EF6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001EEA* ID_OUI_FROM_DATABASE=Sensor Switch, Inc. OUI:001EEF* ID_OUI_FROM_DATABASE=Cantronic International Limited OUI:001EDE* ID_OUI_FROM_DATABASE=BYD COMPANY LIMITED OUI:001EE3* ID_OUI_FROM_DATABASE=T&W Electronics (ShenZhen) Co.,Ltd OUI:001EDD* ID_OUI_FROM_DATABASE=WASKO S.A. OUI:001ED9* ID_OUI_FROM_DATABASE=Mitsubishi Precision Co.,LTd. OUI:001ED4* ID_OUI_FROM_DATABASE=Doble Engineering OUI:001ED3* ID_OUI_FROM_DATABASE=Dot Technology Int'l Co., Ltd. OUI:001ECD* ID_OUI_FROM_DATABASE=KYLAND Technology Co. LTD OUI:001EC6* ID_OUI_FROM_DATABASE=Obvius Holdings LLC OUI:001F9D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001FA2* ID_OUI_FROM_DATABASE=Datron World Communications, Inc. OUI:001F91* ID_OUI_FROM_DATABASE=DBS Lodging Technologies, LLC OUI:001F96* ID_OUI_FROM_DATABASE=APROTECH CO.LTD OUI:001F90* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:001F8F* ID_OUI_FROM_DATABASE=Shanghai Bellmann Digital Source Co.,Ltd. OUI:001F85* ID_OUI_FROM_DATABASE=Apriva ISS, LLC OUI:001F87* ID_OUI_FROM_DATABASE=Skydigital Inc. OUI:001F86* ID_OUI_FROM_DATABASE=digEcor OUI:001F80* ID_OUI_FROM_DATABASE=Lucas Holding bv OUI:001F3E* ID_OUI_FROM_DATABASE=RP-Technik e.K. OUI:001F42* ID_OUI_FROM_DATABASE=Etherstack plc OUI:001F41* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:001F39* ID_OUI_FROM_DATABASE=Construcciones y Auxiliar de Ferrocarriles, S.A. OUI:001F2B* ID_OUI_FROM_DATABASE=Orange Logic OUI:001F2C* ID_OUI_FROM_DATABASE=Starbridge Networks OUI:001F26* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001F1A* ID_OUI_FROM_DATABASE=Prominvest OUI:001EC1* ID_OUI_FROM_DATABASE=3COM EUROPE LTD OUI:001EBA* ID_OUI_FROM_DATABASE=High Density Devices AS OUI:001EB3* ID_OUI_FROM_DATABASE=Primex Wireless OUI:001EB4* ID_OUI_FROM_DATABASE=UNIFAT TECHNOLOGY LTD. OUI:001EAE* ID_OUI_FROM_DATABASE=Continental Automotive Systems OUI:001EA8* ID_OUI_FROM_DATABASE=Datang Mobile Communications Equipment CO.,LTD OUI:001E9C* ID_OUI_FROM_DATABASE=Fidustron INC OUI:001E95* ID_OUI_FROM_DATABASE=SIGMALINK OUI:001E96* ID_OUI_FROM_DATABASE=Sepura Plc OUI:001E8B* ID_OUI_FROM_DATABASE=Infra Access Korea Co., Ltd. OUI:001FEF* ID_OUI_FROM_DATABASE=SHINSEI INDUSTRIES CO.,LTD OUI:001FE8* ID_OUI_FROM_DATABASE=KURUSUGAWA Electronics Industry Inc,. OUI:001FDC* ID_OUI_FROM_DATABASE=Mobile Safe Track Ltd OUI:001FE3* ID_OUI_FROM_DATABASE=LG Electronics OUI:001FD7* ID_OUI_FROM_DATABASE=TELERAD SA OUI:001FCC* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:001FCB* ID_OUI_FROM_DATABASE=NIW Solutions OUI:001FCD* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:001F77* ID_OUI_FROM_DATABASE=HEOL DESIGN OUI:001F73* ID_OUI_FROM_DATABASE=Teraview Technology Co., Ltd. OUI:001F6D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001F61* ID_OUI_FROM_DATABASE=Talent Communication Networks Inc. OUI:001F66* ID_OUI_FROM_DATABASE=PLANAR LLC OUI:001F5A* ID_OUI_FROM_DATABASE=Beckwith Electric Co. OUI:001F53* ID_OUI_FROM_DATABASE=GEMAC Gesellschaft für Mikroelektronikanwendung Chemnitz mbH OUI:001F4E* ID_OUI_FROM_DATABASE=ConMed Linvatec OUI:001F54* ID_OUI_FROM_DATABASE=Lorex Technology Inc. OUI:001F47* ID_OUI_FROM_DATABASE=MCS Logic Inc. OUI:001FD2* ID_OUI_FROM_DATABASE=COMMTECH TECHNOLOGY MACAO COMMERCIAL OFFSHORE LTD. OUI:001FBF* ID_OUI_FROM_DATABASE=Fulhua Microelectronics Corp. Taiwan Branch OUI:001FBA* ID_OUI_FROM_DATABASE=BoYoung Tech. & Marketing, Inc. OUI:001FAC* ID_OUI_FROM_DATABASE=Goodmill Systems Ltd OUI:00211A* ID_OUI_FROM_DATABASE=LInTech Corporation OUI:002113* ID_OUI_FROM_DATABASE=Padtec S/A OUI:002114* ID_OUI_FROM_DATABASE=Hylab Technology Inc. OUI:00210E* ID_OUI_FROM_DATABASE=Orpak Systems L.T.D. OUI:00210A* ID_OUI_FROM_DATABASE=byd:sign Corporation OUI:002104* ID_OUI_FROM_DATABASE=Gigaset Communications GmbH OUI:001FFB* ID_OUI_FROM_DATABASE=Green Packet Bhd OUI:001FF6* ID_OUI_FROM_DATABASE=PS Audio International OUI:001F19* ID_OUI_FROM_DATABASE=BEN-RI ELECTRONICA S.A. OUI:001F13* ID_OUI_FROM_DATABASE=S.& A.S. Ltd. OUI:001F0F* ID_OUI_FROM_DATABASE=Select Engineered Systems OUI:001EFD* ID_OUI_FROM_DATABASE=Microbit 2.0 AB OUI:001F02* ID_OUI_FROM_DATABASE=Pixelmetrix Corporation Pte Ltd OUI:001EF0* ID_OUI_FROM_DATABASE=Gigafin Networks OUI:001D2C* ID_OUI_FROM_DATABASE=Wavetrend Technologies (Pty) Limited OUI:001D27* ID_OUI_FROM_DATABASE=NAC-INTERCOM OUI:001D18* ID_OUI_FROM_DATABASE=Power Innovation GmbH OUI:001D13* ID_OUI_FROM_DATABASE=NextGTV OUI:001D0C* ID_OUI_FROM_DATABASE=MobileCompia OUI:001D06* ID_OUI_FROM_DATABASE=HM Electronics, Inc. OUI:001D05* ID_OUI_FROM_DATABASE=Eaton Corporation OUI:001E62* ID_OUI_FROM_DATABASE=Siemon OUI:001E5D* ID_OUI_FROM_DATABASE=Holosys d.o.o. OUI:001E56* ID_OUI_FROM_DATABASE=Bally Wulff Entertainment GmbH OUI:001E50* ID_OUI_FROM_DATABASE=BATTISTONI RESEARCH OUI:001E4A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001E40* ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co.,Ltd. OUI:001D85* ID_OUI_FROM_DATABASE=Call Direct Cellular Solutions OUI:001D80* ID_OUI_FROM_DATABASE=Beijing Huahuan Eletronics Co.,Ltd OUI:001D68* ID_OUI_FROM_DATABASE=Thomson Telecom Belgium OUI:001D6F* ID_OUI_FROM_DATABASE=Chainzone Technology Co., Ltd OUI:001D76* ID_OUI_FROM_DATABASE=Eyeheight Ltd. OUI:001D7B* ID_OUI_FROM_DATABASE=Ice Energy, Inc. OUI:001D75* ID_OUI_FROM_DATABASE=Radioscape PLC OUI:001D63* ID_OUI_FROM_DATABASE=Miele & Cie. KG OUI:001D5C* ID_OUI_FROM_DATABASE=Tom Communication Industrial Co.,Ltd. OUI:001D55* ID_OUI_FROM_DATABASE=ZANTAZ, Inc OUI:001DC8* ID_OUI_FROM_DATABASE=Navionics Research Inc., dba SCADAmetrics OUI:001DC1* ID_OUI_FROM_DATABASE=Audinate Pty L OUI:001DBB* ID_OUI_FROM_DATABASE=Dynamic System Electronics Corp. OUI:001DAB* ID_OUI_FROM_DATABASE=SwissQual License AG OUI:001E86* ID_OUI_FROM_DATABASE=MEL Co.,Ltd. OUI:001E7F* ID_OUI_FROM_DATABASE=CBM of America OUI:001E7A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001E79* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001E75* ID_OUI_FROM_DATABASE=LG Electronics OUI:001E6F* ID_OUI_FROM_DATABASE=Magna-Power Electronics, Inc. OUI:001E70* ID_OUI_FROM_DATABASE=Cobham Defence Communications Ltd OUI:001E69* ID_OUI_FROM_DATABASE=Thomson Inc. OUI:001D56* ID_OUI_FROM_DATABASE=Kramer Electronics Ltd. OUI:001D50* ID_OUI_FROM_DATABASE=SPINETIX SA OUI:001D4B* ID_OUI_FROM_DATABASE=Grid Connect Inc. OUI:001D46* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001D3F* ID_OUI_FROM_DATABASE=Mitron Pty Ltd OUI:001D39* ID_OUI_FROM_DATABASE=MOOHADIGITAL CO., LTD OUI:001D3A* ID_OUI_FROM_DATABASE=mh acoustics LLC OUI:001D33* ID_OUI_FROM_DATABASE=Maverick Systems Inc. OUI:001E09* ID_OUI_FROM_DATABASE=ZEFATEK Co.,LTD OUI:001E04* ID_OUI_FROM_DATABASE=Hanson Research Corporation OUI:001DF7* ID_OUI_FROM_DATABASE=R. STAHL Schaltgeräte GmbH OUI:001DF8* ID_OUI_FROM_DATABASE=Webpro Vision Technology Corporation OUI:001DF1* ID_OUI_FROM_DATABASE=Intego Systems, Inc. OUI:001DEA* ID_OUI_FROM_DATABASE=Commtest Instruments Ltd OUI:001DDB* ID_OUI_FROM_DATABASE=C-BEL Corporation OUI:001DE5* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001DA4* ID_OUI_FROM_DATABASE=Hangzhou System Technology CO., LTD OUI:001D9F* ID_OUI_FROM_DATABASE=MATT R.P.Traczynscy Sp.J. OUI:001D92* ID_OUI_FROM_DATABASE=MICRO-STAR INT'L CO.,LTD. OUI:001D91* ID_OUI_FROM_DATABASE=Digitize, Inc OUI:001D8C* ID_OUI_FROM_DATABASE=La Crosse Technology LTD OUI:001E39* ID_OUI_FROM_DATABASE=Comsys Communication Ltd. OUI:001E34* ID_OUI_FROM_DATABASE=CryptoMetrics OUI:001E2D* ID_OUI_FROM_DATABASE=STIM OUI:001E26* ID_OUI_FROM_DATABASE=Digifriends Co. Ltd OUI:001E21* ID_OUI_FROM_DATABASE=Qisda Co. OUI:001E1A* ID_OUI_FROM_DATABASE=Best Source Taiwan Inc. OUI:001E14* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001E0A* ID_OUI_FROM_DATABASE=Syba Tech Limited OUI:001C61* ID_OUI_FROM_DATABASE=Galaxy Microsystems LImited OUI:001C55* ID_OUI_FROM_DATABASE=Shenzhen Kaifa Technology Co. OUI:001C5A* ID_OUI_FROM_DATABASE=Advanced Relay Corporation OUI:001C44* ID_OUI_FROM_DATABASE=Bosch Security Systems BV OUI:001C4B* ID_OUI_FROM_DATABASE=Gener8, Inc. OUI:001C38* ID_OUI_FROM_DATABASE=Bio-Rad Laboratories, Inc. OUI:001C3D* ID_OUI_FROM_DATABASE=WaveStorm OUI:001C3F* ID_OUI_FROM_DATABASE=International Police Technologies, Inc. OUI:001C3E* ID_OUI_FROM_DATABASE=ECKey Corporation OUI:001C31* ID_OUI_FROM_DATABASE=Mobile XP Technology Co., LTD OUI:001C2C* ID_OUI_FROM_DATABASE=Synapse OUI:001CF9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001CF3* ID_OUI_FROM_DATABASE=EVS BROADCAST EQUIPMENT OUI:001CF4* ID_OUI_FROM_DATABASE=Media Technology Systems Inc OUI:001CED* ID_OUI_FROM_DATABASE=ENVIRONNEMENT SA OUI:001CE3* ID_OUI_FROM_DATABASE=Optimedical Systems OUI:001CDC* ID_OUI_FROM_DATABASE=Custom Computer Services, Inc. OUI:001CD0* ID_OUI_FROM_DATABASE=Circleone Co.,Ltd. OUI:001BF5* ID_OUI_FROM_DATABASE=Tellink Sistemas de Telecomunicación S.L. OUI:001BF0* ID_OUI_FROM_DATABASE=Value Platforms Limited OUI:001BE8* ID_OUI_FROM_DATABASE=Ultratronik GmbH OUI:001BE1* ID_OUI_FROM_DATABASE=ViaLogy OUI:001BDC* ID_OUI_FROM_DATABASE=Vencer Co., Ltd. OUI:001BD5* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001BCE* ID_OUI_FROM_DATABASE=Measurement Devices Ltd OUI:001C94* ID_OUI_FROM_DATABASE=LI-COR Biosciences OUI:001C8E* ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD OUI:001C8D* ID_OUI_FROM_DATABASE=Mesa Imaging OUI:001C88* ID_OUI_FROM_DATABASE=TRANSYSTEM INC. OUI:001C7E* ID_OUI_FROM_DATABASE=Toshiba OUI:001C83* ID_OUI_FROM_DATABASE=New Level Telecom Co., Ltd. OUI:001C7A* ID_OUI_FROM_DATABASE=Perfectone Netware Company Ltd OUI:001C7B* ID_OUI_FROM_DATABASE=Castlenet Technology Inc. OUI:001C79* ID_OUI_FROM_DATABASE=Cohesive Financial Technologies LLC OUI:001C74* ID_OUI_FROM_DATABASE=Syswan Technologies Inc. OUI:001C6D* ID_OUI_FROM_DATABASE=KYOHRITSU ELECTRONIC INDUSTRY CO., LTD. OUI:001C68* ID_OUI_FROM_DATABASE=Anhui Sun Create Electronics Co., Ltd OUI:001CC9* ID_OUI_FROM_DATABASE=Kaise Electronic Technology Co., Ltd. OUI:001CCA* ID_OUI_FROM_DATABASE=Shanghai Gaozhi Science & Technology Development Co. OUI:001CBD* ID_OUI_FROM_DATABASE=Ezze Mobile Tech., Inc. OUI:001CB8* ID_OUI_FROM_DATABASE=CBC Co., Ltd OUI:001CAD* ID_OUI_FROM_DATABASE=Wuhan Telecommunication Devices Co.,Ltd OUI:001CAE* ID_OUI_FROM_DATABASE=WiChorus, Inc. OUI:001CA7* ID_OUI_FROM_DATABASE=International Quartz Limited OUI:001CA0* ID_OUI_FROM_DATABASE=Production Resource Group, LLC OUI:001C9B* ID_OUI_FROM_DATABASE=FEIG ELECTRONIC GmbH OUI:001B69* ID_OUI_FROM_DATABASE=Equaline Corporation OUI:001B64* ID_OUI_FROM_DATABASE=IsaacLandKorea Co., Ltd, OUI:001B5D* ID_OUI_FROM_DATABASE=Vololink Pty Ltd OUI:001B56* ID_OUI_FROM_DATABASE=Tehuti Networks Ltd. OUI:001B51* ID_OUI_FROM_DATABASE=Vector Technology Corp. OUI:001B45* ID_OUI_FROM_DATABASE=ABB AS, Division Automation Products OUI:001B4A* ID_OUI_FROM_DATABASE=W&W Communications, Inc. OUI:001B43* ID_OUI_FROM_DATABASE=Beijing DG Telecommunications equipment Co.,Ltd OUI:001B3E* ID_OUI_FROM_DATABASE=Curtis, Inc. OUI:001B37* ID_OUI_FROM_DATABASE=Computec Oy OUI:001B32* ID_OUI_FROM_DATABASE=QLogic Corporation OUI:001B2B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001BC9* ID_OUI_FROM_DATABASE=FSN DISPLAY INC OUI:001BC2* ID_OUI_FROM_DATABASE=Integrated Control Technology Limitied OUI:001BBC* ID_OUI_FROM_DATABASE=Silver Peak Systems, Inc. OUI:001BBD* ID_OUI_FROM_DATABASE=FMC Kongsberg Subsea AS OUI:001BB3* ID_OUI_FROM_DATABASE=Condalo GmbH OUI:001BB8* ID_OUI_FROM_DATABASE=BLUEWAY ELECTRONIC CO;LTD OUI:001BAC* ID_OUI_FROM_DATABASE=Curtiss Wright Controls Embedded Computing OUI:001BB1* ID_OUI_FROM_DATABASE=Wistron Neweb Corp. OUI:001BB2* ID_OUI_FROM_DATABASE=Intellect International NV OUI:001BA5* ID_OUI_FROM_DATABASE=MyungMin Systems, Inc. OUI:001BA0* ID_OUI_FROM_DATABASE=Awox OUI:001B99* ID_OUI_FROM_DATABASE=KS System GmbH OUI:001C14* ID_OUI_FROM_DATABASE=VMware, Inc OUI:001C1B* ID_OUI_FROM_DATABASE=Hyperstone GmbH OUI:001C0F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001C08* ID_OUI_FROM_DATABASE=Echo360, Inc. OUI:001C02* ID_OUI_FROM_DATABASE=Pano Logic OUI:001C01* ID_OUI_FROM_DATABASE=ABB Oy Drives OUI:001C03* ID_OUI_FROM_DATABASE=Betty TV Technology AG OUI:001B92* ID_OUI_FROM_DATABASE=l-acoustics OUI:001B8D* ID_OUI_FROM_DATABASE=Electronic Computer Systems, Inc. OUI:001B88* ID_OUI_FROM_DATABASE=Divinet Access Technologies Ltd OUI:001B83* ID_OUI_FROM_DATABASE=Finsoft Ltd OUI:001B7C* ID_OUI_FROM_DATABASE=A & R Cambridge OUI:001B76* ID_OUI_FROM_DATABASE=Ripcode, Inc. OUI:001B75* ID_OUI_FROM_DATABASE=Hypermedia Systems OUI:001B70* ID_OUI_FROM_DATABASE=IRI Ubiteq, INC. OUI:001A18* ID_OUI_FROM_DATABASE=Advanced Simulation Technology inc. OUI:001A0A* ID_OUI_FROM_DATABASE=Adaptive Micro-Ware Inc. OUI:001A05* ID_OUI_FROM_DATABASE=OPTIBASE LTD OUI:001A03* ID_OUI_FROM_DATABASE=Angel Electronics Co., Ltd. OUI:0019FE* ID_OUI_FROM_DATABASE=SHENZHEN SEECOMM TECHNOLOGY CO.,LTD. OUI:0019F9* ID_OUI_FROM_DATABASE=TDK-Lambda OUI:0019ED* ID_OUI_FROM_DATABASE=Axesstel Inc. OUI:0019F4* ID_OUI_FROM_DATABASE=Convergens Oy Ltd OUI:001A79* ID_OUI_FROM_DATABASE=TELECOMUNICATION TECHNOLOGIES LTD. OUI:001A99* ID_OUI_FROM_DATABASE=Smarty (HZ) Information Electronics Co., Ltd OUI:001A9B* ID_OUI_FROM_DATABASE=ADEC & Parter AG OUI:001A8A* ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. OUI:001A8F* ID_OUI_FROM_DATABASE=Nortel OUI:001A94* ID_OUI_FROM_DATABASE=Votronic GmbH OUI:001A83* ID_OUI_FROM_DATABASE=Pegasus Technologies Inc. OUI:001A7E* ID_OUI_FROM_DATABASE=LN Srithai Comm Ltd. OUI:001AF1* ID_OUI_FROM_DATABASE=Embedded Artists AB OUI:001AF6* ID_OUI_FROM_DATABASE=Woven Systems, Inc. OUI:001AEC* ID_OUI_FROM_DATABASE=Keumbee Electronics Co.,Ltd. OUI:001AE0* ID_OUI_FROM_DATABASE=Mythology Tech Express Inc. OUI:001AE5* ID_OUI_FROM_DATABASE=Mvox Technologies Inc. OUI:001AD2* ID_OUI_FROM_DATABASE=Eletronica Nitron Ltda OUI:001AD9* ID_OUI_FROM_DATABASE=International Broadband Electric Communications, Inc. OUI:001ACB* ID_OUI_FROM_DATABASE=Autocom Products Ltd OUI:001ACD* ID_OUI_FROM_DATABASE=Tidel Engineering LP OUI:001A46* ID_OUI_FROM_DATABASE=Digital Multimedia Technology Co., Ltd OUI:001A3A* ID_OUI_FROM_DATABASE=Dongahelecomm OUI:001A3F* ID_OUI_FROM_DATABASE=intelbras OUI:001A41* ID_OUI_FROM_DATABASE=INOCOVA Co.,Ltd OUI:001A2E* ID_OUI_FROM_DATABASE=Ziova Coporation OUI:001A33* ID_OUI_FROM_DATABASE=ASI Communications, Inc. OUI:001A1D* ID_OUI_FROM_DATABASE=PChome Online Inc. OUI:001A24* ID_OUI_FROM_DATABASE=Galaxy Telecom Technologies Ltd OUI:0019A5* ID_OUI_FROM_DATABASE=RadarFind Corporation OUI:0019AC* ID_OUI_FROM_DATABASE=GSP SYSTEMS Inc. OUI:0019B1* ID_OUI_FROM_DATABASE=Arrow7 Corporation OUI:00199E* ID_OUI_FROM_DATABASE=Nifty OUI:0019A0* ID_OUI_FROM_DATABASE=NIHON DATA SYSTENS, INC. OUI:001994* ID_OUI_FROM_DATABASE=Jorjin Technologies Inc. OUI:00198F* ID_OUI_FROM_DATABASE=Alcatel Bell N.V. OUI:0019E1* ID_OUI_FROM_DATABASE=Nortel OUI:0019E8* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0019DA* ID_OUI_FROM_DATABASE=Welltrans O&E Technology Co. , Ltd. OUI:0019DC* ID_OUI_FROM_DATABASE=ENENSYS Technologies OUI:0019C9* ID_OUI_FROM_DATABASE=S&C ELECTRIC COMPANY OUI:0019CE* ID_OUI_FROM_DATABASE=Progressive Gaming International OUI:0019D5* ID_OUI_FROM_DATABASE=IP Innovations, Inc. OUI:0019C4* ID_OUI_FROM_DATABASE=Infocrypt Inc. OUI:0019BF* ID_OUI_FROM_DATABASE=Citiway technology Co.,ltd OUI:0019BD* ID_OUI_FROM_DATABASE=New Media Life OUI:0019B8* ID_OUI_FROM_DATABASE=Boundary Devices OUI:001B26* ID_OUI_FROM_DATABASE=RON-Telecom ZAO OUI:001B1C* ID_OUI_FROM_DATABASE=Coherent OUI:001B1A* ID_OUI_FROM_DATABASE=e-trees Japan, Inc. OUI:001B15* ID_OUI_FROM_DATABASE=Voxtel, Inc. OUI:001B09* ID_OUI_FROM_DATABASE=Matrix Telecom Pvt. Ltd. OUI:001B0E* ID_OUI_FROM_DATABASE=InoTec GmbH Organisationssysteme OUI:001B07* ID_OUI_FROM_DATABASE=Mendocino Software OUI:001B02* ID_OUI_FROM_DATABASE=ED Co.Ltd OUI:001AFB* ID_OUI_FROM_DATABASE=Joby Inc. OUI:001A74* ID_OUI_FROM_DATABASE=Procare International Co OUI:001A6D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001A68* ID_OUI_FROM_DATABASE=Weltec Enterprise Co., Ltd. OUI:001A61* ID_OUI_FROM_DATABASE=PacStar Corp. OUI:001A54* ID_OUI_FROM_DATABASE=Hip Shing Electronics Ltd. OUI:001A59* ID_OUI_FROM_DATABASE=Ircona OUI:001A4D* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:001A52* ID_OUI_FROM_DATABASE=Meshlinx Wireless Inc. OUI:001AC6* ID_OUI_FROM_DATABASE=Micro Control Designs OUI:001ABC* ID_OUI_FROM_DATABASE=U4EA Technologies Ltd OUI:001AC1* ID_OUI_FROM_DATABASE=3Com Ltd OUI:001AB0* ID_OUI_FROM_DATABASE=Signal Networks Pvt. Ltd., OUI:001AB5* ID_OUI_FROM_DATABASE=Home Network System OUI:001AA9* ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD OUI:00183C* ID_OUI_FROM_DATABASE=Encore Software Limited OUI:001841* ID_OUI_FROM_DATABASE=High Tech Computer Corp OUI:001843* ID_OUI_FROM_DATABASE=Dawevision Ltd OUI:001837* ID_OUI_FROM_DATABASE=Universal ABIT Co., Ltd. OUI:001826* ID_OUI_FROM_DATABASE=Cale Access AB OUI:00182B* ID_OUI_FROM_DATABASE=Softier OUI:001818* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00181A* ID_OUI_FROM_DATABASE=AVerMedia Information Inc. OUI:00181F* ID_OUI_FROM_DATABASE=Palmmicro Communications OUI:001804* ID_OUI_FROM_DATABASE=E-TEK DIGITAL TECHNOLOGY LIMITED OUI:001807* ID_OUI_FROM_DATABASE=Fanstel Corp. OUI:00180C* ID_OUI_FROM_DATABASE=Optelian Access Networks OUI:0017FF* ID_OUI_FROM_DATABASE=PLAYLINE Co.,Ltd. OUI:0017F1* ID_OUI_FROM_DATABASE=Renu Electronics Pvt Ltd OUI:0017F3* ID_OUI_FROM_DATABASE=Harris Corparation OUI:0017F8* ID_OUI_FROM_DATABASE=Motech Industries Inc. OUI:0017D4* ID_OUI_FROM_DATABASE=Monsoon Multimedia, Inc OUI:0017D9* ID_OUI_FROM_DATABASE=AAI Corporation OUI:0017E0* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001920* ID_OUI_FROM_DATABASE=KUME electric Co.,Ltd. OUI:001925* ID_OUI_FROM_DATABASE=Intelicis Corporation OUI:001912* ID_OUI_FROM_DATABASE=Welcat Inc OUI:001914* ID_OUI_FROM_DATABASE=Winix Co., Ltd OUI:001919* ID_OUI_FROM_DATABASE=ASTEL Inc. OUI:00190D* ID_OUI_FROM_DATABASE=IEEE 1394c OUI:001901* ID_OUI_FROM_DATABASE=F1MEDIA OUI:001906* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0018F5* ID_OUI_FROM_DATABASE=Shenzhen Streaming Video Technology Company Limited OUI:0018F7* ID_OUI_FROM_DATABASE=Kameleon Technologies OUI:0018FC* ID_OUI_FROM_DATABASE=Altec Electronic AG OUI:001981* ID_OUI_FROM_DATABASE=Vivox Inc OUI:001983* ID_OUI_FROM_DATABASE=CCT R&D Limited OUI:001988* ID_OUI_FROM_DATABASE=Wi2Wi, Inc OUI:001975* ID_OUI_FROM_DATABASE=Beijing Huisen networks technology Inc OUI:00197C* ID_OUI_FROM_DATABASE=Riedel Communications GmbH OUI:001969* ID_OUI_FROM_DATABASE=Nortel OUI:001970* ID_OUI_FROM_DATABASE=Z-Com, Inc. OUI:001964* ID_OUI_FROM_DATABASE=Doorking Inc. OUI:00195F* ID_OUI_FROM_DATABASE=Valemount Networks Corporation OUI:001953* ID_OUI_FROM_DATABASE=Chainleader Communications Corp. OUI:001958* ID_OUI_FROM_DATABASE=Bluetooth SIG, Inc. OUI:00195A* ID_OUI_FROM_DATABASE=Jenaer Antriebstechnik GmbH OUI:0018F0* ID_OUI_FROM_DATABASE=JOYTOTO Co., Ltd. OUI:0018E9* ID_OUI_FROM_DATABASE=Numata Corporation OUI:0018E4* ID_OUI_FROM_DATABASE=YIGUANG OUI:0018DD* ID_OUI_FROM_DATABASE=Silicondust Engineering Ltd OUI:0018D8* ID_OUI_FROM_DATABASE=ARCH METER Corporation OUI:0018D1* ID_OUI_FROM_DATABASE=Siemens Home & Office Comm. Devices OUI:0018D6* ID_OUI_FROM_DATABASE=Swirlnet A/S OUI:0018CC* ID_OUI_FROM_DATABASE=AXIOHM SAS OUI:0018C7* ID_OUI_FROM_DATABASE=Real Time Automation OUI:00186C* ID_OUI_FROM_DATABASE=Neonode AB OUI:001878* ID_OUI_FROM_DATABASE=Mackware GmbH OUI:001867* ID_OUI_FROM_DATABASE=Datalogic ADC OUI:00185B* ID_OUI_FROM_DATABASE=Network Chemistry, Inc OUI:001862* ID_OUI_FROM_DATABASE=Seagate Technology OUI:00184F* ID_OUI_FROM_DATABASE=8 Ways Technology Corp. OUI:001854* ID_OUI_FROM_DATABASE=Argard Co., Ltd OUI:001856* ID_OUI_FROM_DATABASE=EyeFi, Inc OUI:001848* ID_OUI_FROM_DATABASE=Vecima Networks Inc. OUI:001945* ID_OUI_FROM_DATABASE=RF COncepts, LLC OUI:00194C* ID_OUI_FROM_DATABASE=Fujian Stelcom information & Technology CO.,Ltd OUI:001940* ID_OUI_FROM_DATABASE=Rackable Systems OUI:001934* ID_OUI_FROM_DATABASE=TRENDON TOUCH TECHNOLOGY CORP. OUI:001939* ID_OUI_FROM_DATABASE=Gigamips OUI:001931* ID_OUI_FROM_DATABASE=Balluff GmbH OUI:0018BB* ID_OUI_FROM_DATABASE=Eliwell Controls srl OUI:0018B9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0018B4* ID_OUI_FROM_DATABASE=Dawon Media Inc. OUI:0018AD* ID_OUI_FROM_DATABASE=NIDEC SANKYO CORPORATION OUI:0018A8* ID_OUI_FROM_DATABASE=AnNeal Technology Inc. OUI:00189C* ID_OUI_FROM_DATABASE=Weldex Corporation OUI:0018A1* ID_OUI_FROM_DATABASE=Tiqit Computers, Inc. OUI:001897* ID_OUI_FROM_DATABASE=JESS-LINK PRODUCTS Co., LTD OUI:001892* ID_OUI_FROM_DATABASE=ads-tec GmbH OUI:001890* ID_OUI_FROM_DATABASE=RadioCOM, s.r.o. OUI:001884* ID_OUI_FROM_DATABASE=Fon Technology S.L. OUI:00187D* ID_OUI_FROM_DATABASE=Armorlink shanghai Co. Ltd OUI:00187F* ID_OUI_FROM_DATABASE=ZODIANET OUI:0016D1* ID_OUI_FROM_DATABASE=ZAT a.s. OUI:0016C3* ID_OUI_FROM_DATABASE=BA Systems Inc OUI:0016CA* ID_OUI_FROM_DATABASE=Nortel OUI:0016BE* ID_OUI_FROM_DATABASE=INFRANET, Inc. OUI:0016B7* ID_OUI_FROM_DATABASE=Seoul Commtech OUI:0016B2* ID_OUI_FROM_DATABASE=DriveCam Inc OUI:0016B0* ID_OUI_FROM_DATABASE=VK Corporation OUI:0016AB* ID_OUI_FROM_DATABASE=Dansensor A/S OUI:0016A6* ID_OUI_FROM_DATABASE=Dovado FZ-LLC OUI:0017C8* ID_OUI_FROM_DATABASE=KYOCERA Document Solutions Inc. OUI:0017CA* ID_OUI_FROM_DATABASE=Qisda Corporation OUI:0017CF* ID_OUI_FROM_DATABASE=iMCA-GmbH OUI:0017C3* ID_OUI_FROM_DATABASE=KTF Technologies Inc. OUI:0017B7* ID_OUI_FROM_DATABASE=Tonze Technology Co. OUI:0017BC* ID_OUI_FROM_DATABASE=Touchtunes Music Corporation OUI:0017B5* ID_OUI_FROM_DATABASE=Peerless Systems Corporation OUI:001723* ID_OUI_FROM_DATABASE=Summit Data Communications OUI:00171C* ID_OUI_FROM_DATABASE=NT MicroSystems, Inc. OUI:001710* ID_OUI_FROM_DATABASE=Casa Systems Inc. OUI:001715* ID_OUI_FROM_DATABASE=Qstik OUI:001717* ID_OUI_FROM_DATABASE=Leica Geosystems AG OUI:00170B* ID_OUI_FROM_DATABASE=Contela, Inc. OUI:0016FF* ID_OUI_FROM_DATABASE=Wamin Optocomm Mfg Corp OUI:001774* ID_OUI_FROM_DATABASE=Elesta GmbH OUI:001779* ID_OUI_FROM_DATABASE=QuickTel OUI:00177B* ID_OUI_FROM_DATABASE=Azalea Networks inc OUI:001764* ID_OUI_FROM_DATABASE=ATMedia GmbH OUI:001766* ID_OUI_FROM_DATABASE=Accense Technology, Inc. OUI:00175F* ID_OUI_FROM_DATABASE=XENOLINK Communications Co., Ltd. OUI:001751* ID_OUI_FROM_DATABASE=Online Corporation OUI:001753* ID_OUI_FROM_DATABASE=nFore Technology Inc. OUI:001758* ID_OUI_FROM_DATABASE=ThruVision Ltd OUI:001745* ID_OUI_FROM_DATABASE=INNOTZ CO., Ltd OUI:00174C* ID_OUI_FROM_DATABASE=Millipore OUI:00179F* ID_OUI_FROM_DATABASE=Apricorn OUI:0017A9* ID_OUI_FROM_DATABASE=Sentivision OUI:001793* ID_OUI_FROM_DATABASE=Tigi Corporation OUI:00178C* ID_OUI_FROM_DATABASE=Independent Witness, Inc OUI:00178E* ID_OUI_FROM_DATABASE=Gunnebo Cash Automation AB OUI:001780* ID_OUI_FROM_DATABASE=Applied Biosystems B.V. OUI:001787* ID_OUI_FROM_DATABASE=Brother, Brother & Sons ApS OUI:00176B* ID_OUI_FROM_DATABASE=Kiyon, Inc. OUI:00BAC0* ID_OUI_FROM_DATABASE=Biometric Access Company OUI:001673* ID_OUI_FROM_DATABASE=Bury GmbH & Co. KG OUI:001671* ID_OUI_FROM_DATABASE=Symphox Information Co. OUI:001665* ID_OUI_FROM_DATABASE=Cellon France OUI:00166A* ID_OUI_FROM_DATABASE=TPS OUI:00165E* ID_OUI_FROM_DATABASE=Precision I/O OUI:001657* ID_OUI_FROM_DATABASE=Aegate Ltd OUI:001659* ID_OUI_FROM_DATABASE=Z.M.P. RADWAG OUI:001658* ID_OUI_FROM_DATABASE=Fusiontech Technologies Inc. OUI:001652* ID_OUI_FROM_DATABASE=Hoatech Technologies, Inc. OUI:001646* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00164B* ID_OUI_FROM_DATABASE=Quorion Data Systems GmbH OUI:001740* ID_OUI_FROM_DATABASE=Bluberi Gaming Technologies Inc OUI:001736* ID_OUI_FROM_DATABASE=iiTron Inc. OUI:00172F* ID_OUI_FROM_DATABASE=NeuLion Incorporated OUI:001728* ID_OUI_FROM_DATABASE=Selex Communications OUI:00172A* ID_OUI_FROM_DATABASE=Proware Technology Corp.(By Unifosa) OUI:00169A* ID_OUI_FROM_DATABASE=Quadrics Ltd OUI:0016A1* ID_OUI_FROM_DATABASE=3Leaf Networks OUI:001693* ID_OUI_FROM_DATABASE=PowerLink Technology Inc. OUI:001695* ID_OUI_FROM_DATABASE=AVC Technology (International) Limited OUI:00168E* ID_OUI_FROM_DATABASE=Vimicro corporation OUI:001682* ID_OUI_FROM_DATABASE=Pro Dex, Inc OUI:001687* ID_OUI_FROM_DATABASE=Chubb CSC-Vendor AP OUI:00167B* ID_OUI_FROM_DATABASE=Haver&Boecker OUI:0016F3* ID_OUI_FROM_DATABASE=CAST Information Co., Ltd OUI:0016EE* ID_OUI_FROM_DATABASE=Royaldigital Inc. OUI:0016E7* ID_OUI_FROM_DATABASE=Dynamix Promotions Limited OUI:0016DB* ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. OUI:0016E0* ID_OUI_FROM_DATABASE=3Com Ltd OUI:0016D6* ID_OUI_FROM_DATABASE=TDA Tech Pty Ltd OUI:00151E* ID_OUI_FROM_DATABASE=Ethernet Powerlink Standardization Group (EPSG) OUI:001525* ID_OUI_FROM_DATABASE=Chamberlain Access Solutions OUI:001519* ID_OUI_FROM_DATABASE=StoreAge Networking Technologies OUI:001518* ID_OUI_FROM_DATABASE=Shenzhen 10MOONS Technology Development CO.,Ltd OUI:001514* ID_OUI_FROM_DATABASE=Hu Zhou NAVA Networks&Electronics Ltd. OUI:00150E* ID_OUI_FROM_DATABASE=OPENBRAIN TECHNOLOGIES CO., LTD. OUI:00150F* ID_OUI_FROM_DATABASE=mingjong OUI:00150D* ID_OUI_FROM_DATABASE=Hoana Medical, Inc. OUI:001508* ID_OUI_FROM_DATABASE=Global Target Enterprise Inc OUI:0014FC* ID_OUI_FROM_DATABASE=Extandon, Inc. OUI:001501* ID_OUI_FROM_DATABASE=LexBox OUI:0014F5* ID_OUI_FROM_DATABASE=OSI Security Devices OUI:0014E9* ID_OUI_FROM_DATABASE=Nortech International OUI:0014EE* ID_OUI_FROM_DATABASE=Western Digital Technologies, Inc. OUI:0014DF* ID_OUI_FROM_DATABASE=HI-P Tech Corporation OUI:0014E4* ID_OUI_FROM_DATABASE=infinias, LLC OUI:0014D3* ID_OUI_FROM_DATABASE=SEPSA OUI:0014D8* ID_OUI_FROM_DATABASE=bio-logic SA OUI:0014D2* ID_OUI_FROM_DATABASE=Kyuden Technosystems Corporation OUI:0015E0* ID_OUI_FROM_DATABASE=Ericsson OUI:0015DC* ID_OUI_FROM_DATABASE=KT&C Co., Ltd. OUI:0015D5* ID_OUI_FROM_DATABASE=NICEVT OUI:0015D7* ID_OUI_FROM_DATABASE=Reti Corporation OUI:0015D6* ID_OUI_FROM_DATABASE=OSLiNK Sp. z o.o. OUI:0015C4* ID_OUI_FROM_DATABASE=FLOVEL CO., LTD. OUI:0015C9* ID_OUI_FROM_DATABASE=Gumstix, Inc OUI:0015BD* ID_OUI_FROM_DATABASE=Group 4 Technology Ltd OUI:0015B6* ID_OUI_FROM_DATABASE=ShinMaywa Industries, Ltd. OUI:001581* ID_OUI_FROM_DATABASE=MAKUS Inc. OUI:00156B* ID_OUI_FROM_DATABASE=Perfisans Networks Corp. OUI:001570* ID_OUI_FROM_DATABASE=Zebra Technologies Inc OUI:00155D* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:00155F* ID_OUI_FROM_DATABASE=GreenPeak Technologies OUI:001564* ID_OUI_FROM_DATABASE=BEHRINGER Spezielle Studiotechnik GmbH OUI:00155E* ID_OUI_FROM_DATABASE=Morgan Stanley OUI:001558* ID_OUI_FROM_DATABASE=FOXCONN OUI:001551* ID_OUI_FROM_DATABASE=RadioPulse Inc. OUI:001549* ID_OUI_FROM_DATABASE=Dixtal Biomedica Ind. Com. Ltda OUI:00154C* ID_OUI_FROM_DATABASE=Saunders Electronics OUI:00154A* ID_OUI_FROM_DATABASE=WANSHIH ELECTRONIC CO., LTD OUI:00153D* ID_OUI_FROM_DATABASE=ELIM PRODUCT CO. OUI:001544* ID_OUI_FROM_DATABASE=coM.s.a.t. AG OUI:001531* ID_OUI_FROM_DATABASE=KOCOM OUI:001538* ID_OUI_FROM_DATABASE=RFID, Inc. OUI:00152A* ID_OUI_FROM_DATABASE=Nokia GmbH OUI:00161D* ID_OUI_FROM_DATABASE=Innovative Wireless Technologies, Inc. OUI:00161C* ID_OUI_FROM_DATABASE=e:cue OUI:00160C* ID_OUI_FROM_DATABASE=LPL DEVELOPMENT S.A. DE C.V OUI:001611* ID_OUI_FROM_DATABASE=Altecon Srl OUI:001612* ID_OUI_FROM_DATABASE=Otsuka Electronics Co., Ltd. OUI:001605* ID_OUI_FROM_DATABASE=YORKVILLE SOUND INC. OUI:0015F9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001600* ID_OUI_FROM_DATABASE=CelleBrite Mobile Synchronization OUI:0015ED* ID_OUI_FROM_DATABASE=Fulcrum Microsystems, Inc. OUI:0015E1* ID_OUI_FROM_DATABASE=Picochip Ltd OUI:0015E6* ID_OUI_FROM_DATABASE=MOBILE TECHNIKA Inc. OUI:0015B1* ID_OUI_FROM_DATABASE=Ambient Corporation OUI:0015AC* ID_OUI_FROM_DATABASE=Capelon AB OUI:0015A7* ID_OUI_FROM_DATABASE=Robatech AG OUI:001599* ID_OUI_FROM_DATABASE=Samsung Electronics Co., LTD OUI:00159B* ID_OUI_FROM_DATABASE=Nortel OUI:001594* ID_OUI_FROM_DATABASE=BIXOLON CO.,LTD OUI:00158D* ID_OUI_FROM_DATABASE=Jennic Ltd OUI:001588* ID_OUI_FROM_DATABASE=Salutica Allied Solutions Sdn Bhd OUI:0014CC* ID_OUI_FROM_DATABASE=Zetec, Inc. OUI:0014D1* ID_OUI_FROM_DATABASE=TRENDnet OUI:0014C0* ID_OUI_FROM_DATABASE=Symstream Technology Group Ltd OUI:0014C5* ID_OUI_FROM_DATABASE=Alive Technologies Pty Ltd OUI:0014B9* ID_OUI_FROM_DATABASE=MSTAR SEMICONDUCTOR OUI:0014AF* ID_OUI_FROM_DATABASE=Datasym POS Inc. OUI:0014A8* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001641* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. OUI:00163C* ID_OUI_FROM_DATABASE=Rebox B.V. OUI:00162E* ID_OUI_FROM_DATABASE=Space Shuttle Hi-Tech Co., Ltd. OUI:001629* ID_OUI_FROM_DATABASE=Nivus GmbH OUI:001622* ID_OUI_FROM_DATABASE=BBH SYSTEMS GMBH OUI:001616* ID_OUI_FROM_DATABASE=BROWAN COMMUNICATION INC. OUI:00161B* ID_OUI_FROM_DATABASE=Micronet Corporation OUI:00135B* ID_OUI_FROM_DATABASE=PanelLink Cinema, LLC OUI:001362* ID_OUI_FROM_DATABASE=ShinHeung Precision Co., Ltd. OUI:001351* ID_OUI_FROM_DATABASE=Niles Audio Corporation OUI:001345* ID_OUI_FROM_DATABASE=Eaton Corporation OUI:00134A* ID_OUI_FROM_DATABASE=Engim, Inc. OUI:00133E* ID_OUI_FROM_DATABASE=MetaSwitch OUI:00132B* ID_OUI_FROM_DATABASE=Phoenix Digital OUI:001332* ID_OUI_FROM_DATABASE=Beijing Topsec Network Security Technology Co., Ltd. OUI:001337* ID_OUI_FROM_DATABASE=Orient Power Home Network Ltd. OUI:001338* ID_OUI_FROM_DATABASE=FRESENIUS-VIAL OUI:00137A* ID_OUI_FROM_DATABASE=Netvox Technology Co., Ltd. OUI:001381* ID_OUI_FROM_DATABASE=CHIPS & Systems, Inc. OUI:001386* ID_OUI_FROM_DATABASE=ABB Inc./Totalflow OUI:001374* ID_OUI_FROM_DATABASE=Atheros Communications, Inc. OUI:00136E* ID_OUI_FROM_DATABASE=Techmetro Corp. OUI:001373* ID_OUI_FROM_DATABASE=BLwave Electronics Co., Ltd OUI:001367* ID_OUI_FROM_DATABASE=Narayon. Co., Ltd. OUI:001361* ID_OUI_FROM_DATABASE=Biospace Co., Ltd. OUI:001357* ID_OUI_FROM_DATABASE=Soyal Technology Co., Ltd. OUI:001326* ID_OUI_FROM_DATABASE=ECM Systems Ltd OUI:001325* ID_OUI_FROM_DATABASE=Cortina Systems Inc OUI:00131B* ID_OUI_FROM_DATABASE=BeCell Innovations Corp. OUI:00131C* ID_OUI_FROM_DATABASE=LiteTouch, Inc. OUI:001309* ID_OUI_FROM_DATABASE=Ocean Broadband Networks OUI:00130E* ID_OUI_FROM_DATABASE=Focusrite Audio Engineering Limited OUI:0012FC* ID_OUI_FROM_DATABASE=PLANET System Co.,LTD OUI:0012FB* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:0012F6* ID_OUI_FROM_DATABASE=MDK CO.,LTD. OUI:0012F1* ID_OUI_FROM_DATABASE=IFOTEC OUI:00143E* ID_OUI_FROM_DATABASE=AirLink Communications, Inc. OUI:001437* ID_OUI_FROM_DATABASE=GSTeletech Co.,Ltd. OUI:001430* ID_OUI_FROM_DATABASE=ViPowER, Inc OUI:00142B* ID_OUI_FROM_DATABASE=Edata Communication Inc. OUI:001424* ID_OUI_FROM_DATABASE=Merry Electrics CO., LTD. OUI:00141F* ID_OUI_FROM_DATABASE=SunKwang Electronics Co., Ltd OUI:00141A* ID_OUI_FROM_DATABASE=DEICY CORPORATION OUI:001413* ID_OUI_FROM_DATABASE=Trebing & Himstedt Prozeßautomation GmbH & Co. KG OUI:001415* ID_OUI_FROM_DATABASE=Intec Automation inc. OUI:001414* ID_OUI_FROM_DATABASE=Jumpnode Systems LLC. OUI:00140E* ID_OUI_FROM_DATABASE=Nortel OUI:001405* ID_OUI_FROM_DATABASE=OpenIB, Inc. OUI:00140B* ID_OUI_FROM_DATABASE=FIRST INTERNATIONAL COMPUTER, INC. OUI:0013FE* ID_OUI_FROM_DATABASE=GRANDTEC ELECTRONIC CORP. OUI:0013F9* ID_OUI_FROM_DATABASE=Cavera Systems OUI:0013F2* ID_OUI_FROM_DATABASE=Klas Ltd OUI:0013EC* ID_OUI_FROM_DATABASE=Netsnapper Technologies SARL OUI:0013E1* ID_OUI_FROM_DATABASE=Iprobe AB OUI:0013E2* ID_OUI_FROM_DATABASE=GeoVision Inc. OUI:0013D5* ID_OUI_FROM_DATABASE=RuggedCom OUI:0013DC* ID_OUI_FROM_DATABASE=IBTEK INC. OUI:0013D0* ID_OUI_FROM_DATABASE=t+ Medical Ltd OUI:0013CB* ID_OUI_FROM_DATABASE=Zenitel Norway AS OUI:0013C6* ID_OUI_FROM_DATABASE=OpenGear, Inc OUI:0013C5* ID_OUI_FROM_DATABASE=LIGHTRON FIBER-OPTIC DEVICES INC. OUI:0013BB* ID_OUI_FROM_DATABASE=Smartvue Corporation OUI:0013BF* ID_OUI_FROM_DATABASE=Media System Planning Corp. OUI:0013B5* ID_OUI_FROM_DATABASE=Wavesat OUI:0013AE* ID_OUI_FROM_DATABASE=Radiance Technologies, Inc. OUI:0013A2* ID_OUI_FROM_DATABASE=MaxStream, Inc OUI:00139B* ID_OUI_FROM_DATABASE=ioIMAGE Ltd. OUI:00139C* ID_OUI_FROM_DATABASE=Exavera Technologies, Inc. OUI:001396* ID_OUI_FROM_DATABASE=Acbel Polytech Inc. OUI:00138A* ID_OUI_FROM_DATABASE=QINGDAO GOERTEK ELECTRONICS CO.,LTD. OUI:001389* ID_OUI_FROM_DATABASE=Redes de Telefonía Móvil S.A. OUI:00149C* ID_OUI_FROM_DATABASE=HF Company OUI:0014A3* ID_OUI_FROM_DATABASE=Vitelec BV OUI:001497* ID_OUI_FROM_DATABASE=ZHIYUAN Eletronics co.,ltd. OUI:001496* ID_OUI_FROM_DATABASE=Phonic Corp. OUI:001490* ID_OUI_FROM_DATABASE=ASP Corporation OUI:001489* ID_OUI_FROM_DATABASE=B15402100 - JANDEI, S.L. OUI:001484* ID_OUI_FROM_DATABASE=Cermate Technologies Inc. OUI:00147F* ID_OUI_FROM_DATABASE=Thomson Telecom Belgium OUI:00147A* ID_OUI_FROM_DATABASE=Eubus GmbH OUI:001473* ID_OUI_FROM_DATABASE=Bookham Inc OUI:001467* ID_OUI_FROM_DATABASE=ArrowSpan Inc. OUI:001460* ID_OUI_FROM_DATABASE=Kyocera Wireless Corp. OUI:00145B* ID_OUI_FROM_DATABASE=SeekerNet Inc. OUI:00145A* ID_OUI_FROM_DATABASE=Neratec Solutions AG OUI:001459* ID_OUI_FROM_DATABASE=Moram Co., Ltd. OUI:001454* ID_OUI_FROM_DATABASE=Symwave OUI:001443* ID_OUI_FROM_DATABASE=Consultronics Europe Ltd OUI:00144A* ID_OUI_FROM_DATABASE=Taiwan Thick-Film Ind. Corp. OUI:0011C4* ID_OUI_FROM_DATABASE=Terminales de Telecomunicacion Terrestre, S.L. OUI:0011C9* ID_OUI_FROM_DATABASE=MTT Corporation OUI:0011BF* ID_OUI_FROM_DATABASE=AESYS S.p.A. OUI:0011B8* ID_OUI_FROM_DATABASE=Liebherr - Elektronik GmbH OUI:0011AC* ID_OUI_FROM_DATABASE=Simtec Electronics OUI:0011B1* ID_OUI_FROM_DATABASE=BlueExpert Technology Corp. OUI:0011B2* ID_OUI_FROM_DATABASE=2001 Technology Inc. OUI:0011A0* ID_OUI_FROM_DATABASE=Vtech Engineering Canada Ltd OUI:0011A5* ID_OUI_FROM_DATABASE=Fortuna Electronic Corp. OUI:001276* ID_OUI_FROM_DATABASE=CG Power Systems Ireland Limited OUI:00126F* ID_OUI_FROM_DATABASE=Rayson Technology Co., Ltd. OUI:001270* ID_OUI_FROM_DATABASE=NGES Denro Systems OUI:00126A* ID_OUI_FROM_DATABASE=OPTOELECTRONICS Co., Ltd. OUI:001263* ID_OUI_FROM_DATABASE=Data Voice Technologies GmbH OUI:00125E* ID_OUI_FROM_DATABASE=CAEN OUI:00125D* ID_OUI_FROM_DATABASE=CyberNet Inc. OUI:001259* ID_OUI_FROM_DATABASE=THERMO ELECTRON KARLSRUHE OUI:001254* ID_OUI_FROM_DATABASE=Spectra Technologies Holdings Company Ltd OUI:001253* ID_OUI_FROM_DATABASE=AudioDev AB OUI:00129D* ID_OUI_FROM_DATABASE=First International Computer do Brasil OUI:001291* ID_OUI_FROM_DATABASE=KWS Computersysteme GmbH OUI:001296* ID_OUI_FROM_DATABASE=Addlogix OUI:00128F* ID_OUI_FROM_DATABASE=Montilio OUI:001282* ID_OUI_FROM_DATABASE=Qovia OUI:001289* ID_OUI_FROM_DATABASE=Advance Sterilization Products OUI:00127D* ID_OUI_FROM_DATABASE=MobileAria OUI:0011F4* ID_OUI_FROM_DATABASE=woori-net OUI:0011EE* ID_OUI_FROM_DATABASE=Estari, Inc. OUI:0011ED* ID_OUI_FROM_DATABASE=802 Global OUI:0011E8* ID_OUI_FROM_DATABASE=Tixi.Com OUI:0011DB* ID_OUI_FROM_DATABASE=Land-Cellular Corporation OUI:0011DC* ID_OUI_FROM_DATABASE=Glunz & Jensen OUI:0011E1* ID_OUI_FROM_DATABASE=Arcelik A.S OUI:0011CE* ID_OUI_FROM_DATABASE=Ubisense Limited OUI:0011D5* ID_OUI_FROM_DATABASE=Hangzhou Sunyard System Engineering Co.,Ltd. OUI:001246* ID_OUI_FROM_DATABASE=T.O.M TECHNOLOGY INC.. OUI:00124D* ID_OUI_FROM_DATABASE=Inducon BV OUI:001241* ID_OUI_FROM_DATABASE=a2i marketing center OUI:00123A* ID_OUI_FROM_DATABASE=Posystech Inc., Co. OUI:001234* ID_OUI_FROM_DATABASE=Camille Bauer OUI:00122A* ID_OUI_FROM_DATABASE=VTech Telecommunications Ltd. OUI:00122E* ID_OUI_FROM_DATABASE=Signal Technology - AISD OUI:001233* ID_OUI_FROM_DATABASE=JRC TOKKI Co.,Ltd. OUI:001199* ID_OUI_FROM_DATABASE=2wcom Systems GmbH OUI:00118F* ID_OUI_FROM_DATABASE=EUTECH INSTRUMENTS PTE. LTD. OUI:001183* ID_OUI_FROM_DATABASE=Datalogic ADC, Inc. OUI:00117C* ID_OUI_FROM_DATABASE=e-zy.net OUI:001176* ID_OUI_FROM_DATABASE=Intellambda Systems, Inc. OUI:0012C0* ID_OUI_FROM_DATABASE=HotLava Systems, Inc. OUI:0012B5* ID_OUI_FROM_DATABASE=Vialta, Inc. OUI:0012BC* ID_OUI_FROM_DATABASE=Echolab LLC OUI:0012B6* ID_OUI_FROM_DATABASE=Santa Barbara Infrared, Inc. OUI:0012B0* ID_OUI_FROM_DATABASE=Efore Oyj (Plc) OUI:0012A4* ID_OUI_FROM_DATABASE=ThingMagic, LLC OUI:0012A9* ID_OUI_FROM_DATABASE=3Com Ltd OUI:0012A3* ID_OUI_FROM_DATABASE=Trust International B.V. OUI:001224* ID_OUI_FROM_DATABASE=NexQL Corporation OUI:001229* ID_OUI_FROM_DATABASE=BroadEasy Technologies Co.,Ltd OUI:00121D* ID_OUI_FROM_DATABASE=Netfabric Corporation OUI:001211* ID_OUI_FROM_DATABASE=Protechna Herbst GmbH & Co. KG OUI:001218* ID_OUI_FROM_DATABASE=ARUZE Corporation OUI:001205* ID_OUI_FROM_DATABASE=Terrasat Communications, Inc. OUI:00120A* ID_OUI_FROM_DATABASE=Emerson Climate Technologies GmbH OUI:0011FE* ID_OUI_FROM_DATABASE=Keiyo System Research, Inc. OUI:0011F8* ID_OUI_FROM_DATABASE=AIRAYA Corp OUI:0012EC* ID_OUI_FROM_DATABASE=Movacolor b.v. OUI:0012E5* ID_OUI_FROM_DATABASE=Time America, Inc. OUI:0012E0* ID_OUI_FROM_DATABASE=Codan Limited OUI:0012DF* ID_OUI_FROM_DATABASE=Novomatic AG OUI:0012D9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0012C6* ID_OUI_FROM_DATABASE=TGC America, Inc OUI:0012CD* ID_OUI_FROM_DATABASE=ASEM SpA OUI:000FE9* ID_OUI_FROM_DATABASE=GW TECHNOLOGIES CO.,LTD. OUI:000FDD* ID_OUI_FROM_DATABASE=SORDIN AB OUI:000FE2* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Ltd. OUI:000FD6* ID_OUI_FROM_DATABASE=Sarotech Co., Ltd OUI:002654* ID_OUI_FROM_DATABASE=3Com Corporation OUI:000FD0* ID_OUI_FROM_DATABASE=ASTRI OUI:000FCF* ID_OUI_FROM_DATABASE=DataWind Research OUI:000FC3* ID_OUI_FROM_DATABASE=PalmPalm Technology, Inc. OUI:001144* ID_OUI_FROM_DATABASE=Assurance Technology Corp OUI:00113E* ID_OUI_FROM_DATABASE=JL Corporation OUI:001131* ID_OUI_FROM_DATABASE=UNATECH. CO.,LTD OUI:001137* ID_OUI_FROM_DATABASE=AICHI ELECTRIC CO., LTD. OUI:00112D* ID_OUI_FROM_DATABASE=iPulse Systems OUI:111111* ID_OUI_FROM_DATABASE=Private OUI:001123* ID_OUI_FROM_DATABASE=Appointech, Inc. OUI:00111D* ID_OUI_FROM_DATABASE=Hectrix Limited OUI:000F6C* ID_OUI_FROM_DATABASE=ADDI-DATA GmbH OUI:000F6B* ID_OUI_FROM_DATABASE=GateWare Communications GmbH OUI:000F5F* ID_OUI_FROM_DATABASE=Nicety Technologies Inc. (NTS) OUI:000F59* ID_OUI_FROM_DATABASE=Phonak Communications AG OUI:000F5A* ID_OUI_FROM_DATABASE=Peribit Networks OUI:000F53* ID_OUI_FROM_DATABASE=Solarflare Communications Inc OUI:000F47* ID_OUI_FROM_DATABASE=ROBOX SPA OUI:000F4C* ID_OUI_FROM_DATABASE=Elextech INC OUI:001170* ID_OUI_FROM_DATABASE=GSC SRL OUI:001169* ID_OUI_FROM_DATABASE=EMS Satcom OUI:001164* ID_OUI_FROM_DATABASE=ACARD Technology Corp. OUI:00115F* ID_OUI_FROM_DATABASE=ITX Security Co., Ltd. OUI:00115A* ID_OUI_FROM_DATABASE=Ivoclar Vivadent AG OUI:001159* ID_OUI_FROM_DATABASE=MATISSE NETWORKS INC OUI:001153* ID_OUI_FROM_DATABASE=Trident Tek, Inc. OUI:001150* ID_OUI_FROM_DATABASE=Belkin Corporation OUI:001151* ID_OUI_FROM_DATABASE=Mykotronx OUI:00114A* ID_OUI_FROM_DATABASE=KAYABA INDUSTRY Co,.Ltd. OUI:001110* ID_OUI_FROM_DATABASE=Maxanna Technology Co., Ltd. OUI:001117* ID_OUI_FROM_DATABASE=CESNET OUI:001104* ID_OUI_FROM_DATABASE=TELEXY OUI:00110B* ID_OUI_FROM_DATABASE=Franklin Technology Systems OUI:001100* ID_OUI_FROM_DATABASE=Schneider Electric OUI:000FFE* ID_OUI_FROM_DATABASE=G-PRO COMPUTER OUI:000FEF* ID_OUI_FROM_DATABASE=Thales e-Transactions GmbH OUI:000FF0* ID_OUI_FROM_DATABASE=Sunray Co. Ltd. OUI:000FF5* ID_OUI_FROM_DATABASE=GN&S company OUI:000FCA* ID_OUI_FROM_DATABASE=A-JIN TECHLINE CO, LTD OUI:000FBD* ID_OUI_FROM_DATABASE=MRV Communications (Networks) LTD OUI:000FBE* ID_OUI_FROM_DATABASE=e-w/you Inc. OUI:000FB7* ID_OUI_FROM_DATABASE=Cavium OUI:000FA4* ID_OUI_FROM_DATABASE=Sprecher Automation GmbH OUI:000FAB* ID_OUI_FROM_DATABASE=Kyushu Electronics Systems Inc. OUI:000F9D* ID_OUI_FROM_DATABASE=DisplayLink (UK) Ltd OUI:000F98* ID_OUI_FROM_DATABASE=Avamax Co. Ltd. OUI:000F8B* ID_OUI_FROM_DATABASE=Orion MultiSystems Inc OUI:000F8C* ID_OUI_FROM_DATABASE=Gigawavetech Pte Ltd OUI:000F91* ID_OUI_FROM_DATABASE=Aerotelecom Co.,Ltd. OUI:000F7E* ID_OUI_FROM_DATABASE=Ablerex Electronics Co., LTD OUI:000F85* ID_OUI_FROM_DATABASE=ADDO-Japan Corporation OUI:000F72* ID_OUI_FROM_DATABASE=Sandburst OUI:000F79* ID_OUI_FROM_DATABASE=Bluetooth Interest Group Inc. OUI:000F19* ID_OUI_FROM_DATABASE=Boston Scientific OUI:000F0D* ID_OUI_FROM_DATABASE=Hunt Electronic Co., Ltd. OUI:000F06* ID_OUI_FROM_DATABASE=Nortel Networks OUI:000F01* ID_OUI_FROM_DATABASE=DIGITALKS INC OUI:000EFA* ID_OUI_FROM_DATABASE=Optoway Technology Incorporation OUI:000EF4* ID_OUI_FROM_DATABASE=Kasda Networks Inc OUI:000EF3* ID_OUI_FROM_DATABASE=Smarthome OUI:000EEE* ID_OUI_FROM_DATABASE=Muco Industrie BV OUI:000EE7* ID_OUI_FROM_DATABASE=AAC ELECTRONICS CORP. OUI:000F38* ID_OUI_FROM_DATABASE=Netstar OUI:000F40* ID_OUI_FROM_DATABASE=Optical Internetworking Forum OUI:000F33* ID_OUI_FROM_DATABASE=DUALi Inc. OUI:000F2C* ID_OUI_FROM_DATABASE=Uplogix, Inc. OUI:000F26* ID_OUI_FROM_DATABASE=WorldAccxx LLC OUI:000F25* ID_OUI_FROM_DATABASE=AimValley B.V. OUI:000F13* ID_OUI_FROM_DATABASE=Nisca corporation OUI:000F14* ID_OUI_FROM_DATABASE=Mindray Co., Ltd. OUI:000EE1* ID_OUI_FROM_DATABASE=ExtremeSpeed Inc. OUI:000EDB* ID_OUI_FROM_DATABASE=XiNCOM Corp. OUI:000EE2* ID_OUI_FROM_DATABASE=Custom Engineering OUI:000ED5* ID_OUI_FROM_DATABASE=COPAN Systems Inc. OUI:000EC9* ID_OUI_FROM_DATABASE=YOKO Technology Corp. OUI:000ED0* ID_OUI_FROM_DATABASE=Privaris, Inc. OUI:000ED7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000EC4* ID_OUI_FROM_DATABASE=Iskra Transmission d.d. OUI:000EC3* ID_OUI_FROM_DATABASE=Logic Controls, Inc. OUI:000EB6* ID_OUI_FROM_DATABASE=Riverbed Technology, Inc. OUI:000EBD* ID_OUI_FROM_DATABASE=Burdick, a Quinton Compny OUI:000EB1* ID_OUI_FROM_DATABASE=Newcotech,Ltd OUI:000DAA* ID_OUI_FROM_DATABASE=S.A.Tehnology co.,Ltd. OUI:000DA0* ID_OUI_FROM_DATABASE=NEDAP N.V. OUI:000D9F* ID_OUI_FROM_DATABASE=RF Micro Devices OUI:000D9A* ID_OUI_FROM_DATABASE=INFOTEC LTD OUI:000D8D* ID_OUI_FROM_DATABASE=Prosoft Technology, Inc OUI:000D8E* ID_OUI_FROM_DATABASE=Koden Electronics Co., Ltd. OUI:000D84* ID_OUI_FROM_DATABASE=Makus Inc. OUI:000D83* ID_OUI_FROM_DATABASE=Sanmina-SCI Hungary Ltd. OUI:000D76* ID_OUI_FROM_DATABASE=Hokuto Denshi Co,. Ltd. OUI:000D7D* ID_OUI_FROM_DATABASE=Afco Systems OUI:000E51* ID_OUI_FROM_DATABASE=tecna elettronica srl OUI:000E4C* ID_OUI_FROM_DATABASE=Bermai Inc. OUI:000E4B* ID_OUI_FROM_DATABASE=atrium c and i OUI:000E3E* ID_OUI_FROM_DATABASE=Sun Optronics Inc OUI:000E45* ID_OUI_FROM_DATABASE=Beijing Newtry Electronic Technology Ltd OUI:000E39* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000E32* ID_OUI_FROM_DATABASE=Kontron Medical OUI:000E2B* ID_OUI_FROM_DATABASE=Safari Technologies OUI:000E2C* ID_OUI_FROM_DATABASE=Netcodec co. OUI:000E1F* ID_OUI_FROM_DATABASE=TCL Networks Equipment Co., Ltd. OUI:000E26* ID_OUI_FROM_DATABASE=Gincom Technology Corp. OUI:000E1A* ID_OUI_FROM_DATABASE=JPS Communications OUI:000E19* ID_OUI_FROM_DATABASE=LogicaCMG Pty Ltd OUI:000E13* ID_OUI_FROM_DATABASE=Accu-Sort Systems inc. OUI:000E0F* ID_OUI_FROM_DATABASE=ERMME OUI:000E05* ID_OUI_FROM_DATABASE=WIRELESS MATRIX CORP. OUI:000E06* ID_OUI_FROM_DATABASE=Team Simoco Ltd OUI:000E0B* ID_OUI_FROM_DATABASE=Netac Technology Co., Ltd. OUI:000DF8* ID_OUI_FROM_DATABASE=ORGA Kartensysteme GmbH OUI:000DFF* ID_OUI_FROM_DATABASE=CHENMING MOLD INDUSTRY CORP. OUI:000DEC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000DF3* ID_OUI_FROM_DATABASE=Asmax Solutions OUI:000DE6* ID_OUI_FROM_DATABASE=YOUNGBO ENGINEERING CO.,LTD OUI:000DE5* ID_OUI_FROM_DATABASE=Samsung Thales OUI:000DE0* ID_OUI_FROM_DATABASE=ICPDAS Co.,LTD OUI:000DD3* ID_OUI_FROM_DATABASE=SAMWOO Telecommunication Co.,Ltd. OUI:000DD4* ID_OUI_FROM_DATABASE=Symantec Corporation OUI:000DD9* ID_OUI_FROM_DATABASE=Anton Paar GmbH OUI:000DCD* ID_OUI_FROM_DATABASE=GROUPE TXCOM OUI:000EAA* ID_OUI_FROM_DATABASE=Scalent Systems, Inc. OUI:000E9E* ID_OUI_FROM_DATABASE=Topfield Co., Ltd OUI:000EA3* ID_OUI_FROM_DATABASE=CNCR-IT CO.,LTD,HangZhou P.R.CHINA OUI:000EA4* ID_OUI_FROM_DATABASE=Certance Inc. OUI:000E92* ID_OUI_FROM_DATABASE=Open Telecom OUI:000E97* ID_OUI_FROM_DATABASE=Ultracker Technology CO., Inc OUI:000E91* ID_OUI_FROM_DATABASE=Navico Auckland Ltd OUI:000E8B* ID_OUI_FROM_DATABASE=Astarte Technology Co, Ltd. OUI:000E84* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000D6A* ID_OUI_FROM_DATABASE=Redwood Technologies LTD OUI:000D71* ID_OUI_FROM_DATABASE=boca systems OUI:000D5E* ID_OUI_FROM_DATABASE=NEC Personal Products OUI:000D63* ID_OUI_FROM_DATABASE=DENT Instruments, Inc. OUI:000D64* ID_OUI_FROM_DATABASE=COMAG Handels AG OUI:000D57* ID_OUI_FROM_DATABASE=Fujitsu I-Network Systems Limited. OUI:000D52* ID_OUI_FROM_DATABASE=Comart system OUI:000D51* ID_OUI_FROM_DATABASE=DIVR Systems, Inc. OUI:000D47* ID_OUI_FROM_DATABASE=Collex OUI:000DC1* ID_OUI_FROM_DATABASE=SafeWeb Inc OUI:000DC6* ID_OUI_FROM_DATABASE=DigiRose Technology Co., Ltd. OUI:000DBA* ID_OUI_FROM_DATABASE=Océ Document Technologies GmbH OUI:000DB4* ID_OUI_FROM_DATABASE=NETASQ OUI:000DB3* ID_OUI_FROM_DATABASE=SDO Communication Corperation OUI:000DAE* ID_OUI_FROM_DATABASE=SAMSUNG HEAVY INDUSTRIES CO., LTD. OUI:000DA6* ID_OUI_FROM_DATABASE=Universal Switching Corporation OUI:000E78* ID_OUI_FROM_DATABASE=Amtelco OUI:000E70* ID_OUI_FROM_DATABASE=in2 Networks OUI:000E6B* ID_OUI_FROM_DATABASE=Janitza electronics GmbH OUI:000E64* ID_OUI_FROM_DATABASE=Elphel, Inc OUI:000E5D* ID_OUI_FROM_DATABASE=Triple Play Technologies A/S OUI:000E5E* ID_OUI_FROM_DATABASE=Raisecom Technology OUI:000E58* ID_OUI_FROM_DATABASE=Sonos, Inc. OUI:000BE2* ID_OUI_FROM_DATABASE=Lumenera Corporation OUI:000BE7* ID_OUI_FROM_DATABASE=COMFLUX TECHNOLOGY INC. OUI:000BD6* ID_OUI_FROM_DATABASE=Paxton Access Ltd OUI:000BD2* ID_OUI_FROM_DATABASE=Remopro Technology Inc. OUI:000BC6* ID_OUI_FROM_DATABASE=ISAC, Inc. OUI:000BCB* ID_OUI_FROM_DATABASE=Fagor Automation , S. Coop OUI:000BBF* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000BBA* ID_OUI_FROM_DATABASE=Harmonic, Inc OUI:000BB3* ID_OUI_FROM_DATABASE=RiT technologies Ltd. OUI:000C38* ID_OUI_FROM_DATABASE=TelcoBridges Inc. OUI:000C3F* ID_OUI_FROM_DATABASE=Cogent Defence & Security Networks, OUI:000C30* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000C26* ID_OUI_FROM_DATABASE=Weintek Labs. Inc. OUI:000C2E* ID_OUI_FROM_DATABASE=Openet information technology(shenzhen) Co., Ltd. OUI:000C25* ID_OUI_FROM_DATABASE=Allied Telesis Labs, Inc. OUI:000C1F* ID_OUI_FROM_DATABASE=Glimmerglass Networks OUI:000C24* ID_OUI_FROM_DATABASE=ANATOR OUI:000C1B* ID_OUI_FROM_DATABASE=ORACOM Co, Ltd. OUI:000C19* ID_OUI_FROM_DATABASE=Telio Communications GmbH OUI:000C7A* ID_OUI_FROM_DATABASE=DaTARIUS Technologies GmbH OUI:000C67* ID_OUI_FROM_DATABASE=OYO ELECTRIC CO.,LTD OUI:000C4F* ID_OUI_FROM_DATABASE=UDTech Japan Corporation OUI:000C54* ID_OUI_FROM_DATABASE=Pedestal Networks, Inc OUI:000C5B* ID_OUI_FROM_DATABASE=HANWANG TECHNOLOGY CO.,LTD OUI:000C60* ID_OUI_FROM_DATABASE=ACM Systems OUI:000C62* ID_OUI_FROM_DATABASE=ABB AB, Cewe-Control OUI:000C48* ID_OUI_FROM_DATABASE=QoStek Corporation OUI:000C4D* ID_OUI_FROM_DATABASE=Curtiss-Wright Controls Avionics & Electronics OUI:000C14* ID_OUI_FROM_DATABASE=Diagnostic Instruments, Inc. OUI:000C07* ID_OUI_FROM_DATABASE=Iftest AG OUI:000C06* ID_OUI_FROM_DATABASE=Nixvue Systems Pte Ltd OUI:000C08* ID_OUI_FROM_DATABASE=HUMEX Technologies Corp. OUI:000C0D* ID_OUI_FROM_DATABASE=Communications & Power Industries / Satcom Division OUI:000BF5* ID_OUI_FROM_DATABASE=Shanghai Sibo Telecom Technology Co.,Ltd OUI:000BFA* ID_OUI_FROM_DATABASE=EXEMYS SRL OUI:000C01* ID_OUI_FROM_DATABASE=Abatron AG OUI:000BEE* ID_OUI_FROM_DATABASE=inc.jet, Incorporated OUI:000CE6* ID_OUI_FROM_DATABASE=Meru Networks Inc OUI:000CEB* ID_OUI_FROM_DATABASE=CNMP Networks, Inc. OUI:000CE2* ID_OUI_FROM_DATABASE=Rolls-Royce OUI:000CEC* ID_OUI_FROM_DATABASE=Spectracom Corp. OUI:000CD7* ID_OUI_FROM_DATABASE=Nallatech Ltd OUI:000CDE* ID_OUI_FROM_DATABASE=ABB STOTZ-KONTAKT GmbH OUI:000CD2* ID_OUI_FROM_DATABASE=Schaffner EMV AG OUI:000CD8* ID_OUI_FROM_DATABASE=M. K. Juchheim GmbH & Co OUI:000CC6* ID_OUI_FROM_DATABASE=Ka-Ro electronics GmbH OUI:000CCB* ID_OUI_FROM_DATABASE=Design Combus Ltd OUI:000CC5* ID_OUI_FROM_DATABASE=Nextlink Co., Ltd. OUI:000CB3* ID_OUI_FROM_DATABASE=ROUND Co.,Ltd. OUI:000CB8* ID_OUI_FROM_DATABASE=MEDION AG OUI:000CBF* ID_OUI_FROM_DATABASE=Holy Stone Ent. Co., Ltd. OUI:000A07* ID_OUI_FROM_DATABASE=WebWayOne Ltd OUI:000CA1* ID_OUI_FROM_DATABASE=SIGMACOM Co., LTD. OUI:000CA6* ID_OUI_FROM_DATABASE=Mintera Corporation OUI:000CA8* ID_OUI_FROM_DATABASE=Garuda Networks Corporation OUI:000CAD* ID_OUI_FROM_DATABASE=BTU International OUI:000C95* ID_OUI_FROM_DATABASE=PrimeNet OUI:000C9A* ID_OUI_FROM_DATABASE=Hitech Electronics Corp. OUI:000C8E* ID_OUI_FROM_DATABASE=Mentor Engineering Inc OUI:000C93* ID_OUI_FROM_DATABASE=Xeline Co., Ltd. OUI:000C7F* ID_OUI_FROM_DATABASE=synertronixx GmbH OUI:000C82* ID_OUI_FROM_DATABASE=NETWORK TECHNOLOGIES INC OUI:000C87* ID_OUI_FROM_DATABASE=AMD OUI:000C73* ID_OUI_FROM_DATABASE=TELSON ELECTRONICS CO., LTD OUI:000D1D* ID_OUI_FROM_DATABASE=HIGH-TEK HARNESS ENT. CO., LTD. OUI:000D1E* ID_OUI_FROM_DATABASE=Control Techniques OUI:000D0C* ID_OUI_FROM_DATABASE=MDI Security Systems OUI:000D11* ID_OUI_FROM_DATABASE=DENTSPLY - Gendex OUI:000D05* ID_OUI_FROM_DATABASE=cybernet manufacturing inc. OUI:000CF9* ID_OUI_FROM_DATABASE=Xylem Water Solutions OUI:000CFE* ID_OUI_FROM_DATABASE=Grand Electronic Co., Ltd OUI:000CF2* ID_OUI_FROM_DATABASE=GAMESA Eólica OUI:000D43* ID_OUI_FROM_DATABASE=DRS Tactical Systems Inc. OUI:000D37* ID_OUI_FROM_DATABASE=WIPLUG OUI:000D3E* ID_OUI_FROM_DATABASE=APLUX Communications Ltd. OUI:000D3D* ID_OUI_FROM_DATABASE=Hammerhead Systems, Inc. OUI:000D30* ID_OUI_FROM_DATABASE=IceFyre Semiconductor OUI:000D2B* ID_OUI_FROM_DATABASE=Racal Instruments OUI:000D24* ID_OUI_FROM_DATABASE=SENTEC E&E CO., LTD. OUI:000D18* ID_OUI_FROM_DATABASE=Mega-Trend Electronics CO., LTD. OUI:000BA4* ID_OUI_FROM_DATABASE=Shiron Satellite Communications Ltd. (1996) OUI:000BA9* ID_OUI_FROM_DATABASE=CloudShield Technologies, Inc. OUI:000BA3* ID_OUI_FROM_DATABASE=Siemens AG, I&S OUI:000B91* ID_OUI_FROM_DATABASE=Aglaia Gesellschaft für Bildverarbeitung und Kommunikation mbH OUI:000B96* ID_OUI_FROM_DATABASE=Innotrac Diagnostics Oy OUI:000B9D* ID_OUI_FROM_DATABASE=TwinMOS Technologies Inc. OUI:000B8A* ID_OUI_FROM_DATABASE=MITEQ Inc. OUI:000B7E* ID_OUI_FROM_DATABASE=SAGINOMIYA Seisakusho Inc. OUI:000B83* ID_OUI_FROM_DATABASE=DATAWATT B.V. OUI:000AAD* ID_OUI_FROM_DATABASE=Stargames Corporation OUI:000AB2* ID_OUI_FROM_DATABASE=Fresnel Wireless Systems OUI:000AB4* ID_OUI_FROM_DATABASE=ETIC Telecommunications OUI:000AB9* ID_OUI_FROM_DATABASE=Astera Technologies Corp. OUI:000AA1* ID_OUI_FROM_DATABASE=V V S Limited OUI:000AA6* ID_OUI_FROM_DATABASE=Hochiki Corporation OUI:000A8E* ID_OUI_FROM_DATABASE=Invacom Ltd OUI:000A9F* ID_OUI_FROM_DATABASE=Pannaway Technologies, Inc. OUI:000A99* ID_OUI_FROM_DATABASE=Calamp Wireless Networks Inc OUI:000A93* ID_OUI_FROM_DATABASE=W2 Networks, Inc. OUI:000A7F* ID_OUI_FROM_DATABASE=Teradon Industries, Inc OUI:000A86* ID_OUI_FROM_DATABASE=Lenze OUI:000A8B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000B15* ID_OUI_FROM_DATABASE=Platypus Technology OUI:000B10* ID_OUI_FROM_DATABASE=11wave Technonlogy Co.,Ltd OUI:000B09* ID_OUI_FROM_DATABASE=Ifoundry Systems Singapore OUI:000B04* ID_OUI_FROM_DATABASE=Volktek Corporation OUI:000AFD* ID_OUI_FROM_DATABASE=Kentec Electronics OUI:000B02* ID_OUI_FROM_DATABASE=Dallmeier electronic OUI:000AF1* ID_OUI_FROM_DATABASE=Clarity Design, Inc. OUI:000AF6* ID_OUI_FROM_DATABASE=Emerson Climate Technologies Retail Solutions, Inc. OUI:000AEB* ID_OUI_FROM_DATABASE=Shenzhen Tp-Link Technology Co; Ltd. OUI:000AE4* ID_OUI_FROM_DATABASE=Wistron Corp. OUI:000A0E* ID_OUI_FROM_DATABASE=Invivo Research Inc. OUI:000A13* ID_OUI_FROM_DATABASE=Honeywell Video Systems OUI:000A04* ID_OUI_FROM_DATABASE=3Com Ltd OUI:0009FD* ID_OUI_FROM_DATABASE=Ubinetics Limited OUI:0009F4* ID_OUI_FROM_DATABASE=Alcon Laboratories, Inc. OUI:0009E7* ID_OUI_FROM_DATABASE=ADC Techonology OUI:0009EE* ID_OUI_FROM_DATABASE=MEIKYO ELECTRIC CO.,LTD OUI:0009F3* ID_OUI_FROM_DATABASE=WELL Communication Corp. OUI:0009E2* ID_OUI_FROM_DATABASE=Sinbon Electronics Co., Ltd. OUI:0009DB* ID_OUI_FROM_DATABASE=eSpace OUI:000B6B* ID_OUI_FROM_DATABASE=Wistron Neweb Corp. OUI:000B70* ID_OUI_FROM_DATABASE=Load Technology, Inc. OUI:000B72* ID_OUI_FROM_DATABASE=Lawo AG OUI:000B77* ID_OUI_FROM_DATABASE=Cogent Systems, Inc. OUI:000B71* ID_OUI_FROM_DATABASE=Litchfield Communications Inc. OUI:000B5F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000B64* ID_OUI_FROM_DATABASE=Kieback & Peter GmbH & Co KG OUI:000B5B* ID_OUI_FROM_DATABASE=Rincon Research Corporation OUI:000B56* ID_OUI_FROM_DATABASE=Cybernetics OUI:000B4E* ID_OUI_FROM_DATABASE=VertexRSI, General Dynamics SatCOM Technologies, Inc. OUI:000B53* ID_OUI_FROM_DATABASE=INITIUM Co., Ltd. OUI:000A35* ID_OUI_FROM_DATABASE=Xilinx OUI:000A3A* ID_OUI_FROM_DATABASE=J-THREE INTERNATIONAL Holding Co., Ltd. OUI:000A3C* ID_OUI_FROM_DATABASE=Enerpoint Ltd. OUI:000A41* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000A48* ID_OUI_FROM_DATABASE=Albatron Technology OUI:000A2E* ID_OUI_FROM_DATABASE=MAPLE NETWORKS CO., LTD OUI:000A26* ID_OUI_FROM_DATABASE=CEIA S.p.A. OUI:000A28* ID_OUI_FROM_DATABASE=Motorola OUI:000A21* ID_OUI_FROM_DATABASE=Integra Telecom Co. Ltd OUI:000A1A* ID_OUI_FROM_DATABASE=Imerge Ltd OUI:000A15* ID_OUI_FROM_DATABASE=Silicon Data, Inc OUI:000B42* ID_OUI_FROM_DATABASE=commax Co., Ltd. OUI:000B47* ID_OUI_FROM_DATABASE=Advanced Energy OUI:000B34* ID_OUI_FROM_DATABASE=ShangHai Broadband Technologies CO.LTD OUI:000B36* ID_OUI_FROM_DATABASE=Productivity Systems, Inc. OUI:000B28* ID_OUI_FROM_DATABASE=Quatech Inc. OUI:000B2F* ID_OUI_FROM_DATABASE=bplan GmbH OUI:000B1C* ID_OUI_FROM_DATABASE=SIBCO bv OUI:000B21* ID_OUI_FROM_DATABASE=G-Star Communications Inc. OUI:000B23* ID_OUI_FROM_DATABASE=Siemens Subscriber Networks OUI:000A7A* ID_OUI_FROM_DATABASE=Kyoritsu Electric Co., Ltd. OUI:000A6E* ID_OUI_FROM_DATABASE=Harmonic, Inc OUI:000A73* ID_OUI_FROM_DATABASE=Scientific Atlanta OUI:000A60* ID_OUI_FROM_DATABASE=Autostar Technology Pte Ltd OUI:000A67* ID_OUI_FROM_DATABASE=OngCorp OUI:000A6C* ID_OUI_FROM_DATABASE=Walchem Corporation OUI:000A5B* ID_OUI_FROM_DATABASE=Power-One as OUI:000A59* ID_OUI_FROM_DATABASE=HW server OUI:000A54* ID_OUI_FROM_DATABASE=Laguna Hills, Inc. OUI:000A4D* ID_OUI_FROM_DATABASE=Noritz Corporation OUI:000ADF* ID_OUI_FROM_DATABASE=Gennum Corporation OUI:000AD8* ID_OUI_FROM_DATABASE=IPCserv Technology Corp. OUI:000ACC* ID_OUI_FROM_DATABASE=Winnow Networks, Inc. OUI:000AD1* ID_OUI_FROM_DATABASE=MWS OUI:000AD3* ID_OUI_FROM_DATABASE=INITECH Co., Ltd OUI:000AC0* ID_OUI_FROM_DATABASE=Fuyoh Video Industry CO., LTD. OUI:000AC5* ID_OUI_FROM_DATABASE=Color Kinetics OUI:00097B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000982* ID_OUI_FROM_DATABASE=Loewe Opta GmbH OUI:000976* ID_OUI_FROM_DATABASE=Datasoft ISDN Systems GmbH OUI:000969* ID_OUI_FROM_DATABASE=Meret Optical Communications OUI:000963* ID_OUI_FROM_DATABASE=Dominion Lasercom Inc. OUI:00096A* ID_OUI_FROM_DATABASE=Cloverleaf Communications Inc. OUI:00096F* ID_OUI_FROM_DATABASE=Beijing Zhongqing Elegant Tech. Corp.,Limited OUI:00095D* ID_OUI_FROM_DATABASE=Dialogue Technology Corp. OUI:00095F* ID_OUI_FROM_DATABASE=Telebyte, Inc. OUI:000958* ID_OUI_FROM_DATABASE=INTELNET S.A. OUI:00094C* ID_OUI_FROM_DATABASE=Communication Weaver Co.,Ltd. OUI:000951* ID_OUI_FROM_DATABASE=Apogee Imaging Systems OUI:00094B* ID_OUI_FROM_DATABASE=FillFactory NV OUI:0009AE* ID_OUI_FROM_DATABASE=OKANO ELECTRIC CO.,LTD OUI:0009AD* ID_OUI_FROM_DATABASE=HYUNDAI SYSCOMM, INC. OUI:0009B4* ID_OUI_FROM_DATABASE=KISAN TELECOM CO., LTD. OUI:0009A8* ID_OUI_FROM_DATABASE=Eastmode Pte Ltd OUI:00099B* ID_OUI_FROM_DATABASE=Western Telematic Inc. OUI:00099C* ID_OUI_FROM_DATABASE=Naval Research Laboratory OUI:0009A1* ID_OUI_FROM_DATABASE=Telewise Communications, Inc. OUI:000995* ID_OUI_FROM_DATABASE=Castle Technology Ltd OUI:000989* ID_OUI_FROM_DATABASE=VividLogic Inc. OUI:00098E* ID_OUI_FROM_DATABASE=ipcas GmbH OUI:00097C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0009C8* ID_OUI_FROM_DATABASE=SINAGAWA TSUSHIN KEISOU SERVICE OUI:0009CF* ID_OUI_FROM_DATABASE=iAd GmbH OUI:0009D4* ID_OUI_FROM_DATABASE=Transtech Networks OUI:0009BB* ID_OUI_FROM_DATABASE=MathStar, Inc. OUI:0009C0* ID_OUI_FROM_DATABASE=6WIND OUI:000807* ID_OUI_FROM_DATABASE=Access Devices Limited OUI:000801* ID_OUI_FROM_DATABASE=HighSpeed Surfing Inc. OUI:000808* ID_OUI_FROM_DATABASE=PPT Vision, Inc. OUI:0007F7* ID_OUI_FROM_DATABASE=Galtronics OUI:0007FE* ID_OUI_FROM_DATABASE=Rigaku Corporation OUI:0007F8* ID_OUI_FROM_DATABASE=ITDevices, Inc. OUI:0007EB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0007F1* ID_OUI_FROM_DATABASE=TeraBurst Networks Inc. OUI:0007E5* ID_OUI_FROM_DATABASE=Coup Corporation OUI:0007DF* ID_OUI_FROM_DATABASE=Vbrick Systems Inc. OUI:0007DE* ID_OUI_FROM_DATABASE=eCopilt AB OUI:0007CF* ID_OUI_FROM_DATABASE=Anoto AB OUI:0007D2* ID_OUI_FROM_DATABASE=Logopak Systeme GmbH & Co. KG OUI:0008AA* ID_OUI_FROM_DATABASE=KARAM OUI:0008A4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000898* ID_OUI_FROM_DATABASE=Gigabit Optics Corporation OUI:00089D* ID_OUI_FROM_DATABASE=UHD-Elektronik OUI:000890* ID_OUI_FROM_DATABASE=AVILINKS SA OUI:000889* ID_OUI_FROM_DATABASE=Echostar Technologies Corp OUI:000884* ID_OUI_FROM_DATABASE=Index Braille AB OUI:000877* ID_OUI_FROM_DATABASE=Liebert-Hiross Spa OUI:08006B* ID_OUI_FROM_DATABASE=ACCEL TECHNOLOGIES INC. OUI:000871* ID_OUI_FROM_DATABASE=NORTHDATA Co., Ltd. OUI:00087D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000876* ID_OUI_FROM_DATABASE=SDSystem OUI:0008E6* ID_OUI_FROM_DATABASE=Littlefeet OUI:0008D9* ID_OUI_FROM_DATABASE=Mitadenshi Co.,LTD OUI:0008D4* ID_OUI_FROM_DATABASE=IneoQuest Technologies, Inc OUI:0008CD* ID_OUI_FROM_DATABASE=With-Net Inc OUI:0008D3* ID_OUI_FROM_DATABASE=Hercules Technologies S.A.S. OUI:0008C3* ID_OUI_FROM_DATABASE=Contex A/S OUI:0008BD* ID_OUI_FROM_DATABASE=TEPG-US OUI:0008BC* ID_OUI_FROM_DATABASE=Ilevo AB OUI:0008B7* ID_OUI_FROM_DATABASE=HIT Incorporated OUI:0008B0* ID_OUI_FROM_DATABASE=BKtel communications GmbH OUI:00086A* ID_OUI_FROM_DATABASE=Securiton Gmbh OUI:000864* ID_OUI_FROM_DATABASE=Fasy S.p.A. OUI:00085E* ID_OUI_FROM_DATABASE=PCO AG OUI:000851* ID_OUI_FROM_DATABASE=Canadian Bank Note Company, Ltd. OUI:000852* ID_OUI_FROM_DATABASE=Davolink Co. Inc. OUI:000857* ID_OUI_FROM_DATABASE=Polaris Networks, Inc. OUI:00081B* ID_OUI_FROM_DATABASE=Windigo Systems OUI:000822* ID_OUI_FROM_DATABASE=InPro Comm OUI:00082E* ID_OUI_FROM_DATABASE=Multitone Electronics PLC OUI:00081C* ID_OUI_FROM_DATABASE=@pos.com OUI:000828* ID_OUI_FROM_DATABASE=Koei Engineering Ltd. OUI:000816* ID_OUI_FROM_DATABASE=Bluelon ApS OUI:000815* ID_OUI_FROM_DATABASE=CATS Co., Ltd. OUI:00091A* ID_OUI_FROM_DATABASE=Macat Optics & Electronics Co., Ltd. OUI:000919* ID_OUI_FROM_DATABASE=MDS Gateways OUI:000913* ID_OUI_FROM_DATABASE=SystemK Corporation OUI:00090C* ID_OUI_FROM_DATABASE=Mayekawa Mfg. Co. Ltd. OUI:000907* ID_OUI_FROM_DATABASE=Chrysalis Development OUI:000900* ID_OUI_FROM_DATABASE=TMT OUI:0008F8* ID_OUI_FROM_DATABASE=UTC CCS OUI:0008F3* ID_OUI_FROM_DATABASE=WANY OUI:0008EC* ID_OUI_FROM_DATABASE=Optical Zonu Corporation OUI:0008E0* ID_OUI_FROM_DATABASE=ATO Technology Ltd. OUI:0008E5* ID_OUI_FROM_DATABASE=IDK Corporation OUI:000945* ID_OUI_FROM_DATABASE=Palmmicro Communications Inc OUI:00093E* ID_OUI_FROM_DATABASE=C&I Technologies OUI:000932* ID_OUI_FROM_DATABASE=Omnilux OUI:000939* ID_OUI_FROM_DATABASE=ShibaSoku Co.,Ltd. OUI:000926* ID_OUI_FROM_DATABASE=YODA COMMUNICATIONS, INC. OUI:00092B* ID_OUI_FROM_DATABASE=iQstor Networks, Inc. OUI:00092C* ID_OUI_FROM_DATABASE=Hitpoint Inc. OUI:00091F* ID_OUI_FROM_DATABASE=A&D Co., Ltd. OUI:000751* ID_OUI_FROM_DATABASE=m-u-t AG OUI:000750* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000746* ID_OUI_FROM_DATABASE=TURCK, Inc. OUI:00074A* ID_OUI_FROM_DATABASE=Carl Valentin GmbH OUI:00073A* ID_OUI_FROM_DATABASE=Inventel Systemes OUI:000734* ID_OUI_FROM_DATABASE=ONStor, Inc. OUI:000739* ID_OUI_FROM_DATABASE=Scotty Group Austria Gmbh OUI:00072D* ID_OUI_FROM_DATABASE=CNSystems OUI:000727* ID_OUI_FROM_DATABASE=Zi Corporation (HK) Ltd. OUI:000717* ID_OUI_FROM_DATABASE=Wieland Electric GmbH OUI:00071E* ID_OUI_FROM_DATABASE=Tri-M Engineering / Nupak Dev. Corp. OUI:000723* ID_OUI_FROM_DATABASE=ELCON Systemtechnik GmbH OUI:00071D* ID_OUI_FROM_DATABASE=Satelsa Sistemas Y Aplicaciones De Telecomunicaciones, S.A. OUI:000632* ID_OUI_FROM_DATABASE=Mesco Engineering GmbH OUI:000625* ID_OUI_FROM_DATABASE=The Linksys Group, Inc. OUI:00062C* ID_OUI_FROM_DATABASE=Bivio Networks OUI:000624* ID_OUI_FROM_DATABASE=Gentner Communications Corp. OUI:00061B* ID_OUI_FROM_DATABASE=Notebook Development Lab. Lenovo Japan Ltd. OUI:000622* ID_OUI_FROM_DATABASE=Chung Fu Chen Yeh Enterprise Corp. OUI:00061C* ID_OUI_FROM_DATABASE=Hoshino Metal Industries, Ltd. OUI:000621* ID_OUI_FROM_DATABASE=Hinox, Co., Ltd. OUI:00060B* ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies OUI:000611* ID_OUI_FROM_DATABASE=Zeus Wireless, Inc. OUI:000615* ID_OUI_FROM_DATABASE=Kimoto Electric Co., Ltd. OUI:000605* ID_OUI_FROM_DATABASE=Inncom International, Inc. OUI:0005E3* ID_OUI_FROM_DATABASE=LightSand Communications, Inc. OUI:0005EF* ID_OUI_FROM_DATABASE=ADOIR Digital Technology OUI:0005F6* ID_OUI_FROM_DATABASE=Young Chang Co. Ltd. OUI:0005E9* ID_OUI_FROM_DATABASE=Unicess Network, Inc. OUI:0005F0* ID_OUI_FROM_DATABASE=SATEC OUI:0005FC* ID_OUI_FROM_DATABASE=Schenck Pegasus Corp. OUI:0005E0* ID_OUI_FROM_DATABASE=Empirix Corp. OUI:0005D6* ID_OUI_FROM_DATABASE=L-3 Linkabit OUI:0005C4* ID_OUI_FROM_DATABASE=Telect, Inc. OUI:0005D0* ID_OUI_FROM_DATABASE=Solinet Systems OUI:0005CA* ID_OUI_FROM_DATABASE=Hitron Technology, Inc. OUI:0005BD* ID_OUI_FROM_DATABASE=ROAX BV OUI:0005BE* ID_OUI_FROM_DATABASE=Kongsberg Seatex AS OUI:0005C3* ID_OUI_FROM_DATABASE=Pacific Instruments, Inc. OUI:00059D* ID_OUI_FROM_DATABASE=Daniel Computing Systems, Inc. OUI:000796* ID_OUI_FROM_DATABASE=LSI Systems, Inc. OUI:000790* ID_OUI_FROM_DATABASE=Tri-M Technologies (s) Limited OUI:000784* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000789* ID_OUI_FROM_DATABASE=DONGWON SYSTEMS OUI:000783* ID_OUI_FROM_DATABASE=SynCom Network, Inc. OUI:00078A* ID_OUI_FROM_DATABASE=Mentor Data System Inc. OUI:00077A* ID_OUI_FROM_DATABASE=Infoware System Co., Ltd. OUI:00076D* ID_OUI_FROM_DATABASE=Flexlight Networks OUI:000769* ID_OUI_FROM_DATABASE=Italiana Macchi SpA OUI:000773* ID_OUI_FROM_DATABASE=Ascom Powerline Communications Ltd. OUI:00075D* ID_OUI_FROM_DATABASE=Celleritas Inc. OUI:000763* ID_OUI_FROM_DATABASE=Sunniwell Cyber Tech. Co., Ltd. OUI:000756* ID_OUI_FROM_DATABASE=Juyoung Telecom OUI:0007C9* ID_OUI_FROM_DATABASE=Technol Seven Co., Ltd. OUI:00047B* ID_OUI_FROM_DATABASE=Schlumberger OUI:0007C3* ID_OUI_FROM_DATABASE=Thomson OUI:0007BD* ID_OUI_FROM_DATABASE=Radionet Ltd. OUI:0007B0* ID_OUI_FROM_DATABASE=Office Details, Inc. OUI:0007B7* ID_OUI_FROM_DATABASE=Samurai Ind. Prods Eletronicos Ltda OUI:0007B6* ID_OUI_FROM_DATABASE=Telecom Technology Ltd. OUI:0007A3* ID_OUI_FROM_DATABASE=Ositis Software, Inc. OUI:0007A9* ID_OUI_FROM_DATABASE=Novasonics OUI:0007AC* ID_OUI_FROM_DATABASE=Eolring OUI:00079C* ID_OUI_FROM_DATABASE=Golden Electronics Technology Co., Ltd. OUI:0006AB* ID_OUI_FROM_DATABASE=W-Link Systems, Inc. OUI:0006A5* ID_OUI_FROM_DATABASE=PINON Corp. OUI:0006A1* ID_OUI_FROM_DATABASE=Celsian Technologies, Inc. OUI:000694* ID_OUI_FROM_DATABASE=Mobillian Corporation OUI:00069B* ID_OUI_FROM_DATABASE=AVT Audio Video Technologies GmbH OUI:00068E* ID_OUI_FROM_DATABASE=HID Corporation OUI:000688* ID_OUI_FROM_DATABASE=Telways Communication Co., Ltd. OUI:000682* ID_OUI_FROM_DATABASE=Convedia OUI:000681* ID_OUI_FROM_DATABASE=Goepel Electronic GmbH OUI:000655* ID_OUI_FROM_DATABASE=Yipee, Inc. OUI:00D05F* ID_OUI_FROM_DATABASE=VALCOM, INC. OUI:000674* ID_OUI_FROM_DATABASE=Spectrum Control, Inc. OUI:000678* ID_OUI_FROM_DATABASE=Marantz Brand Company OUI:000661* ID_OUI_FROM_DATABASE=NIA Home Technologies Corp. OUI:000668* ID_OUI_FROM_DATABASE=Vicon Industries Inc. OUI:000667* ID_OUI_FROM_DATABASE=Tripp Lite OUI:00066E* ID_OUI_FROM_DATABASE=Delta Electronics, Inc. OUI:00064E* ID_OUI_FROM_DATABASE=Broad Net Technology Inc. OUI:00064F* ID_OUI_FROM_DATABASE=PRO-NETS Technology Corporation OUI:000642* ID_OUI_FROM_DATABASE=Genetel Systems Inc. OUI:00063E* ID_OUI_FROM_DATABASE=Opthos Inc. OUI:000648* ID_OUI_FROM_DATABASE=Seedsware, Inc. OUI:000638* ID_OUI_FROM_DATABASE=Sungjin C&C Co., Ltd. OUI:00070B* ID_OUI_FROM_DATABASE=Novabase SGPS, SA OUI:000710* ID_OUI_FROM_DATABASE=Adax, Inc. OUI:000700* ID_OUI_FROM_DATABASE=Zettamedia Korea OUI:0006F9* ID_OUI_FROM_DATABASE=Mitsui Zosen Systems Research Inc. OUI:000703* ID_OUI_FROM_DATABASE=CSEE Transport OUI:000706* ID_OUI_FROM_DATABASE=Sanritz Corporation OUI:0006E8* ID_OUI_FROM_DATABASE=Optical Network Testing, Inc. OUI:0006EE* ID_OUI_FROM_DATABASE=Shenyang Neu-era Information & Technology Stock Co., Ltd OUI:0006E2* ID_OUI_FROM_DATABASE=Ceemax Technology Co., Ltd. OUI:0006D8* ID_OUI_FROM_DATABASE=Maple Optical Systems OUI:0006D4* ID_OUI_FROM_DATABASE=Interactive Objects, Inc. OUI:0006CE* ID_OUI_FROM_DATABASE=DATENO OUI:0006B7* ID_OUI_FROM_DATABASE=TELEM GmbH OUI:0006BE* ID_OUI_FROM_DATABASE=Baumer Optronic GmbH OUI:0006B8* ID_OUI_FROM_DATABASE=Bandspeed Pty Ltd OUI:0006BD* ID_OUI_FROM_DATABASE=BNTECHNOLOGY Co., Ltd. OUI:0006C2* ID_OUI_FROM_DATABASE=Smartmatic Corporation OUI:0006C7* ID_OUI_FROM_DATABASE=RFNET Technologies Pte Ltd (S) OUI:0006B1* ID_OUI_FROM_DATABASE=Sonicwall OUI:000475* ID_OUI_FROM_DATABASE=3 Com Corporation OUI:00046F* ID_OUI_FROM_DATABASE=Digitel S/A Industria Eletronica OUI:000468* ID_OUI_FROM_DATABASE=Vivity, Inc. OUI:00045C* ID_OUI_FROM_DATABASE=Mobiwave Pte Ltd OUI:000463* ID_OUI_FROM_DATABASE=Bosch Security Systems OUI:000462* ID_OUI_FROM_DATABASE=DAKOS Data & Communication Co., Ltd. OUI:000455* ID_OUI_FROM_DATABASE=ANTARA.net OUI:000456* ID_OUI_FROM_DATABASE=Cambium Networks Limited OUI:000450* ID_OUI_FROM_DATABASE=DMD Computers SRL OUI:000446* ID_OUI_FROM_DATABASE=CYZENTECH Co., Ltd. OUI:00044B* ID_OUI_FROM_DATABASE=NVIDIA OUI:0005AD* ID_OUI_FROM_DATABASE=Topspin Communications, Inc. OUI:0005B1* ID_OUI_FROM_DATABASE=ASB Technology BV OUI:0005B7* ID_OUI_FROM_DATABASE=Arbor Technology Corp. OUI:0005A3* ID_OUI_FROM_DATABASE=QEI, Inc. OUI:000597* ID_OUI_FROM_DATABASE=Eagle Traffic Control Systems OUI:000591* ID_OUI_FROM_DATABASE=Active Silicon Ltd OUI:00058A* ID_OUI_FROM_DATABASE=Netcom Co., Ltd. OUI:000590* ID_OUI_FROM_DATABASE=Swissvoice Ltd. OUI:00057E* ID_OUI_FROM_DATABASE=Eckelmann Steuerungstechnik GmbH OUI:000578* ID_OUI_FROM_DATABASE=Private OUI:000584* ID_OUI_FROM_DATABASE=AbsoluteValue Systems, Inc. OUI:00052E* ID_OUI_FROM_DATABASE=Cinta Networks OUI:00053A* ID_OUI_FROM_DATABASE=Willowglen Services Pte Ltd OUI:000528* ID_OUI_FROM_DATABASE=New Focus, Inc. OUI:000527* ID_OUI_FROM_DATABASE=SJ Tek Co. Ltd OUI:000521* ID_OUI_FROM_DATABASE=Control Microsystems OUI:000515* ID_OUI_FROM_DATABASE=Nuark Co., Ltd. OUI:00051B* ID_OUI_FROM_DATABASE=Magic Control Technology Corporation OUI:000511* ID_OUI_FROM_DATABASE=Complementary Technologies Ltd OUI:00050B* ID_OUI_FROM_DATABASE=SICOM Systems, Inc. OUI:000501* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000505* ID_OUI_FROM_DATABASE=Systems Integration Solutions, Inc. OUI:000504* ID_OUI_FROM_DATABASE=Naray Information & Communication Enterprise OUI:0004FB* ID_OUI_FROM_DATABASE=Commtech, Inc. OUI:000574* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000567* ID_OUI_FROM_DATABASE=Etymonic Design, Inc. OUI:00056E* ID_OUI_FROM_DATABASE=National Enhance Technology, Inc. OUI:00056D* ID_OUI_FROM_DATABASE=Pacific Corporation OUI:000561* ID_OUI_FROM_DATABASE=nac Image Technology, Inc. OUI:00055B* ID_OUI_FROM_DATABASE=Charles Industries, Ltd. OUI:000554* ID_OUI_FROM_DATABASE=Rangestar Wireless OUI:000555* ID_OUI_FROM_DATABASE=Japan Cash Machine Co., Ltd. OUI:000547* ID_OUI_FROM_DATABASE=Starent Networks OUI:00054E* ID_OUI_FROM_DATABASE=Philips OUI:000540* ID_OUI_FROM_DATABASE=FAST Corporation OUI:000541* ID_OUI_FROM_DATABASE=Advanced Systems Co., Ltd. OUI:000534* ID_OUI_FROM_DATABASE=Northstar Engineering Ltd. OUI:0004F4* ID_OUI_FROM_DATABASE=Infinite Electronics Inc. OUI:0004EE* ID_OUI_FROM_DATABASE=Lincoln Electric Company OUI:0004E8* ID_OUI_FROM_DATABASE=IER, Inc. OUI:008086* ID_OUI_FROM_DATABASE=COMPUTER GENERATION INC. OUI:0004DE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0004E4* ID_OUI_FROM_DATABASE=Daeryung Ind., Inc. OUI:0004D7* ID_OUI_FROM_DATABASE=Omitec Instrumentation Ltd. OUI:0004D8* ID_OUI_FROM_DATABASE=IPWireless, Inc. OUI:0004D2* ID_OUI_FROM_DATABASE=Adcon Telemetry GmbH OUI:0004D1* ID_OUI_FROM_DATABASE=Drew Technologies, Inc. OUI:0004CB* ID_OUI_FROM_DATABASE=Tdsoft Communication, Ltd. OUI:0004BF* ID_OUI_FROM_DATABASE=VersaLogic Corp. OUI:0004C5* ID_OUI_FROM_DATABASE=ASE Technologies, USA OUI:00043F* ID_OUI_FROM_DATABASE=ESTeem Wireless Modems, Inc OUI:000439* ID_OUI_FROM_DATABASE=Rosco Entertainment Technology, Inc. OUI:000433* ID_OUI_FROM_DATABASE=Cyberboard A/S OUI:00042C* ID_OUI_FROM_DATABASE=Minet, Inc. OUI:000427* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000426* ID_OUI_FROM_DATABASE=Autosys OUI:000420* ID_OUI_FROM_DATABASE=Slim Devices, Inc. OUI:000413* ID_OUI_FROM_DATABASE=SNOM Technology AG OUI:000418* ID_OUI_FROM_DATABASE=Teltronic S.A.U. OUI:000412* ID_OUI_FROM_DATABASE=WaveSmith Networks, Inc. OUI:00040C* ID_OUI_FROM_DATABASE=Kanno Works, Ltd. OUI:000370* ID_OUI_FROM_DATABASE=NXTV, Inc. OUI:000405* ID_OUI_FROM_DATABASE=ACN Technologies OUI:000406* ID_OUI_FROM_DATABASE=Fa. Metabox AG OUI:0003FB* ID_OUI_FROM_DATABASE=ENEGATE Co.,Ltd. OUI:0003FC* ID_OUI_FROM_DATABASE=Intertex Data AB OUI:0003EF* ID_OUI_FROM_DATABASE=Oneline AG OUI:0003F6* ID_OUI_FROM_DATABASE=Allegro Networks, Inc. OUI:0003EA* ID_OUI_FROM_DATABASE=Mega System Technologies, Inc. OUI:0003E9* ID_OUI_FROM_DATABASE=Akara Canada, Inc. OUI:0003E4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0003D8* ID_OUI_FROM_DATABASE=iMPath Networks, Inc. OUI:0003D5* ID_OUI_FROM_DATABASE=Advanced Communications Co., Ltd. OUI:0003CC* ID_OUI_FROM_DATABASE=Momentum Computer, Inc. OUI:0003D1* ID_OUI_FROM_DATABASE=Takaya Corporation OUI:0003C5* ID_OUI_FROM_DATABASE=Mobotix AG OUI:0003BE* ID_OUI_FROM_DATABASE=Netility OUI:0003B9* ID_OUI_FROM_DATABASE=Hualong Telecom Co., Ltd. OUI:0003B7* ID_OUI_FROM_DATABASE=ZACCESS Systems OUI:0003B3* ID_OUI_FROM_DATABASE=IA Link Systems Co., Ltd. OUI:0003A7* ID_OUI_FROM_DATABASE=Unixtar Technology, Inc. OUI:0003AE* ID_OUI_FROM_DATABASE=Allied Advanced Manufacturing Pte, Ltd. OUI:0003A0* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000398* ID_OUI_FROM_DATABASE=WISI OUI:00039B* ID_OUI_FROM_DATABASE=NetChip Technology, Inc. OUI:000394* ID_OUI_FROM_DATABASE=Connect One OUI:00038D* ID_OUI_FROM_DATABASE=PCS Revenue Control Systems, Inc. OUI:000385* ID_OUI_FROM_DATABASE=Actelis Networks, Inc. OUI:000388* ID_OUI_FROM_DATABASE=Fastfame Technology Co., Ltd. OUI:00037F* ID_OUI_FROM_DATABASE=Atheros Communications, Inc. OUI:0004B8* ID_OUI_FROM_DATABASE=Kumahira Co., Ltd. OUI:0004B2* ID_OUI_FROM_DATABASE=ESSEGI SRL OUI:0004AE* ID_OUI_FROM_DATABASE=Sullair Corporation OUI:0004AB* ID_OUI_FROM_DATABASE=Comverse Network Systems, Inc. OUI:00049F* ID_OUI_FROM_DATABASE=Freescale Semiconductor OUI:0004A4* ID_OUI_FROM_DATABASE=NetEnabled, Inc. OUI:00049E* ID_OUI_FROM_DATABASE=Wirelink Co., Ltd. OUI:000498* ID_OUI_FROM_DATABASE=Mahi Networks OUI:000491* ID_OUI_FROM_DATABASE=Technovision, Inc. OUI:00048C* ID_OUI_FROM_DATABASE=Nayna Networks, Inc. OUI:000492* ID_OUI_FROM_DATABASE=Hive Internet, Ltd. OUI:000485* ID_OUI_FROM_DATABASE=PicoLight OUI:000307* ID_OUI_FROM_DATABASE=Secure Works, Inc. OUI:000300* ID_OUI_FROM_DATABASE=Barracuda Networks, Inc. OUI:0002F8* ID_OUI_FROM_DATABASE=SEAKR Engineering, Inc. OUI:00D024* ID_OUI_FROM_DATABASE=Cognex Corporation OUI:0002F4* ID_OUI_FROM_DATABASE=PCTEL, Inc. OUI:0002FB* ID_OUI_FROM_DATABASE=Baumuller Aulugen-Systemtechnik GmbH OUI:0002E9* ID_OUI_FROM_DATABASE=CS Systemes De Securite - C3S OUI:0002DD* ID_OUI_FROM_DATABASE=Bromax Communications, Ltd. OUI:0002E2* ID_OUI_FROM_DATABASE=NDC Infared Engineering OUI:0002DA* ID_OUI_FROM_DATABASE=ExiO Communications, Inc. OUI:0002D6* ID_OUI_FROM_DATABASE=NICE Systems OUI:0002CA* ID_OUI_FROM_DATABASE=EndPoints, Inc. OUI:0002CF* ID_OUI_FROM_DATABASE=ZyGate Communications, Inc. OUI:0001CD* ID_OUI_FROM_DATABASE=ARtem OUI:0001D2* ID_OUI_FROM_DATABASE=inXtron, Inc. OUI:0001C9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0001C7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0001C2* ID_OUI_FROM_DATABASE=ARK Research Corp. OUI:0001BE* ID_OUI_FROM_DATABASE=Gigalink Co., Ltd. OUI:0001BC* ID_OUI_FROM_DATABASE=Brains Corporation OUI:0001AC* ID_OUI_FROM_DATABASE=Sitara Networks, Inc. OUI:0001A9* ID_OUI_FROM_DATABASE=BMW AG OUI:0001B0* ID_OUI_FROM_DATABASE=Fulltek Technology Co., Ltd. OUI:000179* ID_OUI_FROM_DATABASE=WIRELESS TECHNOLOGY, INC. OUI:000185* ID_OUI_FROM_DATABASE=Hitachi Aloka Medical, Ltd. OUI:00018C* ID_OUI_FROM_DATABASE=Mega Vision OUI:000192* ID_OUI_FROM_DATABASE=Texas Digital Systems OUI:00019E* ID_OUI_FROM_DATABASE=ESS Technology, Inc. OUI:001095* ID_OUI_FROM_DATABASE=Thomson Inc. OUI:000278* ID_OUI_FROM_DATABASE=Samsung Electro-Mechanics Co., Ltd. OUI:00025A* ID_OUI_FROM_DATABASE=Catena Networks OUI:000271* ID_OUI_FROM_DATABASE=Zhone Technologies OUI:00026C* ID_OUI_FROM_DATABASE=Philips CFT OUI:00026A* ID_OUI_FROM_DATABASE=Cocess Telecom Co., Ltd. OUI:000266* ID_OUI_FROM_DATABASE=Thermalogic Corporation OUI:00025F* ID_OUI_FROM_DATABASE=Nortel Networks OUI:000256* ID_OUI_FROM_DATABASE=Alpha Processor, Inc. OUI:000251* ID_OUI_FROM_DATABASE=Soma Networks, Inc. OUI:00024A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00024D* ID_OUI_FROM_DATABASE=Mannesman Dematic Colby Pty. Ltd. OUI:000245* ID_OUI_FROM_DATABASE=Lampus Co, Ltd. OUI:00023E* ID_OUI_FROM_DATABASE=Selta Telematica S.p.a OUI:00023B* ID_OUI_FROM_DATABASE=Ericsson OUI:000237* ID_OUI_FROM_DATABASE=Cosmo Research Corp. OUI:000234* ID_OUI_FROM_DATABASE=Imperial Technology, Inc. OUI:000228* ID_OUI_FROM_DATABASE=Necsom, Ltd. OUI:000224* ID_OUI_FROM_DATABASE=C-COR OUI:00020D* ID_OUI_FROM_DATABASE=Micronpc.com OUI:000220* ID_OUI_FROM_DATABASE=CANON FINETECH INC. OUI:000378* ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. OUI:00036C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000373* ID_OUI_FROM_DATABASE=Aselsan A.S OUI:000368* ID_OUI_FROM_DATABASE=Embedone Co., Ltd. OUI:000366* ID_OUI_FROM_DATABASE=ASM Pacific Technology OUI:000365* ID_OUI_FROM_DATABASE=Kira Information & Communications, Ltd. OUI:000360* ID_OUI_FROM_DATABASE=PAC Interactive Technology, Inc. OUI:00035D* ID_OUI_FROM_DATABASE=Bosung Hi-Net Co., Ltd. OUI:00031A* ID_OUI_FROM_DATABASE=Beijing Broad Telecom Ltd., China OUI:000359* ID_OUI_FROM_DATABASE=DigitalSis OUI:000354* ID_OUI_FROM_DATABASE=Fiber Logic Communications OUI:000352* ID_OUI_FROM_DATABASE=Colubris Networks OUI:00034E* ID_OUI_FROM_DATABASE=Pos Data Company, Ltd. OUI:000342* ID_OUI_FROM_DATABASE=Nortel Networks OUI:0002C3* ID_OUI_FROM_DATABASE=Arelnet Ltd. OUI:0002BE* ID_OUI_FROM_DATABASE=Totsu Engineering, Inc. OUI:0002BA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0002B2* ID_OUI_FROM_DATABASE=Cablevision OUI:0002B5* ID_OUI_FROM_DATABASE=Avnet, Inc. OUI:0002AE* ID_OUI_FROM_DATABASE=Scannex Electronics Ltd. OUI:0002A7* ID_OUI_FROM_DATABASE=Vivace Networks OUI:0002A2* ID_OUI_FROM_DATABASE=Hilscher GmbH OUI:000297* ID_OUI_FROM_DATABASE=C-COR.net OUI:00028E* ID_OUI_FROM_DATABASE=Rapid 5 Networks, Inc. OUI:000293* ID_OUI_FROM_DATABASE=Solid Data Systems OUI:0001FA* ID_OUI_FROM_DATABASE=HOROSCAS OUI:000284* ID_OUI_FROM_DATABASE=AREVA T&D OUI:00027D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00033F* ID_OUI_FROM_DATABASE=BigBand Networks, Ltd. OUI:000336* ID_OUI_FROM_DATABASE=Zetes Technologies OUI:00033B* ID_OUI_FROM_DATABASE=TAMI Tech Co., Ltd. OUI:000328* ID_OUI_FROM_DATABASE=Mace Group, Inc. OUI:00032F* ID_OUI_FROM_DATABASE=Global Sun Technology, Inc. OUI:000320* ID_OUI_FROM_DATABASE=Xpeed, Inc. OUI:000323* ID_OUI_FROM_DATABASE=Cornet Technology, Inc. OUI:00029F* ID_OUI_FROM_DATABASE=L-3 Communication Aviation Recorders OUI:00031F* ID_OUI_FROM_DATABASE=Condev Ltd. OUI:000317* ID_OUI_FROM_DATABASE=Merlin Systems, Inc. OUI:00030E* ID_OUI_FROM_DATABASE=Core Communications Co., Ltd. OUI:000313* ID_OUI_FROM_DATABASE=Access Media SPA OUI:0001A5* ID_OUI_FROM_DATABASE=Nextcomm, Inc. OUI:0001A1* ID_OUI_FROM_DATABASE=Mag-Tek, Inc. OUI:000195* ID_OUI_FROM_DATABASE=Sena Technologies, Inc. OUI:00017D* ID_OUI_FROM_DATABASE=ThermoQuest OUI:000189* ID_OUI_FROM_DATABASE=Refraction Technology, Inc. OUI:00308B* ID_OUI_FROM_DATABASE=Brix Networks OUI:00014F* ID_OUI_FROM_DATABASE=ADTRAN INC OUI:00015A* ID_OUI_FROM_DATABASE=Digital Video Broadcasting OUI:000166* ID_OUI_FROM_DATABASE=TC GROUP A/S OUI:00016D* ID_OUI_FROM_DATABASE=CarrierComm Inc. OUI:00015F* ID_OUI_FROM_DATABASE=DIGITAL DESIGN GmbH OUI:000214* ID_OUI_FROM_DATABASE=DTVRO OUI:000210* ID_OUI_FROM_DATABASE=Fenecom OUI:000208* ID_OUI_FROM_DATABASE=Unify Networks, Inc. OUI:000201* ID_OUI_FROM_DATABASE=IFM Electronic gmbh OUI:0001F5* ID_OUI_FROM_DATABASE=ERIM S.A. OUI:0001FD* ID_OUI_FROM_DATABASE=Digital Voice Systems, Inc. OUI:0001E5* ID_OUI_FROM_DATABASE=Supernet, Inc. OUI:0001E8* ID_OUI_FROM_DATABASE=Force10 Networks, Inc. OUI:0001D9* ID_OUI_FROM_DATABASE=Sigma, Inc. OUI:0001E0* ID_OUI_FROM_DATABASE=Fast Systems, Inc. OUI:0001D5* ID_OUI_FROM_DATABASE=HAEDONG INFO & COMM CO., LTD OUI:000118* ID_OUI_FROM_DATABASE=EZ Digital Co., Ltd. OUI:000124* ID_OUI_FROM_DATABASE=Acer Incorporated OUI:000101* ID_OUI_FROM_DATABASE=Private OUI:00010D* ID_OUI_FROM_DATABASE=CORECO, INC. OUI:000114* ID_OUI_FROM_DATABASE=KANDA TSUSHIN KOGYO CO., LTD. OUI:000111* ID_OUI_FROM_DATABASE=iDigm Inc. OUI:000105* ID_OUI_FROM_DATABASE=Beckhoff Automation GmbH OUI:00029C* ID_OUI_FROM_DATABASE=3COM OUI:00B009* ID_OUI_FROM_DATABASE=Grass Valley, A Belden Brand OUI:00B0B3* ID_OUI_FROM_DATABASE=Xstreamis PLC OUI:00B09D* ID_OUI_FROM_DATABASE=Point Grey Research Inc. OUI:00B094* ID_OUI_FROM_DATABASE=Alaris, Inc. OUI:00B048* ID_OUI_FROM_DATABASE=Marconi Communications Inc. OUI:00B0C7* ID_OUI_FROM_DATABASE=Tellabs Operations, Inc. OUI:003060* ID_OUI_FROM_DATABASE=Powerfile, Inc. OUI:00301C* ID_OUI_FROM_DATABASE=ALTVATER AIRDATA SYSTEMS OUI:003015* ID_OUI_FROM_DATABASE=CP CLARE CORP. OUI:0030E6* ID_OUI_FROM_DATABASE=Draeger Medical Systems, Inc. OUI:003091* ID_OUI_FROM_DATABASE=TAIWAN FIRST LINE ELEC. CORP. OUI:003080* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0030AD* ID_OUI_FROM_DATABASE=SHANGHAI COMMUNICATION OUI:00305B* ID_OUI_FROM_DATABASE=Toko Inc. OUI:003024* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00301F* ID_OUI_FROM_DATABASE=OPTICAL NETWORKS, INC. OUI:0030D9* ID_OUI_FROM_DATABASE=DATACORE SOFTWARE CORP. OUI:00D0FF* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:003058* ID_OUI_FROM_DATABASE=API MOTION OUI:0030C6* ID_OUI_FROM_DATABASE=CONTROL SOLUTIONS, INC. OUI:003036* ID_OUI_FROM_DATABASE=RMP ELEKTRONIKSYSTEME GMBH OUI:00308A* ID_OUI_FROM_DATABASE=NICOTRA SISTEMI S.P.A OUI:00302C* ID_OUI_FROM_DATABASE=SYLANTRO SYSTEMS CORPORATION OUI:003006* ID_OUI_FROM_DATABASE=SUPERPOWER COMPUTER OUI:003079* ID_OUI_FROM_DATABASE=CQOS, INC. OUI:003059* ID_OUI_FROM_DATABASE=KONTRON COMPACT COMPUTERS AG OUI:0030B9* ID_OUI_FROM_DATABASE=ECTEL OUI:00303A* ID_OUI_FROM_DATABASE=MAATEL OUI:0030A3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:003040* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:003064* ID_OUI_FROM_DATABASE=ADLINK TECHNOLOGY, INC. OUI:003097* ID_OUI_FROM_DATABASE=AB Regin OUI:0030EB* ID_OUI_FROM_DATABASE=TURBONET COMMUNICATIONS, INC. OUI:0030C8* ID_OUI_FROM_DATABASE=GAD LINE, LTD. OUI:0030C9* ID_OUI_FROM_DATABASE=LuxN, N OUI:00B01E* ID_OUI_FROM_DATABASE=Rantic Labs, Inc. OUI:00B064* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0030A2* ID_OUI_FROM_DATABASE=Lightner Engineering OUI:0030DE* ID_OUI_FROM_DATABASE=WAGO Kontakttechnik GmbH OUI:00309E* ID_OUI_FROM_DATABASE=WORKBIT CORPORATION. OUI:003057* ID_OUI_FROM_DATABASE=QTelNet, Inc. OUI:00305C* ID_OUI_FROM_DATABASE=SMAR Laboratories Corp. OUI:003082* ID_OUI_FROM_DATABASE=TAIHAN ELECTRIC WIRE CO., LTD. OUI:0030AE* ID_OUI_FROM_DATABASE=Times N System, Inc. OUI:00300D* ID_OUI_FROM_DATABASE=MMC Technology, Inc. OUI:003075* ID_OUI_FROM_DATABASE=ADTECH OUI:0030E7* ID_OUI_FROM_DATABASE=CNF MOBILE SOLUTIONS, INC. OUI:003019* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:003052* ID_OUI_FROM_DATABASE=ELASTIC NETWORKS OUI:003011* ID_OUI_FROM_DATABASE=HMS Industrial Networks OUI:00304A* ID_OUI_FROM_DATABASE=Fraunhofer IPMS OUI:003014* ID_OUI_FROM_DATABASE=DIVIO, INC. OUI:003029* ID_OUI_FROM_DATABASE=OPICOM OUI:0030BD* ID_OUI_FROM_DATABASE=BELKIN COMPONENTS OUI:0030BA* ID_OUI_FROM_DATABASE=AC&T SYSTEM CO., LTD. OUI:00301D* ID_OUI_FROM_DATABASE=SKYSTREAM, INC. OUI:003049* ID_OUI_FROM_DATABASE=BRYANT TECHNOLOGY, LTD. OUI:003041* ID_OUI_FROM_DATABASE=SAEJIN T & M CO., LTD. OUI:00308C* ID_OUI_FROM_DATABASE=Quantum Corporation OUI:00D04F* ID_OUI_FROM_DATABASE=BITRONICS, INC. OUI:00D0EF* ID_OUI_FROM_DATABASE=IGT OUI:00D022* ID_OUI_FROM_DATABASE=INCREDIBLE TECHNOLOGIES, INC. OUI:00D0C8* ID_OUI_FROM_DATABASE=Prevas A/S OUI:00D052* ID_OUI_FROM_DATABASE=ASCEND COMMUNICATIONS, INC. OUI:00D0B1* ID_OUI_FROM_DATABASE=OMEGA ELECTRONICS SA OUI:00D0C1* ID_OUI_FROM_DATABASE=HARMONIC DATA SYSTEMS, LTD. OUI:00D0F0* ID_OUI_FROM_DATABASE=CONVISION TECHNOLOGY GMBH OUI:00D00E* ID_OUI_FROM_DATABASE=PLURIS, INC. OUI:00D055* ID_OUI_FROM_DATABASE=KATHREIN-WERKE KG OUI:00D095* ID_OUI_FROM_DATABASE=Alcatel-Lucent, Enterprise Business Group OUI:00D000* ID_OUI_FROM_DATABASE=FERRAN SCIENTIFIC, INC. OUI:00D005* ID_OUI_FROM_DATABASE=ZHS ZEITMANAGEMENTSYSTEME OUI:00D019* ID_OUI_FROM_DATABASE=DAINIPPON SCREEN CORPORATE OUI:00D053* ID_OUI_FROM_DATABASE=CONNECTED SYSTEMS OUI:00D097* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00016A* ID_OUI_FROM_DATABASE=ALITEC OUI:000176* ID_OUI_FROM_DATABASE=Orient Silver Enterprises OUI:000158* ID_OUI_FROM_DATABASE=Electro Industries/Gauge Tech OUI:00012D* ID_OUI_FROM_DATABASE=Komodo Technology OUI:000139* ID_OUI_FROM_DATABASE=Point Multimedia Systems OUI:000140* ID_OUI_FROM_DATABASE=Sendtek Corporation OUI:00014C* ID_OUI_FROM_DATABASE=Berkeley Process Control OUI:000135* ID_OUI_FROM_DATABASE=KDC Corp. OUI:00013C* ID_OUI_FROM_DATABASE=TIW SYSTEMS OUI:000148* ID_OUI_FROM_DATABASE=X-traWeb Inc. OUI:000120* ID_OUI_FROM_DATABASE=OSCILLOQUARTZ S.A. OUI:000127* ID_OUI_FROM_DATABASE=OPEN Networks Pty Ltd OUI:00309C* ID_OUI_FROM_DATABASE=Timing Applications, Inc. OUI:003086* ID_OUI_FROM_DATABASE=Transistor Devices, Inc. OUI:0030B5* ID_OUI_FROM_DATABASE=Tadiran Microwave Networks OUI:003070* ID_OUI_FROM_DATABASE=1Net Corporation OUI:003044* ID_OUI_FROM_DATABASE=CradlePoint, Inc OUI:00307E* ID_OUI_FROM_DATABASE=Redflex Communication Systems OUI:00307A* ID_OUI_FROM_DATABASE=Advanced Technology & Systems OUI:0030B7* ID_OUI_FROM_DATABASE=Teletrol Systems, Inc. OUI:0030B3* ID_OUI_FROM_DATABASE=San Valley Systems, Inc. OUI:00303B* ID_OUI_FROM_DATABASE=PowerCom Technology OUI:0030BC* ID_OUI_FROM_DATABASE=Optronic AG OUI:003071* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:009003* ID_OUI_FROM_DATABASE=APLIO OUI:0090D7* ID_OUI_FROM_DATABASE=NetBoost Corp. OUI:009093* ID_OUI_FROM_DATABASE=NANAO CORPORATION OUI:0090B4* ID_OUI_FROM_DATABASE=WILLOWBROOK TECHNOLOGIES OUI:009083* ID_OUI_FROM_DATABASE=TURBO COMMUNICATION, INC. OUI:0090BD* ID_OUI_FROM_DATABASE=OMNIA COMMUNICATIONS, INC. OUI:009094* ID_OUI_FROM_DATABASE=OSPREY TECHNOLOGIES, INC. OUI:0090DD* ID_OUI_FROM_DATABASE=MIHARU COMMUNICATIONS Inc OUI:009028* ID_OUI_FROM_DATABASE=NIPPON SIGNAL CO., LTD. OUI:00908C* ID_OUI_FROM_DATABASE=ETREND ELECTRONICS, INC. OUI:00905D* ID_OUI_FROM_DATABASE=NETCOM SICHERHEITSTECHNIK GMBH OUI:009068* ID_OUI_FROM_DATABASE=DVT CORP. OUI:009030* ID_OUI_FROM_DATABASE=HONEYWELL-DATING OUI:0090D3* ID_OUI_FROM_DATABASE=GIESECKE & DEVRIENT GmbH OUI:005081* ID_OUI_FROM_DATABASE=MURATA MACHINERY, LTD. OUI:0050CB* ID_OUI_FROM_DATABASE=JETTER OUI:00500E* ID_OUI_FROM_DATABASE=CHROMATIS NETWORKS, INC. OUI:0050FD* ID_OUI_FROM_DATABASE=VISIONCOMM CO., LTD. OUI:0050FE* ID_OUI_FROM_DATABASE=PCTVnet ASA OUI:0050AB* ID_OUI_FROM_DATABASE=NALTEC, Inc. OUI:005006* ID_OUI_FROM_DATABASE=TAC AB OUI:0050BF* ID_OUI_FROM_DATABASE=Metalligence Technology Corp. OUI:005089* ID_OUI_FROM_DATABASE=SAFETY MANAGEMENT SYSTEMS OUI:005066* ID_OUI_FROM_DATABASE=AtecoM GmbH advanced telecomunication modules OUI:0050D9* ID_OUI_FROM_DATABASE=ENGETRON-ENGENHARIA ELETRONICA IND. e COM. LTDA OUI:005043* ID_OUI_FROM_DATABASE=MARVELL SEMICONDUCTOR, INC. OUI:005018* ID_OUI_FROM_DATABASE=AMIT, Inc. OUI:005059* ID_OUI_FROM_DATABASE=iBAHN OUI:00506A* ID_OUI_FROM_DATABASE=EDEVA, INC. OUI:00502E* ID_OUI_FROM_DATABASE=CAMBEX CORPORATION OUI:005070* ID_OUI_FROM_DATABASE=CHAINTECH COMPUTER CO., LTD. OUI:00503B* ID_OUI_FROM_DATABASE=MEDIAFIRE CORPORATION OUI:005084* ID_OUI_FROM_DATABASE=ATL PRODUCTS OUI:005055* ID_OUI_FROM_DATABASE=DOMS A/S OUI:00504B* ID_OUI_FROM_DATABASE=BARCONET N.V. OUI:005046* ID_OUI_FROM_DATABASE=MENICX INTERNATIONAL CO., LTD. OUI:00502C* ID_OUI_FROM_DATABASE=SOYO COMPUTER, INC. OUI:005060* ID_OUI_FROM_DATABASE=TANDBERG TELECOM AS OUI:0050DD* ID_OUI_FROM_DATABASE=SERRA SOLDADURA, S.A. OUI:00503F* ID_OUI_FROM_DATABASE=ANCHOR GAMES OUI:0050EE* ID_OUI_FROM_DATABASE=TEK DIGITEL CORPORATION OUI:005004* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:005072* ID_OUI_FROM_DATABASE=CORVIS CORPORATION OUI:005012* ID_OUI_FROM_DATABASE=CBL - GMBH OUI:0050E8* ID_OUI_FROM_DATABASE=NOMADIX INC. OUI:0050F2* ID_OUI_FROM_DATABASE=MICROSOFT CORP. OUI:005052* ID_OUI_FROM_DATABASE=TIARA NETWORKS, INC. OUI:005064* ID_OUI_FROM_DATABASE=CAE ELECTRONICS OUI:0050B4* ID_OUI_FROM_DATABASE=SATCHWELL CONTROL SYSTEMS, LTD OUI:0050B2* ID_OUI_FROM_DATABASE=BRODEL GmbH OUI:00D081* ID_OUI_FROM_DATABASE=RTD Embedded Technologies, Inc. OUI:00D011* ID_OUI_FROM_DATABASE=PRISM VIDEO, INC. OUI:00D09B* ID_OUI_FROM_DATABASE=SPECTEL LTD. OUI:00D031* ID_OUI_FROM_DATABASE=INDUSTRIAL LOGIC CORPORATION OUI:00D021* ID_OUI_FROM_DATABASE=REGENT ELECTRONICS CORP. OUI:00D0DF* ID_OUI_FROM_DATABASE=KUZUMI ELECTRONICS, INC. OUI:00D0B4* ID_OUI_FROM_DATABASE=KATSUJIMA CO., LTD. OUI:00D079* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00D0E2* ID_OUI_FROM_DATABASE=MRT MICRO, INC. OUI:00D039* ID_OUI_FROM_DATABASE=UTILICOM, INC. OUI:00504F* ID_OUI_FROM_DATABASE=OLENCOM ELECTRONICS OUI:0050A0* ID_OUI_FROM_DATABASE=DELTA COMPUTER SYSTEMS, INC. OUI:005007* ID_OUI_FROM_DATABASE=SIEMENS TELECOMMUNICATION SYSTEMS LIMITED OUI:005015* ID_OUI_FROM_DATABASE=BRIGHT STAR ENGINEERING OUI:005031* ID_OUI_FROM_DATABASE=AEROFLEX LABORATORIES, INC. OUI:0050DF* ID_OUI_FROM_DATABASE=AirFiber, Inc. OUI:0050F3* ID_OUI_FROM_DATABASE=GLOBAL NET INFORMATION CO., Ltd. OUI:005038* ID_OUI_FROM_DATABASE=DAIN TELECOM CO., LTD. OUI:00D0E1* ID_OUI_FROM_DATABASE=AVIONITEK ISRAEL INC. OUI:00D01B* ID_OUI_FROM_DATABASE=MIMAKI ENGINEERING CO., LTD. OUI:00D06E* ID_OUI_FROM_DATABASE=TRENDVIEW RECORDERS LTD. OUI:00D075* ID_OUI_FROM_DATABASE=ALARIS MEDICAL SYSTEMS, INC. OUI:00509D* ID_OUI_FROM_DATABASE=THE INDUSTREE B.V. OUI:00501E* ID_OUI_FROM_DATABASE=Grass Valley, A Belden Brand OUI:00502B* ID_OUI_FROM_DATABASE=GENRAD LTD. OUI:00500A* ID_OUI_FROM_DATABASE=IRIS TECHNOLOGIES, INC. OUI:00D027* ID_OUI_FROM_DATABASE=APPLIED AUTOMATION, INC. OUI:00D0F6* ID_OUI_FROM_DATABASE=Alcatel Canada OUI:00D0F1* ID_OUI_FROM_DATABASE=SEGA ENTERPRISES, LTD. OUI:00D009* ID_OUI_FROM_DATABASE=HSING TECH. ENTERPRISE CO. LTD OUI:00D080* ID_OUI_FROM_DATABASE=EXABYTE CORPORATION OUI:00D084* ID_OUI_FROM_DATABASE=NEXCOMM SYSTEMS, INC. OUI:00D0B2* ID_OUI_FROM_DATABASE=XIOTECH CORPORATION OUI:00D0E6* ID_OUI_FROM_DATABASE=IBOND INC. OUI:00D099* ID_OUI_FROM_DATABASE=Elcard Wireless Systems Oy OUI:0090AF* ID_OUI_FROM_DATABASE=J. MORITA MFG. CORP. OUI:009088* ID_OUI_FROM_DATABASE=BAXALL SECURITY LTD. OUI:0090E0* ID_OUI_FROM_DATABASE=SYSTRAN CORP. OUI:00903E* ID_OUI_FROM_DATABASE=N.V. PHILIPS INDUSTRIAL ACTIVITIES OUI:0090B9* ID_OUI_FROM_DATABASE=BERAN INSTRUMENTS LTD. OUI:00901A* ID_OUI_FROM_DATABASE=UNISPHERE SOLUTIONS OUI:009082* ID_OUI_FROM_DATABASE=FORCE INSTITUTE OUI:00906A* ID_OUI_FROM_DATABASE=TURNSTONE SYSTEMS, INC. OUI:0001FE* ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION OUI:009077* ID_OUI_FROM_DATABASE=ADVANCED FIBRE COMMUNICATIONS OUI:0090B2* ID_OUI_FROM_DATABASE=AVICI SYSTEMS INC. OUI:009095* ID_OUI_FROM_DATABASE=UNIVERSAL AVIONICS OUI:009012* ID_OUI_FROM_DATABASE=GLOBESPAN SEMICONDUCTOR, INC. OUI:0090B6* ID_OUI_FROM_DATABASE=FIBEX SYSTEMS OUI:0090F4* ID_OUI_FROM_DATABASE=LIGHTNING INSTRUMENTATION OUI:00904F* ID_OUI_FROM_DATABASE=ABB POWER T&D COMPANY, INC. OUI:00905A* ID_OUI_FROM_DATABASE=DEARBORN GROUP, INC. OUI:009066* ID_OUI_FROM_DATABASE=Troika Networks, Inc. OUI:00907A* ID_OUI_FROM_DATABASE=Spectralink, Inc OUI:0090F0* ID_OUI_FROM_DATABASE=Harmonic Video Systems Ltd. OUI:001047* ID_OUI_FROM_DATABASE=ECHO ELETRIC CO. LTD. OUI:00100C* ID_OUI_FROM_DATABASE=ITO CO., LTD. OUI:0010D0* ID_OUI_FROM_DATABASE=WITCOM, LTD. OUI:001006* ID_OUI_FROM_DATABASE=Thales Contact Solutions Ltd. OUI:0010D6* ID_OUI_FROM_DATABASE=Exelis OUI:001076* ID_OUI_FROM_DATABASE=EUREM GmbH OUI:00103F* ID_OUI_FROM_DATABASE=TOLLGRADE COMMUNICATIONS, INC. OUI:001034* ID_OUI_FROM_DATABASE=GNP Computers OUI:001012* ID_OUI_FROM_DATABASE=PROCESSOR SYSTEMS (I) PVT LTD OUI:0010C8* ID_OUI_FROM_DATABASE=COMMUNICATIONS ELECTRONICS SECURITY GROUP OUI:0010D1* ID_OUI_FROM_DATABASE=Top Layer Networks, Inc. OUI:0010F0* ID_OUI_FROM_DATABASE=RITTAL-WERK RUDOLF LOH GmbH & Co. OUI:00106A* ID_OUI_FROM_DATABASE=DIGITAL MICROWAVE CORPORATION OUI:001030* ID_OUI_FROM_DATABASE=EION Inc. OUI:0010A4* ID_OUI_FROM_DATABASE=XIRCOM OUI:001050* ID_OUI_FROM_DATABASE=RION CO., LTD. OUI:00109C* ID_OUI_FROM_DATABASE=M-SYSTEM CO., LTD. OUI:001064* ID_OUI_FROM_DATABASE=DNPG, LLC OUI:001020* ID_OUI_FROM_DATABASE=Hand Held Products Inc OUI:00106E* ID_OUI_FROM_DATABASE=TADIRAN COM. LTD. OUI:00105B* ID_OUI_FROM_DATABASE=NET INSIGHT AB OUI:001002* ID_OUI_FROM_DATABASE=ACTIA OUI:0010A0* ID_OUI_FROM_DATABASE=INNOVEX TECHNOLOGIES, INC. OUI:001074* ID_OUI_FROM_DATABASE=ATEN INTERNATIONAL CO., LTD. OUI:001057* ID_OUI_FROM_DATABASE=Rebel.com, Inc. OUI:0010BC* ID_OUI_FROM_DATABASE=Aastra Telecom OUI:001033* ID_OUI_FROM_DATABASE=ACCESSLAN COMMUNICATIONS, INC. OUI:0004AC* ID_OUI_FROM_DATABASE=IBM Corp OUI:0010B4* ID_OUI_FROM_DATABASE=ATMOSPHERE NETWORKS OUI:0010F9* ID_OUI_FROM_DATABASE=UNIQUE SYSTEMS, INC. OUI:001038* ID_OUI_FROM_DATABASE=MICRO RESEARCH INSTITUTE, INC. OUI:00100A* ID_OUI_FROM_DATABASE=WILLIAMS COMMUNICATIONS GROUP OUI:001080* ID_OUI_FROM_DATABASE=METAWAVE COMMUNICATIONS OUI:0010AB* ID_OUI_FROM_DATABASE=KOITO ELECTRIC INDUSTRIES, LTD. OUI:00903C* ID_OUI_FROM_DATABASE=ATLANTIC NETWORK SYSTEMS OUI:0090CE* ID_OUI_FROM_DATABASE=TETRA GmbH OUI:0090E3* ID_OUI_FROM_DATABASE=AVEX ELECTRONICS INC. OUI:00900B* ID_OUI_FROM_DATABASE=LANNER ELECTRONICS, INC. OUI:0090C8* ID_OUI_FROM_DATABASE=WAVERIDER COMMUNICATIONS (CANADA) INC. OUI:0090B7* ID_OUI_FROM_DATABASE=DIGITAL LIGHTWAVE, INC. OUI:009037* ID_OUI_FROM_DATABASE=ACUCOMM, INC. OUI:009059* ID_OUI_FROM_DATABASE=TELECOM DEVICE K.K. OUI:00E003* ID_OUI_FROM_DATABASE=NOKIA WIRELESS BUSINESS COMMUN OUI:00E0F3* ID_OUI_FROM_DATABASE=WebSprint Communications, Inc. OUI:00E013* ID_OUI_FROM_DATABASE=EASTERN ELECTRONIC CO., LTD. OUI:001063* ID_OUI_FROM_DATABASE=STARGUIDE DIGITAL NETWORKS OUI:0010A7* ID_OUI_FROM_DATABASE=UNEX TECHNOLOGY CORPORATION OUI:001039* ID_OUI_FROM_DATABASE=Vectron Systems AG OUI:0010C3* ID_OUI_FROM_DATABASE=CSI-CONTROL SYSTEMS OUI:00107F* ID_OUI_FROM_DATABASE=CRESTRON ELECTRONICS, INC. OUI:00102C* ID_OUI_FROM_DATABASE=Lasat Networks A/S OUI:0010B7* ID_OUI_FROM_DATABASE=COYOTE TECHNOLOGIES, LLC OUI:006064* ID_OUI_FROM_DATABASE=NETCOMM LIMITED OUI:0060CB* ID_OUI_FROM_DATABASE=HITACHI ZOSEN CORPORATION OUI:006090* ID_OUI_FROM_DATABASE=Artiza Networks Inc OUI:0060A9* ID_OUI_FROM_DATABASE=GESYTEC MBH OUI:0060F2* ID_OUI_FROM_DATABASE=LASERGRAPHICS, INC. OUI:006031* ID_OUI_FROM_DATABASE=HRK SYSTEMS OUI:0060A6* ID_OUI_FROM_DATABASE=PARTICLE MEASURING SYSTEMS OUI:006082* ID_OUI_FROM_DATABASE=NOVALINK TECHNOLOGIES, INC. OUI:006012* ID_OUI_FROM_DATABASE=POWER COMPUTING CORPORATION OUI:00604D* ID_OUI_FROM_DATABASE=MMC NETWORKS, INC. OUI:006048* ID_OUI_FROM_DATABASE=EMC CORPORATION OUI:00600F* ID_OUI_FROM_DATABASE=WESTELL, INC. OUI:0060E5* ID_OUI_FROM_DATABASE=FUJI AUTOMATION CO., LTD. OUI:006010* ID_OUI_FROM_DATABASE=NETWORK MACHINES, INC. OUI:006044* ID_OUI_FROM_DATABASE=LITTON/POLY-SCIENTIFIC OUI:00609B* ID_OUI_FROM_DATABASE=ASTRO-MED, INC. OUI:0060BE* ID_OUI_FROM_DATABASE=WEBTRONICS OUI:006052* ID_OUI_FROM_DATABASE=PERIPHERALS ENTERPRISE CO., Ltd. OUI:00E03F* ID_OUI_FROM_DATABASE=JATON CORPORATION OUI:00E0EB* ID_OUI_FROM_DATABASE=DIGICOM SYSTEMS, INCORPORATED OUI:00E00E* ID_OUI_FROM_DATABASE=AVALON IMAGING SYSTEMS, INC. OUI:00E0CD* ID_OUI_FROM_DATABASE=SAAB SENSIS CORPORATION OUI:00E0CB* ID_OUI_FROM_DATABASE=RESON, INC. OUI:00E048* ID_OUI_FROM_DATABASE=SDL COMMUNICATIONS, INC. OUI:00E083* ID_OUI_FROM_DATABASE=JATO TECHNOLOGIES, INC. OUI:00E03D* ID_OUI_FROM_DATABASE=FOCON ELECTRONIC SYSTEMS A/S OUI:00E0FA* ID_OUI_FROM_DATABASE=TRL TECHNOLOGY, LTD. OUI:00E02C* ID_OUI_FROM_DATABASE=AST COMPUTER OUI:00E00B* ID_OUI_FROM_DATABASE=ROOFTOP COMMUNICATIONS CORP. OUI:00E067* ID_OUI_FROM_DATABASE=eac AUTOMATION-CONSULTING GmbH OUI:00E058* ID_OUI_FROM_DATABASE=PHASE ONE DENMARK A/S OUI:00E089* ID_OUI_FROM_DATABASE=ION Networks, Inc. OUI:00E03B* ID_OUI_FROM_DATABASE=PROMINET CORPORATION OUI:006017* ID_OUI_FROM_DATABASE=TOKIMEC INC. OUI:0060E6* ID_OUI_FROM_DATABASE=SHOMITI SYSTEMS INCORPORATED OUI:006053* ID_OUI_FROM_DATABASE=TOYODA MACHINE WORKS, LTD. OUI:0060A0* ID_OUI_FROM_DATABASE=SWITCHED NETWORK TECHNOLOGIES, INC. OUI:006019* ID_OUI_FROM_DATABASE=Roche Diagnostics OUI:006033* ID_OUI_FROM_DATABASE=ACUITY IMAGING, INC. OUI:0060EE* ID_OUI_FROM_DATABASE=APOLLO OUI:006022* ID_OUI_FROM_DATABASE=VICOM SYSTEMS, INC. OUI:006013* ID_OUI_FROM_DATABASE=NETSTAL MASCHINEN AG OUI:0060F4* ID_OUI_FROM_DATABASE=ADVANCED COMPUTER SOLUTIONS, Inc. OUI:006011* ID_OUI_FROM_DATABASE=CRYSTAL SEMICONDUCTOR CORP. OUI:00600E* ID_OUI_FROM_DATABASE=WAVENET INTERNATIONAL, INC. OUI:0060C0* ID_OUI_FROM_DATABASE=Nera Networks AS OUI:00E062* ID_OUI_FROM_DATABASE=HOST ENGINEERING OUI:00E033* ID_OUI_FROM_DATABASE=E.E.P.D. GmbH OUI:00E079* ID_OUI_FROM_DATABASE=A.T.N.R. OUI:00E09C* ID_OUI_FROM_DATABASE=MII OUI:00E075* ID_OUI_FROM_DATABASE=Verilink Corporation OUI:00E07A* ID_OUI_FROM_DATABASE=MIKRODIDAKT AB OUI:00E03E* ID_OUI_FROM_DATABASE=ALFATECH, INC. OUI:00E09A* ID_OUI_FROM_DATABASE=Positron Inc. OUI:0060D7* ID_OUI_FROM_DATABASE=ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE (EPFL) OUI:006087* ID_OUI_FROM_DATABASE=KANSAI ELECTRIC CO., LTD. OUI:00E029* ID_OUI_FROM_DATABASE=STANDARD MICROSYSTEMS CORP. OUI:00606B* ID_OUI_FROM_DATABASE=Synclayer Inc. OUI:006073* ID_OUI_FROM_DATABASE=REDCREEK COMMUNICATIONS, INC. OUI:006039* ID_OUI_FROM_DATABASE=SanCom Technology, Inc. OUI:0060A5* ID_OUI_FROM_DATABASE=PERFORMANCE TELECOM CORP. OUI:0060B3* ID_OUI_FROM_DATABASE=Z-COM, INC. OUI:006089* ID_OUI_FROM_DATABASE=XATA OUI:00603C* ID_OUI_FROM_DATABASE=HAGIWARA SYS-COM CO., LTD. OUI:00602E* ID_OUI_FROM_DATABASE=CYCLADES CORPORATION OUI:006075* ID_OUI_FROM_DATABASE=PENTEK, INC. OUI:00601C* ID_OUI_FROM_DATABASE=TELXON CORPORATION OUI:006016* ID_OUI_FROM_DATABASE=CLARIION OUI:0060AD* ID_OUI_FROM_DATABASE=MegaChips Corporation OUI:0060B6* ID_OUI_FROM_DATABASE=LAND COMPUTER CO., LTD. OUI:006055* ID_OUI_FROM_DATABASE=CORNELL UNIVERSITY OUI:006015* ID_OUI_FROM_DATABASE=NET2NET CORPORATION OUI:00A01D* ID_OUI_FROM_DATABASE=Red Lion Controls, LP OUI:00A071* ID_OUI_FROM_DATABASE=VIDEO LOTTERY TECHNOLOGIES,INC OUI:00A052* ID_OUI_FROM_DATABASE=STANILITE ELECTRONICS PTY. LTD OUI:00A0EA* ID_OUI_FROM_DATABASE=ETHERCOM CORP. OUI:00A02E* ID_OUI_FROM_DATABASE=BRAND COMMUNICATIONS, LTD. OUI:00A0E2* ID_OUI_FROM_DATABASE=Keisokugiken Corporation OUI:00A0C5* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:00A058* ID_OUI_FROM_DATABASE=GLORY, LTD. OUI:00E093* ID_OUI_FROM_DATABASE=ACKFIN NETWORKS OUI:00E0E3* ID_OUI_FROM_DATABASE=SK-ELEKTRONIK GMBH OUI:00E066* ID_OUI_FROM_DATABASE=ProMax Systems, Inc. OUI:00E0DB* ID_OUI_FROM_DATABASE=ViaVideo Communications, Inc. OUI:00E0DF* ID_OUI_FROM_DATABASE=KEYMILE GmbH OUI:00E00D* ID_OUI_FROM_DATABASE=RADIANT SYSTEMS OUI:00E008* ID_OUI_FROM_DATABASE=AMAZING CONTROLS! INC. OUI:00E086* ID_OUI_FROM_DATABASE=Emerson Network Power, Avocent Division OUI:00E0E1* ID_OUI_FROM_DATABASE=G2 NETWORKS, INC. OUI:00E042* ID_OUI_FROM_DATABASE=Pacom Systems Ltd. OUI:00E08E* ID_OUI_FROM_DATABASE=UTSTARCOM OUI:00E095* ID_OUI_FROM_DATABASE=ADVANCED-VISION TECHNOLGIES CORP. OUI:006006* ID_OUI_FROM_DATABASE=SOTEC CO., LTD OUI:00603D* ID_OUI_FROM_DATABASE=3CX OUI:006029* ID_OUI_FROM_DATABASE=CARY PERIPHERALS INC. OUI:006043* ID_OUI_FROM_DATABASE=iDirect, INC. OUI:0060D1* ID_OUI_FROM_DATABASE=CASCADE COMMUNICATIONS OUI:0060CD* ID_OUI_FROM_DATABASE=VideoServer, Inc. OUI:006094* ID_OUI_FROM_DATABASE=IBM Corp OUI:0060D9* ID_OUI_FROM_DATABASE=TRANSYS NETWORKS INC. OUI:0060AA* ID_OUI_FROM_DATABASE=INTELLIGENT DEVICES INC. (IDI) OUI:00605A* ID_OUI_FROM_DATABASE=CELCORE, INC. OUI:006065* ID_OUI_FROM_DATABASE=BERNECKER & RAINER INDUSTRIE-ELEKTRONIC GmbH OUI:00E07B* ID_OUI_FROM_DATABASE=BAY NETWORKS OUI:00E077* ID_OUI_FROM_DATABASE=WEBGEAR, INC. OUI:00E0D2* ID_OUI_FROM_DATABASE=VERSANET COMMUNICATIONS, INC. OUI:00E04E* ID_OUI_FROM_DATABASE=SANYO DENKI CO., LTD. OUI:00E0DD* ID_OUI_FROM_DATABASE=ZENITH ELECTRONICS CORPORATION OUI:00E0D0* ID_OUI_FROM_DATABASE=NETSPEED, INC. OUI:00E02A* ID_OUI_FROM_DATABASE=TANDBERG TELEVISION AS OUI:00E05B* ID_OUI_FROM_DATABASE=WEST END SYSTEMS CORP. OUI:00E051* ID_OUI_FROM_DATABASE=TALX CORPORATION OUI:00A0F0* ID_OUI_FROM_DATABASE=TORONTO MICROELECTRONICS INC. OUI:00A049* ID_OUI_FROM_DATABASE=DIGITECH INDUSTRIES, INC. OUI:00A027* ID_OUI_FROM_DATABASE=FIREPOWER SYSTEMS, INC. OUI:00A0FF* ID_OUI_FROM_DATABASE=TELLABS OPERATIONS, INC. OUI:00A001* ID_OUI_FROM_DATABASE=DRS Signal Solutions OUI:00A0F1* ID_OUI_FROM_DATABASE=MTI OUI:00A046* ID_OUI_FROM_DATABASE=SCITEX CORP. LTD. OUI:00A0D9* ID_OUI_FROM_DATABASE=CONVEX COMPUTER CORPORATION OUI:00A0B5* ID_OUI_FROM_DATABASE=3H TECHNOLOGY OUI:00A0AC* ID_OUI_FROM_DATABASE=GILAT SATELLITE NETWORKS, LTD. OUI:00A057* ID_OUI_FROM_DATABASE=LANCOM Systems GmbH OUI:00A086* ID_OUI_FROM_DATABASE=AMBER WAVE SYSTEMS, INC. OUI:00A083* ID_OUI_FROM_DATABASE=ASIMMPHONY TURKEY OUI:00A091* ID_OUI_FROM_DATABASE=APPLICOM INTERNATIONAL OUI:00A004* ID_OUI_FROM_DATABASE=NETPOWER, INC. OUI:00A081* ID_OUI_FROM_DATABASE=ALCATEL DATA NETWORKS OUI:00A0D5* ID_OUI_FROM_DATABASE=SIERRA WIRELESS INC. OUI:00200F* ID_OUI_FROM_DATABASE=EBRAINS Inc OUI:0020C7* ID_OUI_FROM_DATABASE=AKAI Professional M.I. Corp. OUI:0020EB* ID_OUI_FROM_DATABASE=CINCINNATI MICROWAVE, INC. OUI:0020E3* ID_OUI_FROM_DATABASE=MCD KENCOM CORPORATION OUI:002013* ID_OUI_FROM_DATABASE=DIVERSIFIED TECHNOLOGY, INC. OUI:0020C1* ID_OUI_FROM_DATABASE=SAXA, Inc. OUI:002087* ID_OUI_FROM_DATABASE=MEMOTEC, INC. OUI:0020F9* ID_OUI_FROM_DATABASE=PARALINK NETWORKS, INC. OUI:00A0F9* ID_OUI_FROM_DATABASE=BINTEC COMMUNICATIONS GMBH OUI:00A0BC* ID_OUI_FROM_DATABASE=VIASAT, INCORPORATED OUI:00A003* ID_OUI_FROM_DATABASE=Siemens Switzerland Ltd., I B T HVP OUI:00A09E* ID_OUI_FROM_DATABASE=ICTV OUI:00A026* ID_OUI_FROM_DATABASE=TELDAT, S.A. OUI:00201A* ID_OUI_FROM_DATABASE=MRV Communications, Inc. OUI:002023* ID_OUI_FROM_DATABASE=T.C. TECHNOLOGIES PTY. LTD OUI:0020F3* ID_OUI_FROM_DATABASE=RAYNET CORPORATION OUI:002039* ID_OUI_FROM_DATABASE=SCINETS OUI:002038* ID_OUI_FROM_DATABASE=VME MICROSYSTEMS INTERNATIONAL CORPORATION OUI:00203E* ID_OUI_FROM_DATABASE=LogiCan Technologies, Inc. OUI:002055* ID_OUI_FROM_DATABASE=ALTECH CO., LTD. OUI:0020D9* ID_OUI_FROM_DATABASE=PANASONIC TECHNOLOGIES, INC./MIECO-US OUI:002080* ID_OUI_FROM_DATABASE=SYNERGY (UK) LTD. OUI:002026* ID_OUI_FROM_DATABASE=AMKLY SYSTEMS, INC. OUI:00203D* ID_OUI_FROM_DATABASE=Honeywell ECC OUI:002019* ID_OUI_FROM_DATABASE=OHLER GMBH OUI:002057* ID_OUI_FROM_DATABASE=TITZE DATENTECHNIK GmbH OUI:0020BE* ID_OUI_FROM_DATABASE=LAN ACCESS CORP. OUI:002022* ID_OUI_FROM_DATABASE=NMS Communications OUI:0020AA* ID_OUI_FROM_DATABASE=Ericsson Television Limited OUI:00208E* ID_OUI_FROM_DATABASE=CHEVIN SOFTWARE ENG. LTD. OUI:00203B* ID_OUI_FROM_DATABASE=WISDM LTD. OUI:002044* ID_OUI_FROM_DATABASE=GENITECH PTY LTD OUI:0020F5* ID_OUI_FROM_DATABASE=PANDATEL AG OUI:002021* ID_OUI_FROM_DATABASE=ALGORITHMS SOFTWARE PVT. LTD. OUI:002074* ID_OUI_FROM_DATABASE=SUNGWOON SYSTEMS OUI:0020CE* ID_OUI_FROM_DATABASE=LOGICAL DESIGN GROUP, INC. OUI:002082* ID_OUI_FROM_DATABASE=ONEAC CORPORATION OUI:0020BF* ID_OUI_FROM_DATABASE=AEHR TEST SYSTEMS OUI:0020F1* ID_OUI_FROM_DATABASE=ALTOS INDIA LIMITED OUI:00205D* ID_OUI_FROM_DATABASE=NANOMATIC OY OUI:0020E1* ID_OUI_FROM_DATABASE=ALAMAR ELECTRONICS OUI:0020CC* ID_OUI_FROM_DATABASE=DIGITAL SERVICES, LTD. OUI:00202C* ID_OUI_FROM_DATABASE=WELLTRONIX CO., LTD. OUI:0020B3* ID_OUI_FROM_DATABASE=Tattile SRL OUI:00A048* ID_OUI_FROM_DATABASE=QUESTECH, LTD. OUI:00A0C4* ID_OUI_FROM_DATABASE=CRISTIE ELECTRONICS LTD. OUI:00A089* ID_OUI_FROM_DATABASE=XPOINT TECHNOLOGIES, INC. OUI:00A0D1* ID_OUI_FROM_DATABASE=INVENTEC CORPORATION OUI:00A0AE* ID_OUI_FROM_DATABASE=NUCOM SYSTEMS, INC. OUI:00A02B* ID_OUI_FROM_DATABASE=TRANSITIONS RESEARCH CORP. OUI:00A0A1* ID_OUI_FROM_DATABASE=EPIC DATA INC. OUI:00A0C3* ID_OUI_FROM_DATABASE=UNICOMPUTER GMBH OUI:00A042* ID_OUI_FROM_DATABASE=SPUR PRODUCTS CORP. OUI:00C007* ID_OUI_FROM_DATABASE=PINNACLE DATA SYSTEMS, INC. OUI:00C0F8* ID_OUI_FROM_DATABASE=ABOUT COMPUTING INC. OUI:00C06F* ID_OUI_FROM_DATABASE=KOMATSU LTD. OUI:00C08E* ID_OUI_FROM_DATABASE=NETWORK INFORMATION TECHNOLOGY OUI:00C05A* ID_OUI_FROM_DATABASE=SEMAPHORE COMMUNICATIONS CORP. OUI:00C0EB* ID_OUI_FROM_DATABASE=SEH COMPUTERTECHNIK GMBH OUI:00C0C7* ID_OUI_FROM_DATABASE=SPARKTRUM MICROSYSTEMS, INC. OUI:00C0D8* ID_OUI_FROM_DATABASE=UNIVERSAL DATA SYSTEMS OUI:00C068* ID_OUI_FROM_DATABASE=HME Clear-Com LTD. OUI:0040DB* ID_OUI_FROM_DATABASE=ADVANCED TECHNICAL SOLUTIONS OUI:00405B* ID_OUI_FROM_DATABASE=FUNASSET LIMITED OUI:00401B* ID_OUI_FROM_DATABASE=PRINTER SYSTEMS CORP. OUI:0040EB* ID_OUI_FROM_DATABASE=MARTIN MARIETTA CORPORATION OUI:0040CD* ID_OUI_FROM_DATABASE=TERA MICROSYSTEMS, INC. OUI:0040E5* ID_OUI_FROM_DATABASE=SYBUS CORPORATION OUI:0040F9* ID_OUI_FROM_DATABASE=COMBINET OUI:004039* ID_OUI_FROM_DATABASE=OPTEC DAIICHI DENKO CO., LTD. OUI:0040FE* ID_OUI_FROM_DATABASE=SYMPLEX COMMUNICATIONS OUI:0020F0* ID_OUI_FROM_DATABASE=UNIVERSAL MICROELECTRONICS CO. OUI:0020EF* ID_OUI_FROM_DATABASE=USC CORPORATION OUI:002016* ID_OUI_FROM_DATABASE=SHOWA ELECTRIC WIRE & CABLE CO OUI:00201F* ID_OUI_FROM_DATABASE=BEST POWER TECHNOLOGY, INC. OUI:002045* ID_OUI_FROM_DATABASE=ION Networks, Inc. OUI:0020B6* ID_OUI_FROM_DATABASE=AGILE NETWORKS, INC. OUI:00208A* ID_OUI_FROM_DATABASE=SONIX COMMUNICATIONS, LTD. OUI:00204C* ID_OUI_FROM_DATABASE=MITRON COMPUTER PTE LTD. OUI:002002* ID_OUI_FROM_DATABASE=SERITECH ENTERPRISE CO., LTD. OUI:00204B* ID_OUI_FROM_DATABASE=AUTOCOMPUTER CO., LTD. OUI:0020AF* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:002048* ID_OUI_FROM_DATABASE=Marconi Communications OUI:002008* ID_OUI_FROM_DATABASE=CABLE & COMPUTER TECHNOLOGY OUI:00C023* ID_OUI_FROM_DATABASE=TUTANKHAMON ELECTRONICS OUI:00C0F3* ID_OUI_FROM_DATABASE=NETWORK COMMUNICATIONS CORP. OUI:00C043* ID_OUI_FROM_DATABASE=STRATACOM OUI:00C0B3* ID_OUI_FROM_DATABASE=COMSTAT DATACOMM CORPORATION OUI:00C0B5* ID_OUI_FROM_DATABASE=CORPORATE NETWORK SYSTEMS,INC. OUI:00403E* ID_OUI_FROM_DATABASE=RASTER OPS CORPORATION OUI:0040AE* ID_OUI_FROM_DATABASE=DELTA CONTROLS, INC. OUI:0040C6* ID_OUI_FROM_DATABASE=FIBERNET RESEARCH, INC. OUI:004092* ID_OUI_FROM_DATABASE=ASP COMPUTER PRODUCTS, INC. OUI:004054* ID_OUI_FROM_DATABASE=CONNECTION MACHINES SERVICES OUI:0040D8* ID_OUI_FROM_DATABASE=OCEAN OFFICE AUTOMATION LTD. OUI:0040C0* ID_OUI_FROM_DATABASE=VISTA CONTROLS CORPORATION OUI:004088* ID_OUI_FROM_DATABASE=MOBIUS TECHNOLOGIES, INC. OUI:00803B* ID_OUI_FROM_DATABASE=APT COMMUNICATIONS, INC. OUI:0080BA* ID_OUI_FROM_DATABASE=SPECIALIX (ASIA) PTE, LTD OUI:00BB01* ID_OUI_FROM_DATABASE=OCTOTHORPE CORP. OUI:00C01F* ID_OUI_FROM_DATABASE=S.E.R.C.E.L. OUI:00C094* ID_OUI_FROM_DATABASE=VMX INC. OUI:00C075* ID_OUI_FROM_DATABASE=XANTE CORPORATION OUI:00C0F9* ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies OUI:00C039* ID_OUI_FROM_DATABASE=Teridian Semiconductor Corporation OUI:00C077* ID_OUI_FROM_DATABASE=DAEWOO TELECOM LTD. OUI:00C02F* ID_OUI_FROM_DATABASE=OKUMA CORPORATION OUI:00C0F1* ID_OUI_FROM_DATABASE=SHINKO ELECTRIC CO., LTD. OUI:00C0DE* ID_OUI_FROM_DATABASE=ZCOMM, INC. OUI:0040AF* ID_OUI_FROM_DATABASE=DIGITAL PRODUCTS, INC. OUI:00404F* ID_OUI_FROM_DATABASE=SPACE & NAVAL WARFARE SYSTEMS OUI:00407B* ID_OUI_FROM_DATABASE=SCIENTIFIC ATLANTA OUI:00404E* ID_OUI_FROM_DATABASE=FLUENT, INC. OUI:00C0F7* ID_OUI_FROM_DATABASE=ENGAGE COMMUNICATION, INC. OUI:00C030* ID_OUI_FROM_DATABASE=INTEGRATED ENGINEERING B. V. OUI:00C04A* ID_OUI_FROM_DATABASE=GROUP 2000 AG OUI:00C0A6* ID_OUI_FROM_DATABASE=EXICOM AUSTRALIA PTY. LTD OUI:00C053* ID_OUI_FROM_DATABASE=Aspect Software Inc. OUI:00C0CF* ID_OUI_FROM_DATABASE=IMATRAN VOIMA OY OUI:00C029* ID_OUI_FROM_DATABASE=Nexans Deutschland GmbH - ANS OUI:00C0A4* ID_OUI_FROM_DATABASE=UNIGRAF OY OUI:00C060* ID_OUI_FROM_DATABASE=ID SCANDINAVIA AS OUI:00C082* ID_OUI_FROM_DATABASE=MOORE PRODUCTS CO. OUI:00C008* ID_OUI_FROM_DATABASE=SECO SRL OUI:00C0BB* ID_OUI_FROM_DATABASE=FORVAL CREATIVE, INC. OUI:00C0E0* ID_OUI_FROM_DATABASE=DSC COMMUNICATION CORP. OUI:00C05E* ID_OUI_FROM_DATABASE=VARI-LITE, INC. OUI:00C031* ID_OUI_FROM_DATABASE=DESIGN RESEARCH SYSTEMS, INC. OUI:00C07C* ID_OUI_FROM_DATABASE=HIGHTECH INFORMATION OUI:00C0AE* ID_OUI_FROM_DATABASE=TOWERCOM CO. INC. DBA PC HOUSE OUI:00C0D6* ID_OUI_FROM_DATABASE=J1 SYSTEMS, INC. OUI:00C0AA* ID_OUI_FROM_DATABASE=SILICON VALLEY COMPUTER OUI:00C04E* ID_OUI_FROM_DATABASE=COMTROL CORPORATION OUI:00C00A* ID_OUI_FROM_DATABASE=MICRO CRAFT OUI:00C02A* ID_OUI_FROM_DATABASE=OHKURA ELECTRIC CO., LTD. OUI:00C0F2* ID_OUI_FROM_DATABASE=TRANSITION NETWORKS OUI:00C01D* ID_OUI_FROM_DATABASE=GRAND JUNCTION NETWORKS, INC. OUI:00C0AD* ID_OUI_FROM_DATABASE=MARBEN COMMUNICATION SYSTEMS OUI:00C024* ID_OUI_FROM_DATABASE=EDEN SISTEMAS DE COMPUTACAO SA OUI:00C0E9* ID_OUI_FROM_DATABASE=OAK SOLUTIONS, LTD. OUI:00C0C5* ID_OUI_FROM_DATABASE=SID INFORMATICA OUI:00C001* ID_OUI_FROM_DATABASE=DIATEK PATIENT MANAGMENT OUI:00C07E* ID_OUI_FROM_DATABASE=KUBOTA CORPORATION ELECTRONIC OUI:008012* ID_OUI_FROM_DATABASE=INTEGRATED MEASUREMENT SYSTEMS OUI:008039* ID_OUI_FROM_DATABASE=ALCATEL STC AUSTRALIA OUI:008023* ID_OUI_FROM_DATABASE=INTEGRATED BUSINESS NETWORKS OUI:0080CA* ID_OUI_FROM_DATABASE=NETCOM RESEARCH INCORPORATED OUI:00804D* ID_OUI_FROM_DATABASE=CYCLONE MICROSYSTEMS, INC. OUI:0080D6* ID_OUI_FROM_DATABASE=NUVOTECH, INC. OUI:0080ED* ID_OUI_FROM_DATABASE=IQ TECHNOLOGIES, INC. OUI:0080C1* ID_OUI_FROM_DATABASE=LANEX CORPORATION OUI:008049* ID_OUI_FROM_DATABASE=NISSIN ELECTRIC CO., LTD. OUI:00807C* ID_OUI_FROM_DATABASE=FIBERCOM, INC. OUI:008079* ID_OUI_FROM_DATABASE=MICROBUS DESIGNS LTD. OUI:0080DE* ID_OUI_FROM_DATABASE=GIPSI S.A. OUI:008004* ID_OUI_FROM_DATABASE=ANTLOW COMMUNICATIONS, LTD. OUI:008078* ID_OUI_FROM_DATABASE=PRACTICAL PERIPHERALS, INC. OUI:008040* ID_OUI_FROM_DATABASE=JOHN FLUKE MANUFACTURING CO. OUI:0000F8* ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION OUI:0080CE* ID_OUI_FROM_DATABASE=BROADCAST TELEVISION SYSTEMS OUI:00801A* ID_OUI_FROM_DATABASE=BELL ATLANTIC OUI:00803F* ID_OUI_FROM_DATABASE=TATUNG COMPANY OUI:0080D4* ID_OUI_FROM_DATABASE=CHASE RESEARCH LTD. OUI:0080CB* ID_OUI_FROM_DATABASE=FALCO DATA PRODUCTS OUI:008075* ID_OUI_FROM_DATABASE=PARSYTEC GMBH OUI:0080EB* ID_OUI_FROM_DATABASE=COMPCONTROL B.V. OUI:008099* ID_OUI_FROM_DATABASE=Eaton Industries GmbH OUI:0080E4* ID_OUI_FROM_DATABASE=NORTHWEST DIGITAL SYSTEMS, INC OUI:008041* ID_OUI_FROM_DATABASE=VEB KOMBINAT ROBOTRON OUI:0080C8* ID_OUI_FROM_DATABASE=D-LINK SYSTEMS, INC. OUI:008036* ID_OUI_FROM_DATABASE=REFLEX MANUFACTURING SYSTEMS OUI:0040F0* ID_OUI_FROM_DATABASE=MicroBrain,Inc. OUI:0040A7* ID_OUI_FROM_DATABASE=ITAUTEC PHILCO S.A. OUI:0040D3* ID_OUI_FROM_DATABASE=KIMPSION INTERNATIONAL CORP. OUI:004065* ID_OUI_FROM_DATABASE=GTE SPACENET OUI:0040CB* ID_OUI_FROM_DATABASE=LANWAN TECHNOLOGIES OUI:004041* ID_OUI_FROM_DATABASE=FUJIKURA LTD. OUI:004053* ID_OUI_FROM_DATABASE=AMPRO COMPUTERS OUI:008032* ID_OUI_FROM_DATABASE=ACCESS CO., LTD. OUI:0080CF* ID_OUI_FROM_DATABASE=EMBEDDED PERFORMANCE INC. OUI:008031* ID_OUI_FROM_DATABASE=BASYS, CORP. OUI:00803A* ID_OUI_FROM_DATABASE=VARITYPER, INC. OUI:00807E* ID_OUI_FROM_DATABASE=SOUTHERN PACIFIC LTD. OUI:008029* ID_OUI_FROM_DATABASE=EAGLE TECHNOLOGY, INC. OUI:00802F* ID_OUI_FROM_DATABASE=NATIONAL INSTRUMENTS CORP. OUI:008051* ID_OUI_FROM_DATABASE=FIBERMUX OUI:0080FD* ID_OUI_FROM_DATABASE=EXSCEED CORPRATION OUI:004008* ID_OUI_FROM_DATABASE=A PLUS INFO CORPORATION OUI:0040E9* ID_OUI_FROM_DATABASE=ACCORD SYSTEMS, INC. OUI:0040B5* ID_OUI_FROM_DATABASE=VIDEO TECHNOLOGY COMPUTERS LTD OUI:004012* ID_OUI_FROM_DATABASE=WINDATA, INC. OUI:00401C* ID_OUI_FROM_DATABASE=AST RESEARCH, INC. OUI:004067* ID_OUI_FROM_DATABASE=OMNIBYTE CORPORATION OUI:004035* ID_OUI_FROM_DATABASE=OPCOM OUI:0040EA* ID_OUI_FROM_DATABASE=PLAIN TREE SYSTEMS INC OUI:0040EF* ID_OUI_FROM_DATABASE=HYPERCOM, INC. OUI:004093* ID_OUI_FROM_DATABASE=PAXDATA NETWORKS LTD. OUI:0040EC* ID_OUI_FROM_DATABASE=MIKASA SYSTEM ENGINEERING OUI:0080B9* ID_OUI_FROM_DATABASE=ARCHE TECHNOLIGIES INC. OUI:0080A7* ID_OUI_FROM_DATABASE=Honeywell International Inc OUI:0040DA* ID_OUI_FROM_DATABASE=TELSPEC LTD OUI:004083* ID_OUI_FROM_DATABASE=TDA INDUSTRIA DE PRODUTOS OUI:0040C8* ID_OUI_FROM_DATABASE=MILAN TECHNOLOGY CORPORATION OUI:0040BC* ID_OUI_FROM_DATABASE=ALGORITHMICS LTD. OUI:00402F* ID_OUI_FROM_DATABASE=XLNT DESIGNS INC. OUI:00405D* ID_OUI_FROM_DATABASE=STAR-TEK, INC. OUI:00405F* ID_OUI_FROM_DATABASE=AFE COMPUTERS LTD. OUI:004043* ID_OUI_FROM_DATABASE=Nokia Siemens Networks GmbH & Co. KG. OUI:00800D* ID_OUI_FROM_DATABASE=VOSSWINKEL F.U. OUI:0080D1* ID_OUI_FROM_DATABASE=KIMTRON CORPORATION OUI:00805D* ID_OUI_FROM_DATABASE=CANSTAR OUI:008094* ID_OUI_FROM_DATABASE=ALFA LAVAL AUTOMATION AB OUI:008047* ID_OUI_FROM_DATABASE=IN-NET CORP. OUI:008064* ID_OUI_FROM_DATABASE=WYSE TECHNOLOGY LLC OUI:0080C5* ID_OUI_FROM_DATABASE=NOVELLCO DE MEXICO OUI:0080AC* ID_OUI_FROM_DATABASE=IMLOGIX, DIVISION OF GENESYS OUI:00808C* ID_OUI_FROM_DATABASE=NetScout Systems, Inc. OUI:000052* ID_OUI_FROM_DATABASE=Intrusion.com, Inc. OUI:0000BD* ID_OUI_FROM_DATABASE=MITSUBISHI CABLE COMPANY OUI:000037* ID_OUI_FROM_DATABASE=OXFORD METRICS LIMITED OUI:00003F* ID_OUI_FROM_DATABASE=SYNTREX, INC. OUI:08007C* ID_OUI_FROM_DATABASE=VITALINK COMMUNICATIONS CORP. OUI:080076* ID_OUI_FROM_DATABASE=PC LAN TECHNOLOGIES OUI:080072* ID_OUI_FROM_DATABASE=XEROX CORP UNIV GRANT PROGRAM OUI:080070* ID_OUI_FROM_DATABASE=MITSUBISHI ELECTRIC CORP. OUI:080068* ID_OUI_FROM_DATABASE=RIDGE COMPUTERS OUI:080062* ID_OUI_FROM_DATABASE=General Dynamics OUI:080057* ID_OUI_FROM_DATABASE=Evans & Sutherland OUI:000010* ID_OUI_FROM_DATABASE=SYTEK INC. OUI:000033* ID_OUI_FROM_DATABASE=EGAN MACHINERY COMPANY OUI:000080* ID_OUI_FROM_DATABASE=CRAY COMMUNICATIONS A/S OUI:0000FD* ID_OUI_FROM_DATABASE=HIGH LEVEL HARDWARE OUI:08008C* ID_OUI_FROM_DATABASE=NETWORK RESEARCH CORPORATION OUI:080089* ID_OUI_FROM_DATABASE=Kinetics OUI:080087* ID_OUI_FROM_DATABASE=XYPLEX OUI:080084* ID_OUI_FROM_DATABASE=TOMEN ELECTRONICS CORP. OUI:00000D* ID_OUI_FROM_DATABASE=FIBRONICS LTD. OUI:00004F* ID_OUI_FROM_DATABASE=LOGICRAFT, INC. OUI:000015* ID_OUI_FROM_DATABASE=DATAPOINT CORPORATION OUI:0000C7* ID_OUI_FROM_DATABASE=ARIX CORPORATION OUI:00001C* ID_OUI_FROM_DATABASE=BELL TECHNOLOGIES OUI:00001A* ID_OUI_FROM_DATABASE=ADVANCED MICRO DEVICES OUI:000082* ID_OUI_FROM_DATABASE=LECTRA SYSTEMES SA OUI:0000DA* ID_OUI_FROM_DATABASE=ATEX OUI:0000DB* ID_OUI_FROM_DATABASE=British Telecommunications plc OUI:0000C1* ID_OUI_FROM_DATABASE=Madge Ltd. OUI:0000F6* ID_OUI_FROM_DATABASE=APPLIED MICROSYSTEMS CORP. OUI:080023* ID_OUI_FROM_DATABASE=Panasonic Communications Co., Ltd. OUI:080022* ID_OUI_FROM_DATABASE=NBI INC. OUI:080019* ID_OUI_FROM_DATABASE=GENERAL ELECTRIC CORPORATION OUI:08004D* ID_OUI_FROM_DATABASE=CORVUS SYSTEMS INC. OUI:08003E* ID_OUI_FROM_DATABASE=CODEX CORPORATION OUI:080033* ID_OUI_FROM_DATABASE=BAUSCH & LOMB OUI:08002F* ID_OUI_FROM_DATABASE=PRIME COMPUTER INC. OUI:080032* ID_OUI_FROM_DATABASE=TIGAN INCORPORATED OUI:08002E* ID_OUI_FROM_DATABASE=METAPHOR COMPUTER SYSTEMS OUI:0000D2* ID_OUI_FROM_DATABASE=SBE, INC. OUI:00006B* ID_OUI_FROM_DATABASE=SILICON GRAPHICS INC./MIPS OUI:0000CC* ID_OUI_FROM_DATABASE=DENSAN CO., LTD. OUI:0000CE* ID_OUI_FROM_DATABASE=MEGADATA CORP. OUI:0000EF* ID_OUI_FROM_DATABASE=KTI OUI:00000F* ID_OUI_FROM_DATABASE=NEXT, INC. OUI:0000C6* ID_OUI_FROM_DATABASE=EON SYSTEMS OUI:0000D5* ID_OUI_FROM_DATABASE=MICROGNOSIS INTERNATIONAL OUI:000078* ID_OUI_FROM_DATABASE=LABTAM LIMITED OUI:0000EB* ID_OUI_FROM_DATABASE=MATSUSHITA COMM. IND. CO. LTD. OUI:00009C* ID_OUI_FROM_DATABASE=ROLM MIL-SPEC COMPUTERS OUI:000032* ID_OUI_FROM_DATABASE=Marconi plc OUI:000069* ID_OUI_FROM_DATABASE=CONCORD COMMUNICATIONS INC OUI:00008B* ID_OUI_FROM_DATABASE=INFOTRON OUI:0000BE* ID_OUI_FROM_DATABASE=THE NTI GROUP OUI:00004C* ID_OUI_FROM_DATABASE=NEC CORPORATION OUI:00003B* ID_OUI_FROM_DATABASE=i Controls, Inc. OUI:0000FE* ID_OUI_FROM_DATABASE=ANNAPOLIS MICRO SYSTEMS OUI:080013* ID_OUI_FROM_DATABASE=Exxon OUI:02BB01* ID_OUI_FROM_DATABASE=OCTOTHORPE CORP. OUI:0000A6* ID_OUI_FROM_DATABASE=NETWORK GENERAL CORPORATION OUI:00DD06* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:00DD0B* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:000007* ID_OUI_FROM_DATABASE=XEROX CORPORATION OUI:080014* ID_OUI_FROM_DATABASE=EXCELAN OUI:08000F* ID_OUI_FROM_DATABASE=MITEL CORPORATION OUI:0000D7* ID_OUI_FROM_DATABASE=DARTMOUTH COLLEGE OUI:00DD00* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:08000A* ID_OUI_FROM_DATABASE=NESTAR SYSTEMS INCORPORATED OUI:08001C* ID_OUI_FROM_DATABASE=KDD-KOKUSAI DEBNSIN DENWA CO. OUI:02AA3C* ID_OUI_FROM_DATABASE=OLIVETTI TELECOMM SPA (OLTECO) OUI:08001D* ID_OUI_FROM_DATABASE=ABLE COMMUNICATIONS INC. OUI:080018* ID_OUI_FROM_DATABASE=PIRELLI FOCOM NETWORKS OUI:080015* ID_OUI_FROM_DATABASE=STC BUSINESS SYSTEMS OUI:00DD03* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:00801F* ID_OUI_FROM_DATABASE=KRUPP ATLAS ELECTRONIK GMBH OUI:00408E* ID_OUI_FROM_DATABASE=Tattile SRL OUI:00800F* ID_OUI_FROM_DATABASE=STANDARD MICROSYSTEMS OUI:080065* ID_OUI_FROM_DATABASE=GENRAD INC. OUI:002275* ID_OUI_FROM_DATABASE=Belkin International Inc. OUI:149182* ID_OUI_FROM_DATABASE=Belkin International Inc. OUI:70106F* ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise OUI:988B5D* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:94FEF4* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:C8CD72* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:E8BE81* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:28FAA0* ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. OUI:3CA348* ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. OUI:F42981* ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. OUI:C4282D* ID_OUI_FROM_DATABASE=Embedded Intellect Pty Ltd OUI:002348* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:B870F4* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:000FB0* ID_OUI_FROM_DATABASE=COMPAL ELECTRONICS, INC. OUI:1C7508* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:8C0EE3* ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD OUI:884AEA* ID_OUI_FROM_DATABASE=Texas Instruments OUI:3829DD* ID_OUI_FROM_DATABASE=ONvocal Inc OUI:F81897* ID_OUI_FROM_DATABASE=2Wire Inc OUI:ECF4BB* ID_OUI_FROM_DATABASE=Dell Inc. OUI:D067E5* ID_OUI_FROM_DATABASE=Dell Inc. OUI:18A99B* ID_OUI_FROM_DATABASE=Dell Inc. OUI:F8DB88* ID_OUI_FROM_DATABASE=Dell Inc. OUI:18FB7B* ID_OUI_FROM_DATABASE=Dell Inc. OUI:001495* ID_OUI_FROM_DATABASE=2Wire Inc OUI:74E6E2* ID_OUI_FROM_DATABASE=Dell Inc. OUI:109836* ID_OUI_FROM_DATABASE=Dell Inc. OUI:44A842* ID_OUI_FROM_DATABASE=Dell Inc. OUI:34E6D7* ID_OUI_FROM_DATABASE=Dell Inc. OUI:000BDB* ID_OUI_FROM_DATABASE=Dell Inc. OUI:001143* ID_OUI_FROM_DATABASE=Dell Inc. OUI:00188B* ID_OUI_FROM_DATABASE=Dell Inc. OUI:D4BED9* ID_OUI_FROM_DATABASE=Dell Inc. OUI:002650* ID_OUI_FROM_DATABASE=2Wire Inc OUI:00217C* ID_OUI_FROM_DATABASE=2Wire Inc OUI:001FB3* ID_OUI_FROM_DATABASE=2Wire Inc OUI:640F28* ID_OUI_FROM_DATABASE=2Wire Inc OUI:001AA0* ID_OUI_FROM_DATABASE=Dell Inc. OUI:002170* ID_OUI_FROM_DATABASE=Dell Inc. OUI:0026B9* ID_OUI_FROM_DATABASE=Dell Inc. OUI:A4BADB* ID_OUI_FROM_DATABASE=Dell Inc. OUI:001E4F* ID_OUI_FROM_DATABASE=Dell Inc. OUI:5CF9DD* ID_OUI_FROM_DATABASE=Dell Inc. OUI:907AF1* ID_OUI_FROM_DATABASE=Wally OUI:28101B* ID_OUI_FROM_DATABASE=MagnaCom OUI:00065B* ID_OUI_FROM_DATABASE=Dell Inc. OUI:448723* ID_OUI_FROM_DATABASE=HOYA SERVICE CORPORATION OUI:806C1B* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:A470D6* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:3407FB* ID_OUI_FROM_DATABASE=Ericsson AB OUI:001B21* ID_OUI_FROM_DATABASE=Intel Corporate OUI:001B77* ID_OUI_FROM_DATABASE=Intel Corporate OUI:18FF0F* ID_OUI_FROM_DATABASE=Intel Corporate OUI:58A839* ID_OUI_FROM_DATABASE=Intel Corporate OUI:A434D9* ID_OUI_FROM_DATABASE=Intel Corporate OUI:00215D* ID_OUI_FROM_DATABASE=Intel Corporate OUI:001676* ID_OUI_FROM_DATABASE=Intel Corporate OUI:984FEE* ID_OUI_FROM_DATABASE=Intel Corporate OUI:E82AEA* ID_OUI_FROM_DATABASE=Intel Corporate OUI:605718* ID_OUI_FROM_DATABASE=Intel Corporate OUI:C4D987* ID_OUI_FROM_DATABASE=Intel Corporate OUI:B4B676* ID_OUI_FROM_DATABASE=Intel Corporate OUI:8C705A* ID_OUI_FROM_DATABASE=Intel Corporate OUI:9C4E36* ID_OUI_FROM_DATABASE=Intel Corporate OUI:541473* ID_OUI_FROM_DATABASE=Wingtech Group (HongKong)Limited OUI:14144B* ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD OUI:001C50* ID_OUI_FROM_DATABASE=TCL Technoly Electronics (Huizhou) Co., Ltd. OUI:00AA01* ID_OUI_FROM_DATABASE=Intel Corporation OUI:5C36B8* ID_OUI_FROM_DATABASE=TCL King Electrical Appliances (Huizhou) Co., Ltd OUI:009027* ID_OUI_FROM_DATABASE=Intel Corporation OUI:A08869* ID_OUI_FROM_DATABASE=Intel Corporate OUI:00C2C6* ID_OUI_FROM_DATABASE=Intel Corporate OUI:B88A60* ID_OUI_FROM_DATABASE=Intel Corporate OUI:00A0C9* ID_OUI_FROM_DATABASE=Intel Corporation OUI:7C7A91* ID_OUI_FROM_DATABASE=Intel Corporate OUI:AC7BA1* ID_OUI_FROM_DATABASE=Intel Corporate OUI:AC7289* ID_OUI_FROM_DATABASE=Intel Corporate OUI:606C66* ID_OUI_FROM_DATABASE=Intel Corporate OUI:4C8093* ID_OUI_FROM_DATABASE=Intel Corporate OUI:BC7737* ID_OUI_FROM_DATABASE=Intel Corporate OUI:A088B4* ID_OUI_FROM_DATABASE=Intel Corporate OUI:00270E* ID_OUI_FROM_DATABASE=Intel Corporate OUI:001DE0* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0024D6* ID_OUI_FROM_DATABASE=Intel Corporate OUI:D8FC93* ID_OUI_FROM_DATABASE=Intel Corporate OUI:E8B1FC* ID_OUI_FROM_DATABASE=Intel Corporate OUI:186472* ID_OUI_FROM_DATABASE=Aruba Networks OUI:00246C* ID_OUI_FROM_DATABASE=Aruba Networks OUI:64D954* ID_OUI_FROM_DATABASE=Taicang T&W Electronics OUI:74C63B* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:CC1FC4* ID_OUI_FROM_DATABASE=InVue OUI:A0D37A* ID_OUI_FROM_DATABASE=Intel Corporate OUI:985FD3* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:00D0AC* ID_OUI_FROM_DATABASE=Commscope, Inc OUI:0025D3* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:742F68* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:DC85DE* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:E0B9A5* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:E04136* ID_OUI_FROM_DATABASE=MitraStar Technology Corp. OUI:E0B2F1* ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED OUI:0026FC* ID_OUI_FROM_DATABASE=AcSiP Technology Corp. OUI:B8616F* ID_OUI_FROM_DATABASE=Accton Technology Corp OUI:0010B5* ID_OUI_FROM_DATABASE=Accton Technology Corp OUI:00A02F* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:6487D7* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:00E098* ID_OUI_FROM_DATABASE=AboCom OUI:F0A225* ID_OUI_FROM_DATABASE=Private OUI:0000B1* ID_OUI_FROM_DATABASE=Alpha Micro OUI:001577* ID_OUI_FROM_DATABASE=Allied Telesis, Inc. OUI:ACE010* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:EC086B* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:00159A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:00192C* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:2421AB* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:6C23B9* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:58170C* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:B8F934* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:205476* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:303926* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:00EB2D* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:B00594* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:40F02F* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:E8617E* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:28E347* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:18CF5E* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:D0DF9A* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:90B134* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:3C438E* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:E86D52* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0015D0* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0013A9* ID_OUI_FROM_DATABASE=Sony Corporation OUI:00219E* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:001E45* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:001813* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:00080E* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0050E3* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:94CCB9* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:40B7F3* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:20E564* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:F87B7A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0023A3* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:64ED57* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0023EE* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:002143* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:5856E8* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0025F1* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0023AF* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001ADE* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001E46* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0018C0* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001A66* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:002163* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:E839DF* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:00138F* ID_OUI_FROM_DATABASE=Asiarock Technology Limited OUI:2CB05D* ID_OUI_FROM_DATABASE=NETGEAR OUI:00146C* ID_OUI_FROM_DATABASE=NETGEAR OUI:1C69A5* ID_OUI_FROM_DATABASE=BlackBerry RTS OUI:003067* ID_OUI_FROM_DATABASE=BIOSTAR Microtech Int'l Corp. OUI:246511* ID_OUI_FROM_DATABASE=AVM GmbH OUI:002308* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:880355* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:A42B8C* ID_OUI_FROM_DATABASE=NETGEAR OUI:04A151* ID_OUI_FROM_DATABASE=NETGEAR OUI:28C68E* ID_OUI_FROM_DATABASE=NETGEAR OUI:5CDC96* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:504A6E* ID_OUI_FROM_DATABASE=NETGEAR OUI:D0D04B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:001D00* ID_OUI_FROM_DATABASE=Brivo Systems, LLC OUI:0010E7* ID_OUI_FROM_DATABASE=Breezecom, Ltd. OUI:5C9656* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:7C4CA5* ID_OUI_FROM_DATABASE=BSkyB Ltd OUI:902106* ID_OUI_FROM_DATABASE=BSkyB Ltd OUI:A4C7DE* ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. OUI:343759* ID_OUI_FROM_DATABASE=zte corporation OUI:00402A* ID_OUI_FROM_DATABASE=Canoga Perkins Corporation OUI:382DE8* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:D087E2* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:205531* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:5440AD* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:842E27* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:50F0D3* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:84119E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:08ECA9* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:10D38A* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:382DD1* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E0CBEE* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:64B853* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:988389* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:244B03* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:FC8F90* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:1816C9* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:F4428F* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:188331* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:8455A5* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:A87C01* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:C01173* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:BCE63F* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B857D8* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:94B10A* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E458B8* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:088C2C* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B86CE8* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:9C65B0* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:C8A823* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:C44202* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:D059E4* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:64B310* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:78ABBB* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:000B3B* ID_OUI_FROM_DATABASE=devolo AG OUI:001D20* ID_OUI_FROM_DATABASE=Comtrend Corporation OUI:6C38A1* ID_OUI_FROM_DATABASE=Ubee Interactive Corp. OUI:140C76* ID_OUI_FROM_DATABASE=FREEBOX SAS OUI:0024D4* ID_OUI_FROM_DATABASE=FREEBOX SAS OUI:A089E4* ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd OUI:001A9A* ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd OUI:AC3A7A* ID_OUI_FROM_DATABASE=Roku, Inc. OUI:CC6DA0* ID_OUI_FROM_DATABASE=Roku, Inc. OUI:000D4B* ID_OUI_FROM_DATABASE=Roku, Inc. OUI:001999* ID_OUI_FROM_DATABASE=Fujitsu Technology Solutions GmbH OUI:0009E1* ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. OUI:C477AB* ID_OUI_FROM_DATABASE=Beijing ASU Tech Co.,Ltd OUI:182A7B* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:0024F3* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:A45C27* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:001DBC* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:001F32* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:544408* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:D8FB5E* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:1886AC* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0021FE* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001DFD* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001EA3* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:002266* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0017B0* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001BEE* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:002548* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:C8D10B* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:C8979F* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:F4F5A5* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:DCB3B4* ID_OUI_FROM_DATABASE=Honeywell Environmental & Combustion Controls (Tianjin) Co., Ltd. OUI:001D98* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:00119F* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0015A0* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001A16* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0022FC* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:3CC243* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:18A6F7* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:246968* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:8CA2FD* ID_OUI_FROM_DATABASE=Starry, Inc. OUI:14BB6E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:AC61EA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:38B54D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:90A62F* ID_OUI_FROM_DATABASE=NAVER OUI:9476B7* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:8C1ABF* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B47443* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:30CBF8* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:000BA2* ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd OUI:F4ED5F* ID_OUI_FROM_DATABASE=SHENZHEN KTC TECHNOLOGY GROUP OUI:2C4D79* ID_OUI_FROM_DATABASE=GoerTek Inc. OUI:40D357* ID_OUI_FROM_DATABASE=Ison Technology Co., Ltd. OUI:A4F1E8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F03404* ID_OUI_FROM_DATABASE=TCT mobile ltd OUI:AC9B0A* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:FC0FE6* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:709E29* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:00351A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:9CD48B* ID_OUI_FROM_DATABASE=Innolux Technology Europe BV OUI:00A0B8* ID_OUI_FROM_DATABASE=NetApp OUI:DCE838* ID_OUI_FROM_DATABASE=CK Telecom (Shenzhen) Limited OUI:545AA6* ID_OUI_FROM_DATABASE=Espressif Inc. OUI:BC8D0E* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:E48184* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:94E98C* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:84262B* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:98B039* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:A47B2C* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:BC6B4D* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:B0754D* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:00CCFC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:2C9662* ID_OUI_FROM_DATABASE=Invenit BV OUI:DC2DCB* ID_OUI_FROM_DATABASE=Beijing Unis HengYue Technology Co., Ltd. OUI:3810D5* ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH OUI:44AAF5* ID_OUI_FROM_DATABASE=Pace plc OUI:1C5F2B* ID_OUI_FROM_DATABASE=D-Link International OUI:D8803C* ID_OUI_FROM_DATABASE=Anhui Huami Information Technology Company Limited OUI:A8E3EE* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:001FA7* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:001315* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:703C03* ID_OUI_FROM_DATABASE=RadiAnt Co.,Ltd OUI:F0D2F1* ID_OUI_FROM_DATABASE=Amazon Technologies Inc. OUI:583277* ID_OUI_FROM_DATABASE=Reliance Communications LLC OUI:CCD3E2* ID_OUI_FROM_DATABASE=Jiangsu Yinhe Electronics Co.,Ltd. OUI:182195* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:A88195* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:88ADD2* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:008E73* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B805AB* ID_OUI_FROM_DATABASE=zte corporation OUI:9C52F8* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:900325* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:DC094C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:DCEE06* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:AC44F2* ID_OUI_FROM_DATABASE=YAMAHA CORPORATION OUI:508965* ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. OUI:808C97* ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD. OUI:30B49E* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:349971* ID_OUI_FROM_DATABASE=Quanta Storage Inc. OUI:24615A* ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. OUI:B0E2E5* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:AC0D1B* ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) OUI:5CC7D7* ID_OUI_FROM_DATABASE=AZROAD TECHNOLOGY COMPANY LIMITED OUI:A0043E* ID_OUI_FROM_DATABASE=Parker Hannifin Manufacturing Germany GmbH & Co. KG OUI:001706* ID_OUI_FROM_DATABASE=Techfaithwireless Communication Technology Limited. OUI:30F6B9* ID_OUI_FROM_DATABASE=Ecocentric Energy OUI:1C3ADE* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:004268* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00BD82* ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd OUI:603ECA* ID_OUI_FROM_DATABASE=Cambridge Medical Robotics Ltd OUI:E4A1E6* ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd OUI:54489C* ID_OUI_FROM_DATABASE=CDOUBLES ELECTRONICS CO. LTD. OUI:54BEF7* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:0C54A5* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:202564* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:600292* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:84002D* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:8019FE* ID_OUI_FROM_DATABASE=JianLing Technology CO., LTD OUI:58605F* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:001188* ID_OUI_FROM_DATABASE=Enterasys OUI:1078D2* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:001E90* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:002465* ID_OUI_FROM_DATABASE=Elentec OUI:001CD7* ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH OUI:0016EC* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:000D87* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:000AE6* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:945089* ID_OUI_FROM_DATABASE=SimonsVoss Technologies GmbH OUI:001F1F* ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. OUI:0016FA* ID_OUI_FROM_DATABASE=ECI Telecom Ltd. OUI:003A7D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:844076* ID_OUI_FROM_DATABASE=Drivenets OUI:E80959* ID_OUI_FROM_DATABASE=Guoguang Electric Co.,Ltd OUI:00144F* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:541379* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:0010E0* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:0090AE* ID_OUI_FROM_DATABASE=ITALTEL S.p.A/RF-UP-I OUI:001E33* ID_OUI_FROM_DATABASE=INVENTEC Corporation OUI:001A29* ID_OUI_FROM_DATABASE=Johnson Outdoors Marine Electronics d/b/a Minnkota OUI:001F09* ID_OUI_FROM_DATABASE=Jastec OUI:D0A4B1* ID_OUI_FROM_DATABASE=Sonifex Ltd. OUI:001DB5* ID_OUI_FROM_DATABASE=Juniper Networks OUI:00239C* ID_OUI_FROM_DATABASE=Juniper Networks OUI:80711F* ID_OUI_FROM_DATABASE=Juniper Networks OUI:28F366* ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD OUI:D44165* ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD OUI:8828B3* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:C4F081* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:801382* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:341290* ID_OUI_FROM_DATABASE=Treeview Co.,Ltd. OUI:BCAD28* ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. OUI:3CB6B7* ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. OUI:28C0DA* ID_OUI_FROM_DATABASE=Juniper Networks OUI:648788* ID_OUI_FROM_DATABASE=Juniper Networks OUI:A8D0E5* ID_OUI_FROM_DATABASE=Juniper Networks OUI:0881F4* ID_OUI_FROM_DATABASE=Juniper Networks OUI:0C6F9C* ID_OUI_FROM_DATABASE=Shaw Communications Inc. OUI:1801E3* ID_OUI_FROM_DATABASE=Bittium Wireless Ltd OUI:C0AC54* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:40F201* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:C891F9* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:4CFF12* ID_OUI_FROM_DATABASE=Fuze Entertainment Co., ltd OUI:0059AC* ID_OUI_FROM_DATABASE=KPN. B.V. OUI:AC9A22* ID_OUI_FROM_DATABASE=NXP Semiconductors OUI:006037* ID_OUI_FROM_DATABASE=NXP Semiconductors OUI:546009* ID_OUI_FROM_DATABASE=Google, Inc. OUI:A47733* ID_OUI_FROM_DATABASE=Google, Inc. OUI:94EB2C* ID_OUI_FROM_DATABASE=Google, Inc. OUI:28BC56* ID_OUI_FROM_DATABASE=EMAC, Inc. OUI:287CDB* ID_OUI_FROM_DATABASE=Hefei Toycloud Technology Co.,ltd OUI:D0B33F* ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. OUI:00738D* ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. OUI:A8CA7B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:ACCF85* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:0CD746* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:440010* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:2435CC* ID_OUI_FROM_DATABASE=Zhongshan Scinan Internet of Things Co.,Ltd. OUI:2C27D7* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:000F3D* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:001195* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:0015E9* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:0CFD37* ID_OUI_FROM_DATABASE=SUSE Linux GmbH OUI:2CFF65* ID_OUI_FROM_DATABASE=Oki Electric Industry Co., Ltd. OUI:001CF0* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:00265A* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:ACF1DF* ID_OUI_FROM_DATABASE=D-Link International OUI:FC7516* ID_OUI_FROM_DATABASE=D-Link International OUI:E0D7BA* ID_OUI_FROM_DATABASE=Texas Instruments OUI:B8FFFE* ID_OUI_FROM_DATABASE=Texas Instruments OUI:78DEE4* ID_OUI_FROM_DATABASE=Texas Instruments OUI:00182F* ID_OUI_FROM_DATABASE=Texas Instruments OUI:001834* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0017E3* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0017EA* ID_OUI_FROM_DATABASE=Texas Instruments OUI:001783* ID_OUI_FROM_DATABASE=Texas Instruments OUI:7C18CD* ID_OUI_FROM_DATABASE=E-TRON Co.,Ltd. OUI:C8665D* ID_OUI_FROM_DATABASE=Aerohive Networks Inc. OUI:3897D6* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:C8478C* ID_OUI_FROM_DATABASE=Beken Corporation OUI:E498D6* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:606944* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:08952A* ID_OUI_FROM_DATABASE=Technicolor CH USA OUI:001977* ID_OUI_FROM_DATABASE=Aerohive Networks Inc. OUI:4018B1* ID_OUI_FROM_DATABASE=Aerohive Networks Inc. OUI:8896B6* ID_OUI_FROM_DATABASE=Global Fire Equipment S.A. OUI:188796* ID_OUI_FROM_DATABASE=HTC Corporation OUI:945330* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:00242C* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:00242B* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:D87988* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:AC2A0C* ID_OUI_FROM_DATABASE=CSR ZHUZHOU INSTITUTE CO.,LTD. OUI:601971* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:F4CA24* ID_OUI_FROM_DATABASE=FreeBit Co., Ltd. OUI:001DD1* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001DD6* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:000A57* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:643150* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:002376* ID_OUI_FROM_DATABASE=HTC Corporation OUI:0007E9* ID_OUI_FROM_DATABASE=Intel Corporation OUI:B46D83* ID_OUI_FROM_DATABASE=Intel Corporate OUI:E4FAFD* ID_OUI_FROM_DATABASE=Intel Corporate OUI:DC5360* ID_OUI_FROM_DATABASE=Intel Corporate OUI:780CB8* ID_OUI_FROM_DATABASE=Intel Corporate OUI:484520* ID_OUI_FROM_DATABASE=Intel Corporate OUI:004026* ID_OUI_FROM_DATABASE=BUFFALO.INC OUI:0002A5* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:A02BB8* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:6CC217* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:3863BB* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:CC3E5F* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:7446A0* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:443192* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:FC15B4* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:EC9A74* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:80C16E* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:D07E28* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:7403BD* ID_OUI_FROM_DATABASE=BUFFALO.INC OUI:101F74* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001A4B* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001F29* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:00215A* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:000F61* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001185* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001279* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001708* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:306023* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:ACB313* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:14ABF0* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0CF893* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:8461A0* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:E83381* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:44E137* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:1C1B68* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:2832C5* ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. OUI:EC4D47* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:88CF98* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:6CE3B6* ID_OUI_FROM_DATABASE=Nera Telecommunications Ltd. OUI:8030DC* ID_OUI_FROM_DATABASE=Texas Instruments OUI:CC78AB* ID_OUI_FROM_DATABASE=Texas Instruments OUI:A4D578* ID_OUI_FROM_DATABASE=Texas Instruments OUI:942CB3* ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. OUI:0452F3* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:241EEB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F431C3* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C4F57C* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:8C7CFF* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:000CDB* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:006069* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:C87B5B* ID_OUI_FROM_DATABASE=zte corporation OUI:98F537* ID_OUI_FROM_DATABASE=zte corporation OUI:001E73* ID_OUI_FROM_DATABASE=zte corporation OUI:0019C6* ID_OUI_FROM_DATABASE=zte corporation OUI:0015EB* ID_OUI_FROM_DATABASE=zte corporation OUI:A051C6* ID_OUI_FROM_DATABASE=Avaya Inc OUI:24D921* ID_OUI_FROM_DATABASE=Avaya Inc OUI:848371* ID_OUI_FROM_DATABASE=Avaya Inc OUI:7052C5* ID_OUI_FROM_DATABASE=Avaya Inc OUI:001B4F* ID_OUI_FROM_DATABASE=Avaya Inc OUI:F0EBD0* ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd. OUI:D8490B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:888603* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:F8E811* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:E09796* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:CCCC81* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:101B54* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:7054F5* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:00197E* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:78DD08* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:9CD21E* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:8096CA* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:D07AB5* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:C40528* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:3CDFBD* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:14B968* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:80717A* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:F49FF3* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:2C5BB8* ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD OUI:B0AA36* ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD OUI:784B87* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:28A183* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:5CF8A1* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:6021C0* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:84DBAC* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:C07009* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:E0191D* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:B8BC1B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:241FA0* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:50A72B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:C85195* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:00F81C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:F4559C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:283CE4* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:64A5C3* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:001D0F* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:5C63BF* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:B0487A* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:388345* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:14E6E4* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:647002* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:6466B3* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:6CE873* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:08E84F* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:04BD70* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:18C58A* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:405FC2* ID_OUI_FROM_DATABASE=Texas Instruments OUI:20CD39* ID_OUI_FROM_DATABASE=Texas Instruments OUI:D8DDFD* ID_OUI_FROM_DATABASE=Texas Instruments OUI:544A16* ID_OUI_FROM_DATABASE=Texas Instruments OUI:EC1127* ID_OUI_FROM_DATABASE=Texas Instruments OUI:247189* ID_OUI_FROM_DATABASE=Texas Instruments OUI:987BF3* ID_OUI_FROM_DATABASE=Texas Instruments OUI:04C06F* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:5C4CA9* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:4C5499* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:00259E* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:001882* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:D4EA0E* ID_OUI_FROM_DATABASE=Avaya Inc OUI:B4475E* ID_OUI_FROM_DATABASE=Avaya Inc OUI:90FB5B* ID_OUI_FROM_DATABASE=Avaya Inc OUI:14F65A* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:0C1DAF* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:28E31F* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:F0B429* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:00906F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0090A6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0090AB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:7426AC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B000B4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:2834A2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:641225* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:544A00* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:5067AE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:BC16F5* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:6899CD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:F44E05* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0CF5A4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:5CFC66* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:D0A5A6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:3C5EC3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:64F69D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:74A2E6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:204C9E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:A055DE* ID_OUI_FROM_DATABASE=Pace plc OUI:0026D9* ID_OUI_FROM_DATABASE=Pace plc OUI:00112F* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:0011D8* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:001731* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:0018F3* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:485B39* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:F46D04* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:3085A9* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:00900C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001079* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00102F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000E08* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:00602F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:006070* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:006083* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00067C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:C8D719* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:CC08E0* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:5855CA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:8C7B9D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:88C663* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C82A14* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:9803D8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:8C5877* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:3451C9* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E0B9BA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D023DB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:B88D12* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:B817C2* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:68A86D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:78A3E4* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:54781A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:58971E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:CCD539* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:20BBC0* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:4C4E35* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:7CAD74* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:10F311* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:08CC68* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:D0C789* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:F84F57* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:34DBFD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:5CA48A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:AC7A4D* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:FC62B9* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:0010A6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E86549* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:84B517* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:046273* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:9C57AD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00223A* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:001839* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:001EE5* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:38C85C* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:F45FD4* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:002306* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:001E3D* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:0019C1* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:BC926B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0050E4* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:003065* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:000A27* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:001451* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0019E3* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:002312* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:002332* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:002436* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:00254B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0026BB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E80688* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:985AEB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:2078F0* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:78D75F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E0ACCB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:98E0D9* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C0CECD* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:70E72C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D03311* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:847D50* ID_OUI_FROM_DATABASE=Holley Metering Limited OUI:6C4A39* ID_OUI_FROM_DATABASE=BITA OUI:C8B5B7* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A8BBCF* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:90B21F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:B8E856* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:1499E2* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:04214C* ID_OUI_FROM_DATABASE=Insight Energy Ventures LLC OUI:B418D1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:80006E* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:60D9C7* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C8F650* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:1C1AC0* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E06678* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:5C8D4E* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:64A3CB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:44FB42* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F41BA1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:3CE072* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E88D28* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:CC785F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:AC3C0B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:88CB87* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:EC3586* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F0C1F1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F4F951* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:18AF8F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C0F2FB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:00F76F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:AC87A3* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:48437C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:34A395* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:9CF387* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A85B78* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:908D6C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0C1539* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:BC4CC4* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0CBC9F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A45E60* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:680927* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:60FACD* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:1CABA7* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:8CFABA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:5C95AE* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E0C97A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:BC52B7* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:14109F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:542696* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D8D1CB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:4C8ECC* ID_OUI_FROM_DATABASE=SILKAN SA OUI:3CEF8C* ID_OUI_FROM_DATABASE=ZHEJIANG DAHUA TECHNOLOGY CO.,LTD. OUI:64BC0C* ID_OUI_FROM_DATABASE=LG Electronics OUI:98F428* ID_OUI_FROM_DATABASE=zte corporation OUI:7C5A67* ID_OUI_FROM_DATABASE=JNC Systems, Inc. OUI:5C4979* ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH OUI:C4BBEA* ID_OUI_FROM_DATABASE=Pakedge Device and Software Inc OUI:84100D* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:D88B4C* ID_OUI_FROM_DATABASE=KingTing Tech. OUI:E81363* ID_OUI_FROM_DATABASE=Comstock RD, Inc. OUI:6C9354* ID_OUI_FROM_DATABASE=Yaojin Technology (Shenzhen) Co., LTD. OUI:4054E4* ID_OUI_FROM_DATABASE=Wearsafe Labs Inc OUI:8CE2DA* ID_OUI_FROM_DATABASE=Circle Media Inc OUI:74D7CA* ID_OUI_FROM_DATABASE=Panasonic Corporation Automotive OUI:1CCDE5* ID_OUI_FROM_DATABASE=Shanghai Wind Technologies Co.,Ltd OUI:20896F* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:D494E8* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:B078F0* ID_OUI_FROM_DATABASE=Beijing HuaqinWorld Technology Co.,Ltd. OUI:3029BE* ID_OUI_FROM_DATABASE=Shanghai MRDcom Co.,Ltd OUI:7011AE* ID_OUI_FROM_DATABASE=Music Life LTD OUI:ECB870* ID_OUI_FROM_DATABASE=Beijing Heweinet Technology Co.,Ltd. OUI:3095E3* ID_OUI_FROM_DATABASE=SHANGHAI SIMCOM LIMITED OUI:401B5F* ID_OUI_FROM_DATABASE=Weifang GoerTek Electronics Co., Ltd. OUI:BC307E* ID_OUI_FROM_DATABASE=Wistron Neweb Corp OUI:4040A7* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:54BE53* ID_OUI_FROM_DATABASE=zte corporation OUI:588BF3* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:A01E0B* ID_OUI_FROM_DATABASE=MINIX Technology Limited OUI:D48304* ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD OUI:385F66* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:544E90* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:28C87A* ID_OUI_FROM_DATABASE=Pace plc OUI:58FC73* ID_OUI_FROM_DATABASE=Arria Live Media, Inc. OUI:2C1BC8* ID_OUI_FROM_DATABASE=Hunan Topview Network System CO.,LTD OUI:5CADCF* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:006D52* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D888CE* ID_OUI_FROM_DATABASE=RF Technology Pty Ltd OUI:D4F4BE* ID_OUI_FROM_DATABASE=Palo Alto Networks OUI:B88687* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:68F956* ID_OUI_FROM_DATABASE=Objetivos y Servicio de Valor Añadido OUI:58B633* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:AC60B6* ID_OUI_FROM_DATABASE=Ericsson AB OUI:F4E926* ID_OUI_FROM_DATABASE=Tianjin Zanpu Technology Inc. OUI:D03742* ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific(shenzhen)Co.,Lt OUI:04C23E* ID_OUI_FROM_DATABASE=HTC Corporation OUI:2CFCE4* ID_OUI_FROM_DATABASE=CTEK Sweden AB OUI:A8A795* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:10868C* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:C0B713* ID_OUI_FROM_DATABASE=Beijing Xiaoyuer Technology Co. Ltd. OUI:DCA3AC* ID_OUI_FROM_DATABASE=RBcloudtech OUI:44656A* ID_OUI_FROM_DATABASE=Mega Video Electronic(HK) Industry Co., Ltd OUI:0C9160* ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD OUI:ECA9FA* ID_OUI_FROM_DATABASE=GUANGDONG GENIUS TECHNOLOGY CO.,LTD. OUI:300C23* ID_OUI_FROM_DATABASE=zte corporation OUI:EC1F72* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD. OUI:445F8C* ID_OUI_FROM_DATABASE=Intercel Group Limited OUI:A48D3B* ID_OUI_FROM_DATABASE=Vizio, Inc OUI:1005B1* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0C756C* ID_OUI_FROM_DATABASE=Anaren Microwave, Inc. OUI:5C5188* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:A039F7* ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) OUI:689AB7* ID_OUI_FROM_DATABASE=Atelier Vision Corporation OUI:640DE6* ID_OUI_FROM_DATABASE=Petra Systems OUI:283713* ID_OUI_FROM_DATABASE=Shenzhen 3Nod Digital Technology Co., Ltd. OUI:7CAB25* ID_OUI_FROM_DATABASE=MESMO TECHNOLOGY INC. OUI:74042B* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication (Wuhan) Company Limited OUI:4455B1* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:A45602* ID_OUI_FROM_DATABASE=fenglian Technology Co.,Ltd. OUI:D06A1F* ID_OUI_FROM_DATABASE=BSE CO.,LTD. OUI:A88038* ID_OUI_FROM_DATABASE=ShenZhen MovingComm Technology Co., Limited OUI:805067* ID_OUI_FROM_DATABASE=W & D TECHNOLOGY CORPORATION OUI:402814* ID_OUI_FROM_DATABASE=RFI Engineering OUI:102C83* ID_OUI_FROM_DATABASE=XIMEA OUI:D468BA* ID_OUI_FROM_DATABASE=Shenzhen Sundray Technologies Company Limited OUI:A47B85* ID_OUI_FROM_DATABASE=ULTIMEDIA Co Ltd, OUI:CC37AB* ID_OUI_FROM_DATABASE=Edgecore Networks Corportation OUI:F80D60* ID_OUI_FROM_DATABASE=CANON INC. OUI:E02CB2* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication (Wuhan) Company Limited OUI:DC15DB* ID_OUI_FROM_DATABASE=Ge Ruili Intelligent Technology ( Beijing ) Co., Ltd. OUI:E8508B* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD. OUI:30F335* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:E89120* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:546172* ID_OUI_FROM_DATABASE=ZODIAC AEROSPACE SAS OUI:54CD10* ID_OUI_FROM_DATABASE=Panasonic Mobile Communications Co.,Ltd. OUI:A4A1E4* ID_OUI_FROM_DATABASE=Innotube, Inc. OUI:706879* ID_OUI_FROM_DATABASE=Saijo Denki International Co., Ltd. OUI:343D98* ID_OUI_FROM_DATABASE=JinQianMao Technology Co.,Ltd. OUI:5804CB* ID_OUI_FROM_DATABASE=Tianjin Huisun Technology Co.,Ltd. OUI:1CB72C* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:40B89A* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:40B837* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:287610* ID_OUI_FROM_DATABASE=IgniteNet OUI:68A378* ID_OUI_FROM_DATABASE=FREEBOX SAS OUI:746A3A* ID_OUI_FROM_DATABASE=Aperi Corporation OUI:1844E6* ID_OUI_FROM_DATABASE=zte corporation OUI:A8D409* ID_OUI_FROM_DATABASE=USA 111 Inc OUI:3089D3* ID_OUI_FROM_DATABASE=HONGKONG UCLOUDLINK NETWORK TECHNOLOGY LIMITED OUI:4CB76D* ID_OUI_FROM_DATABASE=Novi Security OUI:906CAC* ID_OUI_FROM_DATABASE=Fortinet, Inc. OUI:00323A* ID_OUI_FROM_DATABASE=so-logic OUI:64DB81* ID_OUI_FROM_DATABASE=Syszone Co., Ltd. OUI:FC6FB7* ID_OUI_FROM_DATABASE=Pace plc OUI:C4BAA3* ID_OUI_FROM_DATABASE=Beijing Winicssec Technologies Co., Ltd. OUI:A013CB* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:20635F* ID_OUI_FROM_DATABASE=Abeeway OUI:E00370* ID_OUI_FROM_DATABASE=ShenZhen Continental Wireless Technology Co., Ltd. OUI:709C8F* ID_OUI_FROM_DATABASE=Nero AG OUI:807459* ID_OUI_FROM_DATABASE=K's Co.,Ltd. OUI:CC9635* ID_OUI_FROM_DATABASE=LVS Co.,Ltd. OUI:700136* ID_OUI_FROM_DATABASE=FATEK Automation Corporation OUI:E03560* ID_OUI_FROM_DATABASE=Challenger Supply Holdings, LLC OUI:0CB5DE* ID_OUI_FROM_DATABASE=Alcatel Lucent OUI:04C9D9* ID_OUI_FROM_DATABASE=EchoStar Technologies Corp OUI:E4CE70* ID_OUI_FROM_DATABASE=Health & Life co., Ltd. OUI:EC5A86* ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd OUI:802AA8* ID_OUI_FROM_DATABASE=Ubiquiti Networks, Inc. OUI:F87AEF* ID_OUI_FROM_DATABASE=Rosonix Technology, Inc. OUI:10E878* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:BC6010* ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd OUI:C43ABE* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:18B169* ID_OUI_FROM_DATABASE=Sonicwall OUI:D4684D* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:1CC72D* ID_OUI_FROM_DATABASE=Shenzhen Huapu Digital CO.,Ltd OUI:38D82F* ID_OUI_FROM_DATABASE=zte corporation OUI:C8D779* ID_OUI_FROM_DATABASE=Qingdao Haier Telecom Co.,Ltd OUI:A0C562* ID_OUI_FROM_DATABASE=Pace plc OUI:2CA2B4* ID_OUI_FROM_DATABASE=Fortify Technologies, LLC OUI:D87495* ID_OUI_FROM_DATABASE=zte corporation OUI:8C873B* ID_OUI_FROM_DATABASE=Leica Camera AG OUI:28E476* ID_OUI_FROM_DATABASE=Pi-Coral OUI:9C685B* ID_OUI_FROM_DATABASE=Octonion SA OUI:ACABBF* ID_OUI_FROM_DATABASE=AthenTek Inc. OUI:5C41E7* ID_OUI_FROM_DATABASE=Wiatec International Ltd. OUI:DC0914* ID_OUI_FROM_DATABASE=Talk-A-Phone Co. OUI:142971* ID_OUI_FROM_DATABASE=NEMOA ELECTRONICS (HK) CO. LTD OUI:C0BDD1* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD. OUI:346895* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:B47356* ID_OUI_FROM_DATABASE=Hangzhou Treebear Networking Co., Ltd. OUI:D88D5C* ID_OUI_FROM_DATABASE=Elentec OUI:50ADD5* ID_OUI_FROM_DATABASE=Dynalec Corporation OUI:28D98A* ID_OUI_FROM_DATABASE=Hangzhou Konke Technology Co.,Ltd. OUI:BC4DFB* ID_OUI_FROM_DATABASE=Hitron Technologies. Inc OUI:6C25B9* ID_OUI_FROM_DATABASE=BBK Electronics Corp., Ltd., OUI:7429AF* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:40EACE* ID_OUI_FROM_DATABASE=FOUNDER BROADBAND NETWORK SERVICE CO.,LTD OUI:10C67E* ID_OUI_FROM_DATABASE=SHENZHEN JUCHIN TECHNOLOGY CO., LTD OUI:3C4937* ID_OUI_FROM_DATABASE=ASSMANN Electronic GmbH OUI:904506* ID_OUI_FROM_DATABASE=Tokyo Boeki Medisys Inc. OUI:80A85D* ID_OUI_FROM_DATABASE=Osterhout Design Group OUI:9C6C15* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:EC74BA* ID_OUI_FROM_DATABASE=Hirschmann Automation and Control GmbH OUI:683C7D* ID_OUI_FROM_DATABASE=Magic Intelligence Technology Limited OUI:60128B* ID_OUI_FROM_DATABASE=CANON INC. OUI:ECBAFE* ID_OUI_FROM_DATABASE=GIROPTIC OUI:E8447E* ID_OUI_FROM_DATABASE=Bitdefender SRL OUI:84C3E8* ID_OUI_FROM_DATABASE=Vaillant GmbH OUI:B88EC6* ID_OUI_FROM_DATABASE=Stateless Networks OUI:146B72* ID_OUI_FROM_DATABASE=Shenzhen Fortune Ship Technology Co., Ltd. OUI:40A5EF* ID_OUI_FROM_DATABASE=Shenzhen Four Seas Global Link Network Technology Co., Ltd. OUI:7C7A53* ID_OUI_FROM_DATABASE=Phytrex Technology Corp. OUI:4886E8* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:78FC14* ID_OUI_FROM_DATABASE=B Communications Pty Ltd OUI:88E161* ID_OUI_FROM_DATABASE=Art Beijing Science and Technology Development Co., Ltd. OUI:B4A9FE* ID_OUI_FROM_DATABASE=GHIA Technology (Shenzhen) LTD OUI:700FC7* ID_OUI_FROM_DATABASE=SHENZHEN IKINLOOP TECHNOLOGY CO.,LTD. OUI:EC8009* ID_OUI_FROM_DATABASE=NovaSparks OUI:64002D* ID_OUI_FROM_DATABASE=Powerlinq Co., LTD OUI:486B2C* ID_OUI_FROM_DATABASE=BBK Electronics Corp., Ltd., OUI:101218* ID_OUI_FROM_DATABASE=Korins Inc. OUI:EC0EC4* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:B04515* ID_OUI_FROM_DATABASE=mira fitness,LLC. OUI:307512* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:A49D49* ID_OUI_FROM_DATABASE=Ketra, Inc. OUI:C09879* ID_OUI_FROM_DATABASE=Acer Inc. OUI:1C9ECB* ID_OUI_FROM_DATABASE=Beijing Nari Smartchip Microelectronics Company Limited OUI:D48DD9* ID_OUI_FROM_DATABASE=Meld Technology, Inc OUI:2C3796* ID_OUI_FROM_DATABASE=CYBO CO.,LTD. OUI:9470D2* ID_OUI_FROM_DATABASE=WINFIRM TECHNOLOGY OUI:2C2997* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:4CE2F1* ID_OUI_FROM_DATABASE=sclak srl OUI:344DEA* ID_OUI_FROM_DATABASE=zte corporation OUI:908C09* ID_OUI_FROM_DATABASE=Total Phase OUI:1C7E51* ID_OUI_FROM_DATABASE=3bumen.com OUI:E41D2D* ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. OUI:60C798* ID_OUI_FROM_DATABASE=Verifone, Inc. OUI:380E7B* ID_OUI_FROM_DATABASE=V.P.S. Thai Co., Ltd OUI:38F33F* ID_OUI_FROM_DATABASE=TATSUNO CORPORATION OUI:28A5EE* ID_OUI_FROM_DATABASE=Shenzhen SDGI CATV Co., Ltd OUI:94CE31* ID_OUI_FROM_DATABASE=CTS Limited OUI:4CBB58* ID_OUI_FROM_DATABASE=Chicony Electronics Co., Ltd. OUI:C40006* ID_OUI_FROM_DATABASE=Lipi Data Systems Ltd. OUI:789CE7* ID_OUI_FROM_DATABASE=Shenzhen Aikede Technology Co., Ltd OUI:64899A* ID_OUI_FROM_DATABASE=LG Electronics OUI:5C2ED2* ID_OUI_FROM_DATABASE=ABC(XiSheng) Electronics Co.,Ltd OUI:D8F710* ID_OUI_FROM_DATABASE=Libre Wireless Technologies Inc. OUI:68F728* ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd OUI:DCEC06* ID_OUI_FROM_DATABASE=Heimi Network Technology Co., Ltd. OUI:8870EF* ID_OUI_FROM_DATABASE=SC Professional Trading Co., Ltd. OUI:102F6B* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:ACB74F* ID_OUI_FROM_DATABASE=METEL s.r.o. OUI:CCF538* ID_OUI_FROM_DATABASE=3isysnetworks OUI:04DEDB* ID_OUI_FROM_DATABASE=Rockport Networks Inc OUI:68F06D* ID_OUI_FROM_DATABASE=ALONG INDUSTRIAL CO., LIMITED OUI:54F876* ID_OUI_FROM_DATABASE=ABB AG OUI:4857DD* ID_OUI_FROM_DATABASE=Facebook OUI:84930C* ID_OUI_FROM_DATABASE=InCoax Networks Europe AB OUI:D47B35* ID_OUI_FROM_DATABASE=NEO Monitors AS OUI:D8FB11* ID_OUI_FROM_DATABASE=AXACORE OUI:C8D019* ID_OUI_FROM_DATABASE=Shanghai Tigercel Communication Technology Co.,Ltd OUI:18A958* ID_OUI_FROM_DATABASE=PROVISION THAI CO., LTD. OUI:D8DECE* ID_OUI_FROM_DATABASE=ISUNG CO.,LTD OUI:2053CA* ID_OUI_FROM_DATABASE=Risk Technology Ltd OUI:142BD6* ID_OUI_FROM_DATABASE=Guangdong Appscomm Co.,Ltd OUI:C8BA94* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD. OUI:B025AA* ID_OUI_FROM_DATABASE=Private OUI:408256* ID_OUI_FROM_DATABASE=Continental Automotive GmbH OUI:D866EE* ID_OUI_FROM_DATABASE=BOXIN COMMUNICATION CO.,LTD. OUI:3C189F* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:2829CC* ID_OUI_FROM_DATABASE=Corsa Technology Incorporated OUI:FC790B* ID_OUI_FROM_DATABASE=Hitachi High Technologies America, Inc. OUI:28E6E9* ID_OUI_FROM_DATABASE=SIS Sat Internet Services GmbH OUI:BC4E5D* ID_OUI_FROM_DATABASE=ZhongMiao Technology Co., Ltd. OUI:08F728* ID_OUI_FROM_DATABASE=GLOBO Multimedia Sp. z o.o. Sp.k. OUI:70720D* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:8401A7* ID_OUI_FROM_DATABASE=Greyware Automation Products, Inc OUI:C4C9EC* ID_OUI_FROM_DATABASE=Gugaoo HK Limited OUI:F406A5* ID_OUI_FROM_DATABASE=Hangzhou Bianfeng Networking Technology Co., Ltd. OUI:4C3909* ID_OUI_FROM_DATABASE=HPL Electric & Power Private Limited OUI:7CFE4E* ID_OUI_FROM_DATABASE=Shenzhen Safe vision Technology Co.,LTD OUI:54EF92* ID_OUI_FROM_DATABASE=Shenzhen Elink Technology Co., LTD OUI:800E24* ID_OUI_FROM_DATABASE=ForgetBox OUI:FCE186* ID_OUI_FROM_DATABASE=A3M Co., LTD OUI:CCB691* ID_OUI_FROM_DATABASE=NECMagnusCommunications OUI:40167E* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:C89F1D* ID_OUI_FROM_DATABASE=SHENZHEN COMMUNICATION TECHNOLOGIES CO.,LTD OUI:983713* ID_OUI_FROM_DATABASE=PT.Navicom Indonesia OUI:ACA919* ID_OUI_FROM_DATABASE=TrekStor GmbH OUI:84850A* ID_OUI_FROM_DATABASE=Hella Sonnen- und Wetterschutztechnik GmbH OUI:183009* ID_OUI_FROM_DATABASE=Woojin Industrial Systems Co., Ltd. OUI:6081F9* ID_OUI_FROM_DATABASE=Helium Systems, Inc OUI:34C5D0* ID_OUI_FROM_DATABASE=Hagleitner Hygiene International GmbH OUI:74DBD1* ID_OUI_FROM_DATABASE=Ebay Inc OUI:3431C4* ID_OUI_FROM_DATABASE=AVM GmbH OUI:DC537C* ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc. OUI:A00627* ID_OUI_FROM_DATABASE=NEXPA System OUI:303335* ID_OUI_FROM_DATABASE=Boosty OUI:18D5B6* ID_OUI_FROM_DATABASE=SMG Holdings LLC OUI:C8FF77* ID_OUI_FROM_DATABASE=Dyson Limited OUI:C03D46* ID_OUI_FROM_DATABASE=Shanghai Mochui Network Technology Co., Ltd OUI:DCF110* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:54DF00* ID_OUI_FROM_DATABASE=Ulterius Technologies, LLC OUI:E01D38* ID_OUI_FROM_DATABASE=Beijing HuaqinWorld Technology Co.,Ltd OUI:D80CCF* ID_OUI_FROM_DATABASE=C.G.V. S.A.S. OUI:143DF2* ID_OUI_FROM_DATABASE=Beijing Shidai Hongyuan Network Communication Co.,Ltd OUI:B0D59D* ID_OUI_FROM_DATABASE=Shenzhen Zowee Technology Co., Ltd OUI:C4913A* ID_OUI_FROM_DATABASE=Shenzhen Sanland Electronic Co., ltd. OUI:A46032* ID_OUI_FROM_DATABASE=MRV Communications (Networks) LTD OUI:205A00* ID_OUI_FROM_DATABASE=Coval OUI:0C2026* ID_OUI_FROM_DATABASE=noax Technologies AG OUI:240A11* ID_OUI_FROM_DATABASE=TCT Mobile Limited OUI:880FB6* ID_OUI_FROM_DATABASE=Jabil Circuits India Pvt Ltd,-EHTP unit OUI:C4626B* ID_OUI_FROM_DATABASE=ZPT Vigantice OUI:74F85D* ID_OUI_FROM_DATABASE=Berkeley Nucleonics Corp OUI:08D833* ID_OUI_FROM_DATABASE=Shenzhen RF Technology Co,.Ltd OUI:48EE07* ID_OUI_FROM_DATABASE=Silver Palm Technologies LLC OUI:9CFBF1* ID_OUI_FROM_DATABASE=MESOMATIC GmbH & Co.KG OUI:94C014* ID_OUI_FROM_DATABASE=Sorter Sp. j. Konrad Grzeszczyk MichaA, Ziomek OUI:1027BE* ID_OUI_FROM_DATABASE=TVIP OUI:2087AC* ID_OUI_FROM_DATABASE=AES motomation OUI:A824EB* ID_OUI_FROM_DATABASE=ZAO NPO Introtest OUI:447E76* ID_OUI_FROM_DATABASE=Trek Technology (S) Pte Ltd OUI:E8FC60* ID_OUI_FROM_DATABASE=ELCOM Innovations Private Limited OUI:1CFCBB* ID_OUI_FROM_DATABASE=Realfiction ApS OUI:B0EC8F* ID_OUI_FROM_DATABASE=GMX SAS OUI:C40E45* ID_OUI_FROM_DATABASE=ACK Networks,Inc. OUI:5C254C* ID_OUI_FROM_DATABASE=Avire Global Pte Ltd OUI:7C1A03* ID_OUI_FROM_DATABASE=8Locations Co., Ltd. OUI:481842* ID_OUI_FROM_DATABASE=Shanghai Winaas Co. Equipment Co. Ltd. OUI:E817FC* ID_OUI_FROM_DATABASE=NIFTY Corporation OUI:D09C30* ID_OUI_FROM_DATABASE=Foster Electric Company, Limited OUI:78FEE2* ID_OUI_FROM_DATABASE=Shanghai Diveo Technology Co., Ltd OUI:386C9B* ID_OUI_FROM_DATABASE=Ivy Biomedical OUI:E44C6C* ID_OUI_FROM_DATABASE=Shenzhen Guo Wei Electronic Co,. Ltd. OUI:008B43* ID_OUI_FROM_DATABASE=RFTECH OUI:2C957F* ID_OUI_FROM_DATABASE=zte corporation OUI:242642* ID_OUI_FROM_DATABASE=SHARP Corporation. OUI:282246* ID_OUI_FROM_DATABASE=Beijing Sinoix Communication Co., LTD OUI:FC1607* ID_OUI_FROM_DATABASE=Taian Technology(Wuxi) Co.,Ltd. OUI:CC89FD* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:E86183* ID_OUI_FROM_DATABASE=Black Diamond Advanced Technology, LLC OUI:C4824E* ID_OUI_FROM_DATABASE=Changzhou Uchip Electronics Co., LTD. OUI:24A87D* ID_OUI_FROM_DATABASE=Panasonic Automotive Systems Asia Pacific(Thailand)Co.,Ltd. OUI:78EC74* ID_OUI_FROM_DATABASE=Kyland-USA OUI:28C825* ID_OUI_FROM_DATABASE=DellKing Industrial Co., Ltd OUI:64E892* ID_OUI_FROM_DATABASE=Morio Denki Co., Ltd. OUI:086DF2* ID_OUI_FROM_DATABASE=Shenzhen MIMOWAVE Technology Co.,Ltd OUI:64EB8C* ID_OUI_FROM_DATABASE=Seiko Epson Corporation OUI:48D0CF* ID_OUI_FROM_DATABASE=Universal Electronics, Inc. OUI:AC3613* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:DCC793* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:E03F49* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:D8EE78* ID_OUI_FROM_DATABASE=Moog Protokraft OUI:F4B6E5* ID_OUI_FROM_DATABASE=TerraSem Co.,Ltd OUI:28BB59* ID_OUI_FROM_DATABASE=RNET Technologies, Inc. OUI:7C8D91* ID_OUI_FROM_DATABASE=Shanghai Hongzhuo Information Technology co.,LTD OUI:A881F1* ID_OUI_FROM_DATABASE=BMEYE B.V. OUI:241148* ID_OUI_FROM_DATABASE=Entropix, LLC OUI:30B5C2* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:F85C45* ID_OUI_FROM_DATABASE=IC Nexus Co. Ltd. OUI:88F7C7* ID_OUI_FROM_DATABASE=Technicolor USA Inc. OUI:04DB8A* ID_OUI_FROM_DATABASE=Suntech International Ltd. OUI:083F76* ID_OUI_FROM_DATABASE=Intellian Technologies, Inc. OUI:0CC47A* ID_OUI_FROM_DATABASE=Super Micro Computer, Inc. OUI:D0634D* ID_OUI_FROM_DATABASE=Meiko Maschinenbau GmbH & Co. KG OUI:24DBED* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:88C626* ID_OUI_FROM_DATABASE=Logitech - Ultimate Ears OUI:889CA6* ID_OUI_FROM_DATABASE=BTB Korea INC OUI:F025B7* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD. OUI:B0DA00* ID_OUI_FROM_DATABASE=CERA ELECTRONIQUE OUI:447098* ID_OUI_FROM_DATABASE=MING HONG TECHNOLOGY (SHEN ZHEN) LIMITED OUI:54E2E0* ID_OUI_FROM_DATABASE=Pace plc OUI:00EEBD* ID_OUI_FROM_DATABASE=HTC Corporation OUI:48B5A7* ID_OUI_FROM_DATABASE=Glory Horse Industries Ltd. OUI:DC5E36* ID_OUI_FROM_DATABASE=Paterson Technology OUI:50E0C7* ID_OUI_FROM_DATABASE=TurControlSystme AG OUI:9CD643* ID_OUI_FROM_DATABASE=D-Link International OUI:28FC51* ID_OUI_FROM_DATABASE=The Electric Controller and Manufacturing Co., LLC OUI:34A5E1* ID_OUI_FROM_DATABASE=Sensorist ApS OUI:A4E9A3* ID_OUI_FROM_DATABASE=Honest Technology Co., Ltd OUI:C4E92F* ID_OUI_FROM_DATABASE=AB Sciex OUI:9C216A* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:F862AA* ID_OUI_FROM_DATABASE=xn systems OUI:A4059E* ID_OUI_FROM_DATABASE=STA Infinity LLP OUI:6C15F9* ID_OUI_FROM_DATABASE=Nautronix Limited OUI:680AD7* ID_OUI_FROM_DATABASE=Yancheng Kecheng Optoelectronic Technology Co., Ltd OUI:BC8893* ID_OUI_FROM_DATABASE=VILLBAU Ltd. OUI:643F5F* ID_OUI_FROM_DATABASE=Exablaze OUI:E8F226* ID_OUI_FROM_DATABASE=MILLSON CUSTOM SOLUTIONS INC. OUI:7060DE* ID_OUI_FROM_DATABASE=LaVision GmbH OUI:FCFE77* ID_OUI_FROM_DATABASE=Hitachi Reftechno, Inc. OUI:24E271* ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd OUI:70533F* ID_OUI_FROM_DATABASE=Alfa Instrumentos Eletronicos Ltda. OUI:448A5B* ID_OUI_FROM_DATABASE=Micro-Star INT'L CO., LTD. OUI:68193F* ID_OUI_FROM_DATABASE=Digital Airways OUI:5CD61F* ID_OUI_FROM_DATABASE=Qardio, Inc OUI:902083* ID_OUI_FROM_DATABASE=General Engine Management Systems Ltd. OUI:14B126* ID_OUI_FROM_DATABASE=Industrial Software Co OUI:C03580* ID_OUI_FROM_DATABASE=A&R TECH OUI:1446E4* ID_OUI_FROM_DATABASE=AVISTEL OUI:907990* ID_OUI_FROM_DATABASE=Benchmark Electronics Romania SRL OUI:C49380* ID_OUI_FROM_DATABASE=Speedytel technology OUI:B4A82B* ID_OUI_FROM_DATABASE=Histar Digital Electronics Co., Ltd. OUI:60A9B0* ID_OUI_FROM_DATABASE=Merchandising Technologies, Inc OUI:007DFA* ID_OUI_FROM_DATABASE=Volkswagen Group of America OUI:6024C1* ID_OUI_FROM_DATABASE=Jiangsu Zhongxun Electronic Technology Co., Ltd OUI:6C5AB5* ID_OUI_FROM_DATABASE=TCL Technoly Electronics (Huizhou) Co., Ltd. OUI:88789C* ID_OUI_FROM_DATABASE=Game Technologies SA OUI:18AA45* ID_OUI_FROM_DATABASE=Fon Technology OUI:0073E0* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:549359* ID_OUI_FROM_DATABASE=SHENZHEN TWOWING TECHNOLOGIES CO.,LTD. OUI:BC4486* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:284430* ID_OUI_FROM_DATABASE=GenesisTechnical Systems (UK) Ltd OUI:9843DA* ID_OUI_FROM_DATABASE=INTERTECH OUI:8056F2* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:285767* ID_OUI_FROM_DATABASE=Echostar Technologies Corp OUI:B07908* ID_OUI_FROM_DATABASE=Cummings Engineering OUI:04CB1D* ID_OUI_FROM_DATABASE=Traka plc OUI:B87AC9* ID_OUI_FROM_DATABASE=Siemens Ltd. OUI:B0989F* ID_OUI_FROM_DATABASE=LG CNS OUI:3C300C* ID_OUI_FROM_DATABASE=Dewar Electronics Pty Ltd OUI:78B5D2* ID_OUI_FROM_DATABASE=Ever Treasure Industrial Limited OUI:A409CB* ID_OUI_FROM_DATABASE=Alfred Kaercher GmbH & Co KG OUI:C445EC* ID_OUI_FROM_DATABASE=Shanghai Yali Electron Co.,LTD OUI:380B40* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E8611F* ID_OUI_FROM_DATABASE=Dawning Information Industry Co.,Ltd OUI:0CA694* ID_OUI_FROM_DATABASE=Sunitec Enterprise Co.,Ltd OUI:146080* ID_OUI_FROM_DATABASE=zte corporation OUI:986CF5* ID_OUI_FROM_DATABASE=zte corporation OUI:78491D* ID_OUI_FROM_DATABASE=The Will-Burt Company OUI:74D435* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:840F45* ID_OUI_FROM_DATABASE=Shanghai GMT Digital Technologies Co., Ltd OUI:58A2B5* ID_OUI_FROM_DATABASE=LG Electronics OUI:D8270C* ID_OUI_FROM_DATABASE=MaxTronic International Co., Ltd. OUI:E80410* ID_OUI_FROM_DATABASE=Private OUI:8C088B* ID_OUI_FROM_DATABASE=Remote Solution OUI:A47760* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:24A495* ID_OUI_FROM_DATABASE=Thales Canada Inc. OUI:70188B* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:3C77E6* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:5CDD70* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:883612* ID_OUI_FROM_DATABASE=SRC Computers, LLC OUI:E0A198* ID_OUI_FROM_DATABASE=NOJA Power Switchgear Pty Ltd OUI:CC7B35* ID_OUI_FROM_DATABASE=zte corporation OUI:04D437* ID_OUI_FROM_DATABASE=ZNV OUI:CCF407* ID_OUI_FROM_DATABASE=EUKREA ELECTROMATIQUE SARL OUI:BC2BD7* ID_OUI_FROM_DATABASE=Revogi Innovation Co., Ltd. OUI:3C404F* ID_OUI_FROM_DATABASE=Guangdong Pisen Electronics Co. Ltd. OUI:24ECD6* ID_OUI_FROM_DATABASE=CSG Science & Technology Co.,Ltd.Hefei OUI:102279* ID_OUI_FROM_DATABASE=ZeroDesktop, Inc. OUI:CC4AE1* ID_OUI_FROM_DATABASE=fourtec -Fourier Technologies OUI:A4895B* ID_OUI_FROM_DATABASE=ARK INFOSOLUTIONS PVT LTD OUI:38EC11* ID_OUI_FROM_DATABASE=Novatek Microelectronics Corp. OUI:A8CCC5* ID_OUI_FROM_DATABASE=Saab AB (publ) OUI:988E4A* ID_OUI_FROM_DATABASE=NOXUS(BEIJING) TECHNOLOGY CO.,LTD OUI:1C4158* ID_OUI_FROM_DATABASE=Gemalto M2M GmbH OUI:ACD657* ID_OUI_FROM_DATABASE=Shaanxi Guolian Digital TV Technology Co., Ltd. OUI:541B5D* ID_OUI_FROM_DATABASE=Techno-Innov OUI:78CB33* ID_OUI_FROM_DATABASE=DHC Software Co.,Ltd OUI:507691* ID_OUI_FROM_DATABASE=Tekpea, Inc. OUI:C421C8* ID_OUI_FROM_DATABASE=KYOCERA Corporation OUI:A4C0C7* ID_OUI_FROM_DATABASE=ShenZhen Hitom Communication Technology Co..LTD OUI:EC2257* ID_OUI_FROM_DATABASE=JiangSu NanJing University Electronic Information Technology Co.,Ltd OUI:0C84DC* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:341A4C* ID_OUI_FROM_DATABASE=SHENZHEN WEIBU ELECTRONICS CO.,LTD. OUI:A09BBD* ID_OUI_FROM_DATABASE=Total Aviation Solutions Pty Ltd OUI:E8481F* ID_OUI_FROM_DATABASE=Advanced Automotive Antennas OUI:18D6CF* ID_OUI_FROM_DATABASE=Kurth Electronic GmbH OUI:E07F88* ID_OUI_FROM_DATABASE=EVIDENCE Network SIA OUI:1C7CC7* ID_OUI_FROM_DATABASE=Coriant GmbH OUI:542CEA* ID_OUI_FROM_DATABASE=PROTECTRON OUI:00C5DB* ID_OUI_FROM_DATABASE=Datatech Sistemas Digitales Avanzados SL OUI:109AB9* ID_OUI_FROM_DATABASE=Tosibox Oy OUI:F842FB* ID_OUI_FROM_DATABASE=Yasuda Joho Co.,ltd. OUI:887398* ID_OUI_FROM_DATABASE=K2E Tekpoint OUI:68EE96* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:FC6018* ID_OUI_FROM_DATABASE=Zhejiang Kangtai Electric Co., Ltd. OUI:303EAD* ID_OUI_FROM_DATABASE=Sonavox Canada Inc OUI:444A65* ID_OUI_FROM_DATABASE=Silverflare Ltd. OUI:50A0BF* ID_OUI_FROM_DATABASE=Alba Fiber Systems Inc. OUI:3C977E* ID_OUI_FROM_DATABASE=IPS Technology Limited OUI:F02405* ID_OUI_FROM_DATABASE=OPUS High Technology Corporation OUI:D8B04C* ID_OUI_FROM_DATABASE=Jinan USR IOT Technology Co., Ltd. OUI:646EEA* ID_OUI_FROM_DATABASE=Iskratel d.o.o. OUI:043D98* ID_OUI_FROM_DATABASE=ChongQing QingJia Electronics CO.,LTD OUI:E8BB3D* ID_OUI_FROM_DATABASE=Sino Prime-Tech Limited OUI:E492FB* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:98CDB4* ID_OUI_FROM_DATABASE=Virident Systems, Inc. OUI:54E3B0* ID_OUI_FROM_DATABASE=JVL Industri Elektronik OUI:640B4A* ID_OUI_FROM_DATABASE=Digital Telecom Technology Limited OUI:F42012* ID_OUI_FROM_DATABASE=Cuciniale GmbH OUI:4C21D0* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:18104E* ID_OUI_FROM_DATABASE=CEDINT-UPM OUI:2C7B84* ID_OUI_FROM_DATABASE=OOO Petr Telegin OUI:540536* ID_OUI_FROM_DATABASE=Vivago Oy OUI:2CE6CC* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:E0FAEC* ID_OUI_FROM_DATABASE=Platan sp. z o.o. sp. k. OUI:F08EDB* ID_OUI_FROM_DATABASE=VeloCloud Networks OUI:B8DC87* ID_OUI_FROM_DATABASE=IAI Corporation OUI:7C6FF8* ID_OUI_FROM_DATABASE=ShenZhen ACTO Digital Video Technology Co.,Ltd. OUI:8C4B59* ID_OUI_FROM_DATABASE=3D Imaging & Simulations Corp OUI:A4FB8D* ID_OUI_FROM_DATABASE=Hangzhou Dunchong Technology Co.Ltd OUI:0075E1* ID_OUI_FROM_DATABASE=Ampt, LLC OUI:CC04B4* ID_OUI_FROM_DATABASE=Select Comfort OUI:284FCE* ID_OUI_FROM_DATABASE=Liaoning Wontel Science and Technology Development Co.,Ltd. OUI:1449E0* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co.,LTD. OUI:0CC81F* ID_OUI_FROM_DATABASE=Summer Infant, Inc. OUI:D86960* ID_OUI_FROM_DATABASE=Steinsvik OUI:442AFF* ID_OUI_FROM_DATABASE=E3 Technology, Inc. OUI:E440E2* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:0C9301* ID_OUI_FROM_DATABASE=PT. Prasimax Inovasi Teknologi OUI:1CAF05* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:60699B* ID_OUI_FROM_DATABASE=isepos GmbH OUI:B830A8* ID_OUI_FROM_DATABASE=Road-Track Telematics Development OUI:542160* ID_OUI_FROM_DATABASE=Resolution Products OUI:88462A* ID_OUI_FROM_DATABASE=Telechips Inc. OUI:A897DC* ID_OUI_FROM_DATABASE=IBM OUI:E8DE27* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:FC229C* ID_OUI_FROM_DATABASE=Han Kyung I Net Co.,Ltd. OUI:148692* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:1832A2* ID_OUI_FROM_DATABASE=LAON TECHNOLOGY CO., LTD. OUI:6854ED* ID_OUI_FROM_DATABASE=Alcatel-Lucent - Nuage OUI:985C93* ID_OUI_FROM_DATABASE=SBG Systems SAS OUI:64E599* ID_OUI_FROM_DATABASE=EFM Networks OUI:F499AC* ID_OUI_FROM_DATABASE=WEBER Schraubautomaten GmbH OUI:8CC7D0* ID_OUI_FROM_DATABASE=zhejiang ebang communication co.,ltd OUI:70820E* ID_OUI_FROM_DATABASE=as electronics GmbH OUI:DC2BCA* ID_OUI_FROM_DATABASE=Zera GmbH OUI:508D6F* ID_OUI_FROM_DATABASE=CHAHOO Limited OUI:68831A* ID_OUI_FROM_DATABASE=Pandora Mobility Corporation OUI:D4223F* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:0868D0* ID_OUI_FROM_DATABASE=Japan System Design OUI:103DEA* ID_OUI_FROM_DATABASE=HFC Technology (Beijing) Ltd. Co. OUI:E8E875* ID_OUI_FROM_DATABASE=iS5 Communications Inc. OUI:2C7B5A* ID_OUI_FROM_DATABASE=Milper Ltd OUI:185AE8* ID_OUI_FROM_DATABASE=Zenotech.Co.,Ltd OUI:E0AEED* ID_OUI_FROM_DATABASE=LOENK OUI:D4EE07* ID_OUI_FROM_DATABASE=HIWIFI Co., Ltd. OUI:908260* ID_OUI_FROM_DATABASE=IEEE 1904.1 Working Group OUI:FCAD0F* ID_OUI_FROM_DATABASE=QTS NETWORKS OUI:984C04* ID_OUI_FROM_DATABASE=Zhangzhou Keneng Electrical Equipment Co Ltd OUI:CC047C* ID_OUI_FROM_DATABASE=G-WAY Microwave OUI:44F849* ID_OUI_FROM_DATABASE=Union Pacific Railroad OUI:1CFA68* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:D0BE2C* ID_OUI_FROM_DATABASE=CNSLink Co., Ltd. OUI:281878* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:E457A8* ID_OUI_FROM_DATABASE=Stuart Manufacturing, Inc. OUI:2481AA* ID_OUI_FROM_DATABASE=KSH International Co., Ltd. OUI:789966* ID_OUI_FROM_DATABASE=Musilab Electronics (DongGuan)Co.,Ltd. OUI:D8B02E* ID_OUI_FROM_DATABASE=Guangzhou Zonerich Business Machine Co., Ltd OUI:EC2C49* ID_OUI_FROM_DATABASE=University of Tokyo OUI:CC5D57* ID_OUI_FROM_DATABASE=Information System Research Institute,Inc. OUI:1C37BF* ID_OUI_FROM_DATABASE=Cloudium Systems Ltd. OUI:249504* ID_OUI_FROM_DATABASE=SFR OUI:308999* ID_OUI_FROM_DATABASE=Guangdong East Power Co., OUI:D4A499* ID_OUI_FROM_DATABASE=InView Technology Corporation OUI:AC4122* ID_OUI_FROM_DATABASE=Eclipse Electronic Systems Inc. OUI:A073FC* ID_OUI_FROM_DATABASE=Rancore Technologies Private Limited OUI:846223* ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd. OUI:A4E991* ID_OUI_FROM_DATABASE=SISTEMAS AUDIOVISUALES ITELSIS S.L. OUI:84F493* ID_OUI_FROM_DATABASE=OMS spol. s.r.o. OUI:386793* ID_OUI_FROM_DATABASE=Asia Optical Co., Inc. OUI:BCD177* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:C8B373* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:983071* ID_OUI_FROM_DATABASE=DAIKYUNG VASCOM OUI:0C0400* ID_OUI_FROM_DATABASE=Jantar d.o.o. OUI:C04301* ID_OUI_FROM_DATABASE=Epec Oy OUI:687CD5* ID_OUI_FROM_DATABASE=Y Soft Corporation, a.s. OUI:E07C62* ID_OUI_FROM_DATABASE=Whistle Labs, Inc. OUI:FC4499* ID_OUI_FROM_DATABASE=Swarco LEA d.o.o. OUI:0C8484* ID_OUI_FROM_DATABASE=Zenovia Electronics Inc. OUI:5CF370* ID_OUI_FROM_DATABASE=CC&C Technologies, Inc OUI:A01C05* ID_OUI_FROM_DATABASE=NIMAX TELECOM CO.,LTD. OUI:F80DEA* ID_OUI_FROM_DATABASE=ZyCast Technology Inc. OUI:1800DB* ID_OUI_FROM_DATABASE=Fitbit Inc. OUI:50A715* ID_OUI_FROM_DATABASE=Aboundi, Inc. OUI:FC35E6* ID_OUI_FROM_DATABASE=Visteon corp OUI:D866C6* ID_OUI_FROM_DATABASE=Shenzhen Daystar Technology Co.,ltd OUI:1836FC* ID_OUI_FROM_DATABASE=Elecsys International Corporation OUI:F48139* ID_OUI_FROM_DATABASE=CANON INC. OUI:D40BB9* ID_OUI_FROM_DATABASE=Solid Semecs bv. OUI:748E08* ID_OUI_FROM_DATABASE=Bestek Corp. OUI:B8C855* ID_OUI_FROM_DATABASE=Shanghai GBCOM Communication Technology Co.,Ltd. OUI:54A619* ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd OUI:C47DFE* ID_OUI_FROM_DATABASE=A.N. Solutions GmbH OUI:E031D0* ID_OUI_FROM_DATABASE=SZ Telstar CO., LTD OUI:70C6AC* ID_OUI_FROM_DATABASE=Bosch Automotive Aftermarket OUI:2C69BA* ID_OUI_FROM_DATABASE=RF Controls, LLC OUI:DC5726* ID_OUI_FROM_DATABASE=Power-One OUI:2C245F* ID_OUI_FROM_DATABASE=Babolat VS OUI:D464F7* ID_OUI_FROM_DATABASE=CHENGDU USEE DIGITAL TECHNOLOGY CO., LTD OUI:A47ACF* ID_OUI_FROM_DATABASE=VIBICOM COMMUNICATIONS INC. OUI:CC3C3F* ID_OUI_FROM_DATABASE=SA.S.S. Datentechnik AG OUI:905692* ID_OUI_FROM_DATABASE=Autotalks Ltd. OUI:0C2AE7* ID_OUI_FROM_DATABASE=Beijing General Research Institute of Mining and Metallurgy OUI:4439C4* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co.,Ltd OUI:DCD52A* ID_OUI_FROM_DATABASE=Sunny Heart Limited OUI:C4C755* ID_OUI_FROM_DATABASE=Beijing HuaqinWorld Technology Co.,Ltd OUI:9C79AC* ID_OUI_FROM_DATABASE=Suntec Software(Shanghai) Co., Ltd. OUI:6488FF* ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. OUI:F8DFA8* ID_OUI_FROM_DATABASE=zte corporation OUI:ACA430* ID_OUI_FROM_DATABASE=Peerless AV OUI:B4AB2C* ID_OUI_FROM_DATABASE=MtM Technology Corporation OUI:74372F* ID_OUI_FROM_DATABASE=Tongfang Shenzhen Cloudcomputing Technology Co.,Ltd OUI:BC51FE* ID_OUI_FROM_DATABASE=Swann communications Pty Ltd OUI:789ED0* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:D40FB2* ID_OUI_FROM_DATABASE=Applied Micro Electronics AME bv OUI:74FE48* ID_OUI_FROM_DATABASE=ADVANTECH CO., LTD. OUI:D0B498* ID_OUI_FROM_DATABASE=Robert Bosch LLC Automotive Electronics OUI:80B95C* ID_OUI_FROM_DATABASE=ELFTECH Co., Ltd. OUI:E85AA7* ID_OUI_FROM_DATABASE=LLC Emzior OUI:242FFA* ID_OUI_FROM_DATABASE=Toshiba Global Commerce Solutions OUI:A0BAB8* ID_OUI_FROM_DATABASE=Pixon Imaging OUI:9CE1D6* ID_OUI_FROM_DATABASE=Junger Audio-Studiotechnik GmbH OUI:E4E409* ID_OUI_FROM_DATABASE=LEIFHEIT AG OUI:004D32* ID_OUI_FROM_DATABASE=Andon Health Co.,Ltd. OUI:8C04FF* ID_OUI_FROM_DATABASE=Technicolor USA Inc. OUI:C46DF1* ID_OUI_FROM_DATABASE=DataGravity OUI:28D244* ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology Co., Ltd. OUI:ACE87E* ID_OUI_FROM_DATABASE=Bytemark Computer Consulting Ltd OUI:60CDC5* ID_OUI_FROM_DATABASE=Taiwan Carol Electronics., Ltd OUI:1489FD* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:60C5A8* ID_OUI_FROM_DATABASE=Beijing LT Honway Technology Co.,Ltd OUI:B4DF3B* ID_OUI_FROM_DATABASE=Chromlech OUI:A46E79* ID_OUI_FROM_DATABASE=DFT System Co.Ltd OUI:94DE80* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:C88A83* ID_OUI_FROM_DATABASE=Dongguan HuaHong Electronics Co.,Ltd OUI:0CC655* ID_OUI_FROM_DATABASE=Wuxi YSTen Technology Co.,Ltd. OUI:D410CF* ID_OUI_FROM_DATABASE=Huanshun Network Science and Technology Co., Ltd. OUI:B80415* ID_OUI_FROM_DATABASE=Bayan Audio OUI:84C8B1* ID_OUI_FROM_DATABASE=Incognito Software Systems Inc. OUI:645A04* ID_OUI_FROM_DATABASE=Chicony Electronics Co., Ltd. OUI:5C89D4* ID_OUI_FROM_DATABASE=Beijing Banner Electric Co.,Ltd OUI:984CD3* ID_OUI_FROM_DATABASE=Mantis Deposition OUI:8C4CDC* ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. OUI:10683F* ID_OUI_FROM_DATABASE=LG Electronics OUI:D063B4* ID_OUI_FROM_DATABASE=SolidRun Ltd. OUI:2C3BFD* ID_OUI_FROM_DATABASE=Netstor Technology Co., Ltd. OUI:F073AE* ID_OUI_FROM_DATABASE=PEAK-System Technik OUI:684CA8* ID_OUI_FROM_DATABASE=Shenzhen Herotel Tech. Co., Ltd. OUI:F4472A* ID_OUI_FROM_DATABASE=Nanjing Rousing Sci. and Tech. Industrial Co., Ltd OUI:185253* ID_OUI_FROM_DATABASE=Pixord Corporation OUI:A41731* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:FCA9B0* ID_OUI_FROM_DATABASE=MIARTECH (SHANGHAI),INC. OUI:80D733* ID_OUI_FROM_DATABASE=QSR Automations, Inc. OUI:8C3330* ID_OUI_FROM_DATABASE=EmFirst Co., Ltd. OUI:8C0C90* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:08E5DA* ID_OUI_FROM_DATABASE=NANJING FUJITSU COMPUTER PRODUCTS CO.,LTD. OUI:5884E4* ID_OUI_FROM_DATABASE=IP500 Alliance e.V. OUI:04E9E5* ID_OUI_FROM_DATABASE=PJRC.COM, LLC OUI:703811* ID_OUI_FROM_DATABASE=Invensys Rail OUI:ACE64B* ID_OUI_FROM_DATABASE=Shenzhen Baojia Battery Technology Co., Ltd. OUI:303294* ID_OUI_FROM_DATABASE=W-IE-NE-R Plein & Baus GmbH OUI:EC473C* ID_OUI_FROM_DATABASE=Redwire, LLC OUI:5481AD* ID_OUI_FROM_DATABASE=Eagle Research Corporation OUI:7C822D* ID_OUI_FROM_DATABASE=Nortec OUI:745FAE* ID_OUI_FROM_DATABASE=TSL PPL OUI:8462A6* ID_OUI_FROM_DATABASE=EuroCB (Phils), Inc. OUI:80FA5B* ID_OUI_FROM_DATABASE=CLEVO CO. OUI:E4F365* ID_OUI_FROM_DATABASE=Time-O-Matic, Inc. OUI:18550F* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:1C9179* ID_OUI_FROM_DATABASE=Integrated System Technologies Ltd OUI:38F597* ID_OUI_FROM_DATABASE=home2net GmbH OUI:386645* ID_OUI_FROM_DATABASE=OOSIC Technology CO.,Ltd OUI:D0DFB2* ID_OUI_FROM_DATABASE=Genie Networks Limited OUI:808B5C* ID_OUI_FROM_DATABASE=Shenzhen Runhuicheng Technology Co., Ltd OUI:04586F* ID_OUI_FROM_DATABASE=Sichuan Whayer information industry Co.,LTD OUI:449B78* ID_OUI_FROM_DATABASE=The Now Factory OUI:D052A8* ID_OUI_FROM_DATABASE=Physical Graph Corporation OUI:EC43F6* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:34F62D* ID_OUI_FROM_DATABASE=SHARP Corporation OUI:C4EBE3* ID_OUI_FROM_DATABASE=RRCN SAS OUI:4C1A95* ID_OUI_FROM_DATABASE=Novakon Co., Ltd. OUI:C04A00* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:9C3178* ID_OUI_FROM_DATABASE=Foshan Huadian Intelligent Communications Teachnologies Co.,Ltd OUI:48BE2D* ID_OUI_FROM_DATABASE=Symanitron OUI:38E595* ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd OUI:B86091* ID_OUI_FROM_DATABASE=Onnet Technologies and Innovations LLC OUI:201A06* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:D4CA6E* ID_OUI_FROM_DATABASE=u-blox AG OUI:C011A6* ID_OUI_FROM_DATABASE=Fort-Telecom ltd. OUI:B8DAF1* ID_OUI_FROM_DATABASE=Strahlenschutz- Entwicklungs- und Ausruestungsgesellschaft mbH OUI:1C11E1* ID_OUI_FROM_DATABASE=Wartsila Finland Oy OUI:50465D* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:74BFA1* ID_OUI_FROM_DATABASE=HYUNTECK OUI:FCF528* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:F8AA8A* ID_OUI_FROM_DATABASE=Axview Technology (Shenzhen) Co.,Ltd OUI:60F494* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:5894CF* ID_OUI_FROM_DATABASE=Vertex Standard LMR, Inc. OUI:2C5AA3* ID_OUI_FROM_DATABASE=PROMATE ELECTRONIC CO.LTD OUI:9852B1* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:B4009C* ID_OUI_FROM_DATABASE=CableWorld Ltd. OUI:803FD6* ID_OUI_FROM_DATABASE=bytes at work AG OUI:645FFF* ID_OUI_FROM_DATABASE=Nicolet Neuro OUI:2829D9* ID_OUI_FROM_DATABASE=GlobalBeiMing technology (Beijing)Co. Ltd OUI:189A67* ID_OUI_FROM_DATABASE=CSE-Servelec Limited OUI:38A5B6* ID_OUI_FROM_DATABASE=SHENZHEN MEGMEET ELECTRICAL CO.,LTD OUI:E43FA2* ID_OUI_FROM_DATABASE=Wuxi DSP Technologies Inc. OUI:00FD4C* ID_OUI_FROM_DATABASE=NEVATEC OUI:E09DB8* ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. OUI:6045BD* ID_OUI_FROM_DATABASE=Microsoft OUI:9C54CA* ID_OUI_FROM_DATABASE=Zhengzhou VCOM Science and Technology Co.,Ltd OUI:388AB7* ID_OUI_FROM_DATABASE=ITC Networks OUI:BCC23A* ID_OUI_FROM_DATABASE=Thomson Video Networks OUI:00BF15* ID_OUI_FROM_DATABASE=Genetec Inc. OUI:20F85E* ID_OUI_FROM_DATABASE=Delta Electronics OUI:68CE4E* ID_OUI_FROM_DATABASE=L-3 Communications Infrared Products OUI:68B6FC* ID_OUI_FROM_DATABASE=Hitron Technologies. Inc OUI:7C160D* ID_OUI_FROM_DATABASE=Saia-Burgess Controls AG OUI:A4D18F* ID_OUI_FROM_DATABASE=Shenzhen Skyee Optical Fiber Communication Technology Ltd. OUI:0C565C* ID_OUI_FROM_DATABASE=HyBroad Vision (Hong Kong) Technology Co Ltd OUI:647C34* ID_OUI_FROM_DATABASE=Ubee Interactive Corp. OUI:649FF7* ID_OUI_FROM_DATABASE=Kone OYj OUI:B86B23* ID_OUI_FROM_DATABASE=Toshiba OUI:4C068A* ID_OUI_FROM_DATABASE=Basler Electric Company OUI:E0A30F* ID_OUI_FROM_DATABASE=Pevco OUI:5C1737* ID_OUI_FROM_DATABASE=I-View Now, LLC. OUI:049C62* ID_OUI_FROM_DATABASE=BMT Medical Technology s.r.o. OUI:C4BA99* ID_OUI_FROM_DATABASE=I+ME Actia Informatik und Mikro-Elektronik GmbH OUI:0C2A69* ID_OUI_FROM_DATABASE=electric imp, incorporated OUI:BC811F* ID_OUI_FROM_DATABASE=Ingate Systems OUI:34E0CF* ID_OUI_FROM_DATABASE=zte corporation OUI:801DAA* ID_OUI_FROM_DATABASE=Avaya Inc OUI:6C40C6* ID_OUI_FROM_DATABASE=Nimbus Data Systems, Inc. OUI:503F56* ID_OUI_FROM_DATABASE=Syncmold Enterprise Corp OUI:D04CC1* ID_OUI_FROM_DATABASE=SINTRONES Technology Corp. OUI:DC9FA4* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:44C39B* ID_OUI_FROM_DATABASE=OOO RUBEZH NPO OUI:58C232* ID_OUI_FROM_DATABASE=NEC Corporation OUI:D8C691* ID_OUI_FROM_DATABASE=Hichan Technology Corp. OUI:8CFDF0* ID_OUI_FROM_DATABASE=QUALCOMM Incorporated OUI:7C02BC* ID_OUI_FROM_DATABASE=Hansung Electronics Co. LTD OUI:1848D8* ID_OUI_FROM_DATABASE=Fastback Networks OUI:C819F7* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:702393* ID_OUI_FROM_DATABASE=fos4X GmbH OUI:C4731E* ID_OUI_FROM_DATABASE=Samsung Eletronics Co., Ltd OUI:D8AFF1* ID_OUI_FROM_DATABASE=Panasonic Appliances Company OUI:58ECE1* ID_OUI_FROM_DATABASE=Newport Corporation OUI:14358B* ID_OUI_FROM_DATABASE=Mediabridge Products, LLC. OUI:34996F* ID_OUI_FROM_DATABASE=VPI Engineering OUI:241064* ID_OUI_FROM_DATABASE=Shenzhen Ecsino Tecnical Co. Ltd OUI:10D1DC* ID_OUI_FROM_DATABASE=INSTAR Deutschland GmbH OUI:844BF5* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:D8160A* ID_OUI_FROM_DATABASE=Nippon Electro-Sensory Devices OUI:58696C* ID_OUI_FROM_DATABASE=Fujian Ruijie Networks co, ltd OUI:F45433* ID_OUI_FROM_DATABASE=Rockwell Automation OUI:EC9327* ID_OUI_FROM_DATABASE=MEMMERT GmbH + Co. KG OUI:1C43EC* ID_OUI_FROM_DATABASE=JAPAN CIRCUIT CO.,LTD OUI:BC28D6* ID_OUI_FROM_DATABASE=Rowley Associates Limited OUI:F05F5A* ID_OUI_FROM_DATABASE=Getriebebau NORD GmbH and Co. KG OUI:009569* ID_OUI_FROM_DATABASE=LSD Science and Technology Co.,Ltd. OUI:34C803* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:5011EB* ID_OUI_FROM_DATABASE=SilverNet Ltd OUI:5CD41B* ID_OUI_FROM_DATABASE=UCZOON Technology Co., LTD OUI:783CE3* ID_OUI_FROM_DATABASE=Kai-EE OUI:0868EA* ID_OUI_FROM_DATABASE=EITO ELECTRONICS CO., LTD. OUI:5C4A26* ID_OUI_FROM_DATABASE=Enguity Technology Corp OUI:289EDF* ID_OUI_FROM_DATABASE=Danfoss Turbocor Compressors, Inc OUI:50053D* ID_OUI_FROM_DATABASE=CyWee Group Ltd OUI:4C64D9* ID_OUI_FROM_DATABASE=Guangdong Leawin Group Co., Ltd OUI:7CB03E* ID_OUI_FROM_DATABASE=OSRAM GmbH OUI:14B1C8* ID_OUI_FROM_DATABASE=InfiniWing, Inc. OUI:C0493D* ID_OUI_FROM_DATABASE=MAITRISE TECHNOLOGIQUE OUI:34A7BA* ID_OUI_FROM_DATABASE=Fischer International Systems Corporation OUI:ACD364* ID_OUI_FROM_DATABASE=ABB SPA, ABB SACE DIV. OUI:38F8B7* ID_OUI_FROM_DATABASE=V2COM PARTICIPACOES S.A. OUI:B48255* ID_OUI_FROM_DATABASE=Research Products Corporation OUI:C84544* ID_OUI_FROM_DATABASE=Shanghai Enlogic Electric Technology Co., Ltd. OUI:2C750F* ID_OUI_FROM_DATABASE=Shanghai Dongzhou-Lawton Communication Technology Co. Ltd. OUI:B40418* ID_OUI_FROM_DATABASE=Smartchip Integrated Inc. OUI:F4EA67* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:D0AEEC* ID_OUI_FROM_DATABASE=Alpha Networks Inc. OUI:3C98BF* ID_OUI_FROM_DATABASE=Quest Controls, Inc. OUI:D05785* ID_OUI_FROM_DATABASE=Pantech Co., Ltd. OUI:045C06* ID_OUI_FROM_DATABASE=Zmodo Technology Corporation OUI:504A5E* ID_OUI_FROM_DATABASE=Masimo Corporation OUI:38BF33* ID_OUI_FROM_DATABASE=NEC CASIO Mobile Communications OUI:A041A7* ID_OUI_FROM_DATABASE=NL Ministry of Defense OUI:342F6E* ID_OUI_FROM_DATABASE=Anywire corporation OUI:E86D6E* ID_OUI_FROM_DATABASE=voestalpine SIGNALING Fareham Ltd. OUI:F8D462* ID_OUI_FROM_DATABASE=Pumatronix Equipamentos Eletronicos Ltda. OUI:5453ED* ID_OUI_FROM_DATABASE=Sony Corporation OUI:940070* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:6C3A84* ID_OUI_FROM_DATABASE=Shenzhen Aero-Startech. Co.Ltd OUI:C0143D* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:442B03* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:781C5A* ID_OUI_FROM_DATABASE=SHARP Corporation OUI:E4C6E6* ID_OUI_FROM_DATABASE=Mophie, LLC OUI:502D1D* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:BCEA2B* ID_OUI_FROM_DATABASE=CityCom GmbH OUI:944444* ID_OUI_FROM_DATABASE=LG Innotek OUI:E4C806* ID_OUI_FROM_DATABASE=Ceiec Electric Technology Inc. OUI:18B591* ID_OUI_FROM_DATABASE=I-Storm OUI:A45630* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:CCFE3C* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:002AAF* ID_OUI_FROM_DATABASE=LARsys-Automation GmbH OUI:60F3DA* ID_OUI_FROM_DATABASE=Logic Way GmbH OUI:A06D09* ID_OUI_FROM_DATABASE=Intelcan Technosystems Inc. OUI:BC1401* ID_OUI_FROM_DATABASE=Hitron Technologies. Inc OUI:68D925* ID_OUI_FROM_DATABASE=ProSys Development Services OUI:B41DEF* ID_OUI_FROM_DATABASE=Internet Laboratories, Inc. OUI:284121* ID_OUI_FROM_DATABASE=OptiSense Network, LLC OUI:5057A8* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:38458C* ID_OUI_FROM_DATABASE=MyCloud Technology corporation OUI:0C9D56* ID_OUI_FROM_DATABASE=Consort Controls Ltd OUI:3CCE73* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:A47C14* ID_OUI_FROM_DATABASE=ChargeStorm AB OUI:F4600D* ID_OUI_FROM_DATABASE=Panoptic Technology, Inc OUI:ACCF23* ID_OUI_FROM_DATABASE=Hi-flying electronics technology Co.,Ltd OUI:C08170* ID_OUI_FROM_DATABASE=Effigis GeoSolutions OUI:78C4AB* ID_OUI_FROM_DATABASE=Shenzhen Runsil Technology Co.,Ltd OUI:709A0B* ID_OUI_FROM_DATABASE=Italian Institute of Technology OUI:240917* ID_OUI_FROM_DATABASE=Devlin Electronics Limited OUI:DC37D2* ID_OUI_FROM_DATABASE=Hunan HKT Electronic Technology Co., Ltd OUI:048B42* ID_OUI_FROM_DATABASE=Skspruce Technology Limited OUI:5076A6* ID_OUI_FROM_DATABASE=Ecil Informatica Ind. Com. Ltda OUI:B431B8* ID_OUI_FROM_DATABASE=Aviwest OUI:241125* ID_OUI_FROM_DATABASE=Hutek Co., Ltd. OUI:0036FE* ID_OUI_FROM_DATABASE=SuperVision OUI:CC187B* ID_OUI_FROM_DATABASE=Manzanita Systems, Inc. OUI:38B12D* ID_OUI_FROM_DATABASE=Sonotronic Nagel GmbH OUI:E006E6* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:8020AF* ID_OUI_FROM_DATABASE=Trade FIDES, a.s. OUI:50D274* ID_OUI_FROM_DATABASE=Steffes Corporation OUI:48D54C* ID_OUI_FROM_DATABASE=Jeda Networks OUI:3497FB* ID_OUI_FROM_DATABASE=ADVANCED RF TECHNOLOGIES INC OUI:C46413* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:143AEA* ID_OUI_FROM_DATABASE=Dynapower Company LLC OUI:9CA134* ID_OUI_FROM_DATABASE=Nike, Inc. OUI:B4D8A9* ID_OUI_FROM_DATABASE=BetterBots OUI:7CC8D7* ID_OUI_FROM_DATABASE=Damalisk OUI:0091FA* ID_OUI_FROM_DATABASE=Synapse Product Development OUI:A05AA4* ID_OUI_FROM_DATABASE=Grand Products Nevada, Inc. OUI:24C0B3* ID_OUI_FROM_DATABASE=RSF OUI:E00B28* ID_OUI_FROM_DATABASE=Inovonics OUI:500B32* ID_OUI_FROM_DATABASE=Foxda Technology Industrial(ShenZhen)Co.,LTD OUI:E8039A* ID_OUI_FROM_DATABASE=Samsung Electronics CO., LTD OUI:302DE8* ID_OUI_FROM_DATABASE=JDA, LLC (JDA Systems) OUI:70CA9B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:2C3F38* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:803F5D* ID_OUI_FROM_DATABASE=Winstars Technology Ltd OUI:780738* ID_OUI_FROM_DATABASE=Z.U.K. Elzab S.A. OUI:640E36* ID_OUI_FROM_DATABASE=TAZTAG OUI:70EE50* ID_OUI_FROM_DATABASE=Netatmo OUI:EC63E5* ID_OUI_FROM_DATABASE=ePBoard Design LLC OUI:60B606* ID_OUI_FROM_DATABASE=Phorus OUI:F4E6D7* ID_OUI_FROM_DATABASE=Solar Power Technologies, Inc. OUI:78DDD6* ID_OUI_FROM_DATABASE=c-scape OUI:984A47* ID_OUI_FROM_DATABASE=CHG Hospital Beds OUI:3C6A7D* ID_OUI_FROM_DATABASE=Niigata Power Systems Co., Ltd. OUI:FC455F* ID_OUI_FROM_DATABASE=JIANGXI SHANSHUI OPTOELECTRONIC TECHNOLOGY CO.,LTD OUI:3C7059* ID_OUI_FROM_DATABASE=MakerBot Industries OUI:F8FE5C* ID_OUI_FROM_DATABASE=Reciprocal Labs Corp OUI:6C9CED* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:94E0D0* ID_OUI_FROM_DATABASE=HealthStream Taiwan Inc. OUI:DCF858* ID_OUI_FROM_DATABASE=Lorent Networks, Inc. OUI:589396* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:A05E6B* ID_OUI_FROM_DATABASE=MELPER Co., Ltd. OUI:30B3A2* ID_OUI_FROM_DATABASE=Shenzhen Heguang Measurement & Control Technology Co.,Ltd OUI:F0007F* ID_OUI_FROM_DATABASE=Janz - Contadores de Energia, SA OUI:CC944A* ID_OUI_FROM_DATABASE=Pfeiffer Vacuum GmbH OUI:0C8525* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:BCE59F* ID_OUI_FROM_DATABASE=WATERWORLD Technology Co.,LTD OUI:1C5C55* ID_OUI_FROM_DATABASE=PRIMA Cinema, Inc OUI:082522* ID_OUI_FROM_DATABASE=ADVANSEE OUI:4C2F9D* ID_OUI_FROM_DATABASE=ICM Controls OUI:E467BA* ID_OUI_FROM_DATABASE=Danish Interpretation Systems A/S OUI:642737* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:BCFE8C* ID_OUI_FROM_DATABASE=Altronic, LLC OUI:24BBC1* ID_OUI_FROM_DATABASE=Absolute Analysis OUI:7CDD11* ID_OUI_FROM_DATABASE=Chongqing MAS SCI&TECH.Co.,Ltd OUI:C43C3C* ID_OUI_FROM_DATABASE=CYBELEC SA OUI:00D632* ID_OUI_FROM_DATABASE=GE Energy OUI:C40ACB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:7463DF* ID_OUI_FROM_DATABASE=VTS GmbH OUI:3828EA* ID_OUI_FROM_DATABASE=Fujian Netcom Technology Co., LTD OUI:2CEE26* ID_OUI_FROM_DATABASE=Petroleum Geo-Services OUI:DC3E51* ID_OUI_FROM_DATABASE=Solberg & Andersen AS OUI:D8B90E* ID_OUI_FROM_DATABASE=Triple Domain Vision Co.,Ltd. OUI:7C4B78* ID_OUI_FROM_DATABASE=Red Sun Synthesis Pte Ltd OUI:28D1AF* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:68BC0C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:2C9EFC* ID_OUI_FROM_DATABASE=CANON INC. OUI:98C845* ID_OUI_FROM_DATABASE=PacketAccess OUI:988217* ID_OUI_FROM_DATABASE=Disruptive Ltd OUI:80FFA8* ID_OUI_FROM_DATABASE=UNIDIS OUI:489BE2* ID_OUI_FROM_DATABASE=SCI Innovations Ltd OUI:B0E50E* ID_OUI_FROM_DATABASE=NRG SYSTEMS INC OUI:4C5FD2* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:E878A1* ID_OUI_FROM_DATABASE=BEOVIEW INTERCOM DOO OUI:3057AC* ID_OUI_FROM_DATABASE=IRLAB LTD. OUI:9002A9* ID_OUI_FROM_DATABASE=ZHEJIANG DAHUA TECHNOLOGY CO.,LTD OUI:28AF0A* ID_OUI_FROM_DATABASE=Sirius XM Radio Inc OUI:2486F4* ID_OUI_FROM_DATABASE=Ctek, Inc. OUI:3CE5B4* ID_OUI_FROM_DATABASE=KIDASEN INDUSTRIA E COMERCIO DE ANTENAS LTDA OUI:A85BF3* ID_OUI_FROM_DATABASE=Audivo GmbH OUI:344F69* ID_OUI_FROM_DATABASE=EKINOPS SAS OUI:2C4401* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:C02973* ID_OUI_FROM_DATABASE=Audyssey Laboratories Inc. OUI:30168D* ID_OUI_FROM_DATABASE=ProLon OUI:B451F9* ID_OUI_FROM_DATABASE=NB Software OUI:30688C* ID_OUI_FROM_DATABASE=Reach Technology Inc. OUI:88F488* ID_OUI_FROM_DATABASE=cellon communications technology(shenzhen)Co.,Ltd. OUI:0041B4* ID_OUI_FROM_DATABASE=Wuxi Zhongxing Optoelectronics Technology Co.,Ltd. OUI:0007AB* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:D453AF* ID_OUI_FROM_DATABASE=VIGO System S.A. OUI:1CE192* ID_OUI_FROM_DATABASE=Qisda Corporation OUI:20C8B3* ID_OUI_FROM_DATABASE=SHENZHEN BUL-TECH CO.,LTD. OUI:60D819* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:945103* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:58B0D4* ID_OUI_FROM_DATABASE=ZuniData Systems Inc. OUI:64557F* ID_OUI_FROM_DATABASE=NSFOCUS Information Technology Co., Ltd. OUI:406AAB* ID_OUI_FROM_DATABASE=RIM OUI:248707* ID_OUI_FROM_DATABASE=SEnergy Corporation OUI:EC3F05* ID_OUI_FROM_DATABASE=Institute 706, The Second Academy China Aerospace Science & Industry Corp OUI:C4C19F* ID_OUI_FROM_DATABASE=National Oilwell Varco Instrumentation, Monitoring, and Optimization (NOV IMO) OUI:68CD0F* ID_OUI_FROM_DATABASE=U Tek Company Limited OUI:D4CEB8* ID_OUI_FROM_DATABASE=Enatel LTD OUI:ECF236* ID_OUI_FROM_DATABASE=NEOMONTANA ELECTRONICS OUI:E4A5EF* ID_OUI_FROM_DATABASE=TRON LINK ELECTRONICS CO., LTD. OUI:AC4AFE* ID_OUI_FROM_DATABASE=Hisense Broadband Multimedia Technology Co.,Ltd. OUI:2C1EEA* ID_OUI_FROM_DATABASE=AERODEV OUI:FC6C31* ID_OUI_FROM_DATABASE=LXinstruments GmbH OUI:3C6F45* ID_OUI_FROM_DATABASE=Fiberpro Inc. OUI:B4FC75* ID_OUI_FROM_DATABASE=SEMA Electronics(HK) CO.,LTD OUI:5C16C7* ID_OUI_FROM_DATABASE=Big Switch Networks OUI:B0BF99* ID_OUI_FROM_DATABASE=WIZITDONGDO OUI:147DB3* ID_OUI_FROM_DATABASE=JOA TELECOM.CO.,LTD OUI:3CD16E* ID_OUI_FROM_DATABASE=Telepower Communication Co., Ltd OUI:00077D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:D0176A* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:1045BE* ID_OUI_FROM_DATABASE=Norphonic AS OUI:A0E295* ID_OUI_FROM_DATABASE=DAT System Co.,Ltd OUI:40F14C* ID_OUI_FROM_DATABASE=ISE Europe SPRL OUI:98293F* ID_OUI_FROM_DATABASE=Fujian Start Computer Equipment Co.,Ltd OUI:70D4F2* ID_OUI_FROM_DATABASE=RIM OUI:9067F3* ID_OUI_FROM_DATABASE=Alcatel Lucent OUI:64D912* ID_OUI_FROM_DATABASE=Solidica, Inc. OUI:8C5CA1* ID_OUI_FROM_DATABASE=d-broad,INC OUI:C8F981* ID_OUI_FROM_DATABASE=Seneca s.r.l. OUI:8C7712* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:703187* ID_OUI_FROM_DATABASE=ACX GmbH OUI:14307A* ID_OUI_FROM_DATABASE=Avermetrics OUI:8C7EB3* ID_OUI_FROM_DATABASE=Lytro, Inc. OUI:587675* ID_OUI_FROM_DATABASE=Beijing ECHO Technologies Co.,Ltd OUI:78EF4C* ID_OUI_FROM_DATABASE=Unetconvergence Co., Ltd. OUI:E8DA96* ID_OUI_FROM_DATABASE=Zhuhai Tianrui Electrical Power Tech. Co., Ltd. OUI:6CA780* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:04888C* ID_OUI_FROM_DATABASE=Eifelwerk Butler Systeme GmbH OUI:1013EE* ID_OUI_FROM_DATABASE=Justec International Technology INC. OUI:704642* ID_OUI_FROM_DATABASE=CHYNG HONG ELECTRONIC CO., LTD. OUI:78BEB6* ID_OUI_FROM_DATABASE=Enhanced Vision OUI:ECEA03* ID_OUI_FROM_DATABASE=DARFON LIGHTING CORP OUI:C8903E* ID_OUI_FROM_DATABASE=Pakton Technologies OUI:7465D1* ID_OUI_FROM_DATABASE=Atlinks OUI:301A28* ID_OUI_FROM_DATABASE=Mako Networks Ltd OUI:D4945A* ID_OUI_FROM_DATABASE=COSMO CO., LTD OUI:5CF207* ID_OUI_FROM_DATABASE=Speco Technologies OUI:B01B7C* ID_OUI_FROM_DATABASE=Ontrol A.S. OUI:D47B75* ID_OUI_FROM_DATABASE=HARTING Electronics GmbH OUI:70E843* ID_OUI_FROM_DATABASE=Beijing C&W Optical Communication Technology Co.,Ltd. OUI:08ACA5* ID_OUI_FROM_DATABASE=Benu Video, Inc. OUI:D89DB9* ID_OUI_FROM_DATABASE=eMegatech International Corp. OUI:405A9B* ID_OUI_FROM_DATABASE=ANOVO OUI:ACCA54* ID_OUI_FROM_DATABASE=Telldus Technologies AB OUI:CC1EFF* ID_OUI_FROM_DATABASE=Metrological Group BV OUI:941673* ID_OUI_FROM_DATABASE=Point Core SARL OUI:6C5D63* ID_OUI_FROM_DATABASE=ShenZhen Rapoo Technology Co., Ltd. OUI:E4D71D* ID_OUI_FROM_DATABASE=Oraya Therapeutics OUI:C8FE30* ID_OUI_FROM_DATABASE=Bejing DAYO Mobile Communication Technology Ltd. OUI:64B64A* ID_OUI_FROM_DATABASE=ViVOtech, Inc. OUI:DCA7D9* ID_OUI_FROM_DATABASE=Compressor Controls Corp OUI:C455A6* ID_OUI_FROM_DATABASE=Cadac Holdings Ltd OUI:BCBBC9* ID_OUI_FROM_DATABASE=Kellendonk Elektronik GmbH OUI:781DFD* ID_OUI_FROM_DATABASE=Jabil Inc OUI:103711* ID_OUI_FROM_DATABASE=Simlink AS OUI:601199* ID_OUI_FROM_DATABASE=Siama Systems Inc OUI:300B9C* ID_OUI_FROM_DATABASE=Delta Mobile Systems, Inc. OUI:90EA60* ID_OUI_FROM_DATABASE=SPI Lasers Ltd OUI:D46F42* ID_OUI_FROM_DATABASE=WAXESS USA Inc OUI:B0A72A* ID_OUI_FROM_DATABASE=Ensemble Designs, Inc. OUI:50795B* ID_OUI_FROM_DATABASE=Interexport Telecomunicaciones S.A. OUI:E8C229* ID_OUI_FROM_DATABASE=H-Displays (MSC) Bhd OUI:3C6200* ID_OUI_FROM_DATABASE=Samsung electronics CO., LTD OUI:B0BDA1* ID_OUI_FROM_DATABASE=ZAKLAD ELEKTRONICZNY SIMS OUI:8C4435* ID_OUI_FROM_DATABASE=Shanghai BroadMobi Communication Technology Co., Ltd. OUI:24B8D2* ID_OUI_FROM_DATABASE=Opzoon Technology Co.,Ltd. OUI:24CBE7* ID_OUI_FROM_DATABASE=MYK, Inc. OUI:88BFD5* ID_OUI_FROM_DATABASE=Simple Audio Ltd OUI:948B03* ID_OUI_FROM_DATABASE=EAGET Innovation and Technology Co., Ltd. OUI:802DE1* ID_OUI_FROM_DATABASE=Solarbridge Technologies OUI:F081AF* ID_OUI_FROM_DATABASE=IRZ AUTOMATION TECHNOLOGIES LTD OUI:14EB33* ID_OUI_FROM_DATABASE=BSMediasoft Co., Ltd. OUI:AC8674* ID_OUI_FROM_DATABASE=Open Mesh, Inc. OUI:14A9E3* ID_OUI_FROM_DATABASE=MST CORPORATION OUI:589835* ID_OUI_FROM_DATABASE=Technicolor OUI:50D6D7* ID_OUI_FROM_DATABASE=Takahata Precision OUI:B4A5A9* ID_OUI_FROM_DATABASE=MODI GmbH OUI:D09B05* ID_OUI_FROM_DATABASE=Emtronix OUI:98EC65* ID_OUI_FROM_DATABASE=Cosesy ApS OUI:900917* ID_OUI_FROM_DATABASE=Far-sighted mobile OUI:88F077* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:AC4723* ID_OUI_FROM_DATABASE=Genelec OUI:20B7C0* ID_OUI_FROM_DATABASE=OMICRON electronics GmbH OUI:D42C3D* ID_OUI_FROM_DATABASE=Sky Light Digital Limited OUI:806CBC* ID_OUI_FROM_DATABASE=NET New Electronic Technology GmbH OUI:1C184A* ID_OUI_FROM_DATABASE=ShenZhen RicherLink Technologies Co.,LTD OUI:2013E0* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:04E662* ID_OUI_FROM_DATABASE=Acroname Inc. OUI:F0BF97* ID_OUI_FROM_DATABASE=Sony Corporation OUI:C44AD0* ID_OUI_FROM_DATABASE=FIREFLIES SYSTEMS OUI:88E0A0* ID_OUI_FROM_DATABASE=Shenzhen VisionSTOR Technologies Co., Ltd OUI:6879ED* ID_OUI_FROM_DATABASE=SHARP Corporation OUI:9CC0D2* ID_OUI_FROM_DATABASE=Conductix-Wampfler GmbH OUI:408BF6* ID_OUI_FROM_DATABASE=Shenzhen TCL New Technology Co; Ltd. OUI:447E95* ID_OUI_FROM_DATABASE=Alpha and Omega, Inc OUI:E8B748* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:DC16A2* ID_OUI_FROM_DATABASE=Medtronic Diabetes OUI:78CA04* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:2C8BF2* ID_OUI_FROM_DATABASE=Hitachi Metals America Ltd OUI:58F98E* ID_OUI_FROM_DATABASE=SECUDOS GmbH OUI:2826A6* ID_OUI_FROM_DATABASE=PBR electronics GmbH OUI:CC7669* ID_OUI_FROM_DATABASE=SEETECH OUI:E437D7* ID_OUI_FROM_DATABASE=HENRI DEPAEPE S.A.S. OUI:582F42* ID_OUI_FROM_DATABASE=Universal Electric Corporation OUI:AC20AA* ID_OUI_FROM_DATABASE=DMATEK Co., Ltd. OUI:E0A1D7* ID_OUI_FROM_DATABASE=SFR OUI:28852D* ID_OUI_FROM_DATABASE=Touch Networks OUI:F02A61* ID_OUI_FROM_DATABASE=Waldo Networks, Inc. OUI:B8415F* ID_OUI_FROM_DATABASE=ASP AG OUI:2CB69D* ID_OUI_FROM_DATABASE=RED Digital Cinema OUI:988E34* ID_OUI_FROM_DATABASE=ZHEJIANG BOXSAM ELECTRONIC CO.,LTD OUI:D44C24* ID_OUI_FROM_DATABASE=Vuppalamritha Magnetic Components LTD OUI:4CB4EA* ID_OUI_FROM_DATABASE=HRD (S) PTE., LTD. OUI:34BDF9* ID_OUI_FROM_DATABASE=Shanghai WDK Industrial Co.,Ltd. OUI:74CE56* ID_OUI_FROM_DATABASE=Packet Force Technology Limited Company OUI:A89B10* ID_OUI_FROM_DATABASE=inMotion Ltd. OUI:888C19* ID_OUI_FROM_DATABASE=Brady Corp Asia Pacific Ltd OUI:747DB6* ID_OUI_FROM_DATABASE=Aliwei Communications, Inc OUI:B41489* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:AC6F4F* ID_OUI_FROM_DATABASE=Enspert Inc OUI:8886A0* ID_OUI_FROM_DATABASE=Simton Technologies, Ltd. OUI:F0C88C* ID_OUI_FROM_DATABASE=LeddarTech Inc. OUI:68EBC5* ID_OUI_FROM_DATABASE=Angstrem Telecom OUI:448C52* ID_OUI_FROM_DATABASE=KTIS CO., Ltd OUI:686359* ID_OUI_FROM_DATABASE=Advanced Digital Broadcast SA OUI:B8E779* ID_OUI_FROM_DATABASE=9Solutions Oy OUI:4018D7* ID_OUI_FROM_DATABASE=Smartronix, Inc. OUI:18922C* ID_OUI_FROM_DATABASE=Virtual Instruments OUI:F80F84* ID_OUI_FROM_DATABASE=Natural Security SAS OUI:FCA13E* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:BC4760* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:EC9ECD* ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies OUI:303955* ID_OUI_FROM_DATABASE=Shenzhen Jinhengjia Electronic Co., Ltd. OUI:FC5B24* ID_OUI_FROM_DATABASE=Weibel Scientific A/S OUI:34B571* ID_OUI_FROM_DATABASE=PLDS OUI:A862A2* ID_OUI_FROM_DATABASE=JIWUMEDIA CO., LTD. OUI:984E97* ID_OUI_FROM_DATABASE=Starlight Marketing (H. K.) Ltd. OUI:E4E0C5* ID_OUI_FROM_DATABASE=Samsung Electronics Co., LTD OUI:7C6ADB* ID_OUI_FROM_DATABASE=SafeTone Technology Co.,Ltd OUI:EC986C* ID_OUI_FROM_DATABASE=Lufft Mess- und Regeltechnik GmbH OUI:B0518E* ID_OUI_FROM_DATABASE=Holl technology CO.Ltd. OUI:DCDECA* ID_OUI_FROM_DATABASE=Akyllor OUI:A071A9* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:8065E9* ID_OUI_FROM_DATABASE=BenQ Corporation OUI:845DD7* ID_OUI_FROM_DATABASE=Shenzhen Netcom Electronics Co.,Ltd OUI:447DA5* ID_OUI_FROM_DATABASE=VTION INFORMATION TECHNOLOGY (FUJIAN) CO.,LTD OUI:0CCDD3* ID_OUI_FROM_DATABASE=EASTRIVER TECHNOLOGY CO., LTD. OUI:B8E589* ID_OUI_FROM_DATABASE=Payter BV OUI:C89C1D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:503DE5* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:801440* ID_OUI_FROM_DATABASE=Sunlit System Technology Corp OUI:948D50* ID_OUI_FROM_DATABASE=Beamex Oy Ab OUI:94E226* ID_OUI_FROM_DATABASE=D. ORtiz Consulting, LLC OUI:74A722* ID_OUI_FROM_DATABASE=LG Electronics OUI:78D6F0* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics OUI:E8E732* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:386E21* ID_OUI_FROM_DATABASE=Wasion Group Ltd. OUI:D8C99D* ID_OUI_FROM_DATABASE=EA DISPLAY LIMITED OUI:CCFC6D* ID_OUI_FROM_DATABASE=RIZ TRANSMITTERS OUI:AC80D6* ID_OUI_FROM_DATABASE=Hexatronic AB OUI:9CF938* ID_OUI_FROM_DATABASE=AREVA NP GmbH OUI:500E6D* ID_OUI_FROM_DATABASE=TrafficCast International OUI:1CFEA7* ID_OUI_FROM_DATABASE=IDentytech Solutins Ltd. OUI:D0B53D* ID_OUI_FROM_DATABASE=SEPRO ROBOTIQUE OUI:A0DE05* ID_OUI_FROM_DATABASE=JSC Irbis-T OUI:8895B9* ID_OUI_FROM_DATABASE=Unified Packet Systems Crop OUI:78593E* ID_OUI_FROM_DATABASE=RAFI GmbH & Co.KG OUI:684352* ID_OUI_FROM_DATABASE=Bhuu Limited OUI:3CC0C6* ID_OUI_FROM_DATABASE=d&b audiotechnik GmbH OUI:F8DAF4* ID_OUI_FROM_DATABASE=Taishan Online Technology Co., Ltd. OUI:D8E3AE* ID_OUI_FROM_DATABASE=CIRTEC MEDICAL SYSTEMS OUI:A83944* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:FC1FC0* ID_OUI_FROM_DATABASE=EURECAM OUI:4891F6* ID_OUI_FROM_DATABASE=Shenzhen Reach software technology CO.,LTD OUI:EC14F6* ID_OUI_FROM_DATABASE=BioControl AS OUI:B8D06F* ID_OUI_FROM_DATABASE=GUANGZHOU HKUST FOK YING TUNG RESEARCH INSTITUTE OUI:B4C44E* ID_OUI_FROM_DATABASE=VXL eTech Pvt Ltd OUI:F0933A* ID_OUI_FROM_DATABASE=NxtConect OUI:6052D0* ID_OUI_FROM_DATABASE=FACTS Engineering OUI:8C278A* ID_OUI_FROM_DATABASE=Vocollect Inc OUI:FCAF6A* ID_OUI_FROM_DATABASE=Qulsar Inc OUI:ECE555* ID_OUI_FROM_DATABASE=Hirschmann Automation OUI:DCD0F7* ID_OUI_FROM_DATABASE=Bentek Systems Ltd. OUI:D0574C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:8818AE* ID_OUI_FROM_DATABASE=Tamron Co., Ltd OUI:20D607* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:58DB8D* ID_OUI_FROM_DATABASE=Fast Co., Ltd. OUI:18EF63* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:CCCE40* ID_OUI_FROM_DATABASE=Janteq Corp OUI:8C4DEA* ID_OUI_FROM_DATABASE=Cerio Corporation OUI:ECFAAA* ID_OUI_FROM_DATABASE=The IMS Company OUI:CC55AD* ID_OUI_FROM_DATABASE=RIM OUI:F0F7B3* ID_OUI_FROM_DATABASE=Phorm OUI:E8757F* ID_OUI_FROM_DATABASE=FIRS Technologies(Shenzhen) Co., Ltd OUI:C83EA7* ID_OUI_FROM_DATABASE=KUNBUS GmbH OUI:A8D3C8* ID_OUI_FROM_DATABASE=Wachendorff Elektronik GmbH & Co. KG OUI:E0CF2D* ID_OUI_FROM_DATABASE=Gemintek Corporation OUI:68BDAB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:9CADEF* ID_OUI_FROM_DATABASE=Obihai Technology, Inc. OUI:D08999* ID_OUI_FROM_DATABASE=APCON, Inc. OUI:4454C0* ID_OUI_FROM_DATABASE=Thompson Aerospace OUI:B4A4E3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:90903C* ID_OUI_FROM_DATABASE=TRISON TECHNOLOGY CORPORATION OUI:94DD3F* ID_OUI_FROM_DATABASE=A+V Link Technologies, Corp. OUI:C8EE08* ID_OUI_FROM_DATABASE=TANGTOP TECHNOLOGY CO.,LTD OUI:7472F2* ID_OUI_FROM_DATABASE=Chipsip Technology Co., Ltd. OUI:C0CB38* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:5CD998* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:D46CDA* ID_OUI_FROM_DATABASE=CSM GmbH OUI:60EB69* ID_OUI_FROM_DATABASE=Quanta computer Inc. OUI:C4F464* ID_OUI_FROM_DATABASE=Spica international OUI:74911A* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:544A05* ID_OUI_FROM_DATABASE=wenglor sensoric gmbh OUI:5CCA32* ID_OUI_FROM_DATABASE=Theben AG OUI:84C7A9* ID_OUI_FROM_DATABASE=C3PO S.A. OUI:F8AC6D* ID_OUI_FROM_DATABASE=Deltenna Ltd OUI:641084* ID_OUI_FROM_DATABASE=HEXIUM Technical Development Co., Ltd. OUI:C416FA* ID_OUI_FROM_DATABASE=Prysm Inc OUI:E0C286* ID_OUI_FROM_DATABASE=Aisai Communication Technology Co., Ltd. OUI:D84B2A* ID_OUI_FROM_DATABASE=Cognitas Technologies, Inc. OUI:684B88* ID_OUI_FROM_DATABASE=Galtronics Telemetry Inc. OUI:842914* ID_OUI_FROM_DATABASE=EMPORIA TELECOM Produktions- und VertriebsgesmbH & Co KG OUI:4C8B55* ID_OUI_FROM_DATABASE=Grupo Digicon OUI:04A3F3* ID_OUI_FROM_DATABASE=Emicon OUI:F866F2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:7C55E7* ID_OUI_FROM_DATABASE=YSI, Inc. OUI:C02BFC* ID_OUI_FROM_DATABASE=iNES. applied informatics GmbH OUI:AC34CB* ID_OUI_FROM_DATABASE=Shanhai GBCOM Communication Technology Co. Ltd OUI:D4A928* ID_OUI_FROM_DATABASE=GreenWave Reality Inc OUI:9CFFBE* ID_OUI_FROM_DATABASE=OTSL Inc. OUI:2CD1DA* ID_OUI_FROM_DATABASE=Sanjole, Inc. OUI:100E2B* ID_OUI_FROM_DATABASE=NEC CASIO Mobile Communications OUI:445EF3* ID_OUI_FROM_DATABASE=Tonalite Holding B.V. OUI:100C24* ID_OUI_FROM_DATABASE=pomdevices, LLC OUI:58F6BF* ID_OUI_FROM_DATABASE=Kyoto University OUI:B407F9* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS OUI:7CED8D* ID_OUI_FROM_DATABASE=Microsoft OUI:1880F5* ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd OUI:54FDBF* ID_OUI_FROM_DATABASE=Scheidt & Bachmann GmbH OUI:B40EDC* ID_OUI_FROM_DATABASE=LG-Ericsson Co.,Ltd. OUI:A4D1D1* ID_OUI_FROM_DATABASE=ECOtality North America OUI:C8D5FE* ID_OUI_FROM_DATABASE=Shenzhen Zowee Technology Co., Ltd OUI:C49313* ID_OUI_FROM_DATABASE=100fio networks technology llc OUI:A4A80F* ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd. OUI:B8921D* ID_OUI_FROM_DATABASE=BG T&A OUI:48FCB8* ID_OUI_FROM_DATABASE=Woodstream Corporation OUI:548922* ID_OUI_FROM_DATABASE=Zelfy Inc OUI:F8C091* ID_OUI_FROM_DATABASE=Highgates Technology OUI:6C5CDE* ID_OUI_FROM_DATABASE=SunReports, Inc. OUI:241F2C* ID_OUI_FROM_DATABASE=Calsys, Inc. OUI:284846* ID_OUI_FROM_DATABASE=GridCentric Inc. OUI:58B9E1* ID_OUI_FROM_DATABASE=Crystalfontz America, Inc. OUI:646707* ID_OUI_FROM_DATABASE=Beijing Omnific Technology, Ltd. OUI:D4000D* ID_OUI_FROM_DATABASE=Phoenix Broadband Technologies, LLC. OUI:E87AF3* ID_OUI_FROM_DATABASE=S5 Tech S.r.l. OUI:40C7C9* ID_OUI_FROM_DATABASE=Naviit Inc. OUI:A0A763* ID_OUI_FROM_DATABASE=Polytron Vertrieb GmbH OUI:D496DF* ID_OUI_FROM_DATABASE=SUNGJIN C&T CO.,LTD OUI:D07DE5* ID_OUI_FROM_DATABASE=Forward Pay Systems, Inc. OUI:7CEF18* ID_OUI_FROM_DATABASE=Creative Product Design Pty. Ltd. OUI:FCD4F6* ID_OUI_FROM_DATABASE=Messana Air.Ray Conditioning s.r.l. OUI:0CD696* ID_OUI_FROM_DATABASE=Amimon Ltd OUI:B43741* ID_OUI_FROM_DATABASE=Consert, Inc. OUI:F8FB2F* ID_OUI_FROM_DATABASE=Santur Corporation OUI:2CCD43* ID_OUI_FROM_DATABASE=Summit Technology Group OUI:6C8D65* ID_OUI_FROM_DATABASE=Wireless Glue Networks, Inc. OUI:CCFCB1* ID_OUI_FROM_DATABASE=Wireless Technology, Inc. OUI:CC5C75* ID_OUI_FROM_DATABASE=Weightech Com. Imp. Exp. Equip. Pesagem Ltda OUI:A098ED* ID_OUI_FROM_DATABASE=Shandong Intelligent Optical Communication Development Co., Ltd. OUI:34C69A* ID_OUI_FROM_DATABASE=Enecsys Ltd OUI:502A8B* ID_OUI_FROM_DATABASE=Telekom Research and Development Sdn Bhd OUI:F88DEF* ID_OUI_FROM_DATABASE=Tenebraex OUI:EC43E6* ID_OUI_FROM_DATABASE=AWCER Ltd. OUI:F0EC39* ID_OUI_FROM_DATABASE=Essec OUI:5849BA* ID_OUI_FROM_DATABASE=Chitai Electronic Corp. OUI:181714* ID_OUI_FROM_DATABASE=DAEWOOIS OUI:80B289* ID_OUI_FROM_DATABASE=Forworld Electronics Ltd. OUI:14A62C* ID_OUI_FROM_DATABASE=S.M. Dezac S.A. OUI:C80AA9* ID_OUI_FROM_DATABASE=Quanta Computer Inc. OUI:A8F470* ID_OUI_FROM_DATABASE=Fujian Newland Communication Science Technologies Co.,Ltd. OUI:DC1D9F* ID_OUI_FROM_DATABASE=U & B tech OUI:081651* ID_OUI_FROM_DATABASE=SHENZHEN SEA STAR TECHNOLOGY CO.,LTD OUI:DC49C9* ID_OUI_FROM_DATABASE=CASCO SIGNAL LTD OUI:B09134* ID_OUI_FROM_DATABASE=Taleo OUI:A863DF* ID_OUI_FROM_DATABASE=DISPLAIRE CORPORATION OUI:104369* ID_OUI_FROM_DATABASE=Soundmax Electronic Limited OUI:C06C0F* ID_OUI_FROM_DATABASE=Dobbs Stanford OUI:5475D0* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:BC6A16* ID_OUI_FROM_DATABASE=tdvine OUI:C8EF2E* ID_OUI_FROM_DATABASE=Beijing Gefei Tech. Co., Ltd OUI:98DCD9* ID_OUI_FROM_DATABASE=UNITEC Co., Ltd. OUI:30525A* ID_OUI_FROM_DATABASE=NST Co., LTD OUI:6089B7* ID_OUI_FROM_DATABASE=KAEL MÜHENDİSLİK ELEKTRONİK TİCARET SANAYİ LİMİTED ŞİRKETİ OUI:2CA780* ID_OUI_FROM_DATABASE=True Technologies Inc. OUI:545FA9* ID_OUI_FROM_DATABASE=Teracom Limited OUI:ECC882* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:A0B9ED* ID_OUI_FROM_DATABASE=Skytap OUI:502DF4* ID_OUI_FROM_DATABASE=Phytec Messtechnik GmbH OUI:38E8DF* ID_OUI_FROM_DATABASE=b gmbh medien + datenbanken OUI:10189E* ID_OUI_FROM_DATABASE=Elmo Motion Control OUI:88FD15* ID_OUI_FROM_DATABASE=LINEEYE CO., LTD OUI:10445A* ID_OUI_FROM_DATABASE=Shaanxi Hitech Electronic Co., LTD OUI:60B3C4* ID_OUI_FROM_DATABASE=Elber Srl OUI:04C880* ID_OUI_FROM_DATABASE=Samtec Inc OUI:884B39* ID_OUI_FROM_DATABASE=Siemens AG, Healthcare Sector OUI:44C233* ID_OUI_FROM_DATABASE=Guangzhou Comet Technology Development Co.Ltd OUI:B482FE* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:307C30* ID_OUI_FROM_DATABASE=RIM OUI:BC4E3C* ID_OUI_FROM_DATABASE=CORE STAFF CO., LTD. OUI:80BAAC* ID_OUI_FROM_DATABASE=TeleAdapt Ltd OUI:FC4463* ID_OUI_FROM_DATABASE=Universal Audio, Inc OUI:F06853* ID_OUI_FROM_DATABASE=Integrated Corporation OUI:10E6AE* ID_OUI_FROM_DATABASE=Source Technologies, LLC OUI:A4ADB8* ID_OUI_FROM_DATABASE=Vitec Group, Camera Dynamics Ltd OUI:90A2DA* ID_OUI_FROM_DATABASE=GHEO SA OUI:C41ECE* ID_OUI_FROM_DATABASE=HMI Sources Ltd. OUI:BCD5B6* ID_OUI_FROM_DATABASE=d2d technologies OUI:1C8F8A* ID_OUI_FROM_DATABASE=Phase Motion Control SpA OUI:A4B1EE* ID_OUI_FROM_DATABASE=H. ZANDER GmbH & Co. KG OUI:486FD2* ID_OUI_FROM_DATABASE=StorSimple Inc OUI:D4F143* ID_OUI_FROM_DATABASE=IPROAD.,Inc OUI:CC5459* ID_OUI_FROM_DATABASE=OnTime Networks AS OUI:3CB17F* ID_OUI_FROM_DATABASE=Wattwatchers Pty Ld OUI:00DB45* ID_OUI_FROM_DATABASE=THAMWAY CO.,LTD. OUI:A0231B* ID_OUI_FROM_DATABASE=TeleComp R&D Corp. OUI:94C4E9* ID_OUI_FROM_DATABASE=PowerLayer Microsystems HongKong Limited OUI:8843E1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B4ED19* ID_OUI_FROM_DATABASE=Pie Digital, Inc. OUI:888717* ID_OUI_FROM_DATABASE=CANON INC. OUI:E0271A* ID_OUI_FROM_DATABASE=TTC Next-generation Home Network System WG OUI:84C727* ID_OUI_FROM_DATABASE=Gnodal Ltd OUI:E4AB46* ID_OUI_FROM_DATABASE=UAB Selteka OUI:D479C3* ID_OUI_FROM_DATABASE=Cameronet GmbH & Co. KG OUI:945B7E* ID_OUI_FROM_DATABASE=TRILOBIT LTDA. OUI:E85B5B* ID_OUI_FROM_DATABASE=LG ELECTRONICS INC OUI:20D906* ID_OUI_FROM_DATABASE=Iota, Inc. OUI:404022* ID_OUI_FROM_DATABASE=ZIV OUI:70F395* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. OUI:74F726* ID_OUI_FROM_DATABASE=Neuron Robotics OUI:18FC9F* ID_OUI_FROM_DATABASE=Changhe Electronics Co., Ltd. OUI:A438FC* ID_OUI_FROM_DATABASE=Plastic Logic OUI:601D0F* ID_OUI_FROM_DATABASE=Midnite Solar OUI:50A6E3* ID_OUI_FROM_DATABASE=David Clark Company OUI:549A16* ID_OUI_FROM_DATABASE=Uzushio Electric Co.,Ltd. OUI:4001C6* ID_OUI_FROM_DATABASE=3COM EUROPE LTD OUI:608D17* ID_OUI_FROM_DATABASE=Sentrus Government Systems Division, Inc OUI:24BF74* ID_OUI_FROM_DATABASE=Private OUI:80912A* ID_OUI_FROM_DATABASE=Lih Rong electronic Enterprise Co., Ltd. OUI:8038FD* ID_OUI_FROM_DATABASE=LeapFrog Enterprises, Inc. OUI:7072CF* ID_OUI_FROM_DATABASE=EdgeCore Networks OUI:803B9A* ID_OUI_FROM_DATABASE=ghe-ces electronic ag OUI:9CCD82* ID_OUI_FROM_DATABASE=CHENG UEI PRECISION INDUSTRY CO.,LTD OUI:C8AACC* ID_OUI_FROM_DATABASE=Private OUI:003D41* ID_OUI_FROM_DATABASE=Hatteland Computer AS OUI:087618* ID_OUI_FROM_DATABASE=ViE Technologies Sdn. Bhd. OUI:A4AD00* ID_OUI_FROM_DATABASE=Ragsdale Technology OUI:2C1984* ID_OUI_FROM_DATABASE=IDN Telecom, Inc. OUI:3863F6* ID_OUI_FROM_DATABASE=3NOD MULTIMEDIA(SHENZHEN)CO.,LTD OUI:DCE2AC* ID_OUI_FROM_DATABASE=Lumens Digital Optics Inc. OUI:98D88C* ID_OUI_FROM_DATABASE=Nortel Networks OUI:C8873B* ID_OUI_FROM_DATABASE=Net Optics OUI:6CBEE9* ID_OUI_FROM_DATABASE=Alcatel-Lucent-IPD OUI:B0E97E* ID_OUI_FROM_DATABASE=Advanced Micro Peripherals OUI:D44CA7* ID_OUI_FROM_DATABASE=Informtekhnika & Communication, LLC OUI:202CB7* ID_OUI_FROM_DATABASE=Kong Yue Electronics & Information Industry (Xinhui) Ltd. OUI:68CC9C* ID_OUI_FROM_DATABASE=Mine Site Technologies OUI:04B466* ID_OUI_FROM_DATABASE=BSP Co., Ltd. OUI:E41F13* ID_OUI_FROM_DATABASE=IBM Corp OUI:00271B* ID_OUI_FROM_DATABASE=Alec Sicherheitssysteme GmbH OUI:002718* ID_OUI_FROM_DATABASE=Suzhou NEW SEAUNION Video Technology Co.,Ltd OUI:002713* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. OUI:00270C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00270B* ID_OUI_FROM_DATABASE=Adura Technologies OUI:002705* ID_OUI_FROM_DATABASE=Sectronic OUI:002706* ID_OUI_FROM_DATABASE=YOISYS OUI:0026F9* ID_OUI_FROM_DATABASE=S.E.M. srl OUI:0026F3* ID_OUI_FROM_DATABASE=SMC Networks OUI:688540* ID_OUI_FROM_DATABASE=IGI Mobile, Inc. OUI:6465C0* ID_OUI_FROM_DATABASE=Nuvon, Inc OUI:F0DE71* ID_OUI_FROM_DATABASE=Shanghai EDO Technologies Co.,Ltd. OUI:A00798* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:28FBD3* ID_OUI_FROM_DATABASE=Ragentek Technology Group OUI:7C1EB3* ID_OUI_FROM_DATABASE=2N TELEKOMUNIKACE a.s. OUI:146E0A* ID_OUI_FROM_DATABASE=Private OUI:1045F8* ID_OUI_FROM_DATABASE=LNT-Automation GmbH OUI:644F74* ID_OUI_FROM_DATABASE=LENUS Co., Ltd. OUI:787F62* ID_OUI_FROM_DATABASE=GiK mbH OUI:D4AAFF* ID_OUI_FROM_DATABASE=MICRO WORLD OUI:C4FCE4* ID_OUI_FROM_DATABASE=DishTV NZ Ltd OUI:0CD7C2* ID_OUI_FROM_DATABASE=Axium Technologies, Inc. OUI:40F52E* ID_OUI_FROM_DATABASE=Leica Microsystems (Schweiz) AG OUI:C02250* ID_OUI_FROM_DATABASE=Private OUI:64BC11* ID_OUI_FROM_DATABASE=CombiQ AB OUI:4097D1* ID_OUI_FROM_DATABASE=BK Electronics cc OUI:68AAD2* ID_OUI_FROM_DATABASE=DATECS LTD., OUI:0026EC* ID_OUI_FROM_DATABASE=Legrand Home Systems, Inc OUI:0026E6* ID_OUI_FROM_DATABASE=Visionhitech Co., Ltd. OUI:0026E0* ID_OUI_FROM_DATABASE=ASITEQ OUI:0026DA* ID_OUI_FROM_DATABASE=Universal Media Corporation /Slovakia/ s.r.o. OUI:0026D3* ID_OUI_FROM_DATABASE=Zeno Information System OUI:0026D4* ID_OUI_FROM_DATABASE=IRCA SpA OUI:0026CD* ID_OUI_FROM_DATABASE=PurpleComm, Inc. OUI:10880F* ID_OUI_FROM_DATABASE=Daruma Telecomunicações e Informática S.A. OUI:4C4B68* ID_OUI_FROM_DATABASE=Mobile Device, Inc. OUI:94BA31* ID_OUI_FROM_DATABASE=Visiontec da Amazônia Ltda. OUI:F45FF7* ID_OUI_FROM_DATABASE=DQ Technology Inc. OUI:60F13D* ID_OUI_FROM_DATABASE=JABLOCOM s.r.o. OUI:0CEF7C* ID_OUI_FROM_DATABASE=AnaCom Inc OUI:E08FEC* ID_OUI_FROM_DATABASE=REPOTEC CO., LTD. OUI:D0D286* ID_OUI_FROM_DATABASE=Beckman Coulter K.K. OUI:1C0FCF* ID_OUI_FROM_DATABASE=Sypro Optics GmbH OUI:0025AB* ID_OUI_FROM_DATABASE=AIO LCD PC BU / TPV OUI:0025A4* ID_OUI_FROM_DATABASE=EuroDesign embedded technologies GmbH OUI:00259D* ID_OUI_FROM_DATABASE=Private OUI:002598* ID_OUI_FROM_DATABASE=Zhong Shan City Litai Electronic Industrial Co. Ltd OUI:002591* ID_OUI_FROM_DATABASE=NEXTEK, Inc. OUI:00258C* ID_OUI_FROM_DATABASE=ESUS ELEKTRONIK SAN. VE DIS. TIC. LTD. STI. OUI:002587* ID_OUI_FROM_DATABASE=Vitality, Inc. OUI:002581* ID_OUI_FROM_DATABASE=x-star networks Inc. OUI:002582* ID_OUI_FROM_DATABASE=Maksat Technologies (P) Ltd OUI:002578* ID_OUI_FROM_DATABASE=JSC Concern Sozvezdie OUI:00257D* ID_OUI_FROM_DATABASE=PointRed Telecom Private Ltd. OUI:002577* ID_OUI_FROM_DATABASE=D-BOX Technologies OUI:002571* ID_OUI_FROM_DATABASE=Zhejiang Tianle Digital Electric Co.,Ltd OUI:00256A* ID_OUI_FROM_DATABASE=inIT - Institut Industrial IT OUI:002565* ID_OUI_FROM_DATABASE=Vizimax Inc. OUI:00255E* ID_OUI_FROM_DATABASE=Shanghai Dare Technologies Co.,Ltd. OUI:002558* ID_OUI_FROM_DATABASE=MPEDIA OUI:002635* ID_OUI_FROM_DATABASE=Bluetechnix GmbH OUI:00262F* ID_OUI_FROM_DATABASE=HAMAMATSU TOA ELECTRONICS OUI:002623* ID_OUI_FROM_DATABASE=JRD Communication Inc OUI:002628* ID_OUI_FROM_DATABASE=companytec automação e controle ltda. OUI:00261C* ID_OUI_FROM_DATABASE=NEOVIA INC. OUI:002615* ID_OUI_FROM_DATABASE=Teracom Limited OUI:002616* ID_OUI_FROM_DATABASE=Rosemount Inc. OUI:002610* ID_OUI_FROM_DATABASE=Apacewave Technologies OUI:002609* ID_OUI_FROM_DATABASE=Phyllis Co., Ltd. OUI:00268C* ID_OUI_FROM_DATABASE=StarLeaf Ltd. OUI:002692* ID_OUI_FROM_DATABASE=Mitsubishi Electric Co. OUI:002686* ID_OUI_FROM_DATABASE=Quantenna Communcations, Inc. OUI:002680* ID_OUI_FROM_DATABASE=SIL3 Pty.Ltd OUI:00267F* ID_OUI_FROM_DATABASE=Zenterio AB OUI:00267A* ID_OUI_FROM_DATABASE=wuhan hongxin telecommunication technologies co.,ltd OUI:002679* ID_OUI_FROM_DATABASE=Euphonic Technologies, Inc. OUI:002673* ID_OUI_FROM_DATABASE=RICOH COMPANY,LTD. OUI:00266D* ID_OUI_FROM_DATABASE=MobileAccess Networks OUI:0025D6* ID_OUI_FROM_DATABASE=The Kroger Co. OUI:0025CA* ID_OUI_FROM_DATABASE=LS Research, LLC OUI:0025C3* ID_OUI_FROM_DATABASE=Nortel Networks OUI:0025BE* ID_OUI_FROM_DATABASE=Tektrap Systems Inc. OUI:0025BD* ID_OUI_FROM_DATABASE=Italdata Ingegneria dell'Idea S.p.A. OUI:0025B7* ID_OUI_FROM_DATABASE=Costar electronics, inc., OUI:0025B0* ID_OUI_FROM_DATABASE=Schmartz Inc OUI:002546* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002545* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002535* ID_OUI_FROM_DATABASE=Minimax GmbH & Co KG OUI:002532* ID_OUI_FROM_DATABASE=Digital Recorders OUI:00252B* ID_OUI_FROM_DATABASE=Stirling Energy Systems OUI:0025FD* ID_OUI_FROM_DATABASE=OBR Centrum Techniki Morskiej S.A. OUI:002603* ID_OUI_FROM_DATABASE=Shenzhen Wistar Technology Co., Ltd OUI:0025F3* ID_OUI_FROM_DATABASE=Nordwestdeutsche Zählerrevision OUI:0025EC* ID_OUI_FROM_DATABASE=Humanware OUI:0025E2* ID_OUI_FROM_DATABASE=Everspring Industry Co., Ltd. OUI:0025DD* ID_OUI_FROM_DATABASE=SUNNYTEK INFORMATION CO., LTD. OUI:002667* ID_OUI_FROM_DATABASE=CARECOM CO.,LTD. OUI:002660* ID_OUI_FROM_DATABASE=Logiways OUI:002656* ID_OUI_FROM_DATABASE=Sansonic Electronics USA OUI:002653* ID_OUI_FROM_DATABASE=DaySequerra Corporation OUI:00264C* ID_OUI_FROM_DATABASE=Shanghai DigiVision Technology Co., Ltd. OUI:002647* ID_OUI_FROM_DATABASE=WFE TECHNOLOGY CORP. OUI:00263B* ID_OUI_FROM_DATABASE=Onbnetech OUI:0026C1* ID_OUI_FROM_DATABASE=ARTRAY CO., LTD. OUI:0026B5* ID_OUI_FROM_DATABASE=ICOMM Tele Ltd OUI:0026AF* ID_OUI_FROM_DATABASE=Duelco A/S OUI:0026AB* ID_OUI_FROM_DATABASE=SEIKO EPSON CORPORATION OUI:0026A5* ID_OUI_FROM_DATABASE=MICROROBOT.CO.,LTD OUI:00269F* ID_OUI_FROM_DATABASE=Private OUI:002699* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002489* ID_OUI_FROM_DATABASE=Vodafone Omnitel N.V. OUI:00248E* ID_OUI_FROM_DATABASE=Infoware ZRt. OUI:002490* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,LTD OUI:002482* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:002476* ID_OUI_FROM_DATABASE=TAP.tv OUI:00246F* ID_OUI_FROM_DATABASE=Onda Communication spa OUI:00246A* ID_OUI_FROM_DATABASE=Solid Year Co., Ltd. OUI:0023FA* ID_OUI_FROM_DATABASE=RG Nets, Inc. OUI:0023FF* ID_OUI_FROM_DATABASE=Beijing HTTC Technology Ltd. OUI:0023F4* ID_OUI_FROM_DATABASE=Masternaut OUI:0023EA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0023E4* ID_OUI_FROM_DATABASE=IPnect co. ltd. OUI:0023DE* ID_OUI_FROM_DATABASE=Ansync Inc. OUI:0023D1* ID_OUI_FROM_DATABASE=TRG OUI:0023CB* ID_OUI_FROM_DATABASE=Shenzhen Full-join Technology Co.,Ltd OUI:0023D2* ID_OUI_FROM_DATABASE=Inhand Electronics, Inc. OUI:0023D7* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:0024B4* ID_OUI_FROM_DATABASE=ESCATRONIC GmbH OUI:0024AF* ID_OUI_FROM_DATABASE=EchoStar Technologies OUI:0024A8* ID_OUI_FROM_DATABASE=ProCurve Networking by HP OUI:0024AD* ID_OUI_FROM_DATABASE=Adolf Thies Gmbh & Co. KG OUI:00249C* ID_OUI_FROM_DATABASE=Bimeng Comunication System Co. Ltd OUI:002526* ID_OUI_FROM_DATABASE=Genuine Technologies Co., Ltd. OUI:002525* ID_OUI_FROM_DATABASE=CTERA Networks Ltd. OUI:002520* ID_OUI_FROM_DATABASE=SMA Railway Technology GmbH OUI:00251B* ID_OUI_FROM_DATABASE=Philips CareServant OUI:002516* ID_OUI_FROM_DATABASE=Integrated Design Tools, Inc. OUI:00250F* ID_OUI_FROM_DATABASE=On-Ramp Wireless, Inc. OUI:002503* ID_OUI_FROM_DATABASE=IBM Corp OUI:00250A* ID_OUI_FROM_DATABASE=Security Expert Co. Ltd OUI:0024DD* ID_OUI_FROM_DATABASE=Centrak, Inc. OUI:0024D8* ID_OUI_FROM_DATABASE=IlSung Precision OUI:0024CC* ID_OUI_FROM_DATABASE=Fascinations Toys and Gifts, Inc. OUI:0024D1* ID_OUI_FROM_DATABASE=Thomson Inc. OUI:0024CA* ID_OUI_FROM_DATABASE=Tobii Technology AB OUI:0024C5* ID_OUI_FROM_DATABASE=Meridian Audio Limited OUI:0024B9* ID_OUI_FROM_DATABASE=Wuhan Higheasy Electronic Technology Development Co.Ltd OUI:002425* ID_OUI_FROM_DATABASE=Shenzhenshi chuangzhicheng Technology Co.,Ltd OUI:002419* ID_OUI_FROM_DATABASE=Private OUI:002412* ID_OUI_FROM_DATABASE=Benign Technologies Co, Ltd. OUI:00240C* ID_OUI_FROM_DATABASE=DELEC GmbH OUI:002406* ID_OUI_FROM_DATABASE=Pointmobile OUI:0023F9* ID_OUI_FROM_DATABASE=Double-Take Software, INC. OUI:002463* ID_OUI_FROM_DATABASE=Phybridge Inc OUI:002459* ID_OUI_FROM_DATABASE=ABB Automation products GmbH OUI:00245E* ID_OUI_FROM_DATABASE=Hivision Co.,ltd OUI:002451* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00244C* ID_OUI_FROM_DATABASE=Solartron Metrology Ltd OUI:002445* ID_OUI_FROM_DATABASE=CommScope Canada Inc. OUI:00243F* ID_OUI_FROM_DATABASE=Storwize, Inc. OUI:002440* ID_OUI_FROM_DATABASE=Halo Monitoring, Inc. OUI:00243B* ID_OUI_FROM_DATABASE=CSSI (S) Pte Ltd OUI:0024FC* ID_OUI_FROM_DATABASE=QuoPin Co., Ltd. OUI:0024F7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0024F0* ID_OUI_FROM_DATABASE=Seanodes OUI:0024E9* ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd., Storage System Division OUI:0024EB* ID_OUI_FROM_DATABASE=ClearPath Networks, Inc. OUI:0024E4* ID_OUI_FROM_DATABASE=Withings OUI:002435* ID_OUI_FROM_DATABASE=WIDE CORPORATION OUI:00242F* ID_OUI_FROM_DATABASE=Micron OUI:00241F* ID_OUI_FROM_DATABASE=DCT-Delta GmbH OUI:0023C5* ID_OUI_FROM_DATABASE=Radiation Safety and Control Services Inc OUI:0023C4* ID_OUI_FROM_DATABASE=Lux Lumen OUI:0023B8* ID_OUI_FROM_DATABASE=Sichuan Jiuzhou Electronic Technology Co.,Ltd OUI:0023BF* ID_OUI_FROM_DATABASE=Mainpine, Inc. OUI:0023B2* ID_OUI_FROM_DATABASE=Intelligent Mechatronic Systems Inc OUI:0023AC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0023A0* ID_OUI_FROM_DATABASE=Hana CNS Co., LTD. OUI:0023A5* ID_OUI_FROM_DATABASE=SageTV, LLC OUI:0022B6* ID_OUI_FROM_DATABASE=Superflow Technologies Group OUI:0022A3* ID_OUI_FROM_DATABASE=California Eastern Laboratories OUI:00229E* ID_OUI_FROM_DATABASE=Social Aid Research Co., Ltd. OUI:002291* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002292* ID_OUI_FROM_DATABASE=Cinetal OUI:002297* ID_OUI_FROM_DATABASE=XMOS Semiconductor OUI:00228B* ID_OUI_FROM_DATABASE=Kensington Computer Products Group OUI:002284* ID_OUI_FROM_DATABASE=DESAY A&V SCIENCE AND TECHNOLOGY CO.,LTD OUI:00227F* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:002277* ID_OUI_FROM_DATABASE=NEC Australia Pty Ltd OUI:00226D* ID_OUI_FROM_DATABASE=Shenzhen GIEC Electronics Co., Ltd. OUI:002263* ID_OUI_FROM_DATABASE=Koos Technical Services, Inc. OUI:002267* ID_OUI_FROM_DATABASE=Nortel Networks OUI:002259* ID_OUI_FROM_DATABASE=Guangzhou New Postcom Equipment Co.,Ltd. OUI:0022E4* ID_OUI_FROM_DATABASE=APASS TECHNOLOGY CO., LTD. OUI:0022DD* ID_OUI_FROM_DATABASE=Protecta Electronics Ltd OUI:0022D8* ID_OUI_FROM_DATABASE=Shenzhen GST Security and Safety Technology Limited OUI:0022D1* ID_OUI_FROM_DATABASE=Albrecht Jung GmbH & Co. KG OUI:0022C3* ID_OUI_FROM_DATABASE=Zeeport Technology Inc. OUI:0022C7* ID_OUI_FROM_DATABASE=SEGGER Microcontroller GmbH & Co. KG OUI:0022BD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002344* ID_OUI_FROM_DATABASE=Objective Interface Systems, Inc. OUI:002343* ID_OUI_FROM_DATABASE=TEM AG OUI:00233E* ID_OUI_FROM_DATABASE=Alcatel-Lucent-IPD OUI:002337* ID_OUI_FROM_DATABASE=Global Star Solutions ULC OUI:00232B* ID_OUI_FROM_DATABASE=IRD A/S OUI:00231C* ID_OUI_FROM_DATABASE=Fourier Systems Ltd. OUI:00231B* ID_OUI_FROM_DATABASE=Danaher Motion - Kollmorgen OUI:00239F* ID_OUI_FROM_DATABASE=Institut für Prüftechnik OUI:002399* ID_OUI_FROM_DATABASE=VD Division, Samsung Electronics Co. OUI:002393* ID_OUI_FROM_DATABASE=AJINEXTEK OUI:00238F* ID_OUI_FROM_DATABASE=NIDEC COPAL CORPORATION OUI:00238B* ID_OUI_FROM_DATABASE=Quanta Computer Inc. OUI:002385* ID_OUI_FROM_DATABASE=ANTIPODE OUI:00237E* ID_OUI_FROM_DATABASE=ELSTER GMBH OUI:00237F* ID_OUI_FROM_DATABASE=PLANTRONICS, INC. OUI:002379* ID_OUI_FROM_DATABASE=Union Business Machines Co. Ltd. OUI:002253* ID_OUI_FROM_DATABASE=Entorian Technologies OUI:002250* ID_OUI_FROM_DATABASE=Point Six Wireless, LLC OUI:002249* ID_OUI_FROM_DATABASE=HOME MULTIENERGY SL OUI:00224A* ID_OUI_FROM_DATABASE=RAYLASE AG OUI:002240* ID_OUI_FROM_DATABASE=Universal Telecom S/A OUI:00222D* ID_OUI_FROM_DATABASE=SMC Networks Inc. OUI:00222E* ID_OUI_FROM_DATABASE=maintech GmbH OUI:002363* ID_OUI_FROM_DATABASE=Zhuhai RaySharp Technology Co., Ltd. OUI:002364* ID_OUI_FROM_DATABASE=Power Instruments Pte Ltd OUI:002369* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:002370* ID_OUI_FROM_DATABASE=Snell OUI:00235D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002356* ID_OUI_FROM_DATABASE=Packet Forensics LLC OUI:00234A* ID_OUI_FROM_DATABASE=Private OUI:002313* ID_OUI_FROM_DATABASE=Qool Technologies Ltd. OUI:00230D* ID_OUI_FROM_DATABASE=Nortel Networks OUI:002301* ID_OUI_FROM_DATABASE=Witron Technology Limited OUI:0022F7* ID_OUI_FROM_DATABASE=Conceptronic OUI:0022EA* ID_OUI_FROM_DATABASE=Rustelcom Inc. OUI:0022F0* ID_OUI_FROM_DATABASE=3 Greens Aviation Limited OUI:0022E9* ID_OUI_FROM_DATABASE=ProVision Communications OUI:00211C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002117* ID_OUI_FROM_DATABASE=Tellord OUI:002110* ID_OUI_FROM_DATABASE=Clearbox Systems OUI:002106* ID_OUI_FROM_DATABASE=RIM Testing Services OUI:001FFF* ID_OUI_FROM_DATABASE=Respironics, Inc. OUI:001FFE* ID_OUI_FROM_DATABASE=HPN Supply Chain OUI:001FF8* ID_OUI_FROM_DATABASE=Siemens AG, Sector Industry, Drive Technologies, Motion Control Systems OUI:001FFD* ID_OUI_FROM_DATABASE=Indigo Mobile Technologies Corp. OUI:002221* ID_OUI_FROM_DATABASE=ITOH DENKI CO,LTD. OUI:00221B* ID_OUI_FROM_DATABASE=Morega Systems OUI:002220* ID_OUI_FROM_DATABASE=Mitac Technology Corp OUI:002227* ID_OUI_FROM_DATABASE=uv-electronic GmbH OUI:002214* ID_OUI_FROM_DATABASE=RINNAI KOREA OUI:00220E* ID_OUI_FROM_DATABASE=Indigo Security Co., Ltd. OUI:002208* ID_OUI_FROM_DATABASE=Certicom Corp OUI:002201* ID_OUI_FROM_DATABASE=Aksys Networks Inc OUI:0021F7* ID_OUI_FROM_DATABASE=HPN Supply Chain OUI:0021A0* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00219C* ID_OUI_FROM_DATABASE=Honeywld Technology Corp. OUI:002192* ID_OUI_FROM_DATABASE=Baoding Galaxy Electronic Technology Co.,Ltd OUI:00218C* ID_OUI_FROM_DATABASE=TopControl GMBH OUI:002186* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd OUI:00217F* ID_OUI_FROM_DATABASE=Intraco Technology Pte Ltd OUI:00217A* ID_OUI_FROM_DATABASE=Sejin Electron, Inc. OUI:002179* ID_OUI_FROM_DATABASE=IOGEAR, Inc. OUI:002173* ID_OUI_FROM_DATABASE=Ion Torrent Systems, Inc. OUI:001FC3* ID_OUI_FROM_DATABASE=SmartSynch, Inc OUI:001FC8* ID_OUI_FROM_DATABASE=Up-Today Industrial Co., Ltd. OUI:001FC1* ID_OUI_FROM_DATABASE=Hanlong Technology Co.,LTD OUI:001FC2* ID_OUI_FROM_DATABASE=Jow Tong Technology Co Ltd OUI:001FBC* ID_OUI_FROM_DATABASE=EVGA Corporation OUI:001FB0* ID_OUI_FROM_DATABASE=TimeIPS, Inc. OUI:001FB5* ID_OUI_FROM_DATABASE=I/O Interconnect Inc. OUI:001FA9* ID_OUI_FROM_DATABASE=Atlanta DTH, Inc. OUI:0021F1* ID_OUI_FROM_DATABASE=Tutus Data AB OUI:0021F2* ID_OUI_FROM_DATABASE=EASY3CALL Technology Limited OUI:0021EB* ID_OUI_FROM_DATABASE=ESP SYSTEMS, LLC OUI:0021E5* ID_OUI_FROM_DATABASE=Display Solution AG OUI:0021E4* ID_OUI_FROM_DATABASE=I-WIN OUI:0021DF* ID_OUI_FROM_DATABASE=Martin Christ GmbH OUI:0021D2* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:0021D8* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0021CC* ID_OUI_FROM_DATABASE=Flextronics International OUI:001FF1* ID_OUI_FROM_DATABASE=Paradox Hellas S.A. OUI:001FEC* ID_OUI_FROM_DATABASE=Synapse Électronique OUI:001FE5* ID_OUI_FROM_DATABASE=In-Circuit GmbH OUI:001FD9* ID_OUI_FROM_DATABASE=RSD Communications Ltd OUI:001FD4* ID_OUI_FROM_DATABASE=4IPNET, INC. OUI:001FCF* ID_OUI_FROM_DATABASE=MSI Technology GmbH OUI:00213F* ID_OUI_FROM_DATABASE=A-Team Technology Ltd. OUI:002139* ID_OUI_FROM_DATABASE=Escherlogic Inc. OUI:002134* ID_OUI_FROM_DATABASE=Brandywine Communications OUI:00212F* ID_OUI_FROM_DATABASE=Phoebe Micro Inc. OUI:002129* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:00212A* ID_OUI_FROM_DATABASE=Audiovox Corporation OUI:002123* ID_OUI_FROM_DATABASE=Aerosat Avionics OUI:00216D* ID_OUI_FROM_DATABASE=Soltech Co., Ltd. OUI:00216C* ID_OUI_FROM_DATABASE=ODVA OUI:002167* ID_OUI_FROM_DATABASE=HWA JIN T&I Corp. OUI:002160* ID_OUI_FROM_DATABASE=Hidea Solutions Co. Ltd. OUI:002154* ID_OUI_FROM_DATABASE=D-TACQ Solutions Ltd OUI:00214D* ID_OUI_FROM_DATABASE=Guangzhou Skytone Transmission Technology Com. Ltd. OUI:002148* ID_OUI_FROM_DATABASE=Kaco Solar Korea OUI:0021C5* ID_OUI_FROM_DATABASE=3DSP Corp OUI:0021BF* ID_OUI_FROM_DATABASE=Hitachi High-Tech Control Systems Corporation OUI:0021C0* ID_OUI_FROM_DATABASE=Mobile Appliance, Inc. OUI:0021B9* ID_OUI_FROM_DATABASE=Universal Devices Inc. OUI:0021B3* ID_OUI_FROM_DATABASE=Ross Controls OUI:0021B2* ID_OUI_FROM_DATABASE=Fiberblaze A/S OUI:0021AD* ID_OUI_FROM_DATABASE=Nordic ID Oy OUI:0021A6* ID_OUI_FROM_DATABASE=Videotec Spa OUI:001F16* ID_OUI_FROM_DATABASE=Wistron Corporation OUI:001F11* ID_OUI_FROM_DATABASE=OPENMOKO, INC. OUI:001F0B* ID_OUI_FROM_DATABASE=Federal State Unitary Enterprise Industrial UnionElectropribor OUI:001EFF* ID_OUI_FROM_DATABASE=Mueller-Elektronik GmbH & Co. KG OUI:001F06* ID_OUI_FROM_DATABASE=Integrated Dispatch Solutions OUI:001F05* ID_OUI_FROM_DATABASE=iTAS Technology Corp. OUI:001EF3* ID_OUI_FROM_DATABASE=From2 OUI:001EF8* ID_OUI_FROM_DATABASE=Emfinity Inc. OUI:001F7A* ID_OUI_FROM_DATABASE=WiWide Inc. OUI:001F70* ID_OUI_FROM_DATABASE=Botik Technologies LTD OUI:001F75* ID_OUI_FROM_DATABASE=GiBahn Media OUI:001F64* ID_OUI_FROM_DATABASE=Beijing Autelan Technology Inc. OUI:001F6B* ID_OUI_FROM_DATABASE=LG Electronics OUI:001F5E* ID_OUI_FROM_DATABASE=Dyna Technology Co.,Ltd. OUI:001F58* ID_OUI_FROM_DATABASE=EMH Energiemesstechnik GmbH OUI:001F4C* ID_OUI_FROM_DATABASE=Roseman Engineering Ltd OUI:001F51* ID_OUI_FROM_DATABASE=HD Communications Corp OUI:001F4B* ID_OUI_FROM_DATABASE=Lineage Power OUI:001F9F* ID_OUI_FROM_DATABASE=Thomson Telecom Belgium OUI:001F93* ID_OUI_FROM_DATABASE=Xiotech Corporation OUI:001F98* ID_OUI_FROM_DATABASE=DAIICHI-DENTSU LTD. OUI:001F8C* ID_OUI_FROM_DATABASE=CCS Inc. OUI:001F8A* ID_OUI_FROM_DATABASE=Ellion Digital Inc. OUI:001F83* ID_OUI_FROM_DATABASE=Teleplan Technology Services Sdn Bhd OUI:001E37* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. OUI:001E30* ID_OUI_FROM_DATABASE=Shireen Inc OUI:001E2B* ID_OUI_FROM_DATABASE=Radio Systems Design, Inc. OUI:001E24* ID_OUI_FROM_DATABASE=Zhejiang Bell Technology Co.,ltd OUI:001E18* ID_OUI_FROM_DATABASE=Radio Activity srl OUI:001E1D* ID_OUI_FROM_DATABASE=East Coast Datacom, Inc. OUI:001E1E* ID_OUI_FROM_DATABASE=Honeywell Life Safety OUI:001E13* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001E0E* ID_OUI_FROM_DATABASE=MAXI VIEW HOLDINGS LIMITED OUI:001E60* ID_OUI_FROM_DATABASE=Digital Lighting Systems, Inc OUI:001E59* ID_OUI_FROM_DATABASE=Silicon Turnkey Express, LLC OUI:001E54* ID_OUI_FROM_DATABASE=TOYO ELECTRIC Corporation OUI:001E4D* ID_OUI_FROM_DATABASE=Welkin Sciences, LLC OUI:001E48* ID_OUI_FROM_DATABASE=Wi-Links OUI:001E43* ID_OUI_FROM_DATABASE=AISIN AW CO.,LTD. OUI:001E3E* ID_OUI_FROM_DATABASE=KMW Inc. OUI:001EC3* ID_OUI_FROM_DATABASE=Kozio, Inc. OUI:001EBC* ID_OUI_FROM_DATABASE=WINTECH AUTOMATION CO.,LTD. OUI:001EB7* ID_OUI_FROM_DATABASE=TBTech, Co., Ltd. OUI:001EB0* ID_OUI_FROM_DATABASE=ImesD Electronica S.L. OUI:001EA5* ID_OUI_FROM_DATABASE=ROBOTOUS, Inc. OUI:001EAB* ID_OUI_FROM_DATABASE=TeleWell Oy OUI:001E9E* ID_OUI_FROM_DATABASE=ddm hopt + schuler Gmbh + Co. KG OUI:001E99* ID_OUI_FROM_DATABASE=Vantanol Industrial Corporation OUI:001F36* ID_OUI_FROM_DATABASE=Bellwin Information Co. Ltd., OUI:001F35* ID_OUI_FROM_DATABASE=AIR802 LLC OUI:001F30* ID_OUI_FROM_DATABASE=Travelping OUI:001F23* ID_OUI_FROM_DATABASE=Interacoustics OUI:001F24* ID_OUI_FROM_DATABASE=DIGITVIEW TECHNOLOGY CO., LTD. OUI:001F1D* ID_OUI_FROM_DATABASE=Atlas Material Testing Technology LLC OUI:001E92* ID_OUI_FROM_DATABASE=JEULIN S.A. OUI:001E89* ID_OUI_FROM_DATABASE=CRFS Limited OUI:001E84* ID_OUI_FROM_DATABASE=Pika Technologies Inc. OUI:001E7D* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:001E83* ID_OUI_FROM_DATABASE=LAN/MAN Standards Association (LMSC) OUI:001E6C* ID_OUI_FROM_DATABASE=Opaque Systems OUI:001EE6* ID_OUI_FROM_DATABASE=Shenzhen Advanced Video Info-Tech Co., Ltd. OUI:001EE0* ID_OUI_FROM_DATABASE=Urmet Domus SpA OUI:001EDB* ID_OUI_FROM_DATABASE=Giken Trastem Co., Ltd. OUI:001ED6* ID_OUI_FROM_DATABASE=Alentec & Orion AB OUI:001ECF* ID_OUI_FROM_DATABASE=PHILIPS ELECTRONICS UK LTD OUI:001ECA* ID_OUI_FROM_DATABASE=Nortel OUI:001C96* ID_OUI_FROM_DATABASE=Linkwise Technology Pte Ltd OUI:001C91* ID_OUI_FROM_DATABASE=Gefen Inc. OUI:001C8A* ID_OUI_FROM_DATABASE=Cirrascale Corporation OUI:001C84* ID_OUI_FROM_DATABASE=STL Solution Co.,Ltd. OUI:001C80* ID_OUI_FROM_DATABASE=New Business Division/Rhea-Information CO., LTD. OUI:001C76* ID_OUI_FROM_DATABASE=The Wandsworth Group Ltd OUI:001C6F* ID_OUI_FROM_DATABASE=Emfit Ltd OUI:001C71* ID_OUI_FROM_DATABASE=Emergent Electronics OUI:001C70* ID_OUI_FROM_DATABASE=NOVACOMM LTDA OUI:001C6A* ID_OUI_FROM_DATABASE=Weiss Engineering Ltd. OUI:001D59* ID_OUI_FROM_DATABASE=Mitra Energy & Infrastructure OUI:001D52* ID_OUI_FROM_DATABASE=Defzone B.V. OUI:001D4C* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:001D48* ID_OUI_FROM_DATABASE=Sensor-Technik Wiedemann GmbH OUI:001D41* ID_OUI_FROM_DATABASE=Hardy Instruments OUI:001D42* ID_OUI_FROM_DATABASE=Nortel OUI:001D3C* ID_OUI_FROM_DATABASE=Muscle Corporation OUI:001D30* ID_OUI_FROM_DATABASE=YX Wireless S.A. OUI:001D35* ID_OUI_FROM_DATABASE=Viconics Electronics Inc. OUI:001D2F* ID_OUI_FROM_DATABASE=QuantumVision Corporation OUI:001CD3* ID_OUI_FROM_DATABASE=ZP Engineering SEL OUI:001CCE* ID_OUI_FROM_DATABASE=By Techdesign OUI:001CC7* ID_OUI_FROM_DATABASE=Rembrandt Technologies, LLC d/b/a REMSTREAM OUI:001CC2* ID_OUI_FROM_DATABASE=Part II Research, Inc. OUI:001CBB* ID_OUI_FROM_DATABASE=MusicianLink OUI:001CB1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001CB7* ID_OUI_FROM_DATABASE=USC DigiArk Corporation OUI:001CA3* ID_OUI_FROM_DATABASE=Terra OUI:001CA5* ID_OUI_FROM_DATABASE=Zygo Corporation OUI:001CAA* ID_OUI_FROM_DATABASE=Bellon Pty Ltd OUI:001C9D* ID_OUI_FROM_DATABASE=Liecthi AG OUI:001DCA* ID_OUI_FROM_DATABASE=PAV Electronics Limited OUI:001DC4* ID_OUI_FROM_DATABASE=AIOI Systems Co., Ltd. OUI:001DC3* ID_OUI_FROM_DATABASE=RIKOR TV, Ltd OUI:001DB1* ID_OUI_FROM_DATABASE=Crescendo Networks OUI:001DB2* ID_OUI_FROM_DATABASE=HOKKAIDO ELECTRIC ENGINEERING CO.,LTD. OUI:001DB7* ID_OUI_FROM_DATABASE=Tendril Networks, Inc. OUI:001DAD* ID_OUI_FROM_DATABASE=Sinotech Engineering Consultants, Inc. Geotechnical Enginee OUI:001DA8* ID_OUI_FROM_DATABASE=Takahata Electronics Co.,Ltd OUI:001DA7* ID_OUI_FROM_DATABASE=Seamless Internet OUI:001DA1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001D9A* ID_OUI_FROM_DATABASE=GODEX INTERNATIONAL CO., LTD OUI:001D95* ID_OUI_FROM_DATABASE=Flash, Inc. OUI:001D8E* ID_OUI_FROM_DATABASE=Alereon, Inc. OUI:001D87* ID_OUI_FROM_DATABASE=VigTech Labs Sdn Bhd OUI:001D88* ID_OUI_FROM_DATABASE=Clearwire OUI:001D7E* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:001D7D* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:001D6C* ID_OUI_FROM_DATABASE=ClariPhy Communications, Inc. OUI:001D71* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001D78* ID_OUI_FROM_DATABASE=Invengo Information Technology Co.,Ltd OUI:001D65* ID_OUI_FROM_DATABASE=Microwave Radio Communications OUI:001D5E* ID_OUI_FROM_DATABASE=COMING MEDIA CORP. OUI:001D29* ID_OUI_FROM_DATABASE=Doro AB OUI:001D22* ID_OUI_FROM_DATABASE=Foss Analytical A/S OUI:001D1D* ID_OUI_FROM_DATABASE=Inter-M Corporation OUI:001D16* ID_OUI_FROM_DATABASE=SFR OUI:001D10* ID_OUI_FROM_DATABASE=LightHaus Logic, Inc. OUI:001D0A* ID_OUI_FROM_DATABASE=Davis Instruments, Inc. OUI:001D03* ID_OUI_FROM_DATABASE=Design Solutions Inc. OUI:001CFE* ID_OUI_FROM_DATABASE=Quartics Inc OUI:001CFD* ID_OUI_FROM_DATABASE=Universal Electronics OUI:001CF7* ID_OUI_FROM_DATABASE=AudioScience OUI:001CEB* ID_OUI_FROM_DATABASE=Nortel OUI:001CE6* ID_OUI_FROM_DATABASE=INNES OUI:001CE1* ID_OUI_FROM_DATABASE=INDRA SISTEMAS, S.A. OUI:001CDA* ID_OUI_FROM_DATABASE=Exegin Technologies Limited OUI:001E07* ID_OUI_FROM_DATABASE=Winy Technology Co., Ltd. OUI:001E02* ID_OUI_FROM_DATABASE=Sougou Keikaku Kougyou Co.,Ltd. OUI:001E01* ID_OUI_FROM_DATABASE=Renesas Technology Sales Co., Ltd. OUI:001DFB* ID_OUI_FROM_DATABASE=NETCLEUS Systems Corporation OUI:001DF4* ID_OUI_FROM_DATABASE=Magellan Technology Pty Limited OUI:001DEF* ID_OUI_FROM_DATABASE=TRIMM, INC. OUI:001DE8* ID_OUI_FROM_DATABASE=Nikko Denki Tsushin Corporation(NDTC) OUI:001DE3* ID_OUI_FROM_DATABASE=Intuicom OUI:001DDD* ID_OUI_FROM_DATABASE=DAT H.K. LIMITED OUI:001AF8* ID_OUI_FROM_DATABASE=Copley Controls Corporation OUI:001AF3* ID_OUI_FROM_DATABASE=Samyoung Electronics OUI:001AEE* ID_OUI_FROM_DATABASE=Shenztech Ltd OUI:001AE2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001AE7* ID_OUI_FROM_DATABASE=Aztek Networks, Inc. OUI:001AD4* ID_OUI_FROM_DATABASE=iPOX Technology Co., Ltd. OUI:001AD6* ID_OUI_FROM_DATABASE=JIAGNSU AETNA ELECTRIC CO.,LTD OUI:001B97* ID_OUI_FROM_DATABASE=Violin Technologies OUI:001B9C* ID_OUI_FROM_DATABASE=SATEL sp. z o.o. OUI:001B90* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001B86* ID_OUI_FROM_DATABASE=Bosch Access Systems GmbH OUI:001B8B* ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. OUI:001B7F* ID_OUI_FROM_DATABASE=TMN Technologies Telecomunicacoes Ltda OUI:001B81* ID_OUI_FROM_DATABASE=DATAQ Instruments, Inc. OUI:001B80* ID_OUI_FROM_DATABASE=LORD Corporation OUI:001B73* ID_OUI_FROM_DATABASE=DTL Broadcast Ltd OUI:001B6E* ID_OUI_FROM_DATABASE=Anue Systems, Inc. OUI:001B67* ID_OUI_FROM_DATABASE=Cisco Systems Inc OUI:001B60* ID_OUI_FROM_DATABASE=NAVIGON AG OUI:001B54* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001B48* ID_OUI_FROM_DATABASE=Shenzhen Lantech Electronics Co., Ltd. OUI:001B4D* ID_OUI_FROM_DATABASE=Areca Technology Corporation OUI:001B41* ID_OUI_FROM_DATABASE=General Infinity Co.,Ltd. OUI:001B3C* ID_OUI_FROM_DATABASE=Software Technologies Group,Inc. OUI:001B35* ID_OUI_FROM_DATABASE=ChongQing JINOU Science & Technology Development CO.,Ltd OUI:001B2E* ID_OUI_FROM_DATABASE=Sinkyo Electron Inc OUI:001B30* ID_OUI_FROM_DATABASE=Solitech Inc. OUI:001BC7* ID_OUI_FROM_DATABASE=StarVedia Technology Inc. OUI:001BC6* ID_OUI_FROM_DATABASE=Strato Rechenzentrum AG OUI:001BBB* ID_OUI_FROM_DATABASE=RFTech Co.,Ltd OUI:001BB6* ID_OUI_FROM_DATABASE=Bird Electronic Corp. OUI:001BAA* ID_OUI_FROM_DATABASE=XenICs nv OUI:001BA3* ID_OUI_FROM_DATABASE=Flexit Group GmbH OUI:001C63* ID_OUI_FROM_DATABASE=TRUEN OUI:001C57* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001C5E* ID_OUI_FROM_DATABASE=ASTON France OUI:001C46* ID_OUI_FROM_DATABASE=QTUM OUI:001C4D* ID_OUI_FROM_DATABASE=Aplix IP Holdings Corporation OUI:001C3A* ID_OUI_FROM_DATABASE=Element Labs, Inc. OUI:001C41* ID_OUI_FROM_DATABASE=scemtec Transponder Technology GmbH OUI:001C34* ID_OUI_FROM_DATABASE=HUEY CHIAO INTERNATIONAL CO., LTD. OUI:001C33* ID_OUI_FROM_DATABASE=Sutron OUI:001BF7* ID_OUI_FROM_DATABASE=Lund IP Products AB OUI:001BF9* ID_OUI_FROM_DATABASE=Intellitect Water Ltd OUI:001BF8* ID_OUI_FROM_DATABASE=Digitrax Inc. OUI:001BF2* ID_OUI_FROM_DATABASE=KWORLD COMPUTER CO., LTD OUI:001BEB* ID_OUI_FROM_DATABASE=DMP Electronics INC. OUI:001BE6* ID_OUI_FROM_DATABASE=VR AG OUI:001BDF* ID_OUI_FROM_DATABASE=Iskra Sistemi d.d. OUI:001BD3* ID_OUI_FROM_DATABASE=Panasonic Corp. AVC Company OUI:001BD8* ID_OUI_FROM_DATABASE=DVTel LTD OUI:001BCC* ID_OUI_FROM_DATABASE=KINGTEK CCTV ALLIANCE CO., LTD. OUI:001AC8* ID_OUI_FROM_DATABASE=ISL (Instrumentation Scientifique de Laboratoire) OUI:001ACF* ID_OUI_FROM_DATABASE=C.T. ELETTRONICA OUI:001AC3* ID_OUI_FROM_DATABASE=Scientific-Atlanta, Inc OUI:001AB9* ID_OUI_FROM_DATABASE=PMC OUI:001ABE* ID_OUI_FROM_DATABASE=COMPUTER HI-TECH INC. OUI:001AAB* ID_OUI_FROM_DATABASE=eWings s.r.l. OUI:001AB2* ID_OUI_FROM_DATABASE=Cyber Solutions Inc. OUI:001AB7* ID_OUI_FROM_DATABASE=Ethos Networks LTD. OUI:001C2E* ID_OUI_FROM_DATABASE=HPN Supply Chain OUI:001C27* ID_OUI_FROM_DATABASE=Sunell Electronics Co. OUI:001C22* ID_OUI_FROM_DATABASE=Aeris Elettronica s.r.l. OUI:001C1D* ID_OUI_FROM_DATABASE=CHENZHOU GOSPELL DIGITAL TECHNOLOGY CO.,LTD OUI:001C18* ID_OUI_FROM_DATABASE=Sicert S.r.L. OUI:001C0A* ID_OUI_FROM_DATABASE=Shenzhen AEE Technology Co.,Ltd. OUI:001C05* ID_OUI_FROM_DATABASE=Nonin Medical Inc. OUI:001BFE* ID_OUI_FROM_DATABASE=Zavio Inc. OUI:001B29* ID_OUI_FROM_DATABASE=Avantis.Co.,Ltd OUI:001B23* ID_OUI_FROM_DATABASE=SimpleComTools OUI:001B1E* ID_OUI_FROM_DATABASE=HART Communication Foundation OUI:001B12* ID_OUI_FROM_DATABASE=Apprion OUI:001B17* ID_OUI_FROM_DATABASE=Palo Alto Networks OUI:001B0B* ID_OUI_FROM_DATABASE=Phidgets Inc. OUI:001B10* ID_OUI_FROM_DATABASE=ShenZhen Kang Hui Technology Co.,ltd OUI:001B04* ID_OUI_FROM_DATABASE=Affinity International S.p.a OUI:001AFF* ID_OUI_FROM_DATABASE=Wizyoung Tech. OUI:001AFD* ID_OUI_FROM_DATABASE=EVOLIS OUI:00191C* ID_OUI_FROM_DATABASE=Sensicast Systems OUI:00191E* ID_OUI_FROM_DATABASE=Beyondwiz Co., Ltd. OUI:001923* ID_OUI_FROM_DATABASE=Phonex Korea Co., LTD. OUI:00192A* ID_OUI_FROM_DATABASE=Antiope Associates OUI:001910* ID_OUI_FROM_DATABASE=Knick Elektronische Messgeraete GmbH & Co. KG OUI:001917* ID_OUI_FROM_DATABASE=Posiflex Inc. OUI:001909* ID_OUI_FROM_DATABASE=DEVI - Danfoss A/S OUI:00190B* ID_OUI_FROM_DATABASE=Southern Vision Systems, Inc. OUI:001904* ID_OUI_FROM_DATABASE=WB Electronics Sp. z o.o. OUI:0018FF* ID_OUI_FROM_DATABASE=PowerQuattro Co. OUI:0018FA* ID_OUI_FROM_DATABASE=Yushin Precision Equipment Co.,Ltd. OUI:001955* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00194E* ID_OUI_FROM_DATABASE=Ultra Electronics - TCS (Tactical Communication Systems) OUI:001950* ID_OUI_FROM_DATABASE=Harman Multimedia OUI:001949* ID_OUI_FROM_DATABASE=TENTEL COMTECH CO., LTD. OUI:001942* ID_OUI_FROM_DATABASE=ON SOFTWARE INTERNATIONAL LIMITED OUI:00193D* ID_OUI_FROM_DATABASE=GMC Guardian Mobility Corp. OUI:001936* ID_OUI_FROM_DATABASE=STERLITE OPTICAL TECHNOLOGIES LIMITED OUI:00193B* ID_OUI_FROM_DATABASE=Wilibox Deliberant Group LLC OUI:00192F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001A20* ID_OUI_FROM_DATABASE=CMOTECH Co. Ltd. OUI:001A22* ID_OUI_FROM_DATABASE=eQ-3 Entwicklung GmbH OUI:001A14* ID_OUI_FROM_DATABASE=Xin Hua Control Engineering Co.,Ltd. OUI:001A0D* ID_OUI_FROM_DATABASE=HandHeld entertainment, Inc. OUI:001A0F* ID_OUI_FROM_DATABASE=Sistemas Avanzados de Control, S.A. OUI:001A08* ID_OUI_FROM_DATABASE=Simoco Ltd. OUI:001A01* ID_OUI_FROM_DATABASE=Smiths Medical OUI:0019FC* ID_OUI_FROM_DATABASE=PT. Ufoakses Sukses Luarbiasa OUI:0019EF* ID_OUI_FROM_DATABASE=SHENZHEN LINNKING ELECTRONICS CO.,LTD OUI:0019F1* ID_OUI_FROM_DATABASE=Star Communication Network Technology Co.,Ltd OUI:0019F6* ID_OUI_FROM_DATABASE=Acconet (PTE) Ltd OUI:001A76* ID_OUI_FROM_DATABASE=SDT information Technology Co.,LTD. OUI:001A6F* ID_OUI_FROM_DATABASE=MI.TEL s.r.l. OUI:001A6A* ID_OUI_FROM_DATABASE=Tranzas, Inc. OUI:001A63* ID_OUI_FROM_DATABASE=Elster Solutions, LLC, OUI:001A5E* ID_OUI_FROM_DATABASE=Thincom Technology Co.,Ltd OUI:001A57* ID_OUI_FROM_DATABASE=Matrix Design Group, LLC OUI:001A5C* ID_OUI_FROM_DATABASE=Euchner GmbH+Co. KG OUI:001A50* ID_OUI_FROM_DATABASE=PheeNet Technology Corp. OUI:001A9D* ID_OUI_FROM_DATABASE=Skipper Wireless, Inc. OUI:001AA2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001A91* ID_OUI_FROM_DATABASE=FusionDynamic Ltd. OUI:001A96* ID_OUI_FROM_DATABASE=ECLER S.A. OUI:001A90* ID_OUI_FROM_DATABASE=Trópico Sistemas e Telecomunicações da Amazônia LTDA. OUI:001A8C* ID_OUI_FROM_DATABASE=Sophos Ltd OUI:001A85* ID_OUI_FROM_DATABASE=NV Michel Van de Wiele OUI:001A87* ID_OUI_FROM_DATABASE=Canhold International Limited OUI:001A86* ID_OUI_FROM_DATABASE=AdvancedIO Systems Inc OUI:0019B5* ID_OUI_FROM_DATABASE=Famar Fueguina S.A. OUI:0019BA* ID_OUI_FROM_DATABASE=Paradox Security Systems Ltd OUI:0019A2* ID_OUI_FROM_DATABASE=ORDYN TECHNOLOGIES OUI:0019AE* ID_OUI_FROM_DATABASE=Hopling Technologies b.v. OUI:0019A7* ID_OUI_FROM_DATABASE=ITU-T OUI:001996* ID_OUI_FROM_DATABASE=TurboChef Technologies Inc. OUI:00199B* ID_OUI_FROM_DATABASE=Diversified Technical Systems, Inc. OUI:001991* ID_OUI_FROM_DATABASE=avinfo OUI:00198A* ID_OUI_FROM_DATABASE=Northrop Grumman Systems Corp. OUI:00198C* ID_OUI_FROM_DATABASE=iXSea OUI:001985* ID_OUI_FROM_DATABASE=IT Watchdogs, Inc OUI:001972* ID_OUI_FROM_DATABASE=Plexus (Xiamen) Co.,ltd OUI:00196B* ID_OUI_FROM_DATABASE=Danpex Corporation OUI:001966* ID_OUI_FROM_DATABASE=Asiarock Technology Limited OUI:00195C* ID_OUI_FROM_DATABASE=Innotech Corporation OUI:001961* ID_OUI_FROM_DATABASE=Blaupunkt Embedded Systems GmbH OUI:0019DE* ID_OUI_FROM_DATABASE=MOBITEK OUI:0019EA* ID_OUI_FROM_DATABASE=TeraMage Technologies Co., Ltd. OUI:0019CB* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:0019D0* ID_OUI_FROM_DATABASE=Cathexis OUI:0019D7* ID_OUI_FROM_DATABASE=FORTUNETEK CO., LTD OUI:0019B3* ID_OUI_FROM_DATABASE=Stanford Research Systems OUI:001A44* ID_OUI_FROM_DATABASE=JWTrading Co., Ltd OUI:001A49* ID_OUI_FROM_DATABASE=Micro Vision Co.,LTD OUI:001A3D* ID_OUI_FROM_DATABASE=Ajin Vision Co.,Ltd OUI:001A31* ID_OUI_FROM_DATABASE=SCAN COIN Industries AB OUI:001A38* ID_OUI_FROM_DATABASE=Sanmina-SCI OUI:001A2C* ID_OUI_FROM_DATABASE=SATEC Co.,LTD OUI:001A27* ID_OUI_FROM_DATABASE=Ubistar OUI:0017AE* ID_OUI_FROM_DATABASE=GAI-Tronics OUI:0017A2* ID_OUI_FROM_DATABASE=Camrivox Ltd. OUI:0017A7* ID_OUI_FROM_DATABASE=Mobile Computing Promotion Consortium OUI:00179D* ID_OUI_FROM_DATABASE=Kelman Limited OUI:001791* ID_OUI_FROM_DATABASE=LinTech GmbH OUI:001796* ID_OUI_FROM_DATABASE=Rittmeyer AG OUI:001798* ID_OUI_FROM_DATABASE=Azonic Technology Co., LTD OUI:00178A* ID_OUI_FROM_DATABASE=DARTS TECHNOLOGIES CORP. OUI:00177E* ID_OUI_FROM_DATABASE=Meshcom Technologies Inc. OUI:001785* ID_OUI_FROM_DATABASE=Sparr Electronics Ltd OUI:001809* ID_OUI_FROM_DATABASE=CRESYN OUI:00180E* ID_OUI_FROM_DATABASE=Avega Systems OUI:001810* ID_OUI_FROM_DATABASE=IPTrade S.A. OUI:0017F6* ID_OUI_FROM_DATABASE=Pyramid Meriden Inc. OUI:0017FB* ID_OUI_FROM_DATABASE=FA OUI:0017FD* ID_OUI_FROM_DATABASE=Amulet Hotkey OUI:0017EF* ID_OUI_FROM_DATABASE=IBM Corp OUI:0017D7* ID_OUI_FROM_DATABASE=ION Geophysical Corporation Inc. OUI:0017DC* ID_OUI_FROM_DATABASE=DAEMYUNG ZERO1 OUI:0017DE* ID_OUI_FROM_DATABASE=Advantage Six Ltd OUI:0018C3* ID_OUI_FROM_DATABASE=CS Corporation OUI:0018CA* ID_OUI_FROM_DATABASE=Viprinet GmbH OUI:0018BE* ID_OUI_FROM_DATABASE=ANSA Corporation OUI:0018B2* ID_OUI_FROM_DATABASE=ADEUNIS RF OUI:0018B7* ID_OUI_FROM_DATABASE=D3 LED, LLC OUI:0018AB* ID_OUI_FROM_DATABASE=BEIJING LHWT MICROELECTRONICS INC. OUI:0018A6* ID_OUI_FROM_DATABASE=Persistent Systems, LLC OUI:001895* ID_OUI_FROM_DATABASE=Hansun Technologies Inc. OUI:00189A* ID_OUI_FROM_DATABASE=HANA Micron Inc. OUI:0018E7* ID_OUI_FROM_DATABASE=Cameo Communications, INC. OUI:0018EE* ID_OUI_FROM_DATABASE=Videology Imaging Solutions, Inc. OUI:0018E2* ID_OUI_FROM_DATABASE=Topdata Sistemas de Automacao Ltda OUI:0018DB* ID_OUI_FROM_DATABASE=EPL Technology Ltd OUI:0018E0* ID_OUI_FROM_DATABASE=ANAVEO OUI:0018CF* ID_OUI_FROM_DATABASE=Baldor Electric Company OUI:0018D4* ID_OUI_FROM_DATABASE=Unified Display Interface SIG OUI:00184A* ID_OUI_FROM_DATABASE=Catcher, Inc. OUI:00184C* ID_OUI_FROM_DATABASE=Bogen Communications OUI:001845* ID_OUI_FROM_DATABASE=Pulsar-Telecom LLC. OUI:00183E* ID_OUI_FROM_DATABASE=Digilent, Inc OUI:001828* ID_OUI_FROM_DATABASE=e2v technologies (UK) ltd. OUI:00182D* ID_OUI_FROM_DATABASE=Artec Design OUI:001821* ID_OUI_FROM_DATABASE=SINDORICOH OUI:001815* ID_OUI_FROM_DATABASE=GZ Technologies, Inc. OUI:00181C* ID_OUI_FROM_DATABASE=Exterity Limited OUI:001772* ID_OUI_FROM_DATABASE=ASTRO Strobel Kommunikationssysteme GmbH OUI:001777* ID_OUI_FROM_DATABASE=Obsidian Research Corporation OUI:00176E* ID_OUI_FROM_DATABASE=DUCATI SISTEMI OUI:001762* ID_OUI_FROM_DATABASE=Solar Technology, Inc. OUI:001769* ID_OUI_FROM_DATABASE=Cymphonix Corp OUI:00175D* ID_OUI_FROM_DATABASE=Dongseo system. OUI:00175B* ID_OUI_FROM_DATABASE=ACS Solutions Switzerland Ltd. OUI:001756* ID_OUI_FROM_DATABASE=Vinci Labs Oy OUI:00174F* ID_OUI_FROM_DATABASE=iCatch Inc. OUI:0017CD* ID_OUI_FROM_DATABASE=CEC Wireless R&D Ltd. OUI:0017D2* ID_OUI_FROM_DATABASE=THINLINX PTY LTD OUI:0017C6* ID_OUI_FROM_DATABASE=Cross Match Technologies Inc OUI:0017BA* ID_OUI_FROM_DATABASE=SEDO CO., LTD. OUI:0017BF* ID_OUI_FROM_DATABASE=Coherent Research Limited OUI:0017C1* ID_OUI_FROM_DATABASE=CM Precision Technology LTD. OUI:0017B3* ID_OUI_FROM_DATABASE=Aftek Infosys Limited OUI:00186A* ID_OUI_FROM_DATABASE=Global Link Digital Technology Co,.LTD OUI:00186F* ID_OUI_FROM_DATABASE=Setha Industria Eletronica LTDA OUI:001876* ID_OUI_FROM_DATABASE=WowWee Ltd. OUI:001869* ID_OUI_FROM_DATABASE=KINGJIM OUI:001864* ID_OUI_FROM_DATABASE=Eaton Corporation OUI:00185D* ID_OUI_FROM_DATABASE=TAIGUEN TECHNOLOGY (SHEN-ZHEN) CO., LTD. OUI:001851* ID_OUI_FROM_DATABASE=SWsoft OUI:001858* ID_OUI_FROM_DATABASE=TagMaster AB OUI:00189F* ID_OUI_FROM_DATABASE=Lenntek Corporation OUI:00188E* ID_OUI_FROM_DATABASE=Ekahau, Inc. OUI:001887* ID_OUI_FROM_DATABASE=Metasystem SpA OUI:001889* ID_OUI_FROM_DATABASE=WinNet Solutions Limited OUI:00187B* ID_OUI_FROM_DATABASE=4NSYS Co. Ltd. OUI:001661* ID_OUI_FROM_DATABASE=Novatium Solutions (P) Ltd OUI:001663* ID_OUI_FROM_DATABASE=KBT Mobile OUI:001668* ID_OUI_FROM_DATABASE=Eishin Electronics OUI:001662* ID_OUI_FROM_DATABASE=Liyuh Technology Ltd. OUI:00165C* ID_OUI_FROM_DATABASE=Trackflow Ltd OUI:001655* ID_OUI_FROM_DATABASE=FUHO TECHNOLOGY Co., LTD OUI:001650* ID_OUI_FROM_DATABASE=Herley General Microwave Israel. OUI:0015E4* ID_OUI_FROM_DATABASE=Zimmer Elektromedizin OUI:0015DA* ID_OUI_FROM_DATABASE=IRITEL A.D. OUI:0015DF* ID_OUI_FROM_DATABASE=Clivet S.p.A. OUI:0015D3* ID_OUI_FROM_DATABASE=Pantech&Curitel Communications, Inc. OUI:0015C7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0015C0* ID_OUI_FROM_DATABASE=DIGITAL TELEMEDIA CO.,LTD. OUI:0015BA* ID_OUI_FROM_DATABASE=iba AG OUI:00174A* ID_OUI_FROM_DATABASE=SOCOMEC OUI:001743* ID_OUI_FROM_DATABASE=Deck Srl OUI:00173D* ID_OUI_FROM_DATABASE=Neology OUI:00173E* ID_OUI_FROM_DATABASE=LeucotronEquipamentos Ltda. OUI:001738* ID_OUI_FROM_DATABASE=International Business Machines OUI:00172C* ID_OUI_FROM_DATABASE=TAEJIN INFOTECH OUI:001720* ID_OUI_FROM_DATABASE=Image Sensing Systems, Inc. OUI:001725* ID_OUI_FROM_DATABASE=Liquid Computing OUI:001701* ID_OUI_FROM_DATABASE=KDE, Inc. OUI:001703* ID_OUI_FROM_DATABASE=MOSDAN Internation Co.,Ltd OUI:0016FC* ID_OUI_FROM_DATABASE=TOHKEN CO.,LTD. OUI:0016F0* ID_OUI_FROM_DATABASE=Dell OUI:0016F5* ID_OUI_FROM_DATABASE=Dalian Golden Hualu Digital Technology Co.,Ltd OUI:0016E9* ID_OUI_FROM_DATABASE=Tiba Medical Inc OUI:0016E4* ID_OUI_FROM_DATABASE=VANGUARD SECURITY ENGINEERING CORP. OUI:0016DD* ID_OUI_FROM_DATABASE=Gigabeam Corporation OUI:0016E2* ID_OUI_FROM_DATABASE=American Fibertek, Inc. OUI:0016D3* ID_OUI_FROM_DATABASE=Wistron Corporation OUI:0016D8* ID_OUI_FROM_DATABASE=Senea AB OUI:00169C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00169E* ID_OUI_FROM_DATABASE=TV One Ltd OUI:0016A3* ID_OUI_FROM_DATABASE=Ingeteam Transmission&Distribution, S.A. OUI:001690* ID_OUI_FROM_DATABASE=J-TEK INCORPORATION OUI:001697* ID_OUI_FROM_DATABASE=NEC Corporation OUI:001689* ID_OUI_FROM_DATABASE=Pilkor Electronics Co., Ltd OUI:00168B* ID_OUI_FROM_DATABASE=Paralan Corporation OUI:001684* ID_OUI_FROM_DATABASE=Donjin Co.,Ltd. OUI:00167D* ID_OUI_FROM_DATABASE=Sky-Line Information Co., Ltd. OUI:001678* ID_OUI_FROM_DATABASE=SHENZHEN BAOAN GAOKE ELECTRONICS CO., LTD OUI:001649* ID_OUI_FROM_DATABASE=SetOne GmbH OUI:00163F* ID_OUI_FROM_DATABASE=CReTE SYSTEMS Inc. OUI:001638* ID_OUI_FROM_DATABASE=TECOM Co., Ltd. OUI:001633* ID_OUI_FROM_DATABASE=Oxford Diagnostics Ltd. OUI:00162C* ID_OUI_FROM_DATABASE=Xanboo OUI:001627* ID_OUI_FROM_DATABASE=embedded-logic DESIGN AND MORE GmbH OUI:001619* ID_OUI_FROM_DATABASE=Lancelan Technologies S.L. OUI:001614* ID_OUI_FROM_DATABASE=Picosecond Pulse Labs OUI:001719* ID_OUI_FROM_DATABASE=Audiocodes USA, Inc OUI:00171E* ID_OUI_FROM_DATABASE=Theo Benning GmbH & Co. KG OUI:001712* ID_OUI_FROM_DATABASE=ISCO International OUI:00170D* ID_OUI_FROM_DATABASE=Dust Networks Inc. OUI:00160F* ID_OUI_FROM_DATABASE=BADGER METER INC OUI:00160A* ID_OUI_FROM_DATABASE=SWEEX Europe BV OUI:001603* ID_OUI_FROM_DATABASE=COOLKSKY Co., LTD OUI:0015FC* ID_OUI_FROM_DATABASE=Littelfuse Startco OUI:0015F7* ID_OUI_FROM_DATABASE=Wintecronics Ltd. OUI:0015F0* ID_OUI_FROM_DATABASE=EGO BV OUI:0015EA* ID_OUI_FROM_DATABASE=Tellumat (Pty) Ltd OUI:0016C5* ID_OUI_FROM_DATABASE=Shenzhen Xing Feng Industry Co.,Ltd OUI:0016C7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0016CC* ID_OUI_FROM_DATABASE=Xcute Mobile Corp. OUI:0016C0* ID_OUI_FROM_DATABASE=Semtech Corporation OUI:0016B9* ID_OUI_FROM_DATABASE=ProCurve Networking OUI:0016B4* ID_OUI_FROM_DATABASE=Private OUI:0016A8* ID_OUI_FROM_DATABASE=CWT CO., LTD. OUI:0016AD* ID_OUI_FROM_DATABASE=BT-Links Company Limited OUI:001553* ID_OUI_FROM_DATABASE=Cytyc Corporation OUI:001555* ID_OUI_FROM_DATABASE=DFM GmbH OUI:00154E* ID_OUI_FROM_DATABASE=IEC OUI:001547* ID_OUI_FROM_DATABASE=AiZen Solutions Inc. OUI:001542* ID_OUI_FROM_DATABASE=MICROHARD S.R.L. OUI:00153B* ID_OUI_FROM_DATABASE=EMH metering GmbH & Co. KG OUI:001534* ID_OUI_FROM_DATABASE=A Beltrónica-Companhia de Comunicações, Lda OUI:001440* ID_OUI_FROM_DATABASE=ATOMIC Corporation OUI:001439* ID_OUI_FROM_DATABASE=Blonder Tongue Laboratories, Inc. OUI:001434* ID_OUI_FROM_DATABASE=Keri Systems, Inc OUI:00142D* ID_OUI_FROM_DATABASE=Toradex AG OUI:001426* ID_OUI_FROM_DATABASE=NL Technology OUI:001421* ID_OUI_FROM_DATABASE=Total Wireless Technologies Pte. Ltd. OUI:00141C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001583* ID_OUI_FROM_DATABASE=IVT corporation OUI:00157E* ID_OUI_FROM_DATABASE=Weidmüller Interface GmbH & Co. KG OUI:001579* ID_OUI_FROM_DATABASE=Lunatone Industrielle Elektronik GmbH OUI:001574* ID_OUI_FROM_DATABASE=Horizon Semiconductors Ltd. OUI:00156D* ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. OUI:001566* ID_OUI_FROM_DATABASE=A-First Technology Co., Ltd. OUI:001561* ID_OUI_FROM_DATABASE=JJPlus Corporation OUI:00155A* ID_OUI_FROM_DATABASE=DAINIPPON PHARMACEUTICAL CO., LTD. OUI:001554* ID_OUI_FROM_DATABASE=Atalum Wireless S.A. OUI:001528* ID_OUI_FROM_DATABASE=Beacon Medical Products LLC d.b.a. BeaconMedaes OUI:001521* ID_OUI_FROM_DATABASE=Horoquartz OUI:001523* ID_OUI_FROM_DATABASE=Meteor Communications Corporation OUI:001522* ID_OUI_FROM_DATABASE=Dea Security OUI:00151C* ID_OUI_FROM_DATABASE=LENECO OUI:001512* ID_OUI_FROM_DATABASE=Zurich University of Applied Sciences OUI:00150B* ID_OUI_FROM_DATABASE=SAGE INFOTECH LTD. OUI:001506* ID_OUI_FROM_DATABASE=Neo Photonics OUI:0014FF* ID_OUI_FROM_DATABASE=Precise Automation, Inc. OUI:0014F8* ID_OUI_FROM_DATABASE=Scientific Atlanta OUI:0014F3* ID_OUI_FROM_DATABASE=ViXS Systems Inc OUI:0014E7* ID_OUI_FROM_DATABASE=Stolinx,. Inc OUI:0014EC* ID_OUI_FROM_DATABASE=Acro Telecom OUI:0014E2* ID_OUI_FROM_DATABASE=datacom systems inc. OUI:0014D6* ID_OUI_FROM_DATABASE=Jeongmin Electronics Co.,Ltd. OUI:0014DB* ID_OUI_FROM_DATABASE=Elma Trenew Electronic GmbH OUI:0014DD* ID_OUI_FROM_DATABASE=Covergence Inc. OUI:0014DC* ID_OUI_FROM_DATABASE=Communication System Design & Manufacturing (CSDM) OUI:0014CF* ID_OUI_FROM_DATABASE=INVISIO Communications OUI:0014CA* ID_OUI_FROM_DATABASE=Key Radio Systems Limited OUI:0014C3* ID_OUI_FROM_DATABASE=Seagate Technology OUI:0014BC* ID_OUI_FROM_DATABASE=SYNECTIC TELECOM EXPORTS PVT. LTD. OUI:0014B7* ID_OUI_FROM_DATABASE=AR Infotek Inc. OUI:0014AD* ID_OUI_FROM_DATABASE=Gassner Wiege- und Meßtechnik GmbH OUI:0014B2* ID_OUI_FROM_DATABASE=mCubelogics Corporation OUI:0014A6* ID_OUI_FROM_DATABASE=Teranetics, Inc. OUI:00149F* ID_OUI_FROM_DATABASE=System and Chips, Inc. OUI:0014A1* ID_OUI_FROM_DATABASE=Synchronous Communication Corp OUI:001470* ID_OUI_FROM_DATABASE=Prokom Software SA OUI:001469* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001462* ID_OUI_FROM_DATABASE=Digiwell Technology, inc OUI:00145D* ID_OUI_FROM_DATABASE=WJ Communications, Inc. OUI:001450* ID_OUI_FROM_DATABASE=Heim Systems GmbH OUI:001456* ID_OUI_FROM_DATABASE=Edge Products OUI:00144C* ID_OUI_FROM_DATABASE=General Meters Corp. OUI:001445* ID_OUI_FROM_DATABASE=Telefon-Gradnja d.o.o. OUI:001447* ID_OUI_FROM_DATABASE=BOAZ Inc. OUI:001446* ID_OUI_FROM_DATABASE=SuperVision Solutions LLC OUI:0015B3* ID_OUI_FROM_DATABASE=Caretech AB OUI:0015A9* ID_OUI_FROM_DATABASE=KWANG WOO I&C CO.,LTD OUI:00159D* ID_OUI_FROM_DATABASE=Tripp Lite OUI:001591* ID_OUI_FROM_DATABASE=RLW Inc. OUI:00158A* ID_OUI_FROM_DATABASE=SURECOM Technology Corp. OUI:00158F* ID_OUI_FROM_DATABASE=NTT Advanced Technology Corporation OUI:001590* ID_OUI_FROM_DATABASE=Hectronic GmbH OUI:0014A0* ID_OUI_FROM_DATABASE=Accsense, Inc. OUI:001493* ID_OUI_FROM_DATABASE=Systimax Solutions OUI:00148E* ID_OUI_FROM_DATABASE=Tele Power Inc. OUI:001487* ID_OUI_FROM_DATABASE=American Technology Integrators OUI:001482* ID_OUI_FROM_DATABASE=Aurora Networks OUI:001481* ID_OUI_FROM_DATABASE=Multilink Inc OUI:00147C* ID_OUI_FROM_DATABASE=3Com Ltd OUI:001475* ID_OUI_FROM_DATABASE=Wiline Networks, Inc. OUI:0012E7* ID_OUI_FROM_DATABASE=Projectek Networking Electronics Corp. OUI:0012E8* ID_OUI_FROM_DATABASE=Fraunhofer IMS OUI:0012DB* ID_OUI_FROM_DATABASE=ZIEHL industrie-elektronik GmbH + Co KG OUI:0012E2* ID_OUI_FROM_DATABASE=ALAXALA Networks Corporation OUI:0012D6* ID_OUI_FROM_DATABASE=Jiangsu Yitong High-Tech Co.,Ltd OUI:0012D5* ID_OUI_FROM_DATABASE=Motion Reality Inc. OUI:0012C3* ID_OUI_FROM_DATABASE=WIT S.A. OUI:0013E5* ID_OUI_FROM_DATABASE=TENOSYS, INC. OUI:0013EA* ID_OUI_FROM_DATABASE=Kamstrup A/S OUI:0013DE* ID_OUI_FROM_DATABASE=Adapt4, LLC OUI:0013D7* ID_OUI_FROM_DATABASE=SPIDCOM Technologies SA OUI:0013D8* ID_OUI_FROM_DATABASE=Princeton Instruments OUI:0013CF* ID_OUI_FROM_DATABASE=4Access Communications OUI:0013D2* ID_OUI_FROM_DATABASE=PAGE IBERICA, S.A. OUI:0013C9* ID_OUI_FROM_DATABASE=Beyond Achieve Enterprises Ltd. OUI:0013C2* ID_OUI_FROM_DATABASE=WACOM Co.,Ltd OUI:0013BD* ID_OUI_FROM_DATABASE=HYMATOM SA OUI:0013B8* ID_OUI_FROM_DATABASE=RyCo Electronic Systems Limited OUI:00134E* ID_OUI_FROM_DATABASE=Valox Systems, Inc. OUI:001353* ID_OUI_FROM_DATABASE=HYDAC Filtertechnik GMBH OUI:00134D* ID_OUI_FROM_DATABASE=Inepro BV OUI:001347* ID_OUI_FROM_DATABASE=Red Lion Controls, LP OUI:00133B* ID_OUI_FROM_DATABASE=Speed Dragon Multimedia Limited OUI:001340* ID_OUI_FROM_DATABASE=AD.EL s.r.l. OUI:00132E* ID_OUI_FROM_DATABASE=ITian Coporation OUI:001328* ID_OUI_FROM_DATABASE=Westech Korea Inc., OUI:00132D* ID_OUI_FROM_DATABASE=iWise Communications OUI:001334* ID_OUI_FROM_DATABASE=Arkados, Inc. OUI:0013B3* ID_OUI_FROM_DATABASE=Ecom Communications Technology Co., Ltd. OUI:0013AC* ID_OUI_FROM_DATABASE=Sunmyung Electronics Co., LTD OUI:0013A6* ID_OUI_FROM_DATABASE=Extricom Ltd OUI:0013A5* ID_OUI_FROM_DATABASE=General Solutions, LTD. OUI:0013A0* ID_OUI_FROM_DATABASE=ALGOSYSTEM Co., Ltd. OUI:001399* ID_OUI_FROM_DATABASE=STAC Corporation. OUI:001393* ID_OUI_FROM_DATABASE=Panta Systems, Inc. OUI:001394* ID_OUI_FROM_DATABASE=Infohand Co.,Ltd OUI:00138D* ID_OUI_FROM_DATABASE=Kinghold OUI:0012C8* ID_OUI_FROM_DATABASE=Perfect tech OUI:0012B9* ID_OUI_FROM_DATABASE=Fusion Digital Technology OUI:0012BE* ID_OUI_FROM_DATABASE=Astek Corporation OUI:0012AC* ID_OUI_FROM_DATABASE=ONTIMETEK INC. OUI:0012AB* ID_OUI_FROM_DATABASE=WiLife, Inc. OUI:0012B2* ID_OUI_FROM_DATABASE=AVOLITES LTD. OUI:0012A6* ID_OUI_FROM_DATABASE=Dolby Australia OUI:001378* ID_OUI_FROM_DATABASE=Qsan Technology, Inc. OUI:00137D* ID_OUI_FROM_DATABASE=Dynalab, Inc. OUI:001384* ID_OUI_FROM_DATABASE=Advanced Motion Controls OUI:00137E* ID_OUI_FROM_DATABASE=CorEdge Networks, Inc. OUI:00136C* ID_OUI_FROM_DATABASE=TomTom OUI:001365* ID_OUI_FROM_DATABASE=Nortel OUI:00136B* ID_OUI_FROM_DATABASE=E-TEC OUI:001359* ID_OUI_FROM_DATABASE=ProTelevision Technologies A/S OUI:00135E* ID_OUI_FROM_DATABASE=EAB/RWI/K OUI:00129F* ID_OUI_FROM_DATABASE=RAE Systems OUI:001299* ID_OUI_FROM_DATABASE=Ktech Telecommunications Inc OUI:00129A* ID_OUI_FROM_DATABASE=IRT Electronics Pty Ltd OUI:00128C* ID_OUI_FROM_DATABASE=Woodward Governor OUI:001293* ID_OUI_FROM_DATABASE=GE Energy OUI:001287* ID_OUI_FROM_DATABASE=Digital Everywhere Unterhaltungselektronik GmbH OUI:001280* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00131E* ID_OUI_FROM_DATABASE=Peiker acustic GmbH & Co. KG OUI:001323* ID_OUI_FROM_DATABASE=Cap Co., Ltd. OUI:00130B* ID_OUI_FROM_DATABASE=Mextal B.V. OUI:001312* ID_OUI_FROM_DATABASE=Amedia Networks Inc. OUI:0012F8* ID_OUI_FROM_DATABASE=WNI Resources, LLC OUI:0012FF* ID_OUI_FROM_DATABASE=Lely Industries N.V. OUI:001304* ID_OUI_FROM_DATABASE=Flaircomm Technologies Co. LTD OUI:001410* ID_OUI_FROM_DATABASE=Suzhou Keda Technology CO.,Ltd OUI:001417* ID_OUI_FROM_DATABASE=RSE Informations Technologie GmbH OUI:001408* ID_OUI_FROM_DATABASE=Eka Systems Inc. OUI:001402* ID_OUI_FROM_DATABASE=kk-electronic a/s OUI:001401* ID_OUI_FROM_DATABASE=Rivertree Networks Corp. OUI:0013FB* ID_OUI_FROM_DATABASE=RKC INSTRUMENT INC. OUI:0013F4* ID_OUI_FROM_DATABASE=Psitek (Pty) Ltd OUI:0013EF* ID_OUI_FROM_DATABASE=Kingjon Digital Technology Co.,Ltd OUI:0011F7* ID_OUI_FROM_DATABASE=Shenzhen Forward Industry Co., Ltd OUI:0011F2* ID_OUI_FROM_DATABASE=Institute of Network Technologies OUI:0011EB* ID_OUI_FROM_DATABASE=Innovative Integration OUI:0011E6* ID_OUI_FROM_DATABASE=Scientific Atlanta OUI:0011E5* ID_OUI_FROM_DATABASE=KCodes Corporation OUI:0011DF* ID_OUI_FROM_DATABASE=Current Energy OUI:0011D3* ID_OUI_FROM_DATABASE=NextGenTel Holding ASA OUI:00110E* ID_OUI_FROM_DATABASE=Tsurusaki Sealand Transportation Co. Ltd. OUI:001115* ID_OUI_FROM_DATABASE=EPIN Technologies, Inc. OUI:001114* ID_OUI_FROM_DATABASE=EverFocus Electronics Corp. OUI:001107* ID_OUI_FROM_DATABASE=RGB Networks Inc. OUI:001108* ID_OUI_FROM_DATABASE=Orbital Data Corporation OUI:001102* ID_OUI_FROM_DATABASE=Aurora Multimedia Corp. OUI:000FFC* ID_OUI_FROM_DATABASE=Merit Li-Lin Ent. OUI:000FDA* ID_OUI_FROM_DATABASE=YAZAKI CORPORATION OUI:000FF3* ID_OUI_FROM_DATABASE=Jung Myoung Communications&Technology OUI:0011A2* ID_OUI_FROM_DATABASE=Manufacturing Technology Inc OUI:00119B* ID_OUI_FROM_DATABASE=Telesynergy Research Inc. OUI:00118C* ID_OUI_FROM_DATABASE=Missouri Department of Transportation OUI:001191* ID_OUI_FROM_DATABASE=CTS-Clima Temperatur Systeme GmbH OUI:00118B* ID_OUI_FROM_DATABASE=Alcatel-Lucent, Enterprise Business Group OUI:001196* ID_OUI_FROM_DATABASE=Actuality Systems, Inc. OUI:00117E* ID_OUI_FROM_DATABASE=Progeny, A division of Midmark Corp OUI:001179* ID_OUI_FROM_DATABASE=Singular Technology Co. Ltd. OUI:001172* ID_OUI_FROM_DATABASE=COTRON CORPORATION OUI:001166* ID_OUI_FROM_DATABASE=Taelim Electronics Co., Ltd. OUI:00116B* ID_OUI_FROM_DATABASE=Digital Data Communications Asia Co.,Ltd OUI:00116C* ID_OUI_FROM_DATABASE=Nanwang Multimedia Inc.,Ltd OUI:001162* ID_OUI_FROM_DATABASE=STAR MICRONICS CO.,LTD. OUI:001161* ID_OUI_FROM_DATABASE=NetStreams, LLC OUI:001155* ID_OUI_FROM_DATABASE=Sevis Systems OUI:00115C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001147* ID_OUI_FROM_DATABASE=Secom-Industry co.LTD. OUI:00114C* ID_OUI_FROM_DATABASE=caffeina applied research ltd. OUI:001274* ID_OUI_FROM_DATABASE=NIT lab OUI:00127A* ID_OUI_FROM_DATABASE=Sanyu Industry Co.,Ltd. OUI:00126D* ID_OUI_FROM_DATABASE=University of California, Berkeley OUI:001268* ID_OUI_FROM_DATABASE=IPS d.o.o. OUI:001267* ID_OUI_FROM_DATABASE=Panasonic Corporation OUI:001261* ID_OUI_FROM_DATABASE=Adaptix, Inc OUI:001257* ID_OUI_FROM_DATABASE=LeapComm Communication Technologies Inc. OUI:001222* ID_OUI_FROM_DATABASE=Skardin (UK) Ltd OUI:001227* ID_OUI_FROM_DATABASE=Franklin Electric Co., Inc. OUI:00121B* ID_OUI_FROM_DATABASE=Sound Devices, LLC OUI:001221* ID_OUI_FROM_DATABASE=B.Braun Melsungen AG OUI:001214* ID_OUI_FROM_DATABASE=Koenig & Bauer AG OUI:00120F* ID_OUI_FROM_DATABASE=IEEE 802.3 OUI:001208* ID_OUI_FROM_DATABASE=Gantner Instruments GmbH OUI:001201* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001202* ID_OUI_FROM_DATABASE=Decrane Aerospace - Audio International Inc. OUI:0011FC* ID_OUI_FROM_DATABASE=HARTING Electric Gmbh & Co.KG OUI:0011C7* ID_OUI_FROM_DATABASE=Raymarine UK Ltd OUI:0011CC* ID_OUI_FROM_DATABASE=Guangzhou Jinpeng Group Co.,Ltd. OUI:0011B5* ID_OUI_FROM_DATABASE=Shenzhen Powercom Co.,Ltd OUI:0011BA* ID_OUI_FROM_DATABASE=Elexol Pty Ltd OUI:0011C1* ID_OUI_FROM_DATABASE=4P MOBILE DATA PROCESSING OUI:0011A8* ID_OUI_FROM_DATABASE=Quest Technologies OUI:0011A7* ID_OUI_FROM_DATABASE=Infilco Degremont Inc. OUI:001250* ID_OUI_FROM_DATABASE=Tokyo Aircaft Instrument Co., Ltd. OUI:00124B* ID_OUI_FROM_DATABASE=Texas Instruments OUI:001244* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001238* ID_OUI_FROM_DATABASE=SetaBox Technology Co., Ltd. OUI:00123D* ID_OUI_FROM_DATABASE=GES Co, Ltd OUI:00123E* ID_OUI_FROM_DATABASE=ERUNE technology Co., Ltd. OUI:00122C* ID_OUI_FROM_DATABASE=Soenen Controls N.V. OUI:001231* ID_OUI_FROM_DATABASE=Motion Control Systems, Inc. OUI:001146* ID_OUI_FROM_DATABASE=Telecard-Pribor Ltd OUI:001140* ID_OUI_FROM_DATABASE=Nanometrics Inc. OUI:001139* ID_OUI_FROM_DATABASE=STOEBER ANTRIEBSTECHNIK GmbH + Co. KG. OUI:00113A* ID_OUI_FROM_DATABASE=SHINBORAM OUI:001134* ID_OUI_FROM_DATABASE=MediaCell, Inc. OUI:001127* ID_OUI_FROM_DATABASE=TASI, Inc OUI:00112A* ID_OUI_FROM_DATABASE=Niko NV OUI:001121* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000EBB* ID_OUI_FROM_DATABASE=Everbee Networks OUI:000EB4* ID_OUI_FROM_DATABASE=GUANGZHOU GAOKE COMMUNICATIONS TECHNOLOGY CO.LTD. OUI:000EAE* ID_OUI_FROM_DATABASE=GAWELL TECHNOLOGIES CORP. OUI:000EA8* ID_OUI_FROM_DATABASE=United Technologists Europe Limited OUI:000EAD* ID_OUI_FROM_DATABASE=Metanoia Technologies, Inc. OUI:000EA1* ID_OUI_FROM_DATABASE=Formosa Teletek Corporation OUI:000E9C* ID_OUI_FROM_DATABASE=Benchmark Electronics OUI:000E9B* ID_OUI_FROM_DATABASE=Ambit Microsystems Corporation OUI:000E8E* ID_OUI_FROM_DATABASE=SparkLAN Communications, Inc. OUI:000E95* ID_OUI_FROM_DATABASE=Fujiya Denki Seisakusho Co.,Ltd. OUI:000FC1* ID_OUI_FROM_DATABASE=WAVE Corporation OUI:000FC8* ID_OUI_FROM_DATABASE=Chantry Networks OUI:000FC7* ID_OUI_FROM_DATABASE=Dionica R&D Ltd. OUI:000FBA* ID_OUI_FROM_DATABASE=Tevebox AB OUI:000FA7* ID_OUI_FROM_DATABASE=Raptor Networks Technology OUI:000FAE* ID_OUI_FROM_DATABASE=E2O Communications OUI:000FA8* ID_OUI_FROM_DATABASE=Photometrics, Inc. OUI:000F9A* ID_OUI_FROM_DATABASE=Synchrony, Inc. OUI:000FA2* ID_OUI_FROM_DATABASE=2xWireless OUI:000E89* ID_OUI_FROM_DATABASE=CLEMATIC OUI:000E82* ID_OUI_FROM_DATABASE=Commtech Wireless OUI:000E7C* ID_OUI_FROM_DATABASE=Televes S.A. OUI:000E76* ID_OUI_FROM_DATABASE=GEMSOC INNOVISION INC. OUI:000E7B* ID_OUI_FROM_DATABASE=Toshiba OUI:000E6E* ID_OUI_FROM_DATABASE=MAT S.A. (Mircrelec Advanced Technology) OUI:000E72* ID_OUI_FROM_DATABASE=CTS electronics OUI:000E68* ID_OUI_FROM_DATABASE=E-TOP Network Technology Inc. OUI:000E67* ID_OUI_FROM_DATABASE=Eltis Microelectronics Ltd. OUI:000E62* ID_OUI_FROM_DATABASE=Nortel Networks OUI:000FE7* ID_OUI_FROM_DATABASE=Lutron Electronics Co., Inc. OUI:000FEC* ID_OUI_FROM_DATABASE=ARKUS Inc. OUI:000FE0* ID_OUI_FROM_DATABASE=NComputing Co.,Ltd. OUI:000FD4* ID_OUI_FROM_DATABASE=Soundcraft OUI:000FD9* ID_OUI_FROM_DATABASE=FlexDSL Telecommunications AG OUI:000FCD* ID_OUI_FROM_DATABASE=Nortel Networks OUI:000EEA* ID_OUI_FROM_DATABASE=Shadong Luneng Jicheng Electronics,Co.,Ltd OUI:000EDD* ID_OUI_FROM_DATABASE=SHURE INCORPORATED OUI:000EE4* ID_OUI_FROM_DATABASE=BOE TECHNOLOGY GROUP CO.,LTD OUI:000ED8* ID_OUI_FROM_DATABASE=Positron Access Solutions Corp OUI:000ECD* ID_OUI_FROM_DATABASE=SKOV A/S OUI:000ECE* ID_OUI_FROM_DATABASE=S.I.T.T.I. S.p.A. OUI:000ED3* ID_OUI_FROM_DATABASE=Epicenter, Inc. OUI:000EC0* ID_OUI_FROM_DATABASE=Nortel Networks OUI:000EC7* ID_OUI_FROM_DATABASE=Motorola Korea OUI:000F93* ID_OUI_FROM_DATABASE=Landis+Gyr Ltd. OUI:000F94* ID_OUI_FROM_DATABASE=Genexis BV OUI:000F8E* ID_OUI_FROM_DATABASE=DONGYANG TELECOM CO.,LTD. OUI:000F87* ID_OUI_FROM_DATABASE=Maxcess International OUI:000F82* ID_OUI_FROM_DATABASE=Mortara Instrument, Inc. OUI:000F81* ID_OUI_FROM_DATABASE=PAL Pacific Inc. OUI:000F74* ID_OUI_FROM_DATABASE=Qamcom Technology AB OUI:000F7B* ID_OUI_FROM_DATABASE=Arce Sistemas, S.A. OUI:000F68* ID_OUI_FROM_DATABASE=Vavic Network Technology, Inc. OUI:000F6F* ID_OUI_FROM_DATABASE=FTA Communication Technologies OUI:000F62* ID_OUI_FROM_DATABASE=Alcatel Bell Space N.V. OUI:000F5C* ID_OUI_FROM_DATABASE=Day One Digital Media Limited OUI:000F55* ID_OUI_FROM_DATABASE=Datawire Communication Networks Inc. OUI:000F49* ID_OUI_FROM_DATABASE=Northover Solutions Limited OUI:000F50* ID_OUI_FROM_DATABASE=StreamScale Limited OUI:000F42* ID_OUI_FROM_DATABASE=Xalyo Systems OUI:000F1C* ID_OUI_FROM_DATABASE=DigitAll World Co., Ltd OUI:000F0A* ID_OUI_FROM_DATABASE=Clear Edge Networks OUI:000F09* ID_OUI_FROM_DATABASE=Private OUI:000F03* ID_OUI_FROM_DATABASE=COM&C CO., LTD OUI:000EF7* ID_OUI_FROM_DATABASE=Vulcan Portals Inc OUI:000EFC* ID_OUI_FROM_DATABASE=JTAG Technologies B.V. OUI:000EE9* ID_OUI_FROM_DATABASE=WayTech Development, Inc. OUI:000EF0* ID_OUI_FROM_DATABASE=Festo AG & Co. KG OUI:000F4F* ID_OUI_FROM_DATABASE=Cadmus Technology Ltd OUI:000F35* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000F2E* ID_OUI_FROM_DATABASE=Megapower International Corp. OUI:000F29* ID_OUI_FROM_DATABASE=Augmentix Corporation OUI:000F22* ID_OUI_FROM_DATABASE=Helius, Inc. OUI:000F0F* ID_OUI_FROM_DATABASE=Real ID Technology Co., Ltd. OUI:000F16* ID_OUI_FROM_DATABASE=JAY HOW TECHNOLOGY CO., OUI:000F1B* ID_OUI_FROM_DATABASE=Ego Systems Inc. OUI:000D74* ID_OUI_FROM_DATABASE=Sand Network Systems, Inc. OUI:000D7B* ID_OUI_FROM_DATABASE=Consensys Computers Inc. OUI:000D6E* ID_OUI_FROM_DATABASE=K-Patents Oy OUI:000D68* ID_OUI_FROM_DATABASE=Vinci Systems, Inc. OUI:000D6D* ID_OUI_FROM_DATABASE=K-Tech Devices Corp. OUI:000D5B* ID_OUI_FROM_DATABASE=Smart Empire Investments Limited OUI:000D5C* ID_OUI_FROM_DATABASE=Robert Bosch GmbH, VT-ATMO OUI:000D61* ID_OUI_FROM_DATABASE=Giga-Byte Technology Co., Ltd. OUI:000D55* ID_OUI_FROM_DATABASE=SANYCOM Technology Co.,Ltd OUI:000D49* ID_OUI_FROM_DATABASE=Triton Systems of Delaware, Inc. OUI:000D4E* ID_OUI_FROM_DATABASE=NDR Co.,LTD. OUI:000E5B* ID_OUI_FROM_DATABASE=ParkerVision - Direct2Data OUI:000E55* ID_OUI_FROM_DATABASE=AUVITRAN OUI:000E56* ID_OUI_FROM_DATABASE=4G Systems GmbH & Co. KG OUI:000E4F* ID_OUI_FROM_DATABASE=Trajet GmbH OUI:000E48* ID_OUI_FROM_DATABASE=Lipman TransAction Solutions OUI:000E43* ID_OUI_FROM_DATABASE=G-Tek Electronics Sdn. Bhd. OUI:000E34* ID_OUI_FROM_DATABASE=NexGen City, LP OUI:000E3B* ID_OUI_FROM_DATABASE=Hawking Technologies, Inc. OUI:000E2F* ID_OUI_FROM_DATABASE=Roche Diagnostics GmbH OUI:000DFB* ID_OUI_FROM_DATABASE=Komax AG OUI:000DE9* ID_OUI_FROM_DATABASE=Napatech Aps OUI:000DEE* ID_OUI_FROM_DATABASE=Andrew RF Power Amplifier Group OUI:000DE2* ID_OUI_FROM_DATABASE=CMZ Sistemi Elettronici OUI:000DDC* ID_OUI_FROM_DATABASE=VAC OUI:000DD6* ID_OUI_FROM_DATABASE=ITI LTD OUI:000DDB* ID_OUI_FROM_DATABASE=AIRWAVE TECHNOLOGIES INC. OUI:000DCA* ID_OUI_FROM_DATABASE=Tait Electronics OUI:000DCF* ID_OUI_FROM_DATABASE=Cidra Corp. OUI:000E28* ID_OUI_FROM_DATABASE=Dynamic Ratings P/L OUI:000E22* ID_OUI_FROM_DATABASE=Private OUI:000E21* ID_OUI_FROM_DATABASE=MTU Friedrichshafen GmbH OUI:000E15* ID_OUI_FROM_DATABASE=Tadlys LTD OUI:000E1C* ID_OUI_FROM_DATABASE=Hach Company OUI:000E0D* ID_OUI_FROM_DATABASE=Hesch Schröder GmbH OUI:000E10* ID_OUI_FROM_DATABASE=C-guys, Inc. OUI:000DF5* ID_OUI_FROM_DATABASE=Teletronics International Inc. OUI:000DFC* ID_OUI_FROM_DATABASE=ITFOR Inc. OUI:000E01* ID_OUI_FROM_DATABASE=ASIP Technologies Inc. OUI:000CF0* ID_OUI_FROM_DATABASE=M & N GmbH OUI:000CF5* ID_OUI_FROM_DATABASE=InfoExpress OUI:000CE0* ID_OUI_FROM_DATABASE=Trek Diagnostics Inc. OUI:000CE4* ID_OUI_FROM_DATABASE=NeuroCom International, Inc. OUI:000CE9* ID_OUI_FROM_DATABASE=BLOOMBERG L.P. OUI:000CCE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000CD4* ID_OUI_FROM_DATABASE=Positron Public Safety Systems inc. OUI:000CCD* ID_OUI_FROM_DATABASE=IEC - TC57 OUI:000D15* ID_OUI_FROM_DATABASE=Voipac s.r.o. OUI:000D16* ID_OUI_FROM_DATABASE=UHS Systems Pty Ltd OUI:000D1B* ID_OUI_FROM_DATABASE=Kyoto Electronics Manufacturing Co., Ltd. OUI:000D0F* ID_OUI_FROM_DATABASE=Finlux Ltd OUI:000D03* ID_OUI_FROM_DATABASE=Matrics, Inc. OUI:000D08* ID_OUI_FROM_DATABASE=AboveCable, Inc. OUI:000CFC* ID_OUI_FROM_DATABASE=S2io Technologies Corp OUI:000CF6* ID_OUI_FROM_DATABASE=Sitecom Europe BV OUI:000DA3* ID_OUI_FROM_DATABASE=Emerging Technologies Limited OUI:000D9C* ID_OUI_FROM_DATABASE=Elan GmbH & Co KG OUI:000D96* ID_OUI_FROM_DATABASE=Vtera Technology Inc. OUI:000D95* ID_OUI_FROM_DATABASE=Opti-cell, Inc. OUI:000D90* ID_OUI_FROM_DATABASE=Factum Electronics AB OUI:000D89* ID_OUI_FROM_DATABASE=Bils Technology Inc OUI:000D80* ID_OUI_FROM_DATABASE=Online Development Inc OUI:000DC9* ID_OUI_FROM_DATABASE=THALES Elektronik Systeme GmbH OUI:000DC3* ID_OUI_FROM_DATABASE=First Communication, Inc. OUI:000DBC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000DB7* ID_OUI_FROM_DATABASE=SANKO ELECTRIC CO,.LTD OUI:000DB0* ID_OUI_FROM_DATABASE=Olym-tech Co.,Ltd. OUI:000DA8* ID_OUI_FROM_DATABASE=Teletronics Technology Corporation OUI:000D41* ID_OUI_FROM_DATABASE=Siemens AG ICM MP UC RD IT KLF1 OUI:000D3A* ID_OUI_FROM_DATABASE=Microsoft Corp. OUI:000D35* ID_OUI_FROM_DATABASE=PAC International Ltd OUI:000D2E* ID_OUI_FROM_DATABASE=Matsushita Avionics Systems Corporation OUI:000D28* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000D22* ID_OUI_FROM_DATABASE=Unitronics LTD OUI:000D27* ID_OUI_FROM_DATABASE=MICROPLEX Printware AG OUI:000C21* ID_OUI_FROM_DATABASE=Faculty of Science and Technology, Keio University OUI:000C11* ID_OUI_FROM_DATABASE=NIPPON DEMPA CO.,LTD. OUI:000C10* ID_OUI_FROM_DATABASE=PNI Corporation OUI:000C12* ID_OUI_FROM_DATABASE=Micro-Optronic-Messtechnik GmbH OUI:000C17* ID_OUI_FROM_DATABASE=AJA Video Systems Inc OUI:000C04* ID_OUI_FROM_DATABASE=Tecnova OUI:000C0B* ID_OUI_FROM_DATABASE=Broadbus Technologies OUI:000BF8* ID_OUI_FROM_DATABASE=Infinera OUI:000BFF* ID_OUI_FROM_DATABASE=Berkeley Camera Engineering OUI:000BEC* ID_OUI_FROM_DATABASE=NIPPON ELECTRIC INSTRUMENT, INC. OUI:000BB8* ID_OUI_FROM_DATABASE=Kihoku Electronic Co. OUI:000BBD* ID_OUI_FROM_DATABASE=Connexionz Limited OUI:000BAD* ID_OUI_FROM_DATABASE=PC-PoS Inc. OUI:000BA0* ID_OUI_FROM_DATABASE=T&L Information Inc. OUI:000BA7* ID_OUI_FROM_DATABASE=Maranti Networks OUI:000BAC* ID_OUI_FROM_DATABASE=3Com Ltd OUI:000B93* ID_OUI_FROM_DATABASE=Ritter Elektronik OUI:000B98* ID_OUI_FROM_DATABASE=NiceTechVision OUI:000B9B* ID_OUI_FROM_DATABASE=Sirius System Co, Ltd. OUI:000B8C* ID_OUI_FROM_DATABASE=Flextronics OUI:000BF1* ID_OUI_FROM_DATABASE=LAP Laser Applikations OUI:000BDF* ID_OUI_FROM_DATABASE=Shenzhen RouterD Networks Limited OUI:000BDE* ID_OUI_FROM_DATABASE=TELDIX GmbH OUI:000BE0* ID_OUI_FROM_DATABASE=SercoNet Ltd. OUI:000BE5* ID_OUI_FROM_DATABASE=HIMS International Corporation OUI:000BD9* ID_OUI_FROM_DATABASE=General Hydrogen OUI:000BAE* ID_OUI_FROM_DATABASE=Vitals System Inc. OUI:000BD0* ID_OUI_FROM_DATABASE=XiMeta Technology Americas Inc. OUI:000BD5* ID_OUI_FROM_DATABASE=Nvergence, Inc. OUI:000BC4* ID_OUI_FROM_DATABASE=BIOTRONIK GmbH & Co OUI:000BC9* ID_OUI_FROM_DATABASE=Electroline Equipment OUI:000BB1* ID_OUI_FROM_DATABASE=Super Star Technology Co., Ltd. OUI:000BB6* ID_OUI_FROM_DATABASE=Metalligence Technology Corp. OUI:000B79* ID_OUI_FROM_DATABASE=X-COM, Inc. OUI:000B80* ID_OUI_FROM_DATABASE=Lycium Networks OUI:000B87* ID_OUI_FROM_DATABASE=American Reliance Inc. OUI:000B6D* ID_OUI_FROM_DATABASE=SOLECTRON JAPAN NAKANIIDA OUI:000B74* ID_OUI_FROM_DATABASE=Kingwave Technology Co., Ltd. OUI:000B67* ID_OUI_FROM_DATABASE=Topview Technology Corporation OUI:000B61* ID_OUI_FROM_DATABASE=Friedrich Lütze GmbH & Co. KG OUI:000B66* ID_OUI_FROM_DATABASE=Teralink Communications OUI:000B68* ID_OUI_FROM_DATABASE=Addvalue Communications Pte Ltd OUI:000B58* ID_OUI_FROM_DATABASE=Astronautics C.A LTD OUI:000B50* ID_OUI_FROM_DATABASE=Oxygnet OUI:000B44* ID_OUI_FROM_DATABASE=Concord IDea Corp. OUI:000B49* ID_OUI_FROM_DATABASE=RF-Link System Inc. OUI:000B4B* ID_OUI_FROM_DATABASE=VISIOWAVE SA OUI:000B31* ID_OUI_FROM_DATABASE=Yantai ZhiYang Scientific and technology industry CO., LTD OUI:000B3D* ID_OUI_FROM_DATABASE=CONTAL OK Ltd. OUI:000B38* ID_OUI_FROM_DATABASE=Knürr GmbH OUI:000B2A* ID_OUI_FROM_DATABASE=HOWTEL Co., Ltd. OUI:000B2C* ID_OUI_FROM_DATABASE=Eiki Industrial Co. Ltd. OUI:000C97* ID_OUI_FROM_DATABASE=NV ADB TTV Technologies SA OUI:000C9C* ID_OUI_FROM_DATABASE=Chongho information & communications OUI:000C9E* ID_OUI_FROM_DATABASE=MemoryLink Corp. OUI:000C89* ID_OUI_FROM_DATABASE=AC Electric Vehicles, Ltd. OUI:000C8B* ID_OUI_FROM_DATABASE=Connect Tech Inc OUI:000C90* ID_OUI_FROM_DATABASE=Octasic Inc. OUI:000C84* ID_OUI_FROM_DATABASE=Eazix, Inc. OUI:000C75* ID_OUI_FROM_DATABASE=Oriental integrated electronics. LTD OUI:000C77* ID_OUI_FROM_DATABASE=Life Racing Ltd OUI:000C7C* ID_OUI_FROM_DATABASE=Internet Information Image Inc. OUI:000C43* ID_OUI_FROM_DATABASE=Ralink Technology, Corp. OUI:000C45* ID_OUI_FROM_DATABASE=Animation Technologies Inc. OUI:000C29* ID_OUI_FROM_DATABASE=VMware, Inc. OUI:000C3C* ID_OUI_FROM_DATABASE=MediaChorus, Inc. OUI:000C32* ID_OUI_FROM_DATABASE=Avionic Design Development GmbH OUI:000C35* ID_OUI_FROM_DATABASE=KaVo Dental GmbH & Co. KG OUI:000C2B* ID_OUI_FROM_DATABASE=ELIAS Technology, Inc. OUI:000C28* ID_OUI_FROM_DATABASE=RIFATRON OUI:000C1C* ID_OUI_FROM_DATABASE=MicroWeb Co., Ltd. OUI:000C64* ID_OUI_FROM_DATABASE=X2 MSA Group OUI:000C69* ID_OUI_FROM_DATABASE=National Radio Astronomy Observatory OUI:000C70* ID_OUI_FROM_DATABASE=ACC GmbH OUI:000C51* ID_OUI_FROM_DATABASE=Scientific Technologies Inc. OUI:000C56* ID_OUI_FROM_DATABASE=Megatel Computer (1986) Corp. OUI:000C58* ID_OUI_FROM_DATABASE=M&S Systems OUI:000C5D* ID_OUI_FROM_DATABASE=CHIC TECHNOLOGY (CHINA) CORP. OUI:000C4A* ID_OUI_FROM_DATABASE=Cygnus Microsystems (P) Limited OUI:000CC8* ID_OUI_FROM_DATABASE=Xytronix Research & Design, Inc. OUI:000CBB* ID_OUI_FROM_DATABASE=ISKRAEMECO OUI:000CB5* ID_OUI_FROM_DATABASE=Premier Technolgies, Inc OUI:000CBC* ID_OUI_FROM_DATABASE=Iscutum OUI:000CA3* ID_OUI_FROM_DATABASE=Rancho Technology, Inc. OUI:000CAA* ID_OUI_FROM_DATABASE=Cubic Transportation Systems Inc OUI:000A38* ID_OUI_FROM_DATABASE=Apani Networks OUI:000A3F* ID_OUI_FROM_DATABASE=Data East Corporation OUI:000A44* ID_OUI_FROM_DATABASE=Avery Dennison Deutschland GmbH OUI:000A46* ID_OUI_FROM_DATABASE=ARO WELDING TECHNOLOGIES SAS OUI:000A33* ID_OUI_FROM_DATABASE=Emulex Corporation OUI:000A31* ID_OUI_FROM_DATABASE=HCV Consulting OUI:000A2C* ID_OUI_FROM_DATABASE=Active Tchnology Corporation OUI:004252* ID_OUI_FROM_DATABASE=RLX Technologies OUI:000A2A* ID_OUI_FROM_DATABASE=QSI Systems Inc. OUI:000A1E* ID_OUI_FROM_DATABASE=Red-M Products Limited OUI:000A23* ID_OUI_FROM_DATABASE=Parama Networks Inc OUI:000A17* ID_OUI_FROM_DATABASE=NESTAR COMMUNICATIONS, INC OUI:000A1C* ID_OUI_FROM_DATABASE=Bridge Information Co., Ltd. OUI:000B19* ID_OUI_FROM_DATABASE=Vernier Networks, Inc. OUI:000B1E* ID_OUI_FROM_DATABASE=KAPPA opto-electronics GmbH OUI:000B25* ID_OUI_FROM_DATABASE=Aeluros OUI:000B17* ID_OUI_FROM_DATABASE=MKS Instruments OUI:000B12* ID_OUI_FROM_DATABASE=NURI Telecom Co., Ltd. OUI:000B0B* ID_OUI_FROM_DATABASE=Corrent Corporation OUI:000AFA* ID_OUI_FROM_DATABASE=Traverse Technologies Australia OUI:000AFF* ID_OUI_FROM_DATABASE=Kilchherr Elektronik AG OUI:000AF3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000AF8* ID_OUI_FROM_DATABASE=American Telecare Inc. OUI:000AEE* ID_OUI_FROM_DATABASE=GCD Hard- & Software GmbH OUI:000A06* ID_OUI_FROM_DATABASE=Teledex LLC OUI:000A09* ID_OUI_FROM_DATABASE=TaraCom Integrated Products, Inc. OUI:000A0B* ID_OUI_FROM_DATABASE=Sealevel Systems, Inc. OUI:000A10* ID_OUI_FROM_DATABASE=FAST media integrations AG OUI:0009F7* ID_OUI_FROM_DATABASE=SED, a division of Calian OUI:000A01* ID_OUI_FROM_DATABASE=SOHOware, Inc. OUI:0009E9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0009F0* ID_OUI_FROM_DATABASE=Shimizu Technology Inc. OUI:0009EA* ID_OUI_FROM_DATABASE=YEM Inc. OUI:0009E4* ID_OUI_FROM_DATABASE=K Tech Infosystem Inc. OUI:0009D8* ID_OUI_FROM_DATABASE=Fält Communications AB OUI:0009DD* ID_OUI_FROM_DATABASE=Mavin Technology Inc. OUI:0009B1* ID_OUI_FROM_DATABASE=Kanematsu Electronics, Ltd. OUI:0009A3* ID_OUI_FROM_DATABASE=Leadfly Techologies Corp. Ltd. OUI:0009AA* ID_OUI_FROM_DATABASE=Data Comm for Business, Inc. OUI:0009A4* ID_OUI_FROM_DATABASE=HARTEC Corporation OUI:00099E* ID_OUI_FROM_DATABASE=Testech, Inc. OUI:000992* ID_OUI_FROM_DATABASE=InterEpoch Technology,INC. OUI:000997* ID_OUI_FROM_DATABASE=Nortel Networks OUI:000991* ID_OUI_FROM_DATABASE=GE Fanuc Automation Manufacturing, Inc. OUI:00098B* ID_OUI_FROM_DATABASE=Entropic Communications, Inc. OUI:000AAB* ID_OUI_FROM_DATABASE=Toyota Technical Development Corporation OUI:000AB0* ID_OUI_FROM_DATABASE=LOYTEC electronics GmbH OUI:000AB7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000AA4* ID_OUI_FROM_DATABASE=SHANGHAI SURVEILLANCE TECHNOLOGY CO,LTD OUI:000AA9* ID_OUI_FROM_DATABASE=Brooks Automation GmbH OUI:000A91* ID_OUI_FROM_DATABASE=HemoCue AB OUI:000A9D* ID_OUI_FROM_DATABASE=King Young Technology Co. Ltd. OUI:000A8C* ID_OUI_FROM_DATABASE=Guardware Systems Ltd. OUI:000A97* ID_OUI_FROM_DATABASE=SONICblue, Inc. OUI:000A7D* ID_OUI_FROM_DATABASE=Valo, Inc. OUI:000A84* ID_OUI_FROM_DATABASE=Rainsun Enterprise Co., Ltd. OUI:000A89* ID_OUI_FROM_DATABASE=Creval Systems, Inc. OUI:0009D7* ID_OUI_FROM_DATABASE=DC Security Products OUI:0009CA* ID_OUI_FROM_DATABASE=iMaxNetworks(Shenzhen)Limited. OUI:0009D1* ID_OUI_FROM_DATABASE=SERANOA NETWORKS INC OUI:0009C5* ID_OUI_FROM_DATABASE=KINGENE Technology Corporation OUI:0009BD* ID_OUI_FROM_DATABASE=Epygi Technologies, Ltd. OUI:0009B6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00097F* ID_OUI_FROM_DATABASE=Vsecure 2000 LTD. OUI:000984* ID_OUI_FROM_DATABASE=MyCasa Network Inc. OUI:000971* ID_OUI_FROM_DATABASE=Time Management, Inc. OUI:000978* ID_OUI_FROM_DATABASE=AIJI System Co., Ltd. OUI:000972* ID_OUI_FROM_DATABASE=Securebase,Inc OUI:00096C* ID_OUI_FROM_DATABASE=Imedia Semiconductor Corp. OUI:000965* ID_OUI_FROM_DATABASE=HyunJu Computer Co., Ltd. OUI:000960* ID_OUI_FROM_DATABASE=YOZAN Inc. OUI:000956* ID_OUI_FROM_DATABASE=Network Systems Group, Ltd. (NSG) OUI:000955* ID_OUI_FROM_DATABASE=Young Generation International Corp. OUI:000AE9* ID_OUI_FROM_DATABASE=AirVast Technology Inc. OUI:000ADB* ID_OUI_FROM_DATABASE=SkyPilot Network, Inc OUI:000ADD* ID_OUI_FROM_DATABASE=Allworx Corp. OUI:000AE2* ID_OUI_FROM_DATABASE=Binatone Electronics International, Ltd OUI:000ACA* ID_OUI_FROM_DATABASE=YOKOYAMA SHOKAI CO.,Ltd. OUI:000ACF* ID_OUI_FROM_DATABASE=PROVIDEO Multimedia Co. Ltd. OUI:000AD6* ID_OUI_FROM_DATABASE=BeamReach Networks OUI:000ABC* ID_OUI_FROM_DATABASE=Seabridge Ltd. OUI:000ABE* ID_OUI_FROM_DATABASE=OPNET Technologies CO., LTD. OUI:000AC3* ID_OUI_FROM_DATABASE=eM Technics Co., Ltd. OUI:000A78* ID_OUI_FROM_DATABASE=OLITEC OUI:000A71* ID_OUI_FROM_DATABASE=Avrio Technologies, Inc OUI:000A76* ID_OUI_FROM_DATABASE=Beida Jade Bird Huaguang Technology Co.,Ltd OUI:000A63* ID_OUI_FROM_DATABASE=DHD GmbH OUI:000A65* ID_OUI_FROM_DATABASE=GentechMedia.co.,ltd. OUI:000A6A* ID_OUI_FROM_DATABASE=SVM Microwaves s.r.o. OUI:000A5E* ID_OUI_FROM_DATABASE=3COM Corporation OUI:000A52* ID_OUI_FROM_DATABASE=AsiaRF Ltd. OUI:000A4B* ID_OUI_FROM_DATABASE=DataPower Technology, Inc. OUI:00075A* ID_OUI_FROM_DATABASE=Air Products and Chemicals, Inc. OUI:000754* ID_OUI_FROM_DATABASE=Xyterra Computing, Inc. OUI:00074E* ID_OUI_FROM_DATABASE=IPFRONT Inc OUI:00074D* ID_OUI_FROM_DATABASE=Zebra Technologies Corp. OUI:000742* ID_OUI_FROM_DATABASE=Ormazabal OUI:000748* ID_OUI_FROM_DATABASE=The Imaging Source Europe OUI:000736* ID_OUI_FROM_DATABASE=Data Video Technologies Co., Ltd. OUI:00073D* ID_OUI_FROM_DATABASE=Nanjing Postel Telecommunications Co., Ltd. OUI:00073C* ID_OUI_FROM_DATABASE=Telecom Design OUI:00072A* ID_OUI_FROM_DATABASE=Innovance Networks OUI:00072F* ID_OUI_FROM_DATABASE=Intransa, Inc. OUI:000730* ID_OUI_FROM_DATABASE=Hutchison OPTEL Telecom Technology Co., Ltd. OUI:000725* ID_OUI_FROM_DATABASE=Bematech International Corp. OUI:000818* ID_OUI_FROM_DATABASE=Pixelworks, Inc. OUI:000812* ID_OUI_FROM_DATABASE=GM-2 Corporation OUI:000811* ID_OUI_FROM_DATABASE=VOIX Corporation OUI:00080B* ID_OUI_FROM_DATABASE=Birka BPA Informationssystem AB OUI:000805* ID_OUI_FROM_DATABASE=Techno-Holon Corporation OUI:00080C* ID_OUI_FROM_DATABASE=VDA Elettronica spa OUI:0007FB* ID_OUI_FROM_DATABASE=Giga Stream UMTS Technologies GmbH OUI:0007F5* ID_OUI_FROM_DATABASE=Bridgeco Co AG OUI:0007E8* ID_OUI_FROM_DATABASE=EdgeWave OUI:0007EF* ID_OUI_FROM_DATABASE=Lockheed Martin Tactical Systems OUI:0007E2* ID_OUI_FROM_DATABASE=Bitworks, Inc. OUI:0007D6* ID_OUI_FROM_DATABASE=Commil Ltd. OUI:0007DC* ID_OUI_FROM_DATABASE=Atek Co, Ltd. OUI:000923* ID_OUI_FROM_DATABASE=Heaman System Co., Ltd OUI:00091D* ID_OUI_FROM_DATABASE=Proteam Computer Corporation OUI:000924* ID_OUI_FROM_DATABASE=Telebau GmbH OUI:000911* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000916* ID_OUI_FROM_DATABASE=Listman Home Technologies, Inc. OUI:00090A* ID_OUI_FROM_DATABASE=SnedFar Technology Co., Ltd. OUI:000904* ID_OUI_FROM_DATABASE=MONDIAL electronic OUI:000903* ID_OUI_FROM_DATABASE=Panasas, Inc OUI:0008FE* ID_OUI_FROM_DATABASE=UNIK C&C Co.,Ltd. OUI:0008FA* ID_OUI_FROM_DATABASE=Karl E.Brinkmann GmbH OUI:0008EE* ID_OUI_FROM_DATABASE=Logic Product Development OUI:0008F0* ID_OUI_FROM_DATABASE=Next Generation Systems, Inc. OUI:000948* ID_OUI_FROM_DATABASE=Vista Control Systems, Corp. OUI:00094F* ID_OUI_FROM_DATABASE=elmegt GmbH & Co. KG OUI:000943* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00093C* ID_OUI_FROM_DATABASE=Jacques Technologies P/L OUI:000936* ID_OUI_FROM_DATABASE=Ipetronik GmbH & Co. KG OUI:000935* ID_OUI_FROM_DATABASE=Sandvine Incorporated OUI:000929* ID_OUI_FROM_DATABASE=Sanyo Industries (UK) Limited OUI:000930* ID_OUI_FROM_DATABASE=AeroConcierge Inc. OUI:0008E9* ID_OUI_FROM_DATABASE=NextGig OUI:0008DC* ID_OUI_FROM_DATABASE=Wiznet OUI:0008E2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0008DB* ID_OUI_FROM_DATABASE=Corrigent Systems OUI:0008D6* ID_OUI_FROM_DATABASE=HASSNET Inc. OUI:0008CF* ID_OUI_FROM_DATABASE=Nippon Koei Power Systems Co., Ltd. OUI:0008C0* ID_OUI_FROM_DATABASE=ASA SYSTEMS OUI:0008C5* ID_OUI_FROM_DATABASE=Liontech Co., Ltd. OUI:0008C9* ID_OUI_FROM_DATABASE=TechniSat Digital GmbH OUI:0008CA* ID_OUI_FROM_DATABASE=TwinHan Technology Co.,Ltd OUI:0008BF* ID_OUI_FROM_DATABASE=Aptus Elektronik AB OUI:0008B3* ID_OUI_FROM_DATABASE=Fastwel OUI:0008B2* ID_OUI_FROM_DATABASE=SHENZHEN COMPASS TECHNOLOGY DEVELOPMENT CO.,LTD OUI:0008A6* ID_OUI_FROM_DATABASE=Multiware & Image Co., Ltd. OUI:0008AD* ID_OUI_FROM_DATABASE=Toyo-Linx Co., Ltd. OUI:00089A* ID_OUI_FROM_DATABASE=Alcatel Microelectronics OUI:0008A0* ID_OUI_FROM_DATABASE=Stotz Feinmesstechnik GmbH OUI:000892* ID_OUI_FROM_DATABASE=EM Solutions OUI:000896* ID_OUI_FROM_DATABASE=Printronix, Inc. OUI:00088C* ID_OUI_FROM_DATABASE=Quanta Network Systems Inc. OUI:000886* ID_OUI_FROM_DATABASE=Hansung Teliann, Inc. OUI:000873* ID_OUI_FROM_DATABASE=DapTechnology B.V. OUI:00087A* ID_OUI_FROM_DATABASE=Wipotec GmbH OUI:00087F* ID_OUI_FROM_DATABASE=SPAUN electronic GmbH & Co. KG OUI:02608C* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:0007D0* ID_OUI_FROM_DATABASE=Automat Engenharia de Automação Ltda. OUI:0007CD* ID_OUI_FROM_DATABASE=Kumoh Electronic Co, Ltd OUI:0007C7* ID_OUI_FROM_DATABASE=Synectics Systems Limited OUI:00047D* ID_OUI_FROM_DATABASE=Pelco OUI:0007BA* ID_OUI_FROM_DATABASE=UTStarcom, Inc. OUI:00047E* ID_OUI_FROM_DATABASE=Siqura B.V. OUI:0007C1* ID_OUI_FROM_DATABASE=Overture Networks, Inc. OUI:0007C0* ID_OUI_FROM_DATABASE=NetZerver Inc. OUI:0007AE* ID_OUI_FROM_DATABASE=Britestream Networks, Inc. OUI:0007B4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0007A6* ID_OUI_FROM_DATABASE=Home Automation, Inc. OUI:00079A* ID_OUI_FROM_DATABASE=Verint Systems Inc OUI:0007A0* ID_OUI_FROM_DATABASE=e-Watch Inc. OUI:000794* ID_OUI_FROM_DATABASE=Simple Devices, Inc. OUI:000793* ID_OUI_FROM_DATABASE=Shin Satellite Public Company Limited OUI:00078D* ID_OUI_FROM_DATABASE=NetEngines Ltd. OUI:00078E* ID_OUI_FROM_DATABASE=Garz & Friche GmbH OUI:000781* ID_OUI_FROM_DATABASE=Itron Inc. OUI:000787* ID_OUI_FROM_DATABASE=Idea System Co., Ltd. OUI:000777* ID_OUI_FROM_DATABASE=Motah Ltd. OUI:000771* ID_OUI_FROM_DATABASE=Embedded System Corporation OUI:00075B* ID_OUI_FROM_DATABASE=Gibson Guitars OUI:000760* ID_OUI_FROM_DATABASE=TOMIS Information & Telecom Corp. OUI:000767* ID_OUI_FROM_DATABASE=Yuxing Electronics Company Limited OUI:000879* ID_OUI_FROM_DATABASE=CEM Corporation OUI:00086C* ID_OUI_FROM_DATABASE=Plasmon LMS OUI:00086D* ID_OUI_FROM_DATABASE=Missouri FreeNet OUI:000867* ID_OUI_FROM_DATABASE=Uptime Devices OUI:000860* ID_OUI_FROM_DATABASE=LodgeNet Entertainment Corp. OUI:000854* ID_OUI_FROM_DATABASE=Netronix, Inc. OUI:00085A* ID_OUI_FROM_DATABASE=IntiGate Inc. OUI:00081E* ID_OUI_FROM_DATABASE=Repeatit AB OUI:00082B* ID_OUI_FROM_DATABASE=Wooksung Electronics, Inc. OUI:000824* ID_OUI_FROM_DATABASE=Nuance Document Imaging OUI:0005BA* ID_OUI_FROM_DATABASE=Area Netwoeks, Inc. OUI:0005B9* ID_OUI_FROM_DATABASE=Airvana, Inc. OUI:0005C0* ID_OUI_FROM_DATABASE=Digital Network Alacarte Co., Ltd. OUI:000599* ID_OUI_FROM_DATABASE=DRS Test and Energy Management or DRS-TEM OUI:0005A0* ID_OUI_FROM_DATABASE=MOBILINE Kft. OUI:0005A9* ID_OUI_FROM_DATABASE=Princeton Networks, Inc. OUI:0005AA* ID_OUI_FROM_DATABASE=Moore Industries International Inc. OUI:0005AF* ID_OUI_FROM_DATABASE=InnoScan Computing A/S OUI:0005B3* ID_OUI_FROM_DATABASE=Asahi-Engineering Co., Ltd. OUI:00059F* ID_OUI_FROM_DATABASE=Yotta Networks, Inc. OUI:0005A6* ID_OUI_FROM_DATABASE=Extron Electronics OUI:0005B4* ID_OUI_FROM_DATABASE=Aceex Corporation OUI:00058D* ID_OUI_FROM_DATABASE=Lynx Photonic Networks, Inc. OUI:000587* ID_OUI_FROM_DATABASE=Locus, Incorporated OUI:000593* ID_OUI_FROM_DATABASE=Grammar Engine Inc. OUI:000586* ID_OUI_FROM_DATABASE=Lucent Technologies OUI:00057A* ID_OUI_FROM_DATABASE=Overture Networks OUI:00063C* ID_OUI_FROM_DATABASE=Intrinsyc Software International Inc. OUI:00062F* ID_OUI_FROM_DATABASE=Pivotech Systems Inc. OUI:000636* ID_OUI_FROM_DATABASE=Jedai Broadband Networks OUI:000635* ID_OUI_FROM_DATABASE=PacketAir Networks, Inc. OUI:000628* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00061F* ID_OUI_FROM_DATABASE=Vision Components GmbH OUI:000619* ID_OUI_FROM_DATABASE=Connection Technology Systems OUI:00060D* ID_OUI_FROM_DATABASE=Wave7 Optics OUI:000613* ID_OUI_FROM_DATABASE=Kawasaki Microelectronics Incorporated OUI:00060E* ID_OUI_FROM_DATABASE=IGYS Systems, Inc. OUI:0005EC* ID_OUI_FROM_DATABASE=Mosaic Systems Inc. OUI:0005D3* ID_OUI_FROM_DATABASE=eProduction Solutions, Inc. OUI:000608* ID_OUI_FROM_DATABASE=At-Sky SAS OUI:000607* ID_OUI_FROM_DATABASE=Omni Directional Control Technology Inc. OUI:0005E6* ID_OUI_FROM_DATABASE=Egenera, Inc. OUI:000580* ID_OUI_FROM_DATABASE=FibroLAN Ltd. OUI:000576* ID_OUI_FROM_DATABASE=NSM Technology Ltd. OUI:000570* ID_OUI_FROM_DATABASE=Baydel Ltd. OUI:00056A* ID_OUI_FROM_DATABASE=Heuft Systemtechnik GmbH OUI:000563* ID_OUI_FROM_DATABASE=J-Works, Inc. OUI:00055D* ID_OUI_FROM_DATABASE=D-LINK SYSTEMS, INC. OUI:000564* ID_OUI_FROM_DATABASE=Tsinghua Bitway Co., Ltd. OUI:000557* ID_OUI_FROM_DATABASE=Agile TV Corporation OUI:000551* ID_OUI_FROM_DATABASE=F & S Elektronik Systeme GmbH OUI:00054B* ID_OUI_FROM_DATABASE=Eaton Automation AG OUI:00054A* ID_OUI_FROM_DATABASE=Ario Data Networks, Inc. OUI:000544* ID_OUI_FROM_DATABASE=Valley Technologies, Inc. OUI:00053E* ID_OUI_FROM_DATABASE=KID Systeme GmbH OUI:000531* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000538* ID_OUI_FROM_DATABASE=Merilus, Inc. OUI:000532* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000525* ID_OUI_FROM_DATABASE=Puretek Industrial Co., Ltd. OUI:00052B* ID_OUI_FROM_DATABASE=HORIBA, Ltd. OUI:00051F* ID_OUI_FROM_DATABASE=Taijin Media Co., Ltd. OUI:000519* ID_OUI_FROM_DATABASE=Siemens Building Technologies AG, OUI:000518* ID_OUI_FROM_DATABASE=Jupiters Technology OUI:00050E* ID_OUI_FROM_DATABASE=3ware, Inc. OUI:00050F* ID_OUI_FROM_DATABASE=Tanaka S/S Ltd. OUI:000508* ID_OUI_FROM_DATABASE=Inetcam, Inc. OUI:0004FE* ID_OUI_FROM_DATABASE=Pelago Networks OUI:000671* ID_OUI_FROM_DATABASE=Softing AG OUI:000672* ID_OUI_FROM_DATABASE=Netezza OUI:00067B* ID_OUI_FROM_DATABASE=Toplink C&C Corporation OUI:000665* ID_OUI_FROM_DATABASE=Sunny Giken, Inc. OUI:00066B* ID_OUI_FROM_DATABASE=Sysmex Corporation OUI:000652* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000659* ID_OUI_FROM_DATABASE=EAL (Apeldoorn) B.V. OUI:000658* ID_OUI_FROM_DATABASE=Helmut Fischer GmbH Institut für Elektronik und Messtechnik OUI:000646* ID_OUI_FROM_DATABASE=ShenZhen XunBao Network Technology Co Ltd OUI:000640* ID_OUI_FROM_DATABASE=White Rock Networks OUI:00064C* ID_OUI_FROM_DATABASE=Invicta Networks, Inc. OUI:0006B5* ID_OUI_FROM_DATABASE=Source Photonics, Inc. OUI:0006A8* ID_OUI_FROM_DATABASE=KC Technology, Inc. OUI:00069E* ID_OUI_FROM_DATABASE=UNIQA, Inc. OUI:000698* ID_OUI_FROM_DATABASE=egnite GmbH OUI:000692* ID_OUI_FROM_DATABASE=Intruvert Networks, Inc. OUI:00068C* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:000685* ID_OUI_FROM_DATABASE=NetNearU Corporation OUI:00068B* ID_OUI_FROM_DATABASE=AirRunner Technologies, Inc. OUI:000686* ID_OUI_FROM_DATABASE=ZARDCOM Co., Ltd. OUI:00067F* ID_OUI_FROM_DATABASE=Digeo, Inc. OUI:0006DE* ID_OUI_FROM_DATABASE=Flash Technology OUI:0006E4* ID_OUI_FROM_DATABASE=Citel Technologies Ltd. OUI:0006D1* ID_OUI_FROM_DATABASE=Tahoe Networks, Inc. OUI:0006DA* ID_OUI_FROM_DATABASE=ITRAN Communications Ltd. OUI:0006CB* ID_OUI_FROM_DATABASE=Jotron Electronics A/S OUI:0006CC* ID_OUI_FROM_DATABASE=JMI Electronics Co., Ltd. OUI:0006BB* ID_OUI_FROM_DATABASE=ATI Technologies Inc. OUI:0006C5* ID_OUI_FROM_DATABASE=INNOVI Technologies Limited OUI:0006AF* ID_OUI_FROM_DATABASE=Xalted Networks OUI:000719* ID_OUI_FROM_DATABASE=Mobiis Co., Ltd. OUI:000720* ID_OUI_FROM_DATABASE=Trutzschler GmbH & Co. KG OUI:000713* ID_OUI_FROM_DATABASE=IP One, Inc. OUI:00070D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000714* ID_OUI_FROM_DATABASE=Brightcom OUI:0006F1* ID_OUI_FROM_DATABASE=Optillion OUI:0006F0* ID_OUI_FROM_DATABASE=Digeo, Inc. OUI:0006FB* ID_OUI_FROM_DATABASE=Hitachi Printing Solutions, Ltd. OUI:0006EB* ID_OUI_FROM_DATABASE=Global Data OUI:0005F2* ID_OUI_FROM_DATABASE=Power R, Inc. OUI:0005FE* ID_OUI_FROM_DATABASE=Traficon N.V. OUI:0005E5* ID_OUI_FROM_DATABASE=Renishaw PLC OUI:0005F8* ID_OUI_FROM_DATABASE=Real Time Access, Inc. OUI:0005FF* ID_OUI_FROM_DATABASE=SNS Solutions, Inc. OUI:0005DD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0005D9* ID_OUI_FROM_DATABASE=Techno Valley, Inc. OUI:0005C6* ID_OUI_FROM_DATABASE=Triz Communications OUI:0005CC* ID_OUI_FROM_DATABASE=Sumtel Communications, Inc. OUI:00044C* ID_OUI_FROM_DATABASE=JENOPTIK OUI:000448* ID_OUI_FROM_DATABASE=Polaroid Corporation OUI:00043C* ID_OUI_FROM_DATABASE=SONOS Co., Ltd. OUI:000441* ID_OUI_FROM_DATABASE=Half Dome Systems, Inc. OUI:000435* ID_OUI_FROM_DATABASE=Comptek International, Inc. OUI:00042F* ID_OUI_FROM_DATABASE=International Communications Products, Inc. OUI:000429* ID_OUI_FROM_DATABASE=Pixord Corporation OUI:000422* ID_OUI_FROM_DATABASE=Gordon Kapes, Inc. OUI:00041C* ID_OUI_FROM_DATABASE=ipDialog, Inc. OUI:00041D* ID_OUI_FROM_DATABASE=Corega of America OUI:000416* ID_OUI_FROM_DATABASE=Parks S/A Comunicacoes Digitais OUI:000410* ID_OUI_FROM_DATABASE=Spinnaker Networks, Inc. OUI:00040F* ID_OUI_FROM_DATABASE=Asus Network Technologies, Inc. OUI:00040A* ID_OUI_FROM_DATABASE=Sage Systems OUI:000403* ID_OUI_FROM_DATABASE=Nexsi Corporation OUI:0004F8* ID_OUI_FROM_DATABASE=QUALICABLE TV Industria E Com., Ltda OUI:0004F2* ID_OUI_FROM_DATABASE=Polycom OUI:0004EB* ID_OUI_FROM_DATABASE=Paxonet Communications, Inc. OUI:0004EC* ID_OUI_FROM_DATABASE=Memobox SA OUI:0004E6* ID_OUI_FROM_DATABASE=Banyan Network Private Limited OUI:0004DC* ID_OUI_FROM_DATABASE=Nortel Networks OUI:0004E1* ID_OUI_FROM_DATABASE=Infinior Microsystems OUI:0004DB* ID_OUI_FROM_DATABASE=Tellus Group Corp. OUI:0004E2* ID_OUI_FROM_DATABASE=SMC Networks, Inc. OUI:0004D5* ID_OUI_FROM_DATABASE=Hitachi Information & Communication Engineering, Ltd. OUI:0004CF* ID_OUI_FROM_DATABASE=Seagate Technology OUI:0004C9* ID_OUI_FROM_DATABASE=Micro Electron Co., Ltd. OUI:000487* ID_OUI_FROM_DATABASE=Cogency Semiconductor, Inc. OUI:000482* ID_OUI_FROM_DATABASE=Medialogic Corp. OUI:000478* ID_OUI_FROM_DATABASE=G. Star Technology Corporation OUI:000471* ID_OUI_FROM_DATABASE=IPrad OUI:00046B* ID_OUI_FROM_DATABASE=Palm Wireless, Inc. OUI:000465* ID_OUI_FROM_DATABASE=i.s.t isdn-support technik GmbH OUI:000459* ID_OUI_FROM_DATABASE=Veristar Corporation OUI:00045E* ID_OUI_FROM_DATABASE=PolyTrax Information Technology AG OUI:000458* ID_OUI_FROM_DATABASE=Fusion X Co., Ltd. OUI:000452* ID_OUI_FROM_DATABASE=RocketLogix, Inc. OUI:000442* ID_OUI_FROM_DATABASE=NACT OUI:0003F9* ID_OUI_FROM_DATABASE=Pleiades Communications, Inc. OUI:0003E2* ID_OUI_FROM_DATABASE=Comspace Corporation OUI:0003F4* ID_OUI_FROM_DATABASE=NetBurner OUI:0003F3* ID_OUI_FROM_DATABASE=Dazzle Multimedia, Inc. OUI:0003ED* ID_OUI_FROM_DATABASE=Shinkawa Electric Co., Ltd. OUI:0003E7* ID_OUI_FROM_DATABASE=Logostek Co. Ltd. OUI:0003DF* ID_OUI_FROM_DATABASE=Desana Systems OUI:0003DB* ID_OUI_FROM_DATABASE=Apogee Electronics Corp. OUI:0003D6* ID_OUI_FROM_DATABASE=RADVision, Ltd. OUI:0003CF* ID_OUI_FROM_DATABASE=Muxcom, Inc. OUI:0003C8* ID_OUI_FROM_DATABASE=CML Emergency Services OUI:0003C3* ID_OUI_FROM_DATABASE=Micronik Multimedia OUI:0003C0* ID_OUI_FROM_DATABASE=RFTNC Co., Ltd. OUI:0003BC* ID_OUI_FROM_DATABASE=COT GmbH OUI:0003B1* ID_OUI_FROM_DATABASE=Hospira Inc. OUI:0003A5* ID_OUI_FROM_DATABASE=Medea Corporation OUI:0003AA* ID_OUI_FROM_DATABASE=Watlow OUI:0003A2* ID_OUI_FROM_DATABASE=Catapult Communications OUI:000397* ID_OUI_FROM_DATABASE=Watchfront Limited OUI:00039E* ID_OUI_FROM_DATABASE=Tera System Co., Ltd. OUI:000392* ID_OUI_FROM_DATABASE=Hyundai Teletek Co., Ltd. OUI:00038F* ID_OUI_FROM_DATABASE=Weinschel Corporation OUI:00038B* ID_OUI_FROM_DATABASE=PLUS-ONE I&T, Inc. OUI:000386* ID_OUI_FROM_DATABASE=Ho Net, Inc. OUI:00037D* ID_OUI_FROM_DATABASE=Stellcom OUI:000382* ID_OUI_FROM_DATABASE=A-One Co., Ltd. OUI:00037A* ID_OUI_FROM_DATABASE=Taiyo Yuden Co., Ltd. OUI:000376* ID_OUI_FROM_DATABASE=Graphtec Technology, Inc. OUI:000369* ID_OUI_FROM_DATABASE=Nippon Antenna Co., Ltd. OUI:00036F* ID_OUI_FROM_DATABASE=Telsey SPA OUI:000363* ID_OUI_FROM_DATABASE=Miraesys Co., Ltd. OUI:00035E* ID_OUI_FROM_DATABASE=Metropolitan Area Networks, Inc. OUI:000357* ID_OUI_FROM_DATABASE=Intervoice-Brite, Inc. OUI:00034C* ID_OUI_FROM_DATABASE=Shanghai DigiVision Technology Co., Ltd. OUI:000351* ID_OUI_FROM_DATABASE=Diebold, Inc. OUI:000311* ID_OUI_FROM_DATABASE=Micro Technology Co., Ltd. OUI:00030A* ID_OUI_FROM_DATABASE=Argus Technologies OUI:000302* ID_OUI_FROM_DATABASE=Charles Industries, Ltd. OUI:000305* ID_OUI_FROM_DATABASE=MSC Vertriebs GmbH OUI:0002FE* ID_OUI_FROM_DATABASE=Viditec, Inc. OUI:0002F2* ID_OUI_FROM_DATABASE=eDevice, Inc. OUI:0002F7* ID_OUI_FROM_DATABASE=ARM OUI:0002EC* ID_OUI_FROM_DATABASE=Maschoff Design Engineering OUI:0002E4* ID_OUI_FROM_DATABASE=JC HYUN Systems, Inc. OUI:0002E7* ID_OUI_FROM_DATABASE=CAB GmbH & Co KG OUI:0002E0* ID_OUI_FROM_DATABASE=ETAS GmbH OUI:0002D9* ID_OUI_FROM_DATABASE=Reliable Controls OUI:0002D4* ID_OUI_FROM_DATABASE=PDA Peripherals, Inc. OUI:0002D1* ID_OUI_FROM_DATABASE=Vivotek, Inc. OUI:0002CD* ID_OUI_FROM_DATABASE=TeleDream, Inc. OUI:000349* ID_OUI_FROM_DATABASE=Vidicode Datacommunicatie B.V. OUI:000340* ID_OUI_FROM_DATABASE=Floware Wireless Systems, Ltd. OUI:008037* ID_OUI_FROM_DATABASE=Ericsson Group OUI:000332* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000339* ID_OUI_FROM_DATABASE=Eurologic Systems, Ltd. OUI:00032A* ID_OUI_FROM_DATABASE=UniData Communication Systems, Inc. OUI:00032D* ID_OUI_FROM_DATABASE=IBASE Technology, Inc. OUI:000326* ID_OUI_FROM_DATABASE=Iwasaki Information Systems Co., Ltd. OUI:00031D* ID_OUI_FROM_DATABASE=Taiwan Commate Computer, Inc. OUI:000318* ID_OUI_FROM_DATABASE=Cyras Systems, Inc. OUI:0004C2* ID_OUI_FROM_DATABASE=Magnipix, Inc. OUI:0004B6* ID_OUI_FROM_DATABASE=Stratex Networks, Inc. OUI:0004BC* ID_OUI_FROM_DATABASE=Giantec, Inc. OUI:0004B0* ID_OUI_FROM_DATABASE=ELESIGN Co., Ltd. OUI:0004A9* ID_OUI_FROM_DATABASE=SandStream Technologies, Inc. OUI:0004A8* ID_OUI_FROM_DATABASE=Broadmax Technologies, Inc. OUI:0004A2* ID_OUI_FROM_DATABASE=L.S.I. Japan Co., Ltd. OUI:00049B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00049C* ID_OUI_FROM_DATABASE=Surgient Networks, Inc. OUI:000496* ID_OUI_FROM_DATABASE=Extreme Networks OUI:00048F* ID_OUI_FROM_DATABASE=TD Systems Corporation OUI:000488* ID_OUI_FROM_DATABASE=Eurotherm Controls OUI:000281* ID_OUI_FROM_DATABASE=Madge Ltd. OUI:009064* ID_OUI_FROM_DATABASE=Thomson Inc. OUI:00027F* ID_OUI_FROM_DATABASE=ask-technologies.com OUI:00027A* ID_OUI_FROM_DATABASE=IOI Technology Corporation OUI:000273* ID_OUI_FROM_DATABASE=Coriolis Networks OUI:00026E* ID_OUI_FROM_DATABASE=NeGeN Access, Inc. OUI:000263* ID_OUI_FROM_DATABASE=UPS Manufacturing SRL OUI:00025C* ID_OUI_FROM_DATABASE=SCI Systems (Kunshan) Co., Ltd. OUI:000253* ID_OUI_FROM_DATABASE=Televideo, Inc. OUI:00024C* ID_OUI_FROM_DATABASE=SiByte, Inc. OUI:00024E* ID_OUI_FROM_DATABASE=Datacard Group OUI:00012F* ID_OUI_FROM_DATABASE=Twinhead International Corp OUI:00023C* ID_OUI_FROM_DATABASE=Creative Technology, Ltd. OUI:000240* ID_OUI_FROM_DATABASE=Seedek Co., Ltd. OUI:000247* ID_OUI_FROM_DATABASE=Great Dragon Information Technology (Group) Co., Ltd. OUI:000243* ID_OUI_FROM_DATABASE=Raysis Co., Ltd. OUI:000239* ID_OUI_FROM_DATABASE=Visicom OUI:000236* ID_OUI_FROM_DATABASE=INIT GmbH OUI:000231* ID_OUI_FROM_DATABASE=Ingersoll-Rand OUI:00022A* ID_OUI_FROM_DATABASE=Asound Electronic OUI:00022D* ID_OUI_FROM_DATABASE=Agere Systems OUI:000219* ID_OUI_FROM_DATABASE=Paralon Technologies OUI:000186* ID_OUI_FROM_DATABASE=Uwe Disch OUI:00017B* ID_OUI_FROM_DATABASE=Heidelberger Druckmaschinen AG OUI:000182* ID_OUI_FROM_DATABASE=DICA TECHNOLOGIES AG OUI:00018E* ID_OUI_FROM_DATABASE=Logitec Corporation OUI:00019B* ID_OUI_FROM_DATABASE=Kyoto Microcomputer Co., Ltd. OUI:000194* ID_OUI_FROM_DATABASE=Capital Equipment Corporation OUI:000197* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0001A3* ID_OUI_FROM_DATABASE=GENESYS LOGIC, INC. OUI:00014E* ID_OUI_FROM_DATABASE=WIN Enterprises, Inc. OUI:0030AC* ID_OUI_FROM_DATABASE=Systeme Lauer GmbH & Co., Ltd. OUI:00013E* ID_OUI_FROM_DATABASE=Ascom Tateco AB OUI:000145* ID_OUI_FROM_DATABASE=WINSYSTEMS, INC. OUI:000126* ID_OUI_FROM_DATABASE=PAC Labs OUI:00011A* ID_OUI_FROM_DATABASE=Hoffmann und Burmeister GbR OUI:00011D* ID_OUI_FROM_DATABASE=Centillium Communications OUI:000129* ID_OUI_FROM_DATABASE=DFI Inc. OUI:000107* ID_OUI_FROM_DATABASE=Leiser GmbH OUI:00010E* ID_OUI_FROM_DATABASE=Bri-Link Technologies Co., Ltd OUI:000116* ID_OUI_FROM_DATABASE=Netspect Technologies, Inc. OUI:000103* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:00062B* ID_OUI_FROM_DATABASE=INTRASERVER TECHNOLOGY OUI:0002C1* ID_OUI_FROM_DATABASE=Innovative Electronic Designs, Inc. OUI:0002C8* ID_OUI_FROM_DATABASE=Technocom Communications Technology (pte) Ltd OUI:0002A9* ID_OUI_FROM_DATABASE=RACOM, s.r.o. OUI:0002B8* ID_OUI_FROM_DATABASE=WHI KONSULT AB OUI:0002AC* ID_OUI_FROM_DATABASE=3PAR data OUI:0002B1* ID_OUI_FROM_DATABASE=Anritsu, Ltd. OUI:00029A* ID_OUI_FROM_DATABASE=Storage Apps OUI:0002A0* ID_OUI_FROM_DATABASE=Flatstack Ltd. OUI:000295* ID_OUI_FROM_DATABASE=IP.Access Limited OUI:000294* ID_OUI_FROM_DATABASE=Tokyo Sokushin Co., Ltd. OUI:000290* ID_OUI_FROM_DATABASE=Woorigisool, Inc. OUI:000286* ID_OUI_FROM_DATABASE=Occam Networks OUI:00028B* ID_OUI_FROM_DATABASE=VDSL Systems OY OUI:000222* ID_OUI_FROM_DATABASE=Chromisys, Inc. OUI:00021D* ID_OUI_FROM_DATABASE=Data General Communication Ltd. OUI:00020A* ID_OUI_FROM_DATABASE=Gefran Spa OUI:000216* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000206* ID_OUI_FROM_DATABASE=Telital R&D Denmark A/S OUI:000203* ID_OUI_FROM_DATABASE=Woonsang Telecom, Inc. OUI:0001F7* ID_OUI_FROM_DATABASE=Image Display Systems, Inc. OUI:0001EE* ID_OUI_FROM_DATABASE=Comtrol Europe, Ltd. OUI:0001E2* ID_OUI_FROM_DATABASE=Ando Electric Corporation OUI:0001F1* ID_OUI_FROM_DATABASE=Innovative Concepts, Inc. OUI:00B06D* ID_OUI_FROM_DATABASE=Jones Futurex Inc. OUI:0030FE* ID_OUI_FROM_DATABASE=DSA GmbH OUI:00305E* ID_OUI_FROM_DATABASE=Abelko Innovation OUI:00301E* ID_OUI_FROM_DATABASE=3COM EUROPE LTD. OUI:00304D* ID_OUI_FROM_DATABASE=ESI OUI:003046* ID_OUI_FROM_DATABASE=Controlled Electronic Manageme OUI:00307B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0001D6* ID_OUI_FROM_DATABASE=manroland AG OUI:0001DB* ID_OUI_FROM_DATABASE=Freecom Technologies GmbH OUI:0001DE* ID_OUI_FROM_DATABASE=Trango Systems, Inc. OUI:0001CF* ID_OUI_FROM_DATABASE=Alpha Data Parallel Systems, Ltd. OUI:0001CB* ID_OUI_FROM_DATABASE=EVR OUI:0001C4* ID_OUI_FROM_DATABASE=NeoWave, Inc. OUI:0001C0* ID_OUI_FROM_DATABASE=CompuLab, Ltd. OUI:0001B9* ID_OUI_FROM_DATABASE=SKF Condition Monitoring OUI:0001B5* ID_OUI_FROM_DATABASE=Turin Networks, Inc. OUI:00017F* ID_OUI_FROM_DATABASE=Experience Music Project OUI:00016C* ID_OUI_FROM_DATABASE=FOXCONN OUI:000173* ID_OUI_FROM_DATABASE=AMCC OUI:00015C* ID_OUI_FROM_DATABASE=CADANT INC. OUI:000163* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00010A* ID_OUI_FROM_DATABASE=CIS TECHNOLOGY INC. OUI:00016F* ID_OUI_FROM_DATABASE=Inkel Corp. OUI:000155* ID_OUI_FROM_DATABASE=Promise Technology, Inc. OUI:000151* ID_OUI_FROM_DATABASE=Ensemble Communications OUI:000142* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000132* ID_OUI_FROM_DATABASE=Dranetz - BMI OUI:00D07D* ID_OUI_FROM_DATABASE=COSINE COMMUNICATIONS OUI:00D0CA* ID_OUI_FROM_DATABASE=Intrinsyc Software International Inc. OUI:00D058* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00D067* ID_OUI_FROM_DATABASE=CAMPIO COMMUNICATIONS OUI:00D023* ID_OUI_FROM_DATABASE=INFORTREND TECHNOLOGY, INC. OUI:00D02A* ID_OUI_FROM_DATABASE=Voxent Systems Ltd. OUI:00D068* ID_OUI_FROM_DATABASE=IWILL CORPORATION OUI:00D09D* ID_OUI_FROM_DATABASE=VERIS INDUSTRIES OUI:00D09A* ID_OUI_FROM_DATABASE=FILANET CORPORATION OUI:00D00A* ID_OUI_FROM_DATABASE=LANACCESS TELECOM S.A. OUI:00D04A* ID_OUI_FROM_DATABASE=PRESENCE TECHNOLOGY GMBH OUI:00D0C3* ID_OUI_FROM_DATABASE=VIVID TECHNOLOGY PTE, LTD. OUI:00D0F8* ID_OUI_FROM_DATABASE=FUJIAN STAR TERMINAL OUI:00D096* ID_OUI_FROM_DATABASE=3COM EUROPE LTD. OUI:00D003* ID_OUI_FROM_DATABASE=COMDA ENTERPRISES CORP. OUI:00D029* ID_OUI_FROM_DATABASE=WAKEFERN FOOD CORPORATION OUI:00D0F5* ID_OUI_FROM_DATABASE=ORANGE MICRO, INC. OUI:00D0F7* ID_OUI_FROM_DATABASE=NEXT NETS CORPORATION OUI:00D078* ID_OUI_FROM_DATABASE=Eltex of Sweden AB OUI:00D0AF* ID_OUI_FROM_DATABASE=CUTLER-HAMMER, INC. OUI:00D026* ID_OUI_FROM_DATABASE=HIRSCHMANN AUSTRIA GMBH OUI:00D037* ID_OUI_FROM_DATABASE=Pace France OUI:00D010* ID_OUI_FROM_DATABASE=CONVERGENT NETWORKS, INC. OUI:00D074* ID_OUI_FROM_DATABASE=TAQUA SYSTEMS, INC. OUI:00D0D5* ID_OUI_FROM_DATABASE=GRUNDIG AG OUI:00D034* ID_OUI_FROM_DATABASE=ORMEC SYSTEMS CORP. OUI:00D08C* ID_OUI_FROM_DATABASE=GENOA TECHNOLOGY, INC. OUI:00D059* ID_OUI_FROM_DATABASE=AMBIT MICROSYSTEMS CORP. OUI:005020* ID_OUI_FROM_DATABASE=MEDIASTAR CO., LTD. OUI:00503E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00D02B* ID_OUI_FROM_DATABASE=JETCELL, INC. OUI:005017* ID_OUI_FROM_DATABASE=RSR S.R.L. OUI:00D0CC* ID_OUI_FROM_DATABASE=TECHNOLOGIES LYRE INC. OUI:00506D* ID_OUI_FROM_DATABASE=VIDEOJET SYSTEMS OUI:005077* ID_OUI_FROM_DATABASE=PROLIFIC TECHNOLOGY, INC. OUI:0050D4* ID_OUI_FROM_DATABASE=JOOHONG INFORMATION & OUI:00505E* ID_OUI_FROM_DATABASE=DIGITEK MICROLOGIC S.A. OUI:0050E7* ID_OUI_FROM_DATABASE=PARADISE INNOVATIONS (ASIA) OUI:0050B9* ID_OUI_FROM_DATABASE=XITRON TECHNOLOGIES, INC. OUI:00D049* ID_OUI_FROM_DATABASE=IMPRESSTEK CO., LTD. OUI:00D04D* ID_OUI_FROM_DATABASE=DIV OF RESEARCH & STATISTICS OUI:00D035* ID_OUI_FROM_DATABASE=BEHAVIOR TECH. COMPUTER CORP. OUI:00D02D* ID_OUI_FROM_DATABASE=ADEMCO OUI:00D07C* ID_OUI_FROM_DATABASE=KOYO ELECTRONICS INC. CO.,LTD. OUI:00D05B* ID_OUI_FROM_DATABASE=ACROLOOP MOTION CONTROL OUI:00D0C6* ID_OUI_FROM_DATABASE=THOMAS & BETTS CORP. OUI:00D02E* ID_OUI_FROM_DATABASE=COMMUNICATION AUTOMATION CORP. OUI:00D0DA* ID_OUI_FROM_DATABASE=TAICOM DATA SYSTEMS CO., LTD. OUI:00D0E8* ID_OUI_FROM_DATABASE=MAC SYSTEM CO., LTD. OUI:00D03C* ID_OUI_FROM_DATABASE=Vieo, Inc. OUI:00D09F* ID_OUI_FROM_DATABASE=NOVTEK TEST SYSTEMS OUI:00D07E* ID_OUI_FROM_DATABASE=KEYCORP LTD. OUI:00D0EA* ID_OUI_FROM_DATABASE=NEXTONE COMMUNICATIONS, INC. OUI:00D020* ID_OUI_FROM_DATABASE=AIM SYSTEM, INC. OUI:00D064* ID_OUI_FROM_DATABASE=MULTITEL OUI:00D072* ID_OUI_FROM_DATABASE=BROADLOGIC OUI:00309B* ID_OUI_FROM_DATABASE=Smartware OUI:0030AF* ID_OUI_FROM_DATABASE=Honeywell GmbH OUI:003074* ID_OUI_FROM_DATABASE=EQUIINET LTD. OUI:003090* ID_OUI_FROM_DATABASE=CYRA TECHNOLOGIES, INC. OUI:003030* ID_OUI_FROM_DATABASE=HARMONIX CORPORATION OUI:00307C* ID_OUI_FROM_DATABASE=ADID SA OUI:003063* ID_OUI_FROM_DATABASE=SANTERA SYSTEMS, INC. OUI:00309F* ID_OUI_FROM_DATABASE=AMBER NETWORKS OUI:0030A8* ID_OUI_FROM_DATABASE=OL'E COMMUNICATIONS, INC. OUI:00304C* ID_OUI_FROM_DATABASE=APPIAN COMMUNICATIONS, INC. OUI:0030EF* ID_OUI_FROM_DATABASE=NEON TECHNOLOGY, INC. OUI:00306F* ID_OUI_FROM_DATABASE=SEYEON TECH. CO., LTD. OUI:003031* ID_OUI_FROM_DATABASE=LIGHTWAVE COMMUNICATIONS, INC. OUI:003035* ID_OUI_FROM_DATABASE=Corning Incorporated OUI:00302B* ID_OUI_FROM_DATABASE=INALP NETWORKS, INC. OUI:00305F* ID_OUI_FROM_DATABASE=Hasselblad OUI:00302D* ID_OUI_FROM_DATABASE=QUANTUM BRIDGE COMMUNICATIONS OUI:003025* ID_OUI_FROM_DATABASE=CHECKOUT COMPUTER SYSTEMS, LTD OUI:00D01F* ID_OUI_FROM_DATABASE=Senetas Security OUI:003012* ID_OUI_FROM_DATABASE=DIGITAL ENGINEERING LTD. OUI:003077* ID_OUI_FROM_DATABASE=ONPREM NETWORKS OUI:0030D4* ID_OUI_FROM_DATABASE=AAE Systems, Inc. OUI:00D00F* ID_OUI_FROM_DATABASE=SPEECH DESIGN GMBH OUI:00D0CF* ID_OUI_FROM_DATABASE=MORETON BAY OUI:00D073* ID_OUI_FROM_DATABASE=ACN ADVANCED COMMUNICATIONS OUI:00D030* ID_OUI_FROM_DATABASE=Safetran Systems Corp OUI:00D057* ID_OUI_FROM_DATABASE=ULTRAK, INC. OUI:00D03B* ID_OUI_FROM_DATABASE=VISION PRODUCTS PTY. LTD. OUI:00D0BF* ID_OUI_FROM_DATABASE=PIVOTAL TECHNOLOGIES OUI:00D050* ID_OUI_FROM_DATABASE=ISKRATEL OUI:00D0CB* ID_OUI_FROM_DATABASE=DASAN CO., LTD. OUI:00D0D3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00D08E* ID_OUI_FROM_DATABASE=Grass Valley, A Belden Brand OUI:00D0A3* ID_OUI_FROM_DATABASE=VOCAL DATA, INC. OUI:00D0E0* ID_OUI_FROM_DATABASE=DOOIN ELECTRONICS CO. OUI:003054* ID_OUI_FROM_DATABASE=CASTLENET TECHNOLOGY, INC. OUI:003039* ID_OUI_FROM_DATABASE=SOFTBOOK PRESS OUI:003017* ID_OUI_FROM_DATABASE=BlueArc UK Ltd OUI:003076* ID_OUI_FROM_DATABASE=Akamba Corporation OUI:00305D* ID_OUI_FROM_DATABASE=DIGITRA SYSTEMS, INC. OUI:0030F7* ID_OUI_FROM_DATABASE=RAMIX INC. OUI:003033* ID_OUI_FROM_DATABASE=ORIENT TELECOM CO., LTD. OUI:003083* ID_OUI_FROM_DATABASE=Ivron Systems OUI:003007* ID_OUI_FROM_DATABASE=OPTI, INC. OUI:0030DD* ID_OUI_FROM_DATABASE=INDIGITA CORPORATION OUI:0030F2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:003020* ID_OUI_FROM_DATABASE=TSI, Inc.. OUI:003089* ID_OUI_FROM_DATABASE=Spectrapoint Wireless, LLC OUI:003022* ID_OUI_FROM_DATABASE=Fong Kai Industrial Co., Ltd. OUI:0030F8* ID_OUI_FROM_DATABASE=Dynapro Systems, Inc. OUI:0030C2* ID_OUI_FROM_DATABASE=COMONE OUI:003056* ID_OUI_FROM_DATABASE=Beck IPC GmbH OUI:0030D2* ID_OUI_FROM_DATABASE=WIN TECHNOLOGIES, CO., LTD. OUI:003050* ID_OUI_FROM_DATABASE=Versa Technology OUI:0030B8* ID_OUI_FROM_DATABASE=RiverDelta Networks OUI:00904D* ID_OUI_FROM_DATABASE=SPEC S.A. OUI:009079* ID_OUI_FROM_DATABASE=ClearOne, Inc. OUI:00908F* ID_OUI_FROM_DATABASE=AUDIO CODES LTD. OUI:0090D5* ID_OUI_FROM_DATABASE=EUPHONIX, INC. OUI:0090A7* ID_OUI_FROM_DATABASE=CLIENTEC CORPORATION OUI:00907F* ID_OUI_FROM_DATABASE=WatchGuard Technologies, Inc. OUI:00907E* ID_OUI_FROM_DATABASE=VETRONIX CORP. OUI:00902F* ID_OUI_FROM_DATABASE=NETCORE SYSTEMS, INC. OUI:00900D* ID_OUI_FROM_DATABASE=Overland Storage Inc. OUI:009044* ID_OUI_FROM_DATABASE=ASSURED DIGITAL, INC. OUI:009078* ID_OUI_FROM_DATABASE=MER TELEMANAGEMENT SOLUTIONS, LTD. OUI:009009* ID_OUI_FROM_DATABASE=I Controls, Inc. OUI:009015* ID_OUI_FROM_DATABASE=CENTIGRAM COMMUNICATIONS CORP. OUI:0090F3* ID_OUI_FROM_DATABASE=ASPECT COMMUNICATIONS OUI:0090A8* ID_OUI_FROM_DATABASE=NineTiles Networks, Ltd. OUI:00507A* ID_OUI_FROM_DATABASE=XPEED, INC. OUI:005002* ID_OUI_FROM_DATABASE=OMNISEC AG OUI:00508D* ID_OUI_FROM_DATABASE=ABIT COMPUTER CORPORATION OUI:0050CD* ID_OUI_FROM_DATABASE=DIGIANSWER A/S OUI:0050C5* ID_OUI_FROM_DATABASE=ADS Technologies, Inc OUI:00502F* ID_OUI_FROM_DATABASE=TollBridge Technologies, Inc. OUI:005028* ID_OUI_FROM_DATABASE=AVAL COMMUNICATIONS OUI:00505B* ID_OUI_FROM_DATABASE=KAWASAKI LSI U.S.A., INC. OUI:0050F8* ID_OUI_FROM_DATABASE=ENTREGA TECHNOLOGIES, INC. OUI:00506F* ID_OUI_FROM_DATABASE=G-CONNECT OUI:0050CC* ID_OUI_FROM_DATABASE=XYRATEX OUI:0050D5* ID_OUI_FROM_DATABASE=AD SYSTEMS CORP. OUI:0050AA* ID_OUI_FROM_DATABASE=KONICA MINOLTA HOLDINGS, INC. OUI:00509C* ID_OUI_FROM_DATABASE=BETA RESEARCH OUI:005027* ID_OUI_FROM_DATABASE=GENICOM CORPORATION OUI:005010* ID_OUI_FROM_DATABASE=NovaNET Learning, Inc. OUI:00509E* ID_OUI_FROM_DATABASE=Les Technologies SoftAcoustik Inc. OUI:00505F* ID_OUI_FROM_DATABASE=BRAND INNOVATORS OUI:005095* ID_OUI_FROM_DATABASE=PERACOM NETWORKS OUI:005026* ID_OUI_FROM_DATABASE=COSYSTEMS, INC. OUI:0050EF* ID_OUI_FROM_DATABASE=SPE Systemhaus GmbH OUI:005093* ID_OUI_FROM_DATABASE=BOEING OUI:0050D8* ID_OUI_FROM_DATABASE=UNICORN COMPUTER CORP. OUI:009034* ID_OUI_FROM_DATABASE=IMAGIC, INC. OUI:009073* ID_OUI_FROM_DATABASE=GAIO TECHNOLOGY OUI:0090C9* ID_OUI_FROM_DATABASE=DPAC Technologies OUI:0090E7* ID_OUI_FROM_DATABASE=HORSCH ELEKTRONIK AG OUI:009001* ID_OUI_FROM_DATABASE=NISHIMU ELECTRONICS INDUSTRIES CO., LTD. OUI:0090FB* ID_OUI_FROM_DATABASE=PORTWELL, INC. OUI:009070* ID_OUI_FROM_DATABASE=NEO NETWORKS, INC. OUI:0090EF* ID_OUI_FROM_DATABASE=INTEGRIX, INC. OUI:0090B0* ID_OUI_FROM_DATABASE=VADEM OUI:0090D1* ID_OUI_FROM_DATABASE=LEICHU ENTERPRISE CO., LTD. OUI:0050D7* ID_OUI_FROM_DATABASE=TELSTRAT OUI:0050F1* ID_OUI_FROM_DATABASE=Intel Corporation OUI:00501B* ID_OUI_FROM_DATABASE=ABL CANADA, INC. OUI:005036* ID_OUI_FROM_DATABASE=NETCAM, LTD. OUI:0050C9* ID_OUI_FROM_DATABASE=MASPRO DENKOH CORP. OUI:005009* ID_OUI_FROM_DATABASE=PHILIPS BROADBAND NETWORKS OUI:0050C4* ID_OUI_FROM_DATABASE=IMD OUI:0050A3* ID_OUI_FROM_DATABASE=TransMedia Communications, Inc. OUI:005099* ID_OUI_FROM_DATABASE=3COM EUROPE, LTD. OUI:0050A4* ID_OUI_FROM_DATABASE=IO TECH, INC. OUI:0050B3* ID_OUI_FROM_DATABASE=VOICEBOARD CORPORATION OUI:0050B7* ID_OUI_FROM_DATABASE=BOSER TECHNOLOGY CO., LTD. OUI:005056* ID_OUI_FROM_DATABASE=VMware, Inc. OUI:00908D* ID_OUI_FROM_DATABASE=VICKERS ELECTRONICS SYSTEMS OUI:009042* ID_OUI_FROM_DATABASE=ECCS, Inc. OUI:009051* ID_OUI_FROM_DATABASE=ULTIMATE TECHNOLOGY CORP. OUI:0090FF* ID_OUI_FROM_DATABASE=TELLUS TECHNOLOGY INC. OUI:009018* ID_OUI_FROM_DATABASE=ITO ELECTRIC INDUSTRY CO, LTD. OUI:009002* ID_OUI_FROM_DATABASE=ALLGON AB OUI:009016* ID_OUI_FROM_DATABASE=ZAC OUI:009005* ID_OUI_FROM_DATABASE=PROTECH SYSTEMS CO., LTD. OUI:00901E* ID_OUI_FROM_DATABASE=Selesta Ingegneria S.p.A. OUI:009090* ID_OUI_FROM_DATABASE=I-BUS OUI:0090AA* ID_OUI_FROM_DATABASE=INDIGO ACTIVE VISION SYSTEMS LIMITED OUI:00903A* ID_OUI_FROM_DATABASE=NIHON MEDIA TOOL INC. OUI:009055* ID_OUI_FROM_DATABASE=PARKER HANNIFIN CORPORATION COMPUMOTOR DIVISION OUI:00909F* ID_OUI_FROM_DATABASE=DIGI-DATA CORPORATION OUI:0090E4* ID_OUI_FROM_DATABASE=NEC AMERICA, INC. OUI:009013* ID_OUI_FROM_DATABASE=SAMSAN CORP. OUI:0090CC* ID_OUI_FROM_DATABASE=Planex Communications OUI:009004* ID_OUI_FROM_DATABASE=3COM EUROPE LTD. OUI:0090E1* ID_OUI_FROM_DATABASE=TELENA S.P.A. OUI:00504A* ID_OUI_FROM_DATABASE=ELTECO A.S. OUI:00504C* ID_OUI_FROM_DATABASE=Galil Motion Control OUI:005021* ID_OUI_FROM_DATABASE=EIS INTERNATIONAL, INC. OUI:00506E* ID_OUI_FROM_DATABASE=CORDER ENGINEERING CORPORATION OUI:00507E* ID_OUI_FROM_DATABASE=NEWER TECHNOLOGY OUI:0050E6* ID_OUI_FROM_DATABASE=HAKUSAN CORPORATION OUI:0050AE* ID_OUI_FROM_DATABASE=FDK Co., Ltd OUI:00109D* ID_OUI_FROM_DATABASE=CLARINET SYSTEMS, INC. OUI:0010D2* ID_OUI_FROM_DATABASE=NITTO TSUSHINKI CO., LTD OUI:001045* ID_OUI_FROM_DATABASE=Nortel Networks OUI:00106B* ID_OUI_FROM_DATABASE=SONUS NETWORKS, INC. OUI:0010EC* ID_OUI_FROM_DATABASE=RPCG, LLC OUI:001092* ID_OUI_FROM_DATABASE=NETCORE INC. OUI:0010E2* ID_OUI_FROM_DATABASE=ArrayComm, Inc. OUI:001071* ID_OUI_FROM_DATABASE=ADVANET INC. OUI:001069* ID_OUI_FROM_DATABASE=HELIOSS COMMUNICATIONS, INC. OUI:0010FD* ID_OUI_FROM_DATABASE=COCOM A/S OUI:0010AC* ID_OUI_FROM_DATABASE=IMCI TECHNOLOGIES OUI:0010EF* ID_OUI_FROM_DATABASE=DBTEL INCORPORATED OUI:001017* ID_OUI_FROM_DATABASE=Bosch Access Systems GmbH OUI:001024* ID_OUI_FROM_DATABASE=NAGOYA ELECTRIC WORKS CO., LTD OUI:0010DD* ID_OUI_FROM_DATABASE=ENABLE SEMICONDUCTOR, INC. OUI:0010C9* ID_OUI_FROM_DATABASE=MITSUBISHI ELECTRONICS LOGISTIC SUPPORT CO. OUI:001085* ID_OUI_FROM_DATABASE=POLARIS COMMUNICATIONS, INC. OUI:001044* ID_OUI_FROM_DATABASE=InnoLabs Corporation OUI:001056* ID_OUI_FROM_DATABASE=SODICK CO., LTD. OUI:001099* ID_OUI_FROM_DATABASE=InnoMedia, Inc. OUI:001061* ID_OUI_FROM_DATABASE=HOSTLINK CORP. OUI:001093* ID_OUI_FROM_DATABASE=CMS COMPUTERS, LTD. OUI:0010CD* ID_OUI_FROM_DATABASE=INTERFACE CONCEPT OUI:0010F3* ID_OUI_FROM_DATABASE=Nexcom International Co., Ltd. OUI:001005* ID_OUI_FROM_DATABASE=UEC COMMERCIAL OUI:001066* ID_OUI_FROM_DATABASE=ADVANCED CONTROL SYSTEMS, INC. OUI:0010E4* ID_OUI_FROM_DATABASE=NSI CORPORATION OUI:001062* ID_OUI_FROM_DATABASE=NX SERVER, ILNC. OUI:0010B9* ID_OUI_FROM_DATABASE=MAXTOR CORP. OUI:00108B* ID_OUI_FROM_DATABASE=LASERANIMATION SOLLINGER GMBH OUI:00105C* ID_OUI_FROM_DATABASE=QUANTUM DESIGNS (H.K.) LTD. OUI:001042* ID_OUI_FROM_DATABASE=Alacritech, Inc. OUI:001060* ID_OUI_FROM_DATABASE=BILLIONTON SYSTEMS, INC. OUI:0010DE* ID_OUI_FROM_DATABASE=INTERNATIONAL DATACASTING CORPORATION OUI:00105D* ID_OUI_FROM_DATABASE=Draeger Medical OUI:0010E1* ID_OUI_FROM_DATABASE=S.I. TECH, INC. OUI:001091* ID_OUI_FROM_DATABASE=NO WIRES NEEDED BV OUI:0010F5* ID_OUI_FROM_DATABASE=AMHERST SYSTEMS, INC. OUI:001090* ID_OUI_FROM_DATABASE=CIMETRICS, INC. OUI:001070* ID_OUI_FROM_DATABASE=CARADON TREND LTD. OUI:0010BA* ID_OUI_FROM_DATABASE=MARTINHO-DAVIS SYSTEMS, INC. OUI:00107C* ID_OUI_FROM_DATABASE=P-COM, INC. OUI:0010AE* ID_OUI_FROM_DATABASE=SHINKO ELECTRIC INDUSTRIES CO. OUI:001040* ID_OUI_FROM_DATABASE=INTERMEC CORPORATION OUI:0010B0* ID_OUI_FROM_DATABASE=MERIDIAN TECHNOLOGY CORP. OUI:001077* ID_OUI_FROM_DATABASE=SAF DRIVE SYSTEMS, LTD. OUI:0010F4* ID_OUI_FROM_DATABASE=Vertical Communications OUI:001065* ID_OUI_FROM_DATABASE=RADYNE CORPORATION OUI:00104A* ID_OUI_FROM_DATABASE=The Parvus Corporation OUI:0010B3* ID_OUI_FROM_DATABASE=NOKIA MULTIMEDIA TERMINALS OUI:001037* ID_OUI_FROM_DATABASE=CYQ've Technology Co., Ltd. OUI:0010CA* ID_OUI_FROM_DATABASE=Telco Systems, Inc. OUI:001051* ID_OUI_FROM_DATABASE=CMICRO CORPORATION OUI:0010DC* ID_OUI_FROM_DATABASE=MICRO-STAR INTERNATIONAL CO., LTD. OUI:0010EE* ID_OUI_FROM_DATABASE=CTI PRODUCTS, INC. OUI:00101B* ID_OUI_FROM_DATABASE=CORNET TECHNOLOGY, INC. OUI:001032* ID_OUI_FROM_DATABASE=ALTA TECHNOLOGY OUI:001025* ID_OUI_FROM_DATABASE=Grayhill, Inc OUI:001009* ID_OUI_FROM_DATABASE=HORO QUARTZ OUI:0010F8* ID_OUI_FROM_DATABASE=TEXIO TECHNOLOGY CORPORATION OUI:00104D* ID_OUI_FROM_DATABASE=SURTEC INDUSTRIES, INC. OUI:00E0E0* ID_OUI_FROM_DATABASE=SI ELECTRONICS, LTD. OUI:00E00F* ID_OUI_FROM_DATABASE=SHANGHAI BAUD DATA OUI:00E0D1* ID_OUI_FROM_DATABASE=TELSIS LIMITED OUI:00E005* ID_OUI_FROM_DATABASE=TECHNICAL CORP. OUI:00E072* ID_OUI_FROM_DATABASE=LYNK OUI:00E0C1* ID_OUI_FROM_DATABASE=MEMOREX TELEX JAPAN, LTD. OUI:00E0AD* ID_OUI_FROM_DATABASE=EES TECHNOLOGY, LTD. OUI:00E025* ID_OUI_FROM_DATABASE=dit Co., Ltd. OUI:00E0B1* ID_OUI_FROM_DATABASE=Alcatel-Lucent, Enterprise Business Group OUI:00E0E4* ID_OUI_FROM_DATABASE=FANUC ROBOTICS NORTH AMERICA, Inc. OUI:00E031* ID_OUI_FROM_DATABASE=HAGIWARA ELECTRIC CO., LTD. OUI:00E0A5* ID_OUI_FROM_DATABASE=ComCore Semiconductor, Inc. OUI:00E044* ID_OUI_FROM_DATABASE=LSICS CORPORATION OUI:00E05D* ID_OUI_FROM_DATABASE=UNITEC CO., LTD. OUI:00E0B3* ID_OUI_FROM_DATABASE=EtherWAN Systems, Inc. OUI:00E053* ID_OUI_FROM_DATABASE=CELLPORT LABS, INC. OUI:00E07D* ID_OUI_FROM_DATABASE=NETRONIX, INC. OUI:00E0ED* ID_OUI_FROM_DATABASE=SILICOM, LTD. OUI:00E0B4* ID_OUI_FROM_DATABASE=TECHNO SCOPE CO., LTD. OUI:00E0C6* ID_OUI_FROM_DATABASE=LINK2IT, L.L.C. OUI:00E06D* ID_OUI_FROM_DATABASE=COMPUWARE CORPORATION OUI:00E074* ID_OUI_FROM_DATABASE=TIERNAN COMMUNICATIONS, INC. OUI:00E059* ID_OUI_FROM_DATABASE=CONTROLLED ENVIRONMENTS, LTD. OUI:00E006* ID_OUI_FROM_DATABASE=SILICON INTEGRATED SYS. CORP. OUI:00E0F8* ID_OUI_FROM_DATABASE=DICNA CONTROL AB OUI:00E004* ID_OUI_FROM_DATABASE=PMC-SIERRA, INC. OUI:00E0DE* ID_OUI_FROM_DATABASE=DATAX NV OUI:00E078* ID_OUI_FROM_DATABASE=BERKELEY NETWORKS OUI:00E041* ID_OUI_FROM_DATABASE=CSPI OUI:00E0E2* ID_OUI_FROM_DATABASE=INNOVA CORP. OUI:00E009* ID_OUI_FROM_DATABASE=MARATHON TECHNOLOGIES CORP. OUI:00E02F* ID_OUI_FROM_DATABASE=MCNS HOLDINGS, L.P. OUI:00E04C* ID_OUI_FROM_DATABASE=REALTEK SEMICONDUCTOR CORP. OUI:00E047* ID_OUI_FROM_DATABASE=InFocus Corporation OUI:00E092* ID_OUI_FROM_DATABASE=ADMTEK INCORPORATED OUI:00E0FF* ID_OUI_FROM_DATABASE=SECURITY DYNAMICS TECHNOLOGIES, Inc. OUI:08BBCC* ID_OUI_FROM_DATABASE=AK-NORD EDV VERTRIEBSGES. mbH OUI:0060B2* ID_OUI_FROM_DATABASE=PROCESS CONTROL CORP. OUI:006004* ID_OUI_FROM_DATABASE=COMPUTADORES MODULARES SA OUI:0060D6* ID_OUI_FROM_DATABASE=NovAtel Wireless Technologies Ltd. OUI:006000* ID_OUI_FROM_DATABASE=XYCOM INC. OUI:00A019* ID_OUI_FROM_DATABASE=NEBULA CONSULTANTS, INC. OUI:00A0ED* ID_OUI_FROM_DATABASE=Brooks Automation, Inc. OUI:00A0A9* ID_OUI_FROM_DATABASE=NAVTEL COMMUNICATIONS INC. OUI:00A0E1* ID_OUI_FROM_DATABASE=WESTPORT RESEARCH ASSOCIATES, INC. OUI:00A0D6* ID_OUI_FROM_DATABASE=SBE, Inc. OUI:00A05E* ID_OUI_FROM_DATABASE=MYRIAD LOGIC INC. OUI:00A078* ID_OUI_FROM_DATABASE=Marconi Communications OUI:00A00B* ID_OUI_FROM_DATABASE=COMPUTEX CO., LTD. OUI:00A09A* ID_OUI_FROM_DATABASE=NIHON KOHDEN AMERICA OUI:00A095* ID_OUI_FROM_DATABASE=ACACIA NETWORKS, INC. OUI:00A0F2* ID_OUI_FROM_DATABASE=INFOTEK COMMUNICATIONS, INC. OUI:00A0EF* ID_OUI_FROM_DATABASE=LUCIDATA LTD. OUI:00A03F* ID_OUI_FROM_DATABASE=COMPUTER SOCIETY MICROPROCESSOR & MICROPROCESSOR STANDARDS C OUI:00A067* ID_OUI_FROM_DATABASE=NETWORK SERVICES GROUP OUI:00A0A7* ID_OUI_FROM_DATABASE=VORAX CORPORATION OUI:00A02D* ID_OUI_FROM_DATABASE=1394 Trade Association OUI:00A0E6* ID_OUI_FROM_DATABASE=DIALOGIC CORPORATION OUI:00A04A* ID_OUI_FROM_DATABASE=NISSHIN ELECTRIC CO., LTD. OUI:00A05B* ID_OUI_FROM_DATABASE=MARQUIP, INC. OUI:00A08D* ID_OUI_FROM_DATABASE=JACOMO CORPORATION OUI:00A06F* ID_OUI_FROM_DATABASE=THE APPCON GROUP, INC. OUI:00A08E* ID_OUI_FROM_DATABASE=Check Point Software Technologies OUI:00E0AA* ID_OUI_FROM_DATABASE=ELECTROSONIC LTD. OUI:00E085* ID_OUI_FROM_DATABASE=GLOBAL MAINTECH, INC. OUI:00E05A* ID_OUI_FROM_DATABASE=GALEA NETWORK SECURITY OUI:00E022* ID_OUI_FROM_DATABASE=Analog Devices Inc. OUI:00E0E7* ID_OUI_FROM_DATABASE=RAYTHEON E-SYSTEMS, INC. OUI:00E00C* ID_OUI_FROM_DATABASE=MOTOROLA OUI:00E04A* ID_OUI_FROM_DATABASE=ZX Technologies, Inc OUI:00E00A* ID_OUI_FROM_DATABASE=DIBA, INC. OUI:00E0B9* ID_OUI_FROM_DATABASE=BYAS SYSTEMS OUI:00E054* ID_OUI_FROM_DATABASE=KODAI HITEC CO., LTD. OUI:00E0AF* ID_OUI_FROM_DATABASE=GENERAL DYNAMICS INFORMATION SYSTEMS OUI:00605B* ID_OUI_FROM_DATABASE=IntraServer Technology, Inc. OUI:00604B* ID_OUI_FROM_DATABASE=Safe-com GmbH & Co. KG OUI:00A0CD* ID_OUI_FROM_DATABASE=DR. JOHANNES HEIDENHAIN GmbH OUI:00A0DA* ID_OUI_FROM_DATABASE=INTEGRATED SYSTEMS Technology, Inc. OUI:00A03C* ID_OUI_FROM_DATABASE=EG&G NUCLEAR INSTRUMENTS OUI:00A038* ID_OUI_FROM_DATABASE=EMAIL ELECTRONICS OUI:00A0BE* ID_OUI_FROM_DATABASE=INTEGRATED CIRCUIT SYSTEMS, INC. COMMUNICATIONS GROUP OUI:00605D* ID_OUI_FROM_DATABASE=SCANIVALVE CORP. OUI:0060E4* ID_OUI_FROM_DATABASE=COMPUSERVE, INC. OUI:00600A* ID_OUI_FROM_DATABASE=SORD COMPUTER CORPORATION OUI:0060C4* ID_OUI_FROM_DATABASE=SOLITON SYSTEMS K.K. OUI:0060C8* ID_OUI_FROM_DATABASE=KUKA WELDING SYSTEMS & ROBOTS OUI:006030* ID_OUI_FROM_DATABASE=VILLAGE TRONIC ENTWICKLUNG OUI:0060E7* ID_OUI_FROM_DATABASE=RANDATA OUI:00602A* ID_OUI_FROM_DATABASE=SYMICRON COMPUTER COMMUNICATIONS, LTD. OUI:00601E* ID_OUI_FROM_DATABASE=SOFTLAB, INC. OUI:0060F8* ID_OUI_FROM_DATABASE=Loran International Technologies Inc. OUI:006088* ID_OUI_FROM_DATABASE=WHITE MOUNTAIN DSP, INC. OUI:00609A* ID_OUI_FROM_DATABASE=NJK TECHNO CO. OUI:0060CC* ID_OUI_FROM_DATABASE=EMTRAK, INCORPORATED OUI:006036* ID_OUI_FROM_DATABASE=AIT Austrian Institute of Technology GmbH OUI:0060B9* ID_OUI_FROM_DATABASE=NEC Platforms, Ltd OUI:0060CE* ID_OUI_FROM_DATABASE=ACCLAIM COMMUNICATIONS OUI:0060F5* ID_OUI_FROM_DATABASE=ICON WEST, INC. OUI:0060A4* ID_OUI_FROM_DATABASE=GEW Technologies (PTY)Ltd OUI:0060CA* ID_OUI_FROM_DATABASE=HARMONIC SYSTEMS INCORPORATED OUI:006024* ID_OUI_FROM_DATABASE=GRADIENT TECHNOLOGIES, INC. OUI:0060FB* ID_OUI_FROM_DATABASE=PACKETEER, INC. OUI:0060BC* ID_OUI_FROM_DATABASE=KeunYoung Electronics & Communication Co., Ltd. OUI:0060B8* ID_OUI_FROM_DATABASE=CORELIS Inc. OUI:0060FE* ID_OUI_FROM_DATABASE=LYNX SYSTEM DEVELOPERS, INC. OUI:006001* ID_OUI_FROM_DATABASE=InnoSys, Inc. OUI:00607D* ID_OUI_FROM_DATABASE=SENTIENT NETWORKS INC. OUI:00606E* ID_OUI_FROM_DATABASE=DAVICOM SEMICONDUCTOR, INC. OUI:00607E* ID_OUI_FROM_DATABASE=GIGALABS, INC. OUI:0060CF* ID_OUI_FROM_DATABASE=ALTEON NETWORKS, INC. OUI:006026* ID_OUI_FROM_DATABASE=VIKING Modular Solutions OUI:006003* ID_OUI_FROM_DATABASE=TERAOKA WEIGH SYSTEM PTE, LTD. OUI:006059* ID_OUI_FROM_DATABASE=TECHNICAL COMMUNICATIONS CORP. OUI:006066* ID_OUI_FROM_DATABASE=LACROIX Trafic OUI:0060DA* ID_OUI_FROM_DATABASE=Red Lion Controls, LP OUI:006042* ID_OUI_FROM_DATABASE=TKS (USA), INC. OUI:00A023* ID_OUI_FROM_DATABASE=APPLIED CREATIVE TECHNOLOGY, INC. OUI:00A00F* ID_OUI_FROM_DATABASE=Broadband Technologies OUI:00A032* ID_OUI_FROM_DATABASE=GES SINGAPORE PTE. LTD. OUI:002034* ID_OUI_FROM_DATABASE=ROTEC INDUSTRIEAUTOMATION GMBH OUI:0020B2* ID_OUI_FROM_DATABASE=GKD Gesellschaft Fur Kommunikation Und Datentechnik OUI:002004* ID_OUI_FROM_DATABASE=YAMATAKE-HONEYWELL CO., LTD. OUI:0020FE* ID_OUI_FROM_DATABASE=TOPWARE INC. / GRAND COMPUTER OUI:002073* ID_OUI_FROM_DATABASE=FUSION SYSTEMS CORPORATION OUI:00207A* ID_OUI_FROM_DATABASE=WiSE Communications, Inc. OUI:00205C* ID_OUI_FROM_DATABASE=InterNet Systems of Florida, Inc. OUI:00207E* ID_OUI_FROM_DATABASE=FINECOM CO., LTD. OUI:00205A* ID_OUI_FROM_DATABASE=COMPUTER IDENTICS OUI:0020E4* ID_OUI_FROM_DATABASE=HSING TECH ENTERPRISE CO., LTD OUI:00A000* ID_OUI_FROM_DATABASE=CENTILLION NETWORKS, INC. OUI:00A07B* ID_OUI_FROM_DATABASE=DAWN COMPUTER INCORPORATION OUI:00A05C* ID_OUI_FROM_DATABASE=INVENTORY CONVERSION, INC./ OUI:00206F* ID_OUI_FROM_DATABASE=FLOWPOINT CORPORATION OUI:0020DF* ID_OUI_FROM_DATABASE=KYOSAN ELECTRIC MFG. CO., LTD. OUI:002010* ID_OUI_FROM_DATABASE=JEOL SYSTEM TECHNOLOGY CO. LTD OUI:002020* ID_OUI_FROM_DATABASE=MEGATRON COMPUTER INDUSTRIES PTY, LTD. OUI:002037* ID_OUI_FROM_DATABASE=SEAGATE TECHNOLOGY OUI:0020A0* ID_OUI_FROM_DATABASE=OA LABORATORY CO., LTD. OUI:00C0A3* ID_OUI_FROM_DATABASE=DUAL ENTERPRISES CORPORATION OUI:00C095* ID_OUI_FROM_DATABASE=ZNYX OUI:0070B0* ID_OUI_FROM_DATABASE=M/A-COM INC. COMPANIES OUI:009D8E* ID_OUI_FROM_DATABASE=CARDIAC RECORDERS, INC. OUI:006086* ID_OUI_FROM_DATABASE=LOGIC REPLACEMENT TECH. LTD. OUI:001C7C* ID_OUI_FROM_DATABASE=PERQ SYSTEMS CORPORATION OUI:00C059* ID_OUI_FROM_DATABASE=DENSO CORPORATION OUI:00C0A9* ID_OUI_FROM_DATABASE=BARRON MCCANN LTD. OUI:00C069* ID_OUI_FROM_DATABASE=Axxcelera Broadband Wireless OUI:00C019* ID_OUI_FROM_DATABASE=LEAP TECHNOLOGY, INC. OUI:00A062* ID_OUI_FROM_DATABASE=AES PRODATA OUI:00A008* ID_OUI_FROM_DATABASE=NETCORP OUI:00A01B* ID_OUI_FROM_DATABASE=PREMISYS COMMUNICATIONS, INC. OUI:00A04B* ID_OUI_FROM_DATABASE=TFL LAN INC. OUI:00A015* ID_OUI_FROM_DATABASE=WYLE OUI:00A011* ID_OUI_FROM_DATABASE=MUTOH INDUSTRIES LTD. OUI:00A0B6* ID_OUI_FROM_DATABASE=SANRITZ AUTOMATION CO., LTD. OUI:00A0DD* ID_OUI_FROM_DATABASE=AZONIX CORPORATION OUI:00A00A* ID_OUI_FROM_DATABASE=Airspan OUI:00A03B* ID_OUI_FROM_DATABASE=TOSHIN ELECTRIC CO., LTD. OUI:00A0F3* ID_OUI_FROM_DATABASE=STAUBLI OUI:00A097* ID_OUI_FROM_DATABASE=JC INFORMATION SYSTEMS OUI:00A082* ID_OUI_FROM_DATABASE=NKT ELEKTRONIK A/S OUI:00A072* ID_OUI_FROM_DATABASE=OVATION SYSTEMS LTD. OUI:00A0B2* ID_OUI_FROM_DATABASE=SHIMA SEIKI OUI:00A0E5* ID_OUI_FROM_DATABASE=NHC COMMUNICATIONS OUI:00A0D3* ID_OUI_FROM_DATABASE=INSTEM COMPUTER SYSTEMS, LTD. OUI:00A0BA* ID_OUI_FROM_DATABASE=PATTON ELECTRONICS CO. OUI:00A0B4* ID_OUI_FROM_DATABASE=TEXAS MICROSYSTEMS, INC. OUI:00A0AF* ID_OUI_FROM_DATABASE=WMS INDUSTRIES OUI:00A0FE* ID_OUI_FROM_DATABASE=BOSTON TECHNOLOGY, INC. OUI:00202F* ID_OUI_FROM_DATABASE=ZETA COMMUNICATIONS, LTD. OUI:002060* ID_OUI_FROM_DATABASE=ALCATEL ITALIA S.p.A. OUI:00209A* ID_OUI_FROM_DATABASE=THE 3DO COMPANY OUI:00205E* ID_OUI_FROM_DATABASE=CASTLE ROCK, INC. OUI:00207C* ID_OUI_FROM_DATABASE=AUTEC GMBH OUI:002075* ID_OUI_FROM_DATABASE=MOTOROLA COMMUNICATION ISRAEL OUI:002015* ID_OUI_FROM_DATABASE=ACTIS COMPUTER SA OUI:0020E9* ID_OUI_FROM_DATABASE=DANTEL OUI:00204A* ID_OUI_FROM_DATABASE=PRONET GMBH OUI:002029* ID_OUI_FROM_DATABASE=TELEPROCESSING PRODUCTS, INC. OUI:002051* ID_OUI_FROM_DATABASE=Verilink Corporation OUI:0020A1* ID_OUI_FROM_DATABASE=DOVATRON OUI:002024* ID_OUI_FROM_DATABASE=PACIFIC COMMUNICATION SCIENCES OUI:00209D* ID_OUI_FROM_DATABASE=LIPPERT AUTOMATIONSTECHNIK OUI:002041* ID_OUI_FROM_DATABASE=DATA NET OUI:002076* ID_OUI_FROM_DATABASE=REUDO CORPORATION OUI:00206E* ID_OUI_FROM_DATABASE=XACT, INC. OUI:0020CA* ID_OUI_FROM_DATABASE=DIGITAL OCEAN OUI:002085* ID_OUI_FROM_DATABASE=Eaton Corporation OUI:0020CD* ID_OUI_FROM_DATABASE=HYBRID NETWORKS, INC. OUI:0020E7* ID_OUI_FROM_DATABASE=B&W NUCLEAR SERVICE COMPANY OUI:0020AC* ID_OUI_FROM_DATABASE=INTERFLEX DATENSYSTEME GMBH OUI:0020F6* ID_OUI_FROM_DATABASE=NET TEK AND KARLNET, INC. OUI:0020D3* ID_OUI_FROM_DATABASE=OST (OUEST STANDARD TELEMATIQU OUI:0020D8* ID_OUI_FROM_DATABASE=Nortel Networks OUI:002017* ID_OUI_FROM_DATABASE=ORBOTECH OUI:002025* ID_OUI_FROM_DATABASE=CONTROL TECHNOLOGY, INC. OUI:00C08B* ID_OUI_FROM_DATABASE=RISQ MODULAR SYSTEMS, INC. OUI:00C0CD* ID_OUI_FROM_DATABASE=COMELTA, S.A. OUI:00C04B* ID_OUI_FROM_DATABASE=CREATIVE MICROSYSTEMS OUI:00C0A1* ID_OUI_FROM_DATABASE=TOKYO DENSHI SEKEI CO. OUI:00C03E* ID_OUI_FROM_DATABASE=FA. GEBR. HELLER GMBH OUI:00C0E1* ID_OUI_FROM_DATABASE=SONIC SOLUTIONS OUI:00C047* ID_OUI_FROM_DATABASE=UNIMICRO SYSTEMS, INC. OUI:00C046* ID_OUI_FROM_DATABASE=Blue Chip Technology Ltd OUI:00C00D* ID_OUI_FROM_DATABASE=ADVANCED LOGIC RESEARCH, INC. OUI:00C0FA* ID_OUI_FROM_DATABASE=CANARY COMMUNICATIONS, INC. OUI:00C0B7* ID_OUI_FROM_DATABASE=AMERICAN POWER CONVERSION CORP OUI:00C0BA* ID_OUI_FROM_DATABASE=NETVANTAGE OUI:00C0B6* ID_OUI_FROM_DATABASE=Overland Storage, Inc. OUI:00C048* ID_OUI_FROM_DATABASE=BAY TECHNICAL ASSOCIATES OUI:00C03F* ID_OUI_FROM_DATABASE=STORES AUTOMATED SYSTEMS, INC. OUI:00C00E* ID_OUI_FROM_DATABASE=PSITECH, INC. OUI:00C036* ID_OUI_FROM_DATABASE=RAYTECH ELECTRONIC CORP. OUI:00C009* ID_OUI_FROM_DATABASE=KT TECHNOLOGY (S) PTE LTD OUI:00C0EA* ID_OUI_FROM_DATABASE=ARRAY TECHNOLOGY LTD. OUI:00C03A* ID_OUI_FROM_DATABASE=MEN-MIKRO ELEKTRONIK GMBH OUI:00C040* ID_OUI_FROM_DATABASE=ECCI OUI:00C04C* ID_OUI_FROM_DATABASE=DEPARTMENT OF FOREIGN AFFAIRS OUI:00C01C* ID_OUI_FROM_DATABASE=INTERLINK COMMUNICATIONS LTD. OUI:00C017* ID_OUI_FROM_DATABASE=Fluke Corporation OUI:00C086* ID_OUI_FROM_DATABASE=THE LYNK CORPORATION OUI:00C08D* ID_OUI_FROM_DATABASE=TRONIX PRODUCT DEVELOPMENT OUI:00C0AB* ID_OUI_FROM_DATABASE=Telco Systems, Inc. OUI:00C0A2* ID_OUI_FROM_DATABASE=INTERMEDIUM A/S OUI:00C070* ID_OUI_FROM_DATABASE=SECTRA SECURE-TRANSMISSION AB OUI:00C057* ID_OUI_FROM_DATABASE=MYCO ELECTRONICS OUI:00C0DF* ID_OUI_FROM_DATABASE=KYE Systems Corp. OUI:00C0F6* ID_OUI_FROM_DATABASE=CELAN TECHNOLOGY INC. OUI:00C08F* ID_OUI_FROM_DATABASE=Panasonic Electric Works Co., Ltd. OUI:00C012* ID_OUI_FROM_DATABASE=NETSPAN CORPORATION OUI:00C0C4* ID_OUI_FROM_DATABASE=COMPUTER OPERATIONAL OUI:00C0C2* ID_OUI_FROM_DATABASE=INFINITE NETWORKS LTD. OUI:00C0D3* ID_OUI_FROM_DATABASE=OLYMPUS IMAGE SYSTEMS, INC. OUI:00C0B0* ID_OUI_FROM_DATABASE=GCC TECHNOLOGIES,INC. OUI:00C0F4* ID_OUI_FROM_DATABASE=INTERLINK SYSTEM CO., LTD. OUI:00C0E2* ID_OUI_FROM_DATABASE=CALCOMP, INC. OUI:00C0CA* ID_OUI_FROM_DATABASE=ALFA, INC. OUI:00C07B* ID_OUI_FROM_DATABASE=ASCEND COMMUNICATIONS, INC. OUI:00C052* ID_OUI_FROM_DATABASE=BURR-BROWN OUI:00C0BE* ID_OUI_FROM_DATABASE=ALCATEL - SEL OUI:00408F* ID_OUI_FROM_DATABASE=WM-DATA MINFO AB OUI:0040B7* ID_OUI_FROM_DATABASE=STEALTH COMPUTER SYSTEMS OUI:004057* ID_OUI_FROM_DATABASE=LOCKHEED - SANDERS OUI:004017* ID_OUI_FROM_DATABASE=Silex Technology America OUI:004087* ID_OUI_FROM_DATABASE=UBITREX CORPORATION OUI:00400E* ID_OUI_FROM_DATABASE=MEMOTEC, INC. OUI:00C09E* ID_OUI_FROM_DATABASE=CACHE COMPUTERS, INC. OUI:00C093* ID_OUI_FROM_DATABASE=ALTA RESEARCH CORP. OUI:00C034* ID_OUI_FROM_DATABASE=TRANSACTION NETWORK OUI:004034* ID_OUI_FROM_DATABASE=BUSTEK CORPORATION OUI:004097* ID_OUI_FROM_DATABASE=DATEX DIVISION OF OUI:00401E* ID_OUI_FROM_DATABASE=ICC OUI:00407C* ID_OUI_FROM_DATABASE=QUME CORPORATION OUI:004060* ID_OUI_FROM_DATABASE=COMENDEC LTD OUI:004056* ID_OUI_FROM_DATABASE=MCM JAPAN LTD. OUI:004095* ID_OUI_FROM_DATABASE=R.P.T. INTERGROUPS INT'L LTD. OUI:0040C3* ID_OUI_FROM_DATABASE=FISCHER AND PORTER CO. OUI:0040F1* ID_OUI_FROM_DATABASE=CHUO ELECTRONICS CO., LTD. OUI:004061* ID_OUI_FROM_DATABASE=DATATECH ENTERPRISES CO., LTD. OUI:00408B* ID_OUI_FROM_DATABASE=RAYLAN CORPORATION OUI:004020* ID_OUI_FROM_DATABASE=CommScope Inc OUI:00406E* ID_OUI_FROM_DATABASE=COROLLARY, INC. OUI:004066* ID_OUI_FROM_DATABASE=Hitachi Metals, Ltd. OUI:004016* ID_OUI_FROM_DATABASE=ADC - Global Connectivity Solutions Division OUI:004086* ID_OUI_FROM_DATABASE=MICHELS & KLEBERHOFF COMPUTER OUI:0040DC* ID_OUI_FROM_DATABASE=TRITEC ELECTRONIC GMBH OUI:004074* ID_OUI_FROM_DATABASE=CABLE AND WIRELESS OUI:004084* ID_OUI_FROM_DATABASE=HONEYWELL ACS OUI:0040B8* ID_OUI_FROM_DATABASE=IDEA ASSOCIATES OUI:004058* ID_OUI_FROM_DATABASE=KRONOS, INC. OUI:0040A8* ID_OUI_FROM_DATABASE=IMF INTERNATIONAL LTD. OUI:0080BB* ID_OUI_FROM_DATABASE=HUGHES LAN SYSTEMS OUI:00C0A0* ID_OUI_FROM_DATABASE=ADVANCE MICRO RESEARCH, INC. OUI:00C0D7* ID_OUI_FROM_DATABASE=TAIWAN TRADING CENTER DBA OUI:00C037* ID_OUI_FROM_DATABASE=DYNATEM OUI:00C05F* ID_OUI_FROM_DATABASE=FINE-PAL COMPANY LIMITED OUI:0040CE* ID_OUI_FROM_DATABASE=NET-SOURCE, INC. OUI:004080* ID_OUI_FROM_DATABASE=ATHENIX CORPORATION OUI:0040BB* ID_OUI_FROM_DATABASE=GOLDSTAR CABLE CO., LTD. OUI:0040B1* ID_OUI_FROM_DATABASE=CODONICS INC. OUI:00402E* ID_OUI_FROM_DATABASE=PRECISION SOFTWARE, INC. OUI:00C0CE* ID_OUI_FROM_DATABASE=CEI SYSTEMS & ENGINEERING PTE OUI:00409B* ID_OUI_FROM_DATABASE=HAL COMPUTER SYSTEMS INC. OUI:004073* ID_OUI_FROM_DATABASE=BASS ASSOCIATES OUI:10005A* ID_OUI_FROM_DATABASE=IBM Corp OUI:004005* ID_OUI_FROM_DATABASE=ANI COMMUNICATIONS INC. OUI:004099* ID_OUI_FROM_DATABASE=NEWGEN SYSTEMS CORP. OUI:0040E1* ID_OUI_FROM_DATABASE=MARNER INTERNATIONAL, INC. OUI:0080DD* ID_OUI_FROM_DATABASE=GMX INC/GIMIX OUI:0080B7* ID_OUI_FROM_DATABASE=STELLAR COMPUTER OUI:008002* ID_OUI_FROM_DATABASE=SATELCOM (UK) LTD OUI:00805C* ID_OUI_FROM_DATABASE=AGILIS CORPORATION OUI:0080C7* ID_OUI_FROM_DATABASE=XIRCOM OUI:0080E7* ID_OUI_FROM_DATABASE=LYNWOOD SCIENTIFIC DEV. LTD. OUI:008070* ID_OUI_FROM_DATABASE=COMPUTADORAS MICRON OUI:00808F* ID_OUI_FROM_DATABASE=C. ITOH ELECTRONICS, INC. OUI:000091* ID_OUI_FROM_DATABASE=ANRITSU CORPORATION OUI:000094* ID_OUI_FROM_DATABASE=ASANTE TECHNOLOGIES OUI:000090* ID_OUI_FROM_DATABASE=MICROCOM OUI:000047* ID_OUI_FROM_DATABASE=NICOLET INSTRUMENTS CORP. OUI:0000FB* ID_OUI_FROM_DATABASE=RECHNER ZUR KOMMUNIKATION OUI:0000A3* ID_OUI_FROM_DATABASE=NETWORK APPLICATION TECHNOLOGY OUI:00008F* ID_OUI_FROM_DATABASE=Raytheon OUI:00007E* ID_OUI_FROM_DATABASE=CLUSTRIX CORPORATION OUI:00000A* ID_OUI_FROM_DATABASE=OMRON TATEISI ELECTRONICS CO. OUI:000063* ID_OUI_FROM_DATABASE=BARCO CONTROL ROOMS GMBH OUI:00004E* ID_OUI_FROM_DATABASE=AMPEX CORPORATION OUI:0000C2* ID_OUI_FROM_DATABASE=INFORMATION PRESENTATION TECH. OUI:000034* ID_OUI_FROM_DATABASE=NETWORK RESOURCES CORPORATION OUI:000049* ID_OUI_FROM_DATABASE=APRICOT COMPUTERS, LTD OUI:0000E2* ID_OUI_FROM_DATABASE=ACER TECHNOLOGIES CORP. OUI:000097* ID_OUI_FROM_DATABASE=EMC Corporation OUI:0000D4* ID_OUI_FROM_DATABASE=PURE DATA LTD. OUI:0000E1* ID_OUI_FROM_DATABASE=GRID SYSTEMS OUI:000031* ID_OUI_FROM_DATABASE=QPSX COMMUNICATIONS PTY LTD OUI:000044* ID_OUI_FROM_DATABASE=CASTELLE CORPORATION OUI:000027* ID_OUI_FROM_DATABASE=JAPAN RADIO COMPANY OUI:004049* ID_OUI_FROM_DATABASE=Roche Diagnostics International Ltd. OUI:004029* ID_OUI_FROM_DATABASE=Compex OUI:008038* ID_OUI_FROM_DATABASE=DATA RESEARCH & APPLICATIONS OUI:008090* ID_OUI_FROM_DATABASE=MICROTEK INTERNATIONAL, INC. OUI:0080C3* ID_OUI_FROM_DATABASE=BICC INFORMATION SYSTEMS & SVC OUI:00805A* ID_OUI_FROM_DATABASE=TULIP COMPUTERS INTERNAT'L B.V OUI:0080F0* ID_OUI_FROM_DATABASE=Panasonic Communications Co., Ltd. OUI:008043* ID_OUI_FROM_DATABASE=NETWORLD, INC. OUI:0080B0* ID_OUI_FROM_DATABASE=ADVANCED INFORMATION OUI:008066* ID_OUI_FROM_DATABASE=ARCOM CONTROL SYSTEMS, LTD. OUI:004051* ID_OUI_FROM_DATABASE=GRACILIS, INC. OUI:004064* ID_OUI_FROM_DATABASE=KLA INSTRUMENTS CORPORATION OUI:004028* ID_OUI_FROM_DATABASE=NETCOMM LIMITED OUI:004013* ID_OUI_FROM_DATABASE=NTT DATA COMM. SYSTEMS CORP. OUI:0040A0* ID_OUI_FROM_DATABASE=GOLDSTAR CO., LTD. OUI:0040B2* ID_OUI_FROM_DATABASE=SYSTEMFORSCHUNG OUI:004071* ID_OUI_FROM_DATABASE=ATM COMPUTER GMBH OUI:0080F7* ID_OUI_FROM_DATABASE=ZENITH ELECTRONICS OUI:0080BF* ID_OUI_FROM_DATABASE=TAKAOKA ELECTRIC MFG. CO. LTD. OUI:0080F6* ID_OUI_FROM_DATABASE=SYNERGY MICROSYSTEMS OUI:00001F* ID_OUI_FROM_DATABASE=Telco Systems, Inc. OUI:000058* ID_OUI_FROM_DATABASE=RACORE COMPUTER PRODUCTS INC. OUI:000050* ID_OUI_FROM_DATABASE=RADISYS CORPORATION OUI:008082* ID_OUI_FROM_DATABASE=PEP MODULAR COMPUTERS GMBH OUI:008096* ID_OUI_FROM_DATABASE=HUMAN DESIGNED SYSTEMS, INC. OUI:0080D5* ID_OUI_FROM_DATABASE=CADRE TECHNOLOGIES OUI:00803E* ID_OUI_FROM_DATABASE=SYNERNETICS OUI:00809A* ID_OUI_FROM_DATABASE=NOVUS NETWORKS LTD OUI:0080B3* ID_OUI_FROM_DATABASE=AVAL DATA CORPORATION OUI:0080A3* ID_OUI_FROM_DATABASE=Lantronix OUI:00803C* ID_OUI_FROM_DATABASE=TVS ELECTRONICS LTD OUI:008061* ID_OUI_FROM_DATABASE=LITTON SYSTEMS, INC. OUI:0080AD* ID_OUI_FROM_DATABASE=CNET TECHNOLOGY, INC. OUI:008081* ID_OUI_FROM_DATABASE=KENDALL SQUARE RESEARCH CORP. OUI:008019* ID_OUI_FROM_DATABASE=DAYNA COMMUNICATIONS, INC. OUI:00808B* ID_OUI_FROM_DATABASE=DACOLL LIMITED OUI:008097* ID_OUI_FROM_DATABASE=CENTRALP AUTOMATISMES OUI:0080FC* ID_OUI_FROM_DATABASE=AVATAR CORPORATION OUI:008076* ID_OUI_FROM_DATABASE=MCNC OUI:008080* ID_OUI_FROM_DATABASE=DATAMEDIA CORPORATION OUI:0000E6* ID_OUI_FROM_DATABASE=APTOR PRODUITS DE COMM INDUST OUI:000084* ID_OUI_FROM_DATABASE=SUPERNET OUI:0000FF* ID_OUI_FROM_DATABASE=CAMTEC ELECTRONICS LTD. OUI:00007B* ID_OUI_FROM_DATABASE=RESEARCH MACHINES OUI:000056* ID_OUI_FROM_DATABASE=DR. B. STRUCK OUI:0000BB* ID_OUI_FROM_DATABASE=TRI-DATA OUI:080025* ID_OUI_FROM_DATABASE=CONTROL DATA OUI:080020* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:027001* ID_OUI_FROM_DATABASE=RACAL-DATACOM OUI:080006* ID_OUI_FROM_DATABASE=SIEMENS AG OUI:08007E* ID_OUI_FROM_DATABASE=AMALGAMATED WIRELESS(AUS) LTD OUI:080075* ID_OUI_FROM_DATABASE=DANSK DATA ELECTRONIK OUI:080073* ID_OUI_FROM_DATABASE=TECMAR INC. OUI:080069* ID_OUI_FROM_DATABASE=SILICON GRAPHICS INC. OUI:080061* ID_OUI_FROM_DATABASE=JAROGATE LTD. OUI:08005D* ID_OUI_FROM_DATABASE=GOULD INC. OUI:080051* ID_OUI_FROM_DATABASE=EXPERDATA OUI:08004E* ID_OUI_FROM_DATABASE=3COM EUROPE LTD. OUI:08004A* ID_OUI_FROM_DATABASE=BANYAN SYSTEMS INC. OUI:08004C* ID_OUI_FROM_DATABASE=HYDRA COMPUTER SYSTEMS INC. OUI:080043* ID_OUI_FROM_DATABASE=PIXEL COMPUTER INC. OUI:08003A* ID_OUI_FROM_DATABASE=ORCATECH INC. OUI:080035* ID_OUI_FROM_DATABASE=MICROFIVE CORPORATION OUI:080036* ID_OUI_FROM_DATABASE=INTERGRAPH CORPORATION OUI:08002D* ID_OUI_FROM_DATABASE=LAN-TEC INC. OUI:000025* ID_OUI_FROM_DATABASE=RAMTEK CORP. OUI:00003A* ID_OUI_FROM_DATABASE=CHYRON CORPORATION OUI:000077* ID_OUI_FROM_DATABASE=INTERPHASE CORPORATION OUI:000096* ID_OUI_FROM_DATABASE=MARCONI ELECTRONICS LTD. OUI:000076* ID_OUI_FROM_DATABASE=ABEKAS VIDEO SYSTEM OUI:0000EA* ID_OUI_FROM_DATABASE=UPNOD AB OUI:000074* ID_OUI_FROM_DATABASE=RICOH COMPANY LTD. OUI:00006A* ID_OUI_FROM_DATABASE=COMPUTER CONSOLES INC. OUI:0000C4* ID_OUI_FROM_DATABASE=WATERS DIV. OF MILLIPORE OUI:000006* ID_OUI_FROM_DATABASE=XEROX CORPORATION OUI:0001C8* ID_OUI_FROM_DATABASE=THOMAS CONRAD CORP. OUI:02E6D3* ID_OUI_FROM_DATABASE=NIXDORF COMPUTER CORPORATION OUI:00DD0E* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:08008D* ID_OUI_FROM_DATABASE=XYVISION INC. OUI:080059* ID_OUI_FROM_DATABASE=A/S MYCRON OUI:021C7C* ID_OUI_FROM_DATABASE=PERQ SYSTEMS CORPORATION OUI:100000* ID_OUI_FROM_DATABASE=Private OUI:080004* ID_OUI_FROM_DATABASE=CROMEMCO INCORPORATED OUI:00DD07* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:00003E* ID_OUI_FROM_DATABASE=SIMPACT OUI:04E0C4* ID_OUI_FROM_DATABASE=TRIUMPH-ADLER AG OUI:040AE0* ID_OUI_FROM_DATABASE=XMIT AG COMPUTER NETWORKS OUI:080016* ID_OUI_FROM_DATABASE=BARRISTER INFO SYS CORP OUI:080012* ID_OUI_FROM_DATABASE=BELL ATLANTIC INTEGRATED SYST. OUI:0001C8* ID_OUI_FROM_DATABASE=CONRAD CORP. OUI:0000F9* ID_OUI_FROM_DATABASE=QUOTRON SYSTEMS INC. OUI:0000BF* ID_OUI_FROM_DATABASE=SYMMETRIC COMPUTER SYSTEMS OUI:000085* ID_OUI_FROM_DATABASE=CANON INC. OUI:000028* ID_OUI_FROM_DATABASE=PRODIGY SYSTEMS CORPORATION OUI:000012* ID_OUI_FROM_DATABASE=INFORMATION TECHNOLOGY LIMITED OUI:080085* ID_OUI_FROM_DATABASE=ELXSI OUI:00005B* ID_OUI_FROM_DATABASE=ELTEC ELEKTRONIK AG OUI:000054* ID_OUI_FROM_DATABASE=Schneider Electric OUI:0000A9* ID_OUI_FROM_DATABASE=NETWORK SYSTEMS CORP. OUI:000059* ID_OUI_FROM_DATABASE=Hellige GMBH OUI:000099* ID_OUI_FROM_DATABASE=MTX, INC. OUI:0000E9* ID_OUI_FROM_DATABASE=ISICAD, INC. OUI:08003F* ID_OUI_FROM_DATABASE=FRED KOSCHARA ENTERPRISES OUI:080002* ID_OUI_FROM_DATABASE=BRIDGE COMMUNICATIONS INC. OUI:08008B* ID_OUI_FROM_DATABASE=PYRAMID TECHNOLOGY CORP. OUI:000002* ID_OUI_FROM_DATABASE=XEROX CORPORATION OUI:84F6FA* ID_OUI_FROM_DATABASE=Miovision Technologies Incorporated OUI:CC3B3E* ID_OUI_FROM_DATABASE=Lester Electrical OUI:C05627* ID_OUI_FROM_DATABASE=Belkin International Inc. OUI:88074B* ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) OUI:4065A3* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:00789E* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:44E9DD* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:10F681* ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. OUI:B888E3* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:002622* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:001EEC* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:DC0EA1* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:FC4596* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:208984* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:247C4C* ID_OUI_FROM_DATABASE=Herman Miller OUI:ACDE48* ID_OUI_FROM_DATABASE=Private OUI:00A085* ID_OUI_FROM_DATABASE=Private OUI:180373* ID_OUI_FROM_DATABASE=Dell Inc. OUI:F8B156* ID_OUI_FROM_DATABASE=Dell Inc. OUI:1C4024* ID_OUI_FROM_DATABASE=Dell Inc. OUI:F8BC12* ID_OUI_FROM_DATABASE=Dell Inc. OUI:001B5B* ID_OUI_FROM_DATABASE=2Wire Inc OUI:002456* ID_OUI_FROM_DATABASE=2Wire Inc OUI:002351* ID_OUI_FROM_DATABASE=2Wire Inc OUI:00253C* ID_OUI_FROM_DATABASE=2Wire Inc OUI:0022A4* ID_OUI_FROM_DATABASE=2Wire Inc OUI:C0830A* ID_OUI_FROM_DATABASE=2Wire Inc OUI:D0431E* ID_OUI_FROM_DATABASE=Dell Inc. OUI:246E96* ID_OUI_FROM_DATABASE=Dell Inc. OUI:204747* ID_OUI_FROM_DATABASE=Dell Inc. OUI:4C7625* ID_OUI_FROM_DATABASE=Dell Inc. OUI:B8AC6F* ID_OUI_FROM_DATABASE=Dell Inc. OUI:001EC9* ID_OUI_FROM_DATABASE=Dell Inc. OUI:E09861* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:F4F1E1* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:74C99A* ID_OUI_FROM_DATABASE=Ericsson AB OUI:3C197D* ID_OUI_FROM_DATABASE=Ericsson AB OUI:60BEB5* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:7845C4* ID_OUI_FROM_DATABASE=Dell Inc. OUI:B4E1C4* ID_OUI_FROM_DATABASE=Microsoft Mobile Oy OUI:D86C02* ID_OUI_FROM_DATABASE=Huaqin Telecom Technology Co.,Ltd OUI:0019D2* ID_OUI_FROM_DATABASE=Intel Corporate OUI:7C5CF8* ID_OUI_FROM_DATABASE=Intel Corporate OUI:001E67* ID_OUI_FROM_DATABASE=Intel Corporate OUI:001F3C* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0022FA* ID_OUI_FROM_DATABASE=Intel Corporate OUI:001517* ID_OUI_FROM_DATABASE=Intel Corporate OUI:00166F* ID_OUI_FROM_DATABASE=Intel Corporate OUI:A44E31* ID_OUI_FROM_DATABASE=Intel Corporate OUI:6C8814* ID_OUI_FROM_DATABASE=Intel Corporate OUI:F81654* ID_OUI_FROM_DATABASE=Intel Corporate OUI:3413E8* ID_OUI_FROM_DATABASE=Intel Corporate OUI:34E6AD* ID_OUI_FROM_DATABASE=Intel Corporate OUI:FCF8AE* ID_OUI_FROM_DATABASE=Intel Corporate OUI:648099* ID_OUI_FROM_DATABASE=Intel Corporate OUI:002314* ID_OUI_FROM_DATABASE=Intel Corporate OUI:4025C2* ID_OUI_FROM_DATABASE=Intel Corporate OUI:8CA982* ID_OUI_FROM_DATABASE=Intel Corporate OUI:D07E35* ID_OUI_FROM_DATABASE=Intel Corporate OUI:685D43* ID_OUI_FROM_DATABASE=Intel Corporate OUI:90E2BA* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0026C7* ID_OUI_FROM_DATABASE=Intel Corporate OUI:8086F2* ID_OUI_FROM_DATABASE=Intel Corporate OUI:78FF57* ID_OUI_FROM_DATABASE=Intel Corporate OUI:20934D* ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD OUI:00AA00* ID_OUI_FROM_DATABASE=Intel Corporation OUI:6CF37F* ID_OUI_FROM_DATABASE=Aruba Networks OUI:605BB4* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:9C0E4A* ID_OUI_FROM_DATABASE=Shenzhen Vastking Electronic Co.,Ltd. OUI:ACE5F0* ID_OUI_FROM_DATABASE=Doppler Labs OUI:00F28B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:5414FD* ID_OUI_FROM_DATABASE=Orbbec 3D Technology International OUI:1C4BD6* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:94DBC9* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:40E230* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:00006E* ID_OUI_FROM_DATABASE=Artisoft Inc. OUI:A0F459* ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED OUI:0C6AE6* ID_OUI_FROM_DATABASE=Stanley Security Solutions OUI:E874E6* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:00247B* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:689C5E* ID_OUI_FROM_DATABASE=AcSiP Technology Corp. OUI:0012CF* ID_OUI_FROM_DATABASE=Accton Technology Corp OUI:0030D3* ID_OUI_FROM_DATABASE=Agilent Technologies, Inc. OUI:38229D* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:002233* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:D4D184* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:34C3D2* ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED OUI:38E3C5* ID_OUI_FROM_DATABASE=Taicang T&W Electronics OUI:D0E44A* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:9433DD* ID_OUI_FROM_DATABASE=Taco Inc OUI:948815* ID_OUI_FROM_DATABASE=Infinique Worldwide Inc OUI:3010B3* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:001802* ID_OUI_FROM_DATABASE=Alpha Networks Inc. OUI:ECCD6D* ID_OUI_FROM_DATABASE=Allied Telesis, Inc. OUI:74C246* ID_OUI_FROM_DATABASE=Amazon Technologies Inc. OUI:F0272D* ID_OUI_FROM_DATABASE=Amazon Technologies Inc. OUI:00225F* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:0018A4* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001311* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0015A2* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001596* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0000CA* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:983B16* ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. OUI:402BA1* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:0025E7* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:D05162* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:94CE2C* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:001A80* ID_OUI_FROM_DATABASE=Sony Corporation OUI:0024BE* ID_OUI_FROM_DATABASE=Sony Corporation OUI:001620* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:0012EE* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:20689D* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:446D57* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:000F9F* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0011AE* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:002040* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0015CE* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001626* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:00111A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:00152F* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:000B06* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:44EE02* ID_OUI_FROM_DATABASE=MTI Ltd. OUI:001C11* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001CC1* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001D6B* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001E5A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001DBE* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001371* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:C8AA21* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:2C9E5F* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:002495* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:002642* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:A4ED4E* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0024A1* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:002375* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001ADB* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:00149A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001A1B* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001F7E* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0026B6* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:B4EEB4* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:FCB4E6* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:F05C19* ID_OUI_FROM_DATABASE=Aruba Networks OUI:C43DC7* ID_OUI_FROM_DATABASE=NETGEAR OUI:000FB5* ID_OUI_FROM_DATABASE=NETGEAR OUI:00095B* ID_OUI_FROM_DATABASE=NETGEAR OUI:F87394* ID_OUI_FROM_DATABASE=NETGEAR OUI:70AAB2* ID_OUI_FROM_DATABASE=BlackBerry RTS OUI:0026FF* ID_OUI_FROM_DATABASE=BlackBerry RTS OUI:406F2A* ID_OUI_FROM_DATABASE=BlackBerry RTS OUI:002557* ID_OUI_FROM_DATABASE=BlackBerry RTS OUI:0024FE* ID_OUI_FROM_DATABASE=AVM GmbH OUI:745AAA* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:7C1CF1* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:C0FFD4* ID_OUI_FROM_DATABASE=NETGEAR OUI:405D82* ID_OUI_FROM_DATABASE=NETGEAR OUI:803773* ID_OUI_FROM_DATABASE=NETGEAR OUI:00264D* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:74A528* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:30A220* ID_OUI_FROM_DATABASE=ARG Telecom OUI:783E53* ID_OUI_FROM_DATABASE=BSkyB Ltd OUI:4CF2BF* ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. OUI:70D931* ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. OUI:00E063* ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. OUI:E01D3B* ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. OUI:D476EA* ID_OUI_FROM_DATABASE=zte corporation OUI:0040FB* ID_OUI_FROM_DATABASE=CASCADE COMMUNICATIONS OUI:F05A09* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:503275* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:28CC01* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B46293* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:04FE31* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:845181* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:D831CF* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:F8D0BD* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:FCC734* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E4B021* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B0EC71* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:3CBBFD* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:24F5AA* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:2CAE2B* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:C488E5* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:7C9122* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E8B4C8* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:18895B* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E0DB10* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E09971* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:6077E2* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:680571* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:6C2F2C* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:5056BF* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:000136* ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. OUI:F88E85* ID_OUI_FROM_DATABASE=Comtrend Corporation OUI:300D43* ID_OUI_FROM_DATABASE=Microsoft Mobile Oy OUI:6C2779* ID_OUI_FROM_DATABASE=Microsoft Mobile Oy OUI:607EDD* ID_OUI_FROM_DATABASE=Microsoft Mobile Oy OUI:F88096* ID_OUI_FROM_DATABASE=Elsys Equipamentos Eletrônicos Ltda OUI:E0B9E5* ID_OUI_FROM_DATABASE=Technicolor OUI:0CBF15* ID_OUI_FROM_DATABASE=Genetec Inc. OUI:000B5D* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:F4CAE5* ID_OUI_FROM_DATABASE=FREEBOX SAS OUI:002100* ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. OUI:002147* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:0022AA* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:0022D7* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:002331* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:00241E* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:78A2A0* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:001B7A* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:40F407* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:B8AE6E* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:60A8FE* ID_OUI_FROM_DATABASE=Nokia OUI:546751* ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc. OUI:84BA3B* ID_OUI_FROM_DATABASE=CANON INC. OUI:0018C5* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:80501B* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:347E39* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:A87E33* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:00247D* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001BAF* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001C35* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001CD4* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001979* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:9C1874* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0021FC* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001F5D* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0025CF* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0025D0* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001FDE* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:907282* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:006CFD* ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. OUI:1C234F* ID_OUI_FROM_DATABASE=EDMI Europe Ltd OUI:A444D1* ID_OUI_FROM_DATABASE=Wingtech Group (HongKong)Limited OUI:1C9E46* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:005058* ID_OUI_FROM_DATABASE=Sangoma Technologies OUI:3482DE* ID_OUI_FROM_DATABASE=Kiio Inc OUI:0008F6* ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd OUI:00005F* ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd OUI:A0C589* ID_OUI_FROM_DATABASE=Intel Corporate OUI:74BFB7* ID_OUI_FROM_DATABASE=Nusoft Corporation OUI:50DA00* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:9C2A83* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E45D75* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:3CBEE1* ID_OUI_FROM_DATABASE=NIKON CORPORATION OUI:047E4A* ID_OUI_FROM_DATABASE=moobox CO., Ltd. OUI:104FA8* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:F01B6C* ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. OUI:E0C767* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:2C09CB* ID_OUI_FROM_DATABASE=COBS AB OUI:60ACC8* ID_OUI_FROM_DATABASE=KunTeng Inc. OUI:0404EA* ID_OUI_FROM_DATABASE=Valens Semiconductor Ltd. OUI:800DD7* ID_OUI_FROM_DATABASE=Latticework, Inc OUI:402E28* ID_OUI_FROM_DATABASE=MiXTelematics OUI:18C501* ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT OUI:546D52* ID_OUI_FROM_DATABASE=TOPVIEW OPTRONICS CORP. OUI:CCB3AB* ID_OUI_FROM_DATABASE=shenzhen Biocare Bio-Medical Equipment Co.,Ltd. OUI:4CC94F* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:48F7F1* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:E4B318* ID_OUI_FROM_DATABASE=Intel Corporate OUI:00C88B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:A85EE4* ID_OUI_FROM_DATABASE=12Sided Technology, LLC OUI:000CC1* ID_OUI_FROM_DATABASE=Eaton Corporation OUI:0090F9* ID_OUI_FROM_DATABASE=Imagine Communications OUI:04C103* ID_OUI_FROM_DATABASE=Clover Network, Inc. OUI:F877B8* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:1C553A* ID_OUI_FROM_DATABASE=QianGua Corp. OUI:E4A7A0* ID_OUI_FROM_DATABASE=Intel Corporate OUI:E4FAED* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:789682* ID_OUI_FROM_DATABASE=zte corporation OUI:F02745* ID_OUI_FROM_DATABASE=F-Secure Corporation OUI:54D0B4* ID_OUI_FROM_DATABASE=Xiamen Four-Faith Communication Technology Co.,Ltd OUI:D017C2* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:10DA43* ID_OUI_FROM_DATABASE=NETGEAR OUI:001625* ID_OUI_FROM_DATABASE=Impinj, Inc. OUI:1CEA1B* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:DC1AC5* ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. OUI:60EE5C* ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD OUI:BC60A7* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:58D67A* ID_OUI_FROM_DATABASE=TCPlink OUI:00A0DE* ID_OUI_FROM_DATABASE=YAMAHA CORPORATION OUI:081F71* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:2C2D48* ID_OUI_FROM_DATABASE=bct electronic GesmbH OUI:E4A471* ID_OUI_FROM_DATABASE=Intel Corporate OUI:60B617* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:18A3E8* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:741E93* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:F0C77F* ID_OUI_FROM_DATABASE=Texas Instruments OUI:00A0F4* ID_OUI_FROM_DATABASE=GE OUI:00CAE5* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:4883C7* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:7050AF* ID_OUI_FROM_DATABASE=BSkyB Ltd OUI:F4EF9E* ID_OUI_FROM_DATABASE=SGSG SCIENCE & TECHNOLOGY CO. LTD OUI:DC9C9F* ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd OUI:0CBF3F* ID_OUI_FROM_DATABASE=Shenzhen Lencotion Technology Co.,Ltd OUI:84FEDC* ID_OUI_FROM_DATABASE=Borqs Beijing Ltd. OUI:F03E90* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:D8D723* ID_OUI_FROM_DATABASE=IDS, Inc OUI:703A0E* ID_OUI_FROM_DATABASE=Aruba Networks OUI:7054D2* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:7C0507* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:C07CD1* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:94DBDA* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:384C4F* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:E4A8B6* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:244C07* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:E840F2* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:F0D1B8* ID_OUI_FROM_DATABASE=LEDVANCE OUI:60B387* ID_OUI_FROM_DATABASE=Synergics Technologies GmbH OUI:7085C2* ID_OUI_FROM_DATABASE=ASRock Incorporation OUI:C825E1* ID_OUI_FROM_DATABASE=Lemobile Information Technology (Beijing) Co., Ltd OUI:0022B1* ID_OUI_FROM_DATABASE=Elbit Systems Ltd. OUI:0000B4* ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. OUI:00065F* ID_OUI_FROM_DATABASE=ECI Telecom Ltd. OUI:001F45* ID_OUI_FROM_DATABASE=Enterasys OUI:0090FA* ID_OUI_FROM_DATABASE=Emulex Corporation OUI:50C971* ID_OUI_FROM_DATABASE=GN Netcom A/S OUI:001D82* ID_OUI_FROM_DATABASE=GN Netcom A/S OUI:001317* ID_OUI_FROM_DATABASE=GN Netcom A/S OUI:749781* ID_OUI_FROM_DATABASE=zte corporation OUI:B4B15A* ID_OUI_FROM_DATABASE=Siemens AG Energy Management Division OUI:A86BAD* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:D80F99* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:A8D828* ID_OUI_FROM_DATABASE=Ascensia Diabetes Care OUI:FCBC9C* ID_OUI_FROM_DATABASE=Vimar Spa OUI:149ECF* ID_OUI_FROM_DATABASE=Dell Inc. OUI:AC620D* ID_OUI_FROM_DATABASE=Jabil Circuit(Wuxi) Co.,Ltd OUI:008CFA* ID_OUI_FROM_DATABASE=INVENTEC Corporation OUI:0008B9* ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD. OUI:C83F26* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:00E0E6* ID_OUI_FROM_DATABASE=INCAA Computers OUI:5C5EAB* ID_OUI_FROM_DATABASE=Juniper Networks OUI:7819F7* ID_OUI_FROM_DATABASE=Juniper Networks OUI:2C2172* ID_OUI_FROM_DATABASE=Juniper Networks OUI:88E0F3* ID_OUI_FROM_DATABASE=Juniper Networks OUI:4C9614* ID_OUI_FROM_DATABASE=Juniper Networks OUI:3C8AB0* ID_OUI_FROM_DATABASE=Juniper Networks OUI:B0C69A* ID_OUI_FROM_DATABASE=Juniper Networks OUI:009069* ID_OUI_FROM_DATABASE=Juniper Networks OUI:204E71* ID_OUI_FROM_DATABASE=Juniper Networks OUI:F4B52F* ID_OUI_FROM_DATABASE=Juniper Networks OUI:88A25E* ID_OUI_FROM_DATABASE=Juniper Networks OUI:001BC0* ID_OUI_FROM_DATABASE=Juniper Networks OUI:F49EEF* ID_OUI_FROM_DATABASE=Taicang T&W Electronics OUI:F4911E* ID_OUI_FROM_DATABASE=ZHUHAI EWPE INFORMATION TECHNOLOGY INC OUI:94FE22* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:F823B2* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:DCD916* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:002552* ID_OUI_FROM_DATABASE=VXi Corporation OUI:341FE4* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:006CBC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:DC3752* ID_OUI_FROM_DATABASE=GE OUI:F08261* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:D084B0* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:5846E1* ID_OUI_FROM_DATABASE=Baxter International Inc OUI:00D0BD* ID_OUI_FROM_DATABASE=Lattice Semiconductor Corp. (LPA) OUI:001F3A* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:647BD4* ID_OUI_FROM_DATABASE=Texas Instruments OUI:102EAF* ID_OUI_FROM_DATABASE=Texas Instruments OUI:CC8CE3* ID_OUI_FROM_DATABASE=Texas Instruments OUI:B4EED4* ID_OUI_FROM_DATABASE=Texas Instruments OUI:D08CB5* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0030C5* ID_OUI_FROM_DATABASE=CADENCE DESIGN SYSTEMS, INC. OUI:00FEC8* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:BC5436* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0CC731* ID_OUI_FROM_DATABASE=Currant, Inc. OUI:00142F* ID_OUI_FROM_DATABASE=Savvius OUI:70CA4D* ID_OUI_FROM_DATABASE=Shenzhen lnovance Technology Co.,Ltd. OUI:DCC0EB* ID_OUI_FROM_DATABASE=ASSA ABLOY CÔTE PICARDE OUI:047863* ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd. OUI:24BA13* ID_OUI_FROM_DATABASE=RISO KAGAKU CORPORATION OUI:24DA11* ID_OUI_FROM_DATABASE=NO NDA Inc OUI:BCD1D3* ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. OUI:BC4434* ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. OUI:0041D2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:4CFB45* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:A4BA76* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:3871DE* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:2CDDA3* ID_OUI_FROM_DATABASE=Point Grey Research Inc. OUI:24FD5B* ID_OUI_FROM_DATABASE=SmartThings, Inc. OUI:2876CD* ID_OUI_FROM_DATABASE=Funshion Online Technologies Co.,Ltd OUI:F4F5D8* ID_OUI_FROM_DATABASE=Google, Inc. OUI:F4F5E8* ID_OUI_FROM_DATABASE=Google, Inc. OUI:F88FCA* ID_OUI_FROM_DATABASE=Google, Inc. OUI:14D64D* ID_OUI_FROM_DATABASE=D-Link International OUI:C8BE19* ID_OUI_FROM_DATABASE=D-Link International OUI:BCF685* ID_OUI_FROM_DATABASE=D-Link International OUI:CCB255* ID_OUI_FROM_DATABASE=D-Link International OUI:84C9B2* ID_OUI_FROM_DATABASE=D-Link International OUI:EC2280* ID_OUI_FROM_DATABASE=D-Link International OUI:78E3B5* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:984BE1* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:68B599* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0C47C9* ID_OUI_FROM_DATABASE=Amazon Technologies Inc. OUI:001831* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0023D4* ID_OUI_FROM_DATABASE=Texas Instruments OUI:3C2DB7* ID_OUI_FROM_DATABASE=Texas Instruments OUI:40984E* ID_OUI_FROM_DATABASE=Texas Instruments OUI:3C7DB1* ID_OUI_FROM_DATABASE=Texas Instruments OUI:505663* ID_OUI_FROM_DATABASE=Texas Instruments OUI:B0B448* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0017E6* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0017E8* ID_OUI_FROM_DATABASE=Texas Instruments OUI:9059AF* ID_OUI_FROM_DATABASE=Texas Instruments OUI:E0C79D* ID_OUI_FROM_DATABASE=Texas Instruments OUI:003676* ID_OUI_FROM_DATABASE=Pace plc OUI:58DC6D* ID_OUI_FROM_DATABASE=Exceptional Innovation, Inc. OUI:00092D* ID_OUI_FROM_DATABASE=HTC Corporation OUI:F8DB7F* ID_OUI_FROM_DATABASE=HTC Corporation OUI:E899C4* ID_OUI_FROM_DATABASE=HTC Corporation OUI:28565A* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:40490F* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:7CB15D* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:002269* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:18686A* ID_OUI_FROM_DATABASE=zte corporation OUI:0C0535* ID_OUI_FROM_DATABASE=Juniper Systems OUI:E0885D* ID_OUI_FROM_DATABASE=Technicolor CH USA OUI:8CF228* ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. OUI:08EA44* ID_OUI_FROM_DATABASE=Aerohive Networks Inc. OUI:78F882* ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) OUI:C8CBB8* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:9457A5* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0001E7* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:080009* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0080A0* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:D48564* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:3C4A92* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0080E1* ID_OUI_FROM_DATABASE=STMicroelectronics SRL OUI:2C6E85* ID_OUI_FROM_DATABASE=Intel Corporate OUI:00D0B7* ID_OUI_FROM_DATABASE=Intel Corporation OUI:0015D1* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001DD3* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001735* ID_OUI_FROM_DATABASE=Intel Wireless Network Group OUI:9CDFB1* ID_OUI_FROM_DATABASE=Shenzhen Crave Communication Co., LTD OUI:5CF938* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:001D73* ID_OUI_FROM_DATABASE=BUFFALO.INC OUI:001601* ID_OUI_FROM_DATABASE=BUFFALO.INC OUI:106F3F* ID_OUI_FROM_DATABASE=BUFFALO.INC OUI:8857EE* ID_OUI_FROM_DATABASE=BUFFALO.INC OUI:009C02* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:78E7D1* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001B78* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001E0B* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0002B3* ID_OUI_FROM_DATABASE=Intel Corporation OUI:001111* ID_OUI_FROM_DATABASE=Intel Corporation OUI:001320* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0012F0* ID_OUI_FROM_DATABASE=Intel Corporate OUI:9049FA* ID_OUI_FROM_DATABASE=Intel Corporate OUI:C8348E* ID_OUI_FROM_DATABASE=Intel Corporate OUI:780AC7* ID_OUI_FROM_DATABASE=Baofeng TV Co., Ltd. OUI:00508B* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:784859* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:1458D0* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:5065F3* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:A0481C* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:A01D48* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:8851FB* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:AC162D* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:A0B3CC* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:E4115B* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:E8892C* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:E83EFC* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:083E0C* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:8C09F4* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:3CDFA9* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:C005C2* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:6455B1* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:DCD321* ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. OUI:CC4EEC* ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. OUI:88C255* ID_OUI_FROM_DATABASE=Texas Instruments OUI:DC330D* ID_OUI_FROM_DATABASE=Qingdao Haier Telecom Co.,Ltd OUI:94B2CC* ID_OUI_FROM_DATABASE=PIONEER CORPORATION OUI:887F03* ID_OUI_FROM_DATABASE=Comper Technology Investment Limited OUI:50FA84* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:F483CD* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:882593* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:808917* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:5C899A* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:A81B5A* ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD OUI:E422A5* ID_OUI_FROM_DATABASE=PLANTRONICS, INC. OUI:1C994C* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:F02765* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:88308A* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:44A7CF* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:44322A* ID_OUI_FROM_DATABASE=Avaya Inc OUI:FC8399* ID_OUI_FROM_DATABASE=Avaya Inc OUI:00040D* ID_OUI_FROM_DATABASE=Avaya Inc OUI:D842AC* ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd. OUI:34CDBE* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:D46AA8* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:5439DF* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:4846FB* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:200BC7* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:104780* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:30D17E* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:9C28EF* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:E06066* ID_OUI_FROM_DATABASE=Sercomm Corporation OUI:0019E0* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:0023CD* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:002719* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:40169F* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:940C6D* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:74EA3A* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:90F652* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:10FEED* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:C46E1F* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:68A0F6* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:5CF96A* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:B43052* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:88CEFA* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:582AF7* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:F48E92* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:40CBA8* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:087A4C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:D46E5C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:2469A5* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:C8D15E* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:F83DFF* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:0013E0* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:748EF8* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:00E052* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:000480* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:000088* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:344B50* ID_OUI_FROM_DATABASE=zte corporation OUI:FCC897* ID_OUI_FROM_DATABASE=zte corporation OUI:9CD24B* ID_OUI_FROM_DATABASE=zte corporation OUI:C864C7* ID_OUI_FROM_DATABASE=zte corporation OUI:D0154A* ID_OUI_FROM_DATABASE=zte corporation OUI:001FE2* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:001DD9* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:0016CE* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:0014A4* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:D02788* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:300ED5* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:543530* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:90489A* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:88E3AB* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:00664B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:7C6097* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:60DE44* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:3400A3* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:643E8C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:0012D1* ID_OUI_FROM_DATABASE=Texas Instruments OUI:70FF76* ID_OUI_FROM_DATABASE=Texas Instruments OUI:B4994C* ID_OUI_FROM_DATABASE=Texas Instruments OUI:507224* ID_OUI_FROM_DATABASE=Texas Instruments OUI:308730* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:002568* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:D47856* ID_OUI_FROM_DATABASE=Avaya Inc OUI:C057BC* ID_OUI_FROM_DATABASE=Avaya Inc OUI:38BB3C* ID_OUI_FROM_DATABASE=Avaya Inc OUI:E45D52* ID_OUI_FROM_DATABASE=Avaya Inc OUI:A4251B* ID_OUI_FROM_DATABASE=Avaya Inc OUI:6CA849* ID_OUI_FROM_DATABASE=Avaya Inc OUI:048A15* ID_OUI_FROM_DATABASE=Avaya Inc OUI:D4970B* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:F48B32* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:20A783* ID_OUI_FROM_DATABASE=miControl GmbH OUI:005053* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00500F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0050A2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0498F3* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:38C096* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:E0750A* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:B05947* ID_OUI_FROM_DATABASE=Shenzhen Qihu Intelligent Technology Company Limited OUI:00E04F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001011* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0010F6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:80E01D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:80E86F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E4AA5D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:203A07* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:34A84E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E4D3F1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:1CE6C7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E02F6D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:8478AC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:4403A7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:6886A7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B4E9B0* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000832* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B0FAEB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:500604* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:70105C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:C067AF* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:64E950* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B0AA77* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:78BAF9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0016B6* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:0018F8* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:00252E* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:A4A24A* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:602AD0* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:001BFB* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:0016FE* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:3C08F6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:D072DC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:28C7CE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:6CFA89* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:58F39C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:346288* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:881DFC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000389* ID_OUI_FROM_DATABASE=PLANTRONICS, INC. OUI:0CE0E4* ID_OUI_FROM_DATABASE=PLANTRONICS, INC. OUI:7CFADF* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:101C0C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:001124* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:001D4F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:001E52* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:001F5B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:001FF3* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0021E9* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:00236C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:002500* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:60FB42* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F81EDF* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:90840D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D8A25E* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C8BCC8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:28E7CF* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D89E3F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:040CCE* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A4D1D2* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:406C8F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:00C610* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:70DEE2* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0050F0* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00905F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00902B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00100B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00100D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001014* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00E08F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:189C5D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000EA6* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:0013D4* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:002618* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:00248C* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:14DAE9* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:182032* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:6CC26B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:1040F3* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:FC253F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:183451* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C0847A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:64200C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:74E1B6* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0C771A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:00F4B9* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C8334B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:B8F6B1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C09F42* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:189EFC* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:6C3E6D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:8C2DAA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:444C0C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:84FCFE* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E48B7F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:94E96A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:AC293A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:10417F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:7014A6* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A8667F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D02598* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:CC29F5* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:802994* ID_OUI_FROM_DATABASE=Technicolor CH USA OUI:D4B8FF* ID_OUI_FROM_DATABASE=Home Control Singapore Pte Ltd OUI:C8E0EB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A88808* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:907240* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0C4DE9* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D89695* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0C3021* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F0F61C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:B03495* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:848E0C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:6C709F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0C3E9F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:34E2FD* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:609217* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:8863DF* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:80E650* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:006171* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:90FD61* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:5C97F3* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:6C4008* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:24A074* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F02475* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:20A2E4* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:5CF5DA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:649ABE* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:5C969D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A8FAD8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:949426* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E0F5C6* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:28E14C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:54E43A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:90DFFB* ID_OUI_FROM_DATABASE=HOMERIDER SYSTEMS OUI:3C831E* ID_OUI_FROM_DATABASE=CKD Corporation OUI:381C23* ID_OUI_FROM_DATABASE=Hilan Technology CO.,LTD OUI:AC6462* ID_OUI_FROM_DATABASE=zte corporation OUI:C08488* ID_OUI_FROM_DATABASE=Finis Inc OUI:8C99E6* ID_OUI_FROM_DATABASE=TCT Mobile Limited OUI:3CB72B* ID_OUI_FROM_DATABASE=PLUMgrid Inc OUI:243184* ID_OUI_FROM_DATABASE=SHARP Corporation OUI:24DA9B* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:7467F7* ID_OUI_FROM_DATABASE=Zebra Technologoes OUI:3891D5* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:68E8EB* ID_OUI_FROM_DATABASE=Linktel Technologies Co.,Ltd OUI:20C3A4* ID_OUI_FROM_DATABASE=RetailNext OUI:B844D9* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:DC2B2A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:8C10D4* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:B8B2EB* ID_OUI_FROM_DATABASE=Googol Technology (HK) Limited OUI:C40049* ID_OUI_FROM_DATABASE=Kamama OUI:50A9DE* ID_OUI_FROM_DATABASE=Smartcom - Bulgaria AD OUI:C02DEE* ID_OUI_FROM_DATABASE=Cuff OUI:54A3FA* ID_OUI_FROM_DATABASE=BQT Solutions (Australia)Pty Ltd OUI:30F772* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:9023EC* ID_OUI_FROM_DATABASE=Availink, Inc. OUI:203D66* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:B83A9D* ID_OUI_FROM_DATABASE=FIVE INTERACTIVE, LLC OUI:089B4B* ID_OUI_FROM_DATABASE=iKuai Networks OUI:780541* ID_OUI_FROM_DATABASE=Queclink Wireless Solutions Co., Ltd OUI:3C7873* ID_OUI_FROM_DATABASE=Airsonics OUI:3052CB* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:54AB3A* ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. OUI:8809AF* ID_OUI_FROM_DATABASE=Masimo Corp. OUI:E8DED6* ID_OUI_FROM_DATABASE=Intrising Networks, Inc. OUI:E03676* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:C8F9C8* ID_OUI_FROM_DATABASE=NewSharp Technology(SuZhou)Co,Ltd OUI:3C5CC3* ID_OUI_FROM_DATABASE=Shenzhen First Blue Chip Technology Ltd OUI:A8741D* ID_OUI_FROM_DATABASE=PHOENIX CONTACT Electronics GmbH OUI:F4C613* ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd OUI:D404CD* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:EC0133* ID_OUI_FROM_DATABASE=TRINUS SYSTEMS INC. OUI:90D8F3* ID_OUI_FROM_DATABASE=zte corporation OUI:D84710* ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. OUI:444CA8* ID_OUI_FROM_DATABASE=Arista Networks OUI:A4C138* ID_OUI_FROM_DATABASE=Telink Semiconductor (Taipei) Co. Ltd. OUI:683E34* ID_OUI_FROM_DATABASE=Meizu Technology Co., LTD OUI:48E244* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:D8EFCD* ID_OUI_FROM_DATABASE=Nokia OUI:BC5FF6* ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. OUI:1C56FE* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:7CA23E* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:501AA5* ID_OUI_FROM_DATABASE=GN Netcom A/S OUI:F09A51* ID_OUI_FROM_DATABASE=Shanghai Viroyal Electronic Technology Company Limited OUI:9870E8* ID_OUI_FROM_DATABASE=INNATECH SDN BHD OUI:50DF95* ID_OUI_FROM_DATABASE=Lytx OUI:584925* ID_OUI_FROM_DATABASE=E3 Enterprise OUI:94F278* ID_OUI_FROM_DATABASE=Elma Electronic OUI:E8BDD1* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:307CB2* ID_OUI_FROM_DATABASE=ANOV FRANCE OUI:BC6A2F* ID_OUI_FROM_DATABASE=Henge Docks LLC OUI:E4907E* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:48066A* ID_OUI_FROM_DATABASE=Tempered Networks, Inc. OUI:1CF03E* ID_OUI_FROM_DATABASE=Wearhaus Inc. OUI:BCF811* ID_OUI_FROM_DATABASE=Xiamen DNAKE Technology Co.,Ltd OUI:A8827F* ID_OUI_FROM_DATABASE=CIBN Oriental Network(Beijing) CO.,Ltd OUI:609C9F* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:249EAB* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:DC56E6* ID_OUI_FROM_DATABASE=Shenzhen Bococom Technology Co.,LTD OUI:5CA178* ID_OUI_FROM_DATABASE=TableTop Media (dba Ziosk) OUI:A0B437* ID_OUI_FROM_DATABASE=GENERAL DYNAMICS C4 SYSEMS OUI:B89ACD* ID_OUI_FROM_DATABASE=ELITE OPTOELECTRONIC(ASIA)CO.,LTD OUI:800184* ID_OUI_FROM_DATABASE=HTC Corporation OUI:38FACA* ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd OUI:44C69B* ID_OUI_FROM_DATABASE=Wuhan Feng Tian Information Network CO.,LTD OUI:C02567* ID_OUI_FROM_DATABASE=Nexxt Solutions OUI:B46D35* ID_OUI_FROM_DATABASE=Dalian Seasky Automation Co;Ltd OUI:FCE33C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:68EDA4* ID_OUI_FROM_DATABASE=Shenzhen Seavo Technology Co.,Ltd OUI:B899B0* ID_OUI_FROM_DATABASE=Cohere Technologies OUI:2CC5D3* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:80C5E6* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:D85DEF* ID_OUI_FROM_DATABASE=Busch-Jaeger Elektro GmbH OUI:10DF8B* ID_OUI_FROM_DATABASE=Shenzhen CareDear Communication Technology Co.,Ltd OUI:00A784* ID_OUI_FROM_DATABASE=ITX security OUI:3481F4* ID_OUI_FROM_DATABASE=SST Taiwan Ltd. OUI:F4B8A7* ID_OUI_FROM_DATABASE=zte corporation OUI:58F102* ID_OUI_FROM_DATABASE=BLU Products Inc. OUI:B869C2* ID_OUI_FROM_DATABASE=Sunitec Enterprise Co., Ltd. OUI:2CC548* ID_OUI_FROM_DATABASE=IAdea Corporation OUI:84DBFC* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:DCDB70* ID_OUI_FROM_DATABASE=Tonfunk Systementwicklung und Service GmbH OUI:C47D46* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:702A7D* ID_OUI_FROM_DATABASE=EpSpot AB OUI:B8B3DC* ID_OUI_FROM_DATABASE=DEREK (SHAOGUAN) LIMITED OUI:347A60* ID_OUI_FROM_DATABASE=Pace plc OUI:C4EA1D* ID_OUI_FROM_DATABASE=Technicolor OUI:900A39* ID_OUI_FROM_DATABASE=Wiio, Inc. OUI:C4693E* ID_OUI_FROM_DATABASE=Turbulence Design Inc. OUI:1C8341* ID_OUI_FROM_DATABASE=Hefei Bitland Information Technology Co.Ltd OUI:6C1E70* ID_OUI_FROM_DATABASE=Guangzhou YBDS IT Co.,Ltd OUI:C8E130* ID_OUI_FROM_DATABASE=Milkyway Group Ltd OUI:20E407* ID_OUI_FROM_DATABASE=Spark srl OUI:887384* ID_OUI_FROM_DATABASE=Toshiba OUI:8833BE* ID_OUI_FROM_DATABASE=Ivenix, Inc. OUI:34CC28* ID_OUI_FROM_DATABASE=Nexpring Co. LTD., OUI:144146* ID_OUI_FROM_DATABASE=Honeywell (China) Co., LTD OUI:F41563* ID_OUI_FROM_DATABASE=F5 Networks, Inc. OUI:4011DC* ID_OUI_FROM_DATABASE=Sonance OUI:749CE3* ID_OUI_FROM_DATABASE=Art2Wave Canada Inc. OUI:B856BD* ID_OUI_FROM_DATABASE=ITT LLC OUI:107873* ID_OUI_FROM_DATABASE=Shenzhen Jinkeyi Communication Co., Ltd. OUI:7CC709* ID_OUI_FROM_DATABASE=Shenzhen RF-LINK Elec&Technology.,Ltd OUI:3C8C40* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:D45556* ID_OUI_FROM_DATABASE=Fiber Mountain Inc. OUI:F01E34* ID_OUI_FROM_DATABASE=ORICO Technologies Co., Ltd OUI:74A063* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:A89008* ID_OUI_FROM_DATABASE=Beijing Yuecheng Technology Co. Ltd. OUI:183864* ID_OUI_FROM_DATABASE=CAP-TECH INTERNATIONAL CO., LTD. OUI:08D34B* ID_OUI_FROM_DATABASE=Techman Electronics (Changshu) Co., Ltd. OUI:C808E9* ID_OUI_FROM_DATABASE=LG Electronics OUI:589B0B* ID_OUI_FROM_DATABASE=Shineway Technologies, Inc. OUI:78ACBF* ID_OUI_FROM_DATABASE=Igneous Systems OUI:206274* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:5CCCFF* ID_OUI_FROM_DATABASE=Techroutes Network Pvt Ltd OUI:844BB7* ID_OUI_FROM_DATABASE=Beijing Sankuai Online Technology Co.,Ltd OUI:148F21* ID_OUI_FROM_DATABASE=Garmin International OUI:1C7D22* ID_OUI_FROM_DATABASE=Fuji Xerox Co., Ltd. OUI:ACD1B8* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:3C6A9D* ID_OUI_FROM_DATABASE=Dexatek Technology LTD. OUI:14893E* ID_OUI_FROM_DATABASE=VIXTEL TECHNOLOGIES LIMTED OUI:60F189* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:241C04* ID_OUI_FROM_DATABASE=SHENZHEN JEHE TECHNOLOGY DEVELOPMENT CO., LTD. OUI:F8CFC5* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:7C11CD* ID_OUI_FROM_DATABASE=QianTang Technology OUI:0492EE* ID_OUI_FROM_DATABASE=iway AG OUI:B04519* ID_OUI_FROM_DATABASE=TCT mobile ltd OUI:1436C6* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:04C09C* ID_OUI_FROM_DATABASE=Tellabs Inc. OUI:2C337A* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:844464* ID_OUI_FROM_DATABASE=ServerU Inc OUI:78312B* ID_OUI_FROM_DATABASE=zte corporation OUI:74A34A* ID_OUI_FROM_DATABASE=ZIMI CORPORATION OUI:98F5A9* ID_OUI_FROM_DATABASE=OHSUNG ELECTRONICS CO.,LTD. OUI:D89341* ID_OUI_FROM_DATABASE=General Electric Global Research OUI:F4645D* ID_OUI_FROM_DATABASE=Toshiba OUI:30D587* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:A48CDB* ID_OUI_FROM_DATABASE=Lenovo OUI:4062B6* ID_OUI_FROM_DATABASE=Tele system communication OUI:3C2C94* ID_OUI_FROM_DATABASE=杭州德澜科技有限公司(HangZhou Delan Technology Co.,Ltd) OUI:48A9D2* ID_OUI_FROM_DATABASE=Wistron Neweb Corp. OUI:F02A23* ID_OUI_FROM_DATABASE=Creative Next Design OUI:584704* ID_OUI_FROM_DATABASE=Shenzhen Webridge Technology Co.,Ltd OUI:1C14B3* ID_OUI_FROM_DATABASE=Pinyon Technologies OUI:A0E4CB* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:307350* ID_OUI_FROM_DATABASE=Inpeco SA OUI:E8CC18* ID_OUI_FROM_DATABASE=D-Link International OUI:B09137* ID_OUI_FROM_DATABASE=ISis ImageStream Internet Solutions, Inc OUI:745C9F* ID_OUI_FROM_DATABASE=TCT mobile ltd. OUI:3C1E13* ID_OUI_FROM_DATABASE=HANGZHOU SUNRISE TECHNOLOGY CO., LTD OUI:B4A828* ID_OUI_FROM_DATABASE=Shenzhen Concox Information Technology Co., Ltd OUI:50F43C* ID_OUI_FROM_DATABASE=Leeo Inc OUI:FCDBB3* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:B8186F* ID_OUI_FROM_DATABASE=ORIENTAL MOTOR CO., LTD. OUI:1C9C26* ID_OUI_FROM_DATABASE=Zoovel Technologies OUI:9C3583* ID_OUI_FROM_DATABASE=Nipro Diagnostics, Inc OUI:C456FE* ID_OUI_FROM_DATABASE=Lava International Ltd. OUI:B89BE4* ID_OUI_FROM_DATABASE=ABB Power Systems Power Generation OUI:C0EEFB* ID_OUI_FROM_DATABASE=OnePlus Tech (Shenzhen) Ltd OUI:E00DB9* ID_OUI_FROM_DATABASE=Private OUI:A41242* ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. OUI:8CF813* ID_OUI_FROM_DATABASE=ORANGE POLSKA OUI:B479A7* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD. OUI:B8F317* ID_OUI_FROM_DATABASE=iSun Smasher Communications Private Limited OUI:2442BC* ID_OUI_FROM_DATABASE=Alinco,incorporated OUI:C401CE* ID_OUI_FROM_DATABASE=PRESITION (2000) CO., LTD. OUI:D01242* ID_OUI_FROM_DATABASE=BIOS Corporation OUI:6CBFB5* ID_OUI_FROM_DATABASE=Noon Technology Co., Ltd OUI:2CA30E* ID_OUI_FROM_DATABASE=POWER DRAGON DEVELOPMENT LIMITED OUI:4CF5A0* ID_OUI_FROM_DATABASE=Scalable Network Technologies Inc OUI:84E058* ID_OUI_FROM_DATABASE=Pace plc OUI:084656* ID_OUI_FROM_DATABASE=VEO-LABS OUI:4488CB* ID_OUI_FROM_DATABASE=Camco Technologies NV OUI:5014B5* ID_OUI_FROM_DATABASE=Richfit Information Technology Co., Ltd OUI:CC3080* ID_OUI_FROM_DATABASE=VAIO Corporation OUI:F82441* ID_OUI_FROM_DATABASE=Yeelink OUI:108A1B* ID_OUI_FROM_DATABASE=RAONIX Inc. OUI:94B40F* ID_OUI_FROM_DATABASE=Aruba Networks OUI:4C2C83* ID_OUI_FROM_DATABASE=Zhejiang KaNong Network Technology Co.,Ltd. OUI:BCC342* ID_OUI_FROM_DATABASE=Panasonic System Networks Co., Ltd. OUI:E89606* ID_OUI_FROM_DATABASE=testo Instruments (Shenzhen) Co., Ltd. OUI:CC3F1D* ID_OUI_FROM_DATABASE=Intesis Software SL OUI:902181* ID_OUI_FROM_DATABASE=Shanghai Huaqin Telecom Technology Co.,Ltd OUI:D062A0* ID_OUI_FROM_DATABASE=China Essence Technology (Zhumadian) Co., Ltd. OUI:CC10A3* ID_OUI_FROM_DATABASE=Beijing Nan Bao Technology Co., Ltd. OUI:B43934* ID_OUI_FROM_DATABASE=Pen Generations, Inc. OUI:C03896* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:DCC622* ID_OUI_FROM_DATABASE=BUHEUNG SYSTEM OUI:5C2BF5* ID_OUI_FROM_DATABASE=Vivint OUI:6C0B84* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co.,Ltd. OUI:600417* ID_OUI_FROM_DATABASE=POSBANK CO.,LTD OUI:489D18* ID_OUI_FROM_DATABASE=Flashbay Limited OUI:8CB094* ID_OUI_FROM_DATABASE=Airtech I&C Co., Ltd OUI:70F196* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:6C6EFE* ID_OUI_FROM_DATABASE=Core Logic Inc. OUI:E4C62B* ID_OUI_FROM_DATABASE=Airware OUI:80F8EB* ID_OUI_FROM_DATABASE=RayTight OUI:F409D8* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD. OUI:C035C5* ID_OUI_FROM_DATABASE=Prosoft Systems LTD OUI:F8B2F3* ID_OUI_FROM_DATABASE=GUANGZHOU BOSMA TECHNOLOGY CO.,LTD OUI:8C9109* ID_OUI_FROM_DATABASE=Toyoshima Electric Technoeogy(Suzhou) Co.,Ltd. OUI:A44AD3* ID_OUI_FROM_DATABASE=ST Electronics(Shanghai) Co.,Ltd OUI:2497ED* ID_OUI_FROM_DATABASE=Techvision Intelligent Technology Limited OUI:104E07* ID_OUI_FROM_DATABASE=Shanghai Genvision Industries Co.,Ltd OUI:4C11BF* ID_OUI_FROM_DATABASE=ZHEJIANG DAHUA TECHNOLOGY CO.,LTD. OUI:FCD5D9* ID_OUI_FROM_DATABASE=Shenzhen SDMC Technology Co., Ltd. OUI:007532* ID_OUI_FROM_DATABASE=INID BV OUI:A002DC* ID_OUI_FROM_DATABASE=Amazon Technologies Inc. OUI:907EBA* ID_OUI_FROM_DATABASE=UTEK TECHNOLOGY (SHENZHEN) CO.,LTD OUI:488244* ID_OUI_FROM_DATABASE=Life Fitness / Div. of Brunswick OUI:D85DFB* ID_OUI_FROM_DATABASE=Private OUI:7CC4EF* ID_OUI_FROM_DATABASE=Devialet OUI:A8E539* ID_OUI_FROM_DATABASE=Moimstone Co.,Ltd OUI:98F170* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:04C991* ID_OUI_FROM_DATABASE=Phistek INC. OUI:404EEB* ID_OUI_FROM_DATABASE=Higher Way Electronic Co., Ltd. OUI:50BD5F* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:147590* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:ECB907* ID_OUI_FROM_DATABASE=CloudGenix Inc OUI:5CF9F0* ID_OUI_FROM_DATABASE=Atomos Engineering P/L OUI:581F67* ID_OUI_FROM_DATABASE=Open-m technology limited OUI:BC25F0* ID_OUI_FROM_DATABASE=3D Display Technologies Co., Ltd. OUI:94AEE3* ID_OUI_FROM_DATABASE=Belden Hirschmann Industries (Suzhou) Ltd. OUI:44666E* ID_OUI_FROM_DATABASE=IP-LINE OUI:705B2E* ID_OUI_FROM_DATABASE=M2Communication Inc. OUI:0C8C8F* ID_OUI_FROM_DATABASE=Kamo Technology Limited OUI:3CD9CE* ID_OUI_FROM_DATABASE=Eclipse WiFi OUI:C80210* ID_OUI_FROM_DATABASE=LG Innotek OUI:702DD1* ID_OUI_FROM_DATABASE=Newings Communication CO., LTD. OUI:44746C* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:F4F646* ID_OUI_FROM_DATABASE=Dediprog Technology Co. Ltd. OUI:ECD9D1* ID_OUI_FROM_DATABASE=Shenzhen TG-NET Botone Technology Co.,Ltd. OUI:748F4D* ID_OUI_FROM_DATABASE=MEN Mikro Elektronik GmbH OUI:F4FD2B* ID_OUI_FROM_DATABASE=ZOYI Company OUI:FCAA14* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:50FEF2* ID_OUI_FROM_DATABASE=Sify Technologies Ltd OUI:7CE524* ID_OUI_FROM_DATABASE=Quirky, Inc. OUI:7CD30A* ID_OUI_FROM_DATABASE=INVENTEC Corporation OUI:3481C4* ID_OUI_FROM_DATABASE=AVM GmbH OUI:885BDD* ID_OUI_FROM_DATABASE=Aerohive Networks Inc. OUI:A47E39* ID_OUI_FROM_DATABASE=zte corporation OUI:0C63FC* ID_OUI_FROM_DATABASE=Nanjing Signway Technology Co., Ltd OUI:ACA9A0* ID_OUI_FROM_DATABASE=Audioengine, Ltd. OUI:A8A668* ID_OUI_FROM_DATABASE=zte corporation OUI:A8F7E0* ID_OUI_FROM_DATABASE=PLANET Technology Corporation OUI:2C5BE1* ID_OUI_FROM_DATABASE=Centripetal Networks, Inc OUI:D87EB1* ID_OUI_FROM_DATABASE=x.o.ware, inc. OUI:4045DA* ID_OUI_FROM_DATABASE=Spreadtrum Communications (Shanghai) Co., Ltd. OUI:98BE94* ID_OUI_FROM_DATABASE=IBM OUI:D4B43E* ID_OUI_FROM_DATABASE=Messcomp Datentechnik GmbH OUI:48D18E* ID_OUI_FROM_DATABASE=Metis Communication Co.,Ltd OUI:A49F85* ID_OUI_FROM_DATABASE=Lyve Minds, Inc OUI:888914* ID_OUI_FROM_DATABASE=All Components Incorporated OUI:D8150D* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:A06518* ID_OUI_FROM_DATABASE=VNPT TECHNOLOGY OUI:748F1B* ID_OUI_FROM_DATABASE=MasterImage 3D OUI:684898* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E4121D* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:D82A15* ID_OUI_FROM_DATABASE=Leitner SpA OUI:C4291D* ID_OUI_FROM_DATABASE=KLEMSAN ELEKTRIK ELEKTRONIK SAN.VE TIC.AS. OUI:704E01* ID_OUI_FROM_DATABASE=KWANGWON TECH CO., LTD. OUI:848433* ID_OUI_FROM_DATABASE=Paradox Engineering SA OUI:D4319D* ID_OUI_FROM_DATABASE=Sinwatec OUI:DC052F* ID_OUI_FROM_DATABASE=National Products Inc. OUI:CC398C* ID_OUI_FROM_DATABASE=Shiningtek OUI:6C5F1C* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:B42C92* ID_OUI_FROM_DATABASE=Zhejiang Weirong Electronic Co., Ltd OUI:FC1349* ID_OUI_FROM_DATABASE=Global Apps Corp. OUI:8C41F2* ID_OUI_FROM_DATABASE=RDA Technologies Ltd. OUI:FC07A0* ID_OUI_FROM_DATABASE=LRE Medical GmbH OUI:AC02CA* ID_OUI_FROM_DATABASE=HI Solutions, Inc. OUI:F490CA* ID_OUI_FROM_DATABASE=Tensorcom OUI:2C534A* ID_OUI_FROM_DATABASE=Shenzhen Winyao Electronic Limited OUI:CC856C* ID_OUI_FROM_DATABASE=SHENZHEN MDK DIGITAL TECHNOLOGY CO.,LTD OUI:60FFDD* ID_OUI_FROM_DATABASE=C.E. ELECTRONICS, INC OUI:FCBBA1* ID_OUI_FROM_DATABASE=Shenzhen Minicreate Technology Co.,Ltd OUI:50B695* ID_OUI_FROM_DATABASE=Micropoint Biotechnologies,Inc. OUI:B48547* ID_OUI_FROM_DATABASE=Amptown System Company GmbH OUI:085700* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:60E327* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:E4D332* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:A0DA92* ID_OUI_FROM_DATABASE=Nanjing Glarun Atten Technology Co. Ltd. OUI:6828BA* ID_OUI_FROM_DATABASE=Dejai OUI:407875* ID_OUI_FROM_DATABASE=IMBEL - Industria de Material Belico do Brasil OUI:0C4F5A* ID_OUI_FROM_DATABASE=ASA-RT s.r.l. OUI:B4B542* ID_OUI_FROM_DATABASE=Hubbell Power Systems, Inc. OUI:54CDEE* ID_OUI_FROM_DATABASE=ShenZhen Apexis Electronic Co.,Ltd OUI:F8F005* ID_OUI_FROM_DATABASE=Newport Media Inc. OUI:98C0EB* ID_OUI_FROM_DATABASE=Global Regency Ltd OUI:D4224E* ID_OUI_FROM_DATABASE=Alcatel Lucent OUI:28DEF6* ID_OUI_FROM_DATABASE=bioMerieux Inc. OUI:88E8F8* ID_OUI_FROM_DATABASE=YONG TAI ELECTRONIC (DONGGUAN) LTD. OUI:2C073C* ID_OUI_FROM_DATABASE=DEVLINE LIMITED OUI:F015A0* ID_OUI_FROM_DATABASE=KyungDong One Co., Ltd. OUI:ECF72B* ID_OUI_FROM_DATABASE=HD DIGITAL TECH CO., LTD. OUI:D8B6D6* ID_OUI_FROM_DATABASE=Blu Tether Limited OUI:847207* ID_OUI_FROM_DATABASE=I&C Technology OUI:3C25D7* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:1889DF* ID_OUI_FROM_DATABASE=CerebrEX Inc. OUI:30A8DB* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:CC9F35* ID_OUI_FROM_DATABASE=Transbit Sp. z o.o. OUI:8C569D* ID_OUI_FROM_DATABASE=Imaging Solutions Group OUI:A43A69* ID_OUI_FROM_DATABASE=Vers Inc OUI:387B47* ID_OUI_FROM_DATABASE=AKELA, Inc. OUI:7CCD11* ID_OUI_FROM_DATABASE=MS-Magnet OUI:94FBB2* ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd OUI:4CE1BB* ID_OUI_FROM_DATABASE=Zhuhai HiFocus Technology Co., Ltd. OUI:8CDE99* ID_OUI_FROM_DATABASE=Comlab Inc. OUI:085AE0* ID_OUI_FROM_DATABASE=Recovision Technology Co., Ltd. OUI:7CE4AA* ID_OUI_FROM_DATABASE=Private OUI:1820A6* ID_OUI_FROM_DATABASE=Sage Co., Ltd. OUI:BCF61C* ID_OUI_FROM_DATABASE=Geomodeling Wuxi Technology Co. Ltd. OUI:083F3E* ID_OUI_FROM_DATABASE=WSH GmbH OUI:6C09D6* ID_OUI_FROM_DATABASE=Digiquest Electronics LTD OUI:F03A4B* ID_OUI_FROM_DATABASE=Bloombase, Inc. OUI:2C9AA4* ID_OUI_FROM_DATABASE=NGI SpA OUI:B46698* ID_OUI_FROM_DATABASE=Zealabs srl OUI:283B96* ID_OUI_FROM_DATABASE=Cool Control LTD OUI:80D433* ID_OUI_FROM_DATABASE=LzLabs GmbH OUI:687CC8* ID_OUI_FROM_DATABASE=Measurement Systems S. de R.L. OUI:38BF2F* ID_OUI_FROM_DATABASE=Espec Corp. OUI:182012* ID_OUI_FROM_DATABASE=Aztech Associates Inc. OUI:34BE00* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:343111* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:0CBD51* ID_OUI_FROM_DATABASE=TCT Mobile Limited OUI:C0F991* ID_OUI_FROM_DATABASE=GME Standard Communications P/L OUI:14EDA5* ID_OUI_FROM_DATABASE=Wächter GmbH Sicherheitssysteme OUI:E056F4* ID_OUI_FROM_DATABASE=AxesNetwork Solutions inc. OUI:B8C1A2* ID_OUI_FROM_DATABASE=Dragon Path Technologies Co., Limited OUI:50ED78* ID_OUI_FROM_DATABASE=Changzhou Yongse Infotech Co.,Ltd OUI:8CB7F7* ID_OUI_FROM_DATABASE=Shenzhen UniStrong Science & Technology Co., Ltd OUI:085240* ID_OUI_FROM_DATABASE=EbV Elektronikbau- und Vertriebs GmbH OUI:80F25E* ID_OUI_FROM_DATABASE=Kyynel OUI:94DF4E* ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd. OUI:E0AEB2* ID_OUI_FROM_DATABASE=Bender GmbH & Co.KG OUI:2C553C* ID_OUI_FROM_DATABASE=Gainspeed, Inc. OUI:B43E3B* ID_OUI_FROM_DATABASE=Viableware, Inc OUI:F854AF* ID_OUI_FROM_DATABASE=ECI Telecom Ltd. OUI:7C0623* ID_OUI_FROM_DATABASE=Ultra Electronics, CIS OUI:2464EF* ID_OUI_FROM_DATABASE=CYG SUNRI CO.,LTD. OUI:50B888* ID_OUI_FROM_DATABASE=wi2be Tecnologia S/A OUI:844F03* ID_OUI_FROM_DATABASE=Ablelink Electronics Ltd OUI:94B9B4* ID_OUI_FROM_DATABASE=Aptos Technology OUI:D0B523* ID_OUI_FROM_DATABASE=Bestcare Cloucal Corp. OUI:783D5B* ID_OUI_FROM_DATABASE=TELNET Redes Inteligentes S.A. OUI:D0C42F* ID_OUI_FROM_DATABASE=Tamagawa Seiki Co.,Ltd. OUI:5CFFFF* ID_OUI_FROM_DATABASE=Shenzhen Kezhonglong Optoelectronic Technology Co., Ltd OUI:F0D3A7* ID_OUI_FROM_DATABASE=CobaltRay Co., Ltd OUI:20D390* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:847616* ID_OUI_FROM_DATABASE=Addat s.r.o. OUI:D46867* ID_OUI_FROM_DATABASE=Neoventus Design Group OUI:68692E* ID_OUI_FROM_DATABASE=Zycoo Co.,Ltd OUI:1C63B7* ID_OUI_FROM_DATABASE=OpenProducts 237 AB OUI:A0A23C* ID_OUI_FROM_DATABASE=GPMS OUI:A03B1B* ID_OUI_FROM_DATABASE=Inspire Tech OUI:3C6E63* ID_OUI_FROM_DATABASE=Mitron OY OUI:502E5C* ID_OUI_FROM_DATABASE=HTC Corporation OUI:20D21F* ID_OUI_FROM_DATABASE=Wincal Technology Corp. OUI:FC1E16* ID_OUI_FROM_DATABASE=IPEVO corp OUI:6C4B7F* ID_OUI_FROM_DATABASE=Vossloh-Schwabe Deutschland GmbH OUI:0CCB8D* ID_OUI_FROM_DATABASE=ASCO Numatics GmbH OUI:FC019E* ID_OUI_FROM_DATABASE=VIEVU OUI:34AA8B* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:F45F69* ID_OUI_FROM_DATABASE=Matsufu Electronics distribution Company OUI:F4A294* ID_OUI_FROM_DATABASE=EAGLE WORLD DEVELOPMENT CO., LIMITED OUI:2CCD69* ID_OUI_FROM_DATABASE=Aqavi.com OUI:947C3E* ID_OUI_FROM_DATABASE=Polewall Norge AS OUI:385AA8* ID_OUI_FROM_DATABASE=Beijing Zhongdun Security Technology Development Co. OUI:FC3FAB* ID_OUI_FROM_DATABASE=Henan Lanxin Technology Co., Ltd OUI:2847AA* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:682DDC* ID_OUI_FROM_DATABASE=Wuhan Changjiang Electro-Communication Equipment CO.,LTD OUI:FCB0C4* ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co., Ltd OUI:9CBB98* ID_OUI_FROM_DATABASE=Shen Zhen RND Electronic Co.,LTD OUI:345C40* ID_OUI_FROM_DATABASE=Cargt Holdings LLC OUI:34885D* ID_OUI_FROM_DATABASE=Logitech Far East OUI:708D09* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:FCE1D9* ID_OUI_FROM_DATABASE=Stable Imaging Solutions LLC OUI:38B74D* ID_OUI_FROM_DATABASE=Fijowave Limited OUI:A0E5E9* ID_OUI_FROM_DATABASE=enimai Inc OUI:A88D7B* ID_OUI_FROM_DATABASE=SunDroid Global limited. OUI:6064A1* ID_OUI_FROM_DATABASE=RADiflow Ltd. OUI:8079AE* ID_OUI_FROM_DATABASE=ShanDong Tecsunrise Co.,Ltd OUI:2C7155* ID_OUI_FROM_DATABASE=HiveMotion OUI:909916* ID_OUI_FROM_DATABASE=ELVEES NeoTek OJSC OUI:FC1BFF* ID_OUI_FROM_DATABASE=V-ZUG AG OUI:AC5036* ID_OUI_FROM_DATABASE=Pi-Coral Inc OUI:BCEE7B* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:8C3AE3* ID_OUI_FROM_DATABASE=LG Electronics OUI:FC09D8* ID_OUI_FROM_DATABASE=ACTEON Group OUI:0C1262* ID_OUI_FROM_DATABASE=zte corporation OUI:A875E2* ID_OUI_FROM_DATABASE=Aventura Technologies, Inc. OUI:E0D1E6* ID_OUI_FROM_DATABASE=Aliph dba Jawbone OUI:28C671* ID_OUI_FROM_DATABASE=Yota Devices OY OUI:DC1792* ID_OUI_FROM_DATABASE=Captivate Network OUI:7C8306* ID_OUI_FROM_DATABASE=Glen Dimplex Nordic as OUI:84253F* ID_OUI_FROM_DATABASE=Silex Technology, Inc OUI:907A0A* ID_OUI_FROM_DATABASE=Gebr. Bode GmbH & Co KG OUI:306112* ID_OUI_FROM_DATABASE=PAV GmbH OUI:A0C6EC* ID_OUI_FROM_DATABASE=ShenZhen ANYK Technology Co.,LTD OUI:6405BE* ID_OUI_FROM_DATABASE=NEW LIGHT LED OUI:F8FF5F* ID_OUI_FROM_DATABASE=Shenzhen Communication Technology Co.,Ltd OUI:DCC422* ID_OUI_FROM_DATABASE=Systembase Limited OUI:F4BD7C* ID_OUI_FROM_DATABASE=Chengdu jinshi communication Co., LTD OUI:C8F36B* ID_OUI_FROM_DATABASE=Yamato Scale Co.,Ltd. OUI:6C90B1* ID_OUI_FROM_DATABASE=SanLogic Inc OUI:845C93* ID_OUI_FROM_DATABASE=Chabrier Services OUI:D44C9C* ID_OUI_FROM_DATABASE=Shenzhen YOOBAO Technology Co.Ltd OUI:68E166* ID_OUI_FROM_DATABASE=Private OUI:60FEF9* ID_OUI_FROM_DATABASE=Thomas & Betts OUI:FC4BBC* ID_OUI_FROM_DATABASE=Sunplus Technology Co., Ltd. OUI:142D8B* ID_OUI_FROM_DATABASE=Incipio Technologies, Inc OUI:CCE8AC* ID_OUI_FROM_DATABASE=SOYEA Technology Co.,Ltd. OUI:78D38D* ID_OUI_FROM_DATABASE=HONGKONG YUNLINK TECHNOLOGY LIMITED OUI:1C48F9* ID_OUI_FROM_DATABASE=GN Netcom A/S OUI:744BE9* ID_OUI_FROM_DATABASE=EXPLORER HYPERTECH CO.,LTD OUI:B836D8* ID_OUI_FROM_DATABASE=Videoswitch OUI:F835DD* ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. OUI:0CF019* ID_OUI_FROM_DATABASE=Malgn Technology Co., Ltd. OUI:D46A91* ID_OUI_FROM_DATABASE=Snap AV OUI:E8519D* ID_OUI_FROM_DATABASE=Yeonhab Precision Co.,LTD OUI:00B78D* ID_OUI_FROM_DATABASE=Nanjing Shining Electric Automation Co., Ltd OUI:882364* ID_OUI_FROM_DATABASE=Watchnet DVR Inc OUI:A05B21* ID_OUI_FROM_DATABASE=ENVINET GmbH OUI:50B8A2* ID_OUI_FROM_DATABASE=ImTech Technologies LLC, OUI:A41566* ID_OUI_FROM_DATABASE=Wei Fang Goertek Electronics Co.,Ltd OUI:B04C05* ID_OUI_FROM_DATABASE=Fresenius Medical Care Deutschland GmbH OUI:A0EC80* ID_OUI_FROM_DATABASE=zte corporation OUI:9046B7* ID_OUI_FROM_DATABASE=Vadaro Pte Ltd OUI:1C08C1* ID_OUI_FROM_DATABASE=Lg Innotek OUI:201D03* ID_OUI_FROM_DATABASE=Elatec GmbH OUI:C06C6D* ID_OUI_FROM_DATABASE=MagneMotion, Inc. OUI:E03E4A* ID_OUI_FROM_DATABASE=Cavanagh Group International OUI:D890E8* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:24C696* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:30766F* ID_OUI_FROM_DATABASE=LG Electronics OUI:6CB350* ID_OUI_FROM_DATABASE=Anhui comhigher tech co.,ltd OUI:A42305* ID_OUI_FROM_DATABASE=Open Networking Laboratory OUI:1C86AD* ID_OUI_FROM_DATABASE=MCT CO., LTD. OUI:28D93E* ID_OUI_FROM_DATABASE=Telecor Inc. OUI:C80258* ID_OUI_FROM_DATABASE=ITW GSE ApS OUI:1001CA* ID_OUI_FROM_DATABASE=Ashley Butterworth OUI:246AAB* ID_OUI_FROM_DATABASE=IT-IS International OUI:28F532* ID_OUI_FROM_DATABASE=ADD-Engineering BV OUI:78FE41* ID_OUI_FROM_DATABASE=Socus networks OUI:083571* ID_OUI_FROM_DATABASE=CASwell INC. OUI:DCF755* ID_OUI_FROM_DATABASE=SITRONIK OUI:E42D02* ID_OUI_FROM_DATABASE=TCT Mobile Limited OUI:ACCA8E* ID_OUI_FROM_DATABASE=ODA Technologies OUI:74CA25* ID_OUI_FROM_DATABASE=Calxeda, Inc. OUI:181EB0* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:CCBD35* ID_OUI_FROM_DATABASE=Steinel GmbH OUI:9498A2* ID_OUI_FROM_DATABASE=Shanghai LISTEN TECH.LTD OUI:2CB693* ID_OUI_FROM_DATABASE=Radware OUI:88685C* ID_OUI_FROM_DATABASE=Shenzhen ChuangDao & Perpetual Eternal Technology Co.,Ltd OUI:B4FE8C* ID_OUI_FROM_DATABASE=Centro Sicurezza Italia SpA OUI:D82916* ID_OUI_FROM_DATABASE=Ascent Communication Technology OUI:6472D8* ID_OUI_FROM_DATABASE=GooWi Technology Co.,Limited OUI:3C081E* ID_OUI_FROM_DATABASE=Beijing Yupont Electric Power Technology Co.,Ltd OUI:7CA15D* ID_OUI_FROM_DATABASE=GN ReSound A/S OUI:B4DD15* ID_OUI_FROM_DATABASE=ControlThings Oy Ab OUI:F8FEA8* ID_OUI_FROM_DATABASE=Technico Japan Corporation OUI:A8154D* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:D05099* ID_OUI_FROM_DATABASE=ASRock Incorporation OUI:78A106* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:A49EDB* ID_OUI_FROM_DATABASE=AutoCrib, Inc. OUI:282CB2* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:D43A65* ID_OUI_FROM_DATABASE=IGRS Engineering Lab Ltd. OUI:D0EB03* ID_OUI_FROM_DATABASE=Zhehua technology limited OUI:A0861D* ID_OUI_FROM_DATABASE=Chengdu Fuhuaxin Technology co.,Ltd OUI:888964* ID_OUI_FROM_DATABASE=GSI Electronics Inc. OUI:4C82CF* ID_OUI_FROM_DATABASE=Echostar Technologies OUI:9CA577* ID_OUI_FROM_DATABASE=Osorno Enterprises Inc. OUI:C0C3B6* ID_OUI_FROM_DATABASE=Automatic Systems OUI:A8294C* ID_OUI_FROM_DATABASE=Precision Optical Transceivers, Inc. OUI:3C86A8* ID_OUI_FROM_DATABASE=Sangshin elecom .co,, LTD OUI:FCDD55* ID_OUI_FROM_DATABASE=Shenzhen WeWins wireless Co.,Ltd OUI:CC0DEC* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:68B094* ID_OUI_FROM_DATABASE=INESA ELECTRON CO.,LTD OUI:40E730* ID_OUI_FROM_DATABASE=DEY Storage Systems, Inc. OUI:F05DC8* ID_OUI_FROM_DATABASE=Duracell Powermat OUI:6C8686* ID_OUI_FROM_DATABASE=Technonia OUI:4432C8* ID_OUI_FROM_DATABASE=Technicolor USA Inc. OUI:78521A* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:68DB67* ID_OUI_FROM_DATABASE=Nantong Coship Electronics Co., Ltd OUI:BC261D* ID_OUI_FROM_DATABASE=HONG KONG TECON TECHNOLOGY OUI:10B9FE* ID_OUI_FROM_DATABASE=Lika srl OUI:D42751* ID_OUI_FROM_DATABASE=Infopia Co., Ltd OUI:A895B0* ID_OUI_FROM_DATABASE=Aker Subsea Ltd OUI:5C20D0* ID_OUI_FROM_DATABASE=Asoni Communication Co., Ltd. OUI:E0C3F3* ID_OUI_FROM_DATABASE=zte corporation OUI:30CDA7* ID_OUI_FROM_DATABASE=Samsung Electronics ITS, Printer division OUI:104D77* ID_OUI_FROM_DATABASE=Innovative Computer Engineering OUI:788DF7* ID_OUI_FROM_DATABASE=Hitron Technologies. Inc OUI:6CECA1* ID_OUI_FROM_DATABASE=SHENZHEN CLOU ELECTRONICS CO. LTD. OUI:D862DB* ID_OUI_FROM_DATABASE=Eno Inc. OUI:A8D236* ID_OUI_FROM_DATABASE=Lightware Visual Engineering OUI:48F925* ID_OUI_FROM_DATABASE=Maestronic OUI:C0885B* ID_OUI_FROM_DATABASE=SnD Tech Co., Ltd. OUI:64C667* ID_OUI_FROM_DATABASE=Barnes&Noble OUI:C47DCC* ID_OUI_FROM_DATABASE=Zebra Technologies Inc OUI:64535D* ID_OUI_FROM_DATABASE=Frauscher Sensortechnik OUI:105F06* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:00B56D* ID_OUI_FROM_DATABASE=David Electronics Co., LTD. OUI:B461FF* ID_OUI_FROM_DATABASE=Lumigon A/S OUI:9038DF* ID_OUI_FROM_DATABASE=Changzhou Tiannengbo System Co. Ltd. OUI:CC593E* ID_OUI_FROM_DATABASE=TOUMAZ LTD OUI:84E714* ID_OUI_FROM_DATABASE=Liang Herng Enterprise,Co.Ltd. OUI:303D08* ID_OUI_FROM_DATABASE=GLINTT TES S.A. OUI:E496AE* ID_OUI_FROM_DATABASE=ALTOGRAPHICS Inc. OUI:F80BD0* ID_OUI_FROM_DATABASE=Datang Telecom communication terminal (Tianjin) Co., Ltd. OUI:48B9C2* ID_OUI_FROM_DATABASE=Teletics Inc. OUI:D046DC* ID_OUI_FROM_DATABASE=Southwest Research Institute OUI:F8F082* ID_OUI_FROM_DATABASE=Orion Networks International, Inc OUI:046E49* ID_OUI_FROM_DATABASE=TaiYear Electronic Technology (Suzhou) Co., Ltd OUI:08606E* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:BC39A6* ID_OUI_FROM_DATABASE=CSUN System Technology Co.,LTD OUI:ECB541* ID_OUI_FROM_DATABASE=SHINANO E and E Co.Ltd. OUI:D40057* ID_OUI_FROM_DATABASE=MC Technologies GmbH OUI:B85AF7* ID_OUI_FROM_DATABASE=Ouya, Inc OUI:E0D9A2* ID_OUI_FROM_DATABASE=Hippih aps OUI:B0C4E7* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:F0F669* ID_OUI_FROM_DATABASE=Motion Analysis Corporation OUI:F0219D* ID_OUI_FROM_DATABASE=Cal-Comp Electronics & Communications Company Ltd. OUI:F8D7BF* ID_OUI_FROM_DATABASE=REV Ritter GmbH OUI:AC5D10* ID_OUI_FROM_DATABASE=Pace Americas OUI:88F490* ID_OUI_FROM_DATABASE=Jetmobile Pte Ltd OUI:AC8D14* ID_OUI_FROM_DATABASE=Smartrove Inc OUI:18673F* ID_OUI_FROM_DATABASE=Hanover Displays Limited OUI:A00ABF* ID_OUI_FROM_DATABASE=Wieson Technologies Co., Ltd. OUI:2091D9* ID_OUI_FROM_DATABASE=I'M SPA OUI:744D79* ID_OUI_FROM_DATABASE=Arrive Systems Inc. OUI:C83D97* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:38192F* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:141BF0* ID_OUI_FROM_DATABASE=Intellimedia Systems Ltd OUI:101D51* ID_OUI_FROM_DATABASE=ON-Q LLC dba ON-Q Mesh Networks OUI:34C99D* ID_OUI_FROM_DATABASE=EIDOLON COMMUNICATIONS TECHNOLOGY CO. LTD. OUI:8C4AEE* ID_OUI_FROM_DATABASE=GIGA TMS INC OUI:F46DE2* ID_OUI_FROM_DATABASE=zte corporation OUI:B838CA* ID_OUI_FROM_DATABASE=Kyokko Tsushin System CO.,LTD OUI:380FE4* ID_OUI_FROM_DATABASE=Dedicated Network Partners Oy OUI:847A88* ID_OUI_FROM_DATABASE=HTC Corporation OUI:0808C2* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:5461EA* ID_OUI_FROM_DATABASE=Zaplox AB OUI:78324F* ID_OUI_FROM_DATABASE=Millennium Group, Inc. OUI:38B5BD* ID_OUI_FROM_DATABASE=E.G.O. Elektro-Ger OUI:841715* ID_OUI_FROM_DATABASE=GP Electronics (HK) Ltd. OUI:087999* ID_OUI_FROM_DATABASE=AIM GmbH OUI:84C2E4* ID_OUI_FROM_DATABASE=Jiangsu Qinheng Co., Ltd. OUI:C0B8B1* ID_OUI_FROM_DATABASE=BitBox Ltd OUI:0C722C* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:B01408* ID_OUI_FROM_DATABASE=LIGHTSPEED INTERNATIONAL CO. OUI:84ACA4* ID_OUI_FROM_DATABASE=Beijing Novel Super Digital TV Technology Co., Ltd OUI:3C6FF7* ID_OUI_FROM_DATABASE=EnTek Systems, Inc. OUI:48B8DE* ID_OUI_FROM_DATABASE=HOMEWINS TECHNOLOGY CO.,LTD. OUI:20D5BF* ID_OUI_FROM_DATABASE=Samsung Eletronics Co., Ltd OUI:6CD032* ID_OUI_FROM_DATABASE=LG Electronics OUI:1065CF* ID_OUI_FROM_DATABASE=IQSIM OUI:B877C3* ID_OUI_FROM_DATABASE=Decagon Devices, Inc. OUI:849DC5* ID_OUI_FROM_DATABASE=Centera Photonics Inc. OUI:580943* ID_OUI_FROM_DATABASE=Private OUI:547FA8* ID_OUI_FROM_DATABASE=TELCO systems, s.r.o. OUI:5474E6* ID_OUI_FROM_DATABASE=Webtech Wireless OUI:E8A364* ID_OUI_FROM_DATABASE=Signal Path International / Peachtree Audio OUI:D0D6CC* ID_OUI_FROM_DATABASE=Wintop OUI:FC1F19* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS CO., LTD. OUI:9C541C* ID_OUI_FROM_DATABASE=Shenzhen My-power Technology Co.,Ltd OUI:90187C* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD. OUI:10F3DB* ID_OUI_FROM_DATABASE=Gridco Systems, Inc. OUI:B01203* ID_OUI_FROM_DATABASE=Dynamics Hong Kong Limited OUI:7093F8* ID_OUI_FROM_DATABASE=Space Monkey, Inc. OUI:305D38* ID_OUI_FROM_DATABASE=Beissbarth OUI:FCD6BD* ID_OUI_FROM_DATABASE=Robert Bosch GmbH OUI:044A50* ID_OUI_FROM_DATABASE=Ramaxel Technology (Shenzhen) limited company OUI:A4466B* ID_OUI_FROM_DATABASE=EOC Technology OUI:7C386C* ID_OUI_FROM_DATABASE=Real Time Logic OUI:D8AF3B* ID_OUI_FROM_DATABASE=Hangzhou Bigbright Integrated communications system Co.,Ltd OUI:78D34F* ID_OUI_FROM_DATABASE=Pace-O-Matic, Inc. OUI:D857EF* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:647657* ID_OUI_FROM_DATABASE=Innovative Security Designs OUI:60455E* ID_OUI_FROM_DATABASE=Liptel s.r.o. OUI:944A09* ID_OUI_FROM_DATABASE=BitWise Controls OUI:E8102E* ID_OUI_FROM_DATABASE=Really Simple Software, Inc OUI:D48CB5* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:24A43C* ID_OUI_FROM_DATABASE=Ubiquiti Networks, INC OUI:D41E35* ID_OUI_FROM_DATABASE=TOHO Electronics INC. OUI:700BC0* ID_OUI_FROM_DATABASE=Dewav Technology Company OUI:3CF392* ID_OUI_FROM_DATABASE=Virtualtek. Co. Ltd OUI:889676* ID_OUI_FROM_DATABASE=TTC MARCONI s.r.o. OUI:149FE8* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:70B599* ID_OUI_FROM_DATABASE=Embedded Technologies s.r.o. OUI:547398* ID_OUI_FROM_DATABASE=Toyo Electronics Corporation OUI:E0AAB0* ID_OUI_FROM_DATABASE=GENERAL VISION ELECTRONICS CO. LTD. OUI:68B43A* ID_OUI_FROM_DATABASE=WaterFurnace International, Inc. OUI:543968* ID_OUI_FROM_DATABASE=Edgewater Networks Inc OUI:C041F6* ID_OUI_FROM_DATABASE=LG Electronics Inc OUI:985E1B* ID_OUI_FROM_DATABASE=ConversDigital Co., Ltd. OUI:9C0DAC* ID_OUI_FROM_DATABASE=Tymphany HK Limited OUI:8CD3A2* ID_OUI_FROM_DATABASE=VisSim AS OUI:24EE3A* ID_OUI_FROM_DATABASE=Chengdu Yingji Electronic Hi-tech Co Ltd OUI:F82285* ID_OUI_FROM_DATABASE=Cypress Technology CO., LTD. OUI:8482F4* ID_OUI_FROM_DATABASE=Beijing Huasun Unicreate Technology Co., Ltd OUI:0CC47E* ID_OUI_FROM_DATABASE=EUCAST Co., Ltd. OUI:CCE798* ID_OUI_FROM_DATABASE=My Social Stuff OUI:50724D* ID_OUI_FROM_DATABASE=BEG Brueck Electronic GmbH OUI:B898B0* ID_OUI_FROM_DATABASE=Atlona Inc. OUI:1C66AA* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:2C625A* ID_OUI_FROM_DATABASE=Finest Security Systems Co., Ltd OUI:2074CF* ID_OUI_FROM_DATABASE=Shenzhen Voxtech Co.,Ltd OUI:ACBD0B* ID_OUI_FROM_DATABASE=IMAC CO.,LTD OUI:D8D27C* ID_OUI_FROM_DATABASE=JEMA ENERGY, SA OUI:60CBFB* ID_OUI_FROM_DATABASE=AirScape Inc. OUI:4C5427* ID_OUI_FROM_DATABASE=Linepro Sp. z o.o. OUI:3CEAFB* ID_OUI_FROM_DATABASE=NSE AG OUI:3476C5* ID_OUI_FROM_DATABASE=I-O DATA DEVICE, INC. OUI:407074* ID_OUI_FROM_DATABASE=Life Technology (China) Co., Ltd OUI:58BFEA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E856D6* ID_OUI_FROM_DATABASE=NCTech Ltd OUI:4088E0* ID_OUI_FROM_DATABASE=Beijing Ereneben Information Technology Limited Shenzhen Branch OUI:1CF4CA* ID_OUI_FROM_DATABASE=Private OUI:EC4C4D* ID_OUI_FROM_DATABASE=ZAO NPK RoTeK OUI:E8D483* ID_OUI_FROM_DATABASE=ULTIMATE Europe Transportation Equipment GmbH OUI:089E01* ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. OUI:ACD9D6* ID_OUI_FROM_DATABASE=tci GmbH OUI:7493A4* ID_OUI_FROM_DATABASE=Zebra Technologies Corp. OUI:58C38B* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:2CD444* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:EC1A59* ID_OUI_FROM_DATABASE=Belkin International Inc. OUI:04F8C2* ID_OUI_FROM_DATABASE=Flaircomm Microelectronics, Inc. OUI:0C93FB* ID_OUI_FROM_DATABASE=BNS Solutions OUI:E45614* ID_OUI_FROM_DATABASE=Suttle Apparatus OUI:784405* ID_OUI_FROM_DATABASE=FUJITU(HONG KONG) ELECTRONIC Co.,LTD. OUI:C03F2A* ID_OUI_FROM_DATABASE=Biscotti, Inc. OUI:5001BB* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:A40BED* ID_OUI_FROM_DATABASE=Carry Technology Co.,Ltd OUI:0CD996* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:D82DE1* ID_OUI_FROM_DATABASE=Tricascade Inc. OUI:C438D3* ID_OUI_FROM_DATABASE=TAGATEC CO.,LTD OUI:842BBC* ID_OUI_FROM_DATABASE=Modelleisenbahn GmbH OUI:B8B7D7* ID_OUI_FROM_DATABASE=2GIG Technologies OUI:1048B1* ID_OUI_FROM_DATABASE=Beijing Duokan Technology Limited OUI:005D03* ID_OUI_FROM_DATABASE=Xilinx, Inc OUI:20FABB* ID_OUI_FROM_DATABASE=Cambridge Executive Limited OUI:1C0B52* ID_OUI_FROM_DATABASE=EPICOM S.A OUI:747E2D* ID_OUI_FROM_DATABASE=Beijing Thomson CITIC Digital Technology Co. LTD. OUI:E80C75* ID_OUI_FROM_DATABASE=Syncbak, Inc. OUI:BC8B55* ID_OUI_FROM_DATABASE=NPP ELIKS America Inc. DBA T&M Atlantic OUI:D8EB97* ID_OUI_FROM_DATABASE=TRENDnet, Inc. OUI:202598* ID_OUI_FROM_DATABASE=Teleview OUI:44B382* ID_OUI_FROM_DATABASE=Kuang-chi Institute of Advanced Technology OUI:D80DE3* ID_OUI_FROM_DATABASE=FXI TECHNOLOGIES AS OUI:1CE165* ID_OUI_FROM_DATABASE=Marshal Corporation OUI:0CC0C0* ID_OUI_FROM_DATABASE=MAGNETI MARELLI SISTEMAS ELECTRONICOS MEXICO OUI:AC40EA* ID_OUI_FROM_DATABASE=C&T Solution Inc. OUI:F47F35* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:A0F419* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:BCC168* ID_OUI_FROM_DATABASE=DinBox Sverige AB OUI:6CAE8B* ID_OUI_FROM_DATABASE=IBM Corporation OUI:A4F7D0* ID_OUI_FROM_DATABASE=LAN Accessories Co., Ltd. OUI:D4EC0C* ID_OUI_FROM_DATABASE=Harley-Davidson Motor Company OUI:5C0A5B* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS CO., LTD. OUI:6CA96F* ID_OUI_FROM_DATABASE=TransPacket AS OUI:AC0142* ID_OUI_FROM_DATABASE=Uriel Technologies SIA OUI:A007B6* ID_OUI_FROM_DATABASE=Advanced Technical Support, Inc. OUI:542A9C* ID_OUI_FROM_DATABASE=LSY Defense, LLC. OUI:D487D8* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:F89955* ID_OUI_FROM_DATABASE=Fortress Technology Inc OUI:008DDA* ID_OUI_FROM_DATABASE=Link One Co., Ltd. OUI:08B4CF* ID_OUI_FROM_DATABASE=Abicom International OUI:445F7A* ID_OUI_FROM_DATABASE=Shihlin Electric & Engineering Corp. OUI:28BA18* ID_OUI_FROM_DATABASE=NextNav, LLC OUI:2C36F8* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:AC3D05* ID_OUI_FROM_DATABASE=Instorescreen Aisa OUI:F48E09* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:882012* ID_OUI_FROM_DATABASE=LMI Technologies OUI:800A06* ID_OUI_FROM_DATABASE=COMTEC co.,ltd OUI:B827EB* ID_OUI_FROM_DATABASE=Raspberry Pi Foundation OUI:E88DF5* ID_OUI_FROM_DATABASE=ZNYX Networks, Inc. OUI:48EA63* ID_OUI_FROM_DATABASE=Zhejiang Uniview Technologies Co., Ltd. OUI:0CE5D3* ID_OUI_FROM_DATABASE=DH electronics GmbH OUI:C47130* ID_OUI_FROM_DATABASE=Fon Technology S.L. OUI:90CF7D* ID_OUI_FROM_DATABASE=Qingdao Hisense Electric Co.,Ltd. OUI:48D7FF* ID_OUI_FROM_DATABASE=BLANKOM Antennentechnik GmbH OUI:18D66A* ID_OUI_FROM_DATABASE=Inmarsat OUI:C85645* ID_OUI_FROM_DATABASE=Intermas France OUI:F490EA* ID_OUI_FROM_DATABASE=Deciso B.V. OUI:942197* ID_OUI_FROM_DATABASE=Stalmart Technology Limited OUI:AC9403* ID_OUI_FROM_DATABASE=Envision Peripherals Inc OUI:A865B2* ID_OUI_FROM_DATABASE=DONGGUAN YISHANG ELECTRONIC TECHNOLOGY CO., LIMITED OUI:60B982* ID_OUI_FROM_DATABASE=RO.VE.R. Laboratories S.p.A. OUI:B46238* ID_OUI_FROM_DATABASE=Exablox OUI:40704A* ID_OUI_FROM_DATABASE=Power Idea Technology Limited OUI:F0FDA0* ID_OUI_FROM_DATABASE=Acurix Networks LP OUI:D8BF4C* ID_OUI_FROM_DATABASE=Victory Concept Electronics Limited OUI:C0DF77* ID_OUI_FROM_DATABASE=Conrad Electronic SE OUI:C86000* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:645299* ID_OUI_FROM_DATABASE=The Chamberlain Group, Inc OUI:BC125E* ID_OUI_FROM_DATABASE=Beijing WisVideo INC. OUI:C80718* ID_OUI_FROM_DATABASE=TDSi OUI:48ED80* ID_OUI_FROM_DATABASE=daesung eltec OUI:A086EC* ID_OUI_FROM_DATABASE=SAEHAN HITEC Co., Ltd OUI:BC4B79* ID_OUI_FROM_DATABASE=SensingTek OUI:2818FD* ID_OUI_FROM_DATABASE=Aditya Infotech Ltd. OUI:9003B7* ID_OUI_FROM_DATABASE=PARROT OUI:844915* ID_OUI_FROM_DATABASE=vArmour Networks, Inc. OUI:A04CC1* ID_OUI_FROM_DATABASE=Helixtech Corp. OUI:1CB243* ID_OUI_FROM_DATABASE=TDC A/S OUI:1C51B5* ID_OUI_FROM_DATABASE=Techaya LTD OUI:80DB31* ID_OUI_FROM_DATABASE=Power Quotient International Co., Ltd. OUI:8C604F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:74FF7D* ID_OUI_FROM_DATABASE=Wren Sound Systems, LLC OUI:380A94* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:2CC260* ID_OUI_FROM_DATABASE=Ravello Systems OUI:30B216* ID_OUI_FROM_DATABASE=Hytec Geraetebau GmbH OUI:34FC6F* ID_OUI_FROM_DATABASE=ALCEA OUI:C0B357* ID_OUI_FROM_DATABASE=Yoshiki Electronics Industry Ltd. OUI:642DB7* ID_OUI_FROM_DATABASE=SEUNGIL ELECTRONICS OUI:A898C6* ID_OUI_FROM_DATABASE=Shinbo Co., Ltd. OUI:006BA0* ID_OUI_FROM_DATABASE=SHENZHEN UNIVERSAL INTELLISYS PTE LTD OUI:502690* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:B4211D* ID_OUI_FROM_DATABASE=Beijing GuangXin Technology Co., Ltd OUI:E039D7* ID_OUI_FROM_DATABASE=Plexxi, Inc. OUI:FC946C* ID_OUI_FROM_DATABASE=UBIVELOX OUI:B4944E* ID_OUI_FROM_DATABASE=WeTelecom Co., Ltd. OUI:345B11* ID_OUI_FROM_DATABASE=EVI HEAT AB OUI:988BAD* ID_OUI_FROM_DATABASE=Corintech Ltd. OUI:4050E0* ID_OUI_FROM_DATABASE=Milton Security Group LLC OUI:E42C56* ID_OUI_FROM_DATABASE=Lilee Systems, Ltd. OUI:50008C* ID_OUI_FROM_DATABASE=Hong Kong Telecommunications (HKT) Limited OUI:DCA8CF* ID_OUI_FROM_DATABASE=New Spin Golf, LLC. OUI:34BA9A* ID_OUI_FROM_DATABASE=Asiatelco Technologies Co. OUI:D443A8* ID_OUI_FROM_DATABASE=Changzhou Haojie Electric Co., Ltd. OUI:BCB852* ID_OUI_FROM_DATABASE=Cybera, Inc. OUI:70D6B6* ID_OUI_FROM_DATABASE=Metrum Technologies OUI:28D576* ID_OUI_FROM_DATABASE=Premier Wireless, Inc. OUI:C87CBC* ID_OUI_FROM_DATABASE=Valink Co., Ltd. OUI:409FC7* ID_OUI_FROM_DATABASE=BAEKCHUN I&C Co., Ltd. OUI:C87D77* ID_OUI_FROM_DATABASE=Shenzhen Kingtech Communication Equipment Co.,Ltd OUI:A078BA* ID_OUI_FROM_DATABASE=Pantech Co., Ltd. OUI:20BBC6* ID_OUI_FROM_DATABASE=Jabil Circuit Hungary Ltd. OUI:2C9717* ID_OUI_FROM_DATABASE=I.C.Y. B.V. OUI:64E84F* ID_OUI_FROM_DATABASE=Serialway Communication Technology Co. Ltd OUI:6CE907* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:94DF58* ID_OUI_FROM_DATABASE=IJ Electron CO.,Ltd. OUI:8C0CA3* ID_OUI_FROM_DATABASE=Amper OUI:28940F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:5CEB4E* ID_OUI_FROM_DATABASE=R. STAHL HMI Systems GmbH OUI:B8DAF7* ID_OUI_FROM_DATABASE=Advanced Photonics, Inc. OUI:2C36A0* ID_OUI_FROM_DATABASE=Capisco Limited OUI:B06CBF* ID_OUI_FROM_DATABASE=3ality Digital Systems GmbH OUI:20AA4B* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:080D84* ID_OUI_FROM_DATABASE=GECO, Inc. OUI:88E712* ID_OUI_FROM_DATABASE=Whirlpool Corporation OUI:644BF0* ID_OUI_FROM_DATABASE=CalDigit, Inc OUI:2838CF* ID_OUI_FROM_DATABASE=Gen2wave OUI:50FC30* ID_OUI_FROM_DATABASE=Treehouse Labs OUI:70704C* ID_OUI_FROM_DATABASE=Purple Communications, Inc OUI:F47ACC* ID_OUI_FROM_DATABASE=SolidFire, Inc. OUI:F8D3A9* ID_OUI_FROM_DATABASE=AXAN Networks OUI:5CD4AB* ID_OUI_FROM_DATABASE=Zektor OUI:F8462D* ID_OUI_FROM_DATABASE=SYNTEC Incorporation OUI:58677F* ID_OUI_FROM_DATABASE=Clare Controls Inc. OUI:CCA374* ID_OUI_FROM_DATABASE=Guangdong Guanglian Electronic Technology Co.Ltd OUI:50F61A* ID_OUI_FROM_DATABASE=Kunshan JADE Technologies co., Ltd. OUI:941D1C* ID_OUI_FROM_DATABASE=TLab West Systems AB OUI:40667A* ID_OUI_FROM_DATABASE=mediola - connected living AG OUI:64808B* ID_OUI_FROM_DATABASE=VG Controls, Inc. OUI:7C6B52* ID_OUI_FROM_DATABASE=Tigaro Wireless OUI:48C1AC* ID_OUI_FROM_DATABASE=PLANTRONICS, INC. OUI:D826B9* ID_OUI_FROM_DATABASE=Guangdong Coagent Electronics S &T Co., Ltd. OUI:24BC82* ID_OUI_FROM_DATABASE=Dali Wireless, Inc. OUI:F80CF3* ID_OUI_FROM_DATABASE=LG Electronics OUI:64C5AA* ID_OUI_FROM_DATABASE=South African Broadcasting Corporation OUI:64ED62* ID_OUI_FROM_DATABASE=WOORI SYSTEMS Co., Ltd OUI:C4237A* ID_OUI_FROM_DATABASE=WhizNets Inc. OUI:8430E5* ID_OUI_FROM_DATABASE=SkyHawke Technologies, LLC OUI:046D42* ID_OUI_FROM_DATABASE=Bryston Ltd. OUI:50CCF8* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics OUI:D0CF5E* ID_OUI_FROM_DATABASE=Energy Micro AS OUI:644D70* ID_OUI_FROM_DATABASE=dSPACE GmbH OUI:807693* ID_OUI_FROM_DATABASE=Newag SA OUI:2C002C* ID_OUI_FROM_DATABASE=UNOWHY OUI:0481AE* ID_OUI_FROM_DATABASE=Clack Corporation OUI:C09132* ID_OUI_FROM_DATABASE=Patriot Memory OUI:AC81F3* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:94C6EB* ID_OUI_FROM_DATABASE=NOVA electronics, Inc. OUI:10F9EE* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:80971B* ID_OUI_FROM_DATABASE=Altenergy Power System,Inc. OUI:1071F9* ID_OUI_FROM_DATABASE=Cloud Telecomputers, LLC OUI:B8B42E* ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co,Ltd.ShenZhen OUI:A84041* ID_OUI_FROM_DATABASE=Dragino Technology Co., Limited OUI:DCF05D* ID_OUI_FROM_DATABASE=Letta Teknoloji OUI:D05A0F* ID_OUI_FROM_DATABASE=I-BT DIGITAL CO.,LTD OUI:FC2E2D* ID_OUI_FROM_DATABASE=Lorom Industrial Co.LTD. OUI:E84E06* ID_OUI_FROM_DATABASE=EDUP INTERNATIONAL (HK) CO., LTD OUI:B4C799* ID_OUI_FROM_DATABASE=Zebra Technologies Inc OUI:70B921* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:C47B2F* ID_OUI_FROM_DATABASE=Beijing JoinHope Image Technology Ltd. OUI:18F650* ID_OUI_FROM_DATABASE=Multimedia Pacific Limited OUI:38DE60* ID_OUI_FROM_DATABASE=Mohlenhoff GmbH OUI:2839E7* ID_OUI_FROM_DATABASE=Preceno Technology Pte.Ltd. OUI:28D997* ID_OUI_FROM_DATABASE=Yuduan Mobile Co., Ltd. OUI:886B76* ID_OUI_FROM_DATABASE=CHINA HOPEFUL GROUP HOPEFUL ELECTRIC CO.,LTD OUI:A0CF5B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:18C451* ID_OUI_FROM_DATABASE=Tucson Embedded Systems OUI:582EFE* ID_OUI_FROM_DATABASE=Lighting Science Group OUI:D4507A* ID_OUI_FROM_DATABASE=CEIVA Logic, Inc OUI:184617* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:9CC7D1* ID_OUI_FROM_DATABASE=SHARP Corporation OUI:AC9CE4* ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd OUI:00B9F6* ID_OUI_FROM_DATABASE=Shenzhen Super Rich Electronics Co.,Ltd OUI:9C5C8D* ID_OUI_FROM_DATABASE=FIREMAX INDÚSTRIA E COMÉRCIO DE PRODUTOS ELETRÔNICOS LTDA OUI:E01E07* ID_OUI_FROM_DATABASE=Anite Telecoms US. Inc OUI:64D989* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:44D3CA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:24DAB6* ID_OUI_FROM_DATABASE=Sistemas de Gestión Energética S.A. de C.V OUI:B8F5E7* ID_OUI_FROM_DATABASE=WayTools, LLC OUI:980C82* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics OUI:148A70* ID_OUI_FROM_DATABASE=ADS GmbH OUI:FC0012* ID_OUI_FROM_DATABASE=Toshiba Samsung Storage Technolgoy Korea Corporation OUI:F44450* ID_OUI_FROM_DATABASE=BND Co., Ltd. OUI:644346* ID_OUI_FROM_DATABASE=GuangDong Quick Network Computer CO.,LTD OUI:FCE892* ID_OUI_FROM_DATABASE=Hangzhou Lancable Technology Co.,Ltd OUI:FC1794* ID_OUI_FROM_DATABASE=InterCreative Co., Ltd OUI:181420* ID_OUI_FROM_DATABASE=TEB SAS OUI:D03110* ID_OUI_FROM_DATABASE=Ingenic Semiconductor Co.,Ltd OUI:48C862* ID_OUI_FROM_DATABASE=Simo Wireless,Inc. OUI:3C26D5* ID_OUI_FROM_DATABASE=Sotera Wireless OUI:704AAE* ID_OUI_FROM_DATABASE=Xstream Flow (Pty) Ltd OUI:9C934E* ID_OUI_FROM_DATABASE=Xerox Corporation OUI:9439E5* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:7CDD20* ID_OUI_FROM_DATABASE=IOXOS Technologies S.A. OUI:A0E9DB* ID_OUI_FROM_DATABASE=Ningbo FreeWings Technologies Co.,Ltd OUI:9C7BD2* ID_OUI_FROM_DATABASE=NEOLAB Convergence OUI:900D66* ID_OUI_FROM_DATABASE=Digimore Electronics Co., Ltd OUI:BC35E5* ID_OUI_FROM_DATABASE=Hydro Systems Company OUI:283410* ID_OUI_FROM_DATABASE=Enigma Diagnostics Limited OUI:28CCFF* ID_OUI_FROM_DATABASE=Corporacion Empresarial Altra SL OUI:14B73D* ID_OUI_FROM_DATABASE=ARCHEAN Technologies OUI:A433D1* ID_OUI_FROM_DATABASE=Fibrlink Communications Co.,Ltd. OUI:84DE3D* ID_OUI_FROM_DATABASE=Crystal Vision Ltd OUI:F87B8C* ID_OUI_FROM_DATABASE=Amped Wireless OUI:44D2CA* ID_OUI_FROM_DATABASE=Anvia TV Oy OUI:4C1A3A* ID_OUI_FROM_DATABASE=PRIMA Research And Production Enterprise Ltd. OUI:AC0613* ID_OUI_FROM_DATABASE=Senselogix Ltd OUI:B4AA4D* ID_OUI_FROM_DATABASE=Ensequence, Inc. OUI:040A83* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:B42A39* ID_OUI_FROM_DATABASE=ORBIT MERRET, spol. s r. o. OUI:B80B9D* ID_OUI_FROM_DATABASE=ROPEX Industrie-Elektronik GmbH OUI:18AEBB* ID_OUI_FROM_DATABASE=Siemens Convergence Creators GmbH&Co.KG OUI:3891FB* ID_OUI_FROM_DATABASE=Xenox Holding BV OUI:50FAAB* ID_OUI_FROM_DATABASE=L-tek d.o.o. OUI:A8E018* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:44AAE8* ID_OUI_FROM_DATABASE=Nanotec Electronic GmbH & Co. KG OUI:D8DF0D* ID_OUI_FROM_DATABASE=beroNet GmbH OUI:D8C068* ID_OUI_FROM_DATABASE=Netgenetech.co.,ltd. OUI:3C9157* ID_OUI_FROM_DATABASE=Hangzhou Yulong Conmunication Co.,Ltd OUI:50E549* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:A8FCB7* ID_OUI_FROM_DATABASE=Consolidated Resource Imaging OUI:6400F1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:04C5A4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E4DD79* ID_OUI_FROM_DATABASE=En-Vision America, Inc. OUI:60190C* ID_OUI_FROM_DATABASE=RRAMAC OUI:34A709* ID_OUI_FROM_DATABASE=Trevil srl OUI:F80332* ID_OUI_FROM_DATABASE=Khomp OUI:C40F09* ID_OUI_FROM_DATABASE=Hermes electronic GmbH OUI:908D1D* ID_OUI_FROM_DATABASE=GH Technologies OUI:CCB55A* ID_OUI_FROM_DATABASE=Fraunhofer ITWM OUI:587521* ID_OUI_FROM_DATABASE=CJSC RTSoft OUI:948FEE* ID_OUI_FROM_DATABASE=Hughes Telematics, Inc. OUI:E8C320* ID_OUI_FROM_DATABASE=Austco Communication Systems Pty Ltd OUI:D8973B* ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies OUI:0C6E4F* ID_OUI_FROM_DATABASE=PrimeVOLT Co., Ltd. OUI:685B36* ID_OUI_FROM_DATABASE=POWERTECH INDUSTRIAL CO., LTD. OUI:983000* ID_OUI_FROM_DATABASE=Beijing KEMACOM Technologies Co., Ltd. OUI:F81D93* ID_OUI_FROM_DATABASE=Longdhua(Beijing) Controls Technology Co.,Ltd OUI:CC5D4E* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:D0EB9E* ID_OUI_FROM_DATABASE=Seowoo Inc. OUI:BC99BC* ID_OUI_FROM_DATABASE=FonSee Technology Inc. OUI:986022* ID_OUI_FROM_DATABASE=EMW Co., Ltd. OUI:80B32A* ID_OUI_FROM_DATABASE=Alstom Grid OUI:803457* ID_OUI_FROM_DATABASE=OT Systems Limited OUI:B83D4E* ID_OUI_FROM_DATABASE=Shenzhen Cultraview Digital Technology Co.,Ltd Shanghai Branch OUI:3CA72B* ID_OUI_FROM_DATABASE=MRV Communications (Networks) LTD OUI:EC55F9* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:F4D9FB* ID_OUI_FROM_DATABASE=Samsung Electronics CO., LTD OUI:584C19* ID_OUI_FROM_DATABASE=Chongqing Guohong Technology Development Company Limited OUI:8C5FDF* ID_OUI_FROM_DATABASE=Beijing Railway Signal Factory OUI:586D8F* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:14C21D* ID_OUI_FROM_DATABASE=Sabtech Industries OUI:74B00C* ID_OUI_FROM_DATABASE=Network Video Technologies, Inc OUI:C88439* ID_OUI_FROM_DATABASE=Sunrise Technologies OUI:44E4D9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0054AF* ID_OUI_FROM_DATABASE=Continental Automotive Systems Inc. OUI:EC7D9D* ID_OUI_FROM_DATABASE=MEI OUI:9C95F8* ID_OUI_FROM_DATABASE=SmartDoor Systems, LLC OUI:D075BE* ID_OUI_FROM_DATABASE=Reno A&E OUI:7C6C39* ID_OUI_FROM_DATABASE=PIXSYS SRL OUI:9C5D95* ID_OUI_FROM_DATABASE=VTC Electronics Corp. OUI:0CF3EE* ID_OUI_FROM_DATABASE=EM Microelectronic OUI:F0C27C* ID_OUI_FROM_DATABASE=Mianyang Netop Telecom Equipment Co.,Ltd. OUI:008D4E* ID_OUI_FROM_DATABASE=CJSC NII STT OUI:10C586* ID_OUI_FROM_DATABASE=BIO SOUND LAB CO., LTD. OUI:E8BA70* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:6473E2* ID_OUI_FROM_DATABASE=Arbiter Systems, Inc. OUI:00A1DE* ID_OUI_FROM_DATABASE=ShenZhen ShiHua Technology CO.,LTD OUI:04E1C8* ID_OUI_FROM_DATABASE=IMS Soluções em Energia Ltda. OUI:DC05ED* ID_OUI_FROM_DATABASE=Nabtesco Corporation OUI:FC8329* ID_OUI_FROM_DATABASE=Trei technics OUI:94E848* ID_OUI_FROM_DATABASE=FYLDE MICRO LTD OUI:AC5E8C* ID_OUI_FROM_DATABASE=Utillink OUI:CCF3A5* ID_OUI_FROM_DATABASE=Chi Mei Communication Systems, Inc OUI:C4242E* ID_OUI_FROM_DATABASE=Galvanic Applied Sciences Inc OUI:549B12* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:CC7EE7* ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company OUI:58E476* ID_OUI_FROM_DATABASE=CENTRON COMMUNICATIONS TECHNOLOGIES FUJIAN CO.,LTD OUI:B435F7* ID_OUI_FROM_DATABASE=Zhejiang Pearmain Electronics Co.ltd. OUI:346F92* ID_OUI_FROM_DATABASE=White Rodgers Division OUI:8CDB25* ID_OUI_FROM_DATABASE=ESG Solutions OUI:641A22* ID_OUI_FROM_DATABASE=Heliospectra AB OUI:BC20BA* ID_OUI_FROM_DATABASE=Inspur (Shandong) Electronic Information Co., Ltd OUI:249442* ID_OUI_FROM_DATABASE=OPEN ROAD SOLUTIONS , INC. OUI:E0F379* ID_OUI_FROM_DATABASE=Vaddio OUI:B09AE2* ID_OUI_FROM_DATABASE=STEMMER IMAGING GmbH OUI:E441E6* ID_OUI_FROM_DATABASE=Ottec Technology GmbH OUI:10E2D5* ID_OUI_FROM_DATABASE=Qi Hardware Inc. OUI:7CDA84* ID_OUI_FROM_DATABASE=Dongnian Networks Inc. OUI:A036FA* ID_OUI_FROM_DATABASE=Ettus Research LLC OUI:EC836C* ID_OUI_FROM_DATABASE=RM Tech Co., Ltd. OUI:BC71C1* ID_OUI_FROM_DATABASE=XTrillion, Inc. OUI:0C469D* ID_OUI_FROM_DATABASE=MS Sedco OUI:E0E8E8* ID_OUI_FROM_DATABASE=Olive Telecommunication Pvt. Ltd OUI:0C3C65* ID_OUI_FROM_DATABASE=Dome Imaging Inc OUI:40B2C8* ID_OUI_FROM_DATABASE=Nortel Networks OUI:486B91* ID_OUI_FROM_DATABASE=Fleetwood Group Inc. OUI:F43814* ID_OUI_FROM_DATABASE=Shanghai Howell Electronic Co.,Ltd OUI:20AA25* ID_OUI_FROM_DATABASE=IP-NET LLC OUI:ECBBAE* ID_OUI_FROM_DATABASE=Digivoice Tecnologia em Eletronica Ltda OUI:DC2008* ID_OUI_FROM_DATABASE=ASD Electronics Ltd OUI:088DC8* ID_OUI_FROM_DATABASE=Ryowa Electronics Co.,Ltd OUI:D491AF* ID_OUI_FROM_DATABASE=Electroacustica General Iberica, S.A. OUI:CCF67A* ID_OUI_FROM_DATABASE=Ayecka Communication Systems LTD OUI:00BB8E* ID_OUI_FROM_DATABASE=HME Co., Ltd. OUI:C0A26D* ID_OUI_FROM_DATABASE=Abbott Point of Care OUI:205B2A* ID_OUI_FROM_DATABASE=Private OUI:18B430* ID_OUI_FROM_DATABASE=Nest Labs Inc. OUI:F8769B* ID_OUI_FROM_DATABASE=Neopis Co., Ltd. OUI:08E672* ID_OUI_FROM_DATABASE=JEBSEE ELECTRONICS CO.,LTD. OUI:D41296* ID_OUI_FROM_DATABASE=Anobit Technologies Ltd. OUI:B8FF6F* ID_OUI_FROM_DATABASE=Shanghai Typrotech Technology Co.Ltd OUI:DC9C52* ID_OUI_FROM_DATABASE=Sapphire Technology Limited. OUI:68122D* ID_OUI_FROM_DATABASE=Special Instrument Development Co., Ltd. OUI:649B24* ID_OUI_FROM_DATABASE=V Technology Co., Ltd. OUI:0475F5* ID_OUI_FROM_DATABASE=CSST OUI:10A13B* ID_OUI_FROM_DATABASE=FUJIKURA RUBBER LTD. OUI:F4E142* ID_OUI_FROM_DATABASE=Delta Elektronika BV OUI:F00248* ID_OUI_FROM_DATABASE=SmarteBuilding OUI:2CDD0C* ID_OUI_FROM_DATABASE=Discovergy GmbH OUI:CCD811* ID_OUI_FROM_DATABASE=Aiconn Technology Corporation OUI:78D004* ID_OUI_FROM_DATABASE=Neousys Technology Inc. OUI:78A051* ID_OUI_FROM_DATABASE=iiNet Labs Pty Ltd OUI:58A76F* ID_OUI_FROM_DATABASE=iD corporation OUI:44599F* ID_OUI_FROM_DATABASE=Criticare Systems, Inc OUI:3C2F3A* ID_OUI_FROM_DATABASE=SFORZATO Corp. OUI:C0C520* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:6083B2* ID_OUI_FROM_DATABASE=GkWare e.K. OUI:80D019* ID_OUI_FROM_DATABASE=Embed, Inc OUI:ECE90B* ID_OUI_FROM_DATABASE=SISTEMA SOLUCOES ELETRONICAS LTDA - EASYTECH OUI:A08C9B* ID_OUI_FROM_DATABASE=Xtreme Technologies Corp OUI:607688* ID_OUI_FROM_DATABASE=Velodyne OUI:980EE4* ID_OUI_FROM_DATABASE=Private OUI:E828D5* ID_OUI_FROM_DATABASE=Cots Technology OUI:08D5C0* ID_OUI_FROM_DATABASE=Seers Technology Co., Ltd OUI:8CB64F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:6C33A9* ID_OUI_FROM_DATABASE=Magicjack LP OUI:08B7EC* ID_OUI_FROM_DATABASE=Wireless Seismic OUI:30142D* ID_OUI_FROM_DATABASE=Piciorgros GmbH OUI:942053* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:D49C8E* ID_OUI_FROM_DATABASE=University of FUKUI OUI:3C8BFE* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:2CB0DF* ID_OUI_FROM_DATABASE=Soliton Technologies Pvt Ltd OUI:5CF3FC* ID_OUI_FROM_DATABASE=IBM Corp OUI:D01CBB* ID_OUI_FROM_DATABASE=Beijing Ctimes Digital Technology Co., Ltd. OUI:9481A4* ID_OUI_FROM_DATABASE=Azuray Technologies OUI:BCE09D* ID_OUI_FROM_DATABASE=Eoslink OUI:D0A311* ID_OUI_FROM_DATABASE=Neuberger Gebäudeautomation GmbH OUI:3C5A37* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:EC9233* ID_OUI_FROM_DATABASE=Eddyfi NDT Inc OUI:0C8D98* ID_OUI_FROM_DATABASE=TOP EIGHT IND CORP OUI:30493B* ID_OUI_FROM_DATABASE=Nanjing Z-Com Wireless Co.,Ltd OUI:785712* ID_OUI_FROM_DATABASE=Mobile Integration Workgroup OUI:380A0A* ID_OUI_FROM_DATABASE=Sky-City Communication and Electronics Limited Company OUI:38521A* ID_OUI_FROM_DATABASE=Alcatel-Lucent 7705 OUI:C8A1B6* ID_OUI_FROM_DATABASE=Shenzhen Longway Technologies Co., Ltd OUI:641E81* ID_OUI_FROM_DATABASE=Dowslake Microsystems OUI:88ACC1* ID_OUI_FROM_DATABASE=Generiton Co., Ltd. OUI:700258* ID_OUI_FROM_DATABASE=01DB-METRAVIB OUI:D4E8B2* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:20FDF1* ID_OUI_FROM_DATABASE=3COM EUROPE LTD OUI:389592* ID_OUI_FROM_DATABASE=Beijing Tendyron Corporation OUI:705EAA* ID_OUI_FROM_DATABASE=Action Target, Inc. OUI:141BBD* ID_OUI_FROM_DATABASE=Volex Inc. OUI:78C6BB* ID_OUI_FROM_DATABASE=Innovasic, Inc. OUI:DC4EDE* ID_OUI_FROM_DATABASE=SHINYEI TECHNOLOGY CO., LTD. OUI:888B5D* ID_OUI_FROM_DATABASE=Storage Appliance Corporation OUI:F0F842* ID_OUI_FROM_DATABASE=KEEBOX, Inc. OUI:78A714* ID_OUI_FROM_DATABASE=Amphenol OUI:F0DEF1* ID_OUI_FROM_DATABASE=Wistron InfoComm (Kunshan)Co OUI:F450EB* ID_OUI_FROM_DATABASE=Telechips Inc OUI:988EDD* ID_OUI_FROM_DATABASE=TE Connectivity Limerick OUI:98FC11* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:A40CC3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:34E0D7* ID_OUI_FROM_DATABASE=DONGGUAN QISHENG ELECTRONICS INDUSTRIAL CO., LTD OUI:40520D* ID_OUI_FROM_DATABASE=Pico Technology OUI:8C7CB5* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:543131* ID_OUI_FROM_DATABASE=Raster Vision Ltd OUI:90E0F0* ID_OUI_FROM_DATABASE=IEEE 1722a Working Group OUI:1C6F65* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:F0AD4E* ID_OUI_FROM_DATABASE=Globalscale Technologies, Inc. OUI:903D5A* ID_OUI_FROM_DATABASE=Shenzhen Wision Technology Holding Limited OUI:609AA4* ID_OUI_FROM_DATABASE=GVI SECURITY INC. OUI:F0ED1E* ID_OUI_FROM_DATABASE=Bilkon Bilgisayar Kontrollu Cih. Im.Ltd. OUI:206A8A* ID_OUI_FROM_DATABASE=Wistron InfoComm Manufacturing(Kunshan)Co.,Ltd. OUI:F80F41* ID_OUI_FROM_DATABASE=Wistron InfoComm(ZhongShan) Corporation OUI:1CDF0F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:34DF2A* ID_OUI_FROM_DATABASE=Fujikon Industrial Co.,Limited OUI:C88447* ID_OUI_FROM_DATABASE=Beautiful Enterprise Co., Ltd OUI:C88B47* ID_OUI_FROM_DATABASE=Nolangroup S.P.A con Socio Unico OUI:24BA30* ID_OUI_FROM_DATABASE=Technical Consumer Products, Inc. OUI:74D675* ID_OUI_FROM_DATABASE=WYMA Tecnologia OUI:D43D67* ID_OUI_FROM_DATABASE=Carma Industries Inc. OUI:78818F* ID_OUI_FROM_DATABASE=Server Racks Australia Pty Ltd OUI:E0589E* ID_OUI_FROM_DATABASE=Laerdal Medical OUI:44D63D* ID_OUI_FROM_DATABASE=Talari Networks OUI:58FD20* ID_OUI_FROM_DATABASE=Bravida Sakerhet AB OUI:9835B8* ID_OUI_FROM_DATABASE=Assembled Products Corporation OUI:240B2A* ID_OUI_FROM_DATABASE=Viettel Group OUI:68E41F* ID_OUI_FROM_DATABASE=Unglaube Identech GmbH OUI:84F64C* ID_OUI_FROM_DATABASE=Cross Point BV OUI:180C77* ID_OUI_FROM_DATABASE=Westinghouse Electric Company, LLC OUI:ACA016* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:78E400* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:905446* ID_OUI_FROM_DATABASE=TES ELECTRONIC SOLUTIONS OUI:DC7B94* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:68234B* ID_OUI_FROM_DATABASE=Nihon Dengyo Kousaku OUI:18422F* ID_OUI_FROM_DATABASE=Alcatel Lucent OUI:A4BE61* ID_OUI_FROM_DATABASE=EutroVision System, Inc. OUI:E06290* ID_OUI_FROM_DATABASE=Jinan Jovision Science & Technology Co., Ltd. OUI:68DB96* ID_OUI_FROM_DATABASE=OPWILL Technologies CO .,LTD OUI:00F860* ID_OUI_FROM_DATABASE=PT. Panggung Electric Citrabuana OUI:FCEDB9* ID_OUI_FROM_DATABASE=Arrayent OUI:44ED57* ID_OUI_FROM_DATABASE=Longicorn, inc. OUI:90513F* ID_OUI_FROM_DATABASE=Elettronica Santerno SpA OUI:7CA29B* ID_OUI_FROM_DATABASE=D.SignT GmbH & Co. KG OUI:34AAEE* ID_OUI_FROM_DATABASE=Mikrovisatos Servisas UAB OUI:7866AE* ID_OUI_FROM_DATABASE=ZTEC Instruments, Inc. OUI:24AF4A* ID_OUI_FROM_DATABASE=Alcatel-Lucent-IPD OUI:00BD27* ID_OUI_FROM_DATABASE=Exar Corp. OUI:C8A729* ID_OUI_FROM_DATABASE=SYStronics Co., Ltd. OUI:6C9CE9* ID_OUI_FROM_DATABASE=Nimble Storage OUI:7812B8* ID_OUI_FROM_DATABASE=ORANTEK LIMITED OUI:F0B6EB* ID_OUI_FROM_DATABASE=Poslab Technology Co., Ltd. OUI:FCCCE4* ID_OUI_FROM_DATABASE=Ascon Ltd. OUI:34862A* ID_OUI_FROM_DATABASE=Heinz Lackmann GmbH & Co KG OUI:842141* ID_OUI_FROM_DATABASE=Shenzhen Ginwave Technologies Ltd. OUI:B4ED54* ID_OUI_FROM_DATABASE=Wohler Technologies OUI:544249* ID_OUI_FROM_DATABASE=Sony Corporation OUI:24DBAD* ID_OUI_FROM_DATABASE=ShopperTrak RCT Corporation OUI:CC69B0* ID_OUI_FROM_DATABASE=Global Traffic Technologies, LLC OUI:2872C5* ID_OUI_FROM_DATABASE=Smartmatic Corp OUI:E4AD7D* ID_OUI_FROM_DATABASE=SCL Elements OUI:40D40E* ID_OUI_FROM_DATABASE=Biodata Ltd OUI:7C051E* ID_OUI_FROM_DATABASE=RAFAEL LTD. OUI:58570D* ID_OUI_FROM_DATABASE=Danfoss Solar Inverters OUI:E47CF9* ID_OUI_FROM_DATABASE=Samsung Electronics Co., LTD OUI:0C826A* ID_OUI_FROM_DATABASE=Wuhan Huagong Genuine Optics Technology Co., Ltd OUI:5C0E8B* ID_OUI_FROM_DATABASE=Zebra Technologies Inc OUI:38C7BA* ID_OUI_FROM_DATABASE=CS Services Co.,Ltd. OUI:70D57E* ID_OUI_FROM_DATABASE=Scalar Corporation OUI:24A937* ID_OUI_FROM_DATABASE=PURE Storage OUI:348302* ID_OUI_FROM_DATABASE=iFORCOM Co., Ltd OUI:949C55* ID_OUI_FROM_DATABASE=Alta Data Technologies OUI:70D5E7* ID_OUI_FROM_DATABASE=Wellcore Corporation OUI:3CF72A* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:FCE192* ID_OUI_FROM_DATABASE=Sichuan Jinwangtong Electronic Science&Technology Co,.Ltd OUI:F8912A* ID_OUI_FROM_DATABASE=GLP German Light Products GmbH OUI:E02630* ID_OUI_FROM_DATABASE=Intrigue Technologies, Inc. OUI:8C9236* ID_OUI_FROM_DATABASE=Aus.Linx Technology Co., Ltd. OUI:F445ED* ID_OUI_FROM_DATABASE=Portable Innovation Technology Ltd. OUI:6C32DE* ID_OUI_FROM_DATABASE=Indieon Technologies Pvt. Ltd. OUI:FCCF62* ID_OUI_FROM_DATABASE=IBM Corp OUI:D8E72B* ID_OUI_FROM_DATABASE=NetScout Systems, Inc. OUI:B8A3E0* ID_OUI_FROM_DATABASE=BenRui Technology Co.,Ltd OUI:B8F732* ID_OUI_FROM_DATABASE=Aryaka Networks Inc OUI:0CD502* ID_OUI_FROM_DATABASE=Westell OUI:70828E* ID_OUI_FROM_DATABASE=OleumTech Corporation OUI:502A7E* ID_OUI_FROM_DATABASE=Smart electronic GmbH OUI:F0264C* ID_OUI_FROM_DATABASE=Dr. Sigrist AG OUI:3C1CBE* ID_OUI_FROM_DATABASE=JADAK LLC OUI:506313* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:A8995C* ID_OUI_FROM_DATABASE=aizo ag OUI:4012E4* ID_OUI_FROM_DATABASE=Compass-EOS OUI:F8DC7A* ID_OUI_FROM_DATABASE=Variscite LTD OUI:EC4476* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:9CEBE8* ID_OUI_FROM_DATABASE=BizLink (Kunshan) Co.,Ltd OUI:A01859* ID_OUI_FROM_DATABASE=Shenzhen Yidashi Electronics Co Ltd OUI:042234* ID_OUI_FROM_DATABASE=Wireless Standard Extensions OUI:B09074* ID_OUI_FROM_DATABASE=Fulan Electronics Limited OUI:2CA835* ID_OUI_FROM_DATABASE=RIM OUI:3CE5A6* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Ltd. OUI:94F692* ID_OUI_FROM_DATABASE=Geminico co.,Ltd. OUI:8C736E* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:30EFD1* ID_OUI_FROM_DATABASE=Alstom Strongwish (Shenzhen) Co., Ltd. OUI:7C2CF3* ID_OUI_FROM_DATABASE=Secure Electrans Ltd OUI:304174* ID_OUI_FROM_DATABASE=ALTEC LANSING LLC OUI:7830E1* ID_OUI_FROM_DATABASE=UltraClenz, LLC OUI:FCFBFB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:1C129D* ID_OUI_FROM_DATABASE=IEEE PES PSRC/SUB OUI:B40832* ID_OUI_FROM_DATABASE=TC Communications OUI:B42CBE* ID_OUI_FROM_DATABASE=Direct Payment Solutions Limited OUI:F47626* ID_OUI_FROM_DATABASE=Viltechmeda UAB OUI:003A9C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E8E776* ID_OUI_FROM_DATABASE=Shenzhen Kootion Technology Co., Ltd OUI:702F97* ID_OUI_FROM_DATABASE=Aava Mobile Oy OUI:9018AE* ID_OUI_FROM_DATABASE=Shanghai Meridian Technologies, Co. Ltd. OUI:0494A1* ID_OUI_FROM_DATABASE=CATCH THE WIND INC OUI:2C3427* ID_OUI_FROM_DATABASE=ERCO & GENER OUI:389F83* ID_OUI_FROM_DATABASE=OTN Systems N.V. OUI:8C541D* ID_OUI_FROM_DATABASE=LGE OUI:601283* ID_OUI_FROM_DATABASE=Soluciones Tecnologicas para la Salud y el Bienestar SA OUI:003A9D* ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. OUI:C835B8* ID_OUI_FROM_DATABASE=Ericsson, EAB/RWI/K OUI:243C20* ID_OUI_FROM_DATABASE=Dynamode Group OUI:E09153* ID_OUI_FROM_DATABASE=XAVi Technologies Corp. OUI:CC0080* ID_OUI_FROM_DATABASE=BETTINI SRL OUI:644BC3* ID_OUI_FROM_DATABASE=Shanghai WOASiS Telecommunications Ltd., Co. OUI:0CE709* ID_OUI_FROM_DATABASE=Fox Crypto B.V. OUI:002720* ID_OUI_FROM_DATABASE=NEW-SOL COM OUI:00271C* ID_OUI_FROM_DATABASE=MERCURY CORPORATION OUI:002712* ID_OUI_FROM_DATABASE=MaxVision LLC OUI:00270F* ID_OUI_FROM_DATABASE=Envisionnovation Inc OUI:002703* ID_OUI_FROM_DATABASE=Testech Electronics Pte Ltd OUI:88ED1C* ID_OUI_FROM_DATABASE=Cudo Communication Co., Ltd. OUI:B05B1F* ID_OUI_FROM_DATABASE=THERMO FISHER SCIENTIFIC S.P.A. OUI:404A03* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:743256* ID_OUI_FROM_DATABASE=NT-ware Systemprg GmbH OUI:003AAF* ID_OUI_FROM_DATABASE=BlueBit Ltd. OUI:C0BAE6* ID_OUI_FROM_DATABASE=Application Solutions (Electronics and Vision) Ltd OUI:20BFDB* ID_OUI_FROM_DATABASE=DVL OUI:C87E75* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:889821* ID_OUI_FROM_DATABASE=TERAON OUI:0026FD* ID_OUI_FROM_DATABASE=Interactive Intelligence OUI:0026F6* ID_OUI_FROM_DATABASE=Military Communication Institute OUI:0026F0* ID_OUI_FROM_DATABASE=cTrixs International GmbH. OUI:0026EA* ID_OUI_FROM_DATABASE=Cheerchip Electronic Technology (ShangHai) Co., Ltd. OUI:0026E3* ID_OUI_FROM_DATABASE=DTI OUI:0026DD* ID_OUI_FROM_DATABASE=Fival Science & Technology Co.,Ltd. OUI:0026DE* ID_OUI_FROM_DATABASE=FDI MATELEC OUI:0026D7* ID_OUI_FROM_DATABASE=KM Electornic Technology Co., Ltd. OUI:0026D1* ID_OUI_FROM_DATABASE=S Squared Innovations Inc. OUI:54B620* ID_OUI_FROM_DATABASE=SUHDOL E&C Co.Ltd. OUI:C4AAA1* ID_OUI_FROM_DATABASE=SUMMIT DEVELOPMENT, spol.s r.o. OUI:78C40E* ID_OUI_FROM_DATABASE=H&D Wireless OUI:9C5B96* ID_OUI_FROM_DATABASE=NMR Corporation OUI:E4FFDD* ID_OUI_FROM_DATABASE=ELECTRON INDIA OUI:6C8CDB* ID_OUI_FROM_DATABASE=Otus Technologies Ltd OUI:B4417A* ID_OUI_FROM_DATABASE=ShenZhen Gongjin Electronics Co.,Ltd OUI:401597* ID_OUI_FROM_DATABASE=Protect America, Inc. OUI:F852DF* ID_OUI_FROM_DATABASE=VNL Europe AB OUI:1CF061* ID_OUI_FROM_DATABASE=SCAPS GmbH OUI:A893E6* ID_OUI_FROM_DATABASE=JIANGXI JINGGANGSHAN CKING COMMUNICATION TECHNOLOGY CO.,LTD OUI:7825AD* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRONICS CO., LTD. OUI:0026CB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0026C4* ID_OUI_FROM_DATABASE=Cadmos microsystems S.r.l. OUI:0026BE* ID_OUI_FROM_DATABASE=Schoonderbeek Elektronica Systemen B.V. OUI:0026B2* ID_OUI_FROM_DATABASE=Setrix GmbH OUI:0026AC* ID_OUI_FROM_DATABASE=Shanghai LUSTER Teraband photonic Co., Ltd. OUI:0026B1* ID_OUI_FROM_DATABASE=Navis Auto Motive Systems, Inc. OUI:0026A8* ID_OUI_FROM_DATABASE=DAEHAP HYPER-TECH OUI:0026A7* ID_OUI_FROM_DATABASE=CONNECT SRL OUI:60391F* ID_OUI_FROM_DATABASE=ABB Ltd OUI:A07332* ID_OUI_FROM_DATABASE=Cashmaster International Limited OUI:7C7BE4* ID_OUI_FROM_DATABASE=Z'SEDAI KENKYUSHO CORPORATION OUI:40EF4C* ID_OUI_FROM_DATABASE=Fihonest communication co.,Ltd OUI:24CF21* ID_OUI_FROM_DATABASE=Shenzhen State Micro Technology Co., Ltd OUI:04B3B6* ID_OUI_FROM_DATABASE=Seamap (UK) Ltd OUI:10BAA5* ID_OUI_FROM_DATABASE=GANA I&C CO., LTD OUI:586ED6* ID_OUI_FROM_DATABASE=Private OUI:CC5076* ID_OUI_FROM_DATABASE=Ocom Communications, Inc. OUI:705812* ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company OUI:002648* ID_OUI_FROM_DATABASE=Emitech Corp. OUI:002644* ID_OUI_FROM_DATABASE=Thomson Telecom Belgium OUI:00263E* ID_OUI_FROM_DATABASE=Trapeze Networks OUI:002638* ID_OUI_FROM_DATABASE=Xia Men Joyatech Co., Ltd. OUI:00263D* ID_OUI_FROM_DATABASE=MIA Corporation OUI:002631* ID_OUI_FROM_DATABASE=COMMTACT LTD OUI:00262B* ID_OUI_FROM_DATABASE=Wongs Electronics Co. Ltd. OUI:002625* ID_OUI_FROM_DATABASE=MediaSputnik OUI:00261E* ID_OUI_FROM_DATABASE=QINGBANG ELEC(SZ) CO., LTD OUI:002619* ID_OUI_FROM_DATABASE=FRC OUI:0025BA* ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD OUI:0025B5* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0025AE* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:0025A8* ID_OUI_FROM_DATABASE=Kontron (BeiJing) Technology Co.,Ltd OUI:0025A7* ID_OUI_FROM_DATABASE=Comverge, Inc. OUI:0025A2* ID_OUI_FROM_DATABASE=Alta Definicion LINCEO S.L. OUI:002596* ID_OUI_FROM_DATABASE=GIGAVISION srl OUI:00259B* ID_OUI_FROM_DATABASE=Beijing PKUNITY Microsystems Technology Co., Ltd OUI:002595* ID_OUI_FROM_DATABASE=Northwest Signal Supply, Inc OUI:002542* ID_OUI_FROM_DATABASE=Pittasoft OUI:002530* ID_OUI_FROM_DATABASE=Aetas Systems Inc. OUI:002529* ID_OUI_FROM_DATABASE=COMELIT GROUP S.P.A OUI:002522* ID_OUI_FROM_DATABASE=ASRock Incorporation OUI:00251D* ID_OUI_FROM_DATABASE=DSA Encore, LLC OUI:002518* ID_OUI_FROM_DATABASE=Power PLUS Communications AG OUI:002513* ID_OUI_FROM_DATABASE=CXP DIGITAL BV OUI:0026A1* ID_OUI_FROM_DATABASE=Megger OUI:0026A2* ID_OUI_FROM_DATABASE=Instrumentation Technology Systems OUI:00269B* ID_OUI_FROM_DATABASE=SOKRAT Ltd. OUI:002695* ID_OUI_FROM_DATABASE=ZT Group Int'l Inc OUI:00268F* ID_OUI_FROM_DATABASE=MTA SpA OUI:00267C* ID_OUI_FROM_DATABASE=Metz-Werke GmbH & Co KG OUI:00255C* ID_OUI_FROM_DATABASE=NEC Corporation OUI:002550* ID_OUI_FROM_DATABASE=Riverbed Technology OUI:002555* ID_OUI_FROM_DATABASE=Visonic Technologies 1993 Ltd OUI:00254F* ID_OUI_FROM_DATABASE=ELETTROLAB Srl OUI:002549* ID_OUI_FROM_DATABASE=Jeorich Tech. Co.,Ltd. OUI:002538* ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd., Memory Division OUI:002676* ID_OUI_FROM_DATABASE=COMMidt AS OUI:00266F* ID_OUI_FROM_DATABASE=Coordiwise Technology Corp. OUI:002670* ID_OUI_FROM_DATABASE=Cinch Connectors OUI:002663* ID_OUI_FROM_DATABASE=Shenzhen Huitaiwei Tech. Ltd, co. OUI:00265D* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:00264F* ID_OUI_FROM_DATABASE=Krüger &Gothe GmbH OUI:0025E0* ID_OUI_FROM_DATABASE=CeedTec Sdn Bhd OUI:0025DA* ID_OUI_FROM_DATABASE=Secura Key OUI:0025D9* ID_OUI_FROM_DATABASE=DataFab Systems Inc. OUI:0025D4* ID_OUI_FROM_DATABASE=Fortress Technologies OUI:0025CD* ID_OUI_FROM_DATABASE=Skylane Optics OUI:0025C8* ID_OUI_FROM_DATABASE=S-Access GmbH OUI:0025C7* ID_OUI_FROM_DATABASE=altek Corporation OUI:0025C1* ID_OUI_FROM_DATABASE=Nawoo Korea Corp. OUI:002612* ID_OUI_FROM_DATABASE=Space Exploration Technologies OUI:00260B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00260C* ID_OUI_FROM_DATABASE=Dataram OUI:0025FF* ID_OUI_FROM_DATABASE=CreNova Multimedia Co., Ltd OUI:002606* ID_OUI_FROM_DATABASE=RAUMFELD GmbH OUI:0025F9* ID_OUI_FROM_DATABASE=GMK electronic design GmbH OUI:0025F5* ID_OUI_FROM_DATABASE=DVS Korea, Co., Ltd OUI:0025F0* ID_OUI_FROM_DATABASE=Suga Electronics Limited OUI:0025EA* ID_OUI_FROM_DATABASE=Iphion BV OUI:0025E4* ID_OUI_FROM_DATABASE=OMNI-WiFi, LLC OUI:00258F* ID_OUI_FROM_DATABASE=Trident Microsystems, Inc. OUI:00258B* ID_OUI_FROM_DATABASE=Mellanox Technologies Ltd OUI:002585* ID_OUI_FROM_DATABASE=KOKUYO S&T Co., Ltd. OUI:00257B* ID_OUI_FROM_DATABASE=STJ ELECTRONICS PVT LTD OUI:002574* ID_OUI_FROM_DATABASE=KUNIMI MEDIA DEVICE Co., Ltd. OUI:00256F* ID_OUI_FROM_DATABASE=Dantherm Power OUI:002562* ID_OUI_FROM_DATABASE=interbro Co. Ltd. OUI:002561* ID_OUI_FROM_DATABASE=ProCurve Networking by HP OUI:0023F7* ID_OUI_FROM_DATABASE=Private OUI:0023FD* ID_OUI_FROM_DATABASE=AFT Atlas Fahrzeugtechnik GmbH OUI:0023F6* ID_OUI_FROM_DATABASE=Softwell Technology Co., Ltd. OUI:0023EC* ID_OUI_FROM_DATABASE=Algorithmix GmbH OUI:0023E7* ID_OUI_FROM_DATABASE=Hinke A/S OUI:0023E0* ID_OUI_FROM_DATABASE=INO Therapeutics LLC OUI:0024C2* ID_OUI_FROM_DATABASE=Asumo Co.,Ltd. OUI:0024BC* ID_OUI_FROM_DATABASE=HuRob Co.,Ltd OUI:0024B7* ID_OUI_FROM_DATABASE=GridPoint, Inc. OUI:0024AB* ID_OUI_FROM_DATABASE=A7 Engineering, Inc. OUI:0024A6* ID_OUI_FROM_DATABASE=TELESTAR DIGITAL GmbH OUI:00249A* ID_OUI_FROM_DATABASE=Beijing Zhongchuang Telecommunication Test Co., Ltd. OUI:00249F* ID_OUI_FROM_DATABASE=RIM Testing Services OUI:00246D* ID_OUI_FROM_DATABASE=Weinzierl Engineering GmbH OUI:002474* ID_OUI_FROM_DATABASE=Autronica Fire And Securirty OUI:002468* ID_OUI_FROM_DATABASE=Sumavision Technologies Co.,Ltd OUI:002466* ID_OUI_FROM_DATABASE=Unitron nv OUI:002461* ID_OUI_FROM_DATABASE=Shin Wang Tech. OUI:00245C* ID_OUI_FROM_DATABASE=Design-Com Technologies Pty. Ltd. OUI:00244F* ID_OUI_FROM_DATABASE=Asantron Technologies Ltd. OUI:002454* ID_OUI_FROM_DATABASE=Samsung Electronics CO., LTD OUI:002448* ID_OUI_FROM_DATABASE=SpiderCloud Wireless, Inc OUI:00244A* ID_OUI_FROM_DATABASE=Voyant International OUI:002449* ID_OUI_FROM_DATABASE=Shen Zhen Lite Star Electronics Technology Co., Ltd OUI:00250C* ID_OUI_FROM_DATABASE=Enertrac OUI:002505* ID_OUI_FROM_DATABASE=eks Engel GmbH & Co. KG OUI:0024F9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0024F2* ID_OUI_FROM_DATABASE=Uniphone Telecommunication Co., Ltd. OUI:0024ED* ID_OUI_FROM_DATABASE=YT Elec. Co,.Ltd. OUI:0024E6* ID_OUI_FROM_DATABASE=In Motion Technology Inc. OUI:0024E1* ID_OUI_FROM_DATABASE=Convey Computer Corp. OUI:0024DF* ID_OUI_FROM_DATABASE=Digitalbox Europe GmbH OUI:0024DA* ID_OUI_FROM_DATABASE=Innovar Systems Limited OUI:0024CE* ID_OUI_FROM_DATABASE=Exeltech Inc OUI:0024D3* ID_OUI_FROM_DATABASE=QUALICA Inc. OUI:0024C7* ID_OUI_FROM_DATABASE=Mobilarm Ltd OUI:002429* ID_OUI_FROM_DATABASE=MK MASTER INC. OUI:00241C* ID_OUI_FROM_DATABASE=FuGang Electronic (DG) Co.,Ltd OUI:002428* ID_OUI_FROM_DATABASE=EnergyICT OUI:002416* ID_OUI_FROM_DATABASE=Any Use OUI:002410* ID_OUI_FROM_DATABASE=NUETEQ Technology,Inc. OUI:002409* ID_OUI_FROM_DATABASE=The Toro Company OUI:002487* ID_OUI_FROM_DATABASE=Blackboard Inc. OUI:002498* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002485* ID_OUI_FROM_DATABASE=ConteXtream Ltd OUI:002480* ID_OUI_FROM_DATABASE=Meteocontrol GmbH OUI:002479* ID_OUI_FROM_DATABASE=Optec Displays, Inc. OUI:002443* ID_OUI_FROM_DATABASE=Nortel Networks OUI:002439* ID_OUI_FROM_DATABASE=Digital Barriers Advanced Technologies OUI:002432* ID_OUI_FROM_DATABASE=Neostar Technology Co.,LTD OUI:0023DA* ID_OUI_FROM_DATABASE=Industrial Computer Source (Deutschland)GmbH OUI:0023C8* ID_OUI_FROM_DATABASE=TEAM-R OUI:0023C7* ID_OUI_FROM_DATABASE=AVSystem OUI:0023C1* ID_OUI_FROM_DATABASE=Securitas Direct AB OUI:0023BB* ID_OUI_FROM_DATABASE=Schmitt Industries OUI:0023BA* ID_OUI_FROM_DATABASE=Chroma OUI:0023B5* ID_OUI_FROM_DATABASE=ORTANA LTD OUI:002381* ID_OUI_FROM_DATABASE=Lengda Technology(Xiamen) Co.,Ltd. OUI:002382* ID_OUI_FROM_DATABASE=Lih Rong Electronic Enterprise Co., Ltd. OUI:00237B* ID_OUI_FROM_DATABASE=WHDI LLC OUI:002372* ID_OUI_FROM_DATABASE=MORE STAR INDUSTRIAL GROUP LIMITED OUI:002366* ID_OUI_FROM_DATABASE=Beijing Siasun Electronic System Co.,Ltd. OUI:00236B* ID_OUI_FROM_DATABASE=Xembedded, Inc. OUI:002359* ID_OUI_FROM_DATABASE=Benchmark Electronics ( Thailand ) Public Company Limited OUI:00235F* ID_OUI_FROM_DATABASE=Silicon Micro Sensors GmbH OUI:002353* ID_OUI_FROM_DATABASE=F E T Elettronica snc OUI:002347* ID_OUI_FROM_DATABASE=ProCurve Networking by HP OUI:00234C* ID_OUI_FROM_DATABASE=KTC AB OUI:00233A* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:002339* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:002334* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00232E* ID_OUI_FROM_DATABASE=Kedah Electronics Engineering, LLC OUI:002329* ID_OUI_FROM_DATABASE=DDRdrive LLC OUI:002322* ID_OUI_FROM_DATABASE=KISS Teknical Solutions, Inc. OUI:002325* ID_OUI_FROM_DATABASE=IOLAN Holding OUI:002319* ID_OUI_FROM_DATABASE=Sielox LLC OUI:002270* ID_OUI_FROM_DATABASE=ABK North America, LLC OUI:002317* ID_OUI_FROM_DATABASE=Lasercraft Inc OUI:002310* ID_OUI_FROM_DATABASE=LNC Technology Co., Ltd. OUI:002304* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002236* ID_OUI_FROM_DATABASE=VECTOR SP. Z O.O. OUI:002230* ID_OUI_FROM_DATABASE=FutureLogic Inc. OUI:002229* ID_OUI_FROM_DATABASE=Compumedics Ltd OUI:00221D* ID_OUI_FROM_DATABASE=Freegene Technology LTD OUI:002224* ID_OUI_FROM_DATABASE=Good Will Instrument Co., Ltd. OUI:002223* ID_OUI_FROM_DATABASE=TimeKeeping Systems, Inc. OUI:002216* ID_OUI_FROM_DATABASE=SHIBAURA VENDING MACHINE CORPORATION OUI:002217* ID_OUI_FROM_DATABASE=Neat Electronics OUI:002211* ID_OUI_FROM_DATABASE=Rohati Systems OUI:00220A* ID_OUI_FROM_DATABASE=OnLive, Inc OUI:002295* ID_OUI_FROM_DATABASE=SGM Technology for lighting spa OUI:00228E* ID_OUI_FROM_DATABASE=TV-NUMERIC OUI:002289* ID_OUI_FROM_DATABASE=Optosecurity Inc. OUI:002282* ID_OUI_FROM_DATABASE=8086 Consultancy OUI:00227C* ID_OUI_FROM_DATABASE=Woori SMT Co.,ltd OUI:002279* ID_OUI_FROM_DATABASE=Nippon Conlux Co., Ltd. OUI:002273* ID_OUI_FROM_DATABASE=Techway OUI:002274* ID_OUI_FROM_DATABASE=FamilyPhone AB OUI:00226F* ID_OUI_FROM_DATABASE=3onedata Technology Co. Ltd. OUI:00226A* ID_OUI_FROM_DATABASE=Honeywell OUI:0022F3* ID_OUI_FROM_DATABASE=SHARP Corporation OUI:0022EE* ID_OUI_FROM_DATABASE=Algo Communication Products Ltd OUI:0022E7* ID_OUI_FROM_DATABASE=WPS Parking Systems OUI:0022E1* ID_OUI_FROM_DATABASE=ZORT Labs, LLC. OUI:0022E2* ID_OUI_FROM_DATABASE=WABTEC Transit Division OUI:0022DB* ID_OUI_FROM_DATABASE=Translogic Corporation OUI:0022CF* ID_OUI_FROM_DATABASE=PLANEX Communications INC OUI:0022D4* ID_OUI_FROM_DATABASE=ComWorth Co., Ltd. OUI:0022CA* ID_OUI_FROM_DATABASE=Anviz Biometric Tech. Co., Ltd. OUI:0022C5* ID_OUI_FROM_DATABASE=INFORSON Co,Ltd. OUI:002260* ID_OUI_FROM_DATABASE=AFREEY Inc. OUI:00225B* ID_OUI_FROM_DATABASE=Teradici Corporation OUI:002256* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002255* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00224D* ID_OUI_FROM_DATABASE=MITAC INTERNATIONAL CORP. OUI:002252* ID_OUI_FROM_DATABASE=ZOLL Lifecor Corporation OUI:002246* ID_OUI_FROM_DATABASE=Evoc Intelligent Technology Co.,Ltd. OUI:00223C* ID_OUI_FROM_DATABASE=RATIO Entwicklungen GmbH OUI:0022C0* ID_OUI_FROM_DATABASE=Shenzhen Forcelink Electronic Co, Ltd OUI:0022BB* ID_OUI_FROM_DATABASE=beyerdynamic GmbH & Co. KG OUI:0022AE* ID_OUI_FROM_DATABASE=Mattel Inc. OUI:0022AD* ID_OUI_FROM_DATABASE=TELESIS TECHNOLOGIES, INC. OUI:0022A8* ID_OUI_FROM_DATABASE=Ouman Oy OUI:0022A1* ID_OUI_FROM_DATABASE=Huawei Symantec Technologies Co.,Ltd. OUI:00229B* ID_OUI_FROM_DATABASE=AverLogic Technologies, Inc. OUI:00229C* ID_OUI_FROM_DATABASE=Verismo Networks Inc OUI:0023A8* ID_OUI_FROM_DATABASE=Marshall Electronics OUI:00239B* ID_OUI_FROM_DATABASE=Elster Solutions, LLC OUI:002396* ID_OUI_FROM_DATABASE=ANDES TECHNOLOGY CORPORATION OUI:002391* ID_OUI_FROM_DATABASE=Maxian OUI:00238C* ID_OUI_FROM_DATABASE=Private OUI:002387* ID_OUI_FROM_DATABASE=ThinkFlood, Inc. OUI:0021D6* ID_OUI_FROM_DATABASE=LXI Consortium OUI:0021CF* ID_OUI_FROM_DATABASE=The Crypto Group OUI:0021C9* ID_OUI_FROM_DATABASE=Wavecom Asia Pacific Limited OUI:0021CA* ID_OUI_FROM_DATABASE=ART System Co., Ltd. OUI:0021C3* ID_OUI_FROM_DATABASE=CORNELL Communications, Inc. OUI:0021BC* ID_OUI_FROM_DATABASE=ZALA COMPUTER OUI:0021B7* ID_OUI_FROM_DATABASE=Lexmark International Inc. OUI:002152* ID_OUI_FROM_DATABASE=General Satellite Research & Development Limited OUI:002157* ID_OUI_FROM_DATABASE=National Datacast, Inc. OUI:00214B* ID_OUI_FROM_DATABASE=Shenzhen HAMP Science & Technology Co.,Ltd OUI:002145* ID_OUI_FROM_DATABASE=Semptian Technologies Ltd. OUI:002144* ID_OUI_FROM_DATABASE=SS Telecoms OUI:00213C* ID_OUI_FROM_DATABASE=AliphCom OUI:00213B* ID_OUI_FROM_DATABASE=Berkshire Products, Inc OUI:002132* ID_OUI_FROM_DATABASE=Masterclock, Inc. OUI:00212C* ID_OUI_FROM_DATABASE=SemIndia System Private Limited OUI:002131* ID_OUI_FROM_DATABASE=Blynke Inc. OUI:001FD1* ID_OUI_FROM_DATABASE=OPTEX CO.,LTD. OUI:001FCA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001FBE* ID_OUI_FROM_DATABASE=Shenzhen Mopnet Industrial Co.,Ltd OUI:001FB9* ID_OUI_FROM_DATABASE=Paltronics OUI:001FB7* ID_OUI_FROM_DATABASE=WiMate Technologies Corp. OUI:001FB8* ID_OUI_FROM_DATABASE=Universal Remote Control, Inc. OUI:001FB2* ID_OUI_FROM_DATABASE=Sontheim Industrie Elektronik GmbH OUI:00211F* ID_OUI_FROM_DATABASE=SHINSUNG DELTATECH CO.,LTD. OUI:002120* ID_OUI_FROM_DATABASE=Sequel Technologies OUI:002125* ID_OUI_FROM_DATABASE=KUK JE TONG SHIN Co.,LTD OUI:002119* ID_OUI_FROM_DATABASE=Samsung Electro-Mechanics OUI:002112* ID_OUI_FROM_DATABASE=WISCOM SYSTEM CO.,LTD OUI:002103* ID_OUI_FROM_DATABASE=GHI Electronics, LLC OUI:0021B0* ID_OUI_FROM_DATABASE=Tyco Telecommunications OUI:0021A4* ID_OUI_FROM_DATABASE=Dbii Networks OUI:00219A* ID_OUI_FROM_DATABASE=Cambridge Visual Networks Ltd OUI:002196* ID_OUI_FROM_DATABASE=Telsey S.p.A. OUI:002190* ID_OUI_FROM_DATABASE=Goliath Solutions OUI:002189* ID_OUI_FROM_DATABASE=AppTech, Inc. OUI:002184* ID_OUI_FROM_DATABASE=POWERSOFT SRL OUI:002183* ID_OUI_FROM_DATABASE=VATECH HYDRO OUI:001FFA* ID_OUI_FROM_DATABASE=Coretree, Co, Ltd OUI:001FF5* ID_OUI_FROM_DATABASE=Kongsberg Defence & Aerospace OUI:001FF4* ID_OUI_FROM_DATABASE=Power Monitors, Inc. OUI:001FEE* ID_OUI_FROM_DATABASE=ubisys technologies GmbH OUI:001FE7* ID_OUI_FROM_DATABASE=Simet OUI:001FDB* ID_OUI_FROM_DATABASE=Network Supply Corp., OUI:00217D* ID_OUI_FROM_DATABASE=PYXIS S.R.L. OUI:002177* ID_OUI_FROM_DATABASE=W. L. Gore & Associates OUI:002176* ID_OUI_FROM_DATABASE=YMax Telecom Ltd. OUI:002171* ID_OUI_FROM_DATABASE=Wesung TNC Co., Ltd. OUI:002164* ID_OUI_FROM_DATABASE=Special Design Bureau for Seismic Instrumentation OUI:00215E* ID_OUI_FROM_DATABASE=IBM Corp OUI:002151* ID_OUI_FROM_DATABASE=Millinet Co., Ltd. OUI:002204* ID_OUI_FROM_DATABASE=KORATEK OUI:0021FF* ID_OUI_FROM_DATABASE=Cyfrowy Polsat SA OUI:0021FB* ID_OUI_FROM_DATABASE=LG Electronics OUI:0021F5* ID_OUI_FROM_DATABASE=Western Engravers Supply, Inc. OUI:0021EF* ID_OUI_FROM_DATABASE=Kapsys OUI:0021EE* ID_OUI_FROM_DATABASE=Full Spectrum Inc. OUI:0021DC* ID_OUI_FROM_DATABASE=TECNOALARM S.r.l. OUI:0021E2* ID_OUI_FROM_DATABASE=Creative Electronic GmbH OUI:001FAB* ID_OUI_FROM_DATABASE=I.S HIGH TECH.INC OUI:001FA6* ID_OUI_FROM_DATABASE=Stilo srl OUI:001FA1* ID_OUI_FROM_DATABASE=Gtran Inc OUI:001F9C* ID_OUI_FROM_DATABASE=LEDCO OUI:001F8E* ID_OUI_FROM_DATABASE=Metris USA Inc. OUI:001E41* ID_OUI_FROM_DATABASE=Microwave Communication & Component, Inc. OUI:001E2E* ID_OUI_FROM_DATABASE=SIRTI S.p.A. OUI:001E27* ID_OUI_FROM_DATABASE=SBN TECH Co.,Ltd. OUI:001E28* ID_OUI_FROM_DATABASE=Lumexis Corporation OUI:001E22* ID_OUI_FROM_DATABASE=ARVOO Imaging Products BV OUI:001E1B* ID_OUI_FROM_DATABASE=Digital Stream Technology, Inc. OUI:001E16* ID_OUI_FROM_DATABASE=Keytronix OUI:001E15* ID_OUI_FROM_DATABASE=Beech Hill Electronics OUI:001E11* ID_OUI_FROM_DATABASE=ELELUX INTERNATIONAL LTD OUI:001E05* ID_OUI_FROM_DATABASE=Xseed Technologies & Computing OUI:001E0C* ID_OUI_FROM_DATABASE=Sherwood Information Partners, Inc. OUI:001DFE* ID_OUI_FROM_DATABASE=Palm, Inc OUI:001DF9* ID_OUI_FROM_DATABASE=Cybiotronics (Far East) Limited OUI:001DF2* ID_OUI_FROM_DATABASE=Netflix, Inc. OUI:001DEB* ID_OUI_FROM_DATABASE=DINEC International OUI:001DEC* ID_OUI_FROM_DATABASE=Marusys OUI:001F88* ID_OUI_FROM_DATABASE=FMS Force Measuring Systems AG OUI:001F81* ID_OUI_FROM_DATABASE=Accel Semiconductor Corp OUI:001B58* ID_OUI_FROM_DATABASE=ACE CAD Enterprise Co., Ltd. OUI:001F78* ID_OUI_FROM_DATABASE=Blue Fox Porini Textile OUI:001F6E* ID_OUI_FROM_DATABASE=Vtech Engineering Corporation OUI:001F68* ID_OUI_FROM_DATABASE=Martinsson Elektronik AB OUI:001F62* ID_OUI_FROM_DATABASE=JSC Stilsoft OUI:001F67* ID_OUI_FROM_DATABASE=Hitachi,Ltd. OUI:001F55* ID_OUI_FROM_DATABASE=Honeywell Security (China) Co., Ltd. OUI:001E9B* ID_OUI_FROM_DATABASE=San-Eisha, Ltd. OUI:001E94* ID_OUI_FROM_DATABASE=SUPERCOM TECHNOLOGY CORPORATION OUI:001E8F* ID_OUI_FROM_DATABASE=CANON INC. OUI:001E87* ID_OUI_FROM_DATABASE=Realease Limited OUI:001E80* ID_OUI_FROM_DATABASE=Last Mile Ltd. OUI:001E7B* ID_OUI_FROM_DATABASE=R.I.CO. S.r.l. OUI:001E76* ID_OUI_FROM_DATABASE=Thermo Fisher Scientific OUI:001E6A* ID_OUI_FROM_DATABASE=Beijing Bluexon Technology Co.,Ltd OUI:001F56* ID_OUI_FROM_DATABASE=DIGITAL FORECAST OUI:001F4F* ID_OUI_FROM_DATABASE=Thinkware Co. Ltd. OUI:001F48* ID_OUI_FROM_DATABASE=Mojix Inc. OUI:001F43* ID_OUI_FROM_DATABASE=ENTES ELEKTRONIK OUI:001F2E* ID_OUI_FROM_DATABASE=Triangle Research Int'l Pte Ltd OUI:001F2D* ID_OUI_FROM_DATABASE=Electro-Optical Imaging, Inc. OUI:001F27* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001EF5* ID_OUI_FROM_DATABASE=Hitek Automated Inc. OUI:001EFB* ID_OUI_FROM_DATABASE=Trio Motion Technology Ltd OUI:001EE9* ID_OUI_FROM_DATABASE=Stoneridge Electronics AB OUI:001EEE* ID_OUI_FROM_DATABASE=ETL Systems Ltd OUI:001EE2* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:001ED8* ID_OUI_FROM_DATABASE=Digital United Inc. OUI:001ED2* ID_OUI_FROM_DATABASE=Ray Shine Video Technology Inc OUI:001ED1* ID_OUI_FROM_DATABASE=Keyprocessor B.V. OUI:001ECC* ID_OUI_FROM_DATABASE=CDVI OUI:001EC5* ID_OUI_FROM_DATABASE=Middle Atlantic Products Inc OUI:001EC0* ID_OUI_FROM_DATABASE=Microchip Technology Inc. OUI:001EBF* ID_OUI_FROM_DATABASE=Haas Automation Inc. OUI:001EB9* ID_OUI_FROM_DATABASE=Sing Fai Technology Limited OUI:001EB2* ID_OUI_FROM_DATABASE=LG innotek OUI:001EAD* ID_OUI_FROM_DATABASE=Wingtech Group Limited OUI:001EA2* ID_OUI_FROM_DATABASE=Symx Systems, Inc. OUI:001EA7* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:001EA1* ID_OUI_FROM_DATABASE=Brunata a/s OUI:001F20* ID_OUI_FROM_DATABASE=Logitech Europe SA OUI:001F14* ID_OUI_FROM_DATABASE=NexG OUI:001F1B* ID_OUI_FROM_DATABASE=RoyalTek Company Ltd. OUI:001F0D* ID_OUI_FROM_DATABASE=L3 Communications - Telemetry West OUI:001F0E* ID_OUI_FROM_DATABASE=Japan Kyastem Co., Ltd OUI:001EFC* ID_OUI_FROM_DATABASE=JSC MASSA-K OUI:001F08* ID_OUI_FROM_DATABASE=RISCO LTD OUI:001E71* ID_OUI_FROM_DATABASE=MIrcom Group of Companies OUI:001E63* ID_OUI_FROM_DATABASE=Vibro-Meter SA OUI:001E5E* ID_OUI_FROM_DATABASE=COmputime Ltd. OUI:001E57* ID_OUI_FROM_DATABASE=ALCOMA, spol. s r.o. OUI:001E51* ID_OUI_FROM_DATABASE=Converter Industry Srl OUI:001E4B* ID_OUI_FROM_DATABASE=City Theatrical OUI:001E47* ID_OUI_FROM_DATABASE=PT. Hariff Daya Tunggal Engineering OUI:001D37* ID_OUI_FROM_DATABASE=Thales-Panda Transportation System OUI:001D38* ID_OUI_FROM_DATABASE=Seagate Technology OUI:001D32* ID_OUI_FROM_DATABASE=Longkay Communication & Technology (Shanghai) Co. Ltd OUI:001D2B* ID_OUI_FROM_DATABASE=Wuhan Pont Technology CO. , LTD OUI:001D1F* ID_OUI_FROM_DATABASE=Siauliu Tauro Televizoriai, JSC OUI:001D26* ID_OUI_FROM_DATABASE=Rockridgesound Technology Co. OUI:001D25* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:001D1A* ID_OUI_FROM_DATABASE=OvisLink S.A. OUI:001D14* ID_OUI_FROM_DATABASE=SPERADTONE INFORMATION TECHNOLOGY LIMITED OUI:001CDD* ID_OUI_FROM_DATABASE=COWBELL ENGINEERING CO., LTD. OUI:001CDE* ID_OUI_FROM_DATABASE=Interactive Multimedia eXchange Inc. OUI:001CD8* ID_OUI_FROM_DATABASE=BlueAnt Wireless OUI:001CD1* ID_OUI_FROM_DATABASE=Waves Audio LTD OUI:001CCB* ID_OUI_FROM_DATABASE=Forth Corporation Public Company Limited OUI:001CC5* ID_OUI_FROM_DATABASE=3Com Ltd OUI:001CB9* ID_OUI_FROM_DATABASE=KWANG SUNG ELECTRONICS CO., LTD. OUI:001CAF* ID_OUI_FROM_DATABASE=Plato Networks Inc. OUI:001CB4* ID_OUI_FROM_DATABASE=Iridium Satellite LLC OUI:001C65* ID_OUI_FROM_DATABASE=JoeScan, Inc. OUI:001C67* ID_OUI_FROM_DATABASE=Pumpkin Networks, Inc. OUI:001C66* ID_OUI_FROM_DATABASE=UCAMP CO.,LTD OUI:001C60* ID_OUI_FROM_DATABASE=CSP Frontier Technologies,Inc. OUI:001C54* ID_OUI_FROM_DATABASE=Hillstone Networks Inc OUI:001C59* ID_OUI_FROM_DATABASE=DEVON IT OUI:001C4F* ID_OUI_FROM_DATABASE=MACAB AB OUI:001C43* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:001C37* ID_OUI_FROM_DATABASE=Callpod, Inc. OUI:001C3C* ID_OUI_FROM_DATABASE=Seon Design Inc. OUI:001DE6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001DDA* ID_OUI_FROM_DATABASE=Mikroelektronika spol. s r. o. OUI:001DDF* ID_OUI_FROM_DATABASE=Sunitec Enterprise Co., Ltd. OUI:001DCC* ID_OUI_FROM_DATABASE=Hetra Secure Solutions OUI:001DC7* ID_OUI_FROM_DATABASE=L-3 Communications Geneva Aerospace OUI:001DC0* ID_OUI_FROM_DATABASE=Enphase Energy OUI:001DB9* ID_OUI_FROM_DATABASE=Wellspring Wireless OUI:001D07* ID_OUI_FROM_DATABASE=Shenzhen Sang Fei Consumer Communications Co.,Ltd OUI:001D01* ID_OUI_FROM_DATABASE=Neptune Digital OUI:001CFA* ID_OUI_FROM_DATABASE=Alarm.com OUI:001CEE* ID_OUI_FROM_DATABASE=SHARP Corporation OUI:001CF5* ID_OUI_FROM_DATABASE=Wiseblue Technology Limited OUI:001CE8* ID_OUI_FROM_DATABASE=Cummins Inc OUI:001CE4* ID_OUI_FROM_DATABASE=EleSy JSC OUI:001C9F* ID_OUI_FROM_DATABASE=Razorstream, LLC OUI:001C99* ID_OUI_FROM_DATABASE=Shunra Software Ltd. OUI:001C8C* ID_OUI_FROM_DATABASE=DIAL TECHNOLOGY LTD. OUI:001C93* ID_OUI_FROM_DATABASE=ExaDigm Inc OUI:001C87* ID_OUI_FROM_DATABASE=Uriver Inc. OUI:001C82* ID_OUI_FROM_DATABASE=Genew Technologies OUI:001C7D* ID_OUI_FROM_DATABASE=Excelpoint Manufacturing Pte Ltd OUI:001C73* ID_OUI_FROM_DATABASE=Arista Networks, Inc. OUI:001C78* ID_OUI_FROM_DATABASE=WYPLAY SAS OUI:001D62* ID_OUI_FROM_DATABASE=InPhase Technologies OUI:001D61* ID_OUI_FROM_DATABASE=BIJ Corporation OUI:001D5B* ID_OUI_FROM_DATABASE=Tecvan Informática Ltda OUI:001D54* ID_OUI_FROM_DATABASE=Sunnic Technology & Merchandise INC. OUI:001D4A* ID_OUI_FROM_DATABASE=Carestream Health, Inc. OUI:001D45* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001D3E* ID_OUI_FROM_DATABASE=SAKA TECHNO SCIENCE CO.,LTD OUI:001D90* ID_OUI_FROM_DATABASE=EMCO Flow Systems OUI:001D84* ID_OUI_FROM_DATABASE=Gateway, Inc. OUI:001D67* ID_OUI_FROM_DATABASE=AMEC OUI:001D7A* ID_OUI_FROM_DATABASE=Wideband Semiconductor, Inc. OUI:001D74* ID_OUI_FROM_DATABASE=Tianjin China-Silicon Microelectronics Co., Ltd. OUI:001DB4* ID_OUI_FROM_DATABASE=KUMHO ENG CO.,LTD OUI:001DAF* ID_OUI_FROM_DATABASE=Nortel OUI:001D9E* ID_OUI_FROM_DATABASE=AXION TECHNOLOGIES OUI:001DA3* ID_OUI_FROM_DATABASE=SabiOso OUI:001D9D* ID_OUI_FROM_DATABASE=ARTJOY INTERNATIONAL LIMITED OUI:001D97* ID_OUI_FROM_DATABASE=Alertus Technologies LLC OUI:001BA6* ID_OUI_FROM_DATABASE=intotech inc. OUI:001BA1* ID_OUI_FROM_DATABASE=Åmic AB OUI:001B93* ID_OUI_FROM_DATABASE=JC Decaux SA DNT OUI:001B95* ID_OUI_FROM_DATABASE=VIDEO SYSTEMS SRL OUI:001B9A* ID_OUI_FROM_DATABASE=Apollo Fire Detectors Ltd OUI:001B94* ID_OUI_FROM_DATABASE=T.E.M.A. S.p.A. OUI:001B8E* ID_OUI_FROM_DATABASE=Hulu Sweden AB OUI:001B89* ID_OUI_FROM_DATABASE=EMZA Visual Sense Ltd. OUI:001B8A* ID_OUI_FROM_DATABASE=2M Electronic A/S OUI:001B84* ID_OUI_FROM_DATABASE=Scan Engineering Telecom OUI:001B7D* ID_OUI_FROM_DATABASE=CXR Anderson Jacobson OUI:001B71* ID_OUI_FROM_DATABASE=Telular Corp. OUI:001B6A* ID_OUI_FROM_DATABASE=Powerwave Technologies Sweden AB OUI:001B65* ID_OUI_FROM_DATABASE=China Gridcom Co., Ltd OUI:001B5E* ID_OUI_FROM_DATABASE=BPL Limited OUI:001B57* ID_OUI_FROM_DATABASE=SEMINDIA SYSTEMS PRIVATE LIMITED OUI:001B46* ID_OUI_FROM_DATABASE=Blueone Technology Co.,Ltd OUI:001B4B* ID_OUI_FROM_DATABASE=SANION Co., Ltd. OUI:001B3F* ID_OUI_FROM_DATABASE=ProCurve Networking by HP OUI:001BCF* ID_OUI_FROM_DATABASE=Dataupia Corporation OUI:001BD0* ID_OUI_FROM_DATABASE=IDENTEC SOLUTIONS OUI:001BCA* ID_OUI_FROM_DATABASE=Beijing Run Technology LTD. Company OUI:001BC3* ID_OUI_FROM_DATABASE=Mobisolution Co.,Ltd OUI:001BBE* ID_OUI_FROM_DATABASE=ICOP Digital OUI:001BB4* ID_OUI_FROM_DATABASE=Airvod Limited OUI:001BAD* ID_OUI_FROM_DATABASE=iControl Incorporated OUI:001AD1* ID_OUI_FROM_DATABASE=FARGO CO., LTD. OUI:001AD8* ID_OUI_FROM_DATABASE=AlsterAero GmbH OUI:001ACA* ID_OUI_FROM_DATABASE=Tilera Corporation OUI:001ACC* ID_OUI_FROM_DATABASE=Celestial Semiconductor, Ltd OUI:001AC5* ID_OUI_FROM_DATABASE=BreakingPoint Systems, Inc. OUI:001ABB* ID_OUI_FROM_DATABASE=Fontal Technology Incorporation OUI:001AC0* ID_OUI_FROM_DATABASE=JOYBIEN TECHNOLOGIES CO., LTD. OUI:001AB4* ID_OUI_FROM_DATABASE=FFEI Ltd. OUI:001AAF* ID_OUI_FROM_DATABASE=BLUSENS TECHNOLOGY OUI:001C07* ID_OUI_FROM_DATABASE=Cwlinux Limited OUI:001C00* ID_OUI_FROM_DATABASE=Entry Point, LLC OUI:001BF4* ID_OUI_FROM_DATABASE=KENWIN INDUSTRIAL(HK) LTD. OUI:001BEF* ID_OUI_FROM_DATABASE=Blossoms Digital Technology Co.,Ltd. OUI:001BE2* ID_OUI_FROM_DATABASE=AhnLab,Inc. OUI:001BD1* ID_OUI_FROM_DATABASE=SOGESTMATIC OUI:001BD6* ID_OUI_FROM_DATABASE=Kelvin Hughes Ltd OUI:001C30* ID_OUI_FROM_DATABASE=Mode Lighting (UK ) Ltd. OUI:001C2B* ID_OUI_FROM_DATABASE=Alertme.com Limited OUI:001C2A* ID_OUI_FROM_DATABASE=Envisacor Technologies Inc. OUI:001C29* ID_OUI_FROM_DATABASE=CORE DIGITAL ELECTRONICS CO., LTD OUI:001C24* ID_OUI_FROM_DATABASE=Formosa Wireless Systems Corp. OUI:001C1F* ID_OUI_FROM_DATABASE=Quest Retail Technology Pty Ltd OUI:001C1A* ID_OUI_FROM_DATABASE=Thomas Instrumentation, Inc OUI:001C0E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001C13* ID_OUI_FROM_DATABASE=OPTSYS TECHNOLOGY CO., LTD. OUI:001B3A* ID_OUI_FROM_DATABASE=SIMS Corp. OUI:001B2C* ID_OUI_FROM_DATABASE=ATRON electronic GmbH OUI:001B27* ID_OUI_FROM_DATABASE=Merlin CSI OUI:001B25* ID_OUI_FROM_DATABASE=Nortel OUI:001B20* ID_OUI_FROM_DATABASE=TPine Technology OUI:001B19* ID_OUI_FROM_DATABASE=IEEE I&M Society TC9 OUI:001B14* ID_OUI_FROM_DATABASE=Carex Lighting Equipment Factory OUI:001B0D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001AA8* ID_OUI_FROM_DATABASE=Mamiya Digital Imaging Co., Ltd. OUI:001A9F* ID_OUI_FROM_DATABASE=A-Link Ltd OUI:001AA6* ID_OUI_FROM_DATABASE=Telefunken Radio Communication Systems GmbH &CO.KG OUI:001A93* ID_OUI_FROM_DATABASE=ERCO Leuchten GmbH OUI:001A98* ID_OUI_FROM_DATABASE=Asotel Communication Limited Taiwan Branch OUI:001A8E* ID_OUI_FROM_DATABASE=3Way Networks Ltd OUI:001B06* ID_OUI_FROM_DATABASE=Ateliers R. LAUMONIER OUI:001B08* ID_OUI_FROM_DATABASE=Danfoss Drives A/S OUI:001B01* ID_OUI_FROM_DATABASE=Applied Radio Technologies OUI:001AF5* ID_OUI_FROM_DATABASE=PENTAONE. CO., LTD. OUI:001AFA* ID_OUI_FROM_DATABASE=Welch Allyn, Inc. OUI:001AF0* ID_OUI_FROM_DATABASE=Alcatel - IPD OUI:001AE4* ID_OUI_FROM_DATABASE=Medicis Technologies Corporation OUI:001ADD* ID_OUI_FROM_DATABASE=PePWave Ltd OUI:001933* ID_OUI_FROM_DATABASE=Strix Systems, Inc. OUI:001938* ID_OUI_FROM_DATABASE=UMB Communications Co., Ltd. OUI:00192D* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:001926* ID_OUI_FROM_DATABASE=BitsGen Co., Ltd. OUI:001928* ID_OUI_FROM_DATABASE=Siemens AG, Transportation Systems OUI:00190E* ID_OUI_FROM_DATABASE=Atech Technology Co., Ltd. OUI:001913* ID_OUI_FROM_DATABASE=Chuang-Yi Network Equipment Co.Ltd. OUI:001915* ID_OUI_FROM_DATABASE=TECOM Co., Ltd. OUI:00191A* ID_OUI_FROM_DATABASE=IRLINK OUI:00199D* ID_OUI_FROM_DATABASE=VIZIO, Inc. OUI:00198E* ID_OUI_FROM_DATABASE=Oticon A/S OUI:001980* ID_OUI_FROM_DATABASE=Gridpoint Systems OUI:001987* ID_OUI_FROM_DATABASE=Panasonic Mobile Communications Co., Ltd. OUI:00197B* ID_OUI_FROM_DATABASE=Picotest Corp. OUI:001968* ID_OUI_FROM_DATABASE=Digital Video Networks(Shanghai) CO. LTD. OUI:00196D* ID_OUI_FROM_DATABASE=Raybit Systems Korea, Inc OUI:00196F* ID_OUI_FROM_DATABASE=SensoPart GmbH OUI:001952* ID_OUI_FROM_DATABASE=ACOGITO Co., Ltd OUI:001957* ID_OUI_FROM_DATABASE=Saafnet Canada Inc. OUI:001946* ID_OUI_FROM_DATABASE=Cianet Industria e Comercio S/A OUI:001944* ID_OUI_FROM_DATABASE=Fossil Partners, L.P. OUI:00193F* ID_OUI_FROM_DATABASE=RDI technology(Shenzhen) Co.,LTD OUI:001A7D* ID_OUI_FROM_DATABASE=cyber-blue(HK)Ltd OUI:001A82* ID_OUI_FROM_DATABASE=PROBA Building Automation Co.,LTD OUI:001A7C* ID_OUI_FROM_DATABASE=Hirschmann Multimedia B.V. OUI:001A78* ID_OUI_FROM_DATABASE=ubtos OUI:001A7B* ID_OUI_FROM_DATABASE=Teleco, Inc. OUI:001A71* ID_OUI_FROM_DATABASE=Diostech Co., Ltd. OUI:001A6C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001A65* ID_OUI_FROM_DATABASE=Seluxit OUI:001A60* ID_OUI_FROM_DATABASE=Wave Electronics Co.,Ltd. OUI:001A55* ID_OUI_FROM_DATABASE=ACA-Digital Corporation OUI:001A5A* ID_OUI_FROM_DATABASE=Korea Electric Power Data Network (KDN) Co., Ltd OUI:001A4E* ID_OUI_FROM_DATABASE=NTI AG / LinMot OUI:001A53* ID_OUI_FROM_DATABASE=Zylaya OUI:001A42* ID_OUI_FROM_DATABASE=Techcity Technology co., Ltd. OUI:001A47* ID_OUI_FROM_DATABASE=Agami Systems, Inc. OUI:001A3B* ID_OUI_FROM_DATABASE=Doah Elecom Inc. OUI:001A2F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001A36* ID_OUI_FROM_DATABASE=Aipermon GmbH & Co. KG OUI:001A25* ID_OUI_FROM_DATABASE=DELTA DORE OUI:0019C3* ID_OUI_FROM_DATABASE=Qualitrol OUI:0019BE* ID_OUI_FROM_DATABASE=Altai Technologies Limited OUI:0019BC* ID_OUI_FROM_DATABASE=ELECTRO CHANCE SRL OUI:0019A4* ID_OUI_FROM_DATABASE=Austar Technology (hang zhou) Co.,Ltd OUI:0019A9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0019AB* ID_OUI_FROM_DATABASE=Raycom CO ., LTD OUI:0019B0* ID_OUI_FROM_DATABASE=HanYang System OUI:001993* ID_OUI_FROM_DATABASE=Changshu Switchgear MFG. Co.,Ltd. (Former Changshu Switchgea OUI:001998* ID_OUI_FROM_DATABASE=SATO CORPORATION OUI:001A17* ID_OUI_FROM_DATABASE=Teak Technologies, Inc. OUI:001A19* ID_OUI_FROM_DATABASE=Computer Engineering Limited OUI:001A12* ID_OUI_FROM_DATABASE=Essilor OUI:001A0B* ID_OUI_FROM_DATABASE=BONA TECHNOLOGY INC. OUI:001A06* ID_OUI_FROM_DATABASE=OpVista, Inc. OUI:0019FA* ID_OUI_FROM_DATABASE=Cable Vision Electronics CO., LTD. OUI:0019FF* ID_OUI_FROM_DATABASE=Finnzymes OUI:001902* ID_OUI_FROM_DATABASE=Cambridge Consultants Ltd OUI:001907* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0018FD* ID_OUI_FROM_DATABASE=Optimal Technologies International Inc. OUI:0018F1* ID_OUI_FROM_DATABASE=Chunichi Denshi Co.,LTD. OUI:0018EA* ID_OUI_FROM_DATABASE=Alltec GmbH OUI:0018EC* ID_OUI_FROM_DATABASE=Welding Technology Corporation OUI:0018E5* ID_OUI_FROM_DATABASE=Adhoco AG OUI:0018CD* ID_OUI_FROM_DATABASE=Erae Electronics Industry Co., Ltd OUI:0018D2* ID_OUI_FROM_DATABASE=High-Gain Antennas LLC OUI:0019EC* ID_OUI_FROM_DATABASE=Sagamore Systems, Inc. OUI:0019F3* ID_OUI_FROM_DATABASE=Cetis, Inc OUI:0019F8* ID_OUI_FROM_DATABASE=Embedded Systems Design, Inc. OUI:0019E5* ID_OUI_FROM_DATABASE=Lynx Studio Technology, Inc. OUI:0019E7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0019CD* ID_OUI_FROM_DATABASE=Chengdu ethercom information technology Ltd. OUI:0019D4* ID_OUI_FROM_DATABASE=ICX Technologies OUI:0019D9* ID_OUI_FROM_DATABASE=Zeutschel GmbH OUI:0019C8* ID_OUI_FROM_DATABASE=AnyDATA Corporation OUI:001817* ID_OUI_FROM_DATABASE=D. E. Shaw Research, LLC OUI:00181E* ID_OUI_FROM_DATABASE=GDX Technologies Ltd. OUI:001812* ID_OUI_FROM_DATABASE=Beijing Xinwei Telecom Technology Co., Ltd. OUI:001806* ID_OUI_FROM_DATABASE=Hokkei Industries Co., Ltd. OUI:00180B* ID_OUI_FROM_DATABASE=Brilliant Telecommunications OUI:001805* ID_OUI_FROM_DATABASE=Beijing InHand Networking Technology Co.,Ltd. OUI:0017F4* ID_OUI_FROM_DATABASE=ZERON ALLIANCE OUI:0017F9* ID_OUI_FROM_DATABASE=Forcom Sp. z o.o. OUI:001800* ID_OUI_FROM_DATABASE=UNIGRAND LTD OUI:0017B1* ID_OUI_FROM_DATABASE=ACIST Medical Systems, Inc. OUI:0017AA* ID_OUI_FROM_DATABASE=elab-experience inc. OUI:0017AC* ID_OUI_FROM_DATABASE=O'Neil Product Development Inc. OUI:0017A5* ID_OUI_FROM_DATABASE=Ralink Technology Corp OUI:0017A0* ID_OUI_FROM_DATABASE=RoboTech srl OUI:00179B* ID_OUI_FROM_DATABASE=Chant Sincere CO., LTD. OUI:00178F* ID_OUI_FROM_DATABASE=NINGBO YIDONG ELECTRONIC CO.,LTD. OUI:001794* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00178D* ID_OUI_FROM_DATABASE=Checkpoint Systems, Inc. OUI:0018D9* ID_OUI_FROM_DATABASE=Santosha Internatonal, Inc OUI:0018C1* ID_OUI_FROM_DATABASE=Almitec Informática e Comércio OUI:0018C8* ID_OUI_FROM_DATABASE=ISONAS Inc. OUI:0018BC* ID_OUI_FROM_DATABASE=ZAO NVP Bolid OUI:0018B5* ID_OUI_FROM_DATABASE=Magna Carta OUI:0018B0* ID_OUI_FROM_DATABASE=Nortel OUI:0018AE* ID_OUI_FROM_DATABASE=TVT CO.,LTD OUI:0018A2* ID_OUI_FROM_DATABASE=XIP Technology AB OUI:0018A9* ID_OUI_FROM_DATABASE=Ethernet Direct Corporation OUI:00177C* ID_OUI_FROM_DATABASE=Smartlink Network Systems Limited OUI:001781* ID_OUI_FROM_DATABASE=Greystone Data System, Inc. OUI:001788* ID_OUI_FROM_DATABASE=Philips Lighting BV OUI:00176C* ID_OUI_FROM_DATABASE=Pivot3, Inc. OUI:001770* ID_OUI_FROM_DATABASE=Arti Industrial Electronics Ltd. OUI:001775* ID_OUI_FROM_DATABASE=TTE Germany GmbH OUI:001760* ID_OUI_FROM_DATABASE=Naito Densei Machida MFG.CO.,LTD OUI:001765* ID_OUI_FROM_DATABASE=Nortel OUI:001767* ID_OUI_FROM_DATABASE=Earforce AS OUI:001759* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001880* ID_OUI_FROM_DATABASE=Maxim Integrated Products OUI:00186D* ID_OUI_FROM_DATABASE=Zhenjiang Sapphire Electronic Industry CO. OUI:001872* ID_OUI_FROM_DATABASE=Expertise Engineering OUI:001874* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001879* ID_OUI_FROM_DATABASE=dSys OUI:00185A* ID_OUI_FROM_DATABASE=uControl, Inc. OUI:00185F* ID_OUI_FROM_DATABASE=TAC Inc. OUI:001861* ID_OUI_FROM_DATABASE=Ooma, Inc. OUI:001866* ID_OUI_FROM_DATABASE=Leutron Vision OUI:001853* ID_OUI_FROM_DATABASE=Atera Networks LTD. OUI:00184E* ID_OUI_FROM_DATABASE=Lianhe Technologies, Inc. OUI:001847* ID_OUI_FROM_DATABASE=AceNet Technology Inc. OUI:00183B* ID_OUI_FROM_DATABASE=CENITS Co., Ltd. OUI:001840* ID_OUI_FROM_DATABASE=3 Phoenix, Inc. OUI:001842* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001825* ID_OUI_FROM_DATABASE=Private OUI:00182A* ID_OUI_FROM_DATABASE=Taiwan Video & Monitor OUI:001836* ID_OUI_FROM_DATABASE=Reliance Electric Limited OUI:001823* ID_OUI_FROM_DATABASE=Delta Electronics, Inc. OUI:001754* ID_OUI_FROM_DATABASE=Arkino HiTOP Corporation Limited OUI:001746* ID_OUI_FROM_DATABASE=Freedom9 Inc. OUI:001748* ID_OUI_FROM_DATABASE=Neokoros Brasil Ltda OUI:00174D* ID_OUI_FROM_DATABASE=DYNAMIC NETWORK FACTORY, INC. OUI:001741* ID_OUI_FROM_DATABASE=DEFIDEV OUI:001733* ID_OUI_FROM_DATABASE=SFR OUI:00173A* ID_OUI_FROM_DATABASE=Reach Systems Inc. OUI:00172E* ID_OUI_FROM_DATABASE=FXC Inc. OUI:0017ED* ID_OUI_FROM_DATABASE=WooJooIT Ltd. OUI:0017D5* ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. OUI:0017DA* ID_OUI_FROM_DATABASE=Spans Logic OUI:0017E1* ID_OUI_FROM_DATABASE=DACOS Technologies Co., Ltd. OUI:0017C9* ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. OUI:0017D0* ID_OUI_FROM_DATABASE=Opticom Communications, LLC OUI:0017C4* ID_OUI_FROM_DATABASE=Quanta Microsystems, INC. OUI:0017B8* ID_OUI_FROM_DATABASE=NOVATRON CO., LTD. OUI:0017BD* ID_OUI_FROM_DATABASE=Tibetsystem OUI:00189D* ID_OUI_FROM_DATABASE=Navcast Inc. OUI:001893* ID_OUI_FROM_DATABASE=SHENZHEN PHOTON BROADBAND TECHNOLOGY CO.,LTD OUI:001898* ID_OUI_FROM_DATABASE=KINGSTATE ELECTRONICS CORPORATION OUI:001891* ID_OUI_FROM_DATABASE=Zhongshan General K-mate Electronics Co., Ltd OUI:001885* ID_OUI_FROM_DATABASE=Avigilon Corporation OUI:00188C* ID_OUI_FROM_DATABASE=Mobile Action Technology Inc. OUI:00167F* ID_OUI_FROM_DATABASE=Bluebird Soft Inc. OUI:001681* ID_OUI_FROM_DATABASE=Vector Informatik GmbH OUI:00167A* ID_OUI_FROM_DATABASE=Skyworth Overseas Dvelopment Ltd. OUI:001674* ID_OUI_FROM_DATABASE=EuroCB (Phils.), Inc. OUI:00166B* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:00166D* ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific(shenzhen)Co.,Lt OUI:001672* ID_OUI_FROM_DATABASE=Zenway enterprise ltd OUI:00166C* ID_OUI_FROM_DATABASE=Samsung Electonics Digital Video System Division OUI:001666* ID_OUI_FROM_DATABASE=Quantier Communication Inc. OUI:00165F* ID_OUI_FROM_DATABASE=Fairmount Automation OUI:00165A* ID_OUI_FROM_DATABASE=Harman Specialty Group OUI:001653* ID_OUI_FROM_DATABASE=LEGO System A/S IE Electronics Division OUI:0016DF* ID_OUI_FROM_DATABASE=Lundinova AB OUI:0016DA* ID_OUI_FROM_DATABASE=Futronic Technology Co. Ltd. OUI:0016D5* ID_OUI_FROM_DATABASE=Synccom Co., Ltd OUI:0016C9* ID_OUI_FROM_DATABASE=NAT Seattle, Inc. OUI:0016D0* ID_OUI_FROM_DATABASE=ATech elektronika d.o.o. OUI:0016BD* ID_OUI_FROM_DATABASE=ATI Industrial Automation OUI:0016C2* ID_OUI_FROM_DATABASE=Avtec Systems Inc OUI:0016BB* ID_OUI_FROM_DATABASE=Law-Chain Computer Technology Co Ltd OUI:0016AA* ID_OUI_FROM_DATABASE=Kei Communication Technology Inc. OUI:0016AF* ID_OUI_FROM_DATABASE=Shenzhen Union Networks Equipment Co.,Ltd. OUI:00162A* ID_OUI_FROM_DATABASE=Antik computers & communications s.r.o. OUI:001623* ID_OUI_FROM_DATABASE=Interval Media OUI:001617* ID_OUI_FROM_DATABASE=MSI OUI:00161E* ID_OUI_FROM_DATABASE=Woojinnet OUI:00160D* ID_OUI_FROM_DATABASE=Be Here Corporation OUI:001606* ID_OUI_FROM_DATABASE=Ideal Industries OUI:0015FA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0015F5* ID_OUI_FROM_DATABASE=Sustainable Energy Systems OUI:0015F4* ID_OUI_FROM_DATABASE=Eventide OUI:001705* ID_OUI_FROM_DATABASE=Methode Electronics OUI:00170A* ID_OUI_FROM_DATABASE=INEW DIGITAL COMPANY OUI:0016F9* ID_OUI_FROM_DATABASE=CETRTA POT, d.o.o., Kranj OUI:0016F2* ID_OUI_FROM_DATABASE=Dmobile System Co., Ltd. OUI:0016F7* ID_OUI_FROM_DATABASE=L-3 Communications, Aviation Recorders OUI:0016E6* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:00164C* ID_OUI_FROM_DATABASE=PLANET INT Co., Ltd OUI:001647* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001642* ID_OUI_FROM_DATABASE=Pangolin OUI:00163D* ID_OUI_FROM_DATABASE=Tsinghua Tongfang Legend Silicon Tech. Co., Ltd. OUI:001636* ID_OUI_FROM_DATABASE=Quanta Computer Inc. OUI:001631* ID_OUI_FROM_DATABASE=Xteam OUI:00162F* ID_OUI_FROM_DATABASE=Geutebrück GmbH OUI:001630* ID_OUI_FROM_DATABASE=Vativ Technologies OUI:0016A5* ID_OUI_FROM_DATABASE=Tandberg Storage ASA OUI:001699* ID_OUI_FROM_DATABASE=Tonic DVB Marketing Ltd OUI:0016A0* ID_OUI_FROM_DATABASE=Auto-Maskin OUI:001692* ID_OUI_FROM_DATABASE=Scientific-Atlanta, Inc. OUI:001694* ID_OUI_FROM_DATABASE=Sennheiser Communications A/S OUI:00168D* ID_OUI_FROM_DATABASE=KORWIN CO., Ltd. OUI:001686* ID_OUI_FROM_DATABASE=Karl Storz Imaging OUI:0015EE* ID_OUI_FROM_DATABASE=Omnex Control Systems OUI:0015F3* ID_OUI_FROM_DATABASE=PELTOR AB OUI:0015E7* ID_OUI_FROM_DATABASE=Quantec Tontechnik OUI:0015E2* ID_OUI_FROM_DATABASE=Dr.Ing. Herbert Knauer GmbH OUI:0015DD* ID_OUI_FROM_DATABASE=IP Control Systems Ltd. OUI:0015D8* ID_OUI_FROM_DATABASE=Interlink Electronics OUI:0015CA* ID_OUI_FROM_DATABASE=TeraRecon, Inc. OUI:0015BC* ID_OUI_FROM_DATABASE=Develco OUI:0015B5* ID_OUI_FROM_DATABASE=CI Network Corp. OUI:0015B0* ID_OUI_FROM_DATABASE=AUTOTELENET CO.,LTD OUI:0015AB* ID_OUI_FROM_DATABASE=PRO CO SOUND INC OUI:0015A6* ID_OUI_FROM_DATABASE=Digital Electronics Products Ltd. OUI:00159F* ID_OUI_FROM_DATABASE=Terascala, Inc. OUI:001598* ID_OUI_FROM_DATABASE=Kolektor group OUI:001727* ID_OUI_FROM_DATABASE=Thermo Ramsey Italia s.r.l. OUI:001722* ID_OUI_FROM_DATABASE=Hanazeder Electronic GmbH OUI:00171B* ID_OUI_FROM_DATABASE=Innovation Lab Corp. OUI:001714* ID_OUI_FROM_DATABASE=BR Controls Nederland bv OUI:001716* ID_OUI_FROM_DATABASE=Qno Technology Inc. OUI:00170F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0014AA* ID_OUI_FROM_DATABASE=Ashly Audio, Inc. OUI:00149D* ID_OUI_FROM_DATABASE=Sound ID Inc. OUI:001498* ID_OUI_FROM_DATABASE=Viking Design Technology OUI:00148A* ID_OUI_FROM_DATABASE=Elin Ebg Traction Gmbh OUI:001491* ID_OUI_FROM_DATABASE=Daniels Electronics Ltd. dbo Codan Rado Communications OUI:001485* ID_OUI_FROM_DATABASE=Giga-Byte OUI:00147E* ID_OUI_FROM_DATABASE=InnerWireless OUI:001478* ID_OUI_FROM_DATABASE=ShenZhen TP-LINK Technologies Co., Ltd. OUI:001532* ID_OUI_FROM_DATABASE=Consumer Technologies Group, LLC OUI:001539* ID_OUI_FROM_DATABASE=Technodrive srl OUI:00152B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00152D* ID_OUI_FROM_DATABASE=TenX Networks, LLC OUI:00152C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00151F* ID_OUI_FROM_DATABASE=Multivision Intelligent Surveillance (Hong Kong) Ltd OUI:001526* ID_OUI_FROM_DATABASE=Remote Technologies Inc OUI:00151A* ID_OUI_FROM_DATABASE=Hunter Engineering Company OUI:001515* ID_OUI_FROM_DATABASE=Leipold+Co.GmbH OUI:001510* ID_OUI_FROM_DATABASE=Techsphere Co., Ltd OUI:001502* ID_OUI_FROM_DATABASE=BETA tech OUI:001509* ID_OUI_FROM_DATABASE=Plus Technology Co., Ltd OUI:00144E* ID_OUI_FROM_DATABASE=SRISA OUI:001442* ID_OUI_FROM_DATABASE=ATTO CORPORATION OUI:001449* ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. OUI:00143D* ID_OUI_FROM_DATABASE=Aevoe Inc. OUI:00143C* ID_OUI_FROM_DATABASE=Rheinmetall Canada Inc. OUI:00143B* ID_OUI_FROM_DATABASE=Sensovation AG OUI:001436* ID_OUI_FROM_DATABASE=Qwerty Elektronik AB OUI:001423* ID_OUI_FROM_DATABASE=J-S Co. NEUROCOM OUI:001593* ID_OUI_FROM_DATABASE=U4EA Technologies Inc. OUI:00158C* ID_OUI_FROM_DATABASE=Liab ApS OUI:001586* ID_OUI_FROM_DATABASE=Xiamen Overseas Chinese Electronic Co., Ltd. OUI:001585* ID_OUI_FROM_DATABASE=Aonvision Technolopy Corp. OUI:001587* ID_OUI_FROM_DATABASE=Takenaka Seisakusho Co.,Ltd OUI:001580* ID_OUI_FROM_DATABASE=U-WAY CORPORATION OUI:00157B* ID_OUI_FROM_DATABASE=Leuze electronic GmbH + Co. KG OUI:001576* ID_OUI_FROM_DATABASE=LABiTec - Labor Biomedical Technologies GmbH OUI:00156A* ID_OUI_FROM_DATABASE=DG2L Technologies Pvt. Ltd. OUI:00156F* ID_OUI_FROM_DATABASE=Xiranet Communications GmbH OUI:001563* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0014FD* ID_OUI_FROM_DATABASE=Thecus Technology Corp. OUI:0014EF* ID_OUI_FROM_DATABASE=TZero Technologies, Inc. OUI:0014F1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0014F0* ID_OUI_FROM_DATABASE=Business Security OL AB OUI:0014EA* ID_OUI_FROM_DATABASE=S Digm Inc. (Safe Paradigm Inc.) OUI:0014E5* ID_OUI_FROM_DATABASE=Alticast OUI:0014E6* ID_OUI_FROM_DATABASE=AIM Infrarotmodule GmbH OUI:0014E0* ID_OUI_FROM_DATABASE=LET'S Corporation OUI:0014D4* ID_OUI_FROM_DATABASE=K Technology Corporation OUI:0014D9* ID_OUI_FROM_DATABASE=IP Fabrics, Inc. OUI:0014CD* ID_OUI_FROM_DATABASE=DigitalZone Co., Ltd. OUI:0014C1* ID_OUI_FROM_DATABASE=U.S. Robotics Corporation OUI:0014C6* ID_OUI_FROM_DATABASE=Quixant Ltd OUI:0014BA* ID_OUI_FROM_DATABASE=Carvers SA de CV OUI:0014B5* ID_OUI_FROM_DATABASE=PHYSIOMETRIX,INC OUI:0014AB* ID_OUI_FROM_DATABASE=Senhai Electronic Technology Co., Ltd. OUI:0014B0* ID_OUI_FROM_DATABASE=Naeil Community OUI:0014B4* ID_OUI_FROM_DATABASE=General Dynamics United Kingdom Ltd OUI:0014A9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001557* ID_OUI_FROM_DATABASE=Olivetti OUI:00155C* ID_OUI_FROM_DATABASE=Dresser Wayne OUI:00154B* ID_OUI_FROM_DATABASE=Wonde Proud Technology Co., Ltd OUI:001550* ID_OUI_FROM_DATABASE=Nits Technology Inc OUI:001545* ID_OUI_FROM_DATABASE=SEECODE Co., Ltd. OUI:00153E* ID_OUI_FROM_DATABASE=Q-Matic Sweden AB OUI:001477* ID_OUI_FROM_DATABASE=Nertec Inc. OUI:001472* ID_OUI_FROM_DATABASE=China Broadband Wireless IP Standard Group OUI:001466* ID_OUI_FROM_DATABASE=Kleinhenz Elektronik GmbH OUI:00146B* ID_OUI_FROM_DATABASE=Anagran, Inc. OUI:00145F* ID_OUI_FROM_DATABASE=ADITEC CO. LTD OUI:001458* ID_OUI_FROM_DATABASE=HS Automatic ApS OUI:001453* ID_OUI_FROM_DATABASE=ADVANTECH TECHNOLOGIES CO.,LTD OUI:001419* ID_OUI_FROM_DATABASE=SIDSA OUI:001412* ID_OUI_FROM_DATABASE=S-TEC electronics AG OUI:00140D* ID_OUI_FROM_DATABASE=Nortel OUI:001409* ID_OUI_FROM_DATABASE=MAGNETI MARELLI S.E. S.p.A. OUI:00140A* ID_OUI_FROM_DATABASE=WEPIO Co., Ltd. OUI:0013FD* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0013F8* ID_OUI_FROM_DATABASE=Dex Security Solutions OUI:0013F1* ID_OUI_FROM_DATABASE=AMOD Technology Co., Ltd. OUI:00135C* ID_OUI_FROM_DATABASE=OnSite Systems, Inc. OUI:001355* ID_OUI_FROM_DATABASE=TOMEN Cyber-business Solutions, Inc. OUI:001356* ID_OUI_FROM_DATABASE=FLIR Radiation Inc OUI:001350* ID_OUI_FROM_DATABASE=Silver Spring Networks, Inc OUI:001344* ID_OUI_FROM_DATABASE=Fargo Electronics Inc. OUI:001349* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:001343* ID_OUI_FROM_DATABASE=Matsushita Electronic Components (Europe) GmbH OUI:00133D* ID_OUI_FROM_DATABASE=Micro Memory Curtiss Wright Co OUI:00132A* ID_OUI_FROM_DATABASE=Sitronics Telecom Solutions OUI:001331* ID_OUI_FROM_DATABASE=CellPoint Connect OUI:001336* ID_OUI_FROM_DATABASE=Tianjin 712 Communication Broadcasting co., ltd. OUI:001284* ID_OUI_FROM_DATABASE=Lab33 Srl OUI:00127E* ID_OUI_FROM_DATABASE=Digital Lifestyles Group, Inc. OUI:001277* ID_OUI_FROM_DATABASE=Korenix Technologies Co., Ltd. OUI:001272* ID_OUI_FROM_DATABASE=Redux Communications Ltd. OUI:001271* ID_OUI_FROM_DATABASE=Measurement Computing Corp OUI:00126B* ID_OUI_FROM_DATABASE=Ascalade Communications Limited OUI:001264* ID_OUI_FROM_DATABASE=daum electronic gmbh OUI:00125A* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:0012FA* ID_OUI_FROM_DATABASE=THX LTD OUI:001301* ID_OUI_FROM_DATABASE=IronGate S.L. OUI:001307* ID_OUI_FROM_DATABASE=Paravirtual Corporation OUI:0012F5* ID_OUI_FROM_DATABASE=Imarda New Zealand Limited OUI:0012EB* ID_OUI_FROM_DATABASE=PDH Solutions, LLC OUI:0012DE* ID_OUI_FROM_DATABASE=Radio Components Sweden AB OUI:0012DD* ID_OUI_FROM_DATABASE=Shengqu Information Technology (Shanghai) Co., Ltd. OUI:0012E4* ID_OUI_FROM_DATABASE=ZIEHL industrie-electronik GmbH + Co KG OUI:0012D8* ID_OUI_FROM_DATABASE=International Games System Co., Ltd. OUI:0013B6* ID_OUI_FROM_DATABASE=Sling Media, Inc. OUI:0013AF* ID_OUI_FROM_DATABASE=NUMA Technology,Inc. OUI:0013B0* ID_OUI_FROM_DATABASE=Jablotron OUI:0013AA* ID_OUI_FROM_DATABASE=ALS & TEC Ltd. OUI:0013A3* ID_OUI_FROM_DATABASE=Siemens Com CPE Devices OUI:00139E* ID_OUI_FROM_DATABASE=Ciara Technologies Inc. OUI:00139D* ID_OUI_FROM_DATABASE=Marvell Hispana S.L. OUI:0012A8* ID_OUI_FROM_DATABASE=intec GmbH OUI:0012A2* ID_OUI_FROM_DATABASE=VITA OUI:0012A1* ID_OUI_FROM_DATABASE=BluePacket Communications Co., Ltd. OUI:00129C* ID_OUI_FROM_DATABASE=Yulinet OUI:001290* ID_OUI_FROM_DATABASE=KYOWA Electric & Machinery Corp. OUI:001295* ID_OUI_FROM_DATABASE=Aiware Inc. OUI:001283* ID_OUI_FROM_DATABASE=Nortel Networks OUI:00138B* ID_OUI_FROM_DATABASE=Phantom Technologies LLC OUI:001390* ID_OUI_FROM_DATABASE=Termtek Computer Co., Ltd OUI:001376* ID_OUI_FROM_DATABASE=Tabor Electronics Ltd. OUI:00137B* ID_OUI_FROM_DATABASE=Movon Corporation OUI:001382* ID_OUI_FROM_DATABASE=Cetacea Networks Corporation OUI:001387* ID_OUI_FROM_DATABASE=27M Technologies AB OUI:00136F* ID_OUI_FROM_DATABASE=PacketMotion, Inc. OUI:001375* ID_OUI_FROM_DATABASE=American Security Products Co. OUI:001363* ID_OUI_FROM_DATABASE=Verascape, Inc. OUI:001368* ID_OUI_FROM_DATABASE=Saab Danmark A/S OUI:0013F7* ID_OUI_FROM_DATABASE=SMC Networks, Inc. OUI:0013E7* ID_OUI_FROM_DATABASE=Halcro OUI:0013DB* ID_OUI_FROM_DATABASE=SHOEI Electric Co.,Ltd OUI:0013CC* ID_OUI_FROM_DATABASE=Tall Maple Systems OUI:0013C7* ID_OUI_FROM_DATABASE=IONOS Co.,Ltd. OUI:0013C0* ID_OUI_FROM_DATABASE=Trix Tecnologia Ltda. OUI:0012CB* ID_OUI_FROM_DATABASE=CSS Inc. OUI:0012C5* ID_OUI_FROM_DATABASE=V-Show Technology (China) Co.,Ltd OUI:0012CC* ID_OUI_FROM_DATABASE=Bitatek CO., LTD OUI:0012B4* ID_OUI_FROM_DATABASE=Work Microwave GmbH OUI:0012BB* ID_OUI_FROM_DATABASE=Telecommunications Industry Association TR-41 Committee OUI:0012AF* ID_OUI_FROM_DATABASE=ELPRO Technologies OUI:001324* ID_OUI_FROM_DATABASE=Schneider Electric Ultra Terminal OUI:001314* ID_OUI_FROM_DATABASE=Asiamajor Inc. OUI:001319* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00131A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00130D* ID_OUI_FROM_DATABASE=GALILEO AVIONICA OUI:001308* ID_OUI_FROM_DATABASE=Nuvera Fuel Cells OUI:001181* ID_OUI_FROM_DATABASE=InterEnergy Co.Ltd, OUI:00117B* ID_OUI_FROM_DATABASE=Büchi Labortechnik AG OUI:00116F* ID_OUI_FROM_DATABASE=Netforyou Co., LTD. OUI:001168* ID_OUI_FROM_DATABASE=HomeLogic LLC OUI:00115E* ID_OUI_FROM_DATABASE=ProMinent Dosiertechnik GmbH OUI:001157* ID_OUI_FROM_DATABASE=Oki Electric Industry Co., Ltd. OUI:001158* ID_OUI_FROM_DATABASE=Nortel Networks OUI:001152* ID_OUI_FROM_DATABASE=Eidsvoll Electronics AS OUI:0011A4* ID_OUI_FROM_DATABASE=JStream Technologies Inc. OUI:001198* ID_OUI_FROM_DATABASE=Prism Media Products Limited OUI:00119D* ID_OUI_FROM_DATABASE=Diginfo Technology Corporation OUI:00119E* ID_OUI_FROM_DATABASE=Solectron Brazil OUI:00118E* ID_OUI_FROM_DATABASE=Halytech Mace OUI:001193* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001187* ID_OUI_FROM_DATABASE=Category Solutions, Inc OUI:001182* ID_OUI_FROM_DATABASE=IMI Norgren Ltd OUI:0011FF* ID_OUI_FROM_DATABASE=Digitro Tecnologia Ltda OUI:0011FA* ID_OUI_FROM_DATABASE=Rane Corporation OUI:0011F9* ID_OUI_FROM_DATABASE=Nortel Networks OUI:0011F0* ID_OUI_FROM_DATABASE=Wideful Limited OUI:0011EF* ID_OUI_FROM_DATABASE=Conitec Datensysteme GmbH OUI:0011E9* ID_OUI_FROM_DATABASE=STARNEX CO., LTD. OUI:0011DD* ID_OUI_FROM_DATABASE=FROMUS TEC. Co., Ltd. OUI:0011E2* ID_OUI_FROM_DATABASE=Hua Jung Components Co., Ltd. OUI:000FFA* ID_OUI_FROM_DATABASE=Optinel Systems, Inc. OUI:000FFF* ID_OUI_FROM_DATABASE=Control4 OUI:000FF1* ID_OUI_FROM_DATABASE=nex-G Systems Pte.Ltd OUI:000FE4* ID_OUI_FROM_DATABASE=Pantech Co.,Ltd OUI:000FEA* ID_OUI_FROM_DATABASE=Giga-Byte Technology Co.,LTD. OUI:000FE3* ID_OUI_FROM_DATABASE=Damm Cellular Systems A/S OUI:000FD7* ID_OUI_FROM_DATABASE=Harman Music Group OUI:001235* ID_OUI_FROM_DATABASE=Andrew Corporation OUI:00122B* ID_OUI_FROM_DATABASE=Virbiage Pty Ltd OUI:001212* ID_OUI_FROM_DATABASE=PLUS Corporation OUI:001219* ID_OUI_FROM_DATABASE=Ahead Communication Systems Inc OUI:001206* ID_OUI_FROM_DATABASE=iQuest (NZ) Ltd OUI:00120B* ID_OUI_FROM_DATABASE=Chinasys Technologies Limited OUI:00120C* ID_OUI_FROM_DATABASE=CE-Infosys Pte Ltd OUI:001130* ID_OUI_FROM_DATABASE=Allied Telesis (Hong Kong) Ltd. OUI:00111E* ID_OUI_FROM_DATABASE=EPSG (Ethernet Powerlink Standardization Group) OUI:00111F* ID_OUI_FROM_DATABASE=Doremi Labs, Inc. OUI:001112* ID_OUI_FROM_DATABASE=Honeywell CMSS OUI:001118* ID_OUI_FROM_DATABASE=BLX IC Design Corp., Ltd. OUI:001105* ID_OUI_FROM_DATABASE=Sunplus Technology Co., Ltd. OUI:00110C* ID_OUI_FROM_DATABASE=Atmark Techno, Inc. OUI:000FF9* ID_OUI_FROM_DATABASE=Valcretec, Inc. OUI:0011CF* ID_OUI_FROM_DATABASE=Thrane & Thrane A/S OUI:0011D6* ID_OUI_FROM_DATABASE=HandEra, Inc. OUI:0011D0* ID_OUI_FROM_DATABASE=Tandberg Data ASA OUI:0011CA* ID_OUI_FROM_DATABASE=Long Range Systems, Inc. OUI:0011C3* ID_OUI_FROM_DATABASE=Transceiving System Technology Corporation OUI:0011B7* ID_OUI_FROM_DATABASE=Octalix B.V. OUI:0011BE* ID_OUI_FROM_DATABASE=AGP Telecom Co. Ltd OUI:0011BD* ID_OUI_FROM_DATABASE=Bombardier Transportation OUI:0011AB* ID_OUI_FROM_DATABASE=TRUSTABLE TECHNOLOGY CO.,LTD. OUI:0011B0* ID_OUI_FROM_DATABASE=Fortelink Inc. OUI:00125F* ID_OUI_FROM_DATABASE=AWIND Inc. OUI:001255* ID_OUI_FROM_DATABASE=NetEffect Incorporated OUI:00124E* ID_OUI_FROM_DATABASE=XAC AUTOMATION CORP. OUI:001247* ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. OUI:001248* ID_OUI_FROM_DATABASE=EMC Corporation (Kashya) OUI:001242* ID_OUI_FROM_DATABASE=Millennial Net OUI:001236* ID_OUI_FROM_DATABASE=ConSentry Networks OUI:00123B* ID_OUI_FROM_DATABASE=KeRo Systems ApS OUI:00122F* ID_OUI_FROM_DATABASE=Sanei Electric Inc. OUI:00114F* ID_OUI_FROM_DATABASE=US Digital Television, Inc OUI:001149* ID_OUI_FROM_DATABASE=Proliphix Inc. OUI:001142* ID_OUI_FROM_DATABASE=e-SMARTCOM INC. OUI:00113D* ID_OUI_FROM_DATABASE=KN SOLTEC CO.,LTD. OUI:00113C* ID_OUI_FROM_DATABASE=Micronas GmbH OUI:001136* ID_OUI_FROM_DATABASE=Goodrich Sensor Systems OUI:00112C* ID_OUI_FROM_DATABASE=IZT GmbH OUI:000F77* ID_OUI_FROM_DATABASE=DENTUM CO.,LTD OUI:000F71* ID_OUI_FROM_DATABASE=Sanmei Electronics Co.,Ltd OUI:000F78* ID_OUI_FROM_DATABASE=Datacap Systems Inc OUI:000F6A* ID_OUI_FROM_DATABASE=Nortel Networks OUI:000F65* ID_OUI_FROM_DATABASE=icube Corp. OUI:000F5E* ID_OUI_FROM_DATABASE=Veo OUI:000F58* ID_OUI_FROM_DATABASE=Adder Technology Limited OUI:000F52* ID_OUI_FROM_DATABASE=YORK Refrigeration, Marine & Controls OUI:000F57* ID_OUI_FROM_DATABASE=CABLELOGIC Co., Ltd. OUI:000F45* ID_OUI_FROM_DATABASE=Stretch, Inc. OUI:000F46* ID_OUI_FROM_DATABASE=SINAR AG OUI:000F4B* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:000F37* ID_OUI_FROM_DATABASE=Xambala Incorporated OUI:000F3F* ID_OUI_FROM_DATABASE=Big Bear Networks OUI:000F3B* ID_OUI_FROM_DATABASE=Fuji System Machines Co., Ltd. OUI:000F31* ID_OUI_FROM_DATABASE=Allied Vision Technologies Canada Inc OUI:000F32* ID_OUI_FROM_DATABASE=Lootom Telcovideo Network Wuxi Co Ltd OUI:000F2B* ID_OUI_FROM_DATABASE=GREENBELL SYSTEMS OUI:000E93* ID_OUI_FROM_DATABASE=Milénio 3 Sistemas Electrónicos, Lda. OUI:000E8C* ID_OUI_FROM_DATABASE=Siemens AG A&D ET OUI:000E86* ID_OUI_FROM_DATABASE=Alcatel North America OUI:000E80* ID_OUI_FROM_DATABASE=Thomson Technology Inc OUI:000E85* ID_OUI_FROM_DATABASE=Catalyst Enterprises, Inc. OUI:000E74* ID_OUI_FROM_DATABASE=Solar Telecom. Tech OUI:000E79* ID_OUI_FROM_DATABASE=Ample Communications Inc. OUI:000E71* ID_OUI_FROM_DATABASE=Gemstar Technology Development Ltd. OUI:000E6C* ID_OUI_FROM_DATABASE=Device Drivers Limited OUI:000EB8* ID_OUI_FROM_DATABASE=Iiga co.,Ltd OUI:000EB7* ID_OUI_FROM_DATABASE=Knovative, Inc. OUI:000EBE* ID_OUI_FROM_DATABASE=B&B Electronics Manufacturing Co. OUI:000EB2* ID_OUI_FROM_DATABASE=Micro-Research Finland Oy OUI:000EAB* ID_OUI_FROM_DATABASE=Cray Inc OUI:000EA5* ID_OUI_FROM_DATABASE=BLIP Systems OUI:000E9F* ID_OUI_FROM_DATABASE=TEMIC SDS GmbH OUI:000E98* ID_OUI_FROM_DATABASE=HME Clear-Com LTD. OUI:000F24* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000F12* ID_OUI_FROM_DATABASE=Panasonic Europe Ltd. OUI:000F18* ID_OUI_FROM_DATABASE=Industrial Control Systems OUI:000F11* ID_OUI_FROM_DATABASE=Prodrive B.V. OUI:000F0C* ID_OUI_FROM_DATABASE=SYNCHRONIC ENGINEERING OUI:000EFF* ID_OUI_FROM_DATABASE=Megasolution,Inc. OUI:000F00* ID_OUI_FROM_DATABASE=Legra Systems, Inc. OUI:000F05* ID_OUI_FROM_DATABASE=3B SYSTEM INC. OUI:000EF9* ID_OUI_FROM_DATABASE=REA Elektronik GmbH OUI:000FAC* ID_OUI_FROM_DATABASE=IEEE 802.11 OUI:000F9C* ID_OUI_FROM_DATABASE=Panduit Corp OUI:000FA0* ID_OUI_FROM_DATABASE=CANON KOREA BUSINESS SOLUTIONS INC. OUI:000F97* ID_OUI_FROM_DATABASE=Avanex Corporation OUI:000F8A* ID_OUI_FROM_DATABASE=WideView OUI:000F89* ID_OUI_FROM_DATABASE=Winnertec System Co., Ltd. OUI:000F90* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000F7D* ID_OUI_FROM_DATABASE=Xirrus OUI:000F84* ID_OUI_FROM_DATABASE=Astute Networks, Inc. OUI:000FD1* ID_OUI_FROM_DATABASE=Applied Wireless Identifications Group, Inc. OUI:000FD2* ID_OUI_FROM_DATABASE=EWA Technologies, Inc. OUI:000FC4* ID_OUI_FROM_DATABASE=NST co.,LTD. OUI:000FCB* ID_OUI_FROM_DATABASE=3Com Ltd OUI:000FBF* ID_OUI_FROM_DATABASE=DGT Sp. z o.o. OUI:000FB8* ID_OUI_FROM_DATABASE=CallURL Inc. OUI:000FB2* ID_OUI_FROM_DATABASE=Broadband Pacenet (India) Pvt. Ltd. OUI:000FA5* ID_OUI_FROM_DATABASE=BWA Technology GmbH OUI:000FB1* ID_OUI_FROM_DATABASE=Cognio Inc. OUI:000E65* ID_OUI_FROM_DATABASE=TransCore OUI:000E5F* ID_OUI_FROM_DATABASE=activ-net GmbH & Co. KG OUI:000E60* ID_OUI_FROM_DATABASE=360SUN Digital Broadband Corporation OUI:000E52* ID_OUI_FROM_DATABASE=Optium Corporation OUI:000E46* ID_OUI_FROM_DATABASE=Niigata Seimitsu Co.,Ltd. OUI:000E4D* ID_OUI_FROM_DATABASE=Numesa Inc. OUI:000E40* ID_OUI_FROM_DATABASE=Nortel Networks OUI:000E3F* ID_OUI_FROM_DATABASE=Soronti, Inc. OUI:000EF2* ID_OUI_FROM_DATABASE=Infinico Corporation OUI:000EE0* ID_OUI_FROM_DATABASE=Mcharge OUI:000EDF* ID_OUI_FROM_DATABASE=PLX Technology OUI:000EE6* ID_OUI_FROM_DATABASE=Adimos Systems LTD OUI:000ECA* ID_OUI_FROM_DATABASE=WTSS Inc OUI:000ED1* ID_OUI_FROM_DATABASE=Osaka Micro Computer. OUI:000EDA* ID_OUI_FROM_DATABASE=C-TECH UNITED CORP. OUI:000ED6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000EC5* ID_OUI_FROM_DATABASE=Digital Multitools Inc OUI:000DB2* ID_OUI_FROM_DATABASE=Ammasso, Inc. OUI:000DAD* ID_OUI_FROM_DATABASE=Dataprobe, Inc. OUI:000D9E* ID_OUI_FROM_DATABASE=TOKUDEN OHIZUMI SEISAKUSYO Co.,Ltd. OUI:000DA5* ID_OUI_FROM_DATABASE=Fabric7 Systems, Inc OUI:000D99* ID_OUI_FROM_DATABASE=Orbital Sciences Corp.; Launch Systems Group OUI:000D8C* ID_OUI_FROM_DATABASE=Shanghai Wedone Digital Ltd. CO. OUI:000D8B* ID_OUI_FROM_DATABASE=T&D Corporation OUI:000D85* ID_OUI_FROM_DATABASE=Tapwave, Inc. OUI:000D86* ID_OUI_FROM_DATABASE=Huber + Suhner AG OUI:000DD8* ID_OUI_FROM_DATABASE=BBN OUI:000DCC* ID_OUI_FROM_DATABASE=NEOSMART Corp. OUI:000DBF* ID_OUI_FROM_DATABASE=TekTone Sound & Signal Mfg., Inc. OUI:000DC0* ID_OUI_FROM_DATABASE=Spagat AS OUI:000DC5* ID_OUI_FROM_DATABASE=EchoStar Global B.V. OUI:000DB9* ID_OUI_FROM_DATABASE=PC Engines GmbH OUI:000D4C* ID_OUI_FROM_DATABASE=Outline Electronics Ltd. OUI:000D53* ID_OUI_FROM_DATABASE=Beijing 5w Communication Corp. OUI:000D3F* ID_OUI_FROM_DATABASE=VTI Instruments Corporation OUI:000D44* ID_OUI_FROM_DATABASE=Audio BU - Logitech OUI:000D38* ID_OUI_FROM_DATABASE=NISSIN INC. OUI:000D32* ID_OUI_FROM_DATABASE=DispenseSource, Inc. OUI:000D31* ID_OUI_FROM_DATABASE=Compellent Technologies, Inc. OUI:000E04* ID_OUI_FROM_DATABASE=CMA/Microdialysis AB OUI:000DF7* ID_OUI_FROM_DATABASE=Space Dynamics Lab OUI:000DFE* ID_OUI_FROM_DATABASE=Hauppauge Computer Works, Inc. OUI:000DF1* ID_OUI_FROM_DATABASE=IONIX INC. OUI:000DEB* ID_OUI_FROM_DATABASE=CompXs Limited OUI:000DF2* ID_OUI_FROM_DATABASE=Private OUI:000DE4* ID_OUI_FROM_DATABASE=DIGINICS, Inc. OUI:000DDF* ID_OUI_FROM_DATABASE=Japan Image & Network Inc. OUI:000DD2* ID_OUI_FROM_DATABASE=Simrad Optronics ASA OUI:000DD1* ID_OUI_FROM_DATABASE=Stryker Corporation OUI:000D2C* ID_OUI_FROM_DATABASE=Patapsco Designs Ltd OUI:000D25* ID_OUI_FROM_DATABASE=SANDEN CORPORATION OUI:000D1F* ID_OUI_FROM_DATABASE=AV Digital OUI:000D19* ID_OUI_FROM_DATABASE=ROBE Show lighting OUI:000D20* ID_OUI_FROM_DATABASE=ASAHIKASEI TECHNOSYSTEM CO.,LTD. OUI:000D0D* ID_OUI_FROM_DATABASE=ITSupported, LLC OUI:000D12* ID_OUI_FROM_DATABASE=AXELL Corporation OUI:000D00* ID_OUI_FROM_DATABASE=Seaway Networks Inc. OUI:000D06* ID_OUI_FROM_DATABASE=Compulogic Limited OUI:000CD1* ID_OUI_FROM_DATABASE=SFOM Technology Corp. OUI:000CD6* ID_OUI_FROM_DATABASE=PARTNER TECH OUI:000CDD* ID_OUI_FROM_DATABASE=AOS technologies AG OUI:000CCA* ID_OUI_FROM_DATABASE=HGST a Western Digital Company OUI:000CC4* ID_OUI_FROM_DATABASE=Tiptel AG OUI:000CB1* ID_OUI_FROM_DATABASE=Salland Engineering (Europe) BV OUI:000E37* ID_OUI_FROM_DATABASE=Harms & Wende GmbH & Co.KG OUI:000E38* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000E31* ID_OUI_FROM_DATABASE=Olympus Soft Imaging Solutions GmbH OUI:000E2A* ID_OUI_FROM_DATABASE=Private OUI:000E1E* ID_OUI_FROM_DATABASE=QLogic Corporation OUI:000E25* ID_OUI_FROM_DATABASE=Hannae Technology Co., Ltd OUI:000E18* ID_OUI_FROM_DATABASE=MyA Technology OUI:000E17* ID_OUI_FROM_DATABASE=Private OUI:000E0E* ID_OUI_FROM_DATABASE=ESA elettronica S.P.A. OUI:000E0A* ID_OUI_FROM_DATABASE=SAKUMA DESIGN OFFICE OUI:000E12* ID_OUI_FROM_DATABASE=Adaptive Micro Systems Inc. OUI:000D7E* ID_OUI_FROM_DATABASE=Axiowave Networks, Inc. OUI:000D78* ID_OUI_FROM_DATABASE=Engineering & Security OUI:000D77* ID_OUI_FROM_DATABASE=FalconStor Software OUI:000D6B* ID_OUI_FROM_DATABASE=Mita-Teknik A/S OUI:000D65* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000D5F* ID_OUI_FROM_DATABASE=Minds Inc OUI:000D66* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000D58* ID_OUI_FROM_DATABASE=Private OUI:000CFA* ID_OUI_FROM_DATABASE=Digital Systems Corp OUI:000CFF* ID_OUI_FROM_DATABASE=MRO-TEK LIMITED OUI:000CED* ID_OUI_FROM_DATABASE=Real Digital Media OUI:000CEE* ID_OUI_FROM_DATABASE=jp-embedded OUI:000CF3* ID_OUI_FROM_DATABASE=CALL IMAGE SA OUI:000CE7* ID_OUI_FROM_DATABASE=MediaTek Inc. OUI:000CE3* ID_OUI_FROM_DATABASE=Option International N.V. OUI:000B8F* ID_OUI_FROM_DATABASE=AKITA ELECTRONICS SYSTEMS CO.,LTD. OUI:000B89* ID_OUI_FROM_DATABASE=Top Global Technology, Ltd. OUI:000B8E* ID_OUI_FROM_DATABASE=Ascent Corporation OUI:000B90* ID_OUI_FROM_DATABASE=ADVA Optical Networking Ltd. OUI:000B7D* ID_OUI_FROM_DATABASE=SOLOMON EXTREME INTERNATIONAL LTD. OUI:000B82* ID_OUI_FROM_DATABASE=Grandstream Networks, Inc. OUI:000B6F* ID_OUI_FROM_DATABASE=Media Streaming Networks Inc OUI:000B76* ID_OUI_FROM_DATABASE=ET&T Technology Co. Ltd. OUI:000B5E* ID_OUI_FROM_DATABASE=Audio Engineering Society Inc. OUI:000B63* ID_OUI_FROM_DATABASE=Kaleidescape OUI:000C7E* ID_OUI_FROM_DATABASE=Tellium Incorporated OUI:000C86* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000C81* ID_OUI_FROM_DATABASE=Schneider Electric (Australia) OUI:000C72* ID_OUI_FROM_DATABASE=Tempearl Industrial Co., Ltd. OUI:000C79* ID_OUI_FROM_DATABASE=Extel Communications P/L OUI:000C66* ID_OUI_FROM_DATABASE=Pronto Networks Inc OUI:000C6B* ID_OUI_FROM_DATABASE=Kurz Industrie-Elektronik GmbH OUI:000C6D* ID_OUI_FROM_DATABASE=Edwards Ltd. OUI:000C4E* ID_OUI_FROM_DATABASE=Winbest Technology CO,LT OUI:000C53* ID_OUI_FROM_DATABASE=Private OUI:000C5A* ID_OUI_FROM_DATABASE=IBSmm Embedded Electronics Consulting OUI:000C5F* ID_OUI_FROM_DATABASE=Avtec, Inc. OUI:000C47* ID_OUI_FROM_DATABASE=SK Teletech(R&D Planning Team) OUI:000C4C* ID_OUI_FROM_DATABASE=Arcor AG&Co. OUI:000C3E* ID_OUI_FROM_DATABASE=Crest Audio OUI:000C37* ID_OUI_FROM_DATABASE=Geomation, Inc. OUI:000C2D* ID_OUI_FROM_DATABASE=FullWave Technology Co., Ltd. OUI:000C1A* ID_OUI_FROM_DATABASE=Quest Technical Solutions Inc. OUI:000B2E* ID_OUI_FROM_DATABASE=Cal-Comp Electronics (Thailand) Public Company Limited Taipe OUI:000B1B* ID_OUI_FROM_DATABASE=Systronix, Inc. OUI:000B20* ID_OUI_FROM_DATABASE=Hirata corporation OUI:000B22* ID_OUI_FROM_DATABASE=Environmental Systems and Services OUI:000B14* ID_OUI_FROM_DATABASE=ViewSonic Corporation OUI:000B0D* ID_OUI_FROM_DATABASE=Air2U, Inc. OUI:000B0F* ID_OUI_FROM_DATABASE=Bosch Rexroth OUI:000B08* ID_OUI_FROM_DATABASE=Pillar Data Systems OUI:000AFC* ID_OUI_FROM_DATABASE=Core Tec Communications, LLC OUI:000B01* ID_OUI_FROM_DATABASE=DAIICHI ELECTRONICS CO., LTD. OUI:000B55* ID_OUI_FROM_DATABASE=ADInstruments OUI:000B5A* ID_OUI_FROM_DATABASE=HyperEdge OUI:000B52* ID_OUI_FROM_DATABASE=JOYMAX ELECTRONICS CO. LTD. OUI:000B4D* ID_OUI_FROM_DATABASE=Emuzed OUI:000B41* ID_OUI_FROM_DATABASE=Ing. Büro Dr. Beutlhauser OUI:000B46* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000B33* ID_OUI_FROM_DATABASE=Vivato Technologies OUI:000B3A* ID_OUI_FROM_DATABASE=QuStream Corporation OUI:000B3F* ID_OUI_FROM_DATABASE=Anthology Solutions Inc. OUI:000B27* ID_OUI_FROM_DATABASE=Scion Corporation OUI:000C1E* ID_OUI_FROM_DATABASE=Global Cache OUI:000C23* ID_OUI_FROM_DATABASE=Beijing Lanchuan Tech. Co., Ltd. OUI:000C0E* ID_OUI_FROM_DATABASE=XtremeSpectrum, Inc. OUI:000C15* ID_OUI_FROM_DATABASE=CyberPower Systems, Inc. OUI:000C09* ID_OUI_FROM_DATABASE=Hitachi IE Systems Co., Ltd OUI:000BF6* ID_OUI_FROM_DATABASE=Nitgen Co., Ltd OUI:000BFB* ID_OUI_FROM_DATABASE=D-NET International Corporation OUI:000C02* ID_OUI_FROM_DATABASE=ABB Oy OUI:000BC7* ID_OUI_FROM_DATABASE=ICET S.p.A. OUI:000BCE* ID_OUI_FROM_DATABASE=Free2move AB OUI:000BC2* ID_OUI_FROM_DATABASE=Corinex Communication Corp. OUI:000BBB* ID_OUI_FROM_DATABASE=Etin Systems Co., Ltd OUI:000BC0* ID_OUI_FROM_DATABASE=China IWNComm Co., Ltd. OUI:000BAF* ID_OUI_FROM_DATABASE=WOOJU COMMUNICATIONS Co,.Ltd OUI:000BB4* ID_OUI_FROM_DATABASE=RDC Semiconductor Inc., OUI:000BA5* ID_OUI_FROM_DATABASE=Quasar Cipta Mandiri, PT OUI:000BAA* ID_OUI_FROM_DATABASE=Aiphone co.,Ltd OUI:000B9E* ID_OUI_FROM_DATABASE=Yasing Technology Corp. OUI:000B95* ID_OUI_FROM_DATABASE=eBet Gaming Systems Pty Ltd OUI:000CB7* ID_OUI_FROM_DATABASE=Nanjing Huazhuo Electronics Co., Ltd. OUI:000CBE* ID_OUI_FROM_DATABASE=Innominate Security Technologies AG OUI:000CC3* ID_OUI_FROM_DATABASE=BeWAN systems OUI:000CB2* ID_OUI_FROM_DATABASE=UNION co., ltd. OUI:000CA5* ID_OUI_FROM_DATABASE=Naman NZ LTd OUI:000CAC* ID_OUI_FROM_DATABASE=Citizen Watch Co., Ltd. OUI:000C94* ID_OUI_FROM_DATABASE=United Electronic Industries, Inc. (EUI) OUI:000C99* ID_OUI_FROM_DATABASE=HITEL LINK Co.,Ltd OUI:000CA0* ID_OUI_FROM_DATABASE=StorCase Technology, Inc. OUI:000C8D* ID_OUI_FROM_DATABASE=MATRIX VISION GmbH OUI:000C92* ID_OUI_FROM_DATABASE=WolfVision Gmbh OUI:000BEA* ID_OUI_FROM_DATABASE=Zultys Technologies OUI:000BEF* ID_OUI_FROM_DATABASE=Code Corporation OUI:000BE3* ID_OUI_FROM_DATABASE=Key Stream Co., Ltd. OUI:000BE8* ID_OUI_FROM_DATABASE=AOIP OUI:000BE9* ID_OUI_FROM_DATABASE=Actel Corporation OUI:000BD7* ID_OUI_FROM_DATABASE=DORMA Time + Access GmbH OUI:000BDC* ID_OUI_FROM_DATABASE=AKCP OUI:000BD3* ID_OUI_FROM_DATABASE=cd3o OUI:000AF0* ID_OUI_FROM_DATABASE=SHIN-OH ELECTRONICS CO., LTD. R&D OUI:000AF5* ID_OUI_FROM_DATABASE=Airgo Networks, Inc. OUI:000AEC* ID_OUI_FROM_DATABASE=Koatsu Gas Kogyo Co., Ltd. OUI:000AE5* ID_OUI_FROM_DATABASE=ScottCare Corporation OUI:000AE7* ID_OUI_FROM_DATABASE=ELIOP S.A. OUI:000AE0* ID_OUI_FROM_DATABASE=Fujitsu Softek OUI:000AC8* ID_OUI_FROM_DATABASE=ZPSYS CO.,LTD. (Planning&Management) OUI:000ACD* ID_OUI_FROM_DATABASE=Sunrich Technology Limited OUI:000AD4* ID_OUI_FROM_DATABASE=CoreBell Systems Inc. OUI:000AC1* ID_OUI_FROM_DATABASE=Futuretel OUI:000AC6* ID_OUI_FROM_DATABASE=Overture Networks. OUI:000994* ID_OUI_FROM_DATABASE=Cronyx Engineering OUI:000999* ID_OUI_FROM_DATABASE=CP GEORGES RENAULT OUI:000987* ID_OUI_FROM_DATABASE=NISHI NIPPON ELECTRIC WIRE & CABLE CO.,LTD. OUI:000988* ID_OUI_FROM_DATABASE=Nudian Electron Co., Ltd. OUI:00098D* ID_OUI_FROM_DATABASE=Velocity Semiconductor OUI:000981* ID_OUI_FROM_DATABASE=Newport Networks OUI:000975* ID_OUI_FROM_DATABASE=fSONA Communications Corporation OUI:00097A* ID_OUI_FROM_DATABASE=Louis Design Labs. OUI:000968* ID_OUI_FROM_DATABASE=TECHNOVENTURE, INC. OUI:000962* ID_OUI_FROM_DATABASE=Sonitor Technologies AS OUI:000967* ID_OUI_FROM_DATABASE=Tachyon, Inc OUI:00096E* ID_OUI_FROM_DATABASE=GIANT ELECTRONICS LTD. OUI:0009C3* ID_OUI_FROM_DATABASE=NETAS OUI:0009B9* ID_OUI_FROM_DATABASE=Action Imaging Solutions OUI:0009BA* ID_OUI_FROM_DATABASE=MAKU Informationstechik GmbH OUI:0009AC* ID_OUI_FROM_DATABASE=LANVOICE OUI:0009B3* ID_OUI_FROM_DATABASE=MCM Systems Ltd OUI:0009A7* ID_OUI_FROM_DATABASE=Bang & Olufsen A/S OUI:00099A* ID_OUI_FROM_DATABASE=ELMO COMPANY, LIMITED OUI:0009A0* ID_OUI_FROM_DATABASE=Microtechno Corporation OUI:000A80* ID_OUI_FROM_DATABASE=Telkonet Inc. OUI:000A82* ID_OUI_FROM_DATABASE=TATSUTA SYSTEM ELECTRONICS CO.,LTD. OUI:000A87* ID_OUI_FROM_DATABASE=Integrated Micromachines Inc. OUI:000A7B* ID_OUI_FROM_DATABASE=Cornelius Consult OUI:000A6D* ID_OUI_FROM_DATABASE=EKS Elektronikservice GmbH OUI:000A6F* ID_OUI_FROM_DATABASE=ZyFLEX Technologies Inc OUI:000A74* ID_OUI_FROM_DATABASE=Manticom Networks Inc. OUI:000A61* ID_OUI_FROM_DATABASE=Cellinx Systems Inc. OUI:000A68* ID_OUI_FROM_DATABASE=SolarFlare Communications, Inc. OUI:000A5C* ID_OUI_FROM_DATABASE=Carel s.p.a. OUI:0009E6* ID_OUI_FROM_DATABASE=Cyber Switching Inc. OUI:0009E0* ID_OUI_FROM_DATABASE=XEMICS S.A. OUI:0009DA* ID_OUI_FROM_DATABASE=Control Module Inc. OUI:0009DF* ID_OUI_FROM_DATABASE=Vestel Komunikasyon Sanayi ve Ticaret A.S. OUI:0009CD* ID_OUI_FROM_DATABASE=HUDSON SOFT CO.,LTD. OUI:0009C7* ID_OUI_FROM_DATABASE=Movistec OUI:0009CE* ID_OUI_FROM_DATABASE=SpaceBridge Semiconductor Corp. OUI:0009D3* ID_OUI_FROM_DATABASE=Western DataCom Co., Inc. OUI:000AAE* ID_OUI_FROM_DATABASE=Rosemount Process Analytical OUI:000AB3* ID_OUI_FROM_DATABASE=Fa. GIRA OUI:000AB5* ID_OUI_FROM_DATABASE=Digital Electronic Network OUI:000ABA* ID_OUI_FROM_DATABASE=Arcon Technology Limited OUI:000AA2* ID_OUI_FROM_DATABASE=SYSTEK INC. OUI:000AA7* ID_OUI_FROM_DATABASE=FEI Electron Optics OUI:000A8F* ID_OUI_FROM_DATABASE=Aska International Inc. OUI:000A94* ID_OUI_FROM_DATABASE=ShangHai cellink CO., LTD OUI:000A9B* ID_OUI_FROM_DATABASE=TB Group Inc OUI:000A9A* ID_OUI_FROM_DATABASE=Aiptek International Inc OUI:000A50* ID_OUI_FROM_DATABASE=REMOTEK CORPORATION OUI:000A55* ID_OUI_FROM_DATABASE=MARKEM Corporation OUI:000A4E* ID_OUI_FROM_DATABASE=UNITEK Electronics INC. OUI:000A42* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000A49* ID_OUI_FROM_DATABASE=F5 Networks, Inc. OUI:000A36* ID_OUI_FROM_DATABASE=Synelec Telecom Multimedia OUI:000A3B* ID_OUI_FROM_DATABASE=GCT Semiconductor, Inc OUI:000A3D* ID_OUI_FROM_DATABASE=Elo Sistemas Eletronicos S.A. OUI:000A2F* ID_OUI_FROM_DATABASE=Artnix Inc. OUI:000A20* ID_OUI_FROM_DATABASE=SVA Networks, Inc. OUI:000A25* ID_OUI_FROM_DATABASE=CERAGON NETWORKS OUI:000A14* ID_OUI_FROM_DATABASE=TECO a.s. OUI:000A19* ID_OUI_FROM_DATABASE=Valere Power, Inc. OUI:000A0D* ID_OUI_FROM_DATABASE=FCI Deutschland GmbH OUI:000A12* ID_OUI_FROM_DATABASE=Azylex Technology, Inc OUI:0009F9* ID_OUI_FROM_DATABASE=ART JAPAN CO., LTD. OUI:0009FC* ID_OUI_FROM_DATABASE=IPFLEX Inc. OUI:000A03* ID_OUI_FROM_DATABASE=ENDESA SERVICIOS, S.L. OUI:0009ED* ID_OUI_FROM_DATABASE=CipherOptics OUI:0009F2* ID_OUI_FROM_DATABASE=Cohu, Inc., Electronics Division OUI:00095E* ID_OUI_FROM_DATABASE=Masstech Group Inc. OUI:000959* ID_OUI_FROM_DATABASE=Sitecsoft OUI:00094D* ID_OUI_FROM_DATABASE=Braintree Communications Pty Ltd OUI:000952* ID_OUI_FROM_DATABASE=Auerswald GmbH & Co. KG OUI:000946* ID_OUI_FROM_DATABASE=Cluster Labs GmbH OUI:000940* ID_OUI_FROM_DATABASE=AGFEO GmbH & Co. KG OUI:00093F* ID_OUI_FROM_DATABASE=Double-Win Enterpirse CO., LTD OUI:00093A* ID_OUI_FROM_DATABASE=Molex Fiber Optics OUI:000933* ID_OUI_FROM_DATABASE=Ophit Co.Ltd. OUI:00072C* ID_OUI_FROM_DATABASE=Fabricom OUI:000733* ID_OUI_FROM_DATABASE=DANCONTROL Engineering OUI:000732* ID_OUI_FROM_DATABASE=AAEON Technology Inc. OUI:000716* ID_OUI_FROM_DATABASE=J & S Marine Ltd. OUI:00071B* ID_OUI_FROM_DATABASE=CDVI Americas Ltd OUI:000722* ID_OUI_FROM_DATABASE=The Nielsen Company OUI:00071C* ID_OUI_FROM_DATABASE=AT&T Fixed Wireless Services OUI:00070A* ID_OUI_FROM_DATABASE=Unicom Automation Co., Ltd. OUI:00070F* ID_OUI_FROM_DATABASE=Fujant, Inc. OUI:000709* ID_OUI_FROM_DATABASE=Westerstrand Urfabrik AB OUI:000702* ID_OUI_FROM_DATABASE=Varian Medical Systems OUI:0006F3* ID_OUI_FROM_DATABASE=AcceLight Networks OUI:0006F4* ID_OUI_FROM_DATABASE=Prime Electronics & Satellitics Inc. OUI:000705* ID_OUI_FROM_DATABASE=Endress & Hauser GmbH & Co OUI:0006F8* ID_OUI_FROM_DATABASE=The Boeing Company OUI:0006FF* ID_OUI_FROM_DATABASE=Sheba Systems Co., Ltd. OUI:0006FD* ID_OUI_FROM_DATABASE=Comjet Information Systems Corp. OUI:00082D* ID_OUI_FROM_DATABASE=Indus Teqsite Private Limited OUI:000821* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000814* ID_OUI_FROM_DATABASE=TIL Technologies OUI:00081A* ID_OUI_FROM_DATABASE=Sanrad Intelligence Storage Communications (2000) Ltd. OUI:00080F* ID_OUI_FROM_DATABASE=Proximion Fiber Optics AB OUI:000809* ID_OUI_FROM_DATABASE=Systemonic AG OUI:000803* ID_OUI_FROM_DATABASE=Cos Tron OUI:0007FF* ID_OUI_FROM_DATABASE=Gluon Networks OUI:0007F9* ID_OUI_FROM_DATABASE=Sensaphone OUI:0007F3* ID_OUI_FROM_DATABASE=Thinkengine Networks OUI:0007EC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0007F2* ID_OUI_FROM_DATABASE=IOA Corporation OUI:0007B2* ID_OUI_FROM_DATABASE=Transaccess S.A. OUI:0007A4* ID_OUI_FROM_DATABASE=GN Netcom Ltd. OUI:0007AA* ID_OUI_FROM_DATABASE=Quantum Data Inc. OUI:00079D* ID_OUI_FROM_DATABASE=Musashi Co., Ltd. OUI:00079E* ID_OUI_FROM_DATABASE=Ilinx Co., Ltd. OUI:000774* ID_OUI_FROM_DATABASE=GuangZhou Thinker Technology Co. Ltd. OUI:000791* ID_OUI_FROM_DATABASE=International Data Communications, Inc. OUI:000798* ID_OUI_FROM_DATABASE=Selea SRL OUI:000797* ID_OUI_FROM_DATABASE=Netpower Co., Ltd. OUI:00078B* ID_OUI_FROM_DATABASE=Wegener Communications, Inc. OUI:000785* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00077B* ID_OUI_FROM_DATABASE=Millimetrix Broadband Networks OUI:00077E* ID_OUI_FROM_DATABASE=Elrest GmbH OUI:00076F* ID_OUI_FROM_DATABASE=Synoptics Limited OUI:000888* ID_OUI_FROM_DATABASE=OULLIM Information Technology Inc,. OUI:000882* ID_OUI_FROM_DATABASE=SIGMA CORPORATION OUI:00087C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000875* ID_OUI_FROM_DATABASE=Acorp Electronics Corp. OUI:000870* ID_OUI_FROM_DATABASE=Rasvia Systems, Inc. OUI:00086F* ID_OUI_FROM_DATABASE=Resources Computer Network Ltd. OUI:000869* ID_OUI_FROM_DATABASE=Command-e Technology Co.,Ltd. OUI:000863* ID_OUI_FROM_DATABASE=Entrisphere Inc. OUI:00085D* ID_OUI_FROM_DATABASE=Aastra OUI:000862* ID_OUI_FROM_DATABASE=NEC Eluminant Technologies, Inc. OUI:000850* ID_OUI_FROM_DATABASE=Arizona Instrument Corp. OUI:000856* ID_OUI_FROM_DATABASE=Gamatronic Electronic Industries Ltd. OUI:000927* ID_OUI_FROM_DATABASE=TOYOKEIKI CO.,LTD. OUI:00092E* ID_OUI_FROM_DATABASE=B&Tech System Inc. OUI:000920* ID_OUI_FROM_DATABASE=EpoX COMPUTER CO.,LTD. OUI:00091B* ID_OUI_FROM_DATABASE=Digital Generation Inc. OUI:000914* ID_OUI_FROM_DATABASE=COMPUTROLS INC. OUI:00090E* ID_OUI_FROM_DATABASE=Helix Technology Inc. OUI:000908* ID_OUI_FROM_DATABASE=VTech Technology Corp. OUI:00090D* ID_OUI_FROM_DATABASE=LEADER ELECTRONICS CORP. OUI:000901* ID_OUI_FROM_DATABASE=Shenzhen Shixuntong Information & Technoligy Co OUI:0007E6* ID_OUI_FROM_DATABASE=edgeflow Canada Inc. OUI:0007E0* ID_OUI_FROM_DATABASE=Palm Inc. OUI:0007D9* ID_OUI_FROM_DATABASE=Splicecom OUI:0007DA* ID_OUI_FROM_DATABASE=Neuro Telecom Co., Ltd. OUI:0007D3* ID_OUI_FROM_DATABASE=SPGPrints B.V. OUI:0007CA* ID_OUI_FROM_DATABASE=Creatix Polymedia Ges Fur Kommunikaitonssysteme OUI:0007C4* ID_OUI_FROM_DATABASE=JEAN Co. Ltd. OUI:0007BE* ID_OUI_FROM_DATABASE=DataLogic SpA OUI:0007B1* ID_OUI_FROM_DATABASE=Equator Technologies OUI:0007B8* ID_OUI_FROM_DATABASE=Corvalent Corporation OUI:00076E* ID_OUI_FROM_DATABASE=Sinetica Corporation Limited OUI:00076A* ID_OUI_FROM_DATABASE=NEXTEYE Co., Ltd. OUI:00075E* ID_OUI_FROM_DATABASE=Ametek Power Instruments OUI:000765* ID_OUI_FROM_DATABASE=Jade Quantum Technologies, Inc. OUI:000764* ID_OUI_FROM_DATABASE=YoungWoo Telecom Co. Ltd. OUI:000757* ID_OUI_FROM_DATABASE=Topcall International AG OUI:000758* ID_OUI_FROM_DATABASE=Dragonwave OUI:000752* ID_OUI_FROM_DATABASE=Rhythm Watch Co., Ltd. OUI:00074B* ID_OUI_FROM_DATABASE=Daihen Corporation OUI:000745* ID_OUI_FROM_DATABASE=Radlan Computer Communications Ltd. OUI:000738* ID_OUI_FROM_DATABASE=Young Technology Co., Ltd. OUI:00073F* ID_OUI_FROM_DATABASE=Woojyun Systec Co., Ltd. OUI:0008BB* ID_OUI_FROM_DATABASE=NetExcell OUI:0008B5* ID_OUI_FROM_DATABASE=TAI GUEN ENTERPRISE CO., LTD OUI:0008B6* ID_OUI_FROM_DATABASE=RouteFree, Inc. OUI:0008AF* ID_OUI_FROM_DATABASE=Novatec Corporation OUI:0008A9* ID_OUI_FROM_DATABASE=SangSang Technology, Inc. OUI:0008A8* ID_OUI_FROM_DATABASE=Systec Co., Ltd. OUI:0008A3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00089C* ID_OUI_FROM_DATABASE=Elecs Industry Co., Ltd. OUI:000894* ID_OUI_FROM_DATABASE=InnoVISION Multimedia Ltd. OUI:00088F* ID_OUI_FROM_DATABASE=ADVANCED DIGITAL TECHNOLOGY OUI:0008FC* ID_OUI_FROM_DATABASE=Gigaphoton Inc. OUI:0008F9* ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies OUI:0008F4* ID_OUI_FROM_DATABASE=Bluetake Technology Co., Ltd. OUI:0008EB* ID_OUI_FROM_DATABASE=ROMWin Co.,Ltd. OUI:0008E4* ID_OUI_FROM_DATABASE=Envenergy Inc OUI:0008DF* ID_OUI_FROM_DATABASE=Alistel Inc. OUI:0008D8* ID_OUI_FROM_DATABASE=Dowkey Microwave OUI:0008D2* ID_OUI_FROM_DATABASE=ZOOM Networks Inc. OUI:0008CC* ID_OUI_FROM_DATABASE=Remotec, Inc. OUI:0008D1* ID_OUI_FROM_DATABASE=KAREL INC. OUI:0008C2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00068F* ID_OUI_FROM_DATABASE=Telemonitor, Inc. OUI:000689* ID_OUI_FROM_DATABASE=yLez Technologies Pte Ltd OUI:000683* ID_OUI_FROM_DATABASE=Bravara Communications, Inc. OUI:00D0B9* ID_OUI_FROM_DATABASE=MICROTEK INTERNATIONAL, INC. OUI:00067D* ID_OUI_FROM_DATABASE=Takasago Ltd. OUI:000675* ID_OUI_FROM_DATABASE=Banderacom, Inc. OUI:000679* ID_OUI_FROM_DATABASE=Konami Corporation OUI:000663* ID_OUI_FROM_DATABASE=Human Technology Co., Ltd. OUI:00066F* ID_OUI_FROM_DATABASE=Korea Data Systems OUI:000662* ID_OUI_FROM_DATABASE=MBM Technology Ltd. OUI:000669* ID_OUI_FROM_DATABASE=Datasound Laboratories Ltd OUI:00055A* ID_OUI_FROM_DATABASE=Power Dsine Ltd. OUI:00065C* ID_OUI_FROM_DATABASE=Malachite Technologies, Inc. OUI:000650* ID_OUI_FROM_DATABASE=Tiburon Networks, Inc. OUI:000656* ID_OUI_FROM_DATABASE=Tactel AB OUI:00060A* ID_OUI_FROM_DATABASE=Blue2space OUI:000604* ID_OUI_FROM_DATABASE=@Track Communications, Inc. OUI:00CBBD* ID_OUI_FROM_DATABASE=Cambridge Broadband Networks Ltd. OUI:000603* ID_OUI_FROM_DATABASE=Baker Hughes Inc. OUI:A06A00* ID_OUI_FROM_DATABASE=Verilink Corporation OUI:0005EE* ID_OUI_FROM_DATABASE=Siemens AB, Infrastructure & Cities, Building Technologies Division, IC BT SSP SP BA PR OUI:0005F5* ID_OUI_FROM_DATABASE=Geospace Technologies OUI:000601* ID_OUI_FROM_DATABASE=Otanikeiki Co., Ltd. OUI:0005E8* ID_OUI_FROM_DATABASE=TurboWave, Inc. OUI:0005F4* ID_OUI_FROM_DATABASE=System Base Co., Ltd. OUI:0005FB* ID_OUI_FROM_DATABASE=ShareGate, Inc. OUI:0005DB* ID_OUI_FROM_DATABASE=PSI Nentec GmbH OUI:0005DF* ID_OUI_FROM_DATABASE=Electronic Innovation, Inc. OUI:0005CF* ID_OUI_FROM_DATABASE=Thunder River Technologies, Inc. OUI:0005C9* ID_OUI_FROM_DATABASE=LG Innotek Co., Ltd. OUI:0006E7* ID_OUI_FROM_DATABASE=Bit Blitz Communications Inc. OUI:0006ED* ID_OUI_FROM_DATABASE=Inara Networks OUI:0006DC* ID_OUI_FROM_DATABASE=Syabas Technology (Amquest) OUI:0006E1* ID_OUI_FROM_DATABASE=Techno Trade s.a OUI:0006E6* ID_OUI_FROM_DATABASE=DongYang Telecom Co., Ltd. OUI:0006CF* ID_OUI_FROM_DATABASE=Thales Avionics In-Flight Systems, LLC OUI:0006D6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0006D5* ID_OUI_FROM_DATABASE=Diamond Systems Corp. OUI:0006C9* ID_OUI_FROM_DATABASE=Technical Marketing Research, Inc. OUI:0006C3* ID_OUI_FROM_DATABASE=Schindler Elevator Ltd. OUI:0006C8* ID_OUI_FROM_DATABASE=Sumitomo Metal Micro Devices, Inc. OUI:0005D5* ID_OUI_FROM_DATABASE=Speedcom Wireless OUI:0005BC* ID_OUI_FROM_DATABASE=Resource Data Management Ltd OUI:0005C2* ID_OUI_FROM_DATABASE=Soronti, Inc. OUI:0005B0* ID_OUI_FROM_DATABASE=Korea Computer Technology Co., Ltd. OUI:00059C* ID_OUI_FROM_DATABASE=Kleinknecht GmbH, Ing. Büro OUI:0005B6* ID_OUI_FROM_DATABASE=INSYS Microelectronics GmbH OUI:0005A2* ID_OUI_FROM_DATABASE=CELOX Networks OUI:0005AC* ID_OUI_FROM_DATABASE=Northern Digital, Inc. OUI:000589* ID_OUI_FROM_DATABASE=National Datacomputer OUI:000595* ID_OUI_FROM_DATABASE=Alesis Corporation OUI:00058F* ID_OUI_FROM_DATABASE=CLCsoft co. OUI:000596* ID_OUI_FROM_DATABASE=Genotech Co., Ltd. OUI:000506* ID_OUI_FROM_DATABASE=Reddo Networks AB OUI:0004FC* ID_OUI_FROM_DATABASE=Stratus Computer (DE), Inc. OUI:0004F6* ID_OUI_FROM_DATABASE=Amphus OUI:0004F5* ID_OUI_FROM_DATABASE=SnowShore Networks, Inc. OUI:0004E9* ID_OUI_FROM_DATABASE=Infiniswitch Corporation OUI:0004F0* ID_OUI_FROM_DATABASE=International Computers, Ltd OUI:0004EF* ID_OUI_FROM_DATABASE=Polestar Corp. OUI:0004DF* ID_OUI_FROM_DATABASE=Teracom Telematica Ltda. OUI:0004E5* ID_OUI_FROM_DATABASE=Glonet Systems, Inc. OUI:0004D9* ID_OUI_FROM_DATABASE=Titan Electronics, Inc. OUI:00062D* ID_OUI_FROM_DATABASE=TouchStar Technologies, L.L.C. OUI:000649* ID_OUI_FROM_DATABASE=3M Deutschland GmbH OUI:000643* ID_OUI_FROM_DATABASE=SONO Computer Co., Ltd. OUI:00064A* ID_OUI_FROM_DATABASE=Honeywell Co., Ltd. (KOREA) OUI:00063F* ID_OUI_FROM_DATABASE=Everex Communications Inc. OUI:000639* ID_OUI_FROM_DATABASE=Newtec OUI:000633* ID_OUI_FROM_DATABASE=Cross Match Technologies GmbH OUI:000626* ID_OUI_FROM_DATABASE=MWE GmbH OUI:00061D* ID_OUI_FROM_DATABASE=MIP Telecom, Inc. OUI:000623* ID_OUI_FROM_DATABASE=MGE UPS Systems France OUI:000610* ID_OUI_FROM_DATABASE=Abeona Networks Inc OUI:000616* ID_OUI_FROM_DATABASE=Tel Net Co., Ltd. OUI:00054D* ID_OUI_FROM_DATABASE=Brans Technologies, Inc. OUI:000542* ID_OUI_FROM_DATABASE=Otari, Inc. OUI:00053C* ID_OUI_FROM_DATABASE=XIRCOM OUI:00052F* ID_OUI_FROM_DATABASE=Leviton Network Solutions OUI:00053B* ID_OUI_FROM_DATABASE=Harbour Networks Ltd., Co. Beijing OUI:000535* ID_OUI_FROM_DATABASE=Chip PC Ltd. OUI:000529* ID_OUI_FROM_DATABASE=Shanghai Broadan Communication Technology Co., Ltd OUI:000523* ID_OUI_FROM_DATABASE=AVL List GmbH OUI:000522* ID_OUI_FROM_DATABASE=LEA*D Corporation, Inc. OUI:00051C* ID_OUI_FROM_DATABASE=Xnet Technology Corp. OUI:000516* ID_OUI_FROM_DATABASE=SMART Modular Technologies OUI:00050C* ID_OUI_FROM_DATABASE=Network Photonics, Inc. OUI:000512* ID_OUI_FROM_DATABASE=Zebra Technologies Inc OUI:0006BF* ID_OUI_FROM_DATABASE=Accella Technologies Co., Ltd. OUI:0006B9* ID_OUI_FROM_DATABASE=A5TEK Corp. OUI:0006B2* ID_OUI_FROM_DATABASE=Linxtek Co. OUI:0006AC* ID_OUI_FROM_DATABASE=Intersoft Co. OUI:0006A6* ID_OUI_FROM_DATABASE=Artistic Licence Engineering Ltd OUI:0006A2* ID_OUI_FROM_DATABASE=Microtune, Inc. OUI:000695* ID_OUI_FROM_DATABASE=Ensure Technologies, Inc. OUI:00069C* ID_OUI_FROM_DATABASE=Transmode Systems AB OUI:000696* ID_OUI_FROM_DATABASE=Advent Networks OUI:000690* ID_OUI_FROM_DATABASE=Euracom Communication GmbH OUI:00057D* ID_OUI_FROM_DATABASE=Sun Communications, Inc. OUI:00057C* ID_OUI_FROM_DATABASE=RCO Security AB OUI:000583* ID_OUI_FROM_DATABASE=ImageCom Limited OUI:000573* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000572* ID_OUI_FROM_DATABASE=Deonet Co., Ltd. OUI:00056C* ID_OUI_FROM_DATABASE=Hung Chang Co., Ltd. OUI:000566* ID_OUI_FROM_DATABASE=Secui.com Corporation OUI:000560* ID_OUI_FROM_DATABASE=LEADER COMM.CO., LTD OUI:000559* ID_OUI_FROM_DATABASE=Intracom S.A. OUI:000553* ID_OUI_FROM_DATABASE=DVC Company, Inc. OUI:000548* ID_OUI_FROM_DATABASE=Disco Corporation OUI:0003D2* ID_OUI_FROM_DATABASE=Crossbeam Systems, Inc. OUI:0003CD* ID_OUI_FROM_DATABASE=Clovertech, Inc. OUI:0003CA* ID_OUI_FROM_DATABASE=MTS Systems Corp. OUI:0003C6* ID_OUI_FROM_DATABASE=ICUE Systems, Inc. OUI:0003BF* ID_OUI_FROM_DATABASE=Centerpoint Broadband Technologies, Inc. OUI:0003BA* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:0003AF* ID_OUI_FROM_DATABASE=Paragea Communications OUI:0003B4* ID_OUI_FROM_DATABASE=Macrotek International Corp. OUI:0003AC* ID_OUI_FROM_DATABASE=Fronius Schweissmaschinen OUI:0003A8* ID_OUI_FROM_DATABASE=IDOT Computers, Inc. OUI:0003A1* ID_OUI_FROM_DATABASE=HIPER Information & Communication, Inc. OUI:00044E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00044F* ID_OUI_FROM_DATABASE=Schubert System Elektronik Gmbh OUI:000454* ID_OUI_FROM_DATABASE=Quadriga UK OUI:000445* ID_OUI_FROM_DATABASE=LMS Skalar Instruments GmbH OUI:00044A* ID_OUI_FROM_DATABASE=iPolicy Networks, Inc. OUI:000444* ID_OUI_FROM_DATABASE=Western Multiplex Corporation OUI:00043E* ID_OUI_FROM_DATABASE=Telencomm OUI:000438* ID_OUI_FROM_DATABASE=Nortel Networks OUI:000432* ID_OUI_FROM_DATABASE=Voyetra Turtle Beach, Inc. OUI:000437* ID_OUI_FROM_DATABASE=Powin Information Technology, Inc. OUI:00042B* ID_OUI_FROM_DATABASE=IT Access Co., Ltd. OUI:000425* ID_OUI_FROM_DATABASE=Atmel Corporation OUI:000419* ID_OUI_FROM_DATABASE=Fibercycle Networks, Inc. OUI:00041A* ID_OUI_FROM_DATABASE=Ines Test and Measurement GmbH & CoKG OUI:000399* ID_OUI_FROM_DATABASE=Dongju Informations & Communications Co., Ltd. OUI:00039C* ID_OUI_FROM_DATABASE=OptiMight Communications, Inc. OUI:000390* ID_OUI_FROM_DATABASE=Digital Video Communications, Inc. OUI:000395* ID_OUI_FROM_DATABASE=California Amplifier OUI:000380* ID_OUI_FROM_DATABASE=SSH Communications Security Corp. OUI:000374* ID_OUI_FROM_DATABASE=Control Microsystems OUI:0002F0* ID_OUI_FROM_DATABASE=AME Optimedia Technology Co., Ltd. OUI:000379* ID_OUI_FROM_DATABASE=Proscend Communications, Inc. OUI:000371* ID_OUI_FROM_DATABASE=Acomz Networks Corp. OUI:00036D* ID_OUI_FROM_DATABASE=Runtop, Inc. OUI:000361* ID_OUI_FROM_DATABASE=Widcomm, Inc. OUI:0002DE* ID_OUI_FROM_DATABASE=Astrodesign, Inc. OUI:0002DB* ID_OUI_FROM_DATABASE=NETSEC OUI:0002D7* ID_OUI_FROM_DATABASE=EMPEG Ltd OUI:0002D2* ID_OUI_FROM_DATABASE=Workstation AG OUI:000223* ID_OUI_FROM_DATABASE=ClickTV OUI:0002CB* ID_OUI_FROM_DATABASE=TriState Ltd. OUI:0002C4* ID_OUI_FROM_DATABASE=Vector International BVBA OUI:0002BF* ID_OUI_FROM_DATABASE=dotRocket, Inc. OUI:0002BB* ID_OUI_FROM_DATABASE=Continuous Computing Corp OUI:0002BC* ID_OUI_FROM_DATABASE=LVL 7 Systems, Inc. OUI:0002B6* ID_OUI_FROM_DATABASE=Acrosser Technology Co., Ltd. OUI:0002AF* ID_OUI_FROM_DATABASE=TeleCruz Technology, Inc. OUI:0002AA* ID_OUI_FROM_DATABASE=PLcom Co., Ltd. OUI:0002A3* ID_OUI_FROM_DATABASE=ABB Switzerland Ltd, Power Systems OUI:00035A* ID_OUI_FROM_DATABASE=Photron Limited OUI:000355* ID_OUI_FROM_DATABASE=TeraBeam Internet Systems OUI:000353* ID_OUI_FROM_DATABASE=Mitac, Inc. OUI:00034F* ID_OUI_FROM_DATABASE=Sur-Gard Security OUI:00034A* ID_OUI_FROM_DATABASE=RIAS Corporation OUI:000346* ID_OUI_FROM_DATABASE=Hitachi Kokusai Electric, Inc. OUI:000344* ID_OUI_FROM_DATABASE=Tietech.Co., Ltd. OUI:000343* ID_OUI_FROM_DATABASE=Martin Professional A/S OUI:000334* ID_OUI_FROM_DATABASE=Newport Electronics OUI:000337* ID_OUI_FROM_DATABASE=Vaone, Inc. OUI:00033C* ID_OUI_FROM_DATABASE=Daiden Co., Ltd. OUI:000329* ID_OUI_FROM_DATABASE=F3, Inc. OUI:000330* ID_OUI_FROM_DATABASE=Imagenics, Co., Ltd. OUI:000321* ID_OUI_FROM_DATABASE=Reco Research Co., Ltd. OUI:000324* ID_OUI_FROM_DATABASE=SANYO Consumer Electronics Co., Ltd. OUI:00031B* ID_OUI_FROM_DATABASE=Cellvision Systems, Inc. OUI:0001A8* ID_OUI_FROM_DATABASE=Welltech Computer Co., Ltd. OUI:00030F* ID_OUI_FROM_DATABASE=Digital China (Shanghai) Networks Ltd. OUI:000314* ID_OUI_FROM_DATABASE=Teleware Network Systems OUI:00030C* ID_OUI_FROM_DATABASE=Telesoft Technologies Ltd. OUI:000308* ID_OUI_FROM_DATABASE=AM Communications, Inc. OUI:0002FC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000301* ID_OUI_FROM_DATABASE=EXFO OUI:0002F9* ID_OUI_FROM_DATABASE=MIMOS Berhad OUI:0002F5* ID_OUI_FROM_DATABASE=VIVE Synergies, Inc. OUI:0002EA* ID_OUI_FROM_DATABASE=Focus Enhancements OUI:0002E3* ID_OUI_FROM_DATABASE=LITE-ON Communications, Inc. OUI:0004D3* ID_OUI_FROM_DATABASE=Toyokeiki Co., Ltd. OUI:0004CC* ID_OUI_FROM_DATABASE=Peek Traffic B.V. OUI:0004C0* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0004B9* ID_OUI_FROM_DATABASE=S.I. Soubou, Inc. OUI:0004BA* ID_OUI_FROM_DATABASE=KDD Media Will Corporation OUI:0004AF* ID_OUI_FROM_DATABASE=Digital Fountain, Inc. OUI:0004B4* ID_OUI_FROM_DATABASE=CIAC OUI:0004B3* ID_OUI_FROM_DATABASE=Videotek, Inc. OUI:0004A6* ID_OUI_FROM_DATABASE=SAF Tehnika Ltd. OUI:0004A0* ID_OUI_FROM_DATABASE=Verity Instruments, Inc. OUI:0004A5* ID_OUI_FROM_DATABASE=Barco Projection Systems NV OUI:000499* ID_OUI_FROM_DATABASE=Chino Corporation OUI:00048D* ID_OUI_FROM_DATABASE=Teo Technologies, Inc OUI:000493* ID_OUI_FROM_DATABASE=Tsinghua Unisplendour Co., Ltd. OUI:000484* ID_OUI_FROM_DATABASE=Amann GmbH OUI:00048A* ID_OUI_FROM_DATABASE=Temia Vertriebs GmbH OUI:00047A* ID_OUI_FROM_DATABASE=AXXESSIT ASA OUI:000474* ID_OUI_FROM_DATABASE=LEGRAND OUI:00046E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000473* ID_OUI_FROM_DATABASE=Photonex Corporation OUI:000467* ID_OUI_FROM_DATABASE=Wuhan Research Institute of MII OUI:000461* ID_OUI_FROM_DATABASE=EPOX Computer Co., Ltd. OUI:00045B* ID_OUI_FROM_DATABASE=Techsan Electronics Co., Ltd. OUI:000414* ID_OUI_FROM_DATABASE=Umezawa Musen Denki Co., Ltd. OUI:000407* ID_OUI_FROM_DATABASE=Topcon Positioning Systems, Inc. OUI:0003F7* ID_OUI_FROM_DATABASE=Plast-Control GmbH OUI:0003FE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0003FD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000401* ID_OUI_FROM_DATABASE=Osaki Electric Co., Ltd. OUI:0003F0* ID_OUI_FROM_DATABASE=Redfern Broadband Networks OUI:0003EB* ID_OUI_FROM_DATABASE=Atrica OUI:0003E5* ID_OUI_FROM_DATABASE=Hermstedt SG OUI:0003D9* ID_OUI_FROM_DATABASE=Secheron SA OUI:00022F* ID_OUI_FROM_DATABASE=P-Cube, Ltd. OUI:000227* ID_OUI_FROM_DATABASE=ESD Electronic System Design GmbH OUI:00021F* ID_OUI_FROM_DATABASE=Aculab PLC OUI:00021B* ID_OUI_FROM_DATABASE=Kollmorgen-Servotronix OUI:00020C* ID_OUI_FROM_DATABASE=Metro-Optix OUI:000218* ID_OUI_FROM_DATABASE=Advanced Scientific Corp OUI:000213* ID_OUI_FROM_DATABASE=S.D.E.L. OUI:00020F* ID_OUI_FROM_DATABASE=AATR OUI:0001F9* ID_OUI_FROM_DATABASE=TeraGlobal Communications Corp. OUI:000200* ID_OUI_FROM_DATABASE=Net & Sys Co., Ltd. OUI:00015E* ID_OUI_FROM_DATABASE=BEST TECHNOLOGY CO., LTD. OUI:000162* ID_OUI_FROM_DATABASE=Cygnet Technologies, Inc. OUI:000169* ID_OUI_FROM_DATABASE=Celestix Networks Pte Ltd. OUI:000175* ID_OUI_FROM_DATABASE=Radiant Communications Corp. OUI:000159* ID_OUI_FROM_DATABASE=S1 Corporation OUI:000165* ID_OUI_FROM_DATABASE=AirSwitch Corporation OUI:000171* ID_OUI_FROM_DATABASE=Allied Data Technologies OUI:000157* ID_OUI_FROM_DATABASE=SYSWAVE CO., LTD OUI:000153* ID_OUI_FROM_DATABASE=ARCHTEK TELECOM CORPORATION OUI:000144* ID_OUI_FROM_DATABASE=EMC Corporation OUI:00014B* ID_OUI_FROM_DATABASE=Ennovate Networks, Inc. OUI:00012C* ID_OUI_FROM_DATABASE=Aravox Technologies, Inc. OUI:000138* ID_OUI_FROM_DATABASE=XAVi Technologies Corp. OUI:00010C* ID_OUI_FROM_DATABASE=System Talks Inc. OUI:000113* ID_OUI_FROM_DATABASE=OLYMPUS CORPORATION OUI:000100* ID_OUI_FROM_DATABASE=EQUIP'TRANS OUI:00B0AC* ID_OUI_FROM_DATABASE=SIAE-Microelettronica S.p.A. OUI:00B017* ID_OUI_FROM_DATABASE=InfoGear Technology Corp. OUI:0030F0* ID_OUI_FROM_DATABASE=Uniform Industrial Corp. OUI:00B0CE* ID_OUI_FROM_DATABASE=TECHNOLOGY RESCUE OUI:00B080* ID_OUI_FROM_DATABASE=Mannesmann Ipulsys B.V. OUI:00B09A* ID_OUI_FROM_DATABASE=Morrow Technologies Corp. OUI:00B091* ID_OUI_FROM_DATABASE=Transmeta Corp. OUI:0030BE* ID_OUI_FROM_DATABASE=City-Net Technology, Inc. OUI:00303E* ID_OUI_FROM_DATABASE=Radcom Ltd. OUI:0030D7* ID_OUI_FROM_DATABASE=Innovative Systems, L.L.C. OUI:0030FC* ID_OUI_FROM_DATABASE=Terawave Communications, Inc. OUI:00300F* ID_OUI_FROM_DATABASE=IMT - Information Management T OUI:003004* ID_OUI_FROM_DATABASE=LEADTEK RESEARCH INC. OUI:003018* ID_OUI_FROM_DATABASE=Jetway Information Co., Ltd. OUI:003088* ID_OUI_FROM_DATABASE=Ericsson OUI:0030CA* ID_OUI_FROM_DATABASE=Discovery Com OUI:00304F* ID_OUI_FROM_DATABASE=PLANET Technology Corporation OUI:0001FC* ID_OUI_FROM_DATABASE=Keyence Corporation OUI:0001F3* ID_OUI_FROM_DATABASE=QPS, Inc. OUI:0001E4* ID_OUI_FROM_DATABASE=Sitera, Inc. OUI:0001EB* ID_OUI_FROM_DATABASE=C-COM Corporation OUI:0001F0* ID_OUI_FROM_DATABASE=Tridium, Inc. OUI:0001D4* ID_OUI_FROM_DATABASE=Leisure Time, Inc. OUI:0001D8* ID_OUI_FROM_DATABASE=Teltronics, Inc. OUI:0001C6* ID_OUI_FROM_DATABASE=Quarry Technologies OUI:0001CC* ID_OUI_FROM_DATABASE=Japan Total Design Communication Co., Ltd. OUI:0001D1* ID_OUI_FROM_DATABASE=CoNet Communications, Inc. OUI:0001B3* ID_OUI_FROM_DATABASE=Precision Electronic Manufacturing OUI:0001B1* ID_OUI_FROM_DATABASE=General Bandwidth OUI:0001BB* ID_OUI_FROM_DATABASE=Frequentis OUI:00025E* ID_OUI_FROM_DATABASE=High Technology Ltd OUI:000261* ID_OUI_FROM_DATABASE=Tilgin AB OUI:000259* ID_OUI_FROM_DATABASE=Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group OUI:000255* ID_OUI_FROM_DATABASE=IBM Corp OUI:000249* ID_OUI_FROM_DATABASE=Aviv Infocom Co, Ltd. OUI:000250* ID_OUI_FROM_DATABASE=Geyser Networks, Inc. OUI:000242* ID_OUI_FROM_DATABASE=Videoframe Systems OUI:000244* ID_OUI_FROM_DATABASE=SURECOM Technology Co. OUI:00022C* ID_OUI_FROM_DATABASE=ABB Bomem, Inc. OUI:00023A* ID_OUI_FROM_DATABASE=ZSK Stickmaschinen GmbH OUI:000233* ID_OUI_FROM_DATABASE=Mantra Communications, Inc. OUI:0001B7* ID_OUI_FROM_DATABASE=Centos, Inc. OUI:0001AF* ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies OUI:0001AB* ID_OUI_FROM_DATABASE=Main Street Networks OUI:000191* ID_OUI_FROM_DATABASE=SYRED Data Systems OUI:00019D* ID_OUI_FROM_DATABASE=E-Control Systems, Inc. OUI:0001A4* ID_OUI_FROM_DATABASE=Microlink Corporation OUI:000199* ID_OUI_FROM_DATABASE=HeiSei Electronics OUI:0001A0* ID_OUI_FROM_DATABASE=Infinilink Corporation OUI:00017C* ID_OUI_FROM_DATABASE=AG-E GmbH OUI:000188* ID_OUI_FROM_DATABASE=LXCO Technologies ag OUI:000178* ID_OUI_FROM_DATABASE=MARGI Systems, Inc. OUI:00018B* ID_OUI_FROM_DATABASE=NetLinks Co., Ltd. OUI:0030F5* ID_OUI_FROM_DATABASE=Wild Lab. Ltd. OUI:000184* ID_OUI_FROM_DATABASE=SIEB & MEYER AG OUI:000160* ID_OUI_FROM_DATABASE=ELMEX Co., LTD. OUI:000298* ID_OUI_FROM_DATABASE=Broadframe Corporation OUI:000292* ID_OUI_FROM_DATABASE=Logic Innovations, Inc. OUI:00028D* ID_OUI_FROM_DATABASE=Movita Technologies, Inc. OUI:000283* ID_OUI_FROM_DATABASE=Spectrum Controls, Inc. OUI:000277* ID_OUI_FROM_DATABASE=Cash Systemes Industrie OUI:00027C* ID_OUI_FROM_DATABASE=Trilithic, Inc. OUI:000275* ID_OUI_FROM_DATABASE=SMART Technologies, Inc. OUI:000270* ID_OUI_FROM_DATABASE=Crewave Co., Ltd. OUI:000269* ID_OUI_FROM_DATABASE=Nadatel Co., Ltd OUI:000265* ID_OUI_FROM_DATABASE=Virditech Co. Ltd. OUI:000134* ID_OUI_FROM_DATABASE=Selectron Systems AG OUI:00013B* ID_OUI_FROM_DATABASE=BNA SYSTEMS OUI:000147* ID_OUI_FROM_DATABASE=Zhone Technologies OUI:00012B* ID_OUI_FROM_DATABASE=TELENET Co., Ltd. OUI:00011C* ID_OUI_FROM_DATABASE=Universal Talkware Corporation OUI:000123* ID_OUI_FROM_DATABASE=DIGITAL ELECTRONICS CORP. OUI:00011F* ID_OUI_FROM_DATABASE=RC Networks, Inc. OUI:000104* ID_OUI_FROM_DATABASE=DVICO Co., Ltd. OUI:000110* ID_OUI_FROM_DATABASE=Gotham Networks OUI:00D05A* ID_OUI_FROM_DATABASE=SYMBIONICS, LTD. OUI:00D01A* ID_OUI_FROM_DATABASE=URMET TLC S.P.A. OUI:00D0F3* ID_OUI_FROM_DATABASE=SOLARI DI UDINE SPA OUI:00D089* ID_OUI_FROM_DATABASE=DYNACOLOR, INC. OUI:00D08D* ID_OUI_FROM_DATABASE=PHOENIX GROUP, INC. OUI:00D09C* ID_OUI_FROM_DATABASE=KAPADIA COMMUNICATIONS OUI:00D0FE* ID_OUI_FROM_DATABASE=ASTRAL POINT OUI:00D0DC* ID_OUI_FROM_DATABASE=MODULAR MINING SYSTEMS, INC. OUI:00D062* ID_OUI_FROM_DATABASE=DIGIGRAM OUI:00D0A7* ID_OUI_FROM_DATABASE=TOKYO SOKKI KENKYUJO CO., LTD. OUI:00D032* ID_OUI_FROM_DATABASE=YANO ELECTRIC CO., LTD. OUI:00D054* ID_OUI_FROM_DATABASE=SAS INSTITUTE INC. OUI:00D0EB* ID_OUI_FROM_DATABASE=LIGHTERA NETWORKS, INC. OUI:00D01E* ID_OUI_FROM_DATABASE=PINGTEL CORP. OUI:00D0A9* ID_OUI_FROM_DATABASE=SHINANO KENSHI CO., LTD. OUI:00D0F2* ID_OUI_FROM_DATABASE=MONTEREY NETWORKS OUI:0030DB* ID_OUI_FROM_DATABASE=Mindready Solutions, Inc. OUI:00306A* ID_OUI_FROM_DATABASE=PENTA MEDIA CO., LTD. OUI:003021* ID_OUI_FROM_DATABASE=HSING TECH. ENTERPRISE CO.,LTD OUI:0030EA* ID_OUI_FROM_DATABASE=TeraForce Technology Corporation OUI:0030F4* ID_OUI_FROM_DATABASE=STARDOT TECHNOLOGIES OUI:003087* ID_OUI_FROM_DATABASE=VEGA GRIESHABER KG OUI:003000* ID_OUI_FROM_DATABASE=ALLWELL TECHNOLOGY CORP. OUI:003034* ID_OUI_FROM_DATABASE=SET ENGINEERING OUI:00308D* ID_OUI_FROM_DATABASE=Pinnacle Systems, Inc. OUI:00304B* ID_OUI_FROM_DATABASE=ORBACOM SYSTEMS, INC. OUI:0030FA* ID_OUI_FROM_DATABASE=TELICA, INC. OUI:0030E9* ID_OUI_FROM_DATABASE=GMA COMMUNICATION MANUFACT'G OUI:003027* ID_OUI_FROM_DATABASE=KERBANGO, INC. OUI:00D0B8* ID_OUI_FROM_DATABASE=Iomega Corporation OUI:005045* ID_OUI_FROM_DATABASE=RIOWORKS SOLUTIONS, INC. OUI:00507C* ID_OUI_FROM_DATABASE=VIDEOCON AG OUI:005065* ID_OUI_FROM_DATABASE=TDK-Lambda Corporation OUI:0050C7* ID_OUI_FROM_DATABASE=Private OUI:0050F4* ID_OUI_FROM_DATABASE=SIGMATEK GMBH & CO. KG OUI:005076* ID_OUI_FROM_DATABASE=IBM Corp OUI:005075* ID_OUI_FROM_DATABASE=KESTREL SOLUTIONS OUI:005090* ID_OUI_FROM_DATABASE=DCTRI OUI:0050ED* ID_OUI_FROM_DATABASE=ANDA NETWORKS OUI:005096* ID_OUI_FROM_DATABASE=SALIX TECHNOLOGIES, INC. OUI:00509B* ID_OUI_FROM_DATABASE=SWITCHCORE AB OUI:0050A9* ID_OUI_FROM_DATABASE=MOLDAT WIRELESS TECHNOLGIES OUI:00503C* ID_OUI_FROM_DATABASE=TSINGHUA NOVEL ELECTRONICS OUI:0050B6* ID_OUI_FROM_DATABASE=GOOD WAY IND. CO., LTD. OUI:0050FF* ID_OUI_FROM_DATABASE=HAKKO ELECTRONICS CO., LTD. OUI:005032* ID_OUI_FROM_DATABASE=PICAZO COMMUNICATIONS, INC. OUI:0030F6* ID_OUI_FROM_DATABASE=SECURELOGIX CORPORATION OUI:0030B6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0030B2* ID_OUI_FROM_DATABASE=L-3 Sonoma EO OUI:0030D6* ID_OUI_FROM_DATABASE=MSC VERTRIEBS GMBH OUI:003008* ID_OUI_FROM_DATABASE=AVIO DIGITAL, INC. OUI:00306D* ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES OUI:0030E4* ID_OUI_FROM_DATABASE=CHIYODA SYSTEM RIKEN OUI:00301A* ID_OUI_FROM_DATABASE=SMARTBRIDGES PTE. LTD. OUI:0030CD* ID_OUI_FROM_DATABASE=CONEXANT SYSTEMS, INC. OUI:003001* ID_OUI_FROM_DATABASE=SMP OUI:0030E1* ID_OUI_FROM_DATABASE=Network Equipment Technologies, Inc. OUI:0030D8* ID_OUI_FROM_DATABASE=SITEK OUI:003062* ID_OUI_FROM_DATABASE=IP Video Networks Inc OUI:003081* ID_OUI_FROM_DATABASE=ALTOS C&C OUI:00D066* ID_OUI_FROM_DATABASE=WINTRISS ENGINEERING CORP. OUI:00D06F* ID_OUI_FROM_DATABASE=KMC CONTROLS OUI:00D04B* ID_OUI_FROM_DATABASE=LA CIE GROUP S.A. OUI:00D060* ID_OUI_FROM_DATABASE=Panasonic Europe Ltd. OUI:00D002* ID_OUI_FROM_DATABASE=DITECH CORPORATION OUI:00D0A6* ID_OUI_FROM_DATABASE=LANBIRD TECHNOLOGY CO., LTD. OUI:00D0DE* ID_OUI_FROM_DATABASE=PHILIPS MULTIMEDIA NETWORK OUI:00D083* ID_OUI_FROM_DATABASE=INVERTEX, INC. OUI:00D038* ID_OUI_FROM_DATABASE=FIVEMERE, LTD. OUI:00D00C* ID_OUI_FROM_DATABASE=SNIJDER MICRO SYSTEMS OUI:00D086* ID_OUI_FROM_DATABASE=FOVEON, INC. OUI:00D03F* ID_OUI_FROM_DATABASE=AMERICAN COMMUNICATION OUI:00D033* ID_OUI_FROM_DATABASE=DALIAN DAXIAN NETWORK OUI:00D0CE* ID_OUI_FROM_DATABASE=ASYST ELECTRONIC OUI:00D090* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00D0B6* ID_OUI_FROM_DATABASE=CRESCENT NETWORKS, INC. OUI:00D0D2* ID_OUI_FROM_DATABASE=EPILOG CORPORATION OUI:00D071* ID_OUI_FROM_DATABASE=ECHELON CORP. OUI:00D07B* ID_OUI_FROM_DATABASE=COMCAM INTERNATIONAL INC OUI:00D05D* ID_OUI_FROM_DATABASE=INTELLIWORXX, INC. OUI:00D00D* ID_OUI_FROM_DATABASE=MICROMERITICS INSTRUMENT OUI:00D04C* ID_OUI_FROM_DATABASE=EUROTEL TELECOM LTD. OUI:00D0FD* ID_OUI_FROM_DATABASE=OPTIMA TELE.COM, INC. OUI:0050A7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00D0EE* ID_OUI_FROM_DATABASE=DICTAPHONE CORPORATION OUI:00D0B0* ID_OUI_FROM_DATABASE=BITSWITCH LTD. OUI:00D044* ID_OUI_FROM_DATABASE=ALIDIAN NETWORKS, INC. OUI:00D004* ID_OUI_FROM_DATABASE=PENTACOM LTD. OUI:00D045* ID_OUI_FROM_DATABASE=KVASER AB OUI:00D0D0* ID_OUI_FROM_DATABASE=ZHONGXING TELECOM LTD. OUI:00D03E* ID_OUI_FROM_DATABASE=ROCKETCHIPS, INC. OUI:003045* ID_OUI_FROM_DATABASE=Village Networks, Inc. (VNI) OUI:0030BB* ID_OUI_FROM_DATABASE=CacheFlow, Inc. OUI:003053* ID_OUI_FROM_DATABASE=Basler AG OUI:003072* ID_OUI_FROM_DATABASE=Intellibyte Inc. OUI:0030B1* ID_OUI_FROM_DATABASE=TrunkNet OUI:0030A7* ID_OUI_FROM_DATABASE=SCHWEITZER ENGINEERING OUI:003038* ID_OUI_FROM_DATABASE=XCP, INC. OUI:00902C* ID_OUI_FROM_DATABASE=DATA & CONTROL EQUIPMENT LTD. OUI:009049* ID_OUI_FROM_DATABASE=ENTRIDIA CORPORATION OUI:009043* ID_OUI_FROM_DATABASE=Tattile SRL OUI:009076* ID_OUI_FROM_DATABASE=FMT AIRCRAFT GATE SUPPORT SYSTEMS AB OUI:009017* ID_OUI_FROM_DATABASE=Zypcom, Inc OUI:00907B* ID_OUI_FROM_DATABASE=E-TECH, INC. OUI:00909D* ID_OUI_FROM_DATABASE=NovaTech Process Solutions, LLC OUI:009038* ID_OUI_FROM_DATABASE=FOUNTAIN TECHNOLOGIES, INC. OUI:00501F* ID_OUI_FROM_DATABASE=MRG SYSTEMS, LTD. OUI:005092* ID_OUI_FROM_DATABASE=Rigaku Corporation Osaka Plant OUI:00501C* ID_OUI_FROM_DATABASE=JATOM SYSTEMS, INC. OUI:00505C* ID_OUI_FROM_DATABASE=TUNDO CORPORATION OUI:005068* ID_OUI_FROM_DATABASE=ELECTRONIC INDUSTRIES ASSOCIATION OUI:00501A* ID_OUI_FROM_DATABASE=IQinVision OUI:005063* ID_OUI_FROM_DATABASE=OY COMSEL SYSTEM AB OUI:0050DE* ID_OUI_FROM_DATABASE=SIGNUM SYSTEMS CORP. OUI:00507B* ID_OUI_FROM_DATABASE=MERLOT COMMUNICATIONS OUI:005078* ID_OUI_FROM_DATABASE=MEGATON HOUSE, LTD. OUI:00508F* ID_OUI_FROM_DATABASE=ASITA TECHNOLOGIES INT'L LTD. OUI:005057* ID_OUI_FROM_DATABASE=BROADBAND ACCESS SYSTEMS OUI:005087* ID_OUI_FROM_DATABASE=TERASAKI ELECTRIC CO., LTD. OUI:005088* ID_OUI_FROM_DATABASE=AMANO CORPORATION OUI:0050A8* ID_OUI_FROM_DATABASE=OpenCon Systems, Inc. OUI:005062* ID_OUI_FROM_DATABASE=KOUWELL ELECTRONICS CORP. ** OUI:0050B1* ID_OUI_FROM_DATABASE=GIDDINGS & LEWIS OUI:00500C* ID_OUI_FROM_DATABASE=e-Tek Labs, Inc. OUI:005091* ID_OUI_FROM_DATABASE=NETACCESS, INC. OUI:005097* ID_OUI_FROM_DATABASE=MMC-EMBEDDED COMPUTERTECHNIK GmbH OUI:0050AF* ID_OUI_FROM_DATABASE=INTERGON, INC. OUI:0050EB* ID_OUI_FROM_DATABASE=ALPHA-TOP CORPORATION OUI:0050BC* ID_OUI_FROM_DATABASE=HAMMER STORAGE SOLUTIONS OUI:00900F* ID_OUI_FROM_DATABASE=KAWASAKI HEAVY INDUSTRIES, LTD OUI:009036* ID_OUI_FROM_DATABASE=ens, inc. OUI:0090E9* ID_OUI_FROM_DATABASE=JANZ COMPUTER AG OUI:009032* ID_OUI_FROM_DATABASE=PELCOMBE GROUP LTD. OUI:0090B8* ID_OUI_FROM_DATABASE=ROHDE & SCHWARZ GMBH & CO. KG OUI:009058* ID_OUI_FROM_DATABASE=Ultra Electronics Ltd., Command and Control Systems OUI:0090BE* ID_OUI_FROM_DATABASE=IBC/INTEGRATED BUSINESS COMPUTERS OUI:009062* ID_OUI_FROM_DATABASE=ICP VORTEX COMPUTERSYSTEME GmbH OUI:0090C3* ID_OUI_FROM_DATABASE=TOPIC SEMICONDUCTOR CORP. OUI:0090EC* ID_OUI_FROM_DATABASE=PYRESCOM OUI:00903B* ID_OUI_FROM_DATABASE=TriEMS Research Lab, Inc. OUI:009074* ID_OUI_FROM_DATABASE=ARGON NETWORKS, INC. OUI:0090C1* ID_OUI_FROM_DATABASE=Peco II, Inc. OUI:0010D3* ID_OUI_FROM_DATABASE=GRIPS ELECTRONIC GMBH OUI:001087* ID_OUI_FROM_DATABASE=Xstreamis PLC OUI:0010ED* ID_OUI_FROM_DATABASE=SUNDANCE TECHNOLOGY, INC. OUI:001023* ID_OUI_FROM_DATABASE=Network Equipment Technologies OUI:00104E* ID_OUI_FROM_DATABASE=CEOLOGIC OUI:0010FB* ID_OUI_FROM_DATABASE=ZIDA TECHNOLOGIES LIMITED OUI:0010AD* ID_OUI_FROM_DATABASE=SOFTRONICS USB, INC. OUI:0010D5* ID_OUI_FROM_DATABASE=IMASDE CANARIAS, S.A. OUI:0010E5* ID_OUI_FROM_DATABASE=SOLECTRON TEXAS OUI:00102A* ID_OUI_FROM_DATABASE=ZF MICROSYSTEMS, INC. OUI:00107D* ID_OUI_FROM_DATABASE=AURORA COMMUNICATIONS, LTD. OUI:00101C* ID_OUI_FROM_DATABASE=OHM TECHNOLOGIES INTL, LLC OUI:0090C5* ID_OUI_FROM_DATABASE=INTERNET MAGIC, INC. OUI:0090AD* ID_OUI_FROM_DATABASE=ASPECT ELECTRONICS, INC. OUI:009097* ID_OUI_FROM_DATABASE=Sycamore Networks OUI:009008* ID_OUI_FROM_DATABASE=HanA Systems Inc. OUI:0090D4* ID_OUI_FROM_DATABASE=BindView Development Corp. OUI:009089* ID_OUI_FROM_DATABASE=SOFTCOM MICROSYSTEMS, INC. OUI:0090C4* ID_OUI_FROM_DATABASE=JAVELIN SYSTEMS, INC. OUI:009014* ID_OUI_FROM_DATABASE=ROTORK INSTRUMENTS, LTD. OUI:0090B5* ID_OUI_FROM_DATABASE=NIKON CORPORATION OUI:0090C6* ID_OUI_FROM_DATABASE=OPTIM SYSTEMS, INC. OUI:00909B* ID_OUI_FROM_DATABASE=MARKEM-IMAJE OUI:00905B* ID_OUI_FROM_DATABASE=RAYMOND AND LAE ENGINEERING OUI:0090E8* ID_OUI_FROM_DATABASE=MOXA TECHNOLOGIES CORP., LTD. OUI:0090A1* ID_OUI_FROM_DATABASE=Flying Pig Systems/High End Systems Inc. OUI:0090FD* ID_OUI_FROM_DATABASE=CopperCom, Inc. OUI:0090AC* ID_OUI_FROM_DATABASE=OPTIVISION, INC. OUI:00902A* ID_OUI_FROM_DATABASE=COMMUNICATION DEVICES, INC. OUI:009098* ID_OUI_FROM_DATABASE=SBC DESIGNS, INC. OUI:0090CF* ID_OUI_FROM_DATABASE=NORTEL OUI:0050DA* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:0050F9* ID_OUI_FROM_DATABASE=Sensormatic Electronics LLC OUI:0050F6* ID_OUI_FROM_DATABASE=PAN-INTERNATIONAL INDUSTRIAL CORP. OUI:00506C* ID_OUI_FROM_DATABASE=Beijer Electronics Products AB OUI:0050A5* ID_OUI_FROM_DATABASE=CAPITOL BUSINESS SYSTEMS, LTD. OUI:005000* ID_OUI_FROM_DATABASE=NEXO COMMUNICATIONS, INC. OUI:005030* ID_OUI_FROM_DATABASE=FUTURE PLUS SYSTEMS OUI:005037* ID_OUI_FROM_DATABASE=KOGA ELECTRONICS CO. OUI:00106C* ID_OUI_FROM_DATABASE=EDNT GmbH OUI:0010D4* ID_OUI_FROM_DATABASE=STORAGE COMPUTER CORPORATION OUI:0010BF* ID_OUI_FROM_DATABASE=InterAir Wireless OUI:001036* ID_OUI_FROM_DATABASE=INTER-TEL INTEGRATED SYSTEMS OUI:001026* ID_OUI_FROM_DATABASE=ACCELERATED NETWORKS, INC. OUI:00104B* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:000629* ID_OUI_FROM_DATABASE=IBM Corp OUI:001004* ID_OUI_FROM_DATABASE=THE BRANTLEY COILE COMPANY,INC OUI:00103A* ID_OUI_FROM_DATABASE=DIAMOND NETWORK TECH OUI:0010D8* ID_OUI_FROM_DATABASE=CALISTA OUI:001031* ID_OUI_FROM_DATABASE=OBJECTIVE COMMUNICATIONS, INC. OUI:00103D* ID_OUI_FROM_DATABASE=PHASECOM, LTD. OUI:0010C2* ID_OUI_FROM_DATABASE=WILLNET, INC. OUI:00107A* ID_OUI_FROM_DATABASE=AmbiCom, Inc. OUI:0010C4* ID_OUI_FROM_DATABASE=MEDIA GLOBAL LINKS CO., LTD. OUI:0010EB* ID_OUI_FROM_DATABASE=SELSIUS SYSTEMS, INC. OUI:0010FE* ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION OUI:00102E* ID_OUI_FROM_DATABASE=NETWORK SYSTEMS & TECHNOLOGIES PVT. LTD. OUI:0010C1* ID_OUI_FROM_DATABASE=OI ELECTRIC CO., LTD. OUI:00103E* ID_OUI_FROM_DATABASE=NETSCHOOLS CORPORATION OUI:001049* ID_OUI_FROM_DATABASE=ShoreTel, Inc OUI:00105E* ID_OUI_FROM_DATABASE=Spirent plc, Service Assurance Broadband OUI:0010B1* ID_OUI_FROM_DATABASE=FOR-A CO., LTD. OUI:001041* ID_OUI_FROM_DATABASE=BRISTOL BABCOCK, INC. OUI:0010F7* ID_OUI_FROM_DATABASE=IRIICHI TECHNOLOGIES Inc. OUI:00E0FD* ID_OUI_FROM_DATABASE=A-TREND TECHNOLOGY CO., LTD. OUI:00E0FB* ID_OUI_FROM_DATABASE=LEIGHTRONIX, INC. OUI:00E0D3* ID_OUI_FROM_DATABASE=DATENTECHNIK GmbH OUI:00E05E* ID_OUI_FROM_DATABASE=JAPAN AVIATION ELECTRONICS INDUSTRY, LTD. OUI:00E0E5* ID_OUI_FROM_DATABASE=CINCO NETWORKS, INC. OUI:00E0A1* ID_OUI_FROM_DATABASE=HIMA PAUL HILDEBRANDT GmbH Co. KG OUI:00E028* ID_OUI_FROM_DATABASE=APTIX CORPORATION OUI:00E0F2* ID_OUI_FROM_DATABASE=ARLOTTO COMNET, INC. OUI:00E020* ID_OUI_FROM_DATABASE=TECNOMEN OY OUI:00E046* ID_OUI_FROM_DATABASE=BENTLY NEVADA CORP. OUI:00E015* ID_OUI_FROM_DATABASE=HEIWA CORPORATION OUI:00E065* ID_OUI_FROM_DATABASE=OPTICAL ACCESS INTERNATIONAL OUI:00E069* ID_OUI_FROM_DATABASE=JAYCOR OUI:00E05C* ID_OUI_FROM_DATABASE=Panasonic Healthcare Co., Ltd. OUI:00E087* ID_OUI_FROM_DATABASE=LeCroy - Networking Productions Division OUI:00E049* ID_OUI_FROM_DATABASE=MICROWI ELECTRONIC GmbH OUI:00E050* ID_OUI_FROM_DATABASE=EXECUTONE INFORMATION SYSTEMS, INC. OUI:00E064* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRONICS OUI:00E012* ID_OUI_FROM_DATABASE=PLUTO TECHNOLOGIES INTERNATIONAL INC. OUI:00E0D8* ID_OUI_FROM_DATABASE=LANBit Computer, Inc. OUI:00108F* ID_OUI_FROM_DATABASE=RAPTOR SYSTEMS OUI:001089* ID_OUI_FROM_DATABASE=WebSonic OUI:001086* ID_OUI_FROM_DATABASE=ATTO Technology, Inc. OUI:001027* ID_OUI_FROM_DATABASE=L-3 COMMUNICATIONS EAST OUI:0010B8* ID_OUI_FROM_DATABASE=ISHIGAKI COMPUTER SYSTEM CO. OUI:00104C* ID_OUI_FROM_DATABASE=Teledyne LeCroy, Inc OUI:001001* ID_OUI_FROM_DATABASE=Citel OUI:0010CF* ID_OUI_FROM_DATABASE=FIBERLANE COMMUNICATIONS OUI:001068* ID_OUI_FROM_DATABASE=COMOS TELECOM OUI:001067* ID_OUI_FROM_DATABASE=Ericsson OUI:0010F1* ID_OUI_FROM_DATABASE=I-O CORPORATION OUI:001073* ID_OUI_FROM_DATABASE=TECHNOBOX, INC. OUI:00107E* ID_OUI_FROM_DATABASE=BACHMANN ELECTRONIC GmbH OUI:0010C0* ID_OUI_FROM_DATABASE=ARMA, Inc. OUI:001016* ID_OUI_FROM_DATABASE=T.SQWARE OUI:00E02D* ID_OUI_FROM_DATABASE=InnoMediaLogic, Inc. OUI:00E0A9* ID_OUI_FROM_DATABASE=FUNAI ELECTRIC CO., LTD. OUI:00E035* ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies OUI:00E060* ID_OUI_FROM_DATABASE=SHERWOOD OUI:00E0A2* ID_OUI_FROM_DATABASE=MICROSLATE INC. OUI:00E06C* ID_OUI_FROM_DATABASE=Ultra Electronics Limited (AEP Networks) OUI:00E0CE* ID_OUI_FROM_DATABASE=ARN OUI:00E091* ID_OUI_FROM_DATABASE=LG ELECTRONICS, INC. OUI:00E05F* ID_OUI_FROM_DATABASE=e-Net, Inc. OUI:00E02B* ID_OUI_FROM_DATABASE=EXTREME NETWORKS OUI:00E0C7* ID_OUI_FROM_DATABASE=EUROTECH SRL OUI:00E0C4* ID_OUI_FROM_DATABASE=HORNER ELECTRIC, INC. OUI:0010E6* ID_OUI_FROM_DATABASE=APPLIED INTELLIGENT SYSTEMS, INC. OUI:00101E* ID_OUI_FROM_DATABASE=MATSUSHITA ELECTRONIC INSTRUMENTS CORP. OUI:0010F2* ID_OUI_FROM_DATABASE=ANTEC OUI:0010BE* ID_OUI_FROM_DATABASE=MARCH NETWORKS CORPORATION OUI:00E0C5* ID_OUI_FROM_DATABASE=BCOM ELECTRONICS INC. OUI:00E0EE* ID_OUI_FROM_DATABASE=MAREL HF OUI:00E0AC* ID_OUI_FROM_DATABASE=MIDSCO, INC. OUI:00E002* ID_OUI_FROM_DATABASE=CROSSROADS SYSTEMS, INC. OUI:00E057* ID_OUI_FROM_DATABASE=HAN MICROTELECOM. CO., LTD. OUI:00E0F0* ID_OUI_FROM_DATABASE=ABLER TECHNOLOGY, INC. OUI:00E0B7* ID_OUI_FROM_DATABASE=PI GROUP, LTD. OUI:00E0C0* ID_OUI_FROM_DATABASE=SEIWA ELECTRIC MFG. CO., LTD. OUI:006098* ID_OUI_FROM_DATABASE=HT COMMUNICATIONS OUI:0060F7* ID_OUI_FROM_DATABASE=DATAFUSION SYSTEMS OUI:0060DE* ID_OUI_FROM_DATABASE=Kayser-Threde GmbH OUI:0060D0* ID_OUI_FROM_DATABASE=SNMP RESEARCH INCORPORATED OUI:006079* ID_OUI_FROM_DATABASE=Mainstream Data, Inc. OUI:006020* ID_OUI_FROM_DATABASE=PIVOTAL NETWORKING, INC. OUI:0005A8* ID_OUI_FROM_DATABASE=WYLE ELECTRONICS OUI:0060B7* ID_OUI_FROM_DATABASE=CHANNELMATIC, INC. OUI:0060A3* ID_OUI_FROM_DATABASE=CONTINUUM TECHNOLOGY CORP. OUI:006050* ID_OUI_FROM_DATABASE=INTERNIX INC. OUI:0060E0* ID_OUI_FROM_DATABASE=AXIOM TECHNOLOGY CO., LTD. OUI:0060A8* ID_OUI_FROM_DATABASE=TIDOMAT AB OUI:00608E* ID_OUI_FROM_DATABASE=HE ELECTRONICS, TECHNOLOGIE & SYSTEMTECHNIK GmbH OUI:0060F0* ID_OUI_FROM_DATABASE=JOHNSON & JOHNSON MEDICAL, INC OUI:00A022* ID_OUI_FROM_DATABASE=CENTRE FOR DEVELOPMENT OF ADVANCED COMPUTING OUI:00A087* ID_OUI_FROM_DATABASE=Microsemi Corporation OUI:00A007* ID_OUI_FROM_DATABASE=APEXX TECHNOLOGY, INC. OUI:00A066* ID_OUI_FROM_DATABASE=ISA CO., LTD. OUI:00A0AB* ID_OUI_FROM_DATABASE=NETCS INFORMATIONSTECHNIK GMBH OUI:00A0D8* ID_OUI_FROM_DATABASE=SPECTRA - TEK OUI:00A01A* ID_OUI_FROM_DATABASE=BINAR ELEKTRONIK AB OUI:00A0E8* ID_OUI_FROM_DATABASE=REUTERS HOLDINGS PLC OUI:00A076* ID_OUI_FROM_DATABASE=CARDWARE LAB, INC. OUI:00A0A3* ID_OUI_FROM_DATABASE=RELIABLE POWER METERS OUI:00A055* ID_OUI_FROM_DATABASE=Data Device Corporation OUI:00A065* ID_OUI_FROM_DATABASE=Symantec Corporation OUI:00A044* ID_OUI_FROM_DATABASE=NTT IT CO., LTD. OUI:00A05F* ID_OUI_FROM_DATABASE=BTG Electronics Design BV OUI:00A094* ID_OUI_FROM_DATABASE=COMSAT CORPORATION OUI:00A010* ID_OUI_FROM_DATABASE=SYSLOGIC DATENTECHNIK AG OUI:00A012* ID_OUI_FROM_DATABASE=Telco Systems, Inc. OUI:00A063* ID_OUI_FROM_DATABASE=JRL SYSTEMS, INC. OUI:00A08F* ID_OUI_FROM_DATABASE=DESKNET SYSTEMS, INC. OUI:00A0CC* ID_OUI_FROM_DATABASE=LITE-ON COMMUNICATIONS, INC. OUI:00A090* ID_OUI_FROM_DATABASE=TimeStep Corporation OUI:00A0F7* ID_OUI_FROM_DATABASE=V.I COMPUTER CORP. OUI:00A09C* ID_OUI_FROM_DATABASE=Xyplex, Inc. OUI:00A0A0* ID_OUI_FROM_DATABASE=COMPACT DATA, LTD. OUI:0060C6* ID_OUI_FROM_DATABASE=DCS AG OUI:00609E* ID_OUI_FROM_DATABASE=ASC X3 - INFORMATION TECHNOLOGY STANDARDS SECRETARIATS OUI:006084* ID_OUI_FROM_DATABASE=DIGITAL VIDEO OUI:00602D* ID_OUI_FROM_DATABASE=ALERTON TECHNOLOGIES, INC. OUI:006093* ID_OUI_FROM_DATABASE=VARIAN OUI:0060E2* ID_OUI_FROM_DATABASE=QUEST ENGINEERING & DEVELOPMENT OUI:00A039* ID_OUI_FROM_DATABASE=ROSS TECHNOLOGY, INC. OUI:00A06D* ID_OUI_FROM_DATABASE=MANNESMANN TALLY CORPORATION OUI:00A056* ID_OUI_FROM_DATABASE=MICROPROSS OUI:00A051* ID_OUI_FROM_DATABASE=ANGIA COMMUNICATIONS. INC. OUI:00A0A6* ID_OUI_FROM_DATABASE=M.I. SYSTEMS, K.K. OUI:0060D2* ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES TAIWAN TELECOMMUNICATIONS CO., LTD. OUI:006077* ID_OUI_FROM_DATABASE=PRISA NETWORKS OUI:0060AB* ID_OUI_FROM_DATABASE=LARSCOM INCORPORATED OUI:0060E9* ID_OUI_FROM_DATABASE=ATOP TECHNOLOGIES, INC. OUI:00608B* ID_OUI_FROM_DATABASE=ConferTech International OUI:0060C3* ID_OUI_FROM_DATABASE=NETVISION CORPORATION OUI:006051* ID_OUI_FROM_DATABASE=QUALITY SEMICONDUCTOR OUI:00605E* ID_OUI_FROM_DATABASE=LIBERTY TECHNOLOGY NETWORKING OUI:006058* ID_OUI_FROM_DATABASE=COPPER MOUNTAIN COMMUNICATIONS, INC. OUI:00601B* ID_OUI_FROM_DATABASE=MESA ELECTRONICS OUI:0060FF* ID_OUI_FROM_DATABASE=QuVis, Inc. OUI:006056* ID_OUI_FROM_DATABASE=NETWORK TOOLS, INC. OUI:0060D8* ID_OUI_FROM_DATABASE=ELMIC SYSTEMS, INC. OUI:00607A* ID_OUI_FROM_DATABASE=DVS GMBH OUI:006097* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:0060E3* ID_OUI_FROM_DATABASE=ARBIN INSTRUMENTS OUI:006008* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:0060EF* ID_OUI_FROM_DATABASE=FLYTECH TECHNOLOGY CO., LTD. OUI:00E04D* ID_OUI_FROM_DATABASE=INTERNET INITIATIVE JAPAN, INC OUI:00607F* ID_OUI_FROM_DATABASE=AURORA TECHNOLOGIES, INC. OUI:00E039* ID_OUI_FROM_DATABASE=PARADYNE CORP. OUI:006091* ID_OUI_FROM_DATABASE=FIRST PACIFIC NETWORKS, INC. OUI:006002* ID_OUI_FROM_DATABASE=SCREEN SUBTITLING SYSTEMS, LTD OUI:006061* ID_OUI_FROM_DATABASE=WHISTLE COMMUNICATIONS CORP. OUI:0060BD* ID_OUI_FROM_DATABASE=HUBBELL-PULSECOM OUI:006074* ID_OUI_FROM_DATABASE=QSC AUDIO PRODUCTS OUI:00A024* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:00A0FD* ID_OUI_FROM_DATABASE=SCITEX DIGITAL PRINTING, INC. OUI:00A0F5* ID_OUI_FROM_DATABASE=RADGUARD LTD. OUI:00201B* ID_OUI_FROM_DATABASE=NORTHERN TELECOM/NETWORK OUI:0020C0* ID_OUI_FROM_DATABASE=PULSE ELECTRONICS, INC. OUI:00208D* ID_OUI_FROM_DATABASE=CMD TECHNOLOGY OUI:0020DD* ID_OUI_FROM_DATABASE=Cybertec Pty Ltd OUI:0020BD* ID_OUI_FROM_DATABASE=NIOBRARA R & D CORPORATION OUI:0020E6* ID_OUI_FROM_DATABASE=LIDKOPING MACHINE TOOLS AB OUI:002047* ID_OUI_FROM_DATABASE=STEINBRECHER CORP. OUI:0020B5* ID_OUI_FROM_DATABASE=YASKAWA ELECTRIC CORPORATION OUI:002072* ID_OUI_FROM_DATABASE=WORKLINK INNOVATIONS OUI:0020B8* ID_OUI_FROM_DATABASE=PRIME OPTION, INC. OUI:002092* ID_OUI_FROM_DATABASE=CHESS ENGINEERING B.V. OUI:0020B9* ID_OUI_FROM_DATABASE=METRICOM, INC. OUI:00206B* ID_OUI_FROM_DATABASE=KONICA MINOLTA HOLDINGS, INC. OUI:0020FC* ID_OUI_FROM_DATABASE=MATROX OUI:002035* ID_OUI_FROM_DATABASE=IBM Corp OUI:0020E2* ID_OUI_FROM_DATABASE=INFORMATION RESOURCE ENGINEERING OUI:002058* ID_OUI_FROM_DATABASE=ALLIED SIGNAL INC. OUI:00208C* ID_OUI_FROM_DATABASE=GALAXY NETWORKS, INC. OUI:002063* ID_OUI_FROM_DATABASE=WIPRO INFOTECH LTD. OUI:0020DC* ID_OUI_FROM_DATABASE=DENSITRON TAIWAN LTD. OUI:002078* ID_OUI_FROM_DATABASE=RUNTOP, INC. OUI:002042* ID_OUI_FROM_DATABASE=DATAMETRICS CORP. OUI:0020F8* ID_OUI_FROM_DATABASE=CARRERA COMPUTERS, INC. OUI:00200C* ID_OUI_FROM_DATABASE=ADASTRA SYSTEMS CORP. OUI:0020C4* ID_OUI_FROM_DATABASE=INET,INC. OUI:00C003* ID_OUI_FROM_DATABASE=GLOBALNET COMMUNICATIONS OUI:00C0C3* ID_OUI_FROM_DATABASE=ACUSON COMPUTED SONOGRAPHY OUI:00C04D* ID_OUI_FROM_DATABASE=MITEC, INC. OUI:00C055* ID_OUI_FROM_DATABASE=MODULAR COMPUTING TECHNOLOGIES OUI:00A0DB* ID_OUI_FROM_DATABASE=FISHER & PAYKEL PRODUCTION OUI:00A0A5* ID_OUI_FROM_DATABASE=TEKNOR MICROSYSTEME, INC. OUI:00A018* ID_OUI_FROM_DATABASE=CREATIVE CONTROLLERS, INC. OUI:00A09F* ID_OUI_FROM_DATABASE=COMMVISION CORP. OUI:00A06B* ID_OUI_FROM_DATABASE=DMS DORSCH MIKROSYSTEM GMBH OUI:00209F* ID_OUI_FROM_DATABASE=MERCURY COMPUTER SYSTEMS, INC. OUI:0020B7* ID_OUI_FROM_DATABASE=NAMAQUA COMPUTERWARE OUI:00C005* ID_OUI_FROM_DATABASE=LIVINGSTON ENTERPRISES, INC. OUI:00C064* ID_OUI_FROM_DATABASE=GENERAL DATACOMM IND. INC. OUI:00C0C8* ID_OUI_FROM_DATABASE=MICRO BYTE PTY. LTD. OUI:00C090* ID_OUI_FROM_DATABASE=PRAIM S.R.L. OUI:00C011* ID_OUI_FROM_DATABASE=INTERACTIVE COMPUTING DEVICES OUI:00C0FD* ID_OUI_FROM_DATABASE=PROSUM OUI:00C041* ID_OUI_FROM_DATABASE=DIGITAL TRANSMISSION SYSTEMS OUI:00C00F* ID_OUI_FROM_DATABASE=QUANTUM SOFTWARE SYSTEMS LTD. OUI:00C076* ID_OUI_FROM_DATABASE=I-DATA INTERNATIONAL A-S OUI:00C0C6* ID_OUI_FROM_DATABASE=PERSONAL MEDIA CORP. OUI:00C03B* ID_OUI_FROM_DATABASE=MULTIACCESS COMPUTING CORP. OUI:00C099* ID_OUI_FROM_DATABASE=YOSHIKI INDUSTRIAL CO.,LTD. OUI:00C0FC* ID_OUI_FROM_DATABASE=ELASTIC REALITY, INC. OUI:00C067* ID_OUI_FROM_DATABASE=UNITED BARCODE INDUSTRIES OUI:00C0B4* ID_OUI_FROM_DATABASE=MYSON TECHNOLOGY, INC. OUI:00C080* ID_OUI_FROM_DATABASE=NETSTAR, INC. OUI:00C015* ID_OUI_FROM_DATABASE=NEW MEDIA CORPORATION OUI:00C09F* ID_OUI_FROM_DATABASE=QUANTA COMPUTER, INC. OUI:0070B3* ID_OUI_FROM_DATABASE=DATA RECALL LTD. OUI:00E6D3* ID_OUI_FROM_DATABASE=NIXDORF COMPUTER CORP. OUI:00C083* ID_OUI_FROM_DATABASE=TRACE MOUNTAIN PRODUCTS, INC. OUI:002081* ID_OUI_FROM_DATABASE=TITAN ELECTRONICS OUI:00201D* ID_OUI_FROM_DATABASE=KATANA PRODUCTS OUI:0020CF* ID_OUI_FROM_DATABASE=TEST & MEASUREMENT SYSTEMS INC OUI:002043* ID_OUI_FROM_DATABASE=NEURON COMPANY LIMITED OUI:002018* ID_OUI_FROM_DATABASE=CIS TECHNOLOGY INC. OUI:002031* ID_OUI_FROM_DATABASE=Tattile SRL OUI:0020DE* ID_OUI_FROM_DATABASE=JAPAN DIGITAL LABORAT'Y CO.LTD OUI:0020F7* ID_OUI_FROM_DATABASE=CYBERDATA CORPORATION OUI:000267* ID_OUI_FROM_DATABASE=NODE RUNNER, INC. OUI:002064* ID_OUI_FROM_DATABASE=PROTEC MICROSYSTEMS, INC. OUI:002032* ID_OUI_FROM_DATABASE=ALCATEL TAISEL OUI:002027* ID_OUI_FROM_DATABASE=MING FORTUNE INDUSTRY CO., LTD OUI:0020ED* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO., LTD. OUI:00200E* ID_OUI_FROM_DATABASE=SATELLITE TECHNOLOGY MGMT, INC OUI:002096* ID_OUI_FROM_DATABASE=Invensys OUI:0020BB* ID_OUI_FROM_DATABASE=ZAX CORPORATION OUI:00204D* ID_OUI_FROM_DATABASE=INOVIS GMBH OUI:002089* ID_OUI_FROM_DATABASE=T3PLUS NETWORKING, INC. OUI:00205F* ID_OUI_FROM_DATABASE=GAMMADATA COMPUTER GMBH OUI:0020EE* ID_OUI_FROM_DATABASE=GTECH CORPORATION OUI:00A08B* ID_OUI_FROM_DATABASE=ASTON ELECTRONIC DESIGNS LTD. OUI:00A0AA* ID_OUI_FROM_DATABASE=SPACELABS MEDICAL OUI:00A04F* ID_OUI_FROM_DATABASE=AMERITEC CORP. OUI:00A073* ID_OUI_FROM_DATABASE=COM21, INC. OUI:00A084* ID_OUI_FROM_DATABASE=Dataplex Pty Ltd OUI:00A034* ID_OUI_FROM_DATABASE=AXEL OUI:00A092* ID_OUI_FROM_DATABASE=H. BOLLMANN MANUFACTURERS, LTD OUI:00A04D* ID_OUI_FROM_DATABASE=EDA INSTRUMENTS, INC. OUI:00207F* ID_OUI_FROM_DATABASE=KYOEI SANGYO CO., LTD. OUI:002077* ID_OUI_FROM_DATABASE=KARDIOS SYSTEMS CORP. OUI:002068* ID_OUI_FROM_DATABASE=ISDYNE OUI:00202A* ID_OUI_FROM_DATABASE=N.V. DZINE OUI:0020F4* ID_OUI_FROM_DATABASE=SPECTRIX CORPORATION OUI:00204E* ID_OUI_FROM_DATABASE=NETWORK SECURITY SYSTEMS, INC. OUI:00C074* ID_OUI_FROM_DATABASE=TOYODA AUTOMATIC LOOM OUI:00C07F* ID_OUI_FROM_DATABASE=NUPON COMPUTING CORP. OUI:00C027* ID_OUI_FROM_DATABASE=CIPHER SYSTEMS, INC. OUI:00C025* ID_OUI_FROM_DATABASE=DATAPRODUCTS CORPORATION OUI:00C022* ID_OUI_FROM_DATABASE=LASERMASTER TECHNOLOGIES, INC. OUI:00C0E6* ID_OUI_FROM_DATABASE=Verilink Corporation OUI:00C05C* ID_OUI_FROM_DATABASE=ELONEX PLC OUI:00C0C1* ID_OUI_FROM_DATABASE=QUAD/GRAPHICS, INC. OUI:00C091* ID_OUI_FROM_DATABASE=JABIL CIRCUIT, INC. OUI:00C002* ID_OUI_FROM_DATABASE=SERCOMM CORPORATION OUI:00C0F5* ID_OUI_FROM_DATABASE=METACOMP, INC. OUI:00C042* ID_OUI_FROM_DATABASE=DATALUX CORP. OUI:00C089* ID_OUI_FROM_DATABASE=TELINDUS DISTRIBUTION OUI:00C09D* ID_OUI_FROM_DATABASE=DISTRIBUTED SYSTEMS INT'L, INC OUI:00C0A5* ID_OUI_FROM_DATABASE=DICKENS DATA SYSTEMS OUI:00C0E3* ID_OUI_FROM_DATABASE=OSITECH COMMUNICATIONS, INC. OUI:00C071* ID_OUI_FROM_DATABASE=AREANEX COMMUNICATIONS, INC. OUI:00C0AF* ID_OUI_FROM_DATABASE=TEKLOGIX INC. OUI:00C05D* ID_OUI_FROM_DATABASE=L&N TECHNOLOGIES OUI:00C0E4* ID_OUI_FROM_DATABASE=SIEMENS BUILDING OUI:0040C4* ID_OUI_FROM_DATABASE=KINKEI SYSTEM CORPORATION OUI:0040D1* ID_OUI_FROM_DATABASE=FUKUDA DENSHI CO., LTD. OUI:004024* ID_OUI_FROM_DATABASE=COMPAC INC. OUI:0040B6* ID_OUI_FROM_DATABASE=COMPUTERM CORPORATION OUI:00403F* ID_OUI_FROM_DATABASE=SSANGYONG COMPUTER SYSTEMS OUI:004003* ID_OUI_FROM_DATABASE=Emerson Process Management Power & Water Solutions, Inc. OUI:004090* ID_OUI_FROM_DATABASE=ANSEL COMMUNICATIONS OUI:00409A* ID_OUI_FROM_DATABASE=NETWORK EXPRESS, INC. OUI:004055* ID_OUI_FROM_DATABASE=METRONIX GMBH OUI:00C01B* ID_OUI_FROM_DATABASE=SOCKET COMMUNICATIONS, INC. OUI:00C06E* ID_OUI_FROM_DATABASE=HAFT TECHNOLOGY, INC. OUI:00406F* ID_OUI_FROM_DATABASE=SYNC RESEARCH INC. OUI:00401F* ID_OUI_FROM_DATABASE=COLORGRAPH LTD OUI:0040CF* ID_OUI_FROM_DATABASE=STRAWBERRY TREE, INC. OUI:0040F7* ID_OUI_FROM_DATABASE=Polaroid Corporation OUI:004037* ID_OUI_FROM_DATABASE=SEA-ILAN, INC. OUI:0040CC* ID_OUI_FROM_DATABASE=SILCOM MANUF'G TECHNOLOGY INC. OUI:00404C* ID_OUI_FROM_DATABASE=HYPERTEC PTY LTD. OUI:00C0EE* ID_OUI_FROM_DATABASE=KYOCERA CORPORATION OUI:0040A5* ID_OUI_FROM_DATABASE=CLINICOMP INTL. OUI:004059* ID_OUI_FROM_DATABASE=YOSHIDA KOGYO K. K. OUI:004021* ID_OUI_FROM_DATABASE=RASTER GRAPHICS OUI:004081* ID_OUI_FROM_DATABASE=MANNESMANN SCANGRAPHIC GMBH OUI:00806C* ID_OUI_FROM_DATABASE=CEGELEC PROJECTS LTD OUI:00404A* ID_OUI_FROM_DATABASE=WEST AUSTRALIAN DEPARTMENT OUI:00400A* ID_OUI_FROM_DATABASE=PIVOTAL TECHNOLOGIES, INC. OUI:004032* ID_OUI_FROM_DATABASE=DIGITAL COMMUNICATIONS OUI:004042* ID_OUI_FROM_DATABASE=N.A.T. GMBH OUI:0040C2* ID_OUI_FROM_DATABASE=APPLIED COMPUTING DEVICES OUI:00403C* ID_OUI_FROM_DATABASE=FORKS, INC. OUI:004004* ID_OUI_FROM_DATABASE=ICM CO. LTD. OUI:00C0CB* ID_OUI_FROM_DATABASE=CONTROL TECHNOLOGY CORPORATION OUI:00C09A* ID_OUI_FROM_DATABASE=PHOTONICS CORPORATION OUI:00C01A* ID_OUI_FROM_DATABASE=COROMETRICS MEDICAL SYSTEMS OUI:00404B* ID_OUI_FROM_DATABASE=MAPLE COMPUTER SYSTEMS OUI:00401D* ID_OUI_FROM_DATABASE=INVISIBLE SOFTWARE, INC. OUI:0040BD* ID_OUI_FROM_DATABASE=STARLIGHT NETWORKS, INC. OUI:00406D* ID_OUI_FROM_DATABASE=LANCO, INC. OUI:00404D* ID_OUI_FROM_DATABASE=TELECOMMUNICATIONS TECHNIQUES OUI:00C0D0* ID_OUI_FROM_DATABASE=RATOC SYSTEM INC. OUI:00C07A* ID_OUI_FROM_DATABASE=PRIVA B.V. OUI:000701* ID_OUI_FROM_DATABASE=RACAL-DATACOM OUI:00C09C* ID_OUI_FROM_DATABASE=HIOKI E.E. CORPORATION OUI:00C004* ID_OUI_FROM_DATABASE=JAPAN BUSINESS COMPUTER CO.LTD OUI:00C062* ID_OUI_FROM_DATABASE=IMPULSE TECHNOLOGY OUI:00C0BC* ID_OUI_FROM_DATABASE=TELECOM AUSTRALIA/CSSC OUI:00C0EF* ID_OUI_FROM_DATABASE=ABIT CORPORATION OUI:00C03C* ID_OUI_FROM_DATABASE=TOWER TECH S.R.L. OUI:00C061* ID_OUI_FROM_DATABASE=SOLECTEK CORPORATION OUI:004045* ID_OUI_FROM_DATABASE=TWINHEAD CORPORATION OUI:00409D* ID_OUI_FROM_DATABASE=DIGIBOARD, INC. OUI:00401A* ID_OUI_FROM_DATABASE=FUJI ELECTRIC CO., LTD. OUI:0040B9* ID_OUI_FROM_DATABASE=MACQ ELECTRONIQUE SA OUI:0040C7* ID_OUI_FROM_DATABASE=RUBY TECH CORPORATION OUI:004052* ID_OUI_FROM_DATABASE=STAR TECHNOLOGIES, INC. OUI:00407A* ID_OUI_FROM_DATABASE=SOCIETE D'EXPLOITATION DU CNIT OUI:004089* ID_OUI_FROM_DATABASE=MEIDENSHA CORPORATION OUI:00405A* ID_OUI_FROM_DATABASE=GOLDSTAR INFORMATION & COMM. OUI:004070* ID_OUI_FROM_DATABASE=INTERWARE CO., LTD. OUI:008057* ID_OUI_FROM_DATABASE=ADSOFT, LTD. OUI:00807A* ID_OUI_FROM_DATABASE=AITECH SYSTEMS LTD. OUI:0080AA* ID_OUI_FROM_DATABASE=MAXPEED OUI:00C0E7* ID_OUI_FROM_DATABASE=FIBERDATA AB OUI:008095* ID_OUI_FROM_DATABASE=BASIC MERTON HANDELSGES.M.B.H. OUI:008053* ID_OUI_FROM_DATABASE=INTELLICOM, INC. OUI:008026* ID_OUI_FROM_DATABASE=NETWORK PRODUCTS CORPORATION OUI:0080FE* ID_OUI_FROM_DATABASE=AZURE TECHNOLOGIES, INC. OUI:008028* ID_OUI_FROM_DATABASE=TRADPOST (HK) LTD OUI:0080B6* ID_OUI_FROM_DATABASE=THEMIS COMPUTER OUI:008058* ID_OUI_FROM_DATABASE=PRINTER SYSTEMS CORPORATION OUI:0080C0* ID_OUI_FROM_DATABASE=PENRIL DATACOMM OUI:0080F5* ID_OUI_FROM_DATABASE=Quantel Ltd OUI:00608C* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:00804E* ID_OUI_FROM_DATABASE=APEX COMPUTER COMPANY OUI:00800E* ID_OUI_FROM_DATABASE=ATLANTIX CORPORATION OUI:0080DA* ID_OUI_FROM_DATABASE=Bruel & Kjaer Sound & Vibration Measurement A/S OUI:0080BC* ID_OUI_FROM_DATABASE=HITACHI ENGINEERING CO., LTD OUI:008000* ID_OUI_FROM_DATABASE=MULTITECH SYSTEMS, INC. OUI:0080A1* ID_OUI_FROM_DATABASE=MICROTEST, INC. OUI:0080D0* ID_OUI_FROM_DATABASE=COMPUTER PERIPHERALS, INC. OUI:00807D* ID_OUI_FROM_DATABASE=EQUINOX SYSTEMS INC. OUI:008063* ID_OUI_FROM_DATABASE=Hirschmann Automation and Control GmbH OUI:008030* ID_OUI_FROM_DATABASE=NEXUS ELECTRONICS OUI:008022* ID_OUI_FROM_DATABASE=SCAN-OPTICS OUI:000041* ID_OUI_FROM_DATABASE=ICE CORPORATION OUI:0040DE* ID_OUI_FROM_DATABASE=Elsag Datamat spa OUI:004063* ID_OUI_FROM_DATABASE=VIA TECHNOLOGIES, INC. OUI:00406C* ID_OUI_FROM_DATABASE=COPERNIQUE OUI:0040DF* ID_OUI_FROM_DATABASE=DIGALOG SYSTEMS, INC. OUI:004015* ID_OUI_FROM_DATABASE=ASCOM INFRASYS AG OUI:008056* ID_OUI_FROM_DATABASE=SPHINX Electronics GmbH & Co KG OUI:008060* ID_OUI_FROM_DATABASE=NETWORK INTERFACE CORPORATION OUI:00805E* ID_OUI_FROM_DATABASE=LSI LOGIC CORPORATION OUI:008093* ID_OUI_FROM_DATABASE=XYRON CORPORATION OUI:008006* ID_OUI_FROM_DATABASE=COMPUADD CORPORATION OUI:0080EF* ID_OUI_FROM_DATABASE=RATIONAL OUI:0080C4* ID_OUI_FROM_DATABASE=DOCUMENT TECHNOLOGIES, INC. OUI:00801D* ID_OUI_FROM_DATABASE=INTEGRATED INFERENCE MACHINES OUI:008015* ID_OUI_FROM_DATABASE=SEIKO SYSTEMS, INC. OUI:008034* ID_OUI_FROM_DATABASE=SMT GOUPIL OUI:0080C9* ID_OUI_FROM_DATABASE=ALBERTA MICROELECTRONIC CENTRE OUI:00800B* ID_OUI_FROM_DATABASE=CSK CORPORATION OUI:00800A* ID_OUI_FROM_DATABASE=JAPAN COMPUTER CORP. OUI:00806E* ID_OUI_FROM_DATABASE=NIPPON STEEL CORPORATION OUI:008010* ID_OUI_FROM_DATABASE=COMMODORE INTERNATIONAL OUI:0000C8* ID_OUI_FROM_DATABASE=ALTOS COMPUTER SYSTEMS OUI:000098* ID_OUI_FROM_DATABASE=CROSSCOMM CORPORATION OUI:00007D* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:0000A2* ID_OUI_FROM_DATABASE=Bay Networks OUI:000038* ID_OUI_FROM_DATABASE=CSS LABS OUI:000061* ID_OUI_FROM_DATABASE=GATEWAY COMMUNICATIONS OUI:000043* ID_OUI_FROM_DATABASE=MICRO TECHNOLOGY OUI:0000E7* ID_OUI_FROM_DATABASE=Star Gate Technologies OUI:0000F3* ID_OUI_FROM_DATABASE=GANDALF DATA LIMITED OUI:00005C* ID_OUI_FROM_DATABASE=TELEMATICS INTERNATIONAL INC. OUI:0000AC* ID_OUI_FROM_DATABASE=CONWARE COMPUTER CONSULTING OUI:0000F2* ID_OUI_FROM_DATABASE=SPIDER COMMUNICATIONS OUI:000030* ID_OUI_FROM_DATABASE=VG LABORATORY SYSTEMS LTD OUI:000035* ID_OUI_FROM_DATABASE=SPECTRAGRAPHICS CORPORATION OUI:0000E0* ID_OUI_FROM_DATABASE=QUADRAM CORP. OUI:000057* ID_OUI_FROM_DATABASE=SCITEX CORPORATION LTD. OUI:0000D6* ID_OUI_FROM_DATABASE=PUNCH LINE HOLDING OUI:00806F* ID_OUI_FROM_DATABASE=ONELAN LTD. OUI:008098* ID_OUI_FROM_DATABASE=TDK CORPORATION OUI:00809C* ID_OUI_FROM_DATABASE=LUXCOM, INC. OUI:008065* ID_OUI_FROM_DATABASE=CYBERGRAPHIC SYSTEMS PTY LTD. OUI:008016* ID_OUI_FROM_DATABASE=WANDEL AND GOLTERMANN OUI:0080E6* ID_OUI_FROM_DATABASE=PEER NETWORKS, INC. OUI:0080A2* ID_OUI_FROM_DATABASE=CREATIVE ELECTRONIC SYSTEMS OUI:0080E0* ID_OUI_FROM_DATABASE=XTP SYSTEMS, INC. OUI:008050* ID_OUI_FROM_DATABASE=ZIATECH CORPORATION OUI:0080FF* ID_OUI_FROM_DATABASE=SOC. DE TELEINFORMATIQUE RTC OUI:000070* ID_OUI_FROM_DATABASE=HCL LIMITED OUI:00008E* ID_OUI_FROM_DATABASE=SOLBOURNE COMPUTER, INC. OUI:0000DC* ID_OUI_FROM_DATABASE=HAYES MICROCOMPUTER PRODUCTS OUI:000024* ID_OUI_FROM_DATABASE=CONNECT AS OUI:000048* ID_OUI_FROM_DATABASE=SEIKO EPSON CORPORATION OUI:000016* ID_OUI_FROM_DATABASE=DU PONT PIXEL SYSTEMS . OUI:00001E* ID_OUI_FROM_DATABASE=TELSIST INDUSTRIA ELECTRONICA OUI:00807B* ID_OUI_FROM_DATABASE=ARTEL COMMUNICATIONS CORP. OUI:00802E* ID_OUI_FROM_DATABASE=CASTLE ROCK COMPUTING OUI:0080F9* ID_OUI_FROM_DATABASE=HEURIKON CORPORATION OUI:008005* ID_OUI_FROM_DATABASE=CACTUS COMPUTER INC. OUI:008008* ID_OUI_FROM_DATABASE=DYNATECH COMPUTER SYSTEMS OUI:08005E* ID_OUI_FROM_DATABASE=COUNTERPOINT COMPUTER INC. OUI:08005A* ID_OUI_FROM_DATABASE=IBM Corp OUI:080056* ID_OUI_FROM_DATABASE=STANFORD LINEAR ACCEL. CENTER OUI:080053* ID_OUI_FROM_DATABASE=MIDDLE EAST TECH. UNIVERSITY OUI:08004F* ID_OUI_FROM_DATABASE=CYGNET SYSTEMS OUI:080040* ID_OUI_FROM_DATABASE=FERRANTI COMPUTER SYS. LIMITED OUI:08003B* ID_OUI_FROM_DATABASE=TORUS SYSTEMS LIMITED OUI:08003D* ID_OUI_FROM_DATABASE=CADNETIX CORPORATIONS OUI:080039* ID_OUI_FROM_DATABASE=SPIDER SYSTEMS LIMITED OUI:00DD0C* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:000005* ID_OUI_FROM_DATABASE=XEROX CORPORATION OUI:0000AA* ID_OUI_FROM_DATABASE=XEROX CORPORATION OUI:000064* ID_OUI_FROM_DATABASE=Yokogawa Electric Corporation OUI:00002C* ID_OUI_FROM_DATABASE=AUTOTOTE LIMITED OUI:00002A* ID_OUI_FROM_DATABASE=TRW - SEDD/INP OUI:0000F1* ID_OUI_FROM_DATABASE=MAGNA COMPUTER CORPORATION OUI:000083* ID_OUI_FROM_DATABASE=TADPOLE TECHNOLOGY PLC OUI:000020* ID_OUI_FROM_DATABASE=DATAINDUSTRIER DIAB AB OUI:00007A* ID_OUI_FROM_DATABASE=DANA COMPUTER INC. OUI:00007C* ID_OUI_FROM_DATABASE=AMPERE INCORPORATED OUI:00008A* ID_OUI_FROM_DATABASE=DATAHOUSE INFORMATION SYSTEMS OUI:080030* ID_OUI_FROM_DATABASE=NETWORK RESEARCH CORPORATION OUI:080027* ID_OUI_FROM_DATABASE=Cadmus Computer Systems OUI:020701* ID_OUI_FROM_DATABASE=RACAL-DATACOM OUI:080011* ID_OUI_FROM_DATABASE=TEKTRONIX INC. OUI:08007F* ID_OUI_FROM_DATABASE=CARNEGIE-MELLON UNIVERSITY OUI:080082* ID_OUI_FROM_DATABASE=VERITAS SOFTWARE OUI:08007B* ID_OUI_FROM_DATABASE=SANYO ELECTRIC CO. LTD. OUI:080074* ID_OUI_FROM_DATABASE=CASIO COMPUTER CO. LTD. OUI:00406B* ID_OUI_FROM_DATABASE=SYSGEN OUI:AA0001* ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION OUI:080001* ID_OUI_FROM_DATABASE=COMPUTERVISION CORPORATION OUI:000053* ID_OUI_FROM_DATABASE=COMPUCORP OUI:08004B* ID_OUI_FROM_DATABASE=Planning Research Corp. OUI:080003* ID_OUI_FROM_DATABASE=ADVANCED COMPUTER COMM. OUI:00009B* ID_OUI_FROM_DATABASE=INFORMATION INTERNATIONAL, INC OUI:000068* ID_OUI_FROM_DATABASE=ROSEMOUNT CONTROLS OUI:0000A8* ID_OUI_FROM_DATABASE=STRATUS COMPUTER INC. OUI:0000DF* ID_OUI_FROM_DATABASE=BELL & HOWELL PUB SYS DIV OUI:000062* ID_OUI_FROM_DATABASE=BULL HN INFORMATION SYSTEMS OUI:0000AD* ID_OUI_FROM_DATABASE=BRUKER INSTRUMENTS INC. OUI:0000D0* ID_OUI_FROM_DATABASE=DEVELCON ELECTRONICS LTD. OUI:000093* ID_OUI_FROM_DATABASE=PROTEON INC. OUI:0000A0* ID_OUI_FROM_DATABASE=SANYO Electric Co., Ltd. OUI:00DD0F* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:000001* ID_OUI_FROM_DATABASE=XEROX CORPORATION OUI:080021* ID_OUI_FROM_DATABASE=3M COMPANY OUI:AA0004* ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION OUI:08000C* ID_OUI_FROM_DATABASE=MIKLYN DEVELOPMENT CO. OUI:00DD08* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:0000D8* ID_OUI_FROM_DATABASE=NOVELL, INC. OUI:F8E71E* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:A01B29* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:90013B* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:ECDF3A* ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. OUI:E45AA2* ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. OUI:00194B* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:001F95* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:000E59* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:00235A* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:001B38* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:E46F13* ID_OUI_FROM_DATABASE=D-Link International OUI:DC6DCD* ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD OUI:94C150* ID_OUI_FROM_DATABASE=2Wire Inc OUI:60FE20* ID_OUI_FROM_DATABASE=2Wire Inc OUI:D4AE52* ID_OUI_FROM_DATABASE=Dell Inc. OUI:989096* ID_OUI_FROM_DATABASE=Dell Inc. OUI:B82A72* ID_OUI_FROM_DATABASE=Dell Inc. OUI:00D09E* ID_OUI_FROM_DATABASE=2Wire Inc OUI:000D72* ID_OUI_FROM_DATABASE=2Wire Inc OUI:B0E754* ID_OUI_FROM_DATABASE=2Wire Inc OUI:B8E625* ID_OUI_FROM_DATABASE=2Wire Inc OUI:000F1F* ID_OUI_FROM_DATABASE=Dell Inc. OUI:14FEB5* ID_OUI_FROM_DATABASE=Dell Inc. OUI:0015C5* ID_OUI_FROM_DATABASE=Dell Inc. OUI:549F35* ID_OUI_FROM_DATABASE=Dell Inc. OUI:64006A* ID_OUI_FROM_DATABASE=Dell Inc. OUI:B4E10F* ID_OUI_FROM_DATABASE=Dell Inc. OUI:0023AE* ID_OUI_FROM_DATABASE=Dell Inc. OUI:9CD917* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:9068C3* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:408805* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:A4A1C2* ID_OUI_FROM_DATABASE=Ericsson AB OUI:348446* ID_OUI_FROM_DATABASE=Ericsson AB OUI:F8F1B6* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:AC2B6E* ID_OUI_FROM_DATABASE=Intel Corporate OUI:00216A* ID_OUI_FROM_DATABASE=Intel Corporate OUI:001E64* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0016EB* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0018DE* ID_OUI_FROM_DATABASE=Intel Corporate OUI:28B2BD* ID_OUI_FROM_DATABASE=Intel Corporate OUI:08D40C* ID_OUI_FROM_DATABASE=Intel Corporate OUI:843A4B* ID_OUI_FROM_DATABASE=Intel Corporate OUI:681729* ID_OUI_FROM_DATABASE=Intel Corporate OUI:5C514F* ID_OUI_FROM_DATABASE=Intel Corporate OUI:B808CF* ID_OUI_FROM_DATABASE=Intel Corporate OUI:5CC5D4* ID_OUI_FROM_DATABASE=Intel Corporate OUI:7CCCB8* ID_OUI_FROM_DATABASE=Intel Corporate OUI:F40669* ID_OUI_FROM_DATABASE=Intel Corporate OUI:C8F733* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0CD292* ID_OUI_FROM_DATABASE=Intel Corporate OUI:78929C* ID_OUI_FROM_DATABASE=Intel Corporate OUI:6805CA* ID_OUI_FROM_DATABASE=Intel Corporate OUI:4851B7* ID_OUI_FROM_DATABASE=Intel Corporate OUI:3CA9F4* ID_OUI_FROM_DATABASE=Intel Corporate OUI:ACA31E* ID_OUI_FROM_DATABASE=Aruba Networks OUI:9C1C12* ID_OUI_FROM_DATABASE=Aruba Networks OUI:001A1E* ID_OUI_FROM_DATABASE=Aruba Networks OUI:28C2DD* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:84D47E* ID_OUI_FROM_DATABASE=Aruba Networks OUI:A85840* ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. OUI:002423* ID_OUI_FROM_DATABASE=AzureWave Technologies (Shanghai) Inc. OUI:002243* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:74F06D* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:44D832* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:781881* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:B0EE45* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:240A64* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:D0E782* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:A81D16* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:38A53C* ID_OUI_FROM_DATABASE=COMECER Netherlands OUI:0C4C39* ID_OUI_FROM_DATABASE=MitraStar Technology Corp. OUI:581243* ID_OUI_FROM_DATABASE=AcSiP Technology Corp. OUI:0026B8* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:0030F1* ID_OUI_FROM_DATABASE=Accton Technology Corp OUI:001974* ID_OUI_FROM_DATABASE=16063 OUI:3039F2* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:000827* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:001D8B* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:A4526F* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:001CA8* ID_OUI_FROM_DATABASE=AirTies Wireless Netowrks OUI:9097D5* ID_OUI_FROM_DATABASE=Espressif Inc. OUI:18FE34* ID_OUI_FROM_DATABASE=Espressif Inc. OUI:54F6C5* ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD OUI:A43111* ID_OUI_FROM_DATABASE=ZIV OUI:ECF00E* ID_OUI_FROM_DATABASE=AboCom OUI:28EF01* ID_OUI_FROM_DATABASE=Private OUI:5C338E* ID_OUI_FROM_DATABASE=Alpha Networks Inc. OUI:001AEB* ID_OUI_FROM_DATABASE=Allied Telesis R&D Center K.K. OUI:5C93A2* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:E8C74F* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:E8F724* ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise OUI:747548* ID_OUI_FROM_DATABASE=Amazon Technologies Inc. OUI:080046* ID_OUI_FROM_DATABASE=Sony Corporation OUI:001DBA* ID_OUI_FROM_DATABASE=Sony Corporation OUI:000AD9* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:000FDE* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:001EDC* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:001963* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:001B59* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:78843C* ID_OUI_FROM_DATABASE=Sony Corporation OUI:701A04* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:48D224* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:2CD05A* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:74E543* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:A4DB30* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:B8EE65* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:0023F1* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:3017C8* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:18002D* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:04E676* ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. OUI:0022F4* ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. OUI:1C1448* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:707E43* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0003E0* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:00128A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001225* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001AAD* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:A47AA4* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:3C754A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0024C1* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:002136* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0022B4* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:002395* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0023ED* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:745612* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:E46449* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:002493* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:40FC89* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001B52* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:00230B* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001E8D* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0023A2* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001BDD* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001404* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:00195E* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0011F5* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:DCD87C* ID_OUI_FROM_DATABASE=Beijing Jingdong Century Trading Co., LTD. OUI:001C4A* ID_OUI_FROM_DATABASE=AVM GmbH OUI:000B6A* ID_OUI_FROM_DATABASE=Asiarock Technology Limited OUI:40BA61* ID_OUI_FROM_DATABASE=ARIMA Communications Corp. OUI:000D92* ID_OUI_FROM_DATABASE=ARIMA Communications Corp. OUI:009096* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:204E7F* ID_OUI_FROM_DATABASE=NETGEAR OUI:A021B7* ID_OUI_FROM_DATABASE=NETGEAR OUI:0024B2* ID_OUI_FROM_DATABASE=NETGEAR OUI:C03F0E* ID_OUI_FROM_DATABASE=NETGEAR OUI:001F33* ID_OUI_FROM_DATABASE=NETGEAR OUI:841B5E* ID_OUI_FROM_DATABASE=NETGEAR OUI:001CCC* ID_OUI_FROM_DATABASE=BlackBerry RTS OUI:94EBCD* ID_OUI_FROM_DATABASE=BlackBerry RTS OUI:A4E4B8* ID_OUI_FROM_DATABASE=BlackBerry RTS OUI:58671A* ID_OUI_FROM_DATABASE=Barnes&Noble OUI:BC0543* ID_OUI_FROM_DATABASE=AVM GmbH OUI:002675* ID_OUI_FROM_DATABASE=Aztech Electronics Pte Ltd OUI:001D19* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:88252C* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:1883BF* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:9C80DF* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:644FB0* ID_OUI_FROM_DATABASE=Hyunjin.com OUI:001A2A* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:001F3F* ID_OUI_FROM_DATABASE=AVM GmbH OUI:506A03* ID_OUI_FROM_DATABASE=NETGEAR OUI:6CB0CE* ID_OUI_FROM_DATABASE=NETGEAR OUI:100D7F* ID_OUI_FROM_DATABASE=NETGEAR OUI:001018* ID_OUI_FROM_DATABASE=Broadcom OUI:001BE9* ID_OUI_FROM_DATABASE=Broadcom OUI:0020D6* ID_OUI_FROM_DATABASE=Breezecom, Ltd. OUI:008077* ID_OUI_FROM_DATABASE=Brother industries, LTD. OUI:FC2F40* ID_OUI_FROM_DATABASE=Calxeda, Inc. OUI:029D8E* ID_OUI_FROM_DATABASE=CARDIAC RECORDERS, INC. OUI:0026E4* ID_OUI_FROM_DATABASE=Canal + OUI:E458E7* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:8CBFA6* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:7840E4* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:9000DB* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:183A2D* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:A89FBA* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:FC1910* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:083D88* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:5C2E59* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:646CB2* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:A48431* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E4F8EF* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:1867B0* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:F40E22* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:4CBCA5* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:78595E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B0D09C* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:4CA56D* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:08373D* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:50F520* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:A4EBD3* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:28987B* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:9C3AAF* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:1432D1* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:F884F2* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:14B484* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:608F5C* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:389496* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:0CB319* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:08EE8B* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:84A466* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:981DFA* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:FCF136* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:0C8910* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:54FA3E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:702559* ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. OUI:0090D6* ID_OUI_FROM_DATABASE=Crystal Group, Inc. OUI:02CF1C* ID_OUI_FROM_DATABASE=Communication Machinery Corporation OUI:BCF2AF* ID_OUI_FROM_DATABASE=devolo AG OUI:0270B3* ID_OUI_FROM_DATABASE=DATA RECALL LTD. OUI:000FF6* ID_OUI_FROM_DATABASE=DARFON LIGHTING CORP OUI:001DAA* ID_OUI_FROM_DATABASE=DrayTek Corp. OUI:0C75BD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:38F0C8* ID_OUI_FROM_DATABASE=Livestream OUI:0C1167* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:74EAE8* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:A811FC* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001982* ID_OUI_FROM_DATABASE=SmarDTV OUI:00904B* ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. OUI:10C6FC* ID_OUI_FROM_DATABASE=Garmin International OUI:00E000* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:00000E* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:002326* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:0007CB* ID_OUI_FROM_DATABASE=FREEBOX SAS OUI:3C591E* ID_OUI_FROM_DATABASE=TCL King Electrical Appliances (Huizhou) Co., Ltd OUI:002682* ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. OUI:001A73* ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. OUI:34AF2C* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:8CCDE8* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:9CE635* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:600194* ID_OUI_FROM_DATABASE=Espressif Inc. OUI:F44D17* ID_OUI_FROM_DATABASE=GOLDCARD HIGH-TECH CO.,LTD. OUI:0021BD* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:002709* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:E84ECE* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:D86BF7* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:A4C0E1* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:001AE9* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:001CBE* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:001E35* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:001FC5* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:0009BF* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:002403* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:002265* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0019B7* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001D6E* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001B33* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:ECF35B* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:EC9B5B* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:BCC6DB* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:0021AA* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:002669* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0022FD* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:002109* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:002108* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001F01* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:000EED* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001E3A* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001A89* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:002404* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0002EE* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001C9A* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:B83241* ID_OUI_FROM_DATABASE=Wuhan Tianyu Information Industry Co., Ltd. OUI:9897D1* ID_OUI_FROM_DATABASE=MitraStar Technology Corp. OUI:94C960* ID_OUI_FROM_DATABASE=Zhongshan B&T technology.co.,ltd OUI:E04FBD* ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD OUI:001479* ID_OUI_FROM_DATABASE=NEC Magnus Communications,Ltd. OUI:9C4FDA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:1C5CF2* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0821EF* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B462AD* ID_OUI_FROM_DATABASE=Elysia Germany GmbH OUI:747818* ID_OUI_FROM_DATABASE=Jurumani Solutions OUI:A0CBFD* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:34145F* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:803896* ID_OUI_FROM_DATABASE=SHARP Corporation OUI:00D9D1* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:F8D0AC* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:0CFE45* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:D8D43C* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:3C0771* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:686E23* ID_OUI_FROM_DATABASE=Wi3 Inc. OUI:B8A175* ID_OUI_FROM_DATABASE=Roku, Inc. OUI:80D160* ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. OUI:0080E5* ID_OUI_FROM_DATABASE=NetApp OUI:E49A79* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:28A02B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:B44BD2* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:002340* ID_OUI_FROM_DATABASE=MiXTelematics OUI:B48B19* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:4CCC6A* ID_OUI_FROM_DATABASE=Micro-Star INTL CO., LTD. OUI:00AF1F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:245EBE* ID_OUI_FROM_DATABASE=QNAP Systems, Inc. OUI:A89352* ID_OUI_FROM_DATABASE=SHANGHAI ZHONGMI COMMUNICATION TECHNOLOGY CO.,LTD OUI:AC5F3E* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) OUI:985BB0* ID_OUI_FROM_DATABASE=KMDATA INC. OUI:6C8FB5* ID_OUI_FROM_DATABASE=Microsoft Mobile Oy OUI:D4E33F* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:143E60* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:248A07* ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. OUI:9C9D5D* ID_OUI_FROM_DATABASE=Raden Inc OUI:B07FB9* ID_OUI_FROM_DATABASE=NETGEAR OUI:70661B* ID_OUI_FROM_DATABASE=Sonova AG OUI:1C98EC* ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise OUI:EC438B* ID_OUI_FROM_DATABASE=YAPTV OUI:E8FD72* ID_OUI_FROM_DATABASE=SHANGHAI LINGUO TECHNOLOGY CO., LTD. OUI:98BB1E* ID_OUI_FROM_DATABASE=BYD Precision Manufacture Company Ltd. OUI:001D0D* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:00041F* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:20A90E* ID_OUI_FROM_DATABASE=TCT mobile ltd OUI:CCB11A* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:1866DA* ID_OUI_FROM_DATABASE=Dell Inc. OUI:981FB1* ID_OUI_FROM_DATABASE=Shenzhen Lemon Network Technology Co.,Ltd OUI:40476A* ID_OUI_FROM_DATABASE=AG Acquisition Corp. d.b.a. ASTRO Gaming OUI:A4BF01* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0004C6* ID_OUI_FROM_DATABASE=YAMAHA MOTOR CO.,LTD OUI:509EA7* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:DCCF96* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:64CC2E* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:14D11F* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:54511B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:68536C* ID_OUI_FROM_DATABASE=SPnS Co.,Ltd OUI:005BA1* ID_OUI_FROM_DATABASE=shanghai huayuan chuangxin software CO., LTD. OUI:B07E70* ID_OUI_FROM_DATABASE=Zadara Storage Ltd. OUI:405EE1* ID_OUI_FROM_DATABASE=Shenzhen H&T Intelligent Control Co.,Ltd. OUI:88795B* ID_OUI_FROM_DATABASE=Konka Group Co., Ltd. OUI:10F005* ID_OUI_FROM_DATABASE=Intel Corporate OUI:BC9889* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:E42F26* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:344B3D* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:FCF647* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:1088CE* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:D463FE* ID_OUI_FROM_DATABASE=Arcadyan Corporation OUI:9466E7* ID_OUI_FROM_DATABASE=WOM Engineering OUI:F8A188* ID_OUI_FROM_DATABASE=LED Roadway Lighting OUI:001174* ID_OUI_FROM_DATABASE=Mojo Networks, Inc. OUI:BC15AC* ID_OUI_FROM_DATABASE=Vodafone Italia S.p.A. OUI:1C740D* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:140C5B* ID_OUI_FROM_DATABASE=PLNetworks OUI:D0B0CD* ID_OUI_FROM_DATABASE=Moen OUI:DCFE07* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:E47E66* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:9C741A* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:EC93ED* ID_OUI_FROM_DATABASE=DDoS-Guard LTD OUI:4C72B9* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:0071C2* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:F462D0* ID_OUI_FROM_DATABASE=Not for Radio, LLC OUI:94513D* ID_OUI_FROM_DATABASE=iSmart Alarm, Inc. OUI:C89CDC* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:002511* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:000E03* ID_OUI_FROM_DATABASE=Emulex Corporation OUI:001BB9* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:001921* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:00142A* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:0050FC* ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. OUI:200A5E* ID_OUI_FROM_DATABASE=Xiangshan Giant Eagle Technology Developing Co., Ltd. OUI:0001F4* ID_OUI_FROM_DATABASE=Enterasys OUI:487ADA* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:1C7370* ID_OUI_FROM_DATABASE=Neotech OUI:30E37A* ID_OUI_FROM_DATABASE=Intel Corporate OUI:A08CFD* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:4CA003* ID_OUI_FROM_DATABASE=T-21 Technologies LLC OUI:F0EE58* ID_OUI_FROM_DATABASE=PACE Telematics GmbH OUI:001397* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:00A0A4* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:4000E0* ID_OUI_FROM_DATABASE=Derek(Shaoguan)Limited OUI:A4E597* ID_OUI_FROM_DATABASE=Gessler GmbH OUI:001A34* ID_OUI_FROM_DATABASE=Konka Group Co., Ltd. OUI:0024F4* ID_OUI_FROM_DATABASE=Kaminario, Ltd. OUI:001D08* ID_OUI_FROM_DATABASE=Jiangsu Yinhe Electronics Co.,Ltd. OUI:0018D7* ID_OUI_FROM_DATABASE=JAVAD GNSS, Inc. OUI:001C6C* ID_OUI_FROM_DATABASE=30805 OUI:00A0B0* ID_OUI_FROM_DATABASE=I-O DATA DEVICE, INC. OUI:00E0CF* ID_OUI_FROM_DATABASE=INTEGRATED DEVICE OUI:547F54* ID_OUI_FROM_DATABASE=INGENICO OUI:48C049* ID_OUI_FROM_DATABASE=Broad Telecom SA OUI:DC38E1* ID_OUI_FROM_DATABASE=Juniper Networks OUI:40A677* ID_OUI_FROM_DATABASE=Juniper Networks OUI:0C8610* ID_OUI_FROM_DATABASE=Juniper Networks OUI:EC3EF7* ID_OUI_FROM_DATABASE=Juniper Networks OUI:0014F6* ID_OUI_FROM_DATABASE=Juniper Networks OUI:00121E* ID_OUI_FROM_DATABASE=Juniper Networks OUI:0010DB* ID_OUI_FROM_DATABASE=Juniper Networks OUI:307C5E* ID_OUI_FROM_DATABASE=Juniper Networks OUI:002688* ID_OUI_FROM_DATABASE=Juniper Networks OUI:841888* ID_OUI_FROM_DATABASE=Juniper Networks OUI:40B4F0* ID_OUI_FROM_DATABASE=Juniper Networks OUI:0017CB* ID_OUI_FROM_DATABASE=Juniper Networks OUI:E0A3AC* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:044E5A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:E00EDA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:D86CE9* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:3C81D8* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:2CE412* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:181E78* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:0037B7* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:0014BF* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:6C8DC1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:38CADA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:8C579B* ID_OUI_FROM_DATABASE=Wistron Neweb Corporation OUI:B436A9* ID_OUI_FROM_DATABASE=Fibocom Wireless Inc. OUI:6416F0* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:48DB50* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:2400BA* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:68DBCA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:044BED* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:3CBB73* ID_OUI_FROM_DATABASE=Shenzhen Xinguodu Technology Co., Ltd. OUI:3CCF5B* ID_OUI_FROM_DATABASE=ICOMM HK LIMITED OUI:F40304* ID_OUI_FROM_DATABASE=Google, Inc. OUI:78ACC0* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:3C9066* ID_OUI_FROM_DATABASE=SmartRG, Inc. OUI:00195B* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:000D88* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:001346* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:0021BA* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0022A5* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0024BA* ID_OUI_FROM_DATABASE=Texas Instruments OUI:D03761* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0017E4* ID_OUI_FROM_DATABASE=Texas Instruments OUI:5C6B32* ID_OUI_FROM_DATABASE=Texas Instruments OUI:1C4593* ID_OUI_FROM_DATABASE=Texas Instruments OUI:84DD20* ID_OUI_FROM_DATABASE=Texas Instruments OUI:883314* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0017EB* ID_OUI_FROM_DATABASE=Texas Instruments OUI:C4EDBA* ID_OUI_FROM_DATABASE=Texas Instruments OUI:34B1F7* ID_OUI_FROM_DATABASE=Texas Instruments OUI:C8A030* ID_OUI_FROM_DATABASE=Texas Instruments OUI:205532* ID_OUI_FROM_DATABASE=Gotech International Technology Limited OUI:002401* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:1CAFF7* ID_OUI_FROM_DATABASE=D-Link International OUI:B8A386* ID_OUI_FROM_DATABASE=D-Link International OUI:C8D3A3* ID_OUI_FROM_DATABASE=D-Link International OUI:F4FC32* ID_OUI_FROM_DATABASE=Texas Instruments OUI:649C8E* ID_OUI_FROM_DATABASE=Texas Instruments OUI:D8952F* ID_OUI_FROM_DATABASE=Texas Instruments OUI:001833* ID_OUI_FROM_DATABASE=Texas Instruments OUI:4419B6* ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. OUI:C056E3* ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. OUI:C8E7D8* ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. OUI:E01C41* ID_OUI_FROM_DATABASE=Aerohive Networks Inc. OUI:D854A2* ID_OUI_FROM_DATABASE=Aerohive Networks Inc. OUI:9CEFD5* ID_OUI_FROM_DATABASE=Panda Wireless, Inc. OUI:C02C7A* ID_OUI_FROM_DATABASE=Shenzhen Horn Audio Co.,Ltd. OUI:88B8D0* ID_OUI_FROM_DATABASE=Dongguan Koppo Electronic Co.,Ltd OUI:38E7D8* ID_OUI_FROM_DATABASE=HTC Corporation OUI:D8B377* ID_OUI_FROM_DATABASE=HTC Corporation OUI:B4CEF6* ID_OUI_FROM_DATABASE=HTC Corporation OUI:D40B1A* ID_OUI_FROM_DATABASE=HTC Corporation OUI:A08D16* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:2C8158* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:601888* ID_OUI_FROM_DATABASE=zte corporation OUI:8002DF* ID_OUI_FROM_DATABASE=ORA Inc. OUI:D8FC38* ID_OUI_FROM_DATABASE=Giantec Semiconductor Inc OUI:2C6798* ID_OUI_FROM_DATABASE=InTalTech Ltd. OUI:D0BF9C* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:B05ADA* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001083* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0001E6* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:C44044* ID_OUI_FROM_DATABASE=RackTop Systems Inc. OUI:3898D8* ID_OUI_FROM_DATABASE=MERITECH CO.,LTD OUI:C8675E* ID_OUI_FROM_DATABASE=Aerohive Networks Inc. OUI:000CF1* ID_OUI_FROM_DATABASE=Intel Corporation OUI:000E0C* ID_OUI_FROM_DATABASE=Intel Corporation OUI:BC0F64* ID_OUI_FROM_DATABASE=Intel Corporate OUI:6CA100* ID_OUI_FROM_DATABASE=Intel Corporate OUI:94659C* ID_OUI_FROM_DATABASE=Intel Corporate OUI:1002B5* ID_OUI_FROM_DATABASE=Intel Corporate OUI:A468BC* ID_OUI_FROM_DATABASE=Private OUI:001DCF* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001DD5* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001DD0* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:5C571A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:441EA1* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:D8D385* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:18A905* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:00237D* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:002655* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001438* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:001560* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:288023* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:645106* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:5CB901* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:DC4A3E* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:2C59E5* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:9CB654* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:38EAA7* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:E83935* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:901ACA* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:E8ED05* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:90C792* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:789684* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:CC65AD* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:986B3D* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:08EB74* ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. OUI:6CB56B* ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. OUI:940937* ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. OUI:403DEC* ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. OUI:E84DD0* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:D81FCC* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:140467* ID_OUI_FROM_DATABASE=SNK Technologies Co.,Ltd. OUI:EC5F23* ID_OUI_FROM_DATABASE=Qinghai Kimascend Electronics Technology Co. Ltd. OUI:047D50* ID_OUI_FROM_DATABASE=Shenzhen Kang Ying Technology Co.Ltd. OUI:54EFFE* ID_OUI_FROM_DATABASE=Fullpower Technologies, Inc. OUI:EC52DC* ID_OUI_FROM_DATABASE=WORLD MEDIA AND TECHNOLOGY Corp. OUI:A4D18C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:CC25EF* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:240995* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:247F3C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:1C8E5C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:94772B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:F4E3FB* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:04021F* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:0034FE* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:D02DB3* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:086361* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:F80113* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:70723C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:5C7D5E* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:4C8BEF* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:20F3A3* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:ACE87B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:688F84* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:001AB6* ID_OUI_FROM_DATABASE=Texas Instruments OUI:D03972* ID_OUI_FROM_DATABASE=Texas Instruments OUI:7C669D* ID_OUI_FROM_DATABASE=Texas Instruments OUI:78A504* ID_OUI_FROM_DATABASE=Texas Instruments OUI:C4BE84* ID_OUI_FROM_DATABASE=Texas Instruments OUI:D05FB8* ID_OUI_FROM_DATABASE=Texas Instruments OUI:74D6EA* ID_OUI_FROM_DATABASE=Texas Instruments OUI:7CEC79* ID_OUI_FROM_DATABASE=Texas Instruments OUI:E0E5CF* ID_OUI_FROM_DATABASE=Texas Instruments OUI:ACF7F3* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:889471* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:CC4E24* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:50EB1A* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:0027F8* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:000533* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:0060DF* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:4CAC0A* ID_OUI_FROM_DATABASE=zte corporation OUI:0026ED* ID_OUI_FROM_DATABASE=zte corporation OUI:002293* ID_OUI_FROM_DATABASE=zte corporation OUI:FCD733* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:10A5D0* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:D4C9B2* ID_OUI_FROM_DATABASE=Quanergy Systems Inc OUI:E4CE02* ID_OUI_FROM_DATABASE=WyreStorm Technologies Ltd OUI:2002AF* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:0026E8* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:001C26* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:00197D* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:90FBA6* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:142D27* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:ECCB30* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:786A89* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:2008ED* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:509F27* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:CC96A0* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:54A51B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:F4C714* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:286ED4* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:A01290* ID_OUI_FROM_DATABASE=Avaya Inc OUI:F81547* ID_OUI_FROM_DATABASE=Avaya Inc OUI:506184* ID_OUI_FROM_DATABASE=Avaya Inc OUI:BCADAB* ID_OUI_FROM_DATABASE=Avaya Inc OUI:B4A95A* ID_OUI_FROM_DATABASE=Avaya Inc OUI:3C3A73* ID_OUI_FROM_DATABASE=Avaya Inc OUI:04F938* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:FC48EF* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:80FB06* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:D4B110* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:CC53B5* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:002127* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:54E6FC* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:D85D4C* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:F81A67* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:F0F336* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:44B32D* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:F07816* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001310* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:0023BE* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:54D46F* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:24374C* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:BCC810* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:484487* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:445829* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:481D70* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:00214F* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:00E036* ID_OUI_FROM_DATABASE=PIONEER CORPORATION OUI:C83DFC* ID_OUI_FROM_DATABASE=PIONEER CORPORATION OUI:E0AE5E* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:34C731* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:60380E* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:64D4BD* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:00000C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:004096* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:30F70D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B07D47* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:D8B190* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:F0B2E5* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:188B9D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:38ED18* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:ECBD1D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:DCCEC1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:84B261* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:009EC8* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:7C1DD9* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:A086C6* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:584498* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:70E422* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0050BD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:009086* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:005054* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:3C0E23* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001CC3* ID_OUI_FROM_DATABASE=Pace plc OUI:14D4FE* ID_OUI_FROM_DATABASE=Pace plc OUI:70B14E* ID_OUI_FROM_DATABASE=Pace plc OUI:707630* ID_OUI_FROM_DATABASE=Pace plc OUI:90E6BA* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:BCAEC5* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:10BF48* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:A80C0D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B83861* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:6C9989* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:580A20* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0050D1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00500B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:005073* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00603E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00E034* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001868* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:887556* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:60735C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:FC9947* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:7CC537* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:70CD60* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:24AB81* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:581FAA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A46706* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:3C0754* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E4CE8F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E8040B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:B8C75D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:403CFC* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:286AB8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:7CC3A1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:00E16D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:F8C288* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E0ACF1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:FC5B39* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:346F90* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E0D173* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:74A02F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:547C69* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:689CE2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:40A6E8* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B8782E* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:000502* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0010FA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:000393* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0016CB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0017F2* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:001B63* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:001EC2* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:002608* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:7C6D62* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:40D32D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D83062* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C42C03* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:6C2056* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:BC1665* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:44ADD9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0C2724* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:6C416A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:F872EA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0C6803* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:789F70* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:DC3714* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:40331A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:94F6A3* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D81D72* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:70ECE4* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:38C986* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:FCFC48* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:2857BE* ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. OUI:50D59C* ID_OUI_FROM_DATABASE=Thai Habel Industrial Co., Ltd. OUI:FCA386* ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD OUI:F0F249* ID_OUI_FROM_DATABASE=Hitron Technologies. Inc OUI:A4C361* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:AC7F3E* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:280B5C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:90B931* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:24A2E1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:80EA96* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:600308* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:04F13E* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:54724F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:48746E* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:3CAB8E* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:7C6DF8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:48D705* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:3CD0F8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:98D6BB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:4CB199* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:64E682* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:804971* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:98FE94* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D8004D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:98B8E3* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:80929F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:885395* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:9C04EB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:78FD94* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C88550* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D4F46F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:787E61* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:60F81D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:4C7C5F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:48E9F1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:FCE998* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F099BF* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:68644B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A8968A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:4C8D79* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:207D74* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F4F15A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:042665* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:2CB43A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:689C70* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:087045* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:CCE0C3* ID_OUI_FROM_DATABASE=Mangstor, Inc. OUI:84A423* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:346987* ID_OUI_FROM_DATABASE=zte corporation OUI:58685D* ID_OUI_FROM_DATABASE=Tempo Australia Pty Ltd OUI:789C85* ID_OUI_FROM_DATABASE=August Home, Inc. OUI:FCCF43* ID_OUI_FROM_DATABASE=HUIZHOU CITY HUIYANG DISTRICT MEISIQI INDUSTRY DEVELOPMENT CO,.LTD OUI:5882A8* ID_OUI_FROM_DATABASE=Microsoft OUI:B4EF04* ID_OUI_FROM_DATABASE=DAIHAN Scientific Co., Ltd. OUI:049645* ID_OUI_FROM_DATABASE=WUXI SKY CHIP INTERCONNECTION TECHNOLOGY CO.,LTD. OUI:5CE3B6* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:9C88AD* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:C8C2C6* ID_OUI_FROM_DATABASE=Shanghai Airm2m Communication Technology Co., Ltd OUI:EC64E7* ID_OUI_FROM_DATABASE=MOCACARE Corporation OUI:D07C2D* ID_OUI_FROM_DATABASE=Leie IOT technology Co., Ltd OUI:40862E* ID_OUI_FROM_DATABASE=JDM MOBILE INTERNET SOLUTION CO., LTD. OUI:EC388F* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:BC9C31* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:90C99B* ID_OUI_FROM_DATABASE=Recore Systems OUI:5CB559* ID_OUI_FROM_DATABASE=CNEX Labs OUI:5CCF7F* ID_OUI_FROM_DATABASE=Espressif Inc. OUI:380546* ID_OUI_FROM_DATABASE=Foctek Photonics, Inc. OUI:6858C5* ID_OUI_FROM_DATABASE=ZF TRW Automotive OUI:044169* ID_OUI_FROM_DATABASE=GoPro OUI:ACC51B* ID_OUI_FROM_DATABASE=Zhuhai Pantum Electronics Co., Ltd. OUI:4473D6* ID_OUI_FROM_DATABASE=Logitech OUI:E80734* ID_OUI_FROM_DATABASE=Champion Optical Network Engineering, LLC OUI:D02544* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD. OUI:6CEBB2* ID_OUI_FROM_DATABASE=Dongguan Sen DongLv Electronics Co.,Ltd OUI:A03299* ID_OUI_FROM_DATABASE=Lenovo (Beijing) Co., Ltd. OUI:A845CD* ID_OUI_FROM_DATABASE=Siselectron Technology LTD. OUI:D0C193* ID_OUI_FROM_DATABASE=SKYBELL, INC OUI:209BCD* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F0B0E7* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A09169* ID_OUI_FROM_DATABASE=LG Electronics OUI:CC20E8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E435C8* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:38FF36* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:D47208* ID_OUI_FROM_DATABASE=Bragi GmbH OUI:489A42* ID_OUI_FROM_DATABASE=Technomate Ltd OUI:B49D0B* ID_OUI_FROM_DATABASE=BQ OUI:98CB27* ID_OUI_FROM_DATABASE=Galore Networks Pvt. Ltd. OUI:30D32D* ID_OUI_FROM_DATABASE=devolo AG OUI:CC794A* ID_OUI_FROM_DATABASE=BLU Products Inc. OUI:60FD56* ID_OUI_FROM_DATABASE=WOORISYSTEMS CO., Ltd OUI:7CFE90* ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. OUI:483974* ID_OUI_FROM_DATABASE=Proware Technologies Co., Ltd. OUI:E855B4* ID_OUI_FROM_DATABASE=SAI Technology Inc. OUI:9CA69D* ID_OUI_FROM_DATABASE=Whaley Technology Co.Ltd OUI:342606* ID_OUI_FROM_DATABASE=CarePredict, Inc. OUI:B4AE2B* ID_OUI_FROM_DATABASE=Microsoft OUI:80EB77* ID_OUI_FROM_DATABASE=Wistron Corporation OUI:B88981* ID_OUI_FROM_DATABASE=Chengdu InnoThings Technology Co., Ltd. OUI:B4293D* ID_OUI_FROM_DATABASE=Shenzhen Urovo Technology Co.,Ltd. OUI:906FA9* ID_OUI_FROM_DATABASE=NANJING PUTIAN TELECOMMUNICATIONS TECHNOLOGY CO.,LTD. OUI:14B370* ID_OUI_FROM_DATABASE=Gigaset Digital Technology (Shenzhen) Co., Ltd. OUI:FC2FEF* ID_OUI_FROM_DATABASE=UTT Technologies Co., Ltd. OUI:EC21E5* ID_OUI_FROM_DATABASE=Toshiba OUI:44FDA3* ID_OUI_FROM_DATABASE=Everysight LTD. OUI:84D4C8* ID_OUI_FROM_DATABASE=Widex A/S OUI:247260* ID_OUI_FROM_DATABASE=IOTTECH Corp OUI:44975A* ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD OUI:584822* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:F8BF09* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:B4B265* ID_OUI_FROM_DATABASE=DAEHO I&T OUI:081FEB* ID_OUI_FROM_DATABASE=BinCube OUI:785F4C* ID_OUI_FROM_DATABASE=Argox Information Co., Ltd. OUI:E866C4* ID_OUI_FROM_DATABASE=Datawise Systems OUI:5870C6* ID_OUI_FROM_DATABASE=Shanghai Xiaoyi Technology Co., Ltd. OUI:803B2A* ID_OUI_FROM_DATABASE=ABB Xiamen Low Voltage Equipment Co.,Ltd. OUI:A0A65C* ID_OUI_FROM_DATABASE=Supercomputing Systems AG OUI:5CB395* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:C412F5* ID_OUI_FROM_DATABASE=D-Link International OUI:44F436* ID_OUI_FROM_DATABASE=zte corporation OUI:349B5B* ID_OUI_FROM_DATABASE=Maquet GmbH OUI:E861BE* ID_OUI_FROM_DATABASE=Melec Inc. OUI:54B80A* ID_OUI_FROM_DATABASE=D-Link International OUI:D8ADDD* ID_OUI_FROM_DATABASE=Sonavation, Inc. OUI:C09A71* ID_OUI_FROM_DATABASE=XIAMEN MEITU MOBILE TECHNOLOGY CO.LTD OUI:340B40* ID_OUI_FROM_DATABASE=MIOS ELETTRONICA SRL OUI:944A0C* ID_OUI_FROM_DATABASE=Sercomm Corporation OUI:D02516* ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. OUI:D05C7A* ID_OUI_FROM_DATABASE=Sartura d.o.o. OUI:583F54* ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) OUI:9C37F4* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:5CEB68* ID_OUI_FROM_DATABASE=Cheerstar Technology Co., Ltd OUI:F46A92* ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD OUI:14AEDB* ID_OUI_FROM_DATABASE=VTech Telecommunications Ltd. OUI:EC4F82* ID_OUI_FROM_DATABASE=Calix Inc. OUI:B8C3BF* ID_OUI_FROM_DATABASE=Henan Chengshi NetWork Technology Co.,Ltd OUI:C0EE40* ID_OUI_FROM_DATABASE=Laird Technologies OUI:F0182B* ID_OUI_FROM_DATABASE=LG Chem OUI:CC5FBF* ID_OUI_FROM_DATABASE=Topwise 3G Communication Co., Ltd. OUI:14DDA9* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:485D36* ID_OUI_FROM_DATABASE=Verizon OUI:EC60E0* ID_OUI_FROM_DATABASE=AVI-ON LABS OUI:145A83* ID_OUI_FROM_DATABASE=Logi-D inc OUI:4CEEB0* ID_OUI_FROM_DATABASE=SHC Netzwerktechnik GmbH OUI:188EF9* ID_OUI_FROM_DATABASE=G2C Co. Ltd. OUI:809FAB* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:D00492* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:F4E9D4* ID_OUI_FROM_DATABASE=QLogic Corporation OUI:1422DB* ID_OUI_FROM_DATABASE=eero inc. OUI:0C413E* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:007E56* ID_OUI_FROM_DATABASE=China Dragon Technology Limited OUI:086266* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:346C0F* ID_OUI_FROM_DATABASE=Pramod Telecom Pvt. Ltd OUI:3C912B* ID_OUI_FROM_DATABASE=Vexata Inc OUI:54369B* ID_OUI_FROM_DATABASE=1Verge Internet Technology (Beijing) Co., Ltd. OUI:E4FED9* ID_OUI_FROM_DATABASE=EDMI Europe Ltd OUI:2852E0* ID_OUI_FROM_DATABASE=Layon international Electronic & Telecom Co.,Ltd OUI:E48501* ID_OUI_FROM_DATABASE=Geberit International AG OUI:1C3947* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:2CAD13* ID_OUI_FROM_DATABASE=SHENZHEN ZHILU TECHNOLOGY CO.,LTD OUI:68B983* ID_OUI_FROM_DATABASE=b-plus GmbH OUI:BC74D7* ID_OUI_FROM_DATABASE=HangZhou JuRu Technology CO.,LTD OUI:E88E60* ID_OUI_FROM_DATABASE=NSD Corporation OUI:545146* ID_OUI_FROM_DATABASE=AMG Systems Ltd. OUI:84DDB7* ID_OUI_FROM_DATABASE=Cilag GmbH International OUI:78EB14* ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD OUI:D05BA8* ID_OUI_FROM_DATABASE=zte corporation OUI:8CE78C* ID_OUI_FROM_DATABASE=DK Networks OUI:E4BAD9* ID_OUI_FROM_DATABASE=360 Fly Inc. OUI:7C3CB6* ID_OUI_FROM_DATABASE=Shenzhen Homecare Technology Co.,Ltd. OUI:BCE767* ID_OUI_FROM_DATABASE=Quanzhou TDX Electronics Co., Ltd OUI:6CA7FA* ID_OUI_FROM_DATABASE=YOUNGBO ENGINEERING INC. OUI:D0929E* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:F4032F* ID_OUI_FROM_DATABASE=Reduxio Systems OUI:84CFBF* ID_OUI_FROM_DATABASE=Fairphone OUI:AC9E17* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:ACC73F* ID_OUI_FROM_DATABASE=VITSMO CO., LTD. OUI:505527* ID_OUI_FROM_DATABASE=LG Electronics OUI:18BDAD* ID_OUI_FROM_DATABASE=L-TECH CORPORATION OUI:44D244* ID_OUI_FROM_DATABASE=Seiko Epson Corporation OUI:10C07C* ID_OUI_FROM_DATABASE=Blu-ray Disc Association OUI:B87879* ID_OUI_FROM_DATABASE=Roche Diagnostics GmbH OUI:4480EB* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:D06F4A* ID_OUI_FROM_DATABASE=TOPWELL INTERNATIONAL HOLDINGS LIMITED OUI:BC54F9* ID_OUI_FROM_DATABASE=Drogoo Technology Co., Ltd. OUI:349E34* ID_OUI_FROM_DATABASE=Evervictory Electronic Co.Ltd OUI:A0C2DE* ID_OUI_FROM_DATABASE=Costar Video Systems OUI:3809A4* ID_OUI_FROM_DATABASE=Firefly Integrations OUI:00A509* ID_OUI_FROM_DATABASE=WigWag Inc. OUI:A86405* ID_OUI_FROM_DATABASE=nimbus 9, Inc OUI:7076FF* ID_OUI_FROM_DATABASE=KERLINK OUI:68F0BC* ID_OUI_FROM_DATABASE=Shenzhen LiWiFi Technology Co., Ltd OUI:BCD165* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:4CA928* ID_OUI_FROM_DATABASE=Insensi OUI:2884FA* ID_OUI_FROM_DATABASE=SHARP Corporation OUI:3C1E04* ID_OUI_FROM_DATABASE=D-Link International OUI:E0FFF7* ID_OUI_FROM_DATABASE=Softiron Inc. OUI:DC60A1* ID_OUI_FROM_DATABASE=Teledyne DALSA Professional Imaging OUI:78E980* ID_OUI_FROM_DATABASE=RainUs Co.,Ltd OUI:7C8274* ID_OUI_FROM_DATABASE=Shenzhen Hikeen Technology CO.,LTD OUI:B40566* ID_OUI_FROM_DATABASE=SP Best Corporation Co., LTD. OUI:70AD54* ID_OUI_FROM_DATABASE=Malvern Instruments Ltd OUI:DCE026* ID_OUI_FROM_DATABASE=Patrol Tag, Inc OUI:EC3C88* ID_OUI_FROM_DATABASE=MCNEX Co.,Ltd. OUI:F07959* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:E08E3C* ID_OUI_FROM_DATABASE=Aztech Electronics Pte Ltd OUI:78A351* ID_OUI_FROM_DATABASE=SHENZHEN ZHIBOTONG ELECTRONICS CO.,LTD OUI:34FCEF* ID_OUI_FROM_DATABASE=LG Electronics OUI:94E2FD* ID_OUI_FROM_DATABASE=Boge Kompressoren OTTO Boge GmbH & Co. KG OUI:E4695A* ID_OUI_FROM_DATABASE=Dictum Health, Inc. OUI:D46132* ID_OUI_FROM_DATABASE=Pro Concept Manufacturer Co.,Ltd. OUI:54A050* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:841826* ID_OUI_FROM_DATABASE=Osram GmbH OUI:14F893* ID_OUI_FROM_DATABASE=Wuhan FiberHome Digital Technology Co.,Ltd. OUI:9816EC* ID_OUI_FROM_DATABASE=IC Intracom OUI:DCDA4F* ID_OUI_FROM_DATABASE=GETCK TECHNOLOGY, INC OUI:30FAB7* ID_OUI_FROM_DATABASE=Tunai Creative OUI:0809B6* ID_OUI_FROM_DATABASE=Masimo Corp OUI:14EDE4* ID_OUI_FROM_DATABASE=Kaiam Corporation OUI:3438AF* ID_OUI_FROM_DATABASE=Inlab Software GmbH OUI:049B9C* ID_OUI_FROM_DATABASE=Eadingcore Intelligent Technology Co., Ltd. OUI:842690* ID_OUI_FROM_DATABASE=BEIJING THOUGHT SCIENCE CO.,LTD. OUI:B84FD5* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:587BE9* ID_OUI_FROM_DATABASE=AirPro Technology India Pvt. Ltd OUI:FC1D84* ID_OUI_FROM_DATABASE=Autobase OUI:4CE933* ID_OUI_FROM_DATABASE=RailComm, LLC OUI:6050C1* ID_OUI_FROM_DATABASE=Kinetek Sports OUI:003560* ID_OUI_FROM_DATABASE=Rosen Aviation OUI:EC59E7* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:08EFAB* ID_OUI_FROM_DATABASE=SAYME WIRELESS SENSOR NETWORK OUI:C81B6B* ID_OUI_FROM_DATABASE=Innova Security OUI:5C966A* ID_OUI_FROM_DATABASE=RTNET OUI:2C5089* ID_OUI_FROM_DATABASE=Shenzhen Kaixuan Visual Technology Co.,Limited OUI:A89DD2* ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co., Ltd OUI:EC13B2* ID_OUI_FROM_DATABASE=Netonix OUI:74BADB* ID_OUI_FROM_DATABASE=Longconn Electornics(shenzhen)Co.,Ltd OUI:4C7403* ID_OUI_FROM_DATABASE=BQ OUI:5876C5* ID_OUI_FROM_DATABASE=DIGI I'S LTD OUI:00A2F5* ID_OUI_FROM_DATABASE=Guangzhou Yuanyun Network Technology Co.,Ltd OUI:70FC8C* ID_OUI_FROM_DATABASE=OneAccess SA OUI:2C600C* ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. OUI:902CC7* ID_OUI_FROM_DATABASE=C-MAX Asia Limited OUI:1C965A* ID_OUI_FROM_DATABASE=Weifang goertek Electronics CO.,LTD OUI:188219* ID_OUI_FROM_DATABASE=Alibaba Cloud Computing Ltd. OUI:B41780* ID_OUI_FROM_DATABASE=DTI Group Ltd OUI:D437D7* ID_OUI_FROM_DATABASE=zte corporation OUI:AC3870* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:80EACA* ID_OUI_FROM_DATABASE=Dialog Semiconductor Hellas SA OUI:60512C* ID_OUI_FROM_DATABASE=TCT mobile limited OUI:4CBC42* ID_OUI_FROM_DATABASE=Shenzhen Hangsheng Electronics Co.,Ltd. OUI:D82522* ID_OUI_FROM_DATABASE=Pace plc OUI:987E46* ID_OUI_FROM_DATABASE=Emizon Networks Limited OUI:8432EA* ID_OUI_FROM_DATABASE=ANHUI WANZTEN P&T CO., LTD OUI:ACA213* ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD OUI:90B686* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:4C6E6E* ID_OUI_FROM_DATABASE=Comnect Technology CO.,LTD OUI:F4DD9E* ID_OUI_FROM_DATABASE=GoPro OUI:40B3CD* ID_OUI_FROM_DATABASE=Chiyoda Electronics Co.,Ltd. OUI:3451AA* ID_OUI_FROM_DATABASE=JID GLOBAL OUI:04572F* ID_OUI_FROM_DATABASE=Sertel Electronics UK Ltd OUI:08B2A3* ID_OUI_FROM_DATABASE=Cynny Italia S.r.L. OUI:D8977C* ID_OUI_FROM_DATABASE=Grey Innovation OUI:80AD67* ID_OUI_FROM_DATABASE=Kasda Networks Inc OUI:9CAD97* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:30595B* ID_OUI_FROM_DATABASE=streamnow AG OUI:B8AD3E* ID_OUI_FROM_DATABASE=BLUECOM OUI:10C37B* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:48D855* ID_OUI_FROM_DATABASE=Telvent OUI:284ED7* ID_OUI_FROM_DATABASE=OutSmart Power Systems, Inc. OUI:5C5BC2* ID_OUI_FROM_DATABASE=YIK Corporation OUI:184A6F* ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd OUI:EC8A4C* ID_OUI_FROM_DATABASE=zte corporation OUI:340AFF* ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd OUI:8014A8* ID_OUI_FROM_DATABASE=Guangzhou V-SOLUTION Electronic Technology Co., Ltd. OUI:908C63* ID_OUI_FROM_DATABASE=GZ Weedong Networks Technology Co. , Ltd OUI:B49EAC* ID_OUI_FROM_DATABASE=Imagik Int'l Corp OUI:C8E42F* ID_OUI_FROM_DATABASE=Technical Research Design and Development OUI:FC2325* ID_OUI_FROM_DATABASE=EosTek (Shenzhen) Co., Ltd. OUI:485929* ID_OUI_FROM_DATABASE=LG Electronics OUI:A81374* ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company OUI:4C83DE* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:5CB6CC* ID_OUI_FROM_DATABASE=NovaComm Technologies Inc. OUI:B4AE6F* ID_OUI_FROM_DATABASE=Circle Reliance, Inc DBA Cranberry Networks OUI:B89919* ID_OUI_FROM_DATABASE=7signal Solutions, Inc OUI:90DA6A* ID_OUI_FROM_DATABASE=FOCUS H&S Co., Ltd. OUI:A45DA1* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:A43D78* ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD OUI:E8EF89* ID_OUI_FROM_DATABASE=OPMEX Tech. OUI:F4C447* ID_OUI_FROM_DATABASE=Coagent International Enterprise Limited OUI:08DF1F* ID_OUI_FROM_DATABASE=Bose Corporation OUI:542AA2* ID_OUI_FROM_DATABASE=Alpha Networks Inc. OUI:58238C* ID_OUI_FROM_DATABASE=Technicolor CH USA OUI:84948C* ID_OUI_FROM_DATABASE=Hitron Technologies. Inc OUI:CCA0E5* ID_OUI_FROM_DATABASE=DZG Metering GmbH OUI:3059B7* ID_OUI_FROM_DATABASE=Microsoft OUI:80414E* ID_OUI_FROM_DATABASE=BBK Electronics Corp., Ltd., OUI:0874F6* ID_OUI_FROM_DATABASE=Winterhalter Gastronom GmbH OUI:FCC2DE* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:1C1CFD* ID_OUI_FROM_DATABASE=Dalian Hi-Think Computer Technology, Corp OUI:7062B8* ID_OUI_FROM_DATABASE=D-Link International OUI:B875C0* ID_OUI_FROM_DATABASE=PayPal, Inc. OUI:E47FB2* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:38262B* ID_OUI_FROM_DATABASE=UTran Technology OUI:20ED74* ID_OUI_FROM_DATABASE=Ability enterprise co.,Ltd. OUI:982F3C* ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. OUI:7824AF* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:0CAC05* ID_OUI_FROM_DATABASE=Unitend Technologies Inc. OUI:B4B859* ID_OUI_FROM_DATABASE=Texa Spa OUI:045C8E* ID_OUI_FROM_DATABASE=gosund GROUP CO.,LTD OUI:54B753* ID_OUI_FROM_DATABASE=Hunan Fenghui Yinjia Science And Technology Co.,Ltd OUI:4826E8* ID_OUI_FROM_DATABASE=Tek-Air Systems, Inc. OUI:A012DB* ID_OUI_FROM_DATABASE=TABUCHI ELECTRIC CO.,LTD OUI:ACB859* ID_OUI_FROM_DATABASE=Uniband Electronic Corp, OUI:100F18* ID_OUI_FROM_DATABASE=Fu Gang Electronic(KunShan)CO.,LTD OUI:C8D590* ID_OUI_FROM_DATABASE=FLIGHT DATA SYSTEMS OUI:709383* ID_OUI_FROM_DATABASE=Intelligent Optical Network High Tech CO.,LTD. OUI:3CCD93* ID_OUI_FROM_DATABASE=LG ELECTRONICS INC OUI:6047D4* ID_OUI_FROM_DATABASE=FORICS Electronic Technology Co., Ltd. OUI:C09D26* ID_OUI_FROM_DATABASE=Topicon HK Lmd. OUI:B061C7* ID_OUI_FROM_DATABASE=Ericsson-LG Enterprise OUI:B05706* ID_OUI_FROM_DATABASE=Vallox Oy OUI:C8D429* ID_OUI_FROM_DATABASE=Muehlbauer AG OUI:20EAC7* ID_OUI_FROM_DATABASE=SHENZHEN RIOPINE ELECTRONICS CO., LTD OUI:80618F* ID_OUI_FROM_DATABASE=Shenzhen sangfei consumer communications co.,ltd OUI:5CF50D* ID_OUI_FROM_DATABASE=Institute of microelectronic applications OUI:10DEE4* ID_OUI_FROM_DATABASE=automationNEXT GmbH OUI:444891* ID_OUI_FROM_DATABASE=HDMI Licensing, LLC OUI:FC923B* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:38F708* ID_OUI_FROM_DATABASE=National Resource Management, Inc. OUI:C4C919* ID_OUI_FROM_DATABASE=Energy Imports Ltd OUI:88A73C* ID_OUI_FROM_DATABASE=Ragentek Technology Group OUI:B0D7C5* ID_OUI_FROM_DATABASE=Logipix Ltd OUI:38C9A9* ID_OUI_FROM_DATABASE=SMART High Reliability Solutions, Inc. OUI:BC1A67* ID_OUI_FROM_DATABASE=YF Technology Co., Ltd OUI:B024F3* ID_OUI_FROM_DATABASE=Progeny Systems OUI:8C4DB9* ID_OUI_FROM_DATABASE=Unmonday Ltd OUI:D87CDD* ID_OUI_FROM_DATABASE=SANIX INCORPORATED OUI:F8A2B4* ID_OUI_FROM_DATABASE=RHEWA-WAAGENFABRIK August Freudewald GmbH &Co. KG OUI:84FE9E* ID_OUI_FROM_DATABASE=RTC Industries, Inc. OUI:403067* ID_OUI_FROM_DATABASE=Conlog (Pty) Ltd OUI:98DA92* ID_OUI_FROM_DATABASE=Vuzix Corporation OUI:5C2AEF* ID_OUI_FROM_DATABASE=Open Access Pty Ltd OUI:E40439* ID_OUI_FROM_DATABASE=TomTom Software Ltd OUI:90AE1B* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:441E91* ID_OUI_FROM_DATABASE=ARVIDA Intelligent Electronics Technology Co.,Ltd. OUI:6C14F7* ID_OUI_FROM_DATABASE=Erhardt+Leimer GmbH OUI:70F96D* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:CC07E4* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:B4430D* ID_OUI_FROM_DATABASE=Broadlink Pty Ltd OUI:A4BBAF* ID_OUI_FROM_DATABASE=Lime Instruments OUI:7CE1FF* ID_OUI_FROM_DATABASE=Computer Performance, Inc. DBA Digital Loggers, Inc. OUI:D069D0* ID_OUI_FROM_DATABASE=Verto Medical Solutions, LLC OUI:ACE069* ID_OUI_FROM_DATABASE=ISAAC Instruments OUI:E8EA6A* ID_OUI_FROM_DATABASE=StarTech.com OUI:C4E984* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:8059FD* ID_OUI_FROM_DATABASE=Noviga OUI:18FF2E* ID_OUI_FROM_DATABASE=Shenzhen Rui Ying Da Technology Co., Ltd OUI:1CAB01* ID_OUI_FROM_DATABASE=Innovolt OUI:68856A* ID_OUI_FROM_DATABASE=OuterLink Corporation OUI:30F42F* ID_OUI_FROM_DATABASE=ESP OUI:C816BD* ID_OUI_FROM_DATABASE=HISENSE ELECTRIC CO.,LTD. OUI:746A8F* ID_OUI_FROM_DATABASE=VS Vision Systems GmbH OUI:B068B6* ID_OUI_FROM_DATABASE=Hangzhou OYE Technology Co. Ltd OUI:9C65F9* ID_OUI_FROM_DATABASE=AcSiP Technology Corp. OUI:487604* ID_OUI_FROM_DATABASE=Private OUI:D057A1* ID_OUI_FROM_DATABASE=Werma Signaltechnik GmbH & Co. KG OUI:3C89A6* ID_OUI_FROM_DATABASE=KAPELSE OUI:90F1B0* ID_OUI_FROM_DATABASE=Hangzhou Anheng Info&Tech CO.,LTD OUI:9C86DA* ID_OUI_FROM_DATABASE=Phoenix Geophysics Ltd. OUI:48FEEA* ID_OUI_FROM_DATABASE=HOMA B.V. OUI:10DDF4* ID_OUI_FROM_DATABASE=Maxway Electronics CO.,LTD OUI:080371* ID_OUI_FROM_DATABASE=KRG CORPORATE OUI:B43A28* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:ACC595* ID_OUI_FROM_DATABASE=Graphite Systems OUI:3413A8* ID_OUI_FROM_DATABASE=Mediplan Limited OUI:4CD9C4* ID_OUI_FROM_DATABASE=Magneti Marelli Automotive Electronics (Guangzhou) Co. Ltd OUI:743ECB* ID_OUI_FROM_DATABASE=Gentrice tech OUI:7071B3* ID_OUI_FROM_DATABASE=Brain Corporation OUI:208986* ID_OUI_FROM_DATABASE=zte corporation OUI:3CD4D6* ID_OUI_FROM_DATABASE=WirelessWERX, Inc OUI:64E625* ID_OUI_FROM_DATABASE=Woxu Wireless Co., Ltd OUI:7C444C* ID_OUI_FROM_DATABASE=Entertainment Solutions, S.L. OUI:501AC5* ID_OUI_FROM_DATABASE=Microsoft OUI:609620* ID_OUI_FROM_DATABASE=Private OUI:F8572E* ID_OUI_FROM_DATABASE=Core Brands, LLC OUI:E0E631* ID_OUI_FROM_DATABASE=SNB TECHNOLOGIES LIMITED OUI:9401C2* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:20C60D* ID_OUI_FROM_DATABASE=Shanghai annijie Information technology Co.,LTD OUI:7C9763* ID_OUI_FROM_DATABASE=Openmatics s.r.o. OUI:0444A1* ID_OUI_FROM_DATABASE=TELECON GALICIA,S.A. OUI:84569C* ID_OUI_FROM_DATABASE=Coho Data, Inc., OUI:78AE0C* ID_OUI_FROM_DATABASE=Far South Networks OUI:38CA97* ID_OUI_FROM_DATABASE=Contour Design LLC OUI:84A783* ID_OUI_FROM_DATABASE=Alcatel Lucent OUI:2C5D93* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:1CC11A* ID_OUI_FROM_DATABASE=Wavetronix OUI:4CF02E* ID_OUI_FROM_DATABASE=Vifa Denmark A/S OUI:3051F8* ID_OUI_FROM_DATABASE=BYK-Gardner GmbH OUI:94C3E4* ID_OUI_FROM_DATABASE=SCA Schucker Gmbh & Co KG OUI:FC19D0* ID_OUI_FROM_DATABASE=Cloud Vision Networks Technology Co.,Ltd. OUI:20E791* ID_OUI_FROM_DATABASE=Siemens Healthcare Diagnostics, Inc OUI:68764F* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:D4D919* ID_OUI_FROM_DATABASE=GoPro OUI:50C9A0* ID_OUI_FROM_DATABASE=SKIPPER Electronics AS OUI:A49F89* ID_OUI_FROM_DATABASE=Shanghai Rui Rui Communication Technology Co.Ltd. OUI:D850E6* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:94103E* ID_OUI_FROM_DATABASE=Belkin International Inc. OUI:B4750E* ID_OUI_FROM_DATABASE=Belkin International Inc. OUI:346178* ID_OUI_FROM_DATABASE=The Boeing Company OUI:187ED5* ID_OUI_FROM_DATABASE=shenzhen kaism technology Co. Ltd OUI:841B38* ID_OUI_FROM_DATABASE=Shenzhen Excelsecu Data Technology Co.,Ltd OUI:EC2AF0* ID_OUI_FROM_DATABASE=Ypsomed AG OUI:044F8B* ID_OUI_FROM_DATABASE=Adapteva, Inc. OUI:9CE7BD* ID_OUI_FROM_DATABASE=Winduskorea co., Ltd OUI:3842A6* ID_OUI_FROM_DATABASE=Ingenieurbuero Stahlkopf OUI:A0BF50* ID_OUI_FROM_DATABASE=S.C. ADD-PRODUCTION S.R.L. OUI:7CB733* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:705957* ID_OUI_FROM_DATABASE=Medallion Instrumentation Systems OUI:6C8366* ID_OUI_FROM_DATABASE=Nanjing SAC Power Grid Automation Co., Ltd. OUI:88576D* ID_OUI_FROM_DATABASE=XTA Electronics Ltd OUI:F83D4E* ID_OUI_FROM_DATABASE=Softlink Automation System Co., Ltd OUI:FCD817* ID_OUI_FROM_DATABASE=Beijing Hesun Technologies Co.Ltd. OUI:909F43* ID_OUI_FROM_DATABASE=Accutron Instruments Inc. OUI:C42795* ID_OUI_FROM_DATABASE=Technicolor USA Inc. OUI:50C006* ID_OUI_FROM_DATABASE=Carmanah Signs OUI:98FB12* ID_OUI_FROM_DATABASE=Grand Electronics (HK) Ltd OUI:3C1040* ID_OUI_FROM_DATABASE=daesung network OUI:B04545* ID_OUI_FROM_DATABASE=YACOUB Automation GmbH OUI:701D7F* ID_OUI_FROM_DATABASE=Comtech Technology Co., Ltd. OUI:60DB2A* ID_OUI_FROM_DATABASE=HNS OUI:7CBF88* ID_OUI_FROM_DATABASE=Mobilicom LTD OUI:90028A* ID_OUI_FROM_DATABASE=Shenzhen Shidean Legrand Electronic Products Co.,Ltd OUI:4C3C16* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:90356E* ID_OUI_FROM_DATABASE=Vodafone Omnitel N.V. OUI:3CCA87* ID_OUI_FROM_DATABASE=Iders Incorporated OUI:08CA45* ID_OUI_FROM_DATABASE=Toyou Feiji Electronics Co., Ltd. OUI:9CA9E4* ID_OUI_FROM_DATABASE=zte corporation OUI:E47723* ID_OUI_FROM_DATABASE=zte corporation OUI:C098E5* ID_OUI_FROM_DATABASE=University of Michigan OUI:B8DF6B* ID_OUI_FROM_DATABASE=SpotCam Co., Ltd. OUI:742B62* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:A0143D* ID_OUI_FROM_DATABASE=PARROT SA OUI:58BDF9* ID_OUI_FROM_DATABASE=Sigrand OUI:344F3F* ID_OUI_FROM_DATABASE=IO-Power Technology Co., Ltd. OUI:C0C687* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:142BD2* ID_OUI_FROM_DATABASE=Armtel Ltd. OUI:F845AD* ID_OUI_FROM_DATABASE=Konka Group Co., Ltd. OUI:54A54B* ID_OUI_FROM_DATABASE=NSC Communications Siberia Ltd OUI:BC2B6B* ID_OUI_FROM_DATABASE=Beijing Haier IC Design Co.,Ltd OUI:642184* ID_OUI_FROM_DATABASE=Nippon Denki Kagaku Co.,LTD OUI:EC3E09* ID_OUI_FROM_DATABASE=PERFORMANCE DESIGNED PRODUCTS, LLC OUI:EC219F* ID_OUI_FROM_DATABASE=VidaBox LLC OUI:98D331* ID_OUI_FROM_DATABASE=Shenzhen Bolutek Technology Co.,Ltd. OUI:3C1A57* ID_OUI_FROM_DATABASE=Cardiopulmonary Corp OUI:6CF97C* ID_OUI_FROM_DATABASE=Nanoptix Inc. OUI:58E02C* ID_OUI_FROM_DATABASE=Micro Technic A/S OUI:E481B3* ID_OUI_FROM_DATABASE=Shenzhen ACT Industrial Co.,Ltd. OUI:BC8556* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:E4F3E3* ID_OUI_FROM_DATABASE=Shanghai iComhome Co.,Ltd. OUI:04CF25* ID_OUI_FROM_DATABASE=MANYCOLORS, INC. OUI:D41090* ID_OUI_FROM_DATABASE=iNFORM Systems AG OUI:3495DB* ID_OUI_FROM_DATABASE=Logitec Corporation OUI:88142B* ID_OUI_FROM_DATABASE=Protonic Holland OUI:B8241A* ID_OUI_FROM_DATABASE=SWEDA INFORMATICA LTDA OUI:3806B4* ID_OUI_FROM_DATABASE=A.D.C. GmbH OUI:341B22* ID_OUI_FROM_DATABASE=Grandbeing Technology Co., Ltd OUI:B4346C* ID_OUI_FROM_DATABASE=MATSUNICHI DIGITAL TECHNOLOGY (HONG KONG) LIMITED OUI:9C1465* ID_OUI_FROM_DATABASE=Edata Elektronik San. ve Tic. A.Ş. OUI:C45444* ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. OUI:587A4D* ID_OUI_FROM_DATABASE=Stonesoft Corporation OUI:E89218* ID_OUI_FROM_DATABASE=Arcontia International AB OUI:58F387* ID_OUI_FROM_DATABASE=HCCP OUI:B0793C* ID_OUI_FROM_DATABASE=Revolv Inc OUI:D022BE* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co.,LTD. OUI:20CEC4* ID_OUI_FROM_DATABASE=Peraso Technologies OUI:04848A* ID_OUI_FROM_DATABASE=7INOVA TECHNOLOGY LIMITED OUI:94D771* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:20C6EB* ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company OUI:700FEC* ID_OUI_FROM_DATABASE=Poindus Systems Corp. OUI:78D5B5* ID_OUI_FROM_DATABASE=NAVIELEKTRO KY OUI:E067B3* ID_OUI_FROM_DATABASE=C-Data Technology Co., Ltd OUI:B887A8* ID_OUI_FROM_DATABASE=Step Ahead Innovations Inc. OUI:140D4F* ID_OUI_FROM_DATABASE=Flextronics International OUI:B847C6* ID_OUI_FROM_DATABASE=SanJet Technology Corp. OUI:CC3540* ID_OUI_FROM_DATABASE=Technicolor USA Inc. OUI:4CDF3D* ID_OUI_FROM_DATABASE=TEAM ENGINEERS ADVANCE TECHNOLOGIES INDIA PVT LTD OUI:B85E7B* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:70F176* ID_OUI_FROM_DATABASE=Data Modul AG OUI:205721* ID_OUI_FROM_DATABASE=Salix Technology CO., Ltd. OUI:704CED* ID_OUI_FROM_DATABASE=TMRG, Inc. OUI:E8516E* ID_OUI_FROM_DATABASE=TSMART Inc. OUI:A067BE* ID_OUI_FROM_DATABASE=Sicon s.r.l. OUI:7C1AFC* ID_OUI_FROM_DATABASE=Dalian Co-Edifice Video Technology Co., Ltd OUI:C034B4* ID_OUI_FROM_DATABASE=Gigastone Corporation OUI:587E61* ID_OUI_FROM_DATABASE=Hisense Electric Co., Ltd OUI:74ADB7* ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. OUI:C462EA* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:DC6F00* ID_OUI_FROM_DATABASE=Livescribe, Inc. OUI:D0737F* ID_OUI_FROM_DATABASE=Mini-Circuits OUI:A4D094* ID_OUI_FROM_DATABASE=Erwin Peters Systemtechnik GmbH OUI:0488E2* ID_OUI_FROM_DATABASE=Beats Electronics LLC OUI:D00EA4* ID_OUI_FROM_DATABASE=Porsche Cars North America OUI:F415FD* ID_OUI_FROM_DATABASE=Shanghai Pateo Electronic Equipment Manufacturing Co., Ltd. OUI:2C9464* ID_OUI_FROM_DATABASE=Cincoze Co., Ltd. OUI:B050BC* ID_OUI_FROM_DATABASE=SHENZHEN BASICOM ELECTRONIC CO.,LTD. OUI:DC7014* ID_OUI_FROM_DATABASE=Private OUI:40BC73* ID_OUI_FROM_DATABASE=Cronoplast S.L. OUI:78303B* ID_OUI_FROM_DATABASE=Stephen Technologies Co.,Limited OUI:78F5E5* ID_OUI_FROM_DATABASE=BEGA Gantenbrink-Leuchten KG OUI:804B20* ID_OUI_FROM_DATABASE=Ventilation Control OUI:4007C0* ID_OUI_FROM_DATABASE=Railtec Systems GmbH OUI:94B8C5* ID_OUI_FROM_DATABASE=RuggedCom Inc. OUI:8C3C07* ID_OUI_FROM_DATABASE=Skiva Technologies, Inc. OUI:784B08* ID_OUI_FROM_DATABASE=f.robotics acquisitions ltd OUI:0C2D89* ID_OUI_FROM_DATABASE=QiiQ Communications Inc. OUI:604A1C* ID_OUI_FROM_DATABASE=SUYIN Corporation OUI:3423BA* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co.,LTD. OUI:A4D3B5* ID_OUI_FROM_DATABASE=GLITEL Stropkov, s.r.o. OUI:A4F3C1* ID_OUI_FROM_DATABASE=Open Source Robotics Foundation, Inc. OUI:6C8B2F* ID_OUI_FROM_DATABASE=zte corporation OUI:B863BC* ID_OUI_FROM_DATABASE=ROBOTIS, Co, Ltd OUI:C8DDC9* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:CC1AFA* ID_OUI_FROM_DATABASE=zte corporation OUI:8C5AF0* ID_OUI_FROM_DATABASE=Exeltech Solar Products OUI:F8DADF* ID_OUI_FROM_DATABASE=EcoTech, Inc. OUI:30AE7B* ID_OUI_FROM_DATABASE=Deqing Dusun Electron CO., LTD OUI:1441E2* ID_OUI_FROM_DATABASE=Monaco Enterprises, Inc. OUI:F07765* ID_OUI_FROM_DATABASE=Sourcefire, Inc OUI:E4F7A1* ID_OUI_FROM_DATABASE=Datafox GmbH OUI:601E02* ID_OUI_FROM_DATABASE=EltexAlatau OUI:E47D5A* ID_OUI_FROM_DATABASE=Beijing Hanbang Technology Corp. OUI:4C6255* ID_OUI_FROM_DATABASE=SANMINA-SCI SYSTEM DE MEXICO S.A. DE C.V. OUI:381766* ID_OUI_FROM_DATABASE=PROMZAKAZ LTD. OUI:204C6D* ID_OUI_FROM_DATABASE=Hugo Brennenstuhl Gmbh & Co. KG. OUI:DC825B* ID_OUI_FROM_DATABASE=JANUS, spol. s r.o. OUI:B08807* ID_OUI_FROM_DATABASE=Strata Worldwide OUI:9893CC* ID_OUI_FROM_DATABASE=LG Electronics Inc. OUI:74D02B* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:A4E0E6* ID_OUI_FROM_DATABASE=FILIZOLA S.A. PESAGEM E AUTOMACAO OUI:60E00E* ID_OUI_FROM_DATABASE=SHINSEI ELECTRONICS CO LTD OUI:30D46A* ID_OUI_FROM_DATABASE=Autosales Incorporated OUI:30AABD* ID_OUI_FROM_DATABASE=Shanghai Reallytek Information Technology Co.,Ltd OUI:A4B818* ID_OUI_FROM_DATABASE=PENTA Gesellschaft für elektronische Industriedatenverarbeitung mbH OUI:106682* ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. OUI:102831* ID_OUI_FROM_DATABASE=Morion Inc. OUI:D81EDE* ID_OUI_FROM_DATABASE=B&W Group Ltd OUI:6897E8* ID_OUI_FROM_DATABASE=Society of Motion Picture & Television Engineers OUI:24EA40* ID_OUI_FROM_DATABASE=Systeme Helmholz GmbH OUI:FC58FA* ID_OUI_FROM_DATABASE=Shen Zhen Shi Xin Zhong Xin Technology Co.,Ltd. OUI:60601F* ID_OUI_FROM_DATABASE=SZ DJI TECHNOLOGY CO.,LTD OUI:E0C6B3* ID_OUI_FROM_DATABASE=MilDef AB OUI:FCDB96* ID_OUI_FROM_DATABASE=ENERVALLEY CO., LTD OUI:74258A* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:F06BCA* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:FC8B97* ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd OUI:882E5A* ID_OUI_FROM_DATABASE=storONE OUI:D429EA* ID_OUI_FROM_DATABASE=Zimory GmbH OUI:C80E95* ID_OUI_FROM_DATABASE=OmniLync Inc. OUI:18DC56* ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific(shenzhen)Co.,Lt OUI:50ABBF* ID_OUI_FROM_DATABASE=Hoseo Telecom OUI:8C7716* ID_OUI_FROM_DATABASE=LONGCHEER TELECOMMUNICATION LIMITED OUI:C8EEA6* ID_OUI_FROM_DATABASE=Shenzhen SHX Technology Co., Ltd OUI:28CBEB* ID_OUI_FROM_DATABASE=One OUI:18E8DD* ID_OUI_FROM_DATABASE=MODULETEK OUI:2C282D* ID_OUI_FROM_DATABASE=BBK COMMUNICATIAO TECHNOLOGY CO.,LTD. OUI:4CCC34* ID_OUI_FROM_DATABASE=Motorola Solutions Inc. OUI:F82FA8* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:F084C9* ID_OUI_FROM_DATABASE=zte corporation OUI:E894F6* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:94ACCA* ID_OUI_FROM_DATABASE=trivum technologies GmbH OUI:7CD844* ID_OUI_FROM_DATABASE=Enmotus Inc OUI:40B0FA* ID_OUI_FROM_DATABASE=LG Electronics OUI:F4C6D7* ID_OUI_FROM_DATABASE=blackned GmbH OUI:68A40E* ID_OUI_FROM_DATABASE=BSH Bosch and Siemens Home Appliances GmbH OUI:4CCA53* ID_OUI_FROM_DATABASE=Skyera, Inc. OUI:081DFB* ID_OUI_FROM_DATABASE=Shanghai Mexon Communication Technology Co.,Ltd OUI:D0CDE1* ID_OUI_FROM_DATABASE=Scientech Electronics OUI:98D6F7* ID_OUI_FROM_DATABASE=LG Electronics OUI:94756E* ID_OUI_FROM_DATABASE=QinetiQ North America OUI:543D37* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:905F2E* ID_OUI_FROM_DATABASE=TCT Mobile Limited OUI:0C5521* ID_OUI_FROM_DATABASE=Axiros GmbH OUI:A4D856* ID_OUI_FROM_DATABASE=Gimbal, Inc OUI:10A743* ID_OUI_FROM_DATABASE=SK Mtek Limited OUI:E4A7FD* ID_OUI_FROM_DATABASE=Cellco Partnership OUI:24F2DD* ID_OUI_FROM_DATABASE=Radiant Zemax LLC OUI:80CF41* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:7C9A9B* ID_OUI_FROM_DATABASE=VSE valencia smart energy OUI:A845E9* ID_OUI_FROM_DATABASE=Firich Enterprises CO., LTD. OUI:78995C* ID_OUI_FROM_DATABASE=Nationz Technologies Inc OUI:8CC5E1* ID_OUI_FROM_DATABASE=ShenZhen Konka Telecommunication Technology Co.,Ltd OUI:6CB311* ID_OUI_FROM_DATABASE=Shenzhen Lianrui Electronics Co.,Ltd OUI:54115F* ID_OUI_FROM_DATABASE=Atamo Pty Ltd OUI:2411D0* ID_OUI_FROM_DATABASE=Chongqing Ehs Science and Technology Development Co.,Ltd. OUI:6C9AC9* ID_OUI_FROM_DATABASE=Valentine Research, Inc. OUI:10F49A* ID_OUI_FROM_DATABASE=T3 Innovation OUI:1C5A3E* ID_OUI_FROM_DATABASE=Samsung Eletronics Co., Ltd (Visual Display Divison) OUI:5865E6* ID_OUI_FROM_DATABASE=INFOMARK CO., LTD. OUI:BC20A4* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:60BD91* ID_OUI_FROM_DATABASE=Move Innovation OUI:98473C* ID_OUI_FROM_DATABASE=SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD OUI:CC4BFB* ID_OUI_FROM_DATABASE=Hellberg Safety AB OUI:ACA22C* ID_OUI_FROM_DATABASE=Baycity Technologies Ltd OUI:6CADEF* ID_OUI_FROM_DATABASE=KZ Broadband Technologies, Ltd. OUI:044BFF* ID_OUI_FROM_DATABASE=GuangZhou Hedy Digital Technology Co., Ltd OUI:949BFD* ID_OUI_FROM_DATABASE=Trans New Technology, Inc. OUI:E4EEFD* ID_OUI_FROM_DATABASE=MR&D Manufacturing OUI:105CBF* ID_OUI_FROM_DATABASE=DuroByte Inc OUI:30C82A* ID_OUI_FROM_DATABASE=Wi-Next s.r.l. OUI:88A3CC* ID_OUI_FROM_DATABASE=Amatis Controls OUI:EC89F5* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:083AB8* ID_OUI_FROM_DATABASE=Shinoda Plasma Co., Ltd. OUI:A0DD97* ID_OUI_FROM_DATABASE=PolarLink Technologies, Ltd OUI:E05597* ID_OUI_FROM_DATABASE=Emergent Vision Technologies Inc. OUI:A01917* ID_OUI_FROM_DATABASE=Bertel S.p.a. OUI:FC9FAE* ID_OUI_FROM_DATABASE=Fidus Systems Inc OUI:FC0647* ID_OUI_FROM_DATABASE=Cortland Research, LLC OUI:20918A* ID_OUI_FROM_DATABASE=PROFALUX OUI:7C438F* ID_OUI_FROM_DATABASE=E-Band Communications Corp. OUI:FC626E* ID_OUI_FROM_DATABASE=Beijing MDC Telecom OUI:C0B339* ID_OUI_FROM_DATABASE=Comigo Ltd. OUI:DCC0DB* ID_OUI_FROM_DATABASE=Shenzhen Kaiboer Technology Co., Ltd. OUI:7076DD* ID_OUI_FROM_DATABASE=Oxyguard International A/S OUI:E89AFF* ID_OUI_FROM_DATABASE=Fujian Landi Commercial Equipment Co.,Ltd OUI:683B1E* ID_OUI_FROM_DATABASE=Countwise LTD OUI:D4136F* ID_OUI_FROM_DATABASE=Asia Pacific Brands OUI:9C2A70* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:A0A130* ID_OUI_FROM_DATABASE=DLI Taiwan Branch office OUI:38BC1A* ID_OUI_FROM_DATABASE=Meizu technology co.,ltd OUI:ECE915* ID_OUI_FROM_DATABASE=STI Ltd OUI:A81FAF* ID_OUI_FROM_DATABASE=KRYPTON POLSKA OUI:087BAA* ID_OUI_FROM_DATABASE=SVYAZKOMPLEKTSERVICE, LLC OUI:2C26C5* ID_OUI_FROM_DATABASE=zte corporation OUI:BC629F* ID_OUI_FROM_DATABASE=Telenet Systems P. Ltd. OUI:F47B5E* ID_OUI_FROM_DATABASE=Samsung Eletronics Co., Ltd OUI:B47F5E* ID_OUI_FROM_DATABASE=Foresight Manufacture (S) Pte Ltd OUI:785517* ID_OUI_FROM_DATABASE=SankyuElectronics OUI:848E96* ID_OUI_FROM_DATABASE=Embertec Pty Ltd OUI:CC3A61* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. OUI:A00363* ID_OUI_FROM_DATABASE=Robert Bosch Healthcare GmbH OUI:F0F644* ID_OUI_FROM_DATABASE=Whitesky Science & Technology Co.,Ltd. OUI:30D357* ID_OUI_FROM_DATABASE=Logosol, Inc. OUI:14F42A* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:2C441B* ID_OUI_FROM_DATABASE=Spectrum Medical Limited OUI:1C5A6B* ID_OUI_FROM_DATABASE=Philips Electronics Nederland BV OUI:A875D6* ID_OUI_FROM_DATABASE=FreeTek International Co., Ltd. OUI:58EB14* ID_OUI_FROM_DATABASE=Proteus Digital Health OUI:789F87* ID_OUI_FROM_DATABASE=Siemens AG I IA PP PRM OUI:7C0A50* ID_OUI_FROM_DATABASE=J-MEX Inc. OUI:40F2E9* ID_OUI_FROM_DATABASE=IBM OUI:9C0473* ID_OUI_FROM_DATABASE=Tecmobile (International) Ltd. OUI:CC262D* ID_OUI_FROM_DATABASE=Verifi, LLC OUI:3C8AE5* ID_OUI_FROM_DATABASE=Tensun Information Technology(Hangzhou) Co.,LTD OUI:7CB232* ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD OUI:54DF63* ID_OUI_FROM_DATABASE=Intrakey technologies GmbH OUI:7C0187* ID_OUI_FROM_DATABASE=Curtis Instruments, Inc. OUI:388EE7* ID_OUI_FROM_DATABASE=Fanhattan LLC OUI:54F666* ID_OUI_FROM_DATABASE=Berthold Technologies GmbH and Co.KG OUI:802FDE* ID_OUI_FROM_DATABASE=Zurich Instruments AG OUI:08AF78* ID_OUI_FROM_DATABASE=Totus Solutions, Inc. OUI:5C38E0* ID_OUI_FROM_DATABASE=Shanghai Super Electronics Technology Co.,LTD OUI:A0E534* ID_OUI_FROM_DATABASE=Stratec Biomedical AG OUI:2891D0* ID_OUI_FROM_DATABASE=Stage Tec Entwicklungsgesellschaft für professionelle Audiotechnik mbH OUI:A854B2* ID_OUI_FROM_DATABASE=Wistron Neweb Corp. OUI:98291D* ID_OUI_FROM_DATABASE=Jaguar de Mexico, SA de CV OUI:18863A* ID_OUI_FROM_DATABASE=DIGITAL ART SYSTEM OUI:F4B72A* ID_OUI_FROM_DATABASE=TIME INTERCONNECT LTD OUI:34D7B4* ID_OUI_FROM_DATABASE=Tributary Systems, Inc. OUI:F40F9B* ID_OUI_FROM_DATABASE=WAVELINK OUI:144319* ID_OUI_FROM_DATABASE=Creative&Link Technology Limited OUI:64F50E* ID_OUI_FROM_DATABASE=Kinion Technology Company Limited OUI:28A186* ID_OUI_FROM_DATABASE=enblink OUI:1C9492* ID_OUI_FROM_DATABASE=RUAG Schweiz AG OUI:24694A* ID_OUI_FROM_DATABASE=Jasmine Systems Inc. OUI:C8C791* ID_OUI_FROM_DATABASE=Zero1.tv GmbH OUI:60748D* ID_OUI_FROM_DATABASE=Atmaca Elektronik OUI:78D129* ID_OUI_FROM_DATABASE=Vicos OUI:78AB60* ID_OUI_FROM_DATABASE=ABB Australia OUI:289A4B* ID_OUI_FROM_DATABASE=SteelSeries ApS OUI:0CC66A* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:3078C2* ID_OUI_FROM_DATABASE=Innowireless, Co. Ltd. OUI:58986F* ID_OUI_FROM_DATABASE=Revolution Display OUI:7CFE28* ID_OUI_FROM_DATABASE=Salutron Inc. OUI:109FA9* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:C0A364* ID_OUI_FROM_DATABASE=3D Systems Massachusetts OUI:98A7B0* ID_OUI_FROM_DATABASE=MCST ZAO OUI:88DC96* ID_OUI_FROM_DATABASE=SENAO Networks, Inc. OUI:4C0B3A* ID_OUI_FROM_DATABASE=TCT Mobile Limited OUI:C455C2* ID_OUI_FROM_DATABASE=Bach-Simpson OUI:ECA29B* ID_OUI_FROM_DATABASE=Kemppi Oy OUI:04CE14* ID_OUI_FROM_DATABASE=Wilocity LTD. OUI:802AFA* ID_OUI_FROM_DATABASE=Germaneers GmbH OUI:1C8464* ID_OUI_FROM_DATABASE=FORMOSA WIRELESS COMMUNICATION CORP. OUI:D867D9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B4218A* ID_OUI_FROM_DATABASE=Dog Hunter LLC OUI:F8A03D* ID_OUI_FROM_DATABASE=Dinstar Technologies Co., Ltd. OUI:D08CFF* ID_OUI_FROM_DATABASE=UPWIS AB OUI:9C066E* ID_OUI_FROM_DATABASE=Hytera Communications Corporation Limited OUI:746A89* ID_OUI_FROM_DATABASE=Rezolt Corporation OUI:68D1FD* ID_OUI_FROM_DATABASE=Shenzhen Trimax Technology Co.,Ltd OUI:241B13* ID_OUI_FROM_DATABASE=Shanghai Nutshell Electronic Co., Ltd. OUI:B43564* ID_OUI_FROM_DATABASE=Fujian Tian Cheng Electron Science & Technical Development Co.,Ltd. OUI:54D1B0* ID_OUI_FROM_DATABASE=Universal Laser Systems, Inc OUI:A497BB* ID_OUI_FROM_DATABASE=Hitachi Industrial Equipment Systems Co.,Ltd OUI:FC52CE* ID_OUI_FROM_DATABASE=Control iD OUI:E804F3* ID_OUI_FROM_DATABASE=Throughtek Co., Ltd. OUI:B85810* ID_OUI_FROM_DATABASE=NUMERA, INC. OUI:2CAB25* ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd OUI:AC6E1A* ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd OUI:9886B1* ID_OUI_FROM_DATABASE=Flyaudio corporation (China) OUI:28B3AB* ID_OUI_FROM_DATABASE=Genmark Automation OUI:44E8A5* ID_OUI_FROM_DATABASE=Myreka Technologies Sdn. Bhd. OUI:AC14D2* ID_OUI_FROM_DATABASE=wi-daq, inc. OUI:9C4CAE* ID_OUI_FROM_DATABASE=Mesa Labs OUI:7CD9FE* ID_OUI_FROM_DATABASE=New Cosmos Electric Co., Ltd. OUI:E49069* ID_OUI_FROM_DATABASE=Rockwell Automation OUI:B48910* ID_OUI_FROM_DATABASE=Coster T.E. S.P.A. OUI:183919* ID_OUI_FROM_DATABASE=Unicoi Systems OUI:A4B1E9* ID_OUI_FROM_DATABASE=Technicolor OUI:30AEF6* ID_OUI_FROM_DATABASE=Radio Mobile Access OUI:58343B* ID_OUI_FROM_DATABASE=Glovast Technology Ltd. OUI:54A04F* ID_OUI_FROM_DATABASE=t-mac Technologies Ltd OUI:E44F5F* ID_OUI_FROM_DATABASE=EDS Elektronik Destek San.Tic.Ltd.Sti OUI:08B738* ID_OUI_FROM_DATABASE=Lite-On Technogy Corp. OUI:9C6650* ID_OUI_FROM_DATABASE=Glodio Technolies Co.,Ltd Tianjin Branch OUI:503955* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:90CF6F* ID_OUI_FROM_DATABASE=Dlogixs Co Ltd OUI:68AF13* ID_OUI_FROM_DATABASE=Futura Mobility OUI:B82410* ID_OUI_FROM_DATABASE=Magneti Marelli Slovakia s.r.o. OUI:A8EF26* ID_OUI_FROM_DATABASE=Tritonwave OUI:F0D3E7* ID_OUI_FROM_DATABASE=Sensometrix SA OUI:7CC8D0* ID_OUI_FROM_DATABASE=TIANJIN YAAN TECHNOLOGY CO., LTD. OUI:88E917* ID_OUI_FROM_DATABASE=Tamaggo OUI:80AAA4* ID_OUI_FROM_DATABASE=USAG OUI:5C2479* ID_OUI_FROM_DATABASE=Baltech AG OUI:E8CBA1* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:F85F2A* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:286094* ID_OUI_FROM_DATABASE=CAPELEC OUI:60E956* ID_OUI_FROM_DATABASE=Ayla Networks, Inc OUI:287184* ID_OUI_FROM_DATABASE=Spire Payments OUI:1CB094* ID_OUI_FROM_DATABASE=HTC Corporation OUI:FC5090* ID_OUI_FROM_DATABASE=SIMEX Sp. z o.o. OUI:209BA5* ID_OUI_FROM_DATABASE=JIAXING GLEAD Electronics Co.,Ltd OUI:60843B* ID_OUI_FROM_DATABASE=Soladigm, Inc. OUI:508C77* ID_OUI_FROM_DATABASE=DIRMEIER Schanktechnik GmbH &Co KG OUI:6089B1* ID_OUI_FROM_DATABASE=Key Digital Systems OUI:080CC9* ID_OUI_FROM_DATABASE=Mission Technology Group, dba Magma OUI:3C970E* ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd. OUI:A0F450* ID_OUI_FROM_DATABASE=HTC Corporation OUI:44D15E* ID_OUI_FROM_DATABASE=Shanghai Kingto Information Technology Ltd OUI:545EBD* ID_OUI_FROM_DATABASE=NL Technologies OUI:C8BBD3* ID_OUI_FROM_DATABASE=Embrane OUI:ECD19A* ID_OUI_FROM_DATABASE=Zhuhai Liming Industries Co., Ltd OUI:346E8A* ID_OUI_FROM_DATABASE=Ecosense OUI:ACEE3B* ID_OUI_FROM_DATABASE=6harmonics Inc OUI:681605* ID_OUI_FROM_DATABASE=Systems And Electronic Development FZCO OUI:04F17D* ID_OUI_FROM_DATABASE=Tarana Wireless OUI:A0DC04* ID_OUI_FROM_DATABASE=Becker-Antriebe GmbH OUI:B85510* ID_OUI_FROM_DATABASE=Zioncom Electronics (Shenzhen) Ltd. OUI:8CC121* ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company OUI:2CBE97* ID_OUI_FROM_DATABASE=Ingenieurbuero Bickele und Buehler GmbH OUI:045A95* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:B40E96* ID_OUI_FROM_DATABASE=HERAN OUI:BC851F* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:0CAF5A* ID_OUI_FROM_DATABASE=GENUS POWER INFRASTRUCTURES LIMITED OUI:D0699E* ID_OUI_FROM_DATABASE=LUMINEX Lighting Control Equipment OUI:64AE88* ID_OUI_FROM_DATABASE=Polytec GmbH OUI:2C542D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:709E86* ID_OUI_FROM_DATABASE=X6D Limited OUI:946124* ID_OUI_FROM_DATABASE=Pason Systems OUI:DC309C* ID_OUI_FROM_DATABASE=Heyrex Limited OUI:E81324* ID_OUI_FROM_DATABASE=GuangZhou Bonsoninfo System CO.,LTD OUI:0036F8* ID_OUI_FROM_DATABASE=Conti Temic microelectronic GmbH OUI:443839* ID_OUI_FROM_DATABASE=Cumulus Networks, inc OUI:20F002* ID_OUI_FROM_DATABASE=MTData Developments Pty. Ltd. OUI:CC912B* ID_OUI_FROM_DATABASE=TE Connectivity Touch Solutions OUI:785262* ID_OUI_FROM_DATABASE=Shenzhen Hojy Software Co., Ltd. OUI:40336C* ID_OUI_FROM_DATABASE=Godrej & Boyce Mfg. co. ltd OUI:FC1D59* ID_OUI_FROM_DATABASE=I Smart Cities HK Ltd OUI:EC0ED6* ID_OUI_FROM_DATABASE=ITECH INSTRUMENTS SAS OUI:D0D212* ID_OUI_FROM_DATABASE=K2NET Co.,Ltd. OUI:9C8EDC* ID_OUI_FROM_DATABASE=Teracom Limited OUI:146A0B* ID_OUI_FROM_DATABASE=Cypress Electronics Limited OUI:B0750C* ID_OUI_FROM_DATABASE=QA Cafe OUI:B4E1EB* ID_OUI_FROM_DATABASE=Private OUI:FC2A54* ID_OUI_FROM_DATABASE=Connected Data, Inc. OUI:A090DE* ID_OUI_FROM_DATABASE=VEEDIMS,LLC OUI:AC1461* ID_OUI_FROM_DATABASE=ATAW Co., Ltd. OUI:508A42* ID_OUI_FROM_DATABASE=Uptmate Technology Co., LTD OUI:8C57FD* ID_OUI_FROM_DATABASE=LVX Western OUI:002A6A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B88F14* ID_OUI_FROM_DATABASE=Analytica GmbH OUI:94FAE8* ID_OUI_FROM_DATABASE=Shenzhen Eycom Technology Co., Ltd OUI:4844F7* ID_OUI_FROM_DATABASE=Samsung Electronics Co., LTD OUI:3CA315* ID_OUI_FROM_DATABASE=Bless Information & Communications Co., Ltd OUI:F8DB4C* ID_OUI_FROM_DATABASE=PNY Technologies, INC. OUI:F83094* ID_OUI_FROM_DATABASE=Alcatel-Lucent Telecom Limited OUI:2817CE* ID_OUI_FROM_DATABASE=Omnisense Ltd OUI:28E608* ID_OUI_FROM_DATABASE=Tokheim OUI:E477D4* ID_OUI_FROM_DATABASE=Minrray Industry Co.,Ltd OUI:A4B980* ID_OUI_FROM_DATABASE=Parking BOXX Inc. OUI:002D76* ID_OUI_FROM_DATABASE=TITECH GmbH OUI:DC7144* ID_OUI_FROM_DATABASE=Samsung Electro Mechanics OUI:78A183* ID_OUI_FROM_DATABASE=Advidia OUI:F85063* ID_OUI_FROM_DATABASE=Verathon OUI:400E67* ID_OUI_FROM_DATABASE=Tremol Ltd. OUI:901B0E* ID_OUI_FROM_DATABASE=Fujitsu Technology Solutions GmbH OUI:5C6F4F* ID_OUI_FROM_DATABASE=S.A. SISTEL OUI:B058C4* ID_OUI_FROM_DATABASE=Broadcast Microwave Services, Inc OUI:B820E7* ID_OUI_FROM_DATABASE=Guangzhou Horizontal Information & Network Integration Co. Ltd OUI:98588A* ID_OUI_FROM_DATABASE=SYSGRATION Ltd. OUI:842B50* ID_OUI_FROM_DATABASE=Huria Co.,Ltd. OUI:0C5A19* ID_OUI_FROM_DATABASE=Axtion Sdn Bhd OUI:606BBD* ID_OUI_FROM_DATABASE=Samsung Electronics Co., LTD OUI:A00CA1* ID_OUI_FROM_DATABASE=SKTB SKiT OUI:E09579* ID_OUI_FROM_DATABASE=ORTHOsoft inc, d/b/a Zimmer CAS OUI:307ECB* ID_OUI_FROM_DATABASE=SFR OUI:90A783* ID_OUI_FROM_DATABASE=JSW PACIFIC CORPORATION OUI:000830* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:CCEF48* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:78A5DD* ID_OUI_FROM_DATABASE=Shenzhen Smarteye Digital Electronics Co., Ltd OUI:28B0CC* ID_OUI_FROM_DATABASE=Xenya d.o.o. OUI:94D723* ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co., Ltd OUI:ECE744* ID_OUI_FROM_DATABASE=Omntec mfg. inc OUI:80427C* ID_OUI_FROM_DATABASE=Adolf Tedsen GmbH & Co. KG OUI:F8F7D3* ID_OUI_FROM_DATABASE=International Communications Corporation OUI:B89AED* ID_OUI_FROM_DATABASE=OceanServer Technology, Inc OUI:E455EA* ID_OUI_FROM_DATABASE=Dedicated Computing OUI:00FC58* ID_OUI_FROM_DATABASE=WebSilicon Ltd. OUI:64A0E7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:18E80F* ID_OUI_FROM_DATABASE=Viking Electronics Inc. OUI:EC6264* ID_OUI_FROM_DATABASE=Global411 Internet Services, LLC OUI:00F051* ID_OUI_FROM_DATABASE=KWB Gmbh OUI:44DC91* ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. OUI:F0DEB9* ID_OUI_FROM_DATABASE=ShangHai Y&Y Electronics Co., Ltd OUI:AC54EC* ID_OUI_FROM_DATABASE=IEEE P1823 Standards Working Group OUI:C8292A* ID_OUI_FROM_DATABASE=Barun Electronics OUI:E0DADC* ID_OUI_FROM_DATABASE=JVC KENWOOD Corporation OUI:C894D2* ID_OUI_FROM_DATABASE=Jiangsu Datang Electronic Products Co., Ltd OUI:A0423F* ID_OUI_FROM_DATABASE=Tyan Computer Corp OUI:5C18B5* ID_OUI_FROM_DATABASE=Talon Communications OUI:78BAD0* ID_OUI_FROM_DATABASE=Shinybow Technology Co. Ltd. OUI:306CBE* ID_OUI_FROM_DATABASE=Skymotion Technology (HK) Limited OUI:40D559* ID_OUI_FROM_DATABASE=MICRO S.E.R.I. OUI:F82F5B* ID_OUI_FROM_DATABASE=eGauge Systems LLC OUI:3499D7* ID_OUI_FROM_DATABASE=Universal Flow Monitors, Inc. OUI:7C336E* ID_OUI_FROM_DATABASE=MEG Electronics Inc. OUI:D0C1B1* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:D4D249* ID_OUI_FROM_DATABASE=Power Ethernet OUI:10C2BA* ID_OUI_FROM_DATABASE=UTT Co., Ltd. OUI:F0DA7C* ID_OUI_FROM_DATABASE=RLH INDUSTRIES,INC. OUI:40984C* ID_OUI_FROM_DATABASE=Casacom Solutions AG OUI:B8975A* ID_OUI_FROM_DATABASE=BIOSTAR Microtech Int'l Corp. OUI:4833DD* ID_OUI_FROM_DATABASE=ZENNIO AVANCE Y TECNOLOGIA, S.L. OUI:D4D748* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:9CCAD9* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:F8313E* ID_OUI_FROM_DATABASE=endeavour GmbH OUI:10FC54* ID_OUI_FROM_DATABASE=Shany Electronic Co., Ltd. OUI:D4CA6D* ID_OUI_FROM_DATABASE=Routerboard.com OUI:D8E743* ID_OUI_FROM_DATABASE=Wush, Inc OUI:A0F3E4* ID_OUI_FROM_DATABASE=Alcatel Lucent IPD OUI:908FCF* ID_OUI_FROM_DATABASE=UNO System Co., Ltd OUI:903CAE* ID_OUI_FROM_DATABASE=Yunnan KSEC Digital Technology Co.,Ltd. OUI:000831* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:F0620D* ID_OUI_FROM_DATABASE=Shenzhen Egreat Tech Corp.,Ltd OUI:843611* ID_OUI_FROM_DATABASE=hyungseul publishing networks OUI:DC9FDB* ID_OUI_FROM_DATABASE=Ubiquiti Networks, Inc. OUI:B8FD32* ID_OUI_FROM_DATABASE=Zhejiang ROICX Microelectronics OUI:D8052E* ID_OUI_FROM_DATABASE=Skyviia Corporation OUI:F83553* ID_OUI_FROM_DATABASE=Magenta Research Ltd. OUI:DC3C2E* ID_OUI_FROM_DATABASE=Manufacturing System Insights, Inc. OUI:40BC8B* ID_OUI_FROM_DATABASE=itelio GmbH OUI:88C36E* ID_OUI_FROM_DATABASE=Beijing Ereneben lnformation Technology Limited OUI:8CDE52* ID_OUI_FROM_DATABASE=ISSC Technologies Corp. OUI:A8776F* ID_OUI_FROM_DATABASE=Zonoff OUI:FC4DD4* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. OUI:902B34* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:48E1AF* ID_OUI_FROM_DATABASE=Vity OUI:245FDF* ID_OUI_FROM_DATABASE=KYOCERA Corporation OUI:C0A0DE* ID_OUI_FROM_DATABASE=Multi Touch Oy OUI:943AF0* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:B826D4* ID_OUI_FROM_DATABASE=Furukawa Industrial S.A. Produtos Elétricos OUI:14E4EC* ID_OUI_FROM_DATABASE=mLogic LLC OUI:FC0A81* ID_OUI_FROM_DATABASE=Zebra Technologies Inc OUI:AC0DFE* ID_OUI_FROM_DATABASE=Ekon GmbH - myGEKKO OUI:005CB1* ID_OUI_FROM_DATABASE=Gospell DIGITAL TECHNOLOGY CO., LTD OUI:186751* ID_OUI_FROM_DATABASE=KOMEG Industrielle Messtechnik GmbH OUI:B467E9* ID_OUI_FROM_DATABASE=Qingdao GoerTek Technology Co., Ltd. OUI:B49EE6* ID_OUI_FROM_DATABASE=SHENZHEN TECHNOLOGY CO LTD OUI:7041B7* ID_OUI_FROM_DATABASE=Edwards Lifesciences LLC OUI:A849A5* ID_OUI_FROM_DATABASE=Lisantech Co., Ltd. OUI:94DB49* ID_OUI_FROM_DATABASE=SITCORP OUI:30144A* ID_OUI_FROM_DATABASE=Wistron Neweb Corp. OUI:8CD17B* ID_OUI_FROM_DATABASE=CG Mobile OUI:144978* ID_OUI_FROM_DATABASE=Digital Control Incorporated OUI:FC8FC4* ID_OUI_FROM_DATABASE=Intelligent Technology Inc. OUI:F04A2B* ID_OUI_FROM_DATABASE=PYRAMID Computer GmbH OUI:CC9093* ID_OUI_FROM_DATABASE=Hansong Tehnologies OUI:78F7D0* ID_OUI_FROM_DATABASE=Silverbrook Research OUI:F04B6A* ID_OUI_FROM_DATABASE=Scientific Production Association Siberian Arsenal, Ltd. OUI:30DE86* ID_OUI_FROM_DATABASE=Cedac Software S.r.l. OUI:F013C3* ID_OUI_FROM_DATABASE=SHENZHEN FENDA TECHNOLOGY CO., LTD OUI:CCE7DF* ID_OUI_FROM_DATABASE=American Magnetics, Inc. OUI:E44E18* ID_OUI_FROM_DATABASE=Gardasoft VisionLimited OUI:D41C1C* ID_OUI_FROM_DATABASE=RCF S.P.A. OUI:8C94CF* ID_OUI_FROM_DATABASE=Encell Technology, Inc. OUI:149090* ID_OUI_FROM_DATABASE=KongTop industrial(shen zhen)CO.,LTD OUI:F008F1* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:CCF8F0* ID_OUI_FROM_DATABASE=Xi'an HISU Multimedia Technology Co.,Ltd. OUI:30F9ED* ID_OUI_FROM_DATABASE=Sony Corporation OUI:28C718* ID_OUI_FROM_DATABASE=Altierre OUI:2046A1* ID_OUI_FROM_DATABASE=VECOW Co., Ltd OUI:8C271D* ID_OUI_FROM_DATABASE=QuantHouse OUI:9C8BF1* ID_OUI_FROM_DATABASE=The Warehouse Limited OUI:147DC5* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:944696* ID_OUI_FROM_DATABASE=BaudTec Corporation OUI:90342B* ID_OUI_FROM_DATABASE=Gatekeeper Systems, Inc. OUI:D45251* ID_OUI_FROM_DATABASE=IBT Ingenieurbureau Broennimann Thun OUI:3071B2* ID_OUI_FROM_DATABASE=Hangzhou Prevail Optoelectronic Equipment Co.,LTD. OUI:B82ADC* ID_OUI_FROM_DATABASE=EFR Europäische Funk-Rundsteuerung GmbH OUI:B09BD4* ID_OUI_FROM_DATABASE=GNH Software India Private Limited OUI:7CF429* ID_OUI_FROM_DATABASE=NUUO Inc. OUI:B8CDA7* ID_OUI_FROM_DATABASE=Maxeler Technologies Ltd. OUI:F49461* ID_OUI_FROM_DATABASE=NexGen Storage OUI:402CF4* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. OUI:804731* ID_OUI_FROM_DATABASE=Packet Design, Inc. OUI:C4CAD9* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:ACCB09* ID_OUI_FROM_DATABASE=Hefcom Metering (Pty) Ltd OUI:10EED9* ID_OUI_FROM_DATABASE=Canoga Perkins Corporation OUI:240BB1* ID_OUI_FROM_DATABASE=KOSTAL Industrie Elektrik GmbH OUI:20EEC6* ID_OUI_FROM_DATABASE=Elefirst Science & Tech Co ., ltd OUI:807A7F* ID_OUI_FROM_DATABASE=ABB Genway Xiamen Electrical Equipment CO., LTD OUI:14373B* ID_OUI_FROM_DATABASE=PROCOM Systems OUI:B81999* ID_OUI_FROM_DATABASE=Nesys OUI:4C5585* ID_OUI_FROM_DATABASE=Hamilton Systems OUI:8CCF5C* ID_OUI_FROM_DATABASE=BEFEGA GmbH OUI:A0133B* ID_OUI_FROM_DATABASE=HiTi Digital, Inc. OUI:448E12* ID_OUI_FROM_DATABASE=DT Research, Inc. OUI:9C5711* ID_OUI_FROM_DATABASE=Feitian Xunda(Beijing) Aeronautical Information Technology Co., Ltd. OUI:18AD4D* ID_OUI_FROM_DATABASE=Polostar Technology Corporation OUI:4CA74B* ID_OUI_FROM_DATABASE=Alcatel Lucent OUI:549478* ID_OUI_FROM_DATABASE=Silvershore Technology Partners OUI:F4B164* ID_OUI_FROM_DATABASE=Lightning Telecommunications Technology Co. Ltd OUI:0CFC83* ID_OUI_FROM_DATABASE=Airoha Technology Corp., OUI:0C51F7* ID_OUI_FROM_DATABASE=CHAUVIN ARNOUX OUI:70B035* ID_OUI_FROM_DATABASE=Shenzhen Zowee Technology Co., Ltd OUI:708105* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00082F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:542018* ID_OUI_FROM_DATABASE=Tely Labs OUI:581FEF* ID_OUI_FROM_DATABASE=Tuttnaer LTD OUI:F8F25A* ID_OUI_FROM_DATABASE=G-Lab GmbH OUI:BC779F* ID_OUI_FROM_DATABASE=SBM Co., Ltd. OUI:C058A7* ID_OUI_FROM_DATABASE=Pico Systems Co., Ltd. OUI:04D783* ID_OUI_FROM_DATABASE=Y&H E&C Co.,LTD. OUI:00E175* ID_OUI_FROM_DATABASE=AK-Systems Ltd OUI:843F4E* ID_OUI_FROM_DATABASE=Tri-Tech Manufacturing, Inc. OUI:C83232* ID_OUI_FROM_DATABASE=Hunting Innova OUI:D059C3* ID_OUI_FROM_DATABASE=CeraMicro Technology Corporation OUI:EC9681* ID_OUI_FROM_DATABASE=2276427 Ontario Inc OUI:B8288B* ID_OUI_FROM_DATABASE=Parker Hannifin Manufacturing (UK) Ltd OUI:5835D9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:802E14* ID_OUI_FROM_DATABASE=azeti Networks AG OUI:E8944C* ID_OUI_FROM_DATABASE=Cogent Healthcare Systems Ltd OUI:68F895* ID_OUI_FROM_DATABASE=Redflow Limited OUI:A88792* ID_OUI_FROM_DATABASE=Broadband Antenna Tracking Systems OUI:901900* ID_OUI_FROM_DATABASE=SCS SA OUI:AC932F* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:1435B3* ID_OUI_FROM_DATABASE=Future Designs, Inc. OUI:FCF1CD* ID_OUI_FROM_DATABASE=OPTEX-FA CO.,LTD. OUI:B03829* ID_OUI_FROM_DATABASE=Siliconware Precision Industries Co., Ltd. OUI:C86C87* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:BC0F2B* ID_OUI_FROM_DATABASE=FORTUNE TECHGROUP CO.,LTD OUI:8CF9C9* ID_OUI_FROM_DATABASE=MESADA Technology Co.,Ltd. OUI:E42AD3* ID_OUI_FROM_DATABASE=Magneti Marelli S.p.A. Powertrain OUI:FC10BD* ID_OUI_FROM_DATABASE=Control Sistematizado S.A. OUI:443719* ID_OUI_FROM_DATABASE=2 Save Energy Ltd OUI:E83EB6* ID_OUI_FROM_DATABASE=RIM OUI:94FD1D* ID_OUI_FROM_DATABASE=WhereWhen Corp OUI:0CE82F* ID_OUI_FROM_DATABASE=Bonfiglioli Vectron GmbH OUI:C0626B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:74D0DC* ID_OUI_FROM_DATABASE=ERICSSON AB OUI:B4B88D* ID_OUI_FROM_DATABASE=Thuh Company OUI:60F59C* ID_OUI_FROM_DATABASE=CRU-Dataport OUI:C4108A* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:4C73A5* ID_OUI_FROM_DATABASE=KOVE OUI:F86971* ID_OUI_FROM_DATABASE=Seibu Electric Co., OUI:44AA27* ID_OUI_FROM_DATABASE=udworks Co., Ltd. OUI:6CAD3F* ID_OUI_FROM_DATABASE=Hubbell Building Automation, Inc. OUI:8427CE* ID_OUI_FROM_DATABASE=Corporation of the Presiding Bishop of The Church of Jesus Christ of Latter-day Saints OUI:D428B2* ID_OUI_FROM_DATABASE=ioBridge, Inc. OUI:90B8D0* ID_OUI_FROM_DATABASE=Joyent, Inc. OUI:909060* ID_OUI_FROM_DATABASE=RSI VIDEO TECHNOLOGIES OUI:3859F9* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:281471* ID_OUI_FROM_DATABASE=Lantis co., LTD. OUI:1407E0* ID_OUI_FROM_DATABASE=Abrantix AG OUI:DCCF94* ID_OUI_FROM_DATABASE=Beijing Rongcheng Hutong Technology Co., Ltd. OUI:18E288* ID_OUI_FROM_DATABASE=STT Condigi OUI:68876B* ID_OUI_FROM_DATABASE=INQ Mobile Limited OUI:9866EA* ID_OUI_FROM_DATABASE=Industrial Control Communications, Inc. OUI:F4A52A* ID_OUI_FROM_DATABASE=Hawa Technologies Inc OUI:90CF15* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:B8D49D* ID_OUI_FROM_DATABASE=M Seven System Ltd. OUI:B0A10A* ID_OUI_FROM_DATABASE=Pivotal Systems Corporation OUI:48F47D* ID_OUI_FROM_DATABASE=TechVision Holding Internation Limited OUI:6C391D* ID_OUI_FROM_DATABASE=Beijing ZhongHuaHun Network Information center OUI:64D241* ID_OUI_FROM_DATABASE=Keith & Koep GmbH OUI:101212* ID_OUI_FROM_DATABASE=Vivo International Corporation Pty Ltd OUI:5087B8* ID_OUI_FROM_DATABASE=Nuvyyo Inc OUI:E41289* ID_OUI_FROM_DATABASE=topsystem Systemhaus GmbH OUI:A4134E* ID_OUI_FROM_DATABASE=Luxul OUI:B09928* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:8C11CB* ID_OUI_FROM_DATABASE=ABUS Security-Center GmbH & Co. KG OUI:806459* ID_OUI_FROM_DATABASE=Nimbus Inc. OUI:A45A1C* ID_OUI_FROM_DATABASE=smart-electronic GmbH OUI:8C89A5* ID_OUI_FROM_DATABASE=Micro-Star INT'L CO., LTD OUI:3C672C* ID_OUI_FROM_DATABASE=Sciovid Inc. OUI:18D071* ID_OUI_FROM_DATABASE=DASAN CO., LTD. OUI:38D135* ID_OUI_FROM_DATABASE=EasyIO Corporation Sdn. Bhd. OUI:184E94* ID_OUI_FROM_DATABASE=MESSOA TECHNOLOGIES INC. OUI:A8922C* ID_OUI_FROM_DATABASE=LG Electronics OUI:94D93C* ID_OUI_FROM_DATABASE=ENELPS OUI:DC9B1E* ID_OUI_FROM_DATABASE=Intercom, Inc. OUI:5C7757* ID_OUI_FROM_DATABASE=Haivision Network Video OUI:3816D1* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E8B4AE* ID_OUI_FROM_DATABASE=Shenzhen C&D Electronics Co.,Ltd OUI:C45600* ID_OUI_FROM_DATABASE=Galleon Embedded Computing OUI:E42FF6* ID_OUI_FROM_DATABASE=Unicore communication Inc. OUI:B8F4D0* ID_OUI_FROM_DATABASE=Herrmann Ultraschalltechnik GmbH & Co. Kg OUI:B4F323* ID_OUI_FROM_DATABASE=PETATEL INC. OUI:C81E8E* ID_OUI_FROM_DATABASE=ADV Security (S) Pte Ltd OUI:ACCABA* ID_OUI_FROM_DATABASE=Midokura Co., Ltd. OUI:9C417C* ID_OUI_FROM_DATABASE=Hame Technology Co., Limited OUI:10768A* ID_OUI_FROM_DATABASE=EoCell OUI:044665* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:D0131E* ID_OUI_FROM_DATABASE=Sunrex Technology Corp OUI:380197* ID_OUI_FROM_DATABASE=TSST Global,Inc OUI:B40142* ID_OUI_FROM_DATABASE=GCI Science & Technology Co.,LTD OUI:846EB1* ID_OUI_FROM_DATABASE=Park Assist LLC OUI:6C504D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:C0C1C0* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:1CBD0E* ID_OUI_FROM_DATABASE=Amplified Engineering Pty Ltd OUI:F0A764* ID_OUI_FROM_DATABASE=GST Co., Ltd. OUI:A0F217* ID_OUI_FROM_DATABASE=GE Medical System(China) Co., Ltd. OUI:5067F0* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:643409* ID_OUI_FROM_DATABASE=BITwave Pte Ltd OUI:20D5AB* ID_OUI_FROM_DATABASE=Korea Infocom Co.,Ltd. OUI:F05849* ID_OUI_FROM_DATABASE=CareView Communications OUI:BC15A6* ID_OUI_FROM_DATABASE=Taiwan Jantek Electronics,Ltd. OUI:241A8C* ID_OUI_FROM_DATABASE=Squarehead Technology AS OUI:1083D2* ID_OUI_FROM_DATABASE=Microseven Systems, LLC OUI:F05D89* ID_OUI_FROM_DATABASE=Dycon Limited OUI:AC02CF* ID_OUI_FROM_DATABASE=RW Tecnologia Industria e Comercio Ltda OUI:9067B5* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:40987B* ID_OUI_FROM_DATABASE=Aisino Corporation OUI:6C2E33* ID_OUI_FROM_DATABASE=Accelink Technologies Co.,Ltd. OUI:4CEDDE* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:E8E08F* ID_OUI_FROM_DATABASE=GRAVOTECH MARKING SAS OUI:78B6C1* ID_OUI_FROM_DATABASE=AOBO Telecom Co.,Ltd OUI:B8BA68* ID_OUI_FROM_DATABASE=Xi'an Jizhong Digital Communication Co.,Ltd OUI:BC38D2* ID_OUI_FROM_DATABASE=Pandachip Limited OUI:A00BBA* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS OUI:14EE9D* ID_OUI_FROM_DATABASE=AirNav Systems LLC OUI:48174C* ID_OUI_FROM_DATABASE=MicroPower technologies OUI:78471D* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:F81037* ID_OUI_FROM_DATABASE=Atopia Systems, LP OUI:64F987* ID_OUI_FROM_DATABASE=Avvasi Inc. OUI:3C7437* ID_OUI_FROM_DATABASE=RIM OUI:04209A* ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company OUI:64DC01* ID_OUI_FROM_DATABASE=Static Systems Group PLC OUI:90A4DE* ID_OUI_FROM_DATABASE=Wistron Neweb Corp. OUI:1CF5E7* ID_OUI_FROM_DATABASE=Turtle Industry Co., Ltd. OUI:9C4A7B* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:2C8065* ID_OUI_FROM_DATABASE=HARTING Inc. of North America OUI:80C6AB* ID_OUI_FROM_DATABASE=Technicolor USA Inc. OUI:F8F014* ID_OUI_FROM_DATABASE=RackWare Inc. OUI:889FFA* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:E41C4B* ID_OUI_FROM_DATABASE=V2 TECHNOLOGY, INC. OUI:F0F002* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:E0143E* ID_OUI_FROM_DATABASE=Modoosis Inc. OUI:5C6984* ID_OUI_FROM_DATABASE=NUVICO OUI:204AAA* ID_OUI_FROM_DATABASE=Hanscan Spain S.A. OUI:F02572* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:8091C0* ID_OUI_FROM_DATABASE=AgileMesh, Inc. OUI:0CF0B4* ID_OUI_FROM_DATABASE=Globalsat International Technology Ltd OUI:BCC61A* ID_OUI_FROM_DATABASE=SPECTRA EMBEDDED SYSTEMS OUI:48DF1C* ID_OUI_FROM_DATABASE=Wuhan NEC Fibre Optic Communications industry Co. Ltd OUI:D0D3FC* ID_OUI_FROM_DATABASE=Mios, Ltd. OUI:989449* ID_OUI_FROM_DATABASE=Skyworth Wireless Technology Ltd. OUI:C8DF7C* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:F8C678* ID_OUI_FROM_DATABASE=Carefusion OUI:FC3598* ID_OUI_FROM_DATABASE=Favite Inc. OUI:A0AAFD* ID_OUI_FROM_DATABASE=EraThink Technologies Corp. OUI:801F02* ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. OUI:E03E7D* ID_OUI_FROM_DATABASE=data-complex GmbH OUI:A4E32E* ID_OUI_FROM_DATABASE=Silicon & Software Systems Ltd. OUI:1C19DE* ID_OUI_FROM_DATABASE=eyevis GmbH OUI:DC07C1* ID_OUI_FROM_DATABASE=HangZhou QiYang Technology Co.,Ltd. OUI:D8FE8F* ID_OUI_FROM_DATABASE=IDFone Co., Ltd. OUI:0006F6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:ACAB8D* ID_OUI_FROM_DATABASE=Lyngso Marine A/S OUI:181456* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:E8995A* ID_OUI_FROM_DATABASE=PiiGAB, Processinformation i Goteborg AB OUI:18F46A* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:D4E32C* ID_OUI_FROM_DATABASE=S. Siedle & Sohne OUI:68DCE8* ID_OUI_FROM_DATABASE=PacketStorm Communications OUI:78223D* ID_OUI_FROM_DATABASE=Affirmed Networks OUI:60C980* ID_OUI_FROM_DATABASE=Trymus OUI:94CDAC* ID_OUI_FROM_DATABASE=Creowave Oy OUI:F4DCDA* ID_OUI_FROM_DATABASE=Zhuhai Jiahe Communication Technology Co., limited OUI:100D32* ID_OUI_FROM_DATABASE=Embedian, Inc. OUI:D82986* ID_OUI_FROM_DATABASE=Best Wish Technology LTD OUI:C03B8F* ID_OUI_FROM_DATABASE=Minicom Digital Signage OUI:D48890* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:A4218A* ID_OUI_FROM_DATABASE=Nortel Networks OUI:6C0460* ID_OUI_FROM_DATABASE=RBH Access Technologies Inc. OUI:5C864A* ID_OUI_FROM_DATABASE=Secret Labs LLC OUI:B8BA72* ID_OUI_FROM_DATABASE=Cynove OUI:C00D7E* ID_OUI_FROM_DATABASE=Additech, Inc. OUI:68784C* ID_OUI_FROM_DATABASE=Nortel Networks OUI:6C626D* ID_OUI_FROM_DATABASE=Micro-Star INT'L CO., LTD OUI:8841C1* ID_OUI_FROM_DATABASE=ORBISAT DA AMAZONIA IND E AEROL SA OUI:18B209* ID_OUI_FROM_DATABASE=Torrey Pines Logic, Inc OUI:3018CF* ID_OUI_FROM_DATABASE=DEOS control systems GmbH OUI:4CF737* ID_OUI_FROM_DATABASE=SamJi Electronics Co., Ltd OUI:40406B* ID_OUI_FROM_DATABASE=Icomera OUI:1880CE* ID_OUI_FROM_DATABASE=Barberry Solutions Ltd OUI:CC43E3* ID_OUI_FROM_DATABASE=Trump s.a. OUI:6C22AB* ID_OUI_FROM_DATABASE=Ainsworth Game Technology OUI:3C106F* ID_OUI_FROM_DATABASE=ALBAHITH TECHNOLOGIES OUI:7CE044* ID_OUI_FROM_DATABASE=NEON Inc OUI:64D02D* ID_OUI_FROM_DATABASE=Next Generation Integration (NGI) OUI:A04041* ID_OUI_FROM_DATABASE=SAMWONFA Co.,Ltd. OUI:788C54* ID_OUI_FROM_DATABASE=Eltek Technologies LTD OUI:9411DA* ID_OUI_FROM_DATABASE=ITF Fröschl GmbH OUI:10E8EE* ID_OUI_FROM_DATABASE=PhaseSpace OUI:A47C1F* ID_OUI_FROM_DATABASE=Cobham plc OUI:8C1F94* ID_OUI_FROM_DATABASE=RF Surgical System Inc. OUI:74A4A7* ID_OUI_FROM_DATABASE=QRS Music Technologies, Inc. OUI:8039E5* ID_OUI_FROM_DATABASE=PATLITE CORPORATION OUI:BCFFAC* ID_OUI_FROM_DATABASE=TOPCON CORPORATION OUI:602A54* ID_OUI_FROM_DATABASE=CardioTek B.V. OUI:1C3DE7* ID_OUI_FROM_DATABASE=Sigma Koki Co.,Ltd. OUI:482CEA* ID_OUI_FROM_DATABASE=Motorola Inc Business Light Radios OUI:70E139* ID_OUI_FROM_DATABASE=3view Ltd OUI:AC6123* ID_OUI_FROM_DATABASE=Drivven, Inc. OUI:3C04BF* ID_OUI_FROM_DATABASE=PRAVIS SYSTEMS Co.Ltd., OUI:443D21* ID_OUI_FROM_DATABASE=Nuvolt OUI:749050* ID_OUI_FROM_DATABASE=Renesas Electronics Corporation OUI:7CBB6F* ID_OUI_FROM_DATABASE=Cosco Electronics Co., Ltd. OUI:D466A8* ID_OUI_FROM_DATABASE=Riedo Networks GmbH OUI:98E165* ID_OUI_FROM_DATABASE=Accutome OUI:EC66D1* ID_OUI_FROM_DATABASE=B&W Group LTD OUI:385FC3* ID_OUI_FROM_DATABASE=Yu Jeong System, Co.Ltd OUI:94857A* ID_OUI_FROM_DATABASE=Evantage Industries Corp OUI:4451DB* ID_OUI_FROM_DATABASE=Raytheon BBN Technologies OUI:64995D* ID_OUI_FROM_DATABASE=LGE OUI:585076* ID_OUI_FROM_DATABASE=Linear Equipamentos Eletronicos SA OUI:4083DE* ID_OUI_FROM_DATABASE=Zebra Technologies Inc OUI:8897DF* ID_OUI_FROM_DATABASE=Entrypass Corporation Sdn. Bhd. OUI:0C15C5* ID_OUI_FROM_DATABASE=SDTEC Co., Ltd. OUI:9803A0* ID_OUI_FROM_DATABASE=ABB n.v. Power Quality Products OUI:DCFAD5* ID_OUI_FROM_DATABASE=STRONG Ges.m.b.H. OUI:D84606* ID_OUI_FROM_DATABASE=Silicon Valley Global Marketing OUI:5CAC4C* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:689234* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:D0E347* ID_OUI_FROM_DATABASE=Yoga OUI:84A991* ID_OUI_FROM_DATABASE=Cyber Trans Japan Co.,Ltd. OUI:380DD4* ID_OUI_FROM_DATABASE=Primax Electronics LTD. OUI:D81C14* ID_OUI_FROM_DATABASE=Compacta International, Ltd. OUI:9088A2* ID_OUI_FROM_DATABASE=IONICS TECHNOLOGY ME LTDA OUI:B0B8D5* ID_OUI_FROM_DATABASE=Nanjing Nengrui Auto Equipment CO.,Ltd OUI:8497B8* ID_OUI_FROM_DATABASE=Memjet Inc. OUI:A8556A* ID_OUI_FROM_DATABASE=Pocketnet Technology Inc. OUI:B081D8* ID_OUI_FROM_DATABASE=I-sys Corp OUI:206AFF* ID_OUI_FROM_DATABASE=Atlas Elektronik UK Limited OUI:EC542E* ID_OUI_FROM_DATABASE=Shanghai XiMei Electronic Technology Co. Ltd OUI:B88E3A* ID_OUI_FROM_DATABASE=Infinite Technologies JLT OUI:74BE08* ID_OUI_FROM_DATABASE=ATEK Products, LLC OUI:E0EE1B* ID_OUI_FROM_DATABASE=Panasonic Automotive Systems Company of America OUI:E80C38* ID_OUI_FROM_DATABASE=DAEYOUNG INFORMATION SYSTEM CO., LTD OUI:68597F* ID_OUI_FROM_DATABASE=Alcatel Lucent OUI:2C3068* ID_OUI_FROM_DATABASE=Pantech Co.,Ltd OUI:5C4058* ID_OUI_FROM_DATABASE=Jefferson Audio Video Systems, Inc. OUI:64317E* ID_OUI_FROM_DATABASE=Dexin Corporation OUI:AC9B84* ID_OUI_FROM_DATABASE=Smak Tecnologia e Automacao OUI:4C022E* ID_OUI_FROM_DATABASE=CMR KOREA CO., LTD OUI:24A42C* ID_OUI_FROM_DATABASE=KOUKAAM a.s. OUI:34F39B* ID_OUI_FROM_DATABASE=WizLAN Ltd. OUI:74B9EB* ID_OUI_FROM_DATABASE=JinQianMao Technology Co.,Ltd. OUI:244597* ID_OUI_FROM_DATABASE=GEMUE Gebr. Mueller Apparatebau OUI:30694B* ID_OUI_FROM_DATABASE=RIM OUI:AC5135* ID_OUI_FROM_DATABASE=MPI TECH OUI:E4EC10* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:00D38D* ID_OUI_FROM_DATABASE=Hotel Technology Next Generation OUI:3C6278* ID_OUI_FROM_DATABASE=SHENZHEN JETNET TECHNOLOGY CO.,LTD. OUI:8081A5* ID_OUI_FROM_DATABASE=TONGQING COMMUNICATION EQUIPMENT (SHENZHEN) Co.,Ltd OUI:EC8EAD* ID_OUI_FROM_DATABASE=DLX OUI:ECDE3D* ID_OUI_FROM_DATABASE=Lamprey Networks, Inc. OUI:04FE7F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E8056D* ID_OUI_FROM_DATABASE=Nortel Networks OUI:00D11C* ID_OUI_FROM_DATABASE=ACETEL OUI:1056CA* ID_OUI_FROM_DATABASE=Peplink International Ltd. OUI:E83A97* ID_OUI_FROM_DATABASE=OCZ Technology Group OUI:44A689* ID_OUI_FROM_DATABASE=PROMAX ELECTRONICA SA OUI:10CCDB* ID_OUI_FROM_DATABASE=AXIMUM PRODUITS ELECTRONIQUES OUI:6C92BF* ID_OUI_FROM_DATABASE=Inspur Electronic Information Industry Co.,Ltd. OUI:E01CEE* ID_OUI_FROM_DATABASE=Bravo Tech, Inc. OUI:3C1915* ID_OUI_FROM_DATABASE=GFI Chrono Time OUI:EC5C69* ID_OUI_FROM_DATABASE=MITSUBISHI HEAVY INDUSTRIES MECHATRONICS SYSTEMS,LTD. OUI:04E548* ID_OUI_FROM_DATABASE=Cohda Wireless Pty Ltd OUI:0C1DC2* ID_OUI_FROM_DATABASE=SeAH Networks OUI:28CD4C* ID_OUI_FROM_DATABASE=Individual Computers GmbH OUI:8C53F7* ID_OUI_FROM_DATABASE=A&D ENGINEERING CO., LTD. OUI:781185* ID_OUI_FROM_DATABASE=NBS Payment Solutions Inc. OUI:2893FE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:10B7F6* ID_OUI_FROM_DATABASE=Plastoform Industries Ltd. OUI:2059A0* ID_OUI_FROM_DATABASE=Paragon Technologies Inc. OUI:487119* ID_OUI_FROM_DATABASE=SGB GROUP LTD. OUI:E0ABFE* ID_OUI_FROM_DATABASE=Orb Networks, Inc. OUI:CCEA1C* ID_OUI_FROM_DATABASE=DCONWORKS Co., Ltd OUI:ACE348* ID_OUI_FROM_DATABASE=MadgeTech, Inc OUI:687F74* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:CCB888* ID_OUI_FROM_DATABASE=AnB Securite s.a. OUI:CC2218* ID_OUI_FROM_DATABASE=InnoDigital Co., Ltd. OUI:B86491* ID_OUI_FROM_DATABASE=CK Telecom Ltd OUI:80C862* ID_OUI_FROM_DATABASE=Openpeak, Inc OUI:E43593* ID_OUI_FROM_DATABASE=Hangzhou GoTo technology Co.Ltd OUI:E0BC43* ID_OUI_FROM_DATABASE=C2 Microsystems, Inc. OUI:7884EE* ID_OUI_FROM_DATABASE=INDRA ESPACIO S.A. OUI:2C3F3E* ID_OUI_FROM_DATABASE=Alge-Timing GmbH OUI:ECE09B* ID_OUI_FROM_DATABASE=Samsung electronics CO., LTD OUI:C0CFA3* ID_OUI_FROM_DATABASE=Creative Electronics & Software, Inc. OUI:D4823E* ID_OUI_FROM_DATABASE=Argosy Technologies, Ltd. OUI:844823* ID_OUI_FROM_DATABASE=WOXTER TECHNOLOGY Co. Ltd OUI:D0F0DB* ID_OUI_FROM_DATABASE=Ericsson OUI:34C3AC* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:7C1476* ID_OUI_FROM_DATABASE=Damall Technologies SAS OUI:D05875* ID_OUI_FROM_DATABASE=Active Control Technology Inc. OUI:D81BFE* ID_OUI_FROM_DATABASE=TWINLINX CORPORATION OUI:D46CBF* ID_OUI_FROM_DATABASE=Goodrich ISR OUI:5C57C8* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:4CC602* ID_OUI_FROM_DATABASE=Radios, Inc. OUI:3C05AB* ID_OUI_FROM_DATABASE=Product Creation Studio OUI:3C39C3* ID_OUI_FROM_DATABASE=JW Electronics Co., Ltd. OUI:547FEE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:A4C2AB* ID_OUI_FROM_DATABASE=Hangzhou LEAD-IT Information & Technology Co.,Ltd OUI:48AA5D* ID_OUI_FROM_DATABASE=Store Electronic Systems OUI:1062C9* ID_OUI_FROM_DATABASE=Adatis GmbH & Co. KG OUI:D8AE90* ID_OUI_FROM_DATABASE=Itibia Technologies OUI:904716* ID_OUI_FROM_DATABASE=RORZE CORPORATION OUI:28E794* ID_OUI_FROM_DATABASE=Microtime Computer Inc. OUI:8894F9* ID_OUI_FROM_DATABASE=Gemicom Technology, Inc. OUI:0CA42A* ID_OUI_FROM_DATABASE=OB Telecom Electronic Technology Co., Ltd OUI:5850E6* ID_OUI_FROM_DATABASE=Best Buy Corporation OUI:AC9A96* ID_OUI_FROM_DATABASE=Lantiq Deutschland GmbH OUI:E86CDA* ID_OUI_FROM_DATABASE=Supercomputers and Neurocomputers Research Center OUI:24B6B8* ID_OUI_FROM_DATABASE=FRIEM SPA OUI:F86ECF* ID_OUI_FROM_DATABASE=Arcx Inc OUI:8C8401* ID_OUI_FROM_DATABASE=Private OUI:6C7039* ID_OUI_FROM_DATABASE=Novar GmbH OUI:C44619* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:A4561B* ID_OUI_FROM_DATABASE=MCOT Corporation OUI:80EE73* ID_OUI_FROM_DATABASE=Shuttle Inc. OUI:10C73F* ID_OUI_FROM_DATABASE=Midas Klark Teknik Ltd OUI:408A9A* ID_OUI_FROM_DATABASE=TITENG CO., Ltd. OUI:702B1D* ID_OUI_FROM_DATABASE=E-Domus International Limited OUI:F077D0* ID_OUI_FROM_DATABASE=Xcellen OUI:785C72* ID_OUI_FROM_DATABASE=Hioso Technology Co., Ltd. OUI:94236E* ID_OUI_FROM_DATABASE=Shenzhen Junlan Electronic Ltd OUI:88BA7F* ID_OUI_FROM_DATABASE=Qfiednet Co., Ltd. OUI:E02636* ID_OUI_FROM_DATABASE=Nortel Networks OUI:4456B7* ID_OUI_FROM_DATABASE=Spawn Labs, Inc OUI:0C6076* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:0CEEE6* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:A09805* ID_OUI_FROM_DATABASE=OpenVox Communication Co Ltd OUI:00271D* ID_OUI_FROM_DATABASE=Comba Telecom Systems (China) Ltd. OUI:002721* ID_OUI_FROM_DATABASE=Shenzhen Baoan Fenda Industrial Co., Ltd OUI:A09A5A* ID_OUI_FROM_DATABASE=Time Domain OUI:64A837* ID_OUI_FROM_DATABASE=Juni Korea Co., Ltd OUI:B4B5AF* ID_OUI_FROM_DATABASE=Minsung Electronics OUI:044FAA* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:44568D* ID_OUI_FROM_DATABASE=PNC Technologies Co., Ltd. OUI:ACD180* ID_OUI_FROM_DATABASE=Crexendo Business Solutions, Inc. OUI:AC8317* ID_OUI_FROM_DATABASE=Shenzhen Furtunetel Communication Co., Ltd OUI:E80B13* ID_OUI_FROM_DATABASE=Akib Systems Taiwan, INC OUI:44C9A2* ID_OUI_FROM_DATABASE=Greenwald Industries OUI:9CB206* ID_OUI_FROM_DATABASE=PROCENTEC OUI:44F459* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:646E6C* ID_OUI_FROM_DATABASE=Radio Datacom LLC OUI:E4751E* ID_OUI_FROM_DATABASE=Getinge Sterilization AB OUI:F8811A* ID_OUI_FROM_DATABASE=OVERKIZ OUI:042BBB* ID_OUI_FROM_DATABASE=PicoCELA, Inc. OUI:FC0877* ID_OUI_FROM_DATABASE=Prentke Romich Company OUI:ECD00E* ID_OUI_FROM_DATABASE=MiraeRecognition Co., Ltd. OUI:747E1A* ID_OUI_FROM_DATABASE=Red Embedded Design Limited OUI:C47D4F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:4C9EE4* ID_OUI_FROM_DATABASE=Hanyang Navicom Co.,Ltd. OUI:3CDF1E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:BCB181* ID_OUI_FROM_DATABASE=SHARP CORPORATION OUI:78B81A* ID_OUI_FROM_DATABASE=INTER SALES A/S OUI:78192E* ID_OUI_FROM_DATABASE=NASCENT Technology OUI:2C0623* ID_OUI_FROM_DATABASE=Win Leader Inc. OUI:C82E94* ID_OUI_FROM_DATABASE=Halfa Enterprise Co., Ltd. OUI:0C2755* ID_OUI_FROM_DATABASE=Valuable Techologies Limited OUI:C038F9* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:F46349* ID_OUI_FROM_DATABASE=Diffon Corporation OUI:5C8778* ID_OUI_FROM_DATABASE=Cybertelbridge co.,ltd OUI:9C5E73* ID_OUI_FROM_DATABASE=Calibre UK LTD OUI:F06281* ID_OUI_FROM_DATABASE=ProCurve Networking by HP OUI:003A9B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:2C9127* ID_OUI_FROM_DATABASE=Eintechno Corporation OUI:C09C92* ID_OUI_FROM_DATABASE=COBY OUI:849000* ID_OUI_FROM_DATABASE=Arnold & Richter Cine Technik OUI:C87248* ID_OUI_FROM_DATABASE=Aplicom Oy OUI:74D850* ID_OUI_FROM_DATABASE=Evrisko Systems OUI:6CAC60* ID_OUI_FROM_DATABASE=Venetex Corp OUI:DC0265* ID_OUI_FROM_DATABASE=Meditech Kft OUI:986DC8* ID_OUI_FROM_DATABASE=TOSHIBA MITSUBISHI-ELECTRIC INDUSTRIAL SYSTEMS CORPORATION OUI:68A1B7* ID_OUI_FROM_DATABASE=Honghao Mingchuan Technology (Beijing) CO.,Ltd. OUI:7CCFCF* ID_OUI_FROM_DATABASE=Shanghai SEARI Intelligent System Co., Ltd OUI:EC3091* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:3032D4* ID_OUI_FROM_DATABASE=Hanilstm Co., Ltd. OUI:0026EE* ID_OUI_FROM_DATABASE=TKM GmbH OUI:0026E7* ID_OUI_FROM_DATABASE=Shanghai ONLAN Communication Tech. Co., Ltd. OUI:0026E1* ID_OUI_FROM_DATABASE=Stanford University, OpenFlow Group OUI:0026DB* ID_OUI_FROM_DATABASE=Ionics EMS Inc. OUI:0026CE* ID_OUI_FROM_DATABASE=Kozumi USA Corp. OUI:0026D5* ID_OUI_FROM_DATABASE=Ory Solucoes em Comercio de Informatica Ltda. OUI:0026C8* ID_OUI_FROM_DATABASE=System Sensor OUI:002711* ID_OUI_FROM_DATABASE=LanPro Inc OUI:00270D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002707* ID_OUI_FROM_DATABASE=Lift Complex DS, JSC OUI:002700* ID_OUI_FROM_DATABASE=Shenzhen Siglent Technology Co., Ltd. OUI:0026FA* ID_OUI_FROM_DATABASE=BandRich Inc. OUI:0026F4* ID_OUI_FROM_DATABASE=Nesslab OUI:0025D7* ID_OUI_FROM_DATABASE=CEDO OUI:0025D2* ID_OUI_FROM_DATABASE=InpegVision Co., Ltd OUI:0025D1* ID_OUI_FROM_DATABASE=Eastern Asia Technology Limited OUI:0025CB* ID_OUI_FROM_DATABASE=Reiner SCT OUI:0025C4* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:0025BF* ID_OUI_FROM_DATABASE=Wireless Cables Inc. OUI:0025B1* ID_OUI_FROM_DATABASE=Maya-Creation Corporation OUI:0025B8* ID_OUI_FROM_DATABASE=Agile Communications, Inc. OUI:0025B2* ID_OUI_FROM_DATABASE=MBDA Deutschland GmbH OUI:0025AC* ID_OUI_FROM_DATABASE=I-Tech corporation OUI:0026C2* ID_OUI_FROM_DATABASE=SCDI Co. LTD OUI:0026BC* ID_OUI_FROM_DATABASE=General Jack Technology Ltd. OUI:0026B4* ID_OUI_FROM_DATABASE=Ford Motor Company OUI:0026AE* ID_OUI_FROM_DATABASE=Wireless Measurement Ltd OUI:0026AA* ID_OUI_FROM_DATABASE=Kenmec Mechanical Engineering Co., Ltd. OUI:0026A4* ID_OUI_FROM_DATABASE=Novus Produtos Eletronicos Ltda OUI:00269E* ID_OUI_FROM_DATABASE=Quanta Computer Inc OUI:002698* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00269D* ID_OUI_FROM_DATABASE=M2Mnet Co., Ltd. OUI:00268B* ID_OUI_FROM_DATABASE=Guangzhou Escene Computer Technology Limited OUI:002685* ID_OUI_FROM_DATABASE=Digital Innovation OUI:00267E* ID_OUI_FROM_DATABASE=Parrot SA OUI:002678* ID_OUI_FROM_DATABASE=Logic Instrument SA OUI:002672* ID_OUI_FROM_DATABASE=AAMP of America OUI:00266B* ID_OUI_FROM_DATABASE=SHINE UNION ENTERPRISE LIMITED OUI:002666* ID_OUI_FROM_DATABASE=EFM Networks OUI:002665* ID_OUI_FROM_DATABASE=ProtectedLogic Corporation OUI:00265F* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:002651* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002652* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002646* ID_OUI_FROM_DATABASE=SHENYANG TONGFANG MULTIMEDIA TECHNOLOGY COMPANY LIMITED OUI:002640* ID_OUI_FROM_DATABASE=Baustem Broadband Technologies, Ltd. OUI:00263A* ID_OUI_FROM_DATABASE=Digitec Systems OUI:002634* ID_OUI_FROM_DATABASE=Infineta Systems, Inc OUI:002633* ID_OUI_FROM_DATABASE=MIR - Medical International Research OUI:00262E* ID_OUI_FROM_DATABASE=Chengdu Jiuzhou Electronic Technology Inc OUI:002627* ID_OUI_FROM_DATABASE=Truesell OUI:002621* ID_OUI_FROM_DATABASE=InteliCloud Technology Inc. OUI:00261B* ID_OUI_FROM_DATABASE=LAUREL BANK MACHINES CO., LTD. OUI:002614* ID_OUI_FROM_DATABASE=KTNF OUI:00260E* ID_OUI_FROM_DATABASE=Ablaze Systems, LLC OUI:00260F* ID_OUI_FROM_DATABASE=Linn Products Ltd OUI:002602* ID_OUI_FROM_DATABASE=SMART Temps LLC OUI:002601* ID_OUI_FROM_DATABASE=Cutera Inc OUI:0025F7* ID_OUI_FROM_DATABASE=Ansaldo STS USA OUI:0025FC* ID_OUI_FROM_DATABASE=ENDA ENDUSTRIYEL ELEKTRONIK LTD. STI. OUI:0025ED* ID_OUI_FROM_DATABASE=NuVo Technologies LLC OUI:0025EE* ID_OUI_FROM_DATABASE=Avtex Ltd OUI:0025E8* ID_OUI_FROM_DATABASE=Idaho Technology OUI:0025E3* ID_OUI_FROM_DATABASE=Hanshinit Inc. OUI:0025DE* ID_OUI_FROM_DATABASE=Probits Co., LTD. OUI:002579* ID_OUI_FROM_DATABASE=J & F Labs OUI:00257E* ID_OUI_FROM_DATABASE=NEW POS Technology Limited OUI:002572* ID_OUI_FROM_DATABASE=Nemo-Q International AB OUI:002566* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:00256B* ID_OUI_FROM_DATABASE=ATENIX E.E. s.r.l. OUI:00256C* ID_OUI_FROM_DATABASE=Azimut Production Association JSC OUI:00255F* ID_OUI_FROM_DATABASE=SenTec AG OUI:00255A* ID_OUI_FROM_DATABASE=Tantalus Systems Corp. OUI:002559* ID_OUI_FROM_DATABASE=Syphan Technologies Ltd OUI:0025A5* ID_OUI_FROM_DATABASE=Walnut Media Network OUI:00259F* ID_OUI_FROM_DATABASE=TechnoDigital Technologies GmbH OUI:002599* ID_OUI_FROM_DATABASE=Hedon e.d. B.V. OUI:002592* ID_OUI_FROM_DATABASE=Guangzhou Shirui Electronic Co., Ltd OUI:00258D* ID_OUI_FROM_DATABASE=Haier OUI:002588* ID_OUI_FROM_DATABASE=Genie Industries, Inc. OUI:002583* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00254C* ID_OUI_FROM_DATABASE=Videon Central, Inc. OUI:002536* ID_OUI_FROM_DATABASE=Oki Electric Industry Co., Ltd. OUI:00253D* ID_OUI_FROM_DATABASE=DRS Consolidated Controls OUI:002540* ID_OUI_FROM_DATABASE=Quasar Technologies, Inc. OUI:002533* ID_OUI_FROM_DATABASE=WITTENSTEIN AG OUI:00252C* ID_OUI_FROM_DATABASE=Entourage Systems, Inc. OUI:002502* ID_OUI_FROM_DATABASE=NaturalPoint OUI:0024FB* ID_OUI_FROM_DATABASE=Private OUI:0024F6* ID_OUI_FROM_DATABASE=MIYOSHI ELECTRONICS CORPORATION OUI:0024EA* ID_OUI_FROM_DATABASE=iris-GmbH infrared & intelligent sensors OUI:0024E3* ID_OUI_FROM_DATABASE=CAO Group OUI:002527* ID_OUI_FROM_DATABASE=Bitrode Corp. OUI:002524* ID_OUI_FROM_DATABASE=Lightcomm Technology Co., Ltd OUI:00251F* ID_OUI_FROM_DATABASE=ZYNUS VISION INC. OUI:00251A* ID_OUI_FROM_DATABASE=Psiber Data Systems Inc. OUI:002515* ID_OUI_FROM_DATABASE=SFR OUI:00250E* ID_OUI_FROM_DATABASE=gt german telematics gmbh OUI:002507* ID_OUI_FROM_DATABASE=ASTAK Inc. OUI:002509* ID_OUI_FROM_DATABASE=SHARETRONIC Group LTD OUI:002437* ID_OUI_FROM_DATABASE=Motorola - BSG OUI:00243C* ID_OUI_FROM_DATABASE=S.A.A.A. OUI:002430* ID_OUI_FROM_DATABASE=Ruby Tech Corp. OUI:0023FB* ID_OUI_FROM_DATABASE=IP Datatel, LLC. OUI:0023F3* ID_OUI_FROM_DATABASE=Glocom, Inc. OUI:0023EF* ID_OUI_FROM_DATABASE=Zuend Systemtechnik AG OUI:0023E9* ID_OUI_FROM_DATABASE=F5 Networks, Inc. OUI:0023E3* ID_OUI_FROM_DATABASE=Microtronic AG OUI:0023E2* ID_OUI_FROM_DATABASE=SEA Signalisation OUI:0023DD* ID_OUI_FROM_DATABASE=ELGIN S.A. OUI:0023D0* ID_OUI_FROM_DATABASE=Uniloc USA Inc. OUI:0023CA* ID_OUI_FROM_DATABASE=Behind The Set, LLC OUI:0023D6* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,LTD OUI:0024B0* ID_OUI_FROM_DATABASE=ESAB AB OUI:0024A9* ID_OUI_FROM_DATABASE=Ag Leader Technology OUI:0024A2* ID_OUI_FROM_DATABASE=Hong Kong Middleware Technology Limited OUI:0024A4* ID_OUI_FROM_DATABASE=Siklu Communication OUI:00249D* ID_OUI_FROM_DATABASE=NES Technology Inc. OUI:00248A* ID_OUI_FROM_DATABASE=Kaga Electronics Co., Ltd. OUI:00248F* ID_OUI_FROM_DATABASE=DO-MONIX OUI:002491* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:002496* ID_OUI_FROM_DATABASE=Ginzinger electronic systems OUI:00247E* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd OUI:002483* ID_OUI_FROM_DATABASE=LG Electronics OUI:002477* ID_OUI_FROM_DATABASE=Tibbo Technology OUI:002470* ID_OUI_FROM_DATABASE=AUROTECH ultrasound AS. OUI:002472* ID_OUI_FROM_DATABASE=ReDriven Power Inc. OUI:00246B* ID_OUI_FROM_DATABASE=Covia, Inc. OUI:002464* ID_OUI_FROM_DATABASE=Bridge Technologies Co AS OUI:00245F* ID_OUI_FROM_DATABASE=Vine Telecom CO.,Ltd. OUI:002420* ID_OUI_FROM_DATABASE=NetUP Inc. OUI:002426* ID_OUI_FROM_DATABASE=NOHMI BOSAI LTD. OUI:00241A* ID_OUI_FROM_DATABASE=Red Beetle Inc. OUI:002413* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00240D* ID_OUI_FROM_DATABASE=OnePath Networks LTD. OUI:00240E* ID_OUI_FROM_DATABASE=Inventec Besta Co., Ltd. OUI:002407* ID_OUI_FROM_DATABASE=TELEM SAS OUI:002400* ID_OUI_FROM_DATABASE=Nortel Networks OUI:0024D0* ID_OUI_FROM_DATABASE=Shenzhen SOGOOD Industry CO.,LTD. OUI:0024D5* ID_OUI_FROM_DATABASE=Winward Industrial Limited OUI:0024C9* ID_OUI_FROM_DATABASE=Broadband Solutions Group OUI:0024C4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0024BF* ID_OUI_FROM_DATABASE=CIAT OUI:0024B5* ID_OUI_FROM_DATABASE=Nortel Networks OUI:00245A* ID_OUI_FROM_DATABASE=Nanjing Panda Electronics Company Limited OUI:002453* ID_OUI_FROM_DATABASE=Initra d.o.o. OUI:00244D* ID_OUI_FROM_DATABASE=Hokkaido Electronics Corporation OUI:002452* ID_OUI_FROM_DATABASE=Silicon Software GmbH OUI:002446* ID_OUI_FROM_DATABASE=MMB Research Inc. OUI:002441* ID_OUI_FROM_DATABASE=Wanzl Metallwarenfabrik GmbH OUI:002368* ID_OUI_FROM_DATABASE=Zebra Technologies Inc OUI:00236F* ID_OUI_FROM_DATABASE=DAQ System OUI:002362* ID_OUI_FROM_DATABASE=Goldline Controls OUI:002361* ID_OUI_FROM_DATABASE=Unigen Corporation OUI:00235C* ID_OUI_FROM_DATABASE=Aprius, Inc. OUI:002355* ID_OUI_FROM_DATABASE=Kinco Automation(Shanghai) Ltd. OUI:00234F* ID_OUI_FROM_DATABASE=Luminous Power Technologies Pvt. Ltd. OUI:002350* ID_OUI_FROM_DATABASE=LynTec OUI:002349* ID_OUI_FROM_DATABASE=Helmholtz Centre Berlin for Material and Energy OUI:002244* ID_OUI_FROM_DATABASE=Chengdu Linkon Communications Device Co., Ltd OUI:00224F* ID_OUI_FROM_DATABASE=Byzoro Networks Ltd. OUI:002248* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:00223E* ID_OUI_FROM_DATABASE=IRTrans GmbH OUI:002239* ID_OUI_FROM_DATABASE=Indiana Life Sciences Incorporated OUI:002232* ID_OUI_FROM_DATABASE=Design Design Technology Ltd OUI:00222C* ID_OUI_FROM_DATABASE=Ceton Corp OUI:00230E* ID_OUI_FROM_DATABASE=Gorba AG OUI:002307* ID_OUI_FROM_DATABASE=FUTURE INNOVATION TECH CO.,LTD OUI:002302* ID_OUI_FROM_DATABASE=Cobalt Digital, Inc. OUI:0022EB* ID_OUI_FROM_DATABASE=Data Respons A/S OUI:0022EC* ID_OUI_FROM_DATABASE=IDEALBT TECHNOLOGY CORPORATION OUI:0022F1* ID_OUI_FROM_DATABASE=Private OUI:00239E* ID_OUI_FROM_DATABASE=Jiangsu Lemote Technology Corporation Limited OUI:002398* ID_OUI_FROM_DATABASE=Vutlan sro OUI:00238A* ID_OUI_FROM_DATABASE=Ciena Corporation OUI:002384* ID_OUI_FROM_DATABASE=GGH Engineering s.r.l. OUI:002342* ID_OUI_FROM_DATABASE=Coffee Equipment Company OUI:002336* ID_OUI_FROM_DATABASE=METEL s.r.o. OUI:00233D* ID_OUI_FROM_DATABASE=Novero holding B.V. OUI:002330* ID_OUI_FROM_DATABASE=DIZIPIA, INC. OUI:00232C* ID_OUI_FROM_DATABASE=Senticare OUI:002320* ID_OUI_FROM_DATABASE=Nicira Networks OUI:00231D* ID_OUI_FROM_DATABASE=Deltacom Electronics Ltd OUI:00231E* ID_OUI_FROM_DATABASE=Cezzer Multimedia Technologies OUI:0022B8* ID_OUI_FROM_DATABASE=Norcott OUI:0022B7* ID_OUI_FROM_DATABASE=GSS Grundig SAT-Systems GmbH OUI:0022B2* ID_OUI_FROM_DATABASE=4RF Communications Ltd OUI:0022AB* ID_OUI_FROM_DATABASE=Shenzhen Turbosight Technology Ltd OUI:0022A6* ID_OUI_FROM_DATABASE=Sony Computer Entertainment America OUI:00229F* ID_OUI_FROM_DATABASE=Sensys Traffic AB OUI:0022E5* ID_OUI_FROM_DATABASE=Fisher-Rosemount Systems Inc. OUI:0022DE* ID_OUI_FROM_DATABASE=OPPO Digital, Inc. OUI:0022D9* ID_OUI_FROM_DATABASE=Fortex Industrial Ltd. OUI:0022D2* ID_OUI_FROM_DATABASE=All Earth Comércio de Eletrônicos LTDA. OUI:0022CC* ID_OUI_FROM_DATABASE=SciLog, Inc. OUI:0022C8* ID_OUI_FROM_DATABASE=Applied Instruments B.V. OUI:0022BE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00228C* ID_OUI_FROM_DATABASE=Photon Europe GmbH OUI:002286* ID_OUI_FROM_DATABASE=ASTRON OUI:002285* ID_OUI_FROM_DATABASE=NOMUS COMM SYSTEMS OUI:002280* ID_OUI_FROM_DATABASE=A2B Electronics AB OUI:002276* ID_OUI_FROM_DATABASE=Triple EYE B.V. OUI:00227B* ID_OUI_FROM_DATABASE=Apogee Labs, Inc. OUI:002262* ID_OUI_FROM_DATABASE=BEP Marine OUI:00226C* ID_OUI_FROM_DATABASE=LinkSprite Technologies, Inc. OUI:00225E* ID_OUI_FROM_DATABASE=Uwin Technologies Co.,LTD OUI:002258* ID_OUI_FROM_DATABASE=Taiyo Yuden Co., Ltd. OUI:0023C3* ID_OUI_FROM_DATABASE=LogMeIn, Inc. OUI:0023BD* ID_OUI_FROM_DATABASE=Digital Ally, Inc. OUI:0023B7* ID_OUI_FROM_DATABASE=Q-Light Co., Ltd. OUI:0023B1* ID_OUI_FROM_DATABASE=Longcheer Technology (Singapore) Pte Ltd OUI:0023B0* ID_OUI_FROM_DATABASE=COMXION Technology Inc. OUI:0023AB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0023A4* ID_OUI_FROM_DATABASE=New Concepts Development Corp. OUI:001FC0* ID_OUI_FROM_DATABASE=Control Express Finland Oy OUI:001FBB* ID_OUI_FROM_DATABASE=Xenatech Co.,LTD OUI:001FB4* ID_OUI_FROM_DATABASE=SmartShare Systems OUI:001FAD* ID_OUI_FROM_DATABASE=Brown Innovations, Inc OUI:001FAF* ID_OUI_FROM_DATABASE=NextIO, Inc. OUI:001FAE* ID_OUI_FROM_DATABASE=Blick South Africa (Pty) Ltd OUI:001FA8* ID_OUI_FROM_DATABASE=Smart Energy Instruments Inc. OUI:001FA3* ID_OUI_FROM_DATABASE=T&W Electronics(Shenzhen)Co.,Ltd. OUI:002142* ID_OUI_FROM_DATABASE=Advanced Control Systems doo OUI:002140* ID_OUI_FROM_DATABASE=EN Technologies Inc. OUI:002138* ID_OUI_FROM_DATABASE=Cepheid OUI:00212E* ID_OUI_FROM_DATABASE=dresden-elektronik OUI:002128* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:002122* ID_OUI_FROM_DATABASE=Chip-pro Ltd. OUI:00211B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002115* ID_OUI_FROM_DATABASE=PHYWE Systeme GmbH & Co. KG OUI:002116* ID_OUI_FROM_DATABASE=Transcon Electronic Systems, spol. s r. o. OUI:00210F* ID_OUI_FROM_DATABASE=Cernium Corp OUI:00210B* ID_OUI_FROM_DATABASE=GEMINI TRAZE RFID PVT. LTD. OUI:00210C* ID_OUI_FROM_DATABASE=Cymtec Systems, Inc. OUI:002105* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:001FFC* ID_OUI_FROM_DATABASE=Riccius+Sohn GmbH OUI:001FF7* ID_OUI_FROM_DATABASE=Nakajima All Precision Co., Ltd. OUI:00216E* ID_OUI_FROM_DATABASE=Function ATI (Huizhou) Telecommunications Co., Ltd. OUI:002168* ID_OUI_FROM_DATABASE=iVeia, LLC OUI:002161* ID_OUI_FROM_DATABASE=Yournet Inc. OUI:00215B* ID_OUI_FROM_DATABASE=Inotive OUI:002155* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00214E* ID_OUI_FROM_DATABASE=GS Yuasa Power Supply Ltd. OUI:002149* ID_OUI_FROM_DATABASE=China Daheng Group ,Inc. OUI:001FF0* ID_OUI_FROM_DATABASE=Audio Partnership OUI:001FE9* ID_OUI_FROM_DATABASE=Printrex, Inc. OUI:001FEB* ID_OUI_FROM_DATABASE=Trio Datacom Pty Ltd OUI:001FEA* ID_OUI_FROM_DATABASE=Applied Media Technologies Corporation OUI:001FDD* ID_OUI_FROM_DATABASE=GDI LLC OUI:001FD8* ID_OUI_FROM_DATABASE=A-TRUST COMPUTER CORPORATION OUI:001FD3* ID_OUI_FROM_DATABASE=RIVA Networks Inc. OUI:001FCE* ID_OUI_FROM_DATABASE=QTECH LLC OUI:00219D* ID_OUI_FROM_DATABASE=Adesys BV OUI:0021A1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002198* ID_OUI_FROM_DATABASE=Thai Radio Co, LTD OUI:002193* ID_OUI_FROM_DATABASE=Videofon MV OUI:00218D* ID_OUI_FROM_DATABASE=AP Router Ind. Eletronica LTDA OUI:00218E* ID_OUI_FROM_DATABASE=MEKICS CO., LTD. OUI:002187* ID_OUI_FROM_DATABASE=Imacs GmbH OUI:002181* ID_OUI_FROM_DATABASE=Si2 Microsystems Limited OUI:00217B* ID_OUI_FROM_DATABASE=Bastec AB OUI:002174* ID_OUI_FROM_DATABASE=AvaLAN Wireless OUI:0021F8* ID_OUI_FROM_DATABASE=Enseo, Inc. OUI:0021F3* ID_OUI_FROM_DATABASE=Si14 SpA OUI:0021EC* ID_OUI_FROM_DATABASE=Solutronic GmbH OUI:0021E6* ID_OUI_FROM_DATABASE=Starlight Video Limited OUI:0021E0* ID_OUI_FROM_DATABASE=CommAgility Ltd OUI:0021D3* ID_OUI_FROM_DATABASE=BOCOM SECURITY(ASIA PACIFIC) LIMITED OUI:0021D4* ID_OUI_FROM_DATABASE=Vollmer Werke GmbH OUI:0021D9* ID_OUI_FROM_DATABASE=SEKONIC CORPORATION OUI:0021CD* ID_OUI_FROM_DATABASE=LiveTV OUI:0021C7* ID_OUI_FROM_DATABASE=Russound OUI:0021C6* ID_OUI_FROM_DATABASE=CSJ Global, Inc. OUI:0021C1* ID_OUI_FROM_DATABASE=ABB Oy / Medium Voltage Products OUI:0021B4* ID_OUI_FROM_DATABASE=APRO MEDIA CO., LTD OUI:0021AE* ID_OUI_FROM_DATABASE=ALCATEL-LUCENT FRANCE - WTD OUI:0021A2* ID_OUI_FROM_DATABASE=EKE-Electronics Ltd. OUI:0021A7* ID_OUI_FROM_DATABASE=Hantle System Co., Ltd. OUI:00221F* ID_OUI_FROM_DATABASE=eSang Technologies Co., Ltd. OUI:002226* ID_OUI_FROM_DATABASE=Avaak, Inc. OUI:00221A* ID_OUI_FROM_DATABASE=Audio Precision OUI:002213* ID_OUI_FROM_DATABASE=PCI CORPORATION OUI:00220D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00220C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002207* ID_OUI_FROM_DATABASE=Inteno Broadband Technology AB OUI:002202* ID_OUI_FROM_DATABASE=Excito Elektronik i Skåne AB OUI:0021F9* ID_OUI_FROM_DATABASE=WIRECOM Technologies OUI:001F46* ID_OUI_FROM_DATABASE=Nortel OUI:001F40* ID_OUI_FROM_DATABASE=Speakercraft Inc. OUI:001F38* ID_OUI_FROM_DATABASE=POSITRON OUI:001F3D* ID_OUI_FROM_DATABASE=Qbit GmbH OUI:001F37* ID_OUI_FROM_DATABASE=Genesis I&C OUI:001F2A* ID_OUI_FROM_DATABASE=ACCM OUI:001F31* ID_OUI_FROM_DATABASE=Radiocomp OUI:001F25* ID_OUI_FROM_DATABASE=MBS GmbH OUI:001F1E* ID_OUI_FROM_DATABASE=Astec Technology Co., Ltd OUI:001F17* ID_OUI_FROM_DATABASE=IDX Company, Ltd. OUI:001F18* ID_OUI_FROM_DATABASE=Hakusan.Mfg.Co,.Ltd OUI:001E61* ID_OUI_FROM_DATABASE=ITEC GmbH OUI:001E5C* ID_OUI_FROM_DATABASE=RB GeneralEkonomik OUI:001E5B* ID_OUI_FROM_DATABASE=Unitron Company, Inc. OUI:001E55* ID_OUI_FROM_DATABASE=COWON SYSTEMS,Inc. OUI:001E4E* ID_OUI_FROM_DATABASE=DAKO EDV-Ingenieur- und Systemhaus GmbH OUI:001E49* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001E44* ID_OUI_FROM_DATABASE=SANTEC OUI:001E3F* ID_OUI_FROM_DATABASE=TrellisWare Technologies, Inc. OUI:001E38* ID_OUI_FROM_DATABASE=Bluecard Software Technology Co., Ltd. OUI:001E31* ID_OUI_FROM_DATABASE=INFOMARK CO.,LTD. OUI:001E32* ID_OUI_FROM_DATABASE=Zensys OUI:001E2C* ID_OUI_FROM_DATABASE=CyVerse Corporation OUI:001E20* ID_OUI_FROM_DATABASE=Intertain Inc. OUI:001E19* ID_OUI_FROM_DATABASE=GTRI OUI:001E1F* ID_OUI_FROM_DATABASE=Nortel OUI:001E0F* ID_OUI_FROM_DATABASE=Briot International OUI:001EE4* ID_OUI_FROM_DATABASE=ACS Solutions France OUI:001EEB* ID_OUI_FROM_DATABASE=Talk-A-Phone Co. OUI:001EDF* ID_OUI_FROM_DATABASE=Master Industrialization Center Kista OUI:001EDA* ID_OUI_FROM_DATABASE=Wesemann Elektrotechniek B.V. OUI:001ED5* ID_OUI_FROM_DATABASE=Tekon-Automatics OUI:001ECE* ID_OUI_FROM_DATABASE=BISA Technologies (Hong Kong) Limited OUI:001EC8* ID_OUI_FROM_DATABASE=Rapid Mobile (Pty) Ltd OUI:001EBB* ID_OUI_FROM_DATABASE=BLUELIGHT TECHNOLOGY INC. OUI:001EB6* ID_OUI_FROM_DATABASE=TAG Heuer SA OUI:001EB5* ID_OUI_FROM_DATABASE=Ever Sparkle Technologies Ltd OUI:001EAF* ID_OUI_FROM_DATABASE=Ophir Optronics Ltd OUI:001EAA* ID_OUI_FROM_DATABASE=E-Senza Technologies GmbH OUI:001E9D* ID_OUI_FROM_DATABASE=Recall Technologies, Inc. OUI:001E98* ID_OUI_FROM_DATABASE=GreenLine Communications OUI:001E97* ID_OUI_FROM_DATABASE=Medium Link System Technology CO., LTD, OUI:001E91* ID_OUI_FROM_DATABASE=KIMIN Electronic Co., Ltd. OUI:001E8A* ID_OUI_FROM_DATABASE=eCopy, Inc OUI:001E85* ID_OUI_FROM_DATABASE=Lagotek Corporation OUI:001E7E* ID_OUI_FROM_DATABASE=Nortel OUI:001E78* ID_OUI_FROM_DATABASE=Owitek Technology Ltd., OUI:001E6D* ID_OUI_FROM_DATABASE=IT R&D Center OUI:001E6E* ID_OUI_FROM_DATABASE=Shenzhen First Mile Communications Ltd OUI:001E68* ID_OUI_FROM_DATABASE=Quanta Computer OUI:001F71* ID_OUI_FROM_DATABASE=xG Technology, Inc. OUI:001F72* ID_OUI_FROM_DATABASE=QingDao Hiphone Technology Co,.Ltd OUI:001F76* ID_OUI_FROM_DATABASE=AirLogic Systems Inc. OUI:001F6C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001F60* ID_OUI_FROM_DATABASE=COMPASS SYSTEMS CORP. OUI:001F65* ID_OUI_FROM_DATABASE=KOREA ELECTRIC TERMINAL CO., LTD. OUI:001F5F* ID_OUI_FROM_DATABASE=Blatand GmbH OUI:001F59* ID_OUI_FROM_DATABASE=Kronback Tracers OUI:001F4D* ID_OUI_FROM_DATABASE=Segnetics LLC OUI:001F52* ID_OUI_FROM_DATABASE=UVT Unternehmensberatung fur Verkehr und Technik GmbH OUI:001F0A* ID_OUI_FROM_DATABASE=Nortel OUI:001F03* ID_OUI_FROM_DATABASE=NUM AG OUI:001EFE* ID_OUI_FROM_DATABASE=LEVEL s.r.o. OUI:001F04* ID_OUI_FROM_DATABASE=Granch Ltd. OUI:001EF2* ID_OUI_FROM_DATABASE=Micro Motion Inc OUI:001EF7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001EF1* ID_OUI_FROM_DATABASE=Servimat OUI:001F9E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001F92* ID_OUI_FROM_DATABASE=VideoIQ, Inc. OUI:001F97* ID_OUI_FROM_DATABASE=BERTANA srl OUI:001F8B* ID_OUI_FROM_DATABASE=Cache IQ OUI:001F84* ID_OUI_FROM_DATABASE=Gigle Semiconductor OUI:001F7F* ID_OUI_FROM_DATABASE=Phabrix Limited OUI:001CFF* ID_OUI_FROM_DATABASE=Napera Networks Inc OUI:001CF8* ID_OUI_FROM_DATABASE=Parade Technologies, Ltd. OUI:001CF1* ID_OUI_FROM_DATABASE=SUPoX Technology Co. , LTD. OUI:001CF2* ID_OUI_FROM_DATABASE=Tenlon Technology Co.,Ltd. OUI:001CEC* ID_OUI_FROM_DATABASE=Mobilesoft (Aust.) Pty Ltd OUI:001CE7* ID_OUI_FROM_DATABASE=Rocon PLC Research Centre OUI:001CE2* ID_OUI_FROM_DATABASE=Attero Tech, LLC. OUI:001CDB* ID_OUI_FROM_DATABASE=CARPOINT CO.,LTD OUI:001CD5* ID_OUI_FROM_DATABASE=ZeeVee, Inc. OUI:001CCF* ID_OUI_FROM_DATABASE=LIMETEK OUI:001E08* ID_OUI_FROM_DATABASE=Centec Networks Inc OUI:001E03* ID_OUI_FROM_DATABASE=LiComm Co., Ltd. OUI:001DFC* ID_OUI_FROM_DATABASE=KSIC OUI:001DF5* ID_OUI_FROM_DATABASE=Sunshine Co,LTD OUI:001DF6* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:001DF0* ID_OUI_FROM_DATABASE=Vidient Systems, Inc. OUI:001DDC* ID_OUI_FROM_DATABASE=HangZhou DeChangLong Tech&Info Co.,Ltd OUI:001DE4* ID_OUI_FROM_DATABASE=Visioneered Image Systems OUI:001DE2* ID_OUI_FROM_DATABASE=Radionor Communications OUI:001CC8* ID_OUI_FROM_DATABASE=INDUSTRONIC Industrie-Electronic GmbH & Co. KG OUI:001CBC* ID_OUI_FROM_DATABASE=CastGrabber, LLC OUI:001CB2* ID_OUI_FROM_DATABASE=BPT SPA OUI:001CA6* ID_OUI_FROM_DATABASE=Win4NET OUI:001CAB* ID_OUI_FROM_DATABASE=Meyer Sound Laboratories, Inc. OUI:001CAC* ID_OUI_FROM_DATABASE=Qniq Technology Corp. OUI:001CA1* ID_OUI_FROM_DATABASE=AKAMAI TECHNOLOGIES, INC. OUI:001C9C* ID_OUI_FROM_DATABASE=Nortel OUI:001C95* ID_OUI_FROM_DATABASE=Opticomm Corporation OUI:001C90* ID_OUI_FROM_DATABASE=Empacket Corporation OUI:001C8F* ID_OUI_FROM_DATABASE=Advanced Electronic Design, Inc. OUI:001C89* ID_OUI_FROM_DATABASE=Force Communications, Inc. OUI:001C7F* ID_OUI_FROM_DATABASE=Check Point Software Technologies OUI:001C75* ID_OUI_FROM_DATABASE=Segnet Ltd. OUI:001C6E* ID_OUI_FROM_DATABASE=Newbury Networks, Inc. OUI:001C69* ID_OUI_FROM_DATABASE=Packet Vision Ltd OUI:001C62* ID_OUI_FROM_DATABASE=LG Electronics Inc OUI:001DA5* ID_OUI_FROM_DATABASE=WB Electronics OUI:001DA6* ID_OUI_FROM_DATABASE=Media Numerics Limited OUI:001DA0* ID_OUI_FROM_DATABASE=Heng Yu Electronic Manufacturing Company Limited OUI:001D99* ID_OUI_FROM_DATABASE=Cyan Optic, Inc. OUI:001D94* ID_OUI_FROM_DATABASE=Climax Technology Co., Ltd OUI:001D93* ID_OUI_FROM_DATABASE=Modacom OUI:001D8D* ID_OUI_FROM_DATABASE=Raytek GmbH OUI:001D86* ID_OUI_FROM_DATABASE=Shinwa Industries(China) Ltd. OUI:001DC9* ID_OUI_FROM_DATABASE=GainSpan Corp. OUI:001DC2* ID_OUI_FROM_DATABASE=XORTEC OY OUI:001DBD* ID_OUI_FROM_DATABASE=Versamed Inc. OUI:001DB6* ID_OUI_FROM_DATABASE=BestComm Networks, Inc. OUI:001DB0* ID_OUI_FROM_DATABASE=FuJian HengTong Information Technology Co.,Ltd OUI:001DAC* ID_OUI_FROM_DATABASE=Gigamon Systems LLC OUI:001D81* ID_OUI_FROM_DATABASE=GUANGZHOU GATEWAY ELECTRONICS CO., LTD OUI:001D69* ID_OUI_FROM_DATABASE=Knorr-Bremse IT-Services GmbH OUI:001D70* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001D77* ID_OUI_FROM_DATABASE=NSGate OUI:001D7C* ID_OUI_FROM_DATABASE=ABE Elettronica S.p.A. OUI:001D64* ID_OUI_FROM_DATABASE=Adam Communications Systems Int Ltd OUI:001D5D* ID_OUI_FROM_DATABASE=Control Dynamics Pty. Ltd. OUI:001D2E* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:001D21* ID_OUI_FROM_DATABASE=Alcad SL OUI:001D1C* ID_OUI_FROM_DATABASE=Gennet s.a. OUI:001D17* ID_OUI_FROM_DATABASE=Digital Sky Corporation OUI:001D12* ID_OUI_FROM_DATABASE=ROHM CO., LTD. OUI:001D11* ID_OUI_FROM_DATABASE=Analogue & Micro Ltd OUI:001D0B* ID_OUI_FROM_DATABASE=Power Standards Lab OUI:001D04* ID_OUI_FROM_DATABASE=Zipit Wireless, Inc. OUI:001D58* ID_OUI_FROM_DATABASE=CQ Inc OUI:001D57* ID_OUI_FROM_DATABASE=CAETEC Messtechnik OUI:001D51* ID_OUI_FROM_DATABASE=Babcock & Wilcox Power Generation Group, Inc OUI:001D47* ID_OUI_FROM_DATABASE=Covote GmbH & Co KG OUI:001D40* ID_OUI_FROM_DATABASE=Intel – GE Care Innovations LLC OUI:001D34* ID_OUI_FROM_DATABASE=SYRIS Technology Corp OUI:001D2D* ID_OUI_FROM_DATABASE=Pylone, Inc. OUI:001B2A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001B1D* ID_OUI_FROM_DATABASE=Phoenix International Co., Ltd OUI:001B22* ID_OUI_FROM_DATABASE=Palit Microsystems ( H.K.) Ltd. OUI:001B1B* ID_OUI_FROM_DATABASE=Siemens AG, OUI:001B16* ID_OUI_FROM_DATABASE=Celtro Ltd. OUI:001B0A* ID_OUI_FROM_DATABASE=Intelligent Distributed Controls Ltd OUI:001B0F* ID_OUI_FROM_DATABASE=Petratec OUI:001AFE* ID_OUI_FROM_DATABASE=SOFACREAL OUI:001B03* ID_OUI_FROM_DATABASE=Action Technology (SZ) Co., Ltd OUI:001B68* ID_OUI_FROM_DATABASE=Modnnet Co., Ltd OUI:001B62* ID_OUI_FROM_DATABASE=JHT Optoelectronics Co.,Ltd. OUI:001B61* ID_OUI_FROM_DATABASE=Digital Acoustics, LLC OUI:001B5C* ID_OUI_FROM_DATABASE=Azuretec Co., Ltd. OUI:001B55* ID_OUI_FROM_DATABASE=Hurco Automation Ltd. OUI:001B50* ID_OUI_FROM_DATABASE=Nizhny Novgorod Factory named after M.Frunze, FSUE (NZiF) OUI:001B44* ID_OUI_FROM_DATABASE=SanDisk Corporation OUI:001B49* ID_OUI_FROM_DATABASE=Roberts Radio limited OUI:001B42* ID_OUI_FROM_DATABASE=Wise & Blue OUI:001B3D* ID_OUI_FROM_DATABASE=EuroTel Spa OUI:001B36* ID_OUI_FROM_DATABASE=Tsubata Engineering Co.,Ltd. (Head Office) OUI:001B31* ID_OUI_FROM_DATABASE=Neural Image. Co. Ltd. OUI:001C56* ID_OUI_FROM_DATABASE=Pado Systems, Inc. OUI:001C5B* ID_OUI_FROM_DATABASE=Chubb Electronic Security Systems Ltd OUI:001C5D* ID_OUI_FROM_DATABASE=Leica Microsystems OUI:001C5C* ID_OUI_FROM_DATABASE=Integrated Medical Systems, Inc. OUI:001C51* ID_OUI_FROM_DATABASE=Celeno Communications OUI:001C52* ID_OUI_FROM_DATABASE=VISIONEE SRL OUI:001C45* ID_OUI_FROM_DATABASE=Chenbro Micom Co., Ltd. OUI:001C4C* ID_OUI_FROM_DATABASE=Petrotest Instruments OUI:001C39* ID_OUI_FROM_DATABASE=S Netsystems Inc. OUI:001C40* ID_OUI_FROM_DATABASE=VDG-Security bv OUI:001C32* ID_OUI_FROM_DATABASE=Telian Corporation OUI:001AC7* ID_OUI_FROM_DATABASE=UNIPOINT OUI:001AC2* ID_OUI_FROM_DATABASE=YEC Co.,Ltd. OUI:001AB8* ID_OUI_FROM_DATABASE=Anseri Corporation OUI:001ABD* ID_OUI_FROM_DATABASE=Impatica Inc. OUI:001AB1* ID_OUI_FROM_DATABASE=Asia Pacific Satellite Industries Co., Ltd. OUI:001B8C* ID_OUI_FROM_DATABASE=JMicron Technology Corp. OUI:001B91* ID_OUI_FROM_DATABASE=EFKON AG OUI:001B87* ID_OUI_FROM_DATABASE=Deepsound Tech. Co., Ltd OUI:001B82* ID_OUI_FROM_DATABASE=Taiwan Semiconductor Co., Ltd. OUI:001B7B* ID_OUI_FROM_DATABASE=The Tintometer Ltd OUI:001B74* ID_OUI_FROM_DATABASE=MiraLink Corporation OUI:001B6F* ID_OUI_FROM_DATABASE=Teletrak Ltd OUI:001AFC* ID_OUI_FROM_DATABASE=ModusLink Corporation OUI:001AF2* ID_OUI_FROM_DATABASE=Dynavisions Schweiz AG OUI:001AF7* ID_OUI_FROM_DATABASE=dataschalt e+a GmbH OUI:001AED* ID_OUI_FROM_DATABASE=INCOTEC GmbH OUI:001ADF* ID_OUI_FROM_DATABASE=Interactivetv Pty Limited OUI:001AE1* ID_OUI_FROM_DATABASE=EDGE ACCESS INC OUI:001AE6* ID_OUI_FROM_DATABASE=Atlanta Advanced Communications Holdings Limited OUI:001AD3* ID_OUI_FROM_DATABASE=Vamp Ltd. OUI:001ADA* ID_OUI_FROM_DATABASE=Biz-2-Me Inc. OUI:001ACE* ID_OUI_FROM_DATABASE=YUPITERU CORPORATION OUI:001BC8* ID_OUI_FROM_DATABASE=MIURA CO.,LTD OUI:001BC1* ID_OUI_FROM_DATABASE=HOLUX Technology, Inc. OUI:001BB7* ID_OUI_FROM_DATABASE=Alta Heights Technology Corp. OUI:001BAB* ID_OUI_FROM_DATABASE=Telchemy, Incorporated OUI:001BB0* ID_OUI_FROM_DATABASE=BHARAT ELECTRONICS OUI:001BA4* ID_OUI_FROM_DATABASE=S.A.E Afikim OUI:001B9F* ID_OUI_FROM_DATABASE=Calyptech Pty Ltd OUI:001B98* ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. OUI:001B9D* ID_OUI_FROM_DATABASE=Novus Security Sp. z o.o. OUI:001BF6* ID_OUI_FROM_DATABASE=CONWISE Technology Corporation Ltd. OUI:001BF1* ID_OUI_FROM_DATABASE=Nanjing SilverNet Software Co., Ltd. OUI:001BEC* ID_OUI_FROM_DATABASE=Netio Technologies Co., Ltd OUI:001BE7* ID_OUI_FROM_DATABASE=Postek Electronics Co., Ltd. OUI:001BE0* ID_OUI_FROM_DATABASE=TELENOT ELECTRONIC GmbH OUI:001BD9* ID_OUI_FROM_DATABASE=Edgewater Computer Systems OUI:001BDB* ID_OUI_FROM_DATABASE=Valeo VECS OUI:001BDA* ID_OUI_FROM_DATABASE=UTStarcom Inc OUI:001BD4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001BCD* ID_OUI_FROM_DATABASE=DAVISCOMMS (S) PTE LTD OUI:001C2D* ID_OUI_FROM_DATABASE=FlexRadio Systems OUI:001C1C* ID_OUI_FROM_DATABASE=Center Communication Systems GmbH OUI:001C21* ID_OUI_FROM_DATABASE=Nucsafe Inc. OUI:001C20* ID_OUI_FROM_DATABASE=CLB Benelux OUI:001C17* ID_OUI_FROM_DATABASE=Nortel OUI:001C15* ID_OUI_FROM_DATABASE=iPhotonix LLC OUI:001C16* ID_OUI_FROM_DATABASE=ThyssenKrupp Elevator OUI:001C10* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:001C09* ID_OUI_FROM_DATABASE=SAE Electronic Co.,Ltd. OUI:001C04* ID_OUI_FROM_DATABASE=Airgain, Inc. OUI:001BFD* ID_OUI_FROM_DATABASE=Dignsys Inc. OUI:00192B* ID_OUI_FROM_DATABASE=Aclara RF Systems Inc. OUI:001930* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00191F* ID_OUI_FROM_DATABASE=Microlink communications Inc. OUI:001924* ID_OUI_FROM_DATABASE=LBNL Engineering OUI:001911* ID_OUI_FROM_DATABASE=Just In Mobile Information Technologies (Shanghai) Co., Ltd. OUI:001918* ID_OUI_FROM_DATABASE=Interactive Wear AG OUI:00190C* ID_OUI_FROM_DATABASE=Encore Electronics, Inc. OUI:001900* ID_OUI_FROM_DATABASE=Intelliverese - DBA Voicecom OUI:001905* ID_OUI_FROM_DATABASE=SCHRACK Seconet AG OUI:0018F4* ID_OUI_FROM_DATABASE=EO TECHNICS Co., Ltd. OUI:0018F6* ID_OUI_FROM_DATABASE=Thomson Telecom Belgium OUI:0018FB* ID_OUI_FROM_DATABASE=Compro Technology OUI:0019EE* ID_OUI_FROM_DATABASE=CARLO GAVAZZI CONTROLS SPA-Controls Division OUI:0019F0* ID_OUI_FROM_DATABASE=UNIONMAN TECHNOLOGY CO.,LTD OUI:0019F5* ID_OUI_FROM_DATABASE=Imagination Technologies Ltd OUI:0019E9* ID_OUI_FROM_DATABASE=S-Information Technolgy, Co., Ltd. OUI:0019DB* ID_OUI_FROM_DATABASE=MICRO-STAR INTERNATIONAL CO., LTD. OUI:0019DD* ID_OUI_FROM_DATABASE=FEI-Zyfer, Inc. OUI:0019CA* ID_OUI_FROM_DATABASE=Broadata Communications, Inc OUI:0019CF* ID_OUI_FROM_DATABASE=SALICRU, S.A. OUI:0019D6* ID_OUI_FROM_DATABASE=LS Cable and System Ltd. OUI:0019B4* ID_OUI_FROM_DATABASE=Intellio Ltd OUI:001A6E* ID_OUI_FROM_DATABASE=Impro Technologies OUI:001A67* ID_OUI_FROM_DATABASE=Infinite QL Sdn Bhd OUI:001A69* ID_OUI_FROM_DATABASE=Wuhan Yangtze Optical Technology CO.,Ltd. OUI:001A62* ID_OUI_FROM_DATABASE=Data Robotics, Incorporated OUI:001A58* ID_OUI_FROM_DATABASE=CCV Deutschland GmbH - Celectronic eHealth Div. OUI:001A5D* ID_OUI_FROM_DATABASE=Mobinnova Corp. OUI:001A4C* ID_OUI_FROM_DATABASE=Crossbow Technology, Inc OUI:001A51* ID_OUI_FROM_DATABASE=Alfred Mann Foundation OUI:001AAA* ID_OUI_FROM_DATABASE=Analogic Corp. OUI:001AA1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001A9C* ID_OUI_FROM_DATABASE=RightHand Technologies, Inc. OUI:001A8B* ID_OUI_FROM_DATABASE=CHUNIL ELECTRIC IND., CO. OUI:001A95* ID_OUI_FROM_DATABASE=Hisense Mobile Communications Technoligy Co.,Ltd. OUI:001A84* ID_OUI_FROM_DATABASE=V One Multimedia Pte Ltd OUI:0019A1* ID_OUI_FROM_DATABASE=LG INFORMATION & COMM. OUI:0019AD* ID_OUI_FROM_DATABASE=BOBST SA OUI:0019B2* ID_OUI_FROM_DATABASE=XYnetsoft Co.,Ltd OUI:00199A* ID_OUI_FROM_DATABASE=EDO-EVI OUI:00199F* ID_OUI_FROM_DATABASE=DKT A/S OUI:001995* ID_OUI_FROM_DATABASE=Jurong Hi-Tech (Suzhou)Co.ltd OUI:001990* ID_OUI_FROM_DATABASE=ELM DATA Co., Ltd. OUI:001989* ID_OUI_FROM_DATABASE=Sonitrol Corporation OUI:001A3E* ID_OUI_FROM_DATABASE=Faster Technology LLC OUI:001A40* ID_OUI_FROM_DATABASE=A-FOUR TECH CO., LTD. OUI:001A2D* ID_OUI_FROM_DATABASE=The Navvo Group OUI:001A32* ID_OUI_FROM_DATABASE=ACTIVA MULTIMEDIA OUI:001A39* ID_OUI_FROM_DATABASE=Merten GmbH&CoKG OUI:001A28* ID_OUI_FROM_DATABASE=ASWT Co., LTD. Taiwan Branch H.K. OUI:001A1C* ID_OUI_FROM_DATABASE=GT&T Engineering Pte Ltd OUI:001A21* ID_OUI_FROM_DATABASE=Indac B.V. OUI:001A23* ID_OUI_FROM_DATABASE=Ice Qube, Inc OUI:001A15* ID_OUI_FROM_DATABASE=gemalto e-Payment OUI:001A10* ID_OUI_FROM_DATABASE=LUCENT TRANS ELECTRONICS CO.,LTD OUI:001A09* ID_OUI_FROM_DATABASE=Wayfarer Transit Systems Ltd OUI:001A02* ID_OUI_FROM_DATABASE=SECURE CARE PRODUCTS, INC OUI:001A04* ID_OUI_FROM_DATABASE=Interay Solutions BV OUI:001984* ID_OUI_FROM_DATABASE=ESTIC Corporation OUI:001976* ID_OUI_FROM_DATABASE=Xipher Technologies, LLC OUI:001978* ID_OUI_FROM_DATABASE=Datum Systems, Inc. OUI:00196A* ID_OUI_FROM_DATABASE=MikroM GmbH OUI:001971* ID_OUI_FROM_DATABASE=Guangzhou Unicomp Technology Co.,Ltd OUI:001965* ID_OUI_FROM_DATABASE=YuHua TelTech (ShangHai) Co., Ltd. OUI:001960* ID_OUI_FROM_DATABASE=DoCoMo Systems, Inc. OUI:001954* ID_OUI_FROM_DATABASE=Leaf Corporation. OUI:001959* ID_OUI_FROM_DATABASE=Staccato Communications Inc. OUI:00194D* ID_OUI_FROM_DATABASE=Avago Technologies Sdn Bhd OUI:001948* ID_OUI_FROM_DATABASE=AireSpider Networks OUI:001941* ID_OUI_FROM_DATABASE=Pitney Bowes, Inc OUI:001935* ID_OUI_FROM_DATABASE=DUERR DENTAL AG OUI:00193A* ID_OUI_FROM_DATABASE=OESOLUTIONS OUI:00193C* ID_OUI_FROM_DATABASE=HighPoint Technologies Incorporated OUI:001773* ID_OUI_FROM_DATABASE=Laketune Technologies Co. Ltd OUI:001778* ID_OUI_FROM_DATABASE=Central Music Co. OUI:00177A* ID_OUI_FROM_DATABASE=ASSA ABLOY AB OUI:00176F* ID_OUI_FROM_DATABASE=PAX Computer Technology(Shenzhen) Ltd. OUI:00176A* ID_OUI_FROM_DATABASE=Avago Technologies OUI:001763* ID_OUI_FROM_DATABASE=Essentia S.p.A. OUI:00175E* ID_OUI_FROM_DATABASE=Zed-3 OUI:001750* ID_OUI_FROM_DATABASE=GSI Group, MicroE Systems OUI:001752* ID_OUI_FROM_DATABASE=DAGS, Inc OUI:001757* ID_OUI_FROM_DATABASE=RIX TECHNOLOGY LIMITED OUI:00183D* ID_OUI_FROM_DATABASE=Vertex Link Corporation OUI:001844* ID_OUI_FROM_DATABASE=Heads Up Technologies, Inc. OUI:001838* ID_OUI_FROM_DATABASE=PanAccess Communications,Inc. OUI:001827* ID_OUI_FROM_DATABASE=NEC UNIFIED SOLUTIONS NEDERLAND B.V. OUI:00182C* ID_OUI_FROM_DATABASE=Ascend Networks, Inc. OUI:00182E* ID_OUI_FROM_DATABASE=XStreamHD, LLC OUI:00181B* ID_OUI_FROM_DATABASE=TaiJin Metal Co., Ltd. OUI:001814* ID_OUI_FROM_DATABASE=Mitutoyo Corporation OUI:001819* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001820* ID_OUI_FROM_DATABASE=w5networks OUI:001808* ID_OUI_FROM_DATABASE=SightLogix, Inc. OUI:00180D* ID_OUI_FROM_DATABASE=Terabytes Server Storage Tech Corp OUI:001803* ID_OUI_FROM_DATABASE=ArcSoft Shanghai Co. LTD OUI:0017F0* ID_OUI_FROM_DATABASE=SZCOM Broadband Network Technology Co.,Ltd OUI:0017F7* ID_OUI_FROM_DATABASE=CEM Solutions Pvt Ltd OUI:0017FE* ID_OUI_FROM_DATABASE=TALOS SYSTEM INC. OUI:0017D8* ID_OUI_FROM_DATABASE=Magnum Semiconductor, Inc. OUI:0017DD* ID_OUI_FROM_DATABASE=Clipsal Australia OUI:0017DF* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0018C6* ID_OUI_FROM_DATABASE=OPW Fuel Management Systems OUI:0018CB* ID_OUI_FROM_DATABASE=Tecobest Technology Limited OUI:0018BF* ID_OUI_FROM_DATABASE=Essence Technology Solution, Inc. OUI:0018BA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0018B8* ID_OUI_FROM_DATABASE=New Voice International AG OUI:0018B3* ID_OUI_FROM_DATABASE=TEC WizHome Co., Ltd. OUI:0018AC* ID_OUI_FROM_DATABASE=Shanghai Jiao Da HISYS Technology Co. Ltd. OUI:0018A5* ID_OUI_FROM_DATABASE=ADigit Technologies Corp. OUI:0018A7* ID_OUI_FROM_DATABASE=Yoggie Security Systems LTD. OUI:001896* ID_OUI_FROM_DATABASE=Great Well Electronic LTD OUI:00189B* ID_OUI_FROM_DATABASE=Thomson Inc. OUI:00179E* ID_OUI_FROM_DATABASE=Sirit Inc OUI:0017A3* ID_OUI_FROM_DATABASE=MIX s.r.l. OUI:0017A8* ID_OUI_FROM_DATABASE=EDM Corporation OUI:001792* ID_OUI_FROM_DATABASE=Falcom Wireless Comunications Gmbh OUI:001797* ID_OUI_FROM_DATABASE=Telsy Elettronica S.p.A. OUI:001799* ID_OUI_FROM_DATABASE=SmarTire Systems Inc. OUI:00178B* ID_OUI_FROM_DATABASE=Teledyne Technologies Incorporated OUI:00177F* ID_OUI_FROM_DATABASE=Worldsmart Retech OUI:001786* ID_OUI_FROM_DATABASE=wisembed OUI:001877* ID_OUI_FROM_DATABASE=Amplex A/S OUI:00186B* ID_OUI_FROM_DATABASE=Sambu Communics CO., LTD. OUI:001870* ID_OUI_FROM_DATABASE=E28 Shanghai Limited OUI:001863* ID_OUI_FROM_DATABASE=Veritech Electronics Limited OUI:001850* ID_OUI_FROM_DATABASE=Secfone Kft OUI:001855* ID_OUI_FROM_DATABASE=Aeromaritime Systembau GmbH OUI:001857* ID_OUI_FROM_DATABASE=Unilever R&D OUI:001849* ID_OUI_FROM_DATABASE=Pigeon Point Systems LLC OUI:0017C7* ID_OUI_FROM_DATABASE=MARA Systems Consulting AB OUI:0017CE* ID_OUI_FROM_DATABASE=Screen Service Spa OUI:0017D3* ID_OUI_FROM_DATABASE=Etymotic Research, Inc. OUI:0017BB* ID_OUI_FROM_DATABASE=Syrinx Industrial Electronics OUI:0017B4* ID_OUI_FROM_DATABASE=Remote Security Systems, LLC OUI:0017B6* ID_OUI_FROM_DATABASE=Aquantia OUI:0017AF* ID_OUI_FROM_DATABASE=Enermet OUI:0018E8* ID_OUI_FROM_DATABASE=Hacetron Corporation OUI:0018EF* ID_OUI_FROM_DATABASE=Escape Communications, Inc. OUI:0018E3* ID_OUI_FROM_DATABASE=Visualgate Systems, Inc. OUI:0018DC* ID_OUI_FROM_DATABASE=Prostar Co., Ltd. OUI:0018E1* ID_OUI_FROM_DATABASE=Verkerk Service Systemen OUI:0018D0* ID_OUI_FROM_DATABASE=AtRoad, A Trimble Company OUI:0018D5* ID_OUI_FROM_DATABASE=REIGNCOM OUI:0018A0* ID_OUI_FROM_DATABASE=Cierma Ascenseurs OUI:001883* ID_OUI_FROM_DATABASE=FORMOSA21 INC. OUI:00188A* ID_OUI_FROM_DATABASE=Infinova LLC OUI:00188F* ID_OUI_FROM_DATABASE=Montgomery Technology, Inc. OUI:00187C* ID_OUI_FROM_DATABASE=INTERCROSS, LLC OUI:00187E* ID_OUI_FROM_DATABASE=RGB Spectrum OUI:00164A* ID_OUI_FROM_DATABASE=Vibration Technology Limited OUI:001644* ID_OUI_FROM_DATABASE=LITE-ON Technology Corp. OUI:001645* ID_OUI_FROM_DATABASE=Power Distribution, Inc. OUI:00163B* ID_OUI_FROM_DATABASE=VertexRSI/General Dynamics OUI:001640* ID_OUI_FROM_DATABASE=Asmobile Communication Inc. OUI:001639* ID_OUI_FROM_DATABASE=UBIQUAM Co.,Ltd OUI:00163A* ID_OUI_FROM_DATABASE=YVES TECHNOLOGY CO., LTD. OUI:001634* ID_OUI_FROM_DATABASE=Mathtech, Inc. OUI:00162D* ID_OUI_FROM_DATABASE=STNet Co., Ltd. OUI:001628* ID_OUI_FROM_DATABASE=Ultra Electronics Manufacturing and Card Systems OUI:001621* ID_OUI_FROM_DATABASE=Colorado Vnet OUI:00161A* ID_OUI_FROM_DATABASE=Dametric AB OUI:001615* ID_OUI_FROM_DATABASE=Nittan Company, Limited OUI:0016C4* ID_OUI_FROM_DATABASE=SiRF Technology, Inc. OUI:0016C6* ID_OUI_FROM_DATABASE=North Atlantic Industries OUI:0016D2* ID_OUI_FROM_DATABASE=Caspian OUI:0016BF* ID_OUI_FROM_DATABASE=PaloDEx Group Oy OUI:0016B3* ID_OUI_FROM_DATABASE=Photonicbridges (China) Co., Ltd. OUI:0016AC* ID_OUI_FROM_DATABASE=Toho Technology Corp. OUI:0016B1* ID_OUI_FROM_DATABASE=KBS OUI:0016A7* ID_OUI_FROM_DATABASE=AWETA G&P OUI:001724* ID_OUI_FROM_DATABASE=Studer Professional Audio GmbH OUI:001718* ID_OUI_FROM_DATABASE=Vansco Electronics Oy OUI:00171D* ID_OUI_FROM_DATABASE=DIGIT OUI:001711* ID_OUI_FROM_DATABASE=GE Healthcare Bio-Sciences AB OUI:00170C* ID_OUI_FROM_DATABASE=Twig Com Ltd. OUI:001707* ID_OUI_FROM_DATABASE=InGrid, Inc OUI:0016FB* ID_OUI_FROM_DATABASE=SHENZHEN MTC CO.,LTD. OUI:001702* ID_OUI_FROM_DATABASE=Osung Midicom Co., Ltd OUI:001744* ID_OUI_FROM_DATABASE=Araneo Ltd. OUI:00173C* ID_OUI_FROM_DATABASE=Extreme Engineering Solutions OUI:001737* ID_OUI_FROM_DATABASE=Industrie Dial Face S.p.A. OUI:00172B* ID_OUI_FROM_DATABASE=Global Technologies Inc. OUI:001730* ID_OUI_FROM_DATABASE=Automation Electronics OUI:001729* ID_OUI_FROM_DATABASE=Ubicod Co.LTD OUI:00169B* ID_OUI_FROM_DATABASE=Alstom Transport OUI:0016A2* ID_OUI_FROM_DATABASE=CentraLite Systems, Inc. OUI:001696* ID_OUI_FROM_DATABASE=QDI Technology (H.K.) Limited OUI:001688* ID_OUI_FROM_DATABASE=ServerEngines LLC OUI:00168A* ID_OUI_FROM_DATABASE=id-Confirm Inc OUI:001683* ID_OUI_FROM_DATABASE=WEBIO International Co.,.Ltd. OUI:00167C* ID_OUI_FROM_DATABASE=iRex Technologies BV OUI:001610* ID_OUI_FROM_DATABASE=Carina Technology OUI:00160B* ID_OUI_FROM_DATABASE=TVWorks LLC OUI:001604* ID_OUI_FROM_DATABASE=Sigpro OUI:0015FE* ID_OUI_FROM_DATABASE=SCHILLING ROBOTICS LLC OUI:0015FD* ID_OUI_FROM_DATABASE=Complete Media Systems OUI:0015FF* ID_OUI_FROM_DATABASE=Novatel Wireless, Inc. OUI:0015F8* ID_OUI_FROM_DATABASE=Kingtronics Industrial Co. Ltd. OUI:0015EC* ID_OUI_FROM_DATABASE=Boca Devices LLC OUI:0015F1* ID_OUI_FROM_DATABASE=KYLINK Communications Corp. OUI:001677* ID_OUI_FROM_DATABASE=Bihl + Wiedemann GmbH OUI:001670* ID_OUI_FROM_DATABASE=SKNET Corporation OUI:001664* ID_OUI_FROM_DATABASE=Prod-El SpA OUI:001669* ID_OUI_FROM_DATABASE=MRV Communication (Networks) LTD OUI:00165D* ID_OUI_FROM_DATABASE=AirDefense, Inc. OUI:001651* ID_OUI_FROM_DATABASE=Exeo Systems OUI:0015E5* ID_OUI_FROM_DATABASE=Cheertek Inc. OUI:0015DB* ID_OUI_FROM_DATABASE=Canesta Inc. OUI:0015D4* ID_OUI_FROM_DATABASE=Emitor AB OUI:0015C8* ID_OUI_FROM_DATABASE=FlexiPanel Ltd OUI:0015C3* ID_OUI_FROM_DATABASE=Ruf Telematik AG OUI:0015C2* ID_OUI_FROM_DATABASE=3M Germany OUI:0015BE* ID_OUI_FROM_DATABASE=Iqua Ltd. OUI:0015B7* ID_OUI_FROM_DATABASE=Toshiba OUI:0015B9* ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. OUI:0016EF* ID_OUI_FROM_DATABASE=Koko Fitness, Inc. OUI:0016F4* ID_OUI_FROM_DATABASE=Eidicom Co., Ltd. OUI:0016E8* ID_OUI_FROM_DATABASE=Sigma Designs, Inc. OUI:0016ED* ID_OUI_FROM_DATABASE=Digital Safety Technologies, Inc OUI:0016DC* ID_OUI_FROM_DATABASE=ARCHOS OUI:0016E1* ID_OUI_FROM_DATABASE=SiliconStor, Inc. OUI:0016D7* ID_OUI_FROM_DATABASE=Sunways AG OUI:0014CB* ID_OUI_FROM_DATABASE=LifeSync Corporation OUI:0014D0* ID_OUI_FROM_DATABASE=BTI Systems Inc. OUI:0014C4* ID_OUI_FROM_DATABASE=Vitelcom Mobile Technology OUI:0014BE* ID_OUI_FROM_DATABASE=Wink communication technology CO.LTD OUI:0014BD* ID_OUI_FROM_DATABASE=incNETWORKS, Inc OUI:0014B8* ID_OUI_FROM_DATABASE=Hill-Rom OUI:0014AE* ID_OUI_FROM_DATABASE=Wizlogics Co., Ltd. OUI:0014B3* ID_OUI_FROM_DATABASE=CoreStar International Corp OUI:00149B* ID_OUI_FROM_DATABASE=Nokota Communications, LLC OUI:00143F* ID_OUI_FROM_DATABASE=Hotway Technology Corporation OUI:001431* ID_OUI_FROM_DATABASE=PDL Electronics Ltd OUI:001433* ID_OUI_FROM_DATABASE=Empower Technologies(Canada) Inc. OUI:001432* ID_OUI_FROM_DATABASE=Tarallax Wireless, Inc. OUI:00142C* ID_OUI_FROM_DATABASE=Koncept International, Inc. OUI:001425* ID_OUI_FROM_DATABASE=Galactic Computing Corp. OUI:001420* ID_OUI_FROM_DATABASE=G-Links networking company OUI:00141B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00146D* ID_OUI_FROM_DATABASE=RF Technologies OUI:00146F* ID_OUI_FROM_DATABASE=Kohler Co OUI:00146E* ID_OUI_FROM_DATABASE=H. Stoll GmbH & Co. KG OUI:001468* ID_OUI_FROM_DATABASE=CelPlan International, Inc. OUI:001461* ID_OUI_FROM_DATABASE=CORONA CORPORATION OUI:00145C* ID_OUI_FROM_DATABASE=Intronics B.V. OUI:001455* ID_OUI_FROM_DATABASE=Coder Electronics Corporation OUI:001444* ID_OUI_FROM_DATABASE=Grundfos Holding OUI:00144B* ID_OUI_FROM_DATABASE=Hifn, Inc. OUI:001589* ID_OUI_FROM_DATABASE=D-MAX Technology Co.,Ltd OUI:00157D* ID_OUI_FROM_DATABASE=POSDATA CO., LTD. OUI:001582* ID_OUI_FROM_DATABASE=Pulse Eight Limited OUI:00157C* ID_OUI_FROM_DATABASE=Dave Networks, Inc. OUI:001578* ID_OUI_FROM_DATABASE=Audio / Video Innovations OUI:001573* ID_OUI_FROM_DATABASE=NewSoft Technology Corporation OUI:00156C* ID_OUI_FROM_DATABASE=SANE SYSTEM CO., LTD OUI:001571* ID_OUI_FROM_DATABASE=Nolan Systems OUI:001572* ID_OUI_FROM_DATABASE=Red-Lemon OUI:001565* ID_OUI_FROM_DATABASE=XIAMEN YEALINK NETWORK TECHNOLOGY CO.,LTD OUI:001559* ID_OUI_FROM_DATABASE=Securaplane Technologies, Inc. OUI:0014A2* ID_OUI_FROM_DATABASE=Core Micro Systems Inc. OUI:001494* ID_OUI_FROM_DATABASE=ESU AG OUI:00148F* ID_OUI_FROM_DATABASE=Protronic (Far East) Ltd. OUI:001488* ID_OUI_FROM_DATABASE=Akorri OUI:001483* ID_OUI_FROM_DATABASE=eXS Inc. OUI:001480* ID_OUI_FROM_DATABASE=Hitachi-LG Data Storage Korea, Inc OUI:00147B* ID_OUI_FROM_DATABASE=Iteris, Inc. OUI:001474* ID_OUI_FROM_DATABASE=K40 Electronics OUI:0015B8* ID_OUI_FROM_DATABASE=Tahoe OUI:0015B2* ID_OUI_FROM_DATABASE=Advanced Industrial Computer, Inc. OUI:0015AE* ID_OUI_FROM_DATABASE=kyung il OUI:0015AD* ID_OUI_FROM_DATABASE=Accedian Networks OUI:00E0A8* ID_OUI_FROM_DATABASE=SAT GmbH & Co. OUI:0015A1* ID_OUI_FROM_DATABASE=ECA-SINTERS OUI:00159C* ID_OUI_FROM_DATABASE=B-KYUNG SYSTEM Co.,Ltd. OUI:001595* ID_OUI_FROM_DATABASE=Quester Tangent Corporation OUI:00158E* ID_OUI_FROM_DATABASE=Plustek.INC OUI:001552* ID_OUI_FROM_DATABASE=Wi-Gear Inc. OUI:001548* ID_OUI_FROM_DATABASE=CUBE TECHNOLOGIES OUI:00154D* ID_OUI_FROM_DATABASE=Netronome Systems, Inc. OUI:00153C* ID_OUI_FROM_DATABASE=Kprotech Co., Ltd. OUI:001543* ID_OUI_FROM_DATABASE=Aberdeen Test Center OUI:001535* ID_OUI_FROM_DATABASE=OTE Spa OUI:001537* ID_OUI_FROM_DATABASE=Ventus Networks OUI:001536* ID_OUI_FROM_DATABASE=Powertech co.,Ltd OUI:001530* ID_OUI_FROM_DATABASE=EMC Corporation OUI:001529* ID_OUI_FROM_DATABASE=N3 Corporation OUI:0014F9* ID_OUI_FROM_DATABASE=Vantage Controls OUI:0014FB* ID_OUI_FROM_DATABASE=Technical Solutions Inc. OUI:0014FA* ID_OUI_FROM_DATABASE=AsGa S.A. OUI:0014F4* ID_OUI_FROM_DATABASE=DekTec Digital Video B.V. OUI:0014ED* ID_OUI_FROM_DATABASE=Airak, Inc. OUI:0014DE* ID_OUI_FROM_DATABASE=Sage Instruments Inc. OUI:0014E3* ID_OUI_FROM_DATABASE=mm-lab GmbH OUI:0014D7* ID_OUI_FROM_DATABASE=Datastore Technology Corp OUI:001524* ID_OUI_FROM_DATABASE=Numatics, Inc. OUI:00151D* ID_OUI_FROM_DATABASE=M2I CORPORATION OUI:001513* ID_OUI_FROM_DATABASE=EFS sas OUI:001507* ID_OUI_FROM_DATABASE=Renaissance Learning Inc OUI:00129E* ID_OUI_FROM_DATABASE=Surf Communications Inc. OUI:001297* ID_OUI_FROM_DATABASE=O2Micro, Inc. OUI:001298* ID_OUI_FROM_DATABASE=MICO ELECTRIC(SHENZHEN) LIMITED OUI:00128D* ID_OUI_FROM_DATABASE=STB Datenservice GmbH OUI:00128E* ID_OUI_FROM_DATABASE=Q-Free ASA OUI:001292* ID_OUI_FROM_DATABASE=Griffin Technology OUI:00127C* ID_OUI_FROM_DATABASE=SWEGON AB OUI:001281* ID_OUI_FROM_DATABASE=March Networks S.p.A. OUI:00127B* ID_OUI_FROM_DATABASE=VIA Networking Technologies, Inc. OUI:001327* ID_OUI_FROM_DATABASE=Data Acquisitions limited OUI:00131D* ID_OUI_FROM_DATABASE=Scanvaegt International A/S OUI:001322* ID_OUI_FROM_DATABASE=DAQ Electronics, Inc. OUI:001316* ID_OUI_FROM_DATABASE=L-S-B Broadcast Technologies GmbH OUI:00130A* ID_OUI_FROM_DATABASE=Nortel OUI:00130F* ID_OUI_FROM_DATABASE=EGEMEN Bilgisayar Muh San ve Tic LTD STI OUI:0012F7* ID_OUI_FROM_DATABASE=Xiamen Xinglian Electronics Co., Ltd. OUI:0012FE* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:001303* ID_OUI_FROM_DATABASE=GateConnect OUI:0012FD* ID_OUI_FROM_DATABASE=OPTIMUS IC S.A. OUI:00140F* ID_OUI_FROM_DATABASE=Federal State Unitary Enterprise Leningrad R&D Institute of OUI:001416* ID_OUI_FROM_DATABASE=Scosche Industries, Inc. OUI:001406* ID_OUI_FROM_DATABASE=Go Networks OUI:001407* ID_OUI_FROM_DATABASE=Sperian Protection Instrumentation OUI:00140C* ID_OUI_FROM_DATABASE=GKB CCTV CO., LTD. OUI:0013FF* ID_OUI_FROM_DATABASE=Dage-MTI of MC, Inc. OUI:001400* ID_OUI_FROM_DATABASE=MINERVA KOREA CO., LTD OUI:0013FA* ID_OUI_FROM_DATABASE=LifeSize Communications, Inc OUI:0013F3* ID_OUI_FROM_DATABASE=Giga-byte Communications Inc. OUI:0013EE* ID_OUI_FROM_DATABASE=JBX Designs Inc. OUI:0013ED* ID_OUI_FROM_DATABASE=PSIA OUI:00135A* ID_OUI_FROM_DATABASE=Project T&E Limited OUI:00135F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001360* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001352* ID_OUI_FROM_DATABASE=Naztec, Inc. OUI:00134B* ID_OUI_FROM_DATABASE=ToGoldenNet Technology Inc. OUI:00134C* ID_OUI_FROM_DATABASE=YDT Technology International OUI:00133A* ID_OUI_FROM_DATABASE=VadaTech Inc. OUI:00133F* ID_OUI_FROM_DATABASE=Eppendorf Instrumente GmbH OUI:00132C* ID_OUI_FROM_DATABASE=MAZ Brandenburg GmbH OUI:001339* ID_OUI_FROM_DATABASE=CCV Deutschland GmbH OUI:0013AD* ID_OUI_FROM_DATABASE=Sendo Ltd OUI:0013B4* ID_OUI_FROM_DATABASE=Appear TV OUI:0013A8* ID_OUI_FROM_DATABASE=Tanisys Technology OUI:0013A7* ID_OUI_FROM_DATABASE=BATTELLE MEMORIAL INSTITUTE OUI:0013A1* ID_OUI_FROM_DATABASE=Crow Electronic Engeneering OUI:00139A* ID_OUI_FROM_DATABASE=K-ubique ID Corp. OUI:001395* ID_OUI_FROM_DATABASE=congatec AG OUI:00138E* ID_OUI_FROM_DATABASE=FOAB Elektronik AB OUI:001388* ID_OUI_FROM_DATABASE=WiMedia Alliance OUI:0013E4* ID_OUI_FROM_DATABASE=YANGJAE SYSTEMS CORP. OUI:0013E9* ID_OUI_FROM_DATABASE=VeriWave, Inc. OUI:0013E3* ID_OUI_FROM_DATABASE=CoVi Technologies, Inc. OUI:0013DD* ID_OUI_FROM_DATABASE=Abbott Diagnostics OUI:0013D6* ID_OUI_FROM_DATABASE=TII NETWORK TECHNOLOGIES, INC. OUI:0013D1* ID_OUI_FROM_DATABASE=KIRK telecom A/S OUI:0013CA* ID_OUI_FROM_DATABASE=Pico Digital OUI:0013C3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0013C4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0013BA* ID_OUI_FROM_DATABASE=ReadyLinks Inc OUI:0013BE* ID_OUI_FROM_DATABASE=Virtual Conexions OUI:0013B9* ID_OUI_FROM_DATABASE=BM SPA OUI:0012F3* ID_OUI_FROM_DATABASE=connectBlue AB OUI:0012ED* ID_OUI_FROM_DATABASE=AVG Advanced Technologies OUI:0012E6* ID_OUI_FROM_DATABASE=SPECTEC COMPUTER CO., LTD. OUI:0012E1* ID_OUI_FROM_DATABASE=Alliant Networks, Inc OUI:0012D3* ID_OUI_FROM_DATABASE=Zetta Systems, Inc. OUI:0012DA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0012D4* ID_OUI_FROM_DATABASE=Princeton Technology, Ltd OUI:0012C7* ID_OUI_FROM_DATABASE=SECURAY Technologies Ltd.Co. OUI:0012CE* ID_OUI_FROM_DATABASE=Advanced Cybernetics Group OUI:0012C2* ID_OUI_FROM_DATABASE=Apex Electronics Factory OUI:0012C1* ID_OUI_FROM_DATABASE=Check Point Software Technologies OUI:0012B8* ID_OUI_FROM_DATABASE=G2 Microsystems OUI:0012BD* ID_OUI_FROM_DATABASE=Avantec Manufacturing Limited OUI:0012B7* ID_OUI_FROM_DATABASE=PTW Freiburg OUI:0012B1* ID_OUI_FROM_DATABASE=Dai Nippon Printing Co., Ltd OUI:0012A5* ID_OUI_FROM_DATABASE=Stargen, Inc. OUI:0012AA* ID_OUI_FROM_DATABASE=IEE, Inc. OUI:001379* ID_OUI_FROM_DATABASE=PONDER INFORMATION INDUSTRIES LTD. OUI:001380* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001385* ID_OUI_FROM_DATABASE=Add-On Technology Co., LTD. OUI:00137F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00136D* ID_OUI_FROM_DATABASE=Tentaculus AB OUI:001366* ID_OUI_FROM_DATABASE=Neturity Technologies Inc. OUI:001258* ID_OUI_FROM_DATABASE=Activis Polska OUI:001251* ID_OUI_FROM_DATABASE=SILINK OUI:001252* ID_OUI_FROM_DATABASE=Citronix, LLC OUI:001245* ID_OUI_FROM_DATABASE=Zellweger Analytics, Inc. OUI:00124C* ID_OUI_FROM_DATABASE=BBWM Corporation OUI:001239* ID_OUI_FROM_DATABASE=S Net Systems Inc. OUI:001240* ID_OUI_FROM_DATABASE=AMOI ELECTRONICS CO.,LTD OUI:00122D* ID_OUI_FROM_DATABASE=SiNett Corporation OUI:001232* ID_OUI_FROM_DATABASE=LeWiz Communications Inc. OUI:0011C5* ID_OUI_FROM_DATABASE=TEN Technology OUI:0011C8* ID_OUI_FROM_DATABASE=Powercom Co., Ltd. OUI:0011CD* ID_OUI_FROM_DATABASE=Axsun Technologies OUI:0011C6* ID_OUI_FROM_DATABASE=Seagate Technology OUI:0011B4* ID_OUI_FROM_DATABASE=Westermo Teleindustri AB OUI:0011B9* ID_OUI_FROM_DATABASE=Inner Range Pty. Ltd. OUI:0011C0* ID_OUI_FROM_DATABASE=Aday Technology Inc OUI:0011B3* ID_OUI_FROM_DATABASE=YOSHIMIYA CO.,LTD. OUI:0011AD* ID_OUI_FROM_DATABASE=Shanghai Ruijie Technology OUI:001138* ID_OUI_FROM_DATABASE=TAISHIN CO., LTD. OUI:00113F* ID_OUI_FROM_DATABASE=Alcatel DI OUI:001133* ID_OUI_FROM_DATABASE=Siemens Austria SIMEA OUI:001132* ID_OUI_FROM_DATABASE=Synology Incorporated OUI:001129* ID_OUI_FROM_DATABASE=Paradise Datacom Ltd. OUI:00112E* ID_OUI_FROM_DATABASE=CEICOM OUI:001128* ID_OUI_FROM_DATABASE=Streamit OUI:00111B* ID_OUI_FROM_DATABASE=Targa Systems Div L-3 Communications Canada OUI:001122* ID_OUI_FROM_DATABASE=CIMSYS Inc OUI:001171* ID_OUI_FROM_DATABASE=DEXTER Communications, Inc. OUI:001165* ID_OUI_FROM_DATABASE=Znyx Networks OUI:00116A* ID_OUI_FROM_DATABASE=Domo Ltd OUI:001160* ID_OUI_FROM_DATABASE=ARTDIO Company Co., LTD OUI:001154* ID_OUI_FROM_DATABASE=Webpro Technologies Inc. OUI:00114B* ID_OUI_FROM_DATABASE=Francotyp-Postalia GmbH OUI:001145* ID_OUI_FROM_DATABASE=ValuePoint Networks OUI:0011A1* ID_OUI_FROM_DATABASE=VISION NETWARE CO.,LTD OUI:0011A6* ID_OUI_FROM_DATABASE=Sypixx Networks OUI:00119A* ID_OUI_FROM_DATABASE=Alkeria srl OUI:001190* ID_OUI_FROM_DATABASE=Digital Design Corporation OUI:00118A* ID_OUI_FROM_DATABASE=Viewtran Technology Limited OUI:001194* ID_OUI_FROM_DATABASE=Chi Mei Communication Systems, Inc. OUI:001189* ID_OUI_FROM_DATABASE=Aerotech Inc OUI:001184* ID_OUI_FROM_DATABASE=Humo Laboratory,Ltd. OUI:00117D* ID_OUI_FROM_DATABASE=ZMD America, Inc. OUI:001178* ID_OUI_FROM_DATABASE=Chiron Technology Ltd OUI:001177* ID_OUI_FROM_DATABASE=Coaxial Networks, Inc. OUI:001223* ID_OUI_FROM_DATABASE=Pixim OUI:001228* ID_OUI_FROM_DATABASE=Data Ltd. OUI:00121C* ID_OUI_FROM_DATABASE=PARROT S.A. OUI:001210* ID_OUI_FROM_DATABASE=WideRay Corp OUI:001215* ID_OUI_FROM_DATABASE=iStor Networks, Inc. OUI:001216* ID_OUI_FROM_DATABASE=ICP Internet Communication Payment AG OUI:001209* ID_OUI_FROM_DATABASE=Fastrax Ltd OUI:001204* ID_OUI_FROM_DATABASE=u10 Networks, Inc. OUI:0011FD* ID_OUI_FROM_DATABASE=KORG INC. OUI:001203* ID_OUI_FROM_DATABASE=ActivNetworks OUI:0011F3* ID_OUI_FROM_DATABASE=NeoMedia Europe AG OUI:0011E7* ID_OUI_FROM_DATABASE=WORLDSAT - Texas de France OUI:0011EC* ID_OUI_FROM_DATABASE=AVIX INC. OUI:0011E0* ID_OUI_FROM_DATABASE=U-MEDIA Communications, Inc. OUI:0011DA* ID_OUI_FROM_DATABASE=Vivaas Technology Inc. OUI:0011D4* ID_OUI_FROM_DATABASE=NetEnrich, Inc OUI:0011D9* ID_OUI_FROM_DATABASE=TiVo OUI:00111C* ID_OUI_FROM_DATABASE=Pleora Technologies Inc. OUI:00110F* ID_OUI_FROM_DATABASE=netplat,Inc. OUI:001116* ID_OUI_FROM_DATABASE=COTEAU VERT CO., LTD. OUI:001109* ID_OUI_FROM_DATABASE=Micro-Star International OUI:001103* ID_OUI_FROM_DATABASE=kawamura electric inc. OUI:000FFD* ID_OUI_FROM_DATABASE=Glorytek Network Inc. OUI:000FEE* ID_OUI_FROM_DATABASE=XTec, Incorporated OUI:000FF4* ID_OUI_FROM_DATABASE=Guntermann & Drunck GmbH OUI:001275* ID_OUI_FROM_DATABASE=Sentilla Corporation OUI:00126E* ID_OUI_FROM_DATABASE=Seidel Elektronik GmbH Nfg.KG OUI:001269* ID_OUI_FROM_DATABASE=Value Electronics OUI:00125C* ID_OUI_FROM_DATABASE=Green Hills Software, Inc. OUI:000F15* ID_OUI_FROM_DATABASE=Kjaerulff1 A/S OUI:000F1A* ID_OUI_FROM_DATABASE=Gaming Support B.V. OUI:000F0E* ID_OUI_FROM_DATABASE=WaveSplitter Technologies, Inc. OUI:000F08* ID_OUI_FROM_DATABASE=Indagon Oy OUI:000F07* ID_OUI_FROM_DATABASE=Mangrove Systems, Inc. OUI:000F02* ID_OUI_FROM_DATABASE=Digicube Technology Co., Ltd OUI:000EFB* ID_OUI_FROM_DATABASE=Macey Enterprises OUI:000EF5* ID_OUI_FROM_DATABASE=iPAC Technology Co., Ltd. OUI:000EF6* ID_OUI_FROM_DATABASE=E-TEN Information Systems Co., Ltd. OUI:000E8A* ID_OUI_FROM_DATABASE=Avara Technologies Pty. Ltd. OUI:000E83* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000E73* ID_OUI_FROM_DATABASE=Tpack A/S OUI:000E7D* ID_OUI_FROM_DATABASE=Electronics Line 3000 Ltd. OUI:000E77* ID_OUI_FROM_DATABASE=Decru, Inc. OUI:000E7E* ID_OUI_FROM_DATABASE=ionSign Oy OUI:000E6F* ID_OUI_FROM_DATABASE=IRIS Corporation Berhad OUI:000E6A* ID_OUI_FROM_DATABASE=3Com Ltd OUI:000E69* ID_OUI_FROM_DATABASE=China Electric Power Research Institute OUI:000E63* ID_OUI_FROM_DATABASE=Lemke Diagnostics GmbH OUI:000EBC* ID_OUI_FROM_DATABASE=Paragon Fidelity GmbH OUI:000EB0* ID_OUI_FROM_DATABASE=Solutions Radio BV OUI:000EB5* ID_OUI_FROM_DATABASE=Ecastle Electronics Co., Ltd. OUI:000EAF* ID_OUI_FROM_DATABASE=CASTEL OUI:000EA9* ID_OUI_FROM_DATABASE=Shanghai Xun Shi Communications Equipment Ltd. Co. OUI:000E9D* ID_OUI_FROM_DATABASE=Tiscali UK Ltd OUI:000EA2* ID_OUI_FROM_DATABASE=McAfee, Inc OUI:000E90* ID_OUI_FROM_DATABASE=PONICO CORP. OUI:000E8F* ID_OUI_FROM_DATABASE=Sercomm Corp. OUI:000E96* ID_OUI_FROM_DATABASE=Cubic Defense Applications, Inc. OUI:000F4E* ID_OUI_FROM_DATABASE=Cellink OUI:000F41* ID_OUI_FROM_DATABASE=Zipher Ltd OUI:000F48* ID_OUI_FROM_DATABASE=Polypix Inc. OUI:000F4D* ID_OUI_FROM_DATABASE=TalkSwitch OUI:000F39* ID_OUI_FROM_DATABASE=IRIS SENSORS OUI:000F3C* ID_OUI_FROM_DATABASE=Endeleo Limited OUI:000F34* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000F2D* ID_OUI_FROM_DATABASE=CHUNG-HSIN ELECTRIC & MACHINERY MFG.CORP. OUI:000F27* ID_OUI_FROM_DATABASE=TEAL Electronics, Inc. OUI:000F28* ID_OUI_FROM_DATABASE=Itronix Corporation OUI:000F21* ID_OUI_FROM_DATABASE=Scientific Atlanta, Inc OUI:000EE8* ID_OUI_FROM_DATABASE=zioncom OUI:000EEF* ID_OUI_FROM_DATABASE=Private OUI:000EDC* ID_OUI_FROM_DATABASE=Tellion INC. OUI:000EE3* ID_OUI_FROM_DATABASE=Chiyu Technology Co.,Ltd OUI:000EC8* ID_OUI_FROM_DATABASE=Zoran Corporation OUI:000ECF* ID_OUI_FROM_DATABASE=PROFIBUS Nutzerorganisation e.V. OUI:000ED4* ID_OUI_FROM_DATABASE=CRESITT INDUSTRIE OUI:000EC2* ID_OUI_FROM_DATABASE=Lowrance Electronics, Inc. OUI:000EC1* ID_OUI_FROM_DATABASE=MYNAH Technologies OUI:000F92* ID_OUI_FROM_DATABASE=Microhard Systems Inc. OUI:000F99* ID_OUI_FROM_DATABASE=APAC opto Electronics Inc. OUI:000F8D* ID_OUI_FROM_DATABASE=FAST TV-Server AG OUI:000F80* ID_OUI_FROM_DATABASE=Trinity Security Systems,Inc. OUI:000F7F* ID_OUI_FROM_DATABASE=UBSTORAGE Co.,Ltd. OUI:000FC2* ID_OUI_FROM_DATABASE=Uniwell Corporation OUI:000FC9* ID_OUI_FROM_DATABASE=Allnet GmbH OUI:000FBC* ID_OUI_FROM_DATABASE=Onkey Technologies, Inc. OUI:000FBB* ID_OUI_FROM_DATABASE=Nokia Siemens Networks GmbH & Co. KG. OUI:000FB6* ID_OUI_FROM_DATABASE=Europlex Technologies OUI:000FA9* ID_OUI_FROM_DATABASE=PC Fabrik OUI:000FAA* ID_OUI_FROM_DATABASE=Nexus Technologies OUI:000FAF* ID_OUI_FROM_DATABASE=Dialog Inc. OUI:000FE8* ID_OUI_FROM_DATABASE=Lobos, Inc. OUI:000FED* ID_OUI_FROM_DATABASE=Anam Electronics Co., Ltd OUI:000FDB* ID_OUI_FROM_DATABASE=Westell Technologies OUI:000FDC* ID_OUI_FROM_DATABASE=Ueda Japan Radio Co., Ltd. OUI:000FE1* ID_OUI_FROM_DATABASE=ID DIGITAL CORPORATION OUI:000FD5* ID_OUI_FROM_DATABASE=Schwechat - RISE OUI:000FCE* ID_OUI_FROM_DATABASE=Kikusui Electronics Corp. OUI:000F73* ID_OUI_FROM_DATABASE=RS Automation Co., Ltd OUI:000F7A* ID_OUI_FROM_DATABASE=BeiJing NuQX Technology CO.,LTD OUI:000F6D* ID_OUI_FROM_DATABASE=Midas Engineering OUI:000F67* ID_OUI_FROM_DATABASE=West Instruments OUI:000F6E* ID_OUI_FROM_DATABASE=BBox OUI:000F60* ID_OUI_FROM_DATABASE=Lifetron Co.,Ltd OUI:000F5B* ID_OUI_FROM_DATABASE=Delta Information Systems, Inc. OUI:000F54* ID_OUI_FROM_DATABASE=Entrelogic Corporation OUI:000D75* ID_OUI_FROM_DATABASE=Kobian Pte Ltd - Taiwan Branch OUI:000D7C* ID_OUI_FROM_DATABASE=Codian Ltd OUI:000D6F* ID_OUI_FROM_DATABASE=Ember Corporation OUI:000D69* ID_OUI_FROM_DATABASE=TMT&D Corporation OUI:000D70* ID_OUI_FROM_DATABASE=Datamax Corporation OUI:000D5D* ID_OUI_FROM_DATABASE=Raritan Computer, Inc OUI:000D62* ID_OUI_FROM_DATABASE=Funkwerk Dabendorf GmbH OUI:000D50* ID_OUI_FROM_DATABASE=Galazar Networks OUI:000D4A* ID_OUI_FROM_DATABASE=Steag ETA-Optik OUI:000DAB* ID_OUI_FROM_DATABASE=Parker Hannifin GmbH Electromechanical Division Europe OUI:000DA7* ID_OUI_FROM_DATABASE=Private OUI:000DA1* ID_OUI_FROM_DATABASE=MIRAE ITS Co.,LTD. OUI:000DA2* ID_OUI_FROM_DATABASE=Infrant Technologies, Inc. OUI:000D9B* ID_OUI_FROM_DATABASE=Heraeus Electro-Nite International N.V. OUI:000D8F* ID_OUI_FROM_DATABASE=King Tsushin Kogyo Co., LTD. OUI:000D94* ID_OUI_FROM_DATABASE=AFAR Communications,Inc OUI:000D82* ID_OUI_FROM_DATABASE=PHS srl OUI:000D81* ID_OUI_FROM_DATABASE=Pepperl+Fuchs GmbH OUI:000DCE* ID_OUI_FROM_DATABASE=Dynavac Technology Pte Ltd OUI:000DC8* ID_OUI_FROM_DATABASE=AirMagnet, Inc OUI:000DC2* ID_OUI_FROM_DATABASE=Private OUI:000DC7* ID_OUI_FROM_DATABASE=COSMIC ENGINEERING INC. OUI:000DBB* ID_OUI_FROM_DATABASE=Nippon Dentsu Co.,Ltd. OUI:000DB5* ID_OUI_FROM_DATABASE=GLOBALSAT TECHNOLOGY CORPORATION OUI:000DAF* ID_OUI_FROM_DATABASE=Plexus Corp (UK) Ltd OUI:000D29* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000D23* ID_OUI_FROM_DATABASE=Smart Solution, Inc OUI:000D17* ID_OUI_FROM_DATABASE=Turbo Networks Co.Ltd OUI:000D1C* ID_OUI_FROM_DATABASE=Amesys Defense OUI:000D0A* ID_OUI_FROM_DATABASE=Projectiondesign as OUI:000D09* ID_OUI_FROM_DATABASE=Yuehua(Zhuhai) Electronic CO. LTD OUI:000D10* ID_OUI_FROM_DATABASE=Embedtronics Oy OUI:000D04* ID_OUI_FROM_DATABASE=Foxboro Eckardt Development GmbH OUI:000CF7* ID_OUI_FROM_DATABASE=Nortel Networks OUI:000CF8* ID_OUI_FROM_DATABASE=Nortel Networks OUI:000CFD* ID_OUI_FROM_DATABASE=Hyundai ImageQuest Co.,Ltd. OUI:000D4F* ID_OUI_FROM_DATABASE=Kenwood Corporation OUI:000D46* ID_OUI_FROM_DATABASE=Parker SSD Drives OUI:000D42* ID_OUI_FROM_DATABASE=Newbest Development Limited OUI:000D3C* ID_OUI_FROM_DATABASE=i.Tech Dynamic Ltd OUI:000D36* ID_OUI_FROM_DATABASE=Wu Han Routon Electronic Co., Ltd OUI:000D3B* ID_OUI_FROM_DATABASE=Microelectronics Technology Inc. OUI:000D2A* ID_OUI_FROM_DATABASE=Scanmatic AS OUI:000D2F* ID_OUI_FROM_DATABASE=AIN Comm.Tech.Co., LTD OUI:000DFA* ID_OUI_FROM_DATABASE=Micro Control Systems Ltd. OUI:000DF4* ID_OUI_FROM_DATABASE=Watertek Co. OUI:000DF9* ID_OUI_FROM_DATABASE=NDS Limited OUI:000E00* ID_OUI_FROM_DATABASE=Atrie OUI:000DE7* ID_OUI_FROM_DATABASE=Snap-on OEM Group OUI:000DE8* ID_OUI_FROM_DATABASE=Nasaco Electronics Pte. Ltd OUI:000DED* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000DE1* ID_OUI_FROM_DATABASE=Control Products, Inc. OUI:000DD5* ID_OUI_FROM_DATABASE=O'RITE TECHNOLOGY CO.,LTD OUI:000DDA* ID_OUI_FROM_DATABASE=ALLIED TELESIS K.K. OUI:000E20* ID_OUI_FROM_DATABASE=ACCESS Systems Americas, Inc. OUI:000E27* ID_OUI_FROM_DATABASE=Crere Networks, Inc. OUI:000E14* ID_OUI_FROM_DATABASE=Visionary Solutions, Inc. OUI:000E1B* ID_OUI_FROM_DATABASE=IAV GmbH OUI:000E57* ID_OUI_FROM_DATABASE=Iworld Networking, Inc. OUI:000E50* ID_OUI_FROM_DATABASE=Thomson Telecom Belgium OUI:000E4A* ID_OUI_FROM_DATABASE=Changchun Huayu WEBPAD Co.,LTD OUI:000E49* ID_OUI_FROM_DATABASE=Forsway Scandinavia AB OUI:000E3D* ID_OUI_FROM_DATABASE=Televic N.V. OUI:000E44* ID_OUI_FROM_DATABASE=Digital 5, Inc. OUI:000E33* ID_OUI_FROM_DATABASE=Shuko Electronics Co.,Ltd OUI:000E3A* ID_OUI_FROM_DATABASE=Cirrus Logic OUI:000E2D* ID_OUI_FROM_DATABASE=Hyundai Digital Technology Co.,Ltd. OUI:000CEA* ID_OUI_FROM_DATABASE=aphona Kommunikationssysteme OUI:000CD9* ID_OUI_FROM_DATABASE=Itcare Co., Ltd OUI:000CD3* ID_OUI_FROM_DATABASE=Prettl Elektronik Radeberg GmbH OUI:000CDA* ID_OUI_FROM_DATABASE=FreeHand Systems, Inc. OUI:000CDF* ID_OUI_FROM_DATABASE=PULNiX America, Inc OUI:000CC7* ID_OUI_FROM_DATABASE=Intelligent Computer Solutions Inc. OUI:000CCC* ID_OUI_FROM_DATABASE=Aeroscout Ltd. OUI:000C13* ID_OUI_FROM_DATABASE=MediaQ OUI:000C05* ID_OUI_FROM_DATABASE=RPA Reserch Co., Ltd. OUI:000C0C* ID_OUI_FROM_DATABASE=APPRO TECHNOLOGY INC. OUI:000BF4* ID_OUI_FROM_DATABASE=Private OUI:000BF9* ID_OUI_FROM_DATABASE=Gemstone Communications, Inc. OUI:000C00* ID_OUI_FROM_DATABASE=BEB Industrie-Elektronik AG OUI:000BF3* ID_OUI_FROM_DATABASE=BAE SYSTEMS OUI:000C63* ID_OUI_FROM_DATABASE=Zenith Electronics Corporation OUI:000C68* ID_OUI_FROM_DATABASE=SigmaTel, Inc. OUI:000C6F* ID_OUI_FROM_DATABASE=Amtek system co.,LTD. OUI:000C50* ID_OUI_FROM_DATABASE=Seagate Technology OUI:000C55* ID_OUI_FROM_DATABASE=Microlink Communications Inc. OUI:000C5C* ID_OUI_FROM_DATABASE=GTN Systems B.V. OUI:000C61* ID_OUI_FROM_DATABASE=AC Tech corporation DBA Advanced Digital OUI:000CBA* ID_OUI_FROM_DATABASE=Jamex, Inc. OUI:000CB9* ID_OUI_FROM_DATABASE=LEA OUI:000CC0* ID_OUI_FROM_DATABASE=Genera Oy OUI:000CB4* ID_OUI_FROM_DATABASE=AutoCell Laboratories, Inc. OUI:000C34* ID_OUI_FROM_DATABASE=Vixen Co., Ltd. OUI:000CA2* ID_OUI_FROM_DATABASE=Harmonic Video Network OUI:000CA7* ID_OUI_FROM_DATABASE=Metro (Suzhou) Technologies Co., Ltd. OUI:000CA9* ID_OUI_FROM_DATABASE=Ebtron Inc. OUI:000CAE* ID_OUI_FROM_DATABASE=Ailocom Oy OUI:000C42* ID_OUI_FROM_DATABASE=Routerboard.com OUI:000C44* ID_OUI_FROM_DATABASE=Automated Interfaces, Inc. OUI:000C39* ID_OUI_FROM_DATABASE=Sentinel Wireless Inc. OUI:000C3B* ID_OUI_FROM_DATABASE=Orion Electric Co., Ltd. OUI:000C40* ID_OUI_FROM_DATABASE=Altech Controls OUI:000C3A* ID_OUI_FROM_DATABASE=Oxance OUI:000C2F* ID_OUI_FROM_DATABASE=SeorimTechnology Co.,Ltd. OUI:000C31* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000C2A* ID_OUI_FROM_DATABASE=OCTTEL Communication Co., Ltd. OUI:000C27* ID_OUI_FROM_DATABASE=Sammy Corporation OUI:000C18* ID_OUI_FROM_DATABASE=Zenisu Keisoku Inc. OUI:000C20* ID_OUI_FROM_DATABASE=Fi WIn, Inc. OUI:000BED* ID_OUI_FROM_DATABASE=ELM Inc. OUI:000BF2* ID_OUI_FROM_DATABASE=Chih-Kan Technology Co., Ltd. OUI:000BE1* ID_OUI_FROM_DATABASE=Nokia NET Product Operations OUI:000BE6* ID_OUI_FROM_DATABASE=Datel Electronics OUI:000BDA* ID_OUI_FROM_DATABASE=EyeCross Co.,Inc. OUI:000BD1* ID_OUI_FROM_DATABASE=Aeronix, Inc. OUI:000BC5* ID_OUI_FROM_DATABASE=SMC Networks, Inc. OUI:000BCC* ID_OUI_FROM_DATABASE=JUSAN, S.A. OUI:000BB9* ID_OUI_FROM_DATABASE=Imsys AB OUI:000BBE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000BB2* ID_OUI_FROM_DATABASE=SMALLBIG TECHNOLOGY OUI:000BB7* ID_OUI_FROM_DATABASE=Micro Systems Co.,Ltd. OUI:000C96* ID_OUI_FROM_DATABASE=OQO, Inc. OUI:000C9B* ID_OUI_FROM_DATABASE=EE Solutions, Inc OUI:000C8A* ID_OUI_FROM_DATABASE=Bose Corporation OUI:000C8F* ID_OUI_FROM_DATABASE=Nergal s.r.l. OUI:000C83* ID_OUI_FROM_DATABASE=Logical Solutions OUI:000C88* ID_OUI_FROM_DATABASE=Apache Micro Peripherals, Inc. OUI:000C74* ID_OUI_FROM_DATABASE=RIVERTEC CORPORATION OUI:000C76* ID_OUI_FROM_DATABASE=MICRO-STAR INTERNATIONAL CO., LTD. OUI:000C7B* ID_OUI_FROM_DATABASE=ALPHA PROJECT Co.,Ltd. OUI:000B85* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000B7F* ID_OUI_FROM_DATABASE=Align Engineering LLC OUI:000B84* ID_OUI_FROM_DATABASE=BODET OUI:000B73* ID_OUI_FROM_DATABASE=Kodeos Communications OUI:000B78* ID_OUI_FROM_DATABASE=TAIFATECH INC. OUI:000B6C* ID_OUI_FROM_DATABASE=Sychip Inc. OUI:000B60* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000B65* ID_OUI_FROM_DATABASE=Sy.A.C. srl OUI:000B57* ID_OUI_FROM_DATABASE=Silicon Laboratories OUI:000B5C* ID_OUI_FROM_DATABASE=Newtech Co.,Ltd OUI:000B4F* ID_OUI_FROM_DATABASE=Verifone, INC. OUI:000B43* ID_OUI_FROM_DATABASE=Microscan Systems, Inc. OUI:000B48* ID_OUI_FROM_DATABASE=sofrel OUI:000B4A* ID_OUI_FROM_DATABASE=Visimetrics (UK) Ltd OUI:000B35* ID_OUI_FROM_DATABASE=Quad Bit System co., Ltd. OUI:000B37* ID_OUI_FROM_DATABASE=MANUFACTURE DES MONTRES ROLEX SA OUI:000B3C* ID_OUI_FROM_DATABASE=Cygnal Integrated Products, Inc. OUI:000B29* ID_OUI_FROM_DATABASE=LS(LG) Industrial Systems co.,Ltd OUI:000B30* ID_OUI_FROM_DATABASE=Beijing Gongye Science & Technology Co.,Ltd OUI:000BA1* ID_OUI_FROM_DATABASE=SYSCOM Ltd. OUI:000BA8* ID_OUI_FROM_DATABASE=HANBACK ELECTRONICS CO., LTD. OUI:000B92* ID_OUI_FROM_DATABASE=Ascom Danmark A/S OUI:000B97* ID_OUI_FROM_DATABASE=Matsushita Electric Industrial Co.,Ltd. OUI:000B9C* ID_OUI_FROM_DATABASE=TriBeam Technologies, Inc. OUI:000B8B* ID_OUI_FROM_DATABASE=KERAJET, S.A. OUI:0009D6* ID_OUI_FROM_DATABASE=KNC One GmbH OUI:0009D5* ID_OUI_FROM_DATABASE=Signal Communication, Inc. OUI:0009DC* ID_OUI_FROM_DATABASE=Galaxis Technology AG OUI:0009C9* ID_OUI_FROM_DATABASE=BlueWINC Co., Ltd. OUI:0009D0* ID_OUI_FROM_DATABASE=Solacom Technologies Inc. OUI:0009BC* ID_OUI_FROM_DATABASE=Digital Safety Technologies, Inc OUI:0009C1* ID_OUI_FROM_DATABASE=PROCES-DATA A/S OUI:0009C4* ID_OUI_FROM_DATABASE=Medicore Co., Ltd OUI:00098F* ID_OUI_FROM_DATABASE=Cetacean Networks OUI:00097D* ID_OUI_FROM_DATABASE=SecWell Networks Oy OUI:00097E* ID_OUI_FROM_DATABASE=IMI TECHNOLOGY CO., LTD OUI:000983* ID_OUI_FROM_DATABASE=GlobalTop Technology, Inc. OUI:000970* ID_OUI_FROM_DATABASE=Vibration Research Corporation OUI:000977* ID_OUI_FROM_DATABASE=Brunner Elektronik AG OUI:000964* ID_OUI_FROM_DATABASE=Hi-Techniques, Inc. OUI:00096B* ID_OUI_FROM_DATABASE=IBM Corp OUI:000957* ID_OUI_FROM_DATABASE=Supercaller, Inc. OUI:00095C* ID_OUI_FROM_DATABASE=Philips Medical Systems - Cardiac and Monitoring Systems (CM OUI:000AE3* ID_OUI_FROM_DATABASE=YANG MEI TECHNOLOGY CO., LTD OUI:000AEA* ID_OUI_FROM_DATABASE=ADAM ELEKTRONIK LTD. ŞTI OUI:000ADE* ID_OUI_FROM_DATABASE=Happy Communication Co., Ltd. OUI:000AD7* ID_OUI_FROM_DATABASE=Origin ELECTRIC CO.,LTD. OUI:000ACB* ID_OUI_FROM_DATABASE=XPAK MSA Group OUI:000AD0* ID_OUI_FROM_DATABASE=Niigata Develoment Center, F.I.T. Co., Ltd. OUI:000AD2* ID_OUI_FROM_DATABASE=JEPICO Corporation OUI:000ABD* ID_OUI_FROM_DATABASE=Rupprecht & Patashnick Co. OUI:000ABF* ID_OUI_FROM_DATABASE=HIROTA SS OUI:000AC4* ID_OUI_FROM_DATABASE=Daewoo Teletech Co., Ltd OUI:000AAC* ID_OUI_FROM_DATABASE=TerraTec Electronic GmbH OUI:000AB1* ID_OUI_FROM_DATABASE=GENETEC Corporation OUI:000AB8* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000AA5* ID_OUI_FROM_DATABASE=MAXLINK INDUSTRIES LIMITED OUI:000A8D* ID_OUI_FROM_DATABASE=EUROTHERM LIMITED OUI:000A9E* ID_OUI_FROM_DATABASE=BroadWeb Corportation OUI:000AA0* ID_OUI_FROM_DATABASE=Cedar Point Communications OUI:000A98* ID_OUI_FROM_DATABASE=M+F Gwinner GmbH & Co OUI:000A92* ID_OUI_FROM_DATABASE=Presonus Corporation OUI:000A7E* ID_OUI_FROM_DATABASE=The Advantage Group OUI:000A85* ID_OUI_FROM_DATABASE=PLAT'C2,Inc OUI:000A8A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0009B5* ID_OUI_FROM_DATABASE=3J Tech. Co., Ltd. OUI:0009AF* ID_OUI_FROM_DATABASE=e-generis OUI:0009B0* ID_OUI_FROM_DATABASE=Onkyo Corporation OUI:0009A9* ID_OUI_FROM_DATABASE=Ikanos Communications OUI:00099D* ID_OUI_FROM_DATABASE=Haliplex Communications OUI:0009A2* ID_OUI_FROM_DATABASE=Interface Co., Ltd. OUI:000990* ID_OUI_FROM_DATABASE=ACKSYS Communications & systems OUI:000996* ID_OUI_FROM_DATABASE=RDI OUI:00098A* ID_OUI_FROM_DATABASE=EqualLogic Inc OUI:000A77* ID_OUI_FROM_DATABASE=Bluewire Technologies LLC OUI:000A79* ID_OUI_FROM_DATABASE=corega K.K OUI:000A72* ID_OUI_FROM_DATABASE=STEC, INC. OUI:000A5F* ID_OUI_FROM_DATABASE=almedio inc. OUI:000A66* ID_OUI_FROM_DATABASE=MITSUBISHI ELECTRIC SYSTEM & SERVICE CO.,LTD. OUI:000A6B* ID_OUI_FROM_DATABASE=Tadiran Telecom Business Systems LTD OUI:000A5A* ID_OUI_FROM_DATABASE=GreenNET Technologies Co.,Ltd. OUI:000A53* ID_OUI_FROM_DATABASE=Intronics, Incorporated OUI:000A58* ID_OUI_FROM_DATABASE=Freyer & Siegel Elektronik GmbH & Co. KG OUI:000A4C* ID_OUI_FROM_DATABASE=Molecular Devices Corporation OUI:000B24* ID_OUI_FROM_DATABASE=AirLogic OUI:000B1D* ID_OUI_FROM_DATABASE=LayerZero Power Systems, Inc. OUI:000B16* ID_OUI_FROM_DATABASE=Communication Machinery Corporation OUI:000B18* ID_OUI_FROM_DATABASE=Private OUI:000B11* ID_OUI_FROM_DATABASE=HIMEJI ABC TRADING CO.,LTD. OUI:000B0A* ID_OUI_FROM_DATABASE=dBm Optics OUI:000B05* ID_OUI_FROM_DATABASE=Pacific Broadband Networks OUI:000AFE* ID_OUI_FROM_DATABASE=NovaPal Ltd OUI:000B03* ID_OUI_FROM_DATABASE=Taekwang Industrial Co., Ltd OUI:000AEF* ID_OUI_FROM_DATABASE=OTRUM ASA OUI:000AF2* ID_OUI_FROM_DATABASE=NeoAxiom Corp. OUI:000A05* ID_OUI_FROM_DATABASE=Widax Corp. OUI:000A08* ID_OUI_FROM_DATABASE=ALPINE ELECTRONICS, INC. OUI:000A0A* ID_OUI_FROM_DATABASE=SUNIX Co., Ltd. OUI:000A0F* ID_OUI_FROM_DATABASE=Ilryung Telesys, Inc OUI:0009FF* ID_OUI_FROM_DATABASE=X.net 2000 GmbH OUI:0009FE* ID_OUI_FROM_DATABASE=Daisy Technologies, Inc. OUI:000A00* ID_OUI_FROM_DATABASE=Mediatek Corp. OUI:0009F6* ID_OUI_FROM_DATABASE=Shenzhen Eastern Digital Tech Ltd. OUI:0009F5* ID_OUI_FROM_DATABASE=Emerson Network Power Co.,Ltd OUI:0009E8* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0009EF* ID_OUI_FROM_DATABASE=Vocera Communications OUI:0009E3* ID_OUI_FROM_DATABASE=Angel Iglesias S.A. OUI:000A39* ID_OUI_FROM_DATABASE=LoPA Information Technology OUI:000A40* ID_OUI_FROM_DATABASE=Crown Audio -- Harmanm International OUI:000A45* ID_OUI_FROM_DATABASE=Audio-Technica Corp. OUI:000A47* ID_OUI_FROM_DATABASE=Allied Vision Technologies OUI:000A34* ID_OUI_FROM_DATABASE=Identicard Systems Incorporated OUI:000A2D* ID_OUI_FROM_DATABASE=Cabot Communications Limited OUI:000A22* ID_OUI_FROM_DATABASE=Amperion Inc OUI:000A16* ID_OUI_FROM_DATABASE=Lassen Research OUI:000A1B* ID_OUI_FROM_DATABASE=Stream Labs OUI:000878* ID_OUI_FROM_DATABASE=Benchmark Storage Innovations OUI:000872* ID_OUI_FROM_DATABASE=Sorenson Communications OUI:00087E* ID_OUI_FROM_DATABASE=Bon Electro-Telecom Inc. OUI:00086B* ID_OUI_FROM_DATABASE=MIPSYS OUI:000865* ID_OUI_FROM_DATABASE=JASCOM CO., LTD OUI:000866* ID_OUI_FROM_DATABASE=DSX Access Systems, Inc. OUI:00085F* ID_OUI_FROM_DATABASE=Picanol N.V. OUI:000859* ID_OUI_FROM_DATABASE=ShenZhen Unitone Electronics Co., Ltd. OUI:000853* ID_OUI_FROM_DATABASE=Schleicher GmbH & Co. Relaiswerke KG OUI:000858* ID_OUI_FROM_DATABASE=Novatechnology Inc. OUI:00081D* ID_OUI_FROM_DATABASE=Ipsil, Incorporated OUI:000829* ID_OUI_FROM_DATABASE=Aval Nagasaki Corporation OUI:000823* ID_OUI_FROM_DATABASE=Texa Corp. OUI:00082A* ID_OUI_FROM_DATABASE=Powerwallz Network Security OUI:000817* ID_OUI_FROM_DATABASE=EmergeCore Networks LLC OUI:00091E* ID_OUI_FROM_DATABASE=Firstech Technology Corp. OUI:000925* ID_OUI_FROM_DATABASE=VSN Systemen BV OUI:000918* ID_OUI_FROM_DATABASE=SAMSUNG TECHWIN CO.,LTD OUI:000917* ID_OUI_FROM_DATABASE=WEM Technology Inc OUI:000912* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00090B* ID_OUI_FROM_DATABASE=MTL Instruments PLC OUI:000905* ID_OUI_FROM_DATABASE=iTEC Technologies Ltd. OUI:0008FF* ID_OUI_FROM_DATABASE=Trilogy Communications Ltd OUI:000906* ID_OUI_FROM_DATABASE=Esteem Networks OUI:0008FB* ID_OUI_FROM_DATABASE=SonoSite, Inc. OUI:0008F1* ID_OUI_FROM_DATABASE=Voltaire OUI:0008F2* ID_OUI_FROM_DATABASE=C&S Technology OUI:0008F7* ID_OUI_FROM_DATABASE=Hitachi Ltd, Semiconductor & Integrated Circuits Gr OUI:0008ED* ID_OUI_FROM_DATABASE=ST&T Instrument Corp. OUI:0007D1* ID_OUI_FROM_DATABASE=Spectrum Signal Processing Inc. OUI:0007CE* ID_OUI_FROM_DATABASE=Cabletime Limited OUI:0007C8* ID_OUI_FROM_DATABASE=Brain21, Inc. OUI:0007BC* ID_OUI_FROM_DATABASE=Identix Inc. OUI:00047C* ID_OUI_FROM_DATABASE=Skidata AG OUI:0007BB* ID_OUI_FROM_DATABASE=Candera Inc. OUI:0007C2* ID_OUI_FROM_DATABASE=Netsys Telecom OUI:0007B5* ID_OUI_FROM_DATABASE=Any One Wireless Ltd. OUI:0007AF* ID_OUI_FROM_DATABASE=Red Lion Controls, LP OUI:0007A2* ID_OUI_FROM_DATABASE=Opteon Corporation OUI:0007A7* ID_OUI_FROM_DATABASE=A-Z Inc. OUI:0007A1* ID_OUI_FROM_DATABASE=VIASYS Healthcare GmbH OUI:0007A8* ID_OUI_FROM_DATABASE=Haier Group Technologies Ltd. OUI:00094A* ID_OUI_FROM_DATABASE=Homenet Communications OUI:000949* ID_OUI_FROM_DATABASE=Glyph Technologies Inc. OUI:000950* ID_OUI_FROM_DATABASE=Independent Storage Corporation OUI:000944* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00093D* ID_OUI_FROM_DATABASE=Newisys,Inc. OUI:000937* ID_OUI_FROM_DATABASE=Inventec Appliance Corp OUI:000931* ID_OUI_FROM_DATABASE=Future Internet, Inc. OUI:000938* ID_OUI_FROM_DATABASE=Allot Communications OUI:00092A* ID_OUI_FROM_DATABASE=MYTECS Co.,Ltd. OUI:0008B1* ID_OUI_FROM_DATABASE=ProQuent Systems OUI:0008AB* ID_OUI_FROM_DATABASE=EnerLinx.com, Inc. OUI:0008AC* ID_OUI_FROM_DATABASE=Eltromat GmbH OUI:0008A5* ID_OUI_FROM_DATABASE=Peninsula Systems Inc. OUI:000899* ID_OUI_FROM_DATABASE=Netbind, Inc. OUI:00089E* ID_OUI_FROM_DATABASE=Beijing Enter-Net co.LTD OUI:000895* ID_OUI_FROM_DATABASE=DIRC Technologie GmbH & Co.KG OUI:000891* ID_OUI_FROM_DATABASE=Lyan Inc. OUI:00088B* ID_OUI_FROM_DATABASE=Tropic Networks Inc. OUI:00088A* ID_OUI_FROM_DATABASE=Minds@Work OUI:000885* ID_OUI_FROM_DATABASE=EMS Dr. Thomas Wünsche OUI:0008E8* ID_OUI_FROM_DATABASE=Excel Master Ltd. OUI:0008E7* ID_OUI_FROM_DATABASE=SHI ControlSystems,Ltd. OUI:0008E1* ID_OUI_FROM_DATABASE=Barix AG OUI:0008DA* ID_OUI_FROM_DATABASE=SofaWare Technologies Ltd. OUI:0008D5* ID_OUI_FROM_DATABASE=Vanguard Networks Solutions, LLC OUI:0008CE* ID_OUI_FROM_DATABASE=IPMobileNet Inc. OUI:0008C8* ID_OUI_FROM_DATABASE=Soneticom, Inc. OUI:0008C4* ID_OUI_FROM_DATABASE=Hikari Co.,Ltd. OUI:0008BE* ID_OUI_FROM_DATABASE=XENPAK MSA Group OUI:0008B8* ID_OUI_FROM_DATABASE=E.F. Johnson OUI:00079B* ID_OUI_FROM_DATABASE=Aurora Networks OUI:00078F* ID_OUI_FROM_DATABASE=Emkay Innovative Products OUI:000788* ID_OUI_FROM_DATABASE=Clipcomm, Inc. OUI:000779* ID_OUI_FROM_DATABASE=Sungil Telecom Co., Ltd. OUI:000778* ID_OUI_FROM_DATABASE=GERSTEL GmbH & Co. KG OUI:000772* ID_OUI_FROM_DATABASE=Alcatel Shanghai Bell Co., Ltd. OUI:00076C* ID_OUI_FROM_DATABASE=Daehanet, Inc. OUI:00075C* ID_OUI_FROM_DATABASE=Eastman Kodak Company OUI:000761* ID_OUI_FROM_DATABASE=Logitech Europe SA OUI:000768* ID_OUI_FROM_DATABASE=Danfoss A/S OUI:000762* ID_OUI_FROM_DATABASE=Group Sense Limited OUI:000755* ID_OUI_FROM_DATABASE=Lafon OUI:00074F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000741* ID_OUI_FROM_DATABASE=Sierra Automated Systems OUI:000749* ID_OUI_FROM_DATABASE=CENiX Inc. OUI:000735* ID_OUI_FROM_DATABASE=Flarion Technologies, Inc. OUI:00073B* ID_OUI_FROM_DATABASE=Tenovis GmbH & Co KG OUI:000729* ID_OUI_FROM_DATABASE=Kistler Instrumente AG OUI:00072E* ID_OUI_FROM_DATABASE=North Node AB OUI:000728* ID_OUI_FROM_DATABASE=Neo Telecom OUI:000718* ID_OUI_FROM_DATABASE=iCanTek Co., Ltd. OUI:00080D* ID_OUI_FROM_DATABASE=Toshiba OUI:000806* ID_OUI_FROM_DATABASE=Raonet Systems, Inc. OUI:0007FD* ID_OUI_FROM_DATABASE=LANergy Ltd. OUI:0007F6* ID_OUI_FROM_DATABASE=Qqest Software Systems OUI:0007FC* ID_OUI_FROM_DATABASE=Adept Systems Inc. OUI:0007EA* ID_OUI_FROM_DATABASE=Massana, Inc. OUI:0007F0* ID_OUI_FROM_DATABASE=LogiSync LLC OUI:0007E3* ID_OUI_FROM_DATABASE=Navcom Technology, Inc. OUI:0007E4* ID_OUI_FROM_DATABASE=SoftRadio Co., Ltd. OUI:0007DD* ID_OUI_FROM_DATABASE=Cradle Technologies OUI:0007D7* ID_OUI_FROM_DATABASE=Caporis Networks AG OUI:0006E3* ID_OUI_FROM_DATABASE=Quantitative Imaging Corporation OUI:0006DD* ID_OUI_FROM_DATABASE=AT & T Laboratories - Cambridge Ltd OUI:0006A4* ID_OUI_FROM_DATABASE=INNOWELL Corp. OUI:0006D3* ID_OUI_FROM_DATABASE=Alpha Telecom, Inc. U.S.A. OUI:0006D2* ID_OUI_FROM_DATABASE=Tundra Semiconductor Corp. OUI:000647* ID_OUI_FROM_DATABASE=Etrali S.A. OUI:0006D9* ID_OUI_FROM_DATABASE=IPM-Net S.p.A. OUI:0005EA* ID_OUI_FROM_DATABASE=Rednix OUI:0006CD* ID_OUI_FROM_DATABASE=Leaf Imaging Ltd. OUI:0006BC* ID_OUI_FROM_DATABASE=Macrolink, Inc. OUI:0006C6* ID_OUI_FROM_DATABASE=lesswire AG OUI:000654* ID_OUI_FROM_DATABASE=Winpresa Building Automation Technologies GmbH OUI:0006B6* ID_OUI_FROM_DATABASE=Nir-Or Israel Ltd. OUI:0006B0* ID_OUI_FROM_DATABASE=Comtech EF Data Corp. OUI:00071F* ID_OUI_FROM_DATABASE=European Systems Integration OUI:000724* ID_OUI_FROM_DATABASE=Telemax Co., Ltd. OUI:000707* ID_OUI_FROM_DATABASE=Interalia Inc. OUI:00070C* ID_OUI_FROM_DATABASE=SVA-Intrusion.com Co. Ltd. OUI:000711* ID_OUI_FROM_DATABASE=Acterna OUI:000712* ID_OUI_FROM_DATABASE=JAL Information Technology OUI:0006FA* ID_OUI_FROM_DATABASE=IP SQUARE Co, Ltd. OUI:0006EF* ID_OUI_FROM_DATABASE=Maxxan Systems, Inc. OUI:0006EA* ID_OUI_FROM_DATABASE=ELZET80 Mikrocomputer GmbH&Co. KG OUI:0006E9* ID_OUI_FROM_DATABASE=Intime Corp. OUI:0005EB* ID_OUI_FROM_DATABASE=Blue Ridge Networks, Inc. OUI:0005F7* ID_OUI_FROM_DATABASE=Analog Devices, Inc. OUI:0005E4* ID_OUI_FROM_DATABASE=Red Lion Controls Inc. OUI:0005F1* ID_OUI_FROM_DATABASE=Vrcom, Inc. OUI:0005FD* ID_OUI_FROM_DATABASE=PacketLight Networks Ltd. OUI:0005E2* ID_OUI_FROM_DATABASE=Creativ Network Technologies OUI:0005DC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0005E1* ID_OUI_FROM_DATABASE=Trellis Photonics, Ltd. OUI:0005D8* ID_OUI_FROM_DATABASE=Arescom, Inc. OUI:0005D7* ID_OUI_FROM_DATABASE=Vista Imaging, Inc. OUI:0005C5* ID_OUI_FROM_DATABASE=Flaga HF OUI:0005D1* ID_OUI_FROM_DATABASE=Metavector Technologies OUI:0005D2* ID_OUI_FROM_DATABASE=DAP Technologies OUI:0005CB* ID_OUI_FROM_DATABASE=ROIS Technologies, Inc. OUI:00057F* ID_OUI_FROM_DATABASE=Acqis Technology OUI:000579* ID_OUI_FROM_DATABASE=Universal Control Solution Corp. OUI:000575* ID_OUI_FROM_DATABASE=CDS-Electronics BV OUI:00056F* ID_OUI_FROM_DATABASE=Innomedia Technologies Pvt. Ltd. OUI:000569* ID_OUI_FROM_DATABASE=VMware, Inc. OUI:000568* ID_OUI_FROM_DATABASE=Piltofish Networks AB OUI:000562* ID_OUI_FROM_DATABASE=Digital View Limited OUI:00055C* ID_OUI_FROM_DATABASE=Kowa Company, Ltd. OUI:000556* ID_OUI_FROM_DATABASE=360 Systems OUI:000550* ID_OUI_FROM_DATABASE=Vcomms Connect Limited OUI:000545* ID_OUI_FROM_DATABASE=Internet Photonics OUI:00053F* ID_OUI_FROM_DATABASE=VisionTek, Inc. OUI:000546* ID_OUI_FROM_DATABASE=KDDI Network & Solultions Inc. OUI:0006AA* ID_OUI_FROM_DATABASE=VT Miltope OUI:0006A9* ID_OUI_FROM_DATABASE=Universal Instruments Corp. OUI:0006A0* ID_OUI_FROM_DATABASE=Mx Imaging OUI:00069F* ID_OUI_FROM_DATABASE=Kuokoa Networks OUI:000699* ID_OUI_FROM_DATABASE=Vida Design Co. OUI:000693* ID_OUI_FROM_DATABASE=Flexus Computer Technology, Inc. OUI:00069A* ID_OUI_FROM_DATABASE=e & Tel OUI:00068D* ID_OUI_FROM_DATABASE=SEPATON, Inc. OUI:000687* ID_OUI_FROM_DATABASE=Omnitron Systems Technology, Inc. OUI:000680* ID_OUI_FROM_DATABASE=Card Access, Inc. OUI:000539* ID_OUI_FROM_DATABASE=A Brand New World in Sweden AB OUI:000526* ID_OUI_FROM_DATABASE=IPAS GmbH OUI:00052D* ID_OUI_FROM_DATABASE=Zoltrix International Limited OUI:00052C* ID_OUI_FROM_DATABASE=Supreme Magic Corporation OUI:000520* ID_OUI_FROM_DATABASE=Smartronix, Inc. OUI:00051A* ID_OUI_FROM_DATABASE=3COM EUROPE LTD. OUI:000510* ID_OUI_FROM_DATABASE=Infinite Shanghai Communication Terminals Ltd. OUI:000514* ID_OUI_FROM_DATABASE=KDT Systems Co., Ltd. OUI:000509* ID_OUI_FROM_DATABASE=AVOC Nishimura Ltd. OUI:000503* ID_OUI_FROM_DATABASE=ICONAG OUI:00050A* ID_OUI_FROM_DATABASE=ICS Spa OUI:0004FF* ID_OUI_FROM_DATABASE=Acronet Co., Ltd. OUI:000500* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000641* ID_OUI_FROM_DATABASE=ITCN OUI:00063D* ID_OUI_FROM_DATABASE=Microwave Data Systems Inc. OUI:000631* ID_OUI_FROM_DATABASE=Calix OUI:000630* ID_OUI_FROM_DATABASE=Adtranz Sweden OUI:000637* ID_OUI_FROM_DATABASE=Toptrend-Meta Information (ShenZhen) Inc. OUI:000620* ID_OUI_FROM_DATABASE=Serial System Ltd. OUI:00061A* ID_OUI_FROM_DATABASE=Zetari Inc. OUI:00060C* ID_OUI_FROM_DATABASE=Melco Industries, Inc. OUI:000614* ID_OUI_FROM_DATABASE=Prism Holdings OUI:000606* ID_OUI_FROM_DATABASE=RapidWAN, Inc. OUI:000677* ID_OUI_FROM_DATABASE=SICK AG OUI:000673* ID_OUI_FROM_DATABASE=TKH Security Solutions USA OUI:000666* ID_OUI_FROM_DATABASE=Roving Networks OUI:00066D* ID_OUI_FROM_DATABASE=Compuprint S.P.A. OUI:00066C* ID_OUI_FROM_DATABASE=Robinson Corporation OUI:000653* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00065A* ID_OUI_FROM_DATABASE=Strix Systems OUI:00064D* ID_OUI_FROM_DATABASE=Sencore OUI:000660* ID_OUI_FROM_DATABASE=NADEX Co., Ltd. OUI:0005B8* ID_OUI_FROM_DATABASE=Electronic Design Associates, Inc. OUI:0005BF* ID_OUI_FROM_DATABASE=JustEzy Technology, Inc. OUI:0005AE* ID_OUI_FROM_DATABASE=Mediaport USA OUI:0005B2* ID_OUI_FROM_DATABASE=Medison Co., Ltd. OUI:00059E* ID_OUI_FROM_DATABASE=Zinwell Corporation OUI:0005A5* ID_OUI_FROM_DATABASE=KOTT OUI:000598* ID_OUI_FROM_DATABASE=CRONOS S.r.l. OUI:0005A4* ID_OUI_FROM_DATABASE=Lucid Voice Ltd. OUI:000592* ID_OUI_FROM_DATABASE=Pultek Corp. OUI:00058B* ID_OUI_FROM_DATABASE=IPmental, Inc. OUI:00058C* ID_OUI_FROM_DATABASE=Opentech Inc. OUI:00037E* ID_OUI_FROM_DATABASE=PORTech Communications, Inc. OUI:000383* ID_OUI_FROM_DATABASE=Metera Networks, Inc. OUI:000377* ID_OUI_FROM_DATABASE=Gigabit Wireless OUI:00037B* ID_OUI_FROM_DATABASE=IDEC IZUMI Corporation OUI:00036B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000372* ID_OUI_FROM_DATABASE=ULAN OUI:000367* ID_OUI_FROM_DATABASE=Jasmine Networks, Inc. OUI:00036A* ID_OUI_FROM_DATABASE=Mainnet, Ltd. OUI:000364* ID_OUI_FROM_DATABASE=Scenix Semiconductor, Inc. OUI:00035F* ID_OUI_FROM_DATABASE=Prüftechnik Condition Monitoring GmbH & Co. KG OUI:00035C* ID_OUI_FROM_DATABASE=Saint Song Corp. OUI:000358* ID_OUI_FROM_DATABASE=Hanyang Digitech Co., Ltd. OUI:00034D* ID_OUI_FROM_DATABASE=Chiaro Networks, Ltd. OUI:0003FA* ID_OUI_FROM_DATABASE=TiMetra Networks OUI:0003F5* ID_OUI_FROM_DATABASE=Chip2Chip OUI:0003EE* ID_OUI_FROM_DATABASE=MKNet Corporation OUI:0003E8* ID_OUI_FROM_DATABASE=Wavelength Digital Limited OUI:0003E3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0003DC* ID_OUI_FROM_DATABASE=Lexar Media, Inc. OUI:0003D7* ID_OUI_FROM_DATABASE=NextNet Wireless, Inc. OUI:0003D4* ID_OUI_FROM_DATABASE=Alloptic, Inc. OUI:00030B* ID_OUI_FROM_DATABASE=Hunter Technology, Inc. OUI:0003D0* ID_OUI_FROM_DATABASE=KOANKEISO Co., Ltd. OUI:0003C9* ID_OUI_FROM_DATABASE=TECOM Co., Ltd. OUI:0003C4* ID_OUI_FROM_DATABASE=Tomra Systems ASA OUI:0004FA* ID_OUI_FROM_DATABASE=NBS Technologies Inc. OUI:0004F9* ID_OUI_FROM_DATABASE=Xtera Communications, Inc. OUI:0004F3* ID_OUI_FROM_DATABASE=FS FORTH-SYSTEME GmbH OUI:0004E7* ID_OUI_FROM_DATABASE=Lightpointe Communications, Inc OUI:0004ED* ID_OUI_FROM_DATABASE=Billion Electric Co., Ltd. OUI:0004DD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0004D6* ID_OUI_FROM_DATABASE=Takagi Industrial Co., Ltd. OUI:0004D0* ID_OUI_FROM_DATABASE=Softlink s.r.o. OUI:0004CA* ID_OUI_FROM_DATABASE=FreeMs Corp. OUI:0004BE* ID_OUI_FROM_DATABASE=OptXCon, Inc. OUI:0004C3* ID_OUI_FROM_DATABASE=CASTOR Informatique OUI:0004C4* ID_OUI_FROM_DATABASE=Allen & Heath Limited OUI:0004B7* ID_OUI_FROM_DATABASE=AMB i.t. Holding OUI:0004B1* ID_OUI_FROM_DATABASE=Signal Technology, Inc. OUI:0004AD* ID_OUI_FROM_DATABASE=Malibu Networks OUI:0004AA* ID_OUI_FROM_DATABASE=Jetstream Communications OUI:0004A3* ID_OUI_FROM_DATABASE=Microchip Technology, Inc. OUI:00049D* ID_OUI_FROM_DATABASE=Ipanema Technologies OUI:000497* ID_OUI_FROM_DATABASE=MacroSystem Digital Video AG OUI:000490* ID_OUI_FROM_DATABASE=Optical Access OUI:00048B* ID_OUI_FROM_DATABASE=Poscon Corporation OUI:000341* ID_OUI_FROM_DATABASE=Axon Digital Design OUI:00033E* ID_OUI_FROM_DATABASE=Tateyama System Laboratory Co., Ltd. OUI:00033A* ID_OUI_FROM_DATABASE=Silicon Wave, Inc. OUI:000333* ID_OUI_FROM_DATABASE=Digitel Co., Ltd. OUI:00032B* ID_OUI_FROM_DATABASE=GAI Datenfunksysteme GmbH OUI:000327* ID_OUI_FROM_DATABASE=ACT'L OUI:00032E* ID_OUI_FROM_DATABASE=Scope Information Management, Ltd. OUI:000322* ID_OUI_FROM_DATABASE=IDIS Co., Ltd. OUI:00031E* ID_OUI_FROM_DATABASE=Optranet, Inc. OUI:00B052* ID_OUI_FROM_DATABASE=Atheros Communications OUI:000319* ID_OUI_FROM_DATABASE=Infineon AG OUI:000316* ID_OUI_FROM_DATABASE=Nobell Communications, Inc. OUI:000312* ID_OUI_FROM_DATABASE=TR-Systemtechnik GmbH OUI:000447* ID_OUI_FROM_DATABASE=Acrowave Systems Co., Ltd. OUI:00043B* ID_OUI_FROM_DATABASE=Lava Computer Mfg., Inc. OUI:000440* ID_OUI_FROM_DATABASE=cyberPIXIE, Inc. OUI:00043A* ID_OUI_FROM_DATABASE=Intelligent Telecommunications, Inc. OUI:000434* ID_OUI_FROM_DATABASE=Accelent Systems, Inc. OUI:00042D* ID_OUI_FROM_DATABASE=Sarian Systems, Ltd. OUI:00042E* ID_OUI_FROM_DATABASE=Netous Technologies, Ltd. OUI:000428* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000421* ID_OUI_FROM_DATABASE=Ocular Networks OUI:000417* ID_OUI_FROM_DATABASE=ELAU AG OUI:000411* ID_OUI_FROM_DATABASE=Inkra Networks, Inc. OUI:00040B* ID_OUI_FROM_DATABASE=3COM EUROPE LTD. OUI:000404* ID_OUI_FROM_DATABASE=Makino Milling Machine Co., Ltd. OUI:000481* ID_OUI_FROM_DATABASE=Econolite Control Products, Inc. OUI:000486* ID_OUI_FROM_DATABASE=ITTC, University of Kansas OUI:000477* ID_OUI_FROM_DATABASE=Scalant Systems, Inc. OUI:000476* ID_OUI_FROM_DATABASE=3 Com Corporation OUI:000469* ID_OUI_FROM_DATABASE=Innocom, Inc. OUI:000470* ID_OUI_FROM_DATABASE=ipUnplugged AB OUI:00046A* ID_OUI_FROM_DATABASE=Navini Networks OUI:000464* ID_OUI_FROM_DATABASE=Pulse-Link Inc OUI:00045D* ID_OUI_FROM_DATABASE=BEKA Elektronik OUI:0003B2* ID_OUI_FROM_DATABASE=Radware OUI:000457* ID_OUI_FROM_DATABASE=Universal Access Technology, Inc. OUI:000451* ID_OUI_FROM_DATABASE=Medrad, Inc. OUI:0003C1* ID_OUI_FROM_DATABASE=Packet Dynamics Ltd OUI:0003BD* ID_OUI_FROM_DATABASE=OmniCluster Technologies, Inc. OUI:0003B8* ID_OUI_FROM_DATABASE=NetKit Solutions, LLC OUI:0003B6* ID_OUI_FROM_DATABASE=QSI Corporation OUI:0003A6* ID_OUI_FROM_DATABASE=Traxit Technology, Inc. OUI:0003AB* ID_OUI_FROM_DATABASE=Bridge Information Systems OUI:0003A3* ID_OUI_FROM_DATABASE=MAVIX, Ltd. OUI:00039F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00039A* ID_OUI_FROM_DATABASE=SiConnect OUI:00038C* ID_OUI_FROM_DATABASE=Total Impact OUI:000384* ID_OUI_FROM_DATABASE=AETA OUI:000387* ID_OUI_FROM_DATABASE=Blaze Network Products OUI:000306* ID_OUI_FROM_DATABASE=Fusion In Tech Co., Ltd. OUI:000303* ID_OUI_FROM_DATABASE=JAMA Electronics Co., Ltd. OUI:0002FF* ID_OUI_FROM_DATABASE=Handan BroadInfoCom OUI:0002F3* ID_OUI_FROM_DATABASE=Media Serve Co., Ltd. OUI:0002FA* ID_OUI_FROM_DATABASE=DX Antenna Co., Ltd. OUI:0002ED* ID_OUI_FROM_DATABASE=DXO Telecom Co., Ltd. OUI:0002E5* ID_OUI_FROM_DATABASE=Timeware Ltd. OUI:0002E8* ID_OUI_FROM_DATABASE=E.D.&A. OUI:0002DC* ID_OUI_FROM_DATABASE=Fujitsu General Limited OUI:0002E1* ID_OUI_FROM_DATABASE=Integrated Network Corporation OUI:0002D5* ID_OUI_FROM_DATABASE=ACR OUI:0002C9* ID_OUI_FROM_DATABASE=Mellanox Technologies OUI:0002CE* ID_OUI_FROM_DATABASE=FoxJet, Inc. OUI:00B0DB* ID_OUI_FROM_DATABASE=Nextcell, Inc. OUI:00B08E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00B01C* ID_OUI_FROM_DATABASE=Westport Technologies OUI:00B02D* ID_OUI_FROM_DATABASE=ViaGate Technologies, Inc. OUI:00B03B* ID_OUI_FROM_DATABASE=HiQ Networks OUI:0030A9* ID_OUI_FROM_DATABASE=Netiverse, Inc. OUI:00B0F0* ID_OUI_FROM_DATABASE=CALY NETWORKS OUI:00B086* ID_OUI_FROM_DATABASE=LocSoft Limited OUI:0030C4* ID_OUI_FROM_DATABASE=Canon Imaging Systems Inc. OUI:00309D* ID_OUI_FROM_DATABASE=Nimble Microsystems, Inc. OUI:003037* ID_OUI_FROM_DATABASE=Packard Bell Nec Services OUI:00302E* ID_OUI_FROM_DATABASE=Hoft & Wessel AG OUI:00301B* ID_OUI_FROM_DATABASE=SHUTTLE, INC. OUI:003028* ID_OUI_FROM_DATABASE=FASE Saldatura srl OUI:0030FB* ID_OUI_FROM_DATABASE=AZS Technology AG OUI:003048* ID_OUI_FROM_DATABASE=Supermicro Computer, Inc. OUI:0001DA* ID_OUI_FROM_DATABASE=WINCOMM Corporation OUI:0001E1* ID_OUI_FROM_DATABASE=Kinpo Electronics, Inc. OUI:0001DD* ID_OUI_FROM_DATABASE=Avail Networks OUI:0001CE* ID_OUI_FROM_DATABASE=Custom Micro Products, Ltd. OUI:0001CA* ID_OUI_FROM_DATABASE=Geocast Network Systems, Inc. OUI:0001B8* ID_OUI_FROM_DATABASE=Netsensity, Inc. OUI:0001BD* ID_OUI_FROM_DATABASE=Peterson Electro-Musical Products, Inc. OUI:0001B4* ID_OUI_FROM_DATABASE=Wayport, Inc. OUI:0001C3* ID_OUI_FROM_DATABASE=Acromag, Inc. OUI:0001BF* ID_OUI_FROM_DATABASE=Teleforce Co., Ltd. OUI:0001AD* ID_OUI_FROM_DATABASE=Coach Master International d.b.a. CMI Worldwide, Inc. OUI:00017E* ID_OUI_FROM_DATABASE=ADTEK System Science Co., Ltd. OUI:00018A* ID_OUI_FROM_DATABASE=ROI COMPUTER AG OUI:000119* ID_OUI_FROM_DATABASE=RTUnet (Australia) OUI:000125* ID_OUI_FROM_DATABASE=YAESU MUSEN CO., LTD. OUI:000121* ID_OUI_FROM_DATABASE=Watchguard Technologies, Inc. OUI:000128* ID_OUI_FROM_DATABASE=EnjoyWeb, Inc. OUI:000106* ID_OUI_FROM_DATABASE=Tews Datentechnik GmbH OUI:000112* ID_OUI_FROM_DATABASE=Shark Multimedia Inc. OUI:000102* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:000115* ID_OUI_FROM_DATABASE=EXTRATECH CORPORATION OUI:000109* ID_OUI_FROM_DATABASE=Nagano Japan Radio Co., Ltd. OUI:081443* ID_OUI_FROM_DATABASE=UNIBRAIN S.A. OUI:00B0F5* ID_OUI_FROM_DATABASE=NetWorth Technologies, Inc. OUI:00B019* ID_OUI_FROM_DATABASE=UTC CCS OUI:00B02A* ID_OUI_FROM_DATABASE=ORSYS GmbH OUI:00B0AE* ID_OUI_FROM_DATABASE=Symmetricom OUI:000181* ID_OUI_FROM_DATABASE=Nortel Networks OUI:00018D* ID_OUI_FROM_DATABASE=AudeSi Technologies OUI:00019A* ID_OUI_FROM_DATABASE=LEUNIG GmbH OUI:000193* ID_OUI_FROM_DATABASE=Hanbyul Telecom Co., Ltd. OUI:0001A2* ID_OUI_FROM_DATABASE=Logical Co., Ltd. OUI:000196* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0001A6* ID_OUI_FROM_DATABASE=Scientific-Atlanta Arcodan A/S OUI:000172* ID_OUI_FROM_DATABASE=TechnoLand Co., LTD. OUI:00303F* ID_OUI_FROM_DATABASE=TurboComm Tech Inc. OUI:003073* ID_OUI_FROM_DATABASE=International Microsystems, In OUI:00014D* ID_OUI_FROM_DATABASE=Shin Kin Enterprises Co., Ltd OUI:00016B* ID_OUI_FROM_DATABASE=LightChip, Inc. OUI:000167* ID_OUI_FROM_DATABASE=HIOKI E.E. CORPORATION OUI:000215* ID_OUI_FROM_DATABASE=Cotas Computer Technology A/B OUI:000211* ID_OUI_FROM_DATABASE=Nature Worldwide Technology Corp. OUI:000209* ID_OUI_FROM_DATABASE=Shenzhen SED Information Technology Co., Ltd. OUI:000205* ID_OUI_FROM_DATABASE=Hitachi Denshi, Ltd. OUI:000202* ID_OUI_FROM_DATABASE=Amino Communications, Ltd. OUI:0001F6* ID_OUI_FROM_DATABASE=Association of Musical Electronics Industry OUI:0001ED* ID_OUI_FROM_DATABASE=SETA Corp. OUI:0001E9* ID_OUI_FROM_DATABASE=Litton Marine Systems B.V. OUI:0002C6* ID_OUI_FROM_DATABASE=Data Track Technology PLC OUI:0002C2* ID_OUI_FROM_DATABASE=Net Vision Telecom OUI:0002B9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0002B4* ID_OUI_FROM_DATABASE=DAPHNE OUI:0002AD* ID_OUI_FROM_DATABASE=HOYA Corporation OUI:0002A6* ID_OUI_FROM_DATABASE=Effinet Systems Co., Ltd. OUI:0002A1* ID_OUI_FROM_DATABASE=World Wide Packets OUI:00029B* ID_OUI_FROM_DATABASE=Kreatel Communications AB OUI:00029E* ID_OUI_FROM_DATABASE=Information Equipment Co., Ltd. OUI:000296* ID_OUI_FROM_DATABASE=Lectron Co,. Ltd. OUI:00028F* ID_OUI_FROM_DATABASE=Globetek, Inc. OUI:000289* ID_OUI_FROM_DATABASE=DNE Technologies OUI:000285* ID_OUI_FROM_DATABASE=Riverstone Networks OUI:00027E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000280* ID_OUI_FROM_DATABASE=Mu Net, Inc. OUI:000279* ID_OUI_FROM_DATABASE=Control Applications, Ltd. OUI:000272* ID_OUI_FROM_DATABASE=CC&C Technologies, Inc. OUI:00026B* ID_OUI_FROM_DATABASE=BCM Computers Co., Ltd. OUI:00026D* ID_OUI_FROM_DATABASE=Adept Telecom OUI:000262* ID_OUI_FROM_DATABASE=Soyo Group Soyo Com Tech Co., Ltd OUI:000260* ID_OUI_FROM_DATABASE=Accordion Networks, Inc. OUI:00025B* ID_OUI_FROM_DATABASE=Cambridge Silicon Radio OUI:000087* ID_OUI_FROM_DATABASE=HITACHI, LTD. OUI:000252* ID_OUI_FROM_DATABASE=Carrier Corporation OUI:00024B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000246* ID_OUI_FROM_DATABASE=All-Win Tech Co., Ltd. OUI:00017A* ID_OUI_FROM_DATABASE=Chengdu Maipu Electric Industrial Co., Ltd. OUI:000235* ID_OUI_FROM_DATABASE=Paragon Networks International OUI:000238* ID_OUI_FROM_DATABASE=Serome Technology, Inc. OUI:000230* ID_OUI_FROM_DATABASE=Intersoft Electronics OUI:000229* ID_OUI_FROM_DATABASE=Adtec Corporation OUI:000225* ID_OUI_FROM_DATABASE=One Stop Systems OUI:00021C* ID_OUI_FROM_DATABASE=Network Elements, Inc. OUI:000221* ID_OUI_FROM_DATABASE=DSP Application, Ltd. OUI:00016E* ID_OUI_FROM_DATABASE=Conklin Corporation OUI:00015B* ID_OUI_FROM_DATABASE=ITALTEL S.p.A/RF-UP-I OUI:000154* ID_OUI_FROM_DATABASE=G3M Corporation OUI:000150* ID_OUI_FROM_DATABASE=GILAT COMMUNICATIONS, LTD. OUI:00012E* ID_OUI_FROM_DATABASE=PC Partner Ltd. OUI:00013A* ID_OUI_FROM_DATABASE=SHELCAD COMMUNICATIONS, LTD. OUI:000141* ID_OUI_FROM_DATABASE=CABLE PRINT OUI:000131* ID_OUI_FROM_DATABASE=Bosch Security Systems, Inc. OUI:00013D* ID_OUI_FROM_DATABASE=RiscStation Ltd. OUI:000149* ID_OUI_FROM_DATABASE=T.D.T. Transfer Data Test GmbH OUI:00D047* ID_OUI_FROM_DATABASE=XN TECHNOLOGIES OUI:00D018* ID_OUI_FROM_DATABASE=QWES. COM, INC. OUI:00D048* ID_OUI_FROM_DATABASE=ECTON, INC. OUI:00D028* ID_OUI_FROM_DATABASE=Harmonic, Inc OUI:00D02F* ID_OUI_FROM_DATABASE=VLSI TECHNOLOGY INC. OUI:00D025* ID_OUI_FROM_DATABASE=XROSSTECH, INC. OUI:00D085* ID_OUI_FROM_DATABASE=OTIS ELEVATOR COMPANY OUI:00D077* ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES OUI:00D093* ID_OUI_FROM_DATABASE=TQ - COMPONENTS GMBH OUI:00D013* ID_OUI_FROM_DATABASE=PRIMEX AEROSPACE COMPANY OUI:00D056* ID_OUI_FROM_DATABASE=SOMAT CORPORATION OUI:00D017* ID_OUI_FROM_DATABASE=SYNTECH INFORMATION CO., LTD. OUI:00D036* ID_OUI_FROM_DATABASE=TECHNOLOGY ATLANTA CORP. OUI:00D0D6* ID_OUI_FROM_DATABASE=AETHRA TELECOMUNICAZIONI OUI:003078* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:003003* ID_OUI_FROM_DATABASE=Phasys Ltd. OUI:0030D5* ID_OUI_FROM_DATABASE=DResearch GmbH OUI:0030CE* ID_OUI_FROM_DATABASE=Zaffire OUI:003095* ID_OUI_FROM_DATABASE=Procomp Informatics, Ltd. OUI:003055* ID_OUI_FROM_DATABASE=Renesas Technology America, Inc. OUI:0030B0* ID_OUI_FROM_DATABASE=Convergenet Technologies OUI:0030CC* ID_OUI_FROM_DATABASE=Tenor Networks, Inc. OUI:003013* ID_OUI_FROM_DATABASE=NEC Corporation OUI:003061* ID_OUI_FROM_DATABASE=MobyTEL OUI:00D0AB* ID_OUI_FROM_DATABASE=DELTAKABEL TELECOM CV OUI:00D0A8* ID_OUI_FROM_DATABASE=NETWORK ENGINES, INC. OUI:00D01C* ID_OUI_FROM_DATABASE=SBS TECHNOLOGIES, OUI:00D0C0* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00D051* ID_OUI_FROM_DATABASE=O2 MICRO, INC. OUI:00D06D* ID_OUI_FROM_DATABASE=ACRISON, INC. OUI:0050A1* ID_OUI_FROM_DATABASE=CARLO GAVAZZI, INC. OUI:00D06C* ID_OUI_FROM_DATABASE=SHAREWAVE, INC. OUI:00D03A* ID_OUI_FROM_DATABASE=ZONEWORX, INC. OUI:0050C1* ID_OUI_FROM_DATABASE=GEMFLEX NETWORKS, LTD. OUI:0050FB* ID_OUI_FROM_DATABASE=VSK ELECTRONICS OUI:005033* ID_OUI_FROM_DATABASE=MAYAN NETWORKS OUI:0030A0* ID_OUI_FROM_DATABASE=TYCO SUBMARINE SYSTEMS, LTD. OUI:0030CB* ID_OUI_FROM_DATABASE=OMNI FLOW COMPUTERS, INC. OUI:00306B* ID_OUI_FROM_DATABASE=CMOS SYSTEMS, INC. OUI:003068* ID_OUI_FROM_DATABASE=CYBERNETICS TECH. CO., LTD. OUI:0030E3* ID_OUI_FROM_DATABASE=SEDONA NETWORKS CORP. OUI:00D007* ID_OUI_FROM_DATABASE=MIC ASSOCIATES, INC. OUI:00D07F* ID_OUI_FROM_DATABASE=STRATEGY & TECHNOLOGY, LIMITED OUI:003085* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:003026* ID_OUI_FROM_DATABASE=HeiTel Digital Video GmbH OUI:0030A6* ID_OUI_FROM_DATABASE=VIANET TECHNOLOGIES, LTD. OUI:003047* ID_OUI_FROM_DATABASE=NISSEI ELECTRIC CO., LTD. OUI:00D0FC* ID_OUI_FROM_DATABASE=GRANITE MICROSYSTEMS OUI:00D042* ID_OUI_FROM_DATABASE=MAHLO GMBH & CO. UG OUI:00D046* ID_OUI_FROM_DATABASE=DOLBY LABORATORIES, INC. OUI:00D0BA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00D0BC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00D0D8* ID_OUI_FROM_DATABASE=3Com Corporation OUI:00D06B* ID_OUI_FROM_DATABASE=SR TELECOM INC. OUI:0030AA* ID_OUI_FROM_DATABASE=AXUS MICROSYSTEMS, INC. OUI:003043* ID_OUI_FROM_DATABASE=IDREAM TECHNOLOGIES, PTE. LTD. OUI:003010* ID_OUI_FROM_DATABASE=VISIONETICS INTERNATIONAL OUI:003096* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:003084* ID_OUI_FROM_DATABASE=ALLIED TELESYN INTERNAIONAL OUI:0030CF* ID_OUI_FROM_DATABASE=TWO TECHNOLOGIES, INC. OUI:00D0E3* ID_OUI_FROM_DATABASE=ELE-CHEM ENGINEERING CO., LTD. OUI:00D0ED* ID_OUI_FROM_DATABASE=XIOX OUI:00D0C2* ID_OUI_FROM_DATABASE=BALTHAZAR TECHNOLOGY AB OUI:00D0FB* ID_OUI_FROM_DATABASE=TEK MICROSYSTEMS, INCORPORATED OUI:00D082* ID_OUI_FROM_DATABASE=IOWAVE INC. OUI:00D0AD* ID_OUI_FROM_DATABASE=TL INDUSTRIES OUI:00D0DB* ID_OUI_FROM_DATABASE=MCQUAY INTERNATIONAL OUI:00D06A* ID_OUI_FROM_DATABASE=LINKUP SYSTEMS CORPORATION OUI:00D065* ID_OUI_FROM_DATABASE=TOKO ELECTRIC OUI:00D08F* ID_OUI_FROM_DATABASE=ARDENT TECHNOLOGIES, INC. OUI:00D0E7* ID_OUI_FROM_DATABASE=VCON TELECOMMUNICATION LTD. OUI:00D087* ID_OUI_FROM_DATABASE=MICROFIRST INC. OUI:00D008* ID_OUI_FROM_DATABASE=MACTELL CORPORATION OUI:003005* ID_OUI_FROM_DATABASE=Fujitsu Siemens Computers OUI:00304E* ID_OUI_FROM_DATABASE=BUSTEC PRODUCTION LTD. OUI:0030E0* ID_OUI_FROM_DATABASE=OXFORD SEMICONDUCTOR LTD. OUI:0030A1* ID_OUI_FROM_DATABASE=WEBGATE Inc. OUI:00303D* ID_OUI_FROM_DATABASE=IVA CORPORATION OUI:0030C3* ID_OUI_FROM_DATABASE=FLUECKIGER ELEKTRONIK AG OUI:009047* ID_OUI_FROM_DATABASE=GIGA FAST E. LTD. OUI:0090CB* ID_OUI_FROM_DATABASE=Wireless OnLine, Inc. OUI:00903F* ID_OUI_FROM_DATABASE=AZTEC RADIOMEDIA OUI:001043* ID_OUI_FROM_DATABASE=A2 CORPORATION OUI:00108D* ID_OUI_FROM_DATABASE=Johnson Controls, Inc. OUI:00108E* ID_OUI_FROM_DATABASE=HUGH SYMONS CONCEPT Technologies Ltd. OUI:001052* ID_OUI_FROM_DATABASE=METTLER-TOLEDO (ALBSTADT) GMBH OUI:00100E* ID_OUI_FROM_DATABASE=MICRO LINEAR COPORATION OUI:0010D7* ID_OUI_FROM_DATABASE=ARGOSY RESEARCH INC. OUI:001059* ID_OUI_FROM_DATABASE=DIABLO RESEARCH CO. LLC OUI:0010B6* ID_OUI_FROM_DATABASE=ENTRATA COMMUNICATIONS CORP. OUI:001019* ID_OUI_FROM_DATABASE=SIRONA DENTAL SYSTEMS GmbH & Co. KG OUI:001013* ID_OUI_FROM_DATABASE=Kontron America, Inc. OUI:0090A4* ID_OUI_FROM_DATABASE=ALTIGA NETWORKS OUI:00906C* ID_OUI_FROM_DATABASE=Sartorius Hamburg GmbH OUI:0090FC* ID_OUI_FROM_DATABASE=NETWORK COMPUTING DEVICES OUI:0090A3* ID_OUI_FROM_DATABASE=Corecess Inc. OUI:009022* ID_OUI_FROM_DATABASE=IVEX OUI:0090A5* ID_OUI_FROM_DATABASE=SPECTRA LOGIC OUI:0090BA* ID_OUI_FROM_DATABASE=VALID NETWORKS, INC. OUI:0090EE* ID_OUI_FROM_DATABASE=PERSONAL COMMUNICATIONS TECHNOLOGIES OUI:0090CD* ID_OUI_FROM_DATABASE=ENT-EMPRESA NACIONAL DE TELECOMMUNICACOES, S.A. OUI:0090D0* ID_OUI_FROM_DATABASE=Thomson Telecom Belgium OUI:009075* ID_OUI_FROM_DATABASE=NEC DO BRASIL S.A. OUI:00902E* ID_OUI_FROM_DATABASE=NAMCO LIMITED OUI:0090A0* ID_OUI_FROM_DATABASE=8X8 INC. OUI:00907C* ID_OUI_FROM_DATABASE=DIGITALCAST, INC. OUI:0090DF* ID_OUI_FROM_DATABASE=MITSUBISHI CHEMICAL AMERICA, INC. OUI:009023* ID_OUI_FROM_DATABASE=ZILOG INC. OUI:00908A* ID_OUI_FROM_DATABASE=BAYLY COMMUNICATIONS, INC. OUI:009063* ID_OUI_FROM_DATABASE=COHERENT COMMUNICATIONS SYSTEMS CORPORATION OUI:009041* ID_OUI_FROM_DATABASE=APPLIED DIGITAL ACCESS OUI:0090D8* ID_OUI_FROM_DATABASE=WHITECROSS SYSTEMS OUI:009011* ID_OUI_FROM_DATABASE=WAVTrace, Inc. OUI:009040* ID_OUI_FROM_DATABASE=Siemens Network Convergence LLC OUI:0090C7* ID_OUI_FROM_DATABASE=ICOM INC. OUI:009035* ID_OUI_FROM_DATABASE=ALPHA TELECOM, INC. OUI:009087* ID_OUI_FROM_DATABASE=ITIS OUI:00906E* ID_OUI_FROM_DATABASE=PRAXON, INC. OUI:009039* ID_OUI_FROM_DATABASE=SHASTA NETWORKS OUI:00909A* ID_OUI_FROM_DATABASE=ONE WORLD SYSTEMS, INC. OUI:009053* ID_OUI_FROM_DATABASE=DAEWOO ELECTRONICS CO., LTD. OUI:00909E* ID_OUI_FROM_DATABASE=Critical IO, LLC OUI:0090C2* ID_OUI_FROM_DATABASE=JK microsystems, Inc. OUI:009091* ID_OUI_FROM_DATABASE=DigitalScape, Inc. OUI:0090ED* ID_OUI_FROM_DATABASE=CENTRAL SYSTEM RESEARCH CO., LTD. OUI:00901B* ID_OUI_FROM_DATABASE=DIGITAL CONTROLS OUI:00905C* ID_OUI_FROM_DATABASE=EDMI OUI:0090D2* ID_OUI_FROM_DATABASE=ARTEL VIDEO SYSTEMS OUI:00508C* ID_OUI_FROM_DATABASE=RSI SYSTEMS OUI:00502D* ID_OUI_FROM_DATABASE=ACCEL, INC. OUI:0050B8* ID_OUI_FROM_DATABASE=INOVA COMPUTERS GMBH & CO. KG OUI:00503A* ID_OUI_FROM_DATABASE=DATONG ELECTRONICS LTD. OUI:00508E* ID_OUI_FROM_DATABASE=OPTIMATION, INC. OUI:0050BB* ID_OUI_FROM_DATABASE=CMS TECHNOLOGIES OUI:005051* ID_OUI_FROM_DATABASE=IWATSU ELECTRIC CO., LTD. OUI:0050BE* ID_OUI_FROM_DATABASE=FAST MULTIMEDIA AG OUI:0050AD* ID_OUI_FROM_DATABASE=CommUnique Wireless Corp. OUI:005016* ID_OUI_FROM_DATABASE=SST/WOODHEAD INDUSTRIES OUI:005003* ID_OUI_FROM_DATABASE=Xrite Inc OUI:005023* ID_OUI_FROM_DATABASE=PG DESIGN ELECTRONICS, INC. OUI:005039* ID_OUI_FROM_DATABASE=MARINER NETWORKS OUI:00505A* ID_OUI_FROM_DATABASE=NETWORK ALCHEMY, INC. OUI:005071* ID_OUI_FROM_DATABASE=AIWA CO., LTD. OUI:009071* ID_OUI_FROM_DATABASE=Applied Innovation Inc. OUI:009031* ID_OUI_FROM_DATABASE=MYSTICOM, LTD. OUI:00901F* ID_OUI_FROM_DATABASE=ADTEC PRODUCTIONS, INC. OUI:009081* ID_OUI_FROM_DATABASE=ALOHA NETWORKS, INC. OUI:0090B3* ID_OUI_FROM_DATABASE=AGRANAT SYSTEMS OUI:00500D* ID_OUI_FROM_DATABASE=SATORI ELECTORIC CO., LTD. OUI:0050EC* ID_OUI_FROM_DATABASE=OLICOM A/S OUI:005083* ID_OUI_FROM_DATABASE=GILBARCO, INC. OUI:0050CF* ID_OUI_FROM_DATABASE=VANLINK COMMUNICATION TECHNOLOGY RESEARCH INSTITUTE OUI:005008* ID_OUI_FROM_DATABASE=TIVA MICROCOMPUTER CORP. (TMC) OUI:005001* ID_OUI_FROM_DATABASE=YAMASHITA SYSTEMS CORP. OUI:0050B5* ID_OUI_FROM_DATABASE=FICHET-BAUCHE OUI:0050B0* ID_OUI_FROM_DATABASE=TECHNOLOGY ATLANTA CORPORATION OUI:00504E* ID_OUI_FROM_DATABASE=SIERRA MONITOR CORP. OUI:00504D* ID_OUI_FROM_DATABASE=Tokyo Electron Device Limited OUI:0050F7* ID_OUI_FROM_DATABASE=VENTURE MANUFACTURING (SINGAPORE) LTD. OUI:005029* ID_OUI_FROM_DATABASE=1394 PRINTER WORKING GROUP OUI:00E08D* ID_OUI_FROM_DATABASE=PRESSURE SYSTEMS, INC. OUI:00E040* ID_OUI_FROM_DATABASE=DeskStation Technology, Inc. OUI:00E0D6* ID_OUI_FROM_DATABASE=COMPUTER & COMMUNICATION RESEARCH LAB. OUI:00E07E* ID_OUI_FROM_DATABASE=WALT DISNEY IMAGINEERING OUI:00E094* ID_OUI_FROM_DATABASE=OSAI SRL OUI:00E032* ID_OUI_FROM_DATABASE=MISYS FINANCIAL SYSTEMS, LTD. OUI:00E06B* ID_OUI_FROM_DATABASE=W&G SPECIAL PRODUCTS OUI:00E01C* ID_OUI_FROM_DATABASE=Cradlepoint, Inc OUI:00E076* ID_OUI_FROM_DATABASE=DEVELOPMENT CONCEPTS, INC. OUI:00E0A7* ID_OUI_FROM_DATABASE=IPC INFORMATION SYSTEMS, INC. OUI:00E0A4* ID_OUI_FROM_DATABASE=ESAOTE S.p.A. OUI:00E080* ID_OUI_FROM_DATABASE=CONTROL RESOURCES CORPORATION OUI:00E0CC* ID_OUI_FROM_DATABASE=HERO SYSTEMS, LTD. OUI:00E099* ID_OUI_FROM_DATABASE=SAMSON AG OUI:0010E9* ID_OUI_FROM_DATABASE=RAIDTEC LTD. OUI:001003* ID_OUI_FROM_DATABASE=IMATRON, INC. OUI:00105A* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:0010A9* ID_OUI_FROM_DATABASE=ADHOC TECHNOLOGIES OUI:000400* ID_OUI_FROM_DATABASE=LEXMARK INTERNATIONAL, INC. OUI:00101A* ID_OUI_FROM_DATABASE=PictureTel Corp. OUI:001097* ID_OUI_FROM_DATABASE=WinNet Metropolitan Communications Systems, Inc. OUI:00106F* ID_OUI_FROM_DATABASE=TRENTON TECHNOLOGY INC. OUI:0010C6* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. OUI:0010DA* ID_OUI_FROM_DATABASE=Kollmorgen Corp OUI:0010DF* ID_OUI_FROM_DATABASE=RISE COMPUTER INC. OUI:00109E* ID_OUI_FROM_DATABASE=AWARE, INC. OUI:001072* ID_OUI_FROM_DATABASE=GVN TECHNOLOGIES, INC. OUI:00E019* ID_OUI_FROM_DATABASE=ING. GIORDANO ELETTRONICA OUI:00E0D7* ID_OUI_FROM_DATABASE=SUNSHINE ELECTRONICS, INC. OUI:00E0DA* ID_OUI_FROM_DATABASE=Alcatel North America ESD OUI:00E068* ID_OUI_FROM_DATABASE=MERRIMAC SYSTEMS INC. OUI:00E01D* ID_OUI_FROM_DATABASE=WebTV NETWORKS, INC. OUI:00E01F* ID_OUI_FROM_DATABASE=AVIDIA Systems, Inc. OUI:00E056* ID_OUI_FROM_DATABASE=HOLONTECH CORPORATION OUI:00E0C9* ID_OUI_FROM_DATABASE=AutomatedLogic Corporation OUI:00E030* ID_OUI_FROM_DATABASE=MELITA INTERNATIONAL CORP. OUI:00E0BA* ID_OUI_FROM_DATABASE=BERGHOF AUTOMATIONSTECHNIK GmbH OUI:00E0B2* ID_OUI_FROM_DATABASE=TELMAX COMMUNICATIONS CORP. OUI:00E0EF* ID_OUI_FROM_DATABASE=DIONEX OUI:00E0BD* ID_OUI_FROM_DATABASE=INTERFACE SYSTEMS, INC. OUI:00E071* ID_OUI_FROM_DATABASE=EPIS MICROCOMPUTER OUI:00E0A6* ID_OUI_FROM_DATABASE=TELOGY NETWORKS, INC. OUI:00E026* ID_OUI_FROM_DATABASE=Redlake MASD LLC OUI:00E0B8* ID_OUI_FROM_DATABASE=GATEWAY 2000 OUI:00E088* ID_OUI_FROM_DATABASE=LTX-Credence CORPORATION OUI:00E07C* ID_OUI_FROM_DATABASE=METTLER-TOLEDO, INC. OUI:00E08C* ID_OUI_FROM_DATABASE=NEOPARADIGM LABS, INC. OUI:00E061* ID_OUI_FROM_DATABASE=EdgePoint Networks, Inc. OUI:00E06E* ID_OUI_FROM_DATABASE=FAR SYSTEMS S.p.A. OUI:00E01B* ID_OUI_FROM_DATABASE=SPHERE COMMUNICATIONS, INC. OUI:00E0AE* ID_OUI_FROM_DATABASE=XAQTI CORPORATION OUI:00E0C8* ID_OUI_FROM_DATABASE=VIRTUAL ACCESS, LTD. OUI:00101D* ID_OUI_FROM_DATABASE=WINBOND ELECTRONICS CORP. OUI:00105F* ID_OUI_FROM_DATABASE=ZODIAC DATA SYSTEMS OUI:0010CB* ID_OUI_FROM_DATABASE=FACIT K.K. OUI:00108C* ID_OUI_FROM_DATABASE=FUJITSU TELECOMMUNICATIONS EUROPE, LTD. OUI:001075* ID_OUI_FROM_DATABASE=Segate Technology LLC OUI:001058* ID_OUI_FROM_DATABASE=ArrowPoint Communications OUI:0010A8* ID_OUI_FROM_DATABASE=RELIANCE COMPUTER CORP. OUI:0010AA* ID_OUI_FROM_DATABASE=MEDIA4, INC. OUI:0010E8* ID_OUI_FROM_DATABASE=TELOCITY, INCORPORATED OUI:001010* ID_OUI_FROM_DATABASE=INITIO CORPORATION OUI:00E007* ID_OUI_FROM_DATABASE=Avaya ECS Ltd OUI:001022* ID_OUI_FROM_DATABASE=SatCom Media Corporation OUI:0010C7* ID_OUI_FROM_DATABASE=DATA TRANSMISSION NETWORK OUI:001098* ID_OUI_FROM_DATABASE=STARNET TECHNOLOGIES, INC. OUI:001096* ID_OUI_FROM_DATABASE=TRACEWELL SYSTEMS, INC. OUI:001082* ID_OUI_FROM_DATABASE=JNA TELECOMMUNICATIONS LIMITED OUI:001021* ID_OUI_FROM_DATABASE=ENCANTO NETWORKS, INC. OUI:0010CE* ID_OUI_FROM_DATABASE=VOLAMP, LTD. OUI:0010B2* ID_OUI_FROM_DATABASE=COACTIVE AESTHETICS OUI:00109A* ID_OUI_FROM_DATABASE=NETLINE OUI:0010EA* ID_OUI_FROM_DATABASE=ADEPT TECHNOLOGY OUI:0010BD* ID_OUI_FROM_DATABASE=THE TELECOMMUNICATION TECHNOLOGY COMMITTEE (TTC) OUI:0060D5* ID_OUI_FROM_DATABASE=MIYACHI TECHNOS CORP. OUI:006099* ID_OUI_FROM_DATABASE=SBE, Inc. OUI:0060FD* ID_OUI_FROM_DATABASE=NetICs, Inc. OUI:0060B5* ID_OUI_FROM_DATABASE=KEBA GmbH OUI:006027* ID_OUI_FROM_DATABASE=Superior Modular Products OUI:0060C1* ID_OUI_FROM_DATABASE=WaveSpan Corporation OUI:006041* ID_OUI_FROM_DATABASE=Yokogawa Electric Corporation OUI:006005* ID_OUI_FROM_DATABASE=FEEDBACK DATA LTD. OUI:00607B* ID_OUI_FROM_DATABASE=FORE SYSTEMS, INC. OUI:00609C* ID_OUI_FROM_DATABASE=Perkin-Elmer Incorporated OUI:006007* ID_OUI_FROM_DATABASE=ACRES GAMING, INC. OUI:006035* ID_OUI_FROM_DATABASE=DALLAS SEMICONDUCTOR, INC. OUI:0060F1* ID_OUI_FROM_DATABASE=EXP COMPUTER, INC. OUI:006040* ID_OUI_FROM_DATABASE=NETRO CORP. OUI:006034* ID_OUI_FROM_DATABASE=ROBERT BOSCH GmbH OUI:0060BA* ID_OUI_FROM_DATABASE=SAHARA NETWORKS, INC. OUI:006096* ID_OUI_FROM_DATABASE=T.S. MICROTECH INC. OUI:00603A* ID_OUI_FROM_DATABASE=QUICK CONTROLS LTD. OUI:0060AC* ID_OUI_FROM_DATABASE=RESILIENCE CORPORATION OUI:0060EB* ID_OUI_FROM_DATABASE=FOURTHTRACK SYSTEMS OUI:00606D* ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORP. OUI:006014* ID_OUI_FROM_DATABASE=EDEC CO., LTD. OUI:0060E1* ID_OUI_FROM_DATABASE=ORCKIT COMMUNICATIONS LTD. OUI:006062* ID_OUI_FROM_DATABASE=TELESYNC, INC. OUI:006038* ID_OUI_FROM_DATABASE=Nortel Networks OUI:006095* ID_OUI_FROM_DATABASE=ACCU-TIME SYSTEMS, INC. OUI:00A016* ID_OUI_FROM_DATABASE=MICROPOLIS CORP. OUI:00A01C* ID_OUI_FROM_DATABASE=NASCENT NETWORKS CORPORATION OUI:00A0FC* ID_OUI_FROM_DATABASE=IMAGE SCIENCES, INC. OUI:00A0B7* ID_OUI_FROM_DATABASE=CORDANT, INC. OUI:00A037* ID_OUI_FROM_DATABASE=Mindray DS USA, Inc. OUI:00A04C* ID_OUI_FROM_DATABASE=INNOVATIVE SYSTEMS & TECHNOLOGIES, INC. OUI:00A0E9* ID_OUI_FROM_DATABASE=ELECTRONIC RETAILING SYSTEMS INTERNATIONAL OUI:006078* ID_OUI_FROM_DATABASE=POWER MEASUREMENT LTD. OUI:00600D* ID_OUI_FROM_DATABASE=Digital Logic GmbH OUI:00608A* ID_OUI_FROM_DATABASE=CITADEL COMPUTER OUI:00A05D* ID_OUI_FROM_DATABASE=CS COMPUTER SYSTEME GmbH OUI:00A0BD* ID_OUI_FROM_DATABASE=I-TECH CORP. OUI:00A0B9* ID_OUI_FROM_DATABASE=EAGLE TECHNOLOGY, INC. OUI:00A069* ID_OUI_FROM_DATABASE=Symmetricom, Inc. OUI:00A07A* ID_OUI_FROM_DATABASE=ADVANCED PERIPHERALS TECHNOLOGIES, INC. OUI:00A04E* ID_OUI_FROM_DATABASE=VOELKER TECHNOLOGIES, INC. OUI:00A05A* ID_OUI_FROM_DATABASE=KOFAX IMAGE PRODUCTS OUI:00A093* ID_OUI_FROM_DATABASE=B/E AEROSPACE, Inc. OUI:00A0BF* ID_OUI_FROM_DATABASE=WIRELESS DATA GROUP MOTOROLA OUI:00609F* ID_OUI_FROM_DATABASE=PHAST CORPORATION OUI:006067* ID_OUI_FROM_DATABASE=ACER NETXUS INC. OUI:00600C* ID_OUI_FROM_DATABASE=Eurotech Inc. OUI:006025* ID_OUI_FROM_DATABASE=ACTIVE IMAGING PLC OUI:006071* ID_OUI_FROM_DATABASE=MIDAS LAB, INC. OUI:0060A7* ID_OUI_FROM_DATABASE=MICROSENS GmbH & CO. KG OUI:0060FC* ID_OUI_FROM_DATABASE=CONSERVATION THROUGH INNOVATION LTD. OUI:0060D4* ID_OUI_FROM_DATABASE=ELDAT COMMUNICATION LTD. OUI:006085* ID_OUI_FROM_DATABASE=Storage Concepts OUI:0060D3* ID_OUI_FROM_DATABASE=AT&T OUI:006018* ID_OUI_FROM_DATABASE=STELLAR ONE CORPORATION OUI:00602B* ID_OUI_FROM_DATABASE=PEAK AUDIO OUI:00606F* ID_OUI_FROM_DATABASE=CLARION CORPORATION OF AMERICA OUI:0060ED* ID_OUI_FROM_DATABASE=RICARDO TEST AUTOMATION LTD. OUI:0060F6* ID_OUI_FROM_DATABASE=NEXTEST COMMUNICATIONS PRODUCTS, INC. OUI:0060DD* ID_OUI_FROM_DATABASE=MYRICOM, INC. OUI:006092* ID_OUI_FROM_DATABASE=MICRO/SYS, INC. OUI:006080* ID_OUI_FROM_DATABASE=MICROTRONIX DATACOM LTD. OUI:006068* ID_OUI_FROM_DATABASE=Dialogic Corporation OUI:0060DB* ID_OUI_FROM_DATABASE=NTP ELEKTRONIK A/S OUI:00A002* ID_OUI_FROM_DATABASE=LEEDS & NORTHRUP AUSTRALIA PTY LTD OUI:00A0E4* ID_OUI_FROM_DATABASE=OPTIQUEST OUI:00A01F* ID_OUI_FROM_DATABASE=TRICORD SYSTEMS, INC. OUI:00A0C0* ID_OUI_FROM_DATABASE=DIGITAL LINK CORP. OUI:00A043* ID_OUI_FROM_DATABASE=AMERICAN TECHNOLOGY LABS, INC. OUI:00A047* ID_OUI_FROM_DATABASE=INTEGRATED FITNESS CORP. OUI:00A00E* ID_OUI_FROM_DATABASE=VISUAL NETWORKS, INC. OUI:00A07C* ID_OUI_FROM_DATABASE=TONYANG NYLON CO., LTD. OUI:00A0EC* ID_OUI_FROM_DATABASE=TRANSMITTON LTD. OUI:00A07E* ID_OUI_FROM_DATABASE=AVID TECHNOLOGY, INC. OUI:00A035* ID_OUI_FROM_DATABASE=CYLINK CORPORATION OUI:00A028* ID_OUI_FROM_DATABASE=CONNER PERIPHERALS OUI:00A0C7* ID_OUI_FROM_DATABASE=TADIRAN TELECOMMUNICATIONS OUI:00E0BE* ID_OUI_FROM_DATABASE=GENROCO INTERNATIONAL, INC. OUI:00E010* ID_OUI_FROM_DATABASE=HESS SB-AUTOMATENBAU GmbH OUI:00E0E9* ID_OUI_FROM_DATABASE=DATA LABS, INC. OUI:00E0A0* ID_OUI_FROM_DATABASE=WILTRON CO. OUI:00E024* ID_OUI_FROM_DATABASE=GADZOOX NETWORKS OUI:00E017* ID_OUI_FROM_DATABASE=EXXACT GmbH OUI:00603B* ID_OUI_FROM_DATABASE=AMTEC spa OUI:00E08B* ID_OUI_FROM_DATABASE=QLogic Corp. OUI:0020E5* ID_OUI_FROM_DATABASE=APEX DATA, INC. OUI:00207D* ID_OUI_FROM_DATABASE=ADVANCED COMPUTER APPLICATIONS OUI:0020D0* ID_OUI_FROM_DATABASE=VERSALYNX CORPORATION OUI:00206C* ID_OUI_FROM_DATABASE=EVERGREEN TECHNOLOGY CORP. OUI:002012* ID_OUI_FROM_DATABASE=CAMTRONICS MEDICAL SYSTEMS OUI:00200B* ID_OUI_FROM_DATABASE=OCTAGON SYSTEMS CORP. OUI:00209E* ID_OUI_FROM_DATABASE=BROWN'S OPERATING SYSTEM SERVICES, LTD. OUI:0020D7* ID_OUI_FROM_DATABASE=JAPAN MINICOMPUTER SYSTEMS CO., Ltd. OUI:0020FB* ID_OUI_FROM_DATABASE=OCTEL COMMUNICATIONS CORP. OUI:0020B1* ID_OUI_FROM_DATABASE=COMTECH RESEARCH INC. OUI:002033* ID_OUI_FROM_DATABASE=SYNAPSE TECHNOLOGIES, INC. OUI:002099* ID_OUI_FROM_DATABASE=BON ELECTRIC CO., LTD. OUI:0020AE* ID_OUI_FROM_DATABASE=ORNET DATA COMMUNICATION TECH. OUI:0020EA* ID_OUI_FROM_DATABASE=EFFICIENT NETWORKS, INC. OUI:0020FF* ID_OUI_FROM_DATABASE=SYMMETRICAL TECHNOLOGIES OUI:00208B* ID_OUI_FROM_DATABASE=LAPIS TECHNOLOGIES, INC. OUI:002069* ID_OUI_FROM_DATABASE=ISDN SYSTEMS CORPORATION OUI:0020BA* ID_OUI_FROM_DATABASE=CENTER FOR HIGH PERFORMANCE OUI:002006* ID_OUI_FROM_DATABASE=GARRETT COMMUNICATIONS, INC. OUI:00A0A2* ID_OUI_FROM_DATABASE=DIGICOM S.P.A. OUI:00A09B* ID_OUI_FROM_DATABASE=QPSX COMMUNICATIONS, LTD. OUI:00A054* ID_OUI_FROM_DATABASE=Private OUI:00A030* ID_OUI_FROM_DATABASE=CAPTOR NV/SA OUI:00A0B1* ID_OUI_FROM_DATABASE=FIRST VIRTUAL CORPORATION OUI:0020CB* ID_OUI_FROM_DATABASE=PRETEC ELECTRONICS CORP. OUI:0020AB* ID_OUI_FROM_DATABASE=MICRO INDUSTRIES CORP. OUI:00202D* ID_OUI_FROM_DATABASE=TAIYO CORPORATION OUI:00A088* ID_OUI_FROM_DATABASE=ESSENTIAL COMMUNICATIONS OUI:00A0FA* ID_OUI_FROM_DATABASE=Marconi Communication GmbH OUI:00A014* ID_OUI_FROM_DATABASE=CSIR OUI:00A064* ID_OUI_FROM_DATABASE=KVB/ANALECT OUI:00A07F* ID_OUI_FROM_DATABASE=GSM-SYNTEL, LTD. OUI:00A03E* ID_OUI_FROM_DATABASE=ATM FORUM OUI:00A050* ID_OUI_FROM_DATABASE=CYPRESS SEMICONDUCTOR OUI:00A098* ID_OUI_FROM_DATABASE=NetApp OUI:00A021* ID_OUI_FROM_DATABASE=General Dynamics OUI:00A0A8* ID_OUI_FROM_DATABASE=RENEX CORPORATION OUI:002049* ID_OUI_FROM_DATABASE=COMTRON, INC. OUI:002050* ID_OUI_FROM_DATABASE=KOREA COMPUTER INC. OUI:00203C* ID_OUI_FROM_DATABASE=EUROTIME AB OUI:002028* ID_OUI_FROM_DATABASE=WEST EGG SYSTEMS, INC. OUI:002014* ID_OUI_FROM_DATABASE=GLOBAL VIEW CO., LTD. OUI:002053* ID_OUI_FROM_DATABASE=HUNTSVILLE MICROSYSTEMS, INC. OUI:002001* ID_OUI_FROM_DATABASE=DSP SOLUTIONS, INC. OUI:00209C* ID_OUI_FROM_DATABASE=PRIMARY ACCESS CORP. OUI:0020C5* ID_OUI_FROM_DATABASE=EAGLE TECHNOLOGY OUI:002009* ID_OUI_FROM_DATABASE=PACKARD BELL ELEC., INC. OUI:002095* ID_OUI_FROM_DATABASE=RIVA ELECTRONICS OUI:00203F* ID_OUI_FROM_DATABASE=JUKI CORPORATION OUI:00C014* ID_OUI_FROM_DATABASE=TELEMATICS CALABASAS INT'L,INC OUI:00C045* ID_OUI_FROM_DATABASE=ISOLATION SYSTEMS, LTD. OUI:00C000* ID_OUI_FROM_DATABASE=LANOPTICS, LTD. OUI:00AA3C* ID_OUI_FROM_DATABASE=OLIVETTI TELECOM SPA (OLTECO) OUI:00C079* ID_OUI_FROM_DATABASE=FONSYS CO.,LTD. OUI:002011* ID_OUI_FROM_DATABASE=CANOPUS CO., LTD. OUI:00C00B* ID_OUI_FROM_DATABASE=NORCONTROL A.S. OUI:00C0C0* ID_OUI_FROM_DATABASE=SHORE MICROSYSTEMS, INC. OUI:00C00C* ID_OUI_FROM_DATABASE=RELIA TECHNOLGIES OUI:00A0E7* ID_OUI_FROM_DATABASE=CENTRAL DATA CORPORATION OUI:00A068* ID_OUI_FROM_DATABASE=BHP LIMITED OUI:00A0B3* ID_OUI_FROM_DATABASE=ZYKRONIX OUI:00A06E* ID_OUI_FROM_DATABASE=AUSTRON, INC. OUI:00A0BB* ID_OUI_FROM_DATABASE=HILAN GMBH OUI:00A0C8* ID_OUI_FROM_DATABASE=ADTRAN INC. OUI:00A017* ID_OUI_FROM_DATABASE=J B M CORPORATION OUI:0020D5* ID_OUI_FROM_DATABASE=VIPA GMBH OUI:002079* ID_OUI_FROM_DATABASE=MIKRON GMBH OUI:0020FA* ID_OUI_FROM_DATABASE=GDE SYSTEMS, INC. OUI:002007* ID_OUI_FROM_DATABASE=SFA, INC. OUI:002062* ID_OUI_FROM_DATABASE=SCORPION LOGIC, LTD. OUI:00200A* ID_OUI_FROM_DATABASE=SOURCE-COMM CORP. OUI:002000* ID_OUI_FROM_DATABASE=LEXMARK INTERNATIONAL, INC. OUI:002003* ID_OUI_FROM_DATABASE=PIXEL POWER LTD. OUI:0020B4* ID_OUI_FROM_DATABASE=TERMA ELEKTRONIK AS OUI:00205B* ID_OUI_FROM_DATABASE=Kentrox, LLC OUI:002030* ID_OUI_FROM_DATABASE=ANALOG & DIGITAL SYSTEMS OUI:0020A8* ID_OUI_FROM_DATABASE=SAST TECHNOLOGY CORP. OUI:002066* ID_OUI_FROM_DATABASE=GENERAL MAGIC, INC. OUI:002036* ID_OUI_FROM_DATABASE=BMC SOFTWARE OUI:0040BE* ID_OUI_FROM_DATABASE=BOEING DEFENSE & SPACE OUI:004036* ID_OUI_FROM_DATABASE=Zoom Telephonics, Inc OUI:004046* ID_OUI_FROM_DATABASE=UDC RESEARCH LIMITED OUI:00406A* ID_OUI_FROM_DATABASE=KENTEK INFORMATION SYSTEMS,INC OUI:0040F2* ID_OUI_FROM_DATABASE=JANICH & KLASS COMPUTERTECHNIK OUI:004082* ID_OUI_FROM_DATABASE=LABORATORY EQUIPMENT CORP. OUI:004022* ID_OUI_FROM_DATABASE=KLEVER COMPUTERS, INC. OUI:0040A2* ID_OUI_FROM_DATABASE=KINGSTAR TECHNOLOGY INC. OUI:0040B4* ID_OUI_FROM_DATABASE=NEXTCOM K.K. OUI:0040D4* ID_OUI_FROM_DATABASE=GAGE TALKER CORP. OUI:004038* ID_OUI_FROM_DATABASE=TALENT ELECTRIC INCORPORATED OUI:004018* ID_OUI_FROM_DATABASE=ADOBE SYSTEMS, INC. OUI:0040B0* ID_OUI_FROM_DATABASE=BYTEX CORPORATION, ENGINEERING OUI:004040* ID_OUI_FROM_DATABASE=RING ACCESS, INC. OUI:0080D7* ID_OUI_FROM_DATABASE=Fantum Engineering OUI:0080D9* ID_OUI_FROM_DATABASE=EMK Elektronik GmbH & Co. KG OUI:00806A* ID_OUI_FROM_DATABASE=ERI (EMPAC RESEARCH INC.) OUI:00403B* ID_OUI_FROM_DATABASE=SYNERJET INTERNATIONAL CORP. OUI:0040AB* ID_OUI_FROM_DATABASE=ROLAND DG CORPORATION OUI:0040D5* ID_OUI_FROM_DATABASE=Sartorius Mechatronics T&H GmbH OUI:004027* ID_OUI_FROM_DATABASE=SMC MASSACHUSETTS, INC. OUI:00409C* ID_OUI_FROM_DATABASE=TRANSWARE OUI:00405C* ID_OUI_FROM_DATABASE=FUTURE SYSTEMS, INC. OUI:00008C* ID_OUI_FROM_DATABASE=Alloy Computer Products (Australia) Pty Ltd OUI:004000* ID_OUI_FROM_DATABASE=PCI COMPONENTES DA AMZONIA LTD OUI:0040C5* ID_OUI_FROM_DATABASE=MICOM COMMUNICATIONS INC. OUI:0040AA* ID_OUI_FROM_DATABASE=Metso Automation OUI:004023* ID_OUI_FROM_DATABASE=LOGIC CORPORATION OUI:0040A4* ID_OUI_FROM_DATABASE=ROSE ELECTRONICS OUI:004048* ID_OUI_FROM_DATABASE=SMD INFORMATICA S.A. OUI:004025* ID_OUI_FROM_DATABASE=MOLECULAR DYNAMICS OUI:004010* ID_OUI_FROM_DATABASE=SONIC SYSTEMS, INC. OUI:0040CA* ID_OUI_FROM_DATABASE=FIRST INTERNAT'L COMPUTER, INC OUI:004050* ID_OUI_FROM_DATABASE=IRONICS, INCORPORATED OUI:00402B* ID_OUI_FROM_DATABASE=TRIGEM COMPUTER, INC. OUI:00C08C* ID_OUI_FROM_DATABASE=PERFORMANCE TECHNOLOGIES, INC. OUI:00C02B* ID_OUI_FROM_DATABASE=GERLOFF GESELLSCHAFT FUR OUI:00C0A7* ID_OUI_FROM_DATABASE=SEEL LTD. OUI:0040B3* ID_OUI_FROM_DATABASE=ParTech Inc. OUI:00407D* ID_OUI_FROM_DATABASE=EXTENSION TECHNOLOGY CORP. OUI:004079* ID_OUI_FROM_DATABASE=JUKO MANUFACTURE COMPANY, LTD. OUI:0040D9* ID_OUI_FROM_DATABASE=AMERICAN MEGATRENDS INC. OUI:004011* ID_OUI_FROM_DATABASE=ANDOVER CONTROLS CORPORATION OUI:0040C1* ID_OUI_FROM_DATABASE=BIZERBA-WERKE WILHEIM KRAUT OUI:00C06B* ID_OUI_FROM_DATABASE=OSI PLUS CORPORATION OUI:00C06A* ID_OUI_FROM_DATABASE=ZAHNER-ELEKTRIK GMBH & CO. KG OUI:00C097* ID_OUI_FROM_DATABASE=ARCHIPEL SA OUI:00C072* ID_OUI_FROM_DATABASE=KNX LTD. OUI:00C0EC* ID_OUI_FROM_DATABASE=DAUPHIN TECHNOLOGY OUI:00C066* ID_OUI_FROM_DATABASE=DOCUPOINT, INC. OUI:00C028* ID_OUI_FROM_DATABASE=JASCO CORPORATION OUI:00C0DC* ID_OUI_FROM_DATABASE=EOS TECHNOLOGIES, INC. OUI:00C02D* ID_OUI_FROM_DATABASE=FUJI PHOTO FILM CO., LTD. OUI:00C0BD* ID_OUI_FROM_DATABASE=INEX TECHNOLOGIES, INC. OUI:00C054* ID_OUI_FROM_DATABASE=NETWORK PERIPHERALS, LTD. OUI:00C0D5* ID_OUI_FROM_DATABASE=Werbeagentur Jürgen Siebert OUI:00C044* ID_OUI_FROM_DATABASE=EMCOM CORPORATION OUI:00C050* ID_OUI_FROM_DATABASE=TOYO DENKI SEIZO K.K. OUI:00408A* ID_OUI_FROM_DATABASE=TPS TELEPROCESSING SYS. GMBH OUI:0040FD* ID_OUI_FROM_DATABASE=LXE OUI:00403D* ID_OUI_FROM_DATABASE=Teradata Corporation OUI:0040E0* ID_OUI_FROM_DATABASE=ATOMWIDE LTD. OUI:00408C* ID_OUI_FROM_DATABASE=AXIS COMMUNICATIONS AB OUI:004068* ID_OUI_FROM_DATABASE=EXTENDED SYSTEMS OUI:0040BA* ID_OUI_FROM_DATABASE=ALLIANT COMPUTER SYSTEMS CORP. OUI:004069* ID_OUI_FROM_DATABASE=LEMCOM SYSTEMS, INC. OUI:0040F8* ID_OUI_FROM_DATABASE=SYSTEMHAUS DISCOM OUI:004077* ID_OUI_FROM_DATABASE=MAXTON TECHNOLOGY CORPORATION OUI:0040E7* ID_OUI_FROM_DATABASE=ARNOS INSTRUMENTS & COMPUTER OUI:0040AC* ID_OUI_FROM_DATABASE=SUPER WORKSTATION, INC. OUI:00C0AC* ID_OUI_FROM_DATABASE=GAMBIT COMPUTER COMMUNICATIONS OUI:00C02C* ID_OUI_FROM_DATABASE=CENTRUM COMMUNICATIONS, INC. OUI:00C0ED* ID_OUI_FROM_DATABASE=US ARMY ELECTRONIC OUI:00C0D1* ID_OUI_FROM_DATABASE=COMTREE TECHNOLOGY CORPORATION OUI:00C0D2* ID_OUI_FROM_DATABASE=SYNTELLECT, INC. OUI:00C0FB* ID_OUI_FROM_DATABASE=ADVANCED TECHNOLOGY LABS OUI:00C092* ID_OUI_FROM_DATABASE=MENNEN MEDICAL INC. OUI:00C06C* ID_OUI_FROM_DATABASE=SVEC COMPUTER CORP. OUI:00C02E* ID_OUI_FROM_DATABASE=NETWIZ OUI:00C05B* ID_OUI_FROM_DATABASE=NETWORKS NORTHWEST, INC. OUI:00C0BF* ID_OUI_FROM_DATABASE=TECHNOLOGY CONCEPTS, LTD. OUI:00C0C9* ID_OUI_FROM_DATABASE=ELSAG BAILEY PROCESS OUI:00809D* ID_OUI_FROM_DATABASE=Commscraft Ltd. OUI:008017* ID_OUI_FROM_DATABASE=PFU LIMITED OUI:0080F8* ID_OUI_FROM_DATABASE=MIZAR, INC. OUI:008024* ID_OUI_FROM_DATABASE=KALPANA, INC. OUI:008074* ID_OUI_FROM_DATABASE=FISHER CONTROLS OUI:008021* ID_OUI_FROM_DATABASE=Alcatel Canada Inc. OUI:000055* ID_OUI_FROM_DATABASE=COMMISSARIAT A L`ENERGIE ATOM. OUI:000086* ID_OUI_FROM_DATABASE=MEGAHERTZ CORPORATION OUI:000092* ID_OUI_FROM_DATABASE=COGENT DATA TECHNOLOGIES OUI:008068* ID_OUI_FROM_DATABASE=YAMATECH SCIENTIFIC LTD. OUI:0080F2* ID_OUI_FROM_DATABASE=RAYCOM SYSTEMS INC OUI:0080EA* ID_OUI_FROM_DATABASE=ADVA Optical Networking Ltd. OUI:008025* ID_OUI_FROM_DATABASE=STOLLMANN GMBH OUI:000067* ID_OUI_FROM_DATABASE=SOFT * RITE, INC. OUI:0000E8* ID_OUI_FROM_DATABASE=ACCTON TECHNOLOGY CORP. OUI:0000B2* ID_OUI_FROM_DATABASE=TELEVIDEO SYSTEMS, INC. OUI:0000EE* ID_OUI_FROM_DATABASE=NETWORK DESIGNERS, LTD. OUI:000089* ID_OUI_FROM_DATABASE=CAYMAN SYSTEMS INC. OUI:0000F0* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRONICS CO., LTD. OUI:000021* ID_OUI_FROM_DATABASE=SUREMAN COMP. & COMMUN. CORP. OUI:0000CF* ID_OUI_FROM_DATABASE=HAYES MICROCOMPUTER PRODUCTS OUI:0000A4* ID_OUI_FROM_DATABASE=ACORN COMPUTERS LIMITED OUI:000018* ID_OUI_FROM_DATABASE=WEBSTER COMPUTER CORPORATION OUI:008033* ID_OUI_FROM_DATABASE=EMS Aviation, Inc. OUI:008052* ID_OUI_FROM_DATABASE=TECHNICALLY ELITE CONCEPTS OUI:00804F* ID_OUI_FROM_DATABASE=DAIKIN INDUSTRIES, LTD. OUI:00806D* ID_OUI_FROM_DATABASE=CENTURY SYSTEMS CORP. OUI:00802D* ID_OUI_FROM_DATABASE=XYLOGICS INC OUI:008048* ID_OUI_FROM_DATABASE=COMPEX INCORPORATED OUI:008085* ID_OUI_FROM_DATABASE=H-THREE SYSTEMS CORPORATION OUI:008014* ID_OUI_FROM_DATABASE=ESPRIT SYSTEMS OUI:0080B4* ID_OUI_FROM_DATABASE=SOPHIA SYSTEMS OUI:00807F* ID_OUI_FROM_DATABASE=DY-4 INCORPORATED OUI:0000E4* ID_OUI_FROM_DATABASE=IN2 GROUPE INTERTECHNIQUE OUI:000079* ID_OUI_FROM_DATABASE=NETWORTH INCORPORATED OUI:000075* ID_OUI_FROM_DATABASE=Nortel Networks OUI:004009* ID_OUI_FROM_DATABASE=TACHIBANA TECTRON CO., LTD. OUI:00409E* ID_OUI_FROM_DATABASE=CONCURRENT TECHNOLOGIES LTD. OUI:008092* ID_OUI_FROM_DATABASE=Silex Technology, Inc. OUI:008011* ID_OUI_FROM_DATABASE=DIGITAL SYSTEMS INT'L. INC. OUI:008044* ID_OUI_FROM_DATABASE=SYSTECH COMPUTER CORP. OUI:00808A* ID_OUI_FROM_DATABASE=SUMMIT MICROSYSTEMS CORP. OUI:0080E3* ID_OUI_FROM_DATABASE=CORAL NETWORK CORPORATION OUI:008072* ID_OUI_FROM_DATABASE=MICROPLEX SYSTEMS LTD. OUI:008054* ID_OUI_FROM_DATABASE=FRONTIER TECHNOLOGIES CORP. OUI:0080AE* ID_OUI_FROM_DATABASE=HUGHES NETWORK SYSTEMS OUI:0080AF* ID_OUI_FROM_DATABASE=ALLUMER CO., LTD. OUI:0080EC* ID_OUI_FROM_DATABASE=SUPERCOMPUTING SOLUTIONS, INC. OUI:0080A4* ID_OUI_FROM_DATABASE=LIBERTY ELECTRONICS OUI:008073* ID_OUI_FROM_DATABASE=DWB ASSOCIATES OUI:00802B* ID_OUI_FROM_DATABASE=INTEGRATED MARKETING CO OUI:0080BE* ID_OUI_FROM_DATABASE=ARIES RESEARCH OUI:008027* ID_OUI_FROM_DATABASE=ADAPTIVE SYSTEMS, INC. OUI:0080E2* ID_OUI_FROM_DATABASE=T.D.I. CO., LTD. OUI:0040EE* ID_OUI_FROM_DATABASE=OPTIMEM OUI:00405E* ID_OUI_FROM_DATABASE=NORTH HILLS ISRAEL OUI:004072* ID_OUI_FROM_DATABASE=Applied Innovation Inc. OUI:004031* ID_OUI_FROM_DATABASE=KOKUSAI ELECTRIC CO., LTD OUI:00400C* ID_OUI_FROM_DATABASE=GENERAL MICRO SYSTEMS, INC. OUI:0040E6* ID_OUI_FROM_DATABASE=C.A.E.N. OUI:0040FC* ID_OUI_FROM_DATABASE=IBR COMPUTER TECHNIK GMBH OUI:004001* ID_OUI_FROM_DATABASE=Zero One Technology Co. Ltd. OUI:004002* ID_OUI_FROM_DATABASE=PERLE SYSTEMS LIMITED OUI:0080DB* ID_OUI_FROM_DATABASE=GRAPHON CORPORATION OUI:0080B1* ID_OUI_FROM_DATABASE=SOFTCOM A/S OUI:0080D8* ID_OUI_FROM_DATABASE=NETWORK PERIPHERALS INC. OUI:0080AB* ID_OUI_FROM_DATABASE=DUKANE NETWORK INTEGRATION OUI:00809B* ID_OUI_FROM_DATABASE=JUSTSYSTEM CORPORATION OUI:008089* ID_OUI_FROM_DATABASE=TECNETICS (PTY) LTD. OUI:000039* ID_OUI_FROM_DATABASE=TOSHIBA CORPORATION OUI:0000CB* ID_OUI_FROM_DATABASE=COMPU-SHACK ELECTRONIC GMBH OUI:0000D1* ID_OUI_FROM_DATABASE=ADAPTEC INCORPORATED OUI:0000B6* ID_OUI_FROM_DATABASE=MICRO-MATIC RESEARCH OUI:000066* ID_OUI_FROM_DATABASE=TALARIS SYSTEMS, INC. OUI:000014* ID_OUI_FROM_DATABASE=NETRONIX OUI:000072* ID_OUI_FROM_DATABASE=MINIWARE TECHNOLOGY OUI:0000AB* ID_OUI_FROM_DATABASE=LOGIC MODELING CORPORATION OUI:000029* ID_OUI_FROM_DATABASE=IMC NETWORKS CORP. OUI:0080CD* ID_OUI_FROM_DATABASE=MICRONICS COMPUTER, INC. OUI:008083* ID_OUI_FROM_DATABASE=AMDAHL OUI:008003* ID_OUI_FROM_DATABASE=HYTEC ELECTRONICS LTD. OUI:00801B* ID_OUI_FROM_DATABASE=KODIAK TECHNOLOGY OUI:0080CC* ID_OUI_FROM_DATABASE=MICROWAVE BYPASS SYSTEMS OUI:080079* ID_OUI_FROM_DATABASE=THE DROID WORKS OUI:080077* ID_OUI_FROM_DATABASE=TSL COMMUNICATIONS LTD. OUI:080071* ID_OUI_FROM_DATABASE=MATRA (DSIE) OUI:08006A* ID_OUI_FROM_DATABASE=ATT BELL LABORATORIES OUI:08005F* ID_OUI_FROM_DATABASE=SABER TECHNOLOGY CORP. OUI:08005C* ID_OUI_FROM_DATABASE=FOUR PHASE SYSTEMS OUI:08005B* ID_OUI_FROM_DATABASE=VTA TECHNOLOGIES INC. OUI:080058* ID_OUI_FROM_DATABASE=SYSTEMS CONCEPTS OUI:080050* ID_OUI_FROM_DATABASE=DAISY SYSTEMS CORP. OUI:080052* ID_OUI_FROM_DATABASE=INSYSTEC OUI:080047* ID_OUI_FROM_DATABASE=SEQUENT COMPUTER SYSTEMS INC. OUI:080045* ID_OUI_FROM_DATABASE=CONCURRENT COMPUTER CORP. OUI:080044* ID_OUI_FROM_DATABASE=DAVID SYSTEMS INC. OUI:080041* ID_OUI_FROM_DATABASE=RACAL-MILGO INFORMATION SYS.. OUI:080038* ID_OUI_FROM_DATABASE=BULL S.A.S. OUI:08003C* ID_OUI_FROM_DATABASE=SCHLUMBERGER WELL SERVICES OUI:080034* ID_OUI_FROM_DATABASE=FILENET CORPORATION OUI:08002C* ID_OUI_FROM_DATABASE=BRITTON LEE INC. OUI:0000B9* ID_OUI_FROM_DATABASE=MCDONNELL DOUGLAS COMPUTER SYS OUI:00002D* ID_OUI_FROM_DATABASE=CHROMATICS INC OUI:00004A* ID_OUI_FROM_DATABASE=ADC CODENOLL TECHNOLOGY CORP. OUI:0000C0* ID_OUI_FROM_DATABASE=WESTERN DIGITAL CORPORATION OUI:000040* ID_OUI_FROM_DATABASE=APPLICON, INC. OUI:00005D* ID_OUI_FROM_DATABASE=CS TELECOM OUI:08008E* ID_OUI_FROM_DATABASE=Tandem Computers OUI:080086* ID_OUI_FROM_DATABASE=KONICA MINOLTA HOLDINGS, INC. OUI:080083* ID_OUI_FROM_DATABASE=Seiko Instruments Inc. OUI:080080* ID_OUI_FROM_DATABASE=AES DATA INC. OUI:080030* ID_OUI_FROM_DATABASE=ROYAL MELBOURNE INST OF TECH OUI:080064* ID_OUI_FROM_DATABASE=Sitasys AG OUI:00DD09* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:08008A* ID_OUI_FROM_DATABASE=PerfTech, Inc. OUI:00DD04* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:080066* ID_OUI_FROM_DATABASE=AGFA CORPORATION OUI:08001A* ID_OUI_FROM_DATABASE=TIARA/ 10NET OUI:080090* ID_OUI_FROM_DATABASE=SONOMA SYSTEMS OUI:08000B* ID_OUI_FROM_DATABASE=UNISYS CORPORATION OUI:080017* ID_OUI_FROM_DATABASE=NATIONAL SEMICONDUCTOR OUI:00005E* ID_OUI_FROM_DATABASE=ICANN, IANA Department OUI:0000AF* ID_OUI_FROM_DATABASE=Canberra Industries, Inc. OUI:0000EC* ID_OUI_FROM_DATABASE=MICROPROCESS OUI:00009E* ID_OUI_FROM_DATABASE=MARLI S.A. OUI:000042* ID_OUI_FROM_DATABASE=METIER MANAGEMENT SYSTEMS LTD. OUI:00008D* ID_OUI_FROM_DATABASE=Cryptek Inc. OUI:000065* ID_OUI_FROM_DATABASE=Network General Corporation OUI:00004D* ID_OUI_FROM_DATABASE=DCI CORPORATION OUI:080024* ID_OUI_FROM_DATABASE=10NET COMMUNICATIONS/DCA OUI:08001E* ID_OUI_FROM_DATABASE=APOLLO COMPUTER INC. OUI:08001B* ID_OUI_FROM_DATABASE=EMC Corporation OUI:00DD0D* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:AA0002* ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION OUI:080005* ID_OUI_FROM_DATABASE=SYMBOLICS INC. OUI:000000* ID_OUI_FROM_DATABASE=XEROX CORPORATION OUI:0040D6* ID_OUI_FROM_DATABASE=LOCAMATION B.V. OUI:800010* ID_OUI_FROM_DATABASE=ATT BELL LABORATORIES OUI:AA0003* ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION OUI:080008* ID_OUI_FROM_DATABASE=BOLT BERANEK AND NEWMAN INC. OUI:08000E* ID_OUI_FROM_DATABASE=NCR CORPORATION OUI:00006F* ID_OUI_FROM_DATABASE=Madge Ltd. OUI:00005A* ID_OUI_FROM_DATABASE=SysKonnect GmbH OUI:000023* ID_OUI_FROM_DATABASE=ABB INDUSTRIAL SYSTEMS AB OUI:000045* ID_OUI_FROM_DATABASE=FORD AEROSPACE & COMM. CORP. OUI:0000BC* ID_OUI_FROM_DATABASE=Rockwell Automation OUI:0000C3* ID_OUI_FROM_DATABASE=HARRIS CORP COMPUTER SYS DIV OUI:000004* ID_OUI_FROM_DATABASE=XEROX CORPORATION OUI:000009* ID_OUI_FROM_DATABASE=XEROX CORPORATION OUI:00003D* ID_OUI_FROM_DATABASE=UNISYS OUI:F82C18* ID_OUI_FROM_DATABASE=2Wire Inc OUI:00173F* ID_OUI_FROM_DATABASE=Belkin International Inc. OUI:388602* ID_OUI_FROM_DATABASE=Flexoptix GmbH OUI:F4EB38* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:001E74* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:00604C* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:002691* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:C0D044* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:6C2E85* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:CC33BB* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:681590* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:5464D9* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:00023F* ID_OUI_FROM_DATABASE=COMPAL ELECTRONICS, INC. OUI:0080C2* ID_OUI_FROM_DATABASE=IEEE 802.1 OUI:C46699* ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. OUI:002067* ID_OUI_FROM_DATABASE=Private OUI:383BC8* ID_OUI_FROM_DATABASE=2Wire Inc OUI:DC7FA4* ID_OUI_FROM_DATABASE=2Wire Inc OUI:1100AA* ID_OUI_FROM_DATABASE=Private OUI:001288* ID_OUI_FROM_DATABASE=2Wire Inc OUI:001EC7* ID_OUI_FROM_DATABASE=2Wire Inc OUI:28162E* ID_OUI_FROM_DATABASE=2Wire Inc OUI:3CEA4F* ID_OUI_FROM_DATABASE=2Wire Inc OUI:848F69* ID_OUI_FROM_DATABASE=Dell Inc. OUI:90B11C* ID_OUI_FROM_DATABASE=Dell Inc. OUI:F8CAB8* ID_OUI_FROM_DATABASE=Dell Inc. OUI:24B6FD* ID_OUI_FROM_DATABASE=Dell Inc. OUI:000D56* ID_OUI_FROM_DATABASE=Dell Inc. OUI:00123F* ID_OUI_FROM_DATABASE=Dell Inc. OUI:001372* ID_OUI_FROM_DATABASE=Dell Inc. OUI:74867A* ID_OUI_FROM_DATABASE=Dell Inc. OUI:3417EB* ID_OUI_FROM_DATABASE=Dell Inc. OUI:EC8892* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:B07994* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:141AA3* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:CCC3EA* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:34BB26* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:40786A* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:0019B9* ID_OUI_FROM_DATABASE=Dell Inc. OUI:002219* ID_OUI_FROM_DATABASE=Dell Inc. OUI:00B0D0* ID_OUI_FROM_DATABASE=Dell Inc. OUI:5C260A* ID_OUI_FROM_DATABASE=Dell Inc. OUI:B083FE* ID_OUI_FROM_DATABASE=Dell Inc. OUI:141877* ID_OUI_FROM_DATABASE=Dell Inc. OUI:0024E8* ID_OUI_FROM_DATABASE=Dell Inc. OUI:A48E0A* ID_OUI_FROM_DATABASE=DeLaval International AB OUI:00215C* ID_OUI_FROM_DATABASE=Intel Corporate OUI:002315* ID_OUI_FROM_DATABASE=Intel Corporate OUI:001500* ID_OUI_FROM_DATABASE=Intel Corporate OUI:104A7D* ID_OUI_FROM_DATABASE=Intel Corporate OUI:A4C494* ID_OUI_FROM_DATABASE=Intel Corporate OUI:902E1C* ID_OUI_FROM_DATABASE=Intel Corporate OUI:3CFDFE* ID_OUI_FROM_DATABASE=Intel Corporate OUI:B8BF83* ID_OUI_FROM_DATABASE=Intel Corporate OUI:001DE1* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0022FB* ID_OUI_FROM_DATABASE=Intel Corporate OUI:081196* ID_OUI_FROM_DATABASE=Intel Corporate OUI:6036DD* ID_OUI_FROM_DATABASE=Intel Corporate OUI:A0369F* ID_OUI_FROM_DATABASE=Intel Corporate OUI:502DA2* ID_OUI_FROM_DATABASE=Intel Corporate OUI:4C79BA* ID_OUI_FROM_DATABASE=Intel Corporate OUI:4CEB42* ID_OUI_FROM_DATABASE=Intel Corporate OUI:606720* ID_OUI_FROM_DATABASE=Intel Corporate OUI:84A6C8* ID_OUI_FROM_DATABASE=Intel Corporate OUI:5891CF* ID_OUI_FROM_DATABASE=Intel Corporate OUI:88532E* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0024D7* ID_OUI_FROM_DATABASE=Intel Corporate OUI:C40938* ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD OUI:00AA02* ID_OUI_FROM_DATABASE=Intel Corporation OUI:5CD2E4* ID_OUI_FROM_DATABASE=Intel Corporate OUI:04BD88* ID_OUI_FROM_DATABASE=Aruba Networks OUI:000B86* ID_OUI_FROM_DATABASE=Aruba Networks OUI:8896F2* ID_OUI_FROM_DATABASE=Valeo Schalter und Sensoren GmbH OUI:80A589* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:0CCC26* ID_OUI_FROM_DATABASE=Airenetworks OUI:4CB0E8* ID_OUI_FROM_DATABASE=Beijing RongZhi xinghua technology co., LTD OUI:4C14A3* ID_OUI_FROM_DATABASE=TCL Technoly Electronics (Huizhou) Co., Ltd. OUI:F48E38* ID_OUI_FROM_DATABASE=Dell Inc. OUI:74DAEA* ID_OUI_FROM_DATABASE=Texas Instruments OUI:D887D5* ID_OUI_FROM_DATABASE=Leadcore Technology CO.,LTD OUI:00DA55* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:80D21D* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:705A0F* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:586356* ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED OUI:B046FC* ID_OUI_FROM_DATABASE=MitraStar Technology Corp. OUI:08A95A* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:6CADF8* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:54271E* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:008C54* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:F0842F* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:8CB864* ID_OUI_FROM_DATABASE=AcSiP Technology Corp. OUI:0020E0* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:0004E3* ID_OUI_FROM_DATABASE=Accton Technology Corp OUI:409558* ID_OUI_FROM_DATABASE=Aisino Corporation OUI:00D0C9* ID_OUI_FROM_DATABASE=ADVANTECH CO., LTD. OUI:002553* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:00238E* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:001CA2* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:0017C2* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:D0D412* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:000FA3* ID_OUI_FROM_DATABASE=Alpha Networks Inc. OUI:001D6A* ID_OUI_FROM_DATABASE=Alpha Networks Inc. OUI:0000F4* ID_OUI_FROM_DATABASE=Allied Telesis, Inc. OUI:10AE60* ID_OUI_FROM_DATABASE=Private OUI:F04F7C* ID_OUI_FROM_DATABASE=Private OUI:70F1A1* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:6CFAA7* ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. OUI:0024EF* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:6C0E0D* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:B4527D* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:E063E5* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:000E07* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:001A75* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:0016B8* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:001D28* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:001FE4* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:002298* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:0019A6* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001700* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0015A8* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:000E5C* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:000CE5* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0004BD* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:00E06F* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:386BBB* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0015CF* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0014E8* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:24FD52* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:2016D8* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:9CB70D* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:1C659D* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:F80BBE* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:DC4517* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:74F612* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:74E7C6* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:B81619* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:B077AC* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:145BD1* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:6CC1D2* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0025F2* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:002374* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:002641* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0026BA* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:002180* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0019C0* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001B9E* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:E0CA94* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:C0D962* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:00150C* ID_OUI_FROM_DATABASE=AVM GmbH OUI:744401* ID_OUI_FROM_DATABASE=NETGEAR OUI:E091F5* ID_OUI_FROM_DATABASE=NETGEAR OUI:001B2F* ID_OUI_FROM_DATABASE=NETGEAR OUI:00223F* ID_OUI_FROM_DATABASE=NETGEAR OUI:E0469A* ID_OUI_FROM_DATABASE=NETGEAR OUI:F40B93* ID_OUI_FROM_DATABASE=BlackBerry RTS OUI:68ED43* ID_OUI_FROM_DATABASE=BlackBerry RTS OUI:34BB1F* ID_OUI_FROM_DATABASE=BlackBerry RTS OUI:489D24* ID_OUI_FROM_DATABASE=BlackBerry RTS OUI:000F86* ID_OUI_FROM_DATABASE=BlackBerry RTS OUI:001333* ID_OUI_FROM_DATABASE=BaudTec Corporation OUI:507E5D* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:849CA6* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:1CC63C* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:C02506* ID_OUI_FROM_DATABASE=AVM GmbH OUI:0896D7* ID_OUI_FROM_DATABASE=AVM GmbH OUI:008EF2* ID_OUI_FROM_DATABASE=NETGEAR OUI:4494FC* ID_OUI_FROM_DATABASE=NETGEAR OUI:20E52A* ID_OUI_FROM_DATABASE=NETGEAR OUI:9CD36D* ID_OUI_FROM_DATABASE=NETGEAR OUI:C40415* ID_OUI_FROM_DATABASE=NETGEAR OUI:08BD43* ID_OUI_FROM_DATABASE=NETGEAR OUI:4C09D4* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:DC446D* ID_OUI_FROM_DATABASE=Allwinner Technology Co., Ltd OUI:BC620E* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:78F557* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:E02861* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:C4473F* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:000AF7* ID_OUI_FROM_DATABASE=Broadcom OUI:000DB6* ID_OUI_FROM_DATABASE=Broadcom OUI:18C086* ID_OUI_FROM_DATABASE=Broadcom OUI:C03E0F* ID_OUI_FROM_DATABASE=BSkyB Ltd OUI:0020D4* ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. OUI:00001D* ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. OUI:0060BB* ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. OUI:D0542D* ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. OUI:001FC7* ID_OUI_FROM_DATABASE=Casio Hitachi Mobile Communications Co., Ltd. OUI:ACEE9E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:C08997* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:2827BF* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:F05B7B* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:7CF90E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:AC5A14* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B0C559* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:BCD11F* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:A0B4A5* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:80656D* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:48137E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E83A12* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:9C0298* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:6C8336* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B8C68E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:74458A* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:A49A58* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B4EF39* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:14A364* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:3CA10D* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:206E9C* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:183F47* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:0C715D* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:0C1420* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:A80600* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:6CF373* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:90F1AA* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:C4576E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:78BDBC* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:3872C0* ID_OUI_FROM_DATABASE=Comtrend Corporation OUI:F4068D* ID_OUI_FROM_DATABASE=devolo AG OUI:000BCA* ID_OUI_FROM_DATABASE=DATAVAN TC OUI:00507F* ID_OUI_FROM_DATABASE=DrayTek Corp. OUI:3C8970* ID_OUI_FROM_DATABASE=Neosfar OUI:C43655* ID_OUI_FROM_DATABASE=Shenzhen Fenglian Technology Co., Ltd. OUI:78CB68* ID_OUI_FROM_DATABASE=DAEHAP HYPER-TECH OUI:001A7F* ID_OUI_FROM_DATABASE=GCI Science & Technology Co.,LTD OUI:00054F* ID_OUI_FROM_DATABASE=Private OUI:D04D2C* ID_OUI_FROM_DATABASE=Roku, Inc. OUI:E00C7F* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:58BDA3* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:0025A0* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:002659* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:8C56C5* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:CC9E00* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:001656* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:00191D* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:0019FD* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:001EA9* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:A84481* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:8844F6* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:A87B39* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:14C126* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:4C2578* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:001262* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:00174B* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:002547* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001D3B* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0014A7* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001EA4* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001CD6* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001DE9* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:D099D5* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:DC0077* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:0060DC* ID_OUI_FROM_DATABASE=NEC Magnus Communications,Ltd. OUI:9CAED3* ID_OUI_FROM_DATABASE=Seiko Epson Corporation OUI:F45C89* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A41588* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:8C3C4A* ID_OUI_FROM_DATABASE=NAKAYO TELECOMMUNICATIONS,INC OUI:0021FD* ID_OUI_FROM_DATABASE=LACROIX TRAFFIC S.A.U OUI:4CB44A* ID_OUI_FROM_DATABASE=NANOWAVE Technologies Inc. OUI:78C3E9* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:9C5C8E* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:102AB3* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:70884D* ID_OUI_FROM_DATABASE=JAPAN RADIO CO., LTD. OUI:4C55CC* ID_OUI_FROM_DATABASE=Zentri Pty Ltd OUI:BCEC5D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:DC415F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:30636B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:280DFC* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:84683E* ID_OUI_FROM_DATABASE=Intel Corporate OUI:C88722* ID_OUI_FROM_DATABASE=Lumenpulse OUI:FC1A11* ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. OUI:30A9DE* ID_OUI_FROM_DATABASE=LG Innotek OUI:702526* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:903AA0* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:E0CDFD* ID_OUI_FROM_DATABASE=Beijing E3Control Technology Co, LTD OUI:BC52B4* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:08BE77* ID_OUI_FROM_DATABASE=Green Electronics OUI:208B37* ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd OUI:280C28* ID_OUI_FROM_DATABASE=Unigen DataStorage Corporation OUI:980CA5* ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. OUI:1CC035* ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. OUI:34543C* ID_OUI_FROM_DATABASE=TAKAOKA TOKO CO.,LTD. OUI:D49524* ID_OUI_FROM_DATABASE=Clover Network, Inc. OUI:0034DA* ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) OUI:9046A2* ID_OUI_FROM_DATABASE=Tedipay UK Ltd OUI:6479A7* ID_OUI_FROM_DATABASE=Phison Electronics Corp. OUI:0019C5* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:0015C1* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:C83870* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:288335* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:44783E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:202D07* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:FC2FAA* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:D4612E* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:1C6758* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:0452C7* ID_OUI_FROM_DATABASE=Bose Corporation OUI:E85659* ID_OUI_FROM_DATABASE=Advanced-Connectek Inc. OUI:34E70B* ID_OUI_FROM_DATABASE=Beijing HAN Networks Co., Ltd OUI:8801F2* ID_OUI_FROM_DATABASE=Vitec System Engineering Inc. OUI:FC084A* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:847BEB* ID_OUI_FROM_DATABASE=Dell Inc. OUI:F8C96C* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:34BF90* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:D467E7* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:04C1B9* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:689361* ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. OUI:D4AD2D* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:48555F* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:04A316* ID_OUI_FROM_DATABASE=Texas Instruments OUI:98072D* ID_OUI_FROM_DATABASE=Texas Instruments OUI:A082AC* ID_OUI_FROM_DATABASE=Linear DMS Solutions Sdn. Bhd. OUI:705A9E* ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. OUI:002697* ID_OUI_FROM_DATABASE=Alpha Technologies Inc. OUI:4CB8B5* ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd OUI:1CABC0* ID_OUI_FROM_DATABASE=Hitron Technologies. Inc OUI:84E323* ID_OUI_FROM_DATABASE=Green Wave Telecommunication SDN BHD OUI:7071BC* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:44650D* ID_OUI_FROM_DATABASE=Amazon Technologies Inc. OUI:E06995* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:D897BA* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:54D9E4* ID_OUI_FROM_DATABASE=BRILLIANTTS CO., LTD OUI:E4F3F5* ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. OUI:00185C* ID_OUI_FROM_DATABASE=EDSLAB Technologies OUI:000E2E* ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. OUI:00020E* ID_OUI_FROM_DATABASE=ECI Telecom Ltd. OUI:0000C9* ID_OUI_FROM_DATABASE=Emulex Corporation OUI:00115B* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:000795* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:B8AEED* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:C03FD5* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:7427EA* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:00089F* ID_OUI_FROM_DATABASE=EFM Networks OUI:042AE2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001A45* ID_OUI_FROM_DATABASE=GN Netcom A/S OUI:00168F* ID_OUI_FROM_DATABASE=GN Netcom A/S OUI:00104F* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:000782* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:083FBC* ID_OUI_FROM_DATABASE=zte corporation OUI:903809* ID_OUI_FROM_DATABASE=Ericsson AB OUI:1C1B0D* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:E42F56* ID_OUI_FROM_DATABASE=OptoMET GmbH OUI:00A045* ID_OUI_FROM_DATABASE=PHOENIX CONTACT Electronics GmbH OUI:00266C* ID_OUI_FROM_DATABASE=INVENTEC Corporation OUI:001E25* ID_OUI_FROM_DATABASE=INTEK DIGITAL OUI:A0B662* ID_OUI_FROM_DATABASE=Acutvista Innovation Co., Ltd. OUI:00C0F0* ID_OUI_FROM_DATABASE=Kingston Technology Company, Inc. OUI:4C8FA5* ID_OUI_FROM_DATABASE=Jastec OUI:000C49* ID_OUI_FROM_DATABASE=Dangaard Telecom Denmark A/S OUI:CCE17F* ID_OUI_FROM_DATABASE=Juniper Networks OUI:44F477* ID_OUI_FROM_DATABASE=Juniper Networks OUI:5C4527* ID_OUI_FROM_DATABASE=Juniper Networks OUI:F01C2D* ID_OUI_FROM_DATABASE=Juniper Networks OUI:F8C001* ID_OUI_FROM_DATABASE=Juniper Networks OUI:78FE3D* ID_OUI_FROM_DATABASE=Juniper Networks OUI:54E032* ID_OUI_FROM_DATABASE=Juniper Networks OUI:3C6104* ID_OUI_FROM_DATABASE=Juniper Networks OUI:0019E2* ID_OUI_FROM_DATABASE=Juniper Networks OUI:001F12* ID_OUI_FROM_DATABASE=Juniper Networks OUI:0024DC* ID_OUI_FROM_DATABASE=Juniper Networks OUI:50C58D* ID_OUI_FROM_DATABASE=Juniper Networks OUI:000585* ID_OUI_FROM_DATABASE=Juniper Networks OUI:003146* ID_OUI_FROM_DATABASE=Juniper Networks OUI:80ACAC* ID_OUI_FROM_DATABASE=Juniper Networks OUI:BC7574* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:20A680* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:50DD4F* ID_OUI_FROM_DATABASE=Automation Components, Inc OUI:904D4A* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:7C79E8* ID_OUI_FROM_DATABASE=PayRange Inc. OUI:2C3996* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:0054BD* ID_OUI_FROM_DATABASE=Swelaser AB OUI:0057D2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:3C6716* ID_OUI_FROM_DATABASE=Lily Robotics OUI:806AB0* ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. OUI:A0F895* ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. OUI:0078CD* ID_OUI_FROM_DATABASE=Ignition Design Labs OUI:40D855* ID_OUI_FROM_DATABASE=IEEE Registration Authority OUI:28ED6A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:34AB37* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:60A37D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0056CD* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:7081EB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:086698* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:002926* ID_OUI_FROM_DATABASE=Applied Optoelectronics, Inc Taiwan Branch OUI:44C15C* ID_OUI_FROM_DATABASE=Texas Instruments OUI:1CE2CC* ID_OUI_FROM_DATABASE=Texas Instruments OUI:985945* ID_OUI_FROM_DATABASE=Texas Instruments OUI:1CBA8C* ID_OUI_FROM_DATABASE=Texas Instruments OUI:BC6A29* ID_OUI_FROM_DATABASE=Texas Instruments OUI:2CFD37* ID_OUI_FROM_DATABASE=Blue Calypso, Inc. OUI:0C6127* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:001B11* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:001E58* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:002191* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:0022B0* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:F07D68* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:78542E* ID_OUI_FROM_DATABASE=D-Link International OUI:3CDD89* ID_OUI_FROM_DATABASE=SOMO HOLDINGS & TECH. CO.,LTD. OUI:2C56DC* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:001830* ID_OUI_FROM_DATABASE=Texas Instruments OUI:C0E422* ID_OUI_FROM_DATABASE=Texas Instruments OUI:04E451* ID_OUI_FROM_DATABASE=Texas Instruments OUI:D00790* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0017E7* ID_OUI_FROM_DATABASE=Texas Instruments OUI:0017E9* ID_OUI_FROM_DATABASE=Texas Instruments OUI:001E4C* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:B8AF67* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:9C3426* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:188B45* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:B0C090* ID_OUI_FROM_DATABASE=Chicony Electronics Co., Ltd. OUI:001DD2* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:B0C287* ID_OUI_FROM_DATABASE=Technicolor CH USA OUI:1CA770* ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD OUI:C42F90* ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. OUI:9C5D12* ID_OUI_FROM_DATABASE=Aerohive Networks Inc. OUI:1CCB99* ID_OUI_FROM_DATABASE=TCT mobile ltd OUI:A42BB0* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:4CE676* ID_OUI_FROM_DATABASE=BUFFALO.INC OUI:B0C745* ID_OUI_FROM_DATABASE=BUFFALO.INC OUI:CCE1D5* ID_OUI_FROM_DATABASE=BUFFALO.INC OUI:B8FC9A* ID_OUI_FROM_DATABASE=Le Shi Zhi Xin Electronic Technology (Tianjin) Limited OUI:2C4138* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:2C768A* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0018FE* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0019BB* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:002264* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:002481* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:000D9D* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0014C2* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:788B77* ID_OUI_FROM_DATABASE=Standar Telecom OUI:84ACFB* ID_OUI_FROM_DATABASE=Crouzet Automatismes OUI:34BA75* ID_OUI_FROM_DATABASE=Tembo Systems, Inc. OUI:FCFFAA* ID_OUI_FROM_DATABASE=IEEE Registration Authority OUI:00CB00* ID_OUI_FROM_DATABASE=Private OUI:9486CD* ID_OUI_FROM_DATABASE=SEOUL ELECTRONICS&TELECOM OUI:94ABDE* ID_OUI_FROM_DATABASE=OMX Technology - FZE OUI:000E35* ID_OUI_FROM_DATABASE=Intel Corporation OUI:00207B* ID_OUI_FROM_DATABASE=Intel Corporation OUI:0013CE* ID_OUI_FROM_DATABASE=Intel Corporate OUI:801934* ID_OUI_FROM_DATABASE=Intel Corporate OUI:B8B81E* ID_OUI_FROM_DATABASE=Intel Corporate OUI:185E0F* ID_OUI_FROM_DATABASE=Intel Corporate OUI:C80E77* ID_OUI_FROM_DATABASE=Le Shi Zhi Xin Electronic Technology (Tianjin) Limited OUI:843497* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:ECB1D7* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:3CA82A* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:480FCF* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:5820B1* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:2C233A* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:000EB3* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0004EA* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:00306E* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0060B0* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:24BE05* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:94877C* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:407009* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:F8EDA5* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:5465DE* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:6CCA08* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:5C8FE0* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:BCCAB5* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:000FCC* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:000423* ID_OUI_FROM_DATABASE=Intel Corporation OUI:0008C7* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:0010E3* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:00805F* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:BCEAFA* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:5C8A38* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:D89D67* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:2C44FD* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:F0921C* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:B4B52F* ID_OUI_FROM_DATABASE=Hewlett Packard OUI:902155* ID_OUI_FROM_DATABASE=HTC Corporation OUI:64A769* ID_OUI_FROM_DATABASE=HTC Corporation OUI:BCCFCC* ID_OUI_FROM_DATABASE=HTC Corporation OUI:B0F1A3* ID_OUI_FROM_DATABASE=Fengfan (BeiJing) Technology Co., Ltd. OUI:90CDB6* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:7C7D3D* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:4482E5* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:00265C* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:002556* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:542758* ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. OUI:4CD08A* ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. OUI:20906F* ID_OUI_FROM_DATABASE=Shenzhen Tencent Computer System Co., Ltd. OUI:1C7839* ID_OUI_FROM_DATABASE=Shenzhen Tencent Computer System Co., Ltd. OUI:D837BE* ID_OUI_FROM_DATABASE=Shanghai Gongjing Telecom Technology Co,LTD OUI:A4516F* ID_OUI_FROM_DATABASE=Microsoft Mobile Oy OUI:FC64BA* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:246081* ID_OUI_FROM_DATABASE=razberi technologies OUI:8CAB8E* ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd. OUI:9060F1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:EC26CA* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:001FE1* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:002268* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:9471AC* ID_OUI_FROM_DATABASE=TCT mobile ltd OUI:A09347* ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD OUI:2C088C* ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. OUI:D42C0F* ID_OUI_FROM_DATABASE=Pace plc OUI:40F308* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:5CDAD4* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:000E6D* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:904CE5* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:CCAF78* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:1C666D* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:785968* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:F80D43* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:F866D1* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:0071CC* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:B05B67* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:38F889* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:F4DCF9* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:904E2B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:0C96BF* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:9CC172* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:0014C9* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:00010F* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:080088* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:00051E* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. OUI:384608* ID_OUI_FROM_DATABASE=zte corporation OUI:B4B362* ID_OUI_FROM_DATABASE=zte corporation OUI:B075D5* ID_OUI_FROM_DATABASE=zte corporation OUI:08181A* ID_OUI_FROM_DATABASE=zte corporation OUI:002512* ID_OUI_FROM_DATABASE=zte corporation OUI:CCF954* ID_OUI_FROM_DATABASE=Avaya Inc OUI:703018* ID_OUI_FROM_DATABASE=Avaya Inc OUI:B0A37E* ID_OUI_FROM_DATABASE=Qingdao Haier Telecom Co.,Ltd OUI:70A8E3* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:F84ABF* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:4CB16C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:4C1FCC* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:486276* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:AC4E91* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:E468A3* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:80D09B* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:581F28* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:8C34FD* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:90671C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:587F66* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:BC25E0* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:C4072F* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:0CD6BD* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:A49947* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:346BD3* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:1C1D67* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:84A8E4* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:202BC1* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:3475C7* ID_OUI_FROM_DATABASE=Avaya Inc OUI:6CFA58* ID_OUI_FROM_DATABASE=Avaya Inc OUI:64A7DD* ID_OUI_FROM_DATABASE=Avaya Inc OUI:646A52* ID_OUI_FROM_DATABASE=Avaya Inc OUI:F873A2* ID_OUI_FROM_DATABASE=Avaya Inc OUI:64C354* ID_OUI_FROM_DATABASE=Avaya Inc OUI:B4B017* ID_OUI_FROM_DATABASE=Avaya Inc OUI:581626* ID_OUI_FROM_DATABASE=Avaya Inc OUI:741BB2* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:002586* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:F8D111* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:F4EC38* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:20DCE6* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:1C6E4C* ID_OUI_FROM_DATABASE=Logistic Service & Engineering Co.,Ltd OUI:00101F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001054* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:DCEB94* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:5C838F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:AC7E8A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:382056* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:28CFE9* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:00502A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:005014* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0090D9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:009092* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001029* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001007* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00605C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00E0F7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00E0B0* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00E0FE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00E0A3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00E0F9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001BD7* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:105172* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:9017AC* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:94049C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:001237* ID_OUI_FROM_DATABASE=Texas Instruments OUI:948854* ID_OUI_FROM_DATABASE=Texas Instruments OUI:A863F2* ID_OUI_FROM_DATABASE=Texas Instruments OUI:D0FF50* ID_OUI_FROM_DATABASE=Texas Instruments OUI:20C38F* ID_OUI_FROM_DATABASE=Texas Instruments OUI:A0E6F8* ID_OUI_FROM_DATABASE=Texas Instruments OUI:5C313E* ID_OUI_FROM_DATABASE=Texas Instruments OUI:F4B85E* ID_OUI_FROM_DATABASE=Texas Instruments OUI:68C90B* ID_OUI_FROM_DATABASE=Texas Instruments OUI:EC24B8* ID_OUI_FROM_DATABASE=Texas Instruments OUI:689E19* ID_OUI_FROM_DATABASE=Texas Instruments OUI:C46AB7* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:68DFDD* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:64B473* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:7451BA* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:3480B3* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:5006AB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0050E2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:005050* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:009021* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0090B1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00023D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:18E728* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:2C3ECF* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:1005CA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:1CDEA7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:1C6A7A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:CCD8C1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:7C0ECE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:F09E63* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:F07F06* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:84802D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E0899D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:A89D21* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:BCF1F2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:C80084* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:A0F849* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:88908D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:A46C2A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0021BE* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:7CB21B* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:002643* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:002433* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:745E1C* ID_OUI_FROM_DATABASE=PIONEER CORPORATION OUI:0006F5* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:0006F7* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:000704* ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. OUI:1C1D86* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E0B7B1* ID_OUI_FROM_DATABASE=Pace plc OUI:001A92* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:001D60* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:002215* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:20CF30* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:E0CB4E* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:1C872C* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:C4143C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:2401C7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:04DAD2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:F41FC2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:4C0082* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:DCA5F4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:7C95F3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:5017FF* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E8EDF3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:78DA6E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:24E9B3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E425E7* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:080007* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:000A95* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:002241* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0023DF* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0025BC* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:00264A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:0026B0* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:041E64* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D49A20* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:9027E4* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:60334B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A43135* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:9C35EB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:507A55* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A0999B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:24240E* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:903C92* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:341298* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:9C293F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:488AD2* ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. OUI:A88E24* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E8802E* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:68AE20* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E0B52D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:80BE05* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D8BB2C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D04F7E* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:2C1F23* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:549F13* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:B8098A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F0DBE2* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:18EE69* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:748114* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:18F643* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D0A637* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A01828* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D0034B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:5C5948* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:78CA39* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:18E7F4* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:B8FF61* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:DC2B61* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:1093E9* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:442A60* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E0F847* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:145A05* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:28CFDA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:148FC6* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:283737* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:045453* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F0CBA1* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C06394* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:8C006D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:B09FBA* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:DC86D8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:8C2937* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:DC9B9C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:98F0AB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:F0DBF8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:ACCF5C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:3C15C2* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:04489A* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:D8CF9C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:30F7C5* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:008865* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:40B395* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:3090AB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:1CE62B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A0EDCD* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A886DD* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:54EAA8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E4C63D* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:843835* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:7073CB* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:9C207B* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:842999* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:74E2F5* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:20C9D0* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:1402EC* ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise OUI:707938* ID_OUI_FROM_DATABASE=Wuxi Zhanrui Electronic Technology Co.,LTD OUI:646A74* ID_OUI_FROM_DATABASE=AUTH-SERVERS, LLC OUI:34C9F0* ID_OUI_FROM_DATABASE=LM Technologies Ltd OUI:E034E4* ID_OUI_FROM_DATABASE=Feit Electric Company, Inc. OUI:681401* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:98E848* ID_OUI_FROM_DATABASE=Axiim OUI:A0F9E0* ID_OUI_FROM_DATABASE=VIVATEL COMPANY LIMITED OUI:F8C372* ID_OUI_FROM_DATABASE=TSUZUKI DENKI OUI:908D78* ID_OUI_FROM_DATABASE=D-Link International OUI:A4CC32* ID_OUI_FROM_DATABASE=Inficomm Co., Ltd OUI:582BDB* ID_OUI_FROM_DATABASE=Pax AB OUI:D00F6D* ID_OUI_FROM_DATABASE=T&W Electronics Company OUI:48BF74* ID_OUI_FROM_DATABASE=Baicells Technologies Co.,LTD OUI:38F557* ID_OUI_FROM_DATABASE=JOLATA, INC. OUI:280E8B* ID_OUI_FROM_DATABASE=Beijing Spirit Technology Development Co., Ltd. OUI:F44D30* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:DC9A8E* ID_OUI_FROM_DATABASE=Nanjing Cocomm electronics co., LTD OUI:C4EF70* ID_OUI_FROM_DATABASE=Home Skinovations OUI:B813E9* ID_OUI_FROM_DATABASE=Trace Live Network OUI:746F19* ID_OUI_FROM_DATABASE=ICARVISIONS (SHENZHEN) TECHNOLOGY CO., LTD. OUI:7C7176* ID_OUI_FROM_DATABASE=Wuxi iData Technology Company Ltd. OUI:7C0191* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:70480F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A4B805* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:587F57* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:80D605* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:68A828* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:988744* ID_OUI_FROM_DATABASE=Wuxi Hongda Science and Technology Co.,LTD OUI:C869CD* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:BC6C21* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:9C8DD3* ID_OUI_FROM_DATABASE=Leonton Technologies OUI:246C8A* ID_OUI_FROM_DATABASE=YUKAI Engineering OUI:A43831* ID_OUI_FROM_DATABASE=RF elements s.r.o. OUI:D0BAE4* ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd. OUI:A4DCBE* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:10CC1B* ID_OUI_FROM_DATABASE=Liverock technologies,INC OUI:48B620* ID_OUI_FROM_DATABASE=ROLI Ltd. OUI:20D160* ID_OUI_FROM_DATABASE=Private OUI:382187* ID_OUI_FROM_DATABASE=Midea Group Co., Ltd. OUI:305A3A* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:A87285* ID_OUI_FROM_DATABASE=IDT, INC. OUI:AC1FD7* ID_OUI_FROM_DATABASE=Real Vision Technology Co.,Ltd. OUI:C8A2CE* ID_OUI_FROM_DATABASE=Oasis Media Systems LLC OUI:A4DEC9* ID_OUI_FROM_DATABASE=QLove Mobile Intelligence Information Technology (W.H.) Co. Ltd. OUI:3C7A8A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:A4A6A9* ID_OUI_FROM_DATABASE=Private OUI:0469F8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:9C7A03* ID_OUI_FROM_DATABASE=Ciena Corporation OUI:380AAB* ID_OUI_FROM_DATABASE=Formlabs OUI:F41535* ID_OUI_FROM_DATABASE=SPON Communication Technology Co.,Ltd OUI:E41A2C* ID_OUI_FROM_DATABASE=ZPE Systems, Inc. OUI:A815D6* ID_OUI_FROM_DATABASE=Shenzhen Meione Technology CO., LTD OUI:D09380* ID_OUI_FROM_DATABASE=Ducere Technologies Pvt. Ltd. OUI:84A788* ID_OUI_FROM_DATABASE=Perples OUI:6889C1* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:845B12* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:143EBF* ID_OUI_FROM_DATABASE=zte corporation OUI:041E7A* ID_OUI_FROM_DATABASE=DSPWorks OUI:38B725* ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation OUI:ACEC80* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:80EA23* ID_OUI_FROM_DATABASE=Wistron Neweb Corp. OUI:4CC681* ID_OUI_FROM_DATABASE=Shenzhen Aisat Electronic Co., Ltd. OUI:28B9D9* ID_OUI_FROM_DATABASE=Radisys Corporation OUI:E0553D* ID_OUI_FROM_DATABASE=Cisco Meraki OUI:0894EF* ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation OUI:304487* ID_OUI_FROM_DATABASE=Hefei Radio Communication Technology Co., Ltd OUI:E0319E* ID_OUI_FROM_DATABASE=Valve Corporation OUI:E4A32F* ID_OUI_FROM_DATABASE=Shanghai Artimen Technology Co., Ltd. OUI:D47BB0* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:5045F7* ID_OUI_FROM_DATABASE=Liuhe Intelligence Technology Ltd. OUI:20F510* ID_OUI_FROM_DATABASE=Codex Digital Limited OUI:949F3E* ID_OUI_FROM_DATABASE=Sonos, Inc. OUI:788E33* ID_OUI_FROM_DATABASE=Jiangsu SEUIC Technology Co.,Ltd OUI:94D859* ID_OUI_FROM_DATABASE=TCT mobile ltd OUI:E01AEA* ID_OUI_FROM_DATABASE=Allied Telesis, Inc. OUI:340CED* ID_OUI_FROM_DATABASE=Moduel AB OUI:507B9D* ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd OUI:6C7220* ID_OUI_FROM_DATABASE=D-Link International OUI:F02624* ID_OUI_FROM_DATABASE=WAFA TECHNOLOGIES CO., LTD. OUI:F8F464* ID_OUI_FROM_DATABASE=Rawe Electonic GmbH OUI:F4672D* ID_OUI_FROM_DATABASE=ShenZhen Topstar Technology Company OUI:382B78* ID_OUI_FROM_DATABASE=ECO PLUGS ENTERPRISE CO., LTD OUI:606DC7* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:BCEB5F* ID_OUI_FROM_DATABASE=Fujian Beifeng Telecom Technology Co., Ltd. OUI:800B51* ID_OUI_FROM_DATABASE=Chengdu XGimi Technology Co.,Ltd OUI:00FC8D* ID_OUI_FROM_DATABASE=Hitron Technologies. Inc OUI:1CC586* ID_OUI_FROM_DATABASE=Absolute Acoustics OUI:C49A02* ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communicaitons) OUI:E076D0* ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. OUI:24B0A9* ID_OUI_FROM_DATABASE=Shanghai Mobiletek Communication Ltd. OUI:64167F* ID_OUI_FROM_DATABASE=Polycom OUI:54E2C8* ID_OUI_FROM_DATABASE=Dongguan Aoyuan Electronics Technology Co., Ltd OUI:08D0B7* ID_OUI_FROM_DATABASE=HISENSE ELECTRIC CO.,LTD. OUI:20D75A* ID_OUI_FROM_DATABASE=Posh Mobile Limited OUI:88D37B* ID_OUI_FROM_DATABASE=FirmTek, LLC OUI:10AF78* ID_OUI_FROM_DATABASE=Shenzhen ATUE Technology Co., Ltd OUI:B0966C* ID_OUI_FROM_DATABASE=Lanbowan Technology Ltd. OUI:A408EA* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:D4F9A1* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:9CB6D0* ID_OUI_FROM_DATABASE=Rivet Networks OUI:D0C0BF* ID_OUI_FROM_DATABASE=Actions Microelectronics Co., Ltd OUI:94F665* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:707781* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:E04B45* ID_OUI_FROM_DATABASE=Hi-P Electronics Pte Ltd OUI:6C4598* ID_OUI_FROM_DATABASE=Antex Electronic Corp. OUI:94A7B7* ID_OUI_FROM_DATABASE=zte corporation OUI:3C8375* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:C8458F* ID_OUI_FROM_DATABASE=Wyler AG OUI:149A10* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:FC9AFA* ID_OUI_FROM_DATABASE=Motus Global Inc. OUI:5CB43E* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:FCE1FB* ID_OUI_FROM_DATABASE=Array Networks OUI:54E140* ID_OUI_FROM_DATABASE=INGENICO OUI:14157C* ID_OUI_FROM_DATABASE=TOKYO COSMOS ELECTRIC CO.,LTD. OUI:408D5C* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:6CE01E* ID_OUI_FROM_DATABASE=Modcam AB OUI:D09DAB* ID_OUI_FROM_DATABASE=TCT mobile ltd OUI:E8F2E3* ID_OUI_FROM_DATABASE=Starcor Beijing Co.,Limited OUI:D048F3* ID_OUI_FROM_DATABASE=DATTUS Inc OUI:CC19A8* ID_OUI_FROM_DATABASE=PT Inovação e Sistemas SA OUI:6C4418* ID_OUI_FROM_DATABASE=Zappware OUI:44962B* ID_OUI_FROM_DATABASE=Aidon Oy OUI:D4D7A9* ID_OUI_FROM_DATABASE=Shanghai Kaixiang Info Tech LTD OUI:185D9A* ID_OUI_FROM_DATABASE=BobjGear LLC OUI:884157* ID_OUI_FROM_DATABASE=Shenzhen Atsmart Technology Co.,Ltd. OUI:3CDA2A* ID_OUI_FROM_DATABASE=zte corporation OUI:747336* ID_OUI_FROM_DATABASE=MICRODIGTAL Inc OUI:0CE725* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:6C2E72* ID_OUI_FROM_DATABASE=B&B EXPORTING LIMITED OUI:98EECB* ID_OUI_FROM_DATABASE=Wistron InfoComm(ZhongShan)Corporation OUI:FC3288* ID_OUI_FROM_DATABASE=CELOT Wireless Co., Ltd OUI:BCB308* ID_OUI_FROM_DATABASE=HONGKONG RAGENTEK COMMUNICATION TECHNOLOGY CO.,LIMITED OUI:445ECD* ID_OUI_FROM_DATABASE=Razer Inc OUI:749637* ID_OUI_FROM_DATABASE=Todaair Electronic Co., Ltd OUI:2031EB* ID_OUI_FROM_DATABASE=HDSN OUI:C0335E* ID_OUI_FROM_DATABASE=Microsoft OUI:ACCAAB* ID_OUI_FROM_DATABASE=Virtual Electric Inc OUI:241B44* ID_OUI_FROM_DATABASE=Hangzhou Tuners Electronics Co., Ltd OUI:B0E03C* ID_OUI_FROM_DATABASE=TCT mobile ltd OUI:90C35F* ID_OUI_FROM_DATABASE=Nanjing Jiahao Technology Co., Ltd. OUI:18F145* ID_OUI_FROM_DATABASE=NetComm Wireless Limited OUI:4CA515* ID_OUI_FROM_DATABASE=Baikal Electronics JSC OUI:9CE230* ID_OUI_FROM_DATABASE=JULONG CO,.LTD. OUI:80F503* ID_OUI_FROM_DATABASE=Pace plc OUI:34873D* ID_OUI_FROM_DATABASE=Quectel Wireless Solution Co.,Ltd. OUI:186882* ID_OUI_FROM_DATABASE=Beward R&D Co., Ltd. OUI:FC3D93* ID_OUI_FROM_DATABASE=LONGCHEER TELECOMMUNICATION LIMITED OUI:344CA4* ID_OUI_FROM_DATABASE=amazipoint technology Ltd. OUI:A8F038* ID_OUI_FROM_DATABASE=SHEN ZHEN SHI JIN HUA TAI ELECTRONICS CO.,LTD OUI:74E277* ID_OUI_FROM_DATABASE=Vizmonet Pte Ltd OUI:10A659* ID_OUI_FROM_DATABASE=Mobile Create Co.,Ltd. OUI:58856E* ID_OUI_FROM_DATABASE=QSC AG OUI:FCAFAC* ID_OUI_FROM_DATABASE=Socionext Inc. OUI:F8C397* ID_OUI_FROM_DATABASE=NZXT Corp. Ltd. OUI:C4366C* ID_OUI_FROM_DATABASE=LG Innotek OUI:D85DE2* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:60D9A0* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:5C3B35* ID_OUI_FROM_DATABASE=Gehirn Inc. OUI:5CF7C3* ID_OUI_FROM_DATABASE=SYNTECH (HK) TECHNOLOGY LIMITED OUI:3CC2E1* ID_OUI_FROM_DATABASE=XINHUA CONTROL ENGINEERING CO.,LTD OUI:7C534A* ID_OUI_FROM_DATABASE=Metamako OUI:9C3066* ID_OUI_FROM_DATABASE=RWE Effizienz GmbH OUI:FCA22A* ID_OUI_FROM_DATABASE=PT. Callysta Multi Engineering OUI:247656* ID_OUI_FROM_DATABASE=Shanghai Net Miles Fiber Optics Technology Co., LTD. OUI:A0ADA1* ID_OUI_FROM_DATABASE=JMR Electronics, Inc OUI:601970* ID_OUI_FROM_DATABASE=HUIZHOU QIAOXING ELECTRONICS TECHNOLOGY CO., LTD. OUI:887033* ID_OUI_FROM_DATABASE=Hangzhou Silan Microelectronic Inc OUI:8C7967* ID_OUI_FROM_DATABASE=zte corporation OUI:D083D4* ID_OUI_FROM_DATABASE=XTel ApS OUI:78F944* ID_OUI_FROM_DATABASE=Private OUI:CCA4AF* ID_OUI_FROM_DATABASE=Shenzhen Sowell Technology Co., LTD OUI:84F129* ID_OUI_FROM_DATABASE=Metrascale Inc. OUI:2028BC* ID_OUI_FROM_DATABASE=Visionscape Co,. Ltd. OUI:B8F080* ID_OUI_FROM_DATABASE=SPS, INC. OUI:7858F3* ID_OUI_FROM_DATABASE=Vachen Co.,Ltd OUI:FCDC4A* ID_OUI_FROM_DATABASE=G-Wearables Corp. OUI:F42C56* ID_OUI_FROM_DATABASE=SENOR TECH CO LTD OUI:50502A* ID_OUI_FROM_DATABASE=Egardia OUI:48EE0C* ID_OUI_FROM_DATABASE=D-Link International OUI:48C093* ID_OUI_FROM_DATABASE=Xirrus, Inc. OUI:3C1A0F* ID_OUI_FROM_DATABASE=ClearSky Data OUI:ACB57D* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:DCE1AD* ID_OUI_FROM_DATABASE=Shenzhen Wintop Photoelectric Technology Co., Ltd OUI:900CB4* ID_OUI_FROM_DATABASE=Alinket Electronic Technology Co., Ltd OUI:883B8B* ID_OUI_FROM_DATABASE=Cheering Connection Co. Ltd. OUI:94D417* ID_OUI_FROM_DATABASE=GPI KOREA INC. OUI:D855A3* ID_OUI_FROM_DATABASE=zte corporation OUI:70DA9C* ID_OUI_FROM_DATABASE=TECSEN OUI:6CF5E8* ID_OUI_FROM_DATABASE=Mooredoll Inc. OUI:70FF5C* ID_OUI_FROM_DATABASE=Cheerzing Communication(Xiamen)Technology Co.,Ltd OUI:E0107F* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:08115E* ID_OUI_FROM_DATABASE=Bitel Co., Ltd. OUI:44CE7D* ID_OUI_FROM_DATABASE=SFR OUI:0881BC* ID_OUI_FROM_DATABASE=HongKong Ipro Technology Co., Limited OUI:4C16F1* ID_OUI_FROM_DATABASE=zte corporation OUI:800902* ID_OUI_FROM_DATABASE=Keysight Technologies, Inc. OUI:6872DC* ID_OUI_FROM_DATABASE=CETORY.TV Company Limited OUI:D8B6B7* ID_OUI_FROM_DATABASE=Comtrend Corporation OUI:0499E6* ID_OUI_FROM_DATABASE=Shenzhen Yoostar Technology Co., Ltd OUI:94BF95* ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd OUI:344DF7* ID_OUI_FROM_DATABASE=LG Electronics OUI:FC9FE1* ID_OUI_FROM_DATABASE=CONWIN.Tech. Ltd OUI:90203A* ID_OUI_FROM_DATABASE=BYD Precision Manufacture Co.,Ltd OUI:A81B5D* ID_OUI_FROM_DATABASE=Foxtel Management Pty Ltd OUI:B8BD79* ID_OUI_FROM_DATABASE=TrendPoint Systems OUI:2C010B* ID_OUI_FROM_DATABASE=NASCENT Technology, LLC - RemKon OUI:D4EC86* ID_OUI_FROM_DATABASE=LinkedHope Intelligent Technologies Co., Ltd OUI:20A99B* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:6C7660* ID_OUI_FROM_DATABASE=KYOCERA Corporation OUI:A0A3E2* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:54098D* ID_OUI_FROM_DATABASE=deister electronic GmbH OUI:F0FE6B* ID_OUI_FROM_DATABASE=Shanghai High-Flying Electronics Technology Co., Ltd OUI:3CAE69* ID_OUI_FROM_DATABASE=ESA Elektroschaltanlagen Grimma GmbH OUI:00F3DB* ID_OUI_FROM_DATABASE=WOO Sports OUI:08A5C8* ID_OUI_FROM_DATABASE=Sunnovo International Limited OUI:848EDF* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:CCBDD3* ID_OUI_FROM_DATABASE=Ultimaker B.V. OUI:50294D* ID_OUI_FROM_DATABASE=NANJING IOT SENSOR TECHNOLOGY CO,LTD OUI:90EF68* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:0CCFD1* ID_OUI_FROM_DATABASE=SPRINGWAVE Co., Ltd OUI:58108C* ID_OUI_FROM_DATABASE=Intelbras OUI:187117* ID_OUI_FROM_DATABASE=eta plus electronic gmbh OUI:7CB177* ID_OUI_FROM_DATABASE=Satelco AG OUI:8C5D60* ID_OUI_FROM_DATABASE=UCI Corporation Co.,Ltd. OUI:104B46* ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation OUI:4C0BBE* ID_OUI_FROM_DATABASE=Microsoft OUI:08EB29* ID_OUI_FROM_DATABASE=Jiangsu Huitong Group Co.,Ltd. OUI:D88039* ID_OUI_FROM_DATABASE=Microchip Technology Inc. OUI:E48C0F* ID_OUI_FROM_DATABASE=Discovery Insure OUI:587FB7* ID_OUI_FROM_DATABASE=SONAR INDUSTRIAL CO., LTD. OUI:E42354* ID_OUI_FROM_DATABASE=SHENZHEN FUZHI SOFTWARE TECHNOLOGY CO.,LTD OUI:207693* ID_OUI_FROM_DATABASE=Lenovo (Beijing) Limited. OUI:C4BD6A* ID_OUI_FROM_DATABASE=SKF GmbH OUI:14488B* ID_OUI_FROM_DATABASE=Shenzhen Doov Technology Co.,Ltd OUI:70BAEF* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited OUI:CC03FA* ID_OUI_FROM_DATABASE=Technicolor CH USA OUI:603696* ID_OUI_FROM_DATABASE=The Sapling Company OUI:54FFCF* ID_OUI_FROM_DATABASE=Mopria Alliance OUI:BCBC46* ID_OUI_FROM_DATABASE=SKS Welding Systems GmbH OUI:A8D88A* ID_OUI_FROM_DATABASE=Wyconn OUI:00E6E8* ID_OUI_FROM_DATABASE=Netzin Technology Corporation,.Ltd. OUI:64B21D* ID_OUI_FROM_DATABASE=Chengdu Phycom Tech Co., Ltd. OUI:88708C* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:F03D29* ID_OUI_FROM_DATABASE=Actility OUI:909F33* ID_OUI_FROM_DATABASE=EFM Networks OUI:849681* ID_OUI_FROM_DATABASE=Cathay Communication Co.,Ltd OUI:A056B2* ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH OUI:40C62A* ID_OUI_FROM_DATABASE=Shanghai Jing Ren Electronic Technology Co., Ltd. OUI:E8150E* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:F4D032* ID_OUI_FROM_DATABASE=Yunnan Ideal Information&Technology.,Ltd OUI:44A6E5* ID_OUI_FROM_DATABASE=THINKING TECHNOLOGY CO.,LTD OUI:A8329A* ID_OUI_FROM_DATABASE=Digicom Futuristic Technologies Ltd. OUI:B40AC6* ID_OUI_FROM_DATABASE=DEXON Systems Ltd. OUI:480C49* ID_OUI_FROM_DATABASE=NAKAYO TELECOMMUNICATIONS,INC OUI:5CB8CB* ID_OUI_FROM_DATABASE=Allis Communications OUI:4C9EFF* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:C44BD1* ID_OUI_FROM_DATABASE=Wallys Communications Teachnologies Co.,Ltd. OUI:E85D6B* ID_OUI_FROM_DATABASE=Luminate Wireless OUI:8C3357* ID_OUI_FROM_DATABASE=HiteVision Digital Media Technology Co.,Ltd. OUI:506787* ID_OUI_FROM_DATABASE=iTellus OUI:F4D261* ID_OUI_FROM_DATABASE=SEMOCON Co., Ltd OUI:D05AF1* ID_OUI_FROM_DATABASE=Shenzhen Pulier Tech CO.,Ltd OUI:481A84* ID_OUI_FROM_DATABASE=Pointer Telocation Ltd OUI:E4F4C6* ID_OUI_FROM_DATABASE=NETGEAR OUI:DC663A* ID_OUI_FROM_DATABASE=Apacer Technology Inc. OUI:B009D3* ID_OUI_FROM_DATABASE=Avizia OUI:B01041* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:3CAA3F* ID_OUI_FROM_DATABASE=iKey, Ltd. OUI:0C383E* ID_OUI_FROM_DATABASE=Fanvil Technology Co., Ltd. OUI:60CDA9* ID_OUI_FROM_DATABASE=Abloomy OUI:B40B44* ID_OUI_FROM_DATABASE=Smartisan Technology Co., Ltd. OUI:A0FC6E* ID_OUI_FROM_DATABASE=Telegrafia a.s. OUI:44D4E0* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:5CF4AB* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:D0FA1D* ID_OUI_FROM_DATABASE=Qihoo 360 Technology Co.,Ltd OUI:046785* ID_OUI_FROM_DATABASE=scemtec Hard- und Software fuer Mess- und Steuerungstechnik GmbH OUI:FC6DC0* ID_OUI_FROM_DATABASE=BME CORPORATION OUI:784561* ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. OUI:D896E0* ID_OUI_FROM_DATABASE=Alibaba Cloud Computing Ltd. OUI:300D2A* ID_OUI_FROM_DATABASE=Zhejiang Wellcom Technology Co.,Ltd. OUI:8496D8* ID_OUI_FROM_DATABASE=Pace plc OUI:64EAC5* ID_OUI_FROM_DATABASE=SiboTech Automation Co., Ltd. OUI:74DA38* ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. OUI:F4F26D* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:5C1515* ID_OUI_FROM_DATABASE=ADVAN OUI:D0A0D6* ID_OUI_FROM_DATABASE=Chengdu TD Tech Ltd. OUI:8CBF9D* ID_OUI_FROM_DATABASE=Shanghai Xinyou Information Technology Ltd. Co. OUI:D49398* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:78D66F* ID_OUI_FROM_DATABASE=Aristocrat Technologies Australia Pty. Ltd. OUI:50C7BF* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:C06118* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:D0C7C0* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:209AE9* ID_OUI_FROM_DATABASE=Volacomm Co., Ltd OUI:345D10* ID_OUI_FROM_DATABASE=Wytek OUI:58E326* ID_OUI_FROM_DATABASE=Compass Technologies Inc. OUI:848DC7* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:A8BD3A* ID_OUI_FROM_DATABASE=UNIONMAN TECHNOLOGY CO.,LTD OUI:C44E1F* ID_OUI_FROM_DATABASE=BlueN OUI:CCA614* ID_OUI_FROM_DATABASE=AIFA TECHNOLOGY CORP. OUI:B0869E* ID_OUI_FROM_DATABASE=Chloride S.r.L OUI:344F5C* ID_OUI_FROM_DATABASE=R&M AG OUI:A46CC1* ID_OUI_FROM_DATABASE=LTi REEnergy GmbH OUI:90DB46* ID_OUI_FROM_DATABASE=E-LEAD ELECTRONIC CO., LTD OUI:F8A9D0* ID_OUI_FROM_DATABASE=LG Electronics OUI:289AFA* ID_OUI_FROM_DATABASE=TCT Mobile Limited OUI:D42F23* ID_OUI_FROM_DATABASE=Akenori PTE Ltd OUI:286336* ID_OUI_FROM_DATABASE=Siemens AG - Industrial Automation - EWA OUI:38F098* ID_OUI_FROM_DATABASE=Vapor Stone Rail Systems OUI:400107* ID_OUI_FROM_DATABASE=Arista Corp OUI:4C8B30* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:0805CD* ID_OUI_FROM_DATABASE=DongGuang EnMai Electronic Product Co.Ltd. OUI:0092FA* ID_OUI_FROM_DATABASE=SHENZHEN WISKY TECHNOLOGY CO.,LTD OUI:4CF45B* ID_OUI_FROM_DATABASE=Blue Clover Devices OUI:B06971* ID_OUI_FROM_DATABASE=DEI Sales, Inc. OUI:58493B* ID_OUI_FROM_DATABASE=Palo Alto Networks OUI:580528* ID_OUI_FROM_DATABASE=LABRIS NETWORKS OUI:28656B* ID_OUI_FROM_DATABASE=Keystone Microtech Corporation OUI:EC2E4E* ID_OUI_FROM_DATABASE=HITACHI-LG DATA STORAGE INC OUI:505800* ID_OUI_FROM_DATABASE=WyTec International, Inc. OUI:78923E* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:D4CFF9* ID_OUI_FROM_DATABASE=Shenzhen Sen5 Technology Co., Ltd. OUI:D8492F* ID_OUI_FROM_DATABASE=CANON INC. OUI:D46761* ID_OUI_FROM_DATABASE=SAHAB TECHNOLOGY OUI:145645* ID_OUI_FROM_DATABASE=Savitech Corp. OUI:D4E08E* ID_OUI_FROM_DATABASE=ValueHD Corporation OUI:70305D* ID_OUI_FROM_DATABASE=Ubiquoss Inc OUI:5850AB* ID_OUI_FROM_DATABASE=TLS Corporation OUI:90DFB7* ID_OUI_FROM_DATABASE=s.m.s smart microwave sensors GmbH OUI:B843E4* ID_OUI_FROM_DATABASE=Vlatacom OUI:8425A4* ID_OUI_FROM_DATABASE=Tariox Limited OUI:E07F53* ID_OUI_FROM_DATABASE=TECHBOARD SRL OUI:4C0DEE* ID_OUI_FROM_DATABASE=JABIL CIRCUIT (SHANGHAI) LTD. OUI:A07771* ID_OUI_FROM_DATABASE=Vialis BV OUI:D0BD01* ID_OUI_FROM_DATABASE=DS International OUI:C0C569* ID_OUI_FROM_DATABASE=SHANGHAI LYNUC CNC TECHNOLOGY CO.,LTD OUI:200E95* ID_OUI_FROM_DATABASE=IEC – TC9 WG43 OUI:E0DB88* ID_OUI_FROM_DATABASE=Open Standard Digital-IF Interface for SATCOM Systems OUI:D86194* ID_OUI_FROM_DATABASE=Objetivos y Sevicios de Valor Añadido OUI:589CFC* ID_OUI_FROM_DATABASE=FreeBSD Foundation OUI:602103* ID_OUI_FROM_DATABASE=STCUBE.INC OUI:085DDD* ID_OUI_FROM_DATABASE=Mercury Corporation OUI:98349D* ID_OUI_FROM_DATABASE=Krauss Maffei Technologies GmbH OUI:18CC23* ID_OUI_FROM_DATABASE=Philio Technology Corporation OUI:648D9E* ID_OUI_FROM_DATABASE=IVT Electronic Co.,Ltd OUI:CCFA00* ID_OUI_FROM_DATABASE=LG Electronics OUI:CC95D7* ID_OUI_FROM_DATABASE=Vizio, Inc OUI:749C52* ID_OUI_FROM_DATABASE=Huizhou Desay SV Automotive Co., Ltd. OUI:C0F79D* ID_OUI_FROM_DATABASE=Powercode OUI:3C0C48* ID_OUI_FROM_DATABASE=Servergy, Inc. OUI:68D247* ID_OUI_FROM_DATABASE=Portalis LC OUI:FC27A2* ID_OUI_FROM_DATABASE=TRANS ELECTRIC CO., LTD. OUI:14C089* ID_OUI_FROM_DATABASE=DUNE HD LTD OUI:F08A28* ID_OUI_FROM_DATABASE=JIANGSU HENGSION ELECTRONIC S and T CO.,LTD OUI:A8574E* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:DC3EF8* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:706173* ID_OUI_FROM_DATABASE=Calantec GmbH OUI:50C271* ID_OUI_FROM_DATABASE=SECURETECH INC OUI:7C49B9* ID_OUI_FROM_DATABASE=Plexus Manufacturing Sdn Bhd OUI:184462* ID_OUI_FROM_DATABASE=Riava Networks, Inc. OUI:9C443D* ID_OUI_FROM_DATABASE=CHENGDU XUGUANG TECHNOLOGY CO, LTD OUI:301966* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:CC07AB* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E84E84* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:74A4B5* ID_OUI_FROM_DATABASE=Powerleader Science and Technology Co. Ltd. OUI:BC4100* ID_OUI_FROM_DATABASE=CODACO ELECTRONIC s.r.o. OUI:7CCD3C* ID_OUI_FROM_DATABASE=Guangzhou Juzing Technology Co., Ltd OUI:10B26B* ID_OUI_FROM_DATABASE=base Co.,Ltd. OUI:DCCEBC* ID_OUI_FROM_DATABASE=Shenzhen JSR Technology Co.,Ltd. OUI:9486D4* ID_OUI_FROM_DATABASE=Surveillance Pro Corporation OUI:F89550* ID_OUI_FROM_DATABASE=Proton Products Chengdu Ltd OUI:447BC4* ID_OUI_FROM_DATABASE=DualShine Technology(SZ)Co.,Ltd OUI:542F89* ID_OUI_FROM_DATABASE=Euclid Laboratories, Inc. OUI:48B977* ID_OUI_FROM_DATABASE=PulseOn Oy OUI:AC2DA3* ID_OUI_FROM_DATABASE=TXTR GmbH OUI:C8F68D* ID_OUI_FROM_DATABASE=S.E.TECHNOLOGIES LIMITED OUI:BC14EF* ID_OUI_FROM_DATABASE=ITON Technology Limited OUI:14F28E* ID_OUI_FROM_DATABASE=ShenYang ZhongKe-Allwin Technology Co.LTD OUI:C064C6* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:9C44A6* ID_OUI_FROM_DATABASE=SwiftTest, Inc. OUI:44C4A9* ID_OUI_FROM_DATABASE=Opticom Communication, LLC OUI:6C3C53* ID_OUI_FROM_DATABASE=SoundHawk Corp OUI:64BABD* ID_OUI_FROM_DATABASE=SDJ Technologies, Inc. OUI:889166* ID_OUI_FROM_DATABASE=Viewcooper Corp. OUI:103378* ID_OUI_FROM_DATABASE=FLECTRON Co., LTD OUI:DC0575* ID_OUI_FROM_DATABASE=SIEMENS ENERGY AUTOMATION OUI:342387* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:5C1193* ID_OUI_FROM_DATABASE=Seal One AG OUI:B4527E* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:50E14A* ID_OUI_FROM_DATABASE=Private OUI:68FCB3* ID_OUI_FROM_DATABASE=Next Level Security Systems, Inc. OUI:70305E* ID_OUI_FROM_DATABASE=Nanjing Zhongke Menglian Information Technology Co.,LTD OUI:6C98EB* ID_OUI_FROM_DATABASE=Ocedo GmbH OUI:9C8888* ID_OUI_FROM_DATABASE=Simac Techniek NV OUI:180C14* ID_OUI_FROM_DATABASE=iSonea Limited OUI:8CAE89* ID_OUI_FROM_DATABASE=Y-cam Solutions Ltd OUI:58B961* ID_OUI_FROM_DATABASE=SOLEM Electronique OUI:F46ABC* ID_OUI_FROM_DATABASE=Adonit Corp. Ltd. OUI:20180E* ID_OUI_FROM_DATABASE=Shenzhen Sunchip Technology Co., Ltd OUI:80B219* ID_OUI_FROM_DATABASE=ELEKTRON TECHNOLOGY UK LIMITED OUI:D08A55* ID_OUI_FROM_DATABASE=Skullcandy OUI:C4D655* ID_OUI_FROM_DATABASE=Tercel technology co.,ltd OUI:9CA10A* ID_OUI_FROM_DATABASE=SCLE SFE OUI:78D99F* ID_OUI_FROM_DATABASE=NuCom HK Ltd. OUI:44C56F* ID_OUI_FROM_DATABASE=NGN Easy Satfinder (Tianjin) Electronic Co., Ltd OUI:2C5A05* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:848336* ID_OUI_FROM_DATABASE=Newrun OUI:EC71DB* ID_OUI_FROM_DATABASE=Shenzhen Baichuan Digital Technology Co., Ltd. OUI:B8266C* ID_OUI_FROM_DATABASE=ANOV France OUI:284D92* ID_OUI_FROM_DATABASE=Luminator OUI:1C4BB9* ID_OUI_FROM_DATABASE=SMG ENTERPRISE, LLC OUI:0C5CD8* ID_OUI_FROM_DATABASE=DOLI Elektronik GmbH OUI:2C5FF3* ID_OUI_FROM_DATABASE=Pertronic Industries OUI:E0AF4B* ID_OUI_FROM_DATABASE=Pluribus Networks, Inc. OUI:50FC9F* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:C85663* ID_OUI_FROM_DATABASE=Sunflex Europe GmbH OUI:88FED6* ID_OUI_FROM_DATABASE=ShangHai WangYong Software Co., Ltd. OUI:600347* ID_OUI_FROM_DATABASE=Billion Electric Co. Ltd. OUI:084027* ID_OUI_FROM_DATABASE=Gridstore Inc. OUI:7C2048* ID_OUI_FROM_DATABASE=KoamTac OUI:BCF5AC* ID_OUI_FROM_DATABASE=LG Electronics OUI:705986* ID_OUI_FROM_DATABASE=OOO TTV OUI:20DF3F* ID_OUI_FROM_DATABASE=Nanjing SAC Power Grid Automation Co., Ltd. OUI:30786B* ID_OUI_FROM_DATABASE=TIANJIN Golden Pentagon Electronics Co., Ltd. OUI:4CD637* ID_OUI_FROM_DATABASE=Qsono Electronics Co., Ltd OUI:8CF945* ID_OUI_FROM_DATABASE=Power Automation pte Ltd OUI:2C922C* ID_OUI_FROM_DATABASE=Kishu Giken Kogyou Company Ltd,. OUI:509871* ID_OUI_FROM_DATABASE=Inventum Technologies Private Limited OUI:384233* ID_OUI_FROM_DATABASE=Wildeboer Bauteile GmbH OUI:9440A2* ID_OUI_FROM_DATABASE=Anywave Communication Technologies, Inc. OUI:7CB77B* ID_OUI_FROM_DATABASE=Paradigm Electronics Inc OUI:28A241* ID_OUI_FROM_DATABASE=exlar corp OUI:9876B6* ID_OUI_FROM_DATABASE=Adafruit OUI:AC220B* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:88354C* ID_OUI_FROM_DATABASE=Transics OUI:709BFC* ID_OUI_FROM_DATABASE=Bryton Inc. OUI:D82D9B* ID_OUI_FROM_DATABASE=Shenzhen G.Credit Communication Technology Co., Ltd OUI:94BF1E* ID_OUI_FROM_DATABASE=eflow Inc. / Smart Device Planning and Development Division OUI:C0A39E* ID_OUI_FROM_DATABASE=EarthCam, Inc. OUI:088E4F* ID_OUI_FROM_DATABASE=SF Software Solutions OUI:E8EADA* ID_OUI_FROM_DATABASE=Denkovi Assembly Electroncs LTD OUI:DCAE04* ID_OUI_FROM_DATABASE=CELOXICA Ltd OUI:5422F8* ID_OUI_FROM_DATABASE=zte corporation OUI:486E73* ID_OUI_FROM_DATABASE=Pica8, Inc. OUI:A0CEC8* ID_OUI_FROM_DATABASE=CE LINK LIMITED OUI:907A28* ID_OUI_FROM_DATABASE=Beijing Morncloud Information And Technology Co. Ltd. OUI:28285D* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:CCD29B* ID_OUI_FROM_DATABASE=Shenzhen Bopengfa Elec&Technology CO.,Ltd OUI:9C4EBF* ID_OUI_FROM_DATABASE=BoxCast OUI:34A68C* ID_OUI_FROM_DATABASE=Shine Profit Development Limited OUI:78DAB3* ID_OUI_FROM_DATABASE=GBO Technology OUI:80BBEB* ID_OUI_FROM_DATABASE=Satmap Systems Ltd OUI:6CB7F4* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:C06599* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:182666* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:949FB4* ID_OUI_FROM_DATABASE=ChengDu JiaFaAnTai Technology Co.,Ltd OUI:406826* ID_OUI_FROM_DATABASE=Thales UK Limited OUI:5C15E1* ID_OUI_FROM_DATABASE=AIDC TECHNOLOGY (S) PTE LTD OUI:048D38* ID_OUI_FROM_DATABASE=Netcore Technology Inc. OUI:1C4AF7* ID_OUI_FROM_DATABASE=AMON INC OUI:985D46* ID_OUI_FROM_DATABASE=PeopleNet Communication OUI:446755* ID_OUI_FROM_DATABASE=Orbit Irrigation OUI:789F4C* ID_OUI_FROM_DATABASE=HOERBIGER Elektronik GmbH OUI:98F8C1* ID_OUI_FROM_DATABASE=IDT Technology Limited OUI:F47A4E* ID_OUI_FROM_DATABASE=Woojeon&Handan OUI:28BAB5* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:44700B* ID_OUI_FROM_DATABASE=IFFU OUI:8C2F39* ID_OUI_FROM_DATABASE=IBA Dosimetry GmbH OUI:B8F828* ID_OUI_FROM_DATABASE=Changshu Gaoshida Optoelectronic Technology Co. Ltd. OUI:58468F* ID_OUI_FROM_DATABASE=Koncar Electronics and Informatics OUI:103B59* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:746630* ID_OUI_FROM_DATABASE=T:mi Ytti OUI:70E284* ID_OUI_FROM_DATABASE=Wistron InfoComm(Zhongshan) Corporation OUI:B0FEBD* ID_OUI_FROM_DATABASE=Private OUI:940BD5* ID_OUI_FROM_DATABASE=Himax Technologies, Inc OUI:30055C* ID_OUI_FROM_DATABASE=Brother industries, LTD. OUI:0C8268* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:B01743* ID_OUI_FROM_DATABASE=EDISON GLOBAL CIRCUITS LLC OUI:90DA4E* ID_OUI_FROM_DATABASE=AVANU OUI:7038B4* ID_OUI_FROM_DATABASE=Low Tech Solutions OUI:AC1826* ID_OUI_FROM_DATABASE=SEIKO EPSON CORPORATION OUI:4C804F* ID_OUI_FROM_DATABASE=Armstrong Monitoring Corp OUI:901D27* ID_OUI_FROM_DATABASE=zte corporation OUI:7CD762* ID_OUI_FROM_DATABASE=Freestyle Technology Pty Ltd OUI:D073D5* ID_OUI_FROM_DATABASE=LIFI LABS MANAGEMENT PTY LTD OUI:B8C46F* ID_OUI_FROM_DATABASE=PRIMMCON INDUSTRIES INC OUI:505AC6* ID_OUI_FROM_DATABASE=GUANGDONG SUPER TELECOM CO.,LTD. OUI:38A86B* ID_OUI_FROM_DATABASE=Orga BV OUI:141330* ID_OUI_FROM_DATABASE=Anakreon UK LLP OUI:0CF405* ID_OUI_FROM_DATABASE=Beijing Signalway Technologies Co.,Ltd OUI:BC72B1* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:78F7BE* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:1C76CA* ID_OUI_FROM_DATABASE=Terasic Technologies Inc. OUI:0C1105* ID_OUI_FROM_DATABASE=Ringslink (Xiamen) Network Communication Technologies Co., Ltd OUI:945047* ID_OUI_FROM_DATABASE=Rechnerbetriebsgruppe OUI:D8DCE9* ID_OUI_FROM_DATABASE=Kunshan Erlab ductless filtration system Co.,Ltd OUI:54112F* ID_OUI_FROM_DATABASE=Sulzer Pump Solutions Finland Oy OUI:E0DCA0* ID_OUI_FROM_DATABASE=Siemens Electrical Apparatus Ltd., Suzhou Chengdu Branch OUI:4C55B8* ID_OUI_FROM_DATABASE=Turkcell Teknoloji OUI:088039* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:2C72C3* ID_OUI_FROM_DATABASE=Soundmatters OUI:84E4D9* ID_OUI_FROM_DATABASE=Shenzhen NEED technology Ltd. OUI:C44838* ID_OUI_FROM_DATABASE=Satcom Direct, Inc. OUI:545414* ID_OUI_FROM_DATABASE=Digital RF Corea, Inc OUI:24EB65* ID_OUI_FROM_DATABASE=SAET I.S. S.r.l. OUI:D0F27F* ID_OUI_FROM_DATABASE=SteadyServ Technoligies, LLC OUI:DC647C* ID_OUI_FROM_DATABASE=C.R.S. iiMotion GmbH OUI:188410* ID_OUI_FROM_DATABASE=CoreTrust Inc. OUI:A08A87* ID_OUI_FROM_DATABASE=HuiZhou KaiYue Electronic Co.,Ltd OUI:04BFA8* ID_OUI_FROM_DATABASE=ISB Corporation OUI:5C8486* ID_OUI_FROM_DATABASE=Brightsource Industries Israel LTD OUI:28CD9C* ID_OUI_FROM_DATABASE=Shenzhen Dynamax Software Development Co.,Ltd. OUI:E0EDC7* ID_OUI_FROM_DATABASE=Shenzhen Friendcom Technology Development Co., Ltd OUI:2CF203* ID_OUI_FROM_DATABASE=EMKO ELEKTRONIK SAN VE TIC AS OUI:246278* ID_OUI_FROM_DATABASE=sysmocom - systems for mobile communications GmbH OUI:F45842* ID_OUI_FROM_DATABASE=Boxx TV Ltd OUI:A861AA* ID_OUI_FROM_DATABASE=Cloudview Limited OUI:C89346* ID_OUI_FROM_DATABASE=MXCHIP Company Limited OUI:F0F260* ID_OUI_FROM_DATABASE=Mobitec AB OUI:1423D7* ID_OUI_FROM_DATABASE=EUTRONIX CO., LTD. OUI:1C3E84* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:3CFB96* ID_OUI_FROM_DATABASE=Emcraft Systems LLC OUI:081F3F* ID_OUI_FROM_DATABASE=WondaLink Inc. OUI:DC6F08* ID_OUI_FROM_DATABASE=Bay Storage Technology OUI:E492E7* ID_OUI_FROM_DATABASE=Gridlink Tech. Co.,Ltd. OUI:60BB0C* ID_OUI_FROM_DATABASE=Beijing HuaqinWorld Technology Co,Ltd OUI:70E027* ID_OUI_FROM_DATABASE=HONGYU COMMUNICATION TECHNOLOGY LIMITED OUI:E880D8* ID_OUI_FROM_DATABASE=GNTEK Electronics Co.,Ltd. OUI:889B39* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:E432CB* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:188857* ID_OUI_FROM_DATABASE=Beijing Jinhong Xi-Dian Information Technology Corp. OUI:287994* ID_OUI_FROM_DATABASE=Realplay Digital Technology(Shenzhen) Co.,Ltd OUI:105C3B* ID_OUI_FROM_DATABASE=Perma-Pipe, Inc. OUI:40C4D6* ID_OUI_FROM_DATABASE=ChongQing Camyu Technology Development Co.,Ltd. OUI:A0EB76* ID_OUI_FROM_DATABASE=AirCUVE Inc. OUI:6C6126* ID_OUI_FROM_DATABASE=Rinicom Holdings OUI:C04DF7* ID_OUI_FROM_DATABASE=SERELEC OUI:ECD040* ID_OUI_FROM_DATABASE=GEA Farm Technologies GmbH OUI:005907* ID_OUI_FROM_DATABASE=LenovoEMC Products USA, LLC OUI:78B3CE* ID_OUI_FROM_DATABASE=Elo touch solutions OUI:A8FB70* ID_OUI_FROM_DATABASE=WiseSec L.t.d OUI:30F31D* ID_OUI_FROM_DATABASE=zte corporation OUI:E4776B* ID_OUI_FROM_DATABASE=AARTESYS AG OUI:5C335C* ID_OUI_FROM_DATABASE=Swissphone Telecom AG OUI:A4FCCE* ID_OUI_FROM_DATABASE=Security Expert Ltd. OUI:E0CEC3* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:5C43D2* ID_OUI_FROM_DATABASE=HAZEMEYER OUI:D819CE* ID_OUI_FROM_DATABASE=Telesquare OUI:D809C3* ID_OUI_FROM_DATABASE=Cercacor Labs OUI:84ED33* ID_OUI_FROM_DATABASE=BBMC Co.,Ltd OUI:681E8B* ID_OUI_FROM_DATABASE=InfoSight Corporation OUI:C044E3* ID_OUI_FROM_DATABASE=Shenzhen Sinkna Electronics Co., LTD OUI:08F1B7* ID_OUI_FROM_DATABASE=Towerstream Corpration OUI:20858C* ID_OUI_FROM_DATABASE=Assa OUI:187A93* ID_OUI_FROM_DATABASE=AMICCOM Electronics Corporation OUI:94C962* ID_OUI_FROM_DATABASE=Teseq AG OUI:B8763F* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:384369* ID_OUI_FROM_DATABASE=Patrol Products Consortium LLC OUI:D08B7E* ID_OUI_FROM_DATABASE=Passif Semiconductor OUI:6886E7* ID_OUI_FROM_DATABASE=Orbotix, Inc. OUI:2CE871* ID_OUI_FROM_DATABASE=Alert Metalguard ApS OUI:58D071* ID_OUI_FROM_DATABASE=BW Broadcast OUI:C0A0C7* ID_OUI_FROM_DATABASE=FAIRFIELD INDUSTRIES OUI:98208E* ID_OUI_FROM_DATABASE=Definium Technologies OUI:704AE4* ID_OUI_FROM_DATABASE=Rinstrum Pty Ltd OUI:5CA39D* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS CO., LTD. OUI:68B8D9* ID_OUI_FROM_DATABASE=Act KDE, Inc. OUI:F84897* ID_OUI_FROM_DATABASE=Hitachi, Ltd. OUI:74E424* ID_OUI_FROM_DATABASE=APISTE CORPORATION OUI:58D6D3* ID_OUI_FROM_DATABASE=Dairy Cheq Inc OUI:68FB95* ID_OUI_FROM_DATABASE=Generalplus Technology Inc. OUI:6002B4* ID_OUI_FROM_DATABASE=Wistron NeWeb Corp. OUI:E4C146* ID_OUI_FROM_DATABASE=Objetivos y Servicios de Valor A OUI:D4BF2D* ID_OUI_FROM_DATABASE=SE Controls Asia Pacific Ltd OUI:C45DD8* ID_OUI_FROM_DATABASE=HDMI Forum OUI:C44EAC* ID_OUI_FROM_DATABASE=Shenzhen Shiningworth Technology Co., Ltd. OUI:44334C* ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD OUI:C458C2* ID_OUI_FROM_DATABASE=Shenzhen TATFOOK Technology Co., Ltd. OUI:44184F* ID_OUI_FROM_DATABASE=Fitview OUI:8C76C1* ID_OUI_FROM_DATABASE=Goden Tech Limited OUI:DC2A14* ID_OUI_FROM_DATABASE=Shanghai Longjing Technology Co. OUI:0C191F* ID_OUI_FROM_DATABASE=Inform Electronik OUI:080FFA* ID_OUI_FROM_DATABASE=KSP INC. OUI:ECFC55* ID_OUI_FROM_DATABASE=A. Eberle GmbH & Co. KG OUI:0C8CDC* ID_OUI_FROM_DATABASE=Suunto Oy OUI:20B5C6* ID_OUI_FROM_DATABASE=Mimosa Networks OUI:AC3CB4* ID_OUI_FROM_DATABASE=Nilan A/S OUI:A830AD* ID_OUI_FROM_DATABASE=Wei Fang Goertek Electronics Co.,Ltd OUI:8007A2* ID_OUI_FROM_DATABASE=Esson Technology Inc. OUI:2C3557* ID_OUI_FROM_DATABASE=ELLIY Power CO..Ltd OUI:6C5A34* ID_OUI_FROM_DATABASE=Shenzhen Haitianxiong Electronic Co., Ltd. OUI:485A3F* ID_OUI_FROM_DATABASE=WISOL OUI:70F1E5* ID_OUI_FROM_DATABASE=Xetawave LLC OUI:C0AA68* ID_OUI_FROM_DATABASE=OSASI Technos Inc. OUI:B829F7* ID_OUI_FROM_DATABASE=Blaster Tech OUI:CC2D8C* ID_OUI_FROM_DATABASE=LG Electronics Inc OUI:00C14F* ID_OUI_FROM_DATABASE=DDL Co,.ltd. OUI:5CE0CA* ID_OUI_FROM_DATABASE=FeiTian United (Beijing) System Technology Co., Ltd. OUI:9C9811* ID_OUI_FROM_DATABASE=Guangzhou Sunrise Electronics Development Co., Ltd OUI:A0FE91* ID_OUI_FROM_DATABASE=AVAT Automation GmbH OUI:5809E5* ID_OUI_FROM_DATABASE=Kivic Inc. OUI:74ECF1* ID_OUI_FROM_DATABASE=Acumen OUI:6815D3* ID_OUI_FROM_DATABASE=Zaklady Elektroniki i Mechaniki Precyzyjnej R&G S.A. OUI:50B7C3* ID_OUI_FROM_DATABASE=Samsung Electronics CO., LTD OUI:601929* ID_OUI_FROM_DATABASE=VOLTRONIC POWER TECHNOLOGY(SHENZHEN) CORP. OUI:C0BD42* ID_OUI_FROM_DATABASE=ZPA Smart Energy a.s. OUI:48B253* ID_OUI_FROM_DATABASE=Marketaxess Corporation OUI:60D2B9* ID_OUI_FROM_DATABASE=REALAND BIO CO., LTD. OUI:2067B1* ID_OUI_FROM_DATABASE=Pluto inc. OUI:087D21* ID_OUI_FROM_DATABASE=Altasec technology corporation OUI:30FD11* ID_OUI_FROM_DATABASE=MACROTECH (USA) INC. OUI:F8051C* ID_OUI_FROM_DATABASE=DRS Imaging and Targeting Solutions OUI:6032F0* ID_OUI_FROM_DATABASE=Mplus technology OUI:749975* ID_OUI_FROM_DATABASE=IBM Corporation OUI:0CDCCC* ID_OUI_FROM_DATABASE=Inala Technologies OUI:F0ACA4* ID_OUI_FROM_DATABASE=HBC-radiomatic OUI:14DB85* ID_OUI_FROM_DATABASE=S NET MEDIA OUI:D493A0* ID_OUI_FROM_DATABASE=Fidelix Oy OUI:AC7236* ID_OUI_FROM_DATABASE=Lexking Technology Co., Ltd. OUI:CCB3F8* ID_OUI_FROM_DATABASE=FUJITSU ISOTEC LIMITED OUI:3CD7DA* ID_OUI_FROM_DATABASE=SK Mtek microelectronics(shenzhen)limited OUI:E86D54* ID_OUI_FROM_DATABASE=Digit Mobile Inc OUI:9857D3* ID_OUI_FROM_DATABASE=HON HAI-CCPBG PRECISION IND.CO.,LTD. OUI:689423* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:9C8D1A* ID_OUI_FROM_DATABASE=INTEG process group inc OUI:742D0A* ID_OUI_FROM_DATABASE=Norfolk Elektronik AG OUI:480362* ID_OUI_FROM_DATABASE=DESAY ELECTRONICS(HUIZHOU)CO.,LTD OUI:B0358D* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:0CF361* ID_OUI_FROM_DATABASE=Java Information OUI:34BDFA* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:70F927* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:A8AD3D* ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd OUI:8CEEC6* ID_OUI_FROM_DATABASE=Precepscion Pty. Ltd. OUI:ECD950* ID_OUI_FROM_DATABASE=IRT SA OUI:74273C* ID_OUI_FROM_DATABASE=ChangYang Technology (Nanjing) Co., LTD OUI:087CBE* ID_OUI_FROM_DATABASE=Quintic Corp. OUI:C4AD21* ID_OUI_FROM_DATABASE=MEDIAEDGE Corporation OUI:DCBF90* ID_OUI_FROM_DATABASE=HUIZHOU QIAOXING TELECOMMUNICATION INDUSTRY CO.,LTD. OUI:E0F5CA* ID_OUI_FROM_DATABASE=CHENG UEI PRECISION INDUSTRY CO.,LTD. OUI:1C5C60* ID_OUI_FROM_DATABASE=Shenzhen Belzon Technology Co.,LTD. OUI:2CEDEB* ID_OUI_FROM_DATABASE=Alpheus Digital Company Limited OUI:381C4A* ID_OUI_FROM_DATABASE=SIMCom Wireless Solutions Co.,Ltd. OUI:C8DE51* ID_OUI_FROM_DATABASE=Integra Networks, Inc. OUI:5CE8EB* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:901EDD* ID_OUI_FROM_DATABASE=GREAT COMPUTER CORPORATION OUI:2C6289* ID_OUI_FROM_DATABASE=Regenersis (Glenrothes) Ltd OUI:F093C5* ID_OUI_FROM_DATABASE=Garland Technology OUI:4C09B4* ID_OUI_FROM_DATABASE=zte corporation OUI:B8B94E* ID_OUI_FROM_DATABASE=Shenzhen iBaby Labs, Inc. OUI:00F403* ID_OUI_FROM_DATABASE=Orbis Systems Oy OUI:ACC698* ID_OUI_FROM_DATABASE=Kohzu Precision Co., Ltd. OUI:907025* ID_OUI_FROM_DATABASE=Garea Microsys Co.,Ltd. OUI:502ECE* ID_OUI_FROM_DATABASE=Asahi Electronics Co.,Ltd OUI:440CFD* ID_OUI_FROM_DATABASE=NetMan Co., Ltd. OUI:7CEBEA* ID_OUI_FROM_DATABASE=ASCT OUI:085B0E* ID_OUI_FROM_DATABASE=Fortinet, Inc. OUI:4C0FC7* ID_OUI_FROM_DATABASE=Earda Electronics Co.,Ltd OUI:64C944* ID_OUI_FROM_DATABASE=LARK Technologies, Inc OUI:6869F2* ID_OUI_FROM_DATABASE=ComAp s.r.o. OUI:B889CA* ID_OUI_FROM_DATABASE=ILJIN ELECTRIC Co., Ltd. OUI:B85AFE* ID_OUI_FROM_DATABASE=Handaer Communication Technology (Beijing) Co., Ltd OUI:604616* ID_OUI_FROM_DATABASE=XIAMEN VANN INTELLIGENT CO., LTD OUI:ECD925* ID_OUI_FROM_DATABASE=RAMI OUI:38AA3C* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS OUI:049F06* ID_OUI_FROM_DATABASE=Smobile Co., Ltd. OUI:D806D1* ID_OUI_FROM_DATABASE=Honeywell Fire System (Shanghai) Co,. Ltd. OUI:687251* ID_OUI_FROM_DATABASE=Ubiquiti Networks OUI:B8D9CE* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:8C6AE4* ID_OUI_FROM_DATABASE=Viogem Limited OUI:20C1AF* ID_OUI_FROM_DATABASE=i Wit Digital Co., Limited OUI:D88A3B* ID_OUI_FROM_DATABASE=UNIT-EM OUI:BCD940* ID_OUI_FROM_DATABASE=ASR Co,.Ltd. OUI:F45214* ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. OUI:EC4993* ID_OUI_FROM_DATABASE=Qihan Technology Co., Ltd OUI:B0ACFA* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:1C959F* ID_OUI_FROM_DATABASE=Veethree Electronics And Marine LLC OUI:18D949* ID_OUI_FROM_DATABASE=Qvis Labs, LLC OUI:646223* ID_OUI_FROM_DATABASE=Cellient Co., Ltd. OUI:F0E77E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:ACF0B2* ID_OUI_FROM_DATABASE=Becker Electronics Taiwan Ltd. OUI:10A932* ID_OUI_FROM_DATABASE=Beijing Cyber Cloud Technology Co. ,Ltd. OUI:C47BA3* ID_OUI_FROM_DATABASE=NAVIS Inc. OUI:A81758* ID_OUI_FROM_DATABASE=Elektronik System i Umeå AB OUI:44348F* ID_OUI_FROM_DATABASE=MXT INDUSTRIAL LTDA OUI:9C0111* ID_OUI_FROM_DATABASE=Shenzhen Newabel Electronic Co., Ltd. OUI:0CA138* ID_OUI_FROM_DATABASE=Blinq Wireless Inc. OUI:B0B2DC* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:348137* ID_OUI_FROM_DATABASE=UNICARD SA OUI:64F242* ID_OUI_FROM_DATABASE=Gerdes Aktiengesellschaft OUI:60F281* ID_OUI_FROM_DATABASE=TRANWO TECHNOLOGY CO., LTD. OUI:B0E892* ID_OUI_FROM_DATABASE=SEIKO EPSON CORPORATION OUI:642400* ID_OUI_FROM_DATABASE=Xorcom Ltd. OUI:4CAA16* ID_OUI_FROM_DATABASE=AzureWave Technologies (Shanghai) Inc. OUI:1C6BCA* ID_OUI_FROM_DATABASE=Mitsunami Co., Ltd. OUI:08379C* ID_OUI_FROM_DATABASE=Topaz Co. LTD. OUI:E83EFB* ID_OUI_FROM_DATABASE=GEODESIC LTD. OUI:4016FA* ID_OUI_FROM_DATABASE=EKM Metering OUI:3C363D* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:BC0200* ID_OUI_FROM_DATABASE=Stewart Audio OUI:1C973D* ID_OUI_FROM_DATABASE=PRICOM Design OUI:8018A7* ID_OUI_FROM_DATABASE=Samsung Eletronics Co., Ltd OUI:F00786* ID_OUI_FROM_DATABASE=Shandong Bittel Electronics Co., Ltd OUI:885C47* ID_OUI_FROM_DATABASE=Alcatel Lucent OUI:E0F9BE* ID_OUI_FROM_DATABASE=Cloudena Corp. OUI:3CC1F6* ID_OUI_FROM_DATABASE=Melange Systems Pvt. Ltd. OUI:54E63F* ID_OUI_FROM_DATABASE=ShenZhen LingKeWeiEr Technology Co., Ltd. OUI:006B9E* ID_OUI_FROM_DATABASE=VIZIO Inc OUI:F88C1C* ID_OUI_FROM_DATABASE=KAISHUN ELECTRONIC TECHNOLOGY CO., LTD. BEIJING OUI:940149* ID_OUI_FROM_DATABASE=AutoHotBox OUI:C035BD* ID_OUI_FROM_DATABASE=Velocytech Aps OUI:F897CF* ID_OUI_FROM_DATABASE=DAESHIN-INFORMATION TECHNOLOGY CO., LTD. OUI:383F10* ID_OUI_FROM_DATABASE=DBL Technology Ltd. OUI:8C6878* ID_OUI_FROM_DATABASE=Nortek-AS OUI:8016B7* ID_OUI_FROM_DATABASE=Brunel University OUI:9C611D* ID_OUI_FROM_DATABASE=Omni-ID USA, Inc. OUI:78BEBD* ID_OUI_FROM_DATABASE=STULZ GmbH OUI:3C9174* ID_OUI_FROM_DATABASE=ALONG COMMUNICATION TECHNOLOGY OUI:B8E937* ID_OUI_FROM_DATABASE=Sonos, Inc. OUI:E8D0FA* ID_OUI_FROM_DATABASE=MKS Instruments Deutschland GmbH OUI:98262A* ID_OUI_FROM_DATABASE=Applied Research Associates, Inc OUI:B0D2F5* ID_OUI_FROM_DATABASE=Vello Systems, Inc. OUI:C89F42* ID_OUI_FROM_DATABASE=VDII Innovation AB OUI:A41875* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:640E94* ID_OUI_FROM_DATABASE=Pluribus Networks, Inc. OUI:6CE983* ID_OUI_FROM_DATABASE=Gastron Co., LTD. OUI:0CB4EF* ID_OUI_FROM_DATABASE=Digience Co.,Ltd. OUI:D0DB32* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:609084* ID_OUI_FROM_DATABASE=DSSD Inc OUI:A4E731* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:0808EA* ID_OUI_FROM_DATABASE=AMSC OUI:C05E79* ID_OUI_FROM_DATABASE=SHENZHEN HUAXUN ARK TECHNOLOGIES CO.,LTD OUI:A4934C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E85484* ID_OUI_FROM_DATABASE=NEO Information Systems Co., Ltd. OUI:206432* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO.,LTD. OUI:74AE76* ID_OUI_FROM_DATABASE=iNovo Broadband, Inc. OUI:60B933* ID_OUI_FROM_DATABASE=Deutron Electronics Corp. OUI:38EE9D* ID_OUI_FROM_DATABASE=Anedo Ltd. OUI:80CEB1* ID_OUI_FROM_DATABASE=Theissen Training Systems GmbH OUI:3C3888* ID_OUI_FROM_DATABASE=ConnectQuest, llc OUI:08BE09* ID_OUI_FROM_DATABASE=Astrol Electronic AG OUI:D8B8F6* ID_OUI_FROM_DATABASE=Nantworks OUI:6044F5* ID_OUI_FROM_DATABASE=Easy Digital Ltd. OUI:AC51EE* ID_OUI_FROM_DATABASE=Cambridge Communication Systems Ltd OUI:00AA70* ID_OUI_FROM_DATABASE=LG Electronics OUI:10E4AF* ID_OUI_FROM_DATABASE=APR, LLC OUI:E03005* ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd OUI:B0BD6D* ID_OUI_FROM_DATABASE=Echostreams Innovative Solutions OUI:F0D14F* ID_OUI_FROM_DATABASE=LINEAR LLC OUI:AC3D75* ID_OUI_FROM_DATABASE=HANGZHOU ZHIWAY TECHNOLOGIES CO.,LTD. OUI:C01885* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:141A51* ID_OUI_FROM_DATABASE=Treetech Sistemas Digitais OUI:845787* ID_OUI_FROM_DATABASE=DVR C&C Co., Ltd. OUI:F436E1* ID_OUI_FROM_DATABASE=Abilis Systems SARL OUI:587FC8* ID_OUI_FROM_DATABASE=S2M OUI:C49805* ID_OUI_FROM_DATABASE=Minieum Networks, Inc OUI:90F4C1* ID_OUI_FROM_DATABASE=Rand McNally OUI:18193F* ID_OUI_FROM_DATABASE=Tamtron Oy OUI:F8F7FF* ID_OUI_FROM_DATABASE=SYN-TECH SYSTEMS INC OUI:F473CA* ID_OUI_FROM_DATABASE=Conversion Sound Inc. OUI:00E8AB* ID_OUI_FROM_DATABASE=Meggitt Training Systems, Inc. OUI:18421D* ID_OUI_FROM_DATABASE=Private OUI:78617C* ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD OUI:C401B1* ID_OUI_FROM_DATABASE=SeekTech INC OUI:1C5FFF* ID_OUI_FROM_DATABASE=Beijing Ereneben Information Technology Co.,Ltd Shenzhen Branch OUI:C0C946* ID_OUI_FROM_DATABASE=MITSUYA LABORATORIES INC. OUI:ACC2EC* ID_OUI_FROM_DATABASE=CLT INT'L IND. CORP. OUI:702F4B* ID_OUI_FROM_DATABASE=PolyVision Inc. OUI:741489* ID_OUI_FROM_DATABASE=SRT Wireless OUI:94CA0F* ID_OUI_FROM_DATABASE=Honeywell Analytics OUI:848D84* ID_OUI_FROM_DATABASE=Rajant Corporation OUI:D8337F* ID_OUI_FROM_DATABASE=Office FA.com Co.,Ltd. OUI:7CEF8A* ID_OUI_FROM_DATABASE=Inhon International Ltd. OUI:84AF1F* ID_OUI_FROM_DATABASE=Beat System Service Co,. Ltd. OUI:100D2F* ID_OUI_FROM_DATABASE=Online Security Pty. Ltd. OUI:408B07* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:980284* ID_OUI_FROM_DATABASE=Theobroma Systems GmbH OUI:E03C5B* ID_OUI_FROM_DATABASE=SHENZHEN JIAXINJIE ELECTRON CO.,LTD OUI:645563* ID_OUI_FROM_DATABASE=Intelight Inc. OUI:C467B5* ID_OUI_FROM_DATABASE=Libratone A/S OUI:A4EF52* ID_OUI_FROM_DATABASE=Telewave Co., Ltd. OUI:F4044C* ID_OUI_FROM_DATABASE=ValenceTech Limited OUI:1CBBA8* ID_OUI_FROM_DATABASE=OJSC Ufimskiy Zavod Promsvyaz OUI:506028* ID_OUI_FROM_DATABASE=Xirrus Inc. OUI:24B657* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:940B2D* ID_OUI_FROM_DATABASE=NetView Technologies(Shenzhen) Co., Ltd OUI:306E5C* ID_OUI_FROM_DATABASE=Validus Technologies OUI:E843B6* ID_OUI_FROM_DATABASE=QNAP Systems, Inc. OUI:5CC9D3* ID_OUI_FROM_DATABASE=PALLADIUM ENERGY ELETRONICA DA AMAZONIA LTDA OUI:407B1B* ID_OUI_FROM_DATABASE=Mettle Networks Inc. OUI:64E161* ID_OUI_FROM_DATABASE=DEP Corp. OUI:C8A620* ID_OUI_FROM_DATABASE=Nebula, Inc OUI:989080* ID_OUI_FROM_DATABASE=Linkpower Network System Inc Ltd. OUI:0064A6* ID_OUI_FROM_DATABASE=Maquet CardioVascular OUI:3C4E47* ID_OUI_FROM_DATABASE=Etronic A/S OUI:C8F9F9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:F0F755* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:10F96F* ID_OUI_FROM_DATABASE=LG Electronics OUI:B01C91* ID_OUI_FROM_DATABASE=Elim Co OUI:0CA2F4* ID_OUI_FROM_DATABASE=Chameleon Technology (UK) Limited OUI:846AED* ID_OUI_FROM_DATABASE=Wireless Tsukamoto.,co.LTD OUI:D8E952* ID_OUI_FROM_DATABASE=KEOPSYS OUI:3CB9A6* ID_OUI_FROM_DATABASE=Belden Deutschland GmbH OUI:3440B5* ID_OUI_FROM_DATABASE=IBM OUI:90D74F* ID_OUI_FROM_DATABASE=Bookeen OUI:905682* ID_OUI_FROM_DATABASE=Lenbrook Industries Limited OUI:CC6DEF* ID_OUI_FROM_DATABASE=TJK Tietolaite Oy OUI:3CE624* ID_OUI_FROM_DATABASE=LG Display OUI:D8F0F2* ID_OUI_FROM_DATABASE=Zeebo Inc OUI:B0CF4D* ID_OUI_FROM_DATABASE=MI-Zone Technology Ireland OUI:BCB1F3* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:143605* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:B87424* ID_OUI_FROM_DATABASE=Viessmann Elektronik GmbH OUI:C81AFE* ID_OUI_FROM_DATABASE=DLOGIC GmbH OUI:9C53CD* ID_OUI_FROM_DATABASE=ENGICAM s.r.l. OUI:DCC101* ID_OUI_FROM_DATABASE=SOLiD Technologies, Inc. OUI:AC6FBB* ID_OUI_FROM_DATABASE=TATUNG Technology Inc. OUI:1803FA* ID_OUI_FROM_DATABASE=IBT Interfaces OUI:608645* ID_OUI_FROM_DATABASE=Avery Weigh-Tronix, LLC OUI:541DFB* ID_OUI_FROM_DATABASE=Freestyle Energy Ltd OUI:9CF67D* ID_OUI_FROM_DATABASE=Ricardo Prague, s.r.o. OUI:A0E201* ID_OUI_FROM_DATABASE=AVTrace Ltd.(China) OUI:38ECE4* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:04EE91* ID_OUI_FROM_DATABASE=x-fabric GmbH OUI:183825* ID_OUI_FROM_DATABASE=Wuhan Lingjiu High-tech Co.,Ltd. OUI:5404A6* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:F83376* ID_OUI_FROM_DATABASE=Good Mind Innovation Co., Ltd. OUI:C46044* ID_OUI_FROM_DATABASE=Everex Electronics Limited OUI:645422* ID_OUI_FROM_DATABASE=Equinox Payments OUI:D412BB* ID_OUI_FROM_DATABASE=Quadrant Components Inc. Ltd OUI:40E793* ID_OUI_FROM_DATABASE=Shenzhen Siviton Technology Co.,Ltd OUI:2C67FB* ID_OUI_FROM_DATABASE=ShenZhen Zhengjili Electronics Co., LTD OUI:D89760* ID_OUI_FROM_DATABASE=C2 Development, Inc. OUI:1CB17F* ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. OUI:942E17* ID_OUI_FROM_DATABASE=Schneider Electric Canada Inc OUI:B89674* ID_OUI_FROM_DATABASE=AllDSP GmbH & Co. KG OUI:6CA682* ID_OUI_FROM_DATABASE=EDAM information & communications OUI:48A22D* ID_OUI_FROM_DATABASE=Shenzhen Huaxuchang Telecom Technology Co.,Ltd OUI:50ED94* ID_OUI_FROM_DATABASE=EGATEL SL OUI:B87447* ID_OUI_FROM_DATABASE=Convergence Technologies OUI:70A66A* ID_OUI_FROM_DATABASE=Prox Dynamics AS OUI:DC175A* ID_OUI_FROM_DATABASE=Hitachi High-Technologies Corporation OUI:9034FC* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:5C076F* ID_OUI_FROM_DATABASE=Thought Creator OUI:3C0FC1* ID_OUI_FROM_DATABASE=KBC Networks OUI:58E636* ID_OUI_FROM_DATABASE=EVRsafe Technologies OUI:90D11B* ID_OUI_FROM_DATABASE=Palomar Medical Technologies OUI:CC60BB* ID_OUI_FROM_DATABASE=Empower RF Systems OUI:24497B* ID_OUI_FROM_DATABASE=Innovative Converged Devices Inc OUI:ECBD09* ID_OUI_FROM_DATABASE=FUSION Electronics Ltd OUI:54847B* ID_OUI_FROM_DATABASE=Digital Devices GmbH OUI:705CAD* ID_OUI_FROM_DATABASE=Konami Gaming Inc OUI:788973* ID_OUI_FROM_DATABASE=CMC OUI:DCCE41* ID_OUI_FROM_DATABASE=FE GLOBAL HONG KONG LIMITED OUI:4C774F* ID_OUI_FROM_DATABASE=Embedded Wireless Labs OUI:203706* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:7C4C58* ID_OUI_FROM_DATABASE=Scale Computing, Inc. OUI:FCC23D* ID_OUI_FROM_DATABASE=Atmel Corporation OUI:7C1E52* ID_OUI_FROM_DATABASE=Microsoft OUI:DCB4C4* ID_OUI_FROM_DATABASE=Microsoft XCG OUI:74FDA0* ID_OUI_FROM_DATABASE=Compupal (Group) Corporation OUI:C029F3* ID_OUI_FROM_DATABASE=XySystem OUI:48F317* ID_OUI_FROM_DATABASE=Private OUI:B07D62* ID_OUI_FROM_DATABASE=Dipl.-Ing. H. Horstmann GmbH OUI:68974B* ID_OUI_FROM_DATABASE=Shenzhen Costar Electronics Co. Ltd. OUI:B8BB6D* ID_OUI_FROM_DATABASE=ENERES Co.,Ltd. OUI:645DD7* ID_OUI_FROM_DATABASE=Shenzhen Lifesense Medical Electronics Co., Ltd. OUI:D45AB2* ID_OUI_FROM_DATABASE=Galleon Systems OUI:C40142* ID_OUI_FROM_DATABASE=MaxMedia Technology Limited OUI:A06E50* ID_OUI_FROM_DATABASE=Nanotek Elektronik Sistemler Ltd. Sti. OUI:182C91* ID_OUI_FROM_DATABASE=Concept Development, Inc. OUI:EC4670* ID_OUI_FROM_DATABASE=Meinberg Funkuhren GmbH & Co. KG OUI:B40B7A* ID_OUI_FROM_DATABASE=Brusa Elektronik AG OUI:BC764E* ID_OUI_FROM_DATABASE=Rackspace US, Inc. OUI:C4EEAE* ID_OUI_FROM_DATABASE=VSS Monitoring OUI:2437EF* ID_OUI_FROM_DATABASE=EMC Electronic Media Communication SA OUI:CCF9E8* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:D4F63F* ID_OUI_FROM_DATABASE=IEA S.R.L. OUI:4C0289* ID_OUI_FROM_DATABASE=LEX COMPUTECH CO., LTD OUI:C0E54E* ID_OUI_FROM_DATABASE=DENX Computer Systems GmbH OUI:E435FB* ID_OUI_FROM_DATABASE=Sabre Technology (Hull) Ltd OUI:28BE9B* ID_OUI_FROM_DATABASE=Technicolor USA Inc. OUI:F01C13* ID_OUI_FROM_DATABASE=LG Electronics OUI:00CD90* ID_OUI_FROM_DATABASE=MAS Elektronik AG OUI:A8BD1A* ID_OUI_FROM_DATABASE=Honey Bee (Hong Kong) Limited OUI:ACCC8E* ID_OUI_FROM_DATABASE=Axis Communications AB OUI:187C81* ID_OUI_FROM_DATABASE=Valeo Vision Systems OUI:DC1EA3* ID_OUI_FROM_DATABASE=Accensus LLC OUI:A40130* ID_OUI_FROM_DATABASE=ABIsystems Co., LTD OUI:68F125* ID_OUI_FROM_DATABASE=Data Controls Inc. OUI:706F81* ID_OUI_FROM_DATABASE=Private OUI:30E4DB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:742B0F* ID_OUI_FROM_DATABASE=Infinidat Ltd. OUI:280CB8* ID_OUI_FROM_DATABASE=Mikrosay Yazilim ve Elektronik A.S. OUI:A06CEC* ID_OUI_FROM_DATABASE=RIM OUI:443EB2* ID_OUI_FROM_DATABASE=DEOTRON Co., LTD. OUI:8CB82C* ID_OUI_FROM_DATABASE=IPitomy Communications OUI:807DE3* ID_OUI_FROM_DATABASE=Chongqing Sichuan Instrument Microcircuit Co.LTD. OUI:1C8E8E* ID_OUI_FROM_DATABASE=DB Communication & Systems Co., ltd. OUI:F0022B* ID_OUI_FROM_DATABASE=Chrontel OUI:007F28* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:0C924E* ID_OUI_FROM_DATABASE=Rice Lake Weighing Systems OUI:40040C* ID_OUI_FROM_DATABASE=A&T OUI:A0165C* ID_OUI_FROM_DATABASE=Triteka LTD OUI:90B97D* ID_OUI_FROM_DATABASE=Johnson Outdoors Marine Electronics d/b/a Minnkota OUI:8821E3* ID_OUI_FROM_DATABASE=Nebusens, S.L. OUI:B0F1BC* ID_OUI_FROM_DATABASE=Dhemax Ingenieros Ltda OUI:3C096D* ID_OUI_FROM_DATABASE=Powerhouse Dynamics OUI:CC501C* ID_OUI_FROM_DATABASE=KVH Industries, Inc. OUI:AC6FD9* ID_OUI_FROM_DATABASE=Valueplus Inc. OUI:A4E391* ID_OUI_FROM_DATABASE=DENY FONTAINE OUI:04A82A* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:48D8FE* ID_OUI_FROM_DATABASE=ClarIDy Solutions, Inc. OUI:70B265* ID_OUI_FROM_DATABASE=Hiltron s.r.l. OUI:84D9C8* ID_OUI_FROM_DATABASE=Unipattern Co., OUI:1C955D* ID_OUI_FROM_DATABASE=I-LAX ELECTRONICS INC. OUI:94AAB8* ID_OUI_FROM_DATABASE=Joview(Beijing) Technology Co. Ltd. OUI:18B3BA* ID_OUI_FROM_DATABASE=Netlogic AB OUI:F43E9D* ID_OUI_FROM_DATABASE=Benu Networks, Inc. OUI:6469BC* ID_OUI_FROM_DATABASE=Hytera Communications Co .,ltd OUI:64094C* ID_OUI_FROM_DATABASE=Beijing Superbee Wireless Technology Co.,Ltd OUI:F0AE51* ID_OUI_FROM_DATABASE=Xi3 Corp OUI:782EEF* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:78510C* ID_OUI_FROM_DATABASE=LiveU Ltd. OUI:306118* ID_OUI_FROM_DATABASE=Paradom Inc. OUI:C84529* ID_OUI_FROM_DATABASE=IMK Networks Co.,Ltd OUI:A88CEE* ID_OUI_FROM_DATABASE=MicroMade Galka i Drozdz sp.j. OUI:204005* ID_OUI_FROM_DATABASE=feno GmbH OUI:CC52AF* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. OUI:6C81FE* ID_OUI_FROM_DATABASE=Mitsuba Corporation OUI:E8F928* ID_OUI_FROM_DATABASE=RFTECH SRL OUI:703AD8* ID_OUI_FROM_DATABASE=Shenzhen Afoundry Electronic Co., Ltd OUI:4C98EF* ID_OUI_FROM_DATABASE=Zeo OUI:DCA6BD* ID_OUI_FROM_DATABASE=Beijing Lanbo Technology Co., Ltd. OUI:D0667B* ID_OUI_FROM_DATABASE=Samsung Electronics Co., LTD OUI:58E808* ID_OUI_FROM_DATABASE=AUTONICS CORPORATION OUI:B8C716* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:8058C5* ID_OUI_FROM_DATABASE=NovaTec Kommunikationstechnik GmbH OUI:C0EAE4* ID_OUI_FROM_DATABASE=Sonicwall OUI:F8A9DE* ID_OUI_FROM_DATABASE=PUISSANCE PLUS OUI:D4F027* ID_OUI_FROM_DATABASE=Navetas Energy Management OUI:5C0CBB* ID_OUI_FROM_DATABASE=CELIZION Inc. OUI:B8871E* ID_OUI_FROM_DATABASE=Good Mind Industries Co., Ltd. OUI:F8EA0A* ID_OUI_FROM_DATABASE=Dipl.-Math. Michael Rauch OUI:BC5FF4* ID_OUI_FROM_DATABASE=ASRock Incorporation OUI:A4B36A* ID_OUI_FROM_DATABASE=JSC SDO Chromatec OUI:905F8D* ID_OUI_FROM_DATABASE=modas GmbH OUI:E0C922* ID_OUI_FROM_DATABASE=Jireh Energy Tech., Ltd. OUI:28401A* ID_OUI_FROM_DATABASE=C8 MediSensors, Inc. OUI:DC3C84* ID_OUI_FROM_DATABASE=Ticom Geomatics, Inc. OUI:E8CC32* ID_OUI_FROM_DATABASE=Micronet LTD OUI:9C6ABE* ID_OUI_FROM_DATABASE=QEES ApS. OUI:3429EA* ID_OUI_FROM_DATABASE=MCD ELECTRONICS SP. Z O.O. OUI:D43AE9* ID_OUI_FROM_DATABASE=DONGGUAN ipt INDUSTRIAL CO., LTD OUI:ACC935* ID_OUI_FROM_DATABASE=Ness Corporation OUI:7C4A82* ID_OUI_FROM_DATABASE=Portsmith LLC OUI:2C0033* ID_OUI_FROM_DATABASE=EControls, LLC OUI:E0F211* ID_OUI_FROM_DATABASE=Digitalwatt OUI:0432F4* ID_OUI_FROM_DATABASE=Partron OUI:AC199F* ID_OUI_FROM_DATABASE=SUNGROW POWER SUPPLY CO.,LTD. OUI:1CAA07* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:308CFB* ID_OUI_FROM_DATABASE=Dropcam OUI:CCF841* ID_OUI_FROM_DATABASE=Lumewave OUI:701404* ID_OUI_FROM_DATABASE=Limited Liability Company OUI:1C35F1* ID_OUI_FROM_DATABASE=NEW Lift Neue Elektronische Wege Steuerungsbau GmbH OUI:CCD9E9* ID_OUI_FROM_DATABASE=SCR Engineers Ltd. OUI:F0DB30* ID_OUI_FROM_DATABASE=Yottabyte OUI:9C31B6* ID_OUI_FROM_DATABASE=Kulite Semiconductor Products Inc OUI:5C6A7D* ID_OUI_FROM_DATABASE=KENTKART EGE ELEKTRONIK SAN. VE TIC. LTD. STI. OUI:04FF51* ID_OUI_FROM_DATABASE=NOVAMEDIA INNOVISION SP. Z O.O. OUI:FCD4F2* ID_OUI_FROM_DATABASE=The Coca Cola Company OUI:C471FE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:340804* ID_OUI_FROM_DATABASE=D-Link Corporation OUI:B44CC2* ID_OUI_FROM_DATABASE=NR ELECTRIC CO., LTD OUI:084EBF* ID_OUI_FROM_DATABASE=Broad Net Mux Corporation OUI:18ABF5* ID_OUI_FROM_DATABASE=Ultra Electronics - Electrics OUI:48CB6E* ID_OUI_FROM_DATABASE=Cello Electronics (UK) Ltd OUI:EC3BF0* ID_OUI_FROM_DATABASE=NovelSat OUI:A86A6F* ID_OUI_FROM_DATABASE=RIM OUI:4022ED* ID_OUI_FROM_DATABASE=Digital Projection Ltd OUI:0CA402* ID_OUI_FROM_DATABASE=Alcatel Lucent IPD OUI:0817F4* ID_OUI_FROM_DATABASE=IBM Corp OUI:C4D489* ID_OUI_FROM_DATABASE=JiangSu Joyque Information Industry Co.,Ltd OUI:1C7C11* ID_OUI_FROM_DATABASE=EID OUI:F43E61* ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co., Ltd OUI:B0B32B* ID_OUI_FROM_DATABASE=Slican Sp. z o.o. OUI:5842E4* ID_OUI_FROM_DATABASE=Baxter International Inc OUI:8CA048* ID_OUI_FROM_DATABASE=Beijing NeTopChip Technology Co.,LTD OUI:804F58* ID_OUI_FROM_DATABASE=ThinkEco, Inc. OUI:B06563* ID_OUI_FROM_DATABASE=Shanghai Railway Communication Factory OUI:349A0D* ID_OUI_FROM_DATABASE=ZBD Displays Ltd OUI:A0B5DA* ID_OUI_FROM_DATABASE=HongKong THTF Co., Ltd OUI:CCCD64* ID_OUI_FROM_DATABASE=SM-Electronic GmbH OUI:E82877* ID_OUI_FROM_DATABASE=TMY Co., Ltd. OUI:AC8112* ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. OUI:6CA906* ID_OUI_FROM_DATABASE=Telefield Ltd OUI:3C02B1* ID_OUI_FROM_DATABASE=Creation Technologies LP OUI:E46C21* ID_OUI_FROM_DATABASE=messMa GmbH OUI:0470BC* ID_OUI_FROM_DATABASE=Globalstar Inc. OUI:E05FB9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:081735* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:20FECD* ID_OUI_FROM_DATABASE=System In Frontier Inc. OUI:94D019* ID_OUI_FROM_DATABASE=Cydle Corp. OUI:9C220E* ID_OUI_FROM_DATABASE=TASCAN Service GmbH OUI:2CA157* ID_OUI_FROM_DATABASE=acromate, Inc. OUI:70DDA1* ID_OUI_FROM_DATABASE=Tellabs OUI:30EB25* ID_OUI_FROM_DATABASE=INTEK DIGITAL OUI:BC3E13* ID_OUI_FROM_DATABASE=Accordance Systems Inc. OUI:0455CA* ID_OUI_FROM_DATABASE=BriView (Xiamen) Corp. OUI:D45D42* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:BC2846* ID_OUI_FROM_DATABASE=NextBIT Computing Pvt. Ltd. OUI:4425BB* ID_OUI_FROM_DATABASE=Bamboo Entertainment Corporation OUI:B8A8AF* ID_OUI_FROM_DATABASE=Logic S.p.A. OUI:648125* ID_OUI_FROM_DATABASE=Alphatron Marine BV OUI:042605* ID_OUI_FROM_DATABASE=GFR Gesellschaft für Regelungstechnik und Energieeinsparung mbH OUI:9C645E* ID_OUI_FROM_DATABASE=Harman Consumer Group OUI:78CD8E* ID_OUI_FROM_DATABASE=SMC Networks Inc OUI:5C9AD8* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:144C1A* ID_OUI_FROM_DATABASE=Max Communication GmbH OUI:FCE557* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:BC6E76* ID_OUI_FROM_DATABASE=Green Energy Options Ltd OUI:108CCF* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:74E06E* ID_OUI_FROM_DATABASE=Ergophone GmbH OUI:18AF9F* ID_OUI_FROM_DATABASE=DIGITRONIC Automationsanlagen GmbH OUI:EC4644* ID_OUI_FROM_DATABASE=TTK SAS OUI:DCD87F* ID_OUI_FROM_DATABASE=Shenzhen JoinCyber Telecom Equipment Ltd OUI:B08991* ID_OUI_FROM_DATABASE=LGE OUI:44DCCB* ID_OUI_FROM_DATABASE=SEMINDIA SYSTEMS PVT LTD OUI:90D92C* ID_OUI_FROM_DATABASE=HUG-WITSCHI AG OUI:B428F1* ID_OUI_FROM_DATABASE=E-Prime Co., Ltd. OUI:B4749F* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:AC2FA8* ID_OUI_FROM_DATABASE=Humannix Co.,Ltd. OUI:7C4AA8* ID_OUI_FROM_DATABASE=MindTree Wireless PVT Ltd OUI:C8A70A* ID_OUI_FROM_DATABASE=Verizon Business OUI:304EC3* ID_OUI_FROM_DATABASE=Tianjin Techua Technology Co., Ltd. OUI:BC4377* ID_OUI_FROM_DATABASE=Hang Zhou Huite Technology Co.,ltd. OUI:A81B18* ID_OUI_FROM_DATABASE=XTS CORP OUI:04E2F8* ID_OUI_FROM_DATABASE=AEP Ticketing solutions srl OUI:8C5105* ID_OUI_FROM_DATABASE=Shenzhen ireadygo Information Technology CO.,LTD. OUI:28E297* ID_OUI_FROM_DATABASE=Shanghai InfoTM Microelectronics Co.,Ltd. OUI:D093F8* ID_OUI_FROM_DATABASE=Stonestreet One LLC OUI:1C334D* ID_OUI_FROM_DATABASE=ITS Telecom OUI:609E64* ID_OUI_FROM_DATABASE=Vivonic GmbH OUI:906EBB* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:D44F80* ID_OUI_FROM_DATABASE=Kemper Digital GmbH OUI:34684A* ID_OUI_FROM_DATABASE=Teraworks Co., Ltd. OUI:0CC6AC* ID_OUI_FROM_DATABASE=DAGS OUI:D82A7E* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:5CBD9E* ID_OUI_FROM_DATABASE=HONGKONG MIRACLE EAGLE TECHNOLOGY(GROUP) LIMITED OUI:743889* ID_OUI_FROM_DATABASE=ANNAX Anzeigesysteme GmbH OUI:E89A8F* ID_OUI_FROM_DATABASE=Quanta Computer Inc. OUI:647FDA* ID_OUI_FROM_DATABASE=TEKTELIC Communications Inc. OUI:90610C* ID_OUI_FROM_DATABASE=Fida International (S) Pte Ltd OUI:3C5F01* ID_OUI_FROM_DATABASE=Synerchip Co., Ltd. OUI:708B78* ID_OUI_FROM_DATABASE=citygrow technology co., ltd OUI:74CD0C* ID_OUI_FROM_DATABASE=Smith Myers Communications Ltd. OUI:B8EE79* ID_OUI_FROM_DATABASE=YWire Technologies, Inc. OUI:40C245* ID_OUI_FROM_DATABASE=Shenzhen Hexicom Technology Co., Ltd. OUI:7076F0* ID_OUI_FROM_DATABASE=LevelOne Communications (India) Private Limited OUI:48C8B6* ID_OUI_FROM_DATABASE=SysTec GmbH OUI:303855* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:9C4563* ID_OUI_FROM_DATABASE=DIMEP Sistemas OUI:E42771* ID_OUI_FROM_DATABASE=Smartlabs OUI:C4EEF5* ID_OUI_FROM_DATABASE=Oclaro, Inc. OUI:0876FF* ID_OUI_FROM_DATABASE=Thomson Telecom Belgium OUI:401D59* ID_OUI_FROM_DATABASE=Biometric Associates, LP OUI:4C2C80* ID_OUI_FROM_DATABASE=Beijing Skyway Technologies Co.,Ltd OUI:08D29A* ID_OUI_FROM_DATABASE=Proformatique OUI:90D852* ID_OUI_FROM_DATABASE=Comtec Co., Ltd. OUI:28061E* ID_OUI_FROM_DATABASE=NINGBO GLOBAL USEFUL ELECTRIC CO.,LTD OUI:4037AD* ID_OUI_FROM_DATABASE=Macro Image Technology, Inc. OUI:64E8E6* ID_OUI_FROM_DATABASE=global moisture management system OUI:34A183* ID_OUI_FROM_DATABASE=AWare, Inc OUI:740ABC* ID_OUI_FROM_DATABASE=JSJS Designs (Europe) Limited OUI:E8E0B7* ID_OUI_FROM_DATABASE=Toshiba OUI:588D09* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:342109* ID_OUI_FROM_DATABASE=Jensen Scandinavia AS OUI:08FAE0* ID_OUI_FROM_DATABASE=Fohhn Audio AG OUI:B439D6* ID_OUI_FROM_DATABASE=ProCurve Networking by HP OUI:506F9A* ID_OUI_FROM_DATABASE=Wi-Fi Alliance OUI:7CF098* ID_OUI_FROM_DATABASE=Bee Beans Technologies, Inc. OUI:9C7514* ID_OUI_FROM_DATABASE=Wildix srl OUI:BC7DD1* ID_OUI_FROM_DATABASE=Radio Data Comms OUI:28068D* ID_OUI_FROM_DATABASE=ITL, LLC OUI:F0D767* ID_OUI_FROM_DATABASE=Axema Passagekontroll AB OUI:A4AE9A* ID_OUI_FROM_DATABASE=Maestro Wireless Solutions ltd. OUI:5CD135* ID_OUI_FROM_DATABASE=Xtreme Power Systems OUI:9C28BF* ID_OUI_FROM_DATABASE=Continental Automotive Czech Republic s.r.o. OUI:206FEC* ID_OUI_FROM_DATABASE=Braemac CA LLC OUI:64A232* ID_OUI_FROM_DATABASE=OOO Samlight OUI:A082C7* ID_OUI_FROM_DATABASE=P.T.I Co.,LTD OUI:F41F0B* ID_OUI_FROM_DATABASE=YAMABISHI Corporation OUI:447C7F* ID_OUI_FROM_DATABASE=Innolight Technology Corporation OUI:FC75E6* ID_OUI_FROM_DATABASE=Handreamnet OUI:20B0F7* ID_OUI_FROM_DATABASE=Enclustra GmbH OUI:8C90D3* ID_OUI_FROM_DATABASE=Alcatel Lucent OUI:4013D9* ID_OUI_FROM_DATABASE=Global ES OUI:F4DC4D* ID_OUI_FROM_DATABASE=Beijing CCD Digital Technology Co., Ltd OUI:F8B599* ID_OUI_FROM_DATABASE=Guangzhou CHNAVS Digital Technology Co.,Ltd OUI:7C3920* ID_OUI_FROM_DATABASE=SSOMA SECURITY OUI:9C77AA* ID_OUI_FROM_DATABASE=NADASNV OUI:D8B6C1* ID_OUI_FROM_DATABASE=NetworkAccountant, Inc. OUI:58D08F* ID_OUI_FROM_DATABASE=IEEE 1904.1 Working Group OUI:3C99F7* ID_OUI_FROM_DATABASE=Lansentechnology AB OUI:94E711* ID_OUI_FROM_DATABASE=Xirka Dama Persada PT OUI:507D02* ID_OUI_FROM_DATABASE=BIODIT OUI:F44227* ID_OUI_FROM_DATABASE=S & S Research Inc. OUI:D4CBAF* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:CC09C8* ID_OUI_FROM_DATABASE=IMAQLIQ LTD OUI:C4B512* ID_OUI_FROM_DATABASE=General Electric Digital Energy OUI:E02538* ID_OUI_FROM_DATABASE=Titan Pet Products OUI:CC7A30* ID_OUI_FROM_DATABASE=CMAX Wireless Co., Ltd. OUI:D8760A* ID_OUI_FROM_DATABASE=Escort, Inc. OUI:101DC0* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:F49F54* ID_OUI_FROM_DATABASE=Samsung Electronics OUI:6063FD* ID_OUI_FROM_DATABASE=Transcend Communication Beijing Co.,Ltd. OUI:E08A7E* ID_OUI_FROM_DATABASE=Exponent OUI:80C6CA* ID_OUI_FROM_DATABASE=Endian s.r.l. OUI:F8DAE2* ID_OUI_FROM_DATABASE=Beta LaserMike OUI:E80462* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:70B08C* ID_OUI_FROM_DATABASE=Shenou Communication Equipment Co.,Ltd OUI:F0E5C3* ID_OUI_FROM_DATABASE=Drägerwerk AG & Co. KG aA OUI:446132* ID_OUI_FROM_DATABASE=ecobee inc OUI:A4B2A7* ID_OUI_FROM_DATABASE=Adaxys Solutions AG OUI:F455E0* ID_OUI_FROM_DATABASE=Niceway CNC Technology Co.,Ltd.Hunan Province OUI:AC4FFC* ID_OUI_FROM_DATABASE=SVS-VISTEK GmbH OUI:FC7CE7* ID_OUI_FROM_DATABASE=FCI USA LLC OUI:145412* ID_OUI_FROM_DATABASE=Entis Co., Ltd. OUI:807D1B* ID_OUI_FROM_DATABASE=Neosystem Co. Ltd. OUI:14FEAF* ID_OUI_FROM_DATABASE=SAGITTAR LIMITED OUI:7CB542* ID_OUI_FROM_DATABASE=ACES Technology OUI:40CD3A* ID_OUI_FROM_DATABASE=Z3 Technology OUI:045D56* ID_OUI_FROM_DATABASE=camtron industrial inc. OUI:AC83F0* ID_OUI_FROM_DATABASE=ImmediaTV Corporation OUI:6CE0B0* ID_OUI_FROM_DATABASE=SOUND4 OUI:00336C* ID_OUI_FROM_DATABASE=SynapSense Corporation OUI:E446BD* ID_OUI_FROM_DATABASE=C&C TECHNIC TAIWAN CO., LTD. OUI:7415E2* ID_OUI_FROM_DATABASE=Tri-Sen Systems Corporation OUI:F0BDF1* ID_OUI_FROM_DATABASE=Sipod Inc. OUI:288915* ID_OUI_FROM_DATABASE=CashGuard Sverige AB OUI:180675* ID_OUI_FROM_DATABASE=DILAX Intelcom GmbH OUI:40618E* ID_OUI_FROM_DATABASE=Stella-Green Co OUI:9C4E20* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:408493* ID_OUI_FROM_DATABASE=Clavister AB OUI:1C3A4F* ID_OUI_FROM_DATABASE=AccuSpec Electronics, LLC OUI:58E747* ID_OUI_FROM_DATABASE=Deltanet AG OUI:D87533* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:ECFE7E* ID_OUI_FROM_DATABASE=BlueRadios, Inc. OUI:7C6F06* ID_OUI_FROM_DATABASE=Caterpillar Trimble Control Technologies OUI:7C7673* ID_OUI_FROM_DATABASE=ENMAS GmbH OUI:6C6F18* ID_OUI_FROM_DATABASE=Stereotaxis, Inc. OUI:003532* ID_OUI_FROM_DATABASE=Electro-Metrics Corporation OUI:44376F* ID_OUI_FROM_DATABASE=Young Electric Sign Co OUI:8C640B* ID_OUI_FROM_DATABASE=Beyond Devices d.o.o. OUI:F04335* ID_OUI_FROM_DATABASE=DVN(Shanghai)Ltd. OUI:A479E4* ID_OUI_FROM_DATABASE=KLINFO Corp OUI:FCFAF7* ID_OUI_FROM_DATABASE=Shanghai Baud Data Communication Co.,Ltd. OUI:003CC5* ID_OUI_FROM_DATABASE=WONWOO Engineering Co., Ltd OUI:E85E53* ID_OUI_FROM_DATABASE=Infratec Datentechnik GmbH OUI:C848F5* ID_OUI_FROM_DATABASE=MEDISON Xray Co., Ltd OUI:1C17D3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:E8E5D6* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:ACBE75* ID_OUI_FROM_DATABASE=Ufine Technologies Co.,Ltd. OUI:D87157* ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. OUI:806629* ID_OUI_FROM_DATABASE=Prescope Technologies CO.,LTD. OUI:90F278* ID_OUI_FROM_DATABASE=Radius Gateway OUI:68CA00* ID_OUI_FROM_DATABASE=Octopus Systems Limited OUI:4C3089* ID_OUI_FROM_DATABASE=Thales Transportation Systems GmbH OUI:0C7D7C* ID_OUI_FROM_DATABASE=Kexiang Information Technology Co, Ltd. OUI:70D880* ID_OUI_FROM_DATABASE=Upos System sp. z o.o. OUI:0CC9C6* ID_OUI_FROM_DATABASE=Samwin Hong Kong Limited OUI:B45861* ID_OUI_FROM_DATABASE=CRemote, LLC OUI:AC6706* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:B8653B* ID_OUI_FROM_DATABASE=Bolymin, Inc. OUI:B0973A* ID_OUI_FROM_DATABASE=E-Fuel Corporation OUI:A05DC1* ID_OUI_FROM_DATABASE=TMCT Co., LTD. OUI:E0CA4D* ID_OUI_FROM_DATABASE=Shenzhen Unistar Communication Co.,LTD OUI:E497F0* ID_OUI_FROM_DATABASE=Shanghai VLC Technologies Ltd. Co. OUI:44A42D* ID_OUI_FROM_DATABASE=TCT Mobile Limited OUI:204E6B* ID_OUI_FROM_DATABASE=Axxana(israel) ltd OUI:50F003* ID_OUI_FROM_DATABASE=Open Stack, Inc. OUI:0C17F1* ID_OUI_FROM_DATABASE=TELECSYS OUI:5492BE* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:98BC99* ID_OUI_FROM_DATABASE=Edeltech Co.,Ltd. OUI:E8E1E2* ID_OUI_FROM_DATABASE=Energotest OUI:FC683E* ID_OUI_FROM_DATABASE=Directed Perception, Inc OUI:6C1811* ID_OUI_FROM_DATABASE=Decatur Electronics OUI:94592D* ID_OUI_FROM_DATABASE=EKE Building Technology Systems Ltd OUI:9CC077* ID_OUI_FROM_DATABASE=PrintCounts, LLC OUI:A85BB0* ID_OUI_FROM_DATABASE=Shenzhen Dehoo Technology Co.,Ltd OUI:089F97* ID_OUI_FROM_DATABASE=LEROY AUTOMATION OUI:4C5DCD* ID_OUI_FROM_DATABASE=Oy Finnish Electric Vehicle Technologies Ltd OUI:10090C* ID_OUI_FROM_DATABASE=Janome Sewing Machine Co., Ltd. OUI:ECB106* ID_OUI_FROM_DATABASE=Acuro Networks, Inc OUI:7C2E0D* ID_OUI_FROM_DATABASE=Blackmagic Design OUI:08F6F8* ID_OUI_FROM_DATABASE=GET Engineering OUI:6CDC6A* ID_OUI_FROM_DATABASE=Promethean Limited OUI:9055AE* ID_OUI_FROM_DATABASE=Ericsson, EAB/RWI/K OUI:2C3A28* ID_OUI_FROM_DATABASE=Fagor Electrónica OUI:90A7C1* ID_OUI_FROM_DATABASE=Pakedge Device and Software Inc. OUI:80F593* ID_OUI_FROM_DATABASE=IRCO Sistemas de Telecomunicación S.A. OUI:6CFDB9* ID_OUI_FROM_DATABASE=Proware Technologies Co Ltd. OUI:6CFFBE* ID_OUI_FROM_DATABASE=MPB Communications Inc. OUI:583CC6* ID_OUI_FROM_DATABASE=Omneality Ltd. OUI:0097FF* ID_OUI_FROM_DATABASE=Heimann Sensor GmbH OUI:34BA51* ID_OUI_FROM_DATABASE=Se-Kure Controls, Inc. OUI:44A8C2* ID_OUI_FROM_DATABASE=SEWOO TECH CO., LTD OUI:8CD628* ID_OUI_FROM_DATABASE=Ikor Metering OUI:481BD2* ID_OUI_FROM_DATABASE=Intron Scientific co., ltd. OUI:444E1A* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:009363* ID_OUI_FROM_DATABASE=Uni-Link Technology Co., Ltd. OUI:64DB18* ID_OUI_FROM_DATABASE=OpenPattern OUI:580556* ID_OUI_FROM_DATABASE=Elettronica GF S.r.L. OUI:88B627* ID_OUI_FROM_DATABASE=Gembird Europe BV OUI:D41F0C* ID_OUI_FROM_DATABASE=JAI Oy OUI:3C4C69* ID_OUI_FROM_DATABASE=Infinity System S.L. OUI:44E49A* ID_OUI_FROM_DATABASE=OMNITRONICS PTY LTD OUI:74F07D* ID_OUI_FROM_DATABASE=BnCOM Co.,Ltd OUI:1065A3* ID_OUI_FROM_DATABASE=Core Brands LLC OUI:20415A* ID_OUI_FROM_DATABASE=Smarteh d.o.o. OUI:703C39* ID_OUI_FROM_DATABASE=SEAWING Kft OUI:14A86B* ID_OUI_FROM_DATABASE=ShenZhen Telacom Science&Technology Co., Ltd OUI:0CC3A7* ID_OUI_FROM_DATABASE=Meritec OUI:4C322D* ID_OUI_FROM_DATABASE=TELEDATA NETWORKS OUI:B8B1C7* ID_OUI_FROM_DATABASE=BT&COM CO.,LTD OUI:A0BFA5* ID_OUI_FROM_DATABASE=CORESYS OUI:D411D6* ID_OUI_FROM_DATABASE=ShotSpotter, Inc. OUI:7CCB0D* ID_OUI_FROM_DATABASE=Antaira Technologies, LLC OUI:ECE9F8* ID_OUI_FROM_DATABASE=Guang Zhou TRI-SUN Electronics Technology Co., Ltd OUI:E89D87* ID_OUI_FROM_DATABASE=Toshiba OUI:9CAFCA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:784476* ID_OUI_FROM_DATABASE=Zioncom technology co.,ltd OUI:34CE94* ID_OUI_FROM_DATABASE=Parsec (Pty) Ltd OUI:ACE9AA* ID_OUI_FROM_DATABASE=Hay Systems Ltd OUI:082AD0* ID_OUI_FROM_DATABASE=SRD Innovations Inc. OUI:24828A* ID_OUI_FROM_DATABASE=Prowave Technologies Ltd. OUI:6C0F6A* ID_OUI_FROM_DATABASE=JDC Tech Co., Ltd. OUI:6CF049* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:D4C766* ID_OUI_FROM_DATABASE=Acentic GmbH OUI:48EB30* ID_OUI_FROM_DATABASE=ETERNA TECHNOLOGY, INC. OUI:207C8F* ID_OUI_FROM_DATABASE=Quanta Microsystems,Inc. OUI:F8472D* ID_OUI_FROM_DATABASE=X2gen Digital Corp. Ltd OUI:8C598B* ID_OUI_FROM_DATABASE=C Technologies AB OUI:64F970* ID_OUI_FROM_DATABASE=Kenade Electronics Technology Co.,LTD. OUI:A04025* ID_OUI_FROM_DATABASE=Actioncable, Inc. OUI:78998F* ID_OUI_FROM_DATABASE=MEDILINE ITALIA SRL OUI:40ECF8* ID_OUI_FROM_DATABASE=Siemens AG OUI:F04BF2* ID_OUI_FROM_DATABASE=JTECH Communications, Inc. OUI:A8CB95* ID_OUI_FROM_DATABASE=EAST BEST CO., LTD. OUI:C8D1D1* ID_OUI_FROM_DATABASE=AGAiT Technology Corporation OUI:3CF52C* ID_OUI_FROM_DATABASE=DSPECIALISTS GmbH OUI:040EC2* ID_OUI_FROM_DATABASE=ViewSonic Mobile China Limited OUI:5403F5* ID_OUI_FROM_DATABASE=EBN Technology Corp. OUI:7C2F80* ID_OUI_FROM_DATABASE=Gigaset Communications GmbH OUI:446C24* ID_OUI_FROM_DATABASE=Reallin Electronic Co.,Ltd OUI:A0593A* ID_OUI_FROM_DATABASE=V.D.S. Video Display Systems srl OUI:A8F94B* ID_OUI_FROM_DATABASE=Eltex Enterprise Ltd. OUI:906DC8* ID_OUI_FROM_DATABASE=DLG Automação Industrial Ltda OUI:48343D* ID_OUI_FROM_DATABASE=IEP GmbH OUI:C8C13C* ID_OUI_FROM_DATABASE=RuggedTek Hangzhou Co., Ltd OUI:609F9D* ID_OUI_FROM_DATABASE=CloudSwitch OUI:0CE936* ID_OUI_FROM_DATABASE=ELIMOS srl OUI:A4DE50* ID_OUI_FROM_DATABASE=Total Walther GmbH OUI:E8A4C1* ID_OUI_FROM_DATABASE=Deep Sea Electronics PLC OUI:701AED* ID_OUI_FROM_DATABASE=ADVAS CO., LTD. OUI:64C6AF* ID_OUI_FROM_DATABASE=AXERRA Networks Ltd OUI:D8D67E* ID_OUI_FROM_DATABASE=GSK CNC EQUIPMENT CO.,LTD OUI:A4E7E4* ID_OUI_FROM_DATABASE=Connex GmbH OUI:AC583B* ID_OUI_FROM_DATABASE=Human Assembler, Inc. OUI:A05DE7* ID_OUI_FROM_DATABASE=DIRECTV, Inc. OUI:10CA81* ID_OUI_FROM_DATABASE=PRECIA OUI:003A98* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:705AB6* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:003A9A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:ACBEB6* ID_OUI_FROM_DATABASE=Visualedge Technology Co., Ltd. OUI:40A6A4* ID_OUI_FROM_DATABASE=PassivSystems Ltd OUI:903D6B* ID_OUI_FROM_DATABASE=Zicon Technology Corp. OUI:7C3BD5* ID_OUI_FROM_DATABASE=Imago Group OUI:B894D2* ID_OUI_FROM_DATABASE=Retail Innovation HTT AB OUI:DCE71C* ID_OUI_FROM_DATABASE=AUG Elektronik GmbH OUI:88A5BD* ID_OUI_FROM_DATABASE=QPCOM INC. OUI:DC3350* ID_OUI_FROM_DATABASE=TechSAT GmbH OUI:00271E* ID_OUI_FROM_DATABASE=Xagyl Communications OUI:002722* ID_OUI_FROM_DATABASE=Ubiquiti Networks OUI:002716* ID_OUI_FROM_DATABASE=Adachi-Syokai Co., Ltd. OUI:002715* ID_OUI_FROM_DATABASE=Rebound Telecom. Co., Ltd OUI:00270A* ID_OUI_FROM_DATABASE=IEE S.A. OUI:002674* ID_OUI_FROM_DATABASE=Electronic Solutions, Inc. OUI:00266E* ID_OUI_FROM_DATABASE=Nissho-denki Co.,LTD. OUI:00265B* ID_OUI_FROM_DATABASE=Hitron Technologies. Inc OUI:002661* ID_OUI_FROM_DATABASE=Irumtek Co., Ltd. OUI:002657* ID_OUI_FROM_DATABASE=OOO NPP EKRA OUI:00264E* ID_OUI_FROM_DATABASE=Rail & Road Protec GmbH OUI:0025E6* ID_OUI_FROM_DATABASE=Belgian Monitoring Systems bvba OUI:0025E5* ID_OUI_FROM_DATABASE=LG Electronics Inc OUI:0025E1* ID_OUI_FROM_DATABASE=SHANGHAI SEEYOO ELECTRONIC & TECHNOLOGY CO., LTD OUI:0025DB* ID_OUI_FROM_DATABASE=ATI Electronics(Shenzhen) Co., LTD OUI:0025D5* ID_OUI_FROM_DATABASE=Robonica (Pty) Ltd OUI:0025C9* ID_OUI_FROM_DATABASE=SHENZHEN HUAPU DIGITAL CO., LTD OUI:0025CE* ID_OUI_FROM_DATABASE=InnerSpace OUI:0025C2* ID_OUI_FROM_DATABASE=RingBell Co.,Ltd. OUI:0026A0* ID_OUI_FROM_DATABASE=moblic OUI:00269A* ID_OUI_FROM_DATABASE=Carina System Co., Ltd. OUI:002694* ID_OUI_FROM_DATABASE=Senscient Ltd OUI:002693* ID_OUI_FROM_DATABASE=QVidium Technologies, Inc. OUI:00268D* ID_OUI_FROM_DATABASE=CellTel S.p.A. OUI:00268E* ID_OUI_FROM_DATABASE=Alta Solutions, Inc. OUI:002687* ID_OUI_FROM_DATABASE=corega K.K OUI:002681* ID_OUI_FROM_DATABASE=Interspiro AB OUI:00267B* ID_OUI_FROM_DATABASE=GSI Helmholtzzentrum für Schwerionenforschung GmbH OUI:0025BB* ID_OUI_FROM_DATABASE=INNERINT Co., Ltd. OUI:0025B6* ID_OUI_FROM_DATABASE=Telecom FM OUI:0025AF* ID_OUI_FROM_DATABASE=COMFILE Technology OUI:0025AA* ID_OUI_FROM_DATABASE=Beijing Soul Technology Co.,Ltd. OUI:0025A9* ID_OUI_FROM_DATABASE=Shanghai Embedway Information Technologies Co.,Ltd OUI:0025A3* ID_OUI_FROM_DATABASE=Trimax Wireless, Inc. OUI:00259C* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:002597* ID_OUI_FROM_DATABASE=Kalki Communication Technologies OUI:002590* ID_OUI_FROM_DATABASE=Super Micro Computer, Inc. OUI:002580* ID_OUI_FROM_DATABASE=Equipson S.A. OUI:00257C* ID_OUI_FROM_DATABASE=Huachentel Technology Development Co., Ltd OUI:002575* ID_OUI_FROM_DATABASE=FiberPlex Technologies, LLC OUI:002576* ID_OUI_FROM_DATABASE=NELI TECHNOLOGIES OUI:002570* ID_OUI_FROM_DATABASE=Eastern Communications Company Limited OUI:002563* ID_OUI_FROM_DATABASE=Luxtera Inc OUI:002704* ID_OUI_FROM_DATABASE=Accelerated Concepts, Inc OUI:0026FE* ID_OUI_FROM_DATABASE=MKD Technology Inc. OUI:0026F8* ID_OUI_FROM_DATABASE=Golden Highway Industry Development Co., Ltd. OUI:0026F1* ID_OUI_FROM_DATABASE=ProCurve Networking by HP OUI:0026EB* ID_OUI_FROM_DATABASE=Advanced Spectrum Technology Co., Ltd. OUI:0026E5* ID_OUI_FROM_DATABASE=AEG Power Solutions OUI:0026DF* ID_OUI_FROM_DATABASE=TaiDoc Technology Corp. OUI:0026D8* ID_OUI_FROM_DATABASE=Magic Point Inc. OUI:0026D2* ID_OUI_FROM_DATABASE=Pcube Systems, Inc. OUI:0026C5* ID_OUI_FROM_DATABASE=Guangdong Gosun Telecommunications Co.,Ltd OUI:0026C0* ID_OUI_FROM_DATABASE=EnergyHub OUI:0026BF* ID_OUI_FROM_DATABASE=ShenZhen Temobi Science&Tech Development Co.,Ltd OUI:0026B7* ID_OUI_FROM_DATABASE=Kingston Technology Company, Inc. OUI:0026A6* ID_OUI_FROM_DATABASE=TRIXELL OUI:00263C* ID_OUI_FROM_DATABASE=Bachmann Technology GmbH & Co. KG OUI:002637* ID_OUI_FROM_DATABASE=Samsung Electro-Mechanics OUI:002630* ID_OUI_FROM_DATABASE=ACOREL S.A.S OUI:002629* ID_OUI_FROM_DATABASE=Juphoon System Software Inc. OUI:00262A* ID_OUI_FROM_DATABASE=Proxense, LLC OUI:002624* ID_OUI_FROM_DATABASE=Thomson Inc. OUI:00261D* ID_OUI_FROM_DATABASE=COP SECURITY SYSTEM CORP. OUI:002611* ID_OUI_FROM_DATABASE=Licera AB OUI:002617* ID_OUI_FROM_DATABASE=OEM Worldwide OUI:00260A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0025FE* ID_OUI_FROM_DATABASE=Pilot Electronics Corporation OUI:002605* ID_OUI_FROM_DATABASE=CC Systems AB OUI:002604* ID_OUI_FROM_DATABASE=Audio Processing Technology Ltd OUI:0025F4* ID_OUI_FROM_DATABASE=KoCo Connector AG OUI:0025EB* ID_OUI_FROM_DATABASE=Reutech Radar Systems (PTY) Ltd OUI:00242A* ID_OUI_FROM_DATABASE=Hittite Microwave Corporation OUI:00241D* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:002424* ID_OUI_FROM_DATABASE=Axis Network Technology OUI:002417* ID_OUI_FROM_DATABASE=Thomson Telecom Belgium OUI:002418* ID_OUI_FROM_DATABASE=Nextwave Semiconductor OUI:002411* ID_OUI_FROM_DATABASE=PharmaSmart LLC OUI:00240B* ID_OUI_FROM_DATABASE=Virtual Computer Inc. OUI:00240A* ID_OUI_FROM_DATABASE=US Beverage Net OUI:0024B8* ID_OUI_FROM_DATABASE=free alliance sdn bhd OUI:0024BD* ID_OUI_FROM_DATABASE=Hainzl Industriesysteme GmbH OUI:0024B3* ID_OUI_FROM_DATABASE=Graf-Syteco GmbH & Co. KG OUI:0024AE* ID_OUI_FROM_DATABASE=Morpho OUI:0024A7* ID_OUI_FROM_DATABASE=Advanced Video Communications Inc. OUI:0024AC* ID_OUI_FROM_DATABASE=Hangzhou DPtech Technologies Co., Ltd. OUI:00255D* ID_OUI_FROM_DATABASE=Morningstar Corporation OUI:002551* ID_OUI_FROM_DATABASE=SE-Elektronic GmbH OUI:00254A* ID_OUI_FROM_DATABASE=RingCube Technologies, Inc. OUI:002543* ID_OUI_FROM_DATABASE=MONEYTECH OUI:002544* ID_OUI_FROM_DATABASE=LoJack Corporation OUI:002539* ID_OUI_FROM_DATABASE=IfTA GmbH OUI:00253B* ID_OUI_FROM_DATABASE=din Dietmar Nocker Facilitymanagement GmbH OUI:00250B* ID_OUI_FROM_DATABASE=CENTROFACTOR INC OUI:002504* ID_OUI_FROM_DATABASE=Valiant Communications Limited OUI:0024FF* ID_OUI_FROM_DATABASE=QLogic Corporation OUI:0024FD* ID_OUI_FROM_DATABASE=Accedian Networks Inc OUI:0024F8* ID_OUI_FROM_DATABASE=Technical Solutions Company Ltd. OUI:0024F1* ID_OUI_FROM_DATABASE=Shenzhen Fanhai Sanjiang Electronics Co., Ltd. OUI:0024EC* ID_OUI_FROM_DATABASE=United Information Technology Co.,Ltd. OUI:00249B* ID_OUI_FROM_DATABASE=Action Star Enterprise Co., Ltd. OUI:002499* ID_OUI_FROM_DATABASE=Aquila Technologies OUI:002488* ID_OUI_FROM_DATABASE=Centre For Development Of Telematics OUI:002494* ID_OUI_FROM_DATABASE=Shenzhen Baoxin Tech CO., Ltd. OUI:00247A* ID_OUI_FROM_DATABASE=FU YI CHENG Technology Co., Ltd. OUI:002475* ID_OUI_FROM_DATABASE=Compass System(Embedded Dept.) OUI:00246E* ID_OUI_FROM_DATABASE=Phihong USA Corp. OUI:002467* ID_OUI_FROM_DATABASE=AOC International (Europe) GmbH OUI:002469* ID_OUI_FROM_DATABASE=Smart Doorphones OUI:002462* ID_OUI_FROM_DATABASE=Rayzone Corporation OUI:002458* ID_OUI_FROM_DATABASE=PA Bastion CC OUI:00245D* ID_OUI_FROM_DATABASE=Terberg besturingstechniek B.V. OUI:002455* ID_OUI_FROM_DATABASE=MuLogic BV OUI:002450* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00244B* ID_OUI_FROM_DATABASE=PERCEPTRON INC OUI:00253A* ID_OUI_FROM_DATABASE=CEVA, Ltd. OUI:002531* ID_OUI_FROM_DATABASE=Cloud Engines, Inc. OUI:00252F* ID_OUI_FROM_DATABASE=Energy, Inc. OUI:00252A* ID_OUI_FROM_DATABASE=Chengdu GeeYa Technology Co.,LTD OUI:002521* ID_OUI_FROM_DATABASE=Logitek Electronic Systems, Inc. OUI:00251C* ID_OUI_FROM_DATABASE=EDT OUI:002517* ID_OUI_FROM_DATABASE=Venntis, LLC OUI:002510* ID_OUI_FROM_DATABASE=Pico-Tesla Magnetic Therapies OUI:0024E5* ID_OUI_FROM_DATABASE=Seer Technology, Inc OUI:0024E0* ID_OUI_FROM_DATABASE=DS Tech, LLC OUI:0024DE* ID_OUI_FROM_DATABASE=GLOBAL Technology Inc. OUI:0024D9* ID_OUI_FROM_DATABASE=BICOM, Inc. OUI:0024CB* ID_OUI_FROM_DATABASE=Autonet Mobile OUI:0024CD* ID_OUI_FROM_DATABASE=Willow Garage, Inc. OUI:0024C6* ID_OUI_FROM_DATABASE=Hager Electro SAS OUI:00243A* ID_OUI_FROM_DATABASE=Ludl Electronic Products OUI:002434* ID_OUI_FROM_DATABASE=Lectrosonics, Inc. OUI:00242E* ID_OUI_FROM_DATABASE=Datastrip Inc. OUI:002296* ID_OUI_FROM_DATABASE=LinoWave Corporation OUI:00228F* ID_OUI_FROM_DATABASE=CNRS OUI:002290* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00228A* ID_OUI_FROM_DATABASE=Teratronik elektronische systeme gmbh OUI:00227E* ID_OUI_FROM_DATABASE=Chengdu 30Kaitian Communication Industry Co.Ltd OUI:00227D* ID_OUI_FROM_DATABASE=YE DATA INC. OUI:002278* ID_OUI_FROM_DATABASE=Shenzhen Tongfang Multimedia Technology Co.,Ltd. OUI:002272* ID_OUI_FROM_DATABASE=American Micro-Fuel Device Corp. OUI:002271* ID_OUI_FROM_DATABASE=Jäger Computergesteuerte Meßtechnik GmbH. OUI:00226E* ID_OUI_FROM_DATABASE=Gowell Electronic Limited OUI:002358* ID_OUI_FROM_DATABASE=SYSTEL SA OUI:002357* ID_OUI_FROM_DATABASE=Pitronot Technologies and Engineering P.T.E. Ltd. OUI:002352* ID_OUI_FROM_DATABASE=DATASENSOR S.p.A. OUI:00234B* ID_OUI_FROM_DATABASE=Inyuan Technology Inc. OUI:002346* ID_OUI_FROM_DATABASE=Vestac OUI:00233F* ID_OUI_FROM_DATABASE=Purechoice Inc OUI:002338* ID_OUI_FROM_DATABASE=OJ-Electronics A/S OUI:002333* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00232F* ID_OUI_FROM_DATABASE=Advanced Card Systems Ltd. OUI:00232A* ID_OUI_FROM_DATABASE=eonas IT-Beratung und -Entwicklung GmbH OUI:0022C1* ID_OUI_FROM_DATABASE=Active Storage Inc. OUI:0022C2* ID_OUI_FROM_DATABASE=Proview Eletrônica do Brasil LTDA OUI:0022BC* ID_OUI_FROM_DATABASE=JDSU France SAS OUI:0022B5* ID_OUI_FROM_DATABASE=NOVITA OUI:0022A9* ID_OUI_FROM_DATABASE=LG Electronics Inc OUI:0022AF* ID_OUI_FROM_DATABASE=Safety Vision OUI:0022A2* ID_OUI_FROM_DATABASE=Xtramus Technologies OUI:00229D* ID_OUI_FROM_DATABASE=PYUNG-HWA IND.CO.,LTD OUI:002327* ID_OUI_FROM_DATABASE=Shouyo Electronics CO., LTD OUI:002323* ID_OUI_FROM_DATABASE=Zylin AS OUI:00231A* ID_OUI_FROM_DATABASE=ITF Co., Ltd. OUI:002318* ID_OUI_FROM_DATABASE=Toshiba OUI:002311* ID_OUI_FROM_DATABASE=Gloscom Co., Ltd. OUI:00230C* ID_OUI_FROM_DATABASE=CLOVER ELECTRONICS CO.,LTD. OUI:002305* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0022FF* ID_OUI_FROM_DATABASE=NIVIS LLC OUI:0022FE* ID_OUI_FROM_DATABASE=Advanced Illumination OUI:002300* ID_OUI_FROM_DATABASE=Cayee Computer Ltd. OUI:0022F6* ID_OUI_FROM_DATABASE=Syracuse Research Corporation OUI:0022F9* ID_OUI_FROM_DATABASE=Pollin Electronic GmbH OUI:0023AD* ID_OUI_FROM_DATABASE=Xmark Corporation OUI:0023A7* ID_OUI_FROM_DATABASE=Redpine Signals, Inc. OUI:0023A1* ID_OUI_FROM_DATABASE=Trend Electronics Ltd OUI:0023A6* ID_OUI_FROM_DATABASE=E-Mon OUI:00239A* ID_OUI_FROM_DATABASE=EasyData Hardware GmbH OUI:002394* ID_OUI_FROM_DATABASE=Samjeon OUI:002390* ID_OUI_FROM_DATABASE=Algolware Corporation OUI:002386* ID_OUI_FROM_DATABASE=Tour & Andersson AB OUI:002405* ID_OUI_FROM_DATABASE=Dilog Nordic AB OUI:0023F5* ID_OUI_FROM_DATABASE=WILO SE OUI:0023F8* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:0023FE* ID_OUI_FROM_DATABASE=Biodevices, SA OUI:0023F0* ID_OUI_FROM_DATABASE=Shanghai Jinghan Weighing Apparatus Co. Ltd. OUI:0023EB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0023E5* ID_OUI_FROM_DATABASE=IPaXiom Networks OUI:0023E6* ID_OUI_FROM_DATABASE=Pirkus, Inc. OUI:0023D9* ID_OUI_FROM_DATABASE=Banner Engineering OUI:0023D3* ID_OUI_FROM_DATABASE=AirLink WiFi Networking Corp. OUI:0023D8* ID_OUI_FROM_DATABASE=Ball-It Oy OUI:0023C6* ID_OUI_FROM_DATABASE=SMC Corporation OUI:0023C0* ID_OUI_FROM_DATABASE=Broadway Networks OUI:0023B9* ID_OUI_FROM_DATABASE=EADS Deutschland GmbH OUI:0023B3* ID_OUI_FROM_DATABASE=Lyyn AB OUI:0022F5* ID_OUI_FROM_DATABASE=Advanced Realtime Tracking GmbH OUI:0022EF* ID_OUI_FROM_DATABASE=iWDL Technologies OUI:0022E8* ID_OUI_FROM_DATABASE=Applition Co., Ltd. OUI:0022E3* ID_OUI_FROM_DATABASE=Amerigon OUI:0022D5* ID_OUI_FROM_DATABASE=Eaton Corp. Electrical Group Data Center Solutions - Pulizzi OUI:0022DC* ID_OUI_FROM_DATABASE=Vigil Health Solutions Inc. OUI:0022D6* ID_OUI_FROM_DATABASE=Cypak AB OUI:0022D0* ID_OUI_FROM_DATABASE=Polar Electro Oy OUI:0022CB* ID_OUI_FROM_DATABASE=IONODES Inc. OUI:0022C6* ID_OUI_FROM_DATABASE=Sutus Inc OUI:002380* ID_OUI_FROM_DATABASE=Nanoteq OUI:00237A* ID_OUI_FROM_DATABASE=RIM OUI:002377* ID_OUI_FROM_DATABASE=Isotek Electronics Ltd OUI:002371* ID_OUI_FROM_DATABASE=SOAM Systel OUI:002365* ID_OUI_FROM_DATABASE=ELKA-Elektronik GmbH OUI:00236A* ID_OUI_FROM_DATABASE=SmartRG Inc OUI:00235E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00225A* ID_OUI_FROM_DATABASE=Garde Security AB OUI:002254* ID_OUI_FROM_DATABASE=Bigelow Aerospace OUI:002251* ID_OUI_FROM_DATABASE=Lumasense Technologies OUI:00224B* ID_OUI_FROM_DATABASE=AIRTECH TECHNOLOGIES, INC. OUI:002245* ID_OUI_FROM_DATABASE=Leine & Linde AB OUI:002242* ID_OUI_FROM_DATABASE=Alacron Inc. OUI:00223B* ID_OUI_FROM_DATABASE=Communication Networks, LLC OUI:00214C* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRONICS CO., LTD. OUI:002146* ID_OUI_FROM_DATABASE=Sanmina-SCI OUI:00213D* ID_OUI_FROM_DATABASE=Cermetek Microelectronics, Inc. OUI:00213E* ID_OUI_FROM_DATABASE=TomTom OUI:002135* ID_OUI_FROM_DATABASE=ALCATEL-LUCENT OUI:00213A* ID_OUI_FROM_DATABASE=Winchester Systems Inc. OUI:002130* ID_OUI_FROM_DATABASE=Keico Hightech Inc. OUI:00217E* ID_OUI_FROM_DATABASE=Telit Communication s.p.a OUI:002178* ID_OUI_FROM_DATABASE=Matuschek Messtechnik GmbH OUI:002172* ID_OUI_FROM_DATABASE=Seoultek Valley OUI:002166* ID_OUI_FROM_DATABASE=NovAtel Inc. OUI:002165* ID_OUI_FROM_DATABASE=Presstek Inc. OUI:00215F* ID_OUI_FROM_DATABASE=IHSE GmbH OUI:002153* ID_OUI_FROM_DATABASE=SeaMicro Inc. OUI:002158* ID_OUI_FROM_DATABASE=Style Flying Technology Co. OUI:0021AC* ID_OUI_FROM_DATABASE=Infrared Integrated Systems Ltd OUI:0021A5* ID_OUI_FROM_DATABASE=ERLPhase Power Technologies Ltd. OUI:00219F* ID_OUI_FROM_DATABASE=SATEL OY OUI:00218A* ID_OUI_FROM_DATABASE=Electronic Design and Manufacturing Company OUI:00218B* ID_OUI_FROM_DATABASE=Wescon Technology, Inc. OUI:002185* ID_OUI_FROM_DATABASE=MICRO-STAR INT'L CO.,LTD. OUI:001FF9* ID_OUI_FROM_DATABASE=Advanced Knowledge Associates OUI:001FF2* ID_OUI_FROM_DATABASE=VIA Technologies, Inc. OUI:001FED* ID_OUI_FROM_DATABASE=Tecan Systems Inc. OUI:001FE6* ID_OUI_FROM_DATABASE=Alphion Corporation OUI:001FE0* ID_OUI_FROM_DATABASE=EdgeVelocity Corp OUI:001FDA* ID_OUI_FROM_DATABASE=Nortel Networks OUI:002209* ID_OUI_FROM_DATABASE=Omron Healthcare Co., Ltd OUI:002203* ID_OUI_FROM_DATABASE=Glensound Electronics Ltd OUI:002200* ID_OUI_FROM_DATABASE=IBM Corp OUI:0021F6* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:0021F0* ID_OUI_FROM_DATABASE=EW3 Technologies LLC OUI:0021EA* ID_OUI_FROM_DATABASE=Bystronic Laser AG OUI:0021E3* ID_OUI_FROM_DATABASE=SerialTek LLC OUI:0021DE* ID_OUI_FROM_DATABASE=Firepro Wireless OUI:0021DD* ID_OUI_FROM_DATABASE=Northstar Systems Corp OUI:0021D7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:002235* ID_OUI_FROM_DATABASE=Strukton Systems bv OUI:002234* ID_OUI_FROM_DATABASE=Corventis Inc. OUI:00222F* ID_OUI_FROM_DATABASE=Open Grid Computing, Inc. OUI:002228* ID_OUI_FROM_DATABASE=Breeze Innovations Ltd. OUI:002222* ID_OUI_FROM_DATABASE=Schaffner Deutschland GmbH OUI:00221C* ID_OUI_FROM_DATABASE=Private OUI:00220F* ID_OUI_FROM_DATABASE=MoCA (Multimedia over Coax Alliance) OUI:00212B* ID_OUI_FROM_DATABASE=MSA Auer OUI:00211D* ID_OUI_FROM_DATABASE=Dataline AB OUI:002124* ID_OUI_FROM_DATABASE=Optos Plc OUI:002118* ID_OUI_FROM_DATABASE=Athena Tech, Inc. OUI:002111* ID_OUI_FROM_DATABASE=Uniphone Inc. OUI:002107* ID_OUI_FROM_DATABASE=Seowonintech Co Ltd. OUI:002101* ID_OUI_FROM_DATABASE=Aplicaciones Electronicas Quasar (AEQ) OUI:002102* ID_OUI_FROM_DATABASE=UpdateLogic Inc. OUI:0021D1* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:0021D0* ID_OUI_FROM_DATABASE=Global Display Solutions Spa OUI:0021CB* ID_OUI_FROM_DATABASE=SMS TECNOLOGIA ELETRONICA LTDA OUI:0021C4* ID_OUI_FROM_DATABASE=Consilium AB OUI:0021B8* ID_OUI_FROM_DATABASE=Inphi Corporation OUI:0021B1* ID_OUI_FROM_DATABASE=DIGITAL SOLUTIONS LTD OUI:001F82* ID_OUI_FROM_DATABASE=Cal-Comp Electronics & Communications Co., Ltd OUI:001F7D* ID_OUI_FROM_DATABASE=embedded wireless GmbH OUI:001F7B* ID_OUI_FROM_DATABASE=TechNexion Ltd. OUI:001F7C* ID_OUI_FROM_DATABASE=Witelcom AS OUI:001F79* ID_OUI_FROM_DATABASE=Lodam Electronics A/S OUI:001F74* ID_OUI_FROM_DATABASE=Eigen Development OUI:001F6F* ID_OUI_FROM_DATABASE=Fujian Sunnada Communication Co.,Ltd. OUI:001F63* ID_OUI_FROM_DATABASE=JSC Goodwin-Europa OUI:001F6A* ID_OUI_FROM_DATABASE=PacketFlux Technologies, Inc. OUI:001F69* ID_OUI_FROM_DATABASE=Pingood Technology Co., Ltd. OUI:001F57* ID_OUI_FROM_DATABASE=Phonik Innovation Co.,LTD OUI:001F21* ID_OUI_FROM_DATABASE=Inner Mongolia Yin An Science & Technology Development Co.,L OUI:001F22* ID_OUI_FROM_DATABASE=Source Photonics, Inc. OUI:001F1C* ID_OUI_FROM_DATABASE=KOBISHI ELECTRIC Co.,Ltd. OUI:001F15* ID_OUI_FROM_DATABASE=Bioscrypt Inc OUI:001F10* ID_OUI_FROM_DATABASE=TOLEDO DO BRASIL INDUSTRIA DE BALANCAS LTDA OUI:001F0C* ID_OUI_FROM_DATABASE=Intelligent Digital Services GmbH OUI:001F07* ID_OUI_FROM_DATABASE=AZTEQ Mobile OUI:001FAA* ID_OUI_FROM_DATABASE=Taseon, Inc. OUI:001FA5* ID_OUI_FROM_DATABASE=Blue-White Industries OUI:001FA4* ID_OUI_FROM_DATABASE=ShenZhen Gongjin Electronics Co.,Ltd OUI:001FA0* ID_OUI_FROM_DATABASE=A10 Networks OUI:001F9A* ID_OUI_FROM_DATABASE=Nortel Networks OUI:001F99* ID_OUI_FROM_DATABASE=SERONICS co.ltd OUI:001F9B* ID_OUI_FROM_DATABASE=POSBRO OUI:001F94* ID_OUI_FROM_DATABASE=Lascar Electronics Ltd OUI:001F8D* ID_OUI_FROM_DATABASE=Ingenieurbuero Stark GmbH und Ko. KG OUI:001F89* ID_OUI_FROM_DATABASE=Signalion GmbH OUI:001ED0* ID_OUI_FROM_DATABASE=Ingespace OUI:001ECB* ID_OUI_FROM_DATABASE=RPC Energoautomatika Ltd OUI:001EC4* ID_OUI_FROM_DATABASE=Celio Corp OUI:001EBE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001EBD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001EB8* ID_OUI_FROM_DATABASE=Fortis, Inc. OUI:001EB1* ID_OUI_FROM_DATABASE=Cryptsoft Pty Ltd OUI:001EA6* ID_OUI_FROM_DATABASE=Best IT World (India) Pvt. Ltd. OUI:001EAC* ID_OUI_FROM_DATABASE=Armadeus Systems OUI:001E9F* ID_OUI_FROM_DATABASE=Visioneering Systems, Inc. OUI:001EA0* ID_OUI_FROM_DATABASE=XLN-t OUI:001EF4* ID_OUI_FROM_DATABASE=L-3 Communications Display Systems OUI:001EF9* ID_OUI_FROM_DATABASE=Pascom Kommunikations systeme GmbH. OUI:001EFA* ID_OUI_FROM_DATABASE=PROTEI Ltd. OUI:001EE8* ID_OUI_FROM_DATABASE=Mytek OUI:001EED* ID_OUI_FROM_DATABASE=Adventiq Ltd. OUI:001EE7* ID_OUI_FROM_DATABASE=Epic Systems Inc OUI:001EE1* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:001ED7* ID_OUI_FROM_DATABASE=H-Stream Wireless, Inc. OUI:001E6B* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:001E72* ID_OUI_FROM_DATABASE=PCS OUI:001E66* ID_OUI_FROM_DATABASE=RESOL Elektronische Regelungen GmbH OUI:001E5F* ID_OUI_FROM_DATABASE=KwikByte, LLC OUI:001E53* ID_OUI_FROM_DATABASE=Further Tech Co., LTD OUI:001E9A* ID_OUI_FROM_DATABASE=HAMILTON Bonaduz AG OUI:001E93* ID_OUI_FROM_DATABASE=CiriTech Systems Inc OUI:001E8E* ID_OUI_FROM_DATABASE=Hunkeler AG OUI:001E88* ID_OUI_FROM_DATABASE=ANDOR SYSTEM SUPPORT CO., LTD. OUI:001E82* ID_OUI_FROM_DATABASE=SanDisk Corporation OUI:001E81* ID_OUI_FROM_DATABASE=CNB Technology Inc. OUI:001E7C* ID_OUI_FROM_DATABASE=Taiwick Limited OUI:001E77* ID_OUI_FROM_DATABASE=Air2App OUI:001F50* ID_OUI_FROM_DATABASE=Swissdis AG OUI:001F49* ID_OUI_FROM_DATABASE=Manhattan TV Ltd OUI:001F4A* ID_OUI_FROM_DATABASE=Albentia Systems S.A. OUI:001F44* ID_OUI_FROM_DATABASE=GE Transportation Systems OUI:001F2F* ID_OUI_FROM_DATABASE=Berker GmbH & Co. KG OUI:001F34* ID_OUI_FROM_DATABASE=Lung Hwa Electronics Co., Ltd. OUI:001F28* ID_OUI_FROM_DATABASE=HPN Supply Chain OUI:001FD5* ID_OUI_FROM_DATABASE=MICRORISC s.r.o. OUI:001FD6* ID_OUI_FROM_DATABASE=Shenzhen Allywll OUI:001FD0* ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. OUI:001FC9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001FBD* ID_OUI_FROM_DATABASE=Kyocera Wireless Corp. OUI:001FB1* ID_OUI_FROM_DATABASE=Cybertech Inc. OUI:001FB6* ID_OUI_FROM_DATABASE=Chi Lin Technology Co., Ltd. OUI:001D02* ID_OUI_FROM_DATABASE=Cybertech Telecom Development OUI:001CF6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001CEF* ID_OUI_FROM_DATABASE=Primax Electronics LTD OUI:001CEA* ID_OUI_FROM_DATABASE=Scientific-Atlanta, Inc OUI:001CE9* ID_OUI_FROM_DATABASE=Galaxy Technology Limited OUI:001CE5* ID_OUI_FROM_DATABASE=MBS Electronic Systems GmbH OUI:001CE0* ID_OUI_FROM_DATABASE=DASAN TPS OUI:001CD9* ID_OUI_FROM_DATABASE=GlobalTop Technology Inc. OUI:001CD2* ID_OUI_FROM_DATABASE=King Champion (Hong Kong) Limited OUI:001CCD* ID_OUI_FROM_DATABASE=Alektrona Corporation OUI:001CC6* ID_OUI_FROM_DATABASE=ProStor Systems OUI:001CBA* ID_OUI_FROM_DATABASE=VerScient, Inc. OUI:001CB0* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001CB5* ID_OUI_FROM_DATABASE=Neihua Network Technology Co.,LTD.(NHN) OUI:001CB6* ID_OUI_FROM_DATABASE=Duzon CNT Co., Ltd. OUI:001CA9* ID_OUI_FROM_DATABASE=Audiomatica Srl OUI:001D5F* ID_OUI_FROM_DATABASE=OverSpeed SARL OUI:001D53* ID_OUI_FROM_DATABASE=S&O Electronics (Malaysia) Sdn. Bhd. OUI:001D4E* ID_OUI_FROM_DATABASE=TCM Mobile LLC OUI:001D4D* ID_OUI_FROM_DATABASE=Adaptive Recognition Hungary, Inc OUI:001D49* ID_OUI_FROM_DATABASE=Innovation Wireless Inc. OUI:001D44* ID_OUI_FROM_DATABASE=KROHNE Messtechnik GmbH OUI:001D3D* ID_OUI_FROM_DATABASE=Avidyne Corporation OUI:001D43* ID_OUI_FROM_DATABASE=Shenzhen G-link Digital Technology Co., Ltd. OUI:001E17* ID_OUI_FROM_DATABASE=STN BV OUI:001E1C* ID_OUI_FROM_DATABASE=SWS Australia Pty Limited OUI:001E12* ID_OUI_FROM_DATABASE=Ecolab OUI:001E0D* ID_OUI_FROM_DATABASE=Micran Ltd. OUI:001E06* ID_OUI_FROM_DATABASE=WIBRAIN OUI:001DFF* ID_OUI_FROM_DATABASE=Network Critical Solutions Ltd OUI:001E00* ID_OUI_FROM_DATABASE=Shantou Institute of Ultrasonic Instruments OUI:001DFA* ID_OUI_FROM_DATABASE=Fujian LANDI Commercial Equipment Co.,Ltd OUI:001DF3* ID_OUI_FROM_DATABASE=SBS Science & Technology Co., Ltd OUI:001DEE* ID_OUI_FROM_DATABASE=NEXTVISION SISTEMAS DIGITAIS DE TELEVISÃO LTDA. OUI:001DED* ID_OUI_FROM_DATABASE=Grid Net, Inc. OUI:001DDE* ID_OUI_FROM_DATABASE=Zhejiang Broadcast&Television Technology Co.,Ltd. OUI:001DE7* ID_OUI_FROM_DATABASE=Marine Sonic Technology, Ltd. OUI:001DD7* ID_OUI_FROM_DATABASE=Algolith OUI:001DD8* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:001DCB* ID_OUI_FROM_DATABASE=Exéns Development Oy OUI:001DC6* ID_OUI_FROM_DATABASE=SNR Inc. OUI:001DC5* ID_OUI_FROM_DATABASE=Beijing Jiaxun Feihong Electricial Co., Ltd. OUI:001DBF* ID_OUI_FROM_DATABASE=Radiient Technologies, Inc. OUI:001DB8* ID_OUI_FROM_DATABASE=Intoto Inc. OUI:001D36* ID_OUI_FROM_DATABASE=ELECTRONICS CORPORATION OF INDIA LIMITED OUI:001D31* ID_OUI_FROM_DATABASE=HIGHPRO INTERNATIONAL R&D CO,.LTD. OUI:001D2A* ID_OUI_FROM_DATABASE=SHENZHEN BUL-TECH CO.,LTD. OUI:001D23* ID_OUI_FROM_DATABASE=SENSUS OUI:001D24* ID_OUI_FROM_DATABASE=Aclara Power-Line Systems Inc. OUI:001D1B* ID_OUI_FROM_DATABASE=Sangean Electronics Inc. OUI:001D1E* ID_OUI_FROM_DATABASE=KYUSHU TEN CO.,LTD OUI:001D15* ID_OUI_FROM_DATABASE=Shenzhen Dolphin Electronic Co., Ltd OUI:001D0E* ID_OUI_FROM_DATABASE=Agapha Technology co., Ltd. OUI:001DB3* ID_OUI_FROM_DATABASE=HPN Supply Chain OUI:001DAE* ID_OUI_FROM_DATABASE=CHANG TSENG TECHNOLOGY CO., LTD OUI:001DA9* ID_OUI_FROM_DATABASE=Castles Technology, Co., LTD OUI:001DA2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001D9C* ID_OUI_FROM_DATABASE=Rockwell Automation OUI:001D9B* ID_OUI_FROM_DATABASE=Hokuyo Automatic Co., Ltd. OUI:001D96* ID_OUI_FROM_DATABASE=WatchGuard Video OUI:001D8F* ID_OUI_FROM_DATABASE=PureWave Networks OUI:001D8A* ID_OUI_FROM_DATABASE=TechTrex Inc OUI:001D89* ID_OUI_FROM_DATABASE=VaultStor Corporation OUI:001D7F* ID_OUI_FROM_DATABASE=Tekron International Ltd OUI:001D83* ID_OUI_FROM_DATABASE=Emitech Corporation OUI:001D72* ID_OUI_FROM_DATABASE=Wistron Corporation OUI:001D79* ID_OUI_FROM_DATABASE=SIGNAMAX LLC OUI:001D66* ID_OUI_FROM_DATABASE=Hyundai Telecom OUI:001D6D* ID_OUI_FROM_DATABASE=Confidant International LLC OUI:001E42* ID_OUI_FROM_DATABASE=Teltonika OUI:001E3C* ID_OUI_FROM_DATABASE=Lyngbox Media AB OUI:001E2F* ID_OUI_FROM_DATABASE=DiMoto Pty Ltd OUI:001E36* ID_OUI_FROM_DATABASE=IPTE OUI:001E29* ID_OUI_FROM_DATABASE=Hypertherm Inc OUI:001E23* ID_OUI_FROM_DATABASE=Electronic Educational Devices, Inc OUI:001C0C* ID_OUI_FROM_DATABASE=TANITA Corporation OUI:001C06* ID_OUI_FROM_DATABASE=Siemens Numerical Control Ltd., Nanjing OUI:001BFF* ID_OUI_FROM_DATABASE=Millennia Media inc. OUI:001BFA* ID_OUI_FROM_DATABASE=G.i.N. mbH OUI:001BE3* ID_OUI_FROM_DATABASE=Health Hero Network, Inc. OUI:001BE5* ID_OUI_FROM_DATABASE=802automation Limited OUI:001BE4* ID_OUI_FROM_DATABASE=TOWNET SRL OUI:001BDE* ID_OUI_FROM_DATABASE=Renkus-Heinz, Inc. OUI:001BD2* ID_OUI_FROM_DATABASE=ULTRA-X ASIA PACIFIC Inc. OUI:001C6B* ID_OUI_FROM_DATABASE=COVAX Co. Ltd OUI:001C64* ID_OUI_FROM_DATABASE=Landis+Gyr OUI:001C5F* ID_OUI_FROM_DATABASE=Winland Electronics, Inc. OUI:001C53* ID_OUI_FROM_DATABASE=Synergy Lighting Controls OUI:001C58* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001C4E* ID_OUI_FROM_DATABASE=TASA International Limited OUI:001C47* ID_OUI_FROM_DATABASE=Hangzhou Hollysys Automation Co., Ltd OUI:001C49* ID_OUI_FROM_DATABASE=Zoltan Technology Inc. OUI:001C48* ID_OUI_FROM_DATABASE=WiDeFi, Inc. OUI:001C3B* ID_OUI_FROM_DATABASE=AmRoad Technology Inc. OUI:001C42* ID_OUI_FROM_DATABASE=Parallels, Inc. OUI:001B72* ID_OUI_FROM_DATABASE=Sicep s.p.a. OUI:001B6D* ID_OUI_FROM_DATABASE=Midtronics, Inc. OUI:001B6B* ID_OUI_FROM_DATABASE=Swyx Solutions AG OUI:001B6C* ID_OUI_FROM_DATABASE=LookX Digital Media BV OUI:001B66* ID_OUI_FROM_DATABASE=Sennheiser electronic GmbH & Co. KG OUI:001B5F* ID_OUI_FROM_DATABASE=Alien Technology OUI:001B5A* ID_OUI_FROM_DATABASE=Apollo Imaging Technologies, Inc. OUI:001B53* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001B47* ID_OUI_FROM_DATABASE=Futarque A/S OUI:001B4C* ID_OUI_FROM_DATABASE=Signtech OUI:001B4E* ID_OUI_FROM_DATABASE=Navman New Zealand OUI:001B40* ID_OUI_FROM_DATABASE=Network Automation mxc AB OUI:001C9E* ID_OUI_FROM_DATABASE=Dualtech IT AB OUI:001C97* ID_OUI_FROM_DATABASE=Enzytek Technology Inc., OUI:001C98* ID_OUI_FROM_DATABASE=LUCKY TECHNOLOGY (HK) COMPANY LIMITED OUI:001C92* ID_OUI_FROM_DATABASE=Tervela OUI:001C8B* ID_OUI_FROM_DATABASE=MJ Innovations Ltd. OUI:001C86* ID_OUI_FROM_DATABASE=Cranite Systems, Inc. OUI:001C85* ID_OUI_FROM_DATABASE=Eunicorn OUI:001C81* ID_OUI_FROM_DATABASE=NextGen Venturi LTD OUI:001C72* ID_OUI_FROM_DATABASE=Mayer & Cie GmbH & Co KG OUI:001C77* ID_OUI_FROM_DATABASE=Prodys OUI:001B34* ID_OUI_FROM_DATABASE=Focus System Inc. OUI:001B39* ID_OUI_FROM_DATABASE=Proxicast OUI:001B3B* ID_OUI_FROM_DATABASE=Yi-Qing CO., LTD OUI:001B28* ID_OUI_FROM_DATABASE=POLYGON, JSC OUI:001B2D* ID_OUI_FROM_DATABASE=Med-Eng Systems Inc. OUI:001B24* ID_OUI_FROM_DATABASE=Quanta Computer Inc. OUI:001B1F* ID_OUI_FROM_DATABASE=DELTA - Danish Electronics, Light & Acoustics OUI:001B18* ID_OUI_FROM_DATABASE=Tsuken Electric Ind. Co.,Ltd OUI:001B13* ID_OUI_FROM_DATABASE=Icron Technologies Corporation OUI:001B0C* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001BA7* ID_OUI_FROM_DATABASE=Lorica Solutions OUI:001BA2* ID_OUI_FROM_DATABASE=IDS Imaging Development Systems GmbH OUI:001B96* ID_OUI_FROM_DATABASE=General Sensing OUI:001B9B* ID_OUI_FROM_DATABASE=Hose-McCann Communications OUI:001B8F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001B85* ID_OUI_FROM_DATABASE=MAN Diesel SE OUI:001B7E* ID_OUI_FROM_DATABASE=Beckmann GmbH OUI:001B79* ID_OUI_FROM_DATABASE=FAIVELEY TRANSPORT OUI:001C36* ID_OUI_FROM_DATABASE=iNEWiT NV OUI:001C2F* ID_OUI_FROM_DATABASE=Pfister GmbH OUI:001C28* ID_OUI_FROM_DATABASE=Sphairon Technologies GmbH OUI:001C1E* ID_OUI_FROM_DATABASE=emtrion GmbH OUI:001C19* ID_OUI_FROM_DATABASE=secunet Security Networks AG OUI:001C0B* ID_OUI_FROM_DATABASE=SmartAnt Telecom OUI:001C0D* ID_OUI_FROM_DATABASE=G-Technology, Inc. OUI:001BCB* ID_OUI_FROM_DATABASE=PEMPEK SYSTEMS PTY LTD OUI:001BC4* ID_OUI_FROM_DATABASE=Ultratec, Inc. OUI:001BBA* ID_OUI_FROM_DATABASE=Nortel OUI:001BB5* ID_OUI_FROM_DATABASE=ZF Electronics GmbH OUI:001BAE* ID_OUI_FROM_DATABASE=Micro Control Systems, Inc OUI:001BA8* ID_OUI_FROM_DATABASE=UBI&MOBI,.Inc OUI:001B05* ID_OUI_FROM_DATABASE=YMC AG OUI:001B00* ID_OUI_FROM_DATABASE=Neopost Technologies OUI:001AF4* ID_OUI_FROM_DATABASE=Handreamnet OUI:001AF9* ID_OUI_FROM_DATABASE=AeroVIronment (AV Inc) OUI:001AEF* ID_OUI_FROM_DATABASE=Loopcomm Technology, Inc. OUI:001AE3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001AE8* ID_OUI_FROM_DATABASE=Unify GmbH and Co KG OUI:001AEA* ID_OUI_FROM_DATABASE=Radio Terminal Systems Pty Ltd OUI:001A26* ID_OUI_FROM_DATABASE=Deltanode Solutions AB OUI:001A2B* ID_OUI_FROM_DATABASE=Ayecom Technology Co., Ltd. OUI:001A1F* ID_OUI_FROM_DATABASE=Coastal Environmental Systems OUI:001A1A* ID_OUI_FROM_DATABASE=Gentex Corporation/Electro-Acoustic Products OUI:001A13* ID_OUI_FROM_DATABASE=Wanlida Group Co., LTD OUI:001A0E* ID_OUI_FROM_DATABASE=Cheng Uei Precision Industry Co.,Ltd OUI:001A0C* ID_OUI_FROM_DATABASE=Swe-Dish Satellite Systems AB OUI:001A07* ID_OUI_FROM_DATABASE=Arecont Vision OUI:001A00* ID_OUI_FROM_DATABASE=MATRIX INC. OUI:001AD0* ID_OUI_FROM_DATABASE=Albis Technologies AG OUI:001AD5* ID_OUI_FROM_DATABASE=KMC CHAIN INDUSTRIAL CO., LTD. OUI:001AD7* ID_OUI_FROM_DATABASE=Christie Digital Systems, Inc. OUI:001AC9* ID_OUI_FROM_DATABASE=SUZUKEN CO.,LTD OUI:001ABA* ID_OUI_FROM_DATABASE=Caton Overseas Limited OUI:001ABF* ID_OUI_FROM_DATABASE=TRUMPF Laser Marking Systems AG OUI:001A81* ID_OUI_FROM_DATABASE=Zelax OUI:001A88* ID_OUI_FROM_DATABASE=Venergy,Co,Ltd OUI:001A7A* ID_OUI_FROM_DATABASE=Lismore Instruments Limited OUI:001A70* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC OUI:001A72* ID_OUI_FROM_DATABASE=Mosart Semiconductor Corp. OUI:001A6B* ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. OUI:001A64* ID_OUI_FROM_DATABASE=IBM Corp OUI:001A56* ID_OUI_FROM_DATABASE=ViewTel Co,. Ltd. OUI:001A5B* ID_OUI_FROM_DATABASE=NetCare Service Co., Ltd. OUI:001A5F* ID_OUI_FROM_DATABASE=KitWorks.fi Ltd. OUI:0019B6* ID_OUI_FROM_DATABASE=Euro Emme s.r.l. OUI:0019A3* ID_OUI_FROM_DATABASE=asteel electronique atlantique OUI:0019A8* ID_OUI_FROM_DATABASE=WiQuest Communications OUI:0019AA* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0019AF* ID_OUI_FROM_DATABASE=Rigol Technologies, Inc. OUI:001992* ID_OUI_FROM_DATABASE=ADTRAN INC. OUI:001997* ID_OUI_FROM_DATABASE=Soft Device Sdn Bhd OUI:00199C* ID_OUI_FROM_DATABASE=CTRING OUI:001A43* ID_OUI_FROM_DATABASE=Logical Link Communications OUI:001A48* ID_OUI_FROM_DATABASE=Takacom Corporation OUI:001A4A* ID_OUI_FROM_DATABASE=Qumranet Inc. OUI:001A3C* ID_OUI_FROM_DATABASE=Technowave Ltd. OUI:001A30* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001A35* ID_OUI_FROM_DATABASE=BARTEC GmbH OUI:001A37* ID_OUI_FROM_DATABASE=Lear Corporation OUI:0019F2* ID_OUI_FROM_DATABASE=Teradyne K.K. OUI:0019F7* ID_OUI_FROM_DATABASE=Onset Computer Corporation OUI:0019DF* ID_OUI_FROM_DATABASE=Thomson Inc. OUI:0019E6* ID_OUI_FROM_DATABASE=TOYO MEDIC CO.,LTD. OUI:0019EB* ID_OUI_FROM_DATABASE=Pyronix Ltd OUI:0019CC* ID_OUI_FROM_DATABASE=RCG (HK) Ltd OUI:0019D3* ID_OUI_FROM_DATABASE=TRAK Microwave OUI:0019D8* ID_OUI_FROM_DATABASE=MAXFOR OUI:0019C2* ID_OUI_FROM_DATABASE=Equustek Solutions, Inc. OUI:00198B* ID_OUI_FROM_DATABASE=Novera Optics Korea, Inc. OUI:00198D* ID_OUI_FROM_DATABASE=Ocean Optics, Inc. OUI:00197F* ID_OUI_FROM_DATABASE=PLANTRONICS, INC. OUI:001986* ID_OUI_FROM_DATABASE=Cheng Hongjian OUI:001973* ID_OUI_FROM_DATABASE=Zeugma Systems OUI:00197A* ID_OUI_FROM_DATABASE=MAZeT GmbH OUI:001967* ID_OUI_FROM_DATABASE=TELDAT Sp.J. OUI:00196C* ID_OUI_FROM_DATABASE=ETROVISION TECHNOLOGY OUI:00196E* ID_OUI_FROM_DATABASE=Metacom (Pty) Ltd. OUI:001AAC* ID_OUI_FROM_DATABASE=Corelatus AB OUI:001AAE* ID_OUI_FROM_DATABASE=Savant Systems LLC OUI:001AB3* ID_OUI_FROM_DATABASE=VISIONITE INC. OUI:001AA7* ID_OUI_FROM_DATABASE=Torian Wireless OUI:001A9E* ID_OUI_FROM_DATABASE=ICON Digital International Limited OUI:001AA3* ID_OUI_FROM_DATABASE=DELORME OUI:001AA5* ID_OUI_FROM_DATABASE=BRN Phoenix OUI:001AA4* ID_OUI_FROM_DATABASE=Future University-Hakodate OUI:001A97* ID_OUI_FROM_DATABASE=fitivision technology Inc. OUI:001A8D* ID_OUI_FROM_DATABASE=AVECS Bergen GmbH OUI:001962* ID_OUI_FROM_DATABASE=Commerciant, LP OUI:00195D* ID_OUI_FROM_DATABASE=ShenZhen XinHuaTong Opto Electronics Co.,Ltd OUI:001951* ID_OUI_FROM_DATABASE=NETCONS, s.r.o. OUI:001956* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00194A* ID_OUI_FROM_DATABASE=TESTO AG OUI:001943* ID_OUI_FROM_DATABASE=Belden OUI:001873* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001875* ID_OUI_FROM_DATABASE=AnaCise Testnology Pte Ltd OUI:00187A* ID_OUI_FROM_DATABASE=Wiremold OUI:00186E* ID_OUI_FROM_DATABASE=3Com Ltd OUI:00185E* ID_OUI_FROM_DATABASE=Nexterm Inc. OUI:001860* ID_OUI_FROM_DATABASE=SIM Technology Group Shanghai Simcom Ltd., OUI:001865* ID_OUI_FROM_DATABASE=Siemens Healthcare Diagnostics Manufacturing Ltd OUI:001903* ID_OUI_FROM_DATABASE=Bigfoot Networks Inc OUI:0018F9* ID_OUI_FROM_DATABASE=VVOND, Inc. OUI:0018F2* ID_OUI_FROM_DATABASE=Beijing Tianyu Communication Equipment Co., Ltd OUI:0018EB* ID_OUI_FROM_DATABASE=Blue Zen Enterprises Private Limited OUI:0018ED* ID_OUI_FROM_DATABASE=Accutech Ultrasystems Co., Ltd. OUI:0018E6* ID_OUI_FROM_DATABASE=Computer Hardware Design SIA OUI:0018DA* ID_OUI_FROM_DATABASE=AMBER wireless GmbH OUI:0018DF* ID_OUI_FROM_DATABASE=The Morey Corporation OUI:001937* ID_OUI_FROM_DATABASE=CommerceGuard AB OUI:00192E* ID_OUI_FROM_DATABASE=Spectral Instruments, Inc. OUI:001932* ID_OUI_FROM_DATABASE=Gude Analog- und Digialsysteme GmbH OUI:001922* ID_OUI_FROM_DATABASE=CM Comandos Lineares OUI:001927* ID_OUI_FROM_DATABASE=ImCoSys Ltd OUI:001929* ID_OUI_FROM_DATABASE=2M2B Montadora de Maquinas Bahia Brasil LTDA OUI:00190F* ID_OUI_FROM_DATABASE=Advansus Corp. OUI:001916* ID_OUI_FROM_DATABASE=PayTec AG OUI:00191B* ID_OUI_FROM_DATABASE=Sputnik Engineering AG OUI:001908* ID_OUI_FROM_DATABASE=Duaxes Corporation OUI:00190A* ID_OUI_FROM_DATABASE=HASWARE INC. OUI:0017D6* ID_OUI_FROM_DATABASE=Bluechips Microhouse Co.,Ltd. OUI:0017DB* ID_OUI_FROM_DATABASE=CANKO TECHNOLOGIES INC. OUI:0017CC* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:0017D1* ID_OUI_FROM_DATABASE=Nortel OUI:0017C5* ID_OUI_FROM_DATABASE=SonicWALL OUI:0017B9* ID_OUI_FROM_DATABASE=Gambro Lundia AB OUI:0017BE* ID_OUI_FROM_DATABASE=Tratec Telecom B.V. OUI:0017C0* ID_OUI_FROM_DATABASE=PureTech Systems, Inc. OUI:001852* ID_OUI_FROM_DATABASE=StorLink Semiconductors, Inc. OUI:001859* ID_OUI_FROM_DATABASE=Strawberry Linux Co.,Ltd. OUI:00184B* ID_OUI_FROM_DATABASE=Las Vegas Gaming, Inc. OUI:001846* ID_OUI_FROM_DATABASE=Crypto S.A. OUI:00183A* ID_OUI_FROM_DATABASE=Westell Technologies OUI:001829* ID_OUI_FROM_DATABASE=Gatsometer OUI:001835* ID_OUI_FROM_DATABASE=Thoratec / ITC OUI:001824* ID_OUI_FROM_DATABASE=Kimaldi Electronics, S.L. OUI:001822* ID_OUI_FROM_DATABASE=CEC TELECOM CO.,LTD. OUI:0017B2* ID_OUI_FROM_DATABASE=SK Telesys OUI:0017AD* ID_OUI_FROM_DATABASE=AceNet Corporation OUI:0017A6* ID_OUI_FROM_DATABASE=YOSIN ELECTRONICS CO., LTD. OUI:0017A1* ID_OUI_FROM_DATABASE=3soft inc. OUI:00179C* ID_OUI_FROM_DATABASE=DEPRAG SCHULZ GMBH u. CO. OUI:001790* ID_OUI_FROM_DATABASE=HYUNDAI DIGITECH Co, Ltd. OUI:001795* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0018CE* ID_OUI_FROM_DATABASE=Dreamtech Co., Ltd OUI:0018D3* ID_OUI_FROM_DATABASE=TEAMCAST OUI:0018C2* ID_OUI_FROM_DATABASE=Firetide, Inc OUI:0018C4* ID_OUI_FROM_DATABASE=Raba Technologies LLC OUI:0018C9* ID_OUI_FROM_DATABASE=EOps Technology Limited OUI:0018BD* ID_OUI_FROM_DATABASE=SHENZHEN DVBWORLD TECHNOLOGY CO., LTD. OUI:0018B1* ID_OUI_FROM_DATABASE=IBM Corp OUI:0018B6* ID_OUI_FROM_DATABASE=S3C, Inc. OUI:0018AF* ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. OUI:0018A3* ID_OUI_FROM_DATABASE=ZIPPY TECHNOLOGY CORP. OUI:0018AA* ID_OUI_FROM_DATABASE=Protec Fire Detection plc OUI:001816* ID_OUI_FROM_DATABASE=Ubixon Co., Ltd. OUI:00181D* ID_OUI_FROM_DATABASE=ASIA ELECTRONICS CO.,LTD OUI:001811* ID_OUI_FROM_DATABASE=Neuros Technology International, LLC. OUI:00180A* ID_OUI_FROM_DATABASE=Meraki, Inc. OUI:001801* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:0017F5* ID_OUI_FROM_DATABASE=LIG NEOPTEK OUI:0017FA* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:0017FC* ID_OUI_FROM_DATABASE=Suprema Inc. OUI:00189E* ID_OUI_FROM_DATABASE=OMNIKEY GmbH. OUI:001894* ID_OUI_FROM_DATABASE=NPCore, Inc. OUI:001899* ID_OUI_FROM_DATABASE=ShenZhen jieshun Science&Technology Industry CO,LTD. OUI:001886* ID_OUI_FROM_DATABASE=EL-TECH, INC. OUI:001888* ID_OUI_FROM_DATABASE=GOTIVE a.s. OUI:001881* ID_OUI_FROM_DATABASE=Buyang Electronics Industrial Co., Ltd OUI:0016D4* ID_OUI_FROM_DATABASE=Compal Communications, Inc. OUI:0016D9* ID_OUI_FROM_DATABASE=NINGBO BIRD CO.,LTD. OUI:0016C8* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0016CD* ID_OUI_FROM_DATABASE=HIJI HIGH-TECH CO., LTD. OUI:0016C1* ID_OUI_FROM_DATABASE=Eleksen Ltd OUI:0016BA* ID_OUI_FROM_DATABASE=WEATHERNEWS INC. OUI:00164F* ID_OUI_FROM_DATABASE=World Ethnic Broadcastin Inc. OUI:00164D* ID_OUI_FROM_DATABASE=Alcatel North America IP Division OUI:001648* ID_OUI_FROM_DATABASE=SSD Company Limited OUI:001643* ID_OUI_FROM_DATABASE=Sunhillo Corporation OUI:00163E* ID_OUI_FROM_DATABASE=Xensource, Inc. OUI:001637* ID_OUI_FROM_DATABASE=CITEL SpA OUI:001632* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRONICS CO., LTD. OUI:00162B* ID_OUI_FROM_DATABASE=Togami Electric Mfg.co.,Ltd. OUI:001755* ID_OUI_FROM_DATABASE=GE Security OUI:001747* ID_OUI_FROM_DATABASE=Trimble OUI:001749* ID_OUI_FROM_DATABASE=HYUNDAE YONG-O-SA CO.,LTD OUI:00174E* ID_OUI_FROM_DATABASE=Parama-tech Co.,Ltd. OUI:001732* ID_OUI_FROM_DATABASE=Science-Technical Center RISSA OUI:001734* ID_OUI_FROM_DATABASE=ADC Telecommunications OUI:001739* ID_OUI_FROM_DATABASE=Bright Headphone Electronics Company OUI:00172D* ID_OUI_FROM_DATABASE=Axcen Photonics Corporation OUI:001624* ID_OUI_FROM_DATABASE=Teneros, Inc. OUI:001613* ID_OUI_FROM_DATABASE=LibreStream Technologies Inc. OUI:001618* ID_OUI_FROM_DATABASE=HIVION Co., Ltd. OUI:00161F* ID_OUI_FROM_DATABASE=SUNWAVETEC Co., Ltd. OUI:00160E* ID_OUI_FROM_DATABASE=Optica Technologies Inc. OUI:001607* ID_OUI_FROM_DATABASE=Curves International Inc. OUI:001609* ID_OUI_FROM_DATABASE=Unitech electronics co., ltd. OUI:001608* ID_OUI_FROM_DATABASE=Sequans Communications OUI:001602* ID_OUI_FROM_DATABASE=CEYON TECHNOLOGY CO.,LTD. OUI:0015FB* ID_OUI_FROM_DATABASE=setex schermuly textile computer gmbh OUI:0015F6* ID_OUI_FROM_DATABASE=SCIENCE AND ENGINEERING SERVICES, INC. OUI:001782* ID_OUI_FROM_DATABASE=LoBenn Inc. OUI:001789* ID_OUI_FROM_DATABASE=Zenitron Corporation OUI:00176D* ID_OUI_FROM_DATABASE=CORE CORPORATION OUI:001771* ID_OUI_FROM_DATABASE=APD Communications Ltd OUI:001776* ID_OUI_FROM_DATABASE=Meso Scale Diagnostics, LLC OUI:001761* ID_OUI_FROM_DATABASE=Private OUI:001768* ID_OUI_FROM_DATABASE=Zinwave Ltd OUI:00175C* ID_OUI_FROM_DATABASE=SHARP CORPORATION OUI:00175A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001709* ID_OUI_FROM_DATABASE=Exalt Communications OUI:001704* ID_OUI_FROM_DATABASE=Shinco Electronics Group Co.,Ltd OUI:0016FD* ID_OUI_FROM_DATABASE=Jaty Electronics OUI:0016F1* ID_OUI_FROM_DATABASE=OmniSense, LLC OUI:0016F6* ID_OUI_FROM_DATABASE=Video Products Group OUI:0016F8* ID_OUI_FROM_DATABASE=AVIQTECH TECHNOLOGY CO., LTD. OUI:0016E5* ID_OUI_FROM_DATABASE=FORDLEY DEVELOPMENT LIMITED OUI:0016DE* ID_OUI_FROM_DATABASE=FAST Inc OUI:00167E* ID_OUI_FROM_DATABASE=DIBOSS.CO.,LTD OUI:001680* ID_OUI_FROM_DATABASE=Bally Gaming + Systems OUI:001679* ID_OUI_FROM_DATABASE=eOn Communications OUI:00166E* ID_OUI_FROM_DATABASE=Arbitron Inc. OUI:001667* ID_OUI_FROM_DATABASE=A-TEC Subsystem INC. OUI:001660* ID_OUI_FROM_DATABASE=Nortel OUI:00165B* ID_OUI_FROM_DATABASE=Grip Audio OUI:001654* ID_OUI_FROM_DATABASE=Flex-P Industries Sdn. Bhd. OUI:001721* ID_OUI_FROM_DATABASE=FITRE S.p.A. OUI:001726* ID_OUI_FROM_DATABASE=m2c Electronic Technology Ltd. OUI:00171A* ID_OUI_FROM_DATABASE=Winegard Company OUI:00171F* ID_OUI_FROM_DATABASE=IMV Corporation OUI:001713* ID_OUI_FROM_DATABASE=Tiger NetCom OUI:00170E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0016A9* ID_OUI_FROM_DATABASE=2EI OUI:0016AE* ID_OUI_FROM_DATABASE=INVENTEL OUI:00169D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00169F* ID_OUI_FROM_DATABASE=Vimtron Electronics Co., Ltd. OUI:0016A4* ID_OUI_FROM_DATABASE=Ezurio Ltd OUI:001691* ID_OUI_FROM_DATABASE=Moser-Baer AG OUI:001698* ID_OUI_FROM_DATABASE=T&A Mobile Phones OUI:00168C* ID_OUI_FROM_DATABASE=DSL Partner AS OUI:001685* ID_OUI_FROM_DATABASE=Elisa Oyj OUI:0015EF* ID_OUI_FROM_DATABASE=NEC TOKIN Corporation OUI:0015E8* ID_OUI_FROM_DATABASE=Nortel OUI:0015E3* ID_OUI_FROM_DATABASE=Dream Technologies Corporation OUI:0015D9* ID_OUI_FROM_DATABASE=PKC Electronics Oy OUI:0015D2* ID_OUI_FROM_DATABASE=Xantech Corporation OUI:0015CC* ID_OUI_FROM_DATABASE=UQUEST, LTD. OUI:0015CB* ID_OUI_FROM_DATABASE=Surf Communication Solutions Ltd. OUI:0015CD* ID_OUI_FROM_DATABASE=Exartech International Corp. OUI:0015C6* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0015BB* ID_OUI_FROM_DATABASE=SMA Solar Technology AG OUI:0014D5* ID_OUI_FROM_DATABASE=Datang Telecom Technology CO. , LCD,Optical Communication Br OUI:0014DA* ID_OUI_FROM_DATABASE=Huntleigh Healthcare OUI:0014CE* ID_OUI_FROM_DATABASE=NF CORPORATION OUI:0014C8* ID_OUI_FROM_DATABASE=Contemporary Research Corp OUI:0014C7* ID_OUI_FROM_DATABASE=Nortel OUI:0014BB* ID_OUI_FROM_DATABASE=Open Interface North America OUI:0014B6* ID_OUI_FROM_DATABASE=Enswer Technology Inc. OUI:0014AC* ID_OUI_FROM_DATABASE=Bountiful WiFi OUI:0014B1* ID_OUI_FROM_DATABASE=Axell Wireless Limited OUI:001476* ID_OUI_FROM_DATABASE=MultiCom Industries Limited OUI:001471* ID_OUI_FROM_DATABASE=Eastern Asia Technology Limited OUI:00146A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001463* ID_OUI_FROM_DATABASE=IDCS N.V. OUI:001465* ID_OUI_FROM_DATABASE=Novo Nordisk A/S OUI:001464* ID_OUI_FROM_DATABASE=Cryptosoft OUI:00145E* ID_OUI_FROM_DATABASE=IBM Corp OUI:001457* ID_OUI_FROM_DATABASE=T-VIPS AS OUI:001452* ID_OUI_FROM_DATABASE=CALCULEX,INC. OUI:001592* ID_OUI_FROM_DATABASE=Facom UK Ltd (Melksham) OUI:00158B* ID_OUI_FROM_DATABASE=Park Air Systems Ltd OUI:001584* ID_OUI_FROM_DATABASE=Schenck Process GmbH OUI:00157F* ID_OUI_FROM_DATABASE=ChuanG International Holding CO.,LTD. OUI:00157A* ID_OUI_FROM_DATABASE=Telefin S.p.A. OUI:001575* ID_OUI_FROM_DATABASE=Nevis Networks Inc. OUI:00156E* ID_OUI_FROM_DATABASE=A. W. Communication Systems Ltd OUI:001567* ID_OUI_FROM_DATABASE=RADWIN Inc. OUI:001569* ID_OUI_FROM_DATABASE=PECO II, Inc. OUI:001568* ID_OUI_FROM_DATABASE=Dilithium Networks OUI:001562* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001503* ID_OUI_FROM_DATABASE=PROFIcomms s.r.o. OUI:001505* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:001504* ID_OUI_FROM_DATABASE=GAME PLUS CO., LTD. OUI:0014FE* ID_OUI_FROM_DATABASE=Artech Electronics OUI:0014F7* ID_OUI_FROM_DATABASE=CREVIS Co., LTD OUI:0014F2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0014EB* ID_OUI_FROM_DATABASE=AwarePoint Corporation OUI:0014E1* ID_OUI_FROM_DATABASE=Data Display AG OUI:00155B* ID_OUI_FROM_DATABASE=Sampo Corporation OUI:00154F* ID_OUI_FROM_DATABASE=one RF Technology OUI:001546* ID_OUI_FROM_DATABASE=ITG Worldwide Sdn Bhd OUI:001540* ID_OUI_FROM_DATABASE=Nortel OUI:00153F* ID_OUI_FROM_DATABASE=Alcatel Alenia Space Italia OUI:001541* ID_OUI_FROM_DATABASE=StrataLight Communications, Inc. OUI:00153A* ID_OUI_FROM_DATABASE=Shenzhen Syscan Technology Co.,Ltd. OUI:0015BF* ID_OUI_FROM_DATABASE=technicob OUI:0015B4* ID_OUI_FROM_DATABASE=Polymap Wireless LLC OUI:0015AA* ID_OUI_FROM_DATABASE=Rextechnik International Co., OUI:0015A5* ID_OUI_FROM_DATABASE=DCI Co., Ltd. OUI:00159E* ID_OUI_FROM_DATABASE=Mad Catz Interactive Inc OUI:001597* ID_OUI_FROM_DATABASE=AETA AUDIO SYSTEMS OUI:00149E* ID_OUI_FROM_DATABASE=UbONE Co., Ltd OUI:001499* ID_OUI_FROM_DATABASE=Helicomm Inc OUI:001492* ID_OUI_FROM_DATABASE=Liteon, Mobile Media Solution SBU OUI:00148B* ID_OUI_FROM_DATABASE=Globo Electronic GmbH & Co. KG OUI:00148D* ID_OUI_FROM_DATABASE=Cubic Defense Simulation Systems OUI:00148C* ID_OUI_FROM_DATABASE=Fortress Technologies OUI:001486* ID_OUI_FROM_DATABASE=Echo Digital Audio Corporation OUI:00147D* ID_OUI_FROM_DATABASE=Aeon Digital International OUI:001533* ID_OUI_FROM_DATABASE=NADAM.CO.,LTD OUI:00152E* ID_OUI_FROM_DATABASE=PacketHop, Inc. OUI:001527* ID_OUI_FROM_DATABASE=Balboa Instruments OUI:001520* ID_OUI_FROM_DATABASE=Radiocrafts AS OUI:00151B* ID_OUI_FROM_DATABASE=Isilon Systems Inc. OUI:001516* ID_OUI_FROM_DATABASE=URIEL SYSTEMS INC. OUI:001511* ID_OUI_FROM_DATABASE=Data Center Systems OUI:00150A* ID_OUI_FROM_DATABASE=Sonoa Systems, Inc OUI:00131F* ID_OUI_FROM_DATABASE=NxtPhase T&D, Corp. OUI:001318* ID_OUI_FROM_DATABASE=DGSTATION Co., Ltd. OUI:00130C* ID_OUI_FROM_DATABASE=HF System Corporation OUI:001313* ID_OUI_FROM_DATABASE=GuangZhou Post & Telecom Equipment ltd OUI:001354* ID_OUI_FROM_DATABASE=Zcomax Technologies, Inc. OUI:001358* ID_OUI_FROM_DATABASE=Realm Systems, Inc. OUI:00135D* ID_OUI_FROM_DATABASE=NTTPC Communications, Inc. OUI:00134F* ID_OUI_FROM_DATABASE=Tranzeo Wireless Technologies Inc. OUI:001348* ID_OUI_FROM_DATABASE=Artila Electronics Co., Ltd. OUI:001342* ID_OUI_FROM_DATABASE=Vision Research, Inc. OUI:00133C* ID_OUI_FROM_DATABASE=QUINTRON SYSTEMS INC. OUI:001341* ID_OUI_FROM_DATABASE=Shandong New Beiyang Information Technology Co.,Ltd OUI:001329* ID_OUI_FROM_DATABASE=VSST Co., LTD OUI:001330* ID_OUI_FROM_DATABASE=EURO PROTECTION SURVEILLANCE OUI:001335* ID_OUI_FROM_DATABASE=VS Industry Berhad OUI:00132F* ID_OUI_FROM_DATABASE=Interactek OUI:0012C4* ID_OUI_FROM_DATABASE=Viseon, Inc. OUI:0012D0* ID_OUI_FROM_DATABASE=Gossen-Metrawatt-GmbH OUI:0012CA* ID_OUI_FROM_DATABASE=Mechatronic Brick Aps OUI:0012BA* ID_OUI_FROM_DATABASE=FSI Systems, Inc. OUI:0012AE* ID_OUI_FROM_DATABASE=HLS HARD-LINE Solutions Inc. OUI:0012B3* ID_OUI_FROM_DATABASE=Advance Wireless Technology Corp. OUI:0012AD* ID_OUI_FROM_DATABASE=IDS GmbH OUI:00144D* ID_OUI_FROM_DATABASE=Intelligent Systems OUI:001441* ID_OUI_FROM_DATABASE=Innovation Sound Technology Co., LTD. OUI:001448* ID_OUI_FROM_DATABASE=Inventec Multimedia & Telecom Corporation OUI:00143A* ID_OUI_FROM_DATABASE=RAYTALK INTERNATIONAL SRL OUI:001435* ID_OUI_FROM_DATABASE=CityCom Corp. OUI:00142E* ID_OUI_FROM_DATABASE=77 Elektronika Kft. OUI:001429* ID_OUI_FROM_DATABASE=V Center Technologies Co., Ltd. OUI:001428* ID_OUI_FROM_DATABASE=Vocollect, Inc OUI:001427* ID_OUI_FROM_DATABASE=JazzMutant OUI:00141E* ID_OUI_FROM_DATABASE=P.A. Semi, Inc. OUI:0012F9* ID_OUI_FROM_DATABASE=URYU SEISAKU, LTD. OUI:001300* ID_OUI_FROM_DATABASE=IT-FACTORY, INC. OUI:001305* ID_OUI_FROM_DATABASE=Epicom, Inc. OUI:001306* ID_OUI_FROM_DATABASE=Always On Wireless OUI:0012F4* ID_OUI_FROM_DATABASE=Belco International Co.,Ltd. OUI:0012EF* ID_OUI_FROM_DATABASE=OneAccess SA OUI:0012EA* ID_OUI_FROM_DATABASE=Trane OUI:0012E9* ID_OUI_FROM_DATABASE=Abbey Systems Ltd OUI:0012DC* ID_OUI_FROM_DATABASE=SunCorp Industrial Limited OUI:0012E3* ID_OUI_FROM_DATABASE=Agat-RT, Ltd. OUI:0012D7* ID_OUI_FROM_DATABASE=Invento Networks, Inc. OUI:0013F0* ID_OUI_FROM_DATABASE=Wavefront Semiconductor OUI:0013EB* ID_OUI_FROM_DATABASE=Sysmaster Corporation OUI:0013E6* ID_OUI_FROM_DATABASE=Technolution OUI:0013DF* ID_OUI_FROM_DATABASE=Ryvor Corp. OUI:0013D9* ID_OUI_FROM_DATABASE=Matrix Product Development, Inc. OUI:0013DA* ID_OUI_FROM_DATABASE=Diskware Co., Ltd OUI:0013CD* ID_OUI_FROM_DATABASE=MTI co. LTD OUI:0013D3* ID_OUI_FROM_DATABASE=MICRO-STAR INTERNATIONAL CO., LTD. OUI:0013C1* ID_OUI_FROM_DATABASE=Asoka USA Corporation OUI:0013BC* ID_OUI_FROM_DATABASE=Artimi Ltd OUI:0013B7* ID_OUI_FROM_DATABASE=Scantech ID OUI:0013AB* ID_OUI_FROM_DATABASE=Telemotive AG OUI:0013B2* ID_OUI_FROM_DATABASE=Carallon Limited OUI:0013B1* ID_OUI_FROM_DATABASE=Intelligent Control Systems (Asia) Pte Ltd OUI:0013A4* ID_OUI_FROM_DATABASE=KeyEye Communications OUI:00139F* ID_OUI_FROM_DATABASE=Electronics Design Services, Co., Ltd. OUI:001398* ID_OUI_FROM_DATABASE=TrafficSim Co.,Ltd OUI:001392* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:00138C* ID_OUI_FROM_DATABASE=Kumyoung.Co.Ltd OUI:001391* ID_OUI_FROM_DATABASE=OUEN CO.,LTD. OUI:001377* ID_OUI_FROM_DATABASE=Samsung Electronics CO., LTD OUI:00137C* ID_OUI_FROM_DATABASE=Kaicom co., Ltd. OUI:001383* ID_OUI_FROM_DATABASE=Application Technologies and Engineering Research Laboratory OUI:001364* ID_OUI_FROM_DATABASE=Paradigm Technology Inc.. OUI:001369* ID_OUI_FROM_DATABASE=Honda Electron Co., LED. OUI:00136A* ID_OUI_FROM_DATABASE=Hach Lange Sarl OUI:001418* ID_OUI_FROM_DATABASE=C4Line OUI:00141D* ID_OUI_FROM_DATABASE=LTi DRIVES GmbH OUI:001411* ID_OUI_FROM_DATABASE=Deutschmann Automation GmbH & Co. KG OUI:004501* ID_OUI_FROM_DATABASE=Versus Technology, Inc. OUI:001403* ID_OUI_FROM_DATABASE=Renasis, LLC OUI:0013FC* ID_OUI_FROM_DATABASE=SiCortex, Inc OUI:0013F5* ID_OUI_FROM_DATABASE=Akimbi Systems OUI:0013F6* ID_OUI_FROM_DATABASE=Cintech OUI:001286* ID_OUI_FROM_DATABASE=ENDEVCO CORP OUI:00127F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001278* ID_OUI_FROM_DATABASE=International Bar Code OUI:00126C* ID_OUI_FROM_DATABASE=Visonic Ltd. OUI:001273* ID_OUI_FROM_DATABASE=Stoke Inc OUI:001266* ID_OUI_FROM_DATABASE=Swisscom Hospitality Services SA OUI:001265* ID_OUI_FROM_DATABASE=Enerdyne Technologies, Inc. OUI:00125B* ID_OUI_FROM_DATABASE=KAIMEI ELECTRONI OUI:0011D2* ID_OUI_FROM_DATABASE=Perception Digital Ltd OUI:0011D7* ID_OUI_FROM_DATABASE=eWerks Inc OUI:0011D1* ID_OUI_FROM_DATABASE=Soft Imaging System GmbH OUI:0011C2* ID_OUI_FROM_DATABASE=United Fiber Optic Communication OUI:0011CB* ID_OUI_FROM_DATABASE=Jacobsons AB OUI:0011BB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0011BC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0011AA* ID_OUI_FROM_DATABASE=Uniclass Technology, Co., LTD OUI:0011AF* ID_OUI_FROM_DATABASE=Medialink-i,Inc OUI:001200* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0011FB* ID_OUI_FROM_DATABASE=Heidelberg Engineering GmbH OUI:0011F6* ID_OUI_FROM_DATABASE=Asia Pacific Microsystems , Inc. OUI:0011F1* ID_OUI_FROM_DATABASE=QinetiQ Ltd OUI:0011EA* ID_OUI_FROM_DATABASE=IWICS Inc. OUI:0011E3* ID_OUI_FROM_DATABASE=Thomson, Inc. OUI:0011DE* ID_OUI_FROM_DATABASE=EURILOGIC OUI:0011E4* ID_OUI_FROM_DATABASE=Danelec Electronics A/S OUI:001230* ID_OUI_FROM_DATABASE=Picaso Infocommunication CO., LTD. OUI:001226* ID_OUI_FROM_DATABASE=Japan Direx Corporation OUI:001220* ID_OUI_FROM_DATABASE=Cadco Systems OUI:00121A* ID_OUI_FROM_DATABASE=Techno Soft Systemnics Inc. OUI:00121F* ID_OUI_FROM_DATABASE=Harding Instruments OUI:001213* ID_OUI_FROM_DATABASE=Metrohm AG OUI:00120D* ID_OUI_FROM_DATABASE=Advanced Telecommunication Technologies, Inc. OUI:001207* ID_OUI_FROM_DATABASE=Head Strong International Limited OUI:00120E* ID_OUI_FROM_DATABASE=AboCom OUI:00117A* ID_OUI_FROM_DATABASE=Singim International Corp. OUI:00116E* ID_OUI_FROM_DATABASE=PePLink Ltd. OUI:001173* ID_OUI_FROM_DATABASE=SMART Storage Systems OUI:001167* ID_OUI_FROM_DATABASE=Integrated System Solution Corp. OUI:00116D* ID_OUI_FROM_DATABASE=American Time and Signal OUI:001163* ID_OUI_FROM_DATABASE=SYSTEM SPA DEPT. ELECTRONICS OUI:001156* ID_OUI_FROM_DATABASE=Pharos Systems NZ OUI:00115D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0012A7* ID_OUI_FROM_DATABASE=ISR TECHNOLOGIES Inc OUI:0012A0* ID_OUI_FROM_DATABASE=NeoMeridian Sdn Bhd OUI:00129B* ID_OUI_FROM_DATABASE=E2S Electronic Engineering Solutions, S.L. OUI:001294* ID_OUI_FROM_DATABASE=SUMITOMO ELECTRIC DEVICE INNOVATIONS, INC OUI:00128B* ID_OUI_FROM_DATABASE=Sensory Networks Inc OUI:001285* ID_OUI_FROM_DATABASE=Gizmondo Europe Ltd OUI:0011A9* ID_OUI_FROM_DATABASE=MOIMSTONE Co., LTD OUI:0011A3* ID_OUI_FROM_DATABASE=LanReady Technologies Inc. OUI:001197* ID_OUI_FROM_DATABASE=Monitoring Technologies Limited OUI:00119C* ID_OUI_FROM_DATABASE=EP&T Energy OUI:00118D* ID_OUI_FROM_DATABASE=Hanchang System Corp. OUI:001192* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001186* ID_OUI_FROM_DATABASE=Prime Systems, Inc. OUI:00117F* ID_OUI_FROM_DATABASE=Neotune Information Technology Corporation,.LTD OUI:001260* ID_OUI_FROM_DATABASE=Stanton Magnetics,inc. OUI:001256* ID_OUI_FROM_DATABASE=LG INFORMATION & COMM. OUI:00124F* ID_OUI_FROM_DATABASE=Pentair Thermal Management OUI:00124A* ID_OUI_FROM_DATABASE=Dedicated Devices, Inc. OUI:001249* ID_OUI_FROM_DATABASE=Delta Elettronica S.p.A. OUI:001243* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00123C* ID_OUI_FROM_DATABASE=Second Rule LLC OUI:001148* ID_OUI_FROM_DATABASE=Prolon Control Systems OUI:00114D* ID_OUI_FROM_DATABASE=Atsumi Electric Co.,LTD. OUI:00114E* ID_OUI_FROM_DATABASE=690885 Ontario Inc. OUI:001141* ID_OUI_FROM_DATABASE=GoodMan Corporation OUI:00113B* ID_OUI_FROM_DATABASE=Micronet Communications Inc. OUI:001135* ID_OUI_FROM_DATABASE=Grandeye Ltd OUI:001126* ID_OUI_FROM_DATABASE=Venstar Inc. OUI:000EB9* ID_OUI_FROM_DATABASE=HASHIMOTO Electronics Industry Co.,Ltd. OUI:000EBA* ID_OUI_FROM_DATABASE=HANMI SEMICONDUCTOR CO., LTD. OUI:000EAC* ID_OUI_FROM_DATABASE=MINTRON ENTERPRISE CO., LTD. OUI:000EA0* ID_OUI_FROM_DATABASE=NetKlass Technology Inc. OUI:000EA7* ID_OUI_FROM_DATABASE=Endace Technology OUI:000E9A* ID_OUI_FROM_DATABASE=BOE TECHNOLOGY GROUP CO.,LTD OUI:000E99* ID_OUI_FROM_DATABASE=Spectrum Digital, Inc OUI:00112B* ID_OUI_FROM_DATABASE=NetModule AG OUI:001120* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:001125* ID_OUI_FROM_DATABASE=IBM Corp OUI:001119* ID_OUI_FROM_DATABASE=Solteras, Inc. OUI:001113* ID_OUI_FROM_DATABASE=Fraunhofer FOKUS OUI:001106* ID_OUI_FROM_DATABASE=Siemens NV (Belgium) OUI:00110D* ID_OUI_FROM_DATABASE=SANBlaze Technology, Inc. OUI:001101* ID_OUI_FROM_DATABASE=CET Technologies Pte Ltd OUI:000FB3* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:000FA6* ID_OUI_FROM_DATABASE=S2 Security Corporation OUI:000FAD* ID_OUI_FROM_DATABASE=FMN communications GmbH OUI:000F9B* ID_OUI_FROM_DATABASE=Ross Video Limited OUI:000F9E* ID_OUI_FROM_DATABASE=Murrelektronik GmbH OUI:000FA1* ID_OUI_FROM_DATABASE=Gigabit Systems Inc. OUI:000F95* ID_OUI_FROM_DATABASE=ELECOM Co.,LTD Laneed Division OUI:000F96* ID_OUI_FROM_DATABASE=Telco Systems, Inc. OUI:000F8F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000F88* ID_OUI_FROM_DATABASE=AMETEK, Inc. OUI:000F83* ID_OUI_FROM_DATABASE=Brainium Technologies Inc. OUI:000F51* ID_OUI_FROM_DATABASE=Azul Systems, Inc. OUI:000F44* ID_OUI_FROM_DATABASE=Tivella Inc. OUI:000F43* ID_OUI_FROM_DATABASE=Wasabi Systems Inc. OUI:000F4A* ID_OUI_FROM_DATABASE=Kyushu-kyohan co.,ltd OUI:000F3E* ID_OUI_FROM_DATABASE=CardioNet, Inc OUI:000F3A* ID_OUI_FROM_DATABASE=HISHARP OUI:000F30* ID_OUI_FROM_DATABASE=Raza Microelectronics Inc OUI:000F2F* ID_OUI_FROM_DATABASE=W-LINX TECHNOLOGY CO., LTD. OUI:000F36* ID_OUI_FROM_DATABASE=Accurate Techhnologies, Inc. OUI:000F2A* ID_OUI_FROM_DATABASE=Cableware Electronics OUI:000F76* ID_OUI_FROM_DATABASE=Digital Keystone, Inc. OUI:000F70* ID_OUI_FROM_DATABASE=Wintec Industries, inc. OUI:000F75* ID_OUI_FROM_DATABASE=First Silicon Solutions OUI:000F7C* ID_OUI_FROM_DATABASE=ACTi Corporation OUI:000F69* ID_OUI_FROM_DATABASE=SEW Eurodrive GmbH & Co. KG OUI:000F63* ID_OUI_FROM_DATABASE=Obzerv Technologies OUI:000F64* ID_OUI_FROM_DATABASE=D&R Electronica Weesp BV OUI:000F5D* ID_OUI_FROM_DATABASE=Genexis BV OUI:000F56* ID_OUI_FROM_DATABASE=Continuum Photonics Inc OUI:000EEB* ID_OUI_FROM_DATABASE=Sandmartin(zhong shan)Electronics Co.,Ltd OUI:000EEC* ID_OUI_FROM_DATABASE=Orban OUI:000EF1* ID_OUI_FROM_DATABASE=EZQUEST INC. OUI:000EDE* ID_OUI_FROM_DATABASE=REMEC, Inc. OUI:000EE5* ID_OUI_FROM_DATABASE=bitWallet, Inc. OUI:000ECC* ID_OUI_FROM_DATABASE=Tableau, LLC OUI:000ED9* ID_OUI_FROM_DATABASE=Aksys, Ltd. OUI:000ECB* ID_OUI_FROM_DATABASE=VineSys Technology OUI:000ED2* ID_OUI_FROM_DATABASE=Filtronic plc OUI:000EBF* ID_OUI_FROM_DATABASE=Remsdaq Limited OUI:000EC6* ID_OUI_FROM_DATABASE=ASIX ELECTRONICS CORP. OUI:000F23* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000F1D* ID_OUI_FROM_DATABASE=Cosmo Techs Co., Ltd. OUI:000F10* ID_OUI_FROM_DATABASE=RDM Corporation OUI:000F17* ID_OUI_FROM_DATABASE=Insta Elektro GmbH OUI:000F1E* ID_OUI_FROM_DATABASE=Chengdu KT Electric Co.of High & New Technology OUI:000F0B* ID_OUI_FROM_DATABASE=Kentima Technologies AB OUI:000F04* ID_OUI_FROM_DATABASE=cim-usa inc OUI:000EFE* ID_OUI_FROM_DATABASE=EndRun Technologies LLC OUI:000EF8* ID_OUI_FROM_DATABASE=SBC ASI OUI:000EFD* ID_OUI_FROM_DATABASE=FUJINON CORPORATION OUI:000FFB* ID_OUI_FROM_DATABASE=Nippon Denso Industry Co., Ltd. OUI:000FF8* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000FF2* ID_OUI_FROM_DATABASE=Loud Technologies Inc. OUI:000FF7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000FE5* ID_OUI_FROM_DATABASE=MERCURY SECURITY CORPORATION OUI:000FE6* ID_OUI_FROM_DATABASE=MBTech Systems, Inc. OUI:000FEB* ID_OUI_FROM_DATABASE=Cylon Controls OUI:000FDF* ID_OUI_FROM_DATABASE=SOLOMON Technology Corp. OUI:000FD8* ID_OUI_FROM_DATABASE=Force, Inc. OUI:000FD3* ID_OUI_FROM_DATABASE=Digium OUI:000FC6* ID_OUI_FROM_DATABASE=Eurocom Industries A/S OUI:000FC5* ID_OUI_FROM_DATABASE=KeyMed Ltd OUI:000FC0* ID_OUI_FROM_DATABASE=DELCOMp OUI:000FB4* ID_OUI_FROM_DATABASE=Timespace Technology OUI:000FB9* ID_OUI_FROM_DATABASE=Adaptive Instruments OUI:000D4D* ID_OUI_FROM_DATABASE=Ninelanes OUI:000D54* ID_OUI_FROM_DATABASE=3Com Ltd OUI:000D45* ID_OUI_FROM_DATABASE=Tottori SANYO Electric Co., Ltd. OUI:000D48* ID_OUI_FROM_DATABASE=AEWIN Technologies Co., Ltd. OUI:000D40* ID_OUI_FROM_DATABASE=Verint Loronix Video Solutions OUI:000D39* ID_OUI_FROM_DATABASE=Network Electronics OUI:000D33* ID_OUI_FROM_DATABASE=Prediwave Corp. OUI:000D34* ID_OUI_FROM_DATABASE=Shell International Exploration and Production, Inc. OUI:000D2D* ID_OUI_FROM_DATABASE=NCT Deutschland GmbH OUI:000D26* ID_OUI_FROM_DATABASE=Primagraphics Limited OUI:000D21* ID_OUI_FROM_DATABASE=WISCORE Inc. OUI:000D14* ID_OUI_FROM_DATABASE=Vtech Innovation LP dba Advanced American Telephones OUI:000D13* ID_OUI_FROM_DATABASE=Wilhelm Rutenbeck GmbH&Co.KG OUI:000D1A* ID_OUI_FROM_DATABASE=Mustek System Inc. OUI:000D0E* ID_OUI_FROM_DATABASE=Inqnet Systems, Inc. OUI:000D01* ID_OUI_FROM_DATABASE=P&E Microcomputer Systems, Inc. OUI:000D02* ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. OUI:000D07* ID_OUI_FROM_DATABASE=Calrec Audio Ltd OUI:000E8D* ID_OUI_FROM_DATABASE=Systems in Progress Holding GmbH OUI:000E94* ID_OUI_FROM_DATABASE=Maas International BV OUI:000E87* ID_OUI_FROM_DATABASE=adp Gauselmann GmbH OUI:000E81* ID_OUI_FROM_DATABASE=Devicescape Software, Inc. OUI:000E88* ID_OUI_FROM_DATABASE=VIDEOTRON CORP. OUI:000E75* ID_OUI_FROM_DATABASE=New York Air Brake Corp. OUI:000E7A* ID_OUI_FROM_DATABASE=GemWon Communications Co., Ltd. OUI:000E66* ID_OUI_FROM_DATABASE=Hitachi Industry & Control Solutions, Ltd. OUI:000DF6* ID_OUI_FROM_DATABASE=Technology Thesaurus Corp. OUI:000DFD* ID_OUI_FROM_DATABASE=Huges Hi-Tech Inc., OUI:000E02* ID_OUI_FROM_DATABASE=Advantech AMT Inc. OUI:000DF0* ID_OUI_FROM_DATABASE=QCOM TECHNOLOGY INC. OUI:000DEA* ID_OUI_FROM_DATABASE=Kingtel Telecommunication Corp. OUI:000DEF* ID_OUI_FROM_DATABASE=Soc. Coop. Bilanciai OUI:000DDD* ID_OUI_FROM_DATABASE=Profilo Telra Elektronik Sanayi ve Ticaret. A.Ş OUI:000DDE* ID_OUI_FROM_DATABASE=Joyteck Co., Ltd. OUI:000DE3* ID_OUI_FROM_DATABASE=AT Sweden AB OUI:000DD0* ID_OUI_FROM_DATABASE=TetraTec Instruments GmbH OUI:000DD7* ID_OUI_FROM_DATABASE=Bright OUI:000E61* ID_OUI_FROM_DATABASE=MICROTROL LIMITED OUI:000E5A* ID_OUI_FROM_DATABASE=TELEFIELD inc. OUI:000E54* ID_OUI_FROM_DATABASE=AlphaCell Wireless Ltd. OUI:000E4E* ID_OUI_FROM_DATABASE=Waveplus Technology Co., Ltd. OUI:000E53* ID_OUI_FROM_DATABASE=AV TECH CORPORATION OUI:000E47* ID_OUI_FROM_DATABASE=NCI System Co.,Ltd. OUI:000E41* ID_OUI_FROM_DATABASE=NIHON MECHATRONICS CO.,LTD. OUI:000E42* ID_OUI_FROM_DATABASE=Motic Incoporation Ltd. OUI:000E3C* ID_OUI_FROM_DATABASE=Transact Technologies Inc OUI:000E36* ID_OUI_FROM_DATABASE=HEINESYS, Inc. OUI:000DB1* ID_OUI_FROM_DATABASE=Japan Network Service Co., Ltd. OUI:000DA9* ID_OUI_FROM_DATABASE=T.E.A.M. S.L. OUI:000DAC* ID_OUI_FROM_DATABASE=Japan CBM Corporation OUI:000DA4* ID_OUI_FROM_DATABASE=DOSCH & AMAND SYSTEMS AG OUI:000D97* ID_OUI_FROM_DATABASE=ABB Inc./Tropos OUI:000D98* ID_OUI_FROM_DATABASE=S.W.A.C. Schmitt-Walter Automation Consult GmbH OUI:000D8A* ID_OUI_FROM_DATABASE=Winners Electronics Co., Ltd. OUI:000D91* ID_OUI_FROM_DATABASE=Eclipse (HQ Espana) S.L. OUI:000D7F* ID_OUI_FROM_DATABASE=MIDAS COMMUNICATION TECHNOLOGIES PTE LTD ( Foreign Branch) OUI:000D79* ID_OUI_FROM_DATABASE=Dynamic Solutions Co,.Ltd. OUI:000D73* ID_OUI_FROM_DATABASE=Technical Support, Inc. OUI:000D7A* ID_OUI_FROM_DATABASE=DiGATTO Asia Pacific Pte Ltd OUI:000D6C* ID_OUI_FROM_DATABASE=M-Audio OUI:000D5A* ID_OUI_FROM_DATABASE=Tiesse SpA OUI:000D60* ID_OUI_FROM_DATABASE=IBM Corp OUI:000D59* ID_OUI_FROM_DATABASE=Amity Systems, Inc. OUI:000DCB* ID_OUI_FROM_DATABASE=Petcomkorea Co., Ltd. OUI:000DC4* ID_OUI_FROM_DATABASE=Emcore Corporation OUI:000DBE* ID_OUI_FROM_DATABASE=Bel Fuse Europe Ltd.,UK OUI:000DB8* ID_OUI_FROM_DATABASE=SCHILLER AG OUI:000DBD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000E30* ID_OUI_FROM_DATABASE=AERAS Networks, Inc. OUI:000E29* ID_OUI_FROM_DATABASE=Shester Communications Inc OUI:000E23* ID_OUI_FROM_DATABASE=Incipient, Inc. OUI:000E24* ID_OUI_FROM_DATABASE=Huwell Technology Inc. OUI:000E16* ID_OUI_FROM_DATABASE=SouthWing S.L. OUI:000E1D* ID_OUI_FROM_DATABASE=ARION Technology Inc. OUI:000E09* ID_OUI_FROM_DATABASE=Shenzhen Coship Software Co.,LTD. OUI:000E11* ID_OUI_FROM_DATABASE=BDT Büro und Datentechnik GmbH & Co.KG OUI:000BC8* ID_OUI_FROM_DATABASE=AirFlow Networks OUI:000BCF* ID_OUI_FROM_DATABASE=AGFA NDT INC. OUI:000BC3* ID_OUI_FROM_DATABASE=Multiplex, Inc. OUI:000BBC* ID_OUI_FROM_DATABASE=En Garde Systems, Inc. OUI:000BC1* ID_OUI_FROM_DATABASE=Bay Microsystems, Inc. OUI:000BB0* ID_OUI_FROM_DATABASE=Sysnet Telematica srl OUI:000BB5* ID_OUI_FROM_DATABASE=nStor Technologies, Inc. OUI:000BA6* ID_OUI_FROM_DATABASE=Miyakawa Electric Works Ltd. OUI:000BAB* ID_OUI_FROM_DATABASE=Advantech Technology (CHINA) Co., Ltd. OUI:000B99* ID_OUI_FROM_DATABASE=SensAble Technologies, Inc. OUI:000B9A* ID_OUI_FROM_DATABASE=Shanghai Ulink Telecom Equipment Co. Ltd. OUI:000B9F* ID_OUI_FROM_DATABASE=Neue ELSA GmbH OUI:000B94* ID_OUI_FROM_DATABASE=Digital Monitoring Products, Inc. OUI:000C1D* ID_OUI_FROM_DATABASE=Mettler & Fuchs AG OUI:000C22* ID_OUI_FROM_DATABASE=Double D Electronics Ltd OUI:000C0F* ID_OUI_FROM_DATABASE=Techno-One Co., Ltd OUI:000C16* ID_OUI_FROM_DATABASE=Concorde Microsystems Inc. OUI:000C0A* ID_OUI_FROM_DATABASE=Guangdong Province Electronic Technology Research Institute OUI:000BFD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000BF7* ID_OUI_FROM_DATABASE=NIDEK CO.,LTD OUI:000BFC* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000BFE* ID_OUI_FROM_DATABASE=CASTEL Broadband Limited OUI:000C03* ID_OUI_FROM_DATABASE=HDMI Licensing, LLC OUI:000CA4* ID_OUI_FROM_DATABASE=Prompttec Product Management GmbH OUI:000CAB* ID_OUI_FROM_DATABASE=COMMEND International OUI:000C98* ID_OUI_FROM_DATABASE=LETEK Communications Inc. OUI:000C9D* ID_OUI_FROM_DATABASE=UbeeAirWalk, Inc. OUI:000C9F* ID_OUI_FROM_DATABASE=NKE Corporation OUI:000C8C* ID_OUI_FROM_DATABASE=KODICOM CO.,LTD. OUI:000C91* ID_OUI_FROM_DATABASE=Riverhead Networks Inc. OUI:000C80* ID_OUI_FROM_DATABASE=Opelcomm Inc. OUI:000C85* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000CD0* ID_OUI_FROM_DATABASE=Symetrix OUI:000CD5* ID_OUI_FROM_DATABASE=Passave Inc. OUI:000CDC* ID_OUI_FROM_DATABASE=BECS Technology, Inc OUI:000CC9* ID_OUI_FROM_DATABASE=ILWOO DATA & TECHNOLOGY CO.,LTD OUI:000CB0* ID_OUI_FROM_DATABASE=Star Semiconductor Corporation OUI:000CB6* ID_OUI_FROM_DATABASE=NANJING SEU MOBILE & INTERNET TECHNOLOGY CO.,LTD OUI:000CBD* ID_OUI_FROM_DATABASE=Interface Masters, Inc OUI:000CC2* ID_OUI_FROM_DATABASE=ControlNet (India) Private Limited OUI:000CAF* ID_OUI_FROM_DATABASE=TRI TERM CO.,LTD. OUI:000C71* ID_OUI_FROM_DATABASE=Wybron, Inc OUI:000C78* ID_OUI_FROM_DATABASE=In-Tech Electronics Limited OUI:000C7D* ID_OUI_FROM_DATABASE=TEIKOKU ELECTRIC MFG. CO., LTD OUI:000C65* ID_OUI_FROM_DATABASE=Sunin Telecom OUI:000C6A* ID_OUI_FROM_DATABASE=MBARI OUI:000C6C* ID_OUI_FROM_DATABASE=Elgato Systems LLC OUI:000B88* ID_OUI_FROM_DATABASE=Vidisco ltd. OUI:000B8D* ID_OUI_FROM_DATABASE=Avvio Networks OUI:000B7B* ID_OUI_FROM_DATABASE=Test-Um Inc. OUI:000B7A* ID_OUI_FROM_DATABASE=L-3 Linkabit OUI:000B7C* ID_OUI_FROM_DATABASE=Telex Communications OUI:000B81* ID_OUI_FROM_DATABASE=Kaparel Corporation OUI:000B6E* ID_OUI_FROM_DATABASE=Neff Instrument Corp. OUI:000B75* ID_OUI_FROM_DATABASE=Iosoft Ltd. OUI:000B69* ID_OUI_FROM_DATABASE=Franke Finland Oy OUI:0091D6* ID_OUI_FROM_DATABASE=Crystal Group, Inc. OUI:000B62* ID_OUI_FROM_DATABASE=ib-mohnen KG OUI:000B59* ID_OUI_FROM_DATABASE=ScriptPro, LLC OUI:000C52* ID_OUI_FROM_DATABASE=Roll Systems Inc. OUI:000C57* ID_OUI_FROM_DATABASE=MACKIE Engineering Services Belgium BVBA OUI:000C59* ID_OUI_FROM_DATABASE=Indyme Electronics, Inc. OUI:000C5E* ID_OUI_FROM_DATABASE=Calypso Medical OUI:000C4B* ID_OUI_FROM_DATABASE=Cheops Elektronik OUI:000C46* ID_OUI_FROM_DATABASE=Allied Telesyn Inc. OUI:000C3D* ID_OUI_FROM_DATABASE=Glsystech Co., Ltd. OUI:000C33* ID_OUI_FROM_DATABASE=Compucase Enterprise Co. Ltd. OUI:000C36* ID_OUI_FROM_DATABASE=SHARP TAKAYA ELECTRONICS INDUSTRY CO.,LTD. OUI:000C2C* ID_OUI_FROM_DATABASE=Enwiser Inc. OUI:000CFB* ID_OUI_FROM_DATABASE=Korea Network Systems OUI:000CEF* ID_OUI_FROM_DATABASE=Open Networks Engineering Ltd OUI:000CF4* ID_OUI_FROM_DATABASE=AKATSUKI ELECTRIC MFG.CO.,LTD. OUI:000CE8* ID_OUI_FROM_DATABASE=GuangZhou AnJuBao Co., Ltd OUI:000CE1* ID_OUI_FROM_DATABASE=The Open Group OUI:000CCF* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000BEB* ID_OUI_FROM_DATABASE=Systegra AG OUI:000BF0* ID_OUI_FROM_DATABASE=MoTEX Products Co., Ltd. OUI:000BDD* ID_OUI_FROM_DATABASE=TOHOKU RICOH Co., LTD. OUI:000BE4* ID_OUI_FROM_DATABASE=Hosiden Corporation OUI:000BD8* ID_OUI_FROM_DATABASE=Industrial Scientific Corp. OUI:000BD4* ID_OUI_FROM_DATABASE=Beijing Wise Technology & Science Development Co.Ltd OUI:000A1D* ID_OUI_FROM_DATABASE=Optical Communications Products Inc. OUI:000A1F* ID_OUI_FROM_DATABASE=ART WARE Telecommunication Co., Ltd. OUI:000A24* ID_OUI_FROM_DATABASE=Octave Communications OUI:000A18* ID_OUI_FROM_DATABASE=Vichel Inc. OUI:000A0C* ID_OUI_FROM_DATABASE=Scientific Research Corporation OUI:000A11* ID_OUI_FROM_DATABASE=ExPet Technologies, Inc OUI:0009F8* ID_OUI_FROM_DATABASE=UNIMO TECHNOLOGY CO., LTD. OUI:0009FB* ID_OUI_FROM_DATABASE=Philips Patient Monitoring OUI:000A02* ID_OUI_FROM_DATABASE=ANNSO CO., LTD. OUI:0009EB* ID_OUI_FROM_DATABASE=HuMANDATA LTD. OUI:0009EC* ID_OUI_FROM_DATABASE=Daktronics, Inc. OUI:0009F1* ID_OUI_FROM_DATABASE=Yamaki Electric Corporation OUI:0009E5* ID_OUI_FROM_DATABASE=Hottinger Baldwin Messtechnik GmbH OUI:0009D9* ID_OUI_FROM_DATABASE=Neoscale Systems, Inc OUI:0009DE* ID_OUI_FROM_DATABASE=Samjin Information & Communications Co., Ltd. OUI:0009CC* ID_OUI_FROM_DATABASE=Moog GmbH OUI:0009C6* ID_OUI_FROM_DATABASE=Visionics Corporation OUI:0009CB* ID_OUI_FROM_DATABASE=HBrain OUI:0009D2* ID_OUI_FROM_DATABASE=Mai Logic Inc. OUI:0009BE* ID_OUI_FROM_DATABASE=Mamiya-OP Co.,Ltd. OUI:0009C2* ID_OUI_FROM_DATABASE=Onity, Inc. OUI:000B51* ID_OUI_FROM_DATABASE=Micetek International Inc. OUI:000B54* ID_OUI_FROM_DATABASE=BiTMICRO Networks, Inc. OUI:000B45* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000B4C* ID_OUI_FROM_DATABASE=Clarion (M) Sdn Bhd OUI:000B40* ID_OUI_FROM_DATABASE=Oclaro OUI:000B32* ID_OUI_FROM_DATABASE=VORMETRIC, INC. OUI:000B39* ID_OUI_FROM_DATABASE=Keisoku Giken Co.,Ltd. OUI:000B3E* ID_OUI_FROM_DATABASE=BittWare, Inc OUI:000B26* ID_OUI_FROM_DATABASE=Wetek Corporation OUI:000B2B* ID_OUI_FROM_DATABASE=HOSTNET CORPORATION OUI:000B2D* ID_OUI_FROM_DATABASE=Danfoss Inc. OUI:000ABB* ID_OUI_FROM_DATABASE=Taiwan Secom Co,. Ltd OUI:000AC7* ID_OUI_FROM_DATABASE=Unication Group OUI:000AAF* ID_OUI_FROM_DATABASE=Pipal Systems OUI:000AB6* ID_OUI_FROM_DATABASE=COMPUNETIX, INC OUI:000AA3* ID_OUI_FROM_DATABASE=SHIMAFUJI ELECTRIC CO.,LTD. OUI:000AA8* ID_OUI_FROM_DATABASE=ePipe Pty. Ltd. OUI:000AAA* ID_OUI_FROM_DATABASE=AltiGen Communications Inc. OUI:000A90* ID_OUI_FROM_DATABASE=Bayside Interactive, Inc. OUI:000A9C* ID_OUI_FROM_DATABASE=Server Technology, Inc. OUI:000A96* ID_OUI_FROM_DATABASE=MEWTEL TECHNOLOGY INC. OUI:000A81* ID_OUI_FROM_DATABASE=TEIMA Audiotex S.L. OUI:000A83* ID_OUI_FROM_DATABASE=SALTO SYSTEMS S.L. OUI:000A88* ID_OUI_FROM_DATABASE=InCypher S.A. OUI:000A7C* ID_OUI_FROM_DATABASE=Tecton Ltd OUI:000A70* ID_OUI_FROM_DATABASE=MPLS Forum OUI:000A75* ID_OUI_FROM_DATABASE=Caterpillar, Inc OUI:000A62* ID_OUI_FROM_DATABASE=Crinis Networks, Inc. OUI:000A64* ID_OUI_FROM_DATABASE=Eracom Technologies OUI:000A69* ID_OUI_FROM_DATABASE=SUNNY bell Technology Co., Ltd. OUI:000A5D* ID_OUI_FROM_DATABASE=FingerTec Worldwide Sdn Bhd OUI:000AF4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000AED* ID_OUI_FROM_DATABASE=HARTING Systems GmbH & Co KG OUI:000AE8* ID_OUI_FROM_DATABASE=Cathay Roxus Information Technology Co. LTD OUI:000ADA* ID_OUI_FROM_DATABASE=Vindicator Technologies OUI:000ADC* ID_OUI_FROM_DATABASE=RuggedCom Inc. OUI:000AE1* ID_OUI_FROM_DATABASE=EG Technology OUI:000AC9* ID_OUI_FROM_DATABASE=Zambeel Inc OUI:000ACE* ID_OUI_FROM_DATABASE=RADIANTECH, INC. OUI:000AD5* ID_OUI_FROM_DATABASE=Brainchild Electronic Co., Ltd. OUI:000A4F* ID_OUI_FROM_DATABASE=Brain Boxes Limited OUI:000A51* ID_OUI_FROM_DATABASE=GyroSignal Technology Co., Ltd. OUI:000A56* ID_OUI_FROM_DATABASE=HITACHI Maxell Ltd. OUI:000A4A* ID_OUI_FROM_DATABASE=Targa Systems Ltd. OUI:000A37* ID_OUI_FROM_DATABASE=Procera Networks, Inc. OUI:000A3E* ID_OUI_FROM_DATABASE=EADS Telecom OUI:000A43* ID_OUI_FROM_DATABASE=Chunghwa Telecom Co., Ltd. OUI:000A30* ID_OUI_FROM_DATABASE=Visteon Corporation OUI:000A32* ID_OUI_FROM_DATABASE=Xsido Corporation OUI:000A2B* ID_OUI_FROM_DATABASE=Etherstuff OUI:000A29* ID_OUI_FROM_DATABASE=Pan Dacom Networking AG OUI:000B1A* ID_OUI_FROM_DATABASE=Industrial Defender, Inc. OUI:000B1F* ID_OUI_FROM_DATABASE=I CON Computer Co. OUI:000B13* ID_OUI_FROM_DATABASE=ZETRON INC OUI:000B0E* ID_OUI_FROM_DATABASE=Trapeze Networks OUI:000B0C* ID_OUI_FROM_DATABASE=Agile Systems Inc. OUI:000B07* ID_OUI_FROM_DATABASE=Voxpath Networks OUI:000AF9* ID_OUI_FROM_DATABASE=HiConnect, Inc. OUI:000AFB* ID_OUI_FROM_DATABASE=Ambri Limited OUI:000B00* ID_OUI_FROM_DATABASE=FUJIAN START COMPUTER EQUIPMENT CO.,LTD OUI:0009B8* ID_OUI_FROM_DATABASE=Entise Systems OUI:0009B7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0009B2* ID_OUI_FROM_DATABASE=L&F Inc. OUI:0009A5* ID_OUI_FROM_DATABASE=HANSUNG ELETRONIC INDUSTRIES DEVELOPMENT CO., LTD OUI:0009A6* ID_OUI_FROM_DATABASE=Ignis Optics, Inc. OUI:0009AB* ID_OUI_FROM_DATABASE=Netcontrol Oy OUI:00099F* ID_OUI_FROM_DATABASE=VIDEX INC. OUI:0007B3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0007AD* ID_OUI_FROM_DATABASE=Pentacon GmbH Foto-und Feinwerktechnik OUI:0007A5* ID_OUI_FROM_DATABASE=Y.D.K Co. Ltd. OUI:00079F* ID_OUI_FROM_DATABASE=Action Digital Inc. OUI:000792* ID_OUI_FROM_DATABASE=Sütron Electronic GmbH OUI:000799* ID_OUI_FROM_DATABASE=Tipping Point Technologies, Inc. OUI:00078C* ID_OUI_FROM_DATABASE=Elektronikspecialisten i Borlange AB OUI:000786* ID_OUI_FROM_DATABASE=Wireless Networks Inc. OUI:000775* ID_OUI_FROM_DATABASE=Valence Semiconductor, Inc. OUI:00077C* ID_OUI_FROM_DATABASE=Westermo Teleindustri AB OUI:000776* ID_OUI_FROM_DATABASE=Federal APD OUI:00077F* ID_OUI_FROM_DATABASE=J Communications Co., Ltd. OUI:000780* ID_OUI_FROM_DATABASE=Bluegiga Technologies OY OUI:000881* ID_OUI_FROM_DATABASE=DIGITAL HANDS CO.,LTD. OUI:02C08C* ID_OUI_FROM_DATABASE=3COM CORPORATION OUI:00087B* ID_OUI_FROM_DATABASE=RTX Telecom A/S OUI:000880* ID_OUI_FROM_DATABASE=BroadTel Canada Communications inc. OUI:00086E* ID_OUI_FROM_DATABASE=Hyglo AB OUI:000868* ID_OUI_FROM_DATABASE=PurOptix OUI:000861* ID_OUI_FROM_DATABASE=SoftEnergy Co., Ltd. OUI:00084F* ID_OUI_FROM_DATABASE=Qualstar Corporation OUI:00085B* ID_OUI_FROM_DATABASE=Hanbit Electronics Co., Ltd. OUI:000855* ID_OUI_FROM_DATABASE=NASA-Goddard Space Flight Center OUI:00084E* ID_OUI_FROM_DATABASE=DivergeNet, Inc. OUI:00085C* ID_OUI_FROM_DATABASE=Shanghai Dare Technologies Co. Ltd. OUI:0007ED* ID_OUI_FROM_DATABASE=Altera Corporation OUI:0007F4* ID_OUI_FROM_DATABASE=Eletex Co., Ltd. OUI:0007E1* ID_OUI_FROM_DATABASE=WIS Communications Co. Ltd. OUI:0007D4* ID_OUI_FROM_DATABASE=Zhejiang Yutong Network Communication Co Ltd. OUI:0007DB* ID_OUI_FROM_DATABASE=Kirana Networks, Inc. OUI:0007D5* ID_OUI_FROM_DATABASE=3e Technologies Int;., Inc. OUI:0005F9* ID_OUI_FROM_DATABASE=TOA Corporation OUI:0007C5* ID_OUI_FROM_DATABASE=Gcom, Inc. OUI:0007CC* ID_OUI_FROM_DATABASE=Kaba Benzing GmbH OUI:0007C6* ID_OUI_FROM_DATABASE=VDS Vosskuhler GmbH OUI:0007B9* ID_OUI_FROM_DATABASE=Ginganet Corporation OUI:0007BF* ID_OUI_FROM_DATABASE=Armillaire Technologies, Inc. OUI:00047F* ID_OUI_FROM_DATABASE=Chr. Mayr GmbH & Co. KG OUI:000961* ID_OUI_FROM_DATABASE=Switchgear and Instrumentation Ltd OUI:00095A* ID_OUI_FROM_DATABASE=RACEWOOD TECHNOLOGY OUI:000954* ID_OUI_FROM_DATABASE=AMiT spol. s. r. o. OUI:00094E* ID_OUI_FROM_DATABASE=BARTECH SYSTEMS INTERNATIONAL, INC OUI:000953* ID_OUI_FROM_DATABASE=Linkage System Integration Co.Ltd. OUI:000942* ID_OUI_FROM_DATABASE=Wireless Technologies, Inc OUI:000947* ID_OUI_FROM_DATABASE=Aztek, Inc. OUI:00093B* ID_OUI_FROM_DATABASE=HYUNDAI NETWORKS INC. OUI:000934* ID_OUI_FROM_DATABASE=Dream-Multimedia-Tv GmbH OUI:0008BA* ID_OUI_FROM_DATABASE=Erskine Systems Ltd OUI:0008B4* ID_OUI_FROM_DATABASE=SYSPOL OUI:0008AE* ID_OUI_FROM_DATABASE=PacketFront Network Products AB OUI:0008A7* ID_OUI_FROM_DATABASE=iLogic Inc. OUI:0008A2* ID_OUI_FROM_DATABASE=ADI Engineering, Inc. OUI:0008A1* ID_OUI_FROM_DATABASE=CNet Technology Inc. OUI:00089B* ID_OUI_FROM_DATABASE=ICP Electronics Inc. OUI:00088D* ID_OUI_FROM_DATABASE=Sigma-Links Inc. OUI:000893* ID_OUI_FROM_DATABASE=LE INFORMATION COMMUNICATION INC. OUI:00088E* ID_OUI_FROM_DATABASE=Nihon Computer Co., Ltd. OUI:000897* ID_OUI_FROM_DATABASE=Quake Technologies OUI:000887* ID_OUI_FROM_DATABASE=Maschinenfabrik Reinhausen GmbH OUI:0008FD* ID_OUI_FROM_DATABASE=BlueKorea Co., Ltd. OUI:0008F5* ID_OUI_FROM_DATABASE=YESTECHNOLOGY Co.,Ltd. OUI:0008EF* ID_OUI_FROM_DATABASE=DIBAL,S.A. OUI:0008EA* ID_OUI_FROM_DATABASE=Motion Control Engineering, Inc OUI:0008DD* ID_OUI_FROM_DATABASE=Telena Communications, Inc. OUI:0008DE* ID_OUI_FROM_DATABASE=3UP Systems OUI:0008E3* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0008D7* ID_OUI_FROM_DATABASE=HOW CORPORATION OUI:0008CB* ID_OUI_FROM_DATABASE=Zeta Broadband Inc. OUI:0008D0* ID_OUI_FROM_DATABASE=Musashi Engineering Co., LTD. OUI:0008C1* ID_OUI_FROM_DATABASE=Avistar Communications Corporation OUI:0008C6* ID_OUI_FROM_DATABASE=Philips Consumer Communications OUI:000993* ID_OUI_FROM_DATABASE=Visteon Corporation OUI:000998* ID_OUI_FROM_DATABASE=Capinfo Company Limited OUI:000986* ID_OUI_FROM_DATABASE=Metalink LTD. OUI:000985* ID_OUI_FROM_DATABASE=Auto Telecom Company OUI:00098C* ID_OUI_FROM_DATABASE=Option Wireless Sweden OUI:000980* ID_OUI_FROM_DATABASE=Power Zenith Inc. OUI:000973* ID_OUI_FROM_DATABASE=Lenten Technology Co., Ltd. OUI:000974* ID_OUI_FROM_DATABASE=Innopia Technologies, Inc. OUI:000979* ID_OUI_FROM_DATABASE=Advanced Television Systems Committee, Inc. OUI:000966* ID_OUI_FROM_DATABASE=Thales Navigation OUI:00096D* ID_OUI_FROM_DATABASE=Powernet Technologies Corp. OUI:00081F* ID_OUI_FROM_DATABASE=Pou Yuen Tech Corp. Ltd. OUI:000826* ID_OUI_FROM_DATABASE=Colorado Med Tech OUI:000820* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000825* ID_OUI_FROM_DATABASE=Acme Packet OUI:00082C* ID_OUI_FROM_DATABASE=Homag AG OUI:000819* ID_OUI_FROM_DATABASE=Banksys OUI:000810* ID_OUI_FROM_DATABASE=Key Technology, Inc. OUI:000813* ID_OUI_FROM_DATABASE=Diskbank, Inc. OUI:00080A* ID_OUI_FROM_DATABASE=Espera-Werke GmbH OUI:000804* ID_OUI_FROM_DATABASE=ICA Inc. OUI:0007FA* ID_OUI_FROM_DATABASE=ITT Co., Ltd. OUI:0007E7* ID_OUI_FROM_DATABASE=FreeWave Technologies OUI:0007EE* ID_OUI_FROM_DATABASE=telco Informationssysteme GmbH OUI:000928* ID_OUI_FROM_DATABASE=Telecore OUI:00092F* ID_OUI_FROM_DATABASE=Akom Technology Corporation OUI:000922* ID_OUI_FROM_DATABASE=TST Biometrics GmbH OUI:000921* ID_OUI_FROM_DATABASE=Planmeca Oy OUI:00091C* ID_OUI_FROM_DATABASE=CacheVision, Inc OUI:000910* ID_OUI_FROM_DATABASE=Simple Access Inc. OUI:000915* ID_OUI_FROM_DATABASE=CAS Corp. OUI:00090F* ID_OUI_FROM_DATABASE=Fortinet Inc. OUI:000909* ID_OUI_FROM_DATABASE=Telenor Connect A/S OUI:000902* ID_OUI_FROM_DATABASE=Redline Communications Inc. OUI:00065E* ID_OUI_FROM_DATABASE=Photuris, Inc. OUI:000645* ID_OUI_FROM_DATABASE=Meisei Electric Co. Ltd. OUI:000644* ID_OUI_FROM_DATABASE=neix,Inc OUI:00064B* ID_OUI_FROM_DATABASE=Alexon Co., Ltd. OUI:00063B* ID_OUI_FROM_DATABASE=Arcturus Networks Inc. OUI:00063A* ID_OUI_FROM_DATABASE=Dura Micro, Inc. OUI:000634* ID_OUI_FROM_DATABASE=GTE Airfone Inc. OUI:00062A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000627* ID_OUI_FROM_DATABASE=Uniwide Technologies, Inc. OUI:00062E* ID_OUI_FROM_DATABASE=Aristos Logic Corp. OUI:000617* ID_OUI_FROM_DATABASE=Redswitch Inc. OUI:00061E* ID_OUI_FROM_DATABASE=Maxan Systems OUI:000618* ID_OUI_FROM_DATABASE=DigiPower Manufacturing Inc. OUI:000770* ID_OUI_FROM_DATABASE=Ubiquoss Inc OUI:00076B* ID_OUI_FROM_DATABASE=Stralfors AB OUI:00075F* ID_OUI_FROM_DATABASE=VCS Video Communication Systems AG OUI:000766* ID_OUI_FROM_DATABASE=Chou Chin Industrial Co., Ltd. OUI:000759* ID_OUI_FROM_DATABASE=Boris Manufacturing Corp. OUI:00074C* ID_OUI_FROM_DATABASE=Beicom Inc. OUI:000753* ID_OUI_FROM_DATABASE=Beijing Qxcomm Technology Co., Ltd. OUI:000743* ID_OUI_FROM_DATABASE=Chelsio Communications OUI:000744* ID_OUI_FROM_DATABASE=Unico, Inc. OUI:000747* ID_OUI_FROM_DATABASE=Mecalc OUI:000737* ID_OUI_FROM_DATABASE=Soriya Co. Ltd. OUI:00073E* ID_OUI_FROM_DATABASE=China Great-Wall Computer Shenzhen Co., Ltd. OUI:0006C4* ID_OUI_FROM_DATABASE=Piolink Inc. OUI:0006C0* ID_OUI_FROM_DATABASE=United Internetworks, Inc. OUI:0006BA* ID_OUI_FROM_DATABASE=Westwave Communications OUI:0006AD* ID_OUI_FROM_DATABASE=KB Electronics Ltd. OUI:0006B4* ID_OUI_FROM_DATABASE=Vorne Industries, Inc. OUI:0006AE* ID_OUI_FROM_DATABASE=Himachal Futuristic Communications Ltd OUI:0006B3* ID_OUI_FROM_DATABASE=Diagraph Corporation OUI:0006A3* ID_OUI_FROM_DATABASE=Bitran Corporation OUI:00069D* ID_OUI_FROM_DATABASE=Petards Ltd OUI:0006A7* ID_OUI_FROM_DATABASE=Primarion OUI:000657* ID_OUI_FROM_DATABASE=Market Central, Inc. OUI:000697* ID_OUI_FROM_DATABASE=R & D Center OUI:000691* ID_OUI_FROM_DATABASE=PT Inovacao OUI:0005C7* ID_OUI_FROM_DATABASE=I/F-COM A/S OUI:0005CE* ID_OUI_FROM_DATABASE=Prolink Microsystems Corporation OUI:0005C1* ID_OUI_FROM_DATABASE=A-Kyung Motion, Inc. OUI:0005BB* ID_OUI_FROM_DATABASE=Myspace AB OUI:00059B* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0005A7* ID_OUI_FROM_DATABASE=Hyperchip, Inc. OUI:0005B5* ID_OUI_FROM_DATABASE=Broadcom Technologies OUI:00059A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0005A1* ID_OUI_FROM_DATABASE=Zenocom OUI:0005AB* ID_OUI_FROM_DATABASE=Cyber Fone, Inc. OUI:000588* ID_OUI_FROM_DATABASE=Sensoria Corp. OUI:00058E* ID_OUI_FROM_DATABASE=Flextronics International GmbH & Co. Nfg. KG OUI:000612* ID_OUI_FROM_DATABASE=Accusys, Inc. OUI:000609* ID_OUI_FROM_DATABASE=Crossport Systems OUI:00060F* ID_OUI_FROM_DATABASE=Narad Networks Inc OUI:000602* ID_OUI_FROM_DATABASE=Cirkitech Electronics Co. OUI:0005ED* ID_OUI_FROM_DATABASE=Technikum Joanneum GmbH OUI:000600* ID_OUI_FROM_DATABASE=Toshiba Teli Corporation OUI:0005E7* ID_OUI_FROM_DATABASE=Netrake an AudioCodes Company OUI:0005F3* ID_OUI_FROM_DATABASE=Webyn OUI:0005FA* ID_OUI_FROM_DATABASE=IPOptical, Inc. OUI:0005DE* ID_OUI_FROM_DATABASE=Gi Fone Korea, Inc. OUI:0005DA* ID_OUI_FROM_DATABASE=Apex Automationstechnik OUI:0005C8* ID_OUI_FROM_DATABASE=VERYTECH OUI:0005D4* ID_OUI_FROM_DATABASE=FutureSmart Networks, Inc. OUI:0005CD* ID_OUI_FROM_DATABASE=Denon, Ltd. OUI:0006EC* ID_OUI_FROM_DATABASE=Harris Corporation OUI:0006DF* ID_OUI_FROM_DATABASE=AIDONIC Corporation OUI:0006E0* ID_OUI_FROM_DATABASE=MAT Co., Ltd. OUI:0006E5* ID_OUI_FROM_DATABASE=Fujian Newland Computer Ltd. Co. OUI:0006DB* ID_OUI_FROM_DATABASE=ICHIPS Co., Ltd. OUI:0006D0* ID_OUI_FROM_DATABASE=Elgar Electronics Corp. OUI:0006D7* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0006CA* ID_OUI_FROM_DATABASE=American Computer & Digital Components, Inc. (ACDC) OUI:000581* ID_OUI_FROM_DATABASE=Snell OUI:00057B* ID_OUI_FROM_DATABASE=Chung Nam Electronic Co., Ltd. OUI:000582* ID_OUI_FROM_DATABASE=ClearCube Technology OUI:000577* ID_OUI_FROM_DATABASE=SM Information & Communication OUI:000571* ID_OUI_FROM_DATABASE=Seiwa Electronics Co. OUI:00056B* ID_OUI_FROM_DATABASE=C.P. Technology Co., Ltd. OUI:000565* ID_OUI_FROM_DATABASE=Tailyn Communication Company Ltd. OUI:00055F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00055E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000558* ID_OUI_FROM_DATABASE=Synchronous, Inc. OUI:000552* ID_OUI_FROM_DATABASE=Xycotec Computer GmbH OUI:000549* ID_OUI_FROM_DATABASE=Salira Optical Network Systems OUI:00072B* ID_OUI_FROM_DATABASE=Jung Myung Telecom Co., Ltd. OUI:000731* ID_OUI_FROM_DATABASE=Ophir-Spiricon LLC OUI:00071A* ID_OUI_FROM_DATABASE=Finedigital Inc. OUI:000721* ID_OUI_FROM_DATABASE=Formac Elektronik GmbH OUI:00070E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000715* ID_OUI_FROM_DATABASE=General Research of Electronics, Inc. OUI:000708* ID_OUI_FROM_DATABASE=Bitrage Inc. OUI:0006F2* ID_OUI_FROM_DATABASE=Platys Communications OUI:0006FE* ID_OUI_FROM_DATABASE=Ambrado, Inc OUI:0006FC* ID_OUI_FROM_DATABASE=Fnet Co., Ltd. OUI:000684* ID_OUI_FROM_DATABASE=Biacore AB OUI:00068A* ID_OUI_FROM_DATABASE=NeuronNet Co. Ltd. R&D Center OUI:00067E* ID_OUI_FROM_DATABASE=WinCom Systems, Inc. OUI:000670* ID_OUI_FROM_DATABASE=Upponetti Oy OUI:000676* ID_OUI_FROM_DATABASE=Novra Technologies Inc. OUI:00067A* ID_OUI_FROM_DATABASE=JMP Systems OUI:000664* ID_OUI_FROM_DATABASE=Fostex Corporation OUI:00066A* ID_OUI_FROM_DATABASE=InfiniCon Systems, Inc. OUI:000651* ID_OUI_FROM_DATABASE=Aspen Networks Inc. OUI:00065D* ID_OUI_FROM_DATABASE=Heidelberg Web Systems OUI:000415* ID_OUI_FROM_DATABASE=Rasteme Systems Co., Ltd. OUI:000408* ID_OUI_FROM_DATABASE=Sanko Electronics Co., Ltd. OUI:000409* ID_OUI_FROM_DATABASE=Cratos Networks OUI:000402* ID_OUI_FROM_DATABASE=Nexsan Technologies, Ltd. OUI:0003F8* ID_OUI_FROM_DATABASE=SanCastle Technologies, Inc. OUI:0003FF* ID_OUI_FROM_DATABASE=Microsoft Corporation OUI:0003F1* ID_OUI_FROM_DATABASE=Cicada Semiconductor, Inc. OUI:0003F2* ID_OUI_FROM_DATABASE=Seneca Networks OUI:0003EC* ID_OUI_FROM_DATABASE=ICG Research, Inc. OUI:0003E6* ID_OUI_FROM_DATABASE=Entone, Inc. OUI:0003DE* ID_OUI_FROM_DATABASE=OTC Wireless OUI:0003E1* ID_OUI_FROM_DATABASE=Winmate Communication, Inc. OUI:0003DA* ID_OUI_FROM_DATABASE=Takamisawa Cybernetics Co., Ltd. OUI:00054C* ID_OUI_FROM_DATABASE=RF Innovations Pty Ltd OUI:000543* ID_OUI_FROM_DATABASE=IQ Wireless GmbH OUI:00053D* ID_OUI_FROM_DATABASE=Agere Systems OUI:000530* ID_OUI_FROM_DATABASE=Andiamo Systems, Inc. OUI:000537* ID_OUI_FROM_DATABASE=Nets Technology Co., Ltd. OUI:000536* ID_OUI_FROM_DATABASE=Danam Communications, Inc. OUI:000524* ID_OUI_FROM_DATABASE=BTL System (HK) Limited OUI:00052A* ID_OUI_FROM_DATABASE=Ikegami Tsushinki Co., Ltd. OUI:00051D* ID_OUI_FROM_DATABASE=Airocon, Inc. OUI:000517* ID_OUI_FROM_DATABASE=Shellcomm, Inc. OUI:000513* ID_OUI_FROM_DATABASE=VTLinx Multimedia Systems, Inc. OUI:0004D4* ID_OUI_FROM_DATABASE=Proview Electronics Co., Ltd. OUI:0004CE* ID_OUI_FROM_DATABASE=Patria Ailon OUI:0004CD* ID_OUI_FROM_DATABASE=Extenway Solutions Inc OUI:0004C7* ID_OUI_FROM_DATABASE=NetMount OUI:0004C8* ID_OUI_FROM_DATABASE=LIBA Maschinenfabrik GmbH OUI:0004C1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0004BB* ID_OUI_FROM_DATABASE=Bardac Corporation OUI:0004B5* ID_OUI_FROM_DATABASE=Equitrac Corporation OUI:0004A7* ID_OUI_FROM_DATABASE=FabiaTech Corporation OUI:0004A1* ID_OUI_FROM_DATABASE=Pathway Connectivity OUI:00049A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00035B* ID_OUI_FROM_DATABASE=BridgeWave Communications OUI:000356* ID_OUI_FROM_DATABASE=Wincor Nixdorf International GmbH OUI:00034B* ID_OUI_FROM_DATABASE=Nortel Networks OUI:000350* ID_OUI_FROM_DATABASE=BTICINO SPA OUI:000348* ID_OUI_FROM_DATABASE=Norscan Instruments, Ltd. OUI:000345* ID_OUI_FROM_DATABASE=Routrek Networks Corporation OUI:00033D* ID_OUI_FROM_DATABASE=ILSHin Lab OUI:0001EC* ID_OUI_FROM_DATABASE=Ericsson Group OUI:000331* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000338* ID_OUI_FROM_DATABASE=Oak Technology OUI:000335* ID_OUI_FROM_DATABASE=Mirae Technology OUI:00032C* ID_OUI_FROM_DATABASE=ABB Switzerland Ltd OUI:000325* ID_OUI_FROM_DATABASE=Arima Computer Corp. OUI:000453* ID_OUI_FROM_DATABASE=YottaYotta, Inc. OUI:00044D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000449* ID_OUI_FROM_DATABASE=Mapletree Networks OUI:000443* ID_OUI_FROM_DATABASE=Agilent Technologies, Inc. OUI:00043D* ID_OUI_FROM_DATABASE=INDEL AG OUI:000431* ID_OUI_FROM_DATABASE=GlobalStreams, Inc. OUI:000436* ID_OUI_FROM_DATABASE=ELANsat Technologies, Inc. OUI:000430* ID_OUI_FROM_DATABASE=Netgem OUI:00042A* ID_OUI_FROM_DATABASE=Wireless Networks, Inc. OUI:000424* ID_OUI_FROM_DATABASE=TMC s.r.l. OUI:00041B* ID_OUI_FROM_DATABASE=Bridgeworks Ltd. OUI:00041E* ID_OUI_FROM_DATABASE=Shikoku Instrumentation Co., Ltd. OUI:0003D3* ID_OUI_FROM_DATABASE=Internet Energy Systems, Inc. OUI:0003CE* ID_OUI_FROM_DATABASE=ETEN Technologies, Inc. OUI:0003CB* ID_OUI_FROM_DATABASE=Nippon Systems Development Co., Ltd. OUI:0003C2* ID_OUI_FROM_DATABASE=Solphone K.K. OUI:0003C7* ID_OUI_FROM_DATABASE=hopf Elektronik GmbH OUI:0003BB* ID_OUI_FROM_DATABASE=Signal Communications Limited OUI:0003B5* ID_OUI_FROM_DATABASE=Entra Technology Co. OUI:0003B0* ID_OUI_FROM_DATABASE=Xsense Technology Corp. OUI:0003A4* ID_OUI_FROM_DATABASE=Imation Corp. OUI:0003A9* ID_OUI_FROM_DATABASE=AXCENT Media AG OUI:0003AD* ID_OUI_FROM_DATABASE=Emerson Energy Systems AB OUI:000396* ID_OUI_FROM_DATABASE=EZ Cast Co., Ltd. OUI:00039D* ID_OUI_FROM_DATABASE=Qisda Corporation OUI:00050D* ID_OUI_FROM_DATABASE=Midstream Technologies, Inc. OUI:000507* ID_OUI_FROM_DATABASE=Fine Appliance Corp. OUI:0004FD* ID_OUI_FROM_DATABASE=Japan Control Engineering Co., Ltd. OUI:0004F7* ID_OUI_FROM_DATABASE=Omega Band, Inc. OUI:0004F1* ID_OUI_FROM_DATABASE=WhereNet OUI:0004DA* ID_OUI_FROM_DATABASE=Relax Technology, Inc. OUI:008087* ID_OUI_FROM_DATABASE=OKI ELECTRIC INDUSTRY CO., LTD OUI:0004E0* ID_OUI_FROM_DATABASE=Procket Networks OUI:000460* ID_OUI_FROM_DATABASE=Knilink Technology, Inc. OUI:000494* ID_OUI_FROM_DATABASE=Breezecom, Ltd. OUI:00048E* ID_OUI_FROM_DATABASE=Ohm Tech Labs, Inc. OUI:000495* ID_OUI_FROM_DATABASE=Tejas Networks India Limited OUI:000483* ID_OUI_FROM_DATABASE=Deltron Technology, Inc. OUI:000489* ID_OUI_FROM_DATABASE=YAFO Networks, Inc. OUI:000479* ID_OUI_FROM_DATABASE=Radius Co., Ltd. OUI:00046D* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000472* ID_OUI_FROM_DATABASE=Telelynx, Inc. OUI:00046C* ID_OUI_FROM_DATABASE=Cyber Technology Co., Ltd. OUI:000466* ID_OUI_FROM_DATABASE=ARMITEL Co. OUI:00045A* ID_OUI_FROM_DATABASE=The Linksys Group, Inc. OUI:00045F* ID_OUI_FROM_DATABASE=Avalue Technology, Inc. OUI:000391* ID_OUI_FROM_DATABASE=Advanced Digital Broadcast, Ltd. OUI:00038A* ID_OUI_FROM_DATABASE=America Online, Inc. OUI:00038E* ID_OUI_FROM_DATABASE=Atoga Systems, Inc. OUI:00037C* ID_OUI_FROM_DATABASE=Coax Media OUI:000381* ID_OUI_FROM_DATABASE=Ingenico International OUI:000375* ID_OUI_FROM_DATABASE=NetMedia, Inc. OUI:00036E* ID_OUI_FROM_DATABASE=Nicon Systems (Pty) Limited OUI:000362* ID_OUI_FROM_DATABASE=Vodtel Communications, Inc. OUI:00031C* ID_OUI_FROM_DATABASE=Svenska Hardvarufabriken AB OUI:000315* ID_OUI_FROM_DATABASE=Cidco Incorporated OUI:000310* ID_OUI_FROM_DATABASE=E-Globaledge Corporation OUI:00030D* ID_OUI_FROM_DATABASE=Uniwill Computer Corp. OUI:000309* ID_OUI_FROM_DATABASE=Texcel Technology PLC OUI:000304* ID_OUI_FROM_DATABASE=Pacific Broadband Communications OUI:00019F* ID_OUI_FROM_DATABASE=ReadyNet OUI:0002FD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:0002F6* ID_OUI_FROM_DATABASE=Equipe Communications OUI:0002F1* ID_OUI_FROM_DATABASE=Pinetron Co., Ltd. OUI:0002EF* ID_OUI_FROM_DATABASE=CCC Network Systems Group Ltd. OUI:0002EB* ID_OUI_FROM_DATABASE=Pico Communications OUI:0002E6* ID_OUI_FROM_DATABASE=Gould Instrument Systems, Inc. OUI:0002DF* ID_OUI_FROM_DATABASE=Net Com Systems, Inc. OUI:0002D3* ID_OUI_FROM_DATABASE=NetBotz, Inc. OUI:0002D8* ID_OUI_FROM_DATABASE=BRECIS Communications Corporation OUI:0002CC* ID_OUI_FROM_DATABASE=M.C.C.I OUI:0002D0* ID_OUI_FROM_DATABASE=Comdial Corporation OUI:0002C5* ID_OUI_FROM_DATABASE=Evertz Microsystems Ltd. OUI:0002C0* ID_OUI_FROM_DATABASE=Bencent Tzeng Industry Co., Ltd. OUI:0002BD* ID_OUI_FROM_DATABASE=Bionet Co., Ltd. OUI:0002B7* ID_OUI_FROM_DATABASE=Watanabe Electric Industry Co., Ltd. OUI:0002B0* ID_OUI_FROM_DATABASE=Hokubu Communication & Industrial Co., Ltd. OUI:0002A8* ID_OUI_FROM_DATABASE=Air Link Technology OUI:0002AB* ID_OUI_FROM_DATABASE=CTC Union Technologies Co., Ltd. OUI:0002A4* ID_OUI_FROM_DATABASE=AddPac Technology Co., Ltd. OUI:000299* ID_OUI_FROM_DATABASE=Apex, Inc. OUI:00029D* ID_OUI_FROM_DATABASE=Merix Corp. OUI:000291* ID_OUI_FROM_DATABASE=Open Network Co., Ltd. OUI:00028A* ID_OUI_FROM_DATABASE=Ambit Microsystems Corporation OUI:000287* ID_OUI_FROM_DATABASE=Adapcom OUI:00028C* ID_OUI_FROM_DATABASE=Micrel-Synergy Semiconductor OUI:000282* ID_OUI_FROM_DATABASE=ViaClix, Inc. OUI:00027B* ID_OUI_FROM_DATABASE=Amplify Net, Inc. OUI:00024F* ID_OUI_FROM_DATABASE=IPM Datacom S.R.L. OUI:000274* ID_OUI_FROM_DATABASE=Tommy Technologies Corp. OUI:000276* ID_OUI_FROM_DATABASE=Primax Electronics Ltd. OUI:00026F* ID_OUI_FROM_DATABASE=Senao International Co., Ltd. OUI:000264* ID_OUI_FROM_DATABASE=AudioRamp.com OUI:00306C* ID_OUI_FROM_DATABASE=Hitex Holding GmbH OUI:000177* ID_OUI_FROM_DATABASE=EDSL OUI:000161* ID_OUI_FROM_DATABASE=Meta Machine Technology OUI:000168* ID_OUI_FROM_DATABASE=VITANA CORPORATION OUI:000174* ID_OUI_FROM_DATABASE=CyberOptics Corporation OUI:000164* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000170* ID_OUI_FROM_DATABASE=ESE Embedded System Engineer'g OUI:000152* ID_OUI_FROM_DATABASE=CHROMATEK INC. OUI:000156* ID_OUI_FROM_DATABASE=FIREWIREDIRECT.COM, INC. OUI:00013F* ID_OUI_FROM_DATABASE=Neighbor World Co., Ltd. OUI:000146* ID_OUI_FROM_DATABASE=Tesco Controls, Inc. OUI:000133* ID_OUI_FROM_DATABASE=KYOWA Electronic Instruments C OUI:0001E3* ID_OUI_FROM_DATABASE=Siemens AG OUI:0001EA* ID_OUI_FROM_DATABASE=Cirilium Corp. OUI:0001EF* ID_OUI_FROM_DATABASE=Camtel Technology Corp. OUI:0001F2* ID_OUI_FROM_DATABASE=Mark of the Unicorn, Inc. OUI:0001D7* ID_OUI_FROM_DATABASE=F5 Networks, Inc. OUI:0001DC* ID_OUI_FROM_DATABASE=Activetelco OUI:0001DF* ID_OUI_FROM_DATABASE=ISDN Communications, Ltd. OUI:0001D3* ID_OUI_FROM_DATABASE=PAXCOMM, Inc. OUI:0001C5* ID_OUI_FROM_DATABASE=Simpler Networks OUI:0001D0* ID_OUI_FROM_DATABASE=VitalPoint, Inc. OUI:0001B2* ID_OUI_FROM_DATABASE=Digital Processing Systems, Inc. OUI:0001C1* ID_OUI_FROM_DATABASE=Vitesse Semiconductor Corporation OUI:0001BA* ID_OUI_FROM_DATABASE=IC-Net, Inc. OUI:0001B6* ID_OUI_FROM_DATABASE=SAEJIN T&M Co., Ltd. OUI:00022B* ID_OUI_FROM_DATABASE=SAXA, Inc. OUI:000226* ID_OUI_FROM_DATABASE=XESystems, Inc. OUI:00021E* ID_OUI_FROM_DATABASE=SIMTEL S.R.L. OUI:00021A* ID_OUI_FROM_DATABASE=Zuma Networks OUI:00020B* ID_OUI_FROM_DATABASE=Native Networks, Inc. OUI:000212* ID_OUI_FROM_DATABASE=SierraCom OUI:000217* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:000207* ID_OUI_FROM_DATABASE=VisionGlobal Network Corp. OUI:000204* ID_OUI_FROM_DATABASE=Bodmann Industries Elektronik GmbH OUI:0001F8* ID_OUI_FROM_DATABASE=TEXIO TECHNOLOGY CORPORATION OUI:0001FF* ID_OUI_FROM_DATABASE=Data Direct Networks, Inc. OUI:0001FB* ID_OUI_FROM_DATABASE=DoTop Technology, Inc. OUI:000268* ID_OUI_FROM_DATABASE=Harris Government Communications OUI:00025D* ID_OUI_FROM_DATABASE=Calix Networks OUI:000258* ID_OUI_FROM_DATABASE=Flying Packets Communications OUI:000257* ID_OUI_FROM_DATABASE=Microcom Corp. OUI:000254* ID_OUI_FROM_DATABASE=WorldGate OUI:000248* ID_OUI_FROM_DATABASE=Pilz GmbH & Co. OUI:00022E* ID_OUI_FROM_DATABASE=TEAC Corp. R& D OUI:000241* ID_OUI_FROM_DATABASE=Amer.com OUI:000232* ID_OUI_FROM_DATABASE=Avision, Inc. OUI:00012A* ID_OUI_FROM_DATABASE=Telematica Sistems Inteligente OUI:000130* ID_OUI_FROM_DATABASE=Extreme Networks OUI:000137* ID_OUI_FROM_DATABASE=IT Farm Corporation OUI:000143* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00011B* ID_OUI_FROM_DATABASE=Unizone Technologies, Inc. OUI:000122* ID_OUI_FROM_DATABASE=Trend Communications, Ltd. OUI:00011E* ID_OUI_FROM_DATABASE=Precidia Technologies, Inc. OUI:000108* ID_OUI_FROM_DATABASE=AVLAB Technology, Inc. OUI:00010B* ID_OUI_FROM_DATABASE=Space CyberLink, Inc. OUI:0001AE* ID_OUI_FROM_DATABASE=Trex Enterprises OUI:0001AA* ID_OUI_FROM_DATABASE=Airspan Communications, Ltd. OUI:000198* ID_OUI_FROM_DATABASE=Darim Vision OUI:000180* ID_OUI_FROM_DATABASE=AOpen, Inc. OUI:000187* ID_OUI_FROM_DATABASE=I2SE GmbH OUI:00018F* ID_OUI_FROM_DATABASE=Kenetec, Inc. OUI:000183* ID_OUI_FROM_DATABASE=ANITE TELECOMS OUI:00019C* ID_OUI_FROM_DATABASE=JDS Uniphase Inc. OUI:000190* ID_OUI_FROM_DATABASE=SMK-M OUI:0030D1* ID_OUI_FROM_DATABASE=INOVA CORPORATION OUI:003032* ID_OUI_FROM_DATABASE=MagicRam, Inc. OUI:00305A* ID_OUI_FROM_DATABASE=TELGEN CORPORATION OUI:003069* ID_OUI_FROM_DATABASE=IMPACCT TECHNOLOGY CORP. OUI:0030EC* ID_OUI_FROM_DATABASE=BORGARDT OUI:0030B4* ID_OUI_FROM_DATABASE=INTERSIL CORP. OUI:00308E* ID_OUI_FROM_DATABASE=CROSS MATCH TECHNOLOGIES, INC. OUI:0030D0* ID_OUI_FROM_DATABASE=Tellabs OUI:0030A5* ID_OUI_FROM_DATABASE=ACTIVE POWER OUI:003009* ID_OUI_FROM_DATABASE=Tachion Networks, Inc. OUI:00302F* ID_OUI_FROM_DATABASE=GE Aviation System OUI:0030A4* ID_OUI_FROM_DATABASE=Woodwind Communications System OUI:0030E5* ID_OUI_FROM_DATABASE=Amper Datos S.A. OUI:0030C0* ID_OUI_FROM_DATABASE=Lara Technology, Inc. OUI:00300E* ID_OUI_FROM_DATABASE=Klotz Digital AG OUI:003094* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00309A* ID_OUI_FROM_DATABASE=ASTRO TERRA CORP. OUI:00300C* ID_OUI_FROM_DATABASE=CONGRUENCY, LTD. OUI:0030FD* ID_OUI_FROM_DATABASE=INTEGRATED SYSTEMS DESIGN OUI:003023* ID_OUI_FROM_DATABASE=COGENT COMPUTER SYSTEMS, INC. OUI:0030DF* ID_OUI_FROM_DATABASE=KB/TEL TELECOMUNICACIONES OUI:00307D* ID_OUI_FROM_DATABASE=GRE AMERICA, INC. OUI:00D0E4* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00D08B* ID_OUI_FROM_DATABASE=ADVA Optical Networking Ltd. OUI:00D098* ID_OUI_FROM_DATABASE=Photon Dynamics Canada Inc. OUI:00D05E* ID_OUI_FROM_DATABASE=STRATABEAM TECHNOLOGY, INC. OUI:00D0BE* ID_OUI_FROM_DATABASE=EMUTEC INC. OUI:00D0F4* ID_OUI_FROM_DATABASE=CARINTHIAN TECH INSTITUTE OUI:00D0AA* ID_OUI_FROM_DATABASE=CHASE COMMUNICATIONS OUI:00D0FA* ID_OUI_FROM_DATABASE=Thales e-Security Ltd. OUI:00D006* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00D03D* ID_OUI_FROM_DATABASE=GALILEO TECHNOLOGY, LTD. OUI:00D014* ID_OUI_FROM_DATABASE=ROOT, INC. OUI:00D0DD* ID_OUI_FROM_DATABASE=SUNRISE TELECOM, INC. OUI:00D091* ID_OUI_FROM_DATABASE=SMARTSAN SYSTEMS, INC. OUI:00B0EE* ID_OUI_FROM_DATABASE=Ajile Systems, Inc. OUI:00B0E7* ID_OUI_FROM_DATABASE=British Federal Ltd. OUI:00B04A* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00B069* ID_OUI_FROM_DATABASE=Honewell Oy OUI:00B0C2* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00B0DF* ID_OUI_FROM_DATABASE=Starboard Storage Systems OUI:00B0EC* ID_OUI_FROM_DATABASE=EACEM OUI:003092* ID_OUI_FROM_DATABASE=ModuNORM GmbH OUI:0030EE* ID_OUI_FROM_DATABASE=DSG Technology, Inc. OUI:003042* ID_OUI_FROM_DATABASE=DeTeWe-Deutsche Telephonwerke OUI:003099* ID_OUI_FROM_DATABASE=BOENIG UND KALLENBACH OHG OUI:003051* ID_OUI_FROM_DATABASE=ORBIT AVIONIC & COMMUNICATION OUI:0030AB* ID_OUI_FROM_DATABASE=DELTA NETWORKS, INC. OUI:003093* ID_OUI_FROM_DATABASE=Sonnet Technologies, Inc OUI:00303C* ID_OUI_FROM_DATABASE=ONNTO CORP. OUI:0030C7* ID_OUI_FROM_DATABASE=Macromate Corp. OUI:003066* ID_OUI_FROM_DATABASE=RFM OUI:00307F* ID_OUI_FROM_DATABASE=IRLAN LTD. OUI:003016* ID_OUI_FROM_DATABASE=ISHIDA CO., LTD. OUI:00302A* ID_OUI_FROM_DATABASE=SOUTHERN INFORMATION OUI:0030DC* ID_OUI_FROM_DATABASE=RIGHTECH CORPORATION OUI:00D0A4* ID_OUI_FROM_DATABASE=ALANTRO COMMUNICATIONS OUI:00D043* ID_OUI_FROM_DATABASE=ZONAL RETAIL DATA SYSTEMS OUI:00D016* ID_OUI_FROM_DATABASE=SCM MICROSYSTEMS, INC. OUI:00D012* ID_OUI_FROM_DATABASE=GATEWORKS CORP. OUI:00D092* ID_OUI_FROM_DATABASE=GLENAYRE WESTERN MULTIPLEX OUI:00D0C5* ID_OUI_FROM_DATABASE=COMPUTATIONAL SYSTEMS, INC. OUI:0001A7* ID_OUI_FROM_DATABASE=UNEX TECHNOLOGY CORPORATION OUI:00D0B5* ID_OUI_FROM_DATABASE=IPricot formerly DotCom OUI:0030E8* ID_OUI_FROM_DATABASE=ENSIM CORP. OUI:0030ED* ID_OUI_FROM_DATABASE=Expert Magnetics Corp. OUI:0030F9* ID_OUI_FROM_DATABASE=Sollae Systems Co., Ltd. OUI:003098* ID_OUI_FROM_DATABASE=Global Converging Technologies OUI:0030E2* ID_OUI_FROM_DATABASE=GARNET SYSTEMS CO., LTD. OUI:003002* ID_OUI_FROM_DATABASE=Expand Networks OUI:00300B* ID_OUI_FROM_DATABASE=mPHASE Technologies, Inc. OUI:00308F* ID_OUI_FROM_DATABASE=MICRILOR, Inc. OUI:0030F3* ID_OUI_FROM_DATABASE=At Work Computers OUI:00D0F9* ID_OUI_FROM_DATABASE=ACUTE COMMUNICATIONS CORP. OUI:00D063* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00D069* ID_OUI_FROM_DATABASE=TECHNOLOGIC SYSTEMS OUI:00D070* ID_OUI_FROM_DATABASE=LONG WELL ELECTRONICS CORP. OUI:00D061* ID_OUI_FROM_DATABASE=TREMON ENTERPRISES CO., LTD. OUI:00D0C4* ID_OUI_FROM_DATABASE=TERATECH CORPORATION OUI:0030BF* ID_OUI_FROM_DATABASE=MULTIDATA GMBH OUI:00D0D7* ID_OUI_FROM_DATABASE=B2C2, INC. OUI:00D015* ID_OUI_FROM_DATABASE=UNIVEX MICROTECHNOLOGY CORP. OUI:00D0A5* ID_OUI_FROM_DATABASE=AMERICAN ARIUM OUI:00D0E5* ID_OUI_FROM_DATABASE=SOLIDUM SYSTEMS CORP. OUI:00D0B3* ID_OUI_FROM_DATABASE=DRS Technologies Canada Ltd OUI:00D0E9* ID_OUI_FROM_DATABASE=Advantage Century Telecommunication Corp. OUI:00D094* ID_OUI_FROM_DATABASE=Seeion Control LLC OUI:009045* ID_OUI_FROM_DATABASE=Marconi Communications OUI:0090F6* ID_OUI_FROM_DATABASE=ESCALATE NETWORKS, INC. OUI:0090EA* ID_OUI_FROM_DATABASE=ALPHA TECHNOLOGIES, INC. OUI:0090FE* ID_OUI_FROM_DATABASE=ELECOM CO., LTD. (LANEED DIV.) OUI:0090EB* ID_OUI_FROM_DATABASE=SENTRY TELECOM SYSTEMS OUI:00908E* ID_OUI_FROM_DATABASE=Nortel Networks Broadband Access OUI:0090CA* ID_OUI_FROM_DATABASE=ACCORD VIDEO TELECOMMUNICATIONS, LTD. OUI:00908B* ID_OUI_FROM_DATABASE=Tattile SRL OUI:009099* ID_OUI_FROM_DATABASE=ALLIED TELESIS, K.K. OUI:00900E* ID_OUI_FROM_DATABASE=HANDLINK TECHNOLOGIES, INC. OUI:0090F7* ID_OUI_FROM_DATABASE=NBASE COMMUNICATIONS LTD. OUI:009024* ID_OUI_FROM_DATABASE=PIPELINKS, INC. OUI:009052* ID_OUI_FROM_DATABASE=SELCOM ELETTRONICA S.R.L. OUI:0090E5* ID_OUI_FROM_DATABASE=TEKNEMA, INC. OUI:009085* ID_OUI_FROM_DATABASE=GOLDEN ENTERPRISES, INC. OUI:009019* ID_OUI_FROM_DATABASE=HERMES ELECTRONICS CO., LTD. OUI:0090DC* ID_OUI_FROM_DATABASE=TECO INFORMATION SYSTEMS OUI:00D0AE* ID_OUI_FROM_DATABASE=ORESIS COMMUNICATIONS, INC. OUI:00D0D4* ID_OUI_FROM_DATABASE=V-BITS, INC. OUI:00D041* ID_OUI_FROM_DATABASE=AMIGO TECHNOLOGY CO., LTD. OUI:00D0D1* ID_OUI_FROM_DATABASE=Sycamore Networks OUI:00D0A1* ID_OUI_FROM_DATABASE=OSKAR VIERLING GMBH + CO. KG OUI:00D00B* ID_OUI_FROM_DATABASE=RHK TECHNOLOGY, INC. OUI:00D02C* ID_OUI_FROM_DATABASE=CAMPBELL SCIENTIFIC, INC. OUI:00D0A0* ID_OUI_FROM_DATABASE=MIPS DENMARK OUI:00D04E* ID_OUI_FROM_DATABASE=LOGIBAG OUI:00D0D9* ID_OUI_FROM_DATABASE=DEDICATED MICROCOMPUTERS OUI:00D0CD* ID_OUI_FROM_DATABASE=ATAN TECHNOLOGY INC. OUI:00D01D* ID_OUI_FROM_DATABASE=FURUNO ELECTRIC CO., LTD. OUI:00D0C7* ID_OUI_FROM_DATABASE=PATHWAY, INC. OUI:00D05C* ID_OUI_FROM_DATABASE=KATHREIN TechnoTrend GmbH OUI:00D040* ID_OUI_FROM_DATABASE=SYSMATE CO., LTD. OUI:00D08A* ID_OUI_FROM_DATABASE=PHOTRON USA OUI:00D076* ID_OUI_FROM_DATABASE=Bank of America OUI:00D07A* ID_OUI_FROM_DATABASE=AMAQUEST COMPUTER CORP. OUI:00D0BB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:00D001* ID_OUI_FROM_DATABASE=VST TECHNOLOGIES, INC. OUI:00904C* ID_OUI_FROM_DATABASE=Epigram, Inc. OUI:009000* ID_OUI_FROM_DATABASE=DIAMOND MULTIMEDIA OUI:009025* ID_OUI_FROM_DATABASE=BAE Systems Australia (Electronic Systems) Pty Ltd OUI:0090F8* ID_OUI_FROM_DATABASE=MEDIATRIX TELECOM OUI:009084* ID_OUI_FROM_DATABASE=ATECH SYSTEM OUI:009054* ID_OUI_FROM_DATABASE=INNOVATIVE SEMICONDUCTORS, INC OUI:009080* ID_OUI_FROM_DATABASE=NOT LIMITED, INC. OUI:0090C0* ID_OUI_FROM_DATABASE=K.J. LAW ENGINEERS, INC. OUI:0090BC* ID_OUI_FROM_DATABASE=TELEMANN CO., LTD. OUI:00900A* ID_OUI_FROM_DATABASE=PROTON ELECTRONIC INDUSTRIAL CO., LTD. OUI:00904E* ID_OUI_FROM_DATABASE=DELEM BV OUI:00904A* ID_OUI_FROM_DATABASE=CONCUR SYSTEM TECHNOLOGIES OUI:009029* ID_OUI_FROM_DATABASE=CRYPTO AG OUI:009061* ID_OUI_FROM_DATABASE=PACIFIC RESEARCH & ENGINEERING CORPORATION OUI:0090A9* ID_OUI_FROM_DATABASE=WESTERN DIGITAL OUI:009006* ID_OUI_FROM_DATABASE=HAMAMATSU PHOTONICS K.K. OUI:009072* ID_OUI_FROM_DATABASE=SIMRAD AS OUI:005048* ID_OUI_FROM_DATABASE=INFOLIBRIA OUI:0050EA* ID_OUI_FROM_DATABASE=XEL COMMUNICATIONS, INC. OUI:0050CE* ID_OUI_FROM_DATABASE=LG INTERNATIONAL CORP. OUI:005019* ID_OUI_FROM_DATABASE=SPRING TIDE NETWORKS, INC. OUI:0050AC* ID_OUI_FROM_DATABASE=MAPLE COMPUTER CORPORATION OUI:005044* ID_OUI_FROM_DATABASE=ASACA CORPORATION OUI:0050C6* ID_OUI_FROM_DATABASE=LOOP TELECOMMUNICATION INTERNATIONAL, INC. OUI:005049* ID_OUI_FROM_DATABASE=Arbor Networks Inc OUI:00509F* ID_OUI_FROM_DATABASE=HORIZON COMPUTER OUI:0050C8* ID_OUI_FROM_DATABASE=Addonics Technologies, Inc. OUI:0050DC* ID_OUI_FROM_DATABASE=TAS TELEFONBAU A. SCHWABE GMBH & CO. KG OUI:005069* ID_OUI_FROM_DATABASE=PixStream Incorporated OUI:00901D* ID_OUI_FROM_DATABASE=PEC (NZ) LTD. OUI:00902D* ID_OUI_FROM_DATABASE=DATA ELECTRONICS (AUST.) PTY, LTD. OUI:009007* ID_OUI_FROM_DATABASE=DOMEX TECHNOLOGY CORP. OUI:009048* ID_OUI_FROM_DATABASE=ZEAL CORPORATION OUI:0090E6* ID_OUI_FROM_DATABASE=ALi Corporation OUI:009046* ID_OUI_FROM_DATABASE=DEXDYNE, LTD. OUI:00905E* ID_OUI_FROM_DATABASE=RAULAND-BORG CORPORATION OUI:009067* ID_OUI_FROM_DATABASE=WalkAbout Computers, Inc. OUI:0090DA* ID_OUI_FROM_DATABASE=DYNARC, INC. OUI:009026* ID_OUI_FROM_DATABASE=ADVANCED SWITCHING COMMUNICATIONS, INC. OUI:0090BB* ID_OUI_FROM_DATABASE=TAINET COMMUNICATION SYSTEM Corp. OUI:009033* ID_OUI_FROM_DATABASE=INNOVAPHONE AG OUI:009010* ID_OUI_FROM_DATABASE=SIMULATION LABORATORIES, INC. OUI:00903D* ID_OUI_FROM_DATABASE=BIOPAC SYSTEMS, INC. OUI:009057* ID_OUI_FROM_DATABASE=AANetcom, Inc. OUI:00901C* ID_OUI_FROM_DATABASE=mps Software Gmbh OUI:009056* ID_OUI_FROM_DATABASE=TELESTREAM, INC. OUI:00907D* ID_OUI_FROM_DATABASE=Lake Communications OUI:0090DB* ID_OUI_FROM_DATABASE=NEXT LEVEL COMMUNICATIONS OUI:005042* ID_OUI_FROM_DATABASE=SCI MANUFACTURING SINGAPORE PTE, LTD. OUI:0050C0* ID_OUI_FROM_DATABASE=GATAN, INC. OUI:0050D3* ID_OUI_FROM_DATABASE=DIGITAL AUDIO PROCESSING PTY. LTD. OUI:00509A* ID_OUI_FROM_DATABASE=TAG ELECTRONIC SYSTEMS OUI:00507D* ID_OUI_FROM_DATABASE=IFP OUI:0050D0* ID_OUI_FROM_DATABASE=MINERVA SYSTEMS OUI:005098* ID_OUI_FROM_DATABASE=GLOBALOOP, LTD. OUI:0050FA* ID_OUI_FROM_DATABASE=OXTEL, LTD. OUI:005086* ID_OUI_FROM_DATABASE=TELKOM SA, LTD. OUI:0050E1* ID_OUI_FROM_DATABASE=NS TECH ELECTRONICS SDN BHD OUI:005013* ID_OUI_FROM_DATABASE=Chaparral Network Storage OUI:005022* ID_OUI_FROM_DATABASE=ZONET TECHNOLOGY, INC. OUI:005040* ID_OUI_FROM_DATABASE=Panasonic Electric Works Co., Ltd. OUI:0050D6* ID_OUI_FROM_DATABASE=ATLAS COPCO TOOLS AB OUI:005082* ID_OUI_FROM_DATABASE=FORESSON CORPORATION OUI:0050CA* ID_OUI_FROM_DATABASE=NET TO NET TECHNOLOGIES OUI:0050A6* ID_OUI_FROM_DATABASE=OPTRONICS OUI:0050DB* ID_OUI_FROM_DATABASE=CONTEMPORARY CONTROL OUI:00506B* ID_OUI_FROM_DATABASE=SPX-ATEG OUI:005074* ID_OUI_FROM_DATABASE=ADVANCED HI-TECH CORP. OUI:005047* ID_OUI_FROM_DATABASE=Private OUI:005067* ID_OUI_FROM_DATABASE=AEROCOMM, INC. OUI:005024* ID_OUI_FROM_DATABASE=NAVIC SYSTEMS, INC. OUI:005041* ID_OUI_FROM_DATABASE=Coretronic Corporation OUI:0050D2* ID_OUI_FROM_DATABASE=CMC Electronics Inc OUI:0090DE* ID_OUI_FROM_DATABASE=CARDKEY SYSTEMS, INC. OUI:009060* ID_OUI_FROM_DATABASE=SYSTEM CREATE CORP. OUI:0090F1* ID_OUI_FROM_DATABASE=DOT HILL SYSTEMS CORPORATION OUI:0090E2* ID_OUI_FROM_DATABASE=DISTRIBUTED PROCESSING TECHNOLOGY OUI:00906B* ID_OUI_FROM_DATABASE=APPLIED RESOURCES, INC. OUI:009020* ID_OUI_FROM_DATABASE=PHILIPS ANALYTICAL X-RAY B.V. OUI:009065* ID_OUI_FROM_DATABASE=FINISAR CORPORATION OUI:001053* ID_OUI_FROM_DATABASE=COMPUTER TECHNOLOGY CORP. OUI:0010A3* ID_OUI_FROM_DATABASE=OMNITRONIX, INC. OUI:00102B* ID_OUI_FROM_DATABASE=UMAX DATA SYSTEMS, INC. OUI:001055* ID_OUI_FROM_DATABASE=FUJITSU MICROELECTRONICS, INC. OUI:00103C* ID_OUI_FROM_DATABASE=IC ENSEMBLE, INC. OUI:0010D9* ID_OUI_FROM_DATABASE=IBM JAPAN, FUJISAWA MT+D OUI:0010A5* ID_OUI_FROM_DATABASE=OXFORD INSTRUMENTS OUI:001046* ID_OUI_FROM_DATABASE=ALCORN MCBRIDE INC. OUI:00E0DC* ID_OUI_FROM_DATABASE=NEXWARE CORP. OUI:00E0D9* ID_OUI_FROM_DATABASE=TAZMO CO., LTD. OUI:00E0C2* ID_OUI_FROM_DATABASE=NECSY S.p.A. OUI:00E09B* ID_OUI_FROM_DATABASE=ENGAGE NETWORKS, INC. OUI:00E045* ID_OUI_FROM_DATABASE=TOUCHWAVE, INC. OUI:00E055* ID_OUI_FROM_DATABASE=INGENIERIA ELECTRONICA COMERCIAL INELCOM S.A. OUI:00E037* ID_OUI_FROM_DATABASE=CENTURY CORPORATION OUI:00E081* ID_OUI_FROM_DATABASE=TYAN COMPUTER CORP. OUI:00E0D4* ID_OUI_FROM_DATABASE=EXCELLENT COMPUTER OUI:00E01A* ID_OUI_FROM_DATABASE=COMTEC SYSTEMS. CO., LTD. OUI:00E0BC* ID_OUI_FROM_DATABASE=SYMON COMMUNICATIONS, INC. OUI:00E084* ID_OUI_FROM_DATABASE=COMPULITE R&D OUI:00E0F6* ID_OUI_FROM_DATABASE=DECISION EUROPE OUI:00E027* ID_OUI_FROM_DATABASE=DUX, INC. OUI:00E07F* ID_OUI_FROM_DATABASE=LOGISTISTEM s.r.l. OUI:00E043* ID_OUI_FROM_DATABASE=VitalCom OUI:00E0BF* ID_OUI_FROM_DATABASE=TORRENT NETWORKING TECHNOLOGIES CORP. OUI:00E09D* ID_OUI_FROM_DATABASE=SARNOFF CORPORATION OUI:00E0BB* ID_OUI_FROM_DATABASE=NBX CORPORATION OUI:00E08A* ID_OUI_FROM_DATABASE=GEC AVERY, LTD. OUI:00E04B* ID_OUI_FROM_DATABASE=JUMP INDUSTRIELLE COMPUTERTECHNIK GmbH OUI:001015* ID_OUI_FROM_DATABASE=OOmon Inc. OUI:001088* ID_OUI_FROM_DATABASE=AMERICAN NETWORKS INC. OUI:001008* ID_OUI_FROM_DATABASE=VIENNA SYSTEMS CORPORATION OUI:0010CC* ID_OUI_FROM_DATABASE=CLP COMPUTER LOGISTIK PLANUNG GmbH OUI:001094* ID_OUI_FROM_DATABASE=Performance Analysis Broadband, Spirent plc OUI:0010BB* ID_OUI_FROM_DATABASE=DATA & INFORMATION TECHNOLOGY OUI:001028* ID_OUI_FROM_DATABASE=COMPUTER TECHNICA, INC. OUI:00108A* ID_OUI_FROM_DATABASE=TeraLogic, Inc. OUI:0010C5* ID_OUI_FROM_DATABASE=PROTOCOL TECHNOLOGIES, INC. OUI:00106D* ID_OUI_FROM_DATABASE=Axxcelera Broadband Wireless OUI:0010FC* ID_OUI_FROM_DATABASE=BROADBAND NETWORKS, INC. OUI:001078* ID_OUI_FROM_DATABASE=NUERA COMMUNICATIONS, INC. OUI:001048* ID_OUI_FROM_DATABASE=HTRC AUTOMATION, INC. OUI:001081* ID_OUI_FROM_DATABASE=DPS, INC. OUI:00102D* ID_OUI_FROM_DATABASE=HITACHI SOFTWARE ENGINEERING OUI:00109F* ID_OUI_FROM_DATABASE=PAVO, INC. OUI:0010A1* ID_OUI_FROM_DATABASE=KENDIN SEMICONDUCTOR, INC. OUI:001084* ID_OUI_FROM_DATABASE=K-BOT COMMUNICATIONS OUI:0010AF* ID_OUI_FROM_DATABASE=TAC SYSTEMS, INC. OUI:00100F* ID_OUI_FROM_DATABASE=INDUSTRIAL CPU SYSTEMS OUI:0010A2* ID_OUI_FROM_DATABASE=TNS OUI:001000* ID_OUI_FROM_DATABASE=CABLE TELEVISION LABORATORIES, INC. OUI:00103B* ID_OUI_FROM_DATABASE=HIPPI NETWORKING FORUM OUI:0060C2* ID_OUI_FROM_DATABASE=MPL AG OUI:0060A2* ID_OUI_FROM_DATABASE=NIHON UNISYS LIMITED CO. OUI:006046* ID_OUI_FROM_DATABASE=VMETRO, INC. OUI:00609D* ID_OUI_FROM_DATABASE=PMI FOOD EQUIPMENT GROUP OUI:0060BF* ID_OUI_FROM_DATABASE=MACRAIGOR SYSTEMS, INC. OUI:00604A* ID_OUI_FROM_DATABASE=SAIC IDEAS GROUP OUI:006081* ID_OUI_FROM_DATABASE=TV/COM INTERNATIONAL OUI:0060B4* ID_OUI_FROM_DATABASE=GLENAYRE R&D INC. OUI:006045* ID_OUI_FROM_DATABASE=PATHLIGHT TECHNOLOGIES OUI:00A005* ID_OUI_FROM_DATABASE=DANIEL INSTRUMENTS, LTD. OUI:00A053* ID_OUI_FROM_DATABASE=COMPACT DEVICES, INC. OUI:00A033* ID_OUI_FROM_DATABASE=imc MeBsysteme GmbH OUI:00A059* ID_OUI_FROM_DATABASE=HAMILTON HALLMARK OUI:00A0AD* ID_OUI_FROM_DATABASE=MARCONI SPA OUI:00A0F6* ID_OUI_FROM_DATABASE=AutoGas Systems Inc. OUI:00A096* ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO., LTD. OUI:00A006* ID_OUI_FROM_DATABASE=IMAGE DATA PROCESSING SYSTEM GROUP OUI:0060F3* ID_OUI_FROM_DATABASE=Performance Analysis Broadband, Spirent plc OUI:00600B* ID_OUI_FROM_DATABASE=LOGWARE GmbH OUI:00603F* ID_OUI_FROM_DATABASE=PATAPSCO DESIGNS OUI:00607C* ID_OUI_FROM_DATABASE=WaveAccess, Ltd. OUI:00608D* ID_OUI_FROM_DATABASE=UNIPULSE CORP. OUI:006049* ID_OUI_FROM_DATABASE=VINA TECHNOLOGIES OUI:0060A1* ID_OUI_FROM_DATABASE=VPNet, Inc. OUI:0060C9* ID_OUI_FROM_DATABASE=ControlNet, Inc. OUI:00605F* ID_OUI_FROM_DATABASE=NIPPON UNISOFT CORPORATION OUI:006021* ID_OUI_FROM_DATABASE=DSC CORPORATION OUI:00601D* ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES OUI:000800* ID_OUI_FROM_DATABASE=MULTITECH SYSTEMS, INC. OUI:0060C7* ID_OUI_FROM_DATABASE=AMATI COMMUNICATIONS CORP. OUI:00E0CA* ID_OUI_FROM_DATABASE=BEST DATA PRODUCTS OUI:00E097* ID_OUI_FROM_DATABASE=CARRIER ACCESS CORPORATION OUI:00E09F* ID_OUI_FROM_DATABASE=PIXEL VISION OUI:00E0F5* ID_OUI_FROM_DATABASE=TELES AG OUI:00E070* ID_OUI_FROM_DATABASE=DH TECHNOLOGY OUI:00E0B5* ID_OUI_FROM_DATABASE=ARDENT COMMUNICATIONS CORP. OUI:00E073* ID_OUI_FROM_DATABASE=NATIONAL AMUSEMENT NETWORK, INC. OUI:00E09E* ID_OUI_FROM_DATABASE=QUANTUM CORPORATION OUI:00E0E8* ID_OUI_FROM_DATABASE=GRETACODER Data Systems AG OUI:00E016* ID_OUI_FROM_DATABASE=RAPID CITY COMMUNICATIONS OUI:00E001* ID_OUI_FROM_DATABASE=STRAND LIGHTING LIMITED OUI:00E082* ID_OUI_FROM_DATABASE=ANERMA OUI:00E0EA* ID_OUI_FROM_DATABASE=INNOVAT COMMUNICATIONS, INC. OUI:00E06A* ID_OUI_FROM_DATABASE=KAPSCH AG OUI:00E023* ID_OUI_FROM_DATABASE=TELRAD OUI:00E0C3* ID_OUI_FROM_DATABASE=SAKAI SYSTEM DEVELOPMENT CORP. OUI:00601A* ID_OUI_FROM_DATABASE=KEITHLEY INSTRUMENTS OUI:0060AF* ID_OUI_FROM_DATABASE=PACIFIC MICRO DATA, INC. OUI:00601F* ID_OUI_FROM_DATABASE=STALLION TECHNOLOGIES OUI:00608F* ID_OUI_FROM_DATABASE=TEKRAM TECHNOLOGY CO., LTD. OUI:0060C5* ID_OUI_FROM_DATABASE=ANCOT CORP. OUI:006023* ID_OUI_FROM_DATABASE=PERICOM SEMICONDUCTOR CORP. OUI:006063* ID_OUI_FROM_DATABASE=PSION DACOM PLC. OUI:00604F* ID_OUI_FROM_DATABASE=Tattile SRL OUI:0060E8* ID_OUI_FROM_DATABASE=HITACHI COMPUTER PRODUCTS (AMERICA), INC. OUI:006072* ID_OUI_FROM_DATABASE=VXL INSTRUMENTS, LIMITED OUI:006054* ID_OUI_FROM_DATABASE=CONTROLWARE GMBH OUI:00A0DC* ID_OUI_FROM_DATABASE=O.N. ELECTRONIC CO., LTD. OUI:00A013* ID_OUI_FROM_DATABASE=TELTREND LTD. OUI:00A0DF* ID_OUI_FROM_DATABASE=STS TECHNOLOGIES, INC. OUI:00A061* ID_OUI_FROM_DATABASE=PURITAN BENNETT OUI:00A0CE* ID_OUI_FROM_DATABASE=Ecessa OUI:00A02A* ID_OUI_FROM_DATABASE=TRANCELL SYSTEMS OUI:00A02C* ID_OUI_FROM_DATABASE=interWAVE Communications OUI:00A077* ID_OUI_FROM_DATABASE=FUJITSU NEXION, INC. OUI:00A020* ID_OUI_FROM_DATABASE=CITICORP/TTI OUI:00A00D* ID_OUI_FROM_DATABASE=THE PANDA PROJECT OUI:00A031* ID_OUI_FROM_DATABASE=HAZELTINE CORPORATION, MS 1-17 OUI:00A041* ID_OUI_FROM_DATABASE=INFICON OUI:0060FA* ID_OUI_FROM_DATABASE=EDUCATIONAL TECHNOLOGY RESOURCES, INC. OUI:000288* ID_OUI_FROM_DATABASE=GLOBAL VILLAGE COMMUNICATION OUI:0060F9* ID_OUI_FROM_DATABASE=DIAMOND LANE COMMUNICATIONS OUI:0060EA* ID_OUI_FROM_DATABASE=StreamLogic OUI:0060EC* ID_OUI_FROM_DATABASE=HERMARY OPTO ELECTRONICS INC. OUI:00604E* ID_OUI_FROM_DATABASE=CYCLE COMPUTER CORPORATION, INC. OUI:00602C* ID_OUI_FROM_DATABASE=LINX Data Terminals, Inc. OUI:006028* ID_OUI_FROM_DATABASE=MACROVISION CORPORATION OUI:00606A* ID_OUI_FROM_DATABASE=MITSUBISHI WIRELESS COMMUNICATIONS. INC. OUI:00E011* ID_OUI_FROM_DATABASE=Uniden Corporation OUI:00E021* ID_OUI_FROM_DATABASE=FREEGATE CORP. OUI:00E0AB* ID_OUI_FROM_DATABASE=DIMAT S.A. OUI:00E0B6* ID_OUI_FROM_DATABASE=Entrada Networks OUI:00E0EC* ID_OUI_FROM_DATABASE=CELESTICA INC. OUI:00E038* ID_OUI_FROM_DATABASE=PROXIMA CORPORATION OUI:00E090* ID_OUI_FROM_DATABASE=BECKMAN LAB. AUTOMATION DIV. OUI:00E02E* ID_OUI_FROM_DATABASE=SPC ELECTRONICS CORPORATION OUI:00E0F4* ID_OUI_FROM_DATABASE=INSIDE Technology A/S OUI:00E03C* ID_OUI_FROM_DATABASE=AdvanSys OUI:00E096* ID_OUI_FROM_DATABASE=SHIMADZU CORPORATION OUI:00E0F1* ID_OUI_FROM_DATABASE=THAT CORPORATION OUI:00A0D0* ID_OUI_FROM_DATABASE=TEN X TECHNOLOGY, INC. OUI:00A0E0* ID_OUI_FROM_DATABASE=TENNYSON TECHNOLOGIES PTY LTD OUI:00A099* ID_OUI_FROM_DATABASE=K-NET LTD. OUI:00A03D* ID_OUI_FROM_DATABASE=OPTO-22 OUI:00A08C* ID_OUI_FROM_DATABASE=MultiMedia LANs, Inc. OUI:1000E8* ID_OUI_FROM_DATABASE=NATIONAL SEMICONDUCTOR OUI:006076* ID_OUI_FROM_DATABASE=SCHLUMBERGER TECHNOLOGIES RETAIL PETROLEUM SYSTEMS OUI:0060AE* ID_OUI_FROM_DATABASE=TRIO INFORMATION SYSTEMS AB OUI:00606C* ID_OUI_FROM_DATABASE=ARESCOM OUI:006032* ID_OUI_FROM_DATABASE=I-CUBE, INC. OUI:006060* ID_OUI_FROM_DATABASE=Data Innovations North America OUI:00A0EB* ID_OUI_FROM_DATABASE=Encore Networks, Inc. OUI:00A0C1* ID_OUI_FROM_DATABASE=ORTIVUS MEDICAL AB OUI:00A07D* ID_OUI_FROM_DATABASE=SEEQ TECHNOLOGY, INC. OUI:00A0C6* ID_OUI_FROM_DATABASE=QUALCOMM INCORPORATED OUI:00A0CF* ID_OUI_FROM_DATABASE=SOTAS, INC. OUI:00A03A* ID_OUI_FROM_DATABASE=KUBOTEK CORPORATION OUI:00A0D7* ID_OUI_FROM_DATABASE=KASTEN CHASE APPLIED RESEARCH OUI:00A09D* ID_OUI_FROM_DATABASE=JOHNATHON FREEMAN TECHNOLOGIES OUI:00A036* ID_OUI_FROM_DATABASE=APPLIED NETWORK TECHNOLOGY OUI:00A0D2* ID_OUI_FROM_DATABASE=ALLIED TELESIS INTERNATIONAL CORPORATION OUI:00A075* ID_OUI_FROM_DATABASE=MICRON TECHNOLOGY, INC. OUI:00A009* ID_OUI_FROM_DATABASE=WHITETREE NETWORK OUI:00A060* ID_OUI_FROM_DATABASE=ACER PERIPHERALS, INC. OUI:00A00C* ID_OUI_FROM_DATABASE=KINGMAX TECHNOLOGY, INC. OUI:0020FD* ID_OUI_FROM_DATABASE=ITV TECHNOLOGIES, INC. OUI:00200D* ID_OUI_FROM_DATABASE=CARL ZEISS OUI:002091* ID_OUI_FROM_DATABASE=J125, NATIONAL SECURITY AGENCY OUI:002054* ID_OUI_FROM_DATABASE=Sycamore Networks OUI:0020A7* ID_OUI_FROM_DATABASE=PAIRGAIN TECHNOLOGIES, INC. OUI:0020DA* ID_OUI_FROM_DATABASE=Alcatel North America ESD OUI:002005* ID_OUI_FROM_DATABASE=SIMPLE TECHNOLOGY OUI:00202B* ID_OUI_FROM_DATABASE=ADVANCED TELECOMMUNICATIONS MODULES, LTD. OUI:002086* ID_OUI_FROM_DATABASE=MICROTECH ELECTRONICS LIMITED OUI:002052* ID_OUI_FROM_DATABASE=RAGULA SYSTEMS OUI:002090* ID_OUI_FROM_DATABASE=ADVANCED COMPRESSION TECHNOLOGY, INC. OUI:0020A3* ID_OUI_FROM_DATABASE=Harmonic, Inc OUI:00206A* ID_OUI_FROM_DATABASE=OSAKA COMPUTER CORP. OUI:0020DB* ID_OUI_FROM_DATABASE=XNET TECHNOLOGY, INC. OUI:0020A4* ID_OUI_FROM_DATABASE=MULTIPOINT NETWORKS OUI:00201C* ID_OUI_FROM_DATABASE=EXCEL, INC. OUI:00209B* ID_OUI_FROM_DATABASE=ERSAT ELECTRONIC GMBH OUI:0020C9* ID_OUI_FROM_DATABASE=VICTRON BV OUI:0020D1* ID_OUI_FROM_DATABASE=MICROCOMPUTER SYSTEMS (M) SDN. OUI:002084* ID_OUI_FROM_DATABASE=OCE PRINTING SYSTEMS, GMBH OUI:0020C2* ID_OUI_FROM_DATABASE=TEXAS MEMORY SYSTEMS, INC. OUI:0020C8* ID_OUI_FROM_DATABASE=LARSCOM INCORPORATED OUI:0020EC* ID_OUI_FROM_DATABASE=TECHWARE SYSTEMS CORP. OUI:002083* ID_OUI_FROM_DATABASE=PRESTICOM INCORPORATED OUI:00206D* ID_OUI_FROM_DATABASE=DATA RACE, INC. OUI:00203A* ID_OUI_FROM_DATABASE=DIGITAL BI0METRICS INC. OUI:00A06C* ID_OUI_FROM_DATABASE=SHINDENGEN ELECTRIC MFG. CO., LTD. OUI:00A0EE* ID_OUI_FROM_DATABASE=NASHOBA NETWORKS OUI:00A0FB* ID_OUI_FROM_DATABASE=TORAY ENGINEERING CO., LTD. OUI:00A0E3* ID_OUI_FROM_DATABASE=XKL SYSTEMS CORP. OUI:00A01E* ID_OUI_FROM_DATABASE=EST CORPORATION OUI:00A080* ID_OUI_FROM_DATABASE=Tattile SRL OUI:00A0C2* ID_OUI_FROM_DATABASE=R.A. SYSTEMS CO., LTD. OUI:00A0CB* ID_OUI_FROM_DATABASE=ARK TELECOMMUNICATIONS, INC. OUI:00A074* ID_OUI_FROM_DATABASE=PERCEPTION TECHNOLOGY OUI:00A06A* ID_OUI_FROM_DATABASE=Verilink Corporation OUI:00A070* ID_OUI_FROM_DATABASE=COASTCOM OUI:00A079* ID_OUI_FROM_DATABASE=ALPS ELECTRIC (USA), INC. OUI:002059* ID_OUI_FROM_DATABASE=MIRO COMPUTER PRODUCTS AG OUI:0020BC* ID_OUI_FROM_DATABASE=Long Reach Networks Pty Ltd OUI:0020AD* ID_OUI_FROM_DATABASE=LINQ SYSTEMS OUI:002046* ID_OUI_FROM_DATABASE=CIPRICO, INC. OUI:002071* ID_OUI_FROM_DATABASE=IBR GMBH OUI:0020A2* ID_OUI_FROM_DATABASE=GALCOM NETWORKING LTD. OUI:002098* ID_OUI_FROM_DATABASE=HECTRONIC AB OUI:002065* ID_OUI_FROM_DATABASE=SUPERNET NETWORKING INC. OUI:002094* ID_OUI_FROM_DATABASE=CUBIX CORPORATION OUI:0020C3* ID_OUI_FROM_DATABASE=COUNTER SOLUTIONS LTD. OUI:0020A5* ID_OUI_FROM_DATABASE=API ENGINEERING OUI:002070* ID_OUI_FROM_DATABASE=HYNET, LTD. OUI:00201E* ID_OUI_FROM_DATABASE=NETQUEST CORPORATION OUI:002097* ID_OUI_FROM_DATABASE=APPLIED SIGNAL TECHNOLOGY OUI:0020E8* ID_OUI_FROM_DATABASE=DATATREK CORPORATION OUI:00204F* ID_OUI_FROM_DATABASE=DEUTSCHE AEROSPACE AG OUI:00202E* ID_OUI_FROM_DATABASE=DAYSTAR DIGITAL OUI:0020B0* ID_OUI_FROM_DATABASE=GATEWAY DEVICES, INC. OUI:0020A9* ID_OUI_FROM_DATABASE=WHITE HORSE INDUSTRIAL OUI:002061* ID_OUI_FROM_DATABASE=GarrettCom, Inc. OUI:0020C6* ID_OUI_FROM_DATABASE=NECTEC OUI:0020D2* ID_OUI_FROM_DATABASE=RAD DATA COMMUNICATIONS, LTD. OUI:00A0F8* ID_OUI_FROM_DATABASE=Zebra Technologies Inc OUI:00A025* ID_OUI_FROM_DATABASE=REDCOM LABS INC. OUI:00A0D4* ID_OUI_FROM_DATABASE=RADIOLAN, INC. OUI:00A08A* ID_OUI_FROM_DATABASE=BROOKTROUT TECHNOLOGY, INC. OUI:002093* ID_OUI_FROM_DATABASE=LANDINGS TECHNOLOGY CORP. OUI:002056* ID_OUI_FROM_DATABASE=NEOPRODUCTS OUI:0020A6* ID_OUI_FROM_DATABASE=Proxim Wireless OUI:00C073* ID_OUI_FROM_DATABASE=XEDIA CORPORATION OUI:00C0D4* ID_OUI_FROM_DATABASE=AXON NETWORKS, INC. OUI:00C0E5* ID_OUI_FROM_DATABASE=GESPAC, S.A. OUI:00A0CA* ID_OUI_FROM_DATABASE=FUJITSU DENSO LTD. OUI:00A029* ID_OUI_FROM_DATABASE=COULTER CORPORATION OUI:00C088* ID_OUI_FROM_DATABASE=EKF ELEKTRONIK GMBH OUI:00C056* ID_OUI_FROM_DATABASE=SOMELEC OUI:00C063* ID_OUI_FROM_DATABASE=MORNING STAR TECHNOLOGIES, INC OUI:00C021* ID_OUI_FROM_DATABASE=NETEXPRESS OUI:00C049* ID_OUI_FROM_DATABASE=U.S. ROBOTICS, INC. OUI:00C032* ID_OUI_FROM_DATABASE=I-CUBED LIMITED OUI:00C051* ID_OUI_FROM_DATABASE=ADVANCED INTEGRATION RESEARCH OUI:00C085* ID_OUI_FROM_DATABASE=ELECTRONICS FOR IMAGING, INC. OUI:00C0FE* ID_OUI_FROM_DATABASE=APTEC COMPUTER SYSTEMS, INC. OUI:00C0E8* ID_OUI_FROM_DATABASE=PLEXCOM, INC. OUI:00C0B2* ID_OUI_FROM_DATABASE=NORAND CORPORATION OUI:00C0B1* ID_OUI_FROM_DATABASE=GENIUS NET CO. OUI:00C0D9* ID_OUI_FROM_DATABASE=QUINTE NETWORK CONFIDENTIALITY OUI:00C038* ID_OUI_FROM_DATABASE=RASTER IMAGE PROCESSING SYSTEM OUI:00C098* ID_OUI_FROM_DATABASE=CHUNTEX ELECTRONIC CO., LTD. OUI:00C0DD* ID_OUI_FROM_DATABASE=QLogic Corporation OUI:00C08A* ID_OUI_FROM_DATABASE=Lauterbach GmbH OUI:00409F* ID_OUI_FROM_DATABASE=Telco Systems, Inc. OUI:0040FF* ID_OUI_FROM_DATABASE=TELEBIT CORPORATION OUI:0040D7* ID_OUI_FROM_DATABASE=STUDIO GEN INC. OUI:004007* ID_OUI_FROM_DATABASE=TELMAT INFORMATIQUE OUI:00408D* ID_OUI_FROM_DATABASE=THE GOODYEAR TIRE & RUBBER CO. OUI:00402C* ID_OUI_FROM_DATABASE=ISIS DISTRIBUTED SYSTEMS, INC. OUI:00C03D* ID_OUI_FROM_DATABASE=WIESEMANN & THEIS GMBH OUI:00C026* ID_OUI_FROM_DATABASE=LANS TECHNOLOGY CO., LTD. OUI:0040E2* ID_OUI_FROM_DATABASE=MESA RIDGE TECHNOLOGIES, INC. OUI:004078* ID_OUI_FROM_DATABASE=WEARNES AUTOMATION PTE LTD OUI:004062* ID_OUI_FROM_DATABASE=E-SYSTEMS, INC./GARLAND DIV. OUI:0040D2* ID_OUI_FROM_DATABASE=PAGINE CORPORATION OUI:0040D0* ID_OUI_FROM_DATABASE=MITAC INTERNATIONAL CORP. OUI:0040E4* ID_OUI_FROM_DATABASE=E-M TECHNOLOGY, INC. OUI:0040BF* ID_OUI_FROM_DATABASE=CHANNEL SYSTEMS INTERN'L INC. OUI:004094* ID_OUI_FROM_DATABASE=SHOGRAPHICS, INC. OUI:00407F* ID_OUI_FROM_DATABASE=FLIR Systems OUI:0040A9* ID_OUI_FROM_DATABASE=DATACOM INC. OUI:00C07D* ID_OUI_FROM_DATABASE=RISC DEVELOPMENTS LTD. OUI:00C01E* ID_OUI_FROM_DATABASE=LA FRANCAISE DES JEUX OUI:00C084* ID_OUI_FROM_DATABASE=DATA LINK CORP. LTD. OUI:00C087* ID_OUI_FROM_DATABASE=UUNET TECHNOLOGIES, INC. OUI:00C033* ID_OUI_FROM_DATABASE=TELEBIT COMMUNICATIONS APS OUI:00C081* ID_OUI_FROM_DATABASE=METRODATA LTD. OUI:00C006* ID_OUI_FROM_DATABASE=NIPPON AVIONICS CO., LTD. OUI:00C013* ID_OUI_FROM_DATABASE=NETRIX OUI:00C058* ID_OUI_FROM_DATABASE=DATAEXPERT CORP. OUI:0040E8* ID_OUI_FROM_DATABASE=CHARLES RIVER DATA SYSTEMS,INC OUI:004030* ID_OUI_FROM_DATABASE=GK COMPUTER OUI:0080DC* ID_OUI_FROM_DATABASE=PICKER INTERNATIONAL OUI:00C0A8* ID_OUI_FROM_DATABASE=GVC CORPORATION OUI:00C010* ID_OUI_FROM_DATABASE=HIRAKAWA HEWTECH CORP. OUI:00C020* ID_OUI_FROM_DATABASE=ARCO ELECTRONIC, CONTROL LTD. OUI:0040A6* ID_OUI_FROM_DATABASE=Cray, Inc. OUI:004098* ID_OUI_FROM_DATABASE=DRESSLER GMBH & CO. OUI:00C0B9* ID_OUI_FROM_DATABASE=FUNK SOFTWARE, INC. OUI:00C065* ID_OUI_FROM_DATABASE=SCOPE COMMUNICATIONS, INC. OUI:00C018* ID_OUI_FROM_DATABASE=LANART CORPORATION OUI:00C0FF* ID_OUI_FROM_DATABASE=DOT HILL SYSTEMS CORPORATION OUI:00400D* ID_OUI_FROM_DATABASE=LANNET DATA COMMUNICATIONS,LTD OUI:0040F5* ID_OUI_FROM_DATABASE=OEM ENGINES OUI:004019* ID_OUI_FROM_DATABASE=AEON SYSTEMS, INC. OUI:0040A1* ID_OUI_FROM_DATABASE=ERGO COMPUTING OUI:00407E* ID_OUI_FROM_DATABASE=EVERGREEN SYSTEMS, INC. OUI:0040F6* ID_OUI_FROM_DATABASE=KATRON COMPUTERS INC. OUI:004076* ID_OUI_FROM_DATABASE=Sun Conversion Technologies OUI:0040F4* ID_OUI_FROM_DATABASE=CAMEO COMMUNICATIONS, INC. OUI:00C06D* ID_OUI_FROM_DATABASE=BOCA RESEARCH, INC. OUI:00C0DB* ID_OUI_FROM_DATABASE=IPC CORPORATION (PTE) LTD. OUI:00C0DA* ID_OUI_FROM_DATABASE=NICE SYSTEMS LTD. OUI:00C09B* ID_OUI_FROM_DATABASE=RELIANCE COMM/TEC, R-TEC OUI:00C0B8* ID_OUI_FROM_DATABASE=FRASER'S HILL LTD. OUI:00C016* ID_OUI_FROM_DATABASE=ELECTRONIC THEATRE CONTROLS OUI:00C096* ID_OUI_FROM_DATABASE=TAMURA CORPORATION OUI:00C035* ID_OUI_FROM_DATABASE=QUINTAR COMPANY OUI:00C0CC* ID_OUI_FROM_DATABASE=TELESCIENCES CO SYSTEMS, INC. OUI:00C078* ID_OUI_FROM_DATABASE=COMPUTER SYSTEMS ENGINEERING OUI:0040F3* ID_OUI_FROM_DATABASE=NETCOR OUI:004033* ID_OUI_FROM_DATABASE=ADDTRON TECHNOLOGY CO., LTD. OUI:0040A3* ID_OUI_FROM_DATABASE=MICROUNITY SYSTEMS ENGINEERING OUI:0040ED* ID_OUI_FROM_DATABASE=NETWORK CONTROLS INT'NATL INC. OUI:0040AD* ID_OUI_FROM_DATABASE=SMA REGELSYSTEME GMBH OUI:0080D2* ID_OUI_FROM_DATABASE=SHINNIHONDENKO CO., LTD. OUI:0080DF* ID_OUI_FROM_DATABASE=ADC CODENOLL TECHNOLOGY CORP. OUI:008071* ID_OUI_FROM_DATABASE=SAI TECHNOLOGY OUI:00803D* ID_OUI_FROM_DATABASE=SURIGIKEN CO., LTD. OUI:00804B* ID_OUI_FROM_DATABASE=EAGLE TECHNOLOGIES PTY.LTD. OUI:008007* ID_OUI_FROM_DATABASE=DLOG NC-SYSTEME OUI:008001* ID_OUI_FROM_DATABASE=PERIPHONICS CORPORATION OUI:008062* ID_OUI_FROM_DATABASE=INTERFACE CO. OUI:0080F3* ID_OUI_FROM_DATABASE=SUN ELECTRONICS CORP. OUI:00808D* ID_OUI_FROM_DATABASE=WESTCOAST TECHNOLOGY B.V. OUI:0080B2* ID_OUI_FROM_DATABASE=NETWORK EQUIPMENT TECHNOLOGIES OUI:00805B* ID_OUI_FROM_DATABASE=CONDOR SYSTEMS, INC. OUI:00801C* ID_OUI_FROM_DATABASE=NEWPORT SYSTEMS SOLUTIONS OUI:0080C6* ID_OUI_FROM_DATABASE=NATIONAL DATACOMM CORPORATION OUI:0080FA* ID_OUI_FROM_DATABASE=RWT GMBH OUI:008084* ID_OUI_FROM_DATABASE=THE CLOUD INC. OUI:008046* ID_OUI_FROM_DATABASE=Tattile SRL OUI:0080A6* ID_OUI_FROM_DATABASE=REPUBLIC TECHNOLOGY, INC. OUI:008009* ID_OUI_FROM_DATABASE=JUPITER SYSTEMS, INC. OUI:0080B5* ID_OUI_FROM_DATABASE=UNITED NETWORKS INC. OUI:008035* ID_OUI_FROM_DATABASE=TECHNOLOGY WORKS, INC. OUI:008088* ID_OUI_FROM_DATABASE=VICTOR COMPANY OF JAPAN, LTD. OUI:00809E* ID_OUI_FROM_DATABASE=DATUS GMBH OUI:008055* ID_OUI_FROM_DATABASE=FERMILAB OUI:00802A* ID_OUI_FROM_DATABASE=TEST SYSTEMS & SIMULATIONS INC OUI:0040E3* ID_OUI_FROM_DATABASE=QUIN SYSTEMS LTD OUI:004091* ID_OUI_FROM_DATABASE=PROCOMP INDUSTRIA ELETRONICA OUI:004014* ID_OUI_FROM_DATABASE=COMSOFT GMBH OUI:00400F* ID_OUI_FROM_DATABASE=DATACOM TECHNOLOGIES OUI:004085* ID_OUI_FROM_DATABASE=SAAB INSTRUMENTS AB OUI:004006* ID_OUI_FROM_DATABASE=SAMPO TECHNOLOGY CORPORATION OUI:00402D* ID_OUI_FROM_DATABASE=HARRIS ADACOM CORPORATION OUI:004047* ID_OUI_FROM_DATABASE=WIND RIVER SYSTEMS OUI:0040FA* ID_OUI_FROM_DATABASE=MICROBOARDS, INC. OUI:00002E* ID_OUI_FROM_DATABASE=SOCIETE EVIRA OUI:0000ED* ID_OUI_FROM_DATABASE=APRIL OUI:00003C* ID_OUI_FROM_DATABASE=AUSPEX SYSTEMS INC. OUI:000051* ID_OUI_FROM_DATABASE=HOB ELECTRONIC GMBH & CO. KG OUI:0000A7* ID_OUI_FROM_DATABASE=NETWORK COMPUTING DEVICES INC. OUI:0000F7* ID_OUI_FROM_DATABASE=YOUTH KEEP ENTERPRISE CO LTD OUI:0000FC* ID_OUI_FROM_DATABASE=MEIKO OUI:0000B5* ID_OUI_FROM_DATABASE=DATABILITY SOFTWARE SYS. INC. OUI:000026* ID_OUI_FROM_DATABASE=SHA-KEN CO., LTD. OUI:000022* ID_OUI_FROM_DATABASE=VISUAL TECHNOLOGY INC. OUI:00006D* ID_OUI_FROM_DATABASE=CRAY COMMUNICATIONS, LTD. OUI:0000FA* ID_OUI_FROM_DATABASE=MICROSAGE COMPUTER SYSTEMS INC OUI:00002B* ID_OUI_FROM_DATABASE=CRISP AUTOMATION, INC OUI:000019* ID_OUI_FROM_DATABASE=APPLIED DYNAMICS INTERNATIONAL OUI:0080D3* ID_OUI_FROM_DATABASE=SHIVA CORP. OUI:0080A5* ID_OUI_FROM_DATABASE=SPEED INTERNATIONAL OUI:0080A9* ID_OUI_FROM_DATABASE=CLEARPOINT RESEARCH OUI:008069* ID_OUI_FROM_DATABASE=COMPUTONE SYSTEMS OUI:008091* ID_OUI_FROM_DATABASE=TOKYO ELECTRIC CO.,LTD OUI:0080F4* ID_OUI_FROM_DATABASE=TELEMECANIQUE ELECTRIQUE OUI:00800C* ID_OUI_FROM_DATABASE=VIDECOM LIMITED OUI:0080E8* ID_OUI_FROM_DATABASE=CUMULUS CORPORATIION OUI:0000CD* ID_OUI_FROM_DATABASE=Allied Telesis Labs Ltd OUI:0000A5* ID_OUI_FROM_DATABASE=Tattile SRL OUI:00801E* ID_OUI_FROM_DATABASE=XINETRON, INC. OUI:00804A* ID_OUI_FROM_DATABASE=PRO-LOG OUI:008059* ID_OUI_FROM_DATABASE=STANLEY ELECTRIC CO., LTD OUI:00806B* ID_OUI_FROM_DATABASE=SCHMID TELECOMMUNICATION OUI:00802C* ID_OUI_FROM_DATABASE=THE SAGE GROUP PLC OUI:008018* ID_OUI_FROM_DATABASE=KOBE STEEL, LTD. OUI:0080EE* ID_OUI_FROM_DATABASE=THOMSON CSF OUI:008013* ID_OUI_FROM_DATABASE=THOMAS-CONRAD CORPORATION OUI:00808E* ID_OUI_FROM_DATABASE=RADSTONE TECHNOLOGY OUI:000036* ID_OUI_FROM_DATABASE=ATARI CORPORATION OUI:0080BD* ID_OUI_FROM_DATABASE=THE FURUKAWA ELECTRIC CO., LTD OUI:0080A8* ID_OUI_FROM_DATABASE=VITACOM CORPORATION OUI:0080FB* ID_OUI_FROM_DATABASE=BVM LIMITED OUI:008042* ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies OUI:008067* ID_OUI_FROM_DATABASE=SQUARE D COMPANY OUI:008045* ID_OUI_FROM_DATABASE=MATSUSHITA ELECTRIC IND. CO OUI:00804C* ID_OUI_FROM_DATABASE=CONTEC CO., LTD. OUI:008020* ID_OUI_FROM_DATABASE=NETWORK PRODUCTS OUI:00809F* ID_OUI_FROM_DATABASE=ALE International OUI:004044* ID_OUI_FROM_DATABASE=QNIX COMPUTER CO., LTD. OUI:0040DD* ID_OUI_FROM_DATABASE=HONG TECHNOLOGIES OUI:00403A* ID_OUI_FROM_DATABASE=IMPACT TECHNOLOGIES OUI:0040C9* ID_OUI_FROM_DATABASE=NCUBE OUI:004075* ID_OUI_FROM_DATABASE=Tattile SRL OUI:0080F1* ID_OUI_FROM_DATABASE=OPUS SYSTEMS OUI:08008F* ID_OUI_FROM_DATABASE=CHIPCOM CORPORATION OUI:080081* ID_OUI_FROM_DATABASE=ASTECH INC. OUI:08007A* ID_OUI_FROM_DATABASE=INDATA OUI:080078* ID_OUI_FROM_DATABASE=ACCELL CORPORATION OUI:08006E* ID_OUI_FROM_DATABASE=MASSCOMP OUI:08006D* ID_OUI_FROM_DATABASE=WHITECHAPEL COMPUTER WORKS OUI:08006C* ID_OUI_FROM_DATABASE=SUNTEK TECHNOLOGY INT'L OUI:080067* ID_OUI_FROM_DATABASE=ComDesign OUI:080063* ID_OUI_FROM_DATABASE=PLESSEY OUI:080060* ID_OUI_FROM_DATABASE=INDUSTRIAL NETWORKING INC. OUI:000081* ID_OUI_FROM_DATABASE=Bay Networks OUI:0000A1* ID_OUI_FROM_DATABASE=MARQUETTE ELECTRIC CO. OUI:0000F5* ID_OUI_FROM_DATABASE=DIAMOND SALES LIMITED OUI:0000E5* ID_OUI_FROM_DATABASE=SIGMEX LTD. OUI:0000BA* ID_OUI_FROM_DATABASE=SIIG, INC. OUI:00002F* ID_OUI_FROM_DATABASE=TIMEPLEX INC. OUI:0000B8* ID_OUI_FROM_DATABASE=SEIKOSHA CO., LTD. OUI:00007F* ID_OUI_FROM_DATABASE=LINOTYPE-HELL AG OUI:0000B7* ID_OUI_FROM_DATABASE=DOVE COMPUTER CORPORATION OUI:00009A* ID_OUI_FROM_DATABASE=RC COMPUTER A/S OUI:0000DE* ID_OUI_FROM_DATABASE=CETIA OUI:00004B* ID_OUI_FROM_DATABASE=ICL DATA OY OUI:000013* ID_OUI_FROM_DATABASE=CAMEX OUI:000095* ID_OUI_FROM_DATABASE=SONY TEKTRONIX CORP. OUI:080037* ID_OUI_FROM_DATABASE=FUJI-XEROX CO. LTD. OUI:080031* ID_OUI_FROM_DATABASE=LITTLE MACHINES INC. OUI:08002B* ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION OUI:08002A* ID_OUI_FROM_DATABASE=MOSAIC TECHNOLOGIES INC. OUI:080029* ID_OUI_FROM_DATABASE=Megatek Corporation OUI:080026* ID_OUI_FROM_DATABASE=NORSK DATA A.S. OUI:08001F* ID_OUI_FROM_DATABASE=SHARP CORPORATION OUI:0000AE* ID_OUI_FROM_DATABASE=DASSAULT ELECTRONIQUE OUI:0000DD* ID_OUI_FROM_DATABASE=TCL INCORPORATED OUI:0000D9* ID_OUI_FROM_DATABASE=NIPPON TELEGRAPH & TELEPHONE OUI:000046* ID_OUI_FROM_DATABASE=OLIVETTI NORTH AMERICA OUI:000017* ID_OUI_FROM_DATABASE=Oracle OUI:00009F* ID_OUI_FROM_DATABASE=AMERISTAR TECHNOLOGIES INC. OUI:0000E3* ID_OUI_FROM_DATABASE=INTEGRATED MICRO PRODUCTS LTD OUI:000073* ID_OUI_FROM_DATABASE=SIECOR CORPORATION OUI:0000D3* ID_OUI_FROM_DATABASE=WANG LABORATORIES INC. OUI:0000B3* ID_OUI_FROM_DATABASE=CIMLINC INCORPORATED OUI:00009D* ID_OUI_FROM_DATABASE=LOCUS COMPUTING CORPORATION OUI:000060* ID_OUI_FROM_DATABASE=KONTRON ELEKTRONIK GMBH OUI:000011* ID_OUI_FROM_DATABASE=NORMEREL SYSTEMES OUI:08006F* ID_OUI_FROM_DATABASE=PHILIPS APELDOORN B.V. OUI:0000B0* ID_OUI_FROM_DATABASE=RND-RAD NETWORK DEVICES OUI:00001B* ID_OUI_FROM_DATABASE=NOVELL INC. OUI:000071* ID_OUI_FROM_DATABASE=ADRA SYSTEMS INC. OUI:00006C* ID_OUI_FROM_DATABASE=Private OUI:AA0000* ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION OUI:0270B0* ID_OUI_FROM_DATABASE=M/A-COM INC. COMPANIES OUI:00000B* ID_OUI_FROM_DATABASE=MATRIX CORPORATION OUI:080042* ID_OUI_FROM_DATABASE=JAPAN MACNICS CORP. OUI:026086* ID_OUI_FROM_DATABASE=LOGIC REPLACEMENT TECH. LTD. OUI:00DD05* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:00DD0A* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:00BBF0* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:0080E9* ID_OUI_FROM_DATABASE=Madge Ltd. OUI:080055* ID_OUI_FROM_DATABASE=STANFORD TELECOMM. INC. OUI:080048* ID_OUI_FROM_DATABASE=EUROTHERM GAUGING SYSTEMS OUI:080049* ID_OUI_FROM_DATABASE=UNIVATION OUI:00DD02* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:000003* ID_OUI_FROM_DATABASE=XEROX CORPORATION OUI:000008* ID_OUI_FROM_DATABASE=XEROX CORPORATION OUI:080030* ID_OUI_FROM_DATABASE=CERN OUI:00DD01* ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. OUI:18017D* ID_OUI_FROM_DATABASE=Harbin Arteor technology co., LTD OUI:001CDF* ID_OUI_FROM_DATABASE=Belkin International Inc. OUI:944452* ID_OUI_FROM_DATABASE=Belkin International Inc. OUI:08863B* ID_OUI_FROM_DATABASE=Belkin International Inc. OUI:2082C0* ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd OUI:001556* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:002569* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:001BBF* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:4C17EB* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:7C034C* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS OUI:88AE1D* ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. OUI:5C353B* ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc. OUI:C8F230* ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD OUI:1C4419* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:005079* ID_OUI_FROM_DATABASE=Private OUI:9C93E4* ID_OUI_FROM_DATABASE=Private OUI:B0D5CC* ID_OUI_FROM_DATABASE=Texas Instruments OUI:5CF821* ID_OUI_FROM_DATABASE=Texas Instruments OUI:749DDC* ID_OUI_FROM_DATABASE=2Wire Inc OUI:782BCB* ID_OUI_FROM_DATABASE=Dell Inc. OUI:B8CA3A* ID_OUI_FROM_DATABASE=Dell Inc. OUI:F01FAF* ID_OUI_FROM_DATABASE=Dell Inc. OUI:C81F66* ID_OUI_FROM_DATABASE=Dell Inc. OUI:00183F* ID_OUI_FROM_DATABASE=2Wire Inc OUI:0019E4* ID_OUI_FROM_DATABASE=2Wire Inc OUI:001AC4* ID_OUI_FROM_DATABASE=2Wire Inc OUI:001D5A* ID_OUI_FROM_DATABASE=2Wire Inc OUI:34EF44* ID_OUI_FROM_DATABASE=2Wire Inc OUI:982CBE* ID_OUI_FROM_DATABASE=2Wire Inc OUI:001422* ID_OUI_FROM_DATABASE=Dell Inc. OUI:001C23* ID_OUI_FROM_DATABASE=Dell Inc. OUI:00219B* ID_OUI_FROM_DATABASE=Dell Inc. OUI:000874* ID_OUI_FROM_DATABASE=Dell Inc. OUI:002564* ID_OUI_FROM_DATABASE=Dell Inc. OUI:842B2B* ID_OUI_FROM_DATABASE=Dell Inc. OUI:E0DB55* ID_OUI_FROM_DATABASE=Dell Inc. OUI:A41F72* ID_OUI_FROM_DATABASE=Dell Inc. OUI:00C04F* ID_OUI_FROM_DATABASE=Dell Inc. OUI:F04DA2* ID_OUI_FROM_DATABASE=Dell Inc. OUI:BC305B* ID_OUI_FROM_DATABASE=Dell Inc. OUI:001D09* ID_OUI_FROM_DATABASE=Dell Inc. OUI:F8E079* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:1430C6* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:044E06* ID_OUI_FROM_DATABASE=Ericsson AB OUI:000D67* ID_OUI_FROM_DATABASE=Ericsson OUI:E0757D* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company OUI:001E65* ID_OUI_FROM_DATABASE=Intel Corporate OUI:001F3B* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0016EA* ID_OUI_FROM_DATABASE=Intel Corporate OUI:00216B* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0019D1* ID_OUI_FROM_DATABASE=Intel Corporate OUI:001CC0* ID_OUI_FROM_DATABASE=Intel Corporate OUI:5CE0C5* ID_OUI_FROM_DATABASE=Intel Corporate OUI:183DA2* ID_OUI_FROM_DATABASE=Intel Corporate OUI:448500* ID_OUI_FROM_DATABASE=Intel Corporate OUI:809B20* ID_OUI_FROM_DATABASE=Intel Corporate OUI:100BA9* ID_OUI_FROM_DATABASE=Intel Corporate OUI:247703* ID_OUI_FROM_DATABASE=Intel Corporate OUI:C48508* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0026C6* ID_OUI_FROM_DATABASE=Intel Corporate OUI:74E50B* ID_OUI_FROM_DATABASE=Intel Corporate OUI:58946B* ID_OUI_FROM_DATABASE=Intel Corporate OUI:002710* ID_OUI_FROM_DATABASE=Intel Corporate OUI:64D4DA* ID_OUI_FROM_DATABASE=Intel Corporate OUI:DCA971* ID_OUI_FROM_DATABASE=Intel Corporate OUI:001CBF* ID_OUI_FROM_DATABASE=Intel Corporate OUI:A0A8CD* ID_OUI_FROM_DATABASE=Intel Corporate OUI:340286* ID_OUI_FROM_DATABASE=Intel Corporate OUI:34DE1A* ID_OUI_FROM_DATABASE=Intel Corporate OUI:80000B* ID_OUI_FROM_DATABASE=Intel Corporate OUI:B80305* ID_OUI_FROM_DATABASE=Intel Corporate OUI:303A64* ID_OUI_FROM_DATABASE=Intel Corporate OUI:ACFDCE* ID_OUI_FROM_DATABASE=Intel Corporate OUI:E09467* ID_OUI_FROM_DATABASE=Intel Corporate OUI:00DBDF* ID_OUI_FROM_DATABASE=Intel Corporate OUI:0C8BFD* ID_OUI_FROM_DATABASE=Intel Corporate OUI:E09D31* ID_OUI_FROM_DATABASE=Intel Corporate OUI:CC3D82* ID_OUI_FROM_DATABASE=Intel Corporate OUI:D00ED9* ID_OUI_FROM_DATABASE=Taicang T&W Electronics OUI:6C2995* ID_OUI_FROM_DATABASE=Intel Corporate OUI:40E3D6* ID_OUI_FROM_DATABASE=Aruba Networks OUI:24DEC6* ID_OUI_FROM_DATABASE=Aruba Networks OUI:D8C7C8* ID_OUI_FROM_DATABASE=Aruba Networks OUI:18E3BC* ID_OUI_FROM_DATABASE=TCT mobile ltd OUI:900BC1* ID_OUI_FROM_DATABASE=Sprocomm Technologies CO.,Ltd OUI:6C71D9* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:384FF0* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:0015AF* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:485D60* ID_OUI_FROM_DATABASE=AzureWave Technology Inc. OUI:54E4BD* ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED OUI:98743D* ID_OUI_FROM_DATABASE=Shenzhen Jun Kai Hengye Technology Co. Ltd OUI:A04FD4* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:842615* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:5CE2F4* ID_OUI_FROM_DATABASE=AcSiP Technology Corp. OUI:002662* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:00193E* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:0013C8* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:DC0B1A* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:74888B* ID_OUI_FROM_DATABASE=ADB Broadband Italia OUI:8841FC* ID_OUI_FROM_DATABASE=AirTies Wireless Netowrks OUI:182861* ID_OUI_FROM_DATABASE=AirTies Wireless Netowrks OUI:84D6D0* ID_OUI_FROM_DATABASE=Amazon Technologies Inc. OUI:E0CB1D* ID_OUI_FROM_DATABASE=Private OUI:ACD074* ID_OUI_FROM_DATABASE=Espressif Inc. OUI:D05349* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:00BB3A* ID_OUI_FROM_DATABASE=Private OUI:000941* ID_OUI_FROM_DATABASE=Allied Telesis R&D Center K.K. OUI:984B4A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:00014A* ID_OUI_FROM_DATABASE=Sony Corporation OUI:001CA4* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:002345* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:8C6422* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:90C115* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:8400D2* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:5CB524* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:0015A3* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0015A4* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:94A1A2* ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. OUI:00D088* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0017EE* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001180* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:00909C* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:8096B1* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:7CBFB1* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001A77* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:CC7D37* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0017E2* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001784* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0016B5* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001675* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:74DE2B* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:68A3C4* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:002210* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001FC4* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001C12* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001CFB* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0012C9* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:E48399* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:00211E* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0024A0* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:002636* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:C8FF28* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:0024D2* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:DC64B8* ID_OUI_FROM_DATABASE=Shenzhen JingHanDa Electronics Co.Ltd OUI:C4DA7D* ID_OUI_FROM_DATABASE=Ivium Technologies B.V. OUI:9492BC* ID_OUI_FROM_DATABASE=SYNTECH(HK) TECHNOLOGY LIMITED OUI:001A4F* ID_OUI_FROM_DATABASE=AVM GmbH OUI:00040E* ID_OUI_FROM_DATABASE=AVM GmbH OUI:0016E3* ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP OUI:30469A* ID_OUI_FROM_DATABASE=NETGEAR OUI:0026F2* ID_OUI_FROM_DATABASE=NETGEAR OUI:00184D* ID_OUI_FROM_DATABASE=NETGEAR OUI:001E2A* ID_OUI_FROM_DATABASE=NETGEAR OUI:E8FCAF* ID_OUI_FROM_DATABASE=NETGEAR OUI:4C60DE* ID_OUI_FROM_DATABASE=NETGEAR OUI:00300A* ID_OUI_FROM_DATABASE=Aztech Electronics Pte Ltd OUI:A06391* ID_OUI_FROM_DATABASE=NETGEAR OUI:9CC7A6* ID_OUI_FROM_DATABASE=AVM GmbH OUI:DCEF09* ID_OUI_FROM_DATABASE=NETGEAR OUI:743170* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:A8D3F7* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:7C4FB5* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:0012BF* ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation OUI:200CC8* ID_OUI_FROM_DATABASE=NETGEAR OUI:04FE8D* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:480031* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:0019FB* ID_OUI_FROM_DATABASE=BSkyB Ltd OUI:0CF9C0* ID_OUI_FROM_DATABASE=BSkyB Ltd OUI:001BA9* ID_OUI_FROM_DATABASE=Brother industries, LTD. OUI:0011B6* ID_OUI_FROM_DATABASE=Open Systems International OUI:E03E44* ID_OUI_FROM_DATABASE=Broadcom OUI:D40129* ID_OUI_FROM_DATABASE=Broadcom OUI:FCB698* ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. OUI:00E03A* ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. OUI:000117* ID_OUI_FROM_DATABASE=Canal + OUI:0019C7* ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. OUI:006DFB* ID_OUI_FROM_DATABASE=Vutrix Technologies Ltd OUI:C81073* ID_OUI_FROM_DATABASE=CENTURY OPTICOMM CO.,LTD OUI:744AA4* ID_OUI_FROM_DATABASE=zte corporation OUI:9CD35B* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:60AF6D* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B85A73* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:103047* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:109266* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:B047BF* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:7C0BC6* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:804E81* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:244B81* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:50A4C8* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:8425DB* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:D8C4E9* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:50C8E5* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:446D6C* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:38D40B* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:647791* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:781FDB* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:08FC88* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:30C7AE* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:18227E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:00F46F* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:BC1485* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:9CE6E7* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:380195* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:5CF6DC* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:1077B1* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:508569* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:0090A2* ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. OUI:0030DA* ID_OUI_FROM_DATABASE=Comtrend Corporation OUI:64680C* ID_OUI_FROM_DATABASE=Comtrend Corporation OUI:00CF1C* ID_OUI_FROM_DATABASE=Communication Machinery Corporation OUI:0090F5* ID_OUI_FROM_DATABASE=CLEVO CO. OUI:0030FF* ID_OUI_FROM_DATABASE=DataFab Systems Inc. OUI:E498D1* ID_OUI_FROM_DATABASE=Microsoft Mobile Oy OUI:A8A089* ID_OUI_FROM_DATABASE=Tactical Communications OUI:48365F* ID_OUI_FROM_DATABASE=Wintecronics Ltd. OUI:005A39* ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD OUI:5CC6D0* ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd OUI:080581* ID_OUI_FROM_DATABASE=Roku, Inc. OUI:B0A737* ID_OUI_FROM_DATABASE=Roku, Inc. OUI:B83E59* ID_OUI_FROM_DATABASE=Roku, Inc. OUI:DC3A5E* ID_OUI_FROM_DATABASE=Roku, Inc. OUI:0014A5* ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. OUI:001742* ID_OUI_FROM_DATABASE=FUJITSU LIMITED OUI:2C10C1* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:CCFB65* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:40D28A* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:7CBB8A* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:00224C* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:0023CC* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:002444* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:E0E751* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:0017AB* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:001BEA* ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. OUI:48F7C0* ID_OUI_FROM_DATABASE=Cisco SPVTG OUI:0015DE* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001FDF* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:00194F* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:00188D* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:00180F* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:547975* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:2CCC15* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:00BD3A* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:A04E04* ID_OUI_FROM_DATABASE=Nokia Corporation OUI:001370* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:00247C* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0023B4* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001F5C* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001F00* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:00164E* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0016BC* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001ADC* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:002668* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0021AB* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:001E3B* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:0026CC* ID_OUI_FROM_DATABASE=Nokia Danmark A/S OUI:240B0A* ID_OUI_FROM_DATABASE=Palo Alto Networks OUI:C4E510* ID_OUI_FROM_DATABASE=Mechatro, Inc. OUI:74C330* ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD OUI:403F8C* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:14C3C2* ID_OUI_FROM_DATABASE=K.A. Schmersal GmbH & Co. KG OUI:10785B* ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc OUI:20768F* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:C0C522* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:9C5CF9* ID_OUI_FROM_DATABASE=Sony Mobile Communications AB OUI:88A084* ID_OUI_FROM_DATABASE=Formation Data Systems OUI:0025DC* ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd OUI:001CFC* ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd OUI:00D0EC* ID_OUI_FROM_DATABASE=NAKAYO TELECOMMUNICATIONS,INC OUI:8CC661* ID_OUI_FROM_DATABASE=Current, powered by GE OUI:009050* ID_OUI_FROM_DATABASE=Teleste Corporation OUI:BC44B0* ID_OUI_FROM_DATABASE=Elastifile OUI:7864E6* ID_OUI_FROM_DATABASE=Green Motive Technology Limited OUI:743E2B* ID_OUI_FROM_DATABASE=Ruckus Wireless OUI:C0CCF8* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:80ED2C* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:E8B2AC* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:FCF152* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:0080B8* ID_OUI_FROM_DATABASE=DMG MORI B.U.G. CO., LTD. OUI:8489AD* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:40B688* ID_OUI_FROM_DATABASE=LEGIC Identsystems AG OUI:A09D91* ID_OUI_FROM_DATABASE=SoundBridge OUI:30785C* ID_OUI_FROM_DATABASE=Partow Tamas Novin (Parman) OUI:0C54B9* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:C4084A* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:34AA99* ID_OUI_FROM_DATABASE=Alcatel-Lucent OUI:441102* ID_OUI_FROM_DATABASE=EDMI Europe Ltd OUI:2C21D7* ID_OUI_FROM_DATABASE=IMAX Corporation OUI:0026F7* ID_OUI_FROM_DATABASE=Nivetti Systems Pvt. Ltd. OUI:24C3F9* ID_OUI_FROM_DATABASE=Securitas Direct AB OUI:DC4D23* ID_OUI_FROM_DATABASE=MRV Comunications OUI:085BDA* ID_OUI_FROM_DATABASE=CliniCare LTD OUI:00248D* ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc. OUI:0C5A9E* ID_OUI_FROM_DATABASE=Wi-SUN Alliance OUI:00C164* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:10D0AB* ID_OUI_FROM_DATABASE=zte corporation OUI:C4BED4* ID_OUI_FROM_DATABASE=Avaya Inc OUI:98E7F5* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:24BCF8* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:042DB4* ID_OUI_FROM_DATABASE=First Property (Beijing) Co., Ltd Modern MOMA Branch OUI:202DF8* ID_OUI_FROM_DATABASE=Digital Media Cartridge Ltd. OUI:008A96* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:007888* ID_OUI_FROM_DATABASE=Cisco Systems, Inc OUI:98DED0* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:30FC68* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. OUI:5CCA1A* ID_OUI_FROM_DATABASE=Microsoft Mobile Oy OUI:000594* ID_OUI_FROM_DATABASE=HMS Industrial Networks OUI:000AC2* ID_OUI_FROM_DATABASE=Wuhan FiberHome Digital Technology Co.,Ltd. OUI:F08CFB* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:FCF8B7* ID_OUI_FROM_DATABASE=TRONTEQ Electronic OUI:D4F207* ID_OUI_FROM_DATABASE=DIAODIAO(Beijing)Technology CO.,Ltd OUI:D4883F* ID_OUI_FROM_DATABASE=HDPRO CO., LTD. OUI:FC0F4B* ID_OUI_FROM_DATABASE=Texas Instruments OUI:A86AC1* ID_OUI_FROM_DATABASE=HanbitEDS Co., Ltd. OUI:40163B* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:001BF3* ID_OUI_FROM_DATABASE=TRANSRADIO SenderSysteme Berlin AG OUI:E0071B* ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise OUI:88B1E1* ID_OUI_FROM_DATABASE=Mojo Networks, Inc. OUI:74DFBF* ID_OUI_FROM_DATABASE=Liteon Technology Corporation OUI:FC3F7C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:608334* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:84AD58* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:746FF7* ID_OUI_FROM_DATABASE=Wistron Neweb Corporation OUI:B01BD2* ID_OUI_FROM_DATABASE=Le Shi Zhi Xin Electronic Technology (Tianjin) Limited OUI:386077* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:74852A* ID_OUI_FROM_DATABASE=PEGATRON CORPORATION OUI:60B4F7* ID_OUI_FROM_DATABASE=Plume Design Inc OUI:A4D8CA* ID_OUI_FROM_DATABASE=HONG KONG WATER WORLD TECHNOLOGY CO. LIMITED OUI:ECA86B* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:4487FC* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:002197* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:649968* ID_OUI_FROM_DATABASE=Elentec OUI:00109B* ID_OUI_FROM_DATABASE=Emulex Corporation OUI:00E0D5* ID_OUI_FROM_DATABASE=Emulex Corporation OUI:001035* ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. OUI:9CDF03* ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH OUI:00208F* ID_OUI_FROM_DATABASE=ECI Telecom Ltd. OUI:F0407B* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD OUI:94885E* ID_OUI_FROM_DATABASE=Surfilter Network Technology Co., Ltd. OUI:002378* ID_OUI_FROM_DATABASE=GN Netcom A/S OUI:002088* ID_OUI_FROM_DATABASE=GLOBAL VILLAGE COMMUNICATION OUI:BC6A44* ID_OUI_FROM_DATABASE=Commend International GmbH OUI:90C7D8* ID_OUI_FROM_DATABASE=zte corporation OUI:F8DA0C* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:0020F2* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:00015D* ID_OUI_FROM_DATABASE=Oracle Corporation OUI:943BB1* ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD. OUI:146308* ID_OUI_FROM_DATABASE=JABIL CIRCUIT (SHANGHAI) LTD. OUI:08000D* ID_OUI_FROM_DATABASE=International Computers, Ltd OUI:00D0A2* ID_OUI_FROM_DATABASE=INTEGRATED DEVICE OUI:0060B1* ID_OUI_FROM_DATABASE=Input/Output, Inc. OUI:00177D* ID_OUI_FROM_DATABASE=IDT Technology Limited OUI:AC4BC8* ID_OUI_FROM_DATABASE=Juniper Networks OUI:B0A86E* ID_OUI_FROM_DATABASE=Juniper Networks OUI:3C94D5* ID_OUI_FROM_DATABASE=Juniper Networks OUI:288A1C* ID_OUI_FROM_DATABASE=Juniper Networks OUI:100E7E* ID_OUI_FROM_DATABASE=Juniper Networks OUI:84B59C* ID_OUI_FROM_DATABASE=Juniper Networks OUI:544B8C* ID_OUI_FROM_DATABASE=Juniper Networks OUI:541E56* ID_OUI_FROM_DATABASE=Juniper Networks OUI:64649B* ID_OUI_FROM_DATABASE=Juniper Networks OUI:2C6BF5* ID_OUI_FROM_DATABASE=Juniper Networks OUI:002283* ID_OUI_FROM_DATABASE=Juniper Networks OUI:F4CC55* ID_OUI_FROM_DATABASE=Juniper Networks OUI:EC13DB* ID_OUI_FROM_DATABASE=Juniper Networks OUI:002159* ID_OUI_FROM_DATABASE=Juniper Networks OUI:5C70A3* ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) OUI:3497F6* ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:50680A* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD systemd-229/hwdb/20-acpi-vendor.hwdb000066400000000000000000003672041265713322000173150ustar00rootroot00000000000000# This file is part of systemd. # # Data imported from: # http://download.microsoft.com/download/7/E/7/7E7662CF-CBEA-470B-A97E-CE7CE0D98DC2/ISA_PNPID_List.xlsx # Non-unique, duplicate assignements manually removed. acpi:AAA*: ID_VENDOR_FROM_DATABASE=Avolites Ltd acpi:AAE*: ID_VENDOR_FROM_DATABASE=Anatek Electronics Inc. acpi:AAT*: ID_VENDOR_FROM_DATABASE=Ann Arbor Technologies acpi:ABA*: ID_VENDOR_FROM_DATABASE=ABBAHOME INC. acpi:ABC*: ID_VENDOR_FROM_DATABASE=AboCom System Inc acpi:ABD*: ID_VENDOR_FROM_DATABASE=Allen Bradley Company acpi:ABE*: ID_VENDOR_FROM_DATABASE=Alcatel Bell acpi:ABO*: ID_VENDOR_FROM_DATABASE=D-Link Systems Inc acpi:ABT*: ID_VENDOR_FROM_DATABASE=Anchor Bay Technologies, Inc. acpi:ABV*: ID_VENDOR_FROM_DATABASE=Advanced Research Technology acpi:ACA*: ID_VENDOR_FROM_DATABASE=Ariel Corporation acpi:ACB*: ID_VENDOR_FROM_DATABASE=Aculab Ltd acpi:ACC*: ID_VENDOR_FROM_DATABASE=Accton Technology Corporation acpi:ACD*: ID_VENDOR_FROM_DATABASE=AWETA BV acpi:ACE*: ID_VENDOR_FROM_DATABASE=Actek Engineering Pty Ltd acpi:ACG*: ID_VENDOR_FROM_DATABASE=A&R Cambridge Ltd acpi:ACH*: ID_VENDOR_FROM_DATABASE=Archtek Telecom Corporation acpi:ACI*: ID_VENDOR_FROM_DATABASE=Ancor Communications Inc acpi:ACK*: ID_VENDOR_FROM_DATABASE=Acksys acpi:ACL*: ID_VENDOR_FROM_DATABASE=Apricot Computers acpi:ACM*: ID_VENDOR_FROM_DATABASE=Acroloop Motion Control Systems Inc acpi:ACO*: ID_VENDOR_FROM_DATABASE=Allion Computer Inc. acpi:ACP[0-9A-F]*: ID_VENDOR_FROM_DATABASE=Aspen Tech Inc acpi:ACR*: ID_VENDOR_FROM_DATABASE=Acer Technologies acpi:ACS*: ID_VENDOR_FROM_DATABASE=Altos Computer Systems acpi:ACT*: ID_VENDOR_FROM_DATABASE=Applied Creative Technology acpi:ACU*: ID_VENDOR_FROM_DATABASE=Acculogic acpi:ACV*: ID_VENDOR_FROM_DATABASE=ActivCard S.A acpi:ADA*: ID_VENDOR_FROM_DATABASE=Addi-Data GmbH acpi:ADB*: ID_VENDOR_FROM_DATABASE=Aldebbaron acpi:ADC*: ID_VENDOR_FROM_DATABASE=Acnhor Datacomm acpi:ADD*: ID_VENDOR_FROM_DATABASE=Advanced Peripheral Devices Inc acpi:ADE*: ID_VENDOR_FROM_DATABASE=Arithmos, Inc. acpi:ADH*: ID_VENDOR_FROM_DATABASE=Aerodata Holdings Ltd acpi:ADI*: ID_VENDOR_FROM_DATABASE=ADI Systems Inc acpi:ADK*: ID_VENDOR_FROM_DATABASE=Adtek System Science Company Ltd acpi:ADL*: ID_VENDOR_FROM_DATABASE=ASTRA Security Products Ltd acpi:ADM*: ID_VENDOR_FROM_DATABASE=Ad Lib MultiMedia Inc acpi:ADN*: ID_VENDOR_FROM_DATABASE=Analog & Digital Devices Tel. Inc acpi:ADP*: ID_VENDOR_FROM_DATABASE=Adaptec Inc acpi:ADR*: ID_VENDOR_FROM_DATABASE=Nasa Ames Research Center acpi:ADS*: ID_VENDOR_FROM_DATABASE=Analog Devices Inc acpi:ADT*: ID_VENDOR_FROM_DATABASE=Aved Display Technologies acpi:ADV*: ID_VENDOR_FROM_DATABASE=Advanced Micro Devices Inc acpi:ADX*: ID_VENDOR_FROM_DATABASE=Adax Inc acpi:AEC*: ID_VENDOR_FROM_DATABASE=Antex Electronics Corporation acpi:AED*: ID_VENDOR_FROM_DATABASE=Advanced Electronic Designs, Inc. acpi:AEI*: ID_VENDOR_FROM_DATABASE=Actiontec Electric Inc acpi:AEJ*: ID_VENDOR_FROM_DATABASE=Alpha Electronics Company acpi:AEM*: ID_VENDOR_FROM_DATABASE=ASEM S.p.A. acpi:AEN*: ID_VENDOR_FROM_DATABASE=Avencall acpi:AEP*: ID_VENDOR_FROM_DATABASE=Aetas Peripheral International acpi:AET*: ID_VENDOR_FROM_DATABASE=Aethra Telecomunicazioni S.r.l. acpi:AFA*: ID_VENDOR_FROM_DATABASE=Alfa Inc acpi:AGC*: ID_VENDOR_FROM_DATABASE=Beijing Aerospace Golden Card Electronic Engineering Co.,Ltd. acpi:AGI*: ID_VENDOR_FROM_DATABASE=Artish Graphics Inc acpi:AGL*: ID_VENDOR_FROM_DATABASE=Argolis acpi:AGM*: ID_VENDOR_FROM_DATABASE=Advan Int'l Corporation acpi:AGT*: ID_VENDOR_FROM_DATABASE=Agilent Technologies acpi:AHC*: ID_VENDOR_FROM_DATABASE=Advantech Co., Ltd. acpi:AIC*: ID_VENDOR_FROM_DATABASE=Arnos Insturments & Computer Systems acpi:AIE*: ID_VENDOR_FROM_DATABASE=Altmann Industrieelektronik acpi:AII*: ID_VENDOR_FROM_DATABASE=Amptron International Inc. acpi:AIL*: ID_VENDOR_FROM_DATABASE=Altos India Ltd acpi:AIM*: ID_VENDOR_FROM_DATABASE=AIMS Lab Inc acpi:AIR*: ID_VENDOR_FROM_DATABASE=Advanced Integ. Research Inc acpi:AIS*: ID_VENDOR_FROM_DATABASE=Alien Internet Services acpi:AIW*: ID_VENDOR_FROM_DATABASE=Aiwa Company Ltd acpi:AIX*: ID_VENDOR_FROM_DATABASE=ALTINEX, INC. acpi:AJA*: ID_VENDOR_FROM_DATABASE=AJA Video Systems, Inc. acpi:AKB*: ID_VENDOR_FROM_DATABASE=Akebia Ltd acpi:AKE*: ID_VENDOR_FROM_DATABASE=AKAMI Electric Co.,Ltd acpi:AKI*: ID_VENDOR_FROM_DATABASE=AKIA Corporation acpi:AKL*: ID_VENDOR_FROM_DATABASE=AMiT Ltd acpi:AKM*: ID_VENDOR_FROM_DATABASE=Asahi Kasei Microsystems Company Ltd acpi:AKP*: ID_VENDOR_FROM_DATABASE=Atom Komplex Prylad acpi:AKY*: ID_VENDOR_FROM_DATABASE=Askey Computer Corporation acpi:ALA*: ID_VENDOR_FROM_DATABASE=Alacron Inc acpi:ALC*: ID_VENDOR_FROM_DATABASE=Altec Corporation acpi:ALD*: ID_VENDOR_FROM_DATABASE=In4S Inc acpi:ALG*: ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Corp. acpi:ALH*: ID_VENDOR_FROM_DATABASE=AL Systems acpi:ALI*: ID_VENDOR_FROM_DATABASE=Acer Labs acpi:ALJ*: ID_VENDOR_FROM_DATABASE=Altec Lansing acpi:ALK*: ID_VENDOR_FROM_DATABASE=Acrolink Inc acpi:ALL*: ID_VENDOR_FROM_DATABASE=Alliance Semiconductor Corporation acpi:ALM*: ID_VENDOR_FROM_DATABASE=Acutec Ltd. acpi:ALN*: ID_VENDOR_FROM_DATABASE=Alana Technologies acpi:ALO*: ID_VENDOR_FROM_DATABASE=Algolith Inc. acpi:ALP*: ID_VENDOR_FROM_DATABASE=Alps Electric Company Ltd acpi:ALR*: ID_VENDOR_FROM_DATABASE=Advanced Logic acpi:ALS*: ID_VENDOR_FROM_DATABASE=Avance Logic Inc acpi:ALT*: ID_VENDOR_FROM_DATABASE=Altra acpi:ALV*: ID_VENDOR_FROM_DATABASE=AlphaView LCD acpi:ALX*: ID_VENDOR_FROM_DATABASE=ALEXON Co.,Ltd. acpi:AMA*: ID_VENDOR_FROM_DATABASE=Asia Microelectronic Development Inc acpi:AMB*: ID_VENDOR_FROM_DATABASE=Ambient Technologies, Inc. acpi:AMC*: ID_VENDOR_FROM_DATABASE=Attachmate Corporation acpi:AMD*: ID_VENDOR_FROM_DATABASE=Amdek Corporation acpi:AMI*: ID_VENDOR_FROM_DATABASE=American Megatrends Inc acpi:AML*: ID_VENDOR_FROM_DATABASE=Anderson Multimedia Communications (HK) Limited acpi:AMN*: ID_VENDOR_FROM_DATABASE=Amimon LTD. acpi:AMO*: ID_VENDOR_FROM_DATABASE=Amino Technologies PLC and Amino Communications Limited acpi:AMP*: ID_VENDOR_FROM_DATABASE=AMP Inc acpi:AMS *: ID_VENDOR_FROM_DATABASE=ARMSTEL, Inc. acpi:AMT*: ID_VENDOR_FROM_DATABASE=AMT International Industry acpi:AMX*: ID_VENDOR_FROM_DATABASE=AMX LLC acpi:ANA*: ID_VENDOR_FROM_DATABASE=Anakron acpi:ANC*: ID_VENDOR_FROM_DATABASE=Ancot acpi:AND*: ID_VENDOR_FROM_DATABASE=Adtran Inc acpi:ANI*: ID_VENDOR_FROM_DATABASE=Anigma Inc acpi:ANK*: ID_VENDOR_FROM_DATABASE=Anko Electronic Company Ltd acpi:ANL*: ID_VENDOR_FROM_DATABASE=Analogix Semiconductor, Inc acpi:ANO*: ID_VENDOR_FROM_DATABASE=Anorad Corporation acpi:ANP*: ID_VENDOR_FROM_DATABASE=Andrew Network Production acpi:ANR*: ID_VENDOR_FROM_DATABASE=ANR Ltd acpi:ANS*: ID_VENDOR_FROM_DATABASE=Ansel Communication Company acpi:ANT*: ID_VENDOR_FROM_DATABASE=Ace CAD Enterprise Company Ltd acpi:ANX*: ID_VENDOR_FROM_DATABASE=Acer Netxus Inc acpi:AOA*: ID_VENDOR_FROM_DATABASE=AOpen Inc. acpi:AOE*: ID_VENDOR_FROM_DATABASE=Advanced Optics Electronics, Inc. acpi:AOL*: ID_VENDOR_FROM_DATABASE=America OnLine acpi:AOT*: ID_VENDOR_FROM_DATABASE=Alcatel acpi:APC*: ID_VENDOR_FROM_DATABASE=American Power Conversion acpi:APD*: ID_VENDOR_FROM_DATABASE=AppliAdata acpi:APG*: ID_VENDOR_FROM_DATABASE=Horner Electric Inc acpi:API*: ID_VENDOR_FROM_DATABASE=A Plus Info Corporation acpi:APL*: ID_VENDOR_FROM_DATABASE=Aplicom Oy acpi:APM*: ID_VENDOR_FROM_DATABASE=Applied Memory Tech acpi:APN*: ID_VENDOR_FROM_DATABASE=Appian Tech Inc acpi:APP*: ID_VENDOR_FROM_DATABASE=Apple Computer Inc acpi:APR*: ID_VENDOR_FROM_DATABASE=Aprilia s.p.a. acpi:APS*: ID_VENDOR_FROM_DATABASE=Autologic Inc acpi:APT*: ID_VENDOR_FROM_DATABASE=Audio Processing Technology Ltd acpi:APV*: ID_VENDOR_FROM_DATABASE=A+V Link acpi:APX*: ID_VENDOR_FROM_DATABASE=AP Designs Ltd acpi:ARC*: ID_VENDOR_FROM_DATABASE=Alta Research Corporation acpi:ARE*: ID_VENDOR_FROM_DATABASE=ICET S.p.A. acpi:ARG*: ID_VENDOR_FROM_DATABASE=Argus Electronics Co., LTD acpi:ARI*: ID_VENDOR_FROM_DATABASE=Argosy Research Inc acpi:ARK*: ID_VENDOR_FROM_DATABASE=Ark Logic Inc acpi:ARL*: ID_VENDOR_FROM_DATABASE=Arlotto Comnet Inc acpi:ARM*: ID_VENDOR_FROM_DATABASE=Arima acpi:ARO*: ID_VENDOR_FROM_DATABASE=Poso International B.V. acpi:ARS*: ID_VENDOR_FROM_DATABASE=Arescom Inc acpi:ART*: ID_VENDOR_FROM_DATABASE=Corion Industrial Corporation acpi:ASC*: ID_VENDOR_FROM_DATABASE=Ascom Strategic Technology Unit acpi:ASD*: ID_VENDOR_FROM_DATABASE=USC Information Sciences Institute acpi:ASE*: ID_VENDOR_FROM_DATABASE=AseV Display Labs acpi:ASI*: ID_VENDOR_FROM_DATABASE=Ahead Systems acpi:ASK*: ID_VENDOR_FROM_DATABASE=Ask A/S acpi:ASL*: ID_VENDOR_FROM_DATABASE=AccuScene Corporation Ltd acpi:ASM*: ID_VENDOR_FROM_DATABASE=ASEM S.p.A. acpi:ASN*: ID_VENDOR_FROM_DATABASE=Asante Tech Inc acpi:ASP*: ID_VENDOR_FROM_DATABASE=ASP Microelectronics Ltd acpi:AST*: ID_VENDOR_FROM_DATABASE=AST Research Inc acpi:ASU*: ID_VENDOR_FROM_DATABASE=Asuscom Network Inc acpi:ASX*: ID_VENDOR_FROM_DATABASE=AudioScience acpi:ASY*: ID_VENDOR_FROM_DATABASE=Rockwell Collins / Airshow Systems acpi:ATA*: ID_VENDOR_FROM_DATABASE=Allied Telesyn International (Asia) Pte Ltd acpi:ATC*: ID_VENDOR_FROM_DATABASE=Ably-Tech Corporation acpi:ATD*: ID_VENDOR_FROM_DATABASE=Alpha Telecom Inc acpi:ATE*: ID_VENDOR_FROM_DATABASE=Innovate Ltd acpi:ATH*: ID_VENDOR_FROM_DATABASE=Athena Informatica S.R.L. acpi:ATI*: ID_VENDOR_FROM_DATABASE=Allied Telesis KK acpi:ATK*: ID_VENDOR_FROM_DATABASE=Allied Telesyn Int'l acpi:ATL*: ID_VENDOR_FROM_DATABASE=Arcus Technology Ltd acpi:ATM*: ID_VENDOR_FROM_DATABASE=ATM Ltd acpi:ATN*: ID_VENDOR_FROM_DATABASE=Athena Smartcard Solutions Ltd. acpi:ATO*: ID_VENDOR_FROM_DATABASE=ASTRO DESIGN, INC. acpi:ATP*: ID_VENDOR_FROM_DATABASE=Alpha-Top Corporation acpi:ATT*: ID_VENDOR_FROM_DATABASE=AT&T acpi:ATV*: ID_VENDOR_FROM_DATABASE=Office Depot, Inc. acpi:ATX*: ID_VENDOR_FROM_DATABASE=Athenix Corporation acpi:AUI*: ID_VENDOR_FROM_DATABASE=Alps Electric Inc acpi:AUR*: ID_VENDOR_FROM_DATABASE=Aureal Semiconductor acpi:AUT*: ID_VENDOR_FROM_DATABASE=Autotime Corporation acpi:AVA*: ID_VENDOR_FROM_DATABASE=Avaya Communication acpi:AVC*: ID_VENDOR_FROM_DATABASE=Auravision Corporation acpi:AVD*: ID_VENDOR_FROM_DATABASE=Avid Electronics Corporation acpi:AVE*: ID_VENDOR_FROM_DATABASE=Add Value Enterpises (Asia) Pte Ltd acpi:AVI*: ID_VENDOR_FROM_DATABASE=Nippon Avionics Co.,Ltd acpi:AVL*: ID_VENDOR_FROM_DATABASE=Avalue Technology Inc. acpi:AVM*: ID_VENDOR_FROM_DATABASE=AVM GmbH acpi:AVN *: ID_VENDOR_FROM_DATABASE=Advance Computer Corporation acpi:AVO*: ID_VENDOR_FROM_DATABASE=Avocent Corporation acpi:AVR*: ID_VENDOR_FROM_DATABASE=AVer Information Inc. acpi:AVT*: ID_VENDOR_FROM_DATABASE=Avtek (Electronics) Pty Ltd acpi:AVV*: ID_VENDOR_FROM_DATABASE=SBS Technologies (Canada), Inc. (was Avvida Systems, Inc.) acpi:AWC*: ID_VENDOR_FROM_DATABASE=Access Works Comm Inc acpi:AWL*: ID_VENDOR_FROM_DATABASE=Aironet Wireless Communications, Inc acpi:AWS*: ID_VENDOR_FROM_DATABASE=Wave Systems acpi:AXB*: ID_VENDOR_FROM_DATABASE=Adrienne Electronics Corporation acpi:AXC*: ID_VENDOR_FROM_DATABASE=AXIOMTEK CO., LTD. acpi:AXE*: ID_VENDOR_FROM_DATABASE=D-Link Systems Inc (used as 2nd pnpid) acpi:AXI*: ID_VENDOR_FROM_DATABASE=American Magnetics acpi:AXL*: ID_VENDOR_FROM_DATABASE=Axel acpi:AXO*: ID_VENDOR_FROM_DATABASE=Axonic Labs LLC acpi:AXP*: ID_VENDOR_FROM_DATABASE=American Express acpi:AXT*: ID_VENDOR_FROM_DATABASE=Axtend Technologies Inc acpi:AXX*: ID_VENDOR_FROM_DATABASE=Axxon Computer Corporation acpi:AXY*: ID_VENDOR_FROM_DATABASE=AXYZ Automation Services, Inc acpi:AYD*: ID_VENDOR_FROM_DATABASE=Aydin Displays acpi:AYR*: ID_VENDOR_FROM_DATABASE=Airlib, Inc acpi:AZM*: ID_VENDOR_FROM_DATABASE=AZ Middelheim - Radiotherapy acpi:AZT*: ID_VENDOR_FROM_DATABASE=Aztech Systems Ltd acpi:BAC*: ID_VENDOR_FROM_DATABASE=Biometric Access Corporation acpi:BAN*: ID_VENDOR_FROM_DATABASE=Banyan acpi:BBB*: ID_VENDOR_FROM_DATABASE=an-najah university acpi:BBH*: ID_VENDOR_FROM_DATABASE=B&Bh acpi:BBL*: ID_VENDOR_FROM_DATABASE=Brain Boxes Limited acpi:BCC*: ID_VENDOR_FROM_DATABASE=Beaver Computer Corporaton acpi:BCD*: ID_VENDOR_FROM_DATABASE=Barco GmbH acpi:BCM*: ID_VENDOR_FROM_DATABASE=Broadcom acpi:BCQ*: ID_VENDOR_FROM_DATABASE=Deutsche Telekom Berkom GmbH acpi:BCS*: ID_VENDOR_FROM_DATABASE=Booria CAD/CAM systems acpi:BDO*: ID_VENDOR_FROM_DATABASE=Brahler ICS acpi:BDR*: ID_VENDOR_FROM_DATABASE=Blonder Tongue Labs, Inc. acpi:BDS*: ID_VENDOR_FROM_DATABASE=Barco Display Systems acpi:BEC*: ID_VENDOR_FROM_DATABASE=Elektro Beckhoff GmbH acpi:BEI*: ID_VENDOR_FROM_DATABASE=Beckworth Enterprises Inc acpi:BEK*: ID_VENDOR_FROM_DATABASE=Beko Elektronik A.S. acpi:BEL*: ID_VENDOR_FROM_DATABASE=Beltronic Industrieelektronik GmbH acpi:BEO*: ID_VENDOR_FROM_DATABASE=Baug & Olufsen acpi:BFE*: ID_VENDOR_FROM_DATABASE=B.F. Engineering Corporation acpi:BGB*: ID_VENDOR_FROM_DATABASE=Barco Graphics N.V acpi:BGT*: ID_VENDOR_FROM_DATABASE=Budzetron Inc acpi:BHZ*: ID_VENDOR_FROM_DATABASE=BitHeadz, Inc. acpi:BIC*: ID_VENDOR_FROM_DATABASE=Big Island Communications acpi:BII*: ID_VENDOR_FROM_DATABASE=Boeckeler Instruments Inc acpi:BIL*: ID_VENDOR_FROM_DATABASE=Billion Electric Company Ltd acpi:BIO*: ID_VENDOR_FROM_DATABASE=BioLink Technologies International, Inc. acpi:BIT*: ID_VENDOR_FROM_DATABASE=Bit 3 Computer acpi:BLI*: ID_VENDOR_FROM_DATABASE=Busicom acpi:BLN*: ID_VENDOR_FROM_DATABASE=BioLink Technologies acpi:BLP*: ID_VENDOR_FROM_DATABASE=Bloomberg L.P. acpi:BMI*: ID_VENDOR_FROM_DATABASE=Benson Medical Instruments Company acpi:BML*: ID_VENDOR_FROM_DATABASE=BIOMED Lab acpi:BMS*: ID_VENDOR_FROM_DATABASE=BIOMEDISYS acpi:BNE*: ID_VENDOR_FROM_DATABASE=Bull AB acpi:BNK*: ID_VENDOR_FROM_DATABASE=Banksia Tech Pty Ltd acpi:BNO*: ID_VENDOR_FROM_DATABASE=Bang & Olufsen acpi:BNS*: ID_VENDOR_FROM_DATABASE=Boulder Nonlinear Systems acpi:BOB*: ID_VENDOR_FROM_DATABASE=Rainy Orchard acpi:BOE*: ID_VENDOR_FROM_DATABASE=BOE acpi:BOI*: ID_VENDOR_FROM_DATABASE=NINGBO BOIGLE DIGITAL TECHNOLOGY CO.,LTD acpi:BOS*: ID_VENDOR_FROM_DATABASE=BOS acpi:BPD*: ID_VENDOR_FROM_DATABASE=Micro Solutions, Inc. acpi:BPU*: ID_VENDOR_FROM_DATABASE=Best Power acpi:BRA*: ID_VENDOR_FROM_DATABASE=Braemac Pty Ltd acpi:BRC*: ID_VENDOR_FROM_DATABASE=BARC acpi:BRG*: ID_VENDOR_FROM_DATABASE=Bridge Information Co., Ltd acpi:BRI*: ID_VENDOR_FROM_DATABASE=Boca Research Inc acpi:BRM*: ID_VENDOR_FROM_DATABASE=Braemar Inc acpi:BRO*: ID_VENDOR_FROM_DATABASE=BROTHER INDUSTRIES,LTD. acpi:BSE*: ID_VENDOR_FROM_DATABASE=Bose Corporation acpi:BSL*: ID_VENDOR_FROM_DATABASE=Biomedical Systems Laboratory acpi:BSN*: ID_VENDOR_FROM_DATABASE=BRIGHTSIGN, LLC acpi:BST*: ID_VENDOR_FROM_DATABASE=BodySound Technologies, Inc. acpi:BTC*: ID_VENDOR_FROM_DATABASE=Bit 3 Computer acpi:BTE*: ID_VENDOR_FROM_DATABASE=Brilliant Technology acpi:BTF*: ID_VENDOR_FROM_DATABASE=Bitfield Oy acpi:BTI*: ID_VENDOR_FROM_DATABASE=BusTech Inc acpi:BTO*: ID_VENDOR_FROM_DATABASE=BioTao Ltd acpi:BUF*: ID_VENDOR_FROM_DATABASE=Yasuhiko Shirai Melco Inc acpi:BUG*: ID_VENDOR_FROM_DATABASE=B.U.G., Inc. acpi:BUJ*: ID_VENDOR_FROM_DATABASE=ATI Tech Inc acpi:BUL*: ID_VENDOR_FROM_DATABASE=Bull acpi:BUR*: ID_VENDOR_FROM_DATABASE=Bernecker & Rainer Ind-Eletronik GmbH acpi:BUS*: ID_VENDOR_FROM_DATABASE=BusTek acpi:BUT*: ID_VENDOR_FROM_DATABASE=21ST CENTURY ENTERTAINMENT acpi:BWK*: ID_VENDOR_FROM_DATABASE=Bitworks Inc. acpi:BXE*: ID_VENDOR_FROM_DATABASE=Buxco Electronics acpi:BYD*: ID_VENDOR_FROM_DATABASE=byd:sign corporation acpi:CAA*: ID_VENDOR_FROM_DATABASE=Castles Automation Co., Ltd acpi:CAC*: ID_VENDOR_FROM_DATABASE=CA & F Elettronica acpi:CAG*: ID_VENDOR_FROM_DATABASE=CalComp acpi:CAI*: ID_VENDOR_FROM_DATABASE=Canon Inc. acpi:CAL*: ID_VENDOR_FROM_DATABASE=Acon acpi:CAM*: ID_VENDOR_FROM_DATABASE=Cambridge Audio acpi:CAN*: ID_VENDOR_FROM_DATABASE=Canopus Company Ltd acpi:CAR*: ID_VENDOR_FROM_DATABASE=Cardinal Company Ltd acpi:CAS*: ID_VENDOR_FROM_DATABASE=CASIO COMPUTER CO.,LTD acpi:CAT*: ID_VENDOR_FROM_DATABASE=Consultancy in Advanced Technology acpi:CAV*: ID_VENDOR_FROM_DATABASE=Cavium Networks, Inc acpi:CBI*: ID_VENDOR_FROM_DATABASE=ComputerBoards Inc acpi:CBR*: ID_VENDOR_FROM_DATABASE=Cebra Tech A/S acpi:CBT*: ID_VENDOR_FROM_DATABASE=Cabletime Ltd acpi:CBX*: ID_VENDOR_FROM_DATABASE=Cybex Computer Products Corporation acpi:CCC*: ID_VENDOR_FROM_DATABASE=C-Cube Microsystems acpi:CCI*: ID_VENDOR_FROM_DATABASE=Cache acpi:CCJ*: ID_VENDOR_FROM_DATABASE=CONTEC CO.,LTD. acpi:CCL*: ID_VENDOR_FROM_DATABASE=CCL/ITRI acpi:CCP*: ID_VENDOR_FROM_DATABASE=Capetronic USA Inc acpi:CDC*: ID_VENDOR_FROM_DATABASE=Core Dynamics Corporation acpi:CDD*: ID_VENDOR_FROM_DATABASE=Convergent Data Devices acpi:CDE*: ID_VENDOR_FROM_DATABASE=Colin.de acpi:CDG*: ID_VENDOR_FROM_DATABASE=Christie Digital Systems Inc acpi:CDI*: ID_VENDOR_FROM_DATABASE=Concept Development Inc acpi:CDK*: ID_VENDOR_FROM_DATABASE=Cray Communications acpi:CDN*: ID_VENDOR_FROM_DATABASE=Codenoll Technical Corporation acpi:CDP*: ID_VENDOR_FROM_DATABASE=CalComp acpi:CDS*: ID_VENDOR_FROM_DATABASE=Computer Diagnostic Systems acpi:CDT*: ID_VENDOR_FROM_DATABASE=IBM Corporation acpi:CDV*: ID_VENDOR_FROM_DATABASE=Convergent Design Inc. acpi:CEA*: ID_VENDOR_FROM_DATABASE=Consumer Electronics Association acpi:CEC*: ID_VENDOR_FROM_DATABASE=Chicony Electronics Company Ltd acpi:CED*: ID_VENDOR_FROM_DATABASE=Cambridge Electronic Design Ltd acpi:CEF*: ID_VENDOR_FROM_DATABASE=Cefar Digital Vision acpi:CEI*: ID_VENDOR_FROM_DATABASE=Crestron Electronics, Inc. acpi:CEM*: ID_VENDOR_FROM_DATABASE=MEC Electronics GmbH acpi:CEN*: ID_VENDOR_FROM_DATABASE=Centurion Technologies P/L acpi:CEP*: ID_VENDOR_FROM_DATABASE=C-DAC acpi:CER*: ID_VENDOR_FROM_DATABASE=Ceronix acpi:CET*: ID_VENDOR_FROM_DATABASE=TEC CORPORATION acpi:CFG*: ID_VENDOR_FROM_DATABASE=Atlantis acpi:CGA*: ID_VENDOR_FROM_DATABASE=Chunghwa Picture Tubes, LTD acpi:CGS*: ID_VENDOR_FROM_DATABASE=Chyron Corp acpi:CGT*: ID_VENDOR_FROM_DATABASE=congatec AG acpi:CHA*: ID_VENDOR_FROM_DATABASE=Chase Research PLC acpi:CHC*: ID_VENDOR_FROM_DATABASE=Chic Technology Corp. acpi:CHD*: ID_VENDOR_FROM_DATABASE=ChangHong Electric Co.,Ltd acpi:CHE*: ID_VENDOR_FROM_DATABASE=Acer Inc acpi:CHG*: ID_VENDOR_FROM_DATABASE=Sichuan Changhong Electric CO, LTD. acpi:CHI*: ID_VENDOR_FROM_DATABASE=Chrontel Inc acpi:CHL*: ID_VENDOR_FROM_DATABASE=Chloride-R&D acpi:CHM*: ID_VENDOR_FROM_DATABASE=CHIC TECHNOLOGY CORP. acpi:CHO*: ID_VENDOR_FROM_DATABASE=Sichuang Changhong Corporation acpi:CHP*: ID_VENDOR_FROM_DATABASE=CH Products acpi:CHS*: ID_VENDOR_FROM_DATABASE=Agentur Chairos acpi:CHT*: ID_VENDOR_FROM_DATABASE=Chunghwa Picture Tubes,LTD. acpi:CHY*: ID_VENDOR_FROM_DATABASE=Cherry GmbH acpi:CIC*: ID_VENDOR_FROM_DATABASE=Comm. Intelligence Corporation acpi:CII*: ID_VENDOR_FROM_DATABASE=Cromack Industries Inc acpi:CIL*: ID_VENDOR_FROM_DATABASE=Citicom Infotech Private Limited acpi:CIN*: ID_VENDOR_FROM_DATABASE=Citron GmbH acpi:CIP*: ID_VENDOR_FROM_DATABASE=Ciprico Inc acpi:CIR*: ID_VENDOR_FROM_DATABASE=Cirrus Logic Inc acpi:CIS*: ID_VENDOR_FROM_DATABASE=Cisco Systems Inc acpi:CIT*: ID_VENDOR_FROM_DATABASE=Citifax Limited acpi:CKC*: ID_VENDOR_FROM_DATABASE=The Concept Keyboard Company Ltd acpi:CKJ*: ID_VENDOR_FROM_DATABASE=Carina System Co., Ltd. acpi:CLA*: ID_VENDOR_FROM_DATABASE=Clarion Company Ltd acpi:CLD*: ID_VENDOR_FROM_DATABASE=COMMAT L.t.d. acpi:CLE*: ID_VENDOR_FROM_DATABASE=Classe Audio acpi:CLG*: ID_VENDOR_FROM_DATABASE=CoreLogic acpi:CLI*: ID_VENDOR_FROM_DATABASE=Cirrus Logic Inc acpi:CLM*: ID_VENDOR_FROM_DATABASE=CrystaLake Multimedia acpi:CLO*: ID_VENDOR_FROM_DATABASE=Clone Computers acpi:CLT*: ID_VENDOR_FROM_DATABASE=automated computer control systems acpi:CLV*: ID_VENDOR_FROM_DATABASE=Clevo Company acpi:CLX*: ID_VENDOR_FROM_DATABASE=CardLogix acpi:CMC*: ID_VENDOR_FROM_DATABASE=CMC Ltd acpi:CMD*: ID_VENDOR_FROM_DATABASE=Colorado MicroDisplay, Inc. acpi:CMG*: ID_VENDOR_FROM_DATABASE=Chenming Mold Ind. Corp. acpi:CMI*: ID_VENDOR_FROM_DATABASE=C-Media Electronics acpi:CMM*: ID_VENDOR_FROM_DATABASE=Comtime GmbH acpi:CMN*: ID_VENDOR_FROM_DATABASE=Chimei Innolux Corporation acpi:CMO*: ID_VENDOR_FROM_DATABASE=Chi Mei Optoelectronics corp. acpi:CMR*: ID_VENDOR_FROM_DATABASE=Cambridge Research Systems Ltd acpi:CMS*: ID_VENDOR_FROM_DATABASE=CompuMaster Srl acpi:CMX*: ID_VENDOR_FROM_DATABASE=Comex Electronics AB acpi:CNB*: ID_VENDOR_FROM_DATABASE=American Power Conversion acpi:CNC*: ID_VENDOR_FROM_DATABASE=Alvedon Computers Ltd acpi:CNE*: ID_VENDOR_FROM_DATABASE=Cine-tal acpi:CNI*: ID_VENDOR_FROM_DATABASE=Connect Int'l A/S acpi:CNN*: ID_VENDOR_FROM_DATABASE=Canon Inc acpi:CNT*: ID_VENDOR_FROM_DATABASE=COINT Multimedia Systems acpi:COB*: ID_VENDOR_FROM_DATABASE=COBY Electronics Co., Ltd acpi:COD*: ID_VENDOR_FROM_DATABASE=CODAN Pty. Ltd. acpi:COI*: ID_VENDOR_FROM_DATABASE=Codec Inc. acpi:COL*: ID_VENDOR_FROM_DATABASE=Rockwell Collins, Inc. acpi:COM*: ID_VENDOR_FROM_DATABASE=Comtrol Corporation acpi:CON*: ID_VENDOR_FROM_DATABASE=Contec Company Ltd acpi:COO*: ID_VENDOR_FROM_DATABASE=coolux GmbH acpi:COR*: ID_VENDOR_FROM_DATABASE=Corollary Inc acpi:COS*: ID_VENDOR_FROM_DATABASE=CoStar Corporation acpi:COT*: ID_VENDOR_FROM_DATABASE=Core Technology Inc acpi:COW*: ID_VENDOR_FROM_DATABASE=Polycow Productions acpi:COX*: ID_VENDOR_FROM_DATABASE=Comrex acpi:CPC*: ID_VENDOR_FROM_DATABASE=Ciprico Inc acpi:CPD*: ID_VENDOR_FROM_DATABASE=CompuAdd acpi:CPI*: ID_VENDOR_FROM_DATABASE=Computer Peripherals Inc acpi:CPL*: ID_VENDOR_FROM_DATABASE=Compal Electronics Inc acpi:CPM*: ID_VENDOR_FROM_DATABASE=Capella Microsystems Inc. acpi:CPQ*: ID_VENDOR_FROM_DATABASE=Compaq Computer Company acpi:CPT*: ID_VENDOR_FROM_DATABASE=cPATH acpi:CPX*: ID_VENDOR_FROM_DATABASE=Powermatic Data Systems acpi:CRC*: ID_VENDOR_FROM_DATABASE=CONRAC GmbH acpi:CRD*: ID_VENDOR_FROM_DATABASE=Cardinal Technical Inc acpi:CRE*: ID_VENDOR_FROM_DATABASE=Creative Labs Inc acpi:CRI*: ID_VENDOR_FROM_DATABASE=Crio Inc. acpi:CRL*: ID_VENDOR_FROM_DATABASE=Creative Logic   acpi:CRN*: ID_VENDOR_FROM_DATABASE=Cornerstone Imaging acpi:CRO*: ID_VENDOR_FROM_DATABASE=Extraordinary Technologies PTY Limited acpi:CRQ*: ID_VENDOR_FROM_DATABASE=Cirque Corporation acpi:CRS*: ID_VENDOR_FROM_DATABASE=Crescendo Communication Inc acpi:CRV*: ID_VENDOR_FROM_DATABASE=Cerevo Inc. acpi:CRX*: ID_VENDOR_FROM_DATABASE=Cyrix Corporation acpi:CSB*: ID_VENDOR_FROM_DATABASE=Transtex SA acpi:CSC*: ID_VENDOR_FROM_DATABASE=Crystal Semiconductor acpi:CSD*: ID_VENDOR_FROM_DATABASE=Cresta Systems Inc acpi:CSE*: ID_VENDOR_FROM_DATABASE=Concept Solutions & Engineering acpi:CSI*: ID_VENDOR_FROM_DATABASE=Cabletron System Inc acpi:CSM*: ID_VENDOR_FROM_DATABASE=Cosmic Engineering Inc. acpi:CSO*: ID_VENDOR_FROM_DATABASE=California Institute of Technology acpi:CSS*: ID_VENDOR_FROM_DATABASE=CSS Laboratories acpi:CST*: ID_VENDOR_FROM_DATABASE=CSTI Inc acpi:CTA*: ID_VENDOR_FROM_DATABASE=CoSystems Inc acpi:CTC*: ID_VENDOR_FROM_DATABASE=CTC Communication Development Company Ltd acpi:CTE*: ID_VENDOR_FROM_DATABASE=Chunghwa Telecom Co., Ltd. acpi:CTL*: ID_VENDOR_FROM_DATABASE=Creative Technology Ltd acpi:CTM*: ID_VENDOR_FROM_DATABASE=Computerm Corporation acpi:CTN*: ID_VENDOR_FROM_DATABASE=Computone Products acpi:CTP*: ID_VENDOR_FROM_DATABASE=Computer Technology Corporation acpi:CTS*: ID_VENDOR_FROM_DATABASE=Comtec Systems Co., Ltd. acpi:CTX*: ID_VENDOR_FROM_DATABASE=Creatix Polymedia GmbH acpi:CUB*: ID_VENDOR_FROM_DATABASE=Cubix Corporation acpi:CUK*: ID_VENDOR_FROM_DATABASE=Calibre UK Ltd acpi:CVA*: ID_VENDOR_FROM_DATABASE=Covia Inc. acpi:CVS*: ID_VENDOR_FROM_DATABASE=Clarity Visual Systems acpi:CWR*: ID_VENDOR_FROM_DATABASE=Connectware Inc acpi:CXT*: ID_VENDOR_FROM_DATABASE=Conexant Systems acpi:CYB*: ID_VENDOR_FROM_DATABASE=CyberVision acpi:CYC*: ID_VENDOR_FROM_DATABASE=Cylink Corporation acpi:CYD*: ID_VENDOR_FROM_DATABASE=Cyclades Corporation acpi:CYL*: ID_VENDOR_FROM_DATABASE=Cyberlabs acpi:CYT*: ID_VENDOR_FROM_DATABASE=Cytechinfo Inc acpi:CYV*: ID_VENDOR_FROM_DATABASE=Cyviz AS acpi:CYW*: ID_VENDOR_FROM_DATABASE=Cyberware acpi:CYX*: ID_VENDOR_FROM_DATABASE=Cyrix Corporation acpi:CZE*: ID_VENDOR_FROM_DATABASE=Carl Zeiss AG acpi:DAC*: ID_VENDOR_FROM_DATABASE=Digital Acoustics Corporation acpi:DAE*: ID_VENDOR_FROM_DATABASE=Digatron Industrie Elektronik GmbH acpi:DAI*: ID_VENDOR_FROM_DATABASE=DAIS SET Ltd. acpi:DAK*: ID_VENDOR_FROM_DATABASE=Daktronics acpi:DAL*: ID_VENDOR_FROM_DATABASE=Digital Audio Labs Inc acpi:DAN*: ID_VENDOR_FROM_DATABASE=Danelec Marine A/S acpi:DAS*: ID_VENDOR_FROM_DATABASE=DAVIS AS acpi:DAT*: ID_VENDOR_FROM_DATABASE=Datel Inc acpi:DAU*: ID_VENDOR_FROM_DATABASE=Daou Tech Inc acpi:DAV*: ID_VENDOR_FROM_DATABASE=Davicom Semiconductor Inc acpi:DAW*: ID_VENDOR_FROM_DATABASE=DA2 Technologies Inc acpi:DAX*: ID_VENDOR_FROM_DATABASE=Data Apex Ltd acpi:DBD*: ID_VENDOR_FROM_DATABASE=Diebold Inc. acpi:DBI*: ID_VENDOR_FROM_DATABASE=DigiBoard Inc acpi:DBK*: ID_VENDOR_FROM_DATABASE=Databook Inc acpi:DBL*: ID_VENDOR_FROM_DATABASE=Doble Engineering Company acpi:DBN*: ID_VENDOR_FROM_DATABASE=DB Networks Inc acpi:DCA*: ID_VENDOR_FROM_DATABASE=Digital Communications Association acpi:DCC*: ID_VENDOR_FROM_DATABASE=Dale Computer Corporation acpi:DCD*: ID_VENDOR_FROM_DATABASE=Datacast LLC acpi:DCE*: ID_VENDOR_FROM_DATABASE=dSPACE GmbH acpi:DCI*: ID_VENDOR_FROM_DATABASE=Concepts Inc acpi:DCL*: ID_VENDOR_FROM_DATABASE=Dynamic Controls Ltd acpi:DCM*: ID_VENDOR_FROM_DATABASE=DCM Data Products acpi:DCO*: ID_VENDOR_FROM_DATABASE=Dialogue Technology Corporation acpi:DCR*: ID_VENDOR_FROM_DATABASE=Decros Ltd acpi:DCS*: ID_VENDOR_FROM_DATABASE=Diamond Computer Systems Inc acpi:DCT*: ID_VENDOR_FROM_DATABASE=Dancall Telecom A/S acpi:DCV*: ID_VENDOR_FROM_DATABASE=Datatronics Technology Inc acpi:DDA*: ID_VENDOR_FROM_DATABASE=DA2 Technologies Corporation acpi:DDD*: ID_VENDOR_FROM_DATABASE=Danka Data Devices acpi:DDE*: ID_VENDOR_FROM_DATABASE=Datasat Digital Entertainment acpi:DDI*: ID_VENDOR_FROM_DATABASE=Data Display AG acpi:DDS*: ID_VENDOR_FROM_DATABASE=Barco, n.v. acpi:DDT*: ID_VENDOR_FROM_DATABASE=Datadesk Technologies Inc acpi:DDV*: ID_VENDOR_FROM_DATABASE=Delta Information Systems, Inc acpi:DEC*: ID_VENDOR_FROM_DATABASE=Digital Equipment Corporation acpi:DEI*: ID_VENDOR_FROM_DATABASE=Deico Electronics acpi:DEL*: ID_VENDOR_FROM_DATABASE=Dell Inc. acpi:DEN*: ID_VENDOR_FROM_DATABASE=Densitron Computers Ltd acpi:DEX*: ID_VENDOR_FROM_DATABASE=idex displays acpi:DFI*: ID_VENDOR_FROM_DATABASE=DFI acpi:DFK*: ID_VENDOR_FROM_DATABASE=SharkTec A/S acpi:DFT*: ID_VENDOR_FROM_DATABASE=DEI Holdings dba Definitive Technology acpi:DGA*: ID_VENDOR_FROM_DATABASE=Digiital Arts Inc acpi:DGC*: ID_VENDOR_FROM_DATABASE=Data General Corporation acpi:DGI*: ID_VENDOR_FROM_DATABASE=DIGI International acpi:DGK*: ID_VENDOR_FROM_DATABASE=DugoTech Co., LTD acpi:DGP*: ID_VENDOR_FROM_DATABASE=Digicorp European sales S.A. acpi:DGS*: ID_VENDOR_FROM_DATABASE=Diagsoft Inc acpi:DGT*: ID_VENDOR_FROM_DATABASE=The Dearborn Group acpi:DHP*: ID_VENDOR_FROM_DATABASE=DH Print acpi:DHQ*: ID_VENDOR_FROM_DATABASE=Quadram acpi:DHT*: ID_VENDOR_FROM_DATABASE=Projectavision Inc acpi:DIA*: ID_VENDOR_FROM_DATABASE=Diadem acpi:DIG*: ID_VENDOR_FROM_DATABASE=Digicom S.p.A. acpi:DII*: ID_VENDOR_FROM_DATABASE=Dataq Instruments Inc acpi:DIM*: ID_VENDOR_FROM_DATABASE=dPict Imaging, Inc. acpi:DIN*: ID_VENDOR_FROM_DATABASE=Daintelecom Co., Ltd acpi:DIS*: ID_VENDOR_FROM_DATABASE=Diseda S.A. acpi:DIT*: ID_VENDOR_FROM_DATABASE=Dragon Information Technology acpi:DJE*: ID_VENDOR_FROM_DATABASE=Capstone Visual Product Development acpi:DJP*: ID_VENDOR_FROM_DATABASE=Maygay Machines, Ltd acpi:DKY*: ID_VENDOR_FROM_DATABASE=Datakey Inc acpi:DLB*: ID_VENDOR_FROM_DATABASE=Dolby Laboratories Inc. acpi:DLC*: ID_VENDOR_FROM_DATABASE=Diamond Lane Comm. Corporation acpi:DLG*: ID_VENDOR_FROM_DATABASE=Digital-Logic GmbH acpi:DLK*: ID_VENDOR_FROM_DATABASE=D-Link Systems Inc acpi:DLL*: ID_VENDOR_FROM_DATABASE=Dell Inc acpi:DLT*: ID_VENDOR_FROM_DATABASE=Digitelec Informatique Park Cadera acpi:DMB*: ID_VENDOR_FROM_DATABASE=Digicom Systems Inc acpi:DMC*: ID_VENDOR_FROM_DATABASE=Dune Microsystems Corporation acpi:DMM*: ID_VENDOR_FROM_DATABASE=Dimond Multimedia Systems Inc acpi:DMP*: ID_VENDOR_FROM_DATABASE=D&M Holdings Inc, Professional Business Company acpi:DMS*: ID_VENDOR_FROM_DATABASE=DOME imaging systems acpi:DMT*: ID_VENDOR_FROM_DATABASE=Distributed Management Task Force, Inc. (DMTF) acpi:DMV*: ID_VENDOR_FROM_DATABASE=NDS Ltd acpi:DNA*: ID_VENDOR_FROM_DATABASE=DNA Enterprises, Inc. acpi:DNG*: ID_VENDOR_FROM_DATABASE=Apache Micro Peripherals Inc acpi:DNI*: ID_VENDOR_FROM_DATABASE=Deterministic Networks Inc. acpi:DNT*: ID_VENDOR_FROM_DATABASE=Dr. Neuhous Telekommunikation GmbH acpi:DNV*: ID_VENDOR_FROM_DATABASE=DiCon acpi:DOL*: ID_VENDOR_FROM_DATABASE=Dolman Technologies Group Inc acpi:DOM*: ID_VENDOR_FROM_DATABASE=Dome Imaging Systems acpi:DON*: ID_VENDOR_FROM_DATABASE=DENON, Ltd. acpi:DOT*: ID_VENDOR_FROM_DATABASE=Dotronic Mikroelektronik GmbH acpi:DPA*: ID_VENDOR_FROM_DATABASE=DigiTalk Pro AV acpi:DPC*: ID_VENDOR_FROM_DATABASE=Delta Electronics Inc acpi:DPI*: ID_VENDOR_FROM_DATABASE=DocuPoint acpi:DPL*: ID_VENDOR_FROM_DATABASE=Digital Projection Limited acpi:DPM*: ID_VENDOR_FROM_DATABASE=ADPM Synthesis sas acpi:DPS*: ID_VENDOR_FROM_DATABASE=Digital Processing Systems acpi:DPT*: ID_VENDOR_FROM_DATABASE=DPT acpi:DPX*: ID_VENDOR_FROM_DATABASE=DpiX, Inc. acpi:DQB*: ID_VENDOR_FROM_DATABASE=Datacube Inc acpi:DRB*: ID_VENDOR_FROM_DATABASE=Dr. Bott KG acpi:DRC*: ID_VENDOR_FROM_DATABASE=Data Ray Corp. acpi:DRD*: ID_VENDOR_FROM_DATABASE=DIGITAL REFLECTION INC. acpi:DRI*: ID_VENDOR_FROM_DATABASE=Data Race Inc acpi:DRS*: ID_VENDOR_FROM_DATABASE=DRS Defense Solutions, LLC acpi:DSD*: ID_VENDOR_FROM_DATABASE=DS Multimedia Pte Ltd acpi:DSI*: ID_VENDOR_FROM_DATABASE=Digitan Systems Inc acpi:DSM*: ID_VENDOR_FROM_DATABASE=DSM Digital Services GmbH acpi:DSP*: ID_VENDOR_FROM_DATABASE=Domain Technology Inc acpi:DTA*: ID_VENDOR_FROM_DATABASE=DELTATEC acpi:DTC*: ID_VENDOR_FROM_DATABASE=DTC Tech Corporation acpi:DTE*: ID_VENDOR_FROM_DATABASE=Dimension Technologies, Inc. acpi:DTI*: ID_VENDOR_FROM_DATABASE=Diversified Technology, Inc. acpi:DTK*: ID_VENDOR_FROM_DATABASE=Dynax Electronics (HK) Ltd acpi:DTL*: ID_VENDOR_FROM_DATABASE=e-Net Inc acpi:DTN*: ID_VENDOR_FROM_DATABASE=Datang Telephone Co acpi:DTO*: ID_VENDOR_FROM_DATABASE=Deutsche Thomson OHG acpi:DTT*: ID_VENDOR_FROM_DATABASE=Design & Test Technology, Inc. acpi:DTX*: ID_VENDOR_FROM_DATABASE=Data Translation acpi:DUA*: ID_VENDOR_FROM_DATABASE=Dosch & Amand GmbH & Company KG acpi:DUN*: ID_VENDOR_FROM_DATABASE=NCR Corporation acpi:DVD*: ID_VENDOR_FROM_DATABASE=Dictaphone Corporation acpi:DVL*: ID_VENDOR_FROM_DATABASE=Devolo AG acpi:DVS*: ID_VENDOR_FROM_DATABASE=Digital Video System acpi:DVT*: ID_VENDOR_FROM_DATABASE=Data Video acpi:DWE*: ID_VENDOR_FROM_DATABASE=Daewoo Electronics Company Ltd acpi:DXC*: ID_VENDOR_FROM_DATABASE=Digipronix Control Systems acpi:DXD*: ID_VENDOR_FROM_DATABASE=DECIMATOR DESIGN PTY LTD acpi:DXL*: ID_VENDOR_FROM_DATABASE=Dextera Labs Inc acpi:DXP*: ID_VENDOR_FROM_DATABASE=Data Expert Corporation acpi:DXS*: ID_VENDOR_FROM_DATABASE=Signet acpi:DYC*: ID_VENDOR_FROM_DATABASE=Dycam Inc acpi:DYM*: ID_VENDOR_FROM_DATABASE=Dymo-CoStar Corporation acpi:DYN*: ID_VENDOR_FROM_DATABASE=Askey Computer Corporation acpi:DYX*: ID_VENDOR_FROM_DATABASE=Dynax Electronics (HK) Ltd acpi:EAS*: ID_VENDOR_FROM_DATABASE=Evans and Sutherland Computer acpi:EBH*: ID_VENDOR_FROM_DATABASE=Data Price Informatica acpi:EBT*: ID_VENDOR_FROM_DATABASE=HUALONG TECHNOLOGY CO., LTD acpi:ECA*: ID_VENDOR_FROM_DATABASE=Electro Cam Corp. acpi:ECC*: ID_VENDOR_FROM_DATABASE=ESSential Comm. Corporation acpi:ECI*: ID_VENDOR_FROM_DATABASE=Enciris Technologies acpi:ECK*: ID_VENDOR_FROM_DATABASE=Eugene Chukhlomin Sole Proprietorship, d.b.a. acpi:ECL*: ID_VENDOR_FROM_DATABASE=Excel Company Ltd acpi:ECM*: ID_VENDOR_FROM_DATABASE=E-Cmos Tech Corporation acpi:ECO*: ID_VENDOR_FROM_DATABASE=Echo Speech Corporation acpi:ECP*: ID_VENDOR_FROM_DATABASE=Elecom Company Ltd acpi:ECS*: ID_VENDOR_FROM_DATABASE=Elitegroup Computer Systems Company Ltd acpi:ECT*: ID_VENDOR_FROM_DATABASE=Enciris Technologies acpi:EDC*: ID_VENDOR_FROM_DATABASE=e.Digital Corporation acpi:EDG*: ID_VENDOR_FROM_DATABASE=Electronic-Design GmbH acpi:EDI*: ID_VENDOR_FROM_DATABASE=Edimax Tech. Company Ltd acpi:EDM*: ID_VENDOR_FROM_DATABASE=EDMI acpi:EDT*: ID_VENDOR_FROM_DATABASE=Emerging Display Technologies Corp acpi:EEE*: ID_VENDOR_FROM_DATABASE=ET&T Technology Company Ltd acpi:EEH*: ID_VENDOR_FROM_DATABASE=EEH Datalink GmbH acpi:EEP*: ID_VENDOR_FROM_DATABASE=E.E.P.D. GmbH acpi:EES*: ID_VENDOR_FROM_DATABASE=EE Solutions, Inc. acpi:EGA*: ID_VENDOR_FROM_DATABASE=Elgato Systems LLC acpi:EGD*: ID_VENDOR_FROM_DATABASE=EIZO GmbH Display Technologies acpi:EGL*: ID_VENDOR_FROM_DATABASE=Eagle Technology acpi:EGN*: ID_VENDOR_FROM_DATABASE=Egenera, Inc. acpi:EGO*: ID_VENDOR_FROM_DATABASE=Ergo Electronics acpi:EHJ*: ID_VENDOR_FROM_DATABASE=Epson Research acpi:EHN*: ID_VENDOR_FROM_DATABASE=Enhansoft acpi:EIC*: ID_VENDOR_FROM_DATABASE=Eicon Technology Corporation acpi:EKA*: ID_VENDOR_FROM_DATABASE=MagTek Inc. acpi:EKC*: ID_VENDOR_FROM_DATABASE=Eastman Kodak Company acpi:EKS*: ID_VENDOR_FROM_DATABASE=EKSEN YAZILIM acpi:ELA*: ID_VENDOR_FROM_DATABASE=ELAD srl acpi:ELC*: ID_VENDOR_FROM_DATABASE=Electro Scientific Ind acpi:ELE*: ID_VENDOR_FROM_DATABASE=Elecom Company Ltd acpi:ELG*: ID_VENDOR_FROM_DATABASE=Elmeg GmbH Kommunikationstechnik acpi:ELI*: ID_VENDOR_FROM_DATABASE=Edsun Laboratories acpi:ELL*: ID_VENDOR_FROM_DATABASE=Electrosonic Ltd acpi:ELM*: ID_VENDOR_FROM_DATABASE=Elmic Systems Inc acpi:ELO*: ID_VENDOR_FROM_DATABASE=Elo TouchSystems Inc acpi:ELS*: ID_VENDOR_FROM_DATABASE=ELSA GmbH acpi:ELT*: ID_VENDOR_FROM_DATABASE=Element Labs, Inc. acpi:ELX*: ID_VENDOR_FROM_DATABASE=Elonex PLC acpi:EMB*: ID_VENDOR_FROM_DATABASE=Embedded computing inc ltd acpi:EMC*: ID_VENDOR_FROM_DATABASE=eMicro Corporation acpi:EME*: ID_VENDOR_FROM_DATABASE=EMiNE TECHNOLOGY COMPANY, LTD. acpi:EMG*: ID_VENDOR_FROM_DATABASE=EMG Consultants Inc acpi:EMI*: ID_VENDOR_FROM_DATABASE=Ex Machina Inc acpi:EMK*: ID_VENDOR_FROM_DATABASE=Emcore Corporation acpi:EMO*: ID_VENDOR_FROM_DATABASE=ELMO COMPANY, LIMITED acpi:EMU*: ID_VENDOR_FROM_DATABASE=Emulex Corporation acpi:ENC*: ID_VENDOR_FROM_DATABASE=Eizo Nanao Corporation acpi:END*: ID_VENDOR_FROM_DATABASE=ENIDAN Technologies Ltd acpi:ENE*: ID_VENDOR_FROM_DATABASE=ENE Technology Inc. acpi:ENI*: ID_VENDOR_FROM_DATABASE=Efficient Networks acpi:ENS*: ID_VENDOR_FROM_DATABASE=Ensoniq Corporation acpi:ENT*: ID_VENDOR_FROM_DATABASE=Enterprise Comm. & Computing Inc acpi:EPC*: ID_VENDOR_FROM_DATABASE=Empac acpi:EPH *: ID_VENDOR_FROM_DATABASE=Epiphan Systems Inc.  acpi:EPI*: ID_VENDOR_FROM_DATABASE=Envision Peripherals, Inc acpi:EPN*: ID_VENDOR_FROM_DATABASE=EPiCON Inc. acpi:EPS*: ID_VENDOR_FROM_DATABASE=KEPS acpi:EQP*: ID_VENDOR_FROM_DATABASE=Equipe Electronics Ltd. acpi:EQX*: ID_VENDOR_FROM_DATABASE=Equinox Systems Inc acpi:ERG*: ID_VENDOR_FROM_DATABASE=Ergo System acpi:ERI*: ID_VENDOR_FROM_DATABASE=Ericsson Mobile Communications AB acpi:ERN*: ID_VENDOR_FROM_DATABASE=Ericsson, Inc. acpi:ERP*: ID_VENDOR_FROM_DATABASE=Euraplan GmbH acpi:ERT*: ID_VENDOR_FROM_DATABASE=Escort Insturments Corporation acpi:ESA*: ID_VENDOR_FROM_DATABASE=Elbit Systems of America acpi:ESC*: ID_VENDOR_FROM_DATABASE=Eden Sistemas de Computacao S/A acpi:ESD*: ID_VENDOR_FROM_DATABASE=Ensemble Designs, Inc acpi:ESG*: ID_VENDOR_FROM_DATABASE=ELCON Systemtechnik GmbH acpi:ESI*: ID_VENDOR_FROM_DATABASE=Extended Systems, Inc. acpi:ESK*: ID_VENDOR_FROM_DATABASE=ES&S acpi:ESL*: ID_VENDOR_FROM_DATABASE=Esterline Technologies acpi:ESN*: ID_VENDOR_FROM_DATABASE=eSATURNUS acpi:ESS*: ID_VENDOR_FROM_DATABASE=ESS Technology Inc acpi:EST*: ID_VENDOR_FROM_DATABASE=Embedded Solution Technology acpi:ESY*: ID_VENDOR_FROM_DATABASE=E-Systems Inc acpi:ETC*: ID_VENDOR_FROM_DATABASE=Everton Technology Company Ltd acpi:ETD*: ID_VENDOR_FROM_DATABASE=ELAN MICROELECTRONICS CORPORATION acpi:ETH*: ID_VENDOR_FROM_DATABASE=Etherboot Project acpi:ETI*: ID_VENDOR_FROM_DATABASE=Eclipse Tech Inc acpi:ETK*: ID_VENDOR_FROM_DATABASE=eTEK Labs Inc. acpi:ETL*: ID_VENDOR_FROM_DATABASE=Evertz Microsystems Ltd. acpi:ETS*: ID_VENDOR_FROM_DATABASE=Electronic Trade Solutions Ltd acpi:ETT*: ID_VENDOR_FROM_DATABASE=E-Tech Inc acpi:EUT*: ID_VENDOR_FROM_DATABASE=Ericsson Mobile Networks B.V. acpi:EVE*: ID_VENDOR_FROM_DATABASE=Advanced Micro Peripherals Ltd acpi:EVI*: ID_VENDOR_FROM_DATABASE=eviateg GmbH acpi:EVX*: ID_VENDOR_FROM_DATABASE=Everex acpi:EXA*: ID_VENDOR_FROM_DATABASE=Exabyte acpi:EXC*: ID_VENDOR_FROM_DATABASE=Excession Audio acpi:EXI*: ID_VENDOR_FROM_DATABASE=Exide Electronics acpi:EXN*: ID_VENDOR_FROM_DATABASE=RGB Systems, Inc. dba Extron Electronics acpi:EXP*: ID_VENDOR_FROM_DATABASE=Data Export Corporation acpi:EXT*: ID_VENDOR_FROM_DATABASE=Exatech Computadores & Servicos Ltda acpi:EXX*: ID_VENDOR_FROM_DATABASE=Exxact GmbH acpi:EXY*: ID_VENDOR_FROM_DATABASE=Exterity Ltd acpi:EYE*: ID_VENDOR_FROM_DATABASE=eyevis GmbH acpi:EZE*: ID_VENDOR_FROM_DATABASE=EzE Technologies acpi:EZP*: ID_VENDOR_FROM_DATABASE=Storm Technology acpi:FAR*: ID_VENDOR_FROM_DATABASE=Farallon Computing acpi:FBI*: ID_VENDOR_FROM_DATABASE=Interface Corporation acpi:FCB*: ID_VENDOR_FROM_DATABASE=Furukawa Electric Company Ltd acpi:FCG*: ID_VENDOR_FROM_DATABASE=First International Computer Ltd acpi:FCS*: ID_VENDOR_FROM_DATABASE=Focus Enhancements, Inc. acpi:FDC*: ID_VENDOR_FROM_DATABASE=Future Domain acpi:FDT*: ID_VENDOR_FROM_DATABASE=Fujitsu Display Technologies Corp. acpi:FEC*: ID_VENDOR_FROM_DATABASE=FURUNO ELECTRIC CO., LTD. acpi:FEL*: ID_VENDOR_FROM_DATABASE=Fellowes & Questec acpi:FEN*: ID_VENDOR_FROM_DATABASE=Fen Systems Ltd. acpi:FER*: ID_VENDOR_FROM_DATABASE=Ferranti Int'L acpi:FFC*: ID_VENDOR_FROM_DATABASE=FUJIFILM Corporation acpi:FFI*: ID_VENDOR_FROM_DATABASE=Fairfield Industries acpi:FGD*: ID_VENDOR_FROM_DATABASE=Lisa Draexlmaier GmbH acpi:FGL*: ID_VENDOR_FROM_DATABASE=Fujitsu General Limited. acpi:FHL*: ID_VENDOR_FROM_DATABASE=FHLP acpi:FIC*: ID_VENDOR_FROM_DATABASE=Formosa Industrial Computing Inc acpi:FIL*: ID_VENDOR_FROM_DATABASE=Forefront Int'l Ltd acpi:FIN*: ID_VENDOR_FROM_DATABASE=Finecom Co., Ltd. acpi:FIR*: ID_VENDOR_FROM_DATABASE=Chaplet Systems Inc acpi:FIS*: ID_VENDOR_FROM_DATABASE=FLY-IT Simulators acpi:FIT*: ID_VENDOR_FROM_DATABASE=Feature Integration Technology Inc. acpi:FJC*: ID_VENDOR_FROM_DATABASE=Fujitsu Takamisawa Component Limited acpi:FJS*: ID_VENDOR_FROM_DATABASE=Fujitsu Spain acpi:FJT*: ID_VENDOR_FROM_DATABASE=F.J. Tieman BV acpi:FLE*: ID_VENDOR_FROM_DATABASE=ADTI Media, Inc acpi:FLI*: ID_VENDOR_FROM_DATABASE=Faroudja Laboratories acpi:FLY*: ID_VENDOR_FROM_DATABASE=Butterfly Communications acpi:FMA*: ID_VENDOR_FROM_DATABASE=Fast Multimedia AG acpi:FMC*: ID_VENDOR_FROM_DATABASE=Ford Microelectronics Inc acpi:FMI*: ID_VENDOR_FROM_DATABASE=Fujitsu Microelect Inc acpi:FML*: ID_VENDOR_FROM_DATABASE=Fujitsu Microelect Ltd acpi:FMZ*: ID_VENDOR_FROM_DATABASE=Formoza-Altair acpi:FNC*: ID_VENDOR_FROM_DATABASE=Fanuc LTD acpi:FNI*: ID_VENDOR_FROM_DATABASE=Funai Electric Co., Ltd. acpi:FOA*: ID_VENDOR_FROM_DATABASE=FOR-A Company Limited acpi:FOS*: ID_VENDOR_FROM_DATABASE=Foss Tecator acpi:FOX*: ID_VENDOR_FROM_DATABASE=HON HAI PRECISON IND.CO.,LTD. acpi:FPE*: ID_VENDOR_FROM_DATABASE=Fujitsu Peripherals Ltd acpi:FPS*: ID_VENDOR_FROM_DATABASE=Deltec Corporation acpi:FPX*: ID_VENDOR_FROM_DATABASE=Cirel Systemes acpi:FRC*: ID_VENDOR_FROM_DATABASE=Force Computers acpi:FRD*: ID_VENDOR_FROM_DATABASE=Freedom Scientific BLV acpi:FRE*: ID_VENDOR_FROM_DATABASE=Forvus Research Inc acpi:FRI*: ID_VENDOR_FROM_DATABASE=Fibernet Research Inc acpi:FRS*: ID_VENDOR_FROM_DATABASE=South Mountain Technologies, LTD acpi:FSC*: ID_VENDOR_FROM_DATABASE=Future Systems Consulting KK acpi:FSI*: ID_VENDOR_FROM_DATABASE=Fore Systems Inc acpi:FST*: ID_VENDOR_FROM_DATABASE=Modesto PC Inc acpi:FTC*: ID_VENDOR_FROM_DATABASE=Futuretouch Corporation acpi:FTE*: ID_VENDOR_FROM_DATABASE=Frontline Test Equipment Inc. acpi:FTG*: ID_VENDOR_FROM_DATABASE=FTG Data Systems acpi:FTI*: ID_VENDOR_FROM_DATABASE=FastPoint Technologies, Inc. acpi:FTL*: ID_VENDOR_FROM_DATABASE=FUJITSU TEN LIMITED acpi:FTN*: ID_VENDOR_FROM_DATABASE=Fountain Technologies Inc acpi:FTR*: ID_VENDOR_FROM_DATABASE=Mediasonic acpi:FTW*: ID_VENDOR_FROM_DATABASE=MindTribe Product Engineering, Inc. acpi:FUJ*: ID_VENDOR_FROM_DATABASE=Fujitsu Ltd acpi:FUN*: ID_VENDOR_FROM_DATABASE=sisel muhendislik acpi:FUS*: ID_VENDOR_FROM_DATABASE=Fujitsu Siemens Computers GmbH acpi:FVC*: ID_VENDOR_FROM_DATABASE=First Virtual Corporation acpi:FVX*: ID_VENDOR_FROM_DATABASE=C-C-C Group Plc acpi:FWA*: ID_VENDOR_FROM_DATABASE=Attero Tech, LLC acpi:FWR*: ID_VENDOR_FROM_DATABASE=Flat Connections Inc acpi:FXX*: ID_VENDOR_FROM_DATABASE=Fuji Xerox acpi:FZC*: ID_VENDOR_FROM_DATABASE=Founder Group Shenzhen Co. acpi:FZI*: ID_VENDOR_FROM_DATABASE=FZI Forschungszentrum Informatik acpi:GAG*: ID_VENDOR_FROM_DATABASE=Gage Applied Sciences Inc acpi:GAL*: ID_VENDOR_FROM_DATABASE=Galil Motion Control acpi:GAU*: ID_VENDOR_FROM_DATABASE=Gaudi Co., Ltd. acpi:GCC*: ID_VENDOR_FROM_DATABASE=GCC Technologies Inc acpi:GCI*: ID_VENDOR_FROM_DATABASE=Gateway Comm. Inc acpi:GCS*: ID_VENDOR_FROM_DATABASE=Grey Cell Systems Ltd acpi:GDC*: ID_VENDOR_FROM_DATABASE=General Datacom acpi:GDI*: ID_VENDOR_FROM_DATABASE=G. Diehl ISDN GmbH acpi:GDS*: ID_VENDOR_FROM_DATABASE=GDS acpi:GDT*: ID_VENDOR_FROM_DATABASE=Vortex Computersysteme GmbH acpi:GEF*: ID_VENDOR_FROM_DATABASE=GE Fanuc Embedded Systems acpi:GEH*: ID_VENDOR_FROM_DATABASE=GE Intelligent Platforms - Huntsville acpi:GEM*: ID_VENDOR_FROM_DATABASE=Gem Plus acpi:GEN*: ID_VENDOR_FROM_DATABASE=Genesys ATE Inc acpi:GEO*: ID_VENDOR_FROM_DATABASE=GEO Sense acpi:GER*: ID_VENDOR_FROM_DATABASE=GERMANEERS GmbH acpi:GES*: ID_VENDOR_FROM_DATABASE=GES Singapore Pte Ltd acpi:GET*: ID_VENDOR_FROM_DATABASE=Getac Technology Corporation acpi:GFM*: ID_VENDOR_FROM_DATABASE=GFMesstechnik GmbH acpi:GFN*: ID_VENDOR_FROM_DATABASE=Gefen Inc. acpi:GGL*: ID_VENDOR_FROM_DATABASE=Google Inc. acpi:GIC*: ID_VENDOR_FROM_DATABASE=General Inst. Corporation acpi:GIM*: ID_VENDOR_FROM_DATABASE=Guillemont International acpi:GIP*: ID_VENDOR_FROM_DATABASE=GI Provision Ltd acpi:GIS*: ID_VENDOR_FROM_DATABASE=AT&T Global Info Solutions acpi:GJN*: ID_VENDOR_FROM_DATABASE=Grand Junction Networks acpi:GLD*: ID_VENDOR_FROM_DATABASE=Goldmund - Digital Audio SA acpi:GLE*: ID_VENDOR_FROM_DATABASE=AD electronics acpi:GLM*: ID_VENDOR_FROM_DATABASE=Genesys Logic acpi:GLS*: ID_VENDOR_FROM_DATABASE=Gadget Labs LLC acpi:GMK*: ID_VENDOR_FROM_DATABASE=GMK Electronic Design GmbH acpi:GML*: ID_VENDOR_FROM_DATABASE=General Information Systems acpi:GMM*: ID_VENDOR_FROM_DATABASE=GMM Research Inc acpi:GMN*: ID_VENDOR_FROM_DATABASE=GEMINI 2000 Ltd acpi:GMX*: ID_VENDOR_FROM_DATABASE=GMX Inc acpi:GND*: ID_VENDOR_FROM_DATABASE=Gennum Corporation acpi:GNN*: ID_VENDOR_FROM_DATABASE=GN Nettest Inc acpi:GNZ*: ID_VENDOR_FROM_DATABASE=Gunze Ltd acpi:GRA*: ID_VENDOR_FROM_DATABASE=Graphica Computer acpi:GRE*: ID_VENDOR_FROM_DATABASE=GOLD RAIN ENTERPRISES CORP. acpi:GRH*: ID_VENDOR_FROM_DATABASE=Granch Ltd acpi:GRM*: ID_VENDOR_FROM_DATABASE=Garmin International acpi:GRV*: ID_VENDOR_FROM_DATABASE=Advanced Gravis acpi:GRY*: ID_VENDOR_FROM_DATABASE=Robert Gray Company acpi:GSB*: ID_VENDOR_FROM_DATABASE=NIPPONDENCHI CO,.LTD acpi:GSC*: ID_VENDOR_FROM_DATABASE=General Standards Corporation acpi:GSM*: ID_VENDOR_FROM_DATABASE=Goldstar Company Ltd acpi:GST*: ID_VENDOR_FROM_DATABASE=Graphic SystemTechnology acpi:GSY*: ID_VENDOR_FROM_DATABASE=Grossenbacher Systeme AG acpi:GTC*: ID_VENDOR_FROM_DATABASE=Graphtec Corporation acpi:GTI*: ID_VENDOR_FROM_DATABASE=Goldtouch acpi:GTK*: ID_VENDOR_FROM_DATABASE=G-Tech Corporation acpi:GTM*: ID_VENDOR_FROM_DATABASE=Garnet System Company Ltd acpi:GTS*: ID_VENDOR_FROM_DATABASE=Geotest Marvin Test Systems Inc acpi:GTT*: ID_VENDOR_FROM_DATABASE=General Touch Technology Co., Ltd. acpi:GUD*: ID_VENDOR_FROM_DATABASE=Guntermann & Drunck GmbH acpi:GUZ*: ID_VENDOR_FROM_DATABASE=Guzik Technical Enterprises acpi:GVC*: ID_VENDOR_FROM_DATABASE=GVC Corporation acpi:GVL*: ID_VENDOR_FROM_DATABASE=Global Village Communication acpi:GWI*: ID_VENDOR_FROM_DATABASE=GW Instruments acpi:GWY*: ID_VENDOR_FROM_DATABASE=Gateway 2000 acpi:GZE*: ID_VENDOR_FROM_DATABASE=GUNZE Limited acpi:HAE*: ID_VENDOR_FROM_DATABASE=Haider electronics acpi:HAI*: ID_VENDOR_FROM_DATABASE=Haivision Systems Inc. acpi:HAL*: ID_VENDOR_FROM_DATABASE=Halberthal acpi:HAN*: ID_VENDOR_FROM_DATABASE=Hanchang System Corporation acpi:HAR*: ID_VENDOR_FROM_DATABASE=Harris Corporation acpi:HAY*: ID_VENDOR_FROM_DATABASE=Hayes Microcomputer Products Inc acpi:HCA*: ID_VENDOR_FROM_DATABASE=DAT acpi:HCE*: ID_VENDOR_FROM_DATABASE=Hitachi Consumer Electronics Co., Ltd acpi:HCL*: ID_VENDOR_FROM_DATABASE=HCL America Inc acpi:HCM*: ID_VENDOR_FROM_DATABASE=HCL Peripherals acpi:HCP*: ID_VENDOR_FROM_DATABASE=Hitachi Computer Products Inc acpi:HCW*: ID_VENDOR_FROM_DATABASE=Hauppauge Computer Works Inc acpi:HDC*: ID_VENDOR_FROM_DATABASE=HardCom Elektronik & Datateknik acpi:HDI*: ID_VENDOR_FROM_DATABASE=HD-INFO d.o.o. acpi:HDV*: ID_VENDOR_FROM_DATABASE=Holografika kft. acpi:HEC*: ID_VENDOR_FROM_DATABASE=Hisense Electric Co., Ltd. acpi:HEL*: ID_VENDOR_FROM_DATABASE=Hitachi Micro Systems Europe Ltd acpi:HER*: ID_VENDOR_FROM_DATABASE=Ascom Business Systems acpi:HET*: ID_VENDOR_FROM_DATABASE=HETEC Datensysteme GmbH acpi:HHC*: ID_VENDOR_FROM_DATABASE=HIRAKAWA HEWTECH CORP. acpi:HHI*: ID_VENDOR_FROM_DATABASE=Fraunhofer Heinrich-Hertz-Institute acpi:HIB*: ID_VENDOR_FROM_DATABASE=Hibino Corporation acpi:HIC*: ID_VENDOR_FROM_DATABASE=Hitachi Information Technology Co., Ltd. acpi:HIK*: ID_VENDOR_FROM_DATABASE=Hikom Co., Ltd. acpi:HIL*: ID_VENDOR_FROM_DATABASE=Hilevel Technology acpi:HIQ*: ID_VENDOR_FROM_DATABASE=Kaohsiung Opto Electronics Americas, Inc. acpi:HIT*: ID_VENDOR_FROM_DATABASE=Hitachi America Ltd acpi:HJI*: ID_VENDOR_FROM_DATABASE=Harris & Jeffries Inc acpi:HKA*: ID_VENDOR_FROM_DATABASE=HONKO MFG. CO., LTD. acpi:HKG*: ID_VENDOR_FROM_DATABASE=Josef Heim KG acpi:HMC*: ID_VENDOR_FROM_DATABASE=Hualon Microelectric Corporation acpi:HMK*: ID_VENDOR_FROM_DATABASE=hmk Daten-System-Technik BmbH acpi:HMX*: ID_VENDOR_FROM_DATABASE=HUMAX Co., Ltd. acpi:HNS*: ID_VENDOR_FROM_DATABASE=Hughes Network Systems acpi:HOB*: ID_VENDOR_FROM_DATABASE=HOB Electronic GmbH acpi:HOE*: ID_VENDOR_FROM_DATABASE=Hosiden Corporation acpi:HOL*: ID_VENDOR_FROM_DATABASE=Holoeye Photonics AG acpi:HON*: ID_VENDOR_FROM_DATABASE=Sonitronix acpi:HPA*: ID_VENDOR_FROM_DATABASE=Zytor Communications acpi:HPC*: ID_VENDOR_FROM_DATABASE=Hewlett Packard Co. acpi:HPD*: ID_VENDOR_FROM_DATABASE=Hewlett Packard acpi:HPI*: ID_VENDOR_FROM_DATABASE=Headplay, Inc. acpi:HPK*: ID_VENDOR_FROM_DATABASE=HAMAMATSU PHOTONICS K.K. acpi:HPQ*: ID_VENDOR_FROM_DATABASE=HP acpi:HPR*: ID_VENDOR_FROM_DATABASE=H.P.R. Electronics GmbH acpi:HRC*: ID_VENDOR_FROM_DATABASE=Hercules acpi:HRE*: ID_VENDOR_FROM_DATABASE=Qingdao Haier Electronics Co., Ltd. acpi:HRI*: ID_VENDOR_FROM_DATABASE=Hall Research acpi:HRL*: ID_VENDOR_FROM_DATABASE=Herolab GmbH acpi:HRS*: ID_VENDOR_FROM_DATABASE=Harris Semiconductor acpi:HRT*: ID_VENDOR_FROM_DATABASE=HERCULES acpi:HSC*: ID_VENDOR_FROM_DATABASE=Hagiwara Sys-Com Company Ltd acpi:HSD*: ID_VENDOR_FROM_DATABASE=HannStar Display Corp acpi:HSM*: ID_VENDOR_FROM_DATABASE=AT&T Microelectronics acpi:HSP*: ID_VENDOR_FROM_DATABASE=HannStar Display Corp acpi:HTC*: ID_VENDOR_FROM_DATABASE=Hitachi Ltd acpi:HTI*: ID_VENDOR_FROM_DATABASE=Hampshire Company, Inc. acpi:HTK*: ID_VENDOR_FROM_DATABASE=Holtek Microelectronics Inc acpi:HTX*: ID_VENDOR_FROM_DATABASE=Hitex Systementwicklung GmbH acpi:HUB*: ID_VENDOR_FROM_DATABASE=GAI-Tronics, A Hubbell Company acpi:HUM*: ID_VENDOR_FROM_DATABASE=IMP Electronics Ltd. acpi:HWA*: ID_VENDOR_FROM_DATABASE=Harris Canada Inc acpi:HWC*: ID_VENDOR_FROM_DATABASE=DBA Hans Wedemeyer acpi:HWD*: ID_VENDOR_FROM_DATABASE=Highwater Designs Ltd acpi:HWP*: ID_VENDOR_FROM_DATABASE=Hewlett Packard acpi:HXM*: ID_VENDOR_FROM_DATABASE=Hexium Ltd. acpi:HYC*: ID_VENDOR_FROM_DATABASE=Hypercope Gmbh Aachen acpi:HYD*: ID_VENDOR_FROM_DATABASE=Hydis Technologies.Co.,LTD acpi:HYO*: ID_VENDOR_FROM_DATABASE=HYC CO., LTD. acpi:HYP*: ID_VENDOR_FROM_DATABASE=Hyphen Ltd acpi:HYR*: ID_VENDOR_FROM_DATABASE=Hypertec Pty Ltd acpi:HYT*: ID_VENDOR_FROM_DATABASE=Heng Yu Technology (HK) Limited acpi:HYV*: ID_VENDOR_FROM_DATABASE=Hynix Semiconductor acpi:IAF*: ID_VENDOR_FROM_DATABASE=Institut f r angewandte Funksystemtechnik GmbH acpi:IAI*: ID_VENDOR_FROM_DATABASE=Integration Associates, Inc. acpi:IAT*: ID_VENDOR_FROM_DATABASE=IAT Germany GmbH acpi:IBC*: ID_VENDOR_FROM_DATABASE=Integrated Business Systems acpi:IBI*: ID_VENDOR_FROM_DATABASE=INBINE.CO.LTD acpi:IBM*: ID_VENDOR_FROM_DATABASE=IBM acpi:IBP*: ID_VENDOR_FROM_DATABASE=IBP Instruments GmbH acpi:IBR*: ID_VENDOR_FROM_DATABASE=IBR GmbH acpi:ICA*: ID_VENDOR_FROM_DATABASE=ICA Inc acpi:ICC*: ID_VENDOR_FROM_DATABASE=BICC Data Networks Ltd acpi:ICD*: ID_VENDOR_FROM_DATABASE=ICD Inc acpi:ICE*: ID_VENDOR_FROM_DATABASE=IC Ensemble acpi:ICI*: ID_VENDOR_FROM_DATABASE=Infotek Communication Inc acpi:ICM*: ID_VENDOR_FROM_DATABASE=Intracom SA acpi:ICN*: ID_VENDOR_FROM_DATABASE=Sanyo Icon acpi:ICO*: ID_VENDOR_FROM_DATABASE=Intel Corp acpi:ICS*: ID_VENDOR_FROM_DATABASE=Integrated Circuit Systems acpi:ICV*: ID_VENDOR_FROM_DATABASE=Inside Contactless acpi:ICX*: ID_VENDOR_FROM_DATABASE=ICCC A/S acpi:IDC*: ID_VENDOR_FROM_DATABASE=International Datacasting Corporation acpi:IDE*: ID_VENDOR_FROM_DATABASE=IDE Associates acpi:IDK*: ID_VENDOR_FROM_DATABASE=IDK Corporation acpi:IDN*: ID_VENDOR_FROM_DATABASE=Idneo Technologies acpi:IDO*: ID_VENDOR_FROM_DATABASE=IDEO Product Development acpi:IDP*: ID_VENDOR_FROM_DATABASE=Integrated Device Technology, Inc. acpi:IDS*: ID_VENDOR_FROM_DATABASE=Interdigital Sistemas de Informacao acpi:IDT*: ID_VENDOR_FROM_DATABASE=International Display Technology acpi:IDX*: ID_VENDOR_FROM_DATABASE=IDEXX Labs acpi:IEC*: ID_VENDOR_FROM_DATABASE=Interlace Engineering Corporation acpi:IEE*: ID_VENDOR_FROM_DATABASE=IEE acpi:IEI*: ID_VENDOR_FROM_DATABASE=Interlink Electronics acpi:IFS*: ID_VENDOR_FROM_DATABASE=In Focus Systems Inc acpi:IFT*: ID_VENDOR_FROM_DATABASE=Informtech acpi:IFX*: ID_VENDOR_FROM_DATABASE=Infineon Technologies AG acpi:IFZ*: ID_VENDOR_FROM_DATABASE=Infinite Z acpi:IGC*: ID_VENDOR_FROM_DATABASE=Intergate Pty Ltd acpi:IGM*: ID_VENDOR_FROM_DATABASE=IGM Communi acpi:IHE*: ID_VENDOR_FROM_DATABASE=InHand Electronics acpi:IIC*: ID_VENDOR_FROM_DATABASE=ISIC Innoscan Industrial Computers A/S acpi:III*: ID_VENDOR_FROM_DATABASE=Intelligent Instrumentation acpi:IIN*: ID_VENDOR_FROM_DATABASE=IINFRA Co., Ltd acpi:IKS*: ID_VENDOR_FROM_DATABASE=Ikos Systems Inc acpi:ILC*: ID_VENDOR_FROM_DATABASE=Image Logic Corporation acpi:ILS*: ID_VENDOR_FROM_DATABASE=Innotech Corporation acpi:IMA*: ID_VENDOR_FROM_DATABASE=Imagraph acpi:IMB*: ID_VENDOR_FROM_DATABASE=ART s.r.l. acpi:IMC*: ID_VENDOR_FROM_DATABASE=IMC Networks acpi:IMD*: ID_VENDOR_FROM_DATABASE=ImasDe Canarias S.A. acpi:IME*: ID_VENDOR_FROM_DATABASE=Imagraph acpi:IMG*: ID_VENDOR_FROM_DATABASE=IMAGENICS Co., Ltd. acpi:IMI*: ID_VENDOR_FROM_DATABASE=International Microsystems Inc acpi:IMM*: ID_VENDOR_FROM_DATABASE=Immersion Corporation acpi:IMN*: ID_VENDOR_FROM_DATABASE=Impossible Production acpi:IMP*: ID_VENDOR_FROM_DATABASE=Impression Products Incorporated acpi:IMT*: ID_VENDOR_FROM_DATABASE=Inmax Technology Corporation acpi:INC*: ID_VENDOR_FROM_DATABASE=Home Row Inc acpi:IND*: ID_VENDOR_FROM_DATABASE=ILC acpi:INE*: ID_VENDOR_FROM_DATABASE=Inventec Electronics (M) Sdn. Bhd. acpi:INF*: ID_VENDOR_FROM_DATABASE=Inframetrics Inc acpi:ING*: ID_VENDOR_FROM_DATABASE=Integraph Corporation acpi:INI*: ID_VENDOR_FROM_DATABASE=Initio Corporation acpi:INK*: ID_VENDOR_FROM_DATABASE=Indtek Co., Ltd. acpi:INL*: ID_VENDOR_FROM_DATABASE=InnoLux Display Corporation acpi:INM*: ID_VENDOR_FROM_DATABASE=InnoMedia Inc acpi:INN*: ID_VENDOR_FROM_DATABASE=Innovent Systems, Inc. acpi:INO*: ID_VENDOR_FROM_DATABASE=Innolab Pte Ltd acpi:INP*: ID_VENDOR_FROM_DATABASE=Interphase Corporation acpi:INS*: ID_VENDOR_FROM_DATABASE=Ines GmbH acpi:INT*: ID_VENDOR_FROM_DATABASE=Interphase Corporation acpi:inu*: ID_VENDOR_FROM_DATABASE=Inovatec S.p.A. acpi:INV*: ID_VENDOR_FROM_DATABASE=Inviso, Inc. acpi:INZ*: ID_VENDOR_FROM_DATABASE=Best Buy acpi:IOA*: ID_VENDOR_FROM_DATABASE=CRE Technology Corporation acpi:IOD*: ID_VENDOR_FROM_DATABASE=I-O Data Device Inc acpi:IOM*: ID_VENDOR_FROM_DATABASE=Iomega acpi:ION*: ID_VENDOR_FROM_DATABASE=Inside Out Networks acpi:IOS*: ID_VENDOR_FROM_DATABASE=i-O Display System acpi:IOT*: ID_VENDOR_FROM_DATABASE=I/OTech Inc acpi:IPC*: ID_VENDOR_FROM_DATABASE=IPC Corporation acpi:IPD*: ID_VENDOR_FROM_DATABASE=Industrial Products Design, Inc. acpi:IPI*: ID_VENDOR_FROM_DATABASE=Intelligent Platform Management Interface (IPMI) forum (Intel, HP, NEC, Dell) acpi:IPM*: ID_VENDOR_FROM_DATABASE=IPM Industria Politecnica Meridionale SpA acpi:IPN*: ID_VENDOR_FROM_DATABASE=Performance Technologies acpi:IPP*: ID_VENDOR_FROM_DATABASE=IP Power Technologies GmbH acpi:IPR*: ID_VENDOR_FROM_DATABASE=Ithaca Peripherals acpi:IPS*: ID_VENDOR_FROM_DATABASE=IPS, Inc. (Intellectual Property Solutions, Inc.) acpi:IPT*: ID_VENDOR_FROM_DATABASE=International Power Technologies acpi:IPW*: ID_VENDOR_FROM_DATABASE=IPWireless, Inc acpi:IQI*: ID_VENDOR_FROM_DATABASE=IneoQuest Technologies, Inc acpi:IQT*: ID_VENDOR_FROM_DATABASE=IMAGEQUEST Co., Ltd acpi:IRD*: ID_VENDOR_FROM_DATABASE=IRdata acpi:ISA*: ID_VENDOR_FROM_DATABASE=Symbol Technologies acpi:ISC*: ID_VENDOR_FROM_DATABASE=Id3 Semiconductors acpi:ISG*: ID_VENDOR_FROM_DATABASE=Insignia Solutions Inc acpi:ISI*: ID_VENDOR_FROM_DATABASE=Interface Solutions acpi:ISL*: ID_VENDOR_FROM_DATABASE=Isolation Systems acpi:ISM*: ID_VENDOR_FROM_DATABASE=Image Stream Medical acpi:ISP*: ID_VENDOR_FROM_DATABASE=IntreSource Systems Pte Ltd acpi:ISR*: ID_VENDOR_FROM_DATABASE=INSIS Co., LTD. acpi:ISS*: ID_VENDOR_FROM_DATABASE=ISS Inc acpi:IST*: ID_VENDOR_FROM_DATABASE=Intersolve Technologies acpi:ISY*: ID_VENDOR_FROM_DATABASE=International Integrated Systems,Inc.(IISI) acpi:ITA*: ID_VENDOR_FROM_DATABASE=Itausa Export North America acpi:ITC*: ID_VENDOR_FROM_DATABASE=Intercom Inc acpi:ITD*: ID_VENDOR_FROM_DATABASE=Internet Technology Corporation acpi:ITE*: ID_VENDOR_FROM_DATABASE=Integrated Tech Express Inc acpi:ITK*: ID_VENDOR_FROM_DATABASE=ITK Telekommunikation AG acpi:ITL*: ID_VENDOR_FROM_DATABASE=Inter-Tel acpi:ITM*: ID_VENDOR_FROM_DATABASE=ITM inc. acpi:ITN*: ID_VENDOR_FROM_DATABASE=The NTI Group acpi:ITP*: ID_VENDOR_FROM_DATABASE=IT-PRO Consulting und Systemhaus GmbH acpi:ITR*: ID_VENDOR_FROM_DATABASE=Infotronic America, Inc. acpi:ITS*: ID_VENDOR_FROM_DATABASE=IDTECH acpi:ITT*: ID_VENDOR_FROM_DATABASE=I&T Telecom. acpi:ITX*: ID_VENDOR_FROM_DATABASE=integrated Technology Express Inc acpi:IUC*: ID_VENDOR_FROM_DATABASE=ICSL acpi:IVI*: ID_VENDOR_FROM_DATABASE=Intervoice Inc acpi:IVM*: ID_VENDOR_FROM_DATABASE=Iiyama North America acpi:IVS*: ID_VENDOR_FROM_DATABASE=Intevac Photonics Inc. acpi:IWR*: ID_VENDOR_FROM_DATABASE=Icuiti Corporation acpi:IWX*: ID_VENDOR_FROM_DATABASE=Intelliworxx, Inc. acpi:IXD*: ID_VENDOR_FROM_DATABASE=Intertex Data AB acpi:JAC*: ID_VENDOR_FROM_DATABASE=Astec Inc acpi:JAE*: ID_VENDOR_FROM_DATABASE=Japan Aviation Electronics Industry, Limited acpi:JAS*: ID_VENDOR_FROM_DATABASE=Janz Automationssysteme AG acpi:JAT*: ID_VENDOR_FROM_DATABASE=Jaton Corporation acpi:JAZ*: ID_VENDOR_FROM_DATABASE=Carrera Computer Inc acpi:JCE*: ID_VENDOR_FROM_DATABASE=Jace Tech Inc acpi:JDL*: ID_VENDOR_FROM_DATABASE=Japan Digital Laboratory Co.,Ltd. acpi:JEN*: ID_VENDOR_FROM_DATABASE=N-Vision acpi:JET*: ID_VENDOR_FROM_DATABASE=JET POWER TECHNOLOGY CO., LTD. acpi:JFX*: ID_VENDOR_FROM_DATABASE=Jones Futurex Inc acpi:JGD*: ID_VENDOR_FROM_DATABASE=University College acpi:JIC*: ID_VENDOR_FROM_DATABASE=Jaeik Information & Communication Co., Ltd. acpi:JKC*: ID_VENDOR_FROM_DATABASE=JVC KENWOOD Corporation acpi:JMT*: ID_VENDOR_FROM_DATABASE=Micro Technical Company Ltd acpi:JPC*: ID_VENDOR_FROM_DATABASE=JPC Technology Limited acpi:JPW*: ID_VENDOR_FROM_DATABASE=Wallis Hamilton Industries acpi:JQE*: ID_VENDOR_FROM_DATABASE=CNet Technical Inc acpi:JSD*: ID_VENDOR_FROM_DATABASE=JS DigiTech, Inc acpi:JSI*: ID_VENDOR_FROM_DATABASE=Jupiter Systems, Inc. acpi:JSK*: ID_VENDOR_FROM_DATABASE=SANKEN ELECTRIC CO., LTD acpi:JTS*: ID_VENDOR_FROM_DATABASE=JS Motorsports acpi:JTY*: ID_VENDOR_FROM_DATABASE=jetway security micro,inc acpi:JUK*: ID_VENDOR_FROM_DATABASE=Janich & Klass Computertechnik GmbH acpi:JUP*: ID_VENDOR_FROM_DATABASE=Jupiter Systems acpi:JVC*: ID_VENDOR_FROM_DATABASE=JVC acpi:JWD*: ID_VENDOR_FROM_DATABASE=Video International Inc. acpi:JWL*: ID_VENDOR_FROM_DATABASE=Jewell Instruments, LLC acpi:JWS*: ID_VENDOR_FROM_DATABASE=JWSpencer & Co. acpi:JWY*: ID_VENDOR_FROM_DATABASE=Jetway Information Co., Ltd acpi:KAR*: ID_VENDOR_FROM_DATABASE=Karna acpi:KBI*: ID_VENDOR_FROM_DATABASE=Kidboard Inc acpi:KBL*: ID_VENDOR_FROM_DATABASE=Kobil Systems GmbH acpi:KCD*: ID_VENDOR_FROM_DATABASE=Chunichi Denshi Co.,LTD. acpi:KCL*: ID_VENDOR_FROM_DATABASE=Keycorp Ltd acpi:KDE*: ID_VENDOR_FROM_DATABASE=KDE acpi:KDK*: ID_VENDOR_FROM_DATABASE=Kodiak Tech acpi:KDM*: ID_VENDOR_FROM_DATABASE=Korea Data Systems Co., Ltd. acpi:KDS*: ID_VENDOR_FROM_DATABASE=KDS USA acpi:KDT*: ID_VENDOR_FROM_DATABASE=KDDI Technology Corporation acpi:KEC*: ID_VENDOR_FROM_DATABASE=Kyushu Electronics Systems Inc acpi:KEM*: ID_VENDOR_FROM_DATABASE=Kontron Embedded Modules GmbH acpi:KES*: ID_VENDOR_FROM_DATABASE=Kesa Corporation acpi:KEY*: ID_VENDOR_FROM_DATABASE=Key Tech Inc acpi:KFC*: ID_VENDOR_FROM_DATABASE=SCD Tech acpi:KFE*: ID_VENDOR_FROM_DATABASE=Komatsu Forest acpi:KFX*: ID_VENDOR_FROM_DATABASE=Kofax Image Products acpi:KGL*: ID_VENDOR_FROM_DATABASE=KEISOKU GIKEN Co.,Ltd. acpi:KIS*: ID_VENDOR_FROM_DATABASE=KiSS Technology A/S acpi:KMC*: ID_VENDOR_FROM_DATABASE=Mitsumi Company Ltd acpi:KME*: ID_VENDOR_FROM_DATABASE=KIMIN Electronics Co., Ltd. acpi:KML*: ID_VENDOR_FROM_DATABASE=Kensington Microware Ltd acpi:KNC*: ID_VENDOR_FROM_DATABASE=Konica corporation acpi:KNX*: ID_VENDOR_FROM_DATABASE=Nutech Marketing PTL acpi:KOB*: ID_VENDOR_FROM_DATABASE=Kobil Systems GmbH acpi:KOD*: ID_VENDOR_FROM_DATABASE=Eastman Kodak Company acpi:KOE*: ID_VENDOR_FROM_DATABASE=KOLTER ELECTRONIC acpi:KOL*: ID_VENDOR_FROM_DATABASE=Kollmorgen Motion Technologies Group acpi:KOU*: ID_VENDOR_FROM_DATABASE=KOUZIRO Co.,Ltd. acpi:KOW*: ID_VENDOR_FROM_DATABASE=KOWA Company,LTD. acpi:KPC*: ID_VENDOR_FROM_DATABASE=King Phoenix Company acpi:KRL*: ID_VENDOR_FROM_DATABASE=Krell Industries Inc. acpi:KRM*: ID_VENDOR_FROM_DATABASE=Kroma Telecom acpi:KRY*: ID_VENDOR_FROM_DATABASE=Kroy LLC acpi:KSC*: ID_VENDOR_FROM_DATABASE=Kinetic Systems Corporation acpi:KSL*: ID_VENDOR_FROM_DATABASE=Karn Solutions Ltd. acpi:KSX*: ID_VENDOR_FROM_DATABASE=King Tester Corporation acpi:KTC*: ID_VENDOR_FROM_DATABASE=Kingston Tech Corporation acpi:KTD*: ID_VENDOR_FROM_DATABASE=Takahata Electronics Co.,Ltd. acpi:KTE*: ID_VENDOR_FROM_DATABASE=K-Tech acpi:KTG*: ID_VENDOR_FROM_DATABASE=Kayser-Threde GmbH acpi:KTI*: ID_VENDOR_FROM_DATABASE=Konica Technical Inc acpi:KTK*: ID_VENDOR_FROM_DATABASE=Key Tronic Corporation acpi:KTN*: ID_VENDOR_FROM_DATABASE=Katron Tech Inc acpi:KUR*: ID_VENDOR_FROM_DATABASE=Kurta Corporation acpi:KVA*: ID_VENDOR_FROM_DATABASE=Kvaser AB acpi:KVX*: ID_VENDOR_FROM_DATABASE=KeyView acpi:KWD*: ID_VENDOR_FROM_DATABASE=Kenwood Corporation acpi:KYC*: ID_VENDOR_FROM_DATABASE=Kyocera Corporation acpi:KYE*: ID_VENDOR_FROM_DATABASE=KYE Syst Corporation acpi:KYK*: ID_VENDOR_FROM_DATABASE=Samsung Electronics America Inc acpi:KZI*: ID_VENDOR_FROM_DATABASE=K-Zone International co. Ltd. acpi:KZN*: ID_VENDOR_FROM_DATABASE=K-Zone International acpi:LAB*: ID_VENDOR_FROM_DATABASE=ACT Labs Ltd acpi:LAC*: ID_VENDOR_FROM_DATABASE=LaCie acpi:LAF*: ID_VENDOR_FROM_DATABASE=Microline acpi:LAG*: ID_VENDOR_FROM_DATABASE=Laguna Systems acpi:LAN*: ID_VENDOR_FROM_DATABASE=Sodeman Lancom Inc acpi:LAS*: ID_VENDOR_FROM_DATABASE=LASAT Comm. A/S acpi:LAV*: ID_VENDOR_FROM_DATABASE=Lava Computer MFG Inc acpi:LBO*: ID_VENDOR_FROM_DATABASE=Lubosoft acpi:LCC*: ID_VENDOR_FROM_DATABASE=LCI acpi:LCD*: ID_VENDOR_FROM_DATABASE=Toshiba Matsushita Display Technology Co., Ltd acpi:LCE*: ID_VENDOR_FROM_DATABASE=La Commande Electronique acpi:LCI*: ID_VENDOR_FROM_DATABASE=Lite-On Communication Inc acpi:LCM*: ID_VENDOR_FROM_DATABASE=Latitude Comm. acpi:LCN*: ID_VENDOR_FROM_DATABASE=LEXICON acpi:LCS*: ID_VENDOR_FROM_DATABASE=Longshine Electronics Company acpi:LCT*: ID_VENDOR_FROM_DATABASE=Labcal Technologies acpi:LDT*: ID_VENDOR_FROM_DATABASE=LogiDataTech Electronic GmbH acpi:LEC*: ID_VENDOR_FROM_DATABASE=Lectron Company Ltd acpi:LED*: ID_VENDOR_FROM_DATABASE=Long Engineering Design Inc acpi:LEG*: ID_VENDOR_FROM_DATABASE=Legerity, Inc acpi:LEN*: ID_VENDOR_FROM_DATABASE=Lenovo Group Limited acpi:LEO*: ID_VENDOR_FROM_DATABASE=First International Computer Inc acpi:LEX*: ID_VENDOR_FROM_DATABASE=Lexical Ltd acpi:LGC*: ID_VENDOR_FROM_DATABASE=Logic Ltd acpi:LGI*: ID_VENDOR_FROM_DATABASE=Logitech Inc acpi:LGS*: ID_VENDOR_FROM_DATABASE=LG Semicom Company Ltd acpi:LGX*: ID_VENDOR_FROM_DATABASE=Lasergraphics, Inc. acpi:LHA*: ID_VENDOR_FROM_DATABASE=Lars Haagh ApS acpi:LHE*: ID_VENDOR_FROM_DATABASE=Lung Hwa Electronics Company Ltd acpi:LHT*: ID_VENDOR_FROM_DATABASE=Lighthouse Technologies Limited acpi:LIN*: ID_VENDOR_FROM_DATABASE=Lenovo Beijing Co. Ltd. acpi:LIP*: ID_VENDOR_FROM_DATABASE=Linked IP GmbH acpi:LIT*: ID_VENDOR_FROM_DATABASE=Lithics Silicon Technology acpi:LJX*: ID_VENDOR_FROM_DATABASE=Datalogic Corporation acpi:LKM*: ID_VENDOR_FROM_DATABASE=Likom Technology Sdn. Bhd. acpi:LLL*: ID_VENDOR_FROM_DATABASE=L-3 Communications acpi:LMG*: ID_VENDOR_FROM_DATABASE=Lucent Technologies acpi:LMI*: ID_VENDOR_FROM_DATABASE=Lexmark Int'l Inc acpi:LMP*: ID_VENDOR_FROM_DATABASE=Leda Media Products acpi:LMT*: ID_VENDOR_FROM_DATABASE=Laser Master acpi:LND*: ID_VENDOR_FROM_DATABASE=Land Computer Company Ltd acpi:LNK*: ID_VENDOR_FROM_DATABASE=Link Tech Inc acpi:LNR*: ID_VENDOR_FROM_DATABASE=Linear Systems Ltd. acpi:LNT*: ID_VENDOR_FROM_DATABASE=LANETCO International acpi:LNV*: ID_VENDOR_FROM_DATABASE=Lenovo acpi:LOC*: ID_VENDOR_FROM_DATABASE=Locamation B.V. acpi:LOE*: ID_VENDOR_FROM_DATABASE=Loewe Opta GmbH acpi:LOG*: ID_VENDOR_FROM_DATABASE=Logicode Technology Inc acpi:LOL*: ID_VENDOR_FROM_DATABASE=Litelogic Operations Ltd acpi:LPE*: ID_VENDOR_FROM_DATABASE=El-PUSK Co., Ltd. acpi:LPI*: ID_VENDOR_FROM_DATABASE=Design Technology acpi:LSC*: ID_VENDOR_FROM_DATABASE=LifeSize Communications acpi:LSD*: ID_VENDOR_FROM_DATABASE=Intersil Corporation acpi:LSI*: ID_VENDOR_FROM_DATABASE=Loughborough Sound Images acpi:LSJ*: ID_VENDOR_FROM_DATABASE=LSI Japan Company Ltd acpi:LSL*: ID_VENDOR_FROM_DATABASE=Logical Solutions acpi:LSY*: ID_VENDOR_FROM_DATABASE=LSI Systems Inc acpi:LTC*: ID_VENDOR_FROM_DATABASE=Labtec Inc acpi:LTI*: ID_VENDOR_FROM_DATABASE=Jongshine Tech Inc acpi:LTK*: ID_VENDOR_FROM_DATABASE=Lucidity Technology Company Ltd acpi:LTN*: ID_VENDOR_FROM_DATABASE=Litronic Inc acpi:LTS*: ID_VENDOR_FROM_DATABASE=LTS Scale LLC acpi:LTV*: ID_VENDOR_FROM_DATABASE=Leitch Technology International Inc. acpi:LTW*: ID_VENDOR_FROM_DATABASE=Lightware, Inc acpi:LUC*: ID_VENDOR_FROM_DATABASE=Lucent Technologies acpi:LUM*: ID_VENDOR_FROM_DATABASE=Lumagen, Inc. acpi:LUX*: ID_VENDOR_FROM_DATABASE=Luxxell Research Inc acpi:LVI*: ID_VENDOR_FROM_DATABASE=LVI Low Vision International AB acpi:LWC*: ID_VENDOR_FROM_DATABASE=Labway Corporation acpi:LWR*: ID_VENDOR_FROM_DATABASE=Lightware Visual Engineering acpi:LWW*: ID_VENDOR_FROM_DATABASE=Lanier Worldwide acpi:LXC*: ID_VENDOR_FROM_DATABASE=LXCO Technologies AG acpi:LXN*: ID_VENDOR_FROM_DATABASE=Luxeon acpi:LXS*: ID_VENDOR_FROM_DATABASE=ELEA CardWare acpi:LZX*: ID_VENDOR_FROM_DATABASE=Lightwell Company Ltd acpi:MAC*: ID_VENDOR_FROM_DATABASE=MAC System Company Ltd acpi:MAD*: ID_VENDOR_FROM_DATABASE=Xedia Corporation acpi:MAE*: ID_VENDOR_FROM_DATABASE=Maestro Pty Ltd acpi:MAG*: ID_VENDOR_FROM_DATABASE=MAG InnoVision acpi:MAI*: ID_VENDOR_FROM_DATABASE=Mutoh America Inc acpi:MAL*: ID_VENDOR_FROM_DATABASE=Meridian Audio Ltd acpi:MAN*: ID_VENDOR_FROM_DATABASE=LGIC acpi:MAS*: ID_VENDOR_FROM_DATABASE=Mass Inc. acpi:MAT*: ID_VENDOR_FROM_DATABASE=Matsushita Electric Ind. Company Ltd acpi:MAX*: ID_VENDOR_FROM_DATABASE=Rogen Tech Distribution Inc acpi:MAY*: ID_VENDOR_FROM_DATABASE=Maynard Electronics acpi:MAZ*: ID_VENDOR_FROM_DATABASE=MAZeT GmbH acpi:MBC*: ID_VENDOR_FROM_DATABASE=MBC acpi:MBD*: ID_VENDOR_FROM_DATABASE=Microbus PLC acpi:MBM*: ID_VENDOR_FROM_DATABASE=Marshall Electronics acpi:MBV*: ID_VENDOR_FROM_DATABASE=Moreton Bay acpi:MCA*: ID_VENDOR_FROM_DATABASE=American Nuclear Systems Inc acpi:MCC*: ID_VENDOR_FROM_DATABASE=Micro Industries acpi:MCD*: ID_VENDOR_FROM_DATABASE=McDATA Corporation acpi:MCE*: ID_VENDOR_FROM_DATABASE=Metz-Werke GmbH & Co KG acpi:MCG*: ID_VENDOR_FROM_DATABASE=Motorola Computer Group acpi:MCI*: ID_VENDOR_FROM_DATABASE=Micronics Computers acpi:MCL*: ID_VENDOR_FROM_DATABASE=Motorola Communications Israel acpi:MCM*: ID_VENDOR_FROM_DATABASE=Metricom Inc acpi:MCN*: ID_VENDOR_FROM_DATABASE=Micron Electronics Inc acpi:MCO*: ID_VENDOR_FROM_DATABASE=Motion Computing Inc. acpi:MCP*: ID_VENDOR_FROM_DATABASE=Magni Systems Inc acpi:MCQ*: ID_VENDOR_FROM_DATABASE=Mat's Computers acpi:MCR*: ID_VENDOR_FROM_DATABASE=Marina Communicaitons acpi:MCS*: ID_VENDOR_FROM_DATABASE=Micro Computer Systems acpi:MCT*: ID_VENDOR_FROM_DATABASE=Microtec acpi:MDA*: ID_VENDOR_FROM_DATABASE=Media4 Inc acpi:MDC*: ID_VENDOR_FROM_DATABASE=Midori Electronics acpi:MDD*: ID_VENDOR_FROM_DATABASE=MODIS acpi:MDG*: ID_VENDOR_FROM_DATABASE=Madge Networks acpi:MDI*: ID_VENDOR_FROM_DATABASE=Micro Design Inc acpi:MDK*: ID_VENDOR_FROM_DATABASE=Mediatek Corporation acpi:MDO*: ID_VENDOR_FROM_DATABASE=Panasonic acpi:MDR*: ID_VENDOR_FROM_DATABASE=Medar Inc acpi:MDS*: ID_VENDOR_FROM_DATABASE=Micro Display Systems Inc acpi:MDT*: ID_VENDOR_FROM_DATABASE=Magus Data Tech acpi:MDV*: ID_VENDOR_FROM_DATABASE=MET Development Inc acpi:MDX*: ID_VENDOR_FROM_DATABASE=MicroDatec GmbH acpi:MDY*: ID_VENDOR_FROM_DATABASE=Microdyne Inc acpi:MEC*: ID_VENDOR_FROM_DATABASE=Mega System Technologies Inc acpi:MED*: ID_VENDOR_FROM_DATABASE=Messeltronik Dresden GmbH acpi:MEE*: ID_VENDOR_FROM_DATABASE=Mitsubishi Electric Engineering Co., Ltd. acpi:MEG*: ID_VENDOR_FROM_DATABASE=Abeam Tech Ltd acpi:MEI*: ID_VENDOR_FROM_DATABASE=Panasonic Industry Company acpi:MEJ*: ID_VENDOR_FROM_DATABASE=Mac-Eight Co., LTD. acpi:MEL*: ID_VENDOR_FROM_DATABASE=Mitsubishi Electric Corporation acpi:MEN*: ID_VENDOR_FROM_DATABASE=MEN Mikroelectronik Nueruberg GmbH acpi:MEQ*: ID_VENDOR_FROM_DATABASE=Matelect Ltd. acpi:MET*: ID_VENDOR_FROM_DATABASE=Metheus Corporation acpi:MEX*: ID_VENDOR_FROM_DATABASE=MSC Vertriebs GmbH acpi:MFG*: ID_VENDOR_FROM_DATABASE=MicroField Graphics Inc acpi:MFI*: ID_VENDOR_FROM_DATABASE=Micro Firmware acpi:MFR*: ID_VENDOR_FROM_DATABASE=MediaFire Corp. acpi:MGA*: ID_VENDOR_FROM_DATABASE=Mega System Technologies, Inc. acpi:MGC*: ID_VENDOR_FROM_DATABASE=Mentor Graphics Corporation acpi:MGE*: ID_VENDOR_FROM_DATABASE=Schneider Electric S.A. acpi:MGL*: ID_VENDOR_FROM_DATABASE=M-G Technology Ltd acpi:MGT*: ID_VENDOR_FROM_DATABASE=Megatech R & D Company acpi:MIC*: ID_VENDOR_FROM_DATABASE=Micom Communications Inc acpi:MID*: ID_VENDOR_FROM_DATABASE=miro Displays acpi:MII*: ID_VENDOR_FROM_DATABASE=Mitec Inc acpi:MIL*: ID_VENDOR_FROM_DATABASE=Marconi Instruments Ltd acpi:MIM*: ID_VENDOR_FROM_DATABASE=Mimio – A Newell Rubbermaid Company acpi:MIN*: ID_VENDOR_FROM_DATABASE=Minicom Digital Signage acpi:MIP*: ID_VENDOR_FROM_DATABASE=micronpc.com acpi:MIR*: ID_VENDOR_FROM_DATABASE=Miro Computer Prod. acpi:MIS*: ID_VENDOR_FROM_DATABASE=Modular Industrial Solutions Inc acpi:MIT*: ID_VENDOR_FROM_DATABASE=MCM Industrial Technology GmbH acpi:MJI*: ID_VENDOR_FROM_DATABASE=MARANTZ JAPAN, INC. acpi:MJS*: ID_VENDOR_FROM_DATABASE=MJS Designs acpi:MKC*: ID_VENDOR_FROM_DATABASE=Media Tek Inc. acpi:MKT*: ID_VENDOR_FROM_DATABASE=MICROTEK Inc. acpi:MKV*: ID_VENDOR_FROM_DATABASE=Trtheim Technology acpi:MLD*: ID_VENDOR_FROM_DATABASE=Deep Video Imaging Ltd acpi:MLG*: ID_VENDOR_FROM_DATABASE=Micrologica AG acpi:MLI*: ID_VENDOR_FROM_DATABASE=McIntosh Laboratory Inc. acpi:MLM*: ID_VENDOR_FROM_DATABASE=Millennium Engineering Inc acpi:MLN*: ID_VENDOR_FROM_DATABASE=Mark Levinson acpi:MLS*: ID_VENDOR_FROM_DATABASE=Milestone EPE acpi:MLX*: ID_VENDOR_FROM_DATABASE=Mylex Corporation acpi:MMA*: ID_VENDOR_FROM_DATABASE=Micromedia AG acpi:MMD*: ID_VENDOR_FROM_DATABASE=Micromed Biotecnologia Ltd acpi:MMF*: ID_VENDOR_FROM_DATABASE=Minnesota Mining and Manufacturing acpi:MMI*: ID_VENDOR_FROM_DATABASE=Multimax acpi:MMM*: ID_VENDOR_FROM_DATABASE=Electronic Measurements acpi:MMN*: ID_VENDOR_FROM_DATABASE=MiniMan Inc acpi:MMS*: ID_VENDOR_FROM_DATABASE=MMS Electronics acpi:MNC*: ID_VENDOR_FROM_DATABASE=Mini Micro Methods Ltd acpi:MNL*: ID_VENDOR_FROM_DATABASE=Monorail Inc acpi:MNP*: ID_VENDOR_FROM_DATABASE=Microcom acpi:MOD*: ID_VENDOR_FROM_DATABASE=Modular Technology acpi:MOM*: ID_VENDOR_FROM_DATABASE=Momentum Data Systems acpi:MOS*: ID_VENDOR_FROM_DATABASE=Moses Corporation acpi:MOT*: ID_VENDOR_FROM_DATABASE=Motorola UDS acpi:MPC*: ID_VENDOR_FROM_DATABASE=M-Pact Inc acpi:MPI*: ID_VENDOR_FROM_DATABASE=Mediatrix Peripherals Inc acpi:MPJ*: ID_VENDOR_FROM_DATABASE=Microlab acpi:MPL*: ID_VENDOR_FROM_DATABASE=Maple Research Inst. Company Ltd acpi:MPN*: ID_VENDOR_FROM_DATABASE=Mainpine Limited acpi:MPS*: ID_VENDOR_FROM_DATABASE=mps Software GmbH acpi:MPX*: ID_VENDOR_FROM_DATABASE=Micropix Technologies, Ltd. acpi:MQP*: ID_VENDOR_FROM_DATABASE=MultiQ Products AB acpi:MRA*: ID_VENDOR_FROM_DATABASE=Miranda Technologies Inc acpi:MRC*: ID_VENDOR_FROM_DATABASE=Marconi Simulation & Ty-Coch Way Training acpi:MRD*: ID_VENDOR_FROM_DATABASE=MicroDisplay Corporation acpi:MRK*: ID_VENDOR_FROM_DATABASE=Maruko & Company Ltd acpi:MRL*: ID_VENDOR_FROM_DATABASE=Miratel acpi:MRO*: ID_VENDOR_FROM_DATABASE=Medikro Oy acpi:MRT*: ID_VENDOR_FROM_DATABASE=Merging Technologies acpi:MSA*: ID_VENDOR_FROM_DATABASE=Micro Systemation AB acpi:MSC*: ID_VENDOR_FROM_DATABASE=Mouse Systems Corporation acpi:MSD*: ID_VENDOR_FROM_DATABASE=Datenerfassungs- und Informationssysteme acpi:MSF*: ID_VENDOR_FROM_DATABASE=M-Systems Flash Disk Pioneers acpi:MSG*: ID_VENDOR_FROM_DATABASE=MSI GmbH acpi:MSH*: ID_VENDOR_FROM_DATABASE=Microsoft acpi:MSI*: ID_VENDOR_FROM_DATABASE=Microstep acpi:MSK*: ID_VENDOR_FROM_DATABASE=Megasoft Inc acpi:MSL*: ID_VENDOR_FROM_DATABASE=MicroSlate Inc. acpi:MSM*: ID_VENDOR_FROM_DATABASE=Advanced Digital Systems acpi:MSP*: ID_VENDOR_FROM_DATABASE=Mistral Solutions [P] Ltd. acpi:MST*: ID_VENDOR_FROM_DATABASE=MS Telematica acpi:MSU*: ID_VENDOR_FROM_DATABASE=motorola acpi:MSV*: ID_VENDOR_FROM_DATABASE=Mosgi Corporation acpi:MSX*: ID_VENDOR_FROM_DATABASE=Micomsoft Co., Ltd. acpi:MSY*: ID_VENDOR_FROM_DATABASE=MicroTouch Systems Inc acpi:MTB*: ID_VENDOR_FROM_DATABASE=Media Technologies Ltd. acpi:MTC*: ID_VENDOR_FROM_DATABASE=Mars-Tech Corporation acpi:MTD*: ID_VENDOR_FROM_DATABASE=MindTech Display Co. Ltd acpi:MTE*: ID_VENDOR_FROM_DATABASE=MediaTec GmbH acpi:MTH*: ID_VENDOR_FROM_DATABASE=Micro-Tech Hearing Instruments acpi:MTI*: ID_VENDOR_FROM_DATABASE=MaxCom Technical Inc acpi:MTK*: ID_VENDOR_FROM_DATABASE=Microtek International Inc. acpi:MTL*: ID_VENDOR_FROM_DATABASE=Mitel Corporation acpi:MTM*: ID_VENDOR_FROM_DATABASE=Motium acpi:MTN*: ID_VENDOR_FROM_DATABASE=Mtron Storage Technology Co., Ltd. acpi:MTR*: ID_VENDOR_FROM_DATABASE=Mitron computer Inc acpi:MTS*: ID_VENDOR_FROM_DATABASE=Multi-Tech Systems acpi:MTU*: ID_VENDOR_FROM_DATABASE=Mark of the Unicorn Inc acpi:MTX*: ID_VENDOR_FROM_DATABASE=Matrox acpi:MUD*: ID_VENDOR_FROM_DATABASE=Multi-Dimension Institute acpi:MUK*: ID_VENDOR_FROM_DATABASE=mainpine limited acpi:MVD*: ID_VENDOR_FROM_DATABASE=Microvitec PLC acpi:MVI*: ID_VENDOR_FROM_DATABASE=Media Vision Inc acpi:MVM*: ID_VENDOR_FROM_DATABASE=SOBO VISION acpi:MVS*: ID_VENDOR_FROM_DATABASE=Microvision acpi:MVX*: ID_VENDOR_FROM_DATABASE=COM 1 acpi:MWI*: ID_VENDOR_FROM_DATABASE=Multiwave Innovation Pte Ltd acpi:MWR*: ID_VENDOR_FROM_DATABASE=mware acpi:MWY*: ID_VENDOR_FROM_DATABASE=Microway Inc acpi:MXD*: ID_VENDOR_FROM_DATABASE=MaxData Computer GmbH & Co.KG acpi:MXI*: ID_VENDOR_FROM_DATABASE=Macronix Inc acpi:MXL*: ID_VENDOR_FROM_DATABASE=Hitachi Maxell, Ltd. acpi:MXP*: ID_VENDOR_FROM_DATABASE=Maxpeed Corporation acpi:MXT*: ID_VENDOR_FROM_DATABASE=Maxtech Corporation acpi:MXV*: ID_VENDOR_FROM_DATABASE=MaxVision Corporation acpi:MYA*: ID_VENDOR_FROM_DATABASE=Monydata acpi:MYR*: ID_VENDOR_FROM_DATABASE=Myriad Solutions Ltd acpi:MYX*: ID_VENDOR_FROM_DATABASE=Micronyx Inc acpi:NAC*: ID_VENDOR_FROM_DATABASE=Ncast Corporation acpi:NAD*: ID_VENDOR_FROM_DATABASE=NAD Electronics acpi:NAK*: ID_VENDOR_FROM_DATABASE=Nakano Engineering Co.,Ltd. acpi:NAL*: ID_VENDOR_FROM_DATABASE=Network Alchemy acpi:NAT*: ID_VENDOR_FROM_DATABASE=NaturalPoint Inc. acpi:NAV*: ID_VENDOR_FROM_DATABASE=Navigation Corporation acpi:NAX*: ID_VENDOR_FROM_DATABASE=Naxos Tecnologia acpi:NBL*: ID_VENDOR_FROM_DATABASE=N*Able Technologies Inc acpi:NBS*: ID_VENDOR_FROM_DATABASE=National Key Lab. on ISN acpi:NBT*: ID_VENDOR_FROM_DATABASE=NingBo Bestwinning Technology CO., Ltd acpi:NCA*: ID_VENDOR_FROM_DATABASE=Nixdorf Company acpi:NCC*: ID_VENDOR_FROM_DATABASE=NCR Corporation acpi:NCE*: ID_VENDOR_FROM_DATABASE=Norcent Technology, Inc. acpi:NCI*: ID_VENDOR_FROM_DATABASE=NewCom Inc acpi:NCL*: ID_VENDOR_FROM_DATABASE=NetComm Ltd acpi:NCR*: ID_VENDOR_FROM_DATABASE=NCR Electronics acpi:NCS*: ID_VENDOR_FROM_DATABASE=Northgate Computer Systems acpi:NCT*: ID_VENDOR_FROM_DATABASE=NEC CustomTechnica, Ltd. acpi:NDC*: ID_VENDOR_FROM_DATABASE=National DataComm Corporaiton acpi:NDI*: ID_VENDOR_FROM_DATABASE=National Display Systems acpi:NDK*: ID_VENDOR_FROM_DATABASE=Naitoh Densei CO., LTD. acpi:NDL*: ID_VENDOR_FROM_DATABASE=Network Designers acpi:NDS*: ID_VENDOR_FROM_DATABASE=Nokia Data acpi:NEC*: ID_VENDOR_FROM_DATABASE=NEC Corporation acpi:NEO*: ID_VENDOR_FROM_DATABASE=NEO TELECOM CO.,LTD. acpi:NET*: ID_VENDOR_FROM_DATABASE=Mettler Toledo acpi:NEU*: ID_VENDOR_FROM_DATABASE=NEUROTEC - EMPRESA DE PESQUISA E DESENVOLVIMENTO EM BIOMEDICINA acpi:NEX*: ID_VENDOR_FROM_DATABASE=Nexgen Mediatech Inc., acpi:NFC*: ID_VENDOR_FROM_DATABASE=BTC Korea Co., Ltd acpi:NFS*: ID_VENDOR_FROM_DATABASE=Number Five Software acpi:NGC*: ID_VENDOR_FROM_DATABASE=Network General acpi:NGS*: ID_VENDOR_FROM_DATABASE=A D S Exports acpi:NHT*: ID_VENDOR_FROM_DATABASE=Vinci Labs acpi:NIC*: ID_VENDOR_FROM_DATABASE=National Instruments Corporation acpi:NIS*: ID_VENDOR_FROM_DATABASE=Nissei Electric Company acpi:NIT*: ID_VENDOR_FROM_DATABASE=Network Info Technology acpi:NIX*: ID_VENDOR_FROM_DATABASE=Seanix Technology Inc acpi:NLC*: ID_VENDOR_FROM_DATABASE=Next Level Communications acpi:NMP*: ID_VENDOR_FROM_DATABASE=Nokia Mobile Phones acpi:NMS*: ID_VENDOR_FROM_DATABASE=Natural Micro System acpi:NMV*: ID_VENDOR_FROM_DATABASE=NEC-Mitsubishi Electric Visual Systems Corporation acpi:NMX*: ID_VENDOR_FROM_DATABASE=Neomagic acpi:NNC*: ID_VENDOR_FROM_DATABASE=NNC acpi:NOE*: ID_VENDOR_FROM_DATABASE=NordicEye AB acpi:NOI*: ID_VENDOR_FROM_DATABASE=North Invent A/S acpi:NOK*: ID_VENDOR_FROM_DATABASE=Nokia Display Products acpi:NOR*: ID_VENDOR_FROM_DATABASE=Norand Corporation acpi:NOT*: ID_VENDOR_FROM_DATABASE=Not Limited Inc acpi:NPI*: ID_VENDOR_FROM_DATABASE=Network Peripherals Inc acpi:NRL*: ID_VENDOR_FROM_DATABASE=U.S. Naval Research Lab acpi:NRT*: ID_VENDOR_FROM_DATABASE=Beijing Northern Radiantelecom Co. acpi:NRV*: ID_VENDOR_FROM_DATABASE=Taugagreining hf acpi:NSC*: ID_VENDOR_FROM_DATABASE=National Semiconductor Corporation acpi:NSI*: ID_VENDOR_FROM_DATABASE=NISSEI ELECTRIC CO.,LTD acpi:NSP*: ID_VENDOR_FROM_DATABASE=Nspire System Inc. acpi:NSS*: ID_VENDOR_FROM_DATABASE=Newport Systems Solutions acpi:NST*: ID_VENDOR_FROM_DATABASE=Network Security Technology Co acpi:NTC*: ID_VENDOR_FROM_DATABASE=NeoTech S.R.L acpi:NTI*: ID_VENDOR_FROM_DATABASE=New Tech Int'l Company acpi:NTL*: ID_VENDOR_FROM_DATABASE=National Transcomm. Ltd acpi:NTN*: ID_VENDOR_FROM_DATABASE=Nuvoton Technology Corporation acpi:NTR*: ID_VENDOR_FROM_DATABASE=N-trig Innovative Technologies, Inc. acpi:NTS*: ID_VENDOR_FROM_DATABASE=Nits Technology Inc. acpi:NTT*: ID_VENDOR_FROM_DATABASE=NTT Advanced Technology Corporation acpi:NTW*: ID_VENDOR_FROM_DATABASE=Networth Inc acpi:NTX*: ID_VENDOR_FROM_DATABASE=Netaccess Inc acpi:NUG*: ID_VENDOR_FROM_DATABASE=NU Technology, Inc. acpi:NUI*: ID_VENDOR_FROM_DATABASE=NU Inc. acpi:NVC*: ID_VENDOR_FROM_DATABASE=NetVision Corporation acpi:NVD*: ID_VENDOR_FROM_DATABASE=Nvidia acpi:NVI*: ID_VENDOR_FROM_DATABASE=NuVision US, Inc. acpi:NVL*: ID_VENDOR_FROM_DATABASE=Novell Inc acpi:NVT*: ID_VENDOR_FROM_DATABASE=Navatek Engineering Corporation acpi:NWC*: ID_VENDOR_FROM_DATABASE=NW Computer Engineering acpi:NWP*: ID_VENDOR_FROM_DATABASE=NovaWeb Technologies Inc acpi:NWS*: ID_VENDOR_FROM_DATABASE=Newisys, Inc. acpi:NXC*: ID_VENDOR_FROM_DATABASE=NextCom K.K. acpi:NXG*: ID_VENDOR_FROM_DATABASE=Nexgen acpi:NXP*: ID_VENDOR_FROM_DATABASE=NXP Semiconductors bv. acpi:NXQ*: ID_VENDOR_FROM_DATABASE=Nexiq Technologies, Inc. acpi:NXS*: ID_VENDOR_FROM_DATABASE=Technology Nexus Secure Open Systems AB acpi:NYC*: ID_VENDOR_FROM_DATABASE=nakayo telecommunications,inc. acpi:OAK*: ID_VENDOR_FROM_DATABASE=Oak Tech Inc acpi:OAS*: ID_VENDOR_FROM_DATABASE=Oasys Technology Company acpi:OBS*: ID_VENDOR_FROM_DATABASE=Optibase Technologies acpi:OCD*: ID_VENDOR_FROM_DATABASE=Macraigor Systems Inc acpi:OCN*: ID_VENDOR_FROM_DATABASE=Olfan acpi:OCS*: ID_VENDOR_FROM_DATABASE=Open Connect Solutions acpi:ODM*: ID_VENDOR_FROM_DATABASE=ODME Inc. acpi:ODR*: ID_VENDOR_FROM_DATABASE=Odrac acpi:OEC*: ID_VENDOR_FROM_DATABASE=ORION ELECTRIC CO.,LTD acpi:OEI*: ID_VENDOR_FROM_DATABASE=Optum Engineering Inc. acpi:OIC*: ID_VENDOR_FROM_DATABASE=Option Industrial Computers acpi:OIM*: ID_VENDOR_FROM_DATABASE=Option International acpi:OIN*: ID_VENDOR_FROM_DATABASE=Option International acpi:OKI*: ID_VENDOR_FROM_DATABASE=OKI Electric Industrial Company Ltd acpi:OLC*: ID_VENDOR_FROM_DATABASE=Olicom A/S acpi:OLD*: ID_VENDOR_FROM_DATABASE=Olidata S.p.A. acpi:OLI*: ID_VENDOR_FROM_DATABASE=Olivetti acpi:OLT*: ID_VENDOR_FROM_DATABASE=Olitec S.A. acpi:OLV*: ID_VENDOR_FROM_DATABASE=Olitec S.A. acpi:OLY*: ID_VENDOR_FROM_DATABASE=OLYMPUS CORPORATION acpi:OMC*: ID_VENDOR_FROM_DATABASE=OBJIX Multimedia Corporation acpi:OMN*: ID_VENDOR_FROM_DATABASE=Omnitel acpi:OMR*: ID_VENDOR_FROM_DATABASE=Omron Corporation acpi:ONE*: ID_VENDOR_FROM_DATABASE=Oneac Corporation acpi:ONK*: ID_VENDOR_FROM_DATABASE=ONKYO Corporation acpi:ONL*: ID_VENDOR_FROM_DATABASE=OnLive, Inc acpi:ONS*: ID_VENDOR_FROM_DATABASE=On Systems Inc acpi:ONW*: ID_VENDOR_FROM_DATABASE=OPEN Networks Ltd acpi:ONX*: ID_VENDOR_FROM_DATABASE=SOMELEC Z.I. Du Vert Galanta acpi:OOS*: ID_VENDOR_FROM_DATABASE=OSRAM acpi:OPC*: ID_VENDOR_FROM_DATABASE=Opcode Inc acpi:OPI*: ID_VENDOR_FROM_DATABASE=D.N.S. Corporation acpi:OPP*: ID_VENDOR_FROM_DATABASE=OPPO Digital, Inc. acpi:OPT*: ID_VENDOR_FROM_DATABASE=OPTi Inc acpi:OPV*: ID_VENDOR_FROM_DATABASE=Optivision Inc acpi:OQI*: ID_VENDOR_FROM_DATABASE=Oksori Company Ltd acpi:ORG*: ID_VENDOR_FROM_DATABASE=ORGA Kartensysteme GmbH acpi:ORI*: ID_VENDOR_FROM_DATABASE=OSR Open Systems Resources, Inc. acpi:ORN*: ID_VENDOR_FROM_DATABASE=ORION ELECTRIC CO., LTD. acpi:OSA*: ID_VENDOR_FROM_DATABASE=OSAKA Micro Computer, Inc. acpi:OSP*: ID_VENDOR_FROM_DATABASE=OPTI-UPS Corporation acpi:OSR*: ID_VENDOR_FROM_DATABASE=Oksori Company Ltd acpi:OTB*: ID_VENDOR_FROM_DATABASE=outsidetheboxstuff.com acpi:OTI*: ID_VENDOR_FROM_DATABASE=Orchid Technology acpi:OTM*: ID_VENDOR_FROM_DATABASE=Optoma Corporation           acpi:OTT*: ID_VENDOR_FROM_DATABASE=OPTO22, Inc. acpi:OUK*: ID_VENDOR_FROM_DATABASE=OUK Company Ltd acpi:OWL*: ID_VENDOR_FROM_DATABASE=Mediacom Technologies Pte Ltd acpi:OXU*: ID_VENDOR_FROM_DATABASE=Oxus Research S.A. acpi:OYO*: ID_VENDOR_FROM_DATABASE=Shadow Systems acpi:OZC*: ID_VENDOR_FROM_DATABASE=OZ Corporation acpi:OZO*: ID_VENDOR_FROM_DATABASE=Tribe Computer Works Inc acpi:PAC*: ID_VENDOR_FROM_DATABASE=Pacific Avionics Corporation acpi:PAD*: ID_VENDOR_FROM_DATABASE=Promotion and Display Technology Ltd. acpi:PAK*: ID_VENDOR_FROM_DATABASE=Many CNC System Co., Ltd. acpi:PAM*: ID_VENDOR_FROM_DATABASE=Peter Antesberger Messtechnik acpi:PAN*: ID_VENDOR_FROM_DATABASE=The Panda Project acpi:PAR*: ID_VENDOR_FROM_DATABASE=Parallan Comp Inc acpi:PBI*: ID_VENDOR_FROM_DATABASE=Pitney Bowes acpi:PBL*: ID_VENDOR_FROM_DATABASE=Packard Bell Electronics acpi:PBN*: ID_VENDOR_FROM_DATABASE=Packard Bell NEC acpi:PBV*: ID_VENDOR_FROM_DATABASE=Pitney Bowes acpi:PCA*: ID_VENDOR_FROM_DATABASE=Philips BU Add On Card acpi:PCB*: ID_VENDOR_FROM_DATABASE=OCTAL S.A. acpi:PCC*: ID_VENDOR_FROM_DATABASE=PowerCom Technology Company Ltd acpi:PCG*: ID_VENDOR_FROM_DATABASE=First Industrial Computer Inc acpi:PCI*: ID_VENDOR_FROM_DATABASE=Pioneer Computer Inc acpi:PCK*: ID_VENDOR_FROM_DATABASE=PCBANK21 acpi:PCL*: ID_VENDOR_FROM_DATABASE=pentel.co.,ltd acpi:PCM*: ID_VENDOR_FROM_DATABASE=PCM Systems Corporation acpi:PCO*: ID_VENDOR_FROM_DATABASE=Performance Concepts Inc., acpi:PCP*: ID_VENDOR_FROM_DATABASE=Procomp USA Inc acpi:PCS*: ID_VENDOR_FROM_DATABASE=TOSHIBA PERSONAL COMPUTER SYSTEM CORPRATION acpi:PCT*: ID_VENDOR_FROM_DATABASE=PC-Tel Inc acpi:PCW*: ID_VENDOR_FROM_DATABASE=Pacific CommWare Inc acpi:PCX*: ID_VENDOR_FROM_DATABASE=PC Xperten acpi:PDM*: ID_VENDOR_FROM_DATABASE=Psion Dacom Plc. acpi:PDN*: ID_VENDOR_FROM_DATABASE=AT&T Paradyne acpi:PDR*: ID_VENDOR_FROM_DATABASE=Pure Data Inc acpi:PDS*: ID_VENDOR_FROM_DATABASE=PD Systems International Ltd acpi:PDT*: ID_VENDOR_FROM_DATABASE=PDTS - Prozessdatentechnik und Systeme acpi:PDV*: ID_VENDOR_FROM_DATABASE=Prodrive B.V. acpi:PEC*: ID_VENDOR_FROM_DATABASE=POTRANS Electrical Corp. acpi:PEI*: ID_VENDOR_FROM_DATABASE=PEI Electronics Inc acpi:PEL*: ID_VENDOR_FROM_DATABASE=Primax Electric Ltd acpi:PEN*: ID_VENDOR_FROM_DATABASE=Interactive Computer Products Inc acpi:PEP*: ID_VENDOR_FROM_DATABASE=Peppercon AG acpi:PER*: ID_VENDOR_FROM_DATABASE=Perceptive Signal Technologies acpi:PET*: ID_VENDOR_FROM_DATABASE=Practical Electronic Tools acpi:PFT*: ID_VENDOR_FROM_DATABASE=Telia ProSoft AB acpi:PGI*: ID_VENDOR_FROM_DATABASE=PACSGEAR, Inc. acpi:PGM*: ID_VENDOR_FROM_DATABASE=Paradigm Advanced Research Centre acpi:PGP*: ID_VENDOR_FROM_DATABASE=propagamma kommunikation acpi:PGS*: ID_VENDOR_FROM_DATABASE=Princeton Graphic Systems acpi:PHC*: ID_VENDOR_FROM_DATABASE=Pijnenburg Beheer N.V. acpi:PHE*: ID_VENDOR_FROM_DATABASE=Philips Medical Systems Boeblingen GmbH acpi:PHL*: ID_VENDOR_FROM_DATABASE=Philips Consumer Electronics Company acpi:PHO*: ID_VENDOR_FROM_DATABASE=Photonics Systems Inc. acpi:PHS*: ID_VENDOR_FROM_DATABASE=Philips Communication Systems acpi:PHY*: ID_VENDOR_FROM_DATABASE=Phylon Communications acpi:PIE*: ID_VENDOR_FROM_DATABASE=Pacific Image Electronics Company Ltd acpi:PIM*: ID_VENDOR_FROM_DATABASE=Prism, LLC acpi:PIO*: ID_VENDOR_FROM_DATABASE=Pioneer Electronic Corporation acpi:PIX*: ID_VENDOR_FROM_DATABASE=Pixie Tech Inc acpi:PJA*: ID_VENDOR_FROM_DATABASE=Projecta acpi:PJD*: ID_VENDOR_FROM_DATABASE=Projectiondesign AS acpi:PJT*: ID_VENDOR_FROM_DATABASE=Pan Jit International Inc. acpi:PKA*: ID_VENDOR_FROM_DATABASE=Acco UK ltd. acpi:PLC*: ID_VENDOR_FROM_DATABASE=Pro-Log Corporation acpi:PLF*: ID_VENDOR_FROM_DATABASE=Panasonic Avionics Corporation acpi:PLM*: ID_VENDOR_FROM_DATABASE=PROLINK Microsystems Corp. acpi:PLT*: ID_VENDOR_FROM_DATABASE=PT Hartono Istana Teknologi acpi:PLV*: ID_VENDOR_FROM_DATABASE=PLUS Vision Corp. acpi:PLX*: ID_VENDOR_FROM_DATABASE=Parallax Graphics acpi:PLY*: ID_VENDOR_FROM_DATABASE=Polycom Inc. acpi:PMC*: ID_VENDOR_FROM_DATABASE=PMC Consumer Electronics Ltd acpi:PMD*: ID_VENDOR_FROM_DATABASE=TDK USA Corporation acpi:PMM*: ID_VENDOR_FROM_DATABASE=Point Multimedia System acpi:PMT*: ID_VENDOR_FROM_DATABASE=Promate Electronic Co., Ltd. acpi:PMX*: ID_VENDOR_FROM_DATABASE=Photomatrix acpi:PNG*: ID_VENDOR_FROM_DATABASE=Microsoft acpi:PNL*: ID_VENDOR_FROM_DATABASE=Panelview, Inc. acpi:PNR*: ID_VENDOR_FROM_DATABASE=Planar Systems, Inc. acpi:PNS*: ID_VENDOR_FROM_DATABASE=PanaScope acpi:PNX*: ID_VENDOR_FROM_DATABASE=Phoenix Technologies, Ltd. acpi:POL*: ID_VENDOR_FROM_DATABASE=PolyComp (PTY) Ltd. acpi:PON*: ID_VENDOR_FROM_DATABASE=Perpetual Technologies, LLC acpi:POR*: ID_VENDOR_FROM_DATABASE=Portalis LC acpi:PPC*: ID_VENDOR_FROM_DATABASE=Phoenixtec Power Company Ltd acpi:PPD*: ID_VENDOR_FROM_DATABASE=MEPhI acpi:PPI*: ID_VENDOR_FROM_DATABASE=Practical Peripherals acpi:PPM*: ID_VENDOR_FROM_DATABASE=Clinton Electronics Corp. acpi:PPP*: ID_VENDOR_FROM_DATABASE=Purup Prepress AS acpi:PPR*: ID_VENDOR_FROM_DATABASE=PicPro acpi:PPX*: ID_VENDOR_FROM_DATABASE=Perceptive Pixel Inc. acpi:PQI*: ID_VENDOR_FROM_DATABASE=Pixel Qi acpi:PRA*: ID_VENDOR_FROM_DATABASE=PRO/AUTOMATION acpi:PRC*: ID_VENDOR_FROM_DATABASE=PerComm acpi:PRD*: ID_VENDOR_FROM_DATABASE=Praim S.R.L. acpi:PRF*: ID_VENDOR_FROM_DATABASE=Digital Electronics Corporation acpi:PRG*: ID_VENDOR_FROM_DATABASE=The Phoenix Research Group Inc acpi:PRI*: ID_VENDOR_FROM_DATABASE=Priva Hortimation BV acpi:PRM*: ID_VENDOR_FROM_DATABASE=Prometheus acpi:PRO*: ID_VENDOR_FROM_DATABASE=Proteon acpi:PRS*: ID_VENDOR_FROM_DATABASE=Leutron Vision acpi:PRT*: ID_VENDOR_FROM_DATABASE=Parade Technologies, Ltd. acpi:PRX*: ID_VENDOR_FROM_DATABASE=Proxima Corporation acpi:PSA*: ID_VENDOR_FROM_DATABASE=Advanced Signal Processing Technologies acpi:PSC*: ID_VENDOR_FROM_DATABASE=Philips Semiconductors acpi:PSD*: ID_VENDOR_FROM_DATABASE=Peus-Systems GmbH acpi:PSE*: ID_VENDOR_FROM_DATABASE=Practical Solutions Pte., Ltd. acpi:PSI*: ID_VENDOR_FROM_DATABASE=PSI-Perceptive Solutions Inc acpi:PSL*: ID_VENDOR_FROM_DATABASE=Perle Systems Limited acpi:PSM*: ID_VENDOR_FROM_DATABASE=Prosum acpi:PST*: ID_VENDOR_FROM_DATABASE=Global Data SA acpi:PTA*: ID_VENDOR_FROM_DATABASE=PAR Tech Inc. acpi:PTC*: ID_VENDOR_FROM_DATABASE=PS Technology Corporation acpi:PTG*: ID_VENDOR_FROM_DATABASE=Cipher Systems Inc acpi:PTH*: ID_VENDOR_FROM_DATABASE=Pathlight Technology Inc acpi:PTI*: ID_VENDOR_FROM_DATABASE=Promise Technology Inc acpi:PTL*: ID_VENDOR_FROM_DATABASE=Pantel Inc acpi:PTS*: ID_VENDOR_FROM_DATABASE=Plain Tree Systems Inc acpi:PVG*: ID_VENDOR_FROM_DATABASE=Proview Global Co., Ltd acpi:PVI*: ID_VENDOR_FROM_DATABASE=Prime view international Co., Ltd acpi:PVM*: ID_VENDOR_FROM_DATABASE=Penta Studiotechnik GmbH acpi:PVN*: ID_VENDOR_FROM_DATABASE=Pixel Vision acpi:PVP*: ID_VENDOR_FROM_DATABASE=Klos Technologies, Inc. acpi:PXC*: ID_VENDOR_FROM_DATABASE=Phoenix Contact acpi:PXE*: ID_VENDOR_FROM_DATABASE=PIXELA CORPORATION acpi:PXL*: ID_VENDOR_FROM_DATABASE=The Moving Pixel Company acpi:PXM*: ID_VENDOR_FROM_DATABASE=Proxim Inc acpi:QCC*: ID_VENDOR_FROM_DATABASE=QuakeCom Company Ltd acpi:QCH*: ID_VENDOR_FROM_DATABASE=Metronics Inc acpi:QCI*: ID_VENDOR_FROM_DATABASE=Quanta Computer Inc acpi:QCK*: ID_VENDOR_FROM_DATABASE=Quick Corporation acpi:QCL*: ID_VENDOR_FROM_DATABASE=Quadrant Components Inc acpi:QCP*: ID_VENDOR_FROM_DATABASE=Qualcomm Inc acpi:QDI*: ID_VENDOR_FROM_DATABASE=Quantum Data Incorporated acpi:QDM*: ID_VENDOR_FROM_DATABASE=Quadram acpi:QDS*: ID_VENDOR_FROM_DATABASE=Quanta Display Inc. acpi:QFF*: ID_VENDOR_FROM_DATABASE=Padix Co., Inc. acpi:QFI*: ID_VENDOR_FROM_DATABASE=Quickflex, Inc acpi:QLC*: ID_VENDOR_FROM_DATABASE=Q-Logic acpi:QQQ*: ID_VENDOR_FROM_DATABASE=Chuomusen Co., Ltd. acpi:QSI*: ID_VENDOR_FROM_DATABASE=Quantum Solutions, Inc. acpi:QTD*: ID_VENDOR_FROM_DATABASE=Quantum 3D Inc acpi:QTH*: ID_VENDOR_FROM_DATABASE=Questech Ltd acpi:QTI*: ID_VENDOR_FROM_DATABASE=Quicknet Technologies Inc acpi:QTM*: ID_VENDOR_FROM_DATABASE=Quantum acpi:QTR*: ID_VENDOR_FROM_DATABASE=Qtronix Corporation acpi:QUA*: ID_VENDOR_FROM_DATABASE=Quatographic AG acpi:QUE*: ID_VENDOR_FROM_DATABASE=Questra Consulting acpi:QVU*: ID_VENDOR_FROM_DATABASE=Quartics acpi:RAC*: ID_VENDOR_FROM_DATABASE=Racore Computer Products Inc acpi:RAD*: ID_VENDOR_FROM_DATABASE=Radisys Corporation acpi:RAI*: ID_VENDOR_FROM_DATABASE=Rockwell Automation/Intecolor acpi:RAN*: ID_VENDOR_FROM_DATABASE=Rancho Tech Inc acpi:RAR*: ID_VENDOR_FROM_DATABASE=Raritan, Inc. acpi:RAS*: ID_VENDOR_FROM_DATABASE=RAScom Inc acpi:RAT*: ID_VENDOR_FROM_DATABASE=Rent-A-Tech acpi:RAY*: ID_VENDOR_FROM_DATABASE=Raylar Design, Inc. acpi:RCE*: ID_VENDOR_FROM_DATABASE=Parc d'Activite des Bellevues acpi:RCH*: ID_VENDOR_FROM_DATABASE=Reach Technology Inc acpi:RCI*: ID_VENDOR_FROM_DATABASE=RC International acpi:RCN*: ID_VENDOR_FROM_DATABASE=Radio Consult SRL acpi:RCO*: ID_VENDOR_FROM_DATABASE=Rockwell Collins acpi:RDI*: ID_VENDOR_FROM_DATABASE=Rainbow Displays, Inc. acpi:RDM*: ID_VENDOR_FROM_DATABASE=Tremon Enterprises Company Ltd acpi:RDN*: ID_VENDOR_FROM_DATABASE=RADIODATA GmbH acpi:RDS*: ID_VENDOR_FROM_DATABASE=Radius Inc acpi:REA*: ID_VENDOR_FROM_DATABASE=Real D acpi:REC*: ID_VENDOR_FROM_DATABASE=ReCom acpi:RED*: ID_VENDOR_FROM_DATABASE=Research Electronics Development Inc acpi:REF*: ID_VENDOR_FROM_DATABASE=Reflectivity, Inc. acpi:REH*: ID_VENDOR_FROM_DATABASE=Rehan Electronics Ltd. acpi:REL*: ID_VENDOR_FROM_DATABASE=Reliance Electric Ind Corporation acpi:REM*: ID_VENDOR_FROM_DATABASE=SCI Systems Inc. acpi:REN*: ID_VENDOR_FROM_DATABASE=Renesas Technology Corp. acpi:RES*: ID_VENDOR_FROM_DATABASE=ResMed Pty Ltd acpi:RET*: ID_VENDOR_FROM_DATABASE=Resonance Technology, Inc. acpi:REX*: ID_VENDOR_FROM_DATABASE=RATOC Systems, Inc. acpi:RGL*: ID_VENDOR_FROM_DATABASE=Robertson Geologging Ltd acpi:RHD*: ID_VENDOR_FROM_DATABASE=RightHand Technologies acpi:RHM*: ID_VENDOR_FROM_DATABASE=Rohm Company Ltd acpi:RHT*: ID_VENDOR_FROM_DATABASE=Red Hat, Inc. acpi:RIC*: ID_VENDOR_FROM_DATABASE=RICOH COMPANY, LTD. acpi:RII*: ID_VENDOR_FROM_DATABASE=Racal Interlan Inc acpi:RIO*: ID_VENDOR_FROM_DATABASE=Rios Systems Company Ltd acpi:RIT*: ID_VENDOR_FROM_DATABASE=Ritech Inc acpi:RIV*: ID_VENDOR_FROM_DATABASE=Rivulet Communications acpi:RJA*: ID_VENDOR_FROM_DATABASE=Roland Corporation acpi:RJS*: ID_VENDOR_FROM_DATABASE=Advanced Engineering acpi:RKC*: ID_VENDOR_FROM_DATABASE=Reakin Technolohy Corporation acpi:RLD*: ID_VENDOR_FROM_DATABASE=MEPCO acpi:RLN*: ID_VENDOR_FROM_DATABASE=RadioLAN Inc acpi:RMC*: ID_VENDOR_FROM_DATABASE=Raritan Computer, Inc acpi:RMP*: ID_VENDOR_FROM_DATABASE=Research Machines acpi:RMT*: ID_VENDOR_FROM_DATABASE=Roper Mobile acpi:RNB*: ID_VENDOR_FROM_DATABASE=Rainbow Technologies acpi:ROB*: ID_VENDOR_FROM_DATABASE=Robust Electronics GmbH acpi:ROH*: ID_VENDOR_FROM_DATABASE=Rohm Co., Ltd. acpi:ROK*: ID_VENDOR_FROM_DATABASE=Rockwell International acpi:ROP*: ID_VENDOR_FROM_DATABASE=Roper International Ltd acpi:ROS*: ID_VENDOR_FROM_DATABASE=Rohde & Schwarz acpi:RPI*: ID_VENDOR_FROM_DATABASE=RoomPro Technologies acpi:RPT*: ID_VENDOR_FROM_DATABASE=R.P.T.Intergroups acpi:RRI*: ID_VENDOR_FROM_DATABASE=Radicom Research Inc acpi:RSC*: ID_VENDOR_FROM_DATABASE=PhotoTelesis acpi:RSH*: ID_VENDOR_FROM_DATABASE=ADC-Centre acpi:RSI*: ID_VENDOR_FROM_DATABASE=Rampage Systems Inc acpi:RSN*: ID_VENDOR_FROM_DATABASE=Radiospire Networks, Inc. acpi:RSQ*: ID_VENDOR_FROM_DATABASE=R Squared acpi:RSS*: ID_VENDOR_FROM_DATABASE=Rockwell Semiconductor Systems acpi:RSV*: ID_VENDOR_FROM_DATABASE=Ross Video Ltd acpi:RSX*: ID_VENDOR_FROM_DATABASE=Rapid Tech Corporation acpi:RTC*: ID_VENDOR_FROM_DATABASE=Relia Technologies acpi:RTI*: ID_VENDOR_FROM_DATABASE=Rancho Tech Inc acpi:RTL*: ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Company Ltd acpi:RTS*: ID_VENDOR_FROM_DATABASE=Raintree Systems acpi:RUN*: ID_VENDOR_FROM_DATABASE=RUNCO International acpi:RUP*: ID_VENDOR_FROM_DATABASE=Ups Manufactoring s.r.l. acpi:RVC*: ID_VENDOR_FROM_DATABASE=RSI Systems Inc acpi:RVI*: ID_VENDOR_FROM_DATABASE=Realvision Inc acpi:RVL*: ID_VENDOR_FROM_DATABASE=Reveal Computer Prod acpi:RWC*: ID_VENDOR_FROM_DATABASE=Red Wing Corporation acpi:RXT*: ID_VENDOR_FROM_DATABASE=Tectona SoftSolutions (P) Ltd., acpi:SAA*: ID_VENDOR_FROM_DATABASE=Sanritz Automation Co.,Ltd. acpi:SAE*: ID_VENDOR_FROM_DATABASE=Saab Aerotech acpi:SAG*: ID_VENDOR_FROM_DATABASE=Sedlbauer acpi:SAI*: ID_VENDOR_FROM_DATABASE=Sage Inc acpi:SAK*: ID_VENDOR_FROM_DATABASE=Saitek Ltd acpi:SAM*: ID_VENDOR_FROM_DATABASE=Samsung Electric Company acpi:SAN*: ID_VENDOR_FROM_DATABASE=Sanyo Electric Co.,Ltd. acpi:SAS*: ID_VENDOR_FROM_DATABASE=Stores Automated Systems Inc acpi:SAT*: ID_VENDOR_FROM_DATABASE=Shuttle Tech acpi:SBC*: ID_VENDOR_FROM_DATABASE=Shanghai Bell Telephone Equip Mfg Co acpi:SBD*: ID_VENDOR_FROM_DATABASE=Softbed - Consulting & Development Ltd acpi:SBI*: ID_VENDOR_FROM_DATABASE=SMART Technologies Inc. acpi:SBS*: ID_VENDOR_FROM_DATABASE=SBS-or Industrial Computers GmbH acpi:SBT*: ID_VENDOR_FROM_DATABASE=Senseboard Technologies AB acpi:SCC*: ID_VENDOR_FROM_DATABASE=SORD Computer Corporation acpi:SCD*: ID_VENDOR_FROM_DATABASE=Sanyo Electric Company Ltd acpi:SCE*: ID_VENDOR_FROM_DATABASE=Sun Corporation acpi:SCH*: ID_VENDOR_FROM_DATABASE=Schlumberger Cards acpi:SCI*: ID_VENDOR_FROM_DATABASE=System Craft acpi:SCL*: ID_VENDOR_FROM_DATABASE=Sigmacom Co., Ltd. acpi:SCM*: ID_VENDOR_FROM_DATABASE=SCM Microsystems Inc acpi:SCN*: ID_VENDOR_FROM_DATABASE=Scanport, Inc. acpi:SCO*: ID_VENDOR_FROM_DATABASE=SORCUS Computer GmbH acpi:SCP*: ID_VENDOR_FROM_DATABASE=Scriptel Corporation acpi:SCR*: ID_VENDOR_FROM_DATABASE=Systran Corporation acpi:SCS*: ID_VENDOR_FROM_DATABASE=Nanomach Anstalt acpi:SCT*: ID_VENDOR_FROM_DATABASE=Smart Card Technology acpi:SDA*: ID_VENDOR_FROM_DATABASE=SAT (Societe Anonyme) acpi:SDD*: ID_VENDOR_FROM_DATABASE=Intrada-SDD Ltd acpi:SDE*: ID_VENDOR_FROM_DATABASE=Sherwood Digital Electronics Corporation acpi:SDF*: ID_VENDOR_FROM_DATABASE=SODIFF E&T CO., Ltd. acpi:SDH*: ID_VENDOR_FROM_DATABASE=Communications Specialies, Inc. acpi:SDI*: ID_VENDOR_FROM_DATABASE=Samtron Displays Inc acpi:SDK*: ID_VENDOR_FROM_DATABASE=SAIT-Devlonics acpi:SDR*: ID_VENDOR_FROM_DATABASE=SDR Systems acpi:SDS*: ID_VENDOR_FROM_DATABASE=SunRiver Data System acpi:SDT*: ID_VENDOR_FROM_DATABASE=Siemens AG acpi:SDX*: ID_VENDOR_FROM_DATABASE=SDX Business Systems Ltd acpi:SEA*: ID_VENDOR_FROM_DATABASE=Seanix Technology Inc. acpi:SEB*: ID_VENDOR_FROM_DATABASE=system elektronik GmbH acpi:SEC*: ID_VENDOR_FROM_DATABASE=Seiko Epson Corporation acpi:SEE*: ID_VENDOR_FROM_DATABASE=SeeColor Corporation acpi:SEI*: ID_VENDOR_FROM_DATABASE=Seitz & Associates Inc acpi:SEL*: ID_VENDOR_FROM_DATABASE=Way2Call Communications acpi:SEM*: ID_VENDOR_FROM_DATABASE=Samsung Electronics Company Ltd acpi:SEN*: ID_VENDOR_FROM_DATABASE=Sencore acpi:SEO*: ID_VENDOR_FROM_DATABASE=SEOS Ltd acpi:SEP*: ID_VENDOR_FROM_DATABASE=SEP Eletronica Ltda. acpi:SER*: ID_VENDOR_FROM_DATABASE=Sony Ericsson Mobile Communications Inc. acpi:SES*: ID_VENDOR_FROM_DATABASE=Session Control LLC acpi:SET*: ID_VENDOR_FROM_DATABASE=SendTek Corporation acpi:SFM*: ID_VENDOR_FROM_DATABASE=TORNADO Company acpi:SFT*: ID_VENDOR_FROM_DATABASE=Mikroforum Ring 3 acpi:SGC*: ID_VENDOR_FROM_DATABASE=Spectragraphics Corporation acpi:SGD*: ID_VENDOR_FROM_DATABASE=Sigma Designs, Inc. acpi:SGE*: ID_VENDOR_FROM_DATABASE=Kansai Electric Company Ltd acpi:SGI*: ID_VENDOR_FROM_DATABASE=Scan Group Ltd acpi:SGL*: ID_VENDOR_FROM_DATABASE=Super Gate Technology Company Ltd acpi:SGM*: ID_VENDOR_FROM_DATABASE=SAGEM acpi:SGO*: ID_VENDOR_FROM_DATABASE=Logos Design A/S acpi:SGT*: ID_VENDOR_FROM_DATABASE=Stargate Technology acpi:SGW*: ID_VENDOR_FROM_DATABASE=Shanghai Guowei Science and Technology Co., Ltd. acpi:SGX*: ID_VENDOR_FROM_DATABASE=Silicon Graphics Inc acpi:SGZ*: ID_VENDOR_FROM_DATABASE=Systec Computer GmbH acpi:SHC*: ID_VENDOR_FROM_DATABASE=ShibaSoku Co., Ltd. acpi:SHG*: ID_VENDOR_FROM_DATABASE=Soft & Hardware development Goldammer GmbH acpi:SHI*: ID_VENDOR_FROM_DATABASE=Jiangsu Shinco Electronic Group Co., Ltd acpi:SHP*: ID_VENDOR_FROM_DATABASE=Sharp Corporation acpi:SHR*: ID_VENDOR_FROM_DATABASE=Digital Discovery acpi:SHT*: ID_VENDOR_FROM_DATABASE=Shin Ho Tech acpi:SIA*: ID_VENDOR_FROM_DATABASE=SIEMENS AG acpi:SIB*: ID_VENDOR_FROM_DATABASE=Sanyo Electric Company Ltd acpi:SIC*: ID_VENDOR_FROM_DATABASE=Sysmate Corporation acpi:SID*: ID_VENDOR_FROM_DATABASE=Seiko Instruments Information Devices Inc acpi:SIE*: ID_VENDOR_FROM_DATABASE=Siemens acpi:SIG*: ID_VENDOR_FROM_DATABASE=Sigma Designs Inc acpi:SII*: ID_VENDOR_FROM_DATABASE=Silicon Image, Inc. acpi:SIL*: ID_VENDOR_FROM_DATABASE=Silicon Laboratories, Inc acpi:SIM*: ID_VENDOR_FROM_DATABASE=S3 Inc acpi:SIN*: ID_VENDOR_FROM_DATABASE=Singular Technology Co., Ltd. acpi:SIR*: ID_VENDOR_FROM_DATABASE=Sirius Technologies Pty Ltd acpi:SIS*: ID_VENDOR_FROM_DATABASE=Silicon Integrated Systems Corporation acpi:SIT*: ID_VENDOR_FROM_DATABASE=Sitintel acpi:SIU*: ID_VENDOR_FROM_DATABASE=Seiko Instruments USA Inc acpi:SIX*: ID_VENDOR_FROM_DATABASE=Zuniq Data Corporation acpi:SJE*: ID_VENDOR_FROM_DATABASE=Sejin Electron Inc acpi:SKD*: ID_VENDOR_FROM_DATABASE=Schneider & Koch acpi:SKT*: ID_VENDOR_FROM_DATABASE=Samsung Electro-Mechanics Company Ltd acpi:SKY*: ID_VENDOR_FROM_DATABASE=SKYDATA S.P.A. acpi:SLA*: ID_VENDOR_FROM_DATABASE=Systeme Lauer GmbH&Co KG acpi:SLB*: ID_VENDOR_FROM_DATABASE=Shlumberger Ltd acpi:SLC*: ID_VENDOR_FROM_DATABASE=Syslogic Datentechnik AG acpi:SLF*: ID_VENDOR_FROM_DATABASE=StarLeaf acpi:SLH*: ID_VENDOR_FROM_DATABASE=Silicon Library Inc. acpi:SLI*: ID_VENDOR_FROM_DATABASE=Symbios Logic Inc acpi:SLK*: ID_VENDOR_FROM_DATABASE=Silitek Corporation acpi:SLM*: ID_VENDOR_FROM_DATABASE=Solomon Technology Corporation acpi:SLR*: ID_VENDOR_FROM_DATABASE=Schlumberger Technology Corporate acpi:SLS*: ID_VENDOR_FROM_DATABASE=Schnick-Schnack-Systems GmbH acpi:SLT*: ID_VENDOR_FROM_DATABASE=Salt Internatioinal Corp. acpi:SLX*: ID_VENDOR_FROM_DATABASE=Specialix acpi:SMA*: ID_VENDOR_FROM_DATABASE=SMART Modular Technologies acpi:SMB*: ID_VENDOR_FROM_DATABASE=Schlumberger acpi:SMC*: ID_VENDOR_FROM_DATABASE=Standard Microsystems Corporation acpi:SME*: ID_VENDOR_FROM_DATABASE=Sysmate Company acpi:SMI*: ID_VENDOR_FROM_DATABASE=SpaceLabs Medical Inc acpi:SMK*: ID_VENDOR_FROM_DATABASE=SMK CORPORATION acpi:SML*: ID_VENDOR_FROM_DATABASE=Sumitomo Metal Industries, Ltd. acpi:SMM*: ID_VENDOR_FROM_DATABASE=Shark Multimedia Inc acpi:SMO*: ID_VENDOR_FROM_DATABASE=STMicroelectronics acpi:SMP*: ID_VENDOR_FROM_DATABASE=Simple Computing acpi:SMR*: ID_VENDOR_FROM_DATABASE=B.& V. s.r.l. acpi:SMS*: ID_VENDOR_FROM_DATABASE=Silicom Multimedia Systems Inc acpi:SMT*: ID_VENDOR_FROM_DATABASE=Silcom Manufacturing Tech Inc acpi:SNC*: ID_VENDOR_FROM_DATABASE=Sentronic International Corp. acpi:SNI*: ID_VENDOR_FROM_DATABASE=Siemens Microdesign GmbH acpi:SNK*: ID_VENDOR_FROM_DATABASE=S&K Electronics acpi:SNO*: ID_VENDOR_FROM_DATABASE=SINOSUN TECHNOLOGY CO., LTD acpi:SNP*: ID_VENDOR_FROM_DATABASE=Siemens Nixdorf Info Systems acpi:SNS*: ID_VENDOR_FROM_DATABASE=Cirtech (UK) Ltd acpi:SNT*: ID_VENDOR_FROM_DATABASE=SuperNet Inc acpi:SNW*: ID_VENDOR_FROM_DATABASE=Snell & Wilcox acpi:SNX*: ID_VENDOR_FROM_DATABASE=Sonix Comm. Ltd acpi:SNY*: ID_VENDOR_FROM_DATABASE=Sony acpi:SOI*: ID_VENDOR_FROM_DATABASE=Silicon Optix Corporation acpi:SOL*: ID_VENDOR_FROM_DATABASE=Solitron Technologies Inc acpi:SON*: ID_VENDOR_FROM_DATABASE=Sony acpi:SOR*: ID_VENDOR_FROM_DATABASE=Sorcus Computer GmbH acpi:SOT*: ID_VENDOR_FROM_DATABASE=Sotec Company Ltd acpi:SOY*: ID_VENDOR_FROM_DATABASE=SOYO Group, Inc acpi:SPC*: ID_VENDOR_FROM_DATABASE=SpinCore Technologies, Inc acpi:SPE*: ID_VENDOR_FROM_DATABASE=SPEA Software AG acpi:SPH*: ID_VENDOR_FROM_DATABASE=G&W Instruments GmbH acpi:SPI*: ID_VENDOR_FROM_DATABASE=SPACE-I Co., Ltd. acpi:SPK*: ID_VENDOR_FROM_DATABASE=SpeakerCraft acpi:SPL*: ID_VENDOR_FROM_DATABASE=Smart Silicon Systems Pty Ltd acpi:SPN*: ID_VENDOR_FROM_DATABASE=Sapience Corporation acpi:SPR*: ID_VENDOR_FROM_DATABASE=pmns GmbH acpi:SPS*: ID_VENDOR_FROM_DATABASE=Synopsys Inc acpi:SPT*: ID_VENDOR_FROM_DATABASE=Sceptre Tech Inc acpi:SPU*: ID_VENDOR_FROM_DATABASE=SIM2 Multimedia S.P.A. acpi:SPX*: ID_VENDOR_FROM_DATABASE=Simplex Time Recorder Co. acpi:SQT*: ID_VENDOR_FROM_DATABASE=Sequent Computer Systems Inc acpi:SRC*: ID_VENDOR_FROM_DATABASE=Integrated Tech Express Inc acpi:SRD*: ID_VENDOR_FROM_DATABASE=Setred acpi:SRF*: ID_VENDOR_FROM_DATABASE=Surf Communication Solutions Ltd acpi:SRG*: ID_VENDOR_FROM_DATABASE=Intuitive Surgical, Inc. acpi:SRT*: ID_VENDOR_FROM_DATABASE=SeeReal Technologies GmbH acpi:SSC*: ID_VENDOR_FROM_DATABASE=Sierra Semiconductor Inc acpi:SSD*: ID_VENDOR_FROM_DATABASE=FlightSafety International acpi:SSE*: ID_VENDOR_FROM_DATABASE=Samsung Electronic Co. acpi:SSI*: ID_VENDOR_FROM_DATABASE=S-S Technology Inc acpi:SSJ*: ID_VENDOR_FROM_DATABASE=Sankyo Seiki Mfg.co., Ltd acpi:SSP*: ID_VENDOR_FROM_DATABASE=Spectrum Signal Proecessing Inc acpi:SSS*: ID_VENDOR_FROM_DATABASE=S3 Inc acpi:SST*: ID_VENDOR_FROM_DATABASE=SystemSoft Corporation acpi:STA*: ID_VENDOR_FROM_DATABASE=ST Electronics Systems Assembly Pte Ltd acpi:STB*: ID_VENDOR_FROM_DATABASE=STB Systems Inc acpi:STC*: ID_VENDOR_FROM_DATABASE=STAC Electronics acpi:STD*: ID_VENDOR_FROM_DATABASE=STD Computer Inc acpi:STE*: ID_VENDOR_FROM_DATABASE=SII Ido-Tsushin Inc acpi:STF*: ID_VENDOR_FROM_DATABASE=Starflight Electronics acpi:STG*: ID_VENDOR_FROM_DATABASE=StereoGraphics Corp. acpi:STH*: ID_VENDOR_FROM_DATABASE=Semtech Corporation acpi:STI*: ID_VENDOR_FROM_DATABASE=Smart Tech Inc acpi:STK*: ID_VENDOR_FROM_DATABASE=SANTAK CORP. acpi:STL*: ID_VENDOR_FROM_DATABASE=SigmaTel Inc acpi:STM*: ID_VENDOR_FROM_DATABASE=SGS Thomson Microelectronics acpi:STN*: ID_VENDOR_FROM_DATABASE=Samsung Electronics America acpi:STO*: ID_VENDOR_FROM_DATABASE=Stollmann E+V GmbH acpi:STP*: ID_VENDOR_FROM_DATABASE=StreamPlay Ltd acpi:STR*: ID_VENDOR_FROM_DATABASE=Starlight Networks Inc acpi:STS*: ID_VENDOR_FROM_DATABASE=SITECSYSTEM CO., LTD. acpi:STT*: ID_VENDOR_FROM_DATABASE=Star Paging Telecom Tech (Shenzhen) Co. Ltd. acpi:STU*: ID_VENDOR_FROM_DATABASE=Sentelic Corporation acpi:STW*: ID_VENDOR_FROM_DATABASE=Starwin Inc. acpi:STX*: ID_VENDOR_FROM_DATABASE=ST-Ericsson acpi:STY*: ID_VENDOR_FROM_DATABASE=SDS Technologies acpi:SUB*: ID_VENDOR_FROM_DATABASE=Subspace Comm. Inc acpi:SUM*: ID_VENDOR_FROM_DATABASE=Summagraphics Corporation acpi:SUN*: ID_VENDOR_FROM_DATABASE=Sun Electronics Corporation acpi:SUP*: ID_VENDOR_FROM_DATABASE=Supra Corporation acpi:SUR*: ID_VENDOR_FROM_DATABASE=Surenam Computer Corporation acpi:SVA*: ID_VENDOR_FROM_DATABASE=SGEG acpi:SVC*: ID_VENDOR_FROM_DATABASE=Intellix Corp. acpi:SVD*: ID_VENDOR_FROM_DATABASE=SVD Computer acpi:SVI*: ID_VENDOR_FROM_DATABASE=Sun Microsystems acpi:SVS*: ID_VENDOR_FROM_DATABASE=SVSI acpi:SVT*: ID_VENDOR_FROM_DATABASE=SEVIT Co., Ltd. acpi:SWC*: ID_VENDOR_FROM_DATABASE=Software Café acpi:SWI*: ID_VENDOR_FROM_DATABASE=Sierra Wireless Inc. acpi:SWL*: ID_VENDOR_FROM_DATABASE=Sharedware Ltd acpi:SWS*: ID_VENDOR_FROM_DATABASE=Static acpi:SWT*: ID_VENDOR_FROM_DATABASE=Software Technologies Group,Inc. acpi:SXB*: ID_VENDOR_FROM_DATABASE=Syntax-Brillian acpi:SXD*: ID_VENDOR_FROM_DATABASE=Silex technology, Inc. acpi:SXL*: ID_VENDOR_FROM_DATABASE=SolutionInside acpi:SXT*: ID_VENDOR_FROM_DATABASE=SHARP TAKAYA ELECTRONIC INDUSTRY CO.,LTD. acpi:SYC*: ID_VENDOR_FROM_DATABASE=Sysmic acpi:SYE*: ID_VENDOR_FROM_DATABASE=SY Electronics Ltd acpi:SYK*: ID_VENDOR_FROM_DATABASE=Stryker Communications acpi:SYL*: ID_VENDOR_FROM_DATABASE=Sylvania Computer Products acpi:SYM*: ID_VENDOR_FROM_DATABASE=Symicron Computer Communications Ltd. acpi:SYN*: ID_VENDOR_FROM_DATABASE=Synaptics Inc acpi:SYP*: ID_VENDOR_FROM_DATABASE=SYPRO Co Ltd acpi:SYS*: ID_VENDOR_FROM_DATABASE=Sysgration Ltd acpi:SYT*: ID_VENDOR_FROM_DATABASE=Seyeon Tech Company Ltd acpi:SYV*: ID_VENDOR_FROM_DATABASE=SYVAX Inc acpi:SYX*: ID_VENDOR_FROM_DATABASE=Prime Systems, Inc. acpi:TAA*: ID_VENDOR_FROM_DATABASE=Tandberg acpi:TAB*: ID_VENDOR_FROM_DATABASE=Todos Data System AB acpi:TAG*: ID_VENDOR_FROM_DATABASE=Teles AG acpi:TAI*: ID_VENDOR_FROM_DATABASE=Toshiba America Info Systems Inc acpi:TAM*: ID_VENDOR_FROM_DATABASE=Tamura Seisakusyo Ltd acpi:TAS*: ID_VENDOR_FROM_DATABASE=Taskit Rechnertechnik GmbH acpi:TAT*: ID_VENDOR_FROM_DATABASE=Teleliaison Inc acpi:TAX*: ID_VENDOR_FROM_DATABASE=Taxan (Europe) Ltd acpi:TBB*: ID_VENDOR_FROM_DATABASE=Triple S Engineering Inc acpi:TBC*: ID_VENDOR_FROM_DATABASE=Turbo Communication, Inc acpi:TBS*: ID_VENDOR_FROM_DATABASE=Turtle Beach System acpi:TCC*: ID_VENDOR_FROM_DATABASE=Tandon Corporation acpi:TCD*: ID_VENDOR_FROM_DATABASE=Taicom Data Systems Co., Ltd. acpi:TCE*: ID_VENDOR_FROM_DATABASE=Century Corporation acpi:TCH*: ID_VENDOR_FROM_DATABASE=Interaction Systems, Inc acpi:TCI*: ID_VENDOR_FROM_DATABASE=Tulip Computers Int'l B.V. acpi:TCJ*: ID_VENDOR_FROM_DATABASE=TEAC America Inc acpi:TCL*: ID_VENDOR_FROM_DATABASE=Technical Concepts Ltd acpi:TCM*: ID_VENDOR_FROM_DATABASE=3Com Corporation acpi:TCN*: ID_VENDOR_FROM_DATABASE=Tecnetics (PTY) Ltd acpi:TCO*: ID_VENDOR_FROM_DATABASE=Thomas-Conrad Corporation acpi:TCR*: ID_VENDOR_FROM_DATABASE=Thomson Consumer Electronics acpi:TCS*: ID_VENDOR_FROM_DATABASE=Tatung Company of America Inc acpi:TCT*: ID_VENDOR_FROM_DATABASE=Telecom Technology Centre Co. Ltd. acpi:TCX*: ID_VENDOR_FROM_DATABASE=FREEMARS Heavy Industries acpi:TDC*: ID_VENDOR_FROM_DATABASE=Teradici acpi:TDD*: ID_VENDOR_FROM_DATABASE=Tandberg Data Display AS acpi:TDK*: ID_VENDOR_FROM_DATABASE=TDK USA Corporation acpi:TDM*: ID_VENDOR_FROM_DATABASE=Tandem Computer Europe Inc acpi:TDP*: ID_VENDOR_FROM_DATABASE=3D Perception acpi:TDS*: ID_VENDOR_FROM_DATABASE=Tri-Data Systems Inc acpi:TDT*: ID_VENDOR_FROM_DATABASE=TDT acpi:TDV*: ID_VENDOR_FROM_DATABASE=TDVision Systems, Inc. acpi:TDY*: ID_VENDOR_FROM_DATABASE=Tandy Electronics acpi:TEA*: ID_VENDOR_FROM_DATABASE=TEAC System Corporation acpi:TEC*: ID_VENDOR_FROM_DATABASE=Tecmar Inc acpi:TEK*: ID_VENDOR_FROM_DATABASE=Tektronix Inc acpi:TEL*: ID_VENDOR_FROM_DATABASE=Promotion and Display Technology Ltd. acpi:TER*: ID_VENDOR_FROM_DATABASE=TerraTec Electronic GmbH acpi:TGC*: ID_VENDOR_FROM_DATABASE=Toshiba Global Commerce Solutions, Inc. acpi:TGI*: ID_VENDOR_FROM_DATABASE=TriGem Computer Inc acpi:TGM*: ID_VENDOR_FROM_DATABASE=TriGem Computer,Inc. acpi:TGS*: ID_VENDOR_FROM_DATABASE=Torus Systems Ltd acpi:TGV*: ID_VENDOR_FROM_DATABASE=Grass Valley Germany GmbH acpi:THN*: ID_VENDOR_FROM_DATABASE=Thundercom Holdings Sdn. Bhd. acpi:TIC*: ID_VENDOR_FROM_DATABASE=Trigem KinfoComm acpi:TIP*: ID_VENDOR_FROM_DATABASE=TIPTEL AG acpi:TIV*: ID_VENDOR_FROM_DATABASE=OOO Technoinvest acpi:TIX*: ID_VENDOR_FROM_DATABASE=Tixi.Com GmbH acpi:TKC*: ID_VENDOR_FROM_DATABASE=Taiko Electric Works.LTD acpi:TKN*: ID_VENDOR_FROM_DATABASE=Teknor Microsystem Inc acpi:TKO*: ID_VENDOR_FROM_DATABASE=TouchKo, Inc. acpi:TKS*: ID_VENDOR_FROM_DATABASE=TimeKeeping Systems, Inc. acpi:TLA*: ID_VENDOR_FROM_DATABASE=Ferrari Electronic GmbH acpi:TLD*: ID_VENDOR_FROM_DATABASE=Telindus acpi:TLI*: ID_VENDOR_FROM_DATABASE=TOSHIBA TELI CORPORATION acpi:TLK*: ID_VENDOR_FROM_DATABASE=Telelink AG acpi:TLS*: ID_VENDOR_FROM_DATABASE=Teleste Educational OY acpi:TLT*: ID_VENDOR_FROM_DATABASE=Dai Telecom S.p.A. acpi:TLV*: ID_VENDOR_FROM_DATABASE=S3 Inc acpi:TLX*: ID_VENDOR_FROM_DATABASE=Telxon Corporation acpi:TMC*: ID_VENDOR_FROM_DATABASE=Techmedia Computer Systems Corporation acpi:TME*: ID_VENDOR_FROM_DATABASE=AT&T Microelectronics acpi:TMI*: ID_VENDOR_FROM_DATABASE=Texas Microsystem acpi:TMM*: ID_VENDOR_FROM_DATABASE=Time Management, Inc. acpi:TMR*: ID_VENDOR_FROM_DATABASE=Taicom International Inc acpi:TMS*: ID_VENDOR_FROM_DATABASE=Trident Microsystems Ltd acpi:TMT*: ID_VENDOR_FROM_DATABASE=T-Metrics Inc. acpi:TMX*: ID_VENDOR_FROM_DATABASE=Thermotrex Corporation acpi:TNC*: ID_VENDOR_FROM_DATABASE=TNC Industrial Company Ltd acpi:TNM*: ID_VENDOR_FROM_DATABASE=TECNIMAGEN SA acpi:TNY*: ID_VENDOR_FROM_DATABASE=Tennyson Tech Pty Ltd acpi:TOE*: ID_VENDOR_FROM_DATABASE=TOEI Electronics Co., Ltd. acpi:TOG*: ID_VENDOR_FROM_DATABASE=The OPEN Group acpi:TON*: ID_VENDOR_FROM_DATABASE=TONNA acpi:TOP*: ID_VENDOR_FROM_DATABASE=Orion Communications Co., Ltd. acpi:TOS*: ID_VENDOR_FROM_DATABASE=Toshiba Corporation acpi:TOU*: ID_VENDOR_FROM_DATABASE=Touchstone Technology acpi:TPC*: ID_VENDOR_FROM_DATABASE=Touch Panel Systems Corporation acpi:TPE*: ID_VENDOR_FROM_DATABASE=Technology Power Enterprises Inc acpi:TPJ*: ID_VENDOR_FROM_DATABASE=Junnila acpi:TPK*: ID_VENDOR_FROM_DATABASE=TOPRE CORPORATION acpi:TPR*: ID_VENDOR_FROM_DATABASE=Topro Technology Inc acpi:TPS*: ID_VENDOR_FROM_DATABASE=Teleprocessing Systeme GmbH acpi:TPT*: ID_VENDOR_FROM_DATABASE=Thruput Ltd acpi:TPV*: ID_VENDOR_FROM_DATABASE=Top Victory Electronics ( Fujian ) Company Ltd acpi:TPZ*: ID_VENDOR_FROM_DATABASE=Ypoaz Systems Inc acpi:TRA*: ID_VENDOR_FROM_DATABASE=TriTech Microelectronics International acpi:TRC*: ID_VENDOR_FROM_DATABASE=Trioc AB acpi:TRD*: ID_VENDOR_FROM_DATABASE=Trident Microsystem Inc acpi:TRE*: ID_VENDOR_FROM_DATABASE=Tremetrics acpi:TRI*: ID_VENDOR_FROM_DATABASE=Tricord Systems acpi:TRL*: ID_VENDOR_FROM_DATABASE=Royal Information acpi:TRM*: ID_VENDOR_FROM_DATABASE=Tekram Technology Company Ltd acpi:TRN*: ID_VENDOR_FROM_DATABASE=Datacommunicatie Tron B.V. acpi:TRS*: ID_VENDOR_FROM_DATABASE=Torus Systems Ltd acpi:TRT*: ID_VENDOR_FROM_DATABASE=Tritec Electronic AG acpi:TRU*: ID_VENDOR_FROM_DATABASE=Aashima Technology B.V. acpi:TRV*: ID_VENDOR_FROM_DATABASE=Trivisio Prototyping GmbH acpi:TRX*: ID_VENDOR_FROM_DATABASE=Trex Enterprises acpi:TSB*: ID_VENDOR_FROM_DATABASE=Toshiba America Info Systems Inc acpi:TSC*: ID_VENDOR_FROM_DATABASE=Sanyo Electric Company Ltd acpi:TSD*: ID_VENDOR_FROM_DATABASE=TechniSat Digital GmbH acpi:TSE*: ID_VENDOR_FROM_DATABASE=Tottori Sanyo Electric acpi:TSF*: ID_VENDOR_FROM_DATABASE=Racal-Airtech Software Forge Ltd acpi:TSG*: ID_VENDOR_FROM_DATABASE=The Software Group Ltd acpi:TSI*: ID_VENDOR_FROM_DATABASE=TeleVideo Systems acpi:TSL*: ID_VENDOR_FROM_DATABASE=Tottori SANYO Electric Co., Ltd. acpi:TSP*: ID_VENDOR_FROM_DATABASE=U.S. Navy acpi:TST*: ID_VENDOR_FROM_DATABASE=Transtream Inc acpi:TSV*: ID_VENDOR_FROM_DATABASE=TRANSVIDEO acpi:TSY*: ID_VENDOR_FROM_DATABASE=TouchSystems acpi:TTA*: ID_VENDOR_FROM_DATABASE=Topson Technology Co., Ltd. acpi:TTB*: ID_VENDOR_FROM_DATABASE=National Semiconductor Japan Ltd acpi:TTC*: ID_VENDOR_FROM_DATABASE=Telecommunications Techniques Corporation acpi:TTE*: ID_VENDOR_FROM_DATABASE=TTE, Inc. acpi:TTI*: ID_VENDOR_FROM_DATABASE=Trenton Terminals Inc acpi:TTK*: ID_VENDOR_FROM_DATABASE=Totoku Electric Company Ltd acpi:TTL*: ID_VENDOR_FROM_DATABASE=2-Tel B.V. acpi:TTS*: ID_VENDOR_FROM_DATABASE=TechnoTrend Systemtechnik GmbH acpi:TTY*: ID_VENDOR_FROM_DATABASE=TRIDELITY Display Solutions GmbH acpi:TUA*: ID_VENDOR_FROM_DATABASE=T+A elektroakustik GmbH acpi:TUT*: ID_VENDOR_FROM_DATABASE=Tut Systems acpi:TVD*: ID_VENDOR_FROM_DATABASE=Tecnovision acpi:TVI*: ID_VENDOR_FROM_DATABASE=Truevision acpi:TVM*: ID_VENDOR_FROM_DATABASE=Taiwan Video & Monitor Corporation acpi:TVO*: ID_VENDOR_FROM_DATABASE=TV One Ltd acpi:TVR*: ID_VENDOR_FROM_DATABASE=TV Interactive Corporation acpi:TVS*: ID_VENDOR_FROM_DATABASE=TVS Electronics Limited acpi:TVV*: ID_VENDOR_FROM_DATABASE=TV1 GmbH acpi:TWA*: ID_VENDOR_FROM_DATABASE=Tidewater Association acpi:TWE*: ID_VENDOR_FROM_DATABASE=Kontron Electronik acpi:TWH*: ID_VENDOR_FROM_DATABASE=Twinhead International Corporation acpi:TWI*: ID_VENDOR_FROM_DATABASE=Easytel oy acpi:TWK*: ID_VENDOR_FROM_DATABASE=TOWITOKO electronics GmbH acpi:TWX*: ID_VENDOR_FROM_DATABASE=TEKWorx Limited acpi:TXL*: ID_VENDOR_FROM_DATABASE=Trixel Ltd acpi:TXN*: ID_VENDOR_FROM_DATABASE=Texas Insturments acpi:TXT*: ID_VENDOR_FROM_DATABASE=Textron Defense System acpi:TYN*: ID_VENDOR_FROM_DATABASE=Tyan Computer Corporation acpi:UAS*: ID_VENDOR_FROM_DATABASE=Ultima Associates Pte Ltd acpi:UBI*: ID_VENDOR_FROM_DATABASE=Ungermann-Bass Inc acpi:UBL*: ID_VENDOR_FROM_DATABASE=Ubinetics Ltd. acpi:UDN*: ID_VENDOR_FROM_DATABASE=Uniden Corporation acpi:UEC*: ID_VENDOR_FROM_DATABASE=Ultima Electronics Corporation acpi:UEG*: ID_VENDOR_FROM_DATABASE=Elitegroup Computer Systems Company Ltd acpi:UEI*: ID_VENDOR_FROM_DATABASE=Universal Electronics Inc acpi:UET*: ID_VENDOR_FROM_DATABASE=Universal Empowering Technologies acpi:UFG*: ID_VENDOR_FROM_DATABASE=UNIGRAF-USA acpi:UFO*: ID_VENDOR_FROM_DATABASE=UFO Systems Inc acpi:UHB*: ID_VENDOR_FROM_DATABASE=XOCECO acpi:UIC*: ID_VENDOR_FROM_DATABASE=Uniform Industrial Corporation acpi:UJR*: ID_VENDOR_FROM_DATABASE=Ueda Japan Radio Co., Ltd. acpi:ULT*: ID_VENDOR_FROM_DATABASE=Ultra Network Tech acpi:UMC*: ID_VENDOR_FROM_DATABASE=United Microelectr Corporation acpi:UMG*: ID_VENDOR_FROM_DATABASE=Umezawa Giken Co.,Ltd acpi:UMM*: ID_VENDOR_FROM_DATABASE=Universal Multimedia acpi:UNA*: ID_VENDOR_FROM_DATABASE=Unisys DSD acpi:UNB*: ID_VENDOR_FROM_DATABASE=Unisys Corporation acpi:UNC*: ID_VENDOR_FROM_DATABASE=Unisys Corporation acpi:UNI*: ID_VENDOR_FROM_DATABASE=Unisys Corporation acpi:UNM*: ID_VENDOR_FROM_DATABASE=Unisys Corporation acpi:UNO*: ID_VENDOR_FROM_DATABASE=Unisys Corporation acpi:UNP*: ID_VENDOR_FROM_DATABASE=Unitop acpi:UNS*: ID_VENDOR_FROM_DATABASE=Unisys Corporation acpi:UNT*: ID_VENDOR_FROM_DATABASE=Unisys Corporation acpi:UNY*: ID_VENDOR_FROM_DATABASE=Unicate acpi:UPP*: ID_VENDOR_FROM_DATABASE=UPPI acpi:UPS*: ID_VENDOR_FROM_DATABASE=Systems Enhancement acpi:URD*: ID_VENDOR_FROM_DATABASE=Video Computer S.p.A. acpi:USA*: ID_VENDOR_FROM_DATABASE=Utimaco Safeware AG acpi:USD*: ID_VENDOR_FROM_DATABASE=U.S. Digital Corporation acpi:USI*: ID_VENDOR_FROM_DATABASE=Universal Scientific Industrial Co., Ltd. acpi:USR*: ID_VENDOR_FROM_DATABASE=U.S. Robotics Inc acpi:UTD*: ID_VENDOR_FROM_DATABASE=Up to Date Tech acpi:UWC*: ID_VENDOR_FROM_DATABASE=Uniwill Computer Corp. acpi:VAL*: ID_VENDOR_FROM_DATABASE=Valence Computing Corporation acpi:VAR*: ID_VENDOR_FROM_DATABASE=Varian Australia Pty Ltd acpi:VBR*: ID_VENDOR_FROM_DATABASE=VBrick Systems Inc. acpi:VBT*: ID_VENDOR_FROM_DATABASE=Valley Board Ltda acpi:VCC*: ID_VENDOR_FROM_DATABASE=Virtual Computer Corporation acpi:VCI*: ID_VENDOR_FROM_DATABASE=VistaCom Inc acpi:VCJ*: ID_VENDOR_FROM_DATABASE=Victor Company of Japan, Limited acpi:VCM*: ID_VENDOR_FROM_DATABASE=Vector Magnetics, LLC acpi:VCX*: ID_VENDOR_FROM_DATABASE=VCONEX acpi:VDA*: ID_VENDOR_FROM_DATABASE=Victor Data Systems acpi:VDC*: ID_VENDOR_FROM_DATABASE=VDC Display Systems acpi:VDM*: ID_VENDOR_FROM_DATABASE=Vadem acpi:VDO*: ID_VENDOR_FROM_DATABASE=Video & Display Oriented Corporation acpi:VDS*: ID_VENDOR_FROM_DATABASE=Vidisys GmbH & Company acpi:VDT*: ID_VENDOR_FROM_DATABASE=Viditec, Inc. acpi:VEC*: ID_VENDOR_FROM_DATABASE=Vector Informatik GmbH acpi:VEK*: ID_VENDOR_FROM_DATABASE=Vektrex acpi:VES*: ID_VENDOR_FROM_DATABASE=Vestel Elektronik Sanayi ve Ticaret A. S. acpi:VFI*: ID_VENDOR_FROM_DATABASE=VeriFone Inc acpi:VHI*: ID_VENDOR_FROM_DATABASE=Macrocad Development Inc. acpi:VIA*: ID_VENDOR_FROM_DATABASE=VIA Tech Inc acpi:VIB*: ID_VENDOR_FROM_DATABASE=Tatung UK Ltd acpi:VIC*: ID_VENDOR_FROM_DATABASE=Victron B.V. acpi:VID*: ID_VENDOR_FROM_DATABASE=Ingram Macrotron Germany acpi:VIK*: ID_VENDOR_FROM_DATABASE=Viking Connectors acpi:VIN*: ID_VENDOR_FROM_DATABASE=Vine Micros Ltd acpi:VIR*: ID_VENDOR_FROM_DATABASE=Visual Interface, Inc acpi:VIS*: ID_VENDOR_FROM_DATABASE=Visioneer acpi:VIT*: ID_VENDOR_FROM_DATABASE=Visitech AS acpi:VIZ*: ID_VENDOR_FROM_DATABASE=VIZIO, Inc acpi:VLB*: ID_VENDOR_FROM_DATABASE=ValleyBoard Ltda. acpi:VLT*: ID_VENDOR_FROM_DATABASE=VideoLan Technologies acpi:VMI*: ID_VENDOR_FROM_DATABASE=Vermont Microsystems acpi:VML*: ID_VENDOR_FROM_DATABASE=Vine Micros Limited acpi:VMW*: ID_VENDOR_FROM_DATABASE=VMware Inc., acpi:VNC*: ID_VENDOR_FROM_DATABASE=Vinca Corporation acpi:VOB*: ID_VENDOR_FROM_DATABASE=MaxData Computer AG acpi:VPI*: ID_VENDOR_FROM_DATABASE=Video Products Inc acpi:VPR*: ID_VENDOR_FROM_DATABASE=Best Buy acpi:VQ@*: ID_VENDOR_FROM_DATABASE=Vision Quest acpi:VRC*: ID_VENDOR_FROM_DATABASE=Virtual Resources Corporation acpi:VSC*: ID_VENDOR_FROM_DATABASE=ViewSonic Corporation acpi:VSD*: ID_VENDOR_FROM_DATABASE=3M acpi:VSI*: ID_VENDOR_FROM_DATABASE=VideoServer acpi:VSN*: ID_VENDOR_FROM_DATABASE=Ingram Macrotron acpi:VSP*: ID_VENDOR_FROM_DATABASE=Vision Systems GmbH acpi:VSR*: ID_VENDOR_FROM_DATABASE=V-Star Electronics Inc. acpi:VTC*: ID_VENDOR_FROM_DATABASE=VTel Corporation acpi:VTG*: ID_VENDOR_FROM_DATABASE=Voice Technologies Group Inc acpi:VTI*: ID_VENDOR_FROM_DATABASE=VLSI Tech Inc acpi:VTK*: ID_VENDOR_FROM_DATABASE=Viewteck Co., Ltd. acpi:VTL*: ID_VENDOR_FROM_DATABASE=Vivid Technology Pte Ltd acpi:VTM*: ID_VENDOR_FROM_DATABASE=Miltope Corporation acpi:VTN*: ID_VENDOR_FROM_DATABASE=VIDEOTRON CORP. acpi:VTS*: ID_VENDOR_FROM_DATABASE=VTech Computers Ltd acpi:VTV*: ID_VENDOR_FROM_DATABASE=VATIV Technologies acpi:VTX*: ID_VENDOR_FROM_DATABASE=Vestax Corporation acpi:VUT*: ID_VENDOR_FROM_DATABASE=Vutrix (UK) Ltd acpi:VWB*: ID_VENDOR_FROM_DATABASE=Vweb Corp. acpi:WAC*: ID_VENDOR_FROM_DATABASE=Wacom Tech acpi:WAL*: ID_VENDOR_FROM_DATABASE=Wave Access acpi:WAV*: ID_VENDOR_FROM_DATABASE=Wavephore acpi:WBN*: ID_VENDOR_FROM_DATABASE=MicroSoftWare acpi:WBS*: ID_VENDOR_FROM_DATABASE=WB Systemtechnik GmbH acpi:WCI*: ID_VENDOR_FROM_DATABASE=Wisecom Inc acpi:WCS*: ID_VENDOR_FROM_DATABASE=Woodwind Communications Systems Inc acpi:WDC*: ID_VENDOR_FROM_DATABASE=Western Digital acpi:WDE*: ID_VENDOR_FROM_DATABASE=Westinghouse Digital Electronics acpi:WEB*: ID_VENDOR_FROM_DATABASE=WebGear Inc acpi:WEC*: ID_VENDOR_FROM_DATABASE=Winbond Electronics Corporation acpi:WEL *: ID_VENDOR_FROM_DATABASE=W-DEV acpi:WEY*: ID_VENDOR_FROM_DATABASE=WEY Design AG acpi:WHI*: ID_VENDOR_FROM_DATABASE=Whistle Communications acpi:WII*: ID_VENDOR_FROM_DATABASE=Innoware Inc acpi:WIL*: ID_VENDOR_FROM_DATABASE=WIPRO Information Technology Ltd acpi:WIN*: ID_VENDOR_FROM_DATABASE=Wintop Technology Inc acpi:WIP*: ID_VENDOR_FROM_DATABASE=Wipro Infotech acpi:WKH*: ID_VENDOR_FROM_DATABASE=Uni-Take Int'l Inc. acpi:WLD*: ID_VENDOR_FROM_DATABASE=Wildfire Communications Inc acpi:WML*: ID_VENDOR_FROM_DATABASE=Wolfson Microelectronics Ltd acpi:WMO*: ID_VENDOR_FROM_DATABASE=Westermo Teleindustri AB acpi:WMT*: ID_VENDOR_FROM_DATABASE=Winmate Communication Inc acpi:WNI*: ID_VENDOR_FROM_DATABASE=WillNet Inc. acpi:WNV*: ID_VENDOR_FROM_DATABASE=Winnov L.P. acpi:WNX*: ID_VENDOR_FROM_DATABASE=Wincor Nixdorf International GmbH acpi:WPA*: ID_VENDOR_FROM_DATABASE=Matsushita Communication Industrial Co., Ltd. acpi:WPI*: ID_VENDOR_FROM_DATABASE=Wearnes Peripherals International (Pte) Ltd acpi:WRC*: ID_VENDOR_FROM_DATABASE=WiNRADiO Communications acpi:WSC*: ID_VENDOR_FROM_DATABASE=CIS Technology Inc acpi:WSP*: ID_VENDOR_FROM_DATABASE=Wireless And Smart Products Inc. acpi:WST*: ID_VENDOR_FROM_DATABASE=Wistron Corporation acpi:WTC*: ID_VENDOR_FROM_DATABASE=ACC Microelectronics acpi:WTI*: ID_VENDOR_FROM_DATABASE=WorkStation Tech acpi:WTK*: ID_VENDOR_FROM_DATABASE=Wearnes Thakral Pte acpi:WTS*: ID_VENDOR_FROM_DATABASE=Restek Electric Company Ltd acpi:WVM*: ID_VENDOR_FROM_DATABASE=Wave Systems Corporation acpi:WWV*: ID_VENDOR_FROM_DATABASE=World Wide Video, Inc. acpi:WXT*: ID_VENDOR_FROM_DATABASE=Woxter Technology Co. Ltd acpi:WYS*: ID_VENDOR_FROM_DATABASE=Myse Technology acpi:WYT*: ID_VENDOR_FROM_DATABASE=Wooyoung Image & Information Co.,Ltd. acpi:XAC*: ID_VENDOR_FROM_DATABASE=XAC Automation Corp acpi:XAD*: ID_VENDOR_FROM_DATABASE=Alpha Data acpi:XDM*: ID_VENDOR_FROM_DATABASE=XDM Ltd. acpi:XFG*: ID_VENDOR_FROM_DATABASE=Jan Strapko - FOTO acpi:XFO*: ID_VENDOR_FROM_DATABASE=EXFO Electro Optical Engineering acpi:XIN*: ID_VENDOR_FROM_DATABASE=Xinex Networks Inc acpi:XIO*: ID_VENDOR_FROM_DATABASE=Xiotech Corporation acpi:XIR*: ID_VENDOR_FROM_DATABASE=Xirocm Inc acpi:XIT*: ID_VENDOR_FROM_DATABASE=Xitel Pty ltd acpi:XLX*: ID_VENDOR_FROM_DATABASE=Xilinx, Inc. acpi:XMM*: ID_VENDOR_FROM_DATABASE=C3PO S.L. acpi:XNT*: ID_VENDOR_FROM_DATABASE=XN Technologies, Inc. acpi:XQU*: ID_VENDOR_FROM_DATABASE=SHANGHAI SVA-DAV ELECTRONICS CO., LTD acpi:XRC*: ID_VENDOR_FROM_DATABASE=Xircom Inc acpi:XRO*: ID_VENDOR_FROM_DATABASE=XORO ELECTRONICS (CHENGDU) LIMITED acpi:XSN*: ID_VENDOR_FROM_DATABASE=Xscreen AS acpi:XST*: ID_VENDOR_FROM_DATABASE=XS Technologies Inc acpi:XSY*: ID_VENDOR_FROM_DATABASE=XSYS acpi:XTD*: ID_VENDOR_FROM_DATABASE=Icuiti Corporation acpi:XTE*: ID_VENDOR_FROM_DATABASE=X2E GmbH acpi:XTL*: ID_VENDOR_FROM_DATABASE=Crystal Computer acpi:XTN*: ID_VENDOR_FROM_DATABASE=X-10 (USA) Inc acpi:XYC*: ID_VENDOR_FROM_DATABASE=Xycotec Computer GmbH acpi:YED*: ID_VENDOR_FROM_DATABASE=Y-E Data Inc acpi:YHQ*: ID_VENDOR_FROM_DATABASE=Yokogawa Electric Corporation acpi:YHW*: ID_VENDOR_FROM_DATABASE=Exacom SA acpi:YMH*: ID_VENDOR_FROM_DATABASE=Yamaha Corporation acpi:YOW*: ID_VENDOR_FROM_DATABASE=American Biometric Company acpi:ZAN*: ID_VENDOR_FROM_DATABASE=Zandar Technologies plc acpi:ZAX*: ID_VENDOR_FROM_DATABASE=Zefiro Acoustics acpi:ZAZ*: ID_VENDOR_FROM_DATABASE=Zazzle Technologies acpi:ZBR*: ID_VENDOR_FROM_DATABASE=Zebra Technologies International, LLC acpi:ZCT*: ID_VENDOR_FROM_DATABASE=ZeitControl cardsystems GmbH acpi:ZDS*: ID_VENDOR_FROM_DATABASE=Zenith Data Systems acpi:ZGT*: ID_VENDOR_FROM_DATABASE=Zenith Data Systems acpi:ZIC*: ID_VENDOR_FROM_DATABASE=Nationz Technologies Inc. acpi:ZMT*: ID_VENDOR_FROM_DATABASE=Zalman Tech Co., Ltd. acpi:ZMZ*: ID_VENDOR_FROM_DATABASE=Z Microsystems acpi:ZNI*: ID_VENDOR_FROM_DATABASE=Zetinet Inc acpi:ZNX*: ID_VENDOR_FROM_DATABASE=Znyx Adv. Systems acpi:ZOW*: ID_VENDOR_FROM_DATABASE=Zowie Intertainment, Inc acpi:ZRN*: ID_VENDOR_FROM_DATABASE=Zoran Corporation acpi:ZSE*: ID_VENDOR_FROM_DATABASE=Zenith Data Systems acpi:ZTC*: ID_VENDOR_FROM_DATABASE=ZyDAS Technology Corporation acpi:ZTE*: ID_VENDOR_FROM_DATABASE=ZTE Corporation acpi:ZTI*: ID_VENDOR_FROM_DATABASE=Zoom Telephonics Inc acpi:ZTM*: ID_VENDOR_FROM_DATABASE=ZT Group Int'l Inc. acpi:ZTT*: ID_VENDOR_FROM_DATABASE=Z3 Technology acpi:ZYD*: ID_VENDOR_FROM_DATABASE=Zydacron Inc acpi:ZYP*: ID_VENDOR_FROM_DATABASE=Zypcom Inc acpi:ZYT*: ID_VENDOR_FROM_DATABASE=Zytex Computers acpi:ZYX*: ID_VENDOR_FROM_DATABASE=Zyxel acpi:ZZZ*: ID_VENDOR_FROM_DATABASE=Boca Research Inc systemd-229/hwdb/20-bluetooth-vendor-product.hwdb000066400000000000000000001327571265713322000220670ustar00rootroot00000000000000# This file is part of systemd. # # Data imported from: # http://www.bluetooth.org/Technical/AssignedNumbers/identifiers.htm bluetooth:v0000* ID_VENDOR_FROM_DATABASE=Ericsson Technology Licensing bluetooth:v0001* ID_VENDOR_FROM_DATABASE=Nokia Mobile Phones bluetooth:v0002* ID_VENDOR_FROM_DATABASE=Intel Corp. bluetooth:v0003* ID_VENDOR_FROM_DATABASE=IBM Corp. bluetooth:v0004* ID_VENDOR_FROM_DATABASE=Toshiba Corp. bluetooth:v0005* ID_VENDOR_FROM_DATABASE=3Com bluetooth:v0006* ID_VENDOR_FROM_DATABASE=Microsoft bluetooth:v0007* ID_VENDOR_FROM_DATABASE=Lucent bluetooth:v0008* ID_VENDOR_FROM_DATABASE=Motorola bluetooth:v0009* ID_VENDOR_FROM_DATABASE=Infineon Technologies AG bluetooth:v000A* ID_VENDOR_FROM_DATABASE=Cambridge Silicon Radio bluetooth:v000B* ID_VENDOR_FROM_DATABASE=Silicon Wave bluetooth:v000C* ID_VENDOR_FROM_DATABASE=Digianswer A/S bluetooth:v000D* ID_VENDOR_FROM_DATABASE=Texas Instruments Inc. bluetooth:v000E* ID_VENDOR_FROM_DATABASE=Ceva, Inc. (formerly Parthus Technologies, Inc.) bluetooth:v000F* ID_VENDOR_FROM_DATABASE=Broadcom Corporation bluetooth:v0010* ID_VENDOR_FROM_DATABASE=Mitel Semiconductor bluetooth:v0011* ID_VENDOR_FROM_DATABASE=Widcomm, Inc bluetooth:v0012* ID_VENDOR_FROM_DATABASE=Zeevo, Inc. bluetooth:v0013* ID_VENDOR_FROM_DATABASE=Atmel Corporation bluetooth:v0014* ID_VENDOR_FROM_DATABASE=Mitsubishi Electric Corporation bluetooth:v0015* ID_VENDOR_FROM_DATABASE=RTX Telecom A/S bluetooth:v0016* ID_VENDOR_FROM_DATABASE=KC Technology Inc. bluetooth:v0017* ID_VENDOR_FROM_DATABASE=NewLogic bluetooth:v0018* ID_VENDOR_FROM_DATABASE=Transilica, Inc. bluetooth:v0019* ID_VENDOR_FROM_DATABASE=Rohde & Schwarz GmbH & Co. KG bluetooth:v001A* ID_VENDOR_FROM_DATABASE=TTPCom Limited bluetooth:v001B* ID_VENDOR_FROM_DATABASE=Signia Technologies, Inc. bluetooth:v001C* ID_VENDOR_FROM_DATABASE=Conexant Systems Inc. bluetooth:v001D* ID_VENDOR_FROM_DATABASE=Qualcomm bluetooth:v001E* ID_VENDOR_FROM_DATABASE=Inventel bluetooth:v001F* ID_VENDOR_FROM_DATABASE=AVM Berlin bluetooth:v0020* ID_VENDOR_FROM_DATABASE=BandSpeed, Inc. bluetooth:v0021* ID_VENDOR_FROM_DATABASE=Mansella Ltd bluetooth:v0022* ID_VENDOR_FROM_DATABASE=NEC Corporation bluetooth:v0023* ID_VENDOR_FROM_DATABASE=WavePlus Technology Co., Ltd. bluetooth:v0024* ID_VENDOR_FROM_DATABASE=Alcatel bluetooth:v0025* ID_VENDOR_FROM_DATABASE=NXP Semiconductors (formerly Philips Semiconductors) bluetooth:v0026* ID_VENDOR_FROM_DATABASE=C Technologies bluetooth:v0027* ID_VENDOR_FROM_DATABASE=Open Interface bluetooth:v0028* ID_VENDOR_FROM_DATABASE=R F Micro Devices bluetooth:v0029* ID_VENDOR_FROM_DATABASE=Hitachi Ltd bluetooth:v002A* ID_VENDOR_FROM_DATABASE=Symbol Technologies, Inc. bluetooth:v002B* ID_VENDOR_FROM_DATABASE=Tenovis bluetooth:v002C* ID_VENDOR_FROM_DATABASE=Macronix International Co. Ltd. bluetooth:v002D* ID_VENDOR_FROM_DATABASE=GCT Semiconductor bluetooth:v002E* ID_VENDOR_FROM_DATABASE=Norwood Systems bluetooth:v002F* ID_VENDOR_FROM_DATABASE=MewTel Technology Inc. bluetooth:v0030* ID_VENDOR_FROM_DATABASE=ST Microelectronics bluetooth:v0031* ID_VENDOR_FROM_DATABASE=Synopsis bluetooth:v0032* ID_VENDOR_FROM_DATABASE=Red-M (Communications) Ltd bluetooth:v0033* ID_VENDOR_FROM_DATABASE=Commil Ltd bluetooth:v0034* ID_VENDOR_FROM_DATABASE=Computer Access Technology Corporation (CATC) bluetooth:v0035* ID_VENDOR_FROM_DATABASE=Eclipse (HQ Espana) S.L. bluetooth:v0036* ID_VENDOR_FROM_DATABASE=Renesas Electronics Corporation bluetooth:v0037* ID_VENDOR_FROM_DATABASE=Mobilian Corporation bluetooth:v0038* ID_VENDOR_FROM_DATABASE=Terax bluetooth:v0039* ID_VENDOR_FROM_DATABASE=Integrated System Solution Corp. bluetooth:v003A* ID_VENDOR_FROM_DATABASE=Matsushita Electric Industrial Co., Ltd. bluetooth:v003B* ID_VENDOR_FROM_DATABASE=Gennum Corporation bluetooth:v003C* ID_VENDOR_FROM_DATABASE=BlackBerry Limited (formerly Research In Motion) bluetooth:v003D* ID_VENDOR_FROM_DATABASE=IPextreme, Inc. bluetooth:v003E* ID_VENDOR_FROM_DATABASE=Systems and Chips, Inc. bluetooth:v003F* ID_VENDOR_FROM_DATABASE=Bluetooth SIG, Inc. bluetooth:v0040* ID_VENDOR_FROM_DATABASE=Seiko Epson Corporation bluetooth:v0041* ID_VENDOR_FROM_DATABASE=Integrated Silicon Solution Taiwan, Inc. bluetooth:v0042* ID_VENDOR_FROM_DATABASE=CONWISE Technology Corporation Ltd bluetooth:v0043* ID_VENDOR_FROM_DATABASE=PARROT SA bluetooth:v0044* ID_VENDOR_FROM_DATABASE=Socket Mobile bluetooth:v0045* ID_VENDOR_FROM_DATABASE=Atheros Communications, Inc. bluetooth:v0046* ID_VENDOR_FROM_DATABASE=MediaTek, Inc. bluetooth:v0047* ID_VENDOR_FROM_DATABASE=Bluegiga bluetooth:v0048* ID_VENDOR_FROM_DATABASE=Marvell Technology Group Ltd. bluetooth:v0049* ID_VENDOR_FROM_DATABASE=3DSP Corporation bluetooth:v004A* ID_VENDOR_FROM_DATABASE=Accel Semiconductor Ltd. bluetooth:v004B* ID_VENDOR_FROM_DATABASE=Continental Automotive Systems bluetooth:v004C* ID_VENDOR_FROM_DATABASE=Apple, Inc. bluetooth:v004D* ID_VENDOR_FROM_DATABASE=Staccato Communications, Inc. bluetooth:v004E* ID_VENDOR_FROM_DATABASE=Avago Technologies bluetooth:v004F* ID_VENDOR_FROM_DATABASE=APT Licensing Ltd. bluetooth:v0050* ID_VENDOR_FROM_DATABASE=SiRF Technology bluetooth:v0051* ID_VENDOR_FROM_DATABASE=Tzero Technologies, Inc. bluetooth:v0052* ID_VENDOR_FROM_DATABASE=J&M Corporation bluetooth:v0053* ID_VENDOR_FROM_DATABASE=Free2move AB bluetooth:v0054* ID_VENDOR_FROM_DATABASE=3DiJoy Corporation bluetooth:v0055* ID_VENDOR_FROM_DATABASE=Plantronics, Inc. bluetooth:v0056* ID_VENDOR_FROM_DATABASE=Sony Ericsson Mobile Communications bluetooth:v0057* ID_VENDOR_FROM_DATABASE=Harman International Industries, Inc. bluetooth:v0058* ID_VENDOR_FROM_DATABASE=Vizio, Inc. bluetooth:v0059* ID_VENDOR_FROM_DATABASE=Nordic Semiconductor ASA bluetooth:v005A* ID_VENDOR_FROM_DATABASE=EM Microelectronic-Marin SA bluetooth:v005B* ID_VENDOR_FROM_DATABASE=Ralink Technology Corporation bluetooth:v005C* ID_VENDOR_FROM_DATABASE=Belkin International, Inc. bluetooth:v005D* ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Corporation bluetooth:v005E* ID_VENDOR_FROM_DATABASE=Stonestreet One, LLC bluetooth:v005F* ID_VENDOR_FROM_DATABASE=Wicentric, Inc. bluetooth:v0060* ID_VENDOR_FROM_DATABASE=RivieraWaves S.A.S bluetooth:v0061* ID_VENDOR_FROM_DATABASE=RDA Microelectronics bluetooth:v0062* ID_VENDOR_FROM_DATABASE=Gibson Guitars bluetooth:v0063* ID_VENDOR_FROM_DATABASE=MiCommand Inc. bluetooth:v0064* ID_VENDOR_FROM_DATABASE=Band XI International, LLC bluetooth:v0065* ID_VENDOR_FROM_DATABASE=Hewlett-Packard Company bluetooth:v0066* ID_VENDOR_FROM_DATABASE=9Solutions Oy bluetooth:v0067* ID_VENDOR_FROM_DATABASE=GN Netcom A/S bluetooth:v0068* ID_VENDOR_FROM_DATABASE=General Motors bluetooth:v0069* ID_VENDOR_FROM_DATABASE=A&D Engineering, Inc. bluetooth:v006A* ID_VENDOR_FROM_DATABASE=MindTree Ltd. bluetooth:v006B* ID_VENDOR_FROM_DATABASE=Polar Electro OY bluetooth:v006C* ID_VENDOR_FROM_DATABASE=Beautiful Enterprise Co., Ltd. bluetooth:v006D* ID_VENDOR_FROM_DATABASE=BriarTek, Inc. bluetooth:v006E* ID_VENDOR_FROM_DATABASE=Summit Data Communications, Inc. bluetooth:v006F* ID_VENDOR_FROM_DATABASE=Sound ID bluetooth:v0070* ID_VENDOR_FROM_DATABASE=Monster, LLC bluetooth:v0071* ID_VENDOR_FROM_DATABASE=connectBlue AB bluetooth:v0072* ID_VENDOR_FROM_DATABASE=ShangHai Super Smart Electronics Co. Ltd. bluetooth:v0073* ID_VENDOR_FROM_DATABASE=Group Sense Ltd. bluetooth:v0074* ID_VENDOR_FROM_DATABASE=Zomm, LLC bluetooth:v0075* ID_VENDOR_FROM_DATABASE=Samsung Electronics Co. Ltd. bluetooth:v0076* ID_VENDOR_FROM_DATABASE=Creative Technology Ltd. bluetooth:v0077* ID_VENDOR_FROM_DATABASE=Laird Technologies bluetooth:v0078* ID_VENDOR_FROM_DATABASE=Nike, Inc. bluetooth:v0078p0001* ID_PRODUCT_FROM_DATABASE=Nike+ FuelBand bluetooth:v0079* ID_VENDOR_FROM_DATABASE=lesswire AG bluetooth:v007A* ID_VENDOR_FROM_DATABASE=MStar Semiconductor, Inc. bluetooth:v007B* ID_VENDOR_FROM_DATABASE=Hanlynn Technologies bluetooth:v007C* ID_VENDOR_FROM_DATABASE=A & R Cambridge bluetooth:v007D* ID_VENDOR_FROM_DATABASE=Seers Technology Co. Ltd bluetooth:v007E* ID_VENDOR_FROM_DATABASE=Sports Tracking Technologies Ltd. bluetooth:v007F* ID_VENDOR_FROM_DATABASE=Autonet Mobile bluetooth:v0080* ID_VENDOR_FROM_DATABASE=DeLorme Publishing Company, Inc. bluetooth:v0081* ID_VENDOR_FROM_DATABASE=WuXi Vimicro bluetooth:v0082* ID_VENDOR_FROM_DATABASE=Sennheiser Communications A/S bluetooth:v0083* ID_VENDOR_FROM_DATABASE=TimeKeeping Systems, Inc. bluetooth:v0084* ID_VENDOR_FROM_DATABASE=Ludus Helsinki Ltd. bluetooth:v0085* ID_VENDOR_FROM_DATABASE=BlueRadios, Inc. bluetooth:v0086* ID_VENDOR_FROM_DATABASE=equinox AG bluetooth:v0087* ID_VENDOR_FROM_DATABASE=Garmin International, Inc. bluetooth:v0088* ID_VENDOR_FROM_DATABASE=Ecotest bluetooth:v0089* ID_VENDOR_FROM_DATABASE=GN ReSound A/S bluetooth:v008A* ID_VENDOR_FROM_DATABASE=Jawbone bluetooth:v008B* ID_VENDOR_FROM_DATABASE=Topcorn Positioning Systems, LLC bluetooth:v008C* ID_VENDOR_FROM_DATABASE=Gimbal Inc. (formerly Qualcomm Labs, Inc. and Qualcomm Retail Solutions, Inc.) bluetooth:v008D* ID_VENDOR_FROM_DATABASE=Zscan Software bluetooth:v008E* ID_VENDOR_FROM_DATABASE=Quintic Corp. bluetooth:v008F* ID_VENDOR_FROM_DATABASE=Stollman E+V GmbH bluetooth:v0090* ID_VENDOR_FROM_DATABASE=Funai Electric Co., Ltd. bluetooth:v0091* ID_VENDOR_FROM_DATABASE=Advanced PANMOBIL Systems GmbH & Co. KG bluetooth:v0092* ID_VENDOR_FROM_DATABASE=ThinkOptics, Inc. bluetooth:v0093* ID_VENDOR_FROM_DATABASE=Universal Electronics, Inc. bluetooth:v0094* ID_VENDOR_FROM_DATABASE=Airoha Technology Corp. bluetooth:v0095* ID_VENDOR_FROM_DATABASE=NEC Lighting, Ltd. bluetooth:v0096* ID_VENDOR_FROM_DATABASE=ODM Technology, Inc. bluetooth:v0097* ID_VENDOR_FROM_DATABASE=ConnecteDevice Ltd. bluetooth:v0098* ID_VENDOR_FROM_DATABASE=zer01.tv GmbH bluetooth:v0099* ID_VENDOR_FROM_DATABASE=i.Tech Dynamic Global Distribution Ltd. bluetooth:v009A* ID_VENDOR_FROM_DATABASE=Alpwise bluetooth:v009B* ID_VENDOR_FROM_DATABASE=Jiangsu Toppower Automotive Electronics Co., Ltd. bluetooth:v009C* ID_VENDOR_FROM_DATABASE=Colorfy, Inc. bluetooth:v009D* ID_VENDOR_FROM_DATABASE=Geoforce Inc. bluetooth:v009E* ID_VENDOR_FROM_DATABASE=Bose Corporation bluetooth:v009F* ID_VENDOR_FROM_DATABASE=Suunto Oy bluetooth:v00A0* ID_VENDOR_FROM_DATABASE=Kensington Computer Products Group bluetooth:v00A1* ID_VENDOR_FROM_DATABASE=SR-Medizinelektronik bluetooth:v00A2* ID_VENDOR_FROM_DATABASE=Vertu Corporation Limited bluetooth:v00A3* ID_VENDOR_FROM_DATABASE=Meta Watch Ltd. bluetooth:v00A4* ID_VENDOR_FROM_DATABASE=LINAK A/S bluetooth:v00A5* ID_VENDOR_FROM_DATABASE=OTL Dynamics LLC bluetooth:v00A6* ID_VENDOR_FROM_DATABASE=Panda Ocean Inc. bluetooth:v00A7* ID_VENDOR_FROM_DATABASE=Visteon Corporation bluetooth:v00A8* ID_VENDOR_FROM_DATABASE=ARP Devices Limited bluetooth:v00A9* ID_VENDOR_FROM_DATABASE=Magneti Marelli S.p.A bluetooth:v00AA* ID_VENDOR_FROM_DATABASE=CAEN RFID srl bluetooth:v00AB* ID_VENDOR_FROM_DATABASE=Ingenieur-Systemgruppe Zahn GmbH bluetooth:v00AC* ID_VENDOR_FROM_DATABASE=Green Throttle Games bluetooth:v00AD* ID_VENDOR_FROM_DATABASE=Peter Systemtechnik GmbH bluetooth:v00AE* ID_VENDOR_FROM_DATABASE=Omegawave Oy bluetooth:v00AF* ID_VENDOR_FROM_DATABASE=Cinetix bluetooth:v00B0* ID_VENDOR_FROM_DATABASE=Passif Semiconductor Corp bluetooth:v00B1* ID_VENDOR_FROM_DATABASE=Saris Cycling Group, Inc bluetooth:v00B2* ID_VENDOR_FROM_DATABASE=Bekey A/S bluetooth:v00B3* ID_VENDOR_FROM_DATABASE=Clarinox Technologies Pty. Ltd. bluetooth:v00B4* ID_VENDOR_FROM_DATABASE=BDE Technology Co., Ltd. bluetooth:v00B5* ID_VENDOR_FROM_DATABASE=Swirl Networks bluetooth:v00B6* ID_VENDOR_FROM_DATABASE=Meso international bluetooth:v00B7* ID_VENDOR_FROM_DATABASE=TreLab Ltd bluetooth:v00B8* ID_VENDOR_FROM_DATABASE=Qualcomm Innovation Center, Inc. (QuIC) bluetooth:v00B9* ID_VENDOR_FROM_DATABASE=Johnson Controls, Inc. bluetooth:v00BA* ID_VENDOR_FROM_DATABASE=Starkey Laboratories Inc. bluetooth:v00BB* ID_VENDOR_FROM_DATABASE=S-Power Electronics Limited bluetooth:v00BC* ID_VENDOR_FROM_DATABASE=Ace Sensor Inc bluetooth:v00BD* ID_VENDOR_FROM_DATABASE=Aplix Corporation bluetooth:v00BE* ID_VENDOR_FROM_DATABASE=AAMP of America bluetooth:v00BF* ID_VENDOR_FROM_DATABASE=Stalmart Technology Limited bluetooth:v00C0* ID_VENDOR_FROM_DATABASE=AMICCOM Electronics Corporation bluetooth:v00C1* ID_VENDOR_FROM_DATABASE=Shenzhen Excelsecu Data Technology Co.,Ltd bluetooth:v00C2* ID_VENDOR_FROM_DATABASE=Geneq Inc. bluetooth:v00C3* ID_VENDOR_FROM_DATABASE=adidas AG bluetooth:v00C4* ID_VENDOR_FROM_DATABASE=LG Electronics bluetooth:v00C5* ID_VENDOR_FROM_DATABASE=Onset Computer Corporation bluetooth:v00C6* ID_VENDOR_FROM_DATABASE=Selfly BV bluetooth:v00C7* ID_VENDOR_FROM_DATABASE=Quuppa Oy. bluetooth:v00C8* ID_VENDOR_FROM_DATABASE=GeLo Inc bluetooth:v00C9* ID_VENDOR_FROM_DATABASE=Evluma bluetooth:v00CA* ID_VENDOR_FROM_DATABASE=MC10 bluetooth:v00CB* ID_VENDOR_FROM_DATABASE=Binauric SE bluetooth:v00CC* ID_VENDOR_FROM_DATABASE=Beats Electronics bluetooth:v00CD* ID_VENDOR_FROM_DATABASE=Microchip Technology Inc. bluetooth:v00CE* ID_VENDOR_FROM_DATABASE=Elgato Systems GmbH bluetooth:v00CF* ID_VENDOR_FROM_DATABASE=ARCHOS SA bluetooth:v00D0* ID_VENDOR_FROM_DATABASE=Dexcom, Inc. bluetooth:v00D1* ID_VENDOR_FROM_DATABASE=Polar Electro Europe B.V. bluetooth:v00D2* ID_VENDOR_FROM_DATABASE=Dialog Semiconductor B.V. bluetooth:v00D3* ID_VENDOR_FROM_DATABASE=Taixingbang Technology (HK) Co,. LTD. bluetooth:v00D4* ID_VENDOR_FROM_DATABASE=Kawantech bluetooth:v00D5* ID_VENDOR_FROM_DATABASE=Austco Communication Systems bluetooth:v00D6* ID_VENDOR_FROM_DATABASE=Timex Group USA, Inc. bluetooth:v00D7* ID_VENDOR_FROM_DATABASE=Qualcomm Technologies, Inc. bluetooth:v00D8* ID_VENDOR_FROM_DATABASE=Qualcomm Connected Experiences, Inc. bluetooth:v00D9* ID_VENDOR_FROM_DATABASE=Voyetra Turtle Beach bluetooth:v00DA* ID_VENDOR_FROM_DATABASE=txtr GmbH bluetooth:v00DB* ID_VENDOR_FROM_DATABASE=Biosentronics bluetooth:v00DC* ID_VENDOR_FROM_DATABASE=Procter & Gamble bluetooth:v00DD* ID_VENDOR_FROM_DATABASE=Hosiden Corporation bluetooth:v00DE* ID_VENDOR_FROM_DATABASE=Muzik LLC bluetooth:v00DF* ID_VENDOR_FROM_DATABASE=Misfit Wearables Corp bluetooth:v00E0* ID_VENDOR_FROM_DATABASE=Google bluetooth:v00E1* ID_VENDOR_FROM_DATABASE=Danlers Ltd bluetooth:v00E2* ID_VENDOR_FROM_DATABASE=Semilink Inc bluetooth:v00E3* ID_VENDOR_FROM_DATABASE=inMusic Brands, Inc bluetooth:v00E4* ID_VENDOR_FROM_DATABASE=L.S. Research Inc. bluetooth:v00E5* ID_VENDOR_FROM_DATABASE=Eden Software Consultants Ltd. bluetooth:v00E6* ID_VENDOR_FROM_DATABASE=Freshtemp bluetooth:v00E7* ID_VENDOR_FROM_DATABASE=KS Technologies bluetooth:v00E8* ID_VENDOR_FROM_DATABASE=ACTS Technologies bluetooth:v00E9* ID_VENDOR_FROM_DATABASE=Vtrack Systems bluetooth:v00EA* ID_VENDOR_FROM_DATABASE=Nielsen-Kellerman Company bluetooth:v00EB* ID_VENDOR_FROM_DATABASE=Server Technology, Inc. bluetooth:v00EC* ID_VENDOR_FROM_DATABASE=BioResearch Associates bluetooth:v00ED* ID_VENDOR_FROM_DATABASE=Jolly Logic, LLC bluetooth:v00EE* ID_VENDOR_FROM_DATABASE=Above Average Outcomes, Inc. bluetooth:v00EF* ID_VENDOR_FROM_DATABASE=Bitsplitters GmbH bluetooth:v00F0* ID_VENDOR_FROM_DATABASE=PayPal, Inc. bluetooth:v00F1* ID_VENDOR_FROM_DATABASE=Witron Technology Limited bluetooth:v00F2* ID_VENDOR_FROM_DATABASE=Aether Things Inc. (formerly Morse Project Inc.) bluetooth:v00F3* ID_VENDOR_FROM_DATABASE=Kent Displays Inc. bluetooth:v00F4* ID_VENDOR_FROM_DATABASE=Nautilus Inc. bluetooth:v00F5* ID_VENDOR_FROM_DATABASE=Smartifier Oy bluetooth:v00F6* ID_VENDOR_FROM_DATABASE=Elcometer Limited bluetooth:v00F7* ID_VENDOR_FROM_DATABASE=VSN Technologies Inc. bluetooth:v00F8* ID_VENDOR_FROM_DATABASE=AceUni Corp., Ltd. bluetooth:v00F9* ID_VENDOR_FROM_DATABASE=StickNFind bluetooth:v00FA* ID_VENDOR_FROM_DATABASE=Crystal Code AB bluetooth:v00FB* ID_VENDOR_FROM_DATABASE=KOUKAAM a.s. bluetooth:v00FC* ID_VENDOR_FROM_DATABASE=Delphi Corporation bluetooth:v00FD* ID_VENDOR_FROM_DATABASE=ValenceTech Limited bluetooth:v00FE* ID_VENDOR_FROM_DATABASE=Reserved bluetooth:v00FF* ID_VENDOR_FROM_DATABASE=Typo Products, LLC bluetooth:v0100* ID_VENDOR_FROM_DATABASE=TomTom International BV bluetooth:v0101* ID_VENDOR_FROM_DATABASE=Fugoo, Inc bluetooth:v0102* ID_VENDOR_FROM_DATABASE=Keiser Corporation bluetooth:v0103* ID_VENDOR_FROM_DATABASE=Bang & Olufsen A/S bluetooth:v0104* ID_VENDOR_FROM_DATABASE=PLUS Locations Systems Pty Ltd bluetooth:v0105* ID_VENDOR_FROM_DATABASE=Ubiquitous Computing Technology Corporation bluetooth:v0106* ID_VENDOR_FROM_DATABASE=Innovative Yachtter Solutions bluetooth:v0107* ID_VENDOR_FROM_DATABASE=William Demant Holding A/S bluetooth:v0108* ID_VENDOR_FROM_DATABASE=Chicony Electronics Co., Ltd. bluetooth:v0109* ID_VENDOR_FROM_DATABASE=Atus BV bluetooth:v010A* ID_VENDOR_FROM_DATABASE=Codegate Ltd. bluetooth:v010B* ID_VENDOR_FROM_DATABASE=ERi, Inc. bluetooth:v010C* ID_VENDOR_FROM_DATABASE=Transducers Direct, LLC bluetooth:v010D* ID_VENDOR_FROM_DATABASE=Fujitsu Ten Limited bluetooth:v010E* ID_VENDOR_FROM_DATABASE=Audi AG bluetooth:v010F* ID_VENDOR_FROM_DATABASE=HiSilicon Technologies Co., Ltd. bluetooth:v0110* ID_VENDOR_FROM_DATABASE=Nippon Seiki Co., Ltd. bluetooth:v0111* ID_VENDOR_FROM_DATABASE=Steelseries ApS bluetooth:v0112* ID_VENDOR_FROM_DATABASE=Visybl Inc. bluetooth:v0113* ID_VENDOR_FROM_DATABASE=Openbrain Technologies, Co., Ltd. bluetooth:v0114* ID_VENDOR_FROM_DATABASE=Xensr bluetooth:v0115* ID_VENDOR_FROM_DATABASE=e.solutions bluetooth:v0116* ID_VENDOR_FROM_DATABASE=1OAK Technologies bluetooth:v0117* ID_VENDOR_FROM_DATABASE=Wimoto Technologies Inc bluetooth:v0118* ID_VENDOR_FROM_DATABASE=Radius Networks, Inc. bluetooth:v0119* ID_VENDOR_FROM_DATABASE=Wize Technology Co., Ltd. bluetooth:v011A* ID_VENDOR_FROM_DATABASE=Qualcomm Labs, Inc. bluetooth:v011B* ID_VENDOR_FROM_DATABASE=Aruba Networks bluetooth:v011C* ID_VENDOR_FROM_DATABASE=Baidu bluetooth:v011D* ID_VENDOR_FROM_DATABASE=Arendi AG bluetooth:v011E* ID_VENDOR_FROM_DATABASE=Skoda Auto a.s. bluetooth:v011F* ID_VENDOR_FROM_DATABASE=Volkswagon AG bluetooth:v0120* ID_VENDOR_FROM_DATABASE=Porsche AG bluetooth:v0121* ID_VENDOR_FROM_DATABASE=Sino Wealth Electronic Ltd. bluetooth:v0122* ID_VENDOR_FROM_DATABASE=AirTurn, Inc. bluetooth:v0123* ID_VENDOR_FROM_DATABASE=Kinsa, Inc. bluetooth:v0124* ID_VENDOR_FROM_DATABASE=HID Global bluetooth:v0125* ID_VENDOR_FROM_DATABASE=SEAT es bluetooth:v0126* ID_VENDOR_FROM_DATABASE=Promethean Ltd. bluetooth:v0127* ID_VENDOR_FROM_DATABASE=Salutica Allied Solutions bluetooth:v0128* ID_VENDOR_FROM_DATABASE=GPSI Group Pty Ltd bluetooth:v0129* ID_VENDOR_FROM_DATABASE=Nimble Devices Oy bluetooth:v012A* ID_VENDOR_FROM_DATABASE=Changzhou Yongse Infotech Co., Ltd bluetooth:v012B* ID_VENDOR_FROM_DATABASE=SportIQ bluetooth:v012C* ID_VENDOR_FROM_DATABASE=TEMEC Instruments B.V. bluetooth:v012D* ID_VENDOR_FROM_DATABASE=Sony Corporation bluetooth:v012E* ID_VENDOR_FROM_DATABASE=ASSA ABLOY bluetooth:v012F* ID_VENDOR_FROM_DATABASE=Clarion Co., Ltd. bluetooth:v0130* ID_VENDOR_FROM_DATABASE=Warehouse Innovations bluetooth:v0131* ID_VENDOR_FROM_DATABASE=Cypress Semiconductor Corporation bluetooth:v0132* ID_VENDOR_FROM_DATABASE=MADS Inc bluetooth:v0133* ID_VENDOR_FROM_DATABASE=Blue Maestro Limited bluetooth:v0134* ID_VENDOR_FROM_DATABASE=Resolution Products, Inc. bluetooth:v0135* ID_VENDOR_FROM_DATABASE=Airewear LLC bluetooth:v0136* ID_VENDOR_FROM_DATABASE=Seed Labs, Inc. (formerly ETC sp. z.o.o.) bluetooth:v0137* ID_VENDOR_FROM_DATABASE=Prestigio Plaza Ltd. bluetooth:v0138* ID_VENDOR_FROM_DATABASE=NTEO Inc. bluetooth:v0139* ID_VENDOR_FROM_DATABASE=Focus Systems Corporation bluetooth:v013A* ID_VENDOR_FROM_DATABASE=Tencent Holdings Limited bluetooth:v013B* ID_VENDOR_FROM_DATABASE=Allegion bluetooth:v013C* ID_VENDOR_FROM_DATABASE=Murata Manufacuring Co., Ltd. bluetooth:v013D* ID_VENDOR_FROM_DATABASE=WirelessWERX bluetooth:v013E* ID_VENDOR_FROM_DATABASE=Nod, Inc. bluetooth:v013F* ID_VENDOR_FROM_DATABASE=B&B Manufacturing Company bluetooth:v0140* ID_VENDOR_FROM_DATABASE=Alpine Electronics (China) Co., Ltd bluetooth:v0141* ID_VENDOR_FROM_DATABASE=FedEx Services bluetooth:v0142* ID_VENDOR_FROM_DATABASE=Grape Systems Inc. bluetooth:v0143* ID_VENDOR_FROM_DATABASE=Bkon Connect bluetooth:v0144* ID_VENDOR_FROM_DATABASE=Lintech GmbH bluetooth:v0145* ID_VENDOR_FROM_DATABASE=Novatel Wireless bluetooth:v0146* ID_VENDOR_FROM_DATABASE=Ciright bluetooth:v0147* ID_VENDOR_FROM_DATABASE=Mighty Cast, Inc. bluetooth:v0148* ID_VENDOR_FROM_DATABASE=Ambimat Electronics bluetooth:v0149* ID_VENDOR_FROM_DATABASE=Perytons Ltd. bluetooth:v014A* ID_VENDOR_FROM_DATABASE=Tivoli Audio, LLC bluetooth:v014B* ID_VENDOR_FROM_DATABASE=Master Lock bluetooth:v014C* ID_VENDOR_FROM_DATABASE=Mesh-Net Ltd bluetooth:v014D* ID_VENDOR_FROM_DATABASE=Huizhou Desay SV Automotive CO., LTD. bluetooth:v014E* ID_VENDOR_FROM_DATABASE=Tangerine, Inc. bluetooth:v014F* ID_VENDOR_FROM_DATABASE=B&W Group Ltd. bluetooth:v0150* ID_VENDOR_FROM_DATABASE=Pioneer Corporation bluetooth:v0151* ID_VENDOR_FROM_DATABASE=OnBeep bluetooth:v0152* ID_VENDOR_FROM_DATABASE=Vernier Software & Technology bluetooth:v0153* ID_VENDOR_FROM_DATABASE=ROL Ergo bluetooth:v0154* ID_VENDOR_FROM_DATABASE=Pebble Technology bluetooth:v0155* ID_VENDOR_FROM_DATABASE=NETATMO bluetooth:v0156* ID_VENDOR_FROM_DATABASE=Accumulate AB bluetooth:v0157* ID_VENDOR_FROM_DATABASE=Anhui Huami Information Technology Co., Ltd. bluetooth:v0158* ID_VENDOR_FROM_DATABASE=Inmite s.r.o. bluetooth:v0159* ID_VENDOR_FROM_DATABASE=ChefSteps, Inc. bluetooth:v015A* ID_VENDOR_FROM_DATABASE=micas AG bluetooth:v015B* ID_VENDOR_FROM_DATABASE=Biomedical Research Ltd. bluetooth:v015C* ID_VENDOR_FROM_DATABASE=Pitius Tec S.L. bluetooth:v015D* ID_VENDOR_FROM_DATABASE=Estimote, Inc. bluetooth:v015E* ID_VENDOR_FROM_DATABASE=Unikey Technologies, Inc. bluetooth:v015F* ID_VENDOR_FROM_DATABASE=Timer Cap Co. bluetooth:v0160* ID_VENDOR_FROM_DATABASE=AwoX bluetooth:v0161* ID_VENDOR_FROM_DATABASE=yikes bluetooth:v0162* ID_VENDOR_FROM_DATABASE=MADSGlobal NZ Ltd. bluetooth:v0163* ID_VENDOR_FROM_DATABASE=PCH International bluetooth:v0164* ID_VENDOR_FROM_DATABASE=Qingdao Yeelink Information Technology Co., Ltd. bluetooth:v0165* ID_VENDOR_FROM_DATABASE=Milwaukee Tool (formerly Milwaukee Electric Tools) bluetooth:v0166* ID_VENDOR_FROM_DATABASE=MISHIK Pte Ltd bluetooth:v0167* ID_VENDOR_FROM_DATABASE=Bayer HealthCare bluetooth:v0168* ID_VENDOR_FROM_DATABASE=Spicebox LLC bluetooth:v0169* ID_VENDOR_FROM_DATABASE=emberlight bluetooth:v016A* ID_VENDOR_FROM_DATABASE=Cooper-Atkins Corporation bluetooth:v016B* ID_VENDOR_FROM_DATABASE=Qblinks bluetooth:v016C* ID_VENDOR_FROM_DATABASE=MYSPHERA bluetooth:v016D* ID_VENDOR_FROM_DATABASE=LifeScan Inc bluetooth:v016E* ID_VENDOR_FROM_DATABASE=Volantic AB bluetooth:v016F* ID_VENDOR_FROM_DATABASE=Podo Labs, Inc bluetooth:v0170* ID_VENDOR_FROM_DATABASE=Roche Diabetes Care AG bluetooth:v0171* ID_VENDOR_FROM_DATABASE=Amazon Fulfillment Service bluetooth:v0172* ID_VENDOR_FROM_DATABASE=Connovate Technology Private Limited bluetooth:v0173* ID_VENDOR_FROM_DATABASE=Kocomojo, LLC bluetooth:v0174* ID_VENDOR_FROM_DATABASE=Everykey LLC bluetooth:v0175* ID_VENDOR_FROM_DATABASE=Dynamic Controls bluetooth:v0176* ID_VENDOR_FROM_DATABASE=SentriLock bluetooth:v0177* ID_VENDOR_FROM_DATABASE=I-SYST inc. bluetooth:v0178* ID_VENDOR_FROM_DATABASE=CASIO COMPUTER CO., LTD. bluetooth:v0179* ID_VENDOR_FROM_DATABASE=LAPIS Semiconductor Co., Ltd. bluetooth:v017A* ID_VENDOR_FROM_DATABASE=Telemonitor, Inc. bluetooth:v017B* ID_VENDOR_FROM_DATABASE=taskit GmbH bluetooth:v017C* ID_VENDOR_FROM_DATABASE=Daimler AG bluetooth:v017D* ID_VENDOR_FROM_DATABASE=BatAndCat bluetooth:v017E* ID_VENDOR_FROM_DATABASE=BluDotz Ltd bluetooth:v017F* ID_VENDOR_FROM_DATABASE=XTel ApS bluetooth:v0180* ID_VENDOR_FROM_DATABASE=Gigaset Communications GmbH bluetooth:v0181* ID_VENDOR_FROM_DATABASE=Gecko Health Innovations, Inc. bluetooth:v0182* ID_VENDOR_FROM_DATABASE=HOP Ubiquitous bluetooth:v0183* ID_VENDOR_FROM_DATABASE=To Be Assigned bluetooth:v0184* ID_VENDOR_FROM_DATABASE=Nectar bluetooth:v0185* ID_VENDOR_FROM_DATABASE=bel'apps LLC bluetooth:v0186* ID_VENDOR_FROM_DATABASE=CORE Lighting Ltd bluetooth:v0187* ID_VENDOR_FROM_DATABASE=Seraphim Sense Ltd bluetooth:v0188* ID_VENDOR_FROM_DATABASE=Unico RBC bluetooth:v0189* ID_VENDOR_FROM_DATABASE=Physical Enterprises Inc. bluetooth:v018A* ID_VENDOR_FROM_DATABASE=Able Trend Technology Limited bluetooth:v018B* ID_VENDOR_FROM_DATABASE=Konica Minolta, Inc. bluetooth:v018C* ID_VENDOR_FROM_DATABASE=Wilo SE bluetooth:v018D* ID_VENDOR_FROM_DATABASE=Extron Design Services bluetooth:v018E* ID_VENDOR_FROM_DATABASE=Fitbit, Inc. bluetooth:v018F* ID_VENDOR_FROM_DATABASE=Fireflies Systems bluetooth:v0190* ID_VENDOR_FROM_DATABASE=Intelletto Technologies Inc. bluetooth:v0191* ID_VENDOR_FROM_DATABASE=FDK CORPORATION bluetooth:v0192* ID_VENDOR_FROM_DATABASE=Cloudleaf, Inc bluetooth:v0193* ID_VENDOR_FROM_DATABASE=Maveric Automation LLC bluetooth:v0194* ID_VENDOR_FROM_DATABASE=Acoustic Stream Corporation bluetooth:v0195* ID_VENDOR_FROM_DATABASE=Zuli bluetooth:v0196* ID_VENDOR_FROM_DATABASE=Paxton Access Ltd bluetooth:v0197* ID_VENDOR_FROM_DATABASE=WiSilica Inc bluetooth:v0198* ID_VENDOR_FROM_DATABASE=Vengit Limited bluetooth:v0199* ID_VENDOR_FROM_DATABASE=SALTO SYSTEMS S.L. bluetooth:v019A* ID_VENDOR_FROM_DATABASE=TRON Forum (formerly T-Engine Forum) bluetooth:v019B* ID_VENDOR_FROM_DATABASE=CUBETECH s.r.o. bluetooth:v019C* ID_VENDOR_FROM_DATABASE=Cokiya Incorporated bluetooth:v019D* ID_VENDOR_FROM_DATABASE=CVS Health bluetooth:v019E* ID_VENDOR_FROM_DATABASE=Ceruus bluetooth:v019F* ID_VENDOR_FROM_DATABASE=Strainstall Ltd bluetooth:v01A0* ID_VENDOR_FROM_DATABASE=Channel Enterprises (HK) Ltd. bluetooth:v01A1* ID_VENDOR_FROM_DATABASE=FIAMM bluetooth:v01A2* ID_VENDOR_FROM_DATABASE=GIGALANE.CO.,LTD bluetooth:v01A3* ID_VENDOR_FROM_DATABASE=EROAD bluetooth:v01A4* ID_VENDOR_FROM_DATABASE=Mine Safety Appliances bluetooth:v01A5* ID_VENDOR_FROM_DATABASE=Icon Health and Fitness bluetooth:v01A6* ID_VENDOR_FROM_DATABASE=Asandoo GmbH bluetooth:v01A7* ID_VENDOR_FROM_DATABASE=ENERGOUS CORPORATION bluetooth:v01A8* ID_VENDOR_FROM_DATABASE=Taobao bluetooth:v01A9* ID_VENDOR_FROM_DATABASE=Canon Inc. bluetooth:v01AA* ID_VENDOR_FROM_DATABASE=Geophysical Technology Inc. bluetooth:v01AB* ID_VENDOR_FROM_DATABASE=Facebook, Inc. bluetooth:v01AC* ID_VENDOR_FROM_DATABASE=Nipro Diagnostics, Inc. bluetooth:v01AD* ID_VENDOR_FROM_DATABASE=FlightSafety International bluetooth:v01AE* ID_VENDOR_FROM_DATABASE=Earlens Corporation bluetooth:v01AF* ID_VENDOR_FROM_DATABASE=Sunrise Micro Devices, Inc. bluetooth:v01B0* ID_VENDOR_FROM_DATABASE=Star Micronics Co., Ltd. bluetooth:v01B1* ID_VENDOR_FROM_DATABASE=Netizens Sp. z o.o. bluetooth:v01B2* ID_VENDOR_FROM_DATABASE=Nymi Inc. bluetooth:v01B3* ID_VENDOR_FROM_DATABASE=Nytec, Inc. bluetooth:v01B4* ID_VENDOR_FROM_DATABASE=Trineo Sp. z o.o. bluetooth:v01B5* ID_VENDOR_FROM_DATABASE=Nest Labs Inc. bluetooth:v01B6* ID_VENDOR_FROM_DATABASE=LM Technologies Ltd bluetooth:v01B7* ID_VENDOR_FROM_DATABASE=General Electric Company bluetooth:v01B8* ID_VENDOR_FROM_DATABASE=i+D3 S.L. bluetooth:v01B9* ID_VENDOR_FROM_DATABASE=HANA Micron bluetooth:v01BA* ID_VENDOR_FROM_DATABASE=Stages Cycling LLC bluetooth:v01BB* ID_VENDOR_FROM_DATABASE=Cochlear Bone Anchored Solutions AB bluetooth:v01BC* ID_VENDOR_FROM_DATABASE=SenionLab AB bluetooth:v01BD* ID_VENDOR_FROM_DATABASE=Syszone Co., Ltd bluetooth:v01BE* ID_VENDOR_FROM_DATABASE=Pulsate Mobile Ltd. bluetooth:v01BF* ID_VENDOR_FROM_DATABASE=Hong Kong HunterSun Electronic Limited bluetooth:v01C0* ID_VENDOR_FROM_DATABASE=pironex GmbH bluetooth:v01C1* ID_VENDOR_FROM_DATABASE=BRADATECH Corp. bluetooth:v01C2* ID_VENDOR_FROM_DATABASE=Transenergooil AG bluetooth:v01C3* ID_VENDOR_FROM_DATABASE=Bunch bluetooth:v01C4* ID_VENDOR_FROM_DATABASE=DME Microelectronics bluetooth:v01C5* ID_VENDOR_FROM_DATABASE=Bitcraze AB bluetooth:v01C6* ID_VENDOR_FROM_DATABASE=HASWARE Inc. bluetooth:v01C7* ID_VENDOR_FROM_DATABASE=Abiogenix Inc. bluetooth:v01C8* ID_VENDOR_FROM_DATABASE=Poly-Control ApS bluetooth:v01C9* ID_VENDOR_FROM_DATABASE=Avi-on bluetooth:v01CA* ID_VENDOR_FROM_DATABASE=Laerdal Medical AS bluetooth:v01CB* ID_VENDOR_FROM_DATABASE=Fetch My Pet bluetooth:v01CC* ID_VENDOR_FROM_DATABASE=Sam Labs Ltd. bluetooth:v01CD* ID_VENDOR_FROM_DATABASE=Chengdu Synwing Technology Ltd bluetooth:v01CE* ID_VENDOR_FROM_DATABASE=HOUWA SYSTEM DESIGN, k.k. bluetooth:v01CF* ID_VENDOR_FROM_DATABASE=BSH bluetooth:v01D0* ID_VENDOR_FROM_DATABASE=Primus Inter Pares Ltd bluetooth:v01D1* ID_VENDOR_FROM_DATABASE=August bluetooth:v01D2* ID_VENDOR_FROM_DATABASE=Gill Electronics bluetooth:v01D3* ID_VENDOR_FROM_DATABASE=Sky Wave Design bluetooth:v01D4* ID_VENDOR_FROM_DATABASE=Newlab S.r.l. bluetooth:v01D5* ID_VENDOR_FROM_DATABASE=ELAD srl bluetooth:v01D6* ID_VENDOR_FROM_DATABASE=G-wearables inc. bluetooth:v01D7* ID_VENDOR_FROM_DATABASE=Squadrone Systems Inc. bluetooth:v01D8* ID_VENDOR_FROM_DATABASE=Code Corporation bluetooth:v01D9* ID_VENDOR_FROM_DATABASE=Savant Systems LLC bluetooth:v01DA* ID_VENDOR_FROM_DATABASE=Logitech International SA bluetooth:v01DB* ID_VENDOR_FROM_DATABASE=Innblue Consulting bluetooth:v01DC* ID_VENDOR_FROM_DATABASE=iParking Ltd. bluetooth:v01DD* ID_VENDOR_FROM_DATABASE=Koninklijke Philips Electronics N.V. bluetooth:v01DE* ID_VENDOR_FROM_DATABASE=Minelab Electronics Pty Limited bluetooth:v01DF* ID_VENDOR_FROM_DATABASE=Bison Group Ltd. bluetooth:v01E0* ID_VENDOR_FROM_DATABASE=Widex A/S bluetooth:v01E1* ID_VENDOR_FROM_DATABASE=Jolla Ltd bluetooth:v01E2* ID_VENDOR_FROM_DATABASE=Lectronix, Inc. bluetooth:v01E3* ID_VENDOR_FROM_DATABASE=Caterpillar Inc bluetooth:v01E4* ID_VENDOR_FROM_DATABASE=Freedom Innovations bluetooth:v01E5* ID_VENDOR_FROM_DATABASE=Dynamic Devices Ltd bluetooth:v01E6* ID_VENDOR_FROM_DATABASE=Technology Solutions (UK) Ltd bluetooth:v01E7* ID_VENDOR_FROM_DATABASE=IPS Group Inc. bluetooth:v01E8* ID_VENDOR_FROM_DATABASE=STIR bluetooth:v01E9* ID_VENDOR_FROM_DATABASE=Sano, Inc bluetooth:v01EA* ID_VENDOR_FROM_DATABASE=Advanced Application Design, Inc. bluetooth:v01EB* ID_VENDOR_FROM_DATABASE=AutoMap LLC bluetooth:v01EC* ID_VENDOR_FROM_DATABASE=Spreadtrum Communications Shanghai Ltd bluetooth:v01ED* ID_VENDOR_FROM_DATABASE=CuteCircuit LTD bluetooth:v01EE* ID_VENDOR_FROM_DATABASE=Valeo Service bluetooth:v01EF* ID_VENDOR_FROM_DATABASE=Fullpower Technologies, Inc. bluetooth:v01F0* ID_VENDOR_FROM_DATABASE=KloudNation bluetooth:v01F1* ID_VENDOR_FROM_DATABASE=Zebra Technologies Corporation bluetooth:v01F2* ID_VENDOR_FROM_DATABASE=Itron, Inc. bluetooth:v01F3* ID_VENDOR_FROM_DATABASE=The University of Tokyo bluetooth:v01F4* ID_VENDOR_FROM_DATABASE=UTC Fire and Security bluetooth:v01F5* ID_VENDOR_FROM_DATABASE=Cool Webthings Limited bluetooth:v01F6* ID_VENDOR_FROM_DATABASE=DJO Global bluetooth:v01F7* ID_VENDOR_FROM_DATABASE=Gelliner Limited bluetooth:v01F8* ID_VENDOR_FROM_DATABASE=Anyka (Guangzhou) Microelectronics Technology Co, LTD bluetooth:v01F9* ID_VENDOR_FROM_DATABASE=Medtronic, Inc. bluetooth:v01FA* ID_VENDOR_FROM_DATABASE=Gozio, Inc. bluetooth:v01FB* ID_VENDOR_FROM_DATABASE=Form Lifting, LLC bluetooth:v01FC* ID_VENDOR_FROM_DATABASE=Wahoo Fitness, LLC bluetooth:v01FD* ID_VENDOR_FROM_DATABASE=Kontakt Micro-Location Sp. z o.o. bluetooth:v01FE* ID_VENDOR_FROM_DATABASE=Radio System Corporation bluetooth:v01FF* ID_VENDOR_FROM_DATABASE=Freescale Semiconductor, Inc. bluetooth:v0200* ID_VENDOR_FROM_DATABASE=Verifone Systems PTe Ltd. Taiwan Branch bluetooth:v0201* ID_VENDOR_FROM_DATABASE=AR Timing bluetooth:v0202* ID_VENDOR_FROM_DATABASE=Rigado LLC bluetooth:v0203* ID_VENDOR_FROM_DATABASE=Kemppi Oy bluetooth:v0204* ID_VENDOR_FROM_DATABASE=Tapcentive Inc. bluetooth:v0205* ID_VENDOR_FROM_DATABASE=Smartbotics Inc. bluetooth:v0206* ID_VENDOR_FROM_DATABASE=Otter Products, LLC bluetooth:v0207* ID_VENDOR_FROM_DATABASE=STEMP Inc. bluetooth:v0208* ID_VENDOR_FROM_DATABASE=LumiGeek LLC bluetooth:v0209* ID_VENDOR_FROM_DATABASE=InvisionHeart Inc. bluetooth:v020A* ID_VENDOR_FROM_DATABASE=Macnica Inc. bluetooth:v020B* ID_VENDOR_FROM_DATABASE=Jaguar Land Rover Limited bluetooth:v020C* ID_VENDOR_FROM_DATABASE=CoroWare Technologies, Inc bluetooth:v020D* ID_VENDOR_FROM_DATABASE=Simplo Technology Co., LTD bluetooth:v020E* ID_VENDOR_FROM_DATABASE=Omron Healthcare Co., LTD bluetooth:v020F* ID_VENDOR_FROM_DATABASE=Comodule GMBH bluetooth:v0210* ID_VENDOR_FROM_DATABASE=ikeGPS bluetooth:v0211* ID_VENDOR_FROM_DATABASE=Telink Semiconductor Co. Ltd bluetooth:v0212* ID_VENDOR_FROM_DATABASE=Interplan Co., Ltd bluetooth:v0213* ID_VENDOR_FROM_DATABASE=Wyler AG bluetooth:v0214* ID_VENDOR_FROM_DATABASE=IK Multimedia Production srl bluetooth:v0215* ID_VENDOR_FROM_DATABASE=Lukoton Experience Oy bluetooth:v0216* ID_VENDOR_FROM_DATABASE=MTI Ltd bluetooth:v0217* ID_VENDOR_FROM_DATABASE=Tech4home, Lda bluetooth:v0218* ID_VENDOR_FROM_DATABASE=Hiotech AB bluetooth:v0219* ID_VENDOR_FROM_DATABASE=DOTT Limited bluetooth:v021A* ID_VENDOR_FROM_DATABASE=Blue Speck Labs, LLC bluetooth:v021B* ID_VENDOR_FROM_DATABASE=Cisco Systems Inc bluetooth:v021C* ID_VENDOR_FROM_DATABASE=Mobicomm Inc bluetooth:v021D* ID_VENDOR_FROM_DATABASE=Edamic bluetooth:v021E* ID_VENDOR_FROM_DATABASE=Goodnet Ltd bluetooth:v021F* ID_VENDOR_FROM_DATABASE=Luster Leaf Products Inc bluetooth:v0220* ID_VENDOR_FROM_DATABASE=Manus Machina BV bluetooth:v0221* ID_VENDOR_FROM_DATABASE=Mobiquity Networks Inc bluetooth:v0222* ID_VENDOR_FROM_DATABASE=Praxis Dynamics bluetooth:v0223* ID_VENDOR_FROM_DATABASE=Philip Morris Products S.A. bluetooth:v0224* ID_VENDOR_FROM_DATABASE=Comarch SA bluetooth:v0225* ID_VENDOR_FROM_DATABASE=Nestlé Nespresso S.A. bluetooth:v0226* ID_VENDOR_FROM_DATABASE=Merlinia A/S bluetooth:v0227* ID_VENDOR_FROM_DATABASE=LifeBEAM Technologies bluetooth:v0228* ID_VENDOR_FROM_DATABASE=Twocanoes Labs, LLC bluetooth:v0229* ID_VENDOR_FROM_DATABASE=Muoverti Limited bluetooth:v022A* ID_VENDOR_FROM_DATABASE=Stamer Musikanlagen GMBH bluetooth:v022B* ID_VENDOR_FROM_DATABASE=Tesla Motors bluetooth:v022C* ID_VENDOR_FROM_DATABASE=Pharynks Corporation bluetooth:v022D* ID_VENDOR_FROM_DATABASE=Lupine bluetooth:v022E* ID_VENDOR_FROM_DATABASE=Siemens AG bluetooth:v022F* ID_VENDOR_FROM_DATABASE=Huami (Shanghai) Culture Communication CO., LTD bluetooth:v0230* ID_VENDOR_FROM_DATABASE=Foster Electric Company, Ltd bluetooth:v0231* ID_VENDOR_FROM_DATABASE=ETA SA bluetooth:v0232* ID_VENDOR_FROM_DATABASE=x-Senso Solutions Kft bluetooth:v0233* ID_VENDOR_FROM_DATABASE=Shenzhen SuLong Communication Ltd bluetooth:v0234* ID_VENDOR_FROM_DATABASE=FengFan (BeiJing) Technology Co, Ltd bluetooth:v0235* ID_VENDOR_FROM_DATABASE=Qrio Inc bluetooth:v0236* ID_VENDOR_FROM_DATABASE=Pitpatpet Ltd bluetooth:v0237* ID_VENDOR_FROM_DATABASE=MSHeli s.r.l. bluetooth:v0238* ID_VENDOR_FROM_DATABASE=Trakm8 Ltd bluetooth:v0239* ID_VENDOR_FROM_DATABASE=JIN CO, Ltd bluetooth:v023A* ID_VENDOR_FROM_DATABASE=Alatech Technology bluetooth:v023B* ID_VENDOR_FROM_DATABASE=Beijing CarePulse Electronic Technology Co, Ltd bluetooth:v023C* ID_VENDOR_FROM_DATABASE=Awarepoint bluetooth:v023D* ID_VENDOR_FROM_DATABASE=ViCentra B.V. bluetooth:v023E* ID_VENDOR_FROM_DATABASE=Raven Industries bluetooth:v023F* ID_VENDOR_FROM_DATABASE=WaveWare Technologies bluetooth:v0240* ID_VENDOR_FROM_DATABASE=Argenox Technologies bluetooth:v0241* ID_VENDOR_FROM_DATABASE=Bragi GmbH bluetooth:v0242* ID_VENDOR_FROM_DATABASE=16Lab Inc bluetooth:v0243* ID_VENDOR_FROM_DATABASE=Masimo Corp bluetooth:v0244* ID_VENDOR_FROM_DATABASE=Iotera Inc. bluetooth:v0245* ID_VENDOR_FROM_DATABASE=Endress+Hauser bluetooth:v0246* ID_VENDOR_FROM_DATABASE=ACKme Networks, Inc. bluetooth:v0247* ID_VENDOR_FROM_DATABASE=FiftyThree Inc. bluetooth:v0248* ID_VENDOR_FROM_DATABASE=Parker Hannifin Corp bluetooth:v0249* ID_VENDOR_FROM_DATABASE=Transcranial Ltd bluetooth:v024A* ID_VENDOR_FROM_DATABASE=Uwatec AG bluetooth:v024B* ID_VENDOR_FROM_DATABASE=Orlan LLC bluetooth:v024C* ID_VENDOR_FROM_DATABASE=Blue Clover Devices bluetooth:v024D* ID_VENDOR_FROM_DATABASE=M-Way Solutions GmbH bluetooth:v024E* ID_VENDOR_FROM_DATABASE=Microtronics Engineering GmbH bluetooth:v024F* ID_VENDOR_FROM_DATABASE=Schneider Schreibgeräte GmbH bluetooth:v0250* ID_VENDOR_FROM_DATABASE=Sapphire Circuits LLC bluetooth:v0251* ID_VENDOR_FROM_DATABASE=Lumo Bodytech Inc. bluetooth:v0252* ID_VENDOR_FROM_DATABASE=UKC Technosolution bluetooth:v0253* ID_VENDOR_FROM_DATABASE=Xicato Inc. bluetooth:v0254* ID_VENDOR_FROM_DATABASE=Playbrush bluetooth:v0255* ID_VENDOR_FROM_DATABASE=Dai Nippon Printing Co., Ltd. bluetooth:v0256* ID_VENDOR_FROM_DATABASE=G24 Power Limited bluetooth:v0257* ID_VENDOR_FROM_DATABASE=AdBabble Local Commerce Inc. bluetooth:v0258* ID_VENDOR_FROM_DATABASE=Devialet SA bluetooth:v0259* ID_VENDOR_FROM_DATABASE=ALTYOR bluetooth:v025A* ID_VENDOR_FROM_DATABASE=University of Applied Sciences Valais/Haute Ecole Valaisanne bluetooth:v025B* ID_VENDOR_FROM_DATABASE=Five Interactive, LLC dba Zendo bluetooth:v025C* ID_VENDOR_FROM_DATABASE=NetEase (Hangzhou) Network co.Ltd. bluetooth:v025D* ID_VENDOR_FROM_DATABASE=Lexmark International Inc. bluetooth:v025E* ID_VENDOR_FROM_DATABASE=Fluke Corporation bluetooth:v025F* ID_VENDOR_FROM_DATABASE=Yardarm Technologies bluetooth:v0260* ID_VENDOR_FROM_DATABASE=SensaRx bluetooth:v0261* ID_VENDOR_FROM_DATABASE=SECVRE GmbH bluetooth:v0262* ID_VENDOR_FROM_DATABASE=Glacial Ridge Technologies bluetooth:v0263* ID_VENDOR_FROM_DATABASE=Identiv, Inc. bluetooth:v0264* ID_VENDOR_FROM_DATABASE=DDS, Inc. bluetooth:v0265* ID_VENDOR_FROM_DATABASE=SMK Corporation bluetooth:v0266* ID_VENDOR_FROM_DATABASE=Schawbel Technologies LLC bluetooth:v0267* ID_VENDOR_FROM_DATABASE=XMI Systems SA bluetooth:v0268* ID_VENDOR_FROM_DATABASE=Cerevo bluetooth:v0269* ID_VENDOR_FROM_DATABASE=Torrox GmbH & Co KG bluetooth:v026A* ID_VENDOR_FROM_DATABASE=Gemalto bluetooth:v026B* ID_VENDOR_FROM_DATABASE=DEKA Research & Development Corp. bluetooth:v026C* ID_VENDOR_FROM_DATABASE=Domster Tadeusz Szydlowski bluetooth:v026D* ID_VENDOR_FROM_DATABASE=Technogym SPA bluetooth:v026E* ID_VENDOR_FROM_DATABASE=FLEURBAEY BVBA bluetooth:v026F* ID_VENDOR_FROM_DATABASE=Aptcode Solutions bluetooth:v0270* ID_VENDOR_FROM_DATABASE=LSI ADL Technology bluetooth:v0271* ID_VENDOR_FROM_DATABASE=Animas Corp bluetooth:v0272* ID_VENDOR_FROM_DATABASE=Alps Electric Co., Ltd. bluetooth:v0273* ID_VENDOR_FROM_DATABASE=OCEASOFT bluetooth:v0274* ID_VENDOR_FROM_DATABASE=Motsai Research bluetooth:v0275* ID_VENDOR_FROM_DATABASE=Geotab bluetooth:v0276* ID_VENDOR_FROM_DATABASE=E.G.O. Elektro-Gerätebau GmbH bluetooth:v0277* ID_VENDOR_FROM_DATABASE=bewhere inc bluetooth:v0278* ID_VENDOR_FROM_DATABASE=Johnson Outdoors Inc bluetooth:v0279* ID_VENDOR_FROM_DATABASE=steute Schaltgerate GmbH & Co. KG bluetooth:v027A* ID_VENDOR_FROM_DATABASE=Ekomini inc. bluetooth:v027B* ID_VENDOR_FROM_DATABASE=DEFA AS bluetooth:v027C* ID_VENDOR_FROM_DATABASE=Aseptika Ltd bluetooth:v027D* ID_VENDOR_FROM_DATABASE=HUAWEI Technologies Co., Ltd. ( 华为技术有限公司 ) bluetooth:v027E* ID_VENDOR_FROM_DATABASE=HabitAware, LLC bluetooth:v027F* ID_VENDOR_FROM_DATABASE=ruwido austria gmbh bluetooth:v0280* ID_VENDOR_FROM_DATABASE=ITEC corporation bluetooth:v0281* ID_VENDOR_FROM_DATABASE=StoneL bluetooth:v0282* ID_VENDOR_FROM_DATABASE=Sonova AG bluetooth:v0283* ID_VENDOR_FROM_DATABASE=Maven Machines, Inc. bluetooth:v0284* ID_VENDOR_FROM_DATABASE=Synapse Electronics bluetooth:v0285* ID_VENDOR_FROM_DATABASE=Standard Innovation Inc. bluetooth:v0286* ID_VENDOR_FROM_DATABASE=RF Code, Inc. bluetooth:v0287* ID_VENDOR_FROM_DATABASE=Wally Ventures S.L. bluetooth:v0288* ID_VENDOR_FROM_DATABASE=Willowbank Electronics Ltd bluetooth:v0289* ID_VENDOR_FROM_DATABASE=SK Telecom bluetooth:v028A* ID_VENDOR_FROM_DATABASE=Jetro AS bluetooth:v028B* ID_VENDOR_FROM_DATABASE=Code Gears LTD bluetooth:v028C* ID_VENDOR_FROM_DATABASE=NANOLINK APS bluetooth:v028D* ID_VENDOR_FROM_DATABASE=IF, LLC bluetooth:v028E* ID_VENDOR_FROM_DATABASE=RF Digital Corp bluetooth:v028F* ID_VENDOR_FROM_DATABASE=Church & Dwight Co., Inc bluetooth:v0290* ID_VENDOR_FROM_DATABASE=Multibit Oy bluetooth:v0291* ID_VENDOR_FROM_DATABASE=CliniCloud Inc bluetooth:v0292* ID_VENDOR_FROM_DATABASE=SwiftSensors bluetooth:v0293* ID_VENDOR_FROM_DATABASE=Blue Bite bluetooth:v0294* ID_VENDOR_FROM_DATABASE=ELIAS GmbH bluetooth:v0295* ID_VENDOR_FROM_DATABASE=Sivantos GmbH bluetooth:v0296* ID_VENDOR_FROM_DATABASE=Petzl bluetooth:v0297* ID_VENDOR_FROM_DATABASE=storm power ltd bluetooth:v0298* ID_VENDOR_FROM_DATABASE=EISST Ltd bluetooth:v0299* ID_VENDOR_FROM_DATABASE=Inexess Technology Simma KG bluetooth:v029A* ID_VENDOR_FROM_DATABASE=Currant, Inc. bluetooth:v029B* ID_VENDOR_FROM_DATABASE=C2 Development, Inc. bluetooth:v029C* ID_VENDOR_FROM_DATABASE=Blue Sky Scientific, LLC bluetooth:v029D* ID_VENDOR_FROM_DATABASE=ALOTTAZS LABS, LLC bluetooth:v029E* ID_VENDOR_FROM_DATABASE=Kupson spol. s r.o. bluetooth:v029F* ID_VENDOR_FROM_DATABASE=Areus Engineering GmbH bluetooth:v02A0* ID_VENDOR_FROM_DATABASE=Impossible Camera GmbH bluetooth:v02A1* ID_VENDOR_FROM_DATABASE=InventureTrack Systems bluetooth:v02A2* ID_VENDOR_FROM_DATABASE=LockedUp bluetooth:v02A3* ID_VENDOR_FROM_DATABASE=Itude bluetooth:v02A4* ID_VENDOR_FROM_DATABASE=Pacific Lock Company bluetooth:v02A5* ID_VENDOR_FROM_DATABASE=Tendyron Corporation ( 天地融科技股份有限公司 ) bluetooth:v02A6* ID_VENDOR_FROM_DATABASE=Robert Bosch GmbH bluetooth:v02A7* ID_VENDOR_FROM_DATABASE=Illuxtron international B.V. bluetooth:v02A8* ID_VENDOR_FROM_DATABASE=miSport Ltd. bluetooth:v02A9* ID_VENDOR_FROM_DATABASE=Chargelib bluetooth:v02AA* ID_VENDOR_FROM_DATABASE=Doppler Lab bluetooth:v02AB* ID_VENDOR_FROM_DATABASE=BBPOS Limited bluetooth:v02AC* ID_VENDOR_FROM_DATABASE=RTB Elektronik GmbH & Co. KG bluetooth:v02AD* ID_VENDOR_FROM_DATABASE=Rx Networks, Inc. bluetooth:v02AE* ID_VENDOR_FROM_DATABASE=WeatherFlow, Inc. bluetooth:v02AF* ID_VENDOR_FROM_DATABASE=Technicolor USA Inc. bluetooth:v02B0* ID_VENDOR_FROM_DATABASE=Bestechnic(Shanghai),Ltd bluetooth:v02B1* ID_VENDOR_FROM_DATABASE=Raden Inc bluetooth:v02B2* ID_VENDOR_FROM_DATABASE=JouZen Oy bluetooth:v02B3* ID_VENDOR_FROM_DATABASE=CLABER S.P.A. bluetooth:v02B4* ID_VENDOR_FROM_DATABASE=Hyginex, Inc. bluetooth:v02B5* ID_VENDOR_FROM_DATABASE=HANSHIN ELECTRIC RAILWAY CO.,LTD. bluetooth:v02B6* ID_VENDOR_FROM_DATABASE=Schneider Electric bluetooth:v02B7* ID_VENDOR_FROM_DATABASE=Oort Technologies LLC bluetooth:v02B8* ID_VENDOR_FROM_DATABASE=Chrono Therapeutics bluetooth:v02B9* ID_VENDOR_FROM_DATABASE=Rinnai Corporation bluetooth:v02BA* ID_VENDOR_FROM_DATABASE=Swissprime Technologies AG bluetooth:v02BB* ID_VENDOR_FROM_DATABASE=Koha.,Co.Ltd bluetooth:v02BC* ID_VENDOR_FROM_DATABASE=Genevac Ltd bluetooth:v02BD* ID_VENDOR_FROM_DATABASE=Chemtronics bluetooth:v02BE* ID_VENDOR_FROM_DATABASE=Seguro Technology Sp. z o.o. bluetooth:v02BF* ID_VENDOR_FROM_DATABASE=Redbird Flight Simulations bluetooth:v02C0* ID_VENDOR_FROM_DATABASE=Dash Robotics bluetooth:v02C1* ID_VENDOR_FROM_DATABASE=LINE Corporation bluetooth:v02C2* ID_VENDOR_FROM_DATABASE=Guillemot Corporation bluetooth:v02C3* ID_VENDOR_FROM_DATABASE=Techtronic Power Tools Technology Limited bluetooth:v02C4* ID_VENDOR_FROM_DATABASE=Wilson Sporting Goods bluetooth:v02C5* ID_VENDOR_FROM_DATABASE=Lenovo (Singapore) Pte Ltd. ( 联想(新加坡) ) bluetooth:v02C6* ID_VENDOR_FROM_DATABASE=Ayatan Sensors bluetooth:v02C7* ID_VENDOR_FROM_DATABASE=Electronics Tomorrow Limited bluetooth:v02C8* ID_VENDOR_FROM_DATABASE=VASCO Data Security International, Inc. bluetooth:v02C9* ID_VENDOR_FROM_DATABASE=PayRange Inc. bluetooth:v02CA* ID_VENDOR_FROM_DATABASE=ABOV Semiconductor bluetooth:v02CB* ID_VENDOR_FROM_DATABASE=AINA-Wireless Inc. bluetooth:v02CC* ID_VENDOR_FROM_DATABASE=Eijkelkamp Soil & Water bluetooth:v02CD* ID_VENDOR_FROM_DATABASE=BMA ergonomics b.v. bluetooth:v02CE* ID_VENDOR_FROM_DATABASE=Teva Branded Pharmaceutical Products R&D, Inc. bluetooth:v02CF* ID_VENDOR_FROM_DATABASE=Anima bluetooth:v02D0* ID_VENDOR_FROM_DATABASE=3M bluetooth:v02D1* ID_VENDOR_FROM_DATABASE=Empatica Srl bluetooth:v02D2* ID_VENDOR_FROM_DATABASE=Afero, Inc. bluetooth:v02D3* ID_VENDOR_FROM_DATABASE=Powercast Corporation bluetooth:v02D4* ID_VENDOR_FROM_DATABASE=Secuyou ApS bluetooth:v02D5* ID_VENDOR_FROM_DATABASE=OMRON Corporation bluetooth:v02D6* ID_VENDOR_FROM_DATABASE=Send Solutions bluetooth:v02D7* ID_VENDOR_FROM_DATABASE=NIPPON SYSTEMWARE CO.,LTD. bluetooth:v02D8* ID_VENDOR_FROM_DATABASE=Neosfar bluetooth:v02D9* ID_VENDOR_FROM_DATABASE=Fliegl Agrartechnik GmbH bluetooth:v02DA* ID_VENDOR_FROM_DATABASE=Gilvader bluetooth:v02DB* ID_VENDOR_FROM_DATABASE=Digi International Inc (R) bluetooth:v02DC* ID_VENDOR_FROM_DATABASE=DeWalch Technologies, Inc. bluetooth:v02DD* ID_VENDOR_FROM_DATABASE=Flint Rehabilitation Devices, LLC bluetooth:v02DE* ID_VENDOR_FROM_DATABASE=Samsung SDS Co., Ltd. bluetooth:v02DF* ID_VENDOR_FROM_DATABASE=Blur Product Development bluetooth:v02E0* ID_VENDOR_FROM_DATABASE=University of Michigan bluetooth:v02E1* ID_VENDOR_FROM_DATABASE=Victron Energy BV bluetooth:v02E2* ID_VENDOR_FROM_DATABASE=NTT docomo bluetooth:v02E3* ID_VENDOR_FROM_DATABASE=Carmanah Technologies Corp. bluetooth:v02E4* ID_VENDOR_FROM_DATABASE=Bytestorm Ltd. bluetooth:v02E5* ID_VENDOR_FROM_DATABASE=Espressif Incorporated ( 乐鑫信息科技(上海)有限公司 ) systemd-229/hwdb/20-net-ifname.hwdb000066400000000000000000000001571265713322000171200ustar00rootroot00000000000000# This file is part of systemd. # Dell iDRAC Virtual USB NIC usb:v413CpA102* ID_NET_NAME_FROM_DATABASE=idrac systemd-229/hwdb/20-pci-classes.hwdb000066400000000000000000000326161265713322000173100ustar00rootroot00000000000000# This file is part of systemd. # # Data imported from: http://pci-ids.ucw.cz/v2.2/pci.ids pci:v*d*sv*sd*bc00* ID_PCI_CLASS_FROM_DATABASE=Unclassified device pci:v*d*sv*sd*bc00sc00* ID_PCI_SUBCLASS_FROM_DATABASE=Non-VGA unclassified device pci:v*d*sv*sd*bc00sc01* ID_PCI_SUBCLASS_FROM_DATABASE=VGA compatible unclassified device pci:v*d*sv*sd*bc01* ID_PCI_CLASS_FROM_DATABASE=Mass storage controller pci:v*d*sv*sd*bc01sc00* ID_PCI_SUBCLASS_FROM_DATABASE=SCSI storage controller pci:v*d*sv*sd*bc01sc01* ID_PCI_SUBCLASS_FROM_DATABASE=IDE interface pci:v*d*sv*sd*bc01sc02* ID_PCI_SUBCLASS_FROM_DATABASE=Floppy disk controller pci:v*d*sv*sd*bc01sc03* ID_PCI_SUBCLASS_FROM_DATABASE=IPI bus controller pci:v*d*sv*sd*bc01sc04* ID_PCI_SUBCLASS_FROM_DATABASE=RAID bus controller pci:v*d*sv*sd*bc01sc05* ID_PCI_SUBCLASS_FROM_DATABASE=ATA controller pci:v*d*sv*sd*bc01sc05i20* ID_PCI_INTERFACE_FROM_DATABASE=ADMA single stepping pci:v*d*sv*sd*bc01sc05i30* ID_PCI_INTERFACE_FROM_DATABASE=ADMA continuous operation pci:v*d*sv*sd*bc01sc06* ID_PCI_SUBCLASS_FROM_DATABASE=SATA controller pci:v*d*sv*sd*bc01sc06i00* ID_PCI_INTERFACE_FROM_DATABASE=Vendor specific pci:v*d*sv*sd*bc01sc06i01* ID_PCI_INTERFACE_FROM_DATABASE=AHCI 1.0 pci:v*d*sv*sd*bc01sc06i02* ID_PCI_INTERFACE_FROM_DATABASE=Serial Storage Bus pci:v*d*sv*sd*bc01sc07* ID_PCI_SUBCLASS_FROM_DATABASE=Serial Attached SCSI controller pci:v*d*sv*sd*bc01sc07i01* ID_PCI_INTERFACE_FROM_DATABASE=Serial Storage Bus pci:v*d*sv*sd*bc01sc08* ID_PCI_SUBCLASS_FROM_DATABASE=Non-Volatile memory controller pci:v*d*sv*sd*bc01sc08i01* ID_PCI_INTERFACE_FROM_DATABASE=NVMHCI pci:v*d*sv*sd*bc01sc08i02* ID_PCI_INTERFACE_FROM_DATABASE=NVM Express pci:v*d*sv*sd*bc01sc80* ID_PCI_SUBCLASS_FROM_DATABASE=Mass storage controller pci:v*d*sv*sd*bc02* ID_PCI_CLASS_FROM_DATABASE=Network controller pci:v*d*sv*sd*bc02sc00* ID_PCI_SUBCLASS_FROM_DATABASE=Ethernet controller pci:v*d*sv*sd*bc02sc01* ID_PCI_SUBCLASS_FROM_DATABASE=Token ring network controller pci:v*d*sv*sd*bc02sc02* ID_PCI_SUBCLASS_FROM_DATABASE=FDDI network controller pci:v*d*sv*sd*bc02sc03* ID_PCI_SUBCLASS_FROM_DATABASE=ATM network controller pci:v*d*sv*sd*bc02sc04* ID_PCI_SUBCLASS_FROM_DATABASE=ISDN controller pci:v*d*sv*sd*bc02sc05* ID_PCI_SUBCLASS_FROM_DATABASE=WorldFip controller pci:v*d*sv*sd*bc02sc06* ID_PCI_SUBCLASS_FROM_DATABASE=PICMG controller pci:v*d*sv*sd*bc02sc07* ID_PCI_SUBCLASS_FROM_DATABASE=Infiniband controller pci:v*d*sv*sd*bc02sc08* ID_PCI_SUBCLASS_FROM_DATABASE=Fabric controller pci:v*d*sv*sd*bc02sc80* ID_PCI_SUBCLASS_FROM_DATABASE=Network controller pci:v*d*sv*sd*bc03* ID_PCI_CLASS_FROM_DATABASE=Display controller pci:v*d*sv*sd*bc03sc00* ID_PCI_SUBCLASS_FROM_DATABASE=VGA compatible controller pci:v*d*sv*sd*bc03sc00i00* ID_PCI_INTERFACE_FROM_DATABASE=VGA controller pci:v*d*sv*sd*bc03sc00i01* ID_PCI_INTERFACE_FROM_DATABASE=8514 controller pci:v*d*sv*sd*bc03sc01* ID_PCI_SUBCLASS_FROM_DATABASE=XGA compatible controller pci:v*d*sv*sd*bc03sc02* ID_PCI_SUBCLASS_FROM_DATABASE=3D controller pci:v*d*sv*sd*bc03sc80* ID_PCI_SUBCLASS_FROM_DATABASE=Display controller pci:v*d*sv*sd*bc04* ID_PCI_CLASS_FROM_DATABASE=Multimedia controller pci:v*d*sv*sd*bc04sc00* ID_PCI_SUBCLASS_FROM_DATABASE=Multimedia video controller pci:v*d*sv*sd*bc04sc01* ID_PCI_SUBCLASS_FROM_DATABASE=Multimedia audio controller pci:v*d*sv*sd*bc04sc02* ID_PCI_SUBCLASS_FROM_DATABASE=Computer telephony device pci:v*d*sv*sd*bc04sc03* ID_PCI_SUBCLASS_FROM_DATABASE=Audio device pci:v*d*sv*sd*bc04sc80* ID_PCI_SUBCLASS_FROM_DATABASE=Multimedia controller pci:v*d*sv*sd*bc05* ID_PCI_CLASS_FROM_DATABASE=Memory controller pci:v*d*sv*sd*bc05sc00* ID_PCI_SUBCLASS_FROM_DATABASE=RAM memory pci:v*d*sv*sd*bc05sc01* ID_PCI_SUBCLASS_FROM_DATABASE=FLASH memory pci:v*d*sv*sd*bc05sc80* ID_PCI_SUBCLASS_FROM_DATABASE=Memory controller pci:v*d*sv*sd*bc06* ID_PCI_CLASS_FROM_DATABASE=Bridge pci:v*d*sv*sd*bc06sc00* ID_PCI_SUBCLASS_FROM_DATABASE=Host bridge pci:v*d*sv*sd*bc06sc01* ID_PCI_SUBCLASS_FROM_DATABASE=ISA bridge pci:v*d*sv*sd*bc06sc02* ID_PCI_SUBCLASS_FROM_DATABASE=EISA bridge pci:v*d*sv*sd*bc06sc03* ID_PCI_SUBCLASS_FROM_DATABASE=MicroChannel bridge pci:v*d*sv*sd*bc06sc04* ID_PCI_SUBCLASS_FROM_DATABASE=PCI bridge pci:v*d*sv*sd*bc06sc04i00* ID_PCI_INTERFACE_FROM_DATABASE=Normal decode pci:v*d*sv*sd*bc06sc04i01* ID_PCI_INTERFACE_FROM_DATABASE=Subtractive decode pci:v*d*sv*sd*bc06sc05* ID_PCI_SUBCLASS_FROM_DATABASE=PCMCIA bridge pci:v*d*sv*sd*bc06sc06* ID_PCI_SUBCLASS_FROM_DATABASE=NuBus bridge pci:v*d*sv*sd*bc06sc07* ID_PCI_SUBCLASS_FROM_DATABASE=CardBus bridge pci:v*d*sv*sd*bc06sc08* ID_PCI_SUBCLASS_FROM_DATABASE=RACEway bridge pci:v*d*sv*sd*bc06sc08i00* ID_PCI_INTERFACE_FROM_DATABASE=Transparent mode pci:v*d*sv*sd*bc06sc08i01* ID_PCI_INTERFACE_FROM_DATABASE=Endpoint mode pci:v*d*sv*sd*bc06sc09* ID_PCI_SUBCLASS_FROM_DATABASE=Semi-transparent PCI-to-PCI bridge pci:v*d*sv*sd*bc06sc09i40* ID_PCI_INTERFACE_FROM_DATABASE=Primary bus towards host CPU pci:v*d*sv*sd*bc06sc09i80* ID_PCI_INTERFACE_FROM_DATABASE=Secondary bus towards host CPU pci:v*d*sv*sd*bc06sc0A* ID_PCI_SUBCLASS_FROM_DATABASE=InfiniBand to PCI host bridge pci:v*d*sv*sd*bc06sc80* ID_PCI_SUBCLASS_FROM_DATABASE=Bridge pci:v*d*sv*sd*bc07* ID_PCI_CLASS_FROM_DATABASE=Communication controller pci:v*d*sv*sd*bc07sc00* ID_PCI_SUBCLASS_FROM_DATABASE=Serial controller pci:v*d*sv*sd*bc07sc00i00* ID_PCI_INTERFACE_FROM_DATABASE=8250 pci:v*d*sv*sd*bc07sc00i01* ID_PCI_INTERFACE_FROM_DATABASE=16450 pci:v*d*sv*sd*bc07sc00i02* ID_PCI_INTERFACE_FROM_DATABASE=16550 pci:v*d*sv*sd*bc07sc00i03* ID_PCI_INTERFACE_FROM_DATABASE=16650 pci:v*d*sv*sd*bc07sc00i04* ID_PCI_INTERFACE_FROM_DATABASE=16750 pci:v*d*sv*sd*bc07sc00i05* ID_PCI_INTERFACE_FROM_DATABASE=16850 pci:v*d*sv*sd*bc07sc00i06* ID_PCI_INTERFACE_FROM_DATABASE=16950 pci:v*d*sv*sd*bc07sc01* ID_PCI_SUBCLASS_FROM_DATABASE=Parallel controller pci:v*d*sv*sd*bc07sc01i00* ID_PCI_INTERFACE_FROM_DATABASE=SPP pci:v*d*sv*sd*bc07sc01i01* ID_PCI_INTERFACE_FROM_DATABASE=BiDir pci:v*d*sv*sd*bc07sc01i02* ID_PCI_INTERFACE_FROM_DATABASE=ECP pci:v*d*sv*sd*bc07sc01i03* ID_PCI_INTERFACE_FROM_DATABASE=IEEE1284 pci:v*d*sv*sd*bc07sc01iFE* ID_PCI_INTERFACE_FROM_DATABASE=IEEE1284 Target pci:v*d*sv*sd*bc07sc02* ID_PCI_SUBCLASS_FROM_DATABASE=Multiport serial controller pci:v*d*sv*sd*bc07sc03* ID_PCI_SUBCLASS_FROM_DATABASE=Modem pci:v*d*sv*sd*bc07sc03i00* ID_PCI_INTERFACE_FROM_DATABASE=Generic pci:v*d*sv*sd*bc07sc03i01* ID_PCI_INTERFACE_FROM_DATABASE=Hayes/16450 pci:v*d*sv*sd*bc07sc03i02* ID_PCI_INTERFACE_FROM_DATABASE=Hayes/16550 pci:v*d*sv*sd*bc07sc03i03* ID_PCI_INTERFACE_FROM_DATABASE=Hayes/16650 pci:v*d*sv*sd*bc07sc03i04* ID_PCI_INTERFACE_FROM_DATABASE=Hayes/16750 pci:v*d*sv*sd*bc07sc04* ID_PCI_SUBCLASS_FROM_DATABASE=GPIB controller pci:v*d*sv*sd*bc07sc05* ID_PCI_SUBCLASS_FROM_DATABASE=Smard Card controller pci:v*d*sv*sd*bc07sc80* ID_PCI_SUBCLASS_FROM_DATABASE=Communication controller pci:v*d*sv*sd*bc08* ID_PCI_CLASS_FROM_DATABASE=Generic system peripheral pci:v*d*sv*sd*bc08sc00* ID_PCI_SUBCLASS_FROM_DATABASE=PIC pci:v*d*sv*sd*bc08sc00i00* ID_PCI_INTERFACE_FROM_DATABASE=8259 pci:v*d*sv*sd*bc08sc00i01* ID_PCI_INTERFACE_FROM_DATABASE=ISA PIC pci:v*d*sv*sd*bc08sc00i02* ID_PCI_INTERFACE_FROM_DATABASE=EISA PIC pci:v*d*sv*sd*bc08sc00i10* ID_PCI_INTERFACE_FROM_DATABASE=IO-APIC pci:v*d*sv*sd*bc08sc00i20* ID_PCI_INTERFACE_FROM_DATABASE=IO(X)-APIC pci:v*d*sv*sd*bc08sc01* ID_PCI_SUBCLASS_FROM_DATABASE=DMA controller pci:v*d*sv*sd*bc08sc01i00* ID_PCI_INTERFACE_FROM_DATABASE=8237 pci:v*d*sv*sd*bc08sc01i01* ID_PCI_INTERFACE_FROM_DATABASE=ISA DMA pci:v*d*sv*sd*bc08sc01i02* ID_PCI_INTERFACE_FROM_DATABASE=EISA DMA pci:v*d*sv*sd*bc08sc02* ID_PCI_SUBCLASS_FROM_DATABASE=Timer pci:v*d*sv*sd*bc08sc02i00* ID_PCI_INTERFACE_FROM_DATABASE=8254 pci:v*d*sv*sd*bc08sc02i01* ID_PCI_INTERFACE_FROM_DATABASE=ISA Timer pci:v*d*sv*sd*bc08sc02i02* ID_PCI_INTERFACE_FROM_DATABASE=EISA Timers pci:v*d*sv*sd*bc08sc02i03* ID_PCI_INTERFACE_FROM_DATABASE=HPET pci:v*d*sv*sd*bc08sc03* ID_PCI_SUBCLASS_FROM_DATABASE=RTC pci:v*d*sv*sd*bc08sc03i00* ID_PCI_INTERFACE_FROM_DATABASE=Generic pci:v*d*sv*sd*bc08sc03i01* ID_PCI_INTERFACE_FROM_DATABASE=ISA RTC pci:v*d*sv*sd*bc08sc04* ID_PCI_SUBCLASS_FROM_DATABASE=PCI Hot-plug controller pci:v*d*sv*sd*bc08sc05* ID_PCI_SUBCLASS_FROM_DATABASE=SD Host controller pci:v*d*sv*sd*bc08sc06* ID_PCI_SUBCLASS_FROM_DATABASE=IOMMU pci:v*d*sv*sd*bc08sc80* ID_PCI_SUBCLASS_FROM_DATABASE=System peripheral pci:v*d*sv*sd*bc09* ID_PCI_CLASS_FROM_DATABASE=Input device controller pci:v*d*sv*sd*bc09sc00* ID_PCI_SUBCLASS_FROM_DATABASE=Keyboard controller pci:v*d*sv*sd*bc09sc01* ID_PCI_SUBCLASS_FROM_DATABASE=Digitizer Pen pci:v*d*sv*sd*bc09sc02* ID_PCI_SUBCLASS_FROM_DATABASE=Mouse controller pci:v*d*sv*sd*bc09sc03* ID_PCI_SUBCLASS_FROM_DATABASE=Scanner controller pci:v*d*sv*sd*bc09sc04* ID_PCI_SUBCLASS_FROM_DATABASE=Gameport controller pci:v*d*sv*sd*bc09sc04i00* ID_PCI_INTERFACE_FROM_DATABASE=Generic pci:v*d*sv*sd*bc09sc04i10* ID_PCI_INTERFACE_FROM_DATABASE=Extended pci:v*d*sv*sd*bc09sc80* ID_PCI_SUBCLASS_FROM_DATABASE=Input device controller pci:v*d*sv*sd*bc0A* ID_PCI_CLASS_FROM_DATABASE=Docking station pci:v*d*sv*sd*bc0Asc00* ID_PCI_SUBCLASS_FROM_DATABASE=Generic Docking Station pci:v*d*sv*sd*bc0Asc80* ID_PCI_SUBCLASS_FROM_DATABASE=Docking Station pci:v*d*sv*sd*bc0B* ID_PCI_CLASS_FROM_DATABASE=Processor pci:v*d*sv*sd*bc0Bsc00* ID_PCI_SUBCLASS_FROM_DATABASE=386 pci:v*d*sv*sd*bc0Bsc01* ID_PCI_SUBCLASS_FROM_DATABASE=486 pci:v*d*sv*sd*bc0Bsc02* ID_PCI_SUBCLASS_FROM_DATABASE=Pentium pci:v*d*sv*sd*bc0Bsc10* ID_PCI_SUBCLASS_FROM_DATABASE=Alpha pci:v*d*sv*sd*bc0Bsc20* ID_PCI_SUBCLASS_FROM_DATABASE=Power PC pci:v*d*sv*sd*bc0Bsc30* ID_PCI_SUBCLASS_FROM_DATABASE=MIPS pci:v*d*sv*sd*bc0Bsc40* ID_PCI_SUBCLASS_FROM_DATABASE=Co-processor pci:v*d*sv*sd*bc0C* ID_PCI_CLASS_FROM_DATABASE=Serial bus controller pci:v*d*sv*sd*bc0Csc00* ID_PCI_SUBCLASS_FROM_DATABASE=FireWire (IEEE 1394) pci:v*d*sv*sd*bc0Csc00i00* ID_PCI_INTERFACE_FROM_DATABASE=Generic pci:v*d*sv*sd*bc0Csc00i10* ID_PCI_INTERFACE_FROM_DATABASE=OHCI pci:v*d*sv*sd*bc0Csc01* ID_PCI_SUBCLASS_FROM_DATABASE=ACCESS Bus pci:v*d*sv*sd*bc0Csc02* ID_PCI_SUBCLASS_FROM_DATABASE=SSA pci:v*d*sv*sd*bc0Csc03* ID_PCI_SUBCLASS_FROM_DATABASE=USB controller pci:v*d*sv*sd*bc0Csc03i00* ID_PCI_INTERFACE_FROM_DATABASE=UHCI pci:v*d*sv*sd*bc0Csc03i10* ID_PCI_INTERFACE_FROM_DATABASE=OHCI pci:v*d*sv*sd*bc0Csc03i20* ID_PCI_INTERFACE_FROM_DATABASE=EHCI pci:v*d*sv*sd*bc0Csc03i30* ID_PCI_INTERFACE_FROM_DATABASE=XHCI pci:v*d*sv*sd*bc0Csc03i80* ID_PCI_INTERFACE_FROM_DATABASE=Unspecified pci:v*d*sv*sd*bc0Csc03iFE* ID_PCI_INTERFACE_FROM_DATABASE=USB Device pci:v*d*sv*sd*bc0Csc04* ID_PCI_SUBCLASS_FROM_DATABASE=Fibre Channel pci:v*d*sv*sd*bc0Csc05* ID_PCI_SUBCLASS_FROM_DATABASE=SMBus pci:v*d*sv*sd*bc0Csc06* ID_PCI_SUBCLASS_FROM_DATABASE=InfiniBand pci:v*d*sv*sd*bc0Csc07* ID_PCI_SUBCLASS_FROM_DATABASE=IPMI SMIC interface pci:v*d*sv*sd*bc0Csc08* ID_PCI_SUBCLASS_FROM_DATABASE=SERCOS interface pci:v*d*sv*sd*bc0Csc09* ID_PCI_SUBCLASS_FROM_DATABASE=CANBUS pci:v*d*sv*sd*bc0D* ID_PCI_CLASS_FROM_DATABASE=Wireless controller pci:v*d*sv*sd*bc0Dsc00* ID_PCI_SUBCLASS_FROM_DATABASE=IRDA controller pci:v*d*sv*sd*bc0Dsc01* ID_PCI_SUBCLASS_FROM_DATABASE=Consumer IR controller pci:v*d*sv*sd*bc0Dsc10* ID_PCI_SUBCLASS_FROM_DATABASE=RF controller pci:v*d*sv*sd*bc0Dsc11* ID_PCI_SUBCLASS_FROM_DATABASE=Bluetooth pci:v*d*sv*sd*bc0Dsc12* ID_PCI_SUBCLASS_FROM_DATABASE=Broadband pci:v*d*sv*sd*bc0Dsc20* ID_PCI_SUBCLASS_FROM_DATABASE=802.1a controller pci:v*d*sv*sd*bc0Dsc21* ID_PCI_SUBCLASS_FROM_DATABASE=802.1b controller pci:v*d*sv*sd*bc0Dsc80* ID_PCI_SUBCLASS_FROM_DATABASE=Wireless controller pci:v*d*sv*sd*bc0E* ID_PCI_CLASS_FROM_DATABASE=Intelligent controller pci:v*d*sv*sd*bc0Esc00* ID_PCI_SUBCLASS_FROM_DATABASE=I2O pci:v*d*sv*sd*bc0F* ID_PCI_CLASS_FROM_DATABASE=Satellite communications controller pci:v*d*sv*sd*bc0Fsc01* ID_PCI_SUBCLASS_FROM_DATABASE=Satellite TV controller pci:v*d*sv*sd*bc0Fsc02* ID_PCI_SUBCLASS_FROM_DATABASE=Satellite audio communication controller pci:v*d*sv*sd*bc0Fsc03* ID_PCI_SUBCLASS_FROM_DATABASE=Satellite voice communication controller pci:v*d*sv*sd*bc0Fsc04* ID_PCI_SUBCLASS_FROM_DATABASE=Satellite data communication controller pci:v*d*sv*sd*bc10* ID_PCI_CLASS_FROM_DATABASE=Encryption controller pci:v*d*sv*sd*bc10sc00* ID_PCI_SUBCLASS_FROM_DATABASE=Network and computing encryption device pci:v*d*sv*sd*bc10sc10* ID_PCI_SUBCLASS_FROM_DATABASE=Entertainment encryption device pci:v*d*sv*sd*bc10sc80* ID_PCI_SUBCLASS_FROM_DATABASE=Encryption controller pci:v*d*sv*sd*bc11* ID_PCI_CLASS_FROM_DATABASE=Signal processing controller pci:v*d*sv*sd*bc11sc00* ID_PCI_SUBCLASS_FROM_DATABASE=DPIO module pci:v*d*sv*sd*bc11sc01* ID_PCI_SUBCLASS_FROM_DATABASE=Performance counters pci:v*d*sv*sd*bc11sc10* ID_PCI_SUBCLASS_FROM_DATABASE=Communication synchronizer pci:v*d*sv*sd*bc11sc20* ID_PCI_SUBCLASS_FROM_DATABASE=Signal processing management pci:v*d*sv*sd*bc11sc80* ID_PCI_SUBCLASS_FROM_DATABASE=Signal processing controller pci:v*d*sv*sd*bc12* ID_PCI_CLASS_FROM_DATABASE=Processing accelerators pci:v*d*sv*sd*bc12sc00* ID_PCI_SUBCLASS_FROM_DATABASE=Processing accelerators pci:v*d*sv*sd*bc13* ID_PCI_CLASS_FROM_DATABASE=Non-Essential Instrumentation pci:v*d*sv*sd*bc40* ID_PCI_CLASS_FROM_DATABASE=Coprocessor pci:v*d*sv*sd*bcFF* ID_PCI_CLASS_FROM_DATABASE=Unassigned class systemd-229/hwdb/20-pci-vendor-model.hwdb000066400000000000000000122270711265713322000202520ustar00rootroot00000000000000# This file is part of systemd. # # Data imported from: http://pci-ids.ucw.cz/v2.2/pci.ids pci:v00000001* ID_VENDOR_FROM_DATABASE=SafeNet (wrong ID) pci:v00000010* ID_VENDOR_FROM_DATABASE=Allied Telesis, Inc (Wrong ID) pci:v00000010d00008139* ID_MODEL_FROM_DATABASE=AT-2500TX V3 Ethernet pci:v0000001C* ID_VENDOR_FROM_DATABASE=PEAK-System Technik GmbH pci:v0000001Cd00000001* ID_MODEL_FROM_DATABASE=PCAN-PCI CAN-Bus controller pci:v0000001Cd00000001sv0000001Csd00000004* ID_MODEL_FROM_DATABASE=PCAN-PCI CAN-Bus controller (2 Channel CAN Bus SJC1000) pci:v0000001Cd00000001sv0000001Csd00000005* ID_MODEL_FROM_DATABASE=PCAN-PCI CAN-Bus controller (2 Channel CAN Bus SJC1000 (Optically Isolated)) pci:v0000003D* ID_VENDOR_FROM_DATABASE=Lockheed Martin-Marietta Corp pci:v00000059* ID_VENDOR_FROM_DATABASE=Tiger Jet Network Inc. (Wrong ID) pci:v00000070* ID_VENDOR_FROM_DATABASE=Hauppauge computer works Inc. pci:v00000070d00007801* ID_MODEL_FROM_DATABASE=WinTV HVR-1800 MCE pci:v00000071* ID_VENDOR_FROM_DATABASE=Nebula Electronics Ltd. pci:v00000095* ID_VENDOR_FROM_DATABASE=Silicon Image, Inc. (Wrong ID) pci:v00000095d00000680* ID_MODEL_FROM_DATABASE=Ultra ATA/133 IDE RAID CONTROLLER CARD pci:v000000A7* ID_VENDOR_FROM_DATABASE=Teles AG (Wrong ID) pci:v00000100* ID_VENDOR_FROM_DATABASE=Ncipher Corp Ltd pci:v00000123* ID_VENDOR_FROM_DATABASE=General Dynamics pci:v0000018A* ID_VENDOR_FROM_DATABASE=LevelOne pci:v0000018Ad00000106* ID_MODEL_FROM_DATABASE=FPC-0106TX misprogrammed [RTL81xx] pci:v0000021B* ID_VENDOR_FROM_DATABASE=Compaq Computer Corporation pci:v0000021Bd00008139* ID_MODEL_FROM_DATABASE=HNE-300 (RealTek RTL8139c) [iPaq Networking] pci:v00000270* ID_VENDOR_FROM_DATABASE=Hauppauge computer works Inc. (Wrong ID) pci:v000002AC* ID_VENDOR_FROM_DATABASE=SpeedStream pci:v000002ACd00001012* ID_MODEL_FROM_DATABASE=1012 PCMCIA 10/100 Ethernet Card [RTL81xx] pci:v00000303* ID_VENDOR_FROM_DATABASE=Hewlett-Packard Company (Wrong ID) pci:v00000308* ID_VENDOR_FROM_DATABASE=ZyXEL Communications Corporation (Wrong ID) pci:v00000315* ID_VENDOR_FROM_DATABASE=SK-Electronics Co., Ltd. pci:v00000357* ID_VENDOR_FROM_DATABASE=TTTech Computertechnik AG (Wrong ID) pci:v00000357d0000000A* ID_MODEL_FROM_DATABASE=TTP-Monitoring Card V2.0 pci:v00000432* ID_VENDOR_FROM_DATABASE=SCM Microsystems, Inc. pci:v00000432d00000001* ID_MODEL_FROM_DATABASE=Pluto2 DVB-T Receiver for PCMCIA [EasyWatch MobilSet] pci:v00000675* ID_VENDOR_FROM_DATABASE=Dynalink pci:v00000675d00001700* ID_MODEL_FROM_DATABASE=IS64PH ISDN Adapter pci:v00000675d00001702* ID_MODEL_FROM_DATABASE=IS64PH ISDN Adapter pci:v00000675d00001703* ID_MODEL_FROM_DATABASE=ISDN Adapter (PCI Bus, DV, W) pci:v00000675d00001704* ID_MODEL_FROM_DATABASE=ISDN Adapter (PCI Bus, D, C) pci:v00000721* ID_VENDOR_FROM_DATABASE=Sapphire, Inc. pci:v00000777* ID_VENDOR_FROM_DATABASE=Ubiquiti Networks, Inc. pci:v00000795* ID_VENDOR_FROM_DATABASE=Wired Inc. pci:v00000795d00006663* ID_MODEL_FROM_DATABASE=Butane II (MPEG2 encoder board) pci:v00000795d00006666* ID_MODEL_FROM_DATABASE=MediaPress (MPEG2 encoder board) pci:v000007D1* ID_VENDOR_FROM_DATABASE=D-Link System Inc pci:v00000925* ID_VENDOR_FROM_DATABASE=VIA Technologies, Inc. (Wrong ID) pci:v00000A89* ID_VENDOR_FROM_DATABASE=BREA Technologies Inc pci:v00000B0B* ID_VENDOR_FROM_DATABASE=Rhino Equipment Corp. pci:v00000B0Bd00000105* ID_MODEL_FROM_DATABASE=Rhino R1T1 pci:v00000B0Bd00000205* ID_MODEL_FROM_DATABASE=Rhino R4FXO pci:v00000B0Bd00000206* ID_MODEL_FROM_DATABASE=RCB4FXO 4-channel FXO analog telphony card pci:v00000B0Bd00000305* ID_MODEL_FROM_DATABASE=Rhino R4T1 pci:v00000B0Bd00000405* ID_MODEL_FROM_DATABASE=Rhino R8FXX pci:v00000B0Bd00000406* ID_MODEL_FROM_DATABASE=RCB8FXX 8-channel modular analog telphony card pci:v00000B0Bd00000505* ID_MODEL_FROM_DATABASE=Rhino R24FXX pci:v00000B0Bd00000506* ID_MODEL_FROM_DATABASE=RCB24FXS 24-Channel FXS analog telphony card pci:v00000B0Bd00000605* ID_MODEL_FROM_DATABASE=Rhino R2T1 pci:v00000B0Bd00000705* ID_MODEL_FROM_DATABASE=Rhino R24FXS pci:v00000B0Bd00000706* ID_MODEL_FROM_DATABASE=RCB24FXO 24-Channel FXO analog telphony card pci:v00000B0Bd00000905* ID_MODEL_FROM_DATABASE=R1T3 Single T3 Digital Telephony Card pci:v00000B0Bd00000906* ID_MODEL_FROM_DATABASE=RCB24FXX 24-channel modular analog telphony card pci:v00000B0Bd00000A06* ID_MODEL_FROM_DATABASE=RCB672FXX 672-channel modular analog telphony card pci:v00000E11* ID_VENDOR_FROM_DATABASE=Compaq Computer Corporation pci:v00000E11d00000001* ID_MODEL_FROM_DATABASE=PCI to EISA Bridge pci:v00000E11d00000002* ID_MODEL_FROM_DATABASE=PCI to ISA Bridge pci:v00000E11d00000046* ID_MODEL_FROM_DATABASE=Smart Array 64xx pci:v00000E11d00000046sv00000E11sd00004091* ID_MODEL_FROM_DATABASE=Smart Array 64xx (Smart Array 6i) pci:v00000E11d00000046sv00000E11sd0000409A* ID_MODEL_FROM_DATABASE=Smart Array 64xx (Smart Array 641) pci:v00000E11d00000046sv00000E11sd0000409B* ID_MODEL_FROM_DATABASE=Smart Array 64xx (Smart Array 642) pci:v00000E11d00000046sv00000E11sd0000409C* ID_MODEL_FROM_DATABASE=Smart Array 64xx (Smart Array 6400) pci:v00000E11d00000046sv00000E11sd0000409D* ID_MODEL_FROM_DATABASE=Smart Array 64xx (Smart Array 6400 EM) pci:v00000E11d00000049* ID_MODEL_FROM_DATABASE=NC7132 Gigabit Upgrade Module pci:v00000E11d0000004A* ID_MODEL_FROM_DATABASE=NC6136 Gigabit Server Adapter pci:v00000E11d0000005A* ID_MODEL_FROM_DATABASE=Remote Insight II board - Lights-Out pci:v00000E11d0000007C* ID_MODEL_FROM_DATABASE=NC7770 1000BaseTX pci:v00000E11d0000007D* ID_MODEL_FROM_DATABASE=NC6770 1000BaseTX pci:v00000E11d00000085* ID_MODEL_FROM_DATABASE=NC7780 1000BaseTX pci:v00000E11d000000B1* ID_MODEL_FROM_DATABASE=Remote Insight II board - PCI device pci:v00000E11d000000BB* ID_MODEL_FROM_DATABASE=NC7760 pci:v00000E11d000000CA* ID_MODEL_FROM_DATABASE=NC7771 pci:v00000E11d000000CB* ID_MODEL_FROM_DATABASE=NC7781 pci:v00000E11d000000CF* ID_MODEL_FROM_DATABASE=NC7772 pci:v00000E11d000000D0* ID_MODEL_FROM_DATABASE=NC7782 pci:v00000E11d000000D1* ID_MODEL_FROM_DATABASE=NC7783 pci:v00000E11d000000E3* ID_MODEL_FROM_DATABASE=NC7761 pci:v00000E11d00000508* ID_MODEL_FROM_DATABASE=Netelligent 4/16 Token Ring pci:v00000E11d00001000* ID_MODEL_FROM_DATABASE=Triflex/Pentium Bridge, Model 1000 pci:v00000E11d00002000* ID_MODEL_FROM_DATABASE=Triflex/Pentium Bridge, Model 2000 pci:v00000E11d00003032* ID_MODEL_FROM_DATABASE=QVision 1280/p pci:v00000E11d00003033* ID_MODEL_FROM_DATABASE=QVision 1280/p pci:v00000E11d00003034* ID_MODEL_FROM_DATABASE=QVision 1280/p pci:v00000E11d00004000* ID_MODEL_FROM_DATABASE=4000 [Triflex] pci:v00000E11d00004040* ID_MODEL_FROM_DATABASE=Integrated Array pci:v00000E11d00004048* ID_MODEL_FROM_DATABASE=Compaq Raid LC2 pci:v00000E11d00004050* ID_MODEL_FROM_DATABASE=Smart Array 4200 pci:v00000E11d00004051* ID_MODEL_FROM_DATABASE=Smart Array 4250ES pci:v00000E11d00004058* ID_MODEL_FROM_DATABASE=Smart Array 431 pci:v00000E11d00004070* ID_MODEL_FROM_DATABASE=Smart Array 5300 pci:v00000E11d00004080* ID_MODEL_FROM_DATABASE=Smart Array 5i pci:v00000E11d00004082* ID_MODEL_FROM_DATABASE=Smart Array 532 pci:v00000E11d00004083* ID_MODEL_FROM_DATABASE=Smart Array 5312 pci:v00000E11d00004091* ID_MODEL_FROM_DATABASE=Smart Array 6i pci:v00000E11d0000409A* ID_MODEL_FROM_DATABASE=Smart Array 641 pci:v00000E11d0000409B* ID_MODEL_FROM_DATABASE=Smart Array 642 pci:v00000E11d0000409C* ID_MODEL_FROM_DATABASE=Smart Array 6400 pci:v00000E11d0000409D* ID_MODEL_FROM_DATABASE=Smart Array 6400 EM pci:v00000E11d00006010* ID_MODEL_FROM_DATABASE=HotPlug PCI Bridge 6010 pci:v00000E11d00007020* ID_MODEL_FROM_DATABASE=USB Controller pci:v00000E11d0000A0EC* ID_MODEL_FROM_DATABASE=Fibre Channel Host Controller pci:v00000E11d0000A0F0* ID_MODEL_FROM_DATABASE=Advanced System Management Controller pci:v00000E11d0000A0F0sv00000E11sd0000B0F3* ID_MODEL_FROM_DATABASE=Advanced System Management Controller (ProLiant DL360) pci:v00000E11d0000A0F3* ID_MODEL_FROM_DATABASE=Triflex PCI to ISA Bridge pci:v00000E11d0000A0F7* ID_MODEL_FROM_DATABASE=PCI Hotplug Controller pci:v00000E11d0000A0F7sv00008086sd0000002A* ID_MODEL_FROM_DATABASE=PCI Hotplug Controller (A) pci:v00000E11d0000A0F7sv00008086sd0000002B* ID_MODEL_FROM_DATABASE=PCI Hotplug Controller (B) pci:v00000E11d0000A0F8* ID_MODEL_FROM_DATABASE=ZFMicro Chipset USB pci:v00000E11d0000A0FC* ID_MODEL_FROM_DATABASE=FibreChannel HBA Tachyon pci:v00000E11d0000AE10* ID_MODEL_FROM_DATABASE=Smart-2/P RAID Controller pci:v00000E11d0000AE10sv00000E11sd00004030* ID_MODEL_FROM_DATABASE=Smart-2/P RAID Controller (Smart-2/P Array Controller) pci:v00000E11d0000AE10sv00000E11sd00004031* ID_MODEL_FROM_DATABASE=Smart-2/P RAID Controller (Smart-2SL Array Controller) pci:v00000E11d0000AE10sv00000E11sd00004032* ID_MODEL_FROM_DATABASE=Smart-2/P RAID Controller (Smart Array 3200 Controller) pci:v00000E11d0000AE10sv00000E11sd00004033* ID_MODEL_FROM_DATABASE=Smart-2/P RAID Controller (Smart Array 3100ES Controller) pci:v00000E11d0000AE10sv00000E11sd00004034* ID_MODEL_FROM_DATABASE=Smart-2/P RAID Controller (Smart Array 221 Controller) pci:v00000E11d0000AE29* ID_MODEL_FROM_DATABASE=MIS-L pci:v00000E11d0000AE2A* ID_MODEL_FROM_DATABASE=MPC pci:v00000E11d0000AE2B* ID_MODEL_FROM_DATABASE=MIS-E pci:v00000E11d0000AE31* ID_MODEL_FROM_DATABASE=System Management Controller pci:v00000E11d0000AE32* ID_MODEL_FROM_DATABASE=Netelligent 10/100 TX PCI UTP pci:v00000E11d0000AE33* ID_MODEL_FROM_DATABASE=Triflex Dual EIDE Controller pci:v00000E11d0000AE34* ID_MODEL_FROM_DATABASE=Netelligent 10 T PCI UTP pci:v00000E11d0000AE35* ID_MODEL_FROM_DATABASE=Integrated NetFlex-3/P pci:v00000E11d0000AE40* ID_MODEL_FROM_DATABASE=Netelligent Dual 10/100 TX PCI UTP pci:v00000E11d0000AE43* ID_MODEL_FROM_DATABASE=Netelligent Integrated 10/100 TX UTP pci:v00000E11d0000AE69* ID_MODEL_FROM_DATABASE=CETUS-L pci:v00000E11d0000AE6C* ID_MODEL_FROM_DATABASE=Northstar pci:v00000E11d0000AE6D* ID_MODEL_FROM_DATABASE=NorthStar CPU to PCI Bridge pci:v00000E11d0000B011* ID_MODEL_FROM_DATABASE=Netelligent 10/100 TX Embedded UTP pci:v00000E11d0000B012* ID_MODEL_FROM_DATABASE=Netelligent 10 T/2 PCI UTP/Coax pci:v00000E11d0000B01E* ID_MODEL_FROM_DATABASE=NC3120 Fast Ethernet NIC pci:v00000E11d0000B01F* ID_MODEL_FROM_DATABASE=NC3122 Fast Ethernet NIC pci:v00000E11d0000B02F* ID_MODEL_FROM_DATABASE=NC1120 Ethernet NIC pci:v00000E11d0000B030* ID_MODEL_FROM_DATABASE=Netelligent 10/100 TX UTP pci:v00000E11d0000B04A* ID_MODEL_FROM_DATABASE=10/100 TX PCI Intel WOL UTP Controller pci:v00000E11d0000B060* ID_MODEL_FROM_DATABASE=Smart Array 5300 Controller pci:v00000E11d0000B0C6* ID_MODEL_FROM_DATABASE=NC3161 Fast Ethernet NIC pci:v00000E11d0000B0C7* ID_MODEL_FROM_DATABASE=NC3160 Fast Ethernet NIC pci:v00000E11d0000B0D7* ID_MODEL_FROM_DATABASE=NC3121 Fast Ethernet NIC pci:v00000E11d0000B0DD* ID_MODEL_FROM_DATABASE=NC3131 Fast Ethernet NIC pci:v00000E11d0000B0DE* ID_MODEL_FROM_DATABASE=NC3132 Fast Ethernet Module pci:v00000E11d0000B0DF* ID_MODEL_FROM_DATABASE=NC6132 Gigabit Module pci:v00000E11d0000B0E0* ID_MODEL_FROM_DATABASE=NC6133 Gigabit Module pci:v00000E11d0000B0E1* ID_MODEL_FROM_DATABASE=NC3133 Fast Ethernet Module pci:v00000E11d0000B123* ID_MODEL_FROM_DATABASE=NC6134 Gigabit NIC pci:v00000E11d0000B134* ID_MODEL_FROM_DATABASE=NC3163 Fast Ethernet NIC pci:v00000E11d0000B13C* ID_MODEL_FROM_DATABASE=NC3162 Fast Ethernet NIC pci:v00000E11d0000B144* ID_MODEL_FROM_DATABASE=NC3123 Fast Ethernet NIC pci:v00000E11d0000B163* ID_MODEL_FROM_DATABASE=NC3134 Fast Ethernet NIC pci:v00000E11d0000B164* ID_MODEL_FROM_DATABASE=NC3165 Fast Ethernet Upgrade Module pci:v00000E11d0000B178* ID_MODEL_FROM_DATABASE=Smart Array 5i/532 pci:v00000E11d0000B178sv00000E11sd00004080* ID_MODEL_FROM_DATABASE=Smart Array 5i/532 (Smart Array 5i) pci:v00000E11d0000B178sv00000E11sd00004082* ID_MODEL_FROM_DATABASE=Smart Array 5i/532 (Smart Array 532) pci:v00000E11d0000B178sv00000E11sd00004083* ID_MODEL_FROM_DATABASE=Smart Array 5i/532 (Smart Array 5312) pci:v00000E11d0000B1A4* ID_MODEL_FROM_DATABASE=NC7131 Gigabit Server Adapter pci:v00000E11d0000B200* ID_MODEL_FROM_DATABASE=Memory Hot-Plug Controller pci:v00000E11d0000B203* ID_MODEL_FROM_DATABASE=Integrated Lights Out Controller pci:v00000E11d0000B204* ID_MODEL_FROM_DATABASE=Integrated Lights Out Processor pci:v00000E11d0000C000* ID_MODEL_FROM_DATABASE=Remote Insight Lights-Out Edition pci:v00000E11d0000F130* ID_MODEL_FROM_DATABASE=NetFlex-3/P ThunderLAN 1.0 pci:v00000E11d0000F150* ID_MODEL_FROM_DATABASE=NetFlex-3/P ThunderLAN 2.3 pci:v00000E55* ID_VENDOR_FROM_DATABASE=HaSoTec GmbH pci:v00000EAC* ID_VENDOR_FROM_DATABASE=SHF Communication Technologies AG pci:v00000EACd00000008* ID_MODEL_FROM_DATABASE=Ethernet Powerlink Managing Node 01 pci:v00000F62* ID_VENDOR_FROM_DATABASE=Acrox Technologies Co., Ltd. pci:v00001000* ID_VENDOR_FROM_DATABASE=LSI Logic / Symbios Logic pci:v00001000d00000001* ID_MODEL_FROM_DATABASE=53c810 pci:v00001000d00000001sv00001000sd00001000* ID_MODEL_FROM_DATABASE=53c810 (LSI53C810AE PCI to SCSI I/O Processor) pci:v00001000d00000002* ID_MODEL_FROM_DATABASE=53c820 pci:v00001000d00000003* ID_MODEL_FROM_DATABASE=53c825 pci:v00001000d00000003sv00001000sd00001000* ID_MODEL_FROM_DATABASE=53c825 (LSI53C825AE PCI to SCSI I/O Processor (Ultra Wide)) pci:v00001000d00000004* ID_MODEL_FROM_DATABASE=53c815 pci:v00001000d00000005* ID_MODEL_FROM_DATABASE=53c810AP pci:v00001000d00000006* ID_MODEL_FROM_DATABASE=53c860 pci:v00001000d00000006sv00001000sd00001000* ID_MODEL_FROM_DATABASE=53c860 (LSI53C860E PCI to Ultra SCSI I/O Processor) pci:v00001000d0000000A* ID_MODEL_FROM_DATABASE=53c1510 pci:v00001000d0000000Asv00000E11sd0000B143* ID_MODEL_FROM_DATABASE=53c1510 (Integrated Dual Channel Wide Ultra2 SCSI Controller) pci:v00001000d0000000Asv00001000sd00001000* ID_MODEL_FROM_DATABASE=53c1510 (LSI53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Nonintelligent mode)) pci:v00001000d0000000B* ID_MODEL_FROM_DATABASE=53C896/897 pci:v00001000d0000000Bsv00000E11sd00006004* ID_MODEL_FROM_DATABASE=53C896/897 (EOB003 Series SCSI host adapter) pci:v00001000d0000000Bsv00001000sd00001000* ID_MODEL_FROM_DATABASE=53C896/897 (LSI53C896/7 PCI to Dual Channel Ultra2 SCSI Multifunction Controller) pci:v00001000d0000000Bsv00001000sd00001010* ID_MODEL_FROM_DATABASE=53C896/897 (LSI22910 PCI to Dual Channel Ultra2 SCSI host adapter) pci:v00001000d0000000Bsv00001000sd00001020* ID_MODEL_FROM_DATABASE=53C896/897 (LSI21002 PCI to Dual Channel Ultra2 SCSI host adapter) pci:v00001000d0000000Bsv000013E9sd00001000* ID_MODEL_FROM_DATABASE=53C896/897 (6221L-4U (Dual U2W SCSI, dual 10/100TX, graphics)) pci:v00001000d0000000C* ID_MODEL_FROM_DATABASE=53c895 pci:v00001000d0000000Csv00001000sd00001010* ID_MODEL_FROM_DATABASE=53c895 (LSI8951U PCI to Ultra2 SCSI host adapter) pci:v00001000d0000000Csv00001000sd00001020* ID_MODEL_FROM_DATABASE=53c895 (LSI8952U PCI to Ultra2 SCSI host adapter) pci:v00001000d0000000Csv00001DE1sd00003906* ID_MODEL_FROM_DATABASE=53c895 (DC-390U2B SCSI adapter) pci:v00001000d0000000Csv00001DE1sd00003907* ID_MODEL_FROM_DATABASE=53c895 (DC-390U2W) pci:v00001000d0000000D* ID_MODEL_FROM_DATABASE=53c885 pci:v00001000d0000000F* ID_MODEL_FROM_DATABASE=53c875 pci:v00001000d0000000Fsv00000E11sd00007004* ID_MODEL_FROM_DATABASE=53c875 (Embedded Ultra Wide SCSI Controller) pci:v00001000d0000000Fsv00001000sd00001000* ID_MODEL_FROM_DATABASE=53c875 (LSI53C876/E PCI to Dual Channel SCSI Controller) pci:v00001000d0000000Fsv00001000sd00001010* ID_MODEL_FROM_DATABASE=53c875 (LSI22801 PCI to Dual Channel Ultra SCSI host adapter) pci:v00001000d0000000Fsv00001000sd00001020* ID_MODEL_FROM_DATABASE=53c875 (LSI22802 PCI to Dual Channel Ultra SCSI host adapter) pci:v00001000d0000000Fsv00001092sd00008760* ID_MODEL_FROM_DATABASE=53c875 (FirePort 40 Dual SCSI Controller) pci:v00001000d0000000Fsv00001775sd000010D0* ID_MODEL_FROM_DATABASE=53c875 (V5D Single Board Computer Wide Ultra SCSI) pci:v00001000d0000000Fsv00001775sd000010D1* ID_MODEL_FROM_DATABASE=53c875 (V5D Single Board Computer Ultra SCSI) pci:v00001000d0000000Fsv00001DE1sd00003904* ID_MODEL_FROM_DATABASE=53c875 (DC390F/U Ultra Wide SCSI Adapter) pci:v00001000d0000000Fsv00004C53sd00001000* ID_MODEL_FROM_DATABASE=53c875 (CC7/CR7/CP7/VC7/VP7/VR7 mainboard) pci:v00001000d0000000Fsv00004C53sd00001050* ID_MODEL_FROM_DATABASE=53c875 (CT7 mainboard) pci:v00001000d00000010* ID_MODEL_FROM_DATABASE=53C1510 pci:v00001000d00000010sv00000E11sd00004040* ID_MODEL_FROM_DATABASE=53C1510 (Integrated Smart Array Controller) pci:v00001000d00000010sv00000E11sd00004048* ID_MODEL_FROM_DATABASE=53C1510 (RAID LC2 Controller) pci:v00001000d00000010sv00001000sd00001000* ID_MODEL_FROM_DATABASE=53C1510 (PCI to Dual Channel Wide Ultra2 SCSI Controller (Intelligent mode)) pci:v00001000d00000012* ID_MODEL_FROM_DATABASE=53c895a pci:v00001000d00000012sv00001000sd00001000* ID_MODEL_FROM_DATABASE=53c895a (LSI53C895A PCI to Ultra2 SCSI Controller) pci:v00001000d00000013* ID_MODEL_FROM_DATABASE=53c875a pci:v00001000d00000013sv00001000sd00001000* ID_MODEL_FROM_DATABASE=53c875a (LSI53C875A PCI to Ultra SCSI Controller) pci:v00001000d00000020* ID_MODEL_FROM_DATABASE=53c1010 Ultra3 SCSI Adapter pci:v00001000d00000020sv00001000sd00001000* ID_MODEL_FROM_DATABASE=53c1010 Ultra3 SCSI Adapter (LSI53C1010-33 PCI to Dual Channel Ultra160 SCSI Controller) pci:v00001000d00000020sv0000107Bsd00001040* ID_MODEL_FROM_DATABASE=53c1010 Ultra3 SCSI Adapter (Server Onboard 53C1010-33) pci:v00001000d00000020sv00001DE1sd00001020* ID_MODEL_FROM_DATABASE=53c1010 Ultra3 SCSI Adapter (DC-390U3W) pci:v00001000d00000021* ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter pci:v00001000d00000021sv00001000sd00001000* ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (LSI53C1000/1000R/1010R/1010-66 PCI to Ultra160 SCSI Controller) pci:v00001000d00000021sv00001000sd00001010* ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (Asus TR-DLS onboard 53C1010-66) pci:v00001000d00000021sv0000103Csd00001300* ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (Ultra160 SCSI [AB306A]) pci:v00001000d00000021sv0000103Csd00001310* ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (Ultra160 SCSI [A9918A]) pci:v00001000d00000021sv0000103Csd00001330* ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (Ultra160 SCSI [A7059A]) pci:v00001000d00000021sv0000103Csd00001340* ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (Ultra160 SCSI [A7060A]) pci:v00001000d00000021sv0000124Bsd00001070* ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (PMC-USCSI3) pci:v00001000d00000021sv00004C53sd00001080* ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (CT8 mainboard) pci:v00001000d00000021sv00004C53sd00001300* ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (P017 mezzanine (32-bit PMC)) pci:v00001000d00000021sv00004C53sd00001310* ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (P017 mezzanine (64-bit PMC)) pci:v00001000d0000002F* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 IOV [Thunderbolt] pci:v00001000d0000002Fsv00001028sd00001F39* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 IOV [Thunderbolt] (SPERC8-e) pci:v00001000d0000002Fsv00001028sd00001F3E* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 IOV [Thunderbolt] (SPERC 8) pci:v00001000d00000030* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI pci:v00001000d00000030sv00000E11sd000000DA* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (ProLiant ML 350) pci:v00001000d00000030sv00001028sd00000123* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (LSI Logic 1020/1030) pci:v00001000d00000030sv00001028sd0000014A* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (LSI Logic 1020/1030) pci:v00001000d00000030sv00001028sd0000016C* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (PowerEdge 1850 MPT Fusion SCSI/RAID (Perc 4)) pci:v00001000d00000030sv00001028sd00000183* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (LSI Logic 1020/1030) pci:v00001000d00000030sv00001028sd0000018A* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (PERC 4/IM) pci:v00001000d00000030sv00001028sd00001010* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (LSI U320 SCSI Controller) pci:v00001000d00000030sv0000103Csd000012C5* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (Ultra320 SCSI [A7173A]) pci:v00001000d00000030sv0000103Csd00001323* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (Core I/O LAN/SCSI Combo [AB314A]) pci:v00001000d00000030sv0000103Csd00003108* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (Single Channel Ultra320 SCSI HBA G2) pci:v00001000d00000030sv0000124Bsd00001170* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (PMC-USCSI320) pci:v00001000d00000030sv000015ADsd00001976* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (LSI Logic Parallel SCSI Controller) pci:v00001000d00000030sv00001734sd00001052* ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (PRIMERGY BX/RX/TX S2 series onboard SCSI(IME)) pci:v00001000d00000031* ID_MODEL_FROM_DATABASE=53c1030ZC PCI-X Fusion-MPT Dual Ultra320 SCSI pci:v00001000d00000032* ID_MODEL_FROM_DATABASE=53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI pci:v00001000d00000032sv00001000sd00001000* ID_MODEL_FROM_DATABASE=53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI (LSI53C1020/1030 PCI-X to Ultra320 SCSI Controller) pci:v00001000d00000033* ID_MODEL_FROM_DATABASE=1030ZC_53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI pci:v00001000d00000040* ID_MODEL_FROM_DATABASE=53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI pci:v00001000d00000040sv00001000sd00000033* ID_MODEL_FROM_DATABASE=53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI (MegaRAID SCSI 320-2XR) pci:v00001000d00000040sv00001000sd00000066* ID_MODEL_FROM_DATABASE=53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI (MegaRAID SCSI 320-2XRWS) pci:v00001000d00000041* ID_MODEL_FROM_DATABASE=53C1035ZC PCI-X Fusion-MPT Dual Ultra320 SCSI pci:v00001000d00000050* ID_MODEL_FROM_DATABASE=SAS1064 PCI-X Fusion-MPT SAS pci:v00001000d00000050sv00001028sd00001F04* ID_MODEL_FROM_DATABASE=SAS1064 PCI-X Fusion-MPT SAS (SAS 5/E) pci:v00001000d00000050sv00001028sd00001F09* ID_MODEL_FROM_DATABASE=SAS1064 PCI-X Fusion-MPT SAS (SAS 5i/R) pci:v00001000d00000052* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3216/3224 [Cutlass] pci:v00001000d00000053* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3216/3224 [Cutlass] pci:v00001000d00000053sv00001000sd00009350* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3216/3224 [Cutlass] (MegaRAID SAS 9341-16i) pci:v00001000d00000053sv00001000sd00009351* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3216/3224 [Cutlass] (MegaRAID SAS 9341-24i) pci:v00001000d00000054* ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS pci:v00001000d00000054sv00001028sd00001F04* ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS 5/E Adapter Controller) pci:v00001000d00000054sv00001028sd00001F05* ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS 5/i Adapter Controller) pci:v00001000d00000054sv00001028sd00001F06* ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS 5/i Integrated Controller) pci:v00001000d00000054sv00001028sd00001F07* ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS 5/iR Integrated RAID Controller) pci:v00001000d00000054sv00001028sd00001F08* ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS 5/iR Integrated RAID Controller) pci:v00001000d00000054sv00001028sd00001F09* ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS 5/iR Adapter RAID Controller) pci:v00001000d00000054sv000015ADsd00001976* ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS Controller) pci:v00001000d00000055* ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS pci:v00001000d00000055sv00001033sd00008336* ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS1068) pci:v00001000d00000056* ID_MODEL_FROM_DATABASE=SAS1064ET PCI-Express Fusion-MPT SAS pci:v00001000d00000056sv00001014sd000003BB* ID_MODEL_FROM_DATABASE=SAS1064ET PCI-Express Fusion-MPT SAS (ServeRAID BR10il SAS/SATA Controller v2) pci:v00001000d00000057* ID_MODEL_FROM_DATABASE=M1064E MegaRAID SAS pci:v00001000d00000057sv00008086sd0000346C* ID_MODEL_FROM_DATABASE=M1064E MegaRAID SAS (Embedded Software RAID Technology II (ESTRII)) pci:v00001000d00000058* ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS pci:v00001000d00000058sv00001000sd00003140* ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS (SAS3081E-R 8-Port SAS/SATA Host Bus Adapter) pci:v00001000d00000058sv00001028sd0000021D* ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS (SAS 6/iR Integrated Workstations RAID Controller) pci:v00001000d00000058sv00001028sd00001F0E* ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS (SAS 6/iR Adapter RAID Controller) pci:v00001000d00000058sv00001028sd00001F0F* ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS (SAS 6/iR Integrated Blades RAID Controller) pci:v00001000d00000058sv00001028sd00001F10* ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS (SAS 6/iR Integrated RAID Controller) pci:v00001000d00000058sv0000103Csd00003229* ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS (SC44Ge Host Bus Adapter) pci:v00001000d00000059* ID_MODEL_FROM_DATABASE=MegaRAID SAS 8208ELP/8208ELP pci:v00001000d0000005A* ID_MODEL_FROM_DATABASE=SAS1066E PCI-Express Fusion-MPT SAS pci:v00001000d0000005B* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] pci:v00001000d0000005Bsv00001000sd00009265* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9265-8i) pci:v00001000d0000005Bsv00001000sd00009266* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9266-8i) pci:v00001000d0000005Bsv00001000sd00009267* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9267-8i) pci:v00001000d0000005Bsv00001000sd00009268* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9265CV-8i / 9270CV-8i) pci:v00001000d0000005Bsv00001000sd00009269* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9266-4i) pci:v00001000d0000005Bsv00001000sd00009270* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9270-8i) pci:v00001000d0000005Bsv00001000sd00009271* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9271-8i) pci:v00001000d0000005Bsv00001000sd00009272* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9272-8i) pci:v00001000d0000005Bsv00001000sd00009273* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9270CV-8i) pci:v00001000d0000005Bsv00001000sd00009274* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9270-4i) pci:v00001000d0000005Bsv00001000sd00009275* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9271-8iCC) pci:v00001000d0000005Bsv00001000sd00009276* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9271-4i) pci:v00001000d0000005Bsv00001000sd00009285* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9285-8e) pci:v00001000d0000005Bsv00001000sd00009288* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9285CV-8e) pci:v00001000d0000005Bsv00001000sd00009290* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9286-8e) pci:v00001000d0000005Bsv00001000sd00009291* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9286CV-8e) pci:v00001000d0000005Bsv00001000sd00009295* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9286CV-8eCC) pci:v00001000d0000005Bsv00001014sd0000040B* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (ServeRAID M5110 SAS/SATA Controller) pci:v00001000d0000005Bsv00001014sd0000040C* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (ServeRAID M5120 SAS/SATA Controller) pci:v00001000d0000005Bsv00001014sd00000412* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (ServeRAID M5110e SAS/SATA Controller) pci:v00001000d0000005Bsv00001028sd00001F2D* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H810 Adapter) pci:v00001000d0000005Bsv00001028sd00001F30* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710 Embedded) pci:v00001000d0000005Bsv00001028sd00001F31* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710P Adapter) pci:v00001000d0000005Bsv00001028sd00001F33* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710P Mini (for blades)) pci:v00001000d0000005Bsv00001028sd00001F34* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710P Mini (for monolithics)) pci:v00001000d0000005Bsv00001028sd00001F35* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710 Adapter) pci:v00001000d0000005Bsv00001028sd00001F37* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710 Mini (for blades)) pci:v00001000d0000005Bsv00001028sd00001F38* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710 Mini (for monolithics)) pci:v00001000d0000005Bsv000015D9sd00000690* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (LSI MegaRAID ROMB) pci:v00001000d0000005Bsv00008086sd00003510* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (RMS25PB080 RAID Controller) pci:v00001000d0000005Bsv00008086sd00003513* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (RMS25CB080 RAID Controller) pci:v00001000d0000005C* ID_MODEL_FROM_DATABASE=SAS1064A PCI-X Fusion-MPT SAS pci:v00001000d0000005D* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] pci:v00001000d0000005Dsv00001000sd00009361* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (MegaRAID SAS 9361-8i) pci:v00001000d0000005Dsv00001028sd00001F41* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H830 Adapter) pci:v00001000d0000005Dsv00001028sd00001F42* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730P Adapter) pci:v00001000d0000005Dsv00001028sd00001F43* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730 Adapter) pci:v00001000d0000005Dsv00001028sd00001F47* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730P Mini) pci:v00001000d0000005Dsv00001028sd00001F48* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730P Mini (for blades)) pci:v00001000d0000005Dsv00001028sd00001F49* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730 Mini) pci:v00001000d0000005Dsv00001028sd00001F4A* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730 Mini (for blades)) pci:v00001000d0000005Dsv00001028sd00001F4D* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC FD33xS) pci:v00001000d0000005Dsv00001028sd00001F4F* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730P Slim) pci:v00001000d0000005Dsv00001028sd00001F54* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC FD33xD) pci:v00001000d0000005Dsv000017AAsd00001052* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (ThinkServer RAID 720i) pci:v00001000d0000005Dsv000017AAsd00001053* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (ThinkServer RAID 720ix) pci:v00001000d0000005E* ID_MODEL_FROM_DATABASE=SAS1066 PCI-X Fusion-MPT SAS pci:v00001000d0000005F* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] pci:v00001000d0000005Fsv00001028sd00001F44* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (PERC H330 Adapter) pci:v00001000d0000005Fsv00001028sd00001F4B* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (PERC H330 Mini) pci:v00001000d0000005Fsv00001028sd00001F4C* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (PERC H330 Mini (for blades)) pci:v00001000d0000005Fsv00001028sd00001F4D* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (PERC H330 Embedded (for monolithic)) pci:v00001000d0000005Fsv00001054sd0000306A* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (SAS 3004 iMR ROMB) pci:v00001000d0000005Fsv00001D49sd000004DB* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (ServeRAID M1210 SAS/SATA Controller) pci:v00001000d00000060* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 pci:v00001000d00000060sv00001000sd00001006* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS 8888ELP) pci:v00001000d00000060sv00001000sd0000100A* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS 8708ELP) pci:v00001000d00000060sv00001000sd0000100E* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS 8884E) pci:v00001000d00000060sv00001000sd0000100F* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS 8708E) pci:v00001000d00000060sv00001000sd00001010* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SATA 350-8ELP) pci:v00001000d00000060sv00001000sd00001011* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SATA 350-4ELP) pci:v00001000d00000060sv00001000sd00001012* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS 8704ELP) pci:v00001000d00000060sv00001000sd00001016* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS 8880EM2) pci:v00001000d00000060sv00001014sd00000363* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) pci:v00001000d00000060sv00001014sd00000364* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (SystemX MegaRAID SAS 8808E) pci:v00001000d00000060sv00001014sd00000365* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (SystemX MegaRAID SAS 8884E) pci:v00001000d00000060sv00001014sd00000379* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (SystemX MegaRAID SAS 8880EM2) pci:v00001000d00000060sv00001028sd00001F0A* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (PERC 6/E Adapter RAID Controller) pci:v00001000d00000060sv00001028sd00001F0B* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (PERC 6/i Adapter RAID Controller) pci:v00001000d00000060sv00001028sd00001F0C* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (PERC 6/i Integrated RAID Controller) pci:v00001000d00000060sv00001028sd00001F0D* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (PERC 6/i Integrated RAID Controller) pci:v00001000d00000060sv00001028sd00001F11* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (CERC 6/i Integrated RAID Controller) pci:v00001000d00000060sv00001033sd0000835A* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) pci:v00001000d00000060sv00001043sd0000824D* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) pci:v00001000d00000060sv00001170sd0000002F* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) pci:v00001000d00000060sv00001170sd00000036* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) pci:v00001000d00000060sv000015D9sd0000C080* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) pci:v00001000d00000060sv000017AAsd00006B7C* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) pci:v00001000d00000060sv000018A1sd00000003* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (LSI MegaRAID SAS PCI Express ROMB) pci:v00001000d00000060sv00008086sd00001006* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (RAID Controller SRCSAS28EP) pci:v00001000d00000060sv00008086sd0000100A* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (RAID Controller SRCSAS28EV) pci:v00001000d00000060sv00008086sd00001010* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (RAID Controller SRCSATA28E) pci:v00001000d00000060sv00008086sd000034CC* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (Integrated RAID Controller SROMBSAS28E) pci:v00001000d00000060sv00008086sd000034CD* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (Integrated RAID Controller SROMBSAS28E) pci:v00001000d00000060sv00008086sd00003505* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (Integrated RAID Controller SROMBSASMP2) pci:v00001000d00000062* ID_MODEL_FROM_DATABASE=SAS1078 PCI-Express Fusion-MPT SAS pci:v00001000d00000062sv00001000sd00000062* ID_MODEL_FROM_DATABASE=SAS1078 PCI-Express Fusion-MPT SAS pci:v00001000d00000064* ID_MODEL_FROM_DATABASE=SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] pci:v00001000d00000065* ID_MODEL_FROM_DATABASE=SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] pci:v00001000d0000006E* ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 pci:v00001000d00000070* ID_MODEL_FROM_DATABASE=SAS2004 PCI-Express Fusion-MPT SAS-2 [Spitfire] pci:v00001000d00000071* ID_MODEL_FROM_DATABASE=MR SAS HBA 2004 pci:v00001000d00000072* ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] pci:v00001000d00000072sv00001028sd00001F1C* ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (6Gbps SAS HBA Adapter) pci:v00001000d00000072sv00001028sd00001F1D* ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (PERC H200 Adapter) pci:v00001000d00000072sv00001028sd00001F1E* ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (PERC H200 Integrated) pci:v00001000d00000072sv00001028sd00001F1F* ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (PERC H200 Modular) pci:v00001000d00000072sv00001028sd00001F20* ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (PERC H200 Embedded) pci:v00001000d00000072sv00001028sd00001F22* ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (Internal Tape Adapter) pci:v00001000d00000072sv00008086sd0000350F* ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (RMS2LL040 RAID Controller) pci:v00001000d00000073* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] pci:v00001000d00000073sv00001000sd00009240* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (MegaRAID SAS 9240-8i) pci:v00001000d00000073sv00001000sd00009241* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (MegaRAID SAS 9240-4i) pci:v00001000d00000073sv00001000sd000092A0* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (MegaRAID SAS 9220-8i) pci:v00001000d00000073sv00001014sd000003B1* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (ServeRAID M1015 SAS/SATA Controller) pci:v00001000d00000073sv00001028sd00001F4E* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Adapter) pci:v00001000d00000073sv00001028sd00001F4F* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Integrated) pci:v00001000d00000073sv00001028sd00001F50* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Mini Blades) pci:v00001000d00000073sv00001028sd00001F51* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Mini Monolithics) pci:v00001000d00000073sv00001028sd00001F52* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Embedded1) pci:v00001000d00000073sv00001028sd00001F53* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Embedded2) pci:v00001000d00000073sv00001028sd00001F54* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Reserved) pci:v00001000d00000073sv00001054sd00003035* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (LSI MegaRAID SAS 9240-8i) pci:v00001000d00000073sv00001137sd00000072* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (2004 iMR ROMB) pci:v00001000d00000073sv00001137sd00000073* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (2008 ROMB) pci:v00001000d00000073sv00001137sd000000B0* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (UCSC RAID SAS 2008M-8i) pci:v00001000d00000073sv00001137sd000000B1* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (UCSC RAID SAS 2008M-8i) pci:v00001000d00000073sv00001137sd000000C2* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (UCS E-Series Double Wide) pci:v00001000d00000073sv00001137sd000000C3* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (UCS E-Series Single Wide) pci:v00001000d00000073sv000015D9sd00000400* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (Supermicro SMC2008-iMR) pci:v00001000d00000073sv00001734sd00001177* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (RAID Ctrl SAS 6G 0/1 (D2607)) pci:v00001000d00000073sv000017AAsd00001051* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (ThinkServer RAID 510i) pci:v00001000d00000073sv00008086sd0000350D* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (RMS2AF040 RAID Controller) pci:v00001000d00000073sv00008086sd00009240* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (RAID Controller RS2WC080) pci:v00001000d00000073sv00008086sd00009241* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (RAID Controller RS2WC040) pci:v00001000d00000074* ID_MODEL_FROM_DATABASE=SAS2108 PCI-Express Fusion-MPT SAS-2 [Liberator] pci:v00001000d00000076* ID_MODEL_FROM_DATABASE=SAS2108 PCI-Express Fusion-MPT SAS-2 [Liberator] pci:v00001000d00000077* ID_MODEL_FROM_DATABASE=SAS2108 PCI-Express Fusion-MPT SAS-2 [Liberator] pci:v00001000d00000079* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] pci:v00001000d00000079sv00001000sd00009251* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260-4ix) pci:v00001000d00000079sv00001000sd00009256* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260-8ix) pci:v00001000d00000079sv00001000sd00009260* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260-4i) pci:v00001000d00000079sv00001000sd00009261* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260-8i) pci:v00001000d00000079sv00001000sd00009262* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9262-8i) pci:v00001000d00000079sv00001000sd00009263* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9261-8i) pci:v00001000d00000079sv00001000sd00009264* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9264-8i) pci:v00001000d00000079sv00001000sd00009267* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260CV-4i) pci:v00001000d00000079sv00001000sd00009268* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260CV-8i) pci:v00001000d00000079sv00001000sd00009275* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9280-8ex) pci:v00001000d00000079sv00001000sd00009276* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MR9260-16i) pci:v00001000d00000079sv00001000sd00009280* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9280-8e) pci:v00001000d00000079sv00001000sd00009281* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9281-8E) pci:v00001000d00000079sv00001000sd00009282* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9280-4i4e) pci:v00001000d00000079sv00001000sd00009290* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9280DE-24i4e) pci:v00001000d00000079sv00001014sd000003B2* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (ServeRAID M5015 SAS/SATA Controller) pci:v00001000d00000079sv00001014sd000003B3* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (ServeRAID M5025 SAS/SATA Controller) pci:v00001000d00000079sv00001028sd00001F15* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PERC H800 Adapter) pci:v00001000d00000079sv00001028sd00001F16* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PERC H700 Adapter) pci:v00001000d00000079sv00001028sd00001F17* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PERC H700 Integrated) pci:v00001000d00000079sv00001028sd00001F18* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PERC H700 Modular) pci:v00001000d00000079sv00001028sd00001F1A* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PERC H800 Proto Adapter) pci:v00001000d00000079sv00001028sd00001F1B* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PERC H700 Integrated) pci:v00001000d00000079sv00001043sd00008480* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PIKE-2108 16PD) pci:v00001000d00000079sv00001734sd00001176* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Ctrl SAS 6G 5/6 512MB (D2616)) pci:v00001000d00000079sv00001734sd00001177* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Ctrl SAS 6G 0/1 (D2607)) pci:v00001000d00000079sv00008086sd00009256* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260DE-8i) pci:v00001000d00000079sv00008086sd00009260* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RS2BL040) pci:v00001000d00000079sv00008086sd00009261* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RS2BL080) pci:v00001000d00000079sv00008086sd00009264* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (Warm Beach (Caster Lite)) pci:v00001000d00000079sv00008086sd00009267* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RS2VB040) pci:v00001000d00000079sv00008086sd00009268* ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RS2VB080) pci:v00001000d0000007C* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078DE pci:v00001000d0000007Csv00001014sd00000395* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078DE (ServeRAID-AR10is SAS/SATA Controller) pci:v00001000d0000007E* ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD pci:v00001000d00000080* ID_MODEL_FROM_DATABASE=SAS2208 PCI-Express Fusion-MPT SAS-2 pci:v00001000d00000081* ID_MODEL_FROM_DATABASE=SAS2208 PCI-Express Fusion-MPT SAS-2 pci:v00001000d00000082* ID_MODEL_FROM_DATABASE=SAS2208 PCI-Express Fusion-MPT SAS-2 pci:v00001000d00000083* ID_MODEL_FROM_DATABASE=SAS2208 PCI-Express Fusion-MPT SAS-2 pci:v00001000d00000084* ID_MODEL_FROM_DATABASE=SAS2208 PCI-Express Fusion-MPT SAS-2 pci:v00001000d00000085* ID_MODEL_FROM_DATABASE=SAS2208 PCI-Express Fusion-MPT SAS-2 pci:v00001000d00000086* ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 pci:v00001000d00000087* ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 pci:v00001000d00000087sv00001590sd00000044* ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (H220i) pci:v00001000d0000008F* ID_MODEL_FROM_DATABASE=53c875J pci:v00001000d0000008Fsv00001092sd00008000* ID_MODEL_FROM_DATABASE=53c875J (FirePort 40 SCSI Controller) pci:v00001000d0000008Fsv00001092sd00008760* ID_MODEL_FROM_DATABASE=53c875J (FirePort 40 Dual SCSI Host Adapter) pci:v00001000d00000090* ID_MODEL_FROM_DATABASE=SAS3108 PCI-Express Fusion-MPT SAS-3 pci:v00001000d00000091* ID_MODEL_FROM_DATABASE=SAS3108 PCI-Express Fusion-MPT SAS-3 pci:v00001000d00000094* ID_MODEL_FROM_DATABASE=SAS3108 PCI-Express Fusion-MPT SAS-3 pci:v00001000d00000095* ID_MODEL_FROM_DATABASE=SAS3108 PCI-Express Fusion-MPT SAS-3 pci:v00001000d00000096* ID_MODEL_FROM_DATABASE=SAS3004 PCI-Express Fusion-MPT SAS-3 pci:v00001000d00000097* ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 pci:v00001000d00000097sv00001028sd00001F45* ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (12GB/s HBA internal) pci:v00001000d00000097sv00001028sd00001F46* ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (12Gbps HBA) pci:v00001000d000000C0* ID_MODEL_FROM_DATABASE=SAS3324 PCI-Express Fusion-MPT SAS-3 pci:v00001000d000000C1* ID_MODEL_FROM_DATABASE=SAS3324 PCI-Express Fusion-MPT SAS-3 pci:v00001000d000000C2* ID_MODEL_FROM_DATABASE=SAS3324 PCI-Express Fusion-MPT SAS-3 pci:v00001000d000000C3* ID_MODEL_FROM_DATABASE=SAS3324 PCI-Express Fusion-MPT SAS-3 pci:v00001000d000000C4* ID_MODEL_FROM_DATABASE=SAS3224 PCI-Express Fusion-MPT SAS-3 pci:v00001000d000000C5* ID_MODEL_FROM_DATABASE=SAS3316 PCI-Express Fusion-MPT SAS-3 pci:v00001000d000000C6* ID_MODEL_FROM_DATABASE=SAS3316 PCI-Express Fusion-MPT SAS-3 pci:v00001000d000000C7* ID_MODEL_FROM_DATABASE=SAS3316 PCI-Express Fusion-MPT SAS-3 pci:v00001000d000000C8* ID_MODEL_FROM_DATABASE=SAS3316 PCI-Express Fusion-MPT SAS-3 pci:v00001000d000000C9* ID_MODEL_FROM_DATABASE=SAS3216 PCI-Express Fusion-MPT SAS-3 pci:v00001000d000000CE* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3316 [Intruder] pci:v00001000d000000CEsv00001000sd00009371* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3316 [Intruder] (MegaRAID SAS 9361-16i) pci:v00001000d000000CEsv00001000sd00009390* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3316 [Intruder] (MegaRAID SAS 9380-8i8e) pci:v00001000d000000CF* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3324 [Intruder] pci:v00001000d000000CFsv00001000sd00009370* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3324 [Intruder] (MegaRAID SAS 9361-24i) pci:v00001000d00000407* ID_MODEL_FROM_DATABASE=MegaRAID pci:v00001000d00000407sv00001000sd00000530* ID_MODEL_FROM_DATABASE=MegaRAID (530 SCSI 320-0X RAID Controller) pci:v00001000d00000407sv00001000sd00000531* ID_MODEL_FROM_DATABASE=MegaRAID (531 SCSI 320-4X RAID Controller) pci:v00001000d00000407sv00001000sd00000532* ID_MODEL_FROM_DATABASE=MegaRAID (532 SCSI 320-2X RAID Controller) pci:v00001000d00000407sv00001028sd00000531* ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge Expandable RAID Controller 4/QC) pci:v00001000d00000407sv00001028sd00000533* ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge Expandable RAID Controller 4/QC) pci:v00001000d00000407sv00008086sd00000530* ID_MODEL_FROM_DATABASE=MegaRAID (Intel RAID Controller SRCZCRX) pci:v00001000d00000407sv00008086sd00000532* ID_MODEL_FROM_DATABASE=MegaRAID (Intel RAID Controller SRCU42X) pci:v00001000d00000408* ID_MODEL_FROM_DATABASE=MegaRAID pci:v00001000d00000408sv00001000sd00000001* ID_MODEL_FROM_DATABASE=MegaRAID (SCSI 320-1E RAID Controller) pci:v00001000d00000408sv00001000sd00000002* ID_MODEL_FROM_DATABASE=MegaRAID (SCSI 320-2E RAID Controller) pci:v00001000d00000408sv00001025sd0000004D* ID_MODEL_FROM_DATABASE=MegaRAID (ACER ROMB-2E RAID Controller) pci:v00001000d00000408sv00001028sd00000001* ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller PERC4e/SC) pci:v00001000d00000408sv00001028sd00000002* ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller PERC4e/DC) pci:v00001000d00000408sv00001028sd00000012* ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller RAC4) pci:v00001000d00000408sv00001028sd00000015* ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller PERC5) pci:v00001000d00000408sv00001028sd00001F03* ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller PERC5) pci:v00001000d00000408sv00001734sd00001065* ID_MODEL_FROM_DATABASE=MegaRAID (FSC MegaRAID PCI Express ROMB) pci:v00001000d00000408sv00008086sd00000002* ID_MODEL_FROM_DATABASE=MegaRAID (Intel RAID Controller SRCU42E) pci:v00001000d00000408sv00008086sd00003449* ID_MODEL_FROM_DATABASE=MegaRAID (Intel RAID Controller SROMBU) pci:v00001000d00000409* ID_MODEL_FROM_DATABASE=MegaRAID pci:v00001000d00000409sv00001000sd00003004* ID_MODEL_FROM_DATABASE=MegaRAID (SATA 300-4X RAID Controller) pci:v00001000d00000409sv00001000sd00003008* ID_MODEL_FROM_DATABASE=MegaRAID (SATA 300-8X RAID Controller) pci:v00001000d00000409sv00008086sd00003008* ID_MODEL_FROM_DATABASE=MegaRAID (RAID Controller SRCS28X) pci:v00001000d00000409sv00008086sd00003431* ID_MODEL_FROM_DATABASE=MegaRAID (RAID Controller Alief SROMBU42E) pci:v00001000d00000409sv00008086sd00003499* ID_MODEL_FROM_DATABASE=MegaRAID (RAID Controller Harwich SROMBU42E) pci:v00001000d00000411* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 pci:v00001000d00000411sv00001000sd00001001* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS 8408E) pci:v00001000d00000411sv00001000sd00001002* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS 8480E) pci:v00001000d00000411sv00001000sd00001003* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS 8344ELP) pci:v00001000d00000411sv00001000sd00001004* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS 8308ELP) pci:v00001000d00000411sv00001000sd00001008* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS 84016E) pci:v00001000d00000411sv00001000sd0000100C* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SATA 300-12E) pci:v00001000d00000411sv00001000sd0000100D* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SATA 300-16E) pci:v00001000d00000411sv00001000sd00002004* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SATA 300-8ELP) pci:v00001000d00000411sv00001000sd00002005* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SATA 300-4ELP) pci:v00001000d00000411sv00001033sd00008287* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS PCI Express ROMB) pci:v00001000d00000411sv00001054sd00003016* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS RoMB Server) pci:v00001000d00000411sv00001734sd00001081* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS PCI Express ROMB) pci:v00001000d00000411sv00001734sd000010A3* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS PCI Express ROMB) pci:v00001000d00000411sv00008086sd00001001* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (RAID Controller SRCSAS18E) pci:v00001000d00000411sv00008086sd00001003* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (RAID Controller SRCSAS144E) pci:v00001000d00000411sv00008086sd00003500* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (SROMBSAS18E RAID Controller) pci:v00001000d00000411sv00008086sd00003501* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (SROMBSAS18E RAID Controller) pci:v00001000d00000411sv00008086sd00003504* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (SROMBSAS18E RAID Controller) pci:v00001000d00000413* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 [Verde ZCR] pci:v00001000d00000413sv00001000sd00001005* ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 [Verde ZCR] (MegaRAID SAS 8300XLP) pci:v00001000d00000621* ID_MODEL_FROM_DATABASE=FC909 Fibre Channel Adapter pci:v00001000d00000622* ID_MODEL_FROM_DATABASE=FC929 Fibre Channel Adapter pci:v00001000d00000622sv00001000sd00001020* ID_MODEL_FROM_DATABASE=FC929 Fibre Channel Adapter (44929 O Dual Fibre Channel card) pci:v00001000d00000623* ID_MODEL_FROM_DATABASE=FC929 LAN pci:v00001000d00000624* ID_MODEL_FROM_DATABASE=FC919 Fibre Channel Adapter pci:v00001000d00000625* ID_MODEL_FROM_DATABASE=FC919 LAN pci:v00001000d00000626* ID_MODEL_FROM_DATABASE=FC929X Fibre Channel Adapter pci:v00001000d00000626sv00001000sd00001010* ID_MODEL_FROM_DATABASE=FC929X Fibre Channel Adapter (7202-XP-LC Dual Fibre Channel card) pci:v00001000d00000627* ID_MODEL_FROM_DATABASE=FC929X LAN pci:v00001000d00000628* ID_MODEL_FROM_DATABASE=FC919X Fibre Channel Adapter pci:v00001000d00000629* ID_MODEL_FROM_DATABASE=FC919X LAN pci:v00001000d00000640* ID_MODEL_FROM_DATABASE=FC949X Fibre Channel Adapter pci:v00001000d00000642* ID_MODEL_FROM_DATABASE=FC939X Fibre Channel Adapter pci:v00001000d00000646* ID_MODEL_FROM_DATABASE=FC949ES Fibre Channel Adapter pci:v00001000d00000701* ID_MODEL_FROM_DATABASE=83C885 NT50 DigitalScape Fast Ethernet pci:v00001000d00000702* ID_MODEL_FROM_DATABASE=Yellowfin G-NIC gigabit ethernet pci:v00001000d00000702sv00001318sd00000000* ID_MODEL_FROM_DATABASE=Yellowfin G-NIC gigabit ethernet (PEI100X) pci:v00001000d00000804* ID_MODEL_FROM_DATABASE=SA2010 pci:v00001000d00000805* ID_MODEL_FROM_DATABASE=SA2010ZC pci:v00001000d00000806* ID_MODEL_FROM_DATABASE=SA2020 pci:v00001000d00000807* ID_MODEL_FROM_DATABASE=SA2020ZC pci:v00001000d00000901* ID_MODEL_FROM_DATABASE=61C102 pci:v00001000d00001000* ID_MODEL_FROM_DATABASE=63C815 pci:v00001000d00001960* ID_MODEL_FROM_DATABASE=MegaRAID pci:v00001000d00001960sv00001000sd00000518* ID_MODEL_FROM_DATABASE=MegaRAID (518 SCSI 320-2 Controller) pci:v00001000d00001960sv00001000sd00000520* ID_MODEL_FROM_DATABASE=MegaRAID (520 SCSI 320-1 Controller) pci:v00001000d00001960sv00001000sd00000522* ID_MODEL_FROM_DATABASE=MegaRAID (522 i4 133 RAID Controller) pci:v00001000d00001960sv00001000sd00000523* ID_MODEL_FROM_DATABASE=MegaRAID (SATA 150-6 RAID Controller) pci:v00001000d00001960sv00001000sd00004523* ID_MODEL_FROM_DATABASE=MegaRAID (SATA 150-4 RAID Controller) pci:v00001000d00001960sv00001000sd0000A520* ID_MODEL_FROM_DATABASE=MegaRAID (ZCR SCSI 320-0 Controller) pci:v00001000d00001960sv00001028sd00000518* ID_MODEL_FROM_DATABASE=MegaRAID (518 DELL PERC 4/DC RAID Controller) pci:v00001000d00001960sv00001028sd00000520* ID_MODEL_FROM_DATABASE=MegaRAID (520 DELL PERC 4/SC RAID Controller) pci:v00001000d00001960sv00001028sd00000531* ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge Expandable RAID Controller 4/QC) pci:v00001000d00001960sv00001028sd00000533* ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge Expandable RAID Controller 4/QC) pci:v00001000d00001960sv00008086sd00000520* ID_MODEL_FROM_DATABASE=MegaRAID (RAID Controller SRCU41L) pci:v00001000d00001960sv00008086sd00000523* ID_MODEL_FROM_DATABASE=MegaRAID (RAID Controller SRCS16) pci:v00001000d00003050* ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 pci:v00001000d00006001* ID_MODEL_FROM_DATABASE=DX1 Multiformat Broadcast HD/SD Encoder/Decoder pci:v00001001* ID_VENDOR_FROM_DATABASE=Kolter Electronic pci:v00001001d00000010* ID_MODEL_FROM_DATABASE=PCI 1616 Measurement card with 32 digital I/O lines pci:v00001001d00000011* ID_MODEL_FROM_DATABASE=OPTO-PCI Opto-Isolated digital I/O board pci:v00001001d00000012* ID_MODEL_FROM_DATABASE=PCI-AD/DA Analogue I/O board pci:v00001001d00000013* ID_MODEL_FROM_DATABASE=PCI-OPTO-RELAIS Digital I/O board with relay outputs pci:v00001001d00000014* ID_MODEL_FROM_DATABASE=PCI-Counter/Timer Counter Timer board pci:v00001001d00000015* ID_MODEL_FROM_DATABASE=PCI-DAC416 Analogue output board pci:v00001001d00000016* ID_MODEL_FROM_DATABASE=PCI-MFB Analogue I/O board pci:v00001001d00000017* ID_MODEL_FROM_DATABASE=PROTO-3 PCI Prototyping board pci:v00001001d00009100* ID_MODEL_FROM_DATABASE=INI-9100/9100W SCSI Host pci:v00001002* ID_VENDOR_FROM_DATABASE=Advanced Micro Devices, Inc. [AMD/ATI] pci:v00001002d00001304* ID_MODEL_FROM_DATABASE=Kaveri pci:v00001002d00001305* ID_MODEL_FROM_DATABASE=Kaveri pci:v00001002d00001306* ID_MODEL_FROM_DATABASE=Kaveri pci:v00001002d00001307* ID_MODEL_FROM_DATABASE=Kaveri pci:v00001002d00001308* ID_MODEL_FROM_DATABASE=Kaveri HDMI/DP Audio Controller pci:v00001002d00001309* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R6/R7 Graphics] pci:v00001002d0000130A* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R6 Graphics] pci:v00001002d0000130B* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R4 Graphics] pci:v00001002d0000130C* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R7 Graphics] pci:v00001002d0000130D* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R6 Graphics] pci:v00001002d0000130E* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R5 Graphics] pci:v00001002d0000130F* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R7 Graphics] pci:v00001002d00001310* ID_MODEL_FROM_DATABASE=Kaveri pci:v00001002d00001311* ID_MODEL_FROM_DATABASE=Kaveri pci:v00001002d00001312* ID_MODEL_FROM_DATABASE=Kaveri pci:v00001002d00001313* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R7 Graphics] pci:v00001002d00001314* ID_MODEL_FROM_DATABASE=Wrestler HDMI Audio pci:v00001002d00001314sv0000174Bsd00001001* ID_MODEL_FROM_DATABASE=Wrestler HDMI Audio (PURE Fusion Mini) pci:v00001002d00001315* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R5 Graphics] pci:v00001002d00001316* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R5 Graphics] pci:v00001002d00001317* ID_MODEL_FROM_DATABASE=Kaveri pci:v00001002d00001318* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R5 Graphics] pci:v00001002d0000131B* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R4 Graphics] pci:v00001002d0000131C* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R7 Graphics] pci:v00001002d0000131D* ID_MODEL_FROM_DATABASE=Kaveri [Radeon R6 Graphics] pci:v00001002d00001714* ID_MODEL_FROM_DATABASE=BeaverCreek HDMI Audio [Radeon HD 6500D and 6400G-6600G series] pci:v00001002d00001714sv0000103Csd0000168B* ID_MODEL_FROM_DATABASE=BeaverCreek HDMI Audio [Radeon HD 6500D and 6400G-6600G series] (ProBook 4535s) pci:v00001002d00003150* ID_MODEL_FROM_DATABASE=RV380/M24 [Mobility Radeon X600] pci:v00001002d00003150sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=RV380/M24 [Mobility Radeon X600] (nx8220) pci:v00001002d00003151* ID_MODEL_FROM_DATABASE=RV380 GL [FireMV 2400] pci:v00001002d00003152* ID_MODEL_FROM_DATABASE=RV370/M22 [Mobility Radeon X300] pci:v00001002d00003154* ID_MODEL_FROM_DATABASE=RV380/M24 GL [Mobility FireGL V3200] pci:v00001002d00003155* ID_MODEL_FROM_DATABASE=RV380 GL [FireMV 2400] pci:v00001002d00003171* ID_MODEL_FROM_DATABASE=RV380 GL [FireMV 2400] (Secondary) pci:v00001002d00003E50* ID_MODEL_FROM_DATABASE=RV380 [Radeon X600] pci:v00001002d00003E54* ID_MODEL_FROM_DATABASE=RV380 GL [FireGL V3200] pci:v00001002d00003E70* ID_MODEL_FROM_DATABASE=RV380 [Radeon X600] (Secondary) pci:v00001002d00004136* ID_MODEL_FROM_DATABASE=RS100 [Mobility IGP 320M] pci:v00001002d00004137* ID_MODEL_FROM_DATABASE=RS200 [Radeon IGP 340] pci:v00001002d00004144* ID_MODEL_FROM_DATABASE=R300 [Radeon 9500] pci:v00001002d00004146* ID_MODEL_FROM_DATABASE=R300 [Radeon 9700 PRO] pci:v00001002d00004147* ID_MODEL_FROM_DATABASE=R300 GL [FireGL Z1] pci:v00001002d00004148* ID_MODEL_FROM_DATABASE=R350 [Radeon 9800/9800 SE] pci:v00001002d00004150* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] pci:v00001002d00004150sv00001002sd00000002* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (R9600 Pro primary (Asus OEM for HP)) pci:v00001002d00004150sv00001002sd00000003* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (R9600 Pro secondary (Asus OEM for HP)) pci:v00001002d00004150sv00001002sd00004722* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (All-in-Wonder 2006 AGP Edition) pci:v00001002d00004150sv00001458sd00004024* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (GV-R96128D) pci:v00001002d00004150sv0000148Csd00002064* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (R96A-C3N) pci:v00001002d00004150sv0000148Csd00002066* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (R96A-C3N) pci:v00001002d00004150sv0000174Bsd00007C19* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Atlantis Radeon 9600 Pro) pci:v00001002d00004150sv0000174Bsd00007C29* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (GC-R9600PRO) pci:v00001002d00004150sv000017EEsd00002002* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Radeon 9600 256Mb Primary) pci:v00001002d00004150sv000018BCsd00000101* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (GC-R9600PRO (Primary)) pci:v00001002d00004151* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600 Series] pci:v00001002d00004151sv00001043sd0000C004* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600 Series] (A9600SE) pci:v00001002d00004151sv0000174Bsd00007C37* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600 Series] (Radeon 9600 SE) pci:v00001002d00004152* ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] pci:v00001002d00004152sv00001002sd00000002* ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (Radeon 9600XT) pci:v00001002d00004152sv00001002sd00004772* ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (All-in-Wonder 9600 XT) pci:v00001002d00004152sv00001043sd0000C002* ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (Radeon 9600 XT TVD) pci:v00001002d00004152sv00001043sd0000C01A* ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (A9600XT/TD) pci:v00001002d00004152sv00001462sd00009510* ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (RX9600XT (MS-8951)) pci:v00001002d00004152sv0000174Bsd00007C29* ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (Radeon 9600XT) pci:v00001002d00004152sv00001787sd00004002* ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (Radeon 9600 XT) pci:v00001002d00004153* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550] pci:v00001002d00004153sv00001043sd0000010C* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550] (A9550GE/TD) pci:v00001002d00004153sv00001462sd0000932C* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550] (RX9550SE-TD128 (MS-8932)) pci:v00001002d00004154* ID_MODEL_FROM_DATABASE=RV350 GL [FireGL T2] pci:v00001002d00004155* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600] pci:v00001002d00004157* ID_MODEL_FROM_DATABASE=RV350 GL [FireGL T2] pci:v00001002d00004158* ID_MODEL_FROM_DATABASE=68800AX [Graphics Ultra Pro PCI] pci:v00001002d00004164* ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO] (Secondary) pci:v00001002d00004165* ID_MODEL_FROM_DATABASE=R300 [Radeon 9700 PRO] (Secondary) pci:v00001002d00004166* ID_MODEL_FROM_DATABASE=R300 [Radeon 9700 PRO] (Secondary) pci:v00001002d00004168* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9800 SE] (Secondary) pci:v00001002d00004170* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) pci:v00001002d00004170sv00001002sd00000003* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (R9600 Pro secondary (Asus OEM for HP)) pci:v00001002d00004170sv00001002sd00004723* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (All-in-Wonder 2006 AGP Edition (Secondary)) pci:v00001002d00004170sv00001458sd00004025* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (GV-R96128D (Secondary)) pci:v00001002d00004170sv0000148Csd00002067* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (R96A-C3N (Secondary)) pci:v00001002d00004170sv0000174Bsd00007C28* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (GC-R9600PRO (Secondary)) pci:v00001002d00004170sv000017EEsd00002003* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (Radeon 9600 256Mb (Secondary)) pci:v00001002d00004170sv000018BCsd00000100* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (GC-R9600PRO (Secondary)) pci:v00001002d00004171* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600] (Secondary) pci:v00001002d00004171sv00001043sd0000C005* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600] (Secondary) (A9600SE (Secondary)) pci:v00001002d00004171sv0000174Bsd00007C36* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600] (Secondary) (Radeon 9600 SE (secondary)) pci:v00001002d00004172* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) pci:v00001002d00004172sv00001002sd00000003* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) (Radeon 9600XT (Secondary)) pci:v00001002d00004172sv00001002sd00004773* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) (All-in-Wonder 9600 XT (Secondary)) pci:v00001002d00004172sv00001043sd0000C003* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) (A9600XT (Secondary)) pci:v00001002d00004172sv00001043sd0000C01B* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) (A9600XT/TD (Secondary)) pci:v00001002d00004172sv0000174Bsd00007C28* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) (Radeon 9600XT (Secondary)) pci:v00001002d00004172sv00001787sd00004003* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) (Radeon 9600 XT (Secondary)) pci:v00001002d00004173* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550] (Secondary) pci:v00001002d00004173sv00001043sd0000010D* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550] (Secondary) (A9550GE/TD (Secondary)) pci:v00001002d00004242* ID_MODEL_FROM_DATABASE=R200 [All-In-Wonder Radeon 8500 DV] pci:v00001002d00004242sv00001002sd000002AA* ID_MODEL_FROM_DATABASE=R200 [All-In-Wonder Radeon 8500 DV] (Radeon 8500 AIW DV Edition) pci:v00001002d00004243* ID_MODEL_FROM_DATABASE=R200 PCI Bridge [All-in-Wonder Radeon 8500DV] pci:v00001002d00004336* ID_MODEL_FROM_DATABASE=RS100 [Radeon IGP 320M] pci:v00001002d00004336sv00001002sd00004336* ID_MODEL_FROM_DATABASE=RS100 [Radeon IGP 320M] (Pavilion ze4300 ATI Radeon Mobility U1 (IGP 320 M)) pci:v00001002d00004336sv0000103Csd00000024* ID_MODEL_FROM_DATABASE=RS100 [Radeon IGP 320M] (Pavilion ze4400 builtin Video) pci:v00001002d00004336sv0000161Fsd00002029* ID_MODEL_FROM_DATABASE=RS100 [Radeon IGP 320M] (eMachines M5312 builtin Video) pci:v00001002d00004337* ID_MODEL_FROM_DATABASE=RS200M [Radeon IGP 330M/340M/345M/350M] pci:v00001002d00004337sv00001014sd0000053A* ID_MODEL_FROM_DATABASE=RS200M [Radeon IGP 330M/340M/345M/350M] (ThinkPad R40e) pci:v00001002d00004337sv0000103Csd00000850* ID_MODEL_FROM_DATABASE=RS200M [Radeon IGP 330M/340M/345M/350M] (Radeon IGP 345M) pci:v00001002d00004341* ID_MODEL_FROM_DATABASE=IXP150 AC'97 Audio Controller pci:v00001002d00004342* ID_MODEL_FROM_DATABASE=IXP200 3COM 3C920B Ethernet Controller pci:v00001002d00004345* ID_MODEL_FROM_DATABASE=EHCI USB Controller pci:v00001002d00004347* ID_MODEL_FROM_DATABASE=OHCI USB Controller #1 pci:v00001002d00004348* ID_MODEL_FROM_DATABASE=OHCI USB Controller #2 pci:v00001002d00004349* ID_MODEL_FROM_DATABASE=Dual Channel Bus Master PCI IDE Controller pci:v00001002d0000434D* ID_MODEL_FROM_DATABASE=IXP AC'97 Modem pci:v00001002d00004353* ID_MODEL_FROM_DATABASE=SMBus pci:v00001002d00004354* ID_MODEL_FROM_DATABASE=215CT [Mach64 CT PCI] pci:v00001002d00004358* ID_MODEL_FROM_DATABASE=210888CX [Mach64 CX] pci:v00001002d00004361* ID_MODEL_FROM_DATABASE=IXP SB300 AC'97 Audio Controller pci:v00001002d00004363* ID_MODEL_FROM_DATABASE=SMBus pci:v00001002d0000436E* ID_MODEL_FROM_DATABASE=436E Serial ATA Controller pci:v00001002d00004370* ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller pci:v00001002d00004370sv00001025sd00000079* ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (Aspire 5024WLMMi) pci:v00001002d00004370sv00001025sd00000091* ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (Aspire 5032WXMi) pci:v00001002d00004370sv0000103Csd00002A05* ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (Pavilion t3030.de Desktop PC) pci:v00001002d00004370sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (MX6125) pci:v00001002d00004370sv0000105Bsd00000C81* ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (Realtek ALC 653) pci:v00001002d00004370sv0000107Bsd00000300* ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (MX6421) pci:v00001002d00004370sv00001462sd00000131* ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (MS-1013 Notebook) pci:v00001002d00004371* ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-PCI Bridge pci:v00001002d00004371sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-PCI Bridge (MX6125) pci:v00001002d00004371sv00001462sd00007217* ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-PCI Bridge (Aspire L250) pci:v00001002d00004372* ID_MODEL_FROM_DATABASE=IXP SB4x0 SMBus Controller pci:v00001002d00004372sv00001025sd00000080* ID_MODEL_FROM_DATABASE=IXP SB4x0 SMBus Controller (Aspire 5024WLMMi) pci:v00001002d00004372sv0000103Csd00002A20* ID_MODEL_FROM_DATABASE=IXP SB4x0 SMBus Controller (Pavilion t3030.de Desktop PC) pci:v00001002d00004372sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=IXP SB4x0 SMBus Controller (MX6125) pci:v00001002d00004372sv00001462sd00000131* ID_MODEL_FROM_DATABASE=IXP SB4x0 SMBus Controller (MS-1013 Notebook) pci:v00001002d00004372sv00001462sd00007217* ID_MODEL_FROM_DATABASE=IXP SB4x0 SMBus Controller (Aspire L250) pci:v00001002d00004373* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB2 Host Controller pci:v00001002d00004373sv00001025sd00000080* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB2 Host Controller (Aspire 5024WLMMi) pci:v00001002d00004373sv0000103Csd00002A20* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB2 Host Controller (Pavilion t3030.de Desktop PC) pci:v00001002d00004373sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB2 Host Controller (MX6125) pci:v00001002d00004373sv00001462sd00007217* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB2 Host Controller (Aspire L250) pci:v00001002d00004374* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller pci:v00001002d00004374sv0000103Csd00002A20* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (Pavilion t3030.de Desktop PC) pci:v00001002d00004374sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (MX6125) pci:v00001002d00004374sv00001462sd00007217* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (Aspire L250) pci:v00001002d00004375* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller pci:v00001002d00004375sv00001025sd00000080* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (Aspire 5024WLMMi) pci:v00001002d00004375sv0000103Csd00002A20* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (Pavilion t3030.de Desktop PC) pci:v00001002d00004375sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (MX6125) pci:v00001002d00004375sv00001462sd00007217* ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (Aspire L250) pci:v00001002d00004376* ID_MODEL_FROM_DATABASE=IXP SB4x0 IDE Controller pci:v00001002d00004376sv00001025sd00000080* ID_MODEL_FROM_DATABASE=IXP SB4x0 IDE Controller (Aspire 5024WLMMi) pci:v00001002d00004376sv0000103Csd00002A20* ID_MODEL_FROM_DATABASE=IXP SB4x0 IDE Controller (Pavilion t3030.de Desktop PC) pci:v00001002d00004376sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=IXP SB4x0 IDE Controller (MX6125) pci:v00001002d00004376sv00001462sd00000131* ID_MODEL_FROM_DATABASE=IXP SB4x0 IDE Controller (MS-1013 Notebook) pci:v00001002d00004376sv00001462sd00007217* ID_MODEL_FROM_DATABASE=IXP SB4x0 IDE Controller (Aspire L250) pci:v00001002d00004377* ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-ISA Bridge pci:v00001002d00004377sv00001025sd00000080* ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-ISA Bridge (Aspire 5024WLMi) pci:v00001002d00004377sv0000103Csd00002A20* ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-ISA Bridge (Pavilion t3030.de Desktop PC) pci:v00001002d00004377sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-ISA Bridge (MX6125) pci:v00001002d00004377sv00001462sd00007217* ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-ISA Bridge (Aspire L250) pci:v00001002d00004378* ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Modem Controller pci:v00001002d00004378sv00001025sd00000080* ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Modem Controller (Aspire 5024WLMMi) pci:v00001002d00004378sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Modem Controller (MX6125) pci:v00001002d00004378sv00001462sd00000131* ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Modem Controller (MS-1013 Notebook) pci:v00001002d00004379* ID_MODEL_FROM_DATABASE=IXP SB4x0 Serial ATA Controller pci:v00001002d00004379sv00001462sd00007141* ID_MODEL_FROM_DATABASE=IXP SB4x0 Serial ATA Controller (Aspire L250) pci:v00001002d0000437A* ID_MODEL_FROM_DATABASE=IXP SB400 Serial ATA Controller pci:v00001002d0000437Asv00001002sd00004379* ID_MODEL_FROM_DATABASE=IXP SB400 Serial ATA Controller (4379 Serial ATA Controller) pci:v00001002d0000437Asv00001002sd0000437A* ID_MODEL_FROM_DATABASE=IXP SB400 Serial ATA Controller (437A Serial ATA Controller) pci:v00001002d0000437Asv00001462sd00007141* ID_MODEL_FROM_DATABASE=IXP SB400 Serial ATA Controller (Aspire L250) pci:v00001002d0000437Asv000014F1sd00008800* ID_MODEL_FROM_DATABASE=IXP SB400 Serial ATA Controller (Leadtek WinFast TV2000XP Expert) pci:v00001002d0000437B* ID_MODEL_FROM_DATABASE=IXP SB4x0 High Definition Audio Controller pci:v00001002d0000437Bsv00001002sd0000437B* ID_MODEL_FROM_DATABASE=IXP SB4x0 High Definition Audio Controller pci:v00001002d0000437Bsv000010CFsd00001326* ID_MODEL_FROM_DATABASE=IXP SB4x0 High Definition Audio Controller (Fujitsu Lifebook A3040) pci:v00001002d0000437Bsv00001734sd000010B8* ID_MODEL_FROM_DATABASE=IXP SB4x0 High Definition Audio Controller (Realtek High Definition Audio) pci:v00001002d00004380* ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA pci:v00001002d00004380sv0000103Csd00002813* ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA (DC5750 Microtower) pci:v00001002d00004380sv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA (Satellite P305D-S8995E) pci:v00001002d00004380sv00001458sd0000B003* ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA (GA-MA790FX-DS5 (rev. 1.0)) pci:v00001002d00004380sv00001458sd0000B005* ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA (Gigabyte GA-MA69G-S3H Motherboard) pci:v00001002d00004380sv00001462sd00007327* ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA (K9AG Neo2) pci:v00001002d00004380sv000017F2sd00005999* ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA (KI690-AM2 Motherboard) pci:v00001002d00004381* ID_MODEL_FROM_DATABASE=SB600 SATA Controller (RAID 5 mode) pci:v00001002d00004382* ID_MODEL_FROM_DATABASE=SB600 AC97 Audio pci:v00001002d00004383* ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) pci:v00001002d00004383sv00001019sd00002120* ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (A785GM-M) pci:v00001002d00004383sv0000103Csd00001611* ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (Pavilion DM1Z-3000) pci:v00001002d00004383sv0000103Csd0000280A* ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (DC5750 Microtower) pci:v00001002d00004383sv00001043sd00008230* ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (M3A78-EH Motherboard) pci:v00001002d00004383sv00001043sd0000836C* ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (M4A785TD Motherboard) pci:v00001002d00004383sv00001043sd00008410* ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (M4A89GTD PRO/USB3 Motherboard) pci:v00001002d00004383sv00001043sd0000841B* ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (M5A88-V EVO) pci:v00001002d00004383sv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (Satellite P305D-S8995E) pci:v00001002d00004383sv00001458sd0000A022* ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (GA-MA770-DS3rev2.0 Motherboard) pci:v00001002d00004383sv000017F2sd00005000* ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (KI690-AM2 Motherboard) pci:v00001002d00004384* ID_MODEL_FROM_DATABASE=SBx00 PCI to PCI Bridge pci:v00001002d00004385* ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller pci:v00001002d00004385sv00001019sd00002120* ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (A785GM-M) pci:v00001002d00004385sv0000103Csd00001611* ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (Pavilion DM1Z-3000) pci:v00001002d00004385sv0000103Csd0000280A* ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (DC5750 Microtower) pci:v00001002d00004385sv00001043sd000082EF* ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (M3A78-EH Motherboard) pci:v00001002d00004385sv00001043sd00008389* ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (M4A785TD Motherboard) pci:v00001002d00004385sv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (Satellite P305D-S8995E) pci:v00001002d00004385sv00001458sd00004385* ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (GA-MA770-DS3rev2.0 Motherboard) pci:v00001002d00004385sv00001462sd00007368* ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (K9AG Neo2) pci:v00001002d00004385sv000015D9sd0000A811* ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (H8DGU) pci:v00001002d00004385sv0000174Bsd00001001* ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (PURE Fusion Mini) pci:v00001002d00004385sv000017F2sd00005000* ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (KI690-AM2 Motherboard) pci:v00001002d00004386* ID_MODEL_FROM_DATABASE=SB600 USB Controller (EHCI) pci:v00001002d00004386sv0000103Csd0000280A* ID_MODEL_FROM_DATABASE=SB600 USB Controller (EHCI) (DC5750 Microtower) pci:v00001002d00004386sv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=SB600 USB Controller (EHCI) (Satellite P305D-S8995E) pci:v00001002d00004386sv00001462sd00007368* ID_MODEL_FROM_DATABASE=SB600 USB Controller (EHCI) (K9AG Neo2) pci:v00001002d00004386sv000017F2sd00005000* ID_MODEL_FROM_DATABASE=SB600 USB Controller (EHCI) (KI690-AM2 Motherboard) pci:v00001002d00004387* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI0) pci:v00001002d00004387sv0000103Csd0000280A* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI0) (DC5750 Microtower) pci:v00001002d00004387sv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI0) (Satellite P305D-S8995E) pci:v00001002d00004387sv00001462sd00007368* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI0) (K9AG Neo2) pci:v00001002d00004387sv000017F2sd00005000* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI0) (KI690-AM2 Motherboard) pci:v00001002d00004388* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI1) pci:v00001002d00004388sv0000103Csd0000280A* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI1) (DC5750 Microtower) pci:v00001002d00004388sv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI1) (Satellite P305D-S8995E) pci:v00001002d00004388sv00001462sd00007368* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI1) (K9AG Neo2) pci:v00001002d00004388sv000017F2sd00005000* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI1) (KI690-AM2 Motherboard) pci:v00001002d00004389* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI2) pci:v00001002d00004389sv0000103Csd0000280A* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI2) (DC5750 Microtower) pci:v00001002d00004389sv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI2) (Satellite P305D-S8995E) pci:v00001002d00004389sv00001462sd00007368* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI2) (K9AG Neo2) pci:v00001002d00004389sv000017F2sd00005000* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI2) (KI690-AM2 Motherboard) pci:v00001002d0000438A* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI3) pci:v00001002d0000438Asv0000103Csd0000280A* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI3) (DC5750 Microtower) pci:v00001002d0000438Asv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI3) (Satellite P305D-S8995E) pci:v00001002d0000438Asv00001462sd00007368* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI3) (K9AG Neo2) pci:v00001002d0000438Asv000017F2sd00005000* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI3) (KI690-AM2 Motherboard) pci:v00001002d0000438B* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI4) pci:v00001002d0000438Bsv0000103Csd0000280A* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI4) (DC5750 Microtower) pci:v00001002d0000438Bsv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI4) (Satellite P305D-S8995E) pci:v00001002d0000438Bsv00001462sd00007368* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI4) (K9AG Neo2) pci:v00001002d0000438Bsv000017F2sd00005000* ID_MODEL_FROM_DATABASE=SB600 USB (OHCI4) (KI690-AM2 Motherboard) pci:v00001002d0000438C* ID_MODEL_FROM_DATABASE=SB600 IDE pci:v00001002d0000438Csv0000103Csd0000280A* ID_MODEL_FROM_DATABASE=SB600 IDE (DC5750 Microtower) pci:v00001002d0000438Csv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=SB600 IDE (Satellite P305D-S8995E) pci:v00001002d0000438Csv00001458sd00005002* ID_MODEL_FROM_DATABASE=SB600 IDE (Gigabyte GA-MA69G-S3H Motherboard) pci:v00001002d0000438Csv00001462sd00007368* ID_MODEL_FROM_DATABASE=SB600 IDE (K9AG Neo2) pci:v00001002d0000438Csv000017F2sd00005000* ID_MODEL_FROM_DATABASE=SB600 IDE (KI690-AM2 Motherboard) pci:v00001002d0000438D* ID_MODEL_FROM_DATABASE=SB600 PCI to LPC Bridge pci:v00001002d0000438Dsv0000103Csd0000280A* ID_MODEL_FROM_DATABASE=SB600 PCI to LPC Bridge (DC5750 Microtower) pci:v00001002d0000438Dsv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=SB600 PCI to LPC Bridge (Satellite P305D-S8995E) pci:v00001002d0000438Dsv00001462sd00007368* ID_MODEL_FROM_DATABASE=SB600 PCI to LPC Bridge (K9AG Neo2) pci:v00001002d0000438Dsv000017F2sd00005000* ID_MODEL_FROM_DATABASE=SB600 PCI to LPC Bridge (KI690-AM2 Motherboard) pci:v00001002d0000438E* ID_MODEL_FROM_DATABASE=SB600 AC97 Modem pci:v00001002d00004390* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] pci:v00001002d00004390sv00001043sd000082EF* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] (M3A78-EH Motherboard) pci:v00001002d00004390sv00001043sd00008389* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] (M4A785TD Motherboard) pci:v00001002d00004390sv00001458sd0000B002* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] (GA-MA770-DS3rev2.0 Motherboard) pci:v00001002d00004390sv00001849sd00004390* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] (Motherboard (one of many)) pci:v00001002d00004391* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] pci:v00001002d00004391sv0000103Csd00001611* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] (Pavilion DM1Z-3000) pci:v00001002d00004391sv00001043sd000082EF* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] (M3A78-EH Motherboard) pci:v00001002d00004391sv00001043sd00008443* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] (M5A88-V EVO) pci:v00001002d00004391sv0000174Bsd00001001* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] (PURE Fusion Mini) pci:v00001002d00004392* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [Non-RAID5 mode] pci:v00001002d00004393* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [RAID5 mode] pci:v00001002d00004394* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] pci:v00001002d00004395* ID_MODEL_FROM_DATABASE=SB8x0/SB9x0 SATA Controller [Storage mode] pci:v00001002d00004396* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller pci:v00001002d00004396sv00001019sd00002120* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (A785GM-M) pci:v00001002d00004396sv0000103Csd00001611* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (Pavilion DM1Z-3000) pci:v00001002d00004396sv00001043sd000082EF* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (M3A78-EH Motherboard) pci:v00001002d00004396sv00001043sd00008443* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (M5A88-V EVO) pci:v00001002d00004396sv000015D9sd0000A811* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (H8DGU) pci:v00001002d00004396sv0000174Bsd00001001* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (PURE Fusion Mini) pci:v00001002d00004397* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller pci:v00001002d00004397sv00001019sd00002120* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (A785GM-M) pci:v00001002d00004397sv0000103Csd00001611* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (Pavilion DM1Z-3000) pci:v00001002d00004397sv00001043sd000082EF* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (M3A78-EH Motherboard) pci:v00001002d00004397sv00001043sd00008443* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (M5A88-V EVO) pci:v00001002d00004397sv000015D9sd0000A811* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (H8DGU) pci:v00001002d00004397sv0000174Bsd00001001* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (PURE Fusion Mini) pci:v00001002d00004398* ID_MODEL_FROM_DATABASE=SB7x0 USB OHCI1 Controller pci:v00001002d00004398sv00001019sd00002120* ID_MODEL_FROM_DATABASE=SB7x0 USB OHCI1 Controller (A785GM-M) pci:v00001002d00004398sv00001043sd000082EF* ID_MODEL_FROM_DATABASE=SB7x0 USB OHCI1 Controller (M3A78-EH Motherboard) pci:v00001002d00004398sv000015D9sd0000A811* ID_MODEL_FROM_DATABASE=SB7x0 USB OHCI1 Controller (H8DGU) pci:v00001002d00004399* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller pci:v00001002d00004399sv00001019sd00002120* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller (A785GM-M) pci:v00001002d00004399sv00001043sd000082EF* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller (M3A78-EH Motherboard) pci:v00001002d00004399sv00001043sd00008443* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller (M5A88-V EVO) pci:v00001002d00004399sv0000174Bsd00001001* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller (PURE Fusion Mini) pci:v00001002d0000439C* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 IDE Controller pci:v00001002d0000439Csv00001019sd00002120* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 IDE Controller (A785GM-M) pci:v00001002d0000439Csv00001043sd000082EF* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 IDE Controller (M3A78-EH Motherboard) pci:v00001002d0000439D* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller pci:v00001002d0000439Dsv00001019sd00002120* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (A785GM-M) pci:v00001002d0000439Dsv0000103Csd00001611* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (Pavilion DM1Z-3000) pci:v00001002d0000439Dsv00001043sd000082EF* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (M3A78-EH Motherboard) pci:v00001002d0000439Dsv00001043sd00008443* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (M5A88-V EVO) pci:v00001002d0000439Dsv0000174Bsd00001001* ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (PURE Fusion Mini) pci:v00001002d000043A0* ID_MODEL_FROM_DATABASE=SB700/SB800/SB900 PCI to PCI bridge (PCIE port 0) pci:v00001002d000043A1* ID_MODEL_FROM_DATABASE=SB700/SB800/SB900 PCI to PCI bridge (PCIE port 1) pci:v00001002d000043A2* ID_MODEL_FROM_DATABASE=SB900 PCI to PCI bridge (PCIE port 2) pci:v00001002d000043A3* ID_MODEL_FROM_DATABASE=SB900 PCI to PCI bridge (PCIE port 3) pci:v00001002d00004437* ID_MODEL_FROM_DATABASE=RS250 [Mobility Radeon 7000 IGP] pci:v00001002d00004554* ID_MODEL_FROM_DATABASE=210888ET [Mach64 ET] pci:v00001002d00004654* ID_MODEL_FROM_DATABASE=Mach64 VT pci:v00001002d00004742* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X pci:v00001002d00004742sv00001002sd00000040* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X) pci:v00001002d00004742sv00001002sd00000044* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X) pci:v00001002d00004742sv00001002sd00000061* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro AIW AGP 2X) pci:v00001002d00004742sv00001002sd00000062* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro AIW AGP 2X) pci:v00001002d00004742sv00001002sd00000063* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro AIW AGP 2X) pci:v00001002d00004742sv00001002sd00000080* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X) pci:v00001002d00004742sv00001002sd00000084* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X) pci:v00001002d00004742sv00001002sd00004742* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X) pci:v00001002d00004742sv00001002sd00008001* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X) pci:v00001002d00004742sv00001028sd00000082* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X) pci:v00001002d00004742sv00001028sd00004082* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Optiplex GX1 Onboard Display Adapter) pci:v00001002d00004742sv00001028sd00008082* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X) pci:v00001002d00004742sv00001028sd0000C082* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X) pci:v00001002d00004742sv00008086sd00004152* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Xpert 98D AGP 2X) pci:v00001002d00004742sv00008086sd0000464A* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X) pci:v00001002d00004744* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 1X pci:v00001002d00004744sv00001002sd00004744* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 1X (Rage Pro Turbo AGP) pci:v00001002d00004744sv00008086sd00004D55* ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 1X (Rage 3D Pro AGP 1X [Intel MU440EX]) pci:v00001002d00004749* ID_MODEL_FROM_DATABASE=3D Rage PRO PCI pci:v00001002d00004749sv00001002sd00000061* ID_MODEL_FROM_DATABASE=3D Rage PRO PCI (Rage Pro AIW) pci:v00001002d00004749sv00001002sd00000062* ID_MODEL_FROM_DATABASE=3D Rage PRO PCI (Rage Pro AIW) pci:v00001002d0000474D* ID_MODEL_FROM_DATABASE=Rage XL AGP 2X pci:v00001002d0000474Dsv00001002sd00000004* ID_MODEL_FROM_DATABASE=Rage XL AGP 2X (Xpert 98 RXL AGP 2X) pci:v00001002d0000474Dsv00001002sd00000008* ID_MODEL_FROM_DATABASE=Rage XL AGP 2X (Xpert 98 RXL AGP 2X) pci:v00001002d0000474Dsv00001002sd00000080* ID_MODEL_FROM_DATABASE=Rage XL AGP 2X pci:v00001002d0000474Dsv00001002sd00000084* ID_MODEL_FROM_DATABASE=Rage XL AGP 2X (Xpert 98 AGP 2X) pci:v00001002d0000474Dsv00001002sd0000474D* ID_MODEL_FROM_DATABASE=Rage XL AGP 2X (Rage XL AGP) pci:v00001002d0000474Dsv00001033sd0000806A* ID_MODEL_FROM_DATABASE=Rage XL AGP 2X (Rage XL AGP) pci:v00001002d0000474E* ID_MODEL_FROM_DATABASE=Rage XC AGP pci:v00001002d0000474Esv00001002sd0000474E* ID_MODEL_FROM_DATABASE=Rage XC AGP pci:v00001002d0000474F* ID_MODEL_FROM_DATABASE=Rage XL pci:v00001002d0000474Fsv00001002sd00000008* ID_MODEL_FROM_DATABASE=Rage XL pci:v00001002d0000474Fsv00001002sd0000474F* ID_MODEL_FROM_DATABASE=Rage XL pci:v00001002d00004750* ID_MODEL_FROM_DATABASE=3D Rage Pro PCI pci:v00001002d00004750sv00001002sd00000040* ID_MODEL_FROM_DATABASE=3D Rage Pro PCI (Rage Pro Turbo) pci:v00001002d00004750sv00001002sd00000044* ID_MODEL_FROM_DATABASE=3D Rage Pro PCI (Rage Pro Turbo) pci:v00001002d00004750sv00001002sd00000080* ID_MODEL_FROM_DATABASE=3D Rage Pro PCI (Rage Pro Turbo) pci:v00001002d00004750sv00001002sd00000084* ID_MODEL_FROM_DATABASE=3D Rage Pro PCI (Rage Pro Turbo) pci:v00001002d00004750sv00001002sd00004750* ID_MODEL_FROM_DATABASE=3D Rage Pro PCI (Rage Pro Turbo) pci:v00001002d00004752* ID_MODEL_FROM_DATABASE=Rage XL PCI pci:v00001002d00004752sv00000E11sd0000001E* ID_MODEL_FROM_DATABASE=Rage XL PCI (Proliant Rage XL) pci:v00001002d00004752sv00001002sd00000008* ID_MODEL_FROM_DATABASE=Rage XL PCI (Rage XL) pci:v00001002d00004752sv00001002sd00004752* ID_MODEL_FROM_DATABASE=Rage XL PCI (Proliant Rage XL) pci:v00001002d00004752sv00001002sd00008008* ID_MODEL_FROM_DATABASE=Rage XL PCI (Rage XL) pci:v00001002d00004752sv00001014sd00000240* ID_MODEL_FROM_DATABASE=Rage XL PCI (eServer xSeries server mainboard) pci:v00001002d00004752sv00001028sd000000CE* ID_MODEL_FROM_DATABASE=Rage XL PCI (PowerEdge 1400) pci:v00001002d00004752sv00001028sd000000D1* ID_MODEL_FROM_DATABASE=Rage XL PCI (PowerEdge 2550) pci:v00001002d00004752sv00001028sd000000D9* ID_MODEL_FROM_DATABASE=Rage XL PCI (PowerEdge 2500) pci:v00001002d00004752sv00001028sd00000134* ID_MODEL_FROM_DATABASE=Rage XL PCI (PowerEdge 600SC) pci:v00001002d00004752sv00001028sd0000014A* ID_MODEL_FROM_DATABASE=Rage XL PCI (PowerEdge 1750) pci:v00001002d00004752sv00001028sd00000165* ID_MODEL_FROM_DATABASE=Rage XL PCI (PowerEdge 750) pci:v00001002d00004752sv0000103Csd000010E1* ID_MODEL_FROM_DATABASE=Rage XL PCI (NetServer Rage XL) pci:v00001002d00004752sv0000103Csd00003208* ID_MODEL_FROM_DATABASE=Rage XL PCI (ProLiant DL140 G2) pci:v00001002d00004752sv0000107Bsd00006400* ID_MODEL_FROM_DATABASE=Rage XL PCI (6400 Server) pci:v00001002d00004752sv00001734sd0000007A* ID_MODEL_FROM_DATABASE=Rage XL PCI (PRIMERGY RX/TX series onboard VGA) pci:v00001002d00004752sv00001734sd00001073* ID_MODEL_FROM_DATABASE=Rage XL PCI (Primergy Econel 200 D2020 mainboard) pci:v00001002d00004752sv00008086sd00003411* ID_MODEL_FROM_DATABASE=Rage XL PCI (SDS2 Mainboard) pci:v00001002d00004752sv00008086sd00003427* ID_MODEL_FROM_DATABASE=Rage XL PCI (S875WP1-E mainboard) pci:v00001002d00004752sv00008086sd00005744* ID_MODEL_FROM_DATABASE=Rage XL PCI (S845WD1-E mainboard) pci:v00001002d00004753* ID_MODEL_FROM_DATABASE=Rage XC pci:v00001002d00004753sv00001002sd00004753* ID_MODEL_FROM_DATABASE=Rage XC pci:v00001002d00004754* ID_MODEL_FROM_DATABASE=3D Rage II/II+ PCI [Mach64 GT] pci:v00001002d00004755* ID_MODEL_FROM_DATABASE=Mach64 GTB [3D Rage II+ DVD] pci:v00001002d00004756* ID_MODEL_FROM_DATABASE=3D Rage IIC PCI [Mach64 GT IIC] pci:v00001002d00004756sv00001002sd00004756* ID_MODEL_FROM_DATABASE=3D Rage IIC PCI [Mach64 GT IIC] (Rage IIC) pci:v00001002d00004757* ID_MODEL_FROM_DATABASE=3D Rage IIC AGP pci:v00001002d00004757sv00001002sd00004757* ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage IIC AGP) pci:v00001002d00004757sv00001028sd00000089* ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage 3D IIC) pci:v00001002d00004757sv00001028sd0000008E* ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (PowerEdge 1300 onboard video) pci:v00001002d00004757sv00001028sd00004082* ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage 3D IIC) pci:v00001002d00004757sv00001028sd00008082* ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage 3D IIC) pci:v00001002d00004757sv00001028sd0000C082* ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage 3D IIC) pci:v00001002d00004758* ID_MODEL_FROM_DATABASE=210888GX [Mach64 GX PCI] pci:v00001002d00004759* ID_MODEL_FROM_DATABASE=3D Rage IIC PCI pci:v00001002d0000475A* ID_MODEL_FROM_DATABASE=3D Rage IIC AGP pci:v00001002d0000475Asv00001002sd00000084* ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage 3D Pro AGP 2x XPERT 98) pci:v00001002d0000475Asv00001002sd00000087* ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage 3D IIC) pci:v00001002d0000475Asv00001002sd0000475A* ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage IIC AGP) pci:v00001002d00004966* ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] pci:v00001002d00004966sv000010F1sd00000002* ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [Tachyon G9000 PRO]) pci:v00001002d00004966sv0000148Csd00002039* ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [Radeon 9000 Pro "Evil Commando"]) pci:v00001002d00004966sv00001509sd00009A00* ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [Radeon 9000 "AT009"]) pci:v00001002d00004966sv00001681sd00000040* ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [3D prophet 9000]) pci:v00001002d00004966sv0000174Bsd00007176* ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (Radeon 9000 Pro) pci:v00001002d00004966sv0000174Bsd00007192* ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [Radeon 9000 "Atlantis"]) pci:v00001002d00004966sv000017AFsd00002005* ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [Excalibur Radeon 9000 Pro]) pci:v00001002d00004966sv000017AFsd00002006* ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [Excalibur Radeon 9000]) pci:v00001002d0000496E* ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000] (Secondary) pci:v00001002d00004A49* ID_MODEL_FROM_DATABASE=R420 [Radeon X800 PRO/GTO AGP] pci:v00001002d00004A49sv0000174Bsd00002620* ID_MODEL_FROM_DATABASE=R420 [Radeon X800 PRO/GTO AGP] (R420 [Radeon X800 GTO AGP]) pci:v00001002d00004A4A* ID_MODEL_FROM_DATABASE=R420 [Radeon X800 GT AGP] pci:v00001002d00004A4B* ID_MODEL_FROM_DATABASE=R420 [Radeon X800 AGP Series] pci:v00001002d00004A4D* ID_MODEL_FROM_DATABASE=R420 GL [FireGL X3-256] pci:v00001002d00004A4E* ID_MODEL_FROM_DATABASE=RV420/M18 [Mobility Radeon 9800] pci:v00001002d00004A4F* ID_MODEL_FROM_DATABASE=R420 [Radeon X850 AGP] pci:v00001002d00004A50* ID_MODEL_FROM_DATABASE=R420 [Radeon X800 XT Platinum Edition AGP] pci:v00001002d00004A54* ID_MODEL_FROM_DATABASE=R420 [Radeon X800 VE AGP] pci:v00001002d00004A54sv00001002sd00004422* ID_MODEL_FROM_DATABASE=R420 [Radeon X800 VE AGP] (All-In-Wonder X800 VE AGP) pci:v00001002d00004A69* ID_MODEL_FROM_DATABASE=R420 [Radeon X800 PRO/GTO] (Secondary) pci:v00001002d00004A6A* ID_MODEL_FROM_DATABASE=R420 [Radeon X800] (Secondary) pci:v00001002d00004A6B* ID_MODEL_FROM_DATABASE=R420 [Radeon X800 XT AGP] (Secondary) pci:v00001002d00004A70* ID_MODEL_FROM_DATABASE=R420 [Radeon X800 XT Platinum Edition AGP] (Secondary) pci:v00001002d00004A74* ID_MODEL_FROM_DATABASE=R420 [Radeon X800 VE] (Secondary) pci:v00001002d00004B49* ID_MODEL_FROM_DATABASE=R481 [Radeon X850 XT AGP] pci:v00001002d00004B4B* ID_MODEL_FROM_DATABASE=R481 [Radeon X850 PRO AGP] pci:v00001002d00004B4C* ID_MODEL_FROM_DATABASE=R481 [Radeon X850 XT Platinum Edition AGP] pci:v00001002d00004B69* ID_MODEL_FROM_DATABASE=R481 [Radeon X850 XT AGP] (Secondary) pci:v00001002d00004B6B* ID_MODEL_FROM_DATABASE=R481 [Radeon X850 PRO AGP] (Secondary) pci:v00001002d00004B6C* ID_MODEL_FROM_DATABASE=R481 [Radeon X850 XT Platinum Edition AGP] (Secondary) pci:v00001002d00004C42* ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X pci:v00001002d00004C42sv00000E11sd0000B0E7* ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage LT Pro (Compaq Presario 5240)) pci:v00001002d00004C42sv00000E11sd0000B0E8* ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage 3D LT Pro) pci:v00001002d00004C42sv00000E11sd0000B10E* ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (3D Rage LT Pro (Compaq Armada 1750)) pci:v00001002d00004C42sv00001002sd00000040* ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage LT Pro AGP 2X) pci:v00001002d00004C42sv00001002sd00000044* ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage LT Pro AGP 2X) pci:v00001002d00004C42sv00001002sd00004C42* ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage LT Pro AGP 2X) pci:v00001002d00004C42sv00001002sd00008001* ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage LT Pro AGP 2X) pci:v00001002d00004C42sv00001028sd00000085* ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage 3D LT Pro) pci:v00001002d00004C46* ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 2X/Mobility M3 pci:v00001002d00004C46sv00001002sd00000155* ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 2X/Mobility M3 (IBM Thinkpad A22p) pci:v00001002d00004C46sv00001014sd00000155* ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 2X/Mobility M3 (IBM Thinkpad A22p) pci:v00001002d00004C46sv00001028sd000000B1* ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 2X/Mobility M3 (Latitude C600) pci:v00001002d00004C47* ID_MODEL_FROM_DATABASE=3D Rage IIC PCI / Mobility Radeon 7500/7500C pci:v00001002d00004C49* ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI pci:v00001002d00004C49sv00001002sd00000004* ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI (Rage LT Pro) pci:v00001002d00004C49sv00001002sd00000040* ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI (Rage LT Pro) pci:v00001002d00004C49sv00001002sd00000044* ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI (Rage LT Pro) pci:v00001002d00004C49sv00001002sd00004C49* ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI (Rage LT Pro) pci:v00001002d00004C4D* ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series pci:v00001002d00004C4Dsv00000E11sd0000B111* ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (Armada M700) pci:v00001002d00004C4Dsv00000E11sd0000B160* ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (Armada E500) pci:v00001002d00004C4Dsv00001002sd00000084* ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (Xpert 98 AGP 2X (Mobility)) pci:v00001002d00004C4Dsv00001014sd00000154* ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (ThinkPad A20m/A21m) pci:v00001002d00004C4Dsv00001028sd000000AA* ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (Latitude CPt) pci:v00001002d00004C4Dsv00001028sd000000BB* ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (Latitude CPx) pci:v00001002d00004C4Dsv00001179sd0000FF00* ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (Satellite 1715XCDS laptop) pci:v00001002d00004C4Dsv000013BDsd00001019* ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (PC-AR10) pci:v00001002d00004C50* ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI pci:v00001002d00004C50sv00001002sd00004C50* ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI (Rage LT Pro) pci:v00001002d00004C52* ID_MODEL_FROM_DATABASE=Rage Mobility-M1 PCI pci:v00001002d00004C52sv00001033sd00008112* ID_MODEL_FROM_DATABASE=Rage Mobility-M1 PCI (Versa Note VXi) pci:v00001002d00004C54* ID_MODEL_FROM_DATABASE=264LT [Mach64 LT] pci:v00001002d00004C57* ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] pci:v00001002d00004C57sv00001014sd00000517* ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] (ThinkPad T30) pci:v00001002d00004C57sv00001014sd00000530* ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] (ThinkPad T4x Series) pci:v00001002d00004C57sv00001028sd000000E6* ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] (Radeon Mobility M7 LW (Dell Inspiron 8100)) pci:v00001002d00004C57sv00001028sd0000012A* ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] (Latitude C640) pci:v00001002d00004C57sv00001043sd00001622* ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] (Mobility Radeon M7 (L3C/S)) pci:v00001002d00004C57sv0000144Dsd0000C006* ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] (Radeon Mobility M7 LW in vpr Matrix 170B4) pci:v00001002d00004C58* ID_MODEL_FROM_DATABASE=RV200/M7 GL [Mobility FireGL 7800] pci:v00001002d00004C59* ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] pci:v00001002d00004C59sv00000E11sd0000B111* ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (Evo N600c) pci:v00001002d00004C59sv00001014sd00000235* ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (ThinkPad A30/A30p (2652/2653)) pci:v00001002d00004C59sv00001014sd00000239* ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (ThinkPad X22/X23/X24) pci:v00001002d00004C59sv0000103Csd00000025* ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (XE4500 Notebook) pci:v00001002d00004C59sv0000104Dsd000080E7* ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) pci:v00001002d00004C59sv0000104Dsd00008140* ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (PCG-Z1SP laptop) pci:v00001002d00004C59sv00001509sd00001930* ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (Medion MD9703) pci:v00001002d00004C66* ID_MODEL_FROM_DATABASE=RV250/M9 GL [Mobility FireGL 9000/Radeon 9000] pci:v00001002d00004C66sv00001014sd0000054D* ID_MODEL_FROM_DATABASE=RV250/M9 GL [Mobility FireGL 9000/Radeon 9000] (ThinkPad T41) pci:v00001002d00004C6E* ID_MODEL_FROM_DATABASE=RV250/M9 [Mobility Radeon 9000] (Secondary) pci:v00001002d00004D46* ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 4X/Mobility M4 pci:v00001002d00004D52* ID_MODEL_FROM_DATABASE=Theater 550 PRO PCI [ATI TV Wonder 550] pci:v00001002d00004D53* ID_MODEL_FROM_DATABASE=Theater 550 PRO PCIe pci:v00001002d00004E44* ID_MODEL_FROM_DATABASE=R300 [Radeon 9700/9700 PRO] pci:v00001002d00004E44sv00001002sd0000515E* ID_MODEL_FROM_DATABASE=R300 [Radeon 9700/9700 PRO] (Radeon ES1000) pci:v00001002d00004E44sv00001002sd00005965* ID_MODEL_FROM_DATABASE=R300 [Radeon 9700/9700 PRO] (Radeon ES1000) pci:v00001002d00004E45* ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO/9700] pci:v00001002d00004E45sv00001002sd00000002* ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO/9700] (Radeon R300 NE [Radeon 9500 Pro]) pci:v00001002d00004E45sv00001681sd00000002* ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO/9700] (Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro]) pci:v00001002d00004E46* ID_MODEL_FROM_DATABASE=R300 [Radeon 9600 TX] pci:v00001002d00004E47* ID_MODEL_FROM_DATABASE=R300 GL [FireGL X1] pci:v00001002d00004E48* ID_MODEL_FROM_DATABASE=R350 [Radeon 9800 Series] pci:v00001002d00004E49* ID_MODEL_FROM_DATABASE=R350 [Radeon 9800] pci:v00001002d00004E4A* ID_MODEL_FROM_DATABASE=R360 [Radeon 9800 XXL/XT] pci:v00001002d00004E4Asv00001002sd00004E4A* ID_MODEL_FROM_DATABASE=R360 [Radeon 9800 XXL/XT] (R360 [Radeon 9800 XT]) pci:v00001002d00004E4B* ID_MODEL_FROM_DATABASE=R350 GL [FireGL X2 AGP Pro] pci:v00001002d00004E50* ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] pci:v00001002d00004E50sv00001025sd0000005A* ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (TravelMate 290) pci:v00001002d00004E50sv00001025sd00000064* ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (Extensa 3000 series laptop: ATI RV360/M11 [Mobility Radeon 9700]) pci:v00001002d00004E50sv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (NC8000 laptop) pci:v00001002d00004E50sv0000103Csd00000890* ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (NC6000 laptop) pci:v00001002d00004E50sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (P35 notebook) pci:v00001002d00004E50sv00001462sd00000311* ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (MSI M510A) pci:v00001002d00004E50sv00001734sd00001055* ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (Amilo M1420W) pci:v00001002d00004E51* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] pci:v00001002d00004E52* ID_MODEL_FROM_DATABASE=RV350/M10 [Mobility Radeon 9500/9700 SE] pci:v00001002d00004E52sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=RV350/M10 [Mobility Radeon 9500/9700 SE] (P35 notebook) pci:v00001002d00004E54* ID_MODEL_FROM_DATABASE=RV350/M10 GL [Mobility FireGL T2] pci:v00001002d00004E56* ID_MODEL_FROM_DATABASE=RV360/M12 [Mobility Radeon 9550] pci:v00001002d00004E64* ID_MODEL_FROM_DATABASE=R300 [Radeon 9700 PRO] (Secondary) pci:v00001002d00004E65* ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO] (Secondary) pci:v00001002d00004E65sv00001002sd00000003* ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO] (Secondary) (Radeon R300 NE [Radeon 9500 Pro]) pci:v00001002d00004E65sv00001681sd00000003* ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO] (Secondary) (Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro] (Secondary)) pci:v00001002d00004E66* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600] (Secondary) pci:v00001002d00004E67* ID_MODEL_FROM_DATABASE=R300 GL [FireGL X1] (Secondary) pci:v00001002d00004E68* ID_MODEL_FROM_DATABASE=R350 [Radeon 9800 PRO] (Secondary) pci:v00001002d00004E69* ID_MODEL_FROM_DATABASE=R350 [Radeon 9800] (Secondary) pci:v00001002d00004E6A* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9800 XT] (Secondary) pci:v00001002d00004E6Asv00001002sd00004E6A* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9800 XT] (Secondary) (R360 [Radeon 9800 XT] (Secondary)) pci:v00001002d00004E6Asv00001002sd00004E71* ID_MODEL_FROM_DATABASE=RV350 [Radeon 9800 XT] (Secondary) (M10 NQ [Radeon Mobility 9600]) pci:v00001002d00004E71* ID_MODEL_FROM_DATABASE=RV350/M10 [Mobility Radeon 9600] (Secondary) pci:v00001002d00004F72* ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] pci:v00001002d00004F73* ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (Secondary) pci:v00001002d00005044* ID_MODEL_FROM_DATABASE=All-In-Wonder 128 PCI pci:v00001002d00005044sv00001002sd00000028* ID_MODEL_FROM_DATABASE=All-In-Wonder 128 PCI (Rage 128 AIW) pci:v00001002d00005044sv00001002sd00000029* ID_MODEL_FROM_DATABASE=All-In-Wonder 128 PCI (Rage 128 AIW) pci:v00001002d00005046* ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS pci:v00001002d00005046sv00001002sd00000004* ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury Pro) pci:v00001002d00005046sv00001002sd00000008* ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury Pro/Xpert 2000 Pro) pci:v00001002d00005046sv00001002sd00000014* ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury Pro) pci:v00001002d00005046sv00001002sd00000018* ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury Pro/Xpert 2000 Pro) pci:v00001002d00005046sv00001002sd00000028* ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage 128 Pro AIW AGP) pci:v00001002d00005046sv00001002sd0000002A* ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage 128 Pro AIW AGP) pci:v00001002d00005046sv00001002sd00000048* ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury Pro) pci:v00001002d00005046sv00001002sd00002000* ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury MAXX AGP 4x (TMDS) (VGA device)) pci:v00001002d00005046sv00001002sd00002001* ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury MAXX AGP 4x (TMDS) (Extra device?!)) pci:v00001002d00005050* ID_MODEL_FROM_DATABASE=Rage128 [Xpert 128 PCI] pci:v00001002d00005050sv00001002sd00000008* ID_MODEL_FROM_DATABASE=Rage128 [Xpert 128 PCI] (Xpert 128) pci:v00001002d00005052* ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4X TMDS pci:v00001002d00005144* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] pci:v00001002d00005144sv00001002sd00000008* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon VE) pci:v00001002d00005144sv00001002sd00000009* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) pci:v00001002d00005144sv00001002sd0000000A* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) pci:v00001002d00005144sv00001002sd0000001A* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) pci:v00001002d00005144sv00001002sd00000029* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon AIW) pci:v00001002d00005144sv00001002sd00000038* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) pci:v00001002d00005144sv00001002sd00000039* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) pci:v00001002d00005144sv00001002sd0000008A* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) pci:v00001002d00005144sv00001002sd000000BA* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) pci:v00001002d00005144sv00001002sd00000139* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) pci:v00001002d00005144sv00001002sd0000028A* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) pci:v00001002d00005144sv00001002sd000002AA* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon AIW) pci:v00001002d00005144sv00001002sd0000053A* ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) pci:v00001002d00005148* ID_MODEL_FROM_DATABASE=R200 GL [FireGL 8800] pci:v00001002d00005148sv00001002sd0000010A* ID_MODEL_FROM_DATABASE=R200 GL [FireGL 8800] (FireGL 8800 64Mb) pci:v00001002d00005148sv00001002sd00000152* ID_MODEL_FROM_DATABASE=R200 GL [FireGL 8800] (FireGL 8800 128Mb) pci:v00001002d00005148sv00001002sd00000162* ID_MODEL_FROM_DATABASE=R200 GL [FireGL 8800] (FireGL 8700 32Mb) pci:v00001002d00005148sv00001002sd00000172* ID_MODEL_FROM_DATABASE=R200 GL [FireGL 8800] (FireGL 8700 64Mb) pci:v00001002d0000514C* ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] pci:v00001002d0000514Csv00001002sd0000003A* ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] (Radeon R200 QL [Radeon 8500 LE]) pci:v00001002d0000514Csv00001002sd0000013A* ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] (Radeon 8500) pci:v00001002d0000514Csv0000148Csd00002026* ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] (R200 QL [Radeon 8500 Evil Master II Multi Display Edition]) pci:v00001002d0000514Csv00001681sd00000010* ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] (Radeon 8500 [3D Prophet 8500 128Mb]) pci:v00001002d0000514Csv0000174Bsd00007149* ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] (Radeon 8500 LE) pci:v00001002d0000514Csv00001787sd00000F08* ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] (Radeon R200 QL [PowerMagic Radeon 8500]) pci:v00001002d0000514D* ID_MODEL_FROM_DATABASE=R200 [Radeon 9100] pci:v00001002d00005157* ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] pci:v00001002d00005157sv00001002sd0000013A* ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (Radeon 7500) pci:v00001002d00005157sv00001002sd00000F2B* ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (ALL-IN-WONDER VE PCI) pci:v00001002d00005157sv00001002sd0000103A* ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (Dell Optiplex GX260) pci:v00001002d00005157sv00001458sd00004000* ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (RV200 QW [RADEON 7500 PRO MAYA AR]) pci:v00001002d00005157sv0000148Csd00002024* ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (RV200 QW [Radeon 7500LE Dual Display]) pci:v00001002d00005157sv0000148Csd00002025* ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (RV200 QW [Radeon 7500 Evil Master Multi Display Edition]) pci:v00001002d00005157sv0000148Csd00002036* ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (RV200 QW [Radeon 7500 PCI Dual Display]) pci:v00001002d00005157sv0000174Bsd00007146* ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (RV200 QW [Radeon 7500 LE]) pci:v00001002d00005157sv0000174Bsd00007147* ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (Radeon 7500 LE) pci:v00001002d00005157sv0000174Bsd00007161* ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (Radeon RV200 QW [Radeon 7500 LE]) pci:v00001002d00005157sv000017AFsd00000202* ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (RV200 QW [Excalibur Radeon 7500LE]) pci:v00001002d00005159* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] pci:v00001002d00005159sv00001002sd0000000A* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000/Radeon VE) pci:v00001002d00005159sv00001002sd0000000B* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000) pci:v00001002d00005159sv00001002sd00000038* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000/Radeon VE) pci:v00001002d00005159sv00001002sd0000003A* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000/Radeon VE) pci:v00001002d00005159sv00001002sd000000BA* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000/Radeon VE) pci:v00001002d00005159sv00001002sd0000013A* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000/Radeon VE) pci:v00001002d00005159sv00001002sd00000908* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (XVR-100 (supplied by Sun)) pci:v00001002d00005159sv00001014sd0000029A* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Remote Supervisor Adapter II (RSA2)) pci:v00001002d00005159sv00001014sd000002C8* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (eServer xSeries server mainboard) pci:v00001002d00005159sv00001028sd0000016C* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (PowerEdge 1850 Embedded Radeon 7000/VE) pci:v00001002d00005159sv00001028sd0000016D* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (PowerEdge 2850 Embedded Radeon 7000-M) pci:v00001002d00005159sv00001028sd00000170* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (PowerEdge 6850 Embedded Radeon 7000/VE) pci:v00001002d00005159sv00001028sd0000019A* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (PowerEdge SC1425) pci:v00001002d00005159sv0000103Csd00001292* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000) pci:v00001002d00005159sv00001043sd0000C00A* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (A7000/T/64M) pci:v00001002d00005159sv00001458sd00004002* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (RV100 QY [RADEON 7000 PRO MAYA AV Series]) pci:v00001002d00005159sv0000148Csd00002003* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (RV100 QY [Radeon 7000 Multi-Display Edition]) pci:v00001002d00005159sv0000148Csd00002023* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (RV100 QY [Radeon 7000 Evil Master Multi-Display]) pci:v00001002d00005159sv0000148Csd00002081* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (RV6DE) pci:v00001002d00005159sv0000174Bsd00000280* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon RV100 QY [Radeon 7000/VE]) pci:v00001002d00005159sv0000174Bsd00007112* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon VE 7000) pci:v00001002d00005159sv0000174Bsd00007C28* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon VE 7000 DDR) pci:v00001002d00005159sv00001787sd00000202* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (RV100 QY [Excalibur Radeon 7000]) pci:v00001002d00005159sv000017EEsd00001001* ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000 64MB DDR + DVI) pci:v00001002d0000515E* ID_MODEL_FROM_DATABASE=ES1000 pci:v00001002d0000515Esv00001028sd000001BB* ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge 1955 Embedded ATI ES1000) pci:v00001002d0000515Esv00001028sd000001DF* ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge SC440) pci:v00001002d0000515Esv00001028sd000001E6* ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge 860) pci:v00001002d0000515Esv00001028sd000001F0* ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge R900 Embedded ATI ES1000) pci:v00001002d0000515Esv00001028sd00000205* ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge 2970 Embedded ATI ES1000) pci:v00001002d0000515Esv00001028sd0000020B* ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge T605 Embedded ATI ES1000) pci:v00001002d0000515Esv00001028sd0000020F* ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge R300 Embedded ATI ES1000) pci:v00001002d0000515Esv00001028sd00000210* ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge T300 Embedded ATI ES1000) pci:v00001002d0000515Esv00001028sd00000221* ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge R805 Embedded ATI ES1000) pci:v00001002d0000515Esv00001028sd00000223* ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge R905 Embedded ATI ES1000) pci:v00001002d0000515Esv00001028sd00000225* ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge T105 Embedded ATI ES1000) pci:v00001002d0000515Esv00001028sd0000023C* ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge R200 Embedded ATI ES1000) pci:v00001002d0000515Esv0000103Csd00001304* ID_MODEL_FROM_DATABASE=ES1000 (Integrity iLO2 Advanced KVM VGA [AD307A]) pci:v00001002d0000515Esv000015D9sd00008680* ID_MODEL_FROM_DATABASE=ES1000 (X7DVL-E-O motherboard) pci:v00001002d0000515Esv000015D9sd00009680* ID_MODEL_FROM_DATABASE=ES1000 (X7DBN Motherboard) pci:v00001002d0000515Esv00008086sd00003476* ID_MODEL_FROM_DATABASE=ES1000 (S5000PSLSATA Server Board) pci:v00001002d00005245* ID_MODEL_FROM_DATABASE=Rage 128 GL PCI pci:v00001002d00005245sv00001002sd00000008* ID_MODEL_FROM_DATABASE=Rage 128 GL PCI (Xpert 128) pci:v00001002d00005245sv00001002sd00000028* ID_MODEL_FROM_DATABASE=Rage 128 GL PCI (Rage 128 AIW) pci:v00001002d00005245sv00001002sd00000029* ID_MODEL_FROM_DATABASE=Rage 128 GL PCI (Rage 128 AIW) pci:v00001002d00005245sv00001002sd00000068* ID_MODEL_FROM_DATABASE=Rage 128 GL PCI (Rage 128 AIW) pci:v00001002d00005246* ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x pci:v00001002d00005246sv00001002sd00000004* ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x (Magnum/Xpert 128/Xpert 99) pci:v00001002d00005246sv00001002sd00000008* ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x (Magnum/Xpert128/X99/Xpert2000) pci:v00001002d00005246sv00001002sd00000028* ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x (Rage 128 AIW AGP) pci:v00001002d00005246sv00001002sd00000044* ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x (Rage Fury/Xpert 128/Xpert 2000) pci:v00001002d00005246sv00001002sd00000068* ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x (Rage 128 AIW AGP) pci:v00001002d00005246sv00001002sd00000448* ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x (Rage Fury) pci:v00001002d0000524B* ID_MODEL_FROM_DATABASE=Rage 128 VR PCI pci:v00001002d0000524C* ID_MODEL_FROM_DATABASE=Rage 128 VR AGP pci:v00001002d0000524Csv00001002sd00000008* ID_MODEL_FROM_DATABASE=Rage 128 VR AGP (Xpert 99/Xpert 2000) pci:v00001002d0000524Csv00001002sd00000088* ID_MODEL_FROM_DATABASE=Rage 128 VR AGP (Xpert 99) pci:v00001002d00005346* ID_MODEL_FROM_DATABASE=Rage 128 SF/4x AGP 2x pci:v00001002d00005346sv00001002sd00000048* ID_MODEL_FROM_DATABASE=Rage 128 SF/4x AGP 2x (RAGE 128 16MB VGA TVOUT AMC PAL) pci:v00001002d0000534D* ID_MODEL_FROM_DATABASE=Rage 128 4X AGP 4x pci:v00001002d0000534Dsv00001002sd00000008* ID_MODEL_FROM_DATABASE=Rage 128 4X AGP 4x (Xpert 99/Xpert 2000) pci:v00001002d0000534Dsv00001002sd00000018* ID_MODEL_FROM_DATABASE=Rage 128 4X AGP 4x (Xpert 2000) pci:v00001002d00005354* ID_MODEL_FROM_DATABASE=Mach 64 VT pci:v00001002d00005354sv00001002sd00005654* ID_MODEL_FROM_DATABASE=Mach 64 VT (Mach 64 reference) pci:v00001002d00005446* ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x pci:v00001002d00005446sv00001002sd00000004* ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage Fury Pro) pci:v00001002d00005446sv00001002sd00000008* ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage Fury Pro/Xpert 2000 Pro) pci:v00001002d00005446sv00001002sd00000018* ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage Fury Pro/Xpert 2000 Pro) pci:v00001002d00005446sv00001002sd00000028* ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage 128 AIW Pro AGP) pci:v00001002d00005446sv00001002sd00000029* ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage 128 AIW) pci:v00001002d00005446sv00001002sd0000002A* ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage 128 AIW Pro AGP) pci:v00001002d00005446sv00001002sd0000002B* ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage 128 AIW) pci:v00001002d00005446sv00001002sd00000048* ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Xpert 2000 Pro) pci:v00001002d00005452* ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra4XL VR-R AGP pci:v00001002d00005452sv00001002sd0000001C* ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra4XL VR-R AGP (Rage 128 Pro 4XL) pci:v00001002d00005452sv0000103Csd00001279* ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra4XL VR-R AGP (Rage 128 Pro 4XL) pci:v00001002d00005460* ID_MODEL_FROM_DATABASE=RV370/M22 [Mobility Radeon X300] pci:v00001002d00005460sv00001775sd00001100* ID_MODEL_FROM_DATABASE=RV370/M22 [Mobility Radeon X300] (CR11/VR11 Single Board Computer) pci:v00001002d00005461* ID_MODEL_FROM_DATABASE=RV370/M22 [Mobility Radeon X300] pci:v00001002d00005462* ID_MODEL_FROM_DATABASE=RV380/M24C [Mobility Radeon X600 SE] pci:v00001002d00005464* ID_MODEL_FROM_DATABASE=RV370/M22 GL [Mobility FireGL V3100] pci:v00001002d00005549* ID_MODEL_FROM_DATABASE=R423 [Radeon X800 GTO] pci:v00001002d0000554A* ID_MODEL_FROM_DATABASE=R423 [Radeon X800 XT Platinum Edition] pci:v00001002d0000554B* ID_MODEL_FROM_DATABASE=R423 [Radeon X800 GT/SE] pci:v00001002d0000554Bsv00001002sd00000302* ID_MODEL_FROM_DATABASE=R423 [Radeon X800 GT/SE] (Radeon X800 SE) pci:v00001002d0000554D* ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] pci:v00001002d0000554Dsv00001002sd00000322* ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] (All-In-Wonder X800 XL) pci:v00001002d0000554Dsv00001458sd00002124* ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] (GV-R80L256V-B (AGP)) pci:v00001002d0000554E* ID_MODEL_FROM_DATABASE=R430 [All-In-Wonder X800 GT] pci:v00001002d0000554F* ID_MODEL_FROM_DATABASE=R430 [Radeon X800] pci:v00001002d00005550* ID_MODEL_FROM_DATABASE=R423 GL [FireGL V7100] pci:v00001002d00005551* ID_MODEL_FROM_DATABASE=R423 GL [FireGL V5100] pci:v00001002d00005569* ID_MODEL_FROM_DATABASE=R423 [Radeon X800 PRO] (Secondary) pci:v00001002d0000556B* ID_MODEL_FROM_DATABASE=R423 [Radeon X800 GT] (Secondary) pci:v00001002d0000556D* ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] (Secondary) pci:v00001002d0000556Dsv00001458sd00002125* ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] (Secondary) (GV-R80L256V-B (AGP)) pci:v00001002d0000556F* ID_MODEL_FROM_DATABASE=R430 [Radeon X800] (Secondary) pci:v00001002d00005571* ID_MODEL_FROM_DATABASE=R423 GL [FireGL V5100] (Secondary) pci:v00001002d0000564B* ID_MODEL_FROM_DATABASE=RV410/M26 GL [Mobility FireGL V5000] pci:v00001002d0000564F* ID_MODEL_FROM_DATABASE=RV410/M26 [Mobility Radeon X700 XL] pci:v00001002d00005652* ID_MODEL_FROM_DATABASE=RV410/M26 [Mobility Radeon X700] pci:v00001002d00005653* ID_MODEL_FROM_DATABASE=RV410/M26 [Mobility Radeon X700] pci:v00001002d00005653sv00001025sd00000080* ID_MODEL_FROM_DATABASE=RV410/M26 [Mobility Radeon X700] (Aspire 5024WLMi) pci:v00001002d00005653sv0000103Csd00000940* ID_MODEL_FROM_DATABASE=RV410/M26 [Mobility Radeon X700] (Compaq NW8240 Mobile Workstation) pci:v00001002d00005654* ID_MODEL_FROM_DATABASE=264VT [Mach64 VT] pci:v00001002d00005654sv00001002sd00005654* ID_MODEL_FROM_DATABASE=264VT [Mach64 VT] (Mach64VT Reference) pci:v00001002d00005655* ID_MODEL_FROM_DATABASE=264VT3 [Mach64 VT3] pci:v00001002d00005656* ID_MODEL_FROM_DATABASE=264VT4 [Mach64 VT4] pci:v00001002d00005657* ID_MODEL_FROM_DATABASE=RV410 [Radeon X550 XTX / X700] pci:v00001002d00005830* ID_MODEL_FROM_DATABASE=RS300 Host Bridge pci:v00001002d00005831* ID_MODEL_FROM_DATABASE=RS300 Host Bridge pci:v00001002d00005832* ID_MODEL_FROM_DATABASE=RS300 Host Bridge pci:v00001002d00005833* ID_MODEL_FROM_DATABASE=RS300 Host Bridge pci:v00001002d00005834* ID_MODEL_FROM_DATABASE=RS300 [Radeon 9100 IGP] pci:v00001002d00005835* ID_MODEL_FROM_DATABASE=RS300M [Mobility Radeon 9100 IGP] pci:v00001002d00005838* ID_MODEL_FROM_DATABASE=RS300 AGP Bridge pci:v00001002d00005854* ID_MODEL_FROM_DATABASE=RS480 [Radeon Xpress 200 Series] (Secondary) pci:v00001002d00005874* ID_MODEL_FROM_DATABASE=RS480 [Radeon Xpress 1150] (Secondary) pci:v00001002d00005940* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 PRO] (Secondary) pci:v00001002d00005940sv000017AFsd00002021* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 PRO] (Secondary) (Excalibur Radeon 9250 (Secondary)) pci:v00001002d00005941* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Secondary) pci:v00001002d00005941sv00001458sd00004019* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Secondary) (Radeon 9200) pci:v00001002d00005941sv0000174Bsd00007C12* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Secondary) (Radeon 9200) pci:v00001002d00005941sv000017AFsd0000200D* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Secondary) (Excalibur Radeon 9200) pci:v00001002d00005941sv000018BCsd00000050* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Secondary) (GC-R9200-C3 (Secondary)) pci:v00001002d00005944* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE PCI] pci:v00001002d00005950* ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge pci:v00001002d00005950sv00001025sd00000080* ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge (Aspire 5024WLMMi) pci:v00001002d00005950sv0000103Csd0000280A* ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge (DC5750 Microtower) pci:v00001002d00005950sv0000103Csd00002A20* ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge (Pavilion t3030.de Desktop PC) pci:v00001002d00005950sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge (MX6125) pci:v00001002d00005950sv00001462sd00000131* ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge (MS-1013 Notebook) pci:v00001002d00005950sv00001462sd00007217* ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge (Aspire L250) pci:v00001002d00005951* ID_MODEL_FROM_DATABASE=RX480/RX482 Host Bridge pci:v00001002d00005952* ID_MODEL_FROM_DATABASE=RD580 Host Bridge pci:v00001002d00005954* ID_MODEL_FROM_DATABASE=RS480 [Radeon Xpress 200 Series] pci:v00001002d00005954sv00001002sd00005954* ID_MODEL_FROM_DATABASE=RS480 [Radeon Xpress 200 Series] (RV370 [Radeon Xpress 200G Series]) pci:v00001002d00005955* ID_MODEL_FROM_DATABASE=RS480M [Mobility Radeon Xpress 200] pci:v00001002d00005955sv00001002sd00005955* ID_MODEL_FROM_DATABASE=RS480M [Mobility Radeon Xpress 200] (RS480 0x5955 [Radeon XPRESS 200M 5955 (PCIE)]) pci:v00001002d00005955sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=RS480M [Mobility Radeon Xpress 200] (MX6125) pci:v00001002d00005955sv00001462sd00000131* ID_MODEL_FROM_DATABASE=RS480M [Mobility Radeon Xpress 200] (MS-1013 Notebook) pci:v00001002d00005956* ID_MODEL_FROM_DATABASE=RD790 Host Bridge pci:v00001002d00005957* ID_MODEL_FROM_DATABASE=RX780/RX790 Host Bridge pci:v00001002d00005957sv00001849sd00005957* ID_MODEL_FROM_DATABASE=RX780/RX790 Host Bridge (A770CrossFire Motherboard) pci:v00001002d00005958* ID_MODEL_FROM_DATABASE=RD780 Host Bridge pci:v00001002d00005960* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 PRO] pci:v00001002d00005960sv000017AFsd00002020* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 PRO] (Excalibur Radeon 9250) pci:v00001002d00005961* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] pci:v00001002d00005961sv00001002sd00002F72* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (All-in-Wonder 9200 Series) pci:v00001002d00005961sv00001019sd00004C30* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Radeon 9200 VIVO) pci:v00001002d00005961sv000012ABsd00005961* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (YUAN SMARTVGA Radeon 9200) pci:v00001002d00005961sv00001458sd00004018* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Radeon 9200) pci:v00001002d00005961sv0000174Bsd00007C13* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Radeon 9200) pci:v00001002d00005961sv000017AFsd0000200C* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Excalibur Radeon 9200) pci:v00001002d00005961sv000018BCsd00000050* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Radeon 9200 Game Buster) pci:v00001002d00005961sv000018BCsd00000051* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (GC-R9200-C3) pci:v00001002d00005961sv000018BCsd00000053* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Radeon 9200 Game Buster VIVO) pci:v00001002d00005962* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] pci:v00001002d00005964* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] pci:v00001002d00005964sv00001002sd00005964* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE, 64-bit 128MB DDR, 200/166MHz) pci:v00001002d00005964sv00001043sd0000C006* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE / TD / 128M) pci:v00001002d00005964sv00001458sd00004018* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE) pci:v00001002d00005964sv00001458sd00004032* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE 128MB) pci:v00001002d00005964sv0000147Bsd00006191* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (R9200SE-DT) pci:v00001002d00005964sv0000148Csd00002073* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (CN-AG92E) pci:v00001002d00005964sv0000174Bsd00007C13* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE) pci:v00001002d00005964sv00001787sd00005964* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Excalibur 9200SE VIVO 128M) pci:v00001002d00005964sv000017AFsd00002012* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE Excalibur) pci:v00001002d00005964sv000018BCsd00000170* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Sapphire Radeon 9200 SE 128MB Game Buster) pci:v00001002d00005964sv000018BCsd00000173* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (GC-R9200L(SE)-C3H [Radeon 9200 Game Buster]) pci:v00001002d00005965* ID_MODEL_FROM_DATABASE=RV280 GL [FireMV 2200 PCI] pci:v00001002d00005974* ID_MODEL_FROM_DATABASE=RS482/RS485 [Radeon Xpress 1100/1150] pci:v00001002d00005974sv0000103Csd0000280A* ID_MODEL_FROM_DATABASE=RS482/RS485 [Radeon Xpress 1100/1150] (DC5750 Microtower) pci:v00001002d00005974sv00001462sd00007141* ID_MODEL_FROM_DATABASE=RS482/RS485 [Radeon Xpress 1100/1150] (Aspire L250) pci:v00001002d00005975* ID_MODEL_FROM_DATABASE=RS482M [Mobility Radeon Xpress 200] pci:v00001002d00005978* ID_MODEL_FROM_DATABASE=RX780/RD790 PCI to PCI bridge (external gfx0 port A) pci:v00001002d00005978sv00001849sd00005957* ID_MODEL_FROM_DATABASE=RX780/RD790 PCI to PCI bridge (external gfx0 port A) (A770CrossFire Motherboard) pci:v00001002d00005979* ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (external gfx0 port B) pci:v00001002d0000597A* ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port A) pci:v00001002d0000597B* ID_MODEL_FROM_DATABASE=RX780/RD790 PCI to PCI bridge (PCI express gpp port B) pci:v00001002d0000597C* ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port C) pci:v00001002d0000597D* ID_MODEL_FROM_DATABASE=RX780/RD790 PCI to PCI bridge (PCI express gpp port D) pci:v00001002d0000597E* ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port E) pci:v00001002d0000597Esv00001849sd00005957* ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port E) (A770CrossFire Motherboard) pci:v00001002d0000597F* ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port F) pci:v00001002d0000597Fsv00001849sd00005957* ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port F) (A770CrossFire Motherboard) pci:v00001002d00005980* ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (external gfx1 port A) pci:v00001002d00005981* ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (external gfx1 port B) pci:v00001002d00005982* ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (NB-SB link) pci:v00001002d00005A10* ID_MODEL_FROM_DATABASE=RD890 Northbridge only dual slot (2x16) PCI-e GFX Hydra part pci:v00001002d00005A11* ID_MODEL_FROM_DATABASE=RD890 Northbridge only single slot PCI-e GFX Hydra part pci:v00001002d00005A12* ID_MODEL_FROM_DATABASE=RD890 Northbridge only dual slot (2x8) PCI-e GFX Hydra part pci:v00001002d00005A12sv000015D9sd0000A811* ID_MODEL_FROM_DATABASE=RD890 Northbridge only dual slot (2x8) PCI-e GFX Hydra part (H8DGU) pci:v00001002d00005A13* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (external gfx0 port A) pci:v00001002d00005A14* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (external gfx0 port B) pci:v00001002d00005A15* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (PCI express gpp port A) pci:v00001002d00005A16* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (PCI express gpp port B) pci:v00001002d00005A17* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (PCI express gpp port C) pci:v00001002d00005A18* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (PCI express gpp port D) pci:v00001002d00005A18sv000015D9sd0000A811* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (PCI express gpp port D) (H8DGU) pci:v00001002d00005A19* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (PCI express gpp port E) pci:v00001002d00005A1A* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (PCI express gpp port F) pci:v00001002d00005A1B* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (PCI express gpp port G) pci:v00001002d00005A1C* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (PCI express gpp port H) pci:v00001002d00005A1D* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (external gfx1 port A) pci:v00001002d00005A1E* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (external gfx1 port B) pci:v00001002d00005A1F* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (NB-SB link) pci:v00001002d00005A1Fsv000015D9sd0000A811* ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (NB-SB link) (H8DGU) pci:v00001002d00005A20* ID_MODEL_FROM_DATABASE=RD890S PCI Express bridge for GPP2 port 1 pci:v00001002d00005A23* ID_MODEL_FROM_DATABASE=RD990 I/O Memory Management Unit (IOMMU) pci:v00001002d00005A31* ID_MODEL_FROM_DATABASE=RC410 Host Bridge pci:v00001002d00005A33* ID_MODEL_FROM_DATABASE=RS400 Host Bridge pci:v00001002d00005A34* ID_MODEL_FROM_DATABASE=RS4xx PCI Express Port [ext gfx] pci:v00001002d00005A36* ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Express Port 1 pci:v00001002d00005A37* ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Express Port 2 pci:v00001002d00005A38* ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Express Port 3 pci:v00001002d00005A39* ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Express Port 4 pci:v00001002d00005A3F* ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Bridge [int gfx] pci:v00001002d00005A3Fsv00001462sd00007217* ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Bridge [int gfx] (Aspire L250) pci:v00001002d00005A41* ID_MODEL_FROM_DATABASE=RS400 [Radeon Xpress 200] pci:v00001002d00005A42* ID_MODEL_FROM_DATABASE=RS400M [Radeon Xpress 200M] pci:v00001002d00005A61* ID_MODEL_FROM_DATABASE=RC410 [Radeon Xpress 200/1100] pci:v00001002d00005A62* ID_MODEL_FROM_DATABASE=RC410M [Mobility Radeon Xpress 200M] pci:v00001002d00005B60* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] pci:v00001002d00005B60sv00001043sd0000002A* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (Extreme AX300SE-X) pci:v00001002d00005B60sv00001043sd0000032E* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (Extreme AX300/TD) pci:v00001002d00005B60sv00001458sd00002102* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (GV-RX30S128D (X300SE)) pci:v00001002d00005B60sv00001462sd00000400* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (RX300SE-TD128E (MS-8940 REV:200)) pci:v00001002d00005B60sv00001462sd00000402* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (RX300SE-TD128E (MS-8940)) pci:v00001002d00005B60sv0000174Bsd00000500* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (Radeon X300 (PCIE)) pci:v00001002d00005B60sv0000196Dsd00001086* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (X300SE HM) pci:v00001002d00005B62* ID_MODEL_FROM_DATABASE=RV370 [Radeon X600/X600 SE] pci:v00001002d00005B63* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300/X550/X1050 Series] pci:v00001002d00005B64* ID_MODEL_FROM_DATABASE=RV370 GL [FireGL V3100] pci:v00001002d00005B65* ID_MODEL_FROM_DATABASE=RV370 GL [FireMV 2200] pci:v00001002d00005B66* ID_MODEL_FROM_DATABASE=RV370X pci:v00001002d00005B70* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300 SE] pci:v00001002d00005B70sv00001462sd00000403* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300 SE] (Radeon X300 SE 128MB DDR) pci:v00001002d00005B70sv0000174Bsd00000501* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300 SE] (Radeon X300 SE) pci:v00001002d00005B70sv0000196Dsd00001087* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300 SE] (Radeon X300 SE HyperMemory) pci:v00001002d00005B72* ID_MODEL_FROM_DATABASE=RV380 [Radeon X300/X550/X1050 Series] (Secondary) pci:v00001002d00005B73* ID_MODEL_FROM_DATABASE=RV370 [Radeon X300/X550/X1050 Series] (Secondary) pci:v00001002d00005B74* ID_MODEL_FROM_DATABASE=RV370 GL [FireGL V3100] (Secondary) pci:v00001002d00005B75* ID_MODEL_FROM_DATABASE=RV370 GL [FireMV 2200] (Secondary) pci:v00001002d00005C61* ID_MODEL_FROM_DATABASE=RV280/M9+ [Mobility Radeon 9200 AGP] pci:v00001002d00005C63* ID_MODEL_FROM_DATABASE=RV280/M9+ [Mobility Radeon 9200 AGP] pci:v00001002d00005C63sv00001002sd00005C63* ID_MODEL_FROM_DATABASE=RV280/M9+ [Mobility Radeon 9200 AGP] (Apple iBook G4 2004) pci:v00001002d00005C63sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=RV280/M9+ [Mobility Radeon 9200 AGP] (P30 notebook) pci:v00001002d00005D44* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) pci:v00001002d00005D44sv00001458sd00004019* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Radeon 9200 SE (Secondary)) pci:v00001002d00005D44sv00001458sd00004032* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Radeon 9200 SE 128MB) pci:v00001002d00005D44sv0000147Bsd00006190* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (R9200SE-DT (Secondary)) pci:v00001002d00005D44sv0000174Bsd00007C12* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Radeon 9200 SE (Secondary)) pci:v00001002d00005D44sv00001787sd00005965* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Excalibur 9200SE VIVO 128M (Secondary)) pci:v00001002d00005D44sv000017AFsd00002013* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Radeon 9200 SE Excalibur (Secondary)) pci:v00001002d00005D44sv000018BCsd00000171* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Radeon 9200 SE 128MB Game Buster (Secondary)) pci:v00001002d00005D44sv000018BCsd00000172* ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (GC-R9200L(SE)-C3H [Radeon 9200 Game Buster]) pci:v00001002d00005D45* ID_MODEL_FROM_DATABASE=RV280 GL [FireMV 2200 PCI] (Secondary) pci:v00001002d00005D48* ID_MODEL_FROM_DATABASE=R423/M28 [Mobility Radeon X800 XT] pci:v00001002d00005D49* ID_MODEL_FROM_DATABASE=R423/M28 GL [Mobility FireGL V5100] pci:v00001002d00005D4A* ID_MODEL_FROM_DATABASE=R423/M28 [Mobility Radeon X800] pci:v00001002d00005D4D* ID_MODEL_FROM_DATABASE=R480 [Radeon X850 XT Platinum Edition] pci:v00001002d00005D4E* ID_MODEL_FROM_DATABASE=R480 [Radeon X850 SE] pci:v00001002d00005D4F* ID_MODEL_FROM_DATABASE=R480 [Radeon X800 GTO] pci:v00001002d00005D50* ID_MODEL_FROM_DATABASE=R480 GL [FireGL V7200] pci:v00001002d00005D52* ID_MODEL_FROM_DATABASE=R480 [Radeon X850 XT] pci:v00001002d00005D52sv00001002sd00000B12* ID_MODEL_FROM_DATABASE=R480 [Radeon X850 XT] (PowerColor X850XT PCIe (Primary)) pci:v00001002d00005D57* ID_MODEL_FROM_DATABASE=R423 [Radeon X800 XT] pci:v00001002d00005D6D* ID_MODEL_FROM_DATABASE=R480 [Radeon X850 XT Platinum Edition] (Secondary) pci:v00001002d00005D6F* ID_MODEL_FROM_DATABASE=R480 [Radeon X800 GTO] (Secondary) pci:v00001002d00005D72* ID_MODEL_FROM_DATABASE=R480 [Radeon X850 XT] (Secondary) pci:v00001002d00005D72sv00001002sd00000B13* ID_MODEL_FROM_DATABASE=R480 [Radeon X850 XT] (Secondary) (PowerColor X850XT PCIe (Secondary)) pci:v00001002d00005D77* ID_MODEL_FROM_DATABASE=R423 [Radeon X800 XT] (Secondary) pci:v00001002d00005E48* ID_MODEL_FROM_DATABASE=RV410 GL [FireGL V5000] pci:v00001002d00005E49* ID_MODEL_FROM_DATABASE=RV410 [Radeon X700 Series] pci:v00001002d00005E4A* ID_MODEL_FROM_DATABASE=RV410 [Radeon X700 XT] pci:v00001002d00005E4B* ID_MODEL_FROM_DATABASE=RV410 [Radeon X700 PRO] pci:v00001002d00005E4C* ID_MODEL_FROM_DATABASE=RV410 [Radeon X700 SE] pci:v00001002d00005E4D* ID_MODEL_FROM_DATABASE=RV410 [Radeon X700] pci:v00001002d00005E4Dsv0000148Csd00002116* ID_MODEL_FROM_DATABASE=RV410 [Radeon X700] (Bravo X700) pci:v00001002d00005E4F* ID_MODEL_FROM_DATABASE=RV410 [Radeon X700] pci:v00001002d00005E4Fsv00001569sd00001E4F* ID_MODEL_FROM_DATABASE=RV410 [Radeon X700] (Radeon X550 XT) pci:v00001002d00005E6B* ID_MODEL_FROM_DATABASE=RV410 [Radeon X700 PRO] (Secondary) pci:v00001002d00005E6D* ID_MODEL_FROM_DATABASE=RV410 [Radeon X700] (Secondary) pci:v00001002d00005E6Dsv0000148Csd00002117* ID_MODEL_FROM_DATABASE=RV410 [Radeon X700] (Secondary) (Bravo X700 (Secondary)) pci:v00001002d00005F57* ID_MODEL_FROM_DATABASE=R423 [Radeon X800 XT] pci:v00001002d00006600* ID_MODEL_FROM_DATABASE=Mars [Radeon HD 8670A/8670M/8750M] pci:v00001002d00006600sv0000103Csd00001952* ID_MODEL_FROM_DATABASE=Mars [Radeon HD 8670A/8670M/8750M] (ProBook 455 G1) pci:v00001002d00006601* ID_MODEL_FROM_DATABASE=Mars [Radeon HD 8730M] pci:v00001002d00006601sv0000103Csd00002100* ID_MODEL_FROM_DATABASE=Mars [Radeon HD 8730M] (FirePro M4100) pci:v00001002d00006602* ID_MODEL_FROM_DATABASE=Mars pci:v00001002d00006603* ID_MODEL_FROM_DATABASE=Mars pci:v00001002d00006604* ID_MODEL_FROM_DATABASE=Opal XT [Radeon R7 M265] pci:v00001002d00006604sv0000103Csd00008006* ID_MODEL_FROM_DATABASE=Opal XT [Radeon R7 M265] (FirePro M4170) pci:v00001002d00006604sv000017AAsd00003643* ID_MODEL_FROM_DATABASE=Opal XT [Radeon R7 M265] (Radeon R7 A360) pci:v00001002d00006605* ID_MODEL_FROM_DATABASE=Opal PRO [Radeon R7 M260] pci:v00001002d00006606* ID_MODEL_FROM_DATABASE=Mars XTX [Radeon HD 8790M] pci:v00001002d00006606sv00001028sd00000684* ID_MODEL_FROM_DATABASE=Mars XTX [Radeon HD 8790M] (FirePro W4170M) pci:v00001002d00006607* ID_MODEL_FROM_DATABASE=Mars LE [Radeon HD 8530M / R5 M240] pci:v00001002d00006608* ID_MODEL_FROM_DATABASE=Oland GL [FirePro W2100] pci:v00001002d00006610* ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] pci:v00001002d00006610sv00001019sd00000030* ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670) pci:v00001002d00006610sv00001028sd00002120* ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon R7 250) pci:v00001002d00006610sv00001028sd00002322* ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon R7 250) pci:v00001002d00006610sv00001462sd00002910* ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670) pci:v00001002d00006610sv00001462sd00002911* ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670) pci:v00001002d00006610sv0000148Csd00007350* ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon R7 350) pci:v00001002d00006610sv00001642sd00003C81* ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670) pci:v00001002d00006610sv00001642sd00003C91* ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670) pci:v00001002d00006610sv00001642sd00003F09* ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon R7 350) pci:v00001002d00006611* ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM] pci:v00001002d00006611sv00001028sd0000210B* ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM] (Radeon R5 240 OEM) pci:v00001002d00006611sv0000174Bsd00004248* ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM] (Radeon R7 240 OEM) pci:v00001002d00006611sv0000174Bsd0000A240* ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM] (Radeon R7 240 OEM) pci:v00001002d00006611sv0000174Bsd0000D340* ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM] (Radeon R7 340 OEM) pci:v00001002d00006611sv00001B0Asd000090D3* ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM] (Radeon R7 240 OEM) pci:v00001002d00006613* ID_MODEL_FROM_DATABASE=Oland PRO [Radeon R7 240/340] pci:v00001002d00006613sv0000148Csd00007340* ID_MODEL_FROM_DATABASE=Oland PRO [Radeon R7 240/340] (Radeon R7 340) pci:v00001002d00006613sv00001682sd00007240* ID_MODEL_FROM_DATABASE=Oland PRO [Radeon R7 240/340] (R7 240 2048 MB) pci:v00001002d00006620* ID_MODEL_FROM_DATABASE=Mars pci:v00001002d00006621* ID_MODEL_FROM_DATABASE=Mars PRO pci:v00001002d00006623* ID_MODEL_FROM_DATABASE=Mars pci:v00001002d00006631* ID_MODEL_FROM_DATABASE=Oland pci:v00001002d00006640* ID_MODEL_FROM_DATABASE=Saturn XT [FirePro M6100] pci:v00001002d00006641* ID_MODEL_FROM_DATABASE=Saturn PRO [Radeon HD 8930M] pci:v00001002d00006646* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon R9 M280X] pci:v00001002d00006647* ID_MODEL_FROM_DATABASE=Bonaire PRO [Radeon R9 M270X] pci:v00001002d00006649* ID_MODEL_FROM_DATABASE=Bonaire [FirePro W5100] pci:v00001002d00006650* ID_MODEL_FROM_DATABASE=Bonaire pci:v00001002d00006651* ID_MODEL_FROM_DATABASE=Bonaire pci:v00001002d00006658* ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X/360] pci:v00001002d00006658sv0000148Csd00000907* ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X/360] (Radeon R7 360) pci:v00001002d00006658sv00001682sd00000907* ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X/360] (Radeon R7 360) pci:v00001002d00006658sv00001682sd00007360* ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X/360] (Radeon R7 360) pci:v00001002d0000665C* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] pci:v00001002d0000665Csv00001043sd00000452* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 DirectCU II OC) pci:v00001002d0000665Csv00001462sd00002930* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 OC) pci:v00001002d0000665Csv00001462sd00002932* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 8770) pci:v00001002d0000665Csv00001462sd00002934* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R9 260 OEM) pci:v00001002d0000665Csv00001462sd00002938* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R9 360 OEM) pci:v00001002d0000665Csv0000148Csd00000907* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R7 360) pci:v00001002d0000665Csv0000148Csd00009260* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R9 260 OEM) pci:v00001002d0000665Csv0000148Csd00009360* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R9 360 OEM) pci:v00001002d0000665Csv00001682sd00000907* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R7 360) pci:v00001002d0000665Csv00001682sd00003310* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 Black Edition 2 GB) pci:v00001002d0000665Csv0000174Bsd0000E253* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 Dual-X OC) pci:v00001002d0000665Csv00001787sd00002329* ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 TurboDuo) pci:v00001002d0000665D* ID_MODEL_FROM_DATABASE=Bonaire [Radeon R7 200 Series] pci:v00001002d0000665F* ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] pci:v00001002d0000665Fsv00001028sd00000B04* ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] (Radeon R9 360 OEM) pci:v00001002d0000665Fsv00001462sd00002938* ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] (Radeon R9 360 OEM) pci:v00001002d0000665Fsv00001462sd00003271* ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] (Radeon R9 360 OEM) pci:v00001002d0000665Fsv00001682sd00007360* ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] (Radeon R7 360) pci:v00001002d00006660* ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] pci:v00001002d00006660sv00001028sd000005EA* ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon HD 8670M) pci:v00001002d00006660sv00001028sd000006BF* ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M335) pci:v00001002d00006660sv0000103Csd00001970* ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon HD 8670M) pci:v00001002d00006660sv0000103Csd000080BE* ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330) pci:v00001002d00006660sv0000103Csd00008136* ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330) pci:v00001002d00006660sv000017AAsd00003804* ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330) pci:v00001002d00006660sv000017AAsd00003809* ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330) pci:v00001002d00006660sv000017AAsd0000390C* ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330) pci:v00001002d00006663* ID_MODEL_FROM_DATABASE=Sun PRO [Radeon HD 8570A/8570M] pci:v00001002d00006663sv00001025sd00000846* ID_MODEL_FROM_DATABASE=Sun PRO [Radeon HD 8570A/8570M] (Radeon HD 8570A) pci:v00001002d00006664* ID_MODEL_FROM_DATABASE=Jet XT [Radeon R5 M240] pci:v00001002d00006665* ID_MODEL_FROM_DATABASE=Jet PRO [Radeon R5 M230] pci:v00001002d00006665sv000017AAsd0000368F* ID_MODEL_FROM_DATABASE=Jet PRO [Radeon R5 M230] (Radeon R5 A230) pci:v00001002d00006667* ID_MODEL_FROM_DATABASE=Jet ULT [Radeon R5 M230] pci:v00001002d0000666F* ID_MODEL_FROM_DATABASE=Sun LE [Radeon HD 8550M / R5 M230] pci:v00001002d00006704* ID_MODEL_FROM_DATABASE=Cayman PRO GL [FirePro V7900] pci:v00001002d00006707* ID_MODEL_FROM_DATABASE=Cayman LE GL [FirePro V5900] pci:v00001002d00006718* ID_MODEL_FROM_DATABASE=Cayman XT [Radeon HD 6970] pci:v00001002d00006719* ID_MODEL_FROM_DATABASE=Cayman PRO [Radeon HD 6950] pci:v00001002d0000671C* ID_MODEL_FROM_DATABASE=Antilles [Radeon HD 6990] pci:v00001002d0000671D* ID_MODEL_FROM_DATABASE=Antilles [Radeon HD 6990] pci:v00001002d0000671F* ID_MODEL_FROM_DATABASE=Cayman CE [Radeon HD 6930] pci:v00001002d00006720* ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] pci:v00001002d00006720sv00001028sd0000048F* ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6990M) pci:v00001002d00006720sv00001028sd00000490* ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Alienware M17x R3 Radeon HD 6970M) pci:v00001002d00006720sv00001028sd000004A4* ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (FirePro M8900) pci:v00001002d00006720sv00001028sd000004BA* ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6990M) pci:v00001002d00006720sv00001028sd0000053F* ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (FirePro M8900) pci:v00001002d00006720sv0000106Bsd00000B00* ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6970M) pci:v00001002d00006720sv00001558sd00005102* ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6970M) pci:v00001002d00006720sv00001558sd00005104* ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6990M) pci:v00001002d00006720sv00001558sd00007201* ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6990M) pci:v00001002d00006720sv0000174Bsd0000E188* ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6970M) pci:v00001002d00006738* ID_MODEL_FROM_DATABASE=Barts XT [Radeon HD 6870] pci:v00001002d00006738sv00001682sd00003103* ID_MODEL_FROM_DATABASE=Barts XT [Radeon HD 6870] (Radeon HD 8670) pci:v00001002d00006738sv00001787sd0000201A* ID_MODEL_FROM_DATABASE=Barts XT [Radeon HD 6870] (Barts XT [Radeon HD 6870 X2]) pci:v00001002d00006738sv00001787sd0000201B* ID_MODEL_FROM_DATABASE=Barts XT [Radeon HD 6870] (Barts XT [Radeon HD 6870 X2]) pci:v00001002d00006739* ID_MODEL_FROM_DATABASE=Barts PRO [Radeon HD 6850] pci:v00001002d00006739sv00001043sd000003B4* ID_MODEL_FROM_DATABASE=Barts PRO [Radeon HD 6850] (EAH6850 [Radeon HD 6850]) pci:v00001002d0000673E* ID_MODEL_FROM_DATABASE=Barts LE [Radeon HD 6790] pci:v00001002d0000673Esv0000148Csd00007720* ID_MODEL_FROM_DATABASE=Barts LE [Radeon HD 6790] (Radeon HD 7720 OEM) pci:v00001002d00006740* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] pci:v00001002d00006740sv00001019sd0000238C* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv00001019sd0000238E* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv00001019sd00002391* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv00001019sd00002392* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) pci:v00001002d00006740sv00001028sd000004A3* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Precision M4600) pci:v00001002d00006740sv00001028sd0000053E* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (FirePro M5950) pci:v00001002d00006740sv0000103Csd00001630* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (FirePro M5950) pci:v00001002d00006740sv0000103Csd00001631* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (FirePro M5950) pci:v00001002d00006740sv0000103Csd0000164B* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv0000103Csd0000164E* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv0000103Csd00001657* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) pci:v00001002d00006740sv0000103Csd00001658* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) pci:v00001002d00006740sv0000103Csd0000165A* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) pci:v00001002d00006740sv0000103Csd0000165B* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) pci:v00001002d00006740sv0000103Csd00001688* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) pci:v00001002d00006740sv0000103Csd00001689* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) pci:v00001002d00006740sv0000103Csd0000168A* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) pci:v00001002d00006740sv0000103Csd0000185E* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 7690M XT) pci:v00001002d00006740sv0000103Csd00003388* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) pci:v00001002d00006740sv0000103Csd00003389* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) pci:v00001002d00006740sv0000103Csd00003582* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) pci:v00001002d00006740sv0000103Csd0000366C* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv00001043sd00001D02* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv00001043sd00001D12* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv0000104Dsd00009084* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv0000104Dsd00009085* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv0000144Dsd0000B074* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv0000144Dsd0000B077* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv0000144Dsd0000B084* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv0000144Dsd0000B088* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006740sv000017AAsd00003982* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) pci:v00001002d00006741* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] pci:v00001002d00006741sv00001019sd0000238E* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001019sd0000238F* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000379* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000037B* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000037E* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000382* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000384* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000385* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000386* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000387* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000388* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000442* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000451* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000489* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000048B* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000048C* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000050A* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000050B* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000050C* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000050E* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000050F* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000513* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000514* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000515* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000516* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000051E* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000051F* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000520* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000521* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000052A* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000555* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000556* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000055D* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000055E* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000056D* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000059A* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000059B* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000059E* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd0000059F* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000600* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000605* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000606* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001025sd00000619* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001028sd000004C1* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv00001028sd000004C5* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv00001028sd000004CD* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv00001028sd000004D7* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv00001028sd000004D9* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv00001028sd0000052D* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv0000103Csd00001617* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv0000103Csd00001646* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) pci:v00001002d00006741sv0000103Csd00001647* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv0000103Csd0000164B* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv0000103Csd0000164E* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv0000103Csd00001688* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) pci:v00001002d00006741sv0000103Csd00001689* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) pci:v00001002d00006741sv0000103Csd0000168A* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) pci:v00001002d00006741sv0000103Csd00001860* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 7690M) pci:v00001002d00006741sv0000103Csd00003385* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv0000103Csd00003560* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) pci:v00001002d00006741sv0000103Csd0000358D* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) pci:v00001002d00006741sv0000103Csd00003590* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) pci:v00001002d00006741sv0000103Csd00003593* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) pci:v00001002d00006741sv0000103Csd0000366C* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001043sd00001CD2* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001043sd00002121* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001043sd00002122* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001043sd00002123* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001043sd00002125* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 7670M) pci:v00001002d00006741sv00001043sd00002127* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 7670M) pci:v00001002d00006741sv0000104Dsd0000907B* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv0000104Dsd00009080* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv0000104Dsd00009081* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv0000106Bsd000000E2* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (MacBookPro8,2 [Core i7, 15", Late 2011]) pci:v00001002d00006741sv00001179sd0000FD63* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv00001179sd0000FD65* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv0000144Dsd0000C093* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv0000144Dsd0000C0AC* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv0000144Dsd0000C0B3* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) pci:v00001002d00006741sv0000144Dsd0000C539* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv0000144Dsd0000C609* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv0000152Dsd00000914* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv000017AAsd000021E1* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) pci:v00001002d00006741sv000017AAsd00003970* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv000017AAsd00003976* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006741sv00001854sd00000907* ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) pci:v00001002d00006742* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] pci:v00001002d00006742sv00001002sd00006570* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) pci:v00001002d00006742sv00001019sd00002393* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 6610M) pci:v00001002d00006742sv00001043sd00001D82* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (K53SK Laptop Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB22* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB23* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB27* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB2A* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB2C* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB30* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB31* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB32* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB38* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB39* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB3A* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB3B* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB40* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB41* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB47* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB48* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB49* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB51* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB52* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB53* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB56* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB81* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB82* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FB83* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FC56* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FCD4* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001179sd0000FCEE* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) pci:v00001002d00006742sv00001458sd00006570* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) pci:v00001002d00006742sv00001462sd00006570* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) pci:v00001002d00006742sv0000148Csd00006570* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) pci:v00001002d00006742sv00001682sd00006570* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) pci:v00001002d00006742sv0000174Bsd00005570* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 5570]) pci:v00001002d00006742sv0000174Bsd00006570* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) pci:v00001002d00006742sv0000174Bsd00007570* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 7570]) pci:v00001002d00006742sv0000174Bsd00008510* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 8510]) pci:v00001002d00006742sv0000174Bsd00008570* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 8570]) pci:v00001002d00006742sv00001787sd00006570* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) pci:v00001002d00006742sv000017AFsd00006570* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) pci:v00001002d00006742sv00008086sd00002111* ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 6625M) pci:v00001002d00006743* ID_MODEL_FROM_DATABASE=Whistler [Radeon E6760] pci:v00001002d00006749* ID_MODEL_FROM_DATABASE=Turks GL [FirePro V4900] pci:v00001002d0000674A* ID_MODEL_FROM_DATABASE=Turks GL [FirePro V3900] pci:v00001002d00006750* ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] pci:v00001002d00006750sv00001462sd00002670* ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 6670A) pci:v00001002d00006750sv000017AAsd00003079* ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 7650A) pci:v00001002d00006750sv000017AAsd0000307A* ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 6650A) pci:v00001002d00006750sv000017AAsd00003087* ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 7650A) pci:v00001002d00006750sv000017AAsd00003618* ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 6650A) pci:v00001002d00006750sv000017AAsd00003623* ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 6650A) pci:v00001002d00006750sv000017AAsd00003627* ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 6650A) pci:v00001002d00006751* ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] pci:v00001002d00006751sv00001028sd00000548* ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] (Radeon HD 7650A) pci:v00001002d00006751sv00001462sd00002671* ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] (Radeon HD 7670A) pci:v00001002d00006751sv00001462sd00002672* ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] (Radeon HD 7670A) pci:v00001002d00006751sv00001462sd00002680* ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] (Radeon HD 7650A) pci:v00001002d00006751sv00001462sd00002681* ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] (Radeon HD 7650A) pci:v00001002d00006751sv000017AAsd00003087* ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] (Radeon HD 7650A) pci:v00001002d00006758* ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] pci:v00001002d00006758sv00001028sd00000B0E* ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 6670) pci:v00001002d00006758sv0000103Csd00006882* ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 6670) pci:v00001002d00006758sv00001462sd0000250A* ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 7670) pci:v00001002d00006758sv0000148Csd00007670* ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 7670) pci:v00001002d00006758sv00001545sd00007670* ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 7670) pci:v00001002d00006758sv00001682sd00003300* ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 7670) pci:v00001002d00006758sv0000174Bsd00007670* ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 7670) pci:v00001002d00006758sv0000174Bsd0000E181* ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 6670) pci:v00001002d00006758sv00001787sd00002309* ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 6670) pci:v00001002d00006759* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] pci:v00001002d00006759sv0000103Csd00003130* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) pci:v00001002d00006759sv00001043sd00000403* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) pci:v00001002d00006759sv00001462sd00002500* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) pci:v00001002d00006759sv00001462sd00002509* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 7570) pci:v00001002d00006759sv0000148Csd00007570* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 7570) pci:v00001002d00006759sv00001642sd00003A67* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) pci:v00001002d00006759sv00001682sd00003280* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 7570) pci:v00001002d00006759sv00001682sd00003530* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 8550) pci:v00001002d00006759sv0000174Bsd00007570* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 7570) pci:v00001002d00006759sv0000174Bsd0000E142* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) pci:v00001002d00006759sv0000174Bsd0000E181* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) pci:v00001002d00006759sv00001B0Asd0000908F* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) pci:v00001002d00006759sv00001B0Asd00009090* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) pci:v00001002d00006759sv00001B0Asd00009091* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) pci:v00001002d00006759sv00001B0Asd00009092* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) pci:v00001002d00006759sv00001B0Asd0000909E* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) pci:v00001002d00006759sv00001B0Asd000090B5* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 7570) pci:v00001002d00006759sv00001B0Asd000090B6* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 7570) pci:v00001002d0000675B* ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7600 Series] pci:v00001002d0000675D* ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 7570] pci:v00001002d0000675F* ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] pci:v00001002d0000675Fsv0000148Csd00006510* ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 6510) pci:v00001002d0000675Fsv0000148Csd00006530* ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 6530) pci:v00001002d0000675Fsv0000148Csd00007510* ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 7510) pci:v00001002d0000675Fsv00001545sd00007570* ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 7570) pci:v00001002d0000675Fsv0000174Bsd00006510* ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 6510) pci:v00001002d0000675Fsv0000174Bsd00007510* ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 7510) pci:v00001002d0000675Fsv0000174Bsd00008510* ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 8510) pci:v00001002d0000675Fsv00001787sd00002012* ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 5570 2GB GDDR3) pci:v00001002d0000675Fsv00001787sd00002314* ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 5570 1GB DDR2/GDDR3) pci:v00001002d00006760* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] pci:v00001002d00006760sv00001002sd00000124* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001002sd00000134* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001019sd0000238B* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001019sd0000238E* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001019sd00002390* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001019sd00009985* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001028sd000004C1* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001028sd000004C3* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001028sd000004CA* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001028sd000004CB* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001028sd000004CC* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Vostro 3350) pci:v00001002d00006760sv00001028sd000004D1* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001028sd000004D3* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001028sd000004D7* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001028sd00000502* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001028sd00000503* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001028sd00000506* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001028sd00000507* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001028sd00000514* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001028sd0000051C* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) pci:v00001002d00006760sv00001028sd0000051D* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) pci:v00001002d00006760sv0000103Csd0000161A* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000161B* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000161E* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000161F* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00001622* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) pci:v00001002d00006760sv0000103Csd00001623* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) pci:v00001002d00006760sv0000103Csd0000164A* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000164D* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00001651* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00001656* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd00001658* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd00001659* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd0000165B* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd0000165D* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000165F* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00001661* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00001663* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00001665* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00001667* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00001669* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000166B* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000166C* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000166E* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00001670* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00001672* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000167A* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000167B* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000167D* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd0000167F* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd0000168C* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000168F* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00001694* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00001696* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00001698* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000169A* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000169C* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd00001855* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) pci:v00001002d00006760sv0000103Csd00001859* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) pci:v00001002d00006760sv0000103Csd0000185C* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) pci:v00001002d00006760sv0000103Csd0000185D* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv0000103Csd0000185F* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv0000103Csd00001863* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) pci:v00001002d00006760sv0000103Csd0000355C* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd0000355F* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd00003563* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00003565* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00003567* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00003569* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00003581* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd00003584* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd0000358C* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd0000358F* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd00003592* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd00003596* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000103Csd0000366B* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000103Csd00003671* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (FirePro M3900) pci:v00001002d00006760sv0000103Csd00003673* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001043sd0000100A* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001043sd0000100C* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001043sd0000101B* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001043sd0000101C* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001043sd0000102A* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) pci:v00001002d00006760sv00001043sd0000102C* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001043sd0000104B* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001043sd0000105D* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001043sd0000106B* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001043sd0000106D* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001043sd0000107D* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001043sd00001CB2* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001043sd00001D22* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001043sd00001D32* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001043sd00002001* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001043sd00002002* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001043sd00002107* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001043sd00002108* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001043sd00002109* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001043sd000084A0* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001043sd000084E9* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001043sd00008515* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001043sd00008517* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001043sd0000855A* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv0000104Dsd0000907B* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000104Dsd00009081* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000104Dsd00009084* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000104Dsd00009085* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001179sd00000001* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) pci:v00001002d00006760sv00001179sd00000003* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) pci:v00001002d00006760sv00001179sd00000004* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) pci:v00001002d00006760sv00001179sd0000FB22* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB23* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB2C* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB31* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB32* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB33* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB38* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB39* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB3A* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB40* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB41* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB42* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB47* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB48* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB51* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB52* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB53* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB81* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB82* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FB83* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FC51* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001179sd0000FC52* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FC56* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FCD3* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FCD4* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FCEE* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv00001179sd0000FDEE* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv0000144Dsd0000B074* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000144Dsd0000B084* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000144Dsd0000C095* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000144Dsd0000C0B3* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) pci:v00001002d00006760sv0000144Dsd0000C538* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000144Dsd0000C581* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000144Dsd0000C589* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000144Dsd0000C609* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv0000144Dsd0000C625* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv0000144Dsd0000C636* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) pci:v00001002d00006760sv00001462sd000010AC* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv0000152Dsd00000916* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv000017AAsd000021E5* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv000017AAsd00003900* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) pci:v00001002d00006760sv000017AAsd00003902* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) pci:v00001002d00006760sv000017AAsd00003969* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv000017AAsd00003970* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) pci:v00001002d00006760sv000017AAsd00003976* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv000017AAsd0000397B* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv000017AAsd0000397D* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv000017AAsd00005101* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) pci:v00001002d00006760sv000017AAsd00005102* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) pci:v00001002d00006760sv000017AAsd00005103* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) pci:v00001002d00006760sv000017AAsd00005106* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) pci:v00001002d00006760sv00001854sd00000897* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001854sd00000900* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001854sd00000908* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006760sv00001854sd00002015* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) pci:v00001002d00006761* ID_MODEL_FROM_DATABASE=Seymour LP [Radeon HD 6430M] pci:v00001002d00006763* ID_MODEL_FROM_DATABASE=Seymour [Radeon E6460] pci:v00001002d00006764* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M Series] pci:v00001002d00006765* ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M Series] pci:v00001002d00006766* ID_MODEL_FROM_DATABASE=Caicos pci:v00001002d00006767* ID_MODEL_FROM_DATABASE=Caicos pci:v00001002d00006768* ID_MODEL_FROM_DATABASE=Caicos pci:v00001002d00006770* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] pci:v00001002d00006770sv000017AAsd0000308D* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] (Radeon HD 7450A) pci:v00001002d00006770sv000017AAsd00003623* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] (Radeon HD 6450A) pci:v00001002d00006770sv000017AAsd00003627* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] (Radeon HD 6450A) pci:v00001002d00006770sv000017AAsd00003629* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] (Radeon HD 6450A) pci:v00001002d00006770sv000017AAsd0000363C* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] (Radeon HD 6450A) pci:v00001002d00006770sv000017AAsd00003658* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] (Radeon HD 7470A) pci:v00001002d00006771* ID_MODEL_FROM_DATABASE=Caicos XTX [Radeon HD 8490 / R5 235X OEM] pci:v00001002d00006772* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 7450A] pci:v00001002d00006778* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] pci:v00001002d00006778sv00001019sd00000024* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 7470) pci:v00001002d00006778sv00001019sd00000027* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470) pci:v00001002d00006778sv00001028sd00002120* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 7470) pci:v00001002d00006778sv00001462sd0000B491* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470) pci:v00001002d00006778sv00001462sd0000B492* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470) pci:v00001002d00006778sv00001462sd0000B493* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470 OEM) pci:v00001002d00006778sv00001462sd0000B499* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon R5 235 OEM) pci:v00001002d00006778sv00001642sd00003C65* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470) pci:v00001002d00006778sv00001642sd00003C75* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470) pci:v00001002d00006778sv0000174Bsd00008145* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470) pci:v00001002d00006778sv0000174Bsd0000D145* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon R5 235 OEM) pci:v00001002d00006778sv0000174Bsd0000D335* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon R5 310 OEM) pci:v00001002d00006778sv0000174Bsd0000E145* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 7470) pci:v00001002d00006778sv000017AAsd00003694* ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon R5 A220) pci:v00001002d00006779* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] pci:v00001002d00006779sv00001019sd00000016* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv00001019sd00000017* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv00001019sd00000018* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv00001028sd00002120* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv0000103Csd00002128* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv0000103Csd00002AEE* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450A) pci:v00001002d00006779sv00001462sd00002125* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv00001462sd00002346* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) pci:v00001002d00006779sv00001462sd00002490* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv00001462sd00002494* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv00001462sd00002496* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) pci:v00001002d00006779sv0000148Csd00007450* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) pci:v00001002d00006779sv0000148Csd00008450* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 8450 OEM) pci:v00001002d00006779sv00001545sd00007470* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7470) pci:v00001002d00006779sv00001642sd00003A65* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv00001642sd00003A66* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) pci:v00001002d00006779sv00001642sd00003A75* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv00001642sd00003A76* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) pci:v00001002d00006779sv00001682sd00003200* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) pci:v00001002d00006779sv0000174Bsd00007450* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) pci:v00001002d00006779sv0000174Bsd0000E127* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv0000174Bsd0000E153* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv0000174Bsd0000E164* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450 1 GB DDR3) pci:v00001002d00006779sv0000174Bsd0000E180* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv0000174Bsd0000E201* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv000017AFsd00008450* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 8450 OEM) pci:v00001002d00006779sv00001B0Asd00009096* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv00001B0Asd00009097* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv00001B0Asd000090A8* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450A) pci:v00001002d00006779sv00001B0Asd000090B1* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) pci:v00001002d00006779sv00001B0Asd000090B3* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450A) pci:v00001002d00006779sv00001B0Asd000090BB* ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450A) pci:v00001002d0000677B* ID_MODEL_FROM_DATABASE=Caicos PRO [Radeon HD 7450] pci:v00001002d00006780* ID_MODEL_FROM_DATABASE=Tahiti XT GL [FirePro W9000] pci:v00001002d00006784* ID_MODEL_FROM_DATABASE=Tahiti [FirePro Series Graphics Adapter] pci:v00001002d00006788* ID_MODEL_FROM_DATABASE=Tahiti [FirePro Series Graphics Adapter] pci:v00001002d0000678A* ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] pci:v00001002d0000678Asv00001002sd0000030C* ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro W8000) pci:v00001002d0000678Asv00001002sd00000310* ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro S9000) pci:v00001002d0000678Asv00001002sd00000420* ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (Radeon Sky 700) pci:v00001002d0000678Asv00001002sd00000422* ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (Radeon Sky 900) pci:v00001002d0000678Asv00001002sd00000710* ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro S9050) pci:v00001002d0000678Asv00001002sd00000B0E* ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro S10000 Passive) pci:v00001002d0000678Asv00001002sd00000B2A* ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro S10000) pci:v00001002d0000678Asv00001028sd0000030C* ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro W8000) pci:v00001002d0000678Asv00001028sd00000710* ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro S9000) pci:v00001002d00006798* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] pci:v00001002d00006798sv00001002sd00003000* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XT2 [Radeon HD 7970 GHz Edition]) pci:v00001002d00006798sv00001002sd00003001* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XTL [Radeon R9 280X]) pci:v00001002d00006798sv00001002sd00004000* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Radeon HD 8970 OEM) pci:v00001002d00006798sv00001043sd0000041C* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (HD 7970 DirectCU II) pci:v00001002d00006798sv00001043sd00000420* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (HD 7970 DirectCU II TOP) pci:v00001002d00006798sv00001043sd00000444* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (HD 7970 DirectCU II TOP) pci:v00001002d00006798sv00001043sd00000448* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (HD 7970 DirectCU II TOP) pci:v00001002d00006798sv00001043sd0000044A* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XT2 [Matrix HD 7970]) pci:v00001002d00006798sv00001043sd0000044C* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XT2 [Matrix HD 7970 Platinum]) pci:v00001002d00006798sv00001043sd00003001* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XTL [ROG Matrix R9 280X]) pci:v00001002d00006798sv00001043sd00003006* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XTL [Radeon R9 280X DirectCU II TOP]) pci:v00001002d00006798sv00001043sd00009999* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (ARES II) pci:v00001002d00006798sv00001092sd00003000* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XT2 [Radeon HD 7970 GHz Edition]) pci:v00001002d00006798sv00001458sd00002261* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XT2 [Radeon HD 7970 GHz Edition OC]) pci:v00001002d00006798sv00001458sd00003001* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XTL [Radeon R9 280X OC]) pci:v00001002d00006798sv00001462sd00002774* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (MSI R7970 TF 3GD5/OC BE) pci:v00001002d00006798sv00001682sd00003211* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Double D HD 7970 Black Edition) pci:v00001002d00006798sv00001682sd00003213* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (HD 7970 Black Edition) pci:v00001002d00006798sv00001682sd00003214* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Double D HD 7970) pci:v00001002d00006798sv00001787sd0000201C* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (HD 7970 IceQ X²) pci:v00001002d00006798sv00001787sd00002317* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Radeon HD 7990) pci:v00001002d00006798sv00001787sd00003000* ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XT2 [Radeon HD 7970 GHz Edition]) pci:v00001002d00006799* ID_MODEL_FROM_DATABASE=New Zealand [Radeon HD 7900 Series] pci:v00001002d0000679A* ID_MODEL_FROM_DATABASE=Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] pci:v00001002d0000679Asv00001002sd00000B01* ID_MODEL_FROM_DATABASE=Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] (Radeon HD 8950 OEM) pci:v00001002d0000679Asv00001002sd00003000* ID_MODEL_FROM_DATABASE=Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] (Tahiti PRO2 [Radeon HD 7950 Boost]) pci:v00001002d0000679Asv00001462sd00003000* ID_MODEL_FROM_DATABASE=Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] (Radeon HD 8950 OEM) pci:v00001002d0000679Asv0000174Bsd0000A003* ID_MODEL_FROM_DATABASE=Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] (Radeon R9 280) pci:v00001002d0000679B* ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990] pci:v00001002d0000679Bsv00001002sd00000B28* ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990] (Radeon HD 8990 OEM) pci:v00001002d0000679Bsv00001002sd00000B2A* ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990] (Radeon HD 7990) pci:v00001002d0000679Bsv00001462sd00008036* ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990] (Radeon HD 8990 OEM) pci:v00001002d0000679Bsv0000148Csd00008990* ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990] (Radeon HD 8990 OEM) pci:v00001002d0000679E* ID_MODEL_FROM_DATABASE=Tahiti LE [Radeon HD 7870 XT] pci:v00001002d0000679F* ID_MODEL_FROM_DATABASE=Tahiti pci:v00001002d000067A0* ID_MODEL_FROM_DATABASE=Hawaii XT GL [FirePro W9100] pci:v00001002d000067A0sv00001002sd00000335* ID_MODEL_FROM_DATABASE=Hawaii XT GL [FirePro W9100] (FirePro S9150) pci:v00001002d000067A0sv00001028sd0000031F* ID_MODEL_FROM_DATABASE=Hawaii XT GL [FirePro W9100] (FirePro W9100) pci:v00001002d000067A0sv00001028sd00000335* ID_MODEL_FROM_DATABASE=Hawaii XT GL [FirePro W9100] (FirePro S9150) pci:v00001002d000067A1* ID_MODEL_FROM_DATABASE=Hawaii PRO GL [FirePro W8100] pci:v00001002d000067A1sv00001002sd00000335* ID_MODEL_FROM_DATABASE=Hawaii PRO GL [FirePro W8100] (FirePro S9100) pci:v00001002d000067A1sv00001028sd00000335* ID_MODEL_FROM_DATABASE=Hawaii PRO GL [FirePro W8100] (FirePro S9100) pci:v00001002d000067A2* ID_MODEL_FROM_DATABASE=Hawaii GL pci:v00001002d000067A8* ID_MODEL_FROM_DATABASE=Hawaii pci:v00001002d000067A9* ID_MODEL_FROM_DATABASE=Hawaii pci:v00001002d000067AA* ID_MODEL_FROM_DATABASE=Hawaii pci:v00001002d000067B0* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] pci:v00001002d000067B0sv00001043sd0000046A* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X DirectCU II) pci:v00001002d000067B0sv00001043sd0000046C* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X DirectCU II OC) pci:v00001002d000067B0sv00001043sd00000474* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (Matrix R9 290X Platinum) pci:v00001002d000067B0sv00001043sd00000476* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (ARES III) pci:v00001002d000067B0sv00001458sd0000227C* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X WindForce 3X OC) pci:v00001002d000067B0sv00001458sd00002281* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X WindForce 3X OC) pci:v00001002d000067B0sv00001458sd0000228C* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X WindForce 3X) pci:v00001002d000067B0sv00001458sd0000228D* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X WindForce 3X OC) pci:v00001002d000067B0sv00001458sd00002290* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X WindForce 3X) pci:v00001002d000067B0sv00001458sd000022C1* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (Grenada PRO [Radeon R9 390]) pci:v00001002d000067B0sv00001462sd00003070* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X Lightning) pci:v00001002d000067B0sv00001462sd00003071* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X Lightning) pci:v00001002d000067B0sv00001462sd00003072* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X Lightning LE) pci:v00001002d000067B0sv00001462sd00003080* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X Gaming) pci:v00001002d000067B0sv00001462sd00003082* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X Gaming OC) pci:v00001002d000067B0sv0000148Csd00002347* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (Devil 13 Dual Core R9 290X) pci:v00001002d000067B0sv00001682sd00009290* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (Double Dissipation R9 290X) pci:v00001002d000067B0sv0000174Bsd0000E282* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (Vapor-X R9 290X Tri-X OC) pci:v00001002d000067B0sv0000174Bsd0000E285* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X Tri-X OC) pci:v00001002d000067B0sv00001787sd00002020* ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X] (R9 290X IceQ X² Turbo) pci:v00001002d000067B1* ID_MODEL_FROM_DATABASE=Hawaii PRO [Radeon R9 290] pci:v00001002d000067B9* ID_MODEL_FROM_DATABASE=Vesuvius [Radeon R9 295X2] pci:v00001002d000067BE* ID_MODEL_FROM_DATABASE=Hawaii LE pci:v00001002d00006800* ID_MODEL_FROM_DATABASE=Wimbledon XT [Radeon HD 7970M] pci:v00001002d00006800sv00001002sd00000124* ID_MODEL_FROM_DATABASE=Wimbledon XT [Radeon HD 7970M] (Radeon HD 7970M) pci:v00001002d00006800sv00008086sd00002110* ID_MODEL_FROM_DATABASE=Wimbledon XT [Radeon HD 7970M] (Radeon HD 7970M) pci:v00001002d00006800sv00008086sd00002111* ID_MODEL_FROM_DATABASE=Wimbledon XT [Radeon HD 7970M] (Radeon HD 7970M) pci:v00001002d00006801* ID_MODEL_FROM_DATABASE=Neptune XT [Radeon HD 8970M] pci:v00001002d00006801sv00001002sd00000124* ID_MODEL_FROM_DATABASE=Neptune XT [Radeon HD 8970M] (Radeon HD 8970M) pci:v00001002d00006801sv00001462sd00001117* ID_MODEL_FROM_DATABASE=Neptune XT [Radeon HD 8970M] (Radeon R9 M290X) pci:v00001002d00006801sv00008086sd00002110* ID_MODEL_FROM_DATABASE=Neptune XT [Radeon HD 8970M] (Radeon HD 8970M) pci:v00001002d00006801sv00008086sd00002111* ID_MODEL_FROM_DATABASE=Neptune XT [Radeon HD 8970M] (Radeon HD 8970M) pci:v00001002d00006802* ID_MODEL_FROM_DATABASE=Wimbledon pci:v00001002d00006806* ID_MODEL_FROM_DATABASE=Neptune pci:v00001002d00006808* ID_MODEL_FROM_DATABASE=Pitcairn XT GL [FirePro W7000] pci:v00001002d00006808sv00001002sd00000310* ID_MODEL_FROM_DATABASE=Pitcairn XT GL [FirePro W7000] (FirePro S7000) pci:v00001002d00006808sv00001002sd00000420* ID_MODEL_FROM_DATABASE=Pitcairn XT GL [FirePro W7000] (Radeon Sky 500) pci:v00001002d00006809* ID_MODEL_FROM_DATABASE=Pitcairn LE GL [FirePro W5000] pci:v00001002d00006810* ID_MODEL_FROM_DATABASE=Curacao XT [Radeon R7 370 / R9 270X/370 OEM] pci:v00001002d00006810sv0000148Csd00000908* ID_MODEL_FROM_DATABASE=Curacao XT [Radeon R7 370 / R9 270X/370 OEM] (Radeon R9 370 OEM) pci:v00001002d00006810sv00001682sd00007370* ID_MODEL_FROM_DATABASE=Curacao XT [Radeon R7 370 / R9 270X/370 OEM] (Radeon R7 370) pci:v00001002d00006811* ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] pci:v00001002d00006811sv00001028sd00000B00* ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) pci:v00001002d00006811sv00001043sd00002016* ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) pci:v00001002d00006811sv00001458sd00002016* ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) pci:v00001002d00006811sv00001462sd00002016* ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) pci:v00001002d00006811sv0000148Csd00002016* ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) pci:v00001002d00006811sv00001682sd00002015* ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R7 370]) pci:v00001002d00006811sv0000174Bsd00002016* ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) pci:v00001002d00006811sv00001787sd00002016* ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) pci:v00001002d00006816* ID_MODEL_FROM_DATABASE=Pitcairn pci:v00001002d00006817* ID_MODEL_FROM_DATABASE=Pitcairn pci:v00001002d00006818* ID_MODEL_FROM_DATABASE=Pitcairn XT [Radeon HD 7870 GHz Edition] pci:v00001002d00006818sv00001002sd00000B05* ID_MODEL_FROM_DATABASE=Pitcairn XT [Radeon HD 7870 GHz Edition] (Radeon HD 8870 OEM) pci:v00001002d00006818sv0000174Bsd00008B04* ID_MODEL_FROM_DATABASE=Pitcairn XT [Radeon HD 7870 GHz Edition] (Radeon HD 8860) pci:v00001002d00006819* ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] pci:v00001002d00006819sv00001682sd00007269* ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] (Radeon R9 270 1024SP) pci:v00001002d00006819sv00001682sd00009278* ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] (Radeon R9 270 1024SP) pci:v00001002d00006819sv0000174Bsd0000A008* ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] (Radeon R9 270 1024SP) pci:v00001002d00006819sv0000174Bsd0000E221* ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] (Radeon HD 7850 2GB GDDR5 DVI-I/DVI-D/HDMI/DP) pci:v00001002d00006820* ID_MODEL_FROM_DATABASE=Venus XTX [Radeon HD 8890M / R9 M275X/M375X] pci:v00001002d00006820sv0000103Csd00001851* ID_MODEL_FROM_DATABASE=Venus XTX [Radeon HD 8890M / R9 M275X/M375X] (Radeon HD 7750M) pci:v00001002d00006820sv000017AAsd00003643* ID_MODEL_FROM_DATABASE=Venus XTX [Radeon HD 8890M / R9 M275X/M375X] (Radeon R9 A375) pci:v00001002d00006820sv000017AAsd00003801* ID_MODEL_FROM_DATABASE=Venus XTX [Radeon HD 8890M / R9 M275X/M375X] (Radeon R9 M275) pci:v00001002d00006820sv000017AAsd00003824* ID_MODEL_FROM_DATABASE=Venus XTX [Radeon HD 8890M / R9 M275X/M375X] (Radeon R9 M375) pci:v00001002d00006821* ID_MODEL_FROM_DATABASE=Venus XT [Radeon HD 8870M / R9 M270X/M370X] pci:v00001002d00006821sv00001002sd0000031E* ID_MODEL_FROM_DATABASE=Venus XT [Radeon HD 8870M / R9 M270X/M370X] (FirePro SX4000) pci:v00001002d00006821sv00001028sd000005CC* ID_MODEL_FROM_DATABASE=Venus XT [Radeon HD 8870M / R9 M270X/M370X] (FirePro M5100) pci:v00001002d00006821sv00001028sd000015CC* ID_MODEL_FROM_DATABASE=Venus XT [Radeon HD 8870M / R9 M270X/M370X] (FirePro M5100) pci:v00001002d00006821sv0000106Bsd00000149* ID_MODEL_FROM_DATABASE=Venus XT [Radeon HD 8870M / R9 M270X/M370X] (Radeon R9 M370X Mac Edition) pci:v00001002d00006822* ID_MODEL_FROM_DATABASE=Venus PRO [Radeon E8860] pci:v00001002d00006823* ID_MODEL_FROM_DATABASE=Venus PRO [Radeon HD 8850M / R9 M265X] pci:v00001002d00006825* ID_MODEL_FROM_DATABASE=Heathrow XT [Radeon HD 7870M] pci:v00001002d00006825sv00001028sd0000053F* ID_MODEL_FROM_DATABASE=Heathrow XT [Radeon HD 7870M] (FirePro M6000) pci:v00001002d00006825sv00001028sd000005CD* ID_MODEL_FROM_DATABASE=Heathrow XT [Radeon HD 7870M] (FirePro M6000) pci:v00001002d00006825sv00001028sd000015CD* ID_MODEL_FROM_DATABASE=Heathrow XT [Radeon HD 7870M] (FirePro M6000) pci:v00001002d00006825sv0000103Csd0000176C* ID_MODEL_FROM_DATABASE=Heathrow XT [Radeon HD 7870M] (FirePro M6000) pci:v00001002d00006825sv00008086sd00002111* ID_MODEL_FROM_DATABASE=Heathrow XT [Radeon HD 7870M] (Chelsea PRO) pci:v00001002d00006826* ID_MODEL_FROM_DATABASE=Chelsea LP [Radeon HD 7700M Series] pci:v00001002d00006827* ID_MODEL_FROM_DATABASE=Heathrow PRO [Radeon HD 7850M/8850M] pci:v00001002d00006828* ID_MODEL_FROM_DATABASE=Cape Verde PRO [FirePro W600] pci:v00001002d00006829* ID_MODEL_FROM_DATABASE=Cape Verde pci:v00001002d0000682A* ID_MODEL_FROM_DATABASE=Venus PRO pci:v00001002d0000682B* ID_MODEL_FROM_DATABASE=Venus LE [Radeon HD 8830M] pci:v00001002d0000682C* ID_MODEL_FROM_DATABASE=Cape Verde GL [FirePro W4100] pci:v00001002d0000682D* ID_MODEL_FROM_DATABASE=Chelsea XT GL [FirePro M4000] pci:v00001002d0000682F* ID_MODEL_FROM_DATABASE=Chelsea LP [Radeon HD 7730M] pci:v00001002d0000682Fsv0000103Csd00001851* ID_MODEL_FROM_DATABASE=Chelsea LP [Radeon HD 7730M] (Radeon HD 7750M) pci:v00001002d00006830* ID_MODEL_FROM_DATABASE=Cape Verde [Radeon HD 7800M Series] pci:v00001002d00006831* ID_MODEL_FROM_DATABASE=Cape Verde [AMD Radeon HD 7700M Series] pci:v00001002d00006835* ID_MODEL_FROM_DATABASE=Cape Verde PRX [Radeon R9 255 OEM] pci:v00001002d00006837* ID_MODEL_FROM_DATABASE=Cape Verde LE [Radeon HD 7730/8730] pci:v00001002d00006837sv00001462sd00002796* ID_MODEL_FROM_DATABASE=Cape Verde LE [Radeon HD 7730/8730] (Radeon HD 8730) pci:v00001002d00006837sv00001462sd00008092* ID_MODEL_FROM_DATABASE=Cape Verde LE [Radeon HD 7730/8730] (Radeon HD 8730) pci:v00001002d00006837sv0000148Csd00008730* ID_MODEL_FROM_DATABASE=Cape Verde LE [Radeon HD 7730/8730] (Radeon HD 8730) pci:v00001002d00006837sv00001787sd00003000* ID_MODEL_FROM_DATABASE=Cape Verde LE [Radeon HD 7730/8730] (Radeon HD 6570) pci:v00001002d0000683D* ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] pci:v00001002d0000683Dsv00001002sd00000030* ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] (Radeon HD 8760 OEM) pci:v00001002d0000683Dsv00001019sd00000030* ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] (Radeon HD 8760 OEM) pci:v00001002d0000683Dsv0000103Csd00006890* ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] (Radeon HD 8760 OEM) pci:v00001002d0000683Dsv00001043sd00008760* ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] (Radeon HD 8760 OEM) pci:v00001002d0000683Dsv00001462sd00002710* ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] (R7770-PMD1GD5) pci:v00001002d0000683Dsv0000174Bsd00008304* ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] (Radeon HD 8760 OEM) pci:v00001002d0000683F* ID_MODEL_FROM_DATABASE=Cape Verde PRO [Radeon HD 7750/8740 / R7 250E] pci:v00001002d0000683Fsv00001462sd00002790* ID_MODEL_FROM_DATABASE=Cape Verde PRO [Radeon HD 7750/8740 / R7 250E] (Radeon HD 8740) pci:v00001002d0000683Fsv00001462sd00002791* ID_MODEL_FROM_DATABASE=Cape Verde PRO [Radeon HD 7750/8740 / R7 250E] (Radeon HD 8740) pci:v00001002d0000683Fsv00001642sd00003B97* ID_MODEL_FROM_DATABASE=Cape Verde PRO [Radeon HD 7750/8740 / R7 250E] (Radeon HD 8740) pci:v00001002d00006840* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] pci:v00001002d00006840sv00001025sd0000050E* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001025sd0000050F* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001025sd00000513* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001025sd00000514* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001025sd0000056D* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001025sd0000059A* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001025sd0000059B* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001025sd0000059E* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001025sd00000600* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001025sd00000606* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001025sd00000696* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7650M) pci:v00001002d00006840sv00001025sd00000697* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7650M) pci:v00001002d00006840sv00001025sd00000698* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7650M) pci:v00001002d00006840sv00001025sd00000699* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7650M) pci:v00001002d00006840sv00001025sd00000757* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001028sd0000056A* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001028sd0000056E* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001028sd00000598* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001028sd0000059D* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001028sd000005A3* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001028sd000005B9* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001028sd000005BB* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd00001789* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (FirePro M2000) pci:v00001002d00006840sv0000103Csd000017F1* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7570M) pci:v00001002d00006840sv0000103Csd000017F4* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7650M) pci:v00001002d00006840sv0000103Csd00001813* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7590M) pci:v00001002d00006840sv0000103Csd0000182F* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd00001830* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd00001835* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd0000183A* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd0000183C* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd0000183E* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd00001840* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd00001842* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd00001844* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd00001848* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd0000184A* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd0000184C* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd00001895* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd00001897* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd000018A5* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd000018A7* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000103Csd000018F4* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001043sd0000100A* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001043sd0000104B* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001043sd000010DC* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001043sd00002121* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001043sd00002122* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001043sd00002123* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001043sd00002125* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001043sd00002127* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB11* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB22* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB23* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB2C* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB31* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB32* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB38* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB39* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB3A* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB40* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB41* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB47* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB48* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB51* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB52* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB53* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB81* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB82* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FB83* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FC56* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FCD4* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv00001179sd0000FCEE* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000144Dsd0000C0C5* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7690M) pci:v00001002d00006840sv0000144Dsd0000C0CE* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv0000144Dsd0000C0DA* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv000017AAsd00003970* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv000017AAsd0000397B* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv000017AAsd00005101* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv000017AAsd00005102* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006840sv000017AAsd00005103* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) pci:v00001002d00006841* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] pci:v00001002d00006841sv00001028sd00000561* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) pci:v00001002d00006841sv00001028sd0000056C* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) pci:v00001002d00006841sv00001028sd0000057F* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7570M) pci:v00001002d00006841sv0000103Csd000017F1* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7570M) pci:v00001002d00006841sv0000103Csd000017F4* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) pci:v00001002d00006841sv0000103Csd00001813* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7570M) pci:v00001002d00006841sv0000103Csd0000183A* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) pci:v00001002d00006841sv0000103Csd0000183C* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) pci:v00001002d00006841sv0000103Csd0000183E* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) pci:v00001002d00006841sv0000103Csd00001840* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) pci:v00001002d00006841sv0000103Csd00001842* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) pci:v00001002d00006841sv0000103Csd00001844* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) pci:v00001002d00006841sv00001043sd0000100A* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) pci:v00001002d00006841sv00001043sd0000104B* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) pci:v00001002d00006841sv00001043sd000010DC* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) pci:v00001002d00006841sv00001043sd00002134* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) pci:v00001002d00006841sv00001179sd00000001* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7570M) pci:v00001002d00006841sv00001179sd00000002* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7570M) pci:v00001002d00006841sv00001179sd0000FB43* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) pci:v00001002d00006841sv00001179sd0000FB91* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) pci:v00001002d00006841sv00001179sd0000FB92* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) pci:v00001002d00006841sv00001179sd0000FB93* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) pci:v00001002d00006841sv00001179sd0000FBA2* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) pci:v00001002d00006841sv00001179sd0000FBA3* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) pci:v00001002d00006841sv0000144Dsd0000C0C7* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) pci:v00001002d00006842* ID_MODEL_FROM_DATABASE=Thames LE [Radeon HD 7000M Series] pci:v00001002d00006843* ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7670M] pci:v00001002d00006888* ID_MODEL_FROM_DATABASE=Cypress XT [FirePro V8800] pci:v00001002d00006889* ID_MODEL_FROM_DATABASE=Cypress PRO [FirePro V7800] pci:v00001002d00006889sv00001002sd00000301* ID_MODEL_FROM_DATABASE=Cypress PRO [FirePro V7800] (FirePro V7800P) pci:v00001002d0000688A* ID_MODEL_FROM_DATABASE=Cypress XT [FirePro V9800] pci:v00001002d0000688Asv00001002sd0000030C* ID_MODEL_FROM_DATABASE=Cypress XT [FirePro V9800] (FirePro V9800P) pci:v00001002d0000688C* ID_MODEL_FROM_DATABASE=Cypress XT GL [FireStream 9370] pci:v00001002d0000688D* ID_MODEL_FROM_DATABASE=Cypress PRO GL [FireStream 9350] pci:v00001002d00006898* ID_MODEL_FROM_DATABASE=Cypress XT [Radeon HD 5870] pci:v00001002d00006898sv00001002sd00000B00* ID_MODEL_FROM_DATABASE=Cypress XT [Radeon HD 5870] (Radeon HD 5870 Eyefinity⁶ Edition) pci:v00001002d00006898sv0000106Bsd000000D0* ID_MODEL_FROM_DATABASE=Cypress XT [Radeon HD 5870] (Radeon HD 5870 Mac Edition) pci:v00001002d00006898sv00001462sd00008032* ID_MODEL_FROM_DATABASE=Cypress XT [Radeon HD 5870] (Radeon HD 5870 1 GB GDDR5) pci:v00001002d00006898sv0000174Bsd00006870* ID_MODEL_FROM_DATABASE=Cypress XT [Radeon HD 5870] (Radeon HD 6870 1600SP Edition) pci:v00001002d00006899* ID_MODEL_FROM_DATABASE=Cypress PRO [Radeon HD 5850] pci:v00001002d00006899sv00001043sd00000330* ID_MODEL_FROM_DATABASE=Cypress PRO [Radeon HD 5850] (Radeon HD 5850) pci:v00001002d00006899sv0000174Bsd0000237B* ID_MODEL_FROM_DATABASE=Cypress PRO [Radeon HD 5850] (Radeon HD 5850 X2) pci:v00001002d00006899sv0000174Bsd00006850* ID_MODEL_FROM_DATABASE=Cypress PRO [Radeon HD 5850] (Radeon HD 6850 1440SP Edition) pci:v00001002d0000689B* ID_MODEL_FROM_DATABASE=Cypress PRO [Radeon HD 6800 Series] pci:v00001002d0000689C* ID_MODEL_FROM_DATABASE=Hemlock [Radeon HD 5970] pci:v00001002d0000689Csv00001043sd00000352* ID_MODEL_FROM_DATABASE=Hemlock [Radeon HD 5970] (ARES) pci:v00001002d0000689D* ID_MODEL_FROM_DATABASE=Hemlock [Radeon HD 5970] pci:v00001002d0000689E* ID_MODEL_FROM_DATABASE=Cypress LE [Radeon HD 5830] pci:v00001002d000068A0* ID_MODEL_FROM_DATABASE=Broadway XT [Mobility Radeon HD 5870] pci:v00001002d000068A0sv00001028sd000012EF* ID_MODEL_FROM_DATABASE=Broadway XT [Mobility Radeon HD 5870] (FirePro M7820) pci:v00001002d000068A0sv0000103Csd00001520* ID_MODEL_FROM_DATABASE=Broadway XT [Mobility Radeon HD 5870] (FirePro M7820) pci:v00001002d000068A1* ID_MODEL_FROM_DATABASE=Broadway PRO [Mobility Radeon HD 5850] pci:v00001002d000068A1sv0000106Bsd000000CC* ID_MODEL_FROM_DATABASE=Broadway PRO [Mobility Radeon HD 5850] (iMac MC511 Mobility Radeon HD 5850 MXM Module) pci:v00001002d000068A8* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] pci:v00001002d000068A8sv00001025sd00000442* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001025sd00000451* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001025sd0000050A* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001025sd0000050B* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001025sd0000050C* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001025sd0000050E* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001025sd0000050F* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001025sd00000513* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001025sd00000514* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001025sd00000515* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001025sd00000516* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001025sd00000525* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001025sd00000526* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001025sd0000056D* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv00001028sd0000048F* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6870M) pci:v00001002d000068A8sv00001028sd00000490* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6870M) pci:v00001002d000068A8sv00001028sd000004B9* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6870M) pci:v00001002d000068A8sv00001028sd000004BA* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6870M) pci:v00001002d000068A8sv0000103Csd0000159B* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A8sv0000144Dsd0000C0AD* ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) pci:v00001002d000068A9* ID_MODEL_FROM_DATABASE=Juniper XT [FirePro V5800] pci:v00001002d000068B8* ID_MODEL_FROM_DATABASE=Juniper XT [Radeon HD 5770] pci:v00001002d000068B8sv0000106Bsd000000CF* ID_MODEL_FROM_DATABASE=Juniper XT [Radeon HD 5770] (MacPro5,1 [Mac Pro 2.8GHz DDR3]) pci:v00001002d000068B9* ID_MODEL_FROM_DATABASE=Juniper LE [Radeon HD 5670 640SP Edition] pci:v00001002d000068BA* ID_MODEL_FROM_DATABASE=Juniper XT [Radeon HD 6770] pci:v00001002d000068BE* ID_MODEL_FROM_DATABASE=Juniper PRO [Radeon HD 5750] pci:v00001002d000068BEsv0000148Csd00003000* ID_MODEL_FROM_DATABASE=Juniper PRO [Radeon HD 5750] (Radeon HD 6750) pci:v00001002d000068BF* ID_MODEL_FROM_DATABASE=Juniper PRO [Radeon HD 6750] pci:v00001002d000068BFsv0000174Bsd00006750* ID_MODEL_FROM_DATABASE=Juniper PRO [Radeon HD 6750] (Radeon HD 6750) pci:v00001002d000068C0* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] pci:v00001002d000068C0sv00001019sd00002383* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) pci:v00001002d000068C0sv00001028sd000002A2* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) pci:v00001002d000068C0sv00001028sd000002FE* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) pci:v00001002d000068C0sv00001028sd00000419* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) pci:v00001002d000068C0sv0000103Csd0000147D* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) pci:v00001002d000068C0sv0000103Csd00001521* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Madison XT [FirePro M5800]) pci:v00001002d000068C0sv0000103Csd00001593* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 6570) pci:v00001002d000068C0sv0000103Csd00001596* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 6570) pci:v00001002d000068C0sv0000103Csd00001599* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 6570) pci:v00001002d000068C0sv00001043sd00001C22* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) pci:v00001002d000068C0sv000017AAsd00003927* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) pci:v00001002d000068C0sv000017AAsd00003952* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) pci:v00001002d000068C0sv000017AAsd00003978* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Radeon HD 6570M) pci:v00001002d000068C1* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] pci:v00001002d000068C1sv00001025sd00000205* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000293* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000294* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000296* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000308* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000030A* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000311* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000312* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000031C* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000031D* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000033D* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000033E* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000033F* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000346* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000347* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Aspire 7740G) pci:v00001002d000068C1sv00001025sd00000348* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000356* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000357* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000358* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000359* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000035A* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000035B* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000035C* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000035D* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000035E* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000360* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000362* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000364* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000365* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000366* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000367* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000368* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000036C* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000036D* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000036E* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000036F* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000372* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000373* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000377* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000378* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000379* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000037A* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000037B* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000037E* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000037F* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000382* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000383* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000384* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000385* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000386* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000387* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000388* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000038B* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000038C* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000039A* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000411* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000412* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000418* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000419* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000420* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000421* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000425* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000042A* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000042E* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000042F* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000432* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000433* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000442* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000044C* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd0000044E* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000451* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000454* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000455* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000475* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000476* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000487* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000489* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000498* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001025sd00000517* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001025sd0000051A* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001025sd0000051B* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001025sd0000051C* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001025sd0000051D* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001025sd00000525* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001025sd00000526* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001025sd0000052B* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001025sd0000052C* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001025sd0000053C* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001025sd0000053D* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001025sd0000053E* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001025sd0000053F* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001025sd00000607* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C1sv00001028sd0000041B* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001028sd00000447* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001028sd00000448* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001028sd00000456* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001028sd00000457* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000103Csd00001436* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000103Csd00001437* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000103Csd00001440* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000103Csd00001448* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000103Csd00001449* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000103Csd0000144A* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000103Csd0000144B* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000103Csd0000147B* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000103Csd0000149C* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000103Csd0000149E* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000103Csd00001521* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Madison Pro [FirePro M5800]) pci:v00001002d000068C1sv00001043sd00001BC2* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000104Dsd00009071* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000104Dsd00009077* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000104Dsd00009081* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001179sd0000FD00* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001179sd0000FD12* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001179sd0000FD1A* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001179sd0000FD30* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001179sd0000FD31* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001179sd0000FD50* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001179sd0000FD52* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6530M) pci:v00001002d000068C1sv00001179sd0000FD63* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6530M) pci:v00001002d000068C1sv00001179sd0000FD65* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6530M) pci:v00001002d000068C1sv00001179sd0000FDD0* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv00001179sd0000FDD2* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6530M) pci:v00001002d000068C1sv0000144Dsd0000C07E* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv0000144Dsd0000C085* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv000014C0sd00000043* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv000014C0sd0000004D* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv000017AAsd00003928* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv000017AAsd00003951* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) pci:v00001002d000068C1sv000017AAsd00003977* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) pci:v00001002d000068C7* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5570/6550A] pci:v00001002d000068C7sv00001462sd00002241* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5570/6550A] (Mobility Radeon HD 5570) pci:v00001002d000068C7sv00001462sd00002243* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5570/6550A] (Mobility Radeon HD 5570) pci:v00001002d000068C7sv00001462sd00002244* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5570/6550A] (Mobility Radeon HD 5570) pci:v00001002d000068C7sv00001462sd00002245* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5570/6550A] (Radeon HD 6550A) pci:v00001002d000068C7sv00001462sd00002246* ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5570/6550A] (Radeon HD 6550A) pci:v00001002d000068C8* ID_MODEL_FROM_DATABASE=Redwood XT GL [FirePro V4800] pci:v00001002d000068C9* ID_MODEL_FROM_DATABASE=Redwood PRO GL [FirePro V3800] pci:v00001002d000068D8* ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] pci:v00001002d000068D8sv00001028sd000068E0* ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5670) pci:v00001002d000068D8sv0000174Bsd00005690* ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5690) pci:v00001002d000068D8sv0000174Bsd00005730* ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5730) pci:v00001002d000068D8sv0000174Bsd0000E151* ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5670) pci:v00001002d000068D8sv00001787sd00003000* ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5730) pci:v00001002d000068D8sv000017AFsd00003010* ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5730) pci:v00001002d000068D8sv000017AFsd00003011* ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5690) pci:v00001002d000068D9* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] pci:v00001002d000068D9sv0000103Csd00006870* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) pci:v00001002d000068D9sv0000103Csd00006872* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) pci:v00001002d000068D9sv00001043sd000003CE* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5550) pci:v00001002d000068D9sv00001462sd00002151* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) pci:v00001002d000068D9sv00001462sd00002240* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) pci:v00001002d000068D9sv0000148Csd00003000* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6510) pci:v00001002d000068D9sv0000148Csd00003001* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6610) pci:v00001002d000068D9sv00001545sd00005550* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5550) pci:v00001002d000068D9sv00001545sd00007570* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 7570) pci:v00001002d000068D9sv00001642sd00003985* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) pci:v00001002d000068D9sv00001642sd00003996* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) pci:v00001002d000068D9sv0000174Bsd00003000* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6510) pci:v00001002d000068D9sv0000174Bsd00006510* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6510) pci:v00001002d000068D9sv0000174Bsd00006610* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6610) pci:v00001002d000068D9sv0000174Bsd0000E142* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) pci:v00001002d000068D9sv00001787sd00003000* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6510) pci:v00001002d000068D9sv000017AFsd00003000* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6510) pci:v00001002d000068D9sv000017AFsd00003010* ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5630) pci:v00001002d000068DA* ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] pci:v00001002d000068DAsv0000148Csd00003000* ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 6390) pci:v00001002d000068DAsv0000148Csd00003001* ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 6490) pci:v00001002d000068DAsv00001545sd00007570* ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 7570) pci:v00001002d000068DAsv0000174Bsd00003000* ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 6390) pci:v00001002d000068DAsv0000174Bsd00005570* ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 5570) pci:v00001002d000068DAsv0000174Bsd00005630* ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 5630) pci:v00001002d000068DAsv0000174Bsd00006490* ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 6490) pci:v00001002d000068DAsv00001787sd00003000* ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 5630) pci:v00001002d000068DAsv000017AFsd00003000* ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 6390) pci:v00001002d000068DAsv000017AFsd00003010* ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 5630) pci:v00001002d000068DE* ID_MODEL_FROM_DATABASE=Redwood pci:v00001002d000068E0* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] pci:v00001002d000068E0sv00001028sd00000404* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) pci:v00001002d000068E0sv00001028sd00000414* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) pci:v00001002d000068E0sv00001028sd00000434* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) pci:v00001002d000068E0sv0000103Csd00001433* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) pci:v00001002d000068E0sv0000103Csd00001434* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) pci:v00001002d000068E0sv0000103Csd00001469* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) pci:v00001002d000068E0sv0000103Csd0000146B* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) pci:v00001002d000068E0sv0000103Csd00001486* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (TouchSmart tm2-2050er discrete GPU (Mobility Radeon HD 5450)) pci:v00001002d000068E0sv0000103Csd00001622* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) pci:v00001002d000068E0sv0000103Csd00001623* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) pci:v00001002d000068E0sv0000103Csd0000EEEE* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) pci:v00001002d000068E0sv0000104Dsd00009076* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) pci:v00001002d000068E0sv00001682sd0000304E* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Caicos [Radeon HD 5450]) pci:v00001002d000068E0sv00001682sd00006000* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Caicos [Radeon HD 5450]) pci:v00001002d000068E0sv000017AAsd00009E52* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (FirePro M3800) pci:v00001002d000068E0sv000017AAsd00009E53* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (FirePro M3800) pci:v00001002d000068E1* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] pci:v00001002d000068E1sv00001043sd0000041F* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 7350]) pci:v00001002d000068E1sv00001043sd00003000* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) pci:v00001002d000068E1sv0000148Csd00003000* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) pci:v00001002d000068E1sv0000148Csd00003001* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6230]) pci:v00001002d000068E1sv0000148Csd00003002* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6250]) pci:v00001002d000068E1sv0000148Csd00003003* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6350]) pci:v00001002d000068E1sv0000148Csd00007350* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 7350]) pci:v00001002d000068E1sv0000148Csd00008350* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 8350]) pci:v00001002d000068E1sv00001545sd00005450* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) pci:v00001002d000068E1sv00001545sd00007350* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 7350]) pci:v00001002d000068E1sv00001682sd00003000* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) pci:v00001002d000068E1sv00001682sd00006000* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) pci:v00001002d000068E1sv00001682sd00007350* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 7350]) pci:v00001002d000068E1sv0000174Bsd00003000* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) pci:v00001002d000068E1sv0000174Bsd00005470* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5470]) pci:v00001002d000068E1sv0000174Bsd00006000* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) pci:v00001002d000068E1sv0000174Bsd00006230* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6230]) pci:v00001002d000068E1sv0000174Bsd00006350* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6350]) pci:v00001002d000068E1sv0000174Bsd00007350* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 7350]) pci:v00001002d000068E1sv00001787sd00003000* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) pci:v00001002d000068E1sv000017AFsd00003000* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) pci:v00001002d000068E1sv000017AFsd00003001* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6230]) pci:v00001002d000068E1sv000017AFsd00003014* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6350]) pci:v00001002d000068E1sv000017AFsd00003015* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 7350]) pci:v00001002d000068E1sv000017AFsd00008350* ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 8350 OEM]) pci:v00001002d000068E4* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] pci:v00001002d000068E4sv00001019sd00002386* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6350M) pci:v00001002d000068E4sv00001019sd00002387* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6350M) pci:v00001002d000068E4sv00001019sd0000238D* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001019sd0000238E* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001025sd00000382* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001025sd00000489* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001025sd0000048A* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001025sd0000048B* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001025sd0000048C* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001028sd000004C1* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001028sd000004CA* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001028sd000004CC* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001028sd000004CD* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001028sd000004D7* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd00001411* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd00001421* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd00001426* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd00001428* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000142A* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000142B* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000143A* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000143C* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd00001445* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000162C* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000162D* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000162E* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000162F* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd00001639* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000163A* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000163B* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000163C* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000163D* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000163E* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000163F* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd00001641* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd00001643* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd00003578* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd0000357A* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd00003673* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000103Csd00003675* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001043sd00001C92* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001043sd000084A1* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001043sd000084AD* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000104Dsd00009081* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001545sd00007350* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Cedar [Radeon HD 7350]) pci:v00001002d000068E4sv00001558sd00004510* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv00001558sd00005505* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv0000174Bsd00005450* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Cedar [Radeon HD 5450]) pci:v00001002d000068E4sv000017AAsd000021DD* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv000017AAsd000021E9* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv000017AAsd00003971* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) pci:v00001002d000068E4sv000017AAsd00003972* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 7370M) pci:v00001002d000068E4sv000017AAsd0000397A* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M/7370M) pci:v00001002d000068E4sv000017AAsd0000397B* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M/7370M) pci:v00001002d000068E4sv000017AAsd0000397F* ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 7370M) pci:v00001002d000068E5* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] pci:v00001002d000068E5sv00001179sd0000FD3C* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) pci:v00001002d000068E5sv00001179sd0000FD50* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) pci:v00001002d000068E5sv00001179sd0000FD52* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) pci:v00001002d000068E5sv00001179sd0000FD63* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) pci:v00001002d000068E5sv00001179sd0000FD65* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) pci:v00001002d000068E5sv00001179sd0000FD73* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) pci:v00001002d000068E5sv00001179sd0000FD75* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) pci:v00001002d000068E5sv00001179sd0000FDD0* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) pci:v00001002d000068E5sv00001179sd0000FDD2* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) pci:v00001002d000068E5sv00001179sd0000FDEA* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) pci:v00001002d000068E5sv00001179sd0000FDF8* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) pci:v00001002d000068E5sv0000148Csd00005450* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Cedar [Radeon HD 5450]) pci:v00001002d000068E5sv0000148Csd00006350* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Cedar [Radeon HD 6350]) pci:v00001002d000068E5sv0000148Csd00007350* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Cedar [Radeon HD 7350]) pci:v00001002d000068E5sv0000148Csd00008350* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Cedar [Radeon HD 8350]) pci:v00001002d000068E5sv00001545sd00007350* ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Cedar [Radeon HD 7350]) pci:v00001002d000068E8* ID_MODEL_FROM_DATABASE=Cedar pci:v00001002d000068E9* ID_MODEL_FROM_DATABASE=Cedar [ATI FirePro (FireGL) Graphics Adapter] pci:v00001002d000068F1* ID_MODEL_FROM_DATABASE=Cedar GL [FirePro 2460] pci:v00001002d000068F2* ID_MODEL_FROM_DATABASE=Cedar GL [FirePro 2270] pci:v00001002d000068F8* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7300 Series] pci:v00001002d000068F9* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] pci:v00001002d000068F9sv00001019sd00000001* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001019sd00000002* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001019sd00000019* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) pci:v00001002d000068F9sv00001025sd00000518* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001025sd00000519* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001028sd0000010E* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (XPS 8300) pci:v00001002d000068F9sv00001028sd00002126* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) pci:v00001002d000068F9sv0000103Csd00002126* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) pci:v00001002d000068F9sv0000103Csd00002AAC* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv0000103Csd00002AAE* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv0000103Csd00003580* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001043sd00000386* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001043sd000003C2* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (EAH5450 SILENT/DI/512MD2 (LP)) pci:v00001002d000068F9sv00001462sd00002130* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001462sd00002131* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001462sd00002133* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) pci:v00001002d000068F9sv00001462sd00002180* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001462sd00002181* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001462sd00002182* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) pci:v00001002d000068F9sv00001462sd00002183* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) pci:v00001002d000068F9sv00001462sd00002230* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001462sd00002231* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001462sd00002495* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) pci:v00001002d000068F9sv0000148Csd00003001* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5530/6250) pci:v00001002d000068F9sv0000148Csd00003002* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6290) pci:v00001002d000068F9sv0000148Csd00003003* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6230) pci:v00001002d000068F9sv0000148Csd00003004* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) pci:v00001002d000068F9sv0000148Csd00007350* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 7350) pci:v00001002d000068F9sv0000148Csd00008350* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 8350) pci:v00001002d000068F9sv00001545sd00007350* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 7350) pci:v00001002d000068F9sv00001642sd00003983* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001642sd00003984* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) pci:v00001002d000068F9sv00001642sd00003987* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) pci:v00001002d000068F9sv00001642sd00003997* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001642sd00003A05* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001642sd00003B31* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350A) pci:v00001002d000068F9sv00001682sd00003270* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 7350) pci:v00001002d000068F9sv0000174Bsd00003000* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6230) pci:v00001002d000068F9sv0000174Bsd00003987* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) pci:v00001002d000068F9sv0000174Bsd00005470* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5470) pci:v00001002d000068F9sv0000174Bsd00005490* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5490) pci:v00001002d000068F9sv0000174Bsd00005530* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5530) pci:v00001002d000068F9sv0000174Bsd00006230* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6230) pci:v00001002d000068F9sv0000174Bsd00006250* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6250) pci:v00001002d000068F9sv0000174Bsd00006290* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6290) pci:v00001002d000068F9sv0000174Bsd00006350* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) pci:v00001002d000068F9sv0000174Bsd00007350* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 7350) pci:v00001002d000068F9sv0000174Bsd00008350* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 8350) pci:v00001002d000068F9sv0000174Bsd0000E127* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv0000174Bsd0000E145* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv0000174Bsd0000E153* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv00001787sd00003000* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5470) pci:v00001002d000068F9sv00001787sd00003001* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5530) pci:v00001002d000068F9sv00001787sd00003002* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5490) pci:v00001002d000068F9sv000017AAsd00003602* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv000017AAsd00003603* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv000017AAsd0000360F* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv000017AAsd00003619* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) pci:v00001002d000068F9sv000017AFsd00003000* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6250) pci:v00001002d000068F9sv000017AFsd00003001* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6230) pci:v00001002d000068F9sv000017AFsd00003002* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6290) pci:v00001002d000068F9sv000017AFsd00003011* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5470) pci:v00001002d000068F9sv000017AFsd00003012* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5490) pci:v00001002d000068F9sv000017AFsd00003013* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5470) pci:v00001002d000068F9sv000017AFsd00003014* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) pci:v00001002d000068FA* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] pci:v00001002d000068FAsv00001019sd00000019* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FAsv00001019sd00000021* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FAsv00001019sd00000022* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FAsv00001019sd00000026* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 8350) pci:v00001002d000068FAsv0000103Csd00002ADF* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350A) pci:v00001002d000068FAsv0000103Csd00002AE8* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350A) pci:v00001002d000068FAsv00001043sd00008350* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 8350) pci:v00001002d000068FAsv00001462sd00002128* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FAsv00001462sd00002184* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FAsv00001462sd00002186* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FAsv00001462sd00002495* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FAsv00001462sd0000B490* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FAsv00001642sd00003985* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FAsv0000174Bsd00003510* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 8350) pci:v00001002d000068FAsv0000174Bsd00003521* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon R5 220) pci:v00001002d000068FAsv0000174Bsd00003522* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon R5 220) pci:v00001002d000068FAsv0000174Bsd00007350* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FAsv0000174Bsd00008153* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 8350) pci:v00001002d000068FAsv0000174Bsd0000E127* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FAsv0000174Bsd0000E153* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FAsv0000174Bsd0000E180* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FAsv000017AFsd00003015* ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) pci:v00001002d000068FE* ID_MODEL_FROM_DATABASE=Cedar LE pci:v00001002d00006900* ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265] pci:v00001002d00006900sv00001028sd00000640* ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265] (Radeon R7 M265) pci:v00001002d00006900sv0000103Csd00002269* ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265] (Radeon R7 M260) pci:v00001002d00006900sv0000103Csd000022C8* ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265] (Radeon R7 M260) pci:v00001002d00006900sv00001179sd0000F903* ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265] (Radeon R7 M260) pci:v00001002d00006900sv00001179sd0000F934* ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265] (Radeon R7 M260) pci:v00001002d00006901* ID_MODEL_FROM_DATABASE=Topaz PRO [Radeon R5 M255] pci:v00001002d00006921* ID_MODEL_FROM_DATABASE=Amethyst XT [Radeon R9 M295X] pci:v00001002d00006929* ID_MODEL_FROM_DATABASE=Tonga XT GL [FirePro S7150] pci:v00001002d0000692B* ID_MODEL_FROM_DATABASE=Tonga PRO GL [FirePro W7100] pci:v00001002d0000692F* ID_MODEL_FROM_DATABASE=Tonga XTV GL [FirePro S7150V] pci:v00001002d00006938* ID_MODEL_FROM_DATABASE=Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X Mac Edition] pci:v00001002d00006938sv0000174Bsd0000E308* ID_MODEL_FROM_DATABASE=Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X Mac Edition] (Radeon R9 380X Nitro 4G D5) pci:v00001002d00006939* ID_MODEL_FROM_DATABASE=Tonga PRO [Radeon R9 285/380] pci:v00001002d00006939sv0000148Csd00009380* ID_MODEL_FROM_DATABASE=Tonga PRO [Radeon R9 285/380] (Radeon R9 380) pci:v00001002d00006939sv0000174Bsd0000E308* ID_MODEL_FROM_DATABASE=Tonga PRO [Radeon R9 285/380] (Radeon R9 380 Nitro 4G D5) pci:v00001002d0000700F* ID_MODEL_FROM_DATABASE=RS100 AGP Bridge pci:v00001002d00007010* ID_MODEL_FROM_DATABASE=RS200/RS250 AGP Bridge pci:v00001002d00007100* ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 XT] pci:v00001002d00007101* ID_MODEL_FROM_DATABASE=R520/M58 [Mobility Radeon X1800 XT] pci:v00001002d00007102* ID_MODEL_FROM_DATABASE=R520/M58 [Mobility Radeon X1800] pci:v00001002d00007104* ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7200] pci:v00001002d00007109* ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 XL] pci:v00001002d00007109sv00001002sd00000322* ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 XL] (All-in-Wonder X1800XL) pci:v00001002d00007109sv00001002sd00000D02* ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 XL] (Radeon X1800 CrossFire Edition) pci:v00001002d0000710A* ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 GTO] pci:v00001002d0000710Asv00001002sd00000B12* ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 GTO] (Radeon X1800 GTO²) pci:v00001002d0000710B* ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 GTO] pci:v00001002d00007120* ID_MODEL_FROM_DATABASE=R520 [Radeon X1800] (Secondary) pci:v00001002d00007124* ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7200] (Secondary) pci:v00001002d00007129* ID_MODEL_FROM_DATABASE=R520 [Radeon X1800] (Secondary) pci:v00001002d00007129sv00001002sd00000323* ID_MODEL_FROM_DATABASE=R520 [Radeon X1800] (Secondary) (All-In-Wonder X1800 XL (Secondary)) pci:v00001002d00007129sv00001002sd00000D03* ID_MODEL_FROM_DATABASE=R520 [Radeon X1800] (Secondary) (Radeon X1800 CrossFire Edition (Secondary)) pci:v00001002d00007140* ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550/X1600 Series] pci:v00001002d00007142* ID_MODEL_FROM_DATABASE=RV515 PRO [Radeon X1300/X1550 Series] pci:v00001002d00007142sv00001002sd00000322* ID_MODEL_FROM_DATABASE=RV515 PRO [Radeon X1300/X1550 Series] (All-in-Wonder 2006 PCI-E Edition) pci:v00001002d00007142sv00001043sd00000142* ID_MODEL_FROM_DATABASE=RV515 PRO [Radeon X1300/X1550 Series] (EAX1300PRO/TD/256M) pci:v00001002d00007143* ID_MODEL_FROM_DATABASE=RV505 [Radeon X1300/X1550 Series] pci:v00001002d00007145* ID_MODEL_FROM_DATABASE=RV515/M54 [Mobility Radeon X1400] pci:v00001002d00007145sv000017AAsd00002006* ID_MODEL_FROM_DATABASE=RV515/M54 [Mobility Radeon X1400] (Thinkpad T60 model 2007) pci:v00001002d00007146* ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550] pci:v00001002d00007146sv00001002sd00000322* ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550] (All-in-Wonder 2006 PCI-E Edition) pci:v00001002d00007146sv00001545sd00001996* ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550] (Radeon X1300 512MB PCI-e) pci:v00001002d00007147* ID_MODEL_FROM_DATABASE=RV505 [Radeon X1550 64-bit] pci:v00001002d00007149* ID_MODEL_FROM_DATABASE=RV515/M52 [Mobility Radeon X1300] pci:v00001002d0000714A* ID_MODEL_FROM_DATABASE=RV515/M52 [Mobility Radeon X1300] pci:v00001002d00007152* ID_MODEL_FROM_DATABASE=RV515 GL [FireGL V3300] pci:v00001002d00007153* ID_MODEL_FROM_DATABASE=RV515 GL [FireGL V3350] pci:v00001002d0000715F* ID_MODEL_FROM_DATABASE=RV505 CE [Radeon X1550 64-bit] pci:v00001002d00007162* ID_MODEL_FROM_DATABASE=RV515 PRO [Radeon X1300/X1550 Series] (Secondary) pci:v00001002d00007162sv00001002sd00000323* ID_MODEL_FROM_DATABASE=RV515 PRO [Radeon X1300/X1550 Series] (Secondary) (All-in-Wonder 2006 PCI-E Edition (Secondary)) pci:v00001002d00007163* ID_MODEL_FROM_DATABASE=RV505 [Radeon X1550 Series] (Secondary) pci:v00001002d00007166* ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550 Series] (Secondary) pci:v00001002d00007166sv00001002sd00000323* ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550 Series] (Secondary) (All-in-Wonder 2006 PCI-E Edition (Secondary)) pci:v00001002d00007166sv00001545sd00001997* ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550 Series] (Secondary) (Radeon X1300 512MB PCI-e (Secondary)) pci:v00001002d00007167* ID_MODEL_FROM_DATABASE=RV515 [Radeon X1550 64-bit] (Secondary) pci:v00001002d00007172* ID_MODEL_FROM_DATABASE=RV515 GL [FireGL V3300] (Secondary) pci:v00001002d00007173* ID_MODEL_FROM_DATABASE=RV515 GL [FireGL V3350] (Secondary) pci:v00001002d00007181* ID_MODEL_FROM_DATABASE=RV516 [Radeon X1600/X1650 Series] pci:v00001002d00007183* ID_MODEL_FROM_DATABASE=RV516 [Radeon X1300/X1550 Series] pci:v00001002d00007186* ID_MODEL_FROM_DATABASE=RV516/M64 [Mobility Radeon X1450] pci:v00001002d00007187* ID_MODEL_FROM_DATABASE=RV516 [Radeon X1300/X1550 Series] pci:v00001002d00007188* ID_MODEL_FROM_DATABASE=RV516/M64-S [Mobility Radeon X2300] pci:v00001002d00007188sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=RV516/M64-S [Mobility Radeon X2300] (6910p) pci:v00001002d0000718A* ID_MODEL_FROM_DATABASE=RV516/M64 [Mobility Radeon X2300] pci:v00001002d0000718B* ID_MODEL_FROM_DATABASE=RV516/M62 [Mobility Radeon X1350] pci:v00001002d0000718Bsv00001071sd00008209* ID_MODEL_FROM_DATABASE=RV516/M62 [Mobility Radeon X1350] (Medion MIM 2240 Notebook PC [MD98100]) pci:v00001002d0000718C* ID_MODEL_FROM_DATABASE=RV516/M62-CSP64 [Mobility Radeon X1350] pci:v00001002d0000718D* ID_MODEL_FROM_DATABASE=RV516/M64-CSP128 [Mobility Radeon X1450] pci:v00001002d00007193* ID_MODEL_FROM_DATABASE=RV516 [Radeon X1550 Series] pci:v00001002d00007196* ID_MODEL_FROM_DATABASE=RV516/M62-S [Mobility Radeon X1350] pci:v00001002d0000719B* ID_MODEL_FROM_DATABASE=RV516 GL [FireMV 2250] pci:v00001002d0000719F* ID_MODEL_FROM_DATABASE=RV516 [Radeon X1550 Series] pci:v00001002d000071A0* ID_MODEL_FROM_DATABASE=RV516 [Radeon X1300/X1550 Series] (Secondary) pci:v00001002d000071A1* ID_MODEL_FROM_DATABASE=RV516 [Radeon X1600/X1650 Series] (Secondary) pci:v00001002d000071A3* ID_MODEL_FROM_DATABASE=RV516 [Radeon X1300/X1550 Series] (Secondary) pci:v00001002d000071A7* ID_MODEL_FROM_DATABASE=RV516 [Radeon X1300/X1550 Series] (Secondary) pci:v00001002d000071BB* ID_MODEL_FROM_DATABASE=RV516 GL [FireMV 2250] (Secondary) pci:v00001002d000071C0* ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600 XT/X1650 GTO] pci:v00001002d000071C0sv00001002sd0000E160* ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600 XT/X1650 GTO] (Radeon X1650 GTO) pci:v00001002d000071C0sv0000174Bsd0000E160* ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600 XT/X1650 GTO] (Radeon X1650 GTO) pci:v00001002d000071C1* ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] pci:v00001002d000071C1sv0000174Bsd00000880* ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] (Radeon X1700 FSC) pci:v00001002d000071C2* ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600 PRO] pci:v00001002d000071C4* ID_MODEL_FROM_DATABASE=RV530/M56 GL [Mobility FireGL V5200] pci:v00001002d000071C4sv000017AAsd00002007* ID_MODEL_FROM_DATABASE=RV530/M56 GL [Mobility FireGL V5200] (ThinkPad T60p) pci:v00001002d000071C5* ID_MODEL_FROM_DATABASE=RV530/M56-P [Mobility Radeon X1600] pci:v00001002d000071C5sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=RV530/M56-P [Mobility Radeon X1600] (Compaq nx9420 Notebook) pci:v00001002d000071C5sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=RV530/M56-P [Mobility Radeon X1600] (Compaq NW8440) pci:v00001002d000071C5sv00001043sd000010B2* ID_MODEL_FROM_DATABASE=RV530/M56-P [Mobility Radeon X1600] (A6J-Q008) pci:v00001002d000071C5sv0000106Bsd00000080* ID_MODEL_FROM_DATABASE=RV530/M56-P [Mobility Radeon X1600] (MacBook Pro) pci:v00001002d000071C6* ID_MODEL_FROM_DATABASE=RV530LE [Radeon X1600/X1650 PRO] pci:v00001002d000071C7* ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] pci:v00001002d000071C7sv00001787sd00003000* ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] (PowerColor X1650 PRO AGP) pci:v00001002d000071CE* ID_MODEL_FROM_DATABASE=RV530 [Radeon X1300 XT/X1600 PRO] pci:v00001002d000071D2* ID_MODEL_FROM_DATABASE=RV530 GL [FireGL V3400] pci:v00001002d000071D4* ID_MODEL_FROM_DATABASE=RV530/M66 GL [Mobility FireGL V5250] pci:v00001002d000071D5* ID_MODEL_FROM_DATABASE=RV530/M66-P [Mobility Radeon X1700] pci:v00001002d000071D6* ID_MODEL_FROM_DATABASE=RV530/M66-XT [Mobility Radeon X1700] pci:v00001002d000071DE* ID_MODEL_FROM_DATABASE=RV530/M66 [Mobility Radeon X1700/X2500] pci:v00001002d000071E0* ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600] (Secondary) pci:v00001002d000071E0sv0000174Bsd0000E161* ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600] (Secondary) (Radeon X1600 GTO (Secondary)) pci:v00001002d000071E1* ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] (Secondary) pci:v00001002d000071E1sv0000174Bsd00000881* ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] (Secondary) (Radeon X1700 FSC (Secondary)) pci:v00001002d000071E2* ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600] (Secondary) pci:v00001002d000071E6* ID_MODEL_FROM_DATABASE=RV530 [Radeon X1650] (Secondary) pci:v00001002d000071E7* ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] (Secondary) pci:v00001002d000071E7sv00001787sd00003001* ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] (Secondary) (Radeon X1650 PRO AGP) pci:v00001002d000071F2* ID_MODEL_FROM_DATABASE=RV530 GL [FireGL V3400] (Secondary) pci:v00001002d00007210* ID_MODEL_FROM_DATABASE=RV550/M71 [Mobility Radeon HD 2300] pci:v00001002d00007211* ID_MODEL_FROM_DATABASE=RV550/M71 [Mobility Radeon X2300 HD] pci:v00001002d00007240* ID_MODEL_FROM_DATABASE=R580+ [Radeon X1950 XTX] pci:v00001002d00007240sv00001002sd00000D02* ID_MODEL_FROM_DATABASE=R580+ [Radeon X1950 XTX] (Radeon X1950 CrossFire Edition) pci:v00001002d00007244* ID_MODEL_FROM_DATABASE=R580+ [Radeon X1950 XT] pci:v00001002d00007248* ID_MODEL_FROM_DATABASE=R580 [Radeon X1950] pci:v00001002d00007249* ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 XT] pci:v00001002d00007249sv00001002sd00000412* ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 XT] (All-In-Wonder X1900) pci:v00001002d00007249sv00001002sd00000B12* ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 XT] (Radeon X1900 XT/XTX) pci:v00001002d00007249sv00001002sd00000D02* ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 XT] (Radeon X1900 CrossFire Edition) pci:v00001002d00007249sv00001043sd00000160* ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 XT] (Radeon X1900 XTX 512 MB GDDR3) pci:v00001002d0000724B* ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 GT] pci:v00001002d0000724Bsv00001002sd00000B12* ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 GT] (Radeon X1900 (Primary)) pci:v00001002d0000724Bsv00001002sd00000B13* ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 GT] (Radeon X1900 (Secondary)) pci:v00001002d0000724E* ID_MODEL_FROM_DATABASE=R580 GL [FireGL V7350] pci:v00001002d00007269* ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 XT] (Secondary) pci:v00001002d0000726B* ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 GT] (Secondary) pci:v00001002d0000726E* ID_MODEL_FROM_DATABASE=R580 [AMD Stream Processor] (Secondary) pci:v00001002d00007280* ID_MODEL_FROM_DATABASE=RV570 [Radeon X1950 PRO] pci:v00001002d00007288* ID_MODEL_FROM_DATABASE=RV570 [Radeon X1950 GT] pci:v00001002d00007291* ID_MODEL_FROM_DATABASE=RV560 [Radeon X1650 XT] pci:v00001002d00007291sv00001462sd00000810* ID_MODEL_FROM_DATABASE=RV560 [Radeon X1650 XT] (Radeon X1700 SE) pci:v00001002d00007293* ID_MODEL_FROM_DATABASE=RV560 [Radeon X1650 GT] pci:v00001002d000072A0* ID_MODEL_FROM_DATABASE=RV570 [Radeon X1950 PRO] (Secondary) pci:v00001002d000072A8* ID_MODEL_FROM_DATABASE=RV570 [Radeon X1950 GT] (Secondary) pci:v00001002d000072B1* ID_MODEL_FROM_DATABASE=RV560 [Radeon X1650 XT] (Secondary) pci:v00001002d000072B3* ID_MODEL_FROM_DATABASE=RV560 [Radeon X1650 GT] (Secondary) pci:v00001002d00007300* ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] pci:v00001002d00007300sv00001002sd00000B36* ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] (Radeon R9 FURY X / NANO) pci:v00001002d00007300sv00001043sd0000049E* ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] (Radeon R9 FURY) pci:v00001002d00007300sv00001043sd000004A0* ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] (Radeon R9 FURY X) pci:v00001002d00007300sv0000174Bsd0000E329* ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] (Radeon R9 FURY) pci:v00001002d00007833* ID_MODEL_FROM_DATABASE=RS350 Host Bridge pci:v00001002d00007834* ID_MODEL_FROM_DATABASE=RS350 [Radeon 9100 PRO/XT IGP] pci:v00001002d00007835* ID_MODEL_FROM_DATABASE=RS350M [Mobility Radeon 9000 IGP] pci:v00001002d00007838* ID_MODEL_FROM_DATABASE=RS350 AGP Bridge pci:v00001002d00007910* ID_MODEL_FROM_DATABASE=RS690 Host Bridge pci:v00001002d00007910sv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=RS690 Host Bridge (Satellite P305D-S8995E) pci:v00001002d00007910sv000017F2sd00005000* ID_MODEL_FROM_DATABASE=RS690 Host Bridge (KI690-AM2 Motherboard) pci:v00001002d00007911* ID_MODEL_FROM_DATABASE=RS690 Host Bridge pci:v00001002d00007912* ID_MODEL_FROM_DATABASE=RS690 PCI to PCI Bridge (Internal gfx) pci:v00001002d00007913* ID_MODEL_FROM_DATABASE=RS690 PCI to PCI Bridge (PCI Express Graphics Port 0) pci:v00001002d00007915* ID_MODEL_FROM_DATABASE=RS690 PCI to PCI Bridge (PCI Express Port 1) pci:v00001002d00007916* ID_MODEL_FROM_DATABASE=RS690 PCI to PCI Bridge (PCI Express Port 2) pci:v00001002d00007917* ID_MODEL_FROM_DATABASE=RS690 PCI to PCI Bridge (PCI Express Port 3) pci:v00001002d00007917sv00001002sd00007910* ID_MODEL_FROM_DATABASE=RS690 PCI to PCI Bridge (PCI Express Port 3) (RS690 PCI to PCI Bridge) pci:v00001002d00007919* ID_MODEL_FROM_DATABASE=RS690 HDMI Audio [Radeon Xpress 1200 Series] pci:v00001002d00007919sv00001179sd00007919* ID_MODEL_FROM_DATABASE=RS690 HDMI Audio [Radeon Xpress 1200 Series] (Satellite P305D-S8995E) pci:v00001002d00007919sv000017F2sd00005000* ID_MODEL_FROM_DATABASE=RS690 HDMI Audio [Radeon Xpress 1200 Series] (KI690-AM2 Motherboard) pci:v00001002d0000791E* ID_MODEL_FROM_DATABASE=RS690 [Radeon X1200] pci:v00001002d0000791Esv00001462sd00007327* ID_MODEL_FROM_DATABASE=RS690 [Radeon X1200] (K9AG Neo2) pci:v00001002d0000791Esv000017F2sd00005000* ID_MODEL_FROM_DATABASE=RS690 [Radeon X1200] (KI690-AM2 Motherboard) pci:v00001002d0000791F* ID_MODEL_FROM_DATABASE=RS690M [Radeon Xpress 1200/1250/1270] pci:v00001002d0000791Fsv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=RS690M [Radeon Xpress 1200/1250/1270] (Satellite P305D-S8995E) pci:v00001002d00007930* ID_MODEL_FROM_DATABASE=RS600 Host Bridge pci:v00001002d00007932* ID_MODEL_FROM_DATABASE=RS600 PCI to PCI Bridge (Internal gfx) pci:v00001002d00007933* ID_MODEL_FROM_DATABASE=RS600 PCI to PCI Bridge (PCI Express Graphics Port 0) pci:v00001002d00007935* ID_MODEL_FROM_DATABASE=RS600 PCI to PCI Bridge (PCI Express Port 1) pci:v00001002d00007936* ID_MODEL_FROM_DATABASE=RS600 PCI to PCI Bridge (PCI Express Port 2) pci:v00001002d00007937* ID_MODEL_FROM_DATABASE=RS690 PCI to PCI Bridge (PCI Express Port 3) pci:v00001002d0000793B* ID_MODEL_FROM_DATABASE=RS600 HDMI Audio [Radeon Xpress 1250] pci:v00001002d0000793F* ID_MODEL_FROM_DATABASE=RS690M [Radeon Xpress 1200/1250/1270] (Secondary) pci:v00001002d00007941* ID_MODEL_FROM_DATABASE=RS600 [Radeon Xpress 1250] pci:v00001002d00007942* ID_MODEL_FROM_DATABASE=RS600M [Radeon Xpress 1250] pci:v00001002d0000796E* ID_MODEL_FROM_DATABASE=RS740 [Radeon 2100] pci:v00001002d00009400* ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 PRO/XT] pci:v00001002d00009400sv00001002sd00002552* ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 PRO/XT] (Radeon HD 2900 XT) pci:v00001002d00009400sv00001002sd00003000* ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 PRO/XT] (Radeon HD 2900 PRO) pci:v00001002d00009400sv00001002sd00003142* ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 PRO/XT] (HIS Radeon HD 2900XT 512MB GDDR3 VIVO PCIe) pci:v00001002d00009401* ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 XT] pci:v00001002d00009403* ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 PRO] pci:v00001002d00009405* ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 GT] pci:v00001002d0000940A* ID_MODEL_FROM_DATABASE=R600 GL [FireGL V8650] pci:v00001002d0000940B* ID_MODEL_FROM_DATABASE=R600 GL [FireGL V8600] pci:v00001002d0000940F* ID_MODEL_FROM_DATABASE=R600 GL [FireGL V7600] pci:v00001002d00009440* ID_MODEL_FROM_DATABASE=RV770 [Radeon HD 4870] pci:v00001002d00009441* ID_MODEL_FROM_DATABASE=R700 [Radeon HD 4870 X2] pci:v00001002d00009442* ID_MODEL_FROM_DATABASE=RV770 [Radeon HD 4850] pci:v00001002d00009442sv00001002sd00000502* ID_MODEL_FROM_DATABASE=RV770 [Radeon HD 4850] (MSI Radeon HD 4850 512MB GDDR3) pci:v00001002d00009442sv0000174Bsd0000E810* ID_MODEL_FROM_DATABASE=RV770 [Radeon HD 4850] (Radeon HD 4850 512MB GDDR3) pci:v00001002d00009443* ID_MODEL_FROM_DATABASE=R700 [Radeon HD 4850 X2] pci:v00001002d00009444* ID_MODEL_FROM_DATABASE=RV770 GL [FirePro V8750] pci:v00001002d00009446* ID_MODEL_FROM_DATABASE=RV770 GL [FirePro V7760] pci:v00001002d0000944A* ID_MODEL_FROM_DATABASE=RV770/M98L [Mobility Radeon HD 4850] pci:v00001002d0000944B* ID_MODEL_FROM_DATABASE=RV770/M98 [Mobility Radeon HD 4850 X2] pci:v00001002d0000944C* ID_MODEL_FROM_DATABASE=RV770 LE [Radeon HD 4830] pci:v00001002d0000944E* ID_MODEL_FROM_DATABASE=RV770 CE [Radeon HD 4710] pci:v00001002d0000944Esv0000174Bsd00003261* ID_MODEL_FROM_DATABASE=RV770 CE [Radeon HD 4710] (Radeon HD 4810) pci:v00001002d00009450* ID_MODEL_FROM_DATABASE=RV770 GL [FireStream 9270] pci:v00001002d00009452* ID_MODEL_FROM_DATABASE=RV770 GL [FireStream 9250] pci:v00001002d00009456* ID_MODEL_FROM_DATABASE=RV770 GL [FirePro V8700] pci:v00001002d0000945A* ID_MODEL_FROM_DATABASE=RV770/M98-XT [Mobility Radeon HD 4870] pci:v00001002d00009460* ID_MODEL_FROM_DATABASE=RV790 [Radeon HD 4890] pci:v00001002d00009462* ID_MODEL_FROM_DATABASE=RV790 [Radeon HD 4860] pci:v00001002d0000946A* ID_MODEL_FROM_DATABASE=RV770 GL [FirePro M7750] pci:v00001002d00009480* ID_MODEL_FROM_DATABASE=RV730/M96 [Mobility Radeon HD 4650/5165] pci:v00001002d00009480sv0000103Csd00003628* ID_MODEL_FROM_DATABASE=RV730/M96 [Mobility Radeon HD 4650/5165] (Mobility Radeon HD 4650 [dv6-1190en]) pci:v00001002d00009488* ID_MODEL_FROM_DATABASE=RV730/M96-XT [Mobility Radeon HD 4670] pci:v00001002d00009489* ID_MODEL_FROM_DATABASE=RV730/M96 GL [Mobility FireGL V5725] pci:v00001002d00009490* ID_MODEL_FROM_DATABASE=RV730 XT [Radeon HD 4670] pci:v00001002d00009490sv0000174Bsd0000E880* ID_MODEL_FROM_DATABASE=RV730 XT [Radeon HD 4670] (Radeon HD 4670 512MB GDDR3 Dual DVI-I/TVO) pci:v00001002d00009491* ID_MODEL_FROM_DATABASE=RV730/M96-CSP [Radeon E4690] pci:v00001002d00009495* ID_MODEL_FROM_DATABASE=RV730 [Radeon HD 4600 AGP Series] pci:v00001002d00009495sv00001002sd00000028* ID_MODEL_FROM_DATABASE=RV730 [Radeon HD 4600 AGP Series] (Radeon HD 4650/4670 AGP) pci:v00001002d00009495sv00001092sd00000028* ID_MODEL_FROM_DATABASE=RV730 [Radeon HD 4600 AGP Series] (Radeon HD 4670 AGP 512MB DDR2) pci:v00001002d00009495sv00001458sd00000028* ID_MODEL_FROM_DATABASE=RV730 [Radeon HD 4600 AGP Series] (Radeon HD 4650 AGP) pci:v00001002d00009495sv00001682sd00000028* ID_MODEL_FROM_DATABASE=RV730 [Radeon HD 4600 AGP Series] (Radeon HD 4650 AGP) pci:v00001002d00009495sv0000174Bsd00000028* ID_MODEL_FROM_DATABASE=RV730 [Radeon HD 4600 AGP Series] (Radeon HD 4650 AGP DDR2) pci:v00001002d00009498* ID_MODEL_FROM_DATABASE=RV730 PRO [Radeon HD 4650] pci:v00001002d0000949C* ID_MODEL_FROM_DATABASE=RV730 GL [FirePro V7750] pci:v00001002d0000949E* ID_MODEL_FROM_DATABASE=RV730 GL [FirePro V5700] pci:v00001002d0000949F* ID_MODEL_FROM_DATABASE=RV730 GL [FirePro V3750] pci:v00001002d000094A0* ID_MODEL_FROM_DATABASE=RV740/M97 [Mobility Radeon HD 4830] pci:v00001002d000094A1* ID_MODEL_FROM_DATABASE=RV740/M97-XT [Mobility Radeon HD 4860] pci:v00001002d000094A3* ID_MODEL_FROM_DATABASE=RV740/M97 GL [FirePro M7740] pci:v00001002d000094B3* ID_MODEL_FROM_DATABASE=RV740 PRO [Radeon HD 4770] pci:v00001002d000094B4* ID_MODEL_FROM_DATABASE=RV740 PRO [Radeon HD 4750] pci:v00001002d000094C1* ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO/XT] pci:v00001002d000094C1sv00001028sd00000211* ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO/XT] (Optiplex 755) pci:v00001002d000094C1sv00001028sd00000D02* ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO/XT] (Optiplex 755) pci:v00001002d000094C3* ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO] pci:v00001002d000094C3sv00001028sd00000302* ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO] (Radeon HD 2400 Pro) pci:v00001002d000094C3sv0000174Bsd0000E400* ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO] (Radeon HD 2400 PRO) pci:v00001002d000094C3sv000018BCsd00003550* ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO] (Radeon HD 2400 PRO) pci:v00001002d000094C4* ID_MODEL_FROM_DATABASE=RV610 LE [Radeon HD 2400 PRO AGP] pci:v00001002d000094C5* ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 LE] pci:v00001002d000094C7* ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2350] pci:v00001002d000094C8* ID_MODEL_FROM_DATABASE=RV610/M74 [Mobility Radeon HD 2400 XT] pci:v00001002d000094C9* ID_MODEL_FROM_DATABASE=RV610/M72-S [Mobility Radeon HD 2400] pci:v00001002d000094C9sv00001002sd000094C9* ID_MODEL_FROM_DATABASE=RV610/M72-S [Mobility Radeon HD 2400] (Radeon HD2400) pci:v00001002d000094CB* ID_MODEL_FROM_DATABASE=RV610 [Radeon E2400] pci:v00001002d000094CC* ID_MODEL_FROM_DATABASE=RV610 LE [Radeon HD 2400 PRO PCI] pci:v00001002d00009500* ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3850 X2] pci:v00001002d00009501* ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3870] pci:v00001002d00009501sv0000174Bsd0000E620* ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3870] (Radeon HD 3870) pci:v00001002d00009504* ID_MODEL_FROM_DATABASE=RV670/M88 [Mobility Radeon HD 3850] pci:v00001002d00009505* ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3690/3850] pci:v00001002d00009505sv0000148Csd00003000* ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3690/3850] (Radeon HD 3850) pci:v00001002d00009505sv0000174Bsd00003000* ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3690/3850] (Radeon HD 3690/3850) pci:v00001002d00009505sv00001787sd00003000* ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3690/3850] (Radeon HD 3690) pci:v00001002d00009506* ID_MODEL_FROM_DATABASE=RV670/M88 [Mobility Radeon HD 3850 X2] pci:v00001002d00009507* ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3830] pci:v00001002d00009508* ID_MODEL_FROM_DATABASE=RV670/M88-XT [Mobility Radeon HD 3870] pci:v00001002d00009509* ID_MODEL_FROM_DATABASE=RV670/M88 [Mobility Radeon HD 3870 X2] pci:v00001002d0000950F* ID_MODEL_FROM_DATABASE=R680 [Radeon HD 3870 X2] pci:v00001002d00009511* ID_MODEL_FROM_DATABASE=RV670 GL [FireGL V7700] pci:v00001002d00009513* ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3850 X2] pci:v00001002d00009515* ID_MODEL_FROM_DATABASE=RV670 PRO [Radeon HD 3850 AGP] pci:v00001002d00009519* ID_MODEL_FROM_DATABASE=RV670 GL [FireStream 9170] pci:v00001002d00009540* ID_MODEL_FROM_DATABASE=RV710 [Radeon HD 4550] pci:v00001002d0000954F* ID_MODEL_FROM_DATABASE=RV710 [Radeon HD 4350/4550] pci:v00001002d0000954Fsv00001462sd00001618* ID_MODEL_FROM_DATABASE=RV710 [Radeon HD 4350/4550] (R4350 MD512H (MS-V161)) pci:v00001002d00009552* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330/4350/4550] pci:v00001002d00009552sv00001028sd00001103* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330/4350/4550] (M92 [Mobility Radeon HD 4330]) pci:v00001002d00009552sv00001458sd000021AC* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330/4350/4550] (Radeon HD 4350) pci:v00001002d00009552sv00001458sd000021ED* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330/4350/4550] (Radeon HD 4550) pci:v00001002d00009552sv0000148Csd00003000* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330/4350/4550] (Radeon HD 4350 Go! Green 512MB GDDR3) pci:v00001002d00009552sv0000174Bsd00003000* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330/4350/4550] (Radeon HD 4350/4550 HyperMemory DDR2) pci:v00001002d00009553* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] pci:v00001002d00009553sv00001025sd0000015E* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) pci:v00001002d00009553sv00001025sd0000017D* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) pci:v00001002d00009553sv00001025sd00000205* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) pci:v00001002d00009553sv00001025sd00000206* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) pci:v00001002d00009553sv00001025sd00000237* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) pci:v00001002d00009553sv00001028sd000002BE* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) pci:v00001002d00009553sv00001028sd000002E8* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4530) pci:v00001002d00009553sv0000103Csd00003624* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4530) pci:v00001002d00009553sv0000103Csd00003628* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4530) pci:v00001002d00009553sv0000103Csd00003636* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4530) pci:v00001002d00009553sv00001043sd00001B32* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) pci:v00001002d00009553sv00001043sd00001B42* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) pci:v00001002d00009553sv0000104Dsd00009056* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) pci:v00001002d00009553sv00001179sd0000FF82* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Satellite L505-13T GPU (Mobility Radeon HD 5145)) pci:v00001002d00009555* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4350/4550] pci:v00001002d00009555sv0000103Csd00001411* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4350/4550] (ProBook 4720s GPU (Mobility Radeon HD 4350)) pci:v00001002d00009557* ID_MODEL_FROM_DATABASE=RV711 GL [FirePro RG220] pci:v00001002d0000955F* ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330] pci:v00001002d00009580* ID_MODEL_FROM_DATABASE=RV630 [Radeon HD 2600 PRO] pci:v00001002d00009581* ID_MODEL_FROM_DATABASE=RV630/M76 [Mobility Radeon HD 2600] pci:v00001002d00009583* ID_MODEL_FROM_DATABASE=RV630/M76 [Mobility Radeon HD 2600 XT/2700] pci:v00001002d00009583sv0000106Bsd00000083* ID_MODEL_FROM_DATABASE=RV630/M76 [Mobility Radeon HD 2600 XT/2700] (iMac 7,1) pci:v00001002d00009583sv00001734sd00001107* ID_MODEL_FROM_DATABASE=RV630/M76 [Mobility Radeon HD 2600 XT/2700] (Mobility Radeon HD 2700) pci:v00001002d00009586* ID_MODEL_FROM_DATABASE=RV630 XT [Radeon HD 2600 XT AGP] pci:v00001002d00009587* ID_MODEL_FROM_DATABASE=RV630 PRO [Radeon HD 2600 PRO AGP] pci:v00001002d00009588* ID_MODEL_FROM_DATABASE=RV630 XT [Radeon HD 2600 XT] pci:v00001002d00009588sv00001458sd0000216C* ID_MODEL_FROM_DATABASE=RV630 XT [Radeon HD 2600 XT] (Radeon HD 2600 XT, 256MB GDDR3, 2x DVI, TV-out, PCIe (GV-RX26T256H)) pci:v00001002d00009589* ID_MODEL_FROM_DATABASE=RV630 PRO [Radeon HD 2600 PRO] pci:v00001002d00009589sv00001787sd00003000* ID_MODEL_FROM_DATABASE=RV630 PRO [Radeon HD 2600 PRO] (Radeon HD 3610) pci:v00001002d0000958A* ID_MODEL_FROM_DATABASE=RV630 [Radeon HD 2600 X2] pci:v00001002d0000958B* ID_MODEL_FROM_DATABASE=RV630/M76 [Mobility Radeon HD 2600 XT] pci:v00001002d0000958C* ID_MODEL_FROM_DATABASE=RV630 GL [FireGL V5600] pci:v00001002d0000958D* ID_MODEL_FROM_DATABASE=RV630 GL [FireGL V3600] pci:v00001002d00009591* ID_MODEL_FROM_DATABASE=RV635/M86 [Mobility Radeon HD 3650] pci:v00001002d00009591sv00001002sd00009591* ID_MODEL_FROM_DATABASE=RV635/M86 [Mobility Radeon HD 3650] (Mobility Radeon HD 3650) pci:v00001002d00009593* ID_MODEL_FROM_DATABASE=RV635/M86 [Mobility Radeon HD 3670] pci:v00001002d00009595* ID_MODEL_FROM_DATABASE=RV635/M86 GL [Mobility FireGL V5700] pci:v00001002d00009596* ID_MODEL_FROM_DATABASE=RV635 PRO [Radeon HD 3650 AGP] pci:v00001002d00009596sv00001043sd00000028* ID_MODEL_FROM_DATABASE=RV635 PRO [Radeon HD 3650 AGP] (EAH3650 SILENT/HTDI/512M/A) pci:v00001002d00009597* ID_MODEL_FROM_DATABASE=RV635 PRO [Radeon HD 3650 AGP] pci:v00001002d00009598* ID_MODEL_FROM_DATABASE=RV635 [Radeon HD 3650/3750/4570/4580] pci:v00001002d00009598sv00001002sd00009598* ID_MODEL_FROM_DATABASE=RV635 [Radeon HD 3650/3750/4570/4580] (Mobility Radeon HD 3600) pci:v00001002d00009598sv00001043sd000001D6* ID_MODEL_FROM_DATABASE=RV635 [Radeon HD 3650/3750/4570/4580] (EAH3650 Silent) pci:v00001002d00009598sv00001043sd00003001* ID_MODEL_FROM_DATABASE=RV635 [Radeon HD 3650/3750/4570/4580] (Radeon HD 4570) pci:v00001002d00009598sv0000174Bsd00003001* ID_MODEL_FROM_DATABASE=RV635 [Radeon HD 3650/3750/4570/4580] (Radeon HD 3750) pci:v00001002d00009598sv0000174Bsd00004580* ID_MODEL_FROM_DATABASE=RV635 [Radeon HD 3650/3750/4570/4580] (RV635 PRO [Radeon HD 4580]) pci:v00001002d00009599* ID_MODEL_FROM_DATABASE=RV635 PRO [Radeon HD 3650 AGP] pci:v00001002d000095C0* ID_MODEL_FROM_DATABASE=RV620 PRO [Radeon HD 3470] pci:v00001002d000095C0sv00001002sd000095C0* ID_MODEL_FROM_DATABASE=RV620 PRO [Radeon HD 3470] (Mobility Radeon HD 3470) pci:v00001002d000095C2* ID_MODEL_FROM_DATABASE=RV620/M82 [Mobility Radeon HD 3410/3430] pci:v00001002d000095C4* ID_MODEL_FROM_DATABASE=RV620/M82 [Mobility Radeon HD 3450/3470] pci:v00001002d000095C4sv00001002sd000095C4* ID_MODEL_FROM_DATABASE=RV620/M82 [Mobility Radeon HD 3450/3470] (Mobility Radeon HD 3400) pci:v00001002d000095C5* ID_MODEL_FROM_DATABASE=RV620 LE [Radeon HD 3450] pci:v00001002d000095C5sv00001028sd00000342* ID_MODEL_FROM_DATABASE=RV620 LE [Radeon HD 3450] (OptiPlex 980) pci:v00001002d000095C6* ID_MODEL_FROM_DATABASE=RV620 LE [Radeon HD 3450 AGP] pci:v00001002d000095C9* ID_MODEL_FROM_DATABASE=RV620 LE [Radeon HD 3450 PCI] pci:v00001002d000095CC* ID_MODEL_FROM_DATABASE=RV620 GL [FirePro V3700] pci:v00001002d000095CD* ID_MODEL_FROM_DATABASE=RV620 [FirePro 2450] pci:v00001002d000095CF* ID_MODEL_FROM_DATABASE=RV620 GL [FirePro 2260] pci:v00001002d0000960F* ID_MODEL_FROM_DATABASE=RS780 HDMI Audio [Radeon (HD) 3000 Series] pci:v00001002d00009610* ID_MODEL_FROM_DATABASE=RS780 [Radeon HD 3200] pci:v00001002d00009610sv00001458sd0000D000* ID_MODEL_FROM_DATABASE=RS780 [Radeon HD 3200] (GA-MA78GM-S2H Motherboard) pci:v00001002d00009611* ID_MODEL_FROM_DATABASE=RS780C [Radeon 3100] pci:v00001002d00009612* ID_MODEL_FROM_DATABASE=RS780M [Mobility Radeon HD 3200] pci:v00001002d00009613* ID_MODEL_FROM_DATABASE=RS780MC [Mobility Radeon HD 3100] pci:v00001002d00009614* ID_MODEL_FROM_DATABASE=RS780D [Radeon HD 3300] pci:v00001002d00009616* ID_MODEL_FROM_DATABASE=RS780L [Radeon 3000] pci:v00001002d00009640* ID_MODEL_FROM_DATABASE=BeaverCreek [Radeon HD 6550D] pci:v00001002d00009641* ID_MODEL_FROM_DATABASE=BeaverCreek [Radeon HD 6620G] pci:v00001002d00009642* ID_MODEL_FROM_DATABASE=Sumo [Radeon HD 6370D] pci:v00001002d00009643* ID_MODEL_FROM_DATABASE=Sumo [Radeon HD 6380G] pci:v00001002d00009644* ID_MODEL_FROM_DATABASE=Sumo [Radeon HD 6410D] pci:v00001002d00009645* ID_MODEL_FROM_DATABASE=Sumo [Radeon HD 6410D] pci:v00001002d00009647* ID_MODEL_FROM_DATABASE=BeaverCreek [Radeon HD 6520G] pci:v00001002d00009648* ID_MODEL_FROM_DATABASE=Sumo [Radeon HD 6480G] pci:v00001002d00009649* ID_MODEL_FROM_DATABASE=Sumo [Radeon HD 6480G] pci:v00001002d0000964A* ID_MODEL_FROM_DATABASE=BeaverCreek [Radeon HD 6530D] pci:v00001002d0000964B* ID_MODEL_FROM_DATABASE=Sumo pci:v00001002d0000964C* ID_MODEL_FROM_DATABASE=Sumo pci:v00001002d0000964E* ID_MODEL_FROM_DATABASE=Sumo pci:v00001002d0000964F* ID_MODEL_FROM_DATABASE=Sumo pci:v00001002d0000970F* ID_MODEL_FROM_DATABASE=RS880 HDMI Audio [Radeon HD 4200 Series] pci:v00001002d0000970Fsv00001019sd00002120* ID_MODEL_FROM_DATABASE=RS880 HDMI Audio [Radeon HD 4200 Series] (A785GM-M) pci:v00001002d0000970Fsv00001043sd000083A2* ID_MODEL_FROM_DATABASE=RS880 HDMI Audio [Radeon HD 4200 Series] (M4A785TD Motherboard) pci:v00001002d0000970Fsv00001043sd0000843E* ID_MODEL_FROM_DATABASE=RS880 HDMI Audio [Radeon HD 4200 Series] (M5A88-V EVO) pci:v00001002d00009710* ID_MODEL_FROM_DATABASE=RS880 [Radeon HD 4200] pci:v00001002d00009710sv00001019sd00002120* ID_MODEL_FROM_DATABASE=RS880 [Radeon HD 4200] (A785GM-M) pci:v00001002d00009710sv00001043sd000083A2* ID_MODEL_FROM_DATABASE=RS880 [Radeon HD 4200] (M4A785TD Motherboard) pci:v00001002d00009712* ID_MODEL_FROM_DATABASE=RS880M [Mobility Radeon HD 4225/4250] pci:v00001002d00009713* ID_MODEL_FROM_DATABASE=RS880M [Mobility Radeon HD 4100] pci:v00001002d00009714* ID_MODEL_FROM_DATABASE=RS880 [Radeon HD 4290] pci:v00001002d00009715* ID_MODEL_FROM_DATABASE=RS880 [Radeon HD 4250] pci:v00001002d00009715sv00001043sd0000843E* ID_MODEL_FROM_DATABASE=RS880 [Radeon HD 4250] (M5A88-V EVO) pci:v00001002d00009802* ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6310] pci:v00001002d00009802sv0000174Bsd00001001* ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6310] (PURE Fusion Mini) pci:v00001002d00009803* ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6310] pci:v00001002d00009804* ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6250] pci:v00001002d00009805* ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6250] pci:v00001002d00009806* ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6320] pci:v00001002d00009807* ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6290] pci:v00001002d00009808* ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 7340] pci:v00001002d00009809* ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 7310] pci:v00001002d0000980A* ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 7290] pci:v00001002d00009830* ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8400 / R3 Series] pci:v00001002d00009831* ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8400E] pci:v00001002d00009832* ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8330] pci:v00001002d00009833* ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8330E] pci:v00001002d00009834* ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8210] pci:v00001002d00009835* ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8310E] pci:v00001002d00009836* ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8280 / R3 Series] pci:v00001002d00009837* ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8280E] pci:v00001002d00009838* ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8240 / R3 Series] pci:v00001002d00009839* ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8180] pci:v00001002d0000983D* ID_MODEL_FROM_DATABASE=Temash [Radeon HD 8250/8280G] pci:v00001002d00009840* ID_MODEL_FROM_DATABASE=Kabini HDMI/DP Audio pci:v00001002d00009850* ID_MODEL_FROM_DATABASE=Mullins [Radeon R3 Graphics] pci:v00001002d00009851* ID_MODEL_FROM_DATABASE=Mullins [Radeon R4/R5 Graphics] pci:v00001002d00009852* ID_MODEL_FROM_DATABASE=Mullins [Radeon R2 Graphics] pci:v00001002d00009853* ID_MODEL_FROM_DATABASE=Mullins [Radeon R2 Graphics] pci:v00001002d00009854* ID_MODEL_FROM_DATABASE=Mullins [Radeon R3E Graphics] pci:v00001002d00009855* ID_MODEL_FROM_DATABASE=Mullins [Radeon R6 Graphics] pci:v00001002d00009856* ID_MODEL_FROM_DATABASE=Mullins [Radeon R1E/R2E Graphics] pci:v00001002d00009857* ID_MODEL_FROM_DATABASE=Mullins [Radeon APU XX-2200M with R2 Graphics] pci:v00001002d00009858* ID_MODEL_FROM_DATABASE=Mullins pci:v00001002d00009859* ID_MODEL_FROM_DATABASE=Mullins pci:v00001002d0000985A* ID_MODEL_FROM_DATABASE=Mullins pci:v00001002d0000985B* ID_MODEL_FROM_DATABASE=Mullins pci:v00001002d0000985C* ID_MODEL_FROM_DATABASE=Mullins pci:v00001002d0000985D* ID_MODEL_FROM_DATABASE=Mullins pci:v00001002d0000985E* ID_MODEL_FROM_DATABASE=Mullins pci:v00001002d0000985F* ID_MODEL_FROM_DATABASE=Mullins pci:v00001002d00009874* ID_MODEL_FROM_DATABASE=Carrizo pci:v00001002d00009900* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7660G] pci:v00001002d00009900sv0000103Csd00001985* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7660G] (Pavilion 17-e163sg Notebook PC) pci:v00001002d00009901* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7660D] pci:v00001002d00009902* ID_MODEL_FROM_DATABASE=Trinity HDMI Audio Controller pci:v00001002d00009902sv0000103Csd0000194E* ID_MODEL_FROM_DATABASE=Trinity HDMI Audio Controller (ProBook 455 G1 Notebook) pci:v00001002d00009902sv0000103Csd00001985* ID_MODEL_FROM_DATABASE=Trinity HDMI Audio Controller (Pavilion 17-e163sg Notebook PC) pci:v00001002d00009903* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7640G] pci:v00001002d00009903sv0000103Csd0000194E* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7640G] (ProBook 455 G1 Notebook) pci:v00001002d00009903sv0000103Csd00001952* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7640G] (ProBook 455 G1 Notebook) pci:v00001002d00009904* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7560D] pci:v00001002d00009905* ID_MODEL_FROM_DATABASE=Trinity [FirePro A300 Series Graphics] pci:v00001002d00009906* ID_MODEL_FROM_DATABASE=Trinity [FirePro A300 Series Graphics] pci:v00001002d00009907* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7620G] pci:v00001002d00009908* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7600G] pci:v00001002d00009909* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7500G] pci:v00001002d0000990A* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7500G] pci:v00001002d0000990B* ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8650G] pci:v00001002d0000990C* ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8670D] pci:v00001002d0000990D* ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8550G] pci:v00001002d0000990E* ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8570D] pci:v00001002d0000990F* ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8610G] pci:v00001002d00009910* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7660G] pci:v00001002d00009913* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7640G] pci:v00001002d00009917* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7620G] pci:v00001002d00009918* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7600G] pci:v00001002d00009919* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7500G] pci:v00001002d00009920* ID_MODEL_FROM_DATABASE=Liverpool Graphics pci:v00001002d00009921* ID_MODEL_FROM_DATABASE=Liverpool HDMI/DP Audio Controller pci:v00001002d00009990* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7520G] pci:v00001002d00009991* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7540D] pci:v00001002d00009992* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7420G] pci:v00001002d00009993* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7480D] pci:v00001002d00009994* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7400G] pci:v00001002d00009995* ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8450G] pci:v00001002d00009996* ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8470D] pci:v00001002d00009997* ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8350G] pci:v00001002d00009998* ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8370D] pci:v00001002d00009999* ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8510G] pci:v00001002d0000999A* ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8410G] pci:v00001002d0000999B* ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8310G] pci:v00001002d0000999C* ID_MODEL_FROM_DATABASE=Richland pci:v00001002d0000999D* ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8550D] pci:v00001002d000099A0* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7520G] pci:v00001002d000099A2* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7420G] pci:v00001002d000099A4* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7400G] pci:v00001002d0000AA00* ID_MODEL_FROM_DATABASE=R600 HDMI Audio [Radeon HD 2900 Series] pci:v00001002d0000AA08* ID_MODEL_FROM_DATABASE=RV630 HDMI Audio [Radeon HD 2600 Series] pci:v00001002d0000AA10* ID_MODEL_FROM_DATABASE=RV610 HDMI Audio [Radeon HD 2350/2400 Series] pci:v00001002d0000AA10sv0000174Bsd0000AA10* ID_MODEL_FROM_DATABASE=RV610 HDMI Audio [Radeon HD 2350/2400 Series] (Radeon HD 2400 PRO) pci:v00001002d0000AA10sv000018BCsd0000AA10* ID_MODEL_FROM_DATABASE=RV610 HDMI Audio [Radeon HD 2350/2400 Series] (Radeon HD 2400 PRO) pci:v00001002d0000AA18* ID_MODEL_FROM_DATABASE=RV670/680 HDMI Audio [Radeon HD 3690/3800 Series] pci:v00001002d0000AA20* ID_MODEL_FROM_DATABASE=RV635 HDMI Audio [Radeon HD 3600 Series] pci:v00001002d0000AA28* ID_MODEL_FROM_DATABASE=RV620 HDMI Audio [Radeon HD 3400 Series] pci:v00001002d0000AA30* ID_MODEL_FROM_DATABASE=RV770 HDMI Audio [Radeon HD 4850/4870] pci:v00001002d0000AA30sv0000174Bsd0000AA30* ID_MODEL_FROM_DATABASE=RV770 HDMI Audio [Radeon HD 4850/4870] (Radeon HD 4850 512MB GDDR3 PCI-E Dual Slot Fansink) pci:v00001002d0000AA38* ID_MODEL_FROM_DATABASE=RV710/730 HDMI Audio [Radeon HD 4000 series] pci:v00001002d0000AA38sv0000103Csd00003628* ID_MODEL_FROM_DATABASE=RV710/730 HDMI Audio [Radeon HD 4000 series] (dv6-1190en) pci:v00001002d0000AA50* ID_MODEL_FROM_DATABASE=Cypress HDMI Audio [Radeon HD 5800 Series] pci:v00001002d0000AA58* ID_MODEL_FROM_DATABASE=Juniper HDMI Audio [Radeon HD 5700 Series] pci:v00001002d0000AA60* ID_MODEL_FROM_DATABASE=Redwood HDMI Audio [Radeon HD 5000 Series] pci:v00001002d0000AA60sv00001025sd0000033D* ID_MODEL_FROM_DATABASE=Redwood HDMI Audio [Radeon HD 5000 Series] (Mobility Radeon HD 5650) pci:v00001002d0000AA60sv00001025sd00000347* ID_MODEL_FROM_DATABASE=Redwood HDMI Audio [Radeon HD 5000 Series] (Aspire 7740G) pci:v00001002d0000AA68* ID_MODEL_FROM_DATABASE=Cedar HDMI Audio [Radeon HD 5400/6300 Series] pci:v00001002d0000AA68sv00001028sd0000AA68* ID_MODEL_FROM_DATABASE=Cedar HDMI Audio [Radeon HD 5400/6300 Series] (XPS 8300) pci:v00001002d0000AA80* ID_MODEL_FROM_DATABASE=Cayman/Antilles HDMI Audio [Radeon HD 6900 Series] pci:v00001002d0000AA88* ID_MODEL_FROM_DATABASE=Barts HDMI Audio [Radeon HD 6800 Series] pci:v00001002d0000AA90* ID_MODEL_FROM_DATABASE=Turks/Whistler HDMI Audio [Radeon HD 6000 Series] pci:v00001002d0000AA90sv00001028sd000004A3* ID_MODEL_FROM_DATABASE=Turks/Whistler HDMI Audio [Radeon HD 6000 Series] (Precision M4600) pci:v00001002d0000AA98* ID_MODEL_FROM_DATABASE=Caicos HDMI Audio [Radeon HD 6400 Series] pci:v00001002d0000AA98sv0000174Bsd0000AA98* ID_MODEL_FROM_DATABASE=Caicos HDMI Audio [Radeon HD 6400 Series] (Radeon HD 6450 1GB DDR3) pci:v00001002d0000AAA0* ID_MODEL_FROM_DATABASE=Tahiti XT HDMI Audio [Radeon HD 7970 Series] pci:v00001002d0000AAB0* ID_MODEL_FROM_DATABASE=Cape Verde/Pitcairn HDMI Audio [Radeon HD 7700/7800 Series] pci:v00001002d0000AAC0* ID_MODEL_FROM_DATABASE=Tobago HDMI Audio [Radeon R7 360 / R9 360 OEM] pci:v00001002d0000AAC8* ID_MODEL_FROM_DATABASE=Hawaii HDMI Audio pci:v00001002d0000AAD8* ID_MODEL_FROM_DATABASE=Tonga HDMI Audio [Radeon R9 285/380] pci:v00001002d0000AAD8sv0000174Bsd0000AAD8* ID_MODEL_FROM_DATABASE=Tonga HDMI Audio [Radeon R9 285/380] (Radeon R9 285/380 HDMI Audio) pci:v00001002d0000AC00* ID_MODEL_FROM_DATABASE=Theater 600 Pro pci:v00001002d0000AC02* ID_MODEL_FROM_DATABASE=TV Wonder HD 600 PCIe pci:v00001002d0000AC12* ID_MODEL_FROM_DATABASE=Theater HD T507 (DVB-T) TV tuner/capture device pci:v00001002d0000CAB0* ID_MODEL_FROM_DATABASE=RS100 Host Bridge pci:v00001002d0000CAB2* ID_MODEL_FROM_DATABASE=RS200 Host Bridge pci:v00001002d0000CAB3* ID_MODEL_FROM_DATABASE=RS250 Host Bridge pci:v00001002d0000CBB2* ID_MODEL_FROM_DATABASE=RS200 Host Bridge pci:v00001003* ID_VENDOR_FROM_DATABASE=ULSI Systems pci:v00001003d00000201* ID_MODEL_FROM_DATABASE=US201 pci:v00001004* ID_VENDOR_FROM_DATABASE=VLSI Technology Inc pci:v00001004d00000005* ID_MODEL_FROM_DATABASE=82C592-FC1 pci:v00001004d00000006* ID_MODEL_FROM_DATABASE=82C593-FC1 pci:v00001004d00000007* ID_MODEL_FROM_DATABASE=82C594-AFC2 pci:v00001004d00000008* ID_MODEL_FROM_DATABASE=82C596/7 [Wildcat] pci:v00001004d00000009* ID_MODEL_FROM_DATABASE=82C597-AFC2 pci:v00001004d0000000C* ID_MODEL_FROM_DATABASE=82C541 [Lynx] pci:v00001004d0000000D* ID_MODEL_FROM_DATABASE=82C543 [Lynx] pci:v00001004d00000101* ID_MODEL_FROM_DATABASE=82C532 pci:v00001004d00000102* ID_MODEL_FROM_DATABASE=82C534 [Eagle] pci:v00001004d00000103* ID_MODEL_FROM_DATABASE=82C538 pci:v00001004d00000104* ID_MODEL_FROM_DATABASE=82C535 pci:v00001004d00000105* ID_MODEL_FROM_DATABASE=82C147 pci:v00001004d00000200* ID_MODEL_FROM_DATABASE=82C975 pci:v00001004d00000280* ID_MODEL_FROM_DATABASE=82C925 pci:v00001004d00000304* ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio pci:v00001004d00000304sv00001004sd00000304* ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio pci:v00001004d00000304sv0000122Dsd00001206* ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio (DSP368 Audio) pci:v00001004d00000304sv00001483sd00005020* ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio (XWave Thunder 3D Audio) pci:v00001004d00000305* ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Gameport pci:v00001004d00000305sv00001004sd00000305* ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Gameport pci:v00001004d00000305sv0000122Dsd00001207* ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Gameport (DSP368 Audio Gameport) pci:v00001004d00000305sv00001483sd00005021* ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Gameport (XWave Thunder 3D Audio Gameport) pci:v00001004d00000306* ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Support Registers pci:v00001004d00000306sv00001004sd00000306* ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Support Registers pci:v00001004d00000306sv0000122Dsd00001208* ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Support Registers (DSP368 Audio Support Registers) pci:v00001004d00000306sv00001483sd00005022* ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Support Registers (XWave Thunder 3D Audio Support Registers) pci:v00001004d00000307* ID_MODEL_FROM_DATABASE=SAA7785 ThunderBird PCI Audio pci:v00001004d00000307sv00001004sd00000703* ID_MODEL_FROM_DATABASE=SAA7785 ThunderBird PCI Audio (Philips Rhythmic Edge PSC703) pci:v00001004d00000307sv00001004sd00000705* ID_MODEL_FROM_DATABASE=SAA7785 ThunderBird PCI Audio (Philips Seismic Edge PSC705) pci:v00001004d00000307sv00001004sd00000706* ID_MODEL_FROM_DATABASE=SAA7785 ThunderBird PCI Audio (Philips Acoustic Edge PSC706) pci:v00001004d00000308* ID_MODEL_FROM_DATABASE=SAA7785 ThunderBird PCI Audio Gameport pci:v00001004d00000702* ID_MODEL_FROM_DATABASE=VAS96011 [Golden Gate II] pci:v00001004d00000703* ID_MODEL_FROM_DATABASE=Tollgate pci:v00001005* ID_VENDOR_FROM_DATABASE=Avance Logic Inc. [ALI] pci:v00001005d00002064* ID_MODEL_FROM_DATABASE=ALG2032/2064 pci:v00001005d00002128* ID_MODEL_FROM_DATABASE=ALG2364A pci:v00001005d00002301* ID_MODEL_FROM_DATABASE=ALG2301 pci:v00001005d00002302* ID_MODEL_FROM_DATABASE=ALG2302 pci:v00001005d00002364* ID_MODEL_FROM_DATABASE=ALG2364 pci:v00001005d00002464* ID_MODEL_FROM_DATABASE=ALG2364A pci:v00001005d00002501* ID_MODEL_FROM_DATABASE=ALG2564A/25128A pci:v00001006* ID_VENDOR_FROM_DATABASE=Reply Group pci:v00001007* ID_VENDOR_FROM_DATABASE=NetFrame Systems Inc pci:v00001008* ID_VENDOR_FROM_DATABASE=Epson pci:v0000100A* ID_VENDOR_FROM_DATABASE=Phoenix Technologies pci:v0000100B* ID_VENDOR_FROM_DATABASE=National Semiconductor Corporation pci:v0000100Bd00000001* ID_MODEL_FROM_DATABASE=DP83810 pci:v0000100Bd00000002* ID_MODEL_FROM_DATABASE=87415/87560 IDE pci:v0000100Bd0000000E* ID_MODEL_FROM_DATABASE=87560 Legacy I/O pci:v0000100Bd0000000F* ID_MODEL_FROM_DATABASE=FireWire Controller pci:v0000100Bd00000011* ID_MODEL_FROM_DATABASE=NS87560 National PCI System I/O pci:v0000100Bd00000012* ID_MODEL_FROM_DATABASE=USB Controller pci:v0000100Bd00000020* ID_MODEL_FROM_DATABASE=DP83815 (MacPhyter) Ethernet Controller pci:v0000100Bd00000020sv0000103Csd00000024* ID_MODEL_FROM_DATABASE=DP83815 (MacPhyter) Ethernet Controller (Pavilion ze4400 builtin Network) pci:v0000100Bd00000020sv000012D9sd0000000C* ID_MODEL_FROM_DATABASE=DP83815 (MacPhyter) Ethernet Controller (Aculab E1/T1 PMXc cPCI carrier card) pci:v0000100Bd00000020sv00001385sd0000F311* ID_MODEL_FROM_DATABASE=DP83815 (MacPhyter) Ethernet Controller (FA311 / FA312 (FA311 with WoL HW)) pci:v0000100Bd00000020sv00001385sd0000F312* ID_MODEL_FROM_DATABASE=DP83815 (MacPhyter) Ethernet Controller (FA312 (rev. A1) Fast Ethernet PCI Adapter) pci:v0000100Bd00000021* ID_MODEL_FROM_DATABASE=PC87200 PCI to ISA Bridge pci:v0000100Bd00000022* ID_MODEL_FROM_DATABASE=DP83820 10/100/1000 Ethernet Controller pci:v0000100Bd00000022sv00001186sd00004900* ID_MODEL_FROM_DATABASE=DP83820 10/100/1000 Ethernet Controller (DGE-500T) pci:v0000100Bd00000022sv00001385sd0000621A* ID_MODEL_FROM_DATABASE=DP83820 10/100/1000 Ethernet Controller (GA621) pci:v0000100Bd00000022sv00001385sd0000622A* ID_MODEL_FROM_DATABASE=DP83820 10/100/1000 Ethernet Controller (GA622T) pci:v0000100Bd00000028* ID_MODEL_FROM_DATABASE=Geode GX2 Host Bridge pci:v0000100Bd0000002A* ID_MODEL_FROM_DATABASE=CS5535 South Bridge pci:v0000100Bd0000002B* ID_MODEL_FROM_DATABASE=CS5535 ISA bridge pci:v0000100Bd0000002D* ID_MODEL_FROM_DATABASE=CS5535 IDE pci:v0000100Bd0000002E* ID_MODEL_FROM_DATABASE=CS5535 Audio pci:v0000100Bd0000002F* ID_MODEL_FROM_DATABASE=CS5535 USB pci:v0000100Bd00000030* ID_MODEL_FROM_DATABASE=Geode GX2 Graphics Processor pci:v0000100Bd00000035* ID_MODEL_FROM_DATABASE=DP83065 [Saturn] 10/100/1000 Ethernet Controller pci:v0000100Bd00000500* ID_MODEL_FROM_DATABASE=SCx200 Bridge pci:v0000100Bd00000501* ID_MODEL_FROM_DATABASE=SCx200 SMI pci:v0000100Bd00000502* ID_MODEL_FROM_DATABASE=SCx200, SC1100 IDE controller pci:v0000100Bd00000502sv0000100Bsd00000502* ID_MODEL_FROM_DATABASE=SCx200, SC1100 IDE controller (IDE Controller) pci:v0000100Bd00000503* ID_MODEL_FROM_DATABASE=SCx200, SC1100 Audio Controller pci:v0000100Bd00000503sv0000100Bsd00000503* ID_MODEL_FROM_DATABASE=SCx200, SC1100 Audio Controller (XpressAudio controller) pci:v0000100Bd00000504* ID_MODEL_FROM_DATABASE=SCx200 Video pci:v0000100Bd00000505* ID_MODEL_FROM_DATABASE=SCx200 XBus pci:v0000100Bd00000510* ID_MODEL_FROM_DATABASE=SC1100 Bridge pci:v0000100Bd00000510sv0000100Bsd00000500* ID_MODEL_FROM_DATABASE=SC1100 Bridge (GPIO and LPC support bridge) pci:v0000100Bd00000511* ID_MODEL_FROM_DATABASE=SC1100 SMI & ACPI pci:v0000100Bd00000511sv0000100Bsd00000501* ID_MODEL_FROM_DATABASE=SC1100 SMI & ACPI (bridge) pci:v0000100Bd00000515* ID_MODEL_FROM_DATABASE=SC1100 XBus pci:v0000100Bd00000515sv0000100Bsd00000505* ID_MODEL_FROM_DATABASE=SC1100 XBus (SC1100 PCI to XBus bridge) pci:v0000100Bd0000D001* ID_MODEL_FROM_DATABASE=87410 IDE pci:v0000100C* ID_VENDOR_FROM_DATABASE=Tseng Labs Inc pci:v0000100Cd00003202* ID_MODEL_FROM_DATABASE=ET4000/W32p rev A pci:v0000100Cd00003205* ID_MODEL_FROM_DATABASE=ET4000/W32p rev B pci:v0000100Cd00003206* ID_MODEL_FROM_DATABASE=ET4000/W32p rev C pci:v0000100Cd00003207* ID_MODEL_FROM_DATABASE=ET4000/W32p rev D pci:v0000100Cd00003208* ID_MODEL_FROM_DATABASE=ET6000 pci:v0000100Cd00004702* ID_MODEL_FROM_DATABASE=ET6300 pci:v0000100D* ID_VENDOR_FROM_DATABASE=AST Research Inc pci:v0000100E* ID_VENDOR_FROM_DATABASE=Weitek pci:v0000100Ed00009000* ID_MODEL_FROM_DATABASE=P9000 Viper pci:v0000100Ed00009001* ID_MODEL_FROM_DATABASE=P9000 Viper pci:v0000100Ed00009002* ID_MODEL_FROM_DATABASE=P9000 Viper pci:v0000100Ed00009100* ID_MODEL_FROM_DATABASE=P9100 Viper Pro/SE pci:v00001010* ID_VENDOR_FROM_DATABASE=Video Logic, Ltd. pci:v00001011* ID_VENDOR_FROM_DATABASE=Digital Equipment Corporation pci:v00001011d00000001* ID_MODEL_FROM_DATABASE=DECchip 21050 pci:v00001011d00000002* ID_MODEL_FROM_DATABASE=DECchip 21040 [Tulip] pci:v00001011d00000004* ID_MODEL_FROM_DATABASE=DECchip 21030 [TGA] pci:v00001011d00000007* ID_MODEL_FROM_DATABASE=NVRAM [Zephyr NVRAM] pci:v00001011d00000008* ID_MODEL_FROM_DATABASE=KZPSA [KZPSA] pci:v00001011d00000009* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] pci:v00001011d00000009sv00001025sd00000310* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (21140 Fast Ethernet) pci:v00001011d00000009sv000010B8sd00002001* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (SMC9332BDT EtherPower 10/100) pci:v00001011d00000009sv000010B8sd00002002* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (SMC9332BVT EtherPower T4 10/100) pci:v00001011d00000009sv000010B8sd00002003* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (SMC9334BDT EtherPower 10/100 (1-port)) pci:v00001011d00000009sv00001109sd00002400* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (ANA-6944A/TX Fast Ethernet) pci:v00001011d00000009sv00001112sd00002300* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (RNS2300 Fast Ethernet) pci:v00001011d00000009sv00001112sd00002320* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (RNS2320 Fast Ethernet) pci:v00001011d00000009sv00001112sd00002340* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (RNS2340 Fast Ethernet) pci:v00001011d00000009sv00001113sd00001207* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (EN-1207-TX Fast Ethernet) pci:v00001011d00000009sv00001186sd00001100* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (DFE-500TX Fast Ethernet) pci:v00001011d00000009sv00001186sd00001112* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (DFE-570TX Fast Ethernet) pci:v00001011d00000009sv00001186sd00001140* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (DFE-660 Cardbus Ethernet 10/100) pci:v00001011d00000009sv00001186sd00001142* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (DFE-660 Cardbus Ethernet 10/100) pci:v00001011d00000009sv000011F6sd00000503* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (Freedomline Fast Ethernet) pci:v00001011d00000009sv00001282sd00009100* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (AEF-380TXD Fast Ethernet) pci:v00001011d00000009sv00001385sd00001100* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (FA310TX Fast Ethernet) pci:v00001011d00000009sv00002646sd00000001* ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (KNE100TX Fast Ethernet) pci:v00001011d0000000A* ID_MODEL_FROM_DATABASE=21230 Video Codec pci:v00001011d0000000D* ID_MODEL_FROM_DATABASE=PBXGB [TGA2] pci:v00001011d0000000F* ID_MODEL_FROM_DATABASE=DEFPA FDDI PCI-to-PDQ Interface Chip [PFI] pci:v00001011d0000000Fsv00001011sd0000DEF1* ID_MODEL_FROM_DATABASE=DEFPA FDDI PCI-to-PDQ Interface Chip [PFI] (FDDI controller (DEFPA)) pci:v00001011d0000000Fsv0000103Csd0000DEF1* ID_MODEL_FROM_DATABASE=DEFPA FDDI PCI-to-PDQ Interface Chip [PFI] (FDDI controller (3X-DEFPA)) pci:v00001011d00000014* ID_MODEL_FROM_DATABASE=DECchip 21041 [Tulip Pass 3] pci:v00001011d00000014sv00001186sd00000100* ID_MODEL_FROM_DATABASE=DECchip 21041 [Tulip Pass 3] (DE-530+) pci:v00001011d00000016* ID_MODEL_FROM_DATABASE=DGLPB [OPPO] pci:v00001011d00000017* ID_MODEL_FROM_DATABASE=PV-PCI Graphics Controller (ZLXp-L) pci:v00001011d00000018* ID_MODEL_FROM_DATABASE=Memory Channel interface pci:v00001011d00000019* ID_MODEL_FROM_DATABASE=DECchip 21142/43 pci:v00001011d00000019sv00001011sd0000500A* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (DE500A Fast Ethernet) pci:v00001011d00000019sv00001011sd0000500B* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (DE500B Fast Ethernet) pci:v00001011d00000019sv00001014sd00000001* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (10/100 EtherJet Cardbus) pci:v00001011d00000019sv00001025sd00000315* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (ALN315 Fast Ethernet) pci:v00001011d00000019sv00001033sd0000800C* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (PC-9821-CS01 100BASE-TX Interface Card) pci:v00001011d00000019sv00001033sd0000800D* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (PC-9821NR-B06 100BASE-TX Interface Card) pci:v00001011d00000019sv0000103Csd0000125A* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (10/100Base-TX (PCI) [A5506B]) pci:v00001011d00000019sv0000108Dsd00000016* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Rapidfire 2327 10/100 Ethernet) pci:v00001011d00000019sv0000108Dsd00000017* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (GoCard 2250 Ethernet 10/100 Cardbus) pci:v00001011d00000019sv000010B8sd00002005* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (SMC8032DT Extreme Ethernet 10/100) pci:v00001011d00000019sv000010B8sd00008034* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (SMC8034 Extreme Ethernet 10/100) pci:v00001011d00000019sv000010EFsd00008169* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Fast Ethernet) pci:v00001011d00000019sv00001109sd00002A00* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (ANA-6911A/TX Fast Ethernet) pci:v00001011d00000019sv00001109sd00002B00* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (ANA-6911A/TXC Fast Ethernet) pci:v00001011d00000019sv00001109sd00003000* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (ANA-6922/TX Fast Ethernet) pci:v00001011d00000019sv00001113sd00001207* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cheetah Fast Ethernet) pci:v00001011d00000019sv00001113sd00002220* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Fast Ethernet) pci:v00001011d00000019sv0000115Dsd00000002* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Ethernet 10/100) pci:v00001011d00000019sv00001179sd00000203* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Fast Ethernet) pci:v00001011d00000019sv00001179sd00000204* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Fast Ethernet) pci:v00001011d00000019sv00001186sd00001100* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (DFE-500TX Fast Ethernet) pci:v00001011d00000019sv00001186sd00001101* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (DFE-500TX Fast Ethernet) pci:v00001011d00000019sv00001186sd00001102* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (DFE-500TX Fast Ethernet) pci:v00001011d00000019sv00001186sd00001112* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (DFE-570TX Quad Fast Ethernet) pci:v00001011d00000019sv000011F0sd00004235* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (21143 [FASTLine-II UTP 10/100]) pci:v00001011d00000019sv00001259sd00002800* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (AT-2800Tx Fast Ethernet) pci:v00001011d00000019sv00001266sd00000004* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Eagle Fast EtherMAX) pci:v00001011d00000019sv000012AFsd00000019* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (NetFlyer Cardbus Fast Ethernet) pci:v00001011d00000019sv00001374sd00000001* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Ethernet Card 10/100) pci:v00001011d00000019sv00001374sd00000002* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Ethernet Card 10/100) pci:v00001011d00000019sv00001374sd00000007* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Ethernet Card 10/100) pci:v00001011d00000019sv00001374sd00000008* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Ethernet Card 10/100) pci:v00001011d00000019sv00001385sd00002100* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (FA510) pci:v00001011d00000019sv00001395sd00000001* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (10/100 Ethernet CardBus PC Card) pci:v00001011d00000019sv000013D1sd0000AB01* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (EtherFast 10/100 Cardbus (PCMPC200)) pci:v00001011d00000019sv00001498sd0000000A* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (TPMC880-10 10/100Base-T and 10Base2 PMC Ethernet Adapter) pci:v00001011d00000019sv00001498sd0000000B* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (TPMC880-11 Single 10/100Base-T PMC Ethernet Adapter) pci:v00001011d00000019sv00001498sd0000000C* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (TPMC880-12 Single 10Base2 PMC Ethernet Adapter) pci:v00001011d00000019sv000014CBsd00000100* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (LNDL-100N 100Base-TX Ethernet PC Card) pci:v00001011d00000019sv00001668sd00002000* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (FastNet Pro (PE2000)) pci:v00001011d00000019sv00002646sd00000001* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (KNE100TX) pci:v00001011d00000019sv00002646sd00000002* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (KNE-CB4TX) pci:v00001011d00000019sv00008086sd00000001* ID_MODEL_FROM_DATABASE=DECchip 21142/43 (EtherExpress PRO/100 Mobile CardBus 32) pci:v00001011d0000001A* ID_MODEL_FROM_DATABASE=Farallon PN9000SX Gigabit Ethernet pci:v00001011d00000021* ID_MODEL_FROM_DATABASE=DECchip 21052 pci:v00001011d00000022* ID_MODEL_FROM_DATABASE=DECchip 21150 pci:v00001011d00000023* ID_MODEL_FROM_DATABASE=DECchip 21150 pci:v00001011d00000024* ID_MODEL_FROM_DATABASE=DECchip 21152 pci:v00001011d00000025* ID_MODEL_FROM_DATABASE=DECchip 21153 pci:v00001011d00000026* ID_MODEL_FROM_DATABASE=DECchip 21154 pci:v00001011d00000034* ID_MODEL_FROM_DATABASE=56k Modem Cardbus pci:v00001011d00000034sv00001374sd00000003* ID_MODEL_FROM_DATABASE=56k Modem Cardbus pci:v00001011d00000045* ID_MODEL_FROM_DATABASE=DECchip 21553 pci:v00001011d00000046* ID_MODEL_FROM_DATABASE=DECchip 21554 pci:v00001011d00000046sv00000E11sd00004050* ID_MODEL_FROM_DATABASE=DECchip 21554 (Smart Array 4200 Controller) pci:v00001011d00000046sv00000E11sd00004051* ID_MODEL_FROM_DATABASE=DECchip 21554 (Smart Array 4250ES Controller) pci:v00001011d00000046sv00000E11sd00004058* ID_MODEL_FROM_DATABASE=DECchip 21554 (Smart Array 431 Controller) pci:v00001011d00000046sv0000103Csd000010C2* ID_MODEL_FROM_DATABASE=DECchip 21554 (NetRAID-4M) pci:v00001011d00000046sv000012D9sd0000000A* ID_MODEL_FROM_DATABASE=DECchip 21554 (IP Telephony card) pci:v00001011d00000046sv00004C53sd00001050* ID_MODEL_FROM_DATABASE=DECchip 21554 (CT7 mainboard) pci:v00001011d00000046sv00004C53sd00001051* ID_MODEL_FROM_DATABASE=DECchip 21554 (CE7 mainboard) pci:v00001011d00000046sv00009005sd00000364* ID_MODEL_FROM_DATABASE=DECchip 21554 (5400S (Mustang)) pci:v00001011d00000046sv00009005sd00000365* ID_MODEL_FROM_DATABASE=DECchip 21554 (5400S (Mustang)) pci:v00001011d00000046sv00009005sd00001364* ID_MODEL_FROM_DATABASE=DECchip 21554 (Dell PowerEdge RAID Controller 2) pci:v00001011d00000046sv00009005sd00001365* ID_MODEL_FROM_DATABASE=DECchip 21554 (Dell PowerEdge RAID Controller 2) pci:v00001011d00000046sv0000E4BFsd00001000* ID_MODEL_FROM_DATABASE=DECchip 21554 (CC8-1-BLUES) pci:v00001011d00001065* ID_MODEL_FROM_DATABASE=StrongARM DC21285 pci:v00001011d00001065sv00001069sd00000020* ID_MODEL_FROM_DATABASE=StrongARM DC21285 (DAC960P / DAC1164P) pci:v00001012* ID_VENDOR_FROM_DATABASE=Micronics Computers Inc pci:v00001013* ID_VENDOR_FROM_DATABASE=Cirrus Logic pci:v00001013d00000038* ID_MODEL_FROM_DATABASE=GD 7548 pci:v00001013d00000040* ID_MODEL_FROM_DATABASE=GD 7555 Flat Panel GUI Accelerator pci:v00001013d0000004C* ID_MODEL_FROM_DATABASE=GD 7556 Video/Graphics LCD/CRT Ctrlr pci:v00001013d000000A0* ID_MODEL_FROM_DATABASE=GD 5430/40 [Alpine] pci:v00001013d000000A2* ID_MODEL_FROM_DATABASE=GD 5432 [Alpine] pci:v00001013d000000A4* ID_MODEL_FROM_DATABASE=GD 5434-4 [Alpine] pci:v00001013d000000A8* ID_MODEL_FROM_DATABASE=GD 5434-8 [Alpine] pci:v00001013d000000AC* ID_MODEL_FROM_DATABASE=GD 5436 [Alpine] pci:v00001013d000000B0* ID_MODEL_FROM_DATABASE=GD 5440 pci:v00001013d000000B8* ID_MODEL_FROM_DATABASE=GD 5446 pci:v00001013d000000B8sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=GD 5446 (QEMU Virtual Machine) pci:v00001013d000000BC* ID_MODEL_FROM_DATABASE=GD 5480 pci:v00001013d000000BCsv00001013sd000000BC* ID_MODEL_FROM_DATABASE=GD 5480 (CL-GD5480) pci:v00001013d000000D0* ID_MODEL_FROM_DATABASE=GD 5462 pci:v00001013d000000D2* ID_MODEL_FROM_DATABASE=GD 5462 [Laguna I] pci:v00001013d000000D4* ID_MODEL_FROM_DATABASE=GD 5464 [Laguna] pci:v00001013d000000D5* ID_MODEL_FROM_DATABASE=GD 5464 BD [Laguna] pci:v00001013d000000D6* ID_MODEL_FROM_DATABASE=GD 5465 [Laguna] pci:v00001013d000000D6sv000013CEsd00008031* ID_MODEL_FROM_DATABASE=GD 5465 [Laguna] (Barco Metheus 2 Megapixel, Dual Head) pci:v00001013d000000D6sv000013CFsd00008031* ID_MODEL_FROM_DATABASE=GD 5465 [Laguna] (Barco Metheus 2 Megapixel, Dual Head) pci:v00001013d000000E8* ID_MODEL_FROM_DATABASE=GD 5436U pci:v00001013d00001100* ID_MODEL_FROM_DATABASE=CL 6729 pci:v00001013d00001110* ID_MODEL_FROM_DATABASE=PD 6832 PCMCIA/CardBus Ctrlr pci:v00001013d00001112* ID_MODEL_FROM_DATABASE=PD 6834 PCMCIA/CardBus Ctrlr pci:v00001013d00001113* ID_MODEL_FROM_DATABASE=PD 6833 PCMCIA/CardBus Ctrlr pci:v00001013d00001200* ID_MODEL_FROM_DATABASE=GD 7542 [Nordic] pci:v00001013d00001202* ID_MODEL_FROM_DATABASE=GD 7543 [Viking] pci:v00001013d00001204* ID_MODEL_FROM_DATABASE=GD 7541 [Nordic Light] pci:v00001013d00004000* ID_MODEL_FROM_DATABASE=MD 5620 [CLM Data Fax Voice] pci:v00001013d00004400* ID_MODEL_FROM_DATABASE=CD 4400 pci:v00001013d00006001* ID_MODEL_FROM_DATABASE=CS 4610/11 [CrystalClear SoundFusion Audio Accelerator] pci:v00001013d00006001sv00001014sd00001010* ID_MODEL_FROM_DATABASE=CS 4610/11 [CrystalClear SoundFusion Audio Accelerator] (CS4610 SoundFusion Audio Accelerator) pci:v00001013d00006003* ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] pci:v00001013d00006003sv00001013sd00004280* ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (Crystal SoundFusion PCI Audio Accelerator) pci:v00001013d00006003sv00001014sd00000153* ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (ThinkPad 600X/A20m) pci:v00001013d00006003sv0000153Bsd0000112E* ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (DMX XFire 1024) pci:v00001013d00006003sv0000153Bsd00001136* ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (SiXPack 5.1+) pci:v00001013d00006003sv00001681sd00000050* ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (Game Theater XP) pci:v00001013d00006003sv00001681sd0000A010* ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (Gamesurround Fortissimo II) pci:v00001013d00006003sv00001681sd0000A011* ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (Gamesurround Fortissimo III 7.1) pci:v00001013d00006003sv00005053sd00003357* ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (Santa Cruz) pci:v00001013d00006004* ID_MODEL_FROM_DATABASE=CS 4614/22/24 [CrystalClear SoundFusion Audio Accelerator] pci:v00001013d00006005* ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio pci:v00001013d00006005sv00001013sd00004281* ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio pci:v00001013d00006005sv000010CFsd000010A8* ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio pci:v00001013d00006005sv000010CFsd000010A9* ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio pci:v00001013d00006005sv000010CFsd000010AA* ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio pci:v00001013d00006005sv000010CFsd000010AB* ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio pci:v00001013d00006005sv000010CFsd000010AC* ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio pci:v00001013d00006005sv000010CFsd000010AD* ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio pci:v00001013d00006005sv000010CFsd000010B4* ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio pci:v00001013d00006005sv00001179sd00000001* ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio pci:v00001013d00006005sv000014C0sd0000000C* ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio pci:v00001014* ID_VENDOR_FROM_DATABASE=IBM pci:v00001014d00000002* ID_MODEL_FROM_DATABASE=PCI to MCA Bridge pci:v00001014d00000005* ID_MODEL_FROM_DATABASE=Processor to I/O Controller [Alta Lite] pci:v00001014d00000007* ID_MODEL_FROM_DATABASE=Processor to I/O Controller [Alta MP] pci:v00001014d0000000A* ID_MODEL_FROM_DATABASE=PCI to ISA Bridge (IBM27-82376) [Fire Coral] pci:v00001014d00000017* ID_MODEL_FROM_DATABASE=CPU to PCI Bridge pci:v00001014d00000018* ID_MODEL_FROM_DATABASE=TR Auto LANstreamer pci:v00001014d0000001B* ID_MODEL_FROM_DATABASE=GXT-150P pci:v00001014d0000001C* ID_MODEL_FROM_DATABASE=Carrera pci:v00001014d0000001D* ID_MODEL_FROM_DATABASE=SCSI-2 FAST PCI Adapter (82G2675) pci:v00001014d00000020* ID_MODEL_FROM_DATABASE=GXT1000 Graphics Adapter pci:v00001014d00000022* ID_MODEL_FROM_DATABASE=PCI to PCI Bridge (IBM27-82351) pci:v00001014d0000002D* ID_MODEL_FROM_DATABASE=Processor to I/O Controller [Python] pci:v00001014d0000002E* ID_MODEL_FROM_DATABASE=SCSI RAID Adapter [ServeRAID] pci:v00001014d0000002Esv00001014sd0000002E* ID_MODEL_FROM_DATABASE=SCSI RAID Adapter [ServeRAID] (ServeRAID-3x) pci:v00001014d0000002Esv00001014sd0000022E* ID_MODEL_FROM_DATABASE=SCSI RAID Adapter [ServeRAID] (ServeRAID-4H) pci:v00001014d00000031* ID_MODEL_FROM_DATABASE=2 Port Serial Adapter pci:v00001014d00000031sv00001014sd00000031* ID_MODEL_FROM_DATABASE=2 Port Serial Adapter (2721 WAN IOA - 2 Port Sync Serial Adapter) pci:v00001014d00000036* ID_MODEL_FROM_DATABASE=PCI to 32-bit LocalBus Bridge [Miami] pci:v00001014d00000037* ID_MODEL_FROM_DATABASE=PowerPC to PCI Bridge (IBM27-82660) pci:v00001014d0000003A* ID_MODEL_FROM_DATABASE=CPU to PCI Bridge pci:v00001014d0000003C* ID_MODEL_FROM_DATABASE=GXT250P/GXT255P Graphics Adapter pci:v00001014d0000003E* ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller pci:v00001014d0000003Esv00001014sd0000003E* ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (Token-Ring Adapter) pci:v00001014d0000003Esv00001014sd000000CD* ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (Token-Ring Adapter + Wake-On-LAN) pci:v00001014d0000003Esv00001014sd000000CE* ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (16/4 Token-Ring Adapter 2) pci:v00001014d0000003Esv00001014sd000000CF* ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (16/4 Token-Ring Adapter Special) pci:v00001014d0000003Esv00001014sd000000E4* ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (High-Speed 100/16/4 Token-Ring Adapter) pci:v00001014d0000003Esv00001014sd000000E5* ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (16/4 Token-Ring Adapter 2 + Wake-On-LAN) pci:v00001014d0000003Esv00001014sd0000016D* ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (iSeries 2744 Card) pci:v00001014d00000045* ID_MODEL_FROM_DATABASE=SSA Adapter pci:v00001014d00000046* ID_MODEL_FROM_DATABASE=MPIC interrupt controller pci:v00001014d00000047* ID_MODEL_FROM_DATABASE=PCI to PCI Bridge pci:v00001014d00000048* ID_MODEL_FROM_DATABASE=PCI to PCI Bridge pci:v00001014d00000049* ID_MODEL_FROM_DATABASE=Warhead SCSI Controller pci:v00001014d0000004E* ID_MODEL_FROM_DATABASE=ATM Controller (14104e00) pci:v00001014d0000004F* ID_MODEL_FROM_DATABASE=ATM Controller (14104f00) pci:v00001014d00000050* ID_MODEL_FROM_DATABASE=ATM Controller (14105000) pci:v00001014d00000053* ID_MODEL_FROM_DATABASE=25 MBit ATM Controller pci:v00001014d00000054* ID_MODEL_FROM_DATABASE=GXT500P/GXT550P Graphics Adapter pci:v00001014d00000057* ID_MODEL_FROM_DATABASE=MPEG PCI Bridge pci:v00001014d00000058* ID_MODEL_FROM_DATABASE=SSA Adapter [Advanced SerialRAID/X] pci:v00001014d0000005E* ID_MODEL_FROM_DATABASE=GXT800P Graphics Adapter pci:v00001014d0000007C* ID_MODEL_FROM_DATABASE=ATM Controller (14107c00) pci:v00001014d0000007D* ID_MODEL_FROM_DATABASE=3780IDSP [MWave] pci:v00001014d0000008B* ID_MODEL_FROM_DATABASE=EADS PCI to PCI Bridge pci:v00001014d0000008E* ID_MODEL_FROM_DATABASE=GXT3000P Graphics Adapter pci:v00001014d00000090* ID_MODEL_FROM_DATABASE=GXT 3000P pci:v00001014d00000090sv00001014sd0000008E* ID_MODEL_FROM_DATABASE=GXT 3000P (GXT-3000P) pci:v00001014d00000091* ID_MODEL_FROM_DATABASE=SSA Adapter pci:v00001014d00000095* ID_MODEL_FROM_DATABASE=20H2999 PCI Docking Bridge pci:v00001014d00000096* ID_MODEL_FROM_DATABASE=Chukar chipset SCSI controller pci:v00001014d00000096sv00001014sd00000097* ID_MODEL_FROM_DATABASE=Chukar chipset SCSI controller (iSeries 2778 DASD IOA) pci:v00001014d00000096sv00001014sd00000098* ID_MODEL_FROM_DATABASE=Chukar chipset SCSI controller (iSeries 2763 DASD IOA) pci:v00001014d00000096sv00001014sd00000099* ID_MODEL_FROM_DATABASE=Chukar chipset SCSI controller (iSeries 2748 DASD IOA) pci:v00001014d0000009F* ID_MODEL_FROM_DATABASE=PCI 4758 Cryptographic Accelerator pci:v00001014d000000A5* ID_MODEL_FROM_DATABASE=ATM Controller (1410a500) pci:v00001014d000000A6* ID_MODEL_FROM_DATABASE=ATM 155MBPS MM Controller (1410a600) pci:v00001014d000000B7* ID_MODEL_FROM_DATABASE=GXT2000P Graphics Adapter pci:v00001014d000000B7sv00001092sd000000B8* ID_MODEL_FROM_DATABASE=GXT2000P Graphics Adapter (FireGL1 AGP 32Mb) pci:v00001014d000000B8* ID_MODEL_FROM_DATABASE=GXT2000P Graphics Adapter pci:v00001014d000000BE* ID_MODEL_FROM_DATABASE=ATM 622MBPS Controller (1410be00) pci:v00001014d000000DC* ID_MODEL_FROM_DATABASE=Advanced Systems Management Adapter (ASMA) pci:v00001014d000000FC* ID_MODEL_FROM_DATABASE=CPC710 Dual Bridge and Memory Controller (PCI-64) pci:v00001014d00000105* ID_MODEL_FROM_DATABASE=CPC710 Dual Bridge and Memory Controller (PCI-32) pci:v00001014d0000010F* ID_MODEL_FROM_DATABASE=Remote Supervisor Adapter (RSA) pci:v00001014d00000142* ID_MODEL_FROM_DATABASE=Yotta Video Compositor Input pci:v00001014d00000142sv00001014sd00000143* ID_MODEL_FROM_DATABASE=Yotta Video Compositor Input (Yotta Input Controller (ytin)) pci:v00001014d00000144* ID_MODEL_FROM_DATABASE=Yotta Video Compositor Output pci:v00001014d00000144sv00001014sd00000145* ID_MODEL_FROM_DATABASE=Yotta Video Compositor Output (Yotta Output Controller (ytout)) pci:v00001014d00000156* ID_MODEL_FROM_DATABASE=405GP PLB to PCI Bridge pci:v00001014d0000015E* ID_MODEL_FROM_DATABASE=622Mbps ATM PCI Adapter pci:v00001014d00000160* ID_MODEL_FROM_DATABASE=64bit/66MHz PCI ATM 155 MMF pci:v00001014d0000016E* ID_MODEL_FROM_DATABASE=GXT4000P Graphics Adapter pci:v00001014d00000170* ID_MODEL_FROM_DATABASE=GXT6000P Graphics Adapter pci:v00001014d00000170sv00001092sd00000172* ID_MODEL_FROM_DATABASE=GXT6000P Graphics Adapter (Fire GL2) pci:v00001014d00000170sv00001092sd00000173* ID_MODEL_FROM_DATABASE=GXT6000P Graphics Adapter (Fire GL3) pci:v00001014d00000170sv00001092sd00000174* ID_MODEL_FROM_DATABASE=GXT6000P Graphics Adapter (Fire GL4) pci:v00001014d00000170sv00001092sd00000184* ID_MODEL_FROM_DATABASE=GXT6000P Graphics Adapter (Fire GL4s) pci:v00001014d0000017D* ID_MODEL_FROM_DATABASE=GXT300P Graphics Adapter pci:v00001014d00000180* ID_MODEL_FROM_DATABASE=Snipe chipset SCSI controller pci:v00001014d00000180sv00001014sd00000241* ID_MODEL_FROM_DATABASE=Snipe chipset SCSI controller (iSeries 2757 DASD IOA) pci:v00001014d00000180sv00001014sd00000264* ID_MODEL_FROM_DATABASE=Snipe chipset SCSI controller (Quad Channel PCI-X U320 SCSI RAID Adapter (2780)) pci:v00001014d00000188* ID_MODEL_FROM_DATABASE=EADS-X PCI-X to PCI-X Bridge pci:v00001014d000001A7* ID_MODEL_FROM_DATABASE=PCI-X to PCI-X Bridge pci:v00001014d000001BD* ID_MODEL_FROM_DATABASE=ServeRAID Controller pci:v00001014d000001BDsv00001014sd000001BD* ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID 4Lx) pci:v00001014d000001BDsv00001014sd000001BE* ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-4M) pci:v00001014d000001BDsv00001014sd000001BF* ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-4L) pci:v00001014d000001BDsv00001014sd00000208* ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-4Mx) pci:v00001014d000001BDsv00001014sd0000020E* ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-4Lx) pci:v00001014d000001BDsv00001014sd0000022E* ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-4H) pci:v00001014d000001BDsv00001014sd00000258* ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-5i) pci:v00001014d000001BDsv00001014sd00000259* ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-5i) pci:v00001014d000001C1* ID_MODEL_FROM_DATABASE=64bit/66MHz PCI ATM 155 UTP pci:v00001014d000001E6* ID_MODEL_FROM_DATABASE=Cryptographic Accelerator pci:v00001014d000001EF* ID_MODEL_FROM_DATABASE=PowerPC 440GP PCI Bridge pci:v00001014d000001EFsv00001734sd0000102B* ID_MODEL_FROM_DATABASE=PowerPC 440GP PCI Bridge (PCEAS PCI-X Dual Port ESCON Adapter) pci:v00001014d000001EFsv00001734sd000010F8* ID_MODEL_FROM_DATABASE=PowerPC 440GP PCI Bridge (PCEAT PCI-Express Dual Port ESCON Adapter) pci:v00001014d000001FF* ID_MODEL_FROM_DATABASE=10/100 Mbps Ethernet pci:v00001014d00000219* ID_MODEL_FROM_DATABASE=Multiport Serial Adapter pci:v00001014d00000219sv00001014sd0000021A* ID_MODEL_FROM_DATABASE=Multiport Serial Adapter (Dual RVX) pci:v00001014d00000219sv00001014sd00000251* ID_MODEL_FROM_DATABASE=Multiport Serial Adapter (Internal Modem/RVX) pci:v00001014d00000219sv00001014sd00000252* ID_MODEL_FROM_DATABASE=Multiport Serial Adapter (Quad Internal Modem) pci:v00001014d0000021B* ID_MODEL_FROM_DATABASE=GXT6500P Graphics Adapter pci:v00001014d0000021C* ID_MODEL_FROM_DATABASE=GXT4500P Graphics Adapter pci:v00001014d00000233* ID_MODEL_FROM_DATABASE=GXT135P Graphics Adapter pci:v00001014d0000028C* ID_MODEL_FROM_DATABASE=Citrine chipset SCSI controller pci:v00001014d0000028Csv00001014sd0000028D* ID_MODEL_FROM_DATABASE=Citrine chipset SCSI controller (Dual Channel PCI-X DDR SAS RAID Adapter (572E)) pci:v00001014d0000028Csv00001014sd000002BE* ID_MODEL_FROM_DATABASE=Citrine chipset SCSI controller (Dual Channel PCI-X DDR U320 SCSI RAID Adapter (571B)) pci:v00001014d0000028Csv00001014sd000002C0* ID_MODEL_FROM_DATABASE=Citrine chipset SCSI controller (Dual Channel PCI-X DDR U320 SCSI Adapter (571A)) pci:v00001014d0000028Csv00001014sd0000030D* ID_MODEL_FROM_DATABASE=Citrine chipset SCSI controller (PCI-X DDR Auxiliary Cache Adapter (575B)) pci:v00001014d000002A1* ID_MODEL_FROM_DATABASE=Calgary PCI-X Host Bridge pci:v00001014d000002BD* ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller pci:v00001014d000002BDsv00001014sd000002C1* ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller (PCI-X DDR 3Gb SAS Adapter (572A/572C)) pci:v00001014d000002BDsv00001014sd000002C2* ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller (PCI-X DDR 3Gb SAS RAID Adapter (572B/571D)) pci:v00001014d000002BDsv00001014sd00000338* ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller (PCI-X DDR Auxiliary Cache Adapter (575C)) pci:v00001014d00000302* ID_MODEL_FROM_DATABASE=Winnipeg PCI-X Host Bridge pci:v00001014d00000308* ID_MODEL_FROM_DATABASE=CalIOC2 PCI-E Root Port pci:v00001014d00000314* ID_MODEL_FROM_DATABASE=ZISC 036 Neural accelerator card pci:v00001014d0000032D* ID_MODEL_FROM_DATABASE=Axon - Cell Companion Chip pci:v00001014d0000032Dsv00001014sd000003A1* ID_MODEL_FROM_DATABASE=Axon - Cell Companion Chip (PCIe PowerXCell 8i Cell Accelerator Board) pci:v00001014d00000339* ID_MODEL_FROM_DATABASE=Obsidian-E PCI-E SCSI controller pci:v00001014d00000339sv00001014sd0000030A* ID_MODEL_FROM_DATABASE=Obsidian-E PCI-E SCSI controller (PCIe 3Gb SAS RAID Adapter (574E)) pci:v00001014d00000339sv00001014sd0000033A* ID_MODEL_FROM_DATABASE=Obsidian-E PCI-E SCSI controller (PCIe 3Gb SAS Adapter (57B3)) pci:v00001014d00000339sv00001014sd0000035C* ID_MODEL_FROM_DATABASE=Obsidian-E PCI-E SCSI controller (PCIe x8 Internal 3Gb SAS adapter (57CC)) pci:v00001014d00000339sv00001014sd00000360* ID_MODEL_FROM_DATABASE=Obsidian-E PCI-E SCSI controller (PCI-E Auxiliary Cache Adapter (57B7)) pci:v00001014d0000033D* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (FPGA) pci:v00001014d0000033Dsv00001014sd0000033C* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (FPGA) (PCIe2 1.8GB Cache 6Gb SAS RAID Adapter Tri-port (57B5)) pci:v00001014d0000033Dsv00001014sd00000353* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (FPGA) (PCIe2 3.1GB Cache 6Gb SAS RAID Enclosure (57C3)) pci:v00001014d0000033Dsv00001014sd00000354* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (FPGA) (PCIe2 6Gb SAS Adapter Dual-port (57C4)) pci:v00001014d0000033Dsv00001014sd00000356* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (FPGA) (PCIe2 1.8GB Cache 6Gb SAS RAID & SSD Adapter (574D)) pci:v00001014d0000033Dsv00001014sd0000035F* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (FPGA) (PCIe2 6Gb SAS Adapter Quad-port (57B2)) pci:v00001014d0000034A* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) pci:v00001014d0000034Asv00001014sd0000033B* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe2 6Gb SAS RAID Adapter Quad-port (57B4)) pci:v00001014d0000034Asv00001014sd00000355* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe2 3.6GB Cache 6Gb SAS RAID Adapter Quad-port (57B1)) pci:v00001014d0000034Asv00001014sd00000357* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe2 6Gb SAS Adapter Quad-port (57C6)) pci:v00001014d0000034Asv00001014sd0000035D* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 1.8GB Cache RAID SAS Adapter Quad-port 6GB (57C8)) pci:v00001014d0000034Asv00001014sd0000035E* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe2 3.6GB Cache 6Gb SAS RAID Adapter Quad-port (57CE)) pci:v00001014d0000034Asv00001014sd000003FB* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 28GB Cache RAID SAS Enclosure 6Gb x 16 (57D5)) pci:v00001014d0000034Asv00001014sd000003FE* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x8 Cache SAS RAID Internal Adapter 6Gb (57D8)) pci:v00001014d0000034Asv00001014sd000003FF* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x8 SAS RAID Internal Adapter 6Gb (57D7)) pci:v00001014d0000034Asv00001014sd00000474* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x16 Cache SAS RAID Internal Adapter 6Gb (57EB)) pci:v00001014d0000034Asv00001014sd00000475* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x16 SAS RAID Internal Adapter 6Gb (57EC)) pci:v00001014d0000034Asv00001014sd00000499* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x16 Cache SAS RAID Internal Adapter 6Gb (57ED)) pci:v00001014d0000034Asv00001014sd0000049A* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x16 SAS RAID Internal Adapter 6Gb (57EE)) pci:v00001014d0000034Asv00001014sd000004C7* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CCA)) pci:v00001014d0000034Asv00001014sd000004C8* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CD2)) pci:v00001014d0000034Asv00001014sd000004C9* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CCD)) pci:v00001014d0000044B* ID_MODEL_FROM_DATABASE=GenWQE Accelerator Adapter pci:v00001014d000004AA* ID_MODEL_FROM_DATABASE=Flash Adapter 90 (PCIe2 0.9TB) pci:v00001014d000004DA* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS+ Adapter (ASIC) pci:v00001014d000004DAsv00001014sd000004FB* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS+ Adapter (ASIC) (PCIe3 x16 20GB Cache 12Gb Quad SAS RAID+ Adapter(580B)) pci:v00001014d000004DAsv00001014sd000004FC* ID_MODEL_FROM_DATABASE=PCI-E IPR SAS+ Adapter (ASIC) (PCIe3 x8 12Gb Quad SAS RAID+ Adapter(580A)) pci:v00001014d00003022* ID_MODEL_FROM_DATABASE=QLA3022 Network Adapter pci:v00001014d00004022* ID_MODEL_FROM_DATABASE=QLA3022 Network Adapter pci:v00001014d0000FFFF* ID_MODEL_FROM_DATABASE=MPIC-2 interrupt controller pci:v00001015* ID_VENDOR_FROM_DATABASE=LSI Logic Corp of Canada pci:v00001016* ID_VENDOR_FROM_DATABASE=ICL Personal Systems pci:v00001017* ID_VENDOR_FROM_DATABASE=SPEA Software AG pci:v00001017d00005343* ID_MODEL_FROM_DATABASE=SPEA 3D Accelerator pci:v00001018* ID_VENDOR_FROM_DATABASE=Unisys Systems pci:v00001019* ID_VENDOR_FROM_DATABASE=Elitegroup Computer Systems pci:v0000101A* ID_VENDOR_FROM_DATABASE=AT&T GIS (NCR) pci:v0000101Ad00000005* ID_MODEL_FROM_DATABASE=100VG ethernet pci:v0000101Ad00000007* ID_MODEL_FROM_DATABASE=BYNET BIC4G/2C/2G pci:v0000101Ad00000007sv0000101Asd00000019* ID_MODEL_FROM_DATABASE=BYNET BIC4G/2C/2G (BYNET BIC2C) pci:v0000101Ad00000007sv0000101Asd0000001C* ID_MODEL_FROM_DATABASE=BYNET BIC4G/2C/2G (BYNET BIC2G) pci:v0000101Ad00000007sv0000101Asd0000001F* ID_MODEL_FROM_DATABASE=BYNET BIC4G/2C/2G (BYNET BIC4G) pci:v0000101Ad00000009* ID_MODEL_FROM_DATABASE=PQS Memory Controller pci:v0000101Ad0000000A* ID_MODEL_FROM_DATABASE=BYNET BPCI Adapter pci:v0000101Ad0000000B* ID_MODEL_FROM_DATABASE=BYNET 4 Port BYA Switch (BYA4P) pci:v0000101Ad0000000C* ID_MODEL_FROM_DATABASE=BYNET 4 Port BYA Switch (BYA4G) pci:v0000101Ad00000010* ID_MODEL_FROM_DATABASE=NCR AMC Memory Controller pci:v0000101Ad00001DC1* ID_MODEL_FROM_DATABASE=BYNET BIC2M/BIC4M/BYA4M pci:v0000101Ad00001DC1sv0000101Asd00000019* ID_MODEL_FROM_DATABASE=BYNET BIC2M/BIC4M/BYA4M (BIC2M) pci:v0000101Ad00001DC1sv0000101Asd0000001F* ID_MODEL_FROM_DATABASE=BYNET BIC2M/BIC4M/BYA4M (BIC4M) pci:v0000101Ad00001DC1sv0000101Asd00000ECE* ID_MODEL_FROM_DATABASE=BYNET BIC2M/BIC4M/BYA4M (BYA4M) pci:v0000101Ad00001FA8* ID_MODEL_FROM_DATABASE=BYNET Multi-port BIC Adapter (XBIC Based) pci:v0000101Ad00001FA8sv0000101Asd000000C3* ID_MODEL_FROM_DATABASE=BYNET Multi-port BIC Adapter (XBIC Based) (BYNET BIC2SE) pci:v0000101B* ID_VENDOR_FROM_DATABASE=Vitesse Semiconductor pci:v0000101Bd00000452* ID_MODEL_FROM_DATABASE=VSC452 [SuperBMC] pci:v0000101C* ID_VENDOR_FROM_DATABASE=Western Digital pci:v0000101Cd00000193* ID_MODEL_FROM_DATABASE=33C193A pci:v0000101Cd00000196* ID_MODEL_FROM_DATABASE=33C196A pci:v0000101Cd00000197* ID_MODEL_FROM_DATABASE=33C197A pci:v0000101Cd00000296* ID_MODEL_FROM_DATABASE=33C296A pci:v0000101Cd00003193* ID_MODEL_FROM_DATABASE=7193 pci:v0000101Cd00003197* ID_MODEL_FROM_DATABASE=7197 pci:v0000101Cd00003296* ID_MODEL_FROM_DATABASE=33C296A pci:v0000101Cd00004296* ID_MODEL_FROM_DATABASE=34C296 pci:v0000101Cd00009710* ID_MODEL_FROM_DATABASE=Pipeline 9710 pci:v0000101Cd00009712* ID_MODEL_FROM_DATABASE=Pipeline 9712 pci:v0000101Cd0000C24A* ID_MODEL_FROM_DATABASE=90C pci:v0000101D* ID_VENDOR_FROM_DATABASE=Maxim Integrated Products pci:v0000101E* ID_VENDOR_FROM_DATABASE=American Megatrends Inc. pci:v0000101Ed00000009* ID_MODEL_FROM_DATABASE=MegaRAID 428 Ultra RAID Controller (rev 03) pci:v0000101Ed00001960* ID_MODEL_FROM_DATABASE=MegaRAID pci:v0000101Ed00001960sv0000101Esd00000471* ID_MODEL_FROM_DATABASE=MegaRAID (471 Enterprise 1600 RAID Controller) pci:v0000101Ed00001960sv0000101Esd00000475* ID_MODEL_FROM_DATABASE=MegaRAID (475 Express 500/500LC RAID Controller) pci:v0000101Ed00001960sv0000101Esd00000477* ID_MODEL_FROM_DATABASE=MegaRAID (477 Elite 3100 RAID Controller) pci:v0000101Ed00001960sv0000101Esd00000493* ID_MODEL_FROM_DATABASE=MegaRAID (493 Elite 1600 RAID Controller) pci:v0000101Ed00001960sv0000101Esd00000494* ID_MODEL_FROM_DATABASE=MegaRAID (494 Elite 1650 RAID Controller) pci:v0000101Ed00001960sv0000101Esd00000503* ID_MODEL_FROM_DATABASE=MegaRAID (503 Enterprise 1650 RAID Controller) pci:v0000101Ed00001960sv0000101Esd00000511* ID_MODEL_FROM_DATABASE=MegaRAID (511 i4 IDE RAID Controller) pci:v0000101Ed00001960sv0000101Esd00000522* ID_MODEL_FROM_DATABASE=MegaRAID (522 i4133 RAID Controller) pci:v0000101Ed00001960sv00001028sd00000471* ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller 3/QC) pci:v0000101Ed00001960sv00001028sd00000475* ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller 3/SC) pci:v0000101Ed00001960sv00001028sd00000493* ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller 3/DC) pci:v0000101Ed00001960sv00001028sd00000511* ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge Cost Effective RAID Controller ATA100/4Ch) pci:v0000101Ed00001960sv0000103Csd000060E7* ID_MODEL_FROM_DATABASE=MegaRAID (NetRAID-1M) pci:v0000101Ed00001960sv0000103Csd000060E8* ID_MODEL_FROM_DATABASE=MegaRAID (NetRaid 2M [AMI MegaRaid 493]) pci:v0000101Ed00009010* ID_MODEL_FROM_DATABASE=MegaRAID 428 Ultra RAID Controller pci:v0000101Ed00009030* ID_MODEL_FROM_DATABASE=EIDE Controller pci:v0000101Ed00009031* ID_MODEL_FROM_DATABASE=EIDE Controller pci:v0000101Ed00009032* ID_MODEL_FROM_DATABASE=EIDE & SCSI Controller pci:v0000101Ed00009033* ID_MODEL_FROM_DATABASE=SCSI Controller pci:v0000101Ed00009040* ID_MODEL_FROM_DATABASE=Multimedia card pci:v0000101Ed00009060* ID_MODEL_FROM_DATABASE=MegaRAID 434 Ultra GT RAID Controller pci:v0000101Ed00009063* ID_MODEL_FROM_DATABASE=MegaRAC pci:v0000101Ed00009063sv0000101Esd00000767* ID_MODEL_FROM_DATABASE=MegaRAC (Dell Remote Assistant Card 2) pci:v0000101F* ID_VENDOR_FROM_DATABASE=PictureTel pci:v00001020* ID_VENDOR_FROM_DATABASE=Hitachi Computer Products pci:v00001021* ID_VENDOR_FROM_DATABASE=OKI Electric Industry Co. Ltd. pci:v00001022* ID_VENDOR_FROM_DATABASE=Advanced Micro Devices, Inc. [AMD] pci:v00001022d00001100* ID_MODEL_FROM_DATABASE=K8 [Athlon64/Opteron] HyperTransport Technology Configuration pci:v00001022d00001101* ID_MODEL_FROM_DATABASE=K8 [Athlon64/Opteron] Address Map pci:v00001022d00001102* ID_MODEL_FROM_DATABASE=K8 [Athlon64/Opteron] DRAM Controller pci:v00001022d00001103* ID_MODEL_FROM_DATABASE=K8 [Athlon64/Opteron] Miscellaneous Control pci:v00001022d00001200* ID_MODEL_FROM_DATABASE=Family 10h Processor HyperTransport Configuration pci:v00001022d00001201* ID_MODEL_FROM_DATABASE=Family 10h Processor Address Map pci:v00001022d00001202* ID_MODEL_FROM_DATABASE=Family 10h Processor DRAM Controller pci:v00001022d00001203* ID_MODEL_FROM_DATABASE=Family 10h Processor Miscellaneous Control pci:v00001022d00001204* ID_MODEL_FROM_DATABASE=Family 10h Processor Link Control pci:v00001022d00001300* ID_MODEL_FROM_DATABASE=Family 11h Processor HyperTransport Configuration pci:v00001022d00001301* ID_MODEL_FROM_DATABASE=Family 11h Processor Address Map pci:v00001022d00001302* ID_MODEL_FROM_DATABASE=Family 11h Processor DRAM Controller pci:v00001022d00001303* ID_MODEL_FROM_DATABASE=Family 11h Processor Miscellaneous Control pci:v00001022d00001304* ID_MODEL_FROM_DATABASE=Family 11h Processor Link Control pci:v00001022d00001400* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Function 0 pci:v00001022d00001401* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Function 1 pci:v00001022d00001402* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Function 2 pci:v00001022d00001403* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Function 3 pci:v00001022d00001404* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Function 4 pci:v00001022d00001405* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Function 5 pci:v00001022d00001410* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Complex pci:v00001022d00001410sv0000103Csd00001985* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Complex (Pavilion 17-e163sg Notebook PC) pci:v00001022d00001412* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port pci:v00001022d00001412sv00001022sd00001234* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port (Trinity A-series APU) pci:v00001022d00001413* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port pci:v00001022d00001414* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port pci:v00001022d00001414sv00001022sd00001234* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port (Trinity A-series APU) pci:v00001022d00001415* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port pci:v00001022d00001416* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port pci:v00001022d00001417* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port pci:v00001022d00001418* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port pci:v00001022d00001419* ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) I/O Memory Management Unit pci:v00001022d0000141A* ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Function 0 pci:v00001022d0000141B* ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Function 1 pci:v00001022d0000141C* ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Function 2 pci:v00001022d0000141D* ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Function 3 pci:v00001022d0000141E* ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Function 4 pci:v00001022d0000141F* ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Function 5 pci:v00001022d00001422* ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Root Complex pci:v00001022d00001423* ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) I/O Memory Management Unit pci:v00001022d00001426* ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Root Port pci:v00001022d00001436* ID_MODEL_FROM_DATABASE=Liverpool Processor Root Complex pci:v00001022d00001437* ID_MODEL_FROM_DATABASE=Liverpool I/O Memory Management Unit pci:v00001022d00001438* ID_MODEL_FROM_DATABASE=Liverpool Processor Root Port pci:v00001022d00001439* ID_MODEL_FROM_DATABASE=Family 16h Processor Functions 5:1 pci:v00001022d0000145B* ID_MODEL_FROM_DATABASE=Zeppelin Non-Transparent Bridge pci:v00001022d00001510* ID_MODEL_FROM_DATABASE=Family 14h Processor Root Complex pci:v00001022d00001510sv0000174Bsd00001001* ID_MODEL_FROM_DATABASE=Family 14h Processor Root Complex (PURE Fusion Mini) pci:v00001022d00001512* ID_MODEL_FROM_DATABASE=Family 14h Processor Root Port pci:v00001022d00001513* ID_MODEL_FROM_DATABASE=Family 14h Processor Root Port pci:v00001022d00001514* ID_MODEL_FROM_DATABASE=Family 14h Processor Root Port pci:v00001022d00001515* ID_MODEL_FROM_DATABASE=Family 14h Processor Root Port pci:v00001022d00001516* ID_MODEL_FROM_DATABASE=Family 14h Processor Root Port pci:v00001022d00001530* ID_MODEL_FROM_DATABASE=Family 16h Processor Function 0 pci:v00001022d00001531* ID_MODEL_FROM_DATABASE=Family 16h Processor Function 1 pci:v00001022d00001532* ID_MODEL_FROM_DATABASE=Family 16h Processor Function 2 pci:v00001022d00001533* ID_MODEL_FROM_DATABASE=Family 16h Processor Function 3 pci:v00001022d00001534* ID_MODEL_FROM_DATABASE=Family 16h Processor Function 4 pci:v00001022d00001535* ID_MODEL_FROM_DATABASE=Family 16h Processor Function 5 pci:v00001022d00001536* ID_MODEL_FROM_DATABASE=Family 16h Processor Root Complex pci:v00001022d00001538* ID_MODEL_FROM_DATABASE=Family 16h Processor Function 0 pci:v00001022d00001600* ID_MODEL_FROM_DATABASE=Family 15h Processor Function 0 pci:v00001022d00001601* ID_MODEL_FROM_DATABASE=Family 15h Processor Function 1 pci:v00001022d00001602* ID_MODEL_FROM_DATABASE=Family 15h Processor Function 2 pci:v00001022d00001603* ID_MODEL_FROM_DATABASE=Family 15h Processor Function 3 pci:v00001022d00001604* ID_MODEL_FROM_DATABASE=Family 15h Processor Function 4 pci:v00001022d00001605* ID_MODEL_FROM_DATABASE=Family 15h Processor Function 5 pci:v00001022d00001700* ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 0 pci:v00001022d00001701* ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 1 pci:v00001022d00001702* ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 2 pci:v00001022d00001703* ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 3 pci:v00001022d00001704* ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 4 pci:v00001022d00001705* ID_MODEL_FROM_DATABASE=Family 12h Processor Root Complex pci:v00001022d00001707* ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port pci:v00001022d00001708* ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port pci:v00001022d00001709* ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port pci:v00001022d0000170A* ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port pci:v00001022d0000170B* ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port pci:v00001022d0000170C* ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port pci:v00001022d0000170D* ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port pci:v00001022d00001716* ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 5 pci:v00001022d00001718* ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 6 pci:v00001022d00001719* ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 7 pci:v00001022d00002000* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] pci:v00001022d00002000sv00001014sd00002000* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (NetFinity 10/100 Fast Ethernet) pci:v00001022d00002000sv00001022sd00002000* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (PCnet - Fast 79C971) pci:v00001022d00002000sv0000103Csd0000104C* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (Ethernet with LAN remote power Adapter) pci:v00001022d00002000sv0000103Csd00001064* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (Ethernet with LAN remote power Adapter) pci:v00001022d00002000sv0000103Csd00001065* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (Ethernet with LAN remote power Adapter) pci:v00001022d00002000sv0000103Csd0000106C* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (Ethernet with LAN remote power Adapter) pci:v00001022d00002000sv0000103Csd0000106E* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (Ethernet with LAN remote power Adapter) pci:v00001022d00002000sv0000103Csd000010EA* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (Ethernet with LAN remote power Adapter) pci:v00001022d00002000sv00001113sd00001220* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (EN1220 10/100 Fast Ethernet) pci:v00001022d00002000sv00001259sd00002450* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2450 10/100 Fast Ethernet) pci:v00001022d00002000sv00001259sd00002454* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2450v4 10Mb Ethernet Adapter) pci:v00001022d00002000sv00001259sd00002700* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2700TX 10/100 Fast Ethernet) pci:v00001022d00002000sv00001259sd00002701* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2700FX 100Mb Ethernet) pci:v00001022d00002000sv00001259sd00002702* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2700FTX 10/100 Mb Fiber/Copper Fast Ethernet) pci:v00001022d00002000sv00001259sd00002703* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2701FX) pci:v00001022d00002000sv00001259sd00002704* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2701FTX 10/100 Mb Fiber/Copper Fast Ethernet) pci:v00001022d00002000sv00004C53sd00001000* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (CC7/CR7/CP7/VC7/VP7/VR7 mainboard) pci:v00001022d00002000sv00004C53sd00001010* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (CP5/CR6 mainboard) pci:v00001022d00002000sv00004C53sd00001020* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (VR6 mainboard) pci:v00001022d00002000sv00004C53sd00001030* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (PC5 mainboard) pci:v00001022d00002000sv00004C53sd00001040* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (CL7 mainboard) pci:v00001022d00002000sv00004C53sd00001060* ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (PC7 mainboard) pci:v00001022d00002001* ID_MODEL_FROM_DATABASE=79c978 [HomePNA] pci:v00001022d00002001sv00001092sd00000A78* ID_MODEL_FROM_DATABASE=79c978 [HomePNA] (Multimedia Home Network Adapter) pci:v00001022d00002001sv00001668sd00000299* ID_MODEL_FROM_DATABASE=79c978 [HomePNA] (ActionLink Home Network Adapter) pci:v00001022d00002003* ID_MODEL_FROM_DATABASE=Am 1771 MBW [Alchemy] pci:v00001022d00002020* ID_MODEL_FROM_DATABASE=53c974 [PCscsi] pci:v00001022d00002020sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=53c974 [PCscsi] (QEMU Virtual Machine) pci:v00001022d00002040* ID_MODEL_FROM_DATABASE=79c974 pci:v00001022d00002080* ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] Host Bridge pci:v00001022d00002081* ID_MODEL_FROM_DATABASE=Geode LX Video pci:v00001022d00002082* ID_MODEL_FROM_DATABASE=Geode LX AES Security Block pci:v00001022d0000208F* ID_MODEL_FROM_DATABASE=CS5536 GeodeLink PCI South Bridge pci:v00001022d00002090* ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] ISA pci:v00001022d00002091* ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] FLASH pci:v00001022d00002093* ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] Audio pci:v00001022d00002094* ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] OHC pci:v00001022d00002095* ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] EHC pci:v00001022d00002096* ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] UDC pci:v00001022d00002097* ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] UOC pci:v00001022d0000209A* ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] IDE pci:v00001022d00003000* ID_MODEL_FROM_DATABASE=ELanSC520 Microcontroller pci:v00001022d000043A0* ID_MODEL_FROM_DATABASE=Hudson PCI to PCI bridge (PCIE port 0) pci:v00001022d000043A1* ID_MODEL_FROM_DATABASE=Hudson PCI to PCI bridge (PCIE port 1) pci:v00001022d000043A2* ID_MODEL_FROM_DATABASE=Hudson PCI to PCI bridge (PCIE port 2) pci:v00001022d000043A3* ID_MODEL_FROM_DATABASE=Hudson PCI to PCI bridge (PCIE port 3) pci:v00001022d00007006* ID_MODEL_FROM_DATABASE=AMD-751 [Irongate] System Controller pci:v00001022d00007007* ID_MODEL_FROM_DATABASE=AMD-751 [Irongate] AGP Bridge pci:v00001022d0000700A* ID_MODEL_FROM_DATABASE=AMD-IGR4 AGP Host to PCI Bridge pci:v00001022d0000700B* ID_MODEL_FROM_DATABASE=AMD-IGR4 PCI to PCI Bridge pci:v00001022d0000700C* ID_MODEL_FROM_DATABASE=AMD-760 MP [IGD4-2P] System Controller pci:v00001022d0000700D* ID_MODEL_FROM_DATABASE=AMD-760 MP [IGD4-2P] AGP Bridge pci:v00001022d0000700E* ID_MODEL_FROM_DATABASE=AMD-760 [IGD4-1P] System Controller pci:v00001022d0000700F* ID_MODEL_FROM_DATABASE=AMD-760 [IGD4-1P] AGP Bridge pci:v00001022d00007400* ID_MODEL_FROM_DATABASE=AMD-755 [Cobra] ISA pci:v00001022d00007401* ID_MODEL_FROM_DATABASE=AMD-755 [Cobra] IDE pci:v00001022d00007403* ID_MODEL_FROM_DATABASE=AMD-755 [Cobra] ACPI pci:v00001022d00007404* ID_MODEL_FROM_DATABASE=AMD-755 [Cobra] USB pci:v00001022d00007408* ID_MODEL_FROM_DATABASE=AMD-756 [Viper] ISA pci:v00001022d00007409* ID_MODEL_FROM_DATABASE=AMD-756 [Viper] IDE pci:v00001022d0000740B* ID_MODEL_FROM_DATABASE=AMD-756 [Viper] ACPI pci:v00001022d0000740C* ID_MODEL_FROM_DATABASE=AMD-756 [Viper] USB pci:v00001022d00007410* ID_MODEL_FROM_DATABASE=AMD-766 [ViperPlus] ISA pci:v00001022d00007411* ID_MODEL_FROM_DATABASE=AMD-766 [ViperPlus] IDE pci:v00001022d00007413* ID_MODEL_FROM_DATABASE=AMD-766 [ViperPlus] ACPI pci:v00001022d00007414* ID_MODEL_FROM_DATABASE=AMD-766 [ViperPlus] USB pci:v00001022d00007440* ID_MODEL_FROM_DATABASE=AMD-768 [Opus] ISA pci:v00001022d00007440sv00001043sd00008044* ID_MODEL_FROM_DATABASE=AMD-768 [Opus] ISA (A7M-D Mainboard) pci:v00001022d00007441* ID_MODEL_FROM_DATABASE=AMD-768 [Opus] IDE pci:v00001022d00007443* ID_MODEL_FROM_DATABASE=AMD-768 [Opus] ACPI pci:v00001022d00007443sv00001043sd00008044* ID_MODEL_FROM_DATABASE=AMD-768 [Opus] ACPI (A7M-D Mainboard) pci:v00001022d00007445* ID_MODEL_FROM_DATABASE=AMD-768 [Opus] Audio pci:v00001022d00007446* ID_MODEL_FROM_DATABASE=AMD-768 [Opus] MC97 Modem pci:v00001022d00007448* ID_MODEL_FROM_DATABASE=AMD-768 [Opus] PCI pci:v00001022d00007449* ID_MODEL_FROM_DATABASE=AMD-768 [Opus] USB pci:v00001022d00007450* ID_MODEL_FROM_DATABASE=AMD-8131 PCI-X Bridge pci:v00001022d00007451* ID_MODEL_FROM_DATABASE=AMD-8131 PCI-X IOAPIC pci:v00001022d00007454* ID_MODEL_FROM_DATABASE=AMD-8151 System Controller pci:v00001022d00007455* ID_MODEL_FROM_DATABASE=AMD-8151 AGP Bridge pci:v00001022d00007458* ID_MODEL_FROM_DATABASE=AMD-8132 PCI-X Bridge pci:v00001022d00007459* ID_MODEL_FROM_DATABASE=AMD-8132 PCI-X IOAPIC pci:v00001022d00007460* ID_MODEL_FROM_DATABASE=AMD-8111 PCI pci:v00001022d00007460sv0000161Fsd00003017* ID_MODEL_FROM_DATABASE=AMD-8111 PCI (HDAMB) pci:v00001022d00007461* ID_MODEL_FROM_DATABASE=AMD-8111 USB pci:v00001022d00007462* ID_MODEL_FROM_DATABASE=AMD-8111 Ethernet pci:v00001022d00007463* ID_MODEL_FROM_DATABASE=AMD-8111 USB EHCI pci:v00001022d00007464* ID_MODEL_FROM_DATABASE=AMD-8111 USB OHCI pci:v00001022d00007464sv0000161Fsd00003017* ID_MODEL_FROM_DATABASE=AMD-8111 USB OHCI (HDAMB) pci:v00001022d00007468* ID_MODEL_FROM_DATABASE=AMD-8111 LPC pci:v00001022d00007468sv0000161Fsd00003017* ID_MODEL_FROM_DATABASE=AMD-8111 LPC (HDAMB) pci:v00001022d00007469* ID_MODEL_FROM_DATABASE=AMD-8111 IDE pci:v00001022d00007469sv00001022sd00002B80* ID_MODEL_FROM_DATABASE=AMD-8111 IDE ([Quartet]) pci:v00001022d00007469sv0000161Fsd00003017* ID_MODEL_FROM_DATABASE=AMD-8111 IDE (HDAMB) pci:v00001022d0000746A* ID_MODEL_FROM_DATABASE=AMD-8111 SMBus 2.0 pci:v00001022d0000746B* ID_MODEL_FROM_DATABASE=AMD-8111 ACPI pci:v00001022d0000746Bsv0000161Fsd00003017* ID_MODEL_FROM_DATABASE=AMD-8111 ACPI (HDAMB) pci:v00001022d0000746D* ID_MODEL_FROM_DATABASE=AMD-8111 AC97 Audio pci:v00001022d0000746Dsv0000161Fsd00003017* ID_MODEL_FROM_DATABASE=AMD-8111 AC97 Audio (HDAMB) pci:v00001022d0000746E* ID_MODEL_FROM_DATABASE=AMD-8111 MC97 Modem pci:v00001022d0000756B* ID_MODEL_FROM_DATABASE=AMD-8111 ACPI pci:v00001022d00007800* ID_MODEL_FROM_DATABASE=FCH SATA Controller [IDE mode] pci:v00001022d00007801* ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] pci:v00001022d00007801sv0000103Csd0000168B* ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (ProBook 4535s Notebook) pci:v00001022d00007801sv0000103Csd0000194E* ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (ProBook 455 G1 Notebook) pci:v00001022d00007802* ID_MODEL_FROM_DATABASE=FCH SATA Controller [RAID mode] pci:v00001022d00007803* ID_MODEL_FROM_DATABASE=FCH SATA Controller [RAID mode] pci:v00001022d00007804* ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] pci:v00001022d00007804sv0000103Csd00001985* ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (Pavilion 17-e163sg Notebook PC) pci:v00001022d00007805* ID_MODEL_FROM_DATABASE=FCH SATA Controller [RAID mode] pci:v00001022d00007806* ID_MODEL_FROM_DATABASE=FCH SD Flash Controller pci:v00001022d00007807* ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller pci:v00001022d00007807sv0000103Csd0000194E* ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller (ProBook 455 G1 Notebook) pci:v00001022d00007807sv0000103Csd00001985* ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller (Pavilion 17-e163sg Notebook PC) pci:v00001022d00007808* ID_MODEL_FROM_DATABASE=FCH USB EHCI Controller pci:v00001022d00007808sv0000103Csd0000194E* ID_MODEL_FROM_DATABASE=FCH USB EHCI Controller (ProBook 455 G1 Notebook) pci:v00001022d00007808sv0000103Csd00001985* ID_MODEL_FROM_DATABASE=FCH USB EHCI Controller (Pavilion 17-e163sg Notebook PC) pci:v00001022d00007809* ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller pci:v00001022d00007809sv0000103Csd0000194E* ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller (ProBook 455 G1 Notebook) pci:v00001022d0000780B* ID_MODEL_FROM_DATABASE=FCH SMBus Controller pci:v00001022d0000780Bsv0000103Csd0000194E* ID_MODEL_FROM_DATABASE=FCH SMBus Controller (ProBook 455 G1 Notebook) pci:v00001022d0000780Bsv0000103Csd00001985* ID_MODEL_FROM_DATABASE=FCH SMBus Controller (Pavilion 17-e163sg Notebook PC) pci:v00001022d0000780C* ID_MODEL_FROM_DATABASE=FCH IDE Controller pci:v00001022d0000780D* ID_MODEL_FROM_DATABASE=FCH Azalia Controller pci:v00001022d0000780Dsv0000103Csd0000194E* ID_MODEL_FROM_DATABASE=FCH Azalia Controller (ProBook 455 G1 Notebook) pci:v00001022d0000780Dsv0000103Csd00001985* ID_MODEL_FROM_DATABASE=FCH Azalia Controller (Pavilion 17-e163sg Notebook PC) pci:v00001022d0000780Dsv00001043sd00008444* ID_MODEL_FROM_DATABASE=FCH Azalia Controller (F2A85-M Series) pci:v00001022d0000780E* ID_MODEL_FROM_DATABASE=FCH LPC Bridge pci:v00001022d0000780Esv0000103Csd0000194E* ID_MODEL_FROM_DATABASE=FCH LPC Bridge (ProBook 455 G1 Notebook) pci:v00001022d0000780Esv0000103Csd00001985* ID_MODEL_FROM_DATABASE=FCH LPC Bridge (Pavilion 17-e163sg Notebook PC) pci:v00001022d0000780F* ID_MODEL_FROM_DATABASE=FCH PCI Bridge pci:v00001022d00007812* ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller pci:v00001022d00007813* ID_MODEL_FROM_DATABASE=FCH SD Flash Controller pci:v00001022d00007814* ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller pci:v00001022d00007814sv0000103Csd0000194E* ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller (ProBook 455 G1 Notebook) pci:v00001022d00007814sv0000103Csd00001985* ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller (Pavilion 17-e163sg Notebook PC) pci:v00001022d00007900* ID_MODEL_FROM_DATABASE=FCH SATA Controller [IDE mode] pci:v00001022d00007901* ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] pci:v00001022d00007902* ID_MODEL_FROM_DATABASE=FCH SATA Controller [RAID mode] pci:v00001022d00007903* ID_MODEL_FROM_DATABASE=FCH SATA Controller [RAID mode] pci:v00001022d00007904* ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] pci:v00001022d00007906* ID_MODEL_FROM_DATABASE=FCH SD Flash Controller pci:v00001022d00007908* ID_MODEL_FROM_DATABASE=FCH USB EHCI Controller pci:v00001022d0000790B* ID_MODEL_FROM_DATABASE=FCH SMBus Controller pci:v00001022d0000790E* ID_MODEL_FROM_DATABASE=FCH LPC Bridge pci:v00001022d0000790F* ID_MODEL_FROM_DATABASE=FCH PCI Bridge pci:v00001022d00007914* ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller pci:v00001022d00009600* ID_MODEL_FROM_DATABASE=RS780 Host Bridge pci:v00001022d00009600sv00001043sd000082EE* ID_MODEL_FROM_DATABASE=RS780 Host Bridge (M378A-CM Motherboard) pci:v00001022d00009600sv00001043sd000082F1* ID_MODEL_FROM_DATABASE=RS780 Host Bridge (M3A78-EH Motherboard) pci:v00001022d00009601* ID_MODEL_FROM_DATABASE=RS880 Host Bridge pci:v00001022d00009601sv00001019sd00002120* ID_MODEL_FROM_DATABASE=RS880 Host Bridge (A785GM-M) pci:v00001022d00009601sv00001043sd0000843E* ID_MODEL_FROM_DATABASE=RS880 Host Bridge (M5A88-V EVO) pci:v00001022d00009602* ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (int gfx) pci:v00001022d00009603* ID_MODEL_FROM_DATABASE=RS780 PCI to PCI bridge (ext gfx port 0) pci:v00001022d00009604* ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (PCIE port 0) pci:v00001022d00009605* ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (PCIE port 1) pci:v00001022d00009606* ID_MODEL_FROM_DATABASE=RS780 PCI to PCI bridge (PCIE port 2) pci:v00001022d00009607* ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (PCIE port 3) pci:v00001022d00009608* ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (PCIE port 4) pci:v00001022d00009609* ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (PCIE port 5) pci:v00001022d0000960A* ID_MODEL_FROM_DATABASE=RS780 PCI to PCI bridge (NB-SB link) pci:v00001022d0000960B* ID_MODEL_FROM_DATABASE=RS780 PCI to PCI bridge (ext gfx port 1) pci:v00001023* ID_VENDOR_FROM_DATABASE=Trident Microsystems pci:v00001023d00000194* ID_MODEL_FROM_DATABASE=82C194 pci:v00001023d00002000* ID_MODEL_FROM_DATABASE=4DWave DX pci:v00001023d00002001* ID_MODEL_FROM_DATABASE=4DWave NX pci:v00001023d00002001sv0000122Dsd00001400* ID_MODEL_FROM_DATABASE=4DWave NX (Trident PCI288-Q3DII (NX)) pci:v00001023d00002100* ID_MODEL_FROM_DATABASE=CyberBlade XP4m32 pci:v00001023d00002200* ID_MODEL_FROM_DATABASE=XGI Volari XP5 pci:v00001023d00008400* ID_MODEL_FROM_DATABASE=CyberBlade/i7 pci:v00001023d00008400sv00001023sd00008400* ID_MODEL_FROM_DATABASE=CyberBlade/i7 (CyberBlade i7 AGP) pci:v00001023d00008420* ID_MODEL_FROM_DATABASE=CyberBlade/i7d pci:v00001023d00008420sv00000E11sd0000B15A* ID_MODEL_FROM_DATABASE=CyberBlade/i7d (CyberBlade i7 AGP) pci:v00001023d00008500* ID_MODEL_FROM_DATABASE=CyberBlade/i1 pci:v00001023d00008520* ID_MODEL_FROM_DATABASE=CyberBlade i1 pci:v00001023d00008520sv00000E11sd0000B16E* ID_MODEL_FROM_DATABASE=CyberBlade i1 (AGP) pci:v00001023d00008520sv00001023sd00008520* ID_MODEL_FROM_DATABASE=CyberBlade i1 (AGP) pci:v00001023d00008620* ID_MODEL_FROM_DATABASE=CyberBlade/i1 pci:v00001023d00008620sv00001014sd00000502* ID_MODEL_FROM_DATABASE=CyberBlade/i1 (ThinkPad R30/T30) pci:v00001023d00008620sv00001014sd00001025* ID_MODEL_FROM_DATABASE=CyberBlade/i1 (Travelmate 352TE) pci:v00001023d00008820* ID_MODEL_FROM_DATABASE=CyberBlade XPAi1 pci:v00001023d00009320* ID_MODEL_FROM_DATABASE=TGUI 9320 pci:v00001023d00009350* ID_MODEL_FROM_DATABASE=GUI Accelerator pci:v00001023d00009360* ID_MODEL_FROM_DATABASE=Flat panel GUI Accelerator pci:v00001023d00009382* ID_MODEL_FROM_DATABASE=Cyber 9382 [Reference design] pci:v00001023d00009383* ID_MODEL_FROM_DATABASE=Cyber 9383 [Reference design] pci:v00001023d00009385* ID_MODEL_FROM_DATABASE=Cyber 9385 [Reference design] pci:v00001023d00009386* ID_MODEL_FROM_DATABASE=Cyber 9386 pci:v00001023d00009388* ID_MODEL_FROM_DATABASE=Cyber 9388 pci:v00001023d00009397* ID_MODEL_FROM_DATABASE=Cyber 9397 pci:v00001023d0000939A* ID_MODEL_FROM_DATABASE=Cyber 9397DVD pci:v00001023d00009420* ID_MODEL_FROM_DATABASE=TGUI 9420 pci:v00001023d00009430* ID_MODEL_FROM_DATABASE=TGUI 9430 pci:v00001023d00009440* ID_MODEL_FROM_DATABASE=TGUI 9440 pci:v00001023d00009460* ID_MODEL_FROM_DATABASE=TGUI 9460 pci:v00001023d00009470* ID_MODEL_FROM_DATABASE=TGUI 9470 pci:v00001023d00009520* ID_MODEL_FROM_DATABASE=Cyber 9520 pci:v00001023d00009525* ID_MODEL_FROM_DATABASE=Cyber 9525 pci:v00001023d00009540* ID_MODEL_FROM_DATABASE=Cyber 9540 pci:v00001023d00009660* ID_MODEL_FROM_DATABASE=TGUI 9660/938x/968x pci:v00001023d00009680* ID_MODEL_FROM_DATABASE=TGUI 9680 pci:v00001023d00009682* ID_MODEL_FROM_DATABASE=TGUI 9682 pci:v00001023d00009683* ID_MODEL_FROM_DATABASE=TGUI 9683 pci:v00001023d00009685* ID_MODEL_FROM_DATABASE=ProVIDIA 9685 pci:v00001023d00009750* ID_MODEL_FROM_DATABASE=3DImage 9750 pci:v00001023d00009750sv00001014sd00009750* ID_MODEL_FROM_DATABASE=3DImage 9750 pci:v00001023d00009750sv00001023sd00009750* ID_MODEL_FROM_DATABASE=3DImage 9750 pci:v00001023d00009753* ID_MODEL_FROM_DATABASE=TGUI 9753 pci:v00001023d00009754* ID_MODEL_FROM_DATABASE=TGUI 9754 pci:v00001023d00009759* ID_MODEL_FROM_DATABASE=TGUI 975 pci:v00001023d00009783* ID_MODEL_FROM_DATABASE=TGUI 9783 pci:v00001023d00009785* ID_MODEL_FROM_DATABASE=TGUI 9785 pci:v00001023d00009850* ID_MODEL_FROM_DATABASE=3DImage 9850 pci:v00001023d00009880* ID_MODEL_FROM_DATABASE=Blade 3D PCI/AGP pci:v00001023d00009880sv00001023sd00009880* ID_MODEL_FROM_DATABASE=Blade 3D PCI/AGP (Blade 3D) pci:v00001023d00009910* ID_MODEL_FROM_DATABASE=CyberBlade/XP pci:v00001023d00009930* ID_MODEL_FROM_DATABASE=CyberBlade/XPm pci:v00001023d00009960* ID_MODEL_FROM_DATABASE=CyberBlade XP2 pci:v00001024* ID_VENDOR_FROM_DATABASE=Zenith Data Systems pci:v00001025* ID_VENDOR_FROM_DATABASE=Acer Incorporated [ALI] pci:v00001025d00001435* ID_MODEL_FROM_DATABASE=M1435 pci:v00001025d00001445* ID_MODEL_FROM_DATABASE=M1445 pci:v00001025d00001449* ID_MODEL_FROM_DATABASE=M1449 pci:v00001025d00001451* ID_MODEL_FROM_DATABASE=M1451 pci:v00001025d00001461* ID_MODEL_FROM_DATABASE=M1461 pci:v00001025d00001489* ID_MODEL_FROM_DATABASE=M1489 pci:v00001025d00001511* ID_MODEL_FROM_DATABASE=M1511 pci:v00001025d00001512* ID_MODEL_FROM_DATABASE=ALI M1512 Aladdin pci:v00001025d00001513* ID_MODEL_FROM_DATABASE=M1513 pci:v00001025d00001521* ID_MODEL_FROM_DATABASE=ALI M1521 Aladdin III CPU Bridge pci:v00001025d00001521sv000010B9sd00001521* ID_MODEL_FROM_DATABASE=ALI M1521 Aladdin III CPU Bridge pci:v00001025d00001523* ID_MODEL_FROM_DATABASE=ALI M1523 ISA Bridge pci:v00001025d00001523sv000010B9sd00001523* ID_MODEL_FROM_DATABASE=ALI M1523 ISA Bridge pci:v00001025d00001531* ID_MODEL_FROM_DATABASE=M1531 Northbridge [Aladdin IV/IV+] pci:v00001025d00001533* ID_MODEL_FROM_DATABASE=M1533 PCI-to-ISA Bridge pci:v00001025d00001533sv000010B9sd00001533* ID_MODEL_FROM_DATABASE=M1533 PCI-to-ISA Bridge (ALI M1533 Aladdin IV/V ISA South Bridge) pci:v00001025d00001535* ID_MODEL_FROM_DATABASE=M1535 PCI Bridge + Super I/O + FIR pci:v00001025d00001541* ID_MODEL_FROM_DATABASE=M1541 Northbridge [Aladdin V] pci:v00001025d00001541sv000010B9sd00001541* ID_MODEL_FROM_DATABASE=M1541 Northbridge [Aladdin V] (ALI M1541 Aladdin V/V+ AGP+PCI North Bridge) pci:v00001025d00001542* ID_MODEL_FROM_DATABASE=M1542 Northbridge [Aladdin V] pci:v00001025d00001543* ID_MODEL_FROM_DATABASE=M1543 PCI-to-ISA Bridge + Super I/O + FIR pci:v00001025d00001561* ID_MODEL_FROM_DATABASE=M1561 Northbridge [Aladdin 7] pci:v00001025d00001621* ID_MODEL_FROM_DATABASE=M1621 Northbridge [Aladdin-Pro II] pci:v00001025d00001631* ID_MODEL_FROM_DATABASE=M1631 Northbridge+3D Graphics [Aladdin TNT2] pci:v00001025d00001641* ID_MODEL_FROM_DATABASE=M1641 Northbridge [Aladdin-Pro IV] pci:v00001025d00001647* ID_MODEL_FROM_DATABASE=M1647 [MaGiK1] PCI North Bridge pci:v00001025d00001671* ID_MODEL_FROM_DATABASE=M1671 Northbridge [ALADDiN-P4] pci:v00001025d00001672* ID_MODEL_FROM_DATABASE=Northbridge [CyberALADDiN-P4] pci:v00001025d00003141* ID_MODEL_FROM_DATABASE=M3141 pci:v00001025d00003143* ID_MODEL_FROM_DATABASE=M3143 pci:v00001025d00003145* ID_MODEL_FROM_DATABASE=M3145 pci:v00001025d00003147* ID_MODEL_FROM_DATABASE=M3147 pci:v00001025d00003149* ID_MODEL_FROM_DATABASE=M3149 pci:v00001025d00003151* ID_MODEL_FROM_DATABASE=M3151 pci:v00001025d00003307* ID_MODEL_FROM_DATABASE=M3307 MPEG-I Video Controller pci:v00001025d00003309* ID_MODEL_FROM_DATABASE=M3309 MPEG-II Video w/ Software Audio Decoder pci:v00001025d00003321* ID_MODEL_FROM_DATABASE=M3321 MPEG-II Audio/Video Decoder pci:v00001025d00005212* ID_MODEL_FROM_DATABASE=M4803 pci:v00001025d00005215* ID_MODEL_FROM_DATABASE=ALI PCI EIDE Controller pci:v00001025d00005217* ID_MODEL_FROM_DATABASE=M5217H pci:v00001025d00005219* ID_MODEL_FROM_DATABASE=M5219 pci:v00001025d00005225* ID_MODEL_FROM_DATABASE=M5225 pci:v00001025d00005229* ID_MODEL_FROM_DATABASE=M5229 pci:v00001025d00005235* ID_MODEL_FROM_DATABASE=M5235 pci:v00001025d00005237* ID_MODEL_FROM_DATABASE=M5237 PCI USB Host Controller pci:v00001025d00005240* ID_MODEL_FROM_DATABASE=EIDE Controller pci:v00001025d00005241* ID_MODEL_FROM_DATABASE=PCMCIA Bridge pci:v00001025d00005242* ID_MODEL_FROM_DATABASE=General Purpose Controller pci:v00001025d00005243* ID_MODEL_FROM_DATABASE=PCI to PCI Bridge Controller pci:v00001025d00005244* ID_MODEL_FROM_DATABASE=Floppy Disk Controller pci:v00001025d00005247* ID_MODEL_FROM_DATABASE=M1541 PCI to PCI Bridge pci:v00001025d00005251* ID_MODEL_FROM_DATABASE=M5251 P1394 Controller pci:v00001025d00005427* ID_MODEL_FROM_DATABASE=PCI to AGP Bridge pci:v00001025d00005451* ID_MODEL_FROM_DATABASE=M5451 PCI AC-Link Controller Audio Device pci:v00001025d00005453* ID_MODEL_FROM_DATABASE=M5453 PCI AC-Link Controller Modem Device pci:v00001025d00007101* ID_MODEL_FROM_DATABASE=M7101 PCI PMU Power Management Controller pci:v00001025d00007101sv000010B9sd00007101* ID_MODEL_FROM_DATABASE=M7101 PCI PMU Power Management Controller pci:v00001025d00009602* ID_MODEL_FROM_DATABASE=AMD RS780/RS880 PCI to PCI bridge (int gfx) pci:v00001028* ID_VENDOR_FROM_DATABASE=Dell pci:v00001028d00000001* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 2/Si pci:v00001028d00000001sv00001028sd00000001* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 2/Si (PowerEdge 2400) pci:v00001028d00000002* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di pci:v00001028d00000002sv00001028sd00000002* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di (PowerEdge 4400) pci:v00001028d00000002sv00001028sd000000D1* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di (PERC 3/DiV [Viper]) pci:v00001028d00000002sv00001028sd000000D9* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di (PERC 3/DiL [Lexus]) pci:v00001028d00000003* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Si pci:v00001028d00000003sv00001028sd00000003* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Si (PowerEdge 2450) pci:v00001028d00000004* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di [Iguana] pci:v00001028d00000004sv00001028sd00000004* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di [Iguana] (PERC 3/DiF [Iguana]) pci:v00001028d00000006* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di pci:v00001028d00000007* ID_MODEL_FROM_DATABASE=Remote Access Card III pci:v00001028d00000008* ID_MODEL_FROM_DATABASE=Remote Access Card III pci:v00001028d00000009* ID_MODEL_FROM_DATABASE=Remote Access Card III: BMC/SMIC device not present pci:v00001028d0000000A* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di pci:v00001028d0000000Asv00001028sd00000106* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di (PERC 3/DiJ [Jaguar]) pci:v00001028d0000000Asv00001028sd0000011B* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di (PERC 3/DiD [Dagger]) pci:v00001028d0000000Asv00001028sd00000121* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di (PERC 3/DiB [Boxster]) pci:v00001028d0000000C* ID_MODEL_FROM_DATABASE=Embedded Remote Access or ERA/O pci:v00001028d0000000D* ID_MODEL_FROM_DATABASE=Embedded Remote Access: BMC/SMIC device pci:v00001028d0000000E* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4/Di pci:v00001028d0000000F* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4/Di pci:v00001028d0000000Fsv00001028sd0000014A* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4/Di (PowerEdge 1750) pci:v00001028d00000010* ID_MODEL_FROM_DATABASE=Remote Access Card 4 pci:v00001028d00000011* ID_MODEL_FROM_DATABASE=Remote Access Card 4 Daughter Card pci:v00001028d00000012* ID_MODEL_FROM_DATABASE=Remote Access Card 4 Daughter Card Virtual UART pci:v00001028d00000013* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4 pci:v00001028d00000013sv00001028sd0000016C* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4 (PowerEdge Expandable RAID Controller 4e/Si) pci:v00001028d00000013sv00001028sd0000016D* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4 (PowerEdge Expandable RAID Controller 4e/Di) pci:v00001028d00000013sv00001028sd0000016E* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4 (PowerEdge Expandable RAID Controller 4e/Di) pci:v00001028d00000013sv00001028sd0000016F* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4 (PowerEdge Expandable RAID Controller 4e/Di) pci:v00001028d00000013sv00001028sd00000170* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4 (PowerEdge Expandable RAID Controller 4e/Di) pci:v00001028d00000014* ID_MODEL_FROM_DATABASE=Remote Access Card 4 Daughter Card SMIC interface pci:v00001028d00000015* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 5 pci:v00001028d00000015sv00001028sd00001F01* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 5 (PERC 5/E Adapter RAID Controller) pci:v00001028d00000015sv00001028sd00001F02* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 5 (PERC 5/i Adapter RAID Controller) pci:v00001028d00000015sv00001028sd00001F03* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 5 (PERC 5/i Integrated RAID Controller) pci:v00001028d00000016* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller S300 pci:v00001028d00000016sv00001028sd00001F24* ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller S300 (PERC S300 Controller) pci:v00001028d00000073* ID_MODEL_FROM_DATABASE=NV-RAM Adapter pci:v00001029* ID_VENDOR_FROM_DATABASE=Siemens Nixdorf IS pci:v0000102A* ID_VENDOR_FROM_DATABASE=LSI Logic pci:v0000102Ad00000000* ID_MODEL_FROM_DATABASE=HYDRA pci:v0000102Ad00000010* ID_MODEL_FROM_DATABASE=ASPEN pci:v0000102Ad0000001F* ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W /7890/7891 SCSI Controllers pci:v0000102Ad0000001Fsv00009005sd0000000F* ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W /7890/7891 SCSI Controllers (2940U2W SCSI Controller) pci:v0000102Ad0000001Fsv00009005sd00000106* ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W /7890/7891 SCSI Controllers (2940U2W SCSI Controller) pci:v0000102Ad0000001Fsv00009005sd0000A180* ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W /7890/7891 SCSI Controllers (2940U2W SCSI Controller) pci:v0000102Ad000000C5* ID_MODEL_FROM_DATABASE=AIC-7899 U160/m SCSI Controller pci:v0000102Ad000000C5sv00001028sd000000C5* ID_MODEL_FROM_DATABASE=AIC-7899 U160/m SCSI Controller (PowerEdge 2550/2650/4600) pci:v0000102Ad000000CF* ID_MODEL_FROM_DATABASE=AIC-7899P U160/m pci:v0000102Ad000000CFsv00001028sd00000106* ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (PowerEdge 4600) pci:v0000102Ad000000CFsv00001028sd00000121* ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (PowerEdge 2650) pci:v0000102B* ID_VENDOR_FROM_DATABASE=Matrox Electronics Systems Ltd. pci:v0000102Bd00000010* ID_MODEL_FROM_DATABASE=MGA-I [Impression?] pci:v0000102Bd00000100* ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] pci:v0000102Bd00000518* ID_MODEL_FROM_DATABASE=MGA-II [Athena] pci:v0000102Bd00000519* ID_MODEL_FROM_DATABASE=MGA 2064W [Millennium] pci:v0000102Bd0000051A* ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] pci:v0000102Bd0000051Asv0000102Bsd00000100* ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] (MGA-1064SG Mystique) pci:v0000102Bd0000051Asv0000102Bsd00001100* ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] (MGA-1084SG Mystique) pci:v0000102Bd0000051Asv0000102Bsd00001200* ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] (MGA-1084SG Mystique) pci:v0000102Bd0000051Asv00001100sd0000102B* ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] (MGA-1084SG Mystique) pci:v0000102Bd0000051Asv0000110Asd00000018* ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] (Scenic Pro C5 (D1025)) pci:v0000102Bd0000051B* ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] pci:v0000102Bd0000051Bsv0000102Bsd0000051B* ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] (MGA-2164W Millennium II) pci:v0000102Bd0000051Bsv0000102Bsd00001100* ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] (MGA-2164W Millennium II) pci:v0000102Bd0000051Bsv0000102Bsd00001200* ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] (MGA-2164W Millennium II) pci:v0000102Bd0000051Bsv0000102Bsd00002100* ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] (MGA-2164W Millennium II) pci:v0000102Bd0000051E* ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] AGP pci:v0000102Bd0000051F* ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] AGP pci:v0000102Bd0000051Fsv0000102Bsd00002100* ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] AGP (MGA-2164WA [Millennium II A]) pci:v0000102Bd00000520* ID_MODEL_FROM_DATABASE=MGA G200 pci:v0000102Bd00000520sv0000102Bsd0000DBC2* ID_MODEL_FROM_DATABASE=MGA G200 (G200 Multi-Monitor) pci:v0000102Bd00000520sv0000102Bsd0000DBC8* ID_MODEL_FROM_DATABASE=MGA G200 (G200 Multi-Monitor) pci:v0000102Bd00000520sv0000102Bsd0000DBE2* ID_MODEL_FROM_DATABASE=MGA G200 (G200 Multi-Monitor) pci:v0000102Bd00000520sv0000102Bsd0000DBE8* ID_MODEL_FROM_DATABASE=MGA G200 (G200 Multi-Monitor) pci:v0000102Bd00000520sv0000102Bsd0000FF03* ID_MODEL_FROM_DATABASE=MGA G200 (Millennium G200 SD) pci:v0000102Bd00000520sv0000102Bsd0000FF04* ID_MODEL_FROM_DATABASE=MGA G200 (Marvel G200) pci:v0000102Bd00000521* ID_MODEL_FROM_DATABASE=MGA G200 AGP pci:v0000102Bd00000521sv00001014sd0000FF03* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 AGP) pci:v0000102Bd00000521sv0000102Bsd000048E9* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Mystique G200 AGP) pci:v0000102Bd00000521sv0000102Bsd000048F8* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 SD AGP) pci:v0000102Bd00000521sv0000102Bsd00004A60* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 LE AGP) pci:v0000102Bd00000521sv0000102Bsd00004A64* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 AGP) pci:v0000102Bd00000521sv0000102Bsd0000C93C* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 AGP) pci:v0000102Bd00000521sv0000102Bsd0000C9B0* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 AGP) pci:v0000102Bd00000521sv0000102Bsd0000C9BC* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 AGP) pci:v0000102Bd00000521sv0000102Bsd0000CA60* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G250 LE AGP) pci:v0000102Bd00000521sv0000102Bsd0000CA6C* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G250 AGP) pci:v0000102Bd00000521sv0000102Bsd0000DBBC* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 AGP) pci:v0000102Bd00000521sv0000102Bsd0000DBC2* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 MMS (Dual G200)) pci:v0000102Bd00000521sv0000102Bsd0000DBC3* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000DBC8* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 MMS (Dual G200)) pci:v0000102Bd00000521sv0000102Bsd0000DBD2* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000DBD3* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000DBD4* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000DBD5* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000DBD8* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000DBD9* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000DBE2* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 MMS (Quad G200)) pci:v0000102Bd00000521sv0000102Bsd0000DBE3* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000DBE8* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 MMS (Quad G200)) pci:v0000102Bd00000521sv0000102Bsd0000DBF2* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000DBF3* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000DBF4* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000DBF5* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000DBF8* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000DBF9* ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) pci:v0000102Bd00000521sv0000102Bsd0000F806* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Mystique G200 Video AGP) pci:v0000102Bd00000521sv0000102Bsd0000FF00* ID_MODEL_FROM_DATABASE=MGA G200 AGP (MGA-G200 AGP) pci:v0000102Bd00000521sv0000102Bsd0000FF02* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Mystique G200 AGP) pci:v0000102Bd00000521sv0000102Bsd0000FF03* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200A AGP) pci:v0000102Bd00000521sv0000102Bsd0000FF04* ID_MODEL_FROM_DATABASE=MGA G200 AGP (Marvel G200 AGP) pci:v0000102Bd00000521sv0000110Asd00000032* ID_MODEL_FROM_DATABASE=MGA G200 AGP (MGA-G200 AGP) pci:v0000102Bd00000522* ID_MODEL_FROM_DATABASE=MGA G200e [Pilot] ServerEngines (SEP1) pci:v0000102Bd00000522sv0000103Csd000031FA* ID_MODEL_FROM_DATABASE=MGA G200e [Pilot] ServerEngines (SEP1) (ProLiant DL140 G3) pci:v0000102Bd00000525* ID_MODEL_FROM_DATABASE=MGA G400/G450 pci:v0000102Bd00000525sv00000E11sd0000B16F* ID_MODEL_FROM_DATABASE=MGA G400/G450 (MGA-G400 AGP) pci:v0000102Bd00000525sv0000102Bsd00000328* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 16Mb SDRAM) pci:v0000102Bd00000525sv0000102Bsd00000338* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 16Mb SDRAM) pci:v0000102Bd00000525sv0000102Bsd00000378* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 32Mb SDRAM) pci:v0000102Bd00000525sv0000102Bsd00000541* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Dual Head) pci:v0000102Bd00000525sv0000102Bsd00000542* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Dual Head LX) pci:v0000102Bd00000525sv0000102Bsd00000543* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Single Head LX) pci:v0000102Bd00000525sv0000102Bsd00000641* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 32Mb SDRAM Dual Head) pci:v0000102Bd00000525sv0000102Bsd00000642* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 32Mb SDRAM Dual Head LX) pci:v0000102Bd00000525sv0000102Bsd00000643* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 32Mb SDRAM Single Head LX) pci:v0000102Bd00000525sv0000102Bsd000007C0* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Dual Head LE) pci:v0000102Bd00000525sv0000102Bsd000007C1* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 SDR Dual Head LE) pci:v0000102Bd00000525sv0000102Bsd00000D41* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Dual Head PCI) pci:v0000102Bd00000525sv0000102Bsd00000D42* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Dual Head LX PCI) pci:v0000102Bd00000525sv0000102Bsd00000D43* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 32Mb Dual Head PCI) pci:v0000102Bd00000525sv0000102Bsd00000E00* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Marvel G450 eTV) pci:v0000102Bd00000525sv0000102Bsd00000E01* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Marvel G450 eTV) pci:v0000102Bd00000525sv0000102Bsd00000E02* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Marvel G450 eTV) pci:v0000102Bd00000525sv0000102Bsd00000E03* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Marvel G450 eTV) pci:v0000102Bd00000525sv0000102Bsd00000F80* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Low Profile) pci:v0000102Bd00000525sv0000102Bsd00000F81* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Low Profile) pci:v0000102Bd00000525sv0000102Bsd00000F82* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Low Profile DVI) pci:v0000102Bd00000525sv0000102Bsd00000F83* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Low Profile DVI) pci:v0000102Bd00000525sv0000102Bsd000019D8* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 16Mb SGRAM) pci:v0000102Bd00000525sv0000102Bsd000019F8* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 32Mb SGRAM) pci:v0000102Bd00000525sv0000102Bsd00002159* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 Dual Head 16Mb) pci:v0000102Bd00000525sv0000102Bsd00002179* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 MAX/Dual Head 32Mb) pci:v0000102Bd00000525sv0000102Bsd0000217D* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 Dual Head Max) pci:v0000102Bd00000525sv0000102Bsd000023C0* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450) pci:v0000102Bd00000525sv0000102Bsd000023C1* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450) pci:v0000102Bd00000525sv0000102Bsd000023C2* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 DVI) pci:v0000102Bd00000525sv0000102Bsd000023C3* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 DVI) pci:v0000102Bd00000525sv0000102Bsd00002F58* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400) pci:v0000102Bd00000525sv0000102Bsd00002F78* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400) pci:v0000102Bd00000525sv0000102Bsd00003693* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Marvel G400 AGP) pci:v0000102Bd00000525sv0000102Bsd00005DD0* ID_MODEL_FROM_DATABASE=MGA G400/G450 (4Sight II) pci:v0000102Bd00000525sv0000102Bsd00005F50* ID_MODEL_FROM_DATABASE=MGA G400/G450 (4Sight II) pci:v0000102Bd00000525sv0000102Bsd00005F51* ID_MODEL_FROM_DATABASE=MGA G400/G450 (4Sight II) pci:v0000102Bd00000525sv0000102Bsd00005F52* ID_MODEL_FROM_DATABASE=MGA G400/G450 (4Sight II) pci:v0000102Bd00000525sv0000102Bsd00009010* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 Dual Head) pci:v0000102Bd00000525sv00001458sd00000400* ID_MODEL_FROM_DATABASE=MGA G400/G450 (GA-G400) pci:v0000102Bd00000525sv00001705sd00000001* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 32MB SGRAM) pci:v0000102Bd00000525sv00001705sd00000002* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 16MB SGRAM) pci:v0000102Bd00000525sv00001705sd00000003* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 32MB) pci:v0000102Bd00000525sv00001705sd00000004* ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 16MB) pci:v0000102Bd00000527* ID_MODEL_FROM_DATABASE=Parhelia pci:v0000102Bd00000527sv0000102Bsd00000840* ID_MODEL_FROM_DATABASE=Parhelia (128Mb) pci:v0000102Bd00000527sv0000102Bsd00000850* ID_MODEL_FROM_DATABASE=Parhelia (256MB) pci:v0000102Bd00000527sv0000102Bsd00000870* ID_MODEL_FROM_DATABASE=Parhelia (MED2mp-DVI) pci:v0000102Bd00000527sv0000102Bsd00000880* ID_MODEL_FROM_DATABASE=Parhelia (P-256 Edge Overlap Controller) pci:v0000102Bd00000528* ID_MODEL_FROM_DATABASE=Parhelia pci:v0000102Bd00000528sv0000102Bsd00001020* ID_MODEL_FROM_DATABASE=Parhelia (128MB) pci:v0000102Bd00000528sv0000102Bsd00001030* ID_MODEL_FROM_DATABASE=Parhelia (256 MB Dual DVI) pci:v0000102Bd00000528sv0000102Bsd00001040* ID_MODEL_FROM_DATABASE=Parhelia (MED2mp-DVI) pci:v0000102Bd00000528sv0000102Bsd00001050* ID_MODEL_FROM_DATABASE=Parhelia (Sono S20) pci:v0000102Bd00000528sv0000102Bsd00001060* ID_MODEL_FROM_DATABASE=Parhelia (PJ-30L) pci:v0000102Bd00000528sv0000102Bsd00001070* ID_MODEL_FROM_DATABASE=Parhelia (PJ-40L) pci:v0000102Bd00000528sv0000102Bsd00001421* ID_MODEL_FROM_DATABASE=Parhelia (MED5mp) pci:v0000102Bd00000528sv0000102Bsd00001431* ID_MODEL_FROM_DATABASE=Parhelia (MED3mp-DVI) pci:v0000102Bd00000528sv0000102Bsd00001451* ID_MODEL_FROM_DATABASE=Parhelia (MED5mp-DVI) pci:v0000102Bd00000528sv0000102Bsd00001491* ID_MODEL_FROM_DATABASE=Parhelia (MED2mp-DVI) pci:v0000102Bd00000528sv0000102Bsd000014B1* ID_MODEL_FROM_DATABASE=Parhelia (MED3mp-DVI) pci:v0000102Bd00000528sv0000102Bsd000014C1* ID_MODEL_FROM_DATABASE=Parhelia (MED5mp-DVI) pci:v0000102Bd00000528sv0000102Bsd000014E1* ID_MODEL_FROM_DATABASE=Parhelia (PCI 256MB) pci:v0000102Bd00000528sv0000102Bsd000014F1* ID_MODEL_FROM_DATABASE=Parhelia (Precision SGT) pci:v0000102Bd00000528sv0000102Bsd00001501* ID_MODEL_FROM_DATABASE=Parhelia (ATC-4MP) pci:v0000102Bd00000528sv0000102Bsd00001511* ID_MODEL_FROM_DATABASE=Parhelia (ATC-4MP) pci:v0000102Bd00000528sv0000102Bsd00001521* ID_MODEL_FROM_DATABASE=Parhelia (TheatreVUE T30) pci:v0000102Bd00000528sv0000102Bsd00001531* ID_MODEL_FROM_DATABASE=Parhelia (TheatreVUE T20) pci:v0000102Bd00000528sv0000102Bsd00001541* ID_MODEL_FROM_DATABASE=Parhelia (MED2mp-DVI) pci:v0000102Bd00000528sv0000102Bsd00001551* ID_MODEL_FROM_DATABASE=Parhelia (MED3mp-DVI) pci:v0000102Bd00000528sv0000102Bsd00001561* ID_MODEL_FROM_DATABASE=Parhelia (MED5mp-DVI) pci:v0000102Bd00000528sv0000102Bsd00001571* ID_MODEL_FROM_DATABASE=Parhelia (DL256 PCI) pci:v0000102Bd00000528sv0000102Bsd00001591* ID_MODEL_FROM_DATABASE=Parhelia (Precision SDT) pci:v0000102Bd00000528sv0000102Bsd000015A1* ID_MODEL_FROM_DATABASE=Parhelia (MED4mp-DVI) pci:v0000102Bd00000528sv0000102Bsd00002011* ID_MODEL_FROM_DATABASE=Parhelia (HR256) pci:v0000102Bd00000528sv0000102Bsd00002021* ID_MODEL_FROM_DATABASE=Parhelia (QID Pro) pci:v0000102Bd00000528sv0000102Bsd00002061* ID_MODEL_FROM_DATABASE=Parhelia (PJ-40LP) pci:v0000102Bd00000528sv0000102Bsd00002081* ID_MODEL_FROM_DATABASE=Parhelia (EWS Quad) pci:v0000102Bd00000528sv0000102Bsd00002411* ID_MODEL_FROM_DATABASE=Parhelia (PPX-OUT8) pci:v0000102Bd00000528sv0000102Bsd00002421* ID_MODEL_FROM_DATABASE=Parhelia (VPX-OUT8) pci:v0000102Bd00000528sv0000102Bsd00002441* ID_MODEL_FROM_DATABASE=Parhelia (PPX-OUT4) pci:v0000102Bd00000528sv0000102Bsd00002451* ID_MODEL_FROM_DATABASE=Parhelia (VPX-OUT4) pci:v0000102Bd00000528sv0000102Bsd00002491* ID_MODEL_FROM_DATABASE=Parhelia (LPX-OUT4) pci:v0000102Bd00000530* ID_MODEL_FROM_DATABASE=MGA G200EV pci:v0000102Bd00000532* ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 pci:v0000102Bd00000532sv00001028sd00000235* ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge R710 MGA G200eW WPCM450) pci:v0000102Bd00000532sv00001028sd00000236* ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge R610 MGA G200eW WPCM450) pci:v0000102Bd00000532sv00001028sd00000237* ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge T610 MGA G200eW WPCM450) pci:v0000102Bd00000532sv00001028sd00000287* ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge M610 MGA G200eW WPCM450) pci:v0000102Bd00000532sv00001028sd0000028C* ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge R410 MGA G200eW WPCM450) pci:v0000102Bd00000532sv00001028sd0000028D* ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge T410 MGA G200eW WPCM450) pci:v0000102Bd00000532sv00001028sd0000029C* ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge M710 MGA G200eW WPCM450) pci:v0000102Bd00000532sv00001028sd000002A4* ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge T310 MGA G200eW WPCM450) pci:v0000102Bd00000532sv000015D9sd00000624* ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (X9SCM-F Motherboard) pci:v0000102Bd00000532sv000015D9sd0000A811* ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (H8DGU) pci:v0000102Bd00000533* ID_MODEL_FROM_DATABASE=MGA G200EH pci:v0000102Bd00000533sv0000103Csd00003381* ID_MODEL_FROM_DATABASE=MGA G200EH (iLO4) pci:v0000102Bd00000534* ID_MODEL_FROM_DATABASE=G200eR2 pci:v0000102Bd00000540* ID_MODEL_FROM_DATABASE=M91XX pci:v0000102Bd00000540sv0000102Bsd00002080* ID_MODEL_FROM_DATABASE=M91XX (M9140 LP PCIe x16) pci:v0000102Bd00000540sv0000102Bsd000020C0* ID_MODEL_FROM_DATABASE=M91XX (Xenia) pci:v0000102Bd00000540sv0000102Bsd000020C1* ID_MODEL_FROM_DATABASE=M91XX (Xenia Pro) pci:v0000102Bd00000540sv0000102Bsd00002100* ID_MODEL_FROM_DATABASE=M91XX (M9120 PCIe x16) pci:v0000102Bd00000540sv0000102Bsd00002140* ID_MODEL_FROM_DATABASE=M91XX (M9125 PCIe x16) pci:v0000102Bd00000540sv0000102Bsd00002180* ID_MODEL_FROM_DATABASE=M91XX (M9120 Plus LP PCIe x16) pci:v0000102Bd00000540sv0000102Bsd000021C0* ID_MODEL_FROM_DATABASE=M91XX (M9120 Plus LP PCIe x1) pci:v0000102Bd00000540sv0000102Bsd00002200* ID_MODEL_FROM_DATABASE=M91XX (VDA1164 Output Board) pci:v0000102Bd00000540sv0000102Bsd00002240* ID_MODEL_FROM_DATABASE=M91XX (M9148 LP PCIe x16) pci:v0000102Bd00000540sv0000102Bsd00002241* ID_MODEL_FROM_DATABASE=M91XX (M9138 LP PCIe x16) pci:v0000102Bd00000540sv0000102Bsd00002280* ID_MODEL_FROM_DATABASE=M91XX (M9188 ATX PCIe x16) pci:v0000102Bd00000540sv0000102Bsd000022C0* ID_MODEL_FROM_DATABASE=M91XX (M9128 LP PCIe x16) pci:v0000102Bd00000D10* ID_MODEL_FROM_DATABASE=MGA Ultima/Impression pci:v0000102Bd00001000* ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] pci:v0000102Bd00001000sv0000102Bsd0000FF01* ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] (Productiva G100) pci:v0000102Bd00001000sv0000102Bsd0000FF05* ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] (Productiva G100 Multi-Monitor) pci:v0000102Bd00001001* ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP pci:v0000102Bd00001001sv0000102Bsd00001001* ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (MGA-G100 AGP) pci:v0000102Bd00001001sv0000102Bsd0000FF00* ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (MGA-G100 AGP) pci:v0000102Bd00001001sv0000102Bsd0000FF01* ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (MGA-G100 Productiva AGP) pci:v0000102Bd00001001sv0000102Bsd0000FF03* ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (Millennium G100 AGP) pci:v0000102Bd00001001sv0000102Bsd0000FF04* ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (MGA-G100 AGP) pci:v0000102Bd00001001sv0000102Bsd0000FF05* ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (MGA-G100 Productiva AGP Multi-Monitor) pci:v0000102Bd00001001sv0000110Asd0000001E* ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (MGA-G100 AGP) pci:v0000102Bd00002007* ID_MODEL_FROM_DATABASE=MGA Mistral pci:v0000102Bd00002527* ID_MODEL_FROM_DATABASE=Millennium G550 pci:v0000102Bd00002527sv0000102Bsd00000F42* ID_MODEL_FROM_DATABASE=Millennium G550 (Matrox G550 Low Profile PCI) pci:v0000102Bd00002527sv0000102Bsd00000F83* ID_MODEL_FROM_DATABASE=Millennium G550 pci:v0000102Bd00002527sv0000102Bsd00000F84* ID_MODEL_FROM_DATABASE=Millennium G550 (Dual Head DDR 32Mb) pci:v0000102Bd00002527sv0000102Bsd00001E41* ID_MODEL_FROM_DATABASE=Millennium G550 pci:v0000102Bd00002527sv0000102Bsd00002300* ID_MODEL_FROM_DATABASE=Millennium G550 (LP PCIE) pci:v0000102Bd00002537* ID_MODEL_FROM_DATABASE=Millenium P650/P750 pci:v0000102Bd00002537sv0000102Bsd00001820* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (Millennium P750 64MB) pci:v0000102Bd00002537sv0000102Bsd00001830* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (Millennium P650 64MB) pci:v0000102Bd00002537sv0000102Bsd00001850* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (RAD2mp) pci:v0000102Bd00002537sv0000102Bsd00001860* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (RAD3mp) pci:v0000102Bd00002537sv0000102Bsd00001880* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (Sono S10) pci:v0000102Bd00002537sv0000102Bsd00001C10* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (QID 128MB) pci:v0000102Bd00002537sv0000102Bsd00002811* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (Millennium P650 Low-profile PCI 64MB) pci:v0000102Bd00002537sv0000102Bsd00002821* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (Millenium P650 Low-profile PCI) pci:v0000102Bd00002537sv0000102Bsd00002841* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (RAD PCI) pci:v0000102Bd00002537sv0000102Bsd00002851* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (Spectrum PCI) pci:v0000102Bd00002537sv0000102Bsd00002871* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (EpicA TC2) pci:v0000102Bd00002537sv0000102Bsd00002C11* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (QID Low-profile PCI) pci:v0000102Bd00002537sv0000102Bsd00002C21* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (QID LP PCI LW) pci:v0000102Bd00002537sv0000102Bsd00002C31* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (QID LP PCI) pci:v0000102Bd00002537sv0000102Bsd00002C41* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (EpicA TC4) pci:v0000102Bd00002537sv0000102Bsd00003001* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (Extio F1400) pci:v0000102Bd00002537sv0000102Bsd00003011* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (Extio F1220) pci:v0000102Bd00002537sv0000102Bsd00003041* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (RG-200DL) pci:v0000102Bd00002537sv0000102Bsd00003051* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (RG-400SL) pci:v0000102Bd00002537sv0000102Bsd00003061* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (Extio F1420) pci:v0000102Bd00002537sv0000102Bsd00003081* ID_MODEL_FROM_DATABASE=Millenium P650/P750 (Extio F1240) pci:v0000102Bd00002538* ID_MODEL_FROM_DATABASE=Millenium P650 PCIe pci:v0000102Bd00002538sv0000102Bsd00000847* ID_MODEL_FROM_DATABASE=Millenium P650 PCIe (RAD PCIe) pci:v0000102Bd00002538sv0000102Bsd000008C7* ID_MODEL_FROM_DATABASE=Millenium P650 PCIe (Millennium P650 PCIe 128MB) pci:v0000102Bd00002538sv0000102Bsd00000907* ID_MODEL_FROM_DATABASE=Millenium P650 PCIe (Millennium P650 PCIe 64MB) pci:v0000102Bd00002538sv0000102Bsd00000947* ID_MODEL_FROM_DATABASE=Millenium P650 PCIe (Parhelia APVe) pci:v0000102Bd00002538sv0000102Bsd00000987* ID_MODEL_FROM_DATABASE=Millenium P650 PCIe (ATC PCIe 4MP) pci:v0000102Bd00002538sv0000102Bsd00001047* ID_MODEL_FROM_DATABASE=Millenium P650 PCIe (Millennium P650 LP PCIe 128MB) pci:v0000102Bd00002538sv0000102Bsd00001087* ID_MODEL_FROM_DATABASE=Millenium P650 PCIe (Millennium P650 LP PCIe 64MB) pci:v0000102Bd00002538sv0000102Bsd00001801* ID_MODEL_FROM_DATABASE=Millenium P650 PCIe (x1) pci:v0000102Bd00002538sv0000102Bsd00002538* ID_MODEL_FROM_DATABASE=Millenium P650 PCIe (Parhelia APVe) pci:v0000102Bd00002538sv0000102Bsd00003007* ID_MODEL_FROM_DATABASE=Millenium P650 PCIe (QID Low-profile PCIe) pci:v0000102Bd00002538sv0000102Bsd00003087* ID_MODEL_FROM_DATABASE=Millenium P650 PCIe (Aurora VX3mp) pci:v0000102Bd00002538sv0000102Bsd000030C7* ID_MODEL_FROM_DATABASE=Millenium P650 PCIe (QID LP PCIe) pci:v0000102Bd00002539* ID_MODEL_FROM_DATABASE=Millennium P690 pci:v0000102Bd00002539sv0000102Bsd00000040* ID_MODEL_FROM_DATABASE=Millennium P690 (Millenium P690 PCIe x16) pci:v0000102Bd00002539sv0000102Bsd00000042* ID_MODEL_FROM_DATABASE=Millennium P690 (ONYX) pci:v0000102Bd00002539sv0000102Bsd00000043* ID_MODEL_FROM_DATABASE=Millennium P690 (SPECTRA) pci:v0000102Bd00002539sv0000102Bsd00000080* ID_MODEL_FROM_DATABASE=Millennium P690 (Millenium P690 Plus LP PCIe x16) pci:v0000102Bd00002539sv0000102Bsd00000081* ID_MODEL_FROM_DATABASE=Millennium P690 (Millenium P690 LP PCIe x16) pci:v0000102Bd00002539sv0000102Bsd00000082* ID_MODEL_FROM_DATABASE=Millennium P690 (RAD LPX PCIe x16) pci:v0000102Bd00002539sv0000102Bsd000000C0* ID_MODEL_FROM_DATABASE=Millennium P690 (Millenium P690 Plus LP PCI) pci:v0000102Bd00002539sv0000102Bsd000000C2* ID_MODEL_FROM_DATABASE=Millennium P690 (Millenium P690 LP PCI) pci:v0000102Bd00002539sv0000102Bsd000000C3* ID_MODEL_FROM_DATABASE=Millennium P690 (RAD LPX PCI) pci:v0000102Bd00002539sv0000102Bsd00000101* ID_MODEL_FROM_DATABASE=Millennium P690 (Millenium P690 PCI) pci:v0000102Bd00002539sv0000102Bsd00000140* ID_MODEL_FROM_DATABASE=Millennium P690 (Millenium P690 LP PCIe x1) pci:v0000102Bd00002539sv0000102Bsd00000180* ID_MODEL_FROM_DATABASE=Millennium P690 (Display Wall IP Decode 128 MB) pci:v0000102Bd00004164* ID_MODEL_FROM_DATABASE=Morphis QxT frame grabber pci:v0000102Bd000043B4* ID_MODEL_FROM_DATABASE=Morphis Qxt encoding engine pci:v0000102Bd00004510* ID_MODEL_FROM_DATABASE=Morphis COM port pci:v0000102Bd00004536* ID_MODEL_FROM_DATABASE=VIA Framegrabber pci:v0000102Bd00004686* ID_MODEL_FROM_DATABASE=Concord GX (customized Intel 82541) pci:v0000102Bd0000475B* ID_MODEL_FROM_DATABASE=Solios eCL/XCL-B frame grabber pci:v0000102Bd0000475D* ID_MODEL_FROM_DATABASE=Vio frame grabber family pci:v0000102Bd0000475Dsv0000102Bsd00004B90* ID_MODEL_FROM_DATABASE=Vio frame grabber family (Vio Duo frame grabber (single channel)) pci:v0000102Bd0000475Dsv0000102Bsd00004B91* ID_MODEL_FROM_DATABASE=Vio frame grabber family (Vio Duo frame grabber) pci:v0000102Bd0000475Dsv0000102Bsd00004B92* ID_MODEL_FROM_DATABASE=Vio frame grabber family (Vio Analog frame grabber) pci:v0000102Bd0000475Dsv0000102Bsd00004B93* ID_MODEL_FROM_DATABASE=Vio frame grabber family (Vio SDI Frame Grabber) pci:v0000102Bd0000475Dsv0000102Bsd00004B94* ID_MODEL_FROM_DATABASE=Vio frame grabber family (Vio DVI-A frame grabber) pci:v0000102Bd0000475F* ID_MODEL_FROM_DATABASE=Solios (single-Full) CL frame grabber pci:v0000102Bd0000475Fsv0000102Bsd0000475F* ID_MODEL_FROM_DATABASE=Solios (single-Full) CL frame grabber (Solios eCL/XCL-F frame grabber) pci:v0000102Bd0000475Fsv0000102Bsd00004D5F* ID_MODEL_FROM_DATABASE=Solios (single-Full) CL frame grabber (Solios eV-CL (single-Full) frame grabber) pci:v0000102Bd0000475Fsv0000102Bsd00004E5F* ID_MODEL_FROM_DATABASE=Solios (single-Full) CL frame grabber (Solios eM-CL (single-Full) frame grabber) pci:v0000102Bd000047A1* ID_MODEL_FROM_DATABASE=Solios eA/XA frame grabber pci:v0000102Bd000047A1sv0000102Bsd00004BE0* ID_MODEL_FROM_DATABASE=Solios eA/XA frame grabber (Solios eA/XA (single) frame grabber) pci:v0000102Bd000047A1sv0000102Bsd00004BE1* ID_MODEL_FROM_DATABASE=Solios eA/XA frame grabber (Solios eA/XA (dual) frame grabber) pci:v0000102Bd000047A1sv0000102Bsd00004BE2* ID_MODEL_FROM_DATABASE=Solios eA/XA frame grabber (Solios eA/XA (quad) frame grabber) pci:v0000102Bd000047A2* ID_MODEL_FROM_DATABASE=Solios COM port pci:v0000102Bd000047C1* ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber pci:v0000102Bd000047C1sv0000102Bsd00000000* ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios frame grabber) pci:v0000102Bd000047C1sv0000102Bsd00004B80* ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios eCL/XCL (single-Medium) frame grabber) pci:v0000102Bd000047C1sv0000102Bsd00004B81* ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios eCL/XCL (dual-Base) frame grabber) pci:v0000102Bd000047C1sv0000102Bsd00004D80* ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios eV-CL (single-Medium) frame grabber) pci:v0000102Bd000047C1sv0000102Bsd00004D81* ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios eV-CL (dual-Base) frame grabber) pci:v0000102Bd000047C1sv0000102Bsd00004E80* ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios eM-CL (single-Medium) frame grabber) pci:v0000102Bd000047C1sv0000102Bsd00004E81* ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios eM-CL (dual-Base) frame grabber) pci:v0000102Bd000047C2* ID_MODEL_FROM_DATABASE=Solios COM port pci:v0000102Bd00004949* ID_MODEL_FROM_DATABASE=Radient frame grabber family pci:v0000102Bd00004949sv0000102Bsd00000010* ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eCL (Single-full) frame grabber) pci:v0000102Bd00004949sv0000102Bsd00000011* ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eCLV (Single-full) frame grabber) pci:v0000102Bd00004949sv0000102Bsd00000020* ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eCL (Dual-base) frame grabber) pci:v0000102Bd00004949sv0000102Bsd00000030* ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eCL (Dual-full) frame grabber) pci:v0000102Bd00004949sv0000102Bsd00000040* ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eCL (Quad-base) frame grabber) pci:v0000102Bd00004949sv0000102Bsd00000050* ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eCL (Golden) frame grabber) pci:v0000102Bd00004949sv0000102Bsd00001010* ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eV-CXP (quad CXP-6) frame grabber) pci:v0000102Bd00004949sv0000102Bsd00001015* ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eV-CXP (dual CXP-6) frame grabber) pci:v0000102Bd00004949sv0000102Bsd00001020* ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eV-CXP (quad CXP-3) frame grabber) pci:v0000102Bd00004949sv0000102Bsd00001050* ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eV-CXP (Golden) frame grabber) pci:v0000102Bd00004CDC* ID_MODEL_FROM_DATABASE=Morphis JPEG2000 accelerator pci:v0000102Bd00004F54* ID_MODEL_FROM_DATABASE=Morphis (e)Quad frame grabber pci:v0000102Bd00004FC5* ID_MODEL_FROM_DATABASE=Morphis (e)Dual frame grabber pci:v0000102Bd00005E10* ID_MODEL_FROM_DATABASE=Morphis aux I/O pci:v0000102Bd00006573* ID_MODEL_FROM_DATABASE=Shark 10/100 Multiport SwitchNIC pci:v0000102C* ID_VENDOR_FROM_DATABASE=Chips and Technologies pci:v0000102Cd000000B8* ID_MODEL_FROM_DATABASE=F64310 pci:v0000102Cd000000C0* ID_MODEL_FROM_DATABASE=F69000 HiQVideo pci:v0000102Cd000000C0sv0000102Csd000000C0* ID_MODEL_FROM_DATABASE=F69000 HiQVideo pci:v0000102Cd000000C0sv00004C53sd00001000* ID_MODEL_FROM_DATABASE=F69000 HiQVideo (CC7/CR7/CP7/VC7/VP7/VR7 mainboard) pci:v0000102Cd000000C0sv00004C53sd00001010* ID_MODEL_FROM_DATABASE=F69000 HiQVideo (CP5/CR6 mainboard) pci:v0000102Cd000000C0sv00004C53sd00001020* ID_MODEL_FROM_DATABASE=F69000 HiQVideo (VR6 mainboard) pci:v0000102Cd000000C0sv00004C53sd00001030* ID_MODEL_FROM_DATABASE=F69000 HiQVideo (PC5 mainboard) pci:v0000102Cd000000C0sv00004C53sd00001050* ID_MODEL_FROM_DATABASE=F69000 HiQVideo (CT7 mainboard) pci:v0000102Cd000000C0sv00004C53sd00001051* ID_MODEL_FROM_DATABASE=F69000 HiQVideo (CE7 mainboard) pci:v0000102Cd000000D0* ID_MODEL_FROM_DATABASE=F65545 pci:v0000102Cd000000D8* ID_MODEL_FROM_DATABASE=F65545 pci:v0000102Cd000000DC* ID_MODEL_FROM_DATABASE=F65548 pci:v0000102Cd000000E0* ID_MODEL_FROM_DATABASE=F65550 pci:v0000102Cd000000E4* ID_MODEL_FROM_DATABASE=F65554 pci:v0000102Cd000000E5* ID_MODEL_FROM_DATABASE=F65555 HiQVPro pci:v0000102Cd000000E5sv00000E11sd0000B049* ID_MODEL_FROM_DATABASE=F65555 HiQVPro (Armada 1700 Laptop Display Controller) pci:v0000102Cd000000E5sv00001179sd00000001* ID_MODEL_FROM_DATABASE=F65555 HiQVPro (Satellite Pro/Satellite) pci:v0000102Cd000000F0* ID_MODEL_FROM_DATABASE=F68554 pci:v0000102Cd000000F4* ID_MODEL_FROM_DATABASE=F68554 HiQVision pci:v0000102Cd000000F5* ID_MODEL_FROM_DATABASE=F68555 pci:v0000102Cd00000C30* ID_MODEL_FROM_DATABASE=F69030 pci:v0000102Cd00000C30sv00004C53sd00001000* ID_MODEL_FROM_DATABASE=F69030 (CC7/CR7/CP7/VC7/VP7/VR7 mainboard) pci:v0000102Cd00000C30sv00004C53sd00001050* ID_MODEL_FROM_DATABASE=F69030 (CT7 mainboard) pci:v0000102Cd00000C30sv00004C53sd00001051* ID_MODEL_FROM_DATABASE=F69030 (CE7 mainboard) pci:v0000102Cd00000C30sv00004C53sd00001080* ID_MODEL_FROM_DATABASE=F69030 (CT8 mainboard) pci:v0000102D* ID_VENDOR_FROM_DATABASE=Wyse Technology Inc. pci:v0000102Dd000050DC* ID_MODEL_FROM_DATABASE=3328 Audio pci:v0000102E* ID_VENDOR_FROM_DATABASE=Olivetti Advanced Technology pci:v0000102F* ID_VENDOR_FROM_DATABASE=Toshiba America pci:v0000102Fd00000009* ID_MODEL_FROM_DATABASE=r4x00 pci:v0000102Fd0000000A* ID_MODEL_FROM_DATABASE=TX3927 MIPS RISC PCI Controller pci:v0000102Fd00000020* ID_MODEL_FROM_DATABASE=ATM Meteor 155 pci:v0000102Fd00000020sv0000102Fsd000000F8* ID_MODEL_FROM_DATABASE=ATM Meteor 155 pci:v0000102Fd00000030* ID_MODEL_FROM_DATABASE=TC35815CF PCI 10/100 Mbit Ethernet Controller pci:v0000102Fd00000031* ID_MODEL_FROM_DATABASE=TC35815CF PCI 10/100 Mbit Ethernet Controller with WOL pci:v0000102Fd00000032* ID_MODEL_FROM_DATABASE=TC35815CF PCI 10/100 Mbit Ethernet Controller on TX4939 pci:v0000102Fd00000105* ID_MODEL_FROM_DATABASE=TC86C001 [goku-s] IDE pci:v0000102Fd00000106* ID_MODEL_FROM_DATABASE=TC86C001 [goku-s] USB 1.1 Host pci:v0000102Fd00000107* ID_MODEL_FROM_DATABASE=TC86C001 [goku-s] USB Device Controller pci:v0000102Fd00000108* ID_MODEL_FROM_DATABASE=TC86C001 [goku-s] I2C/SIO/GPIO Controller pci:v0000102Fd00000180* ID_MODEL_FROM_DATABASE=TX4927/38 MIPS RISC PCI Controller pci:v0000102Fd00000181* ID_MODEL_FROM_DATABASE=TX4925 MIPS RISC PCI Controller pci:v0000102Fd00000182* ID_MODEL_FROM_DATABASE=TX4937 MIPS RISC PCI Controller pci:v0000102Fd000001B4* ID_MODEL_FROM_DATABASE=Celleb platform IDE interface pci:v0000102Fd000001B5* ID_MODEL_FROM_DATABASE=SCC USB 2.0 EHCI controller pci:v0000102Fd000001B6* ID_MODEL_FROM_DATABASE=SCC USB 1.1 OHCI controller pci:v00001030* ID_VENDOR_FROM_DATABASE=TMC Research pci:v00001031* ID_VENDOR_FROM_DATABASE=Miro Computer Products AG pci:v00001031d00005601* ID_MODEL_FROM_DATABASE=DC20 ASIC pci:v00001031d00005607* ID_MODEL_FROM_DATABASE=Video I/O & motion JPEG compressor pci:v00001031d00005631* ID_MODEL_FROM_DATABASE=Media 3D pci:v00001031d00006057* ID_MODEL_FROM_DATABASE=MiroVideo DC10/DC30+ pci:v00001032* ID_VENDOR_FROM_DATABASE=Compaq pci:v00001033* ID_VENDOR_FROM_DATABASE=NEC Corporation pci:v00001033d00000000* ID_MODEL_FROM_DATABASE=Vr4181A USB Host or Function Control Unit pci:v00001033d00000001* ID_MODEL_FROM_DATABASE=PCI to 486-like bus Bridge pci:v00001033d00000002* ID_MODEL_FROM_DATABASE=PCI to VL98 Bridge pci:v00001033d00000003* ID_MODEL_FROM_DATABASE=ATM Controller pci:v00001033d00000004* ID_MODEL_FROM_DATABASE=R4000 PCI Bridge pci:v00001033d00000005* ID_MODEL_FROM_DATABASE=PCI to 486-like bus Bridge pci:v00001033d00000006* ID_MODEL_FROM_DATABASE=PC-9800 Graphic Accelerator pci:v00001033d00000007* ID_MODEL_FROM_DATABASE=PCI to UX-Bus Bridge pci:v00001033d00000008* ID_MODEL_FROM_DATABASE=PC-9800 Graphic Accelerator pci:v00001033d00000009* ID_MODEL_FROM_DATABASE=PCI to PC9800 Core-Graph Bridge pci:v00001033d00000016* ID_MODEL_FROM_DATABASE=PCI to VL Bridge pci:v00001033d0000001A* ID_MODEL_FROM_DATABASE=[Nile II] pci:v00001033d00000021* ID_MODEL_FROM_DATABASE=Vrc4373 [Nile I] pci:v00001033d00000029* ID_MODEL_FROM_DATABASE=PowerVR PCX1 pci:v00001033d0000002A* ID_MODEL_FROM_DATABASE=PowerVR 3D pci:v00001033d0000002C* ID_MODEL_FROM_DATABASE=Star Alpha 2 pci:v00001033d0000002D* ID_MODEL_FROM_DATABASE=PCI to C-bus Bridge pci:v00001033d00000035* ID_MODEL_FROM_DATABASE=OHCI USB Controller pci:v00001033d00000035sv00001033sd00000035* ID_MODEL_FROM_DATABASE=OHCI USB Controller (USB Controller) pci:v00001033d00000035sv0000103Csd00001293* ID_MODEL_FROM_DATABASE=OHCI USB Controller (USB add-in card) pci:v00001033d00000035sv0000103Csd00001294* ID_MODEL_FROM_DATABASE=OHCI USB Controller (USB 2.0 add-in card) pci:v00001033d00000035sv00001179sd00000001* ID_MODEL_FROM_DATABASE=OHCI USB Controller (USB) pci:v00001033d00000035sv00001186sd00000035* ID_MODEL_FROM_DATABASE=OHCI USB Controller (DUB-C2 USB 2.0 2-port 32-bit cardbus controller) pci:v00001033d00000035sv000012EEsd00007000* ID_MODEL_FROM_DATABASE=OHCI USB Controller (Root Hub) pci:v00001033d00000035sv000014C2sd00000105* ID_MODEL_FROM_DATABASE=OHCI USB Controller (PTI-205N USB 2.0 Host Controller) pci:v00001033d00000035sv00001799sd00000001* ID_MODEL_FROM_DATABASE=OHCI USB Controller (Root Hub) pci:v00001033d00000035sv00001931sd0000000A* ID_MODEL_FROM_DATABASE=OHCI USB Controller (GlobeTrotter Fusion Quad Lite (PPP data)) pci:v00001033d00000035sv00001931sd0000000B* ID_MODEL_FROM_DATABASE=OHCI USB Controller (GlobeTrotter Fusion Quad Lite (GSM data)) pci:v00001033d00000035sv0000807Dsd00000035* ID_MODEL_FROM_DATABASE=OHCI USB Controller (PCI-USB2 (OHCI subsystem)) pci:v00001033d0000003B* ID_MODEL_FROM_DATABASE=PCI to C-bus Bridge pci:v00001033d0000003E* ID_MODEL_FROM_DATABASE=NAPCCARD Cardbus Controller pci:v00001033d00000046* ID_MODEL_FROM_DATABASE=PowerVR PCX2 [midas] pci:v00001033d0000005A* ID_MODEL_FROM_DATABASE=Vrc5074 [Nile 4] pci:v00001033d00000063* ID_MODEL_FROM_DATABASE=uPD72862 [Firewarden] IEEE1394 OHCI 1.0 Link Controller pci:v00001033d00000067* ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset pci:v00001033d00000067sv00001010sd00000020* ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 AGP 32Mb) pci:v00001033d00000067sv00001010sd00000080* ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 AGP 16Mb) pci:v00001033d00000067sv00001010sd00000088* ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 16Mb) pci:v00001033d00000067sv00001010sd00000090* ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 AGP 16Mb) pci:v00001033d00000067sv00001010sd00000098* ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 16Mb) pci:v00001033d00000067sv00001010sd000000A0* ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 AGP 32Mb) pci:v00001033d00000067sv00001010sd000000A8* ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 32Mb) pci:v00001033d00000067sv00001010sd00000120* ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 AGP 32Mb) pci:v00001033d00000072* ID_MODEL_FROM_DATABASE=uPD72874 IEEE1394 OHCI 1.1 3-port PHY-Link Ctrlr pci:v00001033d00000074* ID_MODEL_FROM_DATABASE=56k Voice Modem pci:v00001033d00000074sv00001033sd00008014* ID_MODEL_FROM_DATABASE=56k Voice Modem (RCV56ACF 56k Voice Modem) pci:v00001033d0000009B* ID_MODEL_FROM_DATABASE=Vrc5476 pci:v00001033d000000A5* ID_MODEL_FROM_DATABASE=VRC4173 pci:v00001033d000000A6* ID_MODEL_FROM_DATABASE=VRC5477 AC97 pci:v00001033d000000CD* ID_MODEL_FROM_DATABASE=uPD72870 [Firewarden] IEEE1394a OHCI 1.0 Link/3-port PHY Controller pci:v00001033d000000CDsv000012EEsd00008011* ID_MODEL_FROM_DATABASE=uPD72870 [Firewarden] IEEE1394a OHCI 1.0 Link/3-port PHY Controller (Root hub) pci:v00001033d000000CE* ID_MODEL_FROM_DATABASE=uPD72871 [Firewarden] IEEE1394a OHCI 1.0 Link/1-port PHY Controller pci:v00001033d000000DF* ID_MODEL_FROM_DATABASE=Vr4131 pci:v00001033d000000E0* ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller pci:v00001033d000000E0sv00001186sd0000F100* ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller (DUB-C2 USB 2.0 2-port 32-bit cardbus controller) pci:v00001033d000000E0sv000012EEsd00007001* ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller (Root hub) pci:v00001033d000000E0sv000014C2sd00000205* ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller (PTI-205N USB 2.0 Host Controller) pci:v00001033d000000E0sv00001799sd00000002* ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller (Root Hub) pci:v00001033d000000E0sv0000807Dsd00001043* ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller (PCI-USB2 (EHCI subsystem)) pci:v00001033d000000E7* ID_MODEL_FROM_DATABASE=uPD72873 [Firewarden] IEEE1394a OHCI 1.1 Link/2-port PHY Controller pci:v00001033d000000F2* ID_MODEL_FROM_DATABASE=uPD72874 [Firewarden] IEEE1394a OHCI 1.1 Link/3-port PHY Controller pci:v00001033d000000F3* ID_MODEL_FROM_DATABASE=uPD6113x Multimedia Decoder/Processor [EMMA2] pci:v00001033d0000010C* ID_MODEL_FROM_DATABASE=VR7701 pci:v00001033d00000125* ID_MODEL_FROM_DATABASE=uPD720400 PCI Express - PCI/PCI-X Bridge pci:v00001033d0000013A* ID_MODEL_FROM_DATABASE=Dual Tuner/MPEG Encoder pci:v00001033d00000194* ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller pci:v00001033d00000194sv00001028sd000004A3* ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (Precision M4600) pci:v00001033d00000194sv00001028sd000004B2* ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (Vostro 3350) pci:v00001033d00000194sv00001028sd000004DA* ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (Vostro 3750) pci:v00001033d00000194sv00001043sd00008413* ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (P8P67 Deluxe Motherboard) pci:v00001033d00000194sv0000104Dsd0000907A* ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (Vaio VPCF1) pci:v00001033d00000194sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (QEMU Virtual Machine) pci:v00001033d00000194sv00001B96sd00000001* ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (USB 3.0 PCIe Card) pci:v00001033d000001E7* ID_MODEL_FROM_DATABASE=uPD72873 [Firewarden] IEEE1394a OHCI 1.1 Link/2-port PHY Controller pci:v00001033d000001F2* ID_MODEL_FROM_DATABASE=uPD72874 [Firewarden] IEEE1394a OHCI 1.1 Link/3-port PHY Controller pci:v00001034* ID_VENDOR_FROM_DATABASE=Framatome Connectors USA Inc. pci:v00001035* ID_VENDOR_FROM_DATABASE=Comp. & Comm. Research Lab pci:v00001036* ID_VENDOR_FROM_DATABASE=Future Domain Corp. pci:v00001036d00000000* ID_MODEL_FROM_DATABASE=TMC-18C30 [36C70] pci:v00001037* ID_VENDOR_FROM_DATABASE=Hitachi Micro Systems pci:v00001038* ID_VENDOR_FROM_DATABASE=AMP, Inc pci:v00001039* ID_VENDOR_FROM_DATABASE=Silicon Integrated Systems [SiS] pci:v00001039d00000001* ID_MODEL_FROM_DATABASE=AGP Port (virtual PCI-to-PCI bridge) pci:v00001039d00000002* ID_MODEL_FROM_DATABASE=AGP Port (virtual PCI-to-PCI bridge) pci:v00001039d00000003* ID_MODEL_FROM_DATABASE=AGP Port (virtual PCI-to-PCI bridge) pci:v00001039d00000004* ID_MODEL_FROM_DATABASE=PCI-to-PCI bridge pci:v00001039d00000004sv00001039sd00000000* ID_MODEL_FROM_DATABASE=PCI-to-PCI bridge (PCIe x16 port) pci:v00001039d00000006* ID_MODEL_FROM_DATABASE=85C501/2/3 pci:v00001039d00000008* ID_MODEL_FROM_DATABASE=SiS85C503/5513 (LPC Bridge) pci:v00001039d00000009* ID_MODEL_FROM_DATABASE=5595 Power Management Controller pci:v00001039d0000000A* ID_MODEL_FROM_DATABASE=PCI-to-PCI bridge pci:v00001039d0000000Asv00001039sd00000000* ID_MODEL_FROM_DATABASE=PCI-to-PCI bridge (PCIe x1 port) pci:v00001039d00000016* ID_MODEL_FROM_DATABASE=SiS961/2/3 SMBus controller pci:v00001039d00000018* ID_MODEL_FROM_DATABASE=SiS85C503/5513 (LPC Bridge) pci:v00001039d00000163* ID_MODEL_FROM_DATABASE=163 802.11b/g Wireless LAN Adapter pci:v00001039d00000180* ID_MODEL_FROM_DATABASE=RAID bus controller 180 SATA/PATA [SiS] pci:v00001039d00000181* ID_MODEL_FROM_DATABASE=SATA pci:v00001039d00000182* ID_MODEL_FROM_DATABASE=182 SATA/RAID Controller pci:v00001039d00000182sv00001734sd00001095* ID_MODEL_FROM_DATABASE=182 SATA/RAID Controller (D2030-A1) pci:v00001039d00000186* ID_MODEL_FROM_DATABASE=AHCI Controller (0106) pci:v00001039d00000190* ID_MODEL_FROM_DATABASE=190 Ethernet Adapter pci:v00001039d00000191* ID_MODEL_FROM_DATABASE=191 Gigabit Ethernet Adapter pci:v00001039d00000191sv00001043sd00008139* ID_MODEL_FROM_DATABASE=191 Gigabit Ethernet Adapter (P5SD2-FM/S mainboard) pci:v00001039d00000200* ID_MODEL_FROM_DATABASE=5597/5598/6326 VGA pci:v00001039d00000200sv00001039sd00000000* ID_MODEL_FROM_DATABASE=5597/5598/6326 VGA (SiS5597 SVGA (Shared RAM)) pci:v00001039d00000204* ID_MODEL_FROM_DATABASE=82C204 pci:v00001039d00000205* ID_MODEL_FROM_DATABASE=SG86C205 pci:v00001039d00000300* ID_MODEL_FROM_DATABASE=300/305 PCI/AGP VGA Display Adapter pci:v00001039d00000300sv0000107Dsd00002720* ID_MODEL_FROM_DATABASE=300/305 PCI/AGP VGA Display Adapter (Leadtek WinFast VR300) pci:v00001039d00000310* ID_MODEL_FROM_DATABASE=315H PCI/AGP VGA Display Adapter pci:v00001039d00000315* ID_MODEL_FROM_DATABASE=315 PCI/AGP VGA Display Adapter pci:v00001039d00000325* ID_MODEL_FROM_DATABASE=315PRO PCI/AGP VGA Display Adapter pci:v00001039d00000330* ID_MODEL_FROM_DATABASE=330 [Xabre] PCI/AGP VGA Display Adapter pci:v00001039d00000406* ID_MODEL_FROM_DATABASE=85C501/2 pci:v00001039d00000496* ID_MODEL_FROM_DATABASE=85C496 pci:v00001039d00000530* ID_MODEL_FROM_DATABASE=530 Host pci:v00001039d00000540* ID_MODEL_FROM_DATABASE=540 Host pci:v00001039d00000550* ID_MODEL_FROM_DATABASE=550 Host pci:v00001039d00000597* ID_MODEL_FROM_DATABASE=5513C pci:v00001039d00000601* ID_MODEL_FROM_DATABASE=85C601 pci:v00001039d00000620* ID_MODEL_FROM_DATABASE=620 Host pci:v00001039d00000630* ID_MODEL_FROM_DATABASE=630 Host pci:v00001039d00000633* ID_MODEL_FROM_DATABASE=633 Host pci:v00001039d00000635* ID_MODEL_FROM_DATABASE=635 Host pci:v00001039d00000645* ID_MODEL_FROM_DATABASE=SiS645 Host & Memory & AGP Controller pci:v00001039d00000646* ID_MODEL_FROM_DATABASE=SiS645DX Host & Memory & AGP Controller pci:v00001039d00000648* ID_MODEL_FROM_DATABASE=645xx pci:v00001039d00000649* ID_MODEL_FROM_DATABASE=SiS649 Host pci:v00001039d00000650* ID_MODEL_FROM_DATABASE=650/M650 Host pci:v00001039d00000651* ID_MODEL_FROM_DATABASE=651 Host pci:v00001039d00000655* ID_MODEL_FROM_DATABASE=655 Host pci:v00001039d00000660* ID_MODEL_FROM_DATABASE=660 Host pci:v00001039d00000661* ID_MODEL_FROM_DATABASE=661FX/M661FX/M661MX Host pci:v00001039d00000662* ID_MODEL_FROM_DATABASE=662 Host pci:v00001039d00000671* ID_MODEL_FROM_DATABASE=671MX pci:v00001039d00000730* ID_MODEL_FROM_DATABASE=730 Host pci:v00001039d00000733* ID_MODEL_FROM_DATABASE=733 Host pci:v00001039d00000735* ID_MODEL_FROM_DATABASE=735 Host pci:v00001039d00000740* ID_MODEL_FROM_DATABASE=740 Host pci:v00001039d00000741* ID_MODEL_FROM_DATABASE=741/741GX/M741 Host pci:v00001039d00000741sv00001849sd00000741* ID_MODEL_FROM_DATABASE=741/741GX/M741 Host (K7S41/K7S41GX motherboard) pci:v00001039d00000745* ID_MODEL_FROM_DATABASE=745 Host pci:v00001039d00000746* ID_MODEL_FROM_DATABASE=746 Host pci:v00001039d00000755* ID_MODEL_FROM_DATABASE=755 Host pci:v00001039d00000760* ID_MODEL_FROM_DATABASE=760/M760 Host pci:v00001039d00000761* ID_MODEL_FROM_DATABASE=761/M761 Host pci:v00001039d00000761sv00001734sd00001099* ID_MODEL_FROM_DATABASE=761/M761 Host (D2030-A1 Motherboard) pci:v00001039d00000900* ID_MODEL_FROM_DATABASE=SiS900 PCI Fast Ethernet pci:v00001039d00000900sv00001019sd00000A14* ID_MODEL_FROM_DATABASE=SiS900 PCI Fast Ethernet (K7S5A motherboard) pci:v00001039d00000900sv00001039sd00000900* ID_MODEL_FROM_DATABASE=SiS900 PCI Fast Ethernet (SiS900 10/100 Ethernet Adapter onboard) pci:v00001039d00000900sv00001043sd00008035* ID_MODEL_FROM_DATABASE=SiS900 PCI Fast Ethernet (CUSI-FX motherboard) pci:v00001039d00000900sv00001043sd000080A7* ID_MODEL_FROM_DATABASE=SiS900 PCI Fast Ethernet (Motherboard P4S800D-X) pci:v00001039d00000900sv00001462sd00000900* ID_MODEL_FROM_DATABASE=SiS900 PCI Fast Ethernet (MS-6701 motherboard) pci:v00001039d00000961* ID_MODEL_FROM_DATABASE=SiS961 [MuTIOL Media IO] pci:v00001039d00000962* ID_MODEL_FROM_DATABASE=SiS962 [MuTIOL Media IO] LPC Controller pci:v00001039d00000963* ID_MODEL_FROM_DATABASE=SiS963 [MuTIOL Media IO] LPC Controller pci:v00001039d00000964* ID_MODEL_FROM_DATABASE=SiS964 [MuTIOL Media IO] LPC Controller pci:v00001039d00000965* ID_MODEL_FROM_DATABASE=SiS965 [MuTIOL Media IO] pci:v00001039d00000966* ID_MODEL_FROM_DATABASE=SiS966 [MuTIOL Media IO] pci:v00001039d00000968* ID_MODEL_FROM_DATABASE=SiS968 [MuTIOL Media IO] pci:v00001039d00001180* ID_MODEL_FROM_DATABASE=SATA Controller / IDE mode pci:v00001039d00001182* ID_MODEL_FROM_DATABASE=SATA Controller / RAID mode pci:v00001039d00001182sv00001039sd00000180* ID_MODEL_FROM_DATABASE=SATA Controller / RAID mode (SiS 966 4-port SATA controller) pci:v00001039d00001183* ID_MODEL_FROM_DATABASE=SATA Controller / IDE mode pci:v00001039d00001183sv00001039sd00000180* ID_MODEL_FROM_DATABASE=SATA Controller / IDE mode (SiS 966 4-port SATA controller) pci:v00001039d00001184* ID_MODEL_FROM_DATABASE=AHCI Controller / RAID mode pci:v00001039d00001185* ID_MODEL_FROM_DATABASE=AHCI IDE Controller (0106) pci:v00001039d00003602* ID_MODEL_FROM_DATABASE=83C602 pci:v00001039d00005107* ID_MODEL_FROM_DATABASE=5107 pci:v00001039d00005300* ID_MODEL_FROM_DATABASE=SiS540 PCI Display Adapter pci:v00001039d00005315* ID_MODEL_FROM_DATABASE=550 PCI/AGP VGA Display Adapter pci:v00001039d00005401* ID_MODEL_FROM_DATABASE=486 PCI Chipset pci:v00001039d00005511* ID_MODEL_FROM_DATABASE=5511/5512 pci:v00001039d00005513* ID_MODEL_FROM_DATABASE=5513 IDE Controller pci:v00001039d00005513sv00001019sd00000970* ID_MODEL_FROM_DATABASE=5513 IDE Controller (P6STP-FL motherboard) pci:v00001039d00005513sv00001039sd00005513* ID_MODEL_FROM_DATABASE=5513 IDE Controller (SiS5513 EIDE Controller (A,B step)) pci:v00001039d00005513sv00001043sd00008035* ID_MODEL_FROM_DATABASE=5513 IDE Controller (CUSI-FX motherboard) pci:v00001039d00005513sv00001462sd00007010* ID_MODEL_FROM_DATABASE=5513 IDE Controller (MS-6701 motherboard) pci:v00001039d00005513sv00001631sd00005513* ID_MODEL_FROM_DATABASE=5513 IDE Controller (GA-8SIML Rev1.0 Motherboard) pci:v00001039d00005513sv00001734sd00001095* ID_MODEL_FROM_DATABASE=5513 IDE Controller (D2030-A1 Motherboard) pci:v00001039d00005517* ID_MODEL_FROM_DATABASE=5517 pci:v00001039d00005571* ID_MODEL_FROM_DATABASE=5571 pci:v00001039d00005581* ID_MODEL_FROM_DATABASE=5581 Pentium Chipset pci:v00001039d00005582* ID_MODEL_FROM_DATABASE=5582 pci:v00001039d00005591* ID_MODEL_FROM_DATABASE=5591/5592 Host pci:v00001039d00005596* ID_MODEL_FROM_DATABASE=5596 Pentium Chipset pci:v00001039d00005597* ID_MODEL_FROM_DATABASE=5597 [SiS5582] pci:v00001039d00005600* ID_MODEL_FROM_DATABASE=5600 Host pci:v00001039d00006204* ID_MODEL_FROM_DATABASE=Video decoder & MPEG interface pci:v00001039d00006205* ID_MODEL_FROM_DATABASE=VGA Controller pci:v00001039d00006236* ID_MODEL_FROM_DATABASE=6236 3D-AGP pci:v00001039d00006300* ID_MODEL_FROM_DATABASE=630/730 PCI/AGP VGA Display Adapter pci:v00001039d00006300sv00001019sd00000970* ID_MODEL_FROM_DATABASE=630/730 PCI/AGP VGA Display Adapter (P6STP-FL motherboard) pci:v00001039d00006300sv00001043sd00008035* ID_MODEL_FROM_DATABASE=630/730 PCI/AGP VGA Display Adapter (CUSI-FX motherboard) pci:v00001039d00006300sv0000104Dsd000080E2* ID_MODEL_FROM_DATABASE=630/730 PCI/AGP VGA Display Adapter (VAIO PCV-J200) pci:v00001039d00006306* ID_MODEL_FROM_DATABASE=530/620 PCI/AGP VGA Display Adapter pci:v00001039d00006325* ID_MODEL_FROM_DATABASE=65x/M650/740 PCI/AGP VGA Display Adapter pci:v00001039d00006325sv00001039sd00006325* ID_MODEL_FROM_DATABASE=65x/M650/740 PCI/AGP VGA Display Adapter (SiS 651 onboard [Asus P4SC-EA]) pci:v00001039d00006325sv00001631sd00001004* ID_MODEL_FROM_DATABASE=65x/M650/740 PCI/AGP VGA Display Adapter (SiS 651C onboard [Gigabyte GA-8SIML Rev1.0]) pci:v00001039d00006326* ID_MODEL_FROM_DATABASE=86C326 5598/6326 pci:v00001039d00006326sv00001039sd00006326* ID_MODEL_FROM_DATABASE=86C326 5598/6326 (SiS6326 GUI Accelerator) pci:v00001039d00006326sv00001092sd00000A50* ID_MODEL_FROM_DATABASE=86C326 5598/6326 (SpeedStar A50) pci:v00001039d00006326sv00001092sd00000A70* ID_MODEL_FROM_DATABASE=86C326 5598/6326 (SpeedStar A70) pci:v00001039d00006326sv00001092sd00004910* ID_MODEL_FROM_DATABASE=86C326 5598/6326 (SpeedStar A70) pci:v00001039d00006326sv00001092sd00004920* ID_MODEL_FROM_DATABASE=86C326 5598/6326 (SpeedStar A70) pci:v00001039d00006326sv000010B0sd00006326* ID_MODEL_FROM_DATABASE=86C326 5598/6326 (S6110-B (AGP)) pci:v00001039d00006326sv00001569sd00006326* ID_MODEL_FROM_DATABASE=86C326 5598/6326 (SiS6326 GUI Accelerator) pci:v00001039d00006330* ID_MODEL_FROM_DATABASE=661/741/760 PCI/AGP or 662/761Gx PCIE VGA Display Adapter pci:v00001039d00006330sv00001039sd00006330* ID_MODEL_FROM_DATABASE=661/741/760 PCI/AGP or 662/761Gx PCIE VGA Display Adapter ([M]661xX/[M]741[GX]/[M]760 PCI/AGP VGA Adapter) pci:v00001039d00006330sv00001043sd00008113* ID_MODEL_FROM_DATABASE=661/741/760 PCI/AGP or 662/761Gx PCIE VGA Display Adapter (SiS Real 256E (ASUS P5S800-VM motherboard)) pci:v00001039d00006330sv00001458sd0000D000* ID_MODEL_FROM_DATABASE=661/741/760 PCI/AGP or 662/761Gx PCIE VGA Display Adapter (SiS661FX GUI 2D/3D Accelerator) pci:v00001039d00006330sv00001734sd00001099* ID_MODEL_FROM_DATABASE=661/741/760 PCI/AGP or 662/761Gx PCIE VGA Display Adapter (D2030-A1) pci:v00001039d00006350* ID_MODEL_FROM_DATABASE=770/670 PCIE VGA Display Adapter pci:v00001039d00006351* ID_MODEL_FROM_DATABASE=771/671 PCIE VGA Display Adapter pci:v00001039d00007001* ID_MODEL_FROM_DATABASE=USB 1.1 Controller pci:v00001039d00007001sv00001019sd00000A14* ID_MODEL_FROM_DATABASE=USB 1.1 Controller (K7S5A motherboard) pci:v00001039d00007001sv00001039sd00007000* ID_MODEL_FROM_DATABASE=USB 1.1 Controller (Onboard USB Controller) pci:v00001039d00007001sv00001462sd00005470* ID_MODEL_FROM_DATABASE=USB 1.1 Controller (ECS K7SOM+ motherboard) pci:v00001039d00007001sv00001462sd00007010* ID_MODEL_FROM_DATABASE=USB 1.1 Controller (MS-6701 motherboard) pci:v00001039d00007001sv00001734sd00001095* ID_MODEL_FROM_DATABASE=USB 1.1 Controller (D2030-A1 Motherboard) pci:v00001039d00007002* ID_MODEL_FROM_DATABASE=USB 2.0 Controller pci:v00001039d00007002sv00001462sd00005470* ID_MODEL_FROM_DATABASE=USB 2.0 Controller (K7SOM+ 5.2C Motherboard) pci:v00001039d00007002sv00001462sd00007010* ID_MODEL_FROM_DATABASE=USB 2.0 Controller (MS-6701 motherboard) pci:v00001039d00007002sv00001509sd00007002* ID_MODEL_FROM_DATABASE=USB 2.0 Controller (Onboard USB Controller) pci:v00001039d00007002sv00001734sd00001095* ID_MODEL_FROM_DATABASE=USB 2.0 Controller (D2030-A1) pci:v00001039d00007007* ID_MODEL_FROM_DATABASE=FireWire Controller pci:v00001039d00007007sv00001462sd0000701D* ID_MODEL_FROM_DATABASE=FireWire Controller (MS-6701) pci:v00001039d00007012* ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller pci:v00001039d00007012sv00001019sd00000F05* ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (A928 (i-Buddie)) pci:v00001039d00007012sv00001039sd00007012* ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (SiS 7012 onboard [Asus P4SC-EA] AC'97 Sound Controller) pci:v00001039d00007012sv00001043sd0000818F* ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (A8S-X Motherboard) pci:v00001039d00007012sv000013F6sd00000300* ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (CMI9739(A) on ECS K7S series motherboard) pci:v00001039d00007012sv00001462sd00005850* ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (MSI 648 Max (MS-6585)) pci:v00001039d00007012sv00001462sd00007010* ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (MS-6701 motherboard) pci:v00001039d00007012sv000015BDsd00001001* ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (DFI 661FX motherboard) pci:v00001039d00007012sv00001734sd0000109F* ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (D2030-A1 Motherboard) pci:v00001039d00007012sv00001849sd00007012* ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (K7S41GX motherboard) pci:v00001039d00007013* ID_MODEL_FROM_DATABASE=AC'97 Modem Controller pci:v00001039d00007016* ID_MODEL_FROM_DATABASE=SiS7016 PCI Fast Ethernet Adapter pci:v00001039d00007016sv00001039sd00007016* ID_MODEL_FROM_DATABASE=SiS7016 PCI Fast Ethernet Adapter (SiS7016 10/100 Ethernet Adapter) pci:v00001039d00007018* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv00001014sd000001B6* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv00001014sd000001B7* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv00001019sd00007018* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv00001025sd0000000E* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv00001025sd00000018* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv00001039sd00007018* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv00001043sd00001453* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv00001043sd0000800B* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv0000104Dsd000080E2* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator (VAIO PCV-J200) pci:v00001039d00007018sv00001054sd00007018* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv0000107Dsd00005330* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv0000107Dsd00005350* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv00001170sd00003209* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv00001462sd0000400A* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv000014A4sd00002089* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv000014CDsd00002194* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv000014FFsd00001100* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv0000152Dsd00008808* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv00001558sd00001103* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv00001558sd00002200* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv00001563sd00007018* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv000015C5sd00000111* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv0000270Fsd0000A171* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007018sv0000A0A0sd00000022* ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator pci:v00001039d00007019* ID_MODEL_FROM_DATABASE=SiS7019 Audio Accelerator pci:v00001039d00007502* ID_MODEL_FROM_DATABASE=Azalia Audio Controller pci:v00001039d00007502sv00001043sd000081A1* ID_MODEL_FROM_DATABASE=Azalia Audio Controller (P5SD2-FM/S mainboard) pci:v0000103A* ID_VENDOR_FROM_DATABASE=Seiko Epson Corporation pci:v0000103B* ID_VENDOR_FROM_DATABASE=Tatung Corp. Of America pci:v0000103C* ID_VENDOR_FROM_DATABASE=Hewlett-Packard Company pci:v0000103Cd00001005* ID_MODEL_FROM_DATABASE=A4977A Visualize EG pci:v0000103Cd00001008* ID_MODEL_FROM_DATABASE=Visualize FX pci:v0000103Cd00001028* ID_MODEL_FROM_DATABASE=Tach TL Fibre Channel Host Adapter pci:v0000103Cd00001029* ID_MODEL_FROM_DATABASE=Tach XL2 Fibre Channel Host Adapter pci:v0000103Cd00001029sv0000107Esd0000000F* ID_MODEL_FROM_DATABASE=Tach XL2 Fibre Channel Host Adapter (Interphase 5560 Fibre Channel Adapter) pci:v0000103Cd00001029sv00009004sd00009210* ID_MODEL_FROM_DATABASE=Tach XL2 Fibre Channel Host Adapter (1Gb/2Gb Family Fibre Channel Controller) pci:v0000103Cd00001029sv00009004sd00009211* ID_MODEL_FROM_DATABASE=Tach XL2 Fibre Channel Host Adapter (1Gb/2Gb Family Fibre Channel Controller) pci:v0000103Cd0000102A* ID_MODEL_FROM_DATABASE=Tach TS Fibre Channel Host Adapter pci:v0000103Cd0000102Asv0000107Esd0000000E* ID_MODEL_FROM_DATABASE=Tach TS Fibre Channel Host Adapter (Interphase 5540/5541 Fibre Channel Adapter) pci:v0000103Cd0000102Asv00009004sd00009110* ID_MODEL_FROM_DATABASE=Tach TS Fibre Channel Host Adapter (1Gb/2Gb Family Fibre Channel Controller) pci:v0000103Cd0000102Asv00009004sd00009111* ID_MODEL_FROM_DATABASE=Tach TS Fibre Channel Host Adapter (1Gb/2Gb Family Fibre Channel Controller) pci:v0000103Cd00001030* ID_MODEL_FROM_DATABASE=J2585A DeskDirect 10/100VG NIC pci:v0000103Cd00001031* ID_MODEL_FROM_DATABASE=J2585B HP 10/100VG PCI LAN Adapter pci:v0000103Cd00001031sv0000103Csd00001040* ID_MODEL_FROM_DATABASE=J2585B HP 10/100VG PCI LAN Adapter (J2973A DeskDirect 10BaseT NIC) pci:v0000103Cd00001031sv0000103Csd00001041* ID_MODEL_FROM_DATABASE=J2585B HP 10/100VG PCI LAN Adapter (J2585B DeskDirect 10/100VG NIC) pci:v0000103Cd00001031sv0000103Csd00001042* ID_MODEL_FROM_DATABASE=J2585B HP 10/100VG PCI LAN Adapter (J2970A DeskDirect 10BaseT/2 NIC) pci:v0000103Cd00001040* ID_MODEL_FROM_DATABASE=J2973A DeskDirect 10BaseT NIC pci:v0000103Cd00001041* ID_MODEL_FROM_DATABASE=J2585B DeskDirect 10/100 NIC pci:v0000103Cd00001042* ID_MODEL_FROM_DATABASE=J2970A DeskDirect 10BaseT/2 NIC pci:v0000103Cd00001048* ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART pci:v0000103Cd00001048sv0000103Csd00001049* ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Tosca Console) pci:v0000103Cd00001048sv0000103Csd0000104A* ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Tosca Secondary) pci:v0000103Cd00001048sv0000103Csd0000104B* ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Maestro SP2) pci:v0000103Cd00001048sv0000103Csd00001223* ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Superdome Console) pci:v0000103Cd00001048sv0000103Csd00001226* ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Keystone SP2) pci:v0000103Cd00001048sv0000103Csd00001227* ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Powerbar SP2) pci:v0000103Cd00001048sv0000103Csd00001282* ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Everest SP2) pci:v0000103Cd00001048sv0000103Csd00001301* ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Diva RMP3) pci:v0000103Cd00001054* ID_MODEL_FROM_DATABASE=PCI Local Bus Adapter pci:v0000103Cd00001064* ID_MODEL_FROM_DATABASE=79C970 PCnet Ethernet Controller pci:v0000103Cd0000108B* ID_MODEL_FROM_DATABASE=Visualize FXe pci:v0000103Cd000010C1* ID_MODEL_FROM_DATABASE=NetServer Smart IRQ Router pci:v0000103Cd000010ED* ID_MODEL_FROM_DATABASE=TopTools Remote Control pci:v0000103Cd000010F0* ID_MODEL_FROM_DATABASE=rio System Bus Adapter pci:v0000103Cd000010F1* ID_MODEL_FROM_DATABASE=rio I/O Controller pci:v0000103Cd00001219* ID_MODEL_FROM_DATABASE=NetServer PCI Hot-Plug Controller pci:v0000103Cd0000121A* ID_MODEL_FROM_DATABASE=NetServer SMIC Controller pci:v0000103Cd0000121B* ID_MODEL_FROM_DATABASE=NetServer Legacy COM Port Decoder pci:v0000103Cd0000121C* ID_MODEL_FROM_DATABASE=NetServer PCI COM Port Decoder pci:v0000103Cd00001229* ID_MODEL_FROM_DATABASE=zx1 System Bus Adapter pci:v0000103Cd0000122A* ID_MODEL_FROM_DATABASE=zx1 I/O Controller pci:v0000103Cd0000122E* ID_MODEL_FROM_DATABASE=PCI-X Local Bus Adapter pci:v0000103Cd0000127B* ID_MODEL_FROM_DATABASE=sx1000 System Bus Adapter pci:v0000103Cd0000127C* ID_MODEL_FROM_DATABASE=sx1000 I/O Controller pci:v0000103Cd00001290* ID_MODEL_FROM_DATABASE=Auxiliary Diva Serial Port pci:v0000103Cd00001290sv0000103Csd00001291* ID_MODEL_FROM_DATABASE=Auxiliary Diva Serial Port (Diva SP2) pci:v0000103Cd00001291* ID_MODEL_FROM_DATABASE=Auxiliary Diva Serial Port pci:v0000103Cd000012B4* ID_MODEL_FROM_DATABASE=zx1 QuickSilver AGP8x Local Bus Adapter pci:v0000103Cd000012EB* ID_MODEL_FROM_DATABASE=sx2000 System Bus Adapter pci:v0000103Cd000012EC* ID_MODEL_FROM_DATABASE=sx2000 I/O Controller pci:v0000103Cd000012EE* ID_MODEL_FROM_DATABASE=PCI-X 2.0 Local Bus Adapter pci:v0000103Cd00001302* ID_MODEL_FROM_DATABASE=RMP-3 Shared Memory Driver pci:v0000103Cd00001303* ID_MODEL_FROM_DATABASE=RMP-3 (Remote Management Processor) pci:v0000103Cd00002910* ID_MODEL_FROM_DATABASE=E2910A PCIBus Exerciser pci:v0000103Cd00002925* ID_MODEL_FROM_DATABASE=E2925A 32 Bit, 33 MHzPCI Exerciser & Analyzer pci:v0000103Cd00003206* ID_MODEL_FROM_DATABASE=Adaptec Embedded Serial ATA HostRAID pci:v0000103Cd00003220* ID_MODEL_FROM_DATABASE=Smart Array P600 pci:v0000103Cd00003220sv0000103Csd00003225* ID_MODEL_FROM_DATABASE=Smart Array P600 (3 Gb/s SAS RAID) pci:v0000103Cd00003230* ID_MODEL_FROM_DATABASE=Smart Array Controller pci:v0000103Cd00003230sv0000103Csd00003223* ID_MODEL_FROM_DATABASE=Smart Array Controller (Smart Array P800) pci:v0000103Cd00003230sv0000103Csd00003234* ID_MODEL_FROM_DATABASE=Smart Array Controller (P400 SAS Controller) pci:v0000103Cd00003230sv0000103Csd00003235* ID_MODEL_FROM_DATABASE=Smart Array Controller (P400i SAS Controller) pci:v0000103Cd00003230sv0000103Csd00003237* ID_MODEL_FROM_DATABASE=Smart Array Controller (E500 SAS Controller) pci:v0000103Cd00003230sv0000103Csd0000323D* ID_MODEL_FROM_DATABASE=Smart Array Controller (P700m SAS Controller) pci:v0000103Cd00003238* ID_MODEL_FROM_DATABASE=Smart Array E200i (SAS Controller) pci:v0000103Cd00003238sv0000103Csd00003211* ID_MODEL_FROM_DATABASE=Smart Array E200i (SAS Controller) (Smart Array E200i) pci:v0000103Cd00003238sv0000103Csd00003212* ID_MODEL_FROM_DATABASE=Smart Array E200i (SAS Controller) (Smart Array E200) pci:v0000103Cd00003239* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers pci:v0000103Cd00003239sv0000103Csd000021BD* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P244br) pci:v0000103Cd00003239sv0000103Csd000021BE* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P741m) pci:v0000103Cd00003239sv0000103Csd000021BF* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (H240ar) pci:v0000103Cd00003239sv0000103Csd000021C0* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P440ar) pci:v0000103Cd00003239sv0000103Csd000021C1* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P840ar) pci:v0000103Cd00003239sv0000103Csd000021C2* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P440) pci:v0000103Cd00003239sv0000103Csd000021C3* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P441) pci:v0000103Cd00003239sv0000103Csd000021C4* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (Smart Array) pci:v0000103Cd00003239sv0000103Csd000021C5* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P841) pci:v0000103Cd00003239sv0000103Csd000021C6* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (H244br) pci:v0000103Cd00003239sv0000103Csd000021C7* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (H240) pci:v0000103Cd00003239sv0000103Csd000021C8* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (H241) pci:v0000103Cd00003239sv0000103Csd000021C9* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (Smart Array) pci:v0000103Cd00003239sv0000103Csd000021CA* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P246br) pci:v0000103Cd00003239sv0000103Csd000021CB* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P840) pci:v0000103Cd00003239sv0000103Csd000021CC* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (Smart Array) pci:v0000103Cd00003239sv0000103Csd000021CD* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P240nr) pci:v0000103Cd00003239sv0000103Csd000021CE* ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (H240nr) pci:v0000103Cd0000323A* ID_MODEL_FROM_DATABASE=Smart Array G6 controllers pci:v0000103Cd0000323Asv0000103Csd00003241* ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array P212) pci:v0000103Cd0000323Asv0000103Csd00003243* ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array P410) pci:v0000103Cd0000323Asv0000103Csd00003245* ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array P410i) pci:v0000103Cd0000323Asv0000103Csd00003247* ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array P411) pci:v0000103Cd0000323Asv0000103Csd00003249* ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array P812) pci:v0000103Cd0000323Asv0000103Csd0000324A* ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array 712m (Mezzanine RAID controller)) pci:v0000103Cd0000323Asv0000103Csd0000324B* ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array P711m (Mezzanine RAID controller)) pci:v0000103Cd0000323B* ID_MODEL_FROM_DATABASE=Smart Array Gen8 Controllers pci:v0000103Cd0000323Bsv0000103Csd00003350* ID_MODEL_FROM_DATABASE=Smart Array Gen8 Controllers (P222) pci:v0000103Cd0000323Bsv0000103Csd00003351* ID_MODEL_FROM_DATABASE=Smart Array Gen8 Controllers (P420) pci:v0000103Cd0000323Bsv0000103Csd00003352* ID_MODEL_FROM_DATABASE=Smart Array Gen8 Controllers (P421) pci:v0000103Cd0000323Bsv0000103Csd00003354* ID_MODEL_FROM_DATABASE=Smart Array Gen8 Controllers (P420i) pci:v0000103Cd0000323Bsv0000103Csd00003355* ID_MODEL_FROM_DATABASE=Smart Array Gen8 Controllers (P220i) pci:v0000103Cd0000323C* ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers pci:v0000103Cd0000323Csv0000103Csd00001920* ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P430i) pci:v0000103Cd0000323Csv0000103Csd00001921* ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P830i) pci:v0000103Cd0000323Csv0000103Csd00001922* ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P430) pci:v0000103Cd0000323Csv0000103Csd00001923* ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P431) pci:v0000103Cd0000323Csv0000103Csd00001924* ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P830) pci:v0000103Cd0000323Csv0000103Csd00001925* ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (Smart Array) pci:v0000103Cd0000323Csv0000103Csd00001926* ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P731m) pci:v0000103Cd0000323Csv0000103Csd00001928* ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P230i) pci:v0000103Cd00003300* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Virtual USB Controller pci:v0000103Cd00003300sv0000103Csd00003304* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Virtual USB Controller (iLO2) pci:v0000103Cd00003300sv0000103Csd00003305* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Virtual USB Controller (iLO2) pci:v0000103Cd00003300sv0000103Csd00003309* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Virtual USB Controller (iLO2 GXL/iLO3 GXE) pci:v0000103Cd00003300sv0000103Csd0000330E* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Virtual USB Controller (iLO3) pci:v0000103Cd00003300sv0000103Csd00003381* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Virtual USB Controller (iLO4) pci:v0000103Cd00003301* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Serial Port pci:v0000103Cd00003301sv0000103Csd00003304* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Serial Port (iLO2) pci:v0000103Cd00003301sv0000103Csd00003305* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Serial Port (iLO2) pci:v0000103Cd00003301sv0000103Csd0000330E* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Serial Port (iLO3) pci:v0000103Cd00003301sv0000103Csd00003381* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Serial Port (iLO4) pci:v0000103Cd00003302* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard KCS Interface pci:v0000103Cd00003302sv0000103Csd00003304* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard KCS Interface (iLO2) pci:v0000103Cd00003302sv0000103Csd00003305* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard KCS Interface (iLO2) pci:v0000103Cd00003302sv0000103Csd0000330E* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard KCS Interface (iLO3) pci:v0000103Cd00003302sv0000103Csd00003381* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard KCS Interface (iLO4) pci:v0000103Cd00003305* ID_MODEL_FROM_DATABASE=Integrated Lights-Out (iLO2) Controller pci:v0000103Cd00003306* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Slave Instrumentation & System Support pci:v0000103Cd00003306sv0000103Csd0000330E* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Slave Instrumentation & System Support (iLO3) pci:v0000103Cd00003306sv0000103Csd00003381* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Slave Instrumentation & System Support (iLO4) pci:v0000103Cd00003307* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Management Processor Support and Messaging pci:v0000103Cd00003307sv0000103Csd00003309* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Management Processor Support and Messaging (iLO 2) pci:v0000103Cd00003307sv0000103Csd0000330E* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Management Processor Support and Messaging (iLO3) pci:v0000103Cd00003307sv0000103Csd00003381* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Management Processor Support and Messaging (iLO4) pci:v0000103Cd00003308* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard MS Watchdog Timer pci:v0000103Cd00003308sv0000103Csd0000330E* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard MS Watchdog Timer (iLO3) pci:v0000103Cd00003308sv0000103Csd00003381* ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard MS Watchdog Timer (iLO4) pci:v0000103Cd0000402F* ID_MODEL_FROM_DATABASE=PCIe Root Port pci:v0000103Cd00004030* ID_MODEL_FROM_DATABASE=zx2 System Bus Adapter pci:v0000103Cd00004031* ID_MODEL_FROM_DATABASE=zx2 I/O Controller pci:v0000103Cd00004037* ID_MODEL_FROM_DATABASE=PCIe Local Bus Adapter pci:v0000103Cd0000403B* ID_MODEL_FROM_DATABASE=PCIe Root Port pci:v0000103E* ID_VENDOR_FROM_DATABASE=Solliday Engineering pci:v0000103F* ID_VENDOR_FROM_DATABASE=Synopsys/Logic Modeling Group pci:v00001040* ID_VENDOR_FROM_DATABASE=Accelgraphics Inc. pci:v00001041* ID_VENDOR_FROM_DATABASE=Computrend pci:v00001042* ID_VENDOR_FROM_DATABASE=Micron pci:v00001042d00001000* ID_MODEL_FROM_DATABASE=PC Tech RZ1000 pci:v00001042d00001001* ID_MODEL_FROM_DATABASE=PC Tech RZ1001 pci:v00001042d00003000* ID_MODEL_FROM_DATABASE=Samurai_0 pci:v00001042d00003010* ID_MODEL_FROM_DATABASE=Samurai_1 pci:v00001042d00003020* ID_MODEL_FROM_DATABASE=Samurai_IDE pci:v00001043* ID_VENDOR_FROM_DATABASE=ASUSTeK Computer Inc. pci:v00001043d00000464* ID_MODEL_FROM_DATABASE=Radeon R9 270x GPU pci:v00001043d00000675* ID_MODEL_FROM_DATABASE=ISDNLink P-IN100-ST-D pci:v00001043d00000675sv00000675sd00001704* ID_MODEL_FROM_DATABASE=ISDNLink P-IN100-ST-D (ISDN Adapter (PCI Bus, D, C)) pci:v00001043d00000675sv00000675sd00001707* ID_MODEL_FROM_DATABASE=ISDNLink P-IN100-ST-D (ISDN Adapter (PCI Bus, DV, W)) pci:v00001043d00000675sv000010CFsd0000105E* ID_MODEL_FROM_DATABASE=ISDNLink P-IN100-ST-D (ISDN Adapter (PCI Bus, DV, W)) pci:v00001043d00009602* ID_MODEL_FROM_DATABASE=AMD RS780/RS880 PCI to PCI bridge (int gfx) pci:v00001043d00009602sv00001043sd000083A2* ID_MODEL_FROM_DATABASE=AMD RS780/RS880 PCI to PCI bridge (int gfx) (M4A785TD Motherboard) pci:v00001044* ID_VENDOR_FROM_DATABASE=Adaptec (formerly DPT) pci:v00001044d00001012* ID_MODEL_FROM_DATABASE=Domino RAID Engine pci:v00001044d0000A400* ID_MODEL_FROM_DATABASE=SmartCache/Raid I-IV Controller pci:v00001044d0000A500* ID_MODEL_FROM_DATABASE=PCI Bridge pci:v00001044d0000A501* ID_MODEL_FROM_DATABASE=SmartRAID V Controller pci:v00001044d0000A501sv00001044sd0000C001* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM1554U2 Ultra2 Single Channel) pci:v00001044d0000A501sv00001044sd0000C002* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM1654U2 Ultra2 Single Channel) pci:v00001044d0000A501sv00001044sd0000C003* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM1564U3 Ultra3 Single Channel) pci:v00001044d0000A501sv00001044sd0000C004* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM1564U3 Ultra3 Dual Channel) pci:v00001044d0000A501sv00001044sd0000C005* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM1554U2 Ultra2 Single Channel (NON ACPI)) pci:v00001044d0000A501sv00001044sd0000C00A* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2554U2 Ultra2 Single Channel) pci:v00001044d0000A501sv00001044sd0000C00B* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2654U2 Ultra2 Single Channel) pci:v00001044d0000A501sv00001044sd0000C00C* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2664U3 Ultra3 Single Channel) pci:v00001044d0000A501sv00001044sd0000C00D* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2664U3 Ultra3 Dual Channel) pci:v00001044d0000A501sv00001044sd0000C00E* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2554U2 Ultra2 Single Channel (NON ACPI)) pci:v00001044d0000A501sv00001044sd0000C00F* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2654U2 Ultra2 Single Channel (NON ACPI)) pci:v00001044d0000A501sv00001044sd0000C014* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3754U2 Ultra2 Single Channel (NON ACPI)) pci:v00001044d0000A501sv00001044sd0000C015* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3755U2B Ultra2 Single Channel (NON ACPI)) pci:v00001044d0000A501sv00001044sd0000C016* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3755F Fibre Channel (NON ACPI)) pci:v00001044d0000A501sv00001044sd0000C01E* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3757U2 Ultra2 Single Channel) pci:v00001044d0000A501sv00001044sd0000C01F* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3757U2 Ultra2 Dual Channel) pci:v00001044d0000A501sv00001044sd0000C020* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3767U3 Ultra3 Dual Channel) pci:v00001044d0000A501sv00001044sd0000C021* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3767U3 Ultra3 Quad Channel) pci:v00001044d0000A501sv00001044sd0000C028* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2865U3 Ultra3 Single Channel) pci:v00001044d0000A501sv00001044sd0000C029* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2865U3 Ultra3 Dual Channel) pci:v00001044d0000A501sv00001044sd0000C02A* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2865F Fibre Channel) pci:v00001044d0000A501sv00001044sd0000C03C* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (2000S Ultra3 Single Channel) pci:v00001044d0000A501sv00001044sd0000C03D* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (2000S Ultra3 Dual Channel) pci:v00001044d0000A501sv00001044sd0000C03E* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (2000F Fibre Channel) pci:v00001044d0000A501sv00001044sd0000C046* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (3000S Ultra3 Single Channel) pci:v00001044d0000A501sv00001044sd0000C047* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (3000S Ultra3 Dual Channel) pci:v00001044d0000A501sv00001044sd0000C048* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (3000F Fibre Channel) pci:v00001044d0000A501sv00001044sd0000C050* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (5000S Ultra3 Single Channel) pci:v00001044d0000A501sv00001044sd0000C051* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (5000S Ultra3 Dual Channel) pci:v00001044d0000A501sv00001044sd0000C052* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (5000F Fibre Channel) pci:v00001044d0000A501sv00001044sd0000C05A* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (2400A UDMA Four Channel) pci:v00001044d0000A501sv00001044sd0000C05B* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (2400A UDMA Four Channel DAC) pci:v00001044d0000A501sv00001044sd0000C064* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (3010S Ultra3 Dual Channel) pci:v00001044d0000A501sv00001044sd0000C065* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (3410S Ultra160 Four Channel) pci:v00001044d0000A501sv00001044sd0000C066* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (3010S Fibre Channel) pci:v00001044d0000A511* ID_MODEL_FROM_DATABASE=SmartRAID V Controller pci:v00001044d0000A511sv00001044sd0000C032* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (ASR-2005S I2O Zero Channel) pci:v00001044d0000A511sv00001044sd0000C035* ID_MODEL_FROM_DATABASE=SmartRAID V Controller (ASR-2010S I2O Zero Channel) pci:v00001044d0000C066* ID_MODEL_FROM_DATABASE=3010S Ultra3 Dual Channel pci:v00001045* ID_VENDOR_FROM_DATABASE=OPTi Inc. pci:v00001045d0000A0F8* ID_MODEL_FROM_DATABASE=82C750 [Vendetta] USB Controller pci:v00001045d0000C101* ID_MODEL_FROM_DATABASE=92C264 pci:v00001045d0000C178* ID_MODEL_FROM_DATABASE=92C178 pci:v00001045d0000C556* ID_MODEL_FROM_DATABASE=82X556 [Viper] pci:v00001045d0000C557* ID_MODEL_FROM_DATABASE=82C557 [Viper-M] pci:v00001045d0000C558* ID_MODEL_FROM_DATABASE=82C558 [Viper-M ISA+IDE] pci:v00001045d0000C567* ID_MODEL_FROM_DATABASE=82C750 [Vendetta], device 0 pci:v00001045d0000C568* ID_MODEL_FROM_DATABASE=82C750 [Vendetta], device 1 pci:v00001045d0000C569* ID_MODEL_FROM_DATABASE=82C579 [Viper XPress+ Chipset] pci:v00001045d0000C621* ID_MODEL_FROM_DATABASE=82C621 [Viper-M/N+] pci:v00001045d0000C700* ID_MODEL_FROM_DATABASE=82C700 [FireStar] pci:v00001045d0000C701* ID_MODEL_FROM_DATABASE=82C701 [FireStar Plus] pci:v00001045d0000C814* ID_MODEL_FROM_DATABASE=82C814 [Firebridge 1] pci:v00001045d0000C822* ID_MODEL_FROM_DATABASE=82C822 pci:v00001045d0000C824* ID_MODEL_FROM_DATABASE=82C824 pci:v00001045d0000C825* ID_MODEL_FROM_DATABASE=82C825 [Firebridge 2] pci:v00001045d0000C832* ID_MODEL_FROM_DATABASE=82C832 pci:v00001045d0000C861* ID_MODEL_FROM_DATABASE=82C861 pci:v00001045d0000C881* ID_MODEL_FROM_DATABASE=82C881 [FireLink] 1394 OHCI Link Controller pci:v00001045d0000C895* ID_MODEL_FROM_DATABASE=82C895 pci:v00001045d0000C935* ID_MODEL_FROM_DATABASE=EV1935 ECTIVA MachOne PCIAudio pci:v00001045d0000D568* ID_MODEL_FROM_DATABASE=82C825 [Firebridge 2] pci:v00001045d0000D721* ID_MODEL_FROM_DATABASE=IDE [FireStar] pci:v00001046* ID_VENDOR_FROM_DATABASE=IPC Corporation, Ltd. pci:v00001047* ID_VENDOR_FROM_DATABASE=Genoa Systems Corp pci:v00001048* ID_VENDOR_FROM_DATABASE=Elsa AG pci:v00001048d00000C60* ID_MODEL_FROM_DATABASE=Gladiac MX pci:v00001048d00000D22* ID_MODEL_FROM_DATABASE=Quadro4 900XGL [ELSA GLoria4 900XGL] pci:v00001048d00001000* ID_MODEL_FROM_DATABASE=QuickStep 1000 pci:v00001048d00003000* ID_MODEL_FROM_DATABASE=QuickStep 3000 pci:v00001048d00008901* ID_MODEL_FROM_DATABASE=Gloria XL pci:v00001048d00008901sv00001048sd00000935* ID_MODEL_FROM_DATABASE=Gloria XL (GLoria XL (Virge)) pci:v00001049* ID_VENDOR_FROM_DATABASE=Fountain Technologies, Inc. pci:v0000104A* ID_VENDOR_FROM_DATABASE=STMicroelectronics pci:v0000104Ad00000000* ID_MODEL_FROM_DATABASE=STLS2F Host Bridge pci:v0000104Ad00000008* ID_MODEL_FROM_DATABASE=STG 2000X pci:v0000104Ad00000009* ID_MODEL_FROM_DATABASE=STG 1764X pci:v0000104Ad00000010* ID_MODEL_FROM_DATABASE=STG4000 [3D Prophet Kyro Series] pci:v0000104Ad00000010sv0000104Asd00004018* ID_MODEL_FROM_DATABASE=STG4000 [3D Prophet Kyro Series] (ST PowerVR Kyro (64MB AGP TVO)) pci:v0000104Ad00000010sv00001681sd00000010* ID_MODEL_FROM_DATABASE=STG4000 [3D Prophet Kyro Series] (PowerVR Kyro II [3D Prophet 4500]) pci:v0000104Ad00000010sv00001681sd00000028* ID_MODEL_FROM_DATABASE=STG4000 [3D Prophet Kyro Series] (3D Prophet 4000XT) pci:v0000104Ad00000010sv00001681sd0000C010* ID_MODEL_FROM_DATABASE=STG4000 [3D Prophet Kyro Series] (3D Prophet 4500 TV-Out) pci:v0000104Ad00000010sv00001681sd0000C069* ID_MODEL_FROM_DATABASE=STG4000 [3D Prophet Kyro Series] (3D Prophet 4000XT) pci:v0000104Ad00000201* ID_MODEL_FROM_DATABASE=STPC Vega Northbridge pci:v0000104Ad00000209* ID_MODEL_FROM_DATABASE=STPC Consumer/Industrial North- and Southbridge pci:v0000104Ad0000020A* ID_MODEL_FROM_DATABASE=STPC Atlas/ConsumerS/Consumer IIA Northbridge pci:v0000104Ad0000020B* ID_MODEL_FROM_DATABASE=STPC Consumer II ISA Bridge pci:v0000104Ad00000210* ID_MODEL_FROM_DATABASE=STPC Atlas ISA Bridge pci:v0000104Ad0000021A* ID_MODEL_FROM_DATABASE=STPC Consumer S Southbridge pci:v0000104Ad0000021B* ID_MODEL_FROM_DATABASE=STPC Consumer IIA Southbridge pci:v0000104Ad00000220* ID_MODEL_FROM_DATABASE=STPC Industrial PCI to PCCard bridge pci:v0000104Ad00000228* ID_MODEL_FROM_DATABASE=STPC Atlas IDE pci:v0000104Ad00000229* ID_MODEL_FROM_DATABASE=STPC Vega IDE pci:v0000104Ad00000230* ID_MODEL_FROM_DATABASE=STPC Atlas/Vega OHCI USB Controller pci:v0000104Ad00000238* ID_MODEL_FROM_DATABASE=STPC Vega LAN pci:v0000104Ad00000500* ID_MODEL_FROM_DATABASE=ST70137 [Unicorn] ADSL DMT Transceiver pci:v0000104Ad00000500sv0000104Asd00000500* ID_MODEL_FROM_DATABASE=ST70137 [Unicorn] ADSL DMT Transceiver (BeWAN ADSL PCI st) pci:v0000104Ad00000564* ID_MODEL_FROM_DATABASE=STPC Client Northbridge pci:v0000104Ad00000981* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet pci:v0000104Ad00001746* ID_MODEL_FROM_DATABASE=STG 1764X pci:v0000104Ad00002774* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet pci:v0000104Ad00003520* ID_MODEL_FROM_DATABASE=MPEG-II decoder card pci:v0000104Ad000055CC* ID_MODEL_FROM_DATABASE=STPC Client Southbridge pci:v0000104B* ID_VENDOR_FROM_DATABASE=BusLogic pci:v0000104Bd00000140* ID_MODEL_FROM_DATABASE=BT-946C (old) [multimaster 01] pci:v0000104Bd00001040* ID_MODEL_FROM_DATABASE=BT-946C (BA80C30) [MultiMaster 10] pci:v0000104Bd00008130* ID_MODEL_FROM_DATABASE=Flashpoint LT pci:v0000104C* ID_VENDOR_FROM_DATABASE=Texas Instruments pci:v0000104Cd00000500* ID_MODEL_FROM_DATABASE=100 MBit LAN Controller pci:v0000104Cd00000508* ID_MODEL_FROM_DATABASE=TMS380C2X Compressor Interface pci:v0000104Cd00001000* ID_MODEL_FROM_DATABASE=Eagle i/f AS pci:v0000104Cd0000104C* ID_MODEL_FROM_DATABASE=PCI1510 PC card Cardbus Controller pci:v0000104Cd00003D04* ID_MODEL_FROM_DATABASE=TVP4010 [Permedia] pci:v0000104Cd00003D07* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] pci:v0000104Cd00003D07sv00001011sd00004D10* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (Comet) pci:v0000104Cd00003D07sv00001040sd0000000F* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (AccelStar II) pci:v0000104Cd00003D07sv00001040sd00000011* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (AccelStar II) pci:v0000104Cd00003D07sv00001048sd00000A31* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (WINNER 2000) pci:v0000104Cd00003D07sv00001048sd00000A32* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (GLoria Synergy) pci:v0000104Cd00003D07sv00001048sd00000A34* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (GLoria Synergy) pci:v0000104Cd00003D07sv00001048sd00000A35* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (GLoria Synergy) pci:v0000104Cd00003D07sv00001048sd00000A36* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (GLoria Synergy) pci:v0000104Cd00003D07sv00001048sd00000A43* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (GLoria Synergy) pci:v0000104Cd00003D07sv00001048sd00000A44* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (GLoria Synergy) pci:v0000104Cd00003D07sv0000107Dsd00002633* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (WinFast 3D L2300) pci:v0000104Cd00003D07sv00001092sd00000126* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) pci:v0000104Cd00003D07sv00001092sd00000127* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) pci:v0000104Cd00003D07sv00001092sd00000136* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) pci:v0000104Cd00003D07sv00001092sd00000141* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) pci:v0000104Cd00003D07sv00001092sd00000146* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) pci:v0000104Cd00003D07sv00001092sd00000148* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) pci:v0000104Cd00003D07sv00001092sd00000149* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) pci:v0000104Cd00003D07sv00001092sd00000152* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) pci:v0000104Cd00003D07sv00001092sd00000154* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) pci:v0000104Cd00003D07sv00001092sd00000155* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) pci:v0000104Cd00003D07sv00001092sd00000156* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) pci:v0000104Cd00003D07sv00001092sd00000157* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) pci:v0000104Cd00003D07sv00001097sd00003D01* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (Jeronimo Pro) pci:v0000104Cd00003D07sv00001102sd0000100F* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (Graphics Blaster Extreme) pci:v0000104Cd00003D07sv00003D3Dsd00000100* ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (Reference Permedia 2 3D) pci:v0000104Cd00008000* ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller pci:v0000104Cd00008000sv0000105Esd00008003* ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (FireBoard200) pci:v0000104Cd00008000sv00001443sd00008003* ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (FireBoard200) pci:v0000104Cd00008000sv00001443sd00008005* ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (FireBoard400) pci:v0000104Cd00008000sv00001443sd00008006* ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (FireBoard400) pci:v0000104Cd00008000sv0000E4BFsd00001010* ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (CF1-1-SNARE) pci:v0000104Cd00008000sv0000E4BFsd00001020* ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (CF1-2-SNARE) pci:v0000104Cd00008000sv0000E4BFsd00001040* ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (FireCompact400) pci:v0000104Cd00008009* ID_MODEL_FROM_DATABASE=TSB12LV22 IEEE-1394 Controller pci:v0000104Cd00008009sv0000104Dsd00008032* ID_MODEL_FROM_DATABASE=TSB12LV22 IEEE-1394 Controller (8032 OHCI i.LINK (IEEE 1394) Controller) pci:v0000104Cd00008009sv00001443sd00008010* ID_MODEL_FROM_DATABASE=TSB12LV22 IEEE-1394 Controller (FireBoard400-OHCI) pci:v0000104Cd00008017* ID_MODEL_FROM_DATABASE=PCI4410 FireWire Controller pci:v0000104Cd00008019* ID_MODEL_FROM_DATABASE=TSB12LV23 IEEE-1394 Controller pci:v0000104Cd00008019sv000011BDsd0000000A* ID_MODEL_FROM_DATABASE=TSB12LV23 IEEE-1394 Controller (Studio DV500-1394) pci:v0000104Cd00008019sv000011BDsd0000000E* ID_MODEL_FROM_DATABASE=TSB12LV23 IEEE-1394 Controller (Studio DV) pci:v0000104Cd00008019sv00001443sd00008010* ID_MODEL_FROM_DATABASE=TSB12LV23 IEEE-1394 Controller (FireBoard400-OHCI) pci:v0000104Cd00008019sv0000E4BFsd00001010* ID_MODEL_FROM_DATABASE=TSB12LV23 IEEE-1394 Controller (CF2-1-CYMBAL) pci:v0000104Cd00008020* ID_MODEL_FROM_DATABASE=TSB12LV26 IEEE-1394 Controller (Link) pci:v0000104Cd00008020sv00001028sd000000D8* ID_MODEL_FROM_DATABASE=TSB12LV26 IEEE-1394 Controller (Link) (Precision 530) pci:v0000104Cd00008020sv0000104Dsd000080E2* ID_MODEL_FROM_DATABASE=TSB12LV26 IEEE-1394 Controller (Link) (VAIO PCV-J200) pci:v0000104Cd00008020sv000011BDsd0000000F* ID_MODEL_FROM_DATABASE=TSB12LV26 IEEE-1394 Controller (Link) (Studio DV500-1394) pci:v0000104Cd00008020sv000011BDsd0000001C* ID_MODEL_FROM_DATABASE=TSB12LV26 IEEE-1394 Controller (Link) (Excalibur 4.1) pci:v0000104Cd00008020sv00001443sd00008010* ID_MODEL_FROM_DATABASE=TSB12LV26 IEEE-1394 Controller (Link) (FireBoard400-OHCI) pci:v0000104Cd00008021* ID_MODEL_FROM_DATABASE=TSB43AA22 IEEE-1394 Controller (PHY/Link Integrated) pci:v0000104Cd00008021sv0000104Dsd000080DF* ID_MODEL_FROM_DATABASE=TSB43AA22 IEEE-1394 Controller (PHY/Link Integrated) (Vaio PCG-FX403) pci:v0000104Cd00008021sv0000104Dsd000080E7* ID_MODEL_FROM_DATABASE=TSB43AA22 IEEE-1394 Controller (PHY/Link Integrated) (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) pci:v0000104Cd00008022* ID_MODEL_FROM_DATABASE=TSB43AB22 IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] pci:v0000104Cd00008022sv0000104Csd00008023* ID_MODEL_FROM_DATABASE=TSB43AB22 IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (TSB43AB22/A IEEE-1394a-2000 Controller (PHY/Link)) pci:v0000104Cd00008023* ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] pci:v0000104Cd00008023sv00001028sd00000168* ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (Precision Workstation 670 Mainboard) pci:v0000104Cd00008023sv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (NC8000 laptop) pci:v0000104Cd00008023sv00001043sd0000808B* ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (K8N4/A8N Series Mainboard) pci:v0000104Cd00008023sv00001043sd0000815B* ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (P5W DH Deluxe Motherboard) pci:v0000104Cd00008023sv00001443sd00008023* ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (FireCard400) pci:v0000104Cd00008023sv00008086sd00005044* ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (Desktop Board DP35DP) pci:v0000104Cd00008024* ID_MODEL_FROM_DATABASE=TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link) pci:v0000104Cd00008024sv0000107Dsd00006620* ID_MODEL_FROM_DATABASE=TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link) (Winfast DV2000 FireWire Controller) pci:v0000104Cd00008024sv00001443sd00008024* ID_MODEL_FROM_DATABASE=TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link) (FireBoard Blue) pci:v0000104Cd00008024sv00001458sd00001000* ID_MODEL_FROM_DATABASE=TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link) (Motherboard) pci:v0000104Cd00008025* ID_MODEL_FROM_DATABASE=TSB82AA2 IEEE-1394b Link Layer Controller pci:v0000104Cd00008025sv00001043sd0000813C* ID_MODEL_FROM_DATABASE=TSB82AA2 IEEE-1394b Link Layer Controller (P5P series mainboard) pci:v0000104Cd00008025sv00001443sd00008025* ID_MODEL_FROM_DATABASE=TSB82AA2 IEEE-1394b Link Layer Controller (FireBoard800) pci:v0000104Cd00008025sv00001458sd00001000* ID_MODEL_FROM_DATABASE=TSB82AA2 IEEE-1394b Link Layer Controller (GA-K8N Ultra-9 Mainboard) pci:v0000104Cd00008025sv00001546sd00008025* ID_MODEL_FROM_DATABASE=TSB82AA2 IEEE-1394b Link Layer Controller (FWB-PCI01) pci:v0000104Cd00008025sv000017FCsd00008025* ID_MODEL_FROM_DATABASE=TSB82AA2 IEEE-1394b Link Layer Controller (GIC3800) pci:v0000104Cd00008026* ID_MODEL_FROM_DATABASE=TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) pci:v0000104Cd00008026sv00001025sd00000035* ID_MODEL_FROM_DATABASE=TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) (TravelMate 660) pci:v0000104Cd00008026sv00001025sd0000003C* ID_MODEL_FROM_DATABASE=TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) (Aspire 2001WLCi (Compaq CL50 motherboard)) pci:v0000104Cd00008026sv0000103Csd00000025* ID_MODEL_FROM_DATABASE=TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) (XE4500 Notebook) pci:v0000104Cd00008026sv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) (NX9500) pci:v0000104Cd00008026sv00001043sd0000808D* ID_MODEL_FROM_DATABASE=TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) (A7V333 mainboard.) pci:v0000104Cd00008027* ID_MODEL_FROM_DATABASE=PCI4451 IEEE-1394 Controller pci:v0000104Cd00008027sv00001028sd000000E5* ID_MODEL_FROM_DATABASE=PCI4451 IEEE-1394 Controller (Latitude C810) pci:v0000104Cd00008027sv00001028sd000000E6* ID_MODEL_FROM_DATABASE=PCI4451 IEEE-1394 Controller ((Dell Inspiron 8100)) pci:v0000104Cd00008029* ID_MODEL_FROM_DATABASE=PCI4510 IEEE-1394 Controller pci:v0000104Cd00008029sv00001028sd00000163* ID_MODEL_FROM_DATABASE=PCI4510 IEEE-1394 Controller (Latitude D505) pci:v0000104Cd00008029sv00001028sd00000196* ID_MODEL_FROM_DATABASE=PCI4510 IEEE-1394 Controller (Inspiron 5160) pci:v0000104Cd00008029sv00001071sd00008160* ID_MODEL_FROM_DATABASE=PCI4510 IEEE-1394 Controller (MIM2900) pci:v0000104Cd0000802B* ID_MODEL_FROM_DATABASE=PCI7410,7510,7610 OHCI-Lynx Controller pci:v0000104Cd0000802Bsv00001028sd00000139* ID_MODEL_FROM_DATABASE=PCI7410,7510,7610 OHCI-Lynx Controller (Latitude D400) pci:v0000104Cd0000802Bsv00001028sd0000014E* ID_MODEL_FROM_DATABASE=PCI7410,7510,7610 OHCI-Lynx Controller ((Latitude D800)) pci:v0000104Cd0000802E* ID_MODEL_FROM_DATABASE=PCI7x20 1394a-2000 OHCI Two-Port PHY/Link-Layer Controller pci:v0000104Cd0000802Esv00001028sd0000018D* ID_MODEL_FROM_DATABASE=PCI7x20 1394a-2000 OHCI Two-Port PHY/Link-Layer Controller (Inspiron 700m/710m) pci:v0000104Cd00008031* ID_MODEL_FROM_DATABASE=PCIxx21/x515 Cardbus Controller pci:v0000104Cd00008031sv00001025sd00000064* ID_MODEL_FROM_DATABASE=PCIxx21/x515 Cardbus Controller (Extensa 3000 series laptop) pci:v0000104Cd00008031sv00001025sd00000080* ID_MODEL_FROM_DATABASE=PCIxx21/x515 Cardbus Controller (Aspire 5024WLMi) pci:v0000104Cd00008031sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=PCIxx21/x515 Cardbus Controller (Compaq nw8240/nx8220) pci:v0000104Cd00008031sv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=PCIxx21/x515 Cardbus Controller (NX6110/NC6120) pci:v0000104Cd00008031sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=PCIxx21/x515 Cardbus Controller (MX6125) pci:v0000104Cd00008032* ID_MODEL_FROM_DATABASE=OHCI Compliant IEEE 1394 Host Controller pci:v0000104Cd00008032sv00001025sd00000064* ID_MODEL_FROM_DATABASE=OHCI Compliant IEEE 1394 Host Controller (Extensa 3000 series laptop) pci:v0000104Cd00008032sv00001025sd00000080* ID_MODEL_FROM_DATABASE=OHCI Compliant IEEE 1394 Host Controller (Aspire 5024WLMi) pci:v0000104Cd00008032sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=OHCI Compliant IEEE 1394 Host Controller (Compaq nw8240/nx8220) pci:v0000104Cd00008032sv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=OHCI Compliant IEEE 1394 Host Controller (NX6110/NC6120) pci:v0000104Cd00008032sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=OHCI Compliant IEEE 1394 Host Controller (MX6125) pci:v0000104Cd00008033* ID_MODEL_FROM_DATABASE=PCIxx21 Integrated FlashMedia Controller pci:v0000104Cd00008033sv00001025sd00000064* ID_MODEL_FROM_DATABASE=PCIxx21 Integrated FlashMedia Controller (Extensa 3000 series laptop) pci:v0000104Cd00008033sv00001025sd00000080* ID_MODEL_FROM_DATABASE=PCIxx21 Integrated FlashMedia Controller (Aspire 5024WLMi) pci:v0000104Cd00008033sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=PCIxx21 Integrated FlashMedia Controller (Compaq nw8240/nx8220) pci:v0000104Cd00008033sv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=PCIxx21 Integrated FlashMedia Controller (NX6110/NC6120) pci:v0000104Cd00008033sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=PCIxx21 Integrated FlashMedia Controller (MX6125) pci:v0000104Cd00008034* ID_MODEL_FROM_DATABASE=PCI6411/6421/6611/6621/7411/7421/7611/7621 Secure Digital Controller pci:v0000104Cd00008034sv00001025sd00000080* ID_MODEL_FROM_DATABASE=PCI6411/6421/6611/6621/7411/7421/7611/7621 Secure Digital Controller (Aspire 5024WLMi) pci:v0000104Cd00008034sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=PCI6411/6421/6611/6621/7411/7421/7611/7621 Secure Digital Controller (Compaq nw8240/nx8220) pci:v0000104Cd00008034sv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=PCI6411/6421/6611/6621/7411/7421/7611/7621 Secure Digital Controller (NX6110/NC6120) pci:v0000104Cd00008034sv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=PCI6411/6421/6611/6621/7411/7421/7611/7621 Secure Digital Controller (MX6125) pci:v0000104Cd00008035* ID_MODEL_FROM_DATABASE=PCI6411/6421/6611/6621/7411/7421/7611/7621 Smart Card Controller pci:v0000104Cd00008035sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=PCI6411/6421/6611/6621/7411/7421/7611/7621 Smart Card Controller (Compaq nw8240/nx8220) pci:v0000104Cd00008035sv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=PCI6411/6421/6611/6621/7411/7421/7611/7621 Smart Card Controller (NX6110/NC6120) pci:v0000104Cd00008036* ID_MODEL_FROM_DATABASE=PCI6515 Cardbus Controller pci:v0000104Cd00008038* ID_MODEL_FROM_DATABASE=PCI6515 SmartCard Controller pci:v0000104Cd00008039* ID_MODEL_FROM_DATABASE=PCIxx12 Cardbus Controller pci:v0000104Cd00008039sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=PCIxx12 Cardbus Controller (Compaq nx9420 Notebook) pci:v0000104Cd00008039sv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=PCIxx12 Cardbus Controller (NC2400) pci:v0000104Cd00008039sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=PCIxx12 Cardbus Controller (Compaq nw8440) pci:v0000104Cd00008039sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=PCIxx12 Cardbus Controller (VAIO VGN-NR120E) pci:v0000104Cd0000803A* ID_MODEL_FROM_DATABASE=PCIxx12 OHCI Compliant IEEE 1394 Host Controller pci:v0000104Cd0000803Asv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=PCIxx12 OHCI Compliant IEEE 1394 Host Controller (nx9420) pci:v0000104Cd0000803Asv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=PCIxx12 OHCI Compliant IEEE 1394 Host Controller (NC2400) pci:v0000104Cd0000803Asv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=PCIxx12 OHCI Compliant IEEE 1394 Host Controller (Compaq nw8440) pci:v0000104Cd0000803Asv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=PCIxx12 OHCI Compliant IEEE 1394 Host Controller (VAIO VGN-NR120E) pci:v0000104Cd0000803B* ID_MODEL_FROM_DATABASE=5-in-1 Multimedia Card Reader (SD/MMC/MS/MS PRO/xD) pci:v0000104Cd0000803Bsv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=5-in-1 Multimedia Card Reader (SD/MMC/MS/MS PRO/xD) (nx9420) pci:v0000104Cd0000803Bsv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=5-in-1 Multimedia Card Reader (SD/MMC/MS/MS PRO/xD) (Compaq nw8440) pci:v0000104Cd0000803Bsv0000104Dsd00008212* ID_MODEL_FROM_DATABASE=5-in-1 Multimedia Card Reader (SD/MMC/MS/MS PRO/xD) (VAIO VGN-N21E) pci:v0000104Cd0000803Bsv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=5-in-1 Multimedia Card Reader (SD/MMC/MS/MS PRO/xD) (VAIO VGN-NR120E) pci:v0000104Cd0000803C* ID_MODEL_FROM_DATABASE=PCIxx12 SDA Standard Compliant SD Host Controller pci:v0000104Cd0000803Csv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=PCIxx12 SDA Standard Compliant SD Host Controller (nx9420) pci:v0000104Cd0000803Csv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=PCIxx12 SDA Standard Compliant SD Host Controller (Compaq nw8440) pci:v0000104Cd0000803D* ID_MODEL_FROM_DATABASE=PCIxx12 GemCore based SmartCard controller pci:v0000104Cd0000803Dsv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=PCIxx12 GemCore based SmartCard controller (Compaq nx9420 Notebook) pci:v0000104Cd0000803Dsv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=PCIxx12 GemCore based SmartCard controller (NC2400) pci:v0000104Cd0000803Dsv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=PCIxx12 GemCore based SmartCard controller (nc8430) pci:v0000104Cd0000803Dsv0000103Csd000030AA* ID_MODEL_FROM_DATABASE=PCIxx12 GemCore based SmartCard controller (nc6310) pci:v0000104Cd00008101* ID_MODEL_FROM_DATABASE=TSB43DB42 IEEE-1394a-2000 Controller (PHY/Link) pci:v0000104Cd00008201* ID_MODEL_FROM_DATABASE=PCI1620 Firmware Loading Function pci:v0000104Cd00008204* ID_MODEL_FROM_DATABASE=PCI7410/7510/7610 PCI Firmware Loading Function pci:v0000104Cd00008204sv00001028sd00000139* ID_MODEL_FROM_DATABASE=PCI7410/7510/7610 PCI Firmware Loading Function (Latitude D400) pci:v0000104Cd00008204sv00001028sd0000014E* ID_MODEL_FROM_DATABASE=PCI7410/7510/7610 PCI Firmware Loading Function (Latitude D800) pci:v0000104Cd00008231* ID_MODEL_FROM_DATABASE=XIO2000(A)/XIO2200A PCI Express-to-PCI Bridge pci:v0000104Cd00008231sv00005678sd00001234* ID_MODEL_FROM_DATABASE=XIO2000(A)/XIO2200A PCI Express-to-PCI Bridge (DC-1394 PCIe) pci:v0000104Cd00008232* ID_MODEL_FROM_DATABASE=XIO3130 PCI Express Switch (Upstream) pci:v0000104Cd00008233* ID_MODEL_FROM_DATABASE=XIO3130 PCI Express Switch (Downstream) pci:v0000104Cd00008235* ID_MODEL_FROM_DATABASE=XIO2200A IEEE-1394a-2000 Controller (PHY/Link) pci:v0000104Cd00008235sv00005678sd00001234* ID_MODEL_FROM_DATABASE=XIO2200A IEEE-1394a-2000 Controller (PHY/Link) (DC-1394 PCIe) pci:v0000104Cd0000823E* ID_MODEL_FROM_DATABASE=XIO2213A/B/XIO2221 PCI Express to PCI Bridge [Cheetah Express] pci:v0000104Cd0000823F* ID_MODEL_FROM_DATABASE=XIO2213A/B/XIO2221 IEEE-1394b OHCI Controller [Cheetah Express] pci:v0000104Cd0000823Fsv00001546sd0000803C* ID_MODEL_FROM_DATABASE=XIO2213A/B/XIO2221 IEEE-1394b OHCI Controller [Cheetah Express] (FWB-PCIE1X11B) pci:v0000104Cd00008240* ID_MODEL_FROM_DATABASE=XIO2001 PCI Express-to-PCI Bridge pci:v0000104Cd00008241* ID_MODEL_FROM_DATABASE=TUSB73x0 SuperSpeed USB 3.0 xHCI Host Controller pci:v0000104Cd00008400* ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface pci:v0000104Cd00008400sv00001186sd00003B00* ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface (DWL-650+ PC Card cardbus 22Mbs Wireless Adapter [AirPlus]) pci:v0000104Cd00008400sv00001186sd00003B01* ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface (DWL-520+ 22Mbps PCI Wireless Adapter) pci:v0000104Cd00008400sv00001395sd00002201* ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface (WL22-PC) pci:v0000104Cd00008400sv000016ABsd00008501* ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface (WL-8305 IEEE802.11b+ Wireless LAN PCI Adapter) pci:v0000104Cd00008401* ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface pci:v0000104Cd00008888* ID_MODEL_FROM_DATABASE=Multicore DSP+ARM KeyStone II SOC pci:v0000104Cd00009000* ID_MODEL_FROM_DATABASE=Wireless Interface (of unknown type) pci:v0000104Cd00009065* ID_MODEL_FROM_DATABASE=TMS320DM642 pci:v0000104Cd00009066* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface pci:v0000104Cd00009066sv00000308sd00003404* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (G-102 v1 802.11g Wireless Cardbus Adapter) pci:v0000104Cd00009066sv00000308sd00003406* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (G-162 v2 802.11g Wireless Cardbus Adapter) pci:v0000104Cd00009066sv0000104Csd00009066* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (WL212 Sitecom Wireless Network PCI-Card 100M (Version 1)) pci:v0000104Cd00009066sv0000104Csd00009067* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (TNETW1130GVF) pci:v0000104Cd00009066sv0000104Csd00009096* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (Trendnet TEW-412PC Wireless PCI Adapter (Version A)) pci:v0000104Cd00009066sv00001186sd00003B04* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (DWL-G520+ Wireless PCI Adapter) pci:v0000104Cd00009066sv00001186sd00003B05* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (DWL-G650+ AirPlusG+ CardBus Wireless LAN) pci:v0000104Cd00009066sv00001186sd00003B08* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.B1)) pci:v0000104Cd00009066sv00001385sd00004C00* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (WG311v2 802.11g Wireless PCI Adapter) pci:v0000104Cd00009066sv000013D1sd0000ABA0* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (SWLMP-54108 108Mbps Wireless mini PCI card 802.11g+) pci:v0000104Cd00009066sv000014EAsd0000AB07* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (GW-NS54GM Wireless Cardbus Adapter) pci:v0000104Cd00009066sv000016ECsd0000010D* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (USR5416 802.11g Wireless Turbo PCI Adapter) pci:v0000104Cd00009066sv000016ECsd0000010E* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (USR5410 802.11g Wireless Cardbus Adapter) pci:v0000104Cd00009066sv00001737sd00000033* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (WPC54G v2 802.11g Wireless-G Notebook Adapter) pci:v0000104Cd00009066sv000017CFsd00000032* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (G-162 v1 802.11g Wireless Cardbus Adapter) pci:v0000104Cd00009066sv000017CFsd00000033* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (Z-Com XG650 Wireless miniPCI 802.11b/g) pci:v0000104Cd00009066sv0000187Esd0000340B* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (G-302 v2 802.11g Wireless PCI Adapter) pci:v0000104Cd00009066sv0000187Esd0000340C* ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (G-360 v2 802.11g Wireless PCI Adapter) pci:v0000104Cd0000A001* ID_MODEL_FROM_DATABASE=TDC1570 pci:v0000104Cd0000A100* ID_MODEL_FROM_DATABASE=TDC1561 pci:v0000104Cd0000A102* ID_MODEL_FROM_DATABASE=TNETA1575 HyperSAR Plus w/PCI Host i/f & UTOPIA i/f pci:v0000104Cd0000A106* ID_MODEL_FROM_DATABASE=TMS320C6414 TMS320C6415 TMS320C6416 pci:v0000104Cd0000A106sv0000175Csd00005000* ID_MODEL_FROM_DATABASE=TMS320C6414 TMS320C6415 TMS320C6416 (ASI50xx Audio Adapter) pci:v0000104Cd0000A106sv0000175Csd00006400* ID_MODEL_FROM_DATABASE=TMS320C6414 TMS320C6415 TMS320C6416 (ASI6400 Cobranet series) pci:v0000104Cd0000A106sv0000175Csd00008700* ID_MODEL_FROM_DATABASE=TMS320C6414 TMS320C6415 TMS320C6416 (ASI87xx Radio Tuner card) pci:v0000104Cd0000AC10* ID_MODEL_FROM_DATABASE=PCI1050 pci:v0000104Cd0000AC11* ID_MODEL_FROM_DATABASE=PCI1053 pci:v0000104Cd0000AC12* ID_MODEL_FROM_DATABASE=PCI1130 pci:v0000104Cd0000AC13* ID_MODEL_FROM_DATABASE=PCI1031 pci:v0000104Cd0000AC15* ID_MODEL_FROM_DATABASE=PCI1131 pci:v0000104Cd0000AC16* ID_MODEL_FROM_DATABASE=PCI1250 pci:v0000104Cd0000AC16sv00001014sd00000092* ID_MODEL_FROM_DATABASE=PCI1250 (ThinkPad 600) pci:v0000104Cd0000AC17* ID_MODEL_FROM_DATABASE=PCI1220 pci:v0000104Cd0000AC18* ID_MODEL_FROM_DATABASE=PCI1260 pci:v0000104Cd0000AC19* ID_MODEL_FROM_DATABASE=PCI1221 pci:v0000104Cd0000AC1A* ID_MODEL_FROM_DATABASE=PCI1210 pci:v0000104Cd0000AC1B* ID_MODEL_FROM_DATABASE=PCI1450 pci:v0000104Cd0000AC1Bsv00000E11sd0000B113* ID_MODEL_FROM_DATABASE=PCI1450 (Armada M700) pci:v0000104Cd0000AC1Bsv00001014sd00000130* ID_MODEL_FROM_DATABASE=PCI1450 (ThinkPad 600X/A21m/T20/T22) pci:v0000104Cd0000AC1C* ID_MODEL_FROM_DATABASE=PCI1225 pci:v0000104Cd0000AC1Csv00000E11sd0000B121* ID_MODEL_FROM_DATABASE=PCI1225 (Armada E500) pci:v0000104Cd0000AC1Csv00001028sd00000088* ID_MODEL_FROM_DATABASE=PCI1225 (Latitude CPi A400XT) pci:v0000104Cd0000AC1D* ID_MODEL_FROM_DATABASE=PCI1251A pci:v0000104Cd0000AC1E* ID_MODEL_FROM_DATABASE=PCI1211 pci:v0000104Cd0000AC1F* ID_MODEL_FROM_DATABASE=PCI1251B pci:v0000104Cd0000AC20* ID_MODEL_FROM_DATABASE=TI 2030 pci:v0000104Cd0000AC21* ID_MODEL_FROM_DATABASE=PCI2031 pci:v0000104Cd0000AC22* ID_MODEL_FROM_DATABASE=PCI2032 PCI Docking Bridge pci:v0000104Cd0000AC23* ID_MODEL_FROM_DATABASE=PCI2250 PCI-to-PCI Bridge pci:v0000104Cd0000AC28* ID_MODEL_FROM_DATABASE=PCI2050 PCI-to-PCI Bridge pci:v0000104Cd0000AC2C* ID_MODEL_FROM_DATABASE=PCI2060 PCI-to-PCI Bridge pci:v0000104Cd0000AC30* ID_MODEL_FROM_DATABASE=PCI1260 PC card Cardbus Controller pci:v0000104Cd0000AC40* ID_MODEL_FROM_DATABASE=PCI4450 PC card Cardbus Controller pci:v0000104Cd0000AC41* ID_MODEL_FROM_DATABASE=PCI4410 PC card Cardbus Controller pci:v0000104Cd0000AC42* ID_MODEL_FROM_DATABASE=PCI4451 PC card Cardbus Controller pci:v0000104Cd0000AC42sv00001028sd000000E6* ID_MODEL_FROM_DATABASE=PCI4451 PC card Cardbus Controller (PCI4451 PC card CardBus Controller (Inspiron 8100)) pci:v0000104Cd0000AC44* ID_MODEL_FROM_DATABASE=PCI4510 PC card Cardbus Controller pci:v0000104Cd0000AC44sv00001028sd00000149* ID_MODEL_FROM_DATABASE=PCI4510 PC card Cardbus Controller (Inspiron 5100) pci:v0000104Cd0000AC44sv00001028sd00000163* ID_MODEL_FROM_DATABASE=PCI4510 PC card Cardbus Controller (Latitude D505) pci:v0000104Cd0000AC44sv00001028sd00000196* ID_MODEL_FROM_DATABASE=PCI4510 PC card Cardbus Controller (Inspiron 5160) pci:v0000104Cd0000AC44sv00001071sd00008160* ID_MODEL_FROM_DATABASE=PCI4510 PC card Cardbus Controller (MIM2000) pci:v0000104Cd0000AC46* ID_MODEL_FROM_DATABASE=PCI4520 PC card Cardbus Controller pci:v0000104Cd0000AC46sv00001014sd00000552* ID_MODEL_FROM_DATABASE=PCI4520 PC card Cardbus Controller (ThinkPad) pci:v0000104Cd0000AC47* ID_MODEL_FROM_DATABASE=PCI7510 PC card Cardbus Controller pci:v0000104Cd0000AC47sv00001028sd00000139* ID_MODEL_FROM_DATABASE=PCI7510 PC card Cardbus Controller (Latitude D400) pci:v0000104Cd0000AC47sv00001028sd0000013F* ID_MODEL_FROM_DATABASE=PCI7510 PC card Cardbus Controller (Precision M60) pci:v0000104Cd0000AC47sv00001028sd0000014E* ID_MODEL_FROM_DATABASE=PCI7510 PC card Cardbus Controller (Latitude D800) pci:v0000104Cd0000AC48* ID_MODEL_FROM_DATABASE=PCI7610 PC Card Cardbus Controller pci:v0000104Cd0000AC49* ID_MODEL_FROM_DATABASE=PCI7410 PC Card Cardbus Controller pci:v0000104Cd0000AC4A* ID_MODEL_FROM_DATABASE=PCI7510/7610 CardBus Bridge pci:v0000104Cd0000AC4Asv00001028sd00000139* ID_MODEL_FROM_DATABASE=PCI7510/7610 CardBus Bridge (Latitude D400) pci:v0000104Cd0000AC4Asv00001028sd0000014E* ID_MODEL_FROM_DATABASE=PCI7510/7610 CardBus Bridge (Latitude D800) pci:v0000104Cd0000AC4B* ID_MODEL_FROM_DATABASE=PCI7610 SD/MMC controller pci:v0000104Cd0000AC4C* ID_MODEL_FROM_DATABASE=PCI7610 Memory Stick controller pci:v0000104Cd0000AC50* ID_MODEL_FROM_DATABASE=PCI1410 PC card Cardbus Controller pci:v0000104Cd0000AC51* ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller pci:v0000104Cd0000AC51sv00000E11sd0000004E* ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (Evo N600c) pci:v0000104Cd0000AC51sv00001014sd00000148* ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (ThinkPad A20m) pci:v0000104Cd0000AC51sv00001014sd0000023B* ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (ThinkPad T23) pci:v0000104Cd0000AC51sv00001028sd000000B1* ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (Latitude C600) pci:v0000104Cd0000AC51sv00001028sd0000012A* ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (Latitude C640) pci:v0000104Cd0000AC51sv00001033sd000080CD* ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (Versa Note VXi) pci:v0000104Cd0000AC51sv000010CFsd00001095* ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (Lifebook S-4510/C6155) pci:v0000104Cd0000AC51sv0000E4BFsd00001000* ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (CP2-2-HIPHOP) pci:v0000104Cd0000AC52* ID_MODEL_FROM_DATABASE=PCI1451 PC card Cardbus Controller pci:v0000104Cd0000AC53* ID_MODEL_FROM_DATABASE=PCI1421 PC card Cardbus Controller pci:v0000104Cd0000AC54* ID_MODEL_FROM_DATABASE=PCI1620 PC Card Controller pci:v0000104Cd0000AC54sv0000103Csd000008B0* ID_MODEL_FROM_DATABASE=PCI1620 PC Card Controller (tc1100 tablet) pci:v0000104Cd0000AC55* ID_MODEL_FROM_DATABASE=PCI1520 PC card Cardbus Controller pci:v0000104Cd0000AC55sv00001014sd00000512* ID_MODEL_FROM_DATABASE=PCI1520 PC card Cardbus Controller (ThinkPad T30/T40) pci:v0000104Cd0000AC55sv0000103Csd00000025* ID_MODEL_FROM_DATABASE=PCI1520 PC card Cardbus Controller (XE4500 Notebook) pci:v0000104Cd0000AC56* ID_MODEL_FROM_DATABASE=PCI1510 PC card Cardbus Controller pci:v0000104Cd0000AC56sv00001014sd00000512* ID_MODEL_FROM_DATABASE=PCI1510 PC card Cardbus Controller (ThinkPad R50e) pci:v0000104Cd0000AC56sv00001014sd00000528* ID_MODEL_FROM_DATABASE=PCI1510 PC card Cardbus Controller (ThinkPad R40e) pci:v0000104Cd0000AC56sv000017AAsd00002012* ID_MODEL_FROM_DATABASE=PCI1510 PC card Cardbus Controller (ThinkPad T60/R60 series) pci:v0000104Cd0000AC60* ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller pci:v0000104Cd0000AC60sv0000175Csd00005100* ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (ASI51xx Audio Adapter) pci:v0000104Cd0000AC60sv0000175Csd00006100* ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (ASI61xx Audio Adapter) pci:v0000104Cd0000AC60sv0000175Csd00006200* ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (ASI62xx Audio Adapter) pci:v0000104Cd0000AC60sv0000175Csd00008800* ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (ASI88xx Audio Adapter) pci:v0000104Cd0000AC60sv0000186Fsd00003001* ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (WR-G303 PCI radio receiver) pci:v0000104Cd0000AC60sv0000186Fsd00003005* ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (WR-G305 PCI radio receiver) pci:v0000104Cd0000AC60sv0000186Fsd00003101* ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (WR-G313 PCI radio receiver) pci:v0000104Cd0000AC60sv0000186Fsd00003105* ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (WR-G315 PCI radio receiver) pci:v0000104Cd0000AC8D* ID_MODEL_FROM_DATABASE=PCI 7620 pci:v0000104Cd0000AC8E* ID_MODEL_FROM_DATABASE=PCI7420 CardBus Controller pci:v0000104Cd0000AC8Esv00001028sd0000018D* ID_MODEL_FROM_DATABASE=PCI7420 CardBus Controller (Inspiron 700m/710m) pci:v0000104Cd0000AC8F* ID_MODEL_FROM_DATABASE=PCI7420/7620 SD/MS-Pro Controller pci:v0000104Cd0000AC8Fsv00001028sd0000018D* ID_MODEL_FROM_DATABASE=PCI7420/7620 SD/MS-Pro Controller (Inspiron 700m/710m) pci:v0000104Cd0000B001* ID_MODEL_FROM_DATABASE=TMS320C6424 pci:v0000104Cd0000FE00* ID_MODEL_FROM_DATABASE=FireWire Host Controller pci:v0000104Cd0000FE03* ID_MODEL_FROM_DATABASE=12C01A FireWire Host Controller pci:v0000104D* ID_VENDOR_FROM_DATABASE=Sony Corporation pci:v0000104Dd00008004* ID_MODEL_FROM_DATABASE=DTL-H2500 [Playstation development board] pci:v0000104Dd00008009* ID_MODEL_FROM_DATABASE=CXD1947Q i.LINK Controller pci:v0000104Dd00008039* ID_MODEL_FROM_DATABASE=CXD3222 i.LINK Controller pci:v0000104Dd00008056* ID_MODEL_FROM_DATABASE=Rockwell HCF 56K modem pci:v0000104Dd0000808A* ID_MODEL_FROM_DATABASE=Memory Stick Controller pci:v0000104Dd000081CE* ID_MODEL_FROM_DATABASE=SxS Pro memory card pci:v0000104Dd0000908F* ID_MODEL_FROM_DATABASE=Aeolia ACPI pci:v0000104Dd0000909E* ID_MODEL_FROM_DATABASE=Aeolia Ethernet Controller (Marvell Yukon 2 Family) pci:v0000104Dd0000909F* ID_MODEL_FROM_DATABASE=Aeolia SATA AHCI Controller pci:v0000104Dd000090A0* ID_MODEL_FROM_DATABASE=Aeolia SD/MMC Host Controller pci:v0000104Dd000090A1* ID_MODEL_FROM_DATABASE=Aeolia PCI Express Glue and Miscellaneous Devices pci:v0000104Dd000090A2* ID_MODEL_FROM_DATABASE=Aeolia DMA Controller pci:v0000104Dd000090A3* ID_MODEL_FROM_DATABASE=Aeolia Memory (DDR3/SPM) pci:v0000104Dd000090A4* ID_MODEL_FROM_DATABASE=Aeolia USB 3.0 xHCI Host Controller pci:v0000104E* ID_VENDOR_FROM_DATABASE=Oak Technology, Inc pci:v0000104Ed00000017* ID_MODEL_FROM_DATABASE=OTI-64017 pci:v0000104Ed00000107* ID_MODEL_FROM_DATABASE=OTI-107 [Spitfire] pci:v0000104Ed00000109* ID_MODEL_FROM_DATABASE=Video Adapter pci:v0000104Ed00000111* ID_MODEL_FROM_DATABASE=OTI-64111 [Spitfire] pci:v0000104Ed00000217* ID_MODEL_FROM_DATABASE=OTI-64217 pci:v0000104Ed00000317* ID_MODEL_FROM_DATABASE=OTI-64317 pci:v0000104F* ID_VENDOR_FROM_DATABASE=Co-time Computer Ltd pci:v00001050* ID_VENDOR_FROM_DATABASE=Winbond Electronics Corp pci:v00001050d00000000* ID_MODEL_FROM_DATABASE=NE2000 pci:v00001050d00000001* ID_MODEL_FROM_DATABASE=W83769F pci:v00001050d00000033* ID_MODEL_FROM_DATABASE=W89C33D 802.11 a/b/g BB/MAC pci:v00001050d00000105* ID_MODEL_FROM_DATABASE=W82C105 pci:v00001050d00000840* ID_MODEL_FROM_DATABASE=W89C840 pci:v00001050d00000840sv00001050sd00000001* ID_MODEL_FROM_DATABASE=W89C840 (Ethernet Adapter) pci:v00001050d00000840sv00001050sd00000840* ID_MODEL_FROM_DATABASE=W89C840 (Ethernet Adapter) pci:v00001050d00000940* ID_MODEL_FROM_DATABASE=W89C940 pci:v00001050d00005A5A* ID_MODEL_FROM_DATABASE=W89C940F pci:v00001050d00006692* ID_MODEL_FROM_DATABASE=W6692 pci:v00001050d00006692sv00001043sd00001702* ID_MODEL_FROM_DATABASE=W6692 (ISDN Adapter (PCI Bus, D, W)) pci:v00001050d00006692sv00001043sd00001703* ID_MODEL_FROM_DATABASE=W6692 (ISDN Adapter (PCI Bus, DV, W)) pci:v00001050d00006692sv00001043sd00001707* ID_MODEL_FROM_DATABASE=W6692 (ISDN Adapter (PCI Bus, DV, W)) pci:v00001050d00006692sv0000144Fsd00001702* ID_MODEL_FROM_DATABASE=W6692 (ISDN Adapter (PCI Bus, D, W)) pci:v00001050d00006692sv0000144Fsd00001703* ID_MODEL_FROM_DATABASE=W6692 (ISDN Adapter (PCI Bus, DV, W)) pci:v00001050d00006692sv0000144Fsd00001707* ID_MODEL_FROM_DATABASE=W6692 (ISDN Adapter (PCI Bus, DV, W)) pci:v00001050d00009921* ID_MODEL_FROM_DATABASE=W99200F MPEG-1 Video Encoder pci:v00001050d00009922* ID_MODEL_FROM_DATABASE=W99200F/W9922PF MPEG-1/2 Video Encoder pci:v00001050d00009970* ID_MODEL_FROM_DATABASE=W9970CF pci:v00001051* ID_VENDOR_FROM_DATABASE=Anigma, Inc. pci:v00001052* ID_VENDOR_FROM_DATABASE=?Young Micro Systems pci:v00001053* ID_VENDOR_FROM_DATABASE=Young Micro Systems pci:v00001054* ID_VENDOR_FROM_DATABASE=Hitachi, Ltd pci:v00001054d00003009* ID_MODEL_FROM_DATABASE=2Gbps Fibre Channel to PCI HBA 3009 pci:v00001054d0000300A* ID_MODEL_FROM_DATABASE=4Gbps Fibre Channel to PCI-X HBA 300a pci:v00001054d0000300B* ID_MODEL_FROM_DATABASE=4Gbps Fibre Channel to PCI-X HBA 300b pci:v00001054d0000300F* ID_MODEL_FROM_DATABASE=ColdFusion 3 Chipset Processor to I/O Controller pci:v00001054d00003010* ID_MODEL_FROM_DATABASE=ColdFusion 3 Chipset Memory Controller Hub pci:v00001054d00003011* ID_MODEL_FROM_DATABASE=ColdFusion 3e Chipset Processor to I/O Controller pci:v00001054d00003012* ID_MODEL_FROM_DATABASE=ColdFusion 3e Chipset Memory Controller Hub pci:v00001054d00003017* ID_MODEL_FROM_DATABASE=Unassigned Hitachi Shared FC Device 3017 pci:v00001054d0000301B* ID_MODEL_FROM_DATABASE=Virtual VGA Device pci:v00001054d0000301D* ID_MODEL_FROM_DATABASE=PCIe-to-PCIe Bridge with Virtualization IO Assist Feature pci:v00001054d00003020* ID_MODEL_FROM_DATABASE=FIVE-EX based Fibre Channel to PCIe HBA pci:v00001054d0000302C* ID_MODEL_FROM_DATABASE=M001 PCI Express Switch Upstream Port pci:v00001054d0000302D* ID_MODEL_FROM_DATABASE=M001 PCI Express Switch Downstream Port pci:v00001054d00003070* ID_MODEL_FROM_DATABASE=Hitachi FIVE-FX Fibre Channel to PCIe HBA pci:v00001054d00003505* ID_MODEL_FROM_DATABASE=SH7751 PCI Controller (PCIC) pci:v00001054d0000350E* ID_MODEL_FROM_DATABASE=SH7751R PCI Controller (PCIC) pci:v00001055* ID_VENDOR_FROM_DATABASE=Efar Microsystems pci:v00001055d00009130* ID_MODEL_FROM_DATABASE=SLC90E66 [Victory66] IDE pci:v00001055d00009460* ID_MODEL_FROM_DATABASE=SLC90E66 [Victory66] ISA pci:v00001055d00009462* ID_MODEL_FROM_DATABASE=SLC90E66 [Victory66] USB pci:v00001055d00009463* ID_MODEL_FROM_DATABASE=SLC90E66 [Victory66] ACPI pci:v00001055d0000E420* ID_MODEL_FROM_DATABASE=LAN9420/LAN9420i pci:v00001056* ID_VENDOR_FROM_DATABASE=ICL pci:v00001057* ID_VENDOR_FROM_DATABASE=Motorola pci:v00001057d00000001* ID_MODEL_FROM_DATABASE=MPC105 [Eagle] pci:v00001057d00000002* ID_MODEL_FROM_DATABASE=MPC106 [Grackle] pci:v00001057d00000003* ID_MODEL_FROM_DATABASE=MPC8240 [Kahlua] pci:v00001057d00000004* ID_MODEL_FROM_DATABASE=MPC107 pci:v00001057d00000006* ID_MODEL_FROM_DATABASE=MPC8245 [Unity] pci:v00001057d00000008* ID_MODEL_FROM_DATABASE=MPC8540 pci:v00001057d00000009* ID_MODEL_FROM_DATABASE=MPC8560 pci:v00001057d00000012* ID_MODEL_FROM_DATABASE=MPC8548 [PowerQUICC III] pci:v00001057d00000100* ID_MODEL_FROM_DATABASE=MC145575 [HFC-PCI] pci:v00001057d00000431* ID_MODEL_FROM_DATABASE=KTI829c 100VG pci:v00001057d00001073* ID_MODEL_FROM_DATABASE=Nokia N770 pci:v00001057d00001219* ID_MODEL_FROM_DATABASE=Nokia N800 pci:v00001057d00001801* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor pci:v00001057d00001801sv000014FBsd00000101* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Transas Radar Imitator Board [RIM]) pci:v00001057d00001801sv000014FBsd00000102* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Transas Radar Imitator Board [RIM-2]) pci:v00001057d00001801sv000014FBsd00000202* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Transas Radar Integrator Board [RIB-2]) pci:v00001057d00001801sv000014FBsd00000611* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (1 channel CAN bus Controller [CanPci-1]) pci:v00001057d00001801sv000014FBsd00000612* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (2 channels CAN bus Controller [CanPci-2]) pci:v00001057d00001801sv000014FBsd00000613* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (3 channels CAN bus Controller [CanPci-3]) pci:v00001057d00001801sv000014FBsd00000614* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (4 channels CAN bus Controller [CanPci-4]) pci:v00001057d00001801sv000014FBsd00000621* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (1 channel CAN bus Controller [CanPci2-1]) pci:v00001057d00001801sv000014FBsd00000622* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (2 channels CAN bus Controller [CanPci2-2]) pci:v00001057d00001801sv000014FBsd00000810* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Transas VTS Radar Integrator Board [RIB-4]) pci:v00001057d00001801sv0000175Csd00004200* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (ASI4215 Audio Adapter) pci:v00001057d00001801sv0000175Csd00004300* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (ASI43xx Audio Adapter) pci:v00001057d00001801sv0000175Csd00004400* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (ASI4401 Audio Adapter) pci:v00001057d00001801sv0000ECC0sd00000010* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Darla) pci:v00001057d00001801sv0000ECC0sd00000020* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Gina) pci:v00001057d00001801sv0000ECC0sd00000030* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Layla rev.0) pci:v00001057d00001801sv0000ECC0sd00000031* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Layla rev.1) pci:v00001057d00001801sv0000ECC0sd00000040* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Darla24 rev.0) pci:v00001057d00001801sv0000ECC0sd00000041* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Darla24 rev.1) pci:v00001057d00001801sv0000ECC0sd00000050* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Gina24 rev.0) pci:v00001057d00001801sv0000ECC0sd00000051* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Gina24 rev.1) pci:v00001057d00001801sv0000ECC0sd00000070* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Mona rev.0) pci:v00001057d00001801sv0000ECC0sd00000071* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Mona rev.1) pci:v00001057d00001801sv0000ECC0sd00000072* ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Mona rev.2) pci:v00001057d000018C0* ID_MODEL_FROM_DATABASE=MPC8265A/8266/8272 pci:v00001057d000018C1* ID_MODEL_FROM_DATABASE=MPC8271/MPC8272 pci:v00001057d00003052* ID_MODEL_FROM_DATABASE=SM56 Data Fax Modem pci:v00001057d00003410* ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor pci:v00001057d00003410sv0000ECC0sd00000050* ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Gina24 rev.0) pci:v00001057d00003410sv0000ECC0sd00000051* ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Gina24 rev.1) pci:v00001057d00003410sv0000ECC0sd00000060* ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Layla24) pci:v00001057d00003410sv0000ECC0sd00000070* ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Mona rev.0) pci:v00001057d00003410sv0000ECC0sd00000071* ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Mona rev.1) pci:v00001057d00003410sv0000ECC0sd00000072* ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Mona rev.2) pci:v00001057d00003410sv0000ECC0sd00000080* ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Mia rev.0) pci:v00001057d00003410sv0000ECC0sd00000081* ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Mia rev.1) pci:v00001057d00003410sv0000ECC0sd00000090* ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Indigo) pci:v00001057d00003410sv0000ECC0sd000000A0* ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Indigo IO) pci:v00001057d00003410sv0000ECC0sd000000B0* ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Indigo DJ) pci:v00001057d00003410sv0000ECC0sd00000100* ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (3G) pci:v00001057d00004801* ID_MODEL_FROM_DATABASE=Raven pci:v00001057d00004802* ID_MODEL_FROM_DATABASE=Falcon pci:v00001057d00004803* ID_MODEL_FROM_DATABASE=Hawk pci:v00001057d00004806* ID_MODEL_FROM_DATABASE=CPX8216 pci:v00001057d00004D68* ID_MODEL_FROM_DATABASE=20268 pci:v00001057d00005600* ID_MODEL_FROM_DATABASE=SM56 PCI Modem pci:v00001057d00005600sv00001057sd00000300* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Speakerphone Modem) pci:v00001057d00005600sv00001057sd00000301* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Voice Modem) pci:v00001057d00005600sv00001057sd00000302* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Fax Modem) pci:v00001057d00005600sv00001057sd00005600* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Voice modem) pci:v00001057d00005600sv000013D2sd00000300* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Speakerphone Modem) pci:v00001057d00005600sv000013D2sd00000301* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Voice modem) pci:v00001057d00005600sv000013D2sd00000302* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Fax Modem) pci:v00001057d00005600sv00001436sd00000300* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Speakerphone Modem) pci:v00001057d00005600sv00001436sd00000301* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Voice modem) pci:v00001057d00005600sv00001436sd00000302* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Fax Modem) pci:v00001057d00005600sv0000144Fsd0000100C* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Fax Modem) pci:v00001057d00005600sv00001494sd00000300* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Speakerphone Modem) pci:v00001057d00005600sv00001494sd00000301* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Voice modem) pci:v00001057d00005600sv000014C8sd00000300* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Speakerphone Modem) pci:v00001057d00005600sv000014C8sd00000302* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Fax Modem) pci:v00001057d00005600sv00001668sd00000300* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Speakerphone Modem) pci:v00001057d00005600sv00001668sd00000302* ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Fax Modem) pci:v00001057d00005608* ID_MODEL_FROM_DATABASE=Wildcard X100P pci:v00001057d00005803* ID_MODEL_FROM_DATABASE=MPC5200 pci:v00001057d00005806* ID_MODEL_FROM_DATABASE=MCF54 Coldfire pci:v00001057d00005808* ID_MODEL_FROM_DATABASE=MPC8220 pci:v00001057d00005809* ID_MODEL_FROM_DATABASE=MPC5200B pci:v00001057d00006400* ID_MODEL_FROM_DATABASE=MPC190 Security Processor (S1 family, encryption) pci:v00001057d00006405* ID_MODEL_FROM_DATABASE=MPC184 Security Processor (S1 family) pci:v00001058* ID_VENDOR_FROM_DATABASE=Electronics & Telecommunications RSH pci:v00001059* ID_VENDOR_FROM_DATABASE=Kontron pci:v0000105A* ID_VENDOR_FROM_DATABASE=Promise Technology, Inc. pci:v0000105Ad00000D30* ID_MODEL_FROM_DATABASE=PDC20265 (FastTrak100 Lite/Ultra100) pci:v0000105Ad00000D30sv00001043sd00008042* ID_MODEL_FROM_DATABASE=PDC20265 (FastTrak100 Lite/Ultra100) (AV7266-E South Bridge Promise RAID) pci:v0000105Ad00000D30sv0000105Asd00004D33* ID_MODEL_FROM_DATABASE=PDC20265 (FastTrak100 Lite/Ultra100) (Ultra100) pci:v0000105Ad00000D38* ID_MODEL_FROM_DATABASE=20263 pci:v0000105Ad00000D38sv0000105Asd00004D39* ID_MODEL_FROM_DATABASE=20263 (Fasttrak66) pci:v0000105Ad00001275* ID_MODEL_FROM_DATABASE=20275 pci:v0000105Ad00003318* ID_MODEL_FROM_DATABASE=PDC20318 (SATA150 TX4) pci:v0000105Ad00003319* ID_MODEL_FROM_DATABASE=PDC20319 (FastTrak S150 TX4) pci:v0000105Ad00003319sv0000105Asd00003319* ID_MODEL_FROM_DATABASE=PDC20319 (FastTrak S150 TX4) (FastTrak S150 TX4 4 port SATA PCI board) pci:v0000105Ad00003319sv00008086sd00003427* ID_MODEL_FROM_DATABASE=PDC20319 (FastTrak S150 TX4) (S875WP1-E mainboard) pci:v0000105Ad00003371* ID_MODEL_FROM_DATABASE=PDC20371 (FastTrak S150 TX2plus) pci:v0000105Ad00003373* ID_MODEL_FROM_DATABASE=PDC20378 (FastTrak 378/SATA 378) pci:v0000105Ad00003373sv00001043sd000080F5* ID_MODEL_FROM_DATABASE=PDC20378 (FastTrak 378/SATA 378) (K8V Deluxe/PC-DL Deluxe motherboard) pci:v0000105Ad00003373sv00001462sd0000590D* ID_MODEL_FROM_DATABASE=PDC20378 (FastTrak 378/SATA 378) (KT6 Delta-FIS2R (MS-6590)) pci:v0000105Ad00003373sv00001462sd0000702E* ID_MODEL_FROM_DATABASE=PDC20378 (FastTrak 378/SATA 378) (K8T NEO FIS2R motherboard) pci:v0000105Ad00003375* ID_MODEL_FROM_DATABASE=PDC20375 (SATA150 TX2plus) pci:v0000105Ad00003376* ID_MODEL_FROM_DATABASE=PDC20376 (FastTrak 376) pci:v0000105Ad00003376sv00001043sd0000809E* ID_MODEL_FROM_DATABASE=PDC20376 (FastTrak 376) (A7V8X motherboard) pci:v0000105Ad00003515* ID_MODEL_FROM_DATABASE=PDC40719 [FastTrak TX4300/TX4310] pci:v0000105Ad00003519* ID_MODEL_FROM_DATABASE=PDC40519 (FastTrak TX4200) pci:v0000105Ad00003570* ID_MODEL_FROM_DATABASE=PDC20771 [FastTrak TX2300] pci:v0000105Ad00003571* ID_MODEL_FROM_DATABASE=PDC20571 (FastTrak TX2200) pci:v0000105Ad00003574* ID_MODEL_FROM_DATABASE=PDC20579 SATAII 150 IDE Controller pci:v0000105Ad00003577* ID_MODEL_FROM_DATABASE=PDC40779 (SATA 300 779) pci:v0000105Ad00003D17* ID_MODEL_FROM_DATABASE=PDC40718 (SATA 300 TX4) pci:v0000105Ad00003D18* ID_MODEL_FROM_DATABASE=PDC20518/PDC40518 (SATAII 150 TX4) pci:v0000105Ad00003D73* ID_MODEL_FROM_DATABASE=PDC40775 (SATA 300 TX2plus) pci:v0000105Ad00003D75* ID_MODEL_FROM_DATABASE=PDC20575 (SATAII150 TX2plus) pci:v0000105Ad00003F20* ID_MODEL_FROM_DATABASE=PDC42819 [FastTrak TX2650/TX4650] pci:v0000105Ad00004302* ID_MODEL_FROM_DATABASE=80333 [SuperTrak EX4350] pci:v0000105Ad00004D30* ID_MODEL_FROM_DATABASE=PDC20267 (FastTrak100/Ultra100) pci:v0000105Ad00004D30sv0000105Asd00004D33* ID_MODEL_FROM_DATABASE=PDC20267 (FastTrak100/Ultra100) (Ultra100) pci:v0000105Ad00004D30sv0000105Asd00004D39* ID_MODEL_FROM_DATABASE=PDC20267 (FastTrak100/Ultra100) (FastTrak100) pci:v0000105Ad00004D30sv00008086sd00005744* ID_MODEL_FROM_DATABASE=PDC20267 (FastTrak100/Ultra100) (S845WD1-E mainboard) pci:v0000105Ad00004D33* ID_MODEL_FROM_DATABASE=20246 pci:v0000105Ad00004D33sv0000105Asd00004D33* ID_MODEL_FROM_DATABASE=20246 (IDE Controller) pci:v0000105Ad00004D38* ID_MODEL_FROM_DATABASE=PDC20262 (FastTrak66/Ultra66) pci:v0000105Ad00004D38sv0000105Asd00004D30* ID_MODEL_FROM_DATABASE=PDC20262 (FastTrak66/Ultra66) (Ultra Device on SuperTrak) pci:v0000105Ad00004D38sv0000105Asd00004D33* ID_MODEL_FROM_DATABASE=PDC20262 (FastTrak66/Ultra66) (Ultra66) pci:v0000105Ad00004D38sv0000105Asd00004D39* ID_MODEL_FROM_DATABASE=PDC20262 (FastTrak66/Ultra66) (FastTrak66) pci:v0000105Ad00004D68* ID_MODEL_FROM_DATABASE=PDC20268 [Ultra100 TX2] pci:v0000105Ad00004D68sv0000105Asd00004D68* ID_MODEL_FROM_DATABASE=PDC20268 [Ultra100 TX2] (Ultra100 TX2) pci:v0000105Ad00004D69* ID_MODEL_FROM_DATABASE=20269 pci:v0000105Ad00004D69sv0000105Asd00004D68* ID_MODEL_FROM_DATABASE=20269 (Ultra133TX2) pci:v0000105Ad00005275* ID_MODEL_FROM_DATABASE=PDC20276 (MBFastTrak133 Lite) pci:v0000105Ad00005275sv00001043sd0000807E* ID_MODEL_FROM_DATABASE=PDC20276 (MBFastTrak133 Lite) (A7V333 motherboard.) pci:v0000105Ad00005275sv0000105Asd00000275* ID_MODEL_FROM_DATABASE=PDC20276 (MBFastTrak133 Lite) (SuperTrak SX6000 IDE) pci:v0000105Ad00005275sv0000105Asd00001275* ID_MODEL_FROM_DATABASE=PDC20276 (MBFastTrak133 Lite) (MBFastTrak133 Lite (tm) Controller (RAID mode)) pci:v0000105Ad00005275sv00001458sd0000B001* ID_MODEL_FROM_DATABASE=PDC20276 (MBFastTrak133 Lite) (MBUltra 133) pci:v0000105Ad00005300* ID_MODEL_FROM_DATABASE=DC5300 pci:v0000105Ad00006268* ID_MODEL_FROM_DATABASE=PDC20270 (FastTrak100 LP/TX2/TX4) pci:v0000105Ad00006268sv0000105Asd00004D68* ID_MODEL_FROM_DATABASE=PDC20270 (FastTrak100 LP/TX2/TX4) (FastTrak100 TX2) pci:v0000105Ad00006269* ID_MODEL_FROM_DATABASE=PDC20271 (FastTrak TX2000) pci:v0000105Ad00006269sv0000105Asd00006269* ID_MODEL_FROM_DATABASE=PDC20271 (FastTrak TX2000) (FastTrak TX2/TX2000) pci:v0000105Ad00006300* ID_MODEL_FROM_DATABASE=PDC81731 [FastTrak SX8300] pci:v0000105Ad00006621* ID_MODEL_FROM_DATABASE=PDC20621 (FastTrak S150 SX4/FastTrak SX4000 lite) pci:v0000105Ad00006622* ID_MODEL_FROM_DATABASE=PDC20621 [SATA150 SX4] 4 Channel IDE RAID Controller pci:v0000105Ad00006624* ID_MODEL_FROM_DATABASE=PDC20621 [FastTrak SX4100] pci:v0000105Ad00006626* ID_MODEL_FROM_DATABASE=PDC20618 (Ultra 618) pci:v0000105Ad00006629* ID_MODEL_FROM_DATABASE=PDC20619 (FastTrak TX4000) pci:v0000105Ad00007275* ID_MODEL_FROM_DATABASE=PDC20277 (SBFastTrak133 Lite) pci:v0000105Ad00008002* ID_MODEL_FROM_DATABASE=SATAII150 SX8 pci:v0000105Ad00008350* ID_MODEL_FROM_DATABASE=80333 [SuperTrak EX8350/EX16350], 80331 [SuperTrak EX8300/EX16300] pci:v0000105Ad00008650* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] pci:v0000105Ad00008650sv0000105Asd00004600* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX4650A) pci:v0000105Ad00008650sv0000105Asd00004601* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX4650) pci:v0000105Ad00008650sv0000105Asd00004610* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX4650EL) pci:v0000105Ad00008650sv0000105Asd00008600* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX8650EL) pci:v0000105Ad00008650sv0000105Asd00008601* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX8650A) pci:v0000105Ad00008650sv0000105Asd00008602* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX8654) pci:v0000105Ad00008650sv0000105Asd00008603* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX8658) pci:v0000105Ad00008650sv0000105Asd00008604* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX8650) pci:v0000105Ad00008650sv0000105Asd00008610* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX8650M) pci:v0000105Ad00008650sv0000105Asd0000A600* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX12650) pci:v0000105Ad00008650sv0000105Asd0000B600* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX16650) pci:v0000105Ad00008650sv0000105Asd0000B601* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX16654) pci:v0000105Ad00008650sv0000105Asd0000B602* ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX16658) pci:v0000105Ad00008760* ID_MODEL_FROM_DATABASE=PM8010 [SuperTrak EX SAS and SATA 6G RAID Controller] pci:v0000105Ad0000C350* ID_MODEL_FROM_DATABASE=80333 [SuperTrak EX12350] pci:v0000105Ad0000E350* ID_MODEL_FROM_DATABASE=80333 [SuperTrak EX24350] pci:v0000105B* ID_VENDOR_FROM_DATABASE=Foxconn International, Inc. pci:v0000105C* ID_VENDOR_FROM_DATABASE=Wipro Infotech Limited pci:v0000105D* ID_VENDOR_FROM_DATABASE=Number 9 Computer Company pci:v0000105Dd00002309* ID_MODEL_FROM_DATABASE=Imagine 128 pci:v0000105Dd00002339* ID_MODEL_FROM_DATABASE=Imagine 128-II pci:v0000105Dd00002339sv0000105Dsd00000000* ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) pci:v0000105Dd00002339sv0000105Dsd00000001* ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) pci:v0000105Dd00002339sv0000105Dsd00000002* ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) pci:v0000105Dd00002339sv0000105Dsd00000003* ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) pci:v0000105Dd00002339sv0000105Dsd00000004* ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) pci:v0000105Dd00002339sv0000105Dsd00000005* ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) pci:v0000105Dd00002339sv0000105Dsd00000006* ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) pci:v0000105Dd00002339sv0000105Dsd00000007* ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) pci:v0000105Dd00002339sv0000105Dsd00000008* ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2e 4Mb DRAM) pci:v0000105Dd00002339sv0000105Dsd00000009* ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2e 4Mb DRAM) pci:v0000105Dd00002339sv0000105Dsd0000000A* ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 8Mb VRAM) pci:v0000105Dd00002339sv0000105Dsd0000000B* ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 8Mb H-VRAM) pci:v0000105Dd00002339sv000011A4sd0000000A* ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) pci:v0000105Dd00002339sv000013CCsd00000000* ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) pci:v0000105Dd00002339sv000013CCsd00000004* ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) pci:v0000105Dd00002339sv000013CCsd00000005* ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) pci:v0000105Dd00002339sv000013CCsd00000006* ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) pci:v0000105Dd00002339sv000013CCsd00000008* ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) pci:v0000105Dd00002339sv000013CCsd00000009* ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) pci:v0000105Dd00002339sv000013CCsd0000000A* ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) pci:v0000105Dd00002339sv000013CCsd0000000C* ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) pci:v0000105Dd0000493D* ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] pci:v0000105Dd0000493Dsv000011A4sd0000000A* ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) pci:v0000105Dd0000493Dsv000011A4sd0000000B* ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) pci:v0000105Dd0000493Dsv000013CCsd00000002* ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 4 Megapixel, Dual Head) pci:v0000105Dd0000493Dsv000013CCsd00000003* ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) pci:v0000105Dd0000493Dsv000013CCsd00000007* ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) pci:v0000105Dd0000493Dsv000013CCsd00000008* ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) pci:v0000105Dd0000493Dsv000013CCsd00000009* ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) pci:v0000105Dd0000493Dsv000013CCsd0000000A* ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) pci:v0000105Dd00005348* ID_MODEL_FROM_DATABASE=Revolution 4 pci:v0000105Dd00005348sv0000105Dsd00000037* ID_MODEL_FROM_DATABASE=Revolution 4 (Revolution IV-FP AGP (For SGI 1600SW)) pci:v0000105Dd00005348sv000011A4sd00000028* ID_MODEL_FROM_DATABASE=Revolution 4 (PVS5600M) pci:v0000105Dd00005348sv000011A4sd00000038* ID_MODEL_FROM_DATABASE=Revolution 4 (PVS5600D) pci:v0000105E* ID_VENDOR_FROM_DATABASE=Vtech Computers Ltd pci:v0000105F* ID_VENDOR_FROM_DATABASE=Infotronic America Inc pci:v00001060* ID_VENDOR_FROM_DATABASE=United Microelectronics [UMC] pci:v00001060d00000001* ID_MODEL_FROM_DATABASE=UM82C881 pci:v00001060d00000002* ID_MODEL_FROM_DATABASE=UM82C886 pci:v00001060d00000101* ID_MODEL_FROM_DATABASE=UM8673F pci:v00001060d00000881* ID_MODEL_FROM_DATABASE=UM8881 pci:v00001060d00000886* ID_MODEL_FROM_DATABASE=UM8886F pci:v00001060d00000891* ID_MODEL_FROM_DATABASE=UM8891A pci:v00001060d00001001* ID_MODEL_FROM_DATABASE=UM886A pci:v00001060d0000673A* ID_MODEL_FROM_DATABASE=UM8886BF pci:v00001060d0000673B* ID_MODEL_FROM_DATABASE=EIDE Master/DMA pci:v00001060d00008710* ID_MODEL_FROM_DATABASE=UM8710 pci:v00001060d0000886A* ID_MODEL_FROM_DATABASE=UM8886A pci:v00001060d00008881* ID_MODEL_FROM_DATABASE=UM8881F pci:v00001060d00008886* ID_MODEL_FROM_DATABASE=UM8886F pci:v00001060d0000888A* ID_MODEL_FROM_DATABASE=UM8886A pci:v00001060d00008891* ID_MODEL_FROM_DATABASE=UM8891A pci:v00001060d00009017* ID_MODEL_FROM_DATABASE=UM9017F pci:v00001060d00009018* ID_MODEL_FROM_DATABASE=UM9018 pci:v00001060d00009026* ID_MODEL_FROM_DATABASE=UM9026 pci:v00001060d0000E881* ID_MODEL_FROM_DATABASE=UM8881N pci:v00001060d0000E886* ID_MODEL_FROM_DATABASE=UM8886N pci:v00001060d0000E88A* ID_MODEL_FROM_DATABASE=UM8886N pci:v00001060d0000E891* ID_MODEL_FROM_DATABASE=UM8891N pci:v00001061* ID_VENDOR_FROM_DATABASE=I.I.T. pci:v00001061d00000001* ID_MODEL_FROM_DATABASE=AGX016 pci:v00001061d00000002* ID_MODEL_FROM_DATABASE=IIT3204/3501 pci:v00001062* ID_VENDOR_FROM_DATABASE=Maspar Computer Corp pci:v00001063* ID_VENDOR_FROM_DATABASE=Ocean Office Automation pci:v00001064* ID_VENDOR_FROM_DATABASE=Alcatel pci:v00001064d00001102* ID_MODEL_FROM_DATABASE=Dynamite 2840 (ADSL PCI modem) pci:v00001065* ID_VENDOR_FROM_DATABASE=Texas Microsystems pci:v00001066* ID_VENDOR_FROM_DATABASE=PicoPower Technology pci:v00001066d00000000* ID_MODEL_FROM_DATABASE=PT80C826 pci:v00001066d00000001* ID_MODEL_FROM_DATABASE=PT86C521 [Vesuvius v1] Host Bridge pci:v00001066d00000002* ID_MODEL_FROM_DATABASE=PT86C523 [Vesuvius v3] PCI-ISA Bridge Master pci:v00001066d00000003* ID_MODEL_FROM_DATABASE=PT86C524 [Nile] PCI-to-PCI Bridge pci:v00001066d00000004* ID_MODEL_FROM_DATABASE=PT86C525 [Nile-II] PCI-to-PCI Bridge pci:v00001066d00000005* ID_MODEL_FROM_DATABASE=National PC87550 System Controller pci:v00001066d00008002* ID_MODEL_FROM_DATABASE=PT86C523 [Vesuvius v3] PCI-ISA Bridge Slave pci:v00001067* ID_VENDOR_FROM_DATABASE=Mitsubishi Electric pci:v00001067d00000301* ID_MODEL_FROM_DATABASE=AccelGraphics AccelECLIPSE pci:v00001067d00000304* ID_MODEL_FROM_DATABASE=AccelGALAXY A2100 [OEM Evans & Sutherland] pci:v00001067d00000308* ID_MODEL_FROM_DATABASE=Tornado 3000 [OEM Evans & Sutherland] pci:v00001067d00001002* ID_MODEL_FROM_DATABASE=VG500 [VolumePro Volume Rendering Accelerator] pci:v00001068* ID_VENDOR_FROM_DATABASE=Diversified Technology pci:v00001069* ID_VENDOR_FROM_DATABASE=Mylex Corporation pci:v00001069d00000001* ID_MODEL_FROM_DATABASE=DAC960P pci:v00001069d00000002* ID_MODEL_FROM_DATABASE=DAC960PD pci:v00001069d00000010* ID_MODEL_FROM_DATABASE=DAC960PG pci:v00001069d00000020* ID_MODEL_FROM_DATABASE=DAC960LA pci:v00001069d00000050* ID_MODEL_FROM_DATABASE=AcceleRAID 352/170/160 support Device pci:v00001069d00000050sv00001069sd00000050* ID_MODEL_FROM_DATABASE=AcceleRAID 352/170/160 support Device (AcceleRAID 352 support Device) pci:v00001069d00000050sv00001069sd00000052* ID_MODEL_FROM_DATABASE=AcceleRAID 352/170/160 support Device (AcceleRAID 170 support Device) pci:v00001069d00000050sv00001069sd00000054* ID_MODEL_FROM_DATABASE=AcceleRAID 352/170/160 support Device (AcceleRAID 160 support Device) pci:v00001069d0000B166* ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device pci:v00001069d0000B166sv00001014sd00000242* ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (iSeries 2872 DASD IOA) pci:v00001069d0000B166sv00001014sd00000266* ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (Dual Channel PCI-X U320 SCSI Adapter) pci:v00001069d0000B166sv00001014sd00000278* ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (Dual Channel PCI-X U320 SCSI RAID Adapter) pci:v00001069d0000B166sv00001014sd000002D3* ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (Dual Channel PCI-X U320 SCSI Adapter) pci:v00001069d0000B166sv00001014sd000002D4* ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (Dual Channel PCI-X U320 SCSI RAID Adapter) pci:v00001069d0000B166sv00001069sd00000200* ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (AcceleRAID 400, Single Channel, PCI-X, U320, SCSI RAID) pci:v00001069d0000B166sv00001069sd00000202* ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (AcceleRAID Sapphire, Dual Channel, PCI-X, U320, SCSI RAID) pci:v00001069d0000B166sv00001069sd00000204* ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (AcceleRAID 500, Dual Channel, Low-Profile, PCI-X, U320, SCSI RAID) pci:v00001069d0000B166sv00001069sd00000206* ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (AcceleRAID 600, Dual Channel, PCI-X, U320, SCSI RAID) pci:v00001069d0000BA55* ID_MODEL_FROM_DATABASE=eXtremeRAID 1100 support Device pci:v00001069d0000BA56* ID_MODEL_FROM_DATABASE=eXtremeRAID 2000/3000 support Device pci:v00001069d0000BA56sv00001069sd00000030* ID_MODEL_FROM_DATABASE=eXtremeRAID 2000/3000 support Device (eXtremeRAID 3000 support Device) pci:v00001069d0000BA56sv00001069sd00000040* ID_MODEL_FROM_DATABASE=eXtremeRAID 2000/3000 support Device (eXtremeRAID 2000 support Device) pci:v00001069d0000BA57* ID_MODEL_FROM_DATABASE=eXtremeRAID 4000/5000 support Device pci:v00001069d0000BA57sv00001069sd00000072* ID_MODEL_FROM_DATABASE=eXtremeRAID 4000/5000 support Device (eXtremeRAID 5000 support Device) pci:v0000106A* ID_VENDOR_FROM_DATABASE=Aten Research Inc pci:v0000106B* ID_VENDOR_FROM_DATABASE=Apple Inc. pci:v0000106Bd00000001* ID_MODEL_FROM_DATABASE=Bandit PowerPC host bridge pci:v0000106Bd00000002* ID_MODEL_FROM_DATABASE=Grand Central I/O pci:v0000106Bd00000003* ID_MODEL_FROM_DATABASE=Control Video pci:v0000106Bd00000004* ID_MODEL_FROM_DATABASE=PlanB Video-In pci:v0000106Bd00000007* ID_MODEL_FROM_DATABASE=O'Hare I/O pci:v0000106Bd0000000C* ID_MODEL_FROM_DATABASE=DOS on Mac pci:v0000106Bd0000000E* ID_MODEL_FROM_DATABASE=Hydra Mac I/O pci:v0000106Bd00000010* ID_MODEL_FROM_DATABASE=Heathrow Mac I/O pci:v0000106Bd00000017* ID_MODEL_FROM_DATABASE=Paddington Mac I/O pci:v0000106Bd00000018* ID_MODEL_FROM_DATABASE=UniNorth FireWire pci:v0000106Bd00000019* ID_MODEL_FROM_DATABASE=KeyLargo USB pci:v0000106Bd0000001E* ID_MODEL_FROM_DATABASE=UniNorth Internal PCI pci:v0000106Bd0000001F* ID_MODEL_FROM_DATABASE=UniNorth PCI pci:v0000106Bd00000020* ID_MODEL_FROM_DATABASE=UniNorth AGP pci:v0000106Bd00000021* ID_MODEL_FROM_DATABASE=UniNorth GMAC (Sun GEM) pci:v0000106Bd00000022* ID_MODEL_FROM_DATABASE=KeyLargo Mac I/O pci:v0000106Bd00000024* ID_MODEL_FROM_DATABASE=UniNorth/Pangea GMAC (Sun GEM) pci:v0000106Bd00000025* ID_MODEL_FROM_DATABASE=KeyLargo/Pangea Mac I/O pci:v0000106Bd00000026* ID_MODEL_FROM_DATABASE=KeyLargo/Pangea USB pci:v0000106Bd00000027* ID_MODEL_FROM_DATABASE=UniNorth/Pangea AGP pci:v0000106Bd00000028* ID_MODEL_FROM_DATABASE=UniNorth/Pangea PCI pci:v0000106Bd00000029* ID_MODEL_FROM_DATABASE=UniNorth/Pangea Internal PCI pci:v0000106Bd0000002D* ID_MODEL_FROM_DATABASE=UniNorth 1.5 AGP pci:v0000106Bd0000002E* ID_MODEL_FROM_DATABASE=UniNorth 1.5 PCI pci:v0000106Bd0000002F* ID_MODEL_FROM_DATABASE=UniNorth 1.5 Internal PCI pci:v0000106Bd00000030* ID_MODEL_FROM_DATABASE=UniNorth/Pangea FireWire pci:v0000106Bd00000031* ID_MODEL_FROM_DATABASE=UniNorth 2 FireWire pci:v0000106Bd00000031sv0000106Bsd00005811* ID_MODEL_FROM_DATABASE=UniNorth 2 FireWire (iBook G4 2004) pci:v0000106Bd00000032* ID_MODEL_FROM_DATABASE=UniNorth 2 GMAC (Sun GEM) pci:v0000106Bd00000033* ID_MODEL_FROM_DATABASE=UniNorth 2 ATA/100 pci:v0000106Bd00000034* ID_MODEL_FROM_DATABASE=UniNorth 2 AGP pci:v0000106Bd00000035* ID_MODEL_FROM_DATABASE=UniNorth 2 PCI pci:v0000106Bd00000036* ID_MODEL_FROM_DATABASE=UniNorth 2 Internal PCI pci:v0000106Bd0000003B* ID_MODEL_FROM_DATABASE=UniNorth/Intrepid ATA/100 pci:v0000106Bd0000003E* ID_MODEL_FROM_DATABASE=KeyLargo/Intrepid Mac I/O pci:v0000106Bd0000003F* ID_MODEL_FROM_DATABASE=KeyLargo/Intrepid USB pci:v0000106Bd0000003Fsv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=KeyLargo/Intrepid USB (QEMU Virtual Machine) pci:v0000106Bd00000040* ID_MODEL_FROM_DATABASE=K2 KeyLargo USB pci:v0000106Bd00000041* ID_MODEL_FROM_DATABASE=K2 KeyLargo Mac/IO pci:v0000106Bd00000042* ID_MODEL_FROM_DATABASE=K2 FireWire pci:v0000106Bd00000043* ID_MODEL_FROM_DATABASE=K2 ATA/100 pci:v0000106Bd00000045* ID_MODEL_FROM_DATABASE=K2 HT-PCI Bridge pci:v0000106Bd00000046* ID_MODEL_FROM_DATABASE=K2 HT-PCI Bridge pci:v0000106Bd00000047* ID_MODEL_FROM_DATABASE=K2 HT-PCI Bridge pci:v0000106Bd00000048* ID_MODEL_FROM_DATABASE=K2 HT-PCI Bridge pci:v0000106Bd00000049* ID_MODEL_FROM_DATABASE=K2 HT-PCI Bridge pci:v0000106Bd0000004A* ID_MODEL_FROM_DATABASE=CPC945 HT Bridge pci:v0000106Bd0000004B* ID_MODEL_FROM_DATABASE=U3 AGP pci:v0000106Bd0000004C* ID_MODEL_FROM_DATABASE=K2 GMAC (Sun GEM) pci:v0000106Bd0000004F* ID_MODEL_FROM_DATABASE=Shasta Mac I/O pci:v0000106Bd00000050* ID_MODEL_FROM_DATABASE=Shasta IDE pci:v0000106Bd00000051* ID_MODEL_FROM_DATABASE=Shasta (Sun GEM) pci:v0000106Bd00000052* ID_MODEL_FROM_DATABASE=Shasta Firewire pci:v0000106Bd00000053* ID_MODEL_FROM_DATABASE=Shasta PCI Bridge pci:v0000106Bd00000054* ID_MODEL_FROM_DATABASE=Shasta PCI Bridge pci:v0000106Bd00000055* ID_MODEL_FROM_DATABASE=Shasta PCI Bridge pci:v0000106Bd00000056* ID_MODEL_FROM_DATABASE=U4 PCIe pci:v0000106Bd00000057* ID_MODEL_FROM_DATABASE=U3 HT Bridge pci:v0000106Bd00000058* ID_MODEL_FROM_DATABASE=U3L AGP Bridge pci:v0000106Bd00000059* ID_MODEL_FROM_DATABASE=U3H AGP Bridge pci:v0000106Bd0000005B* ID_MODEL_FROM_DATABASE=CPC945 PCIe Bridge pci:v0000106Bd00000066* ID_MODEL_FROM_DATABASE=Intrepid2 AGP Bridge pci:v0000106Bd00000067* ID_MODEL_FROM_DATABASE=Intrepid2 PCI Bridge pci:v0000106Bd00000068* ID_MODEL_FROM_DATABASE=Intrepid2 PCI Bridge pci:v0000106Bd00000069* ID_MODEL_FROM_DATABASE=Intrepid2 ATA/100 pci:v0000106Bd0000006A* ID_MODEL_FROM_DATABASE=Intrepid2 Firewire pci:v0000106Bd0000006B* ID_MODEL_FROM_DATABASE=Intrepid2 GMAC (Sun GEM) pci:v0000106Bd00000074* ID_MODEL_FROM_DATABASE=U4 HT Bridge pci:v0000106Bd00001645* ID_MODEL_FROM_DATABASE=Broadcom NetXtreme BCM5701 Gigabit Ethernet pci:v0000106Bd00002001* ID_MODEL_FROM_DATABASE=PCI Express SSD pci:v0000106C* ID_VENDOR_FROM_DATABASE=Hynix Semiconductor pci:v0000106Cd00008139* ID_MODEL_FROM_DATABASE=8139c 100BaseTX Ethernet Controller pci:v0000106Cd00008801* ID_MODEL_FROM_DATABASE=Dual Pentium ISA/PCI Motherboard pci:v0000106Cd00008802* ID_MODEL_FROM_DATABASE=PowerPC ISA/PCI Motherboard pci:v0000106Cd00008803* ID_MODEL_FROM_DATABASE=Dual Window Graphics Accelerator pci:v0000106Cd00008804* ID_MODEL_FROM_DATABASE=LAN Controller pci:v0000106Cd00008805* ID_MODEL_FROM_DATABASE=100-BaseT LAN pci:v0000106D* ID_VENDOR_FROM_DATABASE=Sequent Computer Systems pci:v0000106E* ID_VENDOR_FROM_DATABASE=DFI, Inc pci:v0000106F* ID_VENDOR_FROM_DATABASE=City Gate Development Ltd pci:v00001070* ID_VENDOR_FROM_DATABASE=Daewoo Telecom Ltd pci:v00001071* ID_VENDOR_FROM_DATABASE=Mitac pci:v00001071d00008160* ID_MODEL_FROM_DATABASE=Mitac 8060B Mobile Platform pci:v00001072* ID_VENDOR_FROM_DATABASE=GIT Co Ltd pci:v00001073* ID_VENDOR_FROM_DATABASE=Yamaha Corporation pci:v00001073d00000001* ID_MODEL_FROM_DATABASE=3D GUI Accelerator pci:v00001073d00000002* ID_MODEL_FROM_DATABASE=YGV615 [RPA3 3D-Graphics Controller] pci:v00001073d00000003* ID_MODEL_FROM_DATABASE=YMF-740 pci:v00001073d00000004* ID_MODEL_FROM_DATABASE=YMF-724 pci:v00001073d00000004sv00001073sd00000004* ID_MODEL_FROM_DATABASE=YMF-724 (YMF724-Based PCI Audio Adapter) pci:v00001073d00000005* ID_MODEL_FROM_DATABASE=DS1 Audio pci:v00001073d00000005sv00001073sd00000005* ID_MODEL_FROM_DATABASE=DS1 Audio (DS-XG PCI Audio CODEC) pci:v00001073d00000006* ID_MODEL_FROM_DATABASE=DS1 Audio pci:v00001073d00000008* ID_MODEL_FROM_DATABASE=DS1 Audio pci:v00001073d00000008sv00001073sd00000008* ID_MODEL_FROM_DATABASE=DS1 Audio (DS-XG PCI Audio CODEC) pci:v00001073d0000000A* ID_MODEL_FROM_DATABASE=DS1L Audio pci:v00001073d0000000Asv00001073sd00000004* ID_MODEL_FROM_DATABASE=DS1L Audio (DS-XG PCI Audio CODEC) pci:v00001073d0000000Asv00001073sd0000000A* ID_MODEL_FROM_DATABASE=DS1L Audio (DS-XG PCI Audio CODEC) pci:v00001073d0000000Asv00008086sd00004D55* ID_MODEL_FROM_DATABASE=DS1L Audio (DS-XG PCI Audio CODEC [Intel MU440EX]) pci:v00001073d0000000C* ID_MODEL_FROM_DATABASE=YMF-740C [DS-1L Audio Controller] pci:v00001073d0000000Csv0000107Asd0000000C* ID_MODEL_FROM_DATABASE=YMF-740C [DS-1L Audio Controller] (DS-XG PCI Audio CODEC) pci:v00001073d0000000D* ID_MODEL_FROM_DATABASE=YMF-724F [DS-1 Audio Controller] pci:v00001073d0000000Dsv00001073sd0000000D* ID_MODEL_FROM_DATABASE=YMF-724F [DS-1 Audio Controller] (DS-XG PCI Audio CODEC) pci:v00001073d00000010* ID_MODEL_FROM_DATABASE=YMF-744B [DS-1S Audio Controller] pci:v00001073d00000010sv00001073sd00000006* ID_MODEL_FROM_DATABASE=YMF-744B [DS-1S Audio Controller] (DS-XG PCI Audio CODEC) pci:v00001073d00000010sv00001073sd00000010* ID_MODEL_FROM_DATABASE=YMF-744B [DS-1S Audio Controller] (DS-XG PCI Audio CODEC) pci:v00001073d00000012* ID_MODEL_FROM_DATABASE=YMF-754 [DS-1E Audio Controller] pci:v00001073d00000012sv00001073sd00000012* ID_MODEL_FROM_DATABASE=YMF-754 [DS-1E Audio Controller] (DS-XG PCI Audio Codec) pci:v00001073d00000020* ID_MODEL_FROM_DATABASE=DS-1 Audio pci:v00001073d00001000* ID_MODEL_FROM_DATABASE=SW1000XG [XG Factory] pci:v00001073d00002000* ID_MODEL_FROM_DATABASE=DS2416 Digital Mixing Card pci:v00001073d00002000sv00001073sd00002000* ID_MODEL_FROM_DATABASE=DS2416 Digital Mixing Card pci:v00001074* ID_VENDOR_FROM_DATABASE=NexGen Microsystems pci:v00001074d00004E78* ID_MODEL_FROM_DATABASE=82c500/1 pci:v00001075* ID_VENDOR_FROM_DATABASE=Advanced Integrations Research pci:v00001076* ID_VENDOR_FROM_DATABASE=Chaintech Computer Co. Ltd pci:v00001077* ID_VENDOR_FROM_DATABASE=QLogic Corp. pci:v00001077d00001016* ID_MODEL_FROM_DATABASE=ISP10160 Single Channel Ultra3 SCSI Processor pci:v00001077d00001020* ID_MODEL_FROM_DATABASE=ISP1020 Fast-wide SCSI pci:v00001077d00001022* ID_MODEL_FROM_DATABASE=ISP1022 Fast-wide SCSI pci:v00001077d00001080* ID_MODEL_FROM_DATABASE=ISP1080 SCSI Host Adapter pci:v00001077d00001216* ID_MODEL_FROM_DATABASE=ISP12160 Dual Channel Ultra3 SCSI Processor pci:v00001077d00001216sv0000101Esd00008471* ID_MODEL_FROM_DATABASE=ISP12160 Dual Channel Ultra3 SCSI Processor (QLA12160 on AMI MegaRAID) pci:v00001077d00001216sv0000101Esd00008493* ID_MODEL_FROM_DATABASE=ISP12160 Dual Channel Ultra3 SCSI Processor (QLA12160 on AMI MegaRAID) pci:v00001077d00001240* ID_MODEL_FROM_DATABASE=ISP1240 SCSI Host Adapter pci:v00001077d00001280* ID_MODEL_FROM_DATABASE=ISP1280 SCSI Host Adapter pci:v00001077d00001634* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller pci:v00001077d00001634sv00001077sd0000E4F1* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (FastLinQ QL45212H 40GbE Adapter) pci:v00001077d00001634sv00001077sd0000E4F2* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (FastLinQ QL45211H 40GbE Adapter) pci:v00001077d00001634sv00001077sd0000E4F3* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (FastLinQ QL45412H 40GbE Adapter) pci:v00001077d00001634sv00001077sd0000E4F4* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (FastLinQ QL45411H 40GbE Adapter) pci:v00001077d00001644* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 100GbE Controller pci:v00001077d00001644sv00001077sd0000E4F8* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 100GbE Controller (FastLinQ QL45611H 100GbE Adapter) pci:v00001077d00001656* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller pci:v00001077d00001656sv00001077sd0000E4F6* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller (FastLinQ QL45211H 25GbE Adapter) pci:v00001077d00001656sv00001077sd0000E4F7* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller (FastLinQ QL45212H 25GbE Adapter) pci:v00001077d0000165C* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (FCoE) pci:v00001077d0000165Csv00001077sd0000E4F1* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (FCoE) (FastLinQ QL45462H 40GbE FCoE Adapter) pci:v00001077d0000165Csv00001077sd0000E4F2* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (FCoE) (FastLinQ QL45461H 40GbE FCoE Adapter) pci:v00001077d0000165E* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (iSCSI) pci:v00001077d0000165Esv00001077sd0000E4F1* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (iSCSI) (FastLinQ QL45462H 40GbE iSCSI Adapter) pci:v00001077d0000165Esv00001077sd0000E4F2* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (iSCSI) (FastLinQ QL45461H 40GbE iSCSI Adapter) pci:v00001077d00001664* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) pci:v00001077d00001664sv00001077sd0000E4F1* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45462H 40GbE Adapter (SR-IOV VF)) pci:v00001077d00001664sv00001077sd0000E4F2* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45461H 40GbE Adapter (SR-IOV VF)) pci:v00001077d00001664sv00001077sd0000E4F3* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45412H 40GbE Adapter (SR-IOV VF)) pci:v00001077d00001664sv00001077sd0000E4F4* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45411H 40GbE Adapter (SR-IOV VF)) pci:v00001077d00001664sv00001077sd0000E4F6* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45211H 25GbE Adapter (SR-IOV VF)) pci:v00001077d00001664sv00001077sd0000E4F7* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45212H 25GbE Adapter (SR-IOV VF)) pci:v00001077d00001664sv00001077sd0000E4F8* ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45611H 100GbE Adapter (SR-IOV VF)) pci:v00001077d00002020* ID_MODEL_FROM_DATABASE=ISP2020A Fast!SCSI Basic Adapter pci:v00001077d00002031* ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter pci:v00001077d00002031sv0000103Csd000017E7* ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (HP SN1000Q 16Gb Single Port Fibre Channel Adapter) pci:v00001077d00002031sv0000103Csd000017E8* ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (HP SN1000Q 16Gb Dual Port Fibre Channel Adapter) pci:v00001077d00002031sv0000103Csd00001939* ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (HP QMH2672 16Gb Dual Port Fibre Channel Adapter) pci:v00001077d00002031sv0000103Csd00008002* ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (3830C 16G Fibre Channel Host Bus Adapter) pci:v00001077d00002071* ID_MODEL_FROM_DATABASE=ISP2714-based 16/32Gb Fibre Channel to PCIe Adapter pci:v00001077d00002100* ID_MODEL_FROM_DATABASE=QLA2100 64-bit Fibre Channel Adapter pci:v00001077d00002100sv00001077sd00000001* ID_MODEL_FROM_DATABASE=QLA2100 64-bit Fibre Channel Adapter pci:v00001077d00002200* ID_MODEL_FROM_DATABASE=QLA2200 64-bit Fibre Channel Adapter pci:v00001077d00002200sv00001077sd00000002* ID_MODEL_FROM_DATABASE=QLA2200 64-bit Fibre Channel Adapter (QLA2200) pci:v00001077d00002261* ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter pci:v00001077d00002261sv00001590sd000000F9* ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (HPE StoreFabric SN1100Q 16Gb Single Port Fibre Channel Host Bus Adapter) pci:v00001077d00002261sv00001590sd000000FA* ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (HPE StoreFabric SN1100Q 16Gb Dual Port Fibre Channel Host Bus Adapter) pci:v00001077d00002300* ID_MODEL_FROM_DATABASE=QLA2300 64-bit Fibre Channel Adapter pci:v00001077d00002312* ID_MODEL_FROM_DATABASE=ISP2312-based 2Gb Fibre Channel to PCI-X HBA pci:v00001077d00002312sv0000103Csd00000131* ID_MODEL_FROM_DATABASE=ISP2312-based 2Gb Fibre Channel to PCI-X HBA (2Gb Fibre Channel - Single port [A7538A]) pci:v00001077d00002312sv0000103Csd000012BA* ID_MODEL_FROM_DATABASE=ISP2312-based 2Gb Fibre Channel to PCI-X HBA (2Gb Fibre Channel - Dual port [A6826A]) pci:v00001077d00002322* ID_MODEL_FROM_DATABASE=ISP2322-based 2Gb Fibre Channel to PCI-X HBA pci:v00001077d00002422* ID_MODEL_FROM_DATABASE=ISP2422-based 4Gb Fibre Channel to PCI-X HBA pci:v00001077d00002422sv0000103Csd000012D7* ID_MODEL_FROM_DATABASE=ISP2422-based 4Gb Fibre Channel to PCI-X HBA (4Gb Fibre Channel [AB379A]) pci:v00001077d00002422sv0000103Csd000012DD* ID_MODEL_FROM_DATABASE=ISP2422-based 4Gb Fibre Channel to PCI-X HBA (4Gb Fibre Channel [AB429A]) pci:v00001077d00002432* ID_MODEL_FROM_DATABASE=ISP2432-based 4Gb Fibre Channel to PCI Express HBA pci:v00001077d00002432sv0000103Csd00007040* ID_MODEL_FROM_DATABASE=ISP2432-based 4Gb Fibre Channel to PCI Express HBA (FC1142SR 4Gb 1-port PCIe Fibre Channel Host Bus Adapter [HPAE311A]) pci:v00001077d00002532* ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA pci:v00001077d00002532sv0000103Csd00003262* ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (StorageWorks 81Q) pci:v00001077d00002532sv00001077sd00000167* ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (QME2572 Dual Port FC8 HBA Mezzanine) pci:v00001077d00002532sv00001590sd000000FC* ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (HPE StoreFabric 84Q 8Gb Quad Port Fibre Channel Host Bus Adapter) pci:v00001077d00003022* ID_MODEL_FROM_DATABASE=ISP4022-based Ethernet NIC pci:v00001077d00003032* ID_MODEL_FROM_DATABASE=ISP4032-based Ethernet IPv6 NIC pci:v00001077d00004010* ID_MODEL_FROM_DATABASE=ISP4010-based iSCSI TOE HBA pci:v00001077d00004022* ID_MODEL_FROM_DATABASE=ISP4022-based iSCSI TOE HBA pci:v00001077d00004032* ID_MODEL_FROM_DATABASE=ISP4032-based iSCSI TOE IPv6 HBA pci:v00001077d00005432* ID_MODEL_FROM_DATABASE=SP232-based 4Gb Fibre Channel to PCI Express HBA pci:v00001077d00006312* ID_MODEL_FROM_DATABASE=SP202-based 2Gb Fibre Channel to PCI-X HBA pci:v00001077d00006322* ID_MODEL_FROM_DATABASE=SP212-based 2Gb Fibre Channel to PCI-X HBA pci:v00001077d00007220* ID_MODEL_FROM_DATABASE=IBA7220 InfiniBand HCA pci:v00001077d00007322* ID_MODEL_FROM_DATABASE=IBA7322 QDR InfiniBand HCA pci:v00001077d00008000* ID_MODEL_FROM_DATABASE=10GbE Converged Network Adapter (TCP/IP Networking) pci:v00001077d00008001* ID_MODEL_FROM_DATABASE=10GbE Converged Network Adapter (FCoE) pci:v00001077d00008020* ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller pci:v00001077d00008020sv00001028sd00001F64* ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (QMD8262-k 10G DP bNDC KR) pci:v00001077d00008020sv0000103Csd00003346* ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (CN1000Q Dual Port Converged Network Adapter) pci:v00001077d00008020sv0000103Csd00003733* ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (NC523SFP 10Gb 2-port Server Adapter) pci:v00001077d00008020sv00001077sd00000203* ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (8200 Series Single Port 10GbE Converged Network Adapter (TCP/IP Networking)) pci:v00001077d00008020sv00001077sd00000207* ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (8200 Series Dual Port 10GbE Converged Network Adapter (TCP/IP Networking)) pci:v00001077d00008020sv00001077sd0000020B* ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (3200 Series Dual Port 10Gb Intelligent Ethernet Adapter) pci:v00001077d00008020sv00001077sd0000020C* ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (3200 Series Quad Port 1Gb Intelligent Ethernet Adapter) pci:v00001077d00008020sv00001077sd0000020F* ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (3200 Series Single Port 10Gb Intelligent Ethernet Adapter) pci:v00001077d00008020sv00001077sd00000210* ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (QME8242-k 10GbE Dual Port Mezzanine Card) pci:v00001077d00008020sv00001077sd00000233* ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (QME8262-k 10GbE Dual Port Mezzanine Card) pci:v00001077d00008021* ID_MODEL_FROM_DATABASE=8200 Series 10GbE Converged Network Adapter (FCoE) pci:v00001077d00008021sv0000103Csd00003348* ID_MODEL_FROM_DATABASE=8200 Series 10GbE Converged Network Adapter (FCoE) (CN1000Q Dual Port Converged Network Adapter) pci:v00001077d00008021sv00001077sd00000211* ID_MODEL_FROM_DATABASE=8200 Series 10GbE Converged Network Adapter (FCoE) (QME8242-k 10GbE Dual Port Mezzanine Card, FCoE) pci:v00001077d00008022* ID_MODEL_FROM_DATABASE=8200 Series 10GbE Converged Network Adapter (iSCSI) pci:v00001077d00008022sv0000103Csd00003347* ID_MODEL_FROM_DATABASE=8200 Series 10GbE Converged Network Adapter (iSCSI) (CN1000Q Dual Port Converged Network Adapter) pci:v00001077d00008022sv00001077sd00000212* ID_MODEL_FROM_DATABASE=8200 Series 10GbE Converged Network Adapter (iSCSI) (QME8242-k 10GbE Dual Port Mezzanine Card, iSCSI) pci:v00001077d00008030* ID_MODEL_FROM_DATABASE=ISP8324 1/10GbE Converged Network Controller pci:v00001077d00008030sv00001077sd00000243* ID_MODEL_FROM_DATABASE=ISP8324 1/10GbE Converged Network Controller (8300 Series Single Port 10GbE Converged Network Adapter (TCP/IP Networking)) pci:v00001077d00008030sv00001077sd00000246* ID_MODEL_FROM_DATABASE=ISP8324 1/10GbE Converged Network Controller (8300 Series Dual Port 10GbE Converged Network Adapter (TCP/IP Networking)) pci:v00001077d00008031* ID_MODEL_FROM_DATABASE=8300 Series 10GbE Converged Network Adapter (FCoE) pci:v00001077d00008032* ID_MODEL_FROM_DATABASE=8300 Series 10GbE Converged Network Adapter (iSCSI) pci:v00001077d00008430* ID_MODEL_FROM_DATABASE=ISP8324 1/10GbE Converged Network Controller (NIC VF) pci:v00001077d00008431* ID_MODEL_FROM_DATABASE=8300 Series 10GbE Converged Network Adapter (FCoE VF) pci:v00001077d00008432* ID_MODEL_FROM_DATABASE=ISP2432M-based 10GbE Converged Network Adapter (CNA) pci:v00001078* ID_VENDOR_FROM_DATABASE=Cyrix Corporation pci:v00001078d00000000* ID_MODEL_FROM_DATABASE=5510 [Grappa] pci:v00001078d00000001* ID_MODEL_FROM_DATABASE=PCI Master pci:v00001078d00000002* ID_MODEL_FROM_DATABASE=5520 [Cognac] pci:v00001078d00000100* ID_MODEL_FROM_DATABASE=5530 Legacy [Kahlua] pci:v00001078d00000101* ID_MODEL_FROM_DATABASE=5530 SMI [Kahlua] pci:v00001078d00000102* ID_MODEL_FROM_DATABASE=5530 IDE [Kahlua] pci:v00001078d00000103* ID_MODEL_FROM_DATABASE=5530 Audio [Kahlua] pci:v00001078d00000104* ID_MODEL_FROM_DATABASE=5530 Video [Kahlua] pci:v00001078d00000400* ID_MODEL_FROM_DATABASE=ZFMicro PCI Bridge pci:v00001078d00000401* ID_MODEL_FROM_DATABASE=ZFMicro Chipset SMI pci:v00001078d00000402* ID_MODEL_FROM_DATABASE=ZFMicro Chipset IDE pci:v00001078d00000403* ID_MODEL_FROM_DATABASE=ZFMicro Expansion Bus pci:v00001079* ID_VENDOR_FROM_DATABASE=I-Bus pci:v0000107A* ID_VENDOR_FROM_DATABASE=NetWorth pci:v0000107B* ID_VENDOR_FROM_DATABASE=Gateway, Inc. pci:v0000107C* ID_VENDOR_FROM_DATABASE=LG Electronics [Lucky Goldstar Co. Ltd] pci:v0000107D* ID_VENDOR_FROM_DATABASE=LeadTek Research Inc. pci:v0000107Dd00000000* ID_MODEL_FROM_DATABASE=P86C850 pci:v0000107E* ID_VENDOR_FROM_DATABASE=Interphase Corporation pci:v0000107Ed00000001* ID_MODEL_FROM_DATABASE=5515 ATM Adapter [Flipper] pci:v0000107Ed00000002* ID_MODEL_FROM_DATABASE=100 VG AnyLan Controller pci:v0000107Ed00000004* ID_MODEL_FROM_DATABASE=5526 Fibre Channel Host Adapter pci:v0000107Ed00000005* ID_MODEL_FROM_DATABASE=x526 Fibre Channel Host Adapter pci:v0000107Ed00000008* ID_MODEL_FROM_DATABASE=5525/5575 ATM Adapter (155 Mbit) [Atlantic] pci:v0000107Ed00009003* ID_MODEL_FROM_DATABASE=5535-4P-BRI-ST pci:v0000107Ed00009007* ID_MODEL_FROM_DATABASE=5535-4P-BRI-U pci:v0000107Ed00009008* ID_MODEL_FROM_DATABASE=5535-1P-SR pci:v0000107Ed0000900C* ID_MODEL_FROM_DATABASE=5535-1P-SR-ST pci:v0000107Ed0000900E* ID_MODEL_FROM_DATABASE=5535-1P-SR-U pci:v0000107Ed00009011* ID_MODEL_FROM_DATABASE=5535-1P-PRI pci:v0000107Ed00009013* ID_MODEL_FROM_DATABASE=5535-2P-PRI pci:v0000107Ed00009023* ID_MODEL_FROM_DATABASE=5536-4P-BRI-ST pci:v0000107Ed00009027* ID_MODEL_FROM_DATABASE=5536-4P-BRI-U pci:v0000107Ed00009031* ID_MODEL_FROM_DATABASE=5536-1P-PRI pci:v0000107Ed00009033* ID_MODEL_FROM_DATABASE=5536-2P-PRI pci:v0000107F* ID_VENDOR_FROM_DATABASE=Data Technology Corporation pci:v0000107Fd00000802* ID_MODEL_FROM_DATABASE=SL82C105 pci:v00001080* ID_VENDOR_FROM_DATABASE=Contaq Microsystems pci:v00001080d00000600* ID_MODEL_FROM_DATABASE=82C599 pci:v00001080d0000C691* ID_MODEL_FROM_DATABASE=Cypress CY82C691 pci:v00001080d0000C693* ID_MODEL_FROM_DATABASE=82c693 pci:v00001081* ID_VENDOR_FROM_DATABASE=Supermac Technology pci:v00001081d00000D47* ID_MODEL_FROM_DATABASE=Radius PCI to NuBUS Bridge pci:v00001082* ID_VENDOR_FROM_DATABASE=EFA Corporation of America pci:v00001083* ID_VENDOR_FROM_DATABASE=Forex Computer Corporation pci:v00001083d00000001* ID_MODEL_FROM_DATABASE=FR710 pci:v00001084* ID_VENDOR_FROM_DATABASE=Parador pci:v00001086* ID_VENDOR_FROM_DATABASE=J. Bond Computer Systems pci:v00001087* ID_VENDOR_FROM_DATABASE=Cache Computer pci:v00001088* ID_VENDOR_FROM_DATABASE=Microcomputer Systems (M) Son pci:v00001089* ID_VENDOR_FROM_DATABASE=Data General Corporation pci:v0000108A* ID_VENDOR_FROM_DATABASE=SBS Technologies pci:v0000108Ad00000001* ID_MODEL_FROM_DATABASE=VME Bridge Model 617 pci:v0000108Ad00000010* ID_MODEL_FROM_DATABASE=VME Bridge Model 618 pci:v0000108Ad00000040* ID_MODEL_FROM_DATABASE=dataBLIZZARD pci:v0000108Ad00003000* ID_MODEL_FROM_DATABASE=VME Bridge Model 2706 pci:v0000108C* ID_VENDOR_FROM_DATABASE=Oakleigh Systems Inc. pci:v0000108D* ID_VENDOR_FROM_DATABASE=Olicom pci:v0000108Dd00000001* ID_MODEL_FROM_DATABASE=Token-Ring 16/4 PCI Adapter (3136/3137) pci:v0000108Dd00000002* ID_MODEL_FROM_DATABASE=16/4 Token Ring pci:v0000108Dd00000004* ID_MODEL_FROM_DATABASE=RapidFire OC-3139/3140 Token-Ring 16/4 PCI Adapter pci:v0000108Dd00000004sv0000108Dsd00000004* ID_MODEL_FROM_DATABASE=RapidFire OC-3139/3140 Token-Ring 16/4 PCI Adapter (OC-3139/3140 RapidFire Token-Ring 16/4 Adapter) pci:v0000108Dd00000005* ID_MODEL_FROM_DATABASE=GoCard 3250 Token-Ring 16/4 CardBus PC Card pci:v0000108Dd00000006* ID_MODEL_FROM_DATABASE=OC-3530 RapidFire Token-Ring 100 pci:v0000108Dd00000007* ID_MODEL_FROM_DATABASE=RapidFire 3141 Token-Ring 16/4 PCI Fiber Adapter pci:v0000108Dd00000007sv0000108Dsd00000007* ID_MODEL_FROM_DATABASE=RapidFire 3141 Token-Ring 16/4 PCI Fiber Adapter (OC-3141 RapidFire Token-Ring 16/4 Adapter) pci:v0000108Dd00000008* ID_MODEL_FROM_DATABASE=RapidFire 3540 HSTR 100/16/4 PCI Adapter pci:v0000108Dd00000008sv0000108Dsd00000008* ID_MODEL_FROM_DATABASE=RapidFire 3540 HSTR 100/16/4 PCI Adapter (OC-3540 RapidFire HSTR 100/16/4 Adapter) pci:v0000108Dd00000011* ID_MODEL_FROM_DATABASE=OC-2315 pci:v0000108Dd00000012* ID_MODEL_FROM_DATABASE=OC-2325 pci:v0000108Dd00000013* ID_MODEL_FROM_DATABASE=OC-2183/2185 pci:v0000108Dd00000014* ID_MODEL_FROM_DATABASE=OC-2326 pci:v0000108Dd00000019* ID_MODEL_FROM_DATABASE=OC-2327/2250 10/100 Ethernet Adapter pci:v0000108Dd00000019sv0000108Dsd00000016* ID_MODEL_FROM_DATABASE=OC-2327/2250 10/100 Ethernet Adapter (OC-2327 Rapidfire 10/100 Ethernet Adapter) pci:v0000108Dd00000019sv0000108Dsd00000017* ID_MODEL_FROM_DATABASE=OC-2327/2250 10/100 Ethernet Adapter (OC-2250 GoCard 10/100 Ethernet Adapter) pci:v0000108Dd00000021* ID_MODEL_FROM_DATABASE=OC-6151/6152 [RapidFire ATM 155] pci:v0000108Dd00000022* ID_MODEL_FROM_DATABASE=ATM Adapter pci:v0000108E* ID_VENDOR_FROM_DATABASE=Oracle/SUN pci:v0000108Ed00000001* ID_MODEL_FROM_DATABASE=EBUS pci:v0000108Ed00001000* ID_MODEL_FROM_DATABASE=EBUS pci:v0000108Ed00001001* ID_MODEL_FROM_DATABASE=Happy Meal 10/100 Ethernet [hme] pci:v0000108Ed00001100* ID_MODEL_FROM_DATABASE=RIO EBUS pci:v0000108Ed00001100sv0000108Esd00001100* ID_MODEL_FROM_DATABASE=RIO EBUS (on Blade 100 motherboard) pci:v0000108Ed00001101* ID_MODEL_FROM_DATABASE=RIO 10/100 Ethernet [eri] pci:v0000108Ed00001101sv0000108Esd00001101* ID_MODEL_FROM_DATABASE=RIO 10/100 Ethernet [eri] (RIO GEM on Blade 100 motherboard) pci:v0000108Ed00001102* ID_MODEL_FROM_DATABASE=RIO 1394 pci:v0000108Ed00001102sv0000108Esd00001102* ID_MODEL_FROM_DATABASE=RIO 1394 (on Blade 100 motherboard) pci:v0000108Ed00001103* ID_MODEL_FROM_DATABASE=RIO USB pci:v0000108Ed00001103sv0000108Esd00001103* ID_MODEL_FROM_DATABASE=RIO USB (on Blade 100 motherboard) pci:v0000108Ed00001647* ID_MODEL_FROM_DATABASE=Broadcom 570x 10/100/1000 Ethernet [bge] pci:v0000108Ed00001648* ID_MODEL_FROM_DATABASE=Broadcom 570x 10/100/1000 Ethernet [bge] pci:v0000108Ed000016A7* ID_MODEL_FROM_DATABASE=Broadcom 570x 10/100/1000 Ethernet [bge] pci:v0000108Ed000016A8* ID_MODEL_FROM_DATABASE=Broadcom 570x 10/100/1000 Ethernet [bge] pci:v0000108Ed00002BAD* ID_MODEL_FROM_DATABASE=GEM 10/100/1000 Ethernet [ge] pci:v0000108Ed00005000* ID_MODEL_FROM_DATABASE=Simba Advanced PCI Bridge pci:v0000108Ed00005000sv0000108Esd00005000* ID_MODEL_FROM_DATABASE=Simba Advanced PCI Bridge (Netra AX1105-500) pci:v0000108Ed00005043* ID_MODEL_FROM_DATABASE=SunPCI Co-processor pci:v0000108Ed00005CA0* ID_MODEL_FROM_DATABASE=Crypto Accelerator 6000 [mca] pci:v0000108Ed00006300* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006301* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006302* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006303* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006310* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006311* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006312* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006313* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006320* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006323* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006330* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006331* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006332* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006333* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006340* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006343* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006350* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006353* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed00006722* ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] pci:v0000108Ed0000676E* ID_MODEL_FROM_DATABASE=SunPCiIII pci:v0000108Ed00007063* ID_MODEL_FROM_DATABASE=SunPCiII / SunPCiIIpro pci:v0000108Ed00008000* ID_MODEL_FROM_DATABASE=Psycho PCI Bus Module pci:v0000108Ed00008001* ID_MODEL_FROM_DATABASE=Schizo PCI Bus Module pci:v0000108Ed00008002* ID_MODEL_FROM_DATABASE=Schizo+ PCI Bus Module pci:v0000108Ed000080F0* ID_MODEL_FROM_DATABASE=PCIe switch [px] pci:v0000108Ed000080F8* ID_MODEL_FROM_DATABASE=PCIe switch [px] pci:v0000108Ed00009010* ID_MODEL_FROM_DATABASE=PCIe/PCI bridge switch [pxb_plx] pci:v0000108Ed00009020* ID_MODEL_FROM_DATABASE=PCIe/PCI bridge switch [pxb_plx] pci:v0000108Ed00009102* ID_MODEL_FROM_DATABASE=Davicom Fast Ethernet driver for Davicom DM9102A [dmfe] pci:v0000108Ed0000A000* ID_MODEL_FROM_DATABASE=Psycho UPA-PCI Bus Module [pcipsy] pci:v0000108Ed0000A001* ID_MODEL_FROM_DATABASE=Psycho UPA-PCI Bus Module [pcipsy] pci:v0000108Ed0000A001sv0000108Esd0000A001* ID_MODEL_FROM_DATABASE=Psycho UPA-PCI Bus Module [pcipsy] (Ultra IIe on Blade 100 motherboard) pci:v0000108Ed0000A801* ID_MODEL_FROM_DATABASE=Schizo Fireplane-PCI bus bridge module [pcisch] pci:v0000108Ed0000AAAA* ID_MODEL_FROM_DATABASE=Multithreaded Shared 10GbE Ethernet Network Controller pci:v0000108Ed0000ABBA* ID_MODEL_FROM_DATABASE=Cassini 10/100/1000 pci:v0000108Ed0000ABCD* ID_MODEL_FROM_DATABASE=Multithreaded 10-Gigabit Ethernet Network Controller pci:v0000108Ed0000C416* ID_MODEL_FROM_DATABASE=Sun Fire System/System Controller Interface chip [sbbc] pci:v0000108F* ID_VENDOR_FROM_DATABASE=Systemsoft pci:v00001090* ID_VENDOR_FROM_DATABASE=Compro Computer Services, Inc. pci:v00001090d00004610* ID_MODEL_FROM_DATABASE=PCI RTOM pci:v00001090d00004620* ID_MODEL_FROM_DATABASE=GPIO HSD pci:v00001091* ID_VENDOR_FROM_DATABASE=Intergraph Corporation pci:v00001091d00000020* ID_MODEL_FROM_DATABASE=3D graphics processor pci:v00001091d00000021* ID_MODEL_FROM_DATABASE=3D graphics processor w/Texturing pci:v00001091d00000040* ID_MODEL_FROM_DATABASE=3D graphics frame buffer pci:v00001091d00000041* ID_MODEL_FROM_DATABASE=3D graphics frame buffer pci:v00001091d00000060* ID_MODEL_FROM_DATABASE=Proprietary bus bridge pci:v00001091d000000E4* ID_MODEL_FROM_DATABASE=Powerstorm 4D50T pci:v00001091d00000720* ID_MODEL_FROM_DATABASE=Motion JPEG codec pci:v00001091d00000780* ID_MODEL_FROM_DATABASE=Intense3D Wildcat 3410 (MSMT496) pci:v00001091d000007A0* ID_MODEL_FROM_DATABASE=Sun Expert3D-Lite Graphics Accelerator pci:v00001091d00001091* ID_MODEL_FROM_DATABASE=Sun Expert3D Graphics Accelerator pci:v00001092* ID_VENDOR_FROM_DATABASE=Diamond Multimedia Systems pci:v00001092d00000028* ID_MODEL_FROM_DATABASE=Viper V770 pci:v00001092d00000028sv00001092sd00004A00* ID_MODEL_FROM_DATABASE=Viper V770 (32MB) pci:v00001092d000000A0* ID_MODEL_FROM_DATABASE=Speedstar Pro SE pci:v00001092d000000A8* ID_MODEL_FROM_DATABASE=Speedstar 64 pci:v00001092d00000550* ID_MODEL_FROM_DATABASE=Viper V550 pci:v00001092d000008D4* ID_MODEL_FROM_DATABASE=Supra 2260 Modem pci:v00001092d0000094C* ID_MODEL_FROM_DATABASE=SupraExpress 56i Pro pci:v00001092d00001001* ID_MODEL_FROM_DATABASE=Video Crunch It 1001 capture card pci:v00001092d00001092* ID_MODEL_FROM_DATABASE=Viper V330 pci:v00001092d00006120* ID_MODEL_FROM_DATABASE=Maximum DVD pci:v00001092d00008810* ID_MODEL_FROM_DATABASE=Stealth SE pci:v00001092d00008811* ID_MODEL_FROM_DATABASE=Stealth 64/SE pci:v00001092d00008880* ID_MODEL_FROM_DATABASE=Stealth pci:v00001092d00008881* ID_MODEL_FROM_DATABASE=Stealth pci:v00001092d000088B0* ID_MODEL_FROM_DATABASE=Stealth 64 pci:v00001092d000088B1* ID_MODEL_FROM_DATABASE=Stealth 64 pci:v00001092d000088C0* ID_MODEL_FROM_DATABASE=Stealth 64 pci:v00001092d000088C1* ID_MODEL_FROM_DATABASE=Stealth 64 pci:v00001092d000088D0* ID_MODEL_FROM_DATABASE=Stealth 64 pci:v00001092d000088D1* ID_MODEL_FROM_DATABASE=Stealth 64 pci:v00001092d000088F0* ID_MODEL_FROM_DATABASE=Stealth 64 pci:v00001092d000088F1* ID_MODEL_FROM_DATABASE=Stealth 64 pci:v00001092d00009999* ID_MODEL_FROM_DATABASE=DMD-I0928-1 "Monster sound" sound chip pci:v00001093* ID_VENDOR_FROM_DATABASE=National Instruments pci:v00001093d00000160* ID_MODEL_FROM_DATABASE=PCI-DIO-96 pci:v00001093d00000162* ID_MODEL_FROM_DATABASE=PCI-MIO-16XE-50 pci:v00001093d00000FE1* ID_MODEL_FROM_DATABASE=PXI-8320 pci:v00001093d00001150* ID_MODEL_FROM_DATABASE=PCI-6533 (PCI-DIO-32HS) pci:v00001093d00001170* ID_MODEL_FROM_DATABASE=PCI-MIO-16XE-10 pci:v00001093d00001180* ID_MODEL_FROM_DATABASE=PCI-MIO-16E-1 pci:v00001093d00001190* ID_MODEL_FROM_DATABASE=PCI-MIO-16E-4 pci:v00001093d000011B0* ID_MODEL_FROM_DATABASE=PXI-6070E pci:v00001093d000011C0* ID_MODEL_FROM_DATABASE=PXI-6040E pci:v00001093d000011D0* ID_MODEL_FROM_DATABASE=PXI-6030E pci:v00001093d00001270* ID_MODEL_FROM_DATABASE=PCI-6032E pci:v00001093d00001290* ID_MODEL_FROM_DATABASE=PCI-6704 pci:v00001093d000012B0* ID_MODEL_FROM_DATABASE=PCI-6534 pci:v00001093d00001310* ID_MODEL_FROM_DATABASE=PCI-6602 pci:v00001093d00001320* ID_MODEL_FROM_DATABASE=PXI-6533 pci:v00001093d00001330* ID_MODEL_FROM_DATABASE=PCI-6031E pci:v00001093d00001340* ID_MODEL_FROM_DATABASE=PCI-6033E pci:v00001093d00001350* ID_MODEL_FROM_DATABASE=PCI-6071E pci:v00001093d00001360* ID_MODEL_FROM_DATABASE=PXI-6602 pci:v00001093d000013C0* ID_MODEL_FROM_DATABASE=PXI-6508 pci:v00001093d00001490* ID_MODEL_FROM_DATABASE=PXI-6534 pci:v00001093d000014E0* ID_MODEL_FROM_DATABASE=PCI-6110 pci:v00001093d000014F0* ID_MODEL_FROM_DATABASE=PCI-6111 pci:v00001093d00001580* ID_MODEL_FROM_DATABASE=PXI-6031E pci:v00001093d000015B0* ID_MODEL_FROM_DATABASE=PXI-6071E pci:v00001093d00001710* ID_MODEL_FROM_DATABASE=PXI-6509 pci:v00001093d000017C0* ID_MODEL_FROM_DATABASE=PXI-5690 pci:v00001093d000017D0* ID_MODEL_FROM_DATABASE=PCI-6503 pci:v00001093d00001870* ID_MODEL_FROM_DATABASE=PCI-6713 pci:v00001093d00001880* ID_MODEL_FROM_DATABASE=PCI-6711 pci:v00001093d000018B0* ID_MODEL_FROM_DATABASE=PCI-6052E pci:v00001093d000018C0* ID_MODEL_FROM_DATABASE=PXI-6052E pci:v00001093d00001920* ID_MODEL_FROM_DATABASE=PXI-6704 pci:v00001093d00001930* ID_MODEL_FROM_DATABASE=PCI-6040E pci:v00001093d000019C0* ID_MODEL_FROM_DATABASE=PCI-4472 pci:v00001093d00001AA0* ID_MODEL_FROM_DATABASE=PXI-4110 pci:v00001093d00001AD0* ID_MODEL_FROM_DATABASE=PCI-6133 pci:v00001093d00001AE0* ID_MODEL_FROM_DATABASE=PXI-6133 pci:v00001093d00001E30* ID_MODEL_FROM_DATABASE=PCI-6624 pci:v00001093d00001E40* ID_MODEL_FROM_DATABASE=PXI-6624 pci:v00001093d00001E50* ID_MODEL_FROM_DATABASE=PXI-5404 pci:v00001093d00002410* ID_MODEL_FROM_DATABASE=PCI-6733 pci:v00001093d00002420* ID_MODEL_FROM_DATABASE=PXI-6733 pci:v00001093d00002430* ID_MODEL_FROM_DATABASE=PCI-6731 pci:v00001093d00002470* ID_MODEL_FROM_DATABASE=PCI-4474 pci:v00001093d000024A0* ID_MODEL_FROM_DATABASE=PCI-4065 pci:v00001093d000024B0* ID_MODEL_FROM_DATABASE=PXI-4200 pci:v00001093d000024F0* ID_MODEL_FROM_DATABASE=PXI-4472 pci:v00001093d00002510* ID_MODEL_FROM_DATABASE=PCI-4472 pci:v00001093d00002520* ID_MODEL_FROM_DATABASE=PCI-4474 pci:v00001093d000027A0* ID_MODEL_FROM_DATABASE=PCI-6123 pci:v00001093d000027B0* ID_MODEL_FROM_DATABASE=PXI-6123 pci:v00001093d00002880* ID_MODEL_FROM_DATABASE=DAQCard-6601 pci:v00001093d00002890* ID_MODEL_FROM_DATABASE=PCI-6036E pci:v00001093d000028A0* ID_MODEL_FROM_DATABASE=PXI-4461 pci:v00001093d000028B0* ID_MODEL_FROM_DATABASE=PCI-6013 pci:v00001093d000028C0* ID_MODEL_FROM_DATABASE=PCI-6014 pci:v00001093d000028D0* ID_MODEL_FROM_DATABASE=PCI-5122 pci:v00001093d000028E0* ID_MODEL_FROM_DATABASE=PXI-5122 pci:v00001093d000029F0* ID_MODEL_FROM_DATABASE=PXI-7334 pci:v00001093d00002A00* ID_MODEL_FROM_DATABASE=PXI-7344 pci:v00001093d00002A60* ID_MODEL_FROM_DATABASE=PCI-6023E pci:v00001093d00002A70* ID_MODEL_FROM_DATABASE=PCI-6024E pci:v00001093d00002A80* ID_MODEL_FROM_DATABASE=PCI-6025E pci:v00001093d00002AB0* ID_MODEL_FROM_DATABASE=PXI-6025E pci:v00001093d00002B10* ID_MODEL_FROM_DATABASE=PXI-6527 pci:v00001093d00002B20* ID_MODEL_FROM_DATABASE=PCI-6527 pci:v00001093d00002B80* ID_MODEL_FROM_DATABASE=PXI-6713 pci:v00001093d00002B90* ID_MODEL_FROM_DATABASE=PXI-6711 pci:v00001093d00002C60* ID_MODEL_FROM_DATABASE=PCI-6601 pci:v00001093d00002C70* ID_MODEL_FROM_DATABASE=PXI-6601 pci:v00001093d00002C80* ID_MODEL_FROM_DATABASE=PCI-6035E pci:v00001093d00002C90* ID_MODEL_FROM_DATABASE=PCI-6703 pci:v00001093d00002CA0* ID_MODEL_FROM_DATABASE=PCI-6034E pci:v00001093d00002CB0* ID_MODEL_FROM_DATABASE=PCI-7344 pci:v00001093d00002CC0* ID_MODEL_FROM_DATABASE=PXI-6608 pci:v00001093d00002D20* ID_MODEL_FROM_DATABASE=PXI-5600 pci:v00001093d00002DB0* ID_MODEL_FROM_DATABASE=PCI-6608 pci:v00001093d00002DC0* ID_MODEL_FROM_DATABASE=PCI-4070 pci:v00001093d00002DD0* ID_MODEL_FROM_DATABASE=PXI-4070 pci:v00001093d00002EB0* ID_MODEL_FROM_DATABASE=PXI-4472 pci:v00001093d00002EC0* ID_MODEL_FROM_DATABASE=PXI-6115 pci:v00001093d00002ED0* ID_MODEL_FROM_DATABASE=PCI-6115 pci:v00001093d00002EE0* ID_MODEL_FROM_DATABASE=PXI-6120 pci:v00001093d00002EF0* ID_MODEL_FROM_DATABASE=PCI-6120 pci:v00001093d00002FD1* ID_MODEL_FROM_DATABASE=PCI-7334 pci:v00001093d00002FD2* ID_MODEL_FROM_DATABASE=PCI-7350 pci:v00001093d00002FD3* ID_MODEL_FROM_DATABASE=PCI-7342 pci:v00001093d00002FD5* ID_MODEL_FROM_DATABASE=PXI-7350 pci:v00001093d00002FD6* ID_MODEL_FROM_DATABASE=PXI-7342 pci:v00001093d00007003* ID_MODEL_FROM_DATABASE=PCI-6551 pci:v00001093d00007004* ID_MODEL_FROM_DATABASE=PXI-6551 pci:v00001093d0000700B* ID_MODEL_FROM_DATABASE=PXI-5421 pci:v00001093d0000700C* ID_MODEL_FROM_DATABASE=PCI-5421 pci:v00001093d0000701A* ID_MODEL_FROM_DATABASE=VXIpc-87xB pci:v00001093d0000701B* ID_MODEL_FROM_DATABASE=VXIpc-770 pci:v00001093d00007023* ID_MODEL_FROM_DATABASE=PXI-2593 pci:v00001093d00007027* ID_MODEL_FROM_DATABASE=PCI-MXI-2 Universal pci:v00001093d0000702C* ID_MODEL_FROM_DATABASE=PXI-7831R pci:v00001093d0000702D* ID_MODEL_FROM_DATABASE=PCI-7831R pci:v00001093d0000702E* ID_MODEL_FROM_DATABASE=PXI-7811R pci:v00001093d0000702F* ID_MODEL_FROM_DATABASE=PCI-7811R pci:v00001093d00007030* ID_MODEL_FROM_DATABASE=PCI-CAN (Series 2) pci:v00001093d00007031* ID_MODEL_FROM_DATABASE=PCI-CAN/2 (Series 2) pci:v00001093d00007032* ID_MODEL_FROM_DATABASE=PCI-CAN/LS (Series 2) pci:v00001093d00007033* ID_MODEL_FROM_DATABASE=PCI-CAN/LS2 (Series 2) pci:v00001093d00007034* ID_MODEL_FROM_DATABASE=PCI-CAN/DS (Series 2) pci:v00001093d00007035* ID_MODEL_FROM_DATABASE=PXI-8460 (Series 2, 1 port) pci:v00001093d00007036* ID_MODEL_FROM_DATABASE=PXI-8460 (Series 2, 2 ports) pci:v00001093d00007037* ID_MODEL_FROM_DATABASE=PXI-8461 (Series 2, 1 port) pci:v00001093d00007038* ID_MODEL_FROM_DATABASE=PXI-8461 (Series 2, 2 ports) pci:v00001093d00007039* ID_MODEL_FROM_DATABASE=PXI-8462 (Series 2) pci:v00001093d0000703F* ID_MODEL_FROM_DATABASE=PXI-2566 pci:v00001093d00007040* ID_MODEL_FROM_DATABASE=PXI-2567 pci:v00001093d00007044* ID_MODEL_FROM_DATABASE=MXI-4 Connection Monitor pci:v00001093d00007047* ID_MODEL_FROM_DATABASE=PXI-6653 pci:v00001093d0000704C* ID_MODEL_FROM_DATABASE=PXI-2530 pci:v00001093d0000704F* ID_MODEL_FROM_DATABASE=PXI-4220 pci:v00001093d00007050* ID_MODEL_FROM_DATABASE=PXI-4204 pci:v00001093d00007055* ID_MODEL_FROM_DATABASE=PXI-7830R pci:v00001093d00007056* ID_MODEL_FROM_DATABASE=PCI-7830R pci:v00001093d0000705A* ID_MODEL_FROM_DATABASE=PCI-CAN/XS (Series 2) pci:v00001093d0000705B* ID_MODEL_FROM_DATABASE=PCI-CAN/XS2 (Series 2) pci:v00001093d0000705C* ID_MODEL_FROM_DATABASE=PXI-8464 (Series 2, 1 port) pci:v00001093d0000705D* ID_MODEL_FROM_DATABASE=PXI-8464 (Series 2, 2 ports) pci:v00001093d0000705E* ID_MODEL_FROM_DATABASE=cRIO-9102 pci:v00001093d00007060* ID_MODEL_FROM_DATABASE=PXI-5610 pci:v00001093d00007064* ID_MODEL_FROM_DATABASE=PXI-1045 Trigger Routing Module pci:v00001093d00007065* ID_MODEL_FROM_DATABASE=PXI-6652 pci:v00001093d00007066* ID_MODEL_FROM_DATABASE=PXI-6651 pci:v00001093d00007067* ID_MODEL_FROM_DATABASE=PXI-2529 pci:v00001093d00007068* ID_MODEL_FROM_DATABASE=PCI-CAN/SW (Series 2) pci:v00001093d00007069* ID_MODEL_FROM_DATABASE=PCI-CAN/SW2 (Series 2) pci:v00001093d0000706A* ID_MODEL_FROM_DATABASE=PXI-8463 (Series 2, 1 port) pci:v00001093d0000706B* ID_MODEL_FROM_DATABASE=PXI-8463 (Series 2, 2 ports) pci:v00001093d00007073* ID_MODEL_FROM_DATABASE=PCI-6723 pci:v00001093d00007074* ID_MODEL_FROM_DATABASE=PXI-7833R pci:v00001093d00007075* ID_MODEL_FROM_DATABASE=PXI-6552 pci:v00001093d00007076* ID_MODEL_FROM_DATABASE=PCI-6552 pci:v00001093d0000707C* ID_MODEL_FROM_DATABASE=PXI-1428 pci:v00001093d0000707E* ID_MODEL_FROM_DATABASE=PXI-4462 pci:v00001093d00007080* ID_MODEL_FROM_DATABASE=PXI-8430/2 (RS-232) Interface pci:v00001093d00007081* ID_MODEL_FROM_DATABASE=PXI-8431/2 (RS-485) Interface pci:v00001093d00007083* ID_MODEL_FROM_DATABASE=PCI-7833R pci:v00001093d00007085* ID_MODEL_FROM_DATABASE=PCI-6509 pci:v00001093d00007086* ID_MODEL_FROM_DATABASE=PXI-6528 pci:v00001093d00007087* ID_MODEL_FROM_DATABASE=PCI-6515 pci:v00001093d00007088* ID_MODEL_FROM_DATABASE=PCI-6514 pci:v00001093d0000708C* ID_MODEL_FROM_DATABASE=PXI-2568 pci:v00001093d0000708D* ID_MODEL_FROM_DATABASE=PXI-2569 pci:v00001093d000070A9* ID_MODEL_FROM_DATABASE=PCI-6528 pci:v00001093d000070AA* ID_MODEL_FROM_DATABASE=PCI-6229 pci:v00001093d000070AB* ID_MODEL_FROM_DATABASE=PCI-6259 pci:v00001093d000070AC* ID_MODEL_FROM_DATABASE=PCI-6289 pci:v00001093d000070AD* ID_MODEL_FROM_DATABASE=PXI-6251 pci:v00001093d000070AE* ID_MODEL_FROM_DATABASE=PXI-6220 pci:v00001093d000070AF* ID_MODEL_FROM_DATABASE=PCI-6221 pci:v00001093d000070B0* ID_MODEL_FROM_DATABASE=PCI-6220 pci:v00001093d000070B1* ID_MODEL_FROM_DATABASE=PXI-6229 pci:v00001093d000070B2* ID_MODEL_FROM_DATABASE=PXI-6259 pci:v00001093d000070B3* ID_MODEL_FROM_DATABASE=PXI-6289 pci:v00001093d000070B4* ID_MODEL_FROM_DATABASE=PCI-6250 pci:v00001093d000070B5* ID_MODEL_FROM_DATABASE=PXI-6221 pci:v00001093d000070B6* ID_MODEL_FROM_DATABASE=PCI-6280 pci:v00001093d000070B7* ID_MODEL_FROM_DATABASE=PCI-6254 pci:v00001093d000070B8* ID_MODEL_FROM_DATABASE=PCI-6251 pci:v00001093d000070B9* ID_MODEL_FROM_DATABASE=PXI-6250 pci:v00001093d000070BA* ID_MODEL_FROM_DATABASE=PXI-6254 pci:v00001093d000070BB* ID_MODEL_FROM_DATABASE=PXI-6280 pci:v00001093d000070BC* ID_MODEL_FROM_DATABASE=PCI-6284 pci:v00001093d000070BD* ID_MODEL_FROM_DATABASE=PCI-6281 pci:v00001093d000070BE* ID_MODEL_FROM_DATABASE=PXI-6284 pci:v00001093d000070BF* ID_MODEL_FROM_DATABASE=PXI-6281 pci:v00001093d000070C0* ID_MODEL_FROM_DATABASE=PCI-6143 pci:v00001093d000070C3* ID_MODEL_FROM_DATABASE=PCI-6511 pci:v00001093d000070C4* ID_MODEL_FROM_DATABASE=PXI-7330 pci:v00001093d000070C5* ID_MODEL_FROM_DATABASE=PXI-7340 pci:v00001093d000070C6* ID_MODEL_FROM_DATABASE=PCI-7330 pci:v00001093d000070C7* ID_MODEL_FROM_DATABASE=PCI-7340 pci:v00001093d000070C8* ID_MODEL_FROM_DATABASE=PCI-6513 pci:v00001093d000070C9* ID_MODEL_FROM_DATABASE=PXI-6515 pci:v00001093d000070CA* ID_MODEL_FROM_DATABASE=PCI-1405 pci:v00001093d000070CC* ID_MODEL_FROM_DATABASE=PCI-6512 pci:v00001093d000070CD* ID_MODEL_FROM_DATABASE=PXI-6514 pci:v00001093d000070CE* ID_MODEL_FROM_DATABASE=PXI-1405 pci:v00001093d000070CF* ID_MODEL_FROM_DATABASE=PCIe-GPIB pci:v00001093d000070D0* ID_MODEL_FROM_DATABASE=PXI-2570 pci:v00001093d000070D1* ID_MODEL_FROM_DATABASE=PXI-6513 pci:v00001093d000070D2* ID_MODEL_FROM_DATABASE=PXI-6512 pci:v00001093d000070D3* ID_MODEL_FROM_DATABASE=PXI-6511 pci:v00001093d000070D4* ID_MODEL_FROM_DATABASE=PCI-6722 pci:v00001093d000070D6* ID_MODEL_FROM_DATABASE=PXI-4072 pci:v00001093d000070D7* ID_MODEL_FROM_DATABASE=PXI-6541 pci:v00001093d000070D8* ID_MODEL_FROM_DATABASE=PXI-6542 pci:v00001093d000070D9* ID_MODEL_FROM_DATABASE=PCI-6541 pci:v00001093d000070DA* ID_MODEL_FROM_DATABASE=PCI-6542 pci:v00001093d000070DB* ID_MODEL_FROM_DATABASE=PCI-8430/2 (RS-232) Interface pci:v00001093d000070DC* ID_MODEL_FROM_DATABASE=PCI-8431/2 (RS-485) Interface pci:v00001093d000070DD* ID_MODEL_FROM_DATABASE=PXI-8430/4 (RS-232) Interface pci:v00001093d000070DE* ID_MODEL_FROM_DATABASE=PXI-8431/4 (RS-485) Interface pci:v00001093d000070DF* ID_MODEL_FROM_DATABASE=PCI-8430/4 (RS-232) Interface pci:v00001093d000070E0* ID_MODEL_FROM_DATABASE=PCI-8431/4 (RS-485) Interface pci:v00001093d000070E1* ID_MODEL_FROM_DATABASE=PXI-2532 pci:v00001093d000070E2* ID_MODEL_FROM_DATABASE=PXI-8430/8 (RS-232) Interface pci:v00001093d000070E3* ID_MODEL_FROM_DATABASE=PXI-8431/8 (RS-485) Interface pci:v00001093d000070E4* ID_MODEL_FROM_DATABASE=PCI-8430/8 (RS-232) Interface pci:v00001093d000070E5* ID_MODEL_FROM_DATABASE=PCI-8431/8 (RS-485) Interface pci:v00001093d000070E6* ID_MODEL_FROM_DATABASE=PXI-8430/16 (RS-232) Interface pci:v00001093d000070E7* ID_MODEL_FROM_DATABASE=PCI-8430/16 (RS-232) Interface pci:v00001093d000070E8* ID_MODEL_FROM_DATABASE=PXI-8432/2 (Isolated RS-232) Interface pci:v00001093d000070E9* ID_MODEL_FROM_DATABASE=PXI-8433/2 (Isolated RS-485) Interface pci:v00001093d000070EA* ID_MODEL_FROM_DATABASE=PCI-8432/2 (Isolated RS-232) Interface pci:v00001093d000070EB* ID_MODEL_FROM_DATABASE=PCI-8433/2 (Isolated RS-485) Interface pci:v00001093d000070EC* ID_MODEL_FROM_DATABASE=PXI-8432/4 (Isolated RS-232) Interface pci:v00001093d000070ED* ID_MODEL_FROM_DATABASE=PXI-8433/4 (Isolated RS-485) Interface pci:v00001093d000070EE* ID_MODEL_FROM_DATABASE=PCI-8432/4 (Isolated RS-232) Interface pci:v00001093d000070EF* ID_MODEL_FROM_DATABASE=PCI-8433/4 (Isolated RS-485) Interface pci:v00001093d000070F0* ID_MODEL_FROM_DATABASE=PXI-5922 pci:v00001093d000070F1* ID_MODEL_FROM_DATABASE=PCI-5922 pci:v00001093d000070F2* ID_MODEL_FROM_DATABASE=PCI-6224 pci:v00001093d000070F3* ID_MODEL_FROM_DATABASE=PXI-6224 pci:v00001093d000070F6* ID_MODEL_FROM_DATABASE=cRIO-9101 pci:v00001093d000070F7* ID_MODEL_FROM_DATABASE=cRIO-9103 pci:v00001093d000070F8* ID_MODEL_FROM_DATABASE=cRIO-9104 pci:v00001093d000070FF* ID_MODEL_FROM_DATABASE=PXI-6723 pci:v00001093d00007100* ID_MODEL_FROM_DATABASE=PXI-6722 pci:v00001093d00007104* ID_MODEL_FROM_DATABASE=PCIx-1429 pci:v00001093d00007105* ID_MODEL_FROM_DATABASE=PCIe-1429 pci:v00001093d0000710A* ID_MODEL_FROM_DATABASE=PXI-4071 pci:v00001093d0000710D* ID_MODEL_FROM_DATABASE=PXI-6143 pci:v00001093d0000710E* ID_MODEL_FROM_DATABASE=PCIe-GPIB pci:v00001093d0000710F* ID_MODEL_FROM_DATABASE=PXI-5422 pci:v00001093d00007110* ID_MODEL_FROM_DATABASE=PCI-5422 pci:v00001093d00007111* ID_MODEL_FROM_DATABASE=PXI-5441 pci:v00001093d00007119* ID_MODEL_FROM_DATABASE=PXI-6561 pci:v00001093d0000711A* ID_MODEL_FROM_DATABASE=PXI-6562 pci:v00001093d0000711B* ID_MODEL_FROM_DATABASE=PCI-6561 pci:v00001093d0000711C* ID_MODEL_FROM_DATABASE=PCI-6562 pci:v00001093d00007120* ID_MODEL_FROM_DATABASE=PCI-7390 pci:v00001093d00007121* ID_MODEL_FROM_DATABASE=PXI-5122EX pci:v00001093d00007122* ID_MODEL_FROM_DATABASE=PCI-5122EX pci:v00001093d00007123* ID_MODEL_FROM_DATABASE=PXIe-5653 pci:v00001093d00007124* ID_MODEL_FROM_DATABASE=PCI-6510 pci:v00001093d00007125* ID_MODEL_FROM_DATABASE=PCI-6516 pci:v00001093d00007126* ID_MODEL_FROM_DATABASE=PCI-6517 pci:v00001093d00007127* ID_MODEL_FROM_DATABASE=PCI-6518 pci:v00001093d00007128* ID_MODEL_FROM_DATABASE=PCI-6519 pci:v00001093d00007137* ID_MODEL_FROM_DATABASE=PXI-2575 pci:v00001093d0000713C* ID_MODEL_FROM_DATABASE=PXI-2585 pci:v00001093d0000713D* ID_MODEL_FROM_DATABASE=PXI-2586 pci:v00001093d00007142* ID_MODEL_FROM_DATABASE=PXI-4224 pci:v00001093d00007144* ID_MODEL_FROM_DATABASE=PXI-5124 pci:v00001093d00007145* ID_MODEL_FROM_DATABASE=PCI-5124 pci:v00001093d00007146* ID_MODEL_FROM_DATABASE=PCI-6132 pci:v00001093d00007147* ID_MODEL_FROM_DATABASE=PXI-6132 pci:v00001093d00007148* ID_MODEL_FROM_DATABASE=PCI-6122 pci:v00001093d00007149* ID_MODEL_FROM_DATABASE=PXI-6122 pci:v00001093d0000714C* ID_MODEL_FROM_DATABASE=PXI-5114 pci:v00001093d0000714D* ID_MODEL_FROM_DATABASE=PCI-5114 pci:v00001093d00007150* ID_MODEL_FROM_DATABASE=PXI-2564 pci:v00001093d00007152* ID_MODEL_FROM_DATABASE=PCI-5640R pci:v00001093d00007156* ID_MODEL_FROM_DATABASE=PXI-1044 Trigger Routing Module pci:v00001093d0000715D* ID_MODEL_FROM_DATABASE=PCI-1426 pci:v00001093d00007167* ID_MODEL_FROM_DATABASE=PXI-5412 pci:v00001093d00007168* ID_MODEL_FROM_DATABASE=PCI-5412 pci:v00001093d0000716B* ID_MODEL_FROM_DATABASE=PCI-6230 pci:v00001093d0000716C* ID_MODEL_FROM_DATABASE=PCI-6225 pci:v00001093d0000716D* ID_MODEL_FROM_DATABASE=PXI-6225 pci:v00001093d0000716F* ID_MODEL_FROM_DATABASE=PCI-4461 pci:v00001093d00007170* ID_MODEL_FROM_DATABASE=PCI-4462 pci:v00001093d00007171* ID_MODEL_FROM_DATABASE=PCI-6010 pci:v00001093d00007174* ID_MODEL_FROM_DATABASE=PXI-8360 pci:v00001093d00007177* ID_MODEL_FROM_DATABASE=PXI-6230 pci:v00001093d0000717D* ID_MODEL_FROM_DATABASE=PCIe-6251 pci:v00001093d0000717F* ID_MODEL_FROM_DATABASE=PCIe-6259 pci:v00001093d00007187* ID_MODEL_FROM_DATABASE=PCI-1410 pci:v00001093d0000718B* ID_MODEL_FROM_DATABASE=PCI-6521 pci:v00001093d0000718C* ID_MODEL_FROM_DATABASE=PXI-6521 pci:v00001093d00007191* ID_MODEL_FROM_DATABASE=PCI-6154 pci:v00001093d00007193* ID_MODEL_FROM_DATABASE=PXI-7813R pci:v00001093d00007194* ID_MODEL_FROM_DATABASE=PCI-7813R pci:v00001093d00007195* ID_MODEL_FROM_DATABASE=PCI-8254R pci:v00001093d00007197* ID_MODEL_FROM_DATABASE=PXI-5402 pci:v00001093d00007198* ID_MODEL_FROM_DATABASE=PCI-5402 pci:v00001093d0000719F* ID_MODEL_FROM_DATABASE=PCIe-6535 pci:v00001093d000071A0* ID_MODEL_FROM_DATABASE=PCIe-6536 pci:v00001093d000071A3* ID_MODEL_FROM_DATABASE=PXI-5650 pci:v00001093d000071A4* ID_MODEL_FROM_DATABASE=PXI-5652 pci:v00001093d000071A5* ID_MODEL_FROM_DATABASE=PXI-2594 pci:v00001093d000071A7* ID_MODEL_FROM_DATABASE=PXI-2595 pci:v00001093d000071A9* ID_MODEL_FROM_DATABASE=PXI-2596 pci:v00001093d000071AA* ID_MODEL_FROM_DATABASE=PXI-2597 pci:v00001093d000071AB* ID_MODEL_FROM_DATABASE=PXI-2598 pci:v00001093d000071AC* ID_MODEL_FROM_DATABASE=PXI-2599 pci:v00001093d000071AD* ID_MODEL_FROM_DATABASE=PCI-GPIB+ pci:v00001093d000071AE* ID_MODEL_FROM_DATABASE=PCIe-1430 pci:v00001093d000071B7* ID_MODEL_FROM_DATABASE=PXI-1056 Trigger Routing Module pci:v00001093d000071B8* ID_MODEL_FROM_DATABASE=PXI-1045 Trigger Routing Module pci:v00001093d000071B9* ID_MODEL_FROM_DATABASE=PXI-1044 Trigger Routing Module pci:v00001093d000071BB* ID_MODEL_FROM_DATABASE=PXI-2584 pci:v00001093d000071BC* ID_MODEL_FROM_DATABASE=PCI-6221 (37-pin) pci:v00001093d000071BF* ID_MODEL_FROM_DATABASE=PCIe-1427 pci:v00001093d000071C5* ID_MODEL_FROM_DATABASE=PCI-6520 pci:v00001093d000071C6* ID_MODEL_FROM_DATABASE=PXI-2576 pci:v00001093d000071C7* ID_MODEL_FROM_DATABASE=cRIO-9072 pci:v00001093d000071DC* ID_MODEL_FROM_DATABASE=PCI-1588 pci:v00001093d000071E0* ID_MODEL_FROM_DATABASE=PCI-6255 pci:v00001093d000071E1* ID_MODEL_FROM_DATABASE=PXI-6255 pci:v00001093d000071E2* ID_MODEL_FROM_DATABASE=PXI-5406 pci:v00001093d000071E3* ID_MODEL_FROM_DATABASE=PCI-5406 pci:v00001093d000071FC* ID_MODEL_FROM_DATABASE=PXI-4022 pci:v00001093d00007209* ID_MODEL_FROM_DATABASE=PCI-6233 pci:v00001093d0000720A* ID_MODEL_FROM_DATABASE=PXI-6233 pci:v00001093d0000720B* ID_MODEL_FROM_DATABASE=PCI-6238 pci:v00001093d0000720C* ID_MODEL_FROM_DATABASE=PXI-6238 pci:v00001093d00007260* ID_MODEL_FROM_DATABASE=PXI-5142 pci:v00001093d00007261* ID_MODEL_FROM_DATABASE=PCI-5142 pci:v00001093d0000726D* ID_MODEL_FROM_DATABASE=PXI-5651 pci:v00001093d00007273* ID_MODEL_FROM_DATABASE=PXI-4461 pci:v00001093d00007274* ID_MODEL_FROM_DATABASE=PXI-4462 pci:v00001093d00007279* ID_MODEL_FROM_DATABASE=PCI-6232 pci:v00001093d0000727A* ID_MODEL_FROM_DATABASE=PXI-6232 pci:v00001093d0000727B* ID_MODEL_FROM_DATABASE=PCI-6239 pci:v00001093d0000727C* ID_MODEL_FROM_DATABASE=PXI-6239 pci:v00001093d0000727E* ID_MODEL_FROM_DATABASE=SMBus Controller pci:v00001093d0000727Esv00001093sd000075AC* ID_MODEL_FROM_DATABASE=SMBus Controller (PXIe-8388) pci:v00001093d0000727Esv00001093sd000075AD* ID_MODEL_FROM_DATABASE=SMBus Controller (PXIe-8389) pci:v00001093d0000727Esv00001093sd00007650* ID_MODEL_FROM_DATABASE=SMBus Controller (PXIe-8381) pci:v00001093d0000727Esv00001093sd00008360* ID_MODEL_FROM_DATABASE=SMBus Controller (PXIe-8360) pci:v00001093d0000727Esv00001093sd00008370* ID_MODEL_FROM_DATABASE=SMBus Controller (PXIe-8370) pci:v00001093d0000727Esv00001093sd00008375* ID_MODEL_FROM_DATABASE=SMBus Controller (PXIe-8375) pci:v00001093d00007281* ID_MODEL_FROM_DATABASE=PCI-6236 pci:v00001093d00007282* ID_MODEL_FROM_DATABASE=PXI-6236 pci:v00001093d00007283* ID_MODEL_FROM_DATABASE=PXI-2554 pci:v00001093d00007288* ID_MODEL_FROM_DATABASE=PXIe-5611 pci:v00001093d00007293* ID_MODEL_FROM_DATABASE=PCIe-8255R pci:v00001093d0000729D* ID_MODEL_FROM_DATABASE=cRIO-9074 pci:v00001093d000072A4* ID_MODEL_FROM_DATABASE=PCIe-4065 pci:v00001093d000072A7* ID_MODEL_FROM_DATABASE=PCIe-6537 pci:v00001093d000072A8* ID_MODEL_FROM_DATABASE=PXI-5152 pci:v00001093d000072A9* ID_MODEL_FROM_DATABASE=PCI-5152 pci:v00001093d000072AA* ID_MODEL_FROM_DATABASE=PXI-5105 pci:v00001093d000072AB* ID_MODEL_FROM_DATABASE=PCI-5105 pci:v00001093d000072B8* ID_MODEL_FROM_DATABASE=PXI-6682 pci:v00001093d000072D0* ID_MODEL_FROM_DATABASE=PXI-2545 pci:v00001093d000072D1* ID_MODEL_FROM_DATABASE=PXI-2546 pci:v00001093d000072D2* ID_MODEL_FROM_DATABASE=PXI-2547 pci:v00001093d000072D3* ID_MODEL_FROM_DATABASE=PXI-2548 pci:v00001093d000072D4* ID_MODEL_FROM_DATABASE=PXI-2549 pci:v00001093d000072D5* ID_MODEL_FROM_DATABASE=PXI-2555 pci:v00001093d000072D6* ID_MODEL_FROM_DATABASE=PXI-2556 pci:v00001093d000072D7* ID_MODEL_FROM_DATABASE=PXI-2557 pci:v00001093d000072D8* ID_MODEL_FROM_DATABASE=PXI-2558 pci:v00001093d000072D9* ID_MODEL_FROM_DATABASE=PXI-2559 pci:v00001093d000072E8* ID_MODEL_FROM_DATABASE=PXIe-6251 pci:v00001093d000072E9* ID_MODEL_FROM_DATABASE=PXIe-6259 pci:v00001093d000072EF* ID_MODEL_FROM_DATABASE=PXI-4498 pci:v00001093d000072F0* ID_MODEL_FROM_DATABASE=PXI-4496 pci:v00001093d000072FB* ID_MODEL_FROM_DATABASE=PXIe-6672 pci:v00001093d0000730E* ID_MODEL_FROM_DATABASE=PXI-4130 pci:v00001093d0000730F* ID_MODEL_FROM_DATABASE=PXI-5922EX pci:v00001093d00007310* ID_MODEL_FROM_DATABASE=PCI-5922EX pci:v00001093d0000731C* ID_MODEL_FROM_DATABASE=PXI-2535 pci:v00001093d0000731D* ID_MODEL_FROM_DATABASE=PXI-2536 pci:v00001093d00007322* ID_MODEL_FROM_DATABASE=PXIe-6124 pci:v00001093d00007327* ID_MODEL_FROM_DATABASE=PXI-6529 pci:v00001093d0000732C* ID_MODEL_FROM_DATABASE=VXI-8360T pci:v00001093d00007331* ID_MODEL_FROM_DATABASE=PXIe-5602 pci:v00001093d00007332* ID_MODEL_FROM_DATABASE=PXIe-5601 pci:v00001093d00007333* ID_MODEL_FROM_DATABASE=PXI-5900 pci:v00001093d00007335* ID_MODEL_FROM_DATABASE=PXI-2533 pci:v00001093d00007336* ID_MODEL_FROM_DATABASE=PXI-2534 pci:v00001093d00007342* ID_MODEL_FROM_DATABASE=PXI-4461 pci:v00001093d00007349* ID_MODEL_FROM_DATABASE=PXI-5154 pci:v00001093d0000734A* ID_MODEL_FROM_DATABASE=PCI-5154 pci:v00001093d00007357* ID_MODEL_FROM_DATABASE=PXI-4065 pci:v00001093d00007359* ID_MODEL_FROM_DATABASE=PXI-4495 pci:v00001093d00007370* ID_MODEL_FROM_DATABASE=PXI-4461 pci:v00001093d00007373* ID_MODEL_FROM_DATABASE=sbRIO-9601 pci:v00001093d00007374* ID_MODEL_FROM_DATABASE=IOtech-9601 pci:v00001093d00007375* ID_MODEL_FROM_DATABASE=sbRIO-9602 pci:v00001093d00007378* ID_MODEL_FROM_DATABASE=sbRIO-9641 pci:v00001093d0000737D* ID_MODEL_FROM_DATABASE=PXI-5124EX pci:v00001093d00007384* ID_MODEL_FROM_DATABASE=PXI-7851R pci:v00001093d00007385* ID_MODEL_FROM_DATABASE=PXI-7852R pci:v00001093d00007386* ID_MODEL_FROM_DATABASE=PCIe-7851R pci:v00001093d00007387* ID_MODEL_FROM_DATABASE=PCIe-7852R pci:v00001093d00007390* ID_MODEL_FROM_DATABASE=PXI-7841R pci:v00001093d00007391* ID_MODEL_FROM_DATABASE=PXI-7842R pci:v00001093d00007392* ID_MODEL_FROM_DATABASE=PXI-7853R pci:v00001093d00007393* ID_MODEL_FROM_DATABASE=PCIe-7841R pci:v00001093d00007394* ID_MODEL_FROM_DATABASE=PCIe-7842R pci:v00001093d00007397* ID_MODEL_FROM_DATABASE=sbRIO-9611 pci:v00001093d00007398* ID_MODEL_FROM_DATABASE=sbRIO-9612 pci:v00001093d00007399* ID_MODEL_FROM_DATABASE=sbRIO-9631 pci:v00001093d0000739A* ID_MODEL_FROM_DATABASE=sbRIO-9632 pci:v00001093d0000739B* ID_MODEL_FROM_DATABASE=sbRIO-9642 pci:v00001093d000073A1* ID_MODEL_FROM_DATABASE=PXIe-4498 pci:v00001093d000073A2* ID_MODEL_FROM_DATABASE=PXIe-4496 pci:v00001093d000073A5* ID_MODEL_FROM_DATABASE=PXIe-5641R pci:v00001093d000073A7* ID_MODEL_FROM_DATABASE=PXI-8250 Chassis Monitor Module pci:v00001093d000073A8* ID_MODEL_FROM_DATABASE=PXI-8511 CAN/LS pci:v00001093d000073A9* ID_MODEL_FROM_DATABASE=PXI-8511 CAN/LS pci:v00001093d000073AA* ID_MODEL_FROM_DATABASE=PXI-8512 CAN/HS pci:v00001093d000073AB* ID_MODEL_FROM_DATABASE=PXI-8512 CAN/HS pci:v00001093d000073AC* ID_MODEL_FROM_DATABASE=PXI-8513 CAN/XS pci:v00001093d000073AD* ID_MODEL_FROM_DATABASE=PXI-8513 CAN/XS pci:v00001093d000073AF* ID_MODEL_FROM_DATABASE=PXI-8516 LIN pci:v00001093d000073B1* ID_MODEL_FROM_DATABASE=PXI-8517 FlexRay pci:v00001093d000073B2* ID_MODEL_FROM_DATABASE=PXI-8531 CANopen pci:v00001093d000073B3* ID_MODEL_FROM_DATABASE=PXI-8531 CANopen pci:v00001093d000073B4* ID_MODEL_FROM_DATABASE=PXI-8532 DeviceNet pci:v00001093d000073B5* ID_MODEL_FROM_DATABASE=PXI-8532 DeviceNet pci:v00001093d000073B6* ID_MODEL_FROM_DATABASE=PCI-8511 CAN/LS pci:v00001093d000073B7* ID_MODEL_FROM_DATABASE=PCI-8511 CAN/LS pci:v00001093d000073B8* ID_MODEL_FROM_DATABASE=PCI-8512 CAN/HS pci:v00001093d000073B9* ID_MODEL_FROM_DATABASE=PCI-8512 CAN/HS pci:v00001093d000073BA* ID_MODEL_FROM_DATABASE=PCI-8513 CAN/XS pci:v00001093d000073BB* ID_MODEL_FROM_DATABASE=PCI-8513 CAN/XS pci:v00001093d000073BD* ID_MODEL_FROM_DATABASE=PCI-8516 LIN pci:v00001093d000073BF* ID_MODEL_FROM_DATABASE=PCI-8517 FlexRay pci:v00001093d000073C0* ID_MODEL_FROM_DATABASE=PCI-8531 CANopen pci:v00001093d000073C1* ID_MODEL_FROM_DATABASE=PCI-8531 CANopen pci:v00001093d000073C2* ID_MODEL_FROM_DATABASE=PCI-8532 DeviceNet pci:v00001093d000073C3* ID_MODEL_FROM_DATABASE=PCI-8532 DeviceNet pci:v00001093d000073C5* ID_MODEL_FROM_DATABASE=PXIe-2527 pci:v00001093d000073C6* ID_MODEL_FROM_DATABASE=PXIe-2529 pci:v00001093d000073C8* ID_MODEL_FROM_DATABASE=PXIe-2530 pci:v00001093d000073C9* ID_MODEL_FROM_DATABASE=PXIe-2532 pci:v00001093d000073CA* ID_MODEL_FROM_DATABASE=PXIe-2569 pci:v00001093d000073CB* ID_MODEL_FROM_DATABASE=PXIe-2575 pci:v00001093d000073CC* ID_MODEL_FROM_DATABASE=PXIe-2593 pci:v00001093d000073D5* ID_MODEL_FROM_DATABASE=PXI-7951R pci:v00001093d000073D6* ID_MODEL_FROM_DATABASE=PXI-7952R pci:v00001093d000073D7* ID_MODEL_FROM_DATABASE=PXI-7953R pci:v00001093d000073E1* ID_MODEL_FROM_DATABASE=PXI-7854R pci:v00001093d000073EC* ID_MODEL_FROM_DATABASE=PXI-7954R pci:v00001093d000073ED* ID_MODEL_FROM_DATABASE=cRIO-9073 pci:v00001093d000073F0* ID_MODEL_FROM_DATABASE=PXI-5153 pci:v00001093d000073F1* ID_MODEL_FROM_DATABASE=PCI-5153 pci:v00001093d000073F4* ID_MODEL_FROM_DATABASE=PXI-2515 pci:v00001093d000073F6* ID_MODEL_FROM_DATABASE=cRIO-9111 pci:v00001093d000073F7* ID_MODEL_FROM_DATABASE=cRIO-9112 pci:v00001093d000073F8* ID_MODEL_FROM_DATABASE=cRIO-9113 pci:v00001093d000073F9* ID_MODEL_FROM_DATABASE=cRIO-9114 pci:v00001093d000073FA* ID_MODEL_FROM_DATABASE=cRIO-9116 pci:v00001093d000073FB* ID_MODEL_FROM_DATABASE=cRIO-9118 pci:v00001093d00007404* ID_MODEL_FROM_DATABASE=PXI-4132 pci:v00001093d00007405* ID_MODEL_FROM_DATABASE=PXIe-6674T pci:v00001093d00007406* ID_MODEL_FROM_DATABASE=PXIe-6674 pci:v00001093d0000740E* ID_MODEL_FROM_DATABASE=PCIe-8430/16 (RS-232) Interface pci:v00001093d0000740F* ID_MODEL_FROM_DATABASE=PCIe-8430/8 (RS-232) Interface pci:v00001093d00007410* ID_MODEL_FROM_DATABASE=PCIe-8431/16 (RS-485) Interface pci:v00001093d00007411* ID_MODEL_FROM_DATABASE=PCIe-8431/8 (RS-485) Interface pci:v00001093d00007414* ID_MODEL_FROM_DATABASE=PCIe-GPIB+ pci:v00001093d0000741C* ID_MODEL_FROM_DATABASE=PXI-5691 pci:v00001093d0000741D* ID_MODEL_FROM_DATABASE=PXI-5695 pci:v00001093d0000743C* ID_MODEL_FROM_DATABASE=CSC-3059 pci:v00001093d00007448* ID_MODEL_FROM_DATABASE=PXI-2510 pci:v00001093d00007454* ID_MODEL_FROM_DATABASE=PXI-2512 pci:v00001093d00007455* ID_MODEL_FROM_DATABASE=PXI-2514 pci:v00001093d00007456* ID_MODEL_FROM_DATABASE=PXIe-2512 pci:v00001093d00007457* ID_MODEL_FROM_DATABASE=PXIe-2514 pci:v00001093d0000745A* ID_MODEL_FROM_DATABASE=PXI-6682H pci:v00001093d0000745E* ID_MODEL_FROM_DATABASE=PXI-5153EX pci:v00001093d0000745F* ID_MODEL_FROM_DATABASE=PCI-5153EX pci:v00001093d00007460* ID_MODEL_FROM_DATABASE=PXI-5154EX pci:v00001093d00007461* ID_MODEL_FROM_DATABASE=PCI-5154EX pci:v00001093d0000746D* ID_MODEL_FROM_DATABASE=PXIe-5650 pci:v00001093d0000746E* ID_MODEL_FROM_DATABASE=PXIe-5651 pci:v00001093d0000746F* ID_MODEL_FROM_DATABASE=PXIe-5652 pci:v00001093d00007472* ID_MODEL_FROM_DATABASE=PXI-2800 pci:v00001093d00007495* ID_MODEL_FROM_DATABASE=PXIe-5603 pci:v00001093d00007497* ID_MODEL_FROM_DATABASE=PXIe-5605 pci:v00001093d000074AE* ID_MODEL_FROM_DATABASE=PXIe-2515 pci:v00001093d000074B4* ID_MODEL_FROM_DATABASE=PXI-2531 pci:v00001093d000074B5* ID_MODEL_FROM_DATABASE=PXIe-2531 pci:v00001093d000074C1* ID_MODEL_FROM_DATABASE=PXIe-8430/16 (RS-232) Interface pci:v00001093d000074C2* ID_MODEL_FROM_DATABASE=PXIe-8430/8 (RS-232) Interface pci:v00001093d000074C3* ID_MODEL_FROM_DATABASE=PXIe-8431/16 (RS-485) Interface pci:v00001093d000074C4* ID_MODEL_FROM_DATABASE=PXIe-8431/8 (RS-485) Interface pci:v00001093d000074D5* ID_MODEL_FROM_DATABASE=PXIe-5630 pci:v00001093d000074D9* ID_MODEL_FROM_DATABASE=PCIe-8432/2 (Isolated RS-232) Interface pci:v00001093d000074DA* ID_MODEL_FROM_DATABASE=PCIe-8433/2 (Isolated RS-485) Interface pci:v00001093d000074DB* ID_MODEL_FROM_DATABASE=PCIe-8432/4 (Isolated RS-232) Interface pci:v00001093d000074DC* ID_MODEL_FROM_DATABASE=PCIe-8433/4 (Isolated RS-485) Interface pci:v00001093d000074E8* ID_MODEL_FROM_DATABASE=NI 9148 pci:v00001093d00007515* ID_MODEL_FROM_DATABASE=PCIe-8430/2 (RS-232) Interface pci:v00001093d00007516* ID_MODEL_FROM_DATABASE=PCIe-8430/4 (RS-232) Interface pci:v00001093d00007517* ID_MODEL_FROM_DATABASE=PCIe-8431/2 (RS-485) Interface pci:v00001093d00007518* ID_MODEL_FROM_DATABASE=PCIe-8431/4 (RS-485) Interface pci:v00001093d0000751B* ID_MODEL_FROM_DATABASE=cRIO-9081 pci:v00001093d0000751C* ID_MODEL_FROM_DATABASE=cRIO-9082 pci:v00001093d00007528* ID_MODEL_FROM_DATABASE=PXIe-4497 pci:v00001093d00007529* ID_MODEL_FROM_DATABASE=PXIe-4499 pci:v00001093d0000752A* ID_MODEL_FROM_DATABASE=PXIe-4492 pci:v00001093d00007539* ID_MODEL_FROM_DATABASE=NI 9157 pci:v00001093d0000753A* ID_MODEL_FROM_DATABASE=NI 9159 pci:v00001093d00007598* ID_MODEL_FROM_DATABASE=PXI-2571 pci:v00001093d000075A4* ID_MODEL_FROM_DATABASE=PXI-4131A pci:v00001093d000075B1* ID_MODEL_FROM_DATABASE=PCIe-7854R pci:v00001093d000075BA* ID_MODEL_FROM_DATABASE=PXI-2543 pci:v00001093d000075BB* ID_MODEL_FROM_DATABASE=PXIe-2543 pci:v00001093d000075E5* ID_MODEL_FROM_DATABASE=PXI-6683 pci:v00001093d000075E6* ID_MODEL_FROM_DATABASE=PXI-6683H pci:v00001093d000075EF* ID_MODEL_FROM_DATABASE=PXIe-5632 pci:v00001093d0000761C* ID_MODEL_FROM_DATABASE=VXI-8360LT pci:v00001093d0000761F* ID_MODEL_FROM_DATABASE=PXI-2540 pci:v00001093d00007620* ID_MODEL_FROM_DATABASE=PXIe-2540 pci:v00001093d00007621* ID_MODEL_FROM_DATABASE=PXI-2541 pci:v00001093d00007622* ID_MODEL_FROM_DATABASE=PXIe-2541 pci:v00001093d00007626* ID_MODEL_FROM_DATABASE=NI 9154 pci:v00001093d00007627* ID_MODEL_FROM_DATABASE=NI 9155 pci:v00001093d00007638* ID_MODEL_FROM_DATABASE=PXI-2720 pci:v00001093d00007639* ID_MODEL_FROM_DATABASE=PXI-2722 pci:v00001093d0000763A* ID_MODEL_FROM_DATABASE=PXIe-2725 pci:v00001093d0000763B* ID_MODEL_FROM_DATABASE=PXIe-2727 pci:v00001093d0000763C* ID_MODEL_FROM_DATABASE=PXI-4465 pci:v00001093d0000764B* ID_MODEL_FROM_DATABASE=PXIe-2790 pci:v00001093d0000764C* ID_MODEL_FROM_DATABASE=PXI-2520 pci:v00001093d0000764D* ID_MODEL_FROM_DATABASE=PXI-2521 pci:v00001093d0000764E* ID_MODEL_FROM_DATABASE=PXI-2522 pci:v00001093d0000764F* ID_MODEL_FROM_DATABASE=PXI-2523 pci:v00001093d00007654* ID_MODEL_FROM_DATABASE=PXI-2796 pci:v00001093d00007655* ID_MODEL_FROM_DATABASE=PXI-2797 pci:v00001093d00007656* ID_MODEL_FROM_DATABASE=PXI-2798 pci:v00001093d00007657* ID_MODEL_FROM_DATABASE=PXI-2799 pci:v00001093d0000765D* ID_MODEL_FROM_DATABASE=PXI-2542 pci:v00001093d0000765E* ID_MODEL_FROM_DATABASE=PXIe-2542 pci:v00001093d0000765F* ID_MODEL_FROM_DATABASE=PXI-2544 pci:v00001093d00007660* ID_MODEL_FROM_DATABASE=PXIe-2544 pci:v00001093d0000766D* ID_MODEL_FROM_DATABASE=PCIe-6535B pci:v00001093d0000766E* ID_MODEL_FROM_DATABASE=PCIe-6536B pci:v00001093d0000766F* ID_MODEL_FROM_DATABASE=PCIe-6537B pci:v00001093d000076A3* ID_MODEL_FROM_DATABASE=PXIe-6535B pci:v00001093d000076A4* ID_MODEL_FROM_DATABASE=PXIe-6536B pci:v00001093d000076A5* ID_MODEL_FROM_DATABASE=PXIe-6537B pci:v00001093d0000783E* ID_MODEL_FROM_DATABASE=PXI-8368 pci:v00001093d00009020* ID_MODEL_FROM_DATABASE=PXI-2501 pci:v00001093d00009030* ID_MODEL_FROM_DATABASE=PXI-2503 pci:v00001093d00009040* ID_MODEL_FROM_DATABASE=PXI-2527 pci:v00001093d00009050* ID_MODEL_FROM_DATABASE=PXI-2565 pci:v00001093d00009060* ID_MODEL_FROM_DATABASE=PXI-2590 pci:v00001093d00009070* ID_MODEL_FROM_DATABASE=PXI-2591 pci:v00001093d00009080* ID_MODEL_FROM_DATABASE=PXI-2580 pci:v00001093d00009090* ID_MODEL_FROM_DATABASE=PCI-4021 pci:v00001093d000090A0* ID_MODEL_FROM_DATABASE=PXI-4021 pci:v00001093d0000A001* ID_MODEL_FROM_DATABASE=PCI-MXI-2 pci:v00001093d0000B001* ID_MODEL_FROM_DATABASE=PCI-1408 pci:v00001093d0000B011* ID_MODEL_FROM_DATABASE=PXI-1408 pci:v00001093d0000B021* ID_MODEL_FROM_DATABASE=PCI-1424 pci:v00001093d0000B022* ID_MODEL_FROM_DATABASE=PXI-1424 pci:v00001093d0000B031* ID_MODEL_FROM_DATABASE=PCI-1413 pci:v00001093d0000B041* ID_MODEL_FROM_DATABASE=PCI-1407 pci:v00001093d0000B051* ID_MODEL_FROM_DATABASE=PXI-1407 pci:v00001093d0000B061* ID_MODEL_FROM_DATABASE=PCI-1411 pci:v00001093d0000B071* ID_MODEL_FROM_DATABASE=PCI-1422 pci:v00001093d0000B081* ID_MODEL_FROM_DATABASE=PXI-1422 pci:v00001093d0000B091* ID_MODEL_FROM_DATABASE=PXI-1411 pci:v00001093d0000B0B1* ID_MODEL_FROM_DATABASE=PCI-1409 pci:v00001093d0000B0C1* ID_MODEL_FROM_DATABASE=PXI-1409 pci:v00001093d0000B0E1* ID_MODEL_FROM_DATABASE=PCI-1428 pci:v00001093d0000C4C4* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device pci:v00001093d0000C4C4sv00001093sd0000728A* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5421) pci:v00001093d0000C4C4sv00001093sd0000728B* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5442) pci:v00001093d0000C4C4sv00001093sd0000728D* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5451) pci:v00001093d0000C4C4sv00001093sd000072A2* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5122) pci:v00001093d0000C4C4sv00001093sd000072DA* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5422) pci:v00001093d0000C4C4sv00001093sd000072F7* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6535) pci:v00001093d0000C4C4sv00001093sd000072F8* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6536) pci:v00001093d0000C4C4sv00001093sd000072F9* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6537) pci:v00001093d0000C4C4sv00001093sd00007326* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6509) pci:v00001093d0000C4C4sv00001093sd0000736C* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4140) pci:v00001093d0000C4C4sv00001093sd0000738B* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5622) pci:v00001093d0000C4C4sv00001093sd000073C4* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5450) pci:v00001093d0000C4C4sv00001093sd000073C7* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6545) pci:v00001093d0000C4C4sv00001093sd000073D4* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6544) pci:v00001093d0000C4C4sv00001093sd00007425* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6320) pci:v00001093d0000C4C4sv00001093sd00007427* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6321) pci:v00001093d0000C4C4sv00001093sd00007428* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6323) pci:v00001093d0000C4C4sv00001093sd00007429* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6323) pci:v00001093d0000C4C4sv00001093sd0000742A* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6341) pci:v00001093d0000C4C4sv00001093sd0000742B* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6341) pci:v00001093d0000C4C4sv00001093sd0000742C* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6343) pci:v00001093d0000C4C4sv00001093sd0000742D* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6343) pci:v00001093d0000C4C4sv00001093sd0000742F* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6351) pci:v00001093d0000C4C4sv00001093sd00007431* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6353) pci:v00001093d0000C4C4sv00001093sd00007432* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6361) pci:v00001093d0000C4C4sv00001093sd00007433* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6361) pci:v00001093d0000C4C4sv00001093sd00007434* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6363) pci:v00001093d0000C4C4sv00001093sd00007435* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6363) pci:v00001093d0000C4C4sv00001093sd00007436* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6356) pci:v00001093d0000C4C4sv00001093sd00007437* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6358) pci:v00001093d0000C4C4sv00001093sd00007438* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6366) pci:v00001093d0000C4C4sv00001093sd00007439* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6368) pci:v00001093d0000C4C4sv00001093sd00007468* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5185) pci:v00001093d0000C4C4sv00001093sd00007469* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5186) pci:v00001093d0000C4C4sv00001093sd00007492* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4300) pci:v00001093d0000C4C4sv00001093sd00007498* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6548) pci:v00001093d0000C4C4sv00001093sd00007499* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6547) pci:v00001093d0000C4C4sv00001093sd000074A8* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4330) pci:v00001093d0000C4C4sv00001093sd000074A9* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4331) pci:v00001093d0000C4C4sv00001093sd000074B1* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4154) pci:v00001093d0000C4C4sv00001093sd000074B2* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4353) pci:v00001093d0000C4C4sv00001093sd000074B6* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-1433) pci:v00001093d0000C4C4sv00001093sd000074CD* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5643R) pci:v00001093d0000C4C4sv00001093sd000074D0* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7961R) pci:v00001093d0000C4C4sv00001093sd000074DD* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6376) pci:v00001093d0000C4C4sv00001093sd000074DE* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6378) pci:v00001093d0000C4C4sv00001093sd000074E2* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7962R) pci:v00001093d0000C4C4sv00001093sd000074E3* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7965R) pci:v00001093d0000C4C4sv00001093sd000074E5* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4844) pci:v00001093d0000C4C4sv00001093sd000074F3* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-5140) pci:v00001093d0000C4C4sv00001093sd0000753C* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-1435) pci:v00001093d0000C4C4sv00001093sd00007548* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5622 (25MHz DDC)) pci:v00001093d0000C4C4sv00001093sd0000754D* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-5155) pci:v00001093d0000C4C4sv00001093sd00007551* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6556) pci:v00001093d0000C4C4sv00001093sd00007553* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-1473R) pci:v00001093d0000C4C4sv00001093sd00007570* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-1474R) pci:v00001093d0000C4C4sv00001093sd00007571* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-1475R) pci:v00001093d0000C4C4sv00001093sd00007572* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-1476R) pci:v00001093d0000C4C4sv00001093sd000075A2* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5693) pci:v00001093d0000C4C4sv00001093sd000075A3* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5694) pci:v00001093d0000C4C4sv00001093sd000075A5* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4141) pci:v00001093d0000C4C4sv00001093sd000075CE* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7966R) pci:v00001093d0000C4C4sv00001093sd000075CF* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4357) pci:v00001093d0000C4C4sv00001093sd000075D2* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-RevB-5643R) pci:v00001093d0000C4C4sv00001093sd000075D3* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5644R) pci:v00001093d0000C4C4sv00001093sd000075EE* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5645R) pci:v00001093d0000C4C4sv00001093sd00007613* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6555) pci:v00001093d0000C4C4sv00001093sd00007619* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5185) pci:v00001093d0000C4C4sv00001093sd0000761A* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5186) pci:v00001093d0000C4C4sv00001093sd00007629* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4142) pci:v00001093d0000C4C4sv00001093sd0000762A* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4143) pci:v00001093d0000C4C4sv00001093sd0000762B* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4138) pci:v00001093d0000C4C4sv00001093sd0000762C* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4144) pci:v00001093d0000C4C4sv00001093sd0000762D* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4145) pci:v00001093d0000C4C4sv00001093sd0000762E* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5606) pci:v00001093d0000C4C4sv00001093sd00007644* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4841) pci:v00001093d0000C4C4sv00001093sd0000764A* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-8237R-S) pci:v00001093d0000C4C4sv00001093sd00007658* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5162 (4CH)) pci:v00001093d0000C4C4sv00001093sd000076AB* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4322) pci:v00001093d0000C4C4sv00001093sd000076AD* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4112) pci:v00001093d0000C4C4sv00001093sd000076AE* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4113) pci:v00001093d0000C4C4sv00001093sd000076B5* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7971R) pci:v00001093d0000C4C4sv00001093sd000076B6* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7972R) pci:v00001093d0000C4C4sv00001093sd000076B7* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7975R) pci:v00001093d0000C4C4sv00001093sd000076B8* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5696) pci:v00001093d0000C4C4sv00001093sd000076B9* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5654) pci:v00001093d0000C4C4sv00001093sd000076C8* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6614) pci:v00001093d0000C4C4sv00001093sd000076C9* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6612) pci:v00001093d0000C4C4sv00001093sd000076CB* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5646R) pci:v00001093d0000C4C4sv00001093sd000076CC* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5162 (2CH)) pci:v00001093d0000C4C4sv00001093sd000076CE* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (CVS-1459) pci:v00001093d0000C4C4sv00001093sd000076D0* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5160 (2CH)) pci:v00001093d0000C4C4sv00001093sd000076D1* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5160 (4CH)) pci:v00001093d0000C4C4sv00001093sd000076DC* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4610) pci:v00001093d0000C4C4sv00001093sd000076EC* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2524) pci:v00001093d0000C4C4sv00001093sd000076ED* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2525) pci:v00001093d0000C4C4sv00001093sd000076EE* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2526) pci:v00001093d0000C4C4sv00001093sd000076EF* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2737) pci:v00001093d0000C4C4sv00001093sd000076F0* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2738) pci:v00001093d0000C4C4sv00001093sd000076F1* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2739) pci:v00001093d0000C4C4sv00001093sd000076FB* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-1473R-LX110) pci:v00001093d0000C4C4sv00001093sd000076FC* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5105) pci:v00001093d0000C4C4sv00001093sd000076FD* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5114) pci:v00001093d0000C4C4sv00001093sd000076FE* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5644R) pci:v00001093d0000C4C4sv00001093sd000076FF* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5644R) pci:v00001093d0000C4C4sv00001093sd00007700* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5644R) pci:v00001093d0000C4C4sv00001093sd00007701* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5645R) pci:v00001093d0000C4C4sv00001093sd00007702* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5645R) pci:v00001093d0000C4C4sv00001093sd00007703* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5645R) pci:v00001093d0000C4C4sv00001093sd0000770C* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4139) pci:v00001093d0000C4C4sv00001093sd00007711* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4464) pci:v00001093d0000C4C4sv00001093sd00007712* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4463) pci:v00001093d0000C4C4sv00001093sd00007716* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6612) pci:v00001093d0000C4C4sv00001093sd0000771D* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (Unconfigured CA4 Switch) pci:v00001093d0000C4C4sv00001093sd0000771E* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4339) pci:v00001093d0000C4C4sv00001093sd00007735* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9033) pci:v00001093d0000C4C4sv00001093sd0000773E* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5624R) pci:v00001093d0000C4C4sv00001093sd0000774B* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9031) pci:v00001093d0000C4C4sv00001093sd0000774D* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9034) pci:v00001093d0000C4C4sv00001093sd00007755* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9030) pci:v00001093d0000C4C4sv00001093sd00007768* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2747) pci:v00001093d0000C4C4sv00001093sd00007769* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2748) pci:v00001093d0000C4C4sv00001093sd0000776A* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2746) pci:v00001093d0000C4C4sv00001093sd00007777* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7976R) pci:v00001093d0000C4C4sv00001093sd00007782* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5646R) pci:v00001093d0000C4C4sv00001093sd00007783* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5646R) pci:v00001093d0000C4C4sv00001093sd00007784* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5646R) pci:v00001093d0000C4C4sv00001093sd00007790* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5170R (4CH)) pci:v00001093d0000C4C4sv00001093sd00007791* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5170R (8CH)) pci:v00001093d0000C4C4sv00001093sd00007793* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5171R (8CH)) pci:v00001093d0000C4C4sv00001093sd000077A5* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6345) pci:v00001093d0000C4C4sv00001093sd000077A6* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6355) pci:v00001093d0000C4C4sv00001093sd000077A7* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6365) pci:v00001093d0000C4C4sv00001093sd000077A8* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6375) pci:v00001093d0000C4C4sv00001093sd000077AA* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (CVS-1458) pci:v00001093d0000C4C4sv00001093sd000077AD* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (IC-3173) pci:v00001093d0000C4C4sv00001093sd000077B4* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7820R) pci:v00001093d0000C4C4sv00001093sd000077B5* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7821R) pci:v00001093d0000C4C4sv00001093sd000077B6* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7822R) pci:v00001093d0000C4C4sv00001093sd000077B9* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9038) pci:v00001093d0000C4C4sv00001093sd000077BA* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4136) pci:v00001093d0000C4C4sv00001093sd000077BB* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4137) pci:v00001093d0000C4C4sv00001093sd000077C0* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5624R) pci:v00001093d0000C4C4sv00001093sd000077C1* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5624R) pci:v00001093d0000C4C4sv00001093sd000077C2* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5624R) pci:v00001093d0000C4C4sv00001093sd000077CA* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6738) pci:v00001093d0000C4C4sv00001093sd000077CB* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6739) pci:v00001093d0000C4C4sv00001093sd000077DB* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9035) pci:v00001093d0000C4C4sv00001093sd000077DC* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9036) pci:v00001093d0000C4C4sv00001093sd000077DD* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9039) pci:v00001093d0000C4C4sv00001093sd00007802* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4302) pci:v00001093d0000C4C4sv00001093sd00007803* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4303) pci:v00001093d0000C4C4sv00001093sd00007805* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4305) pci:v00001093d0000C4C4sv00001093sd0000788E* ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4304) pci:v00001093d0000C801* ID_MODEL_FROM_DATABASE=PCI-GPIB pci:v00001093d0000C811* ID_MODEL_FROM_DATABASE=PCI-GPIB+ pci:v00001093d0000C821* ID_MODEL_FROM_DATABASE=PXI-GPIB pci:v00001093d0000C831* ID_MODEL_FROM_DATABASE=PMC-GPIB pci:v00001093d0000C840* ID_MODEL_FROM_DATABASE=PCI-GPIB pci:v00001093d0000D130* ID_MODEL_FROM_DATABASE=PCI-232/2 Interface pci:v00001093d0000D140* ID_MODEL_FROM_DATABASE=PCI-232/4 Interface pci:v00001093d0000D150* ID_MODEL_FROM_DATABASE=PCI-232/8 Interface pci:v00001093d0000D160* ID_MODEL_FROM_DATABASE=PCI-485/2 Interface pci:v00001093d0000D170* ID_MODEL_FROM_DATABASE=PCI-485/4 Interface pci:v00001093d0000D190* ID_MODEL_FROM_DATABASE=PXI-8422/2 (Isolated RS-232) Interface pci:v00001093d0000D1A0* ID_MODEL_FROM_DATABASE=PXI-8422/4 (Isolated RS-232) Interface pci:v00001093d0000D1B0* ID_MODEL_FROM_DATABASE=PXI-8423/2 (Isolated RS-485) Interface pci:v00001093d0000D1C0* ID_MODEL_FROM_DATABASE=PXI-8423/4 (Isolated RS-485) Interface pci:v00001093d0000D1D0* ID_MODEL_FROM_DATABASE=PXI-8420/2 (RS-232) Interface pci:v00001093d0000D1E0* ID_MODEL_FROM_DATABASE=PXI-8420/4 (RS-232) Interface pci:v00001093d0000D1F0* ID_MODEL_FROM_DATABASE=PXI-8420/8 (RS-232) Interface pci:v00001093d0000D1F1* ID_MODEL_FROM_DATABASE=PXI-8420/16 (RS-232) Interface pci:v00001093d0000D230* ID_MODEL_FROM_DATABASE=PXI-8421/2 (RS-485) Interface pci:v00001093d0000D240* ID_MODEL_FROM_DATABASE=PXI-8421/4 (RS-485) Interface pci:v00001093d0000D250* ID_MODEL_FROM_DATABASE=PCI-232/2 (Isolated) Interface pci:v00001093d0000D260* ID_MODEL_FROM_DATABASE=PCI-485/2 (Isolated) Interface pci:v00001093d0000D270* ID_MODEL_FROM_DATABASE=PCI-232/4 (Isolated) Interface pci:v00001093d0000D280* ID_MODEL_FROM_DATABASE=PCI-485/4 (Isolated) Interface pci:v00001093d0000D290* ID_MODEL_FROM_DATABASE=PCI-485/8 Interface pci:v00001093d0000D2A0* ID_MODEL_FROM_DATABASE=PXI-8421/8 (RS-485) Interface pci:v00001093d0000D2B0* ID_MODEL_FROM_DATABASE=PCI-232/16 Interface pci:v00001093d0000E111* ID_MODEL_FROM_DATABASE=PCI-CAN pci:v00001093d0000E131* ID_MODEL_FROM_DATABASE=PXI-8461 (1 port) pci:v00001093d0000E141* ID_MODEL_FROM_DATABASE=PCI-CAN/LS pci:v00001093d0000E151* ID_MODEL_FROM_DATABASE=PXI-8460 (1 port) pci:v00001093d0000E211* ID_MODEL_FROM_DATABASE=PCI-CAN/2 pci:v00001093d0000E231* ID_MODEL_FROM_DATABASE=PXI-8461 (2 ports) pci:v00001093d0000E241* ID_MODEL_FROM_DATABASE=PCI-CAN/LS2 pci:v00001093d0000E251* ID_MODEL_FROM_DATABASE=PXI-8460 (2 ports) pci:v00001093d0000E261* ID_MODEL_FROM_DATABASE=PCI-CAN/DS pci:v00001093d0000E271* ID_MODEL_FROM_DATABASE=PXI-8462 pci:v00001093d0000F110* ID_MODEL_FROM_DATABASE=VMEpc-650 pci:v00001093d0000F120* ID_MODEL_FROM_DATABASE=VXIpc-650 pci:v00001093d0000FE00* ID_MODEL_FROM_DATABASE=VXIpc-87x pci:v00001093d0000FE41* ID_MODEL_FROM_DATABASE=VXIpc-860 pci:v00001093d0000FE51* ID_MODEL_FROM_DATABASE=VXIpc-74x pci:v00001093d0000FE61* ID_MODEL_FROM_DATABASE=VXIpc-850 pci:v00001093d0000FE70* ID_MODEL_FROM_DATABASE=VXIpc-880 pci:v00001094* ID_VENDOR_FROM_DATABASE=First International Computers [FIC] pci:v00001095* ID_VENDOR_FROM_DATABASE=Silicon Image, Inc. pci:v00001095d00000240* ID_MODEL_FROM_DATABASE=Adaptec AAR-1210SA SATA HostRAID Controller pci:v00001095d00000640* ID_MODEL_FROM_DATABASE=PCI0640 pci:v00001095d00000643* ID_MODEL_FROM_DATABASE=PCI0643 pci:v00001095d00000646* ID_MODEL_FROM_DATABASE=PCI0646 pci:v00001095d00000647* ID_MODEL_FROM_DATABASE=PCI0647 pci:v00001095d00000648* ID_MODEL_FROM_DATABASE=PCI0648 pci:v00001095d00000648sv00001043sd00008025* ID_MODEL_FROM_DATABASE=PCI0648 (CUBX motherboard) pci:v00001095d00000649* ID_MODEL_FROM_DATABASE=SiI 0649 Ultra ATA/100 PCI to ATA Host Controller pci:v00001095d00000649sv00000E11sd0000005D* ID_MODEL_FROM_DATABASE=SiI 0649 Ultra ATA/100 PCI to ATA Host Controller (Integrated Ultra ATA-100 Dual Channel Controller) pci:v00001095d00000649sv00000E11sd0000007E* ID_MODEL_FROM_DATABASE=SiI 0649 Ultra ATA/100 PCI to ATA Host Controller (Integrated Ultra ATA-100 IDE RAID Controller) pci:v00001095d00000649sv0000101Esd00000649* ID_MODEL_FROM_DATABASE=SiI 0649 Ultra ATA/100 PCI to ATA Host Controller (AMI MegaRAID IDE 100 Controller) pci:v00001095d00000650* ID_MODEL_FROM_DATABASE=PBC0650A pci:v00001095d00000670* ID_MODEL_FROM_DATABASE=USB0670 pci:v00001095d00000670sv00001095sd00000670* ID_MODEL_FROM_DATABASE=USB0670 pci:v00001095d00000673* ID_MODEL_FROM_DATABASE=USB0673 pci:v00001095d00000680* ID_MODEL_FROM_DATABASE=PCI0680 Ultra ATA-133 Host Controller pci:v00001095d00000680sv00001095sd00000680* ID_MODEL_FROM_DATABASE=PCI0680 Ultra ATA-133 Host Controller (SiI 0680 ATA/133 Controller) pci:v00001095d00000680sv00001095sd00003680* ID_MODEL_FROM_DATABASE=PCI0680 Ultra ATA-133 Host Controller (Winic W-680 (Silicon Image 680 based)) pci:v00001095d00003112* ID_MODEL_FROM_DATABASE=SiI 3112 [SATALink/SATARaid] Serial ATA Controller pci:v00001095d00003112sv00001095sd00003112* ID_MODEL_FROM_DATABASE=SiI 3112 [SATALink/SATARaid] Serial ATA Controller (SiI 3112 SATALink Controller) pci:v00001095d00003112sv00001095sd00006112* ID_MODEL_FROM_DATABASE=SiI 3112 [SATALink/SATARaid] Serial ATA Controller (SiI 3112 SATARaid Controller) pci:v00001095d00003112sv00009005sd00000250* ID_MODEL_FROM_DATABASE=SiI 3112 [SATALink/SATARaid] Serial ATA Controller (SATAConnect 1205SA Host Controller) pci:v00001095d00003114* ID_MODEL_FROM_DATABASE=SiI 3114 [SATALink/SATARaid] Serial ATA Controller pci:v00001095d00003114sv00001043sd00008167* ID_MODEL_FROM_DATABASE=SiI 3114 [SATALink/SATARaid] Serial ATA Controller (A8N-SLI Deluxe/Premium Mainboard) pci:v00001095d00003114sv00001095sd00003114* ID_MODEL_FROM_DATABASE=SiI 3114 [SATALink/SATARaid] Serial ATA Controller (SiI 3114 SATALink Controller) pci:v00001095d00003114sv00001095sd00006114* ID_MODEL_FROM_DATABASE=SiI 3114 [SATALink/SATARaid] Serial ATA Controller (SiI 3114 SATARaid Controller) pci:v00001095d00003124* ID_MODEL_FROM_DATABASE=SiI 3124 PCI-X Serial ATA Controller pci:v00001095d00003124sv00001095sd00003124* ID_MODEL_FROM_DATABASE=SiI 3124 PCI-X Serial ATA Controller pci:v00001095d00003132* ID_MODEL_FROM_DATABASE=SiI 3132 Serial ATA Raid II Controller pci:v00001095d00003512* ID_MODEL_FROM_DATABASE=SiI 3512 [SATALink/SATARaid] Serial ATA Controller pci:v00001095d00003512sv00001095sd00003512* ID_MODEL_FROM_DATABASE=SiI 3512 [SATALink/SATARaid] Serial ATA Controller (SiI 3512 SATALink Controller) pci:v00001095d00003512sv00001095sd00006512* ID_MODEL_FROM_DATABASE=SiI 3512 [SATALink/SATARaid] Serial ATA Controller (SiI 3512 SATARaid Controller) pci:v00001095d00003531* ID_MODEL_FROM_DATABASE=SiI 3531 [SATALink/SATARaid] Serial ATA Controller pci:v00001095d00003531sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=SiI 3531 [SATALink/SATARaid] Serial ATA Controller (Medion WIM 2210 Notebook PC [MD96850]) pci:v00001096* ID_VENDOR_FROM_DATABASE=Alacron pci:v00001097* ID_VENDOR_FROM_DATABASE=Appian Technology pci:v00001098* ID_VENDOR_FROM_DATABASE=Quantum Designs (H.K.) Ltd pci:v00001098d00000001* ID_MODEL_FROM_DATABASE=QD-8500 pci:v00001098d00000002* ID_MODEL_FROM_DATABASE=QD-8580 pci:v00001099* ID_VENDOR_FROM_DATABASE=Samsung Electronics Co., Ltd pci:v0000109A* ID_VENDOR_FROM_DATABASE=Packard Bell pci:v0000109B* ID_VENDOR_FROM_DATABASE=Gemlight Computer Ltd. pci:v0000109C* ID_VENDOR_FROM_DATABASE=Megachips Corporation pci:v0000109D* ID_VENDOR_FROM_DATABASE=Zida Technologies Ltd. pci:v0000109E* ID_VENDOR_FROM_DATABASE=Brooktree Corporation pci:v0000109Ed00000310* ID_MODEL_FROM_DATABASE=Bt848 Video Capture pci:v0000109Ed0000032E* ID_MODEL_FROM_DATABASE=Bt878 Video Capture pci:v0000109Ed00000350* ID_MODEL_FROM_DATABASE=Bt848 Video Capture pci:v0000109Ed00000351* ID_MODEL_FROM_DATABASE=Bt849A Video capture pci:v0000109Ed00000369* ID_MODEL_FROM_DATABASE=Bt878 Video Capture pci:v0000109Ed00000369sv00001002sd00000001* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (TV-Wonder) pci:v0000109Ed00000369sv00001002sd00000003* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (TV-Wonder/VE) pci:v0000109Ed0000036C* ID_MODEL_FROM_DATABASE=Bt879(??) Video Capture pci:v0000109Ed0000036Csv000013E9sd00000070* ID_MODEL_FROM_DATABASE=Bt879(??) Video Capture (Win/TV (Video Section)) pci:v0000109Ed0000036E* ID_MODEL_FROM_DATABASE=Bt878 Video Capture pci:v0000109Ed0000036Esv00000070sd000013EB* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (WinTV Series) pci:v0000109Ed0000036Esv00000070sd0000FF01* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Viewcast Osprey 200) pci:v0000109Ed0000036Esv00000071sd00000101* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (DigiTV PCI) pci:v0000109Ed0000036Esv0000107Dsd00006606* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (WinFast TV 2000) pci:v0000109Ed0000036Esv000011BDsd00000012* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (PCTV pro (TV + FM stereo receiver)) pci:v0000109Ed0000036Esv000011BDsd0000001C* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (PCTV Sat (DBC receiver)) pci:v0000109Ed0000036Esv0000127Asd00000001* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878 Mediastream Controller NTSC) pci:v0000109Ed0000036Esv0000127Asd00000002* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878 Mediastream Controller PAL BG) pci:v0000109Ed0000036Esv0000127Asd00000003* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878a Mediastream Controller PAL BG) pci:v0000109Ed0000036Esv0000127Asd00000048* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878/832 Mediastream Controller) pci:v0000109Ed0000036Esv0000144Fsd00003000* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (MagicTView CPH060 - Video) pci:v0000109Ed0000036Esv00001461sd00000002* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (TV98 Series (TV/No FM/Remote)) pci:v0000109Ed0000036Esv00001461sd00000003* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (AverMedia UltraTV PCI 350) pci:v0000109Ed0000036Esv00001461sd00000004* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (AVerTV WDM Video Capture) pci:v0000109Ed0000036Esv00001461sd00000761* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (AverTV DVB-T) pci:v0000109Ed0000036Esv00001461sd00000771* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (AverMedia AVerTV DVB-T 771) pci:v0000109Ed0000036Esv000014F1sd00000001* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878 Mediastream Controller NTSC) pci:v0000109Ed0000036Esv000014F1sd00000002* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878 Mediastream Controller PAL BG) pci:v0000109Ed0000036Esv000014F1sd00000003* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878a Mediastream Controller PAL BG) pci:v0000109Ed0000036Esv000014F1sd00000048* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878/832 Mediastream Controller) pci:v0000109Ed0000036Esv00001822sd00000001* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (VisionPlus DVB card) pci:v0000109Ed0000036Esv00001851sd00001850* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (FlyVideo'98 - Video) pci:v0000109Ed0000036Esv00001851sd00001851* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (FlyVideo II) pci:v0000109Ed0000036Esv00001852sd00001852* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (FlyVideo'98 - Video (with FM Tuner)) pci:v0000109Ed0000036Esv000018ACsd0000D500* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (DViCO FusionHDTV5 Lite) pci:v0000109Ed0000036Esv0000270Fsd0000FC00* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Digitop DTT-1000) pci:v0000109Ed0000036Esv0000AA00sd00001460* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardA Input0) pci:v0000109Ed0000036Esv0000AA01sd00001461* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardA Input1) pci:v0000109Ed0000036Esv0000AA02sd00001462* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardA Input2) pci:v0000109Ed0000036Esv0000AA03sd00001463* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardA Input3) pci:v0000109Ed0000036Esv0000AA04sd00001464* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardB Input0) pci:v0000109Ed0000036Esv0000AA05sd00001465* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardB Input1) pci:v0000109Ed0000036Esv0000AA06sd00001466* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardB Input2) pci:v0000109Ed0000036Esv0000AA07sd00001467* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardB Input3) pci:v0000109Ed0000036Esv0000AA08sd00001468* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardC Input0) pci:v0000109Ed0000036Esv0000AA09sd00001469* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardC Input1) pci:v0000109Ed0000036Esv0000AA0Asd0000146A* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardC Input2) pci:v0000109Ed0000036Esv0000AA0Bsd0000146B* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardC Input3) pci:v0000109Ed0000036Esv0000AA0Csd0000146C* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardD Input0) pci:v0000109Ed0000036Esv0000AA0Dsd0000146D* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardD Input1) pci:v0000109Ed0000036Esv0000AA0Esd0000146E* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardD Input2) pci:v0000109Ed0000036Esv0000AA0Fsd0000146F* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardD Input3) pci:v0000109Ed0000036Esv0000BD11sd00001200* ID_MODEL_FROM_DATABASE=Bt878 Video Capture (PCTV pro (TV + FM stereo receiver)) pci:v0000109Ed0000036F* ID_MODEL_FROM_DATABASE=Bt879 Video Capture pci:v0000109Ed0000036Fsv0000127Asd00000044* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) pci:v0000109Ed0000036Fsv0000127Asd00000122* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL I) pci:v0000109Ed0000036Fsv0000127Asd00000144* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) pci:v0000109Ed0000036Fsv0000127Asd00000222* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL BG) pci:v0000109Ed0000036Fsv0000127Asd00000244* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture NTSC) pci:v0000109Ed0000036Fsv0000127Asd00000322* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) pci:v0000109Ed0000036Fsv0000127Asd00000422* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) pci:v0000109Ed0000036Fsv0000127Asd00001122* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL I) pci:v0000109Ed0000036Fsv0000127Asd00001222* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL BG) pci:v0000109Ed0000036Fsv0000127Asd00001322* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) pci:v0000109Ed0000036Fsv0000127Asd00001522* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture PAL I) pci:v0000109Ed0000036Fsv0000127Asd00001622* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture PAL BG) pci:v0000109Ed0000036Fsv0000127Asd00001722* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture NTSC) pci:v0000109Ed0000036Fsv000014F1sd00000044* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) pci:v0000109Ed0000036Fsv000014F1sd00000122* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL I) pci:v0000109Ed0000036Fsv000014F1sd00000144* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) pci:v0000109Ed0000036Fsv000014F1sd00000222* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL BG) pci:v0000109Ed0000036Fsv000014F1sd00000244* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture NTSC) pci:v0000109Ed0000036Fsv000014F1sd00000322* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) pci:v0000109Ed0000036Fsv000014F1sd00000422* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) pci:v0000109Ed0000036Fsv000014F1sd00001122* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL I) pci:v0000109Ed0000036Fsv000014F1sd00001222* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL BG) pci:v0000109Ed0000036Fsv000014F1sd00001322* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) pci:v0000109Ed0000036Fsv000014F1sd00001522* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture PAL I) pci:v0000109Ed0000036Fsv000014F1sd00001622* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture PAL BG) pci:v0000109Ed0000036Fsv000014F1sd00001722* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture NTSC) pci:v0000109Ed0000036Fsv00001851sd00001850* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (FlyVideo'98 - Video) pci:v0000109Ed0000036Fsv00001851sd00001851* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (FlyVideo II) pci:v0000109Ed0000036Fsv00001852sd00001852* ID_MODEL_FROM_DATABASE=Bt879 Video Capture (FlyVideo'98 - Video (with FM Tuner)) pci:v0000109Ed00000370* ID_MODEL_FROM_DATABASE=Bt880 Video Capture pci:v0000109Ed00000370sv00001851sd00001850* ID_MODEL_FROM_DATABASE=Bt880 Video Capture (FlyVideo'98) pci:v0000109Ed00000370sv00001851sd00001851* ID_MODEL_FROM_DATABASE=Bt880 Video Capture (FlyVideo'98 EZ - video) pci:v0000109Ed00000370sv00001852sd00001852* ID_MODEL_FROM_DATABASE=Bt880 Video Capture (FlyVideo'98 (with FM Tuner)) pci:v0000109Ed00000878* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture pci:v0000109Ed00000878sv00000070sd000013EB* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (WinTV Series) pci:v0000109Ed00000878sv00000070sd0000FF01* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Viewcast Osprey 200) pci:v0000109Ed00000878sv00000071sd00000101* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (DigiTV PCI) pci:v0000109Ed00000878sv00001002sd00000001* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (TV-Wonder) pci:v0000109Ed00000878sv00001002sd00000003* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (TV-Wonder/VE) pci:v0000109Ed00000878sv000011BDsd00000012* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (PCTV pro (TV + FM stereo receiver, audio section)) pci:v0000109Ed00000878sv000011BDsd0000001C* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (PCTV Sat (DBC receiver)) pci:v0000109Ed00000878sv0000127Asd00000001* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) pci:v0000109Ed00000878sv0000127Asd00000002* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) pci:v0000109Ed00000878sv0000127Asd00000003* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) pci:v0000109Ed00000878sv0000127Asd00000048* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) pci:v0000109Ed00000878sv000013E9sd00000070* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Win/TV (Audio Section)) pci:v0000109Ed00000878sv0000144Fsd00003000* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (MagicTView CPH060 - Audio) pci:v0000109Ed00000878sv00001461sd00000002* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Avermedia PCTV98 Audio Capture) pci:v0000109Ed00000878sv00001461sd00000003* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (UltraTV PCI 350) pci:v0000109Ed00000878sv00001461sd00000004* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (AVerTV WDM Audio Capture) pci:v0000109Ed00000878sv00001461sd00000761* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (AVerTV DVB-T) pci:v0000109Ed00000878sv00001461sd00000771* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (AverMedia AVerTV DVB-T 771) pci:v0000109Ed00000878sv000014F1sd00000001* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) pci:v0000109Ed00000878sv000014F1sd00000002* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) pci:v0000109Ed00000878sv000014F1sd00000003* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) pci:v0000109Ed00000878sv000014F1sd00000048* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) pci:v0000109Ed00000878sv00001822sd00000001* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (VisionPlus DVB Card) pci:v0000109Ed00000878sv000018ACsd0000D500* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (DViCO FusionHDTV5 Lite) pci:v0000109Ed00000878sv0000270Fsd0000FC00* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Digitop DTT-1000) pci:v0000109Ed00000878sv0000BD11sd00001200* ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (PCTV pro (TV + FM stereo receiver, audio section)) pci:v0000109Ed00000879* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture pci:v0000109Ed00000879sv0000127Asd00000044* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv0000127Asd00000122* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv0000127Asd00000144* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv0000127Asd00000222* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv0000127Asd00000244* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv0000127Asd00000322* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv0000127Asd00000422* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv0000127Asd00001122* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv0000127Asd00001222* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv0000127Asd00001322* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv0000127Asd00001522* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv0000127Asd00001622* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv0000127Asd00001722* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv000014F1sd00000044* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv000014F1sd00000122* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv000014F1sd00000144* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv000014F1sd00000222* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv000014F1sd00000244* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv000014F1sd00000322* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv000014F1sd00000422* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv000014F1sd00001122* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv000014F1sd00001222* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv000014F1sd00001322* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv000014F1sd00001522* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv000014F1sd00001622* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000879sv000014F1sd00001722* ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) pci:v0000109Ed00000880* ID_MODEL_FROM_DATABASE=Bt880 Audio Capture pci:v0000109Ed00002115* ID_MODEL_FROM_DATABASE=BtV 2115 Mediastream controller pci:v0000109Ed00002125* ID_MODEL_FROM_DATABASE=BtV 2125 Mediastream controller pci:v0000109Ed00002164* ID_MODEL_FROM_DATABASE=BtV 2164 pci:v0000109Ed00002165* ID_MODEL_FROM_DATABASE=BtV 2165 pci:v0000109Ed00008230* ID_MODEL_FROM_DATABASE=Bt8230 ATM Segment/Reassembly Ctrlr (SRC) pci:v0000109Ed00008472* ID_MODEL_FROM_DATABASE=Bt8472 pci:v0000109Ed00008474* ID_MODEL_FROM_DATABASE=Bt8474 pci:v0000109F* ID_VENDOR_FROM_DATABASE=Trigem Computer Inc. pci:v000010A0* ID_VENDOR_FROM_DATABASE=Meidensha Corporation pci:v000010A1* ID_VENDOR_FROM_DATABASE=Juko Electronics Ind. Co. Ltd pci:v000010A2* ID_VENDOR_FROM_DATABASE=Quantum Corporation pci:v000010A3* ID_VENDOR_FROM_DATABASE=Everex Systems Inc pci:v000010A4* ID_VENDOR_FROM_DATABASE=Globe Manufacturing Sales pci:v000010A5* ID_VENDOR_FROM_DATABASE=Smart Link Ltd. pci:v000010A5d00003052* ID_MODEL_FROM_DATABASE=SmartPCI562 56K Modem pci:v000010A5d00005449* ID_MODEL_FROM_DATABASE=SmartPCI561 modem pci:v000010A6* ID_VENDOR_FROM_DATABASE=Informtech Industrial Ltd. pci:v000010A7* ID_VENDOR_FROM_DATABASE=Benchmarq Microelectronics pci:v000010A8* ID_VENDOR_FROM_DATABASE=Sierra Semiconductor pci:v000010A8d00000000* ID_MODEL_FROM_DATABASE=STB Horizon 64 pci:v000010A9* ID_VENDOR_FROM_DATABASE=Silicon Graphics Intl. Corp. pci:v000010A9d00000001* ID_MODEL_FROM_DATABASE=Crosstalk to PCI Bridge pci:v000010A9d00000002* ID_MODEL_FROM_DATABASE=Linc I/O controller pci:v000010A9d00000003* ID_MODEL_FROM_DATABASE=IOC3 I/O controller pci:v000010A9d00000004* ID_MODEL_FROM_DATABASE=O2 MACE pci:v000010A9d00000005* ID_MODEL_FROM_DATABASE=RAD Audio pci:v000010A9d00000006* ID_MODEL_FROM_DATABASE=HPCEX pci:v000010A9d00000007* ID_MODEL_FROM_DATABASE=RPCEX pci:v000010A9d00000008* ID_MODEL_FROM_DATABASE=DiVO VIP pci:v000010A9d00000009* ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet pci:v000010A9d00000009sv000010A9sd00008002* ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet pci:v000010A9d00000010* ID_MODEL_FROM_DATABASE=AMP Video I/O pci:v000010A9d00000011* ID_MODEL_FROM_DATABASE=GRIP pci:v000010A9d00000012* ID_MODEL_FROM_DATABASE=SGH PSHAC GSN pci:v000010A9d00000208* ID_MODEL_FROM_DATABASE=SSIM1 SAS Adapter pci:v000010A9d00001001* ID_MODEL_FROM_DATABASE=Magic Carpet pci:v000010A9d00001002* ID_MODEL_FROM_DATABASE=Lithium pci:v000010A9d00001003* ID_MODEL_FROM_DATABASE=Dual JPEG 1 pci:v000010A9d00001004* ID_MODEL_FROM_DATABASE=Dual JPEG 2 pci:v000010A9d00001005* ID_MODEL_FROM_DATABASE=Dual JPEG 3 pci:v000010A9d00001006* ID_MODEL_FROM_DATABASE=Dual JPEG 4 pci:v000010A9d00001007* ID_MODEL_FROM_DATABASE=Dual JPEG 5 pci:v000010A9d00001008* ID_MODEL_FROM_DATABASE=Cesium pci:v000010A9d0000100A* ID_MODEL_FROM_DATABASE=IOC4 I/O controller pci:v000010A9d00001504* ID_MODEL_FROM_DATABASE=SSIM1 Fibre Channel Adapter pci:v000010A9d00002001* ID_MODEL_FROM_DATABASE=Fibre Channel pci:v000010A9d00002002* ID_MODEL_FROM_DATABASE=ASDE pci:v000010A9d00004001* ID_MODEL_FROM_DATABASE=TIO-CE PCI Express Bridge pci:v000010A9d00004002* ID_MODEL_FROM_DATABASE=TIO-CE PCI Express Port pci:v000010A9d00008001* ID_MODEL_FROM_DATABASE=O2 1394 pci:v000010A9d00008002* ID_MODEL_FROM_DATABASE=G-net NT pci:v000010A9d0000802B* ID_MODEL_FROM_DATABASE=REACT external interrupt controller pci:v000010AA* ID_VENDOR_FROM_DATABASE=ACC Microelectronics pci:v000010AAd00000000* ID_MODEL_FROM_DATABASE=ACCM 2188 pci:v000010AAd00002051* ID_MODEL_FROM_DATABASE=2051 CPU bridge pci:v000010AAd00005842* ID_MODEL_FROM_DATABASE=2051 ISA bridge pci:v000010AB* ID_VENDOR_FROM_DATABASE=Digicom pci:v000010AC* ID_VENDOR_FROM_DATABASE=Honeywell IAC pci:v000010AD* ID_VENDOR_FROM_DATABASE=Symphony Labs pci:v000010ADd00000001* ID_MODEL_FROM_DATABASE=W83769F pci:v000010ADd00000003* ID_MODEL_FROM_DATABASE=SL82C103 pci:v000010ADd00000005* ID_MODEL_FROM_DATABASE=SL82C105 pci:v000010ADd00000103* ID_MODEL_FROM_DATABASE=SL82c103 pci:v000010ADd00000105* ID_MODEL_FROM_DATABASE=SL82c105 pci:v000010ADd00000565* ID_MODEL_FROM_DATABASE=W83C553F/W83C554F pci:v000010AE* ID_VENDOR_FROM_DATABASE=Cornerstone Technology pci:v000010AF* ID_VENDOR_FROM_DATABASE=Micro Computer Systems Inc pci:v000010B0* ID_VENDOR_FROM_DATABASE=CardExpert Technology pci:v000010B1* ID_VENDOR_FROM_DATABASE=Cabletron Systems Inc pci:v000010B2* ID_VENDOR_FROM_DATABASE=Raytheon Company pci:v000010B3* ID_VENDOR_FROM_DATABASE=Databook Inc pci:v000010B3d00003106* ID_MODEL_FROM_DATABASE=DB87144 pci:v000010B3d0000B106* ID_MODEL_FROM_DATABASE=DB87144 pci:v000010B4* ID_VENDOR_FROM_DATABASE=STB Systems Inc pci:v000010B4d00001B1D* ID_MODEL_FROM_DATABASE=Velocity 128 3D pci:v000010B4d00001B1Dsv000010B4sd0000237E* ID_MODEL_FROM_DATABASE=Velocity 128 3D (Velocity 4400) pci:v000010B5* ID_VENDOR_FROM_DATABASE=PLX Technology, Inc. pci:v000010B5d00000001* ID_MODEL_FROM_DATABASE=i960 PCI bus interface pci:v000010B5d00000557* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge pci:v000010B5d00000557sv000010B5sd00009030* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Digium Tormenta 2 T400P-SS7 or E400P-SS7 Quad T1 or E1 PCI card) pci:v000010B5d00001000* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge pci:v000010B5d00001000sv000010B5sd00009030* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (ATCOM AT400P Quad T1 PCI card) pci:v000010B5d00001024* ID_MODEL_FROM_DATABASE=Acromag, Inc. IndustryPack Carrier Card pci:v000010B5d00001042* ID_MODEL_FROM_DATABASE=Brandywine / jxi2, Inc. - PMC-SyncClock32, IRIG A & B, Nasa 36 pci:v000010B5d0000106A* ID_MODEL_FROM_DATABASE=Dual OX16C952 4 port serial adapter [Megawolf Romulus/4] pci:v000010B5d00001076* ID_MODEL_FROM_DATABASE=VScom 800 8 port serial adaptor pci:v000010B5d00001077* ID_MODEL_FROM_DATABASE=VScom 400 4 port serial adaptor pci:v000010B5d00001078* ID_MODEL_FROM_DATABASE=VScom 210 2 port serial and 1 port parallel adaptor pci:v000010B5d00001103* ID_MODEL_FROM_DATABASE=VScom 200 2 port serial adaptor pci:v000010B5d00001146* ID_MODEL_FROM_DATABASE=VScom 010 1 port parallel adaptor pci:v000010B5d00001147* ID_MODEL_FROM_DATABASE=VScom 020 2 port parallel adaptor pci:v000010B5d00002000* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge pci:v000010B5d00002000sv000010B5sd00009030* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (ATCOM AE400P Quad E1 PCI card) pci:v000010B5d00002540* ID_MODEL_FROM_DATABASE=IXXAT CAN-Interface PC-I 04/PCI pci:v000010B5d00002724* ID_MODEL_FROM_DATABASE=Thales PCSM Security Card pci:v000010B5d00003376* ID_MODEL_FROM_DATABASE=Cosateq 4 Port CAN Card pci:v000010B5d00004000* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge pci:v000010B5d00004000sv000010B5sd00009030* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Tormenta 3 Varion V400P/ATCOM TE400P Quad E1/T1/J1 PCI card) pci:v000010B5d00004001* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge pci:v000010B5d00004001sv000010B5sd00009030* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (ATCOM A400PE Quad E1 PCI card) pci:v000010B5d00004002* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge pci:v000010B5d00004002sv000010B5sd00009030* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (ATCOM A400PT Quad T1 PCI card) pci:v000010B5d00006140* ID_MODEL_FROM_DATABASE=PCI6140 32-bit 33MHz PCI-to-PCI Bridge pci:v000010B5d00006150* ID_MODEL_FROM_DATABASE=PCI6150 32-bit 33MHz PCI-to-PCI Bridge pci:v000010B5d00006152* ID_MODEL_FROM_DATABASE=PCI6152 32-bit 66MHz PCI-to-PCI Bridge pci:v000010B5d00006154* ID_MODEL_FROM_DATABASE=PCI6154 64-bit 66MHz PCI-to-PCI Bridge pci:v000010B5d00006254* ID_MODEL_FROM_DATABASE=PCI6254 64-bit 66MHz PCI-to-PCI Bridge pci:v000010B5d00006466* ID_MODEL_FROM_DATABASE=PCI6466 64-bit 66MHz PCI-to-PCI Bridge pci:v000010B5d00006520* ID_MODEL_FROM_DATABASE=PCI6520 64-bit 133MHz PCI-X-to-PCI-X Bridge pci:v000010B5d00006540* ID_MODEL_FROM_DATABASE=PCI6540 64-bit 133MHz PCI-X-to-PCI-X Bridge pci:v000010B5d00006540sv00001775sd00001100* ID_MODEL_FROM_DATABASE=PCI6540 64-bit 133MHz PCI-X-to-PCI-X Bridge (CR11 Single Board Computer) pci:v000010B5d00006540sv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=PCI6540 64-bit 133MHz PCI-X-to-PCI-X Bridge (PSL09 PrPMC) pci:v000010B5d00006541* ID_MODEL_FROM_DATABASE=PCI6540/6466 PCI-PCI bridge (non-transparent mode, primary side) pci:v000010B5d00006541sv00001775sd00001100* ID_MODEL_FROM_DATABASE=PCI6540/6466 PCI-PCI bridge (non-transparent mode, primary side) (CR11 Single Board Computer) pci:v000010B5d00006541sv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=PCI6540/6466 PCI-PCI bridge (non-transparent mode, primary side) (PSL09 PrPMC) pci:v000010B5d00006542* ID_MODEL_FROM_DATABASE=PCI6540/6466 PCI-PCI bridge (non-transparent mode, secondary side) pci:v000010B5d00006542sv00001775sd00001100* ID_MODEL_FROM_DATABASE=PCI6540/6466 PCI-PCI bridge (non-transparent mode, secondary side) (CR11 Single Board Computer) pci:v000010B5d00006542sv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=PCI6540/6466 PCI-PCI bridge (non-transparent mode, secondary side) (PSL09 PrPMC) pci:v000010B5d00008111* ID_MODEL_FROM_DATABASE=PEX 8111 PCI Express-to-PCI Bridge pci:v000010B5d00008112* ID_MODEL_FROM_DATABASE=PEX8112 x1 Lane PCI Express-to-PCI Bridge pci:v000010B5d00008114* ID_MODEL_FROM_DATABASE=PEX 8114 PCI Express-to-PCI/PCI-X Bridge pci:v000010B5d00008311* ID_MODEL_FROM_DATABASE=PEX8311 x1 Lane PCI Express-to-Generic Local Bus Bridge pci:v000010B5d00008505* ID_MODEL_FROM_DATABASE=PEX 8505 5-lane, 5-port PCI Express Switch pci:v000010B5d00008508* ID_MODEL_FROM_DATABASE=PEX 8508 8-lane, 5-port PCI Express Switch pci:v000010B5d00008509* ID_MODEL_FROM_DATABASE=PEX 8509 8-lane, 8-port PCI Express Switch pci:v000010B5d00008512* ID_MODEL_FROM_DATABASE=PEX 8512 12-lane, 5-port PCI Express Switch pci:v000010B5d00008516* ID_MODEL_FROM_DATABASE=PEX 8516 Versatile PCI Express Switch pci:v000010B5d00008517* ID_MODEL_FROM_DATABASE=PEX 8517 16-lane, 5-port PCI Express Switch pci:v000010B5d00008518* ID_MODEL_FROM_DATABASE=PEX 8518 16-lane, 5-port PCI Express Switch pci:v000010B5d00008524* ID_MODEL_FROM_DATABASE=PEX 8524 24-lane, 6-port PCI Express Switch pci:v000010B5d00008525* ID_MODEL_FROM_DATABASE=PEX 8525 24-lane, 5-port PCI Express Switch pci:v000010B5d00008532* ID_MODEL_FROM_DATABASE=PEX 8532 Versatile PCI Express Switch pci:v000010B5d00008533* ID_MODEL_FROM_DATABASE=PEX 8533 32-lane, 6-port PCI Express Switch pci:v000010B5d00008547* ID_MODEL_FROM_DATABASE=PEX 8547 48-lane, 3-port PCI Express Switch pci:v000010B5d00008548* ID_MODEL_FROM_DATABASE=PEX 8548 48-lane, 9-port PCI Express Switch pci:v000010B5d00008604* ID_MODEL_FROM_DATABASE=PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008605* ID_MODEL_FROM_DATABASE=PEX 8605 PCI Express 4-port Gen2 Switch pci:v000010B5d00008606* ID_MODEL_FROM_DATABASE=PEX 8606 6 Lane, 6 Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008608* ID_MODEL_FROM_DATABASE=PEX 8608 8-lane, 8-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008609* ID_MODEL_FROM_DATABASE=PEX 8609 8-lane, 8-Port PCI Express Gen 2 (5.0 GT/s) Switch with DMA pci:v000010B5d00008612* ID_MODEL_FROM_DATABASE=PEX 8612 12-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008613* ID_MODEL_FROM_DATABASE=PEX 8613 12-lane, 3-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008614* ID_MODEL_FROM_DATABASE=PEX 8614 12-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008615* ID_MODEL_FROM_DATABASE=PEX 8615 12-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch with DMA pci:v000010B5d00008616* ID_MODEL_FROM_DATABASE=PEX 8616 16-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008617* ID_MODEL_FROM_DATABASE=PEX 8617 16-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch with P2P pci:v000010B5d00008618* ID_MODEL_FROM_DATABASE=PEX 8618 16-lane, 16-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008619* ID_MODEL_FROM_DATABASE=PEX 8619 16-lane, 16-Port PCI Express Gen 2 (5.0 GT/s) Switch with DMA pci:v000010B5d00008624* ID_MODEL_FROM_DATABASE=PEX 8624 24-lane, 6-Port PCI Express Gen 2 (5.0 GT/s) Switch [ExpressLane] pci:v000010B5d00008624sv000013A3sd00001845* ID_MODEL_FROM_DATABASE=PEX 8624 24-lane, 6-Port PCI Express Gen 2 (5.0 GT/s) Switch [ExpressLane] (DX1845 Acceleration Card) pci:v000010B5d00008625* ID_MODEL_FROM_DATABASE=PEX 8625 24-lane, 24-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008632* ID_MODEL_FROM_DATABASE=PEX 8632 32-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008636* ID_MODEL_FROM_DATABASE=PEX 8636 36-lane, 24-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008647* ID_MODEL_FROM_DATABASE=PEX 8647 48-Lane, 3-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008648* ID_MODEL_FROM_DATABASE=PEX 8648 48-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008649* ID_MODEL_FROM_DATABASE=PEX 8649 48-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008664* ID_MODEL_FROM_DATABASE=PEX 8664 64-lane, 16-Port PCI Express Gen 2 (5.0 GT/s) Switch pci:v000010B5d00008680* ID_MODEL_FROM_DATABASE=PEX 8680 80-lane, 20-Port PCI Express Gen 2 (5.0 GT/s) Multi-Root Switch pci:v000010B5d00008696* ID_MODEL_FROM_DATABASE=PEX 8696 96-lane, 24-Port PCI Express Gen 2 (5.0 GT/s) Multi-Root Switch pci:v000010B5d00008717* ID_MODEL_FROM_DATABASE=PEX 8717 16-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch with DMA pci:v000010B5d00008718* ID_MODEL_FROM_DATABASE=PEX 8718 16-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch pci:v000010B5d00008732* ID_MODEL_FROM_DATABASE=PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch pci:v000010B5d00008734* ID_MODEL_FROM_DATABASE=PEX 8734 32-lane, 8-Port PCI Express Gen 3 (8.0GT/s) Switch pci:v000010B5d00008747* ID_MODEL_FROM_DATABASE=PEX 8747 48-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch pci:v000010B5d000087B0* ID_MODEL_FROM_DATABASE=PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch pci:v000010B5d000087B0sv00001093sd00007761* ID_MODEL_FROM_DATABASE=PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch (PXIe-8830mc) pci:v000010B5d00009016* ID_MODEL_FROM_DATABASE=PLX 9016 8-port serial controller pci:v000010B5d00009030* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge pci:v000010B5d00009030sv000010B5sd00002695* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Hilscher CIF50-PB/DPS Profibus) pci:v000010B5d00009030sv000010B5sd00002862* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI LV (3V/5V): Timecode Reader Board) pci:v000010B5d00009030sv000010B5sd00002906* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Alpermann+Velte PCI TS (3V/5V): Time Synchronisation Board) pci:v000010B5d00009030sv000010B5sd00002940* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI D (3V/5V): Timecode Reader Board) pci:v000010B5d00009030sv000010B5sd00002977* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (IXXAT iPC-I XC16/PCI CAN Board) pci:v000010B5d00009030sv000010B5sd00002978* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (SH ARC-PCIu/SH ARC-PCI104/SH ARC-PCIe SOHARD ARCNET card) pci:v000010B5d00009030sv000010B5sd00003025* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI L (3V/5V): Timecode Reader Board) pci:v000010B5d00009030sv000010B5sd00003068* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI HD (3V/5V): Timecode Reader Board) pci:v000010B5d00009030sv000010B5sd00003463* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI D (v2) (3V/5V): Timecode Reader Board) pci:v000010B5d00009030sv000010B5sd00003591* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (PLURA PCL PCI L (v2) (3.3V/5V): Time Code Reader Board) pci:v000010B5d00009030sv000012FEsd00000111* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (CPCI-ASIO4 (ESD 4-port Serial Interface Board)) pci:v000010B5d00009030sv00001369sd00009C01* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (VX222v2) pci:v000010B5d00009030sv00001369sd00009D01* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (VX222-Mic) pci:v000010B5d00009030sv00001369sd00009D02* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (VX222-Mic) pci:v000010B5d00009030sv00001369sd00009E01* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (PCX924v2) pci:v000010B5d00009030sv00001369sd00009F01* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (PCX924-Mic) pci:v000010B5d00009030sv00001369sd00009F02* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (PCX924-Mic) pci:v000010B5d00009030sv00001369sd0000A001* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (PCX22v2) pci:v000010B5d00009030sv00001369sd0000A701* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (LCM220v2) pci:v000010B5d00009030sv00001369sd0000A801* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (LCM200) pci:v000010B5d00009030sv00001397sd00003136* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (4xS0-ISDN PCI Adapter) pci:v000010B5d00009030sv00001397sd00003137* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (S2M-E1-ISDN PCI Adapter) pci:v000010B5d00009030sv00001518sd00000200* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (ThinkIO-C) pci:v000010B5d00009030sv000015EDsd00001002* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (MCCS 8-port Serial Hot Swap) pci:v000010B5d00009030sv000015EDsd00001003* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (MCCS 16-port Serial Hot Swap) pci:v000010B5d00009030sv0000E1C5sd00000001* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (TE1-PCI) pci:v000010B5d00009030sv0000E1C5sd00000005* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (TA1-PCI) pci:v000010B5d00009030sv0000E1C5sd00000006* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (TA1-PCI4) pci:v000010B5d00009036* ID_MODEL_FROM_DATABASE=9036 pci:v000010B5d00009050* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge pci:v000010B5d00009050sv000010B5sd00001067* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IXXAT CAN i165) pci:v000010B5d00009050sv000010B5sd0000114E* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Wasco WITIO PCI168extended) pci:v000010B5d00009050sv000010B5sd00001169* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Wasco OPTOIO32standard 32 digital in, 32 digital out) pci:v000010B5d00009050sv000010B5sd00001172* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IK220 (Heidenhain)) pci:v000010B5d00009050sv000010B5sd00002036* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (SatPak GPS) pci:v000010B5d00009050sv000010B5sd00002221* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI LV: Timecode Reader Board) pci:v000010B5d00009050sv000010B5sd00002273* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (SH ARC-PCI SOHARD ARCNET card) pci:v000010B5d00009050sv000010B5sd00002431* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI D: Timecode Reader Board) pci:v000010B5d00009050sv000010B5sd00002905* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Alpermann+Velte PCI TS: Time Synchronisation Board) pci:v000010B5d00009050sv000010B5sd00003196* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Goramo PLX200SYN sync serial card) pci:v000010B5d00009050sv000010B5sd00009050* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (PCI-I04 PCI Passive PC/CAN Interface) pci:v000010B5d00009050sv00001369sd00008901* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (PCX11+ PCI) pci:v000010B5d00009050sv00001369sd00008F01* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (VX222) pci:v000010B5d00009050sv00001369sd00009401* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (PCX924) pci:v000010B5d00009050sv00001369sd00009501* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (PCX22) pci:v000010B5d00009050sv00001498sd00000362* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (TPMC866 8 Channel Serial Card) pci:v000010B5d00009050sv00001522sd00000001* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce 4 Port V.90 Data/Fax/Voice Modem) pci:v000010B5d00009050sv00001522sd00000002* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce 2 Port V.90 Data/Fax/Voice Modem) pci:v000010B5d00009050sv00001522sd00000003* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce 6 Port V.90 Data/Fax/Voice Modem) pci:v000010B5d00009050sv00001522sd00000004* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce 8 Port V.90 Data/Fax/Voice Modem) pci:v000010B5d00009050sv00001522sd00000010* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce2000 4 Port V.90 Data/Fax/Voice Modem) pci:v000010B5d00009050sv00001522sd00000020* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce2000 2 Port V.90 Data/Fax/Voice Modem) pci:v000010B5d00009050sv000015EDsd00001000* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Macrolink MCCS 8-port Serial) pci:v000010B5d00009050sv000015EDsd00001001* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Macrolink MCCS 16-port Serial) pci:v000010B5d00009050sv000015EDsd00001002* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Macrolink MCCS 8-port Serial Hot Swap) pci:v000010B5d00009050sv000015EDsd00001003* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Macrolink MCCS 16-port Serial Hot Swap) pci:v000010B5d00009050sv00005654sd00002036* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (OpenSwitch 6 Telephony card) pci:v000010B5d00009050sv00005654sd00003132* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (OpenSwitch 12 Telephony card) pci:v000010B5d00009050sv00005654sd00005634* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (OpenLine4 Telephony Card) pci:v000010B5d00009050sv0000D531sd0000C002* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (PCIntelliCAN 2xSJA1000 CAN bus) pci:v000010B5d00009050sv0000D84Dsd00004006* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4006 1P) pci:v000010B5d00009050sv0000D84Dsd00004008* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4008 1P EPP/ECP) pci:v000010B5d00009050sv0000D84Dsd00004014* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4014 2P) pci:v000010B5d00009050sv0000D84Dsd00004018* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4018 3P EPP/ECP) pci:v000010B5d00009050sv0000D84Dsd00004025* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4025 1S(16C550) RS-232) pci:v000010B5d00009050sv0000D84Dsd00004027* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4027 1S(16C650) RS-232) pci:v000010B5d00009050sv0000D84Dsd00004028* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4028 1S(16C850) RS-232) pci:v000010B5d00009050sv0000D84Dsd00004036* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4036 2S(16C650) RS-232) pci:v000010B5d00009050sv0000D84Dsd00004037* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4037 2S(16C650) RS-232) pci:v000010B5d00009050sv0000D84Dsd00004038* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4038 2S(16C850) RS-232) pci:v000010B5d00009050sv0000D84Dsd00004052* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4052 1S(16C550) RS-422/485) pci:v000010B5d00009050sv0000D84Dsd00004053* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4053 2S(16C550) RS-422/485) pci:v000010B5d00009050sv0000D84Dsd00004055* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4055 4S(16C550) RS-232) pci:v000010B5d00009050sv0000D84Dsd00004058* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4055 4S(16C650) RS-232) pci:v000010B5d00009050sv0000D84Dsd00004065* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4065 8S(16C550) RS-232) pci:v000010B5d00009050sv0000D84Dsd00004068* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4068 8S(16C650) RS-232) pci:v000010B5d00009050sv0000D84Dsd00004078* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4078 2S(16C552) RS-232+1P) pci:v000010B5d00009052* ID_MODEL_FROM_DATABASE=PCI9052 PCI <-> IOBus Bridge pci:v000010B5d00009054* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge pci:v000010B5d00009054sv000010B5sd00002455* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Wessex Techology PHIL-PCI) pci:v000010B5d00009054sv000010B5sd00002696* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Innes Corp AM Radcap card) pci:v000010B5d00009054sv000010B5sd00002717* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Innes Corp Auricon card) pci:v000010B5d00009054sv000010B5sd00002844* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Innes Corp TVS Encoder card) pci:v000010B5d00009054sv000012C7sd00004001* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Intel Dialogic DM/V960-4T1 PCI) pci:v000010B5d00009054sv000012D9sd00000002* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PCI Prosody Card rev 1.5) pci:v000010B5d00009054sv000014B4sd0000D100* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Dektec DTA-100) pci:v000010B5d00009054sv000014B4sd0000D114* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Dektec DTA-120) pci:v000010B5d00009054sv000016DFsd00000011* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PIKA PrimeNet MM PCI) pci:v000010B5d00009054sv000016DFsd00000012* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PIKA PrimeNet MM cPCI 8) pci:v000010B5d00009054sv000016DFsd00000013* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PIKA PrimeNet MM cPCI 8 (without CAS Signaling)) pci:v000010B5d00009054sv000016DFsd00000014* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PIKA PrimeNet MM cPCI 4) pci:v000010B5d00009054sv000016DFsd00000015* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PIKA Daytona MM) pci:v000010B5d00009054sv000016DFsd00000016* ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PIKA InLine MM) pci:v000010B5d00009056* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge pci:v000010B5d00009056sv000010B5sd00002979* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (CellinkBlade 11 - CPCI board VoATM AAL1) pci:v000010B5d00009056sv000010B5sd00003268* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (IXXAT iPC-I XC16/PCIe CAN Board) pci:v000010B5d00009056sv000010B5sd00003352* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCIe HD: Timecode Reader Board) pci:v000010B5d00009056sv000010B5sd00003353* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCIe D: Timecode Reader Board) pci:v000010B5d00009056sv000010B5sd00003354* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCIe LV: Timecode Reader Board) pci:v000010B5d00009056sv000010B5sd00003355* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCIe L: Timecode Reader Board) pci:v000010B5d00009056sv000010B5sd00003415* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Alpermann+Velte PCIe TS: Time Synchronisation Board) pci:v000010B5d00009056sv000010B5sd00003493* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCIe 3G: Timecode Reader Board) pci:v000010B5d00009056sv00001369sd0000C001* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (LX6464ES) pci:v000010B5d00009056sv00001369sd0000C201* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (LX1616ES) pci:v000010B5d00009056sv000014B4sd0000D10A* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (DekTec DTA-110T) pci:v000010B5d00009056sv000014B4sd0000D128* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Dektec DTA-140) pci:v000010B5d00009056sv000014B4sd0000D140* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Dektec DTA-140) pci:v000010B5d00009056sv00001A0Esd0000006F* ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Dektec DTA-111) pci:v000010B5d00009060* ID_MODEL_FROM_DATABASE=PCI9060 32-bit 33MHz PCI <-> IOBus Bridge pci:v000010B5d0000906D* ID_MODEL_FROM_DATABASE=9060SD pci:v000010B5d0000906Dsv0000125Csd00000640* ID_MODEL_FROM_DATABASE=9060SD (Aries 16000P) pci:v000010B5d0000906E* ID_MODEL_FROM_DATABASE=9060ES pci:v000010B5d00009080* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge pci:v000010B5d00009080sv0000103Csd000010EB* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge ((Agilent) E2777B 83K Series Optical Communication Interface) pci:v000010B5d00009080sv0000103Csd000010EC* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge ((Agilent) E6978-66442 PCI CIC) pci:v000010B5d00009080sv000010B5sd00001123* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (Sectra KK631 encryption board) pci:v000010B5d00009080sv000010B5sd00009080* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (9080 [real subsystem ID not set]) pci:v000010B5d00009080sv000012D9sd00000002* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (PCI Prosody Card) pci:v000010B5d00009080sv000012DFsd00004422* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (4422PCI ["Do-All" Telemetry Data Aquisition System]) pci:v000010B5d00009080sv00001369sd00009601* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (PCX822np) pci:v000010B5d00009080sv00001369sd0000A102* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (PCX822v2) pci:v000010B5d00009080sv00001369sd0000A201* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (PCX442) pci:v000010B5d00009080sv00001369sd0000A301* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (LCM440v2) pci:v000010B5d00009080sv00001369sd0000A401* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (VX822) pci:v000010B5d00009080sv00001369sd0000A402* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (VX822v2) pci:v000010B5d00009080sv00001369sd0000A901* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (LCM420) pci:v000010B5d00009080sv00001369sd0000AA01* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (VX820v2) pci:v000010B5d00009080sv00001517sd0000000B* ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (ECSG-1R3ADC-PMC Clock synthesizer) pci:v000010B5d00009656* ID_MODEL_FROM_DATABASE=PCI9656 PCI <-> IOBus Bridge pci:v000010B5d00009656sv00001517sd0000000F* ID_MODEL_FROM_DATABASE=PCI9656 PCI <-> IOBus Bridge (ECDR-GC314-PMC Receiver) pci:v000010B5d00009656sv00001885sd00000700* ID_MODEL_FROM_DATABASE=PCI9656 PCI <-> IOBus Bridge (Tsunami FPGA PMC with Altera Stratix S40) pci:v000010B5d00009656sv00001885sd00000701* ID_MODEL_FROM_DATABASE=PCI9656 PCI <-> IOBus Bridge (Tsunami FPGA PMC with Altera Stratix S30) pci:v000010B5d00009733* ID_MODEL_FROM_DATABASE=PEX 9733 33-lane, 9-port PCI Express Gen 3 (8.0 GT/s) Switch pci:v000010B5d00009749* ID_MODEL_FROM_DATABASE=PEX 9749 49-lane, 13-port PCI Express Gen 3 (8.0 GT/s) Switch pci:v000010B5d0000A100* ID_MODEL_FROM_DATABASE=Blackmagic Design DeckLink pci:v000010B5d0000BB04* ID_MODEL_FROM_DATABASE=B&B 3PCIOSD1A Isolated PCI Serial pci:v000010B5d0000C001* ID_MODEL_FROM_DATABASE=CronyxOmega-PCI (8-port RS232) pci:v000010B5d0000D00D* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge pci:v000010B5d0000D00Dsv000010B5sd00009030* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Digium Tormenta 2 T400P or E400P Quad T1 or E1 PCI card) pci:v000010B5d0000D33D* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge pci:v000010B5d0000D33Dsv000010B5sd00009030* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Tormenta 3 Varion V401PT Quad T1/J1 PCI card) pci:v000010B5d0000D44D* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge pci:v000010B5d0000D44Dsv000010B5sd000017F6* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Allo CP100P/E 1-port E1/T1/J1 PCI/PCIe card) pci:v000010B5d0000D44Dsv000010B5sd000017F7* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Allo CP400P/E 4-port E1/T1/J1 PCI/PCIe card) pci:v000010B5d0000D44Dsv000010B5sd000017F8* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Allo CP200P/E 2-port E1/T1/J1 PCI/PCIe card) pci:v000010B5d0000D44Dsv000010B5sd00009030* ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Tormenta 3 Varion V401PE Quad E1 PCI card) pci:v000010B6* ID_VENDOR_FROM_DATABASE=Madge Networks pci:v000010B6d00000001* ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode pci:v000010B6d00000002* ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk2 pci:v000010B6d00000002sv000010B6sd00000002* ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk2 pci:v000010B6d00000002sv000010B6sd00000006* ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk2 (16/4 CardBus Adapter) pci:v000010B6d00000003* ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk3 pci:v000010B6d00000003sv00000E11sd0000B0FD* ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk3 (Compaq NC4621 PCI, 4/16, WOL) pci:v000010B6d00000003sv000010B6sd00000003* ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk3 pci:v000010B6d00000003sv000010B6sd00000007* ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk3 (Presto PCI Plus Adapter) pci:v000010B6d00000004* ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk1 pci:v000010B6d00000006* ID_MODEL_FROM_DATABASE=16/4 Cardbus Adapter pci:v000010B6d00000006sv000010B6sd00000006* ID_MODEL_FROM_DATABASE=16/4 Cardbus Adapter (16/4 CardBus Adapter) pci:v000010B6d00000007* ID_MODEL_FROM_DATABASE=Presto PCI Adapter pci:v000010B6d00000007sv000010B6sd00000007* ID_MODEL_FROM_DATABASE=Presto PCI Adapter (Presto PCI) pci:v000010B6d00000009* ID_MODEL_FROM_DATABASE=Smart 100/16/4 PCI-HS Ringnode pci:v000010B6d00000009sv000010B6sd00000009* ID_MODEL_FROM_DATABASE=Smart 100/16/4 PCI-HS Ringnode pci:v000010B6d0000000A* ID_MODEL_FROM_DATABASE=Token Ring 100/16/4 Ringnode/Ringrunner pci:v000010B6d0000000Asv000010B6sd0000000A* ID_MODEL_FROM_DATABASE=Token Ring 100/16/4 Ringnode/Ringrunner pci:v000010B6d0000000B* ID_MODEL_FROM_DATABASE=16/4 CardBus Adapter Mk2 pci:v000010B6d0000000Bsv000010B6sd00000008* ID_MODEL_FROM_DATABASE=16/4 CardBus Adapter Mk2 pci:v000010B6d0000000Bsv000010B6sd0000000B* ID_MODEL_FROM_DATABASE=16/4 CardBus Adapter Mk2 (16/4 Cardbus Adapter Mk2) pci:v000010B6d0000000C* ID_MODEL_FROM_DATABASE=RapidFire 3140V2 16/4 TR Adapter pci:v000010B6d0000000Csv000010B6sd0000000C* ID_MODEL_FROM_DATABASE=RapidFire 3140V2 16/4 TR Adapter pci:v000010B6d00001000* ID_MODEL_FROM_DATABASE=Collage 25/155 ATM Client Adapter pci:v000010B6d00001001* ID_MODEL_FROM_DATABASE=Collage 155 ATM Server Adapter pci:v000010B7* ID_VENDOR_FROM_DATABASE=3Com Corporation pci:v000010B7d00000001* ID_MODEL_FROM_DATABASE=3c985 1000BaseSX (SX/TX) pci:v000010B7d00000001sv00009850sd00000001* ID_MODEL_FROM_DATABASE=3c985 1000BaseSX (SX/TX) (3c985B-SX) pci:v000010B7d00000013* ID_MODEL_FROM_DATABASE=AR5212 802.11abg NIC (3CRDAG675) pci:v000010B7d00000013sv000010B7sd00002031* ID_MODEL_FROM_DATABASE=AR5212 802.11abg NIC (3CRDAG675) (3CRDAG675 11a/b/g Wireless PCI Adapter) pci:v000010B7d00000910* ID_MODEL_FROM_DATABASE=3C910-A01 pci:v000010B7d00001006* ID_MODEL_FROM_DATABASE=MINI PCI type 3B Data Fax Modem pci:v000010B7d00001007* ID_MODEL_FROM_DATABASE=Mini PCI 56k Winmodem pci:v000010B7d00001007sv000010B7sd0000615B* ID_MODEL_FROM_DATABASE=Mini PCI 56k Winmodem (Mini PCI 56K Modem) pci:v000010B7d00001007sv000010B7sd0000615C* ID_MODEL_FROM_DATABASE=Mini PCI 56k Winmodem (Mini PCI 56K Modem) pci:v000010B7d00001201* ID_MODEL_FROM_DATABASE=3c982-TXM 10/100baseTX Dual Port A [Hydra] pci:v000010B7d00001202* ID_MODEL_FROM_DATABASE=3c982-TXM 10/100baseTX Dual Port B [Hydra] pci:v000010B7d00001700* ID_MODEL_FROM_DATABASE=3c940 10/100/1000Base-T [Marvell] pci:v000010B7d00001700sv00001043sd000080EB* ID_MODEL_FROM_DATABASE=3c940 10/100/1000Base-T [Marvell] (A7V600/P4P800/K8V motherboard) pci:v000010B7d00001700sv000010B7sd00000010* ID_MODEL_FROM_DATABASE=3c940 10/100/1000Base-T [Marvell] (3C940 Gigabit LOM Ethernet Adapter) pci:v000010B7d00001700sv000010B7sd00000020* ID_MODEL_FROM_DATABASE=3c940 10/100/1000Base-T [Marvell] (3C941 Gigabit LOM Ethernet Adapter) pci:v000010B7d00001700sv0000147Bsd00001407* ID_MODEL_FROM_DATABASE=3c940 10/100/1000Base-T [Marvell] (KV8-MAX3 motherboard) pci:v000010B7d00003390* ID_MODEL_FROM_DATABASE=3c339 TokenLink Velocity pci:v000010B7d00003590* ID_MODEL_FROM_DATABASE=3c359 TokenLink Velocity XL pci:v000010B7d00003590sv000010B7sd00003590* ID_MODEL_FROM_DATABASE=3c359 TokenLink Velocity XL (TokenLink Velocity XL Adapter (3C359/359B)) pci:v000010B7d00004500* ID_MODEL_FROM_DATABASE=3c450 HomePNA [Tornado] pci:v000010B7d00005055* ID_MODEL_FROM_DATABASE=3c555 Laptop Hurricane pci:v000010B7d00005057* ID_MODEL_FROM_DATABASE=3c575 Megahertz 10/100 LAN CardBus [Boomerang] pci:v000010B7d00005057sv000010B7sd00005A57* ID_MODEL_FROM_DATABASE=3c575 Megahertz 10/100 LAN CardBus [Boomerang] (3C575 Megahertz 10/100 LAN Cardbus PC Card) pci:v000010B7d00005157* ID_MODEL_FROM_DATABASE=3cCFE575BT Megahertz 10/100 LAN CardBus [Cyclone] pci:v000010B7d00005157sv000010B7sd00005B57* ID_MODEL_FROM_DATABASE=3cCFE575BT Megahertz 10/100 LAN CardBus [Cyclone] (3C575 Megahertz 10/100 LAN Cardbus PC Card) pci:v000010B7d00005257* ID_MODEL_FROM_DATABASE=3cCFE575CT CardBus [Cyclone] pci:v000010B7d00005257sv000010B7sd00005C57* ID_MODEL_FROM_DATABASE=3cCFE575CT CardBus [Cyclone] (FE575C-3Com 10/100 LAN CardBus-Fast Ethernet) pci:v000010B7d00005900* ID_MODEL_FROM_DATABASE=3c590 10BaseT [Vortex] pci:v000010B7d00005920* ID_MODEL_FROM_DATABASE=3c592 EISA 10mbps Demon/Vortex pci:v000010B7d00005950* ID_MODEL_FROM_DATABASE=3c595 100BaseTX [Vortex] pci:v000010B7d00005951* ID_MODEL_FROM_DATABASE=3c595 100BaseT4 [Vortex] pci:v000010B7d00005952* ID_MODEL_FROM_DATABASE=3c595 100Base-MII [Vortex] pci:v000010B7d00005970* ID_MODEL_FROM_DATABASE=3c597 EISA Fast Demon/Vortex pci:v000010B7d00005B57* ID_MODEL_FROM_DATABASE=3c595 Megahertz 10/100 LAN CardBus [Boomerang] pci:v000010B7d00005B57sv000010B7sd00005B57* ID_MODEL_FROM_DATABASE=3c595 Megahertz 10/100 LAN CardBus [Boomerang] (3C575 Megahertz 10/100 LAN Cardbus PC Card) pci:v000010B7d00006000* ID_MODEL_FROM_DATABASE=3CRSHPW796 [OfficeConnect Wireless CardBus] pci:v000010B7d00006001* ID_MODEL_FROM_DATABASE=3com 3CRWE154G72 [Office Connect Wireless LAN Adapter] pci:v000010B7d00006055* ID_MODEL_FROM_DATABASE=3c556 Hurricane CardBus [Cyclone] pci:v000010B7d00006056* ID_MODEL_FROM_DATABASE=3c556B CardBus [Tornado] pci:v000010B7d00006056sv000010B7sd00006556* ID_MODEL_FROM_DATABASE=3c556B CardBus [Tornado] (10/100 Mini PCI Ethernet Adapter) pci:v000010B7d00006560* ID_MODEL_FROM_DATABASE=3cCFE656 CardBus [Cyclone] pci:v000010B7d00006560sv000010B7sd0000656A* ID_MODEL_FROM_DATABASE=3cCFE656 CardBus [Cyclone] (3CCFEM656 10/100 LAN+56K Modem CardBus) pci:v000010B7d00006561* ID_MODEL_FROM_DATABASE=3cCFEM656 10/100 LAN+56K Modem CardBus pci:v000010B7d00006561sv000010B7sd0000656B* ID_MODEL_FROM_DATABASE=3cCFEM656 10/100 LAN+56K Modem CardBus (3CCFEM656 10/100 LAN+56K Modem CardBus) pci:v000010B7d00006562* ID_MODEL_FROM_DATABASE=3cCFEM656B 10/100 LAN+Winmodem CardBus [Cyclone] pci:v000010B7d00006562sv000010B7sd0000656B* ID_MODEL_FROM_DATABASE=3cCFEM656B 10/100 LAN+Winmodem CardBus [Cyclone] (3CCFEM656B 10/100 LAN+56K Modem CardBus) pci:v000010B7d00006563* ID_MODEL_FROM_DATABASE=3cCFEM656B 10/100 LAN+56K Modem CardBus pci:v000010B7d00006563sv000010B7sd0000656B* ID_MODEL_FROM_DATABASE=3cCFEM656B 10/100 LAN+56K Modem CardBus (3CCFEM656 10/100 LAN+56K Modem CardBus) pci:v000010B7d00006564* ID_MODEL_FROM_DATABASE=3cXFEM656C 10/100 LAN+Winmodem CardBus [Tornado] pci:v000010B7d00007646* ID_MODEL_FROM_DATABASE=3cSOHO100-TX Hurricane pci:v000010B7d00007770* ID_MODEL_FROM_DATABASE=3CRWE777 PCI Wireless Adapter [Airconnect] pci:v000010B7d00007940* ID_MODEL_FROM_DATABASE=3c803 FDDILink UTP Controller pci:v000010B7d00007980* ID_MODEL_FROM_DATABASE=3c804 FDDILink SAS Controller pci:v000010B7d00007990* ID_MODEL_FROM_DATABASE=3c805 FDDILink DAS Controller pci:v000010B7d000080EB* ID_MODEL_FROM_DATABASE=3c940B 10/100/1000Base-T pci:v000010B7d00008811* ID_MODEL_FROM_DATABASE=Token ring pci:v000010B7d00009000* ID_MODEL_FROM_DATABASE=3c900 10BaseT [Boomerang] pci:v000010B7d00009001* ID_MODEL_FROM_DATABASE=3c900 10Mbps Combo [Boomerang] pci:v000010B7d00009004* ID_MODEL_FROM_DATABASE=3c900B-TPO Etherlink XL [Cyclone] pci:v000010B7d00009004sv000010B7sd00009004* ID_MODEL_FROM_DATABASE=3c900B-TPO Etherlink XL [Cyclone] (3C900B-TPO Etherlink XL TPO 10Mb) pci:v000010B7d00009005* ID_MODEL_FROM_DATABASE=3c900B-Combo Etherlink XL [Cyclone] pci:v000010B7d00009005sv000010B7sd00009005* ID_MODEL_FROM_DATABASE=3c900B-Combo Etherlink XL [Cyclone] (3C900B-Combo Etherlink XL Combo) pci:v000010B7d00009006* ID_MODEL_FROM_DATABASE=3c900B-TPC Etherlink XL [Cyclone] pci:v000010B7d0000900A* ID_MODEL_FROM_DATABASE=3c900B-FL 10base-FL [Cyclone] pci:v000010B7d00009050* ID_MODEL_FROM_DATABASE=3c905 100BaseTX [Boomerang] pci:v000010B7d00009051* ID_MODEL_FROM_DATABASE=3c905 100BaseT4 [Boomerang] pci:v000010B7d00009054* ID_MODEL_FROM_DATABASE=3C905B-TX Fast Etherlink XL PCI pci:v000010B7d00009054sv000010B7sd00009054* ID_MODEL_FROM_DATABASE=3C905B-TX Fast Etherlink XL PCI pci:v000010B7d00009055* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] pci:v000010B7d00009055sv00001028sd00000080* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000081* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000082* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000083* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000084* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000085* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000086* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000087* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000088* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000089* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000090* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000091* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000092* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000093* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000094* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000095* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000096* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000097* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000098* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv00001028sd00000099* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009055sv000010B7sd00009055* ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) pci:v000010B7d00009056* ID_MODEL_FROM_DATABASE=3c905B-T4 Fast EtherLink XL [Cyclone] pci:v000010B7d00009058* ID_MODEL_FROM_DATABASE=3c905B Deluxe Etherlink 10/100/BNC [Cyclone] pci:v000010B7d0000905A* ID_MODEL_FROM_DATABASE=3c905B-FX Fast Etherlink XL FX 100baseFx [Cyclone] pci:v000010B7d00009200* ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] pci:v000010B7d00009200sv00001028sd00000095* ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (3C920 Integrated Fast Ethernet Controller) pci:v000010B7d00009200sv00001028sd00000097* ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (3C920 Integrated Fast Ethernet Controller) pci:v000010B7d00009200sv00001028sd000000B4* ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (OptiPlex GX110) pci:v000010B7d00009200sv00001028sd000000D8* ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (Precision 530) pci:v000010B7d00009200sv00001028sd000000FE* ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (Optiplex GX240) pci:v000010B7d00009200sv00001028sd0000012A* ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (3C920 Integrated Fast Ethernet Controller [Latitude C640]) pci:v000010B7d00009200sv000010B7sd00001000* ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (3C905CX-TX/TX-M Fast Etherlink for PC Management NIC) pci:v000010B7d00009200sv000010B7sd00007000* ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (10/100 Mini PCI Ethernet Adapter) pci:v000010B7d00009200sv000010F1sd00002466* ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (Tiger MPX S2466 (3C920 Integrated Fast Ethernet Controller)) pci:v000010B7d00009200sv0000144Dsd0000C005* ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (X10 Laptop) pci:v000010B7d00009201* ID_MODEL_FROM_DATABASE=3C920B-EMB Integrated Fast Ethernet Controller [Tornado] pci:v000010B7d00009201sv00001043sd000080AB* ID_MODEL_FROM_DATABASE=3C920B-EMB Integrated Fast Ethernet Controller [Tornado] (A7N8X Deluxe onboard 3C920B-EMB Integrated Fast Ethernet Controller) pci:v000010B7d00009202* ID_MODEL_FROM_DATABASE=3Com 3C920B-EMB-WNM Integrated Fast Ethernet Controller pci:v000010B7d00009210* ID_MODEL_FROM_DATABASE=3C920B-EMB-WNM Integrated Fast Ethernet Controller pci:v000010B7d00009300* ID_MODEL_FROM_DATABASE=3CSOHO100B-TX 910-A01 [tulip] pci:v000010B7d00009800* ID_MODEL_FROM_DATABASE=3c980-TX Fast Etherlink XL Server Adapter [Cyclone] pci:v000010B7d00009800sv000010B7sd00009800* ID_MODEL_FROM_DATABASE=3c980-TX Fast Etherlink XL Server Adapter [Cyclone] (3c980-TX Fast Etherlink XL Server Adapter) pci:v000010B7d00009805* ID_MODEL_FROM_DATABASE=3c980-C 10/100baseTX NIC [Python-T] pci:v000010B7d00009805sv000010B7sd00001201* ID_MODEL_FROM_DATABASE=3c980-C 10/100baseTX NIC [Python-T] (EtherLink Server 10/100 Dual Port A) pci:v000010B7d00009805sv000010B7sd00001202* ID_MODEL_FROM_DATABASE=3c980-C 10/100baseTX NIC [Python-T] (EtherLink Server 10/100 Dual Port B) pci:v000010B7d00009805sv000010B7sd00009805* ID_MODEL_FROM_DATABASE=3c980-C 10/100baseTX NIC [Python-T] (3c980 10/100baseTX NIC [Python-T]) pci:v000010B7d00009805sv000010F1sd00002462* ID_MODEL_FROM_DATABASE=3c980-C 10/100baseTX NIC [Python-T] (Thunder K7 S2462) pci:v000010B7d00009900* ID_MODEL_FROM_DATABASE=3C990-TX [Typhoon] pci:v000010B7d00009902* ID_MODEL_FROM_DATABASE=3CR990-TX-95 [Typhoon 56-bit] pci:v000010B7d00009903* ID_MODEL_FROM_DATABASE=3CR990-TX-97 [Typhoon 168-bit] pci:v000010B7d00009904* ID_MODEL_FROM_DATABASE=3C990B-TX-M/3C990BSVR [Typhoon2] pci:v000010B7d00009904sv000010B7sd00001000* ID_MODEL_FROM_DATABASE=3C990B-TX-M/3C990BSVR [Typhoon2] (3CR990B-TX-M [Typhoon2]) pci:v000010B7d00009904sv000010B7sd00002000* ID_MODEL_FROM_DATABASE=3C990B-TX-M/3C990BSVR [Typhoon2] (3CR990BSVR [Typhoon2 Server]) pci:v000010B7d00009905* ID_MODEL_FROM_DATABASE=3CR990-FX-95/97/95 [Typhon Fiber] pci:v000010B7d00009905sv000010B7sd00001101* ID_MODEL_FROM_DATABASE=3CR990-FX-95/97/95 [Typhon Fiber] (3CR990-FX-95 [Typhoon Fiber 56-bit]) pci:v000010B7d00009905sv000010B7sd00001102* ID_MODEL_FROM_DATABASE=3CR990-FX-95/97/95 [Typhon Fiber] (3CR990-FX-97 [Typhoon Fiber 168-bit]) pci:v000010B7d00009905sv000010B7sd00002101* ID_MODEL_FROM_DATABASE=3CR990-FX-95/97/95 [Typhon Fiber] (3CR990-FX-95 Server [Typhoon Fiber 56-bit]) pci:v000010B7d00009905sv000010B7sd00002102* ID_MODEL_FROM_DATABASE=3CR990-FX-95/97/95 [Typhon Fiber] (3CR990-FX-97 Server [Typhoon Fiber 168-bit]) pci:v000010B7d00009908* ID_MODEL_FROM_DATABASE=3CR990SVR95 [Typhoon Server 56-bit] pci:v000010B7d00009909* ID_MODEL_FROM_DATABASE=3CR990SVR97 [Typhoon Server 168-bit] pci:v000010B7d0000990A* ID_MODEL_FROM_DATABASE=3C990SVR [Typhoon Server] pci:v000010B7d0000990B* ID_MODEL_FROM_DATABASE=3C990SVR [Typhoon Server] pci:v000010B8* ID_VENDOR_FROM_DATABASE=Standard Microsystems Corp [SMC] pci:v000010B8d00000005* ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter pci:v000010B8d00000005sv00001055sd0000E000* ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (LANEPIC 10/100 [EVB171Q-PCI]) pci:v000010B8d00000005sv00001055sd0000E002* ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (LANEPIC 10/100 [EVB171G-PCI]) pci:v000010B8d00000005sv000010B8sd0000A011* ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (EtherPower II 10/100) pci:v000010B8d00000005sv000010B8sd0000A014* ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (EtherPower II 10/100) pci:v000010B8d00000005sv000010B8sd0000A015* ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (EtherPower II 10/100) pci:v000010B8d00000005sv000010B8sd0000A016* ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (EtherPower II 10/100) pci:v000010B8d00000005sv000010B8sd0000A017* ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (EtherPower II 10/100) pci:v000010B8d00000006* ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter pci:v000010B8d00000006sv00001055sd0000E100* ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) pci:v000010B8d00000006sv00001055sd0000E102* ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) pci:v000010B8d00000006sv00001055sd0000E300* ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) pci:v000010B8d00000006sv00001055sd0000E302* ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) pci:v000010B8d00000006sv000010B8sd0000A012* ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) pci:v000010B8d00000006sv000013A2sd00008002* ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) pci:v000010B8d00000006sv000013A2sd00008006* ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) pci:v000010B8d00001000* ID_MODEL_FROM_DATABASE=FDC 37c665 pci:v000010B8d00001001* ID_MODEL_FROM_DATABASE=FDC 37C922 pci:v000010B8d0000A011* ID_MODEL_FROM_DATABASE=83C170QF pci:v000010B8d0000B106* ID_MODEL_FROM_DATABASE=SMC34C90 pci:v000010B9* ID_VENDOR_FROM_DATABASE=ULi Electronics Inc. pci:v000010B9d00000101* ID_MODEL_FROM_DATABASE=CMI8338/C3DX PCI Audio Device pci:v000010B9d00000111* ID_MODEL_FROM_DATABASE=C-Media CMI8738/C3DX Audio Device (OEM) pci:v000010B9d00000111sv000010B9sd00000111* ID_MODEL_FROM_DATABASE=C-Media CMI8738/C3DX Audio Device (OEM) pci:v000010B9d00000780* ID_MODEL_FROM_DATABASE=Multi-IO Card pci:v000010B9d00000782* ID_MODEL_FROM_DATABASE=Multi-IO Card pci:v000010B9d00001435* ID_MODEL_FROM_DATABASE=M1435 pci:v000010B9d00001445* ID_MODEL_FROM_DATABASE=M1445 pci:v000010B9d00001449* ID_MODEL_FROM_DATABASE=M1449 pci:v000010B9d00001451* ID_MODEL_FROM_DATABASE=M1451 pci:v000010B9d00001461* ID_MODEL_FROM_DATABASE=M1461 pci:v000010B9d00001489* ID_MODEL_FROM_DATABASE=M1489 pci:v000010B9d00001511* ID_MODEL_FROM_DATABASE=M1511 [Aladdin] pci:v000010B9d00001512* ID_MODEL_FROM_DATABASE=M1512 [Aladdin] pci:v000010B9d00001513* ID_MODEL_FROM_DATABASE=M1513 [Aladdin] pci:v000010B9d00001521* ID_MODEL_FROM_DATABASE=M1521 [Aladdin III] pci:v000010B9d00001521sv000010B9sd00001521* ID_MODEL_FROM_DATABASE=M1521 [Aladdin III] (ALI M1521 Aladdin III CPU Bridge) pci:v000010B9d00001523* ID_MODEL_FROM_DATABASE=M1523 pci:v000010B9d00001523sv000010B9sd00001523* ID_MODEL_FROM_DATABASE=M1523 (ALI M1523 ISA Bridge) pci:v000010B9d00001531* ID_MODEL_FROM_DATABASE=M1531 [Aladdin IV] pci:v000010B9d00001533* ID_MODEL_FROM_DATABASE=M1533/M1535/M1543 PCI to ISA Bridge [Aladdin IV/V/V+] pci:v000010B9d00001533sv00001014sd0000053B* ID_MODEL_FROM_DATABASE=M1533/M1535/M1543 PCI to ISA Bridge [Aladdin IV/V/V+] (ThinkPad R40e) pci:v000010B9d00001533sv000010B9sd00001533* ID_MODEL_FROM_DATABASE=M1533/M1535/M1543 PCI to ISA Bridge [Aladdin IV/V/V+] (ALi M1533 Aladdin IV/V ISA Bridge) pci:v000010B9d00001541* ID_MODEL_FROM_DATABASE=M1541 pci:v000010B9d00001541sv000010B9sd00001541* ID_MODEL_FROM_DATABASE=M1541 (ALI M1541 Aladdin V/V+ AGP System Controller) pci:v000010B9d00001543* ID_MODEL_FROM_DATABASE=M1543 pci:v000010B9d00001563* ID_MODEL_FROM_DATABASE=M1563 HyperTransport South Bridge pci:v000010B9d00001563sv000010B9sd00001563* ID_MODEL_FROM_DATABASE=M1563 HyperTransport South Bridge (ASRock 939Dual-SATA2 Motherboard) pci:v000010B9d00001563sv00001849sd00001563* ID_MODEL_FROM_DATABASE=M1563 HyperTransport South Bridge (ASRock 939Dual-SATA2 Motherboard) pci:v000010B9d00001573* ID_MODEL_FROM_DATABASE=PCI to LPC Controller pci:v000010B9d00001575* ID_MODEL_FROM_DATABASE=M1575 South Bridge pci:v000010B9d00001621* ID_MODEL_FROM_DATABASE=M1621 pci:v000010B9d00001631* ID_MODEL_FROM_DATABASE=ALI M1631 PCI North Bridge Aladdin Pro III pci:v000010B9d00001632* ID_MODEL_FROM_DATABASE=M1632M Northbridge+Trident pci:v000010B9d00001641* ID_MODEL_FROM_DATABASE=ALI M1641 PCI North Bridge Aladdin Pro IV pci:v000010B9d00001644* ID_MODEL_FROM_DATABASE=M1644/M1644T Northbridge+Trident pci:v000010B9d00001646* ID_MODEL_FROM_DATABASE=M1646 Northbridge+Trident pci:v000010B9d00001647* ID_MODEL_FROM_DATABASE=M1647 Northbridge [MAGiK 1 / MobileMAGiK 1] pci:v000010B9d00001651* ID_MODEL_FROM_DATABASE=M1651/M1651T Northbridge [Aladdin-Pro 5/5M,Aladdin-Pro 5T/5TM] pci:v000010B9d00001671* ID_MODEL_FROM_DATABASE=M1671 Super P4 Northbridge [AGP4X,PCI and SDR/DDR] pci:v000010B9d00001672* ID_MODEL_FROM_DATABASE=M1672 Northbridge [CyberALADDiN-P4] pci:v000010B9d00001681* ID_MODEL_FROM_DATABASE=M1681 P4 Northbridge [AGP8X,HyperTransport and SDR/DDR] pci:v000010B9d00001687* ID_MODEL_FROM_DATABASE=M1687 K8 Northbridge [AGP8X and HyperTransport] pci:v000010B9d00001689* ID_MODEL_FROM_DATABASE=M1689 K8 Northbridge [Super K8 Single Chip] pci:v000010B9d00001695* ID_MODEL_FROM_DATABASE=M1695 Host Bridge pci:v000010B9d00001697* ID_MODEL_FROM_DATABASE=M1697 HTT Host Bridge pci:v000010B9d00003141* ID_MODEL_FROM_DATABASE=M3141 pci:v000010B9d00003143* ID_MODEL_FROM_DATABASE=M3143 pci:v000010B9d00003145* ID_MODEL_FROM_DATABASE=M3145 pci:v000010B9d00003147* ID_MODEL_FROM_DATABASE=M3147 pci:v000010B9d00003149* ID_MODEL_FROM_DATABASE=M3149 pci:v000010B9d00003151* ID_MODEL_FROM_DATABASE=M3151 pci:v000010B9d00003307* ID_MODEL_FROM_DATABASE=M3307 pci:v000010B9d00003309* ID_MODEL_FROM_DATABASE=M3309 pci:v000010B9d00003323* ID_MODEL_FROM_DATABASE=M3325 Video/Audio Decoder pci:v000010B9d00005212* ID_MODEL_FROM_DATABASE=M4803 pci:v000010B9d00005215* ID_MODEL_FROM_DATABASE=MS4803 pci:v000010B9d00005217* ID_MODEL_FROM_DATABASE=M5217H pci:v000010B9d00005219* ID_MODEL_FROM_DATABASE=M5219 pci:v000010B9d00005225* ID_MODEL_FROM_DATABASE=M5225 pci:v000010B9d00005228* ID_MODEL_FROM_DATABASE=M5228 ALi ATA/RAID Controller pci:v000010B9d00005229* ID_MODEL_FROM_DATABASE=M5229 IDE pci:v000010B9d00005229sv00001014sd0000050F* ID_MODEL_FROM_DATABASE=M5229 IDE (ThinkPad R30) pci:v000010B9d00005229sv00001014sd0000053D* ID_MODEL_FROM_DATABASE=M5229 IDE (ThinkPad R40e) pci:v000010B9d00005229sv0000103Csd00000024* ID_MODEL_FROM_DATABASE=M5229 IDE (Pavilion ze4400 builtin IDE) pci:v000010B9d00005229sv0000103Csd00000025* ID_MODEL_FROM_DATABASE=M5229 IDE (XE4500 Notebook) pci:v000010B9d00005229sv00001043sd00008053* ID_MODEL_FROM_DATABASE=M5229 IDE (A7A266 Motherboard IDE) pci:v000010B9d00005229sv00001849sd00005229* ID_MODEL_FROM_DATABASE=M5229 IDE (ASRock 939Dual-SATA2 Motherboard IDE (PATA)) pci:v000010B9d00005235* ID_MODEL_FROM_DATABASE=M5225 pci:v000010B9d00005237* ID_MODEL_FROM_DATABASE=USB 1.1 Controller pci:v000010B9d00005237sv00001014sd00000540* ID_MODEL_FROM_DATABASE=USB 1.1 Controller (ThinkPad R40e) pci:v000010B9d00005237sv0000103Csd00000024* ID_MODEL_FROM_DATABASE=USB 1.1 Controller (Pavilion ze4400 builtin USB) pci:v000010B9d00005237sv0000103Csd00000025* ID_MODEL_FROM_DATABASE=USB 1.1 Controller (XE4500 Notebook) pci:v000010B9d00005237sv0000104Dsd0000810F* ID_MODEL_FROM_DATABASE=USB 1.1 Controller (VAIO PCG-U1 USB/OHCI Revision 1.0) pci:v000010B9d00005237sv000010B9sd00005237* ID_MODEL_FROM_DATABASE=USB 1.1 Controller (ASRock 939Dual-SATA2 Motherboard) pci:v000010B9d00005237sv00001849sd00005237* ID_MODEL_FROM_DATABASE=USB 1.1 Controller (ASRock 939Dual-SATA2 Motherboard) pci:v000010B9d00005239* ID_MODEL_FROM_DATABASE=USB 2.0 Controller pci:v000010B9d00005239sv000010B9sd00005239* ID_MODEL_FROM_DATABASE=USB 2.0 Controller (ASRock 939Dual-SATA2 Motherboard) pci:v000010B9d00005239sv00001849sd00005239* ID_MODEL_FROM_DATABASE=USB 2.0 Controller (ASRock 939Dual-SATA2 Motherboard) pci:v000010B9d00005243* ID_MODEL_FROM_DATABASE=M1541 PCI to AGP Controller pci:v000010B9d00005246* ID_MODEL_FROM_DATABASE=AGP8X Controller pci:v000010B9d00005247* ID_MODEL_FROM_DATABASE=PCI to AGP Controller pci:v000010B9d00005249* ID_MODEL_FROM_DATABASE=M5249 HTT to PCI Bridge pci:v000010B9d0000524B* ID_MODEL_FROM_DATABASE=PCI Express Root Port pci:v000010B9d0000524C* ID_MODEL_FROM_DATABASE=PCI Express Root Port pci:v000010B9d0000524D* ID_MODEL_FROM_DATABASE=PCI Express Root Port pci:v000010B9d0000524E* ID_MODEL_FROM_DATABASE=PCI Express Root Port pci:v000010B9d00005251* ID_MODEL_FROM_DATABASE=M5251 P1394 OHCI 1.0 Controller pci:v000010B9d00005253* ID_MODEL_FROM_DATABASE=M5253 P1394 OHCI 1.1 Controller pci:v000010B9d00005261* ID_MODEL_FROM_DATABASE=M5261 Ethernet Controller pci:v000010B9d00005263* ID_MODEL_FROM_DATABASE=ULi 1689,1573 integrated ethernet. pci:v000010B9d00005281* ID_MODEL_FROM_DATABASE=ALi M5281 Serial ATA / RAID Host Controller pci:v000010B9d00005287* ID_MODEL_FROM_DATABASE=ULi 5287 SATA pci:v000010B9d00005288* ID_MODEL_FROM_DATABASE=ULi M5288 SATA pci:v000010B9d00005288sv00001043sd00008056* ID_MODEL_FROM_DATABASE=ULi M5288 SATA (A8R-MVP Mainboard) pci:v000010B9d00005289* ID_MODEL_FROM_DATABASE=ULi 5289 SATA pci:v000010B9d00005450* ID_MODEL_FROM_DATABASE=Lucent Technologies Soft Modem AMR pci:v000010B9d00005451* ID_MODEL_FROM_DATABASE=M5451 PCI AC-Link Controller Audio Device pci:v000010B9d00005451sv00001014sd00000506* ID_MODEL_FROM_DATABASE=M5451 PCI AC-Link Controller Audio Device (ThinkPad R30) pci:v000010B9d00005451sv00001014sd0000053E* ID_MODEL_FROM_DATABASE=M5451 PCI AC-Link Controller Audio Device (ThinkPad R40e) pci:v000010B9d00005451sv0000103Csd00000024* ID_MODEL_FROM_DATABASE=M5451 PCI AC-Link Controller Audio Device (Pavilion ze4400 builtin Audio) pci:v000010B9d00005451sv0000103Csd00000025* ID_MODEL_FROM_DATABASE=M5451 PCI AC-Link Controller Audio Device (XE4500 Notebook) pci:v000010B9d00005453* ID_MODEL_FROM_DATABASE=M5453 PCI AC-Link Controller Modem Device pci:v000010B9d00005455* ID_MODEL_FROM_DATABASE=M5455 PCI AC-Link Controller Audio Device pci:v000010B9d00005455sv000010B9sd00005455* ID_MODEL_FROM_DATABASE=M5455 PCI AC-Link Controller Audio Device (ASRock 939Dual-SATA2 Motherboard) pci:v000010B9d00005455sv00001849sd00000850* ID_MODEL_FROM_DATABASE=M5455 PCI AC-Link Controller Audio Device (ASRock 939Dual-SATA2 Motherboard) pci:v000010B9d00005457* ID_MODEL_FROM_DATABASE=M5457 AC'97 Modem Controller pci:v000010B9d00005457sv00001014sd00000535* ID_MODEL_FROM_DATABASE=M5457 AC'97 Modem Controller (ThinkPad R40e) pci:v000010B9d00005457sv0000103Csd00000024* ID_MODEL_FROM_DATABASE=M5457 AC'97 Modem Controller (Pavilion ze4400 builtin Modem Device) pci:v000010B9d00005457sv0000103Csd00000025* ID_MODEL_FROM_DATABASE=M5457 AC'97 Modem Controller (XE4500 Notebook) pci:v000010B9d00005459* ID_MODEL_FROM_DATABASE=SmartLink SmartPCI561 56K Modem pci:v000010B9d0000545A* ID_MODEL_FROM_DATABASE=SmartLink SmartPCI563 56K Modem pci:v000010B9d00005461* ID_MODEL_FROM_DATABASE=HD Audio Controller pci:v000010B9d00005471* ID_MODEL_FROM_DATABASE=M5471 Memory Stick Controller pci:v000010B9d00005473* ID_MODEL_FROM_DATABASE=M5473 SD-MMC Controller pci:v000010B9d00007101* ID_MODEL_FROM_DATABASE=M7101 Power Management Controller [PMU] pci:v000010B9d00007101sv00001014sd00000510* ID_MODEL_FROM_DATABASE=M7101 Power Management Controller [PMU] (ThinkPad R30) pci:v000010B9d00007101sv00001014sd0000053C* ID_MODEL_FROM_DATABASE=M7101 Power Management Controller [PMU] (ThinkPad R40e) pci:v000010B9d00007101sv0000103Csd00000024* ID_MODEL_FROM_DATABASE=M7101 Power Management Controller [PMU] (Pavilion ze4400) pci:v000010B9d00007101sv0000103Csd00000025* ID_MODEL_FROM_DATABASE=M7101 Power Management Controller [PMU] (XE4500 Notebook) pci:v000010B9d00007101sv00001849sd00007101* ID_MODEL_FROM_DATABASE=M7101 Power Management Controller [PMU] (ASRock 939Dual-SATA2 Motherboard) pci:v000010BA* ID_VENDOR_FROM_DATABASE=Mitsubishi Electric Corp. pci:v000010BAd00000301* ID_MODEL_FROM_DATABASE=AccelGraphics AccelECLIPSE pci:v000010BAd00000304* ID_MODEL_FROM_DATABASE=AccelGALAXY A2100 [OEM Evans & Sutherland] pci:v000010BAd00000308* ID_MODEL_FROM_DATABASE=Tornado 3000 [OEM Evans & Sutherland] pci:v000010BAd00000308sv000010DDsd00000024* ID_MODEL_FROM_DATABASE=Tornado 3000 [OEM Evans & Sutherland] (Tornado 3000) pci:v000010BAd00001002* ID_MODEL_FROM_DATABASE=VG500 [VolumePro Volume Rendering Accelerator] pci:v000010BB* ID_VENDOR_FROM_DATABASE=Dapha Electronics Corporation pci:v000010BC* ID_VENDOR_FROM_DATABASE=Advanced Logic Research pci:v000010BD* ID_VENDOR_FROM_DATABASE=Surecom Technology pci:v000010BDd00000E34* ID_MODEL_FROM_DATABASE=NE-34 pci:v000010BE* ID_VENDOR_FROM_DATABASE=Tseng Labs International Co. pci:v000010BF* ID_VENDOR_FROM_DATABASE=Most Inc pci:v000010C0* ID_VENDOR_FROM_DATABASE=Boca Research Inc. pci:v000010C1* ID_VENDOR_FROM_DATABASE=ICM Co., Ltd. pci:v000010C2* ID_VENDOR_FROM_DATABASE=Auspex Systems Inc. pci:v000010C3* ID_VENDOR_FROM_DATABASE=Samsung Semiconductors, Inc. pci:v000010C4* ID_VENDOR_FROM_DATABASE=Award Software International Inc. pci:v000010C5* ID_VENDOR_FROM_DATABASE=Xerox Corporation pci:v000010C6* ID_VENDOR_FROM_DATABASE=Rambus Inc. pci:v000010C7* ID_VENDOR_FROM_DATABASE=Media Vision pci:v000010C8* ID_VENDOR_FROM_DATABASE=Neomagic Corporation pci:v000010C8d00000001* ID_MODEL_FROM_DATABASE=NM2070 [MagicGraph 128] pci:v000010C8d00000002* ID_MODEL_FROM_DATABASE=NM2090 [MagicGraph 128V] pci:v000010C8d00000003* ID_MODEL_FROM_DATABASE=NM2093 [MagicGraph 128ZV] pci:v000010C8d00000004* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] pci:v000010C8d00000004sv00001014sd000000BA* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv00001025sd00001007* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv00001028sd00000074* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv00001028sd00000075* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv00001028sd0000007D* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv00001028sd0000007E* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv00001033sd0000802F* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv0000104Dsd0000801B* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv0000104Dsd0000802F* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv0000104Dsd0000830B* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv000010BAsd00000E00* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv000010C8sd00000004* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv000010CFsd00001029* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv000010F7sd00008308* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv000010F7sd00008309* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv000010F7sd0000830B* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv000010F7sd0000830D* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000004sv000010F7sd00008312* ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) pci:v000010C8d00000005* ID_MODEL_FROM_DATABASE=NM2200 [MagicGraph 256AV] pci:v000010C8d00000005sv00001014sd000000DD* ID_MODEL_FROM_DATABASE=NM2200 [MagicGraph 256AV] (ThinkPad 570) pci:v000010C8d00000005sv00001028sd00000088* ID_MODEL_FROM_DATABASE=NM2200 [MagicGraph 256AV] (Latitude CPi A) pci:v000010C8d00000006* ID_MODEL_FROM_DATABASE=NM2360 [MagicMedia 256ZX] pci:v000010C8d00000006sv00001014sd00000152* ID_MODEL_FROM_DATABASE=NM2360 [MagicMedia 256ZX] (ThinkPad 600X) pci:v000010C8d00000016* ID_MODEL_FROM_DATABASE=NM2380 [MagicMedia 256XL+] pci:v000010C8d00000016sv000010C8sd00000016* ID_MODEL_FROM_DATABASE=NM2380 [MagicMedia 256XL+] (MagicMedia 256XL+) pci:v000010C8d00000025* ID_MODEL_FROM_DATABASE=NM2230 [MagicGraph 256AV+] pci:v000010C8d00000083* ID_MODEL_FROM_DATABASE=NM2093 [MagicGraph 128ZV+] pci:v000010C8d00008005* ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] pci:v000010C8d00008005sv00000E11sd0000B0D1* ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on Discovery) pci:v000010C8d00008005sv00000E11sd0000B126* ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on Durango) pci:v000010C8d00008005sv00001014sd000000DD* ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (ThinkPad 390/i1720/i1721) pci:v000010C8d00008005sv00001025sd00001003* ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on TravelMate 720) pci:v000010C8d00008005sv00001028sd00000088* ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (Latitude CPi A) pci:v000010C8d00008005sv00001028sd0000008F* ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on Colorado Inspiron) pci:v000010C8d00008005sv0000103Csd00000007* ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on Voyager II) pci:v000010C8d00008005sv0000103Csd00000008* ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on Voyager III) pci:v000010C8d00008005sv0000103Csd0000000D* ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on Omnibook 900) pci:v000010C8d00008005sv000010C8sd00008005* ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on FireAnt) pci:v000010C8d00008005sv0000110Asd00008005* ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device) pci:v000010C8d00008005sv000014C0sd00000004* ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device) pci:v000010C8d00008006* ID_MODEL_FROM_DATABASE=NM2360 [MagicMedia 256ZX Audio] pci:v000010C8d00008016* ID_MODEL_FROM_DATABASE=NM2380 [MagicMedia 256XL+ Audio] pci:v000010C9* ID_VENDOR_FROM_DATABASE=Dataexpert Corporation pci:v000010CA* ID_VENDOR_FROM_DATABASE=Fujitsu Microelectr., Inc. pci:v000010CB* ID_VENDOR_FROM_DATABASE=Omron Corporation pci:v000010CC* ID_VENDOR_FROM_DATABASE=Mai Logic Incorporated pci:v000010CCd00000660* ID_MODEL_FROM_DATABASE=Articia S Host Bridge pci:v000010CCd00000661* ID_MODEL_FROM_DATABASE=Articia S PCI Bridge pci:v000010CD* ID_VENDOR_FROM_DATABASE=Advanced System Products, Inc pci:v000010CDd00001100* ID_MODEL_FROM_DATABASE=ASC1100 pci:v000010CDd00001200* ID_MODEL_FROM_DATABASE=ASC1200 [(abp940) Fast SCSI-II] pci:v000010CDd00001300* ID_MODEL_FROM_DATABASE=ASC1300 / ASC3030 [ABP940-U / ABP960-U / ABP3925] pci:v000010CDd00001300sv000010CDsd00001310* ID_MODEL_FROM_DATABASE=ASC1300 / ASC3030 [ABP940-U / ABP960-U / ABP3925] (ASC1300/3030 SCSI adapter) pci:v000010CDd00001300sv00001195sd00001320* ID_MODEL_FROM_DATABASE=ASC1300 / ASC3030 [ABP940-U / ABP960-U / ABP3925] (Ultra-SCSI CardBus PC Card REX CB31) pci:v000010CDd00002300* ID_MODEL_FROM_DATABASE=ABP940-UW pci:v000010CDd00002500* ID_MODEL_FROM_DATABASE=ABP940-U2W pci:v000010CDd00002700* ID_MODEL_FROM_DATABASE=ABP3950-U3W pci:v000010CE* ID_VENDOR_FROM_DATABASE=Radius pci:v000010CF* ID_VENDOR_FROM_DATABASE=Fujitsu Limited. pci:v000010CFd000001EF* ID_MODEL_FROM_DATABASE=PCEA4 PCI-Express Dual Port ESCON Adapter pci:v000010CFd00001414* ID_MODEL_FROM_DATABASE=On-board USB 1.1 companion controller pci:v000010CFd00001415* ID_MODEL_FROM_DATABASE=On-board USB 2.0 EHCI controller pci:v000010CFd00001422* ID_MODEL_FROM_DATABASE=E8410 nVidia graphics adapter pci:v000010CFd0000142D* ID_MODEL_FROM_DATABASE=HD audio (Realtek ALC262) pci:v000010CFd00001430* ID_MODEL_FROM_DATABASE=82566MM Intel 1Gb copper LAN interface pci:v000010CFd00001623* ID_MODEL_FROM_DATABASE=PCEA4 PCI-Express Dual Port ESCON Adapter pci:v000010CFd00002001* ID_MODEL_FROM_DATABASE=mb86605 pci:v000010CFd0000200C* ID_MODEL_FROM_DATABASE=MB86613L IEEE1394 OHCI 1.0 Controller pci:v000010CFd00002010* ID_MODEL_FROM_DATABASE=MB86613S IEEE1394 OHCI 1.1 Controller pci:v000010CFd00002019* ID_MODEL_FROM_DATABASE=MB86295S [CORAL P] pci:v000010CFd0000201E* ID_MODEL_FROM_DATABASE=MB86296S [CORAL PA] pci:v000010CFd0000202B* ID_MODEL_FROM_DATABASE=MB86297A [Carmine Graphics Controller] pci:v000010D1* ID_VENDOR_FROM_DATABASE=FuturePlus Systems Corp. pci:v000010D2* ID_VENDOR_FROM_DATABASE=Molex Incorporated pci:v000010D3* ID_VENDOR_FROM_DATABASE=Jabil Circuit Inc pci:v000010D4* ID_VENDOR_FROM_DATABASE=Hualon Microelectronics pci:v000010D5* ID_VENDOR_FROM_DATABASE=Autologic Inc. pci:v000010D6* ID_VENDOR_FROM_DATABASE=Cetia pci:v000010D7* ID_VENDOR_FROM_DATABASE=BCM Advanced Research pci:v000010D8* ID_VENDOR_FROM_DATABASE=Advanced Peripherals Labs pci:v000010D9* ID_VENDOR_FROM_DATABASE=Macronix, Inc. [MXIC] pci:v000010D9d00000431* ID_MODEL_FROM_DATABASE=MX98715 pci:v000010D9d00000512* ID_MODEL_FROM_DATABASE=MX98713 pci:v000010D9d00000531* ID_MODEL_FROM_DATABASE=MX987x5 pci:v000010D9d00000531sv00001186sd00001200* ID_MODEL_FROM_DATABASE=MX987x5 (DFE-540TX ProFAST 10/100 Adapter) pci:v000010D9d00008625* ID_MODEL_FROM_DATABASE=MX86250 pci:v000010D9d00008626* ID_MODEL_FROM_DATABASE=Macronix MX86251 + 3Dfx Voodoo Rush pci:v000010D9d00008888* ID_MODEL_FROM_DATABASE=MX86200 pci:v000010DA* ID_VENDOR_FROM_DATABASE=Compaq IPG-Austin pci:v000010DAd00000508* ID_MODEL_FROM_DATABASE=TC4048 Token Ring 4/16 pci:v000010DAd00003390* ID_MODEL_FROM_DATABASE=Tl3c3x9 pci:v000010DB* ID_VENDOR_FROM_DATABASE=Rohm LSI Systems, Inc. pci:v000010DC* ID_VENDOR_FROM_DATABASE=CERN/ECP/EDU pci:v000010DCd00000001* ID_MODEL_FROM_DATABASE=STAR/RD24 SCI-PCI (PMC) pci:v000010DCd00000002* ID_MODEL_FROM_DATABASE=TAR/RD24 SCI-PCI (PMC) pci:v000010DCd00000021* ID_MODEL_FROM_DATABASE=HIPPI destination pci:v000010DCd00000022* ID_MODEL_FROM_DATABASE=HIPPI source pci:v000010DCd000010DC* ID_MODEL_FROM_DATABASE=ATT2C15-3 FPGA pci:v000010DD* ID_VENDOR_FROM_DATABASE=Evans & Sutherland pci:v000010DDd00000100* ID_MODEL_FROM_DATABASE=Lightning 1200 pci:v000010DDd00000100sv000010DDsd00000023* ID_MODEL_FROM_DATABASE=Lightning 1200 (15+16M) pci:v000010DE* ID_VENDOR_FROM_DATABASE=NVIDIA Corporation pci:v000010DEd00000008* ID_MODEL_FROM_DATABASE=NV1 [EDGE 3D] pci:v000010DEd00000009* ID_MODEL_FROM_DATABASE=NV1 [EDGE 3D] pci:v000010DEd00000020* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] pci:v000010DEd00000020sv00001043sd00000200* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (V3400 TNT) pci:v000010DEd00000020sv00001048sd00000C18* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Erazor II SGRAM) pci:v000010DEd00000020sv00001048sd00000C19* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Erazor II) pci:v000010DEd00000020sv00001048sd00000C1B* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Erazor II) pci:v000010DEd00000020sv00001048sd00000C1C* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Erazor II) pci:v000010DEd00000020sv00001092sd00000550* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) pci:v000010DEd00000020sv00001092sd00000552* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) pci:v000010DEd00000020sv00001092sd00004804* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) pci:v000010DEd00000020sv00001092sd00004808* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) pci:v000010DEd00000020sv00001092sd00004810* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) pci:v000010DEd00000020sv00001092sd00004812* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) pci:v000010DEd00000020sv00001092sd00004815* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) pci:v000010DEd00000020sv00001092sd00004820* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550 with TV out) pci:v000010DEd00000020sv00001092sd00004822* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) pci:v000010DEd00000020sv00001092sd00004904* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) pci:v000010DEd00000020sv00001092sd00004914* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) pci:v000010DEd00000020sv00001092sd00008225* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) pci:v000010DEd00000020sv000010B4sd0000273D* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Velocity 4400) pci:v000010DEd00000020sv000010B4sd0000273E* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Velocity 4400) pci:v000010DEd00000020sv000010B4sd00002740* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Velocity 4400) pci:v000010DEd00000020sv000010DEsd00000020* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Riva TNT) pci:v000010DEd00000020sv00001102sd00001015* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Graphics Blaster CT6710) pci:v000010DEd00000020sv00001102sd00001016* ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Graphics Blaster RIVA TNT) pci:v000010DEd00000028* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] pci:v000010DEd00000028sv00001043sd00000200* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (AGP-V3800 SGRAM) pci:v000010DEd00000028sv00001043sd00000201* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (AGP-V3800 SDRAM) pci:v000010DEd00000028sv00001043sd00000205* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (PCI-V3800) pci:v000010DEd00000028sv00001043sd00004000* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (AGP-V3800PRO) pci:v000010DEd00000028sv00001048sd00000C21* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Synergy II) pci:v000010DEd00000028sv00001048sd00000C28* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III) pci:v000010DEd00000028sv00001048sd00000C29* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III) pci:v000010DEd00000028sv00001048sd00000C2A* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III) pci:v000010DEd00000028sv00001048sd00000C2B* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III) pci:v000010DEd00000028sv00001048sd00000C31* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III Pro) pci:v000010DEd00000028sv00001048sd00000C32* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III Pro) pci:v000010DEd00000028sv00001048sd00000C33* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III Pro) pci:v000010DEd00000028sv00001048sd00000C34* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III Pro) pci:v000010DEd00000028sv0000107Dsd00002134* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (WinFast 3D S320 II + TV-Out) pci:v000010DEd00000028sv00001092sd00004804* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Viper V770) pci:v000010DEd00000028sv00001092sd00004A00* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Viper V770) pci:v000010DEd00000028sv00001092sd00004A02* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Viper V770 Ultra) pci:v000010DEd00000028sv00001092sd00005A00* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (RIVA TNT2/TNT2 Pro) pci:v000010DEd00000028sv00001092sd00005A40* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Viper V770D AGP) pci:v000010DEd00000028sv00001092sd00006A02* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Viper V770 Ultra) pci:v000010DEd00000028sv00001092sd00007A02* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Viper V770 Ultra) pci:v000010DEd00000028sv000010DEsd00000005* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (RIVA TNT2 Pro) pci:v000010DEd00000028sv000010DEsd0000000F* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Compaq NVIDIA TNT2 Pro) pci:v000010DEd00000028sv00001102sd00001020* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (3D Blaster RIVA TNT2) pci:v000010DEd00000028sv00001102sd00001026* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (3D Blaster RIVA TNT2 Digital) pci:v000010DEd00000028sv00001462sd00008806* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (MS-8806 AGPhantom Graphics Card) pci:v000010DEd00000028sv000014AFsd00005810* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Maxi Gamer Xentor) pci:v000010DEd00000029* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] pci:v000010DEd00000029sv00001043sd00000200* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (AGP-V3800 Deluxe) pci:v000010DEd00000029sv00001043sd00000201* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (AGP-V3800 Ultra SDRAM) pci:v000010DEd00000029sv00001043sd00000205* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (PCI-V3800 Ultra) pci:v000010DEd00000029sv00001048sd00000C2E* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (Erazor III Ultra) pci:v000010DEd00000029sv00001048sd00000C2F* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (Erazor III Ultra) pci:v000010DEd00000029sv00001048sd00000C30* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (Erazor III Ultra) pci:v000010DEd00000029sv00001102sd00001021* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (3D Blaster RIVA TNT2 Ultra) pci:v000010DEd00000029sv00001102sd00001029* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (3D Blaster RIVA TNT2 Ultra) pci:v000010DEd00000029sv00001102sd0000102F* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (3D Blaster RIVA TNT2 Ultra) pci:v000010DEd00000029sv000014AFsd00005820* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (Maxi Gamer Xentor 32) pci:v000010DEd00000029sv00004843sd00004F34* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (Dynamite) pci:v000010DEd0000002A* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2] pci:v000010DEd0000002B* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2] pci:v000010DEd0000002C* ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] pci:v000010DEd0000002Csv00001043sd00000200* ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (AGP-V3800 Combat SDRAM) pci:v000010DEd0000002Csv00001043sd00000201* ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (AGP-V3800 Combat) pci:v000010DEd0000002Csv00001048sd00000C20* ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (TNT2 Vanta) pci:v000010DEd0000002Csv00001048sd00000C21* ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (TNT2 Vanta) pci:v000010DEd0000002Csv00001048sd00000C25* ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (TNT2 Vanta 16MB) pci:v000010DEd0000002Csv00001092sd00006820* ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (Viper V730) pci:v000010DEd0000002Csv00001102sd00001031* ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (CT6938 VANTA 8MB) pci:v000010DEd0000002Csv00001102sd00001034* ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (CT6894 VANTA 16MB) pci:v000010DEd0000002Csv000014AFsd00005008* ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (Maxi Gamer Phoenix 2) pci:v000010DEd0000002D* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] pci:v000010DEd0000002Dsv00001043sd00000200* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (AGP-V3800M) pci:v000010DEd0000002Dsv00001043sd00000201* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (AGP-V3800M) pci:v000010DEd0000002Dsv00001048sd00000C3A* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (Erazor III LT) pci:v000010DEd0000002Dsv00001048sd00000C3B* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (Erazor III LT) pci:v000010DEd0000002Dsv0000107Dsd00002137* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (WinFast 3D S325) pci:v000010DEd0000002Dsv000010DEsd00000006* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (RIVA TNT2 Model 64/Model 64 Pro) pci:v000010DEd0000002Dsv000010DEsd0000001E* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (M64 AGP4x) pci:v000010DEd0000002Dsv00001102sd00001023* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (CT6892 RIVA TNT2 Value) pci:v000010DEd0000002Dsv00001102sd00001024* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (CT6932 RIVA TNT2 Value 32Mb) pci:v000010DEd0000002Dsv00001102sd0000102C* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (CT6931 RIVA TNT2 Value [Jumper]) pci:v000010DEd0000002Dsv00001102sd00001030* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (CT6931 RIVA TNT2 Value) pci:v000010DEd0000002Dsv0000110Asd0000006F* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (GM1000-16) pci:v000010DEd0000002Dsv0000110Asd00000081* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (GM1000-16) pci:v000010DEd0000002Dsv00001462sd00008808* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (MSI-8808) pci:v000010DEd0000002Dsv000014AFsd00005620* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (Gamer Cougar Video Edition) pci:v000010DEd0000002Dsv00001554sd00001041* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (Pixelview RIVA TNT2 M64) pci:v000010DEd0000002Dsv00001569sd0000002D* ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (Palit Microsystems Daytona TNT2 M64) pci:v000010DEd00000034* ID_MODEL_FROM_DATABASE=MCP04 SMBus pci:v000010DEd00000035* ID_MODEL_FROM_DATABASE=MCP04 IDE pci:v000010DEd00000036* ID_MODEL_FROM_DATABASE=MCP04 Serial ATA Controller pci:v000010DEd00000037* ID_MODEL_FROM_DATABASE=MCP04 Ethernet Controller pci:v000010DEd00000038* ID_MODEL_FROM_DATABASE=MCP04 Ethernet Controller pci:v000010DEd0000003A* ID_MODEL_FROM_DATABASE=MCP04 AC'97 Audio Controller pci:v000010DEd0000003B* ID_MODEL_FROM_DATABASE=MCP04 USB Controller pci:v000010DEd0000003C* ID_MODEL_FROM_DATABASE=MCP04 USB Controller pci:v000010DEd0000003D* ID_MODEL_FROM_DATABASE=MCP04 PCI Bridge pci:v000010DEd0000003E* ID_MODEL_FROM_DATABASE=MCP04 Serial ATA Controller pci:v000010DEd00000040* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 Ultra] pci:v000010DEd00000041* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800] pci:v000010DEd00000041sv00001043sd0000817B* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800] (V9999 Gamer Edition) pci:v000010DEd00000041sv0000107Dsd00002992* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800] (WinFast A400) pci:v000010DEd00000041sv00001458sd0000310F* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800] (Geforce 6800 GV-N6812) pci:v000010DEd00000042* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 LE] pci:v000010DEd00000042sv0000107Dsd0000299B* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 LE] (WinFast A400 LE) pci:v000010DEd00000043* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 XE] pci:v000010DEd00000044* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 XT] pci:v000010DEd00000045* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT] pci:v000010DEd00000045sv00001043sd0000817D* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT] (V9999GT) pci:v000010DEd00000045sv00001458sd00003140* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT] (GV-N68T256D) pci:v000010DEd00000047* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GS] pci:v000010DEd00000047sv00001682sd00002109* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GS] (GeForce 6800 GS) pci:v000010DEd00000048* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 XT] pci:v000010DEd0000004E* ID_MODEL_FROM_DATABASE=NV40GL [Quadro FX 4000] pci:v000010DEd00000050* ID_MODEL_FROM_DATABASE=CK804 ISA Bridge pci:v000010DEd00000050sv00001043sd0000815A* ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (K8N4/A8N Series Mainboard) pci:v000010DEd00000050sv000010F1sd00002865* ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (Tomcat K8E (S2865)) pci:v000010DEd00000050sv00001458sd00000C11* ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (GA-K8N Ultra-9 Mainboard) pci:v000010DEd00000050sv00001462sd00007100* ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (MSI K8N Diamond) pci:v000010DEd00000050sv00001462sd00007125* ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (K8N Neo4-F mainboard) pci:v000010DEd00000050sv0000147Bsd00001C1A* ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (KN8-Ultra Mainboard) pci:v000010DEd00000050sv00001565sd00003402* ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (NF4 AM2L Mainboard) pci:v000010DEd00000051* ID_MODEL_FROM_DATABASE=CK804 ISA Bridge pci:v000010DEd00000051sv00001028sd00000225* ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (PowerEdge T105 ISA Bridge) pci:v000010DEd00000052* ID_MODEL_FROM_DATABASE=CK804 SMBus pci:v000010DEd00000052sv00001028sd00000225* ID_MODEL_FROM_DATABASE=CK804 SMBus (PowerEdge T105 SMBus) pci:v000010DEd00000052sv00001043sd0000815A* ID_MODEL_FROM_DATABASE=CK804 SMBus (K8N4/A8N Series Mainboard) pci:v000010DEd00000052sv000010F1sd00002865* ID_MODEL_FROM_DATABASE=CK804 SMBus (Tomcat K8E (S2865)) pci:v000010DEd00000052sv00001458sd00000C11* ID_MODEL_FROM_DATABASE=CK804 SMBus (GA-K8N Ultra-9 Mainboard) pci:v000010DEd00000052sv00001462sd00007100* ID_MODEL_FROM_DATABASE=CK804 SMBus (MSI K8N Diamond) pci:v000010DEd00000052sv00001462sd00007125* ID_MODEL_FROM_DATABASE=CK804 SMBus (K8N Neo4-F mainboard) pci:v000010DEd00000052sv0000147Bsd00001C1A* ID_MODEL_FROM_DATABASE=CK804 SMBus (KN8-Ultra Mainboard) pci:v000010DEd00000052sv00001565sd00003402* ID_MODEL_FROM_DATABASE=CK804 SMBus (NF4 AM2L Mainboard) pci:v000010DEd00000053* ID_MODEL_FROM_DATABASE=CK804 IDE pci:v000010DEd00000053sv00001043sd0000815A* ID_MODEL_FROM_DATABASE=CK804 IDE (K8N4/A8N Series Mainboard) pci:v000010DEd00000053sv000010F1sd00002865* ID_MODEL_FROM_DATABASE=CK804 IDE (Tomcat K8E (S2865)) pci:v000010DEd00000053sv00001458sd00005002* ID_MODEL_FROM_DATABASE=CK804 IDE (GA-K8N Ultra-9 Mainboard) pci:v000010DEd00000053sv00001462sd00007100* ID_MODEL_FROM_DATABASE=CK804 IDE (MSI K8N Diamond) pci:v000010DEd00000053sv00001462sd00007125* ID_MODEL_FROM_DATABASE=CK804 IDE (K8N Neo4-F mainboard) pci:v000010DEd00000053sv0000147Bsd00001C1A* ID_MODEL_FROM_DATABASE=CK804 IDE (KN8-Ultra Mainboard) pci:v000010DEd00000053sv00001565sd00003402* ID_MODEL_FROM_DATABASE=CK804 IDE (NF4 AM2L Mainboard) pci:v000010DEd00000054* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller pci:v000010DEd00000054sv00001028sd00000225* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (PowerEdge T105 Serial ATA) pci:v000010DEd00000054sv00001043sd0000815A* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (A8N Series Mainboard) pci:v000010DEd00000054sv000010F1sd00002865* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (Tomcat K8E (S2865)) pci:v000010DEd00000054sv00001458sd0000B003* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (GA-K8N Ultra-9 Mainboard) pci:v000010DEd00000054sv00001462sd00007100* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (MSI K8N Diamond) pci:v000010DEd00000054sv00001462sd00007125* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (K8N Neo4-F mainboard) pci:v000010DEd00000054sv0000147Bsd00001C1A* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (KN8-Ultra Mainboard) pci:v000010DEd00000054sv00001565sd00005401* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (NF4 AM2L Mainboard) pci:v000010DEd00000055* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller pci:v000010DEd00000055sv00001028sd00000225* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (PowerEdge T105 Serial ATA) pci:v000010DEd00000055sv00001043sd0000815A* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (K8N4/A8N Series Mainboard) pci:v000010DEd00000055sv000010F1sd00002865* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (Tomcat K8E (S2865)) pci:v000010DEd00000055sv00001458sd0000B003* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (GA-K8N Ultra-9 Mainboard) pci:v000010DEd00000055sv00001462sd00007125* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (K8N Neo4-F mainboard) pci:v000010DEd00000055sv0000147Bsd00001C1A* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (KN8-Ultra Mainboard) pci:v000010DEd00000055sv00001565sd00005401* ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (NF4 AM2L Mainboard) pci:v000010DEd00000056* ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller pci:v000010DEd00000057* ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller pci:v000010DEd00000057sv00001043sd00008141* ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (K8N4/A8N Series Mainboard) pci:v000010DEd00000057sv000010DEsd0000CB84* ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (NF4 Lanparty) pci:v000010DEd00000057sv000010F1sd00002865* ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (Tomcat K8E (S2865)) pci:v000010DEd00000057sv00001458sd0000E000* ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (GA-K8N Ultra-9 Mainboard) pci:v000010DEd00000057sv00001462sd00007100* ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (MSI K8N Diamond) pci:v000010DEd00000057sv00001462sd00007125* ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (K8N Neo4-F mainboard) pci:v000010DEd00000057sv0000147Bsd00001C1A* ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (KN8-Ultra Mainboard) pci:v000010DEd00000057sv00001565sd00002501* ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (NF4 AM2L Mainboard) pci:v000010DEd00000058* ID_MODEL_FROM_DATABASE=CK804 AC'97 Modem pci:v000010DEd00000059* ID_MODEL_FROM_DATABASE=CK804 AC'97 Audio Controller pci:v000010DEd00000059sv00001043sd0000812A* ID_MODEL_FROM_DATABASE=CK804 AC'97 Audio Controller (K8N4/A8N Series Mainboard) pci:v000010DEd00000059sv000010F1sd00002865* ID_MODEL_FROM_DATABASE=CK804 AC'97 Audio Controller (Tomcat K8E (S2865)) pci:v000010DEd00000059sv00001462sd00007585* ID_MODEL_FROM_DATABASE=CK804 AC'97 Audio Controller (K8N Neo4-F mainboard) pci:v000010DEd00000059sv0000147Bsd00001C1A* ID_MODEL_FROM_DATABASE=CK804 AC'97 Audio Controller (KN8-Ultra Mainboard) pci:v000010DEd00000059sv00001565sd00008211* ID_MODEL_FROM_DATABASE=CK804 AC'97 Audio Controller (NF4 AM2L Mainboard) pci:v000010DEd0000005A* ID_MODEL_FROM_DATABASE=CK804 USB Controller pci:v000010DEd0000005Asv00001028sd00000225* ID_MODEL_FROM_DATABASE=CK804 USB Controller (PowerEdge T105 onboard USB) pci:v000010DEd0000005Asv00001043sd0000815A* ID_MODEL_FROM_DATABASE=CK804 USB Controller (K8N4/A8N Series Mainboard) pci:v000010DEd0000005Asv000010F1sd00002865* ID_MODEL_FROM_DATABASE=CK804 USB Controller (Tomcat K8E (S2865)) pci:v000010DEd0000005Asv00001458sd00005004* ID_MODEL_FROM_DATABASE=CK804 USB Controller (GA-K8N Ultra-9 Mainboard) pci:v000010DEd0000005Asv00001462sd00007100* ID_MODEL_FROM_DATABASE=CK804 USB Controller (MSI K8N Diamond) pci:v000010DEd0000005Asv00001462sd00007125* ID_MODEL_FROM_DATABASE=CK804 USB Controller (K8N Neo4-F mainboard) pci:v000010DEd0000005Asv0000147Bsd00001C1A* ID_MODEL_FROM_DATABASE=CK804 USB Controller (KN8-Ultra Mainboard) pci:v000010DEd0000005Asv00001565sd00003402* ID_MODEL_FROM_DATABASE=CK804 USB Controller (NF4 AM2L Mainboard) pci:v000010DEd0000005B* ID_MODEL_FROM_DATABASE=CK804 USB Controller pci:v000010DEd0000005Bsv00001028sd00000225* ID_MODEL_FROM_DATABASE=CK804 USB Controller (PowerEdge T105 onboard USB) pci:v000010DEd0000005Bsv00001043sd0000815A* ID_MODEL_FROM_DATABASE=CK804 USB Controller (K8N4/A8N Series Mainboard) pci:v000010DEd0000005Bsv000010F1sd00002865* ID_MODEL_FROM_DATABASE=CK804 USB Controller (Tomcat K8E (S2865)) pci:v000010DEd0000005Bsv00001458sd00005004* ID_MODEL_FROM_DATABASE=CK804 USB Controller (GA-K8N Ultra-9 Mainboard) pci:v000010DEd0000005Bsv00001462sd00007100* ID_MODEL_FROM_DATABASE=CK804 USB Controller (MSI K8N Diamond) pci:v000010DEd0000005Bsv00001462sd00007125* ID_MODEL_FROM_DATABASE=CK804 USB Controller (K8N Neo4-F mainboard) pci:v000010DEd0000005Bsv0000147Bsd00001C1A* ID_MODEL_FROM_DATABASE=CK804 USB Controller (KN8-Ultra Mainboard) pci:v000010DEd0000005Bsv00001565sd00003402* ID_MODEL_FROM_DATABASE=CK804 USB Controller (NF4 AM2L Mainboard) pci:v000010DEd0000005C* ID_MODEL_FROM_DATABASE=CK804 PCI Bridge pci:v000010DEd0000005D* ID_MODEL_FROM_DATABASE=CK804 PCIE Bridge pci:v000010DEd0000005E* ID_MODEL_FROM_DATABASE=CK804 Memory Controller pci:v000010DEd0000005Esv00001028sd00000225* ID_MODEL_FROM_DATABASE=CK804 Memory Controller (PowerEdge T105 Memory Controller) pci:v000010DEd0000005Esv00001043sd0000815A* ID_MODEL_FROM_DATABASE=CK804 Memory Controller (A8N Series Mainboard) pci:v000010DEd0000005Esv000010DEsd0000005E* ID_MODEL_FROM_DATABASE=CK804 Memory Controller (ECS Elitegroup NFORCE3-A939 motherboard.) pci:v000010DEd0000005Esv000010F1sd00002865* ID_MODEL_FROM_DATABASE=CK804 Memory Controller (Tomcat K8E (S2865)) pci:v000010DEd0000005Esv000010F1sd00002891* ID_MODEL_FROM_DATABASE=CK804 Memory Controller (Thunder K8SRE Mainboard) pci:v000010DEd0000005Esv00001458sd00005000* ID_MODEL_FROM_DATABASE=CK804 Memory Controller (GA-K8N Ultra-9 Mainboard) pci:v000010DEd0000005Esv00001462sd00007100* ID_MODEL_FROM_DATABASE=CK804 Memory Controller (K8N Diamond Mainboard) pci:v000010DEd0000005Esv00001462sd00007125* ID_MODEL_FROM_DATABASE=CK804 Memory Controller (K8N Neo4-F Mainboard) pci:v000010DEd0000005Esv0000147Bsd00001C1A* ID_MODEL_FROM_DATABASE=CK804 Memory Controller (KN8-Ultra Mainboard) pci:v000010DEd0000005Esv00001565sd00003402* ID_MODEL_FROM_DATABASE=CK804 Memory Controller (NF4 AM2L Mainboard) pci:v000010DEd0000005F* ID_MODEL_FROM_DATABASE=CK804 Memory Controller pci:v000010DEd00000060* ID_MODEL_FROM_DATABASE=nForce2 ISA Bridge pci:v000010DEd00000060sv00001043sd000080AD* ID_MODEL_FROM_DATABASE=nForce2 ISA Bridge (A7N8X Mainboard) pci:v000010DEd00000060sv0000147Bsd00001C02* ID_MODEL_FROM_DATABASE=nForce2 ISA Bridge (NF7-S/NF7 (nVidia-nForce2) 2.X) pci:v000010DEd00000060sv0000A0A0sd000003BA* ID_MODEL_FROM_DATABASE=nForce2 ISA Bridge (UK79G-1394 motherboard) pci:v000010DEd00000064* ID_MODEL_FROM_DATABASE=nForce2 SMBus (MCP) pci:v000010DEd00000064sv0000147Bsd00001C02* ID_MODEL_FROM_DATABASE=nForce2 SMBus (MCP) (NF7-S/NF7 (nVidia-nForce2) 2.X) pci:v000010DEd00000064sv0000A0A0sd000003BB* ID_MODEL_FROM_DATABASE=nForce2 SMBus (MCP) (UK79G-1394 motherboard) pci:v000010DEd00000065* ID_MODEL_FROM_DATABASE=nForce2 IDE pci:v000010DEd00000065sv000010DEsd00000C11* ID_MODEL_FROM_DATABASE=nForce2 IDE (nForce 2 EIDE Controller) pci:v000010DEd00000065sv0000A0A0sd000003B2* ID_MODEL_FROM_DATABASE=nForce2 IDE (UK79G-1394 motherboard) pci:v000010DEd00000066* ID_MODEL_FROM_DATABASE=nForce2 Ethernet Controller pci:v000010DEd00000066sv00001043sd000080A7* ID_MODEL_FROM_DATABASE=nForce2 Ethernet Controller (A7N8X Mainboard onboard nForce2 Ethernet) pci:v000010DEd00000066sv000010DEsd00000C11* ID_MODEL_FROM_DATABASE=nForce2 Ethernet Controller (nForce MCP-T Networking Adapter) pci:v000010DEd00000066sv0000A0A0sd000003B3* ID_MODEL_FROM_DATABASE=nForce2 Ethernet Controller (UK79G-1394 motherboard) pci:v000010DEd00000067* ID_MODEL_FROM_DATABASE=nForce2 USB Controller pci:v000010DEd00000067sv00001043sd00000C11* ID_MODEL_FROM_DATABASE=nForce2 USB Controller (A7N8X Mainboard) pci:v000010DEd00000067sv0000A0A0sd000003B4* ID_MODEL_FROM_DATABASE=nForce2 USB Controller (UK79G-1394 motherboard) pci:v000010DEd00000068* ID_MODEL_FROM_DATABASE=nForce2 USB Controller pci:v000010DEd00000068sv00001043sd00000C11* ID_MODEL_FROM_DATABASE=nForce2 USB Controller (A7N8X Mainboard) pci:v000010DEd00000068sv0000A0A0sd000003B4* ID_MODEL_FROM_DATABASE=nForce2 USB Controller (UK79G-1394 motherboard) pci:v000010DEd0000006A* ID_MODEL_FROM_DATABASE=nForce2 AC97 Audio Controler (MCP) pci:v000010DEd0000006Asv00001043sd00008095* ID_MODEL_FROM_DATABASE=nForce2 AC97 Audio Controler (MCP) pci:v000010DEd0000006Asv0000A0A0sd00000304* ID_MODEL_FROM_DATABASE=nForce2 AC97 Audio Controler (MCP) (UK79G-1394 motherboard) pci:v000010DEd0000006B* ID_MODEL_FROM_DATABASE=nForce Audio Processing Unit pci:v000010DEd0000006Bsv000010DEsd0000006B* ID_MODEL_FROM_DATABASE=nForce Audio Processing Unit (nForce2 MCP Audio Processing Unit) pci:v000010DEd0000006Bsv0000A0A0sd00000304* ID_MODEL_FROM_DATABASE=nForce Audio Processing Unit (UK79G-1394 motherboard) pci:v000010DEd0000006C* ID_MODEL_FROM_DATABASE=nForce2 External PCI Bridge pci:v000010DEd0000006D* ID_MODEL_FROM_DATABASE=nForce2 PCI Bridge pci:v000010DEd0000006E* ID_MODEL_FROM_DATABASE=nForce2 FireWire (IEEE 1394) Controller pci:v000010DEd0000006Esv0000A0A0sd00000306* ID_MODEL_FROM_DATABASE=nForce2 FireWire (IEEE 1394) Controller (UK79G-1394 motherboard) pci:v000010DEd00000080* ID_MODEL_FROM_DATABASE=MCP2A ISA bridge pci:v000010DEd00000080sv0000147Bsd00001C09* ID_MODEL_FROM_DATABASE=MCP2A ISA bridge (NV7 Motherboard) pci:v000010DEd00000084* ID_MODEL_FROM_DATABASE=MCP2A SMBus pci:v000010DEd00000084sv0000147Bsd00001C09* ID_MODEL_FROM_DATABASE=MCP2A SMBus (NV7 Motherboard) pci:v000010DEd00000085* ID_MODEL_FROM_DATABASE=MCP2A IDE pci:v000010DEd00000085sv0000147Bsd00001C09* ID_MODEL_FROM_DATABASE=MCP2A IDE (NV7 Motherboard) pci:v000010DEd00000086* ID_MODEL_FROM_DATABASE=MCP2A Ethernet Controller pci:v000010DEd00000087* ID_MODEL_FROM_DATABASE=MCP2A USB Controller pci:v000010DEd00000087sv0000147Bsd00001C09* ID_MODEL_FROM_DATABASE=MCP2A USB Controller (NV7 Motherboard) pci:v000010DEd00000088* ID_MODEL_FROM_DATABASE=MCP2A USB Controller pci:v000010DEd00000088sv0000147Bsd00001C09* ID_MODEL_FROM_DATABASE=MCP2A USB Controller (NV7 Motherboard) pci:v000010DEd0000008A* ID_MODEL_FROM_DATABASE=MCP2S AC'97 Audio Controller pci:v000010DEd0000008Asv0000147Bsd00001C09* ID_MODEL_FROM_DATABASE=MCP2S AC'97 Audio Controller (NV7 Motherboard) pci:v000010DEd0000008B* ID_MODEL_FROM_DATABASE=MCP2A PCI Bridge pci:v000010DEd0000008C* ID_MODEL_FROM_DATABASE=MCP2A Ethernet Controller pci:v000010DEd0000008E* ID_MODEL_FROM_DATABASE=nForce2 Serial ATA Controller pci:v000010DEd00000090* ID_MODEL_FROM_DATABASE=G70 [GeForce 7800 GTX] pci:v000010DEd00000091* ID_MODEL_FROM_DATABASE=G70 [GeForce 7800 GTX] pci:v000010DEd00000092* ID_MODEL_FROM_DATABASE=G70 [GeForce 7800 GT] pci:v000010DEd00000093* ID_MODEL_FROM_DATABASE=G70 [GeForce 7800 GS] pci:v000010DEd00000095* ID_MODEL_FROM_DATABASE=G70 [GeForce 7800 SLI] pci:v000010DEd00000097* ID_MODEL_FROM_DATABASE=G70 [GeForce GTS 250] pci:v000010DEd00000098* ID_MODEL_FROM_DATABASE=G70M [GeForce Go 7800] pci:v000010DEd00000099* ID_MODEL_FROM_DATABASE=G70M [GeForce Go 7800 GTX] pci:v000010DEd0000009D* ID_MODEL_FROM_DATABASE=G70GL [Quadro FX 4500] pci:v000010DEd000000A0* ID_MODEL_FROM_DATABASE=NV5 [Aladdin TNT2] pci:v000010DEd000000A0sv000014AFsd00005810* ID_MODEL_FROM_DATABASE=NV5 [Aladdin TNT2] (Maxi Gamer Xentor) pci:v000010DEd000000C0* ID_MODEL_FROM_DATABASE=NV41 [GeForce 6800 GS] pci:v000010DEd000000C1* ID_MODEL_FROM_DATABASE=NV41 [GeForce 6800] pci:v000010DEd000000C2* ID_MODEL_FROM_DATABASE=NV41 [GeForce 6800 LE] pci:v000010DEd000000C3* ID_MODEL_FROM_DATABASE=NV41 [GeForce 6800 XT] pci:v000010DEd000000C5* ID_MODEL_FROM_DATABASE=NV41 pci:v000010DEd000000C6* ID_MODEL_FROM_DATABASE=NV41 pci:v000010DEd000000C7* ID_MODEL_FROM_DATABASE=NV41 pci:v000010DEd000000C8* ID_MODEL_FROM_DATABASE=NV41M [GeForce Go 6800] pci:v000010DEd000000C9* ID_MODEL_FROM_DATABASE=NV41M [GeForce Go 6800 Ultra] pci:v000010DEd000000CC* ID_MODEL_FROM_DATABASE=NV41GLM [Quadro FX Go1400] pci:v000010DEd000000CD* ID_MODEL_FROM_DATABASE=NV42GL [Quadro FX 3450/4000 SDI] pci:v000010DEd000000CDsv000010DEsd0000029B* ID_MODEL_FROM_DATABASE=NV42GL [Quadro FX 3450/4000 SDI] (Quadro FX 3450) pci:v000010DEd000000CE* ID_MODEL_FROM_DATABASE=NV41GL [Quadro FX 1400] pci:v000010DEd000000CF* ID_MODEL_FROM_DATABASE=NV41 pci:v000010DEd000000D0* ID_MODEL_FROM_DATABASE=nForce3 LPC Bridge pci:v000010DEd000000D1* ID_MODEL_FROM_DATABASE=nForce3 Host Bridge pci:v000010DEd000000D2* ID_MODEL_FROM_DATABASE=nForce3 AGP Bridge pci:v000010DEd000000D3* ID_MODEL_FROM_DATABASE=CK804 Memory Controller pci:v000010DEd000000D4* ID_MODEL_FROM_DATABASE=nForce3 SMBus pci:v000010DEd000000D5* ID_MODEL_FROM_DATABASE=nForce3 IDE pci:v000010DEd000000D6* ID_MODEL_FROM_DATABASE=nForce3 Ethernet pci:v000010DEd000000D7* ID_MODEL_FROM_DATABASE=nForce3 USB 1.1 pci:v000010DEd000000D8* ID_MODEL_FROM_DATABASE=nForce3 USB 2.0 pci:v000010DEd000000D9* ID_MODEL_FROM_DATABASE=nForce3 Audio pci:v000010DEd000000DA* ID_MODEL_FROM_DATABASE=nForce3 Audio pci:v000010DEd000000DD* ID_MODEL_FROM_DATABASE=nForce3 PCI Bridge pci:v000010DEd000000DF* ID_MODEL_FROM_DATABASE=CK8S Ethernet Controller pci:v000010DEd000000DFsv00001043sd000080A7* ID_MODEL_FROM_DATABASE=CK8S Ethernet Controller (K8N-E) pci:v000010DEd000000DFsv0000105Bsd00000C43* ID_MODEL_FROM_DATABASE=CK8S Ethernet Controller (Winfast NF3250K8AA) pci:v000010DEd000000DFsv0000147Bsd00001C0B* ID_MODEL_FROM_DATABASE=CK8S Ethernet Controller (NF8 Mainboard) pci:v000010DEd000000E0* ID_MODEL_FROM_DATABASE=nForce3 250Gb LPC Bridge pci:v000010DEd000000E0sv00001043sd0000813F* ID_MODEL_FROM_DATABASE=nForce3 250Gb LPC Bridge (K8N-E) pci:v000010DEd000000E0sv000010DEsd00000C11* ID_MODEL_FROM_DATABASE=nForce3 250Gb LPC Bridge (Winfast NF3250K8AA) pci:v000010DEd000000E0sv00001462sd00007030* ID_MODEL_FROM_DATABASE=nForce3 250Gb LPC Bridge (K8N Neo-FSR v2.0) pci:v000010DEd000000E0sv0000147Bsd00001C0B* ID_MODEL_FROM_DATABASE=nForce3 250Gb LPC Bridge (NF8 Mainboard) pci:v000010DEd000000E0sv00001849sd000000E0* ID_MODEL_FROM_DATABASE=nForce3 250Gb LPC Bridge (Motherboard (one of many)) pci:v000010DEd000000E1* ID_MODEL_FROM_DATABASE=nForce3 250Gb Host Bridge pci:v000010DEd000000E1sv00001043sd0000813F* ID_MODEL_FROM_DATABASE=nForce3 250Gb Host Bridge (K8N-E) pci:v000010DEd000000E1sv00001462sd00007030* ID_MODEL_FROM_DATABASE=nForce3 250Gb Host Bridge (K8N Neo-FSR v2.0) pci:v000010DEd000000E1sv0000147Bsd00001C0B* ID_MODEL_FROM_DATABASE=nForce3 250Gb Host Bridge (NF8 Mainboard) pci:v000010DEd000000E1sv00001849sd000000E1* ID_MODEL_FROM_DATABASE=nForce3 250Gb Host Bridge (Motherboard (one of many)) pci:v000010DEd000000E2* ID_MODEL_FROM_DATABASE=nForce3 250Gb AGP Host to PCI Bridge pci:v000010DEd000000E3* ID_MODEL_FROM_DATABASE=nForce3 Serial ATA Controller pci:v000010DEd000000E3sv00001043sd0000813F* ID_MODEL_FROM_DATABASE=nForce3 Serial ATA Controller (K8N-E) pci:v000010DEd000000E3sv0000105Bsd00000C43* ID_MODEL_FROM_DATABASE=nForce3 Serial ATA Controller (Winfast NF3250K8AA) pci:v000010DEd000000E3sv0000147Bsd00001C0B* ID_MODEL_FROM_DATABASE=nForce3 Serial ATA Controller (NF8 Mainboard) pci:v000010DEd000000E3sv00001849sd000000E3* ID_MODEL_FROM_DATABASE=nForce3 Serial ATA Controller (Motherboard (one of many)) pci:v000010DEd000000E4* ID_MODEL_FROM_DATABASE=nForce 250Gb PCI System Management pci:v000010DEd000000E4sv00001043sd0000813F* ID_MODEL_FROM_DATABASE=nForce 250Gb PCI System Management (K8N-E) pci:v000010DEd000000E4sv0000105Bsd00000C43* ID_MODEL_FROM_DATABASE=nForce 250Gb PCI System Management (Winfast NF3250K8AA) pci:v000010DEd000000E4sv00001462sd00007030* ID_MODEL_FROM_DATABASE=nForce 250Gb PCI System Management (K8N Neo-FSR v2.0) pci:v000010DEd000000E4sv0000147Bsd00001C0B* ID_MODEL_FROM_DATABASE=nForce 250Gb PCI System Management (NF8 Mainboard) pci:v000010DEd000000E4sv00001849sd000000E4* ID_MODEL_FROM_DATABASE=nForce 250Gb PCI System Management (Motherboard (one of many)) pci:v000010DEd000000E5* ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) pci:v000010DEd000000E5sv00001043sd0000813F* ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) (K8N-E) pci:v000010DEd000000E5sv0000105Bsd00000C43* ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) (Winfast NF3250K8AA) pci:v000010DEd000000E5sv00001462sd00007030* ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) (K8N Neo-FSR v2.0) pci:v000010DEd000000E5sv0000147Bsd00001C0B* ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) (NF8 Mainboard) pci:v000010DEd000000E5sv00001849sd000000E5* ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) (Motherboard (one of many)) pci:v000010DEd000000E5sv0000F849sd000000E5* ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) (Motherboard (one of many)) pci:v000010DEd000000E6* ID_MODEL_FROM_DATABASE=CK8S Ethernet Controller pci:v000010DEd000000E7* ID_MODEL_FROM_DATABASE=CK8S USB Controller pci:v000010DEd000000E7sv00001043sd0000813F* ID_MODEL_FROM_DATABASE=CK8S USB Controller (K8N-E) pci:v000010DEd000000E7sv0000105Bsd00000C43* ID_MODEL_FROM_DATABASE=CK8S USB Controller (Winfast NF3250K8AA) pci:v000010DEd000000E7sv00001462sd00007030* ID_MODEL_FROM_DATABASE=CK8S USB Controller (K8N Neo-FSR v2.0) pci:v000010DEd000000E7sv0000147Bsd00001C0B* ID_MODEL_FROM_DATABASE=CK8S USB Controller (NF8 Mainboard) pci:v000010DEd000000E7sv00001849sd000000E7* ID_MODEL_FROM_DATABASE=CK8S USB Controller (Motherboard (one of many)) pci:v000010DEd000000E8* ID_MODEL_FROM_DATABASE=nForce3 EHCI USB 2.0 Controller pci:v000010DEd000000E8sv00001043sd0000813F* ID_MODEL_FROM_DATABASE=nForce3 EHCI USB 2.0 Controller (K8N-E) pci:v000010DEd000000E8sv0000105Bsd00000C43* ID_MODEL_FROM_DATABASE=nForce3 EHCI USB 2.0 Controller (Winfast NF3250K8AA) pci:v000010DEd000000E8sv00001462sd00007030* ID_MODEL_FROM_DATABASE=nForce3 EHCI USB 2.0 Controller (K8N Neo-FSR v2.0) pci:v000010DEd000000E8sv0000147Bsd00001C0B* ID_MODEL_FROM_DATABASE=nForce3 EHCI USB 2.0 Controller (NF8 Mainboard) pci:v000010DEd000000E8sv00001849sd000000E8* ID_MODEL_FROM_DATABASE=nForce3 EHCI USB 2.0 Controller (Motherboard (one of many)) pci:v000010DEd000000EA* ID_MODEL_FROM_DATABASE=nForce3 250Gb AC'97 Audio Controller pci:v000010DEd000000EAsv00001043sd0000819D* ID_MODEL_FROM_DATABASE=nForce3 250Gb AC'97 Audio Controller (K8N-E) pci:v000010DEd000000EAsv0000105Bsd00000C43* ID_MODEL_FROM_DATABASE=nForce3 250Gb AC'97 Audio Controller (Winfast NF3250K8AA) pci:v000010DEd000000EAsv00001462sd0000B010* ID_MODEL_FROM_DATABASE=nForce3 250Gb AC'97 Audio Controller (K8N Neo-FSR v2.0) pci:v000010DEd000000EAsv0000147Bsd00001C0B* ID_MODEL_FROM_DATABASE=nForce3 250Gb AC'97 Audio Controller (NF8 Mainboard) pci:v000010DEd000000ED* ID_MODEL_FROM_DATABASE=nForce3 250Gb PCI-to-PCI Bridge pci:v000010DEd000000EE* ID_MODEL_FROM_DATABASE=nForce3 Serial ATA Controller 2 pci:v000010DEd000000F1* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] pci:v000010DEd000000F1sv00001043sd000081A6* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (N6600GT TD 128M AGP) pci:v000010DEd000000F1sv00001043sd000081C6* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (N6600GT TD 128M AGP) pci:v000010DEd000000F1sv00001458sd00003150* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (GV-N66T128VP) pci:v000010DEd000000F1sv00001554sd00001191* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (PixelView PV-N43UA (128KD)) pci:v000010DEd000000F1sv00001682sd00002119* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (GeForce 6600 GT AGP) pci:v000010DEd000000F2* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] pci:v000010DEd000000F2sv00001554sd00001194* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] (PixelView PV-N43AT (256KD)) pci:v000010DEd000000F2sv00001682sd0000211C* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] (GeForce 6600 256MB DDR DUAL DVI TV) pci:v000010DEd000000F3* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6200] pci:v000010DEd000000F4* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 LE] pci:v000010DEd000000F5* ID_MODEL_FROM_DATABASE=G71 [GeForce 7800 GS] pci:v000010DEd000000F6* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6800 GS/XT] pci:v000010DEd000000F6sv00001682sd0000217E* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6800 GS/XT] (XFX GeForce 6800 XTreme 256MB DDR3 AGP) pci:v000010DEd000000F8* ID_MODEL_FROM_DATABASE=NV40GL [Quadro FX 3400/4400] pci:v000010DEd000000F9* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT/GTO/Ultra] pci:v000010DEd000000F9sv000010DEsd000000F9* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT/GTO/Ultra] (NV40 [GeForce 6800 GT]) pci:v000010DEd000000F9sv00001682sd00002120* ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT/GTO/Ultra] (GEFORCE 6800 GT PCI-E) pci:v000010DEd000000FA* ID_MODEL_FROM_DATABASE=NV36 [GeForce PCX 5750] pci:v000010DEd000000FB* ID_MODEL_FROM_DATABASE=NV38 [GeForce PCX 5900] pci:v000010DEd000000FC* ID_MODEL_FROM_DATABASE=NV37GL [Quadro FX 330/GeForce PCX 5300] pci:v000010DEd000000FD* ID_MODEL_FROM_DATABASE=NV37GL [Quadro PCI-E Series] pci:v000010DEd000000FE* ID_MODEL_FROM_DATABASE=NV38GL [Quadro FX 1300] pci:v000010DEd000000FF* ID_MODEL_FROM_DATABASE=NV18 [GeForce PCX 4300] pci:v000010DEd00000100* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] pci:v000010DEd00000100sv00001043sd00000200* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (AGP-V6600 SGRAM) pci:v000010DEd00000100sv00001043sd00000201* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (AGP-V6600 SDRAM) pci:v000010DEd00000100sv00001043sd00004008* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (AGP-V6600 SGRAM) pci:v000010DEd00000100sv00001043sd00004009* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (AGP-V6600 SDRAM) pci:v000010DEd00000100sv00001048sd00000C41* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (Erazor X) pci:v000010DEd00000100sv00001048sd00000C43* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (ERAZOR X PCI) pci:v000010DEd00000100sv00001048sd00000C48* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (Synergy Force) pci:v000010DEd00000100sv00001102sd0000102D* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (CT6941 GeForce 256) pci:v000010DEd00000100sv000014AFsd00005022* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (3D Prophet SE) pci:v000010DEd00000101* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] pci:v000010DEd00000101sv00001043sd00000202* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (AGP-V6800 DDR) pci:v000010DEd00000101sv00001043sd0000400A* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (AGP-V6800 DDR SGRAM) pci:v000010DEd00000101sv00001043sd0000400B* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (AGP-V6800 DDR SDRAM) pci:v000010DEd00000101sv00001048sd00000C42* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (Erazor X) pci:v000010DEd00000101sv0000107Dsd00002822* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (WinFast GeForce 256) pci:v000010DEd00000101sv00001102sd0000102E* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (CT6970/CT6971) pci:v000010DEd00000101sv000014AFsd00005021* ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (3D Prophet DDR-DVI) pci:v000010DEd00000103* ID_MODEL_FROM_DATABASE=NV10GL [Quadro] pci:v000010DEd00000103sv00001048sd00000C40* ID_MODEL_FROM_DATABASE=NV10GL [Quadro] (GLoria II-64) pci:v000010DEd00000103sv00001048sd00000C44* ID_MODEL_FROM_DATABASE=NV10GL [Quadro] (GLoria II) pci:v000010DEd00000103sv00001048sd00000C45* ID_MODEL_FROM_DATABASE=NV10GL [Quadro] (GLoria II) pci:v000010DEd00000103sv00001048sd00000C4A* ID_MODEL_FROM_DATABASE=NV10GL [Quadro] (GLoria II-64 Pro) pci:v000010DEd00000103sv00001048sd00000C4B* ID_MODEL_FROM_DATABASE=NV10GL [Quadro] (GLoria II-64 Pro DVII) pci:v000010DEd00000110* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] pci:v000010DEd00000110sv00001043sd00004015* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (AGP-V7100 Pro) pci:v000010DEd00000110sv00001043sd00004021* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (V7100 Deluxe Combo) pci:v000010DEd00000110sv00001043sd00004031* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (V7100 Pro with TV output) pci:v000010DEd00000110sv00001048sd00000C60* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Gladiac MX) pci:v000010DEd00000110sv00001048sd00000C61* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Gladiac 511PCI) pci:v000010DEd00000110sv00001048sd00000C63* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Gladiac 511TV-OUT 32MB) pci:v000010DEd00000110sv00001048sd00000C64* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Gladiac 511TV-OUT 64MB) pci:v000010DEd00000110sv00001048sd00000C65* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Gladiac 511TWIN) pci:v000010DEd00000110sv00001048sd00000C66* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Gladiac 311) pci:v000010DEd00000110sv000010B0sd00000001* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (GeForce2 MX Jumbo TV) pci:v000010DEd00000110sv000010DEsd00000091* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Dell OEM GeForce 2 MX 400) pci:v000010DEd00000110sv000010DEsd000000A1* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Apple OEM GeForce2 MX) pci:v000010DEd00000110sv00001462sd00008523* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (MS-8852) pci:v000010DEd00000110sv00001462sd00008817* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (MSI GeForce2 MX400 Pro32S [MS-8817]) pci:v000010DEd00000110sv000014AFsd00007102* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (3D Prophet II MX) pci:v000010DEd00000110sv000014AFsd00007103* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (3D Prophet II MX Dual-Display) pci:v000010DEd00000110sv00001545sd00000023* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Xtasy Rev. B2) pci:v000010DEd00000110sv00001554sd00001081* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (MVGA-NVG11AM(400)) pci:v000010DEd00000111* ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX200] pci:v000010DEd00000112* ID_MODEL_FROM_DATABASE=NV11M [GeForce2 Go] pci:v000010DEd00000113* ID_MODEL_FROM_DATABASE=NV11GL [Quadro2 MXR/EX/Go] pci:v000010DEd00000140* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] pci:v000010DEd00000140sv00001458sd00003125* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (GV-NX66T128D) pci:v000010DEd00000140sv00001458sd00003126* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (GV-NX66T256DE) pci:v000010DEd00000140sv00001462sd00008939* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (MS-8983) pci:v000010DEd00000141* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] pci:v000010DEd00000141sv00001043sd000081B0* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] (EN6600 Silencer) pci:v000010DEd00000141sv0000107Dsd0000593A* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] (LR2A22 128MB TV OUT) pci:v000010DEd00000141sv0000107Dsd0000597B* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] (WINFAST PX6600) pci:v000010DEd00000141sv00001458sd00003124* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] (GV-NX66128DP Turbo Force Edition) pci:v000010DEd00000142* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 LE] pci:v000010DEd00000143* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 VE] pci:v000010DEd00000144* ID_MODEL_FROM_DATABASE=NV43M [GeForce Go 6600] pci:v000010DEd00000145* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6610 XL] pci:v000010DEd00000146* ID_MODEL_FROM_DATABASE=NV43M [GeForce Go6200 TE / 6600 TE] pci:v000010DEd00000147* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6700 XL] pci:v000010DEd00000148* ID_MODEL_FROM_DATABASE=NV43M [GeForce Go 6600] pci:v000010DEd00000149* ID_MODEL_FROM_DATABASE=NV43M [GeForce Go 6600 GT] pci:v000010DEd0000014A* ID_MODEL_FROM_DATABASE=NV43 [Quadro NVS 440] pci:v000010DEd0000014B* ID_MODEL_FROM_DATABASE=NV43 pci:v000010DEd0000014D* ID_MODEL_FROM_DATABASE=NV43GL [Quadro FX 550] pci:v000010DEd0000014E* ID_MODEL_FROM_DATABASE=NV43GL [Quadro FX 540] pci:v000010DEd0000014F* ID_MODEL_FROM_DATABASE=NV43 [GeForce 6200] pci:v000010DEd00000150* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] pci:v000010DEd00000150sv00001043sd00004016* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (V7700 AGP Video Card) pci:v000010DEd00000150sv00001043sd0000402A* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (AGP-V7700) pci:v000010DEd00000150sv00001048sd00000C50* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (Gladiac) pci:v000010DEd00000150sv00001048sd00000C52* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (Gladiac-64) pci:v000010DEd00000150sv0000107Dsd00002840* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (WinFast GeForce2 GTS with TV output) pci:v000010DEd00000150sv0000107Dsd00002842* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (WinFast GeForce 2 Pro) pci:v000010DEd00000150sv000010DEsd0000002E* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (GeForce2 GTS) pci:v000010DEd00000150sv00001462sd0000815A* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (MS-8815) pci:v000010DEd00000150sv00001462sd00008831* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (Creative GeForce2 Pro) pci:v000010DEd00000151* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 Ti] pci:v000010DEd00000151sv00001043sd0000405F* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 Ti] (V7700Ti) pci:v000010DEd00000151sv00001462sd00005506* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 Ti] (Creative 3D Blaster GeForce2 Titanium) pci:v000010DEd00000151sv00001462sd00008364* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 Ti] (MS-8836) pci:v000010DEd00000152* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 Ultra] pci:v000010DEd00000152sv00001048sd00000C56* ID_MODEL_FROM_DATABASE=NV15 [GeForce2 Ultra] (GLADIAC Ultra) pci:v000010DEd00000153* ID_MODEL_FROM_DATABASE=NV15GL [Quadro2 Pro] pci:v000010DEd00000160* ID_MODEL_FROM_DATABASE=NV44 [GeForce 6500] pci:v000010DEd00000161* ID_MODEL_FROM_DATABASE=NV44 [GeForce 6200 TurboCache] pci:v000010DEd00000162* ID_MODEL_FROM_DATABASE=NV44 [GeForce 6200 SE TurboCache] pci:v000010DEd00000163* ID_MODEL_FROM_DATABASE=NV44 [GeForce 6200 LE] pci:v000010DEd00000164* ID_MODEL_FROM_DATABASE=NV44M [GeForce Go 6200] pci:v000010DEd00000165* ID_MODEL_FROM_DATABASE=NV44 [Quadro NVS 285] pci:v000010DEd00000166* ID_MODEL_FROM_DATABASE=NV44M [GeForce Go 6400] pci:v000010DEd00000167* ID_MODEL_FROM_DATABASE=NV44M [GeForce Go 6200] pci:v000010DEd00000168* ID_MODEL_FROM_DATABASE=NV44M [GeForce Go 6400] pci:v000010DEd00000169* ID_MODEL_FROM_DATABASE=NV44 [GeForce 6250] pci:v000010DEd0000016A* ID_MODEL_FROM_DATABASE=NV44 [GeForce 7100 GS] pci:v000010DEd0000016D* ID_MODEL_FROM_DATABASE=NV44 pci:v000010DEd0000016E* ID_MODEL_FROM_DATABASE=NV44 pci:v000010DEd0000016F* ID_MODEL_FROM_DATABASE=NV44 pci:v000010DEd00000170* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 460] pci:v000010DEd00000170sv00001462sd00008630* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 460] (MS-8863) pci:v000010DEd00000171* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] pci:v000010DEd00000171sv000010B0sd00000002* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (Gainward Pro/600 TV) pci:v000010DEd00000171sv000010DEsd00000008* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (Apple OEM GeForce4 MX 440) pci:v000010DEd00000171sv00001462sd00008661* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (G4MX440-VTP) pci:v000010DEd00000171sv00001462sd00008730* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (MX440SES-T (MS-8873)) pci:v000010DEd00000171sv00001462sd00008743* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (MS-8874) pci:v000010DEd00000171sv00001462sd00008852* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (GeForce4 MX440 PCI) pci:v000010DEd00000171sv0000147Bsd00008F00* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (Abit Siluro GeForce4MX440) pci:v000010DEd00000172* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 420] pci:v000010DEd00000172sv00001462sd00008730* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 420] (MS-8873) pci:v000010DEd00000172sv00001462sd00008784* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 420] (MS-8878) pci:v000010DEd00000173* ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440-SE] pci:v000010DEd00000174* ID_MODEL_FROM_DATABASE=NV17M [GeForce4 440 Go] pci:v000010DEd00000175* ID_MODEL_FROM_DATABASE=NV17M [GeForce4 420 Go] pci:v000010DEd00000176* ID_MODEL_FROM_DATABASE=NV17M [GeForce4 420 Go 32M] pci:v000010DEd00000176sv0000103Csd000008B0* ID_MODEL_FROM_DATABASE=NV17M [GeForce4 420 Go 32M] (tc1100 tablet) pci:v000010DEd00000176sv0000144Dsd0000C005* ID_MODEL_FROM_DATABASE=NV17M [GeForce4 420 Go 32M] (X10 Laptop) pci:v000010DEd00000176sv00004C53sd00001090* ID_MODEL_FROM_DATABASE=NV17M [GeForce4 420 Go 32M] (Cx9 / Vx9 mainboard) pci:v000010DEd00000177* ID_MODEL_FROM_DATABASE=NV17M [GeForce4 460 Go] pci:v000010DEd00000178* ID_MODEL_FROM_DATABASE=NV17GL [Quadro4 550 XGL] pci:v000010DEd00000179* ID_MODEL_FROM_DATABASE=NV17M [GeForce4 440 Go 64M] pci:v000010DEd00000179sv000010DEsd00000179* ID_MODEL_FROM_DATABASE=NV17M [GeForce4 440 Go 64M] (GeForce4 MX (Mac)) pci:v000010DEd0000017A* ID_MODEL_FROM_DATABASE=NV17GL [Quadro NVS] pci:v000010DEd0000017B* ID_MODEL_FROM_DATABASE=NV17GL [Quadro4 550 XGL] pci:v000010DEd0000017C* ID_MODEL_FROM_DATABASE=NV17GL [Quadro4 500 GoGL] pci:v000010DEd0000017F* ID_MODEL_FROM_DATABASE=NV17 pci:v000010DEd00000181* ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] pci:v000010DEd00000181sv00001043sd00008063* ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (GeForce4 MX 440 AGP 8X) pci:v000010DEd00000181sv00001043sd0000806F* ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (V9180 Magic) pci:v000010DEd00000181sv00001462sd00008880* ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (MS-StarForce GeForce4 MX 440 with AGP8X) pci:v000010DEd00000181sv00001462sd00008900* ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (MS-8890 GeForce 4 MX440 AGP8X) pci:v000010DEd00000181sv00001462sd00009350* ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (MSI GeForce4 MX T8X with AGP8X) pci:v000010DEd00000181sv0000147Bsd00008F0D* ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (Siluro GF4 MX-8X) pci:v000010DEd00000181sv00001554sd00001111* ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (PixelView MVGA-NVG18A) pci:v000010DEd00000182* ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440SE AGP 8x] pci:v000010DEd00000183* ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 420 AGP 8x] pci:v000010DEd00000184* ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX] pci:v000010DEd00000185* ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 4000] pci:v000010DEd00000186* ID_MODEL_FROM_DATABASE=NV18M [GeForce4 448 Go] pci:v000010DEd00000187* ID_MODEL_FROM_DATABASE=NV18M [GeForce4 488 Go] pci:v000010DEd00000188* ID_MODEL_FROM_DATABASE=NV18GL [Quadro4 580 XGL] pci:v000010DEd00000189* ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX with AGP8X (Mac)] pci:v000010DEd0000018A* ID_MODEL_FROM_DATABASE=NV18GL [Quadro NVS 280 SD] pci:v000010DEd0000018B* ID_MODEL_FROM_DATABASE=NV18GL [Quadro4 380 XGL] pci:v000010DEd0000018C* ID_MODEL_FROM_DATABASE=NV18GL [Quadro NVS 50 PCI] pci:v000010DEd0000018D* ID_MODEL_FROM_DATABASE=NV18M [GeForce4 448 Go] pci:v000010DEd0000018F* ID_MODEL_FROM_DATABASE=NV18 pci:v000010DEd00000190* ID_MODEL_FROM_DATABASE=G80 [GeForce 8800 GTS / 8800 GTX] pci:v000010DEd00000191* ID_MODEL_FROM_DATABASE=G80 [GeForce 8800 GTX] pci:v000010DEd00000192* ID_MODEL_FROM_DATABASE=G80 [GeForce 8800 GTS] pci:v000010DEd00000193* ID_MODEL_FROM_DATABASE=G80 [GeForce 8800 GTS] pci:v000010DEd00000193sv0000107Dsd000020BD* ID_MODEL_FROM_DATABASE=G80 [GeForce 8800 GTS] (WinFast PX 8800 GTS TDH) pci:v000010DEd00000194* ID_MODEL_FROM_DATABASE=G80 [GeForce 8800 Ultra] pci:v000010DEd00000197* ID_MODEL_FROM_DATABASE=G80GL [Tesla C870] pci:v000010DEd0000019D* ID_MODEL_FROM_DATABASE=G80GL [Quadro FX 5600] pci:v000010DEd0000019E* ID_MODEL_FROM_DATABASE=G80GL [Quadro FX 4600] pci:v000010DEd000001A0* ID_MODEL_FROM_DATABASE=nForce 220/420 NV11 [GeForce2 MX] pci:v000010DEd000001A4* ID_MODEL_FROM_DATABASE=nForce CPU bridge pci:v000010DEd000001AB* ID_MODEL_FROM_DATABASE=nForce 420 Memory Controller (DDR) pci:v000010DEd000001AC* ID_MODEL_FROM_DATABASE=nForce 220/420 Memory Controller pci:v000010DEd000001AD* ID_MODEL_FROM_DATABASE=nForce 220/420 Memory Controller pci:v000010DEd000001B0* ID_MODEL_FROM_DATABASE=nForce Audio Processing Unit pci:v000010DEd000001B1* ID_MODEL_FROM_DATABASE=nForce AC'97 Audio Controller pci:v000010DEd000001B2* ID_MODEL_FROM_DATABASE=nForce ISA Bridge pci:v000010DEd000001B4* ID_MODEL_FROM_DATABASE=nForce PCI System Management pci:v000010DEd000001B7* ID_MODEL_FROM_DATABASE=nForce AGP to PCI Bridge pci:v000010DEd000001B8* ID_MODEL_FROM_DATABASE=nForce PCI-to-PCI bridge pci:v000010DEd000001BC* ID_MODEL_FROM_DATABASE=nForce IDE pci:v000010DEd000001C1* ID_MODEL_FROM_DATABASE=nForce AC'97 Modem Controller pci:v000010DEd000001C2* ID_MODEL_FROM_DATABASE=nForce USB Controller pci:v000010DEd000001C3* ID_MODEL_FROM_DATABASE=nForce Ethernet Controller pci:v000010DEd000001D0* ID_MODEL_FROM_DATABASE=G72 [GeForce 7350 LE] pci:v000010DEd000001D1* ID_MODEL_FROM_DATABASE=G72 [GeForce 7300 LE] pci:v000010DEd000001D1sv0000107Dsd00005EFA* ID_MODEL_FROM_DATABASE=G72 [GeForce 7300 LE] (WinFast PX7300LE-TD128) pci:v000010DEd000001D1sv0000107Dsd00005EFB* ID_MODEL_FROM_DATABASE=G72 [GeForce 7300 LE] (WinFast PX7300LE-TD256) pci:v000010DEd000001D1sv00001462sd00000345* ID_MODEL_FROM_DATABASE=G72 [GeForce 7300 LE] (7300LE PCI Express Graphics Adapter) pci:v000010DEd000001D2* ID_MODEL_FROM_DATABASE=G72 [GeForce 7550 LE] pci:v000010DEd000001D3* ID_MODEL_FROM_DATABASE=G72 [GeForce 7200 GS / 7300 SE] pci:v000010DEd000001D3sv00001043sd00008203* ID_MODEL_FROM_DATABASE=G72 [GeForce 7200 GS / 7300 SE] (EN7300SE) pci:v000010DEd000001D3sv00001043sd00008250* ID_MODEL_FROM_DATABASE=G72 [GeForce 7200 GS / 7300 SE] (EN7200GS) pci:v000010DEd000001D5* ID_MODEL_FROM_DATABASE=G72 pci:v000010DEd000001D6* ID_MODEL_FROM_DATABASE=G72M [GeForce Go 7200] pci:v000010DEd000001D7* ID_MODEL_FROM_DATABASE=G72M [Quadro NVS 110M/GeForce Go 7300] pci:v000010DEd000001D8* ID_MODEL_FROM_DATABASE=G72M [GeForce Go 7400] pci:v000010DEd000001D8sv00001028sd000001D7* ID_MODEL_FROM_DATABASE=G72M [GeForce Go 7400] (XPS M1210) pci:v000010DEd000001D9* ID_MODEL_FROM_DATABASE=G72M [GeForce Go 7450] pci:v000010DEd000001DA* ID_MODEL_FROM_DATABASE=G72M [Quadro NVS 110M] pci:v000010DEd000001DB* ID_MODEL_FROM_DATABASE=G72M [Quadro NVS 120M] pci:v000010DEd000001DC* ID_MODEL_FROM_DATABASE=G72GLM [Quadro FX 350M] pci:v000010DEd000001DD* ID_MODEL_FROM_DATABASE=G72 [GeForce 7500 LE] pci:v000010DEd000001DE* ID_MODEL_FROM_DATABASE=G72GL [Quadro FX 350] pci:v000010DEd000001DEsv000010DEsd000001DC* ID_MODEL_FROM_DATABASE=G72GL [Quadro FX 350] (Quadro FX Go350M) pci:v000010DEd000001DF* ID_MODEL_FROM_DATABASE=G72 [GeForce 7300 GS] pci:v000010DEd000001E0* ID_MODEL_FROM_DATABASE=nForce2 IGP2 pci:v000010DEd000001E0sv0000147Bsd00001C09* ID_MODEL_FROM_DATABASE=nForce2 IGP2 (NV7 Motherboard) pci:v000010DEd000001E8* ID_MODEL_FROM_DATABASE=nForce2 AGP pci:v000010DEd000001EA* ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 0 pci:v000010DEd000001EAsv0000A0A0sd000003B9* ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 0 (UK79G-1394 motherboard) pci:v000010DEd000001EB* ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 1 pci:v000010DEd000001EBsv0000A0A0sd000003B9* ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 1 (UK79G-1394 motherboard) pci:v000010DEd000001EC* ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 2 pci:v000010DEd000001ECsv0000A0A0sd000003B9* ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 2 (UK79G-1394 motherboard) pci:v000010DEd000001ED* ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 3 pci:v000010DEd000001EDsv0000A0A0sd000003B9* ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 3 (UK79G-1394 motherboard) pci:v000010DEd000001EE* ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 4 pci:v000010DEd000001EEsv000010DEsd000001EE* ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 4 (MSI Delta-L nForce2 memory controller) pci:v000010DEd000001EEsv0000A0A0sd000003B9* ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 4 (UK79G-1394 motherboard) pci:v000010DEd000001EF* ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 5 pci:v000010DEd000001EFsv0000A0A0sd000003B9* ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 5 (UK79G-1394 motherboard) pci:v000010DEd000001F0* ID_MODEL_FROM_DATABASE=C17 [GeForce4 MX IGP] pci:v000010DEd000001F0sv0000A0A0sd000003B5* ID_MODEL_FROM_DATABASE=C17 [GeForce4 MX IGP] (UK79G-1394 motherboard) pci:v000010DEd00000200* ID_MODEL_FROM_DATABASE=NV20 [GeForce3] pci:v000010DEd00000200sv00001043sd0000402F* ID_MODEL_FROM_DATABASE=NV20 [GeForce3] (AGP-V8200 DDR) pci:v000010DEd00000200sv00001048sd00000C70* ID_MODEL_FROM_DATABASE=NV20 [GeForce3] (GLADIAC 920) pci:v000010DEd00000201* ID_MODEL_FROM_DATABASE=NV20 [GeForce3 Ti 200] pci:v000010DEd00000202* ID_MODEL_FROM_DATABASE=NV20 [GeForce3 Ti 500] pci:v000010DEd00000202sv00001043sd0000405B* ID_MODEL_FROM_DATABASE=NV20 [GeForce3 Ti 500] (V8200 T5) pci:v000010DEd00000202sv00001545sd0000002F* ID_MODEL_FROM_DATABASE=NV20 [GeForce3 Ti 500] (Xtasy 6964) pci:v000010DEd00000203* ID_MODEL_FROM_DATABASE=NV20GL [Quadro DCC] pci:v000010DEd00000211* ID_MODEL_FROM_DATABASE=NV48 [GeForce 6800] pci:v000010DEd00000212* ID_MODEL_FROM_DATABASE=NV48 [GeForce 6800 LE] pci:v000010DEd00000215* ID_MODEL_FROM_DATABASE=NV48 [GeForce 6800 GT] pci:v000010DEd00000218* ID_MODEL_FROM_DATABASE=NV48 [GeForce 6800 XT] pci:v000010DEd00000221* ID_MODEL_FROM_DATABASE=NV44A [GeForce 6200] pci:v000010DEd00000221sv00001043sd000081E1* ID_MODEL_FROM_DATABASE=NV44A [GeForce 6200] (N6200/TD/256M/A) pci:v000010DEd00000221sv00003842sd0000A341* ID_MODEL_FROM_DATABASE=NV44A [GeForce 6200] (256A8N341DX) pci:v000010DEd00000222* ID_MODEL_FROM_DATABASE=NV44 [GeForce 6200 A-LE] pci:v000010DEd00000224* ID_MODEL_FROM_DATABASE=NV44 pci:v000010DEd00000240* ID_MODEL_FROM_DATABASE=C51PV [GeForce 6150] pci:v000010DEd00000240sv00001043sd000081CD* ID_MODEL_FROM_DATABASE=C51PV [GeForce 6150] (A8N-VM CSM) pci:v000010DEd00000240sv00001462sd00007207* ID_MODEL_FROM_DATABASE=C51PV [GeForce 6150] (K8NGM2 series) pci:v000010DEd00000241* ID_MODEL_FROM_DATABASE=C51 [GeForce 6150 LE] pci:v000010DEd00000242* ID_MODEL_FROM_DATABASE=C51G [GeForce 6100] pci:v000010DEd00000242sv0000105Bsd00000CAD* ID_MODEL_FROM_DATABASE=C51G [GeForce 6100] (Winfast 6100K8MB) pci:v000010DEd00000243* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge pci:v000010DEd00000244* ID_MODEL_FROM_DATABASE=C51 [GeForce Go 6150] pci:v000010DEd00000244sv0000103Csd000030B5* ID_MODEL_FROM_DATABASE=C51 [GeForce Go 6150] (Presario V3242AU) pci:v000010DEd00000244sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=C51 [GeForce Go 6150] (Presario V6133CL) pci:v000010DEd00000244sv000010DEsd00000244* ID_MODEL_FROM_DATABASE=C51 [GeForce Go 6150] (GeForce Go 6150) pci:v000010DEd00000245* ID_MODEL_FROM_DATABASE=C51 [Quadro NVS 210S/GeForce 6150LE] pci:v000010DEd00000246* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge pci:v000010DEd00000247* ID_MODEL_FROM_DATABASE=C51 [GeForce Go 6100] pci:v000010DEd00000247sv00001043sd00001382* ID_MODEL_FROM_DATABASE=C51 [GeForce Go 6100] (MCP51 PCI-X GeForce Go 6100) pci:v000010DEd00000248* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge pci:v000010DEd00000249* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge pci:v000010DEd0000024A* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge pci:v000010DEd0000024B* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge pci:v000010DEd0000024C* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge pci:v000010DEd0000024D* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge pci:v000010DEd0000024E* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge pci:v000010DEd0000024F* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge pci:v000010DEd00000250* ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4600] pci:v000010DEd00000251* ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4400] pci:v000010DEd00000251sv00001043sd00008023* ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4400] (v8440 GeForce 4 Ti4400) pci:v000010DEd00000251sv000010DEsd00000251* ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4400] (PNY GeForce4 Ti 4400) pci:v000010DEd00000251sv00001462sd00008710* ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4400] (PNY GeForce4 Ti 4400) pci:v000010DEd00000252* ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti] pci:v000010DEd00000253* ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4200] pci:v000010DEd00000253sv0000107Dsd00002896* ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4200] (WinFast A250 LE TD (Dual VGA/TV-out/DVI)) pci:v000010DEd00000253sv0000147Bsd00008F09* ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4200] (Siluro (Dual VGA/TV-out/DVI)) pci:v000010DEd00000258* ID_MODEL_FROM_DATABASE=NV25GL [Quadro4 900 XGL] pci:v000010DEd00000259* ID_MODEL_FROM_DATABASE=NV25GL [Quadro4 750 XGL] pci:v000010DEd0000025B* ID_MODEL_FROM_DATABASE=NV25GL [Quadro4 700 XGL] pci:v000010DEd00000260* ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge pci:v000010DEd00000260sv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge (Pavilion a1677c) pci:v000010DEd00000260sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge (Presario V6133CL) pci:v000010DEd00000260sv00001043sd000081BC* ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge (A8N-VM CSM Mainboard) pci:v000010DEd00000260sv00001458sd00005001* ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge (GA-M55plus-S3G) pci:v000010DEd00000260sv00001462sd00007207* ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge (K8NGM2 series) pci:v000010DEd00000261* ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge pci:v000010DEd00000261sv0000105Bsd00000CAD* ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge (Winfast 6100K8MB) pci:v000010DEd00000262* ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge pci:v000010DEd00000263* ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge pci:v000010DEd00000264* ID_MODEL_FROM_DATABASE=MCP51 SMBus pci:v000010DEd00000264sv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=MCP51 SMBus (Pavilion a1677c) pci:v000010DEd00000264sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=MCP51 SMBus (Presario V6133CL) pci:v000010DEd00000264sv00001043sd000081BC* ID_MODEL_FROM_DATABASE=MCP51 SMBus (A8N-VM CSM Mainboard) pci:v000010DEd00000264sv0000105Bsd00000CAD* ID_MODEL_FROM_DATABASE=MCP51 SMBus (Winfast 6100K8MB) pci:v000010DEd00000264sv00001462sd00007207* ID_MODEL_FROM_DATABASE=MCP51 SMBus (K8NGM2 series) pci:v000010DEd00000265* ID_MODEL_FROM_DATABASE=MCP51 IDE pci:v000010DEd00000265sv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=MCP51 IDE (Pavilion a1677c) pci:v000010DEd00000265sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=MCP51 IDE (Presario V6133CL) pci:v000010DEd00000265sv00001043sd000081BC* ID_MODEL_FROM_DATABASE=MCP51 IDE (A8N-VM CSM Mainboard) pci:v000010DEd00000265sv00001462sd00007207* ID_MODEL_FROM_DATABASE=MCP51 IDE (K8NGM2 series) pci:v000010DEd00000265sv0000F05Bsd00000CAD* ID_MODEL_FROM_DATABASE=MCP51 IDE (Winfast 6100K8MB) pci:v000010DEd00000266* ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller pci:v000010DEd00000266sv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (Pavilion a1677c) pci:v000010DEd00000266sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (Presario V6133CL) pci:v000010DEd00000266sv00001043sd000081BC* ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (A8N-VM CSM Mainboard) pci:v000010DEd00000266sv00001462sd00007207* ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (K8NGM2 series) pci:v000010DEd00000267* ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller pci:v000010DEd00000267sv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (Pavilion a1677c) pci:v000010DEd00000267sv00001043sd000081BC* ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (A8N-VM CSM Mainboard) pci:v000010DEd00000267sv00001462sd00007207* ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (K8NGM2 series) pci:v000010DEd00000268* ID_MODEL_FROM_DATABASE=MCP51 Ethernet Controller pci:v000010DEd00000269* ID_MODEL_FROM_DATABASE=MCP51 Ethernet Controller pci:v000010DEd00000269sv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=MCP51 Ethernet Controller (Pavilion a1677c) pci:v000010DEd00000269sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=MCP51 Ethernet Controller (Presario V6133CL) pci:v000010DEd00000269sv00001043sd00008141* ID_MODEL_FROM_DATABASE=MCP51 Ethernet Controller (A8N-VM CSM Mainboard) pci:v000010DEd00000269sv00001462sd00007207* ID_MODEL_FROM_DATABASE=MCP51 Ethernet Controller (K8NGM2 series) pci:v000010DEd0000026A* ID_MODEL_FROM_DATABASE=MCP51 MCI pci:v000010DEd0000026B* ID_MODEL_FROM_DATABASE=MCP51 AC97 Audio Controller pci:v000010DEd0000026Bsv0000105Bsd00000CAD* ID_MODEL_FROM_DATABASE=MCP51 AC97 Audio Controller (Winfast 6100K8MB) pci:v000010DEd0000026C* ID_MODEL_FROM_DATABASE=MCP51 High Definition Audio pci:v000010DEd0000026Csv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=MCP51 High Definition Audio (Pavilion a1677c) pci:v000010DEd0000026Csv0000103Csd000030B5* ID_MODEL_FROM_DATABASE=MCP51 High Definition Audio (Presario V3242AU) pci:v000010DEd0000026Csv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=MCP51 High Definition Audio (Presario V6133CL) pci:v000010DEd0000026Csv000010DEsd0000CB84* ID_MODEL_FROM_DATABASE=MCP51 High Definition Audio (ASUSTeK Computer Inc. A8N-VM CSM Mainboard) pci:v000010DEd0000026Csv00001462sd00007207* ID_MODEL_FROM_DATABASE=MCP51 High Definition Audio (K8NGM2 series) pci:v000010DEd0000026D* ID_MODEL_FROM_DATABASE=MCP51 USB Controller pci:v000010DEd0000026Dsv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=MCP51 USB Controller (Pavilion a1677c) pci:v000010DEd0000026Dsv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=MCP51 USB Controller (Presario V6133CL) pci:v000010DEd0000026Dsv00001043sd000081BC* ID_MODEL_FROM_DATABASE=MCP51 USB Controller (A8N-VM CSM Mainboard) pci:v000010DEd0000026Dsv0000105Bsd00000CAD* ID_MODEL_FROM_DATABASE=MCP51 USB Controller (Winfast 6100K8MB) pci:v000010DEd0000026Dsv00001462sd00007207* ID_MODEL_FROM_DATABASE=MCP51 USB Controller (K8NGM2 series) pci:v000010DEd0000026E* ID_MODEL_FROM_DATABASE=MCP51 USB Controller pci:v000010DEd0000026Esv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=MCP51 USB Controller (Pavilion a1677c) pci:v000010DEd0000026Esv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=MCP51 USB Controller (Presario V6133CL) pci:v000010DEd0000026Esv00001043sd000081BC* ID_MODEL_FROM_DATABASE=MCP51 USB Controller (A8N-VM CSM Mainboard) pci:v000010DEd0000026Esv0000105Bsd00000CAD* ID_MODEL_FROM_DATABASE=MCP51 USB Controller (Winfast 6100K8MB) pci:v000010DEd0000026Esv00001462sd00007207* ID_MODEL_FROM_DATABASE=MCP51 USB Controller (K8NGM2 series) pci:v000010DEd0000026F* ID_MODEL_FROM_DATABASE=MCP51 PCI Bridge pci:v000010DEd0000026Fsv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=MCP51 PCI Bridge (Presario V6133CL) pci:v000010DEd00000270* ID_MODEL_FROM_DATABASE=MCP51 Host Bridge pci:v000010DEd00000270sv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=MCP51 Host Bridge (Pavilion a1677c) pci:v000010DEd00000270sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=MCP51 Host Bridge (Presario V6133CL) pci:v000010DEd00000270sv00001043sd000081BC* ID_MODEL_FROM_DATABASE=MCP51 Host Bridge (A8N-VM CSM Mainboard) pci:v000010DEd00000270sv0000105Bsd00000CAD* ID_MODEL_FROM_DATABASE=MCP51 Host Bridge (Winfast 6100K8MB) pci:v000010DEd00000270sv00001458sd00005001* ID_MODEL_FROM_DATABASE=MCP51 Host Bridge (GA-M55plus-S3G) pci:v000010DEd00000270sv00001462sd00007207* ID_MODEL_FROM_DATABASE=MCP51 Host Bridge (K8NGM2 series) pci:v000010DEd00000271* ID_MODEL_FROM_DATABASE=MCP51 PMU pci:v000010DEd00000271sv0000103Csd000030B5* ID_MODEL_FROM_DATABASE=MCP51 PMU (Presario V3242AU) pci:v000010DEd00000271sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=MCP51 PMU (Presario V6133CL) pci:v000010DEd00000272* ID_MODEL_FROM_DATABASE=MCP51 Memory Controller 0 pci:v000010DEd00000272sv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=MCP51 Memory Controller 0 (Pavilion a1677c) pci:v000010DEd00000272sv0000105Bsd00000CAD* ID_MODEL_FROM_DATABASE=MCP51 Memory Controller 0 (Winfast 6100K8MB) pci:v000010DEd0000027E* ID_MODEL_FROM_DATABASE=C51 Memory Controller 2 pci:v000010DEd0000027Esv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=C51 Memory Controller 2 (Pavilion a1677c) pci:v000010DEd0000027Esv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=C51 Memory Controller 2 (Presario V6133CL) pci:v000010DEd0000027Esv00001043sd000081CD* ID_MODEL_FROM_DATABASE=C51 Memory Controller 2 (A8N-VM CSM Mainboard) pci:v000010DEd0000027Esv00001458sd00005000* ID_MODEL_FROM_DATABASE=C51 Memory Controller 2 (GA-M55plus-S3G) pci:v000010DEd0000027Esv00001462sd00007207* ID_MODEL_FROM_DATABASE=C51 Memory Controller 2 (K8NGM2 series) pci:v000010DEd0000027F* ID_MODEL_FROM_DATABASE=C51 Memory Controller 3 pci:v000010DEd0000027Fsv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=C51 Memory Controller 3 (Pavilion a1677c) pci:v000010DEd0000027Fsv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=C51 Memory Controller 3 (Presario V6133CL) pci:v000010DEd0000027Fsv00001043sd000081CD* ID_MODEL_FROM_DATABASE=C51 Memory Controller 3 (A8N-VM CSM Mainboard) pci:v000010DEd0000027Fsv00001458sd00005000* ID_MODEL_FROM_DATABASE=C51 Memory Controller 3 (GA-M55plus-S3G) pci:v000010DEd0000027Fsv00001462sd00007207* ID_MODEL_FROM_DATABASE=C51 Memory Controller 3 (K8NGM2 series) pci:v000010DEd00000280* ID_MODEL_FROM_DATABASE=NV28 [GeForce4 Ti 4800] pci:v000010DEd00000281* ID_MODEL_FROM_DATABASE=NV28 [GeForce4 Ti 4200 AGP 8x] pci:v000010DEd00000282* ID_MODEL_FROM_DATABASE=NV28 [GeForce4 Ti 4800 SE] pci:v000010DEd00000286* ID_MODEL_FROM_DATABASE=NV28M [GeForce4 Ti 4200 Go AGP 8x] pci:v000010DEd00000288* ID_MODEL_FROM_DATABASE=NV28GL [Quadro4 980 XGL] pci:v000010DEd00000289* ID_MODEL_FROM_DATABASE=NV28GL [Quadro4 780 XGL] pci:v000010DEd0000028C* ID_MODEL_FROM_DATABASE=NV28GLM [Quadro4 Go700] pci:v000010DEd00000290* ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GTX] pci:v000010DEd00000291* ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GT/GTO] pci:v000010DEd00000291sv000010DEsd0000042B* ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GT/GTO] (NX7900GTO-T2D512E [7900 GTO]) pci:v000010DEd00000292* ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GS] pci:v000010DEd00000293* ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GX2] pci:v000010DEd00000294* ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GX2] pci:v000010DEd00000295* ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT] pci:v000010DEd00000295sv00001043sd00008225* ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT] (GeForce 7950 GT) pci:v000010DEd00000295sv0000107Dsd00002A68* ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT] (WinFast PX7950GT TDH) pci:v000010DEd00000295sv00001462sd00000663* ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT] (NX7950GT-VT2D512EZ-HD) pci:v000010DEd00000297* ID_MODEL_FROM_DATABASE=G71M [GeForce Go 7950 GTX] pci:v000010DEd00000298* ID_MODEL_FROM_DATABASE=G71M [GeForce Go 7900 GS] pci:v000010DEd00000299* ID_MODEL_FROM_DATABASE=G71M [GeForce Go 7900 GTX] pci:v000010DEd0000029A* ID_MODEL_FROM_DATABASE=G71GLM [Quadro FX 2500M] pci:v000010DEd0000029B* ID_MODEL_FROM_DATABASE=G71GLM [Quadro FX 1500M] pci:v000010DEd0000029C* ID_MODEL_FROM_DATABASE=G71GL [Quadro FX 5500] pci:v000010DEd0000029D* ID_MODEL_FROM_DATABASE=G71GL [Quadro FX 3500] pci:v000010DEd0000029Dsv00001028sd0000019B* ID_MODEL_FROM_DATABASE=G71GL [Quadro FX 3500] (G71GLM [Quadro FX 3500M]) pci:v000010DEd0000029E* ID_MODEL_FROM_DATABASE=G71GL [Quadro FX 1500] pci:v000010DEd0000029F* ID_MODEL_FROM_DATABASE=G71GL [Quadro FX 4500 X2] pci:v000010DEd000002A0* ID_MODEL_FROM_DATABASE=NV2A [XGPU] pci:v000010DEd000002A5* ID_MODEL_FROM_DATABASE=MCPX CPU Bridge pci:v000010DEd000002A6* ID_MODEL_FROM_DATABASE=MCPX Memory Controller pci:v000010DEd000002E0* ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT] pci:v000010DEd000002E0sv000002E0sd00002249* ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT] (GF 7600GT 560M 256MB DDR3 DUAL DVI TV) pci:v000010DEd000002E1* ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS] pci:v000010DEd000002E1sv00001682sd0000222B* ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS] (PV-T73K-UAL3 (256MB)) pci:v000010DEd000002E1sv00001682sd00002247* ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS] (GF 7600GS 512MB DDR2) pci:v000010DEd000002E2* ID_MODEL_FROM_DATABASE=G73 [GeForce 7300 GT] pci:v000010DEd000002E3* ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GS] pci:v000010DEd000002E4* ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT] pci:v000010DEd000002E4sv00001682sd00002271* ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT] (PV-T71A-YDF7 (512MB)) pci:v000010DEd000002F0* ID_MODEL_FROM_DATABASE=C51 Host Bridge pci:v000010DEd000002F0sv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=C51 Host Bridge (Pavilion a1677c) pci:v000010DEd000002F0sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=C51 Host Bridge (Presario V6133CL) pci:v000010DEd000002F0sv00001043sd000081CD* ID_MODEL_FROM_DATABASE=C51 Host Bridge (A8N-VM CSM Mainboard) pci:v000010DEd000002F0sv00001462sd00007207* ID_MODEL_FROM_DATABASE=C51 Host Bridge (K8NGM2 series) pci:v000010DEd000002F1* ID_MODEL_FROM_DATABASE=C51 Host Bridge pci:v000010DEd000002F1sv00001458sd00005000* ID_MODEL_FROM_DATABASE=C51 Host Bridge (GA-M55plus-S3G) pci:v000010DEd000002F2* ID_MODEL_FROM_DATABASE=C51 Host Bridge pci:v000010DEd000002F3* ID_MODEL_FROM_DATABASE=C51 Host Bridge pci:v000010DEd000002F4* ID_MODEL_FROM_DATABASE=C51 Host Bridge pci:v000010DEd000002F5* ID_MODEL_FROM_DATABASE=C51 Host Bridge pci:v000010DEd000002F6* ID_MODEL_FROM_DATABASE=C51 Host Bridge pci:v000010DEd000002F7* ID_MODEL_FROM_DATABASE=C51 Host Bridge pci:v000010DEd000002F8* ID_MODEL_FROM_DATABASE=C51 Memory Controller 5 pci:v000010DEd000002F8sv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=C51 Memory Controller 5 (Pavilion a1677c) pci:v000010DEd000002F8sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=C51 Memory Controller 5 (Presario V6133CL) pci:v000010DEd000002F8sv00001043sd000081CD* ID_MODEL_FROM_DATABASE=C51 Memory Controller 5 (A8N-VM CSM Mainboard) pci:v000010DEd000002F8sv00001458sd00005000* ID_MODEL_FROM_DATABASE=C51 Memory Controller 5 (GA-M55plus-S3G) pci:v000010DEd000002F8sv00001462sd00007207* ID_MODEL_FROM_DATABASE=C51 Memory Controller 5 (K8NGM2 series) pci:v000010DEd000002F9* ID_MODEL_FROM_DATABASE=C51 Memory Controller 4 pci:v000010DEd000002F9sv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=C51 Memory Controller 4 (Pavilion a1677c) pci:v000010DEd000002F9sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=C51 Memory Controller 4 (Presario V6133CL) pci:v000010DEd000002F9sv00001043sd000081CD* ID_MODEL_FROM_DATABASE=C51 Memory Controller 4 (A8N-VM CSM Mainboard) pci:v000010DEd000002F9sv00001458sd00005000* ID_MODEL_FROM_DATABASE=C51 Memory Controller 4 (GA-M55plus-S3G) pci:v000010DEd000002F9sv00001462sd00007207* ID_MODEL_FROM_DATABASE=C51 Memory Controller 4 (K8NGM2 series) pci:v000010DEd000002FA* ID_MODEL_FROM_DATABASE=C51 Memory Controller 0 pci:v000010DEd000002FAsv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=C51 Memory Controller 0 (Pavilion a1677c) pci:v000010DEd000002FAsv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=C51 Memory Controller 0 (Presario V6133CL) pci:v000010DEd000002FAsv00001043sd000081CD* ID_MODEL_FROM_DATABASE=C51 Memory Controller 0 (A8N-VM CSM Mainboard) pci:v000010DEd000002FAsv00001458sd00005000* ID_MODEL_FROM_DATABASE=C51 Memory Controller 0 (GA-M55plus-S3G) pci:v000010DEd000002FAsv00001462sd00007207* ID_MODEL_FROM_DATABASE=C51 Memory Controller 0 (K8NGM2 series) pci:v000010DEd000002FB* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge pci:v000010DEd000002FC* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge pci:v000010DEd000002FCsv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge (Presario V6133CL) pci:v000010DEd000002FD* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge pci:v000010DEd000002FDsv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge (Presario V6133CL) pci:v000010DEd000002FE* ID_MODEL_FROM_DATABASE=C51 Memory Controller 1 pci:v000010DEd000002FEsv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=C51 Memory Controller 1 (Pavilion a1677c) pci:v000010DEd000002FEsv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=C51 Memory Controller 1 (Presario V6133CL) pci:v000010DEd000002FEsv00001043sd000081CD* ID_MODEL_FROM_DATABASE=C51 Memory Controller 1 (A8N-VM CSM Mainboard) pci:v000010DEd000002FEsv00001458sd00005000* ID_MODEL_FROM_DATABASE=C51 Memory Controller 1 (GA-M55plus-S3G) pci:v000010DEd000002FEsv00001462sd00007207* ID_MODEL_FROM_DATABASE=C51 Memory Controller 1 (K8NGM2 series) pci:v000010DEd000002FF* ID_MODEL_FROM_DATABASE=C51 Host Bridge pci:v000010DEd000002FFsv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=C51 Host Bridge (Pavilion a1677c) pci:v000010DEd000002FFsv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=C51 Host Bridge (Presario V6133CL) pci:v000010DEd000002FFsv00001043sd000081CD* ID_MODEL_FROM_DATABASE=C51 Host Bridge (A8N-VM CSM Mainboard) pci:v000010DEd000002FFsv00001458sd00005000* ID_MODEL_FROM_DATABASE=C51 Host Bridge (GA-M55plus-S3G) pci:v000010DEd000002FFsv00001462sd00007207* ID_MODEL_FROM_DATABASE=C51 Host Bridge (K8NGM2 series) pci:v000010DEd00000300* ID_MODEL_FROM_DATABASE=NV30 [GeForce FX] pci:v000010DEd00000301* ID_MODEL_FROM_DATABASE=NV30 [GeForce FX 5800 Ultra] pci:v000010DEd00000302* ID_MODEL_FROM_DATABASE=NV30 [GeForce FX 5800] pci:v000010DEd00000308* ID_MODEL_FROM_DATABASE=NV30GL [Quadro FX 2000] pci:v000010DEd00000309* ID_MODEL_FROM_DATABASE=NV30GL [Quadro FX 1000] pci:v000010DEd00000311* ID_MODEL_FROM_DATABASE=NV31 [GeForce FX 5600 Ultra] pci:v000010DEd00000312* ID_MODEL_FROM_DATABASE=NV31 [GeForce FX 5600] pci:v000010DEd00000314* ID_MODEL_FROM_DATABASE=NV31 [GeForce FX 5600XT] pci:v000010DEd00000314sv00001043sd0000814A* ID_MODEL_FROM_DATABASE=NV31 [GeForce FX 5600XT] (V9560XT/TD) pci:v000010DEd00000316* ID_MODEL_FROM_DATABASE=NV31M pci:v000010DEd00000318* ID_MODEL_FROM_DATABASE=NV31GL pci:v000010DEd0000031A* ID_MODEL_FROM_DATABASE=NV31M [GeForce FX Go5600] pci:v000010DEd0000031B* ID_MODEL_FROM_DATABASE=NV31M [GeForce FX Go5650] pci:v000010DEd0000031C* ID_MODEL_FROM_DATABASE=NV31GLM [Quadro FX Go700] pci:v000010DEd00000320* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] pci:v000010DEd00000321* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200 Ultra] pci:v000010DEd00000322* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] pci:v000010DEd00000322sv00001043sd000002FB* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (V9250 Magic) pci:v000010DEd00000322sv00001043sd00008180* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (V9520-X/TD/128M) pci:v000010DEd00000322sv0000107Dsd00002967* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (WinFast A340T 128MB) pci:v000010DEd00000322sv00001462sd00009110* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (MS-8911 (FX5200-TD128)) pci:v000010DEd00000322sv00001462sd00009171* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (MS-8917 (FX5200-T128)) pci:v000010DEd00000322sv00001462sd00009360* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (MS-8936 (FX5200-T128)) pci:v000010DEd00000322sv00001682sd00001351* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (GeForce FX 5200) pci:v000010DEd00000323* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200LE] pci:v000010DEd00000324* ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200 64M] pci:v000010DEd00000324sv00001028sd00000196* ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200 64M] (Inspiron 5160) pci:v000010DEd00000324sv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200 64M] (Pavilion ZD7000 laptop) pci:v000010DEd00000324sv00001071sd00008160* ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200 64M] (MIM2000) pci:v000010DEd00000325* ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5250] pci:v000010DEd00000326* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5500] pci:v000010DEd00000326sv00001458sd0000310D* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5500] (GeForce FX 5500 128 MB) pci:v000010DEd00000326sv00001682sd00002034* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5500] (GeForce 5500 256 MB) pci:v000010DEd00000327* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5100] pci:v000010DEd00000328* ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200 32M/64M] pci:v000010DEd00000329* ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200] pci:v000010DEd00000329sv000010DEsd00000010* ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200] (Powerbook G4) pci:v000010DEd0000032A* ID_MODEL_FROM_DATABASE=NV34GL [Quadro NVS 280 PCI] pci:v000010DEd0000032B* ID_MODEL_FROM_DATABASE=NV34GL [Quadro FX 500/600 PCI] pci:v000010DEd0000032C* ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5300 / Go5350] pci:v000010DEd0000032D* ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5100] pci:v000010DEd0000032E* ID_MODEL_FROM_DATABASE=NV34 pci:v000010DEd0000032F* ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] pci:v000010DEd00000330* ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900 Ultra] pci:v000010DEd00000330sv00001043sd00008137* ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900 Ultra] (V9950 Ultra / 256 MB) pci:v000010DEd00000331* ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900] pci:v000010DEd00000331sv00001043sd00008145* ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900] (V9950GE) pci:v000010DEd00000332* ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900XT] pci:v000010DEd00000333* ID_MODEL_FROM_DATABASE=NV38 [GeForce FX 5950 Ultra] pci:v000010DEd00000334* ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900ZT] pci:v000010DEd00000334sv00001462sd00009373* ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900ZT] (FX5900ZT-VTD128 (MS-8937)) pci:v000010DEd00000338* ID_MODEL_FROM_DATABASE=NV35GL [Quadro FX 3000] pci:v000010DEd0000033F* ID_MODEL_FROM_DATABASE=NV35GL [Quadro FX 700] pci:v000010DEd00000341* ID_MODEL_FROM_DATABASE=NV36 [GeForce FX 5700 Ultra] pci:v000010DEd00000341sv00001462sd00009380* ID_MODEL_FROM_DATABASE=NV36 [GeForce FX 5700 Ultra] (MS-8938 (FX5700U-TD128)) pci:v000010DEd00000342* ID_MODEL_FROM_DATABASE=NV36 [GeForce FX 5700] pci:v000010DEd00000343* ID_MODEL_FROM_DATABASE=NV36 [GeForce FX 5700LE] pci:v000010DEd00000344* ID_MODEL_FROM_DATABASE=NV36 [GeForce FX 5700VE] pci:v000010DEd00000347* ID_MODEL_FROM_DATABASE=NV36M [GeForce FX Go5700] pci:v000010DEd00000347sv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=NV36M [GeForce FX Go5700] (NX9500) pci:v000010DEd00000348* ID_MODEL_FROM_DATABASE=NV36M [GeForce FX Go5700] pci:v000010DEd0000034C* ID_MODEL_FROM_DATABASE=NV36 [Quadro FX Go1000] pci:v000010DEd0000034D* ID_MODEL_FROM_DATABASE=NV36 pci:v000010DEd0000034E* ID_MODEL_FROM_DATABASE=NV36GL [Quadro FX 1100] pci:v000010DEd00000360* ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge pci:v000010DEd00000361* ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge pci:v000010DEd00000361sv00001028sd00000221* ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge (PowerEdge R805 MCP55 LPC Bridge) pci:v000010DEd00000362* ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge pci:v000010DEd00000362sv0000147Bsd00001C24* ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge (KN9 series mainboard) pci:v000010DEd00000363* ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge pci:v000010DEd00000364* ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge pci:v000010DEd00000364sv00001028sd00000221* ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge (PowerEdge R805 MCP55 LPC Bridge) pci:v000010DEd00000365* ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge pci:v000010DEd00000366* ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge pci:v000010DEd00000367* ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge pci:v000010DEd00000368* ID_MODEL_FROM_DATABASE=MCP55 SMBus Controller pci:v000010DEd00000368sv00001028sd0000020C* ID_MODEL_FROM_DATABASE=MCP55 SMBus Controller (PowerEdge M605 MCP55 SMBus) pci:v000010DEd00000368sv00001028sd00000221* ID_MODEL_FROM_DATABASE=MCP55 SMBus Controller (PowerEdge R805 MCP55 SMBus) pci:v000010DEd00000368sv0000147Bsd00001C24* ID_MODEL_FROM_DATABASE=MCP55 SMBus Controller (KN9 series mainboard) pci:v000010DEd00000369* ID_MODEL_FROM_DATABASE=MCP55 Memory Controller pci:v000010DEd00000369sv0000147Bsd00001C24* ID_MODEL_FROM_DATABASE=MCP55 Memory Controller (KN9 series mainboard) pci:v000010DEd0000036A* ID_MODEL_FROM_DATABASE=MCP55 Memory Controller pci:v000010DEd0000036B* ID_MODEL_FROM_DATABASE=MCP55 SMU pci:v000010DEd0000036C* ID_MODEL_FROM_DATABASE=MCP55 USB Controller pci:v000010DEd0000036Csv00001028sd0000020C* ID_MODEL_FROM_DATABASE=MCP55 USB Controller (PowerEdge M605 MCP55 USB Controller) pci:v000010DEd0000036Csv00001028sd00000221* ID_MODEL_FROM_DATABASE=MCP55 USB Controller (PowerEdge R805 MCP55 USB Controller) pci:v000010DEd0000036Csv0000147Bsd00001C24* ID_MODEL_FROM_DATABASE=MCP55 USB Controller (KN9 series mainboard) pci:v000010DEd0000036D* ID_MODEL_FROM_DATABASE=MCP55 USB Controller pci:v000010DEd0000036Dsv00001028sd0000020C* ID_MODEL_FROM_DATABASE=MCP55 USB Controller (PowerEdge M605 MCP55 USB Controller) pci:v000010DEd0000036Dsv00001028sd00000221* ID_MODEL_FROM_DATABASE=MCP55 USB Controller (PowerEdge R805 MCP55 USB Controller) pci:v000010DEd0000036Dsv0000147Bsd00001C24* ID_MODEL_FROM_DATABASE=MCP55 USB Controller (KN9 series mainboard) pci:v000010DEd0000036E* ID_MODEL_FROM_DATABASE=MCP55 IDE pci:v000010DEd0000036Esv0000147Bsd00001C24* ID_MODEL_FROM_DATABASE=MCP55 IDE (KN9 series mainboard) pci:v000010DEd00000370* ID_MODEL_FROM_DATABASE=MCP55 PCI bridge pci:v000010DEd00000371* ID_MODEL_FROM_DATABASE=MCP55 High Definition Audio pci:v000010DEd00000371sv0000147Bsd00001C24* ID_MODEL_FROM_DATABASE=MCP55 High Definition Audio (KN9 series mainboard) pci:v000010DEd00000372* ID_MODEL_FROM_DATABASE=MCP55 Ethernet pci:v000010DEd00000373* ID_MODEL_FROM_DATABASE=MCP55 Ethernet pci:v000010DEd00000373sv0000147Bsd00001C24* ID_MODEL_FROM_DATABASE=MCP55 Ethernet (KN9 series mainboard) pci:v000010DEd00000374* ID_MODEL_FROM_DATABASE=MCP55 PCI Express bridge pci:v000010DEd00000375* ID_MODEL_FROM_DATABASE=MCP55 PCI Express bridge pci:v000010DEd00000376* ID_MODEL_FROM_DATABASE=MCP55 PCI Express bridge pci:v000010DEd00000377* ID_MODEL_FROM_DATABASE=MCP55 PCI Express bridge pci:v000010DEd00000378* ID_MODEL_FROM_DATABASE=MCP55 PCI Express bridge pci:v000010DEd0000037A* ID_MODEL_FROM_DATABASE=MCP55 Memory Controller pci:v000010DEd0000037E* ID_MODEL_FROM_DATABASE=MCP55 SATA Controller pci:v000010DEd0000037F* ID_MODEL_FROM_DATABASE=MCP55 SATA Controller pci:v000010DEd0000037Fsv00001028sd00000221* ID_MODEL_FROM_DATABASE=MCP55 SATA Controller (PowerEdge R805 MCP55 SATA Controller) pci:v000010DEd0000037Fsv0000147Bsd00001C24* ID_MODEL_FROM_DATABASE=MCP55 SATA Controller (KN9 series mainboard) pci:v000010DEd0000038B* ID_MODEL_FROM_DATABASE=G73 [GeForce 7650 GS] pci:v000010DEd00000390* ID_MODEL_FROM_DATABASE=G73 [GeForce 7650 GS] pci:v000010DEd00000391* ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT] pci:v000010DEd00000391sv00001458sd00003427* ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT] (GV-NX76T128D-RH) pci:v000010DEd00000391sv00001462sd00000452* ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT] (NX7600GT-VT2D256E) pci:v000010DEd00000392* ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS] pci:v000010DEd00000392sv00001462sd00000622* ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS] (NX7600GS-T2D256EH) pci:v000010DEd00000393* ID_MODEL_FROM_DATABASE=G73 [GeForce 7300 GT] pci:v000010DEd00000393sv000010DEsd00000412* ID_MODEL_FROM_DATABASE=G73 [GeForce 7300 GT] (NX7300GT-TD256EH) pci:v000010DEd00000393sv00001462sd00000412* ID_MODEL_FROM_DATABASE=G73 [GeForce 7300 GT] (NX7300GT-TD256EH) pci:v000010DEd00000394* ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 LE] pci:v000010DEd00000395* ID_MODEL_FROM_DATABASE=G73 [GeForce 7300 GT] pci:v000010DEd00000396* ID_MODEL_FROM_DATABASE=G73 pci:v000010DEd00000397* ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7700] pci:v000010DEd00000398* ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7600] pci:v000010DEd00000398sv00001025sd0000006C* ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7600] (Acer 9814 WKMI) pci:v000010DEd00000399* ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7600 GT] pci:v000010DEd0000039A* ID_MODEL_FROM_DATABASE=G73M [Quadro NVS 300M] pci:v000010DEd0000039B* ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7900 SE] pci:v000010DEd0000039C* ID_MODEL_FROM_DATABASE=G73GLM [Quadro FX 550M] pci:v000010DEd0000039Csv000010DEsd0000039C* ID_MODEL_FROM_DATABASE=G73GLM [Quadro FX 550M] (Quadro FX 560M) pci:v000010DEd0000039D* ID_MODEL_FROM_DATABASE=G73 pci:v000010DEd0000039E* ID_MODEL_FROM_DATABASE=G73GL [Quadro FX 560] pci:v000010DEd0000039F* ID_MODEL_FROM_DATABASE=G73 pci:v000010DEd000003A0* ID_MODEL_FROM_DATABASE=C55 Host Bridge pci:v000010DEd000003A1* ID_MODEL_FROM_DATABASE=C55 Host Bridge pci:v000010DEd000003A2* ID_MODEL_FROM_DATABASE=C55 Host Bridge pci:v000010DEd000003A3* ID_MODEL_FROM_DATABASE=C55 Host Bridge pci:v000010DEd000003A4* ID_MODEL_FROM_DATABASE=C55 Host Bridge pci:v000010DEd000003A5* ID_MODEL_FROM_DATABASE=C55 Host Bridge pci:v000010DEd000003A6* ID_MODEL_FROM_DATABASE=C55 Host Bridge pci:v000010DEd000003A7* ID_MODEL_FROM_DATABASE=C55 Host Bridge pci:v000010DEd000003A8* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003A9* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003AA* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003AB* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003AC* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003AD* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003AE* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003AF* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003B0* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003B1* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003B2* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003B3* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003B4* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003B5* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003B6* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003B7* ID_MODEL_FROM_DATABASE=C55 PCI Express bridge pci:v000010DEd000003B8* ID_MODEL_FROM_DATABASE=C55 PCI Express bridge pci:v000010DEd000003B9* ID_MODEL_FROM_DATABASE=C55 PCI Express bridge pci:v000010DEd000003BA* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003BB* ID_MODEL_FROM_DATABASE=C55 PCI Express bridge pci:v000010DEd000003BC* ID_MODEL_FROM_DATABASE=C55 Memory Controller pci:v000010DEd000003D0* ID_MODEL_FROM_DATABASE=C61 [GeForce 6150SE nForce 430] pci:v000010DEd000003D0sv00001028sd0000020E* ID_MODEL_FROM_DATABASE=C61 [GeForce 6150SE nForce 430] (Inspiron 531) pci:v000010DEd000003D1* ID_MODEL_FROM_DATABASE=C61 [GeForce 6100 nForce 405] pci:v000010DEd000003D2* ID_MODEL_FROM_DATABASE=C61 [GeForce 6100 nForce 400] pci:v000010DEd000003D5* ID_MODEL_FROM_DATABASE=C61 [GeForce 6100 nForce 420] pci:v000010DEd000003D6* ID_MODEL_FROM_DATABASE=C61 [GeForce 7025 / nForce 630a] pci:v000010DEd000003E0* ID_MODEL_FROM_DATABASE=MCP61 LPC Bridge pci:v000010DEd000003E0sv00001028sd0000020E* ID_MODEL_FROM_DATABASE=MCP61 LPC Bridge (Inspiron 531) pci:v000010DEd000003E0sv00001849sd000003E0* ID_MODEL_FROM_DATABASE=MCP61 LPC Bridge (939NF6G-VSTA Board) pci:v000010DEd000003E1* ID_MODEL_FROM_DATABASE=MCP61 LPC Bridge pci:v000010DEd000003E1sv00001043sd000083A4* ID_MODEL_FROM_DATABASE=MCP61 LPC Bridge (M4N68T series motherboard) pci:v000010DEd000003E2* ID_MODEL_FROM_DATABASE=MCP61 Host Bridge pci:v000010DEd000003E2sv00001043sd000083A4* ID_MODEL_FROM_DATABASE=MCP61 Host Bridge (M4N68T series motherboard) pci:v000010DEd000003E3* ID_MODEL_FROM_DATABASE=MCP61 LPC Bridge pci:v000010DEd000003E4* ID_MODEL_FROM_DATABASE=MCP61 High Definition Audio pci:v000010DEd000003E5* ID_MODEL_FROM_DATABASE=MCP61 Ethernet pci:v000010DEd000003E6* ID_MODEL_FROM_DATABASE=MCP61 Ethernet pci:v000010DEd000003E7* ID_MODEL_FROM_DATABASE=MCP61 SATA Controller pci:v000010DEd000003E8* ID_MODEL_FROM_DATABASE=MCP61 PCI Express bridge pci:v000010DEd000003E8sv00001028sd0000020E* ID_MODEL_FROM_DATABASE=MCP61 PCI Express bridge (Inspiron 531) pci:v000010DEd000003E8sv00001849sd000003E8* ID_MODEL_FROM_DATABASE=MCP61 PCI Express bridge (939NF6G-VSTA Board) pci:v000010DEd000003E9* ID_MODEL_FROM_DATABASE=MCP61 PCI Express bridge pci:v000010DEd000003E9sv00001028sd0000020E* ID_MODEL_FROM_DATABASE=MCP61 PCI Express bridge (Inspiron 531) pci:v000010DEd000003E9sv00001849sd000003E9* ID_MODEL_FROM_DATABASE=MCP61 PCI Express bridge (939NF6G-VSTA Board) pci:v000010DEd000003EA* ID_MODEL_FROM_DATABASE=MCP61 Memory Controller pci:v000010DEd000003EAsv00001028sd0000020E* ID_MODEL_FROM_DATABASE=MCP61 Memory Controller (Inspiron 531) pci:v000010DEd000003EAsv00001849sd000003EA* ID_MODEL_FROM_DATABASE=MCP61 Memory Controller (939NF6G-VSTA Board) pci:v000010DEd000003EB* ID_MODEL_FROM_DATABASE=MCP61 SMBus pci:v000010DEd000003EBsv00001028sd0000020E* ID_MODEL_FROM_DATABASE=MCP61 SMBus (Inspiron 531) pci:v000010DEd000003EBsv00001043sd000083A4* ID_MODEL_FROM_DATABASE=MCP61 SMBus (M4N68T series motherboard) pci:v000010DEd000003EBsv00001849sd000003EB* ID_MODEL_FROM_DATABASE=MCP61 SMBus (939NF6G-VSTA Board) pci:v000010DEd000003EC* ID_MODEL_FROM_DATABASE=MCP61 IDE pci:v000010DEd000003ECsv00001025sd00000392* ID_MODEL_FROM_DATABASE=MCP61 IDE (ET1350) pci:v000010DEd000003ECsv00001028sd0000020E* ID_MODEL_FROM_DATABASE=MCP61 IDE (Inspiron 531) pci:v000010DEd000003ECsv00001043sd000083A4* ID_MODEL_FROM_DATABASE=MCP61 IDE (M4N68T series motherboard) pci:v000010DEd000003ECsv00001849sd000003EC* ID_MODEL_FROM_DATABASE=MCP61 IDE (939NF6G-VSTA Board) pci:v000010DEd000003EE* ID_MODEL_FROM_DATABASE=MCP61 Ethernet pci:v000010DEd000003EF* ID_MODEL_FROM_DATABASE=MCP61 Ethernet pci:v000010DEd000003EFsv00001025sd00008000* ID_MODEL_FROM_DATABASE=MCP61 Ethernet (ET1350) pci:v000010DEd000003EFsv00001028sd0000020E* ID_MODEL_FROM_DATABASE=MCP61 Ethernet (Inspiron 531) pci:v000010DEd000003EFsv00001043sd000083A4* ID_MODEL_FROM_DATABASE=MCP61 Ethernet (M4N68T series motherboard) pci:v000010DEd000003EFsv00001849sd000003EF* ID_MODEL_FROM_DATABASE=MCP61 Ethernet (939NF6G-VSTA Board) pci:v000010DEd000003F0* ID_MODEL_FROM_DATABASE=MCP61 High Definition Audio pci:v000010DEd000003F0sv00001028sd0000020E* ID_MODEL_FROM_DATABASE=MCP61 High Definition Audio (Inspiron 531) pci:v000010DEd000003F0sv00001043sd00008415* ID_MODEL_FROM_DATABASE=MCP61 High Definition Audio (M4N68T series motherboard) pci:v000010DEd000003F0sv00001849sd00000888* ID_MODEL_FROM_DATABASE=MCP61 High Definition Audio (939NF6G-VSTA Board) pci:v000010DEd000003F1* ID_MODEL_FROM_DATABASE=MCP61 USB 1.1 Controller pci:v000010DEd000003F1sv00001028sd0000020E* ID_MODEL_FROM_DATABASE=MCP61 USB 1.1 Controller (Inspiron 531) pci:v000010DEd000003F1sv00001043sd000083A4* ID_MODEL_FROM_DATABASE=MCP61 USB 1.1 Controller (M4N68T series motherboard) pci:v000010DEd000003F1sv00001849sd000003F1* ID_MODEL_FROM_DATABASE=MCP61 USB 1.1 Controller (939NF6G-VSTA Board) pci:v000010DEd000003F2* ID_MODEL_FROM_DATABASE=MCP61 USB 2.0 Controller pci:v000010DEd000003F2sv00001028sd0000020E* ID_MODEL_FROM_DATABASE=MCP61 USB 2.0 Controller (Inspiron 531) pci:v000010DEd000003F2sv00001043sd000083A4* ID_MODEL_FROM_DATABASE=MCP61 USB 2.0 Controller (M4N68T series motherboard) pci:v000010DEd000003F2sv00001849sd000003F2* ID_MODEL_FROM_DATABASE=MCP61 USB 2.0 Controller (939NF6G-VSTA Board) pci:v000010DEd000003F3* ID_MODEL_FROM_DATABASE=MCP61 PCI bridge pci:v000010DEd000003F3sv00001028sd0000020E* ID_MODEL_FROM_DATABASE=MCP61 PCI bridge (Inspiron 531) pci:v000010DEd000003F3sv00001849sd000003F3* ID_MODEL_FROM_DATABASE=MCP61 PCI bridge (939NF6G-VSTA Board) pci:v000010DEd000003F4* ID_MODEL_FROM_DATABASE=MCP61 SMU pci:v000010DEd000003F5* ID_MODEL_FROM_DATABASE=MCP61 Memory Controller pci:v000010DEd000003F5sv00001028sd0000020E* ID_MODEL_FROM_DATABASE=MCP61 Memory Controller (Inspiron 531) pci:v000010DEd000003F5sv00001043sd000083A4* ID_MODEL_FROM_DATABASE=MCP61 Memory Controller (M4N68T series motherboard) pci:v000010DEd000003F5sv00001849sd000003EB* ID_MODEL_FROM_DATABASE=MCP61 Memory Controller (939NF6G-VSTA Board) pci:v000010DEd000003F6* ID_MODEL_FROM_DATABASE=MCP61 SATA Controller pci:v000010DEd000003F6sv00001028sd0000020E* ID_MODEL_FROM_DATABASE=MCP61 SATA Controller (Inspiron 531) pci:v000010DEd000003F6sv00001043sd000083A4* ID_MODEL_FROM_DATABASE=MCP61 SATA Controller (M4N68T series motherboard) pci:v000010DEd000003F6sv00001849sd000003F6* ID_MODEL_FROM_DATABASE=MCP61 SATA Controller (939NF6G-VSTA Board) pci:v000010DEd000003F7* ID_MODEL_FROM_DATABASE=MCP61 SATA Controller pci:v000010DEd00000400* ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GTS] pci:v000010DEd00000400sv00001043sd00008241* ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GTS] (EN8600GTS) pci:v000010DEd00000401* ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GT] pci:v000010DEd00000402* ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GT] pci:v000010DEd00000402sv00001458sd00003455* ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GT] (GV-NX86T512H) pci:v000010DEd00000402sv00001462sd00000910* ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GT] (NX8600GT-T2D256EZ) pci:v000010DEd00000403* ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GS] pci:v000010DEd00000404* ID_MODEL_FROM_DATABASE=G84 [GeForce 8400 GS] pci:v000010DEd00000404sv00001462sd00001230* ID_MODEL_FROM_DATABASE=G84 [GeForce 8400 GS] (NX8400GS-TD256E) pci:v000010DEd00000405* ID_MODEL_FROM_DATABASE=G84M [GeForce 9500M GS] pci:v000010DEd00000406* ID_MODEL_FROM_DATABASE=G84 [GeForce 8300 GS] pci:v000010DEd00000407* ID_MODEL_FROM_DATABASE=G84M [GeForce 8600M GT] pci:v000010DEd00000408* ID_MODEL_FROM_DATABASE=G84M [GeForce 9650M GS] pci:v000010DEd00000409* ID_MODEL_FROM_DATABASE=G84M [GeForce 8700M GT] pci:v000010DEd0000040A* ID_MODEL_FROM_DATABASE=G84GL [Quadro FX 370] pci:v000010DEd0000040B* ID_MODEL_FROM_DATABASE=G84GLM [Quadro NVS 320M] pci:v000010DEd0000040C* ID_MODEL_FROM_DATABASE=G84GLM [Quadro FX 570M] pci:v000010DEd0000040Csv000017AAsd000020D9* ID_MODEL_FROM_DATABASE=G84GLM [Quadro FX 570M] (ThinkPad T61p) pci:v000010DEd0000040D* ID_MODEL_FROM_DATABASE=G84GLM [Quadro FX 1600M] pci:v000010DEd0000040E* ID_MODEL_FROM_DATABASE=G84GL [Quadro FX 570] pci:v000010DEd0000040F* ID_MODEL_FROM_DATABASE=G84GL [Quadro FX 1700] pci:v000010DEd00000410* ID_MODEL_FROM_DATABASE=G92 [GeForce GT 330] pci:v000010DEd00000414* ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GT] pci:v000010DEd00000420* ID_MODEL_FROM_DATABASE=G86 [GeForce 8400 SE] pci:v000010DEd00000421* ID_MODEL_FROM_DATABASE=G86 [GeForce 8500 GT] pci:v000010DEd00000421sv00001462sd00000960* ID_MODEL_FROM_DATABASE=G86 [GeForce 8500 GT] (NX8500GT-TD512EH/M2) pci:v000010DEd00000422* ID_MODEL_FROM_DATABASE=G86 [GeForce 8400 GS] pci:v000010DEd00000423* ID_MODEL_FROM_DATABASE=G86 [GeForce 8300 GS] pci:v000010DEd00000424* ID_MODEL_FROM_DATABASE=G86 [GeForce 8400 GS] pci:v000010DEd00000425* ID_MODEL_FROM_DATABASE=G86M [GeForce 8600M GS] pci:v000010DEd00000425sv00001025sd00000121* ID_MODEL_FROM_DATABASE=G86M [GeForce 8600M GS] (Aspire 5920G) pci:v000010DEd00000426* ID_MODEL_FROM_DATABASE=G86M [GeForce 8400M GT] pci:v000010DEd00000427* ID_MODEL_FROM_DATABASE=G86M [GeForce 8400M GS] pci:v000010DEd00000427sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=G86M [GeForce 8400M GS] (Pavilion dv6700) pci:v000010DEd00000427sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=G86M [GeForce 8400M GS] (Pavilion dv9668eg Laptop) pci:v000010DEd00000428* ID_MODEL_FROM_DATABASE=G86M [GeForce 8400M G] pci:v000010DEd00000429* ID_MODEL_FROM_DATABASE=G86M [Quadro NVS 140M] pci:v000010DEd00000429sv000017AAsd000020D8* ID_MODEL_FROM_DATABASE=G86M [Quadro NVS 140M] (ThinkPad T61) pci:v000010DEd0000042A* ID_MODEL_FROM_DATABASE=G86M [Quadro NVS 130M] pci:v000010DEd0000042B* ID_MODEL_FROM_DATABASE=G86M [Quadro NVS 135M] pci:v000010DEd0000042C* ID_MODEL_FROM_DATABASE=G86 [GeForce 9400 GT] pci:v000010DEd0000042D* ID_MODEL_FROM_DATABASE=G86GLM [Quadro FX 360M] pci:v000010DEd0000042E* ID_MODEL_FROM_DATABASE=G86M [GeForce 9300M G] pci:v000010DEd0000042F* ID_MODEL_FROM_DATABASE=G86 [Quadro NVS 290] pci:v000010DEd00000440* ID_MODEL_FROM_DATABASE=MCP65 LPC Bridge pci:v000010DEd00000441* ID_MODEL_FROM_DATABASE=MCP65 LPC Bridge pci:v000010DEd00000442* ID_MODEL_FROM_DATABASE=MCP65 LPC Bridge pci:v000010DEd00000442sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=MCP65 LPC Bridge (Pavilion dv9668eg Laptop) pci:v000010DEd00000443* ID_MODEL_FROM_DATABASE=MCP65 LPC Bridge pci:v000010DEd00000444* ID_MODEL_FROM_DATABASE=MCP65 Memory Controller pci:v000010DEd00000444sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=MCP65 Memory Controller (Pavilion dv9668eg Laptop) pci:v000010DEd00000445* ID_MODEL_FROM_DATABASE=MCP65 Memory Controller pci:v000010DEd00000446* ID_MODEL_FROM_DATABASE=MCP65 SMBus pci:v000010DEd00000446sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=MCP65 SMBus (Pavilion dv9668eg Laptop) pci:v000010DEd00000447* ID_MODEL_FROM_DATABASE=MCP65 SMU pci:v000010DEd00000447sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=MCP65 SMU (Pavilion dv9500/9600/9700 series) pci:v000010DEd00000448* ID_MODEL_FROM_DATABASE=MCP65 IDE pci:v000010DEd00000448sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=MCP65 IDE (Pavilion dv9668eg Laptop) pci:v000010DEd00000449* ID_MODEL_FROM_DATABASE=MCP65 PCI bridge pci:v000010DEd00000449sv000010DEsd0000CB84* ID_MODEL_FROM_DATABASE=MCP65 PCI bridge (HP Pavilion dv9668eg Laptop) pci:v000010DEd0000044A* ID_MODEL_FROM_DATABASE=MCP65 High Definition Audio pci:v000010DEd0000044Asv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=MCP65 High Definition Audio (Pavilion dv9668eg Laptop) pci:v000010DEd0000044B* ID_MODEL_FROM_DATABASE=MCP65 High Definition Audio pci:v000010DEd0000044C* ID_MODEL_FROM_DATABASE=MCP65 AHCI Controller pci:v000010DEd0000044D* ID_MODEL_FROM_DATABASE=MCP65 AHCI Controller pci:v000010DEd0000044E* ID_MODEL_FROM_DATABASE=MCP65 AHCI Controller pci:v000010DEd0000044F* ID_MODEL_FROM_DATABASE=MCP65 AHCI Controller pci:v000010DEd00000450* ID_MODEL_FROM_DATABASE=MCP65 Ethernet pci:v000010DEd00000450sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=MCP65 Ethernet (Pavilion dv9668eg Laptop) pci:v000010DEd00000451* ID_MODEL_FROM_DATABASE=MCP65 Ethernet pci:v000010DEd00000452* ID_MODEL_FROM_DATABASE=MCP65 Ethernet pci:v000010DEd00000453* ID_MODEL_FROM_DATABASE=MCP65 Ethernet pci:v000010DEd00000454* ID_MODEL_FROM_DATABASE=MCP65 USB 1.1 OHCI Controller pci:v000010DEd00000454sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=MCP65 USB 1.1 OHCI Controller (Pavilion dv9668eg Laptop) pci:v000010DEd00000455* ID_MODEL_FROM_DATABASE=MCP65 USB 2.0 EHCI Controller pci:v000010DEd00000455sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=MCP65 USB 2.0 EHCI Controller (Pavilion dv9668eg Laptop) pci:v000010DEd00000456* ID_MODEL_FROM_DATABASE=MCP65 USB Controller pci:v000010DEd00000457* ID_MODEL_FROM_DATABASE=MCP65 USB Controller pci:v000010DEd00000458* ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge pci:v000010DEd00000458sv000010DEsd00000000* ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge pci:v000010DEd00000459* ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge pci:v000010DEd00000459sv000010DEsd00000000* ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge pci:v000010DEd0000045A* ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge pci:v000010DEd0000045Asv000010DEsd00000000* ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge pci:v000010DEd0000045B* ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge pci:v000010DEd0000045Bsv000010DEsd00000000* ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge pci:v000010DEd0000045C* ID_MODEL_FROM_DATABASE=MCP65 SATA Controller pci:v000010DEd0000045D* ID_MODEL_FROM_DATABASE=MCP65 SATA Controller pci:v000010DEd0000045Dsv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=MCP65 SATA Controller (Pavilion dv9668eg Laptop) pci:v000010DEd0000045E* ID_MODEL_FROM_DATABASE=MCP65 SATA Controller pci:v000010DEd0000045F* ID_MODEL_FROM_DATABASE=MCP65 SATA Controller pci:v000010DEd00000531* ID_MODEL_FROM_DATABASE=C67 [GeForce 7150M / nForce 630M] pci:v000010DEd00000533* ID_MODEL_FROM_DATABASE=C67 [GeForce 7000M / nForce 610M] pci:v000010DEd0000053A* ID_MODEL_FROM_DATABASE=C68 [GeForce 7050 PV / nForce 630a] pci:v000010DEd0000053B* ID_MODEL_FROM_DATABASE=C68 [GeForce 7050 PV / nForce 630a] pci:v000010DEd0000053Bsv00001043sd00008308* ID_MODEL_FROM_DATABASE=C68 [GeForce 7050 PV / nForce 630a] (M2N68-AM Motherbord) pci:v000010DEd0000053E* ID_MODEL_FROM_DATABASE=C68 [GeForce 7025 / nForce 630a] pci:v000010DEd00000541* ID_MODEL_FROM_DATABASE=MCP67 Memory Controller pci:v000010DEd00000542* ID_MODEL_FROM_DATABASE=MCP67 SMBus pci:v000010DEd00000542sv00001043sd00008308* ID_MODEL_FROM_DATABASE=MCP67 SMBus (M2N68-AM Motherbord) pci:v000010DEd00000543* ID_MODEL_FROM_DATABASE=MCP67 Co-processor pci:v000010DEd00000547* ID_MODEL_FROM_DATABASE=MCP67 Memory Controller pci:v000010DEd00000547sv00001043sd00008308* ID_MODEL_FROM_DATABASE=MCP67 Memory Controller (M2N68-AM Motherbord) pci:v000010DEd00000547sv00001849sd00000547* ID_MODEL_FROM_DATABASE=MCP67 Memory Controller (ALiveNF7G-HDready) pci:v000010DEd00000548* ID_MODEL_FROM_DATABASE=MCP67 ISA Bridge pci:v000010DEd00000548sv00001043sd00008308* ID_MODEL_FROM_DATABASE=MCP67 ISA Bridge (M2N68-AM Motherboard) pci:v000010DEd0000054C* ID_MODEL_FROM_DATABASE=MCP67 Ethernet pci:v000010DEd0000054Csv00001043sd00008308* ID_MODEL_FROM_DATABASE=MCP67 Ethernet (M2N68-AM Motherbord) pci:v000010DEd0000054Csv00001849sd0000054C* ID_MODEL_FROM_DATABASE=MCP67 Ethernet (ALiveNF7G-HDready, MCP67 Gigabit Ethernet) pci:v000010DEd0000054D* ID_MODEL_FROM_DATABASE=MCP67 Ethernet pci:v000010DEd0000054E* ID_MODEL_FROM_DATABASE=MCP67 Ethernet pci:v000010DEd0000054F* ID_MODEL_FROM_DATABASE=MCP67 Ethernet pci:v000010DEd00000550* ID_MODEL_FROM_DATABASE=MCP67 AHCI Controller pci:v000010DEd00000550sv00001043sd00008308* ID_MODEL_FROM_DATABASE=MCP67 AHCI Controller (M2N68-AM Motherboard) pci:v000010DEd00000554* ID_MODEL_FROM_DATABASE=MCP67 AHCI Controller pci:v000010DEd00000554sv00001043sd00008308* ID_MODEL_FROM_DATABASE=MCP67 AHCI Controller (M2N68-AM Motherboard) pci:v000010DEd00000555* ID_MODEL_FROM_DATABASE=MCP67 SATA Controller pci:v000010DEd00000555sv00001043sd00008308* ID_MODEL_FROM_DATABASE=MCP67 SATA Controller (M2N68-AM Motherboard) pci:v000010DEd0000055C* ID_MODEL_FROM_DATABASE=MCP67 High Definition Audio pci:v000010DEd0000055Csv00001043sd00008290* ID_MODEL_FROM_DATABASE=MCP67 High Definition Audio (M2N68-AM Motherboard) pci:v000010DEd0000055D* ID_MODEL_FROM_DATABASE=MCP67 High Definition Audio pci:v000010DEd0000055E* ID_MODEL_FROM_DATABASE=MCP67 OHCI USB 1.1 Controller pci:v000010DEd0000055Esv00001043sd00008308* ID_MODEL_FROM_DATABASE=MCP67 OHCI USB 1.1 Controller (M2N68-AM Motherboard) pci:v000010DEd0000055F* ID_MODEL_FROM_DATABASE=MCP67 EHCI USB 2.0 Controller pci:v000010DEd0000055Fsv00001043sd00008308* ID_MODEL_FROM_DATABASE=MCP67 EHCI USB 2.0 Controller (M2N68-AM Motherboard) pci:v000010DEd00000560* ID_MODEL_FROM_DATABASE=MCP67 IDE Controller pci:v000010DEd00000560sv0000F043sd00008308* ID_MODEL_FROM_DATABASE=MCP67 IDE Controller (M2N68-AM Motherboard) pci:v000010DEd00000561* ID_MODEL_FROM_DATABASE=MCP67 PCI Bridge pci:v000010DEd00000562* ID_MODEL_FROM_DATABASE=MCP67 PCI Express Bridge pci:v000010DEd00000562sv00001849sd00000562* ID_MODEL_FROM_DATABASE=MCP67 PCI Express Bridge (ALiveNF7G-HDready) pci:v000010DEd00000563* ID_MODEL_FROM_DATABASE=MCP67 PCI Express Bridge pci:v000010DEd00000568* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller pci:v000010DEd00000568sv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (Pavilion p6310f) pci:v000010DEd00000568sv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (M3N72-D) pci:v000010DEd00000568sv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (K9N2GM-FIH) pci:v000010DEd00000568sv00001849sd00000568* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (K10N78FullHD-hSLI R3.0 Memory Controller) pci:v000010DEd00000569* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge pci:v000010DEd00000569sv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (Pavilion p6310f) pci:v000010DEd00000569sv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (M3N72-D) pci:v000010DEd00000569sv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (K9N2GM-FIH) pci:v000010DEd00000569sv00001849sd00000569* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (K10N78FullHD-hSLI R3.0 PCI Express Bridge) pci:v000010DEd0000056A* ID_MODEL_FROM_DATABASE=MCP73 [nForce 630i] USB 2.0 Controller (EHCI) pci:v000010DEd0000056Asv00001019sd0000297A* ID_MODEL_FROM_DATABASE=MCP73 [nForce 630i] USB 2.0 Controller (EHCI) (MCP73PVT-SM) pci:v000010DEd0000056Asv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=MCP73 [nForce 630i] USB 2.0 Controller (EHCI) (I-N73V motherboard) pci:v000010DEd0000056C* ID_MODEL_FROM_DATABASE=MCP73 IDE Controller pci:v000010DEd0000056Csv00001019sd0000297A* ID_MODEL_FROM_DATABASE=MCP73 IDE Controller (MCP73PVT-SM) pci:v000010DEd0000056Csv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=MCP73 IDE Controller (I-N73V motherboard) pci:v000010DEd0000056Csv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=MCP73 IDE Controller (JW-IN7150-HD) pci:v000010DEd0000056D* ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge pci:v000010DEd0000056Dsv00001019sd0000297A* ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge (MCP73PVT-SM) pci:v000010DEd0000056Dsv000010DEsd0000CB73* ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge (MCP73 PCI Bridge) pci:v000010DEd0000056E* ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge pci:v000010DEd0000056Esv00001019sd0000297A* ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge (MCP73PVT-SM) pci:v000010DEd0000056Esv000010DEsd00000000* ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge (MCP73 PCIe x16 port) pci:v000010DEd0000056F* ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge pci:v000010DEd0000056Fsv00001019sd0000297A* ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge (MCP73PVT-SM) pci:v000010DEd0000056Fsv000010DEsd00000000* ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge (MCP73 PCIe x1 port) pci:v000010DEd000005B1* ID_MODEL_FROM_DATABASE=NF200 PCIe 2.0 switch pci:v000010DEd000005B8* ID_MODEL_FROM_DATABASE=NF200 PCIe 2.0 switch for GTX 295 pci:v000010DEd000005BE* ID_MODEL_FROM_DATABASE=NF200 PCIe 2.0 switch for Quadro Plex S4 / Tesla S870 / Tesla S1070 / Tesla S2050 pci:v000010DEd000005E0* ID_MODEL_FROM_DATABASE=GT200b [GeForce GTX 295] pci:v000010DEd000005E1* ID_MODEL_FROM_DATABASE=GT200 [GeForce GTX 280] pci:v000010DEd000005E2* ID_MODEL_FROM_DATABASE=GT200 [GeForce GTX 260] pci:v000010DEd000005E3* ID_MODEL_FROM_DATABASE=GT200b [GeForce GTX 285] pci:v000010DEd000005E3sv00001682sd00002490* ID_MODEL_FROM_DATABASE=GT200b [GeForce GTX 285] (GX-285N-ZDF) pci:v000010DEd000005E6* ID_MODEL_FROM_DATABASE=GT200b [GeForce GTX 275] pci:v000010DEd000005E7* ID_MODEL_FROM_DATABASE=GT200GL [Tesla C1060 / M1060] pci:v000010DEd000005E7sv000010DEsd00000595* ID_MODEL_FROM_DATABASE=GT200GL [Tesla C1060 / M1060] (Tesla T10 Processor) pci:v000010DEd000005E7sv000010DEsd0000068F* ID_MODEL_FROM_DATABASE=GT200GL [Tesla C1060 / M1060] (Tesla T10 Processor) pci:v000010DEd000005E7sv000010DEsd00000697* ID_MODEL_FROM_DATABASE=GT200GL [Tesla C1060 / M1060] (Tesla M1060) pci:v000010DEd000005E7sv000010DEsd00000714* ID_MODEL_FROM_DATABASE=GT200GL [Tesla C1060 / M1060] (Tesla M1060) pci:v000010DEd000005E7sv000010DEsd00000743* ID_MODEL_FROM_DATABASE=GT200GL [Tesla C1060 / M1060] (Tesla M1060) pci:v000010DEd000005EA* ID_MODEL_FROM_DATABASE=GT200 [GeForce GTX 260] pci:v000010DEd000005EB* ID_MODEL_FROM_DATABASE=GT200 [GeForce GTX 295] pci:v000010DEd000005ED* ID_MODEL_FROM_DATABASE=GT200GL [Quadro Plex 2200 D2] pci:v000010DEd000005F1* ID_MODEL_FROM_DATABASE=GT200 [GeForce GTX 280] pci:v000010DEd000005F2* ID_MODEL_FROM_DATABASE=GT200 [GeForce GTX 260] pci:v000010DEd000005F8* ID_MODEL_FROM_DATABASE=GT200GL [Quadro Plex 2200 S4] pci:v000010DEd000005F9* ID_MODEL_FROM_DATABASE=GT200GL [Quadro CX] pci:v000010DEd000005FD* ID_MODEL_FROM_DATABASE=GT200GL [Quadro FX 5800] pci:v000010DEd000005FE* ID_MODEL_FROM_DATABASE=GT200GL [Quadro FX 4800] pci:v000010DEd000005FF* ID_MODEL_FROM_DATABASE=GT200GL [Quadro FX 3800] pci:v000010DEd00000600* ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GTS 512] pci:v000010DEd00000601* ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GT] pci:v000010DEd00000602* ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GT] pci:v000010DEd00000603* ID_MODEL_FROM_DATABASE=G92 [GeForce GT 230 OEM] pci:v000010DEd00000604* ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GX2] pci:v000010DEd00000605* ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GT] pci:v000010DEd00000606* ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GS] pci:v000010DEd00000607* ID_MODEL_FROM_DATABASE=G92 [GeForce GTS 240] pci:v000010DEd00000608* ID_MODEL_FROM_DATABASE=G92M [GeForce 9800M GTX] pci:v000010DEd00000609* ID_MODEL_FROM_DATABASE=G92M [GeForce 8800M GTS] pci:v000010DEd00000609sv0000106Bsd000000A7* ID_MODEL_FROM_DATABASE=G92M [GeForce 8800M GTS] (GeForce 8800 GS) pci:v000010DEd0000060A* ID_MODEL_FROM_DATABASE=G92M [GeForce GTX 280M] pci:v000010DEd0000060B* ID_MODEL_FROM_DATABASE=G92M [GeForce 9800M GT] pci:v000010DEd0000060C* ID_MODEL_FROM_DATABASE=G92M [GeForce 8800M GTX] pci:v000010DEd0000060D* ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GS] pci:v000010DEd0000060F* ID_MODEL_FROM_DATABASE=G92M [GeForce GTX 285M] pci:v000010DEd00000610* ID_MODEL_FROM_DATABASE=G92 [GeForce 9600 GSO] pci:v000010DEd00000610sv00001682sd00002385* ID_MODEL_FROM_DATABASE=G92 [GeForce 9600 GSO] (GeForce 9600 GSO 768mb) pci:v000010DEd00000611* ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GT] pci:v000010DEd00000611sv0000107Dsd00002AB0* ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GT] (Winfast PX8800 GT PCI-E) pci:v000010DEd00000611sv000019DAsd00001040* ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GT] (ZT-88TES2P-FSP) pci:v000010DEd00000612* ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GTX / 9800 GTX+] pci:v000010DEd00000613* ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GTX+] pci:v000010DEd00000614* ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GT] pci:v000010DEd00000614sv0000107Dsd00002AB3* ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GT] (WinFast PX9800 GT (S-Fanpipe)) pci:v000010DEd00000615* ID_MODEL_FROM_DATABASE=G92 [GeForce GTS 250] pci:v000010DEd00000615sv00003842sd00001150* ID_MODEL_FROM_DATABASE=G92 [GeForce GTS 250] (GeForce GTS 250 P/N 512-P3-1150-TR) pci:v000010DEd00000615sv00003842sd00001151* ID_MODEL_FROM_DATABASE=G92 [GeForce GTS 250] (GeForce GTS 250 P/N 512-P3-1151-TR) pci:v000010DEd00000615sv00003842sd00001155* ID_MODEL_FROM_DATABASE=G92 [GeForce GTS 250] (GeForce GTS 250 P/N 01G-P3-1155-TR) pci:v000010DEd00000615sv00003842sd00001156* ID_MODEL_FROM_DATABASE=G92 [GeForce GTS 250] (GeForce GTS 250 P/N 01G-P3-1156-TR) pci:v000010DEd00000617* ID_MODEL_FROM_DATABASE=G92M [GeForce 9800M GTX] pci:v000010DEd00000618* ID_MODEL_FROM_DATABASE=G92M [GeForce GTX 260M] pci:v000010DEd00000619* ID_MODEL_FROM_DATABASE=G92GL [Quadro FX 4700 X2] pci:v000010DEd0000061A* ID_MODEL_FROM_DATABASE=G92GL [Quadro FX 3700] pci:v000010DEd0000061B* ID_MODEL_FROM_DATABASE=G92GL [Quadro VX 200] pci:v000010DEd0000061C* ID_MODEL_FROM_DATABASE=G92GLM [Quadro FX 3600M] pci:v000010DEd0000061D* ID_MODEL_FROM_DATABASE=G92GLM [Quadro FX 2800M] pci:v000010DEd0000061E* ID_MODEL_FROM_DATABASE=G92GLM [Quadro FX 3700M] pci:v000010DEd0000061F* ID_MODEL_FROM_DATABASE=G92GLM [Quadro FX 3800M] pci:v000010DEd00000620* ID_MODEL_FROM_DATABASE=G94 [GeForce 9800 GT] pci:v000010DEd00000621* ID_MODEL_FROM_DATABASE=G94 [GeForce GT 230] pci:v000010DEd00000622* ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] pci:v000010DEd00000622sv0000107Dsd00002AC1* ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] (WinFast PX9600GT 1024MB) pci:v000010DEd00000622sv00001458sd00003481* ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] (GV-NX96T512HP) pci:v000010DEd00000623* ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GS] pci:v000010DEd00000624* ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT Green Edition] pci:v000010DEd00000625* ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GSO 512] pci:v000010DEd00000626* ID_MODEL_FROM_DATABASE=G94 [GeForce GT 130] pci:v000010DEd00000627* ID_MODEL_FROM_DATABASE=G94 [GeForce GT 140] pci:v000010DEd00000628* ID_MODEL_FROM_DATABASE=G94M [GeForce 9800M GTS] pci:v000010DEd0000062A* ID_MODEL_FROM_DATABASE=G94M [GeForce 9700M GTS] pci:v000010DEd0000062B* ID_MODEL_FROM_DATABASE=G94M [GeForce 9800M GS] pci:v000010DEd0000062C* ID_MODEL_FROM_DATABASE=G94M [GeForce 9800M GTS] pci:v000010DEd0000062D* ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] pci:v000010DEd0000062E* ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] pci:v000010DEd0000062Esv0000106Bsd00000605* ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] (GeForce GT 130) pci:v000010DEd0000062F* ID_MODEL_FROM_DATABASE=G94 [GeForce 9800 S] pci:v000010DEd00000630* ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] pci:v000010DEd00000631* ID_MODEL_FROM_DATABASE=G94M [GeForce GTS 160M] pci:v000010DEd00000632* ID_MODEL_FROM_DATABASE=G94M [GeForce GTS 150M] pci:v000010DEd00000633* ID_MODEL_FROM_DATABASE=G94 [GeForce GT 220] pci:v000010DEd00000635* ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GSO] pci:v000010DEd00000637* ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] pci:v000010DEd00000638* ID_MODEL_FROM_DATABASE=G94GL [Quadro FX 1800] pci:v000010DEd0000063A* ID_MODEL_FROM_DATABASE=G94GLM [Quadro FX 2700M] pci:v000010DEd0000063F* ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GE] pci:v000010DEd00000640* ID_MODEL_FROM_DATABASE=G96 [GeForce 9500 GT] pci:v000010DEd00000641* ID_MODEL_FROM_DATABASE=G96 [GeForce 9400 GT] pci:v000010DEd00000641sv00001682sd00004009* ID_MODEL_FROM_DATABASE=G96 [GeForce 9400 GT] (PV-T94G-ZAFG) pci:v000010DEd00000642* ID_MODEL_FROM_DATABASE=G96 [D9M-10] pci:v000010DEd00000643* ID_MODEL_FROM_DATABASE=G96 [GeForce 9500 GT] pci:v000010DEd00000644* ID_MODEL_FROM_DATABASE=G96 [GeForce 9500 GS] pci:v000010DEd00000644sv0000174Bsd00009600* ID_MODEL_FROM_DATABASE=G96 [GeForce 9500 GS] (Geforce 9500GS 512M DDR2 V/D/HDMI) pci:v000010DEd00000645* ID_MODEL_FROM_DATABASE=G96 [GeForce 9500 GS] pci:v000010DEd00000646* ID_MODEL_FROM_DATABASE=G96 [GeForce GT 120] pci:v000010DEd00000647* ID_MODEL_FROM_DATABASE=G96M [GeForce 9600M GT] pci:v000010DEd00000648* ID_MODEL_FROM_DATABASE=G96M [GeForce 9600M GS] pci:v000010DEd00000649* ID_MODEL_FROM_DATABASE=G96M [GeForce 9600M GT] pci:v000010DEd00000649sv00001043sd0000202D* ID_MODEL_FROM_DATABASE=G96M [GeForce 9600M GT] (GeForce GT 220M) pci:v000010DEd0000064A* ID_MODEL_FROM_DATABASE=G96M [GeForce 9700M GT] pci:v000010DEd0000064B* ID_MODEL_FROM_DATABASE=G96M [GeForce 9500M G] pci:v000010DEd0000064C* ID_MODEL_FROM_DATABASE=G96M [GeForce 9650M GT] pci:v000010DEd0000064D* ID_MODEL_FROM_DATABASE=G96 [GeForce 9600 GT] pci:v000010DEd0000064E* ID_MODEL_FROM_DATABASE=G96 [GeForce 9600 GT / 9800 GT] pci:v000010DEd00000651* ID_MODEL_FROM_DATABASE=G96M [GeForce G 110M] pci:v000010DEd00000652* ID_MODEL_FROM_DATABASE=G96M [GeForce GT 130M] pci:v000010DEd00000652sv0000152Dsd00000850* ID_MODEL_FROM_DATABASE=G96M [GeForce GT 130M] (GeForce GT 240M LE) pci:v000010DEd00000653* ID_MODEL_FROM_DATABASE=G96M [GeForce GT 120M] pci:v000010DEd00000654* ID_MODEL_FROM_DATABASE=G96M [GeForce GT 220M] pci:v000010DEd00000654sv00001043sd000014A2* ID_MODEL_FROM_DATABASE=G96M [GeForce GT 220M] (GeForce GT 320M) pci:v000010DEd00000654sv00001043sd000014D2* ID_MODEL_FROM_DATABASE=G96M [GeForce GT 220M] (GeForce GT 320M) pci:v000010DEd00000655* ID_MODEL_FROM_DATABASE=G96 [GeForce GT 120] pci:v000010DEd00000656* ID_MODEL_FROM_DATABASE=G96 [GeForce 9650 S] pci:v000010DEd00000658* ID_MODEL_FROM_DATABASE=G96GL [Quadro FX 380] pci:v000010DEd00000659* ID_MODEL_FROM_DATABASE=G96GL [Quadro FX 580] pci:v000010DEd0000065A* ID_MODEL_FROM_DATABASE=G96GLM [Quadro FX 1700M] pci:v000010DEd0000065B* ID_MODEL_FROM_DATABASE=G96 [GeForce 9400 GT] pci:v000010DEd0000065C* ID_MODEL_FROM_DATABASE=G96GLM [Quadro FX 770M] pci:v000010DEd0000065D* ID_MODEL_FROM_DATABASE=G96 [GeForce 9500 GA / 9600 GT / GTS 250] pci:v000010DEd0000065F* ID_MODEL_FROM_DATABASE=G96 [GeForce G210] pci:v000010DEd000006C0* ID_MODEL_FROM_DATABASE=GF100 [GeForce GTX 480] pci:v000010DEd000006C4* ID_MODEL_FROM_DATABASE=GF100 [GeForce GTX 465] pci:v000010DEd000006CA* ID_MODEL_FROM_DATABASE=GF100M [GeForce GTX 480M] pci:v000010DEd000006CB* ID_MODEL_FROM_DATABASE=GF100 [GeForce GTX 480] pci:v000010DEd000006CD* ID_MODEL_FROM_DATABASE=GF100 [GeForce GTX 470] pci:v000010DEd000006D1* ID_MODEL_FROM_DATABASE=GF100GL [Tesla C2050 / C2070] pci:v000010DEd000006D1sv000010DEsd00000771* ID_MODEL_FROM_DATABASE=GF100GL [Tesla C2050 / C2070] (Tesla C2050) pci:v000010DEd000006D1sv000010DEsd00000772* ID_MODEL_FROM_DATABASE=GF100GL [Tesla C2050 / C2070] (Tesla C2070) pci:v000010DEd000006D2* ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070] pci:v000010DEd000006D2sv000010DEsd00000774* ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070] (Tesla M2070) pci:v000010DEd000006D2sv000010DEsd00000830* ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070] (Tesla M2070) pci:v000010DEd000006D2sv000010DEsd00000842* ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070] (Tesla M2070) pci:v000010DEd000006D2sv000010DEsd0000088F* ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070] (Tesla X2070) pci:v000010DEd000006D2sv000010DEsd00000908* ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070] (Tesla M2070) pci:v000010DEd000006D8* ID_MODEL_FROM_DATABASE=GF100GL [Quadro 6000] pci:v000010DEd000006D9* ID_MODEL_FROM_DATABASE=GF100GL [Quadro 5000] pci:v000010DEd000006DA* ID_MODEL_FROM_DATABASE=GF100GLM [Quadro 5000M] pci:v000010DEd000006DC* ID_MODEL_FROM_DATABASE=GF100GL [Quadro 6000] pci:v000010DEd000006DD* ID_MODEL_FROM_DATABASE=GF100GL [Quadro 4000] pci:v000010DEd000006DE* ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] pci:v000010DEd000006DEsv000010DEsd00000773* ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla S2050) pci:v000010DEd000006DEsv000010DEsd0000082F* ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla M2050) pci:v000010DEd000006DEsv000010DEsd00000840* ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla X2070) pci:v000010DEd000006DEsv000010DEsd00000842* ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla M2050) pci:v000010DEd000006DEsv000010DEsd00000846* ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla M2050) pci:v000010DEd000006DEsv000010DEsd00000866* ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla M2050) pci:v000010DEd000006DEsv000010DEsd00000907* ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla M2050) pci:v000010DEd000006DEsv000010DEsd0000091E* ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla M2050) pci:v000010DEd000006DF* ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070-Q] pci:v000010DEd000006DFsv000010DEsd0000084D* ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070-Q] (Tesla M2070-Q) pci:v000010DEd000006DFsv000010DEsd0000087F* ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070-Q] (Tesla M2070-Q) pci:v000010DEd000006E0* ID_MODEL_FROM_DATABASE=G98 [GeForce 9300 GE] pci:v000010DEd000006E0sv0000107Dsd00005A96* ID_MODEL_FROM_DATABASE=G98 [GeForce 9300 GE] (Geforce 9300GE) pci:v000010DEd000006E1* ID_MODEL_FROM_DATABASE=G98 [GeForce 9300 GS] pci:v000010DEd000006E2* ID_MODEL_FROM_DATABASE=G98 [GeForce 8400] pci:v000010DEd000006E3* ID_MODEL_FROM_DATABASE=G98 [GeForce 8300 GS] pci:v000010DEd000006E4* ID_MODEL_FROM_DATABASE=G98 [GeForce 8400 GS Rev. 2] pci:v000010DEd000006E4sv00001458sd00003475* ID_MODEL_FROM_DATABASE=G98 [GeForce 8400 GS Rev. 2] (GV-NX84S256HE [GeForce 8400 GS]) pci:v000010DEd000006E5* ID_MODEL_FROM_DATABASE=G98M [GeForce 9300M GS] pci:v000010DEd000006E6* ID_MODEL_FROM_DATABASE=G98 [GeForce G 100] pci:v000010DEd000006E7* ID_MODEL_FROM_DATABASE=G98 [GeForce 9300 SE] pci:v000010DEd000006E8* ID_MODEL_FROM_DATABASE=G98M [GeForce 9200M GS] pci:v000010DEd000006E8sv0000103Csd0000360B* ID_MODEL_FROM_DATABASE=G98M [GeForce 9200M GS] (GeForce 9200M GE) pci:v000010DEd000006E9* ID_MODEL_FROM_DATABASE=G98M [GeForce 9300M GS] pci:v000010DEd000006E9sv00001043sd000019B2* ID_MODEL_FROM_DATABASE=G98M [GeForce 9300M GS] (U6V laptop) pci:v000010DEd000006EA* ID_MODEL_FROM_DATABASE=G98M [Quadro NVS 150M] pci:v000010DEd000006EB* ID_MODEL_FROM_DATABASE=G98M [Quadro NVS 160M] pci:v000010DEd000006EC* ID_MODEL_FROM_DATABASE=G98M [GeForce G 105M] pci:v000010DEd000006ED* ID_MODEL_FROM_DATABASE=G98 [GeForce 9600 GT / 9800 GT] pci:v000010DEd000006EE* ID_MODEL_FROM_DATABASE=G98 [GeForce 9600 GT / 9800 GT] pci:v000010DEd000006EF* ID_MODEL_FROM_DATABASE=G98M [GeForce G 103M] pci:v000010DEd000006F1* ID_MODEL_FROM_DATABASE=G98M [GeForce G 105M] pci:v000010DEd000006F8* ID_MODEL_FROM_DATABASE=G98 [Quadro NVS 420] pci:v000010DEd000006F9* ID_MODEL_FROM_DATABASE=G98GL [Quadro FX 370 LP] pci:v000010DEd000006FA* ID_MODEL_FROM_DATABASE=G98 [Quadro NVS 450] pci:v000010DEd000006FB* ID_MODEL_FROM_DATABASE=G98GLM [Quadro FX 370M] pci:v000010DEd000006FD* ID_MODEL_FROM_DATABASE=G98 [Quadro NVS 295] pci:v000010DEd000006FF* ID_MODEL_FROM_DATABASE=G98 [HICx16 + Graphics] pci:v000010DEd000006FFsv000010DEsd00000711* ID_MODEL_FROM_DATABASE=G98 [HICx16 + Graphics] (HICx8 + Graphics) pci:v000010DEd00000751* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller pci:v000010DEd00000751sv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (Pavilion p6310f) pci:v000010DEd00000751sv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (M3N72-D) pci:v000010DEd00000751sv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (K9N2GM-FIH) pci:v000010DEd00000751sv00001849sd00000751* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (K10N78FullHD-hSLI R3.0 Memory Controller) pci:v000010DEd00000752* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SMBus pci:v000010DEd00000752sv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SMBus (Pavilion p6310f) pci:v000010DEd00000752sv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SMBus (M3N72-D) pci:v000010DEd00000752sv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SMBus (K9N2GM-FIH) pci:v000010DEd00000752sv00001849sd00000752* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SMBus (K10N78FullHD-hSLI R3.0 SMBus) pci:v000010DEd00000753* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Co-Processor pci:v000010DEd00000753sv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Co-Processor (Pavilion p6310f) pci:v000010DEd00000753sv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Co-Processor (M3N72-D) pci:v000010DEd00000753sv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Co-Processor (K9N2GM-FIH) pci:v000010DEd00000753sv00001849sd00000753* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Co-Processor (K10N78FullHD-hSLI R3.0 Co-Processor) pci:v000010DEd00000754* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller pci:v000010DEd00000754sv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (Pavilion p6310f) pci:v000010DEd00000754sv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (M3N72-D) pci:v000010DEd00000754sv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (K9N2GM-FIH) pci:v000010DEd00000754sv00001849sd00000754* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (K10N78FullHD-hSLI R3.0 Memory Controller) pci:v000010DEd00000759* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] IDE pci:v000010DEd00000759sv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] IDE (M3N72-D) pci:v000010DEd00000759sv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] IDE (K9N2GM-FIH) pci:v000010DEd00000759sv00001849sd00000759* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] IDE (K10N78FullHD-hSLI R3.0 IDE) pci:v000010DEd0000075A* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge pci:v000010DEd0000075Asv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (Pavilion p6310f) pci:v000010DEd0000075Asv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (M3N72-D) pci:v000010DEd0000075Asv00001849sd0000075A* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (K10N78FullHD-hSLI R3.0 PCI Bridge) pci:v000010DEd0000075B* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge pci:v000010DEd0000075Bsv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (Pavilion p6310f) pci:v000010DEd0000075Bsv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (M3N72-D) pci:v000010DEd0000075Bsv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (K9N2GM-FIH) pci:v000010DEd0000075Bsv00001849sd0000075B* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (K10N78FullHD-hSLI R3.0 PCI Express Bridge) pci:v000010DEd0000075C* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] LPC Bridge pci:v000010DEd0000075Csv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] LPC Bridge (Pavilion p6310f) pci:v000010DEd0000075Csv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] LPC Bridge (K9N2GM-FIH) pci:v000010DEd0000075Csv00001849sd0000075C* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] LPC Bridge (K10N78FullHD-hSLI R3.0 LPC Bridge) pci:v000010DEd0000075D* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] LPC Bridge pci:v000010DEd0000075Dsv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] LPC Bridge (M3N72-D) pci:v000010DEd00000760* ID_MODEL_FROM_DATABASE=MCP77 Ethernet pci:v000010DEd00000760sv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP77 Ethernet (Pavilion p6310f) pci:v000010DEd00000760sv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP77 Ethernet (M3N72-D) pci:v000010DEd00000760sv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP77 Ethernet (K9N2GM-FIH) pci:v000010DEd00000760sv00001849sd00000760* ID_MODEL_FROM_DATABASE=MCP77 Ethernet (K10N78FullHD-hSLI R3.0 Ethernet) pci:v000010DEd00000761* ID_MODEL_FROM_DATABASE=MCP77 Ethernet pci:v000010DEd00000762* ID_MODEL_FROM_DATABASE=MCP77 Ethernet pci:v000010DEd00000763* ID_MODEL_FROM_DATABASE=MCP77 Ethernet pci:v000010DEd00000774* ID_MODEL_FROM_DATABASE=MCP72XE/MCP72P/MCP78U/MCP78S High Definition Audio pci:v000010DEd00000774sv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP72XE/MCP72P/MCP78U/MCP78S High Definition Audio (Pavilion p6310f) pci:v000010DEd00000774sv00001043sd000082FE* ID_MODEL_FROM_DATABASE=MCP72XE/MCP72P/MCP78U/MCP78S High Definition Audio (M3N72-D) pci:v000010DEd00000774sv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP72XE/MCP72P/MCP78U/MCP78S High Definition Audio (K9N2GM-FIH) pci:v000010DEd00000774sv00001849sd00003662* ID_MODEL_FROM_DATABASE=MCP72XE/MCP72P/MCP78U/MCP78S High Definition Audio (K10N78FullHD-hSLI R3.0 High Definition Audio) pci:v000010DEd00000778* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge pci:v000010DEd00000778sv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (Pavilion p6310f) pci:v000010DEd00000778sv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (M3N72-D) pci:v000010DEd00000778sv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (K9N2GM-FIH) pci:v000010DEd00000778sv00001849sd00000778* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (K10N78FullHD-hSLI R3.0 PCI Express Bridge) pci:v000010DEd0000077A* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge pci:v000010DEd0000077Asv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (Pavilion p6310f) pci:v000010DEd0000077Asv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (M3N72-D) pci:v000010DEd0000077Asv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (K9N2GM-FIH) pci:v000010DEd0000077Asv00001849sd0000077A* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (K10N78FullHD-hSLI R3.0 PCI Bridge) pci:v000010DEd0000077B* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller pci:v000010DEd0000077Bsv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (Pavilion p6310f) pci:v000010DEd0000077Bsv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (M3N72-D) pci:v000010DEd0000077Bsv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (K9N2GM-FIH) pci:v000010DEd0000077Bsv00001849sd0000077B* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (K10N78FullHD-hSLI R3.0 OHCI USB 1.1 Controller) pci:v000010DEd0000077C* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller pci:v000010DEd0000077Csv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (Pavilion p6310f) pci:v000010DEd0000077Csv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (M3N72-D) pci:v000010DEd0000077Csv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (K9N2GM-FIH) pci:v000010DEd0000077Csv00001849sd0000077C* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (K10N78FullHD-hSLI R3.0 EHCI USB 2.0 Controller) pci:v000010DEd0000077D* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller pci:v000010DEd0000077Dsv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (Pavilion p6310f) pci:v000010DEd0000077Dsv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (M3N72-D) pci:v000010DEd0000077Dsv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (K9N2GM-FIH) pci:v000010DEd0000077Dsv00001849sd0000077D* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (K10N78FullHD-hSLI R3.0 OHCI USB 1.1 Controller) pci:v000010DEd0000077E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller pci:v000010DEd0000077Esv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (Pavilion p6310f) pci:v000010DEd0000077Esv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (M3N72-D) pci:v000010DEd0000077Esv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (K9N2GM-FIH) pci:v000010DEd0000077Esv00001849sd0000077E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (K10N78FullHD-hSLI R3.0 EHCI USB 2.0 Controller) pci:v000010DEd000007C0* ID_MODEL_FROM_DATABASE=MCP73 Host Bridge pci:v000010DEd000007C0sv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=MCP73 Host Bridge (JW-IN7150-HD) pci:v000010DEd000007C1* ID_MODEL_FROM_DATABASE=MCP73 Host Bridge pci:v000010DEd000007C1sv00001019sd0000297A* ID_MODEL_FROM_DATABASE=MCP73 Host Bridge (MCP73PVT-SM) pci:v000010DEd000007C2* ID_MODEL_FROM_DATABASE=MCP73 Host Bridge pci:v000010DEd000007C3* ID_MODEL_FROM_DATABASE=MCP73 Host Bridge pci:v000010DEd000007C3sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=MCP73 Host Bridge (I-N73V motherboard) pci:v000010DEd000007C5* ID_MODEL_FROM_DATABASE=MCP73 Host Bridge pci:v000010DEd000007C8* ID_MODEL_FROM_DATABASE=MCP73 Memory Controller pci:v000010DEd000007C8sv00001019sd0000297A* ID_MODEL_FROM_DATABASE=MCP73 Memory Controller (MCP73PVT-SM) pci:v000010DEd000007C8sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=MCP73 Memory Controller (I-N73V motherboard) pci:v000010DEd000007C8sv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=MCP73 Memory Controller (JW-IN7150-HD) pci:v000010DEd000007CB* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller pci:v000010DEd000007CBsv00001019sd0000297A* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) pci:v000010DEd000007CBsv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) pci:v000010DEd000007CBsv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) pci:v000010DEd000007CD* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller pci:v000010DEd000007CDsv00001019sd0000297A* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) pci:v000010DEd000007CDsv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) pci:v000010DEd000007CDsv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) pci:v000010DEd000007CE* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller pci:v000010DEd000007CEsv00001019sd0000297A* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) pci:v000010DEd000007CEsv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) pci:v000010DEd000007CEsv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) pci:v000010DEd000007CF* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller pci:v000010DEd000007CFsv00001019sd0000297A* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) pci:v000010DEd000007CFsv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) pci:v000010DEd000007CFsv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) pci:v000010DEd000007D0* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller pci:v000010DEd000007D0sv00001019sd0000297A* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) pci:v000010DEd000007D0sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) pci:v000010DEd000007D0sv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) pci:v000010DEd000007D1* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller pci:v000010DEd000007D1sv00001019sd0000297A* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) pci:v000010DEd000007D1sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) pci:v000010DEd000007D1sv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) pci:v000010DEd000007D2* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller pci:v000010DEd000007D2sv00001019sd0000297A* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) pci:v000010DEd000007D2sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) pci:v000010DEd000007D2sv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) pci:v000010DEd000007D3* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller pci:v000010DEd000007D3sv00001019sd0000297A* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) pci:v000010DEd000007D3sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) pci:v000010DEd000007D3sv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) pci:v000010DEd000007D6* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller pci:v000010DEd000007D6sv00001019sd0000297A* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) pci:v000010DEd000007D6sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) pci:v000010DEd000007D6sv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) pci:v000010DEd000007D7* ID_MODEL_FROM_DATABASE=MCP73 LPC Bridge pci:v000010DEd000007D7sv00001019sd0000297A* ID_MODEL_FROM_DATABASE=MCP73 LPC Bridge (MCP73PVT-SM) pci:v000010DEd000007D7sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=MCP73 LPC Bridge (I-N73V motherboard) pci:v000010DEd000007D7sv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=MCP73 LPC Bridge (JW-IN7150-HD) pci:v000010DEd000007D8* ID_MODEL_FROM_DATABASE=MCP73 SMBus pci:v000010DEd000007D8sv00001019sd0000297A* ID_MODEL_FROM_DATABASE=MCP73 SMBus (MCP73PVT-SM) pci:v000010DEd000007D8sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=MCP73 SMBus (I-N73V motherboard) pci:v000010DEd000007D8sv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=MCP73 SMBus (JW-IN7150-HD) pci:v000010DEd000007D9* ID_MODEL_FROM_DATABASE=MCP73 Memory Controller pci:v000010DEd000007D9sv00001019sd0000297A* ID_MODEL_FROM_DATABASE=MCP73 Memory Controller (MCP73PVT-SM) pci:v000010DEd000007D9sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=MCP73 Memory Controller (I-N73V motherboard) pci:v000010DEd000007D9sv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=MCP73 Memory Controller (JW-IN7150-HD) pci:v000010DEd000007DA* ID_MODEL_FROM_DATABASE=MCP73 Co-processor pci:v000010DEd000007DAsv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=MCP73 Co-processor (JW-IN7150-HD) pci:v000010DEd000007DC* ID_MODEL_FROM_DATABASE=MCP73 Ethernet pci:v000010DEd000007DCsv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=MCP73 Ethernet (I-N73V motherboard) pci:v000010DEd000007DD* ID_MODEL_FROM_DATABASE=MCP73 Ethernet pci:v000010DEd000007DE* ID_MODEL_FROM_DATABASE=MCP73 Ethernet pci:v000010DEd000007DF* ID_MODEL_FROM_DATABASE=MCP73 Ethernet pci:v000010DEd000007E0* ID_MODEL_FROM_DATABASE=C73 [GeForce 7150 / nForce 630i] pci:v000010DEd000007E0sv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=C73 [GeForce 7150 / nForce 630i] (JW-IN7150-HD) pci:v000010DEd000007E1* ID_MODEL_FROM_DATABASE=C73 [GeForce 7100 / nForce 630i] pci:v000010DEd000007E1sv00001019sd0000297A* ID_MODEL_FROM_DATABASE=C73 [GeForce 7100 / nForce 630i] (MCP73PVT-SM) pci:v000010DEd000007E2* ID_MODEL_FROM_DATABASE=C73 [GeForce 7050 / nForce 630i] pci:v000010DEd000007E3* ID_MODEL_FROM_DATABASE=C73 [GeForce 7050 / nForce 610i] pci:v000010DEd000007E3sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=C73 [GeForce 7050 / nForce 610i] (I-N73V motherboard) pci:v000010DEd000007E5* ID_MODEL_FROM_DATABASE=C73 [GeForce 7100 / nForce 620i] pci:v000010DEd000007F0* ID_MODEL_FROM_DATABASE=MCP73 SATA Controller (IDE mode) pci:v000010DEd000007F0sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=MCP73 SATA Controller (IDE mode) (I-N73V motherboard) pci:v000010DEd000007F4* ID_MODEL_FROM_DATABASE=GeForce 7100/nForce 630i SATA pci:v000010DEd000007F4sv00001019sd0000297A* ID_MODEL_FROM_DATABASE=GeForce 7100/nForce 630i SATA (MCP73PVT-SM) pci:v000010DEd000007F4sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=GeForce 7100/nForce 630i SATA (I-N73V motherboard) pci:v000010DEd000007F8* ID_MODEL_FROM_DATABASE=MCP73 SATA RAID Controller pci:v000010DEd000007F8sv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=MCP73 SATA RAID Controller (I-N73V motherboard) pci:v000010DEd000007FC* ID_MODEL_FROM_DATABASE=MCP73 High Definition Audio pci:v000010DEd000007FCsv00001019sd0000297A* ID_MODEL_FROM_DATABASE=MCP73 High Definition Audio (MCP73PVT-SM) pci:v000010DEd000007FCsv000010DEsd000007FC* ID_MODEL_FROM_DATABASE=MCP73 High Definition Audio pci:v000010DEd000007FCsv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=MCP73 High Definition Audio (I-N73V motherboard) pci:v000010DEd000007FE* ID_MODEL_FROM_DATABASE=MCP73 OHCI USB 1.1 Controller pci:v000010DEd000007FEsv00001019sd0000297A* ID_MODEL_FROM_DATABASE=MCP73 OHCI USB 1.1 Controller (MCP73PVT-SM) pci:v000010DEd000007FEsv0000147Bsd00001C3E* ID_MODEL_FROM_DATABASE=MCP73 OHCI USB 1.1 Controller (I-N73V motherboard) pci:v000010DEd000007FEsv00001AFAsd00007150* ID_MODEL_FROM_DATABASE=MCP73 OHCI USB 1.1 Controller (JW-IN7150-HD) pci:v000010DEd00000840* ID_MODEL_FROM_DATABASE=C77 [GeForce 8200M] pci:v000010DEd00000844* ID_MODEL_FROM_DATABASE=C77 [GeForce 9100M G] pci:v000010DEd00000845* ID_MODEL_FROM_DATABASE=C77 [GeForce 8200M G] pci:v000010DEd00000846* ID_MODEL_FROM_DATABASE=C77 [GeForce 9200] pci:v000010DEd00000847* ID_MODEL_FROM_DATABASE=C78 [GeForce 9100] pci:v000010DEd00000847sv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=C78 [GeForce 9100] (Pavilion p6310f) pci:v000010DEd00000848* ID_MODEL_FROM_DATABASE=C77 [GeForce 8300] pci:v000010DEd00000849* ID_MODEL_FROM_DATABASE=C77 [GeForce 8200] pci:v000010DEd00000849sv00001462sd00007508* ID_MODEL_FROM_DATABASE=C77 [GeForce 8200] (K9N2GM-FIH) pci:v000010DEd00000849sv00001849sd00000849* ID_MODEL_FROM_DATABASE=C77 [GeForce 8200] (K10N78FullHD-hSLI R3.0 GeForce 8200) pci:v000010DEd0000084A* ID_MODEL_FROM_DATABASE=C77 [nForce 730a] pci:v000010DEd0000084B* ID_MODEL_FROM_DATABASE=C77 [GeForce 8200] pci:v000010DEd0000084C* ID_MODEL_FROM_DATABASE=C77 [nForce 780a/980a SLI] pci:v000010DEd0000084D* ID_MODEL_FROM_DATABASE=C77 [nForce 750a SLI] pci:v000010DEd0000084Dsv00001043sd000082E8* ID_MODEL_FROM_DATABASE=C77 [nForce 750a SLI] (M3N72-D mGPU) pci:v000010DEd0000084F* ID_MODEL_FROM_DATABASE=C77 [GeForce 8100 / nForce 720a] pci:v000010DEd00000860* ID_MODEL_FROM_DATABASE=C79 [GeForce 9300] pci:v000010DEd00000861* ID_MODEL_FROM_DATABASE=C79 [GeForce 9400] pci:v000010DEd00000862* ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M G] pci:v000010DEd00000863* ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M] pci:v000010DEd00000863sv0000106Bsd000000AA* ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M] (MacBook5,1) pci:v000010DEd00000864* ID_MODEL_FROM_DATABASE=C79 [GeForce 9300] pci:v000010DEd00000865* ID_MODEL_FROM_DATABASE=C79 [GeForce 9300/ION] pci:v000010DEd00000866* ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M G] pci:v000010DEd00000866sv0000106Bsd000000B1* ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M G] (GeForce 9400M) pci:v000010DEd00000867* ID_MODEL_FROM_DATABASE=C79 [GeForce 9400] pci:v000010DEd00000867sv0000106Bsd000000AD* ID_MODEL_FROM_DATABASE=C79 [GeForce 9400] (iMac 9,1) pci:v000010DEd00000868* ID_MODEL_FROM_DATABASE=C79 [nForce 760i SLI] pci:v000010DEd00000869* ID_MODEL_FROM_DATABASE=MCP7A [GeForce 9400] pci:v000010DEd0000086A* ID_MODEL_FROM_DATABASE=C79 [GeForce 9400] pci:v000010DEd0000086C* ID_MODEL_FROM_DATABASE=C79 [GeForce 9300 / nForce 730i] pci:v000010DEd0000086D* ID_MODEL_FROM_DATABASE=C79 [GeForce 9200] pci:v000010DEd0000086E* ID_MODEL_FROM_DATABASE=C79 [GeForce 9100M G] pci:v000010DEd0000086F* ID_MODEL_FROM_DATABASE=MCP79 [GeForce 8200M G] pci:v000010DEd00000870* ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M] pci:v000010DEd00000871* ID_MODEL_FROM_DATABASE=C79 [GeForce 9200] pci:v000010DEd00000872* ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] pci:v000010DEd00000872sv00001043sd000019B4* ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G102M) pci:v000010DEd00000872sv00001043sd00001AA2* ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G102M) pci:v000010DEd00000872sv00001043sd00001C02* ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G102M) pci:v000010DEd00000872sv00001043sd00001C42* ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G205M) pci:v000010DEd00000873* ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] pci:v000010DEd00000873sv00001043sd000019B4* ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G102M) pci:v000010DEd00000873sv00001043sd00001C12* ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G102M) pci:v000010DEd00000873sv00001043sd00001C52* ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G205M) pci:v000010DEd00000874* ID_MODEL_FROM_DATABASE=C79 [ION] pci:v000010DEd00000876* ID_MODEL_FROM_DATABASE=ION VGA [GeForce 9400M] pci:v000010DEd0000087A* ID_MODEL_FROM_DATABASE=C79 [GeForce 9400] pci:v000010DEd0000087D* ID_MODEL_FROM_DATABASE=ION VGA pci:v000010DEd0000087Dsv000019DAsd0000A123* ID_MODEL_FROM_DATABASE=ION VGA (IONITX-F-E) pci:v000010DEd0000087E* ID_MODEL_FROM_DATABASE=ION LE VGA pci:v000010DEd0000087F* ID_MODEL_FROM_DATABASE=ION LE VGA pci:v000010DEd000008A0* ID_MODEL_FROM_DATABASE=MCP89 [GeForce 320M] pci:v000010DEd000008A2* ID_MODEL_FROM_DATABASE=MCP89 [GeForce 320M] pci:v000010DEd000008A3* ID_MODEL_FROM_DATABASE=MCP89 [GeForce 320M] pci:v000010DEd000008A4* ID_MODEL_FROM_DATABASE=MCP89 [GeForce 320M] pci:v000010DEd000008A5* ID_MODEL_FROM_DATABASE=MCP89 [GeForce 320M] pci:v000010DEd00000A20* ID_MODEL_FROM_DATABASE=GT216 [GeForce GT 220] pci:v000010DEd00000A20sv00001043sd00008311* ID_MODEL_FROM_DATABASE=GT216 [GeForce GT 220] (ENGT220/DI/1GD3(LP)/V2) pci:v000010DEd00000A21* ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 330M] pci:v000010DEd00000A22* ID_MODEL_FROM_DATABASE=GT216 [GeForce 315] pci:v000010DEd00000A23* ID_MODEL_FROM_DATABASE=GT216 [GeForce 210] pci:v000010DEd00000A26* ID_MODEL_FROM_DATABASE=GT216 [GeForce 405] pci:v000010DEd00000A27* ID_MODEL_FROM_DATABASE=GT216 [GeForce 405] pci:v000010DEd00000A28* ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 230M] pci:v000010DEd00000A29* ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 330M] pci:v000010DEd00000A2A* ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 230M] pci:v000010DEd00000A2B* ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 330M] pci:v000010DEd00000A2C* ID_MODEL_FROM_DATABASE=GT216M [NVS 5100M] pci:v000010DEd00000A2D* ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 320M] pci:v000010DEd00000A30* ID_MODEL_FROM_DATABASE=GT216 [GeForce 505] pci:v000010DEd00000A32* ID_MODEL_FROM_DATABASE=GT216 [GeForce GT 415] pci:v000010DEd00000A34* ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 240M] pci:v000010DEd00000A35* ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 325M] pci:v000010DEd00000A38* ID_MODEL_FROM_DATABASE=GT216GL [Quadro 400] pci:v000010DEd00000A3C* ID_MODEL_FROM_DATABASE=GT216GLM [Quadro FX 880M] pci:v000010DEd00000A60* ID_MODEL_FROM_DATABASE=GT218 [GeForce G210] pci:v000010DEd00000A62* ID_MODEL_FROM_DATABASE=GT218 [GeForce 205] pci:v000010DEd00000A63* ID_MODEL_FROM_DATABASE=GT218 [GeForce 310] pci:v000010DEd00000A64* ID_MODEL_FROM_DATABASE=GT218 [ION] pci:v000010DEd00000A65* ID_MODEL_FROM_DATABASE=GT218 [GeForce 210] pci:v000010DEd00000A65sv00001043sd00008334* ID_MODEL_FROM_DATABASE=GT218 [GeForce 210] (EN210 SILENT) pci:v000010DEd00000A65sv00001462sd00008094* ID_MODEL_FROM_DATABASE=GT218 [GeForce 210] (N210 [Geforce 210] PCIe graphics adapter) pci:v000010DEd00000A66* ID_MODEL_FROM_DATABASE=GT218 [GeForce 310] pci:v000010DEd00000A67* ID_MODEL_FROM_DATABASE=GT218 [GeForce 315] pci:v000010DEd00000A68* ID_MODEL_FROM_DATABASE=GT218M [GeForce G 105M] pci:v000010DEd00000A69* ID_MODEL_FROM_DATABASE=GT218M [GeForce G 105M] pci:v000010DEd00000A6A* ID_MODEL_FROM_DATABASE=GT218M [NVS 2100M] pci:v000010DEd00000A6C* ID_MODEL_FROM_DATABASE=GT218M [NVS 3100M] pci:v000010DEd00000A6Csv00001028sd0000040B* ID_MODEL_FROM_DATABASE=GT218M [NVS 3100M] (Latitude E6510) pci:v000010DEd00000A6Csv000017AAsd00002142* ID_MODEL_FROM_DATABASE=GT218M [NVS 3100M] (ThinkPad T410) pci:v000010DEd00000A6E* ID_MODEL_FROM_DATABASE=GT218M [GeForce 305M] pci:v000010DEd00000A6F* ID_MODEL_FROM_DATABASE=GT218 [ION] pci:v000010DEd00000A70* ID_MODEL_FROM_DATABASE=GT218M [GeForce 310M] pci:v000010DEd00000A71* ID_MODEL_FROM_DATABASE=GT218M [GeForce 305M] pci:v000010DEd00000A72* ID_MODEL_FROM_DATABASE=GT218M [GeForce 310M] pci:v000010DEd00000A73* ID_MODEL_FROM_DATABASE=GT218M [GeForce 305M] pci:v000010DEd00000A74* ID_MODEL_FROM_DATABASE=GT218M [GeForce G210M] pci:v000010DEd00000A74sv00001B0Asd0000903A* ID_MODEL_FROM_DATABASE=GT218M [GeForce G210M] (GeForce G210) pci:v000010DEd00000A75* ID_MODEL_FROM_DATABASE=GT218M [GeForce 310M] pci:v000010DEd00000A76* ID_MODEL_FROM_DATABASE=GT218 [ION 2] pci:v000010DEd00000A78* ID_MODEL_FROM_DATABASE=GT218GL [Quadro FX 380 LP] pci:v000010DEd00000A7A* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] pci:v000010DEd00000A7Asv0000104Dsd0000907E* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FC50* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FC61* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FC71* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FC90* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FCC0* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FCD0* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FCE2* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FCF2* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FD16* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FD40* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FD50* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FD52* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FD61* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FD71* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FD92* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FD96* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FDD0* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FDD2* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001179sd0000FDFE* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv0000144Dsd0000C0A2* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv0000144Dsd0000C0B2* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv0000144Dsd0000C581* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv0000144Dsd0000C587* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv0000144Dsd0000C588* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv0000144Dsd0000C597* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv0000144Dsd0000C606* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001462sd0000AA51* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) pci:v000010DEd00000A7Asv00001462sd0000AA58* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) pci:v000010DEd00000A7Asv00001462sd0000AC71* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) pci:v000010DEd00000A7Asv00001462sd0000AC81* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001462sd0000AC82* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) pci:v000010DEd00000A7Asv00001462sd0000AE33* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) pci:v000010DEd00000A7Asv00001642sd00003980* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) pci:v000010DEd00000A7Asv000017AAsd00003950* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405M) pci:v000010DEd00000A7Asv000017AAsd0000397D* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405M) pci:v000010DEd00000A7Asv00001B0Asd00002091* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7Asv00001B0Asd000090B4* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) pci:v000010DEd00000A7Asv00001BFDsd00000003* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) pci:v000010DEd00000A7Asv00001BFDsd00008006* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) pci:v000010DEd00000A7Asv00001BFDsd00008007* ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) pci:v000010DEd00000A7B* ID_MODEL_FROM_DATABASE=GT218 [GeForce 505] pci:v000010DEd00000A7C* ID_MODEL_FROM_DATABASE=GT218GLM [Quadro FX 380M] pci:v000010DEd00000A80* ID_MODEL_FROM_DATABASE=MCP79 Host Bridge pci:v000010DEd00000A81* ID_MODEL_FROM_DATABASE=MCP79 Host Bridge pci:v000010DEd00000A82* ID_MODEL_FROM_DATABASE=MCP79 Host Bridge pci:v000010DEd00000A83* ID_MODEL_FROM_DATABASE=MCP79 Host Bridge pci:v000010DEd00000A84* ID_MODEL_FROM_DATABASE=MCP79 Host Bridge pci:v000010DEd00000A85* ID_MODEL_FROM_DATABASE=MCP79 Host Bridge pci:v000010DEd00000A86* ID_MODEL_FROM_DATABASE=MCP79 Host Bridge pci:v000010DEd00000A87* ID_MODEL_FROM_DATABASE=MCP79 Host Bridge pci:v000010DEd00000A88* ID_MODEL_FROM_DATABASE=MCP79 Memory Controller pci:v000010DEd00000A89* ID_MODEL_FROM_DATABASE=MCP79 Memory Controller pci:v000010DEd00000A98* ID_MODEL_FROM_DATABASE=MCP79 Memory Controller pci:v000010DEd00000A98sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 Memory Controller (iMac 9,1) pci:v000010DEd00000AA0* ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge pci:v000010DEd00000AA0sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge (Apple iMac 9,1) pci:v000010DEd00000AA2* ID_MODEL_FROM_DATABASE=MCP79 SMBus pci:v000010DEd00000AA2sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 SMBus (Apple iMac 9,1) pci:v000010DEd00000AA2sv000019DAsd0000A123* ID_MODEL_FROM_DATABASE=MCP79 SMBus (IONITX-F-E) pci:v000010DEd00000AA3* ID_MODEL_FROM_DATABASE=MCP79 Co-processor pci:v000010DEd00000AA3sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 Co-processor (Apple iMac 9,1) pci:v000010DEd00000AA3sv000019DAsd0000A123* ID_MODEL_FROM_DATABASE=MCP79 Co-processor (IONITX-F-E) pci:v000010DEd00000AA4* ID_MODEL_FROM_DATABASE=MCP79 Memory Controller pci:v000010DEd00000AA4sv000019DAsd0000A123* ID_MODEL_FROM_DATABASE=MCP79 Memory Controller (IONITX-F-E) pci:v000010DEd00000AA5* ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller pci:v000010DEd00000AA5sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller (Apple iMac 9,1) pci:v000010DEd00000AA5sv000019DAsd0000A123* ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller (IONITX-F-E) pci:v000010DEd00000AA6* ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller pci:v000010DEd00000AA6sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller (Apple iMac 9,1) pci:v000010DEd00000AA6sv000019DAsd0000A123* ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller (IONITX-F-E) pci:v000010DEd00000AA7* ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller pci:v000010DEd00000AA7sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller (Apple iMac 9,1) pci:v000010DEd00000AA7sv000019DAsd0000A123* ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller (IONITX-F-E) pci:v000010DEd00000AA8* ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller pci:v000010DEd00000AA9* ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller pci:v000010DEd00000AA9sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller (Apple iMac 9,1) pci:v000010DEd00000AA9sv000019DAsd0000A123* ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller (IONITX-F-E) pci:v000010DEd00000AAA* ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller pci:v000010DEd00000AAB* ID_MODEL_FROM_DATABASE=MCP79 PCI Bridge pci:v000010DEd00000AABsv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 PCI Bridge (Apple iMac 9,1) pci:v000010DEd00000AAC* ID_MODEL_FROM_DATABASE=MCP79 LPC Bridge pci:v000010DEd00000AAD* ID_MODEL_FROM_DATABASE=MCP79 LPC Bridge pci:v000010DEd00000AADsv000019DAsd0000A123* ID_MODEL_FROM_DATABASE=MCP79 LPC Bridge (IONITX-F-E) pci:v000010DEd00000AAE* ID_MODEL_FROM_DATABASE=MCP79 LPC Bridge pci:v000010DEd00000AAEsv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 LPC Bridge (Apple iMac 9,1) pci:v000010DEd00000AAF* ID_MODEL_FROM_DATABASE=MCP79 LPC Bridge pci:v000010DEd00000AB0* ID_MODEL_FROM_DATABASE=MCP79 Ethernet pci:v000010DEd00000AB0sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 Ethernet (Apple iMac 9,1) pci:v000010DEd00000AB0sv000019DAsd0000A123* ID_MODEL_FROM_DATABASE=MCP79 Ethernet (IONITX-F-E) pci:v000010DEd00000AB1* ID_MODEL_FROM_DATABASE=MCP79 Ethernet pci:v000010DEd00000AB2* ID_MODEL_FROM_DATABASE=MCP79 Ethernet pci:v000010DEd00000AB3* ID_MODEL_FROM_DATABASE=MCP79 Ethernet pci:v000010DEd00000AB4* ID_MODEL_FROM_DATABASE=MCP79 SATA Controller pci:v000010DEd00000AB4sv000019DAsd0000A123* ID_MODEL_FROM_DATABASE=MCP79 SATA Controller (IONITX-F-E) pci:v000010DEd00000AB5* ID_MODEL_FROM_DATABASE=MCP79 SATA Controller pci:v000010DEd00000AB6* ID_MODEL_FROM_DATABASE=MCP79 SATA Controller pci:v000010DEd00000AB7* ID_MODEL_FROM_DATABASE=MCP79 SATA Controller pci:v000010DEd00000AB8* ID_MODEL_FROM_DATABASE=MCP79 AHCI Controller pci:v000010DEd00000AB9* ID_MODEL_FROM_DATABASE=MCP79 AHCI Controller pci:v000010DEd00000AB9sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 AHCI Controller (Apple iMac 9,1) pci:v000010DEd00000ABA* ID_MODEL_FROM_DATABASE=MCP79 AHCI Controller pci:v000010DEd00000ABB* ID_MODEL_FROM_DATABASE=MCP79 AHCI Controller pci:v000010DEd00000ABC* ID_MODEL_FROM_DATABASE=MCP79 RAID Controller pci:v000010DEd00000ABD* ID_MODEL_FROM_DATABASE=MCP79 RAID Controller pci:v000010DEd00000ABE* ID_MODEL_FROM_DATABASE=MCP79 RAID Controller pci:v000010DEd00000ABF* ID_MODEL_FROM_DATABASE=MCP79 RAID Controller pci:v000010DEd00000AC0* ID_MODEL_FROM_DATABASE=MCP79 High Definition Audio pci:v000010DEd00000AC0sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 High Definition Audio (Apple iMac 9,1) pci:v000010DEd00000AC1* ID_MODEL_FROM_DATABASE=MCP79 High Definition Audio pci:v000010DEd00000AC2* ID_MODEL_FROM_DATABASE=MCP79 High Definition Audio pci:v000010DEd00000AC3* ID_MODEL_FROM_DATABASE=MCP79 High Definition Audio pci:v000010DEd00000AC4* ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge pci:v000010DEd00000AC4sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge (Apple iMac 9,1) pci:v000010DEd00000AC5* ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge pci:v000010DEd00000AC6* ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge pci:v000010DEd00000AC6sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge (Apple iMac 9,1) pci:v000010DEd00000AC7* ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge pci:v000010DEd00000AC7sv000010DEsd0000CB79* ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge (Apple iMac 9,1) pci:v000010DEd00000AC8* ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge pci:v000010DEd00000AD0* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SATA Controller (non-AHCI mode) pci:v000010DEd00000AD0sv00001462sd00007508* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SATA Controller (non-AHCI mode) (K9N2GM-FIH) pci:v000010DEd00000AD0sv00001849sd00000AD0* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SATA Controller (non-AHCI mode) (K10N78FullHD-hSLI R3.0 IDE) pci:v000010DEd00000AD4* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] AHCI Controller pci:v000010DEd00000AD4sv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] AHCI Controller (Pavilion p6310f) pci:v000010DEd00000AD4sv00001043sd000082E8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] AHCI Controller (M3N72-D) pci:v000010DEd00000AD4sv00001849sd00000AD4* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] AHCI Controller (K10N78FullHD-hSLI R3.0 AHCI Controller) pci:v000010DEd00000AD8* ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SATA Controller (RAID mode) pci:v000010DEd00000BE2* ID_MODEL_FROM_DATABASE=GT216 HDMI Audio Controller pci:v000010DEd00000BE2sv00001043sd00008311* ID_MODEL_FROM_DATABASE=GT216 HDMI Audio Controller (ENGT220/DI/1GD3(LP)/V2) pci:v000010DEd00000BE3* ID_MODEL_FROM_DATABASE=High Definition Audio Controller pci:v000010DEd00000BE3sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=High Definition Audio Controller (Latitude E6510) pci:v000010DEd00000BE3sv000010DEsd0000066D* ID_MODEL_FROM_DATABASE=High Definition Audio Controller (G98 [GeForce 8400GS]) pci:v000010DEd00000BE3sv00001462sd00008094* ID_MODEL_FROM_DATABASE=High Definition Audio Controller (N210 [Geforce 210] PCIe graphics adapter) pci:v000010DEd00000BE4* ID_MODEL_FROM_DATABASE=High Definition Audio Controller pci:v000010DEd00000BE5* ID_MODEL_FROM_DATABASE=GF100 High Definition Audio Controller pci:v000010DEd00000BE9* ID_MODEL_FROM_DATABASE=GF106 High Definition Audio Controller pci:v000010DEd00000BE9sv00001558sd00008687* ID_MODEL_FROM_DATABASE=GF106 High Definition Audio Controller (CLEVO/KAPOK W860CU) pci:v000010DEd00000BE9sv00003842sd00001452* ID_MODEL_FROM_DATABASE=GF106 High Definition Audio Controller (GeForce GTS 450) pci:v000010DEd00000BEA* ID_MODEL_FROM_DATABASE=GF108 High Definition Audio Controller pci:v000010DEd00000BEAsv00003842sd00001430* ID_MODEL_FROM_DATABASE=GF108 High Definition Audio Controller (GeForce GT 430) pci:v000010DEd00000BEB* ID_MODEL_FROM_DATABASE=GF104 High Definition Audio Controller pci:v000010DEd00000BEBsv00001462sd00002322* ID_MODEL_FROM_DATABASE=GF104 High Definition Audio Controller (N460GTX Cyclone 1GD5/OC) pci:v000010DEd00000BEE* ID_MODEL_FROM_DATABASE=GF116 High Definition Audio Controller pci:v000010DEd00000BF0* ID_MODEL_FROM_DATABASE=Tegra2 PCIe x4 Bridge pci:v000010DEd00000BF1* ID_MODEL_FROM_DATABASE=Tegra2 PCIe x2 Bridge pci:v000010DEd00000CA0* ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 330] pci:v000010DEd00000CA2* ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 320] pci:v000010DEd00000CA3* ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 240] pci:v000010DEd00000CA4* ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 340] pci:v000010DEd00000CA5* ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 220] pci:v000010DEd00000CA7* ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 330] pci:v000010DEd00000CA8* ID_MODEL_FROM_DATABASE=GT215M [GeForce GTS 260M] pci:v000010DEd00000CA9* ID_MODEL_FROM_DATABASE=GT215M [GeForce GTS 250M] pci:v000010DEd00000CAC* ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 220/315] pci:v000010DEd00000CAF* ID_MODEL_FROM_DATABASE=GT215M [GeForce GT 335M] pci:v000010DEd00000CB0* ID_MODEL_FROM_DATABASE=GT215M [GeForce GTS 350M] pci:v000010DEd00000CB1* ID_MODEL_FROM_DATABASE=GT215M [GeForce GTS 360M] pci:v000010DEd00000CBC* ID_MODEL_FROM_DATABASE=GT215GLM [Quadro FX 1800M] pci:v000010DEd00000D60* ID_MODEL_FROM_DATABASE=MCP89 HOST Bridge pci:v000010DEd00000D68* ID_MODEL_FROM_DATABASE=MCP89 Memory Controller pci:v000010DEd00000D69* ID_MODEL_FROM_DATABASE=MCP89 Memory Controller pci:v000010DEd00000D76* ID_MODEL_FROM_DATABASE=MCP89 PCI Express Bridge pci:v000010DEd00000D79* ID_MODEL_FROM_DATABASE=MCP89 SMBus pci:v000010DEd00000D7A* ID_MODEL_FROM_DATABASE=MCP89 Co-Processor pci:v000010DEd00000D7B* ID_MODEL_FROM_DATABASE=MCP89 Memory Controller pci:v000010DEd00000D7D* ID_MODEL_FROM_DATABASE=MCP89 Ethernet pci:v000010DEd00000D80* ID_MODEL_FROM_DATABASE=MCP89 LPC Bridge pci:v000010DEd00000D85* ID_MODEL_FROM_DATABASE=MCP89 SATA Controller pci:v000010DEd00000D88* ID_MODEL_FROM_DATABASE=MCP89 SATA Controller (AHCI mode) pci:v000010DEd00000D89* ID_MODEL_FROM_DATABASE=MCP89 SATA Controller (AHCI mode) pci:v000010DEd00000D8D* ID_MODEL_FROM_DATABASE=MCP89 SATA Controller (RAID mode) pci:v000010DEd00000D94* ID_MODEL_FROM_DATABASE=MCP89 High Definition Audio pci:v000010DEd00000D9C* ID_MODEL_FROM_DATABASE=MCP89 OHCI USB 1.1 Controller pci:v000010DEd00000D9D* ID_MODEL_FROM_DATABASE=MCP89 EHCI USB 2.0 Controller pci:v000010DEd00000DC0* ID_MODEL_FROM_DATABASE=GF106 [GeForce GT 440] pci:v000010DEd00000DC4* ID_MODEL_FROM_DATABASE=GF106 [GeForce GTS 450] pci:v000010DEd00000DC5* ID_MODEL_FROM_DATABASE=GF106 [GeForce GTS 450 OEM] pci:v000010DEd00000DC6* ID_MODEL_FROM_DATABASE=GF106 [GeForce GTS 450] pci:v000010DEd00000DCD* ID_MODEL_FROM_DATABASE=GF106M [GeForce GT 555M] pci:v000010DEd00000DCE* ID_MODEL_FROM_DATABASE=GF106M [GeForce GT 555M] pci:v000010DEd00000DD1* ID_MODEL_FROM_DATABASE=GF106M [GeForce GTX 460M] pci:v000010DEd00000DD1sv00001558sd00008687* ID_MODEL_FROM_DATABASE=GF106M [GeForce GTX 460M] (CLEVO/KAPOK W860CU) pci:v000010DEd00000DD2* ID_MODEL_FROM_DATABASE=GF106M [GeForce GT 445M] pci:v000010DEd00000DD3* ID_MODEL_FROM_DATABASE=GF106M [GeForce GT 435M] pci:v000010DEd00000DD6* ID_MODEL_FROM_DATABASE=GF106M [GeForce GT 550M] pci:v000010DEd00000DD8* ID_MODEL_FROM_DATABASE=GF106GL [Quadro 2000] pci:v000010DEd00000DD8sv000010DEsd00000914* ID_MODEL_FROM_DATABASE=GF106GL [Quadro 2000] (Quadro 2000D) pci:v000010DEd00000DDA* ID_MODEL_FROM_DATABASE=GF106GLM [Quadro 2000M] pci:v000010DEd00000DE0* ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 440] pci:v000010DEd00000DE1* ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 430] pci:v000010DEd00000DE1sv00003842sd00001430* ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 430] (GeForce GT 430) pci:v000010DEd00000DE2* ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 420] pci:v000010DEd00000DE3* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 635M] pci:v000010DEd00000DE4* ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 520] pci:v000010DEd00000DE5* ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 530] pci:v000010DEd00000DE7* ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 610] pci:v000010DEd00000DE8* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 620M] pci:v000010DEd00000DE9* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 630M] pci:v000010DEd00000DE9sv00001025sd00000692* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 630M] (GeForce GT 620M) pci:v000010DEd00000DE9sv00001025sd00000725* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 630M] (GeForce GT 620M) pci:v000010DEd00000DE9sv00001025sd00000728* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 630M] (GeForce GT 620M) pci:v000010DEd00000DE9sv00001025sd0000072B* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 630M] (GeForce GT 620M) pci:v000010DEd00000DE9sv00001025sd0000072E* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 630M] (GeForce GT 620M) pci:v000010DEd00000DE9sv00001025sd00000753* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 630M] (GeForce GT 620M) pci:v000010DEd00000DE9sv00001025sd00000754* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 630M] (GeForce GT 620M) pci:v000010DEd00000DE9sv000017AAsd00003977* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 630M] (GeForce GT 640M LE) pci:v000010DEd00000DE9sv00001B0Asd00002210* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 630M] (GeForce GT 635M) pci:v000010DEd00000DEA* ID_MODEL_FROM_DATABASE=GF108M [GeForce 610M] pci:v000010DEd00000DEAsv000017AAsd0000365A* ID_MODEL_FROM_DATABASE=GF108M [GeForce 610M] (GeForce 615) pci:v000010DEd00000DEAsv000017AAsd0000365B* ID_MODEL_FROM_DATABASE=GF108M [GeForce 610M] (GeForce 615) pci:v000010DEd00000DEAsv000017AAsd0000365E* ID_MODEL_FROM_DATABASE=GF108M [GeForce 610M] (GeForce 615) pci:v000010DEd00000DEAsv000017AAsd00003660* ID_MODEL_FROM_DATABASE=GF108M [GeForce 610M] (GeForce 615) pci:v000010DEd00000DEAsv000017AAsd0000366C* ID_MODEL_FROM_DATABASE=GF108M [GeForce 610M] (GeForce 615) pci:v000010DEd00000DEB* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 555M] pci:v000010DEd00000DEC* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 525M] pci:v000010DEd00000DED* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 520M] pci:v000010DEd00000DEE* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 415M] pci:v000010DEd00000DEF* ID_MODEL_FROM_DATABASE=GF108M [NVS 5400M] pci:v000010DEd00000DF0* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 425M] pci:v000010DEd00000DF1* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 420M] pci:v000010DEd00000DF2* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 435M] pci:v000010DEd00000DF3* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 420M] pci:v000010DEd00000DF4* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 540M] pci:v000010DEd00000DF4sv0000152Dsd00000952* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 540M] (GeForce GT 630M) pci:v000010DEd00000DF4sv0000152Dsd00000953* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 540M] (GeForce GT 630M) pci:v000010DEd00000DF5* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 525M] pci:v000010DEd00000DF6* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 550M] pci:v000010DEd00000DF7* ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 520M] pci:v000010DEd00000DF8* ID_MODEL_FROM_DATABASE=GF108GL [Quadro 600] pci:v000010DEd00000DF9* ID_MODEL_FROM_DATABASE=GF108GLM [Quadro 500M] pci:v000010DEd00000DFA* ID_MODEL_FROM_DATABASE=GF108GLM [Quadro 1000M] pci:v000010DEd00000DFC* ID_MODEL_FROM_DATABASE=GF108GLM [NVS 5200M] pci:v000010DEd00000E08* ID_MODEL_FROM_DATABASE=GF119 HDMI Audio Controller pci:v000010DEd00000E08sv000010B0sd0000104A* ID_MODEL_FROM_DATABASE=GF119 HDMI Audio Controller (Gainward GeForce GT 610) pci:v000010DEd00000E09* ID_MODEL_FROM_DATABASE=GF110 High Definition Audio Controller pci:v000010DEd00000E0A* ID_MODEL_FROM_DATABASE=GK104 HDMI Audio Controller pci:v000010DEd00000E0B* ID_MODEL_FROM_DATABASE=GK106 HDMI Audio Controller pci:v000010DEd00000E0C* ID_MODEL_FROM_DATABASE=GF114 HDMI Audio Controller pci:v000010DEd00000E0F* ID_MODEL_FROM_DATABASE=GK208 HDMI/DP Audio Controller pci:v000010DEd00000E12* ID_MODEL_FROM_DATABASE=TegraK1 PCIe x4 Bridge pci:v000010DEd00000E13* ID_MODEL_FROM_DATABASE=TegraK1 PCIe x1 Bridge pci:v000010DEd00000E1A* ID_MODEL_FROM_DATABASE=GK110 HDMI Audio pci:v000010DEd00000E1B* ID_MODEL_FROM_DATABASE=GK107 HDMI Audio Controller pci:v000010DEd00000E1Bsv0000103Csd0000197B* ID_MODEL_FROM_DATABASE=GK107 HDMI Audio Controller (ZBook 15) pci:v000010DEd00000E1Bsv00001043sd00008428* ID_MODEL_FROM_DATABASE=GK107 HDMI Audio Controller (GTX650-DC-1GD5) pci:v000010DEd00000E1C* ID_MODEL_FROM_DATABASE=Tegra3+ PCIe x4 Bridge pci:v000010DEd00000E1D* ID_MODEL_FROM_DATABASE=Tegra3+ PCIe x2 Bridge pci:v000010DEd00000E22* ID_MODEL_FROM_DATABASE=GF104 [GeForce GTX 460] pci:v000010DEd00000E22sv00001462sd00002322* ID_MODEL_FROM_DATABASE=GF104 [GeForce GTX 460] (N460GTX Cyclone 1GD5/OC) pci:v000010DEd00000E23* ID_MODEL_FROM_DATABASE=GF104 [GeForce GTX 460 SE] pci:v000010DEd00000E24* ID_MODEL_FROM_DATABASE=GF104 [GeForce GTX 460 OEM] pci:v000010DEd00000E30* ID_MODEL_FROM_DATABASE=GF104M [GeForce GTX 470M] pci:v000010DEd00000E31* ID_MODEL_FROM_DATABASE=GF104M [GeForce GTX 485M] pci:v000010DEd00000E3A* ID_MODEL_FROM_DATABASE=GF104GLM [Quadro 3000M] pci:v000010DEd00000E3B* ID_MODEL_FROM_DATABASE=GF104GLM [Quadro 4000M] pci:v000010DEd00000F00* ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 630] pci:v000010DEd00000F01* ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 620] pci:v000010DEd00000F02* ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 730] pci:v000010DEd00000F06* ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 730] pci:v000010DEd00000FBB* ID_MODEL_FROM_DATABASE=GM204 High Definition Audio Controller pci:v000010DEd00000FC0* ID_MODEL_FROM_DATABASE=GK107 [GeForce GT 640 OEM] pci:v000010DEd00000FC1* ID_MODEL_FROM_DATABASE=GK107 [GeForce GT 640] pci:v000010DEd00000FC2* ID_MODEL_FROM_DATABASE=GK107 [GeForce GT 630 OEM] pci:v000010DEd00000FC6* ID_MODEL_FROM_DATABASE=GK107 [GeForce GTX 650] pci:v000010DEd00000FC6sv00001043sd00008428* ID_MODEL_FROM_DATABASE=GK107 [GeForce GTX 650] (GTX650-DC-1GD5) pci:v000010DEd00000FC8* ID_MODEL_FROM_DATABASE=GK107 [GeForce GT 740] pci:v000010DEd00000FC9* ID_MODEL_FROM_DATABASE=GK107 [GeForce GT 730] pci:v000010DEd00000FCD* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 755M] pci:v000010DEd00000FCE* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M LE] pci:v000010DEd00000FD1* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M] pci:v000010DEd00000FD1sv00001043sd00001597* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M] (GeForce GT 650M) pci:v000010DEd00000FD1sv00001043sd000015A7* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M] (GeForce GT 650M) pci:v000010DEd00000FD1sv00001043sd00002103* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M] (N56VZ) pci:v000010DEd00000FD1sv00001043sd00002105* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M] (GeForce GT 650M) pci:v000010DEd00000FD1sv00001043sd00002141* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M] (GeForce GT 650M) pci:v000010DEd00000FD2* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M] pci:v000010DEd00000FD2sv00001028sd0000054F* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M] (GeForce GT 640M) pci:v000010DEd00000FD2sv00001028sd0000055F* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M] (GeForce GT 640M) pci:v000010DEd00000FD2sv00001028sd00000595* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M] (GeForce GT 640M LE) pci:v000010DEd00000FD2sv00001028sd000005B2* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M] (GeForce GT 640M LE) pci:v000010DEd00000FD3* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M LE] pci:v000010DEd00000FD4* ID_MODEL_FROM_DATABASE=GK107M [GeForce GTX 660M] pci:v000010DEd00000FD5* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M Mac Edition] pci:v000010DEd00000FD8* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M Mac Edition] pci:v000010DEd00000FD9* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 645M] pci:v000010DEd00000FDB* ID_MODEL_FROM_DATABASE=GK107M pci:v000010DEd00000FDF* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 740M] pci:v000010DEd00000FE0* ID_MODEL_FROM_DATABASE=GK107M [GeForce GTX 660M Mac Edition] pci:v000010DEd00000FE1* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 730M] pci:v000010DEd00000FE2* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 745M] pci:v000010DEd00000FE3* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 745M] pci:v000010DEd00000FE3sv0000103Csd00002B16* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 745M] (GeForce GT 745A) pci:v000010DEd00000FE3sv000017AAsd00003675* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 745M] (GeForce GT 745A) pci:v000010DEd00000FE4* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 750M] pci:v000010DEd00000FE5* ID_MODEL_FROM_DATABASE=GK107 [GeForce K340 USM] pci:v000010DEd00000FE6* ID_MODEL_FROM_DATABASE=GK107 [GRID K1 NVS USM] pci:v000010DEd00000FE7* ID_MODEL_FROM_DATABASE=GK107GL [GRID K100 vGPU] pci:v000010DEd00000FE7sv000010DEsd0000101E* ID_MODEL_FROM_DATABASE=GK107GL [GRID K100 vGPU] (GRID K100) pci:v000010DEd00000FE9* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 750M Mac Edition] pci:v000010DEd00000FEA* ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 755M Mac Edition] pci:v000010DEd00000FEC* ID_MODEL_FROM_DATABASE=GK107M [GeForce 710A] pci:v000010DEd00000FED* ID_MODEL_FROM_DATABASE=GK107M [GeForce 820M] pci:v000010DEd00000FEE* ID_MODEL_FROM_DATABASE=GK107M [GeForce 810M] pci:v000010DEd00000FEF* ID_MODEL_FROM_DATABASE=GK107GL [GRID K340] pci:v000010DEd00000FF1* ID_MODEL_FROM_DATABASE=GK107 [NVS 1000] pci:v000010DEd00000FF2* ID_MODEL_FROM_DATABASE=GK107GL [GRID K1] pci:v000010DEd00000FF3* ID_MODEL_FROM_DATABASE=GK107GL [Quadro K420] pci:v000010DEd00000FF5* ID_MODEL_FROM_DATABASE=GK107GL [GRID K1 Tesla USM] pci:v000010DEd00000FF6* ID_MODEL_FROM_DATABASE=GK107GLM [Quadro K1100M] pci:v000010DEd00000FF6sv0000103Csd0000197B* ID_MODEL_FROM_DATABASE=GK107GLM [Quadro K1100M] (ZBook 15) pci:v000010DEd00000FF7* ID_MODEL_FROM_DATABASE=GK107GL [GRID K140Q vGPU] pci:v000010DEd00000FF7sv000010DEsd00001037* ID_MODEL_FROM_DATABASE=GK107GL [GRID K140Q vGPU] (GRID K140Q) pci:v000010DEd00000FF8* ID_MODEL_FROM_DATABASE=GK107GLM [Quadro K500M] pci:v000010DEd00000FF9* ID_MODEL_FROM_DATABASE=GK107GL [Quadro K2000D] pci:v000010DEd00000FFA* ID_MODEL_FROM_DATABASE=GK107GL [Quadro K600] pci:v000010DEd00000FFB* ID_MODEL_FROM_DATABASE=GK107GLM [Quadro K2000M] pci:v000010DEd00000FFC* ID_MODEL_FROM_DATABASE=GK107GLM [Quadro K1000M] pci:v000010DEd00000FFD* ID_MODEL_FROM_DATABASE=GK107 [NVS 510] pci:v000010DEd00000FFE* ID_MODEL_FROM_DATABASE=GK107GL [Quadro K2000] pci:v000010DEd00000FFF* ID_MODEL_FROM_DATABASE=GK107GL [Quadro 410] pci:v000010DEd00001001* ID_MODEL_FROM_DATABASE=GK110B [GeForce GTX TITAN Z] pci:v000010DEd00001003* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX Titan LE] pci:v000010DEd00001004* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX 780] pci:v000010DEd00001004sv00003842sd00000784* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX 780] (GK110B [GeForce GTX 780 SC w/ ACX Cooler]) pci:v000010DEd00001004sv00003842sd00001784* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX 780] (GK110B [GeForce GTX 780 Dual FTW w/ ACX Cooler]) pci:v000010DEd00001004sv00003842sd00001788* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX 780] (GK110B [GeForce GTX 780 Dual Classified w/ ACX Cooler]) pci:v000010DEd00001005* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] pci:v000010DEd00001005sv00001043sd00008451* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GTXTITAN-6GD5) pci:v000010DEd00001005sv000010DEsd00001035* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GeForce GTX Titan) pci:v000010DEd00001005sv00003842sd00002790* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GeForce GTX Titan) pci:v000010DEd00001005sv00003842sd00002791* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GeForce GTX Titan SC) pci:v000010DEd00001005sv00003842sd00002793* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GeForce GTX Titan SC Signature) pci:v000010DEd00001005sv00003842sd00002794* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GeForce GTX Titan SC Hydro Copper) pci:v000010DEd00001005sv00003842sd00002795* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GeForce GTX Titan SC Hydro Copper Signature) pci:v000010DEd00001007* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX 780 Rev. 2] pci:v000010DEd00001008* ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX 780 Ti Rev. 2] pci:v000010DEd0000100A* ID_MODEL_FROM_DATABASE=GK110B [GeForce GTX 780 Ti] pci:v000010DEd0000100C* ID_MODEL_FROM_DATABASE=GK110B [GeForce GTX TITAN Black] pci:v000010DEd0000101E* ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20X] pci:v000010DEd0000101F* ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20] pci:v000010DEd00001020* ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20X] pci:v000010DEd00001021* ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20Xm] pci:v000010DEd00001022* ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20c] pci:v000010DEd00001023* ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40m] pci:v000010DEd00001023sv000010DEsd0000097E* ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40m] (12GB Computational Accelerator) pci:v000010DEd00001024* ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40c] pci:v000010DEd00001026* ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20s] pci:v000010DEd00001027* ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40st] pci:v000010DEd00001028* ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20m] pci:v000010DEd00001029* ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40s] pci:v000010DEd0000102A* ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40t] pci:v000010DEd0000102D* ID_MODEL_FROM_DATABASE=GK210GL [Tesla K80] pci:v000010DEd0000102E* ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40d] pci:v000010DEd0000103A* ID_MODEL_FROM_DATABASE=GK110GL [Quadro K6000] pci:v000010DEd0000103C* ID_MODEL_FROM_DATABASE=GK110GL [Quadro K5200] pci:v000010DEd00001040* ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 520] pci:v000010DEd00001042* ID_MODEL_FROM_DATABASE=GF119 [GeForce 510] pci:v000010DEd00001048* ID_MODEL_FROM_DATABASE=GF119 [GeForce 605] pci:v000010DEd00001049* ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 620 OEM] pci:v000010DEd0000104A* ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 610] pci:v000010DEd0000104Asv000010B0sd0000104A* ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 610] (Gainward GeForce GT 610) pci:v000010DEd0000104B* ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 625 OEM] pci:v000010DEd0000104C* ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 705] pci:v000010DEd0000104D* ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 710] pci:v000010DEd00001050* ID_MODEL_FROM_DATABASE=GF119M [GeForce GT 520M] pci:v000010DEd00001051* ID_MODEL_FROM_DATABASE=GF119M [GeForce GT 520MX] pci:v000010DEd00001052* ID_MODEL_FROM_DATABASE=GF119M [GeForce GT 520M] pci:v000010DEd00001054* ID_MODEL_FROM_DATABASE=GF119M [GeForce 410M] pci:v000010DEd00001055* ID_MODEL_FROM_DATABASE=GF119M [GeForce 410M] pci:v000010DEd00001056* ID_MODEL_FROM_DATABASE=GF119M [NVS 4200M] pci:v000010DEd00001057* ID_MODEL_FROM_DATABASE=GF119M [Quadro NVS 4200M] pci:v000010DEd00001058* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] pci:v000010DEd00001058sv0000103Csd00002AED* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 610) pci:v000010DEd00001058sv0000103Csd00002AF1* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 610) pci:v000010DEd00001058sv00001043sd000010AC* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce GT 610M) pci:v000010DEd00001058sv00001043sd000010BC* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce GT 610M) pci:v000010DEd00001058sv00001043sd00001652* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce GT 610M) pci:v000010DEd00001058sv000017AAsd0000367A* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 610M) pci:v000010DEd00001058sv000017AAsd00003682* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 800A) pci:v000010DEd00001058sv000017AAsd00003687* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 800A) pci:v000010DEd00001058sv000017AAsd00003692* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 705A) pci:v000010DEd00001058sv000017AAsd00003695* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 800A) pci:v000010DEd00001058sv000017AAsd0000A117* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 610M) pci:v000010DEd00001059* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] pci:v000010DEd0000105A* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] pci:v000010DEd0000105Asv00001043sd00002111* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce GT 610M) pci:v000010DEd0000105Asv00001043sd00002112* ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce GT 610M) pci:v000010DEd0000105B* ID_MODEL_FROM_DATABASE=GF119M [GeForce 705M] pci:v000010DEd0000105Bsv0000103Csd00002AFB* ID_MODEL_FROM_DATABASE=GF119M [GeForce 705M] (GeForce 705A) pci:v000010DEd0000105Bsv000017AAsd0000309D* ID_MODEL_FROM_DATABASE=GF119M [GeForce 705M] (GeForce 705A) pci:v000010DEd0000105Bsv000017AAsd000030B1* ID_MODEL_FROM_DATABASE=GF119M [GeForce 705M] (GeForce 800A) pci:v000010DEd0000105Bsv000017AAsd000036A1* ID_MODEL_FROM_DATABASE=GF119M [GeForce 705M] (GeForce 800A) pci:v000010DEd0000107C* ID_MODEL_FROM_DATABASE=GF119 [NVS 315] pci:v000010DEd0000107D* ID_MODEL_FROM_DATABASE=GF119 [NVS 310] pci:v000010DEd00001080* ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 580] pci:v000010DEd00001081* ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 570] pci:v000010DEd00001081sv000010DEsd0000087E* ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 570] (Leadtek WinFast GTX 570) pci:v000010DEd00001082* ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 560 Ti OEM] pci:v000010DEd00001084* ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 560 OEM] pci:v000010DEd00001086* ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 570 Rev. 2] pci:v000010DEd00001087* ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 560 Ti 448 Cores] pci:v000010DEd00001088* ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 590] pci:v000010DEd00001089* ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 580] pci:v000010DEd0000108B* ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 580] pci:v000010DEd0000108E* ID_MODEL_FROM_DATABASE=GF110GL [Tesla C2090] pci:v000010DEd00001091* ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2090] pci:v000010DEd00001091sv000010DEsd0000088E* ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2090] (Tesla X2090) pci:v000010DEd00001091sv000010DEsd00000891* ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2090] (Tesla X2090) pci:v000010DEd00001091sv000010DEsd00000974* ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2090] (Tesla X2090) pci:v000010DEd00001091sv000010DEsd0000098D* ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2090] (Tesla X2090) pci:v000010DEd00001094* ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2075] pci:v000010DEd00001094sv000010DEsd00000888* ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2075] (Tesla M2075) pci:v000010DEd00001096* ID_MODEL_FROM_DATABASE=GF110GL [Tesla C2050 / C2075] pci:v000010DEd00001096sv000010DEsd00000910* ID_MODEL_FROM_DATABASE=GF110GL [Tesla C2050 / C2075] (Tesla C2075) pci:v000010DEd00001096sv000010DEsd00000911* ID_MODEL_FROM_DATABASE=GF110GL [Tesla C2050 / C2075] (Tesla C2050) pci:v000010DEd0000109A* ID_MODEL_FROM_DATABASE=GF100GLM [Quadro 5010M] pci:v000010DEd0000109B* ID_MODEL_FROM_DATABASE=GF100GL [Quadro 7000] pci:v000010DEd0000109Bsv000010DEsd00000918* ID_MODEL_FROM_DATABASE=GF100GL [Quadro 7000] (Quadro 7000) pci:v000010DEd000010C0* ID_MODEL_FROM_DATABASE=GT218 [GeForce 9300 GS Rev. 2] pci:v000010DEd000010C3* ID_MODEL_FROM_DATABASE=GT218 [GeForce 8400 GS Rev. 3] pci:v000010DEd000010C5* ID_MODEL_FROM_DATABASE=GT218 [GeForce 405] pci:v000010DEd000010D8* ID_MODEL_FROM_DATABASE=GT218 [NVS 300] pci:v000010DEd00001140* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] pci:v000010DEd00001140sv00001019sd00000799* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001019sd0000999F* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd00000600* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd00000606* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd0000064A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd0000064C* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd0000067A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd00000680* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd00000686* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd00000689* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd0000068B* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd0000068D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd0000068E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd00000691* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd00000692* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd00000694* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd00000702* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd00000719* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd00000725* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd00000728* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd0000072B* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd0000072E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd00000732* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001025sd00000763* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd00000773* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd00000774* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd00000776* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd0000077A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd0000077B* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd0000077C* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd0000077D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd0000077E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd0000077F* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd00000781* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd00000798* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd00000799* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd0000079B* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd0000079C* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd00000807* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd00000821* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd00000823* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd00000830* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd00000833* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd00000837* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001025sd0000083E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000841* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001025sd00000854* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000855* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000856* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000857* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000858* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000863* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000868* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000869* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 810M) pci:v000010DEd00001140sv00001025sd00000873* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000878* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd0000087B* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd0000087C* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 810M) pci:v000010DEd00001140sv00001025sd00000881* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd0000088A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd0000089B* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd0000090F* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000921* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd0000092E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 810M) pci:v000010DEd00001140sv00001025sd0000092F* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000932* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd0000093A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd0000093C* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd0000093F* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000941* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000945* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000954* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001025sd00000965* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001028sd0000054D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv00001028sd0000054E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv00001028sd00000554* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001028sd00000557* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001028sd00000562* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) pci:v000010DEd00001140sv00001028sd00000565* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv00001028sd00000568* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv00001028sd00000590* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv00001028sd00000592* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) pci:v000010DEd00001140sv00001028sd00000594* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) pci:v000010DEd00001140sv00001028sd00000595* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) pci:v000010DEd00001140sv00001028sd000005A2* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) pci:v000010DEd00001140sv00001028sd000005B1* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) pci:v000010DEd00001140sv00001028sd000005B3* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) pci:v000010DEd00001140sv00001028sd000005DA* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv00001028sd000005DE* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001028sd000005E0* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001028sd000005E8* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv00001028sd000005F4* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001028sd0000060F* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001028sd0000064E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001028sd00000652* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001028sd00000653* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001028sd00000655* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001028sd0000065E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001028sd00000662* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001028sd0000068D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001028sd000006C1* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv0000103Csd000018EF* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv0000103Csd000018F9* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv0000103Csd000018FB* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv0000103Csd000018FD* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv0000103Csd000018FF* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv0000103Csd00002335* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv0000103Csd00002337* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv0000103Csd00002AEF* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720A) pci:v000010DEd00001140sv0000103Csd00002AF9* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710A) pci:v000010DEd00001140sv00001043sd000010DD* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) pci:v000010DEd00001140sv00001043sd000010ED* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) pci:v000010DEd00001140sv00001043sd000011FD* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001043sd0000124D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001043sd0000126D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001043sd0000131D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001043sd000013FD* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001043sd000014C7* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001043sd00001507* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001043sd000015AD* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd000015ED* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000160D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000163D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000166D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd000016CD* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd000016DD* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000170D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000176D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000178D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000179D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd000017DD* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd00002132* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001043sd00002136* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) pci:v000010DEd00001140sv00001043sd000021BA* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001043sd000021FA* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001043sd0000220A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001043sd0000221A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001043sd0000223A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 710M) pci:v000010DEd00001140sv00001043sd0000224A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 710M) pci:v000010DEd00001140sv00001043sd0000227A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000228A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000232A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000233A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000236A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000238A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd00008595* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001043sd000085EA* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001043sd000085EB* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd000085EC* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd000085EE* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001043sd000085F3* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000860E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000861A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000861B* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd00008628* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd00008643* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd0000864C* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001043sd00008652* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv0000105Bsd00000DAC* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv0000105Bsd00000DAD* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv0000105Bsd00000EF3* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001072sd0000152D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000010CFsd000017F5* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001179sd0000FA01* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA02* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA03* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA05* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA11* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA13* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA18* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA19* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA21* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA23* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA2A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA32* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA33* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA36* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA38* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA42* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA43* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA45* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA47* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA49* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA58* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA59* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA88* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001179sd0000FA89* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv0000144Dsd0000B092* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv0000144Dsd0000C0D5* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv0000144Dsd0000C0D7* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv0000144Dsd0000C0E2* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) pci:v000010DEd00001140sv0000144Dsd0000C0E3* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) pci:v000010DEd00001140sv0000144Dsd0000C0E4* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) pci:v000010DEd00001140sv0000144Dsd0000C10D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv0000144Dsd0000C652* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv0000144Dsd0000C709* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv0000144Dsd0000C711* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv0000144Dsd0000C736* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv0000144Dsd0000C737* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv0000144Dsd0000C745* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv0000144Dsd0000C750* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001462sd000010B8* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 710M) pci:v000010DEd00001140sv00001462sd000010E9* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001462sd00001116* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001462sd0000AA33* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 720M) pci:v000010DEd00001140sv00001462sd0000AAA2* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001462sd0000AAA3* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001462sd0000ACB2* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001462sd0000ACC1* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001462sd0000AE61* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 720M) pci:v000010DEd00001140sv00001462sd0000AE65* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001462sd0000AE6A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001462sd0000AE71* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000014C0sd00000083* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv0000152Dsd00000926* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 620M) pci:v000010DEd00001140sv0000152Dsd00000982* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv0000152Dsd00000983* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv0000152Dsd00001005* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 820M) pci:v000010DEd00001140sv0000152Dsd00001012* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv0000152Dsd00001019* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv0000152Dsd00001030* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) pci:v000010DEd00001140sv0000152Dsd00001055* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv0000152Dsd00001067* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv0000152Dsd00001072* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv0000152Dsd00001086* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv0000152Dsd00001092* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd00002200* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) pci:v000010DEd00001140sv000017AAsd00002213* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd00002220* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd0000309C* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720A) pci:v000010DEd00001140sv000017AAsd000030B4* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) pci:v000010DEd00001140sv000017AAsd000030B7* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 720A) pci:v000010DEd00001140sv000017AAsd0000361B* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) pci:v000010DEd00001140sv000017AAsd0000361C* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) pci:v000010DEd00001140sv000017AAsd00003656* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv000017AAsd0000365A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 705M) pci:v000010DEd00001140sv000017AAsd0000365E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 800M) pci:v000010DEd00001140sv000017AAsd00003661* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) pci:v000010DEd00001140sv000017AAsd0000366C* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 800M) pci:v000010DEd00001140sv000017AAsd00003685* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 800M) pci:v000010DEd00001140sv000017AAsd00003686* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 800M) pci:v000010DEd00001140sv000017AAsd00003687* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 705A) pci:v000010DEd00001140sv000017AAsd00003696* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) pci:v000010DEd00001140sv000017AAsd0000369B* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) pci:v000010DEd00001140sv000017AAsd0000369C* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) pci:v000010DEd00001140sv000017AAsd0000369D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) pci:v000010DEd00001140sv000017AAsd0000369E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) pci:v000010DEd00001140sv000017AAsd000036A9* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) pci:v000010DEd00001140sv000017AAsd000036AF* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) pci:v000010DEd00001140sv000017AAsd000036B0* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) pci:v000010DEd00001140sv000017AAsd000036B6* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) pci:v000010DEd00001140sv000017AAsd00003800* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd00003801* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd00003802* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd00003803* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd00003804* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd00003806* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd00003808* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd0000380D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd0000380E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd0000380F* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd00003811* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd00003812* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd00003813* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd00003816* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd00003818* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd0000381A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd0000381C* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd00003901* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 610M / GT 620M) pci:v000010DEd00001140sv000017AAsd00003902* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv000017AAsd00003903* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 610M/710M) pci:v000010DEd00001140sv000017AAsd00003904* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M/625M) pci:v000010DEd00001140sv000017AAsd00003905* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd00003907* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd00003910* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 720M) pci:v000010DEd00001140sv000017AAsd00003912* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 720M) pci:v000010DEd00001140sv000017AAsd00003913* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd00003915* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd00003977* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd00003983* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 610M) pci:v000010DEd00001140sv000017AAsd00005001* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 610M) pci:v000010DEd00001140sv000017AAsd00005003* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd00005005* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 705M) pci:v000010DEd00001140sv000017AAsd0000500D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv000017AAsd00005014* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv000017AAsd00005017* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv000017AAsd00005019* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv000017AAsd0000501A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv000017AAsd0000501F* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd00005025* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv000017AAsd00005027* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv000017AAsd0000502A* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv000017AAsd0000502B* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd0000502D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv000017AAsd0000502E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd0000502F* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv000017AAsd00005030* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 705M) pci:v000010DEd00001140sv000017AAsd00005031* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 705M) pci:v000010DEd00001140sv000017AAsd00005032* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd00005033* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd0000503E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv000017AAsd0000503F* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv000017AAsd00005040* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001854sd00000177* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001854sd00000180* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) pci:v000010DEd00001140sv00001854sd00000190* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001854sd00000192* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001854sd00000224* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001B0Asd000001C0* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001B0Asd000020DD* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001B0Asd000020DF* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) pci:v000010DEd00001140sv00001B0Asd0000210E* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001B0Asd00002202* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001B0Asd000090D7* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001B0Asd000090DD* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001B50sd00005530* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001B6Csd00005531* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) pci:v000010DEd00001140sv00001BABsd00000106* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv00001D05sd00001013* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 810M) pci:v000010DEd00001180* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 680] pci:v000010DEd00001180sv00001043sd000083F1* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 680] (GTX680-DC2-2GD5) pci:v000010DEd00001180sv00003842sd00003682* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 680] (GeForce GTX 680 Mac Edition) pci:v000010DEd00001182* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760 Ti] pci:v000010DEd00001183* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 660 Ti] pci:v000010DEd00001184* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 770] pci:v000010DEd00001185* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 660 OEM] pci:v000010DEd00001185sv000010DEsd0000106F* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 660 OEM] (GK104 [GeForce GTX 760 OEM]) pci:v000010DEd00001187* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760] pci:v000010DEd00001188* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 690] pci:v000010DEd00001189* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 670] pci:v000010DEd00001189sv000010DEsd00001074* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 670] (GK104 [GeForce GTX 760 Ti OEM]) pci:v000010DEd0000118A* ID_MODEL_FROM_DATABASE=GK104GL [GRID K520] pci:v000010DEd0000118B* ID_MODEL_FROM_DATABASE=GK104GL [GRID K2 GeForce USM] pci:v000010DEd0000118C* ID_MODEL_FROM_DATABASE=GK104 [GRID K2 NVS USM] pci:v000010DEd0000118D* ID_MODEL_FROM_DATABASE=GK104GL [GRID K200 vGPU] pci:v000010DEd0000118Dsv000010DEsd0000101D* ID_MODEL_FROM_DATABASE=GK104GL [GRID K200 vGPU] (GRID K200) pci:v000010DEd0000118E* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760 OEM] pci:v000010DEd0000118F* ID_MODEL_FROM_DATABASE=GK104GL [Tesla K10] pci:v000010DEd00001191* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760 Rev. 2] pci:v000010DEd00001193* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760 Ti OEM] pci:v000010DEd00001194* ID_MODEL_FROM_DATABASE=GK104GL [Tesla K8] pci:v000010DEd00001195* ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 660 Rev. 2] pci:v000010DEd00001198* ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 880M] pci:v000010DEd00001199* ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 870M] pci:v000010DEd0000119A* ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 860M] pci:v000010DEd0000119D* ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 775M Mac Edition] pci:v000010DEd0000119E* ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 780M Mac Edition] pci:v000010DEd0000119F* ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 780M] pci:v000010DEd000011A0* ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 680M] pci:v000010DEd000011A1* ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 670MX] pci:v000010DEd000011A2* ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 675MX Mac Edition] pci:v000010DEd000011A3* ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 680MX] pci:v000010DEd000011A3sv0000106Bsd0000010D* ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 680MX] (iMac 13,2) pci:v000010DEd000011A7* ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 675MX] pci:v000010DEd000011B0* ID_MODEL_FROM_DATABASE=GK104GL [GRID K240Q\K260Q vGPU] pci:v000010DEd000011B0sv000010DEsd0000101A* ID_MODEL_FROM_DATABASE=GK104GL [GRID K240Q\K260Q vGPU] (GRID K240Q) pci:v000010DEd000011B0sv000010DEsd0000101B* ID_MODEL_FROM_DATABASE=GK104GL [GRID K240Q\K260Q vGPU] (GRID K260Q) pci:v000010DEd000011B1* ID_MODEL_FROM_DATABASE=GK104GL [GRID K2 Tesla USM] pci:v000010DEd000011B4* ID_MODEL_FROM_DATABASE=GK104GL [Quadro K4200] pci:v000010DEd000011B6* ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K3100M] pci:v000010DEd000011B7* ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K4100M] pci:v000010DEd000011B8* ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K5100M] pci:v000010DEd000011BA* ID_MODEL_FROM_DATABASE=GK104GL [Quadro K5000] pci:v000010DEd000011BB* ID_MODEL_FROM_DATABASE=GK104GL [Quadro 4100] pci:v000010DEd000011BC* ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K5000M] pci:v000010DEd000011BD* ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K4000M] pci:v000010DEd000011BE* ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K3000M] pci:v000010DEd000011BF* ID_MODEL_FROM_DATABASE=GK104GL [GRID K2] pci:v000010DEd000011C0* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 660] pci:v000010DEd000011C2* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] pci:v000010DEd000011C2sv00001043sd0000845B* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] (GeForce GTX 650 Ti Boost DirectCU II OC) pci:v000010DEd000011C2sv00001462sd00002874* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] (GeForce GTX 650 Ti Boost TwinFrozr II OC) pci:v000010DEd000011C2sv00001569sd000011C2* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] (GeForce GTX 650 Ti Boost OC) pci:v000010DEd000011C2sv000019DAsd00001281* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] (GeForce GTX 650 Ti Boost OC) pci:v000010DEd000011C2sv00003842sd00003657* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] (GeForce GTX 650 Ti Boost) pci:v000010DEd000011C2sv00003842sd00003658* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] (GeForce GTX 650 Ti Boost Superclocked) pci:v000010DEd000011C3* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti OEM] pci:v000010DEd000011C3sv000010DEsd00001030* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti OEM] (GeForce GTX 650 Ti OEM) pci:v000010DEd000011C4* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 645 OEM] pci:v000010DEd000011C5* ID_MODEL_FROM_DATABASE=GK106 [GeForce GT 740] pci:v000010DEd000011C6* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti] pci:v000010DEd000011C7* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 750 Ti] pci:v000010DEd000011C8* ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 OEM] pci:v000010DEd000011CB* ID_MODEL_FROM_DATABASE=GK106 [GeForce GT 740] pci:v000010DEd000011E0* ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 770M] pci:v000010DEd000011E1* ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 765M] pci:v000010DEd000011E2* ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 765M] pci:v000010DEd000011E3* ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 760M] pci:v000010DEd000011E3sv000017AAsd00003683* ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 760M] (GeForce GTX 760A) pci:v000010DEd000011E7* ID_MODEL_FROM_DATABASE=GK106M pci:v000010DEd000011FA* ID_MODEL_FROM_DATABASE=GK106GL [Quadro K4000] pci:v000010DEd000011FC* ID_MODEL_FROM_DATABASE=GK106GLM [Quadro K2100M] pci:v000010DEd00001200* ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 560 Ti] pci:v000010DEd00001201* ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 560] pci:v000010DEd00001202* ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 560 Ti OEM] pci:v000010DEd00001203* ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 460 SE v2] pci:v000010DEd00001205* ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 460 v2] pci:v000010DEd00001206* ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 555] pci:v000010DEd00001207* ID_MODEL_FROM_DATABASE=GF114 [GeForce GT 645 OEM] pci:v000010DEd00001208* ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 560 SE] pci:v000010DEd00001210* ID_MODEL_FROM_DATABASE=GF114M [GeForce GTX 570M] pci:v000010DEd00001211* ID_MODEL_FROM_DATABASE=GF114M [GeForce GTX 580M] pci:v000010DEd00001212* ID_MODEL_FROM_DATABASE=GF114M [GeForce GTX 675M] pci:v000010DEd00001213* ID_MODEL_FROM_DATABASE=GF114M [GeForce GTX 670M] pci:v000010DEd00001241* ID_MODEL_FROM_DATABASE=GF116 [GeForce GT 545 OEM] pci:v000010DEd00001243* ID_MODEL_FROM_DATABASE=GF116 [GeForce GT 545] pci:v000010DEd00001244* ID_MODEL_FROM_DATABASE=GF116 [GeForce GTX 550 Ti] pci:v000010DEd00001245* ID_MODEL_FROM_DATABASE=GF116 [GeForce GTS 450 Rev. 2] pci:v000010DEd00001246* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 550M] pci:v000010DEd00001247* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] pci:v000010DEd00001247sv00001043sd00001752* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd00001247sv00001043sd00002050* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd00001247sv00001043sd00002051* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd00001247sv00001043sd0000212A* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 635M) pci:v000010DEd00001247sv00001043sd0000212B* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 635M) pci:v000010DEd00001247sv00001043sd0000212C* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 635M) pci:v000010DEd00001247sv0000152Dsd00000930* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 635M) pci:v000010DEd00001248* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] pci:v000010DEd00001248sv0000152Dsd00000930* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 635M) pci:v000010DEd00001248sv000017C0sd000010E7* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd00001248sv000017C0sd000010E8* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd00001248sv000017C0sd000010EA* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd00001248sv00001854sd00000890* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd00001248sv00001854sd00000891* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd00001248sv00001854sd00001795* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd00001248sv00001854sd00001796* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd00001248sv00001854sd00003005* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd00001249* ID_MODEL_FROM_DATABASE=GF116 [GeForce GTS 450 Rev. 3] pci:v000010DEd0000124B* ID_MODEL_FROM_DATABASE=GF116 [GeForce GT 640 OEM] pci:v000010DEd0000124D* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] pci:v000010DEd0000124Dsv00001028sd00000491* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd0000124Dsv00001028sd00000570* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd0000124Dsv00001028sd00000571* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd0000124Dsv00001462sd0000108D* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) pci:v000010DEd0000124Dsv00001462sd000010CC* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 635M) pci:v000010DEd00001251* ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 560M] pci:v000010DEd00001280* ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 635] pci:v000010DEd00001281* ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 710] pci:v000010DEd00001282* ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 640 Rev. 2] pci:v000010DEd00001284* ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 630 Rev. 2] pci:v000010DEd00001286* ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 720] pci:v000010DEd00001287* ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 730] pci:v000010DEd00001288* ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 720] pci:v000010DEd00001289* ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 710] pci:v000010DEd00001290* ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M] pci:v000010DEd00001290sv0000103Csd00002AFA* ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M] (GeForce GT 730A) pci:v000010DEd00001290sv0000103Csd00002B04* ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M] (GeForce GT 730A) pci:v000010DEd00001290sv00001043sd000013AD* ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M] (GeForce GT 730M) pci:v000010DEd00001290sv00001043sd000013CD* ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M] (GeForce GT 730M) pci:v000010DEd00001291* ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 735M] pci:v000010DEd00001292* ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 740M] pci:v000010DEd00001292sv000017AAsd00003675* ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 740M] (GeForce GT 740A) pci:v000010DEd00001292sv000017AAsd0000367C* ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 740M] (GeForce GT 740A) pci:v000010DEd00001292sv000017AAsd00003684* ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 740M] (GeForce GT 740A) pci:v000010DEd00001293* ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M] pci:v000010DEd00001294* ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 740M] pci:v000010DEd00001295* ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] pci:v000010DEd00001295sv0000103Csd00002B0D* ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 710A) pci:v000010DEd00001295sv0000103Csd00002B0F* ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 710A) pci:v000010DEd00001295sv0000103Csd00002B11* ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 710A) pci:v000010DEd00001295sv0000103Csd00002B20* ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 810A) pci:v000010DEd00001295sv0000103Csd00002B21* ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 810A) pci:v000010DEd00001295sv0000103Csd00002B22* ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 810A) pci:v000010DEd00001295sv000017AAsd0000367A* ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 805A) pci:v000010DEd00001295sv000017AAsd0000367C* ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 710A) pci:v000010DEd00001296* ID_MODEL_FROM_DATABASE=GK208M [GeForce 825M] pci:v000010DEd00001298* ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 720M] pci:v000010DEd00001299* ID_MODEL_FROM_DATABASE=GK208M [GeForce 920M] pci:v000010DEd0000129A* ID_MODEL_FROM_DATABASE=GK208M [GeForce 910M] pci:v000010DEd000012A0* ID_MODEL_FROM_DATABASE=GK208 pci:v000010DEd000012B9* ID_MODEL_FROM_DATABASE=GK208GLM [Quadro K610M] pci:v000010DEd000012BA* ID_MODEL_FROM_DATABASE=GK208GLM [Quadro K510M] pci:v000010DEd00001340* ID_MODEL_FROM_DATABASE=GM108M [GeForce 830M] pci:v000010DEd00001340sv0000103Csd00002B2B* ID_MODEL_FROM_DATABASE=GM108M [GeForce 830M] (GeForce 830A) pci:v000010DEd00001341* ID_MODEL_FROM_DATABASE=GM108M [GeForce 840M] pci:v000010DEd00001341sv000017AAsd00003697* ID_MODEL_FROM_DATABASE=GM108M [GeForce 840M] (GeForce 840A) pci:v000010DEd00001341sv000017AAsd00003699* ID_MODEL_FROM_DATABASE=GM108M [GeForce 840M] (GeForce 840A) pci:v000010DEd00001341sv000017AAsd0000369C* ID_MODEL_FROM_DATABASE=GM108M [GeForce 840M] (GeForce 840A) pci:v000010DEd00001344* ID_MODEL_FROM_DATABASE=GM108M [GeForce 845M] pci:v000010DEd00001346* ID_MODEL_FROM_DATABASE=GM108M [GeForce 930M] pci:v000010DEd00001347* ID_MODEL_FROM_DATABASE=GM108M [GeForce 940M] pci:v000010DEd0000134D* ID_MODEL_FROM_DATABASE=GM108M [GeForce 940MX] pci:v000010DEd0000137A* ID_MODEL_FROM_DATABASE=GM108GLM [Quadro K620M] pci:v000010DEd0000137D* ID_MODEL_FROM_DATABASE=GM108M [GeForce 940A] pci:v000010DEd00001380* ID_MODEL_FROM_DATABASE=GM107 [GeForce GTX 750 Ti] pci:v000010DEd00001381* ID_MODEL_FROM_DATABASE=GM107 [GeForce GTX 750] pci:v000010DEd00001382* ID_MODEL_FROM_DATABASE=GM107 [GeForce GTX 745] pci:v000010DEd00001389* ID_MODEL_FROM_DATABASE=GM107GL [GRID M30] pci:v000010DEd00001390* ID_MODEL_FROM_DATABASE=GM107M [GeForce 845M] pci:v000010DEd00001391* ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 850M] pci:v000010DEd00001391sv000017AAsd00003697* ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 850M] (GeForce GTX 850A) pci:v000010DEd00001391sv000017AAsd0000A125* ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 850M] (GeForce GTX 850A) pci:v000010DEd00001392* ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 860M] pci:v000010DEd00001393* ID_MODEL_FROM_DATABASE=GM107M [GeForce 840M] pci:v000010DEd00001398* ID_MODEL_FROM_DATABASE=GM107M [GeForce 845M] pci:v000010DEd0000139A* ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] pci:v000010DEd0000139Asv000017AAsd0000362C* ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A) pci:v000010DEd0000139Asv000017AAsd0000362F* ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A) pci:v000010DEd0000139Asv000017AAsd0000363F* ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A) pci:v000010DEd0000139Asv000017AAsd00003640* ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A) pci:v000010DEd0000139Asv000017AAsd000036B9* ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A) pci:v000010DEd0000139B* ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 960M] pci:v000010DEd0000139Bsv0000103Csd00002B4C* ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 960M] (GeForce GTX 960A) pci:v000010DEd0000139C* ID_MODEL_FROM_DATABASE=GM107M [GeForce 940M] pci:v000010DEd000013B0* ID_MODEL_FROM_DATABASE=GM107GLM [Quadro M2000M] pci:v000010DEd000013B1* ID_MODEL_FROM_DATABASE=GM107GLM [Quadro M1000M] pci:v000010DEd000013B2* ID_MODEL_FROM_DATABASE=GM107GLM [Quadro M600M] pci:v000010DEd000013B3* ID_MODEL_FROM_DATABASE=GM107GLM [Quadro K2200M] pci:v000010DEd000013B9* ID_MODEL_FROM_DATABASE=GM107GL [NVS 810] pci:v000010DEd000013BA* ID_MODEL_FROM_DATABASE=GM107GL [Quadro K2200] pci:v000010DEd000013BB* ID_MODEL_FROM_DATABASE=GM107GL [Quadro K620] pci:v000010DEd000013BC* ID_MODEL_FROM_DATABASE=GM107GL [Quadro K1200] pci:v000010DEd000013BD* ID_MODEL_FROM_DATABASE=GM107GL [GRID M40] pci:v000010DEd000013C0* ID_MODEL_FROM_DATABASE=GM204 [GeForce GTX 980] pci:v000010DEd000013C0sv00001043sd00008504* ID_MODEL_FROM_DATABASE=GM204 [GeForce GTX 980] (GTX980-4GD5) pci:v000010DEd000013C1* ID_MODEL_FROM_DATABASE=GM204 pci:v000010DEd000013C2* ID_MODEL_FROM_DATABASE=GM204 [GeForce GTX 970] pci:v000010DEd000013C3* ID_MODEL_FROM_DATABASE=GM204 pci:v000010DEd000013D7* ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980M] pci:v000010DEd000013D8* ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 970M] pci:v000010DEd000013D9* ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 965M] pci:v000010DEd000013DA* ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980] pci:v000010DEd000013F0* ID_MODEL_FROM_DATABASE=GM204GL [Quadro M5000] pci:v000010DEd000013F1* ID_MODEL_FROM_DATABASE=GM204GL [Quadro M4000] pci:v000010DEd000013F2* ID_MODEL_FROM_DATABASE=GM204GL [Tesla M60] pci:v000010DEd000013F8* ID_MODEL_FROM_DATABASE=GM204GLM [Quadro M5000M] pci:v000010DEd000013F9* ID_MODEL_FROM_DATABASE=GM204GLM [Quadro M4000M] pci:v000010DEd000013FA* ID_MODEL_FROM_DATABASE=GM204GLM [Quadro M3000M] pci:v000010DEd00001401* ID_MODEL_FROM_DATABASE=GM206 [GeForce GTX 960] pci:v000010DEd00001402* ID_MODEL_FROM_DATABASE=GM206 [GeForce GTX 950] pci:v000010DEd00001407* ID_MODEL_FROM_DATABASE=GM206 [GeForce GTX 750 v2] pci:v000010DEd00001427* ID_MODEL_FROM_DATABASE=GM206M [GeForce GTX 965M] pci:v000010DEd00001617* ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980M] pci:v000010DEd00001618* ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 970M] pci:v000010DEd00001619* ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 965M] pci:v000010DEd0000161A* ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980] pci:v000010DEd000017C2* ID_MODEL_FROM_DATABASE=GM200 [GeForce GTX TITAN X] pci:v000010DEd000017C8* ID_MODEL_FROM_DATABASE=GM200 [GeForce GTX 980 Ti] pci:v000010DEd000017F0* ID_MODEL_FROM_DATABASE=GM200GL [Quadro M6000] pci:v000010DEd000017FD* ID_MODEL_FROM_DATABASE=GM200GL [Tesla M40] pci:v000010DF* ID_VENDOR_FROM_DATABASE=Emulex Corporation pci:v000010DFd00000720* ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) pci:v000010DFd00000720sv0000103Csd00001934* ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (FlexFabric 20Gb 2-port 650M Adapter) pci:v000010DFd00000720sv0000103Csd00001935* ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (FlexFabric 20Gb 2-port 650FLB Adapter) pci:v000010DFd00000720sv0000103Csd000021D4* ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (StoreFabric CN1200E 10Gb Converged Network Adapter) pci:v000010DFd00000720sv0000103Csd0000220A* ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (FlexFabric 10Gb 2-port 556FLR-SFP+ Adapter) pci:v000010DFd00000720sv0000103Csd0000803F* ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (Ethernet 10Gb 2-port 557SFP+ Adapter) pci:v000010DFd00000720sv000017AAsd00001056* ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (ThinkServer OCm14102-UX-L AnyFabric) pci:v000010DFd00000720sv000017AAsd00001057* ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (ThinkServer OCm14104-UX-L AnyFabric) pci:v000010DFd00000720sv000017AAsd00001059* ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (ThinkServer OCm14104-UT-L AnyFabric) pci:v000010DFd00000720sv000017AAsd00004014* ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (ThinkServer OCm14102-NX-L AnyFabric) pci:v000010DFd00000722* ID_MODEL_FROM_DATABASE=OneConnect iSCSI Initiator (Skyhawk) pci:v000010DFd00000723* ID_MODEL_FROM_DATABASE=OneConnect iSCSI Initiator + Target (Skyhawk) pci:v000010DFd00000724* ID_MODEL_FROM_DATABASE=OneConnect FCoE Initiator (Skyhawk) pci:v000010DFd00000728* ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk-VF) pci:v000010DFd0000072A* ID_MODEL_FROM_DATABASE=OneConnect iSCSI Initiator (Skyhawk-VF) pci:v000010DFd0000072B* ID_MODEL_FROM_DATABASE=OneConnect iSCSI Initiator + Target (Skyhawk-VF) pci:v000010DFd0000072C* ID_MODEL_FROM_DATABASE=OneConnect FCoE Initiator (Skyhawk-VF) pci:v000010DFd00001AE5* ID_MODEL_FROM_DATABASE=LP6000 Fibre Channel Host Adapter pci:v000010DFd0000E100* ID_MODEL_FROM_DATABASE=Proteus-X: LightPulse IOV Fibre Channel Host Adapter pci:v000010DFd0000E131* ID_MODEL_FROM_DATABASE=LightPulse 8Gb/s PCIe Shared I/O Fibre Channel Adapter pci:v000010DFd0000E180* ID_MODEL_FROM_DATABASE=Proteus-X: LightPulse IOV Fibre Channel Host Adapter pci:v000010DFd0000E200* ID_MODEL_FROM_DATABASE=Lancer-X: LightPulse Fibre Channel Host Adapter pci:v000010DFd0000E208* ID_MODEL_FROM_DATABASE=LightPulse 16Gb Fibre Channel Host Adapter (Lancer-VF) pci:v000010DFd0000E220* ID_MODEL_FROM_DATABASE=OneConnect NIC (Lancer) pci:v000010DFd0000E220sv000017AAsd00001054* ID_MODEL_FROM_DATABASE=OneConnect NIC (Lancer) (ThinkServer LPm16002B-M6-L AnyFabric) pci:v000010DFd0000E220sv000017AAsd00001055* ID_MODEL_FROM_DATABASE=OneConnect NIC (Lancer) (ThinkServer LPm16004B-M8-L AnyFabric) pci:v000010DFd0000E240* ID_MODEL_FROM_DATABASE=OneConnect iSCSI Initiator (Lancer) pci:v000010DFd0000E260* ID_MODEL_FROM_DATABASE=OneConnect FCoE Initiator (Lancer) pci:v000010DFd0000E268* ID_MODEL_FROM_DATABASE=OneConnect 10Gb FCoE Converged Network Adapter (Lancer-VF) pci:v000010DFd0000F011* ID_MODEL_FROM_DATABASE=Saturn: LightPulse Fibre Channel Host Adapter pci:v000010DFd0000F015* ID_MODEL_FROM_DATABASE=Saturn: LightPulse Fibre Channel Host Adapter pci:v000010DFd0000F085* ID_MODEL_FROM_DATABASE=LP850 Fibre Channel Host Adapter pci:v000010DFd0000F095* ID_MODEL_FROM_DATABASE=LP952 Fibre Channel Host Adapter pci:v000010DFd0000F098* ID_MODEL_FROM_DATABASE=LP982 Fibre Channel Host Adapter pci:v000010DFd0000F0A1* ID_MODEL_FROM_DATABASE=Thor LightPulse Fibre Channel Host Adapter pci:v000010DFd0000F0A5* ID_MODEL_FROM_DATABASE=Thor LightPulse Fibre Channel Host Adapter pci:v000010DFd0000F0B5* ID_MODEL_FROM_DATABASE=Viper LightPulse Fibre Channel Host Adapter pci:v000010DFd0000F0D1* ID_MODEL_FROM_DATABASE=Helios LightPulse Fibre Channel Host Adapter pci:v000010DFd0000F0D5* ID_MODEL_FROM_DATABASE=Helios LightPulse Fibre Channel Host Adapter pci:v000010DFd0000F0E1* ID_MODEL_FROM_DATABASE=Zephyr LightPulse Fibre Channel Host Adapter pci:v000010DFd0000F0E5* ID_MODEL_FROM_DATABASE=Zephyr LightPulse Fibre Channel Host Adapter pci:v000010DFd0000F0F5* ID_MODEL_FROM_DATABASE=Neptune LightPulse Fibre Channel Host Adapter pci:v000010DFd0000F100* ID_MODEL_FROM_DATABASE=Saturn-X: LightPulse Fibre Channel Host Adapter pci:v000010DFd0000F111* ID_MODEL_FROM_DATABASE=Saturn-X LightPulse Fibre Channel Host Adapter pci:v000010DFd0000F112* ID_MODEL_FROM_DATABASE=Saturn-X LightPulse Fibre Channel Host Adapter pci:v000010DFd0000F180* ID_MODEL_FROM_DATABASE=LPSe12002 EmulexSecure Fibre Channel Adapter pci:v000010DFd0000F700* ID_MODEL_FROM_DATABASE=LP7000 Fibre Channel Host Adapter pci:v000010DFd0000F701* ID_MODEL_FROM_DATABASE=LP7000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) pci:v000010DFd0000F800* ID_MODEL_FROM_DATABASE=LP8000 Fibre Channel Host Adapter pci:v000010DFd0000F801* ID_MODEL_FROM_DATABASE=LP8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) pci:v000010DFd0000F900* ID_MODEL_FROM_DATABASE=LP9000 Fibre Channel Host Adapter pci:v000010DFd0000F901* ID_MODEL_FROM_DATABASE=LP9000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) pci:v000010DFd0000F980* ID_MODEL_FROM_DATABASE=LP9802 Fibre Channel Host Adapter pci:v000010DFd0000F981* ID_MODEL_FROM_DATABASE=LP9802 Fibre Channel Host Adapter Alternate ID pci:v000010DFd0000F982* ID_MODEL_FROM_DATABASE=LP9802 Fibre Channel Host Adapter Alternate ID pci:v000010DFd0000FA00* ID_MODEL_FROM_DATABASE=Thor-X LightPulse Fibre Channel Host Adapter pci:v000010DFd0000FB00* ID_MODEL_FROM_DATABASE=Viper LightPulse Fibre Channel Host Adapter pci:v000010DFd0000FC00* ID_MODEL_FROM_DATABASE=Thor-X LightPulse Fibre Channel Host Adapter pci:v000010DFd0000FC00sv000010DFsd0000FC00* ID_MODEL_FROM_DATABASE=Thor-X LightPulse Fibre Channel Host Adapter (LP10000 LightPulse Fibre Channel Host Adapter) pci:v000010DFd0000FC10* ID_MODEL_FROM_DATABASE=Helios-X LightPulse Fibre Channel Host Adapter pci:v000010DFd0000FC20* ID_MODEL_FROM_DATABASE=Zephyr-X LightPulse Fibre Channel Host Adapter pci:v000010DFd0000FC40* ID_MODEL_FROM_DATABASE=Saturn-X: LightPulse Fibre Channel Host Adapter pci:v000010DFd0000FC50* ID_MODEL_FROM_DATABASE=Proteus-X: LightPulse IOV Fibre Channel Host Adapter pci:v000010DFd0000FD00* ID_MODEL_FROM_DATABASE=Helios-X LightPulse Fibre Channel Host Adapter pci:v000010DFd0000FD11* ID_MODEL_FROM_DATABASE=Helios-X LightPulse Fibre Channel Host Adapter pci:v000010DFd0000FD12* ID_MODEL_FROM_DATABASE=Helios-X LightPulse Fibre Channel Host Adapter pci:v000010DFd0000FE00* ID_MODEL_FROM_DATABASE=Zephyr-X LightPulse Fibre Channel Host Adapter pci:v000010DFd0000FE05* ID_MODEL_FROM_DATABASE=Zephyr-X: LightPulse FCoE Adapter pci:v000010DFd0000FE11* ID_MODEL_FROM_DATABASE=Zephyr-X LightPulse Fibre Channel Host Adapter pci:v000010DFd0000FE12* ID_MODEL_FROM_DATABASE=Zephyr-X LightPulse FCoE Adapter pci:v000010DFd0000FF00* ID_MODEL_FROM_DATABASE=Neptune LightPulse Fibre Channel Host Adapter pci:v000010E0* ID_VENDOR_FROM_DATABASE=Integrated Micro Solutions Inc. pci:v000010E0d00005026* ID_MODEL_FROM_DATABASE=IMS5026/27/28 pci:v000010E0d00005027* ID_MODEL_FROM_DATABASE=IMS5027 pci:v000010E0d00005028* ID_MODEL_FROM_DATABASE=IMS5028 pci:v000010E0d00008849* ID_MODEL_FROM_DATABASE=IMS8849 pci:v000010E0d00008853* ID_MODEL_FROM_DATABASE=IMS8853 pci:v000010E0d00009128* ID_MODEL_FROM_DATABASE=IMS9128 [Twin turbo 128] pci:v000010E1* ID_VENDOR_FROM_DATABASE=Tekram Technology Co.,Ltd. pci:v000010E1d00000391* ID_MODEL_FROM_DATABASE=TRM-S1040 pci:v000010E1d00000391sv000010E1sd00000391* ID_MODEL_FROM_DATABASE=TRM-S1040 (DC-315U SCSI-3 Host Adapter) pci:v000010E1d0000690C* ID_MODEL_FROM_DATABASE=DC-690c pci:v000010E1d0000DC29* ID_MODEL_FROM_DATABASE=DC-290 pci:v000010E2* ID_VENDOR_FROM_DATABASE=Aptix Corporation pci:v000010E3* ID_VENDOR_FROM_DATABASE=Tundra Semiconductor Corp. pci:v000010E3d00000000* ID_MODEL_FROM_DATABASE=CA91C042 [Universe] pci:v000010E3d00000108* ID_MODEL_FROM_DATABASE=Tsi108 Host Bridge for Single PowerPC pci:v000010E3d00000148* ID_MODEL_FROM_DATABASE=Tsi148 [Tempe] pci:v000010E3d00000148sv00001775sd00001100* ID_MODEL_FROM_DATABASE=Tsi148 [Tempe] (VR11 Single Board Computer) pci:v000010E3d00000860* ID_MODEL_FROM_DATABASE=CA91C860 [QSpan] pci:v000010E3d00000862* ID_MODEL_FROM_DATABASE=CA91C862A [QSpan-II] pci:v000010E3d00008260* ID_MODEL_FROM_DATABASE=CA91L8200B [Dual PCI PowerSpan II] pci:v000010E3d00008261* ID_MODEL_FROM_DATABASE=CA91L8260B [Single PCI PowerSpan II] pci:v000010E3d0000A108* ID_MODEL_FROM_DATABASE=Tsi109 Host Bridge for Dual PowerPC pci:v000010E4* ID_VENDOR_FROM_DATABASE=Tandem Computers pci:v000010E4d00008029* ID_MODEL_FROM_DATABASE=Realtek 8029 Network Card pci:v000010E5* ID_VENDOR_FROM_DATABASE=Micro Industries Corporation pci:v000010E6* ID_VENDOR_FROM_DATABASE=Gainbery Computer Products Inc. pci:v000010E7* ID_VENDOR_FROM_DATABASE=Vadem pci:v000010E8* ID_VENDOR_FROM_DATABASE=Applied Micro Circuits Corp. pci:v000010E8d00001072* ID_MODEL_FROM_DATABASE=INES GPIB-PCI (AMCC5920 based) pci:v000010E8d00002011* ID_MODEL_FROM_DATABASE=Q-Motion Video Capture/Edit board pci:v000010E8d00004750* ID_MODEL_FROM_DATABASE=S5930 [Matchmaker] pci:v000010E8d00005920* ID_MODEL_FROM_DATABASE=S5920 pci:v000010E8d00008043* ID_MODEL_FROM_DATABASE=LANai4.x [Myrinet LANai interface chip] pci:v000010E8d00008062* ID_MODEL_FROM_DATABASE=S5933_PARASTATION pci:v000010E8d0000807D* ID_MODEL_FROM_DATABASE=S5933 [Matchmaker] pci:v000010E8d00008088* ID_MODEL_FROM_DATABASE=Kongsberg Spacetec Format Synchronizer pci:v000010E8d00008089* ID_MODEL_FROM_DATABASE=Kongsberg Spacetec Serial Output Board pci:v000010E8d0000809C* ID_MODEL_FROM_DATABASE=S5933_HEPC3 pci:v000010E8d000080B9* ID_MODEL_FROM_DATABASE=Harmonix Hi-Card P8 (4x active ISDN BRI) pci:v000010E8d000080D7* ID_MODEL_FROM_DATABASE=PCI-9112 pci:v000010E8d000080D8* ID_MODEL_FROM_DATABASE=PCI-7200 pci:v000010E8d000080D9* ID_MODEL_FROM_DATABASE=PCI-9118 pci:v000010E8d000080DA* ID_MODEL_FROM_DATABASE=PCI-9812 pci:v000010E8d000080FC* ID_MODEL_FROM_DATABASE=APCI1500 Signal processing controller (16 dig. inputs + 16 dig. outputs) pci:v000010E8d0000811A* ID_MODEL_FROM_DATABASE=PCI-IEEE1355-DS-DE Interface pci:v000010E8d0000814C* ID_MODEL_FROM_DATABASE=Fastcom ESCC-PCI (Commtech, Inc.) pci:v000010E8d00008170* ID_MODEL_FROM_DATABASE=S5933 [Matchmaker] (Chipset Development Tool) pci:v000010E8d000081E6* ID_MODEL_FROM_DATABASE=Multimedia video controller pci:v000010E8d0000828D* ID_MODEL_FROM_DATABASE=APCI3001 Signal processing controller (up to 16 analog inputs) pci:v000010E8d00008291* ID_MODEL_FROM_DATABASE=Fastcom 232/8-PCI (Commtech, Inc.) pci:v000010E8d000082C4* ID_MODEL_FROM_DATABASE=Fastcom 422/4-PCI (Commtech, Inc.) pci:v000010E8d000082C5* ID_MODEL_FROM_DATABASE=Fastcom 422/2-PCI (Commtech, Inc.) pci:v000010E8d000082C6* ID_MODEL_FROM_DATABASE=Fastcom IG422/1-PCI (Commtech, Inc.) pci:v000010E8d000082C7* ID_MODEL_FROM_DATABASE=Fastcom IG232/2-PCI (Commtech, Inc.) pci:v000010E8d000082CA* ID_MODEL_FROM_DATABASE=Fastcom 232/4-PCI (Commtech, Inc.) pci:v000010E8d000082DB* ID_MODEL_FROM_DATABASE=AJA HDNTV HD SDI Framestore pci:v000010E8d000082E2* ID_MODEL_FROM_DATABASE=Fastcom DIO24H-PCI (Commtech, Inc.) pci:v000010E8d00008406* ID_MODEL_FROM_DATABASE=PCIcanx/PCIcan CAN interface [Kvaser AB] pci:v000010E8d00008407* ID_MODEL_FROM_DATABASE=PCIcan II CAN interface (A1021, PCB-07, PCB-08) [Kvaser AB] pci:v000010E8d00008851* ID_MODEL_FROM_DATABASE=S5933 on Innes Corp FM Radio Capture card pci:v000010E8d0000E004* ID_MODEL_FROM_DATABASE=X-Gene PCIe bridge pci:v000010E9* ID_VENDOR_FROM_DATABASE=Alps Electric Co., Ltd. pci:v000010EA* ID_VENDOR_FROM_DATABASE=Integraphics pci:v000010EAd00001680* ID_MODEL_FROM_DATABASE=IGA-1680 pci:v000010EAd00001682* ID_MODEL_FROM_DATABASE=IGA-1682 pci:v000010EAd00001683* ID_MODEL_FROM_DATABASE=IGA-1683 pci:v000010EAd00002000* ID_MODEL_FROM_DATABASE=CyberPro 2000 pci:v000010EAd00002010* ID_MODEL_FROM_DATABASE=CyberPro 2000A pci:v000010EAd00005000* ID_MODEL_FROM_DATABASE=CyberPro 5000 pci:v000010EAd00005050* ID_MODEL_FROM_DATABASE=CyberPro 5050 pci:v000010EAd00005202* ID_MODEL_FROM_DATABASE=CyberPro 5202 pci:v000010EAd00005252* ID_MODEL_FROM_DATABASE=CyberPro5252 pci:v000010EB* ID_VENDOR_FROM_DATABASE=Artists Graphics pci:v000010EBd00000101* ID_MODEL_FROM_DATABASE=3GA pci:v000010EBd00008111* ID_MODEL_FROM_DATABASE=Twist3 Frame Grabber pci:v000010EC* ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Co., Ltd. pci:v000010ECd00000139* ID_MODEL_FROM_DATABASE=RTL-8139/8139C/8139C+ Ethernet Controller pci:v000010ECd00005208* ID_MODEL_FROM_DATABASE=RTS5208 PCI Express Card Reader pci:v000010ECd00005209* ID_MODEL_FROM_DATABASE=RTS5209 PCI Express Card Reader pci:v000010ECd00005227* ID_MODEL_FROM_DATABASE=RTS5227 PCI Express Card Reader pci:v000010ECd00005227sv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=RTS5227 PCI Express Card Reader (ThinkPad T440p) pci:v000010ECd00005227sv000017AAsd00002214* ID_MODEL_FROM_DATABASE=RTS5227 PCI Express Card Reader (ThinkPad X240) pci:v000010ECd00005229* ID_MODEL_FROM_DATABASE=RTS5229 PCI Express Card Reader pci:v000010ECd00005229sv00001025sd00000813* ID_MODEL_FROM_DATABASE=RTS5229 PCI Express Card Reader (Aspire R7-571) pci:v000010ECd00005229sv0000103Csd0000194E* ID_MODEL_FROM_DATABASE=RTS5229 PCI Express Card Reader (ProBook 455 G1 Notebook) pci:v000010ECd00005229sv0000103Csd00001985* ID_MODEL_FROM_DATABASE=RTS5229 PCI Express Card Reader (Pavilion 17-e163sg Notebook PC) pci:v000010ECd0000522A* ID_MODEL_FROM_DATABASE=RTS522A PCI Express Card Reader pci:v000010ECd00005249* ID_MODEL_FROM_DATABASE=RTS5249 PCI Express Card Reader pci:v000010ECd00005249sv0000103Csd00001909* ID_MODEL_FROM_DATABASE=RTS5249 PCI Express Card Reader (ZBook 15) pci:v000010ECd0000524A* ID_MODEL_FROM_DATABASE=RTS524A PCI Express Card Reader pci:v000010ECd00005250* ID_MODEL_FROM_DATABASE=RTS5250 PCI Express Card Reader pci:v000010ECd0000525A* ID_MODEL_FROM_DATABASE=RTS525A PCI Express Card Reader pci:v000010ECd00005286* ID_MODEL_FROM_DATABASE=RTS5286 PCI Express Card Reader pci:v000010ECd00005288* ID_MODEL_FROM_DATABASE=RTS5288 PCI Express Card Reader pci:v000010ECd00005289* ID_MODEL_FROM_DATABASE=RTL8411 PCI Express Card Reader pci:v000010ECd00005289sv00001043sd00001457* ID_MODEL_FROM_DATABASE=RTL8411 PCI Express Card Reader (K55A Laptop) pci:v000010ECd00008029* ID_MODEL_FROM_DATABASE=RTL-8029(AS) pci:v000010ECd00008029sv000010B8sd00002011* ID_MODEL_FROM_DATABASE=RTL-8029(AS) (EZ-Card (SMC1208)) pci:v000010ECd00008029sv000010ECsd00008029* ID_MODEL_FROM_DATABASE=RTL-8029(AS) pci:v000010ECd00008029sv00001113sd00001208* ID_MODEL_FROM_DATABASE=RTL-8029(AS) (EN1208) pci:v000010ECd00008029sv00001186sd00000300* ID_MODEL_FROM_DATABASE=RTL-8029(AS) (DE-528) pci:v000010ECd00008029sv00001259sd00002400* ID_MODEL_FROM_DATABASE=RTL-8029(AS) (AT-2400) pci:v000010ECd00008029sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=RTL-8029(AS) (QEMU Virtual Machine) pci:v000010ECd00008129* ID_MODEL_FROM_DATABASE=RTL-8129 pci:v000010ECd00008129sv000010ECsd00008129* ID_MODEL_FROM_DATABASE=RTL-8129 (RT8129 Fast Ethernet Adapter) pci:v000010ECd00008129sv000011ECsd00008129* ID_MODEL_FROM_DATABASE=RTL-8129 (RTL8111/8168 PCIe Gigabit Ethernet (misconfigured)) pci:v000010ECd00008136* ID_MODEL_FROM_DATABASE=RTL8101/2/6E PCI Express Fast/Gigabit Ethernet controller pci:v000010ECd00008136sv0000103Csd00001985* ID_MODEL_FROM_DATABASE=RTL8101/2/6E PCI Express Fast/Gigabit Ethernet controller (Pavilion 17-e163sg Notebook PC) pci:v000010ECd00008136sv0000103Csd00002AB1* ID_MODEL_FROM_DATABASE=RTL8101/2/6E PCI Express Fast/Gigabit Ethernet controller (Pavilion p6774) pci:v000010ECd00008136sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=RTL8101/2/6E PCI Express Fast/Gigabit Ethernet controller (Pavilion dv6700) pci:v000010ECd00008136sv00001179sd0000FF64* ID_MODEL_FROM_DATABASE=RTL8101/2/6E PCI Express Fast/Gigabit Ethernet controller (RTL8102E PCI-E Fast Ethernet NIC) pci:v000010ECd00008136sv000017C0sd00001053* ID_MODEL_FROM_DATABASE=RTL8101/2/6E PCI Express Fast/Gigabit Ethernet controller (RTL8101e Medion WIM 2210 Notebook PC [MD96850]) pci:v000010ECd00008138* ID_MODEL_FROM_DATABASE=RT8139 (B/C) Cardbus Fast Ethernet Adapter pci:v000010ECd00008138sv000010ECsd00008138* ID_MODEL_FROM_DATABASE=RT8139 (B/C) Cardbus Fast Ethernet Adapter (RT8139 (B/C) Fast Ethernet Adapter) pci:v000010ECd00008139* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter pci:v000010ECd00008139sv00000357sd0000000A* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (TTP-Monitoring Card V2.0) pci:v000010ECd00008139sv00001025sd0000005A* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (TravelMate 290) pci:v000010ECd00008139sv00001025sd00008920* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (ALN-325) pci:v000010ECd00008139sv00001025sd00008921* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (ALN-325) pci:v000010ECd00008139sv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (NX9500) pci:v000010ECd00008139sv0000103Csd00002A20* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (Pavilion t3030.de Desktop PC) pci:v000010ECd00008139sv0000103Csd000030D9* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (Presario C700) pci:v000010ECd00008139sv00001043sd00001045* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (L8400B or L3C/S notebook) pci:v000010ECd00008139sv00001043sd00008109* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (P5P800-MX Mainboard) pci:v000010ECd00008139sv00001071sd00008160* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (MIM2000) pci:v000010ECd00008139sv000010BDsd00000320* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (EP-320X-R) pci:v000010ECd00008139sv000010ECsd00008139* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter pci:v000010ECd00008139sv000010F7sd00008338* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (Panasonic CF-Y5 laptop) pci:v000010ECd00008139sv00001113sd0000EC01* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (LevelOne FNC-0107TX/FNC-0109TX) pci:v000010ECd00008139sv00001186sd00001104* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (DFE-520TX Fast Ethernet PCI Adapter (rev. D1)) pci:v000010ECd00008139sv00001186sd00001300* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (DFE-538TX) pci:v000010ECd00008139sv00001186sd00001320* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (SN5200) pci:v000010ECd00008139sv00001186sd00008139* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (DRN-32TX) pci:v000010ECd00008139sv000011F6sd00008139* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (FN22-3(A) LinxPRO Ethernet Adapter) pci:v000010ECd00008139sv00001259sd00002500* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (AT-2500TX) pci:v000010ECd00008139sv00001259sd00002503* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (AT-2500TX/ACPI) pci:v000010ECd00008139sv00001385sd0000F31D* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (FA311 v2) pci:v000010ECd00008139sv00001395sd00002100* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (AMB2100) pci:v000010ECd00008139sv00001429sd0000D010* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (ND010/ND012) pci:v000010ECd00008139sv00001432sd00009130* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (EN-9130TX) pci:v000010ECd00008139sv00001436sd00008139* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (RT8139) pci:v000010ECd00008139sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (P30/P35 notebook) pci:v000010ECd00008139sv00001458sd0000E000* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (GA-7VM400M/7VT600 Motherboard) pci:v000010ECd00008139sv00001462sd00000131* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (MS-1013 Notebook) pci:v000010ECd00008139sv00001462sd0000217C* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (Aspire L250) pci:v000010ECd00008139sv00001462sd0000788C* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (865PE Neo2-V Mainboard) pci:v000010ECd00008139sv0000146Csd00001439* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (FE-1439TX) pci:v000010ECd00008139sv00001489sd00006001* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (GF100TXRII) pci:v000010ECd00008139sv00001489sd00006002* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (GF100TXRA) pci:v000010ECd00008139sv0000149Csd0000139A* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (LFE-8139ATX) pci:v000010ECd00008139sv0000149Csd00008139* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (LFE-8139TX) pci:v000010ECd00008139sv000014CBsd00000200* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (LNR-100 Family 10/100 Base-TX Ethernet) pci:v000010ECd00008139sv00001565sd00002300* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (P4TSV Onboard LAN (RTL8100B)) pci:v000010ECd00008139sv00001631sd00007003* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (Onboard RTL8111 on GA-8SIML Rev1.0 Mainboard) pci:v000010ECd00008139sv00001695sd00009001* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (Onboard RTL8101L 10/100 MBit) pci:v000010ECd00008139sv000016ECsd000000FF* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (USR997900A) pci:v000010ECd00008139sv00001799sd00005000* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (F5D5000 PCI Card/Desktop Network PCI Card) pci:v000010ECd00008139sv00001799sd00005010* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (F5D5010 CardBus Notebook Network Card) pci:v000010ECd00008139sv0000187Esd00003303* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (FN312) pci:v000010ECd00008139sv00001904sd00008139* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (RTL8139D Fast Ethernet Adapter) pci:v000010ECd00008139sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (QEMU Virtual Machine) pci:v000010ECd00008139sv00002646sd00000001* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (KNE120TX) pci:v000010ECd00008139sv00008E2Esd00007000* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (KF-230TX) pci:v000010ECd00008139sv00008E2Esd00007100* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (KF-230TX/2) pci:v000010ECd00008139sv0000A0A0sd00000007* ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (ALN-325C) pci:v000010ECd00008167* ID_MODEL_FROM_DATABASE=RTL-8110SC/8169SC Gigabit Ethernet pci:v000010ECd00008167sv00001458sd0000E000* ID_MODEL_FROM_DATABASE=RTL-8110SC/8169SC Gigabit Ethernet (GA-MA69G-S3H Motherboard) pci:v000010ECd00008167sv00001462sd0000235C* ID_MODEL_FROM_DATABASE=RTL-8110SC/8169SC Gigabit Ethernet (P965 Neo MS-7235 mainboard) pci:v000010ECd00008167sv00001462sd0000236C* ID_MODEL_FROM_DATABASE=RTL-8110SC/8169SC Gigabit Ethernet (945P Neo3-F motherboard) pci:v000010ECd00008168* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller pci:v000010ECd00008168sv00001019sd00008168* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (RTL8111/8168 PCI Express Gigabit Ethernet controller) pci:v000010ECd00008168sv00001028sd00000283* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Vostro 220) pci:v000010ECd00008168sv00001028sd000004B2* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Vostro 3350) pci:v000010ECd00008168sv00001028sd000004DA* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Vostro 3750) pci:v000010ECd00008168sv0000103Csd00001611* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Pavilion DM1Z-3000) pci:v000010ECd00008168sv0000103Csd00001950* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (ProBook 450/455) pci:v000010ECd00008168sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Asus IPIBL-LB Motherboard) pci:v000010ECd00008168sv00001043sd000011F5* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (A6J-Q008) pci:v000010ECd00008168sv00001043sd000016D5* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (U6V/U31J laptop) pci:v000010ECd00008168sv00001043sd000081AA* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (P5B) pci:v000010ECd00008168sv00001043sd000082C6* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (M3A78 Series Motherboard) pci:v000010ECd00008168sv00001043sd000083A3* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (M4A785TD Motherboard) pci:v000010ECd00008168sv00001043sd00008432* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (P8P67 and other motherboards) pci:v000010ECd00008168sv00001043sd00008505* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (P8 series motherboard) pci:v000010ECd00008168sv0000105Bsd00000D7C* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (D270S/D250S Motherboard) pci:v000010ECd00008168sv000010ECsd00008168* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (RTL8111/8168 PCI Express Gigabit Ethernet controller) pci:v000010ECd00008168sv00001458sd0000E000* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Motherboard) pci:v000010ECd00008168sv00001462sd0000238C* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Onboard RTL8111b on MSI P965 Platinum Mainboard) pci:v000010ECd00008168sv00001462sd0000368C* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (K9AG Neo2) pci:v000010ECd00008168sv00001462sd00004180* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Wind PC MS-7418) pci:v000010ECd00008168sv00001462sd00007522* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (X58 Pro-E) pci:v000010ECd00008168sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (CC11/CL11) pci:v000010ECd00008168sv00001849sd00008168* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Motherboard (one of many)) pci:v000010ECd00008168sv00007470sd00003468* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (TG-3468 Gigabit PCI Express Network Adapter) pci:v000010ECd00008168sv00008086sd0000D615* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Desktop Board D510MO/D525MW) pci:v000010ECd00008169* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller pci:v000010ECd00008169sv00001025sd00000079* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (Aspire 5024WLMi) pci:v000010ECd00008169sv000010BDsd00003202* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (EP-320G-TX1 32-bit PCI Gigabit Ethernet Adapter) pci:v000010ECd00008169sv000010ECsd00008169* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (RTL8169/8110 Family PCI Gigabit Ethernet NIC) pci:v000010ECd00008169sv00001259sd0000C107* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (CG-LAPCIGT) pci:v000010ECd00008169sv00001371sd0000434E* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (ProG-2000L) pci:v000010ECd00008169sv00001385sd0000311A* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (GA311) pci:v000010ECd00008169sv00001385sd00005200* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (GA511 Gigabit PC Card) pci:v000010ECd00008169sv00001458sd0000E000* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (GA-8I915ME-G Mainboard) pci:v000010ECd00008169sv00001462sd0000030C* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (K8N Neo-FSR v2.0 mainboard) pci:v000010ECd00008169sv00001462sd0000065C* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (Hetis 865GV-E (MS-7065)) pci:v000010ECd00008169sv00001462sd0000702C* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (K8T NEO 2 motherboard) pci:v000010ECd00008169sv00001462sd00007094* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (K8T Neo2-F V2.0) pci:v000010ECd00008169sv000016ECsd0000011F* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (USR997903) pci:v000010ECd00008169sv00001734sd00001091* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (D2030-A1) pci:v000010ECd00008169sv0000A0A0sd00000449* ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (AK86-L motherboard) pci:v000010ECd00008171* ID_MODEL_FROM_DATABASE=RTL8191SEvA Wireless LAN Controller pci:v000010ECd00008172* ID_MODEL_FROM_DATABASE=RTL8191SEvB Wireless LAN Controller pci:v000010ECd00008173* ID_MODEL_FROM_DATABASE=RTL8192SE Wireless LAN Controller pci:v000010ECd00008174* ID_MODEL_FROM_DATABASE=RTL8192SE Wireless LAN Controller pci:v000010ECd00008176* ID_MODEL_FROM_DATABASE=RTL8188CE 802.11b/g/n WiFi Adapter pci:v000010ECd00008176sv00001A3Bsd00001139* ID_MODEL_FROM_DATABASE=RTL8188CE 802.11b/g/n WiFi Adapter (AW-NE139H Half-size Mini PCIe Card) pci:v000010ECd00008177* ID_MODEL_FROM_DATABASE=RTL8191CE PCIe Wireless Network Adapter pci:v000010ECd00008178* ID_MODEL_FROM_DATABASE=RTL8192CE PCIe Wireless Network Adapter pci:v000010ECd00008179* ID_MODEL_FROM_DATABASE=RTL8188EE Wireless Network Adapter pci:v000010ECd00008180* ID_MODEL_FROM_DATABASE=RTL8180L 802.11b MAC pci:v000010ECd00008180sv00001385sd00004700* ID_MODEL_FROM_DATABASE=RTL8180L 802.11b MAC (MA521 802.11b Wireless PC Card) pci:v000010ECd00008180sv00001737sd00000019* ID_MODEL_FROM_DATABASE=RTL8180L 802.11b MAC (WPC11v4 802.11b Wireless-B Notebook Adapter) pci:v000010ECd00008185* ID_MODEL_FROM_DATABASE=RTL-8185 IEEE 802.11a/b/g Wireless LAN Controller pci:v000010ECd0000818B* ID_MODEL_FROM_DATABASE=RTL8192EE PCIe Wireless Network Adapter pci:v000010ECd00008190* ID_MODEL_FROM_DATABASE=RTL8190 802.11n PCI Wireless Network Adapter pci:v000010ECd00008191* ID_MODEL_FROM_DATABASE=RTL8192CE PCIe Wireless Network Adapter pci:v000010ECd00008192* ID_MODEL_FROM_DATABASE=RTL8192E/RTL8192SE Wireless LAN Controller pci:v000010ECd00008193* ID_MODEL_FROM_DATABASE=RTL8192DE Wireless LAN Controller pci:v000010ECd00008197* ID_MODEL_FROM_DATABASE=SmartLAN56 56K Modem pci:v000010ECd00008199* ID_MODEL_FROM_DATABASE=RTL8187SE Wireless LAN Controller pci:v000010ECd00008199sv00001462sd00006894* ID_MODEL_FROM_DATABASE=RTL8187SE Wireless LAN Controller (MN54G2 / MS-6894 Wireless Mini PCIe Card) pci:v000010ECd00008723* ID_MODEL_FROM_DATABASE=RTL8723AE PCIe Wireless Network Adapter pci:v000010ECd00008812* ID_MODEL_FROM_DATABASE=RTL8812AE 802.11ac PCIe Wireless Network Adapter pci:v000010ECd00008813* ID_MODEL_FROM_DATABASE=RTL8813AE 802.11ac PCIe Wireless Network Adapter pci:v000010ECd00008821* ID_MODEL_FROM_DATABASE=RTL8821AE 802.11ac PCIe Wireless Network Adapter pci:v000010ECd0000B723* ID_MODEL_FROM_DATABASE=RTL8723BE PCIe Wireless Network Adapter pci:v000010ED* ID_VENDOR_FROM_DATABASE=Ascii Corporation pci:v000010EDd00007310* ID_MODEL_FROM_DATABASE=V7310 pci:v000010EE* ID_VENDOR_FROM_DATABASE=Xilinx Corporation pci:v000010EEd00000001* ID_MODEL_FROM_DATABASE=EUROCOM for PCI (ECOMP) pci:v000010EEd00000002* ID_MODEL_FROM_DATABASE=Octal E1/T1 for PCI ETP Card pci:v000010EEd00000007* ID_MODEL_FROM_DATABASE=Default PCIe endpoint ID pci:v000010EEd00000205* ID_MODEL_FROM_DATABASE=Wildcard TE205P pci:v000010EEd00000210* ID_MODEL_FROM_DATABASE=Wildcard TE210P pci:v000010EEd00000300* ID_MODEL_FROM_DATABASE=Spartan 3 Designs (Xilinx IP) pci:v000010EEd00000314* ID_MODEL_FROM_DATABASE=Wildcard TE405P/TE410P (1st Gen) pci:v000010EEd00000405* ID_MODEL_FROM_DATABASE=Wildcard TE405P (2nd Gen) pci:v000010EEd00000410* ID_MODEL_FROM_DATABASE=Wildcard TE410P (2nd Gen) pci:v000010EEd00000600* ID_MODEL_FROM_DATABASE=Xilinx 6 Designs (Xilinx IP) pci:v000010EEd00003FC0* ID_MODEL_FROM_DATABASE=RME Digi96 pci:v000010EEd00003FC1* ID_MODEL_FROM_DATABASE=RME Digi96/8 pci:v000010EEd00003FC2* ID_MODEL_FROM_DATABASE=RME Digi96/8 Pro pci:v000010EEd00003FC3* ID_MODEL_FROM_DATABASE=RME Digi96/8 Pad pci:v000010EEd00003FC4* ID_MODEL_FROM_DATABASE=RME Digi9652 (Hammerfall) pci:v000010EEd00003FC5* ID_MODEL_FROM_DATABASE=RME Hammerfall DSP pci:v000010EEd00003FC6* ID_MODEL_FROM_DATABASE=RME Hammerfall DSP MADI pci:v000010EEd00008380* ID_MODEL_FROM_DATABASE=Ellips ProfiXpress Profibus Master pci:v000010EEd00008381* ID_MODEL_FROM_DATABASE=Ellips Santos Frame Grabber pci:v000010EEd0000D154* ID_MODEL_FROM_DATABASE=Copley Controls CAN card (PCI-CAN-02) pci:v000010EEd0000EBF0* ID_MODEL_FROM_DATABASE=SED Systems Modulator/Demodulator pci:v000010EEd0000EBF1* ID_MODEL_FROM_DATABASE=SED Systems Audio Interface Card pci:v000010EEd0000EBF2* ID_MODEL_FROM_DATABASE=SED Systems Common PCI Interface pci:v000010EF* ID_VENDOR_FROM_DATABASE=Racore Computer Products, Inc. pci:v000010EFd00008154* ID_MODEL_FROM_DATABASE=M815x Token Ring Adapter pci:v000010F0* ID_VENDOR_FROM_DATABASE=Peritek Corporation pci:v000010F1* ID_VENDOR_FROM_DATABASE=Tyan Computer pci:v000010F1d00002865* ID_MODEL_FROM_DATABASE=Tyan Thunder K8E S2865 pci:v000010F1d00005300* ID_MODEL_FROM_DATABASE=Tyan S5380 Mainboard pci:v000010F2* ID_VENDOR_FROM_DATABASE=Achme Computer, Inc. pci:v000010F3* ID_VENDOR_FROM_DATABASE=Alaris, Inc. pci:v000010F4* ID_VENDOR_FROM_DATABASE=S-MOS Systems, Inc. pci:v000010F5* ID_VENDOR_FROM_DATABASE=NKK Corporation pci:v000010F5d0000A001* ID_MODEL_FROM_DATABASE=NDR4000 [NR4600 Bridge] pci:v000010F6* ID_VENDOR_FROM_DATABASE=Creative Electronic Systems SA pci:v000010F7* ID_VENDOR_FROM_DATABASE=Matsushita Electric Industrial Co., Ltd. pci:v000010F8* ID_VENDOR_FROM_DATABASE=Altos India Ltd pci:v000010F9* ID_VENDOR_FROM_DATABASE=PC Direct pci:v000010FA* ID_VENDOR_FROM_DATABASE=Truevision pci:v000010FAd0000000C* ID_MODEL_FROM_DATABASE=TARGA 1000 pci:v000010FB* ID_VENDOR_FROM_DATABASE=Thesys Gesellschaft fuer Mikroelektronik mbH pci:v000010FBd0000186F* ID_MODEL_FROM_DATABASE=TH 6255 pci:v000010FC* ID_VENDOR_FROM_DATABASE=I-O Data Device, Inc. pci:v000010FCd00000003* ID_MODEL_FROM_DATABASE=Cardbus IDE Controller pci:v000010FCd00000005* ID_MODEL_FROM_DATABASE=Cardbus SCSI CBSC II pci:v000010FD* ID_VENDOR_FROM_DATABASE=Soyo Computer, Inc pci:v000010FE* ID_VENDOR_FROM_DATABASE=Fast Multimedia AG pci:v000010FF* ID_VENDOR_FROM_DATABASE=NCube pci:v00001100* ID_VENDOR_FROM_DATABASE=Jazz Multimedia pci:v00001101* ID_VENDOR_FROM_DATABASE=Initio Corporation pci:v00001101d00000002* ID_MODEL_FROM_DATABASE=INI-920 Ultra SCSI Adapter pci:v00001101d00001060* ID_MODEL_FROM_DATABASE=INI-A100U2W pci:v00001101d00001622* ID_MODEL_FROM_DATABASE=INI-1623 PCI SATA-II Controller pci:v00001101d00009100* ID_MODEL_FROM_DATABASE=INI-9100/9100W pci:v00001101d00009400* ID_MODEL_FROM_DATABASE=INI-940 Fast Wide SCSI Adapter pci:v00001101d00009401* ID_MODEL_FROM_DATABASE=INI-935 Fast Wide SCSI Adapter pci:v00001101d00009500* ID_MODEL_FROM_DATABASE=INI-950 SCSI Adapter pci:v00001101d00009502* ID_MODEL_FROM_DATABASE=INI-950P Ultra Wide SCSI Adapter pci:v00001102* ID_VENDOR_FROM_DATABASE=Creative Labs pci:v00001102d00000002* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 pci:v00001102d00000002sv0000100Asd00001102* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (SB Live! 5.1 Digital OEM SB0220 EMU10K1-JFF) pci:v00001102d00000002sv00001102sd00000020* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (CT4850 SBLive! Value) pci:v00001102d00000002sv00001102sd00000021* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (CT4620 SBLive!) pci:v00001102d00000002sv00001102sd0000002F* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (SBLive! mainboard implementation) pci:v00001102d00000002sv00001102sd0000100A* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (SB Live! 5.1 Digital OEM [SB0220]) pci:v00001102d00000002sv00001102sd00004001* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (E-mu APS) pci:v00001102d00000002sv00001102sd00008022* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (CT4780 SBLive! Value) pci:v00001102d00000002sv00001102sd00008023* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (CT4790 SoundBlaster PCI512) pci:v00001102d00000002sv00001102sd00008024* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (CT4760 SBLive!) pci:v00001102d00000002sv00001102sd00008025* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (SBLive! Mainboard Implementation) pci:v00001102d00000002sv00001102sd00008026* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (CT4830 SBLive! Value) pci:v00001102d00000002sv00001102sd00008027* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (CT4832 SBLive! Value) pci:v00001102d00000002sv00001102sd00008028* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (CT4760 SBLive! OEM version) pci:v00001102d00000002sv00001102sd00008031* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (CT4831 SBLive! Value) pci:v00001102d00000002sv00001102sd00008040* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (CT4760 SBLive!) pci:v00001102d00000002sv00001102sd00008051* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (CT4850 SBLive! Value) pci:v00001102d00000002sv00001102sd00008061* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (SBLive! Player 5.1) pci:v00001102d00000002sv00001102sd00008064* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (SBLive! 5.1 Model SB0100) pci:v00001102d00000002sv00001102sd00008065* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (SBLive! 5.1 Digital Model SB0220) pci:v00001102d00000002sv00001102sd00008066* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (Live! 5.1 Digital [SB0228]) pci:v00001102d00000002sv00001102sd00008067* ID_MODEL_FROM_DATABASE=SB Live! EMU10k1 (SBLive! 5.1 eMicro 28028) pci:v00001102d00000004* ID_MODEL_FROM_DATABASE=SB Audigy pci:v00001102d00000004sv00001102sd00000051* ID_MODEL_FROM_DATABASE=SB Audigy (SB0090 Audigy Player) pci:v00001102d00000004sv00001102sd00000053* ID_MODEL_FROM_DATABASE=SB Audigy (SB0090 Audigy Player/OEM) pci:v00001102d00000004sv00001102sd00000058* ID_MODEL_FROM_DATABASE=SB Audigy (SB0090 Audigy Player/OEM) pci:v00001102d00000004sv00001102sd00001002* ID_MODEL_FROM_DATABASE=SB Audigy (2 Platinum) pci:v00001102d00000004sv00001102sd00001003* ID_MODEL_FROM_DATABASE=SB Audigy (SB0350 Audigy 2) pci:v00001102d00000004sv00001102sd00001007* ID_MODEL_FROM_DATABASE=SB Audigy (SB0240 Audigy 2 Platinum 6.1) pci:v00001102d00000004sv00001102sd00001009* ID_MODEL_FROM_DATABASE=SB Audigy (2 OEM HP) pci:v00001102d00000004sv00001102sd00002001* ID_MODEL_FROM_DATABASE=SB Audigy (2 ZS Platinum Pro) pci:v00001102d00000004sv00001102sd00002002* ID_MODEL_FROM_DATABASE=SB Audigy (2 ZS (SB0350)) pci:v00001102d00000004sv00001102sd00004001* ID_MODEL_FROM_DATABASE=SB Audigy (E-MU 1010) pci:v00001102d00000004sv00001102sd00004002* ID_MODEL_FROM_DATABASE=SB Audigy (E-MU 0404) pci:v00001102d00000005* ID_MODEL_FROM_DATABASE=SB X-Fi pci:v00001102d00000005sv00001102sd00000021* ID_MODEL_FROM_DATABASE=SB X-Fi (X-Fi Platinum) pci:v00001102d00000005sv00001102sd0000002C* ID_MODEL_FROM_DATABASE=SB X-Fi (X-Fi XtremeGamer FATAL1TY PRO) pci:v00001102d00000005sv00001102sd00001003* ID_MODEL_FROM_DATABASE=SB X-Fi (X-Fi XtremeMusic) pci:v00001102d00000006* ID_MODEL_FROM_DATABASE=[SB Live! Value] EMU10k1X pci:v00001102d00000007* ID_MODEL_FROM_DATABASE=CA0106 Soundblaster pci:v00001102d00000007sv00001102sd00000007* ID_MODEL_FROM_DATABASE=CA0106 Soundblaster (SBLive! 24bit) pci:v00001102d00000007sv00001102sd00001001* ID_MODEL_FROM_DATABASE=CA0106 Soundblaster (SB0310 Audigy LS) pci:v00001102d00000007sv00001102sd00001002* ID_MODEL_FROM_DATABASE=CA0106 Soundblaster (SB0312 Audigy LS) pci:v00001102d00000007sv00001102sd00001006* ID_MODEL_FROM_DATABASE=CA0106 Soundblaster (SB0410 SBLive! 24-bit) pci:v00001102d00000007sv00001102sd0000100A* ID_MODEL_FROM_DATABASE=CA0106 Soundblaster (SB0570 [SB Audigy SE]) pci:v00001102d00000007sv00001102sd00001012* ID_MODEL_FROM_DATABASE=CA0106 Soundblaster (SB0790 X-Fi XA) pci:v00001102d00000007sv00001102sd00001013* ID_MODEL_FROM_DATABASE=CA0106 Soundblaster (Soundblaster X-Fi Xtreme Audio) pci:v00001102d00000007sv00001462sd00001009* ID_MODEL_FROM_DATABASE=CA0106 Soundblaster (K8N Diamond) pci:v00001102d00000008* ID_MODEL_FROM_DATABASE=SB0400 Audigy2 Value pci:v00001102d00000008sv00001102sd00000008* ID_MODEL_FROM_DATABASE=SB0400 Audigy2 Value (EMU0404 Digital Audio System) pci:v00001102d00000008sv00001102sd00004004* ID_MODEL_FROM_DATABASE=SB0400 Audigy2 Value (EMU1010 Digital Audio System [MAEM8960]) pci:v00001102d00000009* ID_MODEL_FROM_DATABASE=[SB X-Fi Xtreme Audio] CA0110-IBG pci:v00001102d00000009sv00001102sd00000010* ID_MODEL_FROM_DATABASE=[SB X-Fi Xtreme Audio] CA0110-IBG pci:v00001102d00000009sv00001102sd00000018* ID_MODEL_FROM_DATABASE=[SB X-Fi Xtreme Audio] CA0110-IBG (SB1040) pci:v00001102d0000000B* ID_MODEL_FROM_DATABASE=EMU20k2 [X-Fi Titanium Series] pci:v00001102d0000000Bsv00001102sd00000041* ID_MODEL_FROM_DATABASE=EMU20k2 [X-Fi Titanium Series] (SB0880 [SoundBlaster X-Fi Titanium PCI-e]) pci:v00001102d00000012* ID_MODEL_FROM_DATABASE=SB Recon3D pci:v00001102d00004001* ID_MODEL_FROM_DATABASE=SB Audigy FireWire Port pci:v00001102d00004001sv00001102sd00000010* ID_MODEL_FROM_DATABASE=SB Audigy FireWire Port pci:v00001102d00007002* ID_MODEL_FROM_DATABASE=SB Live! Game Port pci:v00001102d00007002sv00001102sd00000020* ID_MODEL_FROM_DATABASE=SB Live! Game Port (Gameport Joystick) pci:v00001102d00007003* ID_MODEL_FROM_DATABASE=SB Audigy Game Port pci:v00001102d00007003sv00001102sd00000040* ID_MODEL_FROM_DATABASE=SB Audigy Game Port pci:v00001102d00007003sv00001102sd00000060* ID_MODEL_FROM_DATABASE=SB Audigy Game Port (SB Audigy2 MIDI/Game Port) pci:v00001102d00007004* ID_MODEL_FROM_DATABASE=[SB Live! Value] Input device controller pci:v00001102d00007005* ID_MODEL_FROM_DATABASE=SB Audigy LS Game Port pci:v00001102d00007005sv00001102sd00001001* ID_MODEL_FROM_DATABASE=SB Audigy LS Game Port (SB0310 Audigy LS MIDI/Game port) pci:v00001102d00007005sv00001102sd00001002* ID_MODEL_FROM_DATABASE=SB Audigy LS Game Port (SB0312 Audigy LS MIDI/Game port) pci:v00001102d00007006* ID_MODEL_FROM_DATABASE=[SB X-Fi Xtreme Audio] CA0110-IBG PCIe to PCI Bridge pci:v00001102d00008938* ID_MODEL_FROM_DATABASE=Ectiva EV1938 pci:v00001102d00008938sv00001033sd000080E5* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (SlimTower-Jim (NEC)) pci:v00001102d00008938sv00001071sd00007150* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (Mitac 7150) pci:v00001102d00008938sv0000110Asd00005938* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (Siemens Scenic Mobile 510PIII) pci:v00001102d00008938sv000013BDsd0000100C* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (Ceres-C (Sharp, Intel BX)) pci:v00001102d00008938sv000013BDsd0000100D* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (Sharp, Intel Banister) pci:v00001102d00008938sv000013BDsd0000100E* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (TwinHead P09S/P09S3 (Sharp)) pci:v00001102d00008938sv000013BDsd0000F6F1* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (Marlin (Sharp)) pci:v00001102d00008938sv000014FFsd00000E70* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (P88TE (TWINHEAD INTERNATIONAL Corp)) pci:v00001102d00008938sv000014FFsd0000C401* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (Notebook 9100/9200/2000 (TWINHEAD INTERNATIONAL Corp)) pci:v00001102d00008938sv0000156Dsd0000B400* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (G400 - Geo (AlphaTop (Taiwan))) pci:v00001102d00008938sv0000156Dsd0000B550* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (G560 (AlphaTop (Taiwan))) pci:v00001102d00008938sv0000156Dsd0000B560* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (G560 (AlphaTop (Taiwan))) pci:v00001102d00008938sv0000156Dsd0000B700* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (G700/U700 (AlphaTop (Taiwan))) pci:v00001102d00008938sv0000156Dsd0000B795* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (G795 (AlphaTop (Taiwan))) pci:v00001102d00008938sv0000156Dsd0000B797* ID_MODEL_FROM_DATABASE=Ectiva EV1938 (G797 (AlphaTop (Taiwan))) pci:v00001103* ID_VENDOR_FROM_DATABASE=HighPoint Technologies, Inc. pci:v00001103d00000003* ID_MODEL_FROM_DATABASE=HPT343/345/346/363 pci:v00001103d00000004* ID_MODEL_FROM_DATABASE=HPT366/368/370/370A/372/372N pci:v00001103d00000004sv00001103sd00000001* ID_MODEL_FROM_DATABASE=HPT366/368/370/370A/372/372N (HPT370A) pci:v00001103d00000004sv00001103sd00000004* ID_MODEL_FROM_DATABASE=HPT366/368/370/370A/372/372N (HPT366 UDMA66 (r1) / HPT368 UDMA66 (r2) / HPT370 UDMA100 (r3) / HPT370 UDMA100 RAID (r4)) pci:v00001103d00000004sv00001103sd00000005* ID_MODEL_FROM_DATABASE=HPT366/368/370/370A/372/372N (HPT370 UDMA100) pci:v00001103d00000004sv00001103sd00000006* ID_MODEL_FROM_DATABASE=HPT366/368/370/370A/372/372N (HPT302/302N) pci:v00001103d00000005* ID_MODEL_FROM_DATABASE=HPT372A/372N pci:v00001103d00000006* ID_MODEL_FROM_DATABASE=HPT302/302N pci:v00001103d00000007* ID_MODEL_FROM_DATABASE=HPT371/371N pci:v00001103d00000008* ID_MODEL_FROM_DATABASE=HPT374 pci:v00001103d00000009* ID_MODEL_FROM_DATABASE=HPT372N pci:v00001103d00000620* ID_MODEL_FROM_DATABASE=RocketRAID 620 2 Port SATA-III Controller pci:v00001103d00000622* ID_MODEL_FROM_DATABASE=RocketRAID 622 2 Port SATA-III Controller pci:v00001103d00000640* ID_MODEL_FROM_DATABASE=RocketRAID 640 4 Port SATA-III Controller pci:v00001103d00000641* ID_MODEL_FROM_DATABASE=RocketRAID 640L 4 Port SATA-III Controller pci:v00001103d00000642* ID_MODEL_FROM_DATABASE=RocketRAID 642L SATA-III Controller (2 eSATA ports + 2 internal SATA ports) pci:v00001103d00000644* ID_MODEL_FROM_DATABASE=RocketRAID 644 4 Port SATA-III Controller (eSATA) pci:v00001103d00000645* ID_MODEL_FROM_DATABASE=RocketRAID 644L 4 Port SATA-III Controller (eSATA) pci:v00001103d00000646* ID_MODEL_FROM_DATABASE=RocketRAID 644LS SATA-III Controller (4 eSATA devices connected by 1 SAS cable) pci:v00001103d00001720* ID_MODEL_FROM_DATABASE=RocketRAID 1720 (2x SATA II RAID Controller) pci:v00001103d00001740* ID_MODEL_FROM_DATABASE=RocketRAID 1740 pci:v00001103d00001742* ID_MODEL_FROM_DATABASE=RocketRAID 1742 pci:v00001103d00002210* ID_MODEL_FROM_DATABASE=RocketRAID 2210 SATA-II Controller pci:v00001103d00002210sv000011ABsd000011AB* ID_MODEL_FROM_DATABASE=RocketRAID 2210 SATA-II Controller (88SX6042) pci:v00001103d00002300* ID_MODEL_FROM_DATABASE=RocketRAID 230x 4 Port SATA-II Controller pci:v00001103d00002310* ID_MODEL_FROM_DATABASE=RocketRAID 2310 4 Port SATA-II Controller pci:v00001103d00002320* ID_MODEL_FROM_DATABASE=RocketRAID 2320 SATA-II Controller pci:v00001103d00002322* ID_MODEL_FROM_DATABASE=RocketRAID 2322 SATA-II Controller pci:v00001103d00002340* ID_MODEL_FROM_DATABASE=RocketRAID 2340 16 Port SATA-II Controller pci:v00001103d00002640* ID_MODEL_FROM_DATABASE=RocketRAID 2640 SAS/SATA Controller pci:v00001103d00002722* ID_MODEL_FROM_DATABASE=RocketRAID 2722 pci:v00001103d00002740* ID_MODEL_FROM_DATABASE=RocketRAID 2740 pci:v00001103d00002744* ID_MODEL_FROM_DATABASE=RocketRaid 2744 pci:v00001103d00002782* ID_MODEL_FROM_DATABASE=RocketRAID 2782 pci:v00001103d00003120* ID_MODEL_FROM_DATABASE=RocketRAID 3120 pci:v00001103d00003220* ID_MODEL_FROM_DATABASE=RocketRAID 3220 pci:v00001103d00003320* ID_MODEL_FROM_DATABASE=RocketRAID 3320 pci:v00001103d00004310* ID_MODEL_FROM_DATABASE=RocketRaid 4310 pci:v00001104* ID_VENDOR_FROM_DATABASE=RasterOps Corp. pci:v00001105* ID_VENDOR_FROM_DATABASE=Sigma Designs, Inc. pci:v00001105d00001105* ID_MODEL_FROM_DATABASE=REALmagic Xcard MPEG 1/2/3/4 DVD Decoder pci:v00001105d00008300* ID_MODEL_FROM_DATABASE=REALmagic Hollywood Plus DVD Decoder pci:v00001105d00008400* ID_MODEL_FROM_DATABASE=EM840x REALmagic DVD/MPEG-2 Audio/Video Decoder pci:v00001105d00008401* ID_MODEL_FROM_DATABASE=EM8401 REALmagic DVD/MPEG-2 A/V Decoder pci:v00001105d00008470* ID_MODEL_FROM_DATABASE=EM8470 REALmagic DVD/MPEG-4 A/V Decoder pci:v00001105d00008471* ID_MODEL_FROM_DATABASE=EM8471 REALmagic DVD/MPEG-4 A/V Decoder pci:v00001105d00008475* ID_MODEL_FROM_DATABASE=EM8475 REALmagic DVD/MPEG-4 A/V Decoder pci:v00001105d00008475sv00001105sd00000001* ID_MODEL_FROM_DATABASE=EM8475 REALmagic DVD/MPEG-4 A/V Decoder (REALmagic X-Card) pci:v00001105d00008476* ID_MODEL_FROM_DATABASE=EM8476 REALmagic DVD/MPEG-4 A/V Decoder pci:v00001105d00008476sv0000127Dsd00000000* ID_MODEL_FROM_DATABASE=EM8476 REALmagic DVD/MPEG-4 A/V Decoder (CineView II) pci:v00001105d00008485* ID_MODEL_FROM_DATABASE=EM8485 REALmagic DVD/MPEG-4 A/V Decoder pci:v00001105d00008486* ID_MODEL_FROM_DATABASE=EM8486 REALmagic DVD/MPEG-4 A/V Decoder pci:v00001105d0000C621* ID_MODEL_FROM_DATABASE=EM8621L Digital Media Processor pci:v00001105d0000C622* ID_MODEL_FROM_DATABASE=EM8622L MPEG-4.10 (H.264) and SMPTE 421M (VC-1) A/V Decoder pci:v00001106* ID_VENDOR_FROM_DATABASE=VIA Technologies, Inc. pci:v00001106d00000102* ID_MODEL_FROM_DATABASE=Embedded VIA Ethernet Controller pci:v00001106d00000130* ID_MODEL_FROM_DATABASE=VT6305 1394.A Controller pci:v00001106d00000198* ID_MODEL_FROM_DATABASE=P4X600 Host Bridge pci:v00001106d00000204* ID_MODEL_FROM_DATABASE=K8M800 Host Bridge pci:v00001106d00000208* ID_MODEL_FROM_DATABASE=PT890 Host Bridge pci:v00001106d00000238* ID_MODEL_FROM_DATABASE=K8T890 Host Bridge pci:v00001106d00000258* ID_MODEL_FROM_DATABASE=PT880 Host Bridge pci:v00001106d00000259* ID_MODEL_FROM_DATABASE=CN333/CN400/PM880 Host Bridge pci:v00001106d00000269* ID_MODEL_FROM_DATABASE=KT880 Host Bridge pci:v00001106d00000282* ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge pci:v00001106d00000282sv00001043sd000080A3* ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge (A8V Deluxe) pci:v00001106d00000290* ID_MODEL_FROM_DATABASE=K8M890 Host Bridge pci:v00001106d00000293* ID_MODEL_FROM_DATABASE=PM896 Host Bridge pci:v00001106d00000296* ID_MODEL_FROM_DATABASE=P4M800 Host Bridge pci:v00001106d00000305* ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] pci:v00001106d00000305sv00001019sd00000987* ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] (K7VZA Mainboard) pci:v00001106d00000305sv00001043sd00008033* ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] (A7V Mainboard) pci:v00001106d00000305sv00001043sd0000803E* ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] (A7V-E Mainboard) pci:v00001106d00000305sv00001043sd00008042* ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] (A7V133/A7V133-C Mainboard) pci:v00001106d00000305sv0000147Bsd0000A401* ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] (KT7/KT7-RAID/KT7A/KT7A-RAID Mainboard) pci:v00001106d00000308* ID_MODEL_FROM_DATABASE=PT880 Ultra/PT894 Host Bridge pci:v00001106d00000308sv00001043sd00008199* ID_MODEL_FROM_DATABASE=PT880 Ultra/PT894 Host Bridge (P4V800D-X Mainboard) pci:v00001106d00000308sv00001849sd00000308* ID_MODEL_FROM_DATABASE=PT880 Ultra/PT894 Host Bridge (Motherboard) pci:v00001106d00000314* ID_MODEL_FROM_DATABASE=CN700/VN800/P4M800CE/Pro Host Bridge pci:v00001106d00000324* ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge pci:v00001106d00000327* ID_MODEL_FROM_DATABASE=P4M890 Host Bridge pci:v00001106d00000336* ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge pci:v00001106d00000340* ID_MODEL_FROM_DATABASE=PT900 Host Bridge pci:v00001106d00000351* ID_MODEL_FROM_DATABASE=K8T890CF Host Bridge pci:v00001106d00000353* ID_MODEL_FROM_DATABASE=VX800 Host Bridge pci:v00001106d00000364* ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge pci:v00001106d00000364sv00001043sd000081CE* ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge (P5VD2-VM mothervoard) pci:v00001106d00000391* ID_MODEL_FROM_DATABASE=VT8371 [KX133] pci:v00001106d00000409* ID_MODEL_FROM_DATABASE=VX855/VX875 Host Bridge: Host Control pci:v00001106d00000410* ID_MODEL_FROM_DATABASE=VX900 Host Bridge: Host Control pci:v00001106d00000415* ID_MODEL_FROM_DATABASE=VT6415 PATA IDE Host Controller pci:v00001106d00000415sv00001043sd0000838F* ID_MODEL_FROM_DATABASE=VT6415 PATA IDE Host Controller (Motherboard) pci:v00001106d00000501* ID_MODEL_FROM_DATABASE=VT8501 [Apollo MVP4] pci:v00001106d00000505* ID_MODEL_FROM_DATABASE=VT82C505 pci:v00001106d00000561* ID_MODEL_FROM_DATABASE=VT82C576MV pci:v00001106d00000571* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE pci:v00001106d00000571sv00001019sd00000985* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (P6VXA Motherboard) pci:v00001106d00000571sv00001019sd00000A81* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (L7VTA v1.0 Motherboard (KT400-8235)) pci:v00001106d00000571sv00001043sd00008052* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (VT8233A Bus Master ATA100/66/33 IDE) pci:v00001106d00000571sv00001043sd0000808C* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (A7V8X / A7V333 motherboard) pci:v00001106d00000571sv00001043sd000080A1* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (A7V8X-X motherboard rev. 1.01) pci:v00001106d00000571sv00001043sd000080ED* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (A7V600/K8V-X/A8V Deluxe motherboard) pci:v00001106d00000571sv00001106sd00000571* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (VT82C586/B/VT82C686/A/B/VT8233/A/C/VT8235 PIPC Bus Master IDE) pci:v00001106d00000571sv00001179sd00000001* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (Magnia Z310) pci:v00001106d00000571sv00001297sd0000F641* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (FX41 motherboard) pci:v00001106d00000571sv00001458sd00005002* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (GA-7VAX Mainboard) pci:v00001106d00000571sv00001462sd00005901* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (KT6 Delta-FIS2R (MS-6590)) pci:v00001106d00000571sv00001462sd00007020* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (K8T NEO 2 motherboard) pci:v00001106d00000571sv00001462sd00007094* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (K8T Neo2-F V2.0) pci:v00001106d00000571sv00001462sd00007120* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (KT4AV motherboard) pci:v00001106d00000571sv00001462sd00007181* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (K8MM3-V mainboard) pci:v00001106d00000571sv0000147Bsd00001407* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (KV8-MAX3 motherboard) pci:v00001106d00000571sv00001849sd00000571* ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (K7VT series Motherboards) pci:v00001106d00000576* ID_MODEL_FROM_DATABASE=VT82C576 3V [Apollo Master] pci:v00001106d00000581* ID_MODEL_FROM_DATABASE=CX700/VX700 RAID Controller pci:v00001106d00000581sv00001106sd00000581* ID_MODEL_FROM_DATABASE=CX700/VX700 RAID Controller (Wrong IDE ID) pci:v00001106d00000585* ID_MODEL_FROM_DATABASE=VT82C585VP [Apollo VP1/VPX] pci:v00001106d00000586* ID_MODEL_FROM_DATABASE=VT82C586/A/B PCI-to-ISA [Apollo VP] pci:v00001106d00000586sv00001106sd00000000* ID_MODEL_FROM_DATABASE=VT82C586/A/B PCI-to-ISA [Apollo VP] (MVP3 ISA Bridge) pci:v00001106d00000591* ID_MODEL_FROM_DATABASE=VT8237A SATA 2-Port Controller pci:v00001106d00000595* ID_MODEL_FROM_DATABASE=VT82C595 [Apollo VP2] pci:v00001106d00000596* ID_MODEL_FROM_DATABASE=VT82C596 ISA [Mobile South] pci:v00001106d00000596sv00001106sd00000000* ID_MODEL_FROM_DATABASE=VT82C596 ISA [Mobile South] (VT82C596/A/B PCI to ISA Bridge) pci:v00001106d00000596sv00001458sd00000596* ID_MODEL_FROM_DATABASE=VT82C596 ISA [Mobile South] (VT82C596/A/B PCI to ISA Bridge) pci:v00001106d00000597* ID_MODEL_FROM_DATABASE=VT82C597 [Apollo VP3] pci:v00001106d00000598* ID_MODEL_FROM_DATABASE=VT82C598 [Apollo MVP3] pci:v00001106d00000601* ID_MODEL_FROM_DATABASE=VT8601 [Apollo ProMedia] pci:v00001106d00000605* ID_MODEL_FROM_DATABASE=VT8605 [ProSavage PM133] pci:v00001106d00000605sv0000103Csd00001254* ID_MODEL_FROM_DATABASE=VT8605 [ProSavage PM133] (D9840-60001 [Brio BA410 Motherboard]) pci:v00001106d00000605sv00001043sd0000802C* ID_MODEL_FROM_DATABASE=VT8605 [ProSavage PM133] (CUV4X mainboard) pci:v00001106d00000680* ID_MODEL_FROM_DATABASE=VT82C680 [Apollo P6] pci:v00001106d00000686* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] pci:v00001106d00000686sv00001019sd00000985* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (P6VXA Motherboard) pci:v00001106d00000686sv0000103Csd00001256* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (D9840-60001 [Brio BA410 Motherboard]) pci:v00001106d00000686sv00001043sd0000802C* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (CUV4X mainboard) pci:v00001106d00000686sv00001043sd00008033* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (A7V Mainboard) pci:v00001106d00000686sv00001043sd0000803E* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (A7V-E Mainboard) pci:v00001106d00000686sv00001043sd00008040* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (A7M266 Mainboard) pci:v00001106d00000686sv00001043sd00008042* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (A7V133/A7V133-C Mainboard) pci:v00001106d00000686sv00001106sd00000000* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (VT82C686/A PCI to ISA Bridge) pci:v00001106d00000686sv00001106sd00000686* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (VT82C686/A PCI to ISA Bridge) pci:v00001106d00000686sv00001179sd00000001* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (Magnia Z310) pci:v00001106d00000686sv0000147Bsd0000A702* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (KG7-Lite Mainboard) pci:v00001106d00000691* ID_MODEL_FROM_DATABASE=VT82C693A/694x [Apollo PRO133x] pci:v00001106d00000691sv00001019sd00000985* ID_MODEL_FROM_DATABASE=VT82C693A/694x [Apollo PRO133x] (P6VXA Motherboard) pci:v00001106d00000691sv00001179sd00000001* ID_MODEL_FROM_DATABASE=VT82C693A/694x [Apollo PRO133x] (Magnia Z310) pci:v00001106d00000691sv00001458sd00000691* ID_MODEL_FROM_DATABASE=VT82C693A/694x [Apollo PRO133x] (VT82C691 Apollo Pro System Controller) pci:v00001106d00000693* ID_MODEL_FROM_DATABASE=VT82C693 [Apollo Pro Plus] pci:v00001106d00000698* ID_MODEL_FROM_DATABASE=VT82C693A [Apollo Pro133 AGP] pci:v00001106d00000709* ID_MODEL_FROM_DATABASE=VX11 Standard Host Bridge pci:v00001106d0000070A* ID_MODEL_FROM_DATABASE=VX11 PCI Express Root Port pci:v00001106d0000070B* ID_MODEL_FROM_DATABASE=VX11 PCI Express Root Port pci:v00001106d0000070C* ID_MODEL_FROM_DATABASE=VX11 PCI Express Root Port pci:v00001106d0000070D* ID_MODEL_FROM_DATABASE=VX11 PCI Express Root Port pci:v00001106d0000070E* ID_MODEL_FROM_DATABASE=VX11 PCI Express Root Port pci:v00001106d00000926* ID_MODEL_FROM_DATABASE=VT82C926 [Amazon] pci:v00001106d00001000* ID_MODEL_FROM_DATABASE=VT82C570MV pci:v00001106d00001106* ID_MODEL_FROM_DATABASE=VT82C570MV pci:v00001106d00001122* ID_MODEL_FROM_DATABASE=VX800/VX820 Chrome 9 HC3 Integrated Graphics pci:v00001106d00001204* ID_MODEL_FROM_DATABASE=K8M800 Host Bridge pci:v00001106d00001208* ID_MODEL_FROM_DATABASE=PT890 Host Bridge pci:v00001106d00001238* ID_MODEL_FROM_DATABASE=K8T890 Host Bridge pci:v00001106d00001258* ID_MODEL_FROM_DATABASE=PT880 Host Bridge pci:v00001106d00001259* ID_MODEL_FROM_DATABASE=CN333/CN400/PM880 Host Bridge pci:v00001106d00001269* ID_MODEL_FROM_DATABASE=KT880 Host Bridge pci:v00001106d00001282* ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge pci:v00001106d00001290* ID_MODEL_FROM_DATABASE=K8M890 Host Bridge pci:v00001106d00001293* ID_MODEL_FROM_DATABASE=PM896 Host Bridge pci:v00001106d00001296* ID_MODEL_FROM_DATABASE=P4M800 Host Bridge pci:v00001106d00001308* ID_MODEL_FROM_DATABASE=PT894 Host Bridge pci:v00001106d00001314* ID_MODEL_FROM_DATABASE=CN700/VN800/P4M800CE/Pro Host Bridge pci:v00001106d00001324* ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge pci:v00001106d00001327* ID_MODEL_FROM_DATABASE=P4M890 Host Bridge pci:v00001106d00001336* ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge pci:v00001106d00001340* ID_MODEL_FROM_DATABASE=PT900 Host Bridge pci:v00001106d00001351* ID_MODEL_FROM_DATABASE=VT3351 Host Bridge pci:v00001106d00001353* ID_MODEL_FROM_DATABASE=VX800/VX820 Error Reporting pci:v00001106d00001364* ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge pci:v00001106d00001409* ID_MODEL_FROM_DATABASE=VX855/VX875 Error Reporting pci:v00001106d00001410* ID_MODEL_FROM_DATABASE=VX900 Error Reporting pci:v00001106d00001571* ID_MODEL_FROM_DATABASE=VT82C576M/VT82C586 pci:v00001106d00001595* ID_MODEL_FROM_DATABASE=VT82C595/97 [Apollo VP2/97] pci:v00001106d00001732* ID_MODEL_FROM_DATABASE=VT1732 [Envy24 II] PCI Multi-Channel Audio Controller pci:v00001106d00002106* ID_MODEL_FROM_DATABASE=VIA Rhine Family Fast Ethernet Adapter (VT6105) pci:v00001106d00002204* ID_MODEL_FROM_DATABASE=K8M800 Host Bridge pci:v00001106d00002208* ID_MODEL_FROM_DATABASE=PT890 Host Bridge pci:v00001106d00002238* ID_MODEL_FROM_DATABASE=K8T890 Host Bridge pci:v00001106d00002258* ID_MODEL_FROM_DATABASE=PT880 Host Bridge pci:v00001106d00002259* ID_MODEL_FROM_DATABASE=CN333/CN400/PM880 CPU Host Bridge pci:v00001106d00002269* ID_MODEL_FROM_DATABASE=KT880 Host Bridge pci:v00001106d00002282* ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge pci:v00001106d00002290* ID_MODEL_FROM_DATABASE=K8M890 Host Bridge pci:v00001106d00002293* ID_MODEL_FROM_DATABASE=PM896 Host Bridge pci:v00001106d00002296* ID_MODEL_FROM_DATABASE=P4M800 Host Bridge pci:v00001106d00002308* ID_MODEL_FROM_DATABASE=PT894 Host Bridge pci:v00001106d00002314* ID_MODEL_FROM_DATABASE=CN700/VN800/P4M800CE/Pro Host Bridge pci:v00001106d00002324* ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge pci:v00001106d00002327* ID_MODEL_FROM_DATABASE=P4M890 Host Bridge pci:v00001106d00002336* ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge pci:v00001106d00002340* ID_MODEL_FROM_DATABASE=PT900 Host Bridge pci:v00001106d00002351* ID_MODEL_FROM_DATABASE=VT3351 Host Bridge pci:v00001106d00002353* ID_MODEL_FROM_DATABASE=VX800/VX820 Host Bus Control pci:v00001106d00002364* ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge pci:v00001106d00002409* ID_MODEL_FROM_DATABASE=VX855/VX875 Host Bus Control pci:v00001106d00002410* ID_MODEL_FROM_DATABASE=VX900 CPU Bus Controller pci:v00001106d0000287A* ID_MODEL_FROM_DATABASE=VT8251 PCI to PCI Bridge pci:v00001106d0000287B* ID_MODEL_FROM_DATABASE=VT8251 Host Bridge pci:v00001106d0000287C* ID_MODEL_FROM_DATABASE=VT8251 PCIE Root Port pci:v00001106d0000287D* ID_MODEL_FROM_DATABASE=VT8251 PCIE Root Port pci:v00001106d0000287E* ID_MODEL_FROM_DATABASE=VT8237/8251 Ultra VLINK Controller pci:v00001106d00003022* ID_MODEL_FROM_DATABASE=CLE266 pci:v00001106d00003038* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller pci:v00001106d00003038sv00000925sd00001234* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (onboard UHCI USB 1.1 Controller) pci:v00001106d00003038sv00001019sd00000985* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (P6VXA Motherboard) pci:v00001106d00003038sv00001019sd00000A81* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (L7VTA v1.0 Motherboard (KT400-8235)) pci:v00001106d00003038sv00001043sd00008080* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (A7V333 motherboard) pci:v00001106d00003038sv00001043sd0000808C* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (VT6202 USB2.0 4 port controller) pci:v00001106d00003038sv00001043sd000080A1* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (A7V8X-X motherboard) pci:v00001106d00003038sv00001043sd000080ED* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (A7V600/K8V-X/A8V Deluxe motherboard) pci:v00001106d00003038sv00001179sd00000001* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (Magnia Z310) pci:v00001106d00003038sv00001458sd00005004* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (GA-7VAX Mainboard) pci:v00001106d00003038sv00001462sd00005901* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (KT6 Delta-FIS2R (MS-6590)) pci:v00001106d00003038sv00001462sd00007020* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (K8T NEO 2 motherboard) pci:v00001106d00003038sv00001462sd00007094* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (K8T Neo2-F V2.0) pci:v00001106d00003038sv00001462sd00007120* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (KT4AV motherboard) pci:v00001106d00003038sv00001462sd00007181* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (K8MM3-V mainboard) pci:v00001106d00003038sv0000147Bsd00001407* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (KV8-MAX3 motherboard) pci:v00001106d00003038sv0000182Dsd0000201D* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (CN-029 USB2.0 4 port PCI Card) pci:v00001106d00003038sv00001849sd00003038* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (K7VT series Motherboards) pci:v00001106d00003038sv000019DAsd0000A179* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (ZBOX nano VD01) pci:v00001106d00003038sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (QEMU Virtual Machine) pci:v00001106d00003040* ID_MODEL_FROM_DATABASE=VT82C586B ACPI pci:v00001106d00003043* ID_MODEL_FROM_DATABASE=VT86C100A [Rhine] pci:v00001106d00003043sv000010BDsd00000000* ID_MODEL_FROM_DATABASE=VT86C100A [Rhine] (VT86C100A Fast Ethernet Adapter) pci:v00001106d00003043sv00001106sd00000100* ID_MODEL_FROM_DATABASE=VT86C100A [Rhine] (VT86C100A Fast Ethernet Adapter) pci:v00001106d00003043sv00001186sd00001400* ID_MODEL_FROM_DATABASE=VT86C100A [Rhine] (DFE-530TX PCI Fast Ethernet Adapter (rev. A)) pci:v00001106d00003044* ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller pci:v00001106d00003044sv00000010sd00000001* ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (IEEE 1394 4port DCST 1394-3+1B) pci:v00001106d00003044sv00001025sd0000005A* ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (TravelMate 290) pci:v00001106d00003044sv0000103Csd00002A20* ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (Pavilion t3030.de Desktop PC) pci:v00001106d00003044sv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (Media Center PC m7590n) pci:v00001106d00003044sv00001043sd0000808A* ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (A8V/A8N/P4P800/P5SD2 series motherboard) pci:v00001106d00003044sv00001043sd000081FE* ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (Motherboard) pci:v00001106d00003044sv00001458sd00001000* ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (GA-7VT600-1394 Motherboard) pci:v00001106d00003044sv00001462sd0000207D* ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (K8NGM2 series motherboard) pci:v00001106d00003044sv00001462sd0000217D* ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (Aspire L250) pci:v00001106d00003044sv00001462sd0000590D* ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (KT6 Delta-FIS2R (MS-6590)) pci:v00001106d00003044sv00001462sd0000702D* ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (K8T NEO 2 motherboard) pci:v00001106d00003044sv00001462sd0000971D* ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (MS-6917) pci:v00001106d00003050* ID_MODEL_FROM_DATABASE=VT82C596 Power Management pci:v00001106d00003051* ID_MODEL_FROM_DATABASE=VT82C596 Power Management pci:v00001106d00003053* ID_MODEL_FROM_DATABASE=VT6105M [Rhine-III] pci:v00001106d00003053sv00001186sd00001404* ID_MODEL_FROM_DATABASE=VT6105M [Rhine-III] (DFE-530TX PCI Fast Ethernet Adapter (rev. D)) pci:v00001106d00003057* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] pci:v00001106d00003057sv00001019sd00000985* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (P6VXA Motherboard) pci:v00001106d00003057sv00001019sd00000987* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (K7VZA Motherboard) pci:v00001106d00003057sv00001043sd00008033* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (A7V Mainboard) pci:v00001106d00003057sv00001043sd0000803E* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (A7V-E Mainboard) pci:v00001106d00003057sv00001043sd00008040* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (A7M266 Mainboard) pci:v00001106d00003057sv00001043sd00008042* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (A7V133/A7V133-C Mainboard) pci:v00001106d00003057sv00001179sd00000001* ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (Magnia Z310) pci:v00001106d00003058* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller pci:v00001106d00003058sv00000E11sd00000097* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (SoundMax Digital Integrated Audio) pci:v00001106d00003058sv00000E11sd0000B194* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (Soundmax integrated digital audio) pci:v00001106d00003058sv00001019sd00000985* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (P6VXA Motherboard) pci:v00001106d00003058sv00001019sd00000987* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (K7VZA Motherboard) pci:v00001106d00003058sv0000103Csd00001251* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (D9840-60001 [Brio BA410 Motherboard]) pci:v00001106d00003058sv00001043sd00001106* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (A7V133/A7V133-C Mainboard) pci:v00001106d00003058sv00001106sd00004511* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (Onboard Audio on EP7KXA) pci:v00001106d00003058sv00001106sd0000AA03* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (VT1612A AC'97 Audio Controller) pci:v00001106d00003058sv000011D4sd00005348* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (AD1881A audio) pci:v00001106d00003058sv00001458sd00007600* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (Onboard Audio) pci:v00001106d00003058sv00001462sd00003091* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (MS-6309 Onboard Audio) pci:v00001106d00003058sv00001462sd00003092* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (MS-6309 v2.x Mainboard (VIA VT1611A codec)) pci:v00001106d00003058sv00001462sd00003300* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (MS-6330 Onboard Audio) pci:v00001106d00003058sv00001462sd00003400* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (MS-6340 (VT8363) motherboard) pci:v00001106d00003058sv000015DDsd00007609* ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (Onboard Audio) pci:v00001106d00003059* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller pci:v00001106d00003059sv00001019sd00000A81* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (L7VTA v1.0 Motherboard (KT400-8235)) pci:v00001106d00003059sv00001019sd00001841* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (M811 (VT8367/VT8235/VT6103) [KT333] motherboard) pci:v00001106d00003059sv00001019sd00001877* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (K8M800-M2 (V2.0) onboard audio) pci:v00001106d00003059sv00001043sd00008095* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (A7V8X Motherboard (Realtek ALC650 codec)) pci:v00001106d00003059sv00001043sd000080A1* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (A7V8X-X Motherboard) pci:v00001106d00003059sv00001043sd000080B0* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (A7V600/K8V-X/K8V Deluxe motherboard (ADI AD1980 codec [SoundMAX])) pci:v00001106d00003059sv00001043sd0000810D* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (Asus P5VD1-X (AD1888 codec [SoundMax])) pci:v00001106d00003059sv00001043sd0000812A* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (A8V Deluxe motherboard (Realtek ALC850 codec)) pci:v00001106d00003059sv000010ECsd00008168* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (High Definition Audio) pci:v00001106d00003059sv00001106sd00003059* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (L7VMM2 Motherboard) pci:v00001106d00003059sv00001106sd00004161* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (K7VT2 motherboard) pci:v00001106d00003059sv00001106sd00004170* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (PCPartner P4M800-8237R Motherboard) pci:v00001106d00003059sv00001106sd00004552* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (Soyo KT-600 Dragon Plus (Realtek ALC 650)) pci:v00001106d00003059sv00001297sd0000C160* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (FX41 motherboard (Realtek ALC650 codec)) pci:v00001106d00003059sv00001413sd0000147B* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (KV8 Pro motherboard onboard audio) pci:v00001106d00003059sv00001458sd0000A002* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (GA-7VAX Onboard Audio (Realtek ALC650)) pci:v00001106d00003059sv00001462sd00000080* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (K8T NEO 2 motherboard) pci:v00001106d00003059sv00001462sd00003800* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (KT266 onboard audio) pci:v00001106d00003059sv00001462sd00005901* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (KT6 Delta-FIS2R (MS-6590)) pci:v00001106d00003059sv00001462sd00007181* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (K8MM3-V mainboard) pci:v00001106d00003059sv0000147Bsd00001407* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (KV8-MAX3 motherboard) pci:v00001106d00003059sv00001695sd0000300C* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (Realtek ALC655 audio on EP-8KRA series mainboard) pci:v00001106d00003059sv00001849sd00000850* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (ASRock 775Dual-880 Pro onboard audio (Realtek ALC850)) pci:v00001106d00003059sv00001849sd00009739* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (P4VT8 Mainboard (C-Media CMI9739A codec)) pci:v00001106d00003059sv00001849sd00009761* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (K7VT series Motherboards) pci:v00001106d00003059sv00004005sd00004710* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (MSI K7T266 Pro2-RU (MSI-6380 v2) onboard audio (Realtek/ALC 200/200P)) pci:v00001106d00003059sv0000A0A0sd000001B6* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (AK77-8XN onboard audio) pci:v00001106d00003059sv0000A0A0sd00000342* ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (AK86-L motherboard) pci:v00001106d00003065* ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] pci:v00001106d00003065sv00001043sd000080A1* ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (A7V8X-X Motherboard) pci:v00001106d00003065sv00001043sd000080ED* ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (A7V600-X Motherboard) pci:v00001106d00003065sv00001106sd00000102* ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (VT6102/6103 [Rhine II] Ethernet Controller) pci:v00001106d00003065sv00001186sd00001400* ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (DFE-530TX PCI Fast Ethernet Adapter (rev. A)) pci:v00001106d00003065sv00001186sd00001401* ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (DFE-530TX PCI Fast Ethernet Adapter (rev. B)) pci:v00001106d00003065sv00001186sd00001402* ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (DFE-530TX PCI Fast Ethernet Adapter (rev. B)) pci:v00001106d00003065sv000013B9sd00001421* ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (LD-10/100AL PCI Fast Ethernet Adapter (rev.B)) pci:v00001106d00003065sv00001462sd00007061* ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (MS-7061) pci:v00001106d00003065sv00001462sd00007181* ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (K8MM3-V mainboard) pci:v00001106d00003065sv0000147Bsd00001C09* ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (NV7 Motherboard) pci:v00001106d00003065sv00001695sd00003005* ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (VT6103) pci:v00001106d00003065sv00001849sd00003065* ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (K7VT series Motherboards) pci:v00001106d00003068* ID_MODEL_FROM_DATABASE=AC'97 Modem Controller pci:v00001106d00003068sv00001462sd0000309E* ID_MODEL_FROM_DATABASE=AC'97 Modem Controller (MS-6309 Saturn Motherboard) pci:v00001106d00003074* ID_MODEL_FROM_DATABASE=VT8233 PCI to ISA Bridge pci:v00001106d00003074sv00001043sd00008052* ID_MODEL_FROM_DATABASE=VT8233 PCI to ISA Bridge (VT8233A) pci:v00001106d00003091* ID_MODEL_FROM_DATABASE=VT8633 [Apollo Pro266] pci:v00001106d00003099* ID_MODEL_FROM_DATABASE=VT8366/A/7 [Apollo KT266/A/333] pci:v00001106d00003099sv00001019sd00001841* ID_MODEL_FROM_DATABASE=VT8366/A/7 [Apollo KT266/A/333] (M811 (VT8367/VT8235/VT6103) [KT333] motherboard) pci:v00001106d00003099sv00001043sd00008064* ID_MODEL_FROM_DATABASE=VT8366/A/7 [Apollo KT266/A/333] (A7V266-E Mainboard) pci:v00001106d00003099sv00001043sd0000807F* ID_MODEL_FROM_DATABASE=VT8366/A/7 [Apollo KT266/A/333] (A7V333 Mainboard) pci:v00001106d00003099sv00001849sd00003099* ID_MODEL_FROM_DATABASE=VT8366/A/7 [Apollo KT266/A/333] (K7VT2 motherboard) pci:v00001106d00003101* ID_MODEL_FROM_DATABASE=VT8653 Host Bridge pci:v00001106d00003102* ID_MODEL_FROM_DATABASE=VT8662 Host Bridge pci:v00001106d00003103* ID_MODEL_FROM_DATABASE=VT8615 Host Bridge pci:v00001106d00003104* ID_MODEL_FROM_DATABASE=USB 2.0 pci:v00001106d00003104sv00000925sd00001234* ID_MODEL_FROM_DATABASE=USB 2.0 (onboard EHCI USB 2.0 Controller) pci:v00001106d00003104sv00001019sd00000A81* ID_MODEL_FROM_DATABASE=USB 2.0 (L7VTA v1.0 Motherboard (KT400-8235)) pci:v00001106d00003104sv00001043sd0000808C* ID_MODEL_FROM_DATABASE=USB 2.0 (A7V8X motherboard) pci:v00001106d00003104sv00001043sd000080A1* ID_MODEL_FROM_DATABASE=USB 2.0 (A7V8X-X motherboard rev 1.01) pci:v00001106d00003104sv00001043sd000080ED* ID_MODEL_FROM_DATABASE=USB 2.0 (A7V600/K8V-X/A8V Deluxe motherboard) pci:v00001106d00003104sv00001106sd00003104* ID_MODEL_FROM_DATABASE=USB 2.0 (Controller) pci:v00001106d00003104sv00001297sd0000F641* ID_MODEL_FROM_DATABASE=USB 2.0 (FX41 motherboard) pci:v00001106d00003104sv00001458sd00005004* ID_MODEL_FROM_DATABASE=USB 2.0 (GA-7VAX Mainboard) pci:v00001106d00003104sv00001462sd00005901* ID_MODEL_FROM_DATABASE=USB 2.0 (KT6 Delta-FIS2R (MS-6590)) pci:v00001106d00003104sv00001462sd00007020* ID_MODEL_FROM_DATABASE=USB 2.0 (K8T NEO 2 motherboard) pci:v00001106d00003104sv00001462sd00007094* ID_MODEL_FROM_DATABASE=USB 2.0 (K8T Neo2-F V2.0) pci:v00001106d00003104sv00001462sd00007120* ID_MODEL_FROM_DATABASE=USB 2.0 (KT4AV motherboard) pci:v00001106d00003104sv00001462sd00007181* ID_MODEL_FROM_DATABASE=USB 2.0 (K8MM3-V mainboard) pci:v00001106d00003104sv0000147Bsd00001407* ID_MODEL_FROM_DATABASE=USB 2.0 (KV8-MAX3 motherboard) pci:v00001106d00003104sv0000182Dsd0000201D* ID_MODEL_FROM_DATABASE=USB 2.0 (CN-029 USB 2.0 4 port PCI Card) pci:v00001106d00003104sv00001849sd00003104* ID_MODEL_FROM_DATABASE=USB 2.0 (K7VT series Motherboards) pci:v00001106d00003104sv000019DAsd0000A179* ID_MODEL_FROM_DATABASE=USB 2.0 (ZBOX nano VD01) pci:v00001106d00003106* ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] pci:v00001106d00003106sv00001106sd00000105* ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (VT6106S [Rhine-III]) pci:v00001106d00003106sv00001186sd00001403* ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (DFE-530TX PCI Fast Ethernet Adapter (rev. C)) pci:v00001106d00003106sv00001186sd00001405* ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (DFE-520TX Fast Ethernet PCI Adapter) pci:v00001106d00003106sv00001186sd00001406* ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (DFE-530TX+ rev F2) pci:v00001106d00003106sv00001186sd00001407* ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (DFE-538TX) pci:v00001106d00003108* ID_MODEL_FROM_DATABASE=K8M800/K8N800/K8N800A [S3 UniChrome Pro] pci:v00001106d00003109* ID_MODEL_FROM_DATABASE=VT8233C PCI to ISA Bridge pci:v00001106d00003112* ID_MODEL_FROM_DATABASE=VT8361 [KLE133] Host Bridge pci:v00001106d00003113* ID_MODEL_FROM_DATABASE=VPX/VPX2 PCI to PCI Bridge Controller pci:v00001106d00003116* ID_MODEL_FROM_DATABASE=VT8375 [KM266/KL266] Host Bridge pci:v00001106d00003116sv00001297sd0000F641* ID_MODEL_FROM_DATABASE=VT8375 [KM266/KL266] Host Bridge (FX41 motherboard) pci:v00001106d00003118* ID_MODEL_FROM_DATABASE=CN400/PM800/PM880/PN800/PN880 [S3 UniChrome Pro] pci:v00001106d00003119* ID_MODEL_FROM_DATABASE=VT6120/VT6121/VT6122 Gigabit Ethernet Adapter pci:v00001106d00003122* ID_MODEL_FROM_DATABASE=VT8623 [Apollo CLE266] integrated CastleRock graphics pci:v00001106d00003123* ID_MODEL_FROM_DATABASE=VT8623 [Apollo CLE266] pci:v00001106d00003128* ID_MODEL_FROM_DATABASE=VT8753 [P4X266 AGP] pci:v00001106d00003133* ID_MODEL_FROM_DATABASE=VT3133 Host Bridge pci:v00001106d00003142* ID_MODEL_FROM_DATABASE=VT6651 WiFi Adapter, 802.11b pci:v00001106d00003147* ID_MODEL_FROM_DATABASE=VT8233A ISA Bridge pci:v00001106d00003147sv00001043sd0000808C* ID_MODEL_FROM_DATABASE=VT8233A ISA Bridge (A7V333 motherboard) pci:v00001106d00003148* ID_MODEL_FROM_DATABASE=P4M266 Host Bridge pci:v00001106d00003149* ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller pci:v00001106d00003149sv00001043sd000080ED* ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (A7V600/K8V Deluxe/K8V-X/A8V Deluxe motherboard) pci:v00001106d00003149sv00001458sd0000B003* ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (GA-7VM400AM(F) Motherboard) pci:v00001106d00003149sv00001462sd00005901* ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (KT6 Delta-FIS2R (MS-6590)) pci:v00001106d00003149sv00001462sd00007020* ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (K8T Neo 2 Motherboard) pci:v00001106d00003149sv00001462sd00007094* ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (K8T Neo2-F V2.0) pci:v00001106d00003149sv00001462sd00007181* ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (K8MM3-V mainboard) pci:v00001106d00003149sv0000147Bsd00001407* ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (KV8-MAX3 motherboard) pci:v00001106d00003149sv0000147Bsd00001408* ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (KV7) pci:v00001106d00003149sv00001849sd00003149* ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (K7VT6 motherboard) pci:v00001106d00003149sv0000A0A0sd000004AD* ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (AK86-L motherboard) pci:v00001106d00003156* ID_MODEL_FROM_DATABASE=P/KN266 Host Bridge pci:v00001106d00003157* ID_MODEL_FROM_DATABASE=CX700/VX700 [S3 UniChrome Pro] pci:v00001106d00003164* ID_MODEL_FROM_DATABASE=VT6410 ATA133 RAID controller pci:v00001106d00003164sv00001043sd000080F4* ID_MODEL_FROM_DATABASE=VT6410 ATA133 RAID controller (P4P800 Mainboard Deluxe ATX) pci:v00001106d00003164sv00001462sd00007028* ID_MODEL_FROM_DATABASE=VT6410 ATA133 RAID controller (915P/G Neo2) pci:v00001106d00003168* ID_MODEL_FROM_DATABASE=P4X333/P4X400/PT800 AGP Bridge pci:v00001106d00003168sv00001849sd00003168* ID_MODEL_FROM_DATABASE=P4X333/P4X400/PT800 AGP Bridge (P4VT8 Mainboard) pci:v00001106d00003177* ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge pci:v00001106d00003177sv00001019sd00000A81* ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (L7VTA v1.0 Motherboard (KT400-8235)) pci:v00001106d00003177sv00001019sd00001841* ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (M811 (VT8367/VT8235/VT6103) [KT333] motherboard) pci:v00001106d00003177sv00001043sd0000808C* ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (A7V8X motherboard) pci:v00001106d00003177sv00001043sd000080A1* ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (A7V8X-X motherboard) pci:v00001106d00003177sv00001106sd00000000* ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (KT4AV motherboard) pci:v00001106d00003177sv00001297sd0000F641* ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (FX41 motherboard) pci:v00001106d00003177sv00001458sd00005001* ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (GA-7VAX Mainboard) pci:v00001106d00003177sv00001849sd00003177* ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (K7VT series Motherboards) pci:v00001106d00003178* ID_MODEL_FROM_DATABASE=ProSavageDDR P4N333 Host Bridge pci:v00001106d00003188* ID_MODEL_FROM_DATABASE=VT8385 [K8T800 AGP] Host Bridge pci:v00001106d00003188sv00001043sd000080A3* ID_MODEL_FROM_DATABASE=VT8385 [K8T800 AGP] Host Bridge (K8V Deluxe/K8V-X motherboard) pci:v00001106d00003188sv0000147Bsd00001407* ID_MODEL_FROM_DATABASE=VT8385 [K8T800 AGP] Host Bridge (KV8-MAX3 motherboard) pci:v00001106d00003189* ID_MODEL_FROM_DATABASE=VT8377 [KT400/KT600 AGP] Host Bridge pci:v00001106d00003189sv00001043sd0000807F* ID_MODEL_FROM_DATABASE=VT8377 [KT400/KT600 AGP] Host Bridge (A7V8X motherboard) pci:v00001106d00003189sv00001106sd00000000* ID_MODEL_FROM_DATABASE=VT8377 [KT400/KT600 AGP] Host Bridge (KT4AV motherboard (KT400A)) pci:v00001106d00003189sv00001458sd00005000* ID_MODEL_FROM_DATABASE=VT8377 [KT400/KT600 AGP] Host Bridge (GA-7VAX Mainboard) pci:v00001106d00003189sv00001849sd00003189* ID_MODEL_FROM_DATABASE=VT8377 [KT400/KT600 AGP] Host Bridge (K7VT series Motherboards) pci:v00001106d000031B0* ID_MODEL_FROM_DATABASE=VX11 Standard Host Bridge pci:v00001106d000031B1* ID_MODEL_FROM_DATABASE=VX11 Standard Host Bridge pci:v00001106d000031B2* ID_MODEL_FROM_DATABASE=VX11 DRAM Controller pci:v00001106d000031B3* ID_MODEL_FROM_DATABASE=VX11 Power Management Controller pci:v00001106d000031B4* ID_MODEL_FROM_DATABASE=VX11 I/O APIC pci:v00001106d000031B5* ID_MODEL_FROM_DATABASE=VX11 Scratch Device pci:v00001106d000031B7* ID_MODEL_FROM_DATABASE=VX11 Standard Host Bridge pci:v00001106d000031B8* ID_MODEL_FROM_DATABASE=VX11 PCI to PCI Bridge pci:v00001106d00003204* ID_MODEL_FROM_DATABASE=K8M800 Host Bridge pci:v00001106d00003205* ID_MODEL_FROM_DATABASE=VT8378 [KM400/A] Chipset Host Bridge pci:v00001106d00003205sv00001458sd00005000* ID_MODEL_FROM_DATABASE=VT8378 [KM400/A] Chipset Host Bridge (GA-7VM400M Motherboard) pci:v00001106d00003208* ID_MODEL_FROM_DATABASE=PT890 Host Bridge pci:v00001106d00003213* ID_MODEL_FROM_DATABASE=VPX/VPX2 PCI to PCI Bridge Controller pci:v00001106d00003218* ID_MODEL_FROM_DATABASE=K8T800M Host Bridge pci:v00001106d00003227* ID_MODEL_FROM_DATABASE=VT8237 ISA bridge [KT600/K8T800/K8T890 South] pci:v00001106d00003227sv00001043sd000080ED* ID_MODEL_FROM_DATABASE=VT8237 ISA bridge [KT600/K8T800/K8T890 South] (A7V600/K8V-X/A8V Deluxe motherboard) pci:v00001106d00003227sv00001106sd00003227* ID_MODEL_FROM_DATABASE=VT8237 ISA bridge [KT600/K8T800/K8T890 South] (DFI KT600-AL / Soltek SL-B9D-FGR Motherboard) pci:v00001106d00003227sv00001458sd00005001* ID_MODEL_FROM_DATABASE=VT8237 ISA bridge [KT600/K8T800/K8T890 South] (GA-7VT600 Motherboard) pci:v00001106d00003227sv0000147Bsd00001407* ID_MODEL_FROM_DATABASE=VT8237 ISA bridge [KT600/K8T800/K8T890 South] (KV8-MAX3 motherboard) pci:v00001106d00003227sv00001849sd00003227* ID_MODEL_FROM_DATABASE=VT8237 ISA bridge [KT600/K8T800/K8T890 South] (K7VT4 motherboard) pci:v00001106d00003230* ID_MODEL_FROM_DATABASE=K8M890CE/K8N890CE [Chrome 9] pci:v00001106d00003238* ID_MODEL_FROM_DATABASE=K8T890 Host Bridge pci:v00001106d00003249* ID_MODEL_FROM_DATABASE=VT6421 IDE/SATA Controller pci:v00001106d00003249sv00001106sd00003249* ID_MODEL_FROM_DATABASE=VT6421 IDE/SATA Controller pci:v00001106d0000324A* ID_MODEL_FROM_DATABASE=CX700/VX700 PCI to PCI Bridge pci:v00001106d0000324B* ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge pci:v00001106d0000324E* ID_MODEL_FROM_DATABASE=CX700/VX700 Internal Module Bus pci:v00001106d00003253* ID_MODEL_FROM_DATABASE=VT6655 WiFi Adapter, 802.11a/b/g pci:v00001106d00003258* ID_MODEL_FROM_DATABASE=PT880 Host Bridge pci:v00001106d00003259* ID_MODEL_FROM_DATABASE=CN333/CN400/PM880 Host Bridge pci:v00001106d00003260* ID_MODEL_FROM_DATABASE=VIA Chrome9 HC IGP pci:v00001106d00003269* ID_MODEL_FROM_DATABASE=KT880 Host Bridge pci:v00001106d00003282* ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge pci:v00001106d00003287* ID_MODEL_FROM_DATABASE=VT8251 PCI to ISA Bridge pci:v00001106d00003288* ID_MODEL_FROM_DATABASE=VT8237A/VT8251 HDA Controller pci:v00001106d00003288sv000019DAsd0000A179* ID_MODEL_FROM_DATABASE=VT8237A/VT8251 HDA Controller (ZBOX VD01) pci:v00001106d00003290* ID_MODEL_FROM_DATABASE=K8M890 Host Bridge pci:v00001106d00003296* ID_MODEL_FROM_DATABASE=P4M800 Host Bridge pci:v00001106d00003324* ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge pci:v00001106d00003327* ID_MODEL_FROM_DATABASE=P4M890 Host Bridge pci:v00001106d00003336* ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge pci:v00001106d00003337* ID_MODEL_FROM_DATABASE=VT8237A PCI to ISA Bridge pci:v00001106d00003340* ID_MODEL_FROM_DATABASE=PT900 Host Bridge pci:v00001106d00003343* ID_MODEL_FROM_DATABASE=P4M890 [S3 UniChrome Pro] pci:v00001106d00003344* ID_MODEL_FROM_DATABASE=CN700/P4M800 Pro/P4M800 CE/VN800 Graphics [S3 UniChrome Pro] pci:v00001106d00003349* ID_MODEL_FROM_DATABASE=VT8251 AHCI/SATA 4-Port Controller pci:v00001106d00003351* ID_MODEL_FROM_DATABASE=VT3351 Host Bridge pci:v00001106d00003353* ID_MODEL_FROM_DATABASE=VX800 PCI to PCI Bridge pci:v00001106d00003364* ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge pci:v00001106d00003371* ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 [Chrome 9 HC] pci:v00001106d00003372* ID_MODEL_FROM_DATABASE=VT8237S PCI to ISA Bridge pci:v00001106d0000337A* ID_MODEL_FROM_DATABASE=VT8237A PCI to PCI Bridge pci:v00001106d0000337B* ID_MODEL_FROM_DATABASE=VT8237A Host Bridge pci:v00001106d00003403* ID_MODEL_FROM_DATABASE=VT6315 Series Firewire Controller pci:v00001106d00003403sv00001043sd00008374* ID_MODEL_FROM_DATABASE=VT6315 Series Firewire Controller (M5A88-V EVO) pci:v00001106d00003403sv00001043sd00008384* ID_MODEL_FROM_DATABASE=VT6315 Series Firewire Controller (P8P67 Deluxe Motherboard) pci:v00001106d00003409* ID_MODEL_FROM_DATABASE=VX855/VX875 DRAM Bus Control pci:v00001106d00003410* ID_MODEL_FROM_DATABASE=VX900 DRAM Bus Control pci:v00001106d00003410sv000019DAsd0000A179* ID_MODEL_FROM_DATABASE=VX900 DRAM Bus Control (ZBOX nano VD01) pci:v00001106d00003432* ID_MODEL_FROM_DATABASE=VL80x xHCI USB 3.0 Controller pci:v00001106d00003456* ID_MODEL_FROM_DATABASE=VX11 Standard Host Bridge pci:v00001106d0000345B* ID_MODEL_FROM_DATABASE=VX11 Miscellaneous Bus pci:v00001106d00003483* ID_MODEL_FROM_DATABASE=VL805 USB 3.0 Host Controller pci:v00001106d00003A01* ID_MODEL_FROM_DATABASE=VX11 Graphics [Chrome 645/640] pci:v00001106d00004149* ID_MODEL_FROM_DATABASE=VIA VT6420 (ATA133) Controller pci:v00001106d00004204* ID_MODEL_FROM_DATABASE=K8M800 Host Bridge pci:v00001106d00004208* ID_MODEL_FROM_DATABASE=PT890 Host Bridge pci:v00001106d00004238* ID_MODEL_FROM_DATABASE=K8T890 Host Bridge pci:v00001106d00004258* ID_MODEL_FROM_DATABASE=PT880 Host Bridge pci:v00001106d00004259* ID_MODEL_FROM_DATABASE=CN333/CN400/PM880 Host Bridge pci:v00001106d00004269* ID_MODEL_FROM_DATABASE=KT880 Host Bridge pci:v00001106d00004282* ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge pci:v00001106d00004290* ID_MODEL_FROM_DATABASE=K8M890 Host Bridge pci:v00001106d00004293* ID_MODEL_FROM_DATABASE=PM896 Host Bridge pci:v00001106d00004296* ID_MODEL_FROM_DATABASE=P4M800 Host Bridge pci:v00001106d00004308* ID_MODEL_FROM_DATABASE=PT894 Host Bridge pci:v00001106d00004314* ID_MODEL_FROM_DATABASE=CN700/VN800/P4M800CE/Pro Host Bridge pci:v00001106d00004324* ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge pci:v00001106d00004327* ID_MODEL_FROM_DATABASE=P4M890 Host Bridge pci:v00001106d00004336* ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge pci:v00001106d00004340* ID_MODEL_FROM_DATABASE=PT900 Host Bridge pci:v00001106d00004351* ID_MODEL_FROM_DATABASE=VT3351 Host Bridge pci:v00001106d00004353* ID_MODEL_FROM_DATABASE=VX800/VX820 Power Management Control pci:v00001106d00004364* ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge pci:v00001106d00004409* ID_MODEL_FROM_DATABASE=VX855/VX875 Power Management Control pci:v00001106d00004410* ID_MODEL_FROM_DATABASE=VX900 Power Management and Chip Testing Control pci:v00001106d00004410sv000019DAsd0000A179* ID_MODEL_FROM_DATABASE=VX900 Power Management and Chip Testing Control (ZBOX nano VD01) pci:v00001106d00005030* ID_MODEL_FROM_DATABASE=VT82C596 ACPI [Apollo PRO] pci:v00001106d00005122* ID_MODEL_FROM_DATABASE=VX855/VX875 Chrome 9 HCM Integrated Graphics pci:v00001106d00005208* ID_MODEL_FROM_DATABASE=PT890 I/O APIC Interrupt Controller pci:v00001106d00005238* ID_MODEL_FROM_DATABASE=K8T890 I/O APIC Interrupt Controller pci:v00001106d00005287* ID_MODEL_FROM_DATABASE=VT8251 Serial ATA Controller pci:v00001106d00005290* ID_MODEL_FROM_DATABASE=K8M890 I/O APIC Interrupt Controller pci:v00001106d00005308* ID_MODEL_FROM_DATABASE=PT894 I/O APIC Interrupt Controller pci:v00001106d00005324* ID_MODEL_FROM_DATABASE=VX800 Serial ATA and EIDE Controller pci:v00001106d00005327* ID_MODEL_FROM_DATABASE=P4M890 I/O APIC Interrupt Controller pci:v00001106d00005336* ID_MODEL_FROM_DATABASE=K8M890CE I/O APIC Interrupt Controller pci:v00001106d00005340* ID_MODEL_FROM_DATABASE=PT900 I/O APIC Interrupt Controller pci:v00001106d00005351* ID_MODEL_FROM_DATABASE=VT3351 I/O APIC Interrupt Controller pci:v00001106d00005353* ID_MODEL_FROM_DATABASE=VX800/VX820 APIC and Central Traffic Control pci:v00001106d00005364* ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 I/O APIC Interrupt Controller pci:v00001106d00005372* ID_MODEL_FROM_DATABASE=VT8237/8251 Serial ATA Controller pci:v00001106d00005409* ID_MODEL_FROM_DATABASE=VX855/VX875 APIC and Central Traffic Control pci:v00001106d00005410* ID_MODEL_FROM_DATABASE=VX900 APIC and Central Traffic Control pci:v00001106d00006100* ID_MODEL_FROM_DATABASE=VT85C100A [Rhine II] pci:v00001106d00006287* ID_MODEL_FROM_DATABASE=SATA RAID Controller pci:v00001106d00006290* ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge pci:v00001106d00006327* ID_MODEL_FROM_DATABASE=P4M890 Security Device pci:v00001106d00006353* ID_MODEL_FROM_DATABASE=VX800/VX820 Scratch Registers pci:v00001106d00006364* ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Security Device pci:v00001106d00006409* ID_MODEL_FROM_DATABASE=VX855/VX875 Scratch Registers pci:v00001106d00006410* ID_MODEL_FROM_DATABASE=VX900 Scratch Registers pci:v00001106d00006410sv000019DAsd0000A179* ID_MODEL_FROM_DATABASE=VX900 Scratch Registers (ZBOX nano VD01) pci:v00001106d00007122* ID_MODEL_FROM_DATABASE=VX900 Graphics [Chrome9 HD] pci:v00001106d00007204* ID_MODEL_FROM_DATABASE=K8M800 Host Bridge pci:v00001106d00007205* ID_MODEL_FROM_DATABASE=KM400/KN400/P4M800 [S3 UniChrome] pci:v00001106d00007205sv00001458sd0000D000* ID_MODEL_FROM_DATABASE=KM400/KN400/P4M800 [S3 UniChrome] (Gigabyte GA-7VM400(A)M(F) Motherboard) pci:v00001106d00007205sv00001462sd00007061* ID_MODEL_FROM_DATABASE=KM400/KN400/P4M800 [S3 UniChrome] (MS-7061) pci:v00001106d00007208* ID_MODEL_FROM_DATABASE=PT890 Host Bridge pci:v00001106d00007238* ID_MODEL_FROM_DATABASE=K8T890 Host Bridge pci:v00001106d00007258* ID_MODEL_FROM_DATABASE=PT880 Host Bridge pci:v00001106d00007259* ID_MODEL_FROM_DATABASE=CN333/CN400/PM880 Host Bridge pci:v00001106d00007269* ID_MODEL_FROM_DATABASE=KT880 Host Bridge pci:v00001106d00007282* ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge pci:v00001106d00007290* ID_MODEL_FROM_DATABASE=K8M890 Host Bridge pci:v00001106d00007293* ID_MODEL_FROM_DATABASE=PM896 Host Bridge pci:v00001106d00007296* ID_MODEL_FROM_DATABASE=P4M800 Host Bridge pci:v00001106d00007308* ID_MODEL_FROM_DATABASE=PT894 Host Bridge pci:v00001106d00007314* ID_MODEL_FROM_DATABASE=CN700/VN800/P4M800CE/Pro Host Bridge pci:v00001106d00007324* ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge pci:v00001106d00007327* ID_MODEL_FROM_DATABASE=P4M890 Host Bridge pci:v00001106d00007336* ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge pci:v00001106d00007340* ID_MODEL_FROM_DATABASE=PT900 Host Bridge pci:v00001106d00007351* ID_MODEL_FROM_DATABASE=VT3351 Host Bridge pci:v00001106d00007353* ID_MODEL_FROM_DATABASE=VX800/VX820 North-South Module Interface Control pci:v00001106d00007364* ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge pci:v00001106d00007409* ID_MODEL_FROM_DATABASE=VX855/VX875 North-South Module Interface Control pci:v00001106d00007410* ID_MODEL_FROM_DATABASE=VX900 North-South Module Interface Control pci:v00001106d00007410sv000019DAsd0000A179* ID_MODEL_FROM_DATABASE=VX900 North-South Module Interface Control (ZBOX nano VD01) pci:v00001106d00008231* ID_MODEL_FROM_DATABASE=VT8231 [PCI-to-ISA Bridge] pci:v00001106d00008235* ID_MODEL_FROM_DATABASE=VT8235 ACPI pci:v00001106d00008305* ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133 AGP] pci:v00001106d00008324* ID_MODEL_FROM_DATABASE=CX700/VX700 PCI to ISA Bridge pci:v00001106d00008353* ID_MODEL_FROM_DATABASE=VX800/VX820 Bus Control and Power Management pci:v00001106d00008391* ID_MODEL_FROM_DATABASE=VT8371 [KX133 AGP] pci:v00001106d00008400* ID_MODEL_FROM_DATABASE=MVP4 pci:v00001106d00008409* ID_MODEL_FROM_DATABASE=VX855/VX875 Bus Control and Power Management pci:v00001106d00008410* ID_MODEL_FROM_DATABASE=VX900 Bus Control and Power Management pci:v00001106d00008410sv000019DAsd0000A179* ID_MODEL_FROM_DATABASE=VX900 Bus Control and Power Management (ZBOX VD01) pci:v00001106d00008500* ID_MODEL_FROM_DATABASE=KLE133/PLE133/PLE133T pci:v00001106d00008501* ID_MODEL_FROM_DATABASE=VT8501 [Apollo MVP4 AGP] pci:v00001106d00008596* ID_MODEL_FROM_DATABASE=VT82C596 [Apollo PRO AGP] pci:v00001106d00008597* ID_MODEL_FROM_DATABASE=VT82C597 [Apollo VP3 AGP] pci:v00001106d00008598* ID_MODEL_FROM_DATABASE=VT82C598/694x [Apollo MVP3/Pro133x AGP] pci:v00001106d00008598sv00001019sd00000985* ID_MODEL_FROM_DATABASE=VT82C598/694x [Apollo MVP3/Pro133x AGP] (P6VXA Motherboard) pci:v00001106d00008601* ID_MODEL_FROM_DATABASE=VT8601 [Apollo ProMedia AGP] pci:v00001106d00008605* ID_MODEL_FROM_DATABASE=VT8605 [PM133 AGP] pci:v00001106d00008691* ID_MODEL_FROM_DATABASE=VT82C691 [Apollo Pro] pci:v00001106d00008693* ID_MODEL_FROM_DATABASE=VT82C693 [Apollo Pro Plus] PCI Bridge pci:v00001106d00008A25* ID_MODEL_FROM_DATABASE=PL133/PL133T [S3 ProSavage] pci:v00001106d00008A26* ID_MODEL_FROM_DATABASE=KL133/KL133A/KM133/KM133A [S3 ProSavage] pci:v00001106d00008D01* ID_MODEL_FROM_DATABASE=PN133/PN133T [S3 Twister] pci:v00001106d00008D04* ID_MODEL_FROM_DATABASE=KM266/P4M266/P4M266A/P4N266 [S3 ProSavageDDR] pci:v00001106d00009001* ID_MODEL_FROM_DATABASE=VX900 Serial ATA Controller pci:v00001106d00009082* ID_MODEL_FROM_DATABASE=Standard AHCI 1.0 SATA Controller pci:v00001106d00009140* ID_MODEL_FROM_DATABASE=HDMI Audio Device pci:v00001106d00009201* ID_MODEL_FROM_DATABASE=USB3.0 Controller pci:v00001106d00009530* ID_MODEL_FROM_DATABASE=Secure Digital Memory Card Controller pci:v00001106d000095D0* ID_MODEL_FROM_DATABASE=SDIO Host Controller pci:v00001106d0000A208* ID_MODEL_FROM_DATABASE=PT890 PCI to PCI Bridge Controller pci:v00001106d0000A238* ID_MODEL_FROM_DATABASE=K8T890 PCI to PCI Bridge Controller pci:v00001106d0000A327* ID_MODEL_FROM_DATABASE=P4M890 PCI to PCI Bridge Controller pci:v00001106d0000A353* ID_MODEL_FROM_DATABASE=VX8xx South-North Module Interface Control pci:v00001106d0000A364* ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 PCI to PCI Bridge Controller pci:v00001106d0000A409* ID_MODEL_FROM_DATABASE=VX855/VX875 USB Device Controller pci:v00001106d0000A410* ID_MODEL_FROM_DATABASE=VX900 PCI Express Root Port 0 pci:v00001106d0000B091* ID_MODEL_FROM_DATABASE=VT8633 [Apollo Pro266 AGP] pci:v00001106d0000B099* ID_MODEL_FROM_DATABASE=VT8366/A/7 [Apollo KT266/A/333 AGP] pci:v00001106d0000B101* ID_MODEL_FROM_DATABASE=VT8653 AGP Bridge pci:v00001106d0000B102* ID_MODEL_FROM_DATABASE=VT8362 AGP Bridge pci:v00001106d0000B103* ID_MODEL_FROM_DATABASE=VT8615 AGP Bridge pci:v00001106d0000B112* ID_MODEL_FROM_DATABASE=VT8361 [KLE133] AGP Bridge pci:v00001106d0000B113* ID_MODEL_FROM_DATABASE=VPX/VPX2 I/O APIC Interrupt Controller pci:v00001106d0000B115* ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] PCI Bridge pci:v00001106d0000B168* ID_MODEL_FROM_DATABASE=VT8235 PCI Bridge pci:v00001106d0000B188* ID_MODEL_FROM_DATABASE=VT8237/8251 PCI bridge [K8M890/K8T800/K8T890 South] pci:v00001106d0000B188sv0000147Bsd00001407* ID_MODEL_FROM_DATABASE=VT8237/8251 PCI bridge [K8M890/K8T800/K8T890 South] (KV8-MAX3 motherboard) pci:v00001106d0000B198* ID_MODEL_FROM_DATABASE=VT8237/VX700 PCI Bridge pci:v00001106d0000B213* ID_MODEL_FROM_DATABASE=VPX/VPX2 I/O APIC Interrupt Controller pci:v00001106d0000B353* ID_MODEL_FROM_DATABASE=VX855/VX875/VX900 PCI to PCI Bridge pci:v00001106d0000B410* ID_MODEL_FROM_DATABASE=VX900 PCI Express Root Port 1 pci:v00001106d0000B999* ID_MODEL_FROM_DATABASE=[K8T890 North / VT8237 South] PCI Bridge pci:v00001106d0000C208* ID_MODEL_FROM_DATABASE=PT890 PCI to PCI Bridge Controller pci:v00001106d0000C238* ID_MODEL_FROM_DATABASE=K8T890 PCI to PCI Bridge Controller pci:v00001106d0000C327* ID_MODEL_FROM_DATABASE=P4M890 PCI to PCI Bridge Controller pci:v00001106d0000C340* ID_MODEL_FROM_DATABASE=PT900 PCI to PCI Bridge Controller pci:v00001106d0000C353* ID_MODEL_FROM_DATABASE=VX800/VX820 PCI Express Root Port pci:v00001106d0000C364* ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 PCI to PCI Bridge Controller pci:v00001106d0000C409* ID_MODEL_FROM_DATABASE=VX855/VX875 EIDE Controller pci:v00001106d0000C410* ID_MODEL_FROM_DATABASE=VX900 PCI Express Root Port 2 pci:v00001106d0000D104* ID_MODEL_FROM_DATABASE=VT8237R USB UDCI Controller pci:v00001106d0000D208* ID_MODEL_FROM_DATABASE=PT890 PCI to PCI Bridge Controller pci:v00001106d0000D213* ID_MODEL_FROM_DATABASE=VPX/VPX2 PCI to PCI Bridge Controller pci:v00001106d0000D238* ID_MODEL_FROM_DATABASE=K8T890 PCI to PCI Bridge Controller pci:v00001106d0000D340* ID_MODEL_FROM_DATABASE=PT900 PCI to PCI Bridge Controller pci:v00001106d0000D410* ID_MODEL_FROM_DATABASE=VX900 PCI Express Root Port 3 pci:v00001106d0000E208* ID_MODEL_FROM_DATABASE=PT890 PCI to PCI Bridge Controller pci:v00001106d0000E238* ID_MODEL_FROM_DATABASE=K8T890 PCI to PCI Bridge Controller pci:v00001106d0000E340* ID_MODEL_FROM_DATABASE=PT900 PCI to PCI Bridge Controller pci:v00001106d0000E353* ID_MODEL_FROM_DATABASE=VX800/VX820 PCI Express Root Port pci:v00001106d0000E410* ID_MODEL_FROM_DATABASE=VX900 PCI Express Physical Layer Electrical Sub-block pci:v00001106d0000F208* ID_MODEL_FROM_DATABASE=PT890 PCI to PCI Bridge Controller pci:v00001106d0000F238* ID_MODEL_FROM_DATABASE=K8T890 PCI to PCI Bridge Controller pci:v00001106d0000F340* ID_MODEL_FROM_DATABASE=PT900 PCI to PCI Bridge Controller pci:v00001106d0000F353* ID_MODEL_FROM_DATABASE=VX800/VX820 PCI Express Root Port pci:v00001107* ID_VENDOR_FROM_DATABASE=Stratus Computers pci:v00001107d00000576* ID_MODEL_FROM_DATABASE=VIA VT82C570MV [Apollo] (Wrong vendor ID!) pci:v00001108* ID_VENDOR_FROM_DATABASE=Proteon, Inc. pci:v00001108d00000100* ID_MODEL_FROM_DATABASE=p1690plus_AA pci:v00001108d00000101* ID_MODEL_FROM_DATABASE=p1690plus_AB pci:v00001108d00000105* ID_MODEL_FROM_DATABASE=P1690Plus pci:v00001108d00000108* ID_MODEL_FROM_DATABASE=P1690Plus pci:v00001108d00000138* ID_MODEL_FROM_DATABASE=P1690Plus pci:v00001108d00000139* ID_MODEL_FROM_DATABASE=P1690Plus pci:v00001108d0000013C* ID_MODEL_FROM_DATABASE=P1690Plus pci:v00001108d0000013D* ID_MODEL_FROM_DATABASE=P1690Plus pci:v00001109* ID_VENDOR_FROM_DATABASE=Cogent Data Technologies, Inc. pci:v00001109d00001400* ID_MODEL_FROM_DATABASE=EM110TX [EX110TX] pci:v0000110A* ID_VENDOR_FROM_DATABASE=Siemens AG pci:v0000110Ad00000002* ID_MODEL_FROM_DATABASE=Pirahna 2-port pci:v0000110Ad00000005* ID_MODEL_FROM_DATABASE=Tulip controller, power management, switch extender pci:v0000110Ad00000006* ID_MODEL_FROM_DATABASE=FSC PINC (I/O-APIC) pci:v0000110Ad00000015* ID_MODEL_FROM_DATABASE=FSC Multiprocessor Interrupt Controller pci:v0000110Ad0000001D* ID_MODEL_FROM_DATABASE=FSC Copernicus Management Controller pci:v0000110Ad0000007B* ID_MODEL_FROM_DATABASE=FSC Remote Service Controller, mailbox device pci:v0000110Ad0000007C* ID_MODEL_FROM_DATABASE=FSC Remote Service Controller, shared memory device pci:v0000110Ad0000007D* ID_MODEL_FROM_DATABASE=FSC Remote Service Controller, SMIC device pci:v0000110Ad00002101* ID_MODEL_FROM_DATABASE=HST SAPHIR V Primary PCI (ISDN/PMx) pci:v0000110Ad00002102* ID_MODEL_FROM_DATABASE=DSCC4 PEB/PEF 20534 DMA Supported Serial Communication Controller with 4 Channels pci:v0000110Ad00002104* ID_MODEL_FROM_DATABASE=Eicon Diva 2.02 compatible passive ISDN card pci:v0000110Ad00003141* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5611 / 5621 pci:v0000110Ad00003142* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5613 / 5614 pci:v0000110Ad00003143* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 1613 pci:v0000110Ad00004021* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5512 (Profibus and MPI Cardbus Adapter) pci:v0000110Ad00004029* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5613 A2 pci:v0000110Ad00004029sv0000110Asd00004029* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5613 A2 pci:v0000110Ad00004029sv0000110Asd0000C029* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5613 A2 (SIMATIC NET CP 5614 A2) pci:v0000110Ad00004035* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 1613 A2 pci:v0000110Ad00004036* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 1616 pci:v0000110Ad00004038* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 1604 pci:v0000110Ad00004069* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5623 pci:v0000110Ad00004069sv0000110Asd00004069* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5623 pci:v0000110Ad00004069sv0000110Asd0000C069* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5623 (SIMATIC NET CP 5624) pci:v0000110Ad0000407C* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5612 pci:v0000110Ad0000407D* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5613 A3 pci:v0000110Ad0000407E* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5622 pci:v0000110Ad00004083* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5614 A3 pci:v0000110Ad00004084* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 1626 pci:v0000110Ad00004942* ID_MODEL_FROM_DATABASE=FPGA I-Bus Tracer for MBD pci:v0000110Ad00006120* ID_MODEL_FROM_DATABASE=SZB6120 pci:v0000110B* ID_VENDOR_FROM_DATABASE=Chromatic Research Inc. pci:v0000110Bd00000001* ID_MODEL_FROM_DATABASE=Mpact Media Processor pci:v0000110Bd00000004* ID_MODEL_FROM_DATABASE=Mpact 2 pci:v0000110C* ID_VENDOR_FROM_DATABASE=Mini-Max Technology, Inc. pci:v0000110D* ID_VENDOR_FROM_DATABASE=Znyx Advanced Systems pci:v0000110E* ID_VENDOR_FROM_DATABASE=CPU Technology pci:v0000110F* ID_VENDOR_FROM_DATABASE=Ross Technology pci:v00001110* ID_VENDOR_FROM_DATABASE=Powerhouse Systems pci:v00001110d00006037* ID_MODEL_FROM_DATABASE=Firepower Powerized SMP I/O ASIC pci:v00001110d00006073* ID_MODEL_FROM_DATABASE=Firepower Powerized SMP I/O ASIC pci:v00001111* ID_VENDOR_FROM_DATABASE=Santa Cruz Operation pci:v00001112* ID_VENDOR_FROM_DATABASE=Osicom Technologies Inc pci:v00001112d00002200* ID_MODEL_FROM_DATABASE=FDDI Adapter pci:v00001112d00002300* ID_MODEL_FROM_DATABASE=Fast Ethernet Adapter pci:v00001112d00002340* ID_MODEL_FROM_DATABASE=4 Port Fast Ethernet Adapter pci:v00001112d00002400* ID_MODEL_FROM_DATABASE=ATM Adapter pci:v00001113* ID_VENDOR_FROM_DATABASE=Accton Technology Corporation pci:v00001113d00001211* ID_MODEL_FROM_DATABASE=SMC2-1211TX pci:v00001113d00001211sv0000103Csd00001207* ID_MODEL_FROM_DATABASE=SMC2-1211TX (EN-1207D Fast Ethernet Adapter) pci:v00001113d00001211sv00001113sd00001211* ID_MODEL_FROM_DATABASE=SMC2-1211TX (EN-1207D Fast Ethernet Adapter) pci:v00001113d00001216* ID_MODEL_FROM_DATABASE=EN-1216 Ethernet Adapter pci:v00001113d00001216sv00001113sd00001216* ID_MODEL_FROM_DATABASE=EN-1216 Ethernet Adapter (EN1207F series PCI Fast Ethernet Adapter) pci:v00001113d00001216sv00001113sd00002220* ID_MODEL_FROM_DATABASE=EN-1216 Ethernet Adapter (EN2220A Cardbus Fast Ethernet Adapter) pci:v00001113d00001216sv00001113sd00002242* ID_MODEL_FROM_DATABASE=EN-1216 Ethernet Adapter (EN2242 10/100 Ethernet Mini-PCI Card) pci:v00001113d00001216sv0000111Asd00001020* ID_MODEL_FROM_DATABASE=EN-1216 Ethernet Adapter (SpeedStream 1020 PCI 10/100 Ethernet Adaptor [EN-1207F-TX ?]) pci:v00001113d00001217* ID_MODEL_FROM_DATABASE=EN-1217 Ethernet Adapter pci:v00001113d00005105* ID_MODEL_FROM_DATABASE=10Mbps Network card pci:v00001113d00009211* ID_MODEL_FROM_DATABASE=EN-1207D Fast Ethernet Adapter pci:v00001113d00009211sv00001113sd00009211* ID_MODEL_FROM_DATABASE=EN-1207D Fast Ethernet Adapter pci:v00001113d00009511* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible Fast Ethernet pci:v00001113d0000D301* ID_MODEL_FROM_DATABASE=CPWNA100 (Philips wireless PCMCIA) pci:v00001113d0000EC02* ID_MODEL_FROM_DATABASE=SMC 1244TX v3 pci:v00001113d0000EE23* ID_MODEL_FROM_DATABASE=SMCWPCIT-G 108Mbps Wireless PCI adapter pci:v00001114* ID_VENDOR_FROM_DATABASE=Atmel Corporation pci:v00001114d00000506* ID_MODEL_FROM_DATABASE=at76c506 802.11b Wireless Network Adaptor pci:v00001115* ID_VENDOR_FROM_DATABASE=3D Labs pci:v00001116* ID_VENDOR_FROM_DATABASE=Data Translation pci:v00001116d00000022* ID_MODEL_FROM_DATABASE=DT3001 pci:v00001116d00000023* ID_MODEL_FROM_DATABASE=DT3002 pci:v00001116d00000024* ID_MODEL_FROM_DATABASE=DT3003 pci:v00001116d00000025* ID_MODEL_FROM_DATABASE=DT3004 pci:v00001116d00000026* ID_MODEL_FROM_DATABASE=DT3005 pci:v00001116d00000027* ID_MODEL_FROM_DATABASE=DT3001-PGL pci:v00001116d00000028* ID_MODEL_FROM_DATABASE=DT3003-PGL pci:v00001116d00000051* ID_MODEL_FROM_DATABASE=DT322 pci:v00001116d00000060* ID_MODEL_FROM_DATABASE=DT340 pci:v00001116d00000069* ID_MODEL_FROM_DATABASE=DT332 pci:v00001116d000080C2* ID_MODEL_FROM_DATABASE=DT3162 pci:v00001117* ID_VENDOR_FROM_DATABASE=Datacube, Inc pci:v00001117d00009500* ID_MODEL_FROM_DATABASE=Max-1C SVGA card pci:v00001117d00009501* ID_MODEL_FROM_DATABASE=Max-1C image processing pci:v00001118* ID_VENDOR_FROM_DATABASE=Berg Electronics pci:v00001119* ID_VENDOR_FROM_DATABASE=ICP Vortex Computersysteme GmbH pci:v00001119d00000000* ID_MODEL_FROM_DATABASE=GDT 6000/6020/6050 pci:v00001119d00000001* ID_MODEL_FROM_DATABASE=GDT 6000B/6010 pci:v00001119d00000002* ID_MODEL_FROM_DATABASE=GDT 6110/6510 pci:v00001119d00000003* ID_MODEL_FROM_DATABASE=GDT 6120/6520 pci:v00001119d00000004* ID_MODEL_FROM_DATABASE=GDT 6530 pci:v00001119d00000005* ID_MODEL_FROM_DATABASE=GDT 6550 pci:v00001119d00000006* ID_MODEL_FROM_DATABASE=GDT 6117/6517 pci:v00001119d00000007* ID_MODEL_FROM_DATABASE=GDT 6127/6527 pci:v00001119d00000008* ID_MODEL_FROM_DATABASE=GDT 6537 pci:v00001119d00000009* ID_MODEL_FROM_DATABASE=GDT 6557/6557-ECC pci:v00001119d0000000A* ID_MODEL_FROM_DATABASE=GDT 6115/6515 pci:v00001119d0000000B* ID_MODEL_FROM_DATABASE=GDT 6125/6525 pci:v00001119d0000000C* ID_MODEL_FROM_DATABASE=GDT 6535 pci:v00001119d0000000D* ID_MODEL_FROM_DATABASE=GDT 6555/6555-ECC pci:v00001119d00000100* ID_MODEL_FROM_DATABASE=GDT 6117RP/6517RP pci:v00001119d00000101* ID_MODEL_FROM_DATABASE=GDT 6127RP/6527RP pci:v00001119d00000102* ID_MODEL_FROM_DATABASE=GDT 6537RP pci:v00001119d00000103* ID_MODEL_FROM_DATABASE=GDT 6557RP pci:v00001119d00000104* ID_MODEL_FROM_DATABASE=GDT 6111RP/6511RP pci:v00001119d00000105* ID_MODEL_FROM_DATABASE=GDT 6121RP/6521RP pci:v00001119d00000110* ID_MODEL_FROM_DATABASE=GDT 6117RD/6517RD pci:v00001119d00000111* ID_MODEL_FROM_DATABASE=GDT 6127RD/6527RD pci:v00001119d00000112* ID_MODEL_FROM_DATABASE=GDT 6537RD pci:v00001119d00000113* ID_MODEL_FROM_DATABASE=GDT 6557RD pci:v00001119d00000114* ID_MODEL_FROM_DATABASE=GDT 6111RD/6511RD pci:v00001119d00000115* ID_MODEL_FROM_DATABASE=GDT 6121RD/6521RD pci:v00001119d00000118* ID_MODEL_FROM_DATABASE=GDT 6118RD/6518RD/6618RD pci:v00001119d00000119* ID_MODEL_FROM_DATABASE=GDT 6128RD/6528RD/6628RD pci:v00001119d0000011A* ID_MODEL_FROM_DATABASE=GDT 6538RD/6638RD pci:v00001119d0000011B* ID_MODEL_FROM_DATABASE=GDT 6558RD/6658RD pci:v00001119d00000120* ID_MODEL_FROM_DATABASE=GDT 6117RP2/6517RP2 pci:v00001119d00000121* ID_MODEL_FROM_DATABASE=GDT 6127RP2/6527RP2 pci:v00001119d00000122* ID_MODEL_FROM_DATABASE=GDT 6537RP2 pci:v00001119d00000123* ID_MODEL_FROM_DATABASE=GDT 6557RP2 pci:v00001119d00000124* ID_MODEL_FROM_DATABASE=GDT 6111RP2/6511RP2 pci:v00001119d00000125* ID_MODEL_FROM_DATABASE=GDT 6121RP2/6521RP2 pci:v00001119d00000136* ID_MODEL_FROM_DATABASE=GDT 6113RS/6513RS pci:v00001119d00000137* ID_MODEL_FROM_DATABASE=GDT 6123RS/6523RS pci:v00001119d00000138* ID_MODEL_FROM_DATABASE=GDT 6118RS/6518RS/6618RS pci:v00001119d00000139* ID_MODEL_FROM_DATABASE=GDT 6128RS/6528RS/6628RS pci:v00001119d0000013A* ID_MODEL_FROM_DATABASE=GDT 6538RS/6638RS pci:v00001119d0000013B* ID_MODEL_FROM_DATABASE=GDT 6558RS/6658RS pci:v00001119d0000013C* ID_MODEL_FROM_DATABASE=GDT 6533RS/6633RS pci:v00001119d0000013D* ID_MODEL_FROM_DATABASE=GDT 6543RS/6643RS pci:v00001119d0000013E* ID_MODEL_FROM_DATABASE=GDT 6553RS/6653RS pci:v00001119d0000013F* ID_MODEL_FROM_DATABASE=GDT 6563RS/6663RS pci:v00001119d00000166* ID_MODEL_FROM_DATABASE=GDT 7113RN/7513RN/7613RN pci:v00001119d00000167* ID_MODEL_FROM_DATABASE=GDT 7123RN/7523RN/7623RN pci:v00001119d00000168* ID_MODEL_FROM_DATABASE=GDT 7118RN/7518RN/7518RN pci:v00001119d00000169* ID_MODEL_FROM_DATABASE=GDT 7128RN/7528RN/7628RN pci:v00001119d0000016A* ID_MODEL_FROM_DATABASE=GDT 7538RN/7638RN pci:v00001119d0000016B* ID_MODEL_FROM_DATABASE=GDT 7558RN/7658RN pci:v00001119d0000016C* ID_MODEL_FROM_DATABASE=GDT 7533RN/7633RN pci:v00001119d0000016D* ID_MODEL_FROM_DATABASE=GDT 7543RN/7643RN pci:v00001119d0000016E* ID_MODEL_FROM_DATABASE=GDT 7553RN/7653RN pci:v00001119d0000016F* ID_MODEL_FROM_DATABASE=GDT 7563RN/7663RN pci:v00001119d000001D6* ID_MODEL_FROM_DATABASE=GDT 4x13RZ pci:v00001119d000001D7* ID_MODEL_FROM_DATABASE=GDT 4x23RZ pci:v00001119d000001F6* ID_MODEL_FROM_DATABASE=GDT 8x13RZ pci:v00001119d000001F7* ID_MODEL_FROM_DATABASE=GDT 8x23RZ pci:v00001119d000001FC* ID_MODEL_FROM_DATABASE=GDT 8x33RZ pci:v00001119d000001FD* ID_MODEL_FROM_DATABASE=GDT 8x43RZ pci:v00001119d000001FE* ID_MODEL_FROM_DATABASE=GDT 8x53RZ pci:v00001119d000001FF* ID_MODEL_FROM_DATABASE=GDT 8x63RZ pci:v00001119d00000210* ID_MODEL_FROM_DATABASE=GDT 6519RD/6619RD pci:v00001119d00000211* ID_MODEL_FROM_DATABASE=GDT 6529RD/6629RD pci:v00001119d00000260* ID_MODEL_FROM_DATABASE=GDT 7519RN/7619RN pci:v00001119d00000261* ID_MODEL_FROM_DATABASE=GDT 7529RN/7629RN pci:v00001119d000002FF* ID_MODEL_FROM_DATABASE=GDT MAXRP pci:v00001119d00000300* ID_MODEL_FROM_DATABASE=GDT NEWRX pci:v00001119d00000301* ID_MODEL_FROM_DATABASE=GDT NEWRX2 pci:v0000111A* ID_VENDOR_FROM_DATABASE=Efficient Networks, Inc pci:v0000111Ad00000000* ID_MODEL_FROM_DATABASE=155P-MF1 (FPGA) pci:v0000111Ad00000002* ID_MODEL_FROM_DATABASE=155P-MF1 (ASIC) pci:v0000111Ad00000003* ID_MODEL_FROM_DATABASE=ENI-25P ATM pci:v0000111Ad00000003sv0000111Asd00000000* ID_MODEL_FROM_DATABASE=ENI-25P ATM (ENI-25p Miniport ATM Adapter) pci:v0000111Ad00000005* ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) pci:v0000111Ad00000005sv0000111Asd00000001* ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3010 ATM) pci:v0000111Ad00000005sv0000111Asd00000009* ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3060 ADSL (VPI=0)) pci:v0000111Ad00000005sv0000111Asd00000101* ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3010 ATM) pci:v0000111Ad00000005sv0000111Asd00000109* ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3060CO ADSL (VPI=0)) pci:v0000111Ad00000005sv0000111Asd00000809* ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3060 ADSL (VPI=0 or 8)) pci:v0000111Ad00000005sv0000111Asd00000909* ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3060CO ADSL (VPI=0 or 8)) pci:v0000111Ad00000005sv0000111Asd00000A09* ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3060 ADSL (VPI=<0..15>)) pci:v0000111Ad00000007* ID_MODEL_FROM_DATABASE=SpeedStream ADSL pci:v0000111Ad00000007sv0000111Asd00001001* ID_MODEL_FROM_DATABASE=SpeedStream ADSL (ENI-3061 ADSL [ASIC]) pci:v0000111Ad00001020* ID_MODEL_FROM_DATABASE=SpeedStream PCI 10/100 Network Card pci:v0000111Ad00001203* ID_MODEL_FROM_DATABASE=SpeedStream 1023 Wireless PCI Adapter pci:v0000111B* ID_VENDOR_FROM_DATABASE=Teledyne Electronic Systems pci:v0000111C* ID_VENDOR_FROM_DATABASE=Tricord Systems Inc. pci:v0000111Cd00000001* ID_MODEL_FROM_DATABASE=Powerbis Bridge pci:v0000111D* ID_VENDOR_FROM_DATABASE=Integrated Device Technology, Inc. [IDT] pci:v0000111Dd00000001* ID_MODEL_FROM_DATABASE=IDT77201/77211 155Mbps ATM SAR Controller [NICStAR] pci:v0000111Dd00000003* ID_MODEL_FROM_DATABASE=IDT77222/77252 155Mbps ATM MICRO ABR SAR Controller pci:v0000111Dd00000004* ID_MODEL_FROM_DATABASE=IDT77V252 155Mbps ATM MICRO ABR SAR Controller pci:v0000111Dd00000005* ID_MODEL_FROM_DATABASE=IDT77V222 155Mbps ATM MICRO ABR SAR Controller pci:v0000111Dd00008018* ID_MODEL_FROM_DATABASE=PES12N3A PCI Express Switch pci:v0000111Dd0000801C* ID_MODEL_FROM_DATABASE=PES24N3A PCI Express Switch pci:v0000111Dd00008028* ID_MODEL_FROM_DATABASE=PES4T4 PCI Express Switch pci:v0000111Dd0000802B* ID_MODEL_FROM_DATABASE=PES8T5A PCI Express Switch pci:v0000111Dd0000802C* ID_MODEL_FROM_DATABASE=PES16T4 PCI Express Switch pci:v0000111Dd0000802D* ID_MODEL_FROM_DATABASE=PES16T7 PCI Express Switch pci:v0000111Dd0000802E* ID_MODEL_FROM_DATABASE=PES24T6 PCI Express Switch pci:v0000111Dd0000802F* ID_MODEL_FROM_DATABASE=PES32T8 PCI Express Switch pci:v0000111Dd00008032* ID_MODEL_FROM_DATABASE=PES48T12 PCI Express Switch pci:v0000111Dd00008034* ID_MODEL_FROM_DATABASE=PES16/22/34H16 PCI Express Switch pci:v0000111Dd00008035* ID_MODEL_FROM_DATABASE=PES32H8 PCI Express Switch pci:v0000111Dd00008036* ID_MODEL_FROM_DATABASE=PES48H12 PCI Express Switch pci:v0000111Dd00008037* ID_MODEL_FROM_DATABASE=PES64H16 PCI Express Switch pci:v0000111Dd00008039* ID_MODEL_FROM_DATABASE=PES3T3 PCI Express Switch pci:v0000111Dd0000803A* ID_MODEL_FROM_DATABASE=PES4T4 PCI Express Switch pci:v0000111Dd0000803C* ID_MODEL_FROM_DATABASE=PES5T5 PCI Express Switch pci:v0000111Dd0000803D* ID_MODEL_FROM_DATABASE=PES6T5 PCI Express Switch pci:v0000111Dd00008048* ID_MODEL_FROM_DATABASE=PES8NT2 PCI Express Switch pci:v0000111Dd00008049* ID_MODEL_FROM_DATABASE=PES8NT2 PCI Express Switch pci:v0000111Dd0000804A* ID_MODEL_FROM_DATABASE=PES8NT2 PCI Express Internal NTB pci:v0000111Dd0000804B* ID_MODEL_FROM_DATABASE=PES8NT2 PCI Express External NTB pci:v0000111Dd0000804C* ID_MODEL_FROM_DATABASE=PES16NT2 PCI Express Switch pci:v0000111Dd0000804D* ID_MODEL_FROM_DATABASE=PES16NT2 PCI Express Switch pci:v0000111Dd0000804E* ID_MODEL_FROM_DATABASE=PES16NT2 PCI Express Internal NTB pci:v0000111Dd0000804F* ID_MODEL_FROM_DATABASE=PES16NT2 PCI Express External NTB pci:v0000111Dd00008058* ID_MODEL_FROM_DATABASE=PES12NT3 PCI Express Switch pci:v0000111Dd00008059* ID_MODEL_FROM_DATABASE=PES12NT3 PCI Express Switch pci:v0000111Dd0000805A* ID_MODEL_FROM_DATABASE=PES12NT3 PCI Express Internal NTB pci:v0000111Dd0000805B* ID_MODEL_FROM_DATABASE=PES12NT3 PCI Express External NTB pci:v0000111Dd0000805C* ID_MODEL_FROM_DATABASE=PES24NT3 PCI Express Switch pci:v0000111Dd0000805D* ID_MODEL_FROM_DATABASE=PES24NT3 PCI Express Switch pci:v0000111Dd0000805E* ID_MODEL_FROM_DATABASE=PES24NT3 PCI Express Internal NTB pci:v0000111Dd0000805F* ID_MODEL_FROM_DATABASE=PES24NT3 PCI Express External NTB pci:v0000111Dd00008060* ID_MODEL_FROM_DATABASE=PES16T4G2 PCI Express Gen2 Switch pci:v0000111Dd00008061* ID_MODEL_FROM_DATABASE=PES12T3G2 PCI Express Gen2 Switch pci:v0000111Dd00008068* ID_MODEL_FROM_DATABASE=PES6T6G2 PCI Express Gen2 Switch pci:v0000111Dd0000806A* ID_MODEL_FROM_DATABASE=PES24T3G2 PCI Express Gen2 Switch pci:v0000111Dd0000806Asv000014C1sd0000000C* ID_MODEL_FROM_DATABASE=PES24T3G2 PCI Express Gen2 Switch (10G-PCIE2-8B2) pci:v0000111Dd0000806C* ID_MODEL_FROM_DATABASE=PES16T4A/4T4G2 PCI Express Gen2 Switch pci:v0000111Dd0000806E* ID_MODEL_FROM_DATABASE=PES24T6G2 PCI Express Gen2 Switch pci:v0000111Dd0000806F* ID_MODEL_FROM_DATABASE=HIO524G2 PCI Express Gen2 Switch pci:v0000111Dd00008088* ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch pci:v0000111Dd00008088sv00001093sd0000752F* ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8383mc Device) pci:v0000111Dd00008088sv00001093sd00007543* ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8383mc System Host) pci:v0000111Dd00008088sv00001093sd0000755C* ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8364) pci:v0000111Dd00008088sv00001093sd0000755D* ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8374) pci:v0000111Dd00008088sv00001093sd000075FF* ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8383mc DMA) pci:v0000111Dd00008088sv00001093sd00007600* ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8383mc DMA) pci:v0000111Dd00008088sv00001093sd00007602* ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8384) pci:v0000111Dd0000808F* ID_MODEL_FROM_DATABASE=PES32NT8AG2 pci:v0000111Dd000080CF* ID_MODEL_FROM_DATABASE=F32P08xG3 [PCIe boot mode] pci:v0000111Dd000080D2* ID_MODEL_FROM_DATABASE=F32P08xG3 NVMe controller pci:v0000111E* ID_VENDOR_FROM_DATABASE=Eldec pci:v0000111F* ID_VENDOR_FROM_DATABASE=Precision Digital Images pci:v0000111Fd00004A47* ID_MODEL_FROM_DATABASE=Precision MX Video engine interface pci:v0000111Fd00005243* ID_MODEL_FROM_DATABASE=Frame capture bus interface pci:v00001120* ID_VENDOR_FROM_DATABASE=EMC Corporation pci:v00001121* ID_VENDOR_FROM_DATABASE=Zilog pci:v00001122* ID_VENDOR_FROM_DATABASE=Multi-tech Systems, Inc. pci:v00001123* ID_VENDOR_FROM_DATABASE=Excellent Design, Inc. pci:v00001124* ID_VENDOR_FROM_DATABASE=Leutron Vision AG pci:v00001124d00002581* ID_MODEL_FROM_DATABASE=Picport Monochrome pci:v00001125* ID_VENDOR_FROM_DATABASE=Eurocore pci:v00001126* ID_VENDOR_FROM_DATABASE=Vigra pci:v00001127* ID_VENDOR_FROM_DATABASE=FORE Systems Inc pci:v00001127d00000200* ID_MODEL_FROM_DATABASE=ForeRunner PCA-200 ATM pci:v00001127d00000210* ID_MODEL_FROM_DATABASE=PCA-200PC pci:v00001127d00000250* ID_MODEL_FROM_DATABASE=ATM pci:v00001127d00000300* ID_MODEL_FROM_DATABASE=ForeRunner PCA-200EPC ATM pci:v00001127d00000310* ID_MODEL_FROM_DATABASE=ATM pci:v00001127d00000400* ID_MODEL_FROM_DATABASE=ForeRunnerHE ATM Adapter pci:v00001127d00000400sv00001127sd00000400* ID_MODEL_FROM_DATABASE=ForeRunnerHE ATM Adapter (ForeRunnerHE ATM) pci:v00001129* ID_VENDOR_FROM_DATABASE=Firmworks pci:v0000112A* ID_VENDOR_FROM_DATABASE=Hermes Electronics Company, Ltd. pci:v0000112B* ID_VENDOR_FROM_DATABASE=Linotype - Hell AG pci:v0000112C* ID_VENDOR_FROM_DATABASE=Zenith Data Systems pci:v0000112D* ID_VENDOR_FROM_DATABASE=Ravicad pci:v0000112E* ID_VENDOR_FROM_DATABASE=Infomedia Microelectronics Inc. pci:v0000112F* ID_VENDOR_FROM_DATABASE=Dalsa Inc. pci:v0000112Fd00000000* ID_MODEL_FROM_DATABASE=MVC IC-PCI pci:v0000112Fd00000001* ID_MODEL_FROM_DATABASE=MVC IM-PCI Video frame grabber/processor pci:v0000112Fd00000008* ID_MODEL_FROM_DATABASE=PC-CamLink PCI framegrabber pci:v00001130* ID_VENDOR_FROM_DATABASE=Computervision pci:v00001131* ID_VENDOR_FROM_DATABASE=Philips Semiconductors pci:v00001131d00001561* ID_MODEL_FROM_DATABASE=USB 1.1 Host Controller pci:v00001131d00001561sv00001775sd0000C200* ID_MODEL_FROM_DATABASE=USB 1.1 Host Controller (C2K onboard USB 1.1 host controller) pci:v00001131d00001562* ID_MODEL_FROM_DATABASE=USB 2.0 Host Controller pci:v00001131d00001562sv00001775sd0000C200* ID_MODEL_FROM_DATABASE=USB 2.0 Host Controller (C2K onboard USB 2.0 host controller) pci:v00001131d00003400* ID_MODEL_FROM_DATABASE=SmartPCI56(UCB1500) 56K Modem pci:v00001131d00005400* ID_MODEL_FROM_DATABASE=TriMedia TM1000/1100 pci:v00001131d00005400sv000012CAsd00000000* ID_MODEL_FROM_DATABASE=TriMedia TM1000/1100 (BlueICE) pci:v00001131d00005402* ID_MODEL_FROM_DATABASE=TriMedia TM1300 pci:v00001131d00005402sv00001244sd00000F00* ID_MODEL_FROM_DATABASE=TriMedia TM1300 (Fritz!Card DSL) pci:v00001131d00005402sv000015EBsd00001300* ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1300) pci:v00001131d00005402sv000015EBsd00001302* ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1302) pci:v00001131d00005402sv000015EBsd00001304* ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1304) pci:v00001131d00005402sv000015EBsd00001305* ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1305) pci:v00001131d00005402sv000015EBsd00001306* ID_MODEL_FROM_DATABASE=TriMedia TM1300 (PMCDT1306) pci:v00001131d00005402sv000015EBsd00001308* ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1308) pci:v00001131d00005402sv000015EBsd00001331* ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1301 with SAA7121) pci:v00001131d00005402sv000015EBsd00001337* ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1301 with SAA7127) pci:v00001131d00005402sv000015EBsd00002D3D* ID_MODEL_FROM_DATABASE=TriMedia TM1300 (X3D) pci:v00001131d00005402sv000015EBsd00007022* ID_MODEL_FROM_DATABASE=TriMedia TM1300 (PTM1300) pci:v00001131d00005405* ID_MODEL_FROM_DATABASE=TriMedia TM1500 pci:v00001131d00005405sv00001136sd00000005* ID_MODEL_FROM_DATABASE=TriMedia TM1500 (LCP-1500) pci:v00001131d00005406* ID_MODEL_FROM_DATABASE=TriMedia TM1700 pci:v00001131d0000540B* ID_MODEL_FROM_DATABASE=PNX1005 Media Processor pci:v00001131d0000540Bsv00001131sd00000020* ID_MODEL_FROM_DATABASE=PNX1005 Media Processor (PNXLite PCI Demo Board) pci:v00001131d00007130* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder pci:v00001131d00007130sv00000000sd00004016* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Behold TV 401) pci:v00001131d00007130sv00000000sd00004051* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Behold TV 405 FM) pci:v00001131d00007130sv00000000sd00005051* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Behold TV 505 RDS) pci:v00001131d00007130sv00000000sd0000505B* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Behold TV 505 RDS) pci:v00001131d00007130sv0000102Bsd000048D0* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Matrox CronosPlus) pci:v00001131d00007130sv00001048sd0000226B* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (ELSA EX-VISION 300TV) pci:v00001131d00007130sv0000107Dsd00006655* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (WinFast DTV1000S) pci:v00001131d00007130sv00001131sd00000000* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (SAA7130-based TV tuner card) pci:v00001131d00007130sv00001131sd00002001* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (10MOONS PCI TV CAPTURE CARD) pci:v00001131d00007130sv00001131sd00002005* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Techcom (India) TV Tuner Card (SSD-TV-670)) pci:v00001131d00007130sv00001458sd00009006* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (GT-PS700 DVB-S tuner) pci:v00001131d00007130sv00001461sd0000050C* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Nagase Sangyo TransGear 3000TV) pci:v00001131d00007130sv00001461sd000010FF* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (AVerMedia DVD EZMaker) pci:v00001131d00007130sv00001461sd00002108* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (AverMedia AverTV/305) pci:v00001131d00007130sv00001461sd00002115* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (AverMedia AverTV Studio 305) pci:v00001131d00007130sv0000153Bsd00001152* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Terratec Cinergy 200 TV) pci:v00001131d00007130sv0000185Bsd0000C100* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Compro VideoMate TV PVR/FM) pci:v00001131d00007130sv0000185Bsd0000C901* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Videomate DVB-T200) pci:v00001131d00007130sv00005168sd00000138* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (LifeView FlyVIDEO2000) pci:v00001131d00007130sv00005ACEsd00005010* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Behold TV 501) pci:v00001131d00007130sv00005ACEsd00005050* ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Behold TV 505 FM) pci:v00001131d00007133* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder pci:v00001131d00007133sv00000000sd00004091* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Beholder BeholdTV 409 FM) pci:v00001131d00007133sv00000000sd00005071* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 507 RDS) pci:v00001131d00007133sv00000000sd0000507B* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 507 RDS) pci:v00001131d00007133sv00000000sd00005201* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV Columbus) pci:v00001131d00007133sv00000070sd00006701* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (WinTV HVR-1110) pci:v00001131d00007133sv00001019sd00004CB5* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM)) pci:v00001131d00007133sv00001043sd00000210* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (FlyTV mini Asus Digimatrix) pci:v00001131d00007133sv00001043sd00004843* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (ASUS TV-FM 7133) pci:v00001131d00007133sv00001043sd00004845* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (TV-FM 7135) pci:v00001131d00007133sv00001043sd00004862* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (P7131 Dual) pci:v00001131d00007133sv00001043sd00004876* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (My Cinema-P7131 Hybrid) pci:v00001131d00007133sv00001131sd00000000* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (SAA713x-based TV tuner card) pci:v00001131d00007133sv00001131sd00002001* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Proteus Pro [philips reference design]) pci:v00001131d00007133sv00001131sd00002018* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Tiger reference design) pci:v00001131d00007133sv00001131sd00004EE9* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (MonsterTV Mobile) pci:v00001131d00007133sv00001131sd00007133* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Pinnacle PCTV 301i) pci:v00001131d00007133sv000011BDsd0000002B* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (PCTV Stereo) pci:v00001131d00007133sv000011BDsd0000002E* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (PCTV 110i (saa7133)) pci:v00001131d00007133sv000012ABsd00000800* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (PURPLE TV) pci:v00001131d00007133sv000013C2sd00002804* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Technotrend Budget T-3000 Hybrid) pci:v00001131d00007133sv00001421sd00000335* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Instant TV DVB-T Cardbus) pci:v00001131d00007133sv00001421sd00001370* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Instant TV (saa7135)) pci:v00001131d00007133sv00001435sd00007330* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (VFG7330) pci:v00001131d00007133sv00001435sd00007350* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (VFG7350) pci:v00001131d00007133sv00001458sd00009001* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (GC-PTV-TAF Hybrid TV card) pci:v00001131d00007133sv00001458sd00009002* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (GT-PTV-TAF-RH DVB-T/Analog TV/FM tuner) pci:v00001131d00007133sv00001458sd00009003* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (GT-PTV-AF-RH Analog TV/FM tuner) pci:v00001131d00007133sv00001458sd00009004* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (GT-P8000 DVB-T/Analog TV/FM tuner) pci:v00001131d00007133sv00001458sd00009005* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (GT-P6000 Analog TV/FM tuner) pci:v00001131d00007133sv00001458sd00009008* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (GT-P5100 Analog TV tuner) pci:v00001131d00007133sv00001461sd00001044* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (AVerTVHD MCE A180) pci:v00001131d00007133sv00001461sd00004836* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (M10D Hybrid DVBT) pci:v00001131d00007133sv00001461sd0000861E* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (M105 PAL/SECAM/NTSC/FM Tuner) pci:v00001131d00007133sv00001461sd0000A14B* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (AVerTV Studio 509) pci:v00001131d00007133sv00001461sd0000A836* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (M115 DVB-T, PAL/SECAM/NTSC Tuner) pci:v00001131d00007133sv00001461sd0000F01D* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (DVB-T Super 007) pci:v00001131d00007133sv00001461sd0000F31F* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Avermedia AVerTV GO 007 FM) pci:v00001131d00007133sv00001461sd0000F936* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Hybrid+FM PCI (rev A16D)) pci:v00001131d00007133sv00001462sd00006231* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (TV@nywhere Plus) pci:v00001131d00007133sv00001489sd00000214* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyTV Platinum FM) pci:v00001131d00007133sv000014C0sd00001212* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyTV Platinum Mini2) pci:v00001131d00007133sv0000153Bsd00001160* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Cinergy 250 PCI TV) pci:v00001131d00007133sv0000153Bsd00001162* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Terratec Cinergy 400 mobile) pci:v00001131d00007133sv000017DEsd00007256* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (PlusTV All In One PI610 card) pci:v00001131d00007133sv000017DEsd00007350* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (ATSC 110 Digital / Analog HDTV Tuner) pci:v00001131d00007133sv000017DEsd00007352* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (ATSC 115 Digital / Analog HDTV Tuner) pci:v00001131d00007133sv0000185Bsd0000C100* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (VideoMate TV) pci:v00001131d00007133sv0000185Bsd0000C900* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (VideoMate T750) pci:v00001131d00007133sv00005168sd00000306* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB-T DUO) pci:v00001131d00007133sv00005168sd00000319* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB Trio) pci:v00001131d00007133sv00005168sd00000502* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB-T Duo CardBus) pci:v00001131d00007133sv00005168sd00000520* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB Trio CardBus) pci:v00001131d00007133sv00005168sd00001502* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyTV CardBus) pci:v00001131d00007133sv00005168sd00002502* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB-T CardBus) pci:v00001131d00007133sv00005168sd00002520* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB-S Duo CardBus) pci:v00001131d00007133sv00005168sd00003502* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB-T Hybrid CardBus) pci:v00001131d00007133sv00005168sd00003520* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB Trio N CardBus) pci:v00001131d00007133sv00005ACEsd00005030* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 503 FM) pci:v00001131d00007133sv00005ACEsd00005090* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 509 FM) pci:v00001131d00007133sv00005ACEsd00006090* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 609 FM) pci:v00001131d00007133sv00005ACEsd00006091* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 609 FM) pci:v00001131d00007133sv00005ACEsd00006092* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 609 RDS) pci:v00001131d00007133sv00005ACEsd00006093* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 609 RDS) pci:v00001131d00007133sv00005ACEsd00006190* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV M6) pci:v00001131d00007133sv00005ACEsd00006191* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV M63) pci:v00001131d00007133sv00005ACEsd00006193* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV M6 Extra) pci:v00001131d00007133sv00005ACEsd00006290* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV H6) pci:v00001131d00007133sv00005ACEsd00007090* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV A7) pci:v00001131d00007133sv00005ACEsd00007150* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV H75) pci:v00001131d00007133sv00005ACEsd00007151* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV H75) pci:v00001131d00007133sv00005ACEsd00007190* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV H7) pci:v00001131d00007133sv00005ACEsd00007191* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV H7) pci:v00001131d00007133sv00005ACEsd00007290* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV T7) pci:v00001131d00007133sv00005ACEsd00007591* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV X7) pci:v00001131d00007133sv00005ACEsd00007595* ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV X7) pci:v00001131d00007134* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder pci:v00001131d00007134sv00000000sd00004036* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 403) pci:v00001131d00007134sv00000000sd00004037* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 403 FM) pci:v00001131d00007134sv00000000sd00004071* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 407 FM) pci:v00001131d00007134sv00001019sd00004CB4* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM)) pci:v00001131d00007134sv00001043sd00000210* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Digimatrix TV) pci:v00001131d00007134sv00001043sd00004840* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (ASUS TV-FM 7134) pci:v00001131d00007134sv00001043sd00004842* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (TV-FM 7134) pci:v00001131d00007134sv00001131sd00000000* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (SAA713x-based TV tuner card) pci:v00001131d00007134sv00001131sd00002004* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (EUROPA V3 reference design) pci:v00001131d00007134sv00001131sd00004E85* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (SKNet Monster TV) pci:v00001131d00007134sv00001131sd00006752* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (EMPRESS) pci:v00001131d00007134sv000011BDsd0000002B* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (PCTV Stereo) pci:v00001131d00007134sv000011BDsd0000002D* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (PCTV 300i DVB-T + PAL) pci:v00001131d00007134sv00001461sd00002C00* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (AverTV Hybrid+FM PCI) pci:v00001131d00007134sv00001461sd00009715* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (AVerTV Studio 307) pci:v00001131d00007134sv00001461sd0000A70A* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Avermedia AVerTV 307) pci:v00001131d00007134sv00001461sd0000A70B* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (AverMedia M156 / Medion 2819) pci:v00001131d00007134sv00001461sd0000D6EE* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Cardbus TV/Radio (E500)) pci:v00001131d00007134sv00001471sd0000B7E9* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (AVerTV Cardbus plus) pci:v00001131d00007134sv0000153Bsd00001142* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Terratec Cinergy 400 TV) pci:v00001131d00007134sv0000153Bsd00001143* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Terratec Cinergy 600 TV) pci:v00001131d00007134sv0000153Bsd00001158* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Terratec Cinergy 600 TV MK3) pci:v00001131d00007134sv00001540sd00009524* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (ProVideo PV952) pci:v00001131d00007134sv000016BEsd00000003* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Medion 7134) pci:v00001131d00007134sv0000185Bsd0000C200* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Compro VideoMate Gold+ Pal) pci:v00001131d00007134sv0000185Bsd0000C900* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Videomate DVB-T300) pci:v00001131d00007134sv00001894sd0000A006* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (KNC One TV-Station DVR) pci:v00001131d00007134sv00001894sd0000FE01* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (KNC One TV-Station RDS / Typhoon TV Tuner RDS) pci:v00001131d00007134sv00005168sd00000138* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (FLY TV PRIME 34FM) pci:v00001131d00007134sv00005168sd00000300* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (FlyDVB-S) pci:v00001131d00007134sv00005ACEsd00005070* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 507 FM) pci:v00001131d00007134sv00005ACEsd00006070* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 607 FM) pci:v00001131d00007134sv00005ACEsd00006071* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 607 FM) pci:v00001131d00007134sv00005ACEsd00006072* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 607 RDS) pci:v00001131d00007134sv00005ACEsd00006073* ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 607 RDS) pci:v00001131d00007145* ID_MODEL_FROM_DATABASE=SAA7145 pci:v00001131d00007146* ID_MODEL_FROM_DATABASE=SAA7146 pci:v00001131d00007146sv0000110Asd00000000* ID_MODEL_FROM_DATABASE=SAA7146 (Fujitsu/Siemens DVB-C card rev1.5) pci:v00001131d00007146sv0000110Asd0000FFFF* ID_MODEL_FROM_DATABASE=SAA7146 (Fujitsu/Siemens DVB-C card rev1.5) pci:v00001131d00007146sv00001124sd00002581* ID_MODEL_FROM_DATABASE=SAA7146 (Leutron Vision PicPort) pci:v00001131d00007146sv00001131sd00004F56* ID_MODEL_FROM_DATABASE=SAA7146 (KNC1 DVB-S Budget) pci:v00001131d00007146sv00001131sd00004F60* ID_MODEL_FROM_DATABASE=SAA7146 (Fujitsu-Siemens Activy DVB-S Budget Rev AL) pci:v00001131d00007146sv00001131sd00004F61* ID_MODEL_FROM_DATABASE=SAA7146 (Activy DVB-S Budget Rev GR) pci:v00001131d00007146sv00001131sd00005F61* ID_MODEL_FROM_DATABASE=SAA7146 (Activy DVB-T Budget) pci:v00001131d00007146sv0000114Bsd00002003* ID_MODEL_FROM_DATABASE=SAA7146 (DVRaptor Video Edit/Capture Card) pci:v00001131d00007146sv000011BDsd00000006* ID_MODEL_FROM_DATABASE=SAA7146 (DV500 Overlay) pci:v00001131d00007146sv000011BDsd0000000A* ID_MODEL_FROM_DATABASE=SAA7146 (DV500 Overlay) pci:v00001131d00007146sv000011BDsd0000000F* ID_MODEL_FROM_DATABASE=SAA7146 (DV500 Overlay) pci:v00001131d00007146sv000013C2sd00000000* ID_MODEL_FROM_DATABASE=SAA7146 (Siemens/Technotrend/Hauppauge DVB card rev1.3 or rev1.5) pci:v00001131d00007146sv000013C2sd00000001* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev1.3 or rev1.6) pci:v00001131d00007146sv000013C2sd00000002* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev2.1) pci:v00001131d00007146sv000013C2sd00000003* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev2.1) pci:v00001131d00007146sv000013C2sd00000004* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev2.1) pci:v00001131d00007146sv000013C2sd00000006* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev1.3 or rev1.6) pci:v00001131d00007146sv000013C2sd00000008* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB-T) pci:v00001131d00007146sv000013C2sd0000000A* ID_MODEL_FROM_DATABASE=SAA7146 (Octal/Technotrend DVB-C for iTV) pci:v00001131d00007146sv000013C2sd0000000E* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev2.3) pci:v00001131d00007146sv000013C2sd00001003* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend-Budget/Hauppauge WinTV-NOVA-S DVB card) pci:v00001131d00007146sv000013C2sd00001004* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend-Budget/Hauppauge WinTV-NOVA-C DVB card) pci:v00001131d00007146sv000013C2sd00001005* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend-Budget/Hauppauge WinTV-NOVA-T DVB card) pci:v00001131d00007146sv000013C2sd0000100C* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend-Budget/Hauppauge WinTV-NOVA-CI DVB card) pci:v00001131d00007146sv000013C2sd0000100F* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend-Budget/Hauppauge WinTV-NOVA-CI DVB card) pci:v00001131d00007146sv000013C2sd00001010* ID_MODEL_FROM_DATABASE=SAA7146 (DVB C-1500) pci:v00001131d00007146sv000013C2sd00001011* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend-Budget/Hauppauge WinTV-NOVA-T DVB card) pci:v00001131d00007146sv000013C2sd00001012* ID_MODEL_FROM_DATABASE=SAA7146 (DVB T-1500) pci:v00001131d00007146sv000013C2sd00001013* ID_MODEL_FROM_DATABASE=SAA7146 (SATELCO Multimedia DVB) pci:v00001131d00007146sv000013C2sd00001016* ID_MODEL_FROM_DATABASE=SAA7146 (WinTV-NOVA-SE DVB card) pci:v00001131d00007146sv000013C2sd00001018* ID_MODEL_FROM_DATABASE=SAA7146 (DVB S-1401) pci:v00001131d00007146sv000013C2sd00001019* ID_MODEL_FROM_DATABASE=SAA7146 (S2-3200) pci:v00001131d00007146sv000013C2sd00001102* ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev2.1) pci:v00001131d00007146sv0000153Bsd00001155* ID_MODEL_FROM_DATABASE=SAA7146 (Cinergy 1200 DVB-S) pci:v00001131d00007146sv0000153Bsd00001156* ID_MODEL_FROM_DATABASE=SAA7146 (Cinergy 1200 DVB-C) pci:v00001131d00007146sv0000153Bsd00001157* ID_MODEL_FROM_DATABASE=SAA7146 (Cinergy 1200 DVB-T) pci:v00001131d00007146sv0000153Bsd00001176* ID_MODEL_FROM_DATABASE=SAA7146 (Cinergy 1200 DVB-C (MK3)) pci:v00001131d00007146sv00001894sd00000020* ID_MODEL_FROM_DATABASE=SAA7146 (KNC One DVB-C V1.0) pci:v00001131d00007146sv00001894sd00000023* ID_MODEL_FROM_DATABASE=SAA7146 (TVStation DVB-C plus) pci:v00001131d00007146sv00001894sd00000054* ID_MODEL_FROM_DATABASE=SAA7146 (TV-Station DVB-S) pci:v00001131d00007160* ID_MODEL_FROM_DATABASE=SAA7160 pci:v00001131d00007160sv00001458sd00009009* ID_MODEL_FROM_DATABASE=SAA7160 (E8000 DVB-T/Analog TV/FM tuner) pci:v00001131d00007160sv00001461sd00001455* ID_MODEL_FROM_DATABASE=SAA7160 (AVerTV Hybrid Speedy PCI-E (H788)) pci:v00001131d00007162* ID_MODEL_FROM_DATABASE=SAA7162 pci:v00001131d00007162sv000011BDsd00000101* ID_MODEL_FROM_DATABASE=SAA7162 (Pinnacle PCTV 7010iX TV Card) pci:v00001131d00007164* ID_MODEL_FROM_DATABASE=SAA7164 pci:v00001131d00007164sv00000070sd00008800* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) pci:v00001131d00007164sv00000070sd00008810* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) pci:v00001131d00007164sv00000070sd00008851* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) pci:v00001131d00007164sv00000070sd00008853* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) pci:v00001131d00007164sv00000070sd00008880* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) pci:v00001131d00007164sv00000070sd00008891* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) pci:v00001131d00007164sv00000070sd000088A0* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) pci:v00001131d00007164sv00000070sd000088A1* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) pci:v00001131d00007164sv00000070sd00008900* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) pci:v00001131d00007164sv00000070sd00008901* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) pci:v00001131d00007164sv00000070sd00008940* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200 (submodel 89619)) pci:v00001131d00007164sv00000070sd00008951* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) pci:v00001131d00007164sv00000070sd00008953* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) pci:v00001131d00007164sv00000070sd00008980* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) pci:v00001131d00007164sv00000070sd00008991* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) pci:v00001131d00007164sv00000070sd00008993* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) pci:v00001131d00007164sv00000070sd000089A0* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) pci:v00001131d00007164sv00000070sd000089A1* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) pci:v00001131d00007164sv00000070sd0000F120* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2205) pci:v00001131d00007164sv00000070sd0000F123* ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2215) pci:v00001131d00007231* ID_MODEL_FROM_DATABASE=SAA7231 pci:v00001131d00007231sv00005ACEsd00008000* ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV H8) pci:v00001131d00007231sv00005ACEsd00008001* ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV H8) pci:v00001131d00007231sv00005ACEsd00008050* ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV H85) pci:v00001131d00007231sv00005ACEsd00008051* ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV H85) pci:v00001131d00007231sv00005ACEsd00008100* ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV A8) pci:v00001131d00007231sv00005ACEsd00008101* ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV A8) pci:v00001131d00007231sv00005ACEsd00008150* ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV A85) pci:v00001131d00007231sv00005ACEsd00008151* ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV A85) pci:v00001131d00007231sv00005ACEsd00008201* ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV T8) pci:v00001131d00009730* ID_MODEL_FROM_DATABASE=SAA9730 Integrated Multimedia and Peripheral Controller pci:v00001131d00009730sv00001131sd00000000* ID_MODEL_FROM_DATABASE=SAA9730 Integrated Multimedia and Peripheral Controller (Integrated Multimedia and Peripheral Controller) pci:v00001132* ID_VENDOR_FROM_DATABASE=Mitel Corp. pci:v00001133* ID_VENDOR_FROM_DATABASE=Dialogic Corporation pci:v00001133d00007701* ID_MODEL_FROM_DATABASE=Eiconcard C90 pci:v00001133d00007711* ID_MODEL_FROM_DATABASE=Eiconcard C91 pci:v00001133d00007901* ID_MODEL_FROM_DATABASE=EiconCard S90 pci:v00001133d00007902* ID_MODEL_FROM_DATABASE=EiconCard S90 pci:v00001133d00007911* ID_MODEL_FROM_DATABASE=EiconCard S91 pci:v00001133d00007912* ID_MODEL_FROM_DATABASE=EiconCard S91 pci:v00001133d00007921* ID_MODEL_FROM_DATABASE=Eiconcard S92 pci:v00001133d00007941* ID_MODEL_FROM_DATABASE=EiconCard S94 pci:v00001133d00007942* ID_MODEL_FROM_DATABASE=EiconCard S94 pci:v00001133d00007943* ID_MODEL_FROM_DATABASE=EiconCard S94 pci:v00001133d00007944* ID_MODEL_FROM_DATABASE=EiconCard S94 pci:v00001133d00007945* ID_MODEL_FROM_DATABASE=Eiconcard S94 pci:v00001133d00007948* ID_MODEL_FROM_DATABASE=Eiconcard S94 64bit/66MHz pci:v00001133d00009711* ID_MODEL_FROM_DATABASE=Eiconcard S91 V2 pci:v00001133d00009911* ID_MODEL_FROM_DATABASE=Eiconcard S91 V2 pci:v00001133d00009941* ID_MODEL_FROM_DATABASE=Eiconcard S94 V2 pci:v00001133d00009A41* ID_MODEL_FROM_DATABASE=Eiconcard S94 PCIe pci:v00001133d0000B921* ID_MODEL_FROM_DATABASE=EiconCard P92 pci:v00001133d0000B922* ID_MODEL_FROM_DATABASE=EiconCard P92 pci:v00001133d0000B923* ID_MODEL_FROM_DATABASE=EiconCard P92 pci:v00001133d0000E001* ID_MODEL_FROM_DATABASE=Diva Pro 2.0 S/T pci:v00001133d0000E002* ID_MODEL_FROM_DATABASE=Diva 2.0 S/T PCI pci:v00001133d0000E003* ID_MODEL_FROM_DATABASE=Diva Pro 2.0 U pci:v00001133d0000E004* ID_MODEL_FROM_DATABASE=Diva 2.0 U PCI pci:v00001133d0000E005* ID_MODEL_FROM_DATABASE=Diva 2.01 S/T PCI pci:v00001133d0000E006* ID_MODEL_FROM_DATABASE=Diva CT S/T PCI pci:v00001133d0000E007* ID_MODEL_FROM_DATABASE=Diva CT U PCI pci:v00001133d0000E008* ID_MODEL_FROM_DATABASE=Diva CT Lite S/T PCI pci:v00001133d0000E009* ID_MODEL_FROM_DATABASE=Diva CT Lite U PCI pci:v00001133d0000E00A* ID_MODEL_FROM_DATABASE=Diva ISDN+V.90 PCI pci:v00001133d0000E00B* ID_MODEL_FROM_DATABASE=Diva ISDN PCI 2.02 pci:v00001133d0000E00C* ID_MODEL_FROM_DATABASE=Diva 2.02 PCI U pci:v00001133d0000E00D* ID_MODEL_FROM_DATABASE=Diva Pro 3.0 PCI pci:v00001133d0000E00E* ID_MODEL_FROM_DATABASE=Diva ISDN+CT S/T PCI Rev 2 pci:v00001133d0000E010* ID_MODEL_FROM_DATABASE=Diva Server BRI-2M PCI pci:v00001133d0000E010sv0000110Asd00000021* ID_MODEL_FROM_DATABASE=Diva Server BRI-2M PCI (Fujitsu Siemens ISDN S0) pci:v00001133d0000E011* ID_MODEL_FROM_DATABASE=Diva Server BRI S/T Rev 2 pci:v00001133d0000E012* ID_MODEL_FROM_DATABASE=Diva Server 4BRI-8M PCI pci:v00001133d0000E013* ID_MODEL_FROM_DATABASE=4BRI pci:v00001133d0000E013sv00001133sd00001300* ID_MODEL_FROM_DATABASE=4BRI (Diva V-4BRI-8 PCI v2) pci:v00001133d0000E013sv00001133sd0000E013* ID_MODEL_FROM_DATABASE=4BRI (Diva 4BRI-8 PCI v2) pci:v00001133d0000E014* ID_MODEL_FROM_DATABASE=Diva Server PRI-30M PCI pci:v00001133d0000E015* ID_MODEL_FROM_DATABASE=Diva PRI PCI v2 pci:v00001133d0000E016* ID_MODEL_FROM_DATABASE=Diva Server Voice 4BRI PCI pci:v00001133d0000E017* ID_MODEL_FROM_DATABASE=Diva Server Voice 4BRI Rev 2 pci:v00001133d0000E017sv00001133sd0000E017* ID_MODEL_FROM_DATABASE=Diva Server Voice 4BRI Rev 2 (Diva Server Voice 4BRI-8M 2.0 PCI) pci:v00001133d0000E018* ID_MODEL_FROM_DATABASE=BRI pci:v00001133d0000E018sv00001133sd00001800* ID_MODEL_FROM_DATABASE=BRI (Diva V-BRI-2 PCI v2) pci:v00001133d0000E018sv00001133sd0000E018* ID_MODEL_FROM_DATABASE=BRI (Diva BRI-2 PCI v2) pci:v00001133d0000E019* ID_MODEL_FROM_DATABASE=Diva Server Voice PRI Rev 2 pci:v00001133d0000E019sv00001133sd0000E019* ID_MODEL_FROM_DATABASE=Diva Server Voice PRI Rev 2 (Diva Server Voice PRI 2.0 PCI) pci:v00001133d0000E01A* ID_MODEL_FROM_DATABASE=Diva BRI-2FX PCI v2 pci:v00001133d0000E01B* ID_MODEL_FROM_DATABASE=Diva Server Voice BRI-2M 2.0 PCI pci:v00001133d0000E01Bsv00001133sd0000E01B* ID_MODEL_FROM_DATABASE=Diva Server Voice BRI-2M 2.0 PCI pci:v00001133d0000E01C* ID_MODEL_FROM_DATABASE=PRI pci:v00001133d0000E01Csv00001133sd00001C01* ID_MODEL_FROM_DATABASE=PRI (Diva PRI/E1/T1-8 PCI v3) pci:v00001133d0000E01Csv00001133sd00001C02* ID_MODEL_FROM_DATABASE=PRI (Diva PRI/T1-24 PCI(e) v3) pci:v00001133d0000E01Csv00001133sd00001C03* ID_MODEL_FROM_DATABASE=PRI (Diva PRI/E1-30 PCI(e) v3) pci:v00001133d0000E01Csv00001133sd00001C04* ID_MODEL_FROM_DATABASE=PRI (Diva PRI/E1/T1-CTI PCI(e) v3) pci:v00001133d0000E01Csv00001133sd00001C05* ID_MODEL_FROM_DATABASE=PRI (Diva V-PRI/T1-24 PCI(e) v3) pci:v00001133d0000E01Csv00001133sd00001C06* ID_MODEL_FROM_DATABASE=PRI (Diva V-PRI/E1-30 PCI(e) v3) pci:v00001133d0000E01Csv00001133sd00001C07* ID_MODEL_FROM_DATABASE=PRI (Diva Server PRI/E1/T1-8 Cornet NQ) pci:v00001133d0000E01Csv00001133sd00001C08* ID_MODEL_FROM_DATABASE=PRI (Diva Server PRI/T1-24 Cornet NQ) pci:v00001133d0000E01Csv00001133sd00001C09* ID_MODEL_FROM_DATABASE=PRI (Diva Server PRI/E1-30 Cornet NQ) pci:v00001133d0000E01Csv00001133sd00001C0A* ID_MODEL_FROM_DATABASE=PRI (Diva Server PRI/E1/T1 Cornet NQ) pci:v00001133d0000E01Csv00001133sd00001C0B* ID_MODEL_FROM_DATABASE=PRI (Diva Server V-PRI/T1-24 Cornet NQ) pci:v00001133d0000E01Csv00001133sd00001C0C* ID_MODEL_FROM_DATABASE=PRI (Diva Server V-PRI/E1-30 Cornet NQ) pci:v00001133d0000E01E* ID_MODEL_FROM_DATABASE=2PRI pci:v00001133d0000E01Esv00001133sd00001E01* ID_MODEL_FROM_DATABASE=2PRI (Diva 2PRI/E1/T1-60 PCI v1) pci:v00001133d0000E01Esv00001133sd0000E01E* ID_MODEL_FROM_DATABASE=2PRI (Diva V-2PRI/E1/T1-60 PCI v1) pci:v00001133d0000E020* ID_MODEL_FROM_DATABASE=4PRI pci:v00001133d0000E020sv00001133sd00002001* ID_MODEL_FROM_DATABASE=4PRI (Diva 4PRI/E1/T1-120 PCI v1) pci:v00001133d0000E020sv00001133sd0000E020* ID_MODEL_FROM_DATABASE=4PRI (Diva V-4PRI/E1/T1-120 PCI v1) pci:v00001133d0000E022* ID_MODEL_FROM_DATABASE=Analog-2 pci:v00001133d0000E022sv00001133sd00002200* ID_MODEL_FROM_DATABASE=Analog-2 (Diva V-Analog-2 PCI v1) pci:v00001133d0000E022sv00001133sd0000E022* ID_MODEL_FROM_DATABASE=Analog-2 (Diva Analog-2 PCI v1) pci:v00001133d0000E024* ID_MODEL_FROM_DATABASE=Analog-4 pci:v00001133d0000E024sv00001133sd00002400* ID_MODEL_FROM_DATABASE=Analog-4 (Diva V-Analog-4 PCI v1) pci:v00001133d0000E024sv00001133sd0000E024* ID_MODEL_FROM_DATABASE=Analog-4 (Diva Analog-4 PCI v1) pci:v00001133d0000E028* ID_MODEL_FROM_DATABASE=Analog-8 pci:v00001133d0000E028sv00001133sd00002800* ID_MODEL_FROM_DATABASE=Analog-8 (Diva V-Analog-8 PCI v1) pci:v00001133d0000E028sv00001133sd0000E028* ID_MODEL_FROM_DATABASE=Analog-8 (Diva Analog-8 PCI v1) pci:v00001133d0000E02A* ID_MODEL_FROM_DATABASE=Diva IPM-300 PCI v1 pci:v00001133d0000E02C* ID_MODEL_FROM_DATABASE=Diva IPM-600 PCI v1 pci:v00001133d0000E02E* ID_MODEL_FROM_DATABASE=4BRI pci:v00001133d0000E02Esv00001133sd00002E01* ID_MODEL_FROM_DATABASE=4BRI (Diva V-4BRI-8 PCIe v2) pci:v00001133d0000E02Esv00001133sd0000E02E* ID_MODEL_FROM_DATABASE=4BRI (Diva 4BRI-8 PCIe v2) pci:v00001133d0000E032* ID_MODEL_FROM_DATABASE=BRI pci:v00001133d0000E032sv00001133sd00003201* ID_MODEL_FROM_DATABASE=BRI (Diva V-BRI-2 PCIe v2) pci:v00001133d0000E032sv00001133sd0000E032* ID_MODEL_FROM_DATABASE=BRI (Diva BRI-2 PCIe v2) pci:v00001133d0000E034* ID_MODEL_FROM_DATABASE=Diva BRI-CTI PCI v2 pci:v00001134* ID_VENDOR_FROM_DATABASE=Mercury Computer Systems pci:v00001134d00000001* ID_MODEL_FROM_DATABASE=Raceway Bridge pci:v00001134d00000002* ID_MODEL_FROM_DATABASE=Dual PCI to RapidIO Bridge pci:v00001134d0000000B* ID_MODEL_FROM_DATABASE=POET Serial RapidIO Bridge pci:v00001134d0000000D* ID_MODEL_FROM_DATABASE=POET PSDMS Device pci:v00001135* ID_VENDOR_FROM_DATABASE=Fuji Xerox Co Ltd pci:v00001135d00000001* ID_MODEL_FROM_DATABASE=Printer controller pci:v00001136* ID_VENDOR_FROM_DATABASE=Momentum Data Systems pci:v00001136d00000002* ID_MODEL_FROM_DATABASE=PCI-JTAG pci:v00001137* ID_VENDOR_FROM_DATABASE=Cisco Systems Inc pci:v00001137d00000023* ID_MODEL_FROM_DATABASE=VIC 81 PCIe Upstream Port pci:v00001137d00000040* ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port pci:v00001137d00000040sv00001137sd0000004F* ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1280 Dual 40Gb Mezzanine) pci:v00001137d00000040sv00001137sd00000084* ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1240 Dual 40Gb MLOM) pci:v00001137d00000040sv00001137sd00000085* ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1225 Dual 10Gb SFP+ PCIe) pci:v00001137d00000040sv00001137sd000000CD* ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1285 Dual 40Gb QSFP+ PCIe) pci:v00001137d00000040sv00001137sd000000CE* ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1225T Dual 10GBaseT PCIe) pci:v00001137d00000040sv00001137sd0000012A* ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC M4308 Dual 40Gb) pci:v00001137d00000040sv00001137sd0000012C* ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1340 Dual 40Gb MLOM) pci:v00001137d00000040sv00001137sd0000012E* ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1227 Dual 10Gb SFP+ PCIe) pci:v00001137d00000040sv00001137sd00000137* ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1380 Dual 40Gb Mezzanine) pci:v00001137d00000040sv00001137sd0000014D* ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1385 Dual 40Gb PCIe) pci:v00001137d00000041* ID_MODEL_FROM_DATABASE=VIC PCIe Downstream Port pci:v00001137d00000042* ID_MODEL_FROM_DATABASE=VIC Management Controller pci:v00001137d00000042sv00001137sd00000047* ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC P81E PCIe Management Controller) pci:v00001137d00000042sv00001137sd00000085* ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC 1225 PCIe Management Controller) pci:v00001137d00000042sv00001137sd000000CD* ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC 1285 PCIe Management Controller) pci:v00001137d00000042sv00001137sd000000CE* ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC 1225T PCIe Management Controller) pci:v00001137d00000042sv00001137sd0000012E* ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC 1227 PCIe Management Controller) pci:v00001137d00000042sv00001137sd0000014D* ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC 1385 PCIe Management Controller) pci:v00001137d00000043* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC pci:v00001137d00000043sv00001137sd00000047* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC P81E PCIe Ethernet NIC) pci:v00001137d00000043sv00001137sd00000048* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC M81KR Mezzanine Ethernet NIC) pci:v00001137d00000043sv00001137sd0000004F* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1280 Mezzanine Ethernet NIC) pci:v00001137d00000043sv00001137sd00000084* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1240 MLOM Ethernet NIC) pci:v00001137d00000043sv00001137sd00000085* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1225 PCIe Ethernet NIC) pci:v00001137d00000043sv00001137sd000000CD* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1285 PCIe Ethernet NIC) pci:v00001137d00000043sv00001137sd000000CE* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1225T PCIe Ethernet NIC) pci:v00001137d00000043sv00001137sd0000012A* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC M4308 Ethernet NIC) pci:v00001137d00000043sv00001137sd0000012C* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1340 MLOM Ethernet NIC) pci:v00001137d00000043sv00001137sd0000012E* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1227 PCIe Ethernet NIC) pci:v00001137d00000043sv00001137sd00000137* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1380 Mezzanine Ethernet NIC) pci:v00001137d00000043sv00001137sd0000014D* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1385 PCIe Ethernet NIC) pci:v00001137d00000044* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic pci:v00001137d00000044sv00001137sd00000047* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC P81E PCIe Ethernet NIC Dynamic) pci:v00001137d00000044sv00001137sd00000048* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC M81KR Mezzanine Ethernet NIC Dynamic) pci:v00001137d00000044sv00001137sd0000004F* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1280 Mezzanine Ethernet NIC Dynamic) pci:v00001137d00000044sv00001137sd00000084* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1240 MLOM Ethernet NIC Dynamic) pci:v00001137d00000044sv00001137sd00000085* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1225 PCIe Ethernet NIC Dynamic) pci:v00001137d00000044sv00001137sd000000CD* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1285 PCIe Ethernet NIC Dynamic) pci:v00001137d00000044sv00001137sd000000CE* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1225T PCIe Ethernet NIC Dynamic) pci:v00001137d00000044sv00001137sd0000012A* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC M4308 Ethernet NIC Dynamic) pci:v00001137d00000044sv00001137sd0000012C* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1340 MLOM Ethernet NIC Dynamic) pci:v00001137d00000044sv00001137sd0000012E* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1227 PCIe Ethernet NIC Dynamic) pci:v00001137d00000044sv00001137sd00000137* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1380 Mezzanine Ethernet NIC Dynamic) pci:v00001137d00000044sv00001137sd0000014D* ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1385 PCIe Ethernet NIC Dynamic) pci:v00001137d00000045* ID_MODEL_FROM_DATABASE=VIC FCoE HBA pci:v00001137d00000045sv00001137sd00000047* ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC P81E PCIe FCoE HBA) pci:v00001137d00000045sv00001137sd00000048* ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC M81KR Mezzanine FCoE HBA) pci:v00001137d00000045sv00001137sd0000004F* ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1280 Mezzanine FCoE HBA) pci:v00001137d00000045sv00001137sd00000084* ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1240 MLOM FCoE HBA) pci:v00001137d00000045sv00001137sd00000085* ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1225 PCIe FCoE HBA) pci:v00001137d00000045sv00001137sd000000CD* ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1285 PCIe FCoE HBA) pci:v00001137d00000045sv00001137sd000000CE* ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1225T PCIe FCoE HBA) pci:v00001137d00000045sv00001137sd0000012A* ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC M4308 FCoE HBA) pci:v00001137d00000045sv00001137sd0000012C* ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1340 MLOM FCoE HBA) pci:v00001137d00000045sv00001137sd0000012E* ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1227 PCIe FCoE HBA) pci:v00001137d00000045sv00001137sd00000137* ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1380 Mezzanine FCoE HBA) pci:v00001137d00000045sv00001137sd0000014D* ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1385 PCIe FCoE HBA) pci:v00001137d00000046* ID_MODEL_FROM_DATABASE=VIC SCSI Controller pci:v00001137d00000046sv00001137sd0000012A* ID_MODEL_FROM_DATABASE=VIC SCSI Controller (VIC M4308 SCSI Controller) pci:v00001137d0000004E* ID_MODEL_FROM_DATABASE=VIC 82 PCIe Upstream Port pci:v00001137d00000071* ID_MODEL_FROM_DATABASE=VIC SR-IOV VF pci:v00001137d0000007A* ID_MODEL_FROM_DATABASE=VIC 1300 PCIe Upstream Port pci:v00001137d0000007Asv00001137sd0000012A* ID_MODEL_FROM_DATABASE=VIC 1300 PCIe Upstream Port (VIC M4308 Dual 40Gb) pci:v00001137d0000007Asv00001137sd0000012C* ID_MODEL_FROM_DATABASE=VIC 1300 PCIe Upstream Port (VIC 1340 Dual 40Gb MLOM) pci:v00001137d0000007Asv00001137sd00000137* ID_MODEL_FROM_DATABASE=VIC 1300 PCIe Upstream Port (VIC 1380 Dual 40Gb Mezzanine) pci:v00001137d0000007Asv00001137sd0000014D* ID_MODEL_FROM_DATABASE=VIC 1300 PCIe Upstream Port (VIC 1385 Dual 40Gb PCIe) pci:v00001137d000000CF* ID_MODEL_FROM_DATABASE=VIC Userspace NIC pci:v00001137d000000CFsv00001137sd0000004F* ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1280 Mezzanine Userspace NIC) pci:v00001137d000000CFsv00001137sd00000084* ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1240 MLOM Userspace NIC) pci:v00001137d000000CFsv00001137sd00000085* ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1225 PCIe Userspace NIC) pci:v00001137d000000CFsv00001137sd000000CD* ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1285 PCIe Userspace NIC) pci:v00001137d000000CFsv00001137sd000000CE* ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1225T PCIe Userspace NIC) pci:v00001137d000000CFsv00001137sd0000012A* ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC M4308 Userspace NIC) pci:v00001137d000000CFsv00001137sd0000012C* ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1340 MLOM Userspace NIC) pci:v00001137d000000CFsv00001137sd0000012E* ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1227 PCIe Userspace NIC) pci:v00001137d000000CFsv00001137sd00000137* ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1380 Mezzanine Userspace NIC) pci:v00001138* ID_VENDOR_FROM_DATABASE=Ziatech Corporation pci:v00001138d00008905* ID_MODEL_FROM_DATABASE=8905 [STD 32 Bridge] pci:v00001139* ID_VENDOR_FROM_DATABASE=Dynamic Pictures, Inc pci:v00001139d00000001* ID_MODEL_FROM_DATABASE=VGA Compatible 3D Graphics pci:v0000113A* ID_VENDOR_FROM_DATABASE=FWB Inc pci:v0000113B* ID_VENDOR_FROM_DATABASE=Network Computing Devices pci:v0000113C* ID_VENDOR_FROM_DATABASE=Cyclone Microsystems, Inc. pci:v0000113Cd00000000* ID_MODEL_FROM_DATABASE=PCI-9060 i960 Bridge pci:v0000113Cd00000001* ID_MODEL_FROM_DATABASE=PCI-SDK [PCI i960 Evaluation Platform] pci:v0000113Cd00000911* ID_MODEL_FROM_DATABASE=PCI-911 [i960Jx-based Intelligent I/O Controller] pci:v0000113Cd00000912* ID_MODEL_FROM_DATABASE=PCI-912 [i960CF-based Intelligent I/O Controller] pci:v0000113Cd00000913* ID_MODEL_FROM_DATABASE=PCI-913 pci:v0000113Cd00000914* ID_MODEL_FROM_DATABASE=PCI-914 [I/O Controller w/ secondary PCI bus] pci:v0000113D* ID_VENDOR_FROM_DATABASE=Leading Edge Products Inc pci:v0000113E* ID_VENDOR_FROM_DATABASE=Sanyo Electric Co - Computer Engineering Dept pci:v0000113F* ID_VENDOR_FROM_DATABASE=Equinox Systems, Inc. pci:v0000113Fd00000808* ID_MODEL_FROM_DATABASE=SST-64P Adapter pci:v0000113Fd00001010* ID_MODEL_FROM_DATABASE=SST-128P Adapter pci:v0000113Fd000080C0* ID_MODEL_FROM_DATABASE=SST-16P DB Adapter pci:v0000113Fd000080C4* ID_MODEL_FROM_DATABASE=SST-16P RJ Adapter pci:v0000113Fd000080C8* ID_MODEL_FROM_DATABASE=SST-16P Adapter pci:v0000113Fd00008888* ID_MODEL_FROM_DATABASE=SST-4P Adapter pci:v0000113Fd00009090* ID_MODEL_FROM_DATABASE=SST-8P Adapter pci:v00001140* ID_VENDOR_FROM_DATABASE=Intervoice Inc pci:v00001141* ID_VENDOR_FROM_DATABASE=Crest Microsystem Inc pci:v00001142* ID_VENDOR_FROM_DATABASE=Alliance Semiconductor Corporation pci:v00001142d00003210* ID_MODEL_FROM_DATABASE=AP6410 pci:v00001142d00006422* ID_MODEL_FROM_DATABASE=ProVideo 6422 pci:v00001142d00006424* ID_MODEL_FROM_DATABASE=ProVideo 6424 pci:v00001142d00006425* ID_MODEL_FROM_DATABASE=ProMotion AT25 pci:v00001142d0000643D* ID_MODEL_FROM_DATABASE=ProMotion AT3D pci:v00001143* ID_VENDOR_FROM_DATABASE=NetPower, Inc pci:v00001144* ID_VENDOR_FROM_DATABASE=Cincinnati Milacron pci:v00001144d00000001* ID_MODEL_FROM_DATABASE=Noservo controller pci:v00001145* ID_VENDOR_FROM_DATABASE=Workbit Corporation pci:v00001145d00008007* ID_MODEL_FROM_DATABASE=NinjaSCSI-32 Workbit pci:v00001145d0000F007* ID_MODEL_FROM_DATABASE=NinjaSCSI-32 KME pci:v00001145d0000F010* ID_MODEL_FROM_DATABASE=NinjaSCSI-32 Workbit pci:v00001145d0000F012* ID_MODEL_FROM_DATABASE=NinjaSCSI-32 Logitec pci:v00001145d0000F013* ID_MODEL_FROM_DATABASE=NinjaSCSI-32 Logitec pci:v00001145d0000F015* ID_MODEL_FROM_DATABASE=NinjaSCSI-32 Melco pci:v00001145d0000F020* ID_MODEL_FROM_DATABASE=NinjaSCSI-32 Sony PCGA-DVD51 pci:v00001145d0000F021* ID_MODEL_FROM_DATABASE=NinjaPATA-32 Delkin Cardbus UDMA pci:v00001145d0000F024* ID_MODEL_FROM_DATABASE=NinjaPATA-32 Delkin Cardbus UDMA pci:v00001145d0000F103* ID_MODEL_FROM_DATABASE=NinjaPATA-32 Delkin Cardbus UDMA pci:v00001146* ID_VENDOR_FROM_DATABASE=Force Computers pci:v00001147* ID_VENDOR_FROM_DATABASE=Interface Corp pci:v00001148* ID_VENDOR_FROM_DATABASE=SysKonnect pci:v00001148d00004000* ID_MODEL_FROM_DATABASE=FDDI Adapter pci:v00001148d00004000sv00000E11sd0000B03B* ID_MODEL_FROM_DATABASE=FDDI Adapter (Netelligent 100 FDDI DAS Fibre SC) pci:v00001148d00004000sv00000E11sd0000B03C* ID_MODEL_FROM_DATABASE=FDDI Adapter (Netelligent 100 FDDI SAS Fibre SC) pci:v00001148d00004000sv00000E11sd0000B03D* ID_MODEL_FROM_DATABASE=FDDI Adapter (Netelligent 100 FDDI DAS UTP) pci:v00001148d00004000sv00000E11sd0000B03E* ID_MODEL_FROM_DATABASE=FDDI Adapter (Netelligent 100 FDDI SAS UTP) pci:v00001148d00004000sv00000E11sd0000B03F* ID_MODEL_FROM_DATABASE=FDDI Adapter (Netelligent 100 FDDI SAS Fibre MIC) pci:v00001148d00004000sv00001148sd00005521* ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5521 (SK-NET FDDI-UP)) pci:v00001148d00004000sv00001148sd00005522* ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5522 (SK-NET FDDI-UP DAS)) pci:v00001148d00004000sv00001148sd00005541* ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5541 (SK-NET FDDI-FP)) pci:v00001148d00004000sv00001148sd00005543* ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5543 (SK-NET FDDI-LP)) pci:v00001148d00004000sv00001148sd00005544* ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5544 (SK-NET FDDI-LP DAS)) pci:v00001148d00004000sv00001148sd00005821* ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5821 (SK-NET FDDI-UP64)) pci:v00001148d00004000sv00001148sd00005822* ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5822 (SK-NET FDDI-UP64 DAS)) pci:v00001148d00004000sv00001148sd00005841* ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5841 (SK-NET FDDI-FP64)) pci:v00001148d00004000sv00001148sd00005843* ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5843 (SK-NET FDDI-LP64)) pci:v00001148d00004000sv00001148sd00005844* ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5844 (SK-NET FDDI-LP64 DAS)) pci:v00001148d00004200* ID_MODEL_FROM_DATABASE=Token Ring adapter pci:v00001148d00004300* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) pci:v00001148d00004300sv00001148sd00009821* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T)) pci:v00001148d00004300sv00001148sd00009822* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link)) pci:v00001148d00004300sv00001148sd00009841* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX)) pci:v00001148d00004300sv00001148sd00009842* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link)) pci:v00001148d00004300sv00001148sd00009843* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX)) pci:v00001148d00004300sv00001148sd00009844* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link)) pci:v00001148d00004300sv00001148sd00009861* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition)) pci:v00001148d00004300sv00001148sd00009862* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link)) pci:v00001148d00004300sv00001148sd00009871* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX)) pci:v00001148d00004300sv00001148sd00009872* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) pci:v00001148d00004300sv00001259sd00002970* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2970SX Gigabit Ethernet Adapter) pci:v00001148d00004300sv00001259sd00002971* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2970LX Gigabit Ethernet Adapter) pci:v00001148d00004300sv00001259sd00002972* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2970TX Gigabit Ethernet Adapter) pci:v00001148d00004300sv00001259sd00002973* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2971SX Gigabit Ethernet Adapter) pci:v00001148d00004300sv00001259sd00002974* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2971T Gigabit Ethernet Adapter) pci:v00001148d00004300sv00001259sd00002975* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2970SX/2SC Gigabit Ethernet Adapter) pci:v00001148d00004300sv00001259sd00002976* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2970LX/2SC Gigabit Ethernet Adapter) pci:v00001148d00004300sv00001259sd00002977* ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2970TX/2TX Gigabit Ethernet Adapter) pci:v00001148d00004320* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC pci:v00001148d00004320sv00001148sd00000121* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (Marvell RDK-8001 Adapter) pci:v00001148d00004320sv00001148sd00000221* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (Marvell RDK-8002 Adapter) pci:v00001148d00004320sv00001148sd00000321* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (Marvell RDK-8003 Adapter) pci:v00001148d00004320sv00001148sd00000421* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (Marvell RDK-8004 Adapter) pci:v00001148d00004320sv00001148sd00000621* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (Marvell RDK-8006 Adapter) pci:v00001148d00004320sv00001148sd00000721* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (Marvell RDK-8007 Adapter) pci:v00001148d00004320sv00001148sd00000821* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (Marvell RDK-8008 Adapter) pci:v00001148d00004320sv00001148sd00000921* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (Marvell RDK-8009 Adapter) pci:v00001148d00004320sv00001148sd00001121* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (Marvell RDK-8011 Adapter) pci:v00001148d00004320sv00001148sd00001221* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (Marvell RDK-8012 Adapter) pci:v00001148d00004320sv00001148sd00003221* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (SK-9521 V2.0 10/100/1000Base-T Adapter) pci:v00001148d00004320sv00001148sd00005021* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter) pci:v00001148d00004320sv00001148sd00005041* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter) pci:v00001148d00004320sv00001148sd00005043* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter) pci:v00001148d00004320sv00001148sd00005051* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter) pci:v00001148d00004320sv00001148sd00005061* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter) pci:v00001148d00004320sv00001148sd00005071* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter) pci:v00001148d00004320sv00001148sd00009521* ID_MODEL_FROM_DATABASE=SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter, PCI64, Fiber ZX/SC (SK-9521 10/100/1000Base-T Adapter) pci:v00001148d00004400* ID_MODEL_FROM_DATABASE=SK-9Dxx Gigabit Ethernet Adapter pci:v00001148d00004500* ID_MODEL_FROM_DATABASE=SK-9Mxx Gigabit Ethernet Adapter pci:v00001148d00009000* ID_MODEL_FROM_DATABASE=SK-9S21 10/100/1000Base-T Server Adapter, PCI-X, Copper RJ-45 pci:v00001148d00009843* ID_MODEL_FROM_DATABASE=[Fujitsu] Gigabit Ethernet pci:v00001148d00009E00* ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 pci:v00001148d00009E00sv00001148sd00002100* ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E21 Server Adapter) pci:v00001148d00009E00sv00001148sd000021D0* ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E21D 10/100/1000Base-T Adapter) pci:v00001148d00009E00sv00001148sd00002200* ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E22 Server Adapter) pci:v00001148d00009E00sv00001148sd00008100* ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E81 Server Adapter) pci:v00001148d00009E00sv00001148sd00008200* ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E82 Server Adapter) pci:v00001148d00009E00sv00001148sd00009100* ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E91 Server Adapter) pci:v00001148d00009E00sv00001148sd00009200* ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E92 Server Adapter) pci:v00001148d00009E01* ID_MODEL_FROM_DATABASE=SK-9E21M 10/100/1000Base-T Adapter pci:v00001149* ID_VENDOR_FROM_DATABASE=Win System Corporation pci:v0000114A* ID_VENDOR_FROM_DATABASE=VMIC pci:v0000114Ad00005565* ID_MODEL_FROM_DATABASE=GE-IP PCI5565,PMC5565 Reflective Memory Node pci:v0000114Ad00005579* ID_MODEL_FROM_DATABASE=VMIPCI-5579 (Reflective Memory Card) pci:v0000114Ad00005587* ID_MODEL_FROM_DATABASE=VMIPCI-5587 (Reflective Memory Card) pci:v0000114Ad00006504* ID_MODEL_FROM_DATABASE=VMIC PCI 7755 FPGA pci:v0000114Ad00007587* ID_MODEL_FROM_DATABASE=VMIVME-7587 pci:v0000114B* ID_VENDOR_FROM_DATABASE=Canopus Co., Ltd pci:v0000114C* ID_VENDOR_FROM_DATABASE=Annabooks pci:v0000114D* ID_VENDOR_FROM_DATABASE=IC Corporation pci:v0000114E* ID_VENDOR_FROM_DATABASE=Nikon Systems Inc pci:v0000114F* ID_VENDOR_FROM_DATABASE=Digi International pci:v0000114Fd00000002* ID_MODEL_FROM_DATABASE=AccelePort EPC pci:v0000114Fd00000003* ID_MODEL_FROM_DATABASE=RightSwitch SE-6 pci:v0000114Fd00000004* ID_MODEL_FROM_DATABASE=AccelePort Xem pci:v0000114Fd00000005* ID_MODEL_FROM_DATABASE=AccelePort Xr pci:v0000114Fd00000006* ID_MODEL_FROM_DATABASE=AccelePort Xr,C/X pci:v0000114Fd00000009* ID_MODEL_FROM_DATABASE=AccelePort Xr/J pci:v0000114Fd0000000A* ID_MODEL_FROM_DATABASE=AccelePort EPC/J pci:v0000114Fd0000000C* ID_MODEL_FROM_DATABASE=DataFirePRIme T1 (1-port) pci:v0000114Fd0000000D* ID_MODEL_FROM_DATABASE=SyncPort 2-Port (x.25/FR) pci:v0000114Fd00000011* ID_MODEL_FROM_DATABASE=AccelePort 8r EIA-232 (IBM) pci:v0000114Fd00000012* ID_MODEL_FROM_DATABASE=AccelePort 8r EIA-422 pci:v0000114Fd00000013* ID_MODEL_FROM_DATABASE=AccelePort Xr pci:v0000114Fd00000014* ID_MODEL_FROM_DATABASE=AccelePort 8r EIA-422 pci:v0000114Fd00000015* ID_MODEL_FROM_DATABASE=AccelePort Xem pci:v0000114Fd00000016* ID_MODEL_FROM_DATABASE=AccelePort EPC/X pci:v0000114Fd00000017* ID_MODEL_FROM_DATABASE=AccelePort C/X pci:v0000114Fd0000001A* ID_MODEL_FROM_DATABASE=DataFirePRIme E1 (1-port) pci:v0000114Fd0000001B* ID_MODEL_FROM_DATABASE=AccelePort C/X (IBM) pci:v0000114Fd0000001C* ID_MODEL_FROM_DATABASE=AccelePort Xr (SAIP) pci:v0000114Fd0000001D* ID_MODEL_FROM_DATABASE=DataFire RAS T1/E1/PRI pci:v0000114Fd0000001Dsv0000114Fsd00000050* ID_MODEL_FROM_DATABASE=DataFire RAS T1/E1/PRI (DataFire RAS E1 Adapter) pci:v0000114Fd0000001Dsv0000114Fsd00000051* ID_MODEL_FROM_DATABASE=DataFire RAS T1/E1/PRI (DataFire RAS Dual E1 Adapter) pci:v0000114Fd0000001Dsv0000114Fsd00000052* ID_MODEL_FROM_DATABASE=DataFire RAS T1/E1/PRI (DataFire RAS T1 Adapter) pci:v0000114Fd0000001Dsv0000114Fsd00000053* ID_MODEL_FROM_DATABASE=DataFire RAS T1/E1/PRI (DataFire RAS Dual T1 Adapter) pci:v0000114Fd00000023* ID_MODEL_FROM_DATABASE=AccelePort RAS pci:v0000114Fd00000024* ID_MODEL_FROM_DATABASE=DataFire RAS B4 ST/U pci:v0000114Fd00000024sv0000114Fsd00000030* ID_MODEL_FROM_DATABASE=DataFire RAS B4 ST/U (DataFire RAS BRI U Adapter) pci:v0000114Fd00000024sv0000114Fsd00000031* ID_MODEL_FROM_DATABASE=DataFire RAS B4 ST/U (DataFire RAS BRI S/T Adapter) pci:v0000114Fd00000026* ID_MODEL_FROM_DATABASE=AccelePort 4r 920 pci:v0000114Fd00000027* ID_MODEL_FROM_DATABASE=AccelePort Xr 920 pci:v0000114Fd00000028* ID_MODEL_FROM_DATABASE=ClassicBoard 4 pci:v0000114Fd00000029* ID_MODEL_FROM_DATABASE=ClassicBoard 8 pci:v0000114Fd00000034* ID_MODEL_FROM_DATABASE=AccelePort 2r 920 pci:v0000114Fd00000035* ID_MODEL_FROM_DATABASE=DataFire DSP T1/E1/PRI cPCI pci:v0000114Fd00000040* ID_MODEL_FROM_DATABASE=AccelePort Xp pci:v0000114Fd00000040sv0000114Fsd00000042* ID_MODEL_FROM_DATABASE=AccelePort Xp (AccelePort 2p PCI) pci:v0000114Fd00000040sv0000114Fsd00000043* ID_MODEL_FROM_DATABASE=AccelePort Xp (AccelePort 4p PCI) pci:v0000114Fd00000040sv0000114Fsd00000044* ID_MODEL_FROM_DATABASE=AccelePort Xp (AccelePort 8p PCI) pci:v0000114Fd00000040sv0000114Fsd00000045* ID_MODEL_FROM_DATABASE=AccelePort Xp (AccelePort 16p PCI) pci:v0000114Fd00000040sv0000114Fsd0000004E* ID_MODEL_FROM_DATABASE=AccelePort Xp (AccelePort 32p PCI) pci:v0000114Fd00000042* ID_MODEL_FROM_DATABASE=AccelePort 2p pci:v0000114Fd00000043* ID_MODEL_FROM_DATABASE=AccelePort 4p pci:v0000114Fd00000044* ID_MODEL_FROM_DATABASE=AccelePort 8p pci:v0000114Fd00000045* ID_MODEL_FROM_DATABASE=AccelePort 16p pci:v0000114Fd0000004E* ID_MODEL_FROM_DATABASE=AccelePort 32p pci:v0000114Fd00000070* ID_MODEL_FROM_DATABASE=Datafire Micro V IOM2 (Europe) pci:v0000114Fd00000071* ID_MODEL_FROM_DATABASE=Datafire Micro V (Europe) pci:v0000114Fd00000072* ID_MODEL_FROM_DATABASE=Datafire Micro V IOM2 (North America) pci:v0000114Fd00000073* ID_MODEL_FROM_DATABASE=Datafire Micro V (North America) pci:v0000114Fd000000B0* ID_MODEL_FROM_DATABASE=Digi Neo 4 pci:v0000114Fd000000B1* ID_MODEL_FROM_DATABASE=Digi Neo 8 pci:v0000114Fd000000C8* ID_MODEL_FROM_DATABASE=Digi Neo 2 DB9 pci:v0000114Fd000000C9* ID_MODEL_FROM_DATABASE=Digi Neo 2 DB9 PRI pci:v0000114Fd000000CA* ID_MODEL_FROM_DATABASE=Digi Neo 2 RJ45 pci:v0000114Fd000000CB* ID_MODEL_FROM_DATABASE=Digi Neo 2 RJ45 PRI pci:v0000114Fd000000CC* ID_MODEL_FROM_DATABASE=Digi Neo 1 422 pci:v0000114Fd000000CD* ID_MODEL_FROM_DATABASE=Digi Neo 1 422 485 pci:v0000114Fd000000CE* ID_MODEL_FROM_DATABASE=Digi Neo 2 422 485 pci:v0000114Fd000000D0* ID_MODEL_FROM_DATABASE=ClassicBoard 4 422 pci:v0000114Fd000000D1* ID_MODEL_FROM_DATABASE=ClassicBoard 8 422 pci:v0000114Fd000000F1* ID_MODEL_FROM_DATABASE=Digi Neo PCI-E 4 port pci:v0000114Fd000000F4* ID_MODEL_FROM_DATABASE=Digi Neo 4 (IBM version) pci:v0000114Fd00006001* ID_MODEL_FROM_DATABASE=Avanstar pci:v00001150* ID_VENDOR_FROM_DATABASE=Thinking Machines Corp pci:v00001151* ID_VENDOR_FROM_DATABASE=JAE Electronics Inc. pci:v00001152* ID_VENDOR_FROM_DATABASE=Megatek pci:v00001153* ID_VENDOR_FROM_DATABASE=Land Win Electronic Corp pci:v00001154* ID_VENDOR_FROM_DATABASE=Melco Inc pci:v00001155* ID_VENDOR_FROM_DATABASE=Pine Technology Ltd pci:v00001156* ID_VENDOR_FROM_DATABASE=Periscope Engineering pci:v00001157* ID_VENDOR_FROM_DATABASE=Avsys Corporation pci:v00001158* ID_VENDOR_FROM_DATABASE=Voarx R & D Inc pci:v00001158d00003011* ID_MODEL_FROM_DATABASE=Tokenet/vg 1001/10m anylan pci:v00001158d00009050* ID_MODEL_FROM_DATABASE=Lanfleet/Truevalue pci:v00001158d00009051* ID_MODEL_FROM_DATABASE=Lanfleet/Truevalue pci:v00001159* ID_VENDOR_FROM_DATABASE=Mutech Corp pci:v00001159d00000001* ID_MODEL_FROM_DATABASE=MV-1000 pci:v00001159d00000002* ID_MODEL_FROM_DATABASE=MV-1500 pci:v0000115A* ID_VENDOR_FROM_DATABASE=Harlequin Ltd pci:v0000115B* ID_VENDOR_FROM_DATABASE=Parallax Graphics pci:v0000115C* ID_VENDOR_FROM_DATABASE=Photron Ltd. pci:v0000115D* ID_VENDOR_FROM_DATABASE=Xircom pci:v0000115Dd00000003* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd00000003sv00001014sd00000181* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) pci:v0000115Dd00000003sv00001014sd00001181* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) pci:v0000115Dd00000003sv00001014sd00008181* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) pci:v0000115Dd00000003sv00001014sd00009181* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) pci:v0000115Dd00000003sv0000115Dsd00000181* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd00000003sv0000115Dsd00000182* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (RealPort2 CardBus Ethernet 10/100 (R2BE-100)) pci:v0000115Dd00000003sv0000115Dsd00001181* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd00000003sv00001179sd00000181* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd00000003sv00008086sd00008181* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (EtherExpress PRO/100 Mobile CardBus 32 Adapter) pci:v0000115Dd00000003sv00008086sd00009181* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (EtherExpress PRO/100 Mobile CardBus 32 Adapter) pci:v0000115Dd00000005* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd00000005sv00001014sd00000182* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) pci:v0000115Dd00000005sv00001014sd00001182* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) pci:v0000115Dd00000005sv0000115Dsd00000182* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd00000005sv0000115Dsd00001182* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd00000007* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd00000007sv00001014sd00000182* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) pci:v0000115Dd00000007sv00001014sd00001182* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) pci:v0000115Dd00000007sv0000115Dsd00000182* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd00000007sv0000115Dsd00001182* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd0000000B* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd0000000Bsv00001014sd00000183* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) pci:v0000115Dd0000000Bsv0000115Dsd00000183* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd0000000C* ID_MODEL_FROM_DATABASE=Mini-PCI V.90 56k Modem pci:v0000115Dd0000000F* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd0000000Fsv00001014sd00000183* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) pci:v0000115Dd0000000Fsv0000115Dsd00000183* ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 pci:v0000115Dd000000D4* ID_MODEL_FROM_DATABASE=Mini-PCI K56Flex Modem pci:v0000115Dd00000101* ID_MODEL_FROM_DATABASE=Cardbus 56k modem pci:v0000115Dd00000101sv0000115Dsd00001081* ID_MODEL_FROM_DATABASE=Cardbus 56k modem (Cardbus 56k Modem) pci:v0000115Dd00000103* ID_MODEL_FROM_DATABASE=Cardbus Ethernet + 56k Modem pci:v0000115Dd00000103sv00001014sd00009181* ID_MODEL_FROM_DATABASE=Cardbus Ethernet + 56k Modem (Cardbus 56k Modem) pci:v0000115Dd00000103sv00001115sd00001181* ID_MODEL_FROM_DATABASE=Cardbus Ethernet + 56k Modem (Cardbus Ethernet 100 + 56k Modem) pci:v0000115Dd00000103sv0000115Dsd00001181* ID_MODEL_FROM_DATABASE=Cardbus Ethernet + 56k Modem (CBEM56G-100 Ethernet + 56k Modem) pci:v0000115Dd00000103sv00008086sd00009181* ID_MODEL_FROM_DATABASE=Cardbus Ethernet + 56k Modem (PRO/100 LAN + Modem56 CardBus) pci:v0000115E* ID_VENDOR_FROM_DATABASE=Peer Protocols Inc pci:v0000115F* ID_VENDOR_FROM_DATABASE=Maxtor Corporation pci:v00001160* ID_VENDOR_FROM_DATABASE=Megasoft Inc pci:v00001161* ID_VENDOR_FROM_DATABASE=PFU Limited pci:v00001162* ID_VENDOR_FROM_DATABASE=OA Laboratory Co Ltd pci:v00001163* ID_VENDOR_FROM_DATABASE=Rendition pci:v00001163d00000001* ID_MODEL_FROM_DATABASE=Verite 1000 pci:v00001163d00002000* ID_MODEL_FROM_DATABASE=Verite V2000/V2100/V2200 pci:v00001163d00002000sv00001092sd00002000* ID_MODEL_FROM_DATABASE=Verite V2000/V2100/V2200 (Stealth II S220) pci:v00001164* ID_VENDOR_FROM_DATABASE=Advanced Peripherals Technologies pci:v00001165* ID_VENDOR_FROM_DATABASE=Imagraph Corporation pci:v00001165d00000001* ID_MODEL_FROM_DATABASE=Motion TPEG Recorder/Player with audio pci:v00001166* ID_VENDOR_FROM_DATABASE=Broadcom pci:v00001166d00000000* ID_MODEL_FROM_DATABASE=CMIC-LE pci:v00001166d00000005* ID_MODEL_FROM_DATABASE=CNB20-LE Host Bridge pci:v00001166d00000006* ID_MODEL_FROM_DATABASE=CNB20HE Host Bridge pci:v00001166d00000007* ID_MODEL_FROM_DATABASE=CNB20-LE Host Bridge pci:v00001166d00000008* ID_MODEL_FROM_DATABASE=CNB20HE Host Bridge pci:v00001166d00000009* ID_MODEL_FROM_DATABASE=CNB20LE Host Bridge pci:v00001166d00000010* ID_MODEL_FROM_DATABASE=CIOB30 pci:v00001166d00000011* ID_MODEL_FROM_DATABASE=CMIC-HE pci:v00001166d00000012* ID_MODEL_FROM_DATABASE=CMIC-WS Host Bridge (GC-LE chipset) pci:v00001166d00000013* ID_MODEL_FROM_DATABASE=CNB20-HE Host Bridge pci:v00001166d00000014* ID_MODEL_FROM_DATABASE=CMIC-LE Host Bridge (GC-LE chipset) pci:v00001166d00000015* ID_MODEL_FROM_DATABASE=CMIC-GC Host Bridge pci:v00001166d00000016* ID_MODEL_FROM_DATABASE=CMIC-GC Host Bridge pci:v00001166d00000017* ID_MODEL_FROM_DATABASE=GCNB-LE Host Bridge pci:v00001166d00000031* ID_MODEL_FROM_DATABASE=HT1100 HPX0 HT Host Bridge pci:v00001166d00000036* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] PCI/PCI-X Bridge pci:v00001166d00000101* ID_MODEL_FROM_DATABASE=CIOB-X2 PCI-X I/O Bridge pci:v00001166d00000103* ID_MODEL_FROM_DATABASE=EPB PCI-Express to PCI-X Bridge pci:v00001166d00000104* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] PCI/PCI-X Bridge pci:v00001166d00000110* ID_MODEL_FROM_DATABASE=CIOB-E I/O Bridge with Gigabit Ethernet pci:v00001166d00000130* ID_MODEL_FROM_DATABASE=BCM5780 [HT2000] PCI-X bridge pci:v00001166d00000132* ID_MODEL_FROM_DATABASE=BCM5780 [HT2000] PCI-Express Bridge pci:v00001166d00000132sv00001166sd00000132* ID_MODEL_FROM_DATABASE=BCM5780 [HT2000] PCI-Express Bridge (HT2000 PCI-Express bridge) pci:v00001166d00000140* ID_MODEL_FROM_DATABASE=HT2100 PCI-Express Bridge pci:v00001166d00000141* ID_MODEL_FROM_DATABASE=HT2100 PCI-Express Bridge pci:v00001166d00000142* ID_MODEL_FROM_DATABASE=HT2100 PCI-Express Bridge pci:v00001166d00000144* ID_MODEL_FROM_DATABASE=HT2100 PCI-Express Bridge pci:v00001166d00000200* ID_MODEL_FROM_DATABASE=OSB4 South Bridge pci:v00001166d00000201* ID_MODEL_FROM_DATABASE=CSB5 South Bridge pci:v00001166d00000201sv00004C53sd00001080* ID_MODEL_FROM_DATABASE=CSB5 South Bridge (CT8 mainboard) pci:v00001166d00000203* ID_MODEL_FROM_DATABASE=CSB6 South Bridge pci:v00001166d00000203sv00001734sd00001012* ID_MODEL_FROM_DATABASE=CSB6 South Bridge (PRIMERGY RX/TX series) pci:v00001166d00000205* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] Legacy South Bridge pci:v00001166d00000211* ID_MODEL_FROM_DATABASE=OSB4 IDE Controller pci:v00001166d00000212* ID_MODEL_FROM_DATABASE=CSB5 IDE Controller pci:v00001166d00000212sv00001028sd0000014A* ID_MODEL_FROM_DATABASE=CSB5 IDE Controller (PowerEdge 1750) pci:v00001166d00000212sv00001028sd0000810B* ID_MODEL_FROM_DATABASE=CSB5 IDE Controller (PowerEdge 1650/2550) pci:v00001166d00000212sv00004C53sd00001080* ID_MODEL_FROM_DATABASE=CSB5 IDE Controller (CT8 mainboard) pci:v00001166d00000213* ID_MODEL_FROM_DATABASE=CSB6 RAID/IDE Controller pci:v00001166d00000213sv00001028sd00004134* ID_MODEL_FROM_DATABASE=CSB6 RAID/IDE Controller (PowerEdge 600SC) pci:v00001166d00000213sv00001028sd0000C134* ID_MODEL_FROM_DATABASE=CSB6 RAID/IDE Controller (Poweredge SC600) pci:v00001166d00000213sv00001734sd00001012* ID_MODEL_FROM_DATABASE=CSB6 RAID/IDE Controller (PRIMERGY RX/TX series onboard IDE) pci:v00001166d00000214* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] IDE pci:v00001166d00000214sv00001028sd00000205* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] IDE (PowerEdge 2970 HT1000 IDE) pci:v00001166d00000217* ID_MODEL_FROM_DATABASE=CSB6 IDE Controller pci:v00001166d00000217sv00001028sd00004134* ID_MODEL_FROM_DATABASE=CSB6 IDE Controller (Poweredge SC600) pci:v00001166d0000021B* ID_MODEL_FROM_DATABASE=HT1100 HD Audio pci:v00001166d00000220* ID_MODEL_FROM_DATABASE=OSB4/CSB5 OHCI USB Controller pci:v00001166d00000220sv00004C53sd00001080* ID_MODEL_FROM_DATABASE=OSB4/CSB5 OHCI USB Controller (CT8 mainboard) pci:v00001166d00000221* ID_MODEL_FROM_DATABASE=CSB6 OHCI USB Controller pci:v00001166d00000221sv00001734sd00001012* ID_MODEL_FROM_DATABASE=CSB6 OHCI USB Controller (PRIMERGY RX/TX series onboard OHCI) pci:v00001166d00000223* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] USB pci:v00001166d00000223sv00001028sd00000205* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] USB (PowerEdge 2970 HT1000 USB Controller) pci:v00001166d00000223sv00001028sd0000020B* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] USB (PowerEdge T605 HT1000 USB Controller) pci:v00001166d00000225* ID_MODEL_FROM_DATABASE=CSB5 LPC bridge pci:v00001166d00000227* ID_MODEL_FROM_DATABASE=GCLE-2 Host Bridge pci:v00001166d00000227sv00001734sd00001012* ID_MODEL_FROM_DATABASE=GCLE-2 Host Bridge (PRIMERGY RX/TX series) pci:v00001166d00000230* ID_MODEL_FROM_DATABASE=CSB5 LPC bridge pci:v00001166d00000230sv00004C53sd00001080* ID_MODEL_FROM_DATABASE=CSB5 LPC bridge (CT8 mainboard) pci:v00001166d00000234* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] LPC pci:v00001166d00000234sv00001028sd00000205* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] LPC (PowerEdge 2970 HT1000 LPC) pci:v00001166d00000234sv00001028sd0000020B* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] LPC (PowerEdge T605 HT1000 LPC) pci:v00001166d00000235* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] XIOAPIC0-2 pci:v00001166d00000238* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] WDTimer pci:v00001166d00000240* ID_MODEL_FROM_DATABASE=K2 SATA pci:v00001166d00000241* ID_MODEL_FROM_DATABASE=RAIDCore RC4000 pci:v00001166d00000242* ID_MODEL_FROM_DATABASE=RAIDCore BC4000 pci:v00001166d0000024A* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] SATA (Native SATA Mode) pci:v00001166d0000024Asv00001028sd0000020B* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] SATA (Native SATA Mode) (PowerEdge T605 onboard SATA Controller) pci:v00001166d0000024B* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] SATA (PATA/IDE Mode) pci:v00001166d0000024Bsv00001028sd00000205* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] SATA (PATA/IDE Mode) (PowerEdge 2970 HT1000 SATA controller) pci:v00001166d00000406* ID_MODEL_FROM_DATABASE=HT1100 PCI-X Bridge pci:v00001166d00000408* ID_MODEL_FROM_DATABASE=HT1100 Legacy Device pci:v00001166d0000040A* ID_MODEL_FROM_DATABASE=HT1100 ISA-LPC Bridge pci:v00001166d0000040Asv00001028sd00000223* ID_MODEL_FROM_DATABASE=HT1100 ISA-LPC Bridge (PowerEdge R905 HT1100 ISA-LPC Bridge) pci:v00001166d00000410* ID_MODEL_FROM_DATABASE=HT1100 SATA Controller (Native SATA Mode) pci:v00001166d00000411* ID_MODEL_FROM_DATABASE=HT1100 SATA Controller (PATA / IDE Mode) pci:v00001166d00000412* ID_MODEL_FROM_DATABASE=HT1100 USB OHCI Controller pci:v00001166d00000414* ID_MODEL_FROM_DATABASE=HT1100 USB EHCI Controller pci:v00001166d00000416* ID_MODEL_FROM_DATABASE=HT1100 USB EHCI Controller (with Debug Port) pci:v00001166d00000420* ID_MODEL_FROM_DATABASE=HT1100 PCI-Express Bridge pci:v00001166d00000421* ID_MODEL_FROM_DATABASE=HT1100 SAS/SATA Controller pci:v00001166d00000422* ID_MODEL_FROM_DATABASE=HT1100 PCI-Express Bridge pci:v00001167* ID_VENDOR_FROM_DATABASE=Mutoh Industries Inc pci:v00001168* ID_VENDOR_FROM_DATABASE=Thine Electronics Inc pci:v00001169* ID_VENDOR_FROM_DATABASE=Centre for Development of Advanced Computing pci:v0000116A* ID_VENDOR_FROM_DATABASE=Luminex Software, Inc. pci:v0000116Ad00006100* ID_MODEL_FROM_DATABASE=Bus/Tag Channel pci:v0000116Ad00006800* ID_MODEL_FROM_DATABASE=Escon Channel pci:v0000116Ad00007100* ID_MODEL_FROM_DATABASE=Bus/Tag Channel pci:v0000116Ad00007800* ID_MODEL_FROM_DATABASE=Escon Channel pci:v0000116B* ID_VENDOR_FROM_DATABASE=Connectware Inc pci:v0000116C* ID_VENDOR_FROM_DATABASE=Intelligent Resources Integrated Systems pci:v0000116D* ID_VENDOR_FROM_DATABASE=Martin-Marietta pci:v0000116E* ID_VENDOR_FROM_DATABASE=Electronics for Imaging pci:v0000116F* ID_VENDOR_FROM_DATABASE=Workstation Technology pci:v00001170* ID_VENDOR_FROM_DATABASE=Inventec Corporation pci:v00001171* ID_VENDOR_FROM_DATABASE=Loughborough Sound Images Plc pci:v00001172* ID_VENDOR_FROM_DATABASE=Altera Corporation pci:v00001173* ID_VENDOR_FROM_DATABASE=Adobe Systems, Inc pci:v00001174* ID_VENDOR_FROM_DATABASE=Bridgeport Machines pci:v00001175* ID_VENDOR_FROM_DATABASE=Mitron Computer Inc. pci:v00001176* ID_VENDOR_FROM_DATABASE=SBE Incorporated pci:v00001177* ID_VENDOR_FROM_DATABASE=Silicon Engineering pci:v00001178* ID_VENDOR_FROM_DATABASE=Alfa, Inc. pci:v00001178d0000AFA1* ID_MODEL_FROM_DATABASE=Fast Ethernet Adapter pci:v00001179* ID_VENDOR_FROM_DATABASE=Toshiba America Info Systems pci:v00001179d00000102* ID_MODEL_FROM_DATABASE=Extended IDE Controller pci:v00001179d00000103* ID_MODEL_FROM_DATABASE=EX-IDE Type-B pci:v00001179d00000404* ID_MODEL_FROM_DATABASE=DVD Decoder card pci:v00001179d00000406* ID_MODEL_FROM_DATABASE=Tecra Video Capture device pci:v00001179d00000407* ID_MODEL_FROM_DATABASE=DVD Decoder card (Version 2) pci:v00001179d00000601* ID_MODEL_FROM_DATABASE=CPU to PCI bridge pci:v00001179d00000601sv00001179sd00000001* ID_MODEL_FROM_DATABASE=CPU to PCI bridge (Satellite Pro) pci:v00001179d00000602* ID_MODEL_FROM_DATABASE=PCI to ISA bridge pci:v00001179d00000603* ID_MODEL_FROM_DATABASE=ToPIC95 PCI to CardBus Bridge for Notebooks pci:v00001179d00000604* ID_MODEL_FROM_DATABASE=PCI-Docking Host bridge pci:v00001179d0000060A* ID_MODEL_FROM_DATABASE=ToPIC95 pci:v00001179d0000060Asv00001179sd00000001* ID_MODEL_FROM_DATABASE=ToPIC95 (Satellite Pro) pci:v00001179d0000060F* ID_MODEL_FROM_DATABASE=ToPIC97 pci:v00001179d0000060Fsv00001179sd00000001* ID_MODEL_FROM_DATABASE=ToPIC97 (Satellite 4010) pci:v00001179d00000617* ID_MODEL_FROM_DATABASE=ToPIC100 PCI to Cardbus Bridge with ZV Support pci:v00001179d00000618* ID_MODEL_FROM_DATABASE=CPU to PCI and PCI to ISA bridge pci:v00001179d00000701* ID_MODEL_FROM_DATABASE=FIR Port Type-O pci:v00001179d00000803* ID_MODEL_FROM_DATABASE=TC6371AF SD Host Controller pci:v00001179d00000804* ID_MODEL_FROM_DATABASE=TC6371AF SmartMedia Controller pci:v00001179d00000805* ID_MODEL_FROM_DATABASE=SD TypA Controller pci:v00001179d00000D01* ID_MODEL_FROM_DATABASE=FIR Port Type-DO pci:v00001179d00000D01sv00001179sd00000001* ID_MODEL_FROM_DATABASE=FIR Port Type-DO pci:v0000117A* ID_VENDOR_FROM_DATABASE=A-Trend Technology pci:v0000117B* ID_VENDOR_FROM_DATABASE=L G Electronics, Inc. pci:v0000117C* ID_VENDOR_FROM_DATABASE=ATTO Technology, Inc. pci:v0000117Cd0000002C* ID_MODEL_FROM_DATABASE=ExpressSAS R380 pci:v0000117Cd0000002D* ID_MODEL_FROM_DATABASE=ExpressSAS R348 pci:v0000117Cd00000030* ID_MODEL_FROM_DATABASE=Ultra320 SCSI Host Adapter pci:v0000117Cd00000030sv0000117Csd00008013* ID_MODEL_FROM_DATABASE=Ultra320 SCSI Host Adapter (ExpressPCI UL4D) pci:v0000117Cd00000030sv0000117Csd00008014* ID_MODEL_FROM_DATABASE=Ultra320 SCSI Host Adapter (ExpressPCI UL4S) pci:v0000117Cd00000030sv0000117Csd00008027* ID_MODEL_FROM_DATABASE=Ultra320 SCSI Host Adapter (ExpressPCI UL5D) pci:v0000117Cd00000030sv0000117Csd0000802F* ID_MODEL_FROM_DATABASE=Ultra320 SCSI Host Adapter (ExpressPCI UL5D Low Profile) pci:v0000117Cd00000033* ID_MODEL_FROM_DATABASE=SAS Adapter pci:v0000117Cd00000041* ID_MODEL_FROM_DATABASE=ExpressSAS R30F pci:v0000117Cd00008013* ID_MODEL_FROM_DATABASE=ExpressPCI UL4D pci:v0000117Cd00008014* ID_MODEL_FROM_DATABASE=ExpressPCI UL4S pci:v0000117Cd00008027* ID_MODEL_FROM_DATABASE=ExpressPCI UL5D pci:v0000117D* ID_VENDOR_FROM_DATABASE=Becton & Dickinson pci:v0000117E* ID_VENDOR_FROM_DATABASE=T/R Systems pci:v0000117F* ID_VENDOR_FROM_DATABASE=Integrated Circuit Systems pci:v00001180* ID_VENDOR_FROM_DATABASE=Ricoh Co Ltd pci:v00001180d00000465* ID_MODEL_FROM_DATABASE=RL5c465 pci:v00001180d00000466* ID_MODEL_FROM_DATABASE=RL5c466 pci:v00001180d00000475* ID_MODEL_FROM_DATABASE=RL5c475 pci:v00001180d00000475sv0000144Dsd0000C006* ID_MODEL_FROM_DATABASE=RL5c475 (vpr Matrix 170B4 CardBus bridge) pci:v00001180d00000476* ID_MODEL_FROM_DATABASE=RL5c476 II pci:v00001180d00000476sv00001014sd00000185* ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad A/T/X Series) pci:v00001180d00000476sv00001014sd0000056C* ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad Z60t) pci:v00001180d00000476sv00001028sd0000014F* ID_MODEL_FROM_DATABASE=RL5c476 II (Latitude X300 laptop) pci:v00001180d00000476sv00001028sd00000188* ID_MODEL_FROM_DATABASE=RL5c476 II (Inspiron 6000 laptop) pci:v00001180d00000476sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=RL5c476 II (Compaq 6710b) pci:v00001180d00000476sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=RL5c476 II (Compaq 6910p) pci:v00001180d00000476sv00001043sd00001237* ID_MODEL_FROM_DATABASE=RL5c476 II (A6J-Q008) pci:v00001180d00000476sv00001043sd00001967* ID_MODEL_FROM_DATABASE=RL5c476 II (V6800V) pci:v00001180d00000476sv00001043sd00001987* ID_MODEL_FROM_DATABASE=RL5c476 II (Asus A4K and Z81K notebooks, possibly others ( mid-2005 machines )) pci:v00001180d00000476sv0000104Dsd000080DF* ID_MODEL_FROM_DATABASE=RL5c476 II (Vaio PCG-FX403) pci:v00001180d00000476sv0000104Dsd000080E7* ID_MODEL_FROM_DATABASE=RL5c476 II (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) pci:v00001180d00000476sv0000104Dsd0000814E* ID_MODEL_FROM_DATABASE=RL5c476 II (VAIO GRZ390Z) pci:v00001180d00000476sv000010F7sd00008338* ID_MODEL_FROM_DATABASE=RL5c476 II (Panasonic CF-Y5 laptop) pci:v00001180d00000476sv0000144Dsd0000C005* ID_MODEL_FROM_DATABASE=RL5c476 II (X10 Laptop) pci:v00001180d00000476sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=RL5c476 II (P30/P35 notebook) pci:v00001180d00000476sv000014EFsd00000220* ID_MODEL_FROM_DATABASE=RL5c476 II (PCD-RP-220S) pci:v00001180d00000476sv000017AAsd0000201C* ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad X60/X60s) pci:v00001180d00000476sv000017AAsd000020C4* ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad T61) pci:v00001180d00000476sv000017AAsd000020C6* ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad R61) pci:v00001180d00000477* ID_MODEL_FROM_DATABASE=RL5c477 pci:v00001180d00000478* ID_MODEL_FROM_DATABASE=RL5c478 pci:v00001180d00000478sv00001014sd00000184* ID_MODEL_FROM_DATABASE=RL5c478 (ThinkPad A30p) pci:v00001180d00000511* ID_MODEL_FROM_DATABASE=R5C511 pci:v00001180d00000522* ID_MODEL_FROM_DATABASE=R5C522 IEEE 1394 Controller pci:v00001180d00000522sv00001014sd000001CF* ID_MODEL_FROM_DATABASE=R5C522 IEEE 1394 Controller (ThinkPad A30p) pci:v00001180d00000522sv00001043sd00001967* ID_MODEL_FROM_DATABASE=R5C522 IEEE 1394 Controller (V6800V) pci:v00001180d00000551* ID_MODEL_FROM_DATABASE=R5C551 IEEE 1394 Controller pci:v00001180d00000551sv0000144Dsd0000C006* ID_MODEL_FROM_DATABASE=R5C551 IEEE 1394 Controller (vpr Matrix 170B4) pci:v00001180d00000552* ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller pci:v00001180d00000552sv00001014sd00000511* ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (ThinkPad A/T/X Series) pci:v00001180d00000552sv00001028sd0000014F* ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (Latitude X300 laptop) pci:v00001180d00000552sv00001028sd00000188* ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (Inspiron 6000 laptop) pci:v00001180d00000552sv00001043sd00001237* ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (A6J-Q008) pci:v00001180d00000552sv00001043sd00001757* ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (M2400N laptop) pci:v00001180d00000552sv0000144Dsd0000C005* ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (X10 Laptop) pci:v00001180d00000552sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (P30/P35 notebook) pci:v00001180d00000552sv000017AAsd0000201E* ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (ThinkPad X60/X60s) pci:v00001180d00000554* ID_MODEL_FROM_DATABASE=R5C554 pci:v00001180d00000575* ID_MODEL_FROM_DATABASE=R5C575 SD Bus Host Adapter pci:v00001180d00000576* ID_MODEL_FROM_DATABASE=R5C576 SD Bus Host Adapter pci:v00001180d00000592* ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter pci:v00001180d00000592sv00001025sd00000121* ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Aspire 5920G) pci:v00001180d00000592sv00001028sd000001D7* ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (XPS M1210) pci:v00001180d00000592sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Inspiron 1420) pci:v00001180d00000592sv0000103Csd000030B5* ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Presario V3242AU) pci:v00001180d00000592sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Presario V6133CL) pci:v00001180d00000592sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Pavilion dv6700) pci:v00001180d00000592sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Pavilion dv9500/9600/9700 series) pci:v00001180d00000592sv00001043sd00001237* ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (A6J-Q008) pci:v00001180d00000592sv00001043sd00001967* ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (V6800V) pci:v00001180d00000592sv0000144Dsd0000C018* ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (X20 IV) pci:v00001180d00000592sv000017AAsd000020CA* ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (ThinkPad T61) pci:v00001180d00000811* ID_MODEL_FROM_DATABASE=R5C811 pci:v00001180d00000822* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter pci:v00001180d00000822sv00001014sd00000556* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (ThinkPad X60s / Z60t) pci:v00001180d00000822sv00001014sd00000598* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (ThinkPad Z60m) pci:v00001180d00000822sv00001025sd00000121* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Aspire 5920G) pci:v00001180d00000822sv00001028sd00000188* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Inspiron 6000 laptop) pci:v00001180d00000822sv00001028sd000001A2* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Inspiron 9200) pci:v00001180d00000822sv00001028sd000001D7* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (XPS M1210) pci:v00001180d00000822sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Inspiron 1420) pci:v00001180d00000822sv0000103Csd000003B5* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Presario V3242AU) pci:v00001180d00000822sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Presario V6133CL) pci:v00001180d00000822sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Compaq 6910p) pci:v00001180d00000822sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Pavilion dv6700) pci:v00001180d00000822sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Pavilion dv9668eg Laptop) pci:v00001180d00000822sv00001043sd00001237* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (A6J-Q008) pci:v00001180d00000822sv00001043sd00001967* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (ASUS V6800V) pci:v00001180d00000822sv000010F7sd00008338* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Panasonic CF-Y5 laptop) pci:v00001180d00000822sv0000144Dsd0000C018* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (X20 IV) pci:v00001180d00000822sv000017AAsd0000201D* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (ThinkPad X60/X60s) pci:v00001180d00000822sv000017AAsd000020C7* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (ThinkPad T61) pci:v00001180d00000822sv000017AAsd000020C8* ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (ThinkPad W500) pci:v00001180d00000832* ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller pci:v00001180d00000832sv00001025sd00000121* ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Aspire 5920G) pci:v00001180d00000832sv00001028sd000001D7* ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (XPS M1210) pci:v00001180d00000832sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Inspiron 1420) pci:v00001180d00000832sv00001028sd0000024D* ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Latitude E4300) pci:v00001180d00000832sv0000103Csd000030B5* ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Presario V3242AU) pci:v00001180d00000832sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Presario V6133CL) pci:v00001180d00000832sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Compaq 6910p) pci:v00001180d00000832sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Pavilion dv6700) pci:v00001180d00000832sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Pavilion dv9668eg Laptop) pci:v00001180d00000832sv000017AAsd000020C7* ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (ThinkPad R61) pci:v00001180d00000841* ID_MODEL_FROM_DATABASE=R5C841 CardBus/SD/SDIO/MMC/MS/MSPro/xD/IEEE1394 pci:v00001180d00000843* ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller pci:v00001180d00000843sv00001025sd00000121* ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Aspire 5920G) pci:v00001180d00000843sv00001028sd000001D7* ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (XPS M1210) pci:v00001180d00000843sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Inspiron 1420) pci:v00001180d00000843sv00001028sd000001F5* ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Dell Inspiron 1501) pci:v00001180d00000843sv00001028sd0000024F* ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Dell Latitude e6500) pci:v00001180d00000843sv0000103Csd000003B5* ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Presario V3242AU) pci:v00001180d00000843sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Presario V6133CL) pci:v00001180d00000843sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Pavilion dv9500/9600/9700 series) pci:v00001180d00000843sv00001183sd00000843* ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Alienware Aurora m9700) pci:v00001180d00000852* ID_MODEL_FROM_DATABASE=xD-Picture Card Controller pci:v00001180d00000852sv00001025sd00000121* ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Aspire 5920G) pci:v00001180d00000852sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Inspiron 1420) pci:v00001180d00000852sv0000103Csd000030B5* ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Presario V3242AU) pci:v00001180d00000852sv0000103Csd000030B7* ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Presario V6133CL) pci:v00001180d00000852sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Pavilion dv6700) pci:v00001180d00000852sv0000103Csd000030CF* ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Pavilion dv9668eg Laptop) pci:v00001180d00000852sv00001043sd00001967* ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (V6800V) pci:v00001180d00000852sv00001180sd00000852* ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Pavilion 2410us) pci:v00001180d00000852sv00001324sd000010CF* ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (P7120) pci:v00001180d0000E230* ID_MODEL_FROM_DATABASE=R5U2xx (R5U230 / R5U231 / R5U241) [Memory Stick Host Controller] pci:v00001180d0000E476* ID_MODEL_FROM_DATABASE=CardBus bridge pci:v00001180d0000E476sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=CardBus bridge (Latitude E6410) pci:v00001180d0000E476sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=CardBus bridge (Latitude E6510) pci:v00001180d0000E822* ID_MODEL_FROM_DATABASE=MMC/SD Host Controller pci:v00001180d0000E822sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=MMC/SD Host Controller (Latitude E6410) pci:v00001180d0000E822sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=MMC/SD Host Controller (Latitude E6510) pci:v00001180d0000E823* ID_MODEL_FROM_DATABASE=PCIe SDXC/MMC Host Controller pci:v00001180d0000E832* ID_MODEL_FROM_DATABASE=R5C832 PCIe IEEE 1394 Controller pci:v00001180d0000E832sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=R5C832 PCIe IEEE 1394 Controller (Latitude E6410) pci:v00001180d0000E832sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=R5C832 PCIe IEEE 1394 Controller (Latitude E6510) pci:v00001180d0000E852* ID_MODEL_FROM_DATABASE=PCIe xD-Picture Card Controller pci:v00001181* ID_VENDOR_FROM_DATABASE=Telmatics International pci:v00001183* ID_VENDOR_FROM_DATABASE=Fujikura Ltd pci:v00001184* ID_VENDOR_FROM_DATABASE=Forks Inc pci:v00001185* ID_VENDOR_FROM_DATABASE=Dataworld International Ltd pci:v00001186* ID_VENDOR_FROM_DATABASE=D-Link System Inc pci:v00001186d00001002* ID_MODEL_FROM_DATABASE=DL10050 Sundance Ethernet pci:v00001186d00001002sv00001186sd00001002* ID_MODEL_FROM_DATABASE=DL10050 Sundance Ethernet (DFE-550TX/FX) pci:v00001186d00001002sv00001186sd00001012* ID_MODEL_FROM_DATABASE=DL10050 Sundance Ethernet (DFE-580TX) pci:v00001186d00001025* ID_MODEL_FROM_DATABASE=AirPlus Xtreme G DWL-G650 Adapter pci:v00001186d00001026* ID_MODEL_FROM_DATABASE=AirXpert DWL-AG650 Wireless Cardbus Adapter pci:v00001186d00001043* ID_MODEL_FROM_DATABASE=AirXpert DWL-AG650 Wireless Cardbus Adapter pci:v00001186d00001300* ID_MODEL_FROM_DATABASE=RTL8139 Ethernet pci:v00001186d00001300sv00001186sd00001300* ID_MODEL_FROM_DATABASE=RTL8139 Ethernet (DFE-538TX 10/100 Ethernet Adapter) pci:v00001186d00001300sv00001186sd00001301* ID_MODEL_FROM_DATABASE=RTL8139 Ethernet (DFE-530TX+ 10/100 Ethernet Adapter) pci:v00001186d00001300sv00001186sd00001303* ID_MODEL_FROM_DATABASE=RTL8139 Ethernet (DFE-528TX 10/100 Fast Ethernet PCI Adapter) pci:v00001186d00001340* ID_MODEL_FROM_DATABASE=DFE-690TXD CardBus PC Card pci:v00001186d00001540* ID_MODEL_FROM_DATABASE=DFE-680TX pci:v00001186d00001541* ID_MODEL_FROM_DATABASE=DFE-680TXD CardBus PC Card pci:v00001186d00001561* ID_MODEL_FROM_DATABASE=DRP-32TXD Cardbus PC Card pci:v00001186d00003300* ID_MODEL_FROM_DATABASE=DWL-510 / DWL-610 802.11b [Realtek RTL8180L] pci:v00001186d00003300sv00001186sd00003300* ID_MODEL_FROM_DATABASE=DWL-510 / DWL-610 802.11b [Realtek RTL8180L] (DWL-610 Wireless Cardbus Adapter) pci:v00001186d00003300sv00001186sd00003301* ID_MODEL_FROM_DATABASE=DWL-510 / DWL-610 802.11b [Realtek RTL8180L] (DWL-510 Wireless PCI Adapter) pci:v00001186d00003A10* ID_MODEL_FROM_DATABASE=AirXpert DWL-AG650 Wireless Cardbus Adapter(rev.B) pci:v00001186d00003A11* ID_MODEL_FROM_DATABASE=AirXpert DWL-AG520 Wireless PCI Adapter(rev.B) pci:v00001186d00004000* ID_MODEL_FROM_DATABASE=DL2000-based Gigabit Ethernet pci:v00001186d00004001* ID_MODEL_FROM_DATABASE=DGE-550SX PCI-X Gigabit Ethernet Adapter pci:v00001186d00004200* ID_MODEL_FROM_DATABASE=DFE-520TX Fast Ethernet PCI Adapter pci:v00001186d00004200sv00001186sd00001103* ID_MODEL_FROM_DATABASE=DFE-520TX Fast Ethernet PCI Adapter ((rev. C1)) pci:v00001186d00004300* ID_MODEL_FROM_DATABASE=DGE-528T Gigabit Ethernet Adapter pci:v00001186d00004300sv00001186sd00004300* ID_MODEL_FROM_DATABASE=DGE-528T Gigabit Ethernet Adapter (DGE-528T PCI Gigabit Ethernet Adapter) pci:v00001186d00004300sv00001186sd00004B10* ID_MODEL_FROM_DATABASE=DGE-528T Gigabit Ethernet Adapter (DGE-560T PCI Express (x1) Gigabit Ethernet Adapter) pci:v00001186d00004302* ID_MODEL_FROM_DATABASE=DGE-530T Gigabit Ethernet Adapter (rev.C1) [Realtek RTL8169] pci:v00001186d00004B00* ID_MODEL_FROM_DATABASE=DGE-560T PCI Express Gigabit Ethernet Adapter pci:v00001186d00004B01* ID_MODEL_FROM_DATABASE=DGE-530T Gigabit Ethernet Adapter (rev 11) pci:v00001186d00004B02* ID_MODEL_FROM_DATABASE=DGE-560SX PCI Express Gigabit Ethernet Adapter pci:v00001186d00004B03* ID_MODEL_FROM_DATABASE=DGE-550T Gigabit Ethernet Adapter V.B1 pci:v00001186d00004C00* ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter pci:v00001186d00004C00sv00001186sd00004C00* ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter (DGE-530T Gigabit Ethernet Adapter) pci:v00001186d00008400* ID_MODEL_FROM_DATABASE=D-Link DWL-650+ CardBus PC Card pci:v00001187* ID_VENDOR_FROM_DATABASE=Advanced Technology Laboratories, Inc. pci:v00001188* ID_VENDOR_FROM_DATABASE=Shima Seiki Manufacturing Ltd. pci:v00001189* ID_VENDOR_FROM_DATABASE=Matsushita Electronics Co Ltd pci:v0000118A* ID_VENDOR_FROM_DATABASE=Hilevel Technology pci:v0000118B* ID_VENDOR_FROM_DATABASE=Hypertec Pty Limited pci:v0000118C* ID_VENDOR_FROM_DATABASE=Corollary, Inc pci:v0000118Cd00000014* ID_MODEL_FROM_DATABASE=PCIB [C-bus II to PCI bus host bridge chip] pci:v0000118Cd00001117* ID_MODEL_FROM_DATABASE=Intel 8-way XEON Profusion Chipset [Cache Coherency Filter] pci:v0000118D* ID_VENDOR_FROM_DATABASE=BitFlow Inc pci:v0000118Dd00000001* ID_MODEL_FROM_DATABASE=Raptor-PCI framegrabber pci:v0000118Dd00000012* ID_MODEL_FROM_DATABASE=Model 12 Road Runner Frame Grabber pci:v0000118Dd00000014* ID_MODEL_FROM_DATABASE=Model 14 Road Runner Frame Grabber pci:v0000118Dd00000024* ID_MODEL_FROM_DATABASE=Model 24 Road Runner Frame Grabber pci:v0000118Dd00000044* ID_MODEL_FROM_DATABASE=Model 44 Road Runner Frame Grabber pci:v0000118Dd00000112* ID_MODEL_FROM_DATABASE=Model 12 Road Runner Frame Grabber pci:v0000118Dd00000114* ID_MODEL_FROM_DATABASE=Model 14 Road Runner Frame Grabber pci:v0000118Dd00000124* ID_MODEL_FROM_DATABASE=Model 24 Road Runner Frame Grabber pci:v0000118Dd00000144* ID_MODEL_FROM_DATABASE=Model 44 Road Runner Frame Grabber pci:v0000118Dd00000212* ID_MODEL_FROM_DATABASE=Model 12 Road Runner Frame Grabber pci:v0000118Dd00000214* ID_MODEL_FROM_DATABASE=Model 14 Road Runner Frame Grabber pci:v0000118Dd00000224* ID_MODEL_FROM_DATABASE=Model 24 Road Runner Frame Grabber pci:v0000118Dd00000244* ID_MODEL_FROM_DATABASE=Model 44 Road Runner Frame Grabber pci:v0000118Dd00000312* ID_MODEL_FROM_DATABASE=Model 12 Road Runner Frame Grabber pci:v0000118Dd00000314* ID_MODEL_FROM_DATABASE=Model 14 Road Runner Frame Grabber pci:v0000118Dd00000324* ID_MODEL_FROM_DATABASE=Model 24 Road Runner Frame Grabber pci:v0000118Dd00000344* ID_MODEL_FROM_DATABASE=Model 44 Road Runner Frame Grabber pci:v0000118E* ID_VENDOR_FROM_DATABASE=Hermstedt GmbH pci:v0000118F* ID_VENDOR_FROM_DATABASE=Green Logic pci:v00001190* ID_VENDOR_FROM_DATABASE=Tripace pci:v00001190d0000C731* ID_MODEL_FROM_DATABASE=TP-910/920/940 PCI Ultra(Wide) SCSI Adapter pci:v00001191* ID_VENDOR_FROM_DATABASE=Artop Electronic Corp pci:v00001191d00000003* ID_MODEL_FROM_DATABASE=SCSI Cache Host Adapter pci:v00001191d00000004* ID_MODEL_FROM_DATABASE=ATP8400 pci:v00001191d00000005* ID_MODEL_FROM_DATABASE=ATP850UF pci:v00001191d00000006* ID_MODEL_FROM_DATABASE=ATP860 NO-BIOS pci:v00001191d00000007* ID_MODEL_FROM_DATABASE=ATP860 pci:v00001191d00000008* ID_MODEL_FROM_DATABASE=ATP865 NO-ROM pci:v00001191d00000009* ID_MODEL_FROM_DATABASE=ATP865 pci:v00001191d0000000A* ID_MODEL_FROM_DATABASE=ATP867-A pci:v00001191d0000000B* ID_MODEL_FROM_DATABASE=ATP867-B pci:v00001191d0000000D* ID_MODEL_FROM_DATABASE=ATP8620 pci:v00001191d0000000E* ID_MODEL_FROM_DATABASE=ATP8620 pci:v00001191d00008002* ID_MODEL_FROM_DATABASE=AEC6710 SCSI-2 Host Adapter pci:v00001191d00008010* ID_MODEL_FROM_DATABASE=AEC6712UW SCSI pci:v00001191d00008020* ID_MODEL_FROM_DATABASE=AEC6712U SCSI pci:v00001191d00008030* ID_MODEL_FROM_DATABASE=AEC6712S SCSI pci:v00001191d00008040* ID_MODEL_FROM_DATABASE=AEC6712D SCSI pci:v00001191d00008050* ID_MODEL_FROM_DATABASE=AEC6712SUW SCSI pci:v00001191d00008060* ID_MODEL_FROM_DATABASE=AEC6712 SCSI pci:v00001191d00008080* ID_MODEL_FROM_DATABASE=AEC67160 SCSI pci:v00001191d00008081* ID_MODEL_FROM_DATABASE=AEC67160S SCSI pci:v00001191d0000808A* ID_MODEL_FROM_DATABASE=AEC67162 2-ch. LVD SCSI pci:v00001192* ID_VENDOR_FROM_DATABASE=Densan Company Ltd pci:v00001193* ID_VENDOR_FROM_DATABASE=Zeitnet Inc. pci:v00001193d00000001* ID_MODEL_FROM_DATABASE=1221 pci:v00001193d00000002* ID_MODEL_FROM_DATABASE=1225 pci:v00001194* ID_VENDOR_FROM_DATABASE=Toucan Technology pci:v00001195* ID_VENDOR_FROM_DATABASE=Ratoc System Inc pci:v00001196* ID_VENDOR_FROM_DATABASE=Hytec Electronics Ltd pci:v00001197* ID_VENDOR_FROM_DATABASE=Gage Applied Sciences, Inc. pci:v00001197d0000010C* ID_MODEL_FROM_DATABASE=CompuScope 82G 8bit 2GS/s Analog Input Card pci:v00001198* ID_VENDOR_FROM_DATABASE=Lambda Systems Inc pci:v00001199* ID_VENDOR_FROM_DATABASE=Attachmate Corporation pci:v00001199d00000101* ID_MODEL_FROM_DATABASE=Advanced ISCA/PCI Adapter pci:v0000119A* ID_VENDOR_FROM_DATABASE=Mind Share, Inc. pci:v0000119B* ID_VENDOR_FROM_DATABASE=Omega Micro Inc. pci:v0000119Bd00001221* ID_MODEL_FROM_DATABASE=82C092G pci:v0000119C* ID_VENDOR_FROM_DATABASE=Information Technology Inst. pci:v0000119D* ID_VENDOR_FROM_DATABASE=Bug, Inc. Sapporo Japan pci:v0000119E* ID_VENDOR_FROM_DATABASE=Fujitsu Microelectronics Ltd. pci:v0000119Ed00000001* ID_MODEL_FROM_DATABASE=FireStream 155 pci:v0000119Ed00000003* ID_MODEL_FROM_DATABASE=FireStream 50 pci:v0000119F* ID_VENDOR_FROM_DATABASE=Bull HN Information Systems pci:v000011A0* ID_VENDOR_FROM_DATABASE=Convex Computer Corporation pci:v000011A1* ID_VENDOR_FROM_DATABASE=Hamamatsu Photonics K.K. pci:v000011A2* ID_VENDOR_FROM_DATABASE=Sierra Research and Technology pci:v000011A3* ID_VENDOR_FROM_DATABASE=Deuretzbacher GmbH & Co. Eng. KG pci:v000011A4* ID_VENDOR_FROM_DATABASE=Barco Graphics NV pci:v000011A5* ID_VENDOR_FROM_DATABASE=Microunity Systems Eng. Inc pci:v000011A6* ID_VENDOR_FROM_DATABASE=Pure Data Ltd. pci:v000011A7* ID_VENDOR_FROM_DATABASE=Power Computing Corp. pci:v000011A8* ID_VENDOR_FROM_DATABASE=Systech Corp. pci:v000011A9* ID_VENDOR_FROM_DATABASE=InnoSys Inc. pci:v000011A9d00004240* ID_MODEL_FROM_DATABASE=AMCC S933Q Intelligent Serial Card pci:v000011AA* ID_VENDOR_FROM_DATABASE=Actel pci:v000011AB* ID_VENDOR_FROM_DATABASE=Marvell Technology Group Ltd. pci:v000011ABd00000146* ID_MODEL_FROM_DATABASE=GT-64010/64010A System Controller pci:v000011ABd00000F53* ID_MODEL_FROM_DATABASE=88E6318 Link Street network controller pci:v000011ABd000011AB* ID_MODEL_FROM_DATABASE=MV88SE614x SATA II PCI-E controller pci:v000011ABd0000138F* ID_MODEL_FROM_DATABASE=W8300 802.11 Adapter (rev 07) pci:v000011ABd00001FA6* ID_MODEL_FROM_DATABASE=Marvell W8300 802.11 Adapter pci:v000011ABd00001FA6sv00001186sd00003B08* ID_MODEL_FROM_DATABASE=Marvell W8300 802.11 Adapter (AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.A1)) pci:v000011ABd00001FA7* ID_MODEL_FROM_DATABASE=88W8310 and 88W8000G [Libertas] 802.11g client chipset pci:v000011ABd00001FAA* ID_MODEL_FROM_DATABASE=88w8335 [Libertas] 802.11b/g Wireless pci:v000011ABd00001FAAsv00001385sd00004E00* ID_MODEL_FROM_DATABASE=88w8335 [Libertas] 802.11b/g Wireless (WG511v2 54 Mbps Wireless PC Card) pci:v000011ABd00001FAAsv00001385sd00006B00* ID_MODEL_FROM_DATABASE=88w8335 [Libertas] 802.11b/g Wireless (WG311v3 802.11g Wireless PCI Adapter) pci:v000011ABd00001FAAsv00001737sd00000040* ID_MODEL_FROM_DATABASE=88w8335 [Libertas] 802.11b/g Wireless (WPC54G v5 802.11g Wireless-G Notebook Adapter) pci:v000011ABd00002211* ID_MODEL_FROM_DATABASE=88SB2211 PCI Express to PCI Bridge pci:v000011ABd00002A01* ID_MODEL_FROM_DATABASE=88W8335 [Libertas] 802.11b/g Wireless pci:v000011ABd00002A02* ID_MODEL_FROM_DATABASE=88W8361 [TopDog] 802.11n Wireless pci:v000011ABd00002A02sv000007D1sd00003B02* ID_MODEL_FROM_DATABASE=88W8361 [TopDog] 802.11n Wireless (DIR-615 rev. A1 Mini PCI Wireless Module) pci:v000011ABd00002A02sv00001385sd00007C00* ID_MODEL_FROM_DATABASE=88W8361 [TopDog] 802.11n Wireless (WN511T RangeMax Next 300 Mbps Wireless PC Card) pci:v000011ABd00002A02sv00001385sd00007C01* ID_MODEL_FROM_DATABASE=88W8361 [TopDog] 802.11n Wireless (WN511T RangeMax Next 300 Mbps Wireless Notebook Adapter) pci:v000011ABd00002A02sv00001385sd00007E00* ID_MODEL_FROM_DATABASE=88W8361 [TopDog] 802.11n Wireless (WN311T RangeMax Next 300 Mbps Wireless PCI Adapter) pci:v000011ABd00002A02sv00001799sd0000801B* ID_MODEL_FROM_DATABASE=88W8361 [TopDog] 802.11n Wireless (F5D8011 v2 802.11n N1 Wireless Notebook Card) pci:v000011ABd00002A08* ID_MODEL_FROM_DATABASE=88W8362e [TopDog] 802.11a/b/g/n Wireless pci:v000011ABd00002A0A* ID_MODEL_FROM_DATABASE=88W8363 [TopDog] 802.11n Wireless pci:v000011ABd00002A0C* ID_MODEL_FROM_DATABASE=88W8363 [TopDog] 802.11n Wireless pci:v000011ABd00002A24* ID_MODEL_FROM_DATABASE=88W8363 [TopDog] 802.11n Wireless pci:v000011ABd00002A2B* ID_MODEL_FROM_DATABASE=88W8687 [TopDog] 802.11b/g Wireless pci:v000011ABd00002A30* ID_MODEL_FROM_DATABASE=88W8687 [TopDog] 802.11b/g Wireless pci:v000011ABd00002A40* ID_MODEL_FROM_DATABASE=88W8366 [TopDog] 802.11n Wireless pci:v000011ABd00002A41* ID_MODEL_FROM_DATABASE=88W8366 [TopDog] 802.11n Wireless pci:v000011ABd00002A42* ID_MODEL_FROM_DATABASE=88W8366 [TopDog] 802.11n Wireless pci:v000011ABd00002A43* ID_MODEL_FROM_DATABASE=88W8366 [TopDog] 802.11n Wireless pci:v000011ABd00002A55* ID_MODEL_FROM_DATABASE=88W8864 [Avastar] 802.11ac Wireless pci:v000011ABd00002B36* ID_MODEL_FROM_DATABASE=88W8764 [Avastar] 802.11n Wireless pci:v000011ABd00002B38* ID_MODEL_FROM_DATABASE=88W8897 [AVASTAR] 802.11ac Wireless pci:v000011ABd00004101* ID_MODEL_FROM_DATABASE=OLPC Cafe Controller Secure Digital Controller pci:v000011ABd00004320* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller pci:v000011ABd00004320sv00001019sd00000F38* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (ECS)) pci:v000011ABd00004320sv00001019sd00008001* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (ECS)) pci:v000011ABd00004320sv00001043sd0000173C* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Asus)) pci:v000011ABd00004320sv00001043sd0000811A* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Asus)) pci:v000011ABd00004320sv0000105Bsd00000C19* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Foxconn)) pci:v000011ABd00004320sv000010B8sd0000B452* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (EZ Card 1000 (SMC9452TXV.2)) pci:v000011ABd00004320sv000011ABsd00000121* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell RDK-8001) pci:v000011ABd00004320sv000011ABsd00000321* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell RDK-8003) pci:v000011ABd00004320sv000011ABsd00001021* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell RDK-8010) pci:v000011ABd00004320sv000011ABsd00004320* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell Yukon Gigabit Ethernet 10/100/1000Baset-T Constroller (Asus)) pci:v000011ABd00004320sv000011ABsd00005021* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (64 bit)) pci:v000011ABd00004320sv000011ABsd00009521* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (32 bit)) pci:v000011ABd00004320sv00001458sd0000E000* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Gigabyte)) pci:v000011ABd00004320sv0000147Bsd00001406* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Abit)) pci:v000011ABd00004320sv000015D4sd00000047* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Iwill)) pci:v000011ABd00004320sv00001695sd00009025* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Epox)) pci:v000011ABd00004320sv000017F2sd00001C03* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Albatron)) pci:v000011ABd00004320sv0000270Fsd00002803* ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Chaintech)) pci:v000011ABd00004340* ID_MODEL_FROM_DATABASE=88E8021 PCI-X IPMI Gigabit Ethernet Controller pci:v000011ABd00004341* ID_MODEL_FROM_DATABASE=88E8022 PCI-X IPMI Gigabit Ethernet Controller pci:v000011ABd00004342* ID_MODEL_FROM_DATABASE=88E8061 PCI-E IPMI Gigabit Ethernet Controller pci:v000011ABd00004343* ID_MODEL_FROM_DATABASE=88E8062 PCI-E IPMI Gigabit Ethernet Controller pci:v000011ABd00004344* ID_MODEL_FROM_DATABASE=88E8021 PCI-X IPMI Gigabit Ethernet Controller pci:v000011ABd00004345* ID_MODEL_FROM_DATABASE=88E8022 PCI-X IPMI Gigabit Ethernet Controller pci:v000011ABd00004346* ID_MODEL_FROM_DATABASE=88E8061 PCI-E IPMI Gigabit Ethernet Controller pci:v000011ABd00004347* ID_MODEL_FROM_DATABASE=88E8062 PCI-E IPMI Gigabit Ethernet Controller pci:v000011ABd00004347sv00004C53sd000010D0* ID_MODEL_FROM_DATABASE=88E8062 PCI-E IPMI Gigabit Ethernet Controller (Telum ASLP10 PrAMC Gigabit Ethernet) pci:v000011ABd00004350* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller pci:v000011ABd00004350sv00001179sd00000001* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (Toshiba)) pci:v000011ABd00004350sv000011ABsd00003521* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell RDK-8035) pci:v000011ABd00004350sv00001854sd0000000D* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) pci:v000011ABd00004350sv00001854sd0000000E* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) pci:v000011ABd00004350sv00001854sd0000000F* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) pci:v000011ABd00004350sv00001854sd00000011* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) pci:v000011ABd00004350sv00001854sd00000012* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) pci:v000011ABd00004350sv00001854sd00000016* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) pci:v000011ABd00004350sv00001854sd00000017* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) pci:v000011ABd00004350sv00001854sd00000018* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) pci:v000011ABd00004350sv00001854sd00000019* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) pci:v000011ABd00004350sv00001854sd0000001C* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) pci:v000011ABd00004350sv00001854sd0000001E* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) pci:v000011ABd00004350sv00001854sd00000020* ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) pci:v000011ABd00004351* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller pci:v000011ABd00004351sv0000107Bsd00004009* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (Wistron)) pci:v000011ABd00004351sv000010F7sd00008338* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (Panasonic)) pci:v000011ABd00004351sv00001179sd00000001* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (Toshiba)) pci:v000011ABd00004351sv00001179sd0000FF00* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (Compal)) pci:v000011ABd00004351sv00001179sd0000FF10* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (Inventec)) pci:v000011ABd00004351sv000011ABsd00003621* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell RDK-8036) pci:v000011ABd00004351sv000013D1sd0000AC12* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Abocom EFE3K - 10/100 Ethernet Expresscard) pci:v000011ABd00004351sv0000161Fsd0000203D* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (Arima)) pci:v000011ABd00004351sv00001854sd0000000D* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) pci:v000011ABd00004351sv00001854sd0000000E* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) pci:v000011ABd00004351sv00001854sd0000000F* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) pci:v000011ABd00004351sv00001854sd00000011* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) pci:v000011ABd00004351sv00001854sd00000012* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) pci:v000011ABd00004351sv00001854sd00000016* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) pci:v000011ABd00004351sv00001854sd00000017* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) pci:v000011ABd00004351sv00001854sd00000018* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) pci:v000011ABd00004351sv00001854sd00000019* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) pci:v000011ABd00004351sv00001854sd0000001C* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) pci:v000011ABd00004351sv00001854sd0000001E* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) pci:v000011ABd00004351sv00001854sd00000020* ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) pci:v000011ABd00004352* ID_MODEL_FROM_DATABASE=88E8038 PCI-E Fast Ethernet Controller pci:v000011ABd00004353* ID_MODEL_FROM_DATABASE=88E8039 PCI-E Fast Ethernet Controller pci:v000011ABd00004353sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=88E8039 PCI-E Fast Ethernet Controller (VAIO VGN-NR120E) pci:v000011ABd00004354* ID_MODEL_FROM_DATABASE=88E8040 PCI-E Fast Ethernet Controller pci:v000011ABd00004354sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=88E8040 PCI-E Fast Ethernet Controller (R730 Laptop) pci:v000011ABd00004354sv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=88E8040 PCI-E Fast Ethernet Controller (Notebook N150P) pci:v000011ABd00004355* ID_MODEL_FROM_DATABASE=88E8040T PCI-E Fast Ethernet Controller pci:v000011ABd00004355sv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=88E8040T PCI-E Fast Ethernet Controller (Satellite P305D-S8995E) pci:v000011ABd00004356* ID_MODEL_FROM_DATABASE=88EC033 PCI-E Fast Ethernet Controller pci:v000011ABd00004357* ID_MODEL_FROM_DATABASE=88E8042 PCI-E Fast Ethernet Controller pci:v000011ABd0000435A* ID_MODEL_FROM_DATABASE=88E8048 PCI-E Fast Ethernet Controller pci:v000011ABd00004360* ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller pci:v000011ABd00004360sv00001043sd00008134* ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8052 Gigabit Ethernet Controller (Asus)) pci:v000011ABd00004360sv0000107Bsd00004009* ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8052 Gigabit Ethernet Controller (Wistron)) pci:v000011ABd00004360sv000011ABsd00005221* ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell RDK-8052) pci:v000011ABd00004360sv00001458sd0000E000* ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8052 Gigabit Ethernet Controller (Gigabyte)) pci:v000011ABd00004360sv00001462sd0000052C* ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8052 Gigabit Ethernet Controller (MSI)) pci:v000011ABd00004360sv00001849sd00008052* ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8052 Gigabit Ethernet Controller (ASRock)) pci:v000011ABd00004360sv0000A0A0sd00000509* ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8052 Gigabit Ethernet Controller (Aopen)) pci:v000011ABd00004361* ID_MODEL_FROM_DATABASE=88E8050 PCI-E ASF Gigabit Ethernet Controller pci:v000011ABd00004361sv0000107Bsd00003015* ID_MODEL_FROM_DATABASE=88E8050 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8050 Gigabit Ethernet Controller (Gateway)) pci:v000011ABd00004361sv000011ABsd00005021* ID_MODEL_FROM_DATABASE=88E8050 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8050 Gigabit Ethernet Controller (Intel)) pci:v000011ABd00004361sv00008086sd00003063* ID_MODEL_FROM_DATABASE=88E8050 PCI-E ASF Gigabit Ethernet Controller (D925XCVLK mainboard) pci:v000011ABd00004361sv00008086sd00003439* ID_MODEL_FROM_DATABASE=88E8050 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8050 Gigabit Ethernet Controller (Intel)) pci:v000011ABd00004362* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller pci:v000011ABd00004362sv0000103Csd00002A0D* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Asus)) pci:v000011ABd00004362sv00001043sd00008142* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet controller PCIe (Asus)) pci:v000011ABd00004362sv0000109Fsd00003197* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Trigem)) pci:v000011ABd00004362sv000010F7sd00008338* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Panasonic)) pci:v000011ABd00004362sv000010FDsd0000A430* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (SOYO)) pci:v000011ABd00004362sv00001179sd00000001* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Toshiba)) pci:v000011ABd00004362sv00001179sd0000FF00* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Compal)) pci:v000011ABd00004362sv00001179sd0000FF10* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Inventec)) pci:v000011ABd00004362sv000011ABsd00005321* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell RDK-8053) pci:v000011ABd00004362sv00001297sd0000C240* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)) pci:v000011ABd00004362sv00001297sd0000C241* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)) pci:v000011ABd00004362sv00001297sd0000C242* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)) pci:v000011ABd00004362sv00001297sd0000C243* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)) pci:v000011ABd00004362sv00001297sd0000C244* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)) pci:v000011ABd00004362sv000013D1sd0000AC11* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (EGE5K - Giga Ethernet Expresscard) pci:v000011ABd00004362sv00001458sd0000E000* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Gigabyte)) pci:v000011ABd00004362sv00001462sd0000058C* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (MSI)) pci:v000011ABd00004362sv000014C0sd00000012* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Compal)) pci:v000011ABd00004362sv00001558sd000004A0* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Clevo)) pci:v000011ABd00004362sv000015BDsd00001003* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (DFI)) pci:v000011ABd00004362sv0000161Fsd0000203C* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Arima)) pci:v000011ABd00004362sv0000161Fsd0000203D* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Arima)) pci:v000011ABd00004362sv00001695sd00009029* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Epox)) pci:v000011ABd00004362sv000017F2sd00002C08* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Albatron)) pci:v000011ABd00004362sv000017FFsd00000585* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Quanta)) pci:v000011ABd00004362sv00001849sd00008053* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (ASRock)) pci:v000011ABd00004362sv00001854sd0000000B* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) pci:v000011ABd00004362sv00001854sd0000000C* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) pci:v000011ABd00004362sv00001854sd00000010* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) pci:v000011ABd00004362sv00001854sd00000013* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) pci:v000011ABd00004362sv00001854sd00000014* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) pci:v000011ABd00004362sv00001854sd00000015* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) pci:v000011ABd00004362sv00001854sd0000001A* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) pci:v000011ABd00004362sv00001854sd0000001B* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) pci:v000011ABd00004362sv00001854sd0000001D* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) pci:v000011ABd00004362sv00001854sd0000001F* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) pci:v000011ABd00004362sv00001854sd00000021* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) pci:v000011ABd00004362sv00001854sd00000022* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) pci:v000011ABd00004362sv0000270Fsd00002801* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Chaintech)) pci:v000011ABd00004362sv0000A0A0sd00000506* ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Aopen)) pci:v000011ABd00004363* ID_MODEL_FROM_DATABASE=88E8055 PCI-E Gigabit Ethernet Controller pci:v000011ABd00004364* ID_MODEL_FROM_DATABASE=88E8056 PCI-E Gigabit Ethernet Controller pci:v000011ABd00004364sv00001043sd000081F8* ID_MODEL_FROM_DATABASE=88E8056 PCI-E Gigabit Ethernet Controller (Motherboard) pci:v000011ABd00004364sv000011BAsd000000BA* ID_MODEL_FROM_DATABASE=88E8056 PCI-E Gigabit Ethernet Controller (8056 Gigabit Ethernet Controller) pci:v000011ABd00004365* ID_MODEL_FROM_DATABASE=88E8070 based Ethernet Controller pci:v000011ABd00004366* ID_MODEL_FROM_DATABASE=88EC036 PCI-E Gigabit Ethernet Controller pci:v000011ABd00004367* ID_MODEL_FROM_DATABASE=88EC032 Ethernet Controller pci:v000011ABd00004368* ID_MODEL_FROM_DATABASE=88EC034 Ethernet Controller pci:v000011ABd00004369* ID_MODEL_FROM_DATABASE=88EC042 Ethernet Controller pci:v000011ABd0000436A* ID_MODEL_FROM_DATABASE=88E8058 PCI-E Gigabit Ethernet Controller pci:v000011ABd0000436Asv000011ABsd000000BA* ID_MODEL_FROM_DATABASE=88E8058 PCI-E Gigabit Ethernet Controller (Imac 8,1 Wired Ethernet Adapter) pci:v000011ABd0000436B* ID_MODEL_FROM_DATABASE=88E8071 PCI-E Gigabit Ethernet Controller pci:v000011ABd0000436C* ID_MODEL_FROM_DATABASE=88E8072 PCI-E Gigabit Ethernet Controller pci:v000011ABd0000436D* ID_MODEL_FROM_DATABASE=88E8055 PCI-E Gigabit Ethernet Controller pci:v000011ABd00004370* ID_MODEL_FROM_DATABASE=88E8075 PCI-E Gigabit Ethernet Controller pci:v000011ABd00004380* ID_MODEL_FROM_DATABASE=88E8057 PCI-E Gigabit Ethernet Controller pci:v000011ABd00004381* ID_MODEL_FROM_DATABASE=Yukon Optima 88E8059 [PCIe Gigabit Ethernet Controller with AVB] pci:v000011ABd00004611* ID_MODEL_FROM_DATABASE=GT-64115 System Controller pci:v000011ABd00004620* ID_MODEL_FROM_DATABASE=GT-64120/64120A/64121A System Controller pci:v000011ABd00004801* ID_MODEL_FROM_DATABASE=GT-48001 pci:v000011ABd00005005* ID_MODEL_FROM_DATABASE=Belkin F5D5005 Gigabit Desktop Network PCI Card pci:v000011ABd00005040* ID_MODEL_FROM_DATABASE=MV88SX5040 4-port SATA I PCI-X Controller pci:v000011ABd00005041* ID_MODEL_FROM_DATABASE=MV88SX5041 4-port SATA I PCI-X Controller pci:v000011ABd00005080* ID_MODEL_FROM_DATABASE=MV88SX5080 8-port SATA I PCI-X Controller pci:v000011ABd00005081* ID_MODEL_FROM_DATABASE=MV88SX5081 8-port SATA I PCI-X Controller pci:v000011ABd00005181* ID_MODEL_FROM_DATABASE=88f5181 [Orion-1] ARM SoC pci:v000011ABd00005182* ID_MODEL_FROM_DATABASE=88f5182 [Orion-NAS] ARM SoC pci:v000011ABd00005281* ID_MODEL_FROM_DATABASE=88f5281 [Orion-2] ARM SoC pci:v000011ABd00006041* ID_MODEL_FROM_DATABASE=MV88SX6041 4-port SATA II PCI-X Controller pci:v000011ABd00006042* ID_MODEL_FROM_DATABASE=88SX6042 PCI-X 4-Port SATA-II pci:v000011ABd00006081* ID_MODEL_FROM_DATABASE=MV88SX6081 8-port SATA II PCI-X Controller pci:v000011ABd00006101* ID_MODEL_FROM_DATABASE=88SE6101/6102 single-port PATA133 interface pci:v000011ABd00006101sv00001043sd000082E0* ID_MODEL_FROM_DATABASE=88SE6101/6102 single-port PATA133 interface (P5K PRO Motherboard) pci:v000011ABd00006111* ID_MODEL_FROM_DATABASE=88SE6111 1-port PATA133(IDE) and 1-port SATA II Controllers pci:v000011ABd00006121* ID_MODEL_FROM_DATABASE=88SE6121 SATA II / PATA Controller pci:v000011ABd00006141* ID_MODEL_FROM_DATABASE=88SE614x SATA II PCI-E controller pci:v000011ABd00006145* ID_MODEL_FROM_DATABASE=88SE6145 SATA II PCI-E controller pci:v000011ABd00006180* ID_MODEL_FROM_DATABASE=88F6180 [Kirkwood] ARM SoC pci:v000011ABd00006192* ID_MODEL_FROM_DATABASE=88F6190/6192 [Kirkwood] ARM SoC pci:v000011ABd00006281* ID_MODEL_FROM_DATABASE=88F6281 [Kirkwood] ARM SoC pci:v000011ABd00006381* ID_MODEL_FROM_DATABASE=MV78xx0 [Discovery Innovation] ARM SoC pci:v000011ABd00006440* ID_MODEL_FROM_DATABASE=88SE6440 SAS/SATA PCIe controller pci:v000011ABd00006450* ID_MODEL_FROM_DATABASE=64560 System Controller pci:v000011ABd00006460* ID_MODEL_FROM_DATABASE=MV64360/64361/64362 System Controller pci:v000011ABd00006480* ID_MODEL_FROM_DATABASE=MV64460/64461/64462 System Controller pci:v000011ABd00006480sv00001775sd0000C200* ID_MODEL_FROM_DATABASE=MV64460/64461/64462 System Controller (C2K CompactPCI single board computer) pci:v000011ABd00006485* ID_MODEL_FROM_DATABASE=MV64460/64461/64462 System Controller, Revision B pci:v000011ABd00007042* ID_MODEL_FROM_DATABASE=88SX7042 PCI-e 4-port SATA-II pci:v000011ABd00007042sv000016B8sd0000434B* ID_MODEL_FROM_DATABASE=88SX7042 PCI-e 4-port SATA-II (Tempo SATA E4P) pci:v000011ABd00007810* ID_MODEL_FROM_DATABASE=MV78100 [Discovery Innovation] ARM SoC pci:v000011ABd00007820* ID_MODEL_FROM_DATABASE=MV78200 [Discovery Innovation] ARM SoC pci:v000011ABd00007823* ID_MODEL_FROM_DATABASE=MV78230 [Armada XP] ARM SoC pci:v000011ABd00007846* ID_MODEL_FROM_DATABASE=88F6820 [Armada 385] ARM SoC pci:v000011ABd0000F003* ID_MODEL_FROM_DATABASE=GT-64010 Primary Image Piranha Image Generator pci:v000011AC* ID_VENDOR_FROM_DATABASE=Canon Information Systems Research Aust. pci:v000011AD* ID_VENDOR_FROM_DATABASE=Lite-On Communications Inc pci:v000011ADd00000002* ID_MODEL_FROM_DATABASE=LNE100TX pci:v000011ADd00000002sv000011ADsd00000002* ID_MODEL_FROM_DATABASE=LNE100TX pci:v000011ADd00000002sv000011ADsd00000003* ID_MODEL_FROM_DATABASE=LNE100TX pci:v000011ADd00000002sv000011ADsd0000F003* ID_MODEL_FROM_DATABASE=LNE100TX pci:v000011ADd00000002sv000011ADsd0000FFFF* ID_MODEL_FROM_DATABASE=LNE100TX pci:v000011ADd00000002sv00001385sd0000F004* ID_MODEL_FROM_DATABASE=LNE100TX (FA310TX) pci:v000011ADd00000002sv00002646sd0000F002* ID_MODEL_FROM_DATABASE=LNE100TX (KNE110TX EtheRx Fast Ethernet) pci:v000011ADd0000C115* ID_MODEL_FROM_DATABASE=LNE100TX [Linksys EtherFast 10/100] pci:v000011ADd0000C115sv000011ADsd0000C001* ID_MODEL_FROM_DATABASE=LNE100TX [Linksys EtherFast 10/100] (LNE100TX [ver 2.0]) pci:v000011ADd0000C115sv00002646sd0000000B* ID_MODEL_FROM_DATABASE=LNE100TX [Linksys EtherFast 10/100] (KNE111TX) pci:v000011AE* ID_VENDOR_FROM_DATABASE=Aztech System Ltd pci:v000011AF* ID_VENDOR_FROM_DATABASE=Avid Technology Inc. pci:v000011AFd00000001* ID_MODEL_FROM_DATABASE=Cinema pci:v000011AFd0000EE40* ID_MODEL_FROM_DATABASE=Digidesign Audiomedia III pci:v000011B0* ID_VENDOR_FROM_DATABASE=V3 Semiconductor Inc. pci:v000011B0d00000002* ID_MODEL_FROM_DATABASE=V300PSC pci:v000011B0d00000292* ID_MODEL_FROM_DATABASE=V292PBC [Am29030/40 Bridge] pci:v000011B0d00000960* ID_MODEL_FROM_DATABASE=V96xPBC pci:v000011B0d0000880A* ID_MODEL_FROM_DATABASE=Deltacast Delta-HD-22 pci:v000011B0d0000C960* ID_MODEL_FROM_DATABASE=V96DPC pci:v000011B1* ID_VENDOR_FROM_DATABASE=Apricot Computers pci:v000011B2* ID_VENDOR_FROM_DATABASE=Eastman Kodak pci:v000011B3* ID_VENDOR_FROM_DATABASE=Barr Systems Inc. pci:v000011B4* ID_VENDOR_FROM_DATABASE=Leitch Technology International pci:v000011B5* ID_VENDOR_FROM_DATABASE=Radstone Technology Plc pci:v000011B6* ID_VENDOR_FROM_DATABASE=United Video Corp pci:v000011B7* ID_VENDOR_FROM_DATABASE=Motorola pci:v000011B8* ID_VENDOR_FROM_DATABASE=XPoint Technologies, Inc pci:v000011B8d00000001* ID_MODEL_FROM_DATABASE=Quad PeerMaster pci:v000011B9* ID_VENDOR_FROM_DATABASE=Pathlight Technology Inc. pci:v000011B9d0000C0ED* ID_MODEL_FROM_DATABASE=SSA Controller pci:v000011BA* ID_VENDOR_FROM_DATABASE=Videotron Corp pci:v000011BB* ID_VENDOR_FROM_DATABASE=Pyramid Technology pci:v000011BC* ID_VENDOR_FROM_DATABASE=Network Peripherals Inc pci:v000011BCd00000001* ID_MODEL_FROM_DATABASE=NP-PCI pci:v000011BD* ID_VENDOR_FROM_DATABASE=Pinnacle Systems Inc. pci:v000011BDd0000002E* ID_MODEL_FROM_DATABASE=PCTV 40i pci:v000011BDd00000040* ID_MODEL_FROM_DATABASE=Royal TS Function 1 pci:v000011BDd00000040sv000011BDsd00000044* ID_MODEL_FROM_DATABASE=Royal TS Function 1 (PCTV 2000i Dual DVB-T Pro PCI Tuner 1) pci:v000011BDd00000040sv000011BDsd00000045* ID_MODEL_FROM_DATABASE=Royal TS Function 1 (PCTV Dual Sat Pro PCI 4000i Tuner 1) pci:v000011BDd00000041* ID_MODEL_FROM_DATABASE=RoyalTS Function 2 pci:v000011BDd00000041sv000011BDsd00000044* ID_MODEL_FROM_DATABASE=RoyalTS Function 2 (PCTV 2000i Dual DVB-T Pro PCI Tuner 2) pci:v000011BDd00000041sv000011BDsd00000045* ID_MODEL_FROM_DATABASE=RoyalTS Function 2 (PCTV Dual Sat Pro PCI 4000i Tuner 2) pci:v000011BDd00000042* ID_MODEL_FROM_DATABASE=Royal TS Function 3 pci:v000011BDd00000042sv000011BDsd00000044* ID_MODEL_FROM_DATABASE=Royal TS Function 3 (PCTV 2000i Dual DVB-T Pro PCI Common) pci:v000011BDd00000042sv000011BDsd00000045* ID_MODEL_FROM_DATABASE=Royal TS Function 3 (PCTV Dual Sat Pro PCI 4000i Common) pci:v000011BDd00000051* ID_MODEL_FROM_DATABASE=PCTV HD 800i pci:v000011BDd0000BEDE* ID_MODEL_FROM_DATABASE=AV/DV Studio Capture Card pci:v000011BE* ID_VENDOR_FROM_DATABASE=International Microcircuits Inc pci:v000011BF* ID_VENDOR_FROM_DATABASE=Astrodesign, Inc. pci:v000011C0* ID_VENDOR_FROM_DATABASE=Hewlett Packard pci:v000011C1* ID_VENDOR_FROM_DATABASE=LSI Corporation pci:v000011C1d00000440* ID_MODEL_FROM_DATABASE=56k WinModem pci:v000011C1d00000440sv00001033sd00008015* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) pci:v000011C1d00000440sv00001033sd00008047* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) pci:v000011C1d00000440sv00001033sd0000804F* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) pci:v000011C1d00000440sv000010CFsd0000102C* ID_MODEL_FROM_DATABASE=56k WinModem (LB LT Modem V.90 56k) pci:v000011C1d00000440sv000010CFsd0000104A* ID_MODEL_FROM_DATABASE=56k WinModem (BIBLO LT Modem 56k) pci:v000011C1d00000440sv000010CFsd0000105F* ID_MODEL_FROM_DATABASE=56k WinModem (LB2 LT Modem V.90 56k) pci:v000011C1d00000440sv00001179sd00000001* ID_MODEL_FROM_DATABASE=56k WinModem (Internal V.90 Modem) pci:v000011C1d00000440sv000011C1sd00000440* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) pci:v000011C1d00000440sv0000122Dsd00004101* ID_MODEL_FROM_DATABASE=56k WinModem (MDP7800-U Modem) pci:v000011C1d00000440sv0000122Dsd00004102* ID_MODEL_FROM_DATABASE=56k WinModem (MDP7800SP-U Modem) pci:v000011C1d00000440sv000013E0sd00000040* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) pci:v000011C1d00000440sv000013E0sd00000440* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) pci:v000011C1d00000440sv000013E0sd00000441* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) pci:v000011C1d00000440sv000013E0sd00000450* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) pci:v000011C1d00000440sv000013E0sd0000F100* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) pci:v000011C1d00000440sv000013E0sd0000F101* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) pci:v000011C1d00000440sv0000144Dsd00002101* ID_MODEL_FROM_DATABASE=56k WinModem (LT56PV Modem) pci:v000011C1d00000440sv0000149Fsd00000440* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) pci:v000011C1d00000441* ID_MODEL_FROM_DATABASE=56k WinModem pci:v000011C1d00000441sv00001033sd0000804D* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) pci:v000011C1d00000441sv00001033sd00008065* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) pci:v000011C1d00000441sv00001092sd00000440* ID_MODEL_FROM_DATABASE=56k WinModem (Supra 56i) pci:v000011C1d00000441sv00001179sd00000001* ID_MODEL_FROM_DATABASE=56k WinModem (Internal V.90 Modem) pci:v000011C1d00000441sv000011C1sd00000440* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) pci:v000011C1d00000441sv000011C1sd00000441* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) pci:v000011C1d00000441sv0000122Dsd00004100* ID_MODEL_FROM_DATABASE=56k WinModem (MDP7800-U Modem) pci:v000011C1d00000441sv000013E0sd00000040* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) pci:v000011C1d00000441sv000013E0sd00000100* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) pci:v000011C1d00000441sv000013E0sd00000410* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) pci:v000011C1d00000441sv000013E0sd00000420* ID_MODEL_FROM_DATABASE=56k WinModem (TelePath Internet 56k WinModem) pci:v000011C1d00000441sv000013E0sd00000440* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) pci:v000011C1d00000441sv000013E0sd00000443* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) pci:v000011C1d00000441sv000013E0sd0000F102* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) pci:v000011C1d00000441sv00001416sd00009804* ID_MODEL_FROM_DATABASE=56k WinModem (CommWave 56k Modem) pci:v000011C1d00000441sv0000141Dsd00000440* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) pci:v000011C1d00000441sv0000144Fsd00000441* ID_MODEL_FROM_DATABASE=56k WinModem (Lucent 56k V.90 DF Modem) pci:v000011C1d00000441sv0000144Fsd00000449* ID_MODEL_FROM_DATABASE=56k WinModem (Lucent 56k V.90 DF Modem) pci:v000011C1d00000441sv0000144Fsd0000110D* ID_MODEL_FROM_DATABASE=56k WinModem (Lucent Win Modem) pci:v000011C1d00000441sv00001468sd00000441* ID_MODEL_FROM_DATABASE=56k WinModem (Presario 56k V.90 DF Modem) pci:v000011C1d00000441sv00001668sd00000440* ID_MODEL_FROM_DATABASE=56k WinModem (Lucent Win Modem) pci:v000011C1d00000442* ID_MODEL_FROM_DATABASE=56k WinModem pci:v000011C1d00000442sv000011C1sd00000440* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) pci:v000011C1d00000442sv000011C1sd00000442* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) pci:v000011C1d00000442sv000013E0sd00000412* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) pci:v000011C1d00000442sv000013E0sd00000442* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) pci:v000011C1d00000442sv000013FCsd00002471* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) pci:v000011C1d00000442sv0000144Dsd00002104* ID_MODEL_FROM_DATABASE=56k WinModem (LT56PT Modem) pci:v000011C1d00000442sv0000144Fsd00001104* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) pci:v000011C1d00000442sv0000149Fsd00000440* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) pci:v000011C1d00000442sv00001668sd00000440* ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) pci:v000011C1d00000443* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000444* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000445* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000445sv00008086sd00002203* ID_MODEL_FROM_DATABASE=LT WinModem (PRO/100+ MiniPCI (probably an Ambit U98.003.C.00 combo card)) pci:v000011C1d00000445sv00008086sd00002204* ID_MODEL_FROM_DATABASE=LT WinModem (PRO/100+ MiniPCI on Armada E500) pci:v000011C1d00000446* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000447* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000448* ID_MODEL_FROM_DATABASE=WinModem 56k pci:v000011C1d00000448sv00001014sd00000131* ID_MODEL_FROM_DATABASE=WinModem 56k (Lucent Win Modem) pci:v000011C1d00000448sv00001033sd00008066* ID_MODEL_FROM_DATABASE=WinModem 56k (LT WinModem 56k Data+Fax+Voice+Dsvd) pci:v000011C1d00000448sv000013E0sd00000030* ID_MODEL_FROM_DATABASE=WinModem 56k (56k Voice Modem) pci:v000011C1d00000448sv000013E0sd00000040* ID_MODEL_FROM_DATABASE=WinModem 56k (LT WinModem 56k Data+Fax+Voice+Dsvd) pci:v000011C1d00000448sv00001668sd00002400* ID_MODEL_FROM_DATABASE=WinModem 56k (LT WinModem 56k (MiniPCI Ethernet+Modem)) pci:v000011C1d00000449* ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k pci:v000011C1d00000449sv00000E11sd0000B14D* ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (56k V.90 Modem) pci:v000011C1d00000449sv00001014sd0000018C* ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (ThinkPad 600X) pci:v000011C1d00000449sv000013E0sd00000020* ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (LT WinModem 56k Data+Fax) pci:v000011C1d00000449sv000013E0sd00000041* ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (TelePath Internet 56k WinModem) pci:v000011C1d00000449sv00001436sd00000440* ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (Lucent Win Modem) pci:v000011C1d00000449sv0000144Fsd00000449* ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (Lucent 56k V.90 DFi Modem) pci:v000011C1d00000449sv00001468sd00000410* ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (IBM ThinkPad T23) pci:v000011C1d00000449sv00001468sd00000440* ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (Lucent Win Modem) pci:v000011C1d00000449sv00001468sd00000449* ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (Presario 56k V.90 DFi Modem) pci:v000011C1d0000044A* ID_MODEL_FROM_DATABASE=F-1156IV WinModem (V90, 56KFlex) pci:v000011C1d0000044Asv000010CFsd00001072* ID_MODEL_FROM_DATABASE=F-1156IV WinModem (V90, 56KFlex) (LB Global LT Modem) pci:v000011C1d0000044Asv000013E0sd00000012* ID_MODEL_FROM_DATABASE=F-1156IV WinModem (V90, 56KFlex) (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) pci:v000011C1d0000044Asv000013E0sd00000042* ID_MODEL_FROM_DATABASE=F-1156IV WinModem (V90, 56KFlex) (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) pci:v000011C1d0000044Asv0000144Fsd00001005* ID_MODEL_FROM_DATABASE=F-1156IV WinModem (V90, 56KFlex) (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) pci:v000011C1d0000044B* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d0000044C* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d0000044D* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d0000044E* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d0000044F* ID_MODEL_FROM_DATABASE=V90 WildWire Modem pci:v000011C1d00000450* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000450sv00001033sd000080A8* ID_MODEL_FROM_DATABASE=LT WinModem (Versa Note Vxi) pci:v000011C1d00000450sv0000144Fsd00004005* ID_MODEL_FROM_DATABASE=LT WinModem (Magnia SG20) pci:v000011C1d00000450sv00001468sd00000450* ID_MODEL_FROM_DATABASE=LT WinModem (Evo N600c) pci:v000011C1d00000451* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000452* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000453* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000454* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000455* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000456* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000457* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000458* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000459* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d0000045A* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d0000045C* ID_MODEL_FROM_DATABASE=LT WinModem pci:v000011C1d00000461* ID_MODEL_FROM_DATABASE=V90 WildWire Modem pci:v000011C1d00000462* ID_MODEL_FROM_DATABASE=V90 WildWire Modem pci:v000011C1d00000480* ID_MODEL_FROM_DATABASE=Venus Modem (V90, 56KFlex) pci:v000011C1d0000048C* ID_MODEL_FROM_DATABASE=V.92 56K WinModem pci:v000011C1d0000048F* ID_MODEL_FROM_DATABASE=V.92 56k WinModem pci:v000011C1d00000620* ID_MODEL_FROM_DATABASE=Lucent V.92 Data/Fax Modem pci:v000011C1d00002600* ID_MODEL_FROM_DATABASE=StarPro26XX family (SP2601, SP2603, SP2612) DSP pci:v000011C1d00005400* ID_MODEL_FROM_DATABASE=OR3TP12 FPSC pci:v000011C1d00005656* ID_MODEL_FROM_DATABASE=Venus Modem pci:v000011C1d00005801* ID_MODEL_FROM_DATABASE=USB pci:v000011C1d00005802* ID_MODEL_FROM_DATABASE=USS-312 USB Controller pci:v000011C1d00005803* ID_MODEL_FROM_DATABASE=USS-344S USB Controller pci:v000011C1d00005811* ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller pci:v000011C1d00005811sv0000103Csd00002A34* ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (Pavilion a1677c) pci:v000011C1d00005811sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (Asus IPIBL-LB Motherboard) pci:v000011C1d00005811sv0000103Csd00002A9E* ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (Pavilion p6310f) pci:v000011C1d00005811sv00001043sd00008294* ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (LSI FW322/323 IEEE 1394a FireWire Controller) pci:v000011C1d00005811sv00008086sd0000524C* ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (D865PERL mainboard) pci:v000011C1d00005811sv0000DEADsd00000800* ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (FireWire Host Bus Adapter) pci:v000011C1d00005901* ID_MODEL_FROM_DATABASE=FW643 [TrueFire] PCIe 1394b Controller pci:v000011C1d00005901sv000011C1sd00005900* ID_MODEL_FROM_DATABASE=FW643 [TrueFire] PCIe 1394b Controller pci:v000011C1d00005901sv00001443sd00000643* ID_MODEL_FROM_DATABASE=FW643 [TrueFire] PCIe 1394b Controller (FireBoard800-e V.2) pci:v000011C1d00005901sv00001546sd00000643* ID_MODEL_FROM_DATABASE=FW643 [TrueFire] PCIe 1394b Controller (FWB-PCIE1X2x) pci:v000011C1d00005903* ID_MODEL_FROM_DATABASE=FW533 [TrueFire] PCIe 1394a Controller pci:v000011C1d00008110* ID_MODEL_FROM_DATABASE=T8110 H.100/H.110 TDM switch pci:v000011C1d00008110sv000012D9sd0000000C* ID_MODEL_FROM_DATABASE=T8110 H.100/H.110 TDM switch (E1/T1 PMXc cPCI carrier card) pci:v000011C1d0000AB10* ID_MODEL_FROM_DATABASE=WL60010 Wireless LAN MAC pci:v000011C1d0000AB11* ID_MODEL_FROM_DATABASE=WL60040 Multimode Wireles LAN MAC pci:v000011C1d0000AB11sv000011C1sd0000AB12* ID_MODEL_FROM_DATABASE=WL60040 Multimode Wireles LAN MAC (WaveLAN 11abg Cardbus card (Model 1102)) pci:v000011C1d0000AB11sv000011C1sd0000AB13* ID_MODEL_FROM_DATABASE=WL60040 Multimode Wireles LAN MAC (WaveLAN 11abg MiniPCI card (Model 0512)) pci:v000011C1d0000AB11sv000011C1sd0000AB15* ID_MODEL_FROM_DATABASE=WL60040 Multimode Wireles LAN MAC (WaveLAN 11abg Cardbus card (Model 1106)) pci:v000011C1d0000AB11sv000011C1sd0000AB16* ID_MODEL_FROM_DATABASE=WL60040 Multimode Wireles LAN MAC (WaveLAN 11abg MiniPCI card (Model 0516)) pci:v000011C1d0000AB20* ID_MODEL_FROM_DATABASE=ORiNOCO PCI Adapter pci:v000011C1d0000AB21* ID_MODEL_FROM_DATABASE=Agere Wireless PCI Adapter pci:v000011C1d0000AB30* ID_MODEL_FROM_DATABASE=Hermes2 Mini-PCI WaveLAN a/b/g pci:v000011C1d0000AB30sv000014CDsd00002012* ID_MODEL_FROM_DATABASE=Hermes2 Mini-PCI WaveLAN a/b/g pci:v000011C1d0000ED00* ID_MODEL_FROM_DATABASE=ET-131x PCI-E Ethernet Controller pci:v000011C1d0000ED01* ID_MODEL_FROM_DATABASE=ET-131x PCI-E Ethernet Controller pci:v000011C2* ID_VENDOR_FROM_DATABASE=Sand Microelectronics pci:v000011C3* ID_VENDOR_FROM_DATABASE=NEC Corporation pci:v000011C4* ID_VENDOR_FROM_DATABASE=Document Technologies, Inc pci:v000011C5* ID_VENDOR_FROM_DATABASE=Shiva Corporation pci:v000011C6* ID_VENDOR_FROM_DATABASE=Dainippon Screen Mfg. Co. Ltd pci:v000011C7* ID_VENDOR_FROM_DATABASE=D.C.M. Data Systems pci:v000011C8* ID_VENDOR_FROM_DATABASE=Dolphin Interconnect Solutions AS pci:v000011C8d00000658* ID_MODEL_FROM_DATABASE=PSB32 SCI-Adapter D31x pci:v000011C8d0000D665* ID_MODEL_FROM_DATABASE=PSB64 SCI-Adapter D32x pci:v000011C8d0000D667* ID_MODEL_FROM_DATABASE=PSB66 SCI-Adapter D33x pci:v000011C9* ID_VENDOR_FROM_DATABASE=Magma pci:v000011C9d00000010* ID_MODEL_FROM_DATABASE=16-line serial port w/- DMA pci:v000011C9d00000011* ID_MODEL_FROM_DATABASE=4-line serial port w/- DMA pci:v000011CA* ID_VENDOR_FROM_DATABASE=LSI Systems, Inc pci:v000011CB* ID_VENDOR_FROM_DATABASE=Specialix Research Ltd. pci:v000011CBd00002000* ID_MODEL_FROM_DATABASE=PCI_9050 pci:v000011CBd00002000sv000011CBsd00000200* ID_MODEL_FROM_DATABASE=PCI_9050 (SX) pci:v000011CBd00002000sv000011CBsd0000B008* ID_MODEL_FROM_DATABASE=PCI_9050 (I/O8+) pci:v000011CBd00004000* ID_MODEL_FROM_DATABASE=SUPI_1 pci:v000011CBd00008000* ID_MODEL_FROM_DATABASE=T225 pci:v000011CC* ID_VENDOR_FROM_DATABASE=Michels & Kleberhoff Computer GmbH pci:v000011CD* ID_VENDOR_FROM_DATABASE=HAL Computer Systems, Inc. pci:v000011CE* ID_VENDOR_FROM_DATABASE=Netaccess pci:v000011CF* ID_VENDOR_FROM_DATABASE=Pioneer Electronic Corporation pci:v000011D0* ID_VENDOR_FROM_DATABASE=Lockheed Martin Federal Systems-Manassas pci:v000011D1* ID_VENDOR_FROM_DATABASE=Auravision pci:v000011D1d000001F7* ID_MODEL_FROM_DATABASE=VxP524 pci:v000011D1d000001F9* ID_MODEL_FROM_DATABASE=VxP951 pci:v000011D2* ID_VENDOR_FROM_DATABASE=Intercom Inc. pci:v000011D3* ID_VENDOR_FROM_DATABASE=Trancell Systems Inc pci:v000011D4* ID_VENDOR_FROM_DATABASE=Analog Devices pci:v000011D4d00001535* ID_MODEL_FROM_DATABASE=Blackfin BF535 processor pci:v000011D4d00001805* ID_MODEL_FROM_DATABASE=SM56 PCI modem pci:v000011D5* ID_VENDOR_FROM_DATABASE=Ikon Corporation pci:v000011D5d00000115* ID_MODEL_FROM_DATABASE=10115 pci:v000011D5d00000117* ID_MODEL_FROM_DATABASE=10117 pci:v000011D6* ID_VENDOR_FROM_DATABASE=Tekelec Telecom pci:v000011D7* ID_VENDOR_FROM_DATABASE=Trenton Technology, Inc. pci:v000011D8* ID_VENDOR_FROM_DATABASE=Image Technologies Development pci:v000011D9* ID_VENDOR_FROM_DATABASE=TEC Corporation pci:v000011DA* ID_VENDOR_FROM_DATABASE=Novell pci:v000011DB* ID_VENDOR_FROM_DATABASE=Sega Enterprises Ltd pci:v000011DC* ID_VENDOR_FROM_DATABASE=Questra Corporation pci:v000011DD* ID_VENDOR_FROM_DATABASE=Crosfield Electronics Limited pci:v000011DE* ID_VENDOR_FROM_DATABASE=Zoran Corporation pci:v000011DEd00006017* ID_MODEL_FROM_DATABASE=miroVIDEO DC30 pci:v000011DEd00006057* ID_MODEL_FROM_DATABASE=ZR36057PQC Video cutting chipset pci:v000011DEd00006057sv00001031sd00007EFE* ID_MODEL_FROM_DATABASE=ZR36057PQC Video cutting chipset (DC10 Plus) pci:v000011DEd00006057sv00001031sd0000FC00* ID_MODEL_FROM_DATABASE=ZR36057PQC Video cutting chipset (MiroVIDEO DC50, Motion JPEG Capture/CODEC Board) pci:v000011DEd00006057sv000012F8sd00008A02* ID_MODEL_FROM_DATABASE=ZR36057PQC Video cutting chipset (Tekram Video Kit) pci:v000011DEd00006057sv000013CAsd00004231* ID_MODEL_FROM_DATABASE=ZR36057PQC Video cutting chipset (JPEG/TV Card) pci:v000011DEd00006120* ID_MODEL_FROM_DATABASE=ZR36120 pci:v000011DEd00006120sv00001328sd0000F001* ID_MODEL_FROM_DATABASE=ZR36120 (Cinemaster C DVD Decoder) pci:v000011DEd00006120sv000013C2sd00000000* ID_MODEL_FROM_DATABASE=ZR36120 (MediaFocus Satellite TV Card) pci:v000011DEd00006120sv00001DE1sd00009FFF* ID_MODEL_FROM_DATABASE=ZR36120 (Video Kit C210) pci:v000011DF* ID_VENDOR_FROM_DATABASE=New Wave PDG pci:v000011E0* ID_VENDOR_FROM_DATABASE=Cray Communications A/S pci:v000011E1* ID_VENDOR_FROM_DATABASE=GEC Plessey Semi Inc. pci:v000011E2* ID_VENDOR_FROM_DATABASE=Samsung Information Systems America pci:v000011E3* ID_VENDOR_FROM_DATABASE=Quicklogic Corporation pci:v000011E3d00000001* ID_MODEL_FROM_DATABASE=COM-ON-AIR Dosch&Amand DECT pci:v000011E3d00000560* ID_MODEL_FROM_DATABASE=QL5064 Companion Design Demo Board pci:v000011E3d00005030* ID_MODEL_FROM_DATABASE=PC Watchdog pci:v000011E3d00008417* ID_MODEL_FROM_DATABASE=QL5064 [QuickPCI] PCI v2.2 bridge for SMT417 Dual TMS320C6416T PMC Module pci:v000011E4* ID_VENDOR_FROM_DATABASE=Second Wave Inc pci:v000011E5* ID_VENDOR_FROM_DATABASE=IIX Consulting pci:v000011E6* ID_VENDOR_FROM_DATABASE=Mitsui-Zosen System Research pci:v000011E7* ID_VENDOR_FROM_DATABASE=Toshiba America, Elec. Company pci:v000011E8* ID_VENDOR_FROM_DATABASE=Digital Processing Systems Inc. pci:v000011E9* ID_VENDOR_FROM_DATABASE=Highwater Designs Ltd. pci:v000011EA* ID_VENDOR_FROM_DATABASE=Elsag Bailey pci:v000011EB* ID_VENDOR_FROM_DATABASE=Formation Inc. pci:v000011EC* ID_VENDOR_FROM_DATABASE=Coreco Inc pci:v000011ECd0000000D* ID_MODEL_FROM_DATABASE=Oculus-F/64P pci:v000011ECd00001800* ID_MODEL_FROM_DATABASE=Cobra/C6 pci:v000011ED* ID_VENDOR_FROM_DATABASE=Mediamatics pci:v000011EE* ID_VENDOR_FROM_DATABASE=Dome Imaging Systems Inc pci:v000011EF* ID_VENDOR_FROM_DATABASE=Nicolet Technologies B.V. pci:v000011F0* ID_VENDOR_FROM_DATABASE=Compu-Shack pci:v000011F0d00004231* ID_MODEL_FROM_DATABASE=FDDI pci:v000011F0d00004232* ID_MODEL_FROM_DATABASE=FASTline UTP Quattro pci:v000011F0d00004233* ID_MODEL_FROM_DATABASE=FASTline FO pci:v000011F0d00004234* ID_MODEL_FROM_DATABASE=FASTline UTP pci:v000011F0d00004235* ID_MODEL_FROM_DATABASE=FASTline-II UTP pci:v000011F0d00004236* ID_MODEL_FROM_DATABASE=FASTline-II FO pci:v000011F0d00004731* ID_MODEL_FROM_DATABASE=GIGAline pci:v000011F1* ID_VENDOR_FROM_DATABASE=Symbios Logic Inc pci:v000011F2* ID_VENDOR_FROM_DATABASE=Picture Tel Japan K.K. pci:v000011F3* ID_VENDOR_FROM_DATABASE=Keithley Metrabyte pci:v000011F3d00000011* ID_MODEL_FROM_DATABASE=KPCI-PIO24 pci:v000011F4* ID_VENDOR_FROM_DATABASE=Kinetic Systems Corporation pci:v000011F4d00002915* ID_MODEL_FROM_DATABASE=CAMAC controller pci:v000011F5* ID_VENDOR_FROM_DATABASE=Computing Devices International pci:v000011F6* ID_VENDOR_FROM_DATABASE=Compex pci:v000011F6d00000112* ID_MODEL_FROM_DATABASE=ENet100VG4 pci:v000011F6d00000113* ID_MODEL_FROM_DATABASE=FreedomLine 100 pci:v000011F6d00001401* ID_MODEL_FROM_DATABASE=ReadyLink 2000 pci:v000011F6d00002011* ID_MODEL_FROM_DATABASE=RL100-ATX 10/100 pci:v000011F6d00002011sv000011F6sd00002011* ID_MODEL_FROM_DATABASE=RL100-ATX 10/100 (RL100-ATX) pci:v000011F6d00002201* ID_MODEL_FROM_DATABASE=ReadyLink 100TX (Winbond W89C840) pci:v000011F6d00002201sv000011F6sd00002011* ID_MODEL_FROM_DATABASE=ReadyLink 100TX (Winbond W89C840) (ReadyLink 100TX) pci:v000011F6d00009881* ID_MODEL_FROM_DATABASE=RL100TX Fast Ethernet pci:v000011F7* ID_VENDOR_FROM_DATABASE=Scientific Atlanta pci:v000011F8* ID_VENDOR_FROM_DATABASE=PMC-Sierra Inc. pci:v000011F8d00005220* ID_MODEL_FROM_DATABASE=BR522x [PMC-Sierra maxRAID SAS Controller] pci:v000011F8d00007364* ID_MODEL_FROM_DATABASE=PM7364 [FREEDM - 32 Frame Engine & Datalink Mgr] pci:v000011F8d00007375* ID_MODEL_FROM_DATABASE=PM7375 [LASAR-155 ATM SAR] pci:v000011F8d00007384* ID_MODEL_FROM_DATABASE=PM7384 [FREEDM - 84P672 Frm Engine & Datalink Mgr] pci:v000011F8d00008000* ID_MODEL_FROM_DATABASE=PM8000 [SPC - SAS Protocol Controller] pci:v000011F8d00008032* ID_MODEL_FROM_DATABASE=ATTO Celerity FC8xEN pci:v000011F8d00008032sv0000117Csd0000003B* ID_MODEL_FROM_DATABASE=ATTO Celerity FC8xEN (Celerity FC-82EN Fibre Channel Adapter) pci:v000011F8d00008032sv0000117Csd0000003C* ID_MODEL_FROM_DATABASE=ATTO Celerity FC8xEN (Celerity FC-84EN Fibre Channel Adapter) pci:v000011F9* ID_VENDOR_FROM_DATABASE=I-Cube Inc pci:v000011FA* ID_VENDOR_FROM_DATABASE=Kasan Electronics Company, Ltd. pci:v000011FB* ID_VENDOR_FROM_DATABASE=Datel Inc pci:v000011FC* ID_VENDOR_FROM_DATABASE=Silicon Magic pci:v000011FD* ID_VENDOR_FROM_DATABASE=High Street Consultants pci:v000011FE* ID_VENDOR_FROM_DATABASE=Comtrol Corporation pci:v000011FEd00000001* ID_MODEL_FROM_DATABASE=RocketPort 32 port w/external I/F pci:v000011FEd00000002* ID_MODEL_FROM_DATABASE=RocketPort 8 port w/external I/F pci:v000011FEd00000003* ID_MODEL_FROM_DATABASE=RocketPort 16 port w/external I/F pci:v000011FEd00000004* ID_MODEL_FROM_DATABASE=RocketPort 4 port w/quad cable pci:v000011FEd00000005* ID_MODEL_FROM_DATABASE=RocketPort 8 port w/octa cable pci:v000011FEd00000006* ID_MODEL_FROM_DATABASE=RocketPort 8 port w/RJ11 connectors pci:v000011FEd00000007* ID_MODEL_FROM_DATABASE=RocketPort 4 port w/RJ11 connectors pci:v000011FEd00000008* ID_MODEL_FROM_DATABASE=RocketPort 8 port w/ DB78 SNI (Siemens) connector pci:v000011FEd00000009* ID_MODEL_FROM_DATABASE=RocketPort 16 port w/ DB78 SNI (Siemens) connector pci:v000011FEd0000000A* ID_MODEL_FROM_DATABASE=RocketPort Plus 4 port pci:v000011FEd0000000B* ID_MODEL_FROM_DATABASE=RocketPort Plus 8 port pci:v000011FEd0000000C* ID_MODEL_FROM_DATABASE=RocketModem 6 port pci:v000011FEd0000000D* ID_MODEL_FROM_DATABASE=RocketModem 4-port pci:v000011FEd0000000E* ID_MODEL_FROM_DATABASE=RocketPort Plus 2 port RS232 pci:v000011FEd0000000F* ID_MODEL_FROM_DATABASE=RocketPort Plus 2 port RS422 pci:v000011FEd00000040* ID_MODEL_FROM_DATABASE=RocketPort Infinity Octa, 8port, RJ45 pci:v000011FEd00000041* ID_MODEL_FROM_DATABASE=RocketPort Infinity 32port, External Interface pci:v000011FEd00000042* ID_MODEL_FROM_DATABASE=RocketPort Infinity 8port, External Interface pci:v000011FEd00000043* ID_MODEL_FROM_DATABASE=RocketPort Infinity 16port, External Interface pci:v000011FEd00000044* ID_MODEL_FROM_DATABASE=RocketPort Infinity Quad, 4port, DB pci:v000011FEd00000045* ID_MODEL_FROM_DATABASE=RocketPort Infinity Octa, 8port, DB pci:v000011FEd00000047* ID_MODEL_FROM_DATABASE=RocketPort Infinity 4port, RJ45 pci:v000011FEd0000004F* ID_MODEL_FROM_DATABASE=RocketPort Infinity 2port, SMPTE pci:v000011FEd00000052* ID_MODEL_FROM_DATABASE=RocketPort Infinity Octa, 8port, SMPTE pci:v000011FEd00000801* ID_MODEL_FROM_DATABASE=RocketPort UPCI 32 port w/external I/F pci:v000011FEd00000802* ID_MODEL_FROM_DATABASE=RocketPort UPCI 8 port w/external I/F pci:v000011FEd00000803* ID_MODEL_FROM_DATABASE=RocketPort UPCI 16 port w/external I/F pci:v000011FEd00000805* ID_MODEL_FROM_DATABASE=RocketPort UPCI 8 port w/octa cable pci:v000011FEd0000080C* ID_MODEL_FROM_DATABASE=RocketModem III 8 port pci:v000011FEd0000080D* ID_MODEL_FROM_DATABASE=RocketModem III 4 port pci:v000011FEd00000810* ID_MODEL_FROM_DATABASE=RocketPort UPCI Plus 4 port RS232 pci:v000011FEd00000811* ID_MODEL_FROM_DATABASE=RocketPort UPCI Plus 8 port RS232 pci:v000011FEd00000812* ID_MODEL_FROM_DATABASE=RocketPort UPCI Plus 8 port RS422 pci:v000011FEd00000903* ID_MODEL_FROM_DATABASE=RocketPort Compact PCI 16 port w/external I/F pci:v000011FEd00008015* ID_MODEL_FROM_DATABASE=RocketPort 4-port UART 16954 pci:v000011FF* ID_VENDOR_FROM_DATABASE=Scion Corporation pci:v000011FFd00000003* ID_MODEL_FROM_DATABASE=AG-5 pci:v00001200* ID_VENDOR_FROM_DATABASE=CSS Corporation pci:v00001201* ID_VENDOR_FROM_DATABASE=Vista Controls Corp pci:v00001202* ID_VENDOR_FROM_DATABASE=Network General Corp. pci:v00001202d00004300* ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter pci:v00001202d00004300sv00001202sd00009841* ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter (SK-9841 LX) pci:v00001202d00004300sv00001202sd00009842* ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter (SK-9841 LX dual link) pci:v00001202d00004300sv00001202sd00009843* ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter (SK-9843 SX) pci:v00001202d00004300sv00001202sd00009844* ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter (SK-9843 SX dual link) pci:v00001203* ID_VENDOR_FROM_DATABASE=Bayer Corporation, Agfa Division pci:v00001204* ID_VENDOR_FROM_DATABASE=Lattice Semiconductor Corporation pci:v00001205* ID_VENDOR_FROM_DATABASE=Array Corporation pci:v00001206* ID_VENDOR_FROM_DATABASE=Amdahl Corporation pci:v00001208* ID_VENDOR_FROM_DATABASE=Parsytec GmbH pci:v00001208d00004853* ID_MODEL_FROM_DATABASE=HS-Link Device pci:v00001209* ID_VENDOR_FROM_DATABASE=SCI Systems Inc pci:v0000120A* ID_VENDOR_FROM_DATABASE=Synaptel pci:v0000120B* ID_VENDOR_FROM_DATABASE=Adaptive Solutions pci:v0000120C* ID_VENDOR_FROM_DATABASE=Technical Corp. pci:v0000120D* ID_VENDOR_FROM_DATABASE=Compression Labs, Inc. pci:v0000120E* ID_VENDOR_FROM_DATABASE=Cyclades Corporation pci:v0000120Ed00000100* ID_MODEL_FROM_DATABASE=Cyclom-Y below first megabyte pci:v0000120Ed00000101* ID_MODEL_FROM_DATABASE=Cyclom-Y above first megabyte pci:v0000120Ed00000102* ID_MODEL_FROM_DATABASE=Cyclom-4Y below first megabyte pci:v0000120Ed00000103* ID_MODEL_FROM_DATABASE=Cyclom-4Y above first megabyte pci:v0000120Ed00000104* ID_MODEL_FROM_DATABASE=Cyclom-8Y below first megabyte pci:v0000120Ed00000105* ID_MODEL_FROM_DATABASE=Cyclom-8Y above first megabyte pci:v0000120Ed00000200* ID_MODEL_FROM_DATABASE=Cyclades-Z below first megabyte pci:v0000120Ed00000201* ID_MODEL_FROM_DATABASE=Cyclades-Z above first megabyte pci:v0000120Ed00000300* ID_MODEL_FROM_DATABASE=PC300/RSV or /X21 (2 ports) pci:v0000120Ed00000301* ID_MODEL_FROM_DATABASE=PC300/RSV or /X21 (1 port) pci:v0000120Ed00000310* ID_MODEL_FROM_DATABASE=PC300/TE (2 ports) pci:v0000120Ed00000311* ID_MODEL_FROM_DATABASE=PC300/TE (1 port) pci:v0000120Ed00000320* ID_MODEL_FROM_DATABASE=PC300/TE-M (2 ports) pci:v0000120Ed00000321* ID_MODEL_FROM_DATABASE=PC300/TE-M (1 port) pci:v0000120Ed00000400* ID_MODEL_FROM_DATABASE=PC400 pci:v0000120F* ID_VENDOR_FROM_DATABASE=Essential Communications pci:v0000120Fd00000001* ID_MODEL_FROM_DATABASE=Roadrunner serial HIPPI pci:v00001210* ID_VENDOR_FROM_DATABASE=Hyperparallel Technologies pci:v00001211* ID_VENDOR_FROM_DATABASE=Braintech Inc pci:v00001212* ID_VENDOR_FROM_DATABASE=Kingston Technology Corp. pci:v00001213* ID_VENDOR_FROM_DATABASE=Applied Intelligent Systems, Inc. pci:v00001214* ID_VENDOR_FROM_DATABASE=Performance Technologies, Inc. pci:v00001215* ID_VENDOR_FROM_DATABASE=Interware Co., Ltd pci:v00001216* ID_VENDOR_FROM_DATABASE=Purup Prepress A/S pci:v00001217* ID_VENDOR_FROM_DATABASE=O2 Micro, Inc. pci:v00001217d000000F7* ID_MODEL_FROM_DATABASE=Firewire (IEEE 1394) pci:v00001217d000000F7sv00001071sd00008209* ID_MODEL_FROM_DATABASE=Firewire (IEEE 1394) (Medion MIM 2240 Notebook PC [MD98100]) pci:v00001217d000000F7sv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=Firewire (IEEE 1394) (Satellite P305D-S8995E) pci:v00001217d000010F7* ID_MODEL_FROM_DATABASE=1394 OHCI Compliant Host Controller pci:v00001217d000011F7* ID_MODEL_FROM_DATABASE=OZ600 1394a-2000 Controller pci:v00001217d000011F7sv00001028sd000004A3* ID_MODEL_FROM_DATABASE=OZ600 1394a-2000 Controller (Precision M4600) pci:v00001217d000013F7* ID_MODEL_FROM_DATABASE=1394 OHCI Compliant Host Controller pci:v00001217d00006729* ID_MODEL_FROM_DATABASE=OZ6729 pci:v00001217d0000673A* ID_MODEL_FROM_DATABASE=OZ6730 pci:v00001217d00006832* ID_MODEL_FROM_DATABASE=OZ6832/6833 CardBus Controller pci:v00001217d00006836* ID_MODEL_FROM_DATABASE=OZ6836/6860 CardBus Controller pci:v00001217d00006872* ID_MODEL_FROM_DATABASE=OZ6812 CardBus Controller pci:v00001217d00006925* ID_MODEL_FROM_DATABASE=OZ6922 CardBus Controller pci:v00001217d00006933* ID_MODEL_FROM_DATABASE=OZ6933/711E1 CardBus/SmartCardBus Controller pci:v00001217d00006933sv00001025sd00001016* ID_MODEL_FROM_DATABASE=OZ6933/711E1 CardBus/SmartCardBus Controller (Travelmate 612 TX) pci:v00001217d00006972* ID_MODEL_FROM_DATABASE=OZ601/6912/711E0 CardBus/SmartCardBus Controller pci:v00001217d00006972sv00001014sd0000020C* ID_MODEL_FROM_DATABASE=OZ601/6912/711E0 CardBus/SmartCardBus Controller (ThinkPad R30) pci:v00001217d00006972sv00001028sd00000152* ID_MODEL_FROM_DATABASE=OZ601/6912/711E0 CardBus/SmartCardBus Controller (Latitude D500) pci:v00001217d00006972sv00001179sd00000001* ID_MODEL_FROM_DATABASE=OZ601/6912/711E0 CardBus/SmartCardBus Controller (Magnia Z310) pci:v00001217d00007110* ID_MODEL_FROM_DATABASE=OZ711Mx 4-in-1 MemoryCardBus Accelerator pci:v00001217d00007110sv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=OZ711Mx 4-in-1 MemoryCardBus Accelerator (NC8000 laptop) pci:v00001217d00007110sv0000103Csd00000890* ID_MODEL_FROM_DATABASE=OZ711Mx 4-in-1 MemoryCardBus Accelerator (NC6000 laptop) pci:v00001217d00007110sv00001734sd0000106C* ID_MODEL_FROM_DATABASE=OZ711Mx 4-in-1 MemoryCardBus Accelerator (Amilo A1645) pci:v00001217d00007112* ID_MODEL_FROM_DATABASE=OZ711EC1/M1 SmartCardBus/MemoryCardBus Controller pci:v00001217d00007113* ID_MODEL_FROM_DATABASE=OZ711EC1 SmartCardBus Controller pci:v00001217d00007113sv00001025sd00000035* ID_MODEL_FROM_DATABASE=OZ711EC1 SmartCardBus Controller (TravelMate 660) pci:v00001217d00007114* ID_MODEL_FROM_DATABASE=OZ711M1/MC1 4-in-1 MemoryCardBus Controller pci:v00001217d00007120* ID_MODEL_FROM_DATABASE=Integrated MMC/SD Controller pci:v00001217d00007120sv00001071sd00008209* ID_MODEL_FROM_DATABASE=Integrated MMC/SD Controller (Medion MIM 2240 Notebook PC [MD98100]) pci:v00001217d00007120sv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=Integrated MMC/SD Controller (Satellite P305D-S8995E) pci:v00001217d00007130* ID_MODEL_FROM_DATABASE=Integrated MS/xD Controller pci:v00001217d00007130sv00001071sd00008209* ID_MODEL_FROM_DATABASE=Integrated MS/xD Controller (Medion MIM 2240 Notebook PC [MD98100]) pci:v00001217d00007130sv00001179sd0000FF50* ID_MODEL_FROM_DATABASE=Integrated MS/xD Controller (Satellite P305D-S8995E) pci:v00001217d00007134* ID_MODEL_FROM_DATABASE=OZ711MP1/MS1 MemoryCardBus Controller pci:v00001217d00007135* ID_MODEL_FROM_DATABASE=Cardbus bridge pci:v00001217d00007136* ID_MODEL_FROM_DATABASE=OZ711SP1 Memory CardBus Controller pci:v00001217d000071E2* ID_MODEL_FROM_DATABASE=OZ711E2 SmartCardBus Controller pci:v00001217d00007212* ID_MODEL_FROM_DATABASE=OZ711M2 4-in-1 MemoryCardBus Controller pci:v00001217d00007213* ID_MODEL_FROM_DATABASE=OZ6933E CardBus Controller pci:v00001217d00007223* ID_MODEL_FROM_DATABASE=OZ711M3/MC3 4-in-1 MemoryCardBus Controller pci:v00001217d00007223sv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=OZ711M3/MC3 4-in-1 MemoryCardBus Controller (NC8000 laptop) pci:v00001217d00007223sv0000103Csd00000890* ID_MODEL_FROM_DATABASE=OZ711M3/MC3 4-in-1 MemoryCardBus Controller (NC6000 laptop) pci:v00001217d00007223sv000010CFsd000011C4* ID_MODEL_FROM_DATABASE=OZ711M3/MC3 4-in-1 MemoryCardBus Controller (Lifebook P5020D Laptop) pci:v00001217d00007233* ID_MODEL_FROM_DATABASE=OZ711MP3/MS3 4-in-1 MemoryCardBus Controller pci:v00001217d00008120* ID_MODEL_FROM_DATABASE=Integrated MMC/SD Controller pci:v00001217d00008130* ID_MODEL_FROM_DATABASE=Integrated MS/MSPRO/xD Controller pci:v00001217d00008220* ID_MODEL_FROM_DATABASE=OZ600FJ1/OZ900FJ1 SD/MMC Card Reader Controller pci:v00001217d00008221* ID_MODEL_FROM_DATABASE=OZ600FJ0/OZ900FJ0/OZ600FJS SD/MMC Card Reader Controller pci:v00001217d00008320* ID_MODEL_FROM_DATABASE=OZ600RJ1/OZ900RJ1 SD/MMC Card Reader Controller pci:v00001217d00008320sv00001028sd000004A3* ID_MODEL_FROM_DATABASE=OZ600RJ1/OZ900RJ1 SD/MMC Card Reader Controller (Precision M4600) pci:v00001217d00008321* ID_MODEL_FROM_DATABASE=OZ600RJ0/OZ900RJ0/OZ600RJS SD/MMC Card Reader Controller pci:v00001217d00008330* ID_MODEL_FROM_DATABASE=OZ600 MS/xD Controller pci:v00001217d00008330sv00001028sd000004A3* ID_MODEL_FROM_DATABASE=OZ600 MS/xD Controller (Precision M4600) pci:v00001217d00008331* ID_MODEL_FROM_DATABASE=O2 Flash Memory Card pci:v00001217d00008520* ID_MODEL_FROM_DATABASE=SD/MMC Card Reader Controller pci:v00001218* ID_VENDOR_FROM_DATABASE=Hybricon Corp. pci:v00001219* ID_VENDOR_FROM_DATABASE=First Virtual Corporation pci:v0000121A* ID_VENDOR_FROM_DATABASE=3Dfx Interactive, Inc. pci:v0000121Ad00000001* ID_MODEL_FROM_DATABASE=Voodoo pci:v0000121Ad00000002* ID_MODEL_FROM_DATABASE=Voodoo 2 pci:v0000121Ad00000003* ID_MODEL_FROM_DATABASE=Voodoo Banshee pci:v0000121Ad00000003sv00001092sd00000003* ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion) pci:v0000121Ad00000003sv00001092sd00004000* ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion) pci:v0000121Ad00000003sv00001092sd00004002* ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion) pci:v0000121Ad00000003sv00001092sd00004801* ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion AGP) pci:v0000121Ad00000003sv00001092sd00004803* ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion AGP) pci:v0000121Ad00000003sv00001092sd00008030* ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion) pci:v0000121Ad00000003sv00001092sd00008035* ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion AGP) pci:v0000121Ad00000003sv000010B0sd00000001* ID_MODEL_FROM_DATABASE=Voodoo Banshee (Dragon 4000) pci:v0000121Ad00000003sv00001102sd00001017* ID_MODEL_FROM_DATABASE=Voodoo Banshee (3D Blaster Banshee PCI (CT6760)) pci:v0000121Ad00000003sv00001102sd00001018* ID_MODEL_FROM_DATABASE=Voodoo Banshee (3D Blaster Banshee VE) pci:v0000121Ad00000003sv0000121Asd00000001* ID_MODEL_FROM_DATABASE=Voodoo Banshee (AGP) pci:v0000121Ad00000003sv0000121Asd00000003* ID_MODEL_FROM_DATABASE=Voodoo Banshee (AGP SGRAM) pci:v0000121Ad00000003sv0000121Asd00000004* ID_MODEL_FROM_DATABASE=Voodoo Banshee pci:v0000121Ad00000003sv0000139Csd00000016* ID_MODEL_FROM_DATABASE=Voodoo Banshee (Raven) pci:v0000121Ad00000003sv0000139Csd00000017* ID_MODEL_FROM_DATABASE=Voodoo Banshee (Raven) pci:v0000121Ad00000003sv000014AFsd00000002* ID_MODEL_FROM_DATABASE=Voodoo Banshee (Maxi Gamer Phoenix) pci:v0000121Ad00000004* ID_MODEL_FROM_DATABASE=Voodoo Banshee [Velocity 100] pci:v0000121Ad00000005* ID_MODEL_FROM_DATABASE=Voodoo 3 pci:v0000121Ad00000005sv0000121Asd00000004* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) pci:v0000121Ad00000005sv0000121Asd00000030* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) pci:v0000121Ad00000005sv0000121Asd00000031* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) pci:v0000121Ad00000005sv0000121Asd00000034* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) pci:v0000121Ad00000005sv0000121Asd00000036* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 2000 PCI) pci:v0000121Ad00000005sv0000121Asd00000037* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) pci:v0000121Ad00000005sv0000121Asd00000038* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) pci:v0000121Ad00000005sv0000121Asd0000003A* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) pci:v0000121Ad00000005sv0000121Asd00000044* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3) pci:v0000121Ad00000005sv0000121Asd0000004B* ID_MODEL_FROM_DATABASE=Voodoo 3 (Velocity 100) pci:v0000121Ad00000005sv0000121Asd0000004C* ID_MODEL_FROM_DATABASE=Voodoo 3 (Velocity 200) pci:v0000121Ad00000005sv0000121Asd0000004D* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) pci:v0000121Ad00000005sv0000121Asd0000004E* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) pci:v0000121Ad00000005sv0000121Asd00000051* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) pci:v0000121Ad00000005sv0000121Asd00000052* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) pci:v0000121Ad00000005sv0000121Asd00000057* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 3000 PCI) pci:v0000121Ad00000005sv0000121Asd00000060* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 3500 TV (NTSC)) pci:v0000121Ad00000005sv0000121Asd00000061* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 3500 TV (PAL)) pci:v0000121Ad00000005sv0000121Asd00000062* ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 3500 TV (SECAM)) pci:v0000121Ad00000009* ID_MODEL_FROM_DATABASE=Voodoo 4 / Voodoo 5 pci:v0000121Ad00000009sv0000121Asd00000003* ID_MODEL_FROM_DATABASE=Voodoo 4 / Voodoo 5 (Voodoo5 PCI 5500) pci:v0000121Ad00000009sv0000121Asd00000009* ID_MODEL_FROM_DATABASE=Voodoo 4 / Voodoo 5 (Voodoo5 AGP 5500/6000) pci:v0000121Ad00000057* ID_MODEL_FROM_DATABASE=Voodoo 3/3000 [Avenger] pci:v0000121B* ID_VENDOR_FROM_DATABASE=Advanced Telecommunications Modules pci:v0000121C* ID_VENDOR_FROM_DATABASE=Nippon Texaco., Ltd pci:v0000121D* ID_VENDOR_FROM_DATABASE=LiPPERT ADLINK Technology GmbH pci:v0000121E* ID_VENDOR_FROM_DATABASE=CSPI pci:v0000121Ed00000201* ID_MODEL_FROM_DATABASE=Myrinet 2000 Scalable Cluster Interconnect pci:v0000121F* ID_VENDOR_FROM_DATABASE=Arcus Technology, Inc. pci:v00001220* ID_VENDOR_FROM_DATABASE=Ariel Corporation pci:v00001220d00001220* ID_MODEL_FROM_DATABASE=AMCC 5933 TMS320C80 DSP/Imaging board pci:v00001221* ID_VENDOR_FROM_DATABASE=Contec Co., Ltd pci:v00001221d00009172* ID_MODEL_FROM_DATABASE=PO-64L(PCI)H [Isolated Digital Output Board for PCI] pci:v00001221d000091A2* ID_MODEL_FROM_DATABASE=PO-32L(PCI)H [Isolated Digital Output Board for PCI] pci:v00001221d000091C3* ID_MODEL_FROM_DATABASE=DA16-16(LPCI)L [Un-insulated highly precise analog output board for Low Profile PCI] pci:v00001221d0000B152* ID_MODEL_FROM_DATABASE=DIO-96D2-LPCI pci:v00001221d0000C103* ID_MODEL_FROM_DATABASE=ADA16-32/2(PCI)F [High-Speed Analog I/O Board for PCI] pci:v00001222* ID_VENDOR_FROM_DATABASE=Ancor Communications, Inc. pci:v00001223* ID_VENDOR_FROM_DATABASE=Artesyn Communication Products pci:v00001223d00000003* ID_MODEL_FROM_DATABASE=PM/Link pci:v00001223d00000004* ID_MODEL_FROM_DATABASE=PM/T1 pci:v00001223d00000005* ID_MODEL_FROM_DATABASE=PM/E1 pci:v00001223d00000008* ID_MODEL_FROM_DATABASE=PM/SLS pci:v00001223d00000009* ID_MODEL_FROM_DATABASE=BajaSpan Resource Target pci:v00001223d0000000A* ID_MODEL_FROM_DATABASE=BajaSpan Section 0 pci:v00001223d0000000B* ID_MODEL_FROM_DATABASE=BajaSpan Section 1 pci:v00001223d0000000C* ID_MODEL_FROM_DATABASE=BajaSpan Section 2 pci:v00001223d0000000D* ID_MODEL_FROM_DATABASE=BajaSpan Section 3 pci:v00001223d0000000E* ID_MODEL_FROM_DATABASE=PM/PPC pci:v00001224* ID_VENDOR_FROM_DATABASE=Interactive Images pci:v00001225* ID_VENDOR_FROM_DATABASE=Power I/O, Inc. pci:v00001227* ID_VENDOR_FROM_DATABASE=Tech-Source pci:v00001227d00000006* ID_MODEL_FROM_DATABASE=Raptor GFX 8P pci:v00001227d00000023* ID_MODEL_FROM_DATABASE=Raptor GFX [1100T] pci:v00001227d00000045* ID_MODEL_FROM_DATABASE=Raptor 4000-L [Linux version] pci:v00001227d0000004A* ID_MODEL_FROM_DATABASE=Raptor 4000-LR-L [Linux version] pci:v00001228* ID_VENDOR_FROM_DATABASE=Norsk Elektro Optikk A/S pci:v00001229* ID_VENDOR_FROM_DATABASE=Data Kinesis Inc. pci:v0000122A* ID_VENDOR_FROM_DATABASE=Integrated Telecom pci:v0000122B* ID_VENDOR_FROM_DATABASE=LG Industrial Systems Co., Ltd pci:v0000122C* ID_VENDOR_FROM_DATABASE=Sican GmbH pci:v0000122D* ID_VENDOR_FROM_DATABASE=Aztech System Ltd pci:v0000122Dd00001206* ID_MODEL_FROM_DATABASE=368DSP pci:v0000122Dd00001400* ID_MODEL_FROM_DATABASE=Trident PCI288-Q3DII (NX) pci:v0000122Dd000050DC* ID_MODEL_FROM_DATABASE=3328 Audio pci:v0000122Dd000050DCsv0000122Dsd00000001* ID_MODEL_FROM_DATABASE=3328 Audio pci:v0000122Dd000080DA* ID_MODEL_FROM_DATABASE=3328 Audio pci:v0000122Dd000080DAsv0000122Dsd00000001* ID_MODEL_FROM_DATABASE=3328 Audio pci:v0000122E* ID_VENDOR_FROM_DATABASE=Xyratex pci:v0000122Ed00007722* ID_MODEL_FROM_DATABASE=Napatech XL1 pci:v0000122Ed00007724* ID_MODEL_FROM_DATABASE=Napatech XL2/XA pci:v0000122Ed00007729* ID_MODEL_FROM_DATABASE=Napatech XD pci:v0000122F* ID_VENDOR_FROM_DATABASE=Andrew Corporation pci:v00001230* ID_VENDOR_FROM_DATABASE=Fishcamp Engineering pci:v00001231* ID_VENDOR_FROM_DATABASE=Woodward McCoach, Inc. pci:v00001231d000004E1* ID_MODEL_FROM_DATABASE=Desktop PCI Telephony 4 pci:v00001231d000005E1* ID_MODEL_FROM_DATABASE=Desktop PCI Telephony 5/6 pci:v00001231d00000D00* ID_MODEL_FROM_DATABASE=LightParser pci:v00001231d00000D02* ID_MODEL_FROM_DATABASE=LightParser 2 pci:v00001231d00000D13* ID_MODEL_FROM_DATABASE=Desktop PCI L1/L3 Telephony pci:v00001232* ID_VENDOR_FROM_DATABASE=GPT Limited pci:v00001233* ID_VENDOR_FROM_DATABASE=Bus-Tech, Inc. pci:v00001235* ID_VENDOR_FROM_DATABASE=Risq Modular Systems, Inc. pci:v00001236* ID_VENDOR_FROM_DATABASE=Sigma Designs Corporation pci:v00001236d00000000* ID_MODEL_FROM_DATABASE=RealMagic64/GX pci:v00001236d00006401* ID_MODEL_FROM_DATABASE=REALmagic 64/GX (SD 6425) pci:v00001237* ID_VENDOR_FROM_DATABASE=Alta Technology Corporation pci:v00001238* ID_VENDOR_FROM_DATABASE=Adtran pci:v00001239* ID_VENDOR_FROM_DATABASE=3DO Company pci:v0000123A* ID_VENDOR_FROM_DATABASE=Visicom Laboratories, Inc. pci:v0000123B* ID_VENDOR_FROM_DATABASE=Seeq Technology, Inc. pci:v0000123C* ID_VENDOR_FROM_DATABASE=Century Systems, Inc. pci:v0000123D* ID_VENDOR_FROM_DATABASE=Engineering Design Team, Inc. pci:v0000123Dd00000000* ID_MODEL_FROM_DATABASE=EasyConnect 8/32 pci:v0000123Dd00000002* ID_MODEL_FROM_DATABASE=EasyConnect 8/64 pci:v0000123Dd00000003* ID_MODEL_FROM_DATABASE=EasyIO pci:v0000123E* ID_VENDOR_FROM_DATABASE=Simutech, Inc. pci:v0000123F* ID_VENDOR_FROM_DATABASE=LSI Logic pci:v0000123Fd000000E4* ID_MODEL_FROM_DATABASE=MPEG pci:v0000123Fd00008120* ID_MODEL_FROM_DATABASE=DVxplore Codec pci:v0000123Fd00008120sv000010DEsd000001E1* ID_MODEL_FROM_DATABASE=DVxplore Codec (NVTV PAL) pci:v0000123Fd00008120sv000010DEsd000001E2* ID_MODEL_FROM_DATABASE=DVxplore Codec (NVTV NTSC) pci:v0000123Fd00008120sv000010DEsd000001E3* ID_MODEL_FROM_DATABASE=DVxplore Codec (NVTV PAL) pci:v0000123Fd00008120sv000010DEsd00000248* ID_MODEL_FROM_DATABASE=DVxplore Codec (NVTV NTSC) pci:v0000123Fd00008120sv000010DEsd00000249* ID_MODEL_FROM_DATABASE=DVxplore Codec (NVTV PAL) pci:v0000123Fd00008120sv000011BDsd00000006* ID_MODEL_FROM_DATABASE=DVxplore Codec (DV500 E4) pci:v0000123Fd00008120sv000011BDsd0000000A* ID_MODEL_FROM_DATABASE=DVxplore Codec (DV500 E4) pci:v0000123Fd00008120sv000011BDsd0000000F* ID_MODEL_FROM_DATABASE=DVxplore Codec (DV500 E4) pci:v0000123Fd00008120sv00001809sd00000016* ID_MODEL_FROM_DATABASE=DVxplore Codec (Emuzed MAUI-III PCI PVR FM TV) pci:v0000123Fd00008888* ID_MODEL_FROM_DATABASE=Cinemaster C 3.0 DVD Decoder pci:v0000123Fd00008888sv00001002sd00000001* ID_MODEL_FROM_DATABASE=Cinemaster C 3.0 DVD Decoder pci:v0000123Fd00008888sv00001002sd00000002* ID_MODEL_FROM_DATABASE=Cinemaster C 3.0 DVD Decoder pci:v0000123Fd00008888sv00001328sd00000001* ID_MODEL_FROM_DATABASE=Cinemaster C 3.0 DVD Decoder pci:v00001240* ID_VENDOR_FROM_DATABASE=Marathon Technologies Corp. pci:v00001241* ID_VENDOR_FROM_DATABASE=DSC Communications pci:v00001242* ID_VENDOR_FROM_DATABASE=JNI Corporation pci:v00001242d00001560* ID_MODEL_FROM_DATABASE=JNIC-1560 PCI-X Fibre Channel Controller pci:v00001242d00001560sv00001242sd00006562* ID_MODEL_FROM_DATABASE=JNIC-1560 PCI-X Fibre Channel Controller (FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter) pci:v00001242d00001560sv00001242sd0000656A* ID_MODEL_FROM_DATABASE=JNIC-1560 PCI-X Fibre Channel Controller (FCX-6562 PCI-X Fibre Channel Adapter) pci:v00001242d00004643* ID_MODEL_FROM_DATABASE=FCI-1063 Fibre Channel Adapter pci:v00001242d00006562* ID_MODEL_FROM_DATABASE=FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter pci:v00001242d0000656A* ID_MODEL_FROM_DATABASE=FCX-6562 PCI-X Fibre Channel Adapter pci:v00001243* ID_VENDOR_FROM_DATABASE=Delphax pci:v00001244* ID_VENDOR_FROM_DATABASE=AVM GmbH pci:v00001244d00000700* ID_MODEL_FROM_DATABASE=B1 ISDN pci:v00001244d00000800* ID_MODEL_FROM_DATABASE=C4 ISDN pci:v00001244d00000A00* ID_MODEL_FROM_DATABASE=A1 ISDN [Fritz] pci:v00001244d00000A00sv00001244sd00000A00* ID_MODEL_FROM_DATABASE=A1 ISDN [Fritz] (FRITZ!Card ISDN Controller) pci:v00001244d00000E00* ID_MODEL_FROM_DATABASE=Fritz!Card PCI v2.0 ISDN pci:v00001244d00000E80* ID_MODEL_FROM_DATABASE=Fritz!Card PCI v2.1 ISDN pci:v00001244d00000E80sv00001244sd00000E00* ID_MODEL_FROM_DATABASE=Fritz!Card PCI v2.1 ISDN (PSB 3100F (AVM KAFKA) [Fritz!Card PCI v2.1]) pci:v00001244d00001100* ID_MODEL_FROM_DATABASE=C2 ISDN pci:v00001244d00001200* ID_MODEL_FROM_DATABASE=T1 ISDN pci:v00001244d00002700* ID_MODEL_FROM_DATABASE=Fritz!Card DSL SL pci:v00001244d00002900* ID_MODEL_FROM_DATABASE=Fritz!Card DSL v2.0 pci:v00001245* ID_VENDOR_FROM_DATABASE=A.P.D., S.A. pci:v00001246* ID_VENDOR_FROM_DATABASE=Dipix Technologies, Inc. pci:v00001247* ID_VENDOR_FROM_DATABASE=Xylon Research, Inc. pci:v00001248* ID_VENDOR_FROM_DATABASE=Central Data Corporation pci:v00001249* ID_VENDOR_FROM_DATABASE=Samsung Electronics Co., Ltd. pci:v0000124A* ID_VENDOR_FROM_DATABASE=AEG Electrocom GmbH pci:v0000124B* ID_VENDOR_FROM_DATABASE=SBS/Greenspring Modular I/O pci:v0000124Bd00000040* ID_MODEL_FROM_DATABASE=PCI-40A or cPCI-200 Quad IndustryPack carrier pci:v0000124Bd00000040sv0000124Bsd00009080* ID_MODEL_FROM_DATABASE=PCI-40A or cPCI-200 Quad IndustryPack carrier (PCI9080 Bridge) pci:v0000124C* ID_VENDOR_FROM_DATABASE=Solitron Technologies, Inc. pci:v0000124D* ID_VENDOR_FROM_DATABASE=Stallion Technologies, Inc. pci:v0000124Dd00000000* ID_MODEL_FROM_DATABASE=EasyConnection 8/32 pci:v0000124Dd00000002* ID_MODEL_FROM_DATABASE=EasyConnection 8/64 pci:v0000124Dd00000003* ID_MODEL_FROM_DATABASE=EasyIO pci:v0000124Dd00000004* ID_MODEL_FROM_DATABASE=EasyConnection/RA pci:v0000124E* ID_VENDOR_FROM_DATABASE=Cylink pci:v0000124F* ID_VENDOR_FROM_DATABASE=Infortrend Technology, Inc. pci:v0000124Fd00000041* ID_MODEL_FROM_DATABASE=IFT-2000 Series RAID Controller pci:v00001250* ID_VENDOR_FROM_DATABASE=Hitachi Microcomputer System Ltd pci:v00001251* ID_VENDOR_FROM_DATABASE=VLSI Solutions Oy pci:v00001253* ID_VENDOR_FROM_DATABASE=Guzik Technical Enterprises pci:v00001254* ID_VENDOR_FROM_DATABASE=Linear Systems Ltd. pci:v00001254d00000065* ID_MODEL_FROM_DATABASE=DVB Master FD pci:v00001254d0000007C* ID_MODEL_FROM_DATABASE=DVB Master Quad/o pci:v00001255* ID_VENDOR_FROM_DATABASE=Optibase Ltd pci:v00001255d00001110* ID_MODEL_FROM_DATABASE=MPEG Forge pci:v00001255d00001210* ID_MODEL_FROM_DATABASE=MPEG Fusion pci:v00001255d00002110* ID_MODEL_FROM_DATABASE=VideoPlex pci:v00001255d00002120* ID_MODEL_FROM_DATABASE=VideoPlex CC pci:v00001255d00002130* ID_MODEL_FROM_DATABASE=VideoQuest pci:v00001256* ID_VENDOR_FROM_DATABASE=Perceptive Solutions, Inc. pci:v00001256d00004201* ID_MODEL_FROM_DATABASE=PCI-2220I pci:v00001256d00004401* ID_MODEL_FROM_DATABASE=PCI-2240I pci:v00001256d00005201* ID_MODEL_FROM_DATABASE=PCI-2000 pci:v00001257* ID_VENDOR_FROM_DATABASE=Vertex Networks, Inc. pci:v00001258* ID_VENDOR_FROM_DATABASE=Gilbarco, Inc. pci:v00001259* ID_VENDOR_FROM_DATABASE=Allied Telesis pci:v00001259d00002560* ID_MODEL_FROM_DATABASE=AT-2560 Fast Ethernet Adapter (i82557B) pci:v00001259d00002801* ID_MODEL_FROM_DATABASE=AT-2801FX (RTL-8139) pci:v00001259d0000A117* ID_MODEL_FROM_DATABASE=RTL81xx Fast Ethernet pci:v00001259d0000A11E* ID_MODEL_FROM_DATABASE=RTL81xx Fast Ethernet pci:v00001259d0000A120* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet pci:v0000125A* ID_VENDOR_FROM_DATABASE=ABB Power Systems pci:v0000125B* ID_VENDOR_FROM_DATABASE=Asix Electronics Corporation pci:v0000125Bd00001400* ID_MODEL_FROM_DATABASE=AX88141 Fast Ethernet Controller pci:v0000125Bd00001400sv00001186sd00001100* ID_MODEL_FROM_DATABASE=AX88141 Fast Ethernet Controller (AX8814X Based PCI Fast Ethernet Adapter) pci:v0000125C* ID_VENDOR_FROM_DATABASE=Aurora Technologies, Inc. pci:v0000125Cd00000101* ID_MODEL_FROM_DATABASE=Saturn 4520P pci:v0000125Cd00000640* ID_MODEL_FROM_DATABASE=Aries 16000P pci:v0000125D* ID_VENDOR_FROM_DATABASE=ESS Technology pci:v0000125Dd00000000* ID_MODEL_FROM_DATABASE=ES336H Fax Modem (Early Model) pci:v0000125Dd00001948* ID_MODEL_FROM_DATABASE=ES1948 Maestro-1 pci:v0000125Dd00001968* ID_MODEL_FROM_DATABASE=ES1968 Maestro 2 pci:v0000125Dd00001968sv00001028sd00000085* ID_MODEL_FROM_DATABASE=ES1968 Maestro 2 (ES1968 Maestro-2 PCI) pci:v0000125Dd00001968sv00001033sd00008051* ID_MODEL_FROM_DATABASE=ES1968 Maestro 2 (ES1968 Maestro-2 Audiodrive) pci:v0000125Dd00001969* ID_MODEL_FROM_DATABASE=ES1938/ES1946/ES1969 Solo-1 Audiodrive pci:v0000125Dd00001969sv00001014sd00000166* ID_MODEL_FROM_DATABASE=ES1938/ES1946/ES1969 Solo-1 Audiodrive (ES1969 SOLO-1 AudioDrive on IBM Aptiva Mainboard) pci:v0000125Dd00001969sv0000125Dsd00008888* ID_MODEL_FROM_DATABASE=ES1938/ES1946/ES1969 Solo-1 Audiodrive (Solo-1 Audio Adapter) pci:v0000125Dd00001969sv0000153Bsd0000111B* ID_MODEL_FROM_DATABASE=ES1938/ES1946/ES1969 Solo-1 Audiodrive (Terratec 128i PCI) pci:v0000125Dd00001978* ID_MODEL_FROM_DATABASE=ES1978 Maestro 2E pci:v0000125Dd00001978sv00000E11sd0000B112* ID_MODEL_FROM_DATABASE=ES1978 Maestro 2E (Armada M700/E500) pci:v0000125Dd00001978sv00001033sd0000803C* ID_MODEL_FROM_DATABASE=ES1978 Maestro 2E (ES1978 Maestro-2E Audiodrive) pci:v0000125Dd00001978sv00001033sd00008058* ID_MODEL_FROM_DATABASE=ES1978 Maestro 2E (ES1978 Maestro-2E Audiodrive) pci:v0000125Dd00001978sv00001092sd00004000* ID_MODEL_FROM_DATABASE=ES1978 Maestro 2E (Monster Sound MX400) pci:v0000125Dd00001978sv00001179sd00000001* ID_MODEL_FROM_DATABASE=ES1978 Maestro 2E (ES1978 Maestro-2E Audiodrive) pci:v0000125Dd00001988* ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 pci:v0000125Dd00001988sv00000E11sd00000098* ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 (Evo N600c) pci:v0000125Dd00001988sv00001092sd00004100* ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 (Sonic Impact S100) pci:v0000125Dd00001988sv0000125Dsd00000431* ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 (Allegro AudioDrive) pci:v0000125Dd00001988sv0000125Dsd00001988* ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 (ESS Allegro-1 Audiodrive) pci:v0000125Dd00001988sv0000125Dsd00001998* ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 (Allegro AudioDrive) pci:v0000125Dd00001988sv0000125Dsd00001999* ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 (Allegro-1 AudioDrive) pci:v0000125Dd00001989* ID_MODEL_FROM_DATABASE=ESS Modem pci:v0000125Dd00001989sv0000125Dsd00001989* ID_MODEL_FROM_DATABASE=ESS Modem pci:v0000125Dd00001998* ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Audio Accelerator pci:v0000125Dd00001998sv00001028sd000000B1* ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Audio Accelerator (Latitude C600) pci:v0000125Dd00001998sv00001028sd000000E5* ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Audio Accelerator (Latitude C810) pci:v0000125Dd00001998sv00001028sd000000E6* ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Audio Accelerator (ES1983S Maestro-3i (Dell Inspiron 8100)) pci:v0000125Dd00001999* ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Modem Accelerator pci:v0000125Dd0000199A* ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Audio Accelerator pci:v0000125Dd0000199B* ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Modem Accelerator pci:v0000125Dd00002808* ID_MODEL_FROM_DATABASE=ES336H Fax Modem (Later Model) pci:v0000125Dd00002838* ID_MODEL_FROM_DATABASE=ES2838/2839 SuperLink Modem pci:v0000125Dd00002898* ID_MODEL_FROM_DATABASE=ES2898 Modem pci:v0000125Dd00002898sv0000125Dsd00000424* ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56-PI Data Fax Modem) pci:v0000125Dd00002898sv0000125Dsd00000425* ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56T-PI Data Fax Modem) pci:v0000125Dd00002898sv0000125Dsd00000426* ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56V-PI Data Fax Modem) pci:v0000125Dd00002898sv0000125Dsd00000427* ID_MODEL_FROM_DATABASE=ES2898 Modem (VW-PI Data Fax Modem) pci:v0000125Dd00002898sv0000125Dsd00000428* ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56ST-PI Data Fax Modem) pci:v0000125Dd00002898sv0000125Dsd00000429* ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56SV-PI Data Fax Modem) pci:v0000125Dd00002898sv0000147Asd0000C001* ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56-PI Data Fax Modem) pci:v0000125Dd00002898sv0000148Dsd00001030* ID_MODEL_FROM_DATABASE=ES2898 Modem (HCF WV-PI56 [ESS ES56-PI Data Fax Modem]) pci:v0000125Dd00002898sv000014FEsd00000428* ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56-PI Data Fax Modem) pci:v0000125Dd00002898sv000014FEsd00000429* ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56-PI Data Fax Modem) pci:v0000125E* ID_VENDOR_FROM_DATABASE=Specialvideo Engineering SRL pci:v0000125F* ID_VENDOR_FROM_DATABASE=Concurrent Technologies, Inc. pci:v0000125Fd00002071* ID_MODEL_FROM_DATABASE=CC PMC/232 pci:v0000125Fd00002084* ID_MODEL_FROM_DATABASE=CC PMC/23P pci:v0000125Fd00002091* ID_MODEL_FROM_DATABASE=CC PMC/422 pci:v00001260* ID_VENDOR_FROM_DATABASE=Intersil Corporation pci:v00001260d00003872* ID_MODEL_FROM_DATABASE=ISL3872 [Prism 3] pci:v00001260d00003872sv00001468sd00000202* ID_MODEL_FROM_DATABASE=ISL3872 [Prism 3] (LAN-Express IEEE 802.11b Wireless LAN) pci:v00001260d00003873* ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] pci:v00001260d00003873sv000010CFsd00001169* ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (MBH7WM01-8734 802.11b Wireless Mini PCI Card [ISL3874]) pci:v00001260d00003873sv00001186sd00003501* ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (DWL-520 Wireless PCI Adapter (rev A or B) [ISL3874]) pci:v00001260d00003873sv00001186sd00003700* ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (DWL-520 Wireless PCI Adapter (rev E1) [ISL3872]) pci:v00001260d00003873sv00001385sd00004105* ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (MA311 802.11b wireless adapter [ISL3874]) pci:v00001260d00003873sv00001668sd00000414* ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (HWP01170-01 802.11b PCI Wireless Adapter) pci:v00001260d00003873sv000016A5sd00001601* ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (AIR.mate PC-400 PCI Wireless LAN Adapter) pci:v00001260d00003873sv00001737sd00003874* ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (WMP11 v1 802.11b Wireless-B PCI Adapter [ISL3874]) pci:v00001260d00003873sv00004033sd00007033* ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (PCW200 802.11b Wireless PCI Adapter [ISL3874]) pci:v00001260d00003873sv00008086sd00002510* ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (M3AWEB Wireless 802.11b MiniPCI Adapter) pci:v00001260d00003873sv00008086sd00002513* ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (Wireless 802.11b MiniPCI Adapter) pci:v00001260d00003877* ID_MODEL_FROM_DATABASE=ISL3877 [Prism Indigo] pci:v00001260d00003886* ID_MODEL_FROM_DATABASE=ISL3886 [Prism Javelin/Prism Xbow] pci:v00001260d00003886sv000017CFsd00000037* ID_MODEL_FROM_DATABASE=ISL3886 [Prism Javelin/Prism Xbow] (XG-901 and clones Wireless Adapter) pci:v00001260d00003890* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] pci:v00001260d00003890sv000010B8sd00002802* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (SMC2802W V1 Wireless PCI Adapter [ISL3890]) pci:v00001260d00003890sv000010B8sd00002835* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (SMC2835W Wireless Cardbus Adapter) pci:v00001260d00003890sv000010B8sd0000A835* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (SMC2835W V2 Wireless Cardbus Adapter) pci:v00001260d00003890sv00001113sd00004203* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (WN4201B) pci:v00001260d00003890sv00001113sd00008201* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (T-Com T-Sinus 154pcicard Wireless PCI Adapter) pci:v00001260d00003890sv00001113sd0000B301* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (T-Sinus 154card Cardbus) pci:v00001260d00003890sv00001113sd0000EE03* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (SMC2802W V2 Wireless PCI Adapter [ISL3886]) pci:v00001260d00003890sv00001113sd0000EE08* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (SMC2835W V3 EU Wireless Cardbus Adapter) pci:v00001260d00003890sv00001186sd00003202* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (DWL-G650 A1 Wireless Adapter) pci:v00001260d00003890sv00001259sd0000C104* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (CG-WLCB54GT Wireless Adapter) pci:v00001260d00003890sv00001260sd00000000* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (WG511 v1 54 Mbps Wireless PC Card) pci:v00001260d00003890sv00001385sd00004800* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (WG511 v2/v3 54 Mbps Wireless PC Card) pci:v00001260d00003890sv000016A5sd00001605* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (ALLNET ALL0271 Wireless PCI Adapter) pci:v00001260d00003890sv000017CFsd00000014* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (XG-600 and clones Wireless Adapter) pci:v00001260d00003890sv000017CFsd00000020* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (XG-900 and clones Wireless Adapter) pci:v00001260d00003890sv0000187Esd00003403* ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (G-110 802.11g Wireless Cardbus Adapter) pci:v00001260d00008130* ID_MODEL_FROM_DATABASE=HMP8130 NTSC/PAL Video Decoder pci:v00001260d00008131* ID_MODEL_FROM_DATABASE=HMP8131 NTSC/PAL Video Decoder pci:v00001260d0000FFFF* ID_MODEL_FROM_DATABASE=ISL3886IK pci:v00001260d0000FFFFsv00001260sd00000000* ID_MODEL_FROM_DATABASE=ISL3886IK (Senao 3054MP+ (J) mini-PCI WLAN 802.11g adapter) pci:v00001261* ID_VENDOR_FROM_DATABASE=Matsushita-Kotobuki Electronics Industries, Ltd. pci:v00001262* ID_VENDOR_FROM_DATABASE=ES Computer Company, Ltd. pci:v00001263* ID_VENDOR_FROM_DATABASE=Sonic Solutions pci:v00001264* ID_VENDOR_FROM_DATABASE=Aval Nagasaki Corporation pci:v00001265* ID_VENDOR_FROM_DATABASE=Casio Computer Co., Ltd. pci:v00001266* ID_VENDOR_FROM_DATABASE=Microdyne Corporation pci:v00001266d00000001* ID_MODEL_FROM_DATABASE=NE10/100 Adapter (i82557B) pci:v00001266d00001910* ID_MODEL_FROM_DATABASE=NE2000Plus (RT8029) Ethernet Adapter pci:v00001266d00001910sv00001266sd00001910* ID_MODEL_FROM_DATABASE=NE2000Plus (RT8029) Ethernet Adapter (NE2000Plus Ethernet Adapter) pci:v00001267* ID_VENDOR_FROM_DATABASE=S. A. Telecommunications pci:v00001267d00005352* ID_MODEL_FROM_DATABASE=PCR2101 pci:v00001267d00005A4B* ID_MODEL_FROM_DATABASE=Telsat Turbo pci:v00001268* ID_VENDOR_FROM_DATABASE=Tektronix pci:v00001269* ID_VENDOR_FROM_DATABASE=Thomson-CSF/TTM pci:v0000126A* ID_VENDOR_FROM_DATABASE=Lexmark International, Inc. pci:v0000126B* ID_VENDOR_FROM_DATABASE=Adax, Inc. pci:v0000126C* ID_VENDOR_FROM_DATABASE=Northern Telecom pci:v0000126Cd00001211* ID_MODEL_FROM_DATABASE=10/100BaseTX [RTL81xx] pci:v0000126Cd0000126C* ID_MODEL_FROM_DATABASE=802.11b Wireless Ethernet Adapter pci:v0000126D* ID_VENDOR_FROM_DATABASE=Splash Technology, Inc. pci:v0000126E* ID_VENDOR_FROM_DATABASE=Sumitomo Metal Industries, Ltd. pci:v0000126F* ID_VENDOR_FROM_DATABASE=Silicon Motion, Inc. pci:v0000126Fd00000501* ID_MODEL_FROM_DATABASE=SM501 VoyagerGX Rev. AA pci:v0000126Fd00000510* ID_MODEL_FROM_DATABASE=SM501 VoyagerGX Rev. B pci:v0000126Fd00000710* ID_MODEL_FROM_DATABASE=SM710 LynxEM pci:v0000126Fd00000712* ID_MODEL_FROM_DATABASE=SM712 LynxEM+ pci:v0000126Fd00000718* ID_MODEL_FROM_DATABASE=SM718 LynxSE+ pci:v0000126Fd00000720* ID_MODEL_FROM_DATABASE=SM720 Lynx3DM pci:v0000126Fd00000730* ID_MODEL_FROM_DATABASE=SM731 Cougar3DR pci:v0000126Fd00000750* ID_MODEL_FROM_DATABASE=SM750 pci:v0000126Fd00000810* ID_MODEL_FROM_DATABASE=SM810 LynxE pci:v0000126Fd00000811* ID_MODEL_FROM_DATABASE=SM811 LynxE pci:v0000126Fd00000820* ID_MODEL_FROM_DATABASE=SM820 Lynx3D pci:v0000126Fd00000910* ID_MODEL_FROM_DATABASE=SM910 pci:v00001270* ID_VENDOR_FROM_DATABASE=Olympus Optical Co., Ltd. pci:v00001271* ID_VENDOR_FROM_DATABASE=GW Instruments pci:v00001272* ID_VENDOR_FROM_DATABASE=Telematics International pci:v00001273* ID_VENDOR_FROM_DATABASE=Hughes Network Systems pci:v00001273d00000002* ID_MODEL_FROM_DATABASE=DirecPC pci:v00001274* ID_VENDOR_FROM_DATABASE=Ensoniq pci:v00001274d00001171* ID_MODEL_FROM_DATABASE=ES1373 / Creative Labs CT5803 [AudioPCI] pci:v00001274d00001371* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 pci:v00001274d00001371sv00000E11sd00000024* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (AudioPCI on Motherboard Compaq Deskpro) pci:v00001274d00001371sv00000E11sd0000B1A7* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI) pci:v00001274d00001371sv00001033sd000080AC* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI) pci:v00001274d00001371sv00001042sd00001854* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (Tazer) pci:v00001274d00001371sv0000107Bsd00008054* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (Tabor2) pci:v00001274d00001371sv00001274sd00001371* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (AudioPCI 64V/128 / Creative CT4810/CT5803/CT5806 [Sound Blaster PCI]) pci:v00001274d00001371sv00001274sd00008001* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (CT4751 board) pci:v00001274d00001371sv00001462sd00006470* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6147 1.1A) pci:v00001274d00001371sv00001462sd00006560* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6156 1.10) pci:v00001274d00001371sv00001462sd00006630* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6163BX 1.0A) pci:v00001274d00001371sv00001462sd00006631* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6163VIA 1.0A) pci:v00001274d00001371sv00001462sd00006632* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6163BX 2.0A) pci:v00001274d00001371sv00001462sd00006633* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6163VIA 2.0A) pci:v00001274d00001371sv00001462sd00006820* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6182 1.00) pci:v00001274d00001371sv00001462sd00006822* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6182 1.00A) pci:v00001274d00001371sv00001462sd00006830* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6183 1.00) pci:v00001274d00001371sv00001462sd00006880* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6188 1.00) pci:v00001274d00001371sv00001462sd00006900* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6190 1.00) pci:v00001274d00001371sv00001462sd00006910* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6191) pci:v00001274d00001371sv00001462sd00006930* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6193) pci:v00001274d00001371sv00001462sd00006990* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6199BX 2.0A) pci:v00001274d00001371sv00001462sd00006991* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MS-6199VIA 2.0A) pci:v00001274d00001371sv000014A4sd00002077* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard KR639) pci:v00001274d00001371sv000014A4sd00002105* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MR800) pci:v00001274d00001371sv000014A4sd00002107* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard MR801) pci:v00001274d00001371sv000014A4sd00002172* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard DR739) pci:v00001274d00001371sv00001509sd00009902* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard KW11) pci:v00001274d00001371sv00001509sd00009903* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard KW31) pci:v00001274d00001371sv00001509sd00009904* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard KA11) pci:v00001274d00001371sv00001509sd00009905* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard KC13) pci:v00001274d00001371sv0000152Dsd00008801* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard CP810E) pci:v00001274d00001371sv0000152Dsd00008802* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard CP810) pci:v00001274d00001371sv0000152Dsd00008803* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard P3810E) pci:v00001274d00001371sv0000152Dsd00008804* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard P3810-S) pci:v00001274d00001371sv0000152Dsd00008805* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard P3820-S) pci:v00001274d00001371sv0000270Fsd00002001* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard 6CTR) pci:v00001274d00001371sv0000270Fsd00002200* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard 6WTX) pci:v00001274d00001371sv0000270Fsd00003000* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard 6WSV) pci:v00001274d00001371sv0000270Fsd00003100* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard 6WIV2) pci:v00001274d00001371sv0000270Fsd00003102* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard 6WIV) pci:v00001274d00001371sv0000270Fsd00007060* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard 6ASA2) pci:v00001274d00001371sv00008086sd00004249* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard BI440ZX) pci:v00001274d00001371sv00008086sd0000424C* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard BL440ZX) pci:v00001274d00001371sv00008086sd0000425A* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard BZ440ZX) pci:v00001274d00001371sv00008086sd00004341* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard Cayman) pci:v00001274d00001371sv00008086sd00004343* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard Cape Cod) pci:v00001274d00001371sv00008086sd00004541* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (D815EEA Motherboard) pci:v00001274d00001371sv00008086sd00004649* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard Fire Island) pci:v00001274d00001371sv00008086sd0000464A* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard FJ440ZX) pci:v00001274d00001371sv00008086sd00004D4F* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard Montreal) pci:v00001274d00001371sv00008086sd00004F43* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard OC440LX) pci:v00001274d00001371sv00008086sd00005243* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard RC440BX) pci:v00001274d00001371sv00008086sd00005352* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard SunRiver) pci:v00001274d00001371sv00008086sd00005643* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard Vancouver) pci:v00001274d00001371sv00008086sd00005753* ID_MODEL_FROM_DATABASE=ES1371 / Creative Labs CT2518/ES1373 (ES1371, ES1373 AudioPCI On Motherboard WS440BX) pci:v00001274d00005000* ID_MODEL_FROM_DATABASE=ES1370 [AudioPCI] pci:v00001274d00005880* ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 pci:v00001274d00005880sv00001274sd00002000* ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (Creative CT4810 [Sound Blaster AudioPCI 128]) pci:v00001274d00005880sv00001274sd00002003* ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (Creative SoundBlaster AudioPCI 128) pci:v00001274d00005880sv00001274sd00005880* ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (Creative CT4750 [Sound Blaster PCI 128]) pci:v00001274d00005880sv00001274sd00008001* ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (Sound Blaster 16PCI 4.1ch) pci:v00001274d00005880sv00001458sd0000A000* ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (5880 AudioPCI On Motherboard 6OXET) pci:v00001274d00005880sv00001462sd00006880* ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (5880 AudioPCI On Motherboard MS-6188 1.00) pci:v00001274d00005880sv0000270Fsd00002001* ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (5880 AudioPCI On Motherboard 6CTR) pci:v00001274d00005880sv0000270Fsd00002200* ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (5880 AudioPCI On Motherboard 6WTX) pci:v00001274d00005880sv0000270Fsd00007040* ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (5880 AudioPCI On Motherboard 6ATA4) pci:v00001274d00008001* ID_MODEL_FROM_DATABASE=CT5880 [AudioPCI] pci:v00001274d00008002* ID_MODEL_FROM_DATABASE=5880A [AudioPCI] pci:v00001275* ID_VENDOR_FROM_DATABASE=Network Appliance Corporation pci:v00001276* ID_VENDOR_FROM_DATABASE=Switched Network Technologies, Inc. pci:v00001277* ID_VENDOR_FROM_DATABASE=Comstream pci:v00001278* ID_VENDOR_FROM_DATABASE=Transtech Parallel Systems Ltd. pci:v00001278d00000701* ID_MODEL_FROM_DATABASE=TPE3/TM3 PowerPC Node pci:v00001278d00000710* ID_MODEL_FROM_DATABASE=TPE5 PowerPC PCI board pci:v00001278d00001100* ID_MODEL_FROM_DATABASE=PMC-FPGA02 pci:v00001278d00001101* ID_MODEL_FROM_DATABASE=TS-C43 card with 4 ADSP-TS101 processors pci:v00001279* ID_VENDOR_FROM_DATABASE=Transmeta Corporation pci:v00001279d00000060* ID_MODEL_FROM_DATABASE=TM8000 Northbridge pci:v00001279d00000061* ID_MODEL_FROM_DATABASE=TM8000 AGP bridge pci:v00001279d00000295* ID_MODEL_FROM_DATABASE=Northbridge pci:v00001279d00000395* ID_MODEL_FROM_DATABASE=LongRun Northbridge pci:v00001279d00000396* ID_MODEL_FROM_DATABASE=SDRAM controller pci:v00001279d00000397* ID_MODEL_FROM_DATABASE=BIOS scratchpad pci:v0000127A* ID_VENDOR_FROM_DATABASE=Rockwell International pci:v0000127Ad00001002* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem pci:v0000127Ad00001002sv00001092sd0000094C* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (SupraExpress 56i PRO [Diamond SUP2380]) pci:v0000127Ad00001002sv0000122Dsd00004002* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (HPG / MDP3858-U) pci:v0000127Ad00001002sv0000122Dsd00004005* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (MDP3858-E) pci:v0000127Ad00001002sv0000122Dsd00004007* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (MDP3858-A/-NZ) pci:v0000127Ad00001002sv0000122Dsd00004012* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (MDP3858-SA) pci:v0000127Ad00001002sv0000122Dsd00004017* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (MDP3858-W) pci:v0000127Ad00001002sv0000122Dsd00004018* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (MDP3858-W) pci:v0000127Ad00001002sv0000127Asd00001002* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Rockwell 56K D/F HCF Modem) pci:v0000127Ad00001003* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem pci:v0000127Ad00001003sv00000E11sd0000B0BC* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (229-DF Zephyr) pci:v0000127Ad00001003sv00000E11sd0000B114* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (229-DF Cheetah) pci:v0000127Ad00001003sv00001033sd0000802B* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (229-DF) pci:v0000127Ad00001003sv000013DFsd00001003* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (PCI56RX Modem) pci:v0000127Ad00001003sv000013E0sd00000117* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) pci:v0000127Ad00001003sv000013E0sd00000147* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM F-1156IV+/R3 Spain V.90 Modem) pci:v0000127Ad00001003sv000013E0sd00000197* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) pci:v0000127Ad00001003sv000013E0sd000001C7* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM F-1156IV+/R3 WW V.90 Modem) pci:v0000127Ad00001003sv000013E0sd000001F7* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) pci:v0000127Ad00001003sv00001436sd00001003* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) pci:v0000127Ad00001003sv00001436sd00001103* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM 5614PM3G V.90 Modem) pci:v0000127Ad00001003sv00001436sd00001602* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Compaq 229-DF Ducati) pci:v0000127Ad00001004* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem pci:v0000127Ad00001004sv00001048sd00001500* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem (MicroLink 56k Modem) pci:v0000127Ad00001004sv000010CFsd00001059* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem (Fujitsu 229-DFRT) pci:v0000127Ad00001005* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem pci:v0000127Ad00001005sv00001005sd0000127A* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (AOpen FM56-P) pci:v0000127Ad00001005sv00001033sd00008029* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (229-DFSV) pci:v0000127Ad00001005sv00001033sd00008054* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Modem) pci:v0000127Ad00001005sv000010CFsd0000103C* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu) pci:v0000127Ad00001005sv000010CFsd00001055* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu 229-DFSV) pci:v0000127Ad00001005sv000010CFsd00001056* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu 229-DFSV) pci:v0000127Ad00001005sv0000122Dsd00004003* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-U) pci:v0000127Ad00001005sv0000122Dsd00004006* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Packard Bell MDP3858V-E) pci:v0000127Ad00001005sv0000122Dsd00004008* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-A/SP-NZ) pci:v0000127Ad00001005sv0000122Dsd00004009* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-E) pci:v0000127Ad00001005sv0000122Dsd00004010* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858V-U) pci:v0000127Ad00001005sv0000122Dsd00004011* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-SA) pci:v0000127Ad00001005sv0000122Dsd00004013* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858V-A/V-NZ) pci:v0000127Ad00001005sv0000122Dsd00004015* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-W) pci:v0000127Ad00001005sv0000122Dsd00004016* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858V-W) pci:v0000127Ad00001005sv0000122Dsd00004019* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858V-SA) pci:v0000127Ad00001005sv000013DFsd00001005* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (PCI56RVP Modem) pci:v0000127Ad00001005sv000013E0sd00000187* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM) pci:v0000127Ad00001005sv000013E0sd000001A7* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM) pci:v0000127Ad00001005sv000013E0sd000001B7* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM DF-1156IV+/R3 Spain V.90 Modem) pci:v0000127Ad00001005sv000013E0sd000001D7* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM DF-1156IV+/R3 WW V.90 Modem) pci:v0000127Ad00001005sv00001436sd00001005* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM) pci:v0000127Ad00001005sv00001436sd00001105* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM) pci:v0000127Ad00001005sv00001437sd00001105* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM 5614PS3G V.90 Modem) pci:v0000127Ad00001022* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v0000127Ad00001022sv00001436sd00001303* ID_MODEL_FROM_DATABASE=HCF 56k Modem (M3-5614PM3G V.90 Modem) pci:v0000127Ad00001023* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem pci:v0000127Ad00001023sv0000122Dsd00004020* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Packard Bell MDP3858-WE) pci:v0000127Ad00001023sv0000122Dsd00004023* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (MDP3858-UE) pci:v0000127Ad00001023sv000013E0sd00000247* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM F-1156IV+/R6 Spain V.90 Modem) pci:v0000127Ad00001023sv000013E0sd00000297* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) pci:v0000127Ad00001023sv000013E0sd000002C7* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM F-1156IV+/R6 WW V.90 Modem) pci:v0000127Ad00001023sv00001436sd00001203* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) pci:v0000127Ad00001023sv00001436sd00001303* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) pci:v0000127Ad00001024* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem pci:v0000127Ad00001025* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem pci:v0000127Ad00001025sv000010CFsd0000106A* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu 235-DFSV) pci:v0000127Ad00001025sv0000122Dsd00004021* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Packard Bell MDP3858V-WE) pci:v0000127Ad00001025sv0000122Dsd00004022* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-WE) pci:v0000127Ad00001025sv0000122Dsd00004024* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858V-UE) pci:v0000127Ad00001025sv0000122Dsd00004025* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-UE) pci:v0000127Ad00001026* ID_MODEL_FROM_DATABASE=HCF 56k PCI Speakerphone Modem pci:v0000127Ad00001032* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v0000127Ad00001033* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v0000127Ad00001034* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v0000127Ad00001035* ID_MODEL_FROM_DATABASE=HCF 56k PCI Speakerphone Modem pci:v0000127Ad00001036* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v0000127Ad00001085* ID_MODEL_FROM_DATABASE=HCF 56k Volcano PCI Modem pci:v0000127Ad00002004* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem pci:v0000127Ad00002005* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem pci:v0000127Ad00002005sv0000104Dsd00008044* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (229-DFSV) pci:v0000127Ad00002005sv0000104Dsd00008045* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (229-DFSV) pci:v0000127Ad00002005sv0000104Dsd00008055* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (PBE/Aztech 235W-DFSV) pci:v0000127Ad00002005sv0000104Dsd00008056* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (235-DFSV) pci:v0000127Ad00002005sv0000104Dsd0000805A* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Modem) pci:v0000127Ad00002005sv0000104Dsd0000805F* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Modem) pci:v0000127Ad00002005sv0000104Dsd00008074* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Modem) pci:v0000127Ad00002013* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem pci:v0000127Ad00002013sv00001179sd00000001* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Modem) pci:v0000127Ad00002013sv00001179sd0000FF00* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Modem) pci:v0000127Ad00002014* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem pci:v0000127Ad00002014sv000010CFsd00001057* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (Fujitsu Citicorp III) pci:v0000127Ad00002014sv0000122Dsd00004050* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (MSP3880-U) pci:v0000127Ad00002014sv0000122Dsd00004055* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (MSP3880-W) pci:v0000127Ad00002015* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem pci:v0000127Ad00002015sv000010CFsd00001063* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu) pci:v0000127Ad00002015sv000010CFsd00001064* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu) pci:v0000127Ad00002015sv00001468sd00002015* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu) pci:v0000127Ad00002016* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem pci:v0000127Ad00002016sv0000122Dsd00004051* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (MSP3880V-W) pci:v0000127Ad00002016sv0000122Dsd00004052* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (MSP3880SP-W) pci:v0000127Ad00002016sv0000122Dsd00004054* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (MSP3880V-U) pci:v0000127Ad00002016sv0000122Dsd00004056* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (MSP3880SP-U) pci:v0000127Ad00002016sv0000122Dsd00004057* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (MSP3880SP-A) pci:v0000127Ad00004311* ID_MODEL_FROM_DATABASE=Riptide HSF 56k PCI Modem pci:v0000127Ad00004311sv0000127Asd00004311* ID_MODEL_FROM_DATABASE=Riptide HSF 56k PCI Modem (Ring Modular? Riptide HSF RT HP Dom) pci:v0000127Ad00004311sv000013E0sd00000210* ID_MODEL_FROM_DATABASE=Riptide HSF 56k PCI Modem (HP-GVC) pci:v0000127Ad00004320* ID_MODEL_FROM_DATABASE=Riptide PCI Audio Controller pci:v0000127Ad00004320sv00001235sd00004320* ID_MODEL_FROM_DATABASE=Riptide PCI Audio Controller pci:v0000127Ad00004321* ID_MODEL_FROM_DATABASE=Riptide HCF 56k PCI Modem pci:v0000127Ad00004321sv00001235sd00004321* ID_MODEL_FROM_DATABASE=Riptide HCF 56k PCI Modem (Hewlett Packard DF) pci:v0000127Ad00004321sv00001235sd00004324* ID_MODEL_FROM_DATABASE=Riptide HCF 56k PCI Modem (Hewlett Packard DF) pci:v0000127Ad00004321sv000013E0sd00000210* ID_MODEL_FROM_DATABASE=Riptide HCF 56k PCI Modem (Hewlett Packard DF) pci:v0000127Ad00004321sv0000144Dsd00002321* ID_MODEL_FROM_DATABASE=Riptide HCF 56k PCI Modem (Riptide) pci:v0000127Ad00004322* ID_MODEL_FROM_DATABASE=Riptide PCI Game Controller pci:v0000127Ad00004322sv00001235sd00004322* ID_MODEL_FROM_DATABASE=Riptide PCI Game Controller pci:v0000127Ad00008234* ID_MODEL_FROM_DATABASE=RapidFire 616X ATM155 Adapter pci:v0000127Ad00008234sv0000108Dsd00000022* ID_MODEL_FROM_DATABASE=RapidFire 616X ATM155 Adapter pci:v0000127Ad00008234sv0000108Dsd00000027* ID_MODEL_FROM_DATABASE=RapidFire 616X ATM155 Adapter pci:v0000127B* ID_VENDOR_FROM_DATABASE=Pixera Corporation pci:v0000127C* ID_VENDOR_FROM_DATABASE=Crosspoint Solutions, Inc. pci:v0000127D* ID_VENDOR_FROM_DATABASE=Vela Research pci:v0000127E* ID_VENDOR_FROM_DATABASE=Winnov, L.P. pci:v0000127Ed00000010* ID_MODEL_FROM_DATABASE=Videum 1000 Plus pci:v0000127F* ID_VENDOR_FROM_DATABASE=Fujifilm pci:v00001280* ID_VENDOR_FROM_DATABASE=Photoscript Group Ltd. pci:v00001281* ID_VENDOR_FROM_DATABASE=Yokogawa Electric Corporation pci:v00001282* ID_VENDOR_FROM_DATABASE=Davicom Semiconductor, Inc. pci:v00001282d00006585* ID_MODEL_FROM_DATABASE=DM562P V90 Modem pci:v00001282d00009009* ID_MODEL_FROM_DATABASE=Ethernet 100/10 MBit pci:v00001282d00009100* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet pci:v00001282d00009102* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet pci:v00001282d00009102sv00000291sd00008212* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet (DM9102A (DM9102AE, SM9102AF) Ethernet 100/10 MBit) pci:v00001282d00009132* ID_MODEL_FROM_DATABASE=Ethernet 100/10 MBit pci:v00001283* ID_VENDOR_FROM_DATABASE=Integrated Technology Express, Inc. pci:v00001283d0000673A* ID_MODEL_FROM_DATABASE=IT8330G pci:v00001283d00008152* ID_MODEL_FROM_DATABASE=IT8152F/G Advanced RISC-to-PCI Companion Chip pci:v00001283d00008211* ID_MODEL_FROM_DATABASE=ITE 8211F Single Channel UDMA 133 pci:v00001283d00008211sv00001043sd00008138* ID_MODEL_FROM_DATABASE=ITE 8211F Single Channel UDMA 133 (P5GD1-VW Mainboard) pci:v00001283d00008212* ID_MODEL_FROM_DATABASE=IT8212 Dual channel ATA RAID controller pci:v00001283d00008212sv00001283sd00000001* ID_MODEL_FROM_DATABASE=IT8212 Dual channel ATA RAID controller (IT/ITE8212 Dual channel ATA RAID controller) pci:v00001283d00008213* ID_MODEL_FROM_DATABASE=IT8213 IDE Controller pci:v00001283d00008213sv00001458sd0000B000* ID_MODEL_FROM_DATABASE=IT8213 IDE Controller (GA-EG45M-DS2H Mainboard) pci:v00001283d00008330* ID_MODEL_FROM_DATABASE=IT8330G pci:v00001283d00008872* ID_MODEL_FROM_DATABASE=IT887xF PCI to ISA I/O chip with SMB, GPIO, Serial or Parallel Port pci:v00001283d00008888* ID_MODEL_FROM_DATABASE=IT8888F/G PCI to ISA Bridge with SMB [Golden Gate] pci:v00001283d00008889* ID_MODEL_FROM_DATABASE=IT8889F PCI to ISA Bridge pci:v00001283d00008893* ID_MODEL_FROM_DATABASE=IT8893E PCIe to PCI Bridge pci:v00001283d0000E886* ID_MODEL_FROM_DATABASE=IT8330G pci:v00001284* ID_VENDOR_FROM_DATABASE=Sahara Networks, Inc. pci:v00001285* ID_VENDOR_FROM_DATABASE=Platform Technologies, Inc. pci:v00001285d00000100* ID_MODEL_FROM_DATABASE=AGOGO sound chip (aka ESS Maestro 1) pci:v00001286* ID_VENDOR_FROM_DATABASE=Mazet GmbH pci:v00001287* ID_VENDOR_FROM_DATABASE=M-Pact, Inc. pci:v00001287d0000001E* ID_MODEL_FROM_DATABASE=LS220D DVD Decoder pci:v00001287d0000001F* ID_MODEL_FROM_DATABASE=LS220C DVD Decoder pci:v00001288* ID_VENDOR_FROM_DATABASE=Timestep Corporation pci:v00001289* ID_VENDOR_FROM_DATABASE=AVC Technology, Inc. pci:v0000128A* ID_VENDOR_FROM_DATABASE=Asante Technologies, Inc. pci:v0000128B* ID_VENDOR_FROM_DATABASE=Transwitch Corporation pci:v0000128C* ID_VENDOR_FROM_DATABASE=Retix Corporation pci:v0000128D* ID_VENDOR_FROM_DATABASE=G2 Networks, Inc. pci:v0000128Dd00000021* ID_MODEL_FROM_DATABASE=ATM155 Adapter pci:v0000128E* ID_VENDOR_FROM_DATABASE=Hoontech Corporation/Samho Multi Tech Ltd. pci:v0000128Ed00000008* ID_MODEL_FROM_DATABASE=ST128 WSS/SB pci:v0000128Ed00000009* ID_MODEL_FROM_DATABASE=ST128 SAM9407 pci:v0000128Ed0000000A* ID_MODEL_FROM_DATABASE=ST128 Game Port pci:v0000128Ed0000000B* ID_MODEL_FROM_DATABASE=ST128 MPU Port pci:v0000128Ed0000000C* ID_MODEL_FROM_DATABASE=ST128 Ctrl Port pci:v0000128F* ID_VENDOR_FROM_DATABASE=Tateno Dennou, Inc. pci:v00001290* ID_VENDOR_FROM_DATABASE=Sord Computer Corporation pci:v00001291* ID_VENDOR_FROM_DATABASE=NCS Computer Italia pci:v00001292* ID_VENDOR_FROM_DATABASE=Tritech Microelectronics Inc pci:v00001292d0000FC02* ID_MODEL_FROM_DATABASE=Pyramid3D TR25202 pci:v00001293* ID_VENDOR_FROM_DATABASE=Media Reality Technology pci:v00001294* ID_VENDOR_FROM_DATABASE=Rhetorex, Inc. pci:v00001295* ID_VENDOR_FROM_DATABASE=Imagenation Corporation pci:v00001295d00000800* ID_MODEL_FROM_DATABASE=PXR800 pci:v00001295d00001000* ID_MODEL_FROM_DATABASE=PXD1000 pci:v00001296* ID_VENDOR_FROM_DATABASE=Kofax Image Products pci:v00001297* ID_VENDOR_FROM_DATABASE=Holco Enterprise Co, Ltd/Shuttle Computer pci:v00001298* ID_VENDOR_FROM_DATABASE=Spellcaster Telecommunications Inc. pci:v00001299* ID_VENDOR_FROM_DATABASE=Knowledge Technology Lab. pci:v0000129A* ID_VENDOR_FROM_DATABASE=VMetro, inc. pci:v0000129Ad00000615* ID_MODEL_FROM_DATABASE=PBT-615 PCI-X Bus Analyzer pci:v0000129Ad00001100* ID_MODEL_FROM_DATABASE=PMC-FPGA05 pci:v0000129Ad00001106* ID_MODEL_FROM_DATABASE=XMC-FPGA05F, PCI interface pci:v0000129Ad00001107* ID_MODEL_FROM_DATABASE=XMC-FPGA05F, PCIe interface pci:v0000129Ad00001108* ID_MODEL_FROM_DATABASE=XMC-FPGA05D, PCI interface pci:v0000129Ad00001109* ID_MODEL_FROM_DATABASE=XMC-FPGA05D, PCIe interface pci:v0000129B* ID_VENDOR_FROM_DATABASE=Image Access pci:v0000129C* ID_VENDOR_FROM_DATABASE=Jaycor pci:v0000129D* ID_VENDOR_FROM_DATABASE=Compcore Multimedia, Inc. pci:v0000129E* ID_VENDOR_FROM_DATABASE=Victor Company of Japan, Ltd. pci:v0000129F* ID_VENDOR_FROM_DATABASE=OEC Medical Systems, Inc. pci:v000012A0* ID_VENDOR_FROM_DATABASE=Allen-Bradley Company pci:v000012A1* ID_VENDOR_FROM_DATABASE=Simpact Associates, Inc. pci:v000012A2* ID_VENDOR_FROM_DATABASE=Newgen Systems Corporation pci:v000012A3* ID_VENDOR_FROM_DATABASE=Lucent Technologies pci:v000012A3d00008105* ID_MODEL_FROM_DATABASE=T8105 H100 Digital Switch pci:v000012A4* ID_VENDOR_FROM_DATABASE=NTT Electronics Technology Company pci:v000012A5* ID_VENDOR_FROM_DATABASE=Vision Dynamics Ltd. pci:v000012A6* ID_VENDOR_FROM_DATABASE=Scalable Networks, Inc. pci:v000012A7* ID_VENDOR_FROM_DATABASE=AMO GmbH pci:v000012A8* ID_VENDOR_FROM_DATABASE=News Datacom pci:v000012A9* ID_VENDOR_FROM_DATABASE=Xiotech Corporation pci:v000012AA* ID_VENDOR_FROM_DATABASE=SDL Communications, Inc. pci:v000012AB* ID_VENDOR_FROM_DATABASE=Yuan Yuan Enterprise Co., Ltd. pci:v000012ABd00000000* ID_MODEL_FROM_DATABASE=MPG160/Kuroutoshikou ITVC15-STVLP pci:v000012ABd00000002* ID_MODEL_FROM_DATABASE=AU8830 [Vortex2] Based Sound Card With A3D Support pci:v000012ABd00000003* ID_MODEL_FROM_DATABASE=T507 (DVB-T) TV tuner/capture device pci:v000012ABd00002300* ID_MODEL_FROM_DATABASE=Club-3D Zap TV2100 pci:v000012ABd00003000* ID_MODEL_FROM_DATABASE=MPG-200C PCI DVD Decoder Card pci:v000012ABd00004789* ID_MODEL_FROM_DATABASE=MPC788 MiniPCI Hybrid TV Tuner pci:v000012ABd0000FFF3* ID_MODEL_FROM_DATABASE=MPG600/Kuroutoshikou ITVC16-STVLP pci:v000012ABd0000FFFF* ID_MODEL_FROM_DATABASE=MPG600/Kuroutoshikou ITVC16-STVLP pci:v000012AC* ID_VENDOR_FROM_DATABASE=Measurex Corporation pci:v000012AD* ID_VENDOR_FROM_DATABASE=Multidata GmbH pci:v000012AE* ID_VENDOR_FROM_DATABASE=Alteon Networks Inc. pci:v000012AEd00000001* ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet pci:v000012AEd00000001sv00001014sd00000104* ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet (Gigabit Ethernet-SX PCI Adapter) pci:v000012AEd00000001sv000012AEsd00000001* ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet (Gigabit Ethernet-SX (Universal)) pci:v000012AEd00000002* ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet (Copper) pci:v000012AEd00000002sv000010A9sd00008002* ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet (Copper) (Acenic Gigabit Ethernet) pci:v000012AEd00000002sv000012AEsd00000002* ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet (Copper) (Gigabit Ethernet-T (3C986-T)) pci:v000012AEd000000FA* ID_MODEL_FROM_DATABASE=Farallon PN9100-T Gigabit Ethernet pci:v000012AF* ID_VENDOR_FROM_DATABASE=TDK USA Corp pci:v000012B0* ID_VENDOR_FROM_DATABASE=Jorge Scientific Corp pci:v000012B1* ID_VENDOR_FROM_DATABASE=GammaLink pci:v000012B2* ID_VENDOR_FROM_DATABASE=General Signal Networks pci:v000012B3* ID_VENDOR_FROM_DATABASE=Inter-Face Co Ltd pci:v000012B4* ID_VENDOR_FROM_DATABASE=FutureTel Inc pci:v000012B5* ID_VENDOR_FROM_DATABASE=Granite Systems Inc. pci:v000012B6* ID_VENDOR_FROM_DATABASE=Natural Microsystems pci:v000012B7* ID_VENDOR_FROM_DATABASE=Cognex Modular Vision Systems Div. - Acumen Inc. pci:v000012B8* ID_VENDOR_FROM_DATABASE=Korg pci:v000012B9* ID_VENDOR_FROM_DATABASE=3Com Corp, Modem Division pci:v000012B9d00001006* ID_MODEL_FROM_DATABASE=WinModem pci:v000012B9d00001006sv000012B9sd0000005C* ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal Voice WinModem (Model 3472)) pci:v000012B9d00001006sv000012B9sd0000005E* ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal WinModem (Models 662975)) pci:v000012B9d00001006sv000012B9sd00000062* ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal Voice WinModem (Model 662978)) pci:v000012B9d00001006sv000012B9sd00000068* ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal Voice WinModem (Model 5690)) pci:v000012B9d00001006sv000012B9sd0000007A* ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal Voice WinModem (Model 662974)) pci:v000012B9d00001006sv000012B9sd0000007F* ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal WinModem (Models 5698, 5699)) pci:v000012B9d00001006sv000012B9sd00000080* ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal WinModem (Models 2975, 3528)) pci:v000012B9d00001006sv000012B9sd00000081* ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal Voice WinModem (Models 2974, 3529)) pci:v000012B9d00001006sv000012B9sd00000091* ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal Voice WinModem (Model 2978)) pci:v000012B9d00001007* ID_MODEL_FROM_DATABASE=USR 56k Internal WinModem pci:v000012B9d00001007sv000012B9sd000000A3* ID_MODEL_FROM_DATABASE=USR 56k Internal WinModem ((Model 3595)) pci:v000012B9d00001007sv000012B9sd000000C4* ID_MODEL_FROM_DATABASE=USR 56k Internal WinModem (U.S. Robotics V.92 Voice Faxmodem (2884A/B/C)) pci:v000012B9d00001008* ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 pci:v000012B9d00001008sv000012B9sd000000A2* ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56k Internal FAX Modem (Model 2977)) pci:v000012B9d00001008sv000012B9sd000000AA* ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56k Internal Voice Modem (Model 2976)) pci:v000012B9d00001008sv000012B9sd000000AB* ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56k Internal Voice Modem (Model 5609)) pci:v000012B9d00001008sv000012B9sd000000AC* ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56k Internal Voice Modem (Model 3298)) pci:v000012B9d00001008sv000012B9sd000000AD* ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56k Internal FAX Modem (Model 5610)) pci:v000012B9d00001008sv000012B9sd000000D3* ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56K Internal V92 FAX Modem (Model 5610)) pci:v000012B9d00001008sv000012B9sd0000BABA* ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56K Internal Voice Modem 3CP3298-DEL (Model 5601) [Hawk]) pci:v000012BA* ID_VENDOR_FROM_DATABASE=BittWare, Inc. pci:v000012BB* ID_VENDOR_FROM_DATABASE=Nippon Unisoft Corporation pci:v000012BC* ID_VENDOR_FROM_DATABASE=Array Microsystems pci:v000012BD* ID_VENDOR_FROM_DATABASE=Computerm Corp. pci:v000012BE* ID_VENDOR_FROM_DATABASE=Anchor Chips Inc. pci:v000012BEd00003041* ID_MODEL_FROM_DATABASE=AN3041Q CO-MEM pci:v000012BEd00003042* ID_MODEL_FROM_DATABASE=AN3042Q CO-MEM Lite pci:v000012BEd00003042sv000012BEsd00003042* ID_MODEL_FROM_DATABASE=AN3042Q CO-MEM Lite (Anchor Chips Lite Evaluation Board) pci:v000012BF* ID_VENDOR_FROM_DATABASE=Fujifilm Microdevices pci:v000012C0* ID_VENDOR_FROM_DATABASE=Infimed pci:v000012C1* ID_VENDOR_FROM_DATABASE=GMM Research Corp pci:v000012C2* ID_VENDOR_FROM_DATABASE=Mentec Limited pci:v000012C3* ID_VENDOR_FROM_DATABASE=Holtek Microelectronics Inc pci:v000012C3d00000058* ID_MODEL_FROM_DATABASE=PCI NE2K Ethernet pci:v000012C3d00005598* ID_MODEL_FROM_DATABASE=PCI NE2K Ethernet pci:v000012C4* ID_VENDOR_FROM_DATABASE=Connect Tech Inc pci:v000012C4d00000001* ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 8 (RS232/CL/RJ11) pci:v000012C4d00000002* ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 4 (RS232) pci:v000012C4d00000003* ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 2 (RS232) pci:v000012C4d00000004* ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 8 (UNIV, RS485) pci:v000012C4d00000005* ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 4+4/6+2 (UNIV, RS232/485) pci:v000012C4d00000006* ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 4 (OPTO, RS485) pci:v000012C4d00000007* ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 2+2 (RS232/485) pci:v000012C4d00000008* ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 2 (OPTO, Tx, RS485) pci:v000012C4d00000009* ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 2+6 (RS232/485) pci:v000012C4d0000000A* ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 8 (Tx, RS485) pci:v000012C4d0000000B* ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 4 (Tx, RS485) pci:v000012C4d0000000C* ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 2 (20 MHz, RS485) pci:v000012C4d0000000D* ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 2 PTM pci:v000012C4d00000100* ID_MODEL_FROM_DATABASE=NT960/PCI pci:v000012C4d00000201* ID_MODEL_FROM_DATABASE=cPCI Titan - 2 Port pci:v000012C4d00000202* ID_MODEL_FROM_DATABASE=cPCI Titan - 4 Port pci:v000012C4d00000300* ID_MODEL_FROM_DATABASE=CTI PCI UART 2 (RS232) pci:v000012C4d00000301* ID_MODEL_FROM_DATABASE=CTI PCI UART 4 (RS232) pci:v000012C4d00000302* ID_MODEL_FROM_DATABASE=CTI PCI UART 8 (RS232) pci:v000012C4d00000310* ID_MODEL_FROM_DATABASE=CTI PCI UART 1+1 (RS232/485) pci:v000012C4d00000311* ID_MODEL_FROM_DATABASE=CTI PCI UART 2+2 (RS232/485) pci:v000012C4d00000312* ID_MODEL_FROM_DATABASE=CTI PCI UART 4+4 (RS232/485) pci:v000012C4d00000320* ID_MODEL_FROM_DATABASE=CTI PCI UART 2 pci:v000012C4d00000321* ID_MODEL_FROM_DATABASE=CTI PCI UART 4 pci:v000012C4d00000322* ID_MODEL_FROM_DATABASE=CTI PCI UART 8 pci:v000012C4d00000330* ID_MODEL_FROM_DATABASE=CTI PCI UART 2 (RS485) pci:v000012C4d00000331* ID_MODEL_FROM_DATABASE=CTI PCI UART 4 (RS485) pci:v000012C4d00000332* ID_MODEL_FROM_DATABASE=CTI PCI UART 8 (RS485) pci:v000012C5* ID_VENDOR_FROM_DATABASE=Picture Elements Incorporated pci:v000012C5d0000007E* ID_MODEL_FROM_DATABASE=Imaging/Scanning Subsystem Engine pci:v000012C5d0000007F* ID_MODEL_FROM_DATABASE=Imaging/Scanning Subsystem Engine pci:v000012C5d00000081* ID_MODEL_FROM_DATABASE=PCIVST [Grayscale Thresholding Engine] pci:v000012C5d00000085* ID_MODEL_FROM_DATABASE=Video Simulator/Sender pci:v000012C5d00000086* ID_MODEL_FROM_DATABASE=THR2 Multi-scale Thresholder pci:v000012C6* ID_VENDOR_FROM_DATABASE=Mitani Corporation pci:v000012C7* ID_VENDOR_FROM_DATABASE=Dialogic Corp pci:v000012C7d00000546* ID_MODEL_FROM_DATABASE=Springware D/120JCT-LS pci:v000012C7d00000647* ID_MODEL_FROM_DATABASE=Springware D/240JCT-T1 pci:v000012C7d00000676* ID_MODEL_FROM_DATABASE=Springware D/41JCT-LS pci:v000012C7d00000685* ID_MODEL_FROM_DATABASE=Springware D/480JCT-2T1 pci:v000012C8* ID_VENDOR_FROM_DATABASE=G Force Co, Ltd pci:v000012C9* ID_VENDOR_FROM_DATABASE=Gigi Operations pci:v000012CA* ID_VENDOR_FROM_DATABASE=Integrated Computing Engines pci:v000012CB* ID_VENDOR_FROM_DATABASE=Antex Electronics Corporation pci:v000012CBd00000027* ID_MODEL_FROM_DATABASE=SC4 (StudioCard) pci:v000012CBd0000002E* ID_MODEL_FROM_DATABASE=StudioCard 2000 pci:v000012CC* ID_VENDOR_FROM_DATABASE=Pluto Technologies International pci:v000012CD* ID_VENDOR_FROM_DATABASE=Aims Lab pci:v000012CE* ID_VENDOR_FROM_DATABASE=Netspeed Inc. pci:v000012CF* ID_VENDOR_FROM_DATABASE=Prophet Systems, Inc. pci:v000012D0* ID_VENDOR_FROM_DATABASE=GDE Systems, Inc. pci:v000012D1* ID_VENDOR_FROM_DATABASE=PSITech pci:v000012D2* ID_VENDOR_FROM_DATABASE=NVidia / SGS Thomson (Joint Venture) pci:v000012D2d00000008* ID_MODEL_FROM_DATABASE=NV1 pci:v000012D2d00000009* ID_MODEL_FROM_DATABASE=DAC64 pci:v000012D2d00000018* ID_MODEL_FROM_DATABASE=Riva128 pci:v000012D2d00000018sv00001048sd00000C10* ID_MODEL_FROM_DATABASE=Riva128 (VICTORY Erazor) pci:v000012D2d00000018sv0000107Bsd00008030* ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128) pci:v000012D2d00000018sv00001092sd00000350* ID_MODEL_FROM_DATABASE=Riva128 (Viper V330) pci:v000012D2d00000018sv00001092sd00001092* ID_MODEL_FROM_DATABASE=Riva128 (Viper V330) pci:v000012D2d00000018sv000010B4sd00001B1B* ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128) pci:v000012D2d00000018sv000010B4sd00001B1D* ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128) pci:v000012D2d00000018sv000010B4sd00001B1E* ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128, PAL TV-Out) pci:v000012D2d00000018sv000010B4sd00001B20* ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128 Sapphire) pci:v000012D2d00000018sv000010B4sd00001B21* ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128) pci:v000012D2d00000018sv000010B4sd00001B22* ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128 AGP, NTSC TV-Out) pci:v000012D2d00000018sv000010B4sd00001B23* ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128 AGP, PAL TV-Out) pci:v000012D2d00000018sv000010B4sd00001B27* ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128 DVD) pci:v000012D2d00000018sv000010B4sd00001B88* ID_MODEL_FROM_DATABASE=Riva128 (MVP Pro 128) pci:v000012D2d00000018sv000010B4sd0000222A* ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128 AGP) pci:v000012D2d00000018sv000010B4sd00002230* ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128) pci:v000012D2d00000018sv000010B4sd00002232* ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128) pci:v000012D2d00000018sv000010B4sd00002235* ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128 AGP) pci:v000012D2d00000018sv00002A15sd000054A3* ID_MODEL_FROM_DATABASE=Riva128 (3DVision-SAGP / 3DexPlorer 3000) pci:v000012D2d00000019* ID_MODEL_FROM_DATABASE=Riva128ZX pci:v000012D2d00000020* ID_MODEL_FROM_DATABASE=TNT pci:v000012D2d00000028* ID_MODEL_FROM_DATABASE=TNT2 pci:v000012D2d00000029* ID_MODEL_FROM_DATABASE=UTNT2 pci:v000012D2d0000002C* ID_MODEL_FROM_DATABASE=VTNT2 pci:v000012D2d000000A0* ID_MODEL_FROM_DATABASE=ITNT2 pci:v000012D3* ID_VENDOR_FROM_DATABASE=Vingmed Sound A/S pci:v000012D4* ID_VENDOR_FROM_DATABASE=Ulticom (Formerly DGM&S) pci:v000012D4d00000200* ID_MODEL_FROM_DATABASE=T1 Card pci:v000012D5* ID_VENDOR_FROM_DATABASE=Equator Technologies Inc pci:v000012D5d00000003* ID_MODEL_FROM_DATABASE=BSP16 pci:v000012D5d00001000* ID_MODEL_FROM_DATABASE=BSP15 pci:v000012D6* ID_VENDOR_FROM_DATABASE=Analogic Corp pci:v000012D7* ID_VENDOR_FROM_DATABASE=Biotronic SRL pci:v000012D8* ID_VENDOR_FROM_DATABASE=Pericom Semiconductor pci:v000012D8d000001A7* ID_MODEL_FROM_DATABASE=PI7C21P100 PCI to PCI Bridge pci:v000012D8d0000400A* ID_MODEL_FROM_DATABASE=PI7C9X442SL PCI Express Bridge Port pci:v000012D8d0000400E* ID_MODEL_FROM_DATABASE=PI7C9X442SL USB OHCI Controller pci:v000012D8d0000400F* ID_MODEL_FROM_DATABASE=PI7C9X442SL USB EHCI Controller pci:v000012D8d000071E2* ID_MODEL_FROM_DATABASE=PI7C7300A/PI7C7300D PCI-to-PCI Bridge pci:v000012D8d000071E3* ID_MODEL_FROM_DATABASE=PI7C7300A/PI7C7300D PCI-to-PCI Bridge (Secondary Bus 2) pci:v000012D8d00008140* ID_MODEL_FROM_DATABASE=PI7C8140A PCI-to-PCI Bridge pci:v000012D8d00008148* ID_MODEL_FROM_DATABASE=PI7C8148A/PI7C8148B PCI-to-PCI Bridge pci:v000012D8d00008150* ID_MODEL_FROM_DATABASE=PCI to PCI Bridge pci:v000012D8d00008152* ID_MODEL_FROM_DATABASE=PI7C8152A/PI7C8152B/PI7C8152BI PCI-to-PCI Bridge pci:v000012D8d00008154* ID_MODEL_FROM_DATABASE=PI7C8154A/PI7C8154B/PI7C8154BI PCI-to-PCI Bridge pci:v000012D8d0000E110* ID_MODEL_FROM_DATABASE=PI7C9X110 PCI Express to PCI bridge pci:v000012D8d0000E110sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=PI7C9X110 PCI Express to PCI bridge (CC11/CL11 CompactPCI Bridge) pci:v000012D8d0000E111* ID_MODEL_FROM_DATABASE=PI7C9X111SL PCIe-to-PCI Reversible Bridge pci:v000012D8d0000E130* ID_MODEL_FROM_DATABASE=PCI Express to PCI-XPI7C9X130 PCI-X Bridge pci:v000012D9* ID_VENDOR_FROM_DATABASE=Aculab PLC pci:v000012D9d00000002* ID_MODEL_FROM_DATABASE=PCI Prosody pci:v000012D9d00000004* ID_MODEL_FROM_DATABASE=cPCI Prosody pci:v000012D9d00000005* ID_MODEL_FROM_DATABASE=Aculab E1/T1 PCI card pci:v000012D9d00001078* ID_MODEL_FROM_DATABASE=Prosody X class e1000 device pci:v000012D9d00001078sv000012D9sd0000000D* ID_MODEL_FROM_DATABASE=Prosody X class e1000 device (Prosody X PCI) pci:v000012D9d00001078sv000012D9sd0000000E* ID_MODEL_FROM_DATABASE=Prosody X class e1000 device (Prosody X cPCI) pci:v000012DA* ID_VENDOR_FROM_DATABASE=True Time Inc. pci:v000012DB* ID_VENDOR_FROM_DATABASE=Annapolis Micro Systems, Inc pci:v000012DC* ID_VENDOR_FROM_DATABASE=Symicron Computer Communication Ltd. pci:v000012DD* ID_VENDOR_FROM_DATABASE=Management Graphics pci:v000012DE* ID_VENDOR_FROM_DATABASE=Rainbow Technologies pci:v000012DEd00000200* ID_MODEL_FROM_DATABASE=CryptoSwift CS200 pci:v000012DF* ID_VENDOR_FROM_DATABASE=SBS Technologies Inc pci:v000012E0* ID_VENDOR_FROM_DATABASE=Chase Research pci:v000012E0d00000010* ID_MODEL_FROM_DATABASE=ST16C654 Quad UART pci:v000012E0d00000020* ID_MODEL_FROM_DATABASE=ST16C654 Quad UART pci:v000012E0d00000030* ID_MODEL_FROM_DATABASE=ST16C654 Quad UART pci:v000012E1* ID_VENDOR_FROM_DATABASE=Nintendo Co, Ltd pci:v000012E2* ID_VENDOR_FROM_DATABASE=Datum Inc. Bancomm-Timing Division pci:v000012E3* ID_VENDOR_FROM_DATABASE=Imation Corp - Medical Imaging Systems pci:v000012E4* ID_VENDOR_FROM_DATABASE=Brooktrout Technology Inc pci:v000012E5* ID_VENDOR_FROM_DATABASE=Apex Semiconductor Inc pci:v000012E6* ID_VENDOR_FROM_DATABASE=Cirel Systems pci:v000012E7* ID_VENDOR_FROM_DATABASE=Sunsgroup Corporation pci:v000012E8* ID_VENDOR_FROM_DATABASE=Crisc Corp pci:v000012E9* ID_VENDOR_FROM_DATABASE=GE Spacenet pci:v000012EA* ID_VENDOR_FROM_DATABASE=Zuken pci:v000012EB* ID_VENDOR_FROM_DATABASE=Aureal Semiconductor pci:v000012EBd00000001* ID_MODEL_FROM_DATABASE=Vortex 1 pci:v000012EBd00000001sv0000104Dsd00008036* ID_MODEL_FROM_DATABASE=Vortex 1 (AU8820 Vortex Digital Audio Processor) pci:v000012EBd00000001sv00001092sd00002000* ID_MODEL_FROM_DATABASE=Vortex 1 (Sonic Impact A3D) pci:v000012EBd00000001sv00001092sd00002100* ID_MODEL_FROM_DATABASE=Vortex 1 (Sonic Impact A3D) pci:v000012EBd00000001sv00001092sd00002110* ID_MODEL_FROM_DATABASE=Vortex 1 (Sonic Impact A3D) pci:v000012EBd00000001sv00001092sd00002200* ID_MODEL_FROM_DATABASE=Vortex 1 (Sonic Impact A3D) pci:v000012EBd00000001sv0000122Dsd00001002* ID_MODEL_FROM_DATABASE=Vortex 1 (AU8820 Vortex Digital Audio Processor) pci:v000012EBd00000001sv000012EBsd00000001* ID_MODEL_FROM_DATABASE=Vortex 1 (AU8820 Vortex Digital Audio Processor) pci:v000012EBd00000001sv00005053sd00003355* ID_MODEL_FROM_DATABASE=Vortex 1 (Montego) pci:v000012EBd00000001sv000050B2sd00001111* ID_MODEL_FROM_DATABASE=Vortex 1 (XLerate) pci:v000012EBd00000002* ID_MODEL_FROM_DATABASE=Vortex 2 pci:v000012EBd00000002sv0000104Dsd00008049* ID_MODEL_FROM_DATABASE=Vortex 2 (AU8830 Vortex 3D Digital Audio Processor) pci:v000012EBd00000002sv0000104Dsd0000807B* ID_MODEL_FROM_DATABASE=Vortex 2 (AU8830 Vortex 3D Digital Audio Processor) pci:v000012EBd00000002sv00001092sd00003000* ID_MODEL_FROM_DATABASE=Vortex 2 (Monster Sound II) pci:v000012EBd00000002sv00001092sd00003001* ID_MODEL_FROM_DATABASE=Vortex 2 (Monster Sound II) pci:v000012EBd00000002sv00001092sd00003002* ID_MODEL_FROM_DATABASE=Vortex 2 (Monster Sound II) pci:v000012EBd00000002sv00001092sd00003003* ID_MODEL_FROM_DATABASE=Vortex 2 (Monster Sound II) pci:v000012EBd00000002sv00001092sd00003004* ID_MODEL_FROM_DATABASE=Vortex 2 (Monster Sound II) pci:v000012EBd00000002sv000012EBsd00000002* ID_MODEL_FROM_DATABASE=Vortex 2 (AU8830 Vortex 3D Digital Audio Processor) pci:v000012EBd00000002sv000012EBsd00000088* ID_MODEL_FROM_DATABASE=Vortex 2 (AU8830 Vortex 3D Digital Audio Processor) pci:v000012EBd00000002sv0000144Dsd00003510* ID_MODEL_FROM_DATABASE=Vortex 2 (AU8830 Vortex 3D Digital Audio Processor) pci:v000012EBd00000002sv00005053sd00003356* ID_MODEL_FROM_DATABASE=Vortex 2 (Montego II) pci:v000012EBd00000003* ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor pci:v000012EBd00000003sv0000104Dsd00008049* ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor pci:v000012EBd00000003sv0000104Dsd00008077* ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor pci:v000012EBd00000003sv0000109Fsd00001000* ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor pci:v000012EBd00000003sv000012EBsd00000003* ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor pci:v000012EBd00000003sv00001462sd00006780* ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor pci:v000012EBd00000003sv000014A4sd00002073* ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor pci:v000012EBd00000003sv000014A4sd00002091* ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor pci:v000012EBd00000003sv000014A4sd00002104* ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor pci:v000012EBd00000003sv000014A4sd00002106* ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor pci:v000012EBd00008803* ID_MODEL_FROM_DATABASE=Vortex 56k Software Modem pci:v000012EBd00008803sv000012EBsd00008803* ID_MODEL_FROM_DATABASE=Vortex 56k Software Modem pci:v000012EC* ID_VENDOR_FROM_DATABASE=3A International, Inc. pci:v000012ED* ID_VENDOR_FROM_DATABASE=Optivision Inc. pci:v000012EE* ID_VENDOR_FROM_DATABASE=Orange Micro pci:v000012EF* ID_VENDOR_FROM_DATABASE=Vienna Systems pci:v000012F0* ID_VENDOR_FROM_DATABASE=Pentek pci:v000012F1* ID_VENDOR_FROM_DATABASE=Sorenson Vision Inc pci:v000012F2* ID_VENDOR_FROM_DATABASE=Gammagraphx, Inc. pci:v000012F3* ID_VENDOR_FROM_DATABASE=Radstone Technology pci:v000012F4* ID_VENDOR_FROM_DATABASE=Megatel pci:v000012F5* ID_VENDOR_FROM_DATABASE=Forks pci:v000012F6* ID_VENDOR_FROM_DATABASE=Dawson France pci:v000012F7* ID_VENDOR_FROM_DATABASE=Cognex pci:v000012F8* ID_VENDOR_FROM_DATABASE=Electronic Design GmbH pci:v000012F8d00000002* ID_MODEL_FROM_DATABASE=VideoMaker pci:v000012F9* ID_VENDOR_FROM_DATABASE=Four Fold Ltd pci:v000012FB* ID_VENDOR_FROM_DATABASE=Spectrum Signal Processing pci:v000012FBd00000001* ID_MODEL_FROM_DATABASE=PMC-MAI pci:v000012FBd000000F5* ID_MODEL_FROM_DATABASE=F5 Dakar pci:v000012FBd000002AD* ID_MODEL_FROM_DATABASE=PMC-2MAI pci:v000012FBd00002ADC* ID_MODEL_FROM_DATABASE=ePMC-2ADC pci:v000012FBd00003100* ID_MODEL_FROM_DATABASE=PRO-3100 pci:v000012FBd00003500* ID_MODEL_FROM_DATABASE=PRO-3500 pci:v000012FBd00004D4F* ID_MODEL_FROM_DATABASE=Modena pci:v000012FBd00008120* ID_MODEL_FROM_DATABASE=ePMC-8120 pci:v000012FBd0000DA62* ID_MODEL_FROM_DATABASE=Daytona C6201 PCI (Hurricane) pci:v000012FBd0000DB62* ID_MODEL_FROM_DATABASE=Ingliston XBIF pci:v000012FBd0000DC62* ID_MODEL_FROM_DATABASE=Ingliston PLX9054 pci:v000012FBd0000DD62* ID_MODEL_FROM_DATABASE=Ingliston JTAG/ISP pci:v000012FBd0000EDDC* ID_MODEL_FROM_DATABASE=ePMC-MSDDC pci:v000012FBd0000FA01* ID_MODEL_FROM_DATABASE=ePMC-FPGA pci:v000012FC* ID_VENDOR_FROM_DATABASE=Capital Equipment Corp pci:v000012FD* ID_VENDOR_FROM_DATABASE=I2S pci:v000012FE* ID_VENDOR_FROM_DATABASE=ESD Electronic System Design GmbH pci:v000012FF* ID_VENDOR_FROM_DATABASE=Lexicon pci:v00001300* ID_VENDOR_FROM_DATABASE=Harman International Industries Inc pci:v00001302* ID_VENDOR_FROM_DATABASE=Computer Sciences Corp pci:v00001303* ID_VENDOR_FROM_DATABASE=Innovative Integration pci:v00001303d00000030* ID_MODEL_FROM_DATABASE=X3-SDF 4-channel XMC acquisition board pci:v00001304* ID_VENDOR_FROM_DATABASE=Juniper Networks pci:v00001305* ID_VENDOR_FROM_DATABASE=Netphone, Inc pci:v00001306* ID_VENDOR_FROM_DATABASE=Duet Technologies pci:v00001307* ID_VENDOR_FROM_DATABASE=Measurement Computing pci:v00001307d00000001* ID_MODEL_FROM_DATABASE=PCI-DAS1602/16 pci:v00001307d0000000B* ID_MODEL_FROM_DATABASE=PCI-DIO48H pci:v00001307d0000000C* ID_MODEL_FROM_DATABASE=PCI-PDISO8 pci:v00001307d0000000D* ID_MODEL_FROM_DATABASE=PCI-PDISO16 pci:v00001307d0000000F* ID_MODEL_FROM_DATABASE=PCI-DAS1200 pci:v00001307d00000010* ID_MODEL_FROM_DATABASE=PCI-DAS1602/12 pci:v00001307d00000014* ID_MODEL_FROM_DATABASE=PCI-DIO24H pci:v00001307d00000015* ID_MODEL_FROM_DATABASE=PCI-DIO24H/CTR3 pci:v00001307d00000016* ID_MODEL_FROM_DATABASE=PCI-DIO48H/CTR15 pci:v00001307d00000017* ID_MODEL_FROM_DATABASE=PCI-DIO96H pci:v00001307d00000018* ID_MODEL_FROM_DATABASE=PCI-CTR05 pci:v00001307d00000019* ID_MODEL_FROM_DATABASE=PCI-DAS1200/JR pci:v00001307d0000001A* ID_MODEL_FROM_DATABASE=PCI-DAS1001 pci:v00001307d0000001B* ID_MODEL_FROM_DATABASE=PCI-DAS1002 pci:v00001307d0000001C* ID_MODEL_FROM_DATABASE=PCI-DAS1602JR/16 pci:v00001307d0000001D* ID_MODEL_FROM_DATABASE=PCI-DAS6402/16 pci:v00001307d0000001E* ID_MODEL_FROM_DATABASE=PCI-DAS6402/12 pci:v00001307d0000001F* ID_MODEL_FROM_DATABASE=PCI-DAS16/M1 pci:v00001307d00000020* ID_MODEL_FROM_DATABASE=PCI-DDA02/12 pci:v00001307d00000021* ID_MODEL_FROM_DATABASE=PCI-DDA04/12 pci:v00001307d00000022* ID_MODEL_FROM_DATABASE=PCI-DDA08/12 pci:v00001307d00000023* ID_MODEL_FROM_DATABASE=PCI-DDA02/16 pci:v00001307d00000024* ID_MODEL_FROM_DATABASE=PCI-DDA04/16 pci:v00001307d00000025* ID_MODEL_FROM_DATABASE=PCI-DDA08/16 pci:v00001307d00000026* ID_MODEL_FROM_DATABASE=PCI-DAC04/12-HS pci:v00001307d00000027* ID_MODEL_FROM_DATABASE=PCI-DAC04/16-HS pci:v00001307d00000028* ID_MODEL_FROM_DATABASE=PCI-DIO24 pci:v00001307d00000029* ID_MODEL_FROM_DATABASE=PCI-DAS08 pci:v00001307d0000002C* ID_MODEL_FROM_DATABASE=PCI-INT32 pci:v00001307d00000033* ID_MODEL_FROM_DATABASE=PCI-DUAL-AC5 pci:v00001307d00000034* ID_MODEL_FROM_DATABASE=PCI-DAS-TC pci:v00001307d00000035* ID_MODEL_FROM_DATABASE=PCI-DAS64/M1/16 pci:v00001307d00000036* ID_MODEL_FROM_DATABASE=PCI-DAS64/M2/16 pci:v00001307d00000037* ID_MODEL_FROM_DATABASE=PCI-DAS64/M3/16 pci:v00001307d0000004C* ID_MODEL_FROM_DATABASE=PCI-DAS1000 pci:v00001307d0000004D* ID_MODEL_FROM_DATABASE=PCI-QUAD04 pci:v00001307d00000052* ID_MODEL_FROM_DATABASE=PCI-DAS4020/12 pci:v00001307d00000053* ID_MODEL_FROM_DATABASE=PCIM-DDA06/16 pci:v00001307d00000054* ID_MODEL_FROM_DATABASE=PCI-DIO96 pci:v00001307d0000005D* ID_MODEL_FROM_DATABASE=PCI-DAS6023 pci:v00001307d0000005E* ID_MODEL_FROM_DATABASE=PCI-DAS6025 pci:v00001307d0000005F* ID_MODEL_FROM_DATABASE=PCI-DAS6030 pci:v00001307d00000060* ID_MODEL_FROM_DATABASE=PCI-DAS6031 pci:v00001307d00000061* ID_MODEL_FROM_DATABASE=PCI-DAS6032 pci:v00001307d00000062* ID_MODEL_FROM_DATABASE=PCI-DAS6033 pci:v00001307d00000063* ID_MODEL_FROM_DATABASE=PCI-DAS6034 pci:v00001307d00000064* ID_MODEL_FROM_DATABASE=PCI-DAS6035 pci:v00001307d00000065* ID_MODEL_FROM_DATABASE=PCI-DAS6040 pci:v00001307d00000066* ID_MODEL_FROM_DATABASE=PCI-DAS6052 pci:v00001307d00000067* ID_MODEL_FROM_DATABASE=PCI-DAS6070 pci:v00001307d00000068* ID_MODEL_FROM_DATABASE=PCI-DAS6071 pci:v00001307d0000006F* ID_MODEL_FROM_DATABASE=PCI-DAS6036 pci:v00001307d00000070* ID_MODEL_FROM_DATABASE=PCI-DAC6702 pci:v00001307d00000078* ID_MODEL_FROM_DATABASE=PCI-DAS6013 pci:v00001307d00000079* ID_MODEL_FROM_DATABASE=PCI-DAS6014 pci:v00001307d00000115* ID_MODEL_FROM_DATABASE=PCIe-DAS1602/16 pci:v00001308* ID_VENDOR_FROM_DATABASE=Jato Technologies Inc. pci:v00001308d00000001* ID_MODEL_FROM_DATABASE=NetCelerator Adapter pci:v00001308d00000001sv00001308sd00000001* ID_MODEL_FROM_DATABASE=NetCelerator Adapter pci:v00001309* ID_VENDOR_FROM_DATABASE=AB Semiconductor Ltd pci:v0000130A* ID_VENDOR_FROM_DATABASE=Mitsubishi Electric Microcomputer pci:v0000130B* ID_VENDOR_FROM_DATABASE=Colorgraphic Communications Corp pci:v0000130C* ID_VENDOR_FROM_DATABASE=Ambex Technologies, Inc pci:v0000130D* ID_VENDOR_FROM_DATABASE=Accelerix Inc pci:v0000130E* ID_VENDOR_FROM_DATABASE=Yamatake-Honeywell Co. Ltd pci:v0000130F* ID_VENDOR_FROM_DATABASE=Advanet Inc pci:v00001310* ID_VENDOR_FROM_DATABASE=Gespac pci:v00001311* ID_VENDOR_FROM_DATABASE=Videoserver, Inc pci:v00001312* ID_VENDOR_FROM_DATABASE=Acuity Imaging, Inc pci:v00001313* ID_VENDOR_FROM_DATABASE=Yaskawa Electric Co. pci:v00001315* ID_VENDOR_FROM_DATABASE=Wavesat pci:v00001316* ID_VENDOR_FROM_DATABASE=Teradyne Inc pci:v00001317* ID_VENDOR_FROM_DATABASE=ADMtek pci:v00001317d00000981* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet pci:v00001317d00000985* ID_MODEL_FROM_DATABASE=NC100 Network Everywhere Fast Ethernet 10/100 pci:v00001317d00000985sv00001734sd0000100C* ID_MODEL_FROM_DATABASE=NC100 Network Everywhere Fast Ethernet 10/100 (Scenic N300 ADMtek AN983 10/100 Mbps PCI Adapter) pci:v00001317d00001985* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet pci:v00001317d00001985sv00001385sd0000511A* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet (FA511) pci:v00001317d00001985sv00001395sd00002103* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet (CB100-EZ (4-LED version)) pci:v00001317d00002850* ID_MODEL_FROM_DATABASE=HSP MicroModem 56 pci:v00001317d00005120* ID_MODEL_FROM_DATABASE=ADM5120 OpenGate System-on-Chip pci:v00001317d00008201* ID_MODEL_FROM_DATABASE=ADM8211 802.11b Wireless Interface pci:v00001317d00008201sv000010B8sd00002635* ID_MODEL_FROM_DATABASE=ADM8211 802.11b Wireless Interface (SMC2635W v1 802.11b Wireless Cardbus Adapter) pci:v00001317d00008201sv00001317sd00008201* ID_MODEL_FROM_DATABASE=ADM8211 802.11b Wireless Interface (SMC2635W v2 802.11b Wireless Cardbus Adapter) pci:v00001317d00008211* ID_MODEL_FROM_DATABASE=ADM8211 802.11b Wireless Interface pci:v00001317d00009511* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet pci:v00001318* ID_VENDOR_FROM_DATABASE=Packet Engines Inc. pci:v00001318d00000911* ID_MODEL_FROM_DATABASE=GNIC-II PCI Gigabit Ethernet [Hamachi] pci:v00001319* ID_VENDOR_FROM_DATABASE=Fortemedia, Inc pci:v00001319d00000801* ID_MODEL_FROM_DATABASE=Xwave QS3000A [FM801] pci:v00001319d00000801sv00001319sd00001319* ID_MODEL_FROM_DATABASE=Xwave QS3000A [FM801] (FM801 PCI Audio) pci:v00001319d00000802* ID_MODEL_FROM_DATABASE=Xwave QS3000A [FM801 game port] pci:v00001319d00000802sv00001319sd00001319* ID_MODEL_FROM_DATABASE=Xwave QS3000A [FM801 game port] (FM801 PCI Joystick) pci:v00001319d00001000* ID_MODEL_FROM_DATABASE=FM801 PCI Audio pci:v00001319d00001001* ID_MODEL_FROM_DATABASE=FM801 PCI Joystick pci:v0000131A* ID_VENDOR_FROM_DATABASE=Finisar Corp. pci:v0000131C* ID_VENDOR_FROM_DATABASE=Nippon Electro-Sensory Devices Corp pci:v0000131D* ID_VENDOR_FROM_DATABASE=Sysmic, Inc. pci:v0000131E* ID_VENDOR_FROM_DATABASE=Xinex Networks Inc pci:v0000131F* ID_VENDOR_FROM_DATABASE=Siig Inc pci:v0000131Fd00001000* ID_MODEL_FROM_DATABASE=CyberSerial (1-port) 16550 pci:v0000131Fd00001001* ID_MODEL_FROM_DATABASE=CyberSerial (1-port) 16650 pci:v0000131Fd00001002* ID_MODEL_FROM_DATABASE=CyberSerial (1-port) 16850 pci:v0000131Fd00001010* ID_MODEL_FROM_DATABASE=Duet 1S(16550)+1P pci:v0000131Fd00001011* ID_MODEL_FROM_DATABASE=Duet 1S(16650)+1P pci:v0000131Fd00001012* ID_MODEL_FROM_DATABASE=Duet 1S(16850)+1P pci:v0000131Fd00001020* ID_MODEL_FROM_DATABASE=CyberParallel (1-port) pci:v0000131Fd00001021* ID_MODEL_FROM_DATABASE=CyberParallel (2-port) pci:v0000131Fd00001030* ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16550 pci:v0000131Fd00001031* ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16650 pci:v0000131Fd00001032* ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16850 pci:v0000131Fd00001034* ID_MODEL_FROM_DATABASE=Trio 2S(16550)+1P pci:v0000131Fd00001035* ID_MODEL_FROM_DATABASE=Trio 2S(16650)+1P pci:v0000131Fd00001036* ID_MODEL_FROM_DATABASE=Trio 2S(16850)+1P pci:v0000131Fd00001050* ID_MODEL_FROM_DATABASE=CyberSerial (4-port) 16550 pci:v0000131Fd00001051* ID_MODEL_FROM_DATABASE=CyberSerial (4-port) 16650 pci:v0000131Fd00001052* ID_MODEL_FROM_DATABASE=CyberSerial (4-port) 16850 pci:v0000131Fd00002000* ID_MODEL_FROM_DATABASE=CyberSerial (1-port) 16550 pci:v0000131Fd00002001* ID_MODEL_FROM_DATABASE=CyberSerial (1-port) 16650 pci:v0000131Fd00002002* ID_MODEL_FROM_DATABASE=CyberSerial (1-port) 16850 pci:v0000131Fd00002010* ID_MODEL_FROM_DATABASE=Duet 1S(16550)+1P pci:v0000131Fd00002011* ID_MODEL_FROM_DATABASE=Duet 1S(16650)+1P pci:v0000131Fd00002012* ID_MODEL_FROM_DATABASE=Duet 1S(16850)+1P pci:v0000131Fd00002020* ID_MODEL_FROM_DATABASE=CyberParallel (1-port) pci:v0000131Fd00002021* ID_MODEL_FROM_DATABASE=CyberParallel (2-port) pci:v0000131Fd00002030* ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16550 pci:v0000131Fd00002030sv0000131Fsd00002030* ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16550 (PCI Serial Card) pci:v0000131Fd00002031* ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16650 pci:v0000131Fd00002032* ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16850 pci:v0000131Fd00002040* ID_MODEL_FROM_DATABASE=Trio 1S(16550)+2P pci:v0000131Fd00002041* ID_MODEL_FROM_DATABASE=Trio 1S(16650)+2P pci:v0000131Fd00002042* ID_MODEL_FROM_DATABASE=Trio 1S(16850)+2P pci:v0000131Fd00002050* ID_MODEL_FROM_DATABASE=CyberSerial (4-port) 16550 pci:v0000131Fd00002051* ID_MODEL_FROM_DATABASE=CyberSerial (4-port) 16650 pci:v0000131Fd00002052* ID_MODEL_FROM_DATABASE=CyberSerial (4-port) 16850 pci:v0000131Fd00002060* ID_MODEL_FROM_DATABASE=Trio 2S(16550)+1P pci:v0000131Fd00002061* ID_MODEL_FROM_DATABASE=Trio 2S(16650)+1P pci:v0000131Fd00002062* ID_MODEL_FROM_DATABASE=Trio 2S(16850)+1P pci:v0000131Fd00002081* ID_MODEL_FROM_DATABASE=CyberSerial (8-port) ST16654 pci:v00001320* ID_VENDOR_FROM_DATABASE=Crypto AG pci:v00001321* ID_VENDOR_FROM_DATABASE=Arcobel Graphics BV pci:v00001322* ID_VENDOR_FROM_DATABASE=MTT Co., Ltd pci:v00001323* ID_VENDOR_FROM_DATABASE=Dome Inc pci:v00001324* ID_VENDOR_FROM_DATABASE=Sphere Communications pci:v00001325* ID_VENDOR_FROM_DATABASE=Salix Technologies, Inc pci:v00001326* ID_VENDOR_FROM_DATABASE=Seachange international pci:v00001327* ID_VENDOR_FROM_DATABASE=Voss scientific pci:v00001328* ID_VENDOR_FROM_DATABASE=quadrant international pci:v00001329* ID_VENDOR_FROM_DATABASE=Productivity Enhancement pci:v0000132A* ID_VENDOR_FROM_DATABASE=Microcom Inc. pci:v0000132B* ID_VENDOR_FROM_DATABASE=Broadband Technologies pci:v0000132C* ID_VENDOR_FROM_DATABASE=Micrel Inc pci:v0000132D* ID_VENDOR_FROM_DATABASE=Integrated Silicon Solution, Inc. pci:v00001330* ID_VENDOR_FROM_DATABASE=MMC Networks pci:v00001331* ID_VENDOR_FROM_DATABASE=RadiSys Corporation pci:v00001331d00000030* ID_MODEL_FROM_DATABASE=ENP-2611 pci:v00001331d00008200* ID_MODEL_FROM_DATABASE=82600 Host Bridge pci:v00001331d00008201* ID_MODEL_FROM_DATABASE=82600 IDE pci:v00001331d00008202* ID_MODEL_FROM_DATABASE=82600 USB pci:v00001331d00008210* ID_MODEL_FROM_DATABASE=82600 PCI Bridge pci:v00001332* ID_VENDOR_FROM_DATABASE=Micro Memory pci:v00001332d00005415* ID_MODEL_FROM_DATABASE=MM-5415CN PCI Memory Module with Battery Backup pci:v00001332d00005425* ID_MODEL_FROM_DATABASE=MM-5425CN PCI 64/66 Memory Module with Battery Backup pci:v00001332d00006140* ID_MODEL_FROM_DATABASE=MM-6140D pci:v00001334* ID_VENDOR_FROM_DATABASE=Redcreek Communications, Inc pci:v00001335* ID_VENDOR_FROM_DATABASE=Videomail, Inc pci:v00001337* ID_VENDOR_FROM_DATABASE=Third Planet Publishing pci:v00001338* ID_VENDOR_FROM_DATABASE=BT Electronics pci:v0000133A* ID_VENDOR_FROM_DATABASE=Vtel Corp pci:v0000133B* ID_VENDOR_FROM_DATABASE=Softcom Microsystems pci:v0000133C* ID_VENDOR_FROM_DATABASE=Holontech Corp pci:v0000133D* ID_VENDOR_FROM_DATABASE=SS Technologies pci:v0000133E* ID_VENDOR_FROM_DATABASE=Virtual Computer Corp pci:v0000133F* ID_VENDOR_FROM_DATABASE=SCM Microsystems pci:v00001340* ID_VENDOR_FROM_DATABASE=Atalla Corp pci:v00001341* ID_VENDOR_FROM_DATABASE=Kyoto Microcomputer Co pci:v00001342* ID_VENDOR_FROM_DATABASE=Promax Systems Inc pci:v00001343* ID_VENDOR_FROM_DATABASE=Phylon Communications Inc pci:v00001344* ID_VENDOR_FROM_DATABASE=Micron Technology Inc pci:v00001344d00005150* ID_MODEL_FROM_DATABASE=RealSSD P320h pci:v00001344d00005151* ID_MODEL_FROM_DATABASE=RealSSD P320m pci:v00001344d00005152* ID_MODEL_FROM_DATABASE=RealSSD P320s pci:v00001344d00005153* ID_MODEL_FROM_DATABASE=RealSSD P325m pci:v00001344d00005160* ID_MODEL_FROM_DATABASE=RealSSD P420h pci:v00001344d00005161* ID_MODEL_FROM_DATABASE=RealSSD P420m pci:v00001344d00005163* ID_MODEL_FROM_DATABASE=RealSSD P425m pci:v00001345* ID_VENDOR_FROM_DATABASE=Arescom Inc pci:v00001347* ID_VENDOR_FROM_DATABASE=Odetics pci:v00001349* ID_VENDOR_FROM_DATABASE=Sumitomo Electric Industries, Ltd. pci:v0000134A* ID_VENDOR_FROM_DATABASE=DTC Technology Corp. pci:v0000134Ad00000001* ID_MODEL_FROM_DATABASE=Domex 536 pci:v0000134Ad00000002* ID_MODEL_FROM_DATABASE=Domex DMX3194UP SCSI Adapter pci:v0000134B* ID_VENDOR_FROM_DATABASE=ARK Research Corp. pci:v0000134C* ID_VENDOR_FROM_DATABASE=Chori Joho System Co. Ltd pci:v0000134D* ID_VENDOR_FROM_DATABASE=PCTel Inc pci:v0000134Dd00002189* ID_MODEL_FROM_DATABASE=HSP56 MicroModem pci:v0000134Dd00002486* ID_MODEL_FROM_DATABASE=2304WT V.92 MDC Modem pci:v0000134Dd00007890* ID_MODEL_FROM_DATABASE=HSP MicroModem 56 pci:v0000134Dd00007890sv0000134Dsd00000001* ID_MODEL_FROM_DATABASE=HSP MicroModem 56 (PCT789 adapter) pci:v0000134Dd00007891* ID_MODEL_FROM_DATABASE=HSP MicroModem 56 pci:v0000134Dd00007891sv0000134Dsd00000001* ID_MODEL_FROM_DATABASE=HSP MicroModem 56 pci:v0000134Dd00007892* ID_MODEL_FROM_DATABASE=HSP MicroModem 56 pci:v0000134Dd00007893* ID_MODEL_FROM_DATABASE=HSP MicroModem 56 pci:v0000134Dd00007894* ID_MODEL_FROM_DATABASE=HSP MicroModem 56 pci:v0000134Dd00007895* ID_MODEL_FROM_DATABASE=HSP MicroModem 56 pci:v0000134Dd00007896* ID_MODEL_FROM_DATABASE=HSP MicroModem 56 pci:v0000134Dd00007897* ID_MODEL_FROM_DATABASE=HSP MicroModem 56 pci:v0000134E* ID_VENDOR_FROM_DATABASE=CSTI pci:v0000134F* ID_VENDOR_FROM_DATABASE=Algo System Co Ltd pci:v00001350* ID_VENDOR_FROM_DATABASE=Systec Co. Ltd pci:v00001351* ID_VENDOR_FROM_DATABASE=Sonix Inc pci:v00001353* ID_VENDOR_FROM_DATABASE=Vierling Communication SAS pci:v00001353d00000002* ID_MODEL_FROM_DATABASE=Proserver pci:v00001353d00000003* ID_MODEL_FROM_DATABASE=PCI-FUT pci:v00001353d00000004* ID_MODEL_FROM_DATABASE=PCI-S0 pci:v00001353d00000005* ID_MODEL_FROM_DATABASE=PCI-FUT-S0 pci:v00001354* ID_VENDOR_FROM_DATABASE=Dwave System Inc pci:v00001355* ID_VENDOR_FROM_DATABASE=Kratos Analytical Ltd pci:v00001356* ID_VENDOR_FROM_DATABASE=The Logical Co pci:v00001359* ID_VENDOR_FROM_DATABASE=Prisa Networks pci:v0000135A* ID_VENDOR_FROM_DATABASE=Brain Boxes pci:v0000135Ad00000A61* ID_MODEL_FROM_DATABASE=UC-324 [VELOCITY RS422/485] pci:v0000135B* ID_VENDOR_FROM_DATABASE=Giganet Inc pci:v0000135C* ID_VENDOR_FROM_DATABASE=Quatech Inc pci:v0000135Cd00000010* ID_MODEL_FROM_DATABASE=QSC-100 pci:v0000135Cd00000020* ID_MODEL_FROM_DATABASE=DSC-100 pci:v0000135Cd00000030* ID_MODEL_FROM_DATABASE=DSC-200/300 pci:v0000135Cd00000040* ID_MODEL_FROM_DATABASE=QSC-200/300 pci:v0000135Cd00000050* ID_MODEL_FROM_DATABASE=ESC-100D pci:v0000135Cd00000060* ID_MODEL_FROM_DATABASE=ESC-100M pci:v0000135Cd000000F0* ID_MODEL_FROM_DATABASE=MPAC-100 Syncronous Serial Card (Zilog 85230) pci:v0000135Cd00000170* ID_MODEL_FROM_DATABASE=QSCLP-100 pci:v0000135Cd00000180* ID_MODEL_FROM_DATABASE=DSCLP-100 pci:v0000135Cd00000190* ID_MODEL_FROM_DATABASE=SSCLP-100 pci:v0000135Cd000001A0* ID_MODEL_FROM_DATABASE=QSCLP-200/300 pci:v0000135Cd000001B0* ID_MODEL_FROM_DATABASE=DSCLP-200/300 pci:v0000135Cd000001C0* ID_MODEL_FROM_DATABASE=SSCLP-200/300 pci:v0000135Cd00000258* ID_MODEL_FROM_DATABASE=DSPSX-200/300 pci:v0000135D* ID_VENDOR_FROM_DATABASE=ABB Network Partner AB pci:v0000135E* ID_VENDOR_FROM_DATABASE=Sealevel Systems Inc pci:v0000135Ed00005101* ID_MODEL_FROM_DATABASE=Route 56.PCI - Multi-Protocol Serial Interface (Zilog Z16C32) pci:v0000135Ed00007101* ID_MODEL_FROM_DATABASE=Single Port RS-232/422/485/530 pci:v0000135Ed00007201* ID_MODEL_FROM_DATABASE=Dual Port RS-232/422/485 Interface pci:v0000135Ed00007202* ID_MODEL_FROM_DATABASE=Dual Port RS-232 Interface pci:v0000135Ed00007401* ID_MODEL_FROM_DATABASE=Four Port RS-232 Interface pci:v0000135Ed00007402* ID_MODEL_FROM_DATABASE=Four Port RS-422/485 Interface pci:v0000135Ed00007801* ID_MODEL_FROM_DATABASE=Eight Port RS-232 Interface pci:v0000135Ed00007804* ID_MODEL_FROM_DATABASE=Eight Port RS-232/422/485 Interface pci:v0000135Ed00008001* ID_MODEL_FROM_DATABASE=8001 Digital I/O Adapter pci:v0000135F* ID_VENDOR_FROM_DATABASE=I-Data International A-S pci:v00001360* ID_VENDOR_FROM_DATABASE=Meinberg Funkuhren pci:v00001360d00000101* ID_MODEL_FROM_DATABASE=PCI32 DCF77 Radio Clock pci:v00001360d00000102* ID_MODEL_FROM_DATABASE=PCI509 DCF77 Radio Clock pci:v00001360d00000103* ID_MODEL_FROM_DATABASE=PCI510 DCF77 Radio Clock pci:v00001360d00000104* ID_MODEL_FROM_DATABASE=PCI511 DCF77 Radio Clock pci:v00001360d00000105* ID_MODEL_FROM_DATABASE=PEX511 DCF77 Radio Clock (PCI Express) pci:v00001360d00000106* ID_MODEL_FROM_DATABASE=PZF180PEX High Precision DCF77 Radio Clock (PCI Express) pci:v00001360d00000201* ID_MODEL_FROM_DATABASE=GPS167PCI GPS Receiver pci:v00001360d00000202* ID_MODEL_FROM_DATABASE=GPS168PCI GPS Receiver pci:v00001360d00000203* ID_MODEL_FROM_DATABASE=GPS169PCI GPS Receiver pci:v00001360d00000204* ID_MODEL_FROM_DATABASE=GPS170PCI GPS Receiver pci:v00001360d00000205* ID_MODEL_FROM_DATABASE=GPS170PEX GPS Receiver (PCI Express) pci:v00001360d00000206* ID_MODEL_FROM_DATABASE=GPS180PEX GPS Receiver (PCI Express) pci:v00001360d00000207* ID_MODEL_FROM_DATABASE=GLN180PEX GPS/GLONASS receiver (PCI Express) pci:v00001360d00000208* ID_MODEL_FROM_DATABASE=GPS180AMC GPS Receiver (PCI Express / MicroTCA / AdvancedMC) pci:v00001360d00000301* ID_MODEL_FROM_DATABASE=TCR510PCI IRIG Timecode Reader pci:v00001360d00000302* ID_MODEL_FROM_DATABASE=TCR167PCI IRIG Timecode Reader pci:v00001360d00000303* ID_MODEL_FROM_DATABASE=TCR511PCI IRIG Timecode Reader pci:v00001360d00000304* ID_MODEL_FROM_DATABASE=TCR511PEX IRIG Timecode Reader (PCI Express) pci:v00001360d00000305* ID_MODEL_FROM_DATABASE=TCR170PEX IRIG Timecode Reader (PCI Express) pci:v00001360d00000306* ID_MODEL_FROM_DATABASE=TCR180PEX IRIG Timecode Reader (PCI Express) pci:v00001360d00000501* ID_MODEL_FROM_DATABASE=PTP270PEX PTP/IEEE1588 slave card (PCI Express) pci:v00001360d00000601* ID_MODEL_FROM_DATABASE=FRC511PEX Free Running Clock (PCI Express) pci:v00001361* ID_VENDOR_FROM_DATABASE=Soliton Systems K.K. pci:v00001362* ID_VENDOR_FROM_DATABASE=Fujifacom Corporation pci:v00001363* ID_VENDOR_FROM_DATABASE=Phoenix Technology Ltd pci:v00001364* ID_VENDOR_FROM_DATABASE=ATM Communications Inc pci:v00001365* ID_VENDOR_FROM_DATABASE=Hypercope GmbH pci:v00001366* ID_VENDOR_FROM_DATABASE=Teijin Seiki Co. Ltd pci:v00001367* ID_VENDOR_FROM_DATABASE=Hitachi Zosen Corporation pci:v00001368* ID_VENDOR_FROM_DATABASE=Skyware Corporation pci:v00001369* ID_VENDOR_FROM_DATABASE=Digigram pci:v0000136A* ID_VENDOR_FROM_DATABASE=High Soft Tech pci:v0000136Ad00000004* ID_MODEL_FROM_DATABASE=HST Saphir VII mini PCI pci:v0000136Ad00000007* ID_MODEL_FROM_DATABASE=HST Saphir III E MultiLink 4 pci:v0000136Ad00000008* ID_MODEL_FROM_DATABASE=HST Saphir III E MultiLink 8 pci:v0000136Ad0000000A* ID_MODEL_FROM_DATABASE=HST Saphir III E MultiLink 2 pci:v0000136B* ID_VENDOR_FROM_DATABASE=Kawasaki Steel Corporation pci:v0000136Bd0000FF01* ID_MODEL_FROM_DATABASE=KL5A72002 Motion JPEG pci:v0000136C* ID_VENDOR_FROM_DATABASE=Adtek System Science Co Ltd pci:v0000136D* ID_VENDOR_FROM_DATABASE=Gigalabs Inc pci:v0000136F* ID_VENDOR_FROM_DATABASE=Applied Magic Inc pci:v00001370* ID_VENDOR_FROM_DATABASE=ATL Products pci:v00001371* ID_VENDOR_FROM_DATABASE=CNet Technology Inc pci:v00001371d0000434E* ID_MODEL_FROM_DATABASE=GigaCard Network Adapter pci:v00001371d0000434Esv00001371sd0000434E* ID_MODEL_FROM_DATABASE=GigaCard Network Adapter (N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)) pci:v00001373* ID_VENDOR_FROM_DATABASE=Silicon Vision Inc pci:v00001374* ID_VENDOR_FROM_DATABASE=Silicom Ltd. pci:v00001374d00000024* ID_MODEL_FROM_DATABASE=Silicom Dual port Giga Ethernet BGE Bypass Server Adapter pci:v00001374d00000025* ID_MODEL_FROM_DATABASE=Silicom Quad port Giga Ethernet BGE Bypass Server Adapter pci:v00001374d00000026* ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber Giga Ethernet 546 Bypass Server Adapter pci:v00001374d00000027* ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber LX Giga Ethernet 546 Bypass Server Adapter pci:v00001374d00000029* ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Giga Ethernet 546GB Bypass Server Adapter pci:v00001374d0000002A* ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber Giga Ethernet 546 TAP/Bypass Server Adapter pci:v00001374d0000002B* ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Fast Ethernet 546 TAP/Bypass Server Adapter (PXE2TBI) pci:v00001374d0000002C* ID_MODEL_FROM_DATABASE=Silicom Quad port Copper Giga Ethernet 546GB Bypass Server Adapter (PXG4BPI) pci:v00001374d0000002D* ID_MODEL_FROM_DATABASE=Silicom Quad port Fiber-SX Giga Ethernet 546GB Bypass Server Adapter (PXG4BPFI) pci:v00001374d0000002E* ID_MODEL_FROM_DATABASE=Silicom Quad port Fiber-LX Giga Ethernet 546GB Bypass Server Adapter (PXG4BPFI-LX) pci:v00001374d0000002F* ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber-SX Giga Ethernet 546GB Low profile Bypass Server Adapter (PXG2BPFIL) pci:v00001374d00000030* ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber-LX Giga Ethernet 546GB Low profile Bypass Server Adapter pci:v00001374d00000031* ID_MODEL_FROM_DATABASE=Silicom Quad port Copper Giga Ethernet PCI-E Bypass Server Adapter pci:v00001374d00000032* ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Fast Ethernet 546 TAP/Bypass Server Adapter pci:v00001374d00000034* ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Giga Ethernet PCI-E BGE Bypass Server Adapter pci:v00001374d00000035* ID_MODEL_FROM_DATABASE=Silicom Quad port Copper Giga Ethernet PCI-E BGE Bypass Server Adapter pci:v00001374d00000036* ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber Giga Ethernet PCI-E BGE Bypass Server Adapter pci:v00001374d00000037* ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Ethernet PCI-E Intel based Bypass Server Adapter pci:v00001374d00000038* ID_MODEL_FROM_DATABASE=Silicom Quad port Copper Ethernet PCI-E Intel based Bypass Server Adapter pci:v00001374d00000039* ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber-SX Ethernet PCI-E Intel based Bypass Server Adapter pci:v00001374d0000003A* ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber-LX Ethernet PCI-E Intel based Bypass Server Adapter pci:v00001374d0000003B* ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber Ethernet PMC Intel based Bypass Server Adapter (PMCX2BPFI) pci:v00001374d0000003C* ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Ethernet PCI-X BGE based Bypass Server Adapter (PXG2BPRB) pci:v00001374d0000003D* ID_MODEL_FROM_DATABASE=2-port Copper GBE Bypass with Caviume 1010 PCI-X pci:v00001374d0000003E* ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber Giga Ethernet PCI-E 571 TAP/Bypass Server Adapter (PEG2TBFI) pci:v00001374d0000003F* ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Giga Ethernet PCI-X 546 TAP/Bypass Server Adapter (PXG2TBI) pci:v00001374d00000040* ID_MODEL_FROM_DATABASE=Silicom Quad port Fiber-SX Giga Ethernet 571 Bypass Server Adapter (PEG4BPFI) pci:v00001374d00000042* ID_MODEL_FROM_DATABASE=4-port Copper GBE PMC-X Bypass pci:v00001374d00000043* ID_MODEL_FROM_DATABASE=Silicom Quad port Fiber-SX Giga Ethernet 546 Bypass Server Adapter (PXG4BPFID) pci:v00001374d00000045* ID_MODEL_FROM_DATABASE=Silicom 6 port Copper Giga Ethernet 546 Bypass Server Adapter (PXG6BPI) pci:v00001374d00000046* ID_MODEL_FROM_DATABASE=4-port bypass PCI-E w disconnect low profile pci:v00001374d00000047* ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber-SX Giga Ethernet 571 Bypass Disconnect Server Adapter (PEG2BPFID) pci:v00001374d0000004A* ID_MODEL_FROM_DATABASE=Silicom Quad port Fiber-LX Giga Ethernet 571 Bypass Server Adapter (PEG4BPFI-LX) pci:v00001374d0000004D* ID_MODEL_FROM_DATABASE=Dual port Copper Giga Ethernet PCI-E Bypass Server Adapter pci:v00001374d00000401* ID_MODEL_FROM_DATABASE=Gigabit Ethernet ExpressModule Bypass Server Adapter pci:v00001374d00000420* ID_MODEL_FROM_DATABASE=Gigabit Ethernet ExpressModule Bypass Server Adapter pci:v00001374d00000460* ID_MODEL_FROM_DATABASE=Gigabit Ethernet Express Module Bypass Server Adapter pci:v00001374d00000461* ID_MODEL_FROM_DATABASE=Gigabit Ethernet ExpressModule Bypass Server Adapter pci:v00001374d00000462* ID_MODEL_FROM_DATABASE=Gigabit Ethernet ExpressModule Bypass Server Adapter pci:v00001374d00000470* ID_MODEL_FROM_DATABASE=Octal-port Copper Gigabit Ethernet Express Module Bypass Server Adapter pci:v00001374d00000482* ID_MODEL_FROM_DATABASE=Dual-port Fiber (SR) 10 Gigabit Ethernet ExpressModule Bypass Server Adapter pci:v00001374d00000483* ID_MODEL_FROM_DATABASE=Dual-port Fiber (LR) 10 Gigabit Ethernet ExpressModule Bypass Server Adapter pci:v00001375* ID_VENDOR_FROM_DATABASE=Argosystems Inc pci:v00001376* ID_VENDOR_FROM_DATABASE=LMC pci:v00001377* ID_VENDOR_FROM_DATABASE=Electronic Equipment Production & Distribution GmbH pci:v00001378* ID_VENDOR_FROM_DATABASE=Telemann Co. Ltd pci:v00001379* ID_VENDOR_FROM_DATABASE=Asahi Kasei Microsystems Co Ltd pci:v0000137A* ID_VENDOR_FROM_DATABASE=Mark of the Unicorn Inc pci:v0000137Ad00000001* ID_MODEL_FROM_DATABASE=PCI-324 Audiowire Interface pci:v0000137B* ID_VENDOR_FROM_DATABASE=PPT Vision pci:v0000137C* ID_VENDOR_FROM_DATABASE=Iwatsu Electric Co Ltd pci:v0000137D* ID_VENDOR_FROM_DATABASE=Dynachip Corporation pci:v0000137E* ID_VENDOR_FROM_DATABASE=Patriot Scientific Corporation pci:v0000137F* ID_VENDOR_FROM_DATABASE=Japan Satellite Systems Inc pci:v00001380* ID_VENDOR_FROM_DATABASE=Sanritz Automation Co Ltd pci:v00001381* ID_VENDOR_FROM_DATABASE=Brains Co. Ltd pci:v00001382* ID_VENDOR_FROM_DATABASE=Marian - Electronic & Software pci:v00001382d00000001* ID_MODEL_FROM_DATABASE=ARC88 audio recording card pci:v00001382d00002008* ID_MODEL_FROM_DATABASE=Prodif 96 Pro sound system pci:v00001382d00002048* ID_MODEL_FROM_DATABASE=Prodif Plus sound system pci:v00001382d00002088* ID_MODEL_FROM_DATABASE=Marc 8 Midi sound system pci:v00001382d000020C8* ID_MODEL_FROM_DATABASE=Marc A sound system pci:v00001382d00004008* ID_MODEL_FROM_DATABASE=Marc 2 sound system pci:v00001382d00004010* ID_MODEL_FROM_DATABASE=Marc 2 Pro sound system pci:v00001382d00004048* ID_MODEL_FROM_DATABASE=Marc 4 MIDI sound system pci:v00001382d00004088* ID_MODEL_FROM_DATABASE=Marc 4 Digi sound system pci:v00001382d00004248* ID_MODEL_FROM_DATABASE=Marc X sound system pci:v00001382d00004424* ID_MODEL_FROM_DATABASE=TRACE D4 Sound System pci:v00001383* ID_VENDOR_FROM_DATABASE=Controlnet Inc pci:v00001384* ID_VENDOR_FROM_DATABASE=Reality Simulation Systems Inc pci:v00001385* ID_VENDOR_FROM_DATABASE=Netgear pci:v00001385d0000006B* ID_MODEL_FROM_DATABASE=WA301 802.11b Wireless PCI Adapter pci:v00001385d00004100* ID_MODEL_FROM_DATABASE=MA301 802.11b Wireless PCI Adapter pci:v00001385d00004601* ID_MODEL_FROM_DATABASE=WAG511 802.11a/b/g Dual Band Wireless PC Card pci:v00001385d0000620A* ID_MODEL_FROM_DATABASE=GA620 Gigabit Ethernet pci:v00001385d0000630A* ID_MODEL_FROM_DATABASE=GA630 Gigabit Ethernet pci:v00001386* ID_VENDOR_FROM_DATABASE=Video Domain Technologies pci:v00001387* ID_VENDOR_FROM_DATABASE=Systran Corp pci:v00001388* ID_VENDOR_FROM_DATABASE=Hitachi Information Technology Co Ltd pci:v00001389* ID_VENDOR_FROM_DATABASE=Applicom International pci:v00001389d00000001* ID_MODEL_FROM_DATABASE=PCI1500PFB [Intelligent fieldbus adaptor] pci:v0000138A* ID_VENDOR_FROM_DATABASE=Fusion Micromedia Corp pci:v0000138Ad0000003D* ID_MODEL_FROM_DATABASE=VFS491 Validity Sensor pci:v0000138B* ID_VENDOR_FROM_DATABASE=Tokimec Inc pci:v0000138C* ID_VENDOR_FROM_DATABASE=Silicon Reality pci:v0000138D* ID_VENDOR_FROM_DATABASE=Future Techno Designs pte Ltd pci:v0000138E* ID_VENDOR_FROM_DATABASE=Basler GmbH pci:v0000138F* ID_VENDOR_FROM_DATABASE=Patapsco Designs Inc pci:v00001390* ID_VENDOR_FROM_DATABASE=Concept Development Inc pci:v00001391* ID_VENDOR_FROM_DATABASE=Development Concepts Inc pci:v00001392* ID_VENDOR_FROM_DATABASE=Medialight Inc pci:v00001393* ID_VENDOR_FROM_DATABASE=Moxa Technologies Co Ltd pci:v00001393d00000001* ID_MODEL_FROM_DATABASE=UC7000 Serial pci:v00001393d00001020* ID_MODEL_FROM_DATABASE=CP102 (2-port RS-232 PCI) pci:v00001393d00001021* ID_MODEL_FROM_DATABASE=CP102UL (2-port RS-232 Universal PCI) pci:v00001393d00001022* ID_MODEL_FROM_DATABASE=CP102U (2-port RS-232 Universal PCI) pci:v00001393d00001023* ID_MODEL_FROM_DATABASE=CP-102UF pci:v00001393d00001024* ID_MODEL_FROM_DATABASE=CP-102E (2-port RS-232 Smart PCI Express Serial Board) pci:v00001393d00001025* ID_MODEL_FROM_DATABASE=CP-102EL (2-port RS-232 Smart PCI Express Serial Board) pci:v00001393d00001040* ID_MODEL_FROM_DATABASE=Smartio C104H/PCI pci:v00001393d00001041* ID_MODEL_FROM_DATABASE=CP104U (4-port RS-232 Universal PCI) pci:v00001393d00001042* ID_MODEL_FROM_DATABASE=CP104JU (4-port RS-232 Universal PCI) pci:v00001393d00001043* ID_MODEL_FROM_DATABASE=CP104EL (4-port RS-232 Smart PCI Express) pci:v00001393d00001044* ID_MODEL_FROM_DATABASE=POS104UL (4-port RS-232 Universal PCI) pci:v00001393d00001045* ID_MODEL_FROM_DATABASE=CP-104EL-A (4-port RS-232 PCI Express Serial Board) pci:v00001393d00001080* ID_MODEL_FROM_DATABASE=CB108 (8-port RS-232 PC/104-plus Module) pci:v00001393d00001140* ID_MODEL_FROM_DATABASE=CT-114 series pci:v00001393d00001141* ID_MODEL_FROM_DATABASE=Industrio CP-114 pci:v00001393d00001142* ID_MODEL_FROM_DATABASE=CB114 (4-port RS-232/422/485 PC/104-plus Module) pci:v00001393d00001143* ID_MODEL_FROM_DATABASE=CP-114UL (4-port RS-232/422/485 Smart Universal PCI Serial Board) pci:v00001393d00001144* ID_MODEL_FROM_DATABASE=CP-114EL (4-port RS-232/422/485 Smart PCI Express Serial Board) pci:v00001393d00001180* ID_MODEL_FROM_DATABASE=CP118U (8-port RS-232/422/485 Smart Universal PCI) pci:v00001393d00001181* ID_MODEL_FROM_DATABASE=CP118EL (8-port RS-232/422/485 Smart PCI Express) pci:v00001393d00001182* ID_MODEL_FROM_DATABASE=CP-118EL-A (8-port RS-232/422/485 PCI Express Serial Board) pci:v00001393d00001320* ID_MODEL_FROM_DATABASE=CP132 (2-port RS-422/485 PCI) pci:v00001393d00001321* ID_MODEL_FROM_DATABASE=CP132U (2-Port RS-422/485 Universal PCI) pci:v00001393d00001322* ID_MODEL_FROM_DATABASE=CP-132EL (2-port RS-422/485 Smart PCI Express Serial Board) pci:v00001393d00001340* ID_MODEL_FROM_DATABASE=CP134U (4-Port RS-422/485 Universal PCI) pci:v00001393d00001341* ID_MODEL_FROM_DATABASE=CB134I (4-port RS-422/485 PC/104-plus Module) pci:v00001393d00001380* ID_MODEL_FROM_DATABASE=CP138U (8-port RS-232/422/485 Smart Universal PCI) pci:v00001393d00001680* ID_MODEL_FROM_DATABASE=Smartio C168H/PCI pci:v00001393d00001681* ID_MODEL_FROM_DATABASE=CP-168U V2 Smart Serial Board (8-port RS-232) pci:v00001393d00001682* ID_MODEL_FROM_DATABASE=CP168EL (8-port RS-232 Smart PCI Express) pci:v00001393d00001683* ID_MODEL_FROM_DATABASE=CP-168EL-A (8-port RS-232 PCI Express Serial Board) pci:v00001393d00002040* ID_MODEL_FROM_DATABASE=Intellio CP-204J pci:v00001393d00002180* ID_MODEL_FROM_DATABASE=Intellio C218 Turbo PCI pci:v00001393d00003200* ID_MODEL_FROM_DATABASE=Intellio C320 Turbo PCI pci:v00001394* ID_VENDOR_FROM_DATABASE=Level One Communications pci:v00001394d00000001* ID_MODEL_FROM_DATABASE=LXT1001 Gigabit Ethernet pci:v00001394d00000001sv00001186sd00004800* ID_MODEL_FROM_DATABASE=LXT1001 Gigabit Ethernet (DGE-500SX) pci:v00001394d00000001sv00001394sd00000001* ID_MODEL_FROM_DATABASE=LXT1001 Gigabit Ethernet (NetCelerator Adapter) pci:v00001395* ID_VENDOR_FROM_DATABASE=Ambicom Inc pci:v00001396* ID_VENDOR_FROM_DATABASE=Cipher Systems Inc pci:v00001397* ID_VENDOR_FROM_DATABASE=Cologne Chip Designs GmbH pci:v00001397d000008B4* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] pci:v00001397d000008B4sv00001397sd000008B4* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Cologne Chip HFC-4S Eval. Board]) pci:v00001397d000008B4sv00001397sd0000B51A* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Allo.com BRI card]) pci:v00001397d000008B4sv00001397sd0000B520* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [IOB4ST]) pci:v00001397d000008B4sv00001397sd0000B540* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Swyx SX2 QuadBri]) pci:v00001397d000008B4sv00001397sd0000B550* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Junghanns.NET quadBRI]) pci:v00001397d000008B4sv00001397sd0000B556* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Junghanns.NET duoBRI]) pci:v00001397d000008B4sv00001397sd0000B559* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Junghanns.NET duoBRI miniPCI]) pci:v00001397d000008B4sv00001397sd0000B560* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN4S0]) pci:v00001397d000008B4sv00001397sd0000B566* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN2S0]) pci:v00001397d000008B4sv00001397sd0000B567* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN1S0 miniPCI]) pci:v00001397d000008B4sv00001397sd0000B568* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN4S0 miniPCI]) pci:v00001397d000008B4sv00001397sd0000B569* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN2S0 miniPCI]) pci:v00001397d000008B4sv00001397sd0000B620* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S) pci:v00001397d000008B4sv00001397sd0000B752* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Junghanns.NET quadBRI PCIe]) pci:v00001397d000008B4sv00001397sd0000B761* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN2S0 PCIe]) pci:v00001397d000008B4sv00001397sd0000B762* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN4S0 PCIe]) pci:v00001397d000008B4sv00001397sd0000E884* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [OpenVox B200P]) pci:v00001397d000008B4sv00001397sd0000E888* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [OpenVox B200P / B400P]) pci:v00001397d000016B8* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] pci:v00001397d000016B8sv00001397sd000016B8* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [Cologne Chip HFC-8S Eval. Board]) pci:v00001397d000016B8sv00001397sd0000B521* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [IOB4ST Recording]) pci:v00001397d000016B8sv00001397sd0000B522* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [IOB8ST]) pci:v00001397d000016B8sv00001397sd0000B552* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [Junghanns.NET octoBRI]) pci:v00001397d000016B8sv00001397sd0000B55B* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [Junghanns.NET octoBRI]) pci:v00001397d000016B8sv00001397sd0000B562* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [BeroNet BN8S0]) pci:v00001397d000016B8sv00001397sd0000B56B* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [BeroNet BN8S0+]) pci:v00001397d000016B8sv00001397sd0000B622* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S) pci:v00001397d000016B8sv00001397sd0000E998* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [OpenVox B800P]) pci:v00001397d00002BD0* ID_MODEL_FROM_DATABASE=ISDN network controller [HFC-PCI] pci:v00001397d00002BD0sv00000675sd00001704* ID_MODEL_FROM_DATABASE=ISDN network controller [HFC-PCI] (ISDN Adapter (PCI Bus, D, C)) pci:v00001397d00002BD0sv00000675sd00001708* ID_MODEL_FROM_DATABASE=ISDN network controller [HFC-PCI] (ISDN Adapter (PCI Bus, D, C, ACPI)) pci:v00001397d00002BD0sv00001397sd00002BD0* ID_MODEL_FROM_DATABASE=ISDN network controller [HFC-PCI] (ISDN Board) pci:v00001397d00002BD0sv0000E4BFsd00001000* ID_MODEL_FROM_DATABASE=ISDN network controller [HFC-PCI] (CI1-1-Harp) pci:v00001397d000030B1* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] pci:v00001397d000030B1sv00001397sd000030B1* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Cologne Chip HFC-E1 Eval. Board]) pci:v00001397d000030B1sv00001397sd0000B523* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [IOB1E1]) pci:v00001397d000030B1sv00001397sd0000B543* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Swyx SX2 SinglePRI V2]) pci:v00001397d000030B1sv00001397sd0000B544* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Swyx SX2 DualPRI V2]) pci:v00001397d000030B1sv00001397sd0000B553* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Junghanns.NET singleE1]) pci:v00001397d000030B1sv00001397sd0000B554* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Junghanns.NET doubleE1]) pci:v00001397d000030B1sv00001397sd0000B555* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Junghanns.NET doubleE1 2.0]) pci:v00001397d000030B1sv00001397sd0000B55A* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Junghanns.NET singleE1 miniPCI]) pci:v00001397d000030B1sv00001397sd0000B563* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [beroNet BN1E1]) pci:v00001397d000030B1sv00001397sd0000B564* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [beroNet BN2E1]) pci:v00001397d000030B1sv00001397sd0000B565* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [beroNet BN2E1+]) pci:v00001397d000030B1sv00001397sd0000B56A* ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [beroNet BN1E1 miniPCI]) pci:v00001397d0000B700* ID_MODEL_FROM_DATABASE=ISDN network controller PrimuX S0 [HFC-PCI] pci:v00001397d0000F001* ID_MODEL_FROM_DATABASE=GSM Network Controller [HFC-4GSM] pci:v00001398* ID_VENDOR_FROM_DATABASE=Clarion co. Ltd pci:v00001399* ID_VENDOR_FROM_DATABASE=Rios systems Co Ltd pci:v0000139A* ID_VENDOR_FROM_DATABASE=Alacritech Inc pci:v0000139Ad00000001* ID_MODEL_FROM_DATABASE=Quad Port 10/100 Server Accelerator pci:v0000139Ad00000003* ID_MODEL_FROM_DATABASE=Single Port 10/100 Server Accelerator pci:v0000139Ad00000005* ID_MODEL_FROM_DATABASE=Single Port Gigabit Server Accelerator pci:v0000139B* ID_VENDOR_FROM_DATABASE=Mediasonic Multimedia Systems Ltd pci:v0000139C* ID_VENDOR_FROM_DATABASE=Quantum 3d Inc pci:v0000139D* ID_VENDOR_FROM_DATABASE=EPL limited pci:v0000139E* ID_VENDOR_FROM_DATABASE=Media4 pci:v0000139F* ID_VENDOR_FROM_DATABASE=Aethra s.r.l. pci:v000013A0* ID_VENDOR_FROM_DATABASE=Crystal Group Inc pci:v000013A1* ID_VENDOR_FROM_DATABASE=Kawasaki Heavy Industries Ltd pci:v000013A2* ID_VENDOR_FROM_DATABASE=Ositech Communications Inc pci:v000013A3* ID_VENDOR_FROM_DATABASE=Hifn Inc. pci:v000013A3d00000005* ID_MODEL_FROM_DATABASE=7751 Security Processor pci:v000013A3d00000006* ID_MODEL_FROM_DATABASE=6500 Public Key Processor pci:v000013A3d00000007* ID_MODEL_FROM_DATABASE=7811 Security Processor pci:v000013A3d00000012* ID_MODEL_FROM_DATABASE=7951 Security Processor pci:v000013A3d00000014* ID_MODEL_FROM_DATABASE=78XX Security Processor pci:v000013A3d00000016* ID_MODEL_FROM_DATABASE=8065 Security Processor pci:v000013A3d00000017* ID_MODEL_FROM_DATABASE=8165 Security Processor pci:v000013A3d00000018* ID_MODEL_FROM_DATABASE=8154 Security Processor pci:v000013A3d0000001D* ID_MODEL_FROM_DATABASE=7956 Security Processor pci:v000013A3d0000001F* ID_MODEL_FROM_DATABASE=7855 Security Processor pci:v000013A3d00000020* ID_MODEL_FROM_DATABASE=7955 Security Processor pci:v000013A3d00000026* ID_MODEL_FROM_DATABASE=8155 Security Processor pci:v000013A3d0000002E* ID_MODEL_FROM_DATABASE=9630 Compression Processor pci:v000013A3d0000002F* ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor pci:v000013A3d0000002Fsv000013A3sd00001600* ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor (DR1600 Acceleration Card) pci:v000013A3d0000002Fsv000013A3sd00001605* ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor (DR1605 Acceleration Card) pci:v000013A3d0000002Fsv000013A3sd00001610* ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor (DR1610 Acceleration Card) pci:v000013A3d0000002Fsv000013A3sd00001615* ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor (DR1615 Acceleration Card) pci:v000013A3d0000002Fsv000013A3sd00001620* ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor (DR1620 Acceleration Card) pci:v000013A3d0000002Fsv000013A3sd00001625* ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor (DR1625 Acceleration Card) pci:v000013A3d00000033* ID_MODEL_FROM_DATABASE=8201 Acceleration Processor pci:v000013A3d00000033sv000013A3sd00000036* ID_MODEL_FROM_DATABASE=8201 Acceleration Processor (DX1710 Acceleration Card) pci:v000013A3d00000034* ID_MODEL_FROM_DATABASE=8202 Acceleration Processor pci:v000013A3d00000034sv000013A3sd00000036* ID_MODEL_FROM_DATABASE=8202 Acceleration Processor (DX1720 Acceleration Card) pci:v000013A3d00000035* ID_MODEL_FROM_DATABASE=8203 Acceleration Processor pci:v000013A3d00000035sv000013A3sd00000036* ID_MODEL_FROM_DATABASE=8203 Acceleration Processor (DX1730 Acceleration Card) pci:v000013A3d00000037* ID_MODEL_FROM_DATABASE=8204 Acceleration Processor pci:v000013A3d00000037sv000013A3sd00000036* ID_MODEL_FROM_DATABASE=8204 Acceleration Processor (DX1740 Acceleration Card) pci:v000013A4* ID_VENDOR_FROM_DATABASE=Rascom Inc pci:v000013A5* ID_VENDOR_FROM_DATABASE=Audio Digital Imaging Inc pci:v000013A6* ID_VENDOR_FROM_DATABASE=Videonics Inc pci:v000013A7* ID_VENDOR_FROM_DATABASE=Teles AG pci:v000013A8* ID_VENDOR_FROM_DATABASE=Exar Corp. pci:v000013A8d00000152* ID_MODEL_FROM_DATABASE=XR17C/D152 Dual PCI UART pci:v000013A8d00000154* ID_MODEL_FROM_DATABASE=XR17C154 Quad UART pci:v000013A8d00000158* ID_MODEL_FROM_DATABASE=XR17C158 Octal UART pci:v000013A8d00000252* ID_MODEL_FROM_DATABASE=XR17V252 Dual UART PCI controller pci:v000013A8d00000254* ID_MODEL_FROM_DATABASE=XR17V254 Quad UART PCI controller pci:v000013A8d00000258* ID_MODEL_FROM_DATABASE=XR17V258 Octal UART PCI controller pci:v000013A9* ID_VENDOR_FROM_DATABASE=Siemens Medical Systems, Ultrasound Group pci:v000013AA* ID_VENDOR_FROM_DATABASE=Broadband Networks Inc pci:v000013AB* ID_VENDOR_FROM_DATABASE=Arcom Control Systems Ltd pci:v000013AC* ID_VENDOR_FROM_DATABASE=Motion Media Technology Ltd pci:v000013AD* ID_VENDOR_FROM_DATABASE=Nexus Inc pci:v000013AE* ID_VENDOR_FROM_DATABASE=ALD Technology Ltd pci:v000013AF* ID_VENDOR_FROM_DATABASE=T.Sqware pci:v000013B0* ID_VENDOR_FROM_DATABASE=Maxspeed Corp pci:v000013B1* ID_VENDOR_FROM_DATABASE=Tamura corporation pci:v000013B2* ID_VENDOR_FROM_DATABASE=Techno Chips Co. Ltd pci:v000013B3* ID_VENDOR_FROM_DATABASE=Lanart Corporation pci:v000013B4* ID_VENDOR_FROM_DATABASE=Wellbean Co Inc pci:v000013B5* ID_VENDOR_FROM_DATABASE=ARM pci:v000013B6* ID_VENDOR_FROM_DATABASE=Dlog GmbH pci:v000013B7* ID_VENDOR_FROM_DATABASE=Logic Devices Inc pci:v000013B8* ID_VENDOR_FROM_DATABASE=Nokia Telecommunications oy pci:v000013B9* ID_VENDOR_FROM_DATABASE=Elecom Co Ltd pci:v000013BA* ID_VENDOR_FROM_DATABASE=Oxford Instruments pci:v000013BB* ID_VENDOR_FROM_DATABASE=Sanyo Technosound Co Ltd pci:v000013BC* ID_VENDOR_FROM_DATABASE=Bitran Corporation pci:v000013BD* ID_VENDOR_FROM_DATABASE=Sharp corporation pci:v000013BE* ID_VENDOR_FROM_DATABASE=Miroku Jyoho Service Co. Ltd pci:v000013BF* ID_VENDOR_FROM_DATABASE=Sharewave Inc pci:v000013C0* ID_VENDOR_FROM_DATABASE=Microgate Corporation pci:v000013C0d00000010* ID_MODEL_FROM_DATABASE=SyncLink Adapter v1 pci:v000013C0d00000020* ID_MODEL_FROM_DATABASE=SyncLink SCC Adapter pci:v000013C0d00000030* ID_MODEL_FROM_DATABASE=SyncLink Multiport Adapter pci:v000013C0d00000070* ID_MODEL_FROM_DATABASE=SyncLink GT Adapter pci:v000013C0d00000080* ID_MODEL_FROM_DATABASE=SyncLink GT4 Adapter pci:v000013C0d000000A0* ID_MODEL_FROM_DATABASE=SyncLink GT2 Adapter pci:v000013C0d00000210* ID_MODEL_FROM_DATABASE=SyncLink Adapter v2 pci:v000013C1* ID_VENDOR_FROM_DATABASE=3ware Inc pci:v000013C1d00001000* ID_MODEL_FROM_DATABASE=5xxx/6xxx-series PATA-RAID pci:v000013C1d00001001* ID_MODEL_FROM_DATABASE=7xxx/8xxx-series PATA/SATA-RAID pci:v000013C1d00001001sv000013C1sd00001001* ID_MODEL_FROM_DATABASE=7xxx/8xxx-series PATA/SATA-RAID pci:v000013C1d00001002* ID_MODEL_FROM_DATABASE=9xxx-series SATA-RAID pci:v000013C1d00001003* ID_MODEL_FROM_DATABASE=9550SX SATA-II RAID PCI-X pci:v000013C1d00001004* ID_MODEL_FROM_DATABASE=9650SE SATA-II RAID PCIe pci:v000013C1d00001005* ID_MODEL_FROM_DATABASE=9690SA SAS/SATA-II RAID PCIe pci:v000013C1d00001010* ID_MODEL_FROM_DATABASE=9750 SAS2/SATA-II RAID PCIe pci:v000013C2* ID_VENDOR_FROM_DATABASE=Technotrend Systemtechnik GmbH pci:v000013C2d0000000E* ID_MODEL_FROM_DATABASE=Technotrend/Hauppauge DVB card rev2.3 pci:v000013C2d00001019* ID_MODEL_FROM_DATABASE=TTechnoTrend-budget DVB S2-3200 pci:v000013C3* ID_VENDOR_FROM_DATABASE=Janz Computer AG pci:v000013C4* ID_VENDOR_FROM_DATABASE=Phase Metrics pci:v000013C5* ID_VENDOR_FROM_DATABASE=Alphi Technology Corp pci:v000013C6* ID_VENDOR_FROM_DATABASE=Condor Engineering Inc pci:v000013C6d00000520* ID_MODEL_FROM_DATABASE=CEI-520 A429 Card pci:v000013C6d00000620* ID_MODEL_FROM_DATABASE=CEI-620 A429 Card pci:v000013C6d00000820* ID_MODEL_FROM_DATABASE=CEI-820 A429 Card pci:v000013C6d00000830* ID_MODEL_FROM_DATABASE=CEI-830 A429 Card pci:v000013C6d00001004* ID_MODEL_FROM_DATABASE=P-SER Multi-channel PMC to RS-485/422/232 adapter pci:v000013C7* ID_VENDOR_FROM_DATABASE=Blue Chip Technology Ltd pci:v000013C7d00000ADC* ID_MODEL_FROM_DATABASE=PCI-ADC pci:v000013C7d00000B10* ID_MODEL_FROM_DATABASE=PCI-PIO pci:v000013C7d00000D10* ID_MODEL_FROM_DATABASE=PCI-DIO pci:v000013C7d0000524C* ID_MODEL_FROM_DATABASE=PCI-RLY pci:v000013C7d00005744* ID_MODEL_FROM_DATABASE=PCI-WDT pci:v000013C8* ID_VENDOR_FROM_DATABASE=Apptech Inc pci:v000013C9* ID_VENDOR_FROM_DATABASE=Eaton Corporation pci:v000013CA* ID_VENDOR_FROM_DATABASE=Iomega Corporation pci:v000013CB* ID_VENDOR_FROM_DATABASE=Yano Electric Co Ltd pci:v000013CC* ID_VENDOR_FROM_DATABASE=Metheus Corporation pci:v000013CD* ID_VENDOR_FROM_DATABASE=Compatible Systems Corporation pci:v000013CE* ID_VENDOR_FROM_DATABASE=Cocom A/S pci:v000013CF* ID_VENDOR_FROM_DATABASE=Studio Audio & Video Ltd pci:v000013D0* ID_VENDOR_FROM_DATABASE=Techsan Electronics Co Ltd pci:v000013D0d00002103* ID_MODEL_FROM_DATABASE=B2C2 FlexCopII DVB chip / Technisat SkyStar2 DVB card pci:v000013D0d00002104* ID_MODEL_FROM_DATABASE=B2C2 FlexCopIII DVB chip / Technisat SkyStar2 DVB card (rev 01) pci:v000013D0d00002200* ID_MODEL_FROM_DATABASE=B2C2 FlexCopIII DVB chip / Technisat SkyStar2 DVB card pci:v000013D1* ID_VENDOR_FROM_DATABASE=Abocom Systems Inc pci:v000013D1d0000AB02* ID_MODEL_FROM_DATABASE=ADMtek Centaur-C rev 17 [D-Link DFE-680TX] CardBus Fast Ethernet Adapter pci:v000013D1d0000AB03* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet pci:v000013D1d0000AB06* ID_MODEL_FROM_DATABASE=RTL8139 [FE2000VX] CardBus Fast Ethernet Attached Port Adapter pci:v000013D1d0000AB08* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet pci:v000013D2* ID_VENDOR_FROM_DATABASE=Shark Multimedia Inc pci:v000013D4* ID_VENDOR_FROM_DATABASE=Graphics Microsystems Inc pci:v000013D5* ID_VENDOR_FROM_DATABASE=Media 100 Inc pci:v000013D6* ID_VENDOR_FROM_DATABASE=K.I. Technology Co Ltd pci:v000013D7* ID_VENDOR_FROM_DATABASE=Toshiba Engineering Corporation pci:v000013D8* ID_VENDOR_FROM_DATABASE=Phobos corporation pci:v000013D9* ID_VENDOR_FROM_DATABASE=Apex PC Solutions Inc pci:v000013DA* ID_VENDOR_FROM_DATABASE=Intresource Systems pte Ltd pci:v000013DB* ID_VENDOR_FROM_DATABASE=Janich & Klass Computertechnik GmbH pci:v000013DC* ID_VENDOR_FROM_DATABASE=Netboost Corporation pci:v000013DD* ID_VENDOR_FROM_DATABASE=Multimedia Bundle Inc pci:v000013DE* ID_VENDOR_FROM_DATABASE=ABB Robotics Products AB pci:v000013DF* ID_VENDOR_FROM_DATABASE=E-Tech Inc pci:v000013DFd00000001* ID_MODEL_FROM_DATABASE=PCI56RVP Modem pci:v000013DFd00000001sv000013DFsd00000001* ID_MODEL_FROM_DATABASE=PCI56RVP Modem pci:v000013E0* ID_VENDOR_FROM_DATABASE=GVC Corporation pci:v000013E1* ID_VENDOR_FROM_DATABASE=Silicom Multimedia Systems Inc pci:v000013E2* ID_VENDOR_FROM_DATABASE=Dynamics Research Corporation pci:v000013E3* ID_VENDOR_FROM_DATABASE=Nest Inc pci:v000013E4* ID_VENDOR_FROM_DATABASE=Calculex Inc pci:v000013E5* ID_VENDOR_FROM_DATABASE=Telesoft Design Ltd pci:v000013E6* ID_VENDOR_FROM_DATABASE=Argosy research Inc pci:v000013E7* ID_VENDOR_FROM_DATABASE=NAC Incorporated pci:v000013E8* ID_VENDOR_FROM_DATABASE=Chip Express Corporation pci:v000013E9* ID_VENDOR_FROM_DATABASE=Intraserver Technology Inc pci:v000013EA* ID_VENDOR_FROM_DATABASE=Dallas Semiconductor pci:v000013EB* ID_VENDOR_FROM_DATABASE=Hauppauge Computer Works Inc pci:v000013EC* ID_VENDOR_FROM_DATABASE=Zydacron Inc pci:v000013ECd0000000A* ID_MODEL_FROM_DATABASE=NPC-RC01 Remote control receiver pci:v000013ED* ID_VENDOR_FROM_DATABASE=Raytheion E-Systems pci:v000013EE* ID_VENDOR_FROM_DATABASE=Hayes Microcomputer Products Inc pci:v000013EF* ID_VENDOR_FROM_DATABASE=Coppercom Inc pci:v000013F0* ID_VENDOR_FROM_DATABASE=Sundance Technology Inc / IC Plus Corp pci:v000013F0d00000200* ID_MODEL_FROM_DATABASE=IC Plus IP100A Integrated 10/100 Ethernet MAC + PHY pci:v000013F0d00000200sv00001043sd00008213* ID_MODEL_FROM_DATABASE=IC Plus IP100A Integrated 10/100 Ethernet MAC + PHY (NX1001) pci:v000013F0d00000201* ID_MODEL_FROM_DATABASE=ST201 Sundance Ethernet pci:v000013F0d00001021* ID_MODEL_FROM_DATABASE=TC902x Gigabit Ethernet pci:v000013F0d00001023* ID_MODEL_FROM_DATABASE=IP1000 Family Gigabit Ethernet pci:v000013F0d00001023sv00001043sd00008180* ID_MODEL_FROM_DATABASE=IP1000 Family Gigabit Ethernet (NX1101) pci:v000013F1* ID_VENDOR_FROM_DATABASE=Oce' - Technologies B.V. pci:v000013F2* ID_VENDOR_FROM_DATABASE=Ford Microelectronics Inc pci:v000013F3* ID_VENDOR_FROM_DATABASE=Mcdata Corporation pci:v000013F4* ID_VENDOR_FROM_DATABASE=Troika Networks, Inc. pci:v000013F4d00001401* ID_MODEL_FROM_DATABASE=Zentai Fibre Channel Adapter pci:v000013F5* ID_VENDOR_FROM_DATABASE=Kansai Electric Co. Ltd pci:v000013F6* ID_VENDOR_FROM_DATABASE=C-Media Electronics Inc pci:v000013F6d00000011* ID_MODEL_FROM_DATABASE=CMI8738 pci:v000013F6d00000100* ID_MODEL_FROM_DATABASE=CM8338A pci:v000013F6d00000100sv000013F6sd0000FFFF* ID_MODEL_FROM_DATABASE=CM8338A (CMI8338/C3DX PCI Audio Device) pci:v000013F6d00000101* ID_MODEL_FROM_DATABASE=CM8338B pci:v000013F6d00000101sv000013F6sd00000101* ID_MODEL_FROM_DATABASE=CM8338B (CMI8338-031 PCI Audio Device) pci:v000013F6d00000111* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio pci:v000013F6d00000111sv00001019sd00000970* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (P6STP-FL motherboard) pci:v000013F6d00000111sv00001043sd00008035* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (CUSI-FX motherboard) pci:v000013F6d00000111sv00001043sd00008077* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (CMI8738 6-channel audio controller) pci:v000013F6d00000111sv00001043sd000080E2* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (CMI8738 6ch-MX) pci:v000013F6d00000111sv000013F6sd00000111* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (CMI8738/C3DX PCI Audio Device) pci:v000013F6d00000111sv000013F6sd00009761* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (Theatron Agrippa) pci:v000013F6d00000111sv0000153Bsd00001144* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (Aureon 5.1) pci:v000013F6d00000111sv0000153Bsd00001170* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (Aureon 7.1) pci:v000013F6d00000111sv00001681sd0000A000* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (Gamesurround MUSE XL) pci:v000013F6d00000111sv000017ABsd00000604* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (PSC604 Dynamic Edge) pci:v000013F6d00000111sv000017ABsd00000605* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (PSC605 Sonic Edge) pci:v000013F6d00000111sv000017ABsd00007777* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (PSC605 Sonic Edge) pci:v000013F6d00000111sv0000270Fsd00001103* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (CT-7NJS Ultra motherboard) pci:v000013F6d00000111sv0000270Fsd0000F462* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (7NJL1 motherboard) pci:v000013F6d00000111sv0000584Dsd00003731* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (Digital X-Mystique) pci:v000013F6d00000111sv0000584Dsd00003741* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (X-Plosion 7.1) pci:v000013F6d00000111sv0000584Dsd00003751* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (X-Raider 7.1) pci:v000013F6d00000111sv0000584Dsd00003761* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (X-Mystique 7.1 LP) pci:v000013F6d00000111sv0000584Dsd00003771* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (X-Mystique 7.1 LP Value) pci:v000013F6d00000111sv00007284sd00008384* ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (Striker 7.1) pci:v000013F6d00000211* ID_MODEL_FROM_DATABASE=CM8738 pci:v000013F6d00005011* ID_MODEL_FROM_DATABASE=CM8888 [Oxygen Express] pci:v000013F6d00005011sv000013F6sd00005011* ID_MODEL_FROM_DATABASE=CM8888 [Oxygen Express] (HDA Controller) pci:v000013F6d00008788* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] pci:v000013F6d00008788sv00001043sd00008269* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 200 (Xonar D2)) pci:v000013F6d00008788sv00001043sd00008275* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar DX)) pci:v000013F6d00008788sv00001043sd000082B7* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 200 (Xonar D2X)) pci:v000013F6d00008788sv00001043sd00008314* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 200 (Xonar HDAV1.3)) pci:v000013F6d00008788sv00001043sd00008327* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar DX)) pci:v000013F6d00008788sv00001043sd0000834F* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar D1)) pci:v000013F6d00008788sv00001043sd0000835C* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar Essence STX)) pci:v000013F6d00008788sv00001043sd0000835D* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar ST)) pci:v000013F6d00008788sv00001043sd0000835E* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 200 (Xonar HDAV1.3 Slim)) pci:v000013F6d00008788sv00001043sd0000838E* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 66 (Xonar DS)) pci:v000013F6d00008788sv00001043sd00008428* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar Xense)) pci:v000013F6d00008788sv00001043sd00008467* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (CMI8786 (Xonar DG)) pci:v000013F6d00008788sv00001043sd000085F4* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar Essence STX II)) pci:v000013F6d00008788sv000013F6sd00008782* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (PCI 2.0 HD Audio) pci:v000013F6d00008788sv000013F6sd0000FFFF* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (CMI8787-HG2PCI) pci:v000013F6d00008788sv000014C3sd00001710* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (HiFier Fantasia) pci:v000013F6d00008788sv000014C3sd00001711* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (HiFier Serenade) pci:v000013F6d00008788sv000014C3sd00001713* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (HiFier Serenade III) pci:v000013F6d00008788sv00001A58sd00000910* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Barracuda AC-1) pci:v000013F6d00008788sv0000415Asd00005431* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (X-Meridian 7.1) pci:v000013F6d00008788sv00005431sd0000017A* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (X-Meridian 7.1 2G) pci:v000013F6d00008788sv0000584Dsd00003781* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (HDA X-Purity 7.1 Platinum) pci:v000013F6d00008788sv00007284sd00009761* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (CLARO) pci:v000013F6d00008788sv00007284sd00009781* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (CLARO halo) pci:v000013F6d00008788sv00007284sd00009783* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (eCLARO) pci:v000013F6d00008788sv00007284sd00009787* ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (CLARO II) pci:v000013F7* ID_VENDOR_FROM_DATABASE=Wildfire Communications pci:v000013F8* ID_VENDOR_FROM_DATABASE=Ad Lib Multimedia Inc pci:v000013F9* ID_VENDOR_FROM_DATABASE=NTT Advanced Technology Corp. pci:v000013FA* ID_VENDOR_FROM_DATABASE=Pentland Systems Ltd pci:v000013FB* ID_VENDOR_FROM_DATABASE=Aydin Corp pci:v000013FC* ID_VENDOR_FROM_DATABASE=Computer Peripherals International pci:v000013FD* ID_VENDOR_FROM_DATABASE=Micro Science Inc pci:v000013FE* ID_VENDOR_FROM_DATABASE=Advantech Co. Ltd pci:v000013FEd00001240* ID_MODEL_FROM_DATABASE=PCI-1240 4-channel stepper motor controller card pci:v000013FEd00001600* ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 0) pci:v000013FEd00001600sv00001601sd00000002* ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 0) (PCI-1601 2-port unisolated RS-422/485) pci:v000013FEd00001600sv00001602sd00000002* ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 0) (PCI-1602 2-port isolated RS-422/485) pci:v000013FEd00001600sv00001612sd00000004* ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 0) (PCI-1612 4-port RS-232/422/485) pci:v000013FEd00001603* ID_MODEL_FROM_DATABASE=PCI-1603 2-port isolated RS-232/current loop pci:v000013FEd00001604* ID_MODEL_FROM_DATABASE=PCI-1604 2-port RS-232 pci:v000013FEd000016FF* ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 1: RX/TX steering CPLD) pci:v000013FEd000016FFsv00001601sd00000000* ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 1: RX/TX steering CPLD) (PCI-1601 2-port unisolated RS-422/485 PCI communications card) pci:v000013FEd000016FFsv00001602sd00000000* ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 1: RX/TX steering CPLD) (PCI-1602 2-port isolated RS-422/485) pci:v000013FEd000016FFsv00001612sd00000000* ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 1: RX/TX steering CPLD) (PCI-1612 4-port RS-232/422/485) pci:v000013FEd00001711* ID_MODEL_FROM_DATABASE=PCI-1711 16-channel data acquisition card 12-bit, 100kS/s pci:v000013FEd00001733* ID_MODEL_FROM_DATABASE=PCI-1733 32-channel isolated digital input card pci:v000013FEd00001752* ID_MODEL_FROM_DATABASE=PCI-1752 pci:v000013FEd00001754* ID_MODEL_FROM_DATABASE=PCI-1754 pci:v000013FEd00001756* ID_MODEL_FROM_DATABASE=PCI-1756 pci:v000013FEd0000C302* ID_MODEL_FROM_DATABASE=MIOe-3680 2-Port CAN-Bus MIOe Module with Isolation Protection pci:v000013FF* ID_VENDOR_FROM_DATABASE=Silicon Spice Inc pci:v00001400* ID_VENDOR_FROM_DATABASE=Artx Inc pci:v00001400d00001401* ID_MODEL_FROM_DATABASE=9432 TX pci:v00001401* ID_VENDOR_FROM_DATABASE=CR-Systems A/S pci:v00001402* ID_VENDOR_FROM_DATABASE=Meilhaus Electronic GmbH pci:v00001402d00000630* ID_MODEL_FROM_DATABASE=ME-630 pci:v00001402d00000940* ID_MODEL_FROM_DATABASE=ME-94 pci:v00001402d00000950* ID_MODEL_FROM_DATABASE=ME-95 pci:v00001402d00000960* ID_MODEL_FROM_DATABASE=ME-96 pci:v00001402d00001000* ID_MODEL_FROM_DATABASE=ME-1000 pci:v00001402d0000100A* ID_MODEL_FROM_DATABASE=ME-1000 pci:v00001402d0000100B* ID_MODEL_FROM_DATABASE=ME-1000 pci:v00001402d00001400* ID_MODEL_FROM_DATABASE=ME-1400 pci:v00001402d0000140A* ID_MODEL_FROM_DATABASE=ME-1400A pci:v00001402d0000140B* ID_MODEL_FROM_DATABASE=ME-1400B pci:v00001402d0000140C* ID_MODEL_FROM_DATABASE=ME-1400C pci:v00001402d0000140D* ID_MODEL_FROM_DATABASE=ME-1400D pci:v00001402d0000140E* ID_MODEL_FROM_DATABASE=ME-1400E pci:v00001402d000014EA* ID_MODEL_FROM_DATABASE=ME-1400EA pci:v00001402d000014EB* ID_MODEL_FROM_DATABASE=ME-1400EB pci:v00001402d00001604* ID_MODEL_FROM_DATABASE=ME-1600/4U pci:v00001402d00001608* ID_MODEL_FROM_DATABASE=ME-1600/8U pci:v00001402d0000160C* ID_MODEL_FROM_DATABASE=ME-1600/12U pci:v00001402d0000160F* ID_MODEL_FROM_DATABASE=ME-1600/16U pci:v00001402d0000168F* ID_MODEL_FROM_DATABASE=ME-1600/16U8I pci:v00001402d00004610* ID_MODEL_FROM_DATABASE=ME-4610 pci:v00001402d00004650* ID_MODEL_FROM_DATABASE=ME-4650 pci:v00001402d00004660* ID_MODEL_FROM_DATABASE=ME-4660 pci:v00001402d00004661* ID_MODEL_FROM_DATABASE=ME-4660I pci:v00001402d00004662* ID_MODEL_FROM_DATABASE=ME-4660 pci:v00001402d00004663* ID_MODEL_FROM_DATABASE=ME-4660I pci:v00001402d00004670* ID_MODEL_FROM_DATABASE=ME-4670 pci:v00001402d00004671* ID_MODEL_FROM_DATABASE=ME-4670I pci:v00001402d00004672* ID_MODEL_FROM_DATABASE=ME-4670S pci:v00001402d00004673* ID_MODEL_FROM_DATABASE=ME-4670IS pci:v00001402d00004680* ID_MODEL_FROM_DATABASE=ME-4680 pci:v00001402d00004681* ID_MODEL_FROM_DATABASE=ME-4680I pci:v00001402d00004682* ID_MODEL_FROM_DATABASE=ME-4680S pci:v00001402d00004683* ID_MODEL_FROM_DATABASE=ME-4680IS pci:v00001402d00006004* ID_MODEL_FROM_DATABASE=ME-6000/4 pci:v00001402d00006008* ID_MODEL_FROM_DATABASE=ME-6000/8 pci:v00001402d0000600F* ID_MODEL_FROM_DATABASE=ME-6000/16 pci:v00001402d00006014* ID_MODEL_FROM_DATABASE=ME-6000I/4 pci:v00001402d00006018* ID_MODEL_FROM_DATABASE=ME-6000I/8 pci:v00001402d0000601F* ID_MODEL_FROM_DATABASE=ME-6000I/16 pci:v00001402d00006034* ID_MODEL_FROM_DATABASE=ME-6000ISLE/4 pci:v00001402d00006038* ID_MODEL_FROM_DATABASE=ME-6000ISLE/8 pci:v00001402d0000603F* ID_MODEL_FROM_DATABASE=ME-6000ISLE/16 pci:v00001402d00006044* ID_MODEL_FROM_DATABASE=ME-6000/4/DIO pci:v00001402d00006048* ID_MODEL_FROM_DATABASE=ME-6000/8/DIO pci:v00001402d0000604F* ID_MODEL_FROM_DATABASE=ME-6000/16/DIO pci:v00001402d00006054* ID_MODEL_FROM_DATABASE=ME-6000I/4/DIO pci:v00001402d00006058* ID_MODEL_FROM_DATABASE=ME-6000I/8/DIO pci:v00001402d0000605F* ID_MODEL_FROM_DATABASE=ME-6000I/16/DIO pci:v00001402d00006074* ID_MODEL_FROM_DATABASE=ME-6000ISLE/4/DIO pci:v00001402d00006078* ID_MODEL_FROM_DATABASE=ME-6000ISLE/8/DIO pci:v00001402d0000607F* ID_MODEL_FROM_DATABASE=ME-6000ISLE/16/DIO pci:v00001402d00006104* ID_MODEL_FROM_DATABASE=ME-6100/4 pci:v00001402d00006108* ID_MODEL_FROM_DATABASE=ME-6100/8 pci:v00001402d0000610F* ID_MODEL_FROM_DATABASE=ME-6100/16 pci:v00001402d00006114* ID_MODEL_FROM_DATABASE=ME-6100I/4 pci:v00001402d00006118* ID_MODEL_FROM_DATABASE=ME-6100I/8 pci:v00001402d0000611F* ID_MODEL_FROM_DATABASE=ME-6100I/16 pci:v00001402d00006134* ID_MODEL_FROM_DATABASE=ME-6100ISLE/4 pci:v00001402d00006138* ID_MODEL_FROM_DATABASE=ME-6100ISLE/8 pci:v00001402d0000613F* ID_MODEL_FROM_DATABASE=ME-6100ISLE/16 pci:v00001402d00006144* ID_MODEL_FROM_DATABASE=ME-6100/4/DIO pci:v00001402d00006148* ID_MODEL_FROM_DATABASE=ME-6100/8/DIO pci:v00001402d0000614F* ID_MODEL_FROM_DATABASE=ME-6100/16/DIO pci:v00001402d00006154* ID_MODEL_FROM_DATABASE=ME-6100I/4/DIO pci:v00001402d00006158* ID_MODEL_FROM_DATABASE=ME-6100I/8/DIO pci:v00001402d0000615F* ID_MODEL_FROM_DATABASE=ME-6100I/16/DIO pci:v00001402d00006174* ID_MODEL_FROM_DATABASE=ME-6100ISLE/4/DIO pci:v00001402d00006178* ID_MODEL_FROM_DATABASE=ME-6100ISLE/8/DIO pci:v00001402d0000617F* ID_MODEL_FROM_DATABASE=ME-6100ISLE/16/DIO pci:v00001402d00006259* ID_MODEL_FROM_DATABASE=ME-6200I/9/DIO pci:v00001402d00006359* ID_MODEL_FROM_DATABASE=ME-6300I/9/DIO pci:v00001402d0000810A* ID_MODEL_FROM_DATABASE=ME-8100A pci:v00001402d0000810B* ID_MODEL_FROM_DATABASE=ME-8100B pci:v00001402d0000820A* ID_MODEL_FROM_DATABASE=ME-8200A pci:v00001402d0000820B* ID_MODEL_FROM_DATABASE=ME-8200B pci:v00001403* ID_VENDOR_FROM_DATABASE=Ascor Inc pci:v00001404* ID_VENDOR_FROM_DATABASE=Fundamental Software Inc pci:v00001405* ID_VENDOR_FROM_DATABASE=Excalibur Systems Inc pci:v00001406* ID_VENDOR_FROM_DATABASE=Oce' Printing Systems GmbH pci:v00001407* ID_VENDOR_FROM_DATABASE=Lava Computer mfg Inc pci:v00001407d00000100* ID_MODEL_FROM_DATABASE=Lava Dual Serial pci:v00001407d00000101* ID_MODEL_FROM_DATABASE=Lava Quatro A pci:v00001407d00000102* ID_MODEL_FROM_DATABASE=Lava Quatro B pci:v00001407d00000110* ID_MODEL_FROM_DATABASE=Lava DSerial-PCI Port A pci:v00001407d00000111* ID_MODEL_FROM_DATABASE=Lava DSerial-PCI Port B pci:v00001407d00000120* ID_MODEL_FROM_DATABASE=Quattro-PCI A pci:v00001407d00000121* ID_MODEL_FROM_DATABASE=Quattro-PCI B pci:v00001407d00000180* ID_MODEL_FROM_DATABASE=Lava Octo A pci:v00001407d00000181* ID_MODEL_FROM_DATABASE=Lava Octo B pci:v00001407d00000200* ID_MODEL_FROM_DATABASE=Lava Port Plus pci:v00001407d00000201* ID_MODEL_FROM_DATABASE=Lava Quad A pci:v00001407d00000202* ID_MODEL_FROM_DATABASE=Lava Quad B pci:v00001407d00000220* ID_MODEL_FROM_DATABASE=Lava Quattro PCI Ports A/B pci:v00001407d00000221* ID_MODEL_FROM_DATABASE=Lava Quattro PCI Ports C/D pci:v00001407d00000400* ID_MODEL_FROM_DATABASE=Lava 8255-PIO-PCI pci:v00001407d00000500* ID_MODEL_FROM_DATABASE=Lava Single Serial pci:v00001407d00000520* ID_MODEL_FROM_DATABASE=Lava RS422-SS-PCI pci:v00001407d00000600* ID_MODEL_FROM_DATABASE=Lava Port 650 pci:v00001407d00008000* ID_MODEL_FROM_DATABASE=Lava Parallel pci:v00001407d00008001* ID_MODEL_FROM_DATABASE=Dual parallel port controller A pci:v00001407d00008002* ID_MODEL_FROM_DATABASE=Lava Dual Parallel port A pci:v00001407d00008003* ID_MODEL_FROM_DATABASE=Lava Dual Parallel port B pci:v00001407d00008800* ID_MODEL_FROM_DATABASE=BOCA Research IOPPAR pci:v00001408* ID_VENDOR_FROM_DATABASE=Aloka Co. Ltd pci:v00001409* ID_VENDOR_FROM_DATABASE=Timedia Technology Co Ltd pci:v00001409d00007168* ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) pci:v00001409d00007168sv00001409sd00000002* ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4036A3V (2x RS232 port)) pci:v00001409d00007168sv00001409sd00004027* ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4027A (1x RS232 port)) pci:v00001409d00007168sv00001409sd00004037* ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4037A(L) [SUNIX SUN1889] (2x RS232 port)) pci:v00001409d00007168sv00001409sd00004056* ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4056A (4x RS232)) pci:v00001409d00007168sv00001409sd00005027* ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4027D) pci:v00001409d00007168sv00001409sd00005037* ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4037D (2x RS232 port)) pci:v00001409d00007168sv00001409sd00005066* ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4066R (8x RS232)) pci:v00001409d00007168sv00001409sd00006056* ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4056D (4x RS232 port)) pci:v00001409d00007268* ID_MODEL_FROM_DATABASE=SUN1888 (Dual IEEE1284 parallel port) pci:v00001409d00007268sv00001409sd00000103* ID_MODEL_FROM_DATABASE=SUN1888 (Dual IEEE1284 parallel port) (PAR4008A) pci:v00001409d00007268sv00001409sd00000104* ID_MODEL_FROM_DATABASE=SUN1888 (Dual IEEE1284 parallel port) (PAR4018A) pci:v0000140A* ID_VENDOR_FROM_DATABASE=DSP Research Inc pci:v0000140B* ID_VENDOR_FROM_DATABASE=GE Intelligent Platforms pci:v0000140C* ID_VENDOR_FROM_DATABASE=Elmic Systems Inc pci:v0000140D* ID_VENDOR_FROM_DATABASE=Matsushita Electric Works Ltd pci:v0000140E* ID_VENDOR_FROM_DATABASE=Goepel Electronic GmbH pci:v0000140F* ID_VENDOR_FROM_DATABASE=Salient Systems Corp pci:v00001410* ID_VENDOR_FROM_DATABASE=Midas lab Inc pci:v00001411* ID_VENDOR_FROM_DATABASE=Ikos Systems Inc pci:v00001412* ID_VENDOR_FROM_DATABASE=VIA Technologies Inc. pci:v00001412d00001712* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller pci:v00001412d00001712sv00001412sd00001712* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (Hoontech ST Audio DSP 24) pci:v00001412d00001712sv00001412sd0000D630* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta 1010) pci:v00001412d00001712sv00001412sd0000D631* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta DiO) pci:v00001412d00001712sv00001412sd0000D632* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta 66) pci:v00001412d00001712sv00001412sd0000D633* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta 44) pci:v00001412d00001712sv00001412sd0000D634* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta Audiophile 2496) pci:v00001412d00001712sv00001412sd0000D635* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta TDIF) pci:v00001412d00001712sv00001412sd0000D637* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta RBUS) pci:v00001412d00001712sv00001412sd0000D638* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta 410) pci:v00001412d00001712sv00001412sd0000D63B* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta 1010LT) pci:v00001412d00001712sv00001412sd0000D63C* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (Digigram VX442) pci:v00001412d00001712sv00001416sd00001712* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (Hoontech ST Audio DSP 24 Media 7.1) pci:v00001412d00001712sv0000153Bsd00001115* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (EWS88 MT) pci:v00001412d00001712sv0000153Bsd00001125* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (EWS88 MT (Master)) pci:v00001412d00001712sv0000153Bsd0000112B* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (EWS88 D) pci:v00001412d00001712sv0000153Bsd0000112C* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (EWS88 D (Master)) pci:v00001412d00001712sv0000153Bsd00001130* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (EWX 24/96) pci:v00001412d00001712sv0000153Bsd00001138* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (DMX 6fire 24/96) pci:v00001412d00001712sv0000153Bsd00001151* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (PHASE88) pci:v00001412d00001712sv000016CEsd00001040* ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (Edirol DA-2496) pci:v00001412d00001724* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller pci:v00001412d00001724sv000010B0sd00000200* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (Hollywood@Home 7.1) pci:v00001412d00001724sv00001412sd00001724* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (Albatron PX865PE 7.1) pci:v00001412d00001724sv00001412sd00003630* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (M-Audio Revolution 7.1) pci:v00001412d00001724sv00001412sd00003631* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (M-Audio Revolution 5.1) pci:v00001412d00001724sv00001412sd00003632* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (M-Audio Audiophile 192) pci:v00001412d00001724sv0000153Bsd00001145* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (Aureon 7.1 Space) pci:v00001412d00001724sv0000153Bsd00001147* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (Aureon 5.1 Sky) pci:v00001412d00001724sv0000153Bsd00001150* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (PHASE 22) pci:v00001412d00001724sv0000153Bsd00001153* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (Aureon 7.1 Universe) pci:v00001412d00001724sv000017ABsd00001906* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (PSC 724 [Ultimate Edge]) pci:v00001412d00001724sv0000270Fsd0000F641* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (ZNF3-150) pci:v00001412d00001724sv0000270Fsd0000F645* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (ZNF3-250) pci:v00001412d00001724sv00003130sd00004154* ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (MAYA 44 MKII) pci:v00001413* ID_VENDOR_FROM_DATABASE=Addonics pci:v00001414* ID_VENDOR_FROM_DATABASE=Microsoft Corporation pci:v00001414d00000001* ID_MODEL_FROM_DATABASE=MN-120 (ADMtek Centaur-C based) pci:v00001414d00000002* ID_MODEL_FROM_DATABASE=MN-130 (ADMtek Centaur-P based) pci:v00001414d00005353* ID_MODEL_FROM_DATABASE=Hyper-V virtual VGA pci:v00001414d00005801* ID_MODEL_FROM_DATABASE=XMA Decoder (Xenon) pci:v00001414d00005802* ID_MODEL_FROM_DATABASE=SATA Controller - CdRom (Xenon) pci:v00001414d00005803* ID_MODEL_FROM_DATABASE=SATA Controller - Disk (Xenon) pci:v00001414d00005804* ID_MODEL_FROM_DATABASE=OHCI Controller 0 (Xenon) pci:v00001414d00005805* ID_MODEL_FROM_DATABASE=EHCI Controller 0 (Xenon) pci:v00001414d00005806* ID_MODEL_FROM_DATABASE=OHCI Controller 1 (Xenon) pci:v00001414d00005807* ID_MODEL_FROM_DATABASE=EHCI Controller 1 (Xenon) pci:v00001414d0000580A* ID_MODEL_FROM_DATABASE=Fast Ethernet Adapter (Xenon) pci:v00001414d0000580B* ID_MODEL_FROM_DATABASE=Secure Flash Controller (Xenon) pci:v00001414d0000580D* ID_MODEL_FROM_DATABASE=System Management Controller (Xenon) pci:v00001414d00005811* ID_MODEL_FROM_DATABASE=Xenos GPU (Xenon) pci:v00001415* ID_VENDOR_FROM_DATABASE=Oxford Semiconductor Ltd pci:v00001415d00008401* ID_MODEL_FROM_DATABASE=OX9162 Mode 1 (8-bit bus) pci:v00001415d00008403* ID_MODEL_FROM_DATABASE=OX9162 Mode 0 (parallel port) pci:v00001415d00009500* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Disabled) pci:v00001415d00009501* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) pci:v00001415d00009501sv000012C4sd00000201* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (Titan/cPCI (2 port)) pci:v00001415d00009501sv000012C4sd00000202* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (Titan/cPCI (4 port)) pci:v00001415d00009501sv000012C4sd00000203* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (Titan/cPCI (8 port)) pci:v00001415d00009501sv000012C4sd00000210* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (Titan/104-Plus (8 port, p1-4)) pci:v00001415d00009501sv0000131Fsd00002050* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (CyberPro (4-port)) pci:v00001415d00009501sv0000131Fsd00002051* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (CyberSerial 4S Plus) pci:v00001415d00009501sv000015EDsd00002000* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (MCCR Serial p0-3 of 8) pci:v00001415d00009501sv000015EDsd00002001* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (MCCR Serial p0-3 of 16) pci:v00001415d00009505* ID_MODEL_FROM_DATABASE=OXuPCI952 (Dual 16C950 UART) pci:v00001415d0000950A* ID_MODEL_FROM_DATABASE=EXSYS EX-41092 Dual 16950 Serial adapter pci:v00001415d0000950B* ID_MODEL_FROM_DATABASE=OXCB950 Cardbus 16950 UART pci:v00001415d00009510* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (Disabled) pci:v00001415d00009510sv000012C4sd00000200* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (Disabled) (Titan/cPCI (Unused)) pci:v00001415d00009511* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (8bit bus) pci:v00001415d00009511sv000012C4sd00000211* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (8bit bus) (Titan/104-Plus (8 port, p5-8)) pci:v00001415d00009511sv000015EDsd00002000* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (8bit bus) (MCCR Serial p4-7 of 8) pci:v00001415d00009511sv000015EDsd00002001* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (8bit bus) (MCCR Serial p4-15 of 16) pci:v00001415d00009512* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (32bit bus) pci:v00001415d00009513* ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (parallel port) pci:v00001415d00009521* ID_MODEL_FROM_DATABASE=OX16PCI952 (Dual 16950 UART) pci:v00001415d00009523* ID_MODEL_FROM_DATABASE=OX16PCI952 Integrated Parallel Port pci:v00001415d0000C158* ID_MODEL_FROM_DATABASE=OXPCIe952 Dual 16C950 UART pci:v00001415d0000C158sv0000E4BFsd0000C504* ID_MODEL_FROM_DATABASE=OXPCIe952 Dual 16C950 UART (CP4-SCAT Wireless Technologies Carrier Board) pci:v00001415d0000C158sv0000E4BFsd0000D551* ID_MODEL_FROM_DATABASE=OXPCIe952 Dual 16C950 UART (DU1-MUSTANG Dual-Port RS-485 Interface) pci:v00001415d0000C308* ID_MODEL_FROM_DATABASE=EX-44016 16-port serial pci:v00001416* ID_VENDOR_FROM_DATABASE=Multiwave Innovation pte Ltd pci:v00001417* ID_VENDOR_FROM_DATABASE=Convergenet Technologies Inc pci:v00001418* ID_VENDOR_FROM_DATABASE=Kyushu electronics systems Inc pci:v00001419* ID_VENDOR_FROM_DATABASE=Excel Switching Corp pci:v0000141A* ID_VENDOR_FROM_DATABASE=Apache Micro Peripherals Inc pci:v0000141B* ID_VENDOR_FROM_DATABASE=Zoom Telephonics Inc pci:v0000141D* ID_VENDOR_FROM_DATABASE=Digitan Systems Inc pci:v0000141E* ID_VENDOR_FROM_DATABASE=Fanuc Ltd pci:v0000141F* ID_VENDOR_FROM_DATABASE=Visiontech Ltd pci:v00001420* ID_VENDOR_FROM_DATABASE=Psion Dacom plc pci:v00001420d00008002* ID_MODEL_FROM_DATABASE=Gold Card NetGlobal 56k+10/100Mb CardBus (Ethernet part) pci:v00001420d00008003* ID_MODEL_FROM_DATABASE=Gold Card NetGlobal 56k+10/100Mb CardBus (Modem part) pci:v00001421* ID_VENDOR_FROM_DATABASE=Ads Technologies Inc pci:v00001422* ID_VENDOR_FROM_DATABASE=Ygrec Systems Co Ltd pci:v00001423* ID_VENDOR_FROM_DATABASE=Custom Technology Corp. pci:v00001424* ID_VENDOR_FROM_DATABASE=Videoserver Connections pci:v00001425* ID_VENDOR_FROM_DATABASE=Chelsio Communications Inc pci:v00001425d0000000B* ID_MODEL_FROM_DATABASE=T210 Protocol Engine pci:v00001425d0000000C* ID_MODEL_FROM_DATABASE=T204 Protocol Engine pci:v00001425d00000022* ID_MODEL_FROM_DATABASE=10GbE Ethernet Adapter pci:v00001425d00000030* ID_MODEL_FROM_DATABASE=T310 10GbE Single Port Adapter pci:v00001425d00000030sv0000103Csd0000705E* ID_MODEL_FROM_DATABASE=T310 10GbE Single Port Adapter (PCIe 10GBase-SR [AD386A]) pci:v00001425d00000031* ID_MODEL_FROM_DATABASE=T320 10GbE Dual Port Adapter pci:v00001425d00000032* ID_MODEL_FROM_DATABASE=T302 1GbE Dual Port Adapter pci:v00001425d00000033* ID_MODEL_FROM_DATABASE=T304 1GbE Quad Port Adapter pci:v00001425d00000034* ID_MODEL_FROM_DATABASE=B320 10GbE Dual Port Adapter pci:v00001425d00000035* ID_MODEL_FROM_DATABASE=S310-CR 10GbE Single Port Adapter pci:v00001425d00000036* ID_MODEL_FROM_DATABASE=S320-LP-CR 10GbE Dual Port Adapter pci:v00001425d00000037* ID_MODEL_FROM_DATABASE=N320-G2-CR 10GbE Dual Port Adapter pci:v00001425d00004001* ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Ethernet Controller pci:v00001425d00004002* ID_MODEL_FROM_DATABASE=T422-CR Unified Wire Ethernet Controller pci:v00001425d00004003* ID_MODEL_FROM_DATABASE=T440-CR Unified Wire Ethernet Controller pci:v00001425d00004004* ID_MODEL_FROM_DATABASE=T420-BCH Unified Wire Ethernet Controller pci:v00001425d00004005* ID_MODEL_FROM_DATABASE=T440-BCH Unified Wire Ethernet Controller pci:v00001425d00004006* ID_MODEL_FROM_DATABASE=T440-CH Unified Wire Ethernet Controller pci:v00001425d00004007* ID_MODEL_FROM_DATABASE=T420-SO Unified Wire Ethernet Controller pci:v00001425d00004008* ID_MODEL_FROM_DATABASE=T420-CX Unified Wire Ethernet Controller pci:v00001425d00004009* ID_MODEL_FROM_DATABASE=T420-BT Unified Wire Ethernet Controller pci:v00001425d0000400A* ID_MODEL_FROM_DATABASE=T404-BT Unified Wire Ethernet Controller pci:v00001425d0000400B* ID_MODEL_FROM_DATABASE=B420-SR Unified Wire Ethernet Controller pci:v00001425d0000400C* ID_MODEL_FROM_DATABASE=B404-BT Unified Wire Ethernet Controller pci:v00001425d0000400D* ID_MODEL_FROM_DATABASE=T480 Unified Wire Ethernet Controller pci:v00001425d0000400E* ID_MODEL_FROM_DATABASE=T440-LP-CR Unified Wire Ethernet Controller pci:v00001425d0000400F* ID_MODEL_FROM_DATABASE=T440 [Amsterdam] Unified Wire Ethernet Controller pci:v00001425d00004080* ID_MODEL_FROM_DATABASE=T480-4080 T480 Unified Wire Ethernet Controller pci:v00001425d00004081* ID_MODEL_FROM_DATABASE=T440F-4081 T440-FCoE Unified Wire Ethernet Controller pci:v00001425d00004082* ID_MODEL_FROM_DATABASE=T420-4082 Unified Wire Ethernet Controller pci:v00001425d00004083* ID_MODEL_FROM_DATABASE=T420X-4083 Unified Wire Ethernet Controller pci:v00001425d00004084* ID_MODEL_FROM_DATABASE=T440-4084 Unified Wire Ethernet Controller pci:v00001425d00004085* ID_MODEL_FROM_DATABASE=T420-4085 SFP+ Unified Wire Ethernet Controller pci:v00001425d00004086* ID_MODEL_FROM_DATABASE=T440-4086 10Gbase-T Unified Wire Ethernet Controller pci:v00001425d00004087* ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Ethernet Controller pci:v00001425d00004088* ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Ethernet Controller pci:v00001425d00004401* ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Ethernet Controller pci:v00001425d00004402* ID_MODEL_FROM_DATABASE=T422-CR Unified Wire Ethernet Controller pci:v00001425d00004403* ID_MODEL_FROM_DATABASE=T440-CR Unified Wire Ethernet Controller pci:v00001425d00004404* ID_MODEL_FROM_DATABASE=T420-BCH Unified Wire Ethernet Controller pci:v00001425d00004405* ID_MODEL_FROM_DATABASE=T440-BCH Unified Wire Ethernet Controller pci:v00001425d00004406* ID_MODEL_FROM_DATABASE=T440-CH Unified Wire Ethernet Controller pci:v00001425d00004407* ID_MODEL_FROM_DATABASE=T420-SO Unified Wire Ethernet Controller pci:v00001425d00004408* ID_MODEL_FROM_DATABASE=T420-CX Unified Wire Ethernet Controller pci:v00001425d00004409* ID_MODEL_FROM_DATABASE=T420-BT Unified Wire Ethernet Controller pci:v00001425d0000440A* ID_MODEL_FROM_DATABASE=T404-BT Unified Wire Ethernet Controller pci:v00001425d0000440B* ID_MODEL_FROM_DATABASE=B420-SR Unified Wire Ethernet Controller pci:v00001425d0000440C* ID_MODEL_FROM_DATABASE=B404-BT Unified Wire Ethernet Controller pci:v00001425d0000440D* ID_MODEL_FROM_DATABASE=T480 Unified Wire Ethernet Controller pci:v00001425d0000440E* ID_MODEL_FROM_DATABASE=T440-LP-CR Unified Wire Ethernet Controller pci:v00001425d0000440F* ID_MODEL_FROM_DATABASE=T440 [Amsterdam] Unified Wire Ethernet Controller pci:v00001425d00004480* ID_MODEL_FROM_DATABASE=T480-4080 T480 Unified Wire Ethernet Controller pci:v00001425d00004481* ID_MODEL_FROM_DATABASE=T440F-4081 T440-FCoE Unified Wire Ethernet Controller pci:v00001425d00004482* ID_MODEL_FROM_DATABASE=T420-4082 Unified Wire Ethernet Controller pci:v00001425d00004483* ID_MODEL_FROM_DATABASE=T420X-4083 Unified Wire Ethernet Controller pci:v00001425d00004484* ID_MODEL_FROM_DATABASE=T440-4084 Unified Wire Ethernet Controller pci:v00001425d00004485* ID_MODEL_FROM_DATABASE=T420-4085 SFP+ Unified Wire Ethernet Controller pci:v00001425d00004486* ID_MODEL_FROM_DATABASE=T440-4086 10Gbase-T Unified Wire Ethernet Controller pci:v00001425d00004487* ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Ethernet Controller pci:v00001425d00004488* ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Ethernet Controller pci:v00001425d00004501* ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Storage Controller pci:v00001425d00004502* ID_MODEL_FROM_DATABASE=T422-CR Unified Wire Storage Controller pci:v00001425d00004503* ID_MODEL_FROM_DATABASE=T440-CR Unified Wire Storage Controller pci:v00001425d00004504* ID_MODEL_FROM_DATABASE=T420-BCH Unified Wire Storage Controller pci:v00001425d00004505* ID_MODEL_FROM_DATABASE=T440-BCH Unified Wire Storage Controller pci:v00001425d00004506* ID_MODEL_FROM_DATABASE=T440-CH Unified Wire Storage Controller pci:v00001425d00004507* ID_MODEL_FROM_DATABASE=T420-SO Unified Wire Storage Controller pci:v00001425d00004508* ID_MODEL_FROM_DATABASE=T420-CX Unified Wire Storage Controller pci:v00001425d00004509* ID_MODEL_FROM_DATABASE=T420-BT Unified Wire Storage Controller pci:v00001425d0000450A* ID_MODEL_FROM_DATABASE=T404-BT Unified Wire Storage Controller pci:v00001425d0000450B* ID_MODEL_FROM_DATABASE=B420-SR Unified Wire Storage Controller pci:v00001425d0000450C* ID_MODEL_FROM_DATABASE=B404-BT Unified Wire Storage Controller pci:v00001425d0000450D* ID_MODEL_FROM_DATABASE=T480 Unified Wire Storage Controller pci:v00001425d0000450E* ID_MODEL_FROM_DATABASE=T440-LP-CR Unified Wire Storage Controller pci:v00001425d0000450F* ID_MODEL_FROM_DATABASE=T440 [Amsterdam] Unified Wire Storage Controller pci:v00001425d00004580* ID_MODEL_FROM_DATABASE=T480-4080 T480 Unified Wire Storage Controller pci:v00001425d00004581* ID_MODEL_FROM_DATABASE=T440F-4081 T440-FCoE Unified Wire Storage Controller pci:v00001425d00004582* ID_MODEL_FROM_DATABASE=T420-4082 Unified Wire Storage Controller pci:v00001425d00004583* ID_MODEL_FROM_DATABASE=T420X-4083 Unified Wire Storage Controller pci:v00001425d00004584* ID_MODEL_FROM_DATABASE=T440-4084 Unified Wire Storage Controller pci:v00001425d00004585* ID_MODEL_FROM_DATABASE=T420-4085 SFP+ Unified Wire Storage Controller pci:v00001425d00004586* ID_MODEL_FROM_DATABASE=T440-4086 10Gbase-T Unified Wire Storage Controller pci:v00001425d00004587* ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Storage Controller pci:v00001425d00004588* ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Storage Controller pci:v00001425d00004601* ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Storage Controller pci:v00001425d00004602* ID_MODEL_FROM_DATABASE=T422-CR Unified Wire Storage Controller pci:v00001425d00004603* ID_MODEL_FROM_DATABASE=T440-CR Unified Wire Storage Controller pci:v00001425d00004604* ID_MODEL_FROM_DATABASE=T420-BCH Unified Wire Storage Controller pci:v00001425d00004605* ID_MODEL_FROM_DATABASE=T440-BCH Unified Wire Storage Controller pci:v00001425d00004606* ID_MODEL_FROM_DATABASE=T440-CH Unified Wire Storage Controller pci:v00001425d00004607* ID_MODEL_FROM_DATABASE=T420-SO Unified Wire Storage Controller pci:v00001425d00004608* ID_MODEL_FROM_DATABASE=T420-CX Unified Wire Storage Controller pci:v00001425d00004609* ID_MODEL_FROM_DATABASE=T420-BT Unified Wire Storage Controller pci:v00001425d0000460A* ID_MODEL_FROM_DATABASE=T404-BT Unified Wire Storage Controller pci:v00001425d0000460B* ID_MODEL_FROM_DATABASE=B420-SR Unified Wire Storage Controller pci:v00001425d0000460C* ID_MODEL_FROM_DATABASE=B404-BT Unified Wire Storage Controller pci:v00001425d0000460D* ID_MODEL_FROM_DATABASE=T480 Unified Wire Storage Controller pci:v00001425d0000460E* ID_MODEL_FROM_DATABASE=T440-LP-CR Unified Wire Storage Controller pci:v00001425d0000460F* ID_MODEL_FROM_DATABASE=T440 [Amsterdam] Unified Wire Storage Controller pci:v00001425d00004680* ID_MODEL_FROM_DATABASE=T480-4080 T480 Unified Wire Storage Controller pci:v00001425d00004681* ID_MODEL_FROM_DATABASE=T440F-4081 T440-FCoE Unified Wire Storage Controller pci:v00001425d00004682* ID_MODEL_FROM_DATABASE=T420-4082 Unified Wire Storage Controller pci:v00001425d00004683* ID_MODEL_FROM_DATABASE=T420X-4083 Unified Wire Storage Controller pci:v00001425d00004684* ID_MODEL_FROM_DATABASE=T440-4084 Unified Wire Storage Controller pci:v00001425d00004685* ID_MODEL_FROM_DATABASE=T420-4085 SFP+ Unified Wire Storage Controller pci:v00001425d00004686* ID_MODEL_FROM_DATABASE=T440-4086 10Gbase-T Unified Wire Storage Controller pci:v00001425d00004687* ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Storage Controller pci:v00001425d00004688* ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Storage Controller pci:v00001425d00004701* ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Ethernet Controller pci:v00001425d00004702* ID_MODEL_FROM_DATABASE=T422-CR Unified Wire Ethernet Controller pci:v00001425d00004703* ID_MODEL_FROM_DATABASE=T440-CR Unified Wire Ethernet Controller pci:v00001425d00004704* ID_MODEL_FROM_DATABASE=T420-BCH Unified Wire Ethernet Controller pci:v00001425d00004705* ID_MODEL_FROM_DATABASE=T440-BCH Unified Wire Ethernet Controller pci:v00001425d00004706* ID_MODEL_FROM_DATABASE=T440-CH Unified Wire Ethernet Controller pci:v00001425d00004707* ID_MODEL_FROM_DATABASE=T420-SO Unified Wire Ethernet Controller pci:v00001425d00004708* ID_MODEL_FROM_DATABASE=T420-CX Unified Wire Ethernet Controller pci:v00001425d00004709* ID_MODEL_FROM_DATABASE=T420-BT Unified Wire Ethernet Controller pci:v00001425d0000470A* ID_MODEL_FROM_DATABASE=T404-BT Unified Wire Ethernet Controller pci:v00001425d0000470B* ID_MODEL_FROM_DATABASE=B420-SR Unified Wire Ethernet Controller pci:v00001425d0000470C* ID_MODEL_FROM_DATABASE=B404-BT Unified Wire Ethernet Controller pci:v00001425d0000470D* ID_MODEL_FROM_DATABASE=T480 Unified Wire Ethernet Controller pci:v00001425d0000470E* ID_MODEL_FROM_DATABASE=T440-LP-CR Unified Wire Ethernet Controller pci:v00001425d0000470F* ID_MODEL_FROM_DATABASE=T440 [Amsterdam] Unified Wire Ethernet Controller pci:v00001425d00004780* ID_MODEL_FROM_DATABASE=T480-4080 T480 Unified Wire Ethernet Controller pci:v00001425d00004781* ID_MODEL_FROM_DATABASE=T440F-4081 T440-FCoE Unified Wire Ethernet Controller pci:v00001425d00004782* ID_MODEL_FROM_DATABASE=T420-4082 Unified Wire Ethernet Controller pci:v00001425d00004783* ID_MODEL_FROM_DATABASE=T420X-4083 Unified Wire Ethernet Controller pci:v00001425d00004784* ID_MODEL_FROM_DATABASE=T440-4084 Unified Wire Ethernet Controller pci:v00001425d00004785* ID_MODEL_FROM_DATABASE=T420-4085 SFP+ Unified Wire Ethernet Controller pci:v00001425d00004786* ID_MODEL_FROM_DATABASE=T440-4086 10Gbase-T Unified Wire Ethernet Controller pci:v00001425d00004787* ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Ethernet Controller pci:v00001425d00004788* ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Ethernet Controller pci:v00001425d00004801* ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Ethernet Controller [VF] pci:v00001425d00004802* ID_MODEL_FROM_DATABASE=T422-CR Unified Wire Ethernet Controller [VF] pci:v00001425d00004803* ID_MODEL_FROM_DATABASE=T440-CR Unified Wire Ethernet Controller [VF] pci:v00001425d00004804* ID_MODEL_FROM_DATABASE=T420-BCH Unified Wire Ethernet Controller [VF] pci:v00001425d00004805* ID_MODEL_FROM_DATABASE=T440-BCH Unified Wire Ethernet Controller [VF] pci:v00001425d00004806* ID_MODEL_FROM_DATABASE=T440-CH Unified Wire Ethernet Controller [VF] pci:v00001425d00004807* ID_MODEL_FROM_DATABASE=T420-SO Unified Wire Ethernet Controller [VF] pci:v00001425d00004808* ID_MODEL_FROM_DATABASE=T420-CX Unified Wire Ethernet Controller [VF] pci:v00001425d00004809* ID_MODEL_FROM_DATABASE=T420-BT Unified Wire Ethernet Controller [VF] pci:v00001425d0000480A* ID_MODEL_FROM_DATABASE=T404-BT Unified Wire Ethernet Controller [VF] pci:v00001425d0000480B* ID_MODEL_FROM_DATABASE=B420-SR Unified Wire Ethernet Controller [VF] pci:v00001425d0000480C* ID_MODEL_FROM_DATABASE=B404-BT Unified Wire Ethernet Controller [VF] pci:v00001425d0000480D* ID_MODEL_FROM_DATABASE=T480 Unified Wire Ethernet Controller [VF] pci:v00001425d0000480E* ID_MODEL_FROM_DATABASE=T440-LP-CR Unified Wire Ethernet Controller [VF] pci:v00001425d0000480F* ID_MODEL_FROM_DATABASE=T440 [Amsterdam] Unified Wire Ethernet Controller [VF] pci:v00001425d00004880* ID_MODEL_FROM_DATABASE=T480-4080 T480 Unified Wire Ethernet Controller [VF] pci:v00001425d00004881* ID_MODEL_FROM_DATABASE=T440F-4081 T440-FCoE Unified Wire Ethernet Controller [VF] pci:v00001425d00004882* ID_MODEL_FROM_DATABASE=T420-4082 Unified Wire Ethernet Controller [VF] pci:v00001425d00004883* ID_MODEL_FROM_DATABASE=T420X-4083 Unified Wire Ethernet Controller [VF] pci:v00001425d00004884* ID_MODEL_FROM_DATABASE=T440-4084 Unified Wire Ethernet Controller [VF] pci:v00001425d00004885* ID_MODEL_FROM_DATABASE=T420-4085 SFP+ Unified Wire Ethernet Controller [VF] pci:v00001425d00004886* ID_MODEL_FROM_DATABASE=T440-4086 10Gbase-T Unified Wire Ethernet Controller [VF] pci:v00001425d00004887* ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Ethernet Controller [VF] pci:v00001425d00004888* ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Ethernet Controller [VF] pci:v00001425d00005001* ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller pci:v00001425d00005002* ID_MODEL_FROM_DATABASE=T522-CR Unified Wire Ethernet Controller pci:v00001425d00005003* ID_MODEL_FROM_DATABASE=T540-CR Unified Wire Ethernet Controller pci:v00001425d00005004* ID_MODEL_FROM_DATABASE=T520-BCH Unified Wire Ethernet Controller pci:v00001425d00005005* ID_MODEL_FROM_DATABASE=T540-BCH Unified Wire Ethernet Controller pci:v00001425d00005006* ID_MODEL_FROM_DATABASE=T540-CH Unified Wire Ethernet Controller pci:v00001425d00005007* ID_MODEL_FROM_DATABASE=T520-SO Unified Wire Ethernet Controller pci:v00001425d00005008* ID_MODEL_FROM_DATABASE=T520-CX Unified Wire Ethernet Controller pci:v00001425d00005009* ID_MODEL_FROM_DATABASE=T520-BT Unified Wire Ethernet Controller pci:v00001425d0000500A* ID_MODEL_FROM_DATABASE=T504-BT Unified Wire Ethernet Controller pci:v00001425d0000500B* ID_MODEL_FROM_DATABASE=B520-SR Unified Wire Ethernet Controller pci:v00001425d0000500C* ID_MODEL_FROM_DATABASE=B504-BT Unified Wire Ethernet Controller pci:v00001425d0000500D* ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller pci:v00001425d0000500E* ID_MODEL_FROM_DATABASE=T540-LP-CR Unified Wire Ethernet Controller pci:v00001425d0000500F* ID_MODEL_FROM_DATABASE=T540 [Amsterdam] Unified Wire Ethernet Controller pci:v00001425d00005010* ID_MODEL_FROM_DATABASE=T580-LP-CR Unified Wire Ethernet Controller pci:v00001425d00005011* ID_MODEL_FROM_DATABASE=T520-LL-CR Unified Wire Ethernet Controller pci:v00001425d00005012* ID_MODEL_FROM_DATABASE=T560-CR Unified Wire Ethernet Controller pci:v00001425d00005013* ID_MODEL_FROM_DATABASE=T580-CHR Unified Wire Ethernet Controller pci:v00001425d00005014* ID_MODEL_FROM_DATABASE=T580-SO-CR Unified Wire Ethernet Controller pci:v00001425d00005015* ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Ethernet Controller pci:v00001425d00005016* ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Ethernet Controller pci:v00001425d00005017* ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Ethernet Controller pci:v00001425d00005080* ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller pci:v00001425d00005081* ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Ethernet Controller pci:v00001425d00005082* ID_MODEL_FROM_DATABASE=T504-5082 Unified Wire Ethernet Controller pci:v00001425d00005083* ID_MODEL_FROM_DATABASE=T540-5083 Unified Wire Ethernet Controller pci:v00001425d00005084* ID_MODEL_FROM_DATABASE=T580-5084 Unified Wire Ethernet Controller pci:v00001425d00005085* ID_MODEL_FROM_DATABASE=T580-5085 Unified Wire Ethernet Controller pci:v00001425d00005086* ID_MODEL_FROM_DATABASE=T580-5086 Unified Wire Ethernet Controller pci:v00001425d00005087* ID_MODEL_FROM_DATABASE=T580-5087 Unified Wire Ethernet Controller pci:v00001425d00005088* ID_MODEL_FROM_DATABASE=T570-5088 Unified Wire Ethernet Controller pci:v00001425d00005089* ID_MODEL_FROM_DATABASE=T520-5089 Unified Wire Ethernet Controller pci:v00001425d00005090* ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Ethernet Controller pci:v00001425d00005091* ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Ethernet Controller pci:v00001425d00005092* ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Ethernet Controller pci:v00001425d00005093* ID_MODEL_FROM_DATABASE=T580-5093 Unified Wire Ethernet Controller pci:v00001425d00005094* ID_MODEL_FROM_DATABASE=T540-5094 Unified Wire Ethernet Controller pci:v00001425d00005095* ID_MODEL_FROM_DATABASE=T540-5095 Unified Wire Ethernet Controller pci:v00001425d00005096* ID_MODEL_FROM_DATABASE=T580-5096 Unified Wire Ethernet Controller pci:v00001425d00005097* ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Ethernet Controller pci:v00001425d00005098* ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Ethernet Controller pci:v00001425d00005099* ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Ethernet Controller pci:v00001425d0000509A* ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Ethernet Controller pci:v00001425d0000509B* ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Ethernet Controller pci:v00001425d00005401* ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller pci:v00001425d00005402* ID_MODEL_FROM_DATABASE=T522-CR Unified Wire Ethernet Controller pci:v00001425d00005403* ID_MODEL_FROM_DATABASE=T540-CR Unified Wire Ethernet Controller pci:v00001425d00005404* ID_MODEL_FROM_DATABASE=T520-BCH Unified Wire Ethernet Controller pci:v00001425d00005405* ID_MODEL_FROM_DATABASE=T540-BCH Unified Wire Ethernet Controller pci:v00001425d00005406* ID_MODEL_FROM_DATABASE=T540-CH Unified Wire Ethernet Controller pci:v00001425d00005407* ID_MODEL_FROM_DATABASE=T520-SO Unified Wire Ethernet Controller pci:v00001425d00005408* ID_MODEL_FROM_DATABASE=T520-CX Unified Wire Ethernet Controller pci:v00001425d00005409* ID_MODEL_FROM_DATABASE=T520-BT Unified Wire Ethernet Controller pci:v00001425d0000540A* ID_MODEL_FROM_DATABASE=T504-BT Unified Wire Ethernet Controller pci:v00001425d0000540B* ID_MODEL_FROM_DATABASE=B520-SR Unified Wire Ethernet Controller pci:v00001425d0000540C* ID_MODEL_FROM_DATABASE=B504-BT Unified Wire Ethernet Controller pci:v00001425d0000540D* ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller pci:v00001425d0000540E* ID_MODEL_FROM_DATABASE=T540-LP-CR Unified Wire Ethernet Controller pci:v00001425d0000540F* ID_MODEL_FROM_DATABASE=T540 [Amsterdam] Unified Wire Ethernet Controller pci:v00001425d00005410* ID_MODEL_FROM_DATABASE=T580-LP-CR Unified Wire Ethernet Controller pci:v00001425d00005411* ID_MODEL_FROM_DATABASE=T520-LL-CR Unified Wire Ethernet Controller pci:v00001425d00005412* ID_MODEL_FROM_DATABASE=T560-CR Unified Wire Ethernet Controller pci:v00001425d00005413* ID_MODEL_FROM_DATABASE=T580-CHR Unified Wire Ethernet Controller pci:v00001425d00005414* ID_MODEL_FROM_DATABASE=T580-SO-CR Unified Wire Ethernet Controller pci:v00001425d00005415* ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Ethernet Controller pci:v00001425d00005416* ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Ethernet Controller pci:v00001425d00005417* ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Ethernet Controller pci:v00001425d00005480* ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller pci:v00001425d00005481* ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Ethernet Controller pci:v00001425d00005482* ID_MODEL_FROM_DATABASE=T504-5082 Unified Wire Ethernet Controller pci:v00001425d00005483* ID_MODEL_FROM_DATABASE=T540-5083 Unified Wire Ethernet Controller pci:v00001425d00005484* ID_MODEL_FROM_DATABASE=T580-5084 Unified Wire Ethernet Controller pci:v00001425d00005485* ID_MODEL_FROM_DATABASE=T580-5085 Unified Wire Ethernet Controller pci:v00001425d00005486* ID_MODEL_FROM_DATABASE=T580-5086 Unified Wire Ethernet Controller pci:v00001425d00005487* ID_MODEL_FROM_DATABASE=T580-5087 Unified Wire Ethernet Controller pci:v00001425d00005488* ID_MODEL_FROM_DATABASE=T570-5088 Unified Wire Ethernet Controller pci:v00001425d00005489* ID_MODEL_FROM_DATABASE=T520-5089 Unified Wire Ethernet Controller pci:v00001425d00005490* ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Ethernet Controller pci:v00001425d00005491* ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Ethernet Controller pci:v00001425d00005492* ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Ethernet Controller pci:v00001425d00005493* ID_MODEL_FROM_DATABASE=T580-5093 Unified Wire Ethernet Controller pci:v00001425d00005494* ID_MODEL_FROM_DATABASE=T540-5094 Unified Wire Ethernet Controller pci:v00001425d00005495* ID_MODEL_FROM_DATABASE=T540-5095 Unified Wire Ethernet Controller pci:v00001425d00005496* ID_MODEL_FROM_DATABASE=T580-5096 Unified Wire Ethernet Controller pci:v00001425d00005497* ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Ethernet Controller pci:v00001425d00005498* ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Ethernet Controller pci:v00001425d00005499* ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Ethernet Controller pci:v00001425d0000549A* ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Ethernet Controller pci:v00001425d0000549B* ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Ethernet Controller pci:v00001425d00005501* ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller pci:v00001425d00005502* ID_MODEL_FROM_DATABASE=T522-CR Unified Wire Storage Controller pci:v00001425d00005503* ID_MODEL_FROM_DATABASE=T540-CR Unified Wire Storage Controller pci:v00001425d00005504* ID_MODEL_FROM_DATABASE=T520-BCH Unified Wire Storage Controller pci:v00001425d00005505* ID_MODEL_FROM_DATABASE=T540-BCH Unified Wire Storage Controller pci:v00001425d00005506* ID_MODEL_FROM_DATABASE=T540-CH Unified Wire Storage Controller pci:v00001425d00005507* ID_MODEL_FROM_DATABASE=T520-SO Unified Wire Storage Controller pci:v00001425d00005508* ID_MODEL_FROM_DATABASE=T520-CX Unified Wire Storage Controller pci:v00001425d00005509* ID_MODEL_FROM_DATABASE=T520-BT Unified Wire Storage Controller pci:v00001425d0000550A* ID_MODEL_FROM_DATABASE=T504-BT Unified Wire Storage Controller pci:v00001425d0000550B* ID_MODEL_FROM_DATABASE=B520-SR Unified Wire Storage Controller pci:v00001425d0000550C* ID_MODEL_FROM_DATABASE=B504-BT Unified Wire Storage Controller pci:v00001425d0000550D* ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Storage Controller pci:v00001425d0000550E* ID_MODEL_FROM_DATABASE=T540-LP-CR Unified Wire Storage Controller pci:v00001425d0000550F* ID_MODEL_FROM_DATABASE=T540 [Amsterdam] Unified Wire Storage Controller pci:v00001425d00005510* ID_MODEL_FROM_DATABASE=T580-LP-CR Unified Wire Storage Controller pci:v00001425d00005511* ID_MODEL_FROM_DATABASE=T520-LL-CR Unified Wire Storage Controller pci:v00001425d00005512* ID_MODEL_FROM_DATABASE=T560-CR Unified Wire Storage Controller pci:v00001425d00005513* ID_MODEL_FROM_DATABASE=T580-CHR Unified Wire Storage Controller pci:v00001425d00005514* ID_MODEL_FROM_DATABASE=T580-SO-CR Unified Wire Storage Controller pci:v00001425d00005515* ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Storage Controller pci:v00001425d00005516* ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Storage Controller pci:v00001425d00005517* ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Storage Controller pci:v00001425d00005580* ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Storage Controller pci:v00001425d00005581* ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Storage Controller pci:v00001425d00005582* ID_MODEL_FROM_DATABASE=T504-5082 Unified Wire Storage Controller pci:v00001425d00005583* ID_MODEL_FROM_DATABASE=T540-5083 Unified Wire Storage Controller pci:v00001425d00005584* ID_MODEL_FROM_DATABASE=T580-5084 Unified Wire Storage Controller pci:v00001425d00005585* ID_MODEL_FROM_DATABASE=T580-5085 Unified Wire Storage Controller pci:v00001425d00005586* ID_MODEL_FROM_DATABASE=T580-5086 Unified Wire Storage Controller pci:v00001425d00005587* ID_MODEL_FROM_DATABASE=T580-5087 Unified Wire Storage Controller pci:v00001425d00005588* ID_MODEL_FROM_DATABASE=T570-5088 Unified Wire Storage Controller pci:v00001425d00005589* ID_MODEL_FROM_DATABASE=T520-5089 Unified Wire Storage Controller pci:v00001425d00005590* ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Storage Controller pci:v00001425d00005591* ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Storage Controller pci:v00001425d00005592* ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Storage Controller pci:v00001425d00005593* ID_MODEL_FROM_DATABASE=T580-5093 Unified Wire Storage Controller pci:v00001425d00005594* ID_MODEL_FROM_DATABASE=T540-5094 Unified Wire Storage Controller pci:v00001425d00005595* ID_MODEL_FROM_DATABASE=T540-5095 Unified Wire Storage Controller pci:v00001425d00005596* ID_MODEL_FROM_DATABASE=T580-5096 Unified Wire Storage Controller pci:v00001425d00005597* ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Storage Controller pci:v00001425d00005598* ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Storage Controller pci:v00001425d00005599* ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Storage Controller pci:v00001425d0000559A* ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Storage Controller pci:v00001425d0000559B* ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Storage Controller pci:v00001425d00005601* ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller pci:v00001425d00005602* ID_MODEL_FROM_DATABASE=T522-CR Unified Wire Storage Controller pci:v00001425d00005603* ID_MODEL_FROM_DATABASE=T540-CR Unified Wire Storage Controller pci:v00001425d00005604* ID_MODEL_FROM_DATABASE=T520-BCH Unified Wire Storage Controller pci:v00001425d00005605* ID_MODEL_FROM_DATABASE=T540-BCH Unified Wire Storage Controller pci:v00001425d00005606* ID_MODEL_FROM_DATABASE=T540-CH Unified Wire Storage Controller pci:v00001425d00005607* ID_MODEL_FROM_DATABASE=T520-SO Unified Wire Storage Controller pci:v00001425d00005608* ID_MODEL_FROM_DATABASE=T520-CX Unified Wire Storage Controller pci:v00001425d00005609* ID_MODEL_FROM_DATABASE=T520-BT Unified Wire Storage Controller pci:v00001425d0000560A* ID_MODEL_FROM_DATABASE=T504-BT Unified Wire Storage Controller pci:v00001425d0000560B* ID_MODEL_FROM_DATABASE=B520-SR Unified Wire Storage Controller pci:v00001425d0000560C* ID_MODEL_FROM_DATABASE=B504-BT Unified Wire Storage Controller pci:v00001425d0000560D* ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Storage Controller pci:v00001425d0000560E* ID_MODEL_FROM_DATABASE=T540-LP-CR Unified Wire Storage Controller pci:v00001425d0000560F* ID_MODEL_FROM_DATABASE=T540 [Amsterdam] Unified Wire Storage Controller pci:v00001425d00005610* ID_MODEL_FROM_DATABASE=T580-LP-CR Unified Wire Storage Controller pci:v00001425d00005611* ID_MODEL_FROM_DATABASE=T520-LL-CR Unified Wire Storage Controller pci:v00001425d00005612* ID_MODEL_FROM_DATABASE=T560-CR Unified Wire Storage Controller pci:v00001425d00005613* ID_MODEL_FROM_DATABASE=T580-CHR Unified Wire Storage Controller pci:v00001425d00005614* ID_MODEL_FROM_DATABASE=T580-SO-CR Unified Wire Storage Controller pci:v00001425d00005615* ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Storage Controller pci:v00001425d00005616* ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Storage Controller pci:v00001425d00005617* ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Storage Controller pci:v00001425d00005680* ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Storage Controller pci:v00001425d00005681* ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Storage Controller pci:v00001425d00005682* ID_MODEL_FROM_DATABASE=T504-5082 Unified Wire Storage Controller pci:v00001425d00005683* ID_MODEL_FROM_DATABASE=T540-5083 Unified Wire Storage Controller pci:v00001425d00005684* ID_MODEL_FROM_DATABASE=T580-5084 Unified Wire Storage Controller pci:v00001425d00005685* ID_MODEL_FROM_DATABASE=T580-5085 Unified Wire Storage Controller pci:v00001425d00005686* ID_MODEL_FROM_DATABASE=T580-5086 Unified Wire Storage Controller pci:v00001425d00005687* ID_MODEL_FROM_DATABASE=T580-5087 Unified Wire Storage Controller pci:v00001425d00005688* ID_MODEL_FROM_DATABASE=T570-5088 Unified Wire Storage Controller pci:v00001425d00005689* ID_MODEL_FROM_DATABASE=T520-5089 Unified Wire Storage Controller pci:v00001425d00005690* ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Storage Controller pci:v00001425d00005691* ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Storage Controller pci:v00001425d00005692* ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Storage Controller pci:v00001425d00005693* ID_MODEL_FROM_DATABASE=T580-5093 Unified Wire Storage Controller pci:v00001425d00005694* ID_MODEL_FROM_DATABASE=T540-5094 Unified Wire Storage Controller pci:v00001425d00005695* ID_MODEL_FROM_DATABASE=T540-5095 Unified Wire Storage Controller pci:v00001425d00005696* ID_MODEL_FROM_DATABASE=T580-5096 Unified Wire Storage Controller pci:v00001425d00005697* ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Storage Controller pci:v00001425d00005698* ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Storage Controller pci:v00001425d00005699* ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Storage Controller pci:v00001425d0000569A* ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Storage Controller pci:v00001425d0000569B* ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Storage Controller pci:v00001425d00005701* ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller pci:v00001425d00005702* ID_MODEL_FROM_DATABASE=T522-CR Unified Wire Ethernet Controller pci:v00001425d00005703* ID_MODEL_FROM_DATABASE=T540-CR Unified Wire Ethernet Controller pci:v00001425d00005704* ID_MODEL_FROM_DATABASE=T520-BCH Unified Wire Ethernet Controller pci:v00001425d00005705* ID_MODEL_FROM_DATABASE=T540-BCH Unified Wire Ethernet Controller pci:v00001425d00005706* ID_MODEL_FROM_DATABASE=T540-CH Unified Wire Ethernet Controller pci:v00001425d00005707* ID_MODEL_FROM_DATABASE=T520-SO Unified Wire Ethernet Controller pci:v00001425d00005708* ID_MODEL_FROM_DATABASE=T520-CX Unified Wire Ethernet Controller pci:v00001425d00005709* ID_MODEL_FROM_DATABASE=T520-BT Unified Wire Ethernet Controller pci:v00001425d0000570A* ID_MODEL_FROM_DATABASE=T504-BT Unified Wire Ethernet Controller pci:v00001425d0000570B* ID_MODEL_FROM_DATABASE=B520-SR Unified Wire Ethernet Controller pci:v00001425d0000570C* ID_MODEL_FROM_DATABASE=B504-BT Unified Wire Ethernet Controller pci:v00001425d0000570D* ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller pci:v00001425d0000570E* ID_MODEL_FROM_DATABASE=T540-LP-CR Unified Wire Ethernet Controller pci:v00001425d0000570F* ID_MODEL_FROM_DATABASE=T540 [Amsterdam] Unified Wire Ethernet Controller pci:v00001425d00005710* ID_MODEL_FROM_DATABASE=T580-LP-CR Unified Wire Ethernet Controller pci:v00001425d00005711* ID_MODEL_FROM_DATABASE=T520-LL-CR Unified Wire Ethernet Controller pci:v00001425d00005712* ID_MODEL_FROM_DATABASE=T560-CR Unified Wire Ethernet Controller pci:v00001425d00005713* ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller pci:v00001425d00005714* ID_MODEL_FROM_DATABASE=T580-SO-CR Unified Wire Ethernet Controller pci:v00001425d00005715* ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Ethernet Controller pci:v00001425d00005780* ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller pci:v00001425d00005781* ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Ethernet Controller pci:v00001425d00005782* ID_MODEL_FROM_DATABASE=T504-5082 Unified Wire Ethernet Controller pci:v00001425d00005783* ID_MODEL_FROM_DATABASE=T540-5083 Unified Wire Ethernet Controller pci:v00001425d00005784* ID_MODEL_FROM_DATABASE=T580-5084 Unified Wire Ethernet Controller pci:v00001425d00005785* ID_MODEL_FROM_DATABASE=T580-5085 Unified Wire Ethernet Controller pci:v00001425d00005786* ID_MODEL_FROM_DATABASE=T580-5086 Unified Wire Ethernet Controller pci:v00001425d00005787* ID_MODEL_FROM_DATABASE=T580-5087 Unified Wire Ethernet Controller pci:v00001425d00005788* ID_MODEL_FROM_DATABASE=T570-5088 Unified Wire Ethernet Controller pci:v00001425d00005789* ID_MODEL_FROM_DATABASE=T520-5089 Unified Wire Ethernet Controller pci:v00001425d00005790* ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Ethernet Controller pci:v00001425d00005791* ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Ethernet Controller pci:v00001425d00005792* ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Ethernet Controller pci:v00001425d00005793* ID_MODEL_FROM_DATABASE=T580-5093 Unified Wire Ethernet Controller pci:v00001425d00005794* ID_MODEL_FROM_DATABASE=T540-5094 Unified Wire Ethernet Controller pci:v00001425d00005795* ID_MODEL_FROM_DATABASE=T540-5095 Unified Wire Ethernet Controller pci:v00001425d00005796* ID_MODEL_FROM_DATABASE=T580-5096 Unified Wire Ethernet Controller pci:v00001425d00005797* ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Ethernet Controller pci:v00001425d00005801* ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller [VF] pci:v00001425d00005802* ID_MODEL_FROM_DATABASE=T522-CR Unified Wire Ethernet Controller [VF] pci:v00001425d00005803* ID_MODEL_FROM_DATABASE=T540-CR Unified Wire Ethernet Controller [VF] pci:v00001425d00005804* ID_MODEL_FROM_DATABASE=T520-BCH Unified Wire Ethernet Controller [VF] pci:v00001425d00005805* ID_MODEL_FROM_DATABASE=T540-BCH Unified Wire Ethernet Controller [VF] pci:v00001425d00005806* ID_MODEL_FROM_DATABASE=T540-CH Unified Wire Ethernet Controller [VF] pci:v00001425d00005807* ID_MODEL_FROM_DATABASE=T520-SO Unified Wire Ethernet Controller [VF] pci:v00001425d00005808* ID_MODEL_FROM_DATABASE=T520-CX Unified Wire Ethernet Controller [VF] pci:v00001425d00005809* ID_MODEL_FROM_DATABASE=T520-BT Unified Wire Ethernet Controller [VF] pci:v00001425d0000580A* ID_MODEL_FROM_DATABASE=T504-BT Unified Wire Ethernet Controller [VF] pci:v00001425d0000580B* ID_MODEL_FROM_DATABASE=B520-SR Unified Wire Ethernet Controller [VF] pci:v00001425d0000580C* ID_MODEL_FROM_DATABASE=B504-BT Unified Wire Ethernet Controller [VF] pci:v00001425d0000580D* ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller [VF] pci:v00001425d0000580E* ID_MODEL_FROM_DATABASE=T540-LP-CR Unified Wire Ethernet Controller [VF] pci:v00001425d0000580F* ID_MODEL_FROM_DATABASE=T540 [Amsterdam] Unified Wire Ethernet Controller [VF] pci:v00001425d00005810* ID_MODEL_FROM_DATABASE=T580-LP-CR Unified Wire Ethernet Controller [VF] pci:v00001425d00005811* ID_MODEL_FROM_DATABASE=T520-LL-CR Unified Wire Ethernet Controller [VF] pci:v00001425d00005812* ID_MODEL_FROM_DATABASE=T560-CR Unified Wire Ethernet Controller [VF] pci:v00001425d00005813* ID_MODEL_FROM_DATABASE=T580-CHR Unified Wire Ethernet Controller [VF] pci:v00001425d00005814* ID_MODEL_FROM_DATABASE=T580-SO-CR Unified Wire Ethernet Controller [VF] pci:v00001425d00005815* ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Ethernet Controller [VF] pci:v00001425d00005816* ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Ethernet Controller [VF] pci:v00001425d00005817* ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Ethernet Controller [VF] pci:v00001425d00005880* ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller [VF] pci:v00001425d00005881* ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Ethernet Controller [VF] pci:v00001425d00005882* ID_MODEL_FROM_DATABASE=T504-5082 Unified Wire Ethernet Controller [VF] pci:v00001425d00005883* ID_MODEL_FROM_DATABASE=T540-5083 Unified Wire Ethernet Controller [VF] pci:v00001425d00005884* ID_MODEL_FROM_DATABASE=T580-5084 Unified Wire Ethernet Controller [VF] pci:v00001425d00005885* ID_MODEL_FROM_DATABASE=T580-5085 Unified Wire Ethernet Controller [VF] pci:v00001425d00005886* ID_MODEL_FROM_DATABASE=T580-5086 Unified Wire Ethernet Controller [VF] pci:v00001425d00005887* ID_MODEL_FROM_DATABASE=T580-5087 Unified Wire Ethernet Controller [VF] pci:v00001425d00005888* ID_MODEL_FROM_DATABASE=T570-5088 Unified Wire Ethernet Controller [VF] pci:v00001425d00005889* ID_MODEL_FROM_DATABASE=T520-5089 Unified Wire Ethernet Controller [VF] pci:v00001425d00005890* ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Ethernet Controller [VF] pci:v00001425d00005891* ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Ethernet Controller [VF] pci:v00001425d00005892* ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Ethernet Controller [VF] pci:v00001425d00005893* ID_MODEL_FROM_DATABASE=T580-5093 Unified Wire Ethernet Controller [VF] pci:v00001425d00005894* ID_MODEL_FROM_DATABASE=T540-5094 Unified Wire Ethernet Controller [VF] pci:v00001425d00005895* ID_MODEL_FROM_DATABASE=T540-5095 Unified Wire Ethernet Controller [VF] pci:v00001425d00005896* ID_MODEL_FROM_DATABASE=T580-5096 Unified Wire Ethernet Controller [VF] pci:v00001425d00005897* ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Ethernet Controller [VF] pci:v00001425d00005898* ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Ethernet Controller [VF] pci:v00001425d00005899* ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Ethernet Controller [VF] pci:v00001425d0000589A* ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Ethernet Controller [VF] pci:v00001425d0000589B* ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Ethernet Controller [VF] pci:v00001425d0000A000* ID_MODEL_FROM_DATABASE=PE10K Unified Wire Ethernet Controller pci:v00001426* ID_VENDOR_FROM_DATABASE=Storage Technology Corp. pci:v00001427* ID_VENDOR_FROM_DATABASE=Better On-Line Solutions pci:v00001428* ID_VENDOR_FROM_DATABASE=Edec Co Ltd pci:v00001429* ID_VENDOR_FROM_DATABASE=Unex Technology Corp. pci:v0000142A* ID_VENDOR_FROM_DATABASE=Kingmax Technology Inc pci:v0000142B* ID_VENDOR_FROM_DATABASE=Radiolan pci:v0000142C* ID_VENDOR_FROM_DATABASE=Minton Optic Industry Co Ltd pci:v0000142D* ID_VENDOR_FROM_DATABASE=Pix stream Inc pci:v0000142E* ID_VENDOR_FROM_DATABASE=Vitec Multimedia pci:v0000142Ed00004020* ID_MODEL_FROM_DATABASE=VM2-2 [Video Maker 2] MPEG1/2 Encoder pci:v0000142Ed00004337* ID_MODEL_FROM_DATABASE=VM2-2-C7 [Video Maker 2 rev. C7] MPEG1/2 Encoder pci:v0000142F* ID_VENDOR_FROM_DATABASE=Radicom Research Inc pci:v00001430* ID_VENDOR_FROM_DATABASE=ITT Aerospace/Communications Division pci:v00001431* ID_VENDOR_FROM_DATABASE=Gilat Satellite Networks pci:v00001432* ID_VENDOR_FROM_DATABASE=Edimax Computer Co. pci:v00001432d00009130* ID_MODEL_FROM_DATABASE=RTL81xx Fast Ethernet pci:v00001433* ID_VENDOR_FROM_DATABASE=Eltec Elektronik GmbH pci:v00001435* ID_VENDOR_FROM_DATABASE=RTD Embedded Technologies, Inc. pci:v00001435d00004520* ID_MODEL_FROM_DATABASE=PCI4520 pci:v00001435d00006020* ID_MODEL_FROM_DATABASE=SPM6020 pci:v00001435d00006030* ID_MODEL_FROM_DATABASE=SPM6030 pci:v00001435d00006420* ID_MODEL_FROM_DATABASE=SPM186420 pci:v00001435d00006430* ID_MODEL_FROM_DATABASE=SPM176430 pci:v00001435d00006431* ID_MODEL_FROM_DATABASE=SPM176431 pci:v00001435d00007520* ID_MODEL_FROM_DATABASE=DM7520 pci:v00001435d00007540* ID_MODEL_FROM_DATABASE=SDM7540 pci:v00001435d00007820* ID_MODEL_FROM_DATABASE=DM7820 pci:v00001436* ID_VENDOR_FROM_DATABASE=CIS Technology Inc pci:v00001437* ID_VENDOR_FROM_DATABASE=Nissin Inc Co pci:v00001438* ID_VENDOR_FROM_DATABASE=Atmel-dream pci:v00001439* ID_VENDOR_FROM_DATABASE=Outsource Engineering & Mfg. Inc pci:v0000143A* ID_VENDOR_FROM_DATABASE=Stargate Solutions Inc pci:v0000143B* ID_VENDOR_FROM_DATABASE=Canon Research Center, America pci:v0000143C* ID_VENDOR_FROM_DATABASE=Amlogic Inc pci:v0000143D* ID_VENDOR_FROM_DATABASE=Tamarack Microelectronics Inc pci:v0000143E* ID_VENDOR_FROM_DATABASE=Jones Futurex Inc pci:v0000143F* ID_VENDOR_FROM_DATABASE=Lightwell Co Ltd - Zax Division pci:v00001440* ID_VENDOR_FROM_DATABASE=ALGOL Corp. pci:v00001441* ID_VENDOR_FROM_DATABASE=AGIE Ltd pci:v00001442* ID_VENDOR_FROM_DATABASE=Phoenix Contact GmbH & Co. pci:v00001443* ID_VENDOR_FROM_DATABASE=Unibrain S.A. pci:v00001444* ID_VENDOR_FROM_DATABASE=TRW pci:v00001445* ID_VENDOR_FROM_DATABASE=Logical DO Ltd pci:v00001446* ID_VENDOR_FROM_DATABASE=Graphin Co Ltd pci:v00001447* ID_VENDOR_FROM_DATABASE=AIM GmBH pci:v00001448* ID_VENDOR_FROM_DATABASE=Alesis Studio Electronics pci:v00001449* ID_VENDOR_FROM_DATABASE=TUT Systems Inc pci:v0000144A* ID_VENDOR_FROM_DATABASE=Adlink Technology pci:v0000144Ad00006208* ID_MODEL_FROM_DATABASE=PCI-6208V pci:v0000144Ad00007250* ID_MODEL_FROM_DATABASE=PCI-7250 pci:v0000144Ad00007296* ID_MODEL_FROM_DATABASE=PCI-7296 pci:v0000144Ad00007432* ID_MODEL_FROM_DATABASE=PCI-7432 pci:v0000144Ad00007433* ID_MODEL_FROM_DATABASE=PCI-7433 pci:v0000144Ad00007434* ID_MODEL_FROM_DATABASE=PCI-7434 pci:v0000144Ad00007841* ID_MODEL_FROM_DATABASE=PCI-7841 pci:v0000144Ad00008133* ID_MODEL_FROM_DATABASE=PCI-8133 pci:v0000144Ad00008164* ID_MODEL_FROM_DATABASE=PCI-8164 pci:v0000144Ad00008554* ID_MODEL_FROM_DATABASE=PCI-8554 pci:v0000144Ad00009111* ID_MODEL_FROM_DATABASE=PCI-9111 pci:v0000144Ad00009113* ID_MODEL_FROM_DATABASE=PCI-9113 pci:v0000144Ad00009114* ID_MODEL_FROM_DATABASE=PCI-9114 pci:v0000144B* ID_VENDOR_FROM_DATABASE=Verint Systems Inc. pci:v0000144C* ID_VENDOR_FROM_DATABASE=Catalina Research Inc pci:v0000144D* ID_VENDOR_FROM_DATABASE=Samsung Electronics Co Ltd pci:v0000144Dd00001600* ID_MODEL_FROM_DATABASE=Apple PCIe SSD pci:v0000144Dd0000A800* ID_MODEL_FROM_DATABASE=XP941 PCIe SSD pci:v0000144Dd0000A802* ID_MODEL_FROM_DATABASE=NVMe SSD Controller pci:v0000144Dd0000A820* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X pci:v0000144Dd0000A820sv00001028sd00001F95* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe XS1715 SSD 400GB) pci:v0000144Dd0000A820sv00001028sd00001F96* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe XS1715 SSD 800GB) pci:v0000144Dd0000A820sv00001028sd00001F97* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe XS1715 SSD 1600GB) pci:v0000144Dd0000A820sv00001028sd00001FA4* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 3.2TB SFF) pci:v0000144Dd0000A820sv00001028sd00001FA6* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 3.2TB AIC) pci:v0000144Dd0000A820sv00001028sd00001FBA* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 800GB SFF) pci:v0000144Dd0000A820sv00001028sd00001FBB* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 1.6TB SFF) pci:v0000144Dd0000A820sv00001028sd00001FBC* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 1.6TB AIC) pci:v0000144Dd0000A821* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X pci:v0000144Dd0000A821sv00001028sd00001FB7* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 3.2TB SFF) pci:v0000144Dd0000A821sv00001028sd00001FB8* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 3.2TB AIC) pci:v0000144Dd0000A821sv00001028sd00001FB9* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 6.4TB AIC) pci:v0000144Dd0000A821sv00001028sd00001FC1* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 800GB SFF) pci:v0000144Dd0000A821sv00001028sd00001FC2* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 1.6TB SFF) pci:v0000144Dd0000A821sv00001028sd00001FC4* ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 1.6TB AIC) pci:v0000144E* ID_VENDOR_FROM_DATABASE=OLITEC pci:v0000144F* ID_VENDOR_FROM_DATABASE=Askey Computer Corp. pci:v00001450* ID_VENDOR_FROM_DATABASE=Octave Communications Ind. pci:v00001451* ID_VENDOR_FROM_DATABASE=SP3D Chip Design GmBH pci:v00001453* ID_VENDOR_FROM_DATABASE=MYCOM Inc pci:v00001454* ID_VENDOR_FROM_DATABASE=Altiga Networks pci:v00001455* ID_VENDOR_FROM_DATABASE=Logic Plus Plus Inc pci:v00001456* ID_VENDOR_FROM_DATABASE=Advanced Hardware Architectures pci:v00001457* ID_VENDOR_FROM_DATABASE=Nuera Communications Inc pci:v00001458* ID_VENDOR_FROM_DATABASE=Gigabyte Technology Co., Ltd pci:v00001459* ID_VENDOR_FROM_DATABASE=DOOIN Electronics pci:v0000145A* ID_VENDOR_FROM_DATABASE=Escalate Networks Inc pci:v0000145B* ID_VENDOR_FROM_DATABASE=PRAIM SRL pci:v0000145C* ID_VENDOR_FROM_DATABASE=Cryptek pci:v0000145D* ID_VENDOR_FROM_DATABASE=Gallant Computer Inc pci:v0000145E* ID_VENDOR_FROM_DATABASE=Aashima Technology B.V. pci:v0000145F* ID_VENDOR_FROM_DATABASE=Baldor Electric Company pci:v0000145Fd00000001* ID_MODEL_FROM_DATABASE=NextMove PCI pci:v00001460* ID_VENDOR_FROM_DATABASE=DYNARC INC pci:v00001461* ID_VENDOR_FROM_DATABASE=Avermedia Technologies Inc pci:v00001461d0000A3CE* ID_MODEL_FROM_DATABASE=M179 pci:v00001461d0000A3CF* ID_MODEL_FROM_DATABASE=M179 pci:v00001461d0000A836* ID_MODEL_FROM_DATABASE=M115 DVB-T, PAL/SECAM/NTSC Tuner pci:v00001461d0000E836* ID_MODEL_FROM_DATABASE=M115S Hybrid Analog/DVB PAL/SECAM/NTSC Tuner pci:v00001461d0000F436* ID_MODEL_FROM_DATABASE=AVerTV Hybrid+FM pci:v00001462* ID_VENDOR_FROM_DATABASE=Micro-Star International Co., Ltd. [MSI] pci:v00001463* ID_VENDOR_FROM_DATABASE=Fast Corporation pci:v00001464* ID_VENDOR_FROM_DATABASE=Interactive Circuits & Systems Ltd pci:v00001465* ID_VENDOR_FROM_DATABASE=GN NETTEST Telecom DIV. pci:v00001466* ID_VENDOR_FROM_DATABASE=Designpro Inc. pci:v00001467* ID_VENDOR_FROM_DATABASE=DIGICOM SPA pci:v00001468* ID_VENDOR_FROM_DATABASE=AMBIT Microsystem Corp. pci:v00001469* ID_VENDOR_FROM_DATABASE=Cleveland Motion Controls pci:v0000146A* ID_VENDOR_FROM_DATABASE=Aeroflex pci:v0000146Ad00003010* ID_MODEL_FROM_DATABASE=3010 RF Synthesizer pci:v0000146Ad00003A11* ID_MODEL_FROM_DATABASE=3011A PXI RF Synthesizer pci:v0000146B* ID_VENDOR_FROM_DATABASE=Parascan Technologies Ltd pci:v0000146C* ID_VENDOR_FROM_DATABASE=Ruby Tech Corp. pci:v0000146Cd00001430* ID_MODEL_FROM_DATABASE=FE-1430TX Fast Ethernet PCI Adapter pci:v0000146D* ID_VENDOR_FROM_DATABASE=Tachyon, INC. pci:v0000146E* ID_VENDOR_FROM_DATABASE=Williams Electronics Games, Inc. pci:v0000146F* ID_VENDOR_FROM_DATABASE=Multi Dimensional Consulting Inc pci:v00001470* ID_VENDOR_FROM_DATABASE=Bay Networks pci:v00001471* ID_VENDOR_FROM_DATABASE=Integrated Telecom Express Inc pci:v00001472* ID_VENDOR_FROM_DATABASE=DAIKIN Industries, Ltd pci:v00001473* ID_VENDOR_FROM_DATABASE=ZAPEX Technologies Inc pci:v00001474* ID_VENDOR_FROM_DATABASE=Doug Carson & Associates pci:v00001475* ID_VENDOR_FROM_DATABASE=PICAZO Communications pci:v00001476* ID_VENDOR_FROM_DATABASE=MORTARA Instrument Inc pci:v00001477* ID_VENDOR_FROM_DATABASE=Net Insight pci:v00001478* ID_VENDOR_FROM_DATABASE=DIATREND Corporation pci:v00001479* ID_VENDOR_FROM_DATABASE=TORAY Industries Inc pci:v0000147A* ID_VENDOR_FROM_DATABASE=FORMOSA Industrial Computing pci:v0000147B* ID_VENDOR_FROM_DATABASE=ABIT Computer Corp. pci:v0000147Bd00001084* ID_MODEL_FROM_DATABASE=IP35 [Dark Raider] pci:v0000147C* ID_VENDOR_FROM_DATABASE=AWARE, Inc. pci:v0000147D* ID_VENDOR_FROM_DATABASE=Interworks Computer Products pci:v0000147E* ID_VENDOR_FROM_DATABASE=Matsushita Graphic Communication Systems, Inc. pci:v0000147F* ID_VENDOR_FROM_DATABASE=NIHON UNISYS, Ltd. pci:v00001480* ID_VENDOR_FROM_DATABASE=SCII Telecom pci:v00001481* ID_VENDOR_FROM_DATABASE=BIOPAC Systems Inc pci:v00001482* ID_VENDOR_FROM_DATABASE=ISYTEC - Integrierte Systemtechnik GmBH pci:v00001482d00000001* ID_MODEL_FROM_DATABASE=PCI-16 Host Interface for ITC-16 pci:v00001483* ID_VENDOR_FROM_DATABASE=LABWAY Corporation pci:v00001484* ID_VENDOR_FROM_DATABASE=Logic Corporation pci:v00001485* ID_VENDOR_FROM_DATABASE=ERMA - Electronic GmBH pci:v00001486* ID_VENDOR_FROM_DATABASE=L3 Communications Telemetry & Instrumentation pci:v00001487* ID_VENDOR_FROM_DATABASE=MARQUETTE Medical Systems pci:v00001489* ID_VENDOR_FROM_DATABASE=KYE Systems Corporation pci:v0000148A* ID_VENDOR_FROM_DATABASE=OPTO pci:v0000148B* ID_VENDOR_FROM_DATABASE=INNOMEDIALOGIC Inc. pci:v0000148C* ID_VENDOR_FROM_DATABASE=Tul Corporation / PowerColor pci:v0000148D* ID_VENDOR_FROM_DATABASE=DIGICOM Systems, Inc. pci:v0000148Dd00001003* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem pci:v0000148E* ID_VENDOR_FROM_DATABASE=OSI Plus Corporation pci:v0000148F* ID_VENDOR_FROM_DATABASE=Plant Equipment, Inc. pci:v00001490* ID_VENDOR_FROM_DATABASE=Stone Microsystems PTY Ltd. pci:v00001491* ID_VENDOR_FROM_DATABASE=ZEAL Corporation pci:v00001492* ID_VENDOR_FROM_DATABASE=Time Logic Corporation pci:v00001493* ID_VENDOR_FROM_DATABASE=MAKER Communications pci:v00001494* ID_VENDOR_FROM_DATABASE=WINTOP Technology, Inc. pci:v00001495* ID_VENDOR_FROM_DATABASE=TOKAI Communications Industry Co. Ltd pci:v00001496* ID_VENDOR_FROM_DATABASE=JOYTECH Computer Co., Ltd. pci:v00001497* ID_VENDOR_FROM_DATABASE=SMA Regelsysteme GmBH pci:v00001497d00001497* ID_MODEL_FROM_DATABASE=SMA Technologie AG pci:v00001498* ID_VENDOR_FROM_DATABASE=TEWS Technologies GmbH pci:v00001498d00000330* ID_MODEL_FROM_DATABASE=TPMC816 2 Channel CAN bus controller. pci:v00001498d0000035D* ID_MODEL_FROM_DATABASE=TPMC861 4-Channel Isolated Serial Interface RS422/RS485 pci:v00001498d00000385* ID_MODEL_FROM_DATABASE=TPMC901 Extended CAN bus with 2/4/6 CAN controller pci:v00001498d000021CC* ID_MODEL_FROM_DATABASE=TCP460 CompactPCI 16 Channel Serial Interface RS232/RS422 pci:v00001498d000021CD* ID_MODEL_FROM_DATABASE=TCP461 CompactPCI 8 Channel Serial Interface RS232/RS422 pci:v00001498d00003064* ID_MODEL_FROM_DATABASE=TPCI100 (2 Slot IndustryPack PCI Carrier) pci:v00001498d000030C8* ID_MODEL_FROM_DATABASE=TPCI200 4 Slot IndustryPack PCI Carrier pci:v00001498d000070C8* ID_MODEL_FROM_DATABASE=TPCE200 4 Slot IndustryPack PCIe Carrier pci:v00001499* ID_VENDOR_FROM_DATABASE=EMTEC CO., Ltd pci:v0000149A* ID_VENDOR_FROM_DATABASE=ANDOR Technology Ltd pci:v0000149B* ID_VENDOR_FROM_DATABASE=SEIKO Instruments Inc pci:v0000149C* ID_VENDOR_FROM_DATABASE=OVISLINK Corp. pci:v0000149D* ID_VENDOR_FROM_DATABASE=NEWTEK Inc pci:v0000149Dd00000001* ID_MODEL_FROM_DATABASE=Video Toaster for PC pci:v0000149E* ID_VENDOR_FROM_DATABASE=Mapletree Networks Inc. pci:v0000149F* ID_VENDOR_FROM_DATABASE=LECTRON Co Ltd pci:v000014A0* ID_VENDOR_FROM_DATABASE=SOFTING GmBH pci:v000014A1* ID_VENDOR_FROM_DATABASE=Systembase Co Ltd pci:v000014A2* ID_VENDOR_FROM_DATABASE=Millennium Engineering Inc pci:v000014A3* ID_VENDOR_FROM_DATABASE=Maverick Networks pci:v000014A4* ID_VENDOR_FROM_DATABASE=Lite-On Technology Corporation pci:v000014A4d00004318* ID_MODEL_FROM_DATABASE=Broadcom BCM4318 [AirForce One 54g] 802.11g WLAN Controller pci:v000014A5* ID_VENDOR_FROM_DATABASE=XIONICS Document Technologies Inc pci:v000014A6* ID_VENDOR_FROM_DATABASE=INOVA Computers GmBH & Co KG pci:v000014A7* ID_VENDOR_FROM_DATABASE=MYTHOS Systems Inc pci:v000014A8* ID_VENDOR_FROM_DATABASE=FEATRON Technologies Corporation pci:v000014A9* ID_VENDOR_FROM_DATABASE=HIVERTEC Inc pci:v000014AA* ID_VENDOR_FROM_DATABASE=Advanced MOS Technology Inc pci:v000014AB* ID_VENDOR_FROM_DATABASE=Mentor Graphics Corp. pci:v000014AC* ID_VENDOR_FROM_DATABASE=Novaweb Technologies Inc pci:v000014AD* ID_VENDOR_FROM_DATABASE=Time Space Radio AB pci:v000014AE* ID_VENDOR_FROM_DATABASE=CTI, Inc pci:v000014AF* ID_VENDOR_FROM_DATABASE=Guillemot Corporation pci:v000014AFd00007102* ID_MODEL_FROM_DATABASE=3D Prophet II MX pci:v000014B0* ID_VENDOR_FROM_DATABASE=BST Communication Technology Ltd pci:v000014B1* ID_VENDOR_FROM_DATABASE=Nextcom K.K. pci:v000014B2* ID_VENDOR_FROM_DATABASE=ENNOVATE Networks Inc pci:v000014B3* ID_VENDOR_FROM_DATABASE=XPEED Inc pci:v000014B3d00000000* ID_MODEL_FROM_DATABASE=DSL NIC pci:v000014B4* ID_VENDOR_FROM_DATABASE=PHILIPS Business Electronics B.V. pci:v000014B5* ID_VENDOR_FROM_DATABASE=Creamware GmBH pci:v000014B5d00000200* ID_MODEL_FROM_DATABASE=Scope pci:v000014B5d00000300* ID_MODEL_FROM_DATABASE=Pulsar pci:v000014B5d00000400* ID_MODEL_FROM_DATABASE=PulsarSRB pci:v000014B5d00000600* ID_MODEL_FROM_DATABASE=Pulsar2 pci:v000014B5d00000800* ID_MODEL_FROM_DATABASE=DSP-Board pci:v000014B5d00000900* ID_MODEL_FROM_DATABASE=DSP-Board pci:v000014B5d00000A00* ID_MODEL_FROM_DATABASE=DSP-Board pci:v000014B5d00000B00* ID_MODEL_FROM_DATABASE=DSP-Board pci:v000014B6* ID_VENDOR_FROM_DATABASE=Quantum Data Corp. pci:v000014B7* ID_VENDOR_FROM_DATABASE=PROXIM Inc pci:v000014B7d00000001* ID_MODEL_FROM_DATABASE=Symphony 4110 pci:v000014B8* ID_VENDOR_FROM_DATABASE=Techsoft Technology Co Ltd pci:v000014B9* ID_VENDOR_FROM_DATABASE=Cisco Aironet Wireless Communications pci:v000014B9d00000001* ID_MODEL_FROM_DATABASE=PC4800 pci:v000014B9d00000340* ID_MODEL_FROM_DATABASE=PC4800 pci:v000014B9d00000350* ID_MODEL_FROM_DATABASE=350 series 802.11b Wireless LAN Adapter pci:v000014B9d00004500* ID_MODEL_FROM_DATABASE=PC4500 pci:v000014B9d00004800* ID_MODEL_FROM_DATABASE=Cisco Aironet 340 802.11b Wireless LAN Adapter/Aironet PC4800 pci:v000014B9d0000A504* ID_MODEL_FROM_DATABASE=Cisco Aironet Wireless 802.11b pci:v000014B9d0000A505* ID_MODEL_FROM_DATABASE=Cisco Aironet CB20a 802.11a Wireless LAN Adapter pci:v000014B9d0000A506* ID_MODEL_FROM_DATABASE=Cisco Aironet Mini PCI b/g pci:v000014BA* ID_VENDOR_FROM_DATABASE=INTERNIX Inc. pci:v000014BAd00000600* ID_MODEL_FROM_DATABASE=ARC-PCI/22 pci:v000014BB* ID_VENDOR_FROM_DATABASE=SEMTECH Corporation pci:v000014BC* ID_VENDOR_FROM_DATABASE=Globespan Semiconductor Inc. pci:v000014BCd0000D002* ID_MODEL_FROM_DATABASE=Pulsar [PCI ADSL Card] pci:v000014BCd0000D00F* ID_MODEL_FROM_DATABASE=Pulsar [PCI ADSL Card] pci:v000014BD* ID_VENDOR_FROM_DATABASE=CARDIO Control N.V. pci:v000014BE* ID_VENDOR_FROM_DATABASE=L3 Communications pci:v000014BF* ID_VENDOR_FROM_DATABASE=SPIDER Communications Inc. pci:v000014C0* ID_VENDOR_FROM_DATABASE=COMPAL Electronics Inc pci:v000014C1* ID_VENDOR_FROM_DATABASE=MYRICOM Inc. pci:v000014C1d00000008* ID_MODEL_FROM_DATABASE=Myri-10G Dual-Protocol NIC pci:v000014C1d00000008sv000014C1sd00000008* ID_MODEL_FROM_DATABASE=Myri-10G Dual-Protocol NIC (10G-PCIE-8A) pci:v000014C1d00000008sv000014C1sd00000009* ID_MODEL_FROM_DATABASE=Myri-10G Dual-Protocol NIC (10G-PCIE-8A (MSI-X firmware)) pci:v000014C1d00000008sv000014C1sd0000000A* ID_MODEL_FROM_DATABASE=Myri-10G Dual-Protocol NIC (10G-PCIE-8B) pci:v000014C1d00008043* ID_MODEL_FROM_DATABASE=Myrinet 2000 Scalable Cluster Interconnect pci:v000014C1d00008043sv0000103Csd00001240* ID_MODEL_FROM_DATABASE=Myrinet 2000 Scalable Cluster Interconnect (Myrinet M2L-PCI64/2-3.0 LANai 7.4 (HP OEM)) pci:v000014C2* ID_VENDOR_FROM_DATABASE=DTK Computer pci:v000014C3* ID_VENDOR_FROM_DATABASE=MEDIATEK Corp. pci:v000014C3d00007630* ID_MODEL_FROM_DATABASE=MT7630e 802.11bgn Wireless Network Adapter pci:v000014C3d00007662* ID_MODEL_FROM_DATABASE=MT7662E 802.11ac PCI Express Wireless Network Adapter pci:v000014C4* ID_VENDOR_FROM_DATABASE=IWASAKI Information Systems Co Ltd pci:v000014C5* ID_VENDOR_FROM_DATABASE=Automation Products AB pci:v000014C6* ID_VENDOR_FROM_DATABASE=Data Race Inc pci:v000014C7* ID_VENDOR_FROM_DATABASE=Modular Technology Holdings Ltd pci:v000014C8* ID_VENDOR_FROM_DATABASE=Turbocomm Tech. Inc. pci:v000014C9* ID_VENDOR_FROM_DATABASE=ODIN Telesystems Inc pci:v000014CA* ID_VENDOR_FROM_DATABASE=PE Logic Corp. pci:v000014CB* ID_VENDOR_FROM_DATABASE=Billionton Systems Inc pci:v000014CC* ID_VENDOR_FROM_DATABASE=NAKAYO Telecommunications Inc pci:v000014CD* ID_VENDOR_FROM_DATABASE=Universal Scientific Ind. pci:v000014CE* ID_VENDOR_FROM_DATABASE=Whistle Communications pci:v000014CF* ID_VENDOR_FROM_DATABASE=TEK Microsystems Inc. pci:v000014D0* ID_VENDOR_FROM_DATABASE=Ericsson Axe R & D pci:v000014D1* ID_VENDOR_FROM_DATABASE=Computer Hi-Tech Co Ltd pci:v000014D2* ID_VENDOR_FROM_DATABASE=Titan Electronics Inc pci:v000014D2d00008001* ID_MODEL_FROM_DATABASE=VScom 010L 1 port parallel adaptor pci:v000014D2d00008002* ID_MODEL_FROM_DATABASE=VScom 020L 2 port parallel adaptor pci:v000014D2d00008010* ID_MODEL_FROM_DATABASE=VScom 100L 1 port serial adaptor pci:v000014D2d00008011* ID_MODEL_FROM_DATABASE=VScom 110L 1 port serial and 1 port parallel adaptor pci:v000014D2d00008020* ID_MODEL_FROM_DATABASE=VScom 200L 1 or 2 port serial adaptor pci:v000014D2d00008021* ID_MODEL_FROM_DATABASE=VScom 210L 2 port serial and 1 port parallel adaptor pci:v000014D2d00008028* ID_MODEL_FROM_DATABASE=VScom 200I/200I-SI 2-port serial adapter pci:v000014D2d00008040* ID_MODEL_FROM_DATABASE=VScom 400L 4 port serial adaptor pci:v000014D2d00008043* ID_MODEL_FROM_DATABASE=VScom 430L 4-port serial and 3-port parallel adapter pci:v000014D2d00008048* ID_MODEL_FROM_DATABASE=VScom 400I 4-port serial adapter pci:v000014D2d00008080* ID_MODEL_FROM_DATABASE=VScom 800L 8 port serial adaptor pci:v000014D2d00008088* ID_MODEL_FROM_DATABASE=VScom 800I 8-port serial adapter pci:v000014D2d0000A000* ID_MODEL_FROM_DATABASE=VScom 010H 1 port parallel adaptor pci:v000014D2d0000A001* ID_MODEL_FROM_DATABASE=VScom 100H 1 port serial adaptor pci:v000014D2d0000A003* ID_MODEL_FROM_DATABASE=VScom 400H 4 port serial adaptor pci:v000014D2d0000A004* ID_MODEL_FROM_DATABASE=VScom 400HF1 4 port serial adaptor pci:v000014D2d0000A005* ID_MODEL_FROM_DATABASE=VScom 200H 2 port serial adaptor pci:v000014D2d0000A007* ID_MODEL_FROM_DATABASE=VScom PCI800EH (PCIe) 8-port serial adapter Port 1-4 pci:v000014D2d0000A008* ID_MODEL_FROM_DATABASE=VScom PCI800EH (PCIe) 8-port serial adapter Port 5-8 pci:v000014D2d0000A009* ID_MODEL_FROM_DATABASE=VScom PCI400EH (PCIe) 4-port serial adapter pci:v000014D2d0000E001* ID_MODEL_FROM_DATABASE=VScom 010HV2 1 port parallel adaptor pci:v000014D2d0000E010* ID_MODEL_FROM_DATABASE=VScom 100HV2 1 port serial adaptor pci:v000014D2d0000E020* ID_MODEL_FROM_DATABASE=VScom 200HV2 2 port serial adaptor pci:v000014D3* ID_VENDOR_FROM_DATABASE=CIRTECH (UK) Ltd pci:v000014D4* ID_VENDOR_FROM_DATABASE=Panacom Technology Corp pci:v000014D5* ID_VENDOR_FROM_DATABASE=Nitsuko Corporation pci:v000014D6* ID_VENDOR_FROM_DATABASE=Accusys Inc pci:v000014D6d00006101* ID_MODEL_FROM_DATABASE=ACS-61xxx, PCIe to SAS/SATA RAID HBA pci:v000014D6d00006201* ID_MODEL_FROM_DATABASE=ACS-62xxx, External PCIe to SAS/SATA RAID controller pci:v000014D7* ID_VENDOR_FROM_DATABASE=Hirakawa Hewtech Corp pci:v000014D8* ID_VENDOR_FROM_DATABASE=HOPF Elektronik GmBH pci:v000014D9* ID_VENDOR_FROM_DATABASE=Alliance Semiconductor Corporation pci:v000014D9d00000010* ID_MODEL_FROM_DATABASE=AP1011/SP1011 HyperTransport-PCI Bridge [Sturgeon] pci:v000014D9d00009000* ID_MODEL_FROM_DATABASE=AS90L10204/10208 HyperTransport to PCI-X Bridge pci:v000014DA* ID_VENDOR_FROM_DATABASE=National Aerospace Laboratories pci:v000014DB* ID_VENDOR_FROM_DATABASE=AFAVLAB Technology Inc pci:v000014DBd00002120* ID_MODEL_FROM_DATABASE=TK9902 pci:v000014DBd00002182* ID_MODEL_FROM_DATABASE=AFAVLAB Technology Inc. 8-port serial card pci:v000014DC* ID_VENDOR_FROM_DATABASE=Amplicon Liveline Ltd pci:v000014DCd00000000* ID_MODEL_FROM_DATABASE=PCI230 pci:v000014DCd00000001* ID_MODEL_FROM_DATABASE=PCI242 pci:v000014DCd00000002* ID_MODEL_FROM_DATABASE=PCI244 pci:v000014DCd00000003* ID_MODEL_FROM_DATABASE=PCI247 pci:v000014DCd00000004* ID_MODEL_FROM_DATABASE=PCI248 pci:v000014DCd00000005* ID_MODEL_FROM_DATABASE=PCI249 pci:v000014DCd00000006* ID_MODEL_FROM_DATABASE=PCI260 pci:v000014DCd00000007* ID_MODEL_FROM_DATABASE=PCI224 pci:v000014DCd00000008* ID_MODEL_FROM_DATABASE=PCI234 pci:v000014DCd00000009* ID_MODEL_FROM_DATABASE=PCI236 pci:v000014DCd0000000A* ID_MODEL_FROM_DATABASE=PCI272 pci:v000014DCd0000000B* ID_MODEL_FROM_DATABASE=PCI215 pci:v000014DD* ID_VENDOR_FROM_DATABASE=Boulder Design Labs Inc pci:v000014DE* ID_VENDOR_FROM_DATABASE=Applied Integration Corporation pci:v000014DF* ID_VENDOR_FROM_DATABASE=ASIC Communications Corp pci:v000014E1* ID_VENDOR_FROM_DATABASE=INVERTEX pci:v000014E2* ID_VENDOR_FROM_DATABASE=INFOLIBRIA pci:v000014E3* ID_VENDOR_FROM_DATABASE=AMTELCO pci:v000014E4* ID_VENDOR_FROM_DATABASE=Broadcom Corporation pci:v000014E4d00000576* ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n pci:v000014E4d00000800* ID_MODEL_FROM_DATABASE=Sentry5 Chipcommon I/O Controller pci:v000014E4d00000804* ID_MODEL_FROM_DATABASE=Sentry5 PCI Bridge pci:v000014E4d00000805* ID_MODEL_FROM_DATABASE=Sentry5 MIPS32 CPU pci:v000014E4d00000806* ID_MODEL_FROM_DATABASE=Sentry5 Ethernet Controller pci:v000014E4d0000080B* ID_MODEL_FROM_DATABASE=Sentry5 Crypto Accelerator pci:v000014E4d0000080F* ID_MODEL_FROM_DATABASE=Sentry5 DDR/SDR RAM Controller pci:v000014E4d00000811* ID_MODEL_FROM_DATABASE=Sentry5 External Interface Core pci:v000014E4d00000816* ID_MODEL_FROM_DATABASE=BCM3302 Sentry5 MIPS32 CPU pci:v000014E4d00001570* ID_MODEL_FROM_DATABASE=720p FaceTime HD Camera pci:v000014E4d00001600* ID_MODEL_FROM_DATABASE=NetXtreme BCM5752 Gigabit Ethernet PCI Express pci:v000014E4d00001600sv00001028sd000001C1* ID_MODEL_FROM_DATABASE=NetXtreme BCM5752 Gigabit Ethernet PCI Express (Precision 490) pci:v000014E4d00001600sv00001028sd000001C2* ID_MODEL_FROM_DATABASE=NetXtreme BCM5752 Gigabit Ethernet PCI Express (Latitude D620) pci:v000014E4d00001600sv0000103Csd00003015* ID_MODEL_FROM_DATABASE=NetXtreme BCM5752 Gigabit Ethernet PCI Express (PCIe LAN on Motherboard) pci:v000014E4d00001600sv0000107Bsd00005048* ID_MODEL_FROM_DATABASE=NetXtreme BCM5752 Gigabit Ethernet PCI Express (E4500 Onboard) pci:v000014E4d00001600sv00001259sd00002705* ID_MODEL_FROM_DATABASE=NetXtreme BCM5752 Gigabit Ethernet PCI Express (AT-2711FX) pci:v000014E4d00001601* ID_MODEL_FROM_DATABASE=NetXtreme BCM5752M Gigabit Ethernet PCI Express pci:v000014E4d00001612* ID_MODEL_FROM_DATABASE=BCM70012 Video Decoder [Crystal HD] pci:v000014E4d00001615* ID_MODEL_FROM_DATABASE=BCM70015 Video Decoder [Crystal HD] pci:v000014E4d00001639* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet pci:v000014E4d00001639sv00001028sd00000235* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet (PowerEdge R710 BCM5709 Gigabit Ethernet) pci:v000014E4d00001639sv00001028sd00000236* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet (PowerEdge R610 BCM5709 Gigabit Ethernet) pci:v000014E4d00001639sv00001028sd00000237* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet (PowerEdge T610 BCM5709 Gigabit Ethernet) pci:v000014E4d00001639sv0000103Csd00007055* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet (NC382i Integrated Multi-port PCI Express Gigabit Server Adapter) pci:v000014E4d00001639sv0000103Csd00007059* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet (NC382T PCI Express Dual Port Multifunction Gigabit Server Adapter) pci:v000014E4d00001639sv000010A9sd00008027* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet (Quad port Gigabit Ethernet Controller) pci:v000014E4d0000163A* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709S Gigabit Ethernet pci:v000014E4d0000163Asv00001028sd0000027B* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709S Gigabit Ethernet (PowerEdge M805 Broadcom NetXtreme II BCM5709S) pci:v000014E4d0000163Asv00001028sd0000029C* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709S Gigabit Ethernet (PowerEdge M710 BCM5709S Gigabit Ethernet) pci:v000014E4d0000163Asv0000103Csd0000171D* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709S Gigabit Ethernet (NC382m Dual Port 1GbE Multifunction BL-c Adapter) pci:v000014E4d0000163Asv0000103Csd00007056* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709S Gigabit Ethernet (NC382i Integrated Quad Port PCI Express Gigabit Server Adapter) pci:v000014E4d0000163Asv00001259sd00002984* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709S Gigabit Ethernet (AT-2973SX) pci:v000014E4d0000163B* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5716 Gigabit Ethernet pci:v000014E4d0000163Bsv00001028sd0000028C* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5716 Gigabit Ethernet (PowerEdge R410 BCM5716 Gigabit Ethernet) pci:v000014E4d0000163Bsv00001028sd0000028D* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5716 Gigabit Ethernet (PowerEdge T410 BCM5716 Gigabit Ethernet) pci:v000014E4d0000163Bsv00001028sd000002F1* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5716 Gigabit Ethernet (PowerEdge R510 BCM5716 Gigabit Ethernet) pci:v000014E4d0000163C* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5716S Gigabit Ethernet pci:v000014E4d0000163D* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57811 10-Gigabit Ethernet pci:v000014E4d0000163E* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57811 10 Gigabit Ethernet Multi Function pci:v000014E4d0000163F* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57811 10-Gigabit Ethernet Virtual Function pci:v000014E4d00001641* ID_MODEL_FROM_DATABASE=NetXtreme BCM57787 Gigabit Ethernet PCIe pci:v000014E4d00001642* ID_MODEL_FROM_DATABASE=NetXtreme BCM57764 Gigabit Ethernet PCIe pci:v000014E4d00001643* ID_MODEL_FROM_DATABASE=NetXtreme BCM5725 Gigabit Ethernet PCIe pci:v000014E4d00001644* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet pci:v000014E4d00001644sv00001014sd00000277* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (Broadcom Vigil B5700 1000Base-T) pci:v000014E4d00001644sv00001028sd000000D1* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (Broadcom BCM5700) pci:v000014E4d00001644sv00001028sd00000106* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (Broadcom BCM5700) pci:v000014E4d00001644sv00001028sd00000109* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (Broadcom BCM5700 1000Base-T) pci:v000014E4d00001644sv00001028sd0000010A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (Broadcom BCM5700 1000BaseTX) pci:v000014E4d00001644sv000010B7sd00001000* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C996-T 1000Base-T) pci:v000014E4d00001644sv000010B7sd00001001* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C996B-T 1000Base-T) pci:v000014E4d00001644sv000010B7sd00001002* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C996C-T 1000Base-T) pci:v000014E4d00001644sv000010B7sd00001003* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C997-T 1000Base-T Dual Port) pci:v000014E4d00001644sv000010B7sd00001004* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C996-SX 1000Base-SX) pci:v000014E4d00001644sv000010B7sd00001005* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C997-SX 1000Base-SX Dual Port) pci:v000014E4d00001644sv000010B7sd00001008* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C942 Gigabit LOM (31X31)) pci:v000014E4d00001644sv000014E4sd00000002* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (NetXtreme 1000Base-SX) pci:v000014E4d00001644sv000014E4sd00000003* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (NetXtreme 1000Base-SX) pci:v000014E4d00001644sv000014E4sd00000004* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (NetXtreme 1000Base-T) pci:v000014E4d00001644sv000014E4sd00001028* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (NetXtreme 1000BaseTX) pci:v000014E4d00001644sv000014E4sd00001644* ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (BCM5700 1000Base-T) pci:v000014E4d00001645* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet pci:v000014E4d00001645sv00000E11sd0000007C* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (NC7770 Gigabit Server Adapter (PCI-X, 10/100/1000-T)) pci:v000014E4d00001645sv00000E11sd0000007D* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (NC6770 Gigabit Server Adapter (PCI-X, 1000-SX)) pci:v000014E4d00001645sv00000E11sd00000085* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (NC7780 Gigabit Server Adapter (embedded, WOL)) pci:v000014E4d00001645sv00000E11sd00000099* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (NC7780 Gigabit Server Adapter (embedded, WOL)) pci:v000014E4d00001645sv00000E11sd0000009A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (NC7770 Gigabit Server Adapter (PCI-X, 10/100/1000-T)) pci:v000014E4d00001645sv00000E11sd000000C1* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (NC6770 Gigabit Server Adapter (PCI-X, 1000-SX)) pci:v000014E4d00001645sv00001028sd00000121* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (Broadcom BCM5701 1000Base-T) pci:v000014E4d00001645sv0000103Csd0000128A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-T (HP, OEM 3COM)) pci:v000014E4d00001645sv0000103Csd0000128B* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (1000Base-SX (PCI) [A7073A]) pci:v000014E4d00001645sv0000103Csd000012A4* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (Core Lan 1000Base-T) pci:v000014E4d00001645sv0000103Csd000012C1* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (IOX Core Lan 1000Base-T [A7109AX]) pci:v000014E4d00001645sv0000103Csd00001300* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (Core LAN/SCSI Combo [A6794A]) pci:v000014E4d00001645sv000010A9sd00008010* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (IO9/IO10 Gigabit Ethernet (Copper)) pci:v000014E4d00001645sv000010A9sd00008011* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (Gigabit Ethernet (Copper)) pci:v000014E4d00001645sv000010A9sd00008012* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (Gigabit Ethernet (Fiber)) pci:v000014E4d00001645sv000010B7sd00001004* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (3C996-SX 1000Base-SX) pci:v000014E4d00001645sv000010B7sd00001006* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (3C996B-T 1000Base-T) pci:v000014E4d00001645sv000010B7sd00001007* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (3C1000-T 1000Base-T) pci:v000014E4d00001645sv000010B7sd00001008* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (3C940-BR01 1000Base-T) pci:v000014E4d00001645sv000014E4sd00000001* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-T) pci:v000014E4d00001645sv000014E4sd00000005* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-T) pci:v000014E4d00001645sv000014E4sd00000006* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-T) pci:v000014E4d00001645sv000014E4sd00000007* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-SX) pci:v000014E4d00001645sv000014E4sd00000008* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-T) pci:v000014E4d00001645sv000014E4sd00001645* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet pci:v000014E4d00001645sv000014E4sd00008008* ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-T) pci:v000014E4d00001646* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702 Gigabit Ethernet pci:v000014E4d00001646sv00000E11sd000000BB* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702 Gigabit Ethernet (NC7760 1000BaseTX) pci:v000014E4d00001646sv00001028sd00000126* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702 Gigabit Ethernet (Broadcom BCM5702 1000BaseTX) pci:v000014E4d00001646sv000014E4sd00008009* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702 Gigabit Ethernet (BCM5702 1000BaseTX) pci:v000014E4d00001647* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet pci:v000014E4d00001647sv00000E11sd00000099* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NC7780 1000BaseTX) pci:v000014E4d00001647sv00000E11sd0000009A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NC7770 1000BaseTX) pci:v000014E4d00001647sv000010A9sd00008010* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (SGI IO9 Gigabit Ethernet (Copper)) pci:v000014E4d00001647sv000014E4sd00000009* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (BCM5703 1000BaseTX) pci:v000014E4d00001647sv000014E4sd0000000A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (BCM5703 1000BaseSX) pci:v000014E4d00001647sv000014E4sd0000000B* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (BCM5703 1000BaseTX) pci:v000014E4d00001647sv000014E4sd00008009* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (BCM5703 1000BaseTX) pci:v000014E4d00001647sv000014E4sd0000800A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (BCM5703 1000BaseTX) pci:v000014E4d00001648* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet pci:v000014E4d00001648sv00000E11sd000000CF* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (NC7772 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) pci:v000014E4d00001648sv00000E11sd000000D0* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (NC7782 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) pci:v000014E4d00001648sv00000E11sd000000D1* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (NC7783 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) pci:v000014E4d00001648sv00001028sd0000014A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (PowerEdge 1750) pci:v000014E4d00001648sv00001028sd00000170* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (PowerEdge 6850 Broadcom NetXtreme BCM5704) pci:v000014E4d00001648sv0000103Csd0000310F* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (NC7782 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) pci:v000014E4d00001648sv000010A9sd00008013* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (Dual Port Gigabit Ethernet (PCI-X,Copper)) pci:v000014E4d00001648sv000010A9sd00008018* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (Dual Port Gigabit Ethernet (A330)) pci:v000014E4d00001648sv000010A9sd0000801A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (Dual Port Gigabit Ethernet (IA-blade)) pci:v000014E4d00001648sv000010A9sd0000801B* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (Quad Port Gigabit Ethernet (PCI-E,Copper)) pci:v000014E4d00001648sv000010B7sd00002000* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (3C998-T Dual Port 10/100/1000 PCI-X) pci:v000014E4d00001648sv000010B7sd00003000* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (3C999-T Quad Port 10/100/1000 PCI-X) pci:v000014E4d00001648sv00001166sd00001648* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (NetXtreme CIOB-E 1000Base-T) pci:v000014E4d00001648sv00001734sd0000100B* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (PRIMERGY RX/TX series onboard LAN) pci:v000014E4d00001649* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704S_2 Gigabit Ethernet pci:v000014E4d0000164A* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706 Gigabit Ethernet pci:v000014E4d0000164Asv0000103Csd00001709* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706 Gigabit Ethernet (NC371i Integrated PCI-X Multifunction Gigabit Server Adapter) pci:v000014E4d0000164Asv0000103Csd00003070* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706 Gigabit Ethernet (NC380T PCI Express Dual Port Multifunction Gigabit Server Adapter) pci:v000014E4d0000164Asv0000103Csd00003101* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706 Gigabit Ethernet (NC370T MultifuNCtion Gigabit Server Adapter) pci:v000014E4d0000164Asv0000103Csd00003106* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706 Gigabit Ethernet (NC370i Multifunction Gigabit Server Adapter) pci:v000014E4d0000164C* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet pci:v000014E4d0000164Csv00001028sd000001F0* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (PowerEdge R900 Broadcom NetXtreme II BCM5708) pci:v000014E4d0000164Csv00001028sd00000205* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (PowerEdge 2970 Broadcom NetXtreme II BCM5708) pci:v000014E4d0000164Csv00001028sd0000020B* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (PowerEdge T605 Broadcom NetXtreme II BCM5708) pci:v000014E4d0000164Csv00001028sd00000221* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (PowerEdge R805 Broadcom NetXtreme II BCM5708) pci:v000014E4d0000164Csv00001028sd00000223* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (PowerEdge R905 Broadcom NetXtreme II BCM5708) pci:v000014E4d0000164Csv00001028sd00001F12* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (PowerEdge R805/R905 Broadcom NetXtreme II BCM5708) pci:v000014E4d0000164Csv0000103Csd00007037* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (NC373T PCI Express Multifunction Gigabit Server Adapter) pci:v000014E4d0000164Csv0000103Csd00007038* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (NC373i Integrated Multifunction Gigabit Server Adapter) pci:v000014E4d0000164Csv0000103Csd00007045* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (NC374m PCI Express Dual Port Multifunction Gigabit Server Adapter) pci:v000014E4d0000164D* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702FE Gigabit Ethernet pci:v000014E4d0000164E* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57710 10-Gigabit PCIe [Everest] pci:v000014E4d0000164Esv0000103Csd0000171C* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57710 10-Gigabit PCIe [Everest] (NC532m Dual Port 10GbE Multifunction BL-C Adapter) pci:v000014E4d0000164Esv0000103Csd00007058* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57710 10-Gigabit PCIe [Everest] (NC532i Dual Port 10GbE Multifunction BL-C Adapter) pci:v000014E4d0000164F* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57711 10-Gigabit PCIe pci:v000014E4d00001650* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57711E 10-Gigabit PCIe pci:v000014E4d00001650sv0000103Csd0000171C* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57711E 10-Gigabit PCIe (NC532m Dual Port 10GbE Multifunction BL-C Adapter) pci:v000014E4d00001650sv0000103Csd00007058* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57711E 10-Gigabit PCIe (NC532i Dual Port 10GbE Multifunction BL-C Adapter) pci:v000014E4d00001653* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705 Gigabit Ethernet pci:v000014E4d00001653sv00000E11sd000000E3* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705 Gigabit Ethernet (NC7761 Gigabit Server Adapter) pci:v000014E4d00001653sv00001734sd00001073* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705 Gigabit Ethernet (Primergy Econel 200 D2020 mainboard) pci:v000014E4d00001654* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705_2 Gigabit Ethernet pci:v000014E4d00001654sv00000E11sd000000E3* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705_2 Gigabit Ethernet (NC7761 Gigabit Server Adapter) pci:v000014E4d00001654sv0000103Csd00003100* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705_2 Gigabit Ethernet (NC1020 ProLiant Gigabit Server Adapter 32 PCI) pci:v000014E4d00001654sv0000103Csd00003226* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705_2 Gigabit Ethernet (NC150T 4-port Gigabit Combo Switch & Adapter) pci:v000014E4d00001655* ID_MODEL_FROM_DATABASE=NetXtreme BCM5717 Gigabit Ethernet PCIe pci:v000014E4d00001656* ID_MODEL_FROM_DATABASE=NetXtreme BCM5718 Gigabit Ethernet PCIe pci:v000014E4d00001657* ID_MODEL_FROM_DATABASE=NetXtreme BCM5719 Gigabit Ethernet PCIe pci:v000014E4d00001657sv0000103Csd0000169D* ID_MODEL_FROM_DATABASE=NetXtreme BCM5719 Gigabit Ethernet PCIe (Ethernet 1Gb 4-port 331FLR Adapter) pci:v000014E4d00001657sv0000103Csd000022BE* ID_MODEL_FROM_DATABASE=NetXtreme BCM5719 Gigabit Ethernet PCIe (Ethernet 1Gb 4-port 331i Adapter) pci:v000014E4d00001659* ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express pci:v000014E4d00001659sv00001014sd000002C6* ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (eServer xSeries server mainboard) pci:v000014E4d00001659sv00001028sd000001E6* ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (PowerEdge 860) pci:v000014E4d00001659sv00001028sd0000023C* ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (PowerEdge R200 Broadcom NetXtreme BCM5721) pci:v000014E4d00001659sv0000103Csd0000170B* ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (NC320m PCI Express Dual Port Gigabit Server Adapter) pci:v000014E4d00001659sv0000103Csd00007031* ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (NC320T PCIe Gigabit Server Adapter) pci:v000014E4d00001659sv0000103Csd00007032* ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (NC320i PCIe Gigabit Server Adapter) pci:v000014E4d00001659sv00001734sd00001061* ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (PRIMERGY RX/TX S2 series onboard LAN) pci:v000014E4d0000165A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express pci:v000014E4d0000165Asv00001014sd00000378* ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (IBM System x3350 (Machine type 4192)) pci:v000014E4d0000165Asv00001028sd0000020F* ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (PowerEdge R300 Broadcom NetXtreme 5722) pci:v000014E4d0000165Asv00001028sd00000210* ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (PowerEdge T300 Broadcom NetXtreme 5722) pci:v000014E4d0000165Asv00001028sd00000225* ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (PowerEdge T105 Broadcom NetXtreme 5722) pci:v000014E4d0000165Asv0000103Csd00007051* ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (NC105i PCIe Gigabit Server Adapter) pci:v000014E4d0000165Asv0000103Csd00007052* ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (NC105T PCIe Gigabit Server Adapter) pci:v000014E4d0000165B* ID_MODEL_FROM_DATABASE=NetXtreme BCM5723 Gigabit Ethernet PCIe pci:v000014E4d0000165Bsv0000103Csd0000705D* ID_MODEL_FROM_DATABASE=NetXtreme BCM5723 Gigabit Ethernet PCIe (NC107i Integrated PCI Express Gigabit Server Adapter) pci:v000014E4d0000165C* ID_MODEL_FROM_DATABASE=NetXtreme BCM5724 Gigabit Ethernet PCIe pci:v000014E4d0000165D* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M Gigabit Ethernet pci:v000014E4d0000165Dsv00001028sd0000865D* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M Gigabit Ethernet (Latitude D400) pci:v000014E4d0000165Dsv000014E4sd0000165D* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M Gigabit Ethernet (Dell Latitude D600) pci:v000014E4d0000165E* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M_2 Gigabit Ethernet pci:v000014E4d0000165Esv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M_2 Gigabit Ethernet (NC8000 laptop) pci:v000014E4d0000165Esv0000103Csd00000890* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M_2 Gigabit Ethernet (NC6000 laptop) pci:v000014E4d0000165Esv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M_2 Gigabit Ethernet (NX6110/NC6120) pci:v000014E4d0000165Esv000010CFsd00001279* ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M_2 Gigabit Ethernet (LifeBook E8010D) pci:v000014E4d0000165F* ID_MODEL_FROM_DATABASE=NetXtreme BCM5720 Gigabit Ethernet PCIe pci:v000014E4d00001662* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57712 10 Gigabit Ethernet pci:v000014E4d00001663* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57712 10 Gigabit Ethernet Multi Function pci:v000014E4d00001665* ID_MODEL_FROM_DATABASE=NetXtreme BCM5717 Gigabit Ethernet PCIe pci:v000014E4d00001668* ID_MODEL_FROM_DATABASE=NetXtreme BCM5714 Gigabit Ethernet pci:v000014E4d00001668sv0000103Csd00007039* ID_MODEL_FROM_DATABASE=NetXtreme BCM5714 Gigabit Ethernet (NC324i PCIe Dual Port Gigabit Server Adapter) pci:v000014E4d00001669* ID_MODEL_FROM_DATABASE=NetXtreme 5714S Gigabit Ethernet pci:v000014E4d0000166A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5780 Gigabit Ethernet pci:v000014E4d0000166Asv0000103Csd00007035* ID_MODEL_FROM_DATABASE=NetXtreme BCM5780 Gigabit Ethernet (NC325i Integrated Dual port PCIe Express Gigabit Server Adapter) pci:v000014E4d0000166B* ID_MODEL_FROM_DATABASE=NetXtreme BCM5780S Gigabit Ethernet pci:v000014E4d0000166E* ID_MODEL_FROM_DATABASE=570x 10/100 Integrated Controller pci:v000014E4d0000166F* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57712 10 Gigabit Ethernet Virtual Function pci:v000014E4d00001672* ID_MODEL_FROM_DATABASE=NetXtreme BCM5754M Gigabit Ethernet PCI Express pci:v000014E4d00001673* ID_MODEL_FROM_DATABASE=NetXtreme BCM5755M Gigabit Ethernet PCI Express pci:v000014E4d00001674* ID_MODEL_FROM_DATABASE=NetXtreme BCM5756ME Gigabit Ethernet PCI Express pci:v000014E4d00001677* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express pci:v000014E4d00001677sv00001028sd00000176* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Dimension XPS Gen 4) pci:v000014E4d00001677sv00001028sd00000177* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Dimension 8400) pci:v000014E4d00001677sv00001028sd00000179* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Optiplex GX280) pci:v000014E4d00001677sv00001028sd00000182* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Latitude D610) pci:v000014E4d00001677sv00001028sd00000187* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Precision M70) pci:v000014E4d00001677sv00001028sd000001A8* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Precision 380) pci:v000014E4d00001677sv00001028sd000001AD* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (OptiPlex GX620) pci:v000014E4d00001677sv0000103Csd00003006* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (DC7100 SFF(DX878AV)) pci:v000014E4d00001677sv00001462sd0000028C* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (915P/G Neo2) pci:v000014E4d00001677sv00001734sd0000105D* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Scenic W620) pci:v000014E4d00001678* ID_MODEL_FROM_DATABASE=NetXtreme BCM5715 Gigabit Ethernet pci:v000014E4d00001678sv0000103Csd0000703E* ID_MODEL_FROM_DATABASE=NetXtreme BCM5715 Gigabit Ethernet (NC326i PCIe Dual Port Gigabit Server Adapter) pci:v000014E4d00001679* ID_MODEL_FROM_DATABASE=NetXtreme BCM5715S Gigabit Ethernet pci:v000014E4d00001679sv0000103Csd00001707* ID_MODEL_FROM_DATABASE=NetXtreme BCM5715S Gigabit Ethernet (NC326m PCIe Dual Port Adapter) pci:v000014E4d00001679sv0000103Csd0000170C* ID_MODEL_FROM_DATABASE=NetXtreme BCM5715S Gigabit Ethernet (NC325m PCIe Quad Port Adapter) pci:v000014E4d00001679sv0000103Csd0000703C* ID_MODEL_FROM_DATABASE=NetXtreme BCM5715S Gigabit Ethernet (NC326i PCIe Dual Port Gigabit Server Adapter) pci:v000014E4d0000167A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5754 Gigabit Ethernet PCI Express pci:v000014E4d0000167Asv00001028sd000001DA* ID_MODEL_FROM_DATABASE=NetXtreme BCM5754 Gigabit Ethernet PCI Express (OptiPlex 745) pci:v000014E4d0000167Asv00001028sd000001DE* ID_MODEL_FROM_DATABASE=NetXtreme BCM5754 Gigabit Ethernet PCI Express (Precision 390) pci:v000014E4d0000167Asv00001028sd000001DF* ID_MODEL_FROM_DATABASE=NetXtreme BCM5754 Gigabit Ethernet PCI Express (PowerEdge SC440) pci:v000014E4d0000167Asv00001028sd00000214* ID_MODEL_FROM_DATABASE=NetXtreme BCM5754 Gigabit Ethernet PCI Express (Precision T3400) pci:v000014E4d0000167Asv00001028sd0000021E* ID_MODEL_FROM_DATABASE=NetXtreme BCM5754 Gigabit Ethernet PCI Express (Precision T5400) pci:v000014E4d0000167B* ID_MODEL_FROM_DATABASE=NetXtreme BCM5755 Gigabit Ethernet PCI Express pci:v000014E4d0000167Bsv0000103Csd0000280A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5755 Gigabit Ethernet PCI Express (DC5750 Microtower) pci:v000014E4d0000167D* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751M Gigabit Ethernet PCI Express pci:v000014E4d0000167Dsv00001014sd00000577* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751M Gigabit Ethernet PCI Express (ThinkPad Z60t) pci:v000014E4d0000167Dsv0000103Csd00000934* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751M Gigabit Ethernet PCI Express (nx8220) pci:v000014E4d0000167Dsv0000103Csd00000940* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751M Gigabit Ethernet PCI Express (Compaq nw8240 Mobile Workstation) pci:v000014E4d0000167Dsv000017AAsd00002081* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751M Gigabit Ethernet PCI Express (ThinkPad R60e) pci:v000014E4d0000167E* ID_MODEL_FROM_DATABASE=NetXtreme BCM5751F Fast Ethernet PCI Express pci:v000014E4d0000167F* ID_MODEL_FROM_DATABASE=NetLink BCM5787F Fast Ethernet PCI Express pci:v000014E4d00001680* ID_MODEL_FROM_DATABASE=NetXtreme BCM5761e Gigabit Ethernet PCIe pci:v000014E4d00001681* ID_MODEL_FROM_DATABASE=NetXtreme BCM5761 Gigabit Ethernet PCIe pci:v000014E4d00001682* ID_MODEL_FROM_DATABASE=NetXtreme BCM57762 Gigabit Ethernet PCIe pci:v000014E4d00001683* ID_MODEL_FROM_DATABASE=NetXtreme BCM57767 Gigabit Ethernet PCIe pci:v000014E4d00001684* ID_MODEL_FROM_DATABASE=NetXtreme BCM5764M Gigabit Ethernet PCIe pci:v000014E4d00001685* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57500S Gigabit Ethernet pci:v000014E4d00001686* ID_MODEL_FROM_DATABASE=NetXtreme BCM57766 Gigabit Ethernet PCIe pci:v000014E4d00001687* ID_MODEL_FROM_DATABASE=NetXtreme BCM5762 Gigabit Ethernet PCIe pci:v000014E4d00001688* ID_MODEL_FROM_DATABASE=NetXtreme BCM5761 10/100/1000BASE-T Ethernet pci:v000014E4d00001688sv00001259sd00002708* ID_MODEL_FROM_DATABASE=NetXtreme BCM5761 10/100/1000BASE-T Ethernet (AT-2712 FX) pci:v000014E4d0000168A* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet pci:v000014E4d0000168Asv00001028sd00001F5C* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet (BCM57800 10-Gigabit Ethernet) pci:v000014E4d0000168Asv00001028sd00001F5D* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet (BCM57800 10-Gigabit Ethernet) pci:v000014E4d0000168Asv00001028sd00001F67* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet (BCM57800 1-Gigabit Ethernet) pci:v000014E4d0000168Asv00001028sd00001F68* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet (BCM57800 1-Gigabit Ethernet) pci:v000014E4d0000168D* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet pci:v000014E4d0000168E* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet pci:v000014E4d0000168Esv0000103Csd00001798* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (Flex-10 10Gb 2-port 530FLB Adapter [Meru]) pci:v000014E4d0000168Esv0000103Csd000017A5* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (Flex-10 10Gb 2-port 530M Adapter) pci:v000014E4d0000168Esv0000103Csd000018D3* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (Ethernet 10Gb 2-port 530T Adapter) pci:v000014E4d0000168Esv0000103Csd00001930* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (FlexFabric 10Gb 2-port 534FLR-SFP+ Adapter) pci:v000014E4d0000168Esv0000103Csd00001931* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (StoreFabric CN1100R Dual Port Converged Network Adapter) pci:v000014E4d0000168Esv0000103Csd00001932* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (FlexFabric 10Gb 2-port 534FLB Adapter) pci:v000014E4d0000168Esv0000103Csd00001933* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (FlexFabric 10Gb 2-port 534M Adapter) pci:v000014E4d0000168Esv0000103Csd0000193A* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (FlexFabric 10Gb 2-port 533FLR-T Adapter) pci:v000014E4d0000168Esv0000103Csd00003382* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (Ethernet 10Gb 2-port 530FLR-SFP+ Adapter) pci:v000014E4d0000168Esv0000103Csd0000339D* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (Ethernet 10Gb 2-port 530SFP+ Adapter) pci:v000014E4d00001690* ID_MODEL_FROM_DATABASE=NetXtreme BCM57760 Gigabit Ethernet PCIe pci:v000014E4d00001691* ID_MODEL_FROM_DATABASE=NetLink BCM57788 Gigabit Ethernet PCIe pci:v000014E4d00001691sv00001028sd000004AA* ID_MODEL_FROM_DATABASE=NetLink BCM57788 Gigabit Ethernet PCIe (XPS 8300) pci:v000014E4d00001692* ID_MODEL_FROM_DATABASE=NetLink BCM57780 Gigabit Ethernet PCIe pci:v000014E4d00001692sv00001025sd0000033D* ID_MODEL_FROM_DATABASE=NetLink BCM57780 Gigabit Ethernet PCIe (Aspire 7740G) pci:v000014E4d00001693* ID_MODEL_FROM_DATABASE=NetLink BCM5787M Gigabit Ethernet PCI Express pci:v000014E4d00001693sv00001025sd00000121* ID_MODEL_FROM_DATABASE=NetLink BCM5787M Gigabit Ethernet PCI Express (Aspire 5920G) pci:v000014E4d00001693sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=NetLink BCM5787M Gigabit Ethernet PCI Express (6710b) pci:v000014E4d00001694* ID_MODEL_FROM_DATABASE=NetLink BCM57790 Gigabit Ethernet PCIe pci:v000014E4d00001696* ID_MODEL_FROM_DATABASE=NetXtreme BCM5782 Gigabit Ethernet pci:v000014E4d00001696sv0000103Csd000012BC* ID_MODEL_FROM_DATABASE=NetXtreme BCM5782 Gigabit Ethernet (d530 CMT (DG746A)) pci:v000014E4d00001696sv000014E4sd0000000D* ID_MODEL_FROM_DATABASE=NetXtreme BCM5782 Gigabit Ethernet (NetXtreme BCM5782 1000Base-T) pci:v000014E4d00001698* ID_MODEL_FROM_DATABASE=NetLink BCM5784M Gigabit Ethernet PCIe pci:v000014E4d00001699* ID_MODEL_FROM_DATABASE=NetLink BCM5785 Gigabit Ethernet pci:v000014E4d0000169A* ID_MODEL_FROM_DATABASE=NetLink BCM5786 Gigabit Ethernet PCI Express pci:v000014E4d0000169B* ID_MODEL_FROM_DATABASE=NetLink BCM5787 Gigabit Ethernet PCI Express pci:v000014E4d0000169C* ID_MODEL_FROM_DATABASE=NetXtreme BCM5788 Gigabit Ethernet pci:v000014E4d0000169Csv0000103Csd0000308B* ID_MODEL_FROM_DATABASE=NetXtreme BCM5788 Gigabit Ethernet (MX6125) pci:v000014E4d0000169Csv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=NetXtreme BCM5788 Gigabit Ethernet (NC2400) pci:v000014E4d0000169Csv0000144Dsd0000C018* ID_MODEL_FROM_DATABASE=NetXtreme BCM5788 Gigabit Ethernet (X20) pci:v000014E4d0000169Csv00001462sd0000590C* ID_MODEL_FROM_DATABASE=NetXtreme BCM5788 Gigabit Ethernet (KT6 Delta-FIS2R (MS-6590)) pci:v000014E4d0000169D* ID_MODEL_FROM_DATABASE=NetLink BCM5789 Gigabit Ethernet PCI Express pci:v000014E4d000016A0* ID_MODEL_FROM_DATABASE=NetLink BCM5785 Fast Ethernet pci:v000014E4d000016A1* ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10 Gigabit Ethernet pci:v000014E4d000016A2* ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10/20-Gigabit Ethernet pci:v000014E4d000016A2sv0000103Csd00001916* ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10/20-Gigabit Ethernet (FlexFabric 20Gb 2-port 630FLB Adapter) pci:v000014E4d000016A2sv0000103Csd00001917* ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10/20-Gigabit Ethernet (FlexFabric 20Gb 2-port 630M Adapter) pci:v000014E4d000016A2sv0000103Csd00002231* ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10/20-Gigabit Ethernet (3820C 10/20Gb Converged Network Adapter) pci:v000014E4d000016A2sv0000103Csd000022FA* ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10/20-Gigabit Ethernet (FlexFabric 10Gb 2-port 536FLB Adapter) pci:v000014E4d000016A3* ID_MODEL_FROM_DATABASE=NetXtreme BCM57786 Gigabit Ethernet PCIe pci:v000014E4d000016A4* ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II Ethernet Multi Function pci:v000014E4d000016A4sv0000103Csd00001916* ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II Ethernet Multi Function (NPAR 20Gb 2-port 630FLB Adapter) pci:v000014E4d000016A4sv0000103Csd00001917* ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II Ethernet Multi Function (NPAR 20Gb 2-port 630M Adapter) pci:v000014E4d000016A4sv0000103Csd00002231* ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II Ethernet Multi Function (3820C 10/20Gb Converged Network Adapter (NPAR 1.5)) pci:v000014E4d000016A4sv0000103Csd000022FA* ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II Ethernet Multi Function (FlexFabric 10Gb 2-port 536FLB Adapter (NPAR 1.5)) pci:v000014E4d000016A5* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Multi Function pci:v000014E4d000016A5sv00001028sd00001F5C* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Multi Function (NetXtreme II BCM57800 10-Gigabit Ethernet Multi Function) pci:v000014E4d000016A5sv00001028sd00001F5D* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Multi Function (NetXtreme II BCM57800 10-Gigabit Ethernet Multi Function) pci:v000014E4d000016A5sv00001028sd00001F67* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Multi Function (NetXtreme II BCM57800 1-Gigabit Ethernet Multi Function) pci:v000014E4d000016A5sv00001028sd00001F68* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Multi Function (NetXtreme II BCM57800 1-Gigabit Ethernet Multi Function) pci:v000014E4d000016A6* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702X Gigabit Ethernet pci:v000014E4d000016A6sv00000E11sd000000BB* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702X Gigabit Ethernet (NC7760 Gigabit Server Adapter (PCI-X, 10/100/1000-T)) pci:v000014E4d000016A6sv00001028sd00000126* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702X Gigabit Ethernet (BCM5702 1000Base-T) pci:v000014E4d000016A6sv000014E4sd0000000C* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702X Gigabit Ethernet (BCM5702 1000Base-T) pci:v000014E4d000016A6sv000014E4sd00008009* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702X Gigabit Ethernet (BCM5702 1000Base-T) pci:v000014E4d000016A7* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet pci:v000014E4d000016A7sv00000E11sd000000CA* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) pci:v000014E4d000016A7sv00000E11sd000000CB* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (NC7781 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) pci:v000014E4d000016A7sv00001014sd0000026F* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (eServer xSeries server mainboard) pci:v000014E4d000016A7sv000014E4sd00000009* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (NetXtreme BCM5703 1000Base-T) pci:v000014E4d000016A7sv000014E4sd0000000A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (NetXtreme BCM5703 1000Base-SX) pci:v000014E4d000016A7sv000014E4sd0000000B* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (NetXtreme BCM5703 1000Base-T) pci:v000014E4d000016A7sv000014E4sd0000800A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (NetXtreme BCM5703 1000Base-T) pci:v000014E4d000016A8* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704S Gigabit Ethernet pci:v000014E4d000016A8sv0000103Csd0000132B* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704S Gigabit Ethernet (PCI-X 1000Mbps Dual-port Built-in) pci:v000014E4d000016A8sv000010A9sd00008014* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704S Gigabit Ethernet (Dual Port Gigabit Ethernet (PCI-X,Fiber)) pci:v000014E4d000016A8sv000010A9sd0000801C* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704S Gigabit Ethernet (Quad Port Gigabit Ethernet (PCI-E,Fiber)) pci:v000014E4d000016A8sv000010B7sd00002001* ID_MODEL_FROM_DATABASE=NetXtreme BCM5704S Gigabit Ethernet (3C998-SX Dual Port 1000-SX PCI-X) pci:v000014E4d000016A9* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Virtual Function pci:v000014E4d000016A9sv00001028sd00001F5C* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Virtual Function (NetXtreme II BCM57800 10-Gigabit Ethernet Virtual Function) pci:v000014E4d000016A9sv00001028sd00001F5D* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Virtual Function (NetXtreme II BCM57800 10-Gigabit Ethernet Virtual Function) pci:v000014E4d000016A9sv00001028sd00001F67* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Virtual Function (NetXtreme II BCM57800 1-Gigabit Ethernet Virtual Function) pci:v000014E4d000016A9sv00001028sd00001F68* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Virtual Function (NetXtreme II BCM57800 1-Gigabit Ethernet Virtual Function) pci:v000014E4d000016AA* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706S Gigabit Ethernet pci:v000014E4d000016AAsv0000103Csd00003102* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706S Gigabit Ethernet (NC370F MultifuNCtion Gigabit Server Adapter) pci:v000014E4d000016AAsv0000103Csd0000310C* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706S Gigabit Ethernet (NC370i Multifunction Gigabit Server Adapter) pci:v000014E4d000016AB* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet Multi Function pci:v000014E4d000016AC* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet pci:v000014E4d000016ACsv00001014sd00000304* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet pci:v000014E4d000016ACsv00001028sd000001BB* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet (PowerEdge 1955 Broadcom NetXtreme II BCM5708S) pci:v000014E4d000016ACsv00001028sd0000020C* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet (PowerEdge M605 Broadcom NetXtreme II BCM5708S) pci:v000014E4d000016ACsv0000103Csd00001706* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet (NC373m Multifunction Gigabit Server Adapter) pci:v000014E4d000016ACsv0000103Csd00007038* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet (NC373i PCI Express Multifunction Gigabit Server Adapter) pci:v000014E4d000016ACsv0000103Csd0000703B* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet (NC373i Integrated Multifunction Gigabit Server Adapter) pci:v000014E4d000016ACsv0000103Csd0000703D* ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet (NC373F PCI Express Multifunction Gigabit Server Adapter) pci:v000014E4d000016AD* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function pci:v000014E4d000016ADsv0000103Csd00001916* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function (FlexFabric 20Gb 2-port 630FLB Adapter) pci:v000014E4d000016ADsv0000103Csd00001917* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function (FlexFabric 20Gb 2-port 630M Adapter) pci:v000014E4d000016ADsv0000103Csd00002231* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function (3820C 10/20Gb Converged Network Adapter (SR-IOV VF)) pci:v000014E4d000016ADsv0000103Csd000022FA* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function (FlexFabric 10Gb 2-port 536FLB Adapter (SR-IOV VF)) pci:v000014E4d000016AE* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function pci:v000014E4d000016AEsv0000103Csd00001798* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 530FLB Adapter) pci:v000014E4d000016AEsv0000103Csd000017A5* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 530M Adapter) pci:v000014E4d000016AEsv0000103Csd000018D3* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 530T Adapter) pci:v000014E4d000016AEsv0000103Csd00001930* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 534FLR-SFP+ Adapter) pci:v000014E4d000016AEsv0000103Csd00001931* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR CN1100R Dual Port Converged Network Adapter) pci:v000014E4d000016AEsv0000103Csd00001932* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 534FLB Adapter) pci:v000014E4d000016AEsv0000103Csd00001933* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 534M Adapter) pci:v000014E4d000016AEsv0000103Csd0000193A* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 533FLR-T Adapter) pci:v000014E4d000016AEsv0000103Csd00003382* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 530FLR-SFP+ Adapter) pci:v000014E4d000016AEsv0000103Csd0000339D* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 530SFP+ Adapter) pci:v000014E4d000016AF* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function pci:v000014E4d000016AFsv0000103Csd00001798* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (Flex-10 10Gb 2-port 530FLB Adapter) pci:v000014E4d000016AFsv0000103Csd000017A5* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (Flex-10 10Gb 2-port 530M Adapter) pci:v000014E4d000016AFsv0000103Csd000018D3* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (Ethernet 10Gb 2-port 530T Adapter) pci:v000014E4d000016AFsv0000103Csd00001930* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (FlexFabric 10Gb 2-port 534FLR-SFP+ Adapter) pci:v000014E4d000016AFsv0000103Csd00001931* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (StoreFabric CN1100R Dual Port Converged Network Adapter) pci:v000014E4d000016AFsv0000103Csd00001932* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (FlexFabric 10Gb 2-port 534FLB Adapter) pci:v000014E4d000016AFsv0000103Csd00001933* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (FlexFabric 10Gb 2-port 534M Adapter) pci:v000014E4d000016AFsv0000103Csd0000193A* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (FlexFabric 10Gb 2-port 533FLR-T Adapter) pci:v000014E4d000016AFsv0000103Csd00003382* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (Ethernet 10Gb 2-port 530FLR-SFP+ Adapter) pci:v000014E4d000016AFsv0000103Csd0000339D* ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (Ethernet 10Gb 2-port 530SFP+ Adapter) pci:v000014E4d000016B0* ID_MODEL_FROM_DATABASE=NetXtreme BCM57761 Gigabit Ethernet PCIe pci:v000014E4d000016B1* ID_MODEL_FROM_DATABASE=NetLink BCM57781 Gigabit Ethernet PCIe pci:v000014E4d000016B1sv00001849sd000096B1* ID_MODEL_FROM_DATABASE=NetLink BCM57781 Gigabit Ethernet PCIe (Z77 Extreme4 motherboard) pci:v000014E4d000016B2* ID_MODEL_FROM_DATABASE=NetLink BCM57791 Gigabit Ethernet PCIe pci:v000014E4d000016B3* ID_MODEL_FROM_DATABASE=NetXtreme BCM57786 Gigabit Ethernet PCIe pci:v000014E4d000016B4* ID_MODEL_FROM_DATABASE=NetXtreme BCM57765 Gigabit Ethernet PCIe pci:v000014E4d000016B5* ID_MODEL_FROM_DATABASE=NetLink BCM57785 Gigabit Ethernet PCIe pci:v000014E4d000016B6* ID_MODEL_FROM_DATABASE=NetLink BCM57795 Gigabit Ethernet PCIe pci:v000014E4d000016B7* ID_MODEL_FROM_DATABASE=NetXtreme BCM57782 Gigabit Ethernet PCIe pci:v000014E4d000016BC* ID_MODEL_FROM_DATABASE=BCM57765/57785 SDXC/MMC Card Reader pci:v000014E4d000016BE* ID_MODEL_FROM_DATABASE=BCM57765/57785 MS Card Reader pci:v000014E4d000016BF* ID_MODEL_FROM_DATABASE=BCM57765/57785 xD-Picture Card Reader pci:v000014E4d000016C6* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702A3 Gigabit Ethernet pci:v000014E4d000016C6sv000010B7sd00001100* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702A3 Gigabit Ethernet (3C1000B-T 10/100/1000 PCI) pci:v000014E4d000016C6sv000014E4sd0000000C* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702A3 Gigabit Ethernet (BCM5702 1000Base-T) pci:v000014E4d000016C6sv000014E4sd00008009* ID_MODEL_FROM_DATABASE=NetXtreme BCM5702A3 Gigabit Ethernet (BCM5702 1000Base-T) pci:v000014E4d000016C7* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet pci:v000014E4d000016C7sv00000E11sd000000CA* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) pci:v000014E4d000016C7sv00000E11sd000000CB* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NC7781 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) pci:v000014E4d000016C7sv0000103Csd000012C3* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (Combo FC/GigE-SX [A9782A]) pci:v000014E4d000016C7sv0000103Csd000012CA* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (Combo FC/GigE-T [A9784A]) pci:v000014E4d000016C7sv0000103Csd00001321* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (Core I/O LAN/SCSI Combo [AB314A]) pci:v000014E4d000016C7sv000014E4sd00000009* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NetXtreme BCM5703 1000Base-T) pci:v000014E4d000016C7sv000014E4sd0000000A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NetXtreme BCM5703 1000Base-SX) pci:v000014E4d000016C8* ID_MODEL_FROM_DATABASE=BCM57301 NetXtreme-C Single-port 10Gb Ethernet pci:v000014E4d000016C9* ID_MODEL_FROM_DATABASE=BCM57302 NetXtreme-C Dual-port 10Gb/25Gb Ethernet pci:v000014E4d000016CA* ID_MODEL_FROM_DATABASE=BCM57304 NetXtreme-C Dual-port 10Gb/25Gb/40Gb/50Gb Ethernet pci:v000014E4d000016CB* ID_MODEL_FROM_DATABASE=BCM57304 NetXtreme-C Ethernet Virtual Function pci:v000014E4d000016D0* ID_MODEL_FROM_DATABASE=BCM57402 NetXtreme-E Dual-port 10Gb Ethernet pci:v000014E4d000016D1* ID_MODEL_FROM_DATABASE=BCM57404 NetXtreme-E Dual-port 10Gb/25Gb Ethernet pci:v000014E4d000016D2* ID_MODEL_FROM_DATABASE=BCM57406 NetXtreme-E Dual-port 10GBase-T Ethernet pci:v000014E4d000016D3* ID_MODEL_FROM_DATABASE=BCM57404 NetXtreme-E Ethernet Virtual Function pci:v000014E4d000016DD* ID_MODEL_FROM_DATABASE=NetLink BCM5781 Gigabit Ethernet PCI Express pci:v000014E4d000016F3* ID_MODEL_FROM_DATABASE=NetXtreme BCM5727 Gigabit Ethernet PCIe pci:v000014E4d000016F7* ID_MODEL_FROM_DATABASE=NetXtreme BCM5753 Gigabit Ethernet PCI Express pci:v000014E4d000016FD* ID_MODEL_FROM_DATABASE=NetXtreme BCM5753M Gigabit Ethernet PCI Express pci:v000014E4d000016FDsv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NetXtreme BCM5753M Gigabit Ethernet PCI Express (Compaq nx9420 Notebook) pci:v000014E4d000016FDsv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=NetXtreme BCM5753M Gigabit Ethernet PCI Express (Compaq nw8440) pci:v000014E4d000016FE* ID_MODEL_FROM_DATABASE=NetXtreme BCM5753F Fast Ethernet PCI Express pci:v000014E4d0000170C* ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX pci:v000014E4d0000170Csv00001028sd00000188* ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (Inspiron 6000 laptop) pci:v000014E4d0000170Csv00001028sd0000018D* ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (Inspiron 700m/710m) pci:v000014E4d0000170Csv00001028sd00000196* ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (Inspiron 5160) pci:v000014E4d0000170Csv00001028sd000001AF* ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (Inspiron 6400) pci:v000014E4d0000170Csv00001028sd000001CD* ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (Inspiron 9400 Laptop) pci:v000014E4d0000170Csv00001028sd000001D7* ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (XPS M1210) pci:v000014E4d0000170Csv00001028sd000001D8* ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (Inspiron E1405) pci:v000014E4d0000170Csv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (NX6110/NC6120) pci:v000014E4d0000170Csv0000103Csd000030A2* ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (NX7300 laptop) pci:v000014E4d0000170Csv000014E4sd0000170C* ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (HP Compaq 6720t Mobile Thin Client) pci:v000014E4d0000170D* ID_MODEL_FROM_DATABASE=NetXtreme BCM5901 100Base-TX pci:v000014E4d0000170Dsv00001014sd00000545* ID_MODEL_FROM_DATABASE=NetXtreme BCM5901 100Base-TX (ThinkPad R40e) pci:v000014E4d0000170E* ID_MODEL_FROM_DATABASE=NetXtreme BCM5901 100Base-TX pci:v000014E4d00001712* ID_MODEL_FROM_DATABASE=NetLink BCM5906 Fast Ethernet PCI Express pci:v000014E4d00001713* ID_MODEL_FROM_DATABASE=NetLink BCM5906M Fast Ethernet PCI Express pci:v000014E4d00001713sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=NetLink BCM5906M Fast Ethernet PCI Express (Inspiron 1420) pci:v000014E4d00001713sv00001028sd00000209* ID_MODEL_FROM_DATABASE=NetLink BCM5906M Fast Ethernet PCI Express (XPS M1330) pci:v000014E4d00001713sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=NetLink BCM5906M Fast Ethernet PCI Express (Compaq 6710b) pci:v000014E4d00001713sv000017AAsd00003A23* ID_MODEL_FROM_DATABASE=NetLink BCM5906M Fast Ethernet PCI Express (IdeaPad S10e) pci:v000014E4d00003352* ID_MODEL_FROM_DATABASE=BCM3352 pci:v000014E4d00003360* ID_MODEL_FROM_DATABASE=BCM3360 pci:v000014E4d00004210* ID_MODEL_FROM_DATABASE=BCM4210 iLine10 HomePNA 2.0 pci:v000014E4d00004211* ID_MODEL_FROM_DATABASE=BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem pci:v000014E4d00004212* ID_MODEL_FROM_DATABASE=BCM4212 v.90 56k modem pci:v000014E4d00004220* ID_MODEL_FROM_DATABASE=802-11b/g Wireless PCI controller, packaged as a Linksys WPC54G ver 1.2 PCMCIA card pci:v000014E4d00004222* ID_MODEL_FROM_DATABASE=NetXtreme BCM5753M Gigabit Ethernet PCI Express pci:v000014E4d00004301* ID_MODEL_FROM_DATABASE=BCM4301 802.11b Wireless LAN Controller pci:v000014E4d00004301sv00001028sd00000407* ID_MODEL_FROM_DATABASE=BCM4301 802.11b Wireless LAN Controller (TrueMobile 1180 Onboard WLAN) pci:v000014E4d00004301sv00001043sd00000120* ID_MODEL_FROM_DATABASE=BCM4301 802.11b Wireless LAN Controller (WL-103b Wireless LAN PC Card) pci:v000014E4d00004301sv000016A5sd00001602* ID_MODEL_FROM_DATABASE=BCM4301 802.11b Wireless LAN Controller (B-300 802.11b Wireless CardBus Adapter) pci:v000014E4d00004301sv00001737sd00004301* ID_MODEL_FROM_DATABASE=BCM4301 802.11b Wireless LAN Controller (WMP11 v2.7 802.11b Wireless-B PCI Adapter) pci:v000014E4d00004305* ID_MODEL_FROM_DATABASE=BCM4307 V.90 56k Modem pci:v000014E4d00004306* ID_MODEL_FROM_DATABASE=BCM4306 802.11bg Wireless LAN controller pci:v000014E4d00004307* ID_MODEL_FROM_DATABASE=BCM4306 802.11bg Wireless LAN Controller pci:v000014E4d00004310* ID_MODEL_FROM_DATABASE=BCM4310 Chipcommon I/OController pci:v000014E4d00004311* ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN pci:v000014E4d00004311sv00001028sd00000007* ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (Wireless 1390 WLAN Mini-Card) pci:v000014E4d00004311sv00001028sd00000008* ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (Wireless 1390 WLAN ExpressCard) pci:v000014E4d00004311sv0000103Csd00001363* ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) pci:v000014E4d00004311sv0000103Csd00001364* ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) pci:v000014E4d00004311sv0000103Csd00001365* ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) pci:v000014E4d00004311sv0000103Csd00001374* ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) pci:v000014E4d00004311sv0000103Csd00001375* ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) pci:v000014E4d00004311sv0000103Csd00001376* ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) pci:v000014E4d00004311sv0000103Csd00001377* ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) pci:v000014E4d00004311sv0000103Csd0000137F* ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4322 802.11a/b/g/n Wireless LAN Controller) pci:v000014E4d00004311sv0000103Csd00001380* ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4322 802.11a/b/g/n Wireless LAN Controller) pci:v000014E4d00004311sv000014E4sd00004311* ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM94311MCG) pci:v000014E4d00004312* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g pci:v000014E4d00004312sv00001028sd00000007* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Wireless 1490 Dual Band WLAN Mini-Card) pci:v000014E4d00004312sv00001028sd00000008* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Wireless 1490 Dual Band WLAN ExpressCard) pci:v000014E4d00004312sv0000103Csd0000135A* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004312sv0000103Csd0000135F* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004312sv0000103Csd00001360* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004312sv0000103Csd00001361* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004312sv0000103Csd00001362* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004312sv0000103Csd00001370* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004312sv0000103Csd00001371* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004312sv0000103Csd00001372* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004312sv0000103Csd00001373* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004312sv0000103Csd000030B5* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Presario V3242AU) pci:v000014E4d00004312sv0000106Bsd00000089* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (AirPort Extreme) pci:v000014E4d00004312sv00001371sd0000103C* ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11 Multiband-netwerkadapter(6715s)) pci:v000014E4d00004313* ID_MODEL_FROM_DATABASE=BCM4311 802.11a pci:v000014E4d00004315* ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY pci:v000014E4d00004315sv00001028sd0000000B* ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (Wireless 1395 WLAN Mini-Card) pci:v000014E4d00004315sv00001028sd0000000C* ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (Wireless 1397 WLAN Mini-Card) pci:v000014E4d00004315sv0000103Csd0000137C* ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (BCM4312 802.11b/g Wireless LAN Controller) pci:v000014E4d00004315sv0000103Csd0000137D* ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (BCM4312 802.11b/g Wireless LAN Controller) pci:v000014E4d00004315sv0000103Csd00001507* ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (U98Z049.00 Wireless Mini PCIe Card) pci:v000014E4d00004315sv0000105Bsd0000E003* ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (T77H030.00 Wireless Mini PCIe Card) pci:v000014E4d00004315sv0000105Bsd0000E01B* ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (T77H106.00 Wireless Half-size Mini PCIe Card) pci:v000014E4d00004318* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller pci:v000014E4d00004318sv00001028sd00000005* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Wireless 1370 WLAN Mini-PCI Card) pci:v000014E4d00004318sv00001028sd00000006* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Wireless 1370 WLAN PC Card) pci:v000014E4d00004318sv0000103Csd00001355* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Broadcom 802.11b/g WLAN) pci:v000014E4d00004318sv0000103Csd00001356* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Broadcom 802.11b/g WLAN) pci:v000014E4d00004318sv0000103Csd00001357* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Broadcom 802.11b/g WLAN) pci:v000014E4d00004318sv00001043sd0000100F* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (WL-138G v2 / WL-138gE / WL-100gE) pci:v000014E4d00004318sv00001043sd0000120F* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (A6U notebook embedded card) pci:v000014E4d00004318sv00001154sd00000355* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Buffalo WLI2-PCI-G54S High Speed Mode Wireless Adapter) pci:v000014E4d00004318sv00001468sd00000311* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Aspire 3022WLMi, 5024WLMi, 5020) pci:v000014E4d00004318sv00001468sd00000312* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (TravelMate 2410) pci:v000014E4d00004318sv000014E4sd00000449* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Gateway 7510GX) pci:v000014E4d00004318sv000016ECsd00000119* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (U.S.Robotics Wireless MAXg PC Card) pci:v000014E4d00004318sv00001737sd00000042* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (WMP54GS v1.1 802.11g Wireless-G PCI Adapter with SpeedBooster) pci:v000014E4d00004318sv00001737sd00000048* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (WPC54G v3 802.11g Wireless-G Notebook Adapter) pci:v000014E4d00004318sv00001737sd00000049* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (WPC54GS v2 802.11g Wireless-G Notebook Adapter with SpeedBooster) pci:v000014E4d00004318sv00001799sd00007000* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (F5D7000 v4000 Wireless G Desktop Card) pci:v000014E4d00004318sv00001799sd00007001* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (F5D7001 v2000 Wireless G Plus Desktop Card) pci:v000014E4d00004318sv00001799sd00007010* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (F5D7010 v4000 Wireless G Notebook Card) pci:v000014E4d00004318sv00001799sd00007011* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (F5D7011 v2000 High-Speed Mode Wireless G Notebook Card) pci:v000014E4d00004319* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce 54g] 802.11a/b/g PCI Express Transceiver pci:v000014E4d00004319sv00001028sd00000005* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce 54g] 802.11a/b/g PCI Express Transceiver (Wireless 1470 Dual Band WLAN Mini-PCI Card) pci:v000014E4d00004319sv00001028sd00000006* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce 54g] 802.11a/b/g PCI Express Transceiver (Wireless 1470 Dual Band WLAN PC Card) pci:v000014E4d00004319sv0000103Csd00001358* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce 54g] 802.11a/b/g PCI Express Transceiver (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004319sv0000103Csd00001359* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce 54g] 802.11a/b/g PCI Express Transceiver (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004319sv0000103Csd0000135A* ID_MODEL_FROM_DATABASE=BCM4318 [AirForce 54g] 802.11a/b/g PCI Express Transceiver (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004320* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller pci:v000014E4d00004320sv00001028sd00000001* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (TrueMobile 1300 WLAN Mini-PCI Card) pci:v000014E4d00004320sv00001028sd00000002* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (TrueMobile 1300 WLAN PC Card) pci:v000014E4d00004320sv00001028sd00000003* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Wireless 1350 WLAN Mini-PCI Card) pci:v000014E4d00004320sv00001028sd00000004* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Wireless 1350 WLAN PC Card) pci:v000014E4d00004320sv0000103Csd000012F4* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Broadcom 802.11b/g WLAN) pci:v000014E4d00004320sv0000103Csd000012F8* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Broadcom 802.11b/g WLAN) pci:v000014E4d00004320sv0000103Csd000012FA* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Broadcom 802.11b/g WLAN) pci:v000014E4d00004320sv0000103Csd000012FB* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Broadcom 802.11b/g WLAN) pci:v000014E4d00004320sv00001043sd0000100F* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (WL-100G) pci:v000014E4d00004320sv00001057sd00007025* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (WN825G) pci:v000014E4d00004320sv0000106Bsd0000004E* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (AirPort Extreme) pci:v000014E4d00004320sv00001154sd00000330* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Buffalo WLI2-PCI-G54S High Speed Mode Wireless Desktop Adapter) pci:v000014E4d00004320sv0000144Fsd00007050* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (eMachines M6805 802.11g Built-in Wireless) pci:v000014E4d00004320sv0000144Fsd00007051* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Sonnet Aria Extreme PCI) pci:v000014E4d00004320sv00001737sd00000013* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (WMP54G v1 802.11g PCI Adapter) pci:v000014E4d00004320sv00001737sd00000014* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (WMP54G v2 802.11g PCI Adapter) pci:v000014E4d00004320sv00001737sd00000015* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (WMP54GS v1.0 802.11g Wireless-G PCI Adapter with SpeedBooster) pci:v000014E4d00004320sv00001737sd00004320* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (WPC54G v1 / WPC54GS v1 802.11g Wireless-G Notebook Adapter) pci:v000014E4d00004320sv00001799sd00007000* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (F5D7000 v1000 Wireless G Desktop Card) pci:v000014E4d00004320sv00001799sd00007001* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (F5D7001 v1000 Wireless G Plus Desktop Card) pci:v000014E4d00004320sv00001799sd00007010* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (F5D7010 v1000 Wireless G Notebook Card) pci:v000014E4d00004320sv00001799sd00007011* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (F5D7011 v1000 High-Speed Mode Wireless G Notebook Card) pci:v000014E4d00004320sv0000185Fsd00001220* ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (TravelMate 290E WLAN Mini-PCI Card) pci:v000014E4d00004321* ID_MODEL_FROM_DATABASE=BCM4321 802.11a Wireless Network Controller pci:v000014E4d00004322* ID_MODEL_FROM_DATABASE=BCM4322 802.11bgn Wireless Network Controller pci:v000014E4d00004324* ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller pci:v000014E4d00004324sv00001028sd00000001* ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller (Truemobile 1400) pci:v000014E4d00004324sv00001028sd00000002* ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller (TrueMobile 1400 Dual Band WLAN PC Card) pci:v000014E4d00004324sv00001028sd00000003* ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller (Truemobile 1450 MiniPCI) pci:v000014E4d00004324sv00001028sd00000004* ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller (Wireless 1450 Dual Band WLAN PC Card) pci:v000014E4d00004324sv0000103Csd000012F9* ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004324sv0000103Csd000012FC* ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller (Broadcom 802.11a/b/g WLAN) pci:v000014E4d00004325* ID_MODEL_FROM_DATABASE=BCM4306 802.11bg Wireless Network Controller pci:v000014E4d00004325sv00001414sd00000003* ID_MODEL_FROM_DATABASE=BCM4306 802.11bg Wireless Network Controller (Wireless Notebook Adapter MN-720) pci:v000014E4d00004325sv00001414sd00000004* ID_MODEL_FROM_DATABASE=BCM4306 802.11bg Wireless Network Controller (Wireless PCI Adapter MN-730) pci:v000014E4d00004326* ID_MODEL_FROM_DATABASE=BCM4307 Chipcommon I/O Controller? pci:v000014E4d00004328* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n pci:v000014E4d00004328sv00001028sd00000009* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (Wireless 1500 Draft 802.11n WLAN Mini-Card) pci:v000014E4d00004328sv00001028sd0000000A* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (Wireless 1500 Draft 802.11n WLAN Mini-card) pci:v000014E4d00004328sv0000103Csd00001366* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (Wireless LAN Controller) pci:v000014E4d00004328sv0000103Csd00001367* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (Wireless LAN Controller) pci:v000014E4d00004328sv0000103Csd00001368* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (Wireless LAN Controller) pci:v000014E4d00004328sv0000103Csd00001369* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (Wireless LAN Controller) pci:v000014E4d00004328sv0000106Bsd00000087* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004328sv0000106Bsd00000088* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004328sv0000106Bsd0000008B* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004328sv0000106Bsd0000008C* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004328sv0000106Bsd00000090* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004328sv000014E4sd00004328* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (BCM4328 802.11a/b/g/n) pci:v000014E4d00004328sv00001737sd00000066* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (WPC600N v1 802.11a/b/g/n Wireless-N CardBus Adapter) pci:v000014E4d00004328sv00001737sd00000068* ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (WEC600N v1 802.11a/b/g/n Wireless-N ExpressCard) pci:v000014E4d00004329* ID_MODEL_FROM_DATABASE=BCM4321 802.11b/g/n pci:v000014E4d00004329sv00001385sd00007B00* ID_MODEL_FROM_DATABASE=BCM4321 802.11b/g/n (WN511B RangeMax NEXT Wireless Notebook Adapter) pci:v000014E4d00004329sv00001385sd00007D00* ID_MODEL_FROM_DATABASE=BCM4321 802.11b/g/n (WN311B RangeMax Next 270 Mbps Wireless PCI Adapter) pci:v000014E4d00004329sv00001737sd00000058* ID_MODEL_FROM_DATABASE=BCM4321 802.11b/g/n (WPC300N v1 Wireless-N Notebook Adapter) pci:v000014E4d0000432A* ID_MODEL_FROM_DATABASE=BCM4321 802.11an Wireless Network Controller pci:v000014E4d0000432B* ID_MODEL_FROM_DATABASE=BCM4322 802.11a/b/g/n Wireless LAN Controller pci:v000014E4d0000432Bsv00001028sd0000000D* ID_MODEL_FROM_DATABASE=BCM4322 802.11a/b/g/n Wireless LAN Controller (Wireless 1510 Wireless-N WLAN Mini-Card) pci:v000014E4d0000432Bsv0000106Bsd0000008D* ID_MODEL_FROM_DATABASE=BCM4322 802.11a/b/g/n Wireless LAN Controller (AirPort Extreme) pci:v000014E4d0000432Bsv0000106Bsd0000008E* ID_MODEL_FROM_DATABASE=BCM4322 802.11a/b/g/n Wireless LAN Controller (AirPort Extreme) pci:v000014E4d0000432C* ID_MODEL_FROM_DATABASE=BCM4322 802.11b/g/n pci:v000014E4d0000432Csv00001799sd0000D311* ID_MODEL_FROM_DATABASE=BCM4322 802.11b/g/n (Dynex DX-NNBX 802.11n WLAN Cardbus Card) pci:v000014E4d0000432D* ID_MODEL_FROM_DATABASE=BCM4322 802.11an Wireless Network Controller pci:v000014E4d00004331* ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n pci:v000014E4d00004331sv0000106Bsd000000D6* ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004331sv0000106Bsd000000E4* ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004331sv0000106Bsd000000EF* ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004331sv0000106Bsd000000F4* ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004331sv0000106Bsd000000F5* ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004331sv0000106Bsd0000010E* ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004331sv0000106Bsd0000010F* ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004333* ID_MODEL_FROM_DATABASE=Serial (EDGE/GPRS modem part of Option GT Combo Edge) pci:v000014E4d00004344* ID_MODEL_FROM_DATABASE=EDGE/GPRS data and 802.11b/g combo cardbus [GC89] pci:v000014E4d00004350* ID_MODEL_FROM_DATABASE=BCM43222 Wireless Network Adapter pci:v000014E4d00004351* ID_MODEL_FROM_DATABASE=BCM43222 802.11abgn Wireless Network Adapter pci:v000014E4d00004353* ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n pci:v000014E4d00004353sv00001028sd0000000E* ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n (Wireless 1520 Half-size Mini PCIe Card) pci:v000014E4d00004353sv0000103Csd00001509* ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n (WMIB-275N Half-size Mini PCIe Card) pci:v000014E4d00004353sv0000106Bsd00000093* ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004353sv0000106Bsd000000D1* ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004353sv0000106Bsd000000E9* ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n (AirPort Extreme) pci:v000014E4d00004357* ID_MODEL_FROM_DATABASE=BCM43225 802.11b/g/n pci:v000014E4d00004357sv0000105Bsd0000E021* ID_MODEL_FROM_DATABASE=BCM43225 802.11b/g/n (T77H103.00 Wireless Half-size Mini PCIe Card) pci:v000014E4d00004358* ID_MODEL_FROM_DATABASE=BCM43227 802.11b/g/n pci:v000014E4d00004359* ID_MODEL_FROM_DATABASE=BCM43228 802.11a/b/g/n pci:v000014E4d00004359sv00001028sd00000011* ID_MODEL_FROM_DATABASE=BCM43228 802.11a/b/g/n (Wireless 1530 Half-size Mini PCIe Card) pci:v000014E4d00004359sv0000103Csd0000182C* ID_MODEL_FROM_DATABASE=BCM43228 802.11a/b/g/n (BCM943228HM4L 802.11a/b/g/n 2x2 Wi-Fi Adapter) pci:v000014E4d00004360* ID_MODEL_FROM_DATABASE=BCM4360 802.11ac Wireless Network Adapter pci:v000014E4d00004365* ID_MODEL_FROM_DATABASE=BCM43142 802.11b/g/n pci:v000014E4d00004365sv00001028sd00000016* ID_MODEL_FROM_DATABASE=BCM43142 802.11b/g/n (Wireless 1704 802.11n + BT 4.0) pci:v000014E4d000043A0* ID_MODEL_FROM_DATABASE=BCM4360 802.11ac Wireless Network Adapter pci:v000014E4d000043A1* ID_MODEL_FROM_DATABASE=BCM4360 802.11ac Wireless Network Adapter pci:v000014E4d000043A2* ID_MODEL_FROM_DATABASE=BCM4360 802.11ac Wireless Network Adapter pci:v000014E4d000043A3* ID_MODEL_FROM_DATABASE=BCM4350 802.11ac Wireless Network Adapter pci:v000014E4d000043A9* ID_MODEL_FROM_DATABASE=BCM43217 802.11b/g/n pci:v000014E4d000043AA* ID_MODEL_FROM_DATABASE=BCM43131 802.11b/g/n pci:v000014E4d000043B1* ID_MODEL_FROM_DATABASE=BCM4352 802.11ac Wireless Network Adapter pci:v000014E4d000043BA* ID_MODEL_FROM_DATABASE=BCM43602 802.11ac Wireless LAN SoC pci:v000014E4d000043BB* ID_MODEL_FROM_DATABASE=BCM43602 802.11ac Wireless LAN SoC pci:v000014E4d000043BC* ID_MODEL_FROM_DATABASE=BCM43602 802.11ac Wireless LAN SoC pci:v000014E4d000043D3* ID_MODEL_FROM_DATABASE=BCM43567 802.11ac Wireless Network Adapter pci:v000014E4d000043D9* ID_MODEL_FROM_DATABASE=BCM43570 802.11ac Wireless Network Adapter pci:v000014E4d000043DF* ID_MODEL_FROM_DATABASE=BCM4354 802.11ac Wireless LAN SoC pci:v000014E4d000043E9* ID_MODEL_FROM_DATABASE=BCM4358 802.11ac Wireless LAN SoC pci:v000014E4d000043EC* ID_MODEL_FROM_DATABASE=BCM4356 802.11ac Wireless Network Adapter pci:v000014E4d00004401* ID_MODEL_FROM_DATABASE=BCM4401 100Base-T pci:v000014E4d00004401sv00001025sd00000035* ID_MODEL_FROM_DATABASE=BCM4401 100Base-T (TravelMate 660) pci:v000014E4d00004401sv00001025sd00000064* ID_MODEL_FROM_DATABASE=BCM4401 100Base-T (Extensa 3000 series laptop) pci:v000014E4d00004401sv00001028sd00008127* ID_MODEL_FROM_DATABASE=BCM4401 100Base-T (Dimension 2400) pci:v000014E4d00004401sv0000103Csd000008B0* ID_MODEL_FROM_DATABASE=BCM4401 100Base-T (tc1100 tablet) pci:v000014E4d00004401sv00001043sd000080A8* ID_MODEL_FROM_DATABASE=BCM4401 100Base-T (A7V8X motherboard) pci:v000014E4d00004402* ID_MODEL_FROM_DATABASE=BCM4402 Integrated 10/100BaseT pci:v000014E4d00004403* ID_MODEL_FROM_DATABASE=BCM4402 V.90 56k Modem pci:v000014E4d00004410* ID_MODEL_FROM_DATABASE=BCM4413 iLine32 HomePNA 2.0 pci:v000014E4d00004411* ID_MODEL_FROM_DATABASE=BCM4413 V.90 56k modem pci:v000014E4d00004412* ID_MODEL_FROM_DATABASE=BCM4412 10/100BaseT pci:v000014E4d00004430* ID_MODEL_FROM_DATABASE=BCM44xx CardBus iLine32 HomePNA 2.0 pci:v000014E4d00004432* ID_MODEL_FROM_DATABASE=BCM4432 CardBus 10/100BaseT pci:v000014E4d00004610* ID_MODEL_FROM_DATABASE=BCM4610 Sentry5 PCI to SB Bridge pci:v000014E4d00004611* ID_MODEL_FROM_DATABASE=BCM4610 Sentry5 iLine32 HomePNA 1.0 pci:v000014E4d00004612* ID_MODEL_FROM_DATABASE=BCM4610 Sentry5 V.90 56k Modem pci:v000014E4d00004613* ID_MODEL_FROM_DATABASE=BCM4610 Sentry5 Ethernet Controller pci:v000014E4d00004614* ID_MODEL_FROM_DATABASE=BCM4610 Sentry5 External Interface pci:v000014E4d00004615* ID_MODEL_FROM_DATABASE=BCM4610 Sentry5 USB Controller pci:v000014E4d00004704* ID_MODEL_FROM_DATABASE=BCM4704 PCI to SB Bridge pci:v000014E4d00004705* ID_MODEL_FROM_DATABASE=BCM4704 Sentry5 802.11b Wireless LAN Controller pci:v000014E4d00004706* ID_MODEL_FROM_DATABASE=BCM4704 Sentry5 Ethernet Controller pci:v000014E4d00004707* ID_MODEL_FROM_DATABASE=BCM4704 Sentry5 USB Controller pci:v000014E4d00004708* ID_MODEL_FROM_DATABASE=BCM4704 Crypto Accelerator pci:v000014E4d00004710* ID_MODEL_FROM_DATABASE=BCM4710 Sentry5 PCI to SB Bridge pci:v000014E4d00004711* ID_MODEL_FROM_DATABASE=BCM47xx Sentry5 iLine32 HomePNA 2.0 pci:v000014E4d00004712* ID_MODEL_FROM_DATABASE=BCM47xx V.92 56k modem pci:v000014E4d00004713* ID_MODEL_FROM_DATABASE=Sentry5 Ethernet Controller pci:v000014E4d00004714* ID_MODEL_FROM_DATABASE=BCM47xx Sentry5 External Interface pci:v000014E4d00004715* ID_MODEL_FROM_DATABASE=BCM47xx Sentry5 USB / Ethernet Controller pci:v000014E4d00004716* ID_MODEL_FROM_DATABASE=BCM47xx Sentry5 USB Host Controller pci:v000014E4d00004717* ID_MODEL_FROM_DATABASE=BCM47xx Sentry5 USB Device Controller pci:v000014E4d00004718* ID_MODEL_FROM_DATABASE=Sentry5 Crypto Accelerator pci:v000014E4d00004719* ID_MODEL_FROM_DATABASE=BCM47xx/53xx RoboSwitch Core pci:v000014E4d00004720* ID_MODEL_FROM_DATABASE=BCM4712 MIPS CPU pci:v000014E4d00004727* ID_MODEL_FROM_DATABASE=BCM4313 802.11bgn Wireless Network Adapter pci:v000014E4d00004727sv00001028sd00000010* ID_MODEL_FROM_DATABASE=BCM4313 802.11bgn Wireless Network Adapter (Inspiron M5010 / XPS 8300) pci:v000014E4d00005365* ID_MODEL_FROM_DATABASE=BCM5365P Sentry5 Host Bridge pci:v000014E4d00005600* ID_MODEL_FROM_DATABASE=BCM5600 StrataSwitch 24+2 Ethernet Switch Controller pci:v000014E4d00005605* ID_MODEL_FROM_DATABASE=BCM5605 StrataSwitch 24+2 Ethernet Switch Controller pci:v000014E4d00005615* ID_MODEL_FROM_DATABASE=BCM5615 StrataSwitch 24+2 Ethernet Switch Controller pci:v000014E4d00005625* ID_MODEL_FROM_DATABASE=BCM5625 StrataSwitch 24+2 Ethernet Switch Controller pci:v000014E4d00005645* ID_MODEL_FROM_DATABASE=BCM5645 StrataSwitch 24+2 Ethernet Switch Controller pci:v000014E4d00005670* ID_MODEL_FROM_DATABASE=BCM5670 8-Port 10GE Ethernet Switch Fabric pci:v000014E4d00005680* ID_MODEL_FROM_DATABASE=BCM5680 G-Switch 8 Port Gigabit Ethernet Switch Controller pci:v000014E4d00005690* ID_MODEL_FROM_DATABASE=BCM5690 12-port Multi-Layer Gigabit Ethernet Switch pci:v000014E4d00005691* ID_MODEL_FROM_DATABASE=BCM5691 GE/10GE 8+2 Gigabit Ethernet Switch Controller pci:v000014E4d00005692* ID_MODEL_FROM_DATABASE=BCM5692 12-port Multi-Layer Gigabit Ethernet Switch pci:v000014E4d00005695* ID_MODEL_FROM_DATABASE=BCM5695 12-port + HiGig Multi-Layer Gigabit Ethernet Switch pci:v000014E4d00005698* ID_MODEL_FROM_DATABASE=BCM5698 12-port Multi-Layer Gigabit Ethernet Switch pci:v000014E4d00005820* ID_MODEL_FROM_DATABASE=BCM5820 Crypto Accelerator pci:v000014E4d00005821* ID_MODEL_FROM_DATABASE=BCM5821 Crypto Accelerator pci:v000014E4d00005822* ID_MODEL_FROM_DATABASE=BCM5822 Crypto Accelerator pci:v000014E4d00005823* ID_MODEL_FROM_DATABASE=BCM5823 Crypto Accelerator pci:v000014E4d00005824* ID_MODEL_FROM_DATABASE=BCM5824 Crypto Accelerator pci:v000014E4d00005840* ID_MODEL_FROM_DATABASE=BCM5840 Crypto Accelerator pci:v000014E4d00005841* ID_MODEL_FROM_DATABASE=BCM5841 Crypto Accelerator pci:v000014E4d00005850* ID_MODEL_FROM_DATABASE=BCM5850 Crypto Accelerator pci:v000014E4d00008602* ID_MODEL_FROM_DATABASE=BCM7400/BCM7405 Serial ATA Controller pci:v000014E4d0000A8D8* ID_MODEL_FROM_DATABASE=BCM43224/5 Wireless Network Adapter pci:v000014E4d0000AA52* ID_MODEL_FROM_DATABASE=BCM43602 802.11ac Wireless LAN SoC pci:v000014E4d0000B302* ID_MODEL_FROM_DATABASE=BCM56302 StrataXGS 24x1GE 2x10GE Switch Controller pci:v000014E4d0000B334* ID_MODEL_FROM_DATABASE=BCM56334 StrataXGS 24x1GE 4x10GE Switch Controller pci:v000014E4d0000B800* ID_MODEL_FROM_DATABASE=BCM56800 StrataXGS 10GE Switch Controller pci:v000014E4d0000B842* ID_MODEL_FROM_DATABASE=BCM56842 Trident 10GE Switch Controller pci:v000014E5* ID_VENDOR_FROM_DATABASE=Pixelfusion Ltd pci:v000014E6* ID_VENDOR_FROM_DATABASE=SHINING Technology Inc pci:v000014E7* ID_VENDOR_FROM_DATABASE=3CX pci:v000014E8* ID_VENDOR_FROM_DATABASE=RAYCER Inc pci:v000014E9* ID_VENDOR_FROM_DATABASE=GARNETS System CO Ltd pci:v000014EA* ID_VENDOR_FROM_DATABASE=Planex Communications, Inc pci:v000014EAd0000AB06* ID_MODEL_FROM_DATABASE=FNW-3603-TX CardBus Fast Ethernet pci:v000014EAd0000AB07* ID_MODEL_FROM_DATABASE=RTL81xx RealTek Ethernet pci:v000014EAd0000AB08* ID_MODEL_FROM_DATABASE=FNW-3602-TX CardBus Fast Ethernet pci:v000014EB* ID_VENDOR_FROM_DATABASE=SEIKO EPSON Corp pci:v000014EC* ID_VENDOR_FROM_DATABASE=Agilent Technologies pci:v000014ECd00000000* ID_MODEL_FROM_DATABASE=Aciris Digitizer (malformed ID) pci:v000014ED* ID_VENDOR_FROM_DATABASE=DATAKINETICS Ltd pci:v000014EE* ID_VENDOR_FROM_DATABASE=MASPRO KENKOH Corp pci:v000014EF* ID_VENDOR_FROM_DATABASE=CARRY Computer ENG. CO Ltd pci:v000014F0* ID_VENDOR_FROM_DATABASE=CANON RESEACH CENTRE FRANCE pci:v000014F1* ID_VENDOR_FROM_DATABASE=Conexant Systems, Inc. pci:v000014F1d00001002* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v000014F1d00001003* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v000014F1d00001004* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v000014F1d00001005* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v000014F1d00001006* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v000014F1d00001022* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v000014F1d00001023* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v000014F1d00001024* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v000014F1d00001025* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v000014F1d00001026* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v000014F1d00001032* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v000014F1d00001033* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem pci:v000014F1d00001033sv00001033sd00008077* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (NEC) pci:v000014F1d00001033sv0000122Dsd00004027* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Dell Zeus - MDP3880-W(B) Data Fax Modem) pci:v000014F1d00001033sv0000122Dsd00004030* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Dell Mercury - MDP3880-U(B) Data Fax Modem) pci:v000014F1d00001033sv0000122Dsd00004034* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Dell Thor - MDP3880-W(U) Data Fax Modem) pci:v000014F1d00001033sv000013E0sd0000020D* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Dell Copper) pci:v000014F1d00001033sv000013E0sd0000020E* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Dell Silver) pci:v000014F1d00001033sv000013E0sd00000261* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) pci:v000014F1d00001033sv000013E0sd00000290* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Compaq Goldwing) pci:v000014F1d00001033sv000013E0sd000002A0* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) pci:v000014F1d00001033sv000013E0sd000002B0* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) pci:v000014F1d00001033sv000013E0sd000002C0* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Compaq Scooter) pci:v000014F1d00001033sv000013E0sd000002D0* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) pci:v000014F1d00001033sv0000144Fsd00001500* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P85-DF (1)) pci:v000014F1d00001033sv0000144Fsd00001501* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P85-DF (2)) pci:v000014F1d00001033sv0000144Fsd0000150A* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P85-DF (3)) pci:v000014F1d00001033sv0000144Fsd0000150B* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P85-DF Low Profile (1)) pci:v000014F1d00001033sv0000144Fsd00001510* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P85-DF Low Profile (2)) pci:v000014F1d00001034* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem pci:v000014F1d00001035* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem pci:v000014F1d00001035sv000010CFsd00001098* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu P85-DFSV) pci:v000014F1d00001036* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem pci:v000014F1d00001036sv0000104Dsd00008067* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (HCF 56k Modem) pci:v000014F1d00001036sv0000122Dsd00004029* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (MDP3880SP-W) pci:v000014F1d00001036sv0000122Dsd00004031* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (MDP3880SP-U) pci:v000014F1d00001036sv000013E0sd00000209* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Dell Titanium) pci:v000014F1d00001036sv000013E0sd0000020A* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Dell Graphite) pci:v000014F1d00001036sv000013E0sd00000260* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Gateway Red Owl) pci:v000014F1d00001036sv000013E0sd00000270* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Gateway White Horse) pci:v000014F1d00001052* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Worldwide) pci:v000014F1d00001053* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Worldwide) pci:v000014F1d00001054* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem (Worldwide) pci:v000014F1d00001055* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Worldwide) pci:v000014F1d00001056* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide) pci:v000014F1d00001056sv0000122Dsd00004035* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide) (MDP3900V-W) pci:v000014F1d00001057* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide) pci:v000014F1d00001059* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem (Worldwide) pci:v000014F1d00001063* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem pci:v000014F1d00001064* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem pci:v000014F1d00001065* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem pci:v000014F1d00001066* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem pci:v000014F1d00001066sv0000122Dsd00004033* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Dell Athena - MDP3900V-U) pci:v000014F1d00001085* ID_MODEL_FROM_DATABASE=HCF V90 56k Data/Fax/Voice/Spkp PCI Modem pci:v000014F1d000010B6* ID_MODEL_FROM_DATABASE=CX06834-11 HCF V.92 56k Data/Fax/Voice/Spkp Modem pci:v000014F1d00001433* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem pci:v000014F1d00001434* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem pci:v000014F1d00001435* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem pci:v000014F1d00001436* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem pci:v000014F1d00001453* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem pci:v000014F1d00001453sv000013E0sd00000240* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) pci:v000014F1d00001453sv000013E0sd00000250* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) pci:v000014F1d00001453sv0000144Fsd00001502* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P95-DF (1)) pci:v000014F1d00001453sv0000144Fsd00001503* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P95-DF (2)) pci:v000014F1d00001454* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem pci:v000014F1d00001455* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem pci:v000014F1d00001456* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem pci:v000014F1d00001456sv0000122Dsd00004035* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Dell Europa - MDP3900V-W) pci:v000014F1d00001456sv0000122Dsd00004302* ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Dell MP3930V-W(C) MiniPCI) pci:v000014F1d00001610* ID_MODEL_FROM_DATABASE=ADSL AccessRunner PCI Arbitration Device pci:v000014F1d00001611* ID_MODEL_FROM_DATABASE=AccessRunner PCI ADSL Interface Device pci:v000014F1d00001620* ID_MODEL_FROM_DATABASE=AccessRunner V2 PCI ADSL Arbitration Device pci:v000014F1d00001621* ID_MODEL_FROM_DATABASE=AccessRunner V2 PCI ADSL Interface Device pci:v000014F1d00001622* ID_MODEL_FROM_DATABASE=AccessRunner V2 PCI ADSL Yukon WAN Adapter pci:v000014F1d00001803* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v000014F1d00001803sv00000E11sd00000023* ID_MODEL_FROM_DATABASE=HCF 56k Modem (623-LAN Grizzly) pci:v000014F1d00001803sv00000E11sd00000043* ID_MODEL_FROM_DATABASE=HCF 56k Modem (623-LAN Yogi) pci:v000014F1d00001811* ID_MODEL_FROM_DATABASE=MiniPCI Network Adapter pci:v000014F1d00001815* ID_MODEL_FROM_DATABASE=HCF 56k Modem pci:v000014F1d00001815sv00000E11sd00000022* ID_MODEL_FROM_DATABASE=HCF 56k Modem (Grizzly) pci:v000014F1d00001815sv00000E11sd00000042* ID_MODEL_FROM_DATABASE=HCF 56k Modem (Yogi) pci:v000014F1d00001830* ID_MODEL_FROM_DATABASE=CX861xx Integrated Host Bridge pci:v000014F1d00002003* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem pci:v000014F1d00002004* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem pci:v000014F1d00002005* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem pci:v000014F1d00002006* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem pci:v000014F1d00002013* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem pci:v000014F1d00002013sv00000E11sd0000B195* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Bear) pci:v000014F1d00002013sv00000E11sd0000B196* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Seminole 1) pci:v000014F1d00002013sv00000E11sd0000B1BE* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Seminole 2) pci:v000014F1d00002013sv00001025sd00008013* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Acer) pci:v000014F1d00002013sv00001033sd0000809D* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (NEC) pci:v000014F1d00002013sv00001033sd000080BC* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (NEC) pci:v000014F1d00002013sv0000155Dsd00006793* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (HP) pci:v000014F1d00002013sv0000155Dsd00008850* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (E Machines) pci:v000014F1d00002014* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem pci:v000014F1d00002015* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem pci:v000014F1d00002016* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem pci:v000014F1d00002043* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (WorldW SmartDAA) pci:v000014F1d00002044* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (WorldW SmartDAA) pci:v000014F1d00002045* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (WorldW SmartDAA) pci:v000014F1d00002045sv000014F1sd00002045* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (WorldW SmartDAA) (Generic SoftK56) pci:v000014F1d00002046* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (WorldW SmartDAA) pci:v000014F1d00002063* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (SmartDAA) pci:v000014F1d00002064* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (SmartDAA) pci:v000014F1d00002065* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (SmartDAA) pci:v000014F1d00002066* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (SmartDAA) pci:v000014F1d00002093* ID_MODEL_FROM_DATABASE=HSF 56k Modem pci:v000014F1d00002093sv0000155Dsd00002F07* ID_MODEL_FROM_DATABASE=HSF 56k Modem (Legend) pci:v000014F1d00002143* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Cell Modem (Mob WorldW SmartDAA) pci:v000014F1d00002144* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Cell Modem (Mob WorldW SmartDAA) pci:v000014F1d00002145* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/HS)/Cell Modem (Mob WorldW SmartDAA) pci:v000014F1d00002146* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp/Cell Modem (Mob WorldW SmartDAA) pci:v000014F1d00002163* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Cell Modem (Mob SmartDAA) pci:v000014F1d00002164* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Cell Modem (Mob SmartDAA) pci:v000014F1d00002165* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/HS)/Cell Modem (Mob SmartDAA) pci:v000014F1d00002166* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp/Cell Modem (Mob SmartDAA) pci:v000014F1d00002343* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax CardBus Modem (Mob WorldW SmartDAA) pci:v000014F1d00002344* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice CardBus Modem (Mob WorldW SmartDAA) pci:v000014F1d00002345* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/HS) CardBus Modem (Mob WorldW SmartDAA) pci:v000014F1d00002346* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp CardBus Modem (Mob WorldW SmartDAA) pci:v000014F1d00002363* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax CardBus Modem (Mob SmartDAA) pci:v000014F1d00002364* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice CardBus Modem (Mob SmartDAA) pci:v000014F1d00002365* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/HS) CardBus Modem (Mob SmartDAA) pci:v000014F1d00002366* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp CardBus Modem (Mob SmartDAA) pci:v000014F1d00002443* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Mob WorldW SmartDAA) pci:v000014F1d00002443sv0000104Dsd00008075* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Mob WorldW SmartDAA) (Modem) pci:v000014F1d00002443sv0000104Dsd00008083* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Mob WorldW SmartDAA) (Modem) pci:v000014F1d00002443sv0000104Dsd00008097* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Mob WorldW SmartDAA) (Modem) pci:v000014F1d00002444* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (Mob WorldW SmartDAA) pci:v000014F1d00002445* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/HS) Modem (Mob WorldW SmartDAA) pci:v000014F1d00002446* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (Mob WorldW SmartDAA) pci:v000014F1d00002463* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Mob SmartDAA) pci:v000014F1d00002464* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (Mob SmartDAA) pci:v000014F1d00002465* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/HS) Modem (Mob SmartDAA) pci:v000014F1d00002466* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (Mob SmartDAA) pci:v000014F1d00002702* ID_MODEL_FROM_DATABASE=HSFi modem RD01-D270 pci:v000014F1d00002702sv00001028sd00008D88* ID_MODEL_FROM_DATABASE=HSFi modem RD01-D270 (SmartHSFi V92 56K PCI Modem) pci:v000014F1d00002F00* ID_MODEL_FROM_DATABASE=HSF 56k HSFi Modem pci:v000014F1d00002F00sv000013E0sd00008D84* ID_MODEL_FROM_DATABASE=HSF 56k HSFi Modem (IBM HSFi V.90) pci:v000014F1d00002F00sv000013E0sd00008D85* ID_MODEL_FROM_DATABASE=HSF 56k HSFi Modem (Compaq Stinger) pci:v000014F1d00002F00sv000014F1sd00002004* ID_MODEL_FROM_DATABASE=HSF 56k HSFi Modem (Dynalink 56PMi) pci:v000014F1d00002F02* ID_MODEL_FROM_DATABASE=HSF 56k HSFi Data/Fax pci:v000014F1d00002F11* ID_MODEL_FROM_DATABASE=HSF 56k HSFi Modem pci:v000014F1d00002F20* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem pci:v000014F1d00002F20sv000014F1sd0000200C* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Soft Data Fax Modem with SmartCP) pci:v000014F1d00002F20sv000014F1sd0000200F* ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Dimension 3000) pci:v000014F1d00002F30* ID_MODEL_FROM_DATABASE=SoftV92 SpeakerPhone SoftRing Modem with SmartSP pci:v000014F1d00002F30sv000014F1sd00002014* ID_MODEL_FROM_DATABASE=SoftV92 SpeakerPhone SoftRing Modem with SmartSP (Devolo MikroLink 56K Modem PCI) pci:v000014F1d00002F50* ID_MODEL_FROM_DATABASE=Conexant SoftK56 Data/Fax Modem pci:v000014F1d00005B7A* ID_MODEL_FROM_DATABASE=CX23418 Single-Chip MPEG-2 Encoder with Integrated Analog Video/Broadcast Audio Decoder pci:v000014F1d00005B7Asv00000070sd00007444* ID_MODEL_FROM_DATABASE=CX23418 Single-Chip MPEG-2 Encoder with Integrated Analog Video/Broadcast Audio Decoder (WinTV HVR-1600) pci:v000014F1d00005B7Asv0000107Dsd00006F34* ID_MODEL_FROM_DATABASE=CX23418 Single-Chip MPEG-2 Encoder with Integrated Analog Video/Broadcast Audio Decoder (WinFast DVR3100 H) pci:v000014F1d00005B7Asv00005854sd00003343* ID_MODEL_FROM_DATABASE=CX23418 Single-Chip MPEG-2 Encoder with Integrated Analog Video/Broadcast Audio Decoder (GoTView PCI DVD3 Hybrid) pci:v000014F1d00008200* ID_MODEL_FROM_DATABASE=CX25850 pci:v000014F1d00008234* ID_MODEL_FROM_DATABASE=RS8234 ATM SAR Controller [ServiceSAR Plus] pci:v000014F1d00008800* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder pci:v000014F1d00008800sv00000070sd00002801* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Hauppauge WinTV 28xxx (Roslyn) models) pci:v000014F1d00008800sv00000070sd00003400* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinTV 34604) pci:v000014F1d00008800sv00000070sd00003401* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Hauppauge WinTV 34xxx models) pci:v000014F1d00008800sv00000070sd00006902* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinTV HVR-4000-HD) pci:v000014F1d00008800sv00000070sd00007801* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinTV HVR-1800 MCE) pci:v000014F1d00008800sv00000070sd00009001* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Nova-T DVB-T) pci:v000014F1d00008800sv00000070sd00009200* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Nova-SE2 DVB-S) pci:v000014F1d00008800sv00000070sd00009202* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Nova-S-Plus DVB-S) pci:v000014F1d00008800sv00000070sd00009402* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinTV-HVR1100 DVB-T/Hybrid) pci:v000014F1d00008800sv00000070sd00009600* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinTV 88x Video) pci:v000014F1d00008800sv00000070sd00009802* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinTV-HVR1100 DVB-T/Hybrid (Low Profile)) pci:v000014F1d00008800sv00001002sd000000F8* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (ATI TV Wonder Pro) pci:v000014F1d00008800sv00001002sd000000F9* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (ATI TV Wonder) pci:v000014F1d00008800sv00001002sd0000A101* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (HDTV Wonder) pci:v000014F1d00008800sv00001043sd00004823* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (ASUS PVR-416) pci:v000014F1d00008800sv0000107Dsd00006611* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Winfast TV 2000XP Expert) pci:v000014F1d00008800sv0000107Dsd00006613* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Leadtek Winfast 2000XP Expert) pci:v000014F1d00008800sv0000107Dsd00006620* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Leadtek Winfast DV2000) pci:v000014F1d00008800sv0000107Dsd0000663C* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Leadtek PVR 2000) pci:v000014F1d00008800sv0000107Dsd0000665F* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinFast DTV1000-T) pci:v000014F1d00008800sv000010FCsd0000D003* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (IODATA GV-VCP3/PCI) pci:v000014F1d00008800sv000010FCsd0000D035* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (IODATA GV/BCTV7E) pci:v000014F1d00008800sv00001421sd00000334* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Instant TV DVB-T PCI) pci:v000014F1d00008800sv00001461sd0000000A* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (AVerTV 303 (M126)) pci:v000014F1d00008800sv00001461sd0000000B* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (AverTV Studio 303 (M126)) pci:v000014F1d00008800sv00001461sd00008011* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (UltraTV Media Center PCI 550) pci:v000014F1d00008800sv00001462sd00008606* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (MSI TV-@nywhere Master) pci:v000014F1d00008800sv000014C7sd00000107* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (GDI Black Gold) pci:v000014F1d00008800sv000014F1sd00000187* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Conexant DVB-T reference design) pci:v000014F1d00008800sv000014F1sd00000342* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Digital-Logic MICROSPACE Entertainment Center (MEC)) pci:v000014F1d00008800sv0000153Bsd00001166* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Cinergy 1400 DVB-T) pci:v000014F1d00008800sv00001540sd00002580* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Provideo PV259) pci:v000014F1d00008800sv00001554sd00004811* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (PixelView) pci:v000014F1d00008800sv00001554sd00004813* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Club 3D ZAP1000 MCE Edition) pci:v000014F1d00008800sv000017DEsd000008A1* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (KWorld/VStream XPert DVB-T with cx22702) pci:v000014F1d00008800sv000017DEsd000008A6* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (KWorld/VStream XPert DVB-T) pci:v000014F1d00008800sv000017DEsd000008B2* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (KWorld DVB-S 100) pci:v000014F1d00008800sv000017DEsd0000A8A6* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (digitalnow DNTV Live! DVB-T) pci:v000014F1d00008800sv00001822sd00000025* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (digitalnow DNTV Live! DVB-T Pro) pci:v000014F1d00008800sv0000185Bsd0000E000* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (VideoMate X500) pci:v000014F1d00008800sv000018ACsd0000D500* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (FusionHDTV 5 Gold) pci:v000014F1d00008800sv000018ACsd0000D810* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (FusionHDTV 3 Gold-Q) pci:v000014F1d00008800sv000018ACsd0000D820* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (FusionHDTV 3 Gold-T) pci:v000014F1d00008800sv000018ACsd0000DB00* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (FusionHDTV DVB-T1) pci:v000014F1d00008800sv000018ACsd0000DB11* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (FusionHDTV DVB-T Plus) pci:v000014F1d00008800sv000018ACsd0000DB50* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (FusionHDTV DVB-T Dual Digital) pci:v000014F1d00008800sv00005654sd00002388* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (GoTView PCI Hybrid TV Tuner Card) pci:v000014F1d00008800sv00007063sd00003000* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (pcHDTV HD3000 HDTV) pci:v000014F1d00008800sv00007063sd00005500* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (pcHDTV HD-5500) pci:v000014F1d00008801* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] pci:v000014F1d00008801sv00000070sd00002801* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (Hauppauge WinTV 28xxx (Roslyn) models) pci:v000014F1d00008801sv0000185Bsd0000E000* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (VideoMate X500) pci:v000014F1d00008801sv00005654sd00002388* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (GoTView PCI Hybrid Audio AVStream Device) pci:v000014F1d00008801sv00007063sd00005500* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (pcHDTV HD-5500) pci:v000014F1d00008802* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] pci:v000014F1d00008802sv00000070sd00002801* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (Hauppauge WinTV 28xxx (Roslyn) models) pci:v000014F1d00008802sv00000070sd00006902* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (WinTV HVR-4000-HD) pci:v000014F1d00008802sv00000070sd00009002* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (Nova-T DVB-T Model 909) pci:v000014F1d00008802sv00000070sd00009402* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (WinTV-HVR1100 DVB-T/Hybrid) pci:v000014F1d00008802sv00000070sd00009600* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (WinTV 88x MPEG Encoder) pci:v000014F1d00008802sv00001043sd00004823* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (ASUS PVR-416) pci:v000014F1d00008802sv0000107Dsd0000663C* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (Leadtek PVR 2000) pci:v000014F1d00008802sv0000107Dsd0000665F* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (WinFast DTV1000-T) pci:v000014F1d00008802sv000014F1sd00000187* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (Conexant DVB-T reference design) pci:v000014F1d00008802sv000017DEsd000008A1* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (XPert DVB-T PCI BDA DVBT 23880 Transport Stream Capture) pci:v000014F1d00008802sv000017DEsd000008A6* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (KWorld/VStream XPert DVB-T) pci:v000014F1d00008802sv000018ACsd0000D500* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (DViCO FusionHDTV5 Gold) pci:v000014F1d00008802sv000018ACsd0000D810* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (DViCO FusionHDTV3 Gold-Q) pci:v000014F1d00008802sv000018ACsd0000D820* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (DViCO FusionHDTV3 Gold-T) pci:v000014F1d00008802sv000018ACsd0000DB00* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (DVICO FusionHDTV DVB-T1) pci:v000014F1d00008802sv000018ACsd0000DB10* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (DVICO FusionHDTV DVB-T Plus) pci:v000014F1d00008802sv00005654sd00002388* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (GoTView PCI Hybrid TS Capture Device) pci:v000014F1d00008802sv00007063sd00003000* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (pcHDTV HD3000 HDTV) pci:v000014F1d00008802sv00007063sd00005500* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (pcHDTV HD-5500) pci:v000014F1d00008804* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [IR Port] pci:v000014F1d00008804sv00000070sd00006902* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [IR Port] (WinTV HVR-4000-HD) pci:v000014F1d00008804sv00000070sd00009002* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [IR Port] (Nova-T DVB-T Model 909) pci:v000014F1d00008804sv00000070sd00009402* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [IR Port] (WinTV-HVR1100 DVB-T/Hybrid) pci:v000014F1d00008804sv00007063sd00005500* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [IR Port] (pcHDTV HD-5500) pci:v000014F1d00008811* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] pci:v000014F1d00008811sv00000070sd00003400* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (WinTV 34604) pci:v000014F1d00008811sv00000070sd00003401* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (Hauppauge WinTV 34xxx models) pci:v000014F1d00008811sv00000070sd00006902* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (WinTV HVR-4000-HD) pci:v000014F1d00008811sv00000070sd00009402* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (WinTV-HVR1100 DVB-T/Hybrid) pci:v000014F1d00008811sv00000070sd00009600* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (WinTV 88x Audio) pci:v000014F1d00008811sv00001462sd00008606* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (MSI TV-@nywhere Master) pci:v000014F1d00008811sv000018ACsd0000D500* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (DViCO FusionHDTV5 Gold) pci:v000014F1d00008811sv000018ACsd0000D810* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (DViCO FusionHDTV3 Gold-Q) pci:v000014F1d00008811sv000018ACsd0000D820* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (DViCO FusionHDTV3 Gold-T) pci:v000014F1d00008811sv000018ACsd0000DB00* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (DVICO FusionHDTV DVB-T1) pci:v000014F1d00008811sv00005654sd00002388* ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (GoTView PCI Hybrid Audio Capture Device) pci:v000014F1d00008852* ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder pci:v000014F1d00008852sv00000070sd00008010* ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (WinTV HVR-1400 ExpressCard) pci:v000014F1d00008852sv00000070sd0000F038* ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (WinTV HVR-5525) pci:v000014F1d00008852sv0000107Dsd00006F22* ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (WinFast PxTV1200) pci:v000014F1d00008852sv000013C2sd00003013* ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (TT-budget CT2-4500 CI) pci:v000014F1d00008852sv00001461sd0000C039* ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (AVerTV Hybrid Express (A577)) pci:v000014F1d00008852sv0000153Bsd0000117E* ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (Cinergy T PCIe Dual) pci:v000014F1d00008852sv000018ACsd0000DB78* ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (FusionHDTV DVB-T Dual Express) pci:v000014F1d00008852sv00004254sd00000950* ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (S950) pci:v000014F1d00008852sv00004254sd00000952* ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (S952) pci:v000014F1d00008852sv00004254sd00000982* ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (T982) pci:v000014F1d00008852sv00004254sd00009580* ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (T9580) pci:v000014F1d00008852sv00004254sd0000980C* ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (T980C) pci:v000014F1d00008880* ID_MODEL_FROM_DATABASE=CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb pci:v000014F1d00008880sv00000070sd00002259* ID_MODEL_FROM_DATABASE=CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb (WinTV HVR-1250) pci:v000014F1d00008880sv00000070sd0000C108* ID_MODEL_FROM_DATABASE=CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb (WinTV-HVR-4400-HD model 1278) pci:v000014F1d00008880sv00005654sd00002389* ID_MODEL_FROM_DATABASE=CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb (GoTView X5 DVD Hybrid PCI-E) pci:v000014F1d00008880sv00005654sd00002390* ID_MODEL_FROM_DATABASE=CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb (GoTView X5 3D HYBRID PCI-E) pci:v000014F2* ID_VENDOR_FROM_DATABASE=MOBILITY Electronics pci:v000014F2d00000120* ID_MODEL_FROM_DATABASE=EV1000 bridge pci:v000014F2d00000121* ID_MODEL_FROM_DATABASE=EV1000 Parallel port pci:v000014F2d00000122* ID_MODEL_FROM_DATABASE=EV1000 Serial port pci:v000014F2d00000123* ID_MODEL_FROM_DATABASE=EV1000 Keyboard controller pci:v000014F2d00000124* ID_MODEL_FROM_DATABASE=EV1000 Mouse controller pci:v000014F3* ID_VENDOR_FROM_DATABASE=BroadLogic pci:v000014F3d00002030* ID_MODEL_FROM_DATABASE=2030 DVB-S Satellite Receiver pci:v000014F3d00002035* ID_MODEL_FROM_DATABASE=2035 DVB-S Satellite Receiver pci:v000014F3d00002050* ID_MODEL_FROM_DATABASE=2050 DVB-T Terrestrial (Cable) Receiver pci:v000014F3d00002060* ID_MODEL_FROM_DATABASE=2060 ATSC Terrestrial (Cable) Receiver pci:v000014F4* ID_VENDOR_FROM_DATABASE=TOKYO Electronic Industry CO Ltd pci:v000014F5* ID_VENDOR_FROM_DATABASE=SOPAC Ltd pci:v000014F6* ID_VENDOR_FROM_DATABASE=COYOTE Technologies LLC pci:v000014F7* ID_VENDOR_FROM_DATABASE=WOLF Technology Inc pci:v000014F8* ID_VENDOR_FROM_DATABASE=AUDIOCODES Inc pci:v000014F8d00002077* ID_MODEL_FROM_DATABASE=TP-240 dual span E1 VoIP PCI card pci:v000014F9* ID_VENDOR_FROM_DATABASE=AG COMMUNICATIONS pci:v000014FA* ID_VENDOR_FROM_DATABASE=WANDEL & GOLTERMANN pci:v000014FB* ID_VENDOR_FROM_DATABASE=TRANSAS MARINE (UK) Ltd pci:v000014FC* ID_VENDOR_FROM_DATABASE=Quadrics Ltd pci:v000014FCd00000000* ID_MODEL_FROM_DATABASE=QsNet Elan3 Network Adapter pci:v000014FCd00000001* ID_MODEL_FROM_DATABASE=QsNetII Elan4 Network Adapter pci:v000014FCd00000002* ID_MODEL_FROM_DATABASE=QsNetIII Elan5 Network Adapter pci:v000014FD* ID_VENDOR_FROM_DATABASE=JAPAN Computer Industry Inc pci:v000014FE* ID_VENDOR_FROM_DATABASE=ARCHTEK TELECOM Corp pci:v000014FF* ID_VENDOR_FROM_DATABASE=TWINHEAD INTERNATIONAL Corp pci:v00001500* ID_VENDOR_FROM_DATABASE=DELTA Electronics, Inc pci:v00001500d00001360* ID_MODEL_FROM_DATABASE=RTL81xx RealTek Ethernet pci:v00001501* ID_VENDOR_FROM_DATABASE=BANKSOFT CANADA Ltd pci:v00001502* ID_VENDOR_FROM_DATABASE=MITSUBISHI ELECTRIC LOGISTICS SUPPORT Co Ltd pci:v00001503* ID_VENDOR_FROM_DATABASE=KAWASAKI LSI USA Inc pci:v00001504* ID_VENDOR_FROM_DATABASE=KAISER Electronics pci:v00001505* ID_VENDOR_FROM_DATABASE=ITA INGENIEURBURO FUR TESTAUFGABEN GmbH pci:v00001506* ID_VENDOR_FROM_DATABASE=CHAMELEON Systems Inc pci:v00001507* ID_VENDOR_FROM_DATABASE=Motorola ?? / HTEC pci:v00001507d00000001* ID_MODEL_FROM_DATABASE=MPC105 [Eagle] pci:v00001507d00000002* ID_MODEL_FROM_DATABASE=MPC106 [Grackle] pci:v00001507d00000003* ID_MODEL_FROM_DATABASE=MPC8240 [Kahlua] pci:v00001507d00000100* ID_MODEL_FROM_DATABASE=MC145575 [HFC-PCI] pci:v00001507d00000431* ID_MODEL_FROM_DATABASE=KTI829c 100VG pci:v00001507d00004801* ID_MODEL_FROM_DATABASE=Raven pci:v00001507d00004802* ID_MODEL_FROM_DATABASE=Falcon pci:v00001507d00004803* ID_MODEL_FROM_DATABASE=Hawk pci:v00001507d00004806* ID_MODEL_FROM_DATABASE=CPX8216 pci:v00001508* ID_VENDOR_FROM_DATABASE=HONDA CONNECTORS/MHOTRONICS Inc pci:v00001509* ID_VENDOR_FROM_DATABASE=FIRST INTERNATIONAL Computer Inc pci:v0000150A* ID_VENDOR_FROM_DATABASE=FORVUS RESEARCH Inc pci:v0000150B* ID_VENDOR_FROM_DATABASE=YAMASHITA Systems Corp pci:v0000150C* ID_VENDOR_FROM_DATABASE=KYOPAL CO Ltd pci:v0000150D* ID_VENDOR_FROM_DATABASE=WARPSPPED Inc pci:v0000150E* ID_VENDOR_FROM_DATABASE=C-PORT Corp pci:v0000150F* ID_VENDOR_FROM_DATABASE=INTEC GmbH pci:v00001510* ID_VENDOR_FROM_DATABASE=BEHAVIOR TECH Computer Corp pci:v00001511* ID_VENDOR_FROM_DATABASE=CENTILLIUM Technology Corp pci:v00001512* ID_VENDOR_FROM_DATABASE=ROSUN Technologies Inc pci:v00001513* ID_VENDOR_FROM_DATABASE=Raychem pci:v00001514* ID_VENDOR_FROM_DATABASE=TFL LAN Inc pci:v00001515* ID_VENDOR_FROM_DATABASE=Advent design pci:v00001516* ID_VENDOR_FROM_DATABASE=MYSON Technology Inc pci:v00001516d00000800* ID_MODEL_FROM_DATABASE=MTD-8xx 100/10M Ethernet PCI Adapter pci:v00001516d00000803* ID_MODEL_FROM_DATABASE=SURECOM EP-320X-S 100/10M Ethernet PCI Adapter pci:v00001516d00000803sv00001320sd000010BD* ID_MODEL_FROM_DATABASE=SURECOM EP-320X-S 100/10M Ethernet PCI Adapter pci:v00001516d00000891* ID_MODEL_FROM_DATABASE=MTD-8xx 100/10M Ethernet PCI Adapter pci:v00001517* ID_VENDOR_FROM_DATABASE=ECHOTEK Corp pci:v00001518* ID_VENDOR_FROM_DATABASE=Kontron pci:v00001519* ID_VENDOR_FROM_DATABASE=TELEFON AKTIEBOLAGET LM Ericsson pci:v0000151A* ID_VENDOR_FROM_DATABASE=Globetek pci:v0000151Ad00001002* ID_MODEL_FROM_DATABASE=PCI-1002 pci:v0000151Ad00001004* ID_MODEL_FROM_DATABASE=PCI-1004 pci:v0000151Ad00001008* ID_MODEL_FROM_DATABASE=PCI-1008 pci:v0000151B* ID_VENDOR_FROM_DATABASE=COMBOX Ltd pci:v0000151C* ID_VENDOR_FROM_DATABASE=DIGITAL AUDIO LABS Inc pci:v0000151Cd00000003* ID_MODEL_FROM_DATABASE=Prodif T 2496 pci:v0000151Cd00004000* ID_MODEL_FROM_DATABASE=Prodif 88 pci:v0000151D* ID_VENDOR_FROM_DATABASE=Fujitsu Computer Products Of America pci:v0000151E* ID_VENDOR_FROM_DATABASE=MATRIX Corp pci:v0000151F* ID_VENDOR_FROM_DATABASE=TOPIC SEMICONDUCTOR Corp pci:v0000151Fd00000000* ID_MODEL_FROM_DATABASE=TP560 Data/Fax/Voice 56k modem pci:v00001520* ID_VENDOR_FROM_DATABASE=CHAPLET System Inc pci:v00001521* ID_VENDOR_FROM_DATABASE=BELL Corp pci:v00001522* ID_VENDOR_FROM_DATABASE=MainPine Ltd pci:v00001522d00000100* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge pci:v00001522d00000100sv00001522sd00000200* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceDUO 2 Port V.92/V.44 Data/Fax/Voice Modem) pci:v00001522d00000100sv00001522sd00000300* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceQUATRO 4 Port V.92/V.44 Data/Fax/Voice Modem) pci:v00001522d00000100sv00001522sd00000400* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceDUO+ 2 Port V.92/V.44 Data/Fax/Voice Modem) pci:v00001522d00000100sv00001522sd00000500* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceQUATRO+ 4 Port V.92/V.44 Data/Fax/Voice Modem) pci:v00001522d00000100sv00001522sd00000600* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce+ 2 Port V.90 Data/Fax/Voice Modem) pci:v00001522d00000100sv00001522sd00000700* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce+ 4 Port V.90 Data/Fax/Voice Modem) pci:v00001522d00000100sv00001522sd00000800* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceOCTO+ 8 Port V.92/V.44 Data/Fax/Voice Modem) pci:v00001522d00000100sv00001522sd00000C00* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceDUO+ 2 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem) pci:v00001522d00000100sv00001522sd00000D00* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceQUATRO+ 4 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem) pci:v00001522d00000100sv00001522sd00001D00* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceOCTO+ 8 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem) pci:v00001522d00000100sv00001522sd00002000* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceD1 1 Port V.90 Data Modem) pci:v00001522d00000100sv00001522sd00002100* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceF1 1 Port V.34 Super-G3 Fax Modem) pci:v00001522d00000100sv00001522sd00002200* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceD2 2 Port V.90 Data Modem) pci:v00001522d00000100sv00001522sd00002300* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceF2 2 Port V.34 Super-G3 Fax Modem) pci:v00001522d00000100sv00001522sd00002400* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceD4 4 Port V.90 Data Modem) pci:v00001522d00000100sv00001522sd00002500* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceF4 4 Port V.34 Super-G3 Fax Modem) pci:v00001522d00000100sv00001522sd00002600* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceD8 8 Port V.90 Data Modem) pci:v00001522d00000100sv00001522sd00002700* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceF8 8 Port V.34 Super-G3 Fax Modem) pci:v00001522d00000100sv00001522sd00003000* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express D1 - 1 Port V.92 Data Modem) pci:v00001522d00000100sv00001522sd00003100* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express F1 - 1 Port V.34 Super-G3 Fax Modem) pci:v00001522d00000100sv00001522sd00003200* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express D2 - 2 Port V.92 Data Modem) pci:v00001522d00000100sv00001522sd00003300* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express F2 - 2 Port V.34 Super-G3 Fax Modem) pci:v00001522d00000100sv00001522sd00003400* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express D4 - 4 Port V.92 Data Modem) pci:v00001522d00000100sv00001522sd00003500* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express F4 - 4 Port V.34 Super-G3 Fax Modem) pci:v00001522d00000100sv00001522sd00003C00* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express D8 - 8 Port V.92 Data Modem) pci:v00001522d00000100sv00001522sd00003D00* ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express F8 - 8 Port V.34 Super-G3 Fax Modem) pci:v00001522d00004000* ID_MODEL_FROM_DATABASE=PCI Express UART pci:v00001522d00004000sv00001522sd00004001* ID_MODEL_FROM_DATABASE=PCI Express UART (IQ Express 1-port V.34 Super-G3 Fax) pci:v00001522d00004000sv00001522sd00004002* ID_MODEL_FROM_DATABASE=PCI Express UART (IQ Express 2-port V.34 Super-G3 Fax) pci:v00001522d00004000sv00001522sd00004004* ID_MODEL_FROM_DATABASE=PCI Express UART (IQ Express 4-port V.34 Super-G3 Fax) pci:v00001522d00004000sv00001522sd00004008* ID_MODEL_FROM_DATABASE=PCI Express UART (IQ Express 8-port V.34 Super-G3 Fax) pci:v00001522d00004000sv00001522sd00004100* ID_MODEL_FROM_DATABASE=PCI Express UART (IQ Express SideBand) pci:v00001523* ID_VENDOR_FROM_DATABASE=MUSIC Semiconductors pci:v00001524* ID_VENDOR_FROM_DATABASE=ENE Technology Inc pci:v00001524d00000510* ID_MODEL_FROM_DATABASE=CB710 Memory Card Reader Controller pci:v00001524d00000510sv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=CB710 Memory Card Reader Controller (NX9500) pci:v00001524d00000520* ID_MODEL_FROM_DATABASE=FLASH memory: ENE Technology Inc: pci:v00001524d00000530* ID_MODEL_FROM_DATABASE=ENE PCI Memory Stick Card Reader Controller pci:v00001524d00000550* ID_MODEL_FROM_DATABASE=ENE PCI Secure Digital Card Reader Controller pci:v00001524d00000551* ID_MODEL_FROM_DATABASE=SD/MMC Card Reader Controller pci:v00001524d00000610* ID_MODEL_FROM_DATABASE=PCI Smart Card Reader Controller pci:v00001524d00000720* ID_MODEL_FROM_DATABASE=Memory Stick Card Reader Controller pci:v00001524d00000730* ID_MODEL_FROM_DATABASE=ENE PCI Memory Stick Card Reader Controller pci:v00001524d00000750* ID_MODEL_FROM_DATABASE=ENE PCI SmartMedia / xD Card Reader Controller pci:v00001524d00000751* ID_MODEL_FROM_DATABASE=ENE PCI Secure Digital / MMC Card Reader Controller pci:v00001524d00001211* ID_MODEL_FROM_DATABASE=CB1211 Cardbus Controller pci:v00001524d00001225* ID_MODEL_FROM_DATABASE=CB1225 Cardbus Controller pci:v00001524d00001410* ID_MODEL_FROM_DATABASE=CB1410 Cardbus Controller pci:v00001524d00001410sv00001025sd0000003C* ID_MODEL_FROM_DATABASE=CB1410 Cardbus Controller (CL50 motherboard) pci:v00001524d00001410sv00001025sd0000005A* ID_MODEL_FROM_DATABASE=CB1410 Cardbus Controller (TravelMate 290) pci:v00001524d00001411* ID_MODEL_FROM_DATABASE=CB-710/2/4 Cardbus Controller pci:v00001524d00001411sv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=CB-710/2/4 Cardbus Controller (NX9500) pci:v00001524d00001412* ID_MODEL_FROM_DATABASE=CB-712/4 Cardbus Controller pci:v00001524d00001420* ID_MODEL_FROM_DATABASE=CB1420 Cardbus Controller pci:v00001524d00001421* ID_MODEL_FROM_DATABASE=CB-720/2/4 Cardbus Controller pci:v00001524d00001422* ID_MODEL_FROM_DATABASE=CB-722/4 Cardbus Controller pci:v00001525* ID_VENDOR_FROM_DATABASE=IMPACT Technologies pci:v00001526* ID_VENDOR_FROM_DATABASE=ISS, Inc pci:v00001527* ID_VENDOR_FROM_DATABASE=SOLECTRON pci:v00001528* ID_VENDOR_FROM_DATABASE=ACKSYS pci:v00001529* ID_VENDOR_FROM_DATABASE=AMERICAN MICROSystems Inc pci:v0000152A* ID_VENDOR_FROM_DATABASE=QUICKTURN DESIGN Systems pci:v0000152B* ID_VENDOR_FROM_DATABASE=FLYTECH Technology CO Ltd pci:v0000152C* ID_VENDOR_FROM_DATABASE=MACRAIGOR Systems LLC pci:v0000152D* ID_VENDOR_FROM_DATABASE=QUANTA Computer Inc pci:v0000152E* ID_VENDOR_FROM_DATABASE=MELEC Inc pci:v0000152F* ID_VENDOR_FROM_DATABASE=PHILIPS - CRYPTO pci:v00001530* ID_VENDOR_FROM_DATABASE=ACQIS Technology Inc pci:v00001531* ID_VENDOR_FROM_DATABASE=CHRYON Corp pci:v00001532* ID_VENDOR_FROM_DATABASE=ECHELON Corp pci:v00001532d00000020* ID_MODEL_FROM_DATABASE=LonWorks PCLTA-20 PCI LonTalk Adapter pci:v00001533* ID_VENDOR_FROM_DATABASE=BALTIMORE pci:v00001534* ID_VENDOR_FROM_DATABASE=ROAD Corp pci:v00001535* ID_VENDOR_FROM_DATABASE=EVERGREEN Technologies Inc pci:v00001536* ID_VENDOR_FROM_DATABASE=ACTIS Computer pci:v00001537* ID_VENDOR_FROM_DATABASE=DATALEX COMMUNCATIONS pci:v00001538* ID_VENDOR_FROM_DATABASE=ARALION Inc pci:v00001538d00000303* ID_MODEL_FROM_DATABASE=ARS106S Ultra ATA 133/100/66 Host Controller pci:v00001539* ID_VENDOR_FROM_DATABASE=ATELIER INFORMATIQUES et ELECTRONIQUE ETUDES S.A. pci:v0000153A* ID_VENDOR_FROM_DATABASE=ONO SOKKI pci:v0000153B* ID_VENDOR_FROM_DATABASE=TERRATEC Electronic GmbH pci:v0000153Bd00001144* ID_MODEL_FROM_DATABASE=Aureon 5.1 pci:v0000153Bd00001147* ID_MODEL_FROM_DATABASE=Aureon 5.1 Sky pci:v0000153Bd00001158* ID_MODEL_FROM_DATABASE=Philips Semiconductors SAA7134 (rev 01) [Terratec Cinergy 600 TV] pci:v0000153C* ID_VENDOR_FROM_DATABASE=ANTAL Electronic pci:v0000153D* ID_VENDOR_FROM_DATABASE=FILANET Corp pci:v0000153E* ID_VENDOR_FROM_DATABASE=TECHWELL Inc pci:v0000153F* ID_VENDOR_FROM_DATABASE=MIPS Technologies, Inc. pci:v0000153Fd00000001* ID_MODEL_FROM_DATABASE=SOC-it 101 System Controller pci:v00001540* ID_VENDOR_FROM_DATABASE=PROVIDEO MULTIMEDIA Co Ltd pci:v00001541* ID_VENDOR_FROM_DATABASE=MACHONE Communications pci:v00001542* ID_VENDOR_FROM_DATABASE=Concurrent Computer Corporation pci:v00001542d00009260* ID_MODEL_FROM_DATABASE=RCIM-II Real-Time Clock & Interrupt Module pci:v00001542d00009271* ID_MODEL_FROM_DATABASE=RCIM-III Real-Time Clock & Interrupt Module (PCIe) pci:v00001542d00009272* ID_MODEL_FROM_DATABASE=Pulse Width Modulator Card pci:v00001542d00009277* ID_MODEL_FROM_DATABASE=5 Volt Delta Sigma Converter Card pci:v00001542d00009278* ID_MODEL_FROM_DATABASE=10 Volt Delta Sigma Converter Card pci:v00001542d00009287* ID_MODEL_FROM_DATABASE=Analog Output Card pci:v00001543* ID_VENDOR_FROM_DATABASE=SILICON Laboratories pci:v00001543d00003052* ID_MODEL_FROM_DATABASE=Intel 537 [Winmodem] pci:v00001543d00004C22* ID_MODEL_FROM_DATABASE=Si3036 MC'97 DAA pci:v00001544* ID_VENDOR_FROM_DATABASE=DCM DATA Systems pci:v00001545* ID_VENDOR_FROM_DATABASE=VISIONTEK pci:v00001546* ID_VENDOR_FROM_DATABASE=IOI Technology Corp pci:v00001547* ID_VENDOR_FROM_DATABASE=MITUTOYO Corp pci:v00001548* ID_VENDOR_FROM_DATABASE=JET PROPULSION Laboratory pci:v00001549* ID_VENDOR_FROM_DATABASE=INTERCONNECT Systems Solutions pci:v0000154A* ID_VENDOR_FROM_DATABASE=MAX Technologies Inc pci:v0000154B* ID_VENDOR_FROM_DATABASE=COMPUTEX Co Ltd pci:v0000154C* ID_VENDOR_FROM_DATABASE=VISUAL Technology Inc pci:v0000154D* ID_VENDOR_FROM_DATABASE=PAN INTERNATIONAL Industrial Corp pci:v0000154E* ID_VENDOR_FROM_DATABASE=SERVOTEST Ltd pci:v0000154F* ID_VENDOR_FROM_DATABASE=STRATABEAM Technology pci:v00001550* ID_VENDOR_FROM_DATABASE=OPEN NETWORK Co Ltd pci:v00001551* ID_VENDOR_FROM_DATABASE=SMART Electronic DEVELOPMENT GmBH pci:v00001552* ID_VENDOR_FROM_DATABASE=RACAL AIRTECH Ltd pci:v00001553* ID_VENDOR_FROM_DATABASE=CHICONY Electronics Co Ltd pci:v00001554* ID_VENDOR_FROM_DATABASE=PROLINK Microsystems Corp pci:v00001555* ID_VENDOR_FROM_DATABASE=GESYTEC GmBH pci:v00001556* ID_VENDOR_FROM_DATABASE=PLDA pci:v00001556d00001100* ID_MODEL_FROM_DATABASE=PCI Express Core Reference Design pci:v00001556d0000110F* ID_MODEL_FROM_DATABASE=PCI Express Core Reference Design Virtual Function pci:v00001557* ID_VENDOR_FROM_DATABASE=MEDIASTAR Co Ltd pci:v00001558* ID_VENDOR_FROM_DATABASE=CLEVO/KAPOK Computer pci:v00001559* ID_VENDOR_FROM_DATABASE=SI LOGIC Ltd pci:v0000155A* ID_VENDOR_FROM_DATABASE=INNOMEDIA Inc pci:v0000155B* ID_VENDOR_FROM_DATABASE=PROTAC INTERNATIONAL Corp pci:v0000155C* ID_VENDOR_FROM_DATABASE=Cemax-Icon Inc pci:v0000155D* ID_VENDOR_FROM_DATABASE=Mac System Co Ltd pci:v0000155E* ID_VENDOR_FROM_DATABASE=LP Elektronik GmbH pci:v0000155F* ID_VENDOR_FROM_DATABASE=Perle Systems Ltd pci:v00001560* ID_VENDOR_FROM_DATABASE=Terayon Communications Systems pci:v00001561* ID_VENDOR_FROM_DATABASE=Viewgraphics Inc pci:v00001562* ID_VENDOR_FROM_DATABASE=Symbol Technologies pci:v00001563* ID_VENDOR_FROM_DATABASE=A-Trend Technology Co Ltd pci:v00001564* ID_VENDOR_FROM_DATABASE=Yamakatsu Electronics Industry Co Ltd pci:v00001565* ID_VENDOR_FROM_DATABASE=Biostar Microtech Int'l Corp pci:v00001566* ID_VENDOR_FROM_DATABASE=Ardent Technologies Inc pci:v00001567* ID_VENDOR_FROM_DATABASE=Jungsoft pci:v00001568* ID_VENDOR_FROM_DATABASE=DDK Electronics Inc pci:v00001569* ID_VENDOR_FROM_DATABASE=Palit Microsystems Inc. pci:v0000156A* ID_VENDOR_FROM_DATABASE=Avtec Systems pci:v0000156B* ID_VENDOR_FROM_DATABASE=2wire Inc pci:v0000156C* ID_VENDOR_FROM_DATABASE=Vidac Electronics GmbH pci:v0000156D* ID_VENDOR_FROM_DATABASE=Alpha-Top Corp pci:v0000156E* ID_VENDOR_FROM_DATABASE=Alfa Inc pci:v0000156F* ID_VENDOR_FROM_DATABASE=M-Systems Flash Disk Pioneers Ltd pci:v00001570* ID_VENDOR_FROM_DATABASE=Lecroy Corp pci:v00001571* ID_VENDOR_FROM_DATABASE=Contemporary Controls pci:v00001571d0000A001* ID_MODEL_FROM_DATABASE=CCSI PCI20-485 ARCnet pci:v00001571d0000A002* ID_MODEL_FROM_DATABASE=CCSI PCI20-485D ARCnet pci:v00001571d0000A003* ID_MODEL_FROM_DATABASE=CCSI PCI20-485X ARCnet pci:v00001571d0000A004* ID_MODEL_FROM_DATABASE=CCSI PCI20-CXB ARCnet pci:v00001571d0000A005* ID_MODEL_FROM_DATABASE=CCSI PCI20-CXS ARCnet pci:v00001571d0000A006* ID_MODEL_FROM_DATABASE=CCSI PCI20-FOG-SMA ARCnet pci:v00001571d0000A007* ID_MODEL_FROM_DATABASE=CCSI PCI20-FOG-ST ARCnet pci:v00001571d0000A008* ID_MODEL_FROM_DATABASE=CCSI PCI20-TB5 ARCnet pci:v00001571d0000A009* ID_MODEL_FROM_DATABASE=CCSI PCI20-5-485 5Mbit ARCnet pci:v00001571d0000A00A* ID_MODEL_FROM_DATABASE=CCSI PCI20-5-485D 5Mbit ARCnet pci:v00001571d0000A00B* ID_MODEL_FROM_DATABASE=CCSI PCI20-5-485X 5Mbit ARCnet pci:v00001571d0000A00C* ID_MODEL_FROM_DATABASE=CCSI PCI20-5-FOG-ST 5Mbit ARCnet pci:v00001571d0000A00D* ID_MODEL_FROM_DATABASE=CCSI PCI20-5-FOG-SMA 5Mbit ARCnet pci:v00001571d0000A201* ID_MODEL_FROM_DATABASE=CCSI PCI22-485 10Mbit ARCnet pci:v00001571d0000A202* ID_MODEL_FROM_DATABASE=CCSI PCI22-485D 10Mbit ARCnet pci:v00001571d0000A203* ID_MODEL_FROM_DATABASE=CCSI PCI22-485X 10Mbit ARCnet pci:v00001571d0000A204* ID_MODEL_FROM_DATABASE=CCSI PCI22-CHB 10Mbit ARCnet pci:v00001571d0000A205* ID_MODEL_FROM_DATABASE=CCSI PCI22-FOG_ST 10Mbit ARCnet pci:v00001571d0000A206* ID_MODEL_FROM_DATABASE=CCSI PCI22-THB 10Mbit ARCnet pci:v00001572* ID_VENDOR_FROM_DATABASE=Otis Elevator Company pci:v00001573* ID_VENDOR_FROM_DATABASE=Lattice - Vantis pci:v00001574* ID_VENDOR_FROM_DATABASE=Fairchild Semiconductor pci:v00001575* ID_VENDOR_FROM_DATABASE=Voltaire Advanced Data Security Ltd pci:v00001576* ID_VENDOR_FROM_DATABASE=Viewcast COM pci:v00001578* ID_VENDOR_FROM_DATABASE=HITT pci:v00001578d00004D34* ID_MODEL_FROM_DATABASE=VPMK4 [Video Processor Mk IV] pci:v00001578d00005615* ID_MODEL_FROM_DATABASE=VPMK3 [Video Processor Mk III] pci:v00001579* ID_VENDOR_FROM_DATABASE=Dual Technology Corp pci:v0000157A* ID_VENDOR_FROM_DATABASE=Japan Elecronics Ind Inc pci:v0000157B* ID_VENDOR_FROM_DATABASE=Star Multimedia Corp pci:v0000157C* ID_VENDOR_FROM_DATABASE=Eurosoft (UK) pci:v0000157Cd00008001* ID_MODEL_FROM_DATABASE=Fix2000 PCI Y2K Compliance Card pci:v0000157D* ID_VENDOR_FROM_DATABASE=Gemflex Networks pci:v0000157E* ID_VENDOR_FROM_DATABASE=Transition Networks pci:v0000157F* ID_VENDOR_FROM_DATABASE=PX Instruments Technology Ltd pci:v00001580* ID_VENDOR_FROM_DATABASE=Primex Aerospace Co pci:v00001581* ID_VENDOR_FROM_DATABASE=SEH Computertechnik GmbH pci:v00001582* ID_VENDOR_FROM_DATABASE=Cytec Corp pci:v00001583* ID_VENDOR_FROM_DATABASE=Inet Technologies Inc pci:v00001584* ID_VENDOR_FROM_DATABASE=Uniwill Computer Corp pci:v00001585* ID_VENDOR_FROM_DATABASE=Logitron pci:v00001586* ID_VENDOR_FROM_DATABASE=Lancast Inc pci:v00001587* ID_VENDOR_FROM_DATABASE=Konica Corp pci:v00001588* ID_VENDOR_FROM_DATABASE=Solidum Systems Corp pci:v00001589* ID_VENDOR_FROM_DATABASE=Atlantek Microsystems Pty Ltd pci:v00001589d00000008* ID_MODEL_FROM_DATABASE=Leutron Vision PicPortExpress CL pci:v00001589d00000009* ID_MODEL_FROM_DATABASE=Leutron Vision PicPortExpress CL Stereo pci:v0000158A* ID_VENDOR_FROM_DATABASE=Digalog Systems Inc pci:v0000158B* ID_VENDOR_FROM_DATABASE=Allied Data Technologies pci:v0000158C* ID_VENDOR_FROM_DATABASE=Hitachi Semiconductor & Devices Sales Co Ltd pci:v0000158D* ID_VENDOR_FROM_DATABASE=Point Multimedia Systems pci:v0000158E* ID_VENDOR_FROM_DATABASE=Lara Technology Inc pci:v0000158F* ID_VENDOR_FROM_DATABASE=Ditect Coop pci:v00001590* ID_VENDOR_FROM_DATABASE=Hewlett Packard Enterprise pci:v00001590d00000001* ID_MODEL_FROM_DATABASE=Eagle Cluster Manager pci:v00001590d00000002* ID_MODEL_FROM_DATABASE=Osprey Cluster Manager pci:v00001590d00000003* ID_MODEL_FROM_DATABASE=Harrier Cluster Manager pci:v00001590d0000A01D* ID_MODEL_FROM_DATABASE=FC044X Fibre Channel HBA pci:v00001591* ID_VENDOR_FROM_DATABASE=ARN pci:v00001592* ID_VENDOR_FROM_DATABASE=Syba Tech Ltd pci:v00001592d00000781* ID_MODEL_FROM_DATABASE=Multi-IO Card pci:v00001592d00000782* ID_MODEL_FROM_DATABASE=Parallel Port Card 2xEPP pci:v00001592d00000783* ID_MODEL_FROM_DATABASE=Multi-IO Card pci:v00001592d00000785* ID_MODEL_FROM_DATABASE=Multi-IO Card pci:v00001592d00000786* ID_MODEL_FROM_DATABASE=Multi-IO Card pci:v00001592d00000787* ID_MODEL_FROM_DATABASE=Multi-IO Card pci:v00001592d00000788* ID_MODEL_FROM_DATABASE=Multi-IO Card pci:v00001592d0000078A* ID_MODEL_FROM_DATABASE=Multi-IO Card pci:v00001593* ID_VENDOR_FROM_DATABASE=Bops Inc pci:v00001594* ID_VENDOR_FROM_DATABASE=Netgame Ltd pci:v00001595* ID_VENDOR_FROM_DATABASE=Diva Systems Corp pci:v00001596* ID_VENDOR_FROM_DATABASE=Folsom Research Inc pci:v00001597* ID_VENDOR_FROM_DATABASE=Memec Design Services pci:v00001598* ID_VENDOR_FROM_DATABASE=Granite Microsystems pci:v00001599* ID_VENDOR_FROM_DATABASE=Delta Electronics Inc pci:v0000159A* ID_VENDOR_FROM_DATABASE=General Instrument pci:v0000159B* ID_VENDOR_FROM_DATABASE=Faraday Technology Corp pci:v0000159C* ID_VENDOR_FROM_DATABASE=Stratus Computer Systems pci:v0000159D* ID_VENDOR_FROM_DATABASE=Ningbo Harrison Electronics Co Ltd pci:v0000159E* ID_VENDOR_FROM_DATABASE=A-Max Technology Co Ltd pci:v0000159F* ID_VENDOR_FROM_DATABASE=Galea Network Security pci:v000015A0* ID_VENDOR_FROM_DATABASE=Compumaster SRL pci:v000015A1* ID_VENDOR_FROM_DATABASE=Geocast Network Systems pci:v000015A2* ID_VENDOR_FROM_DATABASE=Catalyst Enterprises Inc pci:v000015A2d00000001* ID_MODEL_FROM_DATABASE=TA700 PCI Bus Analyzer/Exerciser pci:v000015A3* ID_VENDOR_FROM_DATABASE=Italtel pci:v000015A4* ID_VENDOR_FROM_DATABASE=X-Net OY pci:v000015A5* ID_VENDOR_FROM_DATABASE=Toyota Macs Inc pci:v000015A6* ID_VENDOR_FROM_DATABASE=Sunlight Ultrasound Technologies Ltd pci:v000015A7* ID_VENDOR_FROM_DATABASE=SSE Telecom Inc pci:v000015A8* ID_VENDOR_FROM_DATABASE=Shanghai Communications Technologies Center pci:v000015AA* ID_VENDOR_FROM_DATABASE=Moreton Bay pci:v000015AB* ID_VENDOR_FROM_DATABASE=Bluesteel Networks Inc pci:v000015AC* ID_VENDOR_FROM_DATABASE=North Atlantic Instruments pci:v000015AD* ID_VENDOR_FROM_DATABASE=VMware pci:v000015ADd00000405* ID_MODEL_FROM_DATABASE=SVGA II Adapter pci:v000015ADd00000710* ID_MODEL_FROM_DATABASE=SVGA Adapter pci:v000015ADd00000720* ID_MODEL_FROM_DATABASE=VMXNET Ethernet Controller pci:v000015ADd00000740* ID_MODEL_FROM_DATABASE=Virtual Machine Communication Interface pci:v000015ADd00000770* ID_MODEL_FROM_DATABASE=USB2 EHCI Controller pci:v000015ADd00000774* ID_MODEL_FROM_DATABASE=USB1.1 UHCI Controller pci:v000015ADd00000778* ID_MODEL_FROM_DATABASE=USB3 xHCI 0.96 Controller pci:v000015ADd00000779* ID_MODEL_FROM_DATABASE=USB3 xHCI 1.0 Controller pci:v000015ADd00000790* ID_MODEL_FROM_DATABASE=PCI bridge pci:v000015ADd000007A0* ID_MODEL_FROM_DATABASE=PCI Express Root Port pci:v000015ADd000007B0* ID_MODEL_FROM_DATABASE=VMXNET3 Ethernet Controller pci:v000015ADd000007C0* ID_MODEL_FROM_DATABASE=PVSCSI SCSI Controller pci:v000015ADd000007E0* ID_MODEL_FROM_DATABASE=SATA AHCI controller pci:v000015ADd00000801* ID_MODEL_FROM_DATABASE=Virtual Machine Interface pci:v000015ADd00000801sv000015ADsd00000800* ID_MODEL_FROM_DATABASE=Virtual Machine Interface (Hypervisor ROM Interface) pci:v000015ADd00001977* ID_MODEL_FROM_DATABASE=HD Audio Controller pci:v000015AE* ID_VENDOR_FROM_DATABASE=Amersham Pharmacia Biotech pci:v000015B0* ID_VENDOR_FROM_DATABASE=Zoltrix International Ltd pci:v000015B1* ID_VENDOR_FROM_DATABASE=Source Technology Inc pci:v000015B2* ID_VENDOR_FROM_DATABASE=Mosaid Technologies Inc pci:v000015B3* ID_VENDOR_FROM_DATABASE=Mellanox Technologies pci:v000015B3d00000191* ID_MODEL_FROM_DATABASE=MT25408 [ConnectX IB Flash Recovery] pci:v000015B3d000001F6* ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3 Flash Recovery] pci:v000015B3d000001FF* ID_MODEL_FROM_DATABASE=MT27600 Family [Connect-IB Flash Recovery] pci:v000015B3d00000209* ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4 Flash Recovery] pci:v000015B3d0000020B* ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx Flash Recovery] pci:v000015B3d0000020D* ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Flash Recovery] pci:v000015B3d00000262* ID_MODEL_FROM_DATABASE=MT27710 [ConnectX-4 Lx Programmable] EN pci:v000015B3d00000263* ID_MODEL_FROM_DATABASE=MT27710 [ConnectX-4 Lx Programmable Virtual Function] EN pci:v000015B3d00001002* ID_MODEL_FROM_DATABASE=MT25400 Family [ConnectX-2 Virtual Function] pci:v000015B3d00001003* ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] pci:v000015B3d00001003sv0000103Csd00001777* ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (InfiniBand FDR/EN 10/40Gb Dual Port 544FLR-QSFP Adapter (Rev Cx)) pci:v000015B3d00001003sv0000103Csd000017C9* ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (Infiniband QDR/Ethernet 10Gb 2-port 544i Adapter) pci:v000015B3d00001003sv0000103Csd000018CE* ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (InfiniBand QDR/EN 10Gb Dual Port 544M Adapter) pci:v000015B3d00001003sv0000103Csd000018CF* ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (InfiniBand FDR/EN 10/40Gb Dual Port 544M Adapter) pci:v000015B3d00001003sv0000103Csd000018D6* ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (InfiniBand FDR/EN 10/40Gb Dual Port 544QSFP Adapter) pci:v000015B3d00001004* ID_MODEL_FROM_DATABASE=MT27500/MT27520 Family [ConnectX-3/ConnectX-3 Pro Virtual Function] pci:v000015B3d00001005* ID_MODEL_FROM_DATABASE=MT27510 Family pci:v000015B3d00001006* ID_MODEL_FROM_DATABASE=MT27511 Family pci:v000015B3d00001007* ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] pci:v000015B3d00001007sv0000103Csd000022F3* ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (InfiniBand FDR/Ethernet 10Gb/40Gb 2-port 544+QSFP Adapter) pci:v000015B3d00001007sv0000103Csd000022F4* ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (InfiniBand FDR/Ethernet 10Gb/40Gb 2-port 544+FLR-QSFP Adapter) pci:v000015B3d00001007sv0000103Csd0000801F* ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (Ethernet 10G 2-port 546SFP+ Adapter) pci:v000015B3d00001007sv0000117Csd00000090* ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (FastFrame NQ41) pci:v000015B3d00001007sv0000117Csd00000091* ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (FastFrame NQ42) pci:v000015B3d00001007sv0000117Csd00000092* ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (FastFrame NQ11) pci:v000015B3d00001007sv0000117Csd00000093* ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (FastFrame NQ12) pci:v000015B3d00001009* ID_MODEL_FROM_DATABASE=MT27530 Family pci:v000015B3d0000100A* ID_MODEL_FROM_DATABASE=MT27531 Family pci:v000015B3d0000100B* ID_MODEL_FROM_DATABASE=MT27540 Family pci:v000015B3d0000100C* ID_MODEL_FROM_DATABASE=MT27541 Family pci:v000015B3d0000100D* ID_MODEL_FROM_DATABASE=MT27550 Family pci:v000015B3d0000100E* ID_MODEL_FROM_DATABASE=MT27551 Family pci:v000015B3d0000100F* ID_MODEL_FROM_DATABASE=MT27560 Family pci:v000015B3d00001010* ID_MODEL_FROM_DATABASE=MT27561 Family pci:v000015B3d00001011* ID_MODEL_FROM_DATABASE=MT27600 [Connect-IB] pci:v000015B3d00001012* ID_MODEL_FROM_DATABASE=MT27600 Family [Connect-IB Virtual Function] pci:v000015B3d00001013* ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] pci:v000015B3d00001014* ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4 Virtual Function] pci:v000015B3d00001015* ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] pci:v000015B3d00001016* ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx Virtual Function] pci:v000015B3d00001017* ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5] pci:v000015B3d00001018* ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Virtual Function] pci:v000015B3d00005274* ID_MODEL_FROM_DATABASE=MT21108 InfiniBridge pci:v000015B3d00005A44* ID_MODEL_FROM_DATABASE=MT23108 InfiniHost pci:v000015B3d00005A45* ID_MODEL_FROM_DATABASE=MT23108 [Infinihost HCA Flash Recovery] pci:v000015B3d00005A46* ID_MODEL_FROM_DATABASE=MT23108 PCI Bridge pci:v000015B3d00005E8C* ID_MODEL_FROM_DATABASE=MT24204 [InfiniHost III Lx HCA] pci:v000015B3d00005E8D* ID_MODEL_FROM_DATABASE=MT25204 [InfiniHost III Lx HCA Flash Recovery] pci:v000015B3d00006274* ID_MODEL_FROM_DATABASE=MT25204 [InfiniHost III Lx HCA] pci:v000015B3d00006278* ID_MODEL_FROM_DATABASE=MT25208 InfiniHost III Ex (Tavor compatibility mode) pci:v000015B3d00006279* ID_MODEL_FROM_DATABASE=MT25208 [InfiniHost III Ex HCA Flash Recovery] pci:v000015B3d00006282* ID_MODEL_FROM_DATABASE=MT25208 [InfiniHost III Ex] pci:v000015B3d00006340* ID_MODEL_FROM_DATABASE=MT25408 [ConnectX VPI - IB SDR / 10GigE] pci:v000015B3d0000634A* ID_MODEL_FROM_DATABASE=MT25418 [ConnectX VPI PCIe 2.0 2.5GT/s - IB DDR / 10GigE] pci:v000015B3d00006368* ID_MODEL_FROM_DATABASE=MT25448 [ConnectX EN 10GigE, PCIe 2.0 2.5GT/s] pci:v000015B3d00006372* ID_MODEL_FROM_DATABASE=MT25408 [ConnectX EN 10GigE 10GBaseT, PCIe 2.0 2.5GT/s] pci:v000015B3d00006732* ID_MODEL_FROM_DATABASE=MT26418 [ConnectX VPI PCIe 2.0 5GT/s - IB DDR / 10GigE] pci:v000015B3d0000673C* ID_MODEL_FROM_DATABASE=MT26428 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE] pci:v000015B3d0000673Csv0000103Csd00001782* ID_MODEL_FROM_DATABASE=MT26428 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE] (4X QDR InfiniBand Mezzanine HCA for c-Class BladeSystem) pci:v000015B3d0000673Csv000015B3sd00000021* ID_MODEL_FROM_DATABASE=MT26428 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE] (HP InfiniBand 4X QDR CX-2 PCI-e G2 Dual Port HCA) pci:v000015B3d00006746* ID_MODEL_FROM_DATABASE=MT26438 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE Virtualization+] pci:v000015B3d00006746sv0000103Csd00001781* ID_MODEL_FROM_DATABASE=MT26438 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE Virtualization+] (NC543i 1-port 4x QDR IB/Flex-10 10Gb Adapter) pci:v000015B3d00006746sv0000103Csd00003349* ID_MODEL_FROM_DATABASE=MT26438 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE Virtualization+] (NC543i 2-port 4xQDR IB/10Gb Adapter) pci:v000015B3d00006750* ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] pci:v000015B3d00006750sv000015B3sd00000018* ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (HP 10 GbE PCI-e G2 Dual-Port NIC (rev C1)) pci:v000015B3d0000675A* ID_MODEL_FROM_DATABASE=MT25408 [ConnectX EN 10GigE 10GBaseT, PCIe Gen2 5GT/s] pci:v000015B3d00006764* ID_MODEL_FROM_DATABASE=MT26468 [ConnectX EN 10GigE, PCIe 2.0 5GT/s Virtualization+] pci:v000015B3d00006764sv0000103Csd00003313* ID_MODEL_FROM_DATABASE=MT26468 [ConnectX EN 10GigE, PCIe 2.0 5GT/s Virtualization+] (NC542m Dual Port Flex-10 10GbE BLc Adapter) pci:v000015B3d0000676E* ID_MODEL_FROM_DATABASE=MT26478 [ConnectX EN 40GigE, PCIe 2.0 5GT/s] pci:v000015B3d00006778* ID_MODEL_FROM_DATABASE=MT26488 [ConnectX VPI PCIe 2.0 5GT/s - IB DDR / 10GigE Virtualization+] pci:v000015B3d0000C738* ID_MODEL_FROM_DATABASE=MT51136 pci:v000015B3d0000CAF1* ID_MODEL_FROM_DATABASE=ConnectX-4 CAPI Function pci:v000015B3d0000CB84* ID_MODEL_FROM_DATABASE=MT52100 pci:v000015B4* ID_VENDOR_FROM_DATABASE=CCI/TRIAD pci:v000015B5* ID_VENDOR_FROM_DATABASE=Cimetrics Inc pci:v000015B6* ID_VENDOR_FROM_DATABASE=Texas Memory Systems Inc pci:v000015B6d00000001* ID_MODEL_FROM_DATABASE=XP15 DSP Accelerator pci:v000015B6d00000002* ID_MODEL_FROM_DATABASE=XP30 DSP Accelerator pci:v000015B6d00000003* ID_MODEL_FROM_DATABASE=XP00 Data Acquisition Device pci:v000015B6d00000004* ID_MODEL_FROM_DATABASE=XP35 DSP Accelerator pci:v000015B6d00000007* ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-T0] pci:v000015B6d00000008* ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-T1] pci:v000015B6d00000009* ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-E0] pci:v000015B6d0000000A* ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-E1] pci:v000015B6d0000000E* ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-0] pci:v000015B6d0000000F* ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-1] pci:v000015B6d00000010* ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-P0] pci:v000015B6d00000011* ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-P1] pci:v000015B6d00000012* ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-P2] pci:v000015B6d00000013* ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-P3] pci:v000015B6d00000014* ID_MODEL_FROM_DATABASE=RamSan Flash SSD pci:v000015B6d00000015* ID_MODEL_FROM_DATABASE=ZBox pci:v000015B7* ID_VENDOR_FROM_DATABASE=Sandisk Corp pci:v000015B8* ID_VENDOR_FROM_DATABASE=ADDI-DATA GmbH pci:v000015B8d00001001* ID_MODEL_FROM_DATABASE=APCI1516 SP controller (16 digi outputs) pci:v000015B8d00001003* ID_MODEL_FROM_DATABASE=APCI1032 SP controller (32 digi inputs w/ opto coupler) pci:v000015B8d00001004* ID_MODEL_FROM_DATABASE=APCI2032 SP controller (32 digi outputs) pci:v000015B8d00001005* ID_MODEL_FROM_DATABASE=APCI2200 SP controller (8/16 digi outputs (relay)) pci:v000015B8d00001006* ID_MODEL_FROM_DATABASE=APCI1564 SP controller (32 digi ins, 32 digi outs) pci:v000015B8d0000100A* ID_MODEL_FROM_DATABASE=APCI1696 SP controller (96 TTL I/Os) pci:v000015B8d00003001* ID_MODEL_FROM_DATABASE=APCI3501 SP controller (analog output board) pci:v000015B8d0000300F* ID_MODEL_FROM_DATABASE=APCI3600 Noise and vibration measurement board pci:v000015B8d00007001* ID_MODEL_FROM_DATABASE=APCI7420 2-port Serial Controller pci:v000015B8d00007002* ID_MODEL_FROM_DATABASE=APCI7300 Serial Controller pci:v000015B9* ID_VENDOR_FROM_DATABASE=Maestro Digital Communications pci:v000015BA* ID_VENDOR_FROM_DATABASE=Impacct Technology Corp pci:v000015BB* ID_VENDOR_FROM_DATABASE=Portwell Inc pci:v000015BC* ID_VENDOR_FROM_DATABASE=Agilent Technologies pci:v000015BCd00000100* ID_MODEL_FROM_DATABASE=HPFC-5600 Tachyon DX2+ FC pci:v000015BCd00000103* ID_MODEL_FROM_DATABASE=QX4 PCI Express quad 4-gigabit Fibre Channel controller pci:v000015BCd00000105* ID_MODEL_FROM_DATABASE=Celerity FC-44XS/FC-42XS/FC-41XS/FC-44ES/FC-42ES/FC-41ES pci:v000015BCd00000105sv0000117Csd00000022* ID_MODEL_FROM_DATABASE=Celerity FC-44XS/FC-42XS/FC-41XS/FC-44ES/FC-42ES/FC-41ES (Celerity FC-42XS Fibre Channel Adapter) pci:v000015BCd00000105sv0000117Csd00000025* ID_MODEL_FROM_DATABASE=Celerity FC-44XS/FC-42XS/FC-41XS/FC-44ES/FC-42ES/FC-41ES (Celerity FC-44ES Fibre Channel Adapter) pci:v000015BCd00000105sv0000117Csd00000026* ID_MODEL_FROM_DATABASE=Celerity FC-44XS/FC-42XS/FC-41XS/FC-44ES/FC-42ES/FC-41ES (Celerity FC-42ES Fibre Channel Adapter) pci:v000015BCd00001100* ID_MODEL_FROM_DATABASE=E8001-66442 PCI Express CIC pci:v000015BCd00002922* ID_MODEL_FROM_DATABASE=64 Bit, 133MHz PCI-X Exerciser & Protocol Checker pci:v000015BCd00002928* ID_MODEL_FROM_DATABASE=64 Bit, 66MHz PCI Exerciser & Analyzer pci:v000015BCd00002929* ID_MODEL_FROM_DATABASE=64 Bit, 133MHz PCI-X Analyzer & Exerciser pci:v000015BD* ID_VENDOR_FROM_DATABASE=DFI Inc pci:v000015BE* ID_VENDOR_FROM_DATABASE=Sola Electronics pci:v000015BF* ID_VENDOR_FROM_DATABASE=High Tech Computer Corp (HTC) pci:v000015C0* ID_VENDOR_FROM_DATABASE=BVM Ltd pci:v000015C1* ID_VENDOR_FROM_DATABASE=Quantel pci:v000015C2* ID_VENDOR_FROM_DATABASE=Newer Technology Inc pci:v000015C3* ID_VENDOR_FROM_DATABASE=Taiwan Mycomp Co Ltd pci:v000015C4* ID_VENDOR_FROM_DATABASE=EVSX Inc pci:v000015C5* ID_VENDOR_FROM_DATABASE=Procomp Informatics Ltd pci:v000015C5d00008010* ID_MODEL_FROM_DATABASE=1394b - 1394 Firewire 3-Port Host Adapter Card pci:v000015C6* ID_VENDOR_FROM_DATABASE=Technical University of Budapest pci:v000015C7* ID_VENDOR_FROM_DATABASE=Tateyama System Laboratory Co Ltd pci:v000015C7d00000349* ID_MODEL_FROM_DATABASE=Tateyama C-PCI PLC/NC card Rev.01A pci:v000015C8* ID_VENDOR_FROM_DATABASE=Penta Media Co Ltd pci:v000015C9* ID_VENDOR_FROM_DATABASE=Serome Technology Inc pci:v000015CA* ID_VENDOR_FROM_DATABASE=Bitboys OY pci:v000015CB* ID_VENDOR_FROM_DATABASE=AG Electronics Ltd pci:v000015CC* ID_VENDOR_FROM_DATABASE=Hotrail Inc pci:v000015CD* ID_VENDOR_FROM_DATABASE=Dreamtech Co Ltd pci:v000015CE* ID_VENDOR_FROM_DATABASE=Genrad Inc pci:v000015CF* ID_VENDOR_FROM_DATABASE=Hilscher GmbH pci:v000015CFd00000000* ID_MODEL_FROM_DATABASE=CIFX 50E-DP(M/S) pci:v000015D1* ID_VENDOR_FROM_DATABASE=Infineon Technologies AG pci:v000015D2* ID_VENDOR_FROM_DATABASE=FIC (First International Computer Inc) pci:v000015D3* ID_VENDOR_FROM_DATABASE=NDS Technologies Israel Ltd pci:v000015D4* ID_VENDOR_FROM_DATABASE=Iwill Corp pci:v000015D5* ID_VENDOR_FROM_DATABASE=Tatung Co pci:v000015D6* ID_VENDOR_FROM_DATABASE=Entridia Corp pci:v000015D7* ID_VENDOR_FROM_DATABASE=Rockwell-Collins Inc pci:v000015D8* ID_VENDOR_FROM_DATABASE=Cybernetics Technology Co Ltd pci:v000015D9* ID_VENDOR_FROM_DATABASE=Super Micro Computer Inc pci:v000015DA* ID_VENDOR_FROM_DATABASE=Cyberfirm Inc pci:v000015DB* ID_VENDOR_FROM_DATABASE=Applied Computing Systems Inc pci:v000015DC* ID_VENDOR_FROM_DATABASE=Litronic Inc pci:v000015DCd00000001* ID_MODEL_FROM_DATABASE=Argus 300 PCI Cryptography Module pci:v000015DD* ID_VENDOR_FROM_DATABASE=Sigmatel Inc pci:v000015DE* ID_VENDOR_FROM_DATABASE=Malleable Technologies Inc pci:v000015DF* ID_VENDOR_FROM_DATABASE=Infinilink Corp pci:v000015E0* ID_VENDOR_FROM_DATABASE=Cacheflow Inc pci:v000015E1* ID_VENDOR_FROM_DATABASE=Voice Technologies Group Inc pci:v000015E2* ID_VENDOR_FROM_DATABASE=Quicknet Technologies Inc pci:v000015E2d00000500* ID_MODEL_FROM_DATABASE=PhoneJack-PCI pci:v000015E3* ID_VENDOR_FROM_DATABASE=Networth Technologies Inc pci:v000015E4* ID_VENDOR_FROM_DATABASE=VSN Systemen BV pci:v000015E5* ID_VENDOR_FROM_DATABASE=Valley technologies Inc pci:v000015E6* ID_VENDOR_FROM_DATABASE=Agere Inc pci:v000015E7* ID_VENDOR_FROM_DATABASE=Get Engineering Corp pci:v000015E8* ID_VENDOR_FROM_DATABASE=National Datacomm Corp pci:v000015E8d00000130* ID_MODEL_FROM_DATABASE=Wireless PCI Card pci:v000015E8d00000131* ID_MODEL_FROM_DATABASE=NCP130A2 Wireless NIC pci:v000015E9* ID_VENDOR_FROM_DATABASE=Pacific Digital Corp pci:v000015E9d00001841* ID_MODEL_FROM_DATABASE=ADMA-100 DiscStaQ ATA Controller pci:v000015EA* ID_VENDOR_FROM_DATABASE=Tokyo Denshi Sekei K.K. pci:v000015EB* ID_VENDOR_FROM_DATABASE=DResearch Digital Media Systems GmbH pci:v000015EC* ID_VENDOR_FROM_DATABASE=Beckhoff GmbH pci:v000015ECd00003101* ID_MODEL_FROM_DATABASE=FC3101 Profibus DP 1 Channel PCI pci:v000015ECd00005102* ID_MODEL_FROM_DATABASE=FC5102 pci:v000015ED* ID_VENDOR_FROM_DATABASE=Macrolink Inc pci:v000015EE* ID_VENDOR_FROM_DATABASE=In Win Development Inc pci:v000015EF* ID_VENDOR_FROM_DATABASE=Intelligent Paradigm Inc pci:v000015F0* ID_VENDOR_FROM_DATABASE=B-Tree Systems Inc pci:v000015F1* ID_VENDOR_FROM_DATABASE=Times N Systems Inc pci:v000015F2* ID_VENDOR_FROM_DATABASE=Diagnostic Instruments Inc pci:v000015F3* ID_VENDOR_FROM_DATABASE=Digitmedia Corp pci:v000015F4* ID_VENDOR_FROM_DATABASE=Valuesoft pci:v000015F5* ID_VENDOR_FROM_DATABASE=Power Micro Research pci:v000015F6* ID_VENDOR_FROM_DATABASE=Extreme Packet Device Inc pci:v000015F7* ID_VENDOR_FROM_DATABASE=Banctec pci:v000015F8* ID_VENDOR_FROM_DATABASE=Koga Electronics Co pci:v000015F9* ID_VENDOR_FROM_DATABASE=Zenith Electronics Corp pci:v000015FA* ID_VENDOR_FROM_DATABASE=J.P. Axzam Corp pci:v000015FB* ID_VENDOR_FROM_DATABASE=Zilog Inc pci:v000015FC* ID_VENDOR_FROM_DATABASE=Techsan Electronics Co Ltd pci:v000015FD* ID_VENDOR_FROM_DATABASE=N-CUBED.NET pci:v000015FE* ID_VENDOR_FROM_DATABASE=Kinpo Electronics Inc pci:v000015FF* ID_VENDOR_FROM_DATABASE=Fastpoint Technologies Inc pci:v00001600* ID_VENDOR_FROM_DATABASE=Northrop Grumman - Canada Ltd pci:v00001601* ID_VENDOR_FROM_DATABASE=Tenta Technology pci:v00001602* ID_VENDOR_FROM_DATABASE=Prosys-tec Inc pci:v00001603* ID_VENDOR_FROM_DATABASE=Nokia Wireless Communications pci:v00001604* ID_VENDOR_FROM_DATABASE=Central System Research Co Ltd pci:v00001605* ID_VENDOR_FROM_DATABASE=Pairgain Technologies pci:v00001606* ID_VENDOR_FROM_DATABASE=Europop AG pci:v00001607* ID_VENDOR_FROM_DATABASE=Lava Semiconductor Manufacturing Inc pci:v00001608* ID_VENDOR_FROM_DATABASE=Automated Wagering International pci:v00001609* ID_VENDOR_FROM_DATABASE=Scimetric Instruments Inc pci:v00001612* ID_VENDOR_FROM_DATABASE=Telesynergy Research Inc. pci:v00001618* ID_VENDOR_FROM_DATABASE=Stone Ridge Technology pci:v00001618d00000001* ID_MODEL_FROM_DATABASE=RDX 11 pci:v00001618d00000002* ID_MODEL_FROM_DATABASE=HFT-01 pci:v00001618d00000400* ID_MODEL_FROM_DATABASE=FarSync T2P (2 port X.21/V.35/V.24) pci:v00001618d00000440* ID_MODEL_FROM_DATABASE=FarSync T4P (4 port X.21/V.35/V.24) pci:v00001618d00000610* ID_MODEL_FROM_DATABASE=FarSync T1U (1 port X.21/V.35/V.24) pci:v00001618d00000620* ID_MODEL_FROM_DATABASE=FarSync T2U (2 port X.21/V.35/V.24) pci:v00001618d00000640* ID_MODEL_FROM_DATABASE=FarSync T4U (4 port X.21/V.35/V.24) pci:v00001618d00001610* ID_MODEL_FROM_DATABASE=FarSync TE1 (T1,E1) pci:v00001618d00002610* ID_MODEL_FROM_DATABASE=FarSync DSL-S1 (SHDSL) pci:v00001618d00003640* ID_MODEL_FROM_DATABASE=FarSync T4E (4-port X.21/V.35/V.24) pci:v00001618d00004620* ID_MODEL_FROM_DATABASE=FarSync T2Ue PCI Express (2-port X.21/V.35/V.24) pci:v00001618d00004640* ID_MODEL_FROM_DATABASE=FarSync T4Ue PCI Express (4-port X.21/V.35/V.24) pci:v00001619* ID_VENDOR_FROM_DATABASE=FarSite Communications Ltd pci:v00001619d00000400* ID_MODEL_FROM_DATABASE=FarSync T2P (2 port X.21/V.35/V.24) pci:v00001619d00000440* ID_MODEL_FROM_DATABASE=FarSync T4P (4 port X.21/V.35/V.24) pci:v00001619d00000610* ID_MODEL_FROM_DATABASE=FarSync T1U (1 port X.21/V.35/V.24) pci:v00001619d00000620* ID_MODEL_FROM_DATABASE=FarSync T2U (2 port X.21/V.35/V.24) pci:v00001619d00000640* ID_MODEL_FROM_DATABASE=FarSync T4U (4 port X.21/V.35/V.24) pci:v00001619d00001610* ID_MODEL_FROM_DATABASE=FarSync TE1 (T1,E1) pci:v00001619d00001612* ID_MODEL_FROM_DATABASE=FarSync TE1 PCI Express (T1,E1) pci:v00001619d00002610* ID_MODEL_FROM_DATABASE=FarSync DSL-S1 (SHDSL) pci:v00001619d00003640* ID_MODEL_FROM_DATABASE=FarSync T4E (4-port X.21/V.35/V.24) pci:v00001619d00004620* ID_MODEL_FROM_DATABASE=FarSync T2Ue PCI Express (2-port X.21/V.35/V.24) pci:v00001619d00004640* ID_MODEL_FROM_DATABASE=FarSync T4Ue PCI Express (4-port X.21/V.35/V.24) pci:v00001619d00005621* ID_MODEL_FROM_DATABASE=FarSync T2Ee PCI Express (2 port X.21/V.35/V.24) pci:v00001619d00005641* ID_MODEL_FROM_DATABASE=FarSync T4Ee PCI Express (4 port X.21/V.35/V.24) pci:v00001619d00006620* ID_MODEL_FROM_DATABASE=FarSync T2U-PMC PCI Express (2 port X.21/V.35/V.24) pci:v0000161F* ID_VENDOR_FROM_DATABASE=Rioworks pci:v00001626* ID_VENDOR_FROM_DATABASE=TDK Semiconductor Corp. pci:v00001626d00008410* ID_MODEL_FROM_DATABASE=RTL81xx Fast Ethernet pci:v00001629* ID_VENDOR_FROM_DATABASE=Kongsberg Spacetec AS pci:v00001629d00001003* ID_MODEL_FROM_DATABASE=Format synchronizer v3.0 pci:v00001629d00001006* ID_MODEL_FROM_DATABASE=Format synchronizer, model 10500 pci:v00001629d00001007* ID_MODEL_FROM_DATABASE=Format synchronizer, model 21000 pci:v00001629d00002002* ID_MODEL_FROM_DATABASE=Fast Universal Data Output pci:v00001631* ID_VENDOR_FROM_DATABASE=Packard Bell B.V. pci:v00001638* ID_VENDOR_FROM_DATABASE=Standard Microsystems Corp [SMC] pci:v00001638d00001100* ID_MODEL_FROM_DATABASE=SMC2602W EZConnect / Addtron AWA-100 / Eumitcom PCI WL11000 pci:v0000163C* ID_VENDOR_FROM_DATABASE=Smart Link Ltd. pci:v0000163Cd00003052* ID_MODEL_FROM_DATABASE=SmartLink SmartPCI562 56K Modem pci:v0000163Cd00005449* ID_MODEL_FROM_DATABASE=SmartPCI561 Modem pci:v00001641* ID_VENDOR_FROM_DATABASE=MKNet Corp. pci:v00001642* ID_VENDOR_FROM_DATABASE=Bitland(ShenZhen) Information Technology Co., Ltd. pci:v00001657* ID_VENDOR_FROM_DATABASE=Brocade Communications Systems, Inc. pci:v00001657d00000013* ID_MODEL_FROM_DATABASE=425/825/42B/82B 4Gbps/8Gbps PCIe dual port FC HBA pci:v00001657d00000013sv0000103Csd00001742* ID_MODEL_FROM_DATABASE=425/825/42B/82B 4Gbps/8Gbps PCIe dual port FC HBA (82B 8Gbps dual port FC HBA) pci:v00001657d00000013sv0000103Csd00001744* ID_MODEL_FROM_DATABASE=425/825/42B/82B 4Gbps/8Gbps PCIe dual port FC HBA (42B 4Gbps dual port FC HBA) pci:v00001657d00000013sv00001657sd00000014* ID_MODEL_FROM_DATABASE=425/825/42B/82B 4Gbps/8Gbps PCIe dual port FC HBA (425/825 4Gbps/8Gbps PCIe dual port FC HBA) pci:v00001657d00000014* ID_MODEL_FROM_DATABASE=1010/1020/1007/1741 10Gbps CNA pci:v00001657d00000014sv00001657sd00000014* ID_MODEL_FROM_DATABASE=1010/1020/1007/1741 10Gbps CNA (- FCOE) pci:v00001657d00000014sv00001657sd00000015* ID_MODEL_FROM_DATABASE=1010/1020/1007/1741 10Gbps CNA (- LL) pci:v00001657d00000017* ID_MODEL_FROM_DATABASE=415/815/41B/81B 4Gbps/8Gbps PCIe single port FC HBA pci:v00001657d00000017sv0000103Csd00001741* ID_MODEL_FROM_DATABASE=415/815/41B/81B 4Gbps/8Gbps PCIe single port FC HBA (41B 4Gbps single port FC HBA) pci:v00001657d00000017sv0000103Csd00001743* ID_MODEL_FROM_DATABASE=415/815/41B/81B 4Gbps/8Gbps PCIe single port FC HBA (81B 8Gbps single port FC HBA) pci:v00001657d00000017sv00001657sd00000014* ID_MODEL_FROM_DATABASE=415/815/41B/81B 4Gbps/8Gbps PCIe single port FC HBA (415/815 4Gbps/8Gbps single port PCIe FC HBA) pci:v00001657d00000021* ID_MODEL_FROM_DATABASE=804 8Gbps FC HBA for HP Bladesystem c-class pci:v00001657d00000022* ID_MODEL_FROM_DATABASE=1860 16Gbps/10Gbps Fabric Adapter pci:v00001657d00000022sv00001657sd00000022* ID_MODEL_FROM_DATABASE=1860 16Gbps/10Gbps Fabric Adapter (10Gbps CNA - FCOE) pci:v00001657d00000022sv00001657sd00000023* ID_MODEL_FROM_DATABASE=1860 16Gbps/10Gbps Fabric Adapter (10Gbps CNA - LL) pci:v00001657d00000022sv00001657sd00000024* ID_MODEL_FROM_DATABASE=1860 16Gbps/10Gbps Fabric Adapter (16Gbps FC HBA) pci:v00001657d00000023* ID_MODEL_FROM_DATABASE=1867/1869 16Gbps FC HBA pci:v00001657d00000646* ID_MODEL_FROM_DATABASE=400 4Gbps PCIe FC HBA pci:v0000165A* ID_VENDOR_FROM_DATABASE=Epix Inc pci:v0000165Ad0000C100* ID_MODEL_FROM_DATABASE=PIXCI(R) CL1 Camera Link Video Capture Board [custom QL5232] pci:v0000165Ad0000D200* ID_MODEL_FROM_DATABASE=PIXCI(R) D2X Digital Video Capture Board [custom QL5232] pci:v0000165Ad0000D300* ID_MODEL_FROM_DATABASE=PIXCI(R) D3X Digital Video Capture Board [custom QL5232] pci:v0000165Ad0000EB01* ID_MODEL_FROM_DATABASE=PIXCI(R) EB1 PCI Camera Link Video Capture Board pci:v0000165C* ID_VENDOR_FROM_DATABASE=Gidel Ltd. pci:v0000165Cd00005361* ID_MODEL_FROM_DATABASE=PROCStarII60-1 pci:v0000165Cd00005362* ID_MODEL_FROM_DATABASE=PROCStarII60-2 pci:v0000165Cd00005364* ID_MODEL_FROM_DATABASE=PROCStarII60-4 pci:v0000165Cd00005435* ID_MODEL_FROM_DATABASE=ProcSparkII pci:v0000165Cd00005661* ID_MODEL_FROM_DATABASE=ProcE60 pci:v0000165Cd000056E1* ID_MODEL_FROM_DATABASE=ProcE180 pci:v0000165Cd00005911* ID_MODEL_FROM_DATABASE=ProcStarIII110-1 pci:v0000165Cd00005912* ID_MODEL_FROM_DATABASE=ProcStarIII110-2 pci:v0000165Cd00005913* ID_MODEL_FROM_DATABASE=ProcStarIII110-3 pci:v0000165Cd00005914* ID_MODEL_FROM_DATABASE=ProcStarIII110-4 pci:v0000165Cd00005921* ID_MODEL_FROM_DATABASE=ProcStarIII150-1 pci:v0000165Cd00005922* ID_MODEL_FROM_DATABASE=ProcStarIII150-2 pci:v0000165Cd00005923* ID_MODEL_FROM_DATABASE=ProcStarIII150-3 pci:v0000165Cd00005924* ID_MODEL_FROM_DATABASE=ProcStarIII150-4 pci:v0000165Cd00005931* ID_MODEL_FROM_DATABASE=ProcStarIII260-1 pci:v0000165Cd00005932* ID_MODEL_FROM_DATABASE=ProcStarIII260-2 pci:v0000165Cd00005933* ID_MODEL_FROM_DATABASE=ProcStarIII260-3 pci:v0000165Cd00005934* ID_MODEL_FROM_DATABASE=ProcStarIII260-4 pci:v0000165Cd00005941* ID_MODEL_FROM_DATABASE=ProcStarIII340-1 pci:v0000165Cd00005942* ID_MODEL_FROM_DATABASE=ProcStarIII340-2 pci:v0000165Cd00005943* ID_MODEL_FROM_DATABASE=ProcStarIII340-3 pci:v0000165Cd00005944* ID_MODEL_FROM_DATABASE=ProcStarIII340-4 pci:v0000165Cd00005A01* ID_MODEL_FROM_DATABASE=ProceIII80 pci:v0000165Cd00005A11* ID_MODEL_FROM_DATABASE=ProceIII110 pci:v0000165Cd00005A21* ID_MODEL_FROM_DATABASE=ProceIII150 pci:v0000165Cd00005A31* ID_MODEL_FROM_DATABASE=ProceIII260 pci:v0000165Cd00005A41* ID_MODEL_FROM_DATABASE=ProceIII340 pci:v0000165Cd00005B51* ID_MODEL_FROM_DATABASE=ProceIV360 pci:v0000165Cd00005B61* ID_MODEL_FROM_DATABASE=ProceIV530 pci:v0000165Cd00005B71* ID_MODEL_FROM_DATABASE=ProceIV820 pci:v0000165Cd00005C01* ID_MODEL_FROM_DATABASE=ProcStarIV80-1 pci:v0000165Cd00005C02* ID_MODEL_FROM_DATABASE=ProcStarIV80-2 pci:v0000165Cd00005C03* ID_MODEL_FROM_DATABASE=ProcStarIV80-3 pci:v0000165Cd00005C04* ID_MODEL_FROM_DATABASE=ProcStarIV80-4 pci:v0000165Cd00005C11* ID_MODEL_FROM_DATABASE=ProcStarIV110-1 pci:v0000165Cd00005C12* ID_MODEL_FROM_DATABASE=ProcStarIV110-2 pci:v0000165Cd00005C13* ID_MODEL_FROM_DATABASE=ProcStarIV110-3 pci:v0000165Cd00005C14* ID_MODEL_FROM_DATABASE=ProcStarIV110-4 pci:v0000165Cd00005C51* ID_MODEL_FROM_DATABASE=ProcStarIV360-1 pci:v0000165Cd00005C52* ID_MODEL_FROM_DATABASE=ProcStarIV360-2 pci:v0000165Cd00005C53* ID_MODEL_FROM_DATABASE=ProcStarIV360-3 pci:v0000165Cd00005C54* ID_MODEL_FROM_DATABASE=ProcStarIV360-4 pci:v0000165Cd00005C61* ID_MODEL_FROM_DATABASE=ProcStarIV530-1 pci:v0000165Cd00005C62* ID_MODEL_FROM_DATABASE=ProcStarIV530-2 pci:v0000165Cd00005C63* ID_MODEL_FROM_DATABASE=ProcStarIV530-3 pci:v0000165Cd00005C64* ID_MODEL_FROM_DATABASE=ProcStarIV530-4 pci:v0000165Cd00005C71* ID_MODEL_FROM_DATABASE=ProcStarIV820-1 pci:v0000165Cd00005C72* ID_MODEL_FROM_DATABASE=ProcStarIV820-2 pci:v0000165Cd00005C73* ID_MODEL_FROM_DATABASE=ProcStarIV820-3 pci:v0000165Cd00005C74* ID_MODEL_FROM_DATABASE=ProcStarIV820-4 pci:v0000165Cd00005D01* ID_MODEL_FROM_DATABASE=Proc10480 pci:v0000165Cd00005D11* ID_MODEL_FROM_DATABASE=Proc104110 pci:v0000165Cd00005F01* ID_MODEL_FROM_DATABASE=ProceV_A3 pci:v0000165Cd00005F11* ID_MODEL_FROM_DATABASE=ProceV_A7 pci:v0000165Cd00005F21* ID_MODEL_FROM_DATABASE=ProceV_AB pci:v0000165Cd00005F31* ID_MODEL_FROM_DATABASE=ProceV_D5 pci:v0000165Cd00005F41* ID_MODEL_FROM_DATABASE=ProceV_D8 pci:v0000165Cd00006732* ID_MODEL_FROM_DATABASE=Proc6M pci:v0000165Cd00006832* ID_MODEL_FROM_DATABASE=Proc12M pci:v0000165Cd00007101* ID_MODEL_FROM_DATABASE=Proc10a_27 pci:v0000165Cd00007111* ID_MODEL_FROM_DATABASE=Proc10a_48 pci:v0000165Cd00007121* ID_MODEL_FROM_DATABASE=Proc10a_66 pci:v0000165Cd00007141* ID_MODEL_FROM_DATABASE=Proc10a_115 pci:v0000165Cd00007181* ID_MODEL_FROM_DATABASE=Proc10a_27S pci:v0000165Cd00007191* ID_MODEL_FROM_DATABASE=Proc10a_48S pci:v0000165Cd000071A1* ID_MODEL_FROM_DATABASE=Proc10a_66S pci:v0000165D* ID_VENDOR_FROM_DATABASE=Hsing Tech. Enterprise Co., Ltd. pci:v0000165F* ID_VENDOR_FROM_DATABASE=Linux Media Labs, LLC pci:v0000165Fd00001020* ID_MODEL_FROM_DATABASE=LMLM4 MPEG-4 encoder pci:v00001661* ID_VENDOR_FROM_DATABASE=Worldspace Corp. pci:v00001668* ID_VENDOR_FROM_DATABASE=Actiontec Electronics Inc pci:v00001668d00000100* ID_MODEL_FROM_DATABASE=Mini-PCI bridge pci:v0000166D* ID_VENDOR_FROM_DATABASE=Broadcom Corporation pci:v0000166Dd00000001* ID_MODEL_FROM_DATABASE=SiByte BCM1125/1125H/1250 System-on-a-Chip PCI pci:v0000166Dd00000002* ID_MODEL_FROM_DATABASE=SiByte BCM1125H/1250 System-on-a-Chip HyperTransport pci:v0000166Dd00000012* ID_MODEL_FROM_DATABASE=SiByte BCM1280/BCM1480 System-on-a-Chip PCI-X pci:v0000166Dd00000014* ID_MODEL_FROM_DATABASE=Sibyte BCM1280/BCM1480 System-on-a-Chip HyperTransport pci:v00001677* ID_VENDOR_FROM_DATABASE=Bernecker + Rainer pci:v00001677d0000104E* ID_MODEL_FROM_DATABASE=5LS172.6 B&R Dual CAN Interface Card pci:v00001677d000012D7* ID_MODEL_FROM_DATABASE=5LS172.61 B&R Dual CAN Interface Card pci:v00001677d000020AD* ID_MODEL_FROM_DATABASE=5ACPCI.MFIO-K01 Profibus DP / K-Feldbus / COM pci:v00001678* ID_VENDOR_FROM_DATABASE=NetEffect pci:v00001678d00000100* ID_MODEL_FROM_DATABASE=NE020 10Gb Accelerated Ethernet Adapter (iWARP RNIC) pci:v00001679* ID_VENDOR_FROM_DATABASE=Tokyo Electron Device Ltd. pci:v00001679d00003000* ID_MODEL_FROM_DATABASE=SD Standard host controller [Ellen] pci:v0000167B* ID_VENDOR_FROM_DATABASE=ZyDAS Technology Corp. pci:v0000167Bd00002102* ID_MODEL_FROM_DATABASE=ZyDAS ZD1202 pci:v0000167Bd00002102sv0000187Esd00003406* ID_MODEL_FROM_DATABASE=ZyDAS ZD1202 (ZyAIR B-122 CardBus 11Mbs Wireless LAN Card) pci:v0000167Bd00002102sv0000187Esd00003407* ID_MODEL_FROM_DATABASE=ZyDAS ZD1202 (ZyAIR B-320 802.11b Wireless PCI Adapter) pci:v0000167Bd00002116* ID_MODEL_FROM_DATABASE=ZD1212B Wireless Adapter pci:v0000167D* ID_VENDOR_FROM_DATABASE=Samsung Electro-Mechanics Co., Ltd. pci:v0000167Dd0000A000* ID_MODEL_FROM_DATABASE=MagicLAN SWL-2210P 802.11b [Intersil ISL3874] pci:v0000167E* ID_VENDOR_FROM_DATABASE=ONNTO Corp. pci:v00001681* ID_VENDOR_FROM_DATABASE=Hercules pci:v00001682* ID_VENDOR_FROM_DATABASE=XFX Pine Group Inc. pci:v00001688* ID_VENDOR_FROM_DATABASE=CastleNet Technology Inc. pci:v00001688d00001170* ID_MODEL_FROM_DATABASE=WLAN 802.11b card pci:v0000168C* ID_VENDOR_FROM_DATABASE=Qualcomm Atheros pci:v0000168Cd00000007* ID_MODEL_FROM_DATABASE=AR5210 Wireless Network Adapter [AR5000 802.11a] pci:v0000168Cd00000007sv00001737sd00000007* ID_MODEL_FROM_DATABASE=AR5210 Wireless Network Adapter [AR5000 802.11a] (WPC54A Wireless PC Card) pci:v0000168Cd00000007sv00001B47sd00000100* ID_MODEL_FROM_DATABASE=AR5210 Wireless Network Adapter [AR5000 802.11a] (Harmony 8450CN Wireless CardBus Module) pci:v0000168Cd00000007sv00001B47sd00000110* ID_MODEL_FROM_DATABASE=AR5210 Wireless Network Adapter [AR5000 802.11a] (Skyline 4030 / Harmony 8450 802.11a Wireless CardBus Adapter) pci:v0000168Cd00000007sv00008086sd00002501* ID_MODEL_FROM_DATABASE=AR5210 Wireless Network Adapter [AR5000 802.11a] (PRO/Wireless 5000 LAN PCI Adapter Module) pci:v0000168Cd00000011* ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001A 802.11a] pci:v0000168Cd00000012* ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] pci:v0000168Cd00000012sv00001186sd00003A03* ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] (AirPro DWL-A650 Wireless Cardbus Adapter (rev.B)) pci:v0000168Cd00000012sv00001186sd00003A04* ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] (AirPro DWL-AB650 Multimode Wireless Cardbus Adapter) pci:v0000168Cd00000012sv00001186sd00003A05* ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] (AirPro DWL-AB520 Multimode Wireless PCI Adapter) pci:v0000168Cd00000012sv0000126Csd00008031* ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] (2201 Mobile Adapter) pci:v0000168Cd00000012sv00001385sd00004400* ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] (WAB501 802.11ab Wireless CardBus Card) pci:v0000168Cd00000012sv00001B47sd0000AA00* ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] (8460 802.11ab Wireless CardBus Adapter) pci:v0000168Cd00000013* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter pci:v0000168Cd00000013sv00000308sd00003402* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AG-100 802.11ag Wireless Cardbus Adapter) pci:v0000168Cd00000013sv00000308sd00003405* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (G-102 v2 802.11g Wireless Cardbus Adapter) pci:v0000168Cd00000013sv00000308sd00003408* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (G-170S 802.11g Wireless CardBus Adapter) pci:v0000168Cd00000013sv00000E11sd000000E5* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (NC6000/NC8000 laptop) pci:v0000168Cd00000013sv000010B7sd00006002* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (3CRWE154A72 802.11abg Cardbus Adapter) pci:v0000168Cd00000013sv00001113sd0000D301* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Philips CPWNA100 Wireless CardBus adapter) pci:v0000168Cd00000013sv00001113sd0000EE23* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (SMCWPCIT-G 108Mbps Wireless PCI adapter) pci:v0000168Cd00000013sv00001154sd0000033B* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Buffalo WLI-CB-AMG54) pci:v0000168Cd00000013sv00001154sd0000034E* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Buffalo WLI-CB-AG108HP 802.11abg Cardbus Adapter) pci:v0000168Cd00000013sv00001186sd00003202* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (DWL-G650 (Rev B3,B5) Wireless cardbus adapter) pci:v0000168Cd00000013sv00001186sd00003203* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AirPlus DWL-G520 Wireless PCI Adapter (rev. A)) pci:v0000168Cd00000013sv00001186sd00003A07* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AirXpert DWL-AG650 Wireless Cardbus Adapter) pci:v0000168Cd00000013sv00001186sd00003A08* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AirXpert DWL-AG520 Wireless PCI Adapter) pci:v0000168Cd00000013sv00001186sd00003A12* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (D-Link AirPlus DWL-G650 Wireless Cardbus Adapter(rev.C)) pci:v0000168Cd00000013sv00001186sd00003A13* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AirPlus DWL-G520 Wireless PCI Adapter (rev. B)) pci:v0000168Cd00000013sv00001186sd00003A14* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AirPremier AG DWL-AG530 Wireless PCI Adapter (rev.A)) pci:v0000168Cd00000013sv00001186sd00003A17* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (D-Link AirPremier DWL-G680 Wireless Cardbus Adapter) pci:v0000168Cd00000013sv00001186sd00003A18* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (D-Link AirPremier DWL-G550 Wireless PCI Adapter) pci:v0000168Cd00000013sv00001186sd00003A1A* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WNA-2330 802.11bg Wireless CardBus Adapter) pci:v0000168Cd00000013sv00001186sd00003A63* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (D-Link AirPremier DWL-AG660 Wireless Cardbus Adapter) pci:v0000168Cd00000013sv00001186sd00003A93* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Conceptronic C54I Wireless 801.11g PCI card) pci:v0000168Cd00000013sv00001186sd00003A94* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Conceptronic C54C 802.11g Wireless Cardbus Adapter) pci:v0000168Cd00000013sv00001186sd00003AB0* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Allnet ALL0281 Wireless PCI Card) pci:v0000168Cd00000013sv00001385sd00004600* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WAG511 802.11a/b/g Dual Band Wireless PC Card) pci:v0000168Cd00000013sv00001385sd00004610* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WAG511 802.11a/b/g Dual Band Wireless PC Card) pci:v0000168Cd00000013sv00001385sd00004900* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WG311v1 802.11g Wireless PCI Adapter) pci:v0000168Cd00000013sv00001385sd00004A00* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WAG311 802.11a/g Wireless PCI Adapter) pci:v0000168Cd00000013sv00001385sd00004B00* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WG511T 108 Mbps Wireless PC Card (rev.A/B)) pci:v0000168Cd00000013sv00001385sd00004D00* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WG311T 108 Mbps Wireless PCI Adapter (rev.A2)) pci:v0000168Cd00000013sv00001385sd00004F00* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WG511U Double 108 Mbps Wireless PC Card) pci:v0000168Cd00000013sv00001385sd00005A00* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WG311T (rev.A3 v1h3/v1h4) 108 Mbps Wireless PCI Adapter [AR2412]) pci:v0000168Cd00000013sv00001385sd00005B00* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WG511T 108 Mbps Wireless PC Card (rev.C)) pci:v0000168Cd00000013sv00001385sd00005D00* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WPN511 RangeMax Wireless PC Card) pci:v0000168Cd00000013sv00001458sd0000E911* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (GN-WIAG02) pci:v0000168Cd00000013sv00001468sd00000403* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (U10H014 802.11g Cardbus Adapter) pci:v0000168Cd00000013sv00001468sd00000408* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (ThinkPad 11b/g Wireless LAN Mini PCI Adapter) pci:v0000168Cd00000013sv000014B7sd00000A10* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (8480-WD 802.11abg Cardbus Adapter) pci:v0000168Cd00000013sv000014B7sd00000A60* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (8482-WD ORiNOCO 11a/b/g Wireless PCI Adapter) pci:v0000168Cd00000013sv000014B7sd0000AA30* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (8800-FC 802.11bg Cardbus Adapter) pci:v0000168Cd00000013sv000014B7sd0000AA40* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (8470-WD 802.11bg Cardbus Adapter) pci:v0000168Cd00000013sv000014B9sd0000CB21* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (CB21 802.11a/b/g Cardbus Adapter) pci:v0000168Cd00000013sv00001668sd00001026* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (IBM HighRate 11 a/b/g Wireless CardBus Adapter) pci:v0000168Cd00000013sv0000168Csd00000013* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AirPlus XtremeG DWL-G650 Wireless PCMCIA Adapter) pci:v0000168Cd00000013sv0000168Csd00001025* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (DWL-G650B2 Wireless CardBus Adapter) pci:v0000168Cd00000013sv0000168Csd00001027* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Engenius NL-3054CB ARIES b/g CardBus Adapter) pci:v0000168Cd00000013sv0000168Csd00001042* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Ubiquiti Networks SuperRange a/b/g Cardbus Adapter) pci:v0000168Cd00000013sv0000168Csd00001051* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (EZ Connect g 802.11g 108Mbps Wireless PCI Adapter) pci:v0000168Cd00000013sv0000168Csd00002026* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Netgate 5354MP ARIES a(108Mb turbo)/b/g MiniPCI Adapter) pci:v0000168Cd00000013sv0000168Csd00002027* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (D-Link AirPlus DWL-G520 Wireless PCI Adapter (rev. A)) pci:v0000168Cd00000013sv0000168Csd00002041* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Engenius 5354MP Plus ARIES2 b/g MiniPCI Adapter) pci:v0000168Cd00000013sv0000168Csd00002042* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Engenius 5354MP Plus ARIES2 a/b/g MiniPCI Adapter) pci:v0000168Cd00000013sv0000168Csd00002051* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (TRENDnet TEW-443PI Wireless PCI Adapter) pci:v0000168Cd00000013sv000016A5sd0000160A* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (BWP712 802.11bg Wireless CardBus Adapter) pci:v0000168Cd00000013sv000016ABsd00007302* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Trust Speedshare Turbo Pro Wireless PCI Adapter) pci:v0000168Cd00000013sv00001737sd00000017* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WPC55AG) pci:v0000168Cd00000013sv00001737sd00000026* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WMP55AG v1.1) pci:v0000168Cd00000013sv00001737sd00000035* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WPC55AG v1.2 802.11abg Cardbus Adapter) pci:v0000168Cd00000013sv00001737sd00000036* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WMP55AG v1.2 802.11abg PCI Adapter) pci:v0000168Cd00000013sv00001799sd00003000* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (F6D3000 Dual-Band Wireless A+G Desktop Card) pci:v0000168Cd00000013sv00001799sd00003010* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (F6D3010 Dual-Band Wireless A+G Notebook Card) pci:v0000168Cd00000013sv000017CFsd00000042* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Z-COMAX Highpower XG-622H (400mw) 802.11b/g mini-PCI Adapter) pci:v0000168Cd00000013sv0000185Fsd00001012* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (CM9 Wireless a/b/g MiniPCI Adapter) pci:v0000168Cd00000013sv0000185Fsd00002012* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Wistron NeWeb WLAN a+b+g model CB9) pci:v0000168Cd00000013sv0000A727sd00006801* ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (3CRXJK10075 OfficeConnect Wireless 108Mbps 11g XJACK PC Card) pci:v0000168Cd0000001A* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] pci:v0000168Cd0000001Asv00001052sd0000168C* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (Sweex Wireless Lan PC Card 54Mbps) pci:v0000168Cd0000001Asv00001113sd0000EE20* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (SMC Wireless CardBus Adapter 802.11g (SMCWCB-G EU)) pci:v0000168Cd0000001Asv00001113sd0000EE24* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (SMC Wireless PCI Card WPCI-G) pci:v0000168Cd0000001Asv00001186sd00003A15* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.D1)) pci:v0000168Cd0000001Asv00001186sd00003A16* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (AirPlus G DWL-G510 Wireless PCI Adapter(rev.B)) pci:v0000168Cd0000001Asv00001186sd00003A1C* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (WNA-1330 Notebook Adapter) pci:v0000168Cd0000001Asv00001186sd00003A1D* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (WDA-1320 Desktop Adapter) pci:v0000168Cd0000001Asv00001186sd00003A23* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (AirPlus G DWL-G520+A Wireless PCI Adapter) pci:v0000168Cd0000001Asv00001186sd00003A24* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (AirPlus G DWL-G650+A Wireless Cardbus Adapter) pci:v0000168Cd0000001Asv00001186sd00003B08* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.C1)) pci:v0000168Cd0000001Asv0000168Csd0000001A* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (Belkin FD7000) pci:v0000168Cd0000001Asv0000168Csd00001052* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (TP-Link TL-WN510G Wireless CardBus Adapter) pci:v0000168Cd0000001Asv0000168Csd00002052* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (Compex Wireless 802.11 b/g MiniPCI Adapter, Rev A1 [WLM54G]) pci:v0000168Cd0000001Asv000016ECsd00000122* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (Wireless PCI Adapter Model 5418) pci:v0000168Cd0000001Asv00001737sd00000053* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (WPC54G v7 802.11g Wireless-G Notebook Adapter) pci:v0000168Cd0000001Asv00001799sd0000700C* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (F5D7000 v5000 Wireless G Desktop Card) pci:v0000168Cd0000001Asv00001799sd0000701D* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (F5D7010 v5000 Wireless G Notebook Card) pci:v0000168Cd0000001Asv000017F9sd00000008* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (DX-WGNBC 802.11bg Wireless CardBus Adapter) pci:v0000168Cd0000001Asv000017F9sd00000018* ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (DX-WGDTC 802.11bg Wireless PCI Adapter) pci:v0000168Cd0000001B* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] pci:v0000168Cd0000001Bsv00000777sd00001107* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (UB5 802.11a Wireless Mini PCI Adapter) pci:v0000168Cd0000001Bsv00000777sd00003002* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (XR2 802.11g Wireless Mini PCI Adapter) pci:v0000168Cd0000001Bsv00000777sd00003005* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (XR5 802.11a Wireless Mini PCI Adapter) pci:v0000168Cd0000001Bsv00000777sd00003009* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (XR9 900MHz Wireless Mini PCI Adapter) pci:v0000168Cd0000001Bsv00001154sd0000034E* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (WLI-CB-AG108HP 802.11abg Wireless CardBus Adapter) pci:v0000168Cd0000001Bsv00001186sd00003A19* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (D-Link AirPremier AG DWL-AG660 Wireless Cardbus Adapter) pci:v0000168Cd0000001Bsv00001186sd00003A22* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (AirPremier AG DWL-AG530 Wireless PCI Adapter (rev.B)) pci:v0000168Cd0000001Bsv000011ADsd00005001* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (WN5301A 802.11bg Wireless PCI Adapter) pci:v0000168Cd0000001Bsv00001458sd0000E901* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (GN-WI01HT Wireless a/b/g MiniPCI Adapter) pci:v0000168Cd0000001Bsv0000168Csd0000001B* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (Wireless LAN PCI LiteOn) pci:v0000168Cd0000001Bsv0000168Csd00001062* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (IPN-W100CB 802.11abg Wireless CardBus Adapter) pci:v0000168Cd0000001Bsv0000168Csd00002062* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (EnGenius EMP-8602 (400mw) or Compex WLM54AG (SuperAG)) pci:v0000168Cd0000001Bsv0000168Csd00002063* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (EnGenius EMP-8602 (400mw) or Compex WLM54AG) pci:v0000168Cd0000001Bsv000017F9sd0000000B* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (WL-711A 802.11abg Wireless CardBus Adapter) pci:v0000168Cd0000001Bsv000017F9sd0000000C* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (WPIA-112AG 802.11abg Wireless PCI Adapter) pci:v0000168Cd0000001Bsv000017F9sd0000000D* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (PC-686X 802.11abg Wireless Mini PCI Adapter) pci:v0000168Cd0000001Bsv0000185Fsd00001600* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (DCMA-82 High Power WLAN 802.11a/b/g mini-PCI Module (Super A/G, eXtended Range, 400mW)) pci:v0000168Cd0000001Bsv00001948sd00003ABA* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (RBTBJ-AW 802.11abg Wireless Cardbus Adapter) pci:v0000168Cd0000001Bsv0000A727sd00006804* ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (Wireless 11a/b/g PC Card with XJACK(r) Antenna) pci:v0000168Cd0000001C* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) pci:v0000168Cd0000001Csv00000777sd00003006* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (SRX 802.11abg Wireless ExpressCard Adapter) pci:v0000168Cd0000001Csv0000103Csd0000137A* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5BXB63 (Foxconn) 802.11bg Mini PCIe NIC) pci:v0000168Cd0000001Csv0000106Bsd00000086* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AirPort Extreme) pci:v0000168Cd0000001Csv0000144Fsd00007106* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (WLL3140 (Toshiba PA3501U-1MPC) 802.11bg Wireless Mini PCIe Card) pci:v0000168Cd0000001Csv0000144Fsd00007128* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (WLL3141 (Toshiba PA3613U-1MPC) 802.11bg Wireless Mini PCIe Card) pci:v0000168Cd0000001Csv00001468sd00000428* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5BXB63 802.11bg NIC) pci:v0000168Cd0000001Csv00001468sd0000042A* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5007EG 802.11bg NIC) pci:v0000168Cd0000001Csv0000147Bsd00001033* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AirPace Wi-Fi) pci:v0000168Cd0000001Csv0000168Csd0000001C* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR242x 802.11abg NIC (PCI Express)) pci:v0000168Cd0000001Csv0000168Csd00003061* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5006EGS 802.11bg NIC (2.4GHz, PCI Express)) pci:v0000168Cd0000001Csv0000168Csd00003062* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5006EXS 802.11abg NIC (2.4/5.0GHz, PCI Express)) pci:v0000168Cd0000001Csv0000168Csd00003063* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5006EX 802.11abg NIC (2.4/5.0GHz, PCI Express)) pci:v0000168Cd0000001Csv0000168Csd00003065* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5006EG 802.11bg NIC (2.4GHz, PCI Express)) pci:v0000168Cd0000001Csv0000168Csd00003067* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR242x 802.11abg Wireless PCI Express Adapter (rev 01)) pci:v0000168Cd0000001Csv00001A3Bsd00001026* ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AW-GE780 802.11bg Wireless Mini PCIe Card) pci:v0000168Cd0000001D* ID_MODEL_FROM_DATABASE=AR2417 Wireless Network Adapter [AR5007G 802.11bg] pci:v0000168Cd0000001Dsv00001799sd0000720B* ID_MODEL_FROM_DATABASE=AR2417 Wireless Network Adapter [AR5007G 802.11bg] (F5D7000 v8000 Wireless G Desktop Card) pci:v0000168Cd0000001Dsv00001799sd0000721B* ID_MODEL_FROM_DATABASE=AR2417 Wireless Network Adapter [AR5007G 802.11bg] (F5D7010 v8000 Wireless G Notebook Card) pci:v0000168Cd00000020* ID_MODEL_FROM_DATABASE=AR5513 802.11abg Wireless NIC pci:v0000168Cd00000020sv00000308sd00003407* ID_MODEL_FROM_DATABASE=AR5513 802.11abg Wireless NIC (M-102 802.11g Wireless Cardbus Adapter) pci:v0000168Cd00000020sv00001186sd00003A67* ID_MODEL_FROM_DATABASE=AR5513 802.11abg Wireless NIC (DWL-G650M Super G MIMO Wireless Notebook Adapter) pci:v0000168Cd00000020sv00001186sd00003A68* ID_MODEL_FROM_DATABASE=AR5513 802.11abg Wireless NIC (DWL-G520M Wireless 108G MIMO Desktop Adapter) pci:v0000168Cd00000020sv0000187Esd0000340E* ID_MODEL_FROM_DATABASE=AR5513 802.11abg Wireless NIC (M-302 802.11g Wireless PCI Adapter) pci:v0000168Cd00000020sv00001976sd00002003* ID_MODEL_FROM_DATABASE=AR5513 802.11abg Wireless NIC (TEW-601PC 802.11g Wireless CardBus Adapter) pci:v0000168Cd00000023* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] pci:v0000168Cd00000023sv00000308sd0000340B* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (NWD-170N 802.11bgn Wireless CardBus Adapter) pci:v0000168Cd00000023sv00001154sd00000365* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (Buffalo WLP-CB-AG300 802.11abgn Cardbus Adapter) pci:v0000168Cd00000023sv00001154sd00000367* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (WLI-CB-AG301N 802.11abgn Wireless CardBus Adapter) pci:v0000168Cd00000023sv00001186sd00003A6A* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (DWA-642 802.11n RangeBooster N CardBus Adapter) pci:v0000168Cd00000023sv00001186sd00003A6B* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (DWA-547 802.11n RangeBooster N 650 DeskTop Adapter) pci:v0000168Cd00000023sv00001186sd00003A6D* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (DWA-552 802.11n Xtreme N Desktop Adapter (rev A1)) pci:v0000168Cd00000023sv00001186sd00003A76* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (DWA-645 802.11n RangeBooster N 650 Notebook Adapter (rev A1)) pci:v0000168Cd00000023sv00001737sd00000059* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (WPC300N v2 Wireless-N Notebook Adapter) pci:v0000168Cd00000023sv00001737sd00000069* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (WPC100 v1 802.11n RangePlus Wireless Notebook Adapter) pci:v0000168Cd00000023sv00001737sd00000072* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (WMP110 v1 802.11n RangePlus Wireless PCI Adapter) pci:v0000168Cd00000023sv00001799sd00008011* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (F5D8011 v1 802.11n N1 Wireless Notebook Card) pci:v0000168Cd00000023sv0000187Esd00003411* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (NWD-370N 802.11n Wireless PCI Adapter) pci:v0000168Cd00000023sv00001976sd00002008* ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (TEW-621PC 802.11bgn Wireless CardBus Adapter) pci:v0000168Cd00000024* ID_MODEL_FROM_DATABASE=AR5418 Wireless Network Adapter [AR5008E 802.11(a)bgn] (PCI-Express) pci:v0000168Cd00000024sv0000106Bsd00000087* ID_MODEL_FROM_DATABASE=AR5418 Wireless Network Adapter [AR5008E 802.11(a)bgn] (PCI-Express) (AirPort Extreme) pci:v0000168Cd00000024sv00001186sd00003A70* ID_MODEL_FROM_DATABASE=AR5418 Wireless Network Adapter [AR5008E 802.11(a)bgn] (PCI-Express) (DWA-556 Xtreme N PCI Express Desktop Adapter) pci:v0000168Cd00000027* ID_MODEL_FROM_DATABASE=AR9160 Wireless Network Adapter [AR9001 802.11(a)bgn] pci:v0000168Cd00000027sv00000777sd00004082* ID_MODEL_FROM_DATABASE=AR9160 Wireless Network Adapter [AR9001 802.11(a)bgn] (SR71-A 802.11abgn Wireless Mini PCI Adapter) pci:v0000168Cd00000029* ID_MODEL_FROM_DATABASE=AR922X Wireless Network Adapter pci:v0000168Cd00000029sv00000777sd00004005* ID_MODEL_FROM_DATABASE=AR922X Wireless Network Adapter (SR71-15 802.11an Mini PCI Adapter) pci:v0000168Cd00000029sv00001186sd00003A7A* ID_MODEL_FROM_DATABASE=AR922X Wireless Network Adapter (DWA-552 802.11n Xtreme N Desktop Adapter (rev A2)) pci:v0000168Cd00000029sv00001186sd00003A7D* ID_MODEL_FROM_DATABASE=AR922X Wireless Network Adapter (DWA-552 802.11n Xtreme N Desktop Adapter (rev A3)) pci:v0000168Cd0000002A* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) pci:v0000168Cd0000002Asv00000777sd00004F05* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (SR71-X 802.11abgn Wireless ExpressCard Adapter [AR9280]) pci:v0000168Cd0000002Asv0000103Csd00003041* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (AR5BHB92-H 802.11abgn Wireless Half-size Mini PCIe Card [AR9280]) pci:v0000168Cd0000002Asv0000103Csd00003042* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (AzureWave AW-NE773 802.11abgn Wireless Half-size Mini PCIe Card [AR9280]) pci:v0000168Cd0000002Asv0000105Bsd0000E006* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (T77H053.00 802.11bgn Wireless Mini PCIe Card [AR9281]) pci:v0000168Cd0000002Asv0000105Bsd0000E01F* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (T77H047.31 802.11bgn Wireless Half-size Mini PCIe Card [AR9283]) pci:v0000168Cd0000002Asv0000106Bsd0000008F* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (AirPort Extreme) pci:v0000168Cd0000002Asv000011ADsd00006600* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (WN6600A 802.11bgn Wireless Mini PCIe Card [AR9281]) pci:v0000168Cd0000002Asv0000144Fsd00007141* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (WLL6080 802.11bgn Wireless Mini PCIe Card [AR9281]) pci:v0000168Cd0000002Asv0000168Csd00000203* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (DW1525 802.11abgn WLAN PCIe Card [AR9280]) pci:v0000168Cd0000002Asv00001A32sd00000303* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (EM303 802.11bgn Wireless Mini PCIe Card [AR9281]) pci:v0000168Cd0000002Asv00001A32sd00000306* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (EM306 802.11bgn Wireless Half-size Mini PCIe Card [AR9283]) pci:v0000168Cd0000002Asv00001A3Bsd00001067* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (AW-NE771 802.11bgn Wireless Mini PCIe Card [AR9281]) pci:v0000168Cd0000002Asv00001A3Bsd00001081* ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (AW-NE773 802.11abgn Wireless Half-size Mini PCIe Card [AR9280]) pci:v0000168Cd0000002B* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) pci:v0000168Cd0000002Bsv00001028sd00000204* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (Wireless 1502 802.11bgn Half-size Mini PCIe Card) pci:v0000168Cd0000002Bsv00001028sd00000205* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (Wireless 1702 802.11bgn Half-size Mini PCIe Card [AR9002WB-1NGCD]) pci:v0000168Cd0000002Bsv0000103Csd0000303F* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (U98Z062.10 802.11bgn Wireless Half-size Mini PCIe Card) pci:v0000168Cd0000002Bsv0000103Csd00003040* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (U98Z062.12 802.11bgn Wireless Half-size Mini PCIe Card) pci:v0000168Cd0000002Bsv0000105Bsd0000E017* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (T77H126.00 802.11bgn Wireless Half-size Mini PCIe Card) pci:v0000168Cd0000002Bsv0000105Bsd0000E023* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (T77H121.04 802.11bgn Wireless Half-size Mini PCIe Card) pci:v0000168Cd0000002Bsv0000105Bsd0000E025* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (T77H121.05 802.11bgn Wireless Half-size Mini PCIe Card) pci:v0000168Cd0000002Bsv00001113sd0000E811* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (WN7811A (Toshiba PA3722U-1MPC) 802.11bgn Wireless Half-size Mini PCIe Card) pci:v0000168Cd0000002Bsv0000185Fsd000030AF* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (DNXA-95 802.11bgn Wireless Half-size Mini PCIe Card) pci:v0000168Cd0000002Bsv00001931sd00000023* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (Option GTM67x PCIe WiFi Adapter) pci:v0000168Cd0000002Bsv00001A3Bsd00001089* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (AW-NE785 / AW-NE785H 802.11bgn Wireless Full or Half-size Mini PCIe Card) pci:v0000168Cd0000002Bsv00001A3Bsd00002C37* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (AW-NB037H 802.11bgn Wireless Half-size Mini PCIe Card [AR9002WB-1NGCD]) pci:v0000168Cd0000002Bsv00001B9Asd00000401* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (XW204E 802.11bgn Wireless Half-size Mini PCIe Card) pci:v0000168Cd0000002Bsv00001B9Asd00000C03* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (WB214E 802.11bgn Wireless Half-size Mini PCIe Card [AR9002WB-1NGCD]) pci:v0000168Cd0000002C* ID_MODEL_FROM_DATABASE=AR2427 802.11bg Wireless Network Adapter (PCI-Express) pci:v0000168Cd0000002D* ID_MODEL_FROM_DATABASE=AR9227 Wireless Network Adapter pci:v0000168Cd0000002E* ID_MODEL_FROM_DATABASE=AR9287 Wireless Network Adapter (PCI-Express) pci:v0000168Cd0000002Esv0000105Bsd0000E034* ID_MODEL_FROM_DATABASE=AR9287 Wireless Network Adapter (PCI-Express) (T77H167.00) pci:v0000168Cd00000030* ID_MODEL_FROM_DATABASE=AR93xx Wireless Network Adapter pci:v0000168Cd00000030sv0000103Csd00001627* ID_MODEL_FROM_DATABASE=AR93xx Wireless Network Adapter (AR9380/HB112 802.11abgn 3×3 Wi-Fi Adapter) pci:v0000168Cd00000030sv0000106Bsd0000009A* ID_MODEL_FROM_DATABASE=AR93xx Wireless Network Adapter (AirPort Extreme) pci:v0000168Cd00000030sv00001186sd00003A7E* ID_MODEL_FROM_DATABASE=AR93xx Wireless Network Adapter (DWA-566 Wireless N 300 Dual Band PCIe Desktop Adapter) pci:v0000168Cd00000030sv00001A56sd00002000* ID_MODEL_FROM_DATABASE=AR93xx Wireless Network Adapter (Killer Wireless-N 1102 Half-size Mini PCIe Card [AR9382]) pci:v0000168Cd00000030sv00001A56sd00002001* ID_MODEL_FROM_DATABASE=AR93xx Wireless Network Adapter (Killer Wireless-N 1103 Half-size Mini PCIe Card [AR9380]) pci:v0000168Cd00000032* ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter pci:v0000168Cd00000032sv00001028sd00000208* ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (Wireless 1506 WLAN Half Mini-Card) pci:v0000168Cd00000032sv0000103Csd00001838* ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (AR9485/HB125 802.11bgn 1×1 Wi-Fi Adapter) pci:v0000168Cd00000032sv0000105Bsd0000E044* ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (Unex DHXA-225) pci:v0000168Cd00000032sv00001A3Bsd00001186* ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (AW-NE186H) pci:v0000168Cd00000033* ID_MODEL_FROM_DATABASE=AR9580 Wireless Network Adapter pci:v0000168Cd00000034* ID_MODEL_FROM_DATABASE=AR9462 Wireless Network Adapter pci:v0000168Cd00000034sv00001A56sd00002003* ID_MODEL_FROM_DATABASE=AR9462 Wireless Network Adapter (Killer Wireless-N 1202 Half-size Mini PCIe Card) pci:v0000168Cd00000036* ID_MODEL_FROM_DATABASE=QCA9565 / AR9565 Wireless Network Adapter pci:v0000168Cd00000037* ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter pci:v0000168Cd00000037sv00001A3Bsd00002100* ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (AW-NB100H 802.11n Wireless Mini PCIe Card) pci:v0000168Cd0000003C* ID_MODEL_FROM_DATABASE=QCA986x/988x 802.11ac Wireless Network Adapter pci:v0000168Cd0000003E* ID_MODEL_FROM_DATABASE=QCA6174 802.11ac Wireless Network Adapter pci:v0000168Cd0000003Esv00001A56sd00001525* ID_MODEL_FROM_DATABASE=QCA6174 802.11ac Wireless Network Adapter (Killer N1525 Wireless-AC) pci:v0000168Cd00000040* ID_MODEL_FROM_DATABASE=QCA9980/9990 802.11ac Wireless Network Adapter pci:v0000168Cd00000041* ID_MODEL_FROM_DATABASE=QCA6164 802.11ac Wireless Network Adapter pci:v0000168Cd00000050* ID_MODEL_FROM_DATABASE=QCA9887 802.11ac Wireless Network Adapter pci:v0000168Cd00000207* ID_MODEL_FROM_DATABASE=AR5210 Wireless Network Adapter [AR5000 802.11a] pci:v0000168Cd00001014* ID_MODEL_FROM_DATABASE=AR5212 802.11abg NIC pci:v0000168Cd00001014sv00001014sd0000058A* ID_MODEL_FROM_DATABASE=AR5212 802.11abg NIC (ThinkPad 11a/b/g Wireless LAN Mini Express Adapter (AR5BXB6)) pci:v0000168Cd00009013* ID_MODEL_FROM_DATABASE=AR5002X Wireless Network Adapter pci:v0000168Cd0000FF19* ID_MODEL_FROM_DATABASE=AR5006X Wireless Network Adapter pci:v0000168Cd0000FF1B* ID_MODEL_FROM_DATABASE=AR2425 Wireless Network Adapter [AR5007EG 802.11bg] pci:v0000168Cd0000FF1C* ID_MODEL_FROM_DATABASE=AR5008 Wireless Network Adapter pci:v0000168Cd0000FF1D* ID_MODEL_FROM_DATABASE=AR922x Wireless Network Adapter pci:v0000168Cd0000FF1Dsv0000168Csd0000EE1C* ID_MODEL_FROM_DATABASE=AR922x Wireless Network Adapter (AR9220-AC1A [AVM Fritz!Box FON WLAN 7270 v3]) pci:v00001695* ID_VENDOR_FROM_DATABASE=EPoX Computer Co., Ltd. pci:v0000169C* ID_VENDOR_FROM_DATABASE=Netcell Corporation pci:v0000169Cd00000044* ID_MODEL_FROM_DATABASE=Revolution Storage Processing Card pci:v0000169D* ID_VENDOR_FROM_DATABASE=Club-3D VB (Wrong ID) pci:v000016A5* ID_VENDOR_FROM_DATABASE=Tekram Technology Co.,Ltd. pci:v000016AB* ID_VENDOR_FROM_DATABASE=Global Sun Technology Inc pci:v000016ABd00001100* ID_MODEL_FROM_DATABASE=GL24110P pci:v000016ABd00001101* ID_MODEL_FROM_DATABASE=PLX9052 PCMCIA-to-PCI Wireless LAN pci:v000016ABd00001102* ID_MODEL_FROM_DATABASE=PCMCIA-to-PCI Wireless Network Bridge pci:v000016ABd00008501* ID_MODEL_FROM_DATABASE=WL-8305 Wireless LAN PCI Adapter pci:v000016AE* ID_VENDOR_FROM_DATABASE=SafeNet Inc pci:v000016AEd00000001* ID_MODEL_FROM_DATABASE=SafeXcel 1140 pci:v000016AEd0000000A* ID_MODEL_FROM_DATABASE=SafeXcel 1841 pci:v000016AEd00001141* ID_MODEL_FROM_DATABASE=SafeXcel 1141 pci:v000016AEd00001141sv00000001sd00000001* ID_MODEL_FROM_DATABASE=SafeXcel 1141 (v. 1.1) pci:v000016AEd00001841* ID_MODEL_FROM_DATABASE=SafeXcel 1842 pci:v000016AF* ID_VENDOR_FROM_DATABASE=SparkLAN Communications, Inc. pci:v000016B4* ID_VENDOR_FROM_DATABASE=Aspex Semiconductor Ltd pci:v000016B8* ID_VENDOR_FROM_DATABASE=Sonnet Technologies, Inc. pci:v000016BE* ID_VENDOR_FROM_DATABASE=Creatix Polymedia GmbH pci:v000016C3* ID_VENDOR_FROM_DATABASE=Synopsys, Inc. pci:v000016C6* ID_VENDOR_FROM_DATABASE=Micrel-Kendin pci:v000016C6d00008695* ID_MODEL_FROM_DATABASE=Centaur KS8695 ARM processor pci:v000016C6d00008842* ID_MODEL_FROM_DATABASE=KSZ8842-PMQL 2-Port Ethernet Switch pci:v000016C8* ID_VENDOR_FROM_DATABASE=Octasic Inc. pci:v000016C9* ID_VENDOR_FROM_DATABASE=EONIC B.V. The Netherlands pci:v000016CA* ID_VENDOR_FROM_DATABASE=CENATEK Inc pci:v000016CAd00000001* ID_MODEL_FROM_DATABASE=Rocket Drive DL pci:v000016CD* ID_VENDOR_FROM_DATABASE=Advantech Co. Ltd pci:v000016CDd00000101* ID_MODEL_FROM_DATABASE=DirectPCI SRAM for DPX-11x series pci:v000016CDd00000102* ID_MODEL_FROM_DATABASE=DirectPCI SRAM for DPX-S/C/E-series pci:v000016CDd00000103* ID_MODEL_FROM_DATABASE=DirectPCI ROM for DPX-11x series pci:v000016CDd00000104* ID_MODEL_FROM_DATABASE=DirectPCI ROM for DPX-S/C/E-series pci:v000016CDd00000105* ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-114/DPX-115 pci:v000016CDd00000106* ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-116 pci:v000016CDd00000107* ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-116U pci:v000016CDd00000108* ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-117 pci:v000016CDd00000109* ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-112 pci:v000016CDd0000010A* ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-C/E-series pci:v000016CDd0000010B* ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-S series pci:v000016CE* ID_VENDOR_FROM_DATABASE=Roland Corp. pci:v000016D5* ID_VENDOR_FROM_DATABASE=Acromag, Inc. pci:v000016D5d00000504* ID_MODEL_FROM_DATABASE=PMC-DX504 Reconfigurable FPGA with LVDS I/O pci:v000016D5d00000520* ID_MODEL_FROM_DATABASE=PMC520 Serial Communication, 232 Octal pci:v000016D5d00000521* ID_MODEL_FROM_DATABASE=PMC521 Serial Communication, 422/485 Octal pci:v000016D5d00001020* ID_MODEL_FROM_DATABASE=PMC-AX1020 Reconfigurable FPGA with A/D & D/A pci:v000016D5d00001065* ID_MODEL_FROM_DATABASE=PMC-AX1065 Reconfigurable FPGA with A/D & D/A pci:v000016D5d00002004* ID_MODEL_FROM_DATABASE=PMC-DX2004 Reconfigurable FPGA with LVDS I/O pci:v000016D5d00002020* ID_MODEL_FROM_DATABASE=PMC-AX2020 Reconfigurable FPGA with A/D & D/A pci:v000016D5d00002065* ID_MODEL_FROM_DATABASE=PMC-AX2065 Reconfigurable FPGA with A/D & D/A pci:v000016D5d00003020* ID_MODEL_FROM_DATABASE=PMC-AX3020 Reconfigurable FPGA with A/D & D/A pci:v000016D5d00003065* ID_MODEL_FROM_DATABASE=PMC-AX3065 Reconfigurable FPGA with A/D & D/A pci:v000016D5d00004243* ID_MODEL_FROM_DATABASE=PMC424, APC424, AcPC424 Digital I/O and Counter Timer Module pci:v000016D5d00004248* ID_MODEL_FROM_DATABASE=PMC464, APC464, AcPC464 Digital I/O and Counter Timer Module pci:v000016D5d0000424B* ID_MODEL_FROM_DATABASE=PMC-DX2002 Reconfigurable FPGA with Differential I/O pci:v000016D5d00004253* ID_MODEL_FROM_DATABASE=PMC-DX503 Reconfigurable FPGA with TTL and Differential I/O pci:v000016D5d00004312* ID_MODEL_FROM_DATABASE=PMC-CX1002 Reconfigurable Conduction-Cooled FPGA Virtex-II with Differential I/O pci:v000016D5d00004313* ID_MODEL_FROM_DATABASE=PMC-CX1003 Reconfigurable Conduction-Cooled FPGA Virtex-II with CMOS and Differential I/O pci:v000016D5d00004322* ID_MODEL_FROM_DATABASE=PMC-CX2002 Reconfigurable Conduction-Cooled FPGA Virtex-II with Differential I/O pci:v000016D5d00004323* ID_MODEL_FROM_DATABASE=PMC-CX2003 Reconfigurable Conduction-Cooled FPGA Virtex-II with CMOS and Differential I/O pci:v000016D5d00004350* ID_MODEL_FROM_DATABASE=PMC-DX501 Reconfigurable Digital I/O Module pci:v000016D5d00004353* ID_MODEL_FROM_DATABASE=PMC-DX2003 Reconfigurable FPGA with TTL and Differential I/O pci:v000016D5d00004357* ID_MODEL_FROM_DATABASE=PMC-DX502 Reconfigurable Differential I/O Module pci:v000016D5d00004457* ID_MODEL_FROM_DATABASE=PMC730, APC730, AcPC730 Multifunction Module pci:v000016D5d0000464D* ID_MODEL_FROM_DATABASE=PMC408 32-Channel Digital Input/Output Module pci:v000016D5d00004850* ID_MODEL_FROM_DATABASE=PMC220-16 12-Bit Analog Output Module pci:v000016D5d00004A42* ID_MODEL_FROM_DATABASE=PMC483, APC483, AcPC483 Counter Timer Module pci:v000016D5d00004A50* ID_MODEL_FROM_DATABASE=PMC484, APC484, AcPC484 Counter Timer Module pci:v000016D5d00004A56* ID_MODEL_FROM_DATABASE=PMC230 16-Bit Analog Output Module pci:v000016D5d00004B47* ID_MODEL_FROM_DATABASE=PMC330, APC330, AcPC330 Analog Input Module, 16-bit A/D pci:v000016D5d00004C40* ID_MODEL_FROM_DATABASE=PMC-LX40 Reconfigurable Virtex-4 FPGA with plug-in I/O pci:v000016D5d00004C60* ID_MODEL_FROM_DATABASE=PMC-LX60 Reconfigurable Virtex-4 FPGA with plug-in I/O pci:v000016D5d00004D4D* ID_MODEL_FROM_DATABASE=PMC341, APC341, AcPC341 Analog Input Module, Simultaneous Sample & Hold pci:v000016D5d00004D4E* ID_MODEL_FROM_DATABASE=PMC482, APC482, AcPC482 Counter Timer Board pci:v000016D5d0000524D* ID_MODEL_FROM_DATABASE=PMC-DX2001 Reconfigurable FPGA with TTL I/O pci:v000016D5d00005335* ID_MODEL_FROM_DATABASE=PMC-SX35 Reconfigurable Virtex-4 FPGA with plug-in I/O pci:v000016D5d00005456* ID_MODEL_FROM_DATABASE=PMC470 48-Channel Digital Input/Output Module pci:v000016D5d00005601* ID_MODEL_FROM_DATABASE=PMC-VLX85 Reconfigurable Virtex-5 FPGA with plug-in I/O pci:v000016D5d00005602* ID_MODEL_FROM_DATABASE=PMC-VLX110 Reconfigurable Virtex-5 FPGA with plug-in I/O pci:v000016D5d00005603* ID_MODEL_FROM_DATABASE=PMC-VSX95 Reconfigurable Virtex-5 FPGA with plug-in I/O pci:v000016D5d00005604* ID_MODEL_FROM_DATABASE=PMC-VLX155 Reconfigurable Virtex-5 FPGA with plug-in I/O pci:v000016D5d00005605* ID_MODEL_FROM_DATABASE=PMC-VFX70 Reconfigurable Virtex-5 FPGA with plug-in I/O pci:v000016D5d00005606* ID_MODEL_FROM_DATABASE=PMC-VLX155-1M Reconfigurable Virtex-5 FPGA with plug-in I/O pci:v000016D5d00005701* ID_MODEL_FROM_DATABASE=PMC-SLX150: Reconfigurable Spartan-6 FPGA with plug-in I/O pci:v000016D5d00005702* ID_MODEL_FROM_DATABASE=PMC-SLX150-1M: Reconfigurable Spartan-6 FPGA with plug-in I/O pci:v000016D5d00005801* ID_MODEL_FROM_DATABASE=XMC-VLX85 Reconfigurable Virtex-5 FPGA with plug-in I/O pci:v000016D5d00005802* ID_MODEL_FROM_DATABASE=XMC-VLX110 Reconfigurable Virtex-5 FPGA with plug-in I/O pci:v000016D5d00005803* ID_MODEL_FROM_DATABASE=XMC-VSX95 Reconfigurable Virtex-5 FPGA with plug-in I/O pci:v000016D5d00005804* ID_MODEL_FROM_DATABASE=XMC-VLX155 Reconfigurable Virtex-5 FPGA with plug-in I/O pci:v000016D5d00005807* ID_MODEL_FROM_DATABASE=XMC-SLX150: Reconfigurable Spartan-6 FPGA with plug-in I/O pci:v000016D5d00005808* ID_MODEL_FROM_DATABASE=XMC-SLX150-1M: Reconfigurable Spartan-6 FPGA with plug-in I/O pci:v000016D5d00005901* ID_MODEL_FROM_DATABASE=APCe8650 PCI Express IndustryPack Carrier Card pci:v000016D5d00006301* ID_MODEL_FROM_DATABASE=XMC Module with user-configurable Virtex-6 FPGA, 240k logic cells, SFP front I/O pci:v000016D5d00006302* ID_MODEL_FROM_DATABASE=XMC Module with user-configurable Virtex-6 FPGA, 365k logic cells, SFP front I/O pci:v000016D5d00006303* ID_MODEL_FROM_DATABASE=XMC Module with user-configurable Virtex-6 FPGA, 240k logic cells, no front I/O pci:v000016D5d00006304* ID_MODEL_FROM_DATABASE=XMC Module with user-configurable Virtex-6 FPGA, 365k logic cells, no front I/O pci:v000016D5d00007000* ID_MODEL_FROM_DATABASE=XMC-7K325F: User-configurable Kintex-7 FPGA, 325k logic cells plus SFP front I/O pci:v000016D5d00007001* ID_MODEL_FROM_DATABASE=XMC-7K410F: User-configurable Kintex-7 FPGA, 410k logic cells plus SFP front I/O pci:v000016D5d00007002* ID_MODEL_FROM_DATABASE=XMC-7K325AX: User-Configurable Kintex-7 FPGA, 325k logic cells with AXM Plug-In I/O pci:v000016D5d00007003* ID_MODEL_FROM_DATABASE=XMC-7K410AX: User-Configurable Kintex-7 FPGA, 410k logic cells with AXM Plug-In I/O pci:v000016D5d00007004* ID_MODEL_FROM_DATABASE=XMC-7K325CC: User-Configurable Kintex-7 FPGA, 325k logic cells, conduction-cooled pci:v000016D5d00007005* ID_MODEL_FROM_DATABASE=XMC-7K410CC: User-Configurable Kintex-7 FPGA, 410k logic cells, conduction-cooled pci:v000016D5d00007006* ID_MODEL_FROM_DATABASE=XMC-7A200: User-Configurable Artix-7 FPGA, 200k logic cells with Plug-In I/O pci:v000016D5d00007007* ID_MODEL_FROM_DATABASE=XMC-7A200CC: User-Configurable Conduction-Cooled Artix-7 FPGA, with 200k logic cells pci:v000016DA* ID_VENDOR_FROM_DATABASE=Advantech Co., Ltd. pci:v000016DAd00000011* ID_MODEL_FROM_DATABASE=INES GPIB-PCI pci:v000016DF* ID_VENDOR_FROM_DATABASE=PIKA Technologies Inc. pci:v000016E2* ID_VENDOR_FROM_DATABASE=Geotest-MTS pci:v000016E3* ID_VENDOR_FROM_DATABASE=European Space Agency pci:v000016E3d00001E0F* ID_MODEL_FROM_DATABASE=LEON2FT Processor pci:v000016E5* ID_VENDOR_FROM_DATABASE=Intellon Corp. pci:v000016E5d00006000* ID_MODEL_FROM_DATABASE=INT6000 Ethernet-to-Powerline Bridge [HomePlug AV] pci:v000016E5d00006300* ID_MODEL_FROM_DATABASE=INT6300 Ethernet-to-Powerline Bridge [HomePlug AV] pci:v000016EC* ID_VENDOR_FROM_DATABASE=U.S. Robotics pci:v000016ECd000000ED* ID_MODEL_FROM_DATABASE=USR997900 pci:v000016ECd00000116* ID_MODEL_FROM_DATABASE=USR997902 10/100/1000 Mbps PCI Network Card pci:v000016ECd00002F00* ID_MODEL_FROM_DATABASE=USR5660A (USR265660A, USR5660A-BP) 56K PCI Faxmodem pci:v000016ECd00003685* ID_MODEL_FROM_DATABASE=Wireless Access PCI Adapter Model 022415 pci:v000016ECd00004320* ID_MODEL_FROM_DATABASE=USR997904 10/100/1000 64-bit NIC (Marvell Yukon) pci:v000016ECd0000AB06* ID_MODEL_FROM_DATABASE=USR997901A 10/100 Cardbus NIC pci:v000016ED* ID_VENDOR_FROM_DATABASE=Sycron N. V. pci:v000016EDd00001001* ID_MODEL_FROM_DATABASE=UMIO communication card pci:v000016F2* ID_VENDOR_FROM_DATABASE=ETAS GmbH pci:v000016F2d00000200* ID_MODEL_FROM_DATABASE=I/O board pci:v000016F2d00000200sv000016F2sd00000010* ID_MODEL_FROM_DATABASE=I/O board (ES53xx I/O board) pci:v000016F3* ID_VENDOR_FROM_DATABASE=Jetway Information Co., Ltd. pci:v000016F4* ID_VENDOR_FROM_DATABASE=Vweb Corp pci:v000016F4d00008000* ID_MODEL_FROM_DATABASE=VW2010 pci:v000016F6* ID_VENDOR_FROM_DATABASE=VideoTele.com, Inc. pci:v00001702* ID_VENDOR_FROM_DATABASE=Internet Machines Corporation (IMC) pci:v00001705* ID_VENDOR_FROM_DATABASE=Digital First, Inc. pci:v0000170B* ID_VENDOR_FROM_DATABASE=NetOctave pci:v0000170Bd00000100* ID_MODEL_FROM_DATABASE=NSP2000-SSL crypto accelerator pci:v0000170C* ID_VENDOR_FROM_DATABASE=YottaYotta Inc. pci:v00001719* ID_VENDOR_FROM_DATABASE=EZChip Technologies pci:v00001719d00001000* ID_MODEL_FROM_DATABASE=NPA Access Network Processor Family pci:v00001725* ID_VENDOR_FROM_DATABASE=Vitesse Semiconductor pci:v00001725d00007174* ID_MODEL_FROM_DATABASE=VSC7174 PCI/PCI-X Serial ATA Host Bus Controller pci:v0000172A* ID_VENDOR_FROM_DATABASE=Accelerated Encryption pci:v0000172Ad000013C8* ID_MODEL_FROM_DATABASE=AEP SureWare Runner 1000V3 pci:v00001734* ID_VENDOR_FROM_DATABASE=Fujitsu Technology Solutions pci:v00001735* ID_VENDOR_FROM_DATABASE=Aten International Co. Ltd. pci:v00001737* ID_VENDOR_FROM_DATABASE=Linksys pci:v00001737d00000029* ID_MODEL_FROM_DATABASE=WPG54G ver. 4 PCI Card pci:v00001737d00001032* ID_MODEL_FROM_DATABASE=Gigabit Network Adapter pci:v00001737d00001032sv00001737sd00000015* ID_MODEL_FROM_DATABASE=Gigabit Network Adapter (EG1032 v2 Instant Gigabit Network Adapter) pci:v00001737d00001032sv00001737sd00000024* ID_MODEL_FROM_DATABASE=Gigabit Network Adapter (EG1032 v3 Instant Gigabit Network Adapter) pci:v00001737d00001064* ID_MODEL_FROM_DATABASE=Gigabit Network Adapter pci:v00001737d00001064sv00001737sd00000016* ID_MODEL_FROM_DATABASE=Gigabit Network Adapter (EG1064 v2 Instant Gigabit Network Adapter) pci:v00001737d0000AB08* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet pci:v00001737d0000AB09* ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet pci:v0000173B* ID_VENDOR_FROM_DATABASE=Altima (nee Broadcom) pci:v0000173Bd000003E8* ID_MODEL_FROM_DATABASE=AC1000 Gigabit Ethernet pci:v0000173Bd000003E9* ID_MODEL_FROM_DATABASE=AC1001 Gigabit Ethernet pci:v0000173Bd000003EA* ID_MODEL_FROM_DATABASE=AC9100 Gigabit Ethernet pci:v0000173Bd000003EAsv0000173Bsd00000001* ID_MODEL_FROM_DATABASE=AC9100 Gigabit Ethernet (AC1002) pci:v0000173Bd000003EB* ID_MODEL_FROM_DATABASE=AC1003 Gigabit Ethernet pci:v00001743* ID_VENDOR_FROM_DATABASE=Peppercon AG pci:v00001743d00008139* ID_MODEL_FROM_DATABASE=ROL/F-100 Fast Ethernet Adapter with ROL pci:v00001745* ID_VENDOR_FROM_DATABASE=ViXS Systems, Inc. pci:v00001745d00002020* ID_MODEL_FROM_DATABASE=XCode II Series pci:v00001745d00002100* ID_MODEL_FROM_DATABASE=XCode 2100 Series pci:v00001749* ID_VENDOR_FROM_DATABASE=RLX Technologies pci:v0000174B* ID_VENDOR_FROM_DATABASE=PC Partner Limited / Sapphire Technology pci:v0000174D* ID_VENDOR_FROM_DATABASE=WellX Telecom SA pci:v0000175C* ID_VENDOR_FROM_DATABASE=AudioScience Inc pci:v0000175E* ID_VENDOR_FROM_DATABASE=Sanera Systems, Inc. pci:v00001760* ID_VENDOR_FROM_DATABASE=TEDIA spol. s r. o. pci:v00001760d00000101* ID_MODEL_FROM_DATABASE=PCD-7004 Digital Bi-Directional Ports PCI Card pci:v00001760d00000102* ID_MODEL_FROM_DATABASE=PCD-7104 Digital Input & Output PCI Card pci:v00001760d00000303* ID_MODEL_FROM_DATABASE=PCD-7006C Digital Input & Output PCI Card pci:v00001771* ID_VENDOR_FROM_DATABASE=InnoVISION Multimedia Ltd. pci:v00001775* ID_VENDOR_FROM_DATABASE=GE Intelligent Platforms pci:v0000177D* ID_VENDOR_FROM_DATABASE=Cavium, Inc. pci:v0000177Dd00000001* ID_MODEL_FROM_DATABASE=Nitrox XL N1 pci:v0000177Dd00000003* ID_MODEL_FROM_DATABASE=Nitrox XL N1 Lite pci:v0000177Dd00000004* ID_MODEL_FROM_DATABASE=Octeon (and older) FIPS pci:v0000177Dd00000005* ID_MODEL_FROM_DATABASE=Octeon CN38XX Network Processor Pass 3.x pci:v0000177Dd00000006* ID_MODEL_FROM_DATABASE=RoHS pci:v0000177Dd00000010* ID_MODEL_FROM_DATABASE=Nitrox XL NPX pci:v0000177Dd00000020* ID_MODEL_FROM_DATABASE=Octeon CN31XX Network Processor pci:v0000177Dd00000030* ID_MODEL_FROM_DATABASE=Octeon CN30XX Network Processor pci:v0000177Dd00000040* ID_MODEL_FROM_DATABASE=Octeon CN58XX Network Processor pci:v0000177Dd00000050* ID_MODEL_FROM_DATABASE=Octeon CN57XX Network Processor (CN54XX/CN55XX/CN56XX) pci:v0000177Dd00000070* ID_MODEL_FROM_DATABASE=Octeon CN50XX Network Processor pci:v0000177Dd00000080* ID_MODEL_FROM_DATABASE=Octeon CN52XX Network Processor pci:v0000177Dd00000090* ID_MODEL_FROM_DATABASE=Octeon II CN63XX Network Processor pci:v0000177Dd00000091* ID_MODEL_FROM_DATABASE=Octeon II CN68XX Network Processor pci:v0000177Dd00000092* ID_MODEL_FROM_DATABASE=Octeon II CN65XX Network Processor pci:v0000177Dd00000093* ID_MODEL_FROM_DATABASE=Octeon II CN61XX Network Processor pci:v0000177Dd00000094* ID_MODEL_FROM_DATABASE=Octeon Fusion CNF71XX Cell processor pci:v0000177Dd00000095* ID_MODEL_FROM_DATABASE=Octeon III CN78XX Network Processor pci:v0000177Dd00000096* ID_MODEL_FROM_DATABASE=Octeon III CN70XX Network Processor pci:v0000177Dd00009700* ID_MODEL_FROM_DATABASE=Octeon III CN73XX Network Processor pci:v0000177Dd00009800* ID_MODEL_FROM_DATABASE=Octeon Fusion CNF75XX Processor pci:v0000177Dd0000A001* ID_MODEL_FROM_DATABASE=THUNDERX MRML Bridge pci:v0000177Dd0000A002* ID_MODEL_FROM_DATABASE=THUNDERX PCC Bridge pci:v0000177Dd0000A002sv0000177Dsd0000A102* ID_MODEL_FROM_DATABASE=THUNDERX PCC Bridge (CN88XX PCC Bridge) pci:v0000177Dd0000A008* ID_MODEL_FROM_DATABASE=THUNDERX SMMU pci:v0000177Dd0000A008sv0000177Dsd0000A108* ID_MODEL_FROM_DATABASE=THUNDERX SMMU (CN88XX SMMU) pci:v0000177Dd0000A009* ID_MODEL_FROM_DATABASE=THUNDERX Generic Interrupt Controller pci:v0000177Dd0000A00A* ID_MODEL_FROM_DATABASE=THUNDERX GPIO Controller pci:v0000177Dd0000A00B* ID_MODEL_FROM_DATABASE=THUNDERX MPI / SPI Controller pci:v0000177Dd0000A00C* ID_MODEL_FROM_DATABASE=THUNDERX MIO-PTP Controller pci:v0000177Dd0000A00D* ID_MODEL_FROM_DATABASE=THUNDERX MIX Network Controller pci:v0000177Dd0000A00E* ID_MODEL_FROM_DATABASE=THUNDERX Reset Controller pci:v0000177Dd0000A00F* ID_MODEL_FROM_DATABASE=THUNDERX UART Controller pci:v0000177Dd0000A010* ID_MODEL_FROM_DATABASE=THUNDERX eMMC/SD Controller pci:v0000177Dd0000A011* ID_MODEL_FROM_DATABASE=THUNDERX MIO-BOOT Controller pci:v0000177Dd0000A012* ID_MODEL_FROM_DATABASE=THUNDERX TWSI / I2C Controller pci:v0000177Dd0000A013* ID_MODEL_FROM_DATABASE=THUNDERX CCPI (Multi-node connect) pci:v0000177Dd0000A014* ID_MODEL_FROM_DATABASE=THUNDERX Voltage Regulator Module pci:v0000177Dd0000A015* ID_MODEL_FROM_DATABASE=THUNDERX PCIe Switch Logic Interface pci:v0000177Dd0000A016* ID_MODEL_FROM_DATABASE=THUNDERX Key Memory pci:v0000177Dd0000A017* ID_MODEL_FROM_DATABASE=THUNDERX GTI (Global System Timers) pci:v0000177Dd0000A018* ID_MODEL_FROM_DATABASE=THUNDERX Random Number Generator pci:v0000177Dd0000A019* ID_MODEL_FROM_DATABASE=THUNDERX DFA pci:v0000177Dd0000A01A* ID_MODEL_FROM_DATABASE=THUNDERX Zip Coprocessor pci:v0000177Dd0000A01B* ID_MODEL_FROM_DATABASE=THUNDERX xHCI USB Controller pci:v0000177Dd0000A01C* ID_MODEL_FROM_DATABASE=THUNDERX AHCI SATA Controller pci:v0000177Dd0000A01Csv0000177Dsd0000A11C* ID_MODEL_FROM_DATABASE=THUNDERX AHCI SATA Controller (CN88XX AHCI SATA Controller) pci:v0000177Dd0000A01D* ID_MODEL_FROM_DATABASE=THUNDERX RAID Coprocessor pci:v0000177Dd0000A01E* ID_MODEL_FROM_DATABASE=THUNDERX Network Interface Controller pci:v0000177Dd0000A01F* ID_MODEL_FROM_DATABASE=THUNDERX Traffic Network Switch pci:v0000177Dd0000A020* ID_MODEL_FROM_DATABASE=THUNDERX PEM (PCI Express Interface) pci:v0000177Dd0000A021* ID_MODEL_FROM_DATABASE=THUNDERX L2C (Level-2 Cache Controller) pci:v0000177Dd0000A022* ID_MODEL_FROM_DATABASE=THUNDERX LMC (DRAM Controller) pci:v0000177Dd0000A023* ID_MODEL_FROM_DATABASE=THUNDERX OCLA (On-Chip Logic Analyzer) pci:v0000177Dd0000A024* ID_MODEL_FROM_DATABASE=THUNDERX OSM pci:v0000177Dd0000A025* ID_MODEL_FROM_DATABASE=THUNDERX GSER (General Serializer/Deserializer) pci:v0000177Dd0000A026* ID_MODEL_FROM_DATABASE=THUNDERX BGX (Common Ethernet Interface) pci:v0000177Dd0000A027* ID_MODEL_FROM_DATABASE=THUNDERX IOBN pci:v0000177Dd0000A029* ID_MODEL_FROM_DATABASE=THUNDERX NCSI (Network Controller Sideband Interface) pci:v0000177Dd0000A02A* ID_MODEL_FROM_DATABASE=THUNDERX SGP pci:v0000177Dd0000A02B* ID_MODEL_FROM_DATABASE=THUNDERX SMI / MDIO Controller pci:v0000177Dd0000A02C* ID_MODEL_FROM_DATABASE=THUNDERX DAP (Debug Access Port) pci:v0000177Dd0000A02D* ID_MODEL_FROM_DATABASE=THUNDERX PCIERC (PCIe Root Complex) pci:v0000177Dd0000A02E* ID_MODEL_FROM_DATABASE=THUNDERX L2C-TAD pci:v0000177Dd0000A02F* ID_MODEL_FROM_DATABASE=THUNDERX L2C-CBC pci:v0000177Dd0000A030* ID_MODEL_FROM_DATABASE=THUNDERX L2C-MCI pci:v0000177Dd0000A031* ID_MODEL_FROM_DATABASE=THUNDERX MIO-FUS (Fuse Access Controller) pci:v0000177Dd0000A032* ID_MODEL_FROM_DATABASE=THUNDERX FUSF (Fuse Controller) pci:v00001787* ID_VENDOR_FROM_DATABASE=Hightech Information System Ltd. pci:v00001789* ID_VENDOR_FROM_DATABASE=Ennyah Technologies Corp. pci:v00001796* ID_VENDOR_FROM_DATABASE=Research Centre Juelich pci:v00001796d00000001* ID_MODEL_FROM_DATABASE=SIS1100 [Gigabit link] pci:v00001796d00000002* ID_MODEL_FROM_DATABASE=HOTlink pci:v00001796d00000003* ID_MODEL_FROM_DATABASE=Counter Timer pci:v00001796d00000004* ID_MODEL_FROM_DATABASE=CAMAC Controller pci:v00001796d00000005* ID_MODEL_FROM_DATABASE=PROFIBUS pci:v00001796d00000006* ID_MODEL_FROM_DATABASE=AMCC HOTlink pci:v00001796d0000000D* ID_MODEL_FROM_DATABASE=Synchronisation Slave pci:v00001796d0000000E* ID_MODEL_FROM_DATABASE=SIS1100-eCMC pci:v00001796d0000000F* ID_MODEL_FROM_DATABASE=TDC (GPX) pci:v00001796d00000010* ID_MODEL_FROM_DATABASE=PCIe Counter Timer pci:v00001796d00000011* ID_MODEL_FROM_DATABASE=SIS1100-e single link pci:v00001796d00000012* ID_MODEL_FROM_DATABASE=SIS1100-e quad link pci:v00001796d00000015* ID_MODEL_FROM_DATABASE=SIS8100 [Gigabit link, MicroTCA] pci:v00001797* ID_VENDOR_FROM_DATABASE=Intersil Techwell pci:v00001797d00005864* ID_MODEL_FROM_DATABASE=TW5864 multimedia video controller pci:v00001797d00006801* ID_MODEL_FROM_DATABASE=TW6802 multimedia video card pci:v00001797d00006802* ID_MODEL_FROM_DATABASE=TW6802 multimedia other device pci:v00001797d00006810* ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller pci:v00001797d00006811* ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller pci:v00001797d00006812* ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller pci:v00001797d00006813* ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller pci:v00001797d00006814* ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller pci:v00001797d00006815* ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller pci:v00001797d00006816* ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller pci:v00001797d00006817* ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller pci:v00001797d00006864* ID_MODEL_FROM_DATABASE=TW6864 multimedia video controller pci:v00001799* ID_VENDOR_FROM_DATABASE=Belkin pci:v00001799d00006001* ID_MODEL_FROM_DATABASE=F5D6001 Wireless PCI Card [Realtek RTL8180] pci:v00001799d00006020* ID_MODEL_FROM_DATABASE=F5D6020 v3000 Wireless PCMCIA Card [Realtek RTL8180] pci:v00001799d00006060* ID_MODEL_FROM_DATABASE=F5D6060 Wireless PDA Card pci:v00001799d0000700F* ID_MODEL_FROM_DATABASE=F5D7000 v7000 Wireless G Desktop Card [Realtek RTL8185] pci:v00001799d0000701F* ID_MODEL_FROM_DATABASE=F5D7010 v7000 Wireless G Notebook Card [Realtek RTL8185] pci:v0000179A* ID_VENDOR_FROM_DATABASE=id Quantique pci:v0000179Ad00000001* ID_MODEL_FROM_DATABASE=Quantis PCI 16Mbps pci:v0000179C* ID_VENDOR_FROM_DATABASE=Data Patterns pci:v0000179Cd00000557* ID_MODEL_FROM_DATABASE=DP-PCI-557 [PCI 1553B] pci:v0000179Cd00000566* ID_MODEL_FROM_DATABASE=DP-PCI-566 [Intelligent PCI 1553B] pci:v0000179Cd00001152* ID_MODEL_FROM_DATABASE=DP-cPCI-1152 (8-channel Isolated ADC Module) pci:v0000179Cd00005031* ID_MODEL_FROM_DATABASE=DP-CPCI-5031-Synchro Module pci:v0000179Cd00005112* ID_MODEL_FROM_DATABASE=DP-cPCI-5112 [MM-Carrier] pci:v0000179Cd00005121* ID_MODEL_FROM_DATABASE=DP-CPCI-5121-IP Carrier pci:v0000179Cd00005211* ID_MODEL_FROM_DATABASE=DP-CPCI-5211-IP Carrier pci:v0000179Cd00005679* ID_MODEL_FROM_DATABASE=AGE Display Module pci:v000017A0* ID_VENDOR_FROM_DATABASE=Genesys Logic, Inc pci:v000017A0d00007163* ID_MODEL_FROM_DATABASE=GL9701 PCIe to PCI Bridge pci:v000017A0d00008083* ID_MODEL_FROM_DATABASE=GL880 USB 1.1 UHCI controller pci:v000017A0d00008084* ID_MODEL_FROM_DATABASE=GL880 USB 2.0 EHCI controller pci:v000017AA* ID_VENDOR_FROM_DATABASE=Lenovo pci:v000017AB* ID_VENDOR_FROM_DATABASE=Phillips Components pci:v000017AF* ID_VENDOR_FROM_DATABASE=Hightech Information System Ltd. pci:v000017B3* ID_VENDOR_FROM_DATABASE=Hawking Technologies pci:v000017B3d0000AB08* ID_MODEL_FROM_DATABASE=PN672TX 10/100 Ethernet pci:v000017B4* ID_VENDOR_FROM_DATABASE=Indra Networks, Inc. pci:v000017B4d00000011* ID_MODEL_FROM_DATABASE=WebEnhance 100 GZIP Compression Card pci:v000017B4d00000012* ID_MODEL_FROM_DATABASE=WebEnhance 200 GZIP Compression Card pci:v000017B4d00000015* ID_MODEL_FROM_DATABASE=WebEnhance 300 GZIP Compression Card pci:v000017B4d00000016* ID_MODEL_FROM_DATABASE=StorCompress 300 GZIP Compression Card pci:v000017B4d00000017* ID_MODEL_FROM_DATABASE=StorSecure 300 GZIP Compression and AES Encryption Card pci:v000017C0* ID_VENDOR_FROM_DATABASE=Wistron Corp. pci:v000017C2* ID_VENDOR_FROM_DATABASE=Newisys, Inc. pci:v000017CB* ID_VENDOR_FROM_DATABASE=Airgo Networks, Inc. pci:v000017CBd00000001* ID_MODEL_FROM_DATABASE=AGN100 802.11 a/b/g True MIMO Wireless Card pci:v000017CBd00000001sv00001385sd00005C00* ID_MODEL_FROM_DATABASE=AGN100 802.11 a/b/g True MIMO Wireless Card (WGM511 Pre-N 802.11g Wireless CardBus Adapter) pci:v000017CBd00000001sv00001737sd00000045* ID_MODEL_FROM_DATABASE=AGN100 802.11 a/b/g True MIMO Wireless Card (WMP54GX v1 802.11g Wireless-G PCI Adapter with SRX) pci:v000017CBd00000002* ID_MODEL_FROM_DATABASE=AGN300 802.11 a/b/g True MIMO Wireless Card pci:v000017CBd00000002sv00001385sd00006D00* ID_MODEL_FROM_DATABASE=AGN300 802.11 a/b/g True MIMO Wireless Card (WPNT511 RangeMax 240 Mbps Wireless CardBus Adapter) pci:v000017CBd00000002sv00001737sd00000054* ID_MODEL_FROM_DATABASE=AGN300 802.11 a/b/g True MIMO Wireless Card (WPC54GX4 v1 802.11g Wireless-G Notebook Adapter with SRX400) pci:v000017CC* ID_VENDOR_FROM_DATABASE=NetChip Technology, Inc pci:v000017CCd00002280* ID_MODEL_FROM_DATABASE=USB 2.0 pci:v000017CF* ID_VENDOR_FROM_DATABASE=Z-Com, Inc. pci:v000017D3* ID_VENDOR_FROM_DATABASE=Areca Technology Corp. pci:v000017D3d00001110* ID_MODEL_FROM_DATABASE=ARC-1110 4-Port PCI-X to SATA RAID Controller pci:v000017D3d00001120* ID_MODEL_FROM_DATABASE=ARC-1120 8-Port PCI-X to SATA RAID Controller pci:v000017D3d00001130* ID_MODEL_FROM_DATABASE=ARC-1130 12-Port PCI-X to SATA RAID Controller pci:v000017D3d00001160* ID_MODEL_FROM_DATABASE=ARC-1160 16-Port PCI-X to SATA RAID Controller pci:v000017D3d00001170* ID_MODEL_FROM_DATABASE=ARC-1170 24-Port PCI-X to SATA RAID Controller pci:v000017D3d00001201* ID_MODEL_FROM_DATABASE=ARC-1200 2-Port PCI-Express to SATA II RAID Controller pci:v000017D3d00001210* ID_MODEL_FROM_DATABASE=ARC-1210 4-Port PCI-Express to SATA RAID Controller pci:v000017D3d00001214* ID_MODEL_FROM_DATABASE=ARC-12x4 PCIe 2.0 to SAS/SATA 6Gb RAID Controller pci:v000017D3d00001214sv000017D3sd00001214* ID_MODEL_FROM_DATABASE=ARC-12x4 PCIe 2.0 to SAS/SATA 6Gb RAID Controller (ARC-1214 4-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller) pci:v000017D3d00001214sv000017D3sd00001224* ID_MODEL_FROM_DATABASE=ARC-12x4 PCIe 2.0 to SAS/SATA 6Gb RAID Controller (ARC-1224 8-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller) pci:v000017D3d00001214sv000017D3sd00001264* ID_MODEL_FROM_DATABASE=ARC-12x4 PCIe 2.0 to SAS/SATA 6Gb RAID Controller (ARC-1264 12/16 Port PCIe 2.0 to SATA 6Gb RAID Controller) pci:v000017D3d00001214sv000017D3sd00001284* ID_MODEL_FROM_DATABASE=ARC-12x4 PCIe 2.0 to SAS/SATA 6Gb RAID Controller (ARC-1284 24 Port PCIe 2.0 to SATA 6Gb RAID Controller) pci:v000017D3d00001220* ID_MODEL_FROM_DATABASE=ARC-1220 8-Port PCI-Express to SATA RAID Controller pci:v000017D3d00001222* ID_MODEL_FROM_DATABASE=ARC-1222 8-Port PCI-Express to SAS/SATA II RAID Controller pci:v000017D3d00001230* ID_MODEL_FROM_DATABASE=ARC-1230 12-Port PCI-Express to SATA RAID Controller pci:v000017D3d00001260* ID_MODEL_FROM_DATABASE=ARC-1260 16-Port PCI-Express to SATA RAID Controller pci:v000017D3d00001280* ID_MODEL_FROM_DATABASE=ARC-1280/1280ML 24-Port PCI-Express to SATA II RAID Controller pci:v000017D3d00001280sv000017D3sd00001221* ID_MODEL_FROM_DATABASE=ARC-1280/1280ML 24-Port PCI-Express to SATA II RAID Controller (ARC-1221 8-Port PCI-Express to SATA RAID Controller) pci:v000017D3d00001300* ID_MODEL_FROM_DATABASE=ARC-1300ix-16 16-Port PCI-Express to SAS Non-RAID Host Adapter pci:v000017D3d00001320* ID_MODEL_FROM_DATABASE=ARC-1320 8/16 Port PCIe 2.0 to SAS/SATA 6Gb Non-RAID Host Adapter pci:v000017D3d00001330* ID_MODEL_FROM_DATABASE=ARC-1330 16 Port PCIe 3.0 to SAS/SATA 12Gb Non-RAID Host Adapter pci:v000017D3d00001680* ID_MODEL_FROM_DATABASE=ARC-1680 series PCIe to SAS/SATA 3Gb RAID Controller pci:v000017D3d00001680sv000017D3sd00001212* ID_MODEL_FROM_DATABASE=ARC-1680 series PCIe to SAS/SATA 3Gb RAID Controller (ARC-1212 4-Port PCIe to SAS/SATA II RAID Controller) pci:v000017D3d00001680sv000017D3sd00001222* ID_MODEL_FROM_DATABASE=ARC-1680 series PCIe to SAS/SATA 3Gb RAID Controller (ARC-1222 8-Port PCIe to SAS/SATA 3Gb RAID Controller) pci:v000017D3d00001680sv000017D3sd00001680* ID_MODEL_FROM_DATABASE=ARC-1680 series PCIe to SAS/SATA 3Gb RAID Controller (ARC-1680 8/12/16/24 Port PCIe to SAS/SATA 3Gb RAID Controller) pci:v000017D3d00001880* ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller pci:v000017D3d00001880sv000017D3sd00001213* ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1213 4-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller) pci:v000017D3d00001880sv000017D3sd00001215* ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1215 4-Port PCIe 3.0 to SAS/SATA 6Gb RAID Controller) pci:v000017D3d00001880sv000017D3sd00001216* ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1216 4-Port PCIe 3.0 to SAS/SATA 12Gb RAID Controller) pci:v000017D3d00001880sv000017D3sd00001223* ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1223 8-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller) pci:v000017D3d00001880sv000017D3sd00001225* ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1225 8-Port PCIe 3.0 to SAS/SATA 6Gb RAID Controller) pci:v000017D3d00001880sv000017D3sd00001226* ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1226 8-Port PCIe 3.0 to SAS/SATA 12Gb RAID Controller) pci:v000017D3d00001880sv000017D3sd00001880* ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1880 8/12/16/24 Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller) pci:v000017D3d00001880sv000017D3sd00001882* ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1882 8/12/16/24 Port PCIe 3.0 to SAS/SATA 6Gb RAID Controller) pci:v000017D3d00001880sv000017D3sd00001883* ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1883 8/12/16/24 Port PCIe 3.0 to SAS/SATA 12Gb RAID Controller) pci:v000017D5* ID_VENDOR_FROM_DATABASE=Exar Corp. pci:v000017D5d00005731* ID_MODEL_FROM_DATABASE=Xframe 10-Gigabit Ethernet PCI-X pci:v000017D5d00005732* ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 pci:v000017D5d00005831* ID_MODEL_FROM_DATABASE=Xframe 10-Gigabit Ethernet PCI-X pci:v000017D5d00005831sv0000103Csd000012D5* ID_MODEL_FROM_DATABASE=Xframe 10-Gigabit Ethernet PCI-X (PCI-X 133MHz 10GbE SR Fiber) pci:v000017D5d00005831sv000010A9sd00008020* ID_MODEL_FROM_DATABASE=Xframe 10-Gigabit Ethernet PCI-X (Single Port 10-Gigabit Ethernet (PCI-X, Fiber)) pci:v000017D5d00005831sv000010A9sd00008024* ID_MODEL_FROM_DATABASE=Xframe 10-Gigabit Ethernet PCI-X (Single Port 10-Gigabit Ethernet (PCI-X, Fiber)) pci:v000017D5d00005832* ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 pci:v000017D5d00005832sv0000103Csd00001337* ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (PCI-X 266MHz 10GigE SR [AD385A]) pci:v000017D5d00005832sv000010A9sd00008021* ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Single Port 10-Gigabit Ethernet II (PCI-X, Fiber)) pci:v000017D5d00005832sv000017D5sd00006020* ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe II SR) pci:v000017D5d00005832sv000017D5sd00006021* ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe II SR, Low Profile) pci:v000017D5d00005832sv000017D5sd00006022* ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe E SR) pci:v000017D5d00005832sv000017D5sd00006420* ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe II LR) pci:v000017D5d00005832sv000017D5sd00006421* ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe II LR, Low Profile) pci:v000017D5d00005832sv000017D5sd00006422* ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe E LR) pci:v000017D5d00005832sv000017D5sd00006C20* ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe II CX4) pci:v000017D5d00005832sv000017D5sd00006C21* ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe II CX4, Low Profile) pci:v000017D5d00005832sv000017D5sd00006C22* ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe E CX4) pci:v000017D5d00005833* ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe pci:v000017D5d00005833sv000017D5sd00006030* ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3110 Single Port SR) pci:v000017D5d00005833sv000017D5sd00006031* ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3120 Dual Port SR) pci:v000017D5d00005833sv000017D5sd00006430* ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3110 Single Port LR) pci:v000017D5d00005833sv000017D5sd00006431* ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3120 Dual Port LR) pci:v000017D5d00005833sv000017D5sd00007030* ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3110 Single Port LRM) pci:v000017D5d00005833sv000017D5sd00007031* ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3120 Dual Port LRM) pci:v000017D5d00005833sv000017D5sd00007430* ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3110 Single Port 10GBase-T) pci:v000017D5d00005833sv000017D5sd00007431* ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3120 Dual Port 10GBase-T) pci:v000017D5d00005833sv000017D5sd00007830* ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3110 Single Port 10GBase-CR) pci:v000017D5d00005833sv000017D5sd00007831* ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3120 Dual Port 10GBase-CR) pci:v000017DB* ID_VENDOR_FROM_DATABASE=Cray Inc pci:v000017DBd00000101* ID_MODEL_FROM_DATABASE=XT Series [Seastar] 3D Toroidal Router pci:v000017DE* ID_VENDOR_FROM_DATABASE=KWorld Computer Co. Ltd. pci:v000017E4* ID_VENDOR_FROM_DATABASE=Sectra AB pci:v000017E4d00000001* ID_MODEL_FROM_DATABASE=KK671 Cardbus encryption board pci:v000017E4d00000002* ID_MODEL_FROM_DATABASE=KK672 Cardbus encryption board pci:v000017E6* ID_VENDOR_FROM_DATABASE=Entropic Communications Inc. pci:v000017E6d00000010* ID_MODEL_FROM_DATABASE=EN2010 [c.Link] MoCA Network Controller (Coax, PCI interface) pci:v000017E6d00000011* ID_MODEL_FROM_DATABASE=EN2010 [c.Link] MoCA Network Controller (Coax, MPEG interface) pci:v000017E6d00000021* ID_MODEL_FROM_DATABASE=EN2210 [c.Link] MoCA Network Controller (Coax) pci:v000017E6d00000025* ID_MODEL_FROM_DATABASE=EN2510 [c.Link] MoCA Network Controller (Coax, PCIe interface) pci:v000017E6d00000027* ID_MODEL_FROM_DATABASE=EN2710 [c.Link] MoCA 2.0 Network Controller (Coax, PCIe interface) pci:v000017EE* ID_VENDOR_FROM_DATABASE=Connect Components Ltd pci:v000017F2* ID_VENDOR_FROM_DATABASE=Albatron Corp. pci:v000017F3* ID_VENDOR_FROM_DATABASE=RDC Semiconductor, Inc. pci:v000017F3d00001010* ID_MODEL_FROM_DATABASE=R1010 IDE Controller pci:v000017F3d00006020* ID_MODEL_FROM_DATABASE=R6020 North Bridge pci:v000017F3d00006021* ID_MODEL_FROM_DATABASE=R6021 Host Bridge pci:v000017F3d00006030* ID_MODEL_FROM_DATABASE=R6030 ISA Bridge pci:v000017F3d00006031* ID_MODEL_FROM_DATABASE=R6031 ISA Bridge pci:v000017F3d00006040* ID_MODEL_FROM_DATABASE=R6040 MAC Controller pci:v000017F3d00006060* ID_MODEL_FROM_DATABASE=R6060 USB 1.1 Controller pci:v000017F3d00006061* ID_MODEL_FROM_DATABASE=R6061 USB 2.0 Controller pci:v000017F7* ID_VENDOR_FROM_DATABASE=Topdek Semiconductor Inc. pci:v000017F9* ID_VENDOR_FROM_DATABASE=Gemtek Technology Co., Ltd pci:v000017FC* ID_VENDOR_FROM_DATABASE=IOGEAR, Inc. pci:v000017FE* ID_VENDOR_FROM_DATABASE=InProComm Inc. pci:v000017FEd00002120* ID_MODEL_FROM_DATABASE=IPN 2120 802.11b pci:v000017FEd00002120sv00001737sd00000020* ID_MODEL_FROM_DATABASE=IPN 2120 802.11b (WMP11 v4 802.11b Wireless-B PCI Adapter) pci:v000017FEd00002220* ID_MODEL_FROM_DATABASE=IPN 2220 802.11g pci:v000017FEd00002220sv00001468sd00000305* ID_MODEL_FROM_DATABASE=IPN 2220 802.11g (T60N871 802.11g Mini PCI Wireless Adapter) pci:v000017FEd00002220sv00001737sd00000029* ID_MODEL_FROM_DATABASE=IPN 2220 802.11g (WPC54G v4 802.11g Wireless-G Notebook Adapter) pci:v000017FF* ID_VENDOR_FROM_DATABASE=Benq Corporation pci:v00001800* ID_VENDOR_FROM_DATABASE=Qualcore Logic Inc. pci:v00001800d00001100* ID_MODEL_FROM_DATABASE=Nanospeed Trading Gateway pci:v00001803* ID_VENDOR_FROM_DATABASE=ProdaSafe GmbH pci:v00001805* ID_VENDOR_FROM_DATABASE=Euresys S.A. pci:v00001809* ID_VENDOR_FROM_DATABASE=Lumanate, Inc. pci:v00001813* ID_VENDOR_FROM_DATABASE=Ambient Technologies Inc pci:v00001813d00004000* ID_MODEL_FROM_DATABASE=HaM controllerless modem pci:v00001813d00004000sv000016BEsd00000001* ID_MODEL_FROM_DATABASE=HaM controllerless modem (V9x HAM Data Fax Modem) pci:v00001813d00004100* ID_MODEL_FROM_DATABASE=HaM plus Data Fax Modem pci:v00001813d00004100sv000016BEsd00000002* ID_MODEL_FROM_DATABASE=HaM plus Data Fax Modem (V9x HAM 1394) pci:v00001814* ID_VENDOR_FROM_DATABASE=Ralink corp. pci:v00001814d00000101* ID_MODEL_FROM_DATABASE=Wireless PCI Adapter RT2400 / RT2460 pci:v00001814d00000101sv00001043sd00000127* ID_MODEL_FROM_DATABASE=Wireless PCI Adapter RT2400 / RT2460 (WiFi-b add-on Card) pci:v00001814d00000101sv00001371sd00000010* ID_MODEL_FROM_DATABASE=Wireless PCI Adapter RT2400 / RT2460 (Minitar MNW2BPCI Wireless PCI Card) pci:v00001814d00000101sv00001462sd00006828* ID_MODEL_FROM_DATABASE=Wireless PCI Adapter RT2400 / RT2460 (PC11B2 (MS-6828) Wireless 11b PCI Card) pci:v00001814d00000200* ID_MODEL_FROM_DATABASE=RT2500 802.11g PCI [PC54G2] pci:v00001814d00000201* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg pci:v00001814d00000201sv00001043sd0000130F* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (WL-130g) pci:v00001814d00000201sv00001186sd00003C00* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (DWL-G650X Wireless 11g CardBus Adapter) pci:v00001814d00000201sv00001371sd0000001E* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (CWC-854 Wireless-G CardBus Adapter) pci:v00001814d00000201sv00001371sd0000001F* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (CWM-854 Wireless-G Mini PCI Adapter) pci:v00001814d00000201sv00001371sd00000020* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (CWP-854 Wireless-G PCI Adapter) pci:v00001814d00000201sv00001458sd0000E381* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (GN-WMKG 802.11b/g Wireless CardBus Adapter) pci:v00001814d00000201sv00001458sd0000E931* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (GN-WIKG 802.11b/g mini-PCI Adapter) pci:v00001814d00000201sv00001462sd00006833* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (Unknown 802.11g mini-PCI Adapter) pci:v00001814d00000201sv00001462sd00006835* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (Wireless 11G CardBus CB54G2) pci:v00001814d00000201sv00001737sd00000032* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (WMP54G v4.0 PCI Adapter) pci:v00001814d00000201sv00001799sd0000700A* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (F5D7000 v2000/v3000 Wireless G Desktop Card) pci:v00001814d00000201sv00001799sd0000701A* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (F5D7010 v2000/v3000 Wireless G Notebook Card) pci:v00001814d00000201sv00001814sd00002560* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg pci:v00001814d00000201sv0000182Dsd00009073* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (WL-115 Wireless Network PCI Adapter) pci:v00001814d00000201sv0000185Fsd000022A0* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (CN-WF513 Wireless Cardbus Adapter) pci:v00001814d00000201sv000018EBsd00005312* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (WL531P IEEE 802.11g PCI Card-EU) pci:v00001814d00000201sv00001948sd00003C00* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (C54RC v1 Wireless 11g CardBus Adapter) pci:v00001814d00000201sv00001948sd00003C01* ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (C54Ri v1 Wireless 11g PCI Adapter) pci:v00001814d00000300* ID_MODEL_FROM_DATABASE=Wireless Adapter Canyon CN-WF511 pci:v00001814d00000301* ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI pci:v00001814d00000301sv00001186sd00003C08* ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.E1)) pci:v00001814d00000301sv00001186sd00003C09* ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (DWL-G510 Rev C) pci:v00001814d00000301sv000013D1sd0000ABE3* ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (miniPCI Pluscom 802.11 a/b/g) pci:v00001814d00000301sv00001458sd0000E933* ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (GN-WI01GS) pci:v00001814d00000301sv00001458sd0000E934* ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (GN-WP01GS) pci:v00001814d00000301sv00001737sd00000055* ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (WMP54G v4.1) pci:v00001814d00000301sv00001799sd0000700E* ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (F5D7000 v6000 Wireless G Desktop Card) pci:v00001814d00000301sv00001799sd0000701E* ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (F5D7010 v6000 Wireless G Notebook Card) pci:v00001814d00000301sv000017F9sd00000012* ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (AWLC3026T 802.11g Wireless CardBus Adapter) pci:v00001814d00000301sv00001814sd00002561* ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (EW-7108PCg/EW-7128g) pci:v00001814d00000302* ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g pci:v00001814d00000302sv00001186sd00003A71* ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g (DWA-510 Wireless G Desktop Adapter) pci:v00001814d00000302sv00001186sd00003C08* ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g (AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.E2)) pci:v00001814d00000302sv00001186sd00003C09* ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g (AirPlus G DWL-G510 Wireless Network Adapter (Rev.C)) pci:v00001814d00000302sv00001462sd0000B834* ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g (PC54G3 Wireless 11g PCI Card) pci:v00001814d00000302sv00001948sd00003C23* ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g (C54RC v2 Wireless 11g CardBus Adapter) pci:v00001814d00000302sv00001948sd00003C24* ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g (C54Ri v2 Wireless 11g PCI Adapter) pci:v00001814d00000401* ID_MODEL_FROM_DATABASE=RT2600 802.11 MIMO pci:v00001814d00000401sv00001737sd00000052* ID_MODEL_FROM_DATABASE=RT2600 802.11 MIMO (WPC54GR v1 802.11g Wireless-G Notebook Adapter with RangeBooster) pci:v00001814d00000401sv000017F9sd00000011* ID_MODEL_FROM_DATABASE=RT2600 802.11 MIMO (WPCR-137G 802.11bg Wireless CardBus Adapter) pci:v00001814d00000401sv000017F9sd00000016* ID_MODEL_FROM_DATABASE=RT2600 802.11 MIMO (WPIR-119GH 802.11bg Wireless Desktop Adapter) pci:v00001814d00000601* ID_MODEL_FROM_DATABASE=RT2800 802.11n PCI pci:v00001814d00000601sv00001799sd0000801C* ID_MODEL_FROM_DATABASE=RT2800 802.11n PCI (F5D8011 v3 802.11n N1 Wireless Notebook Card) pci:v00001814d00000601sv0000187Esd00003412* ID_MODEL_FROM_DATABASE=RT2800 802.11n PCI (NWD-310N 802.11n Wireless PCI Adapter) pci:v00001814d00000681* ID_MODEL_FROM_DATABASE=RT2890 Wireless 802.11n PCIe pci:v00001814d00000681sv00001458sd0000E939* ID_MODEL_FROM_DATABASE=RT2890 Wireless 802.11n PCIe (GN-WS30N-RH 802.11bgn Mini PCIe Card) pci:v00001814d00000701* ID_MODEL_FROM_DATABASE=RT2760 Wireless 802.11n 1T/2R pci:v00001814d00000701sv00001737sd00000074* ID_MODEL_FROM_DATABASE=RT2760 Wireless 802.11n 1T/2R (WMP110 v2 802.11n RangePlus Wireless PCI Adapter) pci:v00001814d00000781* ID_MODEL_FROM_DATABASE=RT2790 Wireless 802.11n 1T/2R PCIe pci:v00001814d00000781sv00001814sd00002790* ID_MODEL_FROM_DATABASE=RT2790 Wireless 802.11n 1T/2R PCIe pci:v00001814d00003060* ID_MODEL_FROM_DATABASE=RT3060 Wireless 802.11n 1T/1R pci:v00001814d00003060sv00001186sd00003C04* ID_MODEL_FROM_DATABASE=RT3060 Wireless 802.11n 1T/1R (DWA-525 Wireless N 150 Desktop Adapter (rev.A1)) pci:v00001814d00003062* ID_MODEL_FROM_DATABASE=RT3062 Wireless 802.11n 2T/2R pci:v00001814d00003090* ID_MODEL_FROM_DATABASE=RT3090 Wireless 802.11n 1T/1R PCIe pci:v00001814d00003090sv000013BDsd00001057* ID_MODEL_FROM_DATABASE=RT3090 Wireless 802.11n 1T/1R PCIe (GN-WS32L-RH Half-size Mini PCIe Card) pci:v00001814d00003091* ID_MODEL_FROM_DATABASE=RT3091 Wireless 802.11n 1T/2R PCIe pci:v00001814d00003092* ID_MODEL_FROM_DATABASE=RT3092 Wireless 802.11n 2T/2R PCIe pci:v00001814d00003290* ID_MODEL_FROM_DATABASE=RT3290 Wireless 802.11n 1T/1R PCIe pci:v00001814d00003290sv0000103Csd000018EC* ID_MODEL_FROM_DATABASE=RT3290 Wireless 802.11n 1T/1R PCIe (Ralink RT3290LE 802.11bgn 1x1 Wi-Fi and Bluetooth 4.0 Combo Adapter) pci:v00001814d00003298* ID_MODEL_FROM_DATABASE=RT3290 Bluetooth pci:v00001814d00003298sv0000103Csd000018EC* ID_MODEL_FROM_DATABASE=RT3290 Bluetooth (Ralink RT3290LE 802.11bgn 1x1 Wi-Fi and Bluetooth 4.0 Combo Adapter) pci:v00001814d00003592* ID_MODEL_FROM_DATABASE=RT3592 Wireless 802.11abgn 2T/2R PCIe pci:v00001814d0000359F* ID_MODEL_FROM_DATABASE=RT3592 PCIe Wireless Network Adapter pci:v00001814d00005360* ID_MODEL_FROM_DATABASE=RT5360 Wireless 802.11n 1T/1R pci:v00001814d00005360sv00001186sd00003C05* ID_MODEL_FROM_DATABASE=RT5360 Wireless 802.11n 1T/1R (DWA-525 Wireless N 150 Desktop Adapter (rev.A2)) pci:v00001814d00005360sv000020F4sd0000703A* ID_MODEL_FROM_DATABASE=RT5360 Wireless 802.11n 1T/1R (TEW-703PI N150 Wireless PCI Adapter) pci:v00001814d00005362* ID_MODEL_FROM_DATABASE=RT5362 PCI 802.11n Wireless Network Adapter pci:v00001814d00005390* ID_MODEL_FROM_DATABASE=RT5390 Wireless 802.11n 1T/1R PCIe pci:v00001814d00005390sv0000103Csd00001636* ID_MODEL_FROM_DATABASE=RT5390 Wireless 802.11n 1T/1R PCIe (U98Z077.00 Half-size Mini PCIe Card) pci:v00001814d00005392* ID_MODEL_FROM_DATABASE=RT5392 PCIe Wireless Network Adapter pci:v00001814d0000539B* ID_MODEL_FROM_DATABASE=RT5390R 802.11bgn PCIe Wireless Network Adapter pci:v00001814d0000539F* ID_MODEL_FROM_DATABASE=RT5390 [802.11 b/g/n 1T1R G-band PCI Express Single Chip] pci:v00001814d0000539Fsv0000103Csd00001637* ID_MODEL_FROM_DATABASE=RT5390 [802.11 b/g/n 1T1R G-band PCI Express Single Chip] (Pavilion DM1Z-3000 PCIe wireless card) pci:v00001814d00005592* ID_MODEL_FROM_DATABASE=RT5592 PCIe Wireless Network Adapter pci:v00001814d0000E932* ID_MODEL_FROM_DATABASE=RT2560F 802.11 b/g PCI pci:v00001815* ID_VENDOR_FROM_DATABASE=Devolo AG pci:v00001820* ID_VENDOR_FROM_DATABASE=InfiniCon Systems Inc. pci:v00001822* ID_VENDOR_FROM_DATABASE=Twinhan Technology Co. Ltd pci:v00001822d00004E35* ID_MODEL_FROM_DATABASE=Mantis DTV PCI Bridge Controller [Ver 1.0] pci:v0000182D* ID_VENDOR_FROM_DATABASE=SiteCom Europe BV pci:v0000182Dd00003069* ID_MODEL_FROM_DATABASE=ISDN PCI DC-105V2 pci:v0000182Dd00009790* ID_MODEL_FROM_DATABASE=WL-121 Wireless Network Adapter 100g+ [Ver.3] pci:v0000182E* ID_VENDOR_FROM_DATABASE=Raza Microelectronics, Inc. pci:v0000182Ed00000008* ID_MODEL_FROM_DATABASE=XLR516 Processor pci:v0000182F* ID_VENDOR_FROM_DATABASE=Broadcom pci:v0000182Fd0000000B* ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] SATA (RAID Mode) pci:v00001830* ID_VENDOR_FROM_DATABASE=Credence Systems Corporation pci:v0000183B* ID_VENDOR_FROM_DATABASE=MikroM GmbH pci:v0000183Bd000008A7* ID_MODEL_FROM_DATABASE=MVC100 DVI pci:v0000183Bd000008A8* ID_MODEL_FROM_DATABASE=MVC101 SDI pci:v0000183Bd000008A9* ID_MODEL_FROM_DATABASE=MVC102 DVI+Audio pci:v0000183Bd000008B0* ID_MODEL_FROM_DATABASE=MVC200-DC pci:v00001846* ID_VENDOR_FROM_DATABASE=Alcatel-Lucent pci:v00001849* ID_VENDOR_FROM_DATABASE=ASRock Incorporation pci:v0000184A* ID_VENDOR_FROM_DATABASE=Thales Computers pci:v0000184Ad00001100* ID_MODEL_FROM_DATABASE=MAX II cPLD pci:v00001850* ID_VENDOR_FROM_DATABASE=Advantest Corporation pci:v00001850d00000048* ID_MODEL_FROM_DATABASE=EK220-66401 Computer Interface Card pci:v00001851* ID_VENDOR_FROM_DATABASE=Microtune, Inc. pci:v00001852* ID_VENDOR_FROM_DATABASE=Anritsu Corp. pci:v00001853* ID_VENDOR_FROM_DATABASE=SMSC Automotive Infotainment System Group pci:v00001854* ID_VENDOR_FROM_DATABASE=LG Electronics, Inc. pci:v0000185B* ID_VENDOR_FROM_DATABASE=Compro Technology, Inc. pci:v0000185Bd00001489* ID_MODEL_FROM_DATABASE=VideoMate Vista T100 pci:v0000185F* ID_VENDOR_FROM_DATABASE=Wistron NeWeb Corp. pci:v00001864* ID_VENDOR_FROM_DATABASE=SilverBack pci:v00001864d00002110* ID_MODEL_FROM_DATABASE=ISNAP 2110 pci:v00001867* ID_VENDOR_FROM_DATABASE=Topspin Communications pci:v00001867d00005A44* ID_MODEL_FROM_DATABASE=MT23108 InfiniHost HCA pci:v00001867d00005A45* ID_MODEL_FROM_DATABASE=MT23108 InfiniHost HCA flash recovery pci:v00001867d00005A46* ID_MODEL_FROM_DATABASE=MT23108 InfiniHost HCA bridge pci:v00001867d00006278* ID_MODEL_FROM_DATABASE=MT25208 InfiniHost III Ex (Tavor compatibility mode) pci:v00001867d00006282* ID_MODEL_FROM_DATABASE=MT25208 InfiniHost III Ex pci:v0000186C* ID_VENDOR_FROM_DATABASE=Humusoft, s.r.o. pci:v0000186Cd00000612* ID_MODEL_FROM_DATABASE=AD612 Data Acquisition Device pci:v0000186Cd00000614* ID_MODEL_FROM_DATABASE=MF614 Multifunction I/O Card pci:v0000186Cd00000622* ID_MODEL_FROM_DATABASE=AD622 Data Acquisition Device pci:v0000186Cd00000624* ID_MODEL_FROM_DATABASE=MF624 Multifunction I/O PCI Card pci:v0000186Cd00000625* ID_MODEL_FROM_DATABASE=MF625 3-phase Motor Driver pci:v0000186Cd00000634* ID_MODEL_FROM_DATABASE=MF634 Multifunction I/O PCIe Card pci:v0000186F* ID_VENDOR_FROM_DATABASE=WiNRADiO Communications pci:v00001876* ID_VENDOR_FROM_DATABASE=L-3 Communications pci:v00001876d0000A101* ID_MODEL_FROM_DATABASE=VigraWATCH PCI pci:v00001876d0000A102* ID_MODEL_FROM_DATABASE=VigraWATCH PMC pci:v00001876d0000A103* ID_MODEL_FROM_DATABASE=Vigra I/O pci:v0000187E* ID_VENDOR_FROM_DATABASE=ZyXEL Communications Corporation pci:v0000187Ed00003403* ID_MODEL_FROM_DATABASE=ZyAir G-110 802.11g pci:v0000187Ed0000340E* ID_MODEL_FROM_DATABASE=M-302 802.11g XtremeMIMO pci:v00001885* ID_VENDOR_FROM_DATABASE=Avvida Systems Inc. pci:v00001888* ID_VENDOR_FROM_DATABASE=Varisys Ltd pci:v00001888d00000301* ID_MODEL_FROM_DATABASE=VMFX1 FPGA PMC module pci:v00001888d00000601* ID_MODEL_FROM_DATABASE=VSM2 dual PMC carrier pci:v00001888d00000710* ID_MODEL_FROM_DATABASE=VS14x series PowerPC PCI board pci:v00001888d00000720* ID_MODEL_FROM_DATABASE=VS24x series PowerPC PCI board pci:v0000188A* ID_VENDOR_FROM_DATABASE=Ample Communications, Inc pci:v00001890* ID_VENDOR_FROM_DATABASE=Egenera, Inc. pci:v00001894* ID_VENDOR_FROM_DATABASE=KNC One pci:v00001896* ID_VENDOR_FROM_DATABASE=B&B Electronics Manufacturing Company, Inc. pci:v00001896d00004202* ID_MODEL_FROM_DATABASE=MIport 3PCIU2 2-port Serial pci:v00001896d00004204* ID_MODEL_FROM_DATABASE=MIport 3PCIU4 4-port Serial pci:v00001896d00004208* ID_MODEL_FROM_DATABASE=MIport 3PCIU8 8-port Serial pci:v00001896d00004211* ID_MODEL_FROM_DATABASE=MIport 3PCIOU1 1-port Isolated Serial pci:v00001896d00004212* ID_MODEL_FROM_DATABASE=MIport 3PCIOU2 2-port Isolated Serial pci:v00001896d00004214* ID_MODEL_FROM_DATABASE=MIport 3PCIOU4 4-port Isolated Serial pci:v00001896d0000BB10* ID_MODEL_FROM_DATABASE=3PCI2 2-Port Serial pci:v00001896d0000BB11* ID_MODEL_FROM_DATABASE=3PCIO1 1-Port Isolated Serial pci:v00001897* ID_VENDOR_FROM_DATABASE=AMtek pci:v000018A1* ID_VENDOR_FROM_DATABASE=Astute Networks Inc. pci:v000018A2* ID_VENDOR_FROM_DATABASE=Stretch Inc. pci:v000018A2d00000002* ID_MODEL_FROM_DATABASE=VRC6016 16-Channel PCIe DVR Card pci:v000018A3* ID_VENDOR_FROM_DATABASE=AT&T pci:v000018AC* ID_VENDOR_FROM_DATABASE=DViCO Corporation pci:v000018ACd0000D500* ID_MODEL_FROM_DATABASE=FusionHDTV 5 pci:v000018ACd0000D800* ID_MODEL_FROM_DATABASE=FusionHDTV 3 Gold pci:v000018ACd0000D810* ID_MODEL_FROM_DATABASE=FusionHDTV 3 Gold-Q pci:v000018ACd0000D820* ID_MODEL_FROM_DATABASE=FusionHDTV 3 Gold-T pci:v000018ACd0000DB30* ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T Pro pci:v000018ACd0000DB40* ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T Hybrid pci:v000018ACd0000DB78* ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T Dual Express pci:v000018B8* ID_VENDOR_FROM_DATABASE=Ammasso pci:v000018B8d0000B001* ID_MODEL_FROM_DATABASE=AMSO 1100 iWARP/RDMA Gigabit Ethernet Coprocessor pci:v000018BC* ID_VENDOR_FROM_DATABASE=GeCube Technologies, Inc. pci:v000018C3* ID_VENDOR_FROM_DATABASE=Micronas Semiconductor Holding AG pci:v000018C3d00000720* ID_MODEL_FROM_DATABASE=nGene PCI-Express Multimedia Controller pci:v000018C3d00000720sv000007CAsd0000032E* ID_MODEL_FROM_DATABASE=nGene PCI-Express Multimedia Controller (Hybrid M779 PCI-E) pci:v000018C8* ID_VENDOR_FROM_DATABASE=Cray Inc pci:v000018C9* ID_VENDOR_FROM_DATABASE=ARVOO Engineering BV pci:v000018CA* ID_VENDOR_FROM_DATABASE=XGI Technology Inc. (eXtreme Graphics Innovation) pci:v000018CAd00000020* ID_MODEL_FROM_DATABASE=Z7/Z9 (XG20 core) pci:v000018CAd00000021* ID_MODEL_FROM_DATABASE=Z9s/Z9m (XG21 core) pci:v000018CAd00000027* ID_MODEL_FROM_DATABASE=Z11/Z11M pci:v000018CAd00000040* ID_MODEL_FROM_DATABASE=Volari V3XT/V5/V8 pci:v000018CAd00000047* ID_MODEL_FROM_DATABASE=Volari 8300 (chip: XP10, codename: XG47) pci:v000018D2* ID_VENDOR_FROM_DATABASE=Sitecom Europe BV (Wrong ID) pci:v000018D2d00003069* ID_MODEL_FROM_DATABASE=DC-105v2 ISDN controller pci:v000018D8* ID_VENDOR_FROM_DATABASE=Dialogue Technology Corp. pci:v000018DD* ID_VENDOR_FROM_DATABASE=Artimi Inc pci:v000018DDd00004C6F* ID_MODEL_FROM_DATABASE=Artimi RTMI-100 UWB adapter pci:v000018DF* ID_VENDOR_FROM_DATABASE=LeWiz Communications pci:v000018E6* ID_VENDOR_FROM_DATABASE=MPL AG pci:v000018E6d00000001* ID_MODEL_FROM_DATABASE=OSCI [Octal Serial Communication Interface] pci:v000018EB* ID_VENDOR_FROM_DATABASE=Advance Multimedia Internet Technology, Inc. pci:v000018EC* ID_VENDOR_FROM_DATABASE=Cesnet, z.s.p.o. pci:v000018ECd00006D05* ID_MODEL_FROM_DATABASE=ML555 pci:v000018ECd00006D05sv000018ECsd00000100* ID_MODEL_FROM_DATABASE=ML555 (NIC (ethernet interfaces)) pci:v000018ECd00006D05sv000018ECsd00000200* ID_MODEL_FROM_DATABASE=ML555 (NIC (szedata2) 4x1G) pci:v000018ECd00006D05sv000018ECsd00000201* ID_MODEL_FROM_DATABASE=ML555 (NIC (szedata2) 2x10G) pci:v000018ECd00006D05sv000018ECsd00000300* ID_MODEL_FROM_DATABASE=ML555 (NIFIC (szedata2) 4x1G) pci:v000018ECd00006D05sv000018ECsd00000302* ID_MODEL_FROM_DATABASE=ML555 (NIFIC (szedata2) 2x10G) pci:v000018ECd00006D05sv000018ECsd00004200* ID_MODEL_FROM_DATABASE=ML555 (Flexible FlowMon (szedata2) 1x10G) pci:v000018ECd00006D05sv000018ECsd0000FF00* ID_MODEL_FROM_DATABASE=ML555 (Testing design) pci:v000018ECd00006D05sv000018ECsd0000FF01* ID_MODEL_FROM_DATABASE=ML555 (Boot design) pci:v000018ECd0000C006* ID_MODEL_FROM_DATABASE=COMBO6 pci:v000018ECd0000C006sv000018ECsd0000D001* ID_MODEL_FROM_DATABASE=COMBO6 (COMBO-4MTX) pci:v000018ECd0000C006sv000018ECsd0000D002* ID_MODEL_FROM_DATABASE=COMBO6 (COMBO-4SFP) pci:v000018ECd0000C006sv000018ECsd0000D003* ID_MODEL_FROM_DATABASE=COMBO6 (COMBO-4SFPRO) pci:v000018ECd0000C006sv000018ECsd0000D004* ID_MODEL_FROM_DATABASE=COMBO6 (COMBO-2XFP) pci:v000018ECd0000C032* ID_MODEL_FROM_DATABASE=COMBO-LXT110 pci:v000018ECd0000C032sv000018ECsd00000100* ID_MODEL_FROM_DATABASE=COMBO-LXT110 (NIC (ethernet interfaces)) pci:v000018ECd0000C032sv000018ECsd00000200* ID_MODEL_FROM_DATABASE=COMBO-LXT110 (NIC (szedata2) 4x1G) pci:v000018ECd0000C032sv000018ECsd00000201* ID_MODEL_FROM_DATABASE=COMBO-LXT110 (NIC (szedata2) 2x10G) pci:v000018ECd0000C032sv000018ECsd00000300* ID_MODEL_FROM_DATABASE=COMBO-LXT110 (NIFIC (szedata2) 4x1G) pci:v000018ECd0000C032sv000018ECsd00000302* ID_MODEL_FROM_DATABASE=COMBO-LXT110 (NIFIC (szedata2) 2x10G) pci:v000018ECd0000C032sv000018ECsd00004200* ID_MODEL_FROM_DATABASE=COMBO-LXT110 (Flexible FlowMon (szedata2) 1x10G) pci:v000018ECd0000C032sv000018ECsd0000FF00* ID_MODEL_FROM_DATABASE=COMBO-LXT110 (Testing design) pci:v000018ECd0000C032sv000018ECsd0000FF01* ID_MODEL_FROM_DATABASE=COMBO-LXT110 (Boot design) pci:v000018ECd0000C045* ID_MODEL_FROM_DATABASE=COMBO6E pci:v000018ECd0000C050* ID_MODEL_FROM_DATABASE=COMBO-PTM pci:v000018ECd0000C058* ID_MODEL_FROM_DATABASE=COMBO6X pci:v000018ECd0000C058sv000018ECsd0000D001* ID_MODEL_FROM_DATABASE=COMBO6X (COMBO-4MTX) pci:v000018ECd0000C058sv000018ECsd0000D002* ID_MODEL_FROM_DATABASE=COMBO6X (COMBO-4SFP) pci:v000018ECd0000C058sv000018ECsd0000D003* ID_MODEL_FROM_DATABASE=COMBO6X (COMBO-4SFPRO) pci:v000018ECd0000C058sv000018ECsd0000D004* ID_MODEL_FROM_DATABASE=COMBO6X (COMBO-2XFP) pci:v000018ECd0000C132* ID_MODEL_FROM_DATABASE=COMBO-LXT155 pci:v000018ECd0000C132sv000018ECsd00000100* ID_MODEL_FROM_DATABASE=COMBO-LXT155 (NIC (ethernet interfaces)) pci:v000018ECd0000C132sv000018ECsd00000200* ID_MODEL_FROM_DATABASE=COMBO-LXT155 (NIC (szedata2) 4x1G) pci:v000018ECd0000C132sv000018ECsd00000201* ID_MODEL_FROM_DATABASE=COMBO-LXT155 (NIC (szedata2) 2x10G) pci:v000018ECd0000C132sv000018ECsd00000300* ID_MODEL_FROM_DATABASE=COMBO-LXT155 (NIFIC (szedata2) 4x1G) pci:v000018ECd0000C132sv000018ECsd00000302* ID_MODEL_FROM_DATABASE=COMBO-LXT155 (NIFIC (szedata2) 2x10G) pci:v000018ECd0000C132sv000018ECsd00004200* ID_MODEL_FROM_DATABASE=COMBO-LXT155 (Flexible FlowMon (szedata2) 1x10G) pci:v000018ECd0000C132sv000018ECsd0000FF00* ID_MODEL_FROM_DATABASE=COMBO-LXT155 (Testing design) pci:v000018ECd0000C132sv000018ECsd0000FF01* ID_MODEL_FROM_DATABASE=COMBO-LXT155 (Boot design) pci:v000018ECd0000C232* ID_MODEL_FROM_DATABASE=COMBO-FXT100 pci:v000018ECd0000C232sv000018ECsd00000100* ID_MODEL_FROM_DATABASE=COMBO-FXT100 (NIC (ethernet interfaces)) pci:v000018ECd0000C232sv000018ECsd00000200* ID_MODEL_FROM_DATABASE=COMBO-FXT100 (NIC (szedata2) 4x1G) pci:v000018ECd0000C232sv000018ECsd00000201* ID_MODEL_FROM_DATABASE=COMBO-FXT100 (NIC (szedata2) 2x10G) pci:v000018ECd0000C232sv000018ECsd00000300* ID_MODEL_FROM_DATABASE=COMBO-FXT100 (NIFIC (szedata2) 4x1G) pci:v000018ECd0000C232sv000018ECsd00000302* ID_MODEL_FROM_DATABASE=COMBO-FXT100 (NIFIC (szedata2) 2x10G) pci:v000018ECd0000C232sv000018ECsd00004200* ID_MODEL_FROM_DATABASE=COMBO-FXT100 (Flexible FlowMon (szedata2) 1x10G) pci:v000018ECd0000C232sv000018ECsd0000FF00* ID_MODEL_FROM_DATABASE=COMBO-FXT100 (Testing design) pci:v000018ECd0000C232sv000018ECsd0000FF01* ID_MODEL_FROM_DATABASE=COMBO-FXT100 (Boot design) pci:v000018EE* ID_VENDOR_FROM_DATABASE=Chenming Mold Ind. Corp. pci:v000018F1* ID_VENDOR_FROM_DATABASE=Spectrum GmbH pci:v000018F4* ID_VENDOR_FROM_DATABASE=Napatech A/S pci:v000018F4d00000031* ID_MODEL_FROM_DATABASE=NT20X Network Adapter pci:v000018F4d00000051* ID_MODEL_FROM_DATABASE=NT20X Capture Card pci:v000018F4d00000061* ID_MODEL_FROM_DATABASE=NT20E Capture Card pci:v000018F4d00000064* ID_MODEL_FROM_DATABASE=NT20E Inline Card pci:v000018F4d00000071* ID_MODEL_FROM_DATABASE=NT4E Capture Card pci:v000018F4d00000074* ID_MODEL_FROM_DATABASE=NT4E Inline Card pci:v000018F4d00000081* ID_MODEL_FROM_DATABASE=NT4E 4-port Expansion Card pci:v000018F4d00000091* ID_MODEL_FROM_DATABASE=NT20X Capture Card [New Rev] pci:v000018F4d000000A1* ID_MODEL_FROM_DATABASE=NT4E-STD Capture Card pci:v000018F4d000000A4* ID_MODEL_FROM_DATABASE=NT4E-STD Inline Card pci:v000018F4d000000B1* ID_MODEL_FROM_DATABASE=NTBPE Optical Bypass Adapter pci:v000018F4d000000C5* ID_MODEL_FROM_DATABASE=NT20E2 Network Adapter 2x10Gb pci:v000018F4d000000D5* ID_MODEL_FROM_DATABASE=NT40E2-4 Network Adapter 4x10Gb pci:v000018F4d000000E5* ID_MODEL_FROM_DATABASE=NT40E2-1 Network Adapter 1x40Gb pci:v000018F4d000000F5* ID_MODEL_FROM_DATABASE=NT4E2-4T-BP Network Adapter 4x1Gb with Electrical Bypass pci:v000018F4d00000105* ID_MODEL_FROM_DATABASE=NT4E2-4-PTP Network Adapter 4x1Gb pci:v000018F4d00000115* ID_MODEL_FROM_DATABASE=NT20E2-PTP Network Adapter 2x10Gb pci:v000018F4d00000125* ID_MODEL_FROM_DATABASE=NT4E2-4-PTP Network Adapter 4x1Gb pci:v000018F4d00000135* ID_MODEL_FROM_DATABASE=NT20E2-PTP Network Adapter 2x10Gb pci:v000018F4d00000145* ID_MODEL_FROM_DATABASE=NT40E3-4-PTP Network Adapter 4x10Gb pci:v000018F4d00000155* ID_MODEL_FROM_DATABASE=NT100E3-1-PTP Network Adapter 1x100Gb pci:v000018F4d00000175* ID_MODEL_FROM_DATABASE=NT20E3-2-PTP Network Adapter 2x10Gb pci:v000018F6* ID_VENDOR_FROM_DATABASE=NextIO pci:v000018F6d00001000* ID_MODEL_FROM_DATABASE=[Nexsis] Switch Virtual P2P PCIe Bridge pci:v000018F6d00001001* ID_MODEL_FROM_DATABASE=[Texsis] Switch Virtual P2P PCIe Bridge pci:v000018F6d00001050* ID_MODEL_FROM_DATABASE=[Nexsis] Switch Virtual P2P PCI Bridge pci:v000018F6d00001051* ID_MODEL_FROM_DATABASE=[Texsis] Switch Virtual P2P PCI Bridge pci:v000018F6d00002000* ID_MODEL_FROM_DATABASE=[Nexsis] Switch Integrated Mgmt. Endpoint pci:v000018F6d00002001* ID_MODEL_FROM_DATABASE=[Texsis] Switch Integrated Mgmt. Endpoint pci:v000018F7* ID_VENDOR_FROM_DATABASE=Commtech, Inc. pci:v000018F7d00000001* ID_MODEL_FROM_DATABASE=ESCC-PCI-335 Serial PCI Adapter [Fastcom] pci:v000018F7d00000002* ID_MODEL_FROM_DATABASE=422/4-PCI-335 Serial PCI Adapter [Fastcom] pci:v000018F7d00000003* ID_MODEL_FROM_DATABASE=232/4-1M-PCI Serial PCI Adapter [Fastcom] pci:v000018F7d00000004* ID_MODEL_FROM_DATABASE=422/2-PCI-335 Serial PCI Adapter [Fastcom] pci:v000018F7d00000005* ID_MODEL_FROM_DATABASE=IGESCC-PCI-ISO/1 Serial PCI Adapter [Fastcom] pci:v000018F7d0000000A* ID_MODEL_FROM_DATABASE=232/4-PCI-335 Serial PCI Adapter [Fastcom] pci:v000018F7d0000000B* ID_MODEL_FROM_DATABASE=232/8-PCI-335 Serial PCI Adapter [Fastcom] pci:v000018F7d0000000F* ID_MODEL_FROM_DATABASE=FSCC Serial PCI Adapter [Fastcom] pci:v000018F7d00000010* ID_MODEL_FROM_DATABASE=GSCC Serial PCI Adapter [Fastcom] pci:v000018F7d00000011* ID_MODEL_FROM_DATABASE=QSSB Serial PCI Adapter [Fastcom] pci:v000018F7d00000014* ID_MODEL_FROM_DATABASE=SuperFSCC Serial PCI Adapter [Fastcom] pci:v000018F7d00000015* ID_MODEL_FROM_DATABASE=SuperFSCC-104-LVDS Serial PC/104+ Adapter [Fastcom] pci:v000018F7d00000016* ID_MODEL_FROM_DATABASE=FSCC-232 RS-232 Serial PCI Adapter [Fastcom] pci:v000018F7d00000017* ID_MODEL_FROM_DATABASE=SuperFSCC-104 Serial PC/104+ Adapter [Fastcom] pci:v000018F7d00000018* ID_MODEL_FROM_DATABASE=SuperFSCC/4 Serial PCI Adapter [Fastcom] pci:v000018F7d00000019* ID_MODEL_FROM_DATABASE=SuperFSCC Serial PCI Adapter [Fastcom] pci:v000018F7d0000001A* ID_MODEL_FROM_DATABASE=SuperFSCC-LVDS Serial PCI Adapter [Fastcom] pci:v000018F7d0000001B* ID_MODEL_FROM_DATABASE=FSCC/4 Serial PCI Adapter [Fastcom] pci:v000018F7d0000001C* ID_MODEL_FROM_DATABASE=SuperFSCC/4-LVDS Serial PCI Adapter [Fastcom] pci:v000018F7d0000001D* ID_MODEL_FROM_DATABASE=FSCC Serial PCI Adapter [Fastcom] pci:v000018F7d0000001E* ID_MODEL_FROM_DATABASE=SuperFSCC/4 Serial PCIe Adapter [Fastcom] pci:v000018F7d0000001F* ID_MODEL_FROM_DATABASE=SuperFSCC/4 Serial cPCI Adapter [Fastcom] pci:v000018F7d00000020* ID_MODEL_FROM_DATABASE=422/4-PCIe Serial PCIe Adapter [Fastcom] pci:v000018F7d00000021* ID_MODEL_FROM_DATABASE=422/8-PCIe Serial PCIe Adapter [Fastcom] pci:v000018F7d00000022* ID_MODEL_FROM_DATABASE=SuperFSCC/4-LVDS Serial PCIe Adapter [Fastcom] pci:v000018F7d00000023* ID_MODEL_FROM_DATABASE=SuperFSCC/4 Serial cPCI Adapter [Fastcom] pci:v000018F7d00000025* ID_MODEL_FROM_DATABASE=SuperFSCC/4-LVDS Serial PCI Adapter [Fastcom] pci:v000018F7d00000026* ID_MODEL_FROM_DATABASE=SuperFSCC-LVDS Serial PCI Adapter [Fastcom] pci:v000018F7d00000027* ID_MODEL_FROM_DATABASE=FSCC/4 Serial PCIe Adapter [Fastcom] pci:v000018FB* ID_VENDOR_FROM_DATABASE=Resilience Corporation pci:v00001904* ID_VENDOR_FROM_DATABASE=Hangzhou Silan Microelectronics Co., Ltd. pci:v00001904d00002031* ID_MODEL_FROM_DATABASE=SC92031 PCI Fast Ethernet Adapter pci:v00001904d00008139* ID_MODEL_FROM_DATABASE=RTL8139D [Realtek] PCI 10/100BaseTX ethernet adaptor pci:v00001905* ID_VENDOR_FROM_DATABASE=Micronas USA, Inc. pci:v00001912* ID_VENDOR_FROM_DATABASE=Renesas Technology Corp. pci:v00001912d00000002* ID_MODEL_FROM_DATABASE=SH7780 PCI Controller (PCIC) pci:v00001912d00000011* ID_MODEL_FROM_DATABASE=SH7757 PCIe End-Point [PBI] pci:v00001912d00000012* ID_MODEL_FROM_DATABASE=SH7757 PCIe-PCI Bridge [PPB] pci:v00001912d00000013* ID_MODEL_FROM_DATABASE=SH7757 PCIe Switch [PS] pci:v00001912d00000014* ID_MODEL_FROM_DATABASE=uPD720201 USB 3.0 Host Controller pci:v00001912d00000015* ID_MODEL_FROM_DATABASE=uPD720202 USB 3.0 Host Controller pci:v00001912d0000001A* ID_MODEL_FROM_DATABASE=SH7758 PCIe-PCI Bridge [PPB] pci:v00001912d0000001B* ID_MODEL_FROM_DATABASE=SH7758 PCIe End-Point [PBI] pci:v00001912d0000001D* ID_MODEL_FROM_DATABASE=SH7758 PCIe Switch [PS] pci:v00001919* ID_VENDOR_FROM_DATABASE=Soltek Computer Inc. pci:v00001923* ID_VENDOR_FROM_DATABASE=Sangoma Technologies Corp. pci:v00001923d00000040* ID_MODEL_FROM_DATABASE=A200/Remora FXO/FXS Analog AFT card pci:v00001923d00000100* ID_MODEL_FROM_DATABASE=A104d QUAD T1/E1 AFT card pci:v00001923d00000300* ID_MODEL_FROM_DATABASE=A101 single-port T1/E1 pci:v00001923d00000400* ID_MODEL_FROM_DATABASE=A104u Quad T1/E1 AFT pci:v00001924* ID_VENDOR_FROM_DATABASE=Solarflare Communications pci:v00001924d00000703* ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] pci:v00001924d00000703sv000010B8sd00000102* ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SMC10GPCIe-10BT (A2) [TigerCard]) pci:v00001924d00000703sv000010B8sd00000103* ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SMC10GPCIe-10BT (A3) [TigerCard]) pci:v00001924d00000703sv000010B8sd00000201* ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SMC10GPCIe-XFP (A1) [TigerCard]) pci:v00001924d00000703sv00001924sd00000101* ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4001-A1) pci:v00001924d00000703sv00001924sd00000102* ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4001-A2) pci:v00001924d00000703sv00001924sd00000103* ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4001-A3) pci:v00001924d00000703sv00001924sd00000201* ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4002-A1) pci:v00001924d00000703sv00001924sd00000301* ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4003-A1) pci:v00001924d00000703sv00001924sd00000302* ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4003-A2) pci:v00001924d00000703sv00001924sd00000303* ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4003-A3) pci:v00001924d00000703sv00001924sd00000304* ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4003-A4) pci:v00001924d00000703sv00001924sd00000500* ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4005-A0) pci:v00001924d00000710* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] pci:v00001924d00000710sv000010B8sd00000103* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SMC10GPCIe-10BT (A3) [TigerCard]) pci:v00001924d00000710sv000010B8sd00000201* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SMC10GPCIe-XFP (A1) [TigerCard]) pci:v00001924d00000710sv00001924sd00000102* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4001-A2) pci:v00001924d00000710sv00001924sd00000103* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4001-A3) pci:v00001924d00000710sv00001924sd00000201* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4002-A1) pci:v00001924d00000710sv00001924sd00000302* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4003-A2) pci:v00001924d00000710sv00001924sd00000303* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4003-A3) pci:v00001924d00000710sv00001924sd00000304* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4003-A4) pci:v00001924d00000710sv00001924sd00000500* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4005-A0) pci:v00001924d00000710sv00001924sd00005102* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFN4111T-A2) pci:v00001924d00000710sv00001924sd00005103* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFN4111T-R3) pci:v00001924d00000710sv00001924sd00005104* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFN4111T-R4) pci:v00001924d00000710sv00001924sd00005105* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFN4111T-R5) pci:v00001924d00000710sv00001924sd00005201* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFN4112F-R1) pci:v00001924d00000710sv00001924sd00005202* ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFN4112F-R2) pci:v00001924d00000803* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] pci:v00001924d00000803sv00001014sd00000478* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (2-port 10GbE Low-Latency (R7)) pci:v00001924d00000803sv00001014sd00000479* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (2-port 10GbE OpenOnload (R7)) pci:v00001924d00000803sv00001014sd000004A7* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (Solarflare 10Gb Low-latency Dual-port HBA (R7)) pci:v00001924d00000803sv00001014sd000004A8* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (Solarflare 10Gb Dual-port HBA (R7)) pci:v00001924d00000803sv0000103Csd00002132* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (Ethernet 10Gb 2-port 570FLR-SFP+ Adapter (R1)) pci:v00001924d00000803sv0000103Csd00002136* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (Ethernet 10Gb 2-port 570SFP+ Adapter (R7)) pci:v00001924d00000803sv00001924sd00001201* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFA6902F-R1 SFP+ AOE Adapter) pci:v00001924d00000803sv00001924sd00006200* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5122F-R0 SFP+ Server Adapter) pci:v00001924d00000803sv00001924sd00006201* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5122F-R1 SFP+ Server Adapter) pci:v00001924d00000803sv00001924sd00006202* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5122F-R2 SFP+ Server Adapter) pci:v00001924d00000803sv00001924sd00006204* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5122F-R4 SFP+ Server Adapter) pci:v00001924d00000803sv00001924sd00006205* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5122F-R5 SFP+ Server Adapter) pci:v00001924d00000803sv00001924sd00006206* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5122F-R6 SFP+ Server Adapter) pci:v00001924d00000803sv00001924sd00006207* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5122F-R7 SFP+ Server Adapter) pci:v00001924d00000803sv00001924sd00006210* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5322F-R0 SFP+ Precision Time Synchronization Server Adapter) pci:v00001924d00000803sv00001924sd00006211* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5322F-R1 SFP+ Precision Time Synchronization Server Adapter) pci:v00001924d00000803sv00001924sd00006217* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5322F-R7 SFP+ Precision Time Synchronization Server Adapter) pci:v00001924d00000803sv00001924sd00006227* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN6122F-R7 SFP+ Server Adapter) pci:v00001924d00000803sv00001924sd00006237* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN6322F-R7 SFP+ Precision Time Synchronization Server Adapter) pci:v00001924d00000803sv00001924sd00006501* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5802K-R1 Mezzanine Adapter) pci:v00001924d00000803sv00001924sd00006511* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5814H-R1 Mezzanine Adapter) pci:v00001924d00000803sv00001924sd00006521* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5812H-R1 Mezzanine Adapter) pci:v00001924d00000803sv00001924sd00006562* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN6832F-R2 SFP+ Mezzanine Adapter) pci:v00001924d00000803sv00001924sd00006A05* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5112F-R5 SFP+ Server Adapter) pci:v00001924d00000803sv00001924sd00006A06* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5112F-R6 SFP+ Server Adapter) pci:v00001924d00000803sv00001924sd00007206* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5162F-R6 SFP+ Server Adapter) pci:v00001924d00000803sv00001924sd00007207* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5162F-R7 SFP+ Server Adapter) pci:v00001924d00000803sv00001924sd00007A06* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5152F-R6 SFP+ Server Adapter) pci:v00001924d00000803sv00001924sd00007A07* ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm] (SFN5152F-R7 SFP+ Server Adapter) pci:v00001924d00000813* ID_MODEL_FROM_DATABASE=SFL9021 [Solarstorm] pci:v00001924d00000813sv00001924sd00006100* ID_MODEL_FROM_DATABASE=SFL9021 [Solarstorm] (SFN5121T-R0 10GBASE-T Server Adapter) pci:v00001924d00000813sv00001924sd00006102* ID_MODEL_FROM_DATABASE=SFL9021 [Solarstorm] (SFN5121T-R2 10GBASE-T Server Adapter) pci:v00001924d00000813sv00001924sd00006103* ID_MODEL_FROM_DATABASE=SFL9021 [Solarstorm] (SFN5121T-R3 10GBASE-T Server Adapter) pci:v00001924d00000813sv00001924sd00006104* ID_MODEL_FROM_DATABASE=SFL9021 [Solarstorm] (SFN5121T-R4 10GBASE-T Server Adapter) pci:v00001924d00000813sv00001924sd00006902* ID_MODEL_FROM_DATABASE=SFL9021 [Solarstorm] (SFN5111T-R2 10GBASE-T Server Adapter) pci:v00001924d00000813sv00001924sd00006904* ID_MODEL_FROM_DATABASE=SFL9021 [Solarstorm] (SFN5111T-R4 10GBASE-T Server Adapter) pci:v00001924d00000813sv00001924sd00007104* ID_MODEL_FROM_DATABASE=SFL9021 [Solarstorm] (SFN5161T-R4 10GBASE-T Server Adapter) pci:v00001924d00000813sv00001924sd00007904* ID_MODEL_FROM_DATABASE=SFL9021 [Solarstorm] (SFN5151T-R4 10GBASE-T Server Adapter) pci:v00001924d00000903* ID_MODEL_FROM_DATABASE=SFC9120 pci:v00001924d00000903sv00001014sd000004CC* ID_MODEL_FROM_DATABASE=SFC9120 (SFN7122F-R2 2x10GbE SFP+ Flareon Ultra) pci:v00001924d00000903sv00001924sd00008002* ID_MODEL_FROM_DATABASE=SFC9120 (SFN7122F-R1 SFP+ Server Adapter) pci:v00001924d00000903sv00001924sd00008003* ID_MODEL_FROM_DATABASE=SFC9120 (SFN7x41Q-R1 Flareon Ultra 7000 Series 10/40G Adapter) pci:v00001924d00000903sv00001924sd00008006* ID_MODEL_FROM_DATABASE=SFC9120 (SFN7022F-R1 SFP+ Server Adapter) pci:v00001924d00000903sv00001924sd00008007* ID_MODEL_FROM_DATABASE=SFC9120 (SFN7322F-R2 Precision Time SFP+ Server Adapter) pci:v00001924d00000903sv00001924sd00008009* ID_MODEL_FROM_DATABASE=SFC9120 (SFN7x22F-R2 Flareon Ultra 7000 Series 10G Adapter) pci:v00001924d00000903sv00001924sd0000800A* ID_MODEL_FROM_DATABASE=SFC9120 (SFN7x02F-R2 Flareon 7000 Series 10G Adapter) pci:v00001924d00000903sv00001924sd0000800C* ID_MODEL_FROM_DATABASE=SFC9120 (SFN7x22F-R3 Flareon Ultra 7000 Series 10G Adapter) pci:v00001924d00000903sv00001924sd0000800D* ID_MODEL_FROM_DATABASE=SFC9120 (SFN7x02F-R3 Flareon 7000 Series 10G Adapter) pci:v00001924d00000903sv00001924sd00008010* ID_MODEL_FROM_DATABASE=SFC9120 (SFA7942Q-R1 QSFP+ AOE Adapter) pci:v00001924d00000923* ID_MODEL_FROM_DATABASE=SFC9140 pci:v00001924d00000923sv00001924sd0000800B* ID_MODEL_FROM_DATABASE=SFC9140 (SFN7x42Q-R1 Flareon Ultra 7000 Series 10/40G Adapter) pci:v00001924d00000923sv00001924sd0000800E* ID_MODEL_FROM_DATABASE=SFC9140 (SFN7x42Q-R2 Flareon Ultra 7000 Series 10/40G Adapter) pci:v00001924d00000923sv00001924sd0000800F* ID_MODEL_FROM_DATABASE=SFC9140 (SFN7xx4F-R1 Flareon Ultra 7000 Series 10G Adapter) pci:v00001924d00000A03* ID_MODEL_FROM_DATABASE=SFC9220 pci:v00001924d00000A03sv00001924sd00008012* ID_MODEL_FROM_DATABASE=SFC9220 (SFN8522-R1 Flareon Ultra 8000 Series 10G Adapter) pci:v00001924d00000A03sv00001924sd00008014* ID_MODEL_FROM_DATABASE=SFC9220 (SFN8542-R1 Flareon Ultra 8000 Series 10/40G Adapter) pci:v00001924d00001803* ID_MODEL_FROM_DATABASE=SFC9020 Virtual Function [Solarstorm] pci:v00001924d00001813* ID_MODEL_FROM_DATABASE=SFL9021 Virtual Function [Solarstorm] pci:v00001924d00001903* ID_MODEL_FROM_DATABASE=SFC9120 Virtual Function pci:v00001924d00001923* ID_MODEL_FROM_DATABASE=SFC9140 Virtual Function pci:v00001924d00006703* ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] pci:v00001924d00006703sv000010B8sd00000102* ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SMC10GPCIe-10BT (A2) [TigerCard]) pci:v00001924d00006703sv000010B8sd00000103* ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SMC10GPCIe-10BT (A3) [TigerCard]) pci:v00001924d00006703sv000010B8sd00000201* ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SMC10GPCIe-XFP (A1) [TigerCard]) pci:v00001924d00006703sv00001924sd00000101* ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4001-A1) pci:v00001924d00006703sv00001924sd00000102* ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4001-A2) pci:v00001924d00006703sv00001924sd00000103* ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4001-A3) pci:v00001924d00006703sv00001924sd00000201* ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4002-A1) pci:v00001924d00006703sv00001924sd00000301* ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4003-A1) pci:v00001924d00006703sv00001924sd00000302* ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4003-A2) pci:v00001924d00006703sv00001924sd00000303* ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4003-A3) pci:v00001924d00006703sv00001924sd00000304* ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4003-A4) pci:v00001924d00006703sv00001924sd00000500* ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4005-A0) pci:v00001924d0000C101* ID_MODEL_FROM_DATABASE=EF1-21022T [EtherFabric] pci:v0000192A* ID_VENDOR_FROM_DATABASE=BiTMICRO Networks Inc. pci:v0000192E* ID_VENDOR_FROM_DATABASE=TransDimension pci:v00001931* ID_VENDOR_FROM_DATABASE=Option N.V. pci:v00001931d0000000C* ID_MODEL_FROM_DATABASE=Qualcomm MSM6275 UMTS chip pci:v00001932* ID_VENDOR_FROM_DATABASE=DiBcom pci:v0000193C* ID_VENDOR_FROM_DATABASE=MAXIM Integrated Products pci:v0000193F* ID_VENDOR_FROM_DATABASE=Comtech AHA Corp. pci:v0000193Fd00000001* ID_MODEL_FROM_DATABASE=AHA36x-PCIX pci:v0000193Fd00000360* ID_MODEL_FROM_DATABASE=AHA360-PCIe pci:v0000193Fd00000363* ID_MODEL_FROM_DATABASE=AHA363-PCIe pci:v0000193Fd00000364* ID_MODEL_FROM_DATABASE=AHA364-PCIe pci:v0000193Fd00000367* ID_MODEL_FROM_DATABASE=AHA367-PCIe pci:v0000193Fd00000370* ID_MODEL_FROM_DATABASE=AHA370-PCIe pci:v0000193Fd00003641* ID_MODEL_FROM_DATABASE=AHA3641 pci:v0000193Fd00003642* ID_MODEL_FROM_DATABASE=AHA3642 pci:v00001942* ID_VENDOR_FROM_DATABASE=ClearSpeed Technology plc pci:v00001942d0000E511* ID_MODEL_FROM_DATABASE=Advance X620 accelerator card pci:v00001942d0000E521* ID_MODEL_FROM_DATABASE=Advance e620 accelerator card pci:v00001947* ID_VENDOR_FROM_DATABASE=C-guys, Inc. pci:v00001947d00004743* ID_MODEL_FROM_DATABASE=CG200 Dual SD/SDIO Host controller device pci:v00001948* ID_VENDOR_FROM_DATABASE=Alpha Networks Inc. pci:v0000194A* ID_VENDOR_FROM_DATABASE=DapTechnology B.V. pci:v0000194Ad00001111* ID_MODEL_FROM_DATABASE=FireSpy3850 pci:v0000194Ad00001112* ID_MODEL_FROM_DATABASE=FireSpy450b pci:v0000194Ad00001113* ID_MODEL_FROM_DATABASE=FireSpy450bT pci:v0000194Ad00001114* ID_MODEL_FROM_DATABASE=FireSpy850 pci:v0000194Ad00001115* ID_MODEL_FROM_DATABASE=FireSpy850bT pci:v0000194Ad00001200* ID_MODEL_FROM_DATABASE=FireTrac 3460bT pci:v0000194Ad00001201* ID_MODEL_FROM_DATABASE=FireTrac 3460bT (fallback firmware) pci:v0000194Ad00001202* ID_MODEL_FROM_DATABASE=FireTrac 3460bT pci:v0000194Ad00001203* ID_MODEL_FROM_DATABASE=FireTrac 3460bT (fallback firmware) pci:v00001954* ID_VENDOR_FROM_DATABASE=One Stop Systems, Inc. pci:v00001957* ID_VENDOR_FROM_DATABASE=Freescale Semiconductor Inc pci:v00001957d00000012* ID_MODEL_FROM_DATABASE=MPC8548E pci:v00001957d00000013* ID_MODEL_FROM_DATABASE=MPC8548 pci:v00001957d00000014* ID_MODEL_FROM_DATABASE=MPC8543E pci:v00001957d00000015* ID_MODEL_FROM_DATABASE=MPC8543 pci:v00001957d00000018* ID_MODEL_FROM_DATABASE=MPC8547E pci:v00001957d00000019* ID_MODEL_FROM_DATABASE=MPC8545E pci:v00001957d0000001A* ID_MODEL_FROM_DATABASE=MPC8545 pci:v00001957d00000020* ID_MODEL_FROM_DATABASE=MPC8568E pci:v00001957d00000021* ID_MODEL_FROM_DATABASE=MPC8568 pci:v00001957d00000022* ID_MODEL_FROM_DATABASE=MPC8567E pci:v00001957d00000023* ID_MODEL_FROM_DATABASE=MPC8567 pci:v00001957d00000030* ID_MODEL_FROM_DATABASE=MPC8533E pci:v00001957d00000031* ID_MODEL_FROM_DATABASE=MPC8533 pci:v00001957d00000032* ID_MODEL_FROM_DATABASE=MPC8544E pci:v00001957d00000033* ID_MODEL_FROM_DATABASE=MPC8544 pci:v00001957d00000040* ID_MODEL_FROM_DATABASE=MPC8572E pci:v00001957d00000041* ID_MODEL_FROM_DATABASE=MPC8572 pci:v00001957d00000050* ID_MODEL_FROM_DATABASE=MPC8536E pci:v00001957d00000051* ID_MODEL_FROM_DATABASE=MPC8536 pci:v00001957d00000052* ID_MODEL_FROM_DATABASE=MPC8535E pci:v00001957d00000053* ID_MODEL_FROM_DATABASE=MPC8535 pci:v00001957d00000060* ID_MODEL_FROM_DATABASE=MPC8569 pci:v00001957d00000061* ID_MODEL_FROM_DATABASE=MPC8569E pci:v00001957d00000070* ID_MODEL_FROM_DATABASE=P2020E pci:v00001957d00000071* ID_MODEL_FROM_DATABASE=P2020 pci:v00001957d00000078* ID_MODEL_FROM_DATABASE=P2010E pci:v00001957d00000079* ID_MODEL_FROM_DATABASE=P2010 pci:v00001957d00000080* ID_MODEL_FROM_DATABASE=MPC8349E pci:v00001957d00000081* ID_MODEL_FROM_DATABASE=MPC8349 pci:v00001957d00000082* ID_MODEL_FROM_DATABASE=MPC8347E TBGA pci:v00001957d00000083* ID_MODEL_FROM_DATABASE=MPC8347 TBGA pci:v00001957d00000084* ID_MODEL_FROM_DATABASE=MPC8347E PBGA pci:v00001957d00000084sv0000110Asd00004074* ID_MODEL_FROM_DATABASE=MPC8347E PBGA (SIMATIC NET CP 1628) pci:v00001957d00000085* ID_MODEL_FROM_DATABASE=MPC8347 PBGA pci:v00001957d00000085sv0000110Asd00004046* ID_MODEL_FROM_DATABASE=MPC8347 PBGA (SIMATIC NET CP 1623) pci:v00001957d00000086* ID_MODEL_FROM_DATABASE=MPC8343E pci:v00001957d00000087* ID_MODEL_FROM_DATABASE=MPC8343 pci:v00001957d000000B4* ID_MODEL_FROM_DATABASE=MPC8315E pci:v00001957d000000B6* ID_MODEL_FROM_DATABASE=MPC8314E pci:v00001957d000000B6sv00001A56sd00001101* ID_MODEL_FROM_DATABASE=MPC8314E (Killer Xeno Pro Gigabit Ethernet Controller) pci:v00001957d000000C2* ID_MODEL_FROM_DATABASE=MPC8379E pci:v00001957d000000C3* ID_MODEL_FROM_DATABASE=MPC8379 pci:v00001957d000000C4* ID_MODEL_FROM_DATABASE=MPC8378E pci:v00001957d000000C5* ID_MODEL_FROM_DATABASE=MPC8378 pci:v00001957d000000C6* ID_MODEL_FROM_DATABASE=MPC8377E pci:v00001957d000000C7* ID_MODEL_FROM_DATABASE=MPC8377 pci:v00001957d00000100* ID_MODEL_FROM_DATABASE=P1020E pci:v00001957d00000101* ID_MODEL_FROM_DATABASE=P1020 pci:v00001957d00000102* ID_MODEL_FROM_DATABASE=P1021E pci:v00001957d00000103* ID_MODEL_FROM_DATABASE=P1021 pci:v00001957d00000108* ID_MODEL_FROM_DATABASE=P1011E pci:v00001957d00000109* ID_MODEL_FROM_DATABASE=P1011 pci:v00001957d0000010A* ID_MODEL_FROM_DATABASE=P1012E pci:v00001957d0000010B* ID_MODEL_FROM_DATABASE=P1012 pci:v00001957d00000110* ID_MODEL_FROM_DATABASE=P1022E pci:v00001957d00000111* ID_MODEL_FROM_DATABASE=P1022 pci:v00001957d00000111sv00001C7Fsd00005200* ID_MODEL_FROM_DATABASE=P1022 (EB5200) pci:v00001957d00000118* ID_MODEL_FROM_DATABASE=P1013E pci:v00001957d00000119* ID_MODEL_FROM_DATABASE=P1013 pci:v00001957d00000128* ID_MODEL_FROM_DATABASE=P1010 pci:v00001957d00000400* ID_MODEL_FROM_DATABASE=P4080E pci:v00001957d00000401* ID_MODEL_FROM_DATABASE=P4080 pci:v00001957d00000408* ID_MODEL_FROM_DATABASE=P4040E pci:v00001957d00000409* ID_MODEL_FROM_DATABASE=P4040 pci:v00001957d00000440* ID_MODEL_FROM_DATABASE=T4240 with security pci:v00001957d00000441* ID_MODEL_FROM_DATABASE=T4240 without security pci:v00001957d00000446* ID_MODEL_FROM_DATABASE=T4160 with security pci:v00001957d00000447* ID_MODEL_FROM_DATABASE=T4160 without security pci:v00001957d00000830* ID_MODEL_FROM_DATABASE=T2080 with security pci:v00001957d00000831* ID_MODEL_FROM_DATABASE=T2080 without security pci:v00001957d00000838* ID_MODEL_FROM_DATABASE=T2081 with security pci:v00001957d00000839* ID_MODEL_FROM_DATABASE=T2081 without security pci:v00001957d0000580C* ID_MODEL_FROM_DATABASE=MPC5121e pci:v00001957d00007010* ID_MODEL_FROM_DATABASE=MPC8641 PCI Host Bridge pci:v00001957d00007011* ID_MODEL_FROM_DATABASE=MPC8641D PCI Host Bridge pci:v00001957d00007018* ID_MODEL_FROM_DATABASE=MPC8610 pci:v00001957d0000C006* ID_MODEL_FROM_DATABASE=MPC8308 pci:v00001957d0000C006sv00001A56sd00001201* ID_MODEL_FROM_DATABASE=MPC8308 (Killer E2100 Gigabit Ethernet Controller) pci:v00001957d0000FC02* ID_MODEL_FROM_DATABASE=RedStone pci:v00001957d0000FC03* ID_MODEL_FROM_DATABASE=CFI pci:v00001958* ID_VENDOR_FROM_DATABASE=Faster Technology, LLC. pci:v00001959* ID_VENDOR_FROM_DATABASE=PA Semi, Inc pci:v00001959d0000A000* ID_MODEL_FROM_DATABASE=PA6T Core pci:v00001959d0000A001* ID_MODEL_FROM_DATABASE=PWRficient Host Bridge pci:v00001959d0000A002* ID_MODEL_FROM_DATABASE=PWRficient PCI-Express Port pci:v00001959d0000A003* ID_MODEL_FROM_DATABASE=PWRficient SMBus Controller pci:v00001959d0000A004* ID_MODEL_FROM_DATABASE=PWRficient 16550 UART pci:v00001959d0000A005* ID_MODEL_FROM_DATABASE=PWRficient Gigabit Ethernet pci:v00001959d0000A006* ID_MODEL_FROM_DATABASE=PWRficient 10-Gigabit Ethernet pci:v00001959d0000A007* ID_MODEL_FROM_DATABASE=PWRficient DMA Controller pci:v00001959d0000A008* ID_MODEL_FROM_DATABASE=PWRficient LPC/Localbus Interface pci:v00001959d0000A009* ID_MODEL_FROM_DATABASE=PWRficient L2 Cache pci:v00001959d0000A00A* ID_MODEL_FROM_DATABASE=PWRficient DDR2 Memory Controller pci:v00001959d0000A00B* ID_MODEL_FROM_DATABASE=PWRficient SERDES pci:v00001959d0000A00C* ID_MODEL_FROM_DATABASE=PWRficient System/Debug Controller pci:v00001959d0000A00D* ID_MODEL_FROM_DATABASE=PWRficient PCI-Express Internal Endpoint pci:v00001966* ID_VENDOR_FROM_DATABASE=Orad Hi-Tec Systems pci:v00001966d00001975* ID_MODEL_FROM_DATABASE=DVG64 family pci:v00001966d00001977* ID_MODEL_FROM_DATABASE=DVG128 family pci:v00001969* ID_VENDOR_FROM_DATABASE=Qualcomm Atheros pci:v00001969d00001026* ID_MODEL_FROM_DATABASE=AR8121/AR8113/AR8114 Gigabit or Fast Ethernet pci:v00001969d00001026sv00001043sd00008304* ID_MODEL_FROM_DATABASE=AR8121/AR8113/AR8114 Gigabit or Fast Ethernet (P5KPL-CM Motherboard) pci:v00001969d00001048* ID_MODEL_FROM_DATABASE=Attansic L1 Gigabit Ethernet pci:v00001969d00001048sv00001043sd00008226* ID_MODEL_FROM_DATABASE=Attansic L1 Gigabit Ethernet (P5KPL-VM Motherboard) pci:v00001969d00001062* ID_MODEL_FROM_DATABASE=AR8132 Fast Ethernet pci:v00001969d00001063* ID_MODEL_FROM_DATABASE=AR8131 Gigabit Ethernet pci:v00001969d00001063sv00001458sd0000E000* ID_MODEL_FROM_DATABASE=AR8131 Gigabit Ethernet (GA-G31M-ES2L Motherboard) pci:v00001969d00001063sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=AR8131 Gigabit Ethernet (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00001969d00001066* ID_MODEL_FROM_DATABASE=Attansic L2c Gigabit Ethernet pci:v00001969d00001067* ID_MODEL_FROM_DATABASE=Attansic L1c Gigabit Ethernet pci:v00001969d00001073* ID_MODEL_FROM_DATABASE=AR8151 v1.0 Gigabit Ethernet pci:v00001969d00001083* ID_MODEL_FROM_DATABASE=AR8151 v2.0 Gigabit Ethernet pci:v00001969d00001090* ID_MODEL_FROM_DATABASE=AR8162 Fast Ethernet pci:v00001969d00001090sv00001043sd0000108D* ID_MODEL_FROM_DATABASE=AR8162 Fast Ethernet (VivoBook X202E, X202EV) pci:v00001969d00001091* ID_MODEL_FROM_DATABASE=AR8161 Gigabit Ethernet pci:v00001969d00001091sv00001043sd00001477* ID_MODEL_FROM_DATABASE=AR8161 Gigabit Ethernet (N56VZ) pci:v00001969d000010A0* ID_MODEL_FROM_DATABASE=QCA8172 Fast Ethernet pci:v00001969d000010A1* ID_MODEL_FROM_DATABASE=QCA8171 Gigabit Ethernet pci:v00001969d00002048* ID_MODEL_FROM_DATABASE=Attansic L2 Fast Ethernet pci:v00001969d00002060* ID_MODEL_FROM_DATABASE=AR8152 v1.1 Fast Ethernet pci:v00001969d00002062* ID_MODEL_FROM_DATABASE=AR8152 v2.0 Fast Ethernet pci:v00001969d0000E091* ID_MODEL_FROM_DATABASE=Killer E220x Gigabit Ethernet Controller pci:v00001969d0000E0A1* ID_MODEL_FROM_DATABASE=Killer E2400 Gigabit Ethernet Controller pci:v0000196A* ID_VENDOR_FROM_DATABASE=Sensory Networks Inc. pci:v0000196Ad00000101* ID_MODEL_FROM_DATABASE=NodalCore C-1000 Content Classification Accelerator pci:v0000196Ad00000102* ID_MODEL_FROM_DATABASE=NodalCore C-2000 Content Classification Accelerator pci:v0000196Ad00000105* ID_MODEL_FROM_DATABASE=NodalCore C-3000 Content Classification Accelerator pci:v0000196D* ID_VENDOR_FROM_DATABASE=Club-3D BV pci:v00001971* ID_VENDOR_FROM_DATABASE=AGEIA Technologies, Inc. pci:v00001971d00001011* ID_MODEL_FROM_DATABASE=Physics Processing Unit [PhysX] pci:v00001971d00001011sv00001043sd00000001* ID_MODEL_FROM_DATABASE=Physics Processing Unit [PhysX] (PhysX P1) pci:v00001974* ID_VENDOR_FROM_DATABASE=Eberspaecher Electronics pci:v00001976* ID_VENDOR_FROM_DATABASE=TRENDnet pci:v00001977* ID_VENDOR_FROM_DATABASE=Parsec pci:v0000197B* ID_VENDOR_FROM_DATABASE=JMicron Technology Corp. pci:v0000197Bd00000250* ID_MODEL_FROM_DATABASE=JMC250 PCI Express Gigabit Ethernet Controller pci:v0000197Bd00000260* ID_MODEL_FROM_DATABASE=JMC260 PCI Express Fast Ethernet Controller pci:v0000197Bd00000368* ID_MODEL_FROM_DATABASE=JMB368 IDE controller pci:v0000197Bd00002360* ID_MODEL_FROM_DATABASE=JMB360 AHCI Controller pci:v0000197Bd00002361* ID_MODEL_FROM_DATABASE=JMB361 AHCI/IDE pci:v0000197Bd00002361sv00001462sd00007235* ID_MODEL_FROM_DATABASE=JMB361 AHCI/IDE (P965 Neo MS-7235 mainboard) pci:v0000197Bd00002362* ID_MODEL_FROM_DATABASE=JMB362 SATA Controller pci:v0000197Bd00002362sv00001043sd00008460* ID_MODEL_FROM_DATABASE=JMB362 SATA Controller (P8P67 Deluxe Motherboard) pci:v0000197Bd00002363* ID_MODEL_FROM_DATABASE=JMB363 SATA/IDE Controller pci:v0000197Bd00002363sv00001043sd000081E4* ID_MODEL_FROM_DATABASE=JMB363 SATA/IDE Controller (P5B [JMB363]) pci:v0000197Bd00002363sv00001458sd0000B000* ID_MODEL_FROM_DATABASE=JMB363 SATA/IDE Controller (Motherboard) pci:v0000197Bd00002363sv00001849sd00002363* ID_MODEL_FROM_DATABASE=JMB363 SATA/IDE Controller (Motherboard (one of many)) pci:v0000197Bd00002364* ID_MODEL_FROM_DATABASE=JMB364 AHCI Controller pci:v0000197Bd00002365* ID_MODEL_FROM_DATABASE=JMB365 AHCI/IDE pci:v0000197Bd00002366* ID_MODEL_FROM_DATABASE=JMB366 AHCI/IDE pci:v0000197Bd00002368* ID_MODEL_FROM_DATABASE=JMB368 IDE controller pci:v0000197Bd00002369* ID_MODEL_FROM_DATABASE=JMB369 Serial ATA Controller pci:v0000197Bd00002380* ID_MODEL_FROM_DATABASE=IEEE 1394 Host Controller pci:v0000197Bd00002381* ID_MODEL_FROM_DATABASE=Standard SD Host Controller pci:v0000197Bd00002382* ID_MODEL_FROM_DATABASE=SD/MMC Host Controller pci:v0000197Bd00002383* ID_MODEL_FROM_DATABASE=MS Host Controller pci:v0000197Bd00002384* ID_MODEL_FROM_DATABASE=xD Host Controller pci:v0000197Bd00002386* ID_MODEL_FROM_DATABASE=Standard SD Host Controller pci:v0000197Bd00002387* ID_MODEL_FROM_DATABASE=SD/MMC Host Controller pci:v0000197Bd00002388* ID_MODEL_FROM_DATABASE=MS Host Controller pci:v0000197Bd00002389* ID_MODEL_FROM_DATABASE=xD Host Controller pci:v0000197Bd00002391* ID_MODEL_FROM_DATABASE=Standard SD Host Controller pci:v0000197Bd00002392* ID_MODEL_FROM_DATABASE=SD/MMC Host Controller pci:v0000197Bd00002393* ID_MODEL_FROM_DATABASE=MS Host Controller pci:v0000197Bd00002394* ID_MODEL_FROM_DATABASE=xD Host Controller pci:v00001982* ID_VENDOR_FROM_DATABASE=Distant Early Warning Communications Inc pci:v00001982d00001600* ID_MODEL_FROM_DATABASE=OX16C954 HOST-A pci:v00001982d000016FF* ID_MODEL_FROM_DATABASE=OX16C954 HOST-B pci:v00001989* ID_VENDOR_FROM_DATABASE=Montilio Inc. pci:v00001989d00000001* ID_MODEL_FROM_DATABASE=RapidFile Bridge pci:v00001989d00008001* ID_MODEL_FROM_DATABASE=RapidFile pci:v0000198A* ID_VENDOR_FROM_DATABASE=Nallatech Ltd. pci:v00001993* ID_VENDOR_FROM_DATABASE=Innominate Security Technologies AG pci:v00001999* ID_VENDOR_FROM_DATABASE=A-Logics pci:v00001999d0000A900* ID_MODEL_FROM_DATABASE=AM-7209 Video Processor pci:v0000199A* ID_VENDOR_FROM_DATABASE=Pulse-LINK, Inc. pci:v0000199D* ID_VENDOR_FROM_DATABASE=Xsigo Systems pci:v0000199Dd00008209* ID_MODEL_FROM_DATABASE=Virtual NIC Device pci:v0000199Dd0000890A* ID_MODEL_FROM_DATABASE=Virtual HBA Device pci:v0000199F* ID_VENDOR_FROM_DATABASE=Auvitek pci:v0000199Fd00008501* ID_MODEL_FROM_DATABASE=AU85X1 PCI REV1.1 pci:v0000199Fd00008521* ID_MODEL_FROM_DATABASE=AU8521 TV card pci:v000019A2* ID_VENDOR_FROM_DATABASE=Emulex Corporation pci:v000019A2d00000120* ID_MODEL_FROM_DATABASE=x1 PCIe Gen2 Bridge[Pilot4] pci:v000019A2d00000200* ID_MODEL_FROM_DATABASE=BladeEngine 10Gb PCI-E iSCSI adapter pci:v000019A2d00000201* ID_MODEL_FROM_DATABASE=BladeEngine 10Gb PCIe Network Adapter pci:v000019A2d00000211* ID_MODEL_FROM_DATABASE=BladeEngine2 10Gb Gen2 PCIe Network Adapter pci:v000019A2d00000212* ID_MODEL_FROM_DATABASE=BladeEngine2 10Gb Gen2 PCIe iSCSI Adapter pci:v000019A2d00000221* ID_MODEL_FROM_DATABASE=BladeEngine3 10Gb Gen2 PCIe Network Adapter pci:v000019A2d00000222* ID_MODEL_FROM_DATABASE=BladeEngine3 10Gb Gen2 PCIe iSCSI Adapter pci:v000019A2d00000700* ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC pci:v000019A2d00000700sv0000103Csd00001747* ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (NC550SFP DualPort 10GbE Server Adapter) pci:v000019A2d00000700sv0000103Csd00001749* ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (NC550SFP Dual Port Server Adapter) pci:v000019A2d00000700sv0000103Csd0000174A* ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (NC551m Dual Port FlexFabric 10Gb Adapter) pci:v000019A2d00000700sv0000103Csd0000174B* ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (StorageWorks NC550 DualPort Converged Network Adapter) pci:v000019A2d00000700sv0000103Csd00003314* ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (NC551i Dual Port FlexFabric 10Gb Adapter) pci:v000019A2d00000702* ID_MODEL_FROM_DATABASE=OneConnect 10Gb iSCSI Initiator pci:v000019A2d00000704* ID_MODEL_FROM_DATABASE=OneConnect 10Gb FCoE Initiator pci:v000019A2d00000710* ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) pci:v000019A2d00000710sv0000103Csd00003315* ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (NC553i 10Gb 2-port FlexFabric Converged Network Adapter) pci:v000019A2d00000710sv0000103Csd00003340* ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (NC552SFP 2-port 10Gb Server Adapter) pci:v000019A2d00000710sv0000103Csd00003341* ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (NC552m 10Gb 2-port FlexFabric Converged Network Adapter) pci:v000019A2d00000710sv0000103Csd00003345* ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (NC553m 10Gb 2-port FlexFabric Converged Network Adapter) pci:v000019A2d00000710sv0000103Csd0000337B* ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (NC554FLB 10Gb 2-port FlexFabric Converged Network Adapter) pci:v000019A2d00000712* ID_MODEL_FROM_DATABASE=OneConnect 10Gb iSCSI Initiator (be3) pci:v000019A2d00000714* ID_MODEL_FROM_DATABASE=OneConnect 10Gb FCoE Initiator (be3) pci:v000019A2d00000714sv0000103Csd00003315* ID_MODEL_FROM_DATABASE=OneConnect 10Gb FCoE Initiator (be3) (NC553i 10Gb 2-port FlexFabric Converged Network Adapter) pci:v000019A2d00000714sv0000103Csd0000337B* ID_MODEL_FROM_DATABASE=OneConnect 10Gb FCoE Initiator (be3) (NC554FLB 10Gb 2-port FlexFabric Converged Network Adapter) pci:v000019A8* ID_VENDOR_FROM_DATABASE=DAQDATA GmbH pci:v000019AC* ID_VENDOR_FROM_DATABASE=Kasten Chase Applied Research pci:v000019ACd00000001* ID_MODEL_FROM_DATABASE=ACA2400 Crypto Accelerator pci:v000019AE* ID_VENDOR_FROM_DATABASE=Progeny Systems Corporation pci:v000019AEd00000520* ID_MODEL_FROM_DATABASE=4135 HFT Interface Controller pci:v000019AEd00000521* ID_MODEL_FROM_DATABASE=Decimator pci:v000019BA* ID_VENDOR_FROM_DATABASE=ZyXEL Communications Corp. pci:v000019BAd00002330* ID_MODEL_FROM_DATABASE=ZyWALL Turbo Card pci:v000019C1* ID_VENDOR_FROM_DATABASE=Exegy Inc. pci:v000019D1* ID_VENDOR_FROM_DATABASE=Motorola Expedience pci:v000019D4* ID_VENDOR_FROM_DATABASE=Quixant Limited pci:v000019DA* ID_VENDOR_FROM_DATABASE=ZOTAC International (MCO) Ltd. pci:v000019DE* ID_VENDOR_FROM_DATABASE=Pico Computing pci:v000019E2* ID_VENDOR_FROM_DATABASE=Vector Informatik GmbH pci:v000019E3* ID_VENDOR_FROM_DATABASE=DDRdrive LLC pci:v000019E3d00005801* ID_MODEL_FROM_DATABASE=DDRdrive X1 pci:v000019E3d00005808* ID_MODEL_FROM_DATABASE=DDRdrive X8 pci:v000019E3d0000DD52* ID_MODEL_FROM_DATABASE=DDRdrive X1-30 pci:v000019E7* ID_VENDOR_FROM_DATABASE=NET (Network Equipment Technologies) pci:v000019E7d00001001* ID_MODEL_FROM_DATABASE=STIX DSP Card pci:v000019E7d00001002* ID_MODEL_FROM_DATABASE=STIX - 1 Port T1/E1 Card pci:v000019E7d00001003* ID_MODEL_FROM_DATABASE=STIX - 2 Port T1/E1 Card pci:v000019E7d00001004* ID_MODEL_FROM_DATABASE=STIX - 4 Port T1/E1 Card pci:v000019E7d00001005* ID_MODEL_FROM_DATABASE=STIX - 4 Port FXS Card pci:v000019EE* ID_VENDOR_FROM_DATABASE=Netronome Systems, Inc. pci:v000019F1* ID_VENDOR_FROM_DATABASE=BFG Tech pci:v000019FF* ID_VENDOR_FROM_DATABASE=Eclipse Electronic Systems, Inc. pci:v00001A03* ID_VENDOR_FROM_DATABASE=ASPEED Technology, Inc. pci:v00001A03d00001150* ID_MODEL_FROM_DATABASE=AST1150 PCI-to-PCI Bridge pci:v00001A03d00002000* ID_MODEL_FROM_DATABASE=ASPEED Graphics Family pci:v00001A07* ID_VENDOR_FROM_DATABASE=Kvaser AB pci:v00001A07d00000006* ID_MODEL_FROM_DATABASE=CAN interface PC104+ HS/HS pci:v00001A07d00000007* ID_MODEL_FROM_DATABASE=CAN interface PCIcanx II HS or HS/HS pci:v00001A07d00000008* ID_MODEL_FROM_DATABASE=CAN interface PCIEcan HS or HS/HS pci:v00001A07d00000009* ID_MODEL_FROM_DATABASE=CAN interface PCI104 HS/HS pci:v00001A08* ID_VENDOR_FROM_DATABASE=Sierra semiconductor pci:v00001A08d00000000* ID_MODEL_FROM_DATABASE=SC15064 pci:v00001A0E* ID_VENDOR_FROM_DATABASE=DekTec Digital Video B.V. pci:v00001A0Ed0000083F* ID_MODEL_FROM_DATABASE=DTA-2111 VHF/UHF Modulator pci:v00001A17* ID_VENDOR_FROM_DATABASE=Force10 Networks, Inc. pci:v00001A17d00008002* ID_MODEL_FROM_DATABASE=PB-10GE-2P 10GbE Security Card pci:v00001A1D* ID_VENDOR_FROM_DATABASE=GFaI e.V. pci:v00001A1Dd00001A17* ID_MODEL_FROM_DATABASE=Meta Networks MTP-1G IDPS NIC pci:v00001A1E* ID_VENDOR_FROM_DATABASE=3Leaf Systems, Inc. pci:v00001A22* ID_VENDOR_FROM_DATABASE=Ambric Inc. pci:v00001A29* ID_VENDOR_FROM_DATABASE=Fortinet, Inc. pci:v00001A29d00004338* ID_MODEL_FROM_DATABASE=CP8 Content Processor ASIC pci:v00001A29d00004E36* ID_MODEL_FROM_DATABASE=NP6 Network Processor pci:v00001A2B* ID_VENDOR_FROM_DATABASE=Ascom AG pci:v00001A2Bd00000000* ID_MODEL_FROM_DATABASE=GESP v1.2 pci:v00001A2Bd00000001* ID_MODEL_FROM_DATABASE=GESP v1.3 pci:v00001A2Bd00000002* ID_MODEL_FROM_DATABASE=ECOMP v1.3 pci:v00001A2Bd00000005* ID_MODEL_FROM_DATABASE=ETP v1.4 pci:v00001A2Bd0000000A* ID_MODEL_FROM_DATABASE=ETP-104 v1.1 pci:v00001A2Bd0000000E* ID_MODEL_FROM_DATABASE=DSLP-104 v1.1 pci:v00001A30* ID_VENDOR_FROM_DATABASE=Lantiq pci:v00001A30d00000680* ID_MODEL_FROM_DATABASE=MtW8171 [Hyperion II] pci:v00001A30d00000700* ID_MODEL_FROM_DATABASE=Wave300 PSB8224 [Hyperion III] pci:v00001A30d00000710* ID_MODEL_FROM_DATABASE=Wave300 PSB8231 [Hyperion III] pci:v00001A32* ID_VENDOR_FROM_DATABASE=Quanta Microsystems, Inc pci:v00001A3B* ID_VENDOR_FROM_DATABASE=AzureWave pci:v00001A3Bd00001112* ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) pci:v00001A41* ID_VENDOR_FROM_DATABASE=Tilera Corp. pci:v00001A41d00000001* ID_MODEL_FROM_DATABASE=TILE64 processor pci:v00001A41d00000002* ID_MODEL_FROM_DATABASE=TILEPro processor pci:v00001A41d00000200* ID_MODEL_FROM_DATABASE=TILE-Gx processor pci:v00001A41d00000201* ID_MODEL_FROM_DATABASE=TILE-Gx Processor Virtual Function pci:v00001A41d00002000* ID_MODEL_FROM_DATABASE=TILE-Gx PCI Express Root Port pci:v00001A4A* ID_VENDOR_FROM_DATABASE=SLAC National Accelerator Lab PPA-REG pci:v00001A4Ad00001000* ID_MODEL_FROM_DATABASE=MCOR Power Supply Controller pci:v00001A4Ad00001010* ID_MODEL_FROM_DATABASE=AMC EVR - Stockholm Timing Board pci:v00001A4Ad00002000* ID_MODEL_FROM_DATABASE=PGPCard - 4 Lane pci:v00001A4Ad00002001* ID_MODEL_FROM_DATABASE=PGPCard - 8 Lane Plus EVR pci:v00001A4Ad00002010* ID_MODEL_FROM_DATABASE=PCI-Express EVR pci:v00001A51* ID_VENDOR_FROM_DATABASE=Hectronic AB pci:v00001A55* ID_VENDOR_FROM_DATABASE=Rohde & Schwarz DVS GmbH pci:v00001A55d00000010* ID_MODEL_FROM_DATABASE=SDStationOEM pci:v00001A55d00000011* ID_MODEL_FROM_DATABASE=SDStationOEM II pci:v00001A55d00000020* ID_MODEL_FROM_DATABASE=Centaurus pci:v00001A55d00000021* ID_MODEL_FROM_DATABASE=Centaurus II pci:v00001A55d00000022* ID_MODEL_FROM_DATABASE=Centaurus II LT pci:v00001A55d00000030* ID_MODEL_FROM_DATABASE=CLIPSTER-VPU 1.x (Hugo) pci:v00001A55d00000040* ID_MODEL_FROM_DATABASE=Hydra Cinema (JPEG) pci:v00001A55d00000050* ID_MODEL_FROM_DATABASE=CLIPSTER-VPU 2.x (DigiLab) pci:v00001A55d00000060* ID_MODEL_FROM_DATABASE=CLIPSTER-DCI 2.x (HydraX) pci:v00001A55d00000061* ID_MODEL_FROM_DATABASE=Atomix pci:v00001A55d00000062* ID_MODEL_FROM_DATABASE=Atomix LT pci:v00001A55d00000063* ID_MODEL_FROM_DATABASE=Atomix HDMI pci:v00001A55d00000064* ID_MODEL_FROM_DATABASE=Atomix STAN pci:v00001A55d00000065* ID_MODEL_FROM_DATABASE=Atomix HDMI STAN pci:v00001A55d00000070* ID_MODEL_FROM_DATABASE=RED Rocket pci:v00001A55d00000090* ID_MODEL_FROM_DATABASE=CinePlay pci:v00001A56* ID_VENDOR_FROM_DATABASE=Bigfoot Networks, Inc. pci:v00001A57* ID_VENDOR_FROM_DATABASE=Highly Reliable Systems pci:v00001A58* ID_VENDOR_FROM_DATABASE=Razer USA Ltd. pci:v00001A5D* ID_VENDOR_FROM_DATABASE=Celoxica pci:v00001A5E* ID_VENDOR_FROM_DATABASE=Aprius Inc. pci:v00001A5F* ID_VENDOR_FROM_DATABASE=System TALKS Inc. pci:v00001A68* ID_VENDOR_FROM_DATABASE=VirtenSys Limited pci:v00001A71* ID_VENDOR_FROM_DATABASE=XenSource, Inc. pci:v00001A73* ID_VENDOR_FROM_DATABASE=Violin Memory, Inc pci:v00001A73d00000001* ID_MODEL_FROM_DATABASE=Mozart [Memory Appliance 1010] pci:v00001A76* ID_VENDOR_FROM_DATABASE=Wavesat pci:v00001A77* ID_VENDOR_FROM_DATABASE=Lightfleet Corporation pci:v00001A78* ID_VENDOR_FROM_DATABASE=Virident Systems Inc. pci:v00001A78d00000031* ID_MODEL_FROM_DATABASE=FlashMAX Drive pci:v00001A78d00000031sv00001A78sd00000034* ID_MODEL_FROM_DATABASE=FlashMAX Drive (FlashMAX PCIe SSD [rev 3]) pci:v00001A78d00000031sv00001A78sd00000037* ID_MODEL_FROM_DATABASE=FlashMAX Drive (FlashMAX PCIe SSD [rev 3D]) pci:v00001A78d00000031sv00001A78sd00000038* ID_MODEL_FROM_DATABASE=FlashMAX Drive (FlashMAX PCIe SSD [rev 4]) pci:v00001A78d00000031sv00001A78sd00000039* ID_MODEL_FROM_DATABASE=FlashMAX Drive (FlashMAX PCIe SSD [rev 4D]) pci:v00001A78d00000040* ID_MODEL_FROM_DATABASE=FlashMAX II pci:v00001A78d00000041* ID_MODEL_FROM_DATABASE=FlashMAX II pci:v00001A78d00000042* ID_MODEL_FROM_DATABASE=FlashMAX II pci:v00001A78d00000050* ID_MODEL_FROM_DATABASE=FlashMAX III pci:v00001A84* ID_VENDOR_FROM_DATABASE=Commex Technologies pci:v00001A84d00000001* ID_MODEL_FROM_DATABASE=Vulcan SP HT6210 10-Gigabit Ethernet (rev 02) pci:v00001A88* ID_VENDOR_FROM_DATABASE=MEN Mikro Elektronik pci:v00001A88d00004D45* ID_MODEL_FROM_DATABASE=Multifunction IP core pci:v00001A8A* ID_VENDOR_FROM_DATABASE=StarBridge, Inc. pci:v00001A8C* ID_VENDOR_FROM_DATABASE=Verigy Pte. Ltd. pci:v00001A8Cd00001100* ID_MODEL_FROM_DATABASE=E8001-66443 PCI Express CIC pci:v00001A8E* ID_VENDOR_FROM_DATABASE=DRS Technologies pci:v00001A8Ed00002090* ID_MODEL_FROM_DATABASE=Model 2090 PCI Express pci:v00001AA8* ID_VENDOR_FROM_DATABASE=Ciprico, Inc. pci:v00001AA8d00000009* ID_MODEL_FROM_DATABASE=RAIDCore Controller pci:v00001AA8d0000000A* ID_MODEL_FROM_DATABASE=RAIDCore Controller pci:v00001AAE* ID_VENDOR_FROM_DATABASE=Global Velocity, Inc. pci:v00001AB6* ID_VENDOR_FROM_DATABASE=CalDigit, Inc. pci:v00001AB6d00006201* ID_MODEL_FROM_DATABASE=RAID Card pci:v00001AB8* ID_VENDOR_FROM_DATABASE=Parallels, Inc. pci:v00001AB8d00004000* ID_MODEL_FROM_DATABASE=Virtual Machine Communication Interface pci:v00001AB8d00004005* ID_MODEL_FROM_DATABASE=Accelerated Virtual Video Adapter pci:v00001AB8d00004006* ID_MODEL_FROM_DATABASE=Memory Ballooning Controller pci:v00001AB9* ID_VENDOR_FROM_DATABASE=Espia Srl pci:v00001AC8* ID_VENDOR_FROM_DATABASE=Aeroflex Gaisler pci:v00001ACC* ID_VENDOR_FROM_DATABASE=Point of View BV pci:v00001AD7* ID_VENDOR_FROM_DATABASE=Spectracom Corporation pci:v00001AD7d00008000* ID_MODEL_FROM_DATABASE=TSync-PCIe Time Code Processor pci:v00001AD7d00009100* ID_MODEL_FROM_DATABASE=TPRO-PCI-66U Timecode Reader/Generator pci:v00001ADE* ID_VENDOR_FROM_DATABASE=Spin Master Ltd. pci:v00001ADEd00001501* ID_MODEL_FROM_DATABASE=Swipetech barcode scanner pci:v00001AE0* ID_VENDOR_FROM_DATABASE=Google, Inc. pci:v00001AE7* ID_VENDOR_FROM_DATABASE=First Wise Media GmbH pci:v00001AE7d00000520* ID_MODEL_FROM_DATABASE=HFC-S PCI A [X-TENSIONS XC-520] pci:v00001AE8* ID_VENDOR_FROM_DATABASE=Silicon Software GmbH pci:v00001AE8d00000A40* ID_MODEL_FROM_DATABASE=microEnable IV-BASE x1 pci:v00001AE8d00000A41* ID_MODEL_FROM_DATABASE=microEnable IV-FULL x1 pci:v00001AE8d00000A44* ID_MODEL_FROM_DATABASE=microEnable IV-FULL x4 pci:v00001AE8d00000E44* ID_MODEL_FROM_DATABASE=microEnable IV-GigE x4 pci:v00001AE9* ID_VENDOR_FROM_DATABASE=Wilocity Ltd. pci:v00001AE9d00000101* ID_MODEL_FROM_DATABASE=Wil6200 PCI Express Root Port pci:v00001AE9d00000200* ID_MODEL_FROM_DATABASE=Wil6200 PCI Express Port pci:v00001AE9d00000201* ID_MODEL_FROM_DATABASE=Wil6200 Wireless PCI Express Port pci:v00001AE9d00000301* ID_MODEL_FROM_DATABASE=Wil6200 802.11ad Wireless Network Adapter pci:v00001AE9d00000302* ID_MODEL_FROM_DATABASE=Wil6200 802.11ad Wireless Network Adapter pci:v00001AE9d00000310* ID_MODEL_FROM_DATABASE=Wil6200 802.11ad Wireless Network Adapter pci:v00001AEA* ID_VENDOR_FROM_DATABASE=Alcor Micro pci:v00001AEAd00006601* ID_MODEL_FROM_DATABASE=AU6601 PCI-E Flash card reader controller pci:v00001AEC* ID_VENDOR_FROM_DATABASE=Wolfson Microelectronics pci:v00001AED* ID_VENDOR_FROM_DATABASE=SanDisk pci:v00001AEDd00001003* ID_MODEL_FROM_DATABASE=ioDimm3 (v1.2) pci:v00001AEDd00001005* ID_MODEL_FROM_DATABASE=ioDimm3 pci:v00001AEDd00001005sv00001014sd000003C3* ID_MODEL_FROM_DATABASE=ioDimm3 (High IOPS SSD PCIe Adapter) pci:v00001AEDd00001005sv0000103Csd0000176F* ID_MODEL_FROM_DATABASE=ioDimm3 (1.28TB MLC PCIe ioDrive Duo) pci:v00001AEDd00001005sv0000103Csd00001770* ID_MODEL_FROM_DATABASE=ioDimm3 (5.2TB MLC PCIe ioDrive Octal) pci:v00001AEDd00001005sv0000103Csd0000178B* ID_MODEL_FROM_DATABASE=ioDimm3 (160GB SLC PCIe ioDrive) pci:v00001AEDd00001005sv0000103Csd0000178C* ID_MODEL_FROM_DATABASE=ioDimm3 (320GB MLC PCIe ioDrive) pci:v00001AEDd00001005sv0000103Csd0000178D* ID_MODEL_FROM_DATABASE=ioDimm3 (320GB SLC PCIe ioDrive Duo) pci:v00001AEDd00001005sv0000103Csd0000178E* ID_MODEL_FROM_DATABASE=ioDimm3 (640GB MLC PCIe ioDrive Duo) pci:v00001AEDd00001006* ID_MODEL_FROM_DATABASE=ioXtreme pci:v00001AEDd00001007* ID_MODEL_FROM_DATABASE=ioXtreme Pro pci:v00001AEDd00001008* ID_MODEL_FROM_DATABASE=ioXtreme-2 pci:v00001AEDd00002001* ID_MODEL_FROM_DATABASE=ioDrive2 pci:v00001AEDd00003001* ID_MODEL_FROM_DATABASE=ioMemory FHHL pci:v00001AEDd00003002* ID_MODEL_FROM_DATABASE=ioMemory HHHL pci:v00001AEDd00003003* ID_MODEL_FROM_DATABASE=ioMemory Mezzanine pci:v00001AEE* ID_VENDOR_FROM_DATABASE=Caustic Graphics Inc. pci:v00001AF4* ID_VENDOR_FROM_DATABASE=Red Hat, Inc pci:v00001AF4d00001000* ID_MODEL_FROM_DATABASE=Virtio network device pci:v00001AF4d00001001* ID_MODEL_FROM_DATABASE=Virtio block device pci:v00001AF4d00001002* ID_MODEL_FROM_DATABASE=Virtio memory balloon pci:v00001AF4d00001003* ID_MODEL_FROM_DATABASE=Virtio console pci:v00001AF4d00001004* ID_MODEL_FROM_DATABASE=Virtio SCSI pci:v00001AF4d00001005* ID_MODEL_FROM_DATABASE=Virtio RNG pci:v00001AF4d00001009* ID_MODEL_FROM_DATABASE=Virtio filesystem pci:v00001AF4d00001010* ID_MODEL_FROM_DATABASE=Virtio GPU pci:v00001AF4d00001012* ID_MODEL_FROM_DATABASE=Virtio input device pci:v00001AF4d00001110* ID_MODEL_FROM_DATABASE=Inter-VM shared memory pci:v00001AF4d00001110sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=Inter-VM shared memory (QEMU Virtual Machine) pci:v00001AF5* ID_VENDOR_FROM_DATABASE=Netezza Corp. pci:v00001AFA* ID_VENDOR_FROM_DATABASE=J & W Electronics Co., Ltd. pci:v00001B03* ID_VENDOR_FROM_DATABASE=Magnum Semiconductor, Inc, pci:v00001B03d00006100* ID_MODEL_FROM_DATABASE=DXT/DXTPro Multiformat Broadcast HD/SD Encoder/Decoder/Transcoder pci:v00001B03d00007000* ID_MODEL_FROM_DATABASE=D7 Multiformat Broadcast HD/SD Encoder/Decoder/Transcoder pci:v00001B08* ID_VENDOR_FROM_DATABASE=MSC Vertriebs GmbH pci:v00001B0A* ID_VENDOR_FROM_DATABASE=Pegatron pci:v00001B13* ID_VENDOR_FROM_DATABASE=Jaton Corp pci:v00001B1A* ID_VENDOR_FROM_DATABASE=K&F Computing Research Co. pci:v00001B1Ad00000E70* ID_MODEL_FROM_DATABASE=GRAPE pci:v00001B21* ID_VENDOR_FROM_DATABASE=ASMedia Technology Inc. pci:v00001B21d00000611* ID_MODEL_FROM_DATABASE=ASM1061 SATA IDE Controller pci:v00001B21d00000612* ID_MODEL_FROM_DATABASE=ASM1062 Serial ATA Controller pci:v00001B21d00000612sv00001849sd00000612* ID_MODEL_FROM_DATABASE=ASM1062 Serial ATA Controller (Motherboard) pci:v00001B21d00001042* ID_MODEL_FROM_DATABASE=ASM1042 SuperSpeed USB Host Controller pci:v00001B21d00001042sv00001043sd00008488* ID_MODEL_FROM_DATABASE=ASM1042 SuperSpeed USB Host Controller (P8B WS Motherboard) pci:v00001B21d00001042sv00001849sd00001042* ID_MODEL_FROM_DATABASE=ASM1042 SuperSpeed USB Host Controller (Motherboard) pci:v00001B21d00001080* ID_MODEL_FROM_DATABASE=ASM1083/1085 PCIe to PCI Bridge pci:v00001B21d00001080sv00001849sd00001080* ID_MODEL_FROM_DATABASE=ASM1083/1085 PCIe to PCI Bridge (Motherboard) pci:v00001B21d00001142* ID_MODEL_FROM_DATABASE=ASM1042A USB 3.0 Host Controller pci:v00001B21d00001242* ID_MODEL_FROM_DATABASE=ASM1142 USB 3.1 Host Controller pci:v00001B2C* ID_VENDOR_FROM_DATABASE=Opal-RT Technologies Inc. pci:v00001B36* ID_VENDOR_FROM_DATABASE=Red Hat, Inc. pci:v00001B36d00000001* ID_MODEL_FROM_DATABASE=QEMU PCI-PCI bridge pci:v00001B36d00000002* ID_MODEL_FROM_DATABASE=QEMU PCI 16550A Adapter pci:v00001B36d00000002sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=QEMU PCI 16550A Adapter (QEMU Virtual Machine) pci:v00001B36d00000003* ID_MODEL_FROM_DATABASE=QEMU PCI Dual-port 16550A Adapter pci:v00001B36d00000003sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=QEMU PCI Dual-port 16550A Adapter (QEMU Virtual Machine) pci:v00001B36d00000004* ID_MODEL_FROM_DATABASE=QEMU PCI Quad-port 16550A Adapter pci:v00001B36d00000004sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=QEMU PCI Quad-port 16550A Adapter (QEMU Virtual Machine) pci:v00001B36d00000005* ID_MODEL_FROM_DATABASE=QEMU PCI Test Device pci:v00001B36d00000005sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=QEMU PCI Test Device (QEMU Virtual Machine) pci:v00001B36d00000100* ID_MODEL_FROM_DATABASE=QXL paravirtual graphic card pci:v00001B36d00000100sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=QXL paravirtual graphic card (QEMU Virtual Machine) pci:v00001B37* ID_VENDOR_FROM_DATABASE=Signal Processing Devices Sweden AB pci:v00001B37d00000001* ID_MODEL_FROM_DATABASE=ADQ214 pci:v00001B37d00000003* ID_MODEL_FROM_DATABASE=ADQ114 pci:v00001B37d00000005* ID_MODEL_FROM_DATABASE=ADQ112 pci:v00001B37d0000000E* ID_MODEL_FROM_DATABASE=ADQ108 pci:v00001B37d0000000F* ID_MODEL_FROM_DATABASE=ADQDSP pci:v00001B37d00000014* ID_MODEL_FROM_DATABASE=ADQ412 pci:v00001B37d00000015* ID_MODEL_FROM_DATABASE=ADQ212 pci:v00001B37d0000001B* ID_MODEL_FROM_DATABASE=SDR14 pci:v00001B37d0000001C* ID_MODEL_FROM_DATABASE=ADQ1600 pci:v00001B37d0000001E* ID_MODEL_FROM_DATABASE=ADQ208 pci:v00001B37d0000001F* ID_MODEL_FROM_DATABASE=DSU pci:v00001B37d00000020* ID_MODEL_FROM_DATABASE=ADQ14 pci:v00001B37d00002014* ID_MODEL_FROM_DATABASE=TX320 pci:v00001B37d00002019* ID_MODEL_FROM_DATABASE=S6000 pci:v00001B39* ID_VENDOR_FROM_DATABASE=sTec, Inc. pci:v00001B39d00000001* ID_MODEL_FROM_DATABASE=S1120 PCIe Accelerator SSD pci:v00001B3A* ID_VENDOR_FROM_DATABASE=Westar Display Technologies pci:v00001B3Ad00007589* ID_MODEL_FROM_DATABASE=HRED J2000 - JPEG 2000 Video Codec Device pci:v00001B3E* ID_VENDOR_FROM_DATABASE=Teradata Corp. pci:v00001B3Ed00001FA8* ID_MODEL_FROM_DATABASE=BYNET BIC2SE/X pci:v00001B3Ed00001FA8sv00001B3Esd000000A3* ID_MODEL_FROM_DATABASE=BYNET BIC2SE/X (BYNET BIC2SX) pci:v00001B3Ed00001FA8sv00001B3Esd000000C3* ID_MODEL_FROM_DATABASE=BYNET BIC2SE/X (BYNET BIC2SE) pci:v00001B40* ID_VENDOR_FROM_DATABASE=Schooner Information Technology, Inc. pci:v00001B47* ID_VENDOR_FROM_DATABASE=Numascale AS pci:v00001B47d00000601* ID_MODEL_FROM_DATABASE=NumaChip N601 pci:v00001B47d00000602* ID_MODEL_FROM_DATABASE=NumaChip N602 pci:v00001B4B* ID_VENDOR_FROM_DATABASE=Marvell Technology Group Ltd. pci:v00001B4Bd00000640* ID_MODEL_FROM_DATABASE=88SE9128 SATA III 6Gb/s RAID Controller pci:v00001B4Bd00009120* ID_MODEL_FROM_DATABASE=88SE9120 SATA 6Gb/s Controller pci:v00001B4Bd00009123* ID_MODEL_FROM_DATABASE=88SE9123 PCIe SATA 6.0 Gb/s controller pci:v00001B4Bd00009123sv0000DC93sd0000600E* ID_MODEL_FROM_DATABASE=88SE9123 PCIe SATA 6.0 Gb/s controller (DC-6xxe series SATA 6G controller) pci:v00001B4Bd00009125* ID_MODEL_FROM_DATABASE=88SE9125 PCIe SATA 6.0 Gb/s controller pci:v00001B4Bd00009128* ID_MODEL_FROM_DATABASE=88SE9128 PCIe SATA 6 Gb/s RAID controller pci:v00001B4Bd00009130* ID_MODEL_FROM_DATABASE=88SE9128 PCIe SATA 6 Gb/s RAID controller with HyperDuo pci:v00001B4Bd00009130sv00001043sd00008438* ID_MODEL_FROM_DATABASE=88SE9128 PCIe SATA 6 Gb/s RAID controller with HyperDuo (P8P67 Deluxe Motherboard) pci:v00001B4Bd00009172* ID_MODEL_FROM_DATABASE=88SE9172 SATA 6Gb/s Controller pci:v00001B4Bd00009178* ID_MODEL_FROM_DATABASE=88SE9170 PCIe SATA 6Gb/s Controller pci:v00001B4Bd0000917A* ID_MODEL_FROM_DATABASE=88SE9172 SATA III 6Gb/s RAID Controller pci:v00001B4Bd00009183* ID_MODEL_FROM_DATABASE=88SS9183 PCIe SSD Controller pci:v00001B4Bd00009192* ID_MODEL_FROM_DATABASE=88SE9172 SATA III 6Gb/s RAID Controller pci:v00001B4Bd000091A0* ID_MODEL_FROM_DATABASE=88SE912x SATA 6Gb/s Controller [IDE mode] pci:v00001B4Bd000091A4* ID_MODEL_FROM_DATABASE=88SE912x IDE Controller pci:v00001B4Bd00009220* ID_MODEL_FROM_DATABASE=88SE9220 PCIe 2.0 x2 2-port SATA 6 Gb/s RAID Controller pci:v00001B4Bd00009230* ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller pci:v00001B4Bd00009235* ID_MODEL_FROM_DATABASE=88SE9235 PCIe 2.0 x2 4-port SATA 6 Gb/s Controller pci:v00001B4Bd00009445* ID_MODEL_FROM_DATABASE=88SE9445 PCIe 2.0 x4 4-Port SAS/SATA 6 Gbps RAID Controller pci:v00001B4Bd00009480* ID_MODEL_FROM_DATABASE=88SE9480 SAS/SATA 6Gb/s RAID controller pci:v00001B4Bd00009485* ID_MODEL_FROM_DATABASE=88SE9485 SAS/SATA 6Gb/s controller pci:v00001B55* ID_VENDOR_FROM_DATABASE=NetUP Inc. pci:v00001B55d000018F6* ID_MODEL_FROM_DATABASE=Dual DVB Universal CI card pci:v00001B55d00002A2C* ID_MODEL_FROM_DATABASE=Dual DVB-S2-CI card pci:v00001B55d0000E2E4* ID_MODEL_FROM_DATABASE=Dual DVB-T/C-CI RF card pci:v00001B55d0000E5F4* ID_MODEL_FROM_DATABASE=MPEG2 and H264 Encoder-Transcoder pci:v00001B55d0000F1C4* ID_MODEL_FROM_DATABASE=Dual ASI-RX/TX-CI card pci:v00001B66* ID_VENDOR_FROM_DATABASE=Deltacast pci:v00001B66d00000007* ID_MODEL_FROM_DATABASE=Delta-3G-elp-11 SDI I/O Board pci:v00001B6F* ID_VENDOR_FROM_DATABASE=Etron Technology, Inc. pci:v00001B6Fd00007023* ID_MODEL_FROM_DATABASE=EJ168 USB 3.0 Host Controller pci:v00001B6Fd00007052* ID_MODEL_FROM_DATABASE=EJ188/EJ198 USB 3.0 Host Controller pci:v00001B73* ID_VENDOR_FROM_DATABASE=Fresco Logic pci:v00001B73d00001000* ID_MODEL_FROM_DATABASE=FL1000G USB 3.0 Host Controller pci:v00001B73d00001000sv00001D5Csd00001000* ID_MODEL_FROM_DATABASE=FL1000G USB 3.0 Host Controller (Anker USB 3.0 Express Card) pci:v00001B73d00001009* ID_MODEL_FROM_DATABASE=FL1009 USB 3.0 Host Controller pci:v00001B73d00001100* ID_MODEL_FROM_DATABASE=FL1100 USB 3.0 Host Controller pci:v00001B74* ID_VENDOR_FROM_DATABASE=OpenVox Communication Co. Ltd. pci:v00001B74d00000115* ID_MODEL_FROM_DATABASE=D115P/D115E Single-port E1/T1 card pci:v00001B74d0000D130* ID_MODEL_FROM_DATABASE=D130P/D130E Single-port E1/T1 card (3rd GEN) pci:v00001B74d0000D210* ID_MODEL_FROM_DATABASE=D210P/D210E Dual-port E1/T1 card(2nd generation) pci:v00001B74d0000D230* ID_MODEL_FROM_DATABASE=D230 Dual-port E1/T1 card (2nd generation) pci:v00001B74d0000D410* ID_MODEL_FROM_DATABASE=D410/430 Quad-port E1/T1 card pci:v00001B74d0000D430* ID_MODEL_FROM_DATABASE=D410/430 Quad-port E1/T1 card pci:v00001B85* ID_VENDOR_FROM_DATABASE=OCZ Technology Group, Inc. pci:v00001B85d00001041* ID_MODEL_FROM_DATABASE=RevoDrive 3 X2 PCI-Express SSD 240 GB (Marvell Controller) pci:v00001B85d00008788* ID_MODEL_FROM_DATABASE=RevoDrive Hybrid pci:v00001B94* ID_VENDOR_FROM_DATABASE=Signatec / Dynamic Signals Corp pci:v00001B94d0000E400* ID_MODEL_FROM_DATABASE=PX14400 Dual Xilinx Virtex5 based Digitizer pci:v00001B96* ID_VENDOR_FROM_DATABASE=Western Digital pci:v00001B9A* ID_VENDOR_FROM_DATABASE=XAVi Technologies Corp. pci:v00001BAD* ID_VENDOR_FROM_DATABASE=ReFLEX CES pci:v00001BB0* ID_VENDOR_FROM_DATABASE=SimpliVity Corporation pci:v00001BB0d00000002* ID_MODEL_FROM_DATABASE=OmniCube Accelerator OA-3000 pci:v00001BB0d00000010* ID_MODEL_FROM_DATABASE=OmniCube Accelerator OA-3000-2 pci:v00001BB1* ID_VENDOR_FROM_DATABASE=Seagate Technology PLC pci:v00001BB1d0000005D* ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage pci:v00001BB1d0000005Dsv00001BB1sd00006501* ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XP6500-8A1536 1.5TB) pci:v00001BB1d0000005Dsv00001BB1sd00006502* ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XP6500-8A2048) pci:v00001BB1d0000005Dsv00001BB1sd00006503* ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XP6500-8A4096) pci:v00001BB1d0000005Dsv00001BB1sd00006511* ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XH6550-2GB DRAM) pci:v00001BB1d0000005Dsv00001BB1sd00006512* ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XH6550-8GB DRAM) pci:v00001BB1d0000005Dsv00001BB1sd00006521* ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XP6500-8A1536 1.5TB) pci:v00001BB1d0000005Dsv00001BB1sd00006522* ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XP6500-8A2048) pci:v00001BB1d0000005Dsv00001BB1sd00006523* ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XP6500-8A4096) pci:v00001BB3* ID_VENDOR_FROM_DATABASE=Bluecherry pci:v00001BB3d00004304* ID_MODEL_FROM_DATABASE=BC-04120A MPEG4 4 port video encoder / decoder pci:v00001BB3d00004309* ID_MODEL_FROM_DATABASE=BC-08240A MPEG4 4 port video encoder / decoder pci:v00001BB3d00004310* ID_MODEL_FROM_DATABASE=BC-16480A MPEG4 16 port video encoder / decoder pci:v00001BB3d00004E04* ID_MODEL_FROM_DATABASE=BC-04120A 4 port MPEG4 video encoder / decoder pci:v00001BB3d00004E09* ID_MODEL_FROM_DATABASE=BC-08240A 8 port MPEG4 video encoder / decoder pci:v00001BB3d00004E10* ID_MODEL_FROM_DATABASE=BC-16480A 16 port MPEG4 video encoder / decoder pci:v00001BB3d00005304* ID_MODEL_FROM_DATABASE=BC-H04120A 4 port H.264 video and audio encoder / decoder pci:v00001BB3d00005308* ID_MODEL_FROM_DATABASE=BC-H08240A 8 port H.264 video and audio encoder / decoder pci:v00001BB3d00005310* ID_MODEL_FROM_DATABASE=BC-H16480A 16 port H.264 video and audio encoder / decoder pci:v00001BB5* ID_VENDOR_FROM_DATABASE=Quantenna Communications, Inc. pci:v00001BBF* ID_VENDOR_FROM_DATABASE=Maxeler Technologies Ltd. pci:v00001BBFd00000003* ID_MODEL_FROM_DATABASE=MAX3 pci:v00001BBFd00000004* ID_MODEL_FROM_DATABASE=MAX4 pci:v00001BD0* ID_VENDOR_FROM_DATABASE=Astronics Corporation pci:v00001BD0d00001001* ID_MODEL_FROM_DATABASE=Mx5 PMC/XMC Databus Interface Card pci:v00001BD0d00001002* ID_MODEL_FROM_DATABASE=PM1553-5 (PC/104+ MIL-STD-1553 Interface Card) pci:v00001BD0d00001004* ID_MODEL_FROM_DATABASE=AB3000 Series Rugged Computer pci:v00001BD0d00001005* ID_MODEL_FROM_DATABASE=PE1000 (Multi-Protocol PCIe/104 Interface Card) pci:v00001BD0d00001101* ID_MODEL_FROM_DATABASE=OmniBus II PCIe Multi-Protocol Interface Card pci:v00001BD0d00001102* ID_MODEL_FROM_DATABASE=OmniBusBox II Multi-Protocol Interface Core pci:v00001BD0d00001103* ID_MODEL_FROM_DATABASE=OmniBus II cPCIe/PXIe Multi-Protocol Interface Card pci:v00001BD4* ID_VENDOR_FROM_DATABASE=Inspur Electronic Information Industry Co., Ltd. pci:v00001BEE* ID_VENDOR_FROM_DATABASE=IXXAT Automation GmbH pci:v00001BEEd00000003* ID_MODEL_FROM_DATABASE=CAN-IB200/PCIe pci:v00001BF4* ID_VENDOR_FROM_DATABASE=VTI Instruments Corporation pci:v00001BF4d00000001* ID_MODEL_FROM_DATABASE=SentinelEX pci:v00001BFD* ID_VENDOR_FROM_DATABASE=EeeTOP pci:v00001C09* ID_VENDOR_FROM_DATABASE=CSP, Inc. pci:v00001C09d00004254* ID_MODEL_FROM_DATABASE=10G-PCIE3-8D-2S pci:v00001C09d00004255* ID_MODEL_FROM_DATABASE=10G-PCIE3-8D-Q pci:v00001C09d00004256* ID_MODEL_FROM_DATABASE=10G-PCIE3-8D-2S pci:v00001C1C* ID_VENDOR_FROM_DATABASE=Symphony pci:v00001C1Cd00000001* ID_MODEL_FROM_DATABASE=82C101 pci:v00001C28* ID_VENDOR_FROM_DATABASE=Lite-On IT Corp. / Plextor pci:v00001C28d00000122* ID_MODEL_FROM_DATABASE=M6e PCI Express SSD [Marvell 88SS9183] pci:v00001C2C* ID_VENDOR_FROM_DATABASE=Fiberblaze pci:v00001C2Cd0000000A* ID_MODEL_FROM_DATABASE=Capture pci:v00001C2Cd0000000F* ID_MODEL_FROM_DATABASE=SmartNIC pci:v00001C2Cd000000A0* ID_MODEL_FROM_DATABASE=FBC4G Capture 4x1Gb pci:v00001C2Cd000000A1* ID_MODEL_FROM_DATABASE=FBC4XG Capture 4x10Gb pci:v00001C2Cd000000A2* ID_MODEL_FROM_DATABASE=FBC8XG Capture 8x10Gb pci:v00001C2Cd000000A3* ID_MODEL_FROM_DATABASE=FBC2XG Capture 2x10Gb pci:v00001C2Cd000000A4* ID_MODEL_FROM_DATABASE=FBC4XGG3 Capture 4x10Gb pci:v00001C2Cd000000A5* ID_MODEL_FROM_DATABASE=FBC2XLG Capture 2x40Gb pci:v00001C2Cd000000A6* ID_MODEL_FROM_DATABASE=FBC1CG Capture 1x100Gb pci:v00001C2Cd000000A9* ID_MODEL_FROM_DATABASE=FBC2XGHH Capture 2x10Gb pci:v00001C2Cd000000AF* ID_MODEL_FROM_DATABASE=Capture slave device pci:v00001C32* ID_VENDOR_FROM_DATABASE=Highland Technology, Inc. pci:v00001C33* ID_VENDOR_FROM_DATABASE=Daktronics, Inc pci:v00001C3B* ID_VENDOR_FROM_DATABASE=Accensus, LLC pci:v00001C3Bd00000200* ID_MODEL_FROM_DATABASE=Telas2 pci:v00001C3Bd00000300* ID_MODEL_FROM_DATABASE=Telas 2.V pci:v00001C44* ID_VENDOR_FROM_DATABASE=Enmotus Inc pci:v00001C44d00008000* ID_MODEL_FROM_DATABASE=8000 Storage IO Controller pci:v00001C58* ID_VENDOR_FROM_DATABASE=HGST, Inc. pci:v00001C58d00000003* ID_MODEL_FROM_DATABASE=Ultrastar SN100 Series NVMe SSD pci:v00001C58d00000003sv00001014sd000004F5* ID_MODEL_FROM_DATABASE=Ultrastar SN100 Series NVMe SSD (PCIe3 1.6TB NVMe Adapter) pci:v00001C58d00000003sv00001014sd000004F6* ID_MODEL_FROM_DATABASE=Ultrastar SN100 Series NVMe SSD (PCIe3 3.2TB NVMe Adapter) pci:v00001C7E* ID_VENDOR_FROM_DATABASE=TTTech Computertechnik AG pci:v00001C7Ed00000200* ID_MODEL_FROM_DATABASE=zFAS Debug Port pci:v00001C7F* ID_VENDOR_FROM_DATABASE=Elektrobit Austria GmbH pci:v00001C7Fd00005100* ID_MODEL_FROM_DATABASE=EB5100 pci:v00001C8A* ID_VENDOR_FROM_DATABASE=TSF5 Corporation pci:v00001C8Ad00000001* ID_MODEL_FROM_DATABASE=Hunter PCI Express pci:v00001CB1* ID_VENDOR_FROM_DATABASE=Collion UG & Co.KG pci:v00001CC5* ID_VENDOR_FROM_DATABASE=Embedded Intelligence, Inc. pci:v00001CC5d00000100* ID_MODEL_FROM_DATABASE=CAN-PCIe-02 pci:v00001CD2* ID_VENDOR_FROM_DATABASE=SesKion GmbH pci:v00001CD2d00000301* ID_MODEL_FROM_DATABASE=Simulyzer-RT CompactPCI Serial DIO-1 card pci:v00001CD2d00000302* ID_MODEL_FROM_DATABASE=Simulyzer-RT CompactPCI Serial PSI5-ECU-1 card pci:v00001CD2d00000303* ID_MODEL_FROM_DATABASE=Simulyzer-RT CompactPCI Serial PSI5-SIM-1 card pci:v00001CD2d00000304* ID_MODEL_FROM_DATABASE=Simulyzer-RT CompactPCI Serial PWR-ANA-1 card pci:v00001CDD* ID_VENDOR_FROM_DATABASE=secunet Security Networks AG pci:v00001CE4* ID_VENDOR_FROM_DATABASE=Exablaze pci:v00001CE4d00000001* ID_MODEL_FROM_DATABASE=ExaNIC X4 pci:v00001CE4d00000002* ID_MODEL_FROM_DATABASE=ExaNIC X2 pci:v00001CE4d00000003* ID_MODEL_FROM_DATABASE=ExaNIC X10 pci:v00001CE4d00000004* ID_MODEL_FROM_DATABASE=ExaNIC X10-GM pci:v00001CE4d00000005* ID_MODEL_FROM_DATABASE=ExaNIC X40 pci:v00001CF7* ID_VENDOR_FROM_DATABASE=Subspace Dynamics pci:v00001D00* ID_VENDOR_FROM_DATABASE=Pure Storage pci:v00001D1D* ID_VENDOR_FROM_DATABASE=CNEX Labs pci:v00001D1Dd00001F1F* ID_MODEL_FROM_DATABASE=QEMU NVM Express LightNVM Controller pci:v00001D1Dd00002807* ID_MODEL_FROM_DATABASE=8800 series NVMe SSD pci:v00001D21* ID_VENDOR_FROM_DATABASE=Allo pci:v00001D26* ID_VENDOR_FROM_DATABASE=Kalray Inc. pci:v00001D26d00000040* ID_MODEL_FROM_DATABASE=Turbocard2 Accelerator pci:v00001D26d0000E004* ID_MODEL_FROM_DATABASE=AB01/EMB01 Development Board pci:v00001D40* ID_VENDOR_FROM_DATABASE=Techman Electronics (Changshu) Co., Ltd. pci:v00001D44* ID_VENDOR_FROM_DATABASE=DPT pci:v00001D44d0000A400* ID_MODEL_FROM_DATABASE=PM2x24/PM3224 pci:v00001D49* ID_VENDOR_FROM_DATABASE=Lenovo pci:v00001D5C* ID_VENDOR_FROM_DATABASE=Fantasia Trading LLC pci:v00001D61* ID_VENDOR_FROM_DATABASE=Technobox, Inc. pci:v00001D65* ID_VENDOR_FROM_DATABASE=Imagine Communications Corp. pci:v00001D65d000004DE* ID_MODEL_FROM_DATABASE=Taurus/McKinley pci:v00001D6C* ID_VENDOR_FROM_DATABASE=Atomic Rules LLC pci:v00001D6Cd00001001* ID_MODEL_FROM_DATABASE=A5PL-E1 pci:v00001D6Cd00001002* ID_MODEL_FROM_DATABASE=A5PL-E7 pci:v00001D6Cd00001003* ID_MODEL_FROM_DATABASE=S5PEDS-AB pci:v00001D6Cd00001004* ID_MODEL_FROM_DATABASE=KC705-K325 pci:v00001D6Cd00001005* ID_MODEL_FROM_DATABASE=ZC706-Z045 pci:v00001D6Cd00001006* ID_MODEL_FROM_DATABASE=KCU105-KU040 pci:v00001D6Cd00001007* ID_MODEL_FROM_DATABASE=XUSP3S-VU095 [Jasper] pci:v00001D6Cd00004200* ID_MODEL_FROM_DATABASE=A5PL-E1-10GETI [10 GbE Ethernet Traffic Instrument] pci:v00001DE1* ID_VENDOR_FROM_DATABASE=Tekram Technology Co.,Ltd. pci:v00001DE1d00000391* ID_MODEL_FROM_DATABASE=TRM-S1040 [DC-315 / DC-395 series] pci:v00001DE1d00002020* ID_MODEL_FROM_DATABASE=DC-390 pci:v00001DE1d0000690C* ID_MODEL_FROM_DATABASE=690c pci:v00001DE1d0000DC29* ID_MODEL_FROM_DATABASE=DC290 pci:v00001FC0* ID_VENDOR_FROM_DATABASE=Ascom (Finland) Oy pci:v00001FC0d00000300* ID_MODEL_FROM_DATABASE=E2200 Dual E1/Rawpipe Card pci:v00001FC0d00000301* ID_MODEL_FROM_DATABASE=C5400 SHDSL/E1 Card pci:v00001FC1* ID_VENDOR_FROM_DATABASE=QLogic, Corp. pci:v00001FC1d0000000D* ID_MODEL_FROM_DATABASE=IBA6110 InfiniBand HCA pci:v00001FC1d00000010* ID_MODEL_FROM_DATABASE=IBA6120 InfiniBand HCA pci:v00001FC9* ID_VENDOR_FROM_DATABASE=Tehuti Networks Ltd. pci:v00001FC9d00003009* ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC pci:v00001FC9d00003010* ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC pci:v00001FC9d00003010sv00000000sd00003002* ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC (10-Giga TOE Single Port XFP SmartNIC) pci:v00001FC9d00003010sv00000000sd00003004* ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC (10-Giga TOE Single Port SFP+ SmartNIC) pci:v00001FC9d00003010sv00000000sd00003008* ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC (10-Giga TOE Single Port CX4 SmartNIC) pci:v00001FC9d00003014* ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC 2-Port pci:v00001FC9d00003014sv00000000sd00003003* ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC 2-Port (10-Giga TOE Dual Port XFP Low Profile SmartNIC) pci:v00001FC9d00003014sv00000000sd00003005* ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC 2-Port (10-Giga TOE Dual Port SFP+ Low Profile SmartNIC) pci:v00001FC9d00003014sv00000000sd00003014* ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC 2-Port (10-Giga TOE Dual Port CX4 Low Profile SmartNIC) pci:v00001FC9d00003110* ID_MODEL_FROM_DATABASE=10-Giga TOE Single Port SmartNIC pci:v00001FC9d00003110sv00000000sd00003004* ID_MODEL_FROM_DATABASE=10-Giga TOE Single Port SmartNIC (10-Giga TOE Single Port SFP+ SmartNIC) pci:v00001FC9d00003114* ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC pci:v00001FC9d00003114sv00000000sd00003005* ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port SFP+ Low Profile SmartNIC) pci:v00001FC9d00003114sv00000000sd00003011* ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port SFP+/CX4 Low Profile SmartNIC) pci:v00001FC9d00003114sv00000000sd00003012* ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port CX4/SFP+ Low Profile SmartNIC) pci:v00001FC9d00003114sv00000000sd00003014* ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port CX4 Low Profile SmartNIC) pci:v00001FC9d00003310* ID_MODEL_FROM_DATABASE=10-Giga TOE SFP+ Single Port SmartNIC pci:v00001FC9d00003310sv00000000sd00003004* ID_MODEL_FROM_DATABASE=10-Giga TOE SFP+ Single Port SmartNIC (10-Giga TOE Single Port SFP+ SmartNIC) pci:v00001FC9d00003314* ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC pci:v00001FC9d00003314sv00000000sd00003005* ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port SFP+ Low Profile SmartNIC) pci:v00001FC9d00003314sv00000000sd00003011* ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port SFP+/CX4 Low Profile SmartNIC) pci:v00001FC9d00003314sv00000000sd00003012* ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port CX4/SFP+ Low Profile SmartNIC) pci:v00001FC9d00003314sv00000000sd00003014* ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port CX4 Low Profile SmartNIC) pci:v00001FC9d00004010* ID_MODEL_FROM_DATABASE=TN4010 Clean SROM pci:v00001FC9d00004020* ID_MODEL_FROM_DATABASE=TN9030 10GbE CX4 Ethernet Adapter pci:v00001FC9d00004022* ID_MODEL_FROM_DATABASE=TN9310 10GbE SFP+ Ethernet Adapter pci:v00001FC9d00004022sv00001186sd00004D00* ID_MODEL_FROM_DATABASE=TN9310 10GbE SFP+ Ethernet Adapter (DXE-810S 10GbE SFP+ Ethernet Adapter) pci:v00001FC9d00004022sv00001FC9sd00003015* ID_MODEL_FROM_DATABASE=TN9310 10GbE SFP+ Ethernet Adapter (Ethernet Adapter) pci:v00001FC9d00004024* ID_MODEL_FROM_DATABASE=TN9210 10GBase-T Ethernet Adapter pci:v00001FC9d00004025* ID_MODEL_FROM_DATABASE=TN9510 10GBase-T/NBASE-T Ethernet Adapter pci:v00001FC9d00004025sv00001186sd00002900* ID_MODEL_FROM_DATABASE=TN9510 10GBase-T/NBASE-T Ethernet Adapter (DXE-810T 10GBase-T Ethernet Adapter) pci:v00001FC9d00004025sv00001FC9sd00003015* ID_MODEL_FROM_DATABASE=TN9510 10GBase-T/NBASE-T Ethernet Adapter (Ethernet Adapter) pci:v00001FC9d00004026* ID_MODEL_FROM_DATABASE=TN9610 10GbE SFP+ Ethernet Adapter pci:v00001FC9d00004027* ID_MODEL_FROM_DATABASE=TN9710 10GBase-T/NBASE-T Ethernet Adapter pci:v00001FCC* ID_VENDOR_FROM_DATABASE=StreamLabs pci:v00001FCCd0000F416* ID_MODEL_FROM_DATABASE=MS416 pci:v00001FCCd0000FB01* ID_MODEL_FROM_DATABASE=MH4LM pci:v00001FCE* ID_VENDOR_FROM_DATABASE=Cognio Inc. pci:v00001FCEd00000001* ID_MODEL_FROM_DATABASE=Spectrum Analyzer PC Card (SAgE) pci:v00001FD4* ID_VENDOR_FROM_DATABASE=SUNIX Co., Ltd. pci:v00001FD4d00000001* ID_MODEL_FROM_DATABASE=Matrix multiport serial adapter pci:v00001FD4d00001999* ID_MODEL_FROM_DATABASE=Multiport serial controller pci:v00002000* ID_VENDOR_FROM_DATABASE=Smart Link Ltd. pci:v00002000d00002800* ID_MODEL_FROM_DATABASE=SmartPCI2800 V.92 PCI Soft DFT pci:v00002001* ID_VENDOR_FROM_DATABASE=Temporal Research Ltd pci:v00002003* ID_VENDOR_FROM_DATABASE=Smart Link Ltd. pci:v00002003d00008800* ID_MODEL_FROM_DATABASE=LM-I56N pci:v00002004* ID_VENDOR_FROM_DATABASE=Smart Link Ltd. pci:v000020F4* ID_VENDOR_FROM_DATABASE=TRENDnet pci:v00002116* ID_VENDOR_FROM_DATABASE=ZyDAS Technology Corp. pci:v000021C3* ID_VENDOR_FROM_DATABASE=21st Century Computer Corp. pci:v00002304* ID_VENDOR_FROM_DATABASE=Colorgraphic Communications Corp. pci:v00002348* ID_VENDOR_FROM_DATABASE=Racore pci:v00002348d00002010* ID_MODEL_FROM_DATABASE=8142 100VG/AnyLAN pci:v00002646* ID_VENDOR_FROM_DATABASE=Kingston Technologies pci:v0000270B* ID_VENDOR_FROM_DATABASE=Xantel Corporation pci:v0000270F* ID_VENDOR_FROM_DATABASE=Chaintech Computer Co. Ltd pci:v00002711* ID_VENDOR_FROM_DATABASE=AVID Technology Inc. pci:v00002955* ID_VENDOR_FROM_DATABASE=Connectix Virtual PC pci:v00002955d00006E61* ID_MODEL_FROM_DATABASE=OHCI USB 1.1 controller pci:v00002A15* ID_VENDOR_FROM_DATABASE=3D Vision(???) pci:v00002BD8* ID_VENDOR_FROM_DATABASE=ROPEX Industrie-Elektronik GmbH pci:v00003000* ID_VENDOR_FROM_DATABASE=Hansol Electronics Inc. pci:v00003112* ID_VENDOR_FROM_DATABASE=Satelco Ingenieria S.A. pci:v00003142* ID_VENDOR_FROM_DATABASE=Post Impression Systems. pci:v000031AB* ID_VENDOR_FROM_DATABASE=Zonet pci:v000031ABd00001FAA* ID_MODEL_FROM_DATABASE=ZEW1602 802.11b/g Wireless Adapter pci:v00003388* ID_VENDOR_FROM_DATABASE=Hint Corp pci:v00003388d00000013* ID_MODEL_FROM_DATABASE=HiNT HC4 PCI to ISDN bridge, Multimedia audio controller pci:v00003388d00000014* ID_MODEL_FROM_DATABASE=HiNT HC4 PCI to ISDN bridge, Network controller pci:v00003388d00000020* ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (transparent mode) pci:v00003388d00000021* ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) pci:v00003388d00000021sv00001775sd0000C200* ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (C2K CompactPCI interface bridge) pci:v00003388d00000021sv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (CE9) pci:v00003388d00000021sv00004C53sd00001050* ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (CT7 mainboard) pci:v00003388d00000021sv00004C53sd00001080* ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (CT8 mainboard) pci:v00003388d00000021sv00004C53sd00001090* ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (Cx9 mainboard) pci:v00003388d00000021sv00004C53sd000010A0* ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (CA3/CR3 mainboard) pci:v00003388d00000021sv00004C53sd00003010* ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (PPCI mezzanine (32-bit PMC)) pci:v00003388d00000021sv00004C53sd00003011* ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (PPCI mezzanine (64-bit PMC)) pci:v00003388d00000021sv00004C53sd00004000* ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (PMCCARR1 carrier board) pci:v00003388d00000022* ID_MODEL_FROM_DATABASE=HiNT HB4 PCI-PCI Bridge (PCI6150) pci:v00003388d00000026* ID_MODEL_FROM_DATABASE=HB2 PCI-PCI Bridge pci:v00003388d00001018* ID_MODEL_FROM_DATABASE=Audiotrak INCA88 pci:v00003388d00001019* ID_MODEL_FROM_DATABASE=Miditrak 2120 pci:v00003388d0000101A* ID_MODEL_FROM_DATABASE=E.Band [AudioTrak Inca88] pci:v00003388d0000101B* ID_MODEL_FROM_DATABASE=E.Band [AudioTrak Inca88] pci:v00003388d00008011* ID_MODEL_FROM_DATABASE=VXPro II Chipset pci:v00003388d00008011sv00003388sd00008011* ID_MODEL_FROM_DATABASE=VXPro II Chipset (CPU to PCI Bridge) pci:v00003388d00008012* ID_MODEL_FROM_DATABASE=VXPro II Chipset pci:v00003388d00008012sv00003388sd00008012* ID_MODEL_FROM_DATABASE=VXPro II Chipset (PCI to ISA Bridge) pci:v00003388d00008013* ID_MODEL_FROM_DATABASE=VXPro II IDE pci:v00003388d00008013sv00003388sd00008013* ID_MODEL_FROM_DATABASE=VXPro II IDE (VXPro II Chipset EIDE Controller) pci:v00003388d0000A103* ID_MODEL_FROM_DATABASE=Blackmagic Design DeckLink HD Pro pci:v00003411* ID_VENDOR_FROM_DATABASE=Quantum Designs (H.K.) Inc pci:v00003442* ID_VENDOR_FROM_DATABASE=Bihl+Wiedemann GmbH pci:v00003442d00001783* ID_MODEL_FROM_DATABASE=AS-i 3.0 cPCI Master pci:v00003442d00001922* ID_MODEL_FROM_DATABASE=AS-i 3.0 PCI Master pci:v00003475* ID_VENDOR_FROM_DATABASE=Arastra Inc. pci:v00003513* ID_VENDOR_FROM_DATABASE=ARCOM Control Systems Ltd pci:v000037D9* ID_VENDOR_FROM_DATABASE=ITD Firm ltd. pci:v000037D9d00001138* ID_MODEL_FROM_DATABASE=SCHD-PH-8 Phase detector pci:v000037D9d00001140* ID_MODEL_FROM_DATABASE=VR-12-PCI pci:v000037D9d00001141* ID_MODEL_FROM_DATABASE=PCI-485(422) pci:v000037D9d00001142* ID_MODEL_FROM_DATABASE=PCI-CAN2 pci:v00003842* ID_VENDOR_FROM_DATABASE=eVga.com. Corp. pci:v000038EF* ID_VENDOR_FROM_DATABASE=4Links pci:v00003D3D* ID_VENDOR_FROM_DATABASE=3DLabs pci:v00003D3Dd00000001* ID_MODEL_FROM_DATABASE=GLINT 300SX pci:v00003D3Dd00000002* ID_MODEL_FROM_DATABASE=GLINT 500TX pci:v00003D3Dd00000002sv00000000sd00000000* ID_MODEL_FROM_DATABASE=GLINT 500TX (GLoria L) pci:v00003D3Dd00000003* ID_MODEL_FROM_DATABASE=GLINT Delta pci:v00003D3Dd00000003sv00000000sd00000000* ID_MODEL_FROM_DATABASE=GLINT Delta (GLoria XL) pci:v00003D3Dd00000004* ID_MODEL_FROM_DATABASE=Permedia pci:v00003D3Dd00000005* ID_MODEL_FROM_DATABASE=Permedia pci:v00003D3Dd00000006* ID_MODEL_FROM_DATABASE=GLINT MX pci:v00003D3Dd00000006sv00000000sd00000000* ID_MODEL_FROM_DATABASE=GLINT MX (GLoria XL) pci:v00003D3Dd00000006sv00001048sd00000A42* ID_MODEL_FROM_DATABASE=GLINT MX (GLoria XXL) pci:v00003D3Dd00000007* ID_MODEL_FROM_DATABASE=3D Extreme pci:v00003D3Dd00000008* ID_MODEL_FROM_DATABASE=GLINT Gamma G1 pci:v00003D3Dd00000008sv00001048sd00000A42* ID_MODEL_FROM_DATABASE=GLINT Gamma G1 (GLoria XXL) pci:v00003D3Dd00000009* ID_MODEL_FROM_DATABASE=Permedia II 2D+3D pci:v00003D3Dd00000009sv00001040sd00000011* ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (AccelStar II) pci:v00003D3Dd00000009sv00001048sd00000A42* ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (GLoria XXL) pci:v00003D3Dd00000009sv000013E9sd00001000* ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (6221L-4U) pci:v00003D3Dd00000009sv00003D3Dsd00000100* ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (AccelStar II 3D Accelerator) pci:v00003D3Dd00000009sv00003D3Dsd00000111* ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Permedia 3:16) pci:v00003D3Dd00000009sv00003D3Dsd00000114* ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Santa Ana) pci:v00003D3Dd00000009sv00003D3Dsd00000116* ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Oxygen GVX1) pci:v00003D3Dd00000009sv00003D3Dsd00000119* ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Scirocco) pci:v00003D3Dd00000009sv00003D3Dsd00000120* ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Santa Ana PCL) pci:v00003D3Dd00000009sv00003D3Dsd00000125* ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Oxygen VX1) pci:v00003D3Dd00000009sv00003D3Dsd00000127* ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Permedia3 Create!) pci:v00003D3Dd0000000A* ID_MODEL_FROM_DATABASE=GLINT R3 pci:v00003D3Dd0000000Asv00003D3Dsd00000121* ID_MODEL_FROM_DATABASE=GLINT R3 (Oxygen VX1) pci:v00003D3Dd0000000C* ID_MODEL_FROM_DATABASE=GLINT R3 [Oxygen VX1] pci:v00003D3Dd0000000Csv00003D3Dsd00000144* ID_MODEL_FROM_DATABASE=GLINT R3 [Oxygen VX1] (Oxygen VX1-4X AGP [Permedia 4]) pci:v00003D3Dd0000000D* ID_MODEL_FROM_DATABASE=GLint R4 rev A pci:v00003D3Dd0000000E* ID_MODEL_FROM_DATABASE=GLINT Gamma G2 pci:v00003D3Dd00000011* ID_MODEL_FROM_DATABASE=GLint R4 rev B pci:v00003D3Dd00000012* ID_MODEL_FROM_DATABASE=GLint R5 rev A pci:v00003D3Dd00000013* ID_MODEL_FROM_DATABASE=GLint R5 rev B pci:v00003D3Dd00000020* ID_MODEL_FROM_DATABASE=VP10 visual processor pci:v00003D3Dd00000022* ID_MODEL_FROM_DATABASE=VP10 visual processor pci:v00003D3Dd00000024* ID_MODEL_FROM_DATABASE=VP9 visual processor pci:v00003D3Dd0000002C* ID_MODEL_FROM_DATABASE=Wildcat Realizm 100/200 pci:v00003D3Dd00000030* ID_MODEL_FROM_DATABASE=Wildcat Realizm 800 pci:v00003D3Dd00000032* ID_MODEL_FROM_DATABASE=Wildcat Realizm 500 pci:v00003D3Dd00000100* ID_MODEL_FROM_DATABASE=Permedia II 2D+3D pci:v00003D3Dd000007A1* ID_MODEL_FROM_DATABASE=Wildcat III 6210 pci:v00003D3Dd000007A2* ID_MODEL_FROM_DATABASE=Sun XVR-500 Graphics Accelerator pci:v00003D3Dd000007A3* ID_MODEL_FROM_DATABASE=Wildcat IV 7210 pci:v00003D3Dd00001004* ID_MODEL_FROM_DATABASE=Permedia pci:v00003D3Dd00003D04* ID_MODEL_FROM_DATABASE=Permedia pci:v00003D3Dd0000FFFF* ID_MODEL_FROM_DATABASE=Glint VGA pci:v00004005* ID_VENDOR_FROM_DATABASE=Avance Logic Inc. pci:v00004005d00000300* ID_MODEL_FROM_DATABASE=ALS300 PCI Audio Device pci:v00004005d00000308* ID_MODEL_FROM_DATABASE=ALS300+ PCI Audio Device pci:v00004005d00000309* ID_MODEL_FROM_DATABASE=PCI Input Controller pci:v00004005d00001064* ID_MODEL_FROM_DATABASE=ALG-2064 pci:v00004005d00002064* ID_MODEL_FROM_DATABASE=ALG-2064i pci:v00004005d00002128* ID_MODEL_FROM_DATABASE=ALG-2364A GUI Accelerator pci:v00004005d00002301* ID_MODEL_FROM_DATABASE=ALG-2301 pci:v00004005d00002302* ID_MODEL_FROM_DATABASE=ALG-2302 pci:v00004005d00002303* ID_MODEL_FROM_DATABASE=AVG-2302 GUI Accelerator pci:v00004005d00002364* ID_MODEL_FROM_DATABASE=ALG-2364A pci:v00004005d00002464* ID_MODEL_FROM_DATABASE=ALG-2464 pci:v00004005d00002501* ID_MODEL_FROM_DATABASE=ALG-2564A/25128A pci:v00004005d00004000* ID_MODEL_FROM_DATABASE=ALS4000 Audio Chipset pci:v00004005d00004000sv00004005sd00004000* ID_MODEL_FROM_DATABASE=ALS4000 Audio Chipset pci:v00004005d00004710* ID_MODEL_FROM_DATABASE=ALC200/200P pci:v00004033* ID_VENDOR_FROM_DATABASE=Addtron Technology Co, Inc. pci:v00004033d00001360* ID_MODEL_FROM_DATABASE=RTL8139 Ethernet pci:v00004040* ID_VENDOR_FROM_DATABASE=NetXen Incorporated pci:v00004040d00000001* ID_MODEL_FROM_DATABASE=NXB-10GXSR 10-Gigabit Ethernet PCIe Adapter with SR-XFP optical interface pci:v00004040d00000001sv0000103Csd00007047* ID_MODEL_FROM_DATABASE=NXB-10GXSR 10-Gigabit Ethernet PCIe Adapter with SR-XFP optical interface (NC510F PCIe 10-Gigabit Server Adapter) pci:v00004040d00000002* ID_MODEL_FROM_DATABASE=NXB-10GCX4 10-Gigabit Ethernet PCIe Adapter with CX4 copper interface pci:v00004040d00000002sv0000103Csd00007048* ID_MODEL_FROM_DATABASE=NXB-10GCX4 10-Gigabit Ethernet PCIe Adapter with CX4 copper interface (NC510c PCIe 10-Gigabit Server Adapter) pci:v00004040d00000003* ID_MODEL_FROM_DATABASE=NXB-4GCU Quad Gigabit Ethernet PCIe Adapter with 1000-BASE-T interface pci:v00004040d00000004* ID_MODEL_FROM_DATABASE=BladeCenter-H 10-Gigabit Ethernet High Speed Daughter Card pci:v00004040d00000005* ID_MODEL_FROM_DATABASE=NetXen Dual Port 10GbE Multifunction Adapter for c-Class pci:v00004040d00000005sv0000103Csd0000170E* ID_MODEL_FROM_DATABASE=NetXen Dual Port 10GbE Multifunction Adapter for c-Class (NC512m Dual Port 10GbE Multifunction BL-C Adapter) pci:v00004040d00000024* ID_MODEL_FROM_DATABASE=XG Mgmt pci:v00004040d00000025* ID_MODEL_FROM_DATABASE=XG Mgmt pci:v00004040d00000100* ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter pci:v00004040d00000100sv0000103Csd0000171B* ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (NC522m Dual Port 10GbE Multifunction BL-c Adapter) pci:v00004040d00000100sv0000103Csd00001740* ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (NC375T PCI Express Quad Port Gigabit Server Adapter) pci:v00004040d00000100sv0000103Csd00003251* ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (NC375i 1G w/NC524SFP 10G Module) pci:v00004040d00000100sv0000103Csd0000705A* ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (NC375i Integrated Quad Port Multifunction Gigabit Server Adapter) pci:v00004040d00000100sv0000103Csd0000705B* ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (NC522SFP Dual Port 10GbE Server Adapter) pci:v00004040d00000100sv0000152Dsd0000896B* ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (TG20 Dual Port 10GbE Server/Storage Adapter) pci:v00004040d00000100sv00004040sd00000124* ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (NX3031 Quad Port Gigabit Server Adapter) pci:v00004040d00000100sv00004040sd00000126* ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (Dual Port SFP+ 10GbE Server Adapter) pci:v00004143* ID_VENDOR_FROM_DATABASE=Digital Equipment Corp pci:v00004144* ID_VENDOR_FROM_DATABASE=Alpha Data pci:v00004144d00000044* ID_MODEL_FROM_DATABASE=ADM-XRCIIPro pci:v00004150* ID_VENDOR_FROM_DATABASE=ONA Electroerosion pci:v00004150d00000001* ID_MODEL_FROM_DATABASE=PCI32TLITE FILSTRUP1 PCI to VME Bridge Controller pci:v00004150d00000006* ID_MODEL_FROM_DATABASE=PCI32TLITE UART 16550 Opencores pci:v00004150d00000007* ID_MODEL_FROM_DATABASE=PCI32TLITE CAN Controller Opencores pci:v0000415A* ID_VENDOR_FROM_DATABASE=Auzentech, Inc. pci:v0000416C* ID_VENDOR_FROM_DATABASE=Aladdin Knowledge Systems pci:v0000416Cd00000100* ID_MODEL_FROM_DATABASE=AladdinCARD pci:v0000416Cd00000200* ID_MODEL_FROM_DATABASE=CPC pci:v00004254* ID_VENDOR_FROM_DATABASE=DVBSky pci:v00004321* ID_VENDOR_FROM_DATABASE=Tata Power Strategic Electronics Division pci:v00004348* ID_VENDOR_FROM_DATABASE=WCH.CN pci:v00004348d00002273* ID_MODEL_FROM_DATABASE=CH351 PCI Dual Serial Port Controller pci:v00004348d00003253* ID_MODEL_FROM_DATABASE=CH352 PCI Dual Serial Port Controller pci:v00004348d00003453* ID_MODEL_FROM_DATABASE=CH353 PCI Quad Serial Port Controller pci:v00004348d00005053* ID_MODEL_FROM_DATABASE=CH352 PCI Serial and Parallel Port Controller pci:v00004348d00007053* ID_MODEL_FROM_DATABASE=CH353 PCI Dual Serial and Parallel Ports Controller pci:v00004348d00007073* ID_MODEL_FROM_DATABASE=CH356 PCI Quad Serial and Parallel Ports Controller pci:v00004348d00007173* ID_MODEL_FROM_DATABASE=CH355 PCI Quad Serial Port Controller pci:v0000434E* ID_VENDOR_FROM_DATABASE=CAST Navigation LLC pci:v00004444* ID_VENDOR_FROM_DATABASE=Internext Compression Inc pci:v00004444d00000016* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder pci:v00004444d00000016sv00000070sd00000003* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 250) pci:v00004444d00000016sv00000070sd00000009* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) pci:v00004444d00000016sv00000070sd00000801* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) pci:v00004444d00000016sv00000070sd00000807* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) pci:v00004444d00000016sv00000070sd00004001* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 250) pci:v00004444d00000016sv00000070sd00004009* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 250) pci:v00004444d00000016sv00000070sd00004801* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 250) pci:v00004444d00000016sv00000070sd00004803* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 250) pci:v00004444d00000016sv00000070sd00008003* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) pci:v00004444d00000016sv00000070sd00008801* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) pci:v00004444d00000016sv00000070sd0000C801* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) pci:v00004444d00000016sv00000070sd0000E807* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 500 (1st unit)) pci:v00004444d00000016sv00000070sd0000E817* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 500 (2nd unit)) pci:v00004444d00000016sv00000070sd0000FF92* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WiNTV PVR-550) pci:v00004444d00000016sv00000270sd00000801* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) pci:v00004444d00000016sv0000104Dsd0000013D* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (ENX-26 TV Encoder) pci:v00004444d00000016sv000010FCsd0000D038* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (GV-MVP/RX2W (1st unit)) pci:v00004444d00000016sv000010FCsd0000D039* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (GV-MVP/RX2W (2nd unit)) pci:v00004444d00000016sv000012ABsd0000FFF3* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (MPG600) pci:v00004444d00000016sv000012ABsd0000FFFF* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (MPG600) pci:v00004444d00000016sv00001461sd0000C00A* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (PAL/SECAM, Philips FQ1216MK3 tuner)) pci:v00004444d00000016sv00001461sd0000C00B* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (PAL/SECAM+FM, Philips FM1216MK3 tuner)) pci:v00004444d00000016sv00001461sd0000C00C* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC, JAPAN version, Philips FI1286MK2 tuner)) pci:v00004444d00000016sv00001461sd0000C010* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC, Philips FI1236MK3 tuner)) pci:v00004444d00000016sv00001461sd0000C011* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC+FM, Philips FM1236MK3 tuner)) pci:v00004444d00000016sv00001461sd0000C018* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC, Philips FQ1236MK5 tuner)) pci:v00004444d00000016sv00001461sd0000C019* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (UltraTV 1500 MCE, a.k.a. M113 PCI Analog TV (NTSC+FM, Philips FQ1236MK5 tuner)) pci:v00004444d00000016sv00001461sd0000C01A* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (PAL/SECAM, Philips FQ1216MK5 tuner)) pci:v00004444d00000016sv00001461sd0000C01B* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (PAL/SECAM+FM, Philips FM1216MK5 tuner)) pci:v00004444d00000016sv00001461sd0000C030* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC-J, Partsnic tuner)) pci:v00004444d00000016sv00001461sd0000C031* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC-J+FM, Partsnic tuner)) pci:v00004444d00000016sv00001461sd0000C032* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (PAL/SECAM, Partsnic tuner)) pci:v00004444d00000016sv00001461sd0000C033* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (PAL/SECAM+FM, Partsnic tuner)) pci:v00004444d00000016sv00001461sd0000C034* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC, Partsnic tuner)) pci:v00004444d00000016sv00001461sd0000C035* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC+FM, Partsnic tuner)) pci:v00004444d00000016sv00001461sd0000C03F* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (C115 PCI video capture card (no tuner)) pci:v00004444d00000016sv00001461sd0000C136* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M104 mini-PCI Analog TV) pci:v00004444d00000016sv00001461sd0000C20A* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (PAL/SECAM, Philips FQ1216MK3 tuner)) pci:v00004444d00000016sv00001461sd0000C218* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (NTSC, Philips FQ1236MK5 tuner)) pci:v00004444d00000016sv00001461sd0000C219* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (NTSC+FM, Philips FQ1236MK5 tuner)) pci:v00004444d00000016sv00001461sd0000C21A* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (PAL/SECAM, Philips FQ1216MK5 tuner)) pci:v00004444d00000016sv00001461sd0000C21B* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (PAL/SECAM+FM, Philips FM1216MK5 tuner)) pci:v00004444d00000016sv00001461sd0000C230* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (NTSC-J, Partsnic tuner)) pci:v00004444d00000016sv00001461sd0000C231* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (NTSC-J+FM, Partsnic tuner)) pci:v00004444d00000016sv00001461sd0000C232* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (PAL/SECAM, Partsnic tuner)) pci:v00004444d00000016sv00001461sd0000C233* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (PAL/SECAM+FM, Partsnic tuner)) pci:v00004444d00000016sv00001461sd0000C234* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (NTSC, Partsnic tuner)) pci:v00004444d00000016sv00001461sd0000C235* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (NTSC+FM, Partsnic tuner)) pci:v00004444d00000016sv00001461sd0000C337* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (E106 AVerMedia AVerTV Video Capture) pci:v00004444d00000016sv00001461sd0000C439* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M116 AVerMedia AVerTV MCE 116 Plus (NTSC/PAL/SECAM+FM+REMOTE, Xceive 2028 tuner)) pci:v00004444d00000016sv00001461sd0000C5FF* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (C755 AVerTV Video Capture card (no tuner)) pci:v00004444d00000016sv00001461sd0000C6FF* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (C115 PCI video capture card (no tuner)) pci:v00004444d00000016sv00001461sd0000C739* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M785 AVerMedia PCI Analog TV (NTSC/PAL/SECAM+FM, Xceive 2028 tuner)) pci:v00004444d00000016sv00009005sd00000092* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (VideOh! AVC-2010) pci:v00004444d00000016sv00009005sd00000093* ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (VideOh! AVC-2410) pci:v00004444d00000803* ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder pci:v00004444d00000803sv00000070sd00004000* ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder (WinTV PVR-350) pci:v00004444d00000803sv00000070sd00004001* ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder (WinTV PVR-250) pci:v00004444d00000803sv00000070sd00004800* ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder (WinTV PVR-350 (V1)) pci:v00004444d00000803sv000012ABsd00000000* ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder (MPG160) pci:v00004444d00000803sv00001461sd0000A3CE* ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder (M179) pci:v00004444d00000803sv00001461sd0000A3CF* ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder (M179) pci:v00004468* ID_VENDOR_FROM_DATABASE=Bridgeport machines pci:v00004594* ID_VENDOR_FROM_DATABASE=Cogetec Informatique Inc pci:v000045FB* ID_VENDOR_FROM_DATABASE=Baldor Electric Company pci:v00004624* ID_VENDOR_FROM_DATABASE=Budker Institute of Nuclear Physics pci:v00004624d0000ADC1* ID_MODEL_FROM_DATABASE=ADC200ME High speed ADC pci:v00004624d0000DE01* ID_MODEL_FROM_DATABASE=DL200ME High resolution delay line PCI based card pci:v00004624d0000DE02* ID_MODEL_FROM_DATABASE=DL200ME Middle resolution delay line PCI based card pci:v00004680* ID_VENDOR_FROM_DATABASE=Umax Computer Corp pci:v00004843* ID_VENDOR_FROM_DATABASE=Hercules Computer Technology Inc pci:v00004916* ID_VENDOR_FROM_DATABASE=RedCreek Communications Inc pci:v00004916d00001960* ID_MODEL_FROM_DATABASE=RedCreek PCI adapter pci:v00004943* ID_VENDOR_FROM_DATABASE=Growth Networks pci:v0000494F* ID_VENDOR_FROM_DATABASE=ACCES I/O Products, Inc. pci:v0000494Fd00000520* ID_MODEL_FROM_DATABASE=PCI-IDO-48 pci:v0000494Fd00000920* ID_MODEL_FROM_DATABASE=PCI-IDI-48 pci:v0000494Fd00000C50* ID_MODEL_FROM_DATABASE=PCI-DIO-24H pci:v0000494Fd00000C51* ID_MODEL_FROM_DATABASE=PCI-DIO-24D pci:v0000494Fd00000C60* ID_MODEL_FROM_DATABASE=PCI-DIO-48(H) pci:v0000494Fd00000C68* ID_MODEL_FROM_DATABASE=PCI-DIO-72 pci:v0000494Fd00000C70* ID_MODEL_FROM_DATABASE=PCI-DIO-96 pci:v0000494Fd00000C78* ID_MODEL_FROM_DATABASE=PCI-DIO-120 pci:v0000494Fd00000DC8* ID_MODEL_FROM_DATABASE=PCI-IDIO-16 pci:v0000494Fd00000E50* ID_MODEL_FROM_DATABASE=PCI-DIO-24S pci:v0000494Fd00000E51* ID_MODEL_FROM_DATABASE=PCI-DIO-24H(C) pci:v0000494Fd00000E52* ID_MODEL_FROM_DATABASE=PCI-DIO-24D(C) pci:v0000494Fd00000E60* ID_MODEL_FROM_DATABASE=PCI-DIO-48S(H) pci:v0000494Fd00000E61* ID_MODEL_FROM_DATABASE=P104-DIO-24S pci:v0000494Fd00000F00* ID_MODEL_FROM_DATABASE=PCI-IIRO-8 pci:v0000494Fd00000F01* ID_MODEL_FROM_DATABASE=LPCI-IIRO-8 pci:v0000494Fd00000F08* ID_MODEL_FROM_DATABASE=PCI-IIRO-16 pci:v0000494Fd00001050* ID_MODEL_FROM_DATABASE=PCI-422/485-2 pci:v0000494Fd00001058* ID_MODEL_FROM_DATABASE=PCI-COM422/4 pci:v0000494Fd00001059* ID_MODEL_FROM_DATABASE=PCI-COM485/4 pci:v0000494Fd00001068* ID_MODEL_FROM_DATABASE=PCI-COM422/8 pci:v0000494Fd00001069* ID_MODEL_FROM_DATABASE=PCI-COM485/8 pci:v0000494Fd00001088* ID_MODEL_FROM_DATABASE=PCI-COM232/1 pci:v0000494Fd00001090* ID_MODEL_FROM_DATABASE=PCI-COM232/2 pci:v0000494Fd000010A8* ID_MODEL_FROM_DATABASE=P104-COM232-8 pci:v0000494Fd000010C9* ID_MODEL_FROM_DATABASE=PCI-COM-1S pci:v0000494Fd000010D0* ID_MODEL_FROM_DATABASE=PCI-COM2S pci:v0000494Fd000010E8* ID_MODEL_FROM_DATABASE=PCI-COM-8SM pci:v0000494Fd00001148* ID_MODEL_FROM_DATABASE=PCI-ICM-1S pci:v0000494Fd00001150* ID_MODEL_FROM_DATABASE=PCI-ICM-2S pci:v0000494Fd00001158* ID_MODEL_FROM_DATABASE=PCI-ICM422/4 pci:v0000494Fd00001159* ID_MODEL_FROM_DATABASE=PCI-ICM485/4 pci:v0000494Fd00001250* ID_MODEL_FROM_DATABASE=PCI-WDG-2S pci:v0000494Fd000012D0* ID_MODEL_FROM_DATABASE=PCI-WDG-IMPAC pci:v0000494Fd000022C0* ID_MODEL_FROM_DATABASE=PCI-WDG-CSM pci:v0000494Fd00002C50* ID_MODEL_FROM_DATABASE=PCI-DIO-96CT pci:v0000494Fd00002C58* ID_MODEL_FROM_DATABASE=PCI-DIO-96C3 pci:v0000494Fd00005ED0* ID_MODEL_FROM_DATABASE=PCI-DAC pci:v0000494Fd00006C90* ID_MODEL_FROM_DATABASE=PCI-DA12-2 pci:v0000494Fd00006C98* ID_MODEL_FROM_DATABASE=PCI-DA12-4 pci:v0000494Fd00006CA0* ID_MODEL_FROM_DATABASE=PCI-DA12-6 pci:v0000494Fd00006CA8* ID_MODEL_FROM_DATABASE=PCI-DA12-8 pci:v0000494Fd00006CA9* ID_MODEL_FROM_DATABASE=PCI-DA12-8V pci:v0000494Fd00006CB0* ID_MODEL_FROM_DATABASE=PCI-DA12-16 pci:v0000494Fd00006CB1* ID_MODEL_FROM_DATABASE=PCI-DA12-16V pci:v0000494Fd00008EF0* ID_MODEL_FROM_DATABASE=P104-FAS16-16 pci:v0000494Fd0000ACA8* ID_MODEL_FROM_DATABASE=PCI-AI12-16 pci:v0000494Fd0000ACA9* ID_MODEL_FROM_DATABASE=PCI-AI12-16A pci:v0000494Fd0000ECA8* ID_MODEL_FROM_DATABASE=PCI-AIO12-16 pci:v0000494Fd0000ECA9* ID_MODEL_FROM_DATABASE=PCI-A12-16 pci:v0000494Fd0000ECAA* ID_MODEL_FROM_DATABASE=PCI-A12-16A pci:v0000494Fd0000ECE8* ID_MODEL_FROM_DATABASE=PCI-A16-16 pci:v00004978* ID_VENDOR_FROM_DATABASE=Axil Computer Inc pci:v00004A14* ID_VENDOR_FROM_DATABASE=NetVin pci:v00004A14d00005000* ID_MODEL_FROM_DATABASE=NV5000SC pci:v00004A14d00005000sv00004A14sd00005000* ID_MODEL_FROM_DATABASE=NV5000SC (RT8029-Based Ethernet Adapter) pci:v00004B10* ID_VENDOR_FROM_DATABASE=Buslogic Inc. pci:v00004C48* ID_VENDOR_FROM_DATABASE=LUNG HWA Electronics pci:v00004C53* ID_VENDOR_FROM_DATABASE=SBS Technologies pci:v00004C53d00000000* ID_MODEL_FROM_DATABASE=PLUSTEST device pci:v00004C53d00000000sv00004C53sd00003000* ID_MODEL_FROM_DATABASE=PLUSTEST device (PLUSTEST card (PC104+)) pci:v00004C53d00000000sv00004C53sd00003001* ID_MODEL_FROM_DATABASE=PLUSTEST device (PLUSTEST card (PMC)) pci:v00004C53d00000001* ID_MODEL_FROM_DATABASE=PLUSTEST-MM device pci:v00004C53d00000001sv00004C53sd00003002* ID_MODEL_FROM_DATABASE=PLUSTEST-MM device (PLUSTEST-MM card (PMC)) pci:v00004CA1* ID_VENDOR_FROM_DATABASE=Seanix Technology Inc pci:v00004D51* ID_VENDOR_FROM_DATABASE=MediaQ Inc. pci:v00004D51d00000200* ID_MODEL_FROM_DATABASE=MQ-200 pci:v00004D54* ID_VENDOR_FROM_DATABASE=Microtechnica Co Ltd pci:v00004D56* ID_VENDOR_FROM_DATABASE=MATRIX VISION GmbH pci:v00004D56d00000000* ID_MODEL_FROM_DATABASE=[mvHYPERION-CLe/CLb] CameraLink PCI Express x1 Frame Grabber pci:v00004D56d00000001* ID_MODEL_FROM_DATABASE=[mvHYPERION-CLf/CLm] CameraLink PCI Express x4 Frame Grabber pci:v00004D56d00000010* ID_MODEL_FROM_DATABASE=[mvHYPERION-16R16/-32R16] 16 Video Channel PCI Express x4 Frame Grabber pci:v00004D56d00000020* ID_MODEL_FROM_DATABASE=[mvHYPERION-HD-SDI] HD-SDI PCI Express x4 Frame Grabber pci:v00004D56d00000030* ID_MODEL_FROM_DATABASE=[mvHYPERION-HD-SDI-Merger] HD-SDI PCI Express x4 Frame Grabber pci:v00004DDC* ID_VENDOR_FROM_DATABASE=ILC Data Device Corp pci:v00004DDCd00000100* ID_MODEL_FROM_DATABASE=DD-42924I5-300 (ARINC 429 Data Bus) pci:v00004DDCd00000801* ID_MODEL_FROM_DATABASE=BU-65570I1 MIL-STD-1553 Test and Simulation pci:v00004DDCd00000802* ID_MODEL_FROM_DATABASE=BU-65570I2 MIL-STD-1553 Test and Simulation pci:v00004DDCd00000811* ID_MODEL_FROM_DATABASE=BU-65572I1 MIL-STD-1553 Test and Simulation pci:v00004DDCd00000812* ID_MODEL_FROM_DATABASE=BU-65572I2 MIL-STD-1553 Test and Simulation pci:v00004DDCd00000881* ID_MODEL_FROM_DATABASE=BU-65570T1 MIL-STD-1553 Test and Simulation pci:v00004DDCd00000882* ID_MODEL_FROM_DATABASE=BU-65570T2 MIL-STD-1553 Test and Simulation pci:v00004DDCd00000891* ID_MODEL_FROM_DATABASE=BU-65572T1 MIL-STD-1553 Test and Simulation pci:v00004DDCd00000892* ID_MODEL_FROM_DATABASE=BU-65572T2 MIL-STD-1553 Test and Simulation pci:v00004DDCd00000901* ID_MODEL_FROM_DATABASE=BU-65565C1 MIL-STD-1553 Data Bus pci:v00004DDCd00000902* ID_MODEL_FROM_DATABASE=BU-65565C2 MIL-STD-1553 Data Bus pci:v00004DDCd00000903* ID_MODEL_FROM_DATABASE=BU-65565C3 MIL-STD-1553 Data Bus pci:v00004DDCd00000904* ID_MODEL_FROM_DATABASE=BU-65565C4 MIL-STD-1553 Data Bus pci:v00004DDCd00000B01* ID_MODEL_FROM_DATABASE=BU-65569I1 MIL-STD-1553 Data Bus pci:v00004DDCd00000B02* ID_MODEL_FROM_DATABASE=BU-65569I2 MIL-STD-1553 Data Bus pci:v00004DDCd00000B03* ID_MODEL_FROM_DATABASE=BU-65569I3 MIL-STD-1553 Data Bus pci:v00004DDCd00000B04* ID_MODEL_FROM_DATABASE=BU-65569I4 MIL-STD-1553 Data Bus pci:v00005045* ID_VENDOR_FROM_DATABASE=University of Toronto pci:v00005045d00004243* ID_MODEL_FROM_DATABASE=BLASTbus PCI Interface Card v1 pci:v00005046* ID_VENDOR_FROM_DATABASE=GemTek Technology Corporation pci:v00005046d00001001* ID_MODEL_FROM_DATABASE=PCI Radio pci:v00005053* ID_VENDOR_FROM_DATABASE=Voyetra Technologies pci:v00005053d00002010* ID_MODEL_FROM_DATABASE=Daytona Audio Adapter pci:v000050B2* ID_VENDOR_FROM_DATABASE=TerraTec Electronic GmbH pci:v00005136* ID_VENDOR_FROM_DATABASE=S S Technologies pci:v00005143* ID_VENDOR_FROM_DATABASE=Qualcomm Inc pci:v00005145* ID_VENDOR_FROM_DATABASE=Ensoniq (Old) pci:v00005145d00003031* ID_MODEL_FROM_DATABASE=Concert AudioPCI pci:v00005168* ID_VENDOR_FROM_DATABASE=Animation Technologies Inc. pci:v00005168d00000300* ID_MODEL_FROM_DATABASE=FlyDVB-S pci:v00005168d00000301* ID_MODEL_FROM_DATABASE=FlyDVB-T pci:v00005301* ID_VENDOR_FROM_DATABASE=Alliance Semiconductor Corp. pci:v00005301d00000001* ID_MODEL_FROM_DATABASE=ProMotion aT3D pci:v00005333* ID_VENDOR_FROM_DATABASE=S3 Graphics Ltd. pci:v00005333d00000551* ID_MODEL_FROM_DATABASE=Plato/PX (system) pci:v00005333d00005631* ID_MODEL_FROM_DATABASE=86c325 [ViRGE] pci:v00005333d00008800* ID_MODEL_FROM_DATABASE=86c866 [Vision 866] pci:v00005333d00008801* ID_MODEL_FROM_DATABASE=86c964 [Vision 964] pci:v00005333d00008810* ID_MODEL_FROM_DATABASE=86c764_0 [Trio 32 vers 0] pci:v00005333d00008811* ID_MODEL_FROM_DATABASE=86c764/765 [Trio32/64/64V+] pci:v00005333d00008812* ID_MODEL_FROM_DATABASE=86cM65 [Aurora64V+] pci:v00005333d00008813* ID_MODEL_FROM_DATABASE=86c764_3 [Trio 32/64 vers 3] pci:v00005333d00008814* ID_MODEL_FROM_DATABASE=86c767 [Trio 64UV+] pci:v00005333d00008815* ID_MODEL_FROM_DATABASE=86cM65 [Aurora 128] pci:v00005333d0000883D* ID_MODEL_FROM_DATABASE=86c988 [ViRGE/VX] pci:v00005333d00008870* ID_MODEL_FROM_DATABASE=FireGL pci:v00005333d00008880* ID_MODEL_FROM_DATABASE=86c868 [Vision 868 VRAM] vers 0 pci:v00005333d00008881* ID_MODEL_FROM_DATABASE=86c868 [Vision 868 VRAM] vers 1 pci:v00005333d00008882* ID_MODEL_FROM_DATABASE=86c868 [Vision 868 VRAM] vers 2 pci:v00005333d00008883* ID_MODEL_FROM_DATABASE=86c868 [Vision 868 VRAM] vers 3 pci:v00005333d000088B0* ID_MODEL_FROM_DATABASE=86c928 [Vision 928 VRAM] vers 0 pci:v00005333d000088B1* ID_MODEL_FROM_DATABASE=86c928 [Vision 928 VRAM] vers 1 pci:v00005333d000088B2* ID_MODEL_FROM_DATABASE=86c928 [Vision 928 VRAM] vers 2 pci:v00005333d000088B3* ID_MODEL_FROM_DATABASE=86c928 [Vision 928 VRAM] vers 3 pci:v00005333d000088C0* ID_MODEL_FROM_DATABASE=86c864 [Vision 864 DRAM] vers 0 pci:v00005333d000088C1* ID_MODEL_FROM_DATABASE=86c864 [Vision 864 DRAM] vers 1 pci:v00005333d000088C2* ID_MODEL_FROM_DATABASE=86c864 [Vision 864-P DRAM] vers 2 pci:v00005333d000088C3* ID_MODEL_FROM_DATABASE=86c864 [Vision 864-P DRAM] vers 3 pci:v00005333d000088D0* ID_MODEL_FROM_DATABASE=86c964 [Vision 964 VRAM] vers 0 pci:v00005333d000088D1* ID_MODEL_FROM_DATABASE=86c964 [Vision 964 VRAM] vers 1 pci:v00005333d000088D2* ID_MODEL_FROM_DATABASE=86c964 [Vision 964-P VRAM] vers 2 pci:v00005333d000088D3* ID_MODEL_FROM_DATABASE=86c964 [Vision 964-P VRAM] vers 3 pci:v00005333d000088F0* ID_MODEL_FROM_DATABASE=86c968 [Vision 968 VRAM] rev 0 pci:v00005333d000088F1* ID_MODEL_FROM_DATABASE=86c968 [Vision 968 VRAM] rev 1 pci:v00005333d000088F2* ID_MODEL_FROM_DATABASE=86c968 [Vision 968 VRAM] rev 2 pci:v00005333d000088F3* ID_MODEL_FROM_DATABASE=86c968 [Vision 968 VRAM] rev 3 pci:v00005333d00008900* ID_MODEL_FROM_DATABASE=86c755 [Trio 64V2/DX] pci:v00005333d00008900sv00005333sd00008900* ID_MODEL_FROM_DATABASE=86c755 [Trio 64V2/DX] (86C775 Trio64V2/DX) pci:v00005333d00008901* ID_MODEL_FROM_DATABASE=86c775/86c785 [Trio 64V2/DX or /GX] pci:v00005333d00008901sv00005333sd00008901* ID_MODEL_FROM_DATABASE=86c775/86c785 [Trio 64V2/DX or /GX] (86C775 Trio64V2/DX, 86C785 Trio64V2/GX) pci:v00005333d00008902* ID_MODEL_FROM_DATABASE=Plato/PX pci:v00005333d00008903* ID_MODEL_FROM_DATABASE=Trio 3D business multimedia pci:v00005333d00008904* ID_MODEL_FROM_DATABASE=86c365, 86c366 [Trio 3D] pci:v00005333d00008904sv00001014sd000000DB* ID_MODEL_FROM_DATABASE=86c365, 86c366 [Trio 3D] (Integrated Trio3D) pci:v00005333d00008904sv00004843sd0000314A* ID_MODEL_FROM_DATABASE=86c365, 86c366 [Trio 3D] (Terminator 128/3D GLH) pci:v00005333d00008904sv00005333sd00008904* ID_MODEL_FROM_DATABASE=86c365, 86c366 [Trio 3D] (86C365 Trio3D AGP) pci:v00005333d00008905* ID_MODEL_FROM_DATABASE=Trio 64V+ family pci:v00005333d00008906* ID_MODEL_FROM_DATABASE=Trio 64V+ family pci:v00005333d00008907* ID_MODEL_FROM_DATABASE=Trio 64V+ family pci:v00005333d00008908* ID_MODEL_FROM_DATABASE=Trio 64V+ family pci:v00005333d00008909* ID_MODEL_FROM_DATABASE=Trio 64V+ family pci:v00005333d0000890A* ID_MODEL_FROM_DATABASE=Trio 64V+ family pci:v00005333d0000890B* ID_MODEL_FROM_DATABASE=Trio 64V+ family pci:v00005333d0000890C* ID_MODEL_FROM_DATABASE=Trio 64V+ family pci:v00005333d0000890D* ID_MODEL_FROM_DATABASE=Trio 64V+ family pci:v00005333d0000890E* ID_MODEL_FROM_DATABASE=Trio 64V+ family pci:v00005333d0000890F* ID_MODEL_FROM_DATABASE=Trio 64V+ family pci:v00005333d00008A01* ID_MODEL_FROM_DATABASE=86c375 [ViRGE/DX] or 86c385 [ViRGE/GX] pci:v00005333d00008A01sv00000E11sd0000B032* ID_MODEL_FROM_DATABASE=86c375 [ViRGE/DX] or 86c385 [ViRGE/GX] (ViRGE/GX) pci:v00005333d00008A01sv000010B4sd00001617* ID_MODEL_FROM_DATABASE=86c375 [ViRGE/DX] or 86c385 [ViRGE/GX] (Nitro 3D) pci:v00005333d00008A01sv000010B4sd00001717* ID_MODEL_FROM_DATABASE=86c375 [ViRGE/DX] or 86c385 [ViRGE/GX] (Nitro 3D) pci:v00005333d00008A01sv00005333sd00008A01* ID_MODEL_FROM_DATABASE=86c375 [ViRGE/DX] or 86c385 [ViRGE/GX] (ViRGE/DX) pci:v00005333d00008A10* ID_MODEL_FROM_DATABASE=ViRGE/GX2 pci:v00005333d00008A10sv00001092sd00008A10* ID_MODEL_FROM_DATABASE=ViRGE/GX2 (Stealth 3D 4000) pci:v00005333d00008A13* ID_MODEL_FROM_DATABASE=86c360 [Trio 3D/1X], 86c362, 86c368 [Trio 3D/2X] pci:v00005333d00008A13sv00005333sd00008A13* ID_MODEL_FROM_DATABASE=86c360 [Trio 3D/1X], 86c362, 86c368 [Trio 3D/2X] (Trio3D/2X) pci:v00005333d00008A20* ID_MODEL_FROM_DATABASE=86c794 [Savage 3D] pci:v00005333d00008A20sv00005333sd00008A20* ID_MODEL_FROM_DATABASE=86c794 [Savage 3D] (86C391 Savage3D) pci:v00005333d00008A21* ID_MODEL_FROM_DATABASE=86c390 [Savage 3D/MV] pci:v00005333d00008A21sv00005333sd00008A21* ID_MODEL_FROM_DATABASE=86c390 [Savage 3D/MV] (86C390 Savage3D/MV) pci:v00005333d00008A22* ID_MODEL_FROM_DATABASE=Savage 4 pci:v00005333d00008A22sv00001033sd00008068* ID_MODEL_FROM_DATABASE=Savage 4 pci:v00005333d00008A22sv00001033sd00008069* ID_MODEL_FROM_DATABASE=Savage 4 pci:v00005333d00008A22sv00001033sd00008110* ID_MODEL_FROM_DATABASE=Savage 4 (LT) pci:v00005333d00008A22sv0000105Dsd00000018* ID_MODEL_FROM_DATABASE=Savage 4 (SR9 8Mb SDRAM) pci:v00005333d00008A22sv0000105Dsd0000002A* ID_MODEL_FROM_DATABASE=Savage 4 (SR9 Pro 16Mb SDRAM) pci:v00005333d00008A22sv0000105Dsd0000003A* ID_MODEL_FROM_DATABASE=Savage 4 (SR9 Pro 32Mb SDRAM) pci:v00005333d00008A22sv0000105Dsd0000092F* ID_MODEL_FROM_DATABASE=Savage 4 (SR9 Pro+ 16Mb SGRAM) pci:v00005333d00008A22sv00001092sd00004207* ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) pci:v00005333d00008A22sv00001092sd00004800* ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) pci:v00005333d00008A22sv00001092sd00004807* ID_MODEL_FROM_DATABASE=Savage 4 (SpeedStar A90) pci:v00005333d00008A22sv00001092sd00004808* ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) pci:v00005333d00008A22sv00001092sd00004809* ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) pci:v00005333d00008A22sv00001092sd0000480E* ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) pci:v00005333d00008A22sv00001092sd00004904* ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S520) pci:v00005333d00008A22sv00001092sd00004905* ID_MODEL_FROM_DATABASE=Savage 4 (SpeedStar A200) pci:v00005333d00008A22sv00001092sd00004A09* ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) pci:v00005333d00008A22sv00001092sd00004A0B* ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540 Xtreme) pci:v00005333d00008A22sv00001092sd00004A0F* ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) pci:v00005333d00008A22sv00001092sd00004E01* ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) pci:v00005333d00008A22sv00001102sd0000101D* ID_MODEL_FROM_DATABASE=Savage 4 (3d Blaster Savage 4) pci:v00005333d00008A22sv00001102sd0000101E* ID_MODEL_FROM_DATABASE=Savage 4 (3d Blaster Savage 4) pci:v00005333d00008A22sv00005333sd00008100* ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 SDRAM 100) pci:v00005333d00008A22sv00005333sd00008110* ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 SDRAM 110) pci:v00005333d00008A22sv00005333sd00008125* ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 SDRAM 125) pci:v00005333d00008A22sv00005333sd00008143* ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 SDRAM 143) pci:v00005333d00008A22sv00005333sd00008A22* ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4) pci:v00005333d00008A22sv00005333sd00008A2E* ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 32bit) pci:v00005333d00008A22sv00005333sd00009125* ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 SGRAM 125) pci:v00005333d00008A22sv00005333sd00009143* ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 SGRAM 143) pci:v00005333d00008A23* ID_MODEL_FROM_DATABASE=Savage 4 pci:v00005333d00008A25* ID_MODEL_FROM_DATABASE=ProSavage PM133 pci:v00005333d00008A25sv00000303sd00000303* ID_MODEL_FROM_DATABASE=ProSavage PM133 (D9840-60001 [Brio BA410 Motherboard]) pci:v00005333d00008A26* ID_MODEL_FROM_DATABASE=ProSavage KM133 pci:v00005333d00008C00* ID_MODEL_FROM_DATABASE=ViRGE/M3 pci:v00005333d00008C01* ID_MODEL_FROM_DATABASE=ViRGE/MX pci:v00005333d00008C01sv00001179sd00000001* ID_MODEL_FROM_DATABASE=ViRGE/MX pci:v00005333d00008C02* ID_MODEL_FROM_DATABASE=ViRGE/MX+ pci:v00005333d00008C03* ID_MODEL_FROM_DATABASE=ViRGE/MX+MV pci:v00005333d00008C10* ID_MODEL_FROM_DATABASE=86C270-294 [SavageMX-MV] pci:v00005333d00008C11* ID_MODEL_FROM_DATABASE=82C270-294 [SavageMX] pci:v00005333d00008C12* ID_MODEL_FROM_DATABASE=86C270-294 [SavageIX-MV] pci:v00005333d00008C12sv00001014sd0000017F* ID_MODEL_FROM_DATABASE=86C270-294 [SavageIX-MV] (ThinkPad T20/T22) pci:v00005333d00008C12sv00001179sd00000001* ID_MODEL_FROM_DATABASE=86C270-294 [SavageIX-MV] (86C584 SuperSavage/IXC Toshiba) pci:v00005333d00008C13* ID_MODEL_FROM_DATABASE=86C270-294 [SavageIX] pci:v00005333d00008C13sv00001179sd00000001* ID_MODEL_FROM_DATABASE=86C270-294 [SavageIX] (Magnia Z310) pci:v00005333d00008C22* ID_MODEL_FROM_DATABASE=SuperSavage MX/128 pci:v00005333d00008C24* ID_MODEL_FROM_DATABASE=SuperSavage MX/64 pci:v00005333d00008C26* ID_MODEL_FROM_DATABASE=SuperSavage MX/64C pci:v00005333d00008C2A* ID_MODEL_FROM_DATABASE=SuperSavage IX/128 SDR pci:v00005333d00008C2B* ID_MODEL_FROM_DATABASE=SuperSavage IX/128 DDR pci:v00005333d00008C2C* ID_MODEL_FROM_DATABASE=SuperSavage IX/64 SDR pci:v00005333d00008C2D* ID_MODEL_FROM_DATABASE=SuperSavage IX/64 DDR pci:v00005333d00008C2E* ID_MODEL_FROM_DATABASE=SuperSavage IX/C SDR pci:v00005333d00008C2Esv00001014sd000001FC* ID_MODEL_FROM_DATABASE=SuperSavage IX/C SDR (ThinkPad T23) pci:v00005333d00008C2F* ID_MODEL_FROM_DATABASE=SuperSavage IX/C DDR pci:v00005333d00008D01* ID_MODEL_FROM_DATABASE=86C380 [ProSavageDDR K4M266] pci:v00005333d00008D02* ID_MODEL_FROM_DATABASE=VT8636A [ProSavage KN133] AGP4X VGA Controller (TwisterK) pci:v00005333d00008D03* ID_MODEL_FROM_DATABASE=VT8751 [ProSavageDDR P4M266] pci:v00005333d00008D04* ID_MODEL_FROM_DATABASE=VT8375 [ProSavage8 KM266/KL266] pci:v00005333d00008E00* ID_MODEL_FROM_DATABASE=DeltaChrome pci:v00005333d00008E26* ID_MODEL_FROM_DATABASE=ProSavage pci:v00005333d00008E40* ID_MODEL_FROM_DATABASE=2300E Graphics Processor pci:v00005333d00008E48* ID_MODEL_FROM_DATABASE=Matrix [Chrome S25 / S27] pci:v00005333d00008E48sv00005333sd00000130* ID_MODEL_FROM_DATABASE=Matrix [Chrome S25 / S27] (Chrome S27 256M DDR2) pci:v00005333d00009043* ID_MODEL_FROM_DATABASE=Chrome 430 GT pci:v00005333d00009045* ID_MODEL_FROM_DATABASE=Chrome 430 ULP / 435 ULP / 440 GTX pci:v00005333d00009060* ID_MODEL_FROM_DATABASE=Chrome 530 GT pci:v00005333d00009102* ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] pci:v00005333d00009102sv00001092sd00005932* ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) pci:v00005333d00009102sv00001092sd00005934* ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) pci:v00005333d00009102sv00001092sd00005952* ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) pci:v00005333d00009102sv00001092sd00005954* ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) pci:v00005333d00009102sv00001092sd00005A35* ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) pci:v00005333d00009102sv00001092sd00005A37* ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) pci:v00005333d00009102sv00001092sd00005A55* ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) pci:v00005333d00009102sv00001092sd00005A57* ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) pci:v00005333d0000CA00* ID_MODEL_FROM_DATABASE=SonicVibes pci:v00005431* ID_VENDOR_FROM_DATABASE=AuzenTech, Inc. pci:v0000544C* ID_VENDOR_FROM_DATABASE=Teralogic Inc pci:v0000544Cd00000350* ID_MODEL_FROM_DATABASE=TL880-based HDTV/ATSC tuner pci:v0000544D* ID_VENDOR_FROM_DATABASE=TBS Technologies pci:v0000544Dd00006178* ID_MODEL_FROM_DATABASE=DVB-S2 4 Tuner PCIe Card pci:v0000544Dd00006178sv0000544Dsd00006904* ID_MODEL_FROM_DATABASE=DVB-S2 4 Tuner PCIe Card (TBS6904 DVB-S2 Quad Tuner PCIe Card) pci:v0000544Dd00006178sv0000544Dsd00006905* ID_MODEL_FROM_DATABASE=DVB-S2 4 Tuner PCIe Card (TBS6905 DVB-S2 Quad Tuner PCIe Card) pci:v00005452* ID_VENDOR_FROM_DATABASE=SCANLAB AG pci:v00005452d00003443* ID_MODEL_FROM_DATABASE=RTC4 pci:v00005455* ID_VENDOR_FROM_DATABASE=Technische University Berlin pci:v00005455d00004458* ID_MODEL_FROM_DATABASE=S5933 pci:v00005456* ID_VENDOR_FROM_DATABASE=GoTView pci:v00005519* ID_VENDOR_FROM_DATABASE=Cnet Technologies, Inc. pci:v00005544* ID_VENDOR_FROM_DATABASE=Dunord Technologies pci:v00005544d00000001* ID_MODEL_FROM_DATABASE=I-30xx Scanner Interface pci:v00005555* ID_VENDOR_FROM_DATABASE=Genroco, Inc pci:v00005555d00000003* ID_MODEL_FROM_DATABASE=TURBOstor HFP-832 [HiPPI NIC] pci:v00005646* ID_VENDOR_FROM_DATABASE=Vector Fabrics BV pci:v00005654* ID_VENDOR_FROM_DATABASE=VoiceTronix Pty Ltd pci:v00005700* ID_VENDOR_FROM_DATABASE=Netpower pci:v0000584D* ID_VENDOR_FROM_DATABASE=AuzenTech Co., Ltd. pci:v00005851* ID_VENDOR_FROM_DATABASE=Exacq Technologies pci:v00005851d00008008* ID_MODEL_FROM_DATABASE=tDVR8008 8-port video capture card pci:v00005851d00008016* ID_MODEL_FROM_DATABASE=tDVR8016 16-chan video capture card pci:v00005851d00008032* ID_MODEL_FROM_DATABASE=tDVR8032 32-chan video capture card pci:v00005853* ID_VENDOR_FROM_DATABASE=XenSource, Inc. pci:v00005853d00000001* ID_MODEL_FROM_DATABASE=Xen Platform Device pci:v00005853d0000C000* ID_MODEL_FROM_DATABASE=Citrix XenServer PCI Device for Windows Update pci:v00005853d0000C110* ID_MODEL_FROM_DATABASE=Virtualized HID pci:v00005853d0000C147* ID_MODEL_FROM_DATABASE=Virtualized Graphics Device pci:v00005854* ID_VENDOR_FROM_DATABASE=GoTView pci:v00005ACE* ID_VENDOR_FROM_DATABASE=Beholder International Ltd. pci:v0000631C* ID_VENDOR_FROM_DATABASE=SmartInfra Ltd pci:v0000631Cd00001652* ID_MODEL_FROM_DATABASE=PXI-1652 Signal Generator pci:v0000631Cd00002504* ID_MODEL_FROM_DATABASE=PXI-2504 Signal Interrogator pci:v00006356* ID_VENDOR_FROM_DATABASE=UltraStor pci:v00006374* ID_VENDOR_FROM_DATABASE=c't Magazin fuer Computertechnik pci:v00006374d00006773* ID_MODEL_FROM_DATABASE=GPPCI pci:v00006409* ID_VENDOR_FROM_DATABASE=Logitec Corp. pci:v00006549* ID_VENDOR_FROM_DATABASE=Teradici Corp. pci:v00006549d00001200* ID_MODEL_FROM_DATABASE=TERA1200 PC-over-IP Host pci:v00006666* ID_VENDOR_FROM_DATABASE=Decision Computer International Co. pci:v00006666d00000001* ID_MODEL_FROM_DATABASE=PCCOM4 pci:v00006666d00000002* ID_MODEL_FROM_DATABASE=PCCOM8 pci:v00006666d00000004* ID_MODEL_FROM_DATABASE=PCCOM2 pci:v00006666d00000101* ID_MODEL_FROM_DATABASE=PCI 8255/8254 I/O Card pci:v00006666d00000200* ID_MODEL_FROM_DATABASE=12-bit AD/DA Card pci:v00006666d00000201* ID_MODEL_FROM_DATABASE=14-bit AD/DA Card pci:v00006666d00001011* ID_MODEL_FROM_DATABASE=Industrial Card pci:v00006666d00001021* ID_MODEL_FROM_DATABASE=8 photo couple 8 relay Card pci:v00006666d00001022* ID_MODEL_FROM_DATABASE=4 photo couple 4 relay Card pci:v00006666d00001025* ID_MODEL_FROM_DATABASE=16 photo couple 16 relay Card pci:v00006666d00004000* ID_MODEL_FROM_DATABASE=WatchDog Card pci:v00006688* ID_VENDOR_FROM_DATABASE=Zycoo Co., Ltd pci:v00006688d00001200* ID_MODEL_FROM_DATABASE=CooVox TDM Analog Module pci:v00006688d00001400* ID_MODEL_FROM_DATABASE=CooVOX TDM GSM Module pci:v00006688d00001600* ID_MODEL_FROM_DATABASE=CooVOX TDM E1/T1 Module pci:v00006688d00001800* ID_MODEL_FROM_DATABASE=CooVOX TDM BRI Module pci:v00006900* ID_VENDOR_FROM_DATABASE=Red Hat, Inc. pci:v00007063* ID_VENDOR_FROM_DATABASE=pcHDTV pci:v00007063d00002000* ID_MODEL_FROM_DATABASE=HD-2000 pci:v00007063d00003000* ID_MODEL_FROM_DATABASE=HD-3000 pci:v00007063d00005500* ID_MODEL_FROM_DATABASE=HD5500 HDTV pci:v00007284* ID_VENDOR_FROM_DATABASE=HT OMEGA Inc. pci:v00007401* ID_VENDOR_FROM_DATABASE=EndRun Technologies pci:v00007401d0000E100* ID_MODEL_FROM_DATABASE=PTP3100 PCIe PTP Slave Clock pci:v00007470* ID_VENDOR_FROM_DATABASE=TP-LINK Technologies Co., Ltd. pci:v00007604* ID_VENDOR_FROM_DATABASE=O.N. Electronic Co Ltd. pci:v00007BDE* ID_VENDOR_FROM_DATABASE=MIDAC Corporation pci:v00007FED* ID_VENDOR_FROM_DATABASE=PowerTV pci:v00008008* ID_VENDOR_FROM_DATABASE=Quancom Electronic GmbH pci:v00008008d00000010* ID_MODEL_FROM_DATABASE=WDOG1 [PCI-Watchdog 1] pci:v00008008d00000011* ID_MODEL_FROM_DATABASE=PWDOG2 [PCI-Watchdog 2] pci:v00008008d00000015* ID_MODEL_FROM_DATABASE=Clock77/PCI & Clock77/PCIe (DCF-77 receiver) pci:v0000807D* ID_VENDOR_FROM_DATABASE=Asustek Computer, Inc. pci:v00008086* ID_VENDOR_FROM_DATABASE=Intel Corporation pci:v00008086d00000007* ID_MODEL_FROM_DATABASE=82379AB pci:v00008086d00000008* ID_MODEL_FROM_DATABASE=Extended Express System Support Controller pci:v00008086d00000039* ID_MODEL_FROM_DATABASE=21145 Fast Ethernet pci:v00008086d00000040* ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller pci:v00008086d00000041* ID_MODEL_FROM_DATABASE=Core Processor PCI Express x16 Root Port pci:v00008086d00000042* ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller pci:v00008086d00000043* ID_MODEL_FROM_DATABASE=Core Processor Secondary PCI Express Root Port pci:v00008086d00000044* ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller pci:v00008086d00000044sv00001025sd00000347* ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller (Aspire 7740G) pci:v00008086d00000044sv00001025sd00000487* ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller (TravelMate 5742) pci:v00008086d00000044sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller (Latitude E6410) pci:v00008086d00000044sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller (R730 Laptop) pci:v00008086d00000044sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00000044sv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller (PC1-GROOVE) pci:v00008086d00000045* ID_MODEL_FROM_DATABASE=Core Processor PCI Express x16 Root Port pci:v00008086d00000045sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=Core Processor PCI Express x16 Root Port (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00000046* ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller pci:v00008086d00000046sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller (Latitude E6410) pci:v00008086d00000046sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller (R730 Laptop) pci:v00008086d00000046sv000017C0sd000010D9* ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00000046sv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller (PC1-GROOVE) pci:v00008086d00000047* ID_MODEL_FROM_DATABASE=Core Processor Secondary PCI Express Root Port pci:v00008086d00000048* ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller pci:v00008086d00000049* ID_MODEL_FROM_DATABASE=Core Processor PCI Express x16 Root Port pci:v00008086d0000004A* ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller pci:v00008086d0000004B* ID_MODEL_FROM_DATABASE=Core Processor Secondary PCI Express Root Port pci:v00008086d00000050* ID_MODEL_FROM_DATABASE=Core Processor Thermal Management Controller pci:v00008086d00000069* ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller pci:v00008086d00000082* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] pci:v00008086d00000082sv00008086sd00001301* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 AGN) pci:v00008086d00000082sv00008086sd00001306* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 ABG) pci:v00008086d00000082sv00008086sd00001307* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 BG) pci:v00008086d00000082sv00008086sd00001321* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 AGN) pci:v00008086d00000082sv00008086sd00001326* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 ABG) pci:v00008086d00000083* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] pci:v00008086d00000083sv00008086sd00001205* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BGN) pci:v00008086d00000083sv00008086sd00001206* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BG) pci:v00008086d00000083sv00008086sd00001225* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BGN) pci:v00008086d00000083sv00008086sd00001226* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BG) pci:v00008086d00000083sv00008086sd00001305* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BGN) pci:v00008086d00000083sv00008086sd00001306* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BG) pci:v00008086d00000083sv00008086sd00001325* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BGN) pci:v00008086d00000083sv00008086sd00001326* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BG) pci:v00008086d00000084* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] pci:v00008086d00000084sv00008086sd00001215* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BGN) pci:v00008086d00000084sv00008086sd00001216* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BG) pci:v00008086d00000084sv00008086sd00001315* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BGN) pci:v00008086d00000084sv00008086sd00001316* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BG) pci:v00008086d00000085* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] pci:v00008086d00000085sv00008086sd00001311* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 AGN) pci:v00008086d00000085sv00008086sd00001316* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 ABG) pci:v00008086d00000087* ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] pci:v00008086d00000087sv00008086sd00001301* ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] (Centrino Advanced-N + WiMAX 6250 2x2 AGN) pci:v00008086d00000087sv00008086sd00001306* ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] (Centrino Advanced-N + WiMAX 6250 2x2 ABG) pci:v00008086d00000087sv00008086sd00001321* ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] (Centrino Advanced-N + WiMAX 6250 2x2 AGN) pci:v00008086d00000087sv00008086sd00001326* ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] (Centrino Advanced-N + WiMAX 6250 2x2 ABG) pci:v00008086d00000089* ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] pci:v00008086d00000089sv00008086sd00001311* ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] (Centrino Advanced-N + WiMAX 6250 2x2 AGN) pci:v00008086d00000089sv00008086sd00001316* ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] (Centrino Advanced-N + WiMAX 6250 2x2 ABG) pci:v00008086d0000008A* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] pci:v00008086d0000008Asv00008086sd00005305* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] (Centrino Wireless-N 1030 BGN) pci:v00008086d0000008Asv00008086sd00005307* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] (Centrino Wireless-N 1030 BG) pci:v00008086d0000008Asv00008086sd00005325* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] (Centrino Wireless-N 1030 BGN) pci:v00008086d0000008Asv00008086sd00005327* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] (Centrino Wireless-N 1030 BG) pci:v00008086d0000008B* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] pci:v00008086d0000008Bsv00008086sd00005315* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] (Centrino Wireless-N 1030 BGN) pci:v00008086d0000008Bsv00008086sd00005317* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] (Centrino Wireless-N 1030 BG) pci:v00008086d00000090* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] pci:v00008086d00000090sv00008086sd00005211* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 AGN) pci:v00008086d00000090sv00008086sd00005215* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 BGN) pci:v00008086d00000090sv00008086sd00005216* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 ABG) pci:v00008086d00000091* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] pci:v00008086d00000091sv00008086sd00005201* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 AGN) pci:v00008086d00000091sv00008086sd00005205* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 BGN) pci:v00008086d00000091sv00008086sd00005206* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 ABG) pci:v00008086d00000091sv00008086sd00005207* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 BG) pci:v00008086d00000091sv00008086sd00005221* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 AGN) pci:v00008086d00000091sv00008086sd00005225* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 BGN) pci:v00008086d00000091sv00008086sd00005226* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 ABG) pci:v00008086d00000100* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller pci:v00008086d00000100sv00001028sd000004AA* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (XPS 8300) pci:v00008086d00000100sv00001043sd0000844D* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (P8P67/P8H67 Series Motherboard) pci:v00008086d00000101* ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port pci:v00008086d00000101sv00001028sd000004B2* ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port (Vostro 3350) pci:v00008086d00000101sv0000106Bsd000000DC* ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port (MacBookPro8,2 [Core i7, 15", 2011]) pci:v00008086d00000102* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller pci:v00008086d00000102sv00001028sd000004AA* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (XPS 8300) pci:v00008086d00000102sv00001043sd00000102* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (P8H67 Series Motherboard) pci:v00008086d00000104* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller pci:v00008086d00000104sv00001028sd000004A3* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (Precision M4600) pci:v00008086d00000104sv00001028sd000004B2* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (Vostro 3350) pci:v00008086d00000104sv00001028sd000004DA* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (Vostro 3750) pci:v00008086d00000104sv0000106Bsd000000DC* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (MacBookPro8,2 [Core i7, 15", 2011]) pci:v00008086d00000105* ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port pci:v00008086d00000105sv0000106Bsd000000DC* ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port (MacBookPro8,2 [Core i7, 15", 2011]) pci:v00008086d00000106* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller pci:v00008086d00000108* ID_MODEL_FROM_DATABASE=Xeon E3-1200 Processor Family DRAM Controller pci:v00008086d00000109* ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port pci:v00008086d0000010A* ID_MODEL_FROM_DATABASE=Xeon E3-1200 Processor Family Integrated Graphics Controller pci:v00008086d0000010B* ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family Integrated Graphics Controller pci:v00008086d0000010C* ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family DRAM Controller pci:v00008086d0000010D* ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port pci:v00008086d0000010E* ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family Integrated Graphics Controller pci:v00008086d00000112* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller pci:v00008086d00000116* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller pci:v00008086d00000116sv00001028sd000004DA* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (Vostro 3750) pci:v00008086d00000122* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller pci:v00008086d00000126* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller pci:v00008086d00000126sv00001028sd000004CC* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (Vostro 3350) pci:v00008086d00000150* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller pci:v00008086d00000150sv00001043sd000084CA* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller (P8 series motherboard) pci:v00008086d00000150sv000015D9sd00000624* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller (X9SCM-F Motherboard) pci:v00008086d00000150sv00001849sd00000150* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller (Motherboard) pci:v00008086d00000151* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port pci:v00008086d00000151sv00001043sd00001477* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (N56VZ) pci:v00008086d00000151sv00001043sd0000844D* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (P8 series motherboard) pci:v00008086d00000151sv00001043sd000084CA* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (P8H77-I Motherboard) pci:v00008086d00000151sv00008086sd00002010* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (Server Board S1200BTS) pci:v00008086d00000152* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller pci:v00008086d00000152sv00001043sd000084CA* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (P8H77-I Motherboard) pci:v00008086d00000153* ID_MODEL_FROM_DATABASE=3rd Gen Core Processor Thermal Subsystem pci:v00008086d00000153sv00001043sd00001517* ID_MODEL_FROM_DATABASE=3rd Gen Core Processor Thermal Subsystem (Zenbook Prime UX31A) pci:v00008086d00000154* ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller pci:v00008086d00000154sv00001025sd00000806* ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (Aspire E1-470G) pci:v00008086d00000154sv00001025sd00000813* ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (Aspire R7-571) pci:v00008086d00000154sv0000103Csd000017F6* ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (ProBook 4540s) pci:v00008086d00000154sv00001043sd0000108D* ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (VivoBook X202EV) pci:v00008086d00000154sv00001043sd00001477* ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (N56VZ) pci:v00008086d00000154sv00001043sd00001517* ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (Zenbook Prime UX31A) pci:v00008086d00000155* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port pci:v00008086d00000155sv00008086sd00002010* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (Server Board S1200BTS) pci:v00008086d00000156* ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller pci:v00008086d00000156sv00001043sd0000108D* ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller (VivoBook X202EV) pci:v00008086d00000158* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/Ivy Bridge DRAM Controller pci:v00008086d00000158sv00001043sd0000844D* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/Ivy Bridge DRAM Controller (P8 series motherboard) pci:v00008086d00000158sv00008086sd00002010* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/Ivy Bridge DRAM Controller (Server Board S1200BTS) pci:v00008086d00000159* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port pci:v00008086d0000015A* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/Ivy Bridge Graphics Controller pci:v00008086d0000015C* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller pci:v00008086d0000015D* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port pci:v00008086d0000015Dsv00001043sd0000844D* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (P8 series motherboard) pci:v00008086d0000015E* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller pci:v00008086d00000162* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller pci:v00008086d00000162sv00001043sd000084CA* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (P8 series motherboard) pci:v00008086d00000162sv00001849sd00000162* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (Motherboard) pci:v00008086d00000166* ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller pci:v00008086d00000166sv00001043sd00001517* ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller (Zenbook Prime UX31A) pci:v00008086d00000166sv00001043sd00002103* ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller (N56VZ) pci:v00008086d0000016A* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller pci:v00008086d0000016Asv00001043sd0000844D* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (P8B WS Motherboard) pci:v00008086d00000172* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller pci:v00008086d00000176* ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller pci:v00008086d00000309* ID_MODEL_FROM_DATABASE=80303 I/O Processor PCI-to-PCI Bridge pci:v00008086d0000030D* ID_MODEL_FROM_DATABASE=80312 I/O Companion Chip PCI-to-PCI Bridge pci:v00008086d00000326* ID_MODEL_FROM_DATABASE=6700/6702PXH I/OxAPIC Interrupt Controller A pci:v00008086d00000326sv0000103Csd00003208* ID_MODEL_FROM_DATABASE=6700/6702PXH I/OxAPIC Interrupt Controller A (ProLiant DL140 G2) pci:v00008086d00000326sv00001775sd00001100* ID_MODEL_FROM_DATABASE=6700/6702PXH I/OxAPIC Interrupt Controller A (CR11/VR11 Single Board Computer) pci:v00008086d00000327* ID_MODEL_FROM_DATABASE=6700PXH I/OxAPIC Interrupt Controller B pci:v00008086d00000327sv0000103Csd00003208* ID_MODEL_FROM_DATABASE=6700PXH I/OxAPIC Interrupt Controller B (ProLiant DL140 G2) pci:v00008086d00000327sv00001775sd00001100* ID_MODEL_FROM_DATABASE=6700PXH I/OxAPIC Interrupt Controller B (CR11/VR11 Single Board Computer) pci:v00008086d00000329* ID_MODEL_FROM_DATABASE=6700PXH PCI Express-to-PCI Bridge A pci:v00008086d0000032A* ID_MODEL_FROM_DATABASE=6700PXH PCI Express-to-PCI Bridge B pci:v00008086d0000032C* ID_MODEL_FROM_DATABASE=6702PXH PCI Express-to-PCI Bridge A pci:v00008086d00000330* ID_MODEL_FROM_DATABASE=80332 [Dobson] I/O processor (A-Segment Bridge) pci:v00008086d00000331* ID_MODEL_FROM_DATABASE=80332 [Dobson] I/O processor (A-Segment IOAPIC) pci:v00008086d00000332* ID_MODEL_FROM_DATABASE=80332 [Dobson] I/O processor (B-Segment Bridge) pci:v00008086d00000333* ID_MODEL_FROM_DATABASE=80332 [Dobson] I/O processor (B-Segment IOAPIC) pci:v00008086d00000334* ID_MODEL_FROM_DATABASE=80332 [Dobson] I/O processor (ATU) pci:v00008086d00000335* ID_MODEL_FROM_DATABASE=80331 [Lindsay] I/O processor (PCI-X Bridge) pci:v00008086d00000336* ID_MODEL_FROM_DATABASE=80331 [Lindsay] I/O processor (ATU) pci:v00008086d00000340* ID_MODEL_FROM_DATABASE=41210 [Lanai] Serial to Parallel PCI Bridge (A-Segment Bridge) pci:v00008086d00000341* ID_MODEL_FROM_DATABASE=41210 [Lanai] Serial to Parallel PCI Bridge (B-Segment Bridge) pci:v00008086d00000370* ID_MODEL_FROM_DATABASE=80333 Segment-A PCIe Express to PCI-X bridge pci:v00008086d00000371* ID_MODEL_FROM_DATABASE=80333 A-Bus IOAPIC pci:v00008086d00000372* ID_MODEL_FROM_DATABASE=80333 Segment-B PCIe Express to PCI-X bridge pci:v00008086d00000373* ID_MODEL_FROM_DATABASE=80333 B-Bus IOAPIC pci:v00008086d00000374* ID_MODEL_FROM_DATABASE=80333 Address Translation Unit pci:v00008086d00000402* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller pci:v00008086d00000406* ID_MODEL_FROM_DATABASE=4th Gen Core Processor Integrated Graphics Controller pci:v00008086d0000040A* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3 Processor Integrated Graphics Controller pci:v00008086d00000412* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller pci:v00008086d00000416* ID_MODEL_FROM_DATABASE=4th Gen Core Processor Integrated Graphics Controller pci:v00008086d00000416sv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=4th Gen Core Processor Integrated Graphics Controller (ThinkPad T440p) pci:v00008086d0000041A* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3 Processor Integrated Graphics Controller pci:v00008086d0000041E* ID_MODEL_FROM_DATABASE=4th Generation Core Processor Family Integrated Graphics Controller pci:v00008086d00000434* ID_MODEL_FROM_DATABASE=DH89XXCC Series QAT pci:v00008086d00000435* ID_MODEL_FROM_DATABASE=DH895XCC Series QAT pci:v00008086d00000436* ID_MODEL_FROM_DATABASE=DH8900CC Null Device pci:v00008086d00000438* ID_MODEL_FROM_DATABASE=DH8900CC Series Gigabit Network Connection pci:v00008086d0000043A* ID_MODEL_FROM_DATABASE=DH8900CC Series Gigabit Fiber Network Connection pci:v00008086d0000043C* ID_MODEL_FROM_DATABASE=DH8900CC Series Gigabit Backplane Network Connection pci:v00008086d00000440* ID_MODEL_FROM_DATABASE=DH8900CC Series Gigabit SFP Network Connection pci:v00008086d00000442* ID_MODEL_FROM_DATABASE=DH89XXCC Series QAT Virtual Function pci:v00008086d00000443* ID_MODEL_FROM_DATABASE=DH895XCC Series QAT Virtual Function pci:v00008086d00000482* ID_MODEL_FROM_DATABASE=82375EB/SB PCI to EISA Bridge pci:v00008086d00000483* ID_MODEL_FROM_DATABASE=82424TX/ZX [Saturn] CPU to PCI bridge pci:v00008086d00000484* ID_MODEL_FROM_DATABASE=82378ZB/IB, 82379AB (SIO, SIO.A) PCI to ISA Bridge pci:v00008086d00000486* ID_MODEL_FROM_DATABASE=82425EX/ZX [Aries] PCIset with ISA bridge pci:v00008086d000004A3* ID_MODEL_FROM_DATABASE=82434LX/NX [Mercury/Neptune] Processor to PCI bridge pci:v00008086d000004D0* ID_MODEL_FROM_DATABASE=82437FX [Triton FX] pci:v00008086d00000500* ID_MODEL_FROM_DATABASE=E8870 Processor bus control pci:v00008086d00000501* ID_MODEL_FROM_DATABASE=E8870 Memory controller pci:v00008086d00000502* ID_MODEL_FROM_DATABASE=E8870 Scalability Port 0 pci:v00008086d00000503* ID_MODEL_FROM_DATABASE=E8870 Scalability Port 1 pci:v00008086d00000510* ID_MODEL_FROM_DATABASE=E8870IO Hub Interface Port 0 registers (8-bit compatibility port) pci:v00008086d00000511* ID_MODEL_FROM_DATABASE=E8870IO Hub Interface Port 1 registers pci:v00008086d00000512* ID_MODEL_FROM_DATABASE=E8870IO Hub Interface Port 2 registers pci:v00008086d00000513* ID_MODEL_FROM_DATABASE=E8870IO Hub Interface Port 3 registers pci:v00008086d00000514* ID_MODEL_FROM_DATABASE=E8870IO Hub Interface Port 4 registers pci:v00008086d00000515* ID_MODEL_FROM_DATABASE=E8870IO General SIOH registers pci:v00008086d00000516* ID_MODEL_FROM_DATABASE=E8870IO RAS registers pci:v00008086d00000530* ID_MODEL_FROM_DATABASE=E8870SP Scalability Port 0 registers pci:v00008086d00000531* ID_MODEL_FROM_DATABASE=E8870SP Scalability Port 1 registers pci:v00008086d00000532* ID_MODEL_FROM_DATABASE=E8870SP Scalability Port 2 registers pci:v00008086d00000533* ID_MODEL_FROM_DATABASE=E8870SP Scalability Port 3 registers pci:v00008086d00000534* ID_MODEL_FROM_DATABASE=E8870SP Scalability Port 4 registers pci:v00008086d00000535* ID_MODEL_FROM_DATABASE=E8870SP Scalability Port 5 registers pci:v00008086d00000536* ID_MODEL_FROM_DATABASE=E8870SP Interleave registers 0 and 1 pci:v00008086d00000537* ID_MODEL_FROM_DATABASE=E8870SP Interleave registers 2 and 3 pci:v00008086d00000600* ID_MODEL_FROM_DATABASE=RAID Controller pci:v00008086d00000600sv00008086sd00000136* ID_MODEL_FROM_DATABASE=RAID Controller (SRCU31L) pci:v00008086d00000600sv00008086sd000001AF* ID_MODEL_FROM_DATABASE=RAID Controller (SRCZCR) pci:v00008086d00000600sv00008086sd000001C1* ID_MODEL_FROM_DATABASE=RAID Controller (ICP Vortex GDT8546RZ) pci:v00008086d00000600sv00008086sd000001F7* ID_MODEL_FROM_DATABASE=RAID Controller (SCRU32) pci:v00008086d0000061F* ID_MODEL_FROM_DATABASE=80303 I/O Processor pci:v00008086d00000700* ID_MODEL_FROM_DATABASE=CE Media Processor A/V Bridge pci:v00008086d00000701* ID_MODEL_FROM_DATABASE=CE Media Processor NAND Flash Controller pci:v00008086d00000703* ID_MODEL_FROM_DATABASE=CE Media Processor Media Control Unit 1 pci:v00008086d00000704* ID_MODEL_FROM_DATABASE=CE Media Processor Video Capture Interface pci:v00008086d00000707* ID_MODEL_FROM_DATABASE=CE Media Processor SPI Slave pci:v00008086d00000708* ID_MODEL_FROM_DATABASE=CE Media Processor 4100 pci:v00008086d00000800* ID_MODEL_FROM_DATABASE=Moorestown SPI Ctrl 0 pci:v00008086d00000801* ID_MODEL_FROM_DATABASE=Moorestown SPI Ctrl 1 pci:v00008086d00000802* ID_MODEL_FROM_DATABASE=Moorestown I2C 0 pci:v00008086d00000803* ID_MODEL_FROM_DATABASE=Moorestown I2C 1 pci:v00008086d00000804* ID_MODEL_FROM_DATABASE=Moorestown I2C 2 pci:v00008086d00000805* ID_MODEL_FROM_DATABASE=Moorestown Keyboard Ctrl pci:v00008086d00000806* ID_MODEL_FROM_DATABASE=Moorestown USB Ctrl pci:v00008086d00000807* ID_MODEL_FROM_DATABASE=Moorestown SD Host Ctrl 0 pci:v00008086d00000808* ID_MODEL_FROM_DATABASE=Moorestown SD Host Ctrl 1 pci:v00008086d00000809* ID_MODEL_FROM_DATABASE=Moorestown NAND Ctrl pci:v00008086d0000080A* ID_MODEL_FROM_DATABASE=Moorestown Audio Ctrl pci:v00008086d0000080B* ID_MODEL_FROM_DATABASE=Moorestown ISP pci:v00008086d0000080C* ID_MODEL_FROM_DATABASE=Moorestown Security Controller pci:v00008086d0000080D* ID_MODEL_FROM_DATABASE=Moorestown External Displays pci:v00008086d0000080E* ID_MODEL_FROM_DATABASE=Moorestown SCU IPC pci:v00008086d0000080F* ID_MODEL_FROM_DATABASE=Moorestown GPIO Controller pci:v00008086d00000810* ID_MODEL_FROM_DATABASE=Moorestown Power Management Unit pci:v00008086d00000811* ID_MODEL_FROM_DATABASE=Moorestown OTG Ctrl pci:v00008086d00000812* ID_MODEL_FROM_DATABASE=Moorestown SPI Ctrl 2 pci:v00008086d00000813* ID_MODEL_FROM_DATABASE=Moorestown SC DMA pci:v00008086d00000814* ID_MODEL_FROM_DATABASE=Moorestown LPE DMA pci:v00008086d00000815* ID_MODEL_FROM_DATABASE=Moorestown SSP0 pci:v00008086d00000885* ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 pci:v00008086d00000885sv00008086sd00001305* ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 (BGN) pci:v00008086d00000885sv00008086sd00001307* ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 (BG) pci:v00008086d00000885sv00008086sd00001325* ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 (BGN) pci:v00008086d00000885sv00008086sd00001327* ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 (BG) pci:v00008086d00000886* ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 pci:v00008086d00000886sv00008086sd00001315* ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 (BGN) pci:v00008086d00000886sv00008086sd00001317* ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 (BG) pci:v00008086d00000887* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2230 pci:v00008086d00000887sv00008086sd00004062* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2230 (BGN) pci:v00008086d00000887sv00008086sd00004462* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2230 (BGN) pci:v00008086d00000888* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2230 pci:v00008086d00000888sv00008086sd00004262* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2230 (BGN) pci:v00008086d0000088E* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6235 pci:v00008086d0000088Esv00008086sd00004060* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6235 (AGN) pci:v00008086d0000088Esv00008086sd00004460* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6235 (AGN) pci:v00008086d0000088F* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6235 pci:v00008086d0000088Fsv00008086sd00004260* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6235 (AGN) pci:v00008086d00000890* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2200 pci:v00008086d00000890sv00008086sd00004022* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2200 (BGN) pci:v00008086d00000890sv00008086sd00004422* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2200 (BGN) pci:v00008086d00000890sv00008086sd00004822* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2200 (BGN) pci:v00008086d00000891* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2200 pci:v00008086d00000891sv00008086sd00004222* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2200 (BGN) pci:v00008086d00000892* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 135 pci:v00008086d00000892sv00008086sd00000062* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 135 (BGN) pci:v00008086d00000892sv00008086sd00000462* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 135 (BGN) pci:v00008086d00000893* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 135 pci:v00008086d00000893sv00008086sd00000262* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 135 (BGN) pci:v00008086d00000894* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 105 pci:v00008086d00000894sv00008086sd00000022* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 105 (BGN) pci:v00008086d00000894sv00008086sd00000422* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 105 (BGN) pci:v00008086d00000894sv00008086sd00000822* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 105 (BGN) pci:v00008086d00000895* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 105 pci:v00008086d00000895sv00008086sd00000222* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 105 (BGN) pci:v00008086d00000896* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 pci:v00008086d00000896sv00008086sd00005005* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 (BGN) pci:v00008086d00000896sv00008086sd00005007* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 (BG) pci:v00008086d00000896sv00008086sd00005025* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 (BGN) pci:v00008086d00000896sv00008086sd00005027* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 (BG) pci:v00008086d00000897* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 pci:v00008086d00000897sv00008086sd00005015* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 (BGN) pci:v00008086d00000897sv00008086sd00005017* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 (BG) pci:v00008086d000008AE* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 pci:v00008086d000008AEsv00008086sd00001005* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 (BGN) pci:v00008086d000008AEsv00008086sd00001007* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 (BG) pci:v00008086d000008AEsv00008086sd00001025* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 (BGN) pci:v00008086d000008AEsv00008086sd00001027* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 (BG) pci:v00008086d000008AF* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 pci:v00008086d000008AFsv00008086sd00001015* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 (BGN) pci:v00008086d000008AFsv00008086sd00001017* ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 (BG) pci:v00008086d000008B1* ID_MODEL_FROM_DATABASE=Wireless 7260 pci:v00008086d000008B1sv00008086sd00004020* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000402A* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd00004060* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd00004062* ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000406A* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd00004070* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00004072* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00004160* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd00004162* ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) pci:v00008086d000008B1sv00008086sd00004170* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00004420* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd00004460* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd00004462* ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000446A* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd00004470* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00004472* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00004560* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd00004570* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd0000486E* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00004870* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00004A6C* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00004A6E* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00004A70* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00004C60* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00004C70* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00005070* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00005072* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00005170* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd00005770* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd0000C020* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000C02A* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000C060* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000C062* ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000C06A* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000C070* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd0000C072* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd0000C160* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000C162* ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000C170* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd0000C360* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000C420* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000C460* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000C462* ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000C470* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd0000C472* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd0000C560* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000C570* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd0000C760* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B1sv00008086sd0000C770* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd0000CC60* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B1sv00008086sd0000CC70* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B2* ID_MODEL_FROM_DATABASE=Wireless 7260 pci:v00008086d000008B2sv00008086sd00004220* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B2sv00008086sd00004260* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B2sv00008086sd00004262* ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) pci:v00008086d000008B2sv00008086sd0000426A* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B2sv00008086sd00004270* ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) pci:v00008086d000008B2sv00008086sd00004272* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B2sv00008086sd00004360* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B2sv00008086sd00004370* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B2sv00008086sd0000C220* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B2sv00008086sd0000C260* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B2sv00008086sd0000C262* ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) pci:v00008086d000008B2sv00008086sd0000C26A* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) pci:v00008086d000008B2sv00008086sd0000C270* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B2sv00008086sd0000C272* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B2sv00008086sd0000C370* ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) pci:v00008086d000008B3* ID_MODEL_FROM_DATABASE=Wireless 3160 pci:v00008086d000008B3sv00008086sd00000060* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-N 3160) pci:v00008086d000008B3sv00008086sd00000062* ID_MODEL_FROM_DATABASE=Wireless 3160 (Wireless-N 3160) pci:v00008086d000008B3sv00008086sd00000070* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) pci:v00008086d000008B3sv00008086sd00000072* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) pci:v00008086d000008B3sv00008086sd00000170* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) pci:v00008086d000008B3sv00008086sd00000172* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) pci:v00008086d000008B3sv00008086sd00000260* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-N 3160) pci:v00008086d000008B3sv00008086sd00000470* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) pci:v00008086d000008B3sv00008086sd00000472* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) pci:v00008086d000008B3sv00008086sd00001070* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) pci:v00008086d000008B3sv00008086sd00001170* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) pci:v00008086d000008B3sv00008086sd00008060* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless N-3160) pci:v00008086d000008B3sv00008086sd00008062* ID_MODEL_FROM_DATABASE=Wireless 3160 (Wireless N-3160) pci:v00008086d000008B3sv00008086sd00008070* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) pci:v00008086d000008B3sv00008086sd00008072* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) pci:v00008086d000008B3sv00008086sd00008170* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) pci:v00008086d000008B3sv00008086sd00008172* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) pci:v00008086d000008B3sv00008086sd00008470* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) pci:v00008086d000008B3sv00008086sd00008570* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) pci:v00008086d000008B4* ID_MODEL_FROM_DATABASE=Wireless 3160 pci:v00008086d000008B4sv00008086sd00000270* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) pci:v00008086d000008B4sv00008086sd00000272* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) pci:v00008086d000008B4sv00008086sd00000370* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) pci:v00008086d000008B4sv00008086sd00008260* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) pci:v00008086d000008B4sv00008086sd00008270* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) pci:v00008086d000008B4sv00008086sd00008272* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) pci:v00008086d000008B4sv00008086sd00008370* ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) pci:v00008086d000008CF* ID_MODEL_FROM_DATABASE=Atom Processor Z2760 Integrated Graphics Controller pci:v00008086d00000953* ID_MODEL_FROM_DATABASE=PCIe Data Center SSD pci:v00008086d00000953sv00008086sd00003702* ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (DC P3700 SSD) pci:v00008086d00000953sv00008086sd00003703* ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (DC P3700 SSD [2.5" SFF]) pci:v00008086d00000953sv00008086sd00003704* ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (DC P3500 SSD [Add-in Card]) pci:v00008086d00000953sv00008086sd00003705* ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (DC P3500 SSD [2.5" SFF]) pci:v00008086d00000953sv00008086sd00003709* ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (DC P3600 SSD [Add-in Card]) pci:v00008086d00000953sv00008086sd0000370A* ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (DC P3600 SSD [2.5" SFF]) pci:v00008086d00000953sv00008086sd0000370D* ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (SSD 750 Series [Add-in Card]) pci:v00008086d00000953sv00008086sd0000370E* ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (SSD 750 Series [2.5" SFF]) pci:v00008086d0000095A* ID_MODEL_FROM_DATABASE=Wireless 7265 pci:v00008086d0000095Asv00008086sd00001010* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005000* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) pci:v00008086d0000095Asv00008086sd00005002* ID_MODEL_FROM_DATABASE=Wireless 7265 (Wireless-N 7265) pci:v00008086d0000095Asv00008086sd0000500A* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) pci:v00008086d0000095Asv00008086sd00005010* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005012* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005020* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) pci:v00008086d0000095Asv00008086sd0000502A* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) pci:v00008086d0000095Asv00008086sd00005090* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005100* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005102* ID_MODEL_FROM_DATABASE=Wireless 7265 (Wireless-N 7265) pci:v00008086d0000095Asv00008086sd0000510A* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005110* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005112* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005190* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005400* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005410* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005412* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005420* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) pci:v00008086d0000095Asv00008086sd00005490* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005510* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00005590* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00009000* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd0000900A* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00009010* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00009012* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00009110* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00009112* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00009210* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00009310* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00009400* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00009410* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Asv00008086sd00009510* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095B* ID_MODEL_FROM_DATABASE=Wireless 7265 pci:v00008086d0000095Bsv00008086sd00005200* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) pci:v00008086d0000095Bsv00008086sd00005202* ID_MODEL_FROM_DATABASE=Wireless 7265 (Wireless-N 7265) pci:v00008086d0000095Bsv00008086sd0000520A* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) pci:v00008086d0000095Bsv00008086sd00005210* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Bsv00008086sd00005212* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Bsv00008086sd00005290* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Bsv00008086sd00005302* ID_MODEL_FROM_DATABASE=Wireless 7265 (Wireless-N 7265) pci:v00008086d0000095Bsv00008086sd00005310* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d0000095Bsv00008086sd00009200* ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) pci:v00008086d00000960* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor/Bridge pci:v00008086d00000962* ID_MODEL_FROM_DATABASE=80960RM (i960RM) Bridge pci:v00008086d00000964* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor/Bridge pci:v00008086d00000A04* ID_MODEL_FROM_DATABASE=Haswell-ULT DRAM Controller pci:v00008086d00000A04sv000017AAsd00002214* ID_MODEL_FROM_DATABASE=Haswell-ULT DRAM Controller (ThinkPad X240) pci:v00008086d00000A06* ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller pci:v00008086d00000A0C* ID_MODEL_FROM_DATABASE=Haswell-ULT HD Audio Controller pci:v00008086d00000A0Csv000017AAsd00002214* ID_MODEL_FROM_DATABASE=Haswell-ULT HD Audio Controller (ThinkPad X240) pci:v00008086d00000A16* ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller pci:v00008086d00000A16sv000017AAsd00002214* ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller (ThinkPad X240) pci:v00008086d00000A22* ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller pci:v00008086d00000A26* ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller pci:v00008086d00000A2A* ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller pci:v00008086d00000A2E* ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller pci:v00008086d00000BE0* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BE1* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BE1sv0000105Bsd00000D7C* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller (D270S/D250S Motherboard) pci:v00008086d00000BE2* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BE3* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BE4* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BE5* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BE6* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BE7* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BE8* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BE9* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BEA* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BEB* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BEC* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BED* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BEE* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BEF* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller pci:v00008086d00000BF0* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller pci:v00008086d00000BF1* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller pci:v00008086d00000BF2* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller pci:v00008086d00000BF3* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller pci:v00008086d00000BF4* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller pci:v00008086d00000BF5* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller pci:v00008086d00000BF5sv0000105Bsd00000D7C* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller (D270S/D250S Motherboard) pci:v00008086d00000BF6* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller pci:v00008086d00000BF7* ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller pci:v00008086d00000C00* ID_MODEL_FROM_DATABASE=4th Gen Core Processor DRAM Controller pci:v00008086d00000C01* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor PCI Express x16 Controller pci:v00008086d00000C04* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller pci:v00008086d00000C04sv0000103Csd00001909* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller (ZBook 15) pci:v00008086d00000C04sv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller (ThinkPad T440p) pci:v00008086d00000C05* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor PCI Express x8 Controller pci:v00008086d00000C08* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3 Processor DRAM Controller pci:v00008086d00000C09* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor PCI Express x4 Controller pci:v00008086d00000C0C* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller pci:v00008086d00000C0Csv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller (ThinkPad T440p) pci:v00008086d00000C46* ID_MODEL_FROM_DATABASE=Atom Processor S1200 PCI Express Root Port 1 pci:v00008086d00000C47* ID_MODEL_FROM_DATABASE=Atom Processor S1200 PCI Express Root Port 2 pci:v00008086d00000C48* ID_MODEL_FROM_DATABASE=Atom Processor S1200 PCI Express Root Port 3 pci:v00008086d00000C49* ID_MODEL_FROM_DATABASE=Atom Processor S1200 PCI Express Root Port 4 pci:v00008086d00000C4E* ID_MODEL_FROM_DATABASE=Atom Processor S1200 NTB Primary pci:v00008086d00000C50* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device pci:v00008086d00000C51* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device pci:v00008086d00000C52* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device pci:v00008086d00000C53* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device pci:v00008086d00000C54* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C55* ID_MODEL_FROM_DATABASE=Atom Processor S1200 DFX 1 pci:v00008086d00000C56* ID_MODEL_FROM_DATABASE=Atom Processor S1200 DFX 2 pci:v00008086d00000C59* ID_MODEL_FROM_DATABASE=Atom Processor S1200 SMBus 2.0 Controller 0 pci:v00008086d00000C5A* ID_MODEL_FROM_DATABASE=Atom Processor S1200 SMBus 2.0 Controller 1 pci:v00008086d00000C5B* ID_MODEL_FROM_DATABASE=Atom Processor S1200 SMBus Controller 2 pci:v00008086d00000C5C* ID_MODEL_FROM_DATABASE=Atom Processor S1200 SMBus Controller 3 pci:v00008086d00000C5D* ID_MODEL_FROM_DATABASE=Atom Processor S1200 SMBus Controller 4 pci:v00008086d00000C5E* ID_MODEL_FROM_DATABASE=Atom Processor S1200 SMBus Controller 5 pci:v00008086d00000C5F* ID_MODEL_FROM_DATABASE=Atom Processor S1200 UART pci:v00008086d00000C60* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Integrated Legacy Bus pci:v00008086d00000C70* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C71* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C72* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C73* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C74* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C75* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C76* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C77* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C78* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C79* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C7A* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C7B* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C7C* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C7D* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C7E* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000C7F* ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal pci:v00008086d00000D00* ID_MODEL_FROM_DATABASE=Crystal Well DRAM Controller pci:v00008086d00000D01* ID_MODEL_FROM_DATABASE=Crystal Well PCI Express x16 Controller pci:v00008086d00000D04* ID_MODEL_FROM_DATABASE=Crystal Well DRAM Controller pci:v00008086d00000D05* ID_MODEL_FROM_DATABASE=Crystal Well PCI Express x8 Controller pci:v00008086d00000D09* ID_MODEL_FROM_DATABASE=Crystal Well PCI Express x4 Controller pci:v00008086d00000D0C* ID_MODEL_FROM_DATABASE=Crystal Well HD Audio Controller pci:v00008086d00000D16* ID_MODEL_FROM_DATABASE=Crystal Well Integrated Graphics Controller pci:v00008086d00000D26* ID_MODEL_FROM_DATABASE=Crystal Well Integrated Graphics Controller pci:v00008086d00000D36* ID_MODEL_FROM_DATABASE=Crystal Well Integrated Graphics Controller pci:v00008086d00000E00* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DMI2 pci:v00008086d00000E01* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port in DMI2 Mode pci:v00008086d00000E02* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 1a pci:v00008086d00000E03* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 1b pci:v00008086d00000E04* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 2a pci:v00008086d00000E05* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 2b pci:v00008086d00000E06* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 2c pci:v00008086d00000E07* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 2d pci:v00008086d00000E08* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 3a pci:v00008086d00000E09* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 3b pci:v00008086d00000E0A* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 3c pci:v00008086d00000E0B* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 3d pci:v00008086d00000E10* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers pci:v00008086d00000E13* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers pci:v00008086d00000E17* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers pci:v00008086d00000E18* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers pci:v00008086d00000E1C* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers pci:v00008086d00000E1D* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 R2PCIe pci:v00008086d00000E1E* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 UBOX Registers pci:v00008086d00000E1F* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 UBOX Registers pci:v00008086d00000E20* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 0 pci:v00008086d00000E21* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 1 pci:v00008086d00000E22* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 2 pci:v00008086d00000E23* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 3 pci:v00008086d00000E24* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 4 pci:v00008086d00000E25* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 5 pci:v00008086d00000E26* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 6 pci:v00008086d00000E27* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 7 pci:v00008086d00000E28* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 VTd/Memory Map/Misc pci:v00008086d00000E29* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Memory Hotplug pci:v00008086d00000E2A* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO RAS pci:v00008086d00000E2C* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IOAPIC pci:v00008086d00000E2E* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 CBDMA pci:v00008086d00000E2F* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 CBDMA pci:v00008086d00000E30* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 0 pci:v00008086d00000E32* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 0 pci:v00008086d00000E33* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 1 pci:v00008086d00000E34* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 R2PCIe pci:v00008086d00000E36* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring pci:v00008086d00000E37* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring pci:v00008086d00000E38* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 1 pci:v00008086d00000E3A* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 2 pci:v00008086d00000E3E* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring pci:v00008086d00000E3F* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring pci:v00008086d00000E40* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 2 pci:v00008086d00000E41* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Registers pci:v00008086d00000E43* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 2 pci:v00008086d00000E44* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 2 pci:v00008086d00000E45* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Agent Register pci:v00008086d00000E47* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Agent Register pci:v00008086d00000E60* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 1 pci:v00008086d00000E68* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Target Address/Thermal Registers pci:v00008086d00000E6A* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers pci:v00008086d00000E6B* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers pci:v00008086d00000E6C* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers pci:v00008086d00000E6D* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers pci:v00008086d00000E71* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 RAS Registers pci:v00008086d00000E74* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 R2PCIe pci:v00008086d00000E75* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 R2PCIe pci:v00008086d00000E77* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Registers pci:v00008086d00000E79* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 RAS Registers pci:v00008086d00000E7D* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 UBOX Registers pci:v00008086d00000E7F* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Registers pci:v00008086d00000E80* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 0 pci:v00008086d00000E81* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Registers pci:v00008086d00000E83* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 0 pci:v00008086d00000E84* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 0 pci:v00008086d00000E85* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Agent Register pci:v00008086d00000E87* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Registers pci:v00008086d00000E90* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 1 pci:v00008086d00000E93* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 1 pci:v00008086d00000E94* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 1 pci:v00008086d00000E95* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Agent Register pci:v00008086d00000EA0* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 0 pci:v00008086d00000EA8* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Target Address/Thermal Registers pci:v00008086d00000EAA* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers pci:v00008086d00000EAB* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers pci:v00008086d00000EAC* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers pci:v00008086d00000EAD* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers pci:v00008086d00000EAE* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers pci:v00008086d00000EAF* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers pci:v00008086d00000EB0* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 0 pci:v00008086d00000EB1* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 1 pci:v00008086d00000EB2* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 0 pci:v00008086d00000EB3* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 1 pci:v00008086d00000EB4* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 2 pci:v00008086d00000EB5* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 3 pci:v00008086d00000EB6* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 2 pci:v00008086d00000EB7* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 3 pci:v00008086d00000EBC* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers pci:v00008086d00000EBE* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers pci:v00008086d00000EBF* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers pci:v00008086d00000EC0* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 0 pci:v00008086d00000EC1* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 1 pci:v00008086d00000EC2* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 2 pci:v00008086d00000EC3* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 3 pci:v00008086d00000EC4* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 4 pci:v00008086d00000EC8* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 System Address Decoder pci:v00008086d00000EC9* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Broadcast Registers pci:v00008086d00000ECA* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Broadcast Registers pci:v00008086d00000ED8* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO pci:v00008086d00000ED9* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO pci:v00008086d00000EDC* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO pci:v00008086d00000EDD* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO pci:v00008086d00000EDE* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO pci:v00008086d00000EDF* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO pci:v00008086d00000EE0* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EE1* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EE2* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EE3* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EE4* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EE5* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EE6* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EE7* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EE8* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EE9* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EEA* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EEB* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EEC* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EED* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EEE* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers pci:v00008086d00000EF0* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 0 pci:v00008086d00000EF1* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 1 pci:v00008086d00000EF2* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 0 pci:v00008086d00000EF3* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 1 pci:v00008086d00000EF4* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 2 pci:v00008086d00000EF5* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 3 pci:v00008086d00000EF6* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 2 pci:v00008086d00000EF7* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 3 pci:v00008086d00000EF8* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO pci:v00008086d00000EF9* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO pci:v00008086d00000EFA* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO pci:v00008086d00000EFB* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO pci:v00008086d00000EFC* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO pci:v00008086d00000EFD* ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO pci:v00008086d00000F00* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series SoC Transaction Register pci:v00008086d00000F04* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series High Definition Audio Controller pci:v00008086d00000F06* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO1 DMA Controller pci:v00008086d00000F08* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO1 PWM Controller pci:v00008086d00000F09* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO1 PWM Controller pci:v00008086d00000F0A* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO1 HSUART Controller #1 pci:v00008086d00000F0C* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO1 HSUART Controller #2 pci:v00008086d00000F0E* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO1 SPI Controller pci:v00008086d00000F12* ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series SMBus Controller pci:v00008086d00000F14* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series SDIO Controller pci:v00008086d00000F15* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series SDIO Controller pci:v00008086d00000F16* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series SDIO Controller pci:v00008086d00000F18* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series Trusted Execution Engine pci:v00008086d00000F1C* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series Power Control Unit pci:v00008086d00000F20* ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series SATA IDE Controller pci:v00008086d00000F21* ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series SATA IDE Controller pci:v00008086d00000F22* ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series SATA AHCI Controller pci:v00008086d00000F23* ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series SATA AHCI Controller pci:v00008086d00000F28* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPE Audio Controller pci:v00008086d00000F31* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series Graphics & Display pci:v00008086d00000F34* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series USB EHCI pci:v00008086d00000F35* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx, Celeron N2000 Series USB xHCI pci:v00008086d00000F35sv00001025sd00000936* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx, Celeron N2000 Series USB xHCI (Aspire ES1) pci:v00008086d00000F37* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series OTG USB Device pci:v00008086d00000F38* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series Camera ISP pci:v00008086d00000F40* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 DMA Controller pci:v00008086d00000F41* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #1 pci:v00008086d00000F42* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #2 pci:v00008086d00000F43* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #3 pci:v00008086d00000F44* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #4 pci:v00008086d00000F45* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #5 pci:v00008086d00000F46* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #6 pci:v00008086d00000F47* ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #7 pci:v00008086d00000F48* ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series PCI Express Root Port 1 pci:v00008086d00000F4A* ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series PCI Express Root Port 2 pci:v00008086d00000F4C* ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series PCI Express Root Port 3 pci:v00008086d00000F4E* ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series PCI Express Root Port 4 pci:v00008086d00000F50* ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series eMMC 4.5 Controller pci:v00008086d00001000* ID_MODEL_FROM_DATABASE=82542 Gigabit Ethernet Controller (Fiber) pci:v00008086d00001000sv00000E11sd0000B0DF* ID_MODEL_FROM_DATABASE=82542 Gigabit Ethernet Controller (Fiber) (NC6132 Gigabit Ethernet Adapter (1000-SX)) pci:v00008086d00001000sv00000E11sd0000B0E0* ID_MODEL_FROM_DATABASE=82542 Gigabit Ethernet Controller (Fiber) (NC6133 Gigabit Ethernet Adapter (1000-LX)) pci:v00008086d00001000sv00000E11sd0000B123* ID_MODEL_FROM_DATABASE=82542 Gigabit Ethernet Controller (Fiber) (NC6134 Gigabit Ethernet Adapter (1000-LX)) pci:v00008086d00001000sv00001014sd00000119* ID_MODEL_FROM_DATABASE=82542 Gigabit Ethernet Controller (Fiber) (Netfinity Gigabit Ethernet SX Adapter) pci:v00008086d00001000sv00008086sd00001000* ID_MODEL_FROM_DATABASE=82542 Gigabit Ethernet Controller (Fiber) (PRO/1000 Gigabit Server Adapter) pci:v00008086d00001001* ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Fiber) pci:v00008086d00001001sv00000E11sd0000004A* ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Fiber) (NC6136 Gigabit Server Adapter) pci:v00008086d00001001sv00001014sd000001EA* ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Fiber) (Netfinity Gigabit Ethernet SX Adapter) pci:v00008086d00001001sv00008086sd00001002* ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Fiber) (PRO/1000 F Server Adapter) pci:v00008086d00001001sv00008086sd00001003* ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Fiber) (PRO/1000 F Server Adapter) pci:v00008086d00001002* ID_MODEL_FROM_DATABASE=Pro 100 LAN+Modem 56 Cardbus II pci:v00008086d00001002sv00008086sd0000200E* ID_MODEL_FROM_DATABASE=Pro 100 LAN+Modem 56 Cardbus II pci:v00008086d00001002sv00008086sd00002013* ID_MODEL_FROM_DATABASE=Pro 100 LAN+Modem 56 Cardbus II (Pro 100 SR Mobile Combo Adapter) pci:v00008086d00001002sv00008086sd00002017* ID_MODEL_FROM_DATABASE=Pro 100 LAN+Modem 56 Cardbus II (Pro 100 S Combo Mobile Adapter) pci:v00008086d00001004* ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Copper) pci:v00008086d00001004sv00000E11sd00000049* ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Copper) (NC7132 Gigabit Upgrade Module) pci:v00008086d00001004sv00000E11sd0000B1A4* ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Copper) (NC7131 Gigabit Server Adapter) pci:v00008086d00001004sv00001014sd000010F2* ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Copper) (Gigabit Ethernet Server Adapter) pci:v00008086d00001004sv00008086sd00001004* ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Copper) (PRO/1000 T Server Adapter) pci:v00008086d00001004sv00008086sd00002004* ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Copper) (PRO/1000 T Server Adapter) pci:v00008086d00001008* ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) pci:v00008086d00001008sv00001014sd00000269* ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (iSeries 1000/100/10 Ethernet Adapter) pci:v00008086d00001008sv00001028sd0000011B* ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (PowerEdge 1650/2550) pci:v00008086d00001008sv00001028sd0000011C* ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (PRO/1000 XT Network Connection) pci:v00008086d00001008sv00008086sd00001107* ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (PRO/1000 XT Server Adapter) pci:v00008086d00001008sv00008086sd00002107* ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (PRO/1000 XT Server Adapter) pci:v00008086d00001008sv00008086sd00002110* ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (PRO/1000 XT Desktop Adapter) pci:v00008086d00001008sv00008086sd00003108* ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (PRO/1000 XT Network Connection) pci:v00008086d00001009* ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Fiber) pci:v00008086d00001009sv00001014sd00000268* ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Fiber) (iSeries Gigabit Ethernet Adapter) pci:v00008086d00001009sv00008086sd00001109* ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Fiber) (PRO/1000 XF Server Adapter) pci:v00008086d00001009sv00008086sd00002109* ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Fiber) (PRO/1000 XF Server Adapter) pci:v00008086d0000100A* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller pci:v00008086d0000100C* ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (Copper) pci:v00008086d0000100Csv00008086sd00001112* ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (Copper) (PRO/1000 T Desktop Adapter) pci:v00008086d0000100Csv00008086sd00002112* ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (Copper) (PRO/1000 T Desktop Adapter) pci:v00008086d0000100D* ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (LOM) pci:v00008086d0000100Dsv00001028sd00000123* ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (LOM) (PRO/1000 XT Network Connection) pci:v00008086d0000100Dsv00001079sd0000891F* ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (LOM) (82544GC Based Network Connection) pci:v00008086d0000100Dsv00004C53sd00001080* ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (LOM) (CT8 mainboard) pci:v00008086d0000100Dsv00008086sd0000110D* ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (LOM) (82544GC Based Network Connection) pci:v00008086d0000100E* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller pci:v00008086d0000100Esv00001014sd00000265* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 MT Network Connection) pci:v00008086d0000100Esv00001014sd00000267* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 MT Network Connection) pci:v00008086d0000100Esv00001014sd0000026A* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 MT Network Connection) pci:v00008086d0000100Esv00001028sd0000002E* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (Optiplex GX260) pci:v00008086d0000100Esv00001028sd00000134* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PowerEdge 600SC) pci:v00008086d0000100Esv00001028sd00000151* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (Optiplex GX270) pci:v00008086d0000100Esv0000107Bsd00008920* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 MT Desktop Adapter) pci:v00008086d0000100Esv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (QEMU Virtual Machine) pci:v00008086d0000100Esv00008086sd0000001E* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 MT Desktop Adapter) pci:v00008086d0000100Esv00008086sd0000002E* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 MT Desktop Adapter) pci:v00008086d0000100Esv00008086sd00001376* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 GT Desktop Adapter) pci:v00008086d0000100Esv00008086sd00001476* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 GT Desktop Adapter) pci:v00008086d0000100F* ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Copper) pci:v00008086d0000100Fsv00001014sd00000269* ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Copper) (iSeries 1000/100/10 Ethernet Adapter) pci:v00008086d0000100Fsv00001014sd0000028E* ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Copper) (PRO/1000 MT Network Connection) pci:v00008086d0000100Fsv000015ADsd00000750* ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Copper) (PRO/1000 MT Single Port Adapter) pci:v00008086d0000100Fsv00008086sd00001000* ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Copper) (PRO/1000 MT Network Connection) pci:v00008086d0000100Fsv00008086sd00001001* ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Copper) (PRO/1000 MT Server Adapter) pci:v00008086d00001010* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) pci:v00008086d00001010sv00000E11sd000000DB* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (NC7170 Gigabit Server Adapter) pci:v00008086d00001010sv00001014sd0000027C* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (PRO/1000 MT Dual Port Network Adapter) pci:v00008086d00001010sv000015ADsd00000760* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (PRO/1000 MT Dual Port Adapter) pci:v00008086d00001010sv000018FBsd00007872* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (RESlink-X) pci:v00008086d00001010sv00001FC1sd00000026* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (Niagara 2260 Bypass Card) pci:v00008086d00001010sv00004C53sd00001080* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (CT8 mainboard) pci:v00008086d00001010sv00004C53sd000010A0* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (CA3/CR3 mainboard) pci:v00008086d00001010sv00008086sd00001011* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (PRO/1000 MT Dual Port Server Adapter) pci:v00008086d00001010sv00008086sd00001012* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (PRO/1000 MT Dual Port Server Adapter) pci:v00008086d00001010sv00008086sd0000101A* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (PRO/1000 MT Dual Port Network Connection) pci:v00008086d00001010sv00008086sd00003424* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (SE7501HG2 Mainboard) pci:v00008086d00001011* ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Fiber) pci:v00008086d00001011sv00001014sd00000268* ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Fiber) (iSeries Gigabit Ethernet Adapter) pci:v00008086d00001011sv00008086sd00001002* ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Fiber) (PRO/1000 MF Server Adapter) pci:v00008086d00001011sv00008086sd00001003* ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Fiber) (PRO/1000 MF Server Adapter (LX)) pci:v00008086d00001012* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Fiber) pci:v00008086d00001012sv00000E11sd000000DC* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Fiber) (NC6170 Gigabit Server Adapter) pci:v00008086d00001012sv00008086sd00001012* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Fiber) (PRO/1000 MF Dual Port Server Adapter) pci:v00008086d00001013* ID_MODEL_FROM_DATABASE=82541EI Gigabit Ethernet Controller pci:v00008086d00001013sv00008086sd00000013* ID_MODEL_FROM_DATABASE=82541EI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) pci:v00008086d00001013sv00008086sd00001013* ID_MODEL_FROM_DATABASE=82541EI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) pci:v00008086d00001013sv00008086sd00001113* ID_MODEL_FROM_DATABASE=82541EI Gigabit Ethernet Controller (PRO/1000 MT Desktop Adapter) pci:v00008086d00001014* ID_MODEL_FROM_DATABASE=82541ER Gigabit Ethernet Controller pci:v00008086d00001014sv00008086sd00000014* ID_MODEL_FROM_DATABASE=82541ER Gigabit Ethernet Controller (PRO/1000 MT Desktop Connection) pci:v00008086d00001014sv00008086sd00001014* ID_MODEL_FROM_DATABASE=82541ER Gigabit Ethernet Controller (PRO/1000 MT Network Connection) pci:v00008086d00001015* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (LOM) pci:v00008086d00001015sv00008086sd00001015* ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (LOM) (PRO/1000 MT Mobile Connection) pci:v00008086d00001016* ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) pci:v00008086d00001016sv00001014sd0000052C* ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) (PRO/1000 MT Mobile Connection) pci:v00008086d00001016sv00001179sd00000001* ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) (PRO/1000 MT Mobile Connection) pci:v00008086d00001016sv00008086sd00001016* ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) (PRO/1000 MT Mobile Connection) pci:v00008086d00001017* ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller pci:v00008086d00001017sv00008086sd00001017* ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (PR0/1000 MT Desktop Connection) pci:v00008086d00001018* ID_MODEL_FROM_DATABASE=82541EI Gigabit Ethernet Controller pci:v00008086d00001018sv00008086sd00001018* ID_MODEL_FROM_DATABASE=82541EI Gigabit Ethernet Controller (PRO/1000 MT Mobile Connection) pci:v00008086d00001019* ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller pci:v00008086d00001019sv00001458sd00001019* ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (GA-8IPE1000 Pro2 motherboard (865PE)) pci:v00008086d00001019sv00001458sd0000E000* ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (Intel Gigabit Ethernet (Kenai II)) pci:v00008086d00001019sv00008086sd00001019* ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (PRO/1000 CT Desktop Connection) pci:v00008086d00001019sv00008086sd0000301F* ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (D865PERL mainboard) pci:v00008086d00001019sv00008086sd00003025* ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (D875PBZ motherboard) pci:v00008086d00001019sv00008086sd0000302C* ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (Intel 82865G Mainboard (D865GBF)) pci:v00008086d00001019sv00008086sd00003427* ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (S875WP1-E mainboard) pci:v00008086d0000101A* ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (Mobile) pci:v00008086d0000101Asv00008086sd0000101A* ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (Mobile) (PRO/1000 CT Mobile Connection) pci:v00008086d0000101D* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller pci:v00008086d0000101Dsv00008086sd00001000* ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (PRO/1000 MT Quad Port Server Adapter) pci:v00008086d0000101E* ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) pci:v00008086d0000101Esv00001014sd00000549* ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) (Thinkpad) pci:v00008086d0000101Esv00001179sd00000001* ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) (PRO/1000 MT Mobile Connection) pci:v00008086d0000101Esv00008086sd0000101E* ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) (PRO/1000 MT Mobile Connection) pci:v00008086d00001026* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller pci:v00008086d00001026sv00001028sd00000168* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (Precision Workstation 670 Mainboard) pci:v00008086d00001026sv00001028sd00000169* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (Precision 470) pci:v00008086d00001026sv00008086sd00001000* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MT Server Connection) pci:v00008086d00001026sv00008086sd00001001* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MT Server Adapter) pci:v00008086d00001026sv00008086sd00001002* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MT Server Adapter) pci:v00008086d00001026sv00008086sd00001003* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 GT Server Adapter) pci:v00008086d00001026sv00008086sd00001026* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MT Server Connection) pci:v00008086d00001027* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller pci:v00008086d00001027sv0000103Csd00003103* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (NC310F PCI-X Gigabit Server Adapter) pci:v00008086d00001027sv00008086sd00001001* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MF Server Adapter(LX)) pci:v00008086d00001027sv00008086sd00001002* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MF Server Adapter(LX)) pci:v00008086d00001027sv00008086sd00001003* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MF Server Adapter(LX)) pci:v00008086d00001027sv00008086sd00001027* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MF Server Adapter) pci:v00008086d00001028* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller pci:v00008086d00001028sv00008086sd00001028* ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MB Server Connection) pci:v00008086d00001029* ID_MODEL_FROM_DATABASE=82559 Ethernet Controller pci:v00008086d00001030* ID_MODEL_FROM_DATABASE=82559 InBusiness 10/100 pci:v00008086d00001031* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller pci:v00008086d00001031sv00001014sd00000209* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (ThinkPad A/T/X Series) pci:v00008086d00001031sv0000104Dsd000080E7* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (Vaio PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) pci:v00008086d00001031sv0000104Dsd0000813C* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (Vaio PCG-GRV616G) pci:v00008086d00001031sv0000107Bsd00005350* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00001031sv00001179sd00000001* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00001031sv0000144Dsd0000C000* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00001031sv0000144Dsd0000C001* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00001031sv0000144Dsd0000C003* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00001031sv0000144Dsd0000C006* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (vpr Matrix 170B4) pci:v00008086d00001032* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE Ethernet Controller pci:v00008086d00001033* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VM (LOM) Ethernet Controller pci:v00008086d00001034* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VM Ethernet Controller pci:v00008086d00001035* ID_MODEL_FROM_DATABASE=82801CAM (ICH3)/82562EH (LOM) Ethernet Controller pci:v00008086d00001036* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) 82562EH Ethernet Controller pci:v00008086d00001037* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) Chipset Ethernet Controller pci:v00008086d00001038* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VM (KM) Ethernet Controller pci:v00008086d00001038sv00000E11sd00000098* ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VM (KM) Ethernet Controller (Evo N600c) pci:v00008086d00001039* ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (LOM) Ethernet Controller pci:v00008086d00001039sv00001014sd00000267* ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (LOM) Ethernet Controller (NetVista A30p) pci:v00008086d00001039sv0000114Asd00000582* ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (LOM) Ethernet Controller (PC8 onboard ethernet ETH1) pci:v00008086d0000103A* ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (CNR) Ethernet Controller pci:v00008086d0000103B* ID_MODEL_FROM_DATABASE=82801DB PRO/100 VM (LOM) Ethernet Controller pci:v00008086d0000103C* ID_MODEL_FROM_DATABASE=82801DB PRO/100 VM (CNR) Ethernet Controller pci:v00008086d0000103D* ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (MOB) Ethernet Controller pci:v00008086d0000103Dsv00001014sd00000522* ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (MOB) Ethernet Controller (ThinkPad R40) pci:v00008086d0000103Dsv00001028sd00002002* ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (MOB) Ethernet Controller (Latitude D500) pci:v00008086d0000103Dsv00008086sd0000103D* ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (MOB) Ethernet Controller (82562EZ 10/100 Ethernet Controller) pci:v00008086d0000103E* ID_MODEL_FROM_DATABASE=82801DB PRO/100 VM (MOB) Ethernet Controller pci:v00008086d00001040* ID_MODEL_FROM_DATABASE=536EP Data Fax Modem pci:v00008086d00001040sv000016BEsd00001040* ID_MODEL_FROM_DATABASE=536EP Data Fax Modem (V.9X DSP Data Fax Modem) pci:v00008086d00001043* ID_MODEL_FROM_DATABASE=PRO/Wireless LAN 2100 3B Mini PCI Adapter pci:v00008086d00001043sv0000103Csd000008B0* ID_MODEL_FROM_DATABASE=PRO/Wireless LAN 2100 3B Mini PCI Adapter (tc1100 tablet) pci:v00008086d00001043sv00008086sd00002522* ID_MODEL_FROM_DATABASE=PRO/Wireless LAN 2100 3B Mini PCI Adapter (Samsung X10/P30 integrated WLAN) pci:v00008086d00001043sv00008086sd00002527* ID_MODEL_FROM_DATABASE=PRO/Wireless LAN 2100 3B Mini PCI Adapter (MIM2000/Centrino) pci:v00008086d00001043sv00008086sd00002561* ID_MODEL_FROM_DATABASE=PRO/Wireless LAN 2100 3B Mini PCI Adapter (Dell Latitude D800) pci:v00008086d00001043sv00008086sd00002581* ID_MODEL_FROM_DATABASE=PRO/Wireless LAN 2100 3B Mini PCI Adapter (Toshiba Satellite M10) pci:v00008086d00001048* ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller pci:v00008086d00001048sv00008086sd0000A01F* ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE LR Server Adapter) pci:v00008086d00001048sv00008086sd0000A11F* ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE LR Server Adapter) pci:v00008086d00001049* ID_MODEL_FROM_DATABASE=82566MM Gigabit Network Connection pci:v00008086d00001049sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82566MM Gigabit Network Connection (Compaq 6910p) pci:v00008086d00001049sv000017AAsd000020B9* ID_MODEL_FROM_DATABASE=82566MM Gigabit Network Connection (ThinkPad T61/R61) pci:v00008086d0000104A* ID_MODEL_FROM_DATABASE=82566DM Gigabit Network Connection pci:v00008086d0000104B* ID_MODEL_FROM_DATABASE=82566DC Gigabit Network Connection pci:v00008086d0000104C* ID_MODEL_FROM_DATABASE=82562V 10/100 Network Connection pci:v00008086d0000104D* ID_MODEL_FROM_DATABASE=82566MC Gigabit Network Connection pci:v00008086d00001050* ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller pci:v00008086d00001050sv00001028sd0000019D* ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller (Dimension 3000) pci:v00008086d00001050sv00001462sd0000728C* ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller (865PE Neo2 (MS-6728)) pci:v00008086d00001050sv00001462sd0000758C* ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller (MS-6758 (875P Neo)) pci:v00008086d00001050sv00008086sd00003020* ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller (D865PERL mainboard) pci:v00008086d00001050sv00008086sd0000302F* ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller (Desktop Board D865GBF) pci:v00008086d00001050sv00008086sd00003427* ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller (S875WP1-E mainboard) pci:v00008086d00001051* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) integrated LAN Controller pci:v00008086d00001052* ID_MODEL_FROM_DATABASE=PRO/100 VM Network Connection pci:v00008086d00001053* ID_MODEL_FROM_DATABASE=PRO/100 VM Network Connection pci:v00008086d00001054* ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection pci:v00008086d00001055* ID_MODEL_FROM_DATABASE=PRO/100 VM Network Connection pci:v00008086d00001056* ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection pci:v00008086d00001057* ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection pci:v00008086d00001059* ID_MODEL_FROM_DATABASE=82551QM Ethernet Controller pci:v00008086d0000105B* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) pci:v00008086d0000105E* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller pci:v00008086d0000105Esv0000103Csd00007044* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (NC360T PCI Express Dual Port Gigabit Server Adapter) pci:v00008086d0000105Esv0000103Csd0000704E* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Dual Port 1000Base-T (PCIe) [AD337A]) pci:v00008086d0000105Esv00001775sd00001100* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (CR11/VR11 Single Board Computer) pci:v00008086d0000105Esv00001775sd00006003* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Telum GE-QT) pci:v00008086d0000105Esv000018DFsd00001214* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (2x 1GbE, PCIe x1, dual Intel 82571EB chips) pci:v00008086d0000105Esv00008086sd0000005E* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Dual Port Server Connection) pci:v00008086d0000105Esv00008086sd0000105E* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Dual Port Network Connection) pci:v00008086d0000105Esv00008086sd000010D5* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (82571PT Gigabit PT Quad Port Server ExpressModule) pci:v00008086d0000105Esv00008086sd0000115E* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Dual Port Server Adapter) pci:v00008086d0000105Esv00008086sd0000125E* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Dual Port Server Adapter) pci:v00008086d0000105Esv00008086sd0000135E* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Dual Port Server Adapter) pci:v00008086d0000105F* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller pci:v00008086d0000105Fsv0000103Csd0000704F* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Dual Port 1000Base-SX (PCIe) [AD338A]) pci:v00008086d0000105Fsv00008086sd0000005A* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PF Dual Port Server Adapter) pci:v00008086d0000105Fsv00008086sd0000115F* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PF Dual Port Server Adapter) pci:v00008086d0000105Fsv00008086sd0000125F* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PF Dual Port Server Adapter) pci:v00008086d0000105Fsv00008086sd0000135F* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PF Dual Port Server Adapter) pci:v00008086d00001060* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller pci:v00008086d00001060sv00008086sd00000060* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PB Dual Port Server Connection) pci:v00008086d00001060sv00008086sd00001060* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PB Dual Port Server Connection) pci:v00008086d00001064* ID_MODEL_FROM_DATABASE=82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller pci:v00008086d00001064sv00001043sd000080F8* ID_MODEL_FROM_DATABASE=82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller (P5GD1-VW Mainboard) pci:v00008086d00001065* ID_MODEL_FROM_DATABASE=82562ET/EZ/GT/GZ - PRO/100 VE Ethernet Controller pci:v00008086d00001066* ID_MODEL_FROM_DATABASE=82562 EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller pci:v00008086d00001067* ID_MODEL_FROM_DATABASE=82562 EM/EX/GX - PRO/100 VM Ethernet Controller pci:v00008086d00001068* ID_MODEL_FROM_DATABASE=82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller Mobile pci:v00008086d00001069* ID_MODEL_FROM_DATABASE=82562EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller Mobile pci:v00008086d0000106A* ID_MODEL_FROM_DATABASE=82562G - PRO/100 VE (LOM) Ethernet Controller pci:v00008086d0000106B* ID_MODEL_FROM_DATABASE=82562G - PRO/100 VE Ethernet Controller Mobile pci:v00008086d00001075* ID_MODEL_FROM_DATABASE=82547GI Gigabit Ethernet Controller pci:v00008086d00001075sv00001028sd00000165* ID_MODEL_FROM_DATABASE=82547GI Gigabit Ethernet Controller (PowerEdge 750) pci:v00008086d00001075sv00008086sd00000075* ID_MODEL_FROM_DATABASE=82547GI Gigabit Ethernet Controller (PRO/1000 CT Network Connection) pci:v00008086d00001075sv00008086sd00001075* ID_MODEL_FROM_DATABASE=82547GI Gigabit Ethernet Controller (PRO/1000 CT Network Connection) pci:v00008086d00001076* ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller pci:v00008086d00001076sv00001028sd00000165* ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) pci:v00008086d00001076sv00001028sd0000016D* ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) pci:v00008086d00001076sv00001028sd0000019A* ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) pci:v00008086d00001076sv00001028sd0000106D* ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) pci:v00008086d00001076sv00008086sd00000076* ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) pci:v00008086d00001076sv00008086sd00001076* ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) pci:v00008086d00001076sv00008086sd00001176* ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Desktop Adapter) pci:v00008086d00001076sv00008086sd00001276* ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Adapter) pci:v00008086d00001077* ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller pci:v00008086d00001077sv00001179sd00000001* ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Mobile Connection) pci:v00008086d00001077sv00008086sd00000077* ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Mobile Connection) pci:v00008086d00001077sv00008086sd00001077* ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Mobile Connection) pci:v00008086d00001078* ID_MODEL_FROM_DATABASE=82541ER Gigabit Ethernet Controller pci:v00008086d00001078sv00008086sd00001078* ID_MODEL_FROM_DATABASE=82541ER Gigabit Ethernet Controller (82541ER-based Network Connection) pci:v00008086d00001079* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller pci:v00008086d00001079sv0000103Csd000012A6* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Dual Port 1000Base-T [A9900A]) pci:v00008086d00001079sv0000103Csd000012CF* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Core Dual Port 1000Base-T [AB352A]) pci:v00008086d00001079sv00001775sd000010D0* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (V5D Single Board Computer Gigabit Ethernet) pci:v00008086d00001079sv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (CE9) pci:v00008086d00001079sv00001FC1sd00000027* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Niagara 2261 Failover NIC) pci:v00008086d00001079sv00004C53sd00001090* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Cx9 / Vx9 mainboard) pci:v00008086d00001079sv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (CL9 mainboard) pci:v00008086d00001079sv00008086sd00000079* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MT Dual Port Network Connection) pci:v00008086d00001079sv00008086sd00001079* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MT Dual Port Network Connection) pci:v00008086d00001079sv00008086sd00001179* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MT Dual Port Server Adapter) pci:v00008086d00001079sv00008086sd0000117A* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MT Dual Port Server Adapter) pci:v00008086d0000107A* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller pci:v00008086d0000107Asv0000103Csd000012A8* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Dual Port 1000base-SX [A9899A]) pci:v00008086d0000107Asv00008086sd0000107A* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MF Dual Port Server Adapter) pci:v00008086d0000107Asv00008086sd0000127A* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MF Dual Port Server Adapter) pci:v00008086d0000107B* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller pci:v00008086d0000107Bsv00008086sd0000007B* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MB Dual Port Server Connection) pci:v00008086d0000107Bsv00008086sd0000107B* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MB Dual Port Server Connection) pci:v00008086d0000107C* ID_MODEL_FROM_DATABASE=82541PI Gigabit Ethernet Controller pci:v00008086d0000107Csv00008086sd00001376* ID_MODEL_FROM_DATABASE=82541PI Gigabit Ethernet Controller (PRO/1000 GT Desktop Adapter) pci:v00008086d0000107Csv00008086sd00001476* ID_MODEL_FROM_DATABASE=82541PI Gigabit Ethernet Controller (PRO/1000 GT Desktop Adapter) pci:v00008086d0000107D* ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) pci:v00008086d0000107Dsv00008086sd00001082* ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) (PRO/1000 PT Server Adapter) pci:v00008086d0000107Dsv00008086sd00001084* ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) (PRO/1000 PT Server Adapter) pci:v00008086d0000107Dsv00008086sd00001092* ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) (PRO/1000 PT Server Adapter) pci:v00008086d0000107E* ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Fiber) pci:v00008086d0000107Esv00008086sd00001084* ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Fiber) (PRO/1000 PF Server Adapter) pci:v00008086d0000107Esv00008086sd00001085* ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Fiber) (PRO/1000 PF Server Adapter) pci:v00008086d0000107Esv00008086sd00001094* ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Fiber) (PRO/1000 PF Server Adapter) pci:v00008086d0000107F* ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller pci:v00008086d00001080* ID_MODEL_FROM_DATABASE=FA82537EP 56K V.92 Data/Fax Modem PCI pci:v00008086d00001081* ID_MODEL_FROM_DATABASE=631xESB/632xESB LAN Controller Copper pci:v00008086d00001082* ID_MODEL_FROM_DATABASE=631xESB/632xESB LAN Controller fiber pci:v00008086d00001083* ID_MODEL_FROM_DATABASE=631xESB/632xESB LAN Controller SERDES pci:v00008086d00001084* ID_MODEL_FROM_DATABASE=631xESB/632xESB IDE Redirection pci:v00008086d00001085* ID_MODEL_FROM_DATABASE=631xESB/632xESB Serial Port Redirection pci:v00008086d00001086* ID_MODEL_FROM_DATABASE=631xESB/632xESB IPMI/KCS0 pci:v00008086d00001087* ID_MODEL_FROM_DATABASE=631xESB/632xESB UHCI Redirection pci:v00008086d00001089* ID_MODEL_FROM_DATABASE=631xESB/632xESB BT pci:v00008086d0000108A* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller pci:v00008086d0000108Asv00008086sd0000108A* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 P Dual Port Server Adapter) pci:v00008086d0000108Asv00008086sd0000118A* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 P Dual Port Server Adapter) pci:v00008086d0000108B* ID_MODEL_FROM_DATABASE=82573V Gigabit Ethernet Controller (Copper) pci:v00008086d0000108Bsv00001462sd0000176C* ID_MODEL_FROM_DATABASE=82573V Gigabit Ethernet Controller (Copper) (on board on MSI 945P - NEO (MS-7176)) pci:v00008086d0000108C* ID_MODEL_FROM_DATABASE=82573E Gigabit Ethernet Controller (Copper) pci:v00008086d0000108E* ID_MODEL_FROM_DATABASE=82573E KCS (Active Management) pci:v00008086d0000108F* ID_MODEL_FROM_DATABASE=Active Management Technology - SOL pci:v00008086d00001091* ID_MODEL_FROM_DATABASE=PRO/100 VM Network Connection pci:v00008086d00001092* ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection pci:v00008086d00001092sv00001071sd00008209* ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d00001093* ID_MODEL_FROM_DATABASE=PRO/100 VM Network Connection pci:v00008086d00001094* ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection pci:v00008086d00001095* ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection pci:v00008086d00001096* ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Copper) pci:v00008086d00001096sv000015D9sd00001096* ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Copper) (Motherboard) pci:v00008086d00001096sv000015D9sd00008680* ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Copper) (X7DVL-E-O motherboard) pci:v00008086d00001096sv00008086sd00003476* ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Copper) (Intel S5000PSLSATA Server Board) pci:v00008086d00001097* ID_MODEL_FROM_DATABASE=631xESB/632xESB DPT LAN Controller (Fiber) pci:v00008086d00001098* ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Serdes) pci:v00008086d00001099* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) pci:v00008086d00001099sv00008086sd00001099* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) (PRO/1000 GT Quad Port Server Adapter) pci:v00008086d0000109A* ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller pci:v00008086d0000109Asv00001179sd0000FF10* ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller (PRO/1000 PL) pci:v00008086d0000109Asv000017AAsd00002001* ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller (ThinkPad T60) pci:v00008086d0000109Asv000017AAsd0000207E* ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller (ThinkPad X60/X60s) pci:v00008086d0000109Asv00008086sd0000109A* ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller (PRO/1000 PL Network Connection) pci:v00008086d0000109Asv00008086sd0000309C* ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller (Desktop Board D945GTP) pci:v00008086d0000109Asv00008086sd000030A5* ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller (Desktop Board D975XBX) pci:v00008086d0000109B* ID_MODEL_FROM_DATABASE=82546GB PRO/1000 GF Quad Port Server Adapter pci:v00008086d0000109E* ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller pci:v00008086d0000109Esv00008086sd0000A01F* ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE CX4 Server Adapter) pci:v00008086d0000109Esv00008086sd0000A11F* ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE CX4 Server Adapter) pci:v00008086d000010A0* ID_MODEL_FROM_DATABASE=82571EB PRO/1000 AT Quad Port Bypass Adapter pci:v00008086d000010A1* ID_MODEL_FROM_DATABASE=82571EB PRO/1000 AF Quad Port Bypass Adapter pci:v00008086d000010A4* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller pci:v00008086d000010A4sv00008086sd000010A4* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Quad Port Server Adapter) pci:v00008086d000010A4sv00008086sd000011A4* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Quad Port Server Adapter) pci:v00008086d000010A5* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Fiber) pci:v00008086d000010A5sv00008086sd000010A5* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Fiber) (PRO/1000 PF Quad Port Server Adapter) pci:v00008086d000010A5sv00008086sd000010A6* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Fiber) (PRO/1000 PF Quad Port Server Adapter) pci:v00008086d000010A6* ID_MODEL_FROM_DATABASE=82599EB 10-Gigabit Dummy Function pci:v00008086d000010A7* ID_MODEL_FROM_DATABASE=82575EB Gigabit Network Connection pci:v00008086d000010A7sv00008086sd000010A8* ID_MODEL_FROM_DATABASE=82575EB Gigabit Network Connection (82575EB Gigabit Riser Card) pci:v00008086d000010A9* ID_MODEL_FROM_DATABASE=82575EB Gigabit Backplane Connection pci:v00008086d000010B0* ID_MODEL_FROM_DATABASE=82573L PRO/1000 PL Network Connection pci:v00008086d000010B2* ID_MODEL_FROM_DATABASE=82573V PRO/1000 PM Network Connection pci:v00008086d000010B3* ID_MODEL_FROM_DATABASE=82573E PRO/1000 PM Network Connection pci:v00008086d000010B4* ID_MODEL_FROM_DATABASE=82573L PRO/1000 PL Network Connection pci:v00008086d000010B5* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) pci:v00008086d000010B5sv0000103Csd00003109* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) (NC340T PCI-X Quad-port Gigabit Server Adapter) pci:v00008086d000010B5sv00008086sd00001099* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) (PRO/1000 GT Quad Port Server Adapter) pci:v00008086d000010B5sv00008086sd00001199* ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) (PRO/1000 GT Quad Port Server Adapter) pci:v00008086d000010B6* ID_MODEL_FROM_DATABASE=82598 10GbE PCI-Express Ethernet Controller pci:v00008086d000010B9* ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) pci:v00008086d000010B9sv0000103Csd0000704A* ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) (110T PCIe Gigabit Server Adapter) pci:v00008086d000010B9sv00008086sd00001083* ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) (PRO/1000 PT Desktop Adapter) pci:v00008086d000010B9sv00008086sd00001093* ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) (PRO/1000 PT Desktop Adapter) pci:v00008086d000010BA* ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Copper) pci:v00008086d000010BB* ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Serdes) pci:v00008086d000010BC* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper) pci:v00008086d000010BCsv0000103Csd0000704B* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper) (NC364T PCI Express Quad Port Gigabit Server Adapter) pci:v00008086d000010BCsv0000108Esd000011BC* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper) (x4 PCI-Express Quad Gigabit Ethernet UTP Low Profile Adapter) pci:v00008086d000010BCsv00008086sd000010BC* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper) (PRO/1000 PT Quad Port LP Server Adapter) pci:v00008086d000010BCsv00008086sd000011BC* ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper) (PRO/1000 PT Quad Port LP Server Adapter) pci:v00008086d000010BD* ID_MODEL_FROM_DATABASE=82566DM-2 Gigabit Network Connection pci:v00008086d000010BDsv00001028sd00000211* ID_MODEL_FROM_DATABASE=82566DM-2 Gigabit Network Connection (OptiPlex 755) pci:v00008086d000010BF* ID_MODEL_FROM_DATABASE=82567LF Gigabit Network Connection pci:v00008086d000010C0* ID_MODEL_FROM_DATABASE=82562V-2 10/100 Network Connection pci:v00008086d000010C0sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82562V-2 10/100 Network Connection (Inspiron 530) pci:v00008086d000010C2* ID_MODEL_FROM_DATABASE=82562G-2 10/100 Network Connection pci:v00008086d000010C3* ID_MODEL_FROM_DATABASE=82562GT-2 10/100 Network Connection pci:v00008086d000010C4* ID_MODEL_FROM_DATABASE=82562GT 10/100 Network Connection pci:v00008086d000010C5* ID_MODEL_FROM_DATABASE=82562G 10/100 Network Connection pci:v00008086d000010C6* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection pci:v00008086d000010C6sv00008086sd0000A05F* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection (10-Gigabit XF SR Dual Port Server Adapter) pci:v00008086d000010C6sv00008086sd0000A15F* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection (10-Gigabit XF SR Dual Port Server Adapter) pci:v00008086d000010C7* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection pci:v00008086d000010C7sv00001014sd0000037F* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF SR Server Adapter) pci:v00008086d000010C7sv00001014sd00000380* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF LR Server Adapter) pci:v00008086d000010C7sv00008086sd0000A05F* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF SR Server Adapter) pci:v00008086d000010C7sv00008086sd0000A15F* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF SR Server Adapter) pci:v00008086d000010C7sv00008086sd0000A16F* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF SR Server Adapter) pci:v00008086d000010C8* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT Network Connection pci:v00008086d000010C8sv00008086sd0000A10C* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT Network Connection (10-Gigabit AT Server Adapter) pci:v00008086d000010C8sv00008086sd0000A11C* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT Network Connection (10-Gigabit AT Server Adapter) pci:v00008086d000010C8sv00008086sd0000A12C* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT Network Connection (10-Gigabit AT Server Adapter) pci:v00008086d000010C9* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection pci:v00008086d000010C9sv0000103Csd000031EF* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (NC362i Integrated Dual port Gigabit Server Adapter) pci:v00008086d000010C9sv0000103Csd0000323F* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (NC362i Integrated Dual port Gigabit Server Adapter) pci:v00008086d000010C9sv000010A9sd00008028* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (UV-BaseIO dual-port GbE) pci:v00008086d000010C9sv000013A3sd00000037* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (DS4100 Secure Multi-Gigabit Server Adapter with Compression) pci:v00008086d000010C9sv000015D9sd0000A811* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (H8DGU) pci:v00008086d000010C9sv00008086sd0000A01C* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET Dual Port Server Adapter) pci:v00008086d000010C9sv00008086sd0000A03C* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET Dual Port Server Adapter) pci:v00008086d000010C9sv00008086sd0000A04C* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET Dual Port Server Adapter) pci:v00008086d000010CA* ID_MODEL_FROM_DATABASE=82576 Virtual Function pci:v00008086d000010CB* ID_MODEL_FROM_DATABASE=82567V Gigabit Network Connection pci:v00008086d000010CC* ID_MODEL_FROM_DATABASE=82567LM-2 Gigabit Network Connection pci:v00008086d000010CD* ID_MODEL_FROM_DATABASE=82567LF-2 Gigabit Network Connection pci:v00008086d000010CE* ID_MODEL_FROM_DATABASE=82567V-2 Gigabit Network Connection pci:v00008086d000010D3* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection pci:v00008086d000010D3sv0000103Csd00001785* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (NC112i 1-port Ethernet Server Adapter) pci:v00008086d000010D3sv0000103Csd00003250* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (NC112T PCI Express single Port Gigabit Server Adapter) pci:v00008086d000010D3sv00001043sd00008369* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (Motherboard) pci:v00008086d000010D3sv00001093sd000076E9* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (PCIe-8233 Ethernet Adapter) pci:v00008086d000010D3sv000010A9sd00008029* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (Prism XL Single Port Gigabit Ethernet) pci:v00008086d000010D3sv000015D9sd0000060A* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (X7SPA-H/X7SPA-HF Motherboard) pci:v00008086d000010D3sv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (C7SIM-Q Motherboard) pci:v00008086d000010D3sv00008086sd00000001* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (Gigabit CT2 Desktop Adapter) pci:v00008086d000010D3sv00008086sd0000357A* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (Server Board S1200BTS) pci:v00008086d000010D3sv00008086sd0000A01F* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (Gigabit CT Desktop Adapter) pci:v00008086d000010D3sv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (PC1-GROOVE) pci:v00008086d000010D3sv0000E4BFsd000050C2* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (PC2-LIMBO) pci:v00008086d000010D4* ID_MODEL_FROM_DATABASE=Matrox Concord GE (customized Intel 82574) pci:v00008086d000010D5* ID_MODEL_FROM_DATABASE=82571PT Gigabit PT Quad Port Server ExpressModule pci:v00008086d000010D6* ID_MODEL_FROM_DATABASE=82575GB Gigabit Network Connection pci:v00008086d000010D6sv00008086sd000010D6* ID_MODEL_FROM_DATABASE=82575GB Gigabit Network Connection (Gigabit VT Quad Port Server Adapter) pci:v00008086d000010D6sv00008086sd0000145A* ID_MODEL_FROM_DATABASE=82575GB Gigabit Network Connection (Gigabit VT Quad Port Server Adapter) pci:v00008086d000010D6sv00008086sd0000147A* ID_MODEL_FROM_DATABASE=82575GB Gigabit Network Connection (Gigabit VT Quad Port Server Adapter) pci:v00008086d000010D8* ID_MODEL_FROM_DATABASE=82599EB 10 Gigabit Unprogrammed pci:v00008086d000010D9* ID_MODEL_FROM_DATABASE=82571EB Dual Port Gigabit Mezzanine Adapter pci:v00008086d000010D9sv0000103Csd00001716* ID_MODEL_FROM_DATABASE=82571EB Dual Port Gigabit Mezzanine Adapter (NC360m Dual Port 1GbE BL-c Adapter) pci:v00008086d000010DA* ID_MODEL_FROM_DATABASE=82571EB Quad Port Gigabit Mezzanine Adapter pci:v00008086d000010DAsv0000103Csd00001717* ID_MODEL_FROM_DATABASE=82571EB Quad Port Gigabit Mezzanine Adapter (NC364m Quad Port 1GbE BL-c Adapter) pci:v00008086d000010DB* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit Dual Port Network Connection pci:v00008086d000010DD* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT CX4 Network Connection pci:v00008086d000010DE* ID_MODEL_FROM_DATABASE=82567LM-3 Gigabit Network Connection pci:v00008086d000010DF* ID_MODEL_FROM_DATABASE=82567LF-3 Gigabit Network Connection pci:v00008086d000010E1* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection pci:v00008086d000010E1sv00008086sd0000A15F* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection (10-Gigabit SR Dual Port Express Module) pci:v00008086d000010E2* ID_MODEL_FROM_DATABASE=82575GB Gigabit Network Connection pci:v00008086d000010E2sv00008086sd000010E2* ID_MODEL_FROM_DATABASE=82575GB Gigabit Network Connection (Gigabit VT Quad Port Server Adapter) pci:v00008086d000010E5* ID_MODEL_FROM_DATABASE=82567LM-4 Gigabit Network Connection pci:v00008086d000010E6* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection pci:v00008086d000010E6sv00008086sd0000A01F* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit EF Dual Port Server Adapter) pci:v00008086d000010E6sv00008086sd0000A02F* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit EF Dual Port Server Adapter) pci:v00008086d000010E7* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection pci:v00008086d000010E7sv0000103Csd000031FF* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (NC362i Integrated Dual Port BL-c Gigabit Server Adapter) pci:v00008086d000010E8* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection pci:v00008086d000010E8sv00008086sd0000A02B* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET Quad Port Server Adapter) pci:v00008086d000010E8sv00008086sd0000A02C* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET Quad Port Server Adapter) pci:v00008086d000010EA* ID_MODEL_FROM_DATABASE=82577LM Gigabit Network Connection pci:v00008086d000010EAsv00001028sd0000040A* ID_MODEL_FROM_DATABASE=82577LM Gigabit Network Connection (Latitude E6410) pci:v00008086d000010EAsv00001028sd0000040B* ID_MODEL_FROM_DATABASE=82577LM Gigabit Network Connection (Latitude E6510) pci:v00008086d000010EAsv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=82577LM Gigabit Network Connection (PC1-GROOVE) pci:v00008086d000010EB* ID_MODEL_FROM_DATABASE=82577LC Gigabit Network Connection pci:v00008086d000010EC* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT CX4 Network Connection pci:v00008086d000010ECsv00008086sd0000A01F* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT CX4 Network Connection (10-Gigabit CX4 Dual Port Server Adapter) pci:v00008086d000010ECsv00008086sd0000A11F* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT CX4 Network Connection (10-Gigabit CX4 Dual Port Server Adapter) pci:v00008086d000010ED* ID_MODEL_FROM_DATABASE=82599 Ethernet Controller Virtual Function pci:v00008086d000010EF* ID_MODEL_FROM_DATABASE=82578DM Gigabit Network Connection pci:v00008086d000010EFsv00001028sd000002DA* ID_MODEL_FROM_DATABASE=82578DM Gigabit Network Connection (OptiPlex 980) pci:v00008086d000010EFsv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=82578DM Gigabit Network Connection (C7SIM-Q Motherboard) pci:v00008086d000010F0* ID_MODEL_FROM_DATABASE=82578DC Gigabit Network Connection pci:v00008086d000010F1* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection pci:v00008086d000010F1sv00008086sd0000A20F* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection (10-Gigabit AF DA Dual Port Server Adapter) pci:v00008086d000010F1sv00008086sd0000A21F* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection (10-Gigabit AF DA Dual Port Server Adapter) pci:v00008086d000010F4* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection pci:v00008086d000010F4sv00008086sd0000106F* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF LR Server Adapter) pci:v00008086d000010F4sv00008086sd0000A06F* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF LR Server Adapter) pci:v00008086d000010F5* ID_MODEL_FROM_DATABASE=82567LM Gigabit Network Connection pci:v00008086d000010F6* ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection pci:v00008086d000010F7* ID_MODEL_FROM_DATABASE=10 Gigabit BR KX4 Dual Port Network Connection pci:v00008086d000010F7sv0000108Esd00007B12* ID_MODEL_FROM_DATABASE=10 Gigabit BR KX4 Dual Port Network Connection (Sun Dual 10GbE PCIe 2.0 FEM) pci:v00008086d000010F7sv00008086sd0000000D* ID_MODEL_FROM_DATABASE=10 Gigabit BR KX4 Dual Port Network Connection (Ethernet Mezzanine Adapter X520-KX4-2) pci:v00008086d000010F8* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection pci:v00008086d000010F8sv00001028sd00001F63* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection (10GbE 2P X520k bNDC) pci:v00008086d000010F8sv0000103Csd000017D2* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection (Ethernet 10Gb 2-port 560M Adapter) pci:v00008086d000010F8sv0000103Csd000018D0* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection (Ethernet 10Gb 2-port 560FLB Adapter) pci:v00008086d000010F8sv00001059sd00000111* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection (T4007 10GbE interface) pci:v00008086d000010F8sv00008086sd0000000C* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection (Ethernet X520 10GbE Dual Port KX4-KR Mezz) pci:v00008086d000010F9* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Network Connection pci:v00008086d000010FB* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection pci:v00008086d000010FBsv00001028sd00001F72* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10G 4P X520/I350 rNDC) pci:v00008086d000010FBsv0000103Csd000017D0* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10Gb 2-port 560FLR-SFP+ Adapter) pci:v00008086d000010FBsv0000103Csd000017D2* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10Gb 2-port 560M Adapter) pci:v00008086d000010FBsv0000103Csd000017D3* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10Gb 2-port 560SFP+ Adapter) pci:v00008086d000010FBsv0000103Csd0000211B* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10Gb 1-port P560FLR-SFP+ Adapter) pci:v00008086d000010FBsv0000103Csd00002147* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10Gb 1-port 561i Adapter) pci:v00008086d000010FBsv0000103Csd00002159* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10Gb 2-port 562i Adapter) pci:v00008086d000010FBsv0000108Esd00007B11* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-2) pci:v00008086d000010FBsv00001734sd000011A9* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (10 Gigabit Dual Port Network Connection) pci:v00008086d000010FBsv000017AAsd00001071* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (ThinkServer X520-2 AnyFabric) pci:v00008086d000010FBsv000017AAsd00004007* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection pci:v00008086d000010FBsv00008086sd00000002* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-DA2) pci:v00008086d000010FBsv00008086sd00000003* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-2) pci:v00008086d000010FBsv00008086sd00000006* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-1) pci:v00008086d000010FBsv00008086sd00000008* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet OCP Server Adapter X520-2) pci:v00008086d000010FBsv00008086sd0000000A* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-1) pci:v00008086d000010FBsv00008086sd0000000C* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-2) pci:v00008086d000010FBsv00008086sd00007A11* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-2) pci:v00008086d000010FBsv00008086sd00007A12* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-2) pci:v00008086d000010FC* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Network Connection pci:v00008086d000010FE* ID_MODEL_FROM_DATABASE=82552 10/100 Network Connection pci:v00008086d00001107* ID_MODEL_FROM_DATABASE=PRO/1000 MF Server Adapter (LX) pci:v00008086d00001130* ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub pci:v00008086d00001130sv00001025sd00001016* ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (Travelmate 612 TX) pci:v00008086d00001130sv00001043sd00008027* ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (TUSL2-C Mainboard) pci:v00008086d00001130sv0000104Dsd000080DF* ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (Vaio PCG-FX403) pci:v00008086d00001130sv00008086sd00004532* ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (Desktop Board D815EEA2/D815EFV) pci:v00008086d00001130sv00008086sd00004557* ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (D815EGEW Mainboard) pci:v00008086d00001131* ID_MODEL_FROM_DATABASE=82815 815 Chipset AGP Bridge pci:v00008086d00001132* ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) pci:v00008086d00001132sv00001025sd00001016* ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (Travelmate 612 TX) pci:v00008086d00001132sv0000103Csd00002001* ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (e-pc 40) pci:v00008086d00001132sv0000104Dsd000080DF* ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (Vaio PCG-FX403) pci:v00008086d00001132sv00008086sd00004532* ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (Desktop Board D815EEA2/D815EFV) pci:v00008086d00001132sv00008086sd00004541* ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (D815EEA Motherboard) pci:v00008086d00001132sv00008086sd00004557* ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (D815EGEW Mainboard) pci:v00008086d00001161* ID_MODEL_FROM_DATABASE=82806AA PCI64 Hub Advanced Programmable Interrupt Controller pci:v00008086d00001161sv00008086sd00001161* ID_MODEL_FROM_DATABASE=82806AA PCI64 Hub Advanced Programmable Interrupt Controller (82806AA PCI64 Hub APIC) pci:v00008086d00001162* ID_MODEL_FROM_DATABASE=Xscale 80200 Big Endian Companion Chip pci:v00008086d00001200* ID_MODEL_FROM_DATABASE=IXP1200 Network Processor pci:v00008086d00001200sv0000172Asd00000000* ID_MODEL_FROM_DATABASE=IXP1200 Network Processor (AEP SSL Accelerator) pci:v00008086d00001209* ID_MODEL_FROM_DATABASE=8255xER/82551IT Fast Ethernet Controller pci:v00008086d00001209sv0000140Bsd00000610* ID_MODEL_FROM_DATABASE=8255xER/82551IT Fast Ethernet Controller (PMC610 quad Ethernet board) pci:v00008086d00001209sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=8255xER/82551IT Fast Ethernet Controller (QEMU Virtual Machine) pci:v00008086d00001209sv00004C53sd00001050* ID_MODEL_FROM_DATABASE=8255xER/82551IT Fast Ethernet Controller (CT7 mainboard) pci:v00008086d00001209sv00004C53sd00001051* ID_MODEL_FROM_DATABASE=8255xER/82551IT Fast Ethernet Controller (CE7 mainboard) pci:v00008086d00001209sv00004C53sd00001070* ID_MODEL_FROM_DATABASE=8255xER/82551IT Fast Ethernet Controller (PC6 mainboard) pci:v00008086d00001221* ID_MODEL_FROM_DATABASE=82092AA PCI to PCMCIA Bridge pci:v00008086d00001222* ID_MODEL_FROM_DATABASE=82092AA IDE Controller pci:v00008086d00001223* ID_MODEL_FROM_DATABASE=SAA7116 pci:v00008086d00001225* ID_MODEL_FROM_DATABASE=82452KX/GX [Orion] pci:v00008086d00001226* ID_MODEL_FROM_DATABASE=82596 PRO/10 PCI pci:v00008086d00001227* ID_MODEL_FROM_DATABASE=82865 EtherExpress PRO/100A pci:v00008086d00001228* ID_MODEL_FROM_DATABASE=82556 EtherExpress PRO/100 Smart pci:v00008086d00001229* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 pci:v00008086d00001229sv00000E11sd00003001* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) pci:v00008086d00001229sv00000E11sd00003002* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) pci:v00008086d00001229sv00000E11sd00003003* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) pci:v00008086d00001229sv00000E11sd00003004* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) pci:v00008086d00001229sv00000E11sd00003005* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) pci:v00008086d00001229sv00000E11sd00003006* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) pci:v00008086d00001229sv00000E11sd00003007* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) pci:v00008086d00001229sv00000E11sd0000B01E* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3120 Fast Ethernet NIC) pci:v00008086d00001229sv00000E11sd0000B01F* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3122 Fast Ethernet NIC (dual port)) pci:v00008086d00001229sv00000E11sd0000B02F* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC1120 Ethernet NIC) pci:v00008086d00001229sv00000E11sd0000B04A* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (Netelligent 10/100TX NIC with Wake on LAN) pci:v00008086d00001229sv00000E11sd0000B0C6* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3161 Fast Ethernet NIC (embedded, WOL)) pci:v00008086d00001229sv00000E11sd0000B0C7* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3160 Fast Ethernet NIC (embedded)) pci:v00008086d00001229sv00000E11sd0000B0D7* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3121 Fast Ethernet NIC (WOL)) pci:v00008086d00001229sv00000E11sd0000B0DD* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3131 Fast Ethernet NIC (dual port)) pci:v00008086d00001229sv00000E11sd0000B0DE* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3132 Fast Ethernet Module (dual port)) pci:v00008086d00001229sv00000E11sd0000B0E1* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3133 Fast Ethernet Module (100-FX)) pci:v00008086d00001229sv00000E11sd0000B134* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3163 Fast Ethernet NIC (embedded, WOL)) pci:v00008086d00001229sv00000E11sd0000B13C* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3162 Fast Ethernet NIC (embedded)) pci:v00008086d00001229sv00000E11sd0000B144* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3123 Fast Ethernet NIC (WOL)) pci:v00008086d00001229sv00000E11sd0000B163* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3134 Fast Ethernet NIC (dual port)) pci:v00008086d00001229sv00000E11sd0000B164* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3135 Fast Ethernet Upgrade Module (dual port)) pci:v00008086d00001229sv00000E11sd0000B1A4* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC7131 Gigabit Server Adapter) pci:v00008086d00001229sv00001014sd0000005C* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82558B Ethernet Pro 10/100) pci:v00008086d00001229sv00001014sd000001BC* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LAN On Motherboard) pci:v00008086d00001229sv00001014sd000001F1* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Ethernet Server Adapter) pci:v00008086d00001229sv00001014sd000001F2* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Ethernet Server Adapter) pci:v00008086d00001229sv00001014sd00000207* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (Ethernet Pro/100 S) pci:v00008086d00001229sv00001014sd00000232* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Dual Port Server Adapter) pci:v00008086d00001229sv00001014sd0000023A* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (ThinkPad R30) pci:v00008086d00001229sv00001014sd0000105C* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (Netfinity 10/100) pci:v00008086d00001229sv00001014sd00002205* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (ThinkPad A22p) pci:v00008086d00001229sv00001014sd0000305C* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 EtherJet Management Adapter) pci:v00008086d00001229sv00001014sd0000405C* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 EtherJet Adapter with Alert on LAN) pci:v00008086d00001229sv00001014sd0000505C* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 EtherJet Secure Management Adapter) pci:v00008086d00001229sv00001014sd0000605C* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 EtherJet Secure Management Adapter) pci:v00008086d00001229sv00001014sd0000705C* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Netfinity 10/100 Ethernet Security Adapter) pci:v00008086d00001229sv00001014sd0000805C* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Netfinity 10/100 Ethernet Security Adapter) pci:v00008086d00001229sv00001028sd0000009B* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Ethernet Server Adapter) pci:v00008086d00001229sv00001028sd000000CE* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Ethernet Server Adapter) pci:v00008086d00001229sv00001033sd00008000* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PC-9821X-B06) pci:v00008086d00001229sv00001033sd00008016* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PK-UG-X006) pci:v00008086d00001229sv00001033sd0000801F* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PK-UG-X006) pci:v00008086d00001229sv00001033sd00008026* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PK-UG-X006) pci:v00008086d00001229sv00001033sd00008063* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559-based Fast Ethernet Adapter) pci:v00008086d00001229sv00001033sd00008064* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559-based Fast Ethernet Adapter) pci:v00008086d00001229sv0000103Csd000010C0* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) pci:v00008086d00001229sv0000103Csd000010C3* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) pci:v00008086d00001229sv0000103Csd000010CA* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) pci:v00008086d00001229sv0000103Csd000010CB* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) pci:v00008086d00001229sv0000103Csd000010E3* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) pci:v00008086d00001229sv0000103Csd000010E4* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) pci:v00008086d00001229sv0000103Csd00001200* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) pci:v00008086d00001229sv0000108Esd000010CF* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100(B)) pci:v00008086d00001229sv000010C3sd00001100* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (SmartEther100 SC1100) pci:v00008086d00001229sv000010CFsd00001115* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (8255x-based Ethernet Adapter (10/100)) pci:v00008086d00001229sv000010CFsd00001143* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (8255x-based Ethernet Adapter (10/100)) pci:v00008086d00001229sv0000110Asd0000008B* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82551QM Fast Ethernet Multifuction PCI/CardBus Controller) pci:v00008086d00001229sv0000114Asd00000582* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PC8 onboard ethernet ETH2) pci:v00008086d00001229sv00001179sd00000001* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (8255x-based Ethernet Adapter (10/100)) pci:v00008086d00001229sv00001179sd00000002* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PCI FastEther LAN on Docker) pci:v00008086d00001229sv00001179sd00000003* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (8255x-based Fast Ethernet) pci:v00008086d00001229sv00001259sd00002560* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (AT-2560 100) pci:v00008086d00001229sv00001259sd00002561* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (AT-2560 100 FX Ethernet Adapter) pci:v00008086d00001229sv00001266sd00000001* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NE10/100 Adapter) pci:v00008086d00001229sv000013E9sd00001000* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (6221L-4U) pci:v00008086d00001229sv0000144Dsd00002501* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (SEM-2000 MiniPCI LAN Adapter) pci:v00008086d00001229sv0000144Dsd00002502* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (SEM-2100IL MiniPCI LAN Adapter) pci:v00008086d00001229sv00001668sd00001100* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100B (TX) (MiniPCI Ethernet+Modem)) pci:v00008086d00001229sv00001775sd00001100* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (CR11/VR11 Single Board Computer) pci:v00008086d00001229sv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (CE9) pci:v00008086d00001229sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (QEMU Virtual Machine) pci:v00008086d00001229sv00004C53sd00001080* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (CT8 mainboard) pci:v00008086d00001229sv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PSL09 PrPMC) pci:v00008086d00001229sv00008086sd00000001* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100B (TX)) pci:v00008086d00001229sv00008086sd00000002* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100B (T4)) pci:v00008086d00001229sv00008086sd00000003* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/10+) pci:v00008086d00001229sv00008086sd00000004* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 WfM) pci:v00008086d00001229sv00008086sd00000005* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82557 10/100) pci:v00008086d00001229sv00008086sd00000006* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82557 10/100 with Wake on LAN) pci:v00008086d00001229sv00008086sd00000007* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82558 10/100 Adapter) pci:v00008086d00001229sv00008086sd00000008* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82558 10/100 with Wake on LAN) pci:v00008086d00001229sv00008086sd00000009* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82558B PRO/100+ PCI (TP)) pci:v00008086d00001229sv00008086sd0000000A* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Management Adapter) pci:v00008086d00001229sv00008086sd0000000B* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+) pci:v00008086d00001229sv00008086sd0000000C* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Management Adapter) pci:v00008086d00001229sv00008086sd0000000D* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Alert On LAN II* Adapter) pci:v00008086d00001229sv00008086sd0000000E* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Management Adapter with Alert On LAN*) pci:v00008086d00001229sv00008086sd0000000F* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Desktop Adapter) pci:v00008086d00001229sv00008086sd00000010* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Management Adapter) pci:v00008086d00001229sv00008086sd00000011* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Management Adapter) pci:v00008086d00001229sv00008086sd00000012* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Advanced Management Adapter (D)) pci:v00008086d00001229sv00008086sd00000013* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Advanced Management Adapter (E)) pci:v00008086d00001229sv00008086sd00000030* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Management Adapter with Alert On LAN* GC) pci:v00008086d00001229sv00008086sd00000031* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Desktop Adapter) pci:v00008086d00001229sv00008086sd00000040* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Desktop Adapter) pci:v00008086d00001229sv00008086sd00000041* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Desktop Adapter) pci:v00008086d00001229sv00008086sd00000042* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Desktop Adapter) pci:v00008086d00001229sv00008086sd00000050* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Desktop Adapter) pci:v00008086d00001229sv00008086sd00001009* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Server Adapter) pci:v00008086d00001229sv00008086sd0000100C* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Server Adapter (PILA8470B)) pci:v00008086d00001229sv00008086sd00001012* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Server Adapter (D)) pci:v00008086d00001229sv00008086sd00001013* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Server Adapter (E)) pci:v00008086d00001229sv00008086sd00001015* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Dual Port Server Adapter) pci:v00008086d00001229sv00008086sd00001017* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Dual Port Server Adapter) pci:v00008086d00001229sv00008086sd00001030* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Management Adapter with Alert On LAN* G Server) pci:v00008086d00001229sv00008086sd00001040* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Server Adapter) pci:v00008086d00001229sv00008086sd00001041* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Server Adapter) pci:v00008086d00001229sv00008086sd00001042* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Server Adapter) pci:v00008086d00001229sv00008086sd00001050* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Server Adapter) pci:v00008086d00001229sv00008086sd00001051* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Server Adapter) pci:v00008086d00001229sv00008086sd00001052* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Server Adapter) pci:v00008086d00001229sv00008086sd000010F0* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Dual Port Adapter) pci:v00008086d00001229sv00008086sd00001229* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82557/8/9 [Ethernet Pro 100]) pci:v00008086d00001229sv00008086sd00002009* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Mobile Adapter) pci:v00008086d00001229sv00008086sd0000200D* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Cardbus) pci:v00008086d00001229sv00008086sd0000200E* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 LAN+V90 Cardbus Modem) pci:v00008086d00001229sv00008086sd0000200F* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SR Mobile Adapter) pci:v00008086d00001229sv00008086sd00002010* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Mobile Combo Adapter) pci:v00008086d00001229sv00008086sd00002013* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SR Mobile Combo Adapter) pci:v00008086d00001229sv00008086sd00002016* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Mobile Adapter) pci:v00008086d00001229sv00008086sd00002017* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Combo Mobile Adapter) pci:v00008086d00001229sv00008086sd00002018* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SR Mobile Adapter) pci:v00008086d00001229sv00008086sd00002019* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SR Combo Mobile Adapter) pci:v00008086d00001229sv00008086sd00002101* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 P Mobile Adapter) pci:v00008086d00001229sv00008086sd00002102* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Adapter) pci:v00008086d00001229sv00008086sd00002103* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Adapter) pci:v00008086d00001229sv00008086sd00002104* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Adapter) pci:v00008086d00001229sv00008086sd00002105* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Adapter) pci:v00008086d00001229sv00008086sd00002106* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 P Mobile Adapter) pci:v00008086d00001229sv00008086sd00002107* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Network Connection) pci:v00008086d00001229sv00008086sd00002108* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Network Connection) pci:v00008086d00001229sv00008086sd00002200* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 P Mobile Combo Adapter) pci:v00008086d00001229sv00008086sd00002201* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 P Mobile Combo Adapter) pci:v00008086d00001229sv00008086sd00002202* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Combo Adapter) pci:v00008086d00001229sv00008086sd00002203* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) pci:v00008086d00001229sv00008086sd00002204* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) pci:v00008086d00001229sv00008086sd00002205* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Combo Adapter) pci:v00008086d00001229sv00008086sd00002206* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Combo Adapter) pci:v00008086d00001229sv00008086sd00002207* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Combo Adapter) pci:v00008086d00001229sv00008086sd00002208* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 P Mobile Combo Adapter) pci:v00008086d00001229sv00008086sd00002402* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) pci:v00008086d00001229sv00008086sd00002407* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) pci:v00008086d00001229sv00008086sd00002408* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) pci:v00008086d00001229sv00008086sd00002409* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) pci:v00008086d00001229sv00008086sd0000240F* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) pci:v00008086d00001229sv00008086sd00002410* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) pci:v00008086d00001229sv00008086sd00002411* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) pci:v00008086d00001229sv00008086sd00002412* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) pci:v00008086d00001229sv00008086sd00002413* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) pci:v00008086d00001229sv00008086sd00003000* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LAN on Motherboard) pci:v00008086d00001229sv00008086sd00003001* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Basic Alert on LAN*) pci:v00008086d00001229sv00008086sd00003002* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN II*) pci:v00008086d00001229sv00008086sd00003006* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Network Connection) pci:v00008086d00001229sv00008086sd00003007* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Network Connection) pci:v00008086d00001229sv00008086sd00003008* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Network Connection) pci:v00008086d00001229sv00008086sd00003010* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Network Connection) pci:v00008086d00001229sv00008086sd00003011* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Network Connection) pci:v00008086d00001229sv00008086sd00003012* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Network Connection) pci:v00008086d00001229sv00008086sd0000301A* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (S845WD1-E mainboard) pci:v00008086d00001229sv00008086sd00003411* ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (SDS2 Mainboard) pci:v00008086d0000122D* ID_MODEL_FROM_DATABASE=430FX - 82437FX TSC [Triton I] pci:v00008086d0000122E* ID_MODEL_FROM_DATABASE=82371FB PIIX ISA [Triton I] pci:v00008086d00001230* ID_MODEL_FROM_DATABASE=82371FB PIIX IDE [Triton I] pci:v00008086d00001231* ID_MODEL_FROM_DATABASE=DSVD Modem pci:v00008086d00001234* ID_MODEL_FROM_DATABASE=430MX - 82371MX Mobile PCI I/O IDE Xcelerator (MPIIX) pci:v00008086d00001235* ID_MODEL_FROM_DATABASE=430MX - 82437MX Mob. System Ctrlr (MTSC) & 82438MX Data Path (MTDP) pci:v00008086d00001237* ID_MODEL_FROM_DATABASE=440FX - 82441FX PMC [Natoma] pci:v00008086d00001237sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=440FX - 82441FX PMC [Natoma] (Qemu virtual machine) pci:v00008086d00001239* ID_MODEL_FROM_DATABASE=82371FB PIIX IDE Interface pci:v00008086d0000123B* ID_MODEL_FROM_DATABASE=82380PB PCI to PCI Docking Bridge pci:v00008086d0000123C* ID_MODEL_FROM_DATABASE=82380AB (MISA) Mobile PCI-to-ISA Bridge pci:v00008086d0000123D* ID_MODEL_FROM_DATABASE=683053 Programmable Interrupt Device pci:v00008086d0000123E* ID_MODEL_FROM_DATABASE=82466GX (IHPC) Integrated Hot-Plug Controller (hidden mode) pci:v00008086d0000123F* ID_MODEL_FROM_DATABASE=82466GX Integrated Hot-Plug Controller (IHPC) pci:v00008086d00001240* ID_MODEL_FROM_DATABASE=82752 (752) AGP Graphics Accelerator pci:v00008086d0000124B* ID_MODEL_FROM_DATABASE=82380FB (MPCI2) Mobile Docking Controller pci:v00008086d00001250* ID_MODEL_FROM_DATABASE=430HX - 82439HX TXC [Triton II] pci:v00008086d00001360* ID_MODEL_FROM_DATABASE=82806AA PCI64 Hub PCI Bridge pci:v00008086d00001361* ID_MODEL_FROM_DATABASE=82806AA PCI64 Hub Controller (HRes) pci:v00008086d00001361sv00008086sd00001361* ID_MODEL_FROM_DATABASE=82806AA PCI64 Hub Controller (HRes) pci:v00008086d00001361sv00008086sd00008000* ID_MODEL_FROM_DATABASE=82806AA PCI64 Hub Controller (HRes) pci:v00008086d00001460* ID_MODEL_FROM_DATABASE=82870P2 P64H2 Hub PCI Bridge pci:v00008086d00001461* ID_MODEL_FROM_DATABASE=82870P2 P64H2 I/OxAPIC pci:v00008086d00001461sv000015D9sd00003480* ID_MODEL_FROM_DATABASE=82870P2 P64H2 I/OxAPIC (P4DP6) pci:v00008086d00001461sv00004C53sd00001090* ID_MODEL_FROM_DATABASE=82870P2 P64H2 I/OxAPIC (Cx9/Vx9 mainboard) pci:v00008086d00001462* ID_MODEL_FROM_DATABASE=82870P2 P64H2 Hot Plug Controller pci:v00008086d00001501* ID_MODEL_FROM_DATABASE=82567V-3 Gigabit Network Connection pci:v00008086d00001502* ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection pci:v00008086d00001502sv00001028sd000004A3* ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection (Precision M4600) pci:v00008086d00001502sv00008086sd0000357A* ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection (Server Board S1200BTS) pci:v00008086d00001503* ID_MODEL_FROM_DATABASE=82579V Gigabit Network Connection pci:v00008086d00001503sv00001043sd0000849C* ID_MODEL_FROM_DATABASE=82579V Gigabit Network Connection (P8P67 Deluxe Motherboard) pci:v00008086d00001507* ID_MODEL_FROM_DATABASE=Ethernet Express Module X520-P2 pci:v00008086d00001508* ID_MODEL_FROM_DATABASE=82598EB Gigabit BX Network Connection pci:v00008086d0000150A* ID_MODEL_FROM_DATABASE=82576NS Gigabit Network Connection pci:v00008086d0000150B* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT2 Server Adapter pci:v00008086d0000150Bsv00008086sd0000A10C* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT2 Server Adapter pci:v00008086d0000150Bsv00008086sd0000A11C* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT2 Server Adapter pci:v00008086d0000150Bsv00008086sd0000A12C* ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT2 Server Adapter pci:v00008086d0000150C* ID_MODEL_FROM_DATABASE=82583V Gigabit Network Connection pci:v00008086d0000150D* ID_MODEL_FROM_DATABASE=82576 Gigabit Backplane Connection pci:v00008086d0000150Dsv00008086sd0000A10C* ID_MODEL_FROM_DATABASE=82576 Gigabit Backplane Connection (Gigabit ET Quad Port Mezzanine Card) pci:v00008086d0000150E* ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection pci:v00008086d0000150Esv0000103Csd00001780* ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection (NC365T 4-port Ethernet Server Adapter) pci:v00008086d0000150Esv00008086sd000012A1* ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection (Ethernet Server Adapter I340-T4) pci:v00008086d0000150Esv00008086sd000012A2* ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection (Ethernet Server Adapter I340-T4) pci:v00008086d0000150F* ID_MODEL_FROM_DATABASE=82580 Gigabit Fiber Network Connection pci:v00008086d00001510* ID_MODEL_FROM_DATABASE=82580 Gigabit Backplane Connection pci:v00008086d00001511* ID_MODEL_FROM_DATABASE=82580 Gigabit SFP Connection pci:v00008086d00001514* ID_MODEL_FROM_DATABASE=Ethernet X520 10GbE Dual Port KX4 Mezz pci:v00008086d00001514sv00008086sd0000000B* ID_MODEL_FROM_DATABASE=Ethernet X520 10GbE Dual Port KX4 Mezz pci:v00008086d00001515* ID_MODEL_FROM_DATABASE=X540 Ethernet Controller Virtual Function pci:v00008086d00001516* ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection pci:v00008086d00001516sv00008086sd000012B1* ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection (Ethernet Server Adapter I340-T2) pci:v00008086d00001516sv00008086sd000012B2* ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection (Ethernet Server Adapter I340-T2) pci:v00008086d00001517* ID_MODEL_FROM_DATABASE=82599ES 10 Gigabit Network Connection pci:v00008086d00001517sv00001137sd0000006A* ID_MODEL_FROM_DATABASE=82599ES 10 Gigabit Network Connection (UCS CNA M61KR-I Intel Converged Network Adapter) pci:v00008086d00001518* ID_MODEL_FROM_DATABASE=82576NS SerDes Gigabit Network Connection pci:v00008086d0000151C* ID_MODEL_FROM_DATABASE=82599 10 Gigabit TN Network Connection pci:v00008086d0000151Csv0000108Esd00007B13* ID_MODEL_FROM_DATABASE=82599 10 Gigabit TN Network Connection (Dual 10GBASE-T LP) pci:v00008086d00001520* ID_MODEL_FROM_DATABASE=I350 Ethernet Controller Virtual Function pci:v00008086d00001521* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection pci:v00008086d00001521sv00001028sd00000602* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 2P I350-t LOM) pci:v00008086d00001521sv00001028sd00001F60* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 4P I350-t rNDC) pci:v00008086d00001521sv00001028sd00001F62* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 4P X540/I350 rNDC) pci:v00008086d00001521sv00001028sd0000FF9A* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 4P X710/I350 rNDC) pci:v00008086d00001521sv0000103Csd000017D1* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 4-port 366FLR Adapter) pci:v00008086d00001521sv0000103Csd00002003* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 2-port 367i Adapter) pci:v00008086d00001521sv0000103Csd00002226* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 1-port 364i Adapter) pci:v00008086d00001521sv0000103Csd0000337F* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 2-port 361i Adapter) pci:v00008086d00001521sv0000103Csd00003380* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 4-port 366i Adapter) pci:v00008086d00001521sv0000103Csd0000339E* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 2-port 361T Adapter) pci:v00008086d00001521sv0000103Csd00008157* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 4-port 366T Adapter) pci:v00008086d00001521sv0000108Esd00007B16* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Quad Port GbE PCIe 2.0 ExpressModule, UTP) pci:v00008086d00001521sv0000108Esd00007B18* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Quad Port GbE PCIe 2.0 Low Profile Adapter, UTP) pci:v00008086d00001521sv00001093sd00007648* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (PCIe-8237R Ethernet Adapter) pci:v00008086d00001521sv00001093sd00007649* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (PCIe-8236 Ethernet Adapter) pci:v00008086d00001521sv00001093sd000076B1* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (PCIe-8237R-S Ethernet Adapter) pci:v00008086d00001521sv00001093sd0000775B* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (PCIe-8237 Ethernet Adapter) pci:v00008086d00001521sv000010A9sd0000802A* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (UV2-BaseIO dual-port GbE) pci:v00008086d00001521sv000017AAsd00001074* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (ThinkServer I350-T4 AnyFabric) pci:v00008086d00001521sv000017AAsd00004005* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection pci:v00008086d00001521sv00008086sd00000001* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T4) pci:v00008086d00001521sv00008086sd00000002* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T2) pci:v00008086d00001521sv00008086sd000000A1* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T4) pci:v00008086d00001521sv00008086sd000000A2* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T2) pci:v00008086d00001521sv00008086sd00005001* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T4) pci:v00008086d00001521sv00008086sd00005002* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T2) pci:v00008086d00001522* ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection pci:v00008086d00001522sv0000108Esd00007B17* ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Quad Port GbE PCIe 2.0 ExpressModule, MMF) pci:v00008086d00001522sv0000108Esd00007B19* ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Dual Port GbE PCIe 2.0 Low Profile Adapter, MMF) pci:v00008086d00001522sv00008086sd00000002* ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-T2) pci:v00008086d00001522sv00008086sd00000003* ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-F4) pci:v00008086d00001522sv00008086sd00000004* ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-F2) pci:v00008086d00001522sv00008086sd00000005* ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-F1) pci:v00008086d00001522sv00008086sd000000A2* ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-T2) pci:v00008086d00001522sv00008086sd000000A3* ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-F4) pci:v00008086d00001522sv00008086sd000000A4* ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-F2) pci:v00008086d00001523* ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection pci:v00008086d00001523sv00001028sd00000060* ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (Gigabit 2P I350 LOM) pci:v00008086d00001523sv00001028sd00001F9B* ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (Gigabit 4P I350-t bNDC) pci:v00008086d00001523sv0000103Csd00001784* ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (Ethernet 1Gb 2-port 361FLB Adapter) pci:v00008086d00001523sv0000103Csd000018D1* ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (Ethernet 1Gb 2-port 361FLB Adapter) pci:v00008086d00001523sv0000103Csd00001989* ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (Ethernet 1Gb 2-port 363i Adapter) pci:v00008086d00001523sv0000103Csd0000339F* ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (Ethernet 1Gb 4-port 366M Adapter) pci:v00008086d00001523sv00008086sd00001F52* ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (1GbE 4P I350 Mezz) pci:v00008086d00001524* ID_MODEL_FROM_DATABASE=I350 Gigabit Connection pci:v00008086d00001525* ID_MODEL_FROM_DATABASE=82567V-4 Gigabit Network Connection pci:v00008086d00001526* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection pci:v00008086d00001526sv00008086sd0000A05C* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET2 Quad Port Server Adapter) pci:v00008086d00001526sv00008086sd0000A06C* ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET2 Quad Port Server Adapter) pci:v00008086d00001527* ID_MODEL_FROM_DATABASE=82580 Gigabit Fiber Network Connection pci:v00008086d00001527sv00008086sd00000001* ID_MODEL_FROM_DATABASE=82580 Gigabit Fiber Network Connection (Ethernet Server Adapter I340-F4) pci:v00008086d00001527sv00008086sd00000002* ID_MODEL_FROM_DATABASE=82580 Gigabit Fiber Network Connection (Ethernet Server Adapter I340-F4) pci:v00008086d00001528* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 pci:v00008086d00001528sv00001028sd00001F61* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet 10G 4P X540/I350 rNDC) pci:v00008086d00001528sv0000103Csd0000192D* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (561FLR-T 2-port 10Gb Ethernet Adapter) pci:v00008086d00001528sv0000103Csd00002004* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet 10Gb 2-port 561i Adapter) pci:v00008086d00001528sv0000103Csd0000211A* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet 10Gb 2-port 561T Adapter) pci:v00008086d00001528sv0000108Esd00004853* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 pci:v00008086d00001528sv0000108Esd00007B14* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Sun Dual Port 10 GbE PCIe 2.0 ExpressModule, Base-T) pci:v00008086d00001528sv0000108Esd00007B15* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Sun Dual Port 10 GbE PCIe 2.0 Low Profile Adapter, Base-T) pci:v00008086d00001528sv00001137sd000000BF* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet Converged Network Adapter X540-T2) pci:v00008086d00001528sv000017AAsd00001073* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (ThinkServer X540-T2 AnyFabric) pci:v00008086d00001528sv000017AAsd00004006* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 pci:v00008086d00001528sv00008086sd00000001* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet Converged Network Adapter X540-T2) pci:v00008086d00001528sv00008086sd00000002* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet Converged Network Adapter X540-T1) pci:v00008086d00001528sv00008086sd0000001A* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet Converged Network Adapter X540-T2) pci:v00008086d00001528sv00008086sd000000A2* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet Converged Network Adapter X540-T1) pci:v00008086d00001528sv00008086sd00001F61* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet 10G 4P X540/I350 rNDC) pci:v00008086d00001528sv00008086sd00005003* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet 10G 2P X540-t Adapter) pci:v00008086d00001528sv00008086sd00005004* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet 10G 2P X540-t Adapter) pci:v00008086d00001529* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Network Connection with FCoE pci:v00008086d0000152A* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection with FCoE pci:v00008086d00001533* ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection pci:v00008086d00001533sv0000103Csd00000003* ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (Ethernet I210-T1 GbE NIC) pci:v00008086d00001533sv00001093sd00007706* ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (Compact Vision System Ethernet Adapter) pci:v00008086d00001533sv000010A9sd0000802C* ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (UV300 BaseIO single-port GbE) pci:v00008086d00001533sv000010A9sd0000802D* ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (UV3000 BaseIO GbE Network) pci:v00008086d00001533sv000017AAsd00001100* ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (ThinkServer Ethernet Server Adapter) pci:v00008086d00001533sv00008086sd00000001* ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (Ethernet Server Adapter I210-T1) pci:v00008086d00001533sv00008086sd00000002* ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (Ethernet Server Adapter I210-T1) pci:v00008086d00001536* ID_MODEL_FROM_DATABASE=I210 Gigabit Fiber Network Connection pci:v00008086d00001537* ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection pci:v00008086d00001537sv00001059sd00000110* ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection (T4005 1GbE interface) pci:v00008086d00001537sv00001059sd00000111* ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection (T4007 1GbE interface) pci:v00008086d00001537sv00001059sd00000120* ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection (T4008 1GbE interface) pci:v00008086d00001538* ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection pci:v00008086d00001539* ID_MODEL_FROM_DATABASE=I211 Gigabit Network Connection pci:v00008086d0000153A* ID_MODEL_FROM_DATABASE=Ethernet Connection I217-LM pci:v00008086d0000153Asv0000103Csd00001909* ID_MODEL_FROM_DATABASE=Ethernet Connection I217-LM (ZBook 15) pci:v00008086d0000153Asv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=Ethernet Connection I217-LM (ThinkPad T440p) pci:v00008086d0000153B* ID_MODEL_FROM_DATABASE=Ethernet Connection I217-V pci:v00008086d00001547* ID_MODEL_FROM_DATABASE=DSL3510 Thunderbolt Port [Cactus Ridge] pci:v00008086d00001549* ID_MODEL_FROM_DATABASE=DSL3510 Thunderbolt Controller [Cactus Ridge] pci:v00008086d0000154A* ID_MODEL_FROM_DATABASE=Ethernet Server Adapter X520-4 pci:v00008086d0000154Asv00008086sd0000011A* ID_MODEL_FROM_DATABASE=Ethernet Server Adapter X520-4 (Ethernet Converged Network Adapter X520-4) pci:v00008086d0000154Asv00008086sd0000011B* ID_MODEL_FROM_DATABASE=Ethernet Server Adapter X520-4 (Ethernet Converged Network Adapter X520-4) pci:v00008086d0000154Asv00008086sd0000011C* ID_MODEL_FROM_DATABASE=Ethernet Server Adapter X520-4 (Ethernet Converged Network Adapter X520-4) pci:v00008086d0000154C* ID_MODEL_FROM_DATABASE=XL710/X710 Virtual Function pci:v00008086d0000154D* ID_MODEL_FROM_DATABASE=Ethernet 10G 2P X520 Adapter pci:v00008086d0000154Dsv00008086sd00007B11* ID_MODEL_FROM_DATABASE=Ethernet 10G 2P X520 Adapter (10GbE 2P X520 Adapter) pci:v00008086d00001557* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Network Connection pci:v00008086d00001557sv000017AAsd00004008* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Network Connection (82599EN 10 Gigabit Network Connection) pci:v00008086d00001557sv00008086sd00000001* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Network Connection (Ethernet OCP Server Adapter X520-1) pci:v00008086d00001558* ID_MODEL_FROM_DATABASE=Ethernet Converged Network Adapter X520-Q1 pci:v00008086d00001558sv00008086sd0000011A* ID_MODEL_FROM_DATABASE=Ethernet Converged Network Adapter X520-Q1 pci:v00008086d00001558sv00008086sd0000011B* ID_MODEL_FROM_DATABASE=Ethernet Converged Network Adapter X520-Q1 pci:v00008086d00001559* ID_MODEL_FROM_DATABASE=Ethernet Connection I218-V pci:v00008086d0000155A* ID_MODEL_FROM_DATABASE=Ethernet Connection I218-LM pci:v00008086d0000155Asv000017AAsd00002214* ID_MODEL_FROM_DATABASE=Ethernet Connection I218-LM (ThinkPad X240) pci:v00008086d0000155C* ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter pci:v00008086d0000155Csv00008086sd00000001* ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter (X540-T2) pci:v00008086d0000155D* ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter pci:v00008086d0000155Dsv00008086sd00000001* ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter (X520-SR2) pci:v00008086d0000155Dsv00008086sd00000002* ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter (X520-LR2) pci:v00008086d00001560* ID_MODEL_FROM_DATABASE=Ethernet Controller X540 pci:v00008086d00001563* ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T pci:v00008086d00001563sv00008086sd00000001* ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T2) pci:v00008086d00001563sv00008086sd0000001A* ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T2) pci:v00008086d0000156C* ID_MODEL_FROM_DATABASE=DSL5520 Thunderbolt [Falcon Ridge] pci:v00008086d0000156D* ID_MODEL_FROM_DATABASE=DSL5520 Thunderbolt [Falcon Ridge] pci:v00008086d0000156F* ID_MODEL_FROM_DATABASE=Ethernet Connection I219-LM pci:v00008086d00001570* ID_MODEL_FROM_DATABASE=Ethernet Connection I219-V pci:v00008086d00001571* ID_MODEL_FROM_DATABASE=XL710/X710 Virtual Function pci:v00008086d00001572* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ pci:v00008086d00001572sv00001028sd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10G X710 rNDC) pci:v00008086d00001572sv00001028sd00001F99* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10G 4P X710/I350 rNDC) pci:v00008086d00001572sv00001028sd00001F9C* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10G 4P X710 SFP+ rNDC) pci:v00008086d00001572sv0000103Csd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10Gb 562SFP+ Adapter) pci:v00008086d00001572sv0000103Csd000022FC* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (HP Ethernet 10Gb 2-port 562FLR-SFP+ Adapter) pci:v00008086d00001572sv0000103Csd000022FD* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (HP Ethernet 10Gb 2-port 562SFP+ Adapter) pci:v00008086d00001572sv00001137sd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged NIC X710-4) pci:v00008086d00001572sv00001137sd0000013B* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged NIC X710-4) pci:v00008086d00001572sv000017AAsd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (ThinkServer X710 AnyFabric for 10GbE SFP+) pci:v00008086d00001572sv000017AAsd00004001* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (ThinkServer X710-4 AnyFabric for 10GbE SFP+) pci:v00008086d00001572sv000017AAsd00004002* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (ThinkServer X710-2 AnyFabric for 10GbE SFP+) pci:v00008086d00001572sv00008086sd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710) pci:v00008086d00001572sv00008086sd00000001* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710-4) pci:v00008086d00001572sv00008086sd00000002* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710-4) pci:v00008086d00001572sv00008086sd00000004* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710-4) pci:v00008086d00001572sv00008086sd00000005* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10G 4P X710 Adapter) pci:v00008086d00001572sv00008086sd00000006* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10G 2P X710 Adapter) pci:v00008086d00001572sv00008086sd00000007* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710-2) pci:v00008086d00001572sv00008086sd00000008* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710-2) pci:v00008086d00001572sv00008086sd00000009* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ pci:v00008086d00001572sv00008086sd0000000A* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ pci:v00008086d00001572sv00008086sd0000000D* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ pci:v00008086d00001572sv00008086sd00004005* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Controller XL710 for 10 Gigabit SFP+) pci:v00008086d00001572sv00008086sd00004006* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ pci:v00008086d00001578* ID_MODEL_FROM_DATABASE=DSL6540 Thunderbolt [Alpine Ridge] pci:v00008086d0000157B* ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection pci:v00008086d0000157C* ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection pci:v00008086d00001580* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE backplane pci:v00008086d00001581* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane pci:v00008086d00001581sv00001028sd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet 10G X710-k bNDC) pci:v00008086d00001581sv00001028sd00001F98* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet 10G 4P X710-k bNDC) pci:v00008086d00001581sv00001028sd00001F9E* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet 10G 2P X710-k bNDC) pci:v00008086d00001581sv00008086sd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet Converged Network Adapter XL710-Q2) pci:v00008086d00001583* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ pci:v00008086d00001583sv00001028sd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet 40G 2P XL710 QSFP+ rNDC) pci:v00008086d00001583sv00001028sd00001F9F* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet 40G 2P XL710 QSFP+ rNDC) pci:v00008086d00001583sv0000108Esd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (10 Gb/40 Gb Ethernet Adapter) pci:v00008086d00001583sv0000108Esd00007B1B* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (10 Gb/40 Gb Ethernet Adapter) pci:v00008086d00001583sv00001137sd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged NIC XL710-Q2) pci:v00008086d00001583sv00001137sd0000013C* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged NIC XL710-Q2) pci:v00008086d00001583sv00008086sd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q2) pci:v00008086d00001583sv00008086sd00000001* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q2) pci:v00008086d00001583sv00008086sd00000002* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q2) pci:v00008086d00001583sv00008086sd00000003* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet I/O Module XL710-Q2) pci:v00008086d00001583sv00008086sd00000004* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Server Adapter XL710-Q2OCP) pci:v00008086d00001583sv00008086sd00000006* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q2) pci:v00008086d00001584* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ pci:v00008086d00001584sv00008086sd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q1) pci:v00008086d00001584sv00008086sd00000001* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q1) pci:v00008086d00001584sv00008086sd00000002* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q1) pci:v00008086d00001584sv00008086sd00000003* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet I/O Module XL710-Q1) pci:v00008086d00001584sv00008086sd00000004* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Server Adapter XL710-Q1OCP) pci:v00008086d00001585* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE QSFP+ pci:v00008086d00001586* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T pci:v00008086d00001586sv0000108Esd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T pci:v00008086d00001586sv0000108Esd00004857* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T pci:v00008086d00001587* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane pci:v00008086d00001587sv0000103Csd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HP Flex-20 20Gb 2-port 660FLB Adapter) pci:v00008086d00001587sv0000103Csd000022FE* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HP Flex-20 20Gb 2-port 660FLB Adapter) pci:v00008086d00001588* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane pci:v00008086d00001588sv0000103Csd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HP Flex-20 20Gb 2-port 660M Adapter) pci:v00008086d00001588sv0000103Csd000022FF* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HP Flex-20 20Gb 2-port 660M Adapter) pci:v00008086d00001589* ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T pci:v00008086d00001589sv00008086sd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T) pci:v00008086d00001589sv00008086sd00000001* ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T4) pci:v00008086d00001589sv00008086sd00000002* ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T4) pci:v00008086d000015A0* ID_MODEL_FROM_DATABASE=Ethernet Connection (2) I218-LM pci:v00008086d000015A1* ID_MODEL_FROM_DATABASE=Ethernet Connection (2) I218-V pci:v00008086d000015A2* ID_MODEL_FROM_DATABASE=Ethernet Connection (3) I218-LM pci:v00008086d000015A3* ID_MODEL_FROM_DATABASE=Ethernet Connection (3) I218-V pci:v00008086d000015A4* ID_MODEL_FROM_DATABASE=Ethernet Switch FM10000 Host Interface pci:v00008086d000015A5* ID_MODEL_FROM_DATABASE=Ethernet Switch FM10000 Host Virtual Interface pci:v00008086d000015A8* ID_MODEL_FROM_DATABASE=Ethernet Connection X552 Virtual Function pci:v00008086d000015AA* ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE Backplane pci:v00008086d000015AAsv00001059sd00000120* ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE Backplane (T4008 10GbE interface) pci:v00008086d000015AB* ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE Backplane pci:v00008086d000015AC* ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE SFP+ pci:v00008086d000015AD* ID_MODEL_FROM_DATABASE=Ethernet Connection X552/X557-AT 10GBASE-T pci:v00008086d000015AE* ID_MODEL_FROM_DATABASE=Ethernet Connection X552 1000BASE-T pci:v00008086d000015B6* ID_MODEL_FROM_DATABASE=DSL6540 USB 3.1 Controller [Alpine Ridge] pci:v00008086d000015B7* ID_MODEL_FROM_DATABASE=Ethernet Connection (2) I219-LM pci:v00008086d000015B8* ID_MODEL_FROM_DATABASE=Ethernet Connection (2) I219-V pci:v00008086d000015B9* ID_MODEL_FROM_DATABASE=Ethernet Connection (3) I219-LM pci:v00008086d000015D1* ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T pci:v00008086d000015D1sv00008086sd00000002* ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T1) pci:v00008086d000015D1sv00008086sd000000A2* ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T1) pci:v00008086d000015D6* ID_MODEL_FROM_DATABASE=Ethernet Connection (5) I219-V pci:v00008086d000015D7* ID_MODEL_FROM_DATABASE=Ethernet Connection (4) I219-LM pci:v00008086d000015D8* ID_MODEL_FROM_DATABASE=Ethernet Connection (4) I219-V pci:v00008086d000015E3* ID_MODEL_FROM_DATABASE=Ethernet Connection (5) I219-LM pci:v00008086d00001600* ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge -OPI pci:v00008086d00001601* ID_MODEL_FROM_DATABASE=Broadwell-U PCI Express x16 Controller pci:v00008086d00001602* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d00001603* ID_MODEL_FROM_DATABASE=Broadwell-U Processor Thermal Subsystem pci:v00008086d00001604* ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge -OPI pci:v00008086d00001605* ID_MODEL_FROM_DATABASE=Broadwell-U PCI Express x8 Controller pci:v00008086d00001606* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d00001607* ID_MODEL_FROM_DATABASE=Broadwell-U CHAPS Device pci:v00008086d00001608* ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge -OPI pci:v00008086d00001609* ID_MODEL_FROM_DATABASE=Broadwell-U x4 PCIe pci:v00008086d0000160A* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000160B* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000160C* ID_MODEL_FROM_DATABASE=Broadwell-U Audio Controller pci:v00008086d0000160D* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000160E* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000160F* ID_MODEL_FROM_DATABASE=Broadwell-U SoftSKU pci:v00008086d00001610* ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge - DMI pci:v00008086d00001612* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d00001614* ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge - DMI pci:v00008086d00001616* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d00001616sv0000103Csd00002216* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics (ZBook 15u G2 Mobile Workstation) pci:v00008086d00001618* ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge - DMI pci:v00008086d0000161A* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000161B* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000161D* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000161E* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d00001622* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d00001626* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000162A* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000162B* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000162D* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000162E* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d00001632* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d00001636* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000163A* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000163B* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000163D* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d0000163E* ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics pci:v00008086d00001900* ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers pci:v00008086d00001901* ID_MODEL_FROM_DATABASE=Skylake PCIe Controller (x16) pci:v00008086d00001903* ID_MODEL_FROM_DATABASE=Skylake Processor Thermal Subsystem pci:v00008086d00001904* ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers pci:v00008086d00001905* ID_MODEL_FROM_DATABASE=Skylake PCIe Controller (x8) pci:v00008086d00001908* ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers pci:v00008086d00001909* ID_MODEL_FROM_DATABASE=Skylake PCIe Controller (x4) pci:v00008086d0000190C* ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers pci:v00008086d0000190F* ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers pci:v00008086d00001910* ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers pci:v00008086d00001911* ID_MODEL_FROM_DATABASE=Skylake Gaussian Mixture Model pci:v00008086d00001912* ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics pci:v00008086d00001916* ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics pci:v00008086d00001918* ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers pci:v00008086d00001919* ID_MODEL_FROM_DATABASE=Skylake Imaging Unit pci:v00008086d0000191B* ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics pci:v00008086d0000191E* ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics pci:v00008086d0000191F* ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers pci:v00008086d00001926* ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics pci:v00008086d00001932* ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics pci:v00008086d0000193B* ID_MODEL_FROM_DATABASE=Skylake Integrated Graphics pci:v00008086d00001960* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor pci:v00008086d00001960sv0000101Esd00000431* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 431 RAID Controller) pci:v00008086d00001960sv0000101Esd00000438* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 438 Ultra2 LVD RAID Controller) pci:v00008086d00001960sv0000101Esd00000466* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 466 Express Plus RAID Controller) pci:v00008086d00001960sv0000101Esd00000467* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 467 Enterprise 1500 RAID Controller) pci:v00008086d00001960sv0000101Esd00000490* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 490 Express 300 RAID Controller) pci:v00008086d00001960sv0000101Esd00000762* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 762 Express RAID Controller) pci:v00008086d00001960sv0000101Esd000009A0* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (PowerEdge Expandable RAID Controller 2/SC) pci:v00008086d00001960sv00001028sd00000467* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (PowerEdge Expandable RAID Controller 2/DC) pci:v00008086d00001960sv00001028sd00001111* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (PowerEdge Expandable RAID Controller 2/SC) pci:v00008086d00001960sv0000103Csd000003A2* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID) pci:v00008086d00001960sv0000103Csd000010C6* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 438, NetRAID-3Si) pci:v00008086d00001960sv0000103Csd000010C7* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID T5, Integrated NetRAID) pci:v00008086d00001960sv0000103Csd000010CC* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID, Integrated NetRAID) pci:v00008086d00001960sv0000103Csd000010CD* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (NetRAID-1Si) pci:v00008086d00001960sv0000105Asd00000000* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (SuperTrak) pci:v00008086d00001960sv0000105Asd00002168* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (SuperTrak Pro) pci:v00008086d00001960sv0000105Asd00005168* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (SuperTrak66/100) pci:v00008086d00001960sv00001111sd00001111* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 466, PowerEdge Expandable RAID Controller 2/SC) pci:v00008086d00001960sv00001111sd00001112* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (PowerEdge Expandable RAID Controller 2/SC) pci:v00008086d00001960sv0000113Csd000003A2* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID) pci:v00008086d00001960sv0000E4BFsd00001010* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (CG1-RADIO) pci:v00008086d00001960sv0000E4BFsd00001020* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (CU2-QUARTET) pci:v00008086d00001960sv0000E4BFsd00001040* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (CU1-CHORUS) pci:v00008086d00001960sv0000E4BFsd00003100* ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (CX1-BAND) pci:v00008086d00001962* ID_MODEL_FROM_DATABASE=80960RM (i960RM) Microprocessor pci:v00008086d00001962sv0000105Asd00000000* ID_MODEL_FROM_DATABASE=80960RM (i960RM) Microprocessor (SuperTrak SX6000 I2O CPU) pci:v00008086d000019DF* ID_MODEL_FROM_DATABASE=DNV SMBus controller pci:v00008086d00001A21* ID_MODEL_FROM_DATABASE=82840 840 [Carmel] Chipset Host Bridge (Hub A) pci:v00008086d00001A23* ID_MODEL_FROM_DATABASE=82840 840 [Carmel] Chipset AGP Bridge pci:v00008086d00001A24* ID_MODEL_FROM_DATABASE=82840 840 [Carmel] Chipset PCI Bridge (Hub B) pci:v00008086d00001A30* ID_MODEL_FROM_DATABASE=82845 845 [Brookdale] Chipset Host Bridge pci:v00008086d00001A30sv00001028sd0000010E* ID_MODEL_FROM_DATABASE=82845 845 [Brookdale] Chipset Host Bridge (Optiplex GX240) pci:v00008086d00001A30sv0000147Bsd00000505* ID_MODEL_FROM_DATABASE=82845 845 [Brookdale] Chipset Host Bridge (BL7 motherboard) pci:v00008086d00001A30sv000015D9sd00003280* ID_MODEL_FROM_DATABASE=82845 845 [Brookdale] Chipset Host Bridge (Supermicro P4SBE Mainboard) pci:v00008086d00001A31* ID_MODEL_FROM_DATABASE=82845 845 [Brookdale] Chipset AGP Bridge pci:v00008086d00001A38* ID_MODEL_FROM_DATABASE=5000 Series Chipset DMA Engine pci:v00008086d00001A38sv000015D9sd00008680* ID_MODEL_FROM_DATABASE=5000 Series Chipset DMA Engine (X7DVL-E-O motherboard) pci:v00008086d00001A38sv00008086sd00003476* ID_MODEL_FROM_DATABASE=5000 Series Chipset DMA Engine (Intel S5000PSLSATA Server Board) pci:v00008086d00001A48* ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller pci:v00008086d00001A48sv00008086sd0000A01F* ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE SR Server Adapter) pci:v00008086d00001A48sv00008086sd0000A11F* ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE SR Server Adapter) pci:v00008086d00001B48* ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller pci:v00008086d00001B48sv00008086sd0000A01F* ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE LR Server Adapter) pci:v00008086d00001B48sv00008086sd0000A11F* ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE LR Server Adapter) pci:v00008086d00001C00* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 4 port SATA IDE Controller pci:v00008086d00001C01* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 4 port SATA IDE Controller pci:v00008086d00001C02* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA AHCI Controller pci:v00008086d00001C02sv00001028sd000004AA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA AHCI Controller (XPS 8300) pci:v00008086d00001C02sv00001043sd0000844D* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA AHCI Controller (P8 series motherboard) pci:v00008086d00001C02sv00008086sd00007270* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA AHCI Controller (Server Board S1200BTS) pci:v00008086d00001C03* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port SATA AHCI Controller pci:v00008086d00001C03sv00001028sd000004A3* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port SATA AHCI Controller (Precision M4600) pci:v00008086d00001C03sv00001028sd000004B2* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port SATA AHCI Controller (Vostro 3350) pci:v00008086d00001C03sv00001028sd000004DA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port SATA AHCI Controller (Vostro 3750) pci:v00008086d00001C03sv00008086sd00007270* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port SATA AHCI Controller (Apple MacBookPro8,2 [Core i7, 15", 2011]) pci:v00008086d00001C04* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA RAID Controller pci:v00008086d00001C04sv0000103Csd00003118* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA RAID Controller (Smart Array B110i SATA RAID Controller) pci:v00008086d00001C05* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA RAID Controller pci:v00008086d00001C08* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 2 port SATA IDE Controller pci:v00008086d00001C09* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 2 port SATA IDE Controller pci:v00008086d00001C10* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 pci:v00008086d00001C10sv00001028sd000004AA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 (XPS 8300) pci:v00008086d00001C10sv00001028sd000004DA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 (Vostro 3750) pci:v00008086d00001C10sv00001043sd0000844D* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 (P8 series motherboard) pci:v00008086d00001C10sv00008086sd00007270* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 (Server Board S1200BTS / Apple MacBook Pro 8,1/8,2) pci:v00008086d00001C12* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 2 pci:v00008086d00001C12sv00001028sd000004AA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 2 (XPS 8300) pci:v00008086d00001C12sv00008086sd00007270* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 2 (Apple MacBookPro8,2 [Core i7, 15", 2011]) pci:v00008086d00001C14* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 3 pci:v00008086d00001C14sv00001028sd000004DA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 3 (Vostro 3750) pci:v00008086d00001C14sv00008086sd00007270* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 3 (Apple MacBookPro8,2 [Core i7, 15", 2011]) pci:v00008086d00001C16* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 4 pci:v00008086d00001C16sv00001028sd000004AA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 4 (XPS 8300) pci:v00008086d00001C18* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 5 pci:v00008086d00001C18sv00001028sd000004DA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 5 (Vostro 3750) pci:v00008086d00001C18sv00008086sd00007270* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 5 (Server Board S1200BTS) pci:v00008086d00001C1A* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 6 pci:v00008086d00001C1Asv00001028sd000004DA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 6 (Vostro 3750) pci:v00008086d00001C1Asv00001043sd0000844D* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 6 (P8 series motherboard) pci:v00008086d00001C1C* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 7 pci:v00008086d00001C1E* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 8 pci:v00008086d00001C1Esv00001043sd0000844D* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 8 (P8 series motherboard) pci:v00008086d00001C20* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller pci:v00008086d00001C20sv00001028sd00000490* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (Alienware M17x R3) pci:v00008086d00001C20sv00001028sd000004A3* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (Precision M4600) pci:v00008086d00001C20sv00001028sd000004AA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (XPS 8300) pci:v00008086d00001C20sv00001028sd000004B2* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (Vostro 3350) pci:v00008086d00001C20sv00001028sd000004DA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (Vostro 3750) pci:v00008086d00001C20sv00001043sd00008418* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (P8P67 Deluxe Motherboard) pci:v00008086d00001C20sv00001043sd0000841B* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (P8H67 Series Motherboard) pci:v00008086d00001C20sv00008086sd00002008* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (DQ67SW board) pci:v00008086d00001C20sv00008086sd00007270* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (Apple MacBookPro8,2 [Core i7, 15", 2011]) pci:v00008086d00001C22* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller pci:v00008086d00001C22sv00001028sd000004A3* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (Precision M4600) pci:v00008086d00001C22sv00001028sd000004AA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (XPS 8300) pci:v00008086d00001C22sv00001028sd000004B2* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (Vostro 3350) pci:v00008086d00001C22sv00001028sd000004DA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (Vostro 3750) pci:v00008086d00001C22sv00001043sd0000844D* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (P8 series motherboard) pci:v00008086d00001C22sv00008086sd00007270* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (Server Board S1200BTS / Apple MacBook Pro 8,1/8,2) pci:v00008086d00001C24* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family Thermal Management Controller pci:v00008086d00001C25* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family DMI to PCI Bridge pci:v00008086d00001C26* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 pci:v00008086d00001C26sv00001028sd000004A3* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (Precision M4600) pci:v00008086d00001C26sv00001028sd000004AA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (XPS 8300) pci:v00008086d00001C26sv00001028sd000004B2* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (Vostro 3350) pci:v00008086d00001C26sv00001028sd000004DA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (Vostro 3750) pci:v00008086d00001C26sv00001043sd0000844D* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (P8 series motherboard) pci:v00008086d00001C26sv00008086sd00007270* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (Server Board S1200BTS / Apple MacBook Pro 8,1/8,2) pci:v00008086d00001C27* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Universal Host Controller #1 pci:v00008086d00001C27sv00008086sd00007270* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Universal Host Controller #1 (Apple MacBookPro8,2 [Core i7, 15", 2011]) pci:v00008086d00001C2C* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Universal Host Controller #5 pci:v00008086d00001C2Csv00008086sd00007270* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Universal Host Controller #5 (Apple MacBookPro8,2 [Core i7, 15", 2011]) pci:v00008086d00001C2D* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 pci:v00008086d00001C2Dsv00001028sd000004A3* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (Precision M4600) pci:v00008086d00001C2Dsv00001028sd000004AA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (XPS 8300) pci:v00008086d00001C2Dsv00001028sd000004B2* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (Vostro 3350) pci:v00008086d00001C2Dsv00001028sd000004DA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (Vostro 3750) pci:v00008086d00001C2Dsv00001043sd0000844D* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (P8 series motherboard) pci:v00008086d00001C2Dsv00008086sd00007270* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (Server Board S1200BTS / Apple MacBook Pro 8,1/8,2) pci:v00008086d00001C33* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LAN Controller pci:v00008086d00001C35* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family VECI Controller pci:v00008086d00001C3A* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 pci:v00008086d00001C3Asv00001028sd000004A3* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (Precision M4600) pci:v00008086d00001C3Asv00001028sd000004AA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (XPS 8300) pci:v00008086d00001C3Asv00001028sd000004B2* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (Vostro 3350) pci:v00008086d00001C3Asv00001028sd000004DA* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (Vostro 3750) pci:v00008086d00001C3Asv00001043sd0000844D* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (P8 series motherboard) pci:v00008086d00001C3Asv00008086sd00007270* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (Apple MacBookPro8,2 [Core i7, 15", 2011]) pci:v00008086d00001C3B* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #2 pci:v00008086d00001C3C* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family IDE-r Controller pci:v00008086d00001C3D* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family KT Controller pci:v00008086d00001C40* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller pci:v00008086d00001C41* ID_MODEL_FROM_DATABASE=Mobile SFF 6 Series Chipset Family LPC Controller pci:v00008086d00001C42* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller pci:v00008086d00001C43* ID_MODEL_FROM_DATABASE=Mobile 6 Series Chipset Family LPC Controller pci:v00008086d00001C44* ID_MODEL_FROM_DATABASE=Z68 Express Chipset Family LPC Controller pci:v00008086d00001C45* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller pci:v00008086d00001C46* ID_MODEL_FROM_DATABASE=P67 Express Chipset Family LPC Controller pci:v00008086d00001C46sv00001043sd0000844D* ID_MODEL_FROM_DATABASE=P67 Express Chipset Family LPC Controller (P8P67 Deluxe Motherboard) pci:v00008086d00001C47* ID_MODEL_FROM_DATABASE=UM67 Express Chipset Family LPC Controller pci:v00008086d00001C48* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller pci:v00008086d00001C49* ID_MODEL_FROM_DATABASE=HM65 Express Chipset Family LPC Controller pci:v00008086d00001C49sv00008086sd00007270* ID_MODEL_FROM_DATABASE=HM65 Express Chipset Family LPC Controller (Apple MacBookPro8,2 [Core i7, 15", 2011]) pci:v00008086d00001C4A* ID_MODEL_FROM_DATABASE=H67 Express Chipset Family LPC Controller pci:v00008086d00001C4Asv00001028sd000004AA* ID_MODEL_FROM_DATABASE=H67 Express Chipset Family LPC Controller (XPS 8300) pci:v00008086d00001C4Asv00001043sd0000844D* ID_MODEL_FROM_DATABASE=H67 Express Chipset Family LPC Controller (P8H67 Series Motherboard) pci:v00008086d00001C4B* ID_MODEL_FROM_DATABASE=HM67 Express Chipset Family LPC Controller pci:v00008086d00001C4Bsv00001028sd000004B2* ID_MODEL_FROM_DATABASE=HM67 Express Chipset Family LPC Controller (Vostro 3350) pci:v00008086d00001C4Bsv00001028sd000004DA* ID_MODEL_FROM_DATABASE=HM67 Express Chipset Family LPC Controller (Vostro 3750) pci:v00008086d00001C4C* ID_MODEL_FROM_DATABASE=Q65 Express Chipset Family LPC Controller pci:v00008086d00001C4D* ID_MODEL_FROM_DATABASE=QS67 Express Chipset Family LPC Controller pci:v00008086d00001C4E* ID_MODEL_FROM_DATABASE=Q67 Express Chipset Family LPC Controller pci:v00008086d00001C4F* ID_MODEL_FROM_DATABASE=QM67 Express Chipset Family LPC Controller pci:v00008086d00001C4Fsv00001028sd000004A3* ID_MODEL_FROM_DATABASE=QM67 Express Chipset Family LPC Controller (Precision M4600) pci:v00008086d00001C50* ID_MODEL_FROM_DATABASE=B65 Express Chipset Family LPC Controller pci:v00008086d00001C51* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller pci:v00008086d00001C52* ID_MODEL_FROM_DATABASE=C202 Chipset Family LPC Controller pci:v00008086d00001C52sv00008086sd00007270* ID_MODEL_FROM_DATABASE=C202 Chipset Family LPC Controller (Server Board S1200BTS) pci:v00008086d00001C53* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller pci:v00008086d00001C54* ID_MODEL_FROM_DATABASE=C204 Chipset Family LPC Controller pci:v00008086d00001C55* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller pci:v00008086d00001C56* ID_MODEL_FROM_DATABASE=C206 Chipset Family LPC Controller pci:v00008086d00001C56sv00001043sd0000844D* ID_MODEL_FROM_DATABASE=C206 Chipset Family LPC Controller (P8B WS Motherboard) pci:v00008086d00001C57* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller pci:v00008086d00001C58* ID_MODEL_FROM_DATABASE=Upgraded B65 Express Chipset Family LPC Controller pci:v00008086d00001C59* ID_MODEL_FROM_DATABASE=Upgraded HM67 Express Chipset Family LPC Controller pci:v00008086d00001C5A* ID_MODEL_FROM_DATABASE=Upgraded Q67 Express Chipset Family LPC Controller pci:v00008086d00001C5B* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller pci:v00008086d00001C5C* ID_MODEL_FROM_DATABASE=H61 Express Chipset Family LPC Controller pci:v00008086d00001C5D* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller pci:v00008086d00001C5E* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller pci:v00008086d00001C5F* ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller pci:v00008086d00001D00* ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA IDE Controller pci:v00008086d00001D02* ID_MODEL_FROM_DATABASE=C600/X79 series chipset 6-Port SATA AHCI Controller pci:v00008086d00001D04* ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller pci:v00008086d00001D06* ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA Premium RAID Controller pci:v00008086d00001D08* ID_MODEL_FROM_DATABASE=C600/X79 series chipset 2-Port SATA IDE Controller pci:v00008086d00001D10* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 1 pci:v00008086d00001D11* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 1 pci:v00008086d00001D12* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 2 pci:v00008086d00001D13* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 2 pci:v00008086d00001D14* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 3 pci:v00008086d00001D15* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 3 pci:v00008086d00001D16* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 4 pci:v00008086d00001D17* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 4 pci:v00008086d00001D18* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 5 pci:v00008086d00001D19* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 5 pci:v00008086d00001D1A* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 6 pci:v00008086d00001D1B* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 6 pci:v00008086d00001D1C* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 7 pci:v00008086d00001D1D* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 7 pci:v00008086d00001D1E* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 8 pci:v00008086d00001D1F* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 8 pci:v00008086d00001D20* ID_MODEL_FROM_DATABASE=C600/X79 series chipset High Definition Audio Controller pci:v00008086d00001D22* ID_MODEL_FROM_DATABASE=C600/X79 series chipset SMBus Host Controller pci:v00008086d00001D24* ID_MODEL_FROM_DATABASE=C600/X79 series chipset Thermal Management Controller pci:v00008086d00001D25* ID_MODEL_FROM_DATABASE=C600/X79 series chipset DMI to PCI Bridge pci:v00008086d00001D26* ID_MODEL_FROM_DATABASE=C600/X79 series chipset USB2 Enhanced Host Controller #1 pci:v00008086d00001D2D* ID_MODEL_FROM_DATABASE=C600/X79 series chipset USB2 Enhanced Host Controller #2 pci:v00008086d00001D33* ID_MODEL_FROM_DATABASE=C600/X79 series chipset LAN Controller pci:v00008086d00001D35* ID_MODEL_FROM_DATABASE=C600/X79 series chipset VECI Controller pci:v00008086d00001D3A* ID_MODEL_FROM_DATABASE=C600/X79 series chipset MEI Controller #1 pci:v00008086d00001D3B* ID_MODEL_FROM_DATABASE=C600/X79 series chipset MEI Controller #2 pci:v00008086d00001D3C* ID_MODEL_FROM_DATABASE=C600/X79 series chipset IDE-r Controller pci:v00008086d00001D3D* ID_MODEL_FROM_DATABASE=C600/X79 series chipset KT Controller pci:v00008086d00001D3E* ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Virtual Root Port pci:v00008086d00001D3F* ID_MODEL_FROM_DATABASE=C608/C606/X79 series chipset PCI Express Virtual Switch Port pci:v00008086d00001D40* ID_MODEL_FROM_DATABASE=C600/X79 series chipset LPC Controller pci:v00008086d00001D41* ID_MODEL_FROM_DATABASE=C600/X79 series chipset LPC Controller pci:v00008086d00001D50* ID_MODEL_FROM_DATABASE=C608 chipset Dual 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D54* ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D55* ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D58* ID_MODEL_FROM_DATABASE=C606 chipset Dual 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D59* ID_MODEL_FROM_DATABASE=C604/X79 series chipset 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D5A* ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA Storage Control Unit pci:v00008086d00001D5B* ID_MODEL_FROM_DATABASE=C602 chipset 4-Port SATA Storage Control Unit pci:v00008086d00001D5C* ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D5D* ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D5E* ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA Storage Control Unit pci:v00008086d00001D5F* ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA Storage Control Unit pci:v00008086d00001D60* ID_MODEL_FROM_DATABASE=C608 chipset Dual 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D64* ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D65* ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D68* ID_MODEL_FROM_DATABASE=C606 chipset Dual 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D69* ID_MODEL_FROM_DATABASE=C604/X79 series chipset 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D6A* ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA Storage Control Unit pci:v00008086d00001D6B* ID_MODEL_FROM_DATABASE=C602 chipset 4-Port SATA Storage Control Unit pci:v00008086d00001D6C* ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D6D* ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA/SAS Storage Control Unit pci:v00008086d00001D6E* ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA Storage Control Unit pci:v00008086d00001D6F* ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA Storage Control Unit pci:v00008086d00001D70* ID_MODEL_FROM_DATABASE=C600/X79 series chipset SMBus Controller 0 pci:v00008086d00001D71* ID_MODEL_FROM_DATABASE=C608/C606/X79 series chipset SMBus Controller 1 pci:v00008086d00001D72* ID_MODEL_FROM_DATABASE=C608 chipset SMBus Controller 2 pci:v00008086d00001D74* ID_MODEL_FROM_DATABASE=C608/C606/X79 series chipset PCI Express Upstream Port pci:v00008086d00001D76* ID_MODEL_FROM_DATABASE=C600/X79 series chipset Multi-Function Glue pci:v00008086d00001E00* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family 4-port SATA Controller [IDE mode] pci:v00008086d00001E01* ID_MODEL_FROM_DATABASE=7 Series Chipset Family 4-port SATA Controller [IDE mode] pci:v00008086d00001E02* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family 6-port SATA Controller [AHCI mode] pci:v00008086d00001E02sv00001043sd000084CA* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family 6-port SATA Controller [AHCI mode] (P8 series motherboard) pci:v00008086d00001E02sv00001849sd00001E02* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family 6-port SATA Controller [AHCI mode] (Motherboard) pci:v00008086d00001E03* ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] pci:v00008086d00001E03sv00001043sd0000108D* ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] (VivoBook X202EV) pci:v00008086d00001E03sv00001043sd00001477* ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] (N56VZ) pci:v00008086d00001E03sv00001043sd00001517* ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] (Zenbook Prime UX31A) pci:v00008086d00001E04* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SATA Controller [RAID mode] pci:v00008086d00001E05* ID_MODEL_FROM_DATABASE=7 Series Chipset SATA Controller [RAID mode] pci:v00008086d00001E06* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SATA Controller [RAID mode] pci:v00008086d00001E07* ID_MODEL_FROM_DATABASE=7 Series Chipset Family SATA Controller [RAID mode] pci:v00008086d00001E08* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family 2-port SATA Controller [IDE mode] pci:v00008086d00001E09* ID_MODEL_FROM_DATABASE=7 Series Chipset Family 2-port SATA Controller [IDE mode] pci:v00008086d00001E0E* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SATA Controller [RAID mode] pci:v00008086d00001E10* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 pci:v00008086d00001E10sv00001043sd0000108D* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 (VivoBook X202EV) pci:v00008086d00001E10sv00001043sd00001477* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 (N56VZ) pci:v00008086d00001E10sv00001043sd00001517* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 (Zenbook Prime UX31A) pci:v00008086d00001E10sv00001043sd000084CA* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 (P8H77-I Motherboard) pci:v00008086d00001E10sv00001849sd00001E10* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 (Motherboard) pci:v00008086d00001E12* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 2 pci:v00008086d00001E12sv00001043sd0000108D* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 2 (VivoBook X202EV) pci:v00008086d00001E12sv00001043sd00001477* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 2 (N56VZ) pci:v00008086d00001E12sv00001043sd00001517* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 2 (Zenbook Prime UX31A) pci:v00008086d00001E14* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 3 pci:v00008086d00001E16* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 4 pci:v00008086d00001E16sv00001043sd0000108D* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 4 (VivoBook X202EV) pci:v00008086d00001E16sv00001043sd00001477* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 4 (N56VZ) pci:v00008086d00001E16sv00001849sd00001618* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 4 (Z77 Extreme4 motherboard) pci:v00008086d00001E18* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 5 pci:v00008086d00001E18sv00001043sd000084CA* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 5 (P8H77-I Motherboard) pci:v00008086d00001E18sv00001849sd00001E18* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 5 (Motherboard) pci:v00008086d00001E1A* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 6 pci:v00008086d00001E1Asv00001849sd00001E1A* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 6 (Motherboard) pci:v00008086d00001E1C* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 7 pci:v00008086d00001E1E* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 8 pci:v00008086d00001E1Esv00001849sd00001E1E* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 8 (Motherboard) pci:v00008086d00001E20* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller pci:v00008086d00001E20sv00001043sd0000108D* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (VivoBook X202EV) pci:v00008086d00001E20sv00001043sd00001477* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (N56VZ) pci:v00008086d00001E20sv00001043sd00001517* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (Zenbook Prime UX31A) pci:v00008086d00001E20sv00001043sd00008415* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (P8H77-I Motherboard) pci:v00008086d00001E20sv00001043sd00008445* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (ASUS P8Z77-V LX Motherboard) pci:v00008086d00001E20sv00001849sd00001898* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (Z77 Extreme4 motherboard) pci:v00008086d00001E22* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller pci:v00008086d00001E22sv00001043sd0000108D* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller (VivoBook X202EV) pci:v00008086d00001E22sv00001043sd00001477* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller (N56VZ) pci:v00008086d00001E22sv00001043sd00001517* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller (Zenbook Prime UX31A) pci:v00008086d00001E22sv00001043sd000084CA* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller (P8 series motherboard) pci:v00008086d00001E22sv00001849sd00001E22* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller (Motherboard) pci:v00008086d00001E24* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family Thermal Management Controller pci:v00008086d00001E24sv00001043sd00001517* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family Thermal Management Controller (Zenbook Prime UX31A) pci:v00008086d00001E25* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family DMI to PCI Bridge pci:v00008086d00001E26* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 pci:v00008086d00001E26sv00001043sd0000108D* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 (VivoBook X202EV) pci:v00008086d00001E26sv00001043sd00001477* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 (N56VZ) pci:v00008086d00001E26sv00001043sd00001517* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 (Zenbook Prime UX31A) pci:v00008086d00001E26sv00001043sd000084CA* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 (P8 series motherboard) pci:v00008086d00001E26sv00001849sd00001E26* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 (Motherboard) pci:v00008086d00001E2D* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 pci:v00008086d00001E2Dsv00001043sd0000108D* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 (VivoBook X202EV) pci:v00008086d00001E2Dsv00001043sd00001477* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 (N56VZ) pci:v00008086d00001E2Dsv00001043sd00001517* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 (Zenbook Prime UX31A) pci:v00008086d00001E2Dsv00001043sd000084CA* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 (P8 series motherboard) pci:v00008086d00001E2Dsv00001849sd00001E2D* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 (Motherboard) pci:v00008086d00001E31* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller pci:v00008086d00001E31sv0000103Csd000017AB* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (ProBook 6570b) pci:v00008086d00001E31sv00001043sd0000108D* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (VivoBook X202EV) pci:v00008086d00001E31sv00001043sd00001477* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (N56VZ) pci:v00008086d00001E31sv00001043sd00001517* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (Zenbook Prime UX31A) pci:v00008086d00001E31sv00001043sd000084CA* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (P8 series motherboard) pci:v00008086d00001E31sv00001849sd00001E31* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (Motherboard) pci:v00008086d00001E33* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family LAN Controller pci:v00008086d00001E3A* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 pci:v00008086d00001E3Asv00001043sd0000108D* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 (VivoBook X202EV) pci:v00008086d00001E3Asv00001043sd00001477* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 (N56VZ) pci:v00008086d00001E3Asv00001043sd00001517* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 (Zenbook Prime UX31A) pci:v00008086d00001E3Asv00001043sd000084CA* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 (P8 series motherboard) pci:v00008086d00001E3Asv00001849sd00001E3A* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 (Motherboard) pci:v00008086d00001E3B* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #2 pci:v00008086d00001E3C* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family IDE-r Controller pci:v00008086d00001E3D* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family KT Controller pci:v00008086d00001E41* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E42* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E43* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E44* ID_MODEL_FROM_DATABASE=Z77 Express Chipset LPC Controller pci:v00008086d00001E44sv00001043sd000084CA* ID_MODEL_FROM_DATABASE=Z77 Express Chipset LPC Controller (P8 series motherboard) pci:v00008086d00001E44sv00001849sd00001E44* ID_MODEL_FROM_DATABASE=Z77 Express Chipset LPC Controller (Motherboard) pci:v00008086d00001E45* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E46* ID_MODEL_FROM_DATABASE=Z75 Express Chipset LPC Controller pci:v00008086d00001E47* ID_MODEL_FROM_DATABASE=Q77 Express Chipset LPC Controller pci:v00008086d00001E48* ID_MODEL_FROM_DATABASE=Q75 Express Chipset LPC Controller pci:v00008086d00001E49* ID_MODEL_FROM_DATABASE=B75 Express Chipset LPC Controller pci:v00008086d00001E4A* ID_MODEL_FROM_DATABASE=H77 Express Chipset LPC Controller pci:v00008086d00001E4Asv00001043sd000084CA* ID_MODEL_FROM_DATABASE=H77 Express Chipset LPC Controller (P8H77-I Motherboard) pci:v00008086d00001E4B* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E4C* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E4D* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E4E* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E4F* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E50* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E51* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E52* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E53* ID_MODEL_FROM_DATABASE=C216 Series Chipset LPC Controller pci:v00008086d00001E54* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E55* ID_MODEL_FROM_DATABASE=QM77 Express Chipset LPC Controller pci:v00008086d00001E56* ID_MODEL_FROM_DATABASE=QS77 Express Chipset LPC Controller pci:v00008086d00001E57* ID_MODEL_FROM_DATABASE=HM77 Express Chipset LPC Controller pci:v00008086d00001E58* ID_MODEL_FROM_DATABASE=UM77 Express Chipset LPC Controller pci:v00008086d00001E59* ID_MODEL_FROM_DATABASE=HM76 Express Chipset LPC Controller pci:v00008086d00001E59sv00001043sd00001477* ID_MODEL_FROM_DATABASE=HM76 Express Chipset LPC Controller (N56VZ) pci:v00008086d00001E59sv00001043sd00001517* ID_MODEL_FROM_DATABASE=HM76 Express Chipset LPC Controller (Zenbook Prime UX31A) pci:v00008086d00001E5A* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E5B* ID_MODEL_FROM_DATABASE=UM77 Express Chipset LPC Controller pci:v00008086d00001E5C* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E5D* ID_MODEL_FROM_DATABASE=HM75 Express Chipset LPC Controller pci:v00008086d00001E5E* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001E5Esv00001043sd0000108D* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller (VivoBook X202EV) pci:v00008086d00001E5F* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller pci:v00008086d00001F00* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F01* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F02* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F03* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F04* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F05* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F06* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F07* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F08* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F09* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F0A* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F0B* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F0C* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F0D* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F0E* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F0F* ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router pci:v00008086d00001F10* ID_MODEL_FROM_DATABASE=Atom processor C2000 PCIe Root Port 1 pci:v00008086d00001F11* ID_MODEL_FROM_DATABASE=Atom processor C2000 PCIe Root Port 2 pci:v00008086d00001F12* ID_MODEL_FROM_DATABASE=Atom processor C2000 PCIe Root Port 3 pci:v00008086d00001F13* ID_MODEL_FROM_DATABASE=Atom processor C2000 PCIe Root Port 4 pci:v00008086d00001F14* ID_MODEL_FROM_DATABASE=Atom processor C2000 RAS pci:v00008086d00001F15* ID_MODEL_FROM_DATABASE=Atom processor C2000 SMBus 2.0 pci:v00008086d00001F16* ID_MODEL_FROM_DATABASE=Atom processor C2000 RCEC pci:v00008086d00001F18* ID_MODEL_FROM_DATABASE=Atom processor C2000 QAT pci:v00008086d00001F19* ID_MODEL_FROM_DATABASE=Atom processor C2000 QAT pci:v00008086d00001F20* ID_MODEL_FROM_DATABASE=Atom processor C2000 4-Port IDE SATA2 Controller pci:v00008086d00001F21* ID_MODEL_FROM_DATABASE=Atom processor C2000 4-Port IDE SATA2 Controller pci:v00008086d00001F22* ID_MODEL_FROM_DATABASE=Atom processor C2000 AHCI SATA2 Controller pci:v00008086d00001F23* ID_MODEL_FROM_DATABASE=Atom processor C2000 AHCI SATA2 Controller pci:v00008086d00001F24* ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller pci:v00008086d00001F25* ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller pci:v00008086d00001F26* ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller pci:v00008086d00001F27* ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller pci:v00008086d00001F2C* ID_MODEL_FROM_DATABASE=Atom processor C2000 USB Enhanced Host Controller pci:v00008086d00001F2E* ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller pci:v00008086d00001F2F* ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller pci:v00008086d00001F30* ID_MODEL_FROM_DATABASE=Atom processor C2000 2-Port IDE SATA3 Controller pci:v00008086d00001F31* ID_MODEL_FROM_DATABASE=Atom processor C2000 2-Port IDE SATA3 Controller pci:v00008086d00001F32* ID_MODEL_FROM_DATABASE=Atom processor C2000 AHCI SATA3 Controller pci:v00008086d00001F33* ID_MODEL_FROM_DATABASE=Atom processor C2000 AHCI SATA3 Controller pci:v00008086d00001F34* ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller pci:v00008086d00001F35* ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller pci:v00008086d00001F36* ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller pci:v00008086d00001F37* ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller pci:v00008086d00001F38* ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU pci:v00008086d00001F39* ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU pci:v00008086d00001F3A* ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU pci:v00008086d00001F3B* ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU pci:v00008086d00001F3C* ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU SMBus pci:v00008086d00001F3E* ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller pci:v00008086d00001F3F* ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller pci:v00008086d00001F40* ID_MODEL_FROM_DATABASE=Ethernet Connection I354 1.0 GbE Backplane pci:v00008086d00001F40sv00001028sd000005F1* ID_MODEL_FROM_DATABASE=Ethernet Connection I354 1.0 GbE Backplane pci:v00008086d00001F41* ID_MODEL_FROM_DATABASE=Ethernet Connection I354 pci:v00008086d00001F42* ID_MODEL_FROM_DATABASE=Atom processor C2000 GbE pci:v00008086d00001F44* ID_MODEL_FROM_DATABASE=Atom processor C2000 GbE Virtual Function pci:v00008086d00001F45* ID_MODEL_FROM_DATABASE=Ethernet Connection I354 2.5 GbE Backplane pci:v00008086d00002014* ID_MODEL_FROM_DATABASE=Sky Lake-E Ubox Registers pci:v00008086d00002015* ID_MODEL_FROM_DATABASE=Sky Lake-E Ubox Registers pci:v00008086d00002016* ID_MODEL_FROM_DATABASE=Sky Lake-E Ubox Registers pci:v00008086d00002018* ID_MODEL_FROM_DATABASE=Sky Lake-E M2PCI Registers pci:v00008086d0000201A* ID_MODEL_FROM_DATABASE=Sky Lake-E Non-Transparent Bridge Registers pci:v00008086d0000201C* ID_MODEL_FROM_DATABASE=Sky Lake-E Non-Transparent Bridge Registers pci:v00008086d00002021* ID_MODEL_FROM_DATABASE=Sky Lake-E CBDMA Registers pci:v00008086d00002024* ID_MODEL_FROM_DATABASE=Sky Lake-E MM/Vt-d Configuration Registers pci:v00008086d00002030* ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port 1A pci:v00008086d00002031* ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port 1B pci:v00008086d00002032* ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port 1C pci:v00008086d00002033* ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port 1D pci:v00008086d00002035* ID_MODEL_FROM_DATABASE=Sky Lake-E RAS Configuration Registers pci:v00008086d0000204C* ID_MODEL_FROM_DATABASE=Sky Lake-E M3KTI Registers pci:v00008086d0000204D* ID_MODEL_FROM_DATABASE=Sky Lake-E M3KTI Registers pci:v00008086d0000204E* ID_MODEL_FROM_DATABASE=Sky Lake-E M3KTI Registers pci:v00008086d00002054* ID_MODEL_FROM_DATABASE=Sky Lake-E CHA Registers pci:v00008086d00002055* ID_MODEL_FROM_DATABASE=Sky Lake-E CHA Registers pci:v00008086d00002056* ID_MODEL_FROM_DATABASE=Sky Lake-E CHA Registers pci:v00008086d00002057* ID_MODEL_FROM_DATABASE=Sky Lake-E CHA Registers pci:v00008086d00002068* ID_MODEL_FROM_DATABASE=Sky Lake-E DDRIO Registers pci:v00008086d00002069* ID_MODEL_FROM_DATABASE=Sky Lake-E DDRIO Registers pci:v00008086d0000206A* ID_MODEL_FROM_DATABASE=Sky Lake-E IOxAPIC Configuration Registers pci:v00008086d0000206E* ID_MODEL_FROM_DATABASE=Sky Lake-E DDRIO Registers pci:v00008086d0000206F* ID_MODEL_FROM_DATABASE=Sky Lake-E DDRIO Registers pci:v00008086d00002078* ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers pci:v00008086d0000207A* ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers pci:v00008086d00002080* ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers pci:v00008086d00002081* ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers pci:v00008086d00002082* ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers pci:v00008086d00002083* ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers pci:v00008086d00002084* ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers pci:v00008086d00002085* ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers pci:v00008086d00002086* ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers pci:v00008086d0000208D* ID_MODEL_FROM_DATABASE=Sky Lake-E CHA Registers pci:v00008086d0000208E* ID_MODEL_FROM_DATABASE=Sky Lake-E CHA Registers pci:v00008086d00002250* ID_MODEL_FROM_DATABASE=Xeon Phi coprocessor 5100 series pci:v00008086d0000225C* ID_MODEL_FROM_DATABASE=Xeon Phi coprocessor SE10/7120 series pci:v00008086d0000225D* ID_MODEL_FROM_DATABASE=Xeon Phi coprocessor 3120 series pci:v00008086d0000225E* ID_MODEL_FROM_DATABASE=Xeon Phi coprocessor 31S1 pci:v00008086d00002310* ID_MODEL_FROM_DATABASE=DH89xxCC LPC Controller pci:v00008086d00002323* ID_MODEL_FROM_DATABASE=DH89xxCC 4 Port SATA AHCI Controller pci:v00008086d00002330* ID_MODEL_FROM_DATABASE=DH89xxCC SMBus Controller pci:v00008086d00002331* ID_MODEL_FROM_DATABASE=DH89xxCC Chap Counter pci:v00008086d00002332* ID_MODEL_FROM_DATABASE=DH89xxCC Thermal Subsystem pci:v00008086d00002334* ID_MODEL_FROM_DATABASE=DH89xxCC USB2 Enhanced Host Controller #1 pci:v00008086d00002335* ID_MODEL_FROM_DATABASE=DH89xxCC USB2 Enhanced Host Controller #1 pci:v00008086d00002342* ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #1 pci:v00008086d00002343* ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #1 pci:v00008086d00002344* ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #2 pci:v00008086d00002345* ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #2 pci:v00008086d00002346* ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #3 pci:v00008086d00002347* ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #3 pci:v00008086d00002348* ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #4 pci:v00008086d00002349* ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #4 pci:v00008086d00002360* ID_MODEL_FROM_DATABASE=DH89xxCC Watchdog Timer pci:v00008086d00002364* ID_MODEL_FROM_DATABASE=DH89xxCC MEI 0 pci:v00008086d00002365* ID_MODEL_FROM_DATABASE=DH89xxCC MEI 1 pci:v00008086d00002390* ID_MODEL_FROM_DATABASE=DH895XCC Series LPC Controller pci:v00008086d000023A1* ID_MODEL_FROM_DATABASE=DH895XCC Series 2-Port SATA Controller [IDE Mode] pci:v00008086d000023A3* ID_MODEL_FROM_DATABASE=DH895XCC Series 4-Port SATA Controller [AHCI Mode] pci:v00008086d000023A6* ID_MODEL_FROM_DATABASE=DH895XCC Series 2-Port SATA Controller [IDE Mode] pci:v00008086d000023B0* ID_MODEL_FROM_DATABASE=DH895XCC Series SMBus Controller pci:v00008086d000023B1* ID_MODEL_FROM_DATABASE=DH895XCC Series CHAP Counter pci:v00008086d000023B2* ID_MODEL_FROM_DATABASE=DH895XCC Series Thermal Management Controller pci:v00008086d000023B4* ID_MODEL_FROM_DATABASE=DH895XCC Series USB2 Enhanced Host Controller #1 pci:v00008086d000023B5* ID_MODEL_FROM_DATABASE=DH895XCC Series USB2 Enhanced Host Controller #1 pci:v00008086d000023C2* ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #1 pci:v00008086d000023C3* ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #1 pci:v00008086d000023C4* ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #2 pci:v00008086d000023C5* ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #2 pci:v00008086d000023C6* ID_MODEL_FROM_DATABASE=CDH895XCC Series PCI Express Root Port #3 pci:v00008086d000023C7* ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #3 pci:v00008086d000023C8* ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #4 pci:v00008086d000023C9* ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #4 pci:v00008086d000023E0* ID_MODEL_FROM_DATABASE=DH895XCC Series Watchdog Timer pci:v00008086d000023E4* ID_MODEL_FROM_DATABASE=DH895XCC Series MEI Controller #1 pci:v00008086d000023E5* ID_MODEL_FROM_DATABASE=DH895XCC Series MEI Controller #2 pci:v00008086d00002410* ID_MODEL_FROM_DATABASE=82801AA ISA Bridge (LPC) pci:v00008086d00002411* ID_MODEL_FROM_DATABASE=82801AA IDE Controller pci:v00008086d00002412* ID_MODEL_FROM_DATABASE=82801AA USB Controller pci:v00008086d00002413* ID_MODEL_FROM_DATABASE=82801AA SMBus Controller pci:v00008086d00002415* ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller pci:v00008086d00002415sv00001028sd00000095* ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (Precision Workstation 220 Integrated Digital Audio) pci:v00008086d00002415sv00001028sd000000B4* ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (OptiPlex GX110) pci:v00008086d00002415sv0000110Asd00000051* ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (Activy 2xx) pci:v00008086d00002415sv000011D4sd00000040* ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (SoundMAX Integrated Digital Audio) pci:v00008086d00002415sv000011D4sd00000048* ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (SoundMAX Integrated Digital Audio) pci:v00008086d00002415sv000011D4sd00005340* ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (SoundMAX Integrated Digital Audio) pci:v00008086d00002415sv00001734sd00001025* ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (Activy 3xx) pci:v00008086d00002415sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (QEMU Virtual Machine) pci:v00008086d00002416* ID_MODEL_FROM_DATABASE=82801AA AC'97 Modem Controller pci:v00008086d00002418* ID_MODEL_FROM_DATABASE=82801AA PCI Bridge pci:v00008086d00002420* ID_MODEL_FROM_DATABASE=82801AB ISA Bridge (LPC) pci:v00008086d00002421* ID_MODEL_FROM_DATABASE=82801AB IDE Controller pci:v00008086d00002422* ID_MODEL_FROM_DATABASE=82801AB USB Controller pci:v00008086d00002423* ID_MODEL_FROM_DATABASE=82801AB SMBus Controller pci:v00008086d00002425* ID_MODEL_FROM_DATABASE=82801AB AC'97 Audio Controller pci:v00008086d00002425sv000011D4sd00000040* ID_MODEL_FROM_DATABASE=82801AB AC'97 Audio Controller (SoundMAX Integrated Digital Audio) pci:v00008086d00002425sv000011D4sd00000048* ID_MODEL_FROM_DATABASE=82801AB AC'97 Audio Controller (SoundMAX Integrated Digital Audio) pci:v00008086d00002426* ID_MODEL_FROM_DATABASE=82801AB AC'97 Modem Controller pci:v00008086d00002428* ID_MODEL_FROM_DATABASE=82801AB PCI Bridge pci:v00008086d00002440* ID_MODEL_FROM_DATABASE=82801BA ISA Bridge (LPC) pci:v00008086d00002440sv00008086sd00005744* ID_MODEL_FROM_DATABASE=82801BA ISA Bridge (LPC) (S845WD1-E) pci:v00008086d00002442* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 pci:v00008086d00002442sv00001014sd000001C6* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Netvista A40/A40p) pci:v00008086d00002442sv00001025sd00001016* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Travelmate 612 TX) pci:v00008086d00002442sv00001028sd000000C7* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Dimension 8100) pci:v00008086d00002442sv00001028sd000000D8* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Precision 530) pci:v00008086d00002442sv00001028sd0000010E* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Optiplex GX240) pci:v00008086d00002442sv0000103Csd0000126F* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (e-pc 40) pci:v00008086d00002442sv00001043sd00008027* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (TUSL2-C Mainboard) pci:v00008086d00002442sv0000104Dsd000080DF* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Vaio PCG-FX403) pci:v00008086d00002442sv0000147Bsd00000505* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (BL7 motherboard) pci:v00008086d00002442sv0000147Bsd00000507* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (TH7II-RAID) pci:v00008086d00002442sv00008086sd00004532* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Desktop Board D815EEA2/D815EFV) pci:v00008086d00002442sv00008086sd00004557* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (D815EGEW Mainboard) pci:v00008086d00002442sv00008086sd00005744* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (S845WD1-E mainboard) pci:v00008086d00002443* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller pci:v00008086d00002443sv00001014sd000001C6* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Netvista A40/A40p) pci:v00008086d00002443sv00001025sd00001016* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Travelmate 612 TX) pci:v00008086d00002443sv00001028sd000000C7* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Dimension 8100) pci:v00008086d00002443sv00001028sd000000D8* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Precision 530) pci:v00008086d00002443sv00001028sd0000010E* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Optiplex GX240) pci:v00008086d00002443sv0000103Csd0000126F* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (e-pc 40) pci:v00008086d00002443sv00001043sd00008027* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (TUSL2-C Mainboard) pci:v00008086d00002443sv0000104Dsd000080DF* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Vaio PCG-FX403) pci:v00008086d00002443sv0000147Bsd00000505* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (BL7 motherboard) pci:v00008086d00002443sv0000147Bsd00000507* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (TH7II-RAID) pci:v00008086d00002443sv000015D9sd00003280* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Supermicro P4SBE Mainboard) pci:v00008086d00002443sv00008086sd00004532* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Desktop Board D815EEA2/D815EFV) pci:v00008086d00002443sv00008086sd00004557* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (D815EGEW Mainboard) pci:v00008086d00002443sv00008086sd00005744* ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (S845WD1-E mainboard) pci:v00008086d00002444* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 pci:v00008086d00002444sv00001025sd00001016* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (Travelmate 612 TX) pci:v00008086d00002444sv00001028sd000000C7* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (Dimension 8100) pci:v00008086d00002444sv00001028sd000000D8* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (Precision 530) pci:v00008086d00002444sv00001028sd0000010E* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (Optiplex GX240) pci:v00008086d00002444sv0000103Csd0000126F* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (e-pc 40) pci:v00008086d00002444sv00001043sd00008027* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (TUSL2-C Mainboard) pci:v00008086d00002444sv0000104Dsd000080DF* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (Vaio PCG-FX403) pci:v00008086d00002444sv0000147Bsd00000505* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (BL7 motherboard) pci:v00008086d00002444sv0000147Bsd00000507* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (TH7II-RAID) pci:v00008086d00002444sv00008086sd00004532* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (Desktop Board D815EEA2/D815EFV) pci:v00008086d00002444sv00008086sd00005744* ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (S845WD1-E mainboard) pci:v00008086d00002445* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller pci:v00008086d00002445sv00000E11sd0000000B* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Compaq Deskpro EN Audio) pci:v00008086d00002445sv00000E11sd00000088* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Evo D500) pci:v00008086d00002445sv00001014sd000001C6* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Netvista A40/A40p) pci:v00008086d00002445sv00001025sd00001016* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Travelmate 612 TX) pci:v00008086d00002445sv00001028sd000000D8* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Precision 530) pci:v00008086d00002445sv0000103Csd0000126F* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (e-pc 40) pci:v00008086d00002445sv0000104Dsd000080DF* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Vaio PCG-FX403) pci:v00008086d00002445sv00001462sd00003370* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (STAC9721 AC) pci:v00008086d00002445sv0000147Bsd00000505* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (BL7 motherboard) pci:v00008086d00002445sv0000147Bsd00000507* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (TH7II-RAID) pci:v00008086d00002445sv00008086sd00004557* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (D815EGEW Mainboard) pci:v00008086d00002445sv00008086sd00004656* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Desktop Board D815EFV) pci:v00008086d00002446* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Modem Controller pci:v00008086d00002446sv00001025sd00001016* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Modem Controller (Travelmate 612 TX) pci:v00008086d00002446sv0000104Dsd000080DF* ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Modem Controller (Vaio PCG-FX403) pci:v00008086d00002448* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge pci:v00008086d00002448sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Latitude E6410) pci:v00008086d00002448sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Latitude E6510) pci:v00008086d00002448sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Compaq nw8240 Mobile Workstation) pci:v00008086d00002448sv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (NX6110/NC6120) pci:v00008086d00002448sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Compaq nx9420 Notebook) pci:v00008086d00002448sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Compaq nw8440) pci:v00008086d00002448sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Compaq 6910p) pci:v00008086d00002448sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (VAIO VGN-NR120E) pci:v00008086d00002448sv0000105Bsd00000D7C* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (D270S/D250S Motherboard) pci:v00008086d00002448sv00001071sd00008209* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d00002448sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (P30 notebook) pci:v00008086d00002448sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (R730 Laptop) pci:v00008086d00002448sv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Notebook N150P) pci:v00008086d00002448sv00001458sd00005000* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (GA-D525TUD) pci:v00008086d00002448sv00001734sd00001055* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Amilo M1420) pci:v00008086d00002448sv000017AAsd000020AE* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (ThinkPad T61/R61) pci:v00008086d00002448sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00002448sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002448sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Desktop Board D425KT) pci:v00008086d00002448sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (CCG-RUMBA) pci:v00008086d00002449* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller pci:v00008086d00002449sv00000E11sd00000012* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VM) pci:v00008086d00002449sv00000E11sd00000091* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00001014sd000001CE* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00001014sd000001DC* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00001014sd000001EB* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00001014sd000001EC* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00001014sd00000202* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00001014sd00000205* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00001014sd00000217* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00001014sd00000234* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00001014sd0000023D* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00001014sd00000244* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00001014sd00000245* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00001014sd00000265* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (PRO/100 VE Desktop Connection) pci:v00008086d00002449sv00001014sd00000267* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (PRO/100 VE Desktop Connection) pci:v00008086d00002449sv00001014sd0000026A* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (PRO/100 VE Desktop Connection) pci:v00008086d00002449sv0000109Fsd0000315D* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv0000109Fsd00003181* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00001179sd0000FF01* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (PRO/100 VE Network Connection) pci:v00008086d00002449sv00001186sd00007801* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv0000144Dsd00002602* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (HomePNA 1M CNR) pci:v00008086d00002449sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (QEMU Virtual Machine) pci:v00008086d00002449sv00008086sd00003010* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00008086sd00003011* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VM) pci:v00008086d00002449sv00008086sd00003012* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (82562EH based Phoneline) pci:v00008086d00002449sv00008086sd00003013* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) pci:v00008086d00002449sv00008086sd00003014* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VM) pci:v00008086d00002449sv00008086sd00003015* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (82562EH based Phoneline) pci:v00008086d00002449sv00008086sd00003016* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 P Mobile Combo) pci:v00008086d00002449sv00008086sd00003017* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 P Mobile) pci:v00008086d00002449sv00008086sd00003018* ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100) pci:v00008086d0000244A* ID_MODEL_FROM_DATABASE=82801BAM IDE U100 Controller pci:v00008086d0000244Asv00001025sd00001016* ID_MODEL_FROM_DATABASE=82801BAM IDE U100 Controller (Travelmate 612TX) pci:v00008086d0000244Asv0000104Dsd000080DF* ID_MODEL_FROM_DATABASE=82801BAM IDE U100 Controller (Vaio PCG-FX403) pci:v00008086d0000244B* ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller pci:v00008086d0000244Bsv00001014sd000001C6* ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Netvista A40/A40p) pci:v00008086d0000244Bsv00001028sd000000C7* ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Dimension 8100) pci:v00008086d0000244Bsv00001028sd000000D8* ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Precision 530) pci:v00008086d0000244Bsv00001028sd0000010E* ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Optiplex GX240) pci:v00008086d0000244Bsv0000103Csd0000126F* ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (e-pc 40) pci:v00008086d0000244Bsv00001043sd00008027* ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (TUSL2-C Mainboard) pci:v00008086d0000244Bsv0000147Bsd00000505* ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (BL7 motherboard) pci:v00008086d0000244Bsv0000147Bsd00000507* ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (TH7II-RAID) pci:v00008086d0000244Bsv000015D9sd00003280* ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Supermicro P4SBE Mainboard) pci:v00008086d0000244Bsv00008086sd00004532* ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Desktop Board D815EEA2/D815EFV) pci:v00008086d0000244Bsv00008086sd00004557* ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (D815EGEW Mainboard) pci:v00008086d0000244Bsv00008086sd00005744* ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (S845WD1-E mainboard) pci:v00008086d0000244C* ID_MODEL_FROM_DATABASE=82801BAM ISA Bridge (LPC) pci:v00008086d0000244E* ID_MODEL_FROM_DATABASE=82801 PCI Bridge pci:v00008086d0000244Esv00001014sd00000267* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (NetVista A30p) pci:v00008086d0000244Esv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Inspiron 530) pci:v00008086d0000244Esv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Optiplex 755) pci:v00008086d0000244Esv00001028sd000002DA* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (OptiPlex 980) pci:v00008086d0000244Esv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Pavilion A1512X) pci:v00008086d0000244Esv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Asus IPIBL-LB Motherboard) pci:v00008086d0000244Esv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (ProLiant DL140 G3) pci:v00008086d0000244Esv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (ProLiant ML150 G6 Server) pci:v00008086d0000244Esv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (P5K PRO Motherboard) pci:v00008086d0000244Esv00001043sd0000844D* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (P8 series motherboard) pci:v00008086d0000244Esv00001458sd00005000* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Motherboard) pci:v00008086d0000244Esv00001462sd00007418* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Wind PC MS-7418) pci:v00008086d0000244Esv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (C7SIM-Q Motherboard) pci:v00008086d0000244Esv000015D9sd00009680* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (X7DBN Motherboard) pci:v00008086d0000244Esv00001775sd000011CC* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (CC11/CL11) pci:v00008086d0000244Esv00008086sd00007270* ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Server Board S1200BTS) pci:v00008086d00002450* ID_MODEL_FROM_DATABASE=82801E ISA Bridge (LPC) pci:v00008086d00002452* ID_MODEL_FROM_DATABASE=82801E USB Controller pci:v00008086d00002453* ID_MODEL_FROM_DATABASE=82801E SMBus Controller pci:v00008086d00002459* ID_MODEL_FROM_DATABASE=82801E Ethernet Controller 0 pci:v00008086d0000245B* ID_MODEL_FROM_DATABASE=82801E IDE U100 Controller pci:v00008086d0000245D* ID_MODEL_FROM_DATABASE=82801E Ethernet Controller 1 pci:v00008086d0000245E* ID_MODEL_FROM_DATABASE=82801E PCI Bridge pci:v00008086d00002480* ID_MODEL_FROM_DATABASE=82801CA LPC Interface Controller pci:v00008086d00002482* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 pci:v00008086d00002482sv00000E11sd00000030* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (Evo N600c) pci:v00008086d00002482sv00001014sd00000220* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (ThinkPad A/T/X Series) pci:v00008086d00002482sv0000104Dsd000080E7* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) pci:v00008086d00002482sv000015D9sd00003480* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (P4DP6) pci:v00008086d00002482sv00008086sd00001958* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (vpr Matrix 170B4) pci:v00008086d00002482sv00008086sd00003424* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (SE7501HG2 Mainboard) pci:v00008086d00002482sv00008086sd00004541* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (Latitude C640) pci:v00008086d00002483* ID_MODEL_FROM_DATABASE=82801CA/CAM SMBus Controller pci:v00008086d00002483sv00001014sd00000220* ID_MODEL_FROM_DATABASE=82801CA/CAM SMBus Controller (ThinkPad A/T/X Series) pci:v00008086d00002483sv0000104Dsd000080E7* ID_MODEL_FROM_DATABASE=82801CA/CAM SMBus Controller (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) pci:v00008086d00002483sv000015D9sd00003480* ID_MODEL_FROM_DATABASE=82801CA/CAM SMBus Controller (P4DP6) pci:v00008086d00002483sv00008086sd00001958* ID_MODEL_FROM_DATABASE=82801CA/CAM SMBus Controller (vpr Matrix 170B4) pci:v00008086d00002484* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #2 pci:v00008086d00002484sv00000E11sd00000030* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #2 (Evo N600c) pci:v00008086d00002484sv00001014sd00000220* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #2 (ThinkPad A/T/X Series) pci:v00008086d00002484sv0000104Dsd000080E7* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #2 (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) pci:v00008086d00002484sv000015D9sd00003480* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #2 (P4DP6) pci:v00008086d00002484sv00008086sd00001958* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #2 (vpr Matrix 170B4) pci:v00008086d00002485* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller pci:v00008086d00002485sv00001013sd00005959* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (Crystal WMD Audio Codec) pci:v00008086d00002485sv00001014sd00000222* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (ThinkPad A30/A30p/T23) pci:v00008086d00002485sv00001014sd00000508* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (ThinkPad T30) pci:v00008086d00002485sv00001014sd0000051C* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (ThinkPad A/T/X Series) pci:v00008086d00002485sv00001043sd00001583* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (L3C (SPDIF)) pci:v00008086d00002485sv00001043sd00001623* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (L2B (no SPDIF)) pci:v00008086d00002485sv00001043sd00001643* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (L3F) pci:v00008086d00002485sv0000104Dsd000080E7* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) pci:v00008086d00002485sv0000144Dsd0000C006* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (vpr Matrix 170B4) pci:v00008086d00002486* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller pci:v00008086d00002486sv00001014sd00000223* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (ThinkPad A/T/X Series) pci:v00008086d00002486sv00001014sd00000503* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (ThinkPad R31) pci:v00008086d00002486sv00001014sd0000051A* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (ThinkPad A/T/X Series) pci:v00008086d00002486sv0000101Fsd00001025* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (620 Series) pci:v00008086d00002486sv00001043sd00001496* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (PCtel HSP56 MR) pci:v00008086d00002486sv0000104Dsd000080E7* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) pci:v00008086d00002486sv0000134Dsd00004C21* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (Dell Inspiron 2100 internal modem) pci:v00008086d00002486sv0000144Dsd00002115* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (vpr Matrix 170B4 internal modem) pci:v00008086d00002486sv000014F1sd00005421* ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (MD56ORD V.92 MDC Modem) pci:v00008086d00002487* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #3 pci:v00008086d00002487sv00000E11sd00000030* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #3 (Evo N600c) pci:v00008086d00002487sv00001014sd00000220* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #3 (ThinkPad A/T/X Series) pci:v00008086d00002487sv0000104Dsd000080E7* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #3 (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) pci:v00008086d00002487sv000015D9sd00003480* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #3 (P4DP6) pci:v00008086d00002487sv00008086sd00001958* ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #3 (vpr Matrix 170B4) pci:v00008086d0000248A* ID_MODEL_FROM_DATABASE=82801CAM IDE U100 Controller pci:v00008086d0000248Asv00000E11sd00000030* ID_MODEL_FROM_DATABASE=82801CAM IDE U100 Controller (Evo N600c) pci:v00008086d0000248Asv00001014sd00000220* ID_MODEL_FROM_DATABASE=82801CAM IDE U100 Controller (ThinkPad A/T/X Series) pci:v00008086d0000248Asv0000104Dsd000080E7* ID_MODEL_FROM_DATABASE=82801CAM IDE U100 Controller (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) pci:v00008086d0000248Asv00008086sd00001958* ID_MODEL_FROM_DATABASE=82801CAM IDE U100 Controller (vpr Matrix 170B4) pci:v00008086d0000248Asv00008086sd00004541* ID_MODEL_FROM_DATABASE=82801CAM IDE U100 Controller (Latitude C640) pci:v00008086d0000248B* ID_MODEL_FROM_DATABASE=82801CA Ultra ATA Storage Controller pci:v00008086d0000248Bsv000015D9sd00003480* ID_MODEL_FROM_DATABASE=82801CA Ultra ATA Storage Controller (P4DP6) pci:v00008086d0000248C* ID_MODEL_FROM_DATABASE=82801CAM ISA Bridge (LPC) pci:v00008086d000024C0* ID_MODEL_FROM_DATABASE=82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge pci:v00008086d000024C0sv00001014sd00000267* ID_MODEL_FROM_DATABASE=82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge (NetVista A30p) pci:v00008086d000024C0sv00001462sd00005800* ID_MODEL_FROM_DATABASE=82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge (845PE Max (MS-6580)) pci:v00008086d000024C1* ID_MODEL_FROM_DATABASE=82801DBL (ICH4-L) IDE Controller pci:v00008086d000024C2* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 pci:v00008086d000024C2sv00001014sd00000267* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (NetVista A30p) pci:v00008086d000024C2sv00001014sd0000052D* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (ThinkPad) pci:v00008086d000024C2sv00001025sd0000005A* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (TravelMate 290) pci:v00008086d000024C2sv00001025sd00000064* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) pci:v00008086d000024C2sv00001028sd00000126* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Optiplex GX260) pci:v00008086d000024C2sv00001028sd00000160* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Dimension 2400) pci:v00008086d000024C2sv00001028sd00000163* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Latitude D505) pci:v00008086d000024C2sv00001028sd0000018D* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Inspiron 700m/710m) pci:v00008086d000024C2sv00001028sd00000196* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Inspiron 5160) pci:v00008086d000024C2sv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (NC8000 laptop) pci:v00008086d000024C2sv0000103Csd00000890* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (NC6000 laptop) pci:v00008086d000024C2sv0000103Csd000008B0* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (tc1100 tablet) pci:v00008086d000024C2sv00001043sd00008089* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (P4B533) pci:v00008086d000024C2sv00001071sd00008160* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (MIM2000) pci:v00008086d000024C2sv0000114Asd00000582* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (PC8 onboard USB 1.x) pci:v00008086d000024C2sv0000144Dsd0000C005* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (X10 Laptop) pci:v00008086d000024C2sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (P30/P35 notebook) pci:v00008086d000024C2sv00001462sd00005800* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (845PE Max (MS-6580)) pci:v00008086d000024C2sv00001509sd00002990* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Averatec 5110H laptop) pci:v00008086d000024C2sv00001734sd00001004* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (D1451 Mainboard (SCENIC N300, i845GV)) pci:v00008086d000024C2sv00001734sd00001055* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Amilo M1420) pci:v00008086d000024C2sv00004C53sd00001090* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Cx9 / Vx9 mainboard) pci:v00008086d000024C2sv00008086sd000024C2* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Latitude X300) pci:v00008086d000024C2sv00008086sd00004541* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Latitude D400/D500) pci:v00008086d000024C2sv0000E4BFsd00000CC9* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (CC9-SAMBA) pci:v00008086d000024C2sv0000E4BFsd00000CD2* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (CD2-BEBOP) pci:v00008086d000024C3* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller pci:v00008086d000024C3sv00001014sd00000267* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (NetVista A30p) pci:v00008086d000024C3sv00001014sd0000052D* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (ThinkPad) pci:v00008086d000024C3sv00001025sd0000005A* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (TravelMate 290) pci:v00008086d000024C3sv00001025sd00000064* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) pci:v00008086d000024C3sv00001028sd00000126* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Optiplex GX260) pci:v00008086d000024C3sv00001028sd0000014F* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Latitude X300) pci:v00008086d000024C3sv00001028sd00000160* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Dimension 2400) pci:v00008086d000024C3sv00001028sd0000018D* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Inspiron 700m/710m) pci:v00008086d000024C3sv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (NC8000 laptop) pci:v00008086d000024C3sv0000103Csd00000890* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (NC6000 laptop) pci:v00008086d000024C3sv0000103Csd000008B0* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (tc1100 tablet) pci:v00008086d000024C3sv00001071sd00008160* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (MIM2000) pci:v00008086d000024C3sv0000114Asd00000582* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (PC8 onboard SMbus) pci:v00008086d000024C3sv0000144Dsd0000C005* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (X10 Laptop) pci:v00008086d000024C3sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (P30/P35 notebook) pci:v00008086d000024C3sv00001458sd000024C2* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (GA-8PE667 Ultra) pci:v00008086d000024C3sv00001462sd00005800* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (845PE Max (MS-6580)) pci:v00008086d000024C3sv00001734sd00001004* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (D1451 Mainboard (SCENIC N300, i845GV)) pci:v00008086d000024C3sv00001734sd00001055* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Amilo M1420) pci:v00008086d000024C3sv00004C53sd00001090* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Cx9 / Vx9 mainboard) pci:v00008086d000024C3sv0000E4BFsd00000CC9* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (CC9-SAMBA) pci:v00008086d000024C3sv0000E4BFsd00000CD2* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (CD2-BEBOP) pci:v00008086d000024C4* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 pci:v00008086d000024C4sv00001014sd00000267* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (NetVista A30p) pci:v00008086d000024C4sv00001014sd0000052D* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (ThinkPad) pci:v00008086d000024C4sv00001025sd0000005A* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (TravelMate 290) pci:v00008086d000024C4sv00001025sd00000064* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) pci:v00008086d000024C4sv00001028sd00000126* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Optiplex GX260) pci:v00008086d000024C4sv00001028sd00000160* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Dimension 2400) pci:v00008086d000024C4sv00001028sd00000163* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Latitude D505) pci:v00008086d000024C4sv00001028sd0000018D* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Inspiron 700m/710m) pci:v00008086d000024C4sv00001028sd00000196* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Inspiron 5160) pci:v00008086d000024C4sv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (NC8000 laptop) pci:v00008086d000024C4sv0000103Csd00000890* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (NC6000 laptop) pci:v00008086d000024C4sv0000103Csd000008B0* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (tc1100 tablet) pci:v00008086d000024C4sv00001043sd00008089* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (P4B533) pci:v00008086d000024C4sv00001071sd00008160* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (MIM2000) pci:v00008086d000024C4sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (P30/P35 notebook) pci:v00008086d000024C4sv00001462sd00005800* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (845PE Max (MS-6580)) pci:v00008086d000024C4sv00001509sd00002990* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Averatec 5110H) pci:v00008086d000024C4sv00001734sd00001004* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (D1451 Mainboard (SCENIC N300, i845GV)) pci:v00008086d000024C4sv00004C53sd00001090* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Cx9 / Vx9 mainboard) pci:v00008086d000024C4sv00008086sd000024C2* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Latitude X300) pci:v00008086d000024C4sv00008086sd00004541* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Latitude D400/D500) pci:v00008086d000024C4sv0000E4BFsd00000CC9* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (CC9-SAMBA) pci:v00008086d000024C4sv0000E4BFsd00000CD2* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (CD2-BEBOP) pci:v00008086d000024C5* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller pci:v00008086d000024C5sv00000E11sd000000B8* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Analog Devices Inc. codec [SoundMAX]) pci:v00008086d000024C5sv00001014sd00000267* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (NetVista A30p) pci:v00008086d000024C5sv00001014sd00000537* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (ThinkPad T4x Series) pci:v00008086d000024C5sv00001014sd0000055F* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Thinkpad R50e model 1634) pci:v00008086d000024C5sv00001025sd0000005A* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (TravelMate 290) pci:v00008086d000024C5sv00001025sd00000064* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) pci:v00008086d000024C5sv00001028sd00000139* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Latitude D400) pci:v00008086d000024C5sv00001028sd0000014F* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Latitude X300) pci:v00008086d000024C5sv00001028sd00000152* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Latitude D500) pci:v00008086d000024C5sv00001028sd00000160* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Dimension 2400) pci:v00008086d000024C5sv00001028sd00000163* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Latitude D505) pci:v00008086d000024C5sv00001028sd0000018D* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Inspiron 700m/710m [SigmaTel STAC9750,51]) pci:v00008086d000024C5sv00001028sd00000196* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Inspiron 5160) pci:v00008086d000024C5sv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (NC8000 laptop) pci:v00008086d000024C5sv0000103Csd00000890* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (NC6000 laptop) pci:v00008086d000024C5sv0000103Csd000008B0* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (tc1100 tablet) pci:v00008086d000024C5sv00001043sd00001713* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (M2400N/M6800N laptop) pci:v00008086d000024C5sv00001043sd000080B0* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (P4B533) pci:v00008086d000024C5sv00001071sd00008160* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (MIM2000) pci:v00008086d000024C5sv00001179sd00000201* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Toshiba Tecra M1) pci:v00008086d000024C5sv0000144Dsd0000C005* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (X10 Laptop) pci:v00008086d000024C5sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (P30/P35 notebook) pci:v00008086d000024C5sv00001458sd0000A002* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (GA-8PE667 Ultra) pci:v00008086d000024C5sv00001462sd00005800* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (845PE Max (MS-6580)) pci:v00008086d000024C5sv00001734sd00001005* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (D1451 (SCENIC N300, i845GV) Sigmatel STAC9750T) pci:v00008086d000024C5sv00001734sd00001055* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Amilo M1420) pci:v00008086d000024C6* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller pci:v00008086d000024C6sv00001014sd00000524* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (ThinkPad T4x Series) pci:v00008086d000024C6sv00001014sd00000525* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (ThinkPad) pci:v00008086d000024C6sv00001014sd00000559* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (ThinkPad R50e) pci:v00008086d000024C6sv00001025sd0000003C* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (Aspire 2001WLCi (Compal CL50 motherboard) implementation) pci:v00008086d000024C6sv00001025sd0000005A* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (TravelMate 290) pci:v00008086d000024C6sv00001025sd00000064* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) pci:v00008086d000024C6sv00001028sd00000196* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (Inspiron 5160) pci:v00008086d000024C6sv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (NC8000 laptop) pci:v00008086d000024C6sv0000103Csd00000890* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (NC6000 laptop) pci:v00008086d000024C6sv0000103Csd000008B0* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (tc1100 tablet) pci:v00008086d000024C6sv00001043sd00001716* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (M2400N laptop) pci:v00008086d000024C6sv00001043sd00001826* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (M6800N) pci:v00008086d000024C6sv00001071sd00008160* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (MIM2000) pci:v00008086d000024C6sv0000134Dsd00004C21* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (Latitude D500) pci:v00008086d000024C6sv0000144Dsd00002115* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (X10 Laptop) pci:v00008086d000024C6sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (P30/P35 notebook) pci:v00008086d000024C6sv000014F1sd00005422* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (D480 MDC V.9x Modem) pci:v00008086d000024C7* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 pci:v00008086d000024C7sv00001014sd00000267* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (NetVista A30p) pci:v00008086d000024C7sv00001014sd0000052D* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (ThinkPad) pci:v00008086d000024C7sv00001025sd0000005A* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (TravelMate 290) pci:v00008086d000024C7sv00001025sd00000064* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) pci:v00008086d000024C7sv00001028sd00000126* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Optiplex GX260) pci:v00008086d000024C7sv00001028sd00000160* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Dimension 2400) pci:v00008086d000024C7sv00001028sd00000163* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Latitude D505) pci:v00008086d000024C7sv00001028sd0000018D* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Inspiron 700m/710m) pci:v00008086d000024C7sv00001028sd00000196* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Inspiron 5160) pci:v00008086d000024C7sv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (NC8000 laptop) pci:v00008086d000024C7sv0000103Csd00000890* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (NC6000 laptop) pci:v00008086d000024C7sv0000103Csd000008B0* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (tc1100 tablet) pci:v00008086d000024C7sv00001043sd00008089* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (P4B533) pci:v00008086d000024C7sv00001071sd00008160* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (MIM2000) pci:v00008086d000024C7sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (P30/P35 notebook) pci:v00008086d000024C7sv00001462sd00005800* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (845PE Max (MS-6580)) pci:v00008086d000024C7sv00001509sd00002990* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Averatec 5110H) pci:v00008086d000024C7sv00001734sd00001004* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (D1451 Mainboard (SCENIC N300, i845GV)) pci:v00008086d000024C7sv00004C53sd00001090* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Cx9 / Vx9 mainboard) pci:v00008086d000024C7sv00008086sd000024C2* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Latitude X300) pci:v00008086d000024C7sv00008086sd00004541* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Latitude D400/D500) pci:v00008086d000024C7sv0000E4BFsd00000CC9* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (CC9-SAMBA) pci:v00008086d000024C7sv0000E4BFsd00000CD2* ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (CD2-BEBOP) pci:v00008086d000024CA* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller pci:v00008086d000024CAsv00001014sd0000052D* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (ThinkPad) pci:v00008086d000024CAsv00001025sd0000005A* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (TravelMate 290) pci:v00008086d000024CAsv00001025sd00000064* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) pci:v00008086d000024CAsv00001028sd0000014F* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Latitude X300) pci:v00008086d000024CAsv00001028sd00000163* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Latitude D505) pci:v00008086d000024CAsv00001028sd0000018D* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Inspiron 700m/710m) pci:v00008086d000024CAsv00001028sd00000196* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Inspiron 5160) pci:v00008086d000024CAsv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (NC8000 laptop) pci:v00008086d000024CAsv0000103Csd00000890* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (NC6000 laptop) pci:v00008086d000024CAsv0000103Csd000008B0* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (tc1100 tablet) pci:v00008086d000024CAsv00001071sd00008160* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (MIM2000) pci:v00008086d000024CAsv0000144Dsd0000C005* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (X10 Laptop) pci:v00008086d000024CAsv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (P30/P35 notebook) pci:v00008086d000024CAsv00001734sd00001055* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Amilo M1420) pci:v00008086d000024CAsv00008086sd00004541* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Latitude D400/D500) pci:v00008086d000024CB* ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller pci:v00008086d000024CBsv00001014sd00000267* ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (NetVista A30p) pci:v00008086d000024CBsv00001028sd00000126* ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (Optiplex GX260) pci:v00008086d000024CBsv00001028sd00000160* ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (Dimension 2400) pci:v00008086d000024CBsv00001043sd00008089* ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (P4B533) pci:v00008086d000024CBsv0000114Asd00000582* ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (PC8 onboard IDE) pci:v00008086d000024CBsv00001458sd000024C2* ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (GA-8PE667 Ultra) pci:v00008086d000024CBsv00001462sd00005800* ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (845PE Max (MS-6580)) pci:v00008086d000024CBsv00001734sd00001004* ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (D1451 Mainboard (SCENIC N300, i845GV)) pci:v00008086d000024CBsv00004C53sd00001090* ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (Cx9 / Vx9 mainboard) pci:v00008086d000024CBsv0000E4BFsd00000CC9* ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (CC9-SAMBA) pci:v00008086d000024CBsv0000E4BFsd00000CD2* ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (CD2-BEBOP) pci:v00008086d000024CC* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) LPC Interface Bridge pci:v00008086d000024CCsv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) LPC Interface Bridge (P30 notebook) pci:v00008086d000024CCsv00001734sd00001055* ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) LPC Interface Bridge (Amilo M1420) pci:v00008086d000024CD* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller pci:v00008086d000024CDsv00001014sd00000267* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (NetVista A30p) pci:v00008086d000024CDsv00001014sd0000052E* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (ThinkPad) pci:v00008086d000024CDsv00001025sd0000005A* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (TravelMate 290) pci:v00008086d000024CDsv00001025sd00000064* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) pci:v00008086d000024CDsv00001028sd0000011D* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Latitude D600) pci:v00008086d000024CDsv00001028sd00000126* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Optiplex GX260) pci:v00008086d000024CDsv00001028sd00000139* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Latitude D400) pci:v00008086d000024CDsv00001028sd00000152* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Latitude D500) pci:v00008086d000024CDsv00001028sd00000160* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Dimension 2400) pci:v00008086d000024CDsv00001028sd00000163* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Latitude D505) pci:v00008086d000024CDsv00001028sd0000018D* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Inspiron 700m/710m) pci:v00008086d000024CDsv00001028sd00000196* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Inspiron 5160) pci:v00008086d000024CDsv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (NC8000 laptop) pci:v00008086d000024CDsv0000103Csd00000890* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (NC6000 laptop) pci:v00008086d000024CDsv0000103Csd000008B0* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (tc1100 tablet) pci:v00008086d000024CDsv00001043sd00008089* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (P4B533) pci:v00008086d000024CDsv00001071sd00008160* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (MIM2000) pci:v00008086d000024CDsv0000114Asd00000582* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (PC8 onboard USB 2.0) pci:v00008086d000024CDsv00001179sd0000FF00* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Satellite 2430) pci:v00008086d000024CDsv0000144Dsd0000C005* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (X10 Laptop) pci:v00008086d000024CDsv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (P30/P35 notebook) pci:v00008086d000024CDsv00001462sd00003981* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (845PE Max (MS-6580)) pci:v00008086d000024CDsv00001509sd00001968* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Averatec 5110H) pci:v00008086d000024CDsv00001734sd00001004* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (D1451 Mainboard (SCENIC N300, i845GV)) pci:v00008086d000024CDsv00001734sd00001055* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Amilo M1420) pci:v00008086d000024CDsv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (QEMU Virtual Machine) pci:v00008086d000024CDsv00004C53sd00001090* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Cx9 / Vx9 mainboard) pci:v00008086d000024CDsv00008086sd000024C2* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Latitude X300) pci:v00008086d000024CDsv0000E4BFsd00000CC9* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (CC9-SAMBA) pci:v00008086d000024CDsv0000E4BFsd00000CD2* ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (CD2-BEBOP) pci:v00008086d000024D0* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) LPC Interface Bridge pci:v00008086d000024D1* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller pci:v00008086d000024D1sv00001028sd00000168* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (Precision Workstation 670 Mainboard) pci:v00008086d000024D1sv00001028sd00000169* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (Precision 470) pci:v00008086d000024D1sv00001028sd0000019A* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (PowerEdge SC1425) pci:v00008086d000024D1sv0000103Csd000012BC* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (d530 CMT (DG746A)) pci:v00008086d000024D1sv0000103Csd00003208* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (ProLiant DL140 G2) pci:v00008086d000024D1sv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (P4P800 series motherboard) pci:v00008086d000024D1sv00001458sd000024D1* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (GA-8IPE1000 Pro2 motherboard (865PE)) pci:v00008086d000024D1sv00001462sd00007280* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (865PE Neo2 (MS-6728)) pci:v00008086d000024D1sv00001462sd00007650* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (Hetis 865GV-E (MS-7065)) pci:v00008086d000024D1sv00001565sd00005200* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (P4TSV Motherboard (865G)) pci:v00008086d000024D1sv000015D9sd00004580* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (P4SCE Mainboard) pci:v00008086d000024D1sv00008086sd00003427* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (S875WP1-E mainboard) pci:v00008086d000024D1sv00008086sd00004246* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (Desktop Board D865GBF) pci:v00008086d000024D1sv00008086sd00004C43* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (Desktop Board D865GLC) pci:v00008086d000024D1sv00008086sd0000524C* ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (D865PERL mainboard) pci:v00008086d000024D2* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 pci:v00008086d000024D2sv00001014sd000002DD* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (eServer xSeries server mainboard) pci:v00008086d000024D2sv00001014sd000002ED* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (eServer xSeries server mainboard) pci:v00008086d000024D2sv00001028sd00000168* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (Precision Workstation 670 Mainboard) pci:v00008086d000024D2sv00001028sd00000169* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (Precision 470) pci:v00008086d000024D2sv00001028sd0000016C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (PowerEdge 1850 onboard UHCI) pci:v00008086d000024D2sv00001028sd0000016D* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (PowerEdge 2850 onboard UHCI) pci:v00008086d000024D2sv00001028sd00000170* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (PowerEdge 6850 onboard UHCI) pci:v00008086d000024D2sv00001028sd00000183* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (PowerEdge 1800) pci:v00008086d000024D2sv00001028sd0000019A* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (PowerEdge SC1425) pci:v00008086d000024D2sv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (NX9500) pci:v00008086d000024D2sv0000103Csd000012BC* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (d530 CMT (DG746A)) pci:v00008086d000024D2sv0000103Csd00003208* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (ProLiant DL140 G2) pci:v00008086d000024D2sv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (P4P800/P5P800 series motherboard) pci:v00008086d000024D2sv00001458sd000024D2* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (GA-8IPE1000/8KNXP motherboard) pci:v00008086d000024D2sv00001462sd00007280* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (865PE Neo2 (MS-6728)) pci:v00008086d000024D2sv00001565sd00003101* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (P4TSV Motherboard (865G)) pci:v00008086d000024D2sv000015D9sd00004580* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (P4SCE Mainboard) pci:v00008086d000024D2sv00001734sd0000101C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (PRIMERGY RX/TX series onboard UHCI) pci:v00008086d000024D2sv00008086sd00003427* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (S875WP1-E mainboard) pci:v00008086d000024D2sv00008086sd00004246* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (Desktop Board D865GBF) pci:v00008086d000024D2sv00008086sd00004C43* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (Desktop Board D865GLC) pci:v00008086d000024D2sv00008086sd0000524C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (D865PERL mainboard) pci:v00008086d000024D3* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller pci:v00008086d000024D3sv00001014sd000002DD* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (eServer xSeries server mainboard) pci:v00008086d000024D3sv00001014sd000002ED* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (eServer xSeries server mainboard) pci:v00008086d000024D3sv00001028sd00000156* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (Precision 360) pci:v00008086d000024D3sv00001028sd00000168* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (Precision Workstation 670 Mainboard) pci:v00008086d000024D3sv00001028sd00000169* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (Precision 470) pci:v00008086d000024D3sv0000103Csd000012BC* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (d330 uT) pci:v00008086d000024D3sv0000103Csd00003208* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (ProLiant DL140 G2) pci:v00008086d000024D3sv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (P4P800/P5P800 series motherboard) pci:v00008086d000024D3sv00001458sd000024D2* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (GA-8IPE1000 Pro2 motherboard (865PE)) pci:v00008086d000024D3sv00001462sd00007280* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (865PE Neo2 (MS-6728)) pci:v00008086d000024D3sv00001462sd00007650* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (Hetis 865GV-E (MS-7065)) pci:v00008086d000024D3sv00001565sd00003101* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (P4TSV Motherboard (865G)) pci:v00008086d000024D3sv000015D9sd00004580* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (P4SCE Mainboard) pci:v00008086d000024D3sv00001734sd0000101C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (PRIMERGY RX/TX S2 series SMBus) pci:v00008086d000024D3sv00008086sd00003427* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (S875WP1-E mainboard) pci:v00008086d000024D3sv00008086sd00004246* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (Desktop Board D865GBF) pci:v00008086d000024D3sv00008086sd00004C43* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (Desktop Board D865GLC) pci:v00008086d000024D3sv00008086sd0000524C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (D865PERL mainboard) pci:v00008086d000024D4* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 pci:v00008086d000024D4sv00001014sd000002DD* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (eServer xSeries server mainboard) pci:v00008086d000024D4sv00001014sd000002ED* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (eServer xSeries server mainboard) pci:v00008086d000024D4sv00001028sd00000168* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (Precision Workstation 670 Mainboard) pci:v00008086d000024D4sv00001028sd00000169* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (Precision 470) pci:v00008086d000024D4sv00001028sd0000016C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (PowerEdge 1850 onboard UHCI) pci:v00008086d000024D4sv00001028sd0000016D* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (PowerEdge 2850 onboard UHCI) pci:v00008086d000024D4sv00001028sd00000170* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (PowerEdge 6850 onboard UHCI) pci:v00008086d000024D4sv00001028sd00000183* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (PowerEdge 1800) pci:v00008086d000024D4sv00001028sd0000019A* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (PowerEdge SC1425) pci:v00008086d000024D4sv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (NX9500) pci:v00008086d000024D4sv0000103Csd000012BC* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (d530 CMT (DG746A)) pci:v00008086d000024D4sv0000103Csd00003208* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (ProLiant DL140 G2) pci:v00008086d000024D4sv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (P4P800/P5P800 series motherboard) pci:v00008086d000024D4sv00001458sd000024D2* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (GA-8IPE1000 Pro2 motherboard (865PE)) pci:v00008086d000024D4sv00001462sd00007280* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (865PE Neo2 (MS-6728)) pci:v00008086d000024D4sv00001462sd00007650* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (Hetis 865GV-E (MS-7065)) pci:v00008086d000024D4sv00001565sd00003101* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (P4TSV Motherboard (865G)) pci:v00008086d000024D4sv000015D9sd00004580* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (P4SCE Mainboard) pci:v00008086d000024D4sv00001734sd0000101C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (PRIMERGY RX/TX S2 series onboard UHCI) pci:v00008086d000024D4sv00008086sd00003427* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (S875WP1-E mainboard) pci:v00008086d000024D4sv00008086sd00004246* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (Desktop Board D865GBF) pci:v00008086d000024D4sv00008086sd00004C43* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (Desktop Board D865GLC) pci:v00008086d000024D4sv00008086sd0000524C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (D865PERL mainboard) pci:v00008086d000024D5* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller pci:v00008086d000024D5sv0000100Asd0000147B* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (Abit IS7-E motherboard) pci:v00008086d000024D5sv00001028sd00000168* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (Precision Workstation 670 Mainboard) pci:v00008086d000024D5sv00001028sd00000169* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (Precision 470) pci:v00008086d000024D5sv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (NX9500) pci:v00008086d000024D5sv0000103Csd000012BC* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (d330 uT) pci:v00008086d000024D5sv00001043sd000080F3* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (P4P800 series motherboard) pci:v00008086d000024D5sv00001043sd0000810F* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (P5P800-MX Mainboard) pci:v00008086d000024D5sv00001458sd0000A002* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (GA-8IPE1000/8KNXP motherboard) pci:v00008086d000024D5sv00001462sd00000080* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (865PE Neo2-V (MS-6788) Mainboard) pci:v00008086d000024D5sv00001462sd00007280* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (865PE Neo2 (MS-6728)) pci:v00008086d000024D5sv00001462sd00007650* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (Hetis 865GV-E (MS-7065)) pci:v00008086d000024D5sv00008086sd0000A000* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (D865PERL mainboard) pci:v00008086d000024D5sv00008086sd0000E000* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (D865PERL mainboard) pci:v00008086d000024D5sv00008086sd0000E001* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (Desktop Board D865GBF) pci:v00008086d000024D5sv00008086sd0000E002* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (SoundMax Intergrated Digital Audio) pci:v00008086d000024D6* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Modem Controller pci:v00008086d000024D6sv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Modem Controller (NX9500) pci:v00008086d000024D7* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 pci:v00008086d000024D7sv00001014sd000002ED* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (xSeries server mainboard) pci:v00008086d000024D7sv00001028sd00000168* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (Precision Workstation 670 Mainboard) pci:v00008086d000024D7sv00001028sd00000169* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (Precision 470) pci:v00008086d000024D7sv00001028sd0000016C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (PowerEdge 1850 onboard UHCI) pci:v00008086d000024D7sv00001028sd0000016D* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (PowerEdge 2850 onboard UHCI) pci:v00008086d000024D7sv00001028sd00000170* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (PowerEdge 6850 onboard UHCI) pci:v00008086d000024D7sv00001028sd00000183* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (PowerEdge 1800) pci:v00008086d000024D7sv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (NX9500) pci:v00008086d000024D7sv0000103Csd000012BC* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (d530 CMT (DG746A)) pci:v00008086d000024D7sv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (P4P800/P5P800 series motherboard) pci:v00008086d000024D7sv00001458sd000024D2* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (GA-8IPE1000 Pro2 motherboard (865PE)) pci:v00008086d000024D7sv00001462sd00007280* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (865PE Neo2 (MS-6728)) pci:v00008086d000024D7sv00001462sd00007650* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (Hetis 865GV-E (MS-7065)) pci:v00008086d000024D7sv00001565sd00003101* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (P4TSV Motherboard (865G)) pci:v00008086d000024D7sv000015D9sd00004580* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (P4SCE Mainboard) pci:v00008086d000024D7sv00001734sd0000101C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (PRIMERGY RX/TX S2 series onboard UHCI) pci:v00008086d000024D7sv00008086sd00003427* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (S875WP1-E mainboard) pci:v00008086d000024D7sv00008086sd00004246* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (Desktop Board D865GBF) pci:v00008086d000024D7sv00008086sd00004C43* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (Desktop Board D865GLC) pci:v00008086d000024D7sv00008086sd0000524C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (D865PERL mainboard) pci:v00008086d000024DB* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller pci:v00008086d000024DBsv00001014sd000002DD* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (eServer xSeries server mainboard) pci:v00008086d000024DBsv00001014sd000002ED* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (eServer xSeries server mainboard) pci:v00008086d000024DBsv00001028sd00000168* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (Precision Workstation 670 Mainboard) pci:v00008086d000024DBsv00001028sd00000169* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (Precision 470) pci:v00008086d000024DBsv00001028sd0000016C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (PowerEdge 1850 IDE Controller) pci:v00008086d000024DBsv00001028sd0000016D* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (PowerEdge 2850 IDE Controller) pci:v00008086d000024DBsv00001028sd00000170* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (PowerEdge 6850 IDE Controller) pci:v00008086d000024DBsv00001028sd0000019A* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (PowerEdge SC1425) pci:v00008086d000024DBsv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (NX9500) pci:v00008086d000024DBsv0000103Csd000012BC* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (d530 CMT (DG746A)) pci:v00008086d000024DBsv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (P4P800/P5P800 series motherboard) pci:v00008086d000024DBsv00001458sd000024D2* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (GA-8IPE1000 Pro2 motherboard (865PE)) pci:v00008086d000024DBsv00001462sd00007280* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (865PE Neo2 (MS-6728)) pci:v00008086d000024DBsv00001462sd00007580* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (MSI 875P) pci:v00008086d000024DBsv00001462sd00007650* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (Hetis 865GV-E (MS-7065)) pci:v00008086d000024DBsv00001565sd00003101* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (P4TSV Motherboard (865G)) pci:v00008086d000024DBsv000015D9sd00004580* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (P4SCE Mainboard) pci:v00008086d000024DBsv00001734sd0000101C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (PRIMERGY RX/TX S2 series onboard IDE) pci:v00008086d000024DBsv00008086sd000024DB* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (P4C800 Mainboard) pci:v00008086d000024DBsv00008086sd00003427* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (S875WP1-E mainboard) pci:v00008086d000024DBsv00008086sd00004246* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (Desktop Board D865GBF) pci:v00008086d000024DBsv00008086sd00004C43* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (Desktop Board D865GLC) pci:v00008086d000024DBsv00008086sd0000524C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (D865PERL mainboard) pci:v00008086d000024DC* ID_MODEL_FROM_DATABASE=82801EB (ICH5) LPC Interface Bridge pci:v00008086d000024DD* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller pci:v00008086d000024DDsv00001014sd000002DD* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (eServer xSeries server mainboard) pci:v00008086d000024DDsv00001014sd000002ED* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (eServer xSeries server mainboard) pci:v00008086d000024DDsv00001028sd00000168* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (Precision Workstation 670 Mainboard) pci:v00008086d000024DDsv00001028sd00000169* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (Precision 470) pci:v00008086d000024DDsv00001028sd0000016C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (PowerEdge 1850 onboard EHCI) pci:v00008086d000024DDsv00001028sd0000016D* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (PowerEdge 2850 onboard EHCI) pci:v00008086d000024DDsv00001028sd00000170* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (PowerEdge 6850 onboard EHCI) pci:v00008086d000024DDsv00001028sd00000183* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (PowerEdge 1800) pci:v00008086d000024DDsv00001028sd0000019A* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (PowerEdge SC1425) pci:v00008086d000024DDsv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (NX9500) pci:v00008086d000024DDsv0000103Csd000012BC* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (d530 CMT (DG746A)) pci:v00008086d000024DDsv0000103Csd00003208* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (ProLiant DL140 G2) pci:v00008086d000024DDsv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (P4P800/P5P800 series motherboard) pci:v00008086d000024DDsv00001458sd00005006* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (GA-8IPE1000 Pro2 motherboard (865PE)) pci:v00008086d000024DDsv00001462sd00007280* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (865PE Neo2 (MS-6728)) pci:v00008086d000024DDsv00001462sd00007650* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (Hetis 865GV-E (MS-7065)) pci:v00008086d000024DDsv00008086sd00003427* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (S875WP1-E mainboard) pci:v00008086d000024DDsv00008086sd00004246* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (Desktop Board D865GBF) pci:v00008086d000024DDsv00008086sd00004C43* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (Desktop Board D865GLC) pci:v00008086d000024DDsv00008086sd0000524C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (D865PERL mainboard) pci:v00008086d000024DE* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 pci:v00008086d000024DEsv00001014sd000002ED* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (xSeries server mainboard) pci:v00008086d000024DEsv00001028sd00000168* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (Precision Workstation 670 Mainboard) pci:v00008086d000024DEsv00001028sd00000169* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (Precision 470) pci:v00008086d000024DEsv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (P4P800/P5P800 series motherboard) pci:v00008086d000024DEsv00001458sd000024D2* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (GA-8IPE1000 Pro2 motherboard (865PE)) pci:v00008086d000024DEsv00001462sd00007280* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (865PE Neo2 (MS-6728)) pci:v00008086d000024DEsv00001462sd00007650* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (Hetis 865GV-E (MS-7065)) pci:v00008086d000024DEsv00001565sd00003101* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (P4TSV Motherboard (865G)) pci:v00008086d000024DEsv000015D9sd00004580* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (P4SCE Mainboard) pci:v00008086d000024DEsv00001734sd0000101C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (PRIMERGY RX/TX S2 series onboard UHCI) pci:v00008086d000024DEsv00008086sd00003427* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (S875WP1-E mainboard) pci:v00008086d000024DEsv00008086sd00004246* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (Desktop Board D865GBF) pci:v00008086d000024DEsv00008086sd00004C43* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (Desktop Board D865GLC) pci:v00008086d000024DEsv00008086sd0000524C* ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (D865PERL mainboard) pci:v00008086d000024DF* ID_MODEL_FROM_DATABASE=82801ER (ICH5R) SATA Controller pci:v00008086d000024DFsv00001028sd00000168* ID_MODEL_FROM_DATABASE=82801ER (ICH5R) SATA Controller (Precision Workstation 670 Mainboard) pci:v00008086d000024F0* ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] pci:v00008086d000024F0sv000010A9sd0000802E* ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-path HFI 100 Series, 1-port) pci:v00008086d000024F0sv000010A9sd0000802F* ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-path HFI 100 Series, 2-port) pci:v00008086d000024F0sv00008086sd00002628* ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16) pci:v00008086d000024F0sv00008086sd00002629* ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x8) pci:v00008086d000024F0sv00008086sd0000262A* ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 2 Ports, Split PCIe x16) pci:v00008086d000024F0sv00008086sd0000262D* ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, IO Module AHWKPTP100HF) pci:v00008086d000024F1* ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [integrated] pci:v00008086d000024F3* ID_MODEL_FROM_DATABASE=Wireless 8260 pci:v00008086d000024F3sv00008086sd00000010* ID_MODEL_FROM_DATABASE=Wireless 8260 (Dual Band Wireless-AC 8260) pci:v00008086d000024F4* ID_MODEL_FROM_DATABASE=Wireless 8260 pci:v00008086d000024F4sv00008086sd00000030* ID_MODEL_FROM_DATABASE=Wireless 8260 (Dual Band Wireless-AC 8260) pci:v00008086d00002500* ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset Host Bridge (MCH) pci:v00008086d00002500sv00001028sd00000095* ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset Host Bridge (MCH) (Precision Workstation 220 Chipset) pci:v00008086d00002500sv00001043sd0000801C* ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset Host Bridge (MCH) (P3C-2000 system chipset) pci:v00008086d00002501* ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset Host Bridge (MCH) pci:v00008086d00002501sv00001043sd0000801C* ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset Host Bridge (MCH) (P3C-2000 system chipset) pci:v00008086d0000250B* ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset Host Bridge pci:v00008086d0000250F* ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset AGP Bridge pci:v00008086d00002520* ID_MODEL_FROM_DATABASE=82805AA MTH Memory Translator Hub pci:v00008086d00002521* ID_MODEL_FROM_DATABASE=82804AA MRH-S Memory Repeater Hub for SDRAM pci:v00008086d00002530* ID_MODEL_FROM_DATABASE=82850 850 (Tehama) Chipset Host Bridge (MCH) pci:v00008086d00002530sv00001028sd000000C7* ID_MODEL_FROM_DATABASE=82850 850 (Tehama) Chipset Host Bridge (MCH) (Dimension 8100) pci:v00008086d00002530sv0000147Bsd00000507* ID_MODEL_FROM_DATABASE=82850 850 (Tehama) Chipset Host Bridge (MCH) (TH7II-RAID) pci:v00008086d00002531* ID_MODEL_FROM_DATABASE=82860 860 (Wombat) Chipset Host Bridge (MCH) pci:v00008086d00002531sv00001028sd000000D8* ID_MODEL_FROM_DATABASE=82860 860 (Wombat) Chipset Host Bridge (MCH) (Precision 530) pci:v00008086d00002532* ID_MODEL_FROM_DATABASE=82850 850 (Tehama) Chipset AGP Bridge pci:v00008086d00002533* ID_MODEL_FROM_DATABASE=82860 860 (Wombat) Chipset AGP Bridge pci:v00008086d00002534* ID_MODEL_FROM_DATABASE=82860 860 (Wombat) Chipset PCI Bridge pci:v00008086d00002540* ID_MODEL_FROM_DATABASE=E7500 Memory Controller Hub pci:v00008086d00002540sv000015D9sd00003480* ID_MODEL_FROM_DATABASE=E7500 Memory Controller Hub (P4DP6) pci:v00008086d00002541* ID_MODEL_FROM_DATABASE=E7500/E7501 Host RASUM Controller pci:v00008086d00002541sv000015D9sd00003480* ID_MODEL_FROM_DATABASE=E7500/E7501 Host RASUM Controller (P4DP6) pci:v00008086d00002541sv00004C53sd00001090* ID_MODEL_FROM_DATABASE=E7500/E7501 Host RASUM Controller (Cx9 / Vx9 mainboard) pci:v00008086d00002541sv00008086sd00003424* ID_MODEL_FROM_DATABASE=E7500/E7501 Host RASUM Controller (SE7501HG2 Mainboard) pci:v00008086d00002543* ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface B PCI-to-PCI Bridge pci:v00008086d00002544* ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface B RASUM Controller pci:v00008086d00002544sv00004C53sd00001090* ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface B RASUM Controller (Cx9 / Vx9 mainboard) pci:v00008086d00002545* ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface C PCI-to-PCI Bridge pci:v00008086d00002546* ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface C RASUM Controller pci:v00008086d00002547* ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface D PCI-to-PCI Bridge pci:v00008086d00002548* ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface D RASUM Controller pci:v00008086d0000254C* ID_MODEL_FROM_DATABASE=E7501 Memory Controller Hub pci:v00008086d0000254Csv00004C53sd00001090* ID_MODEL_FROM_DATABASE=E7501 Memory Controller Hub (Cx9 / Vx9 mainboard) pci:v00008086d0000254Csv00008086sd00003424* ID_MODEL_FROM_DATABASE=E7501 Memory Controller Hub (SE7501HG2 Mainboard) pci:v00008086d00002550* ID_MODEL_FROM_DATABASE=E7505 Memory Controller Hub pci:v00008086d00002551* ID_MODEL_FROM_DATABASE=E7505/E7205 Series RAS Controller pci:v00008086d00002552* ID_MODEL_FROM_DATABASE=E7505/E7205 PCI-to-AGP Bridge pci:v00008086d00002553* ID_MODEL_FROM_DATABASE=E7505 Hub Interface B PCI-to-PCI Bridge pci:v00008086d00002554* ID_MODEL_FROM_DATABASE=E7505 Hub Interface B PCI-to-PCI Bridge RAS Controller pci:v00008086d0000255D* ID_MODEL_FROM_DATABASE=E7205 Memory Controller Hub pci:v00008086d00002560* ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface pci:v00008086d00002560sv00001028sd00000126* ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface (Optiplex GX260) pci:v00008086d00002560sv00001458sd00002560* ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface (GA-8PE667 Ultra) pci:v00008086d00002560sv00001462sd00005800* ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface (845PE Max (MS-6580)) pci:v00008086d00002561* ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE/PE Host-to-AGP Bridge pci:v00008086d00002562* ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device pci:v00008086d00002562sv00000E11sd000000B9* ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device (Evo D510 SFF) pci:v00008086d00002562sv00001014sd00000267* ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device (NetVista A30p) pci:v00008086d00002562sv00001028sd00000160* ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device (Dimension 2400) pci:v00008086d00002562sv00001734sd00001003* ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device (D1521 Mainboard (Fujitsu-Siemens)) pci:v00008086d00002562sv00001734sd00001004* ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device (D1451 Mainboard (SCENIC N300, i845GV)) pci:v00008086d00002570* ID_MODEL_FROM_DATABASE=82865G/PE/P DRAM Controller/Host-Hub Interface pci:v00008086d00002570sv0000103Csd0000006A* ID_MODEL_FROM_DATABASE=82865G/PE/P DRAM Controller/Host-Hub Interface (NX9500) pci:v00008086d00002570sv0000103Csd000012BC* ID_MODEL_FROM_DATABASE=82865G/PE/P DRAM Controller/Host-Hub Interface (d330 uT) pci:v00008086d00002570sv00001043sd000080F2* ID_MODEL_FROM_DATABASE=82865G/PE/P DRAM Controller/Host-Hub Interface (P4P800/P5P800 series motherboard) pci:v00008086d00002570sv00001458sd00002570* ID_MODEL_FROM_DATABASE=82865G/PE/P DRAM Controller/Host-Hub Interface (GA-8IPE1000 Pro2 motherboard (865PE)) pci:v00008086d00002571* ID_MODEL_FROM_DATABASE=82865G/PE/P AGP Bridge pci:v00008086d00002572* ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller pci:v00008086d00002572sv00001028sd0000019D* ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (Dimension 3000) pci:v00008086d00002572sv0000103Csd000012BC* ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (D530 sff(dc578av)) pci:v00008086d00002572sv00001043sd000080A5* ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (P5P800-MX Mainboard) pci:v00008086d00002572sv00001462sd00007650* ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (Hetis 865GV-E (MS-7065)) pci:v00008086d00002572sv00001734sd0000101B* ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (Fujitsu-Siemens Scenic E300 i865GV) pci:v00008086d00002572sv00008086sd00004246* ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (Desktop Board D865GBF) pci:v00008086d00002572sv00008086sd00004C43* ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (Desktop Board D865GLC) pci:v00008086d00002573* ID_MODEL_FROM_DATABASE=82865G/PE/P PCI to CSA Bridge pci:v00008086d00002576* ID_MODEL_FROM_DATABASE=82865G/PE/P Processor to I/O Memory Interface pci:v00008086d00002578* ID_MODEL_FROM_DATABASE=82875P/E7210 Memory Controller Hub pci:v00008086d00002578sv00001458sd00002578* ID_MODEL_FROM_DATABASE=82875P/E7210 Memory Controller Hub (GA-8KNXP motherboard (875P)) pci:v00008086d00002578sv00001462sd00007580* ID_MODEL_FROM_DATABASE=82875P/E7210 Memory Controller Hub (MS-6758 (875P Neo)) pci:v00008086d00002578sv000015D9sd00004580* ID_MODEL_FROM_DATABASE=82875P/E7210 Memory Controller Hub (P4SCE Motherboard) pci:v00008086d00002579* ID_MODEL_FROM_DATABASE=82875P Processor to AGP Controller pci:v00008086d0000257B* ID_MODEL_FROM_DATABASE=82875P/E7210 Processor to PCI to CSA Bridge pci:v00008086d0000257E* ID_MODEL_FROM_DATABASE=82875P/E7210 Processor to I/O Memory Interface pci:v00008086d00002580* ID_MODEL_FROM_DATABASE=82915G/P/GV/GL/PL/910GL Memory Controller Hub pci:v00008086d00002580sv00001458sd00002580* ID_MODEL_FROM_DATABASE=82915G/P/GV/GL/PL/910GL Memory Controller Hub (GA-8I915ME-G Mainboard) pci:v00008086d00002580sv00001462sd00007028* ID_MODEL_FROM_DATABASE=82915G/P/GV/GL/PL/910GL Memory Controller Hub (915P/G Neo2) pci:v00008086d00002580sv00001734sd0000105B* ID_MODEL_FROM_DATABASE=82915G/P/GV/GL/PL/910GL Memory Controller Hub (Scenic W620) pci:v00008086d00002581* ID_MODEL_FROM_DATABASE=82915G/P/GV/GL/PL/910GL PCI Express Root Port pci:v00008086d00002582* ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller pci:v00008086d00002582sv00001028sd00001079* ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller (Optiplex GX280) pci:v00008086d00002582sv0000103Csd00003006* ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller (DC7100 SFF(DX878AV)) pci:v00008086d00002582sv00001043sd00002582* ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller (P5GD1-VW Mainboard) pci:v00008086d00002582sv00001458sd00002582* ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller (GA-8I915ME-G Mainboard) pci:v00008086d00002582sv00001734sd0000105B* ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller (Scenic W620) pci:v00008086d00002582sv00001849sd00002582* ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller (ASRock P4Dual-915GL) pci:v00008086d00002584* ID_MODEL_FROM_DATABASE=82925X/XE Memory Controller Hub pci:v00008086d00002584sv00001028sd00000177* ID_MODEL_FROM_DATABASE=82925X/XE Memory Controller Hub (Dimension 8400) pci:v00008086d00002585* ID_MODEL_FROM_DATABASE=82925X/XE PCI Express Root Port pci:v00008086d00002588* ID_MODEL_FROM_DATABASE=E7220/E7221 Memory Controller Hub pci:v00008086d00002589* ID_MODEL_FROM_DATABASE=E7220/E7221 PCI Express Root Port pci:v00008086d0000258A* ID_MODEL_FROM_DATABASE=E7221 Integrated Graphics Controller pci:v00008086d00002590* ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller pci:v00008086d00002590sv00001014sd00000575* ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (ThinkPad Z60t) pci:v00008086d00002590sv00001028sd00000182* ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Dell Latitude C610) pci:v00008086d00002590sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Compaq nw8240/nx8220) pci:v00008086d00002590sv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (NX6110/NC6120) pci:v00008086d00002590sv0000104Dsd000081B7* ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Vaio VGN-S3XP) pci:v00008086d00002590sv0000A304sd000081B7* ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Vaio VGN-S3XP) pci:v00008086d00002590sv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (CCD-CALYPSO) pci:v00008086d00002590sv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (CD3-JIVE) pci:v00008086d00002590sv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (XB1) pci:v00008086d00002591* ID_MODEL_FROM_DATABASE=Mobile 915GM/PM Express PCI Express Root Port pci:v00008086d00002591sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=Mobile 915GM/PM Express PCI Express Root Port (Compaq nw8240 Mobile Workstation) pci:v00008086d00002592* ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller pci:v00008086d00002592sv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (NX6110/NC6120) pci:v00008086d00002592sv0000103Csd0000308A* ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (NC6220) pci:v00008086d00002592sv00001043sd00001881* ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (GMA 900 915GM Integrated Graphics) pci:v00008086d00002592sv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (CCD-CALYPSO) pci:v00008086d00002592sv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (CD3-JIVE) pci:v00008086d00002592sv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (XB1) pci:v00008086d000025A1* ID_MODEL_FROM_DATABASE=6300ESB LPC Interface Controller pci:v00008086d000025A2* ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller pci:v00008086d000025A2sv00001734sd00001073* ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller (Primergy Econel 200 D2020 mainboard) pci:v00008086d000025A2sv00001775sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller (V5D Single Board Computer IDE) pci:v00008086d000025A2sv00001775sd00001100* ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller (CR11/VR11 Single Board Computer) pci:v00008086d000025A2sv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller (CE9) pci:v00008086d000025A2sv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller (CL9 mainboard) pci:v00008086d000025A2sv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller (PSL09 PrPMC) pci:v00008086d000025A3* ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller pci:v00008086d000025A3sv00001734sd00001073* ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller (Primergy Econel 200 D2020 mainboard) pci:v00008086d000025A3sv00001775sd00001100* ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller (CR11/VR11 Single Board Computer) pci:v00008086d000025A3sv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller (CE9) pci:v00008086d000025A3sv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller (CL9 mainboard) pci:v00008086d000025A3sv00004C53sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller (Telum ASLP10 Processor AMC) pci:v00008086d000025A3sv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller (PSL09 PrPMC) pci:v00008086d000025A4* ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller pci:v00008086d000025A4sv00001734sd00001073* ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (Primergy Econel 200 D2020 mainboard) pci:v00008086d000025A4sv00001775sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (V5D Single Board Computer) pci:v00008086d000025A4sv00001775sd00001100* ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (CR11/VR11 Single Board Computer) pci:v00008086d000025A4sv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (CE9) pci:v00008086d000025A4sv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (CL9 mainboard) pci:v00008086d000025A4sv00004C53sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (Telum ASLP10 Processor AMC) pci:v00008086d000025A4sv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (PSL09 PrPMC) pci:v00008086d000025A6* ID_MODEL_FROM_DATABASE=6300ESB AC'97 Audio Controller pci:v00008086d000025A6sv00001775sd00001100* ID_MODEL_FROM_DATABASE=6300ESB AC'97 Audio Controller (CR11/VR11 Single Board Computer) pci:v00008086d000025A6sv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=6300ESB AC'97 Audio Controller (CE9) pci:v00008086d000025A6sv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=6300ESB AC'97 Audio Controller (CL9 mainboard) pci:v00008086d000025A7* ID_MODEL_FROM_DATABASE=6300ESB AC'97 Modem Controller pci:v00008086d000025A9* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller pci:v00008086d000025A9sv00001734sd00001073* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (Primergy Econel 200 D2020 mainboard) pci:v00008086d000025A9sv00001775sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (V5D Single Board Computer USB) pci:v00008086d000025A9sv00001775sd00001100* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (CR11/VR11 Single Board Computer) pci:v00008086d000025A9sv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (CE9) pci:v00008086d000025A9sv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (CL9 mainboard) pci:v00008086d000025A9sv00004C53sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (Telum ASLP10 Processor AMC) pci:v00008086d000025A9sv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (PSL09 PrPMC) pci:v00008086d000025AA* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller pci:v00008086d000025AAsv00001734sd00001073* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (Primergy Econel 200 D2020 mainboard) pci:v00008086d000025AAsv00001775sd00001100* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (CR11/VR11 Single Board Computer) pci:v00008086d000025AAsv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (CE9) pci:v00008086d000025AAsv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (CL9 mainboard) pci:v00008086d000025AAsv00004C53sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (Telum ASLP10 Processor AMC) pci:v00008086d000025AAsv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (PSL09 PrPMC) pci:v00008086d000025AB* ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer pci:v00008086d000025ABsv00001734sd00001073* ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (Primergy Econel 200 D2020 mainboard) pci:v00008086d000025ABsv00001775sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (V5D Single Board Computer) pci:v00008086d000025ABsv00001775sd00001100* ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (CR11/VR11 Single Board Computer) pci:v00008086d000025ABsv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (CE9) pci:v00008086d000025ABsv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (QEMU Virtual Machine) pci:v00008086d000025ABsv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (CL9 mainboard) pci:v00008086d000025ABsv00004C53sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (Telum ASLP10 Processor AMC) pci:v00008086d000025ABsv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (PSL09 PrPMC) pci:v00008086d000025AC* ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller pci:v00008086d000025ACsv00001734sd00001073* ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (Primergy Econel 200 D2020 mainboard) pci:v00008086d000025ACsv00001775sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (V5D Single Board Computer) pci:v00008086d000025ACsv00001775sd00001100* ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (CR11/VR11 Single Board Computer) pci:v00008086d000025ACsv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (CE9) pci:v00008086d000025ACsv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (CL9 mainboard) pci:v00008086d000025ACsv00004C53sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (Telum ASLP10 Processor AMC) pci:v00008086d000025ACsv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (PSL09 PrPMC) pci:v00008086d000025AD* ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller pci:v00008086d000025ADsv00001734sd00001073* ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (Primergy Econel 200 D2020 mainboard) pci:v00008086d000025ADsv00001775sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (V5D Single Board Computer USB 2.0) pci:v00008086d000025ADsv00001775sd00001100* ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (CR11/VR11 Single Board Computer) pci:v00008086d000025ADsv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (CE9) pci:v00008086d000025ADsv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (CL9 mainboard) pci:v00008086d000025ADsv00004C53sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (Telum ASLP10 Processor AMC) pci:v00008086d000025ADsv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (PSL09 PrPMC) pci:v00008086d000025AE* ID_MODEL_FROM_DATABASE=6300ESB 64-bit PCI-X Bridge pci:v00008086d000025B0* ID_MODEL_FROM_DATABASE=6300ESB SATA RAID Controller pci:v00008086d000025B0sv00001775sd00001100* ID_MODEL_FROM_DATABASE=6300ESB SATA RAID Controller (CR11/VR11 Single Board Computer) pci:v00008086d000025B0sv00004C53sd000010D0* ID_MODEL_FROM_DATABASE=6300ESB SATA RAID Controller (Telum ASLP10 Processor AMC) pci:v00008086d000025B0sv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=6300ESB SATA RAID Controller (PSL09 PrPMC) pci:v00008086d000025C0* ID_MODEL_FROM_DATABASE=5000X Chipset Memory Controller Hub pci:v00008086d000025D0* ID_MODEL_FROM_DATABASE=5000Z Chipset Memory Controller Hub pci:v00008086d000025D4* ID_MODEL_FROM_DATABASE=5000V Chipset Memory Controller Hub pci:v00008086d000025D4sv000015D9sd00008680* ID_MODEL_FROM_DATABASE=5000V Chipset Memory Controller Hub (X7DVL-E-O motherboard) pci:v00008086d000025D8* ID_MODEL_FROM_DATABASE=5000P Chipset Memory Controller Hub pci:v00008086d000025D8sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=5000P Chipset Memory Controller Hub (X7DBN Motherboard) pci:v00008086d000025D8sv00008086sd00003476* ID_MODEL_FROM_DATABASE=5000P Chipset Memory Controller Hub (S5000PSLSATA Server Board) pci:v00008086d000025E2* ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x4 Port 2 pci:v00008086d000025E3* ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x4 Port 3 pci:v00008086d000025E4* ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x4 Port 4 pci:v00008086d000025E5* ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x4 Port 5 pci:v00008086d000025E6* ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x4 Port 6 pci:v00008086d000025E7* ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x4 Port 7 pci:v00008086d000025F0* ID_MODEL_FROM_DATABASE=5000 Series Chipset FSB Registers pci:v00008086d000025F0sv00001028sd000001BB* ID_MODEL_FROM_DATABASE=5000 Series Chipset FSB Registers (PowerEdge 1955 FSB Registers) pci:v00008086d000025F0sv0000103Csd000031FD* ID_MODEL_FROM_DATABASE=5000 Series Chipset FSB Registers (ProLiant DL140 G3) pci:v00008086d000025F0sv000015D9sd00008680* ID_MODEL_FROM_DATABASE=5000 Series Chipset FSB Registers (X7DVL-E-O motherboard) pci:v00008086d000025F0sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=5000 Series Chipset FSB Registers (X7DBN Motherboard) pci:v00008086d000025F0sv00008086sd00003476* ID_MODEL_FROM_DATABASE=5000 Series Chipset FSB Registers (S5000PSLSATA Server Board) pci:v00008086d000025F1* ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers pci:v00008086d000025F1sv0000103Csd000031FD* ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (ProLiant DL140 G3) pci:v00008086d000025F1sv000015D9sd00008680* ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (X7DVL-E-O motherboard) pci:v00008086d000025F1sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (X7DBN Motherboard) pci:v00008086d000025F1sv00008086sd00003476* ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (S5000PSLSATA Server Board) pci:v00008086d000025F3* ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers pci:v00008086d000025F3sv0000103Csd000031FD* ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (ProLiant DL140 G3) pci:v00008086d000025F3sv000015D9sd00008680* ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (X7DVL-E-O motherboard) pci:v00008086d000025F3sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (X7DBN Motherboard) pci:v00008086d000025F3sv00008086sd00003476* ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (S5000PSLSATA Server Board) pci:v00008086d000025F5* ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers pci:v00008086d000025F5sv0000103Csd000031FD* ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (ProLiant DL140 G3) pci:v00008086d000025F5sv000015D9sd00008680* ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (X7DVL-E-O motherboard) pci:v00008086d000025F5sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (X7DBN Motherboard) pci:v00008086d000025F5sv00008086sd00003476* ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (S5000PSLSATA Server Board) pci:v00008086d000025F6* ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers pci:v00008086d000025F6sv0000103Csd000031FD* ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (ProLiant DL140 G3) pci:v00008086d000025F6sv000015D9sd00008680* ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (X7DVL-E-O motherboard) pci:v00008086d000025F6sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (X7DBN Motherboard) pci:v00008086d000025F6sv00008086sd00003476* ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (S5000PSLSATA Server Board) pci:v00008086d000025F7* ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x8 Port 2-3 pci:v00008086d000025F8* ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x8 Port 4-5 pci:v00008086d000025F9* ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x8 Port 6-7 pci:v00008086d000025FA* ID_MODEL_FROM_DATABASE=5000X Chipset PCI Express x16 Port 4-7 pci:v00008086d00002600* ID_MODEL_FROM_DATABASE=E8500/E8501 Hub Interface 1.5 pci:v00008086d00002600sv00001028sd00000170* ID_MODEL_FROM_DATABASE=E8500/E8501 Hub Interface 1.5 (PowerEdge 6850 Hub Interface) pci:v00008086d00002601* ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port D pci:v00008086d00002602* ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port C0 pci:v00008086d00002603* ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port C1 pci:v00008086d00002604* ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port B0 pci:v00008086d00002605* ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port B1 pci:v00008086d00002606* ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port A0 pci:v00008086d00002607* ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port A1 pci:v00008086d00002608* ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x8 Port C pci:v00008086d00002609* ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x8 Port B pci:v00008086d0000260A* ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x8 Port A pci:v00008086d0000260C* ID_MODEL_FROM_DATABASE=E8500/E8501 IMI Registers pci:v00008086d00002610* ID_MODEL_FROM_DATABASE=E8500/E8501 FSB Registers pci:v00008086d00002611* ID_MODEL_FROM_DATABASE=E8500/E8501 Address Mapping Registers pci:v00008086d00002612* ID_MODEL_FROM_DATABASE=E8500/E8501 RAS Registers pci:v00008086d00002613* ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers pci:v00008086d00002614* ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers pci:v00008086d00002615* ID_MODEL_FROM_DATABASE=E8500/E8501 Miscellaneous Registers pci:v00008086d00002617* ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers pci:v00008086d00002618* ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers pci:v00008086d00002619* ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers pci:v00008086d0000261A* ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers pci:v00008086d0000261B* ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers pci:v00008086d0000261C* ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers pci:v00008086d0000261D* ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers pci:v00008086d0000261E* ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers pci:v00008086d00002620* ID_MODEL_FROM_DATABASE=E8500/E8501 eXternal Memory Bridge pci:v00008086d00002620sv00001028sd00000170* ID_MODEL_FROM_DATABASE=E8500/E8501 eXternal Memory Bridge (PowerEdge 6850 Memory Bridge) pci:v00008086d00002621* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Miscellaneous Registers pci:v00008086d00002621sv00001028sd00000170* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Miscellaneous Registers (PowerEdge 6850 XMB Registers) pci:v00008086d00002622* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Memory Interleaving Registers pci:v00008086d00002622sv00001028sd00000170* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Memory Interleaving Registers (PowerEdge 6850 Memory Interleaving Registers) pci:v00008086d00002623* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB DDR Initialization and Calibration pci:v00008086d00002623sv00001028sd00000170* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB DDR Initialization and Calibration (PowerEdge 6850 DDR Initialization and Calibration) pci:v00008086d00002624* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers pci:v00008086d00002624sv00001028sd00000170* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers (PowerEdge 6850 Reserved Registers) pci:v00008086d00002625* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers pci:v00008086d00002625sv00001028sd00000170* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers (PowerEdge 6850 Reserved Registers) pci:v00008086d00002626* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers pci:v00008086d00002626sv00001028sd00000170* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers (PowerEdge 6850 Reserved Registers) pci:v00008086d00002627* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers pci:v00008086d00002627sv00001028sd00000170* ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers (PowerEdge 6850 Reserved Registers) pci:v00008086d00002640* ID_MODEL_FROM_DATABASE=82801FB/FR (ICH6/ICH6R) LPC Interface Bridge pci:v00008086d00002640sv00001462sd00007028* ID_MODEL_FROM_DATABASE=82801FB/FR (ICH6/ICH6R) LPC Interface Bridge (915P/G Neo2) pci:v00008086d00002640sv00001734sd0000105C* ID_MODEL_FROM_DATABASE=82801FB/FR (ICH6/ICH6R) LPC Interface Bridge (Scenic W620) pci:v00008086d00002640sv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=82801FB/FR (ICH6/ICH6R) LPC Interface Bridge (CCD-CALYPSO) pci:v00008086d00002640sv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=82801FB/FR (ICH6/ICH6R) LPC Interface Bridge (CD3-JIVE) pci:v00008086d00002640sv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=82801FB/FR (ICH6/ICH6R) LPC Interface Bridge (XB1) pci:v00008086d00002641* ID_MODEL_FROM_DATABASE=82801FBM (ICH6M) LPC Interface Bridge pci:v00008086d00002641sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=82801FBM (ICH6M) LPC Interface Bridge (Compaq nw8240/nx8220) pci:v00008086d00002641sv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=82801FBM (ICH6M) LPC Interface Bridge (NX6110/NC6120) pci:v00008086d00002642* ID_MODEL_FROM_DATABASE=82801FW/FRW (ICH6W/ICH6RW) LPC Interface Bridge pci:v00008086d00002651* ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller pci:v00008086d00002651sv00001028sd00000179* ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (Optiplex GX280) pci:v00008086d00002651sv00001043sd00002601* ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (P5GD1-VW Mainboard) pci:v00008086d00002651sv00001734sd0000105C* ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (Scenic W620) pci:v00008086d00002651sv00008086sd00004147* ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (D915GAG Motherboard) pci:v00008086d00002651sv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (CCD-CALYPSO) pci:v00008086d00002651sv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (CD3-JIVE) pci:v00008086d00002651sv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (XB1) pci:v00008086d00002652* ID_MODEL_FROM_DATABASE=82801FR/FRW (ICH6R/ICH6RW) SATA Controller pci:v00008086d00002652sv00001028sd00000177* ID_MODEL_FROM_DATABASE=82801FR/FRW (ICH6R/ICH6RW) SATA Controller (Dimension 8400) pci:v00008086d00002652sv00001462sd00007028* ID_MODEL_FROM_DATABASE=82801FR/FRW (ICH6R/ICH6RW) SATA Controller (915P/G Neo2) pci:v00008086d00002653* ID_MODEL_FROM_DATABASE=82801FBM (ICH6M) SATA Controller pci:v00008086d00002658* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 pci:v00008086d00002658sv00001028sd00000177* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (Dimension 8400) pci:v00008086d00002658sv00001028sd00000179* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (Optiplex GX280) pci:v00008086d00002658sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (Compaq nw8240/nx8220) pci:v00008086d00002658sv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (NX6110/NC6120) pci:v00008086d00002658sv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (P5GD1-VW Mainboard) pci:v00008086d00002658sv00001458sd00002558* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (GA-8I915ME-G Mainboard) pci:v00008086d00002658sv00001462sd00007028* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (915P/G Neo2) pci:v00008086d00002658sv00001734sd0000105C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (Scenic W620) pci:v00008086d00002658sv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (CCD-CALYPSO) pci:v00008086d00002658sv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (CD3-JIVE) pci:v00008086d00002658sv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (XB1) pci:v00008086d00002659* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 pci:v00008086d00002659sv00001028sd00000177* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (Dimension 8400) pci:v00008086d00002659sv00001028sd00000179* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (Optiplex GX280) pci:v00008086d00002659sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (Compaq nw8240/nx8220) pci:v00008086d00002659sv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (NX6110/NC6120) pci:v00008086d00002659sv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (P5GD1-VW Mainboard) pci:v00008086d00002659sv00001458sd00002659* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (GA-8I915ME-G Mainboard) pci:v00008086d00002659sv00001462sd00007028* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (915P/G Neo2) pci:v00008086d00002659sv00001734sd0000105C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (Scenic W620) pci:v00008086d00002659sv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (CCD-CALYPSO) pci:v00008086d00002659sv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (CD3-JIVE) pci:v00008086d00002659sv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (XB1) pci:v00008086d0000265A* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 pci:v00008086d0000265Asv00001028sd00000177* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (Dimension 8400) pci:v00008086d0000265Asv00001028sd00000179* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (Optiplex GX280) pci:v00008086d0000265Asv0000103Csd00000934* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (Compaq nw8240/nx8220) pci:v00008086d0000265Asv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (NX6110/NC6120) pci:v00008086d0000265Asv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (P5GD1-VW Mainboard) pci:v00008086d0000265Asv00001458sd0000265A* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (GA-8I915ME-G Mainboard) pci:v00008086d0000265Asv00001462sd00007028* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (915P/G Neo2) pci:v00008086d0000265Asv00001734sd0000105C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (Scenic W620) pci:v00008086d0000265Asv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (CCD-CALYPSO) pci:v00008086d0000265Asv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (CD3-JIVE) pci:v00008086d0000265Asv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (XB1) pci:v00008086d0000265B* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 pci:v00008086d0000265Bsv00001028sd00000177* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (Dimension 8400) pci:v00008086d0000265Bsv00001028sd00000179* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (Optiplex GX280) pci:v00008086d0000265Bsv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (NX6110/NC6120) pci:v00008086d0000265Bsv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (P5GD1-VW Mainboard) pci:v00008086d0000265Bsv00001458sd0000265A* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (GA-8I915ME-G Mainboard) pci:v00008086d0000265Bsv00001462sd00007028* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (915P/G Neo2) pci:v00008086d0000265Bsv00001734sd0000105C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (Scenic W620) pci:v00008086d0000265Bsv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (CCD-CALYPSO) pci:v00008086d0000265Bsv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (CD3-JIVE) pci:v00008086d0000265Bsv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (XB1) pci:v00008086d0000265C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller pci:v00008086d0000265Csv00001028sd00000177* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (Dimension 8400) pci:v00008086d0000265Csv00001028sd00000179* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (Optiplex GX280) pci:v00008086d0000265Csv0000103Csd00000934* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (Compaq nw8240/nx8220) pci:v00008086d0000265Csv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (NX6110/NC6120) pci:v00008086d0000265Csv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (P5GD1-VW Mainboard) pci:v00008086d0000265Csv00001458sd00005006* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (GA-8I915ME-G Mainboard) pci:v00008086d0000265Csv00001462sd00007028* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (915P/G Neo2) pci:v00008086d0000265Csv00001734sd0000105C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (Scenic W620) pci:v00008086d0000265Csv00008086sd0000265C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (Dimension 3100) pci:v00008086d0000265Csv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (CCD-CALYPSO) pci:v00008086d0000265Csv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (CD3-JIVE) pci:v00008086d0000265Csv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (XB1) pci:v00008086d00002660* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 pci:v00008086d00002660sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 (Compaq nw8240 Mobile Workstation) pci:v00008086d00002660sv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 (NX6110/NC6120) pci:v00008086d00002660sv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 (CCD-CALYPSO) pci:v00008086d00002660sv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 (CD3-JIVE) pci:v00008086d00002660sv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 (XB1) pci:v00008086d00002662* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 pci:v00008086d00002662sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 (Compaq nw8240 Mobile Workstation) pci:v00008086d00002662sv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 (CCD-CALYPSO) pci:v00008086d00002662sv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 (CD3-JIVE) pci:v00008086d00002662sv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 (XB1) pci:v00008086d00002664* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3 pci:v00008086d00002664sv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3 (CCD-CALYPSO) pci:v00008086d00002664sv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3 (CD3-JIVE) pci:v00008086d00002664sv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3 (XB1) pci:v00008086d00002666* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4 pci:v00008086d00002666sv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4 (CCD-CALYPSO) pci:v00008086d00002666sv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4 (CD3-JIVE) pci:v00008086d00002666sv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4 (XB1) pci:v00008086d00002668* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller pci:v00008086d00002668sv00001014sd000005B7* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (ThinkPad Z60t) pci:v00008086d00002668sv0000103Csd00002A09* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (PufferM-UL8E) pci:v00008086d00002668sv00001043sd00001173* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (Asus A6VC) pci:v00008086d00002668sv00001043sd0000814E* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (P5GD1-VW Mainboard) pci:v00008086d00002668sv00001462sd00007028* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (915P/G Neo2) pci:v00008086d00002668sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (QEMU Virtual Machine) pci:v00008086d0000266A* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller pci:v00008086d0000266Asv00001028sd00000177* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (Dimension 8400) pci:v00008086d0000266Asv00001028sd00000179* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (Optiplex GX280) pci:v00008086d0000266Asv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (P5GD1-VW Mainboard) pci:v00008086d0000266Asv00001458sd0000266A* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (GA-8I915ME-G Mainboard) pci:v00008086d0000266Asv00001462sd00007028* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (915P/G Neo2) pci:v00008086d0000266Asv00001734sd0000105C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (Scenic W620) pci:v00008086d0000266Asv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (CCD-CALYPSO) pci:v00008086d0000266Asv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (CD3-JIVE) pci:v00008086d0000266Asv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (XB1) pci:v00008086d0000266C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller pci:v00008086d0000266D* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller pci:v00008086d0000266Dsv00001025sd0000006A* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller (Conexant AC'97 CoDec (in Acer TravelMate 2410 serie laptop)) pci:v00008086d0000266Dsv0000103Csd00000934* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller (Compaq nw8240/nx8220) pci:v00008086d0000266Dsv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller (NX6110/NC6120) pci:v00008086d0000266E* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller pci:v00008086d0000266Esv00001025sd0000006A* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Realtek ALC 655 codec (in Acer TravelMate 2410 serie laptop)) pci:v00008086d0000266Esv00001028sd00000177* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Dimension 8400) pci:v00008086d0000266Esv00001028sd00000179* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Optiplex GX280) pci:v00008086d0000266Esv00001028sd00000182* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Latitude D610 Laptop) pci:v00008086d0000266Esv00001028sd00000187* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Dell Precision M70 Laptop) pci:v00008086d0000266Esv00001028sd00000188* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Inspiron 6000 laptop) pci:v00008086d0000266Esv0000103Csd00000934* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Compaq nw8240/nx8220) pci:v00008086d0000266Esv0000103Csd00000944* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Compaq NC6220) pci:v00008086d0000266Esv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (NX6110/NC6120) pci:v00008086d0000266Esv0000103Csd00003006* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (DC7100 SFF(DX878AV)) pci:v00008086d0000266Esv00001458sd0000A002* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (GA-8I915ME-G Mainboard) pci:v00008086d0000266Esv0000152Dsd00000745* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Packard Bell A8550 Laptop) pci:v00008086d0000266Esv00001734sd0000105A* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Scenic W620) pci:v00008086d0000266F* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller pci:v00008086d0000266Fsv00001028sd00000177* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (Dimension 8400) pci:v00008086d0000266Fsv0000103Csd00000934* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (Compaq nw8240/nx8220) pci:v00008086d0000266Fsv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (NX6110/NC6120) pci:v00008086d0000266Fsv00001043sd000080A6* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (P5GD1-VW Mainboard) pci:v00008086d0000266Fsv00001458sd0000266F* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (GA-8I915ME-G Mainboard) pci:v00008086d0000266Fsv00001462sd00007028* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (915P/G Neo2) pci:v00008086d0000266Fsv00001734sd0000105C* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (Scenic W620) pci:v00008086d0000266Fsv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (CCD-CALYPSO) pci:v00008086d0000266Fsv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (CD3-JIVE) pci:v00008086d0000266Fsv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (XB1) pci:v00008086d00002670* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset LPC Interface Controller pci:v00008086d00002670sv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset LPC Interface Controller (ProLiant DL140 G3) pci:v00008086d00002670sv000015D9sd00008680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset LPC Interface Controller (X7DVL-E-O motherboard) pci:v00008086d00002670sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset LPC Interface Controller (X7DBN Motherboard) pci:v00008086d00002670sv00008086sd00003476* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset LPC Interface Controller (Intel S5000PSLSATA Server Board) pci:v00008086d00002680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset SATA IDE Controller pci:v00008086d00002681* ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA AHCI Controller pci:v00008086d00002681sv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA AHCI Controller (ProLiant DL140 G3) pci:v00008086d00002681sv000015D9sd00008680* ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA AHCI Controller (X7DVL-E-O motherboard) pci:v00008086d00002681sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA AHCI Controller (X7DBN Motherboard) pci:v00008086d00002681sv00008086sd00003476* ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA AHCI Controller (Intel S5000PSLSATA Server Board) pci:v00008086d00002682* ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA RAID Controller pci:v00008086d00002682sv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA RAID Controller (Adaptec Serial ATA HostRAID) pci:v00008086d00002683* ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA RAID Controller pci:v00008086d00002688* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 pci:v00008086d00002688sv00001028sd000001BB* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 (PowerEdge 1955 onboard USB) pci:v00008086d00002688sv00001028sd000001F0* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 (PowerEdge R900 onboard USB) pci:v00008086d00002688sv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 (ProLiant DL140 G3) pci:v00008086d00002688sv000015D9sd00008680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 (X7DVL-E-O motherboard) pci:v00008086d00002688sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 (X7DBN Motherboard) pci:v00008086d00002688sv00008086sd00003476* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 (Intel S5000PSLSATA Server Board) pci:v00008086d00002689* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 pci:v00008086d00002689sv00001028sd000001BB* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 (PowerEdge 1955 onboard USB) pci:v00008086d00002689sv00001028sd000001F0* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 (PowerEdge R900 onboard USB) pci:v00008086d00002689sv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 (ProLiant DL140 G3) pci:v00008086d00002689sv000015D9sd00008680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 (X7DVL-E-O motherboard) pci:v00008086d00002689sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 (X7DBN Motherboard) pci:v00008086d00002689sv00008086sd00003476* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 (Intel S5000PSLSATA Server Board) pci:v00008086d0000268A* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #3 pci:v00008086d0000268Asv00001028sd000001F0* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #3 (PowerEdge R900 onboard USB) pci:v00008086d0000268Asv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #3 (ProLiant DL140 G3) pci:v00008086d0000268Asv000015D9sd00008680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #3 (X7DVL-E-O motherboard) pci:v00008086d0000268Asv000015D9sd00009680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #3 (X7DBN Motherboard) pci:v00008086d0000268Asv00008086sd00003476* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #3 (Intel S5000PSLSATA Server Board) pci:v00008086d0000268B* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #4 pci:v00008086d0000268Bsv00001028sd000001F0* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #4 (PowerEdge R900 onboard USB) pci:v00008086d0000268Bsv000015D9sd00008680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #4 (X7DVL-E-O motherboard) pci:v00008086d0000268Bsv00008086sd00003476* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #4 (Intel S5000PSLSATA Server Board) pci:v00008086d0000268C* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller pci:v00008086d0000268Csv00001028sd000001BB* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller (PowerEdge 1955 onboard USB) pci:v00008086d0000268Csv00001028sd000001F0* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller (PowerEdge R900 onboard USB) pci:v00008086d0000268Csv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller (ProLiant DL140 G3) pci:v00008086d0000268Csv000015D9sd00008680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller (X7DVL-E-O motherboard) pci:v00008086d0000268Csv000015D9sd00009680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller (X7DBN Motherboard) pci:v00008086d0000268Csv00008086sd00003476* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller (Intel S5000PSLSATA Server Board) pci:v00008086d00002690* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 1 pci:v00008086d00002690sv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 1 (ProLiant DL140 G3) pci:v00008086d00002690sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 1 (X7DBN Motherboard) pci:v00008086d00002692* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 2 pci:v00008086d00002692sv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 2 (ProLiant DL140 G3) pci:v00008086d00002694* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 3 pci:v00008086d00002696* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 4 pci:v00008086d00002698* ID_MODEL_FROM_DATABASE=631xESB/632xESB AC '97 Audio Controller pci:v00008086d00002699* ID_MODEL_FROM_DATABASE=631xESB/632xESB AC '97 Modem Controller pci:v00008086d0000269A* ID_MODEL_FROM_DATABASE=631xESB/632xESB High Definition Audio Controller pci:v00008086d0000269B* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset SMBus Controller pci:v00008086d0000269Bsv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset SMBus Controller (ProLiant DL140 G3) pci:v00008086d0000269Bsv000015D9sd00008680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset SMBus Controller (X7DVL-E-O motherboard) pci:v00008086d0000269Bsv000015D9sd00009680* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset SMBus Controller (X7DBN Motherboard) pci:v00008086d0000269Bsv00008086sd00003476* ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset SMBus Controller (Intel S5000PSLSATA Server Board) pci:v00008086d0000269E* ID_MODEL_FROM_DATABASE=631xESB/632xESB IDE Controller pci:v00008086d0000269Esv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=631xESB/632xESB IDE Controller (ProLiant DL140 G3) pci:v00008086d0000269Esv000015D9sd00008680* ID_MODEL_FROM_DATABASE=631xESB/632xESB IDE Controller (X7DVL-E-O motherboard) pci:v00008086d0000269Esv000015D9sd00009680* ID_MODEL_FROM_DATABASE=631xESB/632xESB IDE Controller (X7DBN Motherboard) pci:v00008086d00002770* ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub pci:v00008086d00002770sv00001028sd000001AD* ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub (OptiPlex GX620) pci:v00008086d00002770sv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub (Pavilion A1512X) pci:v00008086d00002770sv00001043sd0000817A* ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub (P5LD2-VM Mainboard) pci:v00008086d00002770sv0000107Bsd00005048* ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub (E4500) pci:v00008086d00002770sv00001462sd00007418* ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub (Wind PC MS-7418) pci:v00008086d00002770sv00008086sd0000544E* ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub (DeskTop Board D945GTP) pci:v00008086d00002771* ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL PCI Express Root Port pci:v00008086d00002772* ID_MODEL_FROM_DATABASE=82945G/GZ Integrated Graphics Controller pci:v00008086d00002772sv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=82945G/GZ Integrated Graphics Controller (Pavilion A1512X) pci:v00008086d00002772sv00001462sd00007418* ID_MODEL_FROM_DATABASE=82945G/GZ Integrated Graphics Controller (Wind PC MS-7418) pci:v00008086d00002772sv00008086sd0000544E* ID_MODEL_FROM_DATABASE=82945G/GZ Integrated Graphics Controller (DeskTop Board D945GTP) pci:v00008086d00002772sv00008086sd0000D605* ID_MODEL_FROM_DATABASE=82945G/GZ Integrated Graphics Controller (Intel Desktop Board D945GCCR) pci:v00008086d00002774* ID_MODEL_FROM_DATABASE=82955X Memory Controller Hub pci:v00008086d00002775* ID_MODEL_FROM_DATABASE=82955X PCI Express Root Port pci:v00008086d00002776* ID_MODEL_FROM_DATABASE=82945G/GZ Integrated Graphics Controller pci:v00008086d00002778* ID_MODEL_FROM_DATABASE=E7230/3000/3010 Memory Controller Hub pci:v00008086d00002778sv00001028sd000001DF* ID_MODEL_FROM_DATABASE=E7230/3000/3010 Memory Controller Hub (PowerEdge SC440) pci:v00008086d00002778sv00001028sd000001E6* ID_MODEL_FROM_DATABASE=E7230/3000/3010 Memory Controller Hub (PowerEdge 860) pci:v00008086d00002779* ID_MODEL_FROM_DATABASE=E7230/3000/3010 PCI Express Root Port pci:v00008086d0000277A* ID_MODEL_FROM_DATABASE=82975X/3010 PCI Express Root Port pci:v00008086d0000277C* ID_MODEL_FROM_DATABASE=82975X Memory Controller Hub pci:v00008086d0000277Csv00001043sd00008178* ID_MODEL_FROM_DATABASE=82975X Memory Controller Hub (P5WDG2 WS Professional motherboard) pci:v00008086d0000277D* ID_MODEL_FROM_DATABASE=82975X PCI Express Root Port pci:v00008086d00002782* ID_MODEL_FROM_DATABASE=82915G Integrated Graphics Controller pci:v00008086d00002782sv00001043sd00002582* ID_MODEL_FROM_DATABASE=82915G Integrated Graphics Controller (P5GD1-VW Mainboard) pci:v00008086d00002782sv00001734sd0000105B* ID_MODEL_FROM_DATABASE=82915G Integrated Graphics Controller (Scenic W620) pci:v00008086d00002792* ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller pci:v00008086d00002792sv0000103Csd0000099C* ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (NX6110/NC6120) pci:v00008086d00002792sv00001043sd00001881* ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (GMA 900 915GM Integrated Graphics) pci:v00008086d00002792sv0000E4BFsd00000CCD* ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (CCD-CALYPSO) pci:v00008086d00002792sv0000E4BFsd00000CD3* ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (CD3-JIVE) pci:v00008086d00002792sv0000E4BFsd000058B1* ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (XB1) pci:v00008086d000027A0* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub pci:v00008086d000027A0sv00001025sd0000006C* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (9814 WKMI) pci:v00008086d000027A0sv00001028sd000001D7* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (XPS M1210) pci:v00008086d000027A0sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (Compaq nx9420 Notebook) pci:v00008086d000027A0sv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (NC2400) pci:v00008086d000027A0sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (Compaq nw8440) pci:v00008086d000027A0sv00001043sd00001237* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (A6J-Q008) pci:v00008086d000027A0sv00001071sd00008209* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027A0sv000017AAsd00002015* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (ThinkPad T60) pci:v00008086d000027A0sv000017AAsd00002017* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (ThinkPad R60/T60/X60 series) pci:v00008086d000027A1* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express PCI Express Root Port pci:v00008086d000027A1sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express PCI Express Root Port (Compaq nx9420 Notebook) pci:v00008086d000027A1sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express PCI Express Root Port (Compaq nw8440) pci:v00008086d000027A1sv00001071sd00008209* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express PCI Express Root Port (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027A2* ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller pci:v00008086d000027A2sv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller (NC2400) pci:v00008086d000027A2sv000017AAsd0000201A* ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller (ThinkPad R60/T60/X60 series) pci:v00008086d000027A2sv00009902sd00001584* ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller (CCE MPL-D10H120F) pci:v00008086d000027A6* ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller pci:v00008086d000027A6sv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller (NC2400) pci:v00008086d000027A6sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller (CC11/CL11 integrated graphics (secondary)) pci:v00008086d000027A6sv000017AAsd0000201A* ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller (ThinkPad R60/T60/X60 series) pci:v00008086d000027AC* ID_MODEL_FROM_DATABASE=Mobile 945GSE Express Memory Controller Hub pci:v00008086d000027ACsv00001775sd000011CC* ID_MODEL_FROM_DATABASE=Mobile 945GSE Express Memory Controller Hub (CC11/CL11) pci:v00008086d000027AD* ID_MODEL_FROM_DATABASE=Mobile 945GSE Express PCI Express Root Port pci:v00008086d000027AE* ID_MODEL_FROM_DATABASE=Mobile 945GSE Express Integrated Graphics Controller pci:v00008086d000027AEsv00001775sd000011CC* ID_MODEL_FROM_DATABASE=Mobile 945GSE Express Integrated Graphics Controller (CC11/CL11 integrated graphics (primary)) pci:v00008086d000027B0* ID_MODEL_FROM_DATABASE=82801GH (ICH7DH) LPC Interface Bridge pci:v00008086d000027B0sv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=82801GH (ICH7DH) LPC Interface Bridge (Pavilion A1512X) pci:v00008086d000027B0sv00008086sd0000544E* ID_MODEL_FROM_DATABASE=82801GH (ICH7DH) LPC Interface Bridge (DeskTop Board D945GTP) pci:v00008086d000027B8* ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge pci:v00008086d000027B8sv00001028sd000001E6* ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (PowerEdge 860) pci:v00008086d000027B8sv00001043sd00008179* ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (P5KPL-VM Motherboard) pci:v00008086d000027B8sv0000107Bsd00005048* ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (E4500) pci:v00008086d000027B8sv00001462sd00007418* ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (Wind PC MS-7418) pci:v00008086d000027B8sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (CC11/CL11) pci:v00008086d000027B8sv00008086sd0000544E* ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (DeskTop Board D945GTP) pci:v00008086d000027B9* ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge pci:v00008086d000027B9sv00001028sd000001D7* ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (XPS M1210) pci:v00008086d000027B9sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (Compaq nx9420 Notebook) pci:v00008086d000027B9sv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (NC2400) pci:v00008086d000027B9sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (Compaq nw8440) pci:v00008086d000027B9sv00001071sd00008209* ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027B9sv000010F7sd00008338* ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (Panasonic CF-Y5 laptop) pci:v00008086d000027B9sv000017AAsd00002009* ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (ThinkPad R60/T60/X60 series) pci:v00008086d000027BC* ID_MODEL_FROM_DATABASE=NM10 Family LPC Controller pci:v00008086d000027BCsv0000105Bsd00000D7C* ID_MODEL_FROM_DATABASE=NM10 Family LPC Controller (D270S/D250S Motherboard) pci:v00008086d000027BCsv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=NM10 Family LPC Controller (Notebook N150P) pci:v00008086d000027BCsv00001458sd00005001* ID_MODEL_FROM_DATABASE=NM10 Family LPC Controller (GA-D525TUD) pci:v00008086d000027BCsv00008086sd00004F4D* ID_MODEL_FROM_DATABASE=NM10 Family LPC Controller (DeskTop Board D510MO) pci:v00008086d000027BCsv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10 Family LPC Controller (Desktop Board D425KT) pci:v00008086d000027BD* ID_MODEL_FROM_DATABASE=82801GHM (ICH7-M DH) LPC Interface Bridge pci:v00008086d000027BDsv00001025sd0000006C* ID_MODEL_FROM_DATABASE=82801GHM (ICH7-M DH) LPC Interface Bridge (9814 WKMI) pci:v00008086d000027C0* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] pci:v00008086d000027C0sv00001028sd000001AD* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (OptiPlex GX620) pci:v00008086d000027C0sv00001028sd000001DF* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (PowerEdge SC440) pci:v00008086d000027C0sv00001028sd000001E6* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (PowerEdge 860) pci:v00008086d000027C0sv00001043sd00008179* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (P5KPL-VM Motherboard) pci:v00008086d000027C0sv0000107Bsd00005048* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (E4500) pci:v00008086d000027C0sv00001462sd00002310* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (MSI Hetis 945) pci:v00008086d000027C0sv00001462sd00007236* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (945P Neo3-F Rev. 2.2 motherboard) pci:v00008086d000027C0sv00001462sd00007418* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (Wind PC MS-7418) pci:v00008086d000027C0sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (CC11/CL11) pci:v00008086d000027C0sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (Desktop Board D425KT) pci:v00008086d000027C0sv00008086sd0000544E* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (DeskTop Board D945GTP) pci:v00008086d000027C1* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] pci:v00008086d000027C1sv00001028sd000001DF* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (PowerEdge SC440) pci:v00008086d000027C1sv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (Pavilion A1512X) pci:v00008086d000027C1sv0000105Bsd00000D7C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (D270S/D250S Motherboard) pci:v00008086d000027C1sv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (Notebook N150P) pci:v00008086d000027C1sv00001458sd0000B005* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (GA-D525TUD) pci:v00008086d000027C1sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (CC11/CL11) pci:v00008086d000027C1sv00008086sd00004F4D* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (DeskTop Board D510MO) pci:v00008086d000027C1sv00008086sd00005842* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (DeskTop Board D975XBX) pci:v00008086d000027C3* ID_MODEL_FROM_DATABASE=82801GR/GDH (ICH7R/ICH7DH) SATA Controller [RAID mode] pci:v00008086d000027C3sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=82801GR/GDH (ICH7R/ICH7DH) SATA Controller [RAID mode] (CC11/CL11) pci:v00008086d000027C3sv00008086sd0000544E* ID_MODEL_FROM_DATABASE=82801GR/GDH (ICH7R/ICH7DH) SATA Controller [RAID mode] (DeskTop Board D945GTP) pci:v00008086d000027C4* ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [IDE mode] pci:v00008086d000027C4sv00001025sd0000006C* ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [IDE mode] (9814 WKMI) pci:v00008086d000027C4sv00001028sd000001D7* ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [IDE mode] (XPS M1210) pci:v00008086d000027C4sv00001071sd00008209* ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [IDE mode] (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027C4sv000017AAsd0000200E* ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [IDE mode] (ThinkPad T60) pci:v00008086d000027C5* ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [AHCI mode] pci:v00008086d000027C5sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [AHCI mode] (Compaq nx9420 Notebook) pci:v00008086d000027C5sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [AHCI mode] (Compaq nw8440) pci:v00008086d000027C5sv000017AAsd0000200D* ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [AHCI mode] (ThinkPad R60/T60/X60 series) pci:v00008086d000027C6* ID_MODEL_FROM_DATABASE=82801GHM (ICH7-M DH) SATA Controller [RAID mode] pci:v00008086d000027C8* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 pci:v00008086d000027C8sv00001025sd0000006C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (9814 WKMI) pci:v00008086d000027C8sv00001028sd000001AD* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (OptiPlex GX620) pci:v00008086d000027C8sv00001028sd000001D7* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (XPS M1210) pci:v00008086d000027C8sv00001028sd000001DF* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (PowerEdge SC440) pci:v00008086d000027C8sv00001028sd000001E6* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (PowerEdge 860) pci:v00008086d000027C8sv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Pavilion A1512X) pci:v00008086d000027C8sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Compaq nx9420 Notebook) pci:v00008086d000027C8sv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (NC2400) pci:v00008086d000027C8sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Compaq nw8440) pci:v00008086d000027C8sv00001043sd00001237* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (A6J-Q008) pci:v00008086d000027C8sv00001043sd00008179* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (P5KPL-VM,P5LD2-VM Mainboard) pci:v00008086d000027C8sv0000105Bsd00000D7C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (D270S/D250S Motherboard) pci:v00008086d000027C8sv00001071sd00008209* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027C8sv0000107Bsd00005048* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (E4500) pci:v00008086d000027C8sv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Notebook N150P) pci:v00008086d000027C8sv00001458sd00005004* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (GA-D525TUD) pci:v00008086d000027C8sv00001462sd00007418* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Wind PC MS-7418) pci:v00008086d000027C8sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (CC11/CL11) pci:v00008086d000027C8sv000017AAsd0000200A* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (ThinkPad R60/T60/X60 series) pci:v00008086d000027C8sv00008086sd00004F4D* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (DeskTop Board D510MO) pci:v00008086d000027C8sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Desktop Board D425KT) pci:v00008086d000027C8sv00008086sd0000544E* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (DeskTop Board D945GTP) pci:v00008086d000027C9* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 pci:v00008086d000027C9sv00001025sd0000006C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (9814 WKMI) pci:v00008086d000027C9sv00001028sd000001AD* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (OptiPlex GX620) pci:v00008086d000027C9sv00001028sd000001D7* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (XPS M1210) pci:v00008086d000027C9sv00001028sd000001DF* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (PowerEdge SC440) pci:v00008086d000027C9sv00001028sd000001E6* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (PowerEdge 860) pci:v00008086d000027C9sv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Pavilion A1512X) pci:v00008086d000027C9sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Compaq nx9420 Notebook) pci:v00008086d000027C9sv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (NC2400) pci:v00008086d000027C9sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Compaq nw8440) pci:v00008086d000027C9sv00001043sd00001237* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (A6J-Q008) pci:v00008086d000027C9sv00001043sd00008179* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (P5KPL-VM,P5LD2-VM Mainboard) pci:v00008086d000027C9sv0000105Bsd00000D7C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (D270S/D250S Motherboard) pci:v00008086d000027C9sv00001071sd00008209* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027C9sv0000107Bsd00005048* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (E4500) pci:v00008086d000027C9sv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Notebook N150P) pci:v00008086d000027C9sv00001458sd00005004* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (GA-D525TUD) pci:v00008086d000027C9sv00001462sd00007418* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Wind PC MS-7418) pci:v00008086d000027C9sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (CC11/CL11) pci:v00008086d000027C9sv000017AAsd0000200A* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (ThinkPad R60/T60/X60 series) pci:v00008086d000027C9sv00008086sd00004F4D* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (DeskTop Board D510MO) pci:v00008086d000027C9sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Desktop Board D425KT) pci:v00008086d000027C9sv00008086sd0000544E* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (DeskTop Board D945GTP) pci:v00008086d000027CA* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 pci:v00008086d000027CAsv00001025sd0000006C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (9814 WKMI) pci:v00008086d000027CAsv00001028sd000001AD* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (OptiPlex GX620) pci:v00008086d000027CAsv00001028sd000001D7* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (XPS M1210) pci:v00008086d000027CAsv00001028sd000001DF* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (PowerEdge SC440) pci:v00008086d000027CAsv00001028sd000001E6* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (PowerEdge 860) pci:v00008086d000027CAsv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Pavilion A1512X) pci:v00008086d000027CAsv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Compaq nx9420 Notebook) pci:v00008086d000027CAsv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (NC2400) pci:v00008086d000027CAsv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Compaq nw8440) pci:v00008086d000027CAsv00001043sd00001237* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (A6J-Q008) pci:v00008086d000027CAsv00001043sd00008179* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (P5KPL-VM,P5LD2-VM Mainboard) pci:v00008086d000027CAsv0000105Bsd00000D7C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (D270S/D250S Motherboard) pci:v00008086d000027CAsv00001071sd00008209* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027CAsv0000107Bsd00005048* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (E4500) pci:v00008086d000027CAsv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Notebook N150P) pci:v00008086d000027CAsv00001458sd00005004* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (GA-D525TUD) pci:v00008086d000027CAsv00001462sd00007418* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Wind PC MS-7418) pci:v00008086d000027CAsv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (CC11/CL11) pci:v00008086d000027CAsv000017AAsd0000200A* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (ThinkPad R60/T60/X60 series) pci:v00008086d000027CAsv00008086sd00004F4D* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (DeskTop Board D510MO) pci:v00008086d000027CAsv00008086sd0000544E* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (DeskTop Board D945GTP) pci:v00008086d000027CB* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 pci:v00008086d000027CBsv00001025sd0000006C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (9814 WKMI) pci:v00008086d000027CBsv00001028sd000001AD* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (OptiPlex GX620) pci:v00008086d000027CBsv00001028sd000001D7* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (XPS M1210) pci:v00008086d000027CBsv00001028sd000001DF* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (PowerEdge SC440) pci:v00008086d000027CBsv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Pavilion A1512X) pci:v00008086d000027CBsv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Compaq nx9420 Notebook) pci:v00008086d000027CBsv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (NC2400) pci:v00008086d000027CBsv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Compaq nw8440) pci:v00008086d000027CBsv00001043sd00001237* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (A6J-Q008) pci:v00008086d000027CBsv00001043sd00008179* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (P5KPL-VM,P5LD2-VM Mainboard) pci:v00008086d000027CBsv0000105Bsd00000D7C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (D270S/D250S Motherboard) pci:v00008086d000027CBsv00001071sd00008209* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027CBsv0000107Bsd00005048* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (E4500) pci:v00008086d000027CBsv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Notebook N150P) pci:v00008086d000027CBsv00001458sd00005004* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (GA-D525TUD) pci:v00008086d000027CBsv00001462sd00007418* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Wind PC MS-7418) pci:v00008086d000027CBsv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (CC11/CL11) pci:v00008086d000027CBsv000017AAsd0000200A* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (ThinkPad R60/T60/X60 series) pci:v00008086d000027CBsv00008086sd00004F4D* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (DeskTop Board D510MO) pci:v00008086d000027CBsv00008086sd0000544E* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (DeskTop Board D945GTP) pci:v00008086d000027CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller pci:v00008086d000027CCsv00001025sd0000006C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (9814 WKMI) pci:v00008086d000027CCsv00001028sd000001AD* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (OptiPlex GX620) pci:v00008086d000027CCsv00001028sd000001D7* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (XPS M1210) pci:v00008086d000027CCsv00001028sd000001DF* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (PowerEdge SC440) pci:v00008086d000027CCsv00001028sd000001E6* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (PowerEdge 860) pci:v00008086d000027CCsv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Pavilion A1512X) pci:v00008086d000027CCsv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Compaq nx9420 Notebook) pci:v00008086d000027CCsv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (NC2400) pci:v00008086d000027CCsv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Compaq nw8440) pci:v00008086d000027CCsv00001043sd00001237* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (A6J-Q008) pci:v00008086d000027CCsv00001043sd00008179* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (P5KPL-VM,P5LD2-VM Mainboard) pci:v00008086d000027CCsv0000105Bsd00000D7C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (D270S/D250S Motherboard) pci:v00008086d000027CCsv00001071sd00008209* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027CCsv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Notebook N150P) pci:v00008086d000027CCsv00001458sd00005006* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (GA-D525TUD) pci:v00008086d000027CCsv00001462sd00007418* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Wind PC MS-7418) pci:v00008086d000027CCsv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (CC11/CL11) pci:v00008086d000027CCsv000017AAsd0000200B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (ThinkPad R60/T60/X60 series) pci:v00008086d000027CCsv00008086sd00004F4D* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (DeskTop Board D510MO) pci:v00008086d000027CCsv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Desktop Board D425KT) pci:v00008086d000027CCsv00008086sd0000544E* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (DeskTop Board D945GTP) pci:v00008086d000027D0* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 pci:v00008086d000027D0sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (Compaq nx9420 Notebook) pci:v00008086d000027D0sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (Compaq nw8440) pci:v00008086d000027D0sv00001071sd00008209* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027D0sv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (Notebook N150P) pci:v00008086d000027D0sv00001458sd00005001* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (GA-D525TUD) pci:v00008086d000027D0sv00001462sd00007418* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (Wind PC MS-7418) pci:v00008086d000027D0sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (CC11/CL11) pci:v00008086d000027D0sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (Desktop Board D425KT) pci:v00008086d000027D2* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 pci:v00008086d000027D2sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (Compaq nx9420 Notebook) pci:v00008086d000027D2sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (Compaq nw8440) pci:v00008086d000027D2sv00001071sd00008209* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027D2sv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (Notebook N150P) pci:v00008086d000027D2sv00001462sd00007418* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (Wind PC MS-7418) pci:v00008086d000027D2sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (CC11/CL11) pci:v00008086d000027D2sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (Desktop Board D425KT) pci:v00008086d000027D4* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 pci:v00008086d000027D4sv00001071sd00008209* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027D4sv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (Notebook N150P) pci:v00008086d000027D4sv00001462sd00007418* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (Wind PC MS-7418) pci:v00008086d000027D4sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (CC11/CL11) pci:v00008086d000027D4sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (Desktop Board D425KT) pci:v00008086d000027D6* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 pci:v00008086d000027D6sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (Compaq nw8440) pci:v00008086d000027D6sv00001071sd00008209* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027D6sv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (Notebook N150P) pci:v00008086d000027D6sv00001462sd00007418* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (Wind PC MS-7418) pci:v00008086d000027D6sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (CC11/CL11) pci:v00008086d000027D6sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (Desktop Board D425KT) pci:v00008086d000027D8* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller pci:v00008086d000027D8sv00001025sd0000006C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (9814 WKMI) pci:v00008086d000027D8sv00001028sd000001D7* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (XPS M1210) pci:v00008086d000027D8sv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Pavilion A1512X) pci:v00008086d000027D8sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Compaq nx9420 Notebook) pci:v00008086d000027D8sv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (NC2400) pci:v00008086d000027D8sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Compaq nw8440) pci:v00008086d000027D8sv00001043sd00001123* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (A6J-Q008) pci:v00008086d000027D8sv00001043sd000013C4* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Asus G2P) pci:v00008086d000027D8sv00001043sd0000817F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (P5LD2-VM Mainboard (Realtek ALC 882 codec)) pci:v00008086d000027D8sv00001043sd00008290* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (P5KPL-VM Motherboard) pci:v00008086d000027D8sv00001043sd000082EA* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (P5KPL-CM Motherboard) pci:v00008086d000027D8sv0000105Bsd00000D7C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (D270S/D250S Motherboard) pci:v00008086d000027D8sv00001071sd00008207* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027D8sv0000107Bsd00005048* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (E4500) pci:v00008086d000027D8sv000010F7sd00008338* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Panasonic CF-Y5 laptop) pci:v00008086d000027D8sv00001179sd0000FF10* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Toshiba Satellite A100-796 audio (Realtek ALC861)) pci:v00008086d000027D8sv00001179sd0000FF31* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (AC97 Data Fax SoftModem with SmartCP) pci:v00008086d000027D8sv00001447sd00001043* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Asus A8JP (Analog Devices AD1986A)) pci:v00008086d000027D8sv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Notebook N150P) pci:v00008086d000027D8sv00001458sd0000A002* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (GA-D525TUD (Realtek ALC887)) pci:v00008086d000027D8sv00001458sd0000A102* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (GA-8I945PG-RH Mainboard) pci:v00008086d000027D8sv00001462sd00007418* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Wind PC MS-7418) pci:v00008086d000027D8sv0000152Dsd00000753* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Softmodem) pci:v00008086d000027D8sv00001734sd000010AD* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Conexant softmodem SmartCP) pci:v00008086d000027D8sv000017AAsd00002010* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (ThinkPad R60/T60/X60 series) pci:v00008086d000027D8sv000017AAsd00003802* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Lenovo 3000 C200 audio [Realtek ALC861VD]) pci:v00008086d000027D8sv00008086sd00001112* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (DeskTop Board D945GTP) pci:v00008086d000027D8sv00008086sd000027D8* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (DeskTop Board D945GTP) pci:v00008086d000027D8sv00008086sd0000D618* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (DeskTop Board D510MO) pci:v00008086d000027D8sv00008384sd00007680* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (STAC9221 HD Audio Codec) pci:v00008086d000027DA* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller pci:v00008086d000027DAsv00001025sd0000006C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (9814 WKMI) pci:v00008086d000027DAsv00001028sd000001AD* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (OptiPlex GX620) pci:v00008086d000027DAsv00001028sd000001D7* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (XPS M1210) pci:v00008086d000027DAsv00001028sd000001DF* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (PowerEdge SC440) pci:v00008086d000027DAsv00001028sd000001E6* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (PowerEdge 860) pci:v00008086d000027DAsv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Pavilion A1512X) pci:v00008086d000027DAsv00001043sd00008179* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (P5KPL-VM Motherboard) pci:v00008086d000027DAsv0000105Bsd00000D7C* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (D270S/D250S Motherboard) pci:v00008086d000027DAsv00001071sd00008209* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Medion MIM 2240 Notebook PC [MD98100]) pci:v00008086d000027DAsv000010F7sd00008338* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Panasonic CF-Y5 laptop) pci:v00008086d000027DAsv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Notebook N150P) pci:v00008086d000027DAsv00001458sd00005001* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (GA-8I945PG-RH/GA-D525TUD Mainboard) pci:v00008086d000027DAsv00001462sd00007418* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Wind PC MS-7418) pci:v00008086d000027DAsv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (CC11/CL11) pci:v00008086d000027DAsv000017AAsd0000200F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (ThinkPad R60/T60/X60 series) pci:v00008086d000027DAsv00008086sd00004F4D* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (DeskTop Board D510MO) pci:v00008086d000027DAsv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Desktop Board D425KT) pci:v00008086d000027DAsv00008086sd0000544E* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (DeskTop Board D945GTP) pci:v00008086d000027DAsv00008086sd00005842* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (DeskTop Board D975XBX) pci:v00008086d000027DC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family LAN Controller pci:v00008086d000027DCsv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family LAN Controller (Pavilion A1512X) pci:v00008086d000027DCsv00008086sd0000308D* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family LAN Controller (DeskTop Board D945GTP) pci:v00008086d000027DD* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) AC'97 Modem Controller pci:v00008086d000027DE* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) AC'97 Audio Controller pci:v00008086d000027DEsv00001028sd000001AD* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) AC'97 Audio Controller (OptiPlex GX620) pci:v00008086d000027DEsv00001462sd00007267* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) AC'97 Audio Controller (Realtek ALC883 Audio Controller) pci:v00008086d000027DEsv00001775sd000011CC* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) AC'97 Audio Controller (CC11 integrated audio (AD1981BL codec)) pci:v00008086d000027DF* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller pci:v00008086d000027DFsv00001028sd000001DF* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (PowerEdge SC440) pci:v00008086d000027DFsv00001028sd000001E6* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (PowerEdge 860) pci:v00008086d000027DFsv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Pavilion A1512X) pci:v00008086d000027DFsv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Compaq nx9420 Notebook) pci:v00008086d000027DFsv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (NC2400) pci:v00008086d000027DFsv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Compaq nw8440) pci:v00008086d000027DFsv00001043sd00001237* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (A6J-Q008) pci:v00008086d000027DFsv00001043sd00008179* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (P5KPL-VM Motherboard) pci:v00008086d000027DFsv0000107Bsd00005048* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (E4500) pci:v00008086d000027DFsv000010F7sd00008338* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Panasonic CF-Y5 laptop) pci:v00008086d000027DFsv00001462sd00007418* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Wind PC MS-7418) pci:v00008086d000027DFsv00001775sd000011CC* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (CC11/CL11) pci:v00008086d000027DFsv000017AAsd0000200C* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (ThinkPad R60/T60/X60 series) pci:v00008086d000027DFsv00008086sd0000544E* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (DeskTop Board D945GTP) pci:v00008086d000027E0* ID_MODEL_FROM_DATABASE=82801GR/GH/GHM (ICH7 Family) PCI Express Port 5 pci:v00008086d000027E0sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=82801GR/GH/GHM (ICH7 Family) PCI Express Port 5 (CC11/CL11) pci:v00008086d000027E2* ID_MODEL_FROM_DATABASE=82801GR/GH/GHM (ICH7 Family) PCI Express Port 6 pci:v00008086d000027E2sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=82801GR/GH/GHM (ICH7 Family) PCI Express Port 6 (CC11/CL11) pci:v00008086d00002810* ID_MODEL_FROM_DATABASE=82801HB/HR (ICH8/R) LPC Interface Controller pci:v00008086d00002810sv00001043sd000081EC* ID_MODEL_FROM_DATABASE=82801HB/HR (ICH8/R) LPC Interface Controller (P5B) pci:v00008086d00002811* ID_MODEL_FROM_DATABASE=82801HEM (ICH8M-E) LPC Interface Controller pci:v00008086d00002811sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801HEM (ICH8M-E) LPC Interface Controller (Compaq 6910p) pci:v00008086d00002811sv000017AAsd000020B6* ID_MODEL_FROM_DATABASE=82801HEM (ICH8M-E) LPC Interface Controller (ThinkPad T61/R61) pci:v00008086d00002811sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801HEM (ICH8M-E) LPC Interface Controller (CCG-RUMBA) pci:v00008086d00002812* ID_MODEL_FROM_DATABASE=82801HH (ICH8DH) LPC Interface Controller pci:v00008086d00002814* ID_MODEL_FROM_DATABASE=82801HO (ICH8DO) LPC Interface Controller pci:v00008086d00002815* ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller pci:v00008086d00002815sv00001025sd00000121* ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Aspire 5920G) pci:v00008086d00002815sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Inspiron 1420) pci:v00008086d00002815sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Compaq 6710b) pci:v00008086d00002815sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Pavilion dv6700) pci:v00008086d00002815sv0000103Csd000030D9* ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Presario C700) pci:v00008086d00002815sv0000104Dsd00009005* ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Vaio VGN-FZ260E) pci:v00008086d00002815sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (VAIO VGN-NR120E) pci:v00008086d00002815sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002820* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) 4 port SATA Controller [IDE mode] pci:v00008086d00002820sv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) 4 port SATA Controller [IDE mode] (OptiPlex 745) pci:v00008086d00002820sv00001462sd00007235* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) 4 port SATA Controller [IDE mode] (P965 Neo MS-7235 mainboard) pci:v00008086d00002821* ID_MODEL_FROM_DATABASE=82801HR/HO/HH (ICH8R/DO/DH) 6 port SATA Controller [AHCI mode] pci:v00008086d00002822* ID_MODEL_FROM_DATABASE=SATA Controller [RAID mode] pci:v00008086d00002822sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=SATA Controller [RAID mode] (Inspiron 530) pci:v00008086d00002822sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=SATA Controller [RAID mode] (Asus IPIBL-LB Motherboard) pci:v00008086d00002822sv00001043sd00008277* ID_MODEL_FROM_DATABASE=SATA Controller [RAID mode] (P5K PRO Motherboard) pci:v00008086d00002823* ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [RAID mode] pci:v00008086d00002824* ID_MODEL_FROM_DATABASE=82801HB (ICH8) 4 port SATA Controller [AHCI mode] pci:v00008086d00002824sv00001043sd000081EC* ID_MODEL_FROM_DATABASE=82801HB (ICH8) 4 port SATA Controller [AHCI mode] (P5B) pci:v00008086d00002825* ID_MODEL_FROM_DATABASE=82801HR/HO/HH (ICH8R/DO/DH) 2 port SATA Controller [IDE mode] pci:v00008086d00002825sv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82801HR/HO/HH (ICH8R/DO/DH) 2 port SATA Controller [IDE mode] (OptiPlex 745) pci:v00008086d00002825sv00001462sd00007235* ID_MODEL_FROM_DATABASE=82801HR/HO/HH (ICH8R/DO/DH) 2 port SATA Controller [IDE mode] (P965 Neo MS-7235 mainboard) pci:v00008086d00002826* ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller pci:v00008086d00002827* ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [RAID mode] pci:v00008086d00002828* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode] pci:v00008086d00002828sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode] (Inspiron 1420) pci:v00008086d00002828sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode] (Compaq 6710b) pci:v00008086d00002828sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode] (CCG-RUMBA) pci:v00008086d00002829* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] pci:v00008086d00002829sv00001025sd00000121* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Aspire 5920G) pci:v00008086d00002829sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Compaq 6710b) pci:v00008086d00002829sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Compaq 6910p) pci:v00008086d00002829sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Pavilion dv6700) pci:v00008086d00002829sv0000103Csd000030D9* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Presario C700) pci:v00008086d00002829sv0000104Dsd00009005* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Vaio VGN-FZ260E) pci:v00008086d00002829sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (VAIO VGN-NR120E) pci:v00008086d00002829sv000017AAsd000020A7* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (ThinkPad T61/R61) pci:v00008086d00002829sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002829sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (CCG-RUMBA) pci:v00008086d0000282A* ID_MODEL_FROM_DATABASE=82801 Mobile SATA Controller [RAID mode] pci:v00008086d0000282Asv00001028sd0000040B* ID_MODEL_FROM_DATABASE=82801 Mobile SATA Controller [RAID mode] (Latitude E6510) pci:v00008086d0000282Asv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=82801 Mobile SATA Controller [RAID mode] (PC1-GROOVE) pci:v00008086d00002830* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 pci:v00008086d00002830sv00001025sd00000121* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Acer Aspire 5920G) pci:v00008086d00002830sv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (OptiPlex 745) pci:v00008086d00002830sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Inspiron 1420) pci:v00008086d00002830sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Compaq 6710b) pci:v00008086d00002830sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Compaq 6910p) pci:v00008086d00002830sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Pavilion dv6700) pci:v00008086d00002830sv0000103Csd000030D9* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Presario C700) pci:v00008086d00002830sv00001043sd000081EC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (P5B) pci:v00008086d00002830sv0000104Dsd00009005* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Vaio VGN-FZ260E) pci:v00008086d00002830sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (VAIO VGN-NR120E) pci:v00008086d00002830sv00001462sd00007235* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (P965 Neo MS-7235 mainboard) pci:v00008086d00002830sv000017AAsd000020AA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (ThinkPad T61/R61) pci:v00008086d00002830sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002830sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (CCG-RUMBA) pci:v00008086d00002831* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 pci:v00008086d00002831sv00001025sd00000121* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Aspire 5920G) pci:v00008086d00002831sv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (OptiPlex 745) pci:v00008086d00002831sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Inspiron 1420) pci:v00008086d00002831sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Compaq 6710b) pci:v00008086d00002831sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Compaq 6910p) pci:v00008086d00002831sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Pavilion dv6700) pci:v00008086d00002831sv0000103Csd000030D9* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Presario C700) pci:v00008086d00002831sv00001043sd000081EC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (P5B) pci:v00008086d00002831sv0000104Dsd00009005* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Vaio VGN-FZ260E) pci:v00008086d00002831sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (VAIO VGN-NR120E) pci:v00008086d00002831sv00001462sd00007235* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (P965 Neo MS-7235 mainboard) pci:v00008086d00002831sv000017AAsd000020AA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (ThinkPad T61/R61) pci:v00008086d00002831sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002831sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (CCG-RUMBA) pci:v00008086d00002832* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 pci:v00008086d00002832sv00001025sd00000121* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Aspire 5920G) pci:v00008086d00002832sv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (OptiPlex 745) pci:v00008086d00002832sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Inspiron 1420) pci:v00008086d00002832sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Compaq 6710b) pci:v00008086d00002832sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Compaq 6910p) pci:v00008086d00002832sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Pavilion dv6700) pci:v00008086d00002832sv0000103Csd000030D9* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Presario C700) pci:v00008086d00002832sv00001043sd000081EC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (P5B) pci:v00008086d00002832sv0000104Dsd00009005* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Vaio VGN-FZ260E) pci:v00008086d00002832sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (VAIO VGN-NR120E) pci:v00008086d00002832sv000017AAsd000020AA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (ThinkPad T61/R61) pci:v00008086d00002832sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002832sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (CCG-RUMBA) pci:v00008086d00002833* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 pci:v00008086d00002833sv00001043sd000081EC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (P5B) pci:v00008086d00002834* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 pci:v00008086d00002834sv00001025sd00000121* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Aspire 5920G) pci:v00008086d00002834sv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (OptiPlex 745) pci:v00008086d00002834sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Inspiron 1420) pci:v00008086d00002834sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Compaq 6710b) pci:v00008086d00002834sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Compaq 6910p) pci:v00008086d00002834sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Pavilion dv6700) pci:v00008086d00002834sv00001043sd000081EC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (P5B) pci:v00008086d00002834sv0000104Dsd00009005* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Vaio VGN-FZ260E) pci:v00008086d00002834sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (VAIO VGN-NR120E) pci:v00008086d00002834sv00001462sd00007235* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (P965 Neo MS-7235 mainboard) pci:v00008086d00002834sv000017AAsd000020AA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (ThinkPad T61/R61) pci:v00008086d00002834sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002834sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (CCG-RUMBA) pci:v00008086d00002835* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 pci:v00008086d00002835sv00001025sd00000121* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Acer Aspire 5920G) pci:v00008086d00002835sv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (OptiPlex 745) pci:v00008086d00002835sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Inspiron 1420) pci:v00008086d00002835sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Compaq 6710b) pci:v00008086d00002835sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Compaq 6910p) pci:v00008086d00002835sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Pavilion dv6700) pci:v00008086d00002835sv00001043sd000081EC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (P5B) pci:v00008086d00002835sv0000104Dsd00009005* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Vaio VGN-FZ260E) pci:v00008086d00002835sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (VAIO VGN-NR120E) pci:v00008086d00002835sv000017AAsd000020AA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Thinkpad T61/R61) pci:v00008086d00002835sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002835sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (CCG-RUMBA) pci:v00008086d00002836* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 pci:v00008086d00002836sv00001025sd00000121* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Aspire 5920G) pci:v00008086d00002836sv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (OptiPlex 745) pci:v00008086d00002836sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Inspiron 1420) pci:v00008086d00002836sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Compaq 6710b) pci:v00008086d00002836sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Compaq 6910p) pci:v00008086d00002836sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Pavilion dv6700) pci:v00008086d00002836sv0000103Csd000030D9* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Presario C700) pci:v00008086d00002836sv00001043sd000081EC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (P5B) pci:v00008086d00002836sv0000104Dsd00009005* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Vaio VGN-FZ260E) pci:v00008086d00002836sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (VAIO VGN-NR120E) pci:v00008086d00002836sv00001462sd00007235* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (P965 Neo MS-7235 mainboard) pci:v00008086d00002836sv000017AAsd000020AB* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (ThinkPad T61/R61) pci:v00008086d00002836sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002836sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (CCG-RUMBA) pci:v00008086d0000283A* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 pci:v00008086d0000283Asv00001025sd00000121* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Acer Aspire 5920G) pci:v00008086d0000283Asv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (OptiPlex 745) pci:v00008086d0000283Asv00001028sd000001F3* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Inspiron 1420) pci:v00008086d0000283Asv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Compaq 6710b) pci:v00008086d0000283Asv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Compaq 6910p) pci:v00008086d0000283Asv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Pavilion dv6700) pci:v00008086d0000283Asv00001043sd000081EC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (P5B) pci:v00008086d0000283Asv0000104Dsd00009005* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Vaio VGN-FZ260E) pci:v00008086d0000283Asv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (VAIO VGN-NR120E) pci:v00008086d0000283Asv000017AAsd000020AB* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (ThinkPad T61/R61) pci:v00008086d0000283Asv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d0000283Asv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (CCG-RUMBA) pci:v00008086d0000283E* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller pci:v00008086d0000283Esv00001025sd00000121* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (Aspire 5920G) pci:v00008086d0000283Esv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (OptiPlex 745) pci:v00008086d0000283Esv00001028sd000001F3* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (Inspiron 1420) pci:v00008086d0000283Esv0000103Csd000030D9* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (Presario C700) pci:v00008086d0000283Esv00001043sd000081EC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (P5B) pci:v00008086d0000283Esv0000104Dsd00009005* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (Vaio VGN-FZ260E) pci:v00008086d0000283Esv0000104Dsd00009008* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (Vaio VGN-SZ79SN_C) pci:v00008086d0000283Esv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (VAIO VGN-NR120E) pci:v00008086d0000283Esv00001462sd00007235* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (P965 Neo MS-7235 mainboard) pci:v00008086d0000283Esv000017AAsd000020A9* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (ThinkPad T61/R61) pci:v00008086d0000283Esv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d0000283Esv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (CCG-RUMBA) pci:v00008086d0000283F* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 1 pci:v00008086d0000283Fsv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 1 (OptiPlex 745) pci:v00008086d0000283Fsv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 1 (Compaq 6910p) pci:v00008086d0000283Fsv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 1 (VAIO VGN-NR120E) pci:v00008086d0000283Fsv000017AAsd000020AD* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 1 (ThinkPad T61/R61) pci:v00008086d0000283Fsv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 1 (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002841* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 2 pci:v00008086d00002841sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 2 (Compaq 6910p) pci:v00008086d00002841sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 2 (VAIO VGN-NR120E) pci:v00008086d00002841sv000017AAsd000020AD* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 2 (ThinkPad T61/R61) pci:v00008086d00002841sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 2 (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002843* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 3 pci:v00008086d00002843sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 3 (VAIO VGN-NR120E) pci:v00008086d00002843sv000017AAsd000020AD* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 3 (ThinkPad T61/R61) pci:v00008086d00002843sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 3 (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002845* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 4 pci:v00008086d00002845sv000017AAsd000020AD* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 4 (ThinkPad T61/R61) pci:v00008086d00002845sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 4 (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002847* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 5 pci:v00008086d00002847sv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 5 (OptiPlex 745) pci:v00008086d00002847sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 5 (Compaq 6910p) pci:v00008086d00002847sv000017AAsd000020AD* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 5 (ThinkPad T61/R61) pci:v00008086d00002847sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 5 (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002849* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 6 pci:v00008086d0000284B* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller pci:v00008086d0000284Bsv00001025sd0000011F* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Realtek ALC268 audio codec) pci:v00008086d0000284Bsv00001025sd00000121* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Aspire 5920G) pci:v00008086d0000284Bsv00001025sd00000145* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Realtek ALC889 (Aspire 8920G w. Dolby Theather)) pci:v00008086d0000284Bsv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (OptiPlex 745) pci:v00008086d0000284Bsv00001028sd000001F3* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Inspiron 1420) pci:v00008086d0000284Bsv00001028sd000001F9* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Dell Latitude D630) pci:v00008086d0000284Bsv00001028sd000001FF* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Dell Precision M4300) pci:v00008086d0000284Bsv00001028sd00000256* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Studio 1735) pci:v00008086d0000284Bsv0000103Csd00002802* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Compaq dc7700p) pci:v00008086d0000284Bsv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Compaq 6710b) pci:v00008086d0000284Bsv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Compaq 6910p) pci:v00008086d0000284Bsv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Pavilion dv6700) pci:v00008086d0000284Bsv00001043sd00001339* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Asus M51S series) pci:v00008086d0000284Bsv00001043sd000081EC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (P5B) pci:v00008086d0000284Bsv0000104Dsd00009005* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Vaio VGN-FZ260E) pci:v00008086d0000284Bsv0000104Dsd00009008* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Vaio VGN-SZ79SN_C) pci:v00008086d0000284Bsv0000104Dsd00009016* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Sony VAIO VGN-AR51M) pci:v00008086d0000284Bsv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (VAIO VGN-NR120E) pci:v00008086d0000284Bsv000014F1sd00005051* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Presario C700) pci:v00008086d0000284Bsv000017AAsd000020AC* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (ThinkPad T61/R61) pci:v00008086d0000284Bsv000017C0sd00004088* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d0000284Bsv00008384sd00007616* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Dell Vostro 1400) pci:v00008086d0000284Bsv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (CCG-RUMBA) pci:v00008086d0000284F* ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) Thermal Reporting Device pci:v00008086d00002850* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller pci:v00008086d00002850sv00001025sd00000121* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Aspire 5920G) pci:v00008086d00002850sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Inspiron 1420) pci:v00008086d00002850sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Compaq 6710b) pci:v00008086d00002850sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Compaq 6910p) pci:v00008086d00002850sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Pavilion dv6700) pci:v00008086d00002850sv0000103Csd000030D9* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Presario C700) pci:v00008086d00002850sv0000104Dsd00009005* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Vaio VGN-FZ260E) pci:v00008086d00002850sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (VAIO VGN-NR120E) pci:v00008086d00002850sv000017AAsd000020A6* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (ThinkPad T61/R61) pci:v00008086d00002850sv000017C0sd00004083* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002850sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (CCG-RUMBA) pci:v00008086d00002912* ID_MODEL_FROM_DATABASE=82801IH (ICH9DH) LPC Interface Controller pci:v00008086d00002914* ID_MODEL_FROM_DATABASE=82801IO (ICH9DO) LPC Interface Controller pci:v00008086d00002914sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801IO (ICH9DO) LPC Interface Controller (Optiplex 755) pci:v00008086d00002916* ID_MODEL_FROM_DATABASE=82801IR (ICH9R) LPC Interface Controller pci:v00008086d00002916sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801IR (ICH9R) LPC Interface Controller (Inspiron 530) pci:v00008086d00002916sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801IR (ICH9R) LPC Interface Controller (Asus IPIBL-LB Motherboard) pci:v00008086d00002916sv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801IR (ICH9R) LPC Interface Controller (P5K PRO Motherboard) pci:v00008086d00002916sv00008086sd00005044* ID_MODEL_FROM_DATABASE=82801IR (ICH9R) LPC Interface Controller (Desktop Board DP35DP) pci:v00008086d00002917* ID_MODEL_FROM_DATABASE=ICH9M-E LPC Interface Controller pci:v00008086d00002917sv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=ICH9M-E LPC Interface Controller (CCM-BOOGIE) pci:v00008086d00002918* ID_MODEL_FROM_DATABASE=82801IB (ICH9) LPC Interface Controller pci:v00008086d00002918sv00001028sd00000236* ID_MODEL_FROM_DATABASE=82801IB (ICH9) LPC Interface Controller (PowerEdge R610 82801IB (ICH9) LPC Interface Controller) pci:v00008086d00002918sv00001462sd00007360* ID_MODEL_FROM_DATABASE=82801IB (ICH9) LPC Interface Controller (G33/P35 Neo) pci:v00008086d00002918sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801IB (ICH9) LPC Interface Controller (QEMU Virtual Machine) pci:v00008086d00002919* ID_MODEL_FROM_DATABASE=ICH9M LPC Interface Controller pci:v00008086d00002920* ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] pci:v00008086d00002920sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] (Inspiron 530) pci:v00008086d00002920sv00001028sd0000020F* ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] (PowerEdge R300 onboard SATA Controller) pci:v00008086d00002920sv00001028sd00000210* ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] (PowerEdge T300 onboard SATA Controller) pci:v00008086d00002920sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] (Optiplex 755) pci:v00008086d00002920sv00001028sd0000023C* ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] (PowerEdge R200 onboard SATA Controller) pci:v00008086d00002920sv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] (P5K PRO Motherboard) pci:v00008086d00002921* ID_MODEL_FROM_DATABASE=82801IB (ICH9) 2 port SATA Controller [IDE mode] pci:v00008086d00002921sv00001028sd00000235* ID_MODEL_FROM_DATABASE=82801IB (ICH9) 2 port SATA Controller [IDE mode] (PowerEdge R710 SATA IDE Controller) pci:v00008086d00002921sv00001028sd00000236* ID_MODEL_FROM_DATABASE=82801IB (ICH9) 2 port SATA Controller [IDE mode] (PowerEdge R610 SATA IDE Controller) pci:v00008086d00002921sv00001028sd00000237* ID_MODEL_FROM_DATABASE=82801IB (ICH9) 2 port SATA Controller [IDE mode] (PowerEdge T610 SATA IDE Controller) pci:v00008086d00002921sv00001462sd00007360* ID_MODEL_FROM_DATABASE=82801IB (ICH9) 2 port SATA Controller [IDE mode] (G33/P35 Neo) pci:v00008086d00002922* ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] pci:v00008086d00002922sv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] (P5K PRO Motherboard) pci:v00008086d00002922sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] (QEMU Virtual Machine) pci:v00008086d00002922sv00008086sd00005044* ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] (Desktop Board DP35DP) pci:v00008086d00002923* ID_MODEL_FROM_DATABASE=82801IB (ICH9) 4 port SATA Controller [AHCI mode] pci:v00008086d00002925* ID_MODEL_FROM_DATABASE=82801IR/IO (ICH9R/DO) SATA Controller [RAID mode] pci:v00008086d00002925sv00001734sd000010E0* ID_MODEL_FROM_DATABASE=82801IR/IO (ICH9R/DO) SATA Controller [RAID mode] (System Board D2542) pci:v00008086d00002925sv00008086sd00002925* ID_MODEL_FROM_DATABASE=82801IR/IO (ICH9R/DO) SATA Controller [RAID mode] (System Board D2542) pci:v00008086d00002926* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] pci:v00008086d00002926sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (Inspiron 530) pci:v00008086d00002926sv00001028sd0000020F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (PowerEdge R300 onboard SATA Controller) pci:v00008086d00002926sv00001028sd00000210* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (PowerEdge T300 onboard SATA Controller) pci:v00008086d00002926sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (Optiplex 755) pci:v00008086d00002926sv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (P5K PRO Motherboard) pci:v00008086d00002926sv00001462sd00007360* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (G33/P35 Neo) pci:v00008086d00002928* ID_MODEL_FROM_DATABASE=82801IBM/IEM (ICH9M/ICH9M-E) 2 port SATA Controller [IDE mode] pci:v00008086d00002929* ID_MODEL_FROM_DATABASE=82801IBM/IEM (ICH9M/ICH9M-E) 4 port SATA Controller [AHCI mode] pci:v00008086d00002929sv0000103Csd00003628* ID_MODEL_FROM_DATABASE=82801IBM/IEM (ICH9M/ICH9M-E) 4 port SATA Controller [AHCI mode] (dv6-1190en) pci:v00008086d00002929sv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=82801IBM/IEM (ICH9M/ICH9M-E) 4 port SATA Controller [AHCI mode] (CCM-BOOGIE) pci:v00008086d0000292C* ID_MODEL_FROM_DATABASE=82801IEM (ICH9M-E) SATA Controller [RAID mode] pci:v00008086d0000292D* ID_MODEL_FROM_DATABASE=82801IBM/IEM (ICH9M/ICH9M-E) 2 port SATA Controller [IDE mode] pci:v00008086d0000292Dsv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=82801IBM/IEM (ICH9M/ICH9M-E) 2 port SATA Controller [IDE mode] (CCM-BOOGIE) pci:v00008086d00002930* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller pci:v00008086d00002930sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (Inspiron 530) pci:v00008086d00002930sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (Optiplex 755) pci:v00008086d00002930sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (Asus IPIBL-LB Motherboard) pci:v00008086d00002930sv0000103Csd00003628* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (dv6-1190en) pci:v00008086d00002930sv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (P5K PRO Motherboard) pci:v00008086d00002930sv00001462sd00007360* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (G33/P35 Neo) pci:v00008086d00002930sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (QEMU Virtual Machine) pci:v00008086d00002930sv00008086sd00005044* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (Desktop Board DP35DP) pci:v00008086d00002930sv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (CCM-BOOGIE) pci:v00008086d00002932* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) Thermal Subsystem pci:v00008086d00002932sv0000103Csd00003628* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) Thermal Subsystem (dv6-1190en) pci:v00008086d00002934* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 pci:v00008086d00002934sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (Inspiron 530) pci:v00008086d00002934sv00001028sd0000020F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge R300 onboard UHCI) pci:v00008086d00002934sv00001028sd00000210* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge T300 onboard UHCI) pci:v00008086d00002934sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (Optiplex 755) pci:v00008086d00002934sv00001028sd00000235* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge R710 USB UHCI Controller) pci:v00008086d00002934sv00001028sd00000236* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge R610 USB UHCI Controller) pci:v00008086d00002934sv00001028sd00000237* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge T610 USB UHCI Controller) pci:v00008086d00002934sv00001028sd0000023C* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge R200 onboard UHCI) pci:v00008086d00002934sv00001028sd00000287* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge M610 onboard UHCI) pci:v00008086d00002934sv00001028sd0000029C* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge M710 USB UHCI Controller) pci:v00008086d00002934sv00001028sd00002011* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (Optiplex 755) pci:v00008086d00002934sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (Asus IPIBL-LB Motherboard) pci:v00008086d00002934sv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (P5K PRO Motherboard) pci:v00008086d00002934sv00001462sd00007360* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (G33/P35 Neo) pci:v00008086d00002934sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (QEMU Virtual Machine) pci:v00008086d00002934sv00008086sd00005044* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (Desktop Board DP35DP) pci:v00008086d00002934sv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (CCM-BOOGIE) pci:v00008086d00002935* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 pci:v00008086d00002935sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (Inspiron 530) pci:v00008086d00002935sv00001028sd0000020F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge R300 onboard UHCI) pci:v00008086d00002935sv00001028sd00000210* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge T300 onboard UHCI) pci:v00008086d00002935sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (Optiplex 755) pci:v00008086d00002935sv00001028sd00000235* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge R710 USB UHCI Controller) pci:v00008086d00002935sv00001028sd00000236* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge R610 USB UHCI Controller) pci:v00008086d00002935sv00001028sd00000237* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge T610 USB UHCI Controller) pci:v00008086d00002935sv00001028sd0000023C* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge R200 onboard UHCI) pci:v00008086d00002935sv00001028sd00000287* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge M610 onboard UHCI) pci:v00008086d00002935sv00001028sd0000029C* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge M710 USB UHCI Controller) pci:v00008086d00002935sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (Asus IPIBL-LB Motherboard) pci:v00008086d00002935sv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (P5K PRO Motherboard) pci:v00008086d00002935sv00001462sd00007360* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (G33/P35 Neo) pci:v00008086d00002935sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (QEMU Virtual Machine) pci:v00008086d00002935sv00008086sd00005044* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (Desktop Board DP35DP) pci:v00008086d00002935sv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (CCM-BOOGIE) pci:v00008086d00002936* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 pci:v00008086d00002936sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (Inspiron 530) pci:v00008086d00002936sv00001028sd0000020F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (PowerEdge R300 onboard UHCI) pci:v00008086d00002936sv00001028sd00000210* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (PowerEdge T300 onboard UHCI) pci:v00008086d00002936sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (Optiplex 755) pci:v00008086d00002936sv00001028sd00000237* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (PowerEdge T610 USB UHCI Controller) pci:v00008086d00002936sv00001028sd0000023C* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (PowerEdge R200 onboard UHCI) pci:v00008086d00002936sv00001028sd00000287* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (PowerEdge M610 onboard UHCI) pci:v00008086d00002936sv00001028sd0000029C* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (PowerEdge M710 USB UHCI Controller) pci:v00008086d00002936sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (Asus IPIBL-LB Motherboard) pci:v00008086d00002936sv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (P5K PRO Motherboard) pci:v00008086d00002936sv00001462sd00007360* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (G33/P35 Neo) pci:v00008086d00002936sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (QEMU Virtual Machine) pci:v00008086d00002936sv00008086sd00005044* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (Desktop Board DP35DP) pci:v00008086d00002936sv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (CCM-BOOGIE) pci:v00008086d00002937* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 pci:v00008086d00002937sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (Inspiron 530) pci:v00008086d00002937sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (Optiplex 755) pci:v00008086d00002937sv00001028sd00000235* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (PowerEdge R710 USB UHCI Controller) pci:v00008086d00002937sv00001028sd00000236* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (PowerEdge R610 USB UHCI Controller) pci:v00008086d00002937sv00001028sd00000237* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (PowerEdge T610 USB UHCI Controller) pci:v00008086d00002937sv00001028sd00000287* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (PowerEdge M610 onboard UHCI) pci:v00008086d00002937sv00001028sd0000029C* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (PowerEdge M710 USB UHCI Controller) pci:v00008086d00002937sv00001028sd00002011* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (Optiplex 755) pci:v00008086d00002937sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (Asus IPIBL-LB Motherboard) pci:v00008086d00002937sv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (P5K PRO Motherboard) pci:v00008086d00002937sv00001462sd00007360* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (G33/P35 Neo) pci:v00008086d00002937sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (QEMU Virtual Machine) pci:v00008086d00002937sv00008086sd00002937* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (Optiplex 755) pci:v00008086d00002937sv00008086sd00002942* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (828011 (ICH9 Family ) USB UHCI Controller) pci:v00008086d00002937sv00008086sd00005044* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (Desktop Board DP35DP) pci:v00008086d00002937sv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (CCM-BOOGIE) pci:v00008086d00002938* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 pci:v00008086d00002938sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (Inspiron 530) pci:v00008086d00002938sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (Optiplex 755) pci:v00008086d00002938sv00001028sd00000235* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (PowerEdge R710 USB UHCI Controller) pci:v00008086d00002938sv00001028sd00000236* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (PowerEdge R610 USB UHCI Controller) pci:v00008086d00002938sv00001028sd00000237* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (PowerEdge T610 USB UHCI Controller) pci:v00008086d00002938sv00001028sd00000287* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (PowerEdge M610 onboard UHCI) pci:v00008086d00002938sv00001028sd0000029C* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (PowerEdge M710 USB UHCI Controller) pci:v00008086d00002938sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (Asus IPIBL-LB Motherboard) pci:v00008086d00002938sv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (P5K PRO Motherboard) pci:v00008086d00002938sv00001462sd00007360* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (G33/P35 Neo) pci:v00008086d00002938sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (QEMU Virtual Machine) pci:v00008086d00002938sv00008086sd00002938* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (Optiplex 755) pci:v00008086d00002938sv00008086sd00005044* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (Desktop Board DP35DP) pci:v00008086d00002938sv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (CCM-BOOGIE) pci:v00008086d00002939* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 pci:v00008086d00002939sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (Inspiron 530) pci:v00008086d00002939sv00001028sd00000210* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (PowerEdge T300 onboard UHCI) pci:v00008086d00002939sv00001028sd00000237* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (PowerEdge T610 USB UHCI Controller) pci:v00008086d00002939sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (Asus IPIBL-LB Motherboard) pci:v00008086d00002939sv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (P5K PRO Motherboard) pci:v00008086d00002939sv00001462sd00007360* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (G33/P35 Neo) pci:v00008086d00002939sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (QEMU Virtual Machine) pci:v00008086d00002939sv00008086sd00005044* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (Desktop Board DP35DP) pci:v00008086d00002939sv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (CCM-BOOGIE) pci:v00008086d0000293A* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 pci:v00008086d0000293Asv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (Inspiron 530) pci:v00008086d0000293Asv00001028sd0000020F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge R300 onboard EHCI) pci:v00008086d0000293Asv00001028sd00000210* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge T300 onboard EHCI) pci:v00008086d0000293Asv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (Optiplex 755) pci:v00008086d0000293Asv00001028sd00000235* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge R710 USB EHCI Controller) pci:v00008086d0000293Asv00001028sd00000236* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge R610 USB EHCI Controller) pci:v00008086d0000293Asv00001028sd00000237* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge T610 USB EHCI Controller) pci:v00008086d0000293Asv00001028sd0000023C* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge R200 onboard EHCI) pci:v00008086d0000293Asv00001028sd00000287* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge M610 onboard EHCI) pci:v00008086d0000293Asv00001028sd0000029C* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge M710 USB EHCI Controller) pci:v00008086d0000293Asv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (Asus IPIBL-LB Motherboard) pci:v00008086d0000293Asv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (P5K PRO Motherboard) pci:v00008086d0000293Asv00001462sd00007360* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (G33/P35 Neo) pci:v00008086d0000293Asv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (QEMU Virtual Machine) pci:v00008086d0000293Asv00008086sd00005044* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (Desktop Board DP35DP) pci:v00008086d0000293Asv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (CCM-BOOGIE) pci:v00008086d0000293C* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 pci:v00008086d0000293Csv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (Inspiron 530) pci:v00008086d0000293Csv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (Optiplex 755) pci:v00008086d0000293Csv00001028sd00000235* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (PowerEdge R710 USB EHCI Controller) pci:v00008086d0000293Csv00001028sd00000236* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (PowerEdge R610 USB EHCI Controller) pci:v00008086d0000293Csv00001028sd00000237* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (PowerEdge T610 USB EHCI Controller) pci:v00008086d0000293Csv00001028sd00000287* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (PowerEdge M610 onboard EHCI) pci:v00008086d0000293Csv00001028sd0000029C* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (PowerEdge M710 USB EHCI Controller) pci:v00008086d0000293Csv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (Asus IPIBL-LB Motherboard) pci:v00008086d0000293Csv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (P5K PRO Motherboard) pci:v00008086d0000293Csv00001462sd00007360* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (G33/P35 Neo) pci:v00008086d0000293Csv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (QEMU Virtual Machine) pci:v00008086d0000293Csv00008086sd0000293C* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (Optiplex 755) pci:v00008086d0000293Csv00008086sd00005044* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (Desktop Board DP35DP) pci:v00008086d0000293Csv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (CCM-BOOGIE) pci:v00008086d0000293E* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller pci:v00008086d0000293Esv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (Inspiron 530) pci:v00008086d0000293Esv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (Optiplex 755) pci:v00008086d0000293Esv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (Asus IPIBL-LB Motherboard) pci:v00008086d0000293Esv0000103Csd00003628* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (dv6-1190en) pci:v00008086d0000293Esv00001043sd0000829F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (P5K PRO Motherboard) pci:v00008086d0000293Esv00001462sd00007360* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (G33/P35 Neo) pci:v00008086d0000293Esv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (QEMU Virtual Machine) pci:v00008086d0000293Esv00008086sd0000293E* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (Optiplex 755) pci:v00008086d0000293Esv00008086sd00002940* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (Optiplex 755) pci:v00008086d0000293Esv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (CCM-BOOGIE) pci:v00008086d00002940* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 1 pci:v00008086d00002940sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 1 (Inspiron 530) pci:v00008086d00002940sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 1 (Optiplex 755) pci:v00008086d00002940sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 1 (Asus IPIBL-LB Motherboard) pci:v00008086d00002940sv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 1 (P5K PRO Motherboard) pci:v00008086d00002940sv00008086sd00002940* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 1 (Optiplex 755) pci:v00008086d00002942* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 2 pci:v00008086d00002942sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 2 (Inspiron 530) pci:v00008086d00002944* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 3 pci:v00008086d00002944sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 3 (Inspiron 530) pci:v00008086d00002944sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 3 (Asus IPIBL-LB Motherboard) pci:v00008086d00002946* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 4 pci:v00008086d00002946sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 4 (Inspiron 530) pci:v00008086d00002948* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 5 pci:v00008086d00002948sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 5 (Inspiron 530) pci:v00008086d00002948sv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 5 (P5K PRO Motherboard) pci:v00008086d0000294A* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 6 pci:v00008086d0000294Asv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 6 (Inspiron 530) pci:v00008086d0000294Asv00001043sd00008277* ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 6 (P5K PRO Motherboard) pci:v00008086d0000294C* ID_MODEL_FROM_DATABASE=82566DC-2 Gigabit Network Connection pci:v00008086d0000294Csv000017AAsd0000302E* ID_MODEL_FROM_DATABASE=82566DC-2 Gigabit Network Connection (82566DM-2 Gigabit Network Connection) pci:v00008086d00002970* ID_MODEL_FROM_DATABASE=82946GZ/PL/GL Memory Controller Hub pci:v00008086d00002971* ID_MODEL_FROM_DATABASE=82946GZ/PL/GL PCI Express Root Port pci:v00008086d00002972* ID_MODEL_FROM_DATABASE=82946GZ/GL Integrated Graphics Controller pci:v00008086d00002973* ID_MODEL_FROM_DATABASE=82946GZ/GL Integrated Graphics Controller pci:v00008086d00002974* ID_MODEL_FROM_DATABASE=82946GZ/GL HECI Controller pci:v00008086d00002975* ID_MODEL_FROM_DATABASE=82946GZ/GL HECI Controller pci:v00008086d00002976* ID_MODEL_FROM_DATABASE=82946GZ/GL PT IDER Controller pci:v00008086d00002977* ID_MODEL_FROM_DATABASE=82946GZ/GL KT Controller pci:v00008086d00002980* ID_MODEL_FROM_DATABASE=82G35 Express DRAM Controller pci:v00008086d00002981* ID_MODEL_FROM_DATABASE=82G35 Express PCI Express Root Port pci:v00008086d00002982* ID_MODEL_FROM_DATABASE=82G35 Express Integrated Graphics Controller pci:v00008086d00002983* ID_MODEL_FROM_DATABASE=82G35 Express Integrated Graphics Controller pci:v00008086d00002984* ID_MODEL_FROM_DATABASE=82G35 Express HECI Controller pci:v00008086d00002990* ID_MODEL_FROM_DATABASE=82Q963/Q965 Memory Controller Hub pci:v00008086d00002990sv00001028sd000001DA* ID_MODEL_FROM_DATABASE=82Q963/Q965 Memory Controller Hub (OptiPlex 745) pci:v00008086d00002991* ID_MODEL_FROM_DATABASE=82Q963/Q965 PCI Express Root Port pci:v00008086d00002992* ID_MODEL_FROM_DATABASE=82Q963/Q965 Integrated Graphics Controller pci:v00008086d00002993* ID_MODEL_FROM_DATABASE=82Q963/Q965 Integrated Graphics Controller pci:v00008086d00002994* ID_MODEL_FROM_DATABASE=82Q963/Q965 HECI Controller pci:v00008086d00002995* ID_MODEL_FROM_DATABASE=82Q963/Q965 HECI Controller pci:v00008086d00002996* ID_MODEL_FROM_DATABASE=82Q963/Q965 PT IDER Controller pci:v00008086d00002997* ID_MODEL_FROM_DATABASE=82Q963/Q965 KT Controller pci:v00008086d000029A0* ID_MODEL_FROM_DATABASE=82P965/G965 Memory Controller Hub pci:v00008086d000029A0sv00001043sd000081EA* ID_MODEL_FROM_DATABASE=82P965/G965 Memory Controller Hub (P5B) pci:v00008086d000029A0sv00001462sd00007276* ID_MODEL_FROM_DATABASE=82P965/G965 Memory Controller Hub (MS-7276 [G965MDH]) pci:v00008086d000029A1* ID_MODEL_FROM_DATABASE=82P965/G965 PCI Express Root Port pci:v00008086d000029A2* ID_MODEL_FROM_DATABASE=82G965 Integrated Graphics Controller pci:v00008086d000029A2sv00001462sd00007276* ID_MODEL_FROM_DATABASE=82G965 Integrated Graphics Controller (MS-7276 [G965MDH]) pci:v00008086d000029A3* ID_MODEL_FROM_DATABASE=82G965 Integrated Graphics Controller pci:v00008086d000029A4* ID_MODEL_FROM_DATABASE=82P965/G965 HECI Controller pci:v00008086d000029A5* ID_MODEL_FROM_DATABASE=82P965/G965 HECI Controller pci:v00008086d000029A6* ID_MODEL_FROM_DATABASE=82P965/G965 PT IDER Controller pci:v00008086d000029A7* ID_MODEL_FROM_DATABASE=82P965/G965 KT Controller pci:v00008086d000029B0* ID_MODEL_FROM_DATABASE=82Q35 Express DRAM Controller pci:v00008086d000029B0sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82Q35 Express DRAM Controller (OptiPlex 755) pci:v00008086d000029B1* ID_MODEL_FROM_DATABASE=82Q35 Express PCI Express Root Port pci:v00008086d000029B1sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82Q35 Express PCI Express Root Port (OptiPlex 755) pci:v00008086d000029B2* ID_MODEL_FROM_DATABASE=82Q35 Express Integrated Graphics Controller pci:v00008086d000029B2sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82Q35 Express Integrated Graphics Controller (OptiPlex 755) pci:v00008086d000029B3* ID_MODEL_FROM_DATABASE=82Q35 Express Integrated Graphics Controller pci:v00008086d000029B3sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82Q35 Express Integrated Graphics Controller (OptiPlex 755) pci:v00008086d000029B4* ID_MODEL_FROM_DATABASE=82Q35 Express MEI Controller pci:v00008086d000029B4sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82Q35 Express MEI Controller (OptiPlex 755) pci:v00008086d000029B5* ID_MODEL_FROM_DATABASE=82Q35 Express MEI Controller pci:v00008086d000029B6* ID_MODEL_FROM_DATABASE=82Q35 Express PT IDER Controller pci:v00008086d000029B6sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82Q35 Express PT IDER Controller (OptiPlex 755) pci:v00008086d000029B7* ID_MODEL_FROM_DATABASE=82Q35 Express Serial KT Controller pci:v00008086d000029B7sv00001028sd00000211* ID_MODEL_FROM_DATABASE=82Q35 Express Serial KT Controller (OptiPlex 755) pci:v00008086d000029C0* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller pci:v00008086d000029C0sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (Inspiron 530) pci:v00008086d000029C0sv0000103Csd00002A6F* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (Asus IPIBL-LB Motherboard) pci:v00008086d000029C0sv00001043sd00008276* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (P5K PRO Motherboard) pci:v00008086d000029C0sv00001043sd000082B0* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (P5KPL-VM Motherboard) pci:v00008086d000029C0sv00001462sd00007360* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (G33/P35 Neo) pci:v00008086d000029C0sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (QEMU Virtual Machine) pci:v00008086d000029C0sv00008086sd00005044* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (Desktop Board DP35DP) pci:v00008086d000029C1* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express PCI Express Root Port pci:v00008086d000029C1sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express PCI Express Root Port (Inspiron 530) pci:v00008086d000029C1sv00001043sd00008276* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express PCI Express Root Port (P5K PRO Motherboard) pci:v00008086d000029C2* ID_MODEL_FROM_DATABASE=82G33/G31 Express Integrated Graphics Controller pci:v00008086d000029C2sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82G33/G31 Express Integrated Graphics Controller (Inspiron 530) pci:v00008086d000029C2sv00001043sd000082B0* ID_MODEL_FROM_DATABASE=82G33/G31 Express Integrated Graphics Controller (P5KPL-VM Motherboard) pci:v00008086d000029C3* ID_MODEL_FROM_DATABASE=82G33/G31 Express Integrated Graphics Controller pci:v00008086d000029C3sv00001028sd0000020D* ID_MODEL_FROM_DATABASE=82G33/G31 Express Integrated Graphics Controller (Inspiron 530) pci:v00008086d000029C3sv00001043sd000082B0* ID_MODEL_FROM_DATABASE=82G33/G31 Express Integrated Graphics Controller (P5KPL-VM Motherboard) pci:v00008086d000029C4* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express MEI Controller pci:v00008086d000029C4sv00008086sd00005044* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express MEI Controller (Desktop Board DP35DP) pci:v00008086d000029C5* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express MEI Controller pci:v00008086d000029C6* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express PT IDER Controller pci:v00008086d000029C7* ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express Serial KT Controller pci:v00008086d000029CF* ID_MODEL_FROM_DATABASE=Virtual HECI Controller pci:v00008086d000029D0* ID_MODEL_FROM_DATABASE=82Q33 Express DRAM Controller pci:v00008086d000029D1* ID_MODEL_FROM_DATABASE=82Q33 Express PCI Express Root Port pci:v00008086d000029D2* ID_MODEL_FROM_DATABASE=82Q33 Express Integrated Graphics Controller pci:v00008086d000029D3* ID_MODEL_FROM_DATABASE=82Q33 Express Integrated Graphics Controller pci:v00008086d000029D4* ID_MODEL_FROM_DATABASE=82Q33 Express MEI Controller pci:v00008086d000029D5* ID_MODEL_FROM_DATABASE=82Q33 Express MEI Controller pci:v00008086d000029D6* ID_MODEL_FROM_DATABASE=82Q33 Express PT IDER Controller pci:v00008086d000029D7* ID_MODEL_FROM_DATABASE=82Q33 Express Serial KT Controller pci:v00008086d000029E0* ID_MODEL_FROM_DATABASE=82X38/X48 Express DRAM Controller pci:v00008086d000029E1* ID_MODEL_FROM_DATABASE=82X38/X48 Express Host-Primary PCI Express Bridge pci:v00008086d000029E4* ID_MODEL_FROM_DATABASE=82X38/X48 Express MEI Controller pci:v00008086d000029E5* ID_MODEL_FROM_DATABASE=82X38/X48 Express MEI Controller pci:v00008086d000029E6* ID_MODEL_FROM_DATABASE=82X38/X48 Express PT IDER Controller pci:v00008086d000029E7* ID_MODEL_FROM_DATABASE=82X38/X48 Express Serial KT Controller pci:v00008086d000029E9* ID_MODEL_FROM_DATABASE=82X38/X48 Express Host-Secondary PCI Express Bridge pci:v00008086d000029F0* ID_MODEL_FROM_DATABASE=3200/3210 Chipset DRAM Controller pci:v00008086d000029F1* ID_MODEL_FROM_DATABASE=3200/3210 Chipset Host-Primary PCI Express Bridge pci:v00008086d000029F4* ID_MODEL_FROM_DATABASE=3200/3210 Chipset MEI Controller pci:v00008086d000029F5* ID_MODEL_FROM_DATABASE=3200/3210 Chipset MEI Controller pci:v00008086d000029F6* ID_MODEL_FROM_DATABASE=3200/3210 Chipset PT IDER Controller pci:v00008086d000029F7* ID_MODEL_FROM_DATABASE=3200/3210 Chipset Serial KT Controller pci:v00008086d000029F9* ID_MODEL_FROM_DATABASE=3210 Chipset Host-Secondary PCI Express Bridge pci:v00008086d00002A00* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub pci:v00008086d00002A00sv00001025sd00000121* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Acer Aspire 5920G) pci:v00008086d00002A00sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Inspiron 1420) pci:v00008086d00002A00sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Compaq 6710b) pci:v00008086d00002A00sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Compaq 6910p) pci:v00008086d00002A00sv0000103Csd000030CC* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Pavilion dv6700) pci:v00008086d00002A00sv0000103Csd000030D9* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Presario C700) pci:v00008086d00002A00sv0000104Dsd00009005* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Vaio VGN-FZ260E) pci:v00008086d00002A00sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (VAIO VGN-NR120E) pci:v00008086d00002A00sv000017AAsd000020B1* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (ThinkPad T61) pci:v00008086d00002A00sv000017AAsd000020B3* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (ThinkPad T61/R61) pci:v00008086d00002A00sv000017C0sd00004082* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002A00sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (CCG-RUMBA) pci:v00008086d00002A01* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 PCI Express Root Port pci:v00008086d00002A02* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) pci:v00008086d00002A02sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (Inspiron 1420) pci:v00008086d00002A02sv00001028sd000001F9* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (Latitude D630) pci:v00008086d00002A02sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (Compaq 6710b) pci:v00008086d00002A02sv0000103Csd000030D9* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (Presario C700) pci:v00008086d00002A02sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (VAIO VGN-NR120E) pci:v00008086d00002A02sv000017AAsd000020B5* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (ThinkPad T61/R61) pci:v00008086d00002A02sv000017C0sd00004082* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002A02sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (CCG-RUMBA) pci:v00008086d00002A03* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) pci:v00008086d00002A03sv00001028sd000001F3* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (Inspiron 1420) pci:v00008086d00002A03sv0000103Csd000030C0* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (Compaq 6710b) pci:v00008086d00002A03sv0000103Csd000030D9* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (Presario C700) pci:v00008086d00002A03sv0000104Dsd0000902D* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (VAIO VGN-NR120E) pci:v00008086d00002A03sv000017AAsd000020B5* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (ThinkPad T61/R61) pci:v00008086d00002A03sv000017C0sd00004082* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (Medion WIM 2210 Notebook PC [MD96850]) pci:v00008086d00002A03sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (CCG-RUMBA) pci:v00008086d00002A04* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 MEI Controller pci:v00008086d00002A04sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 MEI Controller (Compaq 6910p) pci:v00008086d00002A05* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 MEI Controller pci:v00008086d00002A06* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 PT IDER Controller pci:v00008086d00002A06sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 PT IDER Controller (Compaq 6910p) pci:v00008086d00002A07* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 KT Controller pci:v00008086d00002A07sv0000103Csd000030C1* ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 KT Controller (Compaq 6910p) pci:v00008086d00002A10* ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 Memory Controller Hub pci:v00008086d00002A10sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 Memory Controller Hub (CCG-RUMBA) pci:v00008086d00002A11* ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 PCI Express Root Port pci:v00008086d00002A12* ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 Integrated Graphics Controller pci:v00008086d00002A12sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 Integrated Graphics Controller (CCG-RUMBA) pci:v00008086d00002A13* ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 Integrated Graphics Controller pci:v00008086d00002A13sv0000E4BFsd0000CC47* ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 Integrated Graphics Controller (CCG-RUMBA) pci:v00008086d00002A14* ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 MEI Controller pci:v00008086d00002A15* ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 MEI Controller pci:v00008086d00002A16* ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 PT IDER Controller pci:v00008086d00002A17* ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 KT Controller pci:v00008086d00002A40* ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Memory Controller Hub pci:v00008086d00002A40sv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Memory Controller Hub (CCM-BOOGIE) pci:v00008086d00002A41* ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset PCI Express Graphics Port pci:v00008086d00002A41sv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset PCI Express Graphics Port (CCM-BOOGIE) pci:v00008086d00002A42* ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Integrated Graphics Controller pci:v00008086d00002A42sv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Integrated Graphics Controller (CCM-BOOGIE) pci:v00008086d00002A43* ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Integrated Graphics Controller pci:v00008086d00002A43sv0000E4BFsd0000CC4D* ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Integrated Graphics Controller (CCM-BOOGIE) pci:v00008086d00002A44* ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset MEI Controller pci:v00008086d00002A45* ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset MEI Controller pci:v00008086d00002A46* ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset PT IDER Controller pci:v00008086d00002A47* ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset AMT SOL Redirection pci:v00008086d00002A50* ID_MODEL_FROM_DATABASE=Cantiga MEI Controller pci:v00008086d00002A51* ID_MODEL_FROM_DATABASE=Cantiga MEI Controller pci:v00008086d00002A52* ID_MODEL_FROM_DATABASE=Cantiga PT IDER Controller pci:v00008086d00002A53* ID_MODEL_FROM_DATABASE=Cantiga AMT SOL Redirection pci:v00008086d00002B00* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family System Configuration Controller 1 pci:v00008086d00002B02* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family System Configuration Controller 2 pci:v00008086d00002B04* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Power Controller pci:v00008086d00002B08* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Caching Agent 0 pci:v00008086d00002B0C* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Caching Agent 1 pci:v00008086d00002B10* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Home Agent 0 pci:v00008086d00002B13* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Memory Controller 0c pci:v00008086d00002B14* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Memory Controller 0a pci:v00008086d00002B16* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Memory Controller 0b pci:v00008086d00002B18* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Home Agent 1 pci:v00008086d00002B1B* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Memory Controller 1c pci:v00008086d00002B1C* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Memory Controller 1a pci:v00008086d00002B1E* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Memory Controller 1b pci:v00008086d00002B20* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 0 pci:v00008086d00002B22* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family System Configuration Controller 3 pci:v00008086d00002B24* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 1 pci:v00008086d00002B28* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 2 pci:v00008086d00002B2A* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family System Configuration Controller 4 pci:v00008086d00002B2C* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 3 pci:v00008086d00002B30* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 4 pci:v00008086d00002B34* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 5 pci:v00008086d00002B38* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 6 pci:v00008086d00002B3C* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 7 pci:v00008086d00002B40* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Router Port 0-1 pci:v00008086d00002B42* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Router Port 2-3 pci:v00008086d00002B44* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Router Port 4-5 pci:v00008086d00002B46* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Router Port 6-7 pci:v00008086d00002B48* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Test and Debug 0 pci:v00008086d00002B4C* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Test and Debug 1 pci:v00008086d00002B50* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 0: REUT control/status pci:v00008086d00002B52* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 0: Misc. control/status pci:v00008086d00002B54* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 1: REUT control/status pci:v00008086d00002B56* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 1: Misc. control/status pci:v00008086d00002B58* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 2: REUT control/status pci:v00008086d00002B5A* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 2: Misc. control/status pci:v00008086d00002B5C* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 3: REUT control/status pci:v00008086d00002B5E* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 3: Misc. control/status pci:v00008086d00002B60* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family SMI Physical Port 0: REUT control/status pci:v00008086d00002B62* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family SMI Physical Port 0: Misc control/status pci:v00008086d00002B64* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family SMI Physical Port 1: REUT control/status pci:v00008086d00002B66* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family SMI Physical Port 1: Misc control/status pci:v00008086d00002B68* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 8 pci:v00008086d00002B6C* ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 9 pci:v00008086d00002C01* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QuickPath Architecture System Address Decoder pci:v00008086d00002C10* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QPI Link 0 pci:v00008086d00002C11* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QPI Physical 0 pci:v00008086d00002C14* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QPI Link 1 pci:v00008086d00002C15* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QPI Physical 1 pci:v00008086d00002C18* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller pci:v00008086d00002C19* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Target Address Decoder pci:v00008086d00002C1A* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller RAS Registers pci:v00008086d00002C1C* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Test Registers pci:v00008086d00002C20* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 0 Control Registers pci:v00008086d00002C21* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 0 Address Registers pci:v00008086d00002C22* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 0 Rank Registers pci:v00008086d00002C23* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 0 Thermal Control Registers pci:v00008086d00002C28* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 1 Control Registers pci:v00008086d00002C29* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 1 Address Registers pci:v00008086d00002C2A* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 1 Rank Registers pci:v00008086d00002C2B* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 1 Thermal Control Registers pci:v00008086d00002C30* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 2 Control Registers pci:v00008086d00002C31* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 2 Address Registers pci:v00008086d00002C32* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 2 Rank Registers pci:v00008086d00002C33* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 2 Thermal Control Registers pci:v00008086d00002C40* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QuickPath Architecture Generic Non-Core Registers pci:v00008086d00002C41* ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QuickPath Architecture Generic Non-Core Registers pci:v00008086d00002C50* ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers pci:v00008086d00002C51* ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers pci:v00008086d00002C52* ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers pci:v00008086d00002C53* ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers pci:v00008086d00002C54* ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers pci:v00008086d00002C55* ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers pci:v00008086d00002C56* ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers pci:v00008086d00002C57* ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers pci:v00008086d00002C58* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers pci:v00008086d00002C59* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers pci:v00008086d00002C5A* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers pci:v00008086d00002C5B* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers pci:v00008086d00002C5C* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers pci:v00008086d00002C5D* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers pci:v00008086d00002C5E* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers pci:v00008086d00002C5F* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers pci:v00008086d00002C61* ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-core Registers pci:v00008086d00002C62* ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-core Registers pci:v00008086d00002C70* ID_MODEL_FROM_DATABASE=Xeon 5600 Series QuickPath Architecture Generic Non-core Registers pci:v00008086d00002C81* ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture System Address Decoder pci:v00008086d00002C90* ID_MODEL_FROM_DATABASE=Core Processor QPI Link 0 pci:v00008086d00002C91* ID_MODEL_FROM_DATABASE=Core Processor QPI Physical 0 pci:v00008086d00002C98* ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller pci:v00008086d00002C99* ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Target Address Decoder pci:v00008086d00002C9A* ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Test Registers pci:v00008086d00002C9C* ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Test Registers pci:v00008086d00002CA0* ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 0 Control Registers pci:v00008086d00002CA1* ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 0 Address Registers pci:v00008086d00002CA2* ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 0 Rank Registers pci:v00008086d00002CA3* ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 0 Thermal Control Registers pci:v00008086d00002CA8* ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 1 Control Registers pci:v00008086d00002CA9* ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 1 Address Registers pci:v00008086d00002CAA* ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 1 Rank Registers pci:v00008086d00002CAB* ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 1 Thermal Control Registers pci:v00008086d00002CC1* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI System Address Decoder pci:v00008086d00002CD0* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Link 0 pci:v00008086d00002CD1* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Physical 0 pci:v00008086d00002CD4* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Link 1 pci:v00008086d00002CD5* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Physical 1 pci:v00008086d00002CD8* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Registers pci:v00008086d00002CD9* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Target Address Decoder pci:v00008086d00002CDA* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller RAS Registers pci:v00008086d00002CDC* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Test Registers pci:v00008086d00002CE0* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 0 Control pci:v00008086d00002CE1* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 0 Address pci:v00008086d00002CE2* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 0 Rank pci:v00008086d00002CE3* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 0 Thermal Control pci:v00008086d00002CE8* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 1 Control pci:v00008086d00002CE9* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 1 Address pci:v00008086d00002CEA* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 1 Rank pci:v00008086d00002CEB* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 1 Thermal Control pci:v00008086d00002CF0* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 2 Control pci:v00008086d00002CF1* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 2 Address pci:v00008086d00002CF2* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 2 Rank pci:v00008086d00002CF3* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 2 Thermal Control pci:v00008086d00002D01* ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture System Address Decoder pci:v00008086d00002D10* ID_MODEL_FROM_DATABASE=Core Processor QPI Link 0 pci:v00008086d00002D11* ID_MODEL_FROM_DATABASE=1st Generation Core i3/5/7 Processor QPI Physical 0 pci:v00008086d00002D12* ID_MODEL_FROM_DATABASE=1st Generation Core i3/5/7 Processor Reserved pci:v00008086d00002D13* ID_MODEL_FROM_DATABASE=1st Generation Core i3/5/7 Processor Reserved pci:v00008086d00002D81* ID_MODEL_FROM_DATABASE=Xeon 5600 Series QuickPath Architecture System Address Decoder pci:v00008086d00002D90* ID_MODEL_FROM_DATABASE=Xeon 5600 Series QPI Link 0 pci:v00008086d00002D91* ID_MODEL_FROM_DATABASE=Xeon 5600 Series QPI Physical 0 pci:v00008086d00002D92* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Mirror Port Link 0 pci:v00008086d00002D93* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Mirror Port Link 1 pci:v00008086d00002D94* ID_MODEL_FROM_DATABASE=Xeon 5600 Series QPI Link 1 pci:v00008086d00002D95* ID_MODEL_FROM_DATABASE=Xeon 5600 Series QPI Physical 1 pci:v00008086d00002D98* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Registers pci:v00008086d00002D99* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Target Address Decoder pci:v00008086d00002D9A* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller RAS Registers pci:v00008086d00002D9C* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Test Registers pci:v00008086d00002DA0* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 0 Control pci:v00008086d00002DA1* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 0 Address pci:v00008086d00002DA2* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 0 Rank pci:v00008086d00002DA3* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 0 Thermal Control pci:v00008086d00002DA8* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 1 Control pci:v00008086d00002DA9* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 1 Address pci:v00008086d00002DAA* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 1 Rank pci:v00008086d00002DAB* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 1 Thermal Control pci:v00008086d00002DB0* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 2 Control pci:v00008086d00002DB1* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 2 Address pci:v00008086d00002DB2* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 2 Rank pci:v00008086d00002DB3* ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 2 Thermal Control pci:v00008086d00002E00* ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller pci:v00008086d00002E01* ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port pci:v00008086d00002E02* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller pci:v00008086d00002E03* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller pci:v00008086d00002E04* ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller pci:v00008086d00002E05* ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller pci:v00008086d00002E06* ID_MODEL_FROM_DATABASE=4 Series Chipset PT IDER Controller pci:v00008086d00002E07* ID_MODEL_FROM_DATABASE=4 Series Chipset Serial KT Controller pci:v00008086d00002E10* ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller pci:v00008086d00002E11* ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port pci:v00008086d00002E12* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller pci:v00008086d00002E12sv000017AAsd00003048* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller (ThinkCentre M6258) pci:v00008086d00002E13* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller pci:v00008086d00002E14* ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller pci:v00008086d00002E15* ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller pci:v00008086d00002E16* ID_MODEL_FROM_DATABASE=4 Series Chipset PT IDER Controller pci:v00008086d00002E17* ID_MODEL_FROM_DATABASE=4 Series Chipset Serial KT Controller pci:v00008086d00002E20* ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller pci:v00008086d00002E20sv00001028sd00000283* ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller (Dell Vostro 220) pci:v00008086d00002E20sv00001043sd000082D3* ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller (P5Q Deluxe Motherboard) pci:v00008086d00002E20sv00001458sd00005000* ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller (GA-EP45-DS5/GA-EG45M-DS2H Motherboard) pci:v00008086d00002E21* ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port pci:v00008086d00002E21sv00001043sd000082D3* ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port (P5Q Deluxe Motherboard) pci:v00008086d00002E21sv00001458sd00005000* ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port (GA-EP45-DS5 Motherboard) pci:v00008086d00002E22* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller pci:v00008086d00002E22sv00001458sd0000D000* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller (GA-EG45M-DS2H Mainboard) pci:v00008086d00002E23* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller pci:v00008086d00002E23sv00001458sd0000D000* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller (GA-EG45M-DS2H Mainboard) pci:v00008086d00002E24* ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller pci:v00008086d00002E25* ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller pci:v00008086d00002E26* ID_MODEL_FROM_DATABASE=4 Series Chipset PT IDER Controller pci:v00008086d00002E27* ID_MODEL_FROM_DATABASE=4 Series Chipset Serial KT Controller pci:v00008086d00002E29* ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port pci:v00008086d00002E30* ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller pci:v00008086d00002E31* ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port pci:v00008086d00002E32* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller pci:v00008086d00002E33* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller pci:v00008086d00002E34* ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller pci:v00008086d00002E35* ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller pci:v00008086d00002E36* ID_MODEL_FROM_DATABASE=4 Series Chipset PT IDER Controller pci:v00008086d00002E37* ID_MODEL_FROM_DATABASE=4 Series Chipset Serial KT Controller pci:v00008086d00002E40* ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller pci:v00008086d00002E41* ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port pci:v00008086d00002E42* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller pci:v00008086d00002E43* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller pci:v00008086d00002E44* ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller pci:v00008086d00002E45* ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller pci:v00008086d00002E46* ID_MODEL_FROM_DATABASE=4 Series Chipset PT IDER Controller pci:v00008086d00002E47* ID_MODEL_FROM_DATABASE=4 Series Chipset Serial KT Controller pci:v00008086d00002E50* ID_MODEL_FROM_DATABASE=CE Media Processor CE3100 pci:v00008086d00002E52* ID_MODEL_FROM_DATABASE=CE Media Processor Clock and Reset Controller pci:v00008086d00002E58* ID_MODEL_FROM_DATABASE=CE Media Processor Interrupt Controller pci:v00008086d00002E5A* ID_MODEL_FROM_DATABASE=CE Media Processor CE3100 A/V Bridge pci:v00008086d00002E5B* ID_MODEL_FROM_DATABASE=Graphics Media Accelerator 500 Graphics pci:v00008086d00002E5C* ID_MODEL_FROM_DATABASE=CE Media Processor Video Decoder pci:v00008086d00002E5D* ID_MODEL_FROM_DATABASE=CE Media Processor Transport Stream Interface pci:v00008086d00002E5E* ID_MODEL_FROM_DATABASE=CE Media Processor Transport Stream Processor 0 pci:v00008086d00002E5F* ID_MODEL_FROM_DATABASE=CE Media Processor Audio DSP pci:v00008086d00002E60* ID_MODEL_FROM_DATABASE=CE Media Processor Audio Interfaces pci:v00008086d00002E61* ID_MODEL_FROM_DATABASE=CE Media Processor Video Display Controller pci:v00008086d00002E62* ID_MODEL_FROM_DATABASE=CE Media Processor Video Processing Unit pci:v00008086d00002E63* ID_MODEL_FROM_DATABASE=CE Media Processor HDMI Tx Interface pci:v00008086d00002E65* ID_MODEL_FROM_DATABASE=CE Media Processor Expansion Bus Interface pci:v00008086d00002E66* ID_MODEL_FROM_DATABASE=CE Media Processor UART pci:v00008086d00002E67* ID_MODEL_FROM_DATABASE=CE Media Processor General Purpose I/Os pci:v00008086d00002E68* ID_MODEL_FROM_DATABASE=CE Media Processor I2C Interface pci:v00008086d00002E69* ID_MODEL_FROM_DATABASE=CE Media Processor Smart Card Interface pci:v00008086d00002E6A* ID_MODEL_FROM_DATABASE=CE Media Processor SPI Master Interface pci:v00008086d00002E6E* ID_MODEL_FROM_DATABASE=CE Media Processor Gigabit Ethernet Controller pci:v00008086d00002E6F* ID_MODEL_FROM_DATABASE=CE Media Processor Media Timing Unit pci:v00008086d00002E70* ID_MODEL_FROM_DATABASE=CE Media Processor USB pci:v00008086d00002E71* ID_MODEL_FROM_DATABASE=CE Media Processor SATA pci:v00008086d00002E73* ID_MODEL_FROM_DATABASE=CE Media Processor CE3100 PCI Express pci:v00008086d00002E90* ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller pci:v00008086d00002E91* ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port pci:v00008086d00002E92* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller pci:v00008086d00002E93* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller pci:v00008086d00002E94* ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller pci:v00008086d00002E95* ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller pci:v00008086d00002E96* ID_MODEL_FROM_DATABASE=4 Series Chipset PT IDER Controller pci:v00008086d00002F00* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMI2 pci:v00008086d00002F01* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 0 pci:v00008086d00002F02* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 1 pci:v00008086d00002F03* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 1 pci:v00008086d00002F04* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 pci:v00008086d00002F05* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 pci:v00008086d00002F06* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 pci:v00008086d00002F07* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 pci:v00008086d00002F08* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 pci:v00008086d00002F09* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 pci:v00008086d00002F0A* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 pci:v00008086d00002F0B* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 pci:v00008086d00002F10* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug pci:v00008086d00002F11* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug pci:v00008086d00002F12* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug pci:v00008086d00002F13* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug pci:v00008086d00002F14* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug pci:v00008086d00002F15* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug pci:v00008086d00002F16* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug pci:v00008086d00002F17* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug pci:v00008086d00002F18* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug pci:v00008086d00002F19* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug pci:v00008086d00002F1A* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug pci:v00008086d00002F1B* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug pci:v00008086d00002F1C* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug pci:v00008086d00002F1D* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCIe Ring Interface pci:v00008086d00002F1E* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Scratchpad & Semaphore Registers pci:v00008086d00002F1F* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Scratchpad & Semaphore Registers pci:v00008086d00002F20* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 0 pci:v00008086d00002F21* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 1 pci:v00008086d00002F22* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 2 pci:v00008086d00002F23* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 3 pci:v00008086d00002F24* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 4 pci:v00008086d00002F25* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 5 pci:v00008086d00002F26* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 6 pci:v00008086d00002F27* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 7 pci:v00008086d00002F28* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Address Map, VTd_Misc, System Management pci:v00008086d00002F29* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Hot Plug pci:v00008086d00002F2A* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 RAS, Control Status and Global Errors pci:v00008086d00002F2C* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 I/O APIC pci:v00008086d00002F2E* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 RAID 5/6 pci:v00008086d00002F2F* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 RAID 5/6 pci:v00008086d00002F30* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 0 pci:v00008086d00002F32* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 pci:v00008086d00002F33* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 pci:v00008086d00002F34* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCIe Ring Interface pci:v00008086d00002F36* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 0 & 1 Monitoring pci:v00008086d00002F37* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 0 & 1 Monitoring pci:v00008086d00002F38* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 1 pci:v00008086d00002F39* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 I/O Performance Monitoring pci:v00008086d00002F3A* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 pci:v00008086d00002F3E* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 2 Monitoring pci:v00008086d00002F3F* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 2 Monitoring pci:v00008086d00002F40* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 pci:v00008086d00002F41* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 2 Monitoring pci:v00008086d00002F43* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 pci:v00008086d00002F45* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 Debug pci:v00008086d00002F46* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 Debug pci:v00008086d00002F47* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 Debug pci:v00008086d00002F60* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 1 pci:v00008086d00002F68* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Target Address, Thermal & RAS Registers pci:v00008086d00002F6A* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder pci:v00008086d00002F6B* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder pci:v00008086d00002F6C* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder pci:v00008086d00002F6D* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder pci:v00008086d00002F6E* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO Channel 2/3 Broadcast pci:v00008086d00002F6F* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO Global Broadcast pci:v00008086d00002F70* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 0 Debug pci:v00008086d00002F71* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Target Address, Thermal & RAS Registers pci:v00008086d00002F76* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 E3 QPI Link Debug pci:v00008086d00002F78* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 1 Debug pci:v00008086d00002F79* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Target Address, Thermal & RAS Registers pci:v00008086d00002F7D* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Scratchpad & Semaphore Registers pci:v00008086d00002F7E* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 E3 QPI Link Debug pci:v00008086d00002F80* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 pci:v00008086d00002F81* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 0 & 1 Monitoring pci:v00008086d00002F83* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 pci:v00008086d00002F85* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 Debug pci:v00008086d00002F86* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 Debug pci:v00008086d00002F87* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 Debug pci:v00008086d00002F88* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 VCU pci:v00008086d00002F8A* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 VCU pci:v00008086d00002F90* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 pci:v00008086d00002F93* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 pci:v00008086d00002F95* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 Debug pci:v00008086d00002F96* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 Debug pci:v00008086d00002F98* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit pci:v00008086d00002F99* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit pci:v00008086d00002F9A* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit pci:v00008086d00002F9C* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit pci:v00008086d00002FA0* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 0 pci:v00008086d00002FA8* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Target Address, Thermal & RAS Registers pci:v00008086d00002FAA* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder pci:v00008086d00002FAB* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder pci:v00008086d00002FAC* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder pci:v00008086d00002FAD* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder pci:v00008086d00002FAE* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO Channel 0/1 Broadcast pci:v00008086d00002FAF* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO Global Broadcast pci:v00008086d00002FB0* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 0 Thermal Control pci:v00008086d00002FB1* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 1 Thermal Control pci:v00008086d00002FB2* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 0 ERROR Registers pci:v00008086d00002FB3* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 1 ERROR Registers pci:v00008086d00002FB4* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 2 Thermal Control pci:v00008086d00002FB5* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 3 Thermal Control pci:v00008086d00002FB6* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 2 ERROR Registers pci:v00008086d00002FB7* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 3 ERROR Registers pci:v00008086d00002FB8* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 2 & 3 pci:v00008086d00002FB9* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 2 & 3 pci:v00008086d00002FBA* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 2 & 3 pci:v00008086d00002FBB* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 2 & 3 pci:v00008086d00002FBC* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 0 & 1 pci:v00008086d00002FBD* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 0 & 1 pci:v00008086d00002FBE* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 0 & 1 pci:v00008086d00002FBF* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 0 & 1 pci:v00008086d00002FC0* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit pci:v00008086d00002FC1* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit pci:v00008086d00002FC2* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit pci:v00008086d00002FC3* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit pci:v00008086d00002FC4* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit pci:v00008086d00002FC5* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit pci:v00008086d00002FD0* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 0 Thermal Control pci:v00008086d00002FD1* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 1 Thermal Control pci:v00008086d00002FD2* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 0 ERROR Registers pci:v00008086d00002FD3* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 1 ERROR Registers pci:v00008086d00002FD4* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 2 Thermal Control pci:v00008086d00002FD5* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 3 Thermal Control pci:v00008086d00002FD6* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 2 ERROR Registers pci:v00008086d00002FD7* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 3 ERROR Registers pci:v00008086d00002FE0* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FE1* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FE2* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FE3* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FE4* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FE5* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FE6* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FE7* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FE8* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FE9* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FEA* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FEB* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FEC* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FED* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FEE* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FEF* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FF0* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FF1* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FF2* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FF3* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FF4* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FF5* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FF6* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FF7* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers pci:v00008086d00002FF8* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Buffered Ring Agent pci:v00008086d00002FF9* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Buffered Ring Agent pci:v00008086d00002FFA* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Buffered Ring Agent pci:v00008086d00002FFB* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Buffered Ring Agent pci:v00008086d00002FFC* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 System Address Decoder & Broadcast Registers pci:v00008086d00002FFD* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 System Address Decoder & Broadcast Registers pci:v00008086d00002FFE* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 System Address Decoder & Broadcast Registers pci:v00008086d00003165* ID_MODEL_FROM_DATABASE=Wireless 3165 pci:v00008086d00003165sv00008086sd00004010* ID_MODEL_FROM_DATABASE=Wireless 3165 (Dual Band Wireless AC 3165) pci:v00008086d00003165sv00008086sd00004210* ID_MODEL_FROM_DATABASE=Wireless 3165 (Dual Band Wireless AC 3165) pci:v00008086d00003166* ID_MODEL_FROM_DATABASE=Intel Dual Band Wireless-AC 3165 Plus Bluetooth pci:v00008086d00003200* ID_MODEL_FROM_DATABASE=GD31244 PCI-X SATA HBA pci:v00008086d00003200sv00001775sd0000C200* ID_MODEL_FROM_DATABASE=GD31244 PCI-X SATA HBA (C2K onboard SATA host bus adapter) pci:v00008086d00003310* ID_MODEL_FROM_DATABASE=IOP348 I/O Processor pci:v00008086d00003310sv00001054sd00003030* ID_MODEL_FROM_DATABASE=IOP348 I/O Processor (HRA380 Hitachi RAID Adapter to PCIe) pci:v00008086d00003310sv00001054sd00003034* ID_MODEL_FROM_DATABASE=IOP348 I/O Processor (HRA381 Hitachi RAID Adapter to PCIe) pci:v00008086d00003313* ID_MODEL_FROM_DATABASE=IOP348 I/O Processor (SL8e) in IOC Mode SAS/SATA pci:v00008086d0000331B* ID_MODEL_FROM_DATABASE=IOP348 I/O Processor (SL8x) in IOC Mode SAS/SATA pci:v00008086d00003331* ID_MODEL_FROM_DATABASE=IOC340 I/O Controller (VV8e) SAS/SATA pci:v00008086d00003339* ID_MODEL_FROM_DATABASE=IOC340 I/O Controller (VV8x) SAS/SATA pci:v00008086d00003340* ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller pci:v00008086d00003340sv00001014sd00000529* ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (Thinkpad T40 series) pci:v00008086d00003340sv00001025sd0000005A* ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (TravelMate 290) pci:v00008086d00003340sv0000103Csd0000088C* ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (NC8000 laptop) pci:v00008086d00003340sv0000103Csd00000890* ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (NC6000 laptop) pci:v00008086d00003340sv0000103Csd000008B0* ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (tc1100 tablet) pci:v00008086d00003340sv0000144Dsd0000C005* ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (X10 Laptop) pci:v00008086d00003340sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (P30/P35 notebook) pci:v00008086d00003341* ID_MODEL_FROM_DATABASE=82855PM Processor to AGP Controller pci:v00008086d00003341sv0000144Dsd0000C00C* ID_MODEL_FROM_DATABASE=82855PM Processor to AGP Controller (P30 notebook) pci:v00008086d00003363* ID_MODEL_FROM_DATABASE=IOC340 I/O Controller in IOC Mode SAS/SATA pci:v00008086d00003382* ID_MODEL_FROM_DATABASE=81342 [Chevelon] I/O Processor (ATUe) pci:v00008086d000033C3* ID_MODEL_FROM_DATABASE=IOP348 I/O Processor (SL8De) in IOC Mode SAS/SATA pci:v00008086d000033CB* ID_MODEL_FROM_DATABASE=IOP348 I/O Processor (SL8Dx) in IOC Mode SAS/SATA pci:v00008086d00003400* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub to ESI Port pci:v00008086d00003401* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub to ESI Port pci:v00008086d00003402* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub to ESI Port pci:v00008086d00003403* ID_MODEL_FROM_DATABASE=5500 I/O Hub to ESI Port pci:v00008086d00003403sv00001028sd00000236* ID_MODEL_FROM_DATABASE=5500 I/O Hub to ESI Port (PowerEdge R610 I/O Hub to ESI Port) pci:v00008086d00003403sv00001028sd00000287* ID_MODEL_FROM_DATABASE=5500 I/O Hub to ESI Port (PowerEdge M610 I/O Hub to ESI Port) pci:v00008086d00003403sv00001028sd0000028C* ID_MODEL_FROM_DATABASE=5500 I/O Hub to ESI Port (PowerEdge R410 I/O Hub to ESI Port) pci:v00008086d00003403sv00001028sd0000028D* ID_MODEL_FROM_DATABASE=5500 I/O Hub to ESI Port (PowerEdge T410 I/O Hub to ESI Port) pci:v00008086d00003403sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=5500 I/O Hub to ESI Port (ProLiant ML150 G6 Server) pci:v00008086d00003404* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub to ESI Port pci:v00008086d00003405* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub to ESI Port pci:v00008086d00003406* ID_MODEL_FROM_DATABASE=5520 I/O Hub to ESI Port pci:v00008086d00003406sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=5520 I/O Hub to ESI Port (ProLiant G6 series) pci:v00008086d00003407* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub to ESI Port pci:v00008086d00003408* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 1 pci:v00008086d00003408sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 1 (ProLiant G6 series) pci:v00008086d00003409* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 2 pci:v00008086d0000340A* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 3 pci:v00008086d0000340Asv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 3 (ProLiant ML150 G6 Server) pci:v00008086d0000340B* ID_MODEL_FROM_DATABASE=5520/X58 I/O Hub PCI Express Root Port 4 pci:v00008086d0000340C* ID_MODEL_FROM_DATABASE=5520/X58 I/O Hub PCI Express Root Port 5 pci:v00008086d0000340D* ID_MODEL_FROM_DATABASE=5520/X58 I/O Hub PCI Express Root Port 6 pci:v00008086d0000340E* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 7 pci:v00008086d0000340Esv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 7 (ProLiant ML150 G6 Server) pci:v00008086d0000340F* ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 8 pci:v00008086d00003410* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub PCI Express Root Port 9 pci:v00008086d00003411* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub PCI Express Root Port 10 pci:v00008086d00003418* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 Physical Layer Port 0 pci:v00008086d00003419* ID_MODEL_FROM_DATABASE=7500/5520/5500 Physical Layer Port 1 pci:v00008086d00003420* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 pci:v00008086d00003421* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 pci:v00008086d00003422* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub GPIO and Scratch Pad Registers pci:v00008086d00003422sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub GPIO and Scratch Pad Registers (ProLiant G6 series) pci:v00008086d00003423* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub Control Status and RAS Registers pci:v00008086d00003423sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub Control Status and RAS Registers (ProLiant G6 series) pci:v00008086d00003425* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 Physical and Link Layer Registers Port 0 pci:v00008086d00003426* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 Routing and Protocol Layer Registers Port 0 pci:v00008086d00003427* ID_MODEL_FROM_DATABASE=7500/5520/5500 Physical and Link Layer Registers Port 1 pci:v00008086d00003428* ID_MODEL_FROM_DATABASE=7500/5520/5500 Routing & Protocol Layer Register Port 1 pci:v00008086d00003429* ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device pci:v00008086d0000342A* ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device pci:v00008086d0000342B* ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device pci:v00008086d0000342C* ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device pci:v00008086d0000342D* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub I/OxAPIC Interrupt Controller pci:v00008086d0000342E* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub System Management Registers pci:v00008086d0000342Esv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub System Management Registers (ProLiant G6 series) pci:v00008086d0000342F* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 Trusted Execution Technology Registers pci:v00008086d00003430* ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device pci:v00008086d00003431* ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device pci:v00008086d00003432* ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device pci:v00008086d00003433* ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device pci:v00008086d00003438* ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub Throttle Registers pci:v00008086d00003500* ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Upstream Port pci:v00008086d00003500sv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Upstream Port (ProLiant DL140 G3) pci:v00008086d00003500sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Upstream Port (X7DBN Motherboard) pci:v00008086d00003501* ID_MODEL_FROM_DATABASE=6310ESB PCI Express Upstream Port pci:v00008086d00003504* ID_MODEL_FROM_DATABASE=6311ESB/6321ESB I/OxAPIC Interrupt Controller pci:v00008086d00003505* ID_MODEL_FROM_DATABASE=6310ESB I/OxAPIC Interrupt Controller pci:v00008086d0000350C* ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express to PCI-X Bridge pci:v00008086d0000350Csv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express to PCI-X Bridge (ProLiant DL140 G3) pci:v00008086d0000350Csv000015D9sd00009680* ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express to PCI-X Bridge (X7DBN Motherboard) pci:v00008086d0000350D* ID_MODEL_FROM_DATABASE=6310ESB PCI Express to PCI-X Bridge pci:v00008086d00003510* ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Downstream Port E1 pci:v00008086d00003510sv0000103Csd000031FE* ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Downstream Port E1 (ProLiant DL140 G3) pci:v00008086d00003510sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Downstream Port E1 (X7DBN Motherboard) pci:v00008086d00003511* ID_MODEL_FROM_DATABASE=6310ESB PCI Express Downstream Port E1 pci:v00008086d00003514* ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Downstream Port E2 pci:v00008086d00003515* ID_MODEL_FROM_DATABASE=6310ESB PCI Express Downstream Port E2 pci:v00008086d00003518* ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Downstream Port E3 pci:v00008086d00003518sv000015D9sd00009680* ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Downstream Port E3 (X7DBN Motherboard) pci:v00008086d00003519* ID_MODEL_FROM_DATABASE=6310ESB PCI Express Downstream Port E3 pci:v00008086d00003575* ID_MODEL_FROM_DATABASE=82830M/MG/MP Host Bridge pci:v00008086d00003575sv00000E11sd00000030* ID_MODEL_FROM_DATABASE=82830M/MG/MP Host Bridge (Evo N600c) pci:v00008086d00003575sv00001014sd0000021D* ID_MODEL_FROM_DATABASE=82830M/MG/MP Host Bridge (ThinkPad A/T/X Series) pci:v00008086d00003575sv0000104Dsd000080E7* ID_MODEL_FROM_DATABASE=82830M/MG/MP Host Bridge (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) pci:v00008086d00003576* ID_MODEL_FROM_DATABASE=82830M/MP AGP Bridge pci:v00008086d00003577* ID_MODEL_FROM_DATABASE=82830M/MG Integrated Graphics Controller pci:v00008086d00003577sv00001014sd00000513* ID_MODEL_FROM_DATABASE=82830M/MG Integrated Graphics Controller (ThinkPad A/T/X Series) pci:v00008086d00003578* ID_MODEL_FROM_DATABASE=82830M/MG/MP Host Bridge pci:v00008086d00003580* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller pci:v00008086d00003580sv00001014sd0000055C* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (ThinkPad R50e) pci:v00008086d00003580sv00001025sd00000064* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Extensa 3000 series laptop) pci:v00008086d00003580sv00001028sd00000139* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D400) pci:v00008086d00003580sv00001028sd0000014F* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude X300) pci:v00008086d00003580sv00001028sd00000152* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D500) pci:v00008086d00003580sv00001028sd00000163* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D505) pci:v00008086d00003580sv00001028sd0000018D* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Inspiron 700m/710m) pci:v00008086d00003580sv00001028sd00000196* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Inspiron 5160) pci:v00008086d00003580sv0000114Asd00000582* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (PC8) pci:v00008086d00003580sv00001734sd00001055* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Amilo M1420) pci:v00008086d00003580sv00001775sd000010D0* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (V5D Single Board Computer) pci:v00008086d00003580sv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CE9) pci:v00008086d00003580sv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CL9 mainboard) pci:v00008086d00003580sv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (PSL09 PrPMC) pci:v00008086d00003580sv0000E4BFsd00000CC9* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CC9-SAMBA) pci:v00008086d00003580sv0000E4BFsd00000CD2* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CD2-BEBOP) pci:v00008086d00003581* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to AGP Controller pci:v00008086d00003581sv00001734sd00001055* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to AGP Controller (Amilo M1420) pci:v00008086d00003582* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device pci:v00008086d00003582sv00001014sd00000562* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (ThinkPad R50e) pci:v00008086d00003582sv00001028sd00000139* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (Latitude D400) pci:v00008086d00003582sv00001028sd0000014F* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (Latitude X300) pci:v00008086d00003582sv00001028sd00000152* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (Latitude D500) pci:v00008086d00003582sv00001028sd00000163* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (Latitude D505) pci:v00008086d00003582sv00001028sd0000018D* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (Inspiron 700m/710m) pci:v00008086d00003582sv0000114Asd00000582* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (PC8 integrated graphics) pci:v00008086d00003582sv00001775sd000010D0* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (V5D Single Board Computer VGA) pci:v00008086d00003582sv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (CE9) pci:v00008086d00003582sv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (CL9 mainboard) pci:v00008086d00003582sv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (PSL09 PrPMC) pci:v00008086d00003582sv0000E4BFsd00000CC9* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (CC9-SAMBA) pci:v00008086d00003582sv0000E4BFsd00000CD2* ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (CD2-BEBOP) pci:v00008086d00003584* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller pci:v00008086d00003584sv00001014sd0000055D* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (ThinkPad R50e) pci:v00008086d00003584sv00001025sd00000064* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Extensa 3000 series laptop) pci:v00008086d00003584sv00001028sd00000139* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D400) pci:v00008086d00003584sv00001028sd0000014F* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude X300) pci:v00008086d00003584sv00001028sd00000152* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D500) pci:v00008086d00003584sv00001028sd00000163* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D505) pci:v00008086d00003584sv00001028sd0000018D* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Inspiron 700m/710m) pci:v00008086d00003584sv00001028sd00000196* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Inspiron 5160) pci:v00008086d00003584sv0000114Asd00000582* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (PC8) pci:v00008086d00003584sv00001734sd00001055* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Amilo M1420) pci:v00008086d00003584sv00001775sd000010D0* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (V5D Single Board Computer) pci:v00008086d00003584sv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CE9) pci:v00008086d00003584sv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CL9 mainboard) pci:v00008086d00003584sv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (PSL09 PrPMC) pci:v00008086d00003585* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller pci:v00008086d00003585sv00001014sd0000055E* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (ThinkPad R50e) pci:v00008086d00003585sv00001025sd00000064* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Extensa 3000 series laptop) pci:v00008086d00003585sv00001028sd00000139* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D400) pci:v00008086d00003585sv00001028sd0000014F* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude X300) pci:v00008086d00003585sv00001028sd00000152* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D500) pci:v00008086d00003585sv00001028sd00000163* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D505) pci:v00008086d00003585sv00001028sd0000018D* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Inspiron 700m/710m) pci:v00008086d00003585sv00001028sd00000196* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Inspiron 5160) pci:v00008086d00003585sv0000114Asd00000582* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (PC8) pci:v00008086d00003585sv00001734sd00001055* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Amilo M1420) pci:v00008086d00003585sv00001775sd000010D0* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (V5D Single Board Computer) pci:v00008086d00003585sv00001775sd0000CE90* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CE9) pci:v00008086d00003585sv00004C53sd000010B0* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CL9 mainboard) pci:v00008086d00003585sv00004C53sd000010E0* ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (PSL09 PrPMC) pci:v00008086d0000358C* ID_MODEL_FROM_DATABASE=82854 GMCH pci:v00008086d0000358E* ID_MODEL_FROM_DATABASE=82854 GMCH Integrated Graphics Device pci:v00008086d00003590* ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub pci:v00008086d00003590sv00001014sd000002DD* ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (eServer xSeries server mainboard) pci:v00008086d00003590sv00001028sd0000016C* ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (PowerEdge 1850 Memory Controller Hub) pci:v00008086d00003590sv00001028sd0000016D* ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (PowerEdge 2850 Memory Controller Hub) pci:v00008086d00003590sv00001028sd0000019A* ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (PowerEdge SC1425) pci:v00008086d00003590sv00001734sd0000103E* ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (PRIMERGY RX/TX S2 series) pci:v00008086d00003590sv00001775sd00001100* ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (CR11/VR11 Single Board Computer) pci:v00008086d00003590sv00004C53sd000010D0* ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (Telum ASLP10 Processor AMC) pci:v00008086d00003591* ID_MODEL_FROM_DATABASE=E7525/E7520 Error Reporting Registers pci:v00008086d00003591sv00001014sd000002DD* ID_MODEL_FROM_DATABASE=E7525/E7520 Error Reporting Registers (eServer xSeries server mainboard) pci:v00008086d00003591sv00001028sd00000168* ID_MODEL_FROM_DATABASE=E7525/E7520 Error Reporting Registers (Precision Workstation 670 Mainboard) pci:v00008086d00003591sv00001028sd00000169* ID_MODEL_FROM_DATABASE=E7525/E7520 Error Reporting Registers (Precision 470) pci:v00008086d00003591sv0000103Csd00003208* ID_MODEL_FROM_DATABASE=E7525/E7520 Error Reporting Registers (ProLiant DL140 G2) pci:v00008086d00003591sv00004C53sd000010D0* ID_MODEL_FROM_DATABASE=E7525/E7520 Error Reporting Registers (Telum ASLP10 Processor AMC) pci:v00008086d00003592* ID_MODEL_FROM_DATABASE=E7320 Memory Controller Hub pci:v00008086d00003592sv00001734sd00001073* ID_MODEL_FROM_DATABASE=E7320 Memory Controller Hub (Primergy Econel 200 D2020 mainboard) pci:v00008086d00003593* ID_MODEL_FROM_DATABASE=E7320 Error Reporting Registers pci:v00008086d00003593sv00001734sd00001073* ID_MODEL_FROM_DATABASE=E7320 Error Reporting Registers (Primergy Econel 200 D2020 mainboard) pci:v00008086d00003594* ID_MODEL_FROM_DATABASE=E7520 DMA Controller pci:v00008086d00003594sv00001775sd00001100* ID_MODEL_FROM_DATABASE=E7520 DMA Controller (CR11/VR11 Single Board Computer) pci:v00008086d00003594sv00004C53sd000010D0* ID_MODEL_FROM_DATABASE=E7520 DMA Controller (Telum ASLP10 Processor AMC) pci:v00008086d00003595* ID_MODEL_FROM_DATABASE=E7525/E7520/E7320 PCI Express Port A pci:v00008086d00003595sv00001775sd00001100* ID_MODEL_FROM_DATABASE=E7525/E7520/E7320 PCI Express Port A (CR11/VR11 Single Board Computer) pci:v00008086d00003596* ID_MODEL_FROM_DATABASE=E7525/E7520/E7320 PCI Express Port A1 pci:v00008086d00003597* ID_MODEL_FROM_DATABASE=E7525/E7520 PCI Express Port B pci:v00008086d00003597sv00001775sd00001100* ID_MODEL_FROM_DATABASE=E7525/E7520 PCI Express Port B (CR11/VR11 Single Board Computer) pci:v00008086d00003598* ID_MODEL_FROM_DATABASE=E7520 PCI Express Port B1 pci:v00008086d00003598sv00001775sd00001100* ID_MODEL_FROM_DATABASE=E7520 PCI Express Port B1 (CR11/VR11 Single Board Computer) pci:v00008086d00003599* ID_MODEL_FROM_DATABASE=E7520 PCI Express Port C pci:v00008086d00003599sv00001775sd00001100* ID_MODEL_FROM_DATABASE=E7520 PCI Express Port C (CR11/VR11 Single Board Computer) pci:v00008086d0000359A* ID_MODEL_FROM_DATABASE=E7520 PCI Express Port C1 pci:v00008086d0000359B* ID_MODEL_FROM_DATABASE=E7525/E7520/E7320 Extended Configuration Registers pci:v00008086d0000359Bsv00001014sd000002DD* ID_MODEL_FROM_DATABASE=E7525/E7520/E7320 Extended Configuration Registers (eServer xSeries server mainboard) pci:v00008086d0000359E* ID_MODEL_FROM_DATABASE=E7525 Memory Controller Hub pci:v00008086d0000359Esv00001028sd00000168* ID_MODEL_FROM_DATABASE=E7525 Memory Controller Hub (Precision Workstation 670 Mainboard) pci:v00008086d0000359Esv00001028sd00000169* ID_MODEL_FROM_DATABASE=E7525 Memory Controller Hub (Precision 470) pci:v00008086d000035B0* ID_MODEL_FROM_DATABASE=3100 Chipset Memory I/O Controller Hub pci:v00008086d000035B1* ID_MODEL_FROM_DATABASE=3100 DRAM Controller Error Reporting Registers pci:v00008086d000035B5* ID_MODEL_FROM_DATABASE=3100 Chipset Enhanced DMA Controller pci:v00008086d000035B6* ID_MODEL_FROM_DATABASE=3100 Chipset PCI Express Port A pci:v00008086d000035B7* ID_MODEL_FROM_DATABASE=3100 Chipset PCI Express Port A1 pci:v00008086d000035C8* ID_MODEL_FROM_DATABASE=3100 Extended Configuration Test Overflow Registers pci:v00008086d00003600* ID_MODEL_FROM_DATABASE=7300 Chipset Memory Controller Hub pci:v00008086d00003604* ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 1 pci:v00008086d00003605* ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 2 pci:v00008086d00003606* ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 3 pci:v00008086d00003607* ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 4 pci:v00008086d00003608* ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 5 pci:v00008086d00003609* ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 6 pci:v00008086d0000360A* ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 7 pci:v00008086d0000360B* ID_MODEL_FROM_DATABASE=7300 Chipset QuickData Technology Device pci:v00008086d0000360C* ID_MODEL_FROM_DATABASE=7300 Chipset FSB Registers pci:v00008086d0000360Csv00001028sd000001F0* ID_MODEL_FROM_DATABASE=7300 Chipset FSB Registers (PowerEdge R900 7300 Chipset FSB Registers) pci:v00008086d0000360D* ID_MODEL_FROM_DATABASE=7300 Chipset Snoop Filter Registers pci:v00008086d0000360E* ID_MODEL_FROM_DATABASE=7300 Chipset Debug and Miscellaneous Registers pci:v00008086d0000360F* ID_MODEL_FROM_DATABASE=7300 Chipset FBD Branch 0 Registers pci:v00008086d00003610* ID_MODEL_FROM_DATABASE=7300 Chipset FBD Branch 1 Registers pci:v00008086d00003700* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d00003701* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d00003702* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d00003703* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d00003704* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d00003705* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d00003706* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d00003707* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d00003708* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d00003709* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d0000370A* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d0000370B* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d0000370C* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d0000370D* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d0000370E* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d0000370F* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI pci:v00008086d00003710* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA pci:v00008086d00003711* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA pci:v00008086d00003712* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA pci:v00008086d00003713* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA pci:v00008086d00003714* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA pci:v00008086d00003715* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA pci:v00008086d00003716* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA pci:v00008086d00003717* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA pci:v00008086d00003718* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA pci:v00008086d00003719* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA pci:v00008086d0000371A* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Link pci:v00008086d0000371B* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Routing and Protocol pci:v00008086d0000371D* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Routing and Protocol pci:v00008086d00003720* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 PCI Express Root Port 0 pci:v00008086d00003721* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 PCI Express Root Port 1 pci:v00008086d00003722* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 PCI Express Root Port 2 pci:v00008086d00003723* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 PCI Express Root Port 3 pci:v00008086d00003724* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 PCI Express Root Port 4 pci:v00008086d00003725* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 NTB Primary pci:v00008086d00003726* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 NTB Primary pci:v00008086d00003727* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 NTB Secondary pci:v00008086d00003728* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Core pci:v00008086d00003729* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Core pci:v00008086d0000372A* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Core pci:v00008086d0000372B* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Core pci:v00008086d0000372C* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Reserved pci:v00008086d0000373F* ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 IOxAPIC pci:v00008086d00003A00* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) 4-port SATA IDE Controller pci:v00008086d00003A02* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) SATA AHCI Controller pci:v00008086d00003A05* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) SATA RAID Controller pci:v00008086d00003A06* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) 2-port SATA IDE Controller pci:v00008086d00003A14* ID_MODEL_FROM_DATABASE=82801JDO (ICH10DO) LPC Interface Controller pci:v00008086d00003A16* ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) LPC Interface Controller pci:v00008086d00003A16sv00001028sd0000028C* ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) LPC Interface Controller (PowerEdge R410 LPC Interface Controller) pci:v00008086d00003A16sv00001028sd0000028D* ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) LPC Interface Controller (PowerEdge T410 LPC Interface Controller) pci:v00008086d00003A16sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) LPC Interface Controller (ProLiant G6 series) pci:v00008086d00003A16sv00001043sd000082D4* ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) LPC Interface Controller (P5Q Deluxe Motherboard) pci:v00008086d00003A16sv00001458sd00005001* ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) LPC Interface Controller (GA-EP45-DS5 Motherboard) pci:v00008086d00003A18* ID_MODEL_FROM_DATABASE=82801JIB (ICH10) LPC Interface Controller pci:v00008086d00003A1A* ID_MODEL_FROM_DATABASE=82801JD (ICH10D) LPC Interface Controller pci:v00008086d00003A20* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) 4 port SATA IDE Controller #1 pci:v00008086d00003A20sv00001028sd0000028C* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) 4 port SATA IDE Controller #1 (PowerEdge R410 SATA IDE Controller) pci:v00008086d00003A20sv00001028sd0000028D* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) 4 port SATA IDE Controller #1 (PowerEdge T410 SATA IDE Controller) pci:v00008086d00003A22* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SATA AHCI Controller pci:v00008086d00003A22sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SATA AHCI Controller (ProLiant G6 series) pci:v00008086d00003A22sv00001043sd000082D4* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SATA AHCI Controller (P5Q Deluxe Motherboard) pci:v00008086d00003A22sv00001458sd0000B005* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SATA AHCI Controller (GA-EP45-DS5/GA-EG45M-DS2H Motherboard) pci:v00008086d00003A25* ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) SATA RAID Controller pci:v00008086d00003A25sv00001028sd0000028C* ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) SATA RAID Controller (PERC S100 Controller (PE R410)) pci:v00008086d00003A25sv00001028sd0000028D* ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) SATA RAID Controller (PERC S100 Controller (PE T410)) pci:v00008086d00003A25sv00001028sd000002F1* ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) SATA RAID Controller (PERC S100 Controller (PE R510)) pci:v00008086d00003A26* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) 2 port SATA IDE Controller #2 pci:v00008086d00003A26sv00001028sd0000028C* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) 2 port SATA IDE Controller #2 (PowerEdge R410 SATA IDE Controller) pci:v00008086d00003A26sv00001028sd0000028D* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) 2 port SATA IDE Controller #2 (PowerEdge T410 SATA IDE Controller) pci:v00008086d00003A30* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SMBus Controller pci:v00008086d00003A30sv00001043sd000082D4* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SMBus Controller (P5Q Deluxe Motherboard) pci:v00008086d00003A30sv00001458sd00005001* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SMBus Controller (GA-EP45-DS5/GA-EG45M-DS2H Motherboard) pci:v00008086d00003A32* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) Thermal Subsystem pci:v00008086d00003A34* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #1 pci:v00008086d00003A34sv00001028sd0000028C* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #1 (PowerEdge R410 USB UHCI Controller) pci:v00008086d00003A34sv00001028sd0000028D* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #1 (PowerEdge T410 USB UHCI Controller) pci:v00008086d00003A34sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #1 (ProLiant G6 series) pci:v00008086d00003A34sv00001043sd000082D4* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #1 (P5Q Deluxe Motherboard) pci:v00008086d00003A34sv00001458sd00005004* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #1 (GA-EP45-DS5 Motherboard) pci:v00008086d00003A35* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #2 pci:v00008086d00003A35sv00001028sd0000028C* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #2 (PowerEdge R410 USB UHCI Controller) pci:v00008086d00003A35sv00001028sd0000028D* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #2 (PowerEdge T410 USB UHCI Controller) pci:v00008086d00003A35sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #2 (ProLiant G6 series) pci:v00008086d00003A35sv00001043sd000082D4* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #2 (P5Q Deluxe Motherboard) pci:v00008086d00003A35sv00001458sd00005004* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #2 (GA-EP45-DS5 Motherboard) pci:v00008086d00003A36* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #3 pci:v00008086d00003A36sv00001028sd0000028C* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #3 (PowerEdge R410 USB UHCI Controller) pci:v00008086d00003A36sv00001028sd0000028D* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #3 (PowerEdge T410 USB UHCI Controller) pci:v00008086d00003A36sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #3 (ProLiant G6 series) pci:v00008086d00003A36sv00001043sd000082D4* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #3 (P5Q Deluxe Motherboard) pci:v00008086d00003A36sv00001458sd00005004* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #3 (GA-EP45-DS5 Motherboard) pci:v00008086d00003A37* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #4 pci:v00008086d00003A37sv00001028sd0000028C* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #4 (PowerEdge R410 USB UHCI Controller) pci:v00008086d00003A37sv00001028sd0000028D* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #4 (PowerEdge T410 USB UHCI Controller) pci:v00008086d00003A37sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #4 (ProLiant G6 series) pci:v00008086d00003A37sv00001043sd000082D4* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #4 (P5Q Deluxe Motherboard) pci:v00008086d00003A37sv00001458sd00005004* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #4 (Motherboard) pci:v00008086d00003A38* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #5 pci:v00008086d00003A38sv00001028sd0000028C* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #5 (PowerEdge R410 USB UHCI Controller) pci:v00008086d00003A38sv00001028sd0000028D* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #5 (PowerEdge T410 USB UHCI Controller) pci:v00008086d00003A38sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #5 (ProLiant ML150 G6 Server) pci:v00008086d00003A38sv00001043sd000082D4* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #5 (P5Q Deluxe Motherboard) pci:v00008086d00003A38sv00001458sd00005004* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #5 (Motherboard) pci:v00008086d00003A39* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #6 pci:v00008086d00003A39sv00001028sd0000028C* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #6 (PowerEdge R410 USB UHCI Controller) pci:v00008086d00003A39sv00001028sd0000028D* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #6 (PowerEdge T410 USB UHCI Controller) pci:v00008086d00003A39sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #6 (ProLiant ML150 G6 Server) pci:v00008086d00003A39sv00001043sd000082D4* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #6 (P5Q Deluxe Motherboard) pci:v00008086d00003A39sv00001458sd00005004* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #6 (Motherboard) pci:v00008086d00003A3A* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #1 pci:v00008086d00003A3Asv00001028sd0000028C* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #1 (PowerEdge R410 USB EHCI Controller) pci:v00008086d00003A3Asv00001028sd0000028D* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #1 (PowerEdge T410 USB EHCI Controller) pci:v00008086d00003A3Asv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #1 (ProLiant G6 series) pci:v00008086d00003A3Asv00001043sd000082D4* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #1 (P5Q Deluxe Motherboard) pci:v00008086d00003A3Asv00001458sd00005006* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #1 (GA-EP45-DS5 Motherboard) pci:v00008086d00003A3C* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #2 pci:v00008086d00003A3Csv00001028sd0000028C* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #2 (PowerEdge R410 USB EHCI Controller) pci:v00008086d00003A3Csv00001028sd0000028D* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #2 (PowerEdge T410 USB EHCI Controller) pci:v00008086d00003A3Csv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #2 (ProLiant G6 series) pci:v00008086d00003A3Csv00001043sd000082D4* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #2 (P5Q Deluxe Motherboard) pci:v00008086d00003A3Csv00001458sd00005006* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #2 (Motherboard) pci:v00008086d00003A3E* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) HD Audio Controller pci:v00008086d00003A3Esv00001043sd00008311* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) HD Audio Controller (P5Q Deluxe Motherboard) pci:v00008086d00003A3Esv00001458sd0000A002* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) HD Audio Controller (GA-EP45-UD3R Motherboard) pci:v00008086d00003A3Esv00001458sd0000A102* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) HD Audio Controller (GA-EP45-DS5/GA-EG45M-DS2H Motherboard) pci:v00008086d00003A40* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 pci:v00008086d00003A40sv00001028sd0000028C* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 (PowerEdge R410 PCI Express Port 1) pci:v00008086d00003A40sv00001028sd0000028D* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 (PowerEdge T410 PCI Express Port 1) pci:v00008086d00003A40sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 (ProLiant ML150 G6 Server) pci:v00008086d00003A40sv00001043sd000082D4* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 (P5Q Deluxe Motherboard) pci:v00008086d00003A40sv00001043sd000082EA* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 (P6T DeLuxe Motherboard) pci:v00008086d00003A40sv00001458sd00005001* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 (GA-EP45-DS5/GA-EG45M-DS2H Motherboard) pci:v00008086d00003A42* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Port 2 pci:v00008086d00003A44* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 3 pci:v00008086d00003A44sv00001043sd000082EA* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 3 (P6T DeLuxe Motherboard) pci:v00008086d00003A46* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 4 pci:v00008086d00003A46sv00001043sd000082EA* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 4 (P6T DeLuxe Motherboard) pci:v00008086d00003A46sv00001458sd00005001* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 4 (GA-EP45-DS5 Motherboard) pci:v00008086d00003A48* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 5 pci:v00008086d00003A48sv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 5 (ProLiant ML150 G6 Server) pci:v00008086d00003A48sv00001043sd000082EA* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 5 (P6T Deluxe Motherboard) pci:v00008086d00003A48sv00001458sd00005001* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 5 (GA-EP45-DS5 Motherboard) pci:v00008086d00003A4A* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 6 pci:v00008086d00003A4Asv0000103Csd0000330B* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 6 (ProLiant ML150 G6 Server) pci:v00008086d00003A4Asv00001043sd000082D4* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 6 (P5Q Deluxe Motherboard) pci:v00008086d00003A4Asv00001043sd000082EA* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 6 (P6T DeLuxe Motherboard) pci:v00008086d00003A4Asv00001458sd00005001* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 6 (GA-EP45-DS5/GA-EG45M-DS2H Motherboard) pci:v00008086d00003A4C* ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) Gigabit Ethernet Controller pci:v00008086d00003A51* ID_MODEL_FROM_DATABASE=82801JDO (ICH10DO) VECI Controller pci:v00008086d00003A55* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) Virtual SATA Controller pci:v00008086d00003A60* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) SMBus Controller pci:v00008086d00003A62* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) Thermal Subsystem pci:v00008086d00003A64* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB UHCI Controller #1 pci:v00008086d00003A65* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB UHCI Controller #2 pci:v00008086d00003A66* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB UHCI Controller #3 pci:v00008086d00003A67* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB UHCI Controller #4 pci:v00008086d00003A68* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB UHCI Controller #5 pci:v00008086d00003A69* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB UHCI Controller #6 pci:v00008086d00003A6A* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB2 EHCI Controller #1 pci:v00008086d00003A6C* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB2 EHCI Controller #2 pci:v00008086d00003A6E* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) HD Audio Controller pci:v00008086d00003A70* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) PCI Express Port 1 pci:v00008086d00003A72* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) PCI Express Port 2 pci:v00008086d00003A74* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) PCI Express Port 3 pci:v00008086d00003A76* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) PCI Express Port 4 pci:v00008086d00003A78* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) PCI Express Port 5 pci:v00008086d00003A7A* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) PCI Express Port 6 pci:v00008086d00003A7C* ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) Gigabit Ethernet Controller pci:v00008086d00003B00* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B01* ID_MODEL_FROM_DATABASE=Mobile 5 Series Chipset LPC Interface Controller pci:v00008086d00003B02* ID_MODEL_FROM_DATABASE=P55 Chipset LPC Interface Controller pci:v00008086d00003B03* ID_MODEL_FROM_DATABASE=PM55 Chipset LPC Interface Controller pci:v00008086d00003B04* ID_MODEL_FROM_DATABASE=5 Series Chipset LPC Interface Controller pci:v00008086d00003B05* ID_MODEL_FROM_DATABASE=Mobile 5 Series Chipset LPC Interface Controller pci:v00008086d00003B06* ID_MODEL_FROM_DATABASE=H55 Chipset LPC Interface Controller pci:v00008086d00003B07* ID_MODEL_FROM_DATABASE=QM57 Chipset LPC Interface Controller pci:v00008086d00003B07sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=QM57 Chipset LPC Interface Controller (Latitude E6410) pci:v00008086d00003B07sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=QM57 Chipset LPC Interface Controller (Latitude E6510) pci:v00008086d00003B07sv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=QM57 Chipset LPC Interface Controller (PC1-GROOVE) pci:v00008086d00003B08* ID_MODEL_FROM_DATABASE=H57 Chipset LPC Interface Controller pci:v00008086d00003B09* ID_MODEL_FROM_DATABASE=HM55 Chipset LPC Interface Controller pci:v00008086d00003B09sv00001025sd00000347* ID_MODEL_FROM_DATABASE=HM55 Chipset LPC Interface Controller (Aspire 7740G) pci:v00008086d00003B09sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=HM55 Chipset LPC Interface Controller (R730 Laptop) pci:v00008086d00003B09sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=HM55 Chipset LPC Interface Controller (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B0A* ID_MODEL_FROM_DATABASE=Q57 Chipset LPC Interface Controller pci:v00008086d00003B0Asv00001028sd000002DA* ID_MODEL_FROM_DATABASE=Q57 Chipset LPC Interface Controller (OptiPlex 980) pci:v00008086d00003B0Asv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=Q57 Chipset LPC Interface Controller (C7SIM-Q Motherboard) pci:v00008086d00003B0B* ID_MODEL_FROM_DATABASE=HM57 Chipset LPC Interface Controller pci:v00008086d00003B0C* ID_MODEL_FROM_DATABASE=5 Series Chipset LPC Interface Controller pci:v00008086d00003B0D* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B0E* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B0F* ID_MODEL_FROM_DATABASE=QS57 Chipset LPC Interface Controller pci:v00008086d00003B10* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B11* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B12* ID_MODEL_FROM_DATABASE=3400 Series Chipset LPC Interface Controller pci:v00008086d00003B13* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B14* ID_MODEL_FROM_DATABASE=3420 Chipset LPC Interface Controller pci:v00008086d00003B15* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B16* ID_MODEL_FROM_DATABASE=3450 Chipset LPC Interface Controller pci:v00008086d00003B17* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B18* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B19* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B1A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B1B* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B1C* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B1D* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B1E* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B1F* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller pci:v00008086d00003B20* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA IDE Controller pci:v00008086d00003B21* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 2 port SATA IDE Controller pci:v00008086d00003B22* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller pci:v00008086d00003B22sv00001028sd000002DA* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller (OptiPlex 980) pci:v00008086d00003B22sv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller (C7SIM-Q Motherboard) pci:v00008086d00003B23* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA AHCI Controller pci:v00008086d00003B25* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SATA RAID Controller pci:v00008086d00003B25sv0000103Csd00003118* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SATA RAID Controller (Smart Array B110i SATA RAID Controller) pci:v00008086d00003B26* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 2 port SATA IDE Controller pci:v00008086d00003B28* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA IDE Controller pci:v00008086d00003B28sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA IDE Controller (R730 Laptop) pci:v00008086d00003B28sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA IDE Controller (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B29* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA AHCI Controller pci:v00008086d00003B29sv00001025sd00000347* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA AHCI Controller (Aspire 7740G) pci:v00008086d00003B29sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA AHCI Controller (R730 Laptop) pci:v00008086d00003B29sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA AHCI Controller (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B2C* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SATA RAID Controller pci:v00008086d00003B2D* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 2 port SATA IDE Controller pci:v00008086d00003B2Dsv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 2 port SATA IDE Controller (R730 Laptop) pci:v00008086d00003B2Dsv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 2 port SATA IDE Controller (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B2Dsv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 2 port SATA IDE Controller (PC1-GROOVE) pci:v00008086d00003B2E* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA IDE Controller pci:v00008086d00003B2Esv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA IDE Controller (PC1-GROOVE) pci:v00008086d00003B2F* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller pci:v00008086d00003B2Fsv00001028sd0000040A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller (Latitude E6410) pci:v00008086d00003B2Fsv00001028sd0000040B* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller (Latitude E6510) pci:v00008086d00003B2Fsv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller (PC1-GROOVE) pci:v00008086d00003B30* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller pci:v00008086d00003B30sv00001025sd00000347* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (Aspire 7740G) pci:v00008086d00003B30sv00001028sd000002DA* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (OptiPlex 980) pci:v00008086d00003B30sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (Latitude E6410) pci:v00008086d00003B30sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (Latitude E6510) pci:v00008086d00003B30sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (R730 Laptop) pci:v00008086d00003B30sv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (C7SIM-Q Motherboard) pci:v00008086d00003B30sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B30sv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (PC1-GROOVE) pci:v00008086d00003B32* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset Thermal Subsystem pci:v00008086d00003B32sv00001025sd00000347* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset Thermal Subsystem (Aspire 7740G) pci:v00008086d00003B32sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset Thermal Subsystem (Latitude E6410) pci:v00008086d00003B32sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset Thermal Subsystem (R730 Laptop) pci:v00008086d00003B32sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset Thermal Subsystem (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B34* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller pci:v00008086d00003B34sv00001025sd00000347* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Aspire 7740G) pci:v00008086d00003B34sv00001028sd000002DA* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (OptiPlex 980) pci:v00008086d00003B34sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Latitude E6410) pci:v00008086d00003B34sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Latitude E6510) pci:v00008086d00003B34sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (R730 Laptop) pci:v00008086d00003B34sv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (C7SIM-Q Motherboard) pci:v00008086d00003B34sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B34sv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (PC1-GROOVE) pci:v00008086d00003B36* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller pci:v00008086d00003B37* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller pci:v00008086d00003B38* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller pci:v00008086d00003B39* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller pci:v00008086d00003B3A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller pci:v00008086d00003B3B* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller pci:v00008086d00003B3C* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller pci:v00008086d00003B3Csv00001025sd00000347* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Aspire 7740G) pci:v00008086d00003B3Csv00001028sd000002DA* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (OptiPlex 980) pci:v00008086d00003B3Csv00001028sd0000040A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Latitude E6410) pci:v00008086d00003B3Csv00001028sd0000040B* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Latitude E6510) pci:v00008086d00003B3Csv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (R730 Laptop) pci:v00008086d00003B3Csv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (C7SIM-Q Motherboard) pci:v00008086d00003B3Csv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B3Csv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (PC1-GROOVE) pci:v00008086d00003B3E* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller pci:v00008086d00003B3F* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller pci:v00008086d00003B40* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller pci:v00008086d00003B41* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LAN Controller pci:v00008086d00003B42* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 pci:v00008086d00003B42sv00001028sd000002DA* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 (OptiPlex 980) pci:v00008086d00003B42sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 (Latitude E6410) pci:v00008086d00003B42sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 (Latitude E6510) pci:v00008086d00003B42sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 (R730 Laptop) pci:v00008086d00003B42sv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 (C7SIM-Q Motherboard) pci:v00008086d00003B42sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B44* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 2 pci:v00008086d00003B44sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 2 (Latitude E6410) pci:v00008086d00003B44sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 2 (Latitude E6510) pci:v00008086d00003B44sv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 2 (C7SIM-Q Motherboard) pci:v00008086d00003B44sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 2 (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B46* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 3 pci:v00008086d00003B46sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 3 (Latitude E6410) pci:v00008086d00003B46sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 3 (Latitude E6510) pci:v00008086d00003B46sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 3 (R730 Laptop) pci:v00008086d00003B46sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 3 (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B48* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 4 pci:v00008086d00003B48sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 4 (Latitude E6410) pci:v00008086d00003B48sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 4 (Latitude E6510) pci:v00008086d00003B48sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 4 (R730 Laptop) pci:v00008086d00003B4A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 5 pci:v00008086d00003B4Asv00001028sd000002DA* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 5 (OptiPlex 980) pci:v00008086d00003B4Asv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 5 (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B4C* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 6 pci:v00008086d00003B4E* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 7 pci:v00008086d00003B50* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 8 pci:v00008086d00003B53* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset VECI Controller pci:v00008086d00003B56* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio pci:v00008086d00003B56sv00001025sd00000347* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (Aspire 7740G) pci:v00008086d00003B56sv00001028sd000002DA* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (OptiPlex 980) pci:v00008086d00003B56sv00001028sd0000040A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (Latitude E6410) pci:v00008086d00003B56sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (Latitude E6510) pci:v00008086d00003B56sv0000144Dsd0000C06A* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (R730 Laptop) pci:v00008086d00003B56sv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (C7SIM-Q Motherboard) pci:v00008086d00003B56sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B56sv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (PC1-GROOVE) pci:v00008086d00003B57* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio pci:v00008086d00003B64* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset HECI Controller pci:v00008086d00003B64sv00001025sd00000347* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset HECI Controller (Aspire 7740G) pci:v00008086d00003B64sv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset HECI Controller (C7SIM-Q Motherboard) pci:v00008086d00003B64sv000017C0sd000010D2* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset HECI Controller (Medion Akoya E7214 Notebook PC [MD98410]) pci:v00008086d00003B64sv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset HECI Controller (PC1-GROOVE) pci:v00008086d00003B65* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset HECI Controller pci:v00008086d00003B66* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PT IDER Controller pci:v00008086d00003B67* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset KT Controller pci:v00008086d00003B67sv0000E4BFsd000050C1* ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset KT Controller (PC1-GROOVE) pci:v00008086d00003C00* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMI2 pci:v00008086d00003C01* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMI2 in PCI Express Mode pci:v00008086d00003C02* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 1a pci:v00008086d00003C03* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 1b pci:v00008086d00003C04* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 2a pci:v00008086d00003C05* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 2b pci:v00008086d00003C06* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 2c pci:v00008086d00003C07* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 2d pci:v00008086d00003C08* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 3a in PCI Express Mode pci:v00008086d00003C09* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 3b pci:v00008086d00003C0A* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 3c pci:v00008086d00003C0B* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 3d pci:v00008086d00003C0D* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Non-Transparent Bridge pci:v00008086d00003C0E* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Non-Transparent Bridge pci:v00008086d00003C0F* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Non-Transparent Bridge pci:v00008086d00003C20* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 0 pci:v00008086d00003C21* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 1 pci:v00008086d00003C22* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 2 pci:v00008086d00003C23* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 3 pci:v00008086d00003C24* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 4 pci:v00008086d00003C25* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 5 pci:v00008086d00003C26* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 6 pci:v00008086d00003C27* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 7 pci:v00008086d00003C28* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Address Map, VTd_Misc, System Management pci:v00008086d00003C2A* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Control Status and Global Errors pci:v00008086d00003C2C* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 I/O APIC pci:v00008086d00003C2E* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA pci:v00008086d00003C2F* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA pci:v00008086d00003C40* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO Switch and IRP Performance Monitor pci:v00008086d00003C43* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Ring to PCI Express Performance Monitor pci:v00008086d00003C44* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Ring to QuickPath Interconnect Link 0 Performance Monitor pci:v00008086d00003C45* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Ring to QuickPath Interconnect Link 1 Performance Monitor pci:v00008086d00003C46* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Processor Home Agent Performance Monitoring pci:v00008086d00003C71* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller RAS Registers pci:v00008086d00003C80* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QPI Link 0 pci:v00008086d00003C83* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QPI Link Reut 0 pci:v00008086d00003C84* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QPI Link Reut 0 pci:v00008086d00003C90* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QPI Link 1 pci:v00008086d00003C93* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QPI Link Reut 1 pci:v00008086d00003C94* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QPI Link Reut 1 pci:v00008086d00003CA0* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Processor Home Agent pci:v00008086d00003CA8* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Registers pci:v00008086d00003CAA* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 0 pci:v00008086d00003CAB* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 1 pci:v00008086d00003CAC* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 2 pci:v00008086d00003CAD* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 3 pci:v00008086d00003CAE* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 4 pci:v00008086d00003CB0* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Channel 0-3 Thermal Control 0 pci:v00008086d00003CB1* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Channel 0-3 Thermal Control 1 pci:v00008086d00003CB2* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller ERROR Registers 0 pci:v00008086d00003CB3* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller ERROR Registers 1 pci:v00008086d00003CB4* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Channel 0-3 Thermal Control 2 pci:v00008086d00003CB5* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Channel 0-3 Thermal Control 3 pci:v00008086d00003CB6* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller ERROR Registers 2 pci:v00008086d00003CB7* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller ERROR Registers 3 pci:v00008086d00003CB8* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DDRIO pci:v00008086d00003CC0* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Power Control Unit 0 pci:v00008086d00003CC1* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Power Control Unit 1 pci:v00008086d00003CC2* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Power Control Unit 2 pci:v00008086d00003CD0* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Power Control Unit 3 pci:v00008086d00003CE0* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Interrupt Control Registers pci:v00008086d00003CE3* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Semaphore and Scratchpad Configuration Registers pci:v00008086d00003CE4* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 R2PCIe pci:v00008086d00003CE6* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QuickPath Interconnect Agent Ring Registers pci:v00008086d00003CE8* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 0 pci:v00008086d00003CE9* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 5 pci:v00008086d00003CEA* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 1 pci:v00008086d00003CEB* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 6 pci:v00008086d00003CEC* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 3 pci:v00008086d00003CED* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 7 pci:v00008086d00003CEE* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 4 pci:v00008086d00003CEF* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 8 pci:v00008086d00003CF4* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller System Address Decoder 0 pci:v00008086d00003CF5* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller System Address Decoder 1 pci:v00008086d00003CF6* ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 System Address Decoder pci:v00008086d00004000* ID_MODEL_FROM_DATABASE=5400 Chipset Memory Controller Hub pci:v00008086d00004001* ID_MODEL_FROM_DATABASE=5400 Chipset Memory Controller Hub pci:v00008086d00004003* ID_MODEL_FROM_DATABASE=5400 Chipset Memory Controller Hub pci:v00008086d00004021* ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 1 pci:v00008086d00004022* ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 2 pci:v00008086d00004023* ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 3 pci:v00008086d00004024* ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 4 pci:v00008086d00004025* ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 5 pci:v00008086d00004026* ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 6 pci:v00008086d00004027* ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 7 pci:v00008086d00004028* ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 8 pci:v00008086d00004029* ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 9 pci:v00008086d0000402D* ID_MODEL_FROM_DATABASE=5400 Chipset IBIST Registers pci:v00008086d0000402E* ID_MODEL_FROM_DATABASE=5400 Chipset IBIST Registers pci:v00008086d0000402F* ID_MODEL_FROM_DATABASE=5400 Chipset QuickData Technology Device pci:v00008086d00004030* ID_MODEL_FROM_DATABASE=5400 Chipset FSB Registers pci:v00008086d00004031* ID_MODEL_FROM_DATABASE=5400 Chipset CE/SF Registers pci:v00008086d00004032* ID_MODEL_FROM_DATABASE=5400 Chipset IOxAPIC pci:v00008086d00004035* ID_MODEL_FROM_DATABASE=5400 Chipset FBD Registers pci:v00008086d00004036* ID_MODEL_FROM_DATABASE=5400 Chipset FBD Registers pci:v00008086d00004100* ID_MODEL_FROM_DATABASE=Moorestown Graphics and Video pci:v00008086d00004108* ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller pci:v00008086d00004109* ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller pci:v00008086d0000410A* ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller pci:v00008086d0000410B* ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller pci:v00008086d0000410C* ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller pci:v00008086d0000410D* ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller pci:v00008086d0000410E* ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller pci:v00008086d0000410F* ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller pci:v00008086d00004114* ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Host Bridge #1 pci:v00008086d00004115* ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Host Bridge #2 pci:v00008086d00004116* ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Host Bridge #3 pci:v00008086d00004117* ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Host Bridge #4 pci:v00008086d00004220* ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection pci:v00008086d00004220sv0000103Csd00000934* ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (Compaq nw8240/nx8220) pci:v00008086d00004220sv0000103Csd000012F6* ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (nc6120/nx8220/nw8240) pci:v00008086d00004220sv00008086sd00002701* ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (WM3B2200BG Mini-PCI Card) pci:v00008086d00004220sv00008086sd00002712* ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (IBM ThinkPad R50e) pci:v00008086d00004220sv00008086sd00002721* ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (Dell B130 laptop integrated WLAN) pci:v00008086d00004220sv00008086sd00002722* ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (Dell Latitude D600) pci:v00008086d00004220sv00008086sd00002731* ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (Samsung P35 integrated WLAN) pci:v00008086d00004222* ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection pci:v00008086d00004222sv0000103Csd0000135C* ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection pci:v00008086d00004222sv00008086sd00001000* ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (PRO/Wireless 3945ABG Network Connection) pci:v00008086d00004222sv00008086sd00001001* ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (WM3945ABG MOW2) pci:v00008086d00004222sv00008086sd00001005* ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (PRO/Wireless 3945BG Network Connection) pci:v00008086d00004222sv00008086sd00001034* ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (PRO/Wireless 3945BG Network Connection) pci:v00008086d00004222sv00008086sd00001044* ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (PRO/Wireless 3945BG Network Connection) pci:v00008086d00004222sv00008086sd00001C00* ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (PRO/Wireless 3945ABG Network Connection) pci:v00008086d00004223* ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection pci:v00008086d00004223sv00001000sd00008086* ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection (mPCI 3B Americas/Europe ZZA) pci:v00008086d00004223sv00001001sd00008086* ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection (mPCI 3B Europe ZZE) pci:v00008086d00004223sv00001002sd00008086* ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection (mPCI 3B Japan ZZJ) pci:v00008086d00004223sv00001003sd00008086* ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection (mPCI 3B High-Band ZZH) pci:v00008086d00004223sv00001351sd0000103C* ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection (Compaq NC6220) pci:v00008086d00004224* ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection pci:v00008086d00004227* ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection pci:v00008086d00004227sv00008086sd00001011* ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (ThinkPad T60/R60e/X60s) pci:v00008086d00004227sv00008086sd00001014* ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (PRO/Wireless 3945BG Network Connection) pci:v00008086d00004229* ID_MODEL_FROM_DATABASE=PRO/Wireless 4965 AG or AGN [Kedron] Network Connection pci:v00008086d00004229sv00008086sd00001100* ID_MODEL_FROM_DATABASE=PRO/Wireless 4965 AG or AGN [Kedron] Network Connection (Vaio VGN-SZ79SN_C) pci:v00008086d00004229sv00008086sd00001101* ID_MODEL_FROM_DATABASE=PRO/Wireless 4965 AG or AGN [Kedron] Network Connection (PRO/Wireless 4965 AG or AGN) pci:v00008086d0000422B* ID_MODEL_FROM_DATABASE=Centrino Ultimate-N 6300 pci:v00008086d0000422Bsv00008086sd00001101* ID_MODEL_FROM_DATABASE=Centrino Ultimate-N 6300 (3x3 AGN) pci:v00008086d0000422Bsv00008086sd00001121* ID_MODEL_FROM_DATABASE=Centrino Ultimate-N 6300 (3x3 AGN) pci:v00008086d0000422C* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 pci:v00008086d0000422Csv00008086sd00001301* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 AGN) pci:v00008086d0000422Csv00008086sd00001306* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 ABG) pci:v00008086d0000422Csv00008086sd00001307* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 BG) pci:v00008086d0000422Csv00008086sd00001321* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 AGN) pci:v00008086d0000422Csv00008086sd00001326* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 ABG) pci:v00008086d00004230* ID_MODEL_FROM_DATABASE=PRO/Wireless 4965 AG or AGN [Kedron] Network Connection pci:v00008086d00004230sv00008086sd00001110* ID_MODEL_FROM_DATABASE=PRO/Wireless 4965 AG or AGN [Kedron] Network Connection (Lenovo ThinkPad T51) pci:v00008086d00004230sv00008086sd00001111* ID_MODEL_FROM_DATABASE=PRO/Wireless 4965 AG or AGN [Kedron] Network Connection (Lenovo ThinkPad T61) pci:v00008086d00004232* ID_MODEL_FROM_DATABASE=WiFi Link 5100 pci:v00008086d00004232sv00008086sd00001201* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) pci:v00008086d00004232sv00008086sd00001204* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) pci:v00008086d00004232sv00008086sd00001205* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (BGN) pci:v00008086d00004232sv00008086sd00001206* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (ABG) pci:v00008086d00004232sv00008086sd00001221* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) pci:v00008086d00004232sv00008086sd00001224* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) pci:v00008086d00004232sv00008086sd00001225* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (BGN) pci:v00008086d00004232sv00008086sd00001226* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (ABG) pci:v00008086d00004232sv00008086sd00001301* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) pci:v00008086d00004232sv00008086sd00001304* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) pci:v00008086d00004232sv00008086sd00001305* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (BGN) pci:v00008086d00004232sv00008086sd00001306* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (ABG) pci:v00008086d00004232sv00008086sd00001321* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) pci:v00008086d00004232sv00008086sd00001324* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) pci:v00008086d00004232sv00008086sd00001325* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (BGN) pci:v00008086d00004232sv00008086sd00001326* ID_MODEL_FROM_DATABASE=WiFi Link 5100 (ABG) pci:v00008086d00004235* ID_MODEL_FROM_DATABASE=Ultimate N WiFi Link 5300 pci:v00008086d00004236* ID_MODEL_FROM_DATABASE=Ultimate N WiFi Link 5300 pci:v00008086d00004237* ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection pci:v00008086d00004237sv00008086sd00001211* ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 AGN) pci:v00008086d00004237sv00008086sd00001214* ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 AGN) pci:v00008086d00004237sv00008086sd00001215* ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 BGN) pci:v00008086d00004237sv00008086sd00001216* ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 ABG) pci:v00008086d00004237sv00008086sd00001311* ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 AGN) pci:v00008086d00004237sv00008086sd00001314* ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 AGN) pci:v00008086d00004237sv00008086sd00001315* ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 BGN) pci:v00008086d00004237sv00008086sd00001316* ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 ABG) pci:v00008086d00004238* ID_MODEL_FROM_DATABASE=Centrino Ultimate-N 6300 pci:v00008086d00004238sv00008086sd00001111* ID_MODEL_FROM_DATABASE=Centrino Ultimate-N 6300 (3x3 AGN) pci:v00008086d00004239* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 pci:v00008086d00004239sv00008086sd00001311* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 AGN) pci:v00008086d00004239sv00008086sd00001316* ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 ABG) pci:v00008086d0000423A* ID_MODEL_FROM_DATABASE=PRO/Wireless 5350 AGN [Echo Peak] Network Connection pci:v00008086d0000423B* ID_MODEL_FROM_DATABASE=PRO/Wireless 5350 AGN [Echo Peak] Network Connection pci:v00008086d0000423C* ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 pci:v00008086d0000423Csv00008086sd00001201* ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (AGN) pci:v00008086d0000423Csv00008086sd00001206* ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (ABG) pci:v00008086d0000423Csv00008086sd00001221* ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (AGN) pci:v00008086d0000423Csv00008086sd00001301* ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (AGN) pci:v00008086d0000423Csv00008086sd00001306* ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (ABG) pci:v00008086d0000423Csv00008086sd00001321* ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (AGN) pci:v00008086d0000423D* ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 pci:v00008086d0000423Dsv00008086sd00001211* ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (AGN) pci:v00008086d0000423Dsv00008086sd00001216* ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (ABG) pci:v00008086d0000423Dsv00008086sd00001311* ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (AGN) pci:v00008086d0000423Dsv00008086sd00001316* ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (ABG) pci:v00008086d0000444E* ID_MODEL_FROM_DATABASE=Turbo Memory Controller pci:v00008086d00005001* ID_MODEL_FROM_DATABASE=LE80578 pci:v00008086d00005002* ID_MODEL_FROM_DATABASE=LE80578 Graphics Processor Unit pci:v00008086d00005009* ID_MODEL_FROM_DATABASE=LE80578 Video Display Controller pci:v00008086d0000500D* ID_MODEL_FROM_DATABASE=LE80578 Expansion Bus pci:v00008086d0000500E* ID_MODEL_FROM_DATABASE=LE80578 UART Controller pci:v00008086d0000500F* ID_MODEL_FROM_DATABASE=LE80578 General Purpose IO pci:v00008086d00005010* ID_MODEL_FROM_DATABASE=LE80578 I2C Controller pci:v00008086d00005012* ID_MODEL_FROM_DATABASE=LE80578 Serial Peripheral Interface Bus pci:v00008086d00005020* ID_MODEL_FROM_DATABASE=EP80579 Memory Controller Hub pci:v00008086d00005021* ID_MODEL_FROM_DATABASE=EP80579 DRAM Error Reporting Registers pci:v00008086d00005023* ID_MODEL_FROM_DATABASE=EP80579 EDMA Controller pci:v00008086d00005024* ID_MODEL_FROM_DATABASE=EP80579 PCI Express Port PEA0 pci:v00008086d00005025* ID_MODEL_FROM_DATABASE=EP80579 PCI Express Port PEA1 pci:v00008086d00005028* ID_MODEL_FROM_DATABASE=EP80579 S-ATA IDE pci:v00008086d00005029* ID_MODEL_FROM_DATABASE=EP80579 S-ATA AHCI pci:v00008086d0000502A* ID_MODEL_FROM_DATABASE=EP80579 S-ATA Reserved pci:v00008086d0000502B* ID_MODEL_FROM_DATABASE=EP80579 S-ATA Reserved pci:v00008086d0000502C* ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor ASU pci:v00008086d0000502D* ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor with QuickAssist ASU pci:v00008086d0000502E* ID_MODEL_FROM_DATABASE=EP80579 Reserved pci:v00008086d0000502F* ID_MODEL_FROM_DATABASE=EP80579 Reserved pci:v00008086d00005030* ID_MODEL_FROM_DATABASE=EP80579 Reserved pci:v00008086d00005031* ID_MODEL_FROM_DATABASE=EP80579 LPC Bus pci:v00008086d00005032* ID_MODEL_FROM_DATABASE=EP80579 SMBus Controller pci:v00008086d00005033* ID_MODEL_FROM_DATABASE=EP80579 USB 1.1 Controller pci:v00008086d00005035* ID_MODEL_FROM_DATABASE=EP80579 USB 2.0 Controller pci:v00008086d00005037* ID_MODEL_FROM_DATABASE=EP80579 PCI-PCI Bridge (transparent mode) pci:v00008086d00005039* ID_MODEL_FROM_DATABASE=EP80579 Controller Area Network (CAN) interface #1 pci:v00008086d0000503A* ID_MODEL_FROM_DATABASE=EP80579 Controller Area Network (CAN) interface #2 pci:v00008086d0000503B* ID_MODEL_FROM_DATABASE=EP80579 Synchronous Serial Port (SPP) pci:v00008086d0000503C* ID_MODEL_FROM_DATABASE=EP80579 IEEE 1588 Hardware Assist pci:v00008086d0000503D* ID_MODEL_FROM_DATABASE=EP80579 Local Expansion Bus pci:v00008086d0000503E* ID_MODEL_FROM_DATABASE=EP80579 Global Control Unit (GCU) pci:v00008086d0000503F* ID_MODEL_FROM_DATABASE=EP80579 Reserved pci:v00008086d00005040* ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor Gigabit Ethernet MAC pci:v00008086d00005041* ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor with QuickAssist Gigabit Ethernet MAC pci:v00008086d00005042* ID_MODEL_FROM_DATABASE=EP80579 Reserved pci:v00008086d00005043* ID_MODEL_FROM_DATABASE=EP80579 Reserved pci:v00008086d00005044* ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor Gigabit Ethernet MAC pci:v00008086d00005045* ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor with QuickAssist Gigabit Ethernet MAC pci:v00008086d00005046* ID_MODEL_FROM_DATABASE=EP80579 Reserved pci:v00008086d00005047* ID_MODEL_FROM_DATABASE=EP80579 Reserved pci:v00008086d00005048* ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor Gigabit Ethernet MAC pci:v00008086d00005049* ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor with QuickAssist Gigabit Ethernet MAC pci:v00008086d0000504A* ID_MODEL_FROM_DATABASE=EP80579 Reserved pci:v00008086d0000504B* ID_MODEL_FROM_DATABASE=EP80579 Reserved pci:v00008086d0000504C* ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor with QuickAssist TDM pci:v00008086d00005200* ID_MODEL_FROM_DATABASE=EtherExpress PRO/100 Intelligent Server PCI Bridge pci:v00008086d00005201* ID_MODEL_FROM_DATABASE=EtherExpress PRO/100 Intelligent Server Fast Ethernet Controller pci:v00008086d00005201sv00008086sd00000001* ID_MODEL_FROM_DATABASE=EtherExpress PRO/100 Intelligent Server Fast Ethernet Controller (EtherExpress PRO/100 Server Ethernet Adapter) pci:v00008086d0000530D* ID_MODEL_FROM_DATABASE=80310 (IOP) IO Processor pci:v00008086d00005845* ID_MODEL_FROM_DATABASE=QEMU NVM Express Controller pci:v00008086d00005845sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=QEMU NVM Express Controller (QEMU Virtual Machine) pci:v00008086d00005AD4* ID_MODEL_FROM_DATABASE=Broxton SMBus Controller pci:v00008086d000065C0* ID_MODEL_FROM_DATABASE=5100 Chipset Memory Controller Hub pci:v00008086d000065E2* ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x4 Port 2 pci:v00008086d000065E3* ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x4 Port 3 pci:v00008086d000065E4* ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x4 Port 4 pci:v00008086d000065E5* ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x4 Port 5 pci:v00008086d000065E6* ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x4 Port 6 pci:v00008086d000065E7* ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x4 Port 7 pci:v00008086d000065F0* ID_MODEL_FROM_DATABASE=5100 Chipset FSB Registers pci:v00008086d000065F0sv00001028sd0000020F* ID_MODEL_FROM_DATABASE=5100 Chipset FSB Registers (PowerEdge R300) pci:v00008086d000065F0sv00001028sd00000210* ID_MODEL_FROM_DATABASE=5100 Chipset FSB Registers (PowerEdge T300) pci:v00008086d000065F1* ID_MODEL_FROM_DATABASE=5100 Chipset Reserved Registers pci:v00008086d000065F1sv00001028sd00000210* ID_MODEL_FROM_DATABASE=5100 Chipset Reserved Registers (PowerEdge T300) pci:v00008086d000065F3* ID_MODEL_FROM_DATABASE=5100 Chipset Reserved Registers pci:v00008086d000065F5* ID_MODEL_FROM_DATABASE=5100 Chipset DDR Channel 0 Registers pci:v00008086d000065F6* ID_MODEL_FROM_DATABASE=5100 Chipset DDR Channel 1 Registers pci:v00008086d000065F7* ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x8 Port 2-3 pci:v00008086d000065F8* ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x8 Port 4-5 pci:v00008086d000065F9* ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x8 Port 6-7 pci:v00008086d000065FA* ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x16 Port 4-7 pci:v00008086d000065FF* ID_MODEL_FROM_DATABASE=5100 Chipset DMA Engine pci:v00008086d00006F00* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 pci:v00008086d00006F01* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 0 pci:v00008086d00006F02* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 1 pci:v00008086d00006F03* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 1 pci:v00008086d00006F04* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2 pci:v00008086d00006F05* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2 pci:v00008086d00006F06* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2 pci:v00008086d00006F07* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2 pci:v00008086d00006F08* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3 pci:v00008086d00006F09* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3 pci:v00008086d00006F0A* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3 pci:v00008086d00006F0B* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3 pci:v00008086d00006F10* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug pci:v00008086d00006F11* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug pci:v00008086d00006F12* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug pci:v00008086d00006F13* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug pci:v00008086d00006F14* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug pci:v00008086d00006F15* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug pci:v00008086d00006F16* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug pci:v00008086d00006F17* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug pci:v00008086d00006F18* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug pci:v00008086d00006F19* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug pci:v00008086d00006F1A* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug pci:v00008086d00006F1B* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug pci:v00008086d00006F1C* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug pci:v00008086d00006F1D* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R2PCIe Agent pci:v00008086d00006F1E* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Ubox pci:v00008086d00006F1F* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Ubox pci:v00008086d00006F20* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 0 pci:v00008086d00006F21* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 1 pci:v00008086d00006F22* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 2 pci:v00008086d00006F23* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 3 pci:v00008086d00006F24* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 4 pci:v00008086d00006F25* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 5 pci:v00008086d00006F26* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 6 pci:v00008086d00006F27* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 7 pci:v00008086d00006F28* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Map/VTd_Misc/System Management pci:v00008086d00006F29* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Hot Plug pci:v00008086d00006F2A* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO RAS/Control Status/Global Errors pci:v00008086d00006F2C* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC pci:v00008086d00006F30* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 0 pci:v00008086d00006F32* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 pci:v00008086d00006F33* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 pci:v00008086d00006F34* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R2PCIe Agent pci:v00008086d00006F36* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 0/1 pci:v00008086d00006F37* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 0/1 pci:v00008086d00006F38* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1 pci:v00008086d00006F39* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IO Performance Monitoring pci:v00008086d00006F3A* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 pci:v00008086d00006F3E* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 2 pci:v00008086d00006F3F* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 2 pci:v00008086d00006F40* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 pci:v00008086d00006F41* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 2 pci:v00008086d00006F43* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 pci:v00008086d00006F45* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug pci:v00008086d00006F46* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug pci:v00008086d00006F47* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug pci:v00008086d00006F50* ID_MODEL_FROM_DATABASE=Xeon Processor D Family QuickData Technology Register DMA Channel 0 pci:v00008086d00006F51* ID_MODEL_FROM_DATABASE=Xeon Processor D Family QuickData Technology Register DMA Channel 1 pci:v00008086d00006F52* ID_MODEL_FROM_DATABASE=Xeon Processor D Family QuickData Technology Register DMA Channel 2 pci:v00008086d00006F53* ID_MODEL_FROM_DATABASE=Xeon Processor D Family QuickData Technology Register DMA Channel 3 pci:v00008086d00006F60* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1 pci:v00008086d00006F68* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Target Address/Thermal/RAS pci:v00008086d00006F6A* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder pci:v00008086d00006F6B* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder pci:v00008086d00006F6C* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder pci:v00008086d00006F6D* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder pci:v00008086d00006F6E* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Broadcast pci:v00008086d00006F6F* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Global Broadcast pci:v00008086d00006F70* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 0 Debug pci:v00008086d00006F71* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Target Address/Thermal/RAS pci:v00008086d00006F76* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link Debug pci:v00008086d00006F78* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1 Debug pci:v00008086d00006F79* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Target Address/Thermal/RAS pci:v00008086d00006F7D* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Ubox pci:v00008086d00006F7E* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link Debug pci:v00008086d00006F80* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 pci:v00008086d00006F81* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 0/1 pci:v00008086d00006F83* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 pci:v00008086d00006F85* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 Debug pci:v00008086d00006F86* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 Debug pci:v00008086d00006F87* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 Debug pci:v00008086d00006F88* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006F8A* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006F90* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 pci:v00008086d00006F93* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 pci:v00008086d00006F95* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 Debug pci:v00008086d00006F96* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 Debug pci:v00008086d00006F98* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006F99* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006F9A* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006F9C* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FA0* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 0 pci:v00008086d00006FA8* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Target Address/Thermal/RAS pci:v00008086d00006FAA* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder pci:v00008086d00006FAB* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder pci:v00008086d00006FAC* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder pci:v00008086d00006FAD* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder pci:v00008086d00006FAE* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Broadcast pci:v00008086d00006FAF* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Global Broadcast pci:v00008086d00006FB0* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 0 Thermal Control pci:v00008086d00006FB1* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 1 Thermal Control pci:v00008086d00006FB2* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 0 Error pci:v00008086d00006FB3* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 1 Error pci:v00008086d00006FB4* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 2 Thermal Control pci:v00008086d00006FB5* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 3 Thermal Control pci:v00008086d00006FB6* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 2 Error pci:v00008086d00006FB7* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 3 Error pci:v00008086d00006FB8* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface pci:v00008086d00006FB9* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface pci:v00008086d00006FBA* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface pci:v00008086d00006FBB* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface pci:v00008086d00006FBC* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface pci:v00008086d00006FBD* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface pci:v00008086d00006FBE* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface pci:v00008086d00006FBF* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface pci:v00008086d00006FC0* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FC1* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FC2* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FC3* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FC4* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FC5* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FC6* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FC7* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FC8* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FC9* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FCA* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FCB* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FCC* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FCD* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FCE* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FCF* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit pci:v00008086d00006FD0* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 0 Thermal Control pci:v00008086d00006FD1* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 1 Thermal Control pci:v00008086d00006FD2* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 0 Error pci:v00008086d00006FD3* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 1 Error pci:v00008086d00006FD4* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 2 Thermal Control pci:v00008086d00006FD5* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 3 Thermal Control pci:v00008086d00006FD6* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 2 Error pci:v00008086d00006FD7* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 3 Error pci:v00008086d00006FE0* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FE1* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FE2* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FE3* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FE4* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FE5* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FE6* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FE7* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FE8* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FE9* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FEA* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FEB* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FEC* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FED* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FEE* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FEF* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FF0* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FF1* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FF8* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FF9* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FFA* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FFB* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FFC* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FFD* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00006FFE* ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent pci:v00008086d00007000* ID_MODEL_FROM_DATABASE=82371SB PIIX3 ISA [Natoma/Triton II] pci:v00008086d00007000sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82371SB PIIX3 ISA [Natoma/Triton II] (Qemu virtual machine) pci:v00008086d00007010* ID_MODEL_FROM_DATABASE=82371SB PIIX3 IDE [Natoma/Triton II] pci:v00008086d00007010sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82371SB PIIX3 IDE [Natoma/Triton II] (Qemu virtual machine) pci:v00008086d00007020* ID_MODEL_FROM_DATABASE=82371SB PIIX3 USB [Natoma/Triton II] pci:v00008086d00007020sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82371SB PIIX3 USB [Natoma/Triton II] (QEMU Virtual Machine) pci:v00008086d00007030* ID_MODEL_FROM_DATABASE=430VX - 82437VX TVX [Triton VX] pci:v00008086d00007050* ID_MODEL_FROM_DATABASE=Intercast Video Capture Card pci:v00008086d00007051* ID_MODEL_FROM_DATABASE=PB 642365-003 (Business Video Conferencing Card) pci:v00008086d00007100* ID_MODEL_FROM_DATABASE=430TX - 82439TX MTXC pci:v00008086d00007110* ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 ISA pci:v00008086d00007110sv000015ADsd00001976* ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 ISA (Virtual Machine Chipset) pci:v00008086d00007111* ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 IDE pci:v00008086d00007111sv000015ADsd00001976* ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 IDE (Virtual Machine Chipset) pci:v00008086d00007112* ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 USB pci:v00008086d00007112sv000015ADsd00001976* ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 USB (Virtual Machine Chipset) pci:v00008086d00007112sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 USB (QEMU Virtual Machine) pci:v00008086d00007113* ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 ACPI pci:v00008086d00007113sv000015ADsd00001976* ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 ACPI (Virtual Machine Chipset) pci:v00008086d00007113sv00001AF4sd00001100* ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 ACPI (Qemu virtual machine) pci:v00008086d00007120* ID_MODEL_FROM_DATABASE=82810 GMCH (Graphics Memory Controller Hub) pci:v00008086d00007120sv00004C53sd00001040* ID_MODEL_FROM_DATABASE=82810 GMCH (Graphics Memory Controller Hub) (CL7 mainboard) pci:v00008086d00007120sv00004C53sd00001060* ID_MODEL_FROM_DATABASE=82810 GMCH (Graphics Memory Controller Hub) (PC7 mainboard) pci:v00008086d00007121* ID_MODEL_FROM_DATABASE=82810 (CGC) Chipset Graphics Controller pci:v00008086d00007121sv00004C53sd00001040* ID_MODEL_FROM_DATABASE=82810 (CGC) Chipset Graphics Controller (CL7 mainboard) pci:v00008086d00007121sv00004C53sd00001060* ID_MODEL_FROM_DATABASE=82810 (CGC) Chipset Graphics Controller (PC7 mainboard) pci:v00008086d00007121sv00008086sd00004341* ID_MODEL_FROM_DATABASE=82810 (CGC) Chipset Graphics Controller (Cayman (CA810) Mainboard) pci:v00008086d00007122* ID_MODEL_FROM_DATABASE=82810 DC-100 (GMCH) Graphics Memory Controller Hub pci:v00008086d00007123* ID_MODEL_FROM_DATABASE=82810 DC-100 (CGC) Chipset Graphics Controller pci:v00008086d00007124* ID_MODEL_FROM_DATABASE=82810E DC-133 (GMCH) Graphics Memory Controller Hub pci:v00008086d00007124sv00001028sd000000B4* ID_MODEL_FROM_DATABASE=82810E DC-133 (GMCH) Graphics Memory Controller Hub (OptiPlex GX110) pci:v00008086d00007125* ID_MODEL_FROM_DATABASE=82810E DC-133 (CGC) Chipset Graphics Controller pci:v00008086d00007125sv00001028sd000000B4* ID_MODEL_FROM_DATABASE=82810E DC-133 (CGC) Chipset Graphics Controller (OptiPlex GX110) pci:v00008086d00007126* ID_MODEL_FROM_DATABASE=82810 DC-133 System and Graphics Controller pci:v00008086d00007128* ID_MODEL_FROM_DATABASE=82810-M DC-100 System and Graphics Controller pci:v00008086d0000712A* ID_MODEL_FROM_DATABASE=82810-M DC-133 System and Graphics Controller pci:v00008086d00007180* ID_MODEL_FROM_DATABASE=440LX/EX - 82443LX/EX Host bridge pci:v00008086d00007181* ID_MODEL_FROM_DATABASE=440LX/EX - 82443LX/EX AGP bridge pci:v00008086d00007190* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge pci:v00008086d00007190sv00000E11sd00000500* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (Armada 1750 Laptop System Chipset) pci:v00008086d00007190sv00000E11sd0000B110* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (Armada M700/E500) pci:v00008086d00007190sv00001028sd0000008E* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (PowerEdge 1300 mainboard) pci:v00008086d00007190sv00001043sd0000803B* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (CUBX-L/E Mainboard) pci:v00008086d00007190sv00001179sd00000001* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (Toshiba Tecra 8100 Laptop System Chipset) pci:v00008086d00007190sv000015ADsd00001976* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (Virtual Machine Chipset) pci:v00008086d00007190sv00004C53sd00001050* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (CT7 mainboard) pci:v00008086d00007190sv00004C53sd00001051* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (CE7 mainboard) pci:v00008086d00007191* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX AGP bridge pci:v00008086d00007191sv00001028sd0000008E* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX AGP bridge (PowerEdge 1300 mainboard) pci:v00008086d00007192* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) pci:v00008086d00007192sv00000E11sd00000460* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) (Armada 1700 Laptop System Chipset) pci:v00008086d00007192sv00001179sd00000001* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) (Satellite 4010) pci:v00008086d00007192sv00004C53sd00001000* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) (CC7/CR7/CP7/VC7/VP7/VR7 mainboard) pci:v00008086d00007192sv00008086sd00007190* ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) (Dell PowerEdge 350) pci:v00008086d00007194* ID_MODEL_FROM_DATABASE=82440MX Host Bridge pci:v00008086d00007194sv00001033sd00000000* ID_MODEL_FROM_DATABASE=82440MX Host Bridge (Versa Note Vxi) pci:v00008086d00007194sv00004C53sd000010A0* ID_MODEL_FROM_DATABASE=82440MX Host Bridge (CA3/CR3 mainboard) pci:v00008086d00007195* ID_MODEL_FROM_DATABASE=82440MX AC'97 Audio Controller pci:v00008086d00007195sv00001033sd000080CC* ID_MODEL_FROM_DATABASE=82440MX AC'97 Audio Controller (Versa Note VXi) pci:v00008086d00007195sv000010CFsd00001099* ID_MODEL_FROM_DATABASE=82440MX AC'97 Audio Controller (QSound_SigmaTel Stac97 PCI Audio) pci:v00008086d00007195sv000011D4sd00000040* ID_MODEL_FROM_DATABASE=82440MX AC'97 Audio Controller (SoundMAX Integrated Digital Audio) pci:v00008086d00007195sv000011D4sd00000048* ID_MODEL_FROM_DATABASE=82440MX AC'97 Audio Controller (SoundMAX Integrated Digital Audio) pci:v00008086d00007196* ID_MODEL_FROM_DATABASE=82440MX AC'97 Modem Controller pci:v00008086d00007198* ID_MODEL_FROM_DATABASE=82440MX ISA Bridge pci:v00008086d00007199* ID_MODEL_FROM_DATABASE=82440MX EIDE Controller pci:v00008086d0000719A* ID_MODEL_FROM_DATABASE=82440MX USB Universal Host Controller pci:v00008086d0000719B* ID_MODEL_FROM_DATABASE=82440MX Power Management Controller pci:v00008086d000071A0* ID_MODEL_FROM_DATABASE=440GX - 82443GX Host bridge pci:v00008086d000071A0sv00004C53sd00001050* ID_MODEL_FROM_DATABASE=440GX - 82443GX Host bridge (CT7 mainboard) pci:v00008086d000071A0sv00004C53sd00001051* ID_MODEL_FROM_DATABASE=440GX - 82443GX Host bridge (CE7 mainboard) pci:v00008086d000071A1* ID_MODEL_FROM_DATABASE=440GX - 82443GX AGP bridge pci:v00008086d000071A2* ID_MODEL_FROM_DATABASE=440GX - 82443GX Host bridge (AGP disabled) pci:v00008086d000071A2sv00004C53sd00001000* ID_MODEL_FROM_DATABASE=440GX - 82443GX Host bridge (AGP disabled) (CC7/CR7/CP7/VC7/VP7/VR7 mainboard) pci:v00008086d00007600* ID_MODEL_FROM_DATABASE=82372FB PIIX5 ISA pci:v00008086d00007601* ID_MODEL_FROM_DATABASE=82372FB PIIX5 IDE pci:v00008086d00007602* ID_MODEL_FROM_DATABASE=82372FB PIIX5 USB pci:v00008086d00007603* ID_MODEL_FROM_DATABASE=82372FB PIIX5 SMBus pci:v00008086d00007800* ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator pci:v00008086d00007800sv0000003Dsd00000008* ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Starfighter AGP) pci:v00008086d00007800sv0000003Dsd0000000B* ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Starfighter AGP) pci:v00008086d00007800sv00001092sd00000100* ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Stealth II G460) pci:v00008086d00007800sv000010B4sd0000201A* ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Lightspeed 740) pci:v00008086d00007800sv000010B4sd0000202F* ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Lightspeed 740) pci:v00008086d00007800sv00008086sd00000000* ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Terminator 2x/i) pci:v00008086d00007800sv00008086sd00000100* ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Intel740 Graphics Accelerator) pci:v00008086d00008002* ID_MODEL_FROM_DATABASE=Trusted Execution Technology Registers pci:v00008086d00008003* ID_MODEL_FROM_DATABASE=Trusted Execution Technology Registers pci:v00008086d00008100* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) pci:v00008086d00008108* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) Graphics Controller pci:v00008086d00008110* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) PCI Express Port 1 pci:v00008086d00008112* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) PCI Express Port 2 pci:v00008086d00008114* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) USB UHCI #1 pci:v00008086d00008115* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) USB UHCI #2 pci:v00008086d00008116* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) USB UHCI #3 pci:v00008086d00008117* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) USB EHCI #1 pci:v00008086d00008118* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) USB Client Controller pci:v00008086d00008119* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) LPC Bridge pci:v00008086d0000811A* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) IDE Controller pci:v00008086d0000811B* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) HD Audio Controller pci:v00008086d0000811C* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) SDIO Controller #1 pci:v00008086d0000811D* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) SDIO Controller #2 pci:v00008086d0000811E* ID_MODEL_FROM_DATABASE=System Controller Hub (SCH Poulsbo) SDIO Controller #3 pci:v00008086d00008180* ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Express Port 3 pci:v00008086d00008181* ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Express Port 4 pci:v00008086d00008182* ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller pci:v00008086d00008183* ID_MODEL_FROM_DATABASE=Atom Processor E6xx Configuration Unit pci:v00008086d00008184* ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Express Port 1 pci:v00008086d00008185* ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Express Port 2 pci:v00008086d00008186* ID_MODEL_FROM_DATABASE=Atom Processor E6xx LPC Bridge pci:v00008086d000084C4* ID_MODEL_FROM_DATABASE=450KX/GX [Orion] - 82454KX/GX PCI bridge pci:v00008086d000084C5* ID_MODEL_FROM_DATABASE=450KX/GX [Orion] - 82453KX/GX Memory controller pci:v00008086d000084CA* ID_MODEL_FROM_DATABASE=450NX - 82451NX Memory & I/O Controller pci:v00008086d000084CB* ID_MODEL_FROM_DATABASE=450NX - 82454NX/84460GX PCI Expander Bridge pci:v00008086d000084E0* ID_MODEL_FROM_DATABASE=460GX - 84460GX System Address Controller (SAC) pci:v00008086d000084E1* ID_MODEL_FROM_DATABASE=460GX - 84460GX System Data Controller (SDC) pci:v00008086d000084E2* ID_MODEL_FROM_DATABASE=460GX - 84460GX AGP Bridge (GXB function 2) pci:v00008086d000084E3* ID_MODEL_FROM_DATABASE=460GX - 84460GX Memory Address Controller (MAC) pci:v00008086d000084E4* ID_MODEL_FROM_DATABASE=460GX - 84460GX Memory Data Controller (MDC) pci:v00008086d000084E6* ID_MODEL_FROM_DATABASE=460GX - 82466GX Wide and fast PCI eXpander Bridge (WXB) pci:v00008086d000084EA* ID_MODEL_FROM_DATABASE=460GX - 84460GX AGP Bridge (GXB function 1) pci:v00008086d00008500* ID_MODEL_FROM_DATABASE=IXP4XX Network Processor (IXP420/421/422/425/IXC1100) pci:v00008086d00008500sv00001993sd00000DED* ID_MODEL_FROM_DATABASE=IXP4XX Network Processor (IXP420/421/422/425/IXC1100) (mGuard-PCI AV#2) pci:v00008086d00008500sv00001993sd00000DEE* ID_MODEL_FROM_DATABASE=IXP4XX Network Processor (IXP420/421/422/425/IXC1100) (mGuard-PCI AV#1) pci:v00008086d00008500sv00001993sd00000DEF* ID_MODEL_FROM_DATABASE=IXP4XX Network Processor (IXP420/421/422/425/IXC1100) (mGuard-PCI AV#0) pci:v00008086d00008800* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T PCI Express Port pci:v00008086d00008801* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T Packet Hub pci:v00008086d00008802* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T Gigabit Ethernet Controller pci:v00008086d00008803* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T General Purpose IO Controller pci:v00008086d00008804* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB OHCI Controller #4 pci:v00008086d00008805* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB OHCI Controller #5 pci:v00008086d00008806* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB OHCI Controller #6 pci:v00008086d00008807* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB2 EHCI Controller #2 pci:v00008086d00008808* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB Client Controller pci:v00008086d00008809* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T SDIO Controller #1 pci:v00008086d0000880A* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T SDIO Controller #2 pci:v00008086d0000880B* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T SATA AHCI Controller pci:v00008086d0000880C* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB OHCI Controller #1 pci:v00008086d0000880D* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB OHCI Controller #2 pci:v00008086d0000880E* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB OHCI Controller #3 pci:v00008086d0000880F* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB2 EHCI Controller #1 pci:v00008086d00008810* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T DMA Controller #1 pci:v00008086d00008811* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T UART Controller 0 pci:v00008086d00008812* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T UART Controller 1 pci:v00008086d00008813* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T UART Controller 2 pci:v00008086d00008814* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T UART Controller 3 pci:v00008086d00008815* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T DMA Controller #2 pci:v00008086d00008816* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T Serial Peripheral Interface Bus pci:v00008086d00008817* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T I2C Controller pci:v00008086d00008818* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T Controller Area Network (CAN) Controller pci:v00008086d00008819* ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T IEEE 1588 Hardware Assist pci:v00008086d00008C00* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 4-port SATA Controller 1 [IDE mode] pci:v00008086d00008C01* ID_MODEL_FROM_DATABASE=8 Series Chipset Family 4-port SATA Controller 1 [IDE mode] - Mobile pci:v00008086d00008C02* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] pci:v00008086d00008C03* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] pci:v00008086d00008C03sv0000103Csd00001909* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] (ZBook 15) pci:v00008086d00008C03sv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] (ThinkPad T440p) pci:v00008086d00008C04* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] pci:v00008086d00008C05* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] pci:v00008086d00008C06* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] pci:v00008086d00008C07* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] pci:v00008086d00008C08* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 2-port SATA Controller 2 [IDE mode] pci:v00008086d00008C09* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 2-port SATA Controller 2 [IDE mode] pci:v00008086d00008C0E* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] pci:v00008086d00008C0F* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] pci:v00008086d00008C10* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1 pci:v00008086d00008C10sv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1 (ThinkPad T440p) pci:v00008086d00008C11* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1 pci:v00008086d00008C12* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #2 pci:v00008086d00008C12sv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #2 (ThinkPad T440p) pci:v00008086d00008C13* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #2 pci:v00008086d00008C14* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #3 pci:v00008086d00008C15* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #3 pci:v00008086d00008C16* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #4 pci:v00008086d00008C17* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #4 pci:v00008086d00008C18* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #5 pci:v00008086d00008C19* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #5 pci:v00008086d00008C1A* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #6 pci:v00008086d00008C1B* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #6 pci:v00008086d00008C1C* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #7 pci:v00008086d00008C1D* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #7 pci:v00008086d00008C1E* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #8 pci:v00008086d00008C1F* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #8 pci:v00008086d00008C20* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller pci:v00008086d00008C20sv0000103Csd00001909* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller (ZBook 15) pci:v00008086d00008C20sv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller (ThinkPad T440p) pci:v00008086d00008C21* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller pci:v00008086d00008C22* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller pci:v00008086d00008C22sv0000103Csd00001909* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller (ZBook 15) pci:v00008086d00008C22sv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller (ThinkPad T440p) pci:v00008086d00008C23* ID_MODEL_FROM_DATABASE=8 Series Chipset Family CHAP Counters pci:v00008086d00008C24* ID_MODEL_FROM_DATABASE=8 Series Chipset Family Thermal Management Controller pci:v00008086d00008C26* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 pci:v00008086d00008C26sv0000103Csd00001909* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 (ZBook 15) pci:v00008086d00008C26sv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 (ThinkPad T440p) pci:v00008086d00008C2D* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2 pci:v00008086d00008C2Dsv0000103Csd00001909* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2 (ZBook 15) pci:v00008086d00008C2Dsv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2 (ThinkPad T440p) pci:v00008086d00008C31* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI pci:v00008086d00008C31sv0000103Csd00001909* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI (ZBook 15) pci:v00008086d00008C31sv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI (ThinkPad T440p) pci:v00008086d00008C33* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LAN Controller pci:v00008086d00008C34* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family NAND Controller pci:v00008086d00008C3A* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1 pci:v00008086d00008C3Asv0000103Csd00001909* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1 (ZBook 15) pci:v00008086d00008C3Asv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1 (ThinkPad T440p) pci:v00008086d00008C3B* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #2 pci:v00008086d00008C3C* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family IDE-r Controller pci:v00008086d00008C3D* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family KT Controller pci:v00008086d00008C40* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C41* ID_MODEL_FROM_DATABASE=8 Series Chipset Family Mobile Super SKU LPC Controller pci:v00008086d00008C42* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family Desktop Super SKU LPC Controller pci:v00008086d00008C43* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C44* ID_MODEL_FROM_DATABASE=Z87 Express LPC Controller pci:v00008086d00008C45* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C46* ID_MODEL_FROM_DATABASE=Z85 Express LPC Controller pci:v00008086d00008C47* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C48* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C49* ID_MODEL_FROM_DATABASE=HM86 Express LPC Controller pci:v00008086d00008C4A* ID_MODEL_FROM_DATABASE=H87 Express LPC Controller pci:v00008086d00008C4B* ID_MODEL_FROM_DATABASE=HM87 Express LPC Controller pci:v00008086d00008C4C* ID_MODEL_FROM_DATABASE=Q85 Express LPC Controller pci:v00008086d00008C4D* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C4E* ID_MODEL_FROM_DATABASE=Q87 Express LPC Controller pci:v00008086d00008C4F* ID_MODEL_FROM_DATABASE=QM87 Express LPC Controller pci:v00008086d00008C4Fsv0000103Csd00001909* ID_MODEL_FROM_DATABASE=QM87 Express LPC Controller (ZBook 15) pci:v00008086d00008C4Fsv000017AAsd0000220E* ID_MODEL_FROM_DATABASE=QM87 Express LPC Controller (ThinkPad T440p) pci:v00008086d00008C50* ID_MODEL_FROM_DATABASE=B85 Express LPC Controller pci:v00008086d00008C51* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C52* ID_MODEL_FROM_DATABASE=C222 Series Chipset Family Server Essential SKU LPC Controller pci:v00008086d00008C53* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C54* ID_MODEL_FROM_DATABASE=C224 Series Chipset Family Server Standard SKU LPC Controller pci:v00008086d00008C55* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C56* ID_MODEL_FROM_DATABASE=C226 Series Chipset Family Server Advanced SKU LPC Controller pci:v00008086d00008C57* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C58* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family WS SKU LPC Controller pci:v00008086d00008C59* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C5A* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C5B* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C5C* ID_MODEL_FROM_DATABASE=C220 Series Chipset Family H81 Express LPC Controller pci:v00008086d00008C5D* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C5E* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C5F* ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller pci:v00008086d00008C80* ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [IDE Mode] pci:v00008086d00008C81* ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [IDE Mode] pci:v00008086d00008C82* ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [AHCI Mode] pci:v00008086d00008C83* ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [AHCI Mode] pci:v00008086d00008C84* ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [RAID Mode] pci:v00008086d00008C85* ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [RAID Mode] pci:v00008086d00008C86* ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [RAID Mode] pci:v00008086d00008C87* ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [RAID Mode] pci:v00008086d00008C88* ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [IDE Mode] pci:v00008086d00008C89* ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [IDE Mode] pci:v00008086d00008C8E* ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [RAID Mode] pci:v00008086d00008C8F* ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [RAID Mode] pci:v00008086d00008C90* ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 1 pci:v00008086d00008C92* ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 2 pci:v00008086d00008C94* ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 3 pci:v00008086d00008C96* ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 4 pci:v00008086d00008C98* ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 5 pci:v00008086d00008C9A* ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 6 pci:v00008086d00008C9C* ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 7 pci:v00008086d00008C9E* ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 8 pci:v00008086d00008CA0* ID_MODEL_FROM_DATABASE=9 Series Chipset Family HD Audio Controller pci:v00008086d00008CA2* ID_MODEL_FROM_DATABASE=9 Series Chipset Family SMBus Controller pci:v00008086d00008CA4* ID_MODEL_FROM_DATABASE=9 Series Chipset Family Thermal Controller pci:v00008086d00008CA6* ID_MODEL_FROM_DATABASE=9 Series Chipset Family USB EHCI Controller #1 pci:v00008086d00008CAD* ID_MODEL_FROM_DATABASE=9 Series Chipset Family USB EHCI Controller #2 pci:v00008086d00008CB1* ID_MODEL_FROM_DATABASE=9 Series Chipset Family USB xHCI Controller pci:v00008086d00008CB3* ID_MODEL_FROM_DATABASE=9 Series Chipset Family LAN Controller pci:v00008086d00008CBA* ID_MODEL_FROM_DATABASE=9 Series Chipset Family ME Interface #1 pci:v00008086d00008CBB* ID_MODEL_FROM_DATABASE=9 Series Chipset Family ME Interface #2 pci:v00008086d00008CBC* ID_MODEL_FROM_DATABASE=9 Series Chipset Family IDE-R Controller pci:v00008086d00008CBD* ID_MODEL_FROM_DATABASE=9 Series Chipset Family KT Controller pci:v00008086d00008CC1* ID_MODEL_FROM_DATABASE=9 Series Chipset Family LPC Controller pci:v00008086d00008CC2* ID_MODEL_FROM_DATABASE=9 Series Chipset Family LPC Controller pci:v00008086d00008CC3* ID_MODEL_FROM_DATABASE=9 Series Chipset Family HM97 LPC Controller pci:v00008086d00008CC4* ID_MODEL_FROM_DATABASE=9 Series Chipset Family Z97 LPC Controller pci:v00008086d00008CC6* ID_MODEL_FROM_DATABASE=9 Series Chipset Family H97 Controller pci:v00008086d00008D00* ID_MODEL_FROM_DATABASE=C610/X99 series chipset 4-port SATA Controller [IDE mode] pci:v00008086d00008D02* ID_MODEL_FROM_DATABASE=C610/X99 series chipset 6-Port SATA Controller [AHCI mode] pci:v00008086d00008D04* ID_MODEL_FROM_DATABASE=C610/X99 series chipset SATA Controller [RAID mode] pci:v00008086d00008D06* ID_MODEL_FROM_DATABASE=C610/X99 series chipset SATA Controller [RAID mode] pci:v00008086d00008D06sv000017AAsd00001031* ID_MODEL_FROM_DATABASE=C610/X99 series chipset SATA Controller [RAID mode] (ThinkServer RAID 110i) pci:v00008086d00008D08* ID_MODEL_FROM_DATABASE=C610/X99 series chipset 2-port SATA Controller [IDE mode] pci:v00008086d00008D0E* ID_MODEL_FROM_DATABASE=C610/X99 series chipset SATA Controller [RAID mode] pci:v00008086d00008D10* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #1 pci:v00008086d00008D11* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #1 pci:v00008086d00008D12* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #2 pci:v00008086d00008D13* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #2 pci:v00008086d00008D14* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #3 pci:v00008086d00008D15* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #3 pci:v00008086d00008D16* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #4 pci:v00008086d00008D17* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #4 pci:v00008086d00008D18* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #5 pci:v00008086d00008D19* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #5 pci:v00008086d00008D1A* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #6 pci:v00008086d00008D1B* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #6 pci:v00008086d00008D1C* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #7 pci:v00008086d00008D1D* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #7 pci:v00008086d00008D1E* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #8 pci:v00008086d00008D1F* ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #8 pci:v00008086d00008D20* ID_MODEL_FROM_DATABASE=C610/X99 series chipset HD Audio Controller pci:v00008086d00008D21* ID_MODEL_FROM_DATABASE=C610/X99 series chipset HD Audio Controller pci:v00008086d00008D22* ID_MODEL_FROM_DATABASE=C610/X99 series chipset SMBus Controller pci:v00008086d00008D24* ID_MODEL_FROM_DATABASE=C610/X99 series chipset Thermal Subsystem pci:v00008086d00008D26* ID_MODEL_FROM_DATABASE=C610/X99 series chipset USB Enhanced Host Controller #1 pci:v00008086d00008D2D* ID_MODEL_FROM_DATABASE=C610/X99 series chipset USB Enhanced Host Controller #2 pci:v00008086d00008D31* ID_MODEL_FROM_DATABASE=C610/X99 series chipset USB xHCI Host Controller pci:v00008086d00008D33* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LAN Controller pci:v00008086d00008D34* ID_MODEL_FROM_DATABASE=C610/X99 series chipset NAND Controller pci:v00008086d00008D3A* ID_MODEL_FROM_DATABASE=C610/X99 series chipset MEI Controller #1 pci:v00008086d00008D3B* ID_MODEL_FROM_DATABASE=C610/X99 series chipset MEI Controller #2 pci:v00008086d00008D3C* ID_MODEL_FROM_DATABASE=C610/X99 series chipset IDE-r Controller pci:v00008086d00008D3D* ID_MODEL_FROM_DATABASE=C610/X99 series chipset KT Controller pci:v00008086d00008D40* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D41* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D42* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D43* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D44* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D45* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D46* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D47* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D48* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D49* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D4A* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D4B* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D4C* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D4D* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D4E* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D4F* ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller pci:v00008086d00008D60* ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [IDE mode] pci:v00008086d00008D62* ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [AHCI mode] pci:v00008086d00008D64* ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [RAID mode] pci:v00008086d00008D66* ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [RAID mode] pci:v00008086d00008D68* ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [IDE mode] pci:v00008086d00008D6E* ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [RAID mode] pci:v00008086d00008D7C* ID_MODEL_FROM_DATABASE=C610/X99 series chipset SPSR pci:v00008086d00008D7D* ID_MODEL_FROM_DATABASE=C610/X99 series chipset MS SMBus 0 pci:v00008086d00008D7E* ID_MODEL_FROM_DATABASE=C610/X99 series chipset MS SMBus 1 pci:v00008086d00008D7F* ID_MODEL_FROM_DATABASE=C610/X99 series chipset MS SMBus 2 pci:v00008086d00009000* ID_MODEL_FROM_DATABASE=IXP2000 Family Network Processor pci:v00008086d00009001* ID_MODEL_FROM_DATABASE=IXP2400 Network Processor pci:v00008086d00009002* ID_MODEL_FROM_DATABASE=IXP2300 Network Processor pci:v00008086d00009004* ID_MODEL_FROM_DATABASE=IXP2800 Network Processor pci:v00008086d00009621* ID_MODEL_FROM_DATABASE=Integrated RAID pci:v00008086d00009622* ID_MODEL_FROM_DATABASE=Integrated RAID pci:v00008086d00009641* ID_MODEL_FROM_DATABASE=Integrated RAID pci:v00008086d000096A1* ID_MODEL_FROM_DATABASE=Integrated RAID pci:v00008086d00009C00* ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [IDE mode] pci:v00008086d00009C01* ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [IDE mode] pci:v00008086d00009C02* ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [AHCI mode] pci:v00008086d00009C03* ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [AHCI mode] pci:v00008086d00009C03sv000017AAsd00002214* ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [AHCI mode] (ThinkPad X240) pci:v00008086d00009C04* ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [RAID mode] pci:v00008086d00009C05* ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [RAID mode] pci:v00008086d00009C06* ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [RAID mode] pci:v00008086d00009C07* ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [RAID mode] pci:v00008086d00009C08* ID_MODEL_FROM_DATABASE=8 Series SATA Controller 2 [IDE mode] pci:v00008086d00009C09* ID_MODEL_FROM_DATABASE=8 Series SATA Controller 2 [IDE mode] pci:v00008086d00009C0A* ID_MODEL_FROM_DATABASE=8 Series SATA Controller [Reserved] pci:v00008086d00009C0B* ID_MODEL_FROM_DATABASE=8 Series SATA Controller [Reserved] pci:v00008086d00009C0C* ID_MODEL_FROM_DATABASE=8 Series SATA Controller [Reserved] pci:v00008086d00009C0D* ID_MODEL_FROM_DATABASE=8 Series SATA Controller [Reserved] pci:v00008086d00009C0E* ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [RAID mode] pci:v00008086d00009C0F* ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [RAID mode] pci:v00008086d00009C10* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 1 pci:v00008086d00009C11* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 1 pci:v00008086d00009C12* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 2 pci:v00008086d00009C13* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 2 pci:v00008086d00009C14* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 3 pci:v00008086d00009C15* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 3 pci:v00008086d00009C16* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 4 pci:v00008086d00009C17* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 4 pci:v00008086d00009C18* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 5 pci:v00008086d00009C19* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 5 pci:v00008086d00009C1A* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 6 pci:v00008086d00009C1B* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 6 pci:v00008086d00009C1C* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 7 pci:v00008086d00009C1D* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 7 pci:v00008086d00009C1E* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 8 pci:v00008086d00009C1F* ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 8 pci:v00008086d00009C20* ID_MODEL_FROM_DATABASE=8 Series HD Audio Controller pci:v00008086d00009C20sv000017AAsd00002214* ID_MODEL_FROM_DATABASE=8 Series HD Audio Controller (ThinkPad X240) pci:v00008086d00009C21* ID_MODEL_FROM_DATABASE=8 Series HD Audio Controller pci:v00008086d00009C22* ID_MODEL_FROM_DATABASE=8 Series SMBus Controller pci:v00008086d00009C22sv000017AAsd00002214* ID_MODEL_FROM_DATABASE=8 Series SMBus Controller (ThinkPad X240) pci:v00008086d00009C23* ID_MODEL_FROM_DATABASE=8 Series CHAP Counters pci:v00008086d00009C24* ID_MODEL_FROM_DATABASE=8 Series Thermal pci:v00008086d00009C26* ID_MODEL_FROM_DATABASE=8 Series USB EHCI #1 pci:v00008086d00009C26sv000017AAsd00002214* ID_MODEL_FROM_DATABASE=8 Series USB EHCI #1 (ThinkPad X240) pci:v00008086d00009C2D* ID_MODEL_FROM_DATABASE=8 Series USB EHCI #2 pci:v00008086d00009C31* ID_MODEL_FROM_DATABASE=8 Series USB xHCI HC pci:v00008086d00009C31sv000017AAsd00002214* ID_MODEL_FROM_DATABASE=8 Series USB xHCI HC (ThinkPad X240) pci:v00008086d00009C31sv00008086sd00007270* ID_MODEL_FROM_DATABASE=8 Series USB xHCI HC (Apple MacBookAir6,2 / MacBookPro11,1) pci:v00008086d00009C35* ID_MODEL_FROM_DATABASE=8 Series SDIO Controller pci:v00008086d00009C36* ID_MODEL_FROM_DATABASE=8 Series Audio DSP Controller pci:v00008086d00009C3A* ID_MODEL_FROM_DATABASE=8 Series HECI #0 pci:v00008086d00009C3Asv000017AAsd00002214* ID_MODEL_FROM_DATABASE=8 Series HECI #0 (ThinkPad X240) pci:v00008086d00009C3B* ID_MODEL_FROM_DATABASE=8 Series HECI #1 pci:v00008086d00009C3C* ID_MODEL_FROM_DATABASE=8 Series HECI IDER pci:v00008086d00009C3D* ID_MODEL_FROM_DATABASE=8 Series HECI KT pci:v00008086d00009C40* ID_MODEL_FROM_DATABASE=8 Series LPC Controller pci:v00008086d00009C41* ID_MODEL_FROM_DATABASE=8 Series LPC Controller pci:v00008086d00009C42* ID_MODEL_FROM_DATABASE=8 Series LPC Controller pci:v00008086d00009C43* ID_MODEL_FROM_DATABASE=8 Series LPC Controller pci:v00008086d00009C43sv000017AAsd00002214* ID_MODEL_FROM_DATABASE=8 Series LPC Controller (ThinkPad X240) pci:v00008086d00009C44* ID_MODEL_FROM_DATABASE=8 Series LPC Controller pci:v00008086d00009C45* ID_MODEL_FROM_DATABASE=8 Series LPC Controller pci:v00008086d00009C46* ID_MODEL_FROM_DATABASE=8 Series LPC Controller pci:v00008086d00009C47* ID_MODEL_FROM_DATABASE=8 Series LPC Controller pci:v00008086d00009C60* ID_MODEL_FROM_DATABASE=8 Series Low Power Sub-System DMA pci:v00008086d00009C61* ID_MODEL_FROM_DATABASE=8 Series I2C Controller #0 pci:v00008086d00009C62* ID_MODEL_FROM_DATABASE=8 Series I2C Controller #1 pci:v00008086d00009C63* ID_MODEL_FROM_DATABASE=8 Series UART Controller #0 pci:v00008086d00009C64* ID_MODEL_FROM_DATABASE=8 Series UART Controller #1 pci:v00008086d00009C65* ID_MODEL_FROM_DATABASE=8 Series SPI Controller #0 pci:v00008086d00009C66* ID_MODEL_FROM_DATABASE=8 Series SPI Controller #1 pci:v00008086d00009C83* ID_MODEL_FROM_DATABASE=Wildcat Point-LP SATA Controller [AHCI Mode] pci:v00008086d00009C85* ID_MODEL_FROM_DATABASE=Wildcat Point-LP SATA Controller [RAID Mode] pci:v00008086d00009C87* ID_MODEL_FROM_DATABASE=Wildcat Point-LP SATA Controller [RAID Mode] pci:v00008086d00009C8F* ID_MODEL_FROM_DATABASE=Wildcat Point-LP SATA Controller [RAID Mode] pci:v00008086d00009C90* ID_MODEL_FROM_DATABASE=Wildcat Point-LP PCI Express Root Port #1 pci:v00008086d00009C92* ID_MODEL_FROM_DATABASE=Wildcat Point-LP PCI Express Root Port #2 pci:v00008086d00009C94* ID_MODEL_FROM_DATABASE=Wildcat Point-LP PCI Express Root Port #3 pci:v00008086d00009C96* ID_MODEL_FROM_DATABASE=Wildcat Point-LP PCI Express Root Port #4 pci:v00008086d00009C98* ID_MODEL_FROM_DATABASE=Wildcat Point-LP PCI Express Root Port #5 pci:v00008086d00009C9A* ID_MODEL_FROM_DATABASE=Wildcat Point-LP PCI Express Root Port #6 pci:v00008086d00009CA0* ID_MODEL_FROM_DATABASE=Wildcat Point-LP High Definition Audio Controller pci:v00008086d00009CA2* ID_MODEL_FROM_DATABASE=Wildcat Point-LP SMBus Controller pci:v00008086d00009CA4* ID_MODEL_FROM_DATABASE=Wildcat Point-LP Thermal Management Controller pci:v00008086d00009CA6* ID_MODEL_FROM_DATABASE=Wildcat Point-LP USB EHCI Controller pci:v00008086d00009CB1* ID_MODEL_FROM_DATABASE=Wildcat Point-LP USB xHCI Controller pci:v00008086d00009CB5* ID_MODEL_FROM_DATABASE=Wildcat Point-LP Secure Digital IO Controller pci:v00008086d00009CB6* ID_MODEL_FROM_DATABASE=Wildcat Point-LP Smart Sound Technology Controller pci:v00008086d00009CBA* ID_MODEL_FROM_DATABASE=Wildcat Point-LP MEI Controller #1 pci:v00008086d00009CBB* ID_MODEL_FROM_DATABASE=Wildcat Point-LP MEI Controller #2 pci:v00008086d00009CBC* ID_MODEL_FROM_DATABASE=Wildcat Point-LP IDE-r Controller pci:v00008086d00009CBD* ID_MODEL_FROM_DATABASE=Wildcat Point-LP KT Controller pci:v00008086d00009CC1* ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller pci:v00008086d00009CC2* ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller pci:v00008086d00009CC3* ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller pci:v00008086d00009CC5* ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller pci:v00008086d00009CC6* ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller pci:v00008086d00009CC7* ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller pci:v00008086d00009CC9* ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller pci:v00008086d00009CE0* ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO DMA Controller pci:v00008086d00009CE1* ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO I2C Controller #0 pci:v00008086d00009CE2* ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO I2C Controller #1 pci:v00008086d00009CE3* ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO UART Controller #0 pci:v00008086d00009CE4* ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO UART Controller #1 pci:v00008086d00009CE5* ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO GSPI Controller #0 pci:v00008086d00009CE6* ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO GSPI Controller #1 pci:v00008086d00009D03* ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode] pci:v00008086d00009D14* ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #5 pci:v00008086d00009D15* ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #6 pci:v00008086d00009D21* ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC pci:v00008086d00009D23* ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus pci:v00008086d00009D27* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO UART Controller #0 pci:v00008086d00009D28* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO UART Controller #1 pci:v00008086d00009D29* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO SPI Controller #0 pci:v00008086d00009D2A* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO SPI Controller #1 pci:v00008086d00009D2D* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Secure Digital IO Controller pci:v00008086d00009D2F* ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller pci:v00008086d00009D31* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem pci:v00008086d00009D3A* ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 pci:v00008086d00009D48* ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller pci:v00008086d00009D60* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #0 pci:v00008086d00009D60sv00008086sd00009D60* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #0 (100 Series PCH/Sunrise Point PCH I2C0 [Skylake/Kaby Lake LPSS I2C]) pci:v00008086d00009D61* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #1 pci:v00008086d00009D62* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #2 pci:v00008086d00009D63* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #3 pci:v00008086d00009D64* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #4 pci:v00008086d00009D65* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #5 pci:v00008086d00009D66* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO UART Controller #2 pci:v00008086d00009D70* ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio pci:v00008086d0000A000* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge pci:v00008086d0000A000sv00001458sd00005000* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge (GA-D525TUD) pci:v00008086d0000A000sv00008086sd00004F4D* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge (DeskTop Board D510MO) pci:v00008086d0000A000sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge (Desktop Board D425KT) pci:v00008086d0000A001* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller pci:v00008086d0000A001sv00001458sd0000D000* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller (GA-D525TUD) pci:v00008086d0000A001sv00008086sd00004F4D* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller (DeskTop Board D510MO) pci:v00008086d0000A001sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller (Desktop Board D425KT) pci:v00008086d0000A002* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller pci:v00008086d0000A003* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx CHAPS counter pci:v00008086d0000A010* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge pci:v00008086d0000A010sv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge (Notebook N150P) pci:v00008086d0000A011* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller pci:v00008086d0000A011sv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller (Notebook N150P) pci:v00008086d0000A012* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller pci:v00008086d0000A012sv0000144Dsd0000C072* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller (Notebook N150P) pci:v00008086d0000A013* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx CHAPS counter pci:v00008086d0000A102* ID_MODEL_FROM_DATABASE=Sunrise Point-H SATA controller [AHCI mode] pci:v00008086d0000A103* ID_MODEL_FROM_DATABASE=Sunrise Point-H SATA Controller [AHCI mode] pci:v00008086d0000A105* ID_MODEL_FROM_DATABASE=Sunrise Point-H SATA Controller [RAID mode] pci:v00008086d0000A107* ID_MODEL_FROM_DATABASE=Sunrise Point-H SATA Controller [RAID mode] pci:v00008086d0000A10F* ID_MODEL_FROM_DATABASE=Sunrise Point-H SATA Controller [RAID mode] pci:v00008086d0000A110* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #1 pci:v00008086d0000A111* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #2 pci:v00008086d0000A112* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #3 pci:v00008086d0000A113* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #4 pci:v00008086d0000A114* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #5 pci:v00008086d0000A115* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #6 pci:v00008086d0000A116* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #7 pci:v00008086d0000A117* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #8 pci:v00008086d0000A118* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #9 pci:v00008086d0000A119* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #10 pci:v00008086d0000A11A* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #11 pci:v00008086d0000A11B* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #12 pci:v00008086d0000A11C* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #13 pci:v00008086d0000A11D* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #14 pci:v00008086d0000A11E* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #15 pci:v00008086d0000A11F* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Express Root Port #16 pci:v00008086d0000A120* ID_MODEL_FROM_DATABASE=Sunrise Point-H P2SB pci:v00008086d0000A121* ID_MODEL_FROM_DATABASE=Sunrise Point-H PMC pci:v00008086d0000A122* ID_MODEL_FROM_DATABASE=Sunrise Point-H cAVS pci:v00008086d0000A123* ID_MODEL_FROM_DATABASE=Sunrise Point-H SMBus pci:v00008086d0000A124* ID_MODEL_FROM_DATABASE=Sunrise Point-H SPI Controller pci:v00008086d0000A125* ID_MODEL_FROM_DATABASE=Sunrise Point-H Gigabit Ethernet Controller pci:v00008086d0000A126* ID_MODEL_FROM_DATABASE=Sunrise Point-H Northpeak pci:v00008086d0000A127* ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO UART #0 pci:v00008086d0000A128* ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO UART #1 pci:v00008086d0000A129* ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO SPI #0 pci:v00008086d0000A12A* ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO SPI #1 pci:v00008086d0000A12F* ID_MODEL_FROM_DATABASE=Sunrise Point-H USB 3.0 xHCI Controller pci:v00008086d0000A130* ID_MODEL_FROM_DATABASE=Sunrise Point-H USB Device Controller (OTG) pci:v00008086d0000A131* ID_MODEL_FROM_DATABASE=Sunrise Point-H Thermal subsystem pci:v00008086d0000A133* ID_MODEL_FROM_DATABASE=Sunrise Point-H Northpeak ACPI Function pci:v00008086d0000A135* ID_MODEL_FROM_DATABASE=Sunrise Point-H Integrated Sensor Hub pci:v00008086d0000A13A* ID_MODEL_FROM_DATABASE=Sunrise Point-H CSME HECI #1 pci:v00008086d0000A13B* ID_MODEL_FROM_DATABASE=Sunrise Point-H CSME HECI #2 pci:v00008086d0000A13C* ID_MODEL_FROM_DATABASE=Sunrise Point-H CSME IDE Redirection pci:v00008086d0000A13D* ID_MODEL_FROM_DATABASE=Sunrise Point-H KT Redirection pci:v00008086d0000A13E* ID_MODEL_FROM_DATABASE=Sunrise Point-H CSME HECI #3 pci:v00008086d0000A140* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A141* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A142* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A143* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A144* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A145* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A146* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A147* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A148* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A149* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A14A* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A14B* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A14C* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A14D* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A14E* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A14F* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A150* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A151* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A152* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A153* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A154* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A155* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A156* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A157* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A158* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A159* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A15A* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A15B* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A15C* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A15D* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A15E* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A15F* ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller pci:v00008086d0000A160* ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO I2C Controller #0 pci:v00008086d0000A161* ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO I2C Controller #1 pci:v00008086d0000A166* ID_MODEL_FROM_DATABASE=Sunrise Point-H Serial IO UART Controller #2 pci:v00008086d0000A167* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Root Port #17 pci:v00008086d0000A168* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Root Port #18 pci:v00008086d0000A169* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Root Port #19 pci:v00008086d0000A16A* ID_MODEL_FROM_DATABASE=Sunrise Point-H PCI Root Port #20 pci:v00008086d0000A170* ID_MODEL_FROM_DATABASE=Sunrise Point-H HD Audio pci:v00008086d0000A182* ID_MODEL_FROM_DATABASE=Lewisburg SATA Controller [AHCI mode] pci:v00008086d0000A190* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #1 pci:v00008086d0000A191* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #2 pci:v00008086d0000A192* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #3 pci:v00008086d0000A193* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #4 pci:v00008086d0000A194* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #5 pci:v00008086d0000A195* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #6 pci:v00008086d0000A196* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #7 pci:v00008086d0000A197* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #8 pci:v00008086d0000A198* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #9 pci:v00008086d0000A199* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #10 pci:v00008086d0000A19A* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #11 pci:v00008086d0000A19B* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #12 pci:v00008086d0000A19C* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #13 pci:v00008086d0000A19D* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #14 pci:v00008086d0000A19E* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #15 pci:v00008086d0000A19F* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #16 pci:v00008086d0000A1A0* ID_MODEL_FROM_DATABASE=Lewisburg P2SB pci:v00008086d0000A1A1* ID_MODEL_FROM_DATABASE=Lewisburg PMC pci:v00008086d0000A1A2* ID_MODEL_FROM_DATABASE=Lewisburg cAVS pci:v00008086d0000A1A3* ID_MODEL_FROM_DATABASE=Lewisburg SMBus pci:v00008086d0000A1A4* ID_MODEL_FROM_DATABASE=Lewisburg SPI Controller pci:v00008086d0000A1AF* ID_MODEL_FROM_DATABASE=Lewisburg USB 3.0 xHCI Controller pci:v00008086d0000A1BA* ID_MODEL_FROM_DATABASE=Lewisburg CSME: HECI #1 pci:v00008086d0000A1BB* ID_MODEL_FROM_DATABASE=Lewisburg CSME: HECI #2 pci:v00008086d0000A1BC* ID_MODEL_FROM_DATABASE=Lewisburg CSME: IDE-r pci:v00008086d0000A1BD* ID_MODEL_FROM_DATABASE=Lewisburg CSME: KT Controller pci:v00008086d0000A1BE* ID_MODEL_FROM_DATABASE=Lewisburg CSME: HECI #3 pci:v00008086d0000A1C1* ID_MODEL_FROM_DATABASE=Lewisburg LPC Controller pci:v00008086d0000A1C2* ID_MODEL_FROM_DATABASE=Lewisburg LPC Controller pci:v00008086d0000A1C3* ID_MODEL_FROM_DATABASE=Lewisburg LPC Controller pci:v00008086d0000A1C4* ID_MODEL_FROM_DATABASE=Lewisburg LPC Controller pci:v00008086d0000A1C5* ID_MODEL_FROM_DATABASE=Lewisburg LPC Controller pci:v00008086d0000A1C6* ID_MODEL_FROM_DATABASE=Lewisburg LPC Controller pci:v00008086d0000A1C7* ID_MODEL_FROM_DATABASE=Lewisburg LPC Controller pci:v00008086d0000A1D2* ID_MODEL_FROM_DATABASE=Lewisburg SSATA Controller [AHCI mode] pci:v00008086d0000A1E7* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #17 pci:v00008086d0000A1E8* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #18 pci:v00008086d0000A1E9* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #19 pci:v00008086d0000A1EA* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #20 pci:v00008086d0000A1F0* ID_MODEL_FROM_DATABASE=Lewisburg MROM 0 pci:v00008086d0000A1F1* ID_MODEL_FROM_DATABASE=Lewisburg MROM 1 pci:v00008086d0000A1F8* ID_MODEL_FROM_DATABASE=Lewisburg IE: HECI #1 pci:v00008086d0000A1F9* ID_MODEL_FROM_DATABASE=Lewisburg IE: HECI #2 pci:v00008086d0000A1FA* ID_MODEL_FROM_DATABASE=Lewisburg IE: IDE-r pci:v00008086d0000A1FB* ID_MODEL_FROM_DATABASE=Lewisburg IE: KT Controller pci:v00008086d0000A1FC* ID_MODEL_FROM_DATABASE=Lewisburg IE: HECI #3 pci:v00008086d0000A620* ID_MODEL_FROM_DATABASE=6400/6402 Advanced Memory Buffer (AMB) pci:v00008086d0000ABC0* ID_MODEL_FROM_DATABASE=Omni-Path Fabric Switch Silicon 100 Series pci:v00008086d0000B152* ID_MODEL_FROM_DATABASE=21152 PCI-to-PCI Bridge pci:v00008086d0000B152sv00008086sd0000B152* ID_MODEL_FROM_DATABASE=21152 PCI-to-PCI Bridge pci:v00008086d0000B154* ID_MODEL_FROM_DATABASE=21154 PCI-to-PCI Bridge pci:v00008086d0000B555* ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge pci:v00008086d0000B555sv000012C7sd00005005* ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge (SS7HD PCI Adaptor Card) pci:v00008086d0000B555sv000012C7sd00005006* ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge (SS7HDC cPCI Adaptor Card) pci:v00008086d0000B555sv000012D9sd0000000A* ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge (PCI VoIP Gateway) pci:v00008086d0000B555sv00004C53sd00001050* ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge (CT7 mainboard) pci:v00008086d0000B555sv00004C53sd00001051* ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge (CE7 mainboard) pci:v00008086d0000B555sv0000E4BFsd00001000* ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge (CC8-1-BLUES) pci:v00008086d0000D130* ID_MODEL_FROM_DATABASE=Core Processor DMI pci:v00008086d0000D131* ID_MODEL_FROM_DATABASE=Core Processor DMI pci:v00008086d0000D131sv00001028sd000002DA* ID_MODEL_FROM_DATABASE=Core Processor DMI (OptiPlex 980) pci:v00008086d0000D131sv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=Core Processor DMI (C7SIM-Q Motherboard) pci:v00008086d0000D132* ID_MODEL_FROM_DATABASE=Core Processor DMI pci:v00008086d0000D132sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=Core Processor DMI (Latitude E6510) pci:v00008086d0000D133* ID_MODEL_FROM_DATABASE=Core Processor DMI pci:v00008086d0000D134* ID_MODEL_FROM_DATABASE=Core Processor DMI pci:v00008086d0000D135* ID_MODEL_FROM_DATABASE=Core Processor DMI pci:v00008086d0000D136* ID_MODEL_FROM_DATABASE=Core Processor DMI pci:v00008086d0000D137* ID_MODEL_FROM_DATABASE=Core Processor DMI pci:v00008086d0000D138* ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 1 pci:v00008086d0000D138sv00001028sd000002DA* ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 1 (OptiPlex 980) pci:v00008086d0000D138sv00001028sd0000040B* ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 1 (Latitude E6510) pci:v00008086d0000D138sv000015D9sd0000060D* ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 1 (C7SIM-Q Motherboard) pci:v00008086d0000D139* ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 2 pci:v00008086d0000D13A* ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 3 pci:v00008086d0000D13B* ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 4 pci:v00008086d0000D150* ID_MODEL_FROM_DATABASE=Core Processor QPI Link pci:v00008086d0000D151* ID_MODEL_FROM_DATABASE=Core Processor QPI Routing and Protocol Registers pci:v00008086d0000D155* ID_MODEL_FROM_DATABASE=Core Processor System Management Registers pci:v00008086d0000D156* ID_MODEL_FROM_DATABASE=Core Processor Semaphore and Scratchpad Registers pci:v00008086d0000D157* ID_MODEL_FROM_DATABASE=Core Processor System Control and Status Registers pci:v00008086d0000D158* ID_MODEL_FROM_DATABASE=Core Processor Miscellaneous Registers pci:v000080EE* ID_VENDOR_FROM_DATABASE=InnoTek Systemberatung GmbH pci:v000080EEd0000BEEF* ID_MODEL_FROM_DATABASE=VirtualBox Graphics Adapter pci:v000080EEd0000CAFE* ID_MODEL_FROM_DATABASE=VirtualBox Guest Service pci:v00008322* ID_VENDOR_FROM_DATABASE=Sodick America Corp. pci:v00008384* ID_VENDOR_FROM_DATABASE=SigmaTel pci:v00008401* ID_VENDOR_FROM_DATABASE=TRENDware International Inc. pci:v00008686* ID_VENDOR_FROM_DATABASE=ScaleMP pci:v00008686d00001010* ID_MODEL_FROM_DATABASE=vSMPowered system controller [vSMP CTL] pci:v00008800* ID_VENDOR_FROM_DATABASE=Trigem Computer Inc. pci:v00008800d00002008* ID_MODEL_FROM_DATABASE=Video assistant component pci:v00008866* ID_VENDOR_FROM_DATABASE=T-Square Design Inc. pci:v00008888* ID_VENDOR_FROM_DATABASE=Silicon Magic pci:v00008912* ID_VENDOR_FROM_DATABASE=TRX pci:v00008C4A* ID_VENDOR_FROM_DATABASE=Winbond pci:v00008C4Ad00001980* ID_MODEL_FROM_DATABASE=W89C940 misprogrammed [ne2k] pci:v00008E0E* ID_VENDOR_FROM_DATABASE=Computone Corporation pci:v00008E2E* ID_VENDOR_FROM_DATABASE=KTI pci:v00008E2Ed00003000* ID_MODEL_FROM_DATABASE=ET32P2 pci:v00009004* ID_VENDOR_FROM_DATABASE=Adaptec pci:v00009004d00000078* ID_MODEL_FROM_DATABASE=AHA-2940U_CN pci:v00009004d00001078* ID_MODEL_FROM_DATABASE=AIC-7810 pci:v00009004d00001160* ID_MODEL_FROM_DATABASE=AIC-1160 [Family Fibre Channel Adapter] pci:v00009004d00002178* ID_MODEL_FROM_DATABASE=AIC-7821 pci:v00009004d00003860* ID_MODEL_FROM_DATABASE=AHA-2930CU pci:v00009004d00003B78* ID_MODEL_FROM_DATABASE=AHA-4844W/4844UW pci:v00009004d00005075* ID_MODEL_FROM_DATABASE=AIC-755x pci:v00009004d00005078* ID_MODEL_FROM_DATABASE=AIC-7850T/7856T [AVA-2902/4/6 / AHA-2910] pci:v00009004d00005078sv00009004sd00007850* ID_MODEL_FROM_DATABASE=AIC-7850T/7856T [AVA-2902/4/6 / AHA-2910] (AIC-7850T/7856T [AVA-290x / AHA-2910]) pci:v00009004d00005175* ID_MODEL_FROM_DATABASE=AIC-755x pci:v00009004d00005178* ID_MODEL_FROM_DATABASE=AIC-7851 pci:v00009004d00005275* ID_MODEL_FROM_DATABASE=AIC-755x pci:v00009004d00005278* ID_MODEL_FROM_DATABASE=AIC-7852 pci:v00009004d00005375* ID_MODEL_FROM_DATABASE=AIC-755x pci:v00009004d00005378* ID_MODEL_FROM_DATABASE=AIC-7850 pci:v00009004d00005475* ID_MODEL_FROM_DATABASE=AIC-755x pci:v00009004d00005478* ID_MODEL_FROM_DATABASE=AIC-7850 pci:v00009004d00005575* ID_MODEL_FROM_DATABASE=AVA-2930 pci:v00009004d00005578* ID_MODEL_FROM_DATABASE=AIC-7855 pci:v00009004d00005647* ID_MODEL_FROM_DATABASE=ANA-7711 TCP Offload Engine pci:v00009004d00005647sv00009004sd00007710* ID_MODEL_FROM_DATABASE=ANA-7711 TCP Offload Engine (ANA-7711F TCP Offload Engine - Optical) pci:v00009004d00005647sv00009004sd00007711* ID_MODEL_FROM_DATABASE=ANA-7711 TCP Offload Engine (ANA-7711LP TCP Offload Engine - Copper) pci:v00009004d00005675* ID_MODEL_FROM_DATABASE=AIC-755x pci:v00009004d00005678* ID_MODEL_FROM_DATABASE=AIC-7856 pci:v00009004d00005775* ID_MODEL_FROM_DATABASE=AIC-755x pci:v00009004d00005778* ID_MODEL_FROM_DATABASE=AIC-7850 pci:v00009004d00005800* ID_MODEL_FROM_DATABASE=AIC-5800 pci:v00009004d00005900* ID_MODEL_FROM_DATABASE=ANA-5910/5930/5940 ATM155 & 25 LAN Adapter pci:v00009004d00005905* ID_MODEL_FROM_DATABASE=ANA-5910A/5930A/5940A ATM Adapter pci:v00009004d00006038* ID_MODEL_FROM_DATABASE=AIC-3860 pci:v00009004d00006075* ID_MODEL_FROM_DATABASE=AIC-1480 / APA-1480 pci:v00009004d00006075sv00009004sd00007560* ID_MODEL_FROM_DATABASE=AIC-1480 / APA-1480 (Cardbus) pci:v00009004d00006078* ID_MODEL_FROM_DATABASE=AIC-7860 pci:v00009004d00006178* ID_MODEL_FROM_DATABASE=AIC-7861 pci:v00009004d00006178sv00009004sd00007861* ID_MODEL_FROM_DATABASE=AIC-7861 (AHA-2940AU Single) pci:v00009004d00006278* ID_MODEL_FROM_DATABASE=AIC-7860 pci:v00009004d00006378* ID_MODEL_FROM_DATABASE=AIC-7860 pci:v00009004d00006478* ID_MODEL_FROM_DATABASE=AIC-786x pci:v00009004d00006578* ID_MODEL_FROM_DATABASE=AIC-786x pci:v00009004d00006678* ID_MODEL_FROM_DATABASE=AIC-786x pci:v00009004d00006778* ID_MODEL_FROM_DATABASE=AIC-786x pci:v00009004d00006915* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A pci:v00009004d00006915sv00009004sd00000008* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA69011A/TX 10/100) pci:v00009004d00006915sv00009004sd00000009* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA69011A/TX 10/100) pci:v00009004d00006915sv00009004sd00000010* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62022 2-port 10/100) pci:v00009004d00006915sv00009004sd00000018* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62044 4-port 10/100) pci:v00009004d00006915sv00009004sd00000019* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62044 4-port 10/100) pci:v00009004d00006915sv00009004sd00000020* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62022 2-port 10/100) pci:v00009004d00006915sv00009004sd00000028* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA69011A/TX 10/100) pci:v00009004d00006915sv00009004sd00008008* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA69011A/TX 64 bit 10/100) pci:v00009004d00006915sv00009004sd00008009* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA69011A/TX 64 bit 10/100) pci:v00009004d00006915sv00009004sd00008010* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62022 2-port 64 bit 10/100) pci:v00009004d00006915sv00009004sd00008018* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62044 4-port 64 bit 10/100) pci:v00009004d00006915sv00009004sd00008019* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62044 4-port 64 bit 10/100) pci:v00009004d00006915sv00009004sd00008020* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62022 2-port 64 bit 10/100) pci:v00009004d00006915sv00009004sd00008028* ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA69011A/TX 64 bit 10/100) pci:v00009004d00007078* ID_MODEL_FROM_DATABASE=AHA-294x / AIC-7870 pci:v00009004d00007178* ID_MODEL_FROM_DATABASE=AIC-7870P/7871 [AHA-2940/W/S76] pci:v00009004d00007278* ID_MODEL_FROM_DATABASE=AHA-3940/3940W / AIC-7872 pci:v00009004d00007378* ID_MODEL_FROM_DATABASE=AHA-3985 / AIC-7873 pci:v00009004d00007478* ID_MODEL_FROM_DATABASE=AHA-2944/2944W / AIC-7874 pci:v00009004d00007578* ID_MODEL_FROM_DATABASE=AHA-3944/3944W / AIC-7875 pci:v00009004d00007678* ID_MODEL_FROM_DATABASE=AHA-4944W/UW / AIC-7876 pci:v00009004d00007710* ID_MODEL_FROM_DATABASE=ANA-7711F Network Accelerator Card (NAC) - Optical pci:v00009004d00007711* ID_MODEL_FROM_DATABASE=ANA-7711C Network Accelerator Card (NAC) - Copper pci:v00009004d00007778* ID_MODEL_FROM_DATABASE=AIC-787x pci:v00009004d00007810* ID_MODEL_FROM_DATABASE=AIC-7810 pci:v00009004d00007815* ID_MODEL_FROM_DATABASE=AIC-7815 RAID+Memory Controller IC pci:v00009004d00007815sv00009004sd00007815* ID_MODEL_FROM_DATABASE=AIC-7815 RAID+Memory Controller IC (ARO-1130U2 RAID Controller) pci:v00009004d00007815sv00009004sd00007840* ID_MODEL_FROM_DATABASE=AIC-7815 RAID+Memory Controller IC pci:v00009004d00007850* ID_MODEL_FROM_DATABASE=AIC-7850 pci:v00009004d00007855* ID_MODEL_FROM_DATABASE=AHA-2930 pci:v00009004d00007860* ID_MODEL_FROM_DATABASE=AIC-7860 pci:v00009004d00007870* ID_MODEL_FROM_DATABASE=AIC-7870 pci:v00009004d00007871* ID_MODEL_FROM_DATABASE=AHA-2940 pci:v00009004d00007872* ID_MODEL_FROM_DATABASE=AHA-3940 pci:v00009004d00007873* ID_MODEL_FROM_DATABASE=AHA-3980 pci:v00009004d00007874* ID_MODEL_FROM_DATABASE=AHA-2944 pci:v00009004d00007880* ID_MODEL_FROM_DATABASE=AIC-7880P pci:v00009004d00007890* ID_MODEL_FROM_DATABASE=AIC-7890 pci:v00009004d00007891* ID_MODEL_FROM_DATABASE=AIC-789x pci:v00009004d00007892* ID_MODEL_FROM_DATABASE=AIC-789x pci:v00009004d00007893* ID_MODEL_FROM_DATABASE=AIC-789x pci:v00009004d00007894* ID_MODEL_FROM_DATABASE=AIC-789x pci:v00009004d00007895* ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 pci:v00009004d00007895sv00009004sd00007890* ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B) pci:v00009004d00007895sv00009004sd00007891* ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-2940U/2940UW Dual) pci:v00009004d00007895sv00009004sd00007892* ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-3940AU/AUW/AUWD/UWD) pci:v00009004d00007895sv00009004sd00007894* ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-3944AUWD) pci:v00009004d00007895sv00009004sd00007895* ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B) pci:v00009004d00007895sv00009004sd00007896* ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B) pci:v00009004d00007895sv00009004sd00007897* ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B) pci:v00009004d00007896* ID_MODEL_FROM_DATABASE=AIC-789x pci:v00009004d00007897* ID_MODEL_FROM_DATABASE=AIC-789x pci:v00009004d00008078* ID_MODEL_FROM_DATABASE=AIC-7880U pci:v00009004d00008078sv00009004sd00007880* ID_MODEL_FROM_DATABASE=AIC-7880U (AIC-7880P Ultra/Ultra Wide SCSI Chipset) pci:v00009004d00008178* ID_MODEL_FROM_DATABASE=AIC-7870P/7881U [AHA-2940U/UW/D/S76] pci:v00009004d00008178sv00009004sd00007881* ID_MODEL_FROM_DATABASE=AIC-7870P/7881U [AHA-2940U/UW/D/S76] (AHA-2940UW SCSI Host Adapter) pci:v00009004d00008278* ID_MODEL_FROM_DATABASE=AHA-3940U/UW/UWD / AIC-7882U pci:v00009004d00008378* ID_MODEL_FROM_DATABASE=AHA-3940U/UW / AIC-7883U pci:v00009004d00008478* ID_MODEL_FROM_DATABASE=AHA-2944UW / AIC-7884U pci:v00009004d00008578* ID_MODEL_FROM_DATABASE=AHA-3944U/UWD / AIC-7885 pci:v00009004d00008678* ID_MODEL_FROM_DATABASE=AHA-4944UW / AIC-7886 pci:v00009004d00008778* ID_MODEL_FROM_DATABASE=AHA-2940UW Pro / AIC-788x pci:v00009004d00008778sv00009004sd00007887* ID_MODEL_FROM_DATABASE=AHA-2940UW Pro / AIC-788x (2940UW Pro Ultra-Wide SCSI Controller) pci:v00009004d00008878* ID_MODEL_FROM_DATABASE=AHA-2930UW / AIC-7888 pci:v00009004d00008878sv00009004sd00007888* ID_MODEL_FROM_DATABASE=AHA-2930UW / AIC-7888 (AHA-2930UW SCSI Controller) pci:v00009004d00008B78* ID_MODEL_FROM_DATABASE=ABA-1030 pci:v00009004d0000EC78* ID_MODEL_FROM_DATABASE=AHA-4944W/UW pci:v00009005* ID_VENDOR_FROM_DATABASE=Adaptec pci:v00009005d00000010* ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W pci:v00009005d00000010sv00009005sd00002180* ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W (AHA-2940U2 SCSI Controller) pci:v00009005d00000010sv00009005sd00008100* ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W (AHA-2940U2B SCSI Controller) pci:v00009005d00000010sv00009005sd0000A100* ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W (AHA-2940U2B SCSI Controller) pci:v00009005d00000010sv00009005sd0000A180* ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W (AIC-3860Q [AHA-2940U2W/GE] SCSI Controller) pci:v00009005d00000010sv00009005sd0000E100* ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W (AHA-2950U2B SCSI Controller) pci:v00009005d00000011* ID_MODEL_FROM_DATABASE=AHA-2930U2 pci:v00009005d00000013* ID_MODEL_FROM_DATABASE=78902 pci:v00009005d00000013sv00009005sd00000003* ID_MODEL_FROM_DATABASE=78902 (AAA-131U2 Array1000 1 Channel RAID Controller) pci:v00009005d00000013sv00009005sd0000000F* ID_MODEL_FROM_DATABASE=78902 (AIC7890_ARO) pci:v00009005d0000001F* ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W / 7890/7891 pci:v00009005d0000001Fsv00009005sd0000000F* ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W / 7890/7891 (2940U2W SCSI Controller) pci:v00009005d0000001Fsv00009005sd0000A180* ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W / 7890/7891 (2940U2W SCSI Controller) pci:v00009005d00000020* ID_MODEL_FROM_DATABASE=AIC-7890 pci:v00009005d0000002F* ID_MODEL_FROM_DATABASE=AIC-7890 pci:v00009005d00000030* ID_MODEL_FROM_DATABASE=AIC-7890 pci:v00009005d0000003F* ID_MODEL_FROM_DATABASE=AIC-7890 pci:v00009005d00000050* ID_MODEL_FROM_DATABASE=AHA-3940U2x/395U2x pci:v00009005d00000050sv00009005sd0000F500* ID_MODEL_FROM_DATABASE=AHA-3940U2x/395U2x (AHA-3950U2B) pci:v00009005d00000050sv00009005sd0000FFFF* ID_MODEL_FROM_DATABASE=AHA-3940U2x/395U2x (AHA-3950U2B) pci:v00009005d00000051* ID_MODEL_FROM_DATABASE=AHA-3950U2D pci:v00009005d00000051sv00009005sd0000B500* ID_MODEL_FROM_DATABASE=AHA-3950U2D pci:v00009005d00000053* ID_MODEL_FROM_DATABASE=AIC-7896 SCSI Controller pci:v00009005d00000053sv00009005sd0000FFFF* ID_MODEL_FROM_DATABASE=AIC-7896 SCSI Controller (mainboard implementation) pci:v00009005d0000005F* ID_MODEL_FROM_DATABASE=AIC-7896U2/7897U2 pci:v00009005d00000080* ID_MODEL_FROM_DATABASE=AIC-7892A U160/m pci:v00009005d00000080sv00000E11sd0000E2A0* ID_MODEL_FROM_DATABASE=AIC-7892A U160/m (Compaq 64-Bit/66MHz Wide Ultra3 SCSI Adapter) pci:v00009005d00000080sv00009005sd00006220* ID_MODEL_FROM_DATABASE=AIC-7892A U160/m (AHA-29160C) pci:v00009005d00000080sv00009005sd000062A0* ID_MODEL_FROM_DATABASE=AIC-7892A U160/m (29160N Ultra160 SCSI Controller) pci:v00009005d00000080sv00009005sd0000E220* ID_MODEL_FROM_DATABASE=AIC-7892A U160/m (29160LP Low Profile Ultra160 SCSI Controller) pci:v00009005d00000080sv00009005sd0000E2A0* ID_MODEL_FROM_DATABASE=AIC-7892A U160/m (29160 Ultra160 SCSI Controller) pci:v00009005d00000081* ID_MODEL_FROM_DATABASE=AIC-7892B U160/m pci:v00009005d00000081sv00009005sd000062A1* ID_MODEL_FROM_DATABASE=AIC-7892B U160/m (19160 Ultra160 SCSI Controller) pci:v00009005d00000083* ID_MODEL_FROM_DATABASE=AIC-7892D U160/m pci:v00009005d0000008F* ID_MODEL_FROM_DATABASE=AIC-7892P U160/m pci:v00009005d0000008Fsv00001179sd00000001* ID_MODEL_FROM_DATABASE=AIC-7892P U160/m (Magnia Z310) pci:v00009005d0000008Fsv000015D9sd00009005* ID_MODEL_FROM_DATABASE=AIC-7892P U160/m (Onboard SCSI Host Adapter) pci:v00009005d00000092* ID_MODEL_FROM_DATABASE=AVC-2010 [VideoH!] pci:v00009005d00000093* ID_MODEL_FROM_DATABASE=AVC-2410 [VideoH!] pci:v00009005d000000C0* ID_MODEL_FROM_DATABASE=AHA-3960D / AIC-7899A U160/m pci:v00009005d000000C0sv00000E11sd0000F620* ID_MODEL_FROM_DATABASE=AHA-3960D / AIC-7899A U160/m (Compaq 64-Bit/66MHz Dual Channel Wide Ultra3 SCSI Adapter) pci:v00009005d000000C0sv00009005sd0000F620* ID_MODEL_FROM_DATABASE=AHA-3960D / AIC-7899A U160/m (AHA-3960D U160/m) pci:v00009005d000000C1* ID_MODEL_FROM_DATABASE=AIC-7899B U160/m pci:v00009005d000000C3* ID_MODEL_FROM_DATABASE=AIC-7899D U160/m pci:v00009005d000000C5* ID_MODEL_FROM_DATABASE=RAID subsystem HBA pci:v00009005d000000C5sv00001028sd000000C5* ID_MODEL_FROM_DATABASE=RAID subsystem HBA (PowerEdge 2400,2500,2550,4400) pci:v00009005d000000CF* ID_MODEL_FROM_DATABASE=AIC-7899P U160/m pci:v00009005d000000CFsv00001028sd000000CE* ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (PowerEdge 1400) pci:v00009005d000000CFsv00001028sd000000D1* ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (PowerEdge 2550) pci:v00009005d000000CFsv00001028sd000000D9* ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (PowerEdge 2500) pci:v00009005d000000CFsv000010F1sd00002462* ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (Thunder K7 S2462) pci:v00009005d000000CFsv000015D9sd00009005* ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (Onboard SCSI Host Adapter) pci:v00009005d000000CFsv00008086sd00003411* ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (SDS2 Mainboard) pci:v00009005d00000241* ID_MODEL_FROM_DATABASE=Serial ATA II RAID 1420SA pci:v00009005d00000242* ID_MODEL_FROM_DATABASE=Serial ATA II RAID 1220SA pci:v00009005d00000243* ID_MODEL_FROM_DATABASE=Serial ATA II RAID 1430SA pci:v00009005d00000244* ID_MODEL_FROM_DATABASE=eSATA II RAID 1225SA pci:v00009005d00000250* ID_MODEL_FROM_DATABASE=ServeRAID Controller pci:v00009005d00000250sv00001014sd00000279* ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID 6M) pci:v00009005d00000250sv00001014sd0000028C* ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID 6i/6i+) pci:v00009005d00000250sv00001014sd0000028E* ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID 7k) pci:v00009005d00000279* ID_MODEL_FROM_DATABASE=ServeRAID 6M pci:v00009005d00000283* ID_MODEL_FROM_DATABASE=AAC-RAID pci:v00009005d00000283sv00009005sd00000283* ID_MODEL_FROM_DATABASE=AAC-RAID (Catapult) pci:v00009005d00000284* ID_MODEL_FROM_DATABASE=AAC-RAID pci:v00009005d00000284sv00009005sd00000284* ID_MODEL_FROM_DATABASE=AAC-RAID (Tomcat) pci:v00009005d00000285* ID_MODEL_FROM_DATABASE=AAC-RAID pci:v00009005d00000285sv00000E11sd00000295* ID_MODEL_FROM_DATABASE=AAC-RAID (SATA 6Ch (Bearcat)) pci:v00009005d00000285sv00001014sd000002F2* ID_MODEL_FROM_DATABASE=AAC-RAID (ServeRAID 8i) pci:v00009005d00000285sv00001028sd00000287* ID_MODEL_FROM_DATABASE=AAC-RAID (PowerEdge Expandable RAID Controller 320/DC) pci:v00009005d00000285sv00001028sd00000291* ID_MODEL_FROM_DATABASE=AAC-RAID (CERC SATA RAID 2 PCI SATA 6ch (DellCorsair)) pci:v00009005d00000285sv0000103Csd00003227* ID_MODEL_FROM_DATABASE=AAC-RAID (AAR-2610SA) pci:v00009005d00000285sv0000108Esd00000286* ID_MODEL_FROM_DATABASE=AAC-RAID (Sun StorageTek SAS RAID HBA, Internal) pci:v00009005d00000285sv0000108Esd00000287* ID_MODEL_FROM_DATABASE=AAC-RAID (STK RAID EXT) pci:v00009005d00000285sv0000108Esd00007AAC* ID_MODEL_FROM_DATABASE=AAC-RAID (STK RAID REM) pci:v00009005d00000285sv0000108Esd00007AAE* ID_MODEL_FROM_DATABASE=AAC-RAID (STK RAID EX) pci:v00009005d00000285sv000015D9sd000002B5* ID_MODEL_FROM_DATABASE=AAC-RAID (SMC AOC-USAS-S4i) pci:v00009005d00000285sv000015D9sd000002B6* ID_MODEL_FROM_DATABASE=AAC-RAID (SMC AOC-USAS-S8i) pci:v00009005d00000285sv000015D9sd000002C9* ID_MODEL_FROM_DATABASE=AAC-RAID (SMC AOC-USAS-S4iR) pci:v00009005d00000285sv000015D9sd000002CA* ID_MODEL_FROM_DATABASE=AAC-RAID (SMC AOC-USAS-S8iR) pci:v00009005d00000285sv000015D9sd000002D2* ID_MODEL_FROM_DATABASE=AAC-RAID (SMC AOC-USAS-S8i-LP) pci:v00009005d00000285sv000015D9sd000002D3* ID_MODEL_FROM_DATABASE=AAC-RAID (SMC AOC-USAS-S8iR-LP) pci:v00009005d00000285sv000017AAsd00000286* ID_MODEL_FROM_DATABASE=AAC-RAID (Legend S220 (Legend Crusader)) pci:v00009005d00000285sv000017AAsd00000287* ID_MODEL_FROM_DATABASE=AAC-RAID (Legend S230 (Legend Vulcan)) pci:v00009005d00000285sv00009005sd00000285* ID_MODEL_FROM_DATABASE=AAC-RAID (2200S (Vulcan)) pci:v00009005d00000285sv00009005sd00000286* ID_MODEL_FROM_DATABASE=AAC-RAID (2120S (Crusader)) pci:v00009005d00000285sv00009005sd00000287* ID_MODEL_FROM_DATABASE=AAC-RAID (2200S (Vulcan-2m)) pci:v00009005d00000285sv00009005sd00000288* ID_MODEL_FROM_DATABASE=AAC-RAID (3230S (Harrier)) pci:v00009005d00000285sv00009005sd00000289* ID_MODEL_FROM_DATABASE=AAC-RAID (3240S (Tornado)) pci:v00009005d00000285sv00009005sd0000028A* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2020ZCR) pci:v00009005d00000285sv00009005sd0000028B* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2025ZCR (Terminator)) pci:v00009005d00000285sv00009005sd0000028E* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2020SA (Skyhawk)) pci:v00009005d00000285sv00009005sd0000028F* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2025SA) pci:v00009005d00000285sv00009005sd00000290* ID_MODEL_FROM_DATABASE=AAC-RAID (AAR-2410SA PCI SATA 4ch (Jaguar II)) pci:v00009005d00000285sv00009005sd00000292* ID_MODEL_FROM_DATABASE=AAC-RAID (AAR-2810SA PCI SATA 8ch (Corsair-8)) pci:v00009005d00000285sv00009005sd00000293* ID_MODEL_FROM_DATABASE=AAC-RAID (AAR-21610SA PCI SATA 16ch (Corsair-16)) pci:v00009005d00000285sv00009005sd00000294* ID_MODEL_FROM_DATABASE=AAC-RAID (ESD SO-DIMM PCI-X SATA ZCR (Prowler)) pci:v00009005d00000285sv00009005sd00000296* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2240S) pci:v00009005d00000285sv00009005sd00000297* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-4005SAS) pci:v00009005d00000285sv00009005sd00000298* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-4000) pci:v00009005d00000285sv00009005sd00000299* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-4800SAS) pci:v00009005d00000285sv00009005sd0000029A* ID_MODEL_FROM_DATABASE=AAC-RAID (4805SAS) pci:v00009005d00000285sv00009005sd000002A4* ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP9085LI) pci:v00009005d00000285sv00009005sd000002A5* ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5085BR) pci:v00009005d00000285sv00009005sd000002B5* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR5800) pci:v00009005d00000285sv00009005sd000002B6* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR5805) pci:v00009005d00000285sv00009005sd000002B7* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR5808) pci:v00009005d00000285sv00009005sd000002B8* ID_MODEL_FROM_DATABASE=AAC-RAID (ICP5445SL) pci:v00009005d00000285sv00009005sd000002B9* ID_MODEL_FROM_DATABASE=AAC-RAID (ICP5085SL) pci:v00009005d00000285sv00009005sd000002BA* ID_MODEL_FROM_DATABASE=AAC-RAID (ICP5805SL) pci:v00009005d00000285sv00009005sd000002BB* ID_MODEL_FROM_DATABASE=AAC-RAID (3405) pci:v00009005d00000285sv00009005sd000002BC* ID_MODEL_FROM_DATABASE=AAC-RAID (3805) pci:v00009005d00000285sv00009005sd000002BD* ID_MODEL_FROM_DATABASE=AAC-RAID (31205) pci:v00009005d00000285sv00009005sd000002BE* ID_MODEL_FROM_DATABASE=AAC-RAID (31605) pci:v00009005d00000285sv00009005sd000002BF* ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5045BL) pci:v00009005d00000285sv00009005sd000002C0* ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5085BL) pci:v00009005d00000285sv00009005sd000002C1* ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5125BR) pci:v00009005d00000285sv00009005sd000002C2* ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5165BR) pci:v00009005d00000285sv00009005sd000002C3* ID_MODEL_FROM_DATABASE=AAC-RAID (51205) pci:v00009005d00000285sv00009005sd000002C4* ID_MODEL_FROM_DATABASE=AAC-RAID (51605) pci:v00009005d00000285sv00009005sd000002C5* ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5125SL) pci:v00009005d00000285sv00009005sd000002C6* ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5165SL) pci:v00009005d00000285sv00009005sd000002C7* ID_MODEL_FROM_DATABASE=AAC-RAID (3085) pci:v00009005d00000285sv00009005sd000002C8* ID_MODEL_FROM_DATABASE=AAC-RAID (ICP5805BL) pci:v00009005d00000285sv00009005sd000002CE* ID_MODEL_FROM_DATABASE=AAC-RAID (51245) pci:v00009005d00000285sv00009005sd000002CF* ID_MODEL_FROM_DATABASE=AAC-RAID (51645) pci:v00009005d00000285sv00009005sd000002D0* ID_MODEL_FROM_DATABASE=AAC-RAID (52445) pci:v00009005d00000285sv00009005sd000002D1* ID_MODEL_FROM_DATABASE=AAC-RAID (5405) pci:v00009005d00000285sv00009005sd000002D4* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2045) pci:v00009005d00000285sv00009005sd000002D5* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2405) pci:v00009005d00000285sv00009005sd000002D6* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2445) pci:v00009005d00000285sv00009005sd000002D7* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2805) pci:v00009005d00000285sv00009005sd000002D8* ID_MODEL_FROM_DATABASE=AAC-RAID (5405G) pci:v00009005d00000285sv00009005sd000002D9* ID_MODEL_FROM_DATABASE=AAC-RAID (5445G) pci:v00009005d00000285sv00009005sd000002DA* ID_MODEL_FROM_DATABASE=AAC-RAID (5805G) pci:v00009005d00000285sv00009005sd000002DB* ID_MODEL_FROM_DATABASE=AAC-RAID (5085G) pci:v00009005d00000285sv00009005sd000002DC* ID_MODEL_FROM_DATABASE=AAC-RAID (51245G) pci:v00009005d00000285sv00009005sd000002DD* ID_MODEL_FROM_DATABASE=AAC-RAID (51645G) pci:v00009005d00000285sv00009005sd000002DE* ID_MODEL_FROM_DATABASE=AAC-RAID (52445G) pci:v00009005d00000285sv00009005sd000002DF* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2045G) pci:v00009005d00000285sv00009005sd000002E0* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2405G) pci:v00009005d00000285sv00009005sd000002E1* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2445G) pci:v00009005d00000285sv00009005sd000002E2* ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2805G) pci:v00009005d00000286* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) pci:v00009005d00000286sv00001014sd0000034D* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (8s) pci:v00009005d00000286sv00001014sd00009540* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ServeRAID 8k/8k-l4) pci:v00009005d00000286sv00001014sd00009580* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ServeRAID 8k/8k-l8) pci:v00009005d00000286sv00009005sd0000028C* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ASR-2230S + ASR-2230SLP PCI-X (Lancer)) pci:v00009005d00000286sv00009005sd0000028D* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ASR-2130S) pci:v00009005d00000286sv00009005sd0000029B* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ASR-2820SA) pci:v00009005d00000286sv00009005sd0000029C* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ASR-2620SA) pci:v00009005d00000286sv00009005sd0000029D* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ASR-2420SA) pci:v00009005d00000286sv00009005sd0000029E* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP9024R0) pci:v00009005d00000286sv00009005sd0000029F* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP9014R0) pci:v00009005d00000286sv00009005sd000002A0* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP9047MA) pci:v00009005d00000286sv00009005sd000002A1* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP9087MA) pci:v00009005d00000286sv00009005sd000002A2* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (3800) pci:v00009005d00000286sv00009005sd000002A3* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP5445AU) pci:v00009005d00000286sv00009005sd000002A4* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP9085LI) pci:v00009005d00000286sv00009005sd000002A5* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP5085BR) pci:v00009005d00000286sv00009005sd000002A6* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP9067MA) pci:v00009005d00000286sv00009005sd000002A7* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (3805) pci:v00009005d00000286sv00009005sd000002A8* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (3400) pci:v00009005d00000286sv00009005sd000002A9* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP5085AU) pci:v00009005d00000286sv00009005sd000002AA* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP5045AU) pci:v00009005d00000286sv00009005sd000002AC* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (1800) pci:v00009005d00000286sv00009005sd000002B3* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (2400) pci:v00009005d00000286sv00009005sd000002B4* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP5045AL) pci:v00009005d00000286sv00009005sd00000800* ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (Callisto) pci:v00009005d0000028B* ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 pci:v00009005d0000028Bsv00009005sd00000200* ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 Entry Level - ASR-6405E - 4 internal 6G SAS ports) pci:v00009005d0000028Bsv00009005sd00000201* ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 Entry Level - ASR-6805E - 8 internal 6G SAS ports) pci:v00009005d0000028Bsv00009005sd00000300* ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 - ASR-6405 - 4 internal 6G SAS ports) pci:v00009005d0000028Bsv00009005sd00000301* ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 - ASR-6805 - 8 internal 6G SAS ports) pci:v00009005d0000028Bsv00009005sd00000302* ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 - ASR-6445 - 4 internal and 4 external 6G SAS ports) pci:v00009005d0000028Bsv00009005sd00000310* ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 Connectors on Top - ASR-6405T - 4 internal 6G SAS ports) pci:v00009005d0000028Bsv00009005sd00000311* ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 Connectors on Top - ASR-6805T - 8 internal 6G SAS) pci:v00009005d0000028Bsv00009005sd00000400* ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 - ASR-61205 - 12 internal 6G SAS ports) pci:v00009005d0000028Bsv00009005sd00000401* ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 - ASR-61605 - 16 internal 6G SAS ports) pci:v00009005d0000028Bsv00009005sd00000403* ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 - ASR-62405 - 24 internal 6G SAS ports) pci:v00009005d0000028C* ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 pci:v00009005d0000028Csv00009005sd00000500* ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 - ASR-7805 - 8 internal 6G SAS Port/PCIe 3.0) pci:v00009005d0000028Csv00009005sd00000501* ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 - ASR-71605 - 16 internal 6G SAS Port/PCIe 3.0) pci:v00009005d0000028Csv00009005sd00000502* ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 - ASR-71685 - 16 internal 8 external 6G SAS Port/PCIe 3.0) pci:v00009005d0000028Csv00009005sd00000503* ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 - ASR-72405 - 24 internal 0 external 6G SAS Port/PCIe 3.0) pci:v00009005d0000028Csv00009005sd00000504* ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 - ASR-7885 - 8 internal 8 external 6G SAS Port/PCIe 3.0) pci:v00009005d0000028Csv00009005sd00000505* ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 Entry Level - ASR-71685E - 16 internal 8 external 6G SAS Port/PCIe 3.0) pci:v00009005d0000028Csv00009005sd00000506* ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 Entry Level - ASR-72405E - 24 internal 0 external 6G SAS Port/PCIe 3.0) pci:v00009005d0000028D* ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 pci:v00009005d0000028Dsv00009005sd00000550* ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 (Series 8 - ASR-82405 - 24 internal 0 external 12G SAS Port/PCIe 3.0) pci:v00009005d0000028Dsv00009005sd00000551* ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 (Series 8 - ASR-81605 - 16 internal 0 external 12G SAS Port/PCIe 3.0) pci:v00009005d0000028Dsv00009005sd00000552* ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 (Series 8 - ASR-8805 - 8 internal 0 external 12G SAS Port/PCIe 3.0) pci:v00009005d0000028Dsv00009005sd00000553* ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 (Series 8 - ASR-8085 - 0 internal 8 external 12G SAS Port/PCIe 3.0) pci:v00009005d0000028Dsv00009005sd00000554* ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 (Series 8 - ASR-8885 - 8 internal 8 external 12G SAS Port/PCIe 3.0) pci:v00009005d00000410* ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA RAID) pci:v00009005d00000410sv00009005sd00000410* ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA RAID) (ASC-48300(Spirit RAID)) pci:v00009005d00000410sv00009005sd00000411* ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA RAID) (ASC-58300 (Oakmont RAID)) pci:v00009005d00000412* ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA non-RAID) pci:v00009005d00000412sv00009005sd00000412* ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA non-RAID) (ASC-48300 (Spirit non-RAID)) pci:v00009005d00000412sv00009005sd00000413* ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA non-RAID) (ASC-58300 (Oakmont non-RAID)) pci:v00009005d00000415* ID_MODEL_FROM_DATABASE=ASC-58300 SAS (Razor-External HBA RAID) pci:v00009005d00000416* ID_MODEL_FROM_DATABASE=ASC-58300 SAS (Razor-External HBA non-RAID) pci:v00009005d0000041E* ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor ASIC non-RAID) pci:v00009005d0000041F* ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor ASIC RAID) pci:v00009005d0000041Fsv00009005sd0000041F* ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor ASIC RAID) pci:v00009005d0000042F* ID_MODEL_FROM_DATABASE=VSC7250/7251 SAS (Aurora ASIC non-RAID) pci:v00009005d00000430* ID_MODEL_FROM_DATABASE=AIC-9405W SAS (Razor-Lite HBA RAID) pci:v00009005d00000430sv00009005sd00000430* ID_MODEL_FROM_DATABASE=AIC-9405W SAS (Razor-Lite HBA RAID) (ASC-44300 (Spirit-Lite RAID)) pci:v00009005d00000432* ID_MODEL_FROM_DATABASE=AIC-9405W SAS (Razor-Lite HBA non-RAID) pci:v00009005d00000432sv00009005sd00000432* ID_MODEL_FROM_DATABASE=AIC-9405W SAS (Razor-Lite HBA non-RAID) (ASC-44300 (Spirit-Lite non-RAID)) pci:v00009005d0000043E* ID_MODEL_FROM_DATABASE=AIC-9405W SAS (Razor-Lite ASIC non-RAID) pci:v00009005d0000043F* ID_MODEL_FROM_DATABASE=AIC-9405W SAS (Razor-Lite ASIC RAID) pci:v00009005d00000450* ID_MODEL_FROM_DATABASE=ASC-1405 Unified Serial HBA pci:v00009005d00000500* ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller pci:v00009005d00000500sv00001014sd000002C1* ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller (PCI-X DDR 3Gb SAS Adapter (572A/572C)) pci:v00009005d00000500sv00001014sd000002C2* ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller (PCI-X DDR 3Gb SAS RAID Adapter (572B/572D)) pci:v00009005d00000503* ID_MODEL_FROM_DATABASE=Scamp chipset SCSI controller pci:v00009005d00000503sv00001014sd000002BF* ID_MODEL_FROM_DATABASE=Scamp chipset SCSI controller (Quad Channel PCI-X DDR U320 SCSI RAID Adapter (571E)) pci:v00009005d00000503sv00001014sd000002C3* ID_MODEL_FROM_DATABASE=Scamp chipset SCSI controller (PCI-X DDR 3Gb SAS RAID Adapter (572F)) pci:v00009005d00000503sv00001014sd000002D5* ID_MODEL_FROM_DATABASE=Scamp chipset SCSI controller (Quad Channel PCI-X DDR U320 SCSI RAID Adapter (571F)) pci:v00009005d00000910* ID_MODEL_FROM_DATABASE=AUA-3100B pci:v00009005d0000091E* ID_MODEL_FROM_DATABASE=AUA-3100B pci:v00009005d00008000* ID_MODEL_FROM_DATABASE=ASC-29320A U320 pci:v00009005d0000800F* ID_MODEL_FROM_DATABASE=AIC-7901 U320 pci:v00009005d00008010* ID_MODEL_FROM_DATABASE=ASC-39320 U320 pci:v00009005d00008011* ID_MODEL_FROM_DATABASE=ASC-39320D pci:v00009005d00008011sv00000E11sd000000AC* ID_MODEL_FROM_DATABASE=ASC-39320D (U320) pci:v00009005d00008011sv00009005sd00000041* ID_MODEL_FROM_DATABASE=ASC-39320D (U320) pci:v00009005d00008012* ID_MODEL_FROM_DATABASE=ASC-29320 U320 pci:v00009005d00008013* ID_MODEL_FROM_DATABASE=ASC-29320B U320 pci:v00009005d00008014* ID_MODEL_FROM_DATABASE=ASC-29320LP U320 pci:v00009005d00008015* ID_MODEL_FROM_DATABASE=ASC-39320B U320 pci:v00009005d00008016* ID_MODEL_FROM_DATABASE=ASC-39320A U320 pci:v00009005d00008017* ID_MODEL_FROM_DATABASE=ASC-29320ALP U320 pci:v00009005d00008017sv00009005sd00000044* ID_MODEL_FROM_DATABASE=ASC-29320ALP U320 (ASC-29320ALP PCIx U320) pci:v00009005d00008017sv00009005sd00000045* ID_MODEL_FROM_DATABASE=ASC-29320ALP U320 (ASC-29320LPE PCIe U320) pci:v00009005d0000801C* ID_MODEL_FROM_DATABASE=ASC-39320D U320 pci:v00009005d0000801D* ID_MODEL_FROM_DATABASE=AIC-7902B U320 pci:v00009005d0000801Dsv00001014sd000002CC* ID_MODEL_FROM_DATABASE=AIC-7902B U320 (ServeRAID 7e) pci:v00009005d0000801E* ID_MODEL_FROM_DATABASE=AIC-7901A U320 pci:v00009005d0000801F* ID_MODEL_FROM_DATABASE=AIC-7902 U320 pci:v00009005d0000801Fsv00001734sd00001011* ID_MODEL_FROM_DATABASE=AIC-7902 U320 (PRIMERGY RX300 onboard SCSI) pci:v00009005d00008080* ID_MODEL_FROM_DATABASE=ASC-29320A U320 w/HostRAID pci:v00009005d00008081* ID_MODEL_FROM_DATABASE=PMC-Sierra PM8001 SAS HBA [Series 6H] pci:v00009005d00008088* ID_MODEL_FROM_DATABASE=PMC-Sierra PM8018 SAS HBA [Series 7H] pci:v00009005d00008089* ID_MODEL_FROM_DATABASE=PMC-Sierra PM8019 SAS encryption HBA [Series 7He] pci:v00009005d0000808F* ID_MODEL_FROM_DATABASE=AIC-7901 U320 w/HostRAID pci:v00009005d0000808Fsv00001028sd00000168* ID_MODEL_FROM_DATABASE=AIC-7901 U320 w/HostRAID (Precision Workstation 670 Mainboard) pci:v00009005d00008090* ID_MODEL_FROM_DATABASE=ASC-39320 U320 w/HostRAID pci:v00009005d00008091* ID_MODEL_FROM_DATABASE=ASC-39320D U320 w/HostRAID pci:v00009005d00008092* ID_MODEL_FROM_DATABASE=ASC-29320 U320 w/HostRAID pci:v00009005d00008093* ID_MODEL_FROM_DATABASE=ASC-29320B U320 w/HostRAID pci:v00009005d00008094* ID_MODEL_FROM_DATABASE=ASC-29320LP U320 w/HostRAID pci:v00009005d00008095* ID_MODEL_FROM_DATABASE=ASC-39320(B) U320 w/HostRAID pci:v00009005d00008096* ID_MODEL_FROM_DATABASE=ASC-39320A U320 w/HostRAID pci:v00009005d00008097* ID_MODEL_FROM_DATABASE=ASC-29320ALP U320 w/HostRAID pci:v00009005d0000809C* ID_MODEL_FROM_DATABASE=ASC-39320D(B) U320 w/HostRAID pci:v00009005d0000809D* ID_MODEL_FROM_DATABASE=AIC-7902(B) U320 w/HostRAID pci:v00009005d0000809Dsv00001014sd000002CC* ID_MODEL_FROM_DATABASE=AIC-7902(B) U320 w/HostRAID (ServeRAID 7e) pci:v00009005d0000809E* ID_MODEL_FROM_DATABASE=AIC-7901A U320 w/HostRAID pci:v00009005d0000809F* ID_MODEL_FROM_DATABASE=AIC-7902 U320 w/HostRAID pci:v0000907F* ID_VENDOR_FROM_DATABASE=Atronics pci:v0000907Fd00002015* ID_MODEL_FROM_DATABASE=IDE-2015PL pci:v0000919A* ID_VENDOR_FROM_DATABASE=Gigapixel Corp pci:v00009412* ID_VENDOR_FROM_DATABASE=Holtek pci:v00009412d00006565* ID_MODEL_FROM_DATABASE=6565 pci:v00009413* ID_VENDOR_FROM_DATABASE=Softlogic Co., Ltd. pci:v00009413d00006010* ID_MODEL_FROM_DATABASE=SOLO6010 MPEG-4 Video encoder/decoder pci:v00009413d00006110* ID_MODEL_FROM_DATABASE=SOLO6110 H.264 Video encoder/decoder pci:v00009618* ID_VENDOR_FROM_DATABASE=JusonTech Corporation pci:v00009618d00000001* ID_MODEL_FROM_DATABASE=JusonTech Gigabit Ethernet Controller pci:v00009699* ID_VENDOR_FROM_DATABASE=Omni Media Technology Inc pci:v00009699d00006565* ID_MODEL_FROM_DATABASE=6565 pci:v00009710* ID_VENDOR_FROM_DATABASE=MosChip Semiconductor Technology Ltd. pci:v00009710d00009250* ID_MODEL_FROM_DATABASE=PCI-to-PCI bridge [MCS9250] pci:v00009710d00009805* ID_MODEL_FROM_DATABASE=PCI 1 port parallel adapter pci:v00009710d00009815* ID_MODEL_FROM_DATABASE=PCI 9815 Multi-I/O Controller pci:v00009710d00009815sv00001000sd00000020* ID_MODEL_FROM_DATABASE=PCI 9815 Multi-I/O Controller (2P0S (2 port parallel adaptor)) pci:v00009710d00009820* ID_MODEL_FROM_DATABASE=PCI 9820 Multi-I/O Controller pci:v00009710d00009835* ID_MODEL_FROM_DATABASE=PCI 9835 Multi-I/O Controller pci:v00009710d00009835sv00001000sd00000002* ID_MODEL_FROM_DATABASE=PCI 9835 Multi-I/O Controller (2S (16C550 UART)) pci:v00009710d00009835sv00001000sd00000012* ID_MODEL_FROM_DATABASE=PCI 9835 Multi-I/O Controller (1P2S) pci:v00009710d00009845* ID_MODEL_FROM_DATABASE=PCI 9845 Multi-I/O Controller pci:v00009710d00009845sv00001000sd00000004* ID_MODEL_FROM_DATABASE=PCI 9845 Multi-I/O Controller (0P4S (4 port 16550A serial card)) pci:v00009710d00009845sv00001000sd00000006* ID_MODEL_FROM_DATABASE=PCI 9845 Multi-I/O Controller (0P6S (6 port 16550a serial card)) pci:v00009710d00009845sv00001000sd00000014* ID_MODEL_FROM_DATABASE=PCI 9845 Multi-I/O Controller (1P4S (1 Parallel / 4 16550A Serial Port Adapter)) pci:v00009710d00009855* ID_MODEL_FROM_DATABASE=PCI 9855 Multi-I/O Controller pci:v00009710d00009855sv00001000sd00000014* ID_MODEL_FROM_DATABASE=PCI 9855 Multi-I/O Controller (1P4S) pci:v00009710d00009855sv00001000sd00000022* ID_MODEL_FROM_DATABASE=PCI 9855 Multi-I/O Controller (2P2S (2 Parallel / 2 16550A Serial Port Adapter)) pci:v00009710d00009865* ID_MODEL_FROM_DATABASE=PCI 9865 Multi-I/O Controller pci:v00009710d00009901* ID_MODEL_FROM_DATABASE=PCIe 9901 Multi-I/O Controller pci:v00009710d00009904* ID_MODEL_FROM_DATABASE=4-Port PCIe Serial Adapter pci:v00009710d00009912* ID_MODEL_FROM_DATABASE=PCIe 9912 Multi-I/O Controller pci:v00009710d00009922* ID_MODEL_FROM_DATABASE=MCS9922 PCIe Multi-I/O Controller pci:v00009710d00009990* ID_MODEL_FROM_DATABASE=MCS9990 PCIe to 4‐Port USB 2.0 Host Controller pci:v00009850* ID_VENDOR_FROM_DATABASE=3Com (wrong ID) pci:v00009902* ID_VENDOR_FROM_DATABASE=Stargen Inc. pci:v00009902d00000001* ID_MODEL_FROM_DATABASE=SG2010 PCI over Starfabric Bridge pci:v00009902d00000002* ID_MODEL_FROM_DATABASE=SG2010 PCI to Starfabric Gateway pci:v00009902d00000003* ID_MODEL_FROM_DATABASE=SG1010 Starfabric Switch and PCI Bridge pci:v0000A0A0* ID_VENDOR_FROM_DATABASE=AOPEN Inc. pci:v0000A0F1* ID_VENDOR_FROM_DATABASE=UNISYS Corporation pci:v0000A200* ID_VENDOR_FROM_DATABASE=NEC Corporation pci:v0000A259* ID_VENDOR_FROM_DATABASE=Hewlett Packard pci:v0000A25B* ID_VENDOR_FROM_DATABASE=Hewlett Packard GmbH PL24-MKT pci:v0000A304* ID_VENDOR_FROM_DATABASE=Sony pci:v0000A727* ID_VENDOR_FROM_DATABASE=3Com Corporation pci:v0000A727d00000013* ID_MODEL_FROM_DATABASE=3CRPAG175 Wireless PC Card pci:v0000A727d00006803* ID_MODEL_FROM_DATABASE=3CRDAG675B Wireless 11a/b/g Adapter pci:v0000AA00* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA01* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA02* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA03* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA04* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA05* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA06* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA07* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA08* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA09* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA0A* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA0B* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA0C* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA0D* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA0E* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA0F* ID_VENDOR_FROM_DATABASE=iTuner pci:v0000AA42* ID_VENDOR_FROM_DATABASE=Scitex Digital Video pci:v0000AA55* ID_VENDOR_FROM_DATABASE=Ncomputing X300 PCI-Engine pci:v0000AAAA* ID_VENDOR_FROM_DATABASE=Adnaco Technology Inc. pci:v0000AAAAd00000001* ID_MODEL_FROM_DATABASE=H1 PCIe over fiber optic host controller pci:v0000AAAAd00000002* ID_MODEL_FROM_DATABASE=R1BP1 PCIe over fiber optic expansion chassis pci:v0000ABCD* ID_VENDOR_FROM_DATABASE=Vadatech Inc. pci:v0000AC1E* ID_VENDOR_FROM_DATABASE=Digital Receiver Technology Inc pci:v0000AC3D* ID_VENDOR_FROM_DATABASE=Actuality Systems pci:v0000AD00* ID_VENDOR_FROM_DATABASE=Alta Data Technologies LLC pci:v0000AECB* ID_VENDOR_FROM_DATABASE=Adrienne Electronics Corporation pci:v0000AECBd00006250* ID_MODEL_FROM_DATABASE=VITC/LTC Timecode Reader card [PCI-VLTC/RDR] pci:v0000AFFE* ID_VENDOR_FROM_DATABASE=Sirrix AG security technologies pci:v0000AFFEd000001E1* ID_MODEL_FROM_DATABASE=PCI1E1 1-port ISDN E1 interface pci:v0000AFFEd000002E1* ID_MODEL_FROM_DATABASE=PCI2E1 2-port ISDN E1 interface pci:v0000AFFEd0000450E* ID_MODEL_FROM_DATABASE=PCI4S0EC 4-port ISDN S0 interface pci:v0000AFFEd0000DEAD* ID_MODEL_FROM_DATABASE=Sirrix.PCI4S0 4-port ISDN S0 interface pci:v0000B100* ID_VENDOR_FROM_DATABASE=OpenVox Communication Co. Ltd. pci:v0000B10B* ID_VENDOR_FROM_DATABASE=Uakron PCI Project pci:v0000B1B3* ID_VENDOR_FROM_DATABASE=Shiva Europe Limited pci:v0000B1D9* ID_VENDOR_FROM_DATABASE=ATCOM Technology co., LTD. pci:v0000BD11* ID_VENDOR_FROM_DATABASE=Pinnacle Systems, Inc. (Wrong ID) pci:v0000BDBD* ID_VENDOR_FROM_DATABASE=Blackmagic Design pci:v0000BDBDd0000A106* ID_MODEL_FROM_DATABASE=Multibridge Extreme pci:v0000BDBDd0000A117* ID_MODEL_FROM_DATABASE=Intensity Pro pci:v0000BDBDd0000A11A* ID_MODEL_FROM_DATABASE=DeckLink HD Extreme 2 pci:v0000BDBDd0000A11B* ID_MODEL_FROM_DATABASE=DeckLink SDI/Duo/Quad pci:v0000BDBDd0000A11C* ID_MODEL_FROM_DATABASE=DeckLink HD Extreme 3 pci:v0000BDBDd0000A11D* ID_MODEL_FROM_DATABASE=DeckLink Studio pci:v0000BDBDd0000A11E* ID_MODEL_FROM_DATABASE=DeckLink Optical Fibre pci:v0000BDBDd0000A120* ID_MODEL_FROM_DATABASE=Decklink Studio 2 pci:v0000BDBDd0000A121* ID_MODEL_FROM_DATABASE=DeckLink HD Extreme 3D/3D+ pci:v0000BDBDd0000A124* ID_MODEL_FROM_DATABASE=Intensity Extreme pci:v0000BDBDd0000A126* ID_MODEL_FROM_DATABASE=Intensity Shuttle pci:v0000BDBDd0000A127* ID_MODEL_FROM_DATABASE=UltraStudio Express pci:v0000BDBDd0000A129* ID_MODEL_FROM_DATABASE=UltraStudio Mini Monitor pci:v0000BDBDd0000A12A* ID_MODEL_FROM_DATABASE=UltraStudio Mini Recorder pci:v0000BDBDd0000A12D* ID_MODEL_FROM_DATABASE=UltraStudio 4K pci:v0000BDBDd0000A12E* ID_MODEL_FROM_DATABASE=DeckLink 4K Extreme pci:v0000BDBDd0000A12F* ID_MODEL_FROM_DATABASE=DeckLink Mini Monitor pci:v0000BDBDd0000A130* ID_MODEL_FROM_DATABASE=DeckLink Mini Recorder pci:v0000BDBDd0000A132* ID_MODEL_FROM_DATABASE=UltraStudio 4K pci:v0000BDBDd0000A136* ID_MODEL_FROM_DATABASE=DeckLink 4K Extreme 12G pci:v0000BDBDd0000A137* ID_MODEL_FROM_DATABASE=DeckLink Studio 4K pci:v0000BDBDd0000A138* ID_MODEL_FROM_DATABASE=Decklink SDI 4K pci:v0000BDBDd0000A139* ID_MODEL_FROM_DATABASE=Intensity Pro 4K pci:v0000C001* ID_VENDOR_FROM_DATABASE=TSI Telsys pci:v0000C0A9* ID_VENDOR_FROM_DATABASE=Micron/Crucial Technology pci:v0000C0DE* ID_VENDOR_FROM_DATABASE=Motorola pci:v0000C0FE* ID_VENDOR_FROM_DATABASE=Motion Engineering, Inc. pci:v0000CA50* ID_VENDOR_FROM_DATABASE=Varian Australia Pty Ltd pci:v0000CACE* ID_VENDOR_FROM_DATABASE=CACE Technologies, Inc. pci:v0000CACEd00000001* ID_MODEL_FROM_DATABASE=TurboCap Port A pci:v0000CACEd00000002* ID_MODEL_FROM_DATABASE=TurboCap Port B pci:v0000CACEd00000023* ID_MODEL_FROM_DATABASE=AirPcap N pci:v0000CAED* ID_VENDOR_FROM_DATABASE=Canny Edge pci:v0000CAFE* ID_VENDOR_FROM_DATABASE=Chrysalis-ITS pci:v0000CAFEd00000003* ID_MODEL_FROM_DATABASE=Luna K3 Hardware Security Module pci:v0000CAFEd00000006* ID_MODEL_FROM_DATABASE=Luna PCI-e 3000 Hardware Security Module pci:v0000CCCC* ID_VENDOR_FROM_DATABASE=Catapult Communications pci:v0000CCEC* ID_VENDOR_FROM_DATABASE=Curtiss-Wright Controls Embedded Computing pci:v0000CDDD* ID_VENDOR_FROM_DATABASE=Tyzx, Inc. pci:v0000CDDDd00000101* ID_MODEL_FROM_DATABASE=DeepSea 1 High Speed Stereo Vision Frame Grabber pci:v0000CDDDd00000200* ID_MODEL_FROM_DATABASE=DeepSea 2 High Speed Stereo Vision Frame Grabber pci:v0000CEBA* ID_VENDOR_FROM_DATABASE=KEBA AG pci:v0000D161* ID_VENDOR_FROM_DATABASE=Digium, Inc. pci:v0000D161d00000120* ID_MODEL_FROM_DATABASE=Wildcard TE120P single-span T1/E1/J1 card pci:v0000D161d00000205* ID_MODEL_FROM_DATABASE=Wildcard TE205P/TE207P dual-span T1/E1/J1 card 5.0V pci:v0000D161d00000210* ID_MODEL_FROM_DATABASE=Wildcard TE210P/TE212P dual-span T1/E1/J1 card 3.3V pci:v0000D161d00000220* ID_MODEL_FROM_DATABASE=Wildcard TE220 dual-span T1/E1/J1 card 3.3V (PCI-Express) pci:v0000D161d00000405* ID_MODEL_FROM_DATABASE=Wildcard TE405P/TE407P quad-span T1/E1/J1 card 5.0V pci:v0000D161d00000410* ID_MODEL_FROM_DATABASE=Wildcard TE410P/TE412P quad-span T1/E1/J1 card 3.3V pci:v0000D161d00000420* ID_MODEL_FROM_DATABASE=Wildcard TE420P quad-span T1/E1/J1 card 3.3V (PCI-Express) pci:v0000D161d00000800* ID_MODEL_FROM_DATABASE=Wildcard TDM800P 8-port analog card pci:v0000D161d00001205* ID_MODEL_FROM_DATABASE=Wildcard TE205P/TE207P dual-span T1/E1/J1 card 5.0V (u1) pci:v0000D161d00001220* ID_MODEL_FROM_DATABASE=Wildcard TE220 dual-span T1/E1/J1 card 3.3V (PCI-Express) (5th gen) pci:v0000D161d00001405* ID_MODEL_FROM_DATABASE=Wildcard TE405P/TE407P quad-span T1/E1/J1 card 5.0V (u1) pci:v0000D161d00001410* ID_MODEL_FROM_DATABASE=Wildcard TE410P quad-span T1/E1/J1 card 3.3V (5th Gen) pci:v0000D161d00001420* ID_MODEL_FROM_DATABASE=Wildcard TE420 quad-span T1/E1/J1 card 3.3V (PCI-Express) (5th gen) pci:v0000D161d00001820* ID_MODEL_FROM_DATABASE=Wildcard TE820 octal-span T1/E1/J1 card 3.3V (PCI-Express) pci:v0000D161d00002400* ID_MODEL_FROM_DATABASE=Wildcard TDM2400P 24-port analog card pci:v0000D161d00003400* ID_MODEL_FROM_DATABASE=Wildcard TC400P transcoder base card pci:v0000D161d00008000* ID_MODEL_FROM_DATABASE=Wildcard TE121 single-span T1/E1/J1 card (PCI-Express) pci:v0000D161d00008001* ID_MODEL_FROM_DATABASE=Wildcard TE122 single-span T1/E1/J1 card pci:v0000D161d00008002* ID_MODEL_FROM_DATABASE=Wildcard AEX800 8-port analog card (PCI-Express) pci:v0000D161d00008003* ID_MODEL_FROM_DATABASE=Wildcard AEX2400 24-port analog card (PCI-Express) pci:v0000D161d00008004* ID_MODEL_FROM_DATABASE=Wildcard TCE400P transcoder base card pci:v0000D161d00008005* ID_MODEL_FROM_DATABASE=Wildcard TDM410 4-port analog card pci:v0000D161d00008006* ID_MODEL_FROM_DATABASE=Wildcard AEX410 4-port analog card (PCI-Express) pci:v0000D161d00008007* ID_MODEL_FROM_DATABASE=Hx8 Series 8-port Base Card pci:v0000D161d00008008* ID_MODEL_FROM_DATABASE=Hx8 Series 8-port Base Card (PCI-Express) pci:v0000D161d0000800A* ID_MODEL_FROM_DATABASE=Wildcard TE133 single-span T1/E1/J1 card (PCI Express) pci:v0000D161d0000800B* ID_MODEL_FROM_DATABASE=Wildcard TE134 single-span T1/E1/J1 card pci:v0000D161d0000800C* ID_MODEL_FROM_DATABASE=Wildcard A8A 8-port analog card pci:v0000D161d0000800D* ID_MODEL_FROM_DATABASE=Wildcard A8B 8-port analog card (PCI-Express) pci:v0000D161d0000800E* ID_MODEL_FROM_DATABASE=Wildcard TE235/TE435 quad-span T1/E1/J1 card (PCI-Express) pci:v0000D161d0000800F* ID_MODEL_FROM_DATABASE=Wildcard A4A 4-port analog card pci:v0000D161d00008010* ID_MODEL_FROM_DATABASE=Wildcard A4B 4-port analog card (PCI-Express) pci:v0000D161d00008013* ID_MODEL_FROM_DATABASE=Wildcard TE236/TE436 quad-span T1/E1/J1 card pci:v0000D161d0000B410* ID_MODEL_FROM_DATABASE=Wildcard B410 quad-BRI card pci:v0000D4D4* ID_VENDOR_FROM_DATABASE=Dy4 Systems Inc pci:v0000D4D4d00000601* ID_MODEL_FROM_DATABASE=PCI Mezzanine Card pci:v0000D531* ID_VENDOR_FROM_DATABASE=I+ME ACTIA GmbH pci:v0000D84D* ID_VENDOR_FROM_DATABASE=Exsys pci:v0000DADA* ID_VENDOR_FROM_DATABASE=Datapath Limited pci:v0000DADAd00000133* ID_MODEL_FROM_DATABASE=VisionRGB-X2 pci:v0000DADAd00000139* ID_MODEL_FROM_DATABASE=VisionRGB-E1 pci:v0000DADAd00000144* ID_MODEL_FROM_DATABASE=VisionSD8 pci:v0000DADAd00000150* ID_MODEL_FROM_DATABASE=VisionRGB-E2 pci:v0000DADAd00000151* ID_MODEL_FROM_DATABASE=VisionSD4+1 pci:v0000DADAd00000159* ID_MODEL_FROM_DATABASE=VisionAV pci:v0000DADAd00000161* ID_MODEL_FROM_DATABASE=DGC161 pci:v0000DADAd00000165* ID_MODEL_FROM_DATABASE=DGC165 pci:v0000DADAd00000167* ID_MODEL_FROM_DATABASE=DGC167 pci:v0000DADAd00000168* ID_MODEL_FROM_DATABASE=DGC168 pci:v0000DADAd00001139* ID_MODEL_FROM_DATABASE=VisionRGB-E1S pci:v0000DADAd00001150* ID_MODEL_FROM_DATABASE=VisionRGB-E2S pci:v0000DADAd00001151* ID_MODEL_FROM_DATABASE=VisionSD4+1S pci:v0000DADAd00001153* ID_MODEL_FROM_DATABASE=VisionDVI-DL pci:v0000DADAd00001154* ID_MODEL_FROM_DATABASE=VisionSDI2 pci:v0000DB10* ID_VENDOR_FROM_DATABASE=Diablo Technologies pci:v0000DC93* ID_VENDOR_FROM_DATABASE=Dawicontrol GmbH pci:v0000DCBA* ID_VENDOR_FROM_DATABASE=Dynamic Engineering pci:v0000DCBAd00000046* ID_MODEL_FROM_DATABASE=PCIe Altera Cyclone IV pci:v0000DCBAd00000047* ID_MODEL_FROM_DATABASE=VPX-RCB pci:v0000DCBAd00000048* ID_MODEL_FROM_DATABASE=PMC-Biserial-III-BAE9 pci:v0000DCBAd0000004E* ID_MODEL_FROM_DATABASE=PC104p-Biserial-III-NVY5 pci:v0000DCBAd0000004F* ID_MODEL_FROM_DATABASE=PC104p-Biserial-III-NVY6 pci:v0000DCBAd00000052* ID_MODEL_FROM_DATABASE=PCIeBiSerialDb37 BA22 LVDS IO pci:v0000DD01* ID_VENDOR_FROM_DATABASE=Digital Devices GmbH pci:v0000DD01d00000003* ID_MODEL_FROM_DATABASE=Octopus DVB Adapter pci:v0000DD01d00000003sv0000DD01sd00000001* ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Octopus DVB adapter) pci:v0000DD01d00000003sv0000DD01sd00000002* ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Octopus LE DVB adapter) pci:v0000DD01d00000003sv0000DD01sd00000003* ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Octopus OEM) pci:v0000DD01d00000003sv0000DD01sd00000004* ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Octopus V3 DVB adapter) pci:v0000DD01d00000003sv0000DD01sd00000010* ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Octopus Mini) pci:v0000DD01d00000003sv0000DD01sd00000020* ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Cine S2 V6 DVB adapter) pci:v0000DD01d00000003sv0000DD01sd00000021* ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Cine S2 V6.5 DVB adapter) pci:v0000DD01d00000003sv0000DD01sd00000030* ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Cine CT V6.1 DVB adapter) pci:v0000DD01d00000003sv0000DD01sd0000DB03* ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Mystique SaTiX-S2 V3 DVB adapter) pci:v0000DD01d00000006* ID_MODEL_FROM_DATABASE=Cine V7 pci:v0000DD01d00000007* ID_MODEL_FROM_DATABASE=Max pci:v0000DD01d00000007sv0000DD01sd00000023* ID_MODEL_FROM_DATABASE=Max (S8 4/8) pci:v0000DD01d00000011* ID_MODEL_FROM_DATABASE=Octopus CI DVB Adapter pci:v0000DD01d00000011sv0000DD01sd00000040* ID_MODEL_FROM_DATABASE=Octopus CI DVB Adapter (Octopus CI) pci:v0000DD01d00000011sv0000DD01sd00000041* ID_MODEL_FROM_DATABASE=Octopus CI DVB Adapter (Octopus CI Single) pci:v0000DD01d00000201* ID_MODEL_FROM_DATABASE=Resi DVB-C Modulator pci:v0000DD01d00000201sv0000DD01sd00000001* ID_MODEL_FROM_DATABASE=Resi DVB-C Modulator pci:v0000DEAD* ID_VENDOR_FROM_DATABASE=Indigita Corporation pci:v0000DEAF* ID_VENDOR_FROM_DATABASE=Middle Digital Inc. pci:v0000DEAFd00009050* ID_MODEL_FROM_DATABASE=PC Weasel Virtual VGA pci:v0000DEAFd00009051* ID_MODEL_FROM_DATABASE=PC Weasel Serial Port pci:v0000DEAFd00009052* ID_MODEL_FROM_DATABASE=PC Weasel Watchdog Timer pci:v0000DEDA* ID_VENDOR_FROM_DATABASE=XIMEA pci:v0000DEDAd00004001* ID_MODEL_FROM_DATABASE=Camera CB pci:v0000DEDAd00004021* ID_MODEL_FROM_DATABASE=Camera MT pci:v0000E000* ID_VENDOR_FROM_DATABASE=Winbond pci:v0000E000d0000E000* ID_MODEL_FROM_DATABASE=W89C940 pci:v0000E159* ID_VENDOR_FROM_DATABASE=Tiger Jet Network Inc. pci:v0000E159d00000001* ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface pci:v0000E159d00000001sv00000059sd00000001* ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface (128k ISDN-S/T Adapter) pci:v0000E159d00000001sv00000059sd00000003* ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface (128k ISDN-U Adapter) pci:v0000E159d00000001sv000000A7sd00000001* ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface (TELES.S0/PCI 2.x ISDN Adapter) pci:v0000E159d00000001sv00008086sd00000003* ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface (Digium X100P/X101P analogue PSTN FXO interface) pci:v0000E159d00000001sv0000B100sd00000003* ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface (OpenVox A400P 4-port analog card) pci:v0000E159d00000001sv0000B1D9sd00000003* ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface (AX400P 4-port analog card) pci:v0000E159d00000002* ID_MODEL_FROM_DATABASE=Tiger100APC ISDN chipset pci:v0000E1C5* ID_VENDOR_FROM_DATABASE=Elcus pci:v0000E4BF* ID_VENDOR_FROM_DATABASE=EKF Elektronik GmbH pci:v0000E4BFd00000CCD* ID_MODEL_FROM_DATABASE=CCD-CALYPSO pci:v0000E4BFd00000CD1* ID_MODEL_FROM_DATABASE=CD1-OPERA pci:v0000E4BFd00000CD2* ID_MODEL_FROM_DATABASE=CD2-BEBOP pci:v0000E4BFd00000CD3* ID_MODEL_FROM_DATABASE=CD3-JIVE pci:v0000E4BFd000050C1* ID_MODEL_FROM_DATABASE=PC1-GROOVE pci:v0000E4BFd000050C2* ID_MODEL_FROM_DATABASE=PC2-LIMBO pci:v0000E4BFd000053C1* ID_MODEL_FROM_DATABASE=SC1-ALLEGRO pci:v0000E4BFd0000CC47* ID_MODEL_FROM_DATABASE=CCG-RUMBA pci:v0000E4BFd0000CC4D* ID_MODEL_FROM_DATABASE=CCM-BOOGIE pci:v0000E4E4* ID_VENDOR_FROM_DATABASE=Xorcom pci:v0000E55E* ID_VENDOR_FROM_DATABASE=Essence Technology, Inc. pci:v0000EA01* ID_VENDOR_FROM_DATABASE=Eagle Technology pci:v0000EA01d0000000A* ID_MODEL_FROM_DATABASE=PCI-773 Temperature Card pci:v0000EA01d00000032* ID_MODEL_FROM_DATABASE=PCI-730 & PC104P-30 Card pci:v0000EA01d0000003E* ID_MODEL_FROM_DATABASE=PCI-762 Opto-Isolator Card pci:v0000EA01d00000041* ID_MODEL_FROM_DATABASE=PCI-763 Reed Relay Card pci:v0000EA01d00000043* ID_MODEL_FROM_DATABASE=PCI-769 Opto-Isolator Reed Relay Combo Card pci:v0000EA01d00000046* ID_MODEL_FROM_DATABASE=PCI-766 Analog Output Card pci:v0000EA01d00000052* ID_MODEL_FROM_DATABASE=PCI-703 Analog I/O Card pci:v0000EA01d00000800* ID_MODEL_FROM_DATABASE=PCI-800 Digital I/O Card pci:v0000EA60* ID_VENDOR_FROM_DATABASE=RME pci:v0000EA60d00009896* ID_MODEL_FROM_DATABASE=Digi32 pci:v0000EA60d00009897* ID_MODEL_FROM_DATABASE=Digi32 Pro pci:v0000EA60d00009898* ID_MODEL_FROM_DATABASE=Digi32/8 pci:v0000EABB* ID_VENDOR_FROM_DATABASE=Aashima Technology B.V. pci:v0000EACE* ID_VENDOR_FROM_DATABASE=Endace Measurement Systems, Ltd pci:v0000EACEd00003100* ID_MODEL_FROM_DATABASE=DAG 3.10 OC-3/OC-12 pci:v0000EACEd00003200* ID_MODEL_FROM_DATABASE=DAG 3.2x OC-3/OC-12 pci:v0000EACEd0000320E* ID_MODEL_FROM_DATABASE=DAG 3.2E Fast Ethernet pci:v0000EACEd0000340E* ID_MODEL_FROM_DATABASE=DAG 3.4E Fast Ethernet pci:v0000EACEd0000341E* ID_MODEL_FROM_DATABASE=DAG 3.41E Fast Ethernet pci:v0000EACEd00003500* ID_MODEL_FROM_DATABASE=DAG 3.5 OC-3/OC-12 pci:v0000EACEd0000351C* ID_MODEL_FROM_DATABASE=DAG 3.5ECM Fast Ethernet pci:v0000EACEd0000360D* ID_MODEL_FROM_DATABASE=DAG 3.6D DS3 pci:v0000EACEd0000360E* ID_MODEL_FROM_DATABASE=DAG 3.6E Fast Ethernet pci:v0000EACEd0000368E* ID_MODEL_FROM_DATABASE=DAG 3.6E Gig Ethernet pci:v0000EACEd00003707* ID_MODEL_FROM_DATABASE=DAG 3.7T T1/E1/J1 pci:v0000EACEd0000370D* ID_MODEL_FROM_DATABASE=DAG 3.7D DS3/E3 pci:v0000EACEd0000378E* ID_MODEL_FROM_DATABASE=DAG 3.7G Gig Ethernet pci:v0000EACEd00003800* ID_MODEL_FROM_DATABASE=DAG 3.8S OC-3/OC-12 pci:v0000EACEd00004100* ID_MODEL_FROM_DATABASE=DAG 4.10 OC-48 pci:v0000EACEd00004110* ID_MODEL_FROM_DATABASE=DAG 4.11 OC-48 pci:v0000EACEd00004220* ID_MODEL_FROM_DATABASE=DAG 4.2 OC-48 pci:v0000EACEd0000422E* ID_MODEL_FROM_DATABASE=DAG 4.2GE Gig Ethernet pci:v0000EACEd00004230* ID_MODEL_FROM_DATABASE=DAG 4.2S OC-48 pci:v0000EACEd0000423E* ID_MODEL_FROM_DATABASE=DAG 4.2GE Gig Ethernet pci:v0000EACEd00004300* ID_MODEL_FROM_DATABASE=DAG 4.3S OC-48 pci:v0000EACEd0000430E* ID_MODEL_FROM_DATABASE=DAG 4.3GE Gig Ethernet pci:v0000EACEd0000452E* ID_MODEL_FROM_DATABASE=DAG 4.5G2 Gig Ethernet pci:v0000EACEd0000454E* ID_MODEL_FROM_DATABASE=DAG 4.5G4 Gig Ethernet pci:v0000EACEd000045B8* ID_MODEL_FROM_DATABASE=DAG 4.5Z8 Gig Ethernet pci:v0000EACEd000045BE* ID_MODEL_FROM_DATABASE=DAG 4.5Z2 Gig Ethernet pci:v0000EACEd0000520E* ID_MODEL_FROM_DATABASE=DAG 5.2X 10G Ethernet pci:v0000EACEd0000521A* ID_MODEL_FROM_DATABASE=DAG 5.2SXA 10G Ethernet/OC-192 pci:v0000EACEd00005400* ID_MODEL_FROM_DATABASE=DAG 5.4S-12 OC-3/OC-12 pci:v0000EACEd00005401* ID_MODEL_FROM_DATABASE=DAG 5.4SG-48 Gig Ethernet/OC-3/OC-12/OC-48 pci:v0000EACEd0000540A* ID_MODEL_FROM_DATABASE=DAG 5.4GA Gig Ethernet pci:v0000EACEd0000541A* ID_MODEL_FROM_DATABASE=DAG 5.4SA-12 OC-3/OC-12 pci:v0000EACEd0000542A* ID_MODEL_FROM_DATABASE=DAG 5.4SGA-48 Gig Ethernet/OC-3/OC-12/OC-48 pci:v0000EACEd00006000* ID_MODEL_FROM_DATABASE=DAG 6.0SE 10G Ethernet/OC-192 pci:v0000EACEd00006100* ID_MODEL_FROM_DATABASE=DAG 6.1SE 10G Ethernet/OC-192 pci:v0000EACEd00006200* ID_MODEL_FROM_DATABASE=DAG 6.2SE 10G Ethernet/OC-192 pci:v0000EACEd00007100* ID_MODEL_FROM_DATABASE=DAG 7.1S OC-3/OC-12 pci:v0000EACEd00007400* ID_MODEL_FROM_DATABASE=DAG 7.4S OC-3/OC-12 pci:v0000EACEd00007401* ID_MODEL_FROM_DATABASE=DAG 7.4S48 OC-48 pci:v0000EACEd0000752E* ID_MODEL_FROM_DATABASE=DAG 7.5G2 Gig Ethernet pci:v0000EACEd0000754E* ID_MODEL_FROM_DATABASE=DAG 7.5G4 Gig Ethernet pci:v0000EACEd00008100* ID_MODEL_FROM_DATABASE=DAG 8.1X 10G Ethernet pci:v0000EACEd00008101* ID_MODEL_FROM_DATABASE=DAG 8.1SX 10G Ethernet/OC-192 pci:v0000EACEd00008102* ID_MODEL_FROM_DATABASE=DAG 8.1X 10G Ethernet pci:v0000EACEd0000820E* ID_MODEL_FROM_DATABASE=DAG 8.2X 10G Ethernet pci:v0000EACEd0000820F* ID_MODEL_FROM_DATABASE=DAG 8.2X 10G Ethernet (2nd bus) pci:v0000EACEd00008400* ID_MODEL_FROM_DATABASE=DAG 8.4I Infiniband x4 SDR pci:v0000EACEd00008500* ID_MODEL_FROM_DATABASE=DAG 8.5I Infiniband x4 DDR pci:v0000EACEd00009200* ID_MODEL_FROM_DATABASE=DAG 9.2SX2 10G Ethernet pci:v0000EACEd0000920E* ID_MODEL_FROM_DATABASE=DAG 9.2X2 10G Ethernet pci:v0000EACEd0000A120* ID_MODEL_FROM_DATABASE=DAG 10X2-P 10G Ethernet pci:v0000EACEd0000A12E* ID_MODEL_FROM_DATABASE=DAG 10X2-S 10G Ethernet pci:v0000EACEd0000A140* ID_MODEL_FROM_DATABASE=DAG 10X4-P 10G Ethernet pci:v0000EC80* ID_VENDOR_FROM_DATABASE=Belkin Corporation pci:v0000EC80d0000EC00* ID_MODEL_FROM_DATABASE=F5D6000 pci:v0000ECC0* ID_VENDOR_FROM_DATABASE=Echo Digital Audio Corporation pci:v0000EDD8* ID_VENDOR_FROM_DATABASE=ARK Logic Inc pci:v0000EDD8d0000A091* ID_MODEL_FROM_DATABASE=1000PV [Stingray] pci:v0000EDD8d0000A099* ID_MODEL_FROM_DATABASE=2000PV [Stingray] pci:v0000EDD8d0000A0A1* ID_MODEL_FROM_DATABASE=2000MT pci:v0000EDD8d0000A0A9* ID_MODEL_FROM_DATABASE=2000MI pci:v0000F043* ID_VENDOR_FROM_DATABASE=ASUSTeK Computer Inc. (Wrong ID) pci:v0000F05B* ID_VENDOR_FROM_DATABASE=Foxconn International, Inc. (Wrong ID) pci:v0000F1D0* ID_VENDOR_FROM_DATABASE=AJA Video pci:v0000F1D0d0000C0FE* ID_MODEL_FROM_DATABASE=Xena HS/HD-R pci:v0000F1D0d0000C0FF* ID_MODEL_FROM_DATABASE=Kona/Xena 2 pci:v0000F1D0d0000CAFE* ID_MODEL_FROM_DATABASE=Kona SD pci:v0000F1D0d0000CFEE* ID_MODEL_FROM_DATABASE=Xena LS/SD-22-DA/SD-DA pci:v0000F1D0d0000DAFF* ID_MODEL_FROM_DATABASE=KONA LHi pci:v0000F1D0d0000DCAF* ID_MODEL_FROM_DATABASE=Kona HD pci:v0000F1D0d0000DFEE* ID_MODEL_FROM_DATABASE=Xena HD-DA pci:v0000F1D0d0000EFAC* ID_MODEL_FROM_DATABASE=Xena SD-MM/SD-22-MM pci:v0000F1D0d0000FACD* ID_MODEL_FROM_DATABASE=Xena HD-MM pci:v0000F5F5* ID_VENDOR_FROM_DATABASE=F5 Networks, Inc. pci:v0000F849* ID_VENDOR_FROM_DATABASE=ASRock Incorporation (Wrong ID) pci:v0000FA57* ID_VENDOR_FROM_DATABASE=Interagon AS pci:v0000FA57d00000001* ID_MODEL_FROM_DATABASE=PMC [Pattern Matching Chip] pci:v0000FAB7* ID_VENDOR_FROM_DATABASE=Fabric7 Systems, Inc. pci:v0000FEBD* ID_VENDOR_FROM_DATABASE=Ultraview Corp. pci:v0000FEDA* ID_VENDOR_FROM_DATABASE=Broadcom Inc pci:v0000FEDAd0000A0FA* ID_MODEL_FROM_DATABASE=BCM4210 iLine10 HomePNA 2.0 pci:v0000FEDAd0000A10E* ID_MODEL_FROM_DATABASE=BCM4230 iLine10 HomePNA 2.0 pci:v0000FEDE* ID_VENDOR_FROM_DATABASE=Fedetec Inc. pci:v0000FEDEd00000003* ID_MODEL_FROM_DATABASE=TABIC PCI v3 pci:v0000FFFD* ID_VENDOR_FROM_DATABASE=XenSource, Inc. pci:v0000FFFDd00000101* ID_MODEL_FROM_DATABASE=PCI Event Channel Controller pci:v0000FFFE* ID_VENDOR_FROM_DATABASE=VMWare Inc (temporary ID) pci:v0000FFFEd00000710* ID_MODEL_FROM_DATABASE=Virtual SVGA pci:v0000FFFF* ID_VENDOR_FROM_DATABASE=Illegal Vendor ID systemd-229/hwdb/20-sdio-classes.hwdb000066400000000000000000000014171265713322000174660ustar00rootroot00000000000000# This file is part of systemd. # # Data imported from: hwdb/sdio.ids sdio:c00v*d* ID_SDIO_CLASS_FROM_DATABASE=Not a SDIO standard interface sdio:c01v*d* ID_SDIO_CLASS_FROM_DATABASE=UART standard interface sdio:c02v*d* ID_SDIO_CLASS_FROM_DATABASE=Bluetooth Type-A standard interface sdio:c03v*d* ID_SDIO_CLASS_FROM_DATABASE=Bluetooth Type-B standard interface sdio:c04v*d* ID_SDIO_CLASS_FROM_DATABASE=GPS standard interface sdio:c05v*d* ID_SDIO_CLASS_FROM_DATABASE=Camera standard interface sdio:c06v*d* ID_SDIO_CLASS_FROM_DATABASE=PHS standard interface sdio:c07v*d* ID_SDIO_CLASS_FROM_DATABASE=WLAN interface sdio:c08v*d* ID_SDIO_CLASS_FROM_DATABASE=Embedded SDIO-ATA standard interface sdio:c09v*d* ID_SDIO_CLASS_FROM_DATABASE=Bluetooth AMP standard interface systemd-229/hwdb/20-sdio-vendor-model.hwdb000066400000000000000000000077431265713322000204340ustar00rootroot00000000000000# This file is part of systemd. # # Data imported from: hwdb/sdio.ids sdio:c*v0020* ID_VENDOR_FROM_DATABASE=ST-Ericsson sdio:c*v0020d2280* ID_MODEL_FROM_DATABASE=CW1200 sdio:c*v0089* ID_VENDOR_FROM_DATABASE=Intel Corp. sdio:c*v0092* ID_VENDOR_FROM_DATABASE=C-guys, Inc. sdio:c*v0092d0001* ID_MODEL_FROM_DATABASE=SD-Link11b WiFi Card (TI ACX100) sdio:c*v0092d0004* ID_MODEL_FROM_DATABASE=EW-CG1102GC sdio:c*v0092d0005* ID_MODEL_FROM_DATABASE=SD FM Radio 2 sdio:c*v0092d5544* ID_MODEL_FROM_DATABASE=SD FM Radio sdio:c*v0097* ID_VENDOR_FROM_DATABASE=Texas Instruments, Inc. sdio:c*v0097d4076* ID_MODEL_FROM_DATABASE=WL1271 sdio:c*v0098* ID_VENDOR_FROM_DATABASE=Toshiba Corp. sdio:c*v0098d0001* ID_MODEL_FROM_DATABASE=SD BT Card 1 sdio:c*v0098d0002* ID_MODEL_FROM_DATABASE=SD BT Card 2 sdio:c*v0098d0003* ID_MODEL_FROM_DATABASE=SD BT Card 3 sdio:c*v0104* ID_VENDOR_FROM_DATABASE=Socket Communications, Inc. sdio:c*v0104d005E* ID_MODEL_FROM_DATABASE=SD Scanner sdio:c*v0104d00C5* ID_MODEL_FROM_DATABASE=Bluetooth SDIO Card sdio:c*v0271* ID_VENDOR_FROM_DATABASE=Atheros Communications, Inc. sdio:c*v0271d0108* ID_MODEL_FROM_DATABASE=AR6001 sdio:c*v0271d0109* ID_MODEL_FROM_DATABASE=AR6001 sdio:c*v0271d010A* ID_MODEL_FROM_DATABASE=AR6001 sdio:c*v0271d010B* ID_MODEL_FROM_DATABASE=AR6001 sdio:c*v0296* ID_VENDOR_FROM_DATABASE=GCT Semiconductor, Inc. sdio:c*v0296d5347* ID_MODEL_FROM_DATABASE=GDM72xx WiMAX sdio:c*v02D0* ID_VENDOR_FROM_DATABASE=Broadcom Corp. sdio:c*v02D0d044B* ID_MODEL_FROM_DATABASE=Nintendo Wii WLAN daughter card sdio:c*v02D0dA887* ID_MODEL_FROM_DATABASE=BCM43143 WLAN card sdio:c*v02D0d4324* ID_MODEL_FROM_DATABASE=BCM43241 WLAN card sdio:c*v02D0d4329* ID_MODEL_FROM_DATABASE=BCM4329 WLAN card sdio:c*v02D0d4330* ID_MODEL_FROM_DATABASE=BCM4330 WLAN card sdio:c*v02D0d4334* ID_MODEL_FROM_DATABASE=BCM4334 WLAN card sdio:c*v02D0dA94C* ID_MODEL_FROM_DATABASE=BCM43340 WLAN card sdio:c*v02D0dA94D* ID_MODEL_FROM_DATABASE=BCM43341 WLAN card sdio:c*v02D0d4335* ID_MODEL_FROM_DATABASE=BCM4335/BCM4339 WLAN card sdio:c*v02D0dA962* ID_MODEL_FROM_DATABASE=BCM43362 WLAN card sdio:c*v02D0d4354* ID_MODEL_FROM_DATABASE=BCM4354 WLAN card sdio:c*v02DB* ID_VENDOR_FROM_DATABASE=SyChip Inc. sdio:c*v02DBd0002* ID_MODEL_FROM_DATABASE=Pegasus WLAN SDIO Card (6060SD) sdio:c*v02DF* ID_VENDOR_FROM_DATABASE=Marvell Technology Group Ltd. sdio:c*v02DFd9103* ID_MODEL_FROM_DATABASE=Libertas sdio:c*v02DFd9104* ID_MODEL_FROM_DATABASE=SD8688 WLAN sdio:c*v02DFd9105* ID_MODEL_FROM_DATABASE=SD8688 BT sdio:c*v02DFd9116* ID_MODEL_FROM_DATABASE=SD8786 WLAN sdio:c*v02DFd9119* ID_MODEL_FROM_DATABASE=SD8787 WLAN sdio:c*v02DFd911A* ID_MODEL_FROM_DATABASE=SD8787 BT sdio:c*v02DFd911B* ID_MODEL_FROM_DATABASE=SD8787 BT AMP sdio:c*v02DFd9129* ID_MODEL_FROM_DATABASE=SD8797 WLAN sdio:c*v02DFd912A* ID_MODEL_FROM_DATABASE=SD8797 BT sdio:c*v02DFd912E* ID_MODEL_FROM_DATABASE=SD8897 BT sdio:c*v02DFd912D* ID_MODEL_FROM_DATABASE=SD8897 WLAN sdio:c*v02FE* ID_VENDOR_FROM_DATABASE=Spectec Computer Co., Ltd sdio:c*v02FEd2128* ID_MODEL_FROM_DATABASE=SDIO WLAN Card (SDW820) sdio:c*v032A* ID_VENDOR_FROM_DATABASE=Cambridge Silicon Radio sdio:c*v032Ad0001* ID_MODEL_FROM_DATABASE=UniFi 1 sdio:c*v032Ad0002* ID_MODEL_FROM_DATABASE=UniFi 2 sdio:c*v032Ad0007* ID_MODEL_FROM_DATABASE=UniFi 3 sdio:c*v032Ad0008* ID_MODEL_FROM_DATABASE=UniFi 4 sdio:c*v037A* ID_VENDOR_FROM_DATABASE=MediaTek Inc. sdio:c*v037Ad5911* ID_MODEL_FROM_DATABASE=Spectec WLAN-11b/g sdio:c*v039A* ID_VENDOR_FROM_DATABASE=Siano Mobile Silicon sdio:c*v0501* ID_VENDOR_FROM_DATABASE=Globalsat Technology Co. sdio:c*v0501dF501* ID_MODEL_FROM_DATABASE=SD-501 GPS Card sdio:c*v104C* ID_VENDOR_FROM_DATABASE=Texas Instruments, Inc. sdio:c*v104Cd9066* ID_MODEL_FROM_DATABASE=WL1251 sdio:c*v1180* ID_VENDOR_FROM_DATABASE=Ricoh Co., Ltd sdio:c*v1180dE823* ID_MODEL_FROM_DATABASE=MMC card reader sdio:c*v13D1* ID_VENDOR_FROM_DATABASE=AboCom Systems, Inc. sdio:c*v13D1dAC02* ID_MODEL_FROM_DATABASE=SDW11G systemd-229/hwdb/20-usb-classes.hwdb000066400000000000000000000176061265713322000173300ustar00rootroot00000000000000# This file is part of systemd. # # Data imported from: http://www.linux-usb.org/usb.ids usb:v*p*d*dc01* ID_USB_CLASS_FROM_DATABASE=Audio usb:v*p*d*dc01dsc01* ID_USB_SUBCLASS_FROM_DATABASE=Control Device usb:v*p*d*dc01dsc02* ID_USB_SUBCLASS_FROM_DATABASE=Streaming usb:v*p*d*dc01dsc03* ID_USB_SUBCLASS_FROM_DATABASE=MIDI Streaming usb:v*p*d*dc02* ID_USB_CLASS_FROM_DATABASE=Communications usb:v*p*d*dc02dsc01* ID_USB_SUBCLASS_FROM_DATABASE=Direct Line usb:v*p*d*dc02dsc02* ID_USB_SUBCLASS_FROM_DATABASE=Abstract (modem) usb:v*p*d*dc02dsc02dp01* ID_USB_PROTOCOL_FROM_DATABASE=AT-commands (v.25ter) usb:v*p*d*dc02dsc02dp02* ID_USB_PROTOCOL_FROM_DATABASE=AT-commands (PCCA101) usb:v*p*d*dc02dsc02dp03* ID_USB_PROTOCOL_FROM_DATABASE=AT-commands (PCCA101 + wakeup) usb:v*p*d*dc02dsc02dp04* ID_USB_PROTOCOL_FROM_DATABASE=AT-commands (GSM) usb:v*p*d*dc02dsc02dp05* ID_USB_PROTOCOL_FROM_DATABASE=AT-commands (3G) usb:v*p*d*dc02dsc02dp06* ID_USB_PROTOCOL_FROM_DATABASE=AT-commands (CDMA) usb:v*p*d*dc02dsc02dpFE* ID_USB_PROTOCOL_FROM_DATABASE=Defined by command set descriptor usb:v*p*d*dc02dsc02dpFF* ID_USB_PROTOCOL_FROM_DATABASE=Vendor Specific (MSFT RNDIS?) usb:v*p*d*dc02dsc03* ID_USB_SUBCLASS_FROM_DATABASE=Telephone usb:v*p*d*dc02dsc04* ID_USB_SUBCLASS_FROM_DATABASE=Multi-Channel usb:v*p*d*dc02dsc05* ID_USB_SUBCLASS_FROM_DATABASE=CAPI Control usb:v*p*d*dc02dsc06* ID_USB_SUBCLASS_FROM_DATABASE=Ethernet Networking usb:v*p*d*dc02dsc07* ID_USB_SUBCLASS_FROM_DATABASE=ATM Networking usb:v*p*d*dc02dsc08* ID_USB_SUBCLASS_FROM_DATABASE=Wireless Handset Control usb:v*p*d*dc02dsc09* ID_USB_SUBCLASS_FROM_DATABASE=Device Management usb:v*p*d*dc02dsc0A* ID_USB_SUBCLASS_FROM_DATABASE=Mobile Direct Line usb:v*p*d*dc02dsc0B* ID_USB_SUBCLASS_FROM_DATABASE=OBEX usb:v*p*d*dc02dsc0C* ID_USB_SUBCLASS_FROM_DATABASE=Ethernet Emulation usb:v*p*d*dc02dsc0Cdp07* ID_USB_PROTOCOL_FROM_DATABASE=Ethernet Emulation (EEM) usb:v*p*d*dc03* ID_USB_CLASS_FROM_DATABASE=Human Interface Device usb:v*p*d*dc03dsc00dp01* ID_USB_PROTOCOL_FROM_DATABASE=Keyboard usb:v*p*d*dc03dsc00dp02* ID_USB_PROTOCOL_FROM_DATABASE=Mouse usb:v*p*d*dc03dsc01* ID_USB_SUBCLASS_FROM_DATABASE=Boot Interface Subclass usb:v*p*d*dc03dsc01dp01* ID_USB_PROTOCOL_FROM_DATABASE=Keyboard usb:v*p*d*dc03dsc01dp02* ID_USB_PROTOCOL_FROM_DATABASE=Mouse usb:v*p*d*dc05* ID_USB_CLASS_FROM_DATABASE=Physical Interface Device usb:v*p*d*dc06* ID_USB_CLASS_FROM_DATABASE=Imaging usb:v*p*d*dc06dsc01* ID_USB_SUBCLASS_FROM_DATABASE=Still Image Capture usb:v*p*d*dc06dsc01dp01* ID_USB_PROTOCOL_FROM_DATABASE=Picture Transfer Protocol (PIMA 15470) usb:v*p*d*dc07* ID_USB_CLASS_FROM_DATABASE=Printer usb:v*p*d*dc07dsc01* ID_USB_SUBCLASS_FROM_DATABASE=Printer usb:v*p*d*dc07dsc01dp00* ID_USB_PROTOCOL_FROM_DATABASE=Reserved/Undefined usb:v*p*d*dc07dsc01dp01* ID_USB_PROTOCOL_FROM_DATABASE=Unidirectional usb:v*p*d*dc07dsc01dp02* ID_USB_PROTOCOL_FROM_DATABASE=Bidirectional usb:v*p*d*dc07dsc01dp03* ID_USB_PROTOCOL_FROM_DATABASE=IEEE 1284.4 compatible bidirectional usb:v*p*d*dc07dsc01dpFF* ID_USB_PROTOCOL_FROM_DATABASE=Vendor Specific usb:v*p*d*dc08* ID_USB_CLASS_FROM_DATABASE=Mass Storage usb:v*p*d*dc08dsc01* ID_USB_SUBCLASS_FROM_DATABASE=RBC (typically Flash) usb:v*p*d*dc08dsc01dp00* ID_USB_PROTOCOL_FROM_DATABASE=Control/Bulk/Interrupt usb:v*p*d*dc08dsc01dp01* ID_USB_PROTOCOL_FROM_DATABASE=Control/Bulk usb:v*p*d*dc08dsc01dp50* ID_USB_PROTOCOL_FROM_DATABASE=Bulk-Only usb:v*p*d*dc08dsc02* ID_USB_SUBCLASS_FROM_DATABASE=SFF-8020i, MMC-2 (ATAPI) usb:v*p*d*dc08dsc03* ID_USB_SUBCLASS_FROM_DATABASE=QIC-157 usb:v*p*d*dc08dsc04* ID_USB_SUBCLASS_FROM_DATABASE=Floppy (UFI) usb:v*p*d*dc08dsc04dp00* ID_USB_PROTOCOL_FROM_DATABASE=Control/Bulk/Interrupt usb:v*p*d*dc08dsc04dp01* ID_USB_PROTOCOL_FROM_DATABASE=Control/Bulk usb:v*p*d*dc08dsc04dp50* ID_USB_PROTOCOL_FROM_DATABASE=Bulk-Only usb:v*p*d*dc08dsc05* ID_USB_SUBCLASS_FROM_DATABASE=SFF-8070i usb:v*p*d*dc08dsc06* ID_USB_SUBCLASS_FROM_DATABASE=SCSI usb:v*p*d*dc08dsc06dp00* ID_USB_PROTOCOL_FROM_DATABASE=Control/Bulk/Interrupt usb:v*p*d*dc08dsc06dp01* ID_USB_PROTOCOL_FROM_DATABASE=Control/Bulk usb:v*p*d*dc08dsc06dp50* ID_USB_PROTOCOL_FROM_DATABASE=Bulk-Only usb:v*p*d*dc09* ID_USB_CLASS_FROM_DATABASE=Hub usb:v*p*d*dc09dsc00dp00* ID_USB_PROTOCOL_FROM_DATABASE=Full speed (or root) hub usb:v*p*d*dc09dsc00dp01* ID_USB_PROTOCOL_FROM_DATABASE=Single TT usb:v*p*d*dc09dsc00dp02* ID_USB_PROTOCOL_FROM_DATABASE=TT per port usb:v*p*d*dc0A* ID_USB_CLASS_FROM_DATABASE=CDC Data usb:v*p*d*dc0Adsc00dp30* ID_USB_PROTOCOL_FROM_DATABASE=I.430 ISDN BRI usb:v*p*d*dc0Adsc00dp31* ID_USB_PROTOCOL_FROM_DATABASE=HDLC usb:v*p*d*dc0Adsc00dp32* ID_USB_PROTOCOL_FROM_DATABASE=Transparent usb:v*p*d*dc0Adsc00dp50* ID_USB_PROTOCOL_FROM_DATABASE=Q.921M usb:v*p*d*dc0Adsc00dp51* ID_USB_PROTOCOL_FROM_DATABASE=Q.921 usb:v*p*d*dc0Adsc00dp52* ID_USB_PROTOCOL_FROM_DATABASE=Q.921TM usb:v*p*d*dc0Adsc00dp90* ID_USB_PROTOCOL_FROM_DATABASE=V.42bis usb:v*p*d*dc0Adsc00dp91* ID_USB_PROTOCOL_FROM_DATABASE=Q.932 EuroISDN usb:v*p*d*dc0Adsc00dp92* ID_USB_PROTOCOL_FROM_DATABASE=V.120 V.24 rate ISDN usb:v*p*d*dc0Adsc00dp93* ID_USB_PROTOCOL_FROM_DATABASE=CAPI 2.0 usb:v*p*d*dc0Adsc00dpFD* ID_USB_PROTOCOL_FROM_DATABASE=Host Based Driver usb:v*p*d*dc0Adsc00dpFE* ID_USB_PROTOCOL_FROM_DATABASE=CDC PUF usb:v*p*d*dc0Adsc00dpFF* ID_USB_PROTOCOL_FROM_DATABASE=Vendor specific usb:v*p*d*dc0B* ID_USB_CLASS_FROM_DATABASE=Chip/SmartCard usb:v*p*d*dc0D* ID_USB_CLASS_FROM_DATABASE=Content Security usb:v*p*d*dc0E* ID_USB_CLASS_FROM_DATABASE=Video usb:v*p*d*dc0Edsc01* ID_USB_SUBCLASS_FROM_DATABASE=Video Control usb:v*p*d*dc0Edsc02* ID_USB_SUBCLASS_FROM_DATABASE=Video Streaming usb:v*p*d*dc0Edsc03* ID_USB_SUBCLASS_FROM_DATABASE=Video Interface Collection usb:v*p*d*dc58* ID_USB_CLASS_FROM_DATABASE=Xbox usb:v*p*d*dc58dsc42* ID_USB_SUBCLASS_FROM_DATABASE=Controller usb:v*p*d*dcDC* ID_USB_CLASS_FROM_DATABASE=Diagnostic usb:v*p*d*dcDCdsc01* ID_USB_SUBCLASS_FROM_DATABASE=Reprogrammable Diagnostics usb:v*p*d*dcDCdsc01dp01* ID_USB_PROTOCOL_FROM_DATABASE=USB2 Compliance usb:v*p*d*dcE0* ID_USB_CLASS_FROM_DATABASE=Wireless usb:v*p*d*dcE0dsc01* ID_USB_SUBCLASS_FROM_DATABASE=Radio Frequency usb:v*p*d*dcE0dsc01dp01* ID_USB_PROTOCOL_FROM_DATABASE=Bluetooth usb:v*p*d*dcE0dsc01dp02* ID_USB_PROTOCOL_FROM_DATABASE=Ultra WideBand Radio Control usb:v*p*d*dcE0dsc01dp03* ID_USB_PROTOCOL_FROM_DATABASE=RNDIS usb:v*p*d*dcE0dsc02* ID_USB_SUBCLASS_FROM_DATABASE=Wireless USB Wire Adapter usb:v*p*d*dcE0dsc02dp01* ID_USB_PROTOCOL_FROM_DATABASE=Host Wire Adapter Control/Data Streaming usb:v*p*d*dcE0dsc02dp02* ID_USB_PROTOCOL_FROM_DATABASE=Device Wire Adapter Control/Data Streaming usb:v*p*d*dcE0dsc02dp03* ID_USB_PROTOCOL_FROM_DATABASE=Device Wire Adapter Isochronous Streaming usb:v*p*d*dcEF* ID_USB_CLASS_FROM_DATABASE=Miscellaneous Device usb:v*p*d*dcEFdsc01dp01* ID_USB_PROTOCOL_FROM_DATABASE=Microsoft ActiveSync usb:v*p*d*dcEFdsc01dp02* ID_USB_PROTOCOL_FROM_DATABASE=Palm Sync usb:v*p*d*dcEFdsc02dp01* ID_USB_PROTOCOL_FROM_DATABASE=Interface Association usb:v*p*d*dcEFdsc02dp02* ID_USB_PROTOCOL_FROM_DATABASE=Wire Adapter Multifunction Peripheral usb:v*p*d*dcEFdsc03dp01* ID_USB_PROTOCOL_FROM_DATABASE=Cable Based Association usb:v*p*d*dcEFdsc05* ID_USB_SUBCLASS_FROM_DATABASE=USB3 Vision usb:v*p*d*dcFE* ID_USB_CLASS_FROM_DATABASE=Application Specific Interface usb:v*p*d*dcFEdsc01* ID_USB_SUBCLASS_FROM_DATABASE=Device Firmware Update usb:v*p*d*dcFEdsc02* ID_USB_SUBCLASS_FROM_DATABASE=IRDA Bridge usb:v*p*d*dcFEdsc03* ID_USB_SUBCLASS_FROM_DATABASE=Test and Measurement usb:v*p*d*dcFEdsc03dp01* ID_USB_PROTOCOL_FROM_DATABASE=TMC usb:v*p*d*dcFEdsc03dp02* ID_USB_PROTOCOL_FROM_DATABASE=USB488 usb:v*p*d*dcFF* ID_USB_CLASS_FROM_DATABASE=Vendor Specific Class usb:v*p*d*dcFFdscFF* ID_USB_SUBCLASS_FROM_DATABASE=Vendor Specific Subclass usb:v*p*d*dcFFdscFFdpFF* ID_USB_PROTOCOL_FROM_DATABASE=Vendor Specific Protocol systemd-229/hwdb/20-usb-vendor-model.hwdb000066400000000000000000042576661265713322000203060ustar00rootroot00000000000000# This file is part of systemd. # # Data imported from: http://www.linux-usb.org/usb.ids usb:v0001* ID_VENDOR_FROM_DATABASE=Fry's Electronics usb:v0001p7778* ID_MODEL_FROM_DATABASE=Counterfeit flash drive [Kingston] usb:v0002* ID_VENDOR_FROM_DATABASE=Ingram usb:v0003* ID_VENDOR_FROM_DATABASE=Club Mac usb:v0004* ID_VENDOR_FROM_DATABASE=Nebraska Furniture Mart usb:v0011* ID_VENDOR_FROM_DATABASE=Unknown usb:v0011p7788* ID_MODEL_FROM_DATABASE=counterfeit flash drive usb:v0053* ID_VENDOR_FROM_DATABASE=Planex usb:v0053p5301* ID_MODEL_FROM_DATABASE=GW-US54ZGL 802.11bg usb:v0079* ID_VENDOR_FROM_DATABASE=DragonRise Inc. usb:v0079p0006* ID_MODEL_FROM_DATABASE=PC TWIN SHOCK Gamepad usb:v0079p0011* ID_MODEL_FROM_DATABASE=Gamepad usb:v0105* ID_VENDOR_FROM_DATABASE=Trust International B.V. usb:v0105p145F* ID_MODEL_FROM_DATABASE=NW-3100 802.11b/g 54Mbps Wireless Network Adapter [zd1211] usb:v0127* ID_VENDOR_FROM_DATABASE=IBP usb:v0127p0002* ID_MODEL_FROM_DATABASE=HDM Interface usb:v0145* ID_VENDOR_FROM_DATABASE=Unknown usb:v0145p0112* ID_MODEL_FROM_DATABASE=Card Reader usb:v017C* ID_VENDOR_FROM_DATABASE=MLK usb:v017Cp145F* ID_MODEL_FROM_DATABASE=Trust Deskset usb:v0200* ID_VENDOR_FROM_DATABASE=TP-Link usb:v0200p0201* ID_MODEL_FROM_DATABASE=MA180 UMTS Modem usb:v0204* ID_VENDOR_FROM_DATABASE=Chipsbank Microelectronics Co., Ltd usb:v0204p6025* ID_MODEL_FROM_DATABASE=CBM2080 / CBM2090 Flash drive controller usb:v0204p6026* ID_MODEL_FROM_DATABASE=CBM1180 Flash drive controller usb:v0218* ID_VENDOR_FROM_DATABASE=Hangzhou Worlde usb:v0218p0301* ID_MODEL_FROM_DATABASE=MIDI Port usb:v02AD* ID_VENDOR_FROM_DATABASE=HUMAX Co., Ltd. usb:v02ADp138C* ID_MODEL_FROM_DATABASE=PVR Mass Storage usb:v0300* ID_VENDOR_FROM_DATABASE=MM300 eBook Reader usb:v0324* ID_VENDOR_FROM_DATABASE=OCZ Technology Inc usb:v0324pBC06* ID_MODEL_FROM_DATABASE=OCZ ATV USB 2.0 Flash Drive usb:v0324pBC08* ID_MODEL_FROM_DATABASE=OCZ Rally2/ATV USB 2.0 Flash Drive usb:v0325* ID_VENDOR_FROM_DATABASE=OCZ Technology Inc usb:v0325pAC02* ID_MODEL_FROM_DATABASE=ATV Turbo / Rally2 Dual Channel USB 2.0 Flash Drive usb:v0386* ID_VENDOR_FROM_DATABASE=LTS usb:v0386p0001* ID_MODEL_FROM_DATABASE=PSX for USB Converter usb:v03D9* ID_VENDOR_FROM_DATABASE=Shenzhen Sinote Tech-Electron Co., Ltd usb:v03D9p0499* ID_MODEL_FROM_DATABASE=SE340D PC Remote Control usb:v03DA* ID_VENDOR_FROM_DATABASE=Bernd Walter Computer Technology usb:v03DAp0002* ID_MODEL_FROM_DATABASE=HD44780 LCD interface usb:v03E8* ID_VENDOR_FROM_DATABASE=EndPoints, Inc. usb:v03E8p0004* ID_MODEL_FROM_DATABASE=SE401 Webcam usb:v03E8p0008* ID_MODEL_FROM_DATABASE=101 Ethernet [klsi] usb:v03E8p0015* ID_MODEL_FROM_DATABASE=ATAPI Enclosure usb:v03E8p2123* ID_MODEL_FROM_DATABASE=SiPix StyleCam Deluxe usb:v03E8p8004* ID_MODEL_FROM_DATABASE=Aox 99001 usb:v03E9* ID_VENDOR_FROM_DATABASE=Thesys Microelectronics usb:v03EA* ID_VENDOR_FROM_DATABASE=Data Broadcasting Corp. usb:v03EB* ID_VENDOR_FROM_DATABASE=Atmel Corp. usb:v03EBp0902* ID_MODEL_FROM_DATABASE=4-Port Hub usb:v03EBp2002* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v03EBp2015* ID_MODEL_FROM_DATABASE=at90usbkey sample firmware (HID keyboard) usb:v03EBp2018* ID_MODEL_FROM_DATABASE=at90usbkey sample firmware (CDC ACM) usb:v03EBp2019* ID_MODEL_FROM_DATABASE=stk525 sample firmware (microphone) usb:v03EBp201C* ID_MODEL_FROM_DATABASE=at90usbkey sample firmware (HID mouse) usb:v03EBp201D* ID_MODEL_FROM_DATABASE=at90usbkey sample firmware (HID generic) usb:v03EBp2022* ID_MODEL_FROM_DATABASE=at90usbkey sample firmware (composite device) usb:v03EBp2040* ID_MODEL_FROM_DATABASE=LUFA Test PID usb:v03EBp2041* ID_MODEL_FROM_DATABASE=LUFA Mouse Demo Application usb:v03EBp2042* ID_MODEL_FROM_DATABASE=LUFA Keyboard Demo Application usb:v03EBp2043* ID_MODEL_FROM_DATABASE=LUFA Joystick Demo Application usb:v03EBp2044* ID_MODEL_FROM_DATABASE=LUFA CDC Demo Application usb:v03EBp2045* ID_MODEL_FROM_DATABASE=LUFA Mass Storage Demo Application usb:v03EBp2046* ID_MODEL_FROM_DATABASE=LUFA Audio Output Demo Application usb:v03EBp2047* ID_MODEL_FROM_DATABASE=LUFA Audio Input Demo Application usb:v03EBp2048* ID_MODEL_FROM_DATABASE=LUFA MIDI Demo Application usb:v03EBp2049* ID_MODEL_FROM_DATABASE=Stripe Snoop Magnetic Stripe Reader usb:v03EBp204A* ID_MODEL_FROM_DATABASE=LUFA CDC Class Bootloader usb:v03EBp204B* ID_MODEL_FROM_DATABASE=LUFA USB to Serial Adapter Project usb:v03EBp204C* ID_MODEL_FROM_DATABASE=LUFA RNDIS Demo Application usb:v03EBp204D* ID_MODEL_FROM_DATABASE=LUFA Combined Mouse and Keyboard Demo Application usb:v03EBp204E* ID_MODEL_FROM_DATABASE=LUFA Dual CDC Demo Application usb:v03EBp204F* ID_MODEL_FROM_DATABASE=LUFA Generic HID Demo Application usb:v03EBp2060* ID_MODEL_FROM_DATABASE=Benito Programmer Project usb:v03EBp2061* ID_MODEL_FROM_DATABASE=LUFA Combined Mass Storage and Keyboard Demo Application usb:v03EBp2062* ID_MODEL_FROM_DATABASE=LUFA Combined CDC and Mouse Demo Application usb:v03EBp2063* ID_MODEL_FROM_DATABASE=LUFA Datalogger Device usb:v03EBp2064* ID_MODEL_FROM_DATABASE=Interfaceless Control-Only LUFA Devices usb:v03EBp2065* ID_MODEL_FROM_DATABASE=LUFA Test and Measurement Demo Application usb:v03EBp2066* ID_MODEL_FROM_DATABASE=LUFA Multiple Report HID Demo usb:v03EBp2068* ID_MODEL_FROM_DATABASE=LUFA Virtual Serial/Mass Storage Demo usb:v03EBp2069* ID_MODEL_FROM_DATABASE=LUFA Webserver Project usb:v03EBp2103* ID_MODEL_FROM_DATABASE=JTAG ICE mkII usb:v03EBp2104* ID_MODEL_FROM_DATABASE=AVR ISP mkII usb:v03EBp2105* ID_MODEL_FROM_DATABASE=AVRONE! usb:v03EBp2106* ID_MODEL_FROM_DATABASE=STK600 development board usb:v03EBp2107* ID_MODEL_FROM_DATABASE=AVR Dragon usb:v03EBp2109* ID_MODEL_FROM_DATABASE=STK541 ZigBee Development Board usb:v03EBp210D* ID_MODEL_FROM_DATABASE=XPLAIN evaluation kit (CDC ACM) usb:v03EBp2110* ID_MODEL_FROM_DATABASE=AVR JTAGICE3 Debugger and Programmer usb:v03EBp2122* ID_MODEL_FROM_DATABASE=XMEGA-A1 Explained evaluation kit usb:v03EBp2141* ID_MODEL_FROM_DATABASE=ICE debugger usb:v03EBp2310* ID_MODEL_FROM_DATABASE=EVK11xx evaluation board usb:v03EBp2FE4* ID_MODEL_FROM_DATABASE=ATxmega32A4U DFU bootloader usb:v03EBp2FE6* ID_MODEL_FROM_DATABASE=Cactus V6 (DFU) usb:v03EBp2FEA* ID_MODEL_FROM_DATABASE=Cactus RF60 (DFU) usb:v03EBp2FF0* ID_MODEL_FROM_DATABASE=atmega32u2 DFU bootloader usb:v03EBp2FF4* ID_MODEL_FROM_DATABASE=atmega32u4 DFU bootloader usb:v03EBp2FFA* ID_MODEL_FROM_DATABASE=at90usb162 DFU bootloader usb:v03EBp2FFB* ID_MODEL_FROM_DATABASE=at90usb AVR DFU bootloader usb:v03EBp2FFD* ID_MODEL_FROM_DATABASE=at89c5130/c5131 DFU bootloader usb:v03EBp2FFF* ID_MODEL_FROM_DATABASE=at89c5132/c51snd1c DFU bootloader usb:v03EBp3301* ID_MODEL_FROM_DATABASE=at43301 4-Port Hub usb:v03EBp3312* ID_MODEL_FROM_DATABASE=4-Port Hub usb:v03EBp4102* ID_MODEL_FROM_DATABASE=AirVast W-Buddie WN210 usb:v03EBp5601* ID_MODEL_FROM_DATABASE=at76c510 Prism-II 802.11b Access Point usb:v03EBp5603* ID_MODEL_FROM_DATABASE=Cisco 7920 WiFi IP Phone usb:v03EBp6119* ID_MODEL_FROM_DATABASE=AT91SAM CDC Demo Application usb:v03EBp6124* ID_MODEL_FROM_DATABASE=at91sam SAMBA bootloader usb:v03EBp6127* ID_MODEL_FROM_DATABASE=AT91SAM HID Keyboard Demo Application usb:v03EBp6129* ID_MODEL_FROM_DATABASE=AT91SAM Mass Storage Demo Application usb:v03EBp6200* ID_MODEL_FROM_DATABASE=AT91SAM HID Mouse Demo Application usb:v03EBp7603* ID_MODEL_FROM_DATABASE=D-Link DWL-120 802.11b Wireless Adapter [Atmel at76c503a] usb:v03EBp7604* ID_MODEL_FROM_DATABASE=at76c503a 802.11b Adapter usb:v03EBp7605* ID_MODEL_FROM_DATABASE=at76c503a 802.11b Adapter usb:v03EBp7606* ID_MODEL_FROM_DATABASE=at76c505 802.11b Adapter usb:v03EBp7611* ID_MODEL_FROM_DATABASE=at76c510 rfmd2948 802.11b Access Point usb:v03EBp7613* ID_MODEL_FROM_DATABASE=WL-1130 USB usb:v03EBp7614* ID_MODEL_FROM_DATABASE=AT76c505a Wireless Adapter usb:v03EBp7615* ID_MODEL_FROM_DATABASE=AT76C505AMX Wireless Adapter usb:v03EBp7617* ID_MODEL_FROM_DATABASE=AT76C505AS Wireless Adapter usb:v03EBp7800* ID_MODEL_FROM_DATABASE=Mini Album usb:v03EBpFF07* ID_MODEL_FROM_DATABASE=Tux Droid fish dongle usb:v03EC* ID_VENDOR_FROM_DATABASE=Iwatsu America, Inc. usb:v03ED* ID_VENDOR_FROM_DATABASE=Mitel Corp. usb:v03EE* ID_VENDOR_FROM_DATABASE=Mitsumi usb:v03EEp0000* ID_MODEL_FROM_DATABASE=CD-R/RW Drive usb:v03EEp2501* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v03EEp2502* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v03EEp5609* ID_MODEL_FROM_DATABASE=Japanese Keyboard usb:v03EEp641F* ID_MODEL_FROM_DATABASE=WIF-0402C Bluetooth Adapter usb:v03EEp6438* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v03EEp6440* ID_MODEL_FROM_DATABASE=WML-C52APR Bluetooth Adapter usb:v03EEp6901* ID_MODEL_FROM_DATABASE=SmartDisk FDD usb:v03EEp6902* ID_MODEL_FROM_DATABASE=Floppy Disk Drive usb:v03EEp7500* ID_MODEL_FROM_DATABASE=CD-R/RW usb:v03EEpFFFF* ID_MODEL_FROM_DATABASE=Dongle with BlueCore in DFU mode usb:v03F0* ID_VENDOR_FROM_DATABASE=Hewlett-Packard usb:v03F0p0004* ID_MODEL_FROM_DATABASE=DeskJet 895c usb:v03F0p0011* ID_MODEL_FROM_DATABASE=OfficeJet G55 usb:v03F0p0012* ID_MODEL_FROM_DATABASE=DeskJet 1125C Printer Port usb:v03F0p0024* ID_MODEL_FROM_DATABASE=KU-0316 Keyboard usb:v03F0p002A* ID_MODEL_FROM_DATABASE=LaserJet P1102 usb:v03F0p0101* ID_MODEL_FROM_DATABASE=ScanJet 4100c usb:v03F0p0102* ID_MODEL_FROM_DATABASE=PhotoSmart S20 usb:v03F0p0104* ID_MODEL_FROM_DATABASE=DeskJet 880c/970c usb:v03F0p0105* ID_MODEL_FROM_DATABASE=ScanJet 4200c usb:v03F0p0107* ID_MODEL_FROM_DATABASE=CD-Writer Plus usb:v03F0p010C* ID_MODEL_FROM_DATABASE=Multimedia Keyboard Hub usb:v03F0p0111* ID_MODEL_FROM_DATABASE=G55xi Printer/Scanner/Copier usb:v03F0p0117* ID_MODEL_FROM_DATABASE=LaserJet 3200 usb:v03F0p011C* ID_MODEL_FROM_DATABASE=hn210w 802.11b Adapter usb:v03F0p011D* ID_MODEL_FROM_DATABASE=Bluetooth 1.2 Interface [Broadcom BCM2035] usb:v03F0p0121* ID_MODEL_FROM_DATABASE=HP 39g+ [F2224A], 39gs [F2223A], 40gs [F2225A], 48gII [F2226A], 49g+ [F2228A], 50g [F2229A, NW240AA] usb:v03F0p0122* ID_MODEL_FROM_DATABASE=HID Internet Keyboard usb:v03F0p0125* ID_MODEL_FROM_DATABASE=DAT72 Tape usb:v03F0p0139* ID_MODEL_FROM_DATABASE=Barcode Scanner 4430 usb:v03F0p0201* ID_MODEL_FROM_DATABASE=ScanJet 6200c usb:v03F0p0202* ID_MODEL_FROM_DATABASE=PhotoSmart S20 usb:v03F0p0204* ID_MODEL_FROM_DATABASE=DeskJet 815c usb:v03F0p0205* ID_MODEL_FROM_DATABASE=ScanJet 3300c usb:v03F0p0207* ID_MODEL_FROM_DATABASE=CD-Writer Plus 8200e usb:v03F0p020C* ID_MODEL_FROM_DATABASE=Multimedia Keyboard usb:v03F0p0211* ID_MODEL_FROM_DATABASE=OfficeJet G85 usb:v03F0p0212* ID_MODEL_FROM_DATABASE=DeskJet 1220C usb:v03F0p0217* ID_MODEL_FROM_DATABASE=LaserJet 2200 usb:v03F0p0218* ID_MODEL_FROM_DATABASE=APOLLO P2500/2600 usb:v03F0p0221* ID_MODEL_FROM_DATABASE=StreamSmart 400 [F2235AA] usb:v03F0p022A* ID_MODEL_FROM_DATABASE=Laserjet CP1525nw usb:v03F0p0241* ID_MODEL_FROM_DATABASE=Link-5 micro dongle usb:v03F0p0304* ID_MODEL_FROM_DATABASE=DeskJet 810c/812c usb:v03F0p0305* ID_MODEL_FROM_DATABASE=ScanJet 4300c usb:v03F0p0307* ID_MODEL_FROM_DATABASE=CD-Writer+ CD-4e usb:v03F0p0311* ID_MODEL_FROM_DATABASE=OfficeJet G85xi usb:v03F0p0312* ID_MODEL_FROM_DATABASE=Color Inkjet CP1700 usb:v03F0p0314* ID_MODEL_FROM_DATABASE=designjet 30/130 series usb:v03F0p0317* ID_MODEL_FROM_DATABASE=LaserJet 1200 usb:v03F0p0324* ID_MODEL_FROM_DATABASE=SK-2885 keyboard usb:v03F0p034A* ID_MODEL_FROM_DATABASE=Elite Keyboard usb:v03F0p0401* ID_MODEL_FROM_DATABASE=ScanJet 5200c usb:v03F0p0404* ID_MODEL_FROM_DATABASE=DeskJet 830c/832c usb:v03F0p0405* ID_MODEL_FROM_DATABASE=ScanJet 3400cse usb:v03F0p0411* ID_MODEL_FROM_DATABASE=OfficeJet G95 usb:v03F0p0412* ID_MODEL_FROM_DATABASE=Printing Support usb:v03F0p0417* ID_MODEL_FROM_DATABASE=LaserJet 1200 series usb:v03F0p0423* ID_MODEL_FROM_DATABASE=HS-COMBO Cardreader usb:v03F0p042A* ID_MODEL_FROM_DATABASE=LaserJet M1132 MFP usb:v03F0p0441* ID_MODEL_FROM_DATABASE=Prime [NW280AA, G8X92AA] usb:v03F0p0504* ID_MODEL_FROM_DATABASE=DeskJet 885c usb:v03F0p0505* ID_MODEL_FROM_DATABASE=ScanJet 2100c usb:v03F0p0507* ID_MODEL_FROM_DATABASE=DVD+RW usb:v03F0p050C* ID_MODEL_FROM_DATABASE=5219 Wireless Keyboard usb:v03F0p0511* ID_MODEL_FROM_DATABASE=OfficeJet K60 usb:v03F0p0512* ID_MODEL_FROM_DATABASE=DeckJet 450 usb:v03F0p0517* ID_MODEL_FROM_DATABASE=LaserJet 1000 usb:v03F0p051D* ID_MODEL_FROM_DATABASE=Bluetooth Interface usb:v03F0p0601* ID_MODEL_FROM_DATABASE=ScanJet 6300c usb:v03F0p0604* ID_MODEL_FROM_DATABASE=DeskJet 840c usb:v03F0p0605* ID_MODEL_FROM_DATABASE=ScanJet 2200c usb:v03F0p0611* ID_MODEL_FROM_DATABASE=OfficeJet K60xi usb:v03F0p0612* ID_MODEL_FROM_DATABASE=business inkjet 3000 usb:v03F0p0624* ID_MODEL_FROM_DATABASE=Bluetooth Dongle usb:v03F0p0701* ID_MODEL_FROM_DATABASE=ScanJet 5300c/5370c usb:v03F0p0704* ID_MODEL_FROM_DATABASE=DeskJet 825c usb:v03F0p0705* ID_MODEL_FROM_DATABASE=ScanJet 4400c usb:v03F0p070C* ID_MODEL_FROM_DATABASE=Personal Media Drive usb:v03F0p0711* ID_MODEL_FROM_DATABASE=OfficeJet K80 usb:v03F0p0712* ID_MODEL_FROM_DATABASE=DeskJet 1180c usb:v03F0p0714* ID_MODEL_FROM_DATABASE=Printing Support usb:v03F0p0741* ID_MODEL_FROM_DATABASE=Prime Wireless Kit [FOK65AA] usb:v03F0p0801* ID_MODEL_FROM_DATABASE=ScanJet 7400c usb:v03F0p0804* ID_MODEL_FROM_DATABASE=DeskJet 816c usb:v03F0p0805* ID_MODEL_FROM_DATABASE=HP4470C usb:v03F0p0811* ID_MODEL_FROM_DATABASE=OfficeJet K80xi usb:v03F0p0817* ID_MODEL_FROM_DATABASE=LaserJet 3300 usb:v03F0p0901* ID_MODEL_FROM_DATABASE=ScanJet 2300c usb:v03F0p0904* ID_MODEL_FROM_DATABASE=DeskJet 845c usb:v03F0p0912* ID_MODEL_FROM_DATABASE=Printing Support usb:v03F0p0917* ID_MODEL_FROM_DATABASE=LaserJet 3330 usb:v03F0p0924* ID_MODEL_FROM_DATABASE=Modular Smartcard Keyboard usb:v03F0p094A* ID_MODEL_FROM_DATABASE=Optical Mouse [672662-001] usb:v03F0p0A01* ID_MODEL_FROM_DATABASE=ScanJet 2400c usb:v03F0p0A17* ID_MODEL_FROM_DATABASE=color LaserJet 3700 usb:v03F0p0B01* ID_MODEL_FROM_DATABASE=ScanJet 82x0C usb:v03F0p0B0C* ID_MODEL_FROM_DATABASE=Wireless Keyboard and Optical Mouse receiver usb:v03F0p0B17* ID_MODEL_FROM_DATABASE=LaserJet 2300d usb:v03F0p0C17* ID_MODEL_FROM_DATABASE=LaserJet 1010 usb:v03F0p0C24* ID_MODEL_FROM_DATABASE=Bluetooth Dongle usb:v03F0p0D12* ID_MODEL_FROM_DATABASE=OfficeJet 9100 series usb:v03F0p0D17* ID_MODEL_FROM_DATABASE=LaserJet 1012 usb:v03F0p0E17* ID_MODEL_FROM_DATABASE=LaserJet 1015 usb:v03F0p0F0C* ID_MODEL_FROM_DATABASE=Wireless Keyboard and Optical Mouse receiver usb:v03F0p0F11* ID_MODEL_FROM_DATABASE=OfficeJet V40 usb:v03F0p0F12* ID_MODEL_FROM_DATABASE=Printing Support usb:v03F0p0F17* ID_MODEL_FROM_DATABASE=LaserJet 1150 usb:v03F0p0F2A* ID_MODEL_FROM_DATABASE=LaserJet 400 color M451dn usb:v03F0p1001* ID_MODEL_FROM_DATABASE=Photo Scanner 1000 usb:v03F0p1002* ID_MODEL_FROM_DATABASE=PhotoSmart 140 series usb:v03F0p1004* ID_MODEL_FROM_DATABASE=DeskJet 970c/970cse usb:v03F0p1005* ID_MODEL_FROM_DATABASE=ScanJet 5400c usb:v03F0p1011* ID_MODEL_FROM_DATABASE=OfficeJet V40xi usb:v03F0p1016* ID_MODEL_FROM_DATABASE=Jornada 548 / iPAQ HW6515 Pocket PC usb:v03F0p1017* ID_MODEL_FROM_DATABASE=LaserJet 1300 usb:v03F0p1024* ID_MODEL_FROM_DATABASE=Smart Card Keyboard usb:v03F0p1027* ID_MODEL_FROM_DATABASE=Virtual keyboard and mouse usb:v03F0p1102* ID_MODEL_FROM_DATABASE=PhotoSmart 240 series usb:v03F0p1104* ID_MODEL_FROM_DATABASE=DeskJet 959c usb:v03F0p1105* ID_MODEL_FROM_DATABASE=ScanJet 5470c/5490c usb:v03F0p1111* ID_MODEL_FROM_DATABASE=OfficeJet v60 usb:v03F0p1116* ID_MODEL_FROM_DATABASE=Jornada 568 Pocket PC usb:v03F0p1117* ID_MODEL_FROM_DATABASE=LaserJet 1300n usb:v03F0p1151* ID_MODEL_FROM_DATABASE=PSC-750xi Printer/Scanner/Copier usb:v03F0p1198* ID_MODEL_FROM_DATABASE=HID-compliant mouse usb:v03F0p1202* ID_MODEL_FROM_DATABASE=PhotoSmart 320 series usb:v03F0p1204* ID_MODEL_FROM_DATABASE=DeskJet 930c usb:v03F0p1205* ID_MODEL_FROM_DATABASE=ScanJet 4500C/5550C usb:v03F0p1211* ID_MODEL_FROM_DATABASE=OfficeJet v60xi usb:v03F0p1217* ID_MODEL_FROM_DATABASE=LaserJet 2300L usb:v03F0p1227* ID_MODEL_FROM_DATABASE=Virtual CD-ROM usb:v03F0p1302* ID_MODEL_FROM_DATABASE=PhotoSmart 370 series usb:v03F0p1305* ID_MODEL_FROM_DATABASE=ScanJet 4570c usb:v03F0p1311* ID_MODEL_FROM_DATABASE=OfficeJet V30 usb:v03F0p1312* ID_MODEL_FROM_DATABASE=DeskJet 460 usb:v03F0p1317* ID_MODEL_FROM_DATABASE=LaserJet 1005 usb:v03F0p1327* ID_MODEL_FROM_DATABASE=iLO Virtual Hub usb:v03F0p134A* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v03F0p1405* ID_MODEL_FROM_DATABASE=ScanJet 3670 usb:v03F0p1411* ID_MODEL_FROM_DATABASE=PSC 750 usb:v03F0p1424* ID_MODEL_FROM_DATABASE=f2105 Monitor Hub usb:v03F0p1502* ID_MODEL_FROM_DATABASE=PhotoSmart 420 series usb:v03F0p1504* ID_MODEL_FROM_DATABASE=DeskJet 920c usb:v03F0p150C* ID_MODEL_FROM_DATABASE=Mood Lighting (Microchip Technology Inc.) usb:v03F0p1511* ID_MODEL_FROM_DATABASE=PSC 750xi usb:v03F0p1512* ID_MODEL_FROM_DATABASE=Printing Support usb:v03F0p1517* ID_MODEL_FROM_DATABASE=color LaserJet 3500 usb:v03F0p1524* ID_MODEL_FROM_DATABASE=Smart Card Keyboard - KR usb:v03F0p1539* ID_MODEL_FROM_DATABASE=Mini Magnetic Stripe Reader usb:v03F0p1541* ID_MODEL_FROM_DATABASE=Prime [G8X92AA] usb:v03F0p1602* ID_MODEL_FROM_DATABASE=PhotoSmart 330 series usb:v03F0p1604* ID_MODEL_FROM_DATABASE=DeskJet 940c usb:v03F0p1605* ID_MODEL_FROM_DATABASE=ScanJet 5530C PhotoSmart usb:v03F0p1611* ID_MODEL_FROM_DATABASE=psc 780 usb:v03F0p1617* ID_MODEL_FROM_DATABASE=LaserJet 3015 usb:v03F0p161D* ID_MODEL_FROM_DATABASE=Wireless Rechargeable Optical Mouse (HID) usb:v03F0p1624* ID_MODEL_FROM_DATABASE=Smart Card Keyboard - JP usb:v03F0p1702* ID_MODEL_FROM_DATABASE=PhotoSmart 380 series usb:v03F0p1704* ID_MODEL_FROM_DATABASE=DeskJet 948C usb:v03F0p1705* ID_MODEL_FROM_DATABASE=ScanJet 5590 usb:v03F0p1711* ID_MODEL_FROM_DATABASE=psc 780xi usb:v03F0p1712* ID_MODEL_FROM_DATABASE=Printing Support usb:v03F0p1717* ID_MODEL_FROM_DATABASE=LaserJet 3020 usb:v03F0p171D* ID_MODEL_FROM_DATABASE=Bluetooth 2.0 Interface [Broadcom BCM2045] usb:v03F0p1801* ID_MODEL_FROM_DATABASE=Inkjet P-2000U usb:v03F0p1802* ID_MODEL_FROM_DATABASE=PhotoSmart 470 series usb:v03F0p1804* ID_MODEL_FROM_DATABASE=DeskJet 916C usb:v03F0p1805* ID_MODEL_FROM_DATABASE=ScanJet 7650 usb:v03F0p1811* ID_MODEL_FROM_DATABASE=PSC 720 usb:v03F0p1812* ID_MODEL_FROM_DATABASE=OfficeJet Pro K550 usb:v03F0p1817* ID_MODEL_FROM_DATABASE=LaserJet 3030 usb:v03F0p181D* ID_MODEL_FROM_DATABASE=Bluetooth 2.0 Interface usb:v03F0p1902* ID_MODEL_FROM_DATABASE=PhotoSmart A430 series usb:v03F0p1904* ID_MODEL_FROM_DATABASE=DeskJet 3820 usb:v03F0p1911* ID_MODEL_FROM_DATABASE=OfficeJet V45 usb:v03F0p1917* ID_MODEL_FROM_DATABASE=LaserJet 3380 usb:v03F0p1A02* ID_MODEL_FROM_DATABASE=PhotoSmart A510 series usb:v03F0p1A11* ID_MODEL_FROM_DATABASE=OfficeJet 5100 series usb:v03F0p1A17* ID_MODEL_FROM_DATABASE=color LaserJet 4650 usb:v03F0p1B02* ID_MODEL_FROM_DATABASE=PhotoSmart A610 series usb:v03F0p1B04* ID_MODEL_FROM_DATABASE=DeskJet 3810 usb:v03F0p1B05* ID_MODEL_FROM_DATABASE=ScanJet 4850C/4890C usb:v03F0p1B07* ID_MODEL_FROM_DATABASE=Premium Starter Webcam usb:v03F0p1C02* ID_MODEL_FROM_DATABASE=PhotoSmart A710 series usb:v03F0p1C17* ID_MODEL_FROM_DATABASE=Color LaserJet 2550l usb:v03F0p1D02* ID_MODEL_FROM_DATABASE=PhotoSmart A310 series usb:v03F0p1D17* ID_MODEL_FROM_DATABASE=LaserJet 1320 usb:v03F0p1D24* ID_MODEL_FROM_DATABASE=Barcode scanner usb:v03F0p1E02* ID_MODEL_FROM_DATABASE=PhotoSmart A320 Printer series usb:v03F0p1E11* ID_MODEL_FROM_DATABASE=PSC-950 usb:v03F0p1E17* ID_MODEL_FROM_DATABASE=LaserJet 1160 series usb:v03F0p1F02* ID_MODEL_FROM_DATABASE=PhotoSmart A440 Printer series usb:v03F0p1F11* ID_MODEL_FROM_DATABASE=PSC 920 usb:v03F0p1F12* ID_MODEL_FROM_DATABASE=OfficeJet Pro K5300 usb:v03F0p1F17* ID_MODEL_FROM_DATABASE=color LaserJet 5550 usb:v03F0p1F1D* ID_MODEL_FROM_DATABASE=un2400 Gobi Wireless Modem usb:v03F0p2001* ID_MODEL_FROM_DATABASE=Floppy usb:v03F0p2002* ID_MODEL_FROM_DATABASE=Hub usb:v03F0p2004* ID_MODEL_FROM_DATABASE=DeskJet 640c usb:v03F0p2005* ID_MODEL_FROM_DATABASE=ScanJet 3570c usb:v03F0p2012* ID_MODEL_FROM_DATABASE=OfficeJet Pro K5400 usb:v03F0p201D* ID_MODEL_FROM_DATABASE=un2400 Gobi Wireless Modem (QDL mode) usb:v03F0p2039* ID_MODEL_FROM_DATABASE=Cashdrawer usb:v03F0p2102* ID_MODEL_FROM_DATABASE=PhotoSmart 7345 usb:v03F0p2104* ID_MODEL_FROM_DATABASE=DeskJet 630c usb:v03F0p2112* ID_MODEL_FROM_DATABASE=OfficeJet Pro L7500 usb:v03F0p211D* ID_MODEL_FROM_DATABASE=Sierra MC5725 [ev2210] usb:v03F0p2202* ID_MODEL_FROM_DATABASE=PhotoSmart 7600 series usb:v03F0p2205* ID_MODEL_FROM_DATABASE=ScanJet 3500c usb:v03F0p2212* ID_MODEL_FROM_DATABASE=OfficeJet Pro L7600 usb:v03F0p2217* ID_MODEL_FROM_DATABASE=color LaserJet 9500 MFP usb:v03F0p2302* ID_MODEL_FROM_DATABASE=PhotoSmart 7600 series usb:v03F0p2304* ID_MODEL_FROM_DATABASE=DeskJet 656c usb:v03F0p2305* ID_MODEL_FROM_DATABASE=ScanJet 3970c usb:v03F0p2311* ID_MODEL_FROM_DATABASE=OfficeJet d series usb:v03F0p2312* ID_MODEL_FROM_DATABASE=OfficeJet Pro L7700 usb:v03F0p2317* ID_MODEL_FROM_DATABASE=LaserJet 4350 usb:v03F0p231D* ID_MODEL_FROM_DATABASE=Broadcom 2070 Bluetooth Combo usb:v03F0p2402* ID_MODEL_FROM_DATABASE=PhotoSmart 7700 series usb:v03F0p2404* ID_MODEL_FROM_DATABASE=Deskjet F2280 series usb:v03F0p2405* ID_MODEL_FROM_DATABASE=ScanJet 4070 PhotoSmart usb:v03F0p2417* ID_MODEL_FROM_DATABASE=LaserJet 4250 usb:v03F0p241D* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem (QDL mode) usb:v03F0p2424* ID_MODEL_FROM_DATABASE=LP1965 19" Monitor Hub usb:v03F0p2502* ID_MODEL_FROM_DATABASE=PhotoSmart 7700 series usb:v03F0p2504* ID_MODEL_FROM_DATABASE=DeskJet F4200 series usb:v03F0p2505* ID_MODEL_FROM_DATABASE=ScanJet 3770 usb:v03F0p2512* ID_MODEL_FROM_DATABASE=OfficeJet Pro L7300 / Compaq LA2405 series monitor usb:v03F0p2514* ID_MODEL_FROM_DATABASE=4-port hub usb:v03F0p2517* ID_MODEL_FROM_DATABASE=LaserJet 2410 usb:v03F0p251D* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem usb:v03F0p2524* ID_MODEL_FROM_DATABASE=LP3065 30" Monitor Hub usb:v03F0p2602* ID_MODEL_FROM_DATABASE=PhotoSmart A520 series usb:v03F0p2605* ID_MODEL_FROM_DATABASE=ScanJet 3800c usb:v03F0p2611* ID_MODEL_FROM_DATABASE=OfficeJet 7100 series usb:v03F0p2617* ID_MODEL_FROM_DATABASE=Color LaserJet 2820 series usb:v03F0p2624* ID_MODEL_FROM_DATABASE=Pole Display (HP522 2 x 20 Line Display) usb:v03F0p2702* ID_MODEL_FROM_DATABASE=PhotoSmart A620 series usb:v03F0p2704* ID_MODEL_FROM_DATABASE=DeskJet 915 usb:v03F0p2717* ID_MODEL_FROM_DATABASE=Color LaserJet 2830 usb:v03F0p2724* ID_MODEL_FROM_DATABASE=Magnetic Stripe Reader IDRA-334133-HP usb:v03F0p2805* ID_MODEL_FROM_DATABASE=Scanjet G2710 usb:v03F0p2811* ID_MODEL_FROM_DATABASE=PSC-2100 usb:v03F0p2817* ID_MODEL_FROM_DATABASE=Color LaserJet 2840 usb:v03F0p2902* ID_MODEL_FROM_DATABASE=PhotoSmart A820 series usb:v03F0p2911* ID_MODEL_FROM_DATABASE=PSC 2200 usb:v03F0p2917* ID_MODEL_FROM_DATABASE=LaserJet 2420 usb:v03F0p2A11* ID_MODEL_FROM_DATABASE=PSC 2150 series usb:v03F0p2A17* ID_MODEL_FROM_DATABASE=LaserJet 2430 usb:v03F0p2A1D* ID_MODEL_FROM_DATABASE=Integrated Module with Bluetooth 2.1 Wireless technology usb:v03F0p2B11* ID_MODEL_FROM_DATABASE=PSC 2170 series usb:v03F0p2B17* ID_MODEL_FROM_DATABASE=LaserJet 1020 usb:v03F0p2C12* ID_MODEL_FROM_DATABASE=Officejet J4680 usb:v03F0p2C17* ID_MODEL_FROM_DATABASE=LaserJet 1022 usb:v03F0p2C24* ID_MODEL_FROM_DATABASE=Logitech M-UAL-96 Mouse usb:v03F0p2D05* ID_MODEL_FROM_DATABASE=Scanjet 7000 usb:v03F0p2D11* ID_MODEL_FROM_DATABASE=OfficeJet 6110 usb:v03F0p2D17* ID_MODEL_FROM_DATABASE=Printing Support usb:v03F0p2E11* ID_MODEL_FROM_DATABASE=PSC 1000 usb:v03F0p2E17* ID_MODEL_FROM_DATABASE=LaserJet 2600n usb:v03F0p2E24* ID_MODEL_FROM_DATABASE=LP2275w Monitor Hub usb:v03F0p2F11* ID_MODEL_FROM_DATABASE=PSC 1200 usb:v03F0p2F17* ID_MODEL_FROM_DATABASE=EWS 2605dn usb:v03F0p2F24* ID_MODEL_FROM_DATABASE=LP2475w Monitor Hub usb:v03F0p3002* ID_MODEL_FROM_DATABASE=PhotoSmart P1000 usb:v03F0p3004* ID_MODEL_FROM_DATABASE=DeskJet 980c usb:v03F0p3005* ID_MODEL_FROM_DATABASE=ScanJet 4670v usb:v03F0p3011* ID_MODEL_FROM_DATABASE=PSC 1100 series usb:v03F0p3017* ID_MODEL_FROM_DATABASE=Printing Support usb:v03F0p3102* ID_MODEL_FROM_DATABASE=PhotoSmart P1100 Printer w/ Card Reader usb:v03F0p3104* ID_MODEL_FROM_DATABASE=DeskJet 960c usb:v03F0p3111* ID_MODEL_FROM_DATABASE=OfficeJet 4100 series usb:v03F0p3117* ID_MODEL_FROM_DATABASE=EWS 2605dtn usb:v03F0p311D* ID_MODEL_FROM_DATABASE=Atheros AR9285 Malbec Bluetooth Adapter usb:v03F0p3202* ID_MODEL_FROM_DATABASE=PhotoSmart 1215 usb:v03F0p3207* ID_MODEL_FROM_DATABASE=4 GB flash drive usb:v03F0p3211* ID_MODEL_FROM_DATABASE=OfficeJet 4105 series usb:v03F0p3217* ID_MODEL_FROM_DATABASE=LaserJet 3050 usb:v03F0p3302* ID_MODEL_FROM_DATABASE=PhotoSmart 1218 usb:v03F0p3304* ID_MODEL_FROM_DATABASE=DeskJet 990c usb:v03F0p3312* ID_MODEL_FROM_DATABASE=OfficeJet J6410 usb:v03F0p3317* ID_MODEL_FROM_DATABASE=LaserJet 3052 usb:v03F0p3402* ID_MODEL_FROM_DATABASE=PhotoSmart 1115 usb:v03F0p3404* ID_MODEL_FROM_DATABASE=DeskJet 6122 usb:v03F0p3417* ID_MODEL_FROM_DATABASE=LaserJet 3055 usb:v03F0p3502* ID_MODEL_FROM_DATABASE=PhotoSmart 230 usb:v03F0p3504* ID_MODEL_FROM_DATABASE=DeskJet 6127c usb:v03F0p3511* ID_MODEL_FROM_DATABASE=PSC 2300 usb:v03F0p3517* ID_MODEL_FROM_DATABASE=LaserJet 3390 usb:v03F0p3602* ID_MODEL_FROM_DATABASE=PhotoSmart 1315 usb:v03F0p3611* ID_MODEL_FROM_DATABASE=PSC 2410 PhotoSmart usb:v03F0p3617* ID_MODEL_FROM_DATABASE=Color LaserJet 2605 usb:v03F0p3711* ID_MODEL_FROM_DATABASE=PSC 2500 usb:v03F0p3717* ID_MODEL_FROM_DATABASE=EWS UPD usb:v03F0p3724* ID_MODEL_FROM_DATABASE=Webcam usb:v03F0p3802* ID_MODEL_FROM_DATABASE=PhotoSmart 100 usb:v03F0p3807* ID_MODEL_FROM_DATABASE=c485w Flash Drive usb:v03F0p3817* ID_MODEL_FROM_DATABASE=LaserJet P2015 series usb:v03F0p3902* ID_MODEL_FROM_DATABASE=PhotoSmart 130 usb:v03F0p3912* ID_MODEL_FROM_DATABASE=Officejet Pro 8500 usb:v03F0p3A02* ID_MODEL_FROM_DATABASE=PhotoSmart 7150 usb:v03F0p3A11* ID_MODEL_FROM_DATABASE=OfficeJet 5500 series usb:v03F0p3A17* ID_MODEL_FROM_DATABASE=Printing Support usb:v03F0p3B02* ID_MODEL_FROM_DATABASE=PhotoSmart 7150~ usb:v03F0p3B05* ID_MODEL_FROM_DATABASE=Scanjet N8460 usb:v03F0p3B11* ID_MODEL_FROM_DATABASE=PSC 1300 series usb:v03F0p3B17* ID_MODEL_FROM_DATABASE=LaserJet M1005 MFP usb:v03F0p3C02* ID_MODEL_FROM_DATABASE=PhotoSmart 7350 usb:v03F0p3C05* ID_MODEL_FROM_DATABASE=Scanjet Professional 1000 Mobile Scanner usb:v03F0p3C11* ID_MODEL_FROM_DATABASE=PSC 1358 usb:v03F0p3C17* ID_MODEL_FROM_DATABASE=EWS UPD usb:v03F0p3D02* ID_MODEL_FROM_DATABASE=PhotoSmart 7350~ usb:v03F0p3D11* ID_MODEL_FROM_DATABASE=OfficeJet 4215 usb:v03F0p3D17* ID_MODEL_FROM_DATABASE=LaserJet P1005 usb:v03F0p3E02* ID_MODEL_FROM_DATABASE=PhotoSmart 7550 usb:v03F0p3E17* ID_MODEL_FROM_DATABASE=LaserJet P1006 usb:v03F0p3F02* ID_MODEL_FROM_DATABASE=PhotoSmart 7550~ usb:v03F0p3F11* ID_MODEL_FROM_DATABASE=PSC-1315/PSC-1317 usb:v03F0p4002* ID_MODEL_FROM_DATABASE=PhotoSmart 635/715/720/735/935/E337 (storage) usb:v03F0p4004* ID_MODEL_FROM_DATABASE=CP1160 usb:v03F0p4102* ID_MODEL_FROM_DATABASE=PhotoSmart 618 usb:v03F0p4105* ID_MODEL_FROM_DATABASE=ScanJet 4370 usb:v03F0p4111* ID_MODEL_FROM_DATABASE=OfficeJet 7200 series usb:v03F0p4117* ID_MODEL_FROM_DATABASE=LaserJet 1018 usb:v03F0p4202* ID_MODEL_FROM_DATABASE=PhotoSmart 812 usb:v03F0p4205* ID_MODEL_FROM_DATABASE=ScanJet G3010 usb:v03F0p4211* ID_MODEL_FROM_DATABASE=OfficeJet 7300 series usb:v03F0p4217* ID_MODEL_FROM_DATABASE=EWS CM1015 usb:v03F0p4302* ID_MODEL_FROM_DATABASE=PhotoSmart 850 (ptp) usb:v03F0p4305* ID_MODEL_FROM_DATABASE=ScanJet G3110 usb:v03F0p4311* ID_MODEL_FROM_DATABASE=OfficeJet 7400 series usb:v03F0p4317* ID_MODEL_FROM_DATABASE=Color LaserJet CM1017 usb:v03F0p4402* ID_MODEL_FROM_DATABASE=PhotoSmart 935 (ptp) usb:v03F0p4417* ID_MODEL_FROM_DATABASE=EWS UPD usb:v03F0p4502* ID_MODEL_FROM_DATABASE=PhotoSmart 945 (PTP mode) usb:v03F0p4505* ID_MODEL_FROM_DATABASE=ScanJet G4010 usb:v03F0p4507* ID_MODEL_FROM_DATABASE=External HDD usb:v03F0p4511* ID_MODEL_FROM_DATABASE=PhotoSmart 2600 usb:v03F0p4512* ID_MODEL_FROM_DATABASE=E709n [Officejet 6500 Wireless] usb:v03F0p4517* ID_MODEL_FROM_DATABASE=EWS UPD usb:v03F0p4605* ID_MODEL_FROM_DATABASE=ScanJet G4050 usb:v03F0p4611* ID_MODEL_FROM_DATABASE=PhotoSmart 2700 usb:v03F0p4717* ID_MODEL_FROM_DATABASE=Color LaserJet CP1215 usb:v03F0p4811* ID_MODEL_FROM_DATABASE=PSC 1600 usb:v03F0p4911* ID_MODEL_FROM_DATABASE=PSC 2350 usb:v03F0p4B11* ID_MODEL_FROM_DATABASE=OfficeJet 6200 usb:v03F0p4C11* ID_MODEL_FROM_DATABASE=PSC 1500 series usb:v03F0p4C17* ID_MODEL_FROM_DATABASE=EWS UPD usb:v03F0p4D11* ID_MODEL_FROM_DATABASE=PSC 1400 usb:v03F0p4D17* ID_MODEL_FROM_DATABASE=EWS UPD usb:v03F0p4E11* ID_MODEL_FROM_DATABASE=PhotoSmart 2570 series usb:v03F0p4F11* ID_MODEL_FROM_DATABASE=OfficeJet 5600 (USBHUB) usb:v03F0p4F17* ID_MODEL_FROM_DATABASE=Color LaserJet CM1312 MFP usb:v03F0p5004* ID_MODEL_FROM_DATABASE=DeskJet 995c usb:v03F0p5011* ID_MODEL_FROM_DATABASE=PhotoSmart 3100 series usb:v03F0p5017* ID_MODEL_FROM_DATABASE=EWS UPD usb:v03F0p5111* ID_MODEL_FROM_DATABASE=PhotoSmart 3200 series usb:v03F0p5211* ID_MODEL_FROM_DATABASE=PhotoSmart 3300 series usb:v03F0p5307* ID_MODEL_FROM_DATABASE=v165w Stick usb:v03F0p5311* ID_MODEL_FROM_DATABASE=OfficeJet 6300 usb:v03F0p5312* ID_MODEL_FROM_DATABASE=Officejet Pro 8500A usb:v03F0p5411* ID_MODEL_FROM_DATABASE=OfficeJet 4300 usb:v03F0p5511* ID_MODEL_FROM_DATABASE=DeskJet F300 series usb:v03F0p5611* ID_MODEL_FROM_DATABASE=PhotoSmart C3180 usb:v03F0p5617* ID_MODEL_FROM_DATABASE=LaserJet M1120 MFP usb:v03F0p5711* ID_MODEL_FROM_DATABASE=PhotoSmart C4100 series usb:v03F0p5717* ID_MODEL_FROM_DATABASE=LaserJet M1120n MFP usb:v03F0p5811* ID_MODEL_FROM_DATABASE=PhotoSmart C5100 series usb:v03F0p5817* ID_MODEL_FROM_DATABASE=LaserJet M1319f MFP usb:v03F0p5911* ID_MODEL_FROM_DATABASE=PhotoSmart C6180 usb:v03F0p5912* ID_MODEL_FROM_DATABASE=Officejet Pro 8600 usb:v03F0p5A11* ID_MODEL_FROM_DATABASE=PhotoSmart C7100 series usb:v03F0p5B11* ID_MODEL_FROM_DATABASE=OfficeJet J2100 series usb:v03F0p5B12* ID_MODEL_FROM_DATABASE=Officejet Pro 8100 usb:v03F0p5C11* ID_MODEL_FROM_DATABASE=PhotoSmart C4200 Printer series usb:v03F0p5C12* ID_MODEL_FROM_DATABASE=OfficeJet 6700 usb:v03F0p5C17* ID_MODEL_FROM_DATABASE=LaserJet P2055 series usb:v03F0p5D11* ID_MODEL_FROM_DATABASE=PhotoSmart C5200 series usb:v03F0p5E11* ID_MODEL_FROM_DATABASE=PhotoSmart D7400 series usb:v03F0p6004* ID_MODEL_FROM_DATABASE=DeskJet 5550 usb:v03F0p6102* ID_MODEL_FROM_DATABASE=Hewlett Packard Digital Camera usb:v03F0p6104* ID_MODEL_FROM_DATABASE=DeskJet 5650c usb:v03F0p6117* ID_MODEL_FROM_DATABASE=color LaserJet 3550 usb:v03F0p6202* ID_MODEL_FROM_DATABASE=PhotoSmart 215 usb:v03F0p6204* ID_MODEL_FROM_DATABASE=DeskJet 5150c usb:v03F0p6217* ID_MODEL_FROM_DATABASE=Color LaserJet 4700 usb:v03F0p6302* ID_MODEL_FROM_DATABASE=PhotoSmart 318/612 usb:v03F0p6317* ID_MODEL_FROM_DATABASE=Color LaserJet 4730mfp usb:v03F0p6402* ID_MODEL_FROM_DATABASE=PhotoSmart 715 (ptp) usb:v03F0p6411* ID_MODEL_FROM_DATABASE=PhotoSmart C8100 series usb:v03F0p6417* ID_MODEL_FROM_DATABASE=LaserJet 5200 usb:v03F0p6502* ID_MODEL_FROM_DATABASE=PhotoSmart 120 (ptp) usb:v03F0p6511* ID_MODEL_FROM_DATABASE=PhotoSmart C7200 series usb:v03F0p6602* ID_MODEL_FROM_DATABASE=PhotoSmart 320 usb:v03F0p6611* ID_MODEL_FROM_DATABASE=PhotoSmart C4380 series usb:v03F0p6617* ID_MODEL_FROM_DATABASE=LaserJet 5200L usb:v03F0p6702* ID_MODEL_FROM_DATABASE=PhotoSmart 720 (ptp) usb:v03F0p6717* ID_MODEL_FROM_DATABASE=Color LaserJet 3000 usb:v03F0p6802* ID_MODEL_FROM_DATABASE=PhotoSmart 620 (ptp) usb:v03F0p6811* ID_MODEL_FROM_DATABASE=PhotoSmart D5300 series usb:v03F0p6817* ID_MODEL_FROM_DATABASE=Color LaserJet 3800 usb:v03F0p6911* ID_MODEL_FROM_DATABASE=PhotoSmart D7200 series usb:v03F0p6917* ID_MODEL_FROM_DATABASE=Color LaserJet 3600 usb:v03F0p6A02* ID_MODEL_FROM_DATABASE=PhotoSmart 735 (ptp) usb:v03F0p6A11* ID_MODEL_FROM_DATABASE=PhotoSmart C6200 series usb:v03F0p6A17* ID_MODEL_FROM_DATABASE=LaserJet 4240 usb:v03F0p6B02* ID_MODEL_FROM_DATABASE=PhotoSmart R707 (PTP mode) usb:v03F0p6B11* ID_MODEL_FROM_DATABASE=Photosmart C4500 series usb:v03F0p6C11* ID_MODEL_FROM_DATABASE=Photosmart C4480 usb:v03F0p6C17* ID_MODEL_FROM_DATABASE=Color LaserJet 4610 usb:v03F0p6F17* ID_MODEL_FROM_DATABASE=Color LaserJet CP6015 series usb:v03F0p7004* ID_MODEL_FROM_DATABASE=DeskJet 3320c usb:v03F0p7102* ID_MODEL_FROM_DATABASE=PhotoSmart 635 (PTP mode) usb:v03F0p7104* ID_MODEL_FROM_DATABASE=DeskJet 3420c usb:v03F0p7117* ID_MODEL_FROM_DATABASE=CM8060 Color MFP with Edgeline Technology usb:v03F0p7202* ID_MODEL_FROM_DATABASE=PhotoSmart 43x (ptp) usb:v03F0p7204* ID_MODEL_FROM_DATABASE=DeskJet 36xx usb:v03F0p7217* ID_MODEL_FROM_DATABASE=LaserJet M5035 MFP usb:v03F0p7302* ID_MODEL_FROM_DATABASE=PhotoSmart M307 (PTP mode) usb:v03F0p7304* ID_MODEL_FROM_DATABASE=DeskJet 35xx usb:v03F0p7311* ID_MODEL_FROM_DATABASE=Photosmart Premium C309 usb:v03F0p7317* ID_MODEL_FROM_DATABASE=LaserJet P3005 usb:v03F0p7404* ID_MODEL_FROM_DATABASE=Printing Support usb:v03F0p7417* ID_MODEL_FROM_DATABASE=LaserJet M4345 MFP usb:v03F0p7504* ID_MODEL_FROM_DATABASE=Printing Support usb:v03F0p7517* ID_MODEL_FROM_DATABASE=LaserJet M3035 MFP usb:v03F0p7604* ID_MODEL_FROM_DATABASE=DeskJet 3940 usb:v03F0p7611* ID_MODEL_FROM_DATABASE=DeskJet F2492 All-in-One usb:v03F0p7617* ID_MODEL_FROM_DATABASE=LaserJet P3004 usb:v03F0p7702* ID_MODEL_FROM_DATABASE=PhotoSmart R817 (PTP mode) usb:v03F0p7704* ID_MODEL_FROM_DATABASE=DeskJet D4100 usb:v03F0p7717* ID_MODEL_FROM_DATABASE=CM8050 Color MFP with Edgeline Technology usb:v03F0p7804* ID_MODEL_FROM_DATABASE=DeskJet D1360 usb:v03F0p7817* ID_MODEL_FROM_DATABASE=Color LaserJet CP3505 usb:v03F0p7917* ID_MODEL_FROM_DATABASE=LaserJet M5025 MFP usb:v03F0p7A02* ID_MODEL_FROM_DATABASE=PhotoSmart M415 (PTP mode) usb:v03F0p7A04* ID_MODEL_FROM_DATABASE=DeskJet D2460 usb:v03F0p7A17* ID_MODEL_FROM_DATABASE=LaserJet M3027 MFP usb:v03F0p7B02* ID_MODEL_FROM_DATABASE=PhotoSmart M23 (PTP mode) usb:v03F0p7B17* ID_MODEL_FROM_DATABASE=Color LaserJet CP4005 usb:v03F0p7C17* ID_MODEL_FROM_DATABASE=Color LaserJet CM6040 series usb:v03F0p7D04* ID_MODEL_FROM_DATABASE=DeskJet F2100 Printer series usb:v03F0p7D17* ID_MODEL_FROM_DATABASE=Color LaserJet CM4730 MFP usb:v03F0p7E04* ID_MODEL_FROM_DATABASE=DeskJet F4100 Printer series usb:v03F0p8017* ID_MODEL_FROM_DATABASE=LaserJet P4515 usb:v03F0p8104* ID_MODEL_FROM_DATABASE=Printing Support usb:v03F0p8117* ID_MODEL_FROM_DATABASE=LaserJet P4015 usb:v03F0p811C* ID_MODEL_FROM_DATABASE=Ethernet HN210E usb:v03F0p8204* ID_MODEL_FROM_DATABASE=Printing Support usb:v03F0p8207* ID_MODEL_FROM_DATABASE=FHA-3510 2.4GHz Wireless Optical Mobile Mouse usb:v03F0p8217* ID_MODEL_FROM_DATABASE=LaserJet P4014 usb:v03F0p8317* ID_MODEL_FROM_DATABASE=LaserJet M9050 MFP usb:v03F0p8404* ID_MODEL_FROM_DATABASE=DeskJet 6800 series usb:v03F0p8417* ID_MODEL_FROM_DATABASE=LaserJet M9040 MFP usb:v03F0p8504* ID_MODEL_FROM_DATABASE=DeskJet 6600 series usb:v03F0p8604* ID_MODEL_FROM_DATABASE=DeskJet 5440 usb:v03F0p8607* ID_MODEL_FROM_DATABASE=Optical Mobile Mouse usb:v03F0p8704* ID_MODEL_FROM_DATABASE=DeskJet 5940 usb:v03F0p8711* ID_MODEL_FROM_DATABASE=Deskjet 2050 J510 usb:v03F0p8804* ID_MODEL_FROM_DATABASE=DeskJet 6980 series usb:v03F0p8904* ID_MODEL_FROM_DATABASE=DeskJet 6940 series usb:v03F0p8C07* ID_MODEL_FROM_DATABASE=Digital Stereo Headset usb:v03F0p8C11* ID_MODEL_FROM_DATABASE=Deskjet F4500 series usb:v03F0p9002* ID_MODEL_FROM_DATABASE=PhotoSmart M437 usb:v03F0p9102* ID_MODEL_FROM_DATABASE=PhotoSmart M537 usb:v03F0p9302* ID_MODEL_FROM_DATABASE=PhotoSmart R930 series usb:v03F0p9402* ID_MODEL_FROM_DATABASE=PhotoSmart R837 usb:v03F0p9502* ID_MODEL_FROM_DATABASE=PhotoSmart R840 series usb:v03F0p9602* ID_MODEL_FROM_DATABASE=PhotoSmart M730 series usb:v03F0p9702* ID_MODEL_FROM_DATABASE=PhotoSmart R740 series usb:v03F0p9802* ID_MODEL_FROM_DATABASE=PhotoSmart Mz60 series usb:v03F0p9902* ID_MODEL_FROM_DATABASE=PhotoSmart M630 series usb:v03F0p9A02* ID_MODEL_FROM_DATABASE=PhotoSmart E330 series usb:v03F0p9B02* ID_MODEL_FROM_DATABASE=PhotoSmart M540 series usb:v03F0p9B07* ID_MODEL_FROM_DATABASE=Portable Drive usb:v03F0p9C02* ID_MODEL_FROM_DATABASE=PhotoSmart M440 series usb:v03F0pA004* ID_MODEL_FROM_DATABASE=DeskJet 5850c usb:v03F0pA011* ID_MODEL_FROM_DATABASE=Deskjet 3050A usb:v03F0pB002* ID_MODEL_FROM_DATABASE=PhotoSmart 7200 series usb:v03F0pB102* ID_MODEL_FROM_DATABASE=PhotoSmart 7200 series usb:v03F0pB107* ID_MODEL_FROM_DATABASE=v255w/c310w Flash Drive usb:v03F0pB116* ID_MODEL_FROM_DATABASE=Webcam usb:v03F0pB202* ID_MODEL_FROM_DATABASE=PhotoSmart 7600 series usb:v03F0pB302* ID_MODEL_FROM_DATABASE=PhotoSmart 7600 series usb:v03F0pB402* ID_MODEL_FROM_DATABASE=PhotoSmart 7700 series usb:v03F0pB502* ID_MODEL_FROM_DATABASE=PhotoSmart 7700 series usb:v03F0pB602* ID_MODEL_FROM_DATABASE=PhotoSmart 7900 series usb:v03F0pB702* ID_MODEL_FROM_DATABASE=PhotoSmart 7900 series usb:v03F0pB802* ID_MODEL_FROM_DATABASE=PhotoSmart 7400 series usb:v03F0pB902* ID_MODEL_FROM_DATABASE=PhotoSmart 7800 series usb:v03F0pBA02* ID_MODEL_FROM_DATABASE=PhotoSmart 8100 series usb:v03F0pBB02* ID_MODEL_FROM_DATABASE=PhotoSmart 8400 series usb:v03F0pBC02* ID_MODEL_FROM_DATABASE=PhotoSmart 8700 series usb:v03F0pBD02* ID_MODEL_FROM_DATABASE=PhotoSmart Pro B9100 series usb:v03F0pBEF4* ID_MODEL_FROM_DATABASE=NEC Picty760 usb:v03F0pC002* ID_MODEL_FROM_DATABASE=PhotoSmart 7800 series usb:v03F0pC102* ID_MODEL_FROM_DATABASE=PhotoSmart 8000 series usb:v03F0pC111* ID_MODEL_FROM_DATABASE=Deskjet 1510 usb:v03F0pC202* ID_MODEL_FROM_DATABASE=PhotoSmart 8200 series usb:v03F0pC302* ID_MODEL_FROM_DATABASE=DeskJet D2300 usb:v03F0pC402* ID_MODEL_FROM_DATABASE=PhotoSmart D5100 series usb:v03F0pC502* ID_MODEL_FROM_DATABASE=PhotoSmart D6100 series usb:v03F0pC602* ID_MODEL_FROM_DATABASE=PhotoSmart D7100 series usb:v03F0pC702* ID_MODEL_FROM_DATABASE=PhotoSmart D7300 series usb:v03F0pC802* ID_MODEL_FROM_DATABASE=PhotoSmart D5060 Printer usb:v03F0pD104* ID_MODEL_FROM_DATABASE=Bluetooth Dongle usb:v03F0pD507* ID_MODEL_FROM_DATABASE=39gII [NW249AA] usb:v03F0pEFBE* ID_MODEL_FROM_DATABASE=NEC Picty900 usb:v03F0pF0BE* ID_MODEL_FROM_DATABASE=NEC Picty920 usb:v03F0pF1BE* ID_MODEL_FROM_DATABASE=NEC Picty800 usb:v03F1* ID_VENDOR_FROM_DATABASE=Genoa Technology usb:v03F2* ID_VENDOR_FROM_DATABASE=Oak Technology, Inc. usb:v03F3* ID_VENDOR_FROM_DATABASE=Adaptec, Inc. usb:v03F3p0020* ID_MODEL_FROM_DATABASE=AWN-8020 WLAN [Intersil PRISM 2.5] usb:v03F3p0080* ID_MODEL_FROM_DATABASE=AVC-1100 Audio Capture usb:v03F3p0083* ID_MODEL_FROM_DATABASE=AVC-2200 Device usb:v03F3p0087* ID_MODEL_FROM_DATABASE=AVC-2210 Loader usb:v03F3p0088* ID_MODEL_FROM_DATABASE=AVC-2210 Device usb:v03F3p008B* ID_MODEL_FROM_DATABASE=AVC-2310 Loader usb:v03F3p008C* ID_MODEL_FROM_DATABASE=AVC-2310 Device usb:v03F3p0094* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v03F3p009B* ID_MODEL_FROM_DATABASE=AVC-1410 GameBridge TV NTSC usb:v03F3p2000* ID_MODEL_FROM_DATABASE=USBXchange usb:v03F3p2001* ID_MODEL_FROM_DATABASE=USBXchange Adapter usb:v03F3p2002* ID_MODEL_FROM_DATABASE=USB2-Xchange usb:v03F3p2003* ID_MODEL_FROM_DATABASE=USB2-Xchange Adapter usb:v03F3p4000* ID_MODEL_FROM_DATABASE=4-port hub usb:v03F3pADCC* ID_MODEL_FROM_DATABASE=Composite Device Support usb:v03F4* ID_VENDOR_FROM_DATABASE=Diebold, Inc. usb:v03F5* ID_VENDOR_FROM_DATABASE=Siemens Electromechanical usb:v03F8* ID_VENDOR_FROM_DATABASE=Epson Imaging Technology Center usb:v03F9* ID_VENDOR_FROM_DATABASE=KeyTronic Corp. usb:v03F9p0100* ID_MODEL_FROM_DATABASE=KT-2001 Keyboard usb:v03F9p0101* ID_MODEL_FROM_DATABASE=Keyboard usb:v03F9p0102* ID_MODEL_FROM_DATABASE=Keyboard Mouse usb:v03FB* ID_VENDOR_FROM_DATABASE=OPTi, Inc. usb:v03FC* ID_VENDOR_FROM_DATABASE=Elitegroup Computer Systems usb:v03FD* ID_VENDOR_FROM_DATABASE=Xilinx, Inc. usb:v03FDp0008* ID_MODEL_FROM_DATABASE=Platform Cable USB II usb:v03FE* ID_VENDOR_FROM_DATABASE=Farallon Comunications usb:v0400* ID_VENDOR_FROM_DATABASE=National Semiconductor Corp. usb:v0400p05DC* ID_MODEL_FROM_DATABASE=Rigol Technologies DS1000USB Oscilloscope usb:v0400p0807* ID_MODEL_FROM_DATABASE=Bluetooth Dongle usb:v0400p080A* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0400p09C4* ID_MODEL_FROM_DATABASE=Rigol Technologies DG1022 Arbitrary Waveform Generator usb:v0400p1000* ID_MODEL_FROM_DATABASE=Mustek BearPaw 1200 Scanner usb:v0400p1001* ID_MODEL_FROM_DATABASE=Mustek BearPaw 2400 Scanner usb:v0400p1237* ID_MODEL_FROM_DATABASE=Hub usb:v0400pA000* ID_MODEL_FROM_DATABASE=Smart Display Reference Device usb:v0400pC359* ID_MODEL_FROM_DATABASE=Logitech Harmony usb:v0400pC35B* ID_MODEL_FROM_DATABASE=Printing Support usb:v0400pC55D* ID_MODEL_FROM_DATABASE=Rigol Technologies DS5000USB Oscilloscope usb:v0401* ID_VENDOR_FROM_DATABASE=National Registry, Inc. usb:v0402* ID_VENDOR_FROM_DATABASE=ALi Corp. usb:v0402p5462* ID_MODEL_FROM_DATABASE=M5462 IDE Controller usb:v0402p5602* ID_MODEL_FROM_DATABASE=M5602 Video Camera Controller usb:v0402p5603* ID_MODEL_FROM_DATABASE=M5603 Video Camera Controller usb:v0402p5606* ID_MODEL_FROM_DATABASE=M5606 Video Camera Controller [UVC] usb:v0402p5621* ID_MODEL_FROM_DATABASE=M5621 High-Speed IDE Controller usb:v0402p5623* ID_MODEL_FROM_DATABASE=M5623 Scanner Controller usb:v0402p5627* ID_MODEL_FROM_DATABASE=Welland ME-740PS USB2 3.5" Power Saving Enclosure usb:v0402p5632* ID_MODEL_FROM_DATABASE=M5632 Host-to-Host Link usb:v0402p5635* ID_MODEL_FROM_DATABASE=M5635 Flash Card Reader usb:v0402p5636* ID_MODEL_FROM_DATABASE=USB 2.0 Storage Device usb:v0402p5637* ID_MODEL_FROM_DATABASE=M5637 IDE Controller usb:v0402p5642* ID_MODEL_FROM_DATABASE=Storage Device usb:v0402p5661* ID_MODEL_FROM_DATABASE=M5661 MP3 player usb:v0402p5667* ID_MODEL_FROM_DATABASE=M5667 MP3 player usb:v0402p9665* ID_MODEL_FROM_DATABASE=Gateway Webcam usb:v0403* ID_VENDOR_FROM_DATABASE=Future Technology Devices International, Ltd usb:v0403p0000* ID_MODEL_FROM_DATABASE=H4SMK 7 Port Hub / Bricked Counterfeit FT232 Serial (UART) IC usb:v0403p0232* ID_MODEL_FROM_DATABASE=Serial Converter usb:v0403p1060* ID_MODEL_FROM_DATABASE=JTAG adapter usb:v0403p1234* ID_MODEL_FROM_DATABASE=IronLogic RFID Adapter [Z-2 USB] usb:v0403p1235* ID_MODEL_FROM_DATABASE=Iron Logic Z-397 RS-485/422 converter usb:v0403p6001* ID_MODEL_FROM_DATABASE=FT232 Serial (UART) IC usb:v0403p6002* ID_MODEL_FROM_DATABASE=Lumel PD12 usb:v0403p6007* ID_MODEL_FROM_DATABASE=Serial Converter usb:v0403p6008* ID_MODEL_FROM_DATABASE=Serial Converter usb:v0403p6009* ID_MODEL_FROM_DATABASE=Serial Converter usb:v0403p6010* ID_MODEL_FROM_DATABASE=FT2232C Dual USB-UART/FIFO IC usb:v0403p6011* ID_MODEL_FROM_DATABASE=FT4232H Quad HS USB-UART/FIFO IC usb:v0403p6014* ID_MODEL_FROM_DATABASE=FT232H Single HS USB-UART/FIFO IC usb:v0403p6015* ID_MODEL_FROM_DATABASE=Bridge(I2C/SPI/UART/FIFO) usb:v0403p8028* ID_MODEL_FROM_DATABASE=Dev board JTAG (FT232H based) usb:v0403p8040* ID_MODEL_FROM_DATABASE=4 Port Hub usb:v0403p8070* ID_MODEL_FROM_DATABASE=7 Port Hub usb:v0403p8140* ID_MODEL_FROM_DATABASE=Vehicle Explorer Interface usb:v0403p8210* ID_MODEL_FROM_DATABASE=MGTimer - MGCC (Vic) Timing System usb:v0403p8370* ID_MODEL_FROM_DATABASE=7 Port Hub usb:v0403p8371* ID_MODEL_FROM_DATABASE=PS/2 Keyboard And Mouse usb:v0403p8372* ID_MODEL_FROM_DATABASE=FT8U100AX Serial Port usb:v0403p8A28* ID_MODEL_FROM_DATABASE=Rainforest Automation ZigBee Controller usb:v0403p8A98* ID_MODEL_FROM_DATABASE=TIAO Multi-Protocol Adapter usb:v0403p8B28* ID_MODEL_FROM_DATABASE=Alpermann+Velte TCI70 usb:v0403p8B29* ID_MODEL_FROM_DATABASE=Alpermann+Velte TC60 CLS usb:v0403p8B2A* ID_MODEL_FROM_DATABASE=Alpermann+Velte Rubidium Q1 usb:v0403p8B2B* ID_MODEL_FROM_DATABASE=Alpermann+Velte TCD usb:v0403p8B2C* ID_MODEL_FROM_DATABASE=Alpermann+Velte TCC70 usb:v0403p9090* ID_MODEL_FROM_DATABASE=SNAP Stick 200 usb:v0403p9132* ID_MODEL_FROM_DATABASE=LCD and Temperature Interface usb:v0403p9133* ID_MODEL_FROM_DATABASE=CallerID usb:v0403p9135* ID_MODEL_FROM_DATABASE=Rotary Pub alarm usb:v0403p9136* ID_MODEL_FROM_DATABASE=Pulsecounter usb:v0403p9E90* ID_MODEL_FROM_DATABASE=Marvell OpenRD Base/Client usb:v0403p9F80* ID_MODEL_FROM_DATABASE=Ewert Energy Systems CANdapter usb:v0403pA6D0* ID_MODEL_FROM_DATABASE=Texas Instruments XDS100v2 JTAG / BeagleBone A3 usb:v0403pA951* ID_MODEL_FROM_DATABASE=HCP HIT GSM/GPRS modem [Cinterion MC55i] usb:v0403pA9A0* ID_MODEL_FROM_DATABASE=FT2232D - Dual UART/FIFO IC - FTDI usb:v0403pABB8* ID_MODEL_FROM_DATABASE=Lego Mindstorms NXTCam usb:v0403pB810* ID_MODEL_FROM_DATABASE=US Interface Navigator (CAT and 2nd PTT lines) usb:v0403pB811* ID_MODEL_FROM_DATABASE=US Interface Navigator (WKEY and FSK lines) usb:v0403pB812* ID_MODEL_FROM_DATABASE=US Interface Navigator (RS232 and CONFIG lines) usb:v0403pB9B0* ID_MODEL_FROM_DATABASE=Fujitsu SK-16FX-100PMC V1.1 usb:v0403pBAF8* ID_MODEL_FROM_DATABASE=Amontec JTAGkey usb:v0403pBCD8* ID_MODEL_FROM_DATABASE=Stellaris Development Board usb:v0403pBCD9* ID_MODEL_FROM_DATABASE=Stellaris Evaluation Board usb:v0403pBCDA* ID_MODEL_FROM_DATABASE=Stellaris ICDI Board usb:v0403pBDC8* ID_MODEL_FROM_DATABASE=Egnite GmbH - JTAG/RS-232 adapter usb:v0403pBFD8* ID_MODEL_FROM_DATABASE=OpenDCC usb:v0403pBFD9* ID_MODEL_FROM_DATABASE=OpenDCC (Sniffer) usb:v0403pBFDA* ID_MODEL_FROM_DATABASE=OpenDCC (Throttle) usb:v0403pBFDB* ID_MODEL_FROM_DATABASE=OpenDCC (Gateway) usb:v0403pBFDC* ID_MODEL_FROM_DATABASE=OpenDCC (GBM) usb:v0403pC630* ID_MODEL_FROM_DATABASE=lcd2usb interface usb:v0403pC631* ID_MODEL_FROM_DATABASE=i2c-tiny-usb interface usb:v0403pC632* ID_MODEL_FROM_DATABASE=xu1541 c64 floppy drive interface usb:v0403pC633* ID_MODEL_FROM_DATABASE=TinyCrypt dongle usb:v0403pC634* ID_MODEL_FROM_DATABASE=glcd2usb interface usb:v0403pC7D0* ID_MODEL_FROM_DATABASE=RR-CirKits LocoBuffer-USB usb:v0403pC8B8* ID_MODEL_FROM_DATABASE=Alpermann+Velte MTD TCU usb:v0403pC8B9* ID_MODEL_FROM_DATABASE=Alpermann+Velte MTD TCU 1HE usb:v0403pC8BA* ID_MODEL_FROM_DATABASE=Alpermann+Velte Rubidium H1 usb:v0403pC8BB* ID_MODEL_FROM_DATABASE=Alpermann+Velte Rubidium H3 usb:v0403pC8BC* ID_MODEL_FROM_DATABASE=Alpermann+Velte Rubidium S1 usb:v0403pC8BD* ID_MODEL_FROM_DATABASE=Alpermann+Velte Rubidium T1 usb:v0403pC8BE* ID_MODEL_FROM_DATABASE=Alpermann+Velte Rubidium D1 usb:v0403pC8BF* ID_MODEL_FROM_DATABASE=Alpermann+Velte TC60 RLV usb:v0403pCC48* ID_MODEL_FROM_DATABASE=Tactrix OpenPort 1.3 Mitsubishi usb:v0403pCC49* ID_MODEL_FROM_DATABASE=Tactrix OpenPort 1.3 Subaru usb:v0403pCC4A* ID_MODEL_FROM_DATABASE=Tactrix OpenPort 1.3 Universal usb:v0403pCFF8* ID_MODEL_FROM_DATABASE=Amontec JTAGkey usb:v0403pD010* ID_MODEL_FROM_DATABASE=SCS PTC-IIusb usb:v0403pD011* ID_MODEL_FROM_DATABASE=SCS Position-Tracker/TNC usb:v0403pD012* ID_MODEL_FROM_DATABASE=SCS DRAGON 1 usb:v0403pD013* ID_MODEL_FROM_DATABASE=SCS DRAGON 1 usb:v0403pD388* ID_MODEL_FROM_DATABASE=Xsens converter usb:v0403pD389* ID_MODEL_FROM_DATABASE=Xsens Wireless Receiver usb:v0403pD38A* ID_MODEL_FROM_DATABASE=Xsens serial converter usb:v0403pD38B* ID_MODEL_FROM_DATABASE=Xsens serial converter usb:v0403pD38C* ID_MODEL_FROM_DATABASE=Xsens Wireless Receiver usb:v0403pD38D* ID_MODEL_FROM_DATABASE=Xsens Awinda Station usb:v0403pD38E* ID_MODEL_FROM_DATABASE=Xsens serial converter usb:v0403pD38F* ID_MODEL_FROM_DATABASE=Xsens serial converter usb:v0403pD491* ID_MODEL_FROM_DATABASE=Zolix Omni 1509 monochromator usb:v0403pD578* ID_MODEL_FROM_DATABASE=Accesio USB-COM-4SM usb:v0403pD6F8* ID_MODEL_FROM_DATABASE=UNI Black BOX usb:v0403pD738* ID_MODEL_FROM_DATABASE=Propox JTAGcable II usb:v0403pD739* ID_MODEL_FROM_DATABASE=Propox ISPcable III usb:v0403pD9A9* ID_MODEL_FROM_DATABASE=Actisense USG-1 NMEA Serial Gateway usb:v0403pD9AA* ID_MODEL_FROM_DATABASE=Actisense NGT-1 NMEA2000 PC Interface usb:v0403pD9AB* ID_MODEL_FROM_DATABASE=Actisense NGT-1 NMEA2000 Gateway usb:v0403pDAF4* ID_MODEL_FROM_DATABASE=Qundis Serial Infrared Head usb:v0403pE0D0* ID_MODEL_FROM_DATABASE=Total Phase Aardvark I2C/SPI Host Adapter usb:v0403pE521* ID_MODEL_FROM_DATABASE=EVER Sinline XL Series UPS usb:v0403pE6C8* ID_MODEL_FROM_DATABASE=PYRAMID Computer GmbH LCD usb:v0403pE700* ID_MODEL_FROM_DATABASE=Elster Unicom III Optical Probe usb:v0403pE729* ID_MODEL_FROM_DATABASE=Segway Robotic Mobility Platforms 200 usb:v0403pE888* ID_MODEL_FROM_DATABASE=Expert ISDN Control USB usb:v0403pE889* ID_MODEL_FROM_DATABASE=USB-RS232 OptoBridge usb:v0403pE88A* ID_MODEL_FROM_DATABASE=Expert mouseCLOCK USB II usb:v0403pE88B* ID_MODEL_FROM_DATABASE=Precision Clock MSF USB usb:v0403pE88C* ID_MODEL_FROM_DATABASE=Expert mouseCLOCK USB II HBG usb:v0403pE8D8* ID_MODEL_FROM_DATABASE=Aaronia AG Spectran Spectrum Analyzer usb:v0403pE8DC* ID_MODEL_FROM_DATABASE=Aaronia AG UBBV Preamplifier usb:v0403pEA90* ID_MODEL_FROM_DATABASE=Eclo 1-Wire Adapter usb:v0403pECD9* ID_MODEL_FROM_DATABASE=miControl miCan-Stick usb:v0403pED71* ID_MODEL_FROM_DATABASE=HAMEG HO870 Serial Port usb:v0403pED72* ID_MODEL_FROM_DATABASE=HAMEG HO720 Serial Port usb:v0403pED73* ID_MODEL_FROM_DATABASE=HAMEG HO730 Serial Port usb:v0403pED74* ID_MODEL_FROM_DATABASE=HAMEG HO820 Serial Port usb:v0403pEF10* ID_MODEL_FROM_DATABASE=FT1245BL usb:v0403pF070* ID_MODEL_FROM_DATABASE=Serial Converter 422/485 [Vardaan VEUSB422R3] usb:v0403pF0C8* ID_MODEL_FROM_DATABASE=SPROG Decoder Programmer usb:v0403pF0C9* ID_MODEL_FROM_DATABASE=SPROG-DCC CAN-USB usb:v0403pF0E9* ID_MODEL_FROM_DATABASE=Tagsys L-P101 usb:v0403pF1A0* ID_MODEL_FROM_DATABASE=Asix PRESTO Programmer usb:v0403pF208* ID_MODEL_FROM_DATABASE=Papenmeier Braille-Display usb:v0403pF3C0* ID_MODEL_FROM_DATABASE=4N-GALAXY Serial Converter usb:v0403pF608* ID_MODEL_FROM_DATABASE=CTI USB-485-Mini usb:v0403pF60B* ID_MODEL_FROM_DATABASE=CTI USB-Nano-485 usb:v0403pF680* ID_MODEL_FROM_DATABASE=Suunto Sports Instrument usb:v0403pF758* ID_MODEL_FROM_DATABASE=GW Instek GDS-8x0 Oscilloscope usb:v0403pF7C0* ID_MODEL_FROM_DATABASE=ZeitControl Cardsystems TagTracer MIFARE usb:v0403pF850* ID_MODEL_FROM_DATABASE=USB-UIRT (Universal Infrared Receiver+Transmitter) usb:v0403pF918* ID_MODEL_FROM_DATABASE=Ant8 Logic Probe usb:v0403pFA00* ID_MODEL_FROM_DATABASE=Matrix Orbital USB Serial usb:v0403pFA01* ID_MODEL_FROM_DATABASE=Matrix Orbital MX2 or MX3 usb:v0403pFA02* ID_MODEL_FROM_DATABASE=Matrix Orbital MX4 or MX5 usb:v0403pFA03* ID_MODEL_FROM_DATABASE=Matrix Orbital VK/LK202 Family usb:v0403pFA04* ID_MODEL_FROM_DATABASE=Matrix Orbital VK/LK204 Family usb:v0403pFA20* ID_MODEL_FROM_DATABASE=Ross-Tech HEX-USB usb:v0403pFC08* ID_MODEL_FROM_DATABASE=Crystalfontz CFA-632 USB LCD usb:v0403pFC09* ID_MODEL_FROM_DATABASE=Crystalfontz CFA-634 USB LCD usb:v0403pFC0B* ID_MODEL_FROM_DATABASE=Crystalfontz CFA-633 USB LCD usb:v0403pFC0C* ID_MODEL_FROM_DATABASE=Crystalfontz CFA-631 USB LCD usb:v0403pFC0D* ID_MODEL_FROM_DATABASE=Crystalfontz CFA-635 USB LCD usb:v0403pFC82* ID_MODEL_FROM_DATABASE=SEMC DSS-20/DSS-25 SyncStation usb:v0403pFD48* ID_MODEL_FROM_DATABASE=ShipModul MiniPlex-4xUSB NMEA Multiplexer usb:v0403pFD49* ID_MODEL_FROM_DATABASE=ShipModul MiniPlex-4xUSB-AIS NMEA Multiplexer usb:v0403pFD4B* ID_MODEL_FROM_DATABASE=ShipModul MiniPlex NMEA Multiplexer usb:v0403pFF08* ID_MODEL_FROM_DATABASE=ToolHouse LoopBack Adapter usb:v0403pFF18* ID_MODEL_FROM_DATABASE=ScienceScope Logbook ML usb:v0403pFF19* ID_MODEL_FROM_DATABASE=Logbook Bus usb:v0403pFF1A* ID_MODEL_FROM_DATABASE=Logbook Bus usb:v0403pFF1B* ID_MODEL_FROM_DATABASE=Logbook Bus usb:v0403pFF1C* ID_MODEL_FROM_DATABASE=ScienceScope Logbook LS usb:v0403pFF1D* ID_MODEL_FROM_DATABASE=ScienceScope Logbook HS usb:v0403pFF1E* ID_MODEL_FROM_DATABASE=Logbook Bus usb:v0403pFF1F* ID_MODEL_FROM_DATABASE=Logbook Bus usb:v0404* ID_VENDOR_FROM_DATABASE=NCR Corp. usb:v0404p0202* ID_MODEL_FROM_DATABASE=78XX Scanner usb:v0404p0203* ID_MODEL_FROM_DATABASE=78XX Scanner - Embedded System usb:v0404p0310* ID_MODEL_FROM_DATABASE=K590 Printer, Self-Service usb:v0404p0311* ID_MODEL_FROM_DATABASE=7167 Printer, Receipt/Slip usb:v0404p0312* ID_MODEL_FROM_DATABASE=7197 Printer Receipt usb:v0404p0320* ID_MODEL_FROM_DATABASE=5932-USB Keyboard usb:v0404p0321* ID_MODEL_FROM_DATABASE=5953-USB Dynakey usb:v0404p0322* ID_MODEL_FROM_DATABASE=5932-USB Enhanced Keyboard usb:v0404p0323* ID_MODEL_FROM_DATABASE=5932-USB Enhanced Keyboard, Flash-Recovery/Download usb:v0404p0324* ID_MODEL_FROM_DATABASE=5953-USB Enhanced Dynakey usb:v0404p0325* ID_MODEL_FROM_DATABASE=5953-USB Enhanced Dynakey Flash-Recovery/Download usb:v0404p0328* ID_MODEL_FROM_DATABASE=K016: USB-MSR ISO 3-track MSR: POS Standard (See HID pages) usb:v0404p0329* ID_MODEL_FROM_DATABASE=K018: USB-MSR JIS 2-Track MSR: POS Standard usb:v0404p032A* ID_MODEL_FROM_DATABASE=K016: USB-MSR ISO 3-Track MSR: HID Keyboard Mode usb:v0404p032B* ID_MODEL_FROM_DATABASE=K016/K018: USB-MSR Flash-Recovery/Download usb:v0405* ID_VENDOR_FROM_DATABASE=Synopsys, Inc. usb:v0406* ID_VENDOR_FROM_DATABASE=Fujitsu-ICL Computers usb:v0407* ID_VENDOR_FROM_DATABASE=Fujitsu Personal Systems, Inc. usb:v0408* ID_VENDOR_FROM_DATABASE=Quanta Computer, Inc. usb:v0408p0103* ID_MODEL_FROM_DATABASE=FV TouchCam N1 (Audio) usb:v0408p030C* ID_MODEL_FROM_DATABASE=HP Webcam usb:v0408p03B2* ID_MODEL_FROM_DATABASE=HP Webcam usb:v0408p1030* ID_MODEL_FROM_DATABASE=FV TouchCam N1 (Video) usb:v0408p3000* ID_MODEL_FROM_DATABASE=Optical dual-touch panel usb:v0408p3001* ID_MODEL_FROM_DATABASE=Optical Touch Screen usb:v0409* ID_VENDOR_FROM_DATABASE=NEC Corp. usb:v0409p0011* ID_MODEL_FROM_DATABASE=PC98 Series Layout Keyboard Mouse usb:v0409p0012* ID_MODEL_FROM_DATABASE=ATerm IT75DSU ISDN TA usb:v0409p0014* ID_MODEL_FROM_DATABASE=Japanese Keyboard usb:v0409p0019* ID_MODEL_FROM_DATABASE=109 Japanese Keyboard with Bus-Powered Hub usb:v0409p001A* ID_MODEL_FROM_DATABASE=PC98 Series Layout Keyboard with Bus-Powered Hub usb:v0409p0025* ID_MODEL_FROM_DATABASE=Mini Keyboard with Bus-Powered Hub usb:v0409p0027* ID_MODEL_FROM_DATABASE=MultiSync Monitor usb:v0409p002C* ID_MODEL_FROM_DATABASE=Clik!-USB Drive usb:v0409p0034* ID_MODEL_FROM_DATABASE=109 Japanese Keyboard with One-touch start buttons usb:v0409p003F* ID_MODEL_FROM_DATABASE=Wireless Keyboard with One-touch start buttons usb:v0409p0040* ID_MODEL_FROM_DATABASE=Floppy usb:v0409p004E* ID_MODEL_FROM_DATABASE=SuperScript 1400 Series usb:v0409p004F* ID_MODEL_FROM_DATABASE=Wireless Keyboard with One-touch start buttons usb:v0409p0050* ID_MODEL_FROM_DATABASE=7-port hub usb:v0409p0058* ID_MODEL_FROM_DATABASE=HighSpeed Hub usb:v0409p0059* ID_MODEL_FROM_DATABASE=HighSpeed Hub usb:v0409p005A* ID_MODEL_FROM_DATABASE=HighSpeed Hub usb:v0409p006A* ID_MODEL_FROM_DATABASE=Conceptronic USB Harddisk Box usb:v0409p007D* ID_MODEL_FROM_DATABASE=MINICUBE2 usb:v0409p007E* ID_MODEL_FROM_DATABASE=PG-FP5 Flash Memory Programmer usb:v0409p0081* ID_MODEL_FROM_DATABASE=SuperScript 1400 Series usb:v0409p0082* ID_MODEL_FROM_DATABASE=SuperScript 1400 Series usb:v0409p0094* ID_MODEL_FROM_DATABASE=Japanese Keyboard with One-touch start buttons usb:v0409p0095* ID_MODEL_FROM_DATABASE=Japanese Keyboard usb:v0409p00A9* ID_MODEL_FROM_DATABASE=AtermIT21L 128K Support Standard usb:v0409p00AA* ID_MODEL_FROM_DATABASE=AtermITX72 128K Support Standard usb:v0409p00AB* ID_MODEL_FROM_DATABASE=AtermITX62 128K Support Standard usb:v0409p00AC* ID_MODEL_FROM_DATABASE=AtermIT42 128K Support Standard usb:v0409p00AE* ID_MODEL_FROM_DATABASE=INSMATEV70G-MAX Standard usb:v0409p00AF* ID_MODEL_FROM_DATABASE=AtermITX70 128K Support Standard usb:v0409p00B0* ID_MODEL_FROM_DATABASE=AtermITX80 128K Support Standard usb:v0409p00B2* ID_MODEL_FROM_DATABASE=AtermITX80D 128K Support Standard usb:v0409p00C0* ID_MODEL_FROM_DATABASE=Wireless Remocon usb:v0409p00F7* ID_MODEL_FROM_DATABASE=Smart Display PK-SD10 usb:v0409p011D* ID_MODEL_FROM_DATABASE=e228 Mobile Phone usb:v0409p0203* ID_MODEL_FROM_DATABASE=HID Audio Controls usb:v0409p021D* ID_MODEL_FROM_DATABASE=Aterm WL54SU2 802.11g Wireless Adapter [Atheros AR5523] usb:v0409p0248* ID_MODEL_FROM_DATABASE=Aterm PA-WL54GU usb:v0409p0249* ID_MODEL_FROM_DATABASE=Aterm WL300NU-G usb:v0409p02B4* ID_MODEL_FROM_DATABASE=Aterm WL300NU-AG usb:v0409p02B6* ID_MODEL_FROM_DATABASE=Aterm WL300NU-GS 802.11n Wireless Adapter usb:v0409p02BC* ID_MODEL_FROM_DATABASE=Computer Monitor usb:v0409p0300* ID_MODEL_FROM_DATABASE=LifeTouch Note usb:v0409p0301* ID_MODEL_FROM_DATABASE=LifeTouch Note (debug mode) usb:v0409p55AA* ID_MODEL_FROM_DATABASE=Hub usb:v0409p55AB* ID_MODEL_FROM_DATABASE=Hub [iMac/iTouch kbd] usb:v0409p8010* ID_MODEL_FROM_DATABASE=Intellibase Hub usb:v0409p8011* ID_MODEL_FROM_DATABASE=Intellibase Hub usb:v0409pEFBE* ID_MODEL_FROM_DATABASE=P!cty 900 [HP DJ] usb:v0409pF0BE* ID_MODEL_FROM_DATABASE=P!cty 920 [HP DJ 812c] usb:v040A* ID_VENDOR_FROM_DATABASE=Kodak Co. usb:v040Ap0001* ID_MODEL_FROM_DATABASE=DVC-323 usb:v040Ap0002* ID_MODEL_FROM_DATABASE=DVC-325 usb:v040Ap0100* ID_MODEL_FROM_DATABASE=DC-220 usb:v040Ap0110* ID_MODEL_FROM_DATABASE=DC-260 usb:v040Ap0111* ID_MODEL_FROM_DATABASE=DC-265 usb:v040Ap0112* ID_MODEL_FROM_DATABASE=DC-290 usb:v040Ap0120* ID_MODEL_FROM_DATABASE=DC-240 usb:v040Ap0121* ID_MODEL_FROM_DATABASE=DC-240 (PTP firmware) usb:v040Ap0130* ID_MODEL_FROM_DATABASE=DC-280 usb:v040Ap0131* ID_MODEL_FROM_DATABASE=DC-5000 usb:v040Ap0132* ID_MODEL_FROM_DATABASE=DC-3400 usb:v040Ap0140* ID_MODEL_FROM_DATABASE=DC-4800 usb:v040Ap0160* ID_MODEL_FROM_DATABASE=DC4800 usb:v040Ap0170* ID_MODEL_FROM_DATABASE=DX3900 usb:v040Ap0200* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0300* ID_MODEL_FROM_DATABASE=EZ-200 usb:v040Ap0400* ID_MODEL_FROM_DATABASE=MC3 usb:v040Ap0402* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0403* ID_MODEL_FROM_DATABASE=Z7590 usb:v040Ap0500* ID_MODEL_FROM_DATABASE=DX3500 usb:v040Ap0510* ID_MODEL_FROM_DATABASE=DX3600 usb:v040Ap0525* ID_MODEL_FROM_DATABASE=DX3215 usb:v040Ap0530* ID_MODEL_FROM_DATABASE=DX3700 usb:v040Ap0535* ID_MODEL_FROM_DATABASE=EasyShare CX4230 Camera usb:v040Ap0540* ID_MODEL_FROM_DATABASE=LS420 usb:v040Ap0550* ID_MODEL_FROM_DATABASE=DX4900 usb:v040Ap0555* ID_MODEL_FROM_DATABASE=DX4330 usb:v040Ap0560* ID_MODEL_FROM_DATABASE=CX4200 usb:v040Ap0565* ID_MODEL_FROM_DATABASE=CX4210 usb:v040Ap0566* ID_MODEL_FROM_DATABASE=CX4300 usb:v040Ap0567* ID_MODEL_FROM_DATABASE=LS753 usb:v040Ap0568* ID_MODEL_FROM_DATABASE=LS443 usb:v040Ap0569* ID_MODEL_FROM_DATABASE=LS663 usb:v040Ap0570* ID_MODEL_FROM_DATABASE=DX6340 usb:v040Ap0571* ID_MODEL_FROM_DATABASE=CX6330 usb:v040Ap0572* ID_MODEL_FROM_DATABASE=DX6440 usb:v040Ap0573* ID_MODEL_FROM_DATABASE=CX6230 usb:v040Ap0574* ID_MODEL_FROM_DATABASE=CX6200 usb:v040Ap0575* ID_MODEL_FROM_DATABASE=DX6490 usb:v040Ap0576* ID_MODEL_FROM_DATABASE=DX4530 usb:v040Ap0577* ID_MODEL_FROM_DATABASE=DX7630 usb:v040Ap0578* ID_MODEL_FROM_DATABASE=CX7300/CX7310 usb:v040Ap0579* ID_MODEL_FROM_DATABASE=CX7220 usb:v040Ap057A* ID_MODEL_FROM_DATABASE=CX7330 usb:v040Ap057B* ID_MODEL_FROM_DATABASE=CX7430 usb:v040Ap057C* ID_MODEL_FROM_DATABASE=CX7530 usb:v040Ap057D* ID_MODEL_FROM_DATABASE=DX7440 usb:v040Ap057E* ID_MODEL_FROM_DATABASE=C300 usb:v040Ap057F* ID_MODEL_FROM_DATABASE=DX7590 usb:v040Ap0580* ID_MODEL_FROM_DATABASE=Z730 usb:v040Ap0581* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0582* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0583* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0584* ID_MODEL_FROM_DATABASE=CX6445 usb:v040Ap0585* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0586* ID_MODEL_FROM_DATABASE=CX7525 usb:v040Ap0587* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0588* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0589* ID_MODEL_FROM_DATABASE=EasyShare C360 usb:v040Ap058A* ID_MODEL_FROM_DATABASE=C310 usb:v040Ap058B* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap058C* ID_MODEL_FROM_DATABASE=C330 usb:v040Ap058D* ID_MODEL_FROM_DATABASE=C340 usb:v040Ap058E* ID_MODEL_FROM_DATABASE=V530 usb:v040Ap058F* ID_MODEL_FROM_DATABASE=V550 usb:v040Ap0590* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0591* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0592* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0593* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0594* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0595* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0596* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0597* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap0598* ID_MODEL_FROM_DATABASE=EASYSHARE M1033 digital camera usb:v040Ap0599* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap059A* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap059B* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap059C* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap059D* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap059E* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap059F* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05A0* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05A1* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05A2* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05A3* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05A4* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05A5* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05A6* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05A7* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05A8* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05A9* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05AA* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05AB* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05AC* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05AD* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05AE* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05AF* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05B0* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05B1* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05B2* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05B3* ID_MODEL_FROM_DATABASE=EasyShare Z710 Camera usb:v040Ap05B4* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05B5* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05B6* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05B7* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05B8* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05B9* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05BA* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05BB* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05BC* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05BD* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05BE* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05BF* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05C0* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05C1* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05C2* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05C3* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05C4* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05C5* ID_MODEL_FROM_DATABASE=Digital Camera usb:v040Ap05C8* ID_MODEL_FROM_DATABASE=EASYSHARE Z1485 IS Digital Camera usb:v040Ap05D3* ID_MODEL_FROM_DATABASE=EasyShare M320 Camera usb:v040Ap05D4* ID_MODEL_FROM_DATABASE=EasyShare C180 Digital Camera usb:v040Ap1001* ID_MODEL_FROM_DATABASE=EasyShare SV811 Digital Picture Frame usb:v040Ap4000* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v040Ap4021* ID_MODEL_FROM_DATABASE=Photo Printer 6800 usb:v040Ap4022* ID_MODEL_FROM_DATABASE=1400 Digital Photo Printer usb:v040Ap402B* ID_MODEL_FROM_DATABASE=Photo Printer 6850 usb:v040Ap402E* ID_MODEL_FROM_DATABASE=605 Photo Printer usb:v040Ap4034* ID_MODEL_FROM_DATABASE=805 Photo Printer usb:v040Ap404F* ID_MODEL_FROM_DATABASE=305 Photo Printer usb:v040Ap4056* ID_MODEL_FROM_DATABASE=ESP 7200 Series AiO usb:v040Ap4109* ID_MODEL_FROM_DATABASE=EasyShare Printer Dock Series 3 usb:v040Ap410D* ID_MODEL_FROM_DATABASE=EasyShare G600 Printer Dock usb:v040Ap5010* ID_MODEL_FROM_DATABASE=Wireless Adapter usb:v040Ap5012* ID_MODEL_FROM_DATABASE=DBT-220 Bluetooth Adapter usb:v040Ap6001* ID_MODEL_FROM_DATABASE=i30 usb:v040Ap6002* ID_MODEL_FROM_DATABASE=i40 usb:v040Ap6003* ID_MODEL_FROM_DATABASE=i50 usb:v040Ap6004* ID_MODEL_FROM_DATABASE=i60 usb:v040Ap6005* ID_MODEL_FROM_DATABASE=i80 usb:v040Ap6029* ID_MODEL_FROM_DATABASE=i900 usb:v040Ap602A* ID_MODEL_FROM_DATABASE=i900 usb:v040B* ID_VENDOR_FROM_DATABASE=Weltrend Semiconductor usb:v040Bp0A68* ID_MODEL_FROM_DATABASE=Func MS-3 gaming mouse [WT6573F MCU] usb:v040Bp6510* ID_MODEL_FROM_DATABASE=Weltrend Bar Code Reader usb:v040Bp6520* ID_MODEL_FROM_DATABASE=XBOX Xploder usb:v040Bp6533* ID_MODEL_FROM_DATABASE=Speed-Link Competition Pro usb:v040Bp6543* ID_MODEL_FROM_DATABASE=Manhattan Magnetic Card Strip Reader usb:v040C* ID_VENDOR_FROM_DATABASE=VTech Computers, Ltd usb:v040D* ID_VENDOR_FROM_DATABASE=VIA Technologies, Inc. usb:v040Dp3184* ID_MODEL_FROM_DATABASE=VNT VT6656 USB-802.11 Wireless LAN Adapter usb:v040Dp6205* ID_MODEL_FROM_DATABASE=USB 2.0 Card Reader usb:v040E* ID_VENDOR_FROM_DATABASE=MCCI usb:v040F* ID_VENDOR_FROM_DATABASE=Echo Speech Corp. usb:v0411* ID_VENDOR_FROM_DATABASE=BUFFALO INC. (formerly MelCo., Inc.) usb:v0411p0001* ID_MODEL_FROM_DATABASE=LUA-TX Ethernet [pegasus] usb:v0411p0005* ID_MODEL_FROM_DATABASE=LUA-TX Ethernet usb:v0411p0006* ID_MODEL_FROM_DATABASE=WLI-USB-L11 Wireless LAN Adapter usb:v0411p0009* ID_MODEL_FROM_DATABASE=LUA2-TX Ethernet usb:v0411p000B* ID_MODEL_FROM_DATABASE=WLI-USB-L11G-WR Wireless LAN Adapter usb:v0411p000D* ID_MODEL_FROM_DATABASE=WLI-USB-L11G Wireless LAN Adapter usb:v0411p0012* ID_MODEL_FROM_DATABASE=LUA-KTX Ethernet usb:v0411p0013* ID_MODEL_FROM_DATABASE=USB2-IDE Adapter usb:v0411p0016* ID_MODEL_FROM_DATABASE=WLI-USB-S11 802.11b Adapter usb:v0411p0018* ID_MODEL_FROM_DATABASE=USB2-IDE Adapter usb:v0411p001C* ID_MODEL_FROM_DATABASE=USB-IDE Bridge: DUB-PxxG usb:v0411p0027* ID_MODEL_FROM_DATABASE=WLI-USB-KS11G 802.11b Adapter usb:v0411p002A* ID_MODEL_FROM_DATABASE=SMSC USB97C202 "HD-HB300V2-EU" usb:v0411p003D* ID_MODEL_FROM_DATABASE=LUA-U2-KTX Ethernet usb:v0411p0044* ID_MODEL_FROM_DATABASE=WLI-USB-KB11 Wireless LAN Adapter usb:v0411p004B* ID_MODEL_FROM_DATABASE=WLI-USB-G54 802.11g Adapter [Broadcom 4320 USB] usb:v0411p004D* ID_MODEL_FROM_DATABASE=WLI-USB-B11 Wireless LAN Adapter usb:v0411p0050* ID_MODEL_FROM_DATABASE=WLI2-USB2-G54 Wireless LAN Adapter usb:v0411p005E* ID_MODEL_FROM_DATABASE=WLI-U2-KG54-YB WLAN usb:v0411p0065* ID_MODEL_FROM_DATABASE=Python2 WDM Encoder usb:v0411p0066* ID_MODEL_FROM_DATABASE=WLI-U2-KG54 WLAN usb:v0411p0067* ID_MODEL_FROM_DATABASE=WLI-U2-KG54-AI WLAN usb:v0411p006E* ID_MODEL_FROM_DATABASE=LUA-U2-GT 10/100/1000 Ethernet Adapter usb:v0411p0089* ID_MODEL_FROM_DATABASE=RUF-C/U2 Flash Drive usb:v0411p008B* ID_MODEL_FROM_DATABASE=Nintendo Wi-Fi usb:v0411p0091* ID_MODEL_FROM_DATABASE=WLI-U2-KAMG54 Wireless LAN Adapter usb:v0411p0092* ID_MODEL_FROM_DATABASE=WLI-U2-KAMG54 Bootloader usb:v0411p0097* ID_MODEL_FROM_DATABASE=WLI-U2-KG54-BB usb:v0411p00A9* ID_MODEL_FROM_DATABASE=WLI-U2-AMG54HP Wireless LAN Adapter usb:v0411p00AA* ID_MODEL_FROM_DATABASE=WLI-U2-AMG54HP Bootloader usb:v0411p00B3* ID_MODEL_FROM_DATABASE=PC-OP-RS1 RemoteStation usb:v0411p00BC* ID_MODEL_FROM_DATABASE=WLI-U2-KG125S 802.11g Adapter [Broadcom 4320 USB] usb:v0411p00CA* ID_MODEL_FROM_DATABASE=802.11n Network Adapter usb:v0411p00CB* ID_MODEL_FROM_DATABASE=WLI-U2-G300N 802.11n Adapter usb:v0411p00D8* ID_MODEL_FROM_DATABASE=WLI-U2-SG54HP usb:v0411p00D9* ID_MODEL_FROM_DATABASE=WLI-U2-G54HP usb:v0411p00DA* ID_MODEL_FROM_DATABASE=WLI-U2-KG54L 802.11bg [ZyDAS ZD1211B] usb:v0411p00DB* ID_MODEL_FROM_DATABASE=External Hard Drive HD-PF32OU2 [Buffalo Ministation] usb:v0411p00E8* ID_MODEL_FROM_DATABASE=WLI-UC-G300N Wireless LAN Adapter [Ralink RT2870] usb:v0411p0105* ID_MODEL_FROM_DATABASE=External Hard Drive HD-CEU2 [Drive Station] usb:v0411p012C* ID_MODEL_FROM_DATABASE=SATA Bridge usb:v0411p012E* ID_MODEL_FROM_DATABASE=WLI-UC-AG300N Wireless LAN Adapter usb:v0411p0148* ID_MODEL_FROM_DATABASE=WLI-UC-G300HP Wireless LAN Adapter usb:v0411p0150* ID_MODEL_FROM_DATABASE=WLP-UC-AG300 Wireless LAN Adapter usb:v0411p0157* ID_MODEL_FROM_DATABASE=External Hard Drive HD-PEU2 usb:v0411p0158* ID_MODEL_FROM_DATABASE=WLI-UC-GNHP Wireless LAN Adapter usb:v0411p015D* ID_MODEL_FROM_DATABASE=WLI-UC-GN Wireless LAN Adapter [Ralink RT3070] usb:v0411p016F* ID_MODEL_FROM_DATABASE=WLI-UC-G301N Wireless LAN Adapter [Ralink RT3072] usb:v0411p017F* ID_MODEL_FROM_DATABASE=Sony UWA-BR100 802.11abgn Wireless Adapter [Atheros AR7010+AR9280] usb:v0411p019E* ID_MODEL_FROM_DATABASE=WLI-UC-GNP Wireless LAN Adapter usb:v0411p01A1* ID_MODEL_FROM_DATABASE=MiniStation Metro usb:v0411p01A2* ID_MODEL_FROM_DATABASE=WLI-UC-GNM Wireless LAN Adapter [Ralink RT8070] usb:v0411p01DC* ID_MODEL_FROM_DATABASE=Ultra-Slim Portable DVD Writer (DVSM-PC58U2V) usb:v0411p01DE* ID_MODEL_FROM_DATABASE=External Hard Drive HD-PCTU3 [Buffalo MiniStation] usb:v0411p01EE* ID_MODEL_FROM_DATABASE=WLI-UC-GNM2 Wireless LAN Adapter [Ralink RT3070] usb:v0411p01F1* ID_MODEL_FROM_DATABASE=SATA Adapter [HD-LBU3] usb:v0411p01FD* ID_MODEL_FROM_DATABASE=WLI-UC-G450 Wireless LAN Adapter usb:v0412* ID_VENDOR_FROM_DATABASE=Award Software International usb:v0413* ID_VENDOR_FROM_DATABASE=Leadtek Research, Inc. usb:v0413p1310* ID_MODEL_FROM_DATABASE=WinFast TV - NTSC + FM usb:v0413p1311* ID_MODEL_FROM_DATABASE=WinFast TV - NTSC + MTS + FM usb:v0413p1312* ID_MODEL_FROM_DATABASE=WinFast TV - PAL BG + FM usb:v0413p1313* ID_MODEL_FROM_DATABASE=WinFast TV - PAL BG+TXT + FM usb:v0413p1314* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL I usb:v0413p1315* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL I+TXT usb:v0413p1316* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL DK usb:v0413p1317* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL DK+TXT usb:v0413p1318* ID_MODEL_FROM_DATABASE=WinFast TV - PAL I/DK + FM usb:v0413p1319* ID_MODEL_FROM_DATABASE=WinFast TV - PAL N + FM usb:v0413p131A* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP SECAM LL usb:v0413p131B* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP SECAM LL+TXT usb:v0413p131C* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP SECAM DK usb:v0413p131D* ID_MODEL_FROM_DATABASE=WinFast TV - SECAM DK + TXT + FM usb:v0413p131E* ID_MODEL_FROM_DATABASE=WinFast TV - NTSC Japan + FM usb:v0413p1320* ID_MODEL_FROM_DATABASE=WinFast TV - NTSC usb:v0413p1321* ID_MODEL_FROM_DATABASE=WinFast TV - NTSC + MTS usb:v0413p1322* ID_MODEL_FROM_DATABASE=WinFast TV - PAL BG usb:v0413p1323* ID_MODEL_FROM_DATABASE=WinFast TV - PAL BG+TXT usb:v0413p1324* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL I usb:v0413p1325* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL I+TXT usb:v0413p1326* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL DK usb:v0413p1327* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL DK+TXT usb:v0413p1328* ID_MODEL_FROM_DATABASE=WinFast TV - PAL I/DK usb:v0413p1329* ID_MODEL_FROM_DATABASE=WinFast TV - PAL N usb:v0413p132A* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP SECAM LL usb:v0413p132B* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP SECAM LL+TXT usb:v0413p132C* ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP SECAM DK usb:v0413p132D* ID_MODEL_FROM_DATABASE=WinFast TV - SECAM DK + TXT usb:v0413p132E* ID_MODEL_FROM_DATABASE=WinFast TV - NTSC Japan usb:v0413p6023* ID_MODEL_FROM_DATABASE=EMP Audio Device usb:v0413p6024* ID_MODEL_FROM_DATABASE=WinFast PalmTop/Novo TV Video usb:v0413p6025* ID_MODEL_FROM_DATABASE=WinFast DTV Dongle (cold state) usb:v0413p6026* ID_MODEL_FROM_DATABASE=WinFast DTV Dongle (warm state) usb:v0413p6029* ID_MODEL_FROM_DATABASE=WinFast DTV Dongle Gold usb:v0413p6125* ID_MODEL_FROM_DATABASE=WinFast DTV Dongle usb:v0413p6126* ID_MODEL_FROM_DATABASE=WinFast DTV Dongle BDA Driver usb:v0413p6A03* ID_MODEL_FROM_DATABASE=RTL2832 [WinFast DTV Dongle Mini] usb:v0413p6F00* ID_MODEL_FROM_DATABASE=WinFast DTV Dongle (STK7700P based) usb:v0414* ID_VENDOR_FROM_DATABASE=Giga-Byte Technology Co., Ltd usb:v0416* ID_VENDOR_FROM_DATABASE=Winbond Electronics Corp. usb:v0416p0035* ID_MODEL_FROM_DATABASE=W89C35 802.11bg WLAN Adapter usb:v0416p0101* ID_MODEL_FROM_DATABASE=Hub usb:v0416p0961* ID_MODEL_FROM_DATABASE=AVL Flash Card Reader usb:v0416p3810* ID_MODEL_FROM_DATABASE=Smart Card Controller usb:v0416p3811* ID_MODEL_FROM_DATABASE=Generic Controller - Single interface usb:v0416p3812* ID_MODEL_FROM_DATABASE=Smart Card Controller_2Interface usb:v0416p3813* ID_MODEL_FROM_DATABASE=Panel Display usb:v0416p5011* ID_MODEL_FROM_DATABASE=Virtual Com Port usb:v0416p5518* ID_MODEL_FROM_DATABASE=4-Port Hub usb:v0416p551A* ID_MODEL_FROM_DATABASE=PC Sync Keypad usb:v0416p551B* ID_MODEL_FROM_DATABASE=PC Async Keypad usb:v0416p551C* ID_MODEL_FROM_DATABASE=Sync Tenkey usb:v0416p551D* ID_MODEL_FROM_DATABASE=Async Tenkey usb:v0416p551E* ID_MODEL_FROM_DATABASE=Keyboard usb:v0416p551F* ID_MODEL_FROM_DATABASE=Keyboard w/ Sys and Media usb:v0416p5521* ID_MODEL_FROM_DATABASE=Keyboard usb:v0416p6481* ID_MODEL_FROM_DATABASE=16-bit Scanner usb:v0416p7721* ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer usb:v0416p7722* ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer usb:v0416p7723* ID_MODEL_FROM_DATABASE=SD Card Reader usb:v0417* ID_VENDOR_FROM_DATABASE=Symbios Logic usb:v0418* ID_VENDOR_FROM_DATABASE=AST Research usb:v0419* ID_VENDOR_FROM_DATABASE=Samsung Info. Systems America, Inc. usb:v0419p0001* ID_MODEL_FROM_DATABASE=IrDA Remote Controller / Creative Cordless Mouse usb:v0419p0600* ID_MODEL_FROM_DATABASE=Desktop Wireless 6000 usb:v0419p3001* ID_MODEL_FROM_DATABASE=Xerox P1202 Laser Printer usb:v0419p3003* ID_MODEL_FROM_DATABASE=Olivetti PG L12L usb:v0419p3201* ID_MODEL_FROM_DATABASE=Docuprint P8ex usb:v0419p3404* ID_MODEL_FROM_DATABASE=SCX-5x12 series usb:v0419p3406* ID_MODEL_FROM_DATABASE=MFP 830 series usb:v0419p3407* ID_MODEL_FROM_DATABASE=ML-912 usb:v0419p3601* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v0419p3602* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v0419p4602* ID_MODEL_FROM_DATABASE=Remote NDIS Network Device usb:v0419p8001* ID_MODEL_FROM_DATABASE=Hub usb:v0419p8002* ID_MODEL_FROM_DATABASE=SyncMaster HID Monitor Control usb:v0419pAA03* ID_MODEL_FROM_DATABASE=SDAS-3 MP3 Player usb:v041A* ID_VENDOR_FROM_DATABASE=Phoenix Technologies, Ltd usb:v041B* ID_VENDOR_FROM_DATABASE=d'TV usb:v041D* ID_VENDOR_FROM_DATABASE=S3, Inc. usb:v041E* ID_VENDOR_FROM_DATABASE=Creative Technology, Ltd usb:v041Ep1002* ID_MODEL_FROM_DATABASE=Nomad II usb:v041Ep1003* ID_MODEL_FROM_DATABASE=Blaster GamePad Cobra usb:v041Ep1050* ID_MODEL_FROM_DATABASE=GamePad Cobra usb:v041Ep1053* ID_MODEL_FROM_DATABASE=Mouse Gamer HD7600L usb:v041Ep200C* ID_MODEL_FROM_DATABASE=MuVo V100 usb:v041Ep2020* ID_MODEL_FROM_DATABASE=Zen X-Fi 2 usb:v041Ep2029* ID_MODEL_FROM_DATABASE=ZiiO usb:v041Ep2801* ID_MODEL_FROM_DATABASE=Prodikeys PC-MIDI multifunction keyboard usb:v041Ep3000* ID_MODEL_FROM_DATABASE=SoundBlaster Extigy usb:v041Ep3002* ID_MODEL_FROM_DATABASE=SB External Composite Device usb:v041Ep3010* ID_MODEL_FROM_DATABASE=SoundBlaster MP3+ usb:v041Ep3014* ID_MODEL_FROM_DATABASE=SB External Composite Device usb:v041Ep3015* ID_MODEL_FROM_DATABASE=Sound Blaster Digital Music LX usb:v041Ep3020* ID_MODEL_FROM_DATABASE=SoundBlaster Audigy 2 NX usb:v041Ep3030* ID_MODEL_FROM_DATABASE=SB External Composite Device usb:v041Ep3040* ID_MODEL_FROM_DATABASE=SoundBlaster Live! 24-bit External SB0490 usb:v041Ep3060* ID_MODEL_FROM_DATABASE=Sound Blaster Audigy 2 ZS External usb:v041Ep3061* ID_MODEL_FROM_DATABASE=SoundBlaster Audigy 2 ZS Video Editor usb:v041Ep3090* ID_MODEL_FROM_DATABASE=Sound Blaster Digital Music SX usb:v041Ep30D3* ID_MODEL_FROM_DATABASE=Sound Blaster Play! usb:v041Ep3100* ID_MODEL_FROM_DATABASE=IR Receiver (SB0540) usb:v041Ep3121* ID_MODEL_FROM_DATABASE=WoW tap chat usb:v041Ep3220* ID_MODEL_FROM_DATABASE=Sound Blaster Tactic(3D) Sigma sound card usb:v041Ep3F00* ID_MODEL_FROM_DATABASE=E-Mu Xboard 25 MIDI Controller usb:v041Ep3F02* ID_MODEL_FROM_DATABASE=E-Mu 0202 usb:v041Ep3F04* ID_MODEL_FROM_DATABASE=E-Mu 0404 usb:v041Ep3F07* ID_MODEL_FROM_DATABASE=E-Mu Xmidi 1x1 usb:v041Ep4003* ID_MODEL_FROM_DATABASE=VideoBlaster Webcam Go Plus [W9967CF] usb:v041Ep4004* ID_MODEL_FROM_DATABASE=Nomad II MG usb:v041Ep4005* ID_MODEL_FROM_DATABASE=Webcam Blaster Go ES usb:v041Ep4007* ID_MODEL_FROM_DATABASE=Go Mini usb:v041Ep400A* ID_MODEL_FROM_DATABASE=PC-Cam 300 usb:v041Ep400B* ID_MODEL_FROM_DATABASE=PC-Cam 600 usb:v041Ep400C* ID_MODEL_FROM_DATABASE=Webcam 5 [pwc] usb:v041Ep400D* ID_MODEL_FROM_DATABASE=Webcam PD1001 usb:v041Ep400F* ID_MODEL_FROM_DATABASE=PC-CAM 550 (Composite) usb:v041Ep4011* ID_MODEL_FROM_DATABASE=Webcam PRO eX usb:v041Ep4012* ID_MODEL_FROM_DATABASE=PC-CAM350 usb:v041Ep4013* ID_MODEL_FROM_DATABASE=PC-Cam 750 usb:v041Ep4015* ID_MODEL_FROM_DATABASE=CardCam Value usb:v041Ep4016* ID_MODEL_FROM_DATABASE=CardCam usb:v041Ep4017* ID_MODEL_FROM_DATABASE=Webcam Mobile [PD1090] usb:v041Ep4018* ID_MODEL_FROM_DATABASE=Webcam Vista [PD1100] usb:v041Ep4019* ID_MODEL_FROM_DATABASE=Audio Device usb:v041Ep401A* ID_MODEL_FROM_DATABASE=Webcam Vista [PD1100] usb:v041Ep401C* ID_MODEL_FROM_DATABASE=Webcam NX [PD1110] usb:v041Ep401D* ID_MODEL_FROM_DATABASE=Webcam NX Ultra usb:v041Ep401E* ID_MODEL_FROM_DATABASE=Webcam NX Pro usb:v041Ep401F* ID_MODEL_FROM_DATABASE=Webcam Notebook [PD1171] usb:v041Ep4020* ID_MODEL_FROM_DATABASE=Webcam NX usb:v041Ep4021* ID_MODEL_FROM_DATABASE=Webcam NX Ultra usb:v041Ep4022* ID_MODEL_FROM_DATABASE=Webcam NX Pro usb:v041Ep4028* ID_MODEL_FROM_DATABASE=Vista Plus cam [VF0090] usb:v041Ep4029* ID_MODEL_FROM_DATABASE=Webcam Live! usb:v041Ep402F* ID_MODEL_FROM_DATABASE=DC-CAM 3000Z usb:v041Ep4034* ID_MODEL_FROM_DATABASE=Webcam Instant usb:v041Ep4035* ID_MODEL_FROM_DATABASE=Webcam Instant usb:v041Ep4036* ID_MODEL_FROM_DATABASE=Webcam Live!/Live! Pro usb:v041Ep4037* ID_MODEL_FROM_DATABASE=Webcam Live! usb:v041Ep4038* ID_MODEL_FROM_DATABASE=ORITE CCD Webcam [PC370R] usb:v041Ep4039* ID_MODEL_FROM_DATABASE=Webcam Live! Effects usb:v041Ep403A* ID_MODEL_FROM_DATABASE=Webcam NX Pro 2 usb:v041Ep403B* ID_MODEL_FROM_DATABASE=Creative Webcam Vista [VF0010] usb:v041Ep403C* ID_MODEL_FROM_DATABASE=Webcam Live! Ultra usb:v041Ep403D* ID_MODEL_FROM_DATABASE=Webcam Notebook Ultra usb:v041Ep403E* ID_MODEL_FROM_DATABASE=Webcam Vista Plus usb:v041Ep4041* ID_MODEL_FROM_DATABASE=Webcam Live! Motion usb:v041Ep4043* ID_MODEL_FROM_DATABASE=Vibra Plus Webcam usb:v041Ep4045* ID_MODEL_FROM_DATABASE=Live! Cam Voice usb:v041Ep4049* ID_MODEL_FROM_DATABASE=Live! Cam Voice usb:v041Ep4051* ID_MODEL_FROM_DATABASE=Live! Cam Notebook Pro [VF0250] usb:v041Ep4052* ID_MODEL_FROM_DATABASE=Live! Cam Vista IM usb:v041Ep4053* ID_MODEL_FROM_DATABASE=Live! Cam Video IM usb:v041Ep4054* ID_MODEL_FROM_DATABASE=Live! Cam Video IM usb:v041Ep4055* ID_MODEL_FROM_DATABASE=Live! Cam Video IM Pro usb:v041Ep4056* ID_MODEL_FROM_DATABASE=Live! Cam Video IM Pro usb:v041Ep4057* ID_MODEL_FROM_DATABASE=Live! Cam Optia usb:v041Ep4058* ID_MODEL_FROM_DATABASE=Live! Cam Optia AF usb:v041Ep405F* ID_MODEL_FROM_DATABASE=WebCam Vista (VF0330) usb:v041Ep4061* ID_MODEL_FROM_DATABASE=Live! Cam Notebook Pro [VF0400] usb:v041Ep4063* ID_MODEL_FROM_DATABASE=Live! Cam Video IM Pro usb:v041Ep4068* ID_MODEL_FROM_DATABASE=Live! Cam Notebook [VF0470] usb:v041Ep406C* ID_MODEL_FROM_DATABASE=Live! Cam Sync [VF0520] usb:v041Ep4083* ID_MODEL_FROM_DATABASE=Live! Cam Socialize [VF0640] usb:v041Ep4087* ID_MODEL_FROM_DATABASE=Live! Cam Socialize HD 1080 [VF0680] usb:v041Ep4088* ID_MODEL_FROM_DATABASE=Live! Cam Chat HD [VF0700] usb:v041Ep4095* ID_MODEL_FROM_DATABASE=Live! Cam Sync HD [VF0770] usb:v041Ep4100* ID_MODEL_FROM_DATABASE=Nomad Jukebox 2 usb:v041Ep4101* ID_MODEL_FROM_DATABASE=Nomad Jukebox 3 usb:v041Ep4102* ID_MODEL_FROM_DATABASE=NOMAD MuVo^2 usb:v041Ep4106* ID_MODEL_FROM_DATABASE=Nomad MuVo usb:v041Ep4107* ID_MODEL_FROM_DATABASE=NOMAD MuVo usb:v041Ep4108* ID_MODEL_FROM_DATABASE=Nomad Jukebox Zen usb:v041Ep4109* ID_MODEL_FROM_DATABASE=Nomad Jukebox Zen NX usb:v041Ep410B* ID_MODEL_FROM_DATABASE=Nomad Jukebox Zen USB 2.0 usb:v041Ep410C* ID_MODEL_FROM_DATABASE=Nomad MuVo NX usb:v041Ep410F* ID_MODEL_FROM_DATABASE=NOMAD MuVo^2 (Flash) usb:v041Ep4110* ID_MODEL_FROM_DATABASE=Nomad Jukebox Zen Xtra usb:v041Ep4111* ID_MODEL_FROM_DATABASE=Dell Digital Jukebox usb:v041Ep4116* ID_MODEL_FROM_DATABASE=MuVo^2 usb:v041Ep4117* ID_MODEL_FROM_DATABASE=Nomad MuVo TX usb:v041Ep411B* ID_MODEL_FROM_DATABASE=Zen Touch usb:v041Ep411C* ID_MODEL_FROM_DATABASE=Nomad MuVo USB 2.0 usb:v041Ep411D* ID_MODEL_FROM_DATABASE=Zen usb:v041Ep411E* ID_MODEL_FROM_DATABASE=Zen Micro usb:v041Ep4120* ID_MODEL_FROM_DATABASE=Nomad MuVo TX FM usb:v041Ep4123* ID_MODEL_FROM_DATABASE=Zen Portable Media Center usb:v041Ep4124* ID_MODEL_FROM_DATABASE=MuVo^2 FM (uHDD) usb:v041Ep4126* ID_MODEL_FROM_DATABASE=Dell DJ (2nd gen) usb:v041Ep4127* ID_MODEL_FROM_DATABASE=Dell DJ usb:v041Ep4128* ID_MODEL_FROM_DATABASE=NOMAD Jukebox Zen Xtra (mtp) usb:v041Ep412B* ID_MODEL_FROM_DATABASE=MuVo N200 with FM radio usb:v041Ep412F* ID_MODEL_FROM_DATABASE=Dell Digital Jukebox 2.Gen usb:v041Ep4130* ID_MODEL_FROM_DATABASE=Zen Micro (mtp) usb:v041Ep4131* ID_MODEL_FROM_DATABASE=DAP-HD0014 [Zen Touch] (MTP) usb:v041Ep4133* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v041Ep4134* ID_MODEL_FROM_DATABASE=Zen Neeon usb:v041Ep4136* ID_MODEL_FROM_DATABASE=Zen Sleek usb:v041Ep4137* ID_MODEL_FROM_DATABASE=Zen Sleek (mtp) usb:v041Ep4139* ID_MODEL_FROM_DATABASE=Zen Nano Plus usb:v041Ep413C* ID_MODEL_FROM_DATABASE=Zen MicroPhoto usb:v041Ep4150* ID_MODEL_FROM_DATABASE=Zen V (MTP) usb:v041Ep4151* ID_MODEL_FROM_DATABASE=Zen Vision:M (mtp) usb:v041Ep4152* ID_MODEL_FROM_DATABASE=Zen V Plus usb:v041Ep4153* ID_MODEL_FROM_DATABASE=Zen Vision W usb:v041Ep4154* ID_MODEL_FROM_DATABASE=Zen Stone usb:v041Ep4155* ID_MODEL_FROM_DATABASE=Zen Stone plus usb:v041Ep4157* ID_MODEL_FROM_DATABASE=Zen (MTP) usb:v041Ep500F* ID_MODEL_FROM_DATABASE=Broadband Blaster 8012U-V usb:v041Ep5015* ID_MODEL_FROM_DATABASE=TECOM Bluetooth Device usb:v041EpFFFF* ID_MODEL_FROM_DATABASE=Webcam Live! Ultra usb:v041F* ID_VENDOR_FROM_DATABASE=LCS Telegraphics usb:v0420* ID_VENDOR_FROM_DATABASE=Chips and Technologies usb:v0420p1307* ID_MODEL_FROM_DATABASE=Celly SIM Card Reader usb:v0421* ID_VENDOR_FROM_DATABASE=Nokia Mobile Phones usb:v0421p0001* ID_MODEL_FROM_DATABASE=E61i (PC Suite mode) usb:v0421p0018* ID_MODEL_FROM_DATABASE=6288 GSM Smartphone usb:v0421p0019* ID_MODEL_FROM_DATABASE=6288 GSM Smartphone (imaging mode) usb:v0421p001A* ID_MODEL_FROM_DATABASE=6288 GSM Smartphone (file transfer mode) usb:v0421p0024* ID_MODEL_FROM_DATABASE=5610 XpressMusic (Storage mode) usb:v0421p0025* ID_MODEL_FROM_DATABASE=5610 XpressMusic (PC Suite mode) usb:v0421p0028* ID_MODEL_FROM_DATABASE=5610 XpressMusic (Imaging mode) usb:v0421p002D* ID_MODEL_FROM_DATABASE=6120 Phone (Mass storage mode) usb:v0421p002E* ID_MODEL_FROM_DATABASE=6120 Phone (Media-Player mode) usb:v0421p002F* ID_MODEL_FROM_DATABASE=6120 Phone (PC-Suite mode) usb:v0421p0042* ID_MODEL_FROM_DATABASE=E51 (PC Suite mode) usb:v0421p0064* ID_MODEL_FROM_DATABASE=3109c GSM Phone usb:v0421p006B* ID_MODEL_FROM_DATABASE=5310 Xpress Music (PC Suite mode) usb:v0421p006C* ID_MODEL_FROM_DATABASE=5310 Xpress music (Storage mode) usb:v0421p006D* ID_MODEL_FROM_DATABASE=N95 (Storage mode) usb:v0421p006E* ID_MODEL_FROM_DATABASE=N95 (Multimedia mode) usb:v0421p006F* ID_MODEL_FROM_DATABASE=N95 (Printing mode) usb:v0421p0070* ID_MODEL_FROM_DATABASE=N95 (PC Suite mode) usb:v0421p0096* ID_MODEL_FROM_DATABASE=N810 Internet Tablet usb:v0421p00AA* ID_MODEL_FROM_DATABASE=E71 (Mass storage mode) usb:v0421p00AB* ID_MODEL_FROM_DATABASE=E71 (PC Suite mode) usb:v0421p00E4* ID_MODEL_FROM_DATABASE=E71 (Media transfer mode) usb:v0421p0103* ID_MODEL_FROM_DATABASE=ADL Flashing Engine AVALON Parent usb:v0421p0104* ID_MODEL_FROM_DATABASE=ADL Re-Flashing Engine Parent usb:v0421p0105* ID_MODEL_FROM_DATABASE=Nokia Firmware Upgrade Mode usb:v0421p0106* ID_MODEL_FROM_DATABASE=ROM Parent usb:v0421p0154* ID_MODEL_FROM_DATABASE=5800 XpressMusic (PC Suite mode) usb:v0421p0155* ID_MODEL_FROM_DATABASE=5800 XpressMusic (Multimedia mode) usb:v0421p0156* ID_MODEL_FROM_DATABASE=5800 XpressMusic (Storage mode) usb:v0421p0157* ID_MODEL_FROM_DATABASE=5800 XpressMusic (Imaging mode) usb:v0421p0199* ID_MODEL_FROM_DATABASE=6700 Classic (msc) usb:v0421p019A* ID_MODEL_FROM_DATABASE=6700 Classic (PC Suite) usb:v0421p019B* ID_MODEL_FROM_DATABASE=6700 Classic (mtp) usb:v0421p01B0* ID_MODEL_FROM_DATABASE=6303 classic Phone (PC Suite mode) usb:v0421p01B1* ID_MODEL_FROM_DATABASE=6303 classic Phone (Mass storage mode) usb:v0421p01B2* ID_MODEL_FROM_DATABASE=6303 classic Phone (Printing and media mode) usb:v0421p01C7* ID_MODEL_FROM_DATABASE=N900 (Storage Mode) usb:v0421p01C8* ID_MODEL_FROM_DATABASE=N900 (PC-Suite Mode) usb:v0421p0228* ID_MODEL_FROM_DATABASE=5530 XpressMusic usb:v0421p023A* ID_MODEL_FROM_DATABASE=6730 Classic usb:v0421p026A* ID_MODEL_FROM_DATABASE=N97 (mass storage) usb:v0421p026B* ID_MODEL_FROM_DATABASE=N97 (Multimedia) usb:v0421p026C* ID_MODEL_FROM_DATABASE=N97 (PC Suite) usb:v0421p026D* ID_MODEL_FROM_DATABASE=N97 (Pictures) usb:v0421p0295* ID_MODEL_FROM_DATABASE=660i/6600i Slide Phone (Mass Storage) usb:v0421p0297* ID_MODEL_FROM_DATABASE=660i/6600i Slide Phone (Still Image) usb:v0421p02E1* ID_MODEL_FROM_DATABASE=5230 (Storage mode) usb:v0421p02E2* ID_MODEL_FROM_DATABASE=5230 (Multimedia mode) usb:v0421p02E3* ID_MODEL_FROM_DATABASE=5230 (PC-Suite mode) usb:v0421p02E4* ID_MODEL_FROM_DATABASE=5230 (Imaging mode) usb:v0421p0360* ID_MODEL_FROM_DATABASE=C1-01 Ovi Suite Mode usb:v0421p0396* ID_MODEL_FROM_DATABASE=C7-00 (Modem mode) usb:v0421p03A4* ID_MODEL_FROM_DATABASE=C5 (Storage mode) usb:v0421p03C0* ID_MODEL_FROM_DATABASE=C7-00 (Mass storage mode) usb:v0421p03C1* ID_MODEL_FROM_DATABASE=C7-00 (Media transfer mode) usb:v0421p03CD* ID_MODEL_FROM_DATABASE=C7-00 (Nokia Suite mode) usb:v0421p03D1* ID_MODEL_FROM_DATABASE=N950 usb:v0421p0400* ID_MODEL_FROM_DATABASE=7600 Phone Parent usb:v0421p0401* ID_MODEL_FROM_DATABASE=6650 GSM Phone usb:v0421p0402* ID_MODEL_FROM_DATABASE=6255 Phone Parent usb:v0421p0404* ID_MODEL_FROM_DATABASE=5510 usb:v0421p0405* ID_MODEL_FROM_DATABASE=9500 GSM Communicator usb:v0421p0407* ID_MODEL_FROM_DATABASE=Music Player HDR-1(tm) usb:v0421p040B* ID_MODEL_FROM_DATABASE=N-Gage GSM Phone usb:v0421p040D* ID_MODEL_FROM_DATABASE=6620 Phone Parent usb:v0421p040E* ID_MODEL_FROM_DATABASE=6651 Phone Parent usb:v0421p040F* ID_MODEL_FROM_DATABASE=6230 GSM Phone usb:v0421p0410* ID_MODEL_FROM_DATABASE=6630 Imaging Smartphone usb:v0421p0411* ID_MODEL_FROM_DATABASE=7610 Phone Parent usb:v0421p0413* ID_MODEL_FROM_DATABASE=6260 Phone Parent usb:v0421p0414* ID_MODEL_FROM_DATABASE=7370 usb:v0421p0415* ID_MODEL_FROM_DATABASE=9300 GSM Smartphone usb:v0421p0416* ID_MODEL_FROM_DATABASE=6170 Phone Parent usb:v0421p0417* ID_MODEL_FROM_DATABASE=7270 Phone Parent usb:v0421p0418* ID_MODEL_FROM_DATABASE=E70 (PC Suite mode) usb:v0421p0419* ID_MODEL_FROM_DATABASE=E60 (PC Suite mode) usb:v0421p041A* ID_MODEL_FROM_DATABASE=9500 GSM Communicator (RNDIS) usb:v0421p041B* ID_MODEL_FROM_DATABASE=9300 GSM Smartphone (RNDIS) usb:v0421p041C* ID_MODEL_FROM_DATABASE=7710 Phone Parent usb:v0421p041D* ID_MODEL_FROM_DATABASE=6670 Phone Parent usb:v0421p041E* ID_MODEL_FROM_DATABASE=6680 usb:v0421p041F* ID_MODEL_FROM_DATABASE=6235 Phone Parent usb:v0421p0421* ID_MODEL_FROM_DATABASE=3230 Phone Parent usb:v0421p0422* ID_MODEL_FROM_DATABASE=6681 Phone Parent usb:v0421p0423* ID_MODEL_FROM_DATABASE=6682 Phone Parent usb:v0421p0428* ID_MODEL_FROM_DATABASE=6230i Modem usb:v0421p0429* ID_MODEL_FROM_DATABASE=6230i MultiMedia Card usb:v0421p0431* ID_MODEL_FROM_DATABASE=770 Internet Tablet usb:v0421p0432* ID_MODEL_FROM_DATABASE=N90 Phone Parent usb:v0421p0435* ID_MODEL_FROM_DATABASE=E70 (IP Passthrough/RNDIS mode) usb:v0421p0436* ID_MODEL_FROM_DATABASE=E60 (IP Passthrough/RNDIS mode) usb:v0421p0437* ID_MODEL_FROM_DATABASE=6265 Phone Parent usb:v0421p043A* ID_MODEL_FROM_DATABASE=N70 USB Phone Parent usb:v0421p043B* ID_MODEL_FROM_DATABASE=3155 Phone Parent usb:v0421p043C* ID_MODEL_FROM_DATABASE=6155 Phone Parent usb:v0421p043D* ID_MODEL_FROM_DATABASE=6270 Phone Parent usb:v0421p0443* ID_MODEL_FROM_DATABASE=N70 Phone Parent usb:v0421p0444* ID_MODEL_FROM_DATABASE=N91 usb:v0421p044C* ID_MODEL_FROM_DATABASE=NM850iG Phone Parent usb:v0421p044D* ID_MODEL_FROM_DATABASE=E61 (PC Suite mode) usb:v0421p044E* ID_MODEL_FROM_DATABASE=E61 (Data Exchange mode) usb:v0421p044F* ID_MODEL_FROM_DATABASE=E61 (IP Passthrough/RNDIS mode) usb:v0421p0453* ID_MODEL_FROM_DATABASE=9300 Phone Parent usb:v0421p0456* ID_MODEL_FROM_DATABASE=6111 Phone Parent usb:v0421p0457* ID_MODEL_FROM_DATABASE=6111 Phone (Printing mode) usb:v0421p045A* ID_MODEL_FROM_DATABASE=6280 Phone Parent usb:v0421p045D* ID_MODEL_FROM_DATABASE=6282 Phone Parent usb:v0421p046E* ID_MODEL_FROM_DATABASE=6110 Navigator usb:v0421p0471* ID_MODEL_FROM_DATABASE=6110 Navigator usb:v0421p0485* ID_MODEL_FROM_DATABASE=MTP Device usb:v0421p04B9* ID_MODEL_FROM_DATABASE=5300 usb:v0421p04BC* ID_MODEL_FROM_DATABASE=5200 (Nokia mode) usb:v0421p04BD* ID_MODEL_FROM_DATABASE=5200 (Storage mode) usb:v0421p04BE* ID_MODEL_FROM_DATABASE=5200 (MTP mode) usb:v0421p04C3* ID_MODEL_FROM_DATABASE=N800 Internet Tablet usb:v0421p04CE* ID_MODEL_FROM_DATABASE=E90 Communicator (PC Suite mode) usb:v0421p04CF* ID_MODEL_FROM_DATABASE=E90 Communicator (Storage mode) usb:v0421p04F0* ID_MODEL_FROM_DATABASE=Nokia N95 (PC Suite mode) usb:v0421p04F9* ID_MODEL_FROM_DATABASE=6300 (PC Suite mode) usb:v0421p0508* ID_MODEL_FROM_DATABASE=E65 (PC Suite mode) usb:v0421p0509* ID_MODEL_FROM_DATABASE=E65 (Storage mode) usb:v0421p0518* ID_MODEL_FROM_DATABASE=N9 Phone usb:v0421p054D* ID_MODEL_FROM_DATABASE=C2-01 usb:v0421p0600* ID_MODEL_FROM_DATABASE=Digital Pen SU-1B usb:v0421p0610* ID_MODEL_FROM_DATABASE=CS-15 (Internet Stick 3G modem) usb:v0421p0661* ID_MODEL_FROM_DATABASE=Lumia 620/920 usb:v0421p069A* ID_MODEL_FROM_DATABASE=130 [RM-1035] (Charging only) usb:v0421p0720* ID_MODEL_FROM_DATABASE=X (RM-980) usb:v0421p0800* ID_MODEL_FROM_DATABASE=Connectivity Cable DKU-5 usb:v0421p0801* ID_MODEL_FROM_DATABASE=Data Cable DKU-6 usb:v0421p0802* ID_MODEL_FROM_DATABASE=CA-42 Phone Parent usb:v0422* ID_VENDOR_FROM_DATABASE=ADI Systems, Inc. usb:v0423* ID_VENDOR_FROM_DATABASE=Computer Access Technology Corp. usb:v0423p000A* ID_MODEL_FROM_DATABASE=NetMate Ethernet usb:v0423p000C* ID_MODEL_FROM_DATABASE=NetMate2 Ethernet usb:v0423p000D* ID_MODEL_FROM_DATABASE=USB Chief Analyzer usb:v0423p0100* ID_MODEL_FROM_DATABASE=Generic Universal Protocol Analyzer usb:v0423p0101* ID_MODEL_FROM_DATABASE=UPA USBTracer usb:v0423p0200* ID_MODEL_FROM_DATABASE=Generic 10K Universal Protocol Analyzer usb:v0423p020A* ID_MODEL_FROM_DATABASE=PETracer ML usb:v0423p0300* ID_MODEL_FROM_DATABASE=Generic Universal Protocol Analyzer usb:v0423p0301* ID_MODEL_FROM_DATABASE=2500H Tracer Trainer usb:v0423p030A* ID_MODEL_FROM_DATABASE=PETracer x1 usb:v0423p1237* ID_MODEL_FROM_DATABASE=Andromeda Hub usb:v0424* ID_VENDOR_FROM_DATABASE=Standard Microsystems Corp. usb:v0424p0001* ID_MODEL_FROM_DATABASE=Integrated Hub usb:v0424p0ACD* ID_MODEL_FROM_DATABASE=Sitecom Internal Multi Memory reader/writer MD-005 usb:v0424p0FDC* ID_MODEL_FROM_DATABASE=Floppy usb:v0424p10CD* ID_MODEL_FROM_DATABASE=Sitecom Internal Multi Memory reader/writer MD-005 usb:v0424p2020* ID_MODEL_FROM_DATABASE=USB Hub usb:v0424p20CD* ID_MODEL_FROM_DATABASE=Sitecom Internal Multi Memory reader/writer MD-005 usb:v0424p20FC* ID_MODEL_FROM_DATABASE=6-in-1 Card Reader usb:v0424p2134* ID_MODEL_FROM_DATABASE=Hub usb:v0424p2228* ID_MODEL_FROM_DATABASE=9-in-2 Card Reader usb:v0424p223A* ID_MODEL_FROM_DATABASE=8-in-1 Card Reader usb:v0424p2503* ID_MODEL_FROM_DATABASE=USB 2.0 Hub usb:v0424p2504* ID_MODEL_FROM_DATABASE=USB 2.0 Hub usb:v0424p2507* ID_MODEL_FROM_DATABASE=hub usb:v0424p2512* ID_MODEL_FROM_DATABASE=USB 2.0 Hub usb:v0424p2513* ID_MODEL_FROM_DATABASE=2.0 Hub usb:v0424p2514* ID_MODEL_FROM_DATABASE=USB 2.0 Hub usb:v0424p2517* ID_MODEL_FROM_DATABASE=Hub usb:v0424p2524* ID_MODEL_FROM_DATABASE=USB MultiSwitch Hub usb:v0424p2602* ID_MODEL_FROM_DATABASE=USB 2.0 Hub usb:v0424p2640* ID_MODEL_FROM_DATABASE=USB 2.0 Hub usb:v0424p2660* ID_MODEL_FROM_DATABASE=Hub usb:v0424p4060* ID_MODEL_FROM_DATABASE=Ultra Fast Media Reader usb:v0424p4064* ID_MODEL_FROM_DATABASE=Ultra Fast Media Reader usb:v0424p5434* ID_MODEL_FROM_DATABASE=Hub usb:v0424p5534* ID_MODEL_FROM_DATABASE=Hub usb:v0424p7500* ID_MODEL_FROM_DATABASE=LAN7500 Ethernet 10/100/1000 Adapter usb:v0424p9512* ID_MODEL_FROM_DATABASE=SMC9512/9514 USB Hub usb:v0424p9514* ID_MODEL_FROM_DATABASE=SMC9514 Hub usb:v0424pA700* ID_MODEL_FROM_DATABASE=2 Port Hub usb:v0424pEC00* ID_MODEL_FROM_DATABASE=SMSC9512/9514 Fast Ethernet Adapter usb:v0425* ID_VENDOR_FROM_DATABASE=Motorola Semiconductors HK, Ltd usb:v0425p0101* ID_MODEL_FROM_DATABASE=G-Tech Wireless Mouse & Keyboard usb:v0425pF102* ID_MODEL_FROM_DATABASE=G-Tech U+P Wireless Mouse usb:v0426* ID_VENDOR_FROM_DATABASE=Integrated Device Technology, Inc. usb:v0426p0426* ID_MODEL_FROM_DATABASE=WDM Driver usb:v0427* ID_VENDOR_FROM_DATABASE=Motorola Electronics Taiwan, Ltd usb:v0428* ID_VENDOR_FROM_DATABASE=Advanced Gravis Computer Tech, Ltd usb:v0428p4001* ID_MODEL_FROM_DATABASE=GamePad Pro usb:v0429* ID_VENDOR_FROM_DATABASE=Cirrus Logic usb:v042A* ID_VENDOR_FROM_DATABASE=Ericsson Austrian, AG usb:v042B* ID_VENDOR_FROM_DATABASE=Intel Corp. usb:v042Bp9316* ID_MODEL_FROM_DATABASE=8x931Hx Customer Hub usb:v042C* ID_VENDOR_FROM_DATABASE=Innovative Semiconductors, Inc. usb:v042D* ID_VENDOR_FROM_DATABASE=Micronics usb:v042E* ID_VENDOR_FROM_DATABASE=Acer, Inc. usb:v042Ep0380* ID_MODEL_FROM_DATABASE=MP3 Player usb:v042F* ID_VENDOR_FROM_DATABASE=Molex, Inc. usb:v0430* ID_VENDOR_FROM_DATABASE=Sun Microsystems, Inc. usb:v0430p0002* ID_MODEL_FROM_DATABASE=109 Keyboard usb:v0430p0005* ID_MODEL_FROM_DATABASE=Type 6 Keyboard usb:v0430p000A* ID_MODEL_FROM_DATABASE=109 Japanese Keyboard usb:v0430p000B* ID_MODEL_FROM_DATABASE=109 Japanese Keyboard usb:v0430p0082* ID_MODEL_FROM_DATABASE=109 Japanese Keyboard usb:v0430p0083* ID_MODEL_FROM_DATABASE=109 Japanese Keyboard usb:v0430p00A2* ID_MODEL_FROM_DATABASE=Type 7 Keyboard usb:v0430p0100* ID_MODEL_FROM_DATABASE=3-button Mouse usb:v0430p100E* ID_MODEL_FROM_DATABASE=24.1" LCD Monitor v4 / FID-638 Mouse usb:v0430p36BA* ID_MODEL_FROM_DATABASE=Bus Powered Hub usb:v0430pA101* ID_MODEL_FROM_DATABASE=remote key/mouse for P3 chip usb:v0430pA102* ID_MODEL_FROM_DATABASE=remote key/mouse/storage for P3 chip usb:v0430pA103* ID_MODEL_FROM_DATABASE=remote storage for P3 chip usb:v0430pA4A2* ID_MODEL_FROM_DATABASE=Ethernet (RNDIS and CDC ethernet) usb:v0430pCDAB* ID_MODEL_FROM_DATABASE=Raritan KVM dongle usb:v0431* ID_VENDOR_FROM_DATABASE=Itac Systems, Inc. usb:v0431p0100* ID_MODEL_FROM_DATABASE=Mouse-Trak 3-button Track Ball usb:v0432* ID_VENDOR_FROM_DATABASE=Unisys Corp. usb:v0433* ID_VENDOR_FROM_DATABASE=Alps Electric, Inc. usb:v0433p1101* ID_MODEL_FROM_DATABASE=IBM Game Controller usb:v0433pABAB* ID_MODEL_FROM_DATABASE=Keyboard usb:v0434* ID_VENDOR_FROM_DATABASE=Samsung Info. Systems America, Inc. usb:v0435* ID_VENDOR_FROM_DATABASE=Hyundai Electronics America usb:v0436* ID_VENDOR_FROM_DATABASE=Taugagreining HF usb:v0436p0005* ID_MODEL_FROM_DATABASE=CameraMate (DPCM_USB) usb:v0437* ID_VENDOR_FROM_DATABASE=Framatome Connectors USA usb:v0438* ID_VENDOR_FROM_DATABASE=Advanced Micro Devices, Inc. usb:v0439* ID_VENDOR_FROM_DATABASE=Voice Technologies Group usb:v043D* ID_VENDOR_FROM_DATABASE=Lexmark International, Inc. usb:v043Dp0001* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp0002* ID_MODEL_FROM_DATABASE=Optra E310 Printer usb:v043Dp0003* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp0004* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp0005* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp0006* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp0007* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp0008* ID_MODEL_FROM_DATABASE=Inkjet Color Printer usb:v043Dp0009* ID_MODEL_FROM_DATABASE=Optra S2450 Printer usb:v043Dp000A* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp000B* ID_MODEL_FROM_DATABASE=Inkjet Color Printer usb:v043Dp000C* ID_MODEL_FROM_DATABASE=Optra E312 Printer usb:v043Dp000D* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp000E* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp000F* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp0010* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp0011* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp0012* ID_MODEL_FROM_DATABASE=Inkjet Color Printer usb:v043Dp0013* ID_MODEL_FROM_DATABASE=Inkjet Color Printer usb:v043Dp0014* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0015* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0016* ID_MODEL_FROM_DATABASE=Z12 Color Jetprinter usb:v043Dp0017* ID_MODEL_FROM_DATABASE=Z32 printer usb:v043Dp0018* ID_MODEL_FROM_DATABASE=Z52 Printer usb:v043Dp0019* ID_MODEL_FROM_DATABASE=Forms Printer usb:v043Dp001A* ID_MODEL_FROM_DATABASE=Z65 Printer usb:v043Dp001B* ID_MODEL_FROM_DATABASE=InkJet Photo Printer usb:v043Dp001C* ID_MODEL_FROM_DATABASE=Kodak Personal Picture Maker 200 Printer usb:v043Dp001D* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp001E* ID_MODEL_FROM_DATABASE=InkJet Photo Printer usb:v043Dp001F* ID_MODEL_FROM_DATABASE=Kodak Personal Picture Maker 200 Card Reader usb:v043Dp0020* ID_MODEL_FROM_DATABASE=Z51 Printer usb:v043Dp0021* ID_MODEL_FROM_DATABASE=Z33 Printer usb:v043Dp0022* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0023* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp0024* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp0025* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0026* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0027* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0028* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0029* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp002A* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp002B* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp002C* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp002D* ID_MODEL_FROM_DATABASE=X70/X73 Scan/Print/Copy usb:v043Dp002E* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp002F* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0030* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0031* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0032* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0033* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0034* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0035* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0036* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0037* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0038* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0039* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp003A* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp003B* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp003C* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp003D* ID_MODEL_FROM_DATABASE=X83 Scan/Print/Copy usb:v043Dp003E* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp003F* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0040* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0041* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0042* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0043* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0044* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0045* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0046* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0047* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0048* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp0049* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp004A* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp004B* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp004C* ID_MODEL_FROM_DATABASE=Scan Print Copy usb:v043Dp004D* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp004E* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp004F* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0050* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0051* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp0052* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp0053* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0054* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0057* ID_MODEL_FROM_DATABASE=Z35 Printer usb:v043Dp0058* ID_MODEL_FROM_DATABASE=Laser Printer usb:v043Dp005A* ID_MODEL_FROM_DATABASE=X63 usb:v043Dp005C* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0060* ID_MODEL_FROM_DATABASE=X74/X75 Scanner usb:v043Dp0061* ID_MODEL_FROM_DATABASE=X74 Hub usb:v043Dp0065* ID_MODEL_FROM_DATABASE=X5130 usb:v043Dp0069* ID_MODEL_FROM_DATABASE=X74/X75 Printer usb:v043Dp006D* ID_MODEL_FROM_DATABASE=X125 usb:v043Dp006E* ID_MODEL_FROM_DATABASE=C510 usb:v043Dp0072* ID_MODEL_FROM_DATABASE=X6170 Printer usb:v043Dp0073* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0078* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp0079* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp007A* ID_MODEL_FROM_DATABASE=Generic Hub usb:v043Dp007B* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp007C* ID_MODEL_FROM_DATABASE=X1110/X1130/X1140/X1150/X1170/X1180/X1185 usb:v043Dp007D* ID_MODEL_FROM_DATABASE=Photo 3150 usb:v043Dp008A* ID_MODEL_FROM_DATABASE=4200 series usb:v043Dp008B* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp008C* ID_MODEL_FROM_DATABASE=to CF/SM/SD/MS Card Reader usb:v043Dp008E* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp008F* ID_MODEL_FROM_DATABASE=X422 usb:v043Dp0093* ID_MODEL_FROM_DATABASE=X5250 usb:v043Dp0095* ID_MODEL_FROM_DATABASE=E220 Printer usb:v043Dp0096* ID_MODEL_FROM_DATABASE=2200 series usb:v043Dp0097* ID_MODEL_FROM_DATABASE=P6250 usb:v043Dp0098* ID_MODEL_FROM_DATABASE=7100 series usb:v043Dp009E* ID_MODEL_FROM_DATABASE=P910 series Human Interface Device usb:v043Dp009F* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp00A9* ID_MODEL_FROM_DATABASE=IBM Infoprint 1410 MFP usb:v043Dp00AB* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp00B2* ID_MODEL_FROM_DATABASE=3300 series usb:v043Dp00B8* ID_MODEL_FROM_DATABASE=7300 series usb:v043Dp00B9* ID_MODEL_FROM_DATABASE=8300 series usb:v043Dp00BA* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp00BB* ID_MODEL_FROM_DATABASE=2300 series usb:v043Dp00BD* ID_MODEL_FROM_DATABASE=Printing Support usb:v043Dp00BE* ID_MODEL_FROM_DATABASE=Printing Support usb:v043Dp00BF* ID_MODEL_FROM_DATABASE=Printing Support usb:v043Dp00C0* ID_MODEL_FROM_DATABASE=6300 series usb:v043Dp00C1* ID_MODEL_FROM_DATABASE=4300 series usb:v043Dp00C7* ID_MODEL_FROM_DATABASE=Printing Support usb:v043Dp00C8* ID_MODEL_FROM_DATABASE=Printing Support usb:v043Dp00C9* ID_MODEL_FROM_DATABASE=Printing Support usb:v043Dp00CB* ID_MODEL_FROM_DATABASE=Printing Support usb:v043Dp00CC* ID_MODEL_FROM_DATABASE=E120(n) usb:v043Dp00D0* ID_MODEL_FROM_DATABASE=9300 series usb:v043Dp00D3* ID_MODEL_FROM_DATABASE=X340 Scanner usb:v043Dp00D4* ID_MODEL_FROM_DATABASE=X342n Scanner usb:v043Dp00D5* ID_MODEL_FROM_DATABASE=Printing Support usb:v043Dp00D6* ID_MODEL_FROM_DATABASE=X340 Scanner usb:v043Dp00E8* ID_MODEL_FROM_DATABASE=X642e usb:v043Dp00E9* ID_MODEL_FROM_DATABASE=2400 series usb:v043Dp00F6* ID_MODEL_FROM_DATABASE=3400 series usb:v043Dp00F7* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp00FF* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v043Dp010B* ID_MODEL_FROM_DATABASE=2500 series usb:v043Dp010D* ID_MODEL_FROM_DATABASE=3500-4500 series usb:v043Dp010F* ID_MODEL_FROM_DATABASE=6500 series usb:v043Dp0142* ID_MODEL_FROM_DATABASE=X3650 (Printer, Scanner, Copier) usb:v043Dp01FA* ID_MODEL_FROM_DATABASE=S310 series usb:v043Dp4303* ID_MODEL_FROM_DATABASE=Xerox WorkCentre Pro 412 usb:v043E* ID_VENDOR_FROM_DATABASE=LG Electronics USA, Inc. usb:v043Ep3001* ID_MODEL_FROM_DATABASE=AN-WF100 802.11abgn Wireless Adapter [Broadcom BCM4323] usb:v043Ep42BD* ID_MODEL_FROM_DATABASE=Flatron 795FT Plus Monitor usb:v043Ep4A4D* ID_MODEL_FROM_DATABASE=Flatron 915FT Plus Monitor usb:v043Ep7001* ID_MODEL_FROM_DATABASE=MF-PD100 Soul Digital MP3 Player usb:v043Ep7013* ID_MODEL_FROM_DATABASE=MP3 Player usb:v043Ep70D7* ID_MODEL_FROM_DATABASE=Mouse Scanner LSM-150 [LG Smart Scan Mouse] usb:v043Ep70F5* ID_MODEL_FROM_DATABASE=External HDD usb:v043Ep8484* ID_MODEL_FROM_DATABASE=LPC-U30 Webcam II usb:v043Ep8585* ID_MODEL_FROM_DATABASE=LPC-UC35 Webcam usb:v043Ep8888* ID_MODEL_FROM_DATABASE=Electronics VCS Camera II(LPC-U20) usb:v043Ep9800* ID_MODEL_FROM_DATABASE=Remote Control Receiver_iMON usb:v043Ep9803* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v043Ep9804* ID_MODEL_FROM_DATABASE=DMB Receiver Control usb:v043Ep9C01* ID_MODEL_FROM_DATABASE=LGE Sync usb:v043F* ID_VENDOR_FROM_DATABASE=RadiSys Corp. usb:v0440* ID_VENDOR_FROM_DATABASE=Eizo Nanao Corp. usb:v0441* ID_VENDOR_FROM_DATABASE=Winbond Systems Lab. usb:v0441p1456* ID_MODEL_FROM_DATABASE=Hub usb:v0442* ID_VENDOR_FROM_DATABASE=Ericsson, Inc. usb:v0442pABBA* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0443* ID_VENDOR_FROM_DATABASE=Gateway, Inc. usb:v0443p000E* ID_MODEL_FROM_DATABASE=Multimedia Keyboard usb:v0443p002E* ID_MODEL_FROM_DATABASE=Millennium Keyboard usb:v0445* ID_VENDOR_FROM_DATABASE=Lucent Technologies, Inc. usb:v0446* ID_VENDOR_FROM_DATABASE=NMB Technologies Corp. usb:v0446p6781* ID_MODEL_FROM_DATABASE=Keyboard with PS/2 Mouse Port usb:v0446p6782* ID_MODEL_FROM_DATABASE=Keyboard usb:v0447* ID_VENDOR_FROM_DATABASE=Momentum Microsystems usb:v044A* ID_VENDOR_FROM_DATABASE=Shamrock Tech. Co., Ltd usb:v044B* ID_VENDOR_FROM_DATABASE=WSI usb:v044C* ID_VENDOR_FROM_DATABASE=CCL/ITRI usb:v044D* ID_VENDOR_FROM_DATABASE=Siemens Nixdorf AG usb:v044E* ID_VENDOR_FROM_DATABASE=Alps Electric Co., Ltd usb:v044Ep1104* ID_MODEL_FROM_DATABASE=Japanese Keyboard usb:v044Ep2002* ID_MODEL_FROM_DATABASE=MD-5500 Printer usb:v044Ep2014* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v044Ep3001* ID_MODEL_FROM_DATABASE=UGTZ4 Bluetooth usb:v044Ep3002* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v044Ep3003* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v044Ep3004* ID_MODEL_FROM_DATABASE=Bluetooth Adapter usb:v044Ep3005* ID_MODEL_FROM_DATABASE=Integrated Bluetooth Device usb:v044Ep3006* ID_MODEL_FROM_DATABASE=Bluetooth Adapter usb:v044Ep3007* ID_MODEL_FROM_DATABASE=Bluetooth Controller (ALPS/UGX) usb:v044Ep300C* ID_MODEL_FROM_DATABASE=Bluetooth Controller (ALPS/UGPZ6) usb:v044Ep300D* ID_MODEL_FROM_DATABASE=Bluetooth Controller (ALPS/UGPZ6) usb:v044Ep3010* ID_MODEL_FROM_DATABASE=Bluetooth Adapter usb:v044Ep3017* ID_MODEL_FROM_DATABASE=BCM2046 Bluetooth Device usb:v044EpFFFF* ID_MODEL_FROM_DATABASE=Compaq Bluetooth Multiport Module usb:v044F* ID_VENDOR_FROM_DATABASE=ThrustMaster, Inc. usb:v044Fp0400* ID_MODEL_FROM_DATABASE=HOTAS Cougar usb:v044Fp044F* ID_MODEL_FROM_DATABASE=GP XID usb:v044FpA003* ID_MODEL_FROM_DATABASE=Rage 3D Game Pad usb:v044FpA01B* ID_MODEL_FROM_DATABASE=PK-GP301 Driving Wheel usb:v044FpA0A0* ID_MODEL_FROM_DATABASE=Top Gun Joystick usb:v044FpA0A1* ID_MODEL_FROM_DATABASE=Top Gun Joystick (rev2) usb:v044FpA0A3* ID_MODEL_FROM_DATABASE=Fusion Digital GamePad usb:v044FpA201* ID_MODEL_FROM_DATABASE=PK-GP201 PlayStick usb:v044FpB108* ID_MODEL_FROM_DATABASE=T-Flight Hotas X Flight Stick usb:v044FpB10A* ID_MODEL_FROM_DATABASE=T.16000M Joystick usb:v044FpB203* ID_MODEL_FROM_DATABASE=360 Modena Pro Wheel usb:v044FpB300* ID_MODEL_FROM_DATABASE=Firestorm Dual Power usb:v044FpB303* ID_MODEL_FROM_DATABASE=FireStorm Dual Analog 2 usb:v044FpB304* ID_MODEL_FROM_DATABASE=Firestorm Dual Power usb:v044FpB307* ID_MODEL_FROM_DATABASE=vibrating Upad usb:v044FpB30B* ID_MODEL_FROM_DATABASE=Wireless VibrationPad usb:v044FpB315* ID_MODEL_FROM_DATABASE=Firestorm Dual Analog 3 usb:v044FpB323* ID_MODEL_FROM_DATABASE=Dual Trigger 3-in-1 (PC Mode) usb:v044FpB324* ID_MODEL_FROM_DATABASE=Dual Trigger 3-in-1 (PS3 Mode) usb:v044FpB603* ID_MODEL_FROM_DATABASE=force feedback Wheel usb:v044FpB605* ID_MODEL_FROM_DATABASE=force feedback Racing Wheel usb:v044FpB651* ID_MODEL_FROM_DATABASE=Ferrari GT Rumble Force Wheel usb:v044FpB653* ID_MODEL_FROM_DATABASE=RGT Force Feedback Clutch Racing Wheel usb:v044FpB654* ID_MODEL_FROM_DATABASE=Ferrari GT Force Feedback Wheel usb:v044FpB700* ID_MODEL_FROM_DATABASE=Tacticalboard usb:v0450* ID_VENDOR_FROM_DATABASE=DFI, Inc. usb:v0451* ID_VENDOR_FROM_DATABASE=Texas Instruments, Inc. usb:v0451p1234* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0451p1428* ID_MODEL_FROM_DATABASE=Hub usb:v0451p1446* ID_MODEL_FROM_DATABASE=TUSB2040/2070 Hub usb:v0451p16A6* ID_MODEL_FROM_DATABASE=BM-USBD1 BlueRobin RF heart rate sensor receiver usb:v0451p2036* ID_MODEL_FROM_DATABASE=TUSB2036 Hub usb:v0451p2046* ID_MODEL_FROM_DATABASE=TUSB2046 Hub usb:v0451p2077* ID_MODEL_FROM_DATABASE=TUSB2077 Hub usb:v0451p2F90* ID_MODEL_FROM_DATABASE=SM-USB-DIG usb:v0451p3410* ID_MODEL_FROM_DATABASE=TUSB3410 Microcontroller usb:v0451p3F00* ID_MODEL_FROM_DATABASE=OMAP1610 usb:v0451p3F02* ID_MODEL_FROM_DATABASE=SMC WSKP100 Wi-Fi Phone usb:v0451p5409* ID_MODEL_FROM_DATABASE=Frontier Labs NEX IA+ Digital Audio Player usb:v0451p6000* ID_MODEL_FROM_DATABASE=AU5 ADSL Modem (pre-reenum) usb:v0451p6001* ID_MODEL_FROM_DATABASE=AU5 ADSL Modem usb:v0451p6060* ID_MODEL_FROM_DATABASE=RNDIS/BeWAN ADSL2+ usb:v0451p6070* ID_MODEL_FROM_DATABASE=RNDIS/BeWAN ADSL2+ usb:v0451p625F* ID_MODEL_FROM_DATABASE=TUSB6250 ATA Bridge usb:v0451p8042* ID_MODEL_FROM_DATABASE=Hub usb:v0451p8142* ID_MODEL_FROM_DATABASE=TUSB8041 4-Port Hub usb:v0451p926B* ID_MODEL_FROM_DATABASE=TUSB9260 Boot Loader usb:v0451pDBC0* ID_MODEL_FROM_DATABASE=Device Bay Controller usb:v0451pE001* ID_MODEL_FROM_DATABASE=GraphLink [SilverLink] usb:v0451pE003* ID_MODEL_FROM_DATABASE=TI-84 Plus Calculator usb:v0451pE004* ID_MODEL_FROM_DATABASE=TI-89 Titanium Calculator usb:v0451pE008* ID_MODEL_FROM_DATABASE=TI-84 Plus Silver Calculator usb:v0451pE012* ID_MODEL_FROM_DATABASE=TI-Nspire Calculator usb:v0451pF430* ID_MODEL_FROM_DATABASE=MSP-FET430UIF JTAG Tool usb:v0451pF432* ID_MODEL_FROM_DATABASE=eZ430 Development Tool usb:v0451pFFFF* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0452* ID_VENDOR_FROM_DATABASE=Mitsubishi Electronics America, Inc. usb:v0452p0021* ID_MODEL_FROM_DATABASE=HID Monitor Controls usb:v0452p0050* ID_MODEL_FROM_DATABASE=Diamond Pro 900u CRT Monitor usb:v0452p0051* ID_MODEL_FROM_DATABASE=Integrated Hub usb:v0452p0100* ID_MODEL_FROM_DATABASE=Control Panel for Leica TCS SP5 usb:v0453* ID_VENDOR_FROM_DATABASE=CMD Technology usb:v0453p6781* ID_MODEL_FROM_DATABASE=NMB Keyboard usb:v0453p6783* ID_MODEL_FROM_DATABASE=Chicony Composite Keyboard usb:v0454* ID_VENDOR_FROM_DATABASE=Vobis Microcomputer AG usb:v0455* ID_VENDOR_FROM_DATABASE=Telematics International, Inc. usb:v0456* ID_VENDOR_FROM_DATABASE=Analog Devices, Inc. usb:v0456pF000* ID_MODEL_FROM_DATABASE=FT2232 JTAG ICE [gnICE] usb:v0456pF001* ID_MODEL_FROM_DATABASE=FT2232H Hi-Speed JTAG ICE [gnICE+] usb:v0457* ID_VENDOR_FROM_DATABASE=Silicon Integrated Systems Corp. usb:v0457p0150* ID_MODEL_FROM_DATABASE=Super Talent 1GB Flash Drive usb:v0457p0151* ID_MODEL_FROM_DATABASE=Super Flash 1GB / GXT 64MB Flash Drive usb:v0457p0162* ID_MODEL_FROM_DATABASE=SiS162 usb Wireless LAN Adapter usb:v0457p0163* ID_MODEL_FROM_DATABASE=SiS163U 802.11 Wireless LAN Adapter usb:v0457p0817* ID_MODEL_FROM_DATABASE=SiS-184-ASUS-4352.17 touch panel usb:v0457p5401* ID_MODEL_FROM_DATABASE=Wireless Adapter RO80211GS-USB usb:v0458* ID_VENDOR_FROM_DATABASE=KYE Systems Corp. (Mouse Systems) usb:v0458p0001* ID_MODEL_FROM_DATABASE=Mouse usb:v0458p0002* ID_MODEL_FROM_DATABASE=Genius NetMouse Pro usb:v0458p0003* ID_MODEL_FROM_DATABASE=Genius NetScroll+ usb:v0458p0006* ID_MODEL_FROM_DATABASE=Easy Mouse+ usb:v0458p000B* ID_MODEL_FROM_DATABASE=NetMouse Wheel(P+U) usb:v0458p000C* ID_MODEL_FROM_DATABASE=TACOMA Fingerprint V1.06.01 usb:v0458p000E* ID_MODEL_FROM_DATABASE=Genius NetScroll Optical usb:v0458p0013* ID_MODEL_FROM_DATABASE=TACOMA Fingerprint Mouse V1.06.01 usb:v0458p001A* ID_MODEL_FROM_DATABASE=Genius WebScroll+ usb:v0458p002E* ID_MODEL_FROM_DATABASE=NetScroll + Traveler / NetScroll 110 usb:v0458p0036* ID_MODEL_FROM_DATABASE=Pocket Mouse LE usb:v0458p0039* ID_MODEL_FROM_DATABASE=NetScroll+ Superior usb:v0458p003A* ID_MODEL_FROM_DATABASE=NetScroll+ Mini Traveler / Genius NetScroll 120 usb:v0458p004C* ID_MODEL_FROM_DATABASE=Slimstar Pro Keyboard usb:v0458p0056* ID_MODEL_FROM_DATABASE=Ergo 300 Mouse usb:v0458p0057* ID_MODEL_FROM_DATABASE=Enhanced Gaming Device usb:v0458p0059* ID_MODEL_FROM_DATABASE=Enhanced Laser Device usb:v0458p005A* ID_MODEL_FROM_DATABASE=Enhanced Device usb:v0458p005B* ID_MODEL_FROM_DATABASE=Enhanced Device usb:v0458p005C* ID_MODEL_FROM_DATABASE=Enhanced Laser Gaming Device usb:v0458p005D* ID_MODEL_FROM_DATABASE=Enhanced Device usb:v0458p0061* ID_MODEL_FROM_DATABASE=Bluetooth Dongle usb:v0458p0066* ID_MODEL_FROM_DATABASE=Genius Traveler 1000 Wireless Mouse usb:v0458p0072* ID_MODEL_FROM_DATABASE=Navigator 335 usb:v0458p0083* ID_MODEL_FROM_DATABASE=Bluetooth Dongle usb:v0458p0087* ID_MODEL_FROM_DATABASE=Ergo 525V Laser Mouse usb:v0458p0089* ID_MODEL_FROM_DATABASE=Genius Traveler 350 usb:v0458p00CA* ID_MODEL_FROM_DATABASE=Pen Mouse usb:v0458p0100* ID_MODEL_FROM_DATABASE=EasyPen Tablet usb:v0458p0101* ID_MODEL_FROM_DATABASE=CueCat usb:v0458p011B* ID_MODEL_FROM_DATABASE=NetScroll T220 usb:v0458p1001* ID_MODEL_FROM_DATABASE=Joystick usb:v0458p1002* ID_MODEL_FROM_DATABASE=Game Pad usb:v0458p1003* ID_MODEL_FROM_DATABASE=Genius VideoCam usb:v0458p1004* ID_MODEL_FROM_DATABASE=Flight2000 F-23 Joystick usb:v0458p100A* ID_MODEL_FROM_DATABASE=Aashima Technology Trust Sight Fighter Vibration Feedback Joystick usb:v0458p2001* ID_MODEL_FROM_DATABASE=ColorPage-Vivid Pro Scanner usb:v0458p2004* ID_MODEL_FROM_DATABASE=ColorPage-HR6 V1 Scanner usb:v0458p2005* ID_MODEL_FROM_DATABASE=ColorPage-HR6/Vivid3 usb:v0458p2007* ID_MODEL_FROM_DATABASE=ColorPage-HR6 V2 Scanner usb:v0458p2008* ID_MODEL_FROM_DATABASE=ColorPage-HR6 V2 Scanner usb:v0458p2009* ID_MODEL_FROM_DATABASE=ColorPage-HR6A Scanner usb:v0458p2011* ID_MODEL_FROM_DATABASE=ColorPage-Vivid3x Scanner usb:v0458p2012* ID_MODEL_FROM_DATABASE=Plustek Scanner usb:v0458p2013* ID_MODEL_FROM_DATABASE=ColorPage-HR7 Scanner usb:v0458p2014* ID_MODEL_FROM_DATABASE=ColorPage-Vivid4 usb:v0458p2015* ID_MODEL_FROM_DATABASE=ColorPage-HR7LE Scanner usb:v0458p2016* ID_MODEL_FROM_DATABASE=ColorPage-HR6X Scanner usb:v0458p2017* ID_MODEL_FROM_DATABASE=ColorPage-Vivid3xe usb:v0458p2018* ID_MODEL_FROM_DATABASE=ColorPage-HR7X usb:v0458p2019* ID_MODEL_FROM_DATABASE=ColorPage-HR6X Slim usb:v0458p201A* ID_MODEL_FROM_DATABASE=ColorPage-Vivid4xe usb:v0458p201B* ID_MODEL_FROM_DATABASE=ColorPage-Vivid4x usb:v0458p201C* ID_MODEL_FROM_DATABASE=ColorPage-HR8 usb:v0458p201D* ID_MODEL_FROM_DATABASE=ColorPage-Vivid 1200 X usb:v0458p201E* ID_MODEL_FROM_DATABASE=ColorPage-Slim 1200 usb:v0458p201F* ID_MODEL_FROM_DATABASE=ColorPage-Vivid 1200 XE usb:v0458p2020* ID_MODEL_FROM_DATABASE=ColorPage-Slim 1200 USB2 usb:v0458p2021* ID_MODEL_FROM_DATABASE=ColorPage-SF600 usb:v0458p3017* ID_MODEL_FROM_DATABASE=SPEED WHEEL 3 Vibration usb:v0458p3018* ID_MODEL_FROM_DATABASE=Wireless 2.4Ghz Game Pad usb:v0458p3019* ID_MODEL_FROM_DATABASE=10-Button USB Joystick with Vibration usb:v0458p301A* ID_MODEL_FROM_DATABASE=MaxFire G-12U Vibration usb:v0458p301D* ID_MODEL_FROM_DATABASE=Genius MaxFire MiniPad usb:v0458p400F* ID_MODEL_FROM_DATABASE=Genius TVGo DVB-T02Q MCE usb:v0458p4012* ID_MODEL_FROM_DATABASE=TVGo DVB-T03 [AF9015] usb:v0458p5003* ID_MODEL_FROM_DATABASE=G-pen 560 Tablet usb:v0458p5004* ID_MODEL_FROM_DATABASE=G-pen Tablet usb:v0458p505E* ID_MODEL_FROM_DATABASE=Genius iSlim 330 usb:v0458p6001* ID_MODEL_FROM_DATABASE=GF3000F Ethernet Adapter usb:v0458p7004* ID_MODEL_FROM_DATABASE=VideoCAM Express V2 usb:v0458p7006* ID_MODEL_FROM_DATABASE=Dsc 1.3 Smart Camera Device usb:v0458p7007* ID_MODEL_FROM_DATABASE=VideoCAM Web usb:v0458p7009* ID_MODEL_FROM_DATABASE=G-Shot G312 Still Camera Device usb:v0458p700C* ID_MODEL_FROM_DATABASE=VideoCAM Web V3 usb:v0458p700D* ID_MODEL_FROM_DATABASE=G-Shot G511 Composite Device usb:v0458p700F* ID_MODEL_FROM_DATABASE=VideoCAM Web usb:v0458p7012* ID_MODEL_FROM_DATABASE=WebCAM USB2.0 usb:v0458p7014* ID_MODEL_FROM_DATABASE=VideoCAM Live V3 usb:v0458p701C* ID_MODEL_FROM_DATABASE=G-Shot G512 Still Camera usb:v0458p7020* ID_MODEL_FROM_DATABASE=Sim 321C usb:v0458p7025* ID_MODEL_FROM_DATABASE=Eye 311Q Camera usb:v0458p7029* ID_MODEL_FROM_DATABASE=Genius Look 320s (SN9C201 + HV7131R) usb:v0458p702F* ID_MODEL_FROM_DATABASE=Genius Slim 322 usb:v0458p7035* ID_MODEL_FROM_DATABASE=i-Look 325T Camera usb:v0458p7045* ID_MODEL_FROM_DATABASE=Genius Look 1320 V2 usb:v0458p704C* ID_MODEL_FROM_DATABASE=Genius i-Look 1321 usb:v0458p704D* ID_MODEL_FROM_DATABASE=Slim 1322AF usb:v0458p7055* ID_MODEL_FROM_DATABASE=Slim 2020AF camera usb:v0458p705A* ID_MODEL_FROM_DATABASE=Asus USB2.0 Webcam usb:v0458p705C* ID_MODEL_FROM_DATABASE=Genius iSlim 1300AF usb:v0458p7061* ID_MODEL_FROM_DATABASE=Genius iLook 1321 V2 usb:v0458p7066* ID_MODEL_FROM_DATABASE=Acer Crystal Eye Webcam usb:v0458p7067* ID_MODEL_FROM_DATABASE=Genius iSlim 1300AF V2 usb:v0458p7068* ID_MODEL_FROM_DATABASE=Genius eFace 1325R usb:v0458p706D* ID_MODEL_FROM_DATABASE=Genius iSlim 2000AF V2 usb:v0458p7076* ID_MODEL_FROM_DATABASE=Genius FaceCam 312 usb:v0458p7079* ID_MODEL_FROM_DATABASE=FaceCam 2025R usb:v0458p707F* ID_MODEL_FROM_DATABASE=TVGo DVB-T03 [RTL2832] usb:v0458p7088* ID_MODEL_FROM_DATABASE=WideCam 1050 usb:v0458p7089* ID_MODEL_FROM_DATABASE=Genius FaceCam 320 usb:v0458p708C* ID_MODEL_FROM_DATABASE=Genius WideCam F100 usb:v0459* ID_VENDOR_FROM_DATABASE=Adobe Systems, Inc. usb:v045A* ID_VENDOR_FROM_DATABASE=SONICblue, Inc. usb:v045Ap07DA* ID_MODEL_FROM_DATABASE=Supra Express 56K modem usb:v045Ap0B4A* ID_MODEL_FROM_DATABASE=SupraMax 2890 56K Modem [Lucent Atlas] usb:v045Ap0B68* ID_MODEL_FROM_DATABASE=SupraMax 56K Modem usb:v045Ap5001* ID_MODEL_FROM_DATABASE=Rio 600 MP3 Player usb:v045Ap5002* ID_MODEL_FROM_DATABASE=Rio 800 MP3 Player usb:v045Ap5003* ID_MODEL_FROM_DATABASE=Nike Psa/Play MP3 Player usb:v045Ap5005* ID_MODEL_FROM_DATABASE=Rio S10 MP3 Player usb:v045Ap5006* ID_MODEL_FROM_DATABASE=Rio S50 MP3 Player usb:v045Ap5007* ID_MODEL_FROM_DATABASE=Rio S35 MP3 Player usb:v045Ap5008* ID_MODEL_FROM_DATABASE=Rio 900 MP3 Player usb:v045Ap5009* ID_MODEL_FROM_DATABASE=Rio S30 MP3 Player usb:v045Ap500D* ID_MODEL_FROM_DATABASE=Fuse MP3 Player usb:v045Ap500E* ID_MODEL_FROM_DATABASE=Chiba MP3 Player usb:v045Ap500F* ID_MODEL_FROM_DATABASE=Cali MP3 Player usb:v045Ap5010* ID_MODEL_FROM_DATABASE=Rio S11 MP3 Player usb:v045Ap501C* ID_MODEL_FROM_DATABASE=Virgin MPF-1000 usb:v045Ap501D* ID_MODEL_FROM_DATABASE=Rio Fuse usb:v045Ap501E* ID_MODEL_FROM_DATABASE=Rio Chiba usb:v045Ap501F* ID_MODEL_FROM_DATABASE=Rio Cali usb:v045Ap503F* ID_MODEL_FROM_DATABASE=Cali256 MP3 Player usb:v045Ap5202* ID_MODEL_FROM_DATABASE=Rio Riot MP3 Player usb:v045Ap5210* ID_MODEL_FROM_DATABASE=Rio Karma Music Player usb:v045Ap5220* ID_MODEL_FROM_DATABASE=Rio Nitrus MP3 Player usb:v045Ap5221* ID_MODEL_FROM_DATABASE=Rio Eigen usb:v045B* ID_VENDOR_FROM_DATABASE=Hitachi, Ltd usb:v045Bp0053* ID_MODEL_FROM_DATABASE=RX610 RX-Stick usb:v045D* ID_VENDOR_FROM_DATABASE=Nortel Networks, Ltd usb:v045E* ID_VENDOR_FROM_DATABASE=Microsoft Corp. usb:v045Ep0007* ID_MODEL_FROM_DATABASE=SideWinder Game Pad usb:v045Ep0008* ID_MODEL_FROM_DATABASE=SideWinder Precision Pro usb:v045Ep0009* ID_MODEL_FROM_DATABASE=IntelliMouse usb:v045Ep000B* ID_MODEL_FROM_DATABASE=Natural Keyboard Elite usb:v045Ep000E* ID_MODEL_FROM_DATABASE=SideWinder® Freestyle Pro usb:v045Ep0014* ID_MODEL_FROM_DATABASE=Digital Sound System 80 usb:v045Ep001A* ID_MODEL_FROM_DATABASE=SideWinder Precision Racing Wheel usb:v045Ep001B* ID_MODEL_FROM_DATABASE=SideWinder Force Feedback 2 Joystick usb:v045Ep001C* ID_MODEL_FROM_DATABASE=Internet Keyboard Pro usb:v045Ep001D* ID_MODEL_FROM_DATABASE=Natural Keyboard Pro usb:v045Ep001E* ID_MODEL_FROM_DATABASE=IntelliMouse Explorer usb:v045Ep0023* ID_MODEL_FROM_DATABASE=Trackball Optical usb:v045Ep0024* ID_MODEL_FROM_DATABASE=Trackball Explorer usb:v045Ep0025* ID_MODEL_FROM_DATABASE=IntelliEye Mouse usb:v045Ep0026* ID_MODEL_FROM_DATABASE=SideWinder GamePad Pro usb:v045Ep0027* ID_MODEL_FROM_DATABASE=SideWinder PnP GamePad usb:v045Ep0028* ID_MODEL_FROM_DATABASE=SideWinder Dual Strike usb:v045Ep0029* ID_MODEL_FROM_DATABASE=IntelliMouse Optical usb:v045Ep002B* ID_MODEL_FROM_DATABASE=Internet Keyboard Pro usb:v045Ep002D* ID_MODEL_FROM_DATABASE=Internet Keyboard usb:v045Ep002F* ID_MODEL_FROM_DATABASE=Integrated Hub usb:v045Ep0033* ID_MODEL_FROM_DATABASE=Sidewinder Strategic Commander usb:v045Ep0034* ID_MODEL_FROM_DATABASE=SideWinder Force Feedback Wheel usb:v045Ep0038* ID_MODEL_FROM_DATABASE=SideWinder Precision 2 usb:v045Ep0039* ID_MODEL_FROM_DATABASE=IntelliMouse Optical usb:v045Ep003B* ID_MODEL_FROM_DATABASE=SideWinder Game Voice usb:v045Ep003C* ID_MODEL_FROM_DATABASE=SideWinder Joystick usb:v045Ep0040* ID_MODEL_FROM_DATABASE=Wheel Mouse Optical usb:v045Ep0047* ID_MODEL_FROM_DATABASE=IntelliMouse Explorer 3.0 usb:v045Ep0048* ID_MODEL_FROM_DATABASE=Office Keyboard 1.0A usb:v045Ep0053* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v045Ep0059* ID_MODEL_FROM_DATABASE=Wireless IntelliMouse Explorer usb:v045Ep005C* ID_MODEL_FROM_DATABASE=Office Keyboard (106/109) usb:v045Ep005F* ID_MODEL_FROM_DATABASE=Wireless MultiMedia Keyboard usb:v045Ep0061* ID_MODEL_FROM_DATABASE=Wireless MultiMedia Keyboard (106/109) usb:v045Ep0063* ID_MODEL_FROM_DATABASE=Wireless Natural MultiMedia Keyboard usb:v045Ep0065* ID_MODEL_FROM_DATABASE=Wireless Natural MultiMedia Keyboard (106/109) usb:v045Ep006A* ID_MODEL_FROM_DATABASE=Wireless Optical Mouse (IntelliPoint) usb:v045Ep006D* ID_MODEL_FROM_DATABASE=eHome Remote Control Keyboard keys usb:v045Ep006E* ID_MODEL_FROM_DATABASE=MN-510 802.11b Wireless Adapter [Intersil ISL3873B] usb:v045Ep006F* ID_MODEL_FROM_DATABASE=Smart Display Reference Device usb:v045Ep0070* ID_MODEL_FROM_DATABASE=Wireless MultiMedia Keyboard usb:v045Ep0071* ID_MODEL_FROM_DATABASE=Wireless MultiMedia Keyboard (106/109) usb:v045Ep0072* ID_MODEL_FROM_DATABASE=Wireless Natural MultiMedia Keyboard usb:v045Ep0073* ID_MODEL_FROM_DATABASE=Wireless Natural MultiMedia Keyboard (106/109) usb:v045Ep0079* ID_MODEL_FROM_DATABASE=IXI Ogo CT-17 handheld device usb:v045Ep007A* ID_MODEL_FROM_DATABASE=10/100 USB NIC usb:v045Ep007D* ID_MODEL_FROM_DATABASE=Notebook Optical Mouse usb:v045Ep007E* ID_MODEL_FROM_DATABASE=Wireless Transceiver for Bluetooth usb:v045Ep0080* ID_MODEL_FROM_DATABASE=Digital Media Pro Keyboard usb:v045Ep0083* ID_MODEL_FROM_DATABASE=Basic Optical Mouse usb:v045Ep0084* ID_MODEL_FROM_DATABASE=Basic Optical Mouse usb:v045Ep008A* ID_MODEL_FROM_DATABASE=Wireless Keyboard and Mouse usb:v045Ep008B* ID_MODEL_FROM_DATABASE=Dual Receiver Wireless Mouse (IntelliPoint) usb:v045Ep008C* ID_MODEL_FROM_DATABASE=Wireless Intellimouse Explorer 2.0 usb:v045Ep0095* ID_MODEL_FROM_DATABASE=IntelliMouse Explorer 4.0 (IntelliPoint) usb:v045Ep009C* ID_MODEL_FROM_DATABASE=Wireless Transceiver for Bluetooth 2.0 usb:v045Ep009D* ID_MODEL_FROM_DATABASE=Wireless Optical Desktop 3.0 usb:v045Ep00A0* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v045Ep00A4* ID_MODEL_FROM_DATABASE=Compact Optical Mouse, model 1016 usb:v045Ep00B0* ID_MODEL_FROM_DATABASE=Digital Media Pro Keyboard usb:v045Ep00B4* ID_MODEL_FROM_DATABASE=Digital Media Keyboard 1.0A usb:v045Ep00B9* ID_MODEL_FROM_DATABASE=Wireless Optical Mouse 3.0 usb:v045Ep00BB* ID_MODEL_FROM_DATABASE=Fingerprint Reader usb:v045Ep00BC* ID_MODEL_FROM_DATABASE=Fingerprint Reader usb:v045Ep00BD* ID_MODEL_FROM_DATABASE=Fingerprint Reader usb:v045Ep00C2* ID_MODEL_FROM_DATABASE=MN-710 802.11g Wireless Adapter [Intersil ISL3886] usb:v045Ep00C9* ID_MODEL_FROM_DATABASE=MTP Device usb:v045Ep00CA* ID_MODEL_FROM_DATABASE=Fingerprint Reader usb:v045Ep00CB* ID_MODEL_FROM_DATABASE=Basic Optical Mouse v2.0 usb:v045Ep00CE* ID_MODEL_FROM_DATABASE=Generic PPC Flash device usb:v045Ep00D1* ID_MODEL_FROM_DATABASE=Optical Mouse with Tilt Wheel usb:v045Ep00DA* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v045Ep00DB* ID_MODEL_FROM_DATABASE=Natural Ergonomic Keyboard 4000 V1.0 usb:v045Ep00DD* ID_MODEL_FROM_DATABASE=Comfort Curve Keyboard 2000 V1.0 usb:v045Ep00E1* ID_MODEL_FROM_DATABASE=Wireless Laser Mouse 6000 Reciever usb:v045Ep00F4* ID_MODEL_FROM_DATABASE=LifeCam VX-6000 (SN9C20x + OV9650) usb:v045Ep00F5* ID_MODEL_FROM_DATABASE=LifeCam VX-3000 usb:v045Ep00F6* ID_MODEL_FROM_DATABASE=Comfort Optical Mouse 1000 usb:v045Ep00F7* ID_MODEL_FROM_DATABASE=LifeCam VX-1000 usb:v045Ep00F8* ID_MODEL_FROM_DATABASE=LifeCam NX-6000 usb:v045Ep00F9* ID_MODEL_FROM_DATABASE=Wireless Desktop Receiver 3.1 usb:v045Ep0202* ID_MODEL_FROM_DATABASE=Xbox Controller usb:v045Ep0280* ID_MODEL_FROM_DATABASE=XBox Device usb:v045Ep0283* ID_MODEL_FROM_DATABASE=Xbox Communicator usb:v045Ep0284* ID_MODEL_FROM_DATABASE=Xbox DVD Playback Kit usb:v045Ep0285* ID_MODEL_FROM_DATABASE=Xbox Controller S usb:v045Ep0288* ID_MODEL_FROM_DATABASE=Xbox Controller S Hub usb:v045Ep0289* ID_MODEL_FROM_DATABASE=Xbox Controller S usb:v045Ep028B* ID_MODEL_FROM_DATABASE=Xbox360 DVD Emulator usb:v045Ep028D* ID_MODEL_FROM_DATABASE=Xbox360 Memory Unit 64MB usb:v045Ep028E* ID_MODEL_FROM_DATABASE=Xbox360 Controller usb:v045Ep028F* ID_MODEL_FROM_DATABASE=Xbox360 Wireless Controller usb:v045Ep0290* ID_MODEL_FROM_DATABASE=Xbox360 Performance Pipe (PIX) usb:v045Ep0291* ID_MODEL_FROM_DATABASE=Xbox 360 Wireless Receiver for Windows usb:v045Ep0292* ID_MODEL_FROM_DATABASE=Xbox360 Wireless Networking Adapter usb:v045Ep029C* ID_MODEL_FROM_DATABASE=Xbox360 HD-DVD Drive usb:v045Ep029D* ID_MODEL_FROM_DATABASE=Xbox360 HD-DVD Drive usb:v045Ep029E* ID_MODEL_FROM_DATABASE=Xbox360 HD-DVD Memory Unit usb:v045Ep02A0* ID_MODEL_FROM_DATABASE=Xbox360 Big Button IR usb:v045Ep02A1* ID_MODEL_FROM_DATABASE=Xbox 360 Wireless Receiver for Windows usb:v045Ep02A8* ID_MODEL_FROM_DATABASE=Xbox360 Wireless N Networking Adapter [Atheros AR7010+AR9280] usb:v045Ep02AD* ID_MODEL_FROM_DATABASE=Xbox NUI Audio usb:v045Ep02AE* ID_MODEL_FROM_DATABASE=Xbox NUI Camera usb:v045Ep02B0* ID_MODEL_FROM_DATABASE=Xbox NUI Motor usb:v045Ep02B6* ID_MODEL_FROM_DATABASE=Xbox 360 / Bluetooth Wireless Headset usb:v045Ep02BE* ID_MODEL_FROM_DATABASE=Kinect for Windows NUI Audio usb:v045Ep02BF* ID_MODEL_FROM_DATABASE=Kinect for Windows NUI Camera usb:v045Ep02C2* ID_MODEL_FROM_DATABASE=Kinect for Windows NUI Motor usb:v045Ep02D1* ID_MODEL_FROM_DATABASE=XBOX One Controller for Windows usb:v045Ep02D5* ID_MODEL_FROM_DATABASE=Xbox One Digital TV Tuner usb:v045Ep0400* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0401* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0402* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0403* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0404* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0405* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0406* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0407* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0408* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0409* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep040A* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep040B* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep040C* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep040D* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep040E* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep040F* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0410* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0411* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0412* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0413* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0414* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0415* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0416* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0417* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 usb:v045Ep0432* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0433* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0434* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0435* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0436* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0437* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0438* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0439* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep043A* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep043B* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep043C* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep043D* ID_MODEL_FROM_DATABASE=Becker Traffic Assist Highspeed 7934 usb:v045Ep043E* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep043F* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0440* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0441* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0442* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0443* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0444* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0445* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0446* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0447* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0448* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0449* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep044A* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep044B* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep044C* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep044D* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep044E* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep044F* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0450* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0451* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0452* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0453* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0454* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0455* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0456* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0457* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0458* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0459* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep045A* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep045B* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep045C* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep045D* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep045E* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep045F* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0460* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0461* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0462* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0463* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0464* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0465* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0466* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0467* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0468* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0469* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep046A* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep046B* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep046C* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep046D* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep046E* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep046F* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0470* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0471* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0472* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0473* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0474* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0475* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0476* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0477* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0478* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep0479* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep047A* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep047B* ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 usb:v045Ep04C8* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 usb:v045Ep04C9* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 usb:v045Ep04CA* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 usb:v045Ep04CB* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 usb:v045Ep04CC* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 usb:v045Ep04CD* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 usb:v045Ep04CE* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 usb:v045Ep04D7* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04D8* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04D9* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04DA* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04DB* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04DC* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04DD* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04DE* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04DF* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04E0* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04E1* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04E2* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04E3* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04E4* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04E5* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04E6* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04E7* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04E8* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04E9* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04EA* ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 usb:v045Ep04EC* ID_MODEL_FROM_DATABASE=Windows Phone (Zune) usb:v045Ep063E* ID_MODEL_FROM_DATABASE=Zune HD Media Player usb:v045Ep0640* ID_MODEL_FROM_DATABASE=KIN Phone usb:v045Ep0641* ID_MODEL_FROM_DATABASE=KIN Phone usb:v045Ep0642* ID_MODEL_FROM_DATABASE=KIN Phone usb:v045Ep0707* ID_MODEL_FROM_DATABASE=Wireless Laser Mouse 8000 usb:v045Ep0708* ID_MODEL_FROM_DATABASE=Transceiver v 3.0 for Bluetooth usb:v045Ep070A* ID_MODEL_FROM_DATABASE=Charon Bluetooth Dongle (DFU) usb:v045Ep070F* ID_MODEL_FROM_DATABASE=LifeChat LX-3000 Headset usb:v045Ep0710* ID_MODEL_FROM_DATABASE=Zune Media Player usb:v045Ep0713* ID_MODEL_FROM_DATABASE=Wireless Presenter Mouse 8000 usb:v045Ep0719* ID_MODEL_FROM_DATABASE=Xbox 360 Wireless Adapter usb:v045Ep071F* ID_MODEL_FROM_DATABASE=Mouse/Keyboard 2.4GHz Transceiver V2.0 usb:v045Ep0721* ID_MODEL_FROM_DATABASE=LifeCam NX-3000 (UVC-compliant) usb:v045Ep0723* ID_MODEL_FROM_DATABASE=LifeCam VX-7000 (UVC-compliant) usb:v045Ep0724* ID_MODEL_FROM_DATABASE=SideWinder Mouse usb:v045Ep0728* ID_MODEL_FROM_DATABASE=LifeCam VX-5000 usb:v045Ep0730* ID_MODEL_FROM_DATABASE=Digital Media Keyboard 3000 usb:v045Ep0734* ID_MODEL_FROM_DATABASE=Wireless Optical Desktop 700 usb:v045Ep0736* ID_MODEL_FROM_DATABASE=Sidewinder X5 Mouse usb:v045Ep0737* ID_MODEL_FROM_DATABASE=Compact Optical Mouse 500 usb:v045Ep0745* ID_MODEL_FROM_DATABASE=Nano Transceiver v1.0 for Bluetooth usb:v045Ep0750* ID_MODEL_FROM_DATABASE=Wired Keyboard 600 usb:v045Ep0752* ID_MODEL_FROM_DATABASE=Wired Keyboard 400 usb:v045Ep075D* ID_MODEL_FROM_DATABASE=LifeCam Cinema usb:v045Ep0766* ID_MODEL_FROM_DATABASE=LifeCam VX-800 usb:v045Ep0768* ID_MODEL_FROM_DATABASE=Sidewinder X4 usb:v045Ep076C* ID_MODEL_FROM_DATABASE=Comfort Mouse 4500 usb:v045Ep076D* ID_MODEL_FROM_DATABASE=LifeCam HD-5000 usb:v045Ep0772* ID_MODEL_FROM_DATABASE=LifeCam Studio usb:v045Ep0779* ID_MODEL_FROM_DATABASE=LifeCam HD-3000 usb:v045Ep0780* ID_MODEL_FROM_DATABASE=Comfort Curve Keyboard 3000 usb:v045Ep0797* ID_MODEL_FROM_DATABASE=Optical Mouse 200 usb:v045Ep07A5* ID_MODEL_FROM_DATABASE=Wireless Receiver 1461C usb:v045Ep07F8* ID_MODEL_FROM_DATABASE=Wired Keyboard 600 (model 1576) usb:v045Ep07FD* ID_MODEL_FROM_DATABASE=Nano Transceiver 1.1 usb:v045Ep930A* ID_MODEL_FROM_DATABASE=ISOUSB.SYS Intel 82930 Isochronous IO Test Board usb:v045EpFFCA* ID_MODEL_FROM_DATABASE=Catalina usb:v045EpFFF8* ID_MODEL_FROM_DATABASE=Keyboard usb:v045EpFFFF* ID_MODEL_FROM_DATABASE=Windows CE Mass Storage usb:v0460* ID_VENDOR_FROM_DATABASE=Ace Cad Enterprise Co., Ltd usb:v0460p0004* ID_MODEL_FROM_DATABASE=Tablet (5x3.75) usb:v0460p0006* ID_MODEL_FROM_DATABASE=LCD Tablet (12x9) usb:v0460p0008* ID_MODEL_FROM_DATABASE=Tablet (3x2.25) usb:v0461* ID_VENDOR_FROM_DATABASE=Primax Electronics, Ltd usb:v0461p0010* ID_MODEL_FROM_DATABASE=HP PR1101U / Primax PMX-KPR1101U Keyboard usb:v0461p0300* ID_MODEL_FROM_DATABASE=G2-300 Scanner usb:v0461p0301* ID_MODEL_FROM_DATABASE=G2E-300 Scanner usb:v0461p0302* ID_MODEL_FROM_DATABASE=G2-300 #2 Scanner usb:v0461p0303* ID_MODEL_FROM_DATABASE=G2E-300 #2 Scanner usb:v0461p0340* ID_MODEL_FROM_DATABASE=Colorado 9600 Scanner usb:v0461p0341* ID_MODEL_FROM_DATABASE=Colorado 600u Scanner usb:v0461p0345* ID_MODEL_FROM_DATABASE=Visioneer 6200 Scanner usb:v0461p0346* ID_MODEL_FROM_DATABASE=Memorex Maxx 6136u Scanner usb:v0461p0347* ID_MODEL_FROM_DATABASE=Primascan Colorado 2600u/Visioneer 4400 Scanner usb:v0461p0360* ID_MODEL_FROM_DATABASE=Colorado 19200 Scanner usb:v0461p0361* ID_MODEL_FROM_DATABASE=Colorado 1200u Scanner usb:v0461p0363* ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) usb:v0461p0364* ID_MODEL_FROM_DATABASE=LG Electronics Scanworks 600U Scanner usb:v0461p0365* ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) usb:v0461p0366* ID_MODEL_FROM_DATABASE=6400 usb:v0461p0367* ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) usb:v0461p0371* ID_MODEL_FROM_DATABASE=Visioneer Onetouch 8920 Scanner usb:v0461p0374* ID_MODEL_FROM_DATABASE=UMAX Astra 2500 usb:v0461p0375* ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) usb:v0461p0377* ID_MODEL_FROM_DATABASE=Medion MD 5345 Scanner usb:v0461p0378* ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) usb:v0461p037B* ID_MODEL_FROM_DATABASE=Medion MD 6190 Scanner usb:v0461p037C* ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) usb:v0461p0380* ID_MODEL_FROM_DATABASE=G2-600 Scanner usb:v0461p0381* ID_MODEL_FROM_DATABASE=ReadyScan 636i Scanner usb:v0461p0382* ID_MODEL_FROM_DATABASE=G2-600 #2 Scanner usb:v0461p0383* ID_MODEL_FROM_DATABASE=G2E-600 Scanner usb:v0461p038A* ID_MODEL_FROM_DATABASE=UMAX Astra 3000/3600 usb:v0461p038B* ID_MODEL_FROM_DATABASE=Xerox 2400 Onetouch usb:v0461p038C* ID_MODEL_FROM_DATABASE=UMAX Astra 4100 usb:v0461p0392* ID_MODEL_FROM_DATABASE=Medion/Lifetec/Tevion/Cytron MD 6190 usb:v0461p03A8* ID_MODEL_FROM_DATABASE=9420M usb:v0461p0813* ID_MODEL_FROM_DATABASE=IBM UltraPort Camera usb:v0461p0815* ID_MODEL_FROM_DATABASE=Micro Innovations IC200 Webcam usb:v0461p0819* ID_MODEL_FROM_DATABASE=Fujifilm IX-30 Camera [webcam mode] usb:v0461p081A* ID_MODEL_FROM_DATABASE=Fujifilm IX-30 Camera [storage mode] usb:v0461p081C* ID_MODEL_FROM_DATABASE=Elitegroup ECS-C11 Camera usb:v0461p081D* ID_MODEL_FROM_DATABASE=Elitegroup ECS-C11 Storage usb:v0461p0A00* ID_MODEL_FROM_DATABASE=Micro Innovations Web Cam 320 usb:v0461p4D01* ID_MODEL_FROM_DATABASE=Comfort Keyboard usb:v0461p4D02* ID_MODEL_FROM_DATABASE=Mouse-in-a-Box usb:v0461p4D03* ID_MODEL_FROM_DATABASE=Kensington Mouse-in-a-box usb:v0461p4D04* ID_MODEL_FROM_DATABASE=Mouse usb:v0461p4D06* ID_MODEL_FROM_DATABASE=Balless Mouse (HID) usb:v0461p4D0F* ID_MODEL_FROM_DATABASE=HP Optical Mouse usb:v0461p4D15* ID_MODEL_FROM_DATABASE=Dell Optical Mouse usb:v0461p4D17* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v0461p4D20* ID_MODEL_FROM_DATABASE=HP Optical Mouse usb:v0461p4D2A* ID_MODEL_FROM_DATABASE=PoPo Elixir Mouse (HID) usb:v0461p4D2B* ID_MODEL_FROM_DATABASE=Wireless Laser Mini Mouse (HID) usb:v0461p4D2C* ID_MODEL_FROM_DATABASE=PoPo Mini Pointer Mouse (HID) usb:v0461p4D2E* ID_MODEL_FROM_DATABASE=Optical Mobile Mouse (HID) usb:v0461p4D51* ID_MODEL_FROM_DATABASE=0Y357C PMX-MMOCZUL (B) [Dell Laser Mouse] usb:v0461p4D62* ID_MODEL_FROM_DATABASE=HP Laser Mobile Mini Mouse usb:v0461p4D75* ID_MODEL_FROM_DATABASE=Rocketfish RF-FLBTAD Bluetooth Adapter usb:v0461p4D81* ID_MODEL_FROM_DATABASE=Dell N889 Optical Mouse usb:v0461p4DE7* ID_MODEL_FROM_DATABASE=webcam usb:v0463* ID_VENDOR_FROM_DATABASE=MGE UPS Systems usb:v0463p0001* ID_MODEL_FROM_DATABASE=UPS usb:v0463pFFFF* ID_MODEL_FROM_DATABASE=UPS usb:v0464* ID_VENDOR_FROM_DATABASE=AMP/Tycoelectronics Corp. usb:v0467* ID_VENDOR_FROM_DATABASE=AT&T Paradyne usb:v0468* ID_VENDOR_FROM_DATABASE=Wieson Technologies Co., Ltd usb:v046A* ID_VENDOR_FROM_DATABASE=Cherry GmbH usb:v046Ap0001* ID_MODEL_FROM_DATABASE=Keyboard usb:v046Ap0003* ID_MODEL_FROM_DATABASE=My3000 Hub usb:v046Ap0004* ID_MODEL_FROM_DATABASE=CyBoard Keyboard usb:v046Ap0005* ID_MODEL_FROM_DATABASE=XX33 SmartCard Reader Keyboard usb:v046Ap0008* ID_MODEL_FROM_DATABASE=Wireless Keyboard and Mouse usb:v046Ap0010* ID_MODEL_FROM_DATABASE=SmartBoard XX44 usb:v046Ap0011* ID_MODEL_FROM_DATABASE=G83 (RS 6000) Keyboard usb:v046Ap0021* ID_MODEL_FROM_DATABASE=CyMotion Expert Combo usb:v046Ap0023* ID_MODEL_FROM_DATABASE=CyMotion Master Linux Keyboard G230 usb:v046Ap0027* ID_MODEL_FROM_DATABASE=CyMotion Master Solar Keyboard usb:v046Ap002A* ID_MODEL_FROM_DATABASE=Wireless Mouse & Keyboard usb:v046Ap002D* ID_MODEL_FROM_DATABASE=SmartTerminal XX44 usb:v046Ap003E* ID_MODEL_FROM_DATABASE=SmartTerminal ST-2xxx usb:v046Ap0041* ID_MODEL_FROM_DATABASE=G86 6240 Keyboard usb:v046Ap0080* ID_MODEL_FROM_DATABASE=eHealth Terminal ST 1503 usb:v046Ap0081* ID_MODEL_FROM_DATABASE=eHealth Keyboard G87 1504 usb:v046Ap0106* ID_MODEL_FROM_DATABASE=R-300 Wireless Mouse Receiver usb:v046Ap010D* ID_MODEL_FROM_DATABASE=MX-Board 3.0 Keyboard usb:v046B* ID_VENDOR_FROM_DATABASE=American Megatrends, Inc. usb:v046Bp0001* ID_MODEL_FROM_DATABASE=Keyboard usb:v046Bp0101* ID_MODEL_FROM_DATABASE=PS/2 Keyboard, Mouse & Joystick Ports usb:v046Bp0301* ID_MODEL_FROM_DATABASE=USB 1.0 Hub usb:v046Bp0500* ID_MODEL_FROM_DATABASE=Serial & Parallel Ports usb:v046BpFF10* ID_MODEL_FROM_DATABASE=Virtual Keyboard and Mouse usb:v046C* ID_VENDOR_FROM_DATABASE=Toshiba Corp., Digital Media Equipment usb:v046D* ID_VENDOR_FROM_DATABASE=Logitech, Inc. usb:v046Dp0082* ID_MODEL_FROM_DATABASE=Acer Aspire 5672 Webcam usb:v046Dp0200* ID_MODEL_FROM_DATABASE=WingMan Extreme Joystick usb:v046Dp0203* ID_MODEL_FROM_DATABASE=M2452 Keyboard usb:v046Dp0301* ID_MODEL_FROM_DATABASE=M4848 Mouse usb:v046Dp0401* ID_MODEL_FROM_DATABASE=HP PageScan usb:v046Dp0402* ID_MODEL_FROM_DATABASE=NEC PageScan usb:v046Dp040F* ID_MODEL_FROM_DATABASE=Logitech/Storm PageScan usb:v046Dp0430* ID_MODEL_FROM_DATABASE=Mic (Cordless) usb:v046Dp0801* ID_MODEL_FROM_DATABASE=QuickCam Home usb:v046Dp0802* ID_MODEL_FROM_DATABASE=Webcam C200 usb:v046Dp0804* ID_MODEL_FROM_DATABASE=Webcam C250 usb:v046Dp0805* ID_MODEL_FROM_DATABASE=Webcam C300 usb:v046Dp0807* ID_MODEL_FROM_DATABASE=Webcam B500 usb:v046Dp0808* ID_MODEL_FROM_DATABASE=Webcam C600 usb:v046Dp0809* ID_MODEL_FROM_DATABASE=Webcam Pro 9000 usb:v046Dp080A* ID_MODEL_FROM_DATABASE=Portable Webcam C905 usb:v046Dp080F* ID_MODEL_FROM_DATABASE=Webcam C120 usb:v046Dp0810* ID_MODEL_FROM_DATABASE=QuickCam Pro usb:v046Dp0819* ID_MODEL_FROM_DATABASE=Webcam C210 usb:v046Dp081B* ID_MODEL_FROM_DATABASE=Webcam C310 usb:v046Dp081D* ID_MODEL_FROM_DATABASE=HD Webcam C510 usb:v046Dp0820* ID_MODEL_FROM_DATABASE=QuickCam VC usb:v046Dp0821* ID_MODEL_FROM_DATABASE=HD Webcam C910 usb:v046Dp0825* ID_MODEL_FROM_DATABASE=Webcam C270 usb:v046Dp0826* ID_MODEL_FROM_DATABASE=HD Webcam C525 usb:v046Dp0828* ID_MODEL_FROM_DATABASE=HD Webcam B990 usb:v046Dp082B* ID_MODEL_FROM_DATABASE=Webcam C170 usb:v046Dp082D* ID_MODEL_FROM_DATABASE=HD Pro Webcam C920 usb:v046Dp0830* ID_MODEL_FROM_DATABASE=QuickClip usb:v046Dp0836* ID_MODEL_FROM_DATABASE=B525 HD Webcam usb:v046Dp0837* ID_MODEL_FROM_DATABASE=BCC950 ConferenceCam usb:v046Dp0840* ID_MODEL_FROM_DATABASE=QuickCam Express usb:v046Dp0843* ID_MODEL_FROM_DATABASE=Webcam C930e usb:v046Dp0850* ID_MODEL_FROM_DATABASE=QuickCam Web usb:v046Dp0870* ID_MODEL_FROM_DATABASE=QuickCam Express usb:v046Dp0890* ID_MODEL_FROM_DATABASE=QuickCam Traveler usb:v046Dp0892* ID_MODEL_FROM_DATABASE=OrbiCam usb:v046Dp0894* ID_MODEL_FROM_DATABASE=CrystalCam usb:v046Dp0895* ID_MODEL_FROM_DATABASE=QuickCam for Dell Notebooks usb:v046Dp0896* ID_MODEL_FROM_DATABASE=OrbiCam usb:v046Dp0897* ID_MODEL_FROM_DATABASE=QuickCam for Dell Notebooks usb:v046Dp0899* ID_MODEL_FROM_DATABASE=QuickCam for Dell Notebooks usb:v046Dp089D* ID_MODEL_FROM_DATABASE=QuickCam E2500 series usb:v046Dp08A0* ID_MODEL_FROM_DATABASE=QuickCam IM usb:v046Dp08A1* ID_MODEL_FROM_DATABASE=QuickCam IM with sound usb:v046Dp08A2* ID_MODEL_FROM_DATABASE=Labtec Webcam Pro usb:v046Dp08A3* ID_MODEL_FROM_DATABASE=QuickCam QuickCam Chat usb:v046Dp08A6* ID_MODEL_FROM_DATABASE=QuickCam IM usb:v046Dp08A7* ID_MODEL_FROM_DATABASE=QuickCam Image usb:v046Dp08A9* ID_MODEL_FROM_DATABASE=Notebook Deluxe usb:v046Dp08AA* ID_MODEL_FROM_DATABASE=Labtec Notebooks usb:v046Dp08AC* ID_MODEL_FROM_DATABASE=QuickCam Cool usb:v046Dp08AD* ID_MODEL_FROM_DATABASE=QuickCam Communicate STX usb:v046Dp08AE* ID_MODEL_FROM_DATABASE=QuickCam for Notebooks usb:v046Dp08AF* ID_MODEL_FROM_DATABASE=QuickCam Easy/Cool usb:v046Dp08B0* ID_MODEL_FROM_DATABASE=QuickCam 3000 Pro [pwc] usb:v046Dp08B1* ID_MODEL_FROM_DATABASE=QuickCam Notebook Pro usb:v046Dp08B2* ID_MODEL_FROM_DATABASE=QuickCam Pro 4000 usb:v046Dp08B3* ID_MODEL_FROM_DATABASE=QuickCam Zoom usb:v046Dp08B4* ID_MODEL_FROM_DATABASE=QuickCam Zoom usb:v046Dp08B5* ID_MODEL_FROM_DATABASE=QuickCam Sphere usb:v046Dp08B9* ID_MODEL_FROM_DATABASE=QuickCam IM usb:v046Dp08BD* ID_MODEL_FROM_DATABASE=Microphone (Pro 4000) usb:v046Dp08C0* ID_MODEL_FROM_DATABASE=QuickCam Pro 3000 usb:v046Dp08C1* ID_MODEL_FROM_DATABASE=QuickCam Fusion usb:v046Dp08C2* ID_MODEL_FROM_DATABASE=QuickCam PTZ usb:v046Dp08C3* ID_MODEL_FROM_DATABASE=Camera (Notebooks Pro) usb:v046Dp08C5* ID_MODEL_FROM_DATABASE=QuickCam Pro 5000 usb:v046Dp08C6* ID_MODEL_FROM_DATABASE=QuickCam for DELL Notebooks usb:v046Dp08C7* ID_MODEL_FROM_DATABASE=QuickCam OEM Cisco VT Camera II usb:v046Dp08C9* ID_MODEL_FROM_DATABASE=QuickCam Ultra Vision usb:v046Dp08CA* ID_MODEL_FROM_DATABASE=Mic (Fusion) usb:v046Dp08CB* ID_MODEL_FROM_DATABASE=Mic (Notebooks Pro) usb:v046Dp08CC* ID_MODEL_FROM_DATABASE=Mic (PTZ) usb:v046Dp08CE* ID_MODEL_FROM_DATABASE=QuickCam Pro 5000 usb:v046Dp08CF* ID_MODEL_FROM_DATABASE=QuickCam UpdateMe usb:v046Dp08D0* ID_MODEL_FROM_DATABASE=QuickCam Express usb:v046Dp08D7* ID_MODEL_FROM_DATABASE=QuickCam Communicate STX usb:v046Dp08D8* ID_MODEL_FROM_DATABASE=QuickCam for Notebook Deluxe usb:v046Dp08D9* ID_MODEL_FROM_DATABASE=QuickCam IM/Connect usb:v046Dp08DA* ID_MODEL_FROM_DATABASE=QuickCam Messanger usb:v046Dp08DD* ID_MODEL_FROM_DATABASE=QuickCam for Notebooks usb:v046Dp08E0* ID_MODEL_FROM_DATABASE=QuickCam Express usb:v046Dp08E1* ID_MODEL_FROM_DATABASE=Labtec Webcam usb:v046Dp08F0* ID_MODEL_FROM_DATABASE=QuickCam Messenger usb:v046Dp08F1* ID_MODEL_FROM_DATABASE=QuickCam Express usb:v046Dp08F2* ID_MODEL_FROM_DATABASE=Microphone (Messenger) usb:v046Dp08F3* ID_MODEL_FROM_DATABASE=QuickCam Express usb:v046Dp08F4* ID_MODEL_FROM_DATABASE=Labtec Webcam usb:v046Dp08F5* ID_MODEL_FROM_DATABASE=QuickCam Messenger Communicate usb:v046Dp08F6* ID_MODEL_FROM_DATABASE=QuickCam Messenger Plus usb:v046Dp0900* ID_MODEL_FROM_DATABASE=ClickSmart 310 usb:v046Dp0901* ID_MODEL_FROM_DATABASE=ClickSmart 510 usb:v046Dp0903* ID_MODEL_FROM_DATABASE=ClickSmart 820 usb:v046Dp0905* ID_MODEL_FROM_DATABASE=ClickSmart 820 usb:v046Dp0910* ID_MODEL_FROM_DATABASE=QuickCam Cordless usb:v046Dp0920* ID_MODEL_FROM_DATABASE=QuickCam Express usb:v046Dp0921* ID_MODEL_FROM_DATABASE=Labtec Webcam usb:v046Dp0922* ID_MODEL_FROM_DATABASE=QuickCam Live usb:v046Dp0928* ID_MODEL_FROM_DATABASE=QuickCam Express usb:v046Dp0929* ID_MODEL_FROM_DATABASE=Labtec Webcam Pro usb:v046Dp092A* ID_MODEL_FROM_DATABASE=QuickCam for Notebooks usb:v046Dp092B* ID_MODEL_FROM_DATABASE=Labtec Webcam Plus usb:v046Dp092C* ID_MODEL_FROM_DATABASE=QuickCam Chat usb:v046Dp092D* ID_MODEL_FROM_DATABASE=QuickCam Express / Go usb:v046Dp092E* ID_MODEL_FROM_DATABASE=QuickCam Chat usb:v046Dp092F* ID_MODEL_FROM_DATABASE=QuickCam Express Plus usb:v046Dp0950* ID_MODEL_FROM_DATABASE=Pocket Camera usb:v046Dp0960* ID_MODEL_FROM_DATABASE=ClickSmart 420 usb:v046Dp0970* ID_MODEL_FROM_DATABASE=Pocket750 usb:v046Dp0990* ID_MODEL_FROM_DATABASE=QuickCam Pro 9000 usb:v046Dp0991* ID_MODEL_FROM_DATABASE=QuickCam Pro for Notebooks usb:v046Dp0992* ID_MODEL_FROM_DATABASE=QuickCam Communicate Deluxe usb:v046Dp0994* ID_MODEL_FROM_DATABASE=QuickCam Orbit/Sphere AF usb:v046Dp09A1* ID_MODEL_FROM_DATABASE=QuickCam Communicate MP/S5500 usb:v046Dp09A2* ID_MODEL_FROM_DATABASE=QuickCam Communicate Deluxe/S7500 usb:v046Dp09A4* ID_MODEL_FROM_DATABASE=QuickCam E 3500 usb:v046Dp09A5* ID_MODEL_FROM_DATABASE=Quickcam 3000 For Business usb:v046Dp09A6* ID_MODEL_FROM_DATABASE=QuickCam Vision Pro usb:v046Dp09B0* ID_MODEL_FROM_DATABASE=Acer OrbiCam usb:v046Dp09B2* ID_MODEL_FROM_DATABASE=Fujitsu Webcam usb:v046Dp09C0* ID_MODEL_FROM_DATABASE=QuickCam for Dell Notebooks Mic usb:v046Dp09C1* ID_MODEL_FROM_DATABASE=QuickCam Deluxe for Notebooks usb:v046Dp0A01* ID_MODEL_FROM_DATABASE=USB Headset usb:v046Dp0A02* ID_MODEL_FROM_DATABASE=Premium Stereo USB Headset 350 usb:v046Dp0A03* ID_MODEL_FROM_DATABASE=Logitech USB Microphone usb:v046Dp0A04* ID_MODEL_FROM_DATABASE=V20 portable speakers (USB powered) usb:v046Dp0A07* ID_MODEL_FROM_DATABASE=Z-10 Speakers usb:v046Dp0A0B* ID_MODEL_FROM_DATABASE=ClearChat Pro USB usb:v046Dp0A0C* ID_MODEL_FROM_DATABASE=Clear Chat Comfort USB Headset usb:v046Dp0A13* ID_MODEL_FROM_DATABASE=Z-5 Speakers usb:v046Dp0A17* ID_MODEL_FROM_DATABASE=G330 Headset usb:v046Dp0A1F* ID_MODEL_FROM_DATABASE=G930 usb:v046Dp0A29* ID_MODEL_FROM_DATABASE=H600 [Wireless Headset] usb:v046Dp0A37* ID_MODEL_FROM_DATABASE=USB Headset H540 usb:v046Dp0A38* ID_MODEL_FROM_DATABASE=Headset H340 usb:v046Dp0A44* ID_MODEL_FROM_DATABASE=Headset H390 usb:v046Dp0A4D* ID_MODEL_FROM_DATABASE=G430 Surround Sound Gaming Headset usb:v046Dp0B02* ID_MODEL_FROM_DATABASE=C-UV35 [Bluetooth Mini-Receiver] (HID proxy mode) usb:v046Dp8801* ID_MODEL_FROM_DATABASE=Video Camera usb:v046DpB305* ID_MODEL_FROM_DATABASE=BT Mini-Receiver usb:v046DpBFE4* ID_MODEL_FROM_DATABASE=Premium Optical Wheel Mouse usb:v046DpC000* ID_MODEL_FROM_DATABASE=N43 [Pilot Mouse] usb:v046DpC001* ID_MODEL_FROM_DATABASE=N48/M-BB48/M-UK96A [FirstMouse Plus] usb:v046DpC002* ID_MODEL_FROM_DATABASE=M-BA47 [MouseMan Plus] usb:v046DpC003* ID_MODEL_FROM_DATABASE=MouseMan usb:v046DpC004* ID_MODEL_FROM_DATABASE=WingMan Gaming Mouse usb:v046DpC005* ID_MODEL_FROM_DATABASE=WingMan Gaming Wheel Mouse usb:v046DpC00B* ID_MODEL_FROM_DATABASE=MouseMan Wheel usb:v046DpC00C* ID_MODEL_FROM_DATABASE=Optical Wheel Mouse usb:v046DpC00D* ID_MODEL_FROM_DATABASE=MouseMan Wheel+ usb:v046DpC00E* ID_MODEL_FROM_DATABASE=M-BJ58/M-BJ69 Optical Wheel Mouse usb:v046DpC00F* ID_MODEL_FROM_DATABASE=MouseMan Traveler/Mobile usb:v046DpC011* ID_MODEL_FROM_DATABASE=Optical MouseMan usb:v046DpC012* ID_MODEL_FROM_DATABASE=Mouseman Dual Optical usb:v046DpC014* ID_MODEL_FROM_DATABASE=Corded Workstation Mouse usb:v046DpC015* ID_MODEL_FROM_DATABASE=Corded Workstation Mouse usb:v046DpC016* ID_MODEL_FROM_DATABASE=Optical Wheel Mouse usb:v046DpC018* ID_MODEL_FROM_DATABASE=Optical Wheel Mouse usb:v046DpC019* ID_MODEL_FROM_DATABASE=Optical Tilt Wheel Mouse usb:v046DpC01A* ID_MODEL_FROM_DATABASE=M-BQ85 Optical Wheel Mouse usb:v046DpC01B* ID_MODEL_FROM_DATABASE=MX310 Optical Mouse usb:v046DpC01C* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v046DpC01D* ID_MODEL_FROM_DATABASE=MX510 Optical Mouse usb:v046DpC01E* ID_MODEL_FROM_DATABASE=MX518 Optical Mouse usb:v046DpC024* ID_MODEL_FROM_DATABASE=MX300 Optical Mouse usb:v046DpC025* ID_MODEL_FROM_DATABASE=MX500 Optical Mouse usb:v046DpC030* ID_MODEL_FROM_DATABASE=iFeel Mouse usb:v046DpC031* ID_MODEL_FROM_DATABASE=iFeel Mouse+ usb:v046DpC032* ID_MODEL_FROM_DATABASE=MouseMan iFeel usb:v046DpC033* ID_MODEL_FROM_DATABASE=iFeel MouseMan+ usb:v046DpC034* ID_MODEL_FROM_DATABASE=MouseMan Optical usb:v046DpC035* ID_MODEL_FROM_DATABASE=Mouse usb:v046DpC036* ID_MODEL_FROM_DATABASE=Mouse usb:v046DpC037* ID_MODEL_FROM_DATABASE=Mouse usb:v046DpC038* ID_MODEL_FROM_DATABASE=Mouse usb:v046DpC03D* ID_MODEL_FROM_DATABASE=M-BT96a Pilot Optical Mouse usb:v046DpC03E* ID_MODEL_FROM_DATABASE=Premium Optical Wheel Mouse (M-BT58) usb:v046DpC03F* ID_MODEL_FROM_DATABASE=M-BT85 [UltraX Optical Mouse] usb:v046DpC040* ID_MODEL_FROM_DATABASE=Corded Tilt-Wheel Mouse usb:v046DpC041* ID_MODEL_FROM_DATABASE=G5 Laser Mouse usb:v046DpC042* ID_MODEL_FROM_DATABASE=G3 Laser Mouse usb:v046DpC043* ID_MODEL_FROM_DATABASE=MX320/MX400 Laser Mouse usb:v046DpC044* ID_MODEL_FROM_DATABASE=LX3 Optical Mouse usb:v046DpC045* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v046DpC046* ID_MODEL_FROM_DATABASE=RX1000 Laser Mouse usb:v046DpC047* ID_MODEL_FROM_DATABASE=Laser Mouse M-UAL120 usb:v046DpC048* ID_MODEL_FROM_DATABASE=G9 Laser Mouse usb:v046DpC049* ID_MODEL_FROM_DATABASE=G5 Laser Mouse usb:v046DpC050* ID_MODEL_FROM_DATABASE=RX 250 Optical Mouse usb:v046DpC051* ID_MODEL_FROM_DATABASE=G3 (MX518) Optical Mouse usb:v046DpC053* ID_MODEL_FROM_DATABASE=Laser Mouse usb:v046DpC054* ID_MODEL_FROM_DATABASE=Bluetooth mini-receiver usb:v046DpC058* ID_MODEL_FROM_DATABASE=M115 Mouse usb:v046DpC05A* ID_MODEL_FROM_DATABASE=M90/M100 Optical Mouse usb:v046DpC05B* ID_MODEL_FROM_DATABASE=M-U0004 810-001317 [B110 Optical USB Mouse] usb:v046DpC05D* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v046DpC05F* ID_MODEL_FROM_DATABASE=M115 Optical Mouse usb:v046DpC061* ID_MODEL_FROM_DATABASE=RX1500 Laser Mouse usb:v046DpC062* ID_MODEL_FROM_DATABASE=M-UAS144 [LS1 Laser Mouse] usb:v046DpC063* ID_MODEL_FROM_DATABASE=DELL Laser Mouse usb:v046DpC064* ID_MODEL_FROM_DATABASE=M110 corded optical mouse (M-B0001) usb:v046DpC066* ID_MODEL_FROM_DATABASE=G9x Laser Mouse usb:v046DpC068* ID_MODEL_FROM_DATABASE=G500 Laser Mouse usb:v046DpC069* ID_MODEL_FROM_DATABASE=M-U0007 [Corded Mouse M500] usb:v046DpC06A* ID_MODEL_FROM_DATABASE=USB Optical Mouse usb:v046DpC06B* ID_MODEL_FROM_DATABASE=G700 Wireless Gaming Mouse usb:v046DpC06C* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v046DpC077* ID_MODEL_FROM_DATABASE=M105 Optical Mouse usb:v046DpC07C* ID_MODEL_FROM_DATABASE=M-R0017 [G700s Rechargeable Gaming Mouse] usb:v046DpC101* ID_MODEL_FROM_DATABASE=UltraX Media Remote usb:v046DpC110* ID_MODEL_FROM_DATABASE=Harmony 785/885 Remote usb:v046DpC111* ID_MODEL_FROM_DATABASE=Harmony 525 Remote usb:v046DpC112* ID_MODEL_FROM_DATABASE=Harmony 890 Remote usb:v046DpC11F* ID_MODEL_FROM_DATABASE=Harmony 900/1100 Remote usb:v046DpC121* ID_MODEL_FROM_DATABASE=Harmony One Remote usb:v046DpC122* ID_MODEL_FROM_DATABASE=Harmony 650/700 Remote usb:v046DpC124* ID_MODEL_FROM_DATABASE=Harmony 300/350 Remote usb:v046DpC125* ID_MODEL_FROM_DATABASE=Harmony 200 Remote usb:v046DpC126* ID_MODEL_FROM_DATABASE=Harmony Link usb:v046DpC129* ID_MODEL_FROM_DATABASE=Harmony Hub usb:v046DpC12B* ID_MODEL_FROM_DATABASE=Harmony Touch/Ultimate Remote usb:v046DpC201* ID_MODEL_FROM_DATABASE=WingMan Extreme Joystick with Throttle usb:v046DpC202* ID_MODEL_FROM_DATABASE=WingMan Formula usb:v046DpC207* ID_MODEL_FROM_DATABASE=WingMan Extreme Digital 3D usb:v046DpC208* ID_MODEL_FROM_DATABASE=WingMan Gamepad Extreme usb:v046DpC209* ID_MODEL_FROM_DATABASE=WingMan Gamepad usb:v046DpC20A* ID_MODEL_FROM_DATABASE=WingMan RumblePad usb:v046DpC20B* ID_MODEL_FROM_DATABASE=WingMan Action Pad usb:v046DpC20C* ID_MODEL_FROM_DATABASE=WingMan Precision usb:v046DpC20D* ID_MODEL_FROM_DATABASE=WingMan Attack 2 usb:v046DpC20E* ID_MODEL_FROM_DATABASE=WingMan Formula GP usb:v046DpC211* ID_MODEL_FROM_DATABASE=iTouch Cordless Reciever usb:v046DpC212* ID_MODEL_FROM_DATABASE=WingMan Extreme Digital 3D usb:v046DpC213* ID_MODEL_FROM_DATABASE=J-UH16 (Freedom 2.4 Cordless Joystick) usb:v046DpC214* ID_MODEL_FROM_DATABASE=ATK3 (Attack III Joystick) usb:v046DpC215* ID_MODEL_FROM_DATABASE=Extreme 3D Pro usb:v046DpC216* ID_MODEL_FROM_DATABASE=Dual Action Gamepad usb:v046DpC218* ID_MODEL_FROM_DATABASE=Logitech RumblePad 2 USB usb:v046DpC219* ID_MODEL_FROM_DATABASE=Cordless RumblePad 2 usb:v046DpC21A* ID_MODEL_FROM_DATABASE=Precision Gamepad usb:v046DpC21C* ID_MODEL_FROM_DATABASE=G13 Advanced Gameboard usb:v046DpC21D* ID_MODEL_FROM_DATABASE=F310 Gamepad [XInput Mode] usb:v046DpC21E* ID_MODEL_FROM_DATABASE=F510 Gamepad [XInput Mode] usb:v046DpC21F* ID_MODEL_FROM_DATABASE=F710 Wireless Gamepad [XInput Mode] usb:v046DpC221* ID_MODEL_FROM_DATABASE=G11/G15 Keyboard / Keyboard usb:v046DpC222* ID_MODEL_FROM_DATABASE=G15 Keyboard / LCD usb:v046DpC223* ID_MODEL_FROM_DATABASE=G11/G15 Keyboard / USB Hub usb:v046DpC225* ID_MODEL_FROM_DATABASE=G11/G15 Keyboard / G keys usb:v046DpC226* ID_MODEL_FROM_DATABASE=G15 Refresh Keyboard usb:v046DpC227* ID_MODEL_FROM_DATABASE=G15 Refresh Keyboard usb:v046DpC228* ID_MODEL_FROM_DATABASE=G19 Gaming Keyboard usb:v046DpC229* ID_MODEL_FROM_DATABASE=G19 Gaming Keyboard Macro Interface usb:v046DpC22A* ID_MODEL_FROM_DATABASE=Gaming Keyboard G110 usb:v046DpC22B* ID_MODEL_FROM_DATABASE=Gaming Keyboard G110 G-keys usb:v046DpC22D* ID_MODEL_FROM_DATABASE=G510 Gaming Keyboard usb:v046DpC22E* ID_MODEL_FROM_DATABASE=G510 Gaming Keyboard onboard audio usb:v046DpC245* ID_MODEL_FROM_DATABASE=G400 Optical Mouse usb:v046DpC246* ID_MODEL_FROM_DATABASE=Gaming Mouse G300 usb:v046DpC248* ID_MODEL_FROM_DATABASE=G105 Gaming Keyboard usb:v046DpC24A* ID_MODEL_FROM_DATABASE=G600 Gaming Mouse usb:v046DpC24C* ID_MODEL_FROM_DATABASE=G400s Optical Mouse usb:v046DpC24D* ID_MODEL_FROM_DATABASE=G710 Gaming Keyboard usb:v046DpC24E* ID_MODEL_FROM_DATABASE=G500s Laser Gaming Mouse usb:v046DpC281* ID_MODEL_FROM_DATABASE=WingMan Force usb:v046DpC283* ID_MODEL_FROM_DATABASE=WingMan Force 3D usb:v046DpC285* ID_MODEL_FROM_DATABASE=WingMan Strike Force 3D usb:v046DpC286* ID_MODEL_FROM_DATABASE=Force 3D Pro usb:v046DpC287* ID_MODEL_FROM_DATABASE=Flight System G940 usb:v046DpC291* ID_MODEL_FROM_DATABASE=WingMan Formula Force usb:v046DpC293* ID_MODEL_FROM_DATABASE=WingMan Formula Force GP usb:v046DpC294* ID_MODEL_FROM_DATABASE=Driving Force usb:v046DpC295* ID_MODEL_FROM_DATABASE=Momo Force Steering Wheel usb:v046DpC298* ID_MODEL_FROM_DATABASE=Driving Force Pro usb:v046DpC299* ID_MODEL_FROM_DATABASE=G25 Racing Wheel usb:v046DpC29B* ID_MODEL_FROM_DATABASE=G27 Racing Wheel usb:v046DpC29C* ID_MODEL_FROM_DATABASE=Speed Force Wireless Wheel for Wii usb:v046DpC2A0* ID_MODEL_FROM_DATABASE=Wingman Force Feedback Mouse usb:v046DpC2A1* ID_MODEL_FROM_DATABASE=WingMan Force Feedback Mouse usb:v046DpC301* ID_MODEL_FROM_DATABASE=iTouch Keyboard usb:v046DpC302* ID_MODEL_FROM_DATABASE=iTouch Pro Keyboard usb:v046DpC303* ID_MODEL_FROM_DATABASE=iTouch Keyboard usb:v046DpC305* ID_MODEL_FROM_DATABASE=Internet Keyboard usb:v046DpC307* ID_MODEL_FROM_DATABASE=Internet Keyboard usb:v046DpC308* ID_MODEL_FROM_DATABASE=Internet Navigator Keyboard usb:v046DpC309* ID_MODEL_FROM_DATABASE=Y-BF37 [Internet Navigator Keyboard] usb:v046DpC30A* ID_MODEL_FROM_DATABASE=iTouch Composite usb:v046DpC30B* ID_MODEL_FROM_DATABASE=NetPlay Keyboard usb:v046DpC30C* ID_MODEL_FROM_DATABASE=Internet Keys (X) usb:v046DpC30D* ID_MODEL_FROM_DATABASE=Internet Keys usb:v046DpC30E* ID_MODEL_FROM_DATABASE=UltraX Keyboard (Y-BL49) usb:v046DpC30F* ID_MODEL_FROM_DATABASE=Logicool HID-Compliant Keyboard (106 key) usb:v046DpC311* ID_MODEL_FROM_DATABASE=Y-UF49 [Internet Pro Keyboard] usb:v046DpC312* ID_MODEL_FROM_DATABASE=DeLuxe 250 Keyboard usb:v046DpC313* ID_MODEL_FROM_DATABASE=Internet 350 Keyboard usb:v046DpC315* ID_MODEL_FROM_DATABASE=Classic Keyboard 200 usb:v046DpC316* ID_MODEL_FROM_DATABASE=HID-Compliant Keyboard usb:v046DpC317* ID_MODEL_FROM_DATABASE=Wave Corded Keyboard usb:v046DpC318* ID_MODEL_FROM_DATABASE=Illuminated Keyboard usb:v046DpC31A* ID_MODEL_FROM_DATABASE=Comfort Wave 450 usb:v046DpC31B* ID_MODEL_FROM_DATABASE=Compact Keyboard K300 usb:v046DpC31C* ID_MODEL_FROM_DATABASE=Keyboard K120 usb:v046DpC31D* ID_MODEL_FROM_DATABASE=Media Keyboard K200 usb:v046DpC401* ID_MODEL_FROM_DATABASE=TrackMan Marble Wheel usb:v046DpC402* ID_MODEL_FROM_DATABASE=Marble Mouse (2-button) usb:v046DpC403* ID_MODEL_FROM_DATABASE=Turbo TrackMan Marble FX usb:v046DpC404* ID_MODEL_FROM_DATABASE=TrackMan Wheel usb:v046DpC408* ID_MODEL_FROM_DATABASE=Marble Mouse (4-button) usb:v046DpC501* ID_MODEL_FROM_DATABASE=Cordless Mouse Receiver usb:v046DpC502* ID_MODEL_FROM_DATABASE=Cordless Mouse & iTouch Keys usb:v046DpC503* ID_MODEL_FROM_DATABASE=Cordless Mouse+Keyboard Receiver usb:v046DpC504* ID_MODEL_FROM_DATABASE=Cordless Mouse+Keyboard Receiver usb:v046DpC505* ID_MODEL_FROM_DATABASE=Cordless Mouse+Keyboard Receiver usb:v046DpC506* ID_MODEL_FROM_DATABASE=MX700 Cordless Mouse Receiver usb:v046DpC508* ID_MODEL_FROM_DATABASE=Cordless Trackball usb:v046DpC509* ID_MODEL_FROM_DATABASE=Cordless Keyboard & Mouse usb:v046DpC50A* ID_MODEL_FROM_DATABASE=Cordless Mouse usb:v046DpC50B* ID_MODEL_FROM_DATABASE=Cordless Desktop Optical usb:v046DpC50C* ID_MODEL_FROM_DATABASE=Cordless Desktop S510 usb:v046DpC50D* ID_MODEL_FROM_DATABASE=Cordless Mouse usb:v046DpC50E* ID_MODEL_FROM_DATABASE=Cordless Mouse Receiver usb:v046DpC510* ID_MODEL_FROM_DATABASE=Cordless Mouse usb:v046DpC512* ID_MODEL_FROM_DATABASE=LX-700 Cordless Desktop Receiver usb:v046DpC513* ID_MODEL_FROM_DATABASE=MX3000 Cordless Desktop Receiver usb:v046DpC514* ID_MODEL_FROM_DATABASE=Cordless Mouse usb:v046DpC515* ID_MODEL_FROM_DATABASE=Cordless 2.4 GHz Presenter Presentation remote control usb:v046DpC517* ID_MODEL_FROM_DATABASE=LX710 Cordless Desktop Laser usb:v046DpC518* ID_MODEL_FROM_DATABASE=MX610 Laser Cordless Mouse usb:v046DpC51A* ID_MODEL_FROM_DATABASE=MX Revolution/G7 Cordless Mouse usb:v046DpC51B* ID_MODEL_FROM_DATABASE=V220 Cordless Optical Mouse for Notebooks usb:v046DpC521* ID_MODEL_FROM_DATABASE=Cordless Mouse Receiver usb:v046DpC525* ID_MODEL_FROM_DATABASE=MX Revolution Cordless Mouse usb:v046DpC526* ID_MODEL_FROM_DATABASE=Nano Receiver usb:v046DpC529* ID_MODEL_FROM_DATABASE=Logitech Keyboard + Mice usb:v046DpC52B* ID_MODEL_FROM_DATABASE=Unifying Receiver usb:v046DpC52D* ID_MODEL_FROM_DATABASE=R700 Remote Presenter receiver usb:v046DpC52E* ID_MODEL_FROM_DATABASE=MK260 Wireless Combo Receiver usb:v046DpC52F* ID_MODEL_FROM_DATABASE=Unifying Receiver usb:v046DpC531* ID_MODEL_FROM_DATABASE=C-U0007 [Unifying Receiver] usb:v046DpC532* ID_MODEL_FROM_DATABASE=Unifying Receiver usb:v046DpC534* ID_MODEL_FROM_DATABASE=Unifying Receiver usb:v046DpC603* ID_MODEL_FROM_DATABASE=3Dconnexion Spacemouse Plus XT usb:v046DpC605* ID_MODEL_FROM_DATABASE=3Dconnexion CADman usb:v046DpC606* ID_MODEL_FROM_DATABASE=3Dconnexion Spacemouse Classic usb:v046DpC621* ID_MODEL_FROM_DATABASE=3Dconnexion Spaceball 5000 usb:v046DpC623* ID_MODEL_FROM_DATABASE=3Dconnexion Space Traveller 3D Mouse usb:v046DpC625* ID_MODEL_FROM_DATABASE=3Dconnexion Space Pilot 3D Mouse usb:v046DpC626* ID_MODEL_FROM_DATABASE=3Dconnexion Space Navigator 3D Mouse usb:v046DpC627* ID_MODEL_FROM_DATABASE=3Dconnexion Space Explorer 3D Mouse usb:v046DpC628* ID_MODEL_FROM_DATABASE=3Dconnexion Space Navigator for Notebooks usb:v046DpC629* ID_MODEL_FROM_DATABASE=3Dconnexion SpacePilot Pro 3D Mouse usb:v046DpC62B* ID_MODEL_FROM_DATABASE=3Dconnexion Space Mouse Pro usb:v046DpC640* ID_MODEL_FROM_DATABASE=NuLOOQ navigator usb:v046DpC702* ID_MODEL_FROM_DATABASE=Cordless Presenter usb:v046DpC703* ID_MODEL_FROM_DATABASE=Elite Keyboard Y-RP20 + Mouse MX900 (Bluetooth) usb:v046DpC704* ID_MODEL_FROM_DATABASE=diNovo Wireless Desktop usb:v046DpC705* ID_MODEL_FROM_DATABASE=MX900 Bluetooth Wireless Hub (C-UJ16A) usb:v046DpC707* ID_MODEL_FROM_DATABASE=Bluetooth wireless hub usb:v046DpC708* ID_MODEL_FROM_DATABASE=Bluetooth wireless hub usb:v046DpC709* ID_MODEL_FROM_DATABASE=BT Mini-Receiver (HCI mode) usb:v046DpC70A* ID_MODEL_FROM_DATABASE=MX5000 Cordless Desktop usb:v046DpC70B* ID_MODEL_FROM_DATABASE=BT Mini-Receiver (HID proxy mode) usb:v046DpC70C* ID_MODEL_FROM_DATABASE=BT Mini-Receiver (HID proxy mode) usb:v046DpC70D* ID_MODEL_FROM_DATABASE=Bluetooth wireless hub usb:v046DpC70E* ID_MODEL_FROM_DATABASE=MX1000 Bluetooth Laser Mouse usb:v046DpC70F* ID_MODEL_FROM_DATABASE=Bluetooth wireless hub usb:v046DpC712* ID_MODEL_FROM_DATABASE=Bluetooth wireless hub usb:v046DpC714* ID_MODEL_FROM_DATABASE=diNovo Edge Keyboard usb:v046DpC715* ID_MODEL_FROM_DATABASE=Bluetooth wireless hub usb:v046DpC71A* ID_MODEL_FROM_DATABASE=Bluetooth wireless hub usb:v046DpC71D* ID_MODEL_FROM_DATABASE=Bluetooth wireless hub usb:v046DpC71F* ID_MODEL_FROM_DATABASE=diNovo Mini Wireless Keyboard usb:v046DpC720* ID_MODEL_FROM_DATABASE=Bluetooth wireless hub usb:v046DpCA03* ID_MODEL_FROM_DATABASE=MOMO Racing usb:v046DpCA04* ID_MODEL_FROM_DATABASE=Formula Vibration Feedback Wheel usb:v046DpCAB1* ID_MODEL_FROM_DATABASE=Cordless Keyboard for Wii HID Receiver usb:v046DpD001* ID_MODEL_FROM_DATABASE=QuickCam Pro usb:v046E* ID_VENDOR_FROM_DATABASE=Behavior Tech. Computer Corp. usb:v046Ep0100* ID_MODEL_FROM_DATABASE=Keyboard usb:v046Ep3001* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v046Ep3002* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v046Ep3003* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v046Ep3005* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v046Ep3008* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v046Ep5250* ID_MODEL_FROM_DATABASE=KeyMaestro Multimedia Keyboard usb:v046Ep5273* ID_MODEL_FROM_DATABASE=KeyMaestro Multimedia Keyboard usb:v046Ep52E6* ID_MODEL_FROM_DATABASE=Cordless Mouse usb:v046Ep5308* ID_MODEL_FROM_DATABASE=KeyMaestro Keyboard usb:v046Ep5408* ID_MODEL_FROM_DATABASE=KeyMaestro Multimedia Keyboard/Hub usb:v046Ep5500* ID_MODEL_FROM_DATABASE=Portable Keyboard 86+9 keys (Model 6100C US) usb:v046Ep5550* ID_MODEL_FROM_DATABASE=5 button optical mouse model M873U usb:v046Ep5720* ID_MODEL_FROM_DATABASE=Smart Card Reader usb:v046Ep6782* ID_MODEL_FROM_DATABASE=BTC 7932 mouse+keyboard usb:v046F* ID_VENDOR_FROM_DATABASE=Crystal Semiconductor usb:v0471* ID_VENDOR_FROM_DATABASE=Philips (or NXP) usb:v0471p0101* ID_MODEL_FROM_DATABASE=DSS350 Digital Speaker System usb:v0471p0104* ID_MODEL_FROM_DATABASE=DSS330 Digital Speaker System [uda1321] usb:v0471p0105* ID_MODEL_FROM_DATABASE=UDA1321 usb:v0471p014F* ID_MODEL_FROM_DATABASE=GoGear SA9200 usb:v0471p0160* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0471p0161* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0471p0163* ID_MODEL_FROM_DATABASE=GoGear SA1100 usb:v0471p0164* ID_MODEL_FROM_DATABASE=GoGear SA1110/02 usb:v0471p0165* ID_MODEL_FROM_DATABASE=GoGear SA1330 usb:v0471p0201* ID_MODEL_FROM_DATABASE=Hub usb:v0471p0222* ID_MODEL_FROM_DATABASE=Creative Nomad Jukebox usb:v0471p0302* ID_MODEL_FROM_DATABASE=PCA645VC Webcam [pwc] usb:v0471p0303* ID_MODEL_FROM_DATABASE=PCA646VC Webcam [pwc] usb:v0471p0304* ID_MODEL_FROM_DATABASE=Askey VC010 Webcam [pwc] usb:v0471p0307* ID_MODEL_FROM_DATABASE=PCVC675K Webcam [pwc] usb:v0471p0308* ID_MODEL_FROM_DATABASE=PCVC680K Webcam [pwc] usb:v0471p030B* ID_MODEL_FROM_DATABASE=PC VGA Camera (Vesta Fun) usb:v0471p030C* ID_MODEL_FROM_DATABASE=PCVC690K Webcam [pwc] usb:v0471p0310* ID_MODEL_FROM_DATABASE=PCVC730K Webcam [pwc] usb:v0471p0311* ID_MODEL_FROM_DATABASE=PCVC740K ToUcam Pro [pwc] usb:v0471p0312* ID_MODEL_FROM_DATABASE=PCVC750K Webcam [pwc] usb:v0471p0314* ID_MODEL_FROM_DATABASE=DMVC 1000K usb:v0471p0316* ID_MODEL_FROM_DATABASE=DMVC 2000K Video Capture usb:v0471p0321* ID_MODEL_FROM_DATABASE=FunCam usb:v0471p0322* ID_MODEL_FROM_DATABASE=DMVC1300K PC Camera usb:v0471p0325* ID_MODEL_FROM_DATABASE=SPC 200NC PC Camera usb:v0471p0326* ID_MODEL_FROM_DATABASE=SPC 300NC PC Camera usb:v0471p0327* ID_MODEL_FROM_DATABASE=Webcam SPC 6000 NC (Webcam w/ mic) usb:v0471p0328* ID_MODEL_FROM_DATABASE=SPC 700NC PC Camera usb:v0471p0329* ID_MODEL_FROM_DATABASE=SPC 900NC PC Camera / ORITE CCD Webcam(PC370R) usb:v0471p032D* ID_MODEL_FROM_DATABASE=SPC 210NC PC Camera usb:v0471p032E* ID_MODEL_FROM_DATABASE=SPC 315NC PC Camera usb:v0471p0330* ID_MODEL_FROM_DATABASE=SPC 710NC PC Camera usb:v0471p0331* ID_MODEL_FROM_DATABASE=SPC 1300NC PC Camera usb:v0471p0332* ID_MODEL_FROM_DATABASE=SPC 1000NC PC Camera usb:v0471p0333* ID_MODEL_FROM_DATABASE=SPC 620NC PC Camera usb:v0471p0334* ID_MODEL_FROM_DATABASE=SPC 520/525NC PC Camera usb:v0471p0401* ID_MODEL_FROM_DATABASE=Semiconductors CICT Keyboard usb:v0471p0402* ID_MODEL_FROM_DATABASE=PS/2 Mouse on Semiconductors CICT Keyboard usb:v0471p0406* ID_MODEL_FROM_DATABASE=15 inch Detachable Monitor usb:v0471p0407* ID_MODEL_FROM_DATABASE=10 inch Mobile Monitor usb:v0471p0408* ID_MODEL_FROM_DATABASE=SG3WA1/74 802.11b WLAN Adapter [Atmel AT76C503A] usb:v0471p0471* ID_MODEL_FROM_DATABASE=Digital Speaker System usb:v0471p0601* ID_MODEL_FROM_DATABASE=OVU1020 IR Dongle (Kbd+Mouse) usb:v0471p0602* ID_MODEL_FROM_DATABASE=ATI Remote Wonder II Input Device usb:v0471p0603* ID_MODEL_FROM_DATABASE=ATI Remote Wonder II Controller usb:v0471p0608* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v0471p060A* ID_MODEL_FROM_DATABASE=TSU9600 Remote Control usb:v0471p060C* ID_MODEL_FROM_DATABASE=Consumer Infrared Transceiver (HP) usb:v0471p060D* ID_MODEL_FROM_DATABASE=Consumer Infrared Transceiver (SRM5100) usb:v0471p060E* ID_MODEL_FROM_DATABASE=RF Dongle usb:v0471p060F* ID_MODEL_FROM_DATABASE=Consumer Infrared Transceiver usb:v0471p0613* ID_MODEL_FROM_DATABASE=Infrared Transceiver usb:v0471p0617* ID_MODEL_FROM_DATABASE=IEEE802.15.4 RF Dongle usb:v0471p0619* ID_MODEL_FROM_DATABASE=TSU9400 Remote Control usb:v0471p0666* ID_MODEL_FROM_DATABASE=Hantek DDS-3005 Arbitrary Waveform Generator usb:v0471p0700* ID_MODEL_FROM_DATABASE=Semiconductors CICT Hub usb:v0471p0701* ID_MODEL_FROM_DATABASE=150P1 TFT Display usb:v0471p0809* ID_MODEL_FROM_DATABASE=AVNET Bluetooth Device usb:v0471p0811* ID_MODEL_FROM_DATABASE=JR24 CDRW usb:v0471p0814* ID_MODEL_FROM_DATABASE=DCCX38/P data cable usb:v0471p0815* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v0471p0844* ID_MODEL_FROM_DATABASE=SA2111/02 1GB Flash Audio Player usb:v0471p084A* ID_MODEL_FROM_DATABASE=GoGear SA3125 usb:v0471p084E* ID_MODEL_FROM_DATABASE=GoGear SA60xx (mtp) usb:v0471p0888* ID_MODEL_FROM_DATABASE=Hantek DDS-3005 Arbitrary Waveform Generator usb:v0471p1103* ID_MODEL_FROM_DATABASE=Digital Speaker System usb:v0471p1120* ID_MODEL_FROM_DATABASE=Creative Rhomba MP3 player usb:v0471p1125* ID_MODEL_FROM_DATABASE=Nike psa[128max Player usb:v0471p1137* ID_MODEL_FROM_DATABASE=HDD065 MP3 player usb:v0471p1201* ID_MODEL_FROM_DATABASE=Arima Bluetooth Device usb:v0471p1230* ID_MODEL_FROM_DATABASE=Wireless Adapter 11g usb:v0471p1232* ID_MODEL_FROM_DATABASE=SNU6500 Wireless Adapter usb:v0471p1233* ID_MODEL_FROM_DATABASE=Wireless Adapter Bootloader Download usb:v0471p1236* ID_MODEL_FROM_DATABASE=SNU5600 802.11bg usb:v0471p1237* ID_MODEL_FROM_DATABASE=TalkTalk SNU5630NS/05 802.11bg usb:v0471p1552* ID_MODEL_FROM_DATABASE=ISP 1581 Hi-Speed USB MPEG2 Encoder Reference Kit usb:v0471p1801* ID_MODEL_FROM_DATABASE=Diva MP3 player usb:v0471p200A* ID_MODEL_FROM_DATABASE=Wireless Network Adapter usb:v0471p200F* ID_MODEL_FROM_DATABASE=802.11n Wireless Adapter usb:v0471p2021* ID_MODEL_FROM_DATABASE=SDE3273FC/97 2.5" SATA HDD Enclosure [INIC-1608L] usb:v0471p2022* ID_MODEL_FROM_DATABASE=GoGear SA52XX usb:v0471p2034* ID_MODEL_FROM_DATABASE=Webcam SPC530NC usb:v0471p2036* ID_MODEL_FROM_DATABASE=Webcam SPC1030NC usb:v0471p203F* ID_MODEL_FROM_DATABASE=TSU9200 Remote Control usb:v0471p2046* ID_MODEL_FROM_DATABASE=TSU9800 Remote Control usb:v0471p204E* ID_MODEL_FROM_DATABASE=GoGear RaGa (SA1942/02) usb:v0471p205E* ID_MODEL_FROM_DATABASE=TSU9300 Remote Control usb:v0471p206C* ID_MODEL_FROM_DATABASE=MCE IR Receiver - Spinel plusf0r ASUS usb:v0471p2070* ID_MODEL_FROM_DATABASE=GoGear Mix usb:v0471p2076* ID_MODEL_FROM_DATABASE=GoGear Aria usb:v0471p2079* ID_MODEL_FROM_DATABASE=GoGear Opus usb:v0471p2088* ID_MODEL_FROM_DATABASE=MCE IR Receiver with ALS- Spinel plus for ASUS usb:v0471p209E* ID_MODEL_FROM_DATABASE=PTA01 Wireless Adapter usb:v0471p20B6* ID_MODEL_FROM_DATABASE=GoGear Vibe usb:v0471p20D0* ID_MODEL_FROM_DATABASE=SPZ2000 Webcam [PixArt PAC7332] usb:v0471p20E3* ID_MODEL_FROM_DATABASE=GoGear Raga usb:v0471p20E4* ID_MODEL_FROM_DATABASE=GoGear ViBE 8GB usb:v0471p2160* ID_MODEL_FROM_DATABASE=Mio LINK Heart Rate Monitor usb:v0471p262C* ID_MODEL_FROM_DATABASE=SPC230NC Webcam usb:v0471p485D* ID_MODEL_FROM_DATABASE=Senselock SenseIV v2.x usb:v0471pDF55* ID_MODEL_FROM_DATABASE=LPCXpresso LPC-Link usb:v0472* ID_VENDOR_FROM_DATABASE=Chicony Electronics Co., Ltd usb:v0472p0065* ID_MODEL_FROM_DATABASE=PFU-65 Keyboard [Chicony] usb:v0472pB086* ID_MODEL_FROM_DATABASE=Asus USB2.0 Webcam usb:v0472pB091* ID_MODEL_FROM_DATABASE=Webcam usb:v0473* ID_VENDOR_FROM_DATABASE=Sanyo Information Business Co., Ltd usb:v0474* ID_VENDOR_FROM_DATABASE=Sanyo Electric Co., Ltd usb:v0474p0110* ID_MODEL_FROM_DATABASE=Digital Voice Recorder R200 usb:v0474p0217* ID_MODEL_FROM_DATABASE=Xacti J2 usb:v0474p022F* ID_MODEL_FROM_DATABASE=C5 Digital Media Camera (mass storage mode) usb:v0474p0230* ID_MODEL_FROM_DATABASE=C5 Digital Media Camera (PictBridge mode) usb:v0474p0231* ID_MODEL_FROM_DATABASE=C5 Digital Media Camera (PC control mode) usb:v0474p0401* ID_MODEL_FROM_DATABASE=Optical Drive usb:v0474p0701* ID_MODEL_FROM_DATABASE=SCP-4900 Cellphone usb:v0474p071F* ID_MODEL_FROM_DATABASE=Usb Com Port Enumerator usb:v0474p0722* ID_MODEL_FROM_DATABASE=W33SA Camera usb:v0475* ID_VENDOR_FROM_DATABASE=Relisys/Teco Information System usb:v0475p0100* ID_MODEL_FROM_DATABASE=NEC Petiscan usb:v0475p0103* ID_MODEL_FROM_DATABASE=Eclipse 1200U/Episode usb:v0475p0210* ID_MODEL_FROM_DATABASE=Scorpio Ultra 3 usb:v0476* ID_VENDOR_FROM_DATABASE=AESP usb:v0477* ID_VENDOR_FROM_DATABASE=Seagate Technology, Inc. usb:v0478* ID_VENDOR_FROM_DATABASE=Connectix Corp. usb:v0478p0001* ID_MODEL_FROM_DATABASE=QuickCam usb:v0478p0002* ID_MODEL_FROM_DATABASE=QuickClip usb:v0478p0003* ID_MODEL_FROM_DATABASE=QuickCam Pro usb:v0479* ID_VENDOR_FROM_DATABASE=Advanced Peripheral Laboratories usb:v047A* ID_VENDOR_FROM_DATABASE=Semtech Corp. usb:v047Ap0004* ID_MODEL_FROM_DATABASE=ScreenCoder UR7HCTS2-USB usb:v047B* ID_VENDOR_FROM_DATABASE=Silitek Corp. usb:v047Bp0001* ID_MODEL_FROM_DATABASE=Keyboard usb:v047Bp0002* ID_MODEL_FROM_DATABASE=Keyboard and Mouse usb:v047Bp0011* ID_MODEL_FROM_DATABASE=SK-1688U Keyboard usb:v047Bp00F9* ID_MODEL_FROM_DATABASE=SK-1789u Keyboard usb:v047Bp0101* ID_MODEL_FROM_DATABASE=BlueTooth Keyboard and Mouse usb:v047Bp020B* ID_MODEL_FROM_DATABASE=SK-3105 SmartCard Reader usb:v047Bp050E* ID_MODEL_FROM_DATABASE=Internet Compact Keyboard usb:v047Bp1000* ID_MODEL_FROM_DATABASE=Trust Office Scan USB 19200 usb:v047Bp1002* ID_MODEL_FROM_DATABASE=HP ScanJet 4300c Parallel Port usb:v047C* ID_VENDOR_FROM_DATABASE=Dell Computer Corp. usb:v047CpFFFF* ID_MODEL_FROM_DATABASE=UPS Tower 500W LV usb:v047D* ID_VENDOR_FROM_DATABASE=Kensington usb:v047Dp1001* ID_MODEL_FROM_DATABASE=Mouse*in*a*Box usb:v047Dp1002* ID_MODEL_FROM_DATABASE=Expert Mouse Pro usb:v047Dp1003* ID_MODEL_FROM_DATABASE=Orbit TrackBall usb:v047Dp1004* ID_MODEL_FROM_DATABASE=MouseWorks usb:v047Dp1005* ID_MODEL_FROM_DATABASE=TurboBall usb:v047Dp1006* ID_MODEL_FROM_DATABASE=TurboRing usb:v047Dp1009* ID_MODEL_FROM_DATABASE=Orbit TrackBall for Mac usb:v047Dp1012* ID_MODEL_FROM_DATABASE=PocketMouse usb:v047Dp1013* ID_MODEL_FROM_DATABASE=Mouse*in*a*Box Optical Pro usb:v047Dp1014* ID_MODEL_FROM_DATABASE=Expert Mouse Pro Wireless usb:v047Dp1015* ID_MODEL_FROM_DATABASE=Expert Mouse usb:v047Dp1016* ID_MODEL_FROM_DATABASE=ADB/USB Orbit usb:v047Dp1018* ID_MODEL_FROM_DATABASE=Studio Mouse usb:v047Dp101D* ID_MODEL_FROM_DATABASE=Mouse*in*a*Box Optical Pro usb:v047Dp101E* ID_MODEL_FROM_DATABASE=Studio Mouse Wireless usb:v047Dp101F* ID_MODEL_FROM_DATABASE=PocketMouse Pro usb:v047Dp1020* ID_MODEL_FROM_DATABASE=Expert Mouse Trackball usb:v047Dp1021* ID_MODEL_FROM_DATABASE=Expert Mouse Wireless usb:v047Dp1022* ID_MODEL_FROM_DATABASE=Orbit Optical usb:v047Dp1023* ID_MODEL_FROM_DATABASE=Pocket Mouse Pro Wireless usb:v047Dp1024* ID_MODEL_FROM_DATABASE=PocketMouse usb:v047Dp1025* ID_MODEL_FROM_DATABASE=Mouse*in*a*Box Optical Elite Wireless usb:v047Dp1026* ID_MODEL_FROM_DATABASE=Pocket Mouse Pro usb:v047Dp1027* ID_MODEL_FROM_DATABASE=StudioMouse usb:v047Dp1028* ID_MODEL_FROM_DATABASE=StudioMouse Wireless usb:v047Dp1029* ID_MODEL_FROM_DATABASE=Mouse*in*a*Box Optical Elite usb:v047Dp102A* ID_MODEL_FROM_DATABASE=Mouse*in*a*Box Optical usb:v047Dp102B* ID_MODEL_FROM_DATABASE=PocketMouse usb:v047Dp102C* ID_MODEL_FROM_DATABASE=Iridio usb:v047Dp102D* ID_MODEL_FROM_DATABASE=Pilot Optical usb:v047Dp102E* ID_MODEL_FROM_DATABASE=Pilot Optical Pro usb:v047Dp102F* ID_MODEL_FROM_DATABASE=Pilot Optical Pro Wireless usb:v047Dp1042* ID_MODEL_FROM_DATABASE=Ci25m Notebook Optical Mouse [Diamond Eye Precision] usb:v047Dp1043* ID_MODEL_FROM_DATABASE=Ci65m Wireless Notebook Optical Mouse usb:v047Dp104A* ID_MODEL_FROM_DATABASE=PilotMouse Mini Retractable usb:v047Dp105D* ID_MODEL_FROM_DATABASE=PocketMouse Bluetooth usb:v047Dp105E* ID_MODEL_FROM_DATABASE=Bluetooth EDR Dongle usb:v047Dp1061* ID_MODEL_FROM_DATABASE=PocketMouse Grip usb:v047Dp1062* ID_MODEL_FROM_DATABASE=PocketMouse Max usb:v047Dp1063* ID_MODEL_FROM_DATABASE=PocketMouse Max Wireless usb:v047Dp1064* ID_MODEL_FROM_DATABASE=PocketMouse 2.0 Wireless usb:v047Dp1065* ID_MODEL_FROM_DATABASE=PocketMouse 2.0 usb:v047Dp1066* ID_MODEL_FROM_DATABASE=PocketMouse Max Glow usb:v047Dp1067* ID_MODEL_FROM_DATABASE=ValueMouse usb:v047Dp1068* ID_MODEL_FROM_DATABASE=ValueOpt White usb:v047Dp1069* ID_MODEL_FROM_DATABASE=ValueOpt Black usb:v047Dp106A* ID_MODEL_FROM_DATABASE=PilotMouse Laser Wireless Mini usb:v047Dp106B* ID_MODEL_FROM_DATABASE=PilotMouse Laser - 3 Button usb:v047Dp106C* ID_MODEL_FROM_DATABASE=PilotMouse Laser - Gaming usb:v047Dp106D* ID_MODEL_FROM_DATABASE=PilotMouse Laser - Wired usb:v047Dp106E* ID_MODEL_FROM_DATABASE=PilotMouse Micro Laser usb:v047Dp1070* ID_MODEL_FROM_DATABASE=ValueOpt Travel usb:v047Dp1071* ID_MODEL_FROM_DATABASE=ValueOpt RF TX usb:v047Dp1072* ID_MODEL_FROM_DATABASE=PocketMouse Colour usb:v047Dp1073* ID_MODEL_FROM_DATABASE=PilotMouse Laser - 6 Button usb:v047Dp1074* ID_MODEL_FROM_DATABASE=PilotMouse Laser Wireless Mini usb:v047Dp1075* ID_MODEL_FROM_DATABASE=SlimBlade Presenter Media Mouse usb:v047Dp1076* ID_MODEL_FROM_DATABASE=SlimBlade Media Mouse usb:v047Dp1077* ID_MODEL_FROM_DATABASE=SlimBlade Presenter Mouse usb:v047Dp1152* ID_MODEL_FROM_DATABASE=Bluetooth EDR Dongle usb:v047Dp2002* ID_MODEL_FROM_DATABASE=Optical Elite Wireless usb:v047Dp2010* ID_MODEL_FROM_DATABASE=Wireless Presentation Remote usb:v047Dp2012* ID_MODEL_FROM_DATABASE=Wireless Presenter with Laser Pointer usb:v047Dp2021* ID_MODEL_FROM_DATABASE=PilotBoard Wireless usb:v047Dp2030* ID_MODEL_FROM_DATABASE=PilotBoard Wireless usb:v047Dp2034* ID_MODEL_FROM_DATABASE=SlimBlade Media Notebook Set usb:v047Dp2041* ID_MODEL_FROM_DATABASE=SlimBlade Trackball usb:v047Dp2048* ID_MODEL_FROM_DATABASE=Orbit Trackball with Scroll Ring usb:v047Dp4003* ID_MODEL_FROM_DATABASE=Gravis Xterminator Digital Gamepad usb:v047Dp4005* ID_MODEL_FROM_DATABASE=Gravis Eliminator GamePad Pro usb:v047Dp4006* ID_MODEL_FROM_DATABASE=Gravis Eliminator AfterShock usb:v047Dp4007* ID_MODEL_FROM_DATABASE=Gravis Xterminator Force usb:v047Dp4008* ID_MODEL_FROM_DATABASE=Gravis Destroyer TiltPad usb:v047Dp5001* ID_MODEL_FROM_DATABASE=Cabo I Camera usb:v047Dp5002* ID_MODEL_FROM_DATABASE=VideoCam CABO II usb:v047Dp5003* ID_MODEL_FROM_DATABASE=VideoCam usb:v047E* ID_VENDOR_FROM_DATABASE=Agere Systems, Inc. (Lucent) usb:v047Ep0300* ID_MODEL_FROM_DATABASE=ORiNOCO Card usb:v047Ep1001* ID_MODEL_FROM_DATABASE=USS720 Parallel Port usb:v047Ep2892* ID_MODEL_FROM_DATABASE=Systems Soft Modem usb:v047EpBAD1* ID_MODEL_FROM_DATABASE=Lucent 56k Modem usb:v047EpF101* ID_MODEL_FROM_DATABASE=Atlas Modem usb:v047F* ID_VENDOR_FROM_DATABASE=Plantronics, Inc. usb:v047Fp0101* ID_MODEL_FROM_DATABASE=Bulk Driver usb:v047Fp0301* ID_MODEL_FROM_DATABASE=Bulk Driver usb:v047Fp0411* ID_MODEL_FROM_DATABASE=Savi Office Base Station usb:v047Fp0CA1* ID_MODEL_FROM_DATABASE=USB DSP v4 Audio Interface usb:v047Fp4254* ID_MODEL_FROM_DATABASE=BUA-100 Bluetooth Adapter usb:v047FpAC01* ID_MODEL_FROM_DATABASE=Savi 7xx usb:v047FpAD01* ID_MODEL_FROM_DATABASE=GameCom 777 5.1 Headset usb:v047FpC008* ID_MODEL_FROM_DATABASE=Audio 655 DSP usb:v047FpC00E* ID_MODEL_FROM_DATABASE=Blackwire C310 headset usb:v0480* ID_VENDOR_FROM_DATABASE=Toshiba America Inc usb:v0480p0001* ID_MODEL_FROM_DATABASE=InTouch Module usb:v0480p0004* ID_MODEL_FROM_DATABASE=InTouch Module usb:v0480p0011* ID_MODEL_FROM_DATABASE=InTouch Module usb:v0480p0014* ID_MODEL_FROM_DATABASE=InTouch Module usb:v0480p0100* ID_MODEL_FROM_DATABASE=Stor.E Slim USB 3.0 usb:v0480p0200* ID_MODEL_FROM_DATABASE=External Disk usb:v0480pA006* ID_MODEL_FROM_DATABASE=External Disk 1.5TB usb:v0480pA007* ID_MODEL_FROM_DATABASE=External Disk USB 3.0 usb:v0480pA009* ID_MODEL_FROM_DATABASE=Stor.E Basics usb:v0480pA00D* ID_MODEL_FROM_DATABASE=STOR.E BASICS 500GB usb:v0480pA202* ID_MODEL_FROM_DATABASE=Canvio Basics HDD usb:v0480pB001* ID_MODEL_FROM_DATABASE=Stor.E Partner usb:v0480pD000* ID_MODEL_FROM_DATABASE=External Disk 2TB Model DT01ABA200 usb:v0480pD010* ID_MODEL_FROM_DATABASE=External Disk 3TB usb:v0480pD011* ID_MODEL_FROM_DATABASE=Canvio Desk usb:v0481* ID_VENDOR_FROM_DATABASE=Zenith Data Systems usb:v0482* ID_VENDOR_FROM_DATABASE=Kyocera Corp. usb:v0482p000E* ID_MODEL_FROM_DATABASE=FS-1020D Printer usb:v0482p000F* ID_MODEL_FROM_DATABASE=FS-1920 Mono Printer usb:v0482p0100* ID_MODEL_FROM_DATABASE=Finecam S3x usb:v0482p0101* ID_MODEL_FROM_DATABASE=Finecam S4 usb:v0482p0103* ID_MODEL_FROM_DATABASE=Finecam S5 usb:v0482p0105* ID_MODEL_FROM_DATABASE=Finecam L3 usb:v0482p0106* ID_MODEL_FROM_DATABASE=Finecam usb:v0482p0107* ID_MODEL_FROM_DATABASE=Digital Camera Device usb:v0482p0108* ID_MODEL_FROM_DATABASE=Digital Camera Device usb:v0482p0203* ID_MODEL_FROM_DATABASE=AH-K3001V usb:v0482p0204* ID_MODEL_FROM_DATABASE=iBurst Terminal usb:v0483* ID_VENDOR_FROM_DATABASE=STMicroelectronics usb:v0483p0137* ID_MODEL_FROM_DATABASE=BeWAN ADSL USB ST (blue or green) usb:v0483p0138* ID_MODEL_FROM_DATABASE=Unicorn II (ST70138B + MTC-20174TQ chipset) usb:v0483p1307* ID_MODEL_FROM_DATABASE=Cytronix 6in1 Card Reader usb:v0483p163D* ID_MODEL_FROM_DATABASE=Cool Icam Digi-MP3 usb:v0483p2015* ID_MODEL_FROM_DATABASE=TouchChip® Fingerprint Reader usb:v0483p2016* ID_MODEL_FROM_DATABASE=Fingerprint Reader usb:v0483p2017* ID_MODEL_FROM_DATABASE=Biometric Smart Card Reader usb:v0483p2018* ID_MODEL_FROM_DATABASE=BioSimKey usb:v0483p2302* ID_MODEL_FROM_DATABASE=Portable Flash Device (PFD) usb:v0483p347B* ID_MODEL_FROM_DATABASE=ST-LINK/V2-1 usb:v0483p3744* ID_MODEL_FROM_DATABASE=STLINK Pseudo disk usb:v0483p3747* ID_MODEL_FROM_DATABASE=ST Micro Connect Lite usb:v0483p3748* ID_MODEL_FROM_DATABASE=ST-LINK/V2 usb:v0483p374B* ID_MODEL_FROM_DATABASE=ST-LINK/V2.1 (Nucleo-F103RB) usb:v0483p4810* ID_MODEL_FROM_DATABASE=ISDN adapter usb:v0483p481D* ID_MODEL_FROM_DATABASE=BT Digital Access adapter usb:v0483p5000* ID_MODEL_FROM_DATABASE=ST Micro/Ergenic ERG BT-002 Bluetooth Adapter usb:v0483p5001* ID_MODEL_FROM_DATABASE=ST Micro Bluetooth Device usb:v0483p5710* ID_MODEL_FROM_DATABASE=Joystick in FS Mode usb:v0483p5720* ID_MODEL_FROM_DATABASE=STM microSD Flash Device usb:v0483p5721* ID_MODEL_FROM_DATABASE=Hantek DDS-3X25 Arbitrary Waveform Generator usb:v0483p5730* ID_MODEL_FROM_DATABASE=STM32 Audio Streaming usb:v0483p5740* ID_MODEL_FROM_DATABASE=STM32F407 usb:v0483p7270* ID_MODEL_FROM_DATABASE=ST Micro Serial Bridge usb:v0483p7554* ID_MODEL_FROM_DATABASE=56k SoftModem usb:v0483p91D1* ID_MODEL_FROM_DATABASE=Sensor Hub usb:v0483pDF11* ID_MODEL_FROM_DATABASE=STM Device in DFU Mode usb:v0483pFF10* ID_MODEL_FROM_DATABASE=Swann ST56 Modem usb:v0484* ID_VENDOR_FROM_DATABASE=Specialix usb:v0485* ID_VENDOR_FROM_DATABASE=Nokia Monitors usb:v0486* ID_VENDOR_FROM_DATABASE=ASUS Computers, Inc. usb:v0486p0185* ID_MODEL_FROM_DATABASE=EeePC T91MT HID Touch Panel usb:v0487* ID_VENDOR_FROM_DATABASE=Stewart Connector usb:v0488* ID_VENDOR_FROM_DATABASE=Cirque Corp. usb:v0489* ID_VENDOR_FROM_DATABASE=Foxconn / Hon Hai usb:v0489p0502* ID_MODEL_FROM_DATABASE=SmartMedia Card Reader Firmware Loader usb:v0489p0503* ID_MODEL_FROM_DATABASE=SmartMedia Card Reader usb:v0489pD00C* ID_MODEL_FROM_DATABASE=Rollei Compactline (Storage Mode) usb:v0489pD00E* ID_MODEL_FROM_DATABASE=Rollei Compactline (Video Mode) usb:v0489pE000* ID_MODEL_FROM_DATABASE=T-Com TC 300 usb:v0489pE003* ID_MODEL_FROM_DATABASE=Pirelli DP-L10 usb:v0489pE00D* ID_MODEL_FROM_DATABASE=Broadcom Bluetooth 2.1 Device usb:v0489pE00F* ID_MODEL_FROM_DATABASE=Foxconn T77H114 BCM2070 [Single-Chip Bluetooth 2.1 + EDR Adapter] usb:v0489pE011* ID_MODEL_FROM_DATABASE=Acer Bluetooth module usb:v0489pE016* ID_MODEL_FROM_DATABASE=Ubee PXU1900 WiMAX Adapter [Beceem BCSM250] usb:v0489pE02C* ID_MODEL_FROM_DATABASE=Atheros AR5BBU12 Bluetooth Device usb:v0489pE032* ID_MODEL_FROM_DATABASE=Broadcom BCM20702 Bluetooth usb:v0489pE042* ID_MODEL_FROM_DATABASE=Broadcom BCM20702 Bluetooth usb:v0489pE04D* ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth usb:v048A* ID_VENDOR_FROM_DATABASE=S-MOS Systems, Inc. usb:v048C* ID_VENDOR_FROM_DATABASE=Alps Electric Ireland, Ltd usb:v048D* ID_VENDOR_FROM_DATABASE=Integrated Technology Express, Inc. usb:v048Dp1165* ID_MODEL_FROM_DATABASE=IT1165 Flash Controller usb:v048Dp1336* ID_MODEL_FROM_DATABASE=SD/MMC Cardreader usb:v048Dp1345* ID_MODEL_FROM_DATABASE=Multi Cardreader usb:v048Dp9006* ID_MODEL_FROM_DATABASE=IT9135 BDA Afatech DVB-T HDTV Dongle usb:v048Dp9009* ID_MODEL_FROM_DATABASE=Zolid HD DVD Maker usb:v048Dp9135* ID_MODEL_FROM_DATABASE=Zolid Mini DVB-T Stick usb:v048Dp9306* ID_MODEL_FROM_DATABASE=IT930x DVB stick usb:v048Dp9503* ID_MODEL_FROM_DATABASE=ITE it9503 feature-limited DVB-T transmission chip [ccHDtv] usb:v048Dp9507* ID_MODEL_FROM_DATABASE=ITE it9507 full featured DVB-T transmission chip [ccHDtv] usb:v048F* ID_VENDOR_FROM_DATABASE=Eicon Tech. usb:v0490* ID_VENDOR_FROM_DATABASE=United Microelectronics Corp. usb:v0491* ID_VENDOR_FROM_DATABASE=Capetronic usb:v0491p0003* ID_MODEL_FROM_DATABASE=Taxan Monitor Control usb:v0492* ID_VENDOR_FROM_DATABASE=Samsung SemiConductor, Inc. usb:v0492p0140* ID_MODEL_FROM_DATABASE=MP3 player usb:v0492p0141* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0493* ID_VENDOR_FROM_DATABASE=MAG Technology Co., Ltd usb:v0495* ID_VENDOR_FROM_DATABASE=ESS Technology, Inc. usb:v0496* ID_VENDOR_FROM_DATABASE=Micron Electronics usb:v0497* ID_VENDOR_FROM_DATABASE=Smile International usb:v0497pC001* ID_MODEL_FROM_DATABASE=Camera Device usb:v0498* ID_VENDOR_FROM_DATABASE=Capetronic (Kaohsiung) Corp. usb:v0499* ID_VENDOR_FROM_DATABASE=Yamaha Corp. usb:v0499p1000* ID_MODEL_FROM_DATABASE=UX256 MIDI I/F usb:v0499p1001* ID_MODEL_FROM_DATABASE=MU1000 usb:v0499p1002* ID_MODEL_FROM_DATABASE=MU2000 usb:v0499p1003* ID_MODEL_FROM_DATABASE=MU500 usb:v0499p1004* ID_MODEL_FROM_DATABASE=UW500 usb:v0499p1005* ID_MODEL_FROM_DATABASE=MOTIF6 usb:v0499p1006* ID_MODEL_FROM_DATABASE=MOTIF7 usb:v0499p1007* ID_MODEL_FROM_DATABASE=MOTIF8 usb:v0499p1008* ID_MODEL_FROM_DATABASE=UX96 MIDI I/F usb:v0499p1009* ID_MODEL_FROM_DATABASE=UX16 MIDI I/F usb:v0499p100A* ID_MODEL_FROM_DATABASE=EOS BX usb:v0499p100C* ID_MODEL_FROM_DATABASE=UC-MX usb:v0499p100D* ID_MODEL_FROM_DATABASE=UC-KX usb:v0499p100E* ID_MODEL_FROM_DATABASE=S08 usb:v0499p100F* ID_MODEL_FROM_DATABASE=CLP-150 usb:v0499p1010* ID_MODEL_FROM_DATABASE=CLP-170 usb:v0499p1011* ID_MODEL_FROM_DATABASE=P-250 usb:v0499p1012* ID_MODEL_FROM_DATABASE=TYROS usb:v0499p1013* ID_MODEL_FROM_DATABASE=PF-500 usb:v0499p1014* ID_MODEL_FROM_DATABASE=S90 usb:v0499p1015* ID_MODEL_FROM_DATABASE=MOTIF-R usb:v0499p1016* ID_MODEL_FROM_DATABASE=MDP-5 usb:v0499p1017* ID_MODEL_FROM_DATABASE=CVP-204 usb:v0499p1018* ID_MODEL_FROM_DATABASE=CVP-206 usb:v0499p1019* ID_MODEL_FROM_DATABASE=CVP-208 usb:v0499p101A* ID_MODEL_FROM_DATABASE=CVP-210 usb:v0499p101B* ID_MODEL_FROM_DATABASE=PSR-1100 usb:v0499p101C* ID_MODEL_FROM_DATABASE=PSR-2100 usb:v0499p101D* ID_MODEL_FROM_DATABASE=CLP-175 usb:v0499p101E* ID_MODEL_FROM_DATABASE=PSR-K1 usb:v0499p101F* ID_MODEL_FROM_DATABASE=EZ-J24 usb:v0499p1020* ID_MODEL_FROM_DATABASE=EZ-250i usb:v0499p1021* ID_MODEL_FROM_DATABASE=MOTIF ES 6 usb:v0499p1022* ID_MODEL_FROM_DATABASE=MOTIF ES 7 usb:v0499p1023* ID_MODEL_FROM_DATABASE=MOTIF ES 8 usb:v0499p1024* ID_MODEL_FROM_DATABASE=CVP-301 usb:v0499p1025* ID_MODEL_FROM_DATABASE=CVP-303 usb:v0499p1026* ID_MODEL_FROM_DATABASE=CVP-305 usb:v0499p1027* ID_MODEL_FROM_DATABASE=CVP-307 usb:v0499p1028* ID_MODEL_FROM_DATABASE=CVP-309 usb:v0499p1029* ID_MODEL_FROM_DATABASE=CVP-309GP usb:v0499p102A* ID_MODEL_FROM_DATABASE=PSR-1500 usb:v0499p102B* ID_MODEL_FROM_DATABASE=PSR-3000 usb:v0499p102E* ID_MODEL_FROM_DATABASE=ELS-01/01C usb:v0499p1030* ID_MODEL_FROM_DATABASE=PSR-295/293 usb:v0499p1031* ID_MODEL_FROM_DATABASE=DGX-205/203 usb:v0499p1032* ID_MODEL_FROM_DATABASE=DGX-305 usb:v0499p1033* ID_MODEL_FROM_DATABASE=DGX-505 usb:v0499p1037* ID_MODEL_FROM_DATABASE=PSR-E403 usb:v0499p103C* ID_MODEL_FROM_DATABASE=MOTIF-RACK ES usb:v0499p1054* ID_MODEL_FROM_DATABASE=S90XS Keyboard/Music Synthesizer usb:v0499p160F* ID_MODEL_FROM_DATABASE=P-105 usb:v0499p2000* ID_MODEL_FROM_DATABASE=DGP-7 usb:v0499p2001* ID_MODEL_FROM_DATABASE=DGP-5 usb:v0499p3001* ID_MODEL_FROM_DATABASE=YST-MS55D USB Speaker usb:v0499p3003* ID_MODEL_FROM_DATABASE=YST-M45D USB Speaker usb:v0499p4000* ID_MODEL_FROM_DATABASE=NetVolante RTA54i Broadband&ISDN Router usb:v0499p4001* ID_MODEL_FROM_DATABASE=NetVolante RTW65b Broadband Wireless Router usb:v0499p4002* ID_MODEL_FROM_DATABASE=NetVolante RTW65i Broadband&ISDN Wireless Router usb:v0499p4004* ID_MODEL_FROM_DATABASE=NetVolante RTA55i Broadband VoIP Router usb:v0499p5000* ID_MODEL_FROM_DATABASE=CS1D usb:v0499p5001* ID_MODEL_FROM_DATABASE=DSP1D usb:v0499p5002* ID_MODEL_FROM_DATABASE=DME32 usb:v0499p5003* ID_MODEL_FROM_DATABASE=DM2000 usb:v0499p5004* ID_MODEL_FROM_DATABASE=02R96 usb:v0499p5005* ID_MODEL_FROM_DATABASE=ACU16-C usb:v0499p5006* ID_MODEL_FROM_DATABASE=NHB32-C usb:v0499p5007* ID_MODEL_FROM_DATABASE=DM1000 usb:v0499p5008* ID_MODEL_FROM_DATABASE=01V96 usb:v0499p5009* ID_MODEL_FROM_DATABASE=SPX2000 usb:v0499p500A* ID_MODEL_FROM_DATABASE=PM5D usb:v0499p500B* ID_MODEL_FROM_DATABASE=DME64N usb:v0499p500C* ID_MODEL_FROM_DATABASE=DME24N usb:v0499p6001* ID_MODEL_FROM_DATABASE=CRW2200UX Lightspeed 2 External CD-RW Drive usb:v0499p7000* ID_MODEL_FROM_DATABASE=DTX usb:v0499p7010* ID_MODEL_FROM_DATABASE=UB99 usb:v049A* ID_VENDOR_FROM_DATABASE=Gandalf Technologies, Ltd usb:v049B* ID_VENDOR_FROM_DATABASE=Curtis Computer Products usb:v049C* ID_VENDOR_FROM_DATABASE=Acer Advanced Labs, Inc. usb:v049Cp0002* ID_MODEL_FROM_DATABASE=Keyboard (???) usb:v049D* ID_VENDOR_FROM_DATABASE=VLSI Technology usb:v049F* ID_VENDOR_FROM_DATABASE=Compaq Computer Corp. usb:v049Fp0002* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v049Fp0003* ID_MODEL_FROM_DATABASE=iPAQ PocketPC usb:v049Fp000E* ID_MODEL_FROM_DATABASE=Internet Keyboard usb:v049Fp0012* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v049Fp0018* ID_MODEL_FROM_DATABASE=PA-1/PA-2 MP3 Player usb:v049Fp0019* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v049Fp001A* ID_MODEL_FROM_DATABASE=S4 100 Scanner usb:v049Fp001E* ID_MODEL_FROM_DATABASE=IJ650 Inkjet Printer usb:v049Fp001F* ID_MODEL_FROM_DATABASE=WL215 Adapter usb:v049Fp0021* ID_MODEL_FROM_DATABASE=S200 Scanner usb:v049Fp0027* ID_MODEL_FROM_DATABASE=Bluetooth Multiport Module by Compaq usb:v049Fp002A* ID_MODEL_FROM_DATABASE=1400P Inkjet Printer usb:v049Fp002B* ID_MODEL_FROM_DATABASE=A3000 usb:v049Fp002C* ID_MODEL_FROM_DATABASE=Lexmark X125 usb:v049Fp0032* ID_MODEL_FROM_DATABASE=802.11b Adapter [ipaq h5400] usb:v049Fp0033* ID_MODEL_FROM_DATABASE=Wireless LAN MultiPort W100 [Intersil PRISM 2.5] usb:v049Fp0036* ID_MODEL_FROM_DATABASE=Bluetooth Multiport Module usb:v049Fp0051* ID_MODEL_FROM_DATABASE=KU-0133 Easy Access Interner Keyboard usb:v049Fp0076* ID_MODEL_FROM_DATABASE=Wireless LAN MultiPort W200 usb:v049Fp0080* ID_MODEL_FROM_DATABASE=GPRS Multiport usb:v049Fp0086* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v049Fp504A* ID_MODEL_FROM_DATABASE=Personal Jukebox PJB100 usb:v049Fp505A* ID_MODEL_FROM_DATABASE=Linux-USB "CDC Subset" Device, or Itsy (experimental) usb:v049Fp8511* ID_MODEL_FROM_DATABASE=iPAQ Networking 10/100 Ethernet [pegasus2] usb:v04A0* ID_VENDOR_FROM_DATABASE=Digital Equipment Corp. usb:v04A1* ID_VENDOR_FROM_DATABASE=SystemSoft Corp. usb:v04A1pFFF0* ID_MODEL_FROM_DATABASE=Telex Composite Device usb:v04A2* ID_VENDOR_FROM_DATABASE=FirePower Systems usb:v04A3* ID_VENDOR_FROM_DATABASE=Trident Microsystems, Inc. usb:v04A4* ID_VENDOR_FROM_DATABASE=Hitachi, Ltd usb:v04A4p0004* ID_MODEL_FROM_DATABASE=DVD-CAM DZ-MV100A Camcorder usb:v04A4p001E* ID_MODEL_FROM_DATABASE=DVDCAM USB HS Interface usb:v04A5* ID_VENDOR_FROM_DATABASE=Acer Peripherals Inc. (now BenQ Corp.) usb:v04A5p0001* ID_MODEL_FROM_DATABASE=Keyboard usb:v04A5p0002* ID_MODEL_FROM_DATABASE=API Ergo K/B usb:v04A5p0003* ID_MODEL_FROM_DATABASE=API Generic K/B Mouse usb:v04A5p12A6* ID_MODEL_FROM_DATABASE=AcerScan C310U usb:v04A5p1A20* ID_MODEL_FROM_DATABASE=Prisa 310U usb:v04A5p1A2A* ID_MODEL_FROM_DATABASE=Prisa 620U usb:v04A5p2022* ID_MODEL_FROM_DATABASE=Prisa 320U/340U usb:v04A5p2040* ID_MODEL_FROM_DATABASE=Prisa 620UT usb:v04A5p205E* ID_MODEL_FROM_DATABASE=ScanPrisa 640BU usb:v04A5p2060* ID_MODEL_FROM_DATABASE=Prisa 620U+/640U usb:v04A5p207E* ID_MODEL_FROM_DATABASE=Prisa 640BU usb:v04A5p209E* ID_MODEL_FROM_DATABASE=ScanPrisa 640BT usb:v04A5p20AE* ID_MODEL_FROM_DATABASE=S2W 3000U usb:v04A5p20B0* ID_MODEL_FROM_DATABASE=S2W 3300U/4300U usb:v04A5p20BE* ID_MODEL_FROM_DATABASE=Prisa 640BT usb:v04A5p20C0* ID_MODEL_FROM_DATABASE=Prisa 1240UT usb:v04A5p20DE* ID_MODEL_FROM_DATABASE=S2W 4300U+ usb:v04A5p20F8* ID_MODEL_FROM_DATABASE=Benq 5000 usb:v04A5p20FC* ID_MODEL_FROM_DATABASE=Benq 5000 usb:v04A5p20FE* ID_MODEL_FROM_DATABASE=SW2 5300U usb:v04A5p2137* ID_MODEL_FROM_DATABASE=Benq 5150/5250 usb:v04A5p2202* ID_MODEL_FROM_DATABASE=Benq 7400UT usb:v04A5p2311* ID_MODEL_FROM_DATABASE=Benq 5560 usb:v04A5p3003* ID_MODEL_FROM_DATABASE=Benq Webcam usb:v04A5p3008* ID_MODEL_FROM_DATABASE=Benq 1500 usb:v04A5p300A* ID_MODEL_FROM_DATABASE=Benq 3410 usb:v04A5p300C* ID_MODEL_FROM_DATABASE=Benq 1016 usb:v04A5p3019* ID_MODEL_FROM_DATABASE=Benq DC C40 usb:v04A5p4000* ID_MODEL_FROM_DATABASE=P30 Composite Device usb:v04A5p4013* ID_MODEL_FROM_DATABASE=BenQ-Siemens EF82/SL91 usb:v04A5p4044* ID_MODEL_FROM_DATABASE=BenQ-Siemens SF71 usb:v04A5p4045* ID_MODEL_FROM_DATABASE=BenQ-Siemens E81 usb:v04A5p4048* ID_MODEL_FROM_DATABASE=BenQ M7 usb:v04A5p6001* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6002* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6003* ID_MODEL_FROM_DATABASE=ATA/ATAPI Adapter usb:v04A5p6004* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6005* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6006* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6007* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6008* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6009* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p600A* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p600B* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p600C* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p600D* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p600E* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p600F* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6010* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6011* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6012* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6013* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6014* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6015* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v04A5p6125* ID_MODEL_FROM_DATABASE=MP3 Player usb:v04A5p6180* ID_MODEL_FROM_DATABASE=MP3 Player usb:v04A5p6200* ID_MODEL_FROM_DATABASE=MP3 Player usb:v04A5p7500* ID_MODEL_FROM_DATABASE=Hi-Speed Mass Storage Device usb:v04A5p9000* ID_MODEL_FROM_DATABASE=AWL300 Wireless Adapter usb:v04A5p9001* ID_MODEL_FROM_DATABASE=AWL400 Wireless Adapter usb:v04A5p9213* ID_MODEL_FROM_DATABASE=Kbd Hub usb:v04A6* ID_VENDOR_FROM_DATABASE=Nokia Display Products usb:v04A6p00B9* ID_MODEL_FROM_DATABASE=Audio usb:v04A6p0180* ID_MODEL_FROM_DATABASE=Hub Type P usb:v04A6p0181* ID_MODEL_FROM_DATABASE=HID Monitor Controls usb:v04A7* ID_VENDOR_FROM_DATABASE=Visioneer usb:v04A7p0100* ID_MODEL_FROM_DATABASE=StrobePro usb:v04A7p0101* ID_MODEL_FROM_DATABASE=Strobe Pro Scanner (1.01) usb:v04A7p0102* ID_MODEL_FROM_DATABASE=StrobePro Scanner usb:v04A7p0211* ID_MODEL_FROM_DATABASE=OneTouch 7600 Scanner usb:v04A7p0221* ID_MODEL_FROM_DATABASE=OneTouch 5300 Scanner usb:v04A7p0223* ID_MODEL_FROM_DATABASE=OneTouch 8200 usb:v04A7p0224* ID_MODEL_FROM_DATABASE=OneTouch 4800 USB/Microtek Scanport 3000 usb:v04A7p0225* ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) usb:v04A7p0226* ID_MODEL_FROM_DATABASE=OneTouch 5300 USB usb:v04A7p0229* ID_MODEL_FROM_DATABASE=OneTouch 7100 usb:v04A7p022A* ID_MODEL_FROM_DATABASE=OneTouch 6600 usb:v04A7p022C* ID_MODEL_FROM_DATABASE=OneTouch 9000/9020 usb:v04A7p0231* ID_MODEL_FROM_DATABASE=6100 Scanner usb:v04A7p0311* ID_MODEL_FROM_DATABASE=6200 EPP/USB Scanner usb:v04A7p0321* ID_MODEL_FROM_DATABASE=OneTouch 8100 EPP/USB Scanner usb:v04A7p0331* ID_MODEL_FROM_DATABASE=OneTouch 8600 EPP/USB Scanner usb:v04A7p0341* ID_MODEL_FROM_DATABASE=6400 usb:v04A7p0361* ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) usb:v04A7p0362* ID_MODEL_FROM_DATABASE=OneTouch 9320 usb:v04A7p0371* ID_MODEL_FROM_DATABASE=OneTouch 8700/8920 usb:v04A7p0380* ID_MODEL_FROM_DATABASE=OneTouch 7700 usb:v04A7p0382* ID_MODEL_FROM_DATABASE=Photo Port 7700 usb:v04A7p0390* ID_MODEL_FROM_DATABASE=9650 usb:v04A7p03A0* ID_MODEL_FROM_DATABASE=Xerox 4800 One Touch usb:v04A7p0410* ID_MODEL_FROM_DATABASE=OneTouch Pro 8800/8820 usb:v04A7p0421* ID_MODEL_FROM_DATABASE=9450 USB usb:v04A7p0423* ID_MODEL_FROM_DATABASE=9750 Scanner usb:v04A7p0424* ID_MODEL_FROM_DATABASE=Strobe XP 450 usb:v04A7p0425* ID_MODEL_FROM_DATABASE=Strobe XP 100 usb:v04A7p0426* ID_MODEL_FROM_DATABASE=Strobe XP 200 usb:v04A7p0427* ID_MODEL_FROM_DATABASE=Strobe XP 100 usb:v04A7p0444* ID_MODEL_FROM_DATABASE=OneTouch 7300 usb:v04A7p0445* ID_MODEL_FROM_DATABASE=CardReader 100 usb:v04A7p0446* ID_MODEL_FROM_DATABASE=Xerox DocuMate 510 usb:v04A7p0447* ID_MODEL_FROM_DATABASE=XEROX DocuMate 520 usb:v04A7p0448* ID_MODEL_FROM_DATABASE=XEROX DocuMate 250 usb:v04A7p0449* ID_MODEL_FROM_DATABASE=Xerox DocuMate 252 usb:v04A7p044A* ID_MODEL_FROM_DATABASE=Xerox 6400 usb:v04A7p044C* ID_MODEL_FROM_DATABASE=Xerox DocuMate 262 usb:v04A7p0474* ID_MODEL_FROM_DATABASE=Strobe XP 300 usb:v04A7p0475* ID_MODEL_FROM_DATABASE=Xerox DocuMate 272 usb:v04A7p0478* ID_MODEL_FROM_DATABASE=Strobe XP 220 usb:v04A7p0479* ID_MODEL_FROM_DATABASE=Strobe XP 470 usb:v04A7p047A* ID_MODEL_FROM_DATABASE=9450 usb:v04A7p047B* ID_MODEL_FROM_DATABASE=9650 usb:v04A7p047D* ID_MODEL_FROM_DATABASE=9420 usb:v04A7p0480* ID_MODEL_FROM_DATABASE=9520 usb:v04A7p048F* ID_MODEL_FROM_DATABASE=Strobe XP 470 usb:v04A7p0491* ID_MODEL_FROM_DATABASE=Strobe XP 450 usb:v04A7p0493* ID_MODEL_FROM_DATABASE=9750 usb:v04A7p0494* ID_MODEL_FROM_DATABASE=Strobe XP 120 usb:v04A7p0497* ID_MODEL_FROM_DATABASE=Patriot 430 usb:v04A7p0498* ID_MODEL_FROM_DATABASE=Patriot 680 usb:v04A7p0499* ID_MODEL_FROM_DATABASE=Patriot 780 usb:v04A7p049B* ID_MODEL_FROM_DATABASE=Strobe XP 100 usb:v04A7p04A0* ID_MODEL_FROM_DATABASE=7400 usb:v04A7p04AC* ID_MODEL_FROM_DATABASE=Xerox Travel Scanner 100 usb:v04A8* ID_VENDOR_FROM_DATABASE=Multivideo Labs, Inc. usb:v04A8p0101* ID_MODEL_FROM_DATABASE=Hub usb:v04A8p0303* ID_MODEL_FROM_DATABASE=Peripheral Switch usb:v04A8p0404* ID_MODEL_FROM_DATABASE=Peripheral Switch usb:v04A9* ID_VENDOR_FROM_DATABASE=Canon, Inc. usb:v04A9p1005* ID_MODEL_FROM_DATABASE=BJ Printer Hub usb:v04A9p1035* ID_MODEL_FROM_DATABASE=PD Printer Storage usb:v04A9p1050* ID_MODEL_FROM_DATABASE=BJC-8200 usb:v04A9p1051* ID_MODEL_FROM_DATABASE=BJC-3000 Color Printer usb:v04A9p1052* ID_MODEL_FROM_DATABASE=BJC-6100 usb:v04A9p1053* ID_MODEL_FROM_DATABASE=BJC-6200 usb:v04A9p1054* ID_MODEL_FROM_DATABASE=BJC-6500 usb:v04A9p1055* ID_MODEL_FROM_DATABASE=BJC-85 usb:v04A9p1056* ID_MODEL_FROM_DATABASE=BJC-2110 Color Printer usb:v04A9p1057* ID_MODEL_FROM_DATABASE=LR1 usb:v04A9p105A* ID_MODEL_FROM_DATABASE=BJC-55 usb:v04A9p105B* ID_MODEL_FROM_DATABASE=S600 Printer usb:v04A9p105C* ID_MODEL_FROM_DATABASE=S400 usb:v04A9p105D* ID_MODEL_FROM_DATABASE=S450 Printer usb:v04A9p105E* ID_MODEL_FROM_DATABASE=S800 usb:v04A9p1062* ID_MODEL_FROM_DATABASE=S500 Printer usb:v04A9p1063* ID_MODEL_FROM_DATABASE=S4500 usb:v04A9p1064* ID_MODEL_FROM_DATABASE=S300 Printer usb:v04A9p1065* ID_MODEL_FROM_DATABASE=S100 usb:v04A9p1066* ID_MODEL_FROM_DATABASE=S630 usb:v04A9p1067* ID_MODEL_FROM_DATABASE=S900 usb:v04A9p1068* ID_MODEL_FROM_DATABASE=S9000 usb:v04A9p1069* ID_MODEL_FROM_DATABASE=S820 usb:v04A9p106A* ID_MODEL_FROM_DATABASE=S200 Printer usb:v04A9p106B* ID_MODEL_FROM_DATABASE=S520 Printer usb:v04A9p106D* ID_MODEL_FROM_DATABASE=S750 Printer usb:v04A9p106E* ID_MODEL_FROM_DATABASE=S820D usb:v04A9p1070* ID_MODEL_FROM_DATABASE=S530D usb:v04A9p1072* ID_MODEL_FROM_DATABASE=I850 Printer usb:v04A9p1073* ID_MODEL_FROM_DATABASE=I550 Printer usb:v04A9p1074* ID_MODEL_FROM_DATABASE=S330 Printer usb:v04A9p1076* ID_MODEL_FROM_DATABASE=i70 usb:v04A9p1077* ID_MODEL_FROM_DATABASE=i950 usb:v04A9p107A* ID_MODEL_FROM_DATABASE=S830D usb:v04A9p107B* ID_MODEL_FROM_DATABASE=i320 usb:v04A9p107C* ID_MODEL_FROM_DATABASE=i470D usb:v04A9p107D* ID_MODEL_FROM_DATABASE=i9100 usb:v04A9p107E* ID_MODEL_FROM_DATABASE=i450 usb:v04A9p107F* ID_MODEL_FROM_DATABASE=i860 usb:v04A9p1082* ID_MODEL_FROM_DATABASE=i350 usb:v04A9p1084* ID_MODEL_FROM_DATABASE=i250 usb:v04A9p1085* ID_MODEL_FROM_DATABASE=i255 usb:v04A9p1086* ID_MODEL_FROM_DATABASE=i560 usb:v04A9p1088* ID_MODEL_FROM_DATABASE=i965 usb:v04A9p108A* ID_MODEL_FROM_DATABASE=i455 usb:v04A9p108B* ID_MODEL_FROM_DATABASE=i900D usb:v04A9p108C* ID_MODEL_FROM_DATABASE=i475D usb:v04A9p108D* ID_MODEL_FROM_DATABASE=PIXMA iP2000 usb:v04A9p108F* ID_MODEL_FROM_DATABASE=i80 usb:v04A9p1090* ID_MODEL_FROM_DATABASE=i9900 Photo Printer usb:v04A9p1091* ID_MODEL_FROM_DATABASE=PIXMA iP1500 usb:v04A9p1093* ID_MODEL_FROM_DATABASE=PIXMA iP4000 usb:v04A9p1094* ID_MODEL_FROM_DATABASE=PIXMA iP3000x Printer usb:v04A9p1095* ID_MODEL_FROM_DATABASE=PIXMA iP6000D usb:v04A9p1097* ID_MODEL_FROM_DATABASE=PIXMA iP5000 usb:v04A9p1098* ID_MODEL_FROM_DATABASE=PIXMA iP1000 usb:v04A9p1099* ID_MODEL_FROM_DATABASE=PIXMA iP8500 usb:v04A9p109C* ID_MODEL_FROM_DATABASE=PIXMA iP4000R usb:v04A9p109D* ID_MODEL_FROM_DATABASE=iP90 usb:v04A9p10A0* ID_MODEL_FROM_DATABASE=PIXMA iP1600 Printer usb:v04A9p10A2* ID_MODEL_FROM_DATABASE=iP4200 usb:v04A9p10A4* ID_MODEL_FROM_DATABASE=iP5200R usb:v04A9p10A5* ID_MODEL_FROM_DATABASE=iP5200 usb:v04A9p10A7* ID_MODEL_FROM_DATABASE=iP6210D usb:v04A9p10A8* ID_MODEL_FROM_DATABASE=iP6220D usb:v04A9p10A9* ID_MODEL_FROM_DATABASE=iP6600D usb:v04A9p10B6* ID_MODEL_FROM_DATABASE=PIXMA iP4300 Printer usb:v04A9p10C2* ID_MODEL_FROM_DATABASE=PIXMA iP1800 Printer usb:v04A9p10C4* ID_MODEL_FROM_DATABASE=Pixma iP4500 Printer usb:v04A9p1404* ID_MODEL_FROM_DATABASE=W6400PG usb:v04A9p1405* ID_MODEL_FROM_DATABASE=W8400PG usb:v04A9p150F* ID_MODEL_FROM_DATABASE=BIJ2350 PCL usb:v04A9p1510* ID_MODEL_FROM_DATABASE=BIJ1350 PCL usb:v04A9p1512* ID_MODEL_FROM_DATABASE=BIJ1350D PCL usb:v04A9p1601* ID_MODEL_FROM_DATABASE=DR-2080C Scanner usb:v04A9p1607* ID_MODEL_FROM_DATABASE=DR-6080 Scanner usb:v04A9p1700* ID_MODEL_FROM_DATABASE=PIXMA MP110 Scanner usb:v04A9p1701* ID_MODEL_FROM_DATABASE=PIXMA MP130 Scanner usb:v04A9p1702* ID_MODEL_FROM_DATABASE=MP410 Composite usb:v04A9p1703* ID_MODEL_FROM_DATABASE=MP430 Composite usb:v04A9p1704* ID_MODEL_FROM_DATABASE=MP330 Composite usb:v04A9p1706* ID_MODEL_FROM_DATABASE=PIXMA MP750 Scanner usb:v04A9p1707* ID_MODEL_FROM_DATABASE=PIXMA MP780 Scanner usb:v04A9p1708* ID_MODEL_FROM_DATABASE=PIXMA MP760 Scanner usb:v04A9p1709* ID_MODEL_FROM_DATABASE=PIXMA MP150 Scanner usb:v04A9p170A* ID_MODEL_FROM_DATABASE=PIXMA MP170 Scanner usb:v04A9p170B* ID_MODEL_FROM_DATABASE=PIXMA MP450 Scanner usb:v04A9p170C* ID_MODEL_FROM_DATABASE=PIXMA MP500 Scanner usb:v04A9p170D* ID_MODEL_FROM_DATABASE=PIXMA MP800 Scanner usb:v04A9p170E* ID_MODEL_FROM_DATABASE=MP800R usb:v04A9p1710* ID_MODEL_FROM_DATABASE=MP950 usb:v04A9p1712* ID_MODEL_FROM_DATABASE=MP530 usb:v04A9p1713* ID_MODEL_FROM_DATABASE=PIXMA MP830 Scanner usb:v04A9p1714* ID_MODEL_FROM_DATABASE=MP160 usb:v04A9p1715* ID_MODEL_FROM_DATABASE=MP180 Storage usb:v04A9p1716* ID_MODEL_FROM_DATABASE=MP460 Composite usb:v04A9p1717* ID_MODEL_FROM_DATABASE=MP510 usb:v04A9p1718* ID_MODEL_FROM_DATABASE=MP600 Storage usb:v04A9p171A* ID_MODEL_FROM_DATABASE=MP810 Storage usb:v04A9p171B* ID_MODEL_FROM_DATABASE=MP960 usb:v04A9p1721* ID_MODEL_FROM_DATABASE=MP210 ser usb:v04A9p1723* ID_MODEL_FROM_DATABASE=MP470 ser usb:v04A9p1724* ID_MODEL_FROM_DATABASE=PIXMA MP520 series usb:v04A9p1725* ID_MODEL_FROM_DATABASE=MP610 ser usb:v04A9p1726* ID_MODEL_FROM_DATABASE=MP970 ser usb:v04A9p1727* ID_MODEL_FROM_DATABASE=MX300 ser usb:v04A9p1728* ID_MODEL_FROM_DATABASE=MX310 ser usb:v04A9p1729* ID_MODEL_FROM_DATABASE=MX700 ser usb:v04A9p172B* ID_MODEL_FROM_DATABASE=MP140 ser usb:v04A9p1736* ID_MODEL_FROM_DATABASE=PIXMA MX320 series usb:v04A9p173A* ID_MODEL_FROM_DATABASE=MP250 series printer usb:v04A9p173B* ID_MODEL_FROM_DATABASE=PIXMA MP270 All-In-One Printer usb:v04A9p173E* ID_MODEL_FROM_DATABASE=MP560 usb:v04A9p173F* ID_MODEL_FROM_DATABASE=Pixma MP640 Multifunction device usb:v04A9p1748* ID_MODEL_FROM_DATABASE=Pixma MG5150 usb:v04A9p174D* ID_MODEL_FROM_DATABASE=MX360 ser usb:v04A9p176D* ID_MODEL_FROM_DATABASE=PIXMA MG2550 usb:v04A9p1900* ID_MODEL_FROM_DATABASE=CanoScan LiDE 90 usb:v04A9p1901* ID_MODEL_FROM_DATABASE=CanoScan 8800F usb:v04A9p1904* ID_MODEL_FROM_DATABASE=CanoScan LiDE 100 usb:v04A9p1905* ID_MODEL_FROM_DATABASE=CanoScan LiDE 200 usb:v04A9p1906* ID_MODEL_FROM_DATABASE=CanoScan 5600F usb:v04A9p1907* ID_MODEL_FROM_DATABASE=CanoScan LiDE 700F usb:v04A9p1909* ID_MODEL_FROM_DATABASE=CanoScan LiDE 110 usb:v04A9p190A* ID_MODEL_FROM_DATABASE=CanoScan LiDE 210 usb:v04A9p190D* ID_MODEL_FROM_DATABASE=CanoScan 9000F Mark II usb:v04A9p190E* ID_MODEL_FROM_DATABASE=CanoScan LiDE 120 usb:v04A9p2200* ID_MODEL_FROM_DATABASE=CanoScan LiDE 25 usb:v04A9p2201* ID_MODEL_FROM_DATABASE=CanoScan FB320U usb:v04A9p2202* ID_MODEL_FROM_DATABASE=CanoScan FB620U usb:v04A9p2204* ID_MODEL_FROM_DATABASE=CanoScan FB630U usb:v04A9p2205* ID_MODEL_FROM_DATABASE=CanoScan FB1210U usb:v04A9p2206* ID_MODEL_FROM_DATABASE=CanoScan N650U/N656U usb:v04A9p2207* ID_MODEL_FROM_DATABASE=CanoScan 1220U usb:v04A9p2208* ID_MODEL_FROM_DATABASE=CanoScan D660U usb:v04A9p220A* ID_MODEL_FROM_DATABASE=CanoScan D2400UF usb:v04A9p220B* ID_MODEL_FROM_DATABASE=CanoScan D646U usb:v04A9p220C* ID_MODEL_FROM_DATABASE=CanoScan D1250U2 usb:v04A9p220D* ID_MODEL_FROM_DATABASE=CanoScan N670U/N676U/LiDE 20 usb:v04A9p220E* ID_MODEL_FROM_DATABASE=CanoScan N1240U/LiDE 30 usb:v04A9p220F* ID_MODEL_FROM_DATABASE=CanoScan 8000F usb:v04A9p2210* ID_MODEL_FROM_DATABASE=CanoScan 9900F usb:v04A9p2212* ID_MODEL_FROM_DATABASE=CanoScan 5000F usb:v04A9p2213* ID_MODEL_FROM_DATABASE=CanoScan LiDE 50/LiDE 35/LiDE 40 usb:v04A9p2214* ID_MODEL_FROM_DATABASE=CanoScan LiDE 80 usb:v04A9p2215* ID_MODEL_FROM_DATABASE=CanoScan 3000/3000F/3000ex usb:v04A9p2216* ID_MODEL_FROM_DATABASE=CanoScan 3200F usb:v04A9p2217* ID_MODEL_FROM_DATABASE=CanoScan 5200F usb:v04A9p2219* ID_MODEL_FROM_DATABASE=CanoScan 9950F usb:v04A9p221B* ID_MODEL_FROM_DATABASE=CanoScan 4200F usb:v04A9p221C* ID_MODEL_FROM_DATABASE=CanoScan LiDE 60 usb:v04A9p221E* ID_MODEL_FROM_DATABASE=CanoScan 8400F usb:v04A9p221F* ID_MODEL_FROM_DATABASE=CanoScan LiDE 500F usb:v04A9p2220* ID_MODEL_FROM_DATABASE=CanoScan LIDE 25 usb:v04A9p2224* ID_MODEL_FROM_DATABASE=CanoScan LiDE 600F usb:v04A9p2225* ID_MODEL_FROM_DATABASE=CanoScan LiDE 70 usb:v04A9p2228* ID_MODEL_FROM_DATABASE=CanoScan 4400F usb:v04A9p2229* ID_MODEL_FROM_DATABASE=CanoScan 8600F usb:v04A9p2602* ID_MODEL_FROM_DATABASE=MultiPASS C555 usb:v04A9p2603* ID_MODEL_FROM_DATABASE=MultiPASS C755 usb:v04A9p260A* ID_MODEL_FROM_DATABASE=CAPT Printer usb:v04A9p260E* ID_MODEL_FROM_DATABASE=LBP-2000 usb:v04A9p2610* ID_MODEL_FROM_DATABASE=MPC600F usb:v04A9p2611* ID_MODEL_FROM_DATABASE=SmartBase MPC400 usb:v04A9p2612* ID_MODEL_FROM_DATABASE=MultiPASS C855 usb:v04A9p2617* ID_MODEL_FROM_DATABASE=CAPT Printer usb:v04A9p261A* ID_MODEL_FROM_DATABASE=iR1600 usb:v04A9p261B* ID_MODEL_FROM_DATABASE=iR1610 usb:v04A9p261C* ID_MODEL_FROM_DATABASE=iC2300 usb:v04A9p261F* ID_MODEL_FROM_DATABASE=MPC200 Printer usb:v04A9p2621* ID_MODEL_FROM_DATABASE=iR2000 usb:v04A9p2622* ID_MODEL_FROM_DATABASE=iR2010 usb:v04A9p2623* ID_MODEL_FROM_DATABASE=FAX-B180C usb:v04A9p2629* ID_MODEL_FROM_DATABASE=FAXPHONE L75 usb:v04A9p262B* ID_MODEL_FROM_DATABASE=LaserShot LBP-1120 Printer usb:v04A9p262D* ID_MODEL_FROM_DATABASE=iR C3200 usb:v04A9p262F* ID_MODEL_FROM_DATABASE=MultiPASS MP730 usb:v04A9p2630* ID_MODEL_FROM_DATABASE=MultiPASS MP700 usb:v04A9p2631* ID_MODEL_FROM_DATABASE=LASER CLASS 700 usb:v04A9p2632* ID_MODEL_FROM_DATABASE=FAX-L2000 usb:v04A9p2635* ID_MODEL_FROM_DATABASE=MPC190 usb:v04A9p2637* ID_MODEL_FROM_DATABASE=iR C6800 usb:v04A9p2638* ID_MODEL_FROM_DATABASE=iR C3100 usb:v04A9p263C* ID_MODEL_FROM_DATABASE=Smartbase MP360 usb:v04A9p263D* ID_MODEL_FROM_DATABASE=MP370 usb:v04A9p263E* ID_MODEL_FROM_DATABASE=MP390 FAX usb:v04A9p263F* ID_MODEL_FROM_DATABASE=MP375 usb:v04A9p2646* ID_MODEL_FROM_DATABASE=MF5530 Scanner Device V1.9.1 usb:v04A9p2647* ID_MODEL_FROM_DATABASE=MF5550 Composite usb:v04A9p264D* ID_MODEL_FROM_DATABASE=PIXMA MP710 usb:v04A9p264E* ID_MODEL_FROM_DATABASE=MF5630 usb:v04A9p264F* ID_MODEL_FROM_DATABASE=MF5650 (FAX) usb:v04A9p2650* ID_MODEL_FROM_DATABASE=iR 6800C EUR usb:v04A9p2651* ID_MODEL_FROM_DATABASE=iR 3100C EUR usb:v04A9p2655* ID_MODEL_FROM_DATABASE=FP-L170/MF350/L380/L398 usb:v04A9p2659* ID_MODEL_FROM_DATABASE=MF8100 usb:v04A9p265B* ID_MODEL_FROM_DATABASE=CAPT Printer usb:v04A9p265C* ID_MODEL_FROM_DATABASE=iR C3220 usb:v04A9p265D* ID_MODEL_FROM_DATABASE=MF5730 usb:v04A9p265E* ID_MODEL_FROM_DATABASE=MF5750 usb:v04A9p265F* ID_MODEL_FROM_DATABASE=MF5770 usb:v04A9p2660* ID_MODEL_FROM_DATABASE=MF3110 usb:v04A9p2663* ID_MODEL_FROM_DATABASE=iR3570/iR4570 usb:v04A9p2664* ID_MODEL_FROM_DATABASE=iR2270/iR2870 usb:v04A9p2665* ID_MODEL_FROM_DATABASE=iR C2620 usb:v04A9p2666* ID_MODEL_FROM_DATABASE=iR C5800 usb:v04A9p2667* ID_MODEL_FROM_DATABASE=iR85PLUS usb:v04A9p2669* ID_MODEL_FROM_DATABASE=iR105PLUS usb:v04A9p266A* ID_MODEL_FROM_DATABASE=CAPT Device usb:v04A9p266B* ID_MODEL_FROM_DATABASE=iR8070 usb:v04A9p266C* ID_MODEL_FROM_DATABASE=iR9070 usb:v04A9p266D* ID_MODEL_FROM_DATABASE=iR 5800C EUR usb:v04A9p266E* ID_MODEL_FROM_DATABASE=CAPT Device usb:v04A9p266F* ID_MODEL_FROM_DATABASE=iR2230 usb:v04A9p2670* ID_MODEL_FROM_DATABASE=iR3530 usb:v04A9p2671* ID_MODEL_FROM_DATABASE=iR5570/iR6570 usb:v04A9p2672* ID_MODEL_FROM_DATABASE=iR C3170 usb:v04A9p2673* ID_MODEL_FROM_DATABASE=iR 3170C EUR usb:v04A9p2674* ID_MODEL_FROM_DATABASE=L120 usb:v04A9p2675* ID_MODEL_FROM_DATABASE=iR2830 usb:v04A9p2676* ID_MODEL_FROM_DATABASE=CAPT Device usb:v04A9p2677* ID_MODEL_FROM_DATABASE=iR C2570 usb:v04A9p2678* ID_MODEL_FROM_DATABASE=iR 2570C EUR usb:v04A9p2679* ID_MODEL_FROM_DATABASE=CAPT Device usb:v04A9p267A* ID_MODEL_FROM_DATABASE=iR2016 usb:v04A9p267B* ID_MODEL_FROM_DATABASE=iR2020 usb:v04A9p267D* ID_MODEL_FROM_DATABASE=MF7100 series usb:v04A9p2684* ID_MODEL_FROM_DATABASE=MF3200 series usb:v04A9p2686* ID_MODEL_FROM_DATABASE=MF6500 series usb:v04A9p2687* ID_MODEL_FROM_DATABASE=iR4530 usb:v04A9p2688* ID_MODEL_FROM_DATABASE=LBP3460 usb:v04A9p268C* ID_MODEL_FROM_DATABASE=iR C6870 usb:v04A9p268D* ID_MODEL_FROM_DATABASE=iR 6870C EUR usb:v04A9p268E* ID_MODEL_FROM_DATABASE=iR C5870 usb:v04A9p268F* ID_MODEL_FROM_DATABASE=iR 5870C EUR usb:v04A9p2691* ID_MODEL_FROM_DATABASE=iR7105 usb:v04A9p26A3* ID_MODEL_FROM_DATABASE=MF4100 series usb:v04A9p26B0* ID_MODEL_FROM_DATABASE=MF4600 series usb:v04A9p26B4* ID_MODEL_FROM_DATABASE=MF4010 series usb:v04A9p26B5* ID_MODEL_FROM_DATABASE=MF4200 series usb:v04A9p26DA* ID_MODEL_FROM_DATABASE=LBP3010B printer usb:v04A9p26E6* ID_MODEL_FROM_DATABASE=iR1024 usb:v04A9p2736* ID_MODEL_FROM_DATABASE=I-SENSYS MF4550d usb:v04A9p2737* ID_MODEL_FROM_DATABASE=MF4410 usb:v04A9p3041* ID_MODEL_FROM_DATABASE=PowerShot S10 usb:v04A9p3042* ID_MODEL_FROM_DATABASE=CanoScan FS4000US Film Scanner usb:v04A9p3043* ID_MODEL_FROM_DATABASE=PowerShot S20 usb:v04A9p3044* ID_MODEL_FROM_DATABASE=EOS D30 usb:v04A9p3045* ID_MODEL_FROM_DATABASE=PowerShot S100 usb:v04A9p3046* ID_MODEL_FROM_DATABASE=IXY Digital usb:v04A9p3047* ID_MODEL_FROM_DATABASE=Digital IXUS usb:v04A9p3048* ID_MODEL_FROM_DATABASE=PowerShot G1 usb:v04A9p3049* ID_MODEL_FROM_DATABASE=PowerShot Pro90 IS usb:v04A9p304A* ID_MODEL_FROM_DATABASE=CP-10 usb:v04A9p304B* ID_MODEL_FROM_DATABASE=IXY Digital 300 usb:v04A9p304C* ID_MODEL_FROM_DATABASE=PowerShot S300 usb:v04A9p304D* ID_MODEL_FROM_DATABASE=Digital IXUS 300 usb:v04A9p304E* ID_MODEL_FROM_DATABASE=PowerShot A20 usb:v04A9p304F* ID_MODEL_FROM_DATABASE=PowerShot A10 usb:v04A9p3050* ID_MODEL_FROM_DATABASE=PowerShot unknown 1 usb:v04A9p3051* ID_MODEL_FROM_DATABASE=PowerShot S110 usb:v04A9p3052* ID_MODEL_FROM_DATABASE=Digital IXUS V usb:v04A9p3055* ID_MODEL_FROM_DATABASE=PowerShot G2 usb:v04A9p3056* ID_MODEL_FROM_DATABASE=PowerShot S40 usb:v04A9p3057* ID_MODEL_FROM_DATABASE=PowerShot S30 usb:v04A9p3058* ID_MODEL_FROM_DATABASE=PowerShot A40 usb:v04A9p3059* ID_MODEL_FROM_DATABASE=PowerShot A30 usb:v04A9p305B* ID_MODEL_FROM_DATABASE=ZR45MC Digital Camcorder usb:v04A9p305C* ID_MODEL_FROM_DATABASE=PowerShot unknown 2 usb:v04A9p3060* ID_MODEL_FROM_DATABASE=EOS D60 usb:v04A9p3061* ID_MODEL_FROM_DATABASE=PowerShot A100 usb:v04A9p3062* ID_MODEL_FROM_DATABASE=PowerShot A200 usb:v04A9p3063* ID_MODEL_FROM_DATABASE=CP-100 usb:v04A9p3065* ID_MODEL_FROM_DATABASE=PowerShot S200 usb:v04A9p3066* ID_MODEL_FROM_DATABASE=Digital IXUS 330 usb:v04A9p3067* ID_MODEL_FROM_DATABASE=MV550i Digital Video Camera usb:v04A9p3069* ID_MODEL_FROM_DATABASE=PowerShot G3 usb:v04A9p306A* ID_MODEL_FROM_DATABASE=Digital unknown 3 usb:v04A9p306B* ID_MODEL_FROM_DATABASE=MVX2i Digital Video Camera usb:v04A9p306C* ID_MODEL_FROM_DATABASE=PowerShot S45 usb:v04A9p306D* ID_MODEL_FROM_DATABASE=PowerShot S45 PtP Mode usb:v04A9p306E* ID_MODEL_FROM_DATABASE=PowerShot G3 (normal mode) usb:v04A9p306F* ID_MODEL_FROM_DATABASE=PowerShot G3 (ptp) usb:v04A9p3070* ID_MODEL_FROM_DATABASE=PowerShot S230 usb:v04A9p3071* ID_MODEL_FROM_DATABASE=PowerShot S230 (ptp) usb:v04A9p3072* ID_MODEL_FROM_DATABASE=PowerShot SD100 / Digital IXUS II (ptp) usb:v04A9p3073* ID_MODEL_FROM_DATABASE=PowerShot A70 (ptp) usb:v04A9p3074* ID_MODEL_FROM_DATABASE=PowerShot A60 (ptp) usb:v04A9p3075* ID_MODEL_FROM_DATABASE=IXUS 400 Camera usb:v04A9p3076* ID_MODEL_FROM_DATABASE=PowerShot A300 usb:v04A9p3077* ID_MODEL_FROM_DATABASE=PowerShot S50 usb:v04A9p3078* ID_MODEL_FROM_DATABASE=ZR70MC Digital Camcorder usb:v04A9p307A* ID_MODEL_FROM_DATABASE=MV650i (normal mode) usb:v04A9p307B* ID_MODEL_FROM_DATABASE=MV630i Digital Video Camera usb:v04A9p307C* ID_MODEL_FROM_DATABASE=CP-200 usb:v04A9p307D* ID_MODEL_FROM_DATABASE=CP-300 usb:v04A9p307F* ID_MODEL_FROM_DATABASE=Optura 20 usb:v04A9p3080* ID_MODEL_FROM_DATABASE=MVX150i (normal mode) / Optura 20 (normal mode) usb:v04A9p3081* ID_MODEL_FROM_DATABASE=Optura 10 usb:v04A9p3082* ID_MODEL_FROM_DATABASE=MVX100i / Optura 10 usb:v04A9p3083* ID_MODEL_FROM_DATABASE=EOS 10D usb:v04A9p3084* ID_MODEL_FROM_DATABASE=EOS 300D / EOS Digital Rebel usb:v04A9p3085* ID_MODEL_FROM_DATABASE=PowerShot G5 usb:v04A9p3087* ID_MODEL_FROM_DATABASE=Elura 50 (PTP mode) usb:v04A9p3088* ID_MODEL_FROM_DATABASE=Elura 50 (normal mode) usb:v04A9p308D* ID_MODEL_FROM_DATABASE=MVX3i usb:v04A9p308E* ID_MODEL_FROM_DATABASE=FV M1 (normal mode) / MVX 3i (normal mode) / Optura Xi (normal mode) usb:v04A9p3093* ID_MODEL_FROM_DATABASE=Optura 300 usb:v04A9p3096* ID_MODEL_FROM_DATABASE=IXY DV M2 (normal mode) / MVX 10i (normal mode) usb:v04A9p3099* ID_MODEL_FROM_DATABASE=EOS 300D (ptp) usb:v04A9p309A* ID_MODEL_FROM_DATABASE=PowerShot A80 usb:v04A9p309B* ID_MODEL_FROM_DATABASE=Digital IXUS (ptp) usb:v04A9p309C* ID_MODEL_FROM_DATABASE=PowerShot S1 IS usb:v04A9p309D* ID_MODEL_FROM_DATABASE=Powershot Pro 1 usb:v04A9p309F* ID_MODEL_FROM_DATABASE=Camera usb:v04A9p30A0* ID_MODEL_FROM_DATABASE=Camera usb:v04A9p30A1* ID_MODEL_FROM_DATABASE=Camera usb:v04A9p30A2* ID_MODEL_FROM_DATABASE=Camera usb:v04A9p30A8* ID_MODEL_FROM_DATABASE=Elura 60E/Optura 40 (ptp) usb:v04A9p30A9* ID_MODEL_FROM_DATABASE=MVX25i (normal mode) / Optura 40 (normal mode) usb:v04A9p30B1* ID_MODEL_FROM_DATABASE=PowerShot S70 (normal mode) / PowerShot S70 (PTP mode) usb:v04A9p30B2* ID_MODEL_FROM_DATABASE=PowerShot S60 (normal mode) / PowerShot S60 (PTP mode) usb:v04A9p30B3* ID_MODEL_FROM_DATABASE=PowerShot G6 (normal mode) / PowerShot G6 (PTP mode) usb:v04A9p30B4* ID_MODEL_FROM_DATABASE=PowerShot S500 usb:v04A9p30B5* ID_MODEL_FROM_DATABASE=PowerShot A75 usb:v04A9p30B6* ID_MODEL_FROM_DATABASE=Digital IXUS II2 / Digital IXUS II2 (PTP mode) / PowerShot SD110 (PTP mode) / PowerShot SD110 Digital ELPH usb:v04A9p30B7* ID_MODEL_FROM_DATABASE=PowerShot A400 / PowerShot A400 (PTP mode) usb:v04A9p30B8* ID_MODEL_FROM_DATABASE=PowerShot A310 / PowerShot A310 (PTP mode) usb:v04A9p30B9* ID_MODEL_FROM_DATABASE=Powershot A85 usb:v04A9p30BA* ID_MODEL_FROM_DATABASE=PowerShot S410 Digital Elph usb:v04A9p30BB* ID_MODEL_FROM_DATABASE=PowerShot A95 usb:v04A9p30BD* ID_MODEL_FROM_DATABASE=CP-220 usb:v04A9p30BE* ID_MODEL_FROM_DATABASE=CP-330 usb:v04A9p30BF* ID_MODEL_FROM_DATABASE=Digital IXUS 40 usb:v04A9p30C0* ID_MODEL_FROM_DATABASE=Digital IXUS 30 (PTP mode) / PowerShot SD200 (PTP mode) usb:v04A9p30C1* ID_MODEL_FROM_DATABASE=Digital IXUS 50 (normal mode) / IXY Digital 55 (normal mode) / PowerShot A520 (PTP mode) / PowerShot SD400 (normal mode) usb:v04A9p30C2* ID_MODEL_FROM_DATABASE=PowerShot A510 (normal mode) / PowerShot A510 (PTP mode) usb:v04A9p30C4* ID_MODEL_FROM_DATABASE=Digital IXUS i5 (normal mode) / IXY Digital L2 (normal mode) / PowerShot SD20 (normal mode) usb:v04A9p30EA* ID_MODEL_FROM_DATABASE=EOS 1D Mark II (PTP mode) usb:v04A9p30EB* ID_MODEL_FROM_DATABASE=EOS 20D usb:v04A9p30EC* ID_MODEL_FROM_DATABASE=EOS 20D (ptp) usb:v04A9p30EE* ID_MODEL_FROM_DATABASE=EOS 350D usb:v04A9p30EF* ID_MODEL_FROM_DATABASE=EOS 350D (ptp) usb:v04A9p30F0* ID_MODEL_FROM_DATABASE=PowerShot S2 IS (PTP mode) usb:v04A9p30F2* ID_MODEL_FROM_DATABASE=Digital IXUS 700 (normal mode) / Digital IXUS 700 (PTP mode) / IXY Digital 600 (normal mode) / PowerShot SD500 (normal mode) / PowerShot SD500 (PTP mode) usb:v04A9p30F4* ID_MODEL_FROM_DATABASE=PowerShot SD30 / Ixus iZoom / IXY DIGITAL L3 usb:v04A9p30F5* ID_MODEL_FROM_DATABASE=SELPHY CP500 usb:v04A9p30F6* ID_MODEL_FROM_DATABASE=SELPHY CP400 usb:v04A9p30F8* ID_MODEL_FROM_DATABASE=Powershot A430 usb:v04A9p30F9* ID_MODEL_FROM_DATABASE=PowerShot A410 (PTP mode) usb:v04A9p30FA* ID_MODEL_FROM_DATABASE=PowerShot S80 usb:v04A9p30FC* ID_MODEL_FROM_DATABASE=PowerShot A620 (PTP mode) usb:v04A9p30FD* ID_MODEL_FROM_DATABASE=PowerShot A610 (normal mode)/PowerShot A610 (PTP mode) usb:v04A9p30FE* ID_MODEL_FROM_DATABASE=Digital IXUS 65 (PTP mode)/PowerShot SD630 (PTP mode) usb:v04A9p30FF* ID_MODEL_FROM_DATABASE=Digital IXUS 55 (PTP mode)/PowerShot SD450 (PTP mode) usb:v04A9p3100* ID_MODEL_FROM_DATABASE=PowerShot TX1 usb:v04A9p310B* ID_MODEL_FROM_DATABASE=SELPHY CP600 usb:v04A9p310E* ID_MODEL_FROM_DATABASE=Digital IXUS 50 (PTP mode) usb:v04A9p310F* ID_MODEL_FROM_DATABASE=PowerShot A420 usb:v04A9p3110* ID_MODEL_FROM_DATABASE=EOS Digital Rebel XTi usb:v04A9p3115* ID_MODEL_FROM_DATABASE=PowerShot SD900 / Digital IXUS 900 Ti / IXY DIGITAL 1000 usb:v04A9p3116* ID_MODEL_FROM_DATABASE=Digital IXUS 750 / PowerShot SD550 (PTP mode) usb:v04A9p3117* ID_MODEL_FROM_DATABASE=PowerShot A700 usb:v04A9p3119* ID_MODEL_FROM_DATABASE=PowerShot SD700 IS / Digital IXUS 800 IS / IXY Digital 800 IS usb:v04A9p311A* ID_MODEL_FROM_DATABASE=PowerShot S3 IS usb:v04A9p311B* ID_MODEL_FROM_DATABASE=PowerShot A540 usb:v04A9p311C* ID_MODEL_FROM_DATABASE=PowerShot SD600 DIGITAL ELPH / DIGITAL IXUS 60 / IXY DIGITAL 70 usb:v04A9p3125* ID_MODEL_FROM_DATABASE=PowerShot G7 usb:v04A9p3126* ID_MODEL_FROM_DATABASE=PowerShot A530 usb:v04A9p3127* ID_MODEL_FROM_DATABASE=SELPHY CP710 usb:v04A9p3128* ID_MODEL_FROM_DATABASE=SELPHY CP510 usb:v04A9p312D* ID_MODEL_FROM_DATABASE=Elura 100 usb:v04A9p3136* ID_MODEL_FROM_DATABASE=PowerShot SD800 IS / Digital IXUS 850 IS / IXY DIGITAL 900 IS usb:v04A9p3137* ID_MODEL_FROM_DATABASE=PowerShot SD40 / Digital IXUS i7 IXY / DIGITAL L4 usb:v04A9p3138* ID_MODEL_FROM_DATABASE=PowerShot A710 IS usb:v04A9p3139* ID_MODEL_FROM_DATABASE=PowerShot A640 usb:v04A9p313A* ID_MODEL_FROM_DATABASE=PowerShot A630 usb:v04A9p3141* ID_MODEL_FROM_DATABASE=SELPHY ES1 usb:v04A9p3142* ID_MODEL_FROM_DATABASE=SELPHY CP730 usb:v04A9p3143* ID_MODEL_FROM_DATABASE=SELPHY CP720 usb:v04A9p3145* ID_MODEL_FROM_DATABASE=EOS 450D usb:v04A9p3146* ID_MODEL_FROM_DATABASE=EOS 40D usb:v04A9p3147* ID_MODEL_FROM_DATABASE=EOS 1Ds Mark III usb:v04A9p3148* ID_MODEL_FROM_DATABASE=PowerShot S5 IS usb:v04A9p3149* ID_MODEL_FROM_DATABASE=PowerShot A460 usb:v04A9p314B* ID_MODEL_FROM_DATABASE=PowerShot SD850 IS DIGITAL ELPH / Digital IXUS 950 IS / IXY DIGITAL 810 IS usb:v04A9p314C* ID_MODEL_FROM_DATABASE=PowerShot A570 IS usb:v04A9p314D* ID_MODEL_FROM_DATABASE=PowerShot A560 usb:v04A9p314E* ID_MODEL_FROM_DATABASE=PowerShot SD750 DIGITAL ELPH / DIGITAL IXUS 75 / IXY DIGITAL 90 usb:v04A9p314F* ID_MODEL_FROM_DATABASE=PowerShot SD1000 DIGITAL ELPH / DIGITAL IXUS 70 / IXY DIGITAL 10 usb:v04A9p3150* ID_MODEL_FROM_DATABASE=PowerShot A550 usb:v04A9p3155* ID_MODEL_FROM_DATABASE=PowerShot A450 usb:v04A9p315A* ID_MODEL_FROM_DATABASE=PowerShot G9 usb:v04A9p315B* ID_MODEL_FROM_DATABASE=PowerShot A650 IS usb:v04A9p315D* ID_MODEL_FROM_DATABASE=PowerShot A720 usb:v04A9p315E* ID_MODEL_FROM_DATABASE=PowerShot SX100 IS usb:v04A9p315F* ID_MODEL_FROM_DATABASE=PowerShot SD950 IS DIGITAL ELPH / DIGITAL IXUS 960 IS / IXY DIGITAL 2000 IS usb:v04A9p3160* ID_MODEL_FROM_DATABASE=Digital IXUS 860 IS usb:v04A9p3170* ID_MODEL_FROM_DATABASE=SELPHY CP750 usb:v04A9p3171* ID_MODEL_FROM_DATABASE=SELPHY CP740 usb:v04A9p3172* ID_MODEL_FROM_DATABASE=SELPHY CP520 usb:v04A9p3173* ID_MODEL_FROM_DATABASE=PowerShot SD890 IS DIGITAL ELPH / Digital IXUS 970 IS / IXY DIGITAL 820 IS usb:v04A9p3174* ID_MODEL_FROM_DATABASE=PowerShot SD790 IS DIGITAL ELPH / Digital IXUS 90 IS / IXY DIGITAL 95 IS usb:v04A9p3175* ID_MODEL_FROM_DATABASE=IXY Digital 25 IS usb:v04A9p3176* ID_MODEL_FROM_DATABASE=PowerShot A590 usb:v04A9p3177* ID_MODEL_FROM_DATABASE=PowerShot A580 usb:v04A9p317A* ID_MODEL_FROM_DATABASE=PC1267 [Powershot A470] usb:v04A9p3184* ID_MODEL_FROM_DATABASE=Digital IXUS 80 IS (PTP mode) usb:v04A9p3185* ID_MODEL_FROM_DATABASE=SELPHY ES2 usb:v04A9p3186* ID_MODEL_FROM_DATABASE=SELPHY ES20 usb:v04A9p318D* ID_MODEL_FROM_DATABASE=PowerShot SX100 IS usb:v04A9p318E* ID_MODEL_FROM_DATABASE=PowerShot A1000 IS usb:v04A9p318F* ID_MODEL_FROM_DATABASE=PowerShot G10 usb:v04A9p3191* ID_MODEL_FROM_DATABASE=PowerShot A2000 IS usb:v04A9p3192* ID_MODEL_FROM_DATABASE=PowerShot SX110 IS usb:v04A9p3193* ID_MODEL_FROM_DATABASE=PowerShot SD990 IS DIGITAL ELPH / Digital IXUS 980 IS / IXY DIGITAL 3000 IS usb:v04A9p3195* ID_MODEL_FROM_DATABASE=PowerShot SX1 IS usb:v04A9p3196* ID_MODEL_FROM_DATABASE=PowerShot SD880 IS DIGITAL ELPH / Digital IXUS 870 IS / IXY DIGITAL 920 IS usb:v04A9p319A* ID_MODEL_FROM_DATABASE=EOS 7D usb:v04A9p319B* ID_MODEL_FROM_DATABASE=EOS 50D usb:v04A9p31AA* ID_MODEL_FROM_DATABASE=SELPHY CP770 usb:v04A9p31AB* ID_MODEL_FROM_DATABASE=SELPHY CP760 usb:v04A9p31AD* ID_MODEL_FROM_DATABASE=PowerShot E1 usb:v04A9p31AF* ID_MODEL_FROM_DATABASE=SELPHY ES3 usb:v04A9p31B0* ID_MODEL_FROM_DATABASE=SELPHY ES30 usb:v04A9p31B1* ID_MODEL_FROM_DATABASE=SELPHY CP530 usb:v04A9p31BC* ID_MODEL_FROM_DATABASE=PowerShot D10 usb:v04A9p31BD* ID_MODEL_FROM_DATABASE=PowerShot SD960 IS DIGITAL ELPH / Digital IXUS 110 IS / IXY DIGITAL 510 IS usb:v04A9p31BE* ID_MODEL_FROM_DATABASE=PowerShot A2100 IS usb:v04A9p31BF* ID_MODEL_FROM_DATABASE=PowerShot A480 usb:v04A9p31C0* ID_MODEL_FROM_DATABASE=PowerShot SX200 IS usb:v04A9p31C1* ID_MODEL_FROM_DATABASE=PowerShot SD970 IS DIGITAL ELPH / Digital IXUS 990 IS / IXY DIGITAL 830 IS usb:v04A9p31C2* ID_MODEL_FROM_DATABASE=PowerShot SD780 IS DIGITAL ELPH / Digital IXUS 100 IS / IXY DIGITAL 210 IS usb:v04A9p31C3* ID_MODEL_FROM_DATABASE=PowerShot A1100 IS usb:v04A9p31C4* ID_MODEL_FROM_DATABASE=PowerShot SD1200 IS DIGITAL ELPH / Digital IXUS 95 IS / IXY DIGITAL 110 IS usb:v04A9p31CF* ID_MODEL_FROM_DATABASE=EOS Rebel T1i / EOS 500D / EOS Kiss X3 usb:v04A9p31DD* ID_MODEL_FROM_DATABASE=SELPHY CP780 usb:v04A9p31DF* ID_MODEL_FROM_DATABASE=PowerShot G11 usb:v04A9p31E0* ID_MODEL_FROM_DATABASE=PowerShot SX120 IS usb:v04A9p31E1* ID_MODEL_FROM_DATABASE=PowerShot S90 usb:v04A9p31E4* ID_MODEL_FROM_DATABASE=PowerShot SX20 IS usb:v04A9p31E5* ID_MODEL_FROM_DATABASE=Digital IXUS 200 IS usb:v04A9p31E6* ID_MODEL_FROM_DATABASE=PowerShot SD940 IS DIGITAL ELPH / Digital IXUS 120 IS / IXY DIGITAL 220 IS usb:v04A9p31E7* ID_MODEL_FROM_DATABASE=SELPHY CP790 usb:v04A9p31EA* ID_MODEL_FROM_DATABASE=EOS Rebel T2i / EOS 550D / EOS Kiss X4 usb:v04A9p31EE* ID_MODEL_FROM_DATABASE=SELPHY ES40 usb:v04A9p31EF* ID_MODEL_FROM_DATABASE=PowerShot A495 usb:v04A9p31F0* ID_MODEL_FROM_DATABASE=PowerShot A490 usb:v04A9p31F1* ID_MODEL_FROM_DATABASE=PowerShot A3100 IS / PowerShot A3150 IS usb:v04A9p31F2* ID_MODEL_FROM_DATABASE=PowerShot A3000 IS usb:v04A9p31F3* ID_MODEL_FROM_DATABASE=PowerShot Digital ELPH SD1400 IS usb:v04A9p31F4* ID_MODEL_FROM_DATABASE=PowerShot SD1300 IS / IXUS 105 usb:v04A9p31F5* ID_MODEL_FROM_DATABASE=Powershot SD3500 IS / IXUS 210 IS usb:v04A9p31F6* ID_MODEL_FROM_DATABASE=PowerShot SX210 IS usb:v04A9p31F7* ID_MODEL_FROM_DATABASE=Powershot SD4000 IS / IXUS 300 HS / IXY 30S usb:v04A9p31F8* ID_MODEL_FROM_DATABASE=Powershot SD4500 IS / IXUS 1000 HS / IXY 50S usb:v04A9p31FF* ID_MODEL_FROM_DATABASE=Digital IXUS 55 usb:v04A9p3209* ID_MODEL_FROM_DATABASE=Vixia HF S21 A usb:v04A9p320F* ID_MODEL_FROM_DATABASE=PowerShot G12 usb:v04A9p3210* ID_MODEL_FROM_DATABASE=Powershot SX30 IS usb:v04A9p3211* ID_MODEL_FROM_DATABASE=PowerShot SX130 IS usb:v04A9p3212* ID_MODEL_FROM_DATABASE=Powershot S95 usb:v04A9p3214* ID_MODEL_FROM_DATABASE=SELPHY CP800 usb:v04A9p3218* ID_MODEL_FROM_DATABASE=EOS 600D / Rebel T3i (ptp) usb:v04A9p3223* ID_MODEL_FROM_DATABASE=PowerShot A3300 IS usb:v04A9p3224* ID_MODEL_FROM_DATABASE=PowerShot A3200 IS usb:v04A9p3225* ID_MODEL_FROM_DATABASE=PowerShot ELPH 500 HS / IXUS 310 HS usb:v04A9p3226* ID_MODEL_FROM_DATABASE=PowerShow A800 usb:v04A9p3227* ID_MODEL_FROM_DATABASE=PowerShot ELPH 100 HS / IXUS 115 HS usb:v04A9p3228* ID_MODEL_FROM_DATABASE=PowerShot SX230 HS usb:v04A9p3229* ID_MODEL_FROM_DATABASE=PowerShot ELPH 300 HS / IXUS 220 HS usb:v04A9p322A* ID_MODEL_FROM_DATABASE=PowerShot A2200 usb:v04A9p322B* ID_MODEL_FROM_DATABASE=Powershot A1200 usb:v04A9p322C* ID_MODEL_FROM_DATABASE=PowerShot SX220 HS usb:v04A9p3233* ID_MODEL_FROM_DATABASE=PowerShot G1 X usb:v04A9p3234* ID_MODEL_FROM_DATABASE=PowerShot SX150 IS usb:v04A9p3235* ID_MODEL_FROM_DATABASE=PowerShot ELPH 510 HS / IXUS 1100 HS usb:v04A9p3236* ID_MODEL_FROM_DATABASE=PowerShot S100 usb:v04A9p3237* ID_MODEL_FROM_DATABASE=PowerShot ELPH 310 HS / IXUS 230 HS usb:v04A9p3238* ID_MODEL_FROM_DATABASE=PowerShot SX40 HS usb:v04A9p323B* ID_MODEL_FROM_DATABASE=EOS Rebel T4i usb:v04A9p323E* ID_MODEL_FROM_DATABASE=PowerShot A1300 usb:v04A9p323F* ID_MODEL_FROM_DATABASE=PowerShot A810 usb:v04A9p3240* ID_MODEL_FROM_DATABASE=PowerShot ELPH 320 HS / IXUS 240 HS usb:v04A9p3241* ID_MODEL_FROM_DATABASE=PowerShot ELPH 110 HS / IXUS 125 HS usb:v04A9p3242* ID_MODEL_FROM_DATABASE=PowerShot D20 usb:v04A9p3243* ID_MODEL_FROM_DATABASE=PowerShot A4000 IS usb:v04A9p3244* ID_MODEL_FROM_DATABASE=PowerShot SX260 HS usb:v04A9p3245* ID_MODEL_FROM_DATABASE=PowerShot SX240 HS usb:v04A9p3247* ID_MODEL_FROM_DATABASE=PowerShot ELPH 520 HS / IXUS 500 HS usb:v04A9p3248* ID_MODEL_FROM_DATABASE=PowerShot A3400 IS usb:v04A9p3249* ID_MODEL_FROM_DATABASE=PowerShot A2400 IS usb:v04A9p324A* ID_MODEL_FROM_DATABASE=PowerShot A2300 usb:v04A9p3255* ID_MODEL_FROM_DATABASE=SELPHY CP900 usb:v04A9p3256* ID_MODEL_FROM_DATABASE=SELPHY CP810 usb:v04A9p3258* ID_MODEL_FROM_DATABASE=PowerShot G15 usb:v04A9p3259* ID_MODEL_FROM_DATABASE=PowerShot SX50 HS usb:v04A9p325A* ID_MODEL_FROM_DATABASE=PowerShot SX160 IS usb:v04A9p325B* ID_MODEL_FROM_DATABASE=PowerShot S110 usb:v04A9p325C* ID_MODEL_FROM_DATABASE=PowerShot SX500 IS usb:v04A9p325E* ID_MODEL_FROM_DATABASE=PowerShot N usb:v04A9p325F* ID_MODEL_FROM_DATABASE=PowerShot SX280 HS usb:v04A9p3260* ID_MODEL_FROM_DATABASE=PowerShot SX270 HS usb:v04A9p3261* ID_MODEL_FROM_DATABASE=PowerShot A3500 IS usb:v04A9p3262* ID_MODEL_FROM_DATABASE=PowerShot A2600 usb:v04A9p3263* ID_MODEL_FROM_DATABASE=PowerShot SX275 HS usb:v04A9p3264* ID_MODEL_FROM_DATABASE=PowerShot A1400 usb:v04A9p3265* ID_MODEL_FROM_DATABASE=Powershot ELPH 130 IS / IXUS 140 usb:v04A9p3266* ID_MODEL_FROM_DATABASE=Powershot ELPH 120 IS / IXUS 135 usb:v04A9p3268* ID_MODEL_FROM_DATABASE=PowerShot ELPH 330 HS / IXUS 255 HS usb:v04A9p3271* ID_MODEL_FROM_DATABASE=PowerShot A2500 usb:v04A9p3276* ID_MODEL_FROM_DATABASE=PowerShot SX170 IS usb:v04A9p3277* ID_MODEL_FROM_DATABASE=PowerShot SX510 HS usb:v04A9p3278* ID_MODEL_FROM_DATABASE=PowerShot S200 usb:v04A9p327D* ID_MODEL_FROM_DATABASE=Powershot ELPH 115 IS / IXUS 132 usb:v04A9p327F* ID_MODEL_FROM_DATABASE=EOS Rebel T5 / EOS 1200D / EOS Kiss X70 usb:v04A9p3284* ID_MODEL_FROM_DATABASE=PowerShot D30 usb:v04A9p3285* ID_MODEL_FROM_DATABASE=PowerShot SX700 HS usb:v04A9p3286* ID_MODEL_FROM_DATABASE=PowerShot SX600 HS usb:v04A9p3287* ID_MODEL_FROM_DATABASE=PowerShot ELPH 140 IS / IXUS 150 usb:v04A9p3288* ID_MODEL_FROM_DATABASE=Powershot ELPH 135 / IXUS 145 usb:v04A9p3289* ID_MODEL_FROM_DATABASE=PowerShot ELPH 340 HS / IXUS 265 HS usb:v04A9p328A* ID_MODEL_FROM_DATABASE=PowerShot ELPH 150 IS / IXUS 155 usb:v04A9p328B* ID_MODEL_FROM_DATABASE=PowerShot N Facebook(R) Ready usb:v04A9p3299* ID_MODEL_FROM_DATABASE=EOS M3 usb:v04A9p329A* ID_MODEL_FROM_DATABASE=PowerShot SX60 HS usb:v04A9p329B* ID_MODEL_FROM_DATABASE=PowerShot SX520 HS usb:v04A9p329C* ID_MODEL_FROM_DATABASE=PowerShot SX400 IS usb:v04A9p329F* ID_MODEL_FROM_DATABASE=PowerShot SX530 HS usb:v04A9p32A6* ID_MODEL_FROM_DATABASE=PowerShot SX710 HS usb:v04A9p32AA* ID_MODEL_FROM_DATABASE=Powershot ELPH 160 / IXUS 160 usb:v04A9p32AC* ID_MODEL_FROM_DATABASE=PowerShot ELPH 170 IS / IXUS 170 usb:v04AA* ID_VENDOR_FROM_DATABASE=DaeWoo Telecom, Ltd usb:v04AB* ID_VENDOR_FROM_DATABASE=Chromatic Research usb:v04AC* ID_VENDOR_FROM_DATABASE=Micro Audiometrics Corp. usb:v04AD* ID_VENDOR_FROM_DATABASE=Dooin Electronics usb:v04ADp2501* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v04AF* ID_VENDOR_FROM_DATABASE=Winnov L.P. usb:v04B0* ID_VENDOR_FROM_DATABASE=Nikon Corp. usb:v04B0p0102* ID_MODEL_FROM_DATABASE=Coolpix 990 usb:v04B0p0103* ID_MODEL_FROM_DATABASE=Coolpix 880 usb:v04B0p0104* ID_MODEL_FROM_DATABASE=Coolpix 995 usb:v04B0p0106* ID_MODEL_FROM_DATABASE=Coolpix 775 usb:v04B0p0107* ID_MODEL_FROM_DATABASE=Coolpix 5000 usb:v04B0p0108* ID_MODEL_FROM_DATABASE=Coolpix 2500 usb:v04B0p0109* ID_MODEL_FROM_DATABASE=Coolpix 2500 (ptp) usb:v04B0p010A* ID_MODEL_FROM_DATABASE=Coolpix 4500 usb:v04B0p010B* ID_MODEL_FROM_DATABASE=Coolpix 4500 (ptp) usb:v04B0p010D* ID_MODEL_FROM_DATABASE=Coolpix 5700 (ptp) usb:v04B0p010E* ID_MODEL_FROM_DATABASE=Coolpix 4300 (storage) usb:v04B0p010F* ID_MODEL_FROM_DATABASE=Coolpix 4300 (ptp) usb:v04B0p0110* ID_MODEL_FROM_DATABASE=Coolpix 3500 (Sierra Mode) usb:v04B0p0111* ID_MODEL_FROM_DATABASE=Coolpix 3500 (ptp) usb:v04B0p0112* ID_MODEL_FROM_DATABASE=Coolpix 885 (ptp) usb:v04B0p0113* ID_MODEL_FROM_DATABASE=Coolpix 5000 (ptp) usb:v04B0p0114* ID_MODEL_FROM_DATABASE=Coolpix 3100 (storage) usb:v04B0p0115* ID_MODEL_FROM_DATABASE=Coolpix 3100 (ptp) usb:v04B0p0117* ID_MODEL_FROM_DATABASE=Coolpix 2100 (ptp) usb:v04B0p0119* ID_MODEL_FROM_DATABASE=Coolpix 5400 (ptp) usb:v04B0p011D* ID_MODEL_FROM_DATABASE=Coolpix 3700 (ptp) usb:v04B0p0121* ID_MODEL_FROM_DATABASE=Coolpix 3200 (ptp) usb:v04B0p0122* ID_MODEL_FROM_DATABASE=Coolpix 2200 (ptp) usb:v04B0p0124* ID_MODEL_FROM_DATABASE=Coolpix 8400 (mass storage mode) usb:v04B0p0125* ID_MODEL_FROM_DATABASE=Coolpix 8400 (ptp) usb:v04B0p0126* ID_MODEL_FROM_DATABASE=Coolpix 8800 usb:v04B0p0129* ID_MODEL_FROM_DATABASE=Coolpix 4800 (ptp) usb:v04B0p012C* ID_MODEL_FROM_DATABASE=Coolpix 4100 (storage) usb:v04B0p012D* ID_MODEL_FROM_DATABASE=Coolpix 4100 (ptp) usb:v04B0p012E* ID_MODEL_FROM_DATABASE=Coolpix 5600 (ptp) usb:v04B0p0130* ID_MODEL_FROM_DATABASE=Coolpix 4600 (ptp) usb:v04B0p0135* ID_MODEL_FROM_DATABASE=Coolpix 5900 (ptp) usb:v04B0p0136* ID_MODEL_FROM_DATABASE=Coolpix 7900 (storage) usb:v04B0p0137* ID_MODEL_FROM_DATABASE=Coolpix 7900 (ptp) usb:v04B0p013A* ID_MODEL_FROM_DATABASE=Coolpix 100 (storage) usb:v04B0p013B* ID_MODEL_FROM_DATABASE=Coolpix 100 (ptp) usb:v04B0p0141* ID_MODEL_FROM_DATABASE=Coolpix P2 (storage) usb:v04B0p0142* ID_MODEL_FROM_DATABASE=Coolpix P2 (ptp) usb:v04B0p0163* ID_MODEL_FROM_DATABASE=Coolpix P5100 (ptp) usb:v04B0p0169* ID_MODEL_FROM_DATABASE=Coolpix P50 (ptp) usb:v04B0p0202* ID_MODEL_FROM_DATABASE=Coolpix SQ (ptp) usb:v04B0p0203* ID_MODEL_FROM_DATABASE=Coolpix 4200 (mass storage mode) usb:v04B0p0204* ID_MODEL_FROM_DATABASE=Coolpix 4200 (ptp) usb:v04B0p0205* ID_MODEL_FROM_DATABASE=Coolpix 5200 (storage) usb:v04B0p0206* ID_MODEL_FROM_DATABASE=Coolpix 5200 (ptp) usb:v04B0p0301* ID_MODEL_FROM_DATABASE=Coolpix 2000 (storage) usb:v04B0p0302* ID_MODEL_FROM_DATABASE=Coolpix 2000 (ptp) usb:v04B0p0317* ID_MODEL_FROM_DATABASE=Coolpix L20 (ptp) usb:v04B0p0402* ID_MODEL_FROM_DATABASE=DSC D100 (ptp) usb:v04B0p0403* ID_MODEL_FROM_DATABASE=D2H (mass storage mode) usb:v04B0p0404* ID_MODEL_FROM_DATABASE=D2H SLR (ptp) usb:v04B0p0405* ID_MODEL_FROM_DATABASE=D70 (mass storage mode) usb:v04B0p0406* ID_MODEL_FROM_DATABASE=DSC D70 (ptp) usb:v04B0p0408* ID_MODEL_FROM_DATABASE=D2X SLR (ptp) usb:v04B0p0409* ID_MODEL_FROM_DATABASE=D50 digital camera usb:v04B0p040A* ID_MODEL_FROM_DATABASE=D50 (ptp) usb:v04B0p040C* ID_MODEL_FROM_DATABASE=D2Hs usb:v04B0p040E* ID_MODEL_FROM_DATABASE=DSC D70s (ptp) usb:v04B0p040F* ID_MODEL_FROM_DATABASE=D200 (mass storage mode) usb:v04B0p0410* ID_MODEL_FROM_DATABASE=D200 (ptp) usb:v04B0p0413* ID_MODEL_FROM_DATABASE=D40 (mass storage mode) usb:v04B0p041E* ID_MODEL_FROM_DATABASE=D60 digital camera (mass storage mode) usb:v04B0p0422* ID_MODEL_FROM_DATABASE=D700 (ptp) usb:v04B0p0423* ID_MODEL_FROM_DATABASE=D5000 usb:v04B0p0424* ID_MODEL_FROM_DATABASE=D3000 usb:v04B0p0425* ID_MODEL_FROM_DATABASE=D300S usb:v04B0p0428* ID_MODEL_FROM_DATABASE=D7000 usb:v04B0p0429* ID_MODEL_FROM_DATABASE=D5100 usb:v04B0p042A* ID_MODEL_FROM_DATABASE=D800 (ptp) usb:v04B0p0F03* ID_MODEL_FROM_DATABASE=PD-10 Wireless Printer Adapter usb:v04B0p4000* ID_MODEL_FROM_DATABASE=Coolscan LS 40 ED usb:v04B0p4001* ID_MODEL_FROM_DATABASE=LS 50 ED/Coolscan V ED usb:v04B0p4002* ID_MODEL_FROM_DATABASE=Super Coolscan LS-5000 ED usb:v04B1* ID_VENDOR_FROM_DATABASE=Pan International usb:v04B3* ID_VENDOR_FROM_DATABASE=IBM Corp. usb:v04B3p3003* ID_MODEL_FROM_DATABASE=Rapid Access III Keyboard usb:v04B3p3004* ID_MODEL_FROM_DATABASE=Media Access Pro Keyboard usb:v04B3p300A* ID_MODEL_FROM_DATABASE=Rapid Access IIIe Keyboard usb:v04B3p3016* ID_MODEL_FROM_DATABASE=UltraNav Keyboard Hub usb:v04B3p3018* ID_MODEL_FROM_DATABASE=UltraNav Keyboard usb:v04B3p301A* ID_MODEL_FROM_DATABASE=2-port low-power hub usb:v04B3p301B* ID_MODEL_FROM_DATABASE=SK-8815 Keyboard usb:v04B3p301C* ID_MODEL_FROM_DATABASE=Enhanced Performance Keyboard usb:v04B3p3020* ID_MODEL_FROM_DATABASE=Enhanced Performance Keyboard usb:v04B3p3025* ID_MODEL_FROM_DATABASE=NetVista Full Width Keyboard usb:v04B3p3100* ID_MODEL_FROM_DATABASE=NetVista Mouse usb:v04B3p3103* ID_MODEL_FROM_DATABASE=ScrollPoint Pro Mouse usb:v04B3p3104* ID_MODEL_FROM_DATABASE=ScrollPoint Wireless Mouse usb:v04B3p3105* ID_MODEL_FROM_DATABASE=ScrollPoint Optical (HID) usb:v04B3p3107* ID_MODEL_FROM_DATABASE=ThinkPad 800dpi Optical Travel Mouse usb:v04B3p3108* ID_MODEL_FROM_DATABASE=800dpi Optical Mouse w/ Scroll Point usb:v04B3p3109* ID_MODEL_FROM_DATABASE=Optical ScrollPoint Pro Mouse usb:v04B3p310B* ID_MODEL_FROM_DATABASE=Red Wheel Mouse usb:v04B3p310C* ID_MODEL_FROM_DATABASE=Wheel Mouse usb:v04B3p4427* ID_MODEL_FROM_DATABASE=Portable CD ROM usb:v04B3p4482* ID_MODEL_FROM_DATABASE=Serial Converter usb:v04B3p4484* ID_MODEL_FROM_DATABASE=SMSC USB20H04 3-Port Hub [ThinkPad X4 UltraBase, Wistron S Note-3 Media Slice] usb:v04B3p4485* ID_MODEL_FROM_DATABASE=ThinkPad Dock Hub usb:v04B3p4524* ID_MODEL_FROM_DATABASE=40 Character Vacuum Fluorescent Display usb:v04B3p4525* ID_MODEL_FROM_DATABASE=Double sided CRT usb:v04B3p4535* ID_MODEL_FROM_DATABASE=4610 Suremark Printer usb:v04B3p4550* ID_MODEL_FROM_DATABASE=NVRAM (128 KB) usb:v04B3p4554* ID_MODEL_FROM_DATABASE=Cash Drawer usb:v04B3p4580* ID_MODEL_FROM_DATABASE=Hub w/ NVRAM usb:v04B3p4581* ID_MODEL_FROM_DATABASE=4800-2xx Hub w/ Cash Drawer usb:v04B3p4604* ID_MODEL_FROM_DATABASE=Keyboard w/ Card Reader usb:v04B3p4671* ID_MODEL_FROM_DATABASE=4820 LCD w/ MSR/KB usb:v04B4* ID_VENDOR_FROM_DATABASE=Cypress Semiconductor Corp. usb:v04B4p0001* ID_MODEL_FROM_DATABASE=Mouse usb:v04B4p0002* ID_MODEL_FROM_DATABASE=CY7C63x0x Thermometer usb:v04B4p0033* ID_MODEL_FROM_DATABASE=Mouse usb:v04B4p0060* ID_MODEL_FROM_DATABASE=Wireless optical mouse usb:v04B4p0100* ID_MODEL_FROM_DATABASE=Cino FuzzyScan F760-B usb:v04B4p0101* ID_MODEL_FROM_DATABASE=Keyboard/Hub usb:v04B4p0102* ID_MODEL_FROM_DATABASE=Keyboard with APM usb:v04B4p0130* ID_MODEL_FROM_DATABASE=MyIRC Remote Receiver usb:v04B4p0306* ID_MODEL_FROM_DATABASE=Telephone Receiver usb:v04B4p0407* ID_MODEL_FROM_DATABASE=Optical Skype Mouse usb:v04B4p0BAD* ID_MODEL_FROM_DATABASE=MetaGeek Wi-Spy usb:v04B4p1002* ID_MODEL_FROM_DATABASE=CY7C63001 R100 FM Radio usb:v04B4p1006* ID_MODEL_FROM_DATABASE=Human Interface Device usb:v04B4p2050* ID_MODEL_FROM_DATABASE=hub usb:v04B4p2830* ID_MODEL_FROM_DATABASE=Opera1 DVB-S (cold state) usb:v04B4p3813* ID_MODEL_FROM_DATABASE=NANO BIOS Programmer usb:v04B4p4235* ID_MODEL_FROM_DATABASE=Monitor 02 Driver usb:v04B4p4381* ID_MODEL_FROM_DATABASE=SCAPS USC-1 Scanner Controller usb:v04B4p4611* ID_MODEL_FROM_DATABASE=Storage Adapter FX2 (CY) usb:v04B4p4616* ID_MODEL_FROM_DATABASE=Flash Disk (TPP) usb:v04B4p5201* ID_MODEL_FROM_DATABASE=Combi Keyboard-Hub (Hub) usb:v04B4p5202* ID_MODEL_FROM_DATABASE=Combi Keyboard-Hub (Keyboard) usb:v04B4p5500* ID_MODEL_FROM_DATABASE=HID->COM RS232 Adapter usb:v04B4p5A9B* ID_MODEL_FROM_DATABASE=Dacal CD/DVD Library D-101/DC-300/DC-016RW usb:v04B4p6370* ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 usb:v04B4p6560* ID_MODEL_FROM_DATABASE=CY7C65640 USB-2.0 "TetraHub" usb:v04B4p6830* ID_MODEL_FROM_DATABASE=CY7C68300A EZ-USB AT2 USB 2.0 to ATA/ATAPI usb:v04B4p6831* ID_MODEL_FROM_DATABASE=Storage Adapter ISD-300LP (CY) usb:v04B4p7417* ID_MODEL_FROM_DATABASE=Wireless PC Lock/Ultra Mouse usb:v04B4p8329* ID_MODEL_FROM_DATABASE=USB To keyboard/Mouse Converter usb:v04B4p8613* ID_MODEL_FROM_DATABASE=CY7C68013 EZ-USB FX2 USB 2.0 Development Kit usb:v04B4p8614* ID_MODEL_FROM_DATABASE=DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) usb:v04B4p861F* ID_MODEL_FROM_DATABASE=Anysee E30 USB 2.0 DVB-T Receiver usb:v04B4pBCA1* ID_MODEL_FROM_DATABASE=Barcode Reader usb:v04B4pCC04* ID_MODEL_FROM_DATABASE=Centor USB RACIA-ALVAR USB PORT usb:v04B4pCC06* ID_MODEL_FROM_DATABASE=Centor-P RACIA-ALVAR USB PORT usb:v04B4pD5D5* ID_MODEL_FROM_DATABASE=CY7C63x0x Zoltrix Z-Boxer GamePad usb:v04B4pDE61* ID_MODEL_FROM_DATABASE=Barcode Reader usb:v04B4pDE64* ID_MODEL_FROM_DATABASE=Barcode Reader usb:v04B4pF000* ID_MODEL_FROM_DATABASE=CY30700 Licorice evaluation board usb:v04B4pF111* ID_MODEL_FROM_DATABASE=CY8CKIT-002 PSoC MiniProg3 Rev A Program and debug kit usb:v04B4pF115* ID_MODEL_FROM_DATABASE=PSoC FirstTouch Programmer usb:v04B4pFD13* ID_MODEL_FROM_DATABASE=Programmable power socket usb:v04B5* ID_VENDOR_FROM_DATABASE=ROHM LSI Systems USA, LLC usb:v04B5p3064* ID_MODEL_FROM_DATABASE=Hantek DSO-3064 usb:v04B6* ID_VENDOR_FROM_DATABASE=Hint Corp. usb:v04B7* ID_VENDOR_FROM_DATABASE=Compal Electronics, Inc. usb:v04B8* ID_VENDOR_FROM_DATABASE=Seiko Epson Corp. usb:v04B8p0001* ID_MODEL_FROM_DATABASE=Stylus Color 740 / Photo 750 usb:v04B8p0002* ID_MODEL_FROM_DATABASE=ISD Smart Cable for Mac usb:v04B8p0003* ID_MODEL_FROM_DATABASE=ISD Smart Cable usb:v04B8p0004* ID_MODEL_FROM_DATABASE=Printer usb:v04B8p0005* ID_MODEL_FROM_DATABASE=Printer usb:v04B8p0006* ID_MODEL_FROM_DATABASE=Printer usb:v04B8p0007* ID_MODEL_FROM_DATABASE=Printer usb:v04B8p0015* ID_MODEL_FROM_DATABASE=Stylus Photo R3000 usb:v04B8p0101* ID_MODEL_FROM_DATABASE=GT-7000U [Perfection 636] usb:v04B8p0102* ID_MODEL_FROM_DATABASE=GT-2200 usb:v04B8p0103* ID_MODEL_FROM_DATABASE=GT-6600U [Perfection 610] usb:v04B8p0104* ID_MODEL_FROM_DATABASE=GT-7600UF [Perfection 1200U/1200U Photo] usb:v04B8p0105* ID_MODEL_FROM_DATABASE=Stylus Scan 2000 usb:v04B8p0106* ID_MODEL_FROM_DATABASE=Stylus Scan 2500 usb:v04B8p0107* ID_MODEL_FROM_DATABASE=ES-2000 [Expression 1600U] usb:v04B8p0108* ID_MODEL_FROM_DATABASE=CC-700 usb:v04B8p0109* ID_MODEL_FROM_DATABASE=ES-8500 [Expression 1640 XL] usb:v04B8p010A* ID_MODEL_FROM_DATABASE=GT-8700/GT-8700F [Perfection 1640SU/1640SU PHOTO] usb:v04B8p010B* ID_MODEL_FROM_DATABASE=GT-7700U [Perfection 1240U] usb:v04B8p010C* ID_MODEL_FROM_DATABASE=GT-6700U [Perfection 640] usb:v04B8p010D* ID_MODEL_FROM_DATABASE=CC-500L usb:v04B8p010E* ID_MODEL_FROM_DATABASE=ES-2200 [Perfection 1680] usb:v04B8p010F* ID_MODEL_FROM_DATABASE=GT-7200U [Perfection 1250/1250 PHOTO] usb:v04B8p0110* ID_MODEL_FROM_DATABASE=GT-8200U/GT-8200UF [Perfection 1650/1650 PHOTO] usb:v04B8p0112* ID_MODEL_FROM_DATABASE=GT-9700F [Perfection 2450 PHOTO] usb:v04B8p0114* ID_MODEL_FROM_DATABASE=Perfection 660 usb:v04B8p0116* ID_MODEL_FROM_DATABASE=GT-9400UF [Perfection 3170] usb:v04B8p0118* ID_MODEL_FROM_DATABASE=GT-F600 [Perfection 4180] usb:v04B8p0119* ID_MODEL_FROM_DATABASE=GT-X750 [Perfection 4490 Photo] usb:v04B8p011A* ID_MODEL_FROM_DATABASE=CC-550L [1000 ICS] usb:v04B8p011B* ID_MODEL_FROM_DATABASE=GT-9300UF [Perfection 2400 PHOTO] usb:v04B8p011C* ID_MODEL_FROM_DATABASE=GT-9800F [Perfection 3200] usb:v04B8p011D* ID_MODEL_FROM_DATABASE=GT-7300U [Perfection 1260/1260 PHOTO] usb:v04B8p011E* ID_MODEL_FROM_DATABASE=GT-8300UF [Perfection 1660 PHOTO] usb:v04B8p011F* ID_MODEL_FROM_DATABASE=GT-8400UF [Perfection 1670/1670 PHOTO] usb:v04B8p0120* ID_MODEL_FROM_DATABASE=GT-7400U [Perfection 1270] usb:v04B8p0121* ID_MODEL_FROM_DATABASE=GT-F500/GT-F550 [Perfection 2480/2580 PHOTO] usb:v04B8p0122* ID_MODEL_FROM_DATABASE=GT-F520/GT-F570 [Perfection 3590 PHOTO] usb:v04B8p0126* ID_MODEL_FROM_DATABASE=ES-7000H [GT-15000] usb:v04B8p0128* ID_MODEL_FROM_DATABASE=GT-X700 [Perfection 4870] usb:v04B8p0129* ID_MODEL_FROM_DATABASE=ES-10000G [Expression 10000XL] usb:v04B8p012A* ID_MODEL_FROM_DATABASE=GT-X800 [Perfection 4990 PHOTO] usb:v04B8p012B* ID_MODEL_FROM_DATABASE=ES-H300 [GT-2500] usb:v04B8p012C* ID_MODEL_FROM_DATABASE=GT-X900 [Perfection V700/V750 Photo] usb:v04B8p012D* ID_MODEL_FROM_DATABASE=GT-F650 [GT-S600/Perfection V10/V100] usb:v04B8p012E* ID_MODEL_FROM_DATABASE=GT-F670 [Perfection V200 Photo] usb:v04B8p012F* ID_MODEL_FROM_DATABASE=GT-F700 [Perfection V350] usb:v04B8p0130* ID_MODEL_FROM_DATABASE=GT-X770 [Perfection V500] usb:v04B8p0131* ID_MODEL_FROM_DATABASE=GT-F720 [GT-S620/Perfection V30/V300 Photo] usb:v04B8p0133* ID_MODEL_FROM_DATABASE=GT-1500 [GT-D1000] usb:v04B8p0135* ID_MODEL_FROM_DATABASE=GT-X970 usb:v04B8p0136* ID_MODEL_FROM_DATABASE=ES-D400 [GT-S80] usb:v04B8p0137* ID_MODEL_FROM_DATABASE=ES-D200 [GT-S50] usb:v04B8p0138* ID_MODEL_FROM_DATABASE=ES-H7200 [GT-20000] usb:v04B8p013A* ID_MODEL_FROM_DATABASE=GT-X820 [Perfection V600 Photo] usb:v04B8p0142* ID_MODEL_FROM_DATABASE=GT-F730 [GT-S630/Perfection V33/V330 Photo] usb:v04B8p0143* ID_MODEL_FROM_DATABASE=GT-S55 usb:v04B8p0144* ID_MODEL_FROM_DATABASE=GT-S85 usb:v04B8p0202* ID_MODEL_FROM_DATABASE=Receipt Printer M129C/TM-T70 usb:v04B8p0401* ID_MODEL_FROM_DATABASE=CP 800 Digital Camera usb:v04B8p0402* ID_MODEL_FROM_DATABASE=PhotoPC 850z usb:v04B8p0403* ID_MODEL_FROM_DATABASE=PhotoPC 3000z usb:v04B8p0509* ID_MODEL_FROM_DATABASE=JVC PIX-MC10 usb:v04B8p0601* ID_MODEL_FROM_DATABASE=Stylus Photo 875DC Card Reader usb:v04B8p0602* ID_MODEL_FROM_DATABASE=Stylus Photo 895 Card Reader usb:v04B8p0801* ID_MODEL_FROM_DATABASE=CC-600PX [Stylus CX5200/CX5400/CX6600] usb:v04B8p0802* ID_MODEL_FROM_DATABASE=CC-570L [Stylus CX3100/CX3200] usb:v04B8p0803* ID_MODEL_FROM_DATABASE=Printer (Composite Device) usb:v04B8p0804* ID_MODEL_FROM_DATABASE=Storage Device usb:v04B8p0805* ID_MODEL_FROM_DATABASE=Stylus CX6300/CX6400 usb:v04B8p0806* ID_MODEL_FROM_DATABASE=PM-A850 [Stylus Photo RX600/610] usb:v04B8p0807* ID_MODEL_FROM_DATABASE=Stylus Photo RX500/510 usb:v04B8p0808* ID_MODEL_FROM_DATABASE=Stylus CX5200/CX5300/CX5400 usb:v04B8p0809* ID_MODEL_FROM_DATABASE=Storage Device usb:v04B8p080A* ID_MODEL_FROM_DATABASE=F-3200 usb:v04B8p080C* ID_MODEL_FROM_DATABASE=ME100 [Stylus CX1500] usb:v04B8p080D* ID_MODEL_FROM_DATABASE=Stylus CX4500/4600 usb:v04B8p080E* ID_MODEL_FROM_DATABASE=PX-A550 [CX-3500/3600/3650 MFP] usb:v04B8p080F* ID_MODEL_FROM_DATABASE=Stylus Photo RX420/RX425/RX430 usb:v04B8p0810* ID_MODEL_FROM_DATABASE=PM-A900 [Stylus Photo RX700] usb:v04B8p0811* ID_MODEL_FROM_DATABASE=PM-A870 [Stylus Photo RX620/RX630] usb:v04B8p0812* ID_MODEL_FROM_DATABASE=MFP Composite Device usb:v04B8p0813* ID_MODEL_FROM_DATABASE=Stylus CX6500/6600 usb:v04B8p0814* ID_MODEL_FROM_DATABASE=PM-A700 usb:v04B8p0815* ID_MODEL_FROM_DATABASE=LP-A500 [AcuLaser CX1] usb:v04B8p0816* ID_MODEL_FROM_DATABASE=Printer (Composite Device) usb:v04B8p0817* ID_MODEL_FROM_DATABASE=LP-M5500/LP-M5500F usb:v04B8p0818* ID_MODEL_FROM_DATABASE=Stylus CX3700/CX3800/DX3800 usb:v04B8p0819* ID_MODEL_FROM_DATABASE=PX-A650 [Stylus CX4700/CX4800/DX4800/DX4850] usb:v04B8p081A* ID_MODEL_FROM_DATABASE=PM-A750 [Stylus Photo RX520/RX530] usb:v04B8p081B* ID_MODEL_FROM_DATABASE=MFP Composite Device usb:v04B8p081C* ID_MODEL_FROM_DATABASE=PM-A890 [Stylus Photo RX640/RX650] usb:v04B8p081D* ID_MODEL_FROM_DATABASE=PM-A950 usb:v04B8p081E* ID_MODEL_FROM_DATABASE=MFP Composite Device usb:v04B8p081F* ID_MODEL_FROM_DATABASE=Stylus CX7700/7800 usb:v04B8p0820* ID_MODEL_FROM_DATABASE=Stylus CX4100/CX4200/DX4200 usb:v04B8p0821* ID_MODEL_FROM_DATABASE=Stylus CX5700F/CX5800F usb:v04B8p0822* ID_MODEL_FROM_DATABASE=Storage Device usb:v04B8p0823* ID_MODEL_FROM_DATABASE=MFP Composite Device usb:v04B8p0824* ID_MODEL_FROM_DATABASE=Storage Device usb:v04B8p0825* ID_MODEL_FROM_DATABASE=MFP Composite Device usb:v04B8p0826* ID_MODEL_FROM_DATABASE=Storage Device usb:v04B8p0827* ID_MODEL_FROM_DATABASE=PM-A820 [Stylus Photo RX560/RX580/RX585/RX590] usb:v04B8p0828* ID_MODEL_FROM_DATABASE=PM-A970 usb:v04B8p0829* ID_MODEL_FROM_DATABASE=PM-T990 usb:v04B8p082A* ID_MODEL_FROM_DATABASE=PM-A920 usb:v04B8p082B* ID_MODEL_FROM_DATABASE=Stylus CX5900/CX5000/DX5000/DX5050 usb:v04B8p082C* ID_MODEL_FROM_DATABASE=Storage Device usb:v04B8p082D* ID_MODEL_FROM_DATABASE=Storage Device usb:v04B8p082E* ID_MODEL_FROM_DATABASE=PX-A720 [Stylus CX5900/CX6000/DX6000] usb:v04B8p082F* ID_MODEL_FROM_DATABASE=PX-A620 [Stylus CX3900/DX4000/DX4050] usb:v04B8p0830* ID_MODEL_FROM_DATABASE=ME 200 [Stylus CX2800/CX2900] usb:v04B8p0831* ID_MODEL_FROM_DATABASE=Stylus CX6900F/CX7000F/DX7000F usb:v04B8p0832* ID_MODEL_FROM_DATABASE=MFP Composite Device usb:v04B8p0833* ID_MODEL_FROM_DATABASE=LP-M5600 usb:v04B8p0834* ID_MODEL_FROM_DATABASE=LP-M6000 usb:v04B8p0835* ID_MODEL_FROM_DATABASE=AcuLaser CX21 usb:v04B8p0836* ID_MODEL_FROM_DATABASE=PM-T960 usb:v04B8p0837* ID_MODEL_FROM_DATABASE=PM-A940 [Stylus Photo RX680/RX685/RX690] usb:v04B8p0838* ID_MODEL_FROM_DATABASE=PX-A640 [CX7300/CX7400/DX7400] usb:v04B8p0839* ID_MODEL_FROM_DATABASE=PX-A740 [CX8300/CX8400/DX8400] usb:v04B8p083A* ID_MODEL_FROM_DATABASE=PX-FA700 [CX9300F/CX9400Fax/DX9400F] usb:v04B8p083B* ID_MODEL_FROM_DATABASE=MFP Composite Device usb:v04B8p083C* ID_MODEL_FROM_DATABASE=PM-A840S [Stylus Photo RX595/RX610] usb:v04B8p083D* ID_MODEL_FROM_DATABASE=MFP Composite Device usb:v04B8p083E* ID_MODEL_FROM_DATABASE=MFP Composite Device usb:v04B8p083F* ID_MODEL_FROM_DATABASE=Stylus CX4300/CX4400/CX5500/CX5600/DX4400/DX4450 usb:v04B8p0841* ID_MODEL_FROM_DATABASE=PX-401A [ME 300/Stylus NX100] usb:v04B8p0843* ID_MODEL_FROM_DATABASE=LP-M5000 usb:v04B8p0844* ID_MODEL_FROM_DATABASE=EP-901A/EP-901F [Artisan 800/Stylus Photo PX800FW] usb:v04B8p0846* ID_MODEL_FROM_DATABASE=EP-801A [Artisan 700/Stylus Photo PX700W/TX700W] usb:v04B8p0847* ID_MODEL_FROM_DATABASE=PX-601F [ME Office 700FW/Stylus Office BX600FW/TX600FW] usb:v04B8p0848* ID_MODEL_FROM_DATABASE=ME Office 600F/Stylus Office BX300F/TX300F usb:v04B8p0849* ID_MODEL_FROM_DATABASE=Stylus SX205 usb:v04B8p084A* ID_MODEL_FROM_DATABASE=PX-501A [Stylus NX400] usb:v04B8p084D* ID_MODEL_FROM_DATABASE=PX-402A [Stylus SX115/Stylus NX110 Series] usb:v04B8p084F* ID_MODEL_FROM_DATABASE=ME OFFICE 510 usb:v04B8p0850* ID_MODEL_FROM_DATABASE=EP-702A [Stylus Photo PX650/TX650 Series] usb:v04B8p0851* ID_MODEL_FROM_DATABASE=Stylus SX410 usb:v04B8p0852* ID_MODEL_FROM_DATABASE=EP-802A [Artisan 710 Series/Stylus Photo PX710W/TX720W Series] usb:v04B8p0853* ID_MODEL_FROM_DATABASE=EP-902A [Artisan 810 Series/Stylus Photo PX810FW Series] usb:v04B8p0854* ID_MODEL_FROM_DATABASE=ME OFFICE 650FN Series/Stylus Office BX310FN/TX520FN Series usb:v04B8p0855* ID_MODEL_FROM_DATABASE=PX-602F [Stylus Office BX610FW/TX620FW Series] usb:v04B8p0856* ID_MODEL_FROM_DATABASE=PX-502A [Stylus SX515W] usb:v04B8p085C* ID_MODEL_FROM_DATABASE=ME 320/330 Series [Stylus SX125] usb:v04B8p085D* ID_MODEL_FROM_DATABASE=PX-603F [ME OFFICE 960FWD Series/Stylus Office BX625FWD/TX620FWD Series] usb:v04B8p085E* ID_MODEL_FROM_DATABASE=PX-503A [ME OFFICE 900WD Series/Stylus Office BX525WD] usb:v04B8p085F* ID_MODEL_FROM_DATABASE=Stylus Office BX320FW/TX525FW Series usb:v04B8p0860* ID_MODEL_FROM_DATABASE=EP-903A/EP-903F [Artisan 835/Stylus Photo PX820FWD Series] usb:v04B8p0861* ID_MODEL_FROM_DATABASE=EP-803A/EP-803AW [Artisan 725/Stylus Photo PX720WD/TX720WD Series] usb:v04B8p0862* ID_MODEL_FROM_DATABASE=EP-703A [Stylus Photo PX660 Series] usb:v04B8p0863* ID_MODEL_FROM_DATABASE=ME OFFICE 620F Series/Stylus Office BX305F/BX305FW/TX320F usb:v04B8p0864* ID_MODEL_FROM_DATABASE=ME OFFICE 560W Series usb:v04B8p0865* ID_MODEL_FROM_DATABASE=ME OFFICE 520 Series usb:v04B8p0866* ID_MODEL_FROM_DATABASE=AcuLaser MX20DN/MX20DNF/MX21DNF usb:v04B8p0869* ID_MODEL_FROM_DATABASE=PX-1600F usb:v04B8p086A* ID_MODEL_FROM_DATABASE=PX-673F [Stylus Office BX925FWD] usb:v04B8p0870* ID_MODEL_FROM_DATABASE=Stylus Office BX305FW Plus usb:v04B8p0871* ID_MODEL_FROM_DATABASE=K200 Series usb:v04B8p0872* ID_MODEL_FROM_DATABASE=K300 Series usb:v04B8p0873* ID_MODEL_FROM_DATABASE=L200 Series usb:v04B8p0878* ID_MODEL_FROM_DATABASE=EP-704A usb:v04B8p0879* ID_MODEL_FROM_DATABASE=EP-904A/EP-904F [Artisan 837/Stylus Photo PX830FWD Series] usb:v04B8p087B* ID_MODEL_FROM_DATABASE=EP-804A/EP-804AR/EP-804AW [Stylus Photo PX730WD/Artisan 730 Series] usb:v04B8p087C* ID_MODEL_FROM_DATABASE=PX-1700F usb:v04B8p087D* ID_MODEL_FROM_DATABASE=PX-B750F/WP-4525 Series usb:v04B8p087F* ID_MODEL_FROM_DATABASE=PX-403A usb:v04B8p0880* ID_MODEL_FROM_DATABASE=PX-434A [Stylus NX330 Series] usb:v04B8p0881* ID_MODEL_FROM_DATABASE=PX-404A [ME OFFICE 535] usb:v04B8p0883* ID_MODEL_FROM_DATABASE=ME 340 Series/Stylus NX130 Series usb:v04B8p0884* ID_MODEL_FROM_DATABASE=Stylus NX430W Series usb:v04B8p0885* ID_MODEL_FROM_DATABASE=Stylus NX230/SX235W Series usb:v04B8p088F* ID_MODEL_FROM_DATABASE=Stylus Office BX635FWD usb:v04B8p0890* ID_MODEL_FROM_DATABASE=ME OFFICE 940FW Series/Stylus Office BX630FW Series usb:v04B8p0891* ID_MODEL_FROM_DATABASE=Stylus Office BX535WD usb:v04B8p0892* ID_MODEL_FROM_DATABASE=Stylus Office BX935FWD usb:v04B8p0893* ID_MODEL_FROM_DATABASE=EP-774A usb:v04B9* ID_VENDOR_FROM_DATABASE=Rainbow Technologies, Inc. usb:v04B9p0300* ID_MODEL_FROM_DATABASE=SafeNet USB SuperPro/UltraPro usb:v04B9p1000* ID_MODEL_FROM_DATABASE=iKey 1000 Token usb:v04B9p1001* ID_MODEL_FROM_DATABASE=iKey 1200 Token usb:v04B9p1002* ID_MODEL_FROM_DATABASE=iKey Token usb:v04B9p1003* ID_MODEL_FROM_DATABASE=iKey Token usb:v04B9p1004* ID_MODEL_FROM_DATABASE=iKey Token usb:v04B9p1005* ID_MODEL_FROM_DATABASE=iKey Token usb:v04B9p1006* ID_MODEL_FROM_DATABASE=iKey Token usb:v04B9p1200* ID_MODEL_FROM_DATABASE=iKey 2000 Token usb:v04B9p1201* ID_MODEL_FROM_DATABASE=iKey Token usb:v04B9p1202* ID_MODEL_FROM_DATABASE=iKey 2032 Token usb:v04B9p1203* ID_MODEL_FROM_DATABASE=iKey Token usb:v04B9p1204* ID_MODEL_FROM_DATABASE=iKey Token usb:v04B9p1205* ID_MODEL_FROM_DATABASE=iKey Token usb:v04B9p1206* ID_MODEL_FROM_DATABASE=iKey 4000 Token usb:v04B9p1300* ID_MODEL_FROM_DATABASE=iKey 3000 Token usb:v04B9p1301* ID_MODEL_FROM_DATABASE=iKey 3000 usb:v04B9p1302* ID_MODEL_FROM_DATABASE=iKey Token usb:v04B9p1303* ID_MODEL_FROM_DATABASE=iKey Token usb:v04B9p1304* ID_MODEL_FROM_DATABASE=iKey Token usb:v04B9p1305* ID_MODEL_FROM_DATABASE=iKey Token usb:v04B9p1306* ID_MODEL_FROM_DATABASE=iKey Token usb:v04BA* ID_VENDOR_FROM_DATABASE=Toucan Systems, Ltd usb:v04BB* ID_VENDOR_FROM_DATABASE=I-O Data Device, Inc. usb:v04BBp0101* ID_MODEL_FROM_DATABASE=USB2-IDE/ATAPI Bridge Adapter usb:v04BBp0201* ID_MODEL_FROM_DATABASE=USB2-IDE/ATAPI Bridge Adapter usb:v04BBp0204* ID_MODEL_FROM_DATABASE=DVD Multi-plus unit iU-CD2 usb:v04BBp0206* ID_MODEL_FROM_DATABASE=DVD Multi-plus unit DVR-UEH8 usb:v04BBp0301* ID_MODEL_FROM_DATABASE=Storage Device usb:v04BBp0314* ID_MODEL_FROM_DATABASE=USB-SSMRW SD-card usb:v04BBp0319* ID_MODEL_FROM_DATABASE=USB2-IDE/ATAPI Bridge Adapter usb:v04BBp031A* ID_MODEL_FROM_DATABASE=USB2-IDE/ATAPI Bridge Adapter usb:v04BBp031B* ID_MODEL_FROM_DATABASE=USB2-IDE/ATAPI Bridge Adapter usb:v04BBp031E* ID_MODEL_FROM_DATABASE=USB-SDRW SD-card usb:v04BBp0502* ID_MODEL_FROM_DATABASE=Nogatech Live! (BT) usb:v04BBp0528* ID_MODEL_FROM_DATABASE=GV-USB Video Capture usb:v04BBp0901* ID_MODEL_FROM_DATABASE=USB ETT usb:v04BBp0904* ID_MODEL_FROM_DATABASE=ET/TX Ethernet [pegasus] usb:v04BBp0913* ID_MODEL_FROM_DATABASE=ET/TX-S Ethernet [pegasus2] usb:v04BBp0919* ID_MODEL_FROM_DATABASE=USB WN-B11 usb:v04BBp0922* ID_MODEL_FROM_DATABASE=IOData AirPort WN-B11/USBS 802.11b usb:v04BBp0930* ID_MODEL_FROM_DATABASE=ETG-US2 usb:v04BBp0937* ID_MODEL_FROM_DATABASE=WN-WAG/USL Wireless LAN Adapter usb:v04BBp0938* ID_MODEL_FROM_DATABASE=WN-G54/USL Wireless LAN Adapter usb:v04BBp093B* ID_MODEL_FROM_DATABASE=WN-GDN/USB usb:v04BBp093F* ID_MODEL_FROM_DATABASE=WNGDNUS2 802.11n usb:v04BBp0944* ID_MODEL_FROM_DATABASE=WHG-AGDN/US Wireless LAN Adapter usb:v04BBp0945* ID_MODEL_FROM_DATABASE=WN-GDN/US3 Wireless LAN Adapter usb:v04BBp0947* ID_MODEL_FROM_DATABASE=WN-G150U Wireless LAN Adapter usb:v04BBp0948* ID_MODEL_FROM_DATABASE=WN-G300U Wireless LAN Adapter usb:v04BBp0A03* ID_MODEL_FROM_DATABASE=Serial USB-RSAQ1 usb:v04BBp0A07* ID_MODEL_FROM_DATABASE=USB2-iCN Adapter usb:v04BBp0A08* ID_MODEL_FROM_DATABASE=USB2-iCN Adapter usb:v04BBp0C01* ID_MODEL_FROM_DATABASE=FM-10 Pro Disk usb:v04BD* ID_VENDOR_FROM_DATABASE=Toshiba Electronics Taiwan Corp. usb:v04BE* ID_VENDOR_FROM_DATABASE=Telia Research AB usb:v04BF* ID_VENDOR_FROM_DATABASE=TDK Corp. usb:v04BFp0100* ID_MODEL_FROM_DATABASE=MediaReader CF usb:v04BFp0115* ID_MODEL_FROM_DATABASE=USB-PDC Adapter UPA9664 usb:v04BFp0116* ID_MODEL_FROM_DATABASE=USB-cdmaOne Adapter UCA1464 usb:v04BFp0117* ID_MODEL_FROM_DATABASE=USB-PHS Adapter UHA6400 usb:v04BFp0118* ID_MODEL_FROM_DATABASE=USB-PHS Adapter UPA6400 usb:v04BFp0135* ID_MODEL_FROM_DATABASE=MediaReader Dual usb:v04BFp0202* ID_MODEL_FROM_DATABASE=73S1121F Smart Card Reader- usb:v04BFp0309* ID_MODEL_FROM_DATABASE=Bluetooth USB dongle usb:v04BFp030A* ID_MODEL_FROM_DATABASE=IBM Bluetooth Ultraport Module usb:v04BFp030B* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v04BFp030C* ID_MODEL_FROM_DATABASE=Ultraport Bluetooth Device usb:v04BFp0310* ID_MODEL_FROM_DATABASE=Integrated Bluetooth usb:v04BFp0311* ID_MODEL_FROM_DATABASE=Integrated Bluetooth Device usb:v04BFp0317* ID_MODEL_FROM_DATABASE=Bluetooth UltraPort Module from IBM usb:v04BFp0318* ID_MODEL_FROM_DATABASE=IBM Integrated Bluetooth usb:v04BFp0319* ID_MODEL_FROM_DATABASE=Bluetooth Adapter usb:v04BFp0320* ID_MODEL_FROM_DATABASE=Bluetooth Adapter usb:v04BFp0321* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v04BFp0A28* ID_MODEL_FROM_DATABASE=INDI AV-IN Device usb:v04C1* ID_VENDOR_FROM_DATABASE=U.S. Robotics (3Com) usb:v04C1p0020* ID_MODEL_FROM_DATABASE=56K Voice Pro usb:v04C1p0022* ID_MODEL_FROM_DATABASE=56K Voice Pro usb:v04C1p007E* ID_MODEL_FROM_DATABASE=ISDN TA usb:v04C1p0082* ID_MODEL_FROM_DATABASE=OfficeConnect Analog Modem usb:v04C1p008F* ID_MODEL_FROM_DATABASE=Pro ISDN TA usb:v04C1p0097* ID_MODEL_FROM_DATABASE=OfficeConnect Analog usb:v04C1p009D* ID_MODEL_FROM_DATABASE=HomeConnect Webcam [vicam] usb:v04C1p00A9* ID_MODEL_FROM_DATABASE=ISDN Pro TA-U usb:v04C1p00B9* ID_MODEL_FROM_DATABASE=HomeConnect IDSL Modem usb:v04C1p3021* ID_MODEL_FROM_DATABASE=56k Voice FaxModem Pro usb:v04C2* ID_VENDOR_FROM_DATABASE=Methode Electronics Far East PTE, Ltd usb:v04C3* ID_VENDOR_FROM_DATABASE=Maxi Switch, Inc. usb:v04C3p1102* ID_MODEL_FROM_DATABASE=Mouse usb:v04C3p2102* ID_MODEL_FROM_DATABASE=Mouse usb:v04C4* ID_VENDOR_FROM_DATABASE=Lockheed Martin Energy Research usb:v04C5* ID_VENDOR_FROM_DATABASE=Fujitsu, Ltd usb:v04C5p1029* ID_MODEL_FROM_DATABASE=fi-4010c Scanner usb:v04C5p1033* ID_MODEL_FROM_DATABASE=fi-4110CU usb:v04C5p1041* ID_MODEL_FROM_DATABASE=fi-4120c Scanner usb:v04C5p1042* ID_MODEL_FROM_DATABASE=fi-4220c Scanner usb:v04C5p105B* ID_MODEL_FROM_DATABASE=AH-F401U Air H device usb:v04C5p1084* ID_MODEL_FROM_DATABASE=PalmSecure Sensor V2 usb:v04C5p1096* ID_MODEL_FROM_DATABASE=fi-5110EOX usb:v04C5p1097* ID_MODEL_FROM_DATABASE=fi-5110C usb:v04C5p10AE* ID_MODEL_FROM_DATABASE=fi-4120C2 usb:v04C5p10AF* ID_MODEL_FROM_DATABASE=fi-4220C2 usb:v04C5p10C7* ID_MODEL_FROM_DATABASE=fi-60f scanner usb:v04C5p10E0* ID_MODEL_FROM_DATABASE=fi-5120c Scanner usb:v04C5p10E1* ID_MODEL_FROM_DATABASE=fi-5220C usb:v04C5p10E7* ID_MODEL_FROM_DATABASE=fi-5900C usb:v04C5p10FE* ID_MODEL_FROM_DATABASE=S500 usb:v04C5p1150* ID_MODEL_FROM_DATABASE=fi-6230 usb:v04C5p201D* ID_MODEL_FROM_DATABASE=SATA 3.0 6Gbit/s Adaptor [GROOVY] usb:v04C6* ID_VENDOR_FROM_DATABASE=Toshiba America Electronic Components usb:v04C7* ID_VENDOR_FROM_DATABASE=Micro Macro Technologies usb:v04C8* ID_VENDOR_FROM_DATABASE=Konica Corp. usb:v04C8p0720* ID_MODEL_FROM_DATABASE=Digital Color Camera usb:v04C8p0721* ID_MODEL_FROM_DATABASE=e-miniD Camera usb:v04C8p0722* ID_MODEL_FROM_DATABASE=e-mini usb:v04C8p0723* ID_MODEL_FROM_DATABASE=KD-200Z Camera usb:v04C8p0726* ID_MODEL_FROM_DATABASE=KD-310Z Camera usb:v04C8p0728* ID_MODEL_FROM_DATABASE=Revio C2 Mass Storage Device usb:v04C8p0729* ID_MODEL_FROM_DATABASE=Revio C2 Digital Camera usb:v04C8p072C* ID_MODEL_FROM_DATABASE=Revio KD20M usb:v04C8p072D* ID_MODEL_FROM_DATABASE=Revio KD410Z usb:v04CA* ID_VENDOR_FROM_DATABASE=Lite-On Technology Corp. usb:v04CAp004F* ID_MODEL_FROM_DATABASE=SK-9020 keyboard usb:v04CAp1766* ID_MODEL_FROM_DATABASE=HID Monitor Controls usb:v04CAp2004* ID_MODEL_FROM_DATABASE=Bluetooth 4.0 [Broadcom BCM20702A0] usb:v04CAp2006* ID_MODEL_FROM_DATABASE=Broadcom BCM43142A0 Bluetooth Device usb:v04CAp300B* ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth usb:v04CAp300D* ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth usb:v04CAp300F* ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth usb:v04CAp3014* ID_MODEL_FROM_DATABASE=Qualcoom Atheros Bluetooth usb:v04CAp7025* ID_MODEL_FROM_DATABASE=HP HD Webcam usb:v04CAp7046* ID_MODEL_FROM_DATABASE=TOSHIBA Web Camera - HD usb:v04CAp9304* ID_MODEL_FROM_DATABASE=Hub usb:v04CApF01C* ID_MODEL_FROM_DATABASE=TT1280DA DVB-T TV Tuner usb:v04CB* ID_VENDOR_FROM_DATABASE=Fuji Photo Film Co., Ltd usb:v04CBp0100* ID_MODEL_FROM_DATABASE=FinePix 30i/40i/50i, A101/201, 1300/2200, 1400/2400/2600/2800/4500/4700/4800/4900/6800/6900 Zoom usb:v04CBp0103* ID_MODEL_FROM_DATABASE=FinePix NX-500/NX-700 printer usb:v04CBp0104* ID_MODEL_FROM_DATABASE=FinePix A101, 2600/2800/4800/6800 Zoom (PC CAM) usb:v04CBp0108* ID_MODEL_FROM_DATABASE=FinePix F601 Zoom (DSC) usb:v04CBp0109* ID_MODEL_FROM_DATABASE=FinePix F601 Zoom (PC CAM) usb:v04CBp010A* ID_MODEL_FROM_DATABASE=FinePix S602 (Pro) Zoom (DSC) usb:v04CBp010B* ID_MODEL_FROM_DATABASE=FinePix S602 (Pro) Zoom (PC CAM) usb:v04CBp010D* ID_MODEL_FROM_DATABASE=FinePix Digital Camera 020531 usb:v04CBp010E* ID_MODEL_FROM_DATABASE=FinePix F402 Zoom (DSC) usb:v04CBp010F* ID_MODEL_FROM_DATABASE=FinePix F402 Zoom (PC CAM) usb:v04CBp0110* ID_MODEL_FROM_DATABASE=FinePix M603 Zoom (DSC) usb:v04CBp0111* ID_MODEL_FROM_DATABASE=FinePix M603 Zoom (PC CAM) usb:v04CBp0112* ID_MODEL_FROM_DATABASE=FinePix A202, A200 Zoom (DSC) usb:v04CBp0113* ID_MODEL_FROM_DATABASE=FinePix A202, A200 Zoom (PC CAM) usb:v04CBp0114* ID_MODEL_FROM_DATABASE=FinePix F401 Zoom (DSC) usb:v04CBp0115* ID_MODEL_FROM_DATABASE=FinePix F401 Zoom (PC CAM) usb:v04CBp0116* ID_MODEL_FROM_DATABASE=FinePix A203 Zoom (DSC) usb:v04CBp0117* ID_MODEL_FROM_DATABASE=FinePix A203 Zoom (PC CAM) usb:v04CBp0118* ID_MODEL_FROM_DATABASE=FinePix A303 Zoom (DSC) usb:v04CBp0119* ID_MODEL_FROM_DATABASE=FinePix A303 Zoom (PC CAM) usb:v04CBp011A* ID_MODEL_FROM_DATABASE=FinePix S304/3800 Zoom (DSC) usb:v04CBp011B* ID_MODEL_FROM_DATABASE=FinePix S304/3800 Zoom (PC CAM) usb:v04CBp011C* ID_MODEL_FROM_DATABASE=FinePix A204/2650 Zoom (DSC) usb:v04CBp011D* ID_MODEL_FROM_DATABASE=FinePix A204/2650 Zoom (PC CAM) usb:v04CBp0120* ID_MODEL_FROM_DATABASE=FinePix F700 Zoom (DSC) usb:v04CBp0121* ID_MODEL_FROM_DATABASE=FinePix F700 Zoom (PC CAM) usb:v04CBp0122* ID_MODEL_FROM_DATABASE=FinePix F410 Zoom (DSC) usb:v04CBp0123* ID_MODEL_FROM_DATABASE=FinePix F410 Zoom (PC CAM) usb:v04CBp0124* ID_MODEL_FROM_DATABASE=FinePix A310 Zoom (DSC) usb:v04CBp0125* ID_MODEL_FROM_DATABASE=FinePix A310 Zoom (PC CAM) usb:v04CBp0126* ID_MODEL_FROM_DATABASE=FinePix A210 Zoom (DSC) usb:v04CBp0127* ID_MODEL_FROM_DATABASE=FinePix A210 Zoom (PC CAM) usb:v04CBp0128* ID_MODEL_FROM_DATABASE=FinePix A205(S) Zoom (DSC) usb:v04CBp0129* ID_MODEL_FROM_DATABASE=FinePix A205(S) Zoom (PC CAM) usb:v04CBp012A* ID_MODEL_FROM_DATABASE=FinePix F610 Zoom (DSC) usb:v04CBp012B* ID_MODEL_FROM_DATABASE=FinePix Digital Camera 030513 usb:v04CBp012C* ID_MODEL_FROM_DATABASE=FinePix S7000 Zoom (DSC) usb:v04CBp012D* ID_MODEL_FROM_DATABASE=FinePix S7000 Zoom (PC CAM) usb:v04CBp012F* ID_MODEL_FROM_DATABASE=FinePix Digital Camera 030731 usb:v04CBp0130* ID_MODEL_FROM_DATABASE=FinePix S5000 Zoom (DSC) usb:v04CBp0131* ID_MODEL_FROM_DATABASE=FinePix S5000 Zoom (PC CAM) usb:v04CBp013B* ID_MODEL_FROM_DATABASE=FinePix Digital Camera 030722 usb:v04CBp013C* ID_MODEL_FROM_DATABASE=FinePix S3000 Zoom (DSC) usb:v04CBp013D* ID_MODEL_FROM_DATABASE=FinePix S3000 Zoom (PC CAM) usb:v04CBp013E* ID_MODEL_FROM_DATABASE=FinePix F420 Zoom (DSC) usb:v04CBp013F* ID_MODEL_FROM_DATABASE=FinePix F420 Zoom (PC CAM) usb:v04CBp0142* ID_MODEL_FROM_DATABASE=FinePix S7000 Zoom (PTP) usb:v04CBp0148* ID_MODEL_FROM_DATABASE=FinePix A330 Zoom (DSC) usb:v04CBp0149* ID_MODEL_FROM_DATABASE=FinePix A330 Zoom (UVC) usb:v04CBp014A* ID_MODEL_FROM_DATABASE=FinePix A330 Zoom (PTP) usb:v04CBp014B* ID_MODEL_FROM_DATABASE=FinePix A340 Zoom (DSC) usb:v04CBp014C* ID_MODEL_FROM_DATABASE=FinePix A340 Zoom (UVC) usb:v04CBp0159* ID_MODEL_FROM_DATABASE=FinePix F710 Zoom (DSC) usb:v04CBp0165* ID_MODEL_FROM_DATABASE=FinePix S3500 Zoom (DSC) usb:v04CBp0168* ID_MODEL_FROM_DATABASE=FinePix E500 Zoom (DSC) usb:v04CBp0169* ID_MODEL_FROM_DATABASE=FinePix E500 Zoom (UVC) usb:v04CBp016B* ID_MODEL_FROM_DATABASE=FinePix E510 Zoom (DSC) usb:v04CBp016C* ID_MODEL_FROM_DATABASE=FinePix E510 Zoom (PC CAM) usb:v04CBp016E* ID_MODEL_FROM_DATABASE=FinePix S5500 Zoom (DSC) usb:v04CBp016F* ID_MODEL_FROM_DATABASE=FinePix S5500 Zoom (UVC) usb:v04CBp0171* ID_MODEL_FROM_DATABASE=FinePix E550 Zoom (DSC) usb:v04CBp0172* ID_MODEL_FROM_DATABASE=FinePix E550 Zoom (UVC) usb:v04CBp0177* ID_MODEL_FROM_DATABASE=FinePix F10 (DSC) usb:v04CBp0179* ID_MODEL_FROM_DATABASE=Finepix F10 (PTP) usb:v04CBp0186* ID_MODEL_FROM_DATABASE=FinePix S5200/S5600 Zoom (DSC) usb:v04CBp0188* ID_MODEL_FROM_DATABASE=FinePix S5200/S5600 Zoom (PTP) usb:v04CBp018E* ID_MODEL_FROM_DATABASE=FinePix S9500 Zoom (DSC) usb:v04CBp018F* ID_MODEL_FROM_DATABASE=FinePix S9500 Zoom (PTP) usb:v04CBp0192* ID_MODEL_FROM_DATABASE=FinePix E900 Zoom (DSC) usb:v04CBp0193* ID_MODEL_FROM_DATABASE=FinePix E900 Zoom (PTP) usb:v04CBp019B* ID_MODEL_FROM_DATABASE=FinePix F30 (PTP) usb:v04CBp01AF* ID_MODEL_FROM_DATABASE=FinePix A700 (PTP) usb:v04CBp01BF* ID_MODEL_FROM_DATABASE=FinePix F6000fd/S6500fd Zoom (PTP) usb:v04CBp01C0* ID_MODEL_FROM_DATABASE=FinePix F20 (PTP) usb:v04CBp01C1* ID_MODEL_FROM_DATABASE=FinePix F31fd (PTP) usb:v04CBp01C4* ID_MODEL_FROM_DATABASE=FinePix S5700 Zoom (PTP) usb:v04CBp01C5* ID_MODEL_FROM_DATABASE=FinePix F40fd (PTP) usb:v04CBp01C6* ID_MODEL_FROM_DATABASE=FinePix A820 Zoom (PTP) usb:v04CBp01D2* ID_MODEL_FROM_DATABASE=FinePix A800 Zoom (PTP) usb:v04CBp01D3* ID_MODEL_FROM_DATABASE=FinePix A920 (PTP) usb:v04CBp01D4* ID_MODEL_FROM_DATABASE=FinePix F50fd (PTP) usb:v04CBp01D5* ID_MODEL_FROM_DATABASE=FinePix F47 (PTP) usb:v04CBp01F7* ID_MODEL_FROM_DATABASE=FinePix J250 (PTP) usb:v04CBp01FD* ID_MODEL_FROM_DATABASE=A160 usb:v04CBp023E* ID_MODEL_FROM_DATABASE=FinePix AX300 usb:v04CBp0240* ID_MODEL_FROM_DATABASE=FinePix S2950 Digital Camera usb:v04CBp0241* ID_MODEL_FROM_DATABASE=FinePix S3200 Digital Camera usb:v04CBp0278* ID_MODEL_FROM_DATABASE=FinePix JV300 usb:v04CC* ID_VENDOR_FROM_DATABASE=ST-Ericsson usb:v04CCp1122* ID_MODEL_FROM_DATABASE=Hub usb:v04CCp1520* ID_MODEL_FROM_DATABASE=USB 2.0 Hub (Avocent KVM) usb:v04CCp1521* ID_MODEL_FROM_DATABASE=USB 2.0 Hub usb:v04CCp1A62* ID_MODEL_FROM_DATABASE=GW Instek GSP-830 Spectrum Analyzer (HID) usb:v04CCp2323* ID_MODEL_FROM_DATABASE=Ux500 serial debug port usb:v04CCp2533* ID_MODEL_FROM_DATABASE=NFC device (PN533) usb:v04CCp8116* ID_MODEL_FROM_DATABASE=Camera usb:v04CD* ID_VENDOR_FROM_DATABASE=Tatung Co. Of America usb:v04CE* ID_VENDOR_FROM_DATABASE=ScanLogic Corp. usb:v04CEp0002* ID_MODEL_FROM_DATABASE=SL11R-IDE IDE Bridge usb:v04CEp0100* ID_MODEL_FROM_DATABASE=USB2PRN Printer Class usb:v04CEp0300* ID_MODEL_FROM_DATABASE=Phantom 336CX - C3 scanner usb:v04CEp04CE* ID_MODEL_FROM_DATABASE=SL11DEMO, VID: 0x4ce, PID: 0x4ce usb:v04CEp07D1* ID_MODEL_FROM_DATABASE=SL11R, VID: 0x4ce, PID: 0x07D1 usb:v04CF* ID_VENDOR_FROM_DATABASE=Myson Century, Inc. usb:v04CFp0022* ID_MODEL_FROM_DATABASE=OCZ Alchemy Series Elixir II Keyboard usb:v04CFp0800* ID_MODEL_FROM_DATABASE=MTP800 Mass Storage Device usb:v04CFp8810* ID_MODEL_FROM_DATABASE=CS8810 Mass Storage Device usb:v04CFp8811* ID_MODEL_FROM_DATABASE=CS8811 Mass Storage Device usb:v04CFp8813* ID_MODEL_FROM_DATABASE=CS8813 Mass Storage Device usb:v04CFp8818* ID_MODEL_FROM_DATABASE=USB2.0 to ATAPI Bridge Controller usb:v04CFp8819* ID_MODEL_FROM_DATABASE=USB 2.0 SD/MMC Reader usb:v04CFp9920* ID_MODEL_FROM_DATABASE=CS8819A2-114 Mass Storage Device usb:v04D0* ID_VENDOR_FROM_DATABASE=Digi International usb:v04D1* ID_VENDOR_FROM_DATABASE=ITT Canon usb:v04D2* ID_VENDOR_FROM_DATABASE=Altec Lansing Technologies usb:v04D2p0070* ID_MODEL_FROM_DATABASE=ADA70 Speakers usb:v04D2p0305* ID_MODEL_FROM_DATABASE=Non-Compliant Audio Device usb:v04D2p0311* ID_MODEL_FROM_DATABASE=ADA-310 Speakers usb:v04D2p2060* ID_MODEL_FROM_DATABASE=Claritel-i750 - vp usb:v04D2pFF05* ID_MODEL_FROM_DATABASE=ADA-305 Speakers usb:v04D2pFF47* ID_MODEL_FROM_DATABASE=Lansing HID Audio Controls usb:v04D2pFF49* ID_MODEL_FROM_DATABASE=Lansing HID Audio Controls usb:v04D3* ID_VENDOR_FROM_DATABASE=VidUS, Inc. usb:v04D4* ID_VENDOR_FROM_DATABASE=LSI Logic, Inc. usb:v04D5* ID_VENDOR_FROM_DATABASE=Forte Technologies, Inc. usb:v04D6* ID_VENDOR_FROM_DATABASE=Mentor Graphics usb:v04D7* ID_VENDOR_FROM_DATABASE=Oki Semiconductor usb:v04D7p1BE4* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v04D8* ID_VENDOR_FROM_DATABASE=Microchip Technology, Inc. usb:v04D8p0002* ID_MODEL_FROM_DATABASE=PicoLCD 20x2 usb:v04D8p0003* ID_MODEL_FROM_DATABASE=PICkit 2 Microcontroller Programmer usb:v04D8p000A* ID_MODEL_FROM_DATABASE=CDC RS-232 Emulation Demo usb:v04D8p000B* ID_MODEL_FROM_DATABASE=PIC18F2550 (32K Flashable 10 Channel, 10 Bit A/D USB Microcontroller) usb:v04D8p0032* ID_MODEL_FROM_DATABASE=PICkit1 usb:v04D8p0033* ID_MODEL_FROM_DATABASE=PICkit2 usb:v04D8p0036* ID_MODEL_FROM_DATABASE=PICkit Serial Analyzer usb:v04D8p00E0* ID_MODEL_FROM_DATABASE=PIC32 Starter Board usb:v04D8p04CD* ID_MODEL_FROM_DATABASE=28Cxxx EEPROM Programmer usb:v04D8p0A04* ID_MODEL_FROM_DATABASE=AGP LIN Serial Analyzer usb:v04D8p8000* ID_MODEL_FROM_DATABASE=In-Circuit Debugger usb:v04D8p8001* ID_MODEL_FROM_DATABASE=ICD2 in-circuit debugger usb:v04D8p8101* ID_MODEL_FROM_DATABASE=PIC24F Starter Kit usb:v04D8p8107* ID_MODEL_FROM_DATABASE=Microstick II usb:v04D8p8108* ID_MODEL_FROM_DATABASE=ChipKit Pro MX7 (PIC32MX) usb:v04D8p9004* ID_MODEL_FROM_DATABASE=Microchip REAL ICE usb:v04D8p900A* ID_MODEL_FROM_DATABASE=PICkit3 usb:v04D8pC001* ID_MODEL_FROM_DATABASE=PicoLCD 20x4 usb:v04D8pE11C* ID_MODEL_FROM_DATABASE=TL866CS EEPROM Programmer [MiniPRO] usb:v04D8pF2C4* ID_MODEL_FROM_DATABASE=Macareux-labs Hygrometry Temperature Sensor usb:v04D8pF3AA* ID_MODEL_FROM_DATABASE=Macareux-labs Usbce Bootloader mode usb:v04D8pF437* ID_MODEL_FROM_DATABASE=SBE Tech Ultrasonic Anemometer usb:v04D8pF4B5* ID_MODEL_FROM_DATABASE=SmartScope usb:v04D8pF8DA* ID_MODEL_FROM_DATABASE=Hughski Ltd. ColorHug usb:v04D8pF8E8* ID_MODEL_FROM_DATABASE=Harmony 300/350 Remote usb:v04D8pF91C* ID_MODEL_FROM_DATABASE=SPROG IIv3 usb:v04D8pFAFF* ID_MODEL_FROM_DATABASE=Dangerous Prototypes BusPirate v4 Bootloader mode usb:v04D8pFB00* ID_MODEL_FROM_DATABASE=Dangerous Prototypes BusPirate v4 usb:v04D8pFBB2* ID_MODEL_FROM_DATABASE=GCUSB-nStep stepper motor controller usb:v04D8pFBBA* ID_MODEL_FROM_DATABASE=DiscFerret Magnetic Disc Analyser (bootloader mode) usb:v04D8pFBBB* ID_MODEL_FROM_DATABASE=DiscFerret Magnetic Disc Analyser (active mode) usb:v04D8pFC1E* ID_MODEL_FROM_DATABASE=Bachrus Speedometer Interface usb:v04D8pFC92* ID_MODEL_FROM_DATABASE=Open Bench Logic Sniffer usb:v04D8pFFEE* ID_MODEL_FROM_DATABASE=Devantech USB-ISS usb:v04D8pFFEF* ID_MODEL_FROM_DATABASE=PICoPLC [APStech] usb:v04D9* ID_VENDOR_FROM_DATABASE=Holtek Semiconductor, Inc. usb:v04D9p0022* ID_MODEL_FROM_DATABASE=Portable Keyboard usb:v04D9p048E* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v04D9p0499* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v04D9p1203* ID_MODEL_FROM_DATABASE=Keyboard usb:v04D9p1400* ID_MODEL_FROM_DATABASE=PS/2 keyboard + mouse controller usb:v04D9p1503* ID_MODEL_FROM_DATABASE=Keyboard usb:v04D9p1603* ID_MODEL_FROM_DATABASE=Keyboard usb:v04D9p1702* ID_MODEL_FROM_DATABASE=Keyboard LKS02 usb:v04D9p2011* ID_MODEL_FROM_DATABASE=Keyboard [Diatec Filco Majestouch 1] usb:v04D9p2013* ID_MODEL_FROM_DATABASE=Keyboard [Das Keyboard] usb:v04D9p2221* ID_MODEL_FROM_DATABASE=Keyboard usb:v04D9p2323* ID_MODEL_FROM_DATABASE=Keyboard usb:v04D9p2519* ID_MODEL_FROM_DATABASE=Shenzhen LogoTech 2.4GHz receiver usb:v04D9p2832* ID_MODEL_FROM_DATABASE=HT82A832R Audio MCU usb:v04D9p2834* ID_MODEL_FROM_DATABASE=HT82A834R Audio MCU usb:v04D9pA055* ID_MODEL_FROM_DATABASE=Keyboard usb:v04DA* ID_VENDOR_FROM_DATABASE=Panasonic (Matsushita) usb:v04DAp0901* ID_MODEL_FROM_DATABASE=LS-120 Camera usb:v04DAp0912* ID_MODEL_FROM_DATABASE=SDR-S10 usb:v04DAp0B01* ID_MODEL_FROM_DATABASE=CD-R/RW Drive usb:v04DAp0B03* ID_MODEL_FROM_DATABASE=SuperDisk 240MB usb:v04DAp0D01* ID_MODEL_FROM_DATABASE=CD-R Drive KXL-840AN usb:v04DAp0D09* ID_MODEL_FROM_DATABASE=CD-R Drive KXL-RW32AN usb:v04DAp0D0A* ID_MODEL_FROM_DATABASE=CD-R Drive KXL-CB20AN usb:v04DAp0D0D* ID_MODEL_FROM_DATABASE=CDRCB03 usb:v04DAp0D0E* ID_MODEL_FROM_DATABASE=DVD-ROM & CD-R/RW usb:v04DAp0F40* ID_MODEL_FROM_DATABASE=Printer usb:v04DAp104D* ID_MODEL_FROM_DATABASE=Elite Panaboard UB-T880 (HID) usb:v04DAp104E* ID_MODEL_FROM_DATABASE=Elite Panaboard Pen Adaptor (HID) usb:v04DAp1500* ID_MODEL_FROM_DATABASE=MFSUSB Driver usb:v04DAp1800* ID_MODEL_FROM_DATABASE=DY-WL10 802.11abgn Adapter [Broadcom BCM4323] usb:v04DAp1B00* ID_MODEL_FROM_DATABASE=MultiMediaCard usb:v04DAp2121* ID_MODEL_FROM_DATABASE=EB-VS6 usb:v04DAp2316* ID_MODEL_FROM_DATABASE=DVC Mass Storage Device usb:v04DAp2317* ID_MODEL_FROM_DATABASE=DVC USB-SERIAL Driver for WinXP usb:v04DAp2318* ID_MODEL_FROM_DATABASE=NV-GS11/230/250 (webcam mode) usb:v04DAp2319* ID_MODEL_FROM_DATABASE=NV-GS15 (webcam mode) usb:v04DAp231A* ID_MODEL_FROM_DATABASE=NV-GS11/230/250 (DV mode) usb:v04DAp231D* ID_MODEL_FROM_DATABASE=DVC Web Camera Device usb:v04DAp231E* ID_MODEL_FROM_DATABASE=DVC DV Stream Device usb:v04DAp2372* ID_MODEL_FROM_DATABASE=Lumix Camera (Storage mode) usb:v04DAp2374* ID_MODEL_FROM_DATABASE=Lumix Camera (PTP mode) usb:v04DAp2451* ID_MODEL_FROM_DATABASE=HDC-SD9 usb:v04DAp245B* ID_MODEL_FROM_DATABASE=HC-X920K (3MOS Full HD video camcorder) usb:v04DAp2497* ID_MODEL_FROM_DATABASE=HDC-TM700 usb:v04DAp250C* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) usb:v04DAp250D* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem usb:v04DAp3904* ID_MODEL_FROM_DATABASE=N5HBZ0000055 802.11abgn Wireless Adapter [Atheros AR7010+AR9280] usb:v04DAp3C04* ID_MODEL_FROM_DATABASE=JT-P100MR-20 [ePassport Reader] usb:v04DB* ID_VENDOR_FROM_DATABASE=Hypertec Pty, Ltd usb:v04DC* ID_VENDOR_FROM_DATABASE=Huan Hsin Holdings, Ltd usb:v04DD* ID_VENDOR_FROM_DATABASE=Sharp Corp. usb:v04DDp13A6* ID_MODEL_FROM_DATABASE=MFC2000 usb:v04DDp6006* ID_MODEL_FROM_DATABASE=AL-1216 usb:v04DDp6007* ID_MODEL_FROM_DATABASE=AL-1045 usb:v04DDp6008* ID_MODEL_FROM_DATABASE=AL-1255 usb:v04DDp6009* ID_MODEL_FROM_DATABASE=AL-1530CS usb:v04DDp600A* ID_MODEL_FROM_DATABASE=AL-1540CS usb:v04DDp600B* ID_MODEL_FROM_DATABASE=AL-1456 usb:v04DDp600C* ID_MODEL_FROM_DATABASE=AL-1555 usb:v04DDp600D* ID_MODEL_FROM_DATABASE=AL-1225 usb:v04DDp600E* ID_MODEL_FROM_DATABASE=AL-1551CS usb:v04DDp600F* ID_MODEL_FROM_DATABASE=AR-122E usb:v04DDp6010* ID_MODEL_FROM_DATABASE=AR-152E usb:v04DDp6011* ID_MODEL_FROM_DATABASE=AR-157E usb:v04DDp6012* ID_MODEL_FROM_DATABASE=SN-1045 usb:v04DDp6013* ID_MODEL_FROM_DATABASE=SN-1255 usb:v04DDp6014* ID_MODEL_FROM_DATABASE=SN-1456 usb:v04DDp6015* ID_MODEL_FROM_DATABASE=SN-1555 usb:v04DDp6016* ID_MODEL_FROM_DATABASE=AR-153E usb:v04DDp6017* ID_MODEL_FROM_DATABASE=AR-122E N usb:v04DDp6018* ID_MODEL_FROM_DATABASE=AR-153E N usb:v04DDp6019* ID_MODEL_FROM_DATABASE=AR-152E N usb:v04DDp601A* ID_MODEL_FROM_DATABASE=AR-157E N usb:v04DDp601B* ID_MODEL_FROM_DATABASE=AL-1217 usb:v04DDp601C* ID_MODEL_FROM_DATABASE=AL-1226 usb:v04DDp601D* ID_MODEL_FROM_DATABASE=AR-123E usb:v04DDp6021* ID_MODEL_FROM_DATABASE=IS01 usb:v04DDp7002* ID_MODEL_FROM_DATABASE=DVC Ver.1.0 usb:v04DDp7004* ID_MODEL_FROM_DATABASE=VE-CG40U Digital Still Camera usb:v04DDp7005* ID_MODEL_FROM_DATABASE=VE-CG30 Digital Still Camera usb:v04DDp7007* ID_MODEL_FROM_DATABASE=VL-Z7S Digital Camcorder usb:v04DDp8004* ID_MODEL_FROM_DATABASE=Zaurus SL-5000D/SL-5500 PDA usb:v04DDp8005* ID_MODEL_FROM_DATABASE=Zaurus A-300 usb:v04DDp8006* ID_MODEL_FROM_DATABASE=Zaurus SL-B500/SL-5600 PDA usb:v04DDp8007* ID_MODEL_FROM_DATABASE=Zaurus C-700 PDA usb:v04DDp9009* ID_MODEL_FROM_DATABASE=AR-M160 usb:v04DDp9014* ID_MODEL_FROM_DATABASE=IM-DR80 Portable NetMD Player usb:v04DDp9031* ID_MODEL_FROM_DATABASE=Zaurus C-750/C-760/C-860/SL-C3000 PDA usb:v04DDp9032* ID_MODEL_FROM_DATABASE=Zaurus SL-6000 usb:v04DDp903A* ID_MODEL_FROM_DATABASE=GSM GPRS usb:v04DDp9050* ID_MODEL_FROM_DATABASE=Zaurus C-860 PDA usb:v04DDp9056* ID_MODEL_FROM_DATABASE=Viewcam Z usb:v04DDp9073* ID_MODEL_FROM_DATABASE=AM-900 usb:v04DDp9074* ID_MODEL_FROM_DATABASE=GSM GPRS usb:v04DDp90A9* ID_MODEL_FROM_DATABASE=Sharp Composite usb:v04DDp90D0* ID_MODEL_FROM_DATABASE=USB-to-Serial Comm. Port usb:v04DDp90F2* ID_MODEL_FROM_DATABASE=Sharp 3G GSM USB Control usb:v04DDp9120* ID_MODEL_FROM_DATABASE=WS004SH usb:v04DDp9122* ID_MODEL_FROM_DATABASE=WS007SH usb:v04DDp9123* ID_MODEL_FROM_DATABASE=W-ZERO3 ES Smartphone usb:v04DDp91A3* ID_MODEL_FROM_DATABASE=922SH Internet Machine usb:v04DDp939A* ID_MODEL_FROM_DATABASE=IS03 usb:v04DE* ID_VENDOR_FROM_DATABASE=MindShare, Inc. usb:v04DF* ID_VENDOR_FROM_DATABASE=Interlink Electronics usb:v04E1* ID_VENDOR_FROM_DATABASE=Iiyama North America, Inc. usb:v04E1p0201* ID_MODEL_FROM_DATABASE=Monitor Hub usb:v04E2* ID_VENDOR_FROM_DATABASE=Exar Corp. usb:v04E2p1410* ID_MODEL_FROM_DATABASE=XR21V1410 USB-UART IC usb:v04E3* ID_VENDOR_FROM_DATABASE=Zilog, Inc. usb:v04E4* ID_VENDOR_FROM_DATABASE=ACC Microelectronics usb:v04E5* ID_VENDOR_FROM_DATABASE=Promise Technology usb:v04E6* ID_VENDOR_FROM_DATABASE=SCM Microsystems, Inc. usb:v04E6p0001* ID_MODEL_FROM_DATABASE=E-USB ATA Bridge usb:v04E6p0002* ID_MODEL_FROM_DATABASE=eUSCSI SCSI Bridge usb:v04E6p0003* ID_MODEL_FROM_DATABASE=eUSB SmartMedia Card Reader usb:v04E6p0005* ID_MODEL_FROM_DATABASE=eUSB SmartMedia/CompactFlash Card Reader usb:v04E6p0006* ID_MODEL_FROM_DATABASE=eUSB SmartMedia Card Reader usb:v04E6p0007* ID_MODEL_FROM_DATABASE=Hifd usb:v04E6p0009* ID_MODEL_FROM_DATABASE=eUSB ATA/ATAPI Adapter usb:v04E6p000A* ID_MODEL_FROM_DATABASE=eUSB CompactFlash Adapter usb:v04E6p000B* ID_MODEL_FROM_DATABASE=eUSCSI Bridge usb:v04E6p000C* ID_MODEL_FROM_DATABASE=eUSCSI Bridge usb:v04E6p000D* ID_MODEL_FROM_DATABASE=Dazzle MS usb:v04E6p0012* ID_MODEL_FROM_DATABASE=Dazzle SD/MMC usb:v04E6p0101* ID_MODEL_FROM_DATABASE=eUSB ATA Bridge (Sony Spressa USB CDRW) usb:v04E6p0311* ID_MODEL_FROM_DATABASE=Dazzle DM-CF usb:v04E6p0312* ID_MODEL_FROM_DATABASE=Dazzle DM-SD/MMC usb:v04E6p0313* ID_MODEL_FROM_DATABASE=Dazzle SM usb:v04E6p0314* ID_MODEL_FROM_DATABASE=Dazzle MS usb:v04E6p0322* ID_MODEL_FROM_DATABASE=e-Film Reader-5 usb:v04E6p0325* ID_MODEL_FROM_DATABASE=eUSB ORCA Quad Reader usb:v04E6p0327* ID_MODEL_FROM_DATABASE=Digital Media Reader usb:v04E6p03FE* ID_MODEL_FROM_DATABASE=DMHS2 DFU Adapter usb:v04E6p0406* ID_MODEL_FROM_DATABASE=eUSB SmartDM Reader usb:v04E6p04E6* ID_MODEL_FROM_DATABASE=eUSB DFU Adapter usb:v04E6p04E7* ID_MODEL_FROM_DATABASE=STCII DFU Adapter usb:v04E6p04E8* ID_MODEL_FROM_DATABASE=eUSBDM DFU Adapter usb:v04E6p04E9* ID_MODEL_FROM_DATABASE=DM-E DFU Adapter usb:v04E6p0500* ID_MODEL_FROM_DATABASE=Veridicom 5thSense Fingerprint Sensor and eUSB SmartCard usb:v04E6p0701* ID_MODEL_FROM_DATABASE=DCS200 Loader Device usb:v04E6p0702* ID_MODEL_FROM_DATABASE=DVD Creation Station 200 usb:v04E6p0703* ID_MODEL_FROM_DATABASE=DVC100 Loader Device usb:v04E6p0704* ID_MODEL_FROM_DATABASE=Digital Video Creator 100 usb:v04E6p1001* ID_MODEL_FROM_DATABASE=SCR300 Smart Card Reader usb:v04E6p1010* ID_MODEL_FROM_DATABASE=USBAT-2 CompactFlash Card Reader usb:v04E6p1014* ID_MODEL_FROM_DATABASE=e-Film Reader-3 usb:v04E6p1020* ID_MODEL_FROM_DATABASE=USBAT ATA/ATAPI Adapter usb:v04E6p2007* ID_MODEL_FROM_DATABASE=RSA SecurID ComboReader usb:v04E6p2009* ID_MODEL_FROM_DATABASE=Citibank Smart Card Reader usb:v04E6p200A* ID_MODEL_FROM_DATABASE=Reflex v.2 Smart Card Reader usb:v04E6p200D* ID_MODEL_FROM_DATABASE=STR391 Reader usb:v04E6p5111* ID_MODEL_FROM_DATABASE=SCR331-DI SmartCard Reader usb:v04E6p5113* ID_MODEL_FROM_DATABASE=SCR333 SmartCard Reader usb:v04E6p5114* ID_MODEL_FROM_DATABASE=SCR331-DI SmartCard Reader usb:v04E6p5115* ID_MODEL_FROM_DATABASE=SCR335 SmartCard Reader usb:v04E6p5116* ID_MODEL_FROM_DATABASE=SCR331-LC1 / SCR3310 SmartCard Reader usb:v04E6p5117* ID_MODEL_FROM_DATABASE=SCR3320 - Smart Card Reader usb:v04E6p5118* ID_MODEL_FROM_DATABASE=Expresscard SIM Card Reader usb:v04E6p5119* ID_MODEL_FROM_DATABASE=SCR3340 - ExpressCard54 Smart Card Reader usb:v04E6p511B* ID_MODEL_FROM_DATABASE=SmartCard Reader usb:v04E6p511D* ID_MODEL_FROM_DATABASE=SCR3311 Smart Card Reader usb:v04E6p5120* ID_MODEL_FROM_DATABASE=SCR331-DI SmartCard Reader usb:v04E6p5121* ID_MODEL_FROM_DATABASE=SDI010 Smart Card Reader usb:v04E6p5151* ID_MODEL_FROM_DATABASE=SCR338 Keyboard Smart Card Reader usb:v04E6p5292* ID_MODEL_FROM_DATABASE=SCL011 RFID reader usb:v04E6p5410* ID_MODEL_FROM_DATABASE=SCR35xx Smart Card Reader usb:v04E6p5591* ID_MODEL_FROM_DATABASE=SCL3711-NFC&RW usb:v04E6pE000* ID_MODEL_FROM_DATABASE=SCRx31 Reader usb:v04E6pE001* ID_MODEL_FROM_DATABASE=SCR331 SmartCard Reader usb:v04E6pE003* ID_MODEL_FROM_DATABASE=SPR532 PinPad SmartCard Reader usb:v04E7* ID_VENDOR_FROM_DATABASE=Elo TouchSystems usb:v04E7p0001* ID_MODEL_FROM_DATABASE=TouchScreen usb:v04E7p0002* ID_MODEL_FROM_DATABASE=Touchmonitor Interface 2600 Rev 2 usb:v04E7p0004* ID_MODEL_FROM_DATABASE=4000U CarrollTouch® Touchmonitor Interface usb:v04E7p0007* ID_MODEL_FROM_DATABASE=2500U IntelliTouch® Touchmonitor Interface usb:v04E7p0008* ID_MODEL_FROM_DATABASE=3000U AccuTouch® Touchmonitor Interface usb:v04E7p0009* ID_MODEL_FROM_DATABASE=4000U CarrollTouch® Touchmonitor Interface usb:v04E7p0020* ID_MODEL_FROM_DATABASE=Touchscreen Interface (2700) usb:v04E7p0021* ID_MODEL_FROM_DATABASE=Touchmonitor Interface usb:v04E7p0030* ID_MODEL_FROM_DATABASE=4500U CarrollTouch® Touchmonitor Interface usb:v04E7p0032* ID_MODEL_FROM_DATABASE=Touchmonitor Interface usb:v04E7p0033* ID_MODEL_FROM_DATABASE=Touchmonitor Interface usb:v04E7p0041* ID_MODEL_FROM_DATABASE=5010 Surface Capacitive Touchmonitor Interface usb:v04E7p0042* ID_MODEL_FROM_DATABASE=Touchmonitor Interface usb:v04E7p0050* ID_MODEL_FROM_DATABASE=2216 AccuTouch® Touchmonitor Interface usb:v04E7p0071* ID_MODEL_FROM_DATABASE=Touchmonitor Interface usb:v04E7p0072* ID_MODEL_FROM_DATABASE=Touchmonitor Interface usb:v04E7p0081* ID_MODEL_FROM_DATABASE=Touchmonitor Interface usb:v04E7p0082* ID_MODEL_FROM_DATABASE=Touchmonitor Interface usb:v04E7p00FF* ID_MODEL_FROM_DATABASE=Touchmonitor Interface usb:v04E8* ID_VENDOR_FROM_DATABASE=Samsung Electronics Co., Ltd usb:v04E8p0100* ID_MODEL_FROM_DATABASE=Kingston Flash Drive (128MB) usb:v04E8p0110* ID_MODEL_FROM_DATABASE=Connect3D Flash Drive usb:v04E8p0111* ID_MODEL_FROM_DATABASE=Connect3D Flash Drive usb:v04E8p0300* ID_MODEL_FROM_DATABASE=E2530 / GT-C3350 Phones (Mass storage mode) usb:v04E8p1003* ID_MODEL_FROM_DATABASE=MP3 Player and Recorder usb:v04E8p1006* ID_MODEL_FROM_DATABASE=SDC-200Z usb:v04E8p130C* ID_MODEL_FROM_DATABASE=NX100 usb:v04E8p1F05* ID_MODEL_FROM_DATABASE=S2 Portable [JMicron] (500GB) usb:v04E8p1F06* ID_MODEL_FROM_DATABASE=HX-MU064DA portable harddisk usb:v04E8p2018* ID_MODEL_FROM_DATABASE=WIS09ABGN LinkStick Wireless LAN Adapter usb:v04E8p2035* ID_MODEL_FROM_DATABASE=Digital Photo Frame Mass Storage usb:v04E8p2036* ID_MODEL_FROM_DATABASE=Digital Photo Frame Mini Monitor usb:v04E8p3004* ID_MODEL_FROM_DATABASE=ML-4600 usb:v04E8p3005* ID_MODEL_FROM_DATABASE=Docuprint P1210 usb:v04E8p3008* ID_MODEL_FROM_DATABASE=ML-6060 laser printer usb:v04E8p300C* ID_MODEL_FROM_DATABASE=ML-1210 Printer usb:v04E8p300E* ID_MODEL_FROM_DATABASE=Laser Printer usb:v04E8p3104* ID_MODEL_FROM_DATABASE=ML-3550N usb:v04E8p3210* ID_MODEL_FROM_DATABASE=ML-5200A Laser Printer usb:v04E8p3226* ID_MODEL_FROM_DATABASE=Laser Printer usb:v04E8p3228* ID_MODEL_FROM_DATABASE=Laser Printer usb:v04E8p322A* ID_MODEL_FROM_DATABASE=Laser Printer usb:v04E8p322C* ID_MODEL_FROM_DATABASE=Laser Printer usb:v04E8p3230* ID_MODEL_FROM_DATABASE=ML-1440 usb:v04E8p3232* ID_MODEL_FROM_DATABASE=Laser Printer usb:v04E8p3236* ID_MODEL_FROM_DATABASE=ML-1450 usb:v04E8p3238* ID_MODEL_FROM_DATABASE=ML-1430 usb:v04E8p323A* ID_MODEL_FROM_DATABASE=ML-1710 Printer usb:v04E8p323B* ID_MODEL_FROM_DATABASE=Phaser 3130 usb:v04E8p323C* ID_MODEL_FROM_DATABASE=Laser Printer usb:v04E8p323D* ID_MODEL_FROM_DATABASE=Phaser 3120 usb:v04E8p323E* ID_MODEL_FROM_DATABASE=Laser Printer usb:v04E8p3240* ID_MODEL_FROM_DATABASE=Laser Printer usb:v04E8p3242* ID_MODEL_FROM_DATABASE=ML-1510 Laser Printer usb:v04E8p3248* ID_MODEL_FROM_DATABASE=Color Laser Printer usb:v04E8p324A* ID_MODEL_FROM_DATABASE=Laser Printer usb:v04E8p324C* ID_MODEL_FROM_DATABASE=ML-1740 Printer usb:v04E8p324D* ID_MODEL_FROM_DATABASE=Phaser 3121 usb:v04E8p3256* ID_MODEL_FROM_DATABASE=ML-1520 Laser Printer usb:v04E8p325B* ID_MODEL_FROM_DATABASE=Xerox Phaser 3117 Laser Printer usb:v04E8p325F* ID_MODEL_FROM_DATABASE=Phaser 3425 Laser Printer usb:v04E8p3260* ID_MODEL_FROM_DATABASE=CLP-510 Color Laser Printer usb:v04E8p3268* ID_MODEL_FROM_DATABASE=ML-1610 Mono Laser Printer usb:v04E8p326C* ID_MODEL_FROM_DATABASE=ML-2010P Mono Laser Printer usb:v04E8p3276* ID_MODEL_FROM_DATABASE=ML-3050/ML-3051 Laser Printer usb:v04E8p328E* ID_MODEL_FROM_DATABASE=CLP-310 Color Laser Printer usb:v04E8p3292* ID_MODEL_FROM_DATABASE=ML-1640 Series Laser Printer usb:v04E8p3296* ID_MODEL_FROM_DATABASE=ML-2580N Mono Laser Printer usb:v04E8p3297* ID_MODEL_FROM_DATABASE=ML-191x/ML-252x Laser Printer usb:v04E8p329F* ID_MODEL_FROM_DATABASE=CLP-325 Color Laser Printer usb:v04E8p3301* ID_MODEL_FROM_DATABASE=ML-1660 Series usb:v04E8p330C* ID_MODEL_FROM_DATABASE=ML-1865 usb:v04E8p3310* ID_MODEL_FROM_DATABASE=ML-331x Series Laser Printer usb:v04E8p3315* ID_MODEL_FROM_DATABASE=ML-2540 Series Laser Printer usb:v04E8p331E* ID_MODEL_FROM_DATABASE=M262x/M282x Xpress Series Laser Printer usb:v04E8p3409* ID_MODEL_FROM_DATABASE=SCX-4216F Scanner usb:v04E8p340C* ID_MODEL_FROM_DATABASE=SCX-5x15 series usb:v04E8p340D* ID_MODEL_FROM_DATABASE=SCX-6x20 series usb:v04E8p340E* ID_MODEL_FROM_DATABASE=MFP 560 series usb:v04E8p340F* ID_MODEL_FROM_DATABASE=Printing Support usb:v04E8p3412* ID_MODEL_FROM_DATABASE=SCX-4x20 series usb:v04E8p3413* ID_MODEL_FROM_DATABASE=SCX-4100 Scanner usb:v04E8p3415* ID_MODEL_FROM_DATABASE=Composite Device usb:v04E8p3419* ID_MODEL_FROM_DATABASE=Composite Device usb:v04E8p341A* ID_MODEL_FROM_DATABASE=Printing Support usb:v04E8p341B* ID_MODEL_FROM_DATABASE=SCX-4200 series usb:v04E8p341C* ID_MODEL_FROM_DATABASE=Composite Device usb:v04E8p341D* ID_MODEL_FROM_DATABASE=Composite Device usb:v04E8p341F* ID_MODEL_FROM_DATABASE=Composite Device usb:v04E8p3420* ID_MODEL_FROM_DATABASE=Composite Device usb:v04E8p3426* ID_MODEL_FROM_DATABASE=SCX-4500 Laser Printer usb:v04E8p342D* ID_MODEL_FROM_DATABASE=SCX-4x28 Series usb:v04E8p344F* ID_MODEL_FROM_DATABASE=SCX-3400 Series usb:v04E8p3605* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v04E8p3606* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v04E8p3609* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v04E8p3902* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v04E8p3903* ID_MODEL_FROM_DATABASE=Xerox WorkCentre XK50cx usb:v04E8p390F* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v04E8p3911* ID_MODEL_FROM_DATABASE=SCX-1020 series usb:v04E8p4005* ID_MODEL_FROM_DATABASE=GT-S8000 Jet (msc) usb:v04E8p4F1F* ID_MODEL_FROM_DATABASE=GT-S8000 Jet (mtp) usb:v04E8p5000* ID_MODEL_FROM_DATABASE=YP-MF series usb:v04E8p5001* ID_MODEL_FROM_DATABASE=YP-100 usb:v04E8p5002* ID_MODEL_FROM_DATABASE=YP-30 usb:v04E8p5003* ID_MODEL_FROM_DATABASE=YP-700 usb:v04E8p5004* ID_MODEL_FROM_DATABASE=YP-30 usb:v04E8p5005* ID_MODEL_FROM_DATABASE=YP-300 usb:v04E8p5006* ID_MODEL_FROM_DATABASE=YP-750 usb:v04E8p500D* ID_MODEL_FROM_DATABASE=MP3 Player usb:v04E8p5010* ID_MODEL_FROM_DATABASE=Yepp YP-35 usb:v04E8p5011* ID_MODEL_FROM_DATABASE=YP-780 usb:v04E8p5013* ID_MODEL_FROM_DATABASE=YP-60 usb:v04E8p5015* ID_MODEL_FROM_DATABASE=yepp upgrade usb:v04E8p501B* ID_MODEL_FROM_DATABASE=MP3 Player usb:v04E8p5021* ID_MODEL_FROM_DATABASE=Yepp YP-ST5 usb:v04E8p5026* ID_MODEL_FROM_DATABASE=YP-MT6V usb:v04E8p5027* ID_MODEL_FROM_DATABASE=YP-T7 usb:v04E8p502B* ID_MODEL_FROM_DATABASE=YP-F1 usb:v04E8p5032* ID_MODEL_FROM_DATABASE=YP-J70 usb:v04E8p503B* ID_MODEL_FROM_DATABASE=YP-U1 MP3 Player usb:v04E8p503D* ID_MODEL_FROM_DATABASE=YP-T7F usb:v04E8p5041* ID_MODEL_FROM_DATABASE=YP-Z5 usb:v04E8p5050* ID_MODEL_FROM_DATABASE=YP-U2 MP3 Player usb:v04E8p5051* ID_MODEL_FROM_DATABASE=YP-F2R usb:v04E8p5055* ID_MODEL_FROM_DATABASE=YP-T9 usb:v04E8p507D* ID_MODEL_FROM_DATABASE=YP-U3 (mtp) usb:v04E8p507F* ID_MODEL_FROM_DATABASE=YP-T9J usb:v04E8p5080* ID_MODEL_FROM_DATABASE=Yepp YP-K3 (msc) usb:v04E8p5081* ID_MODEL_FROM_DATABASE=Yepp YP-K3 (mtp) usb:v04E8p5082* ID_MODEL_FROM_DATABASE=YP-P2 (msc) usb:v04E8p5083* ID_MODEL_FROM_DATABASE=YP-P2 (mtp) usb:v04E8p508A* ID_MODEL_FROM_DATABASE=YP-T10 usb:v04E8p508B* ID_MODEL_FROM_DATABASE=YP-S5 MP3 Player usb:v04E8p508C* ID_MODEL_FROM_DATABASE=YP-S5 usb:v04E8p5090* ID_MODEL_FROM_DATABASE=YP-S3 (msc) usb:v04E8p5091* ID_MODEL_FROM_DATABASE=YP-S3 (mtp) usb:v04E8p5092* ID_MODEL_FROM_DATABASE=YP-U4 (msc) usb:v04E8p5093* ID_MODEL_FROM_DATABASE=YP-U4 (mtp) usb:v04E8p5095* ID_MODEL_FROM_DATABASE=YP-S2 usb:v04E8p510F* ID_MODEL_FROM_DATABASE=YP-R1 usb:v04E8p5119* ID_MODEL_FROM_DATABASE=Yepp YP-P3 usb:v04E8p511C* ID_MODEL_FROM_DATABASE=YP-Q2 usb:v04E8p5121* ID_MODEL_FROM_DATABASE=YP-U5 usb:v04E8p5123* ID_MODEL_FROM_DATABASE=Yepp YP-M1 usb:v04E8p5A00* ID_MODEL_FROM_DATABASE=YP-NEU usb:v04E8p5A01* ID_MODEL_FROM_DATABASE=YP-NDU usb:v04E8p5A03* ID_MODEL_FROM_DATABASE=Yepp MP3 Player usb:v04E8p5A04* ID_MODEL_FROM_DATABASE=YP-800 usb:v04E8p5A08* ID_MODEL_FROM_DATABASE=YP-90 usb:v04E8p5A0F* ID_MODEL_FROM_DATABASE=Meizu M6 MiniPlayer usb:v04E8p5B01* ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer usb:v04E8p5B02* ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer usb:v04E8p5B03* ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer usb:v04E8p5B04* ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer usb:v04E8p5B05* ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer usb:v04E8p5B11* ID_MODEL_FROM_DATABASE=SEW-2001u Card usb:v04E8p5F00* ID_MODEL_FROM_DATABASE=NEXiO Sync usb:v04E8p5F01* ID_MODEL_FROM_DATABASE=NEXiO Sync usb:v04E8p5F02* ID_MODEL_FROM_DATABASE=NEXiO Sync usb:v04E8p5F03* ID_MODEL_FROM_DATABASE=NEXiO Sync usb:v04E8p5F04* ID_MODEL_FROM_DATABASE=NEXiO Sync usb:v04E8p5F05* ID_MODEL_FROM_DATABASE=STORY Station 1TB usb:v04E8p6032* ID_MODEL_FROM_DATABASE=G2 Portable hard drive usb:v04E8p6033* ID_MODEL_FROM_DATABASE=G2 Portable device usb:v04E8p6034* ID_MODEL_FROM_DATABASE=G2 Portable hard drive usb:v04E8p60B3* ID_MODEL_FROM_DATABASE=M2 Portable Hard Drive usb:v04E8p60C4* ID_MODEL_FROM_DATABASE=M2 Portable Hard Drive USB 3.0 usb:v04E8p6124* ID_MODEL_FROM_DATABASE=D3 Station External Hard Drive usb:v04E8p6125* ID_MODEL_FROM_DATABASE=D3 Station External Hard Drive usb:v04E8p61B5* ID_MODEL_FROM_DATABASE=M3 Portable Hard Drive 2TB usb:v04E8p61B6* ID_MODEL_FROM_DATABASE=M3 Portable Hard Drive 1TB usb:v04E8p6601* ID_MODEL_FROM_DATABASE=Mobile Phone usb:v04E8p6602* ID_MODEL_FROM_DATABASE=Galaxy usb:v04E8p6603* ID_MODEL_FROM_DATABASE=Galaxy usb:v04E8p6611* ID_MODEL_FROM_DATABASE=MITs Sync usb:v04E8p6613* ID_MODEL_FROM_DATABASE=MITs Sync usb:v04E8p6615* ID_MODEL_FROM_DATABASE=MITs Sync usb:v04E8p6617* ID_MODEL_FROM_DATABASE=MITs Sync usb:v04E8p6619* ID_MODEL_FROM_DATABASE=MITs Sync usb:v04E8p661B* ID_MODEL_FROM_DATABASE=MITs Sync usb:v04E8p661E* ID_MODEL_FROM_DATABASE=Handheld usb:v04E8p6620* ID_MODEL_FROM_DATABASE=Handheld usb:v04E8p6622* ID_MODEL_FROM_DATABASE=Handheld usb:v04E8p6624* ID_MODEL_FROM_DATABASE=Handheld usb:v04E8p662E* ID_MODEL_FROM_DATABASE=MITs Sync usb:v04E8p6630* ID_MODEL_FROM_DATABASE=MITs Sync usb:v04E8p6632* ID_MODEL_FROM_DATABASE=MITs Sync usb:v04E8p663E* ID_MODEL_FROM_DATABASE=D900e/B2100 Phone usb:v04E8p663F* ID_MODEL_FROM_DATABASE=SGH-E720/SGH-E840 usb:v04E8p6640* ID_MODEL_FROM_DATABASE=Usb Modem Enumerator usb:v04E8p6651* ID_MODEL_FROM_DATABASE=i8510 Innov8 usb:v04E8p6702* ID_MODEL_FROM_DATABASE=X830 usb:v04E8p6708* ID_MODEL_FROM_DATABASE=U600 Phone usb:v04E8p6709* ID_MODEL_FROM_DATABASE=U600 usb:v04E8p6734* ID_MODEL_FROM_DATABASE=Juke usb:v04E8p6759* ID_MODEL_FROM_DATABASE=D900e/B2100 Media Player usb:v04E8p675A* ID_MODEL_FROM_DATABASE=D900e/B2100 Mass Storage usb:v04E8p675B* ID_MODEL_FROM_DATABASE=D900e Camera usb:v04E8p6772* ID_MODEL_FROM_DATABASE=Standalone LTE device (Trial) usb:v04E8p6795* ID_MODEL_FROM_DATABASE=S5230 usb:v04E8p6802* ID_MODEL_FROM_DATABASE=Standalone HSPA device usb:v04E8p6806* ID_MODEL_FROM_DATABASE=Composite LTE device (Trial) usb:v04E8p6807* ID_MODEL_FROM_DATABASE=Composite HSPA device usb:v04E8p681C* ID_MODEL_FROM_DATABASE=Galaxy Portal/Spica/S usb:v04E8p681D* ID_MODEL_FROM_DATABASE=Galaxy Portal/Spica Android Phone usb:v04E8p6843* ID_MODEL_FROM_DATABASE=E2530 Phone (Samsung Kies mode) usb:v04E8p684E* ID_MODEL_FROM_DATABASE=Wave (GT-S8500) usb:v04E8p685B* ID_MODEL_FROM_DATABASE=GT-I9100 Phone [Galaxy S II] (mass storage mode) usb:v04E8p685C* ID_MODEL_FROM_DATABASE=GT-I9250 Phone [Galaxy Nexus] (Mass storage mode) usb:v04E8p685D* ID_MODEL_FROM_DATABASE=GT-I9100 Phone [Galaxy S II] (Download mode) usb:v04E8p685E* ID_MODEL_FROM_DATABASE=GT-I9100 / GT-C3350 Phones (USB Debugging mode) usb:v04E8p6860* ID_MODEL_FROM_DATABASE=Galaxy (MTP) usb:v04E8p6863* ID_MODEL_FROM_DATABASE=GT-I9500 [Galaxy S4] / GT-I9250 [Galaxy Nexus] (network tethering) usb:v04E8p6864* ID_MODEL_FROM_DATABASE=GT-I9070 (network tethering, USB debugging enabled) usb:v04E8p6865* ID_MODEL_FROM_DATABASE=GT-I9300 Phone [Galaxy S III] (PTP mode) usb:v04E8p6866* ID_MODEL_FROM_DATABASE=GT-I9300 Phone [Galaxy S III] (debugging mode) usb:v04E8p6868* ID_MODEL_FROM_DATABASE=Escape Composite driver for Android Phones: Modem+Diagnostic+ADB usb:v04E8p6875* ID_MODEL_FROM_DATABASE=GT-B3710 Standalone LTE device (Commercial) usb:v04E8p6876* ID_MODEL_FROM_DATABASE=GT-B3710 LTE Modem usb:v04E8p6877* ID_MODEL_FROM_DATABASE=Galaxy S usb:v04E8p687A* ID_MODEL_FROM_DATABASE=GT-E2370 mobile phone usb:v04E8p6888* ID_MODEL_FROM_DATABASE=GT-B3730 Composite LTE device (Commercial) usb:v04E8p6889* ID_MODEL_FROM_DATABASE=GT-B3730 Composite LTE device (Commercial) usb:v04E8p689A* ID_MODEL_FROM_DATABASE=LTE Storage Driver [CMC2xx] usb:v04E8p689E* ID_MODEL_FROM_DATABASE=GT-S5670 [Galaxy Fit] usb:v04E8p68AA* ID_MODEL_FROM_DATABASE=Reality usb:v04E8p7011* ID_MODEL_FROM_DATABASE=SEW-2003U Card usb:v04E8p7021* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v04E8p7061* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v04E8p7080* ID_MODEL_FROM_DATABASE=Anycall SCH-W580 usb:v04E8p7081* ID_MODEL_FROM_DATABASE=Human Interface Device usb:v04E8p8001* ID_MODEL_FROM_DATABASE=Handheld usb:v04E8pE020* ID_MODEL_FROM_DATABASE=SERI E02 SCOM 6200 UMTS Phone usb:v04E8pE021* ID_MODEL_FROM_DATABASE=SERI E02 SCOM 6200 Virtual UARTs usb:v04E8pE022* ID_MODEL_FROM_DATABASE=SERI E02 SCOM 6200 Flash Load Disk usb:v04E8pF000* ID_MODEL_FROM_DATABASE=Intensity 3 (Mass Storage Mode) usb:v04E8pFF30* ID_MODEL_FROM_DATABASE=SG_iMON usb:v04E9* ID_VENDOR_FROM_DATABASE=PC-Tel, Inc. usb:v04EA* ID_VENDOR_FROM_DATABASE=Brooktree Corp. usb:v04EB* ID_VENDOR_FROM_DATABASE=Northstar Systems, Inc. usb:v04EBpE004* ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver usb:v04EC* ID_VENDOR_FROM_DATABASE=Tokyo Electron Device, Ltd usb:v04ED* ID_VENDOR_FROM_DATABASE=Annabooks usb:v04EF* ID_VENDOR_FROM_DATABASE=Pacific Electronic International, Inc. usb:v04F0* ID_VENDOR_FROM_DATABASE=Daewoo Electronics Co., Ltd usb:v04F1* ID_VENDOR_FROM_DATABASE=Victor Company of Japan, Ltd usb:v04F1p0001* ID_MODEL_FROM_DATABASE=GC-QX3 Digital Still Camera usb:v04F1p0004* ID_MODEL_FROM_DATABASE=GR-DVL815U Digital Video Camera usb:v04F1p0006* ID_MODEL_FROM_DATABASE=DV Camera Storage usb:v04F1p0008* ID_MODEL_FROM_DATABASE=GZ-MG30AA/MC500E Digital Video Camera usb:v04F1p0009* ID_MODEL_FROM_DATABASE=GR-DX25EK Digital Video Camera usb:v04F1p000A* ID_MODEL_FROM_DATABASE=GR-D72 Digital Video Camera usb:v04F1p1001* ID_MODEL_FROM_DATABASE=GC-A50 Camera Device usb:v04F1p3008* ID_MODEL_FROM_DATABASE=MP-PRX1 Ethernet usb:v04F1p3009* ID_MODEL_FROM_DATABASE=MP-XP7250 WLAN Adapter usb:v04F2* ID_VENDOR_FROM_DATABASE=Chicony Electronics Co., Ltd usb:v04F2p0001* ID_MODEL_FROM_DATABASE=KU-8933 Keyboard usb:v04F2p0002* ID_MODEL_FROM_DATABASE=NT68P81 Keyboard usb:v04F2p0110* ID_MODEL_FROM_DATABASE=KU-2971 Keyboard usb:v04F2p0111* ID_MODEL_FROM_DATABASE=KU-9908 Keyboard usb:v04F2p0112* ID_MODEL_FROM_DATABASE=KU-8933 Keyboard with PS/2 Mouse port usb:v04F2p0116* ID_MODEL_FROM_DATABASE=KU-2971/KU-0325 Keyboard usb:v04F2p0200* ID_MODEL_FROM_DATABASE=KBR-0108 usb:v04F2p0201* ID_MODEL_FROM_DATABASE=Gaming Keyboard KPD0250 usb:v04F2p0220* ID_MODEL_FROM_DATABASE=Wireless HID Receiver usb:v04F2p0402* ID_MODEL_FROM_DATABASE=Genius LuxeMate i200 Keyboard usb:v04F2p0403* ID_MODEL_FROM_DATABASE=KU-0420 keyboard usb:v04F2p0418* ID_MODEL_FROM_DATABASE=KU-0418 Tactical Pad usb:v04F2p0618* ID_MODEL_FROM_DATABASE=RG-0618U Wireless HID Receiver & KG-0609 Wireless Keyboard with Touchpad usb:v04F2p0760* ID_MODEL_FROM_DATABASE=Acer KU-0760 Keyboard usb:v04F2p0841* ID_MODEL_FROM_DATABASE=HP Multimedia Keyboard usb:v04F2p0860* ID_MODEL_FROM_DATABASE=2.4G Multimedia Wireless Kit usb:v04F2p1061* ID_MODEL_FROM_DATABASE=HP KG-1061 Wireless Keyboard+Mouse usb:v04F2p1121* ID_MODEL_FROM_DATABASE=Periboard 717 Mini Wireless Keyboard usb:v04F2pA001* ID_MODEL_FROM_DATABASE=E-Video DC-100 Camera usb:v04F2pA120* ID_MODEL_FROM_DATABASE=ORITE CCD Webcam(PC370R) usb:v04F2pA121* ID_MODEL_FROM_DATABASE=ORITE CCD Webcam(PC370R) usb:v04F2pA122* ID_MODEL_FROM_DATABASE=ORITE CCD Webcam(PC370R) usb:v04F2pA123* ID_MODEL_FROM_DATABASE=ORITE CCD Webcam(PC370R) usb:v04F2pA124* ID_MODEL_FROM_DATABASE=ORITE CCD Webcam(PC370R) usb:v04F2pA128* ID_MODEL_FROM_DATABASE=PC Camera (SN9C202 + OV7663 + EEPROM) usb:v04F2pA133* ID_MODEL_FROM_DATABASE=Gateway Webcam usb:v04F2pA136* ID_MODEL_FROM_DATABASE=LabTec Webcam 5500 usb:v04F2pA147* ID_MODEL_FROM_DATABASE=Medion Webcam usb:v04F2pA204* ID_MODEL_FROM_DATABASE=DSC WIA Device (1300) usb:v04F2pA208* ID_MODEL_FROM_DATABASE=DSC WIA Device (2320) usb:v04F2pA209* ID_MODEL_FROM_DATABASE=Labtec DC-2320 usb:v04F2pA20A* ID_MODEL_FROM_DATABASE=DSC WIA Device (3310) usb:v04F2pA20C* ID_MODEL_FROM_DATABASE=DSC WIA Device (3320) usb:v04F2pA210* ID_MODEL_FROM_DATABASE=Audio Device usb:v04F2pB008* ID_MODEL_FROM_DATABASE=USB 2.0 Camera usb:v04F2pB009* ID_MODEL_FROM_DATABASE=Integrated Camera usb:v04F2pB010* ID_MODEL_FROM_DATABASE=Integrated Camera usb:v04F2pB012* ID_MODEL_FROM_DATABASE=1.3 MPixel UVC Webcam usb:v04F2pB013* ID_MODEL_FROM_DATABASE=USB 2.0 Camera usb:v04F2pB015* ID_MODEL_FROM_DATABASE=VGA 24fps UVC Webcam usb:v04F2pB016* ID_MODEL_FROM_DATABASE=VGA 30fps UVC Webcam usb:v04F2pB018* ID_MODEL_FROM_DATABASE=2M UVC Webcam usb:v04F2pB021* ID_MODEL_FROM_DATABASE=ViewSonic 1.3M, USB2.0 Webcam usb:v04F2pB022* ID_MODEL_FROM_DATABASE=Gateway USB 2.0 Webcam usb:v04F2pB023* ID_MODEL_FROM_DATABASE=Gateway USB 2.0 Webcam usb:v04F2pB024* ID_MODEL_FROM_DATABASE=USB 2.0 Webcam usb:v04F2pB025* ID_MODEL_FROM_DATABASE=Camera usb:v04F2pB027* ID_MODEL_FROM_DATABASE=Gateway USB 2.0 Webcam usb:v04F2pB028* ID_MODEL_FROM_DATABASE=VGA UVC Webcam usb:v04F2pB029* ID_MODEL_FROM_DATABASE=1.3M UVC Webcam usb:v04F2pB036* ID_MODEL_FROM_DATABASE=Asus Integrated 0.3M UVC Webcam usb:v04F2pB044* ID_MODEL_FROM_DATABASE=Acer CrystalEye Webcam usb:v04F2pB057* ID_MODEL_FROM_DATABASE=integrated USB webcam usb:v04F2pB059* ID_MODEL_FROM_DATABASE=CKF7037 HP webcam usb:v04F2pB064* ID_MODEL_FROM_DATABASE=CNA7137 Integrated Webcam usb:v04F2pB070* ID_MODEL_FROM_DATABASE=Camera usb:v04F2pB071* ID_MODEL_FROM_DATABASE=2.0M UVC Webcam / CNF7129 usb:v04F2pB083* ID_MODEL_FROM_DATABASE=CKF7063 Webcam (HP) usb:v04F2pB091* ID_MODEL_FROM_DATABASE=Webcam usb:v04F2pB104* ID_MODEL_FROM_DATABASE=CNF7069 Webcam usb:v04F2pB107* ID_MODEL_FROM_DATABASE=CNF7070 Webcam usb:v04F2pB14C* ID_MODEL_FROM_DATABASE=CNF8050 Webcam usb:v04F2pB15C* ID_MODEL_FROM_DATABASE=Sony Vaio Integrated Camera usb:v04F2pB175* ID_MODEL_FROM_DATABASE=4-Port Hub usb:v04F2pB1AA* ID_MODEL_FROM_DATABASE=Webcam-101 usb:v04F2pB1B4* ID_MODEL_FROM_DATABASE=Lenovo Integrated Camera usb:v04F2pB1B9* ID_MODEL_FROM_DATABASE=Asus Integrated Webcam usb:v04F2pB1CF* ID_MODEL_FROM_DATABASE=Lenovo Integrated Camera usb:v04F2pB1D6* ID_MODEL_FROM_DATABASE=CNF9055 Toshiba Webcam usb:v04F2pB1E4* ID_MODEL_FROM_DATABASE=Toshiba Integrated Webcam usb:v04F2pB213* ID_MODEL_FROM_DATABASE=Fujitsu Integrated Camera usb:v04F2pB217* ID_MODEL_FROM_DATABASE=Lenovo Integrated Camera (0.3MP) usb:v04F2pB221* ID_MODEL_FROM_DATABASE=integrated camera usb:v04F2pB230* ID_MODEL_FROM_DATABASE=Integrated HP HD Webcam usb:v04F2pB257* ID_MODEL_FROM_DATABASE=Lenovo Integrated Camera usb:v04F2pB26B* ID_MODEL_FROM_DATABASE=Sony Visual Communication Camera usb:v04F2pB272* ID_MODEL_FROM_DATABASE=Lenovo EasyCamera usb:v04F2pB2B0* ID_MODEL_FROM_DATABASE=Camera usb:v04F2pB2B9* ID_MODEL_FROM_DATABASE=Lenovo Integrated Camera UVC usb:v04F2pB2DA* ID_MODEL_FROM_DATABASE=thinkpad t430s camera usb:v04F2pB2EA* ID_MODEL_FROM_DATABASE=Integrated Camera [ThinkPad] usb:v04F2pB330* ID_MODEL_FROM_DATABASE=Asus 720p CMOS webcam usb:v04F2pB354* ID_MODEL_FROM_DATABASE=UVC 1.00 device HD UVC WebCam usb:v04F2pB394* ID_MODEL_FROM_DATABASE=Integrated Camera usb:v04F2pB3F6* ID_MODEL_FROM_DATABASE=HD WebCam (Acer) usb:v04F2pB40E* ID_MODEL_FROM_DATABASE=HP Truevision HD camera usb:v04F2pB444* ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam usb:v04F3* ID_VENDOR_FROM_DATABASE=Elan Microelectronics Corp. usb:v04F3p000A* ID_MODEL_FROM_DATABASE=Touchscreen usb:v04F3p0103* ID_MODEL_FROM_DATABASE=ActiveJet K-2024 Multimedia Keyboard usb:v04F3p01A4* ID_MODEL_FROM_DATABASE=Wireless Keyboard usb:v04F3p0201* ID_MODEL_FROM_DATABASE=Touchscreen usb:v04F3p0210* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v04F3p0212* ID_MODEL_FROM_DATABASE=Laser Mouse usb:v04F3p0214* ID_MODEL_FROM_DATABASE=Lynx M9 Optical Mouse usb:v04F3p0230* ID_MODEL_FROM_DATABASE=3D Optical Mouse usb:v04F3p0232* ID_MODEL_FROM_DATABASE=Mouse usb:v04F3p02F4* ID_MODEL_FROM_DATABASE=2.4G Cordless Mouse usb:v04F3p0381* ID_MODEL_FROM_DATABASE=Touchscreen usb:v04F3p04A0* ID_MODEL_FROM_DATABASE=Dream Cheeky Stress/Panic Button usb:v04F4* ID_VENDOR_FROM_DATABASE=Harting Elektronik, Inc. usb:v04F5* ID_VENDOR_FROM_DATABASE=Fujitsu-ICL Systems, Inc. usb:v04F6* ID_VENDOR_FROM_DATABASE=Norand Corp. usb:v04F7* ID_VENDOR_FROM_DATABASE=Newnex Technology Corp. usb:v04F8* ID_VENDOR_FROM_DATABASE=FuturePlus Systems usb:v04F9* ID_VENDOR_FROM_DATABASE=Brother Industries, Ltd usb:v04F9p0002* ID_MODEL_FROM_DATABASE=HL-1050 Laser Printer usb:v04F9p0005* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0006* ID_MODEL_FROM_DATABASE=HL-1240 Laser Printer usb:v04F9p0007* ID_MODEL_FROM_DATABASE=HL-1250 Laser Printer usb:v04F9p0008* ID_MODEL_FROM_DATABASE=HL-1270 Laser Printer usb:v04F9p0009* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p000A* ID_MODEL_FROM_DATABASE=P2500 series usb:v04F9p000B* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p000C* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p000D* ID_MODEL_FROM_DATABASE=HL-1440 Laser Printer usb:v04F9p000E* ID_MODEL_FROM_DATABASE=HL-1450 series usb:v04F9p000F* ID_MODEL_FROM_DATABASE=HL-1470N series usb:v04F9p0010* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0011* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0012* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0013* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0014* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0015* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0016* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0017* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0018* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p001A* ID_MODEL_FROM_DATABASE=HL-1430 Laser Printer usb:v04F9p001C* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p001E* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0020* ID_MODEL_FROM_DATABASE=HL-5130 series usb:v04F9p0021* ID_MODEL_FROM_DATABASE=HL-5140 series usb:v04F9p0022* ID_MODEL_FROM_DATABASE=HL-5150D series usb:v04F9p0023* ID_MODEL_FROM_DATABASE=HL-5170DN series usb:v04F9p0024* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0025* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0027* ID_MODEL_FROM_DATABASE=HL-2030 Laser Printer usb:v04F9p0028* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0029* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p002A* ID_MODEL_FROM_DATABASE=HL-52x0 series usb:v04F9p002B* ID_MODEL_FROM_DATABASE=HL-5250DN Printer usb:v04F9p002C* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p002D* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p0039* ID_MODEL_FROM_DATABASE=HL-5340 series usb:v04F9p0042* ID_MODEL_FROM_DATABASE=HL-2270DW Laser Printer usb:v04F9p0100* ID_MODEL_FROM_DATABASE=MFC8600/9650 series usb:v04F9p0101* ID_MODEL_FROM_DATABASE=MFC9600/9870 series usb:v04F9p0102* ID_MODEL_FROM_DATABASE=MFC9750/1200 series usb:v04F9p0104* ID_MODEL_FROM_DATABASE=MFC-8300J usb:v04F9p0105* ID_MODEL_FROM_DATABASE=MFC-9600J usb:v04F9p0106* ID_MODEL_FROM_DATABASE=MFC-7300C usb:v04F9p0107* ID_MODEL_FROM_DATABASE=MFC-7400C usb:v04F9p0108* ID_MODEL_FROM_DATABASE=MFC-9200C usb:v04F9p0109* ID_MODEL_FROM_DATABASE=MFC-830 usb:v04F9p010A* ID_MODEL_FROM_DATABASE=MFC-840 usb:v04F9p010B* ID_MODEL_FROM_DATABASE=MFC-860 usb:v04F9p010C* ID_MODEL_FROM_DATABASE=MFC-7400J usb:v04F9p010D* ID_MODEL_FROM_DATABASE=MFC-9200J usb:v04F9p010E* ID_MODEL_FROM_DATABASE=MFC-3100C Scanner usb:v04F9p010F* ID_MODEL_FROM_DATABASE=MFC-5100C usb:v04F9p0110* ID_MODEL_FROM_DATABASE=MFC-4800 Scanner usb:v04F9p0111* ID_MODEL_FROM_DATABASE=MFC-6800 usb:v04F9p0112* ID_MODEL_FROM_DATABASE=DCP1000 Port(FaxModem) usb:v04F9p0113* ID_MODEL_FROM_DATABASE=MFC-8500 usb:v04F9p0114* ID_MODEL_FROM_DATABASE=MFC9700 Port(FaxModem) usb:v04F9p0115* ID_MODEL_FROM_DATABASE=MFC-9800 Scanner usb:v04F9p0116* ID_MODEL_FROM_DATABASE=DCP1400 Scanner usb:v04F9p0119* ID_MODEL_FROM_DATABASE=MFC-9660 usb:v04F9p011A* ID_MODEL_FROM_DATABASE=MFC-9860 usb:v04F9p011B* ID_MODEL_FROM_DATABASE=MFC-9880 usb:v04F9p011C* ID_MODEL_FROM_DATABASE=MFC-9760 usb:v04F9p011D* ID_MODEL_FROM_DATABASE=MFC-9070 usb:v04F9p011E* ID_MODEL_FROM_DATABASE=MFC-9180 usb:v04F9p011F* ID_MODEL_FROM_DATABASE=MFC-9160 usb:v04F9p0120* ID_MODEL_FROM_DATABASE=MFC580 Port(FaxModem) usb:v04F9p0121* ID_MODEL_FROM_DATABASE=MFC-590 usb:v04F9p0122* ID_MODEL_FROM_DATABASE=MFC-5100J usb:v04F9p0124* ID_MODEL_FROM_DATABASE=MFC-4800J usb:v04F9p0125* ID_MODEL_FROM_DATABASE=MFC-6800J usb:v04F9p0127* ID_MODEL_FROM_DATABASE=MFC-9800J usb:v04F9p0128* ID_MODEL_FROM_DATABASE=MFC-8500J usb:v04F9p0129* ID_MODEL_FROM_DATABASE=Imagistics 2500 (MFC-8640D clone) usb:v04F9p012B* ID_MODEL_FROM_DATABASE=MFC-9030 usb:v04F9p012E* ID_MODEL_FROM_DATABASE=FAX4100e IntelliFax 4100e usb:v04F9p012F* ID_MODEL_FROM_DATABASE=FAX-4750e usb:v04F9p0130* ID_MODEL_FROM_DATABASE=FAX-5750e usb:v04F9p0132* ID_MODEL_FROM_DATABASE=MFC-5200C RemovableDisk usb:v04F9p0135* ID_MODEL_FROM_DATABASE=MFC-100 Scanner usb:v04F9p0136* ID_MODEL_FROM_DATABASE=MFC-150CL Scanner usb:v04F9p013C* ID_MODEL_FROM_DATABASE=MFC-890 Port usb:v04F9p013D* ID_MODEL_FROM_DATABASE=MFC-5200J usb:v04F9p013E* ID_MODEL_FROM_DATABASE=MFC-4420C RemovableDisk usb:v04F9p013F* ID_MODEL_FROM_DATABASE=MFC-4820C RemovableDisk usb:v04F9p0140* ID_MODEL_FROM_DATABASE=DCP-8020 usb:v04F9p0141* ID_MODEL_FROM_DATABASE=DCP-8025D usb:v04F9p0142* ID_MODEL_FROM_DATABASE=MFC-8420 usb:v04F9p0143* ID_MODEL_FROM_DATABASE=MFC-8820D usb:v04F9p0144* ID_MODEL_FROM_DATABASE=DCP-4020C RemovableDisk usb:v04F9p0146* ID_MODEL_FROM_DATABASE=MFC-3220C usb:v04F9p0147* ID_MODEL_FROM_DATABASE=FAX-1820C Printer usb:v04F9p0148* ID_MODEL_FROM_DATABASE=MFC-3320CN usb:v04F9p0149* ID_MODEL_FROM_DATABASE=FAX-1920CN Printer usb:v04F9p014A* ID_MODEL_FROM_DATABASE=MFC-3420C usb:v04F9p014B* ID_MODEL_FROM_DATABASE=MFC-3820CN usb:v04F9p014C* ID_MODEL_FROM_DATABASE=DCP-3020C usb:v04F9p014D* ID_MODEL_FROM_DATABASE=FAX-1815C Printer usb:v04F9p014E* ID_MODEL_FROM_DATABASE=MFC-8820J usb:v04F9p014F* ID_MODEL_FROM_DATABASE=DCP-8025J usb:v04F9p0150* ID_MODEL_FROM_DATABASE=MFC-8220 Port(FaxModem) usb:v04F9p0151* ID_MODEL_FROM_DATABASE=MFC-8210J usb:v04F9p0153* ID_MODEL_FROM_DATABASE=DCP-1000J usb:v04F9p0157* ID_MODEL_FROM_DATABASE=MFC-3420J Printer usb:v04F9p0158* ID_MODEL_FROM_DATABASE=MFC-3820JN Port(FaxModem) usb:v04F9p015D* ID_MODEL_FROM_DATABASE=MFC Composite Device usb:v04F9p015E* ID_MODEL_FROM_DATABASE=DCP-8045D usb:v04F9p015F* ID_MODEL_FROM_DATABASE=MFC-8440 usb:v04F9p0160* ID_MODEL_FROM_DATABASE=MFC-8840D usb:v04F9p0161* ID_MODEL_FROM_DATABASE=MFC-210C usb:v04F9p0162* ID_MODEL_FROM_DATABASE=MFC-420CN Remote Setup Port usb:v04F9p0163* ID_MODEL_FROM_DATABASE=MFC-410CN RemovableDisk usb:v04F9p0165* ID_MODEL_FROM_DATABASE=MFC-620CN usb:v04F9p0166* ID_MODEL_FROM_DATABASE=MFC-610CLN RemovableDisk usb:v04F9p0168* ID_MODEL_FROM_DATABASE=MFC-620CLN usb:v04F9p0169* ID_MODEL_FROM_DATABASE=DCP-110C RemovableDisk usb:v04F9p016B* ID_MODEL_FROM_DATABASE=DCP-310CN RemovableDisk usb:v04F9p016C* ID_MODEL_FROM_DATABASE=FAX-2440C Printer usb:v04F9p016D* ID_MODEL_FROM_DATABASE=MFC-5440CN usb:v04F9p016E* ID_MODEL_FROM_DATABASE=MFC-5840CN Remote Setup Port usb:v04F9p0170* ID_MODEL_FROM_DATABASE=FAX-1840C Printer usb:v04F9p0171* ID_MODEL_FROM_DATABASE=FAX-1835C Printer usb:v04F9p0172* ID_MODEL_FROM_DATABASE=FAX-1940CN Printer usb:v04F9p0173* ID_MODEL_FROM_DATABASE=MFC-3240C Remote Setup Port usb:v04F9p0174* ID_MODEL_FROM_DATABASE=MFC-3340CN RemovableDisk usb:v04F9p017B* ID_MODEL_FROM_DATABASE=Imagistics sx2100 usb:v04F9p0180* ID_MODEL_FROM_DATABASE=MFC-7420 usb:v04F9p0181* ID_MODEL_FROM_DATABASE=MFC-7820N Port(FaxModem) usb:v04F9p0182* ID_MODEL_FROM_DATABASE=DCP-7010 usb:v04F9p0183* ID_MODEL_FROM_DATABASE=DCP-7020 usb:v04F9p0184* ID_MODEL_FROM_DATABASE=DCP-7025 Printer usb:v04F9p0185* ID_MODEL_FROM_DATABASE=MFC-7220 Printer usb:v04F9p0186* ID_MODEL_FROM_DATABASE=Composite Device usb:v04F9p0187* ID_MODEL_FROM_DATABASE=FAX-2820 Printer usb:v04F9p0188* ID_MODEL_FROM_DATABASE=FAX-2920 Printer usb:v04F9p018A* ID_MODEL_FROM_DATABASE=MFC-9420CN usb:v04F9p018C* ID_MODEL_FROM_DATABASE=DCP-115C usb:v04F9p018D* ID_MODEL_FROM_DATABASE=DCP-116C usb:v04F9p018E* ID_MODEL_FROM_DATABASE=DCP-117C usb:v04F9p018F* ID_MODEL_FROM_DATABASE=DCP-118C usb:v04F9p0190* ID_MODEL_FROM_DATABASE=DCP-120C usb:v04F9p0191* ID_MODEL_FROM_DATABASE=DCP-315CN usb:v04F9p0192* ID_MODEL_FROM_DATABASE=DCP-340CW usb:v04F9p0193* ID_MODEL_FROM_DATABASE=MFC-215C usb:v04F9p0194* ID_MODEL_FROM_DATABASE=MFC-425CN usb:v04F9p0195* ID_MODEL_FROM_DATABASE=MFC-820CW Remote Setup Port usb:v04F9p0196* ID_MODEL_FROM_DATABASE=MFC-820CN Remote Setup Port usb:v04F9p0197* ID_MODEL_FROM_DATABASE=MFC-640CW usb:v04F9p019A* ID_MODEL_FROM_DATABASE=MFC-840CLN Remote Setup Port usb:v04F9p01A2* ID_MODEL_FROM_DATABASE=MFC-8640D usb:v04F9p01A3* ID_MODEL_FROM_DATABASE=Composite Device usb:v04F9p01A4* ID_MODEL_FROM_DATABASE=DCP-8065DN Printer usb:v04F9p01A5* ID_MODEL_FROM_DATABASE=MFC-8460N Port(FaxModem) usb:v04F9p01A6* ID_MODEL_FROM_DATABASE=MFC-8860DN Port(FaxModem) usb:v04F9p01A7* ID_MODEL_FROM_DATABASE=MFC-8870DW Printer usb:v04F9p01A8* ID_MODEL_FROM_DATABASE=DCP-130C usb:v04F9p01A9* ID_MODEL_FROM_DATABASE=DCP-330C usb:v04F9p01AA* ID_MODEL_FROM_DATABASE=DCP-540CN usb:v04F9p01AB* ID_MODEL_FROM_DATABASE=MFC-240C usb:v04F9p01AE* ID_MODEL_FROM_DATABASE=DCP-750CW RemovableDisk usb:v04F9p01AF* ID_MODEL_FROM_DATABASE=MFC-440CN usb:v04F9p01B0* ID_MODEL_FROM_DATABASE=MFC-660CN usb:v04F9p01B1* ID_MODEL_FROM_DATABASE=MFC-665CW usb:v04F9p01B2* ID_MODEL_FROM_DATABASE=MFC-845CW usb:v04F9p01B4* ID_MODEL_FROM_DATABASE=MFC-460CN usb:v04F9p01B5* ID_MODEL_FROM_DATABASE=MFC-630CD usb:v04F9p01B6* ID_MODEL_FROM_DATABASE=MFC-850CDN usb:v04F9p01B7* ID_MODEL_FROM_DATABASE=MFC-5460CN usb:v04F9p01B8* ID_MODEL_FROM_DATABASE=MFC-5860CN usb:v04F9p01BA* ID_MODEL_FROM_DATABASE=MFC-3360C usb:v04F9p01BD* ID_MODEL_FROM_DATABASE=MFC-8660DN usb:v04F9p01BE* ID_MODEL_FROM_DATABASE=DCP-750CN RemovableDisk usb:v04F9p01BF* ID_MODEL_FROM_DATABASE=MFC-860CDN usb:v04F9p01C0* ID_MODEL_FROM_DATABASE=DCP-128C usb:v04F9p01C1* ID_MODEL_FROM_DATABASE=DCP-129C usb:v04F9p01C2* ID_MODEL_FROM_DATABASE=DCP-131C usb:v04F9p01C3* ID_MODEL_FROM_DATABASE=DCP-329C usb:v04F9p01C4* ID_MODEL_FROM_DATABASE=DCP-331C usb:v04F9p01C5* ID_MODEL_FROM_DATABASE=MFC-239C usb:v04F9p01C9* ID_MODEL_FROM_DATABASE=DCP-9040CN usb:v04F9p01CA* ID_MODEL_FROM_DATABASE=MFC-9440CN usb:v04F9p01CB* ID_MODEL_FROM_DATABASE=DCP-9045CDN usb:v04F9p01CC* ID_MODEL_FROM_DATABASE=MFC-9840CDW usb:v04F9p01CE* ID_MODEL_FROM_DATABASE=DCP-135C usb:v04F9p01CF* ID_MODEL_FROM_DATABASE=DCP-150C usb:v04F9p01D0* ID_MODEL_FROM_DATABASE=DCP-350C usb:v04F9p01D1* ID_MODEL_FROM_DATABASE=DCP-560CN usb:v04F9p01D2* ID_MODEL_FROM_DATABASE=DCP-770CW usb:v04F9p01D3* ID_MODEL_FROM_DATABASE=DCP-770CN usb:v04F9p01D4* ID_MODEL_FROM_DATABASE=MFC-230C usb:v04F9p01D5* ID_MODEL_FROM_DATABASE=MFC-235C usb:v04F9p01D6* ID_MODEL_FROM_DATABASE=MFC-260C usb:v04F9p01D7* ID_MODEL_FROM_DATABASE=MFC-465CN usb:v04F9p01D8* ID_MODEL_FROM_DATABASE=MFC-680CN usb:v04F9p01D9* ID_MODEL_FROM_DATABASE=MFC-685CW usb:v04F9p01DA* ID_MODEL_FROM_DATABASE=MFC-885CW usb:v04F9p01DB* ID_MODEL_FROM_DATABASE=MFC-480CN usb:v04F9p01DC* ID_MODEL_FROM_DATABASE=MFC-650CD usb:v04F9p01DD* ID_MODEL_FROM_DATABASE=MFC-870CDN usb:v04F9p01DE* ID_MODEL_FROM_DATABASE=MFC-880CDN usb:v04F9p01DF* ID_MODEL_FROM_DATABASE=DCP-155C usb:v04F9p01E0* ID_MODEL_FROM_DATABASE=MFC-265C usb:v04F9p01E1* ID_MODEL_FROM_DATABASE=DCP-153C usb:v04F9p01E2* ID_MODEL_FROM_DATABASE=DCP-157C usb:v04F9p01E3* ID_MODEL_FROM_DATABASE=DCP-353C usb:v04F9p01E4* ID_MODEL_FROM_DATABASE=DCP-357C usb:v04F9p01E7* ID_MODEL_FROM_DATABASE=MFC-7340 usb:v04F9p01E9* ID_MODEL_FROM_DATABASE=DCP-7040 usb:v04F9p01EA* ID_MODEL_FROM_DATABASE=DCP-7030 usb:v04F9p01EB* ID_MODEL_FROM_DATABASE=MFC-7320 usb:v04F9p01EC* ID_MODEL_FROM_DATABASE=MFC-9640CW usb:v04F9p01F4* ID_MODEL_FROM_DATABASE=MFC-5890CN usb:v04F9p020A* ID_MODEL_FROM_DATABASE=MFC-8670DN usb:v04F9p020C* ID_MODEL_FROM_DATABASE=DCP-9042CDN usb:v04F9p020D* ID_MODEL_FROM_DATABASE=MFC-9450CDN usb:v04F9p0216* ID_MODEL_FROM_DATABASE=MFC-8880DN usb:v04F9p0217* ID_MODEL_FROM_DATABASE=MFC-8480DN usb:v04F9p0219* ID_MODEL_FROM_DATABASE=MFC-8380DN usb:v04F9p021A* ID_MODEL_FROM_DATABASE=MFC-8370DN usb:v04F9p021B* ID_MODEL_FROM_DATABASE=DCP-8070D usb:v04F9p021C* ID_MODEL_FROM_DATABASE=MFC-9320CW usb:v04F9p021D* ID_MODEL_FROM_DATABASE=MFC-9120CN usb:v04F9p021E* ID_MODEL_FROM_DATABASE=DCP-9010CN usb:v04F9p0220* ID_MODEL_FROM_DATABASE=MFC-9010CN usb:v04F9p0222* ID_MODEL_FROM_DATABASE=DCP-195C usb:v04F9p0223* ID_MODEL_FROM_DATABASE=DCP-365CN usb:v04F9p0224* ID_MODEL_FROM_DATABASE=DCP-375CW usb:v04F9p0225* ID_MODEL_FROM_DATABASE=DCP-395CN usb:v04F9p0227* ID_MODEL_FROM_DATABASE=DCP-595CN usb:v04F9p0228* ID_MODEL_FROM_DATABASE=MFC-255CW usb:v04F9p0229* ID_MODEL_FROM_DATABASE=MFC-295CN usb:v04F9p022A* ID_MODEL_FROM_DATABASE=MFC-495CW usb:v04F9p022B* ID_MODEL_FROM_DATABASE=MFC-495CN usb:v04F9p022C* ID_MODEL_FROM_DATABASE=MFC-795CW usb:v04F9p022D* ID_MODEL_FROM_DATABASE=MFC-675CD usb:v04F9p022E* ID_MODEL_FROM_DATABASE=MFC-695CDN usb:v04F9p022F* ID_MODEL_FROM_DATABASE=MFC-735CD usb:v04F9p0230* ID_MODEL_FROM_DATABASE=MFC-935CDN usb:v04F9p0234* ID_MODEL_FROM_DATABASE=DCP-373CW usb:v04F9p0235* ID_MODEL_FROM_DATABASE=DCP-377CW usb:v04F9p0236* ID_MODEL_FROM_DATABASE=DCP-390CN usb:v04F9p0239* ID_MODEL_FROM_DATABASE=MFC-253CW usb:v04F9p023A* ID_MODEL_FROM_DATABASE=MFC-257CW usb:v04F9p023E* ID_MODEL_FROM_DATABASE=DCP-197C usb:v04F9p023F* ID_MODEL_FROM_DATABASE=MFC-8680DN usb:v04F9p0240* ID_MODEL_FROM_DATABASE=MFC-J950DN usb:v04F9p0248* ID_MODEL_FROM_DATABASE=DCP-7055 scanner/printer usb:v04F9p0253* ID_MODEL_FROM_DATABASE=DCP-J125 usb:v04F9p0254* ID_MODEL_FROM_DATABASE=DCP-J315W usb:v04F9p0255* ID_MODEL_FROM_DATABASE=DCP-J515W usb:v04F9p0256* ID_MODEL_FROM_DATABASE=DCP-J515N usb:v04F9p0257* ID_MODEL_FROM_DATABASE=DCP-J715W usb:v04F9p0258* ID_MODEL_FROM_DATABASE=DCP-J715N usb:v04F9p0259* ID_MODEL_FROM_DATABASE=MFC-J220 usb:v04F9p025A* ID_MODEL_FROM_DATABASE=MFC-J410 usb:v04F9p025B* ID_MODEL_FROM_DATABASE=MFC-J265W usb:v04F9p025C* ID_MODEL_FROM_DATABASE=MFC-J415W usb:v04F9p025D* ID_MODEL_FROM_DATABASE=MFC-J615W usb:v04F9p025E* ID_MODEL_FROM_DATABASE=MFC-J615N usb:v04F9p025F* ID_MODEL_FROM_DATABASE=MFC-J700D usb:v04F9p0260* ID_MODEL_FROM_DATABASE=MFC-J800D usb:v04F9p0261* ID_MODEL_FROM_DATABASE=MFC-J850DN usb:v04F9p026B* ID_MODEL_FROM_DATABASE=MFC-J630W usb:v04F9p026D* ID_MODEL_FROM_DATABASE=MFC-J805D usb:v04F9p026E* ID_MODEL_FROM_DATABASE=MFC-J855DN usb:v04F9p026F* ID_MODEL_FROM_DATABASE=MFC-J270W usb:v04F9p0273* ID_MODEL_FROM_DATABASE=DCP-7057 scanner/printer usb:v04F9p0276* ID_MODEL_FROM_DATABASE=MFC-5895CW usb:v04F9p0278* ID_MODEL_FROM_DATABASE=MFC-J410W usb:v04F9p0279* ID_MODEL_FROM_DATABASE=DCP-J525W usb:v04F9p027A* ID_MODEL_FROM_DATABASE=DCP-J525N usb:v04F9p027B* ID_MODEL_FROM_DATABASE=DCP-J725DW usb:v04F9p027C* ID_MODEL_FROM_DATABASE=DCP-J725N usb:v04F9p027D* ID_MODEL_FROM_DATABASE=DCP-J925DW usb:v04F9p027E* ID_MODEL_FROM_DATABASE=MFC-J955DN usb:v04F9p027F* ID_MODEL_FROM_DATABASE=MFC-J280W usb:v04F9p0280* ID_MODEL_FROM_DATABASE=MFC-J435W usb:v04F9p0281* ID_MODEL_FROM_DATABASE=MFC-J430W usb:v04F9p0282* ID_MODEL_FROM_DATABASE=MFC-J625DW usb:v04F9p0283* ID_MODEL_FROM_DATABASE=MFC-J825DW usb:v04F9p0284* ID_MODEL_FROM_DATABASE=MFC-J825N usb:v04F9p0285* ID_MODEL_FROM_DATABASE=MFC-J705D usb:v04F9p0287* ID_MODEL_FROM_DATABASE=MFC-J860DN usb:v04F9p0288* ID_MODEL_FROM_DATABASE=MFC-J5910DW usb:v04F9p0289* ID_MODEL_FROM_DATABASE=MFC-J5910CDW usb:v04F9p028A* ID_MODEL_FROM_DATABASE=DCP-J925N usb:v04F9p028D* ID_MODEL_FROM_DATABASE=MFC-J835DW usb:v04F9p028F* ID_MODEL_FROM_DATABASE=MFC-J425W usb:v04F9p0290* ID_MODEL_FROM_DATABASE=MFC-J432W usb:v04F9p0291* ID_MODEL_FROM_DATABASE=DCP-8110DN usb:v04F9p0292* ID_MODEL_FROM_DATABASE=DCP-8150DN usb:v04F9p0293* ID_MODEL_FROM_DATABASE=DCP-8155DN usb:v04F9p0294* ID_MODEL_FROM_DATABASE=DCP-8250DN usb:v04F9p0295* ID_MODEL_FROM_DATABASE=MFC-8510DN usb:v04F9p0296* ID_MODEL_FROM_DATABASE=MFC-8520DN usb:v04F9p0298* ID_MODEL_FROM_DATABASE=MFC-8910DW usb:v04F9p0299* ID_MODEL_FROM_DATABASE=MFC-8950DW usb:v04F9p029A* ID_MODEL_FROM_DATABASE=MFC-8690DW usb:v04F9p029C* ID_MODEL_FROM_DATABASE=MFC-8515DN usb:v04F9p029E* ID_MODEL_FROM_DATABASE=MFC-9125CN usb:v04F9p029F* ID_MODEL_FROM_DATABASE=MFC-9325CW usb:v04F9p02A0* ID_MODEL_FROM_DATABASE=DCP-J140W usb:v04F9p02A5* ID_MODEL_FROM_DATABASE=MFC-7240 usb:v04F9p02A6* ID_MODEL_FROM_DATABASE=FAX-2940 usb:v04F9p02A7* ID_MODEL_FROM_DATABASE=FAX-2950 usb:v04F9p02A8* ID_MODEL_FROM_DATABASE=MFC-7290 usb:v04F9p02AB* ID_MODEL_FROM_DATABASE=FAX-2990 usb:v04F9p02AC* ID_MODEL_FROM_DATABASE=DCP-8110D usb:v04F9p02AD* ID_MODEL_FROM_DATABASE=MFC-9130CW usb:v04F9p02AE* ID_MODEL_FROM_DATABASE=MFC-9140CDN usb:v04F9p02AF* ID_MODEL_FROM_DATABASE=MFC-9330CDW usb:v04F9p02B0* ID_MODEL_FROM_DATABASE=MFC-9340CDW usb:v04F9p02B1* ID_MODEL_FROM_DATABASE=DCP-9020CDN usb:v04F9p02B2* ID_MODEL_FROM_DATABASE=MFC-J810DN usb:v04F9p02B3* ID_MODEL_FROM_DATABASE=MFC-J4510DW usb:v04F9p02B4* ID_MODEL_FROM_DATABASE=MFC-J4710DW usb:v04F9p02B5* ID_MODEL_FROM_DATABASE=DCP-8112DN usb:v04F9p02B6* ID_MODEL_FROM_DATABASE=DCP-8152DN usb:v04F9p02B7* ID_MODEL_FROM_DATABASE=DCP-8157DN usb:v04F9p02B8* ID_MODEL_FROM_DATABASE=MFC-8512DN usb:v04F9p02BA* ID_MODEL_FROM_DATABASE=MFC-8912DW usb:v04F9p02BB* ID_MODEL_FROM_DATABASE=MFC-8952DW usb:v04F9p02BC* ID_MODEL_FROM_DATABASE=DCP-J540N usb:v04F9p02BD* ID_MODEL_FROM_DATABASE=DCP-J740N usb:v04F9p02BE* ID_MODEL_FROM_DATABASE=MFC-J710D usb:v04F9p02BF* ID_MODEL_FROM_DATABASE=MFC-J840N usb:v04F9p02C0* ID_MODEL_FROM_DATABASE=DCP-J940N usb:v04F9p02C1* ID_MODEL_FROM_DATABASE=MFC-J960DN usb:v04F9p02C2* ID_MODEL_FROM_DATABASE=DCP-J4110DW usb:v04F9p02C3* ID_MODEL_FROM_DATABASE=MFC-J4310DW usb:v04F9p02C4* ID_MODEL_FROM_DATABASE=MFC-J4410DW usb:v04F9p02C5* ID_MODEL_FROM_DATABASE=MFC-J4610DW usb:v04F9p02C6* ID_MODEL_FROM_DATABASE=DCP-J4210N usb:v04F9p02C7* ID_MODEL_FROM_DATABASE=MFC-J4510N usb:v04F9p02C8* ID_MODEL_FROM_DATABASE=MFC-J4910CDW usb:v04F9p02C9* ID_MODEL_FROM_DATABASE=MFC-J4810DN usb:v04F9p02CA* ID_MODEL_FROM_DATABASE=MFC-8712DW usb:v04F9p02CB* ID_MODEL_FROM_DATABASE=MFC-8710DW usb:v04F9p02CC* ID_MODEL_FROM_DATABASE=MFC-J2310 usb:v04F9p02CD* ID_MODEL_FROM_DATABASE=MFC-J2510 usb:v04F9p02CE* ID_MODEL_FROM_DATABASE=DCP-7055W usb:v04F9p02CF* ID_MODEL_FROM_DATABASE=DCP-7057W usb:v04F9p02D0* ID_MODEL_FROM_DATABASE=DCP-1510 usb:v04F9p02D1* ID_MODEL_FROM_DATABASE=MFC-1810 usb:v04F9p02D3* ID_MODEL_FROM_DATABASE=DCP-9020CDW usb:v04F9p02D4* ID_MODEL_FROM_DATABASE=MFC-8810DW usb:v04F9p02DD* ID_MODEL_FROM_DATABASE=DCP-J4215N usb:v04F9p02DE* ID_MODEL_FROM_DATABASE=DCP-J132W usb:v04F9p02DF* ID_MODEL_FROM_DATABASE=DCP-J152W usb:v04F9p02E0* ID_MODEL_FROM_DATABASE=DCP-J152N usb:v04F9p02E1* ID_MODEL_FROM_DATABASE=DCP-J172W usb:v04F9p02E2* ID_MODEL_FROM_DATABASE=DCP-J552DW usb:v04F9p02E3* ID_MODEL_FROM_DATABASE=DCP-J552N usb:v04F9p02E4* ID_MODEL_FROM_DATABASE=DCP-J752DW usb:v04F9p02E5* ID_MODEL_FROM_DATABASE=DCP-J752N usb:v04F9p02E6* ID_MODEL_FROM_DATABASE=DCP-J952N usb:v04F9p02E7* ID_MODEL_FROM_DATABASE=MFC-J245 usb:v04F9p02E8* ID_MODEL_FROM_DATABASE=MFC-J470DW usb:v04F9p02E9* ID_MODEL_FROM_DATABASE=MFC-J475DW usb:v04F9p02EA* ID_MODEL_FROM_DATABASE=MFC-J285DW usb:v04F9p02EB* ID_MODEL_FROM_DATABASE=MFC-J650DW usb:v04F9p02EC* ID_MODEL_FROM_DATABASE=MFC-J870DW usb:v04F9p02ED* ID_MODEL_FROM_DATABASE=MFC-J870N usb:v04F9p02EE* ID_MODEL_FROM_DATABASE=MFC-J720D usb:v04F9p02EF* ID_MODEL_FROM_DATABASE=MFC-J820DN usb:v04F9p02F0* ID_MODEL_FROM_DATABASE=MFC-J980DN usb:v04F9p02F1* ID_MODEL_FROM_DATABASE=MFC-J890DN usb:v04F9p02F2* ID_MODEL_FROM_DATABASE=MFC-J6520DW usb:v04F9p02F3* ID_MODEL_FROM_DATABASE=MFC-J6570CDW usb:v04F9p02F4* ID_MODEL_FROM_DATABASE=MFC-J6720DW usb:v04F9p02F5* ID_MODEL_FROM_DATABASE=MFC-J6920DW usb:v04F9p02F6* ID_MODEL_FROM_DATABASE=MFC-J6970CDW usb:v04F9p02F7* ID_MODEL_FROM_DATABASE=MFC-J6975CDW usb:v04F9p02F8* ID_MODEL_FROM_DATABASE=MFC-J6770CDW usb:v04F9p02F9* ID_MODEL_FROM_DATABASE=DCP-J132N usb:v04F9p02FA* ID_MODEL_FROM_DATABASE=MFC-J450DW usb:v04F9p02FB* ID_MODEL_FROM_DATABASE=MFC-J875DW usb:v04F9p02FC* ID_MODEL_FROM_DATABASE=DCP-J100 usb:v04F9p02FD* ID_MODEL_FROM_DATABASE=DCP-J105 usb:v04F9p02FE* ID_MODEL_FROM_DATABASE=MFC-J200 usb:v04F9p02FF* ID_MODEL_FROM_DATABASE=MFC-J3520 usb:v04F9p0300* ID_MODEL_FROM_DATABASE=MFC-J3720 usb:v04F9p030F* ID_MODEL_FROM_DATABASE=DCP-L8400CDN usb:v04F9p0310* ID_MODEL_FROM_DATABASE=DCP-L8450CDW usb:v04F9p0311* ID_MODEL_FROM_DATABASE=MFC-L8600CDW usb:v04F9p0312* ID_MODEL_FROM_DATABASE=MFC-L8650CDW usb:v04F9p0313* ID_MODEL_FROM_DATABASE=MFC-L8850CDW usb:v04F9p0314* ID_MODEL_FROM_DATABASE=MFC-L9550CDW usb:v04F9p0318* ID_MODEL_FROM_DATABASE=MFC-7365DN usb:v04F9p0320* ID_MODEL_FROM_DATABASE=MFC-L2740DW usb:v04F9p0321* ID_MODEL_FROM_DATABASE=DCP-L2500D usb:v04F9p0322* ID_MODEL_FROM_DATABASE=DCP-L2520DW usb:v04F9p0324* ID_MODEL_FROM_DATABASE=DCP-L2520D usb:v04F9p0326* ID_MODEL_FROM_DATABASE=DCP-L2540DN usb:v04F9p0328* ID_MODEL_FROM_DATABASE=DCP-L2540DW usb:v04F9p0329* ID_MODEL_FROM_DATABASE=DCP-L2560DW usb:v04F9p0330* ID_MODEL_FROM_DATABASE=HL-L2380DW usb:v04F9p0331* ID_MODEL_FROM_DATABASE=MFC-L2700DW usb:v04F9p0335* ID_MODEL_FROM_DATABASE=FAX-L2700DN usb:v04F9p0337* ID_MODEL_FROM_DATABASE=MFC-L2720DW usb:v04F9p0338* ID_MODEL_FROM_DATABASE=MFC-L2720DN usb:v04F9p0339* ID_MODEL_FROM_DATABASE=DCP-J4120DW usb:v04F9p033A* ID_MODEL_FROM_DATABASE=MFC-J4320DW usb:v04F9p033C* ID_MODEL_FROM_DATABASE=MFC-J2320 usb:v04F9p033D* ID_MODEL_FROM_DATABASE=MFC-J4420DW usb:v04F9p0340* ID_MODEL_FROM_DATABASE=MFC-J4620DW usb:v04F9p0341* ID_MODEL_FROM_DATABASE=MFC-J2720 usb:v04F9p0342* ID_MODEL_FROM_DATABASE=MFC-J4625DW usb:v04F9p0343* ID_MODEL_FROM_DATABASE=MFC-J5320DW usb:v04F9p0346* ID_MODEL_FROM_DATABASE=MFC-J5620DW usb:v04F9p0347* ID_MODEL_FROM_DATABASE=MFC-J5720DW usb:v04F9p0349* ID_MODEL_FROM_DATABASE=DCP-J4220N usb:v04F9p034B* ID_MODEL_FROM_DATABASE=MFC-J4720N usb:v04F9p034E* ID_MODEL_FROM_DATABASE=MFC-J5720CDW usb:v04F9p034F* ID_MODEL_FROM_DATABASE=MFC-J5820DN usb:v04F9p0350* ID_MODEL_FROM_DATABASE=MFC-J5620CDW usb:v04F9p0351* ID_MODEL_FROM_DATABASE=DCP-J137N usb:v04F9p0353* ID_MODEL_FROM_DATABASE=DCP-J557N usb:v04F9p0354* ID_MODEL_FROM_DATABASE=DCP-J757N usb:v04F9p0355* ID_MODEL_FROM_DATABASE=DCP-J957N usb:v04F9p0356* ID_MODEL_FROM_DATABASE=MFC-J877N usb:v04F9p0357* ID_MODEL_FROM_DATABASE=MFC-J727D usb:v04F9p0358* ID_MODEL_FROM_DATABASE=MFC-J987DN usb:v04F9p0359* ID_MODEL_FROM_DATABASE=MFC-J827DN usb:v04F9p035A* ID_MODEL_FROM_DATABASE=MFC-J897DN usb:v04F9p035B* ID_MODEL_FROM_DATABASE=DCP-1610W usb:v04F9p035C* ID_MODEL_FROM_DATABASE=DCP-1610NW usb:v04F9p035D* ID_MODEL_FROM_DATABASE=MFC-1910W usb:v04F9p035E* ID_MODEL_FROM_DATABASE=MFC-1910NW usb:v04F9p0360* ID_MODEL_FROM_DATABASE=DCP-1618W usb:v04F9p0361* ID_MODEL_FROM_DATABASE=MFC-1919NW usb:v04F9p0364* ID_MODEL_FROM_DATABASE=MFC-J5625DW usb:v04F9p0365* ID_MODEL_FROM_DATABASE=MFC-J4520DW usb:v04F9p0366* ID_MODEL_FROM_DATABASE=MFC-J5520DW usb:v04F9p0367* ID_MODEL_FROM_DATABASE=DCP-7080D usb:v04F9p0368* ID_MODEL_FROM_DATABASE=DCP-7080 usb:v04F9p0369* ID_MODEL_FROM_DATABASE=DCP-7180DN usb:v04F9p036A* ID_MODEL_FROM_DATABASE=DCP-7189DW usb:v04F9p036B* ID_MODEL_FROM_DATABASE=MFC-7380 usb:v04F9p036C* ID_MODEL_FROM_DATABASE=MFC-7480D usb:v04F9p036D* ID_MODEL_FROM_DATABASE=MFC-7880DN usb:v04F9p036E* ID_MODEL_FROM_DATABASE=MFC-7889DW usb:v04F9p036F* ID_MODEL_FROM_DATABASE=DCP-9022CDW usb:v04F9p0370* ID_MODEL_FROM_DATABASE=MFC-9142CDN usb:v04F9p0371* ID_MODEL_FROM_DATABASE=MFC-9332CDW usb:v04F9p0372* ID_MODEL_FROM_DATABASE=MFC-9342CDW usb:v04F9p0373* ID_MODEL_FROM_DATABASE=MFC-L2700D usb:v04F9p0376* ID_MODEL_FROM_DATABASE=DCP-1600 usb:v04F9p0377* ID_MODEL_FROM_DATABASE=MFC-1900 usb:v04F9p0378* ID_MODEL_FROM_DATABASE=DCP-1608 usb:v04F9p0379* ID_MODEL_FROM_DATABASE=DCP-1619 usb:v04F9p037A* ID_MODEL_FROM_DATABASE=MFC-1906 usb:v04F9p037B* ID_MODEL_FROM_DATABASE=MFC-1908 usb:v04F9p037C* ID_MODEL_FROM_DATABASE=ADS-2000e usb:v04F9p037D* ID_MODEL_FROM_DATABASE=ADS-2100e usb:v04F9p037E* ID_MODEL_FROM_DATABASE=ADS-2500We usb:v04F9p037F* ID_MODEL_FROM_DATABASE=ADS-2600We usb:v04F9p0380* ID_MODEL_FROM_DATABASE=DCP-J562DW usb:v04F9p0381* ID_MODEL_FROM_DATABASE=DCP-J562N usb:v04F9p0383* ID_MODEL_FROM_DATABASE=DCP-J962N usb:v04F9p0384* ID_MODEL_FROM_DATABASE=MFC-J480DW usb:v04F9p0385* ID_MODEL_FROM_DATABASE=MFC-J485DW usb:v04F9p0386* ID_MODEL_FROM_DATABASE=MFC-J460DW usb:v04F9p0388* ID_MODEL_FROM_DATABASE=MFC-J680DW usb:v04F9p0389* ID_MODEL_FROM_DATABASE=MFC-J880DW usb:v04F9p038A* ID_MODEL_FROM_DATABASE=MFC-J885DW usb:v04F9p038B* ID_MODEL_FROM_DATABASE=MFC-J880N usb:v04F9p038C* ID_MODEL_FROM_DATABASE=MFC-J730DN usb:v04F9p038D* ID_MODEL_FROM_DATABASE=MFC-J990DN usb:v04F9p038E* ID_MODEL_FROM_DATABASE=MFC-J830DN usb:v04F9p038F* ID_MODEL_FROM_DATABASE=MFC-J900DN usb:v04F9p0390* ID_MODEL_FROM_DATABASE=MFC-J5920DW usb:v04F9p0392* ID_MODEL_FROM_DATABASE=MFC-L2705DW usb:v04F9p0393* ID_MODEL_FROM_DATABASE=DCP-T300 usb:v04F9p0394* ID_MODEL_FROM_DATABASE=DCP-T500W usb:v04F9p0395* ID_MODEL_FROM_DATABASE=DCP-T700W usb:v04F9p0396* ID_MODEL_FROM_DATABASE=MFC-T800W usb:v04F9p0397* ID_MODEL_FROM_DATABASE=DCP-J963N usb:v04F9p03B3* ID_MODEL_FROM_DATABASE=MFC-J6925DW usb:v04F9p03B4* ID_MODEL_FROM_DATABASE=MFC-J6573CDW usb:v04F9p03B5* ID_MODEL_FROM_DATABASE=MFC-J6973CDW usb:v04F9p03B6* ID_MODEL_FROM_DATABASE=MFC-J6990CDW usb:v04F9p03BB* ID_MODEL_FROM_DATABASE=MFC-L2680W usb:v04F9p03BC* ID_MODEL_FROM_DATABASE=MFC-L2700DN usb:v04F9p03BD* ID_MODEL_FROM_DATABASE=DCP-J762N usb:v04F9p1000* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p1002* ID_MODEL_FROM_DATABASE=Printer usb:v04F9p2002* ID_MODEL_FROM_DATABASE=PTUSB Printing usb:v04F9p2004* ID_MODEL_FROM_DATABASE=PT-2300/2310 p-Touch Laber Printer usb:v04F9p2015* ID_MODEL_FROM_DATABASE=QL-500 P-touch label printer usb:v04F9p2016* ID_MODEL_FROM_DATABASE=QL-550 P-touch label printer usb:v04F9p201A* ID_MODEL_FROM_DATABASE=PT-18R P-touch label printer usb:v04F9p201B* ID_MODEL_FROM_DATABASE=QL-650TD P-Touch Label Printer usb:v04F9p2027* ID_MODEL_FROM_DATABASE=QL-560 P-Touch Label Printer usb:v04F9p202B* ID_MODEL_FROM_DATABASE=PT-7600 P-Touch Label Printer usb:v04F9p2100* ID_MODEL_FROM_DATABASE=Card Reader Writer usb:v04F9p60A0* ID_MODEL_FROM_DATABASE=ADS-2000 usb:v04F9p60A1* ID_MODEL_FROM_DATABASE=ADS-2100 usb:v04F9p60A4* ID_MODEL_FROM_DATABASE=ADS-2500W usb:v04F9p60A5* ID_MODEL_FROM_DATABASE=ADS-2600W usb:v04F9p60A6* ID_MODEL_FROM_DATABASE=ADS-1000W usb:v04F9p60A7* ID_MODEL_FROM_DATABASE=ADS-1100W usb:v04F9p60A8* ID_MODEL_FROM_DATABASE=ADS-1500W usb:v04F9p60A9* ID_MODEL_FROM_DATABASE=ADS-1600W usb:v04FA* ID_VENDOR_FROM_DATABASE=Dallas Semiconductor usb:v04FAp2490* ID_MODEL_FROM_DATABASE=DS1490F 2-in-1 Fob, 1-Wire adapter usb:v04FAp4201* ID_MODEL_FROM_DATABASE=DS4201 Audio DAC usb:v04FB* ID_VENDOR_FROM_DATABASE=Biostar Microtech International Corp. usb:v04FC* ID_VENDOR_FROM_DATABASE=Sunplus Technology Co., Ltd usb:v04FCp0003* ID_MODEL_FROM_DATABASE=CM1092 / Wintech CM-5098 Optical Mouse usb:v04FCp0005* ID_MODEL_FROM_DATABASE=USB OpticalWheel Mouse usb:v04FCp0013* ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 usb:v04FCp0015* ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 usb:v04FCp00D3* ID_MODEL_FROM_DATABASE=00052486 / Laser Mouse M1052 [hama] usb:v04FCp0171* ID_MODEL_FROM_DATABASE=SPCA1527A/SPCA1528 SD card camera (Mass Storage mode) usb:v04FCp0201* ID_MODEL_FROM_DATABASE=SPCP825 RS232C Adapter usb:v04FCp0232* ID_MODEL_FROM_DATABASE=Fingerprint usb:v04FCp0538* ID_MODEL_FROM_DATABASE=Wireless Optical Mouse 2.4G [Bright] usb:v04FCp0561* ID_MODEL_FROM_DATABASE=Flexcam 100 usb:v04FCp05D8* ID_MODEL_FROM_DATABASE=Wireless keyboard/mouse usb:v04FCp0C15* ID_MODEL_FROM_DATABASE=SPIF215A SATA bridge usb:v04FCp0C25* ID_MODEL_FROM_DATABASE=SATALink SPIF225A usb:v04FCp1528* ID_MODEL_FROM_DATABASE=SPCA1527A/SPCA1528 SD card camera (webcam mode) usb:v04FCp1533* ID_MODEL_FROM_DATABASE=Mass Storage usb:v04FCp2080* ID_MODEL_FROM_DATABASE=ASUS Webcam usb:v04FCp500C* ID_MODEL_FROM_DATABASE=CA500C Digital Camera usb:v04FCp504A* ID_MODEL_FROM_DATABASE=Aiptek Mini PenCam 1.3 usb:v04FCp504B* ID_MODEL_FROM_DATABASE=Aiptek Mega PockerCam 1.3/Maxell MaxPocket LE 1.3 usb:v04FCp5330* ID_MODEL_FROM_DATABASE=Digitrex 2110 usb:v04FCp5331* ID_MODEL_FROM_DATABASE=Vivitar Vivicam 10 usb:v04FCp5360* ID_MODEL_FROM_DATABASE=Sunplus Generic Digital Camera usb:v04FCp5563* ID_MODEL_FROM_DATABASE=Digital Media Player MP3/WMA [The Sharper Image] usb:v04FCp5720* ID_MODEL_FROM_DATABASE=Card Reader Driver usb:v04FCp6333* ID_MODEL_FROM_DATABASE=Siri A9 UVC chipset usb:v04FCp7333* ID_MODEL_FROM_DATABASE=Finet Technology Palmpix DC-85 usb:v04FCp757A* ID_MODEL_FROM_DATABASE=Aiptek, MP315 MP3 Player usb:v04FCpFFFF* ID_MODEL_FROM_DATABASE=PureDigital Ritz Disposable usb:v04FD* ID_VENDOR_FROM_DATABASE=Soliton Systems, K.K. usb:v04FDp0003* ID_MODEL_FROM_DATABASE=Smart Card Reader II usb:v04FE* ID_VENDOR_FROM_DATABASE=PFU, Ltd usb:v04FF* ID_VENDOR_FROM_DATABASE=E-CMOS Corp. usb:v0500* ID_VENDOR_FROM_DATABASE=Siam United Hi-Tech usb:v0500p0001* ID_MODEL_FROM_DATABASE=DART Keyboard Mouse usb:v0500p0002* ID_MODEL_FROM_DATABASE=DART-2 Keyboard usb:v0501* ID_VENDOR_FROM_DATABASE=Fujikura DDK, Ltd usb:v0502* ID_VENDOR_FROM_DATABASE=Acer, Inc. usb:v0502p0001* ID_MODEL_FROM_DATABASE=Handheld usb:v0502p0736* ID_MODEL_FROM_DATABASE=Handheld usb:v0502p15B1* ID_MODEL_FROM_DATABASE=PDA n311 usb:v0502p1631* ID_MODEL_FROM_DATABASE=c10 Series usb:v0502p1632* ID_MODEL_FROM_DATABASE=c20 Series usb:v0502p16E1* ID_MODEL_FROM_DATABASE=n10 Handheld Sync usb:v0502p16E2* ID_MODEL_FROM_DATABASE=n20 Pocket PC Sync usb:v0502p16E3* ID_MODEL_FROM_DATABASE=n30 Handheld Sync usb:v0502p2008* ID_MODEL_FROM_DATABASE=Liquid Gallant Duo E350 (preloader) usb:v0502p3202* ID_MODEL_FROM_DATABASE=Liquid usb:v0502p3203* ID_MODEL_FROM_DATABASE=Liquid (Debug mode) usb:v0502p3230* ID_MODEL_FROM_DATABASE=BeTouch E120 usb:v0502p3317* ID_MODEL_FROM_DATABASE=Liquid usb:v0502p3325* ID_MODEL_FROM_DATABASE=Iconia tablet A500 usb:v0502p3341* ID_MODEL_FROM_DATABASE=Iconia tablet A500 usb:v0502p33C3* ID_MODEL_FROM_DATABASE=Liquid Gallant Duo E350 usb:v0502p33C4* ID_MODEL_FROM_DATABASE=Liquid Gallant Duo E350 (debug mode) usb:v0502p33C7* ID_MODEL_FROM_DATABASE=Liquid Gallant Duo E350 (USB tethering) usb:v0502p33C8* ID_MODEL_FROM_DATABASE=Liquid Gallant Duo E350 (debug mode, USB tethering) usb:v0502pD001* ID_MODEL_FROM_DATABASE=Divio NW801/DVC-V6+ Digital Camera usb:v0503* ID_VENDOR_FROM_DATABASE=Hitachi America, Ltd usb:v0504* ID_VENDOR_FROM_DATABASE=Hayes Microcomputer Products usb:v0506* ID_VENDOR_FROM_DATABASE=3Com Corp. usb:v0506p009D* ID_MODEL_FROM_DATABASE=HomeConnect Camera usb:v0506p00A0* ID_MODEL_FROM_DATABASE=3CREB96 Bluetooth Adapter usb:v0506p00A1* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0506p00A2* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0506p00DF* ID_MODEL_FROM_DATABASE=3Com Home Connect lite usb:v0506p0100* ID_MODEL_FROM_DATABASE=HomeConnect ADSL Modem Driver usb:v0506p03E8* ID_MODEL_FROM_DATABASE=3C19250 Ethernet [klsi] usb:v0506p0A01* ID_MODEL_FROM_DATABASE=3CRSHEW696 Wireless Adapter usb:v0506p0A11* ID_MODEL_FROM_DATABASE=3CRWE254G72 802.11g Adapter usb:v0506p11F8* ID_MODEL_FROM_DATABASE=HomeConnect 3C460 usb:v0506p2922* ID_MODEL_FROM_DATABASE=HomeConnect Cable Modem External with usb:v0506p3021* ID_MODEL_FROM_DATABASE=U.S.Robotics 56000 Voice FaxModem Pro usb:v0506p4601* ID_MODEL_FROM_DATABASE=3C460B 10/100 Ethernet Adapter usb:v0506pF002* ID_MODEL_FROM_DATABASE=3CP4218 ADSL Modem (pre-init) usb:v0506pF003* ID_MODEL_FROM_DATABASE=3CP4218 ADSL Modem usb:v0506pF100* ID_MODEL_FROM_DATABASE=3CP4218 ADSL Modem (pre-init) usb:v0507* ID_VENDOR_FROM_DATABASE=Hosiden Corp. usb:v0507p0011* ID_MODEL_FROM_DATABASE=Konami ParaParaParadise Controller usb:v0508* ID_VENDOR_FROM_DATABASE=Clarion Co., Ltd usb:v0509* ID_VENDOR_FROM_DATABASE=Aztech Systems, Ltd usb:v0509p0801* ID_MODEL_FROM_DATABASE=ADSL Modem usb:v0509p0802* ID_MODEL_FROM_DATABASE=ADSL Modem (RFC1483) usb:v0509p0806* ID_MODEL_FROM_DATABASE=DSL Modem usb:v0509p080F* ID_MODEL_FROM_DATABASE=Binatone ADSL500 Modem Network Interface usb:v0509p0812* ID_MODEL_FROM_DATABASE=Pirelli ADSL Modem Network Interface usb:v050A* ID_VENDOR_FROM_DATABASE=Cinch Connectors usb:v050B* ID_VENDOR_FROM_DATABASE=Cable System International usb:v050C* ID_VENDOR_FROM_DATABASE=InnoMedia, Inc. usb:v050D* ID_VENDOR_FROM_DATABASE=Belkin Components usb:v050Dp0004* ID_MODEL_FROM_DATABASE=Direct Connect usb:v050Dp0012* ID_MODEL_FROM_DATABASE=F8T012 Bluetooth Adapter usb:v050Dp0013* ID_MODEL_FROM_DATABASE=F8T013 Bluetooth Adapter usb:v050Dp0017* ID_MODEL_FROM_DATABASE=B8T017 Bluetooth+EDR 2.1 / F4U017 USB 2.0 7-port Hub usb:v050Dp003A* ID_MODEL_FROM_DATABASE=Universal Media Reader usb:v050Dp0050* ID_MODEL_FROM_DATABASE=F5D6050 802.11b Wireless Adapter v2000 [Atmel at76c503a] usb:v050Dp0081* ID_MODEL_FROM_DATABASE=F8T001v2 Bluetooth usb:v050Dp0083* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v050Dp0084* ID_MODEL_FROM_DATABASE=F8T003v2 Bluetooth usb:v050Dp0102* ID_MODEL_FROM_DATABASE=Flip KVM usb:v050Dp0103* ID_MODEL_FROM_DATABASE=F5U103 Serial Adapter [etek] usb:v050Dp0106* ID_MODEL_FROM_DATABASE=VideoBus II Adapter, Video usb:v050Dp0108* ID_MODEL_FROM_DATABASE=F1DE108B KVM usb:v050Dp0109* ID_MODEL_FROM_DATABASE=F5U109/F5U409 PDA Adapter usb:v050Dp0115* ID_MODEL_FROM_DATABASE=SCSI Adapter usb:v050Dp0119* ID_MODEL_FROM_DATABASE=F5U120-PC Dual PS/2 Ports / F5U118-UNV ADB Adapter usb:v050Dp0121* ID_MODEL_FROM_DATABASE=F5D5050 100Mbps Ethernet usb:v050Dp0122* ID_MODEL_FROM_DATABASE=Ethernet Adapter usb:v050Dp0131* ID_MODEL_FROM_DATABASE=Bluetooth Device with trace filter usb:v050Dp016A* ID_MODEL_FROM_DATABASE=Bluetooth Mini Dongle usb:v050Dp0200* ID_MODEL_FROM_DATABASE=Nostromo SpeedPad n52te Gaming Keyboard usb:v050Dp0201* ID_MODEL_FROM_DATABASE=Peripheral Switch usb:v050Dp0208* ID_MODEL_FROM_DATABASE=USBView II Video Adapter [nt1004] usb:v050Dp0210* ID_MODEL_FROM_DATABASE=F5U228 Hi-Speed USB 2.0 DVD Creator usb:v050Dp0211* ID_MODEL_FROM_DATABASE=F5U211 USB 2.0 15-in-1 Media Reader & Writer usb:v050Dp0224* ID_MODEL_FROM_DATABASE=F5U224 USB 2.0 4-Port Hub usb:v050Dp0234* ID_MODEL_FROM_DATABASE=F5U234 USB 2.0 4-Port Hub usb:v050Dp0237* ID_MODEL_FROM_DATABASE=F5U237 USB 2.0 7-Port Hub usb:v050Dp0240* ID_MODEL_FROM_DATABASE=F5U240 USB 2.0 CF Card Reader usb:v050Dp0249* ID_MODEL_FROM_DATABASE=USB 2 Flash Media Device usb:v050Dp0257* ID_MODEL_FROM_DATABASE=F5U257 Serial usb:v050Dp0304* ID_MODEL_FROM_DATABASE=FSU304 USB 2.0 - 4 Ports Hub usb:v050Dp0307* ID_MODEL_FROM_DATABASE=USB 2.0 - 7 ports Hub [FSU307] usb:v050Dp0409* ID_MODEL_FROM_DATABASE=F5U409 Serial usb:v050Dp0416* ID_MODEL_FROM_DATABASE=Staples 12416 7 port desktop hub usb:v050Dp0551* ID_MODEL_FROM_DATABASE=F6C550-AVR UPS usb:v050Dp065A* ID_MODEL_FROM_DATABASE=F8T065BF Mini Bluetooth 4.0 Adapter usb:v050Dp0706* ID_MODEL_FROM_DATABASE=2-N-1 7-Port Hub (Lower half) usb:v050Dp0802* ID_MODEL_FROM_DATABASE=Nostromo n40 Gamepad usb:v050Dp0803* ID_MODEL_FROM_DATABASE=Nostromo 1745 GamePad usb:v050Dp0805* ID_MODEL_FROM_DATABASE=Nostromo N50 GamePad usb:v050Dp0815* ID_MODEL_FROM_DATABASE=Nostromo n52 HID SpeedPad Mouse Wheel usb:v050Dp0826* ID_MODEL_FROM_DATABASE=ErgoFit Wireless Optical Mouse (HID) usb:v050Dp0980* ID_MODEL_FROM_DATABASE=HID UPS Battery usb:v050Dp1004* ID_MODEL_FROM_DATABASE=F9L1004 802.11n Surf N300 XR Wireless Adapter [Realtek RTL8192CU] usb:v050Dp1102* ID_MODEL_FROM_DATABASE=F7D1102 N150/Surf Micro Wireless Adapter v1000 [Realtek RTL8188CUS] usb:v050Dp1103* ID_MODEL_FROM_DATABASE=F9L1103 N750 DB 802.11abgn 2x3:3 [Ralink RT3573] usb:v050Dp1106* ID_MODEL_FROM_DATABASE=F9L1106v1 802.11a/b/g/n/ac Wireless Adapter [Broadcom BCM43526] usb:v050Dp1109* ID_MODEL_FROM_DATABASE=F9L1109v1 802.11a/b/g/n/ac Wireless Adapter [Realtek RTL8812AU] usb:v050Dp110A* ID_MODEL_FROM_DATABASE=F9L1101v2 802.11abgn Wireless Adapter [Realtek RTL8192DU] usb:v050Dp11F2* ID_MODEL_FROM_DATABASE=ISY Wireless Micro Adapter IWL 2000 [RTL8188CUS] usb:v050Dp1202* ID_MODEL_FROM_DATABASE=F5U120-PC Parallel Printer Port usb:v050Dp1203* ID_MODEL_FROM_DATABASE=F5U120-PC Serial Port usb:v050Dp2103* ID_MODEL_FROM_DATABASE=F7D2102 802.11n N300 Micro Wireless Adapter v3000 [Realtek RTL8192CU] usb:v050Dp21F1* ID_MODEL_FROM_DATABASE=N300 WLAN N Adapter [ISY] usb:v050Dp21F2* ID_MODEL_FROM_DATABASE=RTL8192CU 802.11n WLAN Adapter [ISY IWL 4000] usb:v050Dp258A* ID_MODEL_FROM_DATABASE=F5U258 Host to Host cable usb:v050Dp3101* ID_MODEL_FROM_DATABASE=F1DF102U/F1DG102U Flip Hub usb:v050Dp3201* ID_MODEL_FROM_DATABASE=F1DF102U/F1DG102U Flip KVM usb:v050Dp4050* ID_MODEL_FROM_DATABASE=ZD1211B usb:v050Dp5055* ID_MODEL_FROM_DATABASE=F5D5055 Gigabit Network Adapter [AX88xxx] usb:v050Dp6050* ID_MODEL_FROM_DATABASE=F6D6050 802.11abgn Wireless Adapter [Broadcom BCM4323] usb:v050Dp6051* ID_MODEL_FROM_DATABASE=F5D6051 802.11b Wireless Network Adapter [ZyDAS ZD1201] usb:v050Dp615A* ID_MODEL_FROM_DATABASE=F7D4101 / F9L1101v1 802.11abgn Wireless Adapter [Broadcom BCM4323] usb:v050Dp7050* ID_MODEL_FROM_DATABASE=F5D7050 Wireless G Adapter v1000/v2000 [Intersil ISL3887] usb:v050Dp7051* ID_MODEL_FROM_DATABASE=F5D7051 802.11g Adapter v1000 [Broadcom 4320 USB] usb:v050Dp705A* ID_MODEL_FROM_DATABASE=F5D7050 Wireless G Adapter v3000 [Ralink RT2571W] usb:v050Dp705B* ID_MODEL_FROM_DATABASE=Wireless G Adapter usb:v050Dp705C* ID_MODEL_FROM_DATABASE=F5D7050 Wireless G Adapter v4000 [Zydas ZD1211B] usb:v050Dp705E* ID_MODEL_FROM_DATABASE=F5D7050 Wireless G Adapter v5000 [Realtek RTL8187B] usb:v050Dp706A* ID_MODEL_FROM_DATABASE=2-N-1 7-Port Hub (Upper half) usb:v050Dp8053* ID_MODEL_FROM_DATABASE=F5D8053 N Wireless USB Adapter v1000/v4000 [Ralink RT2870] usb:v050Dp805C* ID_MODEL_FROM_DATABASE=F5D8053 N Wireless Adapter v3000 [Ralink RT2870] usb:v050Dp805E* ID_MODEL_FROM_DATABASE=F5D8053 N Wireless USB Adapter v5000 [Realtek RTL8192U] usb:v050Dp815C* ID_MODEL_FROM_DATABASE=F5D8053 N Wireless USB Adapter v3000 [Ralink RT2870] usb:v050Dp815F* ID_MODEL_FROM_DATABASE=F5D8053 N Wireless USB Adapter v6000 [Realtek RTL8192SU] usb:v050Dp825A* ID_MODEL_FROM_DATABASE=F5D8055 N+ Wireless Adapter v1000 [Ralink RT2870] usb:v050Dp825B* ID_MODEL_FROM_DATABASE=F5D8055 N+ Wireless Adapter v2000 [Ralink RT3072] usb:v050Dp845A* ID_MODEL_FROM_DATABASE=F7D2101 802.11n Surf & Share Wireless Adapter v1000 [Realtek RTL8192SU] usb:v050Dp905B* ID_MODEL_FROM_DATABASE=F5D9050 Wireless G+ MIMO Network Adapter v3000 [Ralink RT2573] usb:v050Dp905C* ID_MODEL_FROM_DATABASE=F5D9050 Wireless G+ MIMO Network Adapter v4000 [Ralink RT2573] usb:v050Dp935A* ID_MODEL_FROM_DATABASE=F6D4050 N150 Enhanced Wireless Network Adapter v1000 [Ralink RT3070] usb:v050Dp935B* ID_MODEL_FROM_DATABASE=F6D4050 N150 Enhanced Wireless Network Adapter v2000 [Ralink RT3070] usb:v050Dp945A* ID_MODEL_FROM_DATABASE=F7D1101 v1 Basic Wireless Adapter [Realtek RTL8188SU] usb:v050Dp945B* ID_MODEL_FROM_DATABASE=F7D1101 v2 Basic Wireless Adapter [Ralink RT3370] usb:v050DpD321* ID_MODEL_FROM_DATABASE=Dynex DX-NUSB 802.11bgn Wireless Adapter [Broadcom BCM43231] usb:v050E* ID_VENDOR_FROM_DATABASE=Neon Technology, Inc. usb:v050F* ID_VENDOR_FROM_DATABASE=KC Technology, Inc. usb:v050Fp0001* ID_MODEL_FROM_DATABASE=Hub usb:v050Fp0003* ID_MODEL_FROM_DATABASE=KC82C160S Hub usb:v050Fp0180* ID_MODEL_FROM_DATABASE=KC-180 IrDA Dongle usb:v050Fp0190* ID_MODEL_FROM_DATABASE=KC2190 USB Host-to-Host cable usb:v0510* ID_VENDOR_FROM_DATABASE=Sejin Electron, Inc. usb:v0510p0001* ID_MODEL_FROM_DATABASE=Keyboard usb:v0510p1000* ID_MODEL_FROM_DATABASE=Keyboard with PS/2 Mouse Port usb:v0510pE001* ID_MODEL_FROM_DATABASE=Mouse usb:v0511* ID_VENDOR_FROM_DATABASE=N'Able (DataBook) Technologies, Inc. usb:v0511p002B* ID_MODEL_FROM_DATABASE=AOC DVB usb:v0512* ID_VENDOR_FROM_DATABASE=Hualon Microelectronics Corp. usb:v0513* ID_VENDOR_FROM_DATABASE=digital-X, Inc. usb:v0514* ID_VENDOR_FROM_DATABASE=FCI Electronics usb:v0515* ID_VENDOR_FROM_DATABASE=ACTC usb:v0516* ID_VENDOR_FROM_DATABASE=Longwell Electronics usb:v0517* ID_VENDOR_FROM_DATABASE=Butterfly Communications usb:v0518* ID_VENDOR_FROM_DATABASE=EzKEY Corp. usb:v0518p0001* ID_MODEL_FROM_DATABASE=USB to PS2 Adaptor v1.09 usb:v0518p0002* ID_MODEL_FROM_DATABASE=EZ-9900C Keyboard usb:v0519* ID_VENDOR_FROM_DATABASE=Star Micronics Co., Ltd usb:v0519p0003* ID_MODEL_FROM_DATABASE=TSP100ECO/TSP100II usb:v0519pC002* ID_MODEL_FROM_DATABASE=Xlive Bluetooth XBM-100S MP3 Player usb:v051A* ID_VENDOR_FROM_DATABASE=WYSE Technology usb:v051ApA005* ID_MODEL_FROM_DATABASE=Smart Display Version 9973 usb:v051B* ID_VENDOR_FROM_DATABASE=Silicon Graphics usb:v051C* ID_VENDOR_FROM_DATABASE=Shuttle, Inc. usb:v051Cp0005* ID_MODEL_FROM_DATABASE=VFD Module usb:v051CpC001* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v051CpC002* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v051D* ID_VENDOR_FROM_DATABASE=American Power Conversion usb:v051Dp0001* ID_MODEL_FROM_DATABASE=UPS usb:v051Dp0002* ID_MODEL_FROM_DATABASE=Uninterruptible Power Supply usb:v051Dp0003* ID_MODEL_FROM_DATABASE=UPS usb:v051E* ID_VENDOR_FROM_DATABASE=Scientific Atlanta, Inc. usb:v051F* ID_VENDOR_FROM_DATABASE=IO Systems (Elite Electronics), Inc. usb:v0520* ID_VENDOR_FROM_DATABASE=Taiwan Semiconductor Manufacturing Co. usb:v0521* ID_VENDOR_FROM_DATABASE=Airborn Connectors usb:v0522* ID_VENDOR_FROM_DATABASE=Advanced Connectek, Inc. usb:v0523* ID_VENDOR_FROM_DATABASE=ATEN GmbH usb:v0524* ID_VENDOR_FROM_DATABASE=Sola Electronics usb:v0525* ID_VENDOR_FROM_DATABASE=Netchip Technology, Inc. usb:v0525p100D* ID_MODEL_FROM_DATABASE=RFMD Bluetooth Device usb:v0525p1080* ID_MODEL_FROM_DATABASE=NET1080 USB-USB Bridge usb:v0525p1200* ID_MODEL_FROM_DATABASE=SSDC Adapter II usb:v0525p1265* ID_MODEL_FROM_DATABASE=File-backed Storage Gadget usb:v0525p3424* ID_MODEL_FROM_DATABASE=Lumidigm Venus fingerprint sensor usb:v0525pA0F0* ID_MODEL_FROM_DATABASE=Cambridge Electronic Devices Power1401 mk 2 usb:v0525pA140* ID_MODEL_FROM_DATABASE=USB Clik! 40 usb:v0525pA141* ID_MODEL_FROM_DATABASE=(OME) PocketZip 40 MP3 Player Driver usb:v0525pA220* ID_MODEL_FROM_DATABASE=GVC Bluetooth Wireless Adapter usb:v0525pA4A0* ID_MODEL_FROM_DATABASE=Linux-USB "Gadget Zero" usb:v0525pA4A1* ID_MODEL_FROM_DATABASE=Linux-USB Ethernet Gadget usb:v0525pA4A2* ID_MODEL_FROM_DATABASE=Linux-USB Ethernet/RNDIS Gadget usb:v0525pA4A3* ID_MODEL_FROM_DATABASE=Linux-USB user-mode isochronous source/sink usb:v0525pA4A4* ID_MODEL_FROM_DATABASE=Linux-USB user-mode bulk source/sink usb:v0525pA4A5* ID_MODEL_FROM_DATABASE=Pocketbook Pro 903 usb:v0525pA4A6* ID_MODEL_FROM_DATABASE=Linux-USB Serial Gadget usb:v0525pA4A7* ID_MODEL_FROM_DATABASE=Linux-USB Serial Gadget (CDC ACM mode) usb:v0525pA4A8* ID_MODEL_FROM_DATABASE=Linux-USB Printer Gadget usb:v0525pA4A9* ID_MODEL_FROM_DATABASE=Linux-USB OBEX Gadget usb:v0525pA4AA* ID_MODEL_FROM_DATABASE=Linux-USB CDC Composite Gadge (Ethernet and ACM) usb:v0526* ID_VENDOR_FROM_DATABASE=Temic MHS S.A. usb:v0527* ID_VENDOR_FROM_DATABASE=ALTRA usb:v0528* ID_VENDOR_FROM_DATABASE=ATI Technologies, Inc. usb:v0528p7561* ID_MODEL_FROM_DATABASE=TV Wonder usb:v0528p7562* ID_MODEL_FROM_DATABASE=TV Wonder, Edition (FN5) usb:v0528p7563* ID_MODEL_FROM_DATABASE=TV Wonder, Edition (FI) usb:v0528p7564* ID_MODEL_FROM_DATABASE=TV Wonder, Edition (FQ) usb:v0528p7565* ID_MODEL_FROM_DATABASE=TV Wonder, Edition (NTSC+) usb:v0528p7566* ID_MODEL_FROM_DATABASE=TV Wonder, Edition (FN5) usb:v0528p7567* ID_MODEL_FROM_DATABASE=TV Wonder, Edition (FI) usb:v0528p7568* ID_MODEL_FROM_DATABASE=TV Wonder, Edition (FQ) usb:v0528p7569* ID_MODEL_FROM_DATABASE=Live! Pro (A) usb:v0528p756A* ID_MODEL_FROM_DATABASE=Live! Pro Audio (O) usb:v0529* ID_VENDOR_FROM_DATABASE=Aladdin Knowledge Systems usb:v0529p0001* ID_MODEL_FROM_DATABASE=HASP copy protection dongle usb:v0529p030B* ID_MODEL_FROM_DATABASE=eToken R1 v3.1.3.x usb:v0529p0313* ID_MODEL_FROM_DATABASE=eToken R1 v3.2.3.x usb:v0529p031B* ID_MODEL_FROM_DATABASE=eToken R1 v3.3.3.x usb:v0529p0323* ID_MODEL_FROM_DATABASE=eToken R1 v3.4.3.x usb:v0529p0412* ID_MODEL_FROM_DATABASE=eToken R2 v2.2.4.x usb:v0529p041A* ID_MODEL_FROM_DATABASE=eToken R2 v2.2.4.x usb:v0529p0422* ID_MODEL_FROM_DATABASE=eToken R2 v2.4.4.x usb:v0529p042A* ID_MODEL_FROM_DATABASE=eToken R2 v2.5.4.x usb:v0529p050C* ID_MODEL_FROM_DATABASE=eToken Pro v4.1.5.x usb:v0529p0514* ID_MODEL_FROM_DATABASE=eToken Pro v4.2.5.4 usb:v0529p0600* ID_MODEL_FROM_DATABASE=eToken Pro 64k (4.2) usb:v0529p0620* ID_MODEL_FROM_DATABASE=Token JC usb:v052A* ID_VENDOR_FROM_DATABASE=Crescent Heart Software usb:v052B* ID_VENDOR_FROM_DATABASE=Tekom Technologies, Inc. usb:v052Bp0102* ID_MODEL_FROM_DATABASE=Ca508A HP1020 Camera v.1.3.1.6 usb:v052Bp0801* ID_MODEL_FROM_DATABASE=Yakumo MegaImage 37 usb:v052Bp1512* ID_MODEL_FROM_DATABASE=Yakumo MegaImage IV usb:v052Bp1513* ID_MODEL_FROM_DATABASE=Aosta CX100 Webcam usb:v052Bp1514* ID_MODEL_FROM_DATABASE=Aosta CX100 Webcam Storage usb:v052Bp1905* ID_MODEL_FROM_DATABASE=Yakumo MegaImage 47 usb:v052Bp1911* ID_MODEL_FROM_DATABASE=Yakumo MegaImage 47 SL usb:v052Bp2202* ID_MODEL_FROM_DATABASE=WDM Still Image Capture usb:v052Bp2203* ID_MODEL_FROM_DATABASE=Sound Vision Stream Driver usb:v052Bp3A06* ID_MODEL_FROM_DATABASE=DigiLife DDV-5120A usb:v052BpD001* ID_MODEL_FROM_DATABASE=P35U Camera Capture usb:v052C* ID_VENDOR_FROM_DATABASE=Canon Information Systems, Inc. usb:v052D* ID_VENDOR_FROM_DATABASE=Avid Electronics Corp. usb:v052E* ID_VENDOR_FROM_DATABASE=Standard Microsystems Corp. usb:v052F* ID_VENDOR_FROM_DATABASE=Unicore Software, Inc. usb:v0530* ID_VENDOR_FROM_DATABASE=American Microsystems, Inc. usb:v0531* ID_VENDOR_FROM_DATABASE=Wacom Technology Corp. usb:v0532* ID_VENDOR_FROM_DATABASE=Systech Corp. usb:v0533* ID_VENDOR_FROM_DATABASE=Alcatel Mobile Phones usb:v0534* ID_VENDOR_FROM_DATABASE=Motorola, Inc. usb:v0535* ID_VENDOR_FROM_DATABASE=LIH TZU Electric Co., Ltd usb:v0536* ID_VENDOR_FROM_DATABASE=Hand Held Products (Welch Allyn, Inc.) usb:v0536p01A0* ID_MODEL_FROM_DATABASE=PDT usb:v0537* ID_VENDOR_FROM_DATABASE=Inventec Corp. usb:v0538* ID_VENDOR_FROM_DATABASE=Caldera International, Inc. (SCO) usb:v0539* ID_VENDOR_FROM_DATABASE=Shyh Shiun Terminals Co., Ltd usb:v053A* ID_VENDOR_FROM_DATABASE=PrehKeyTec GmbH usb:v053Ap0B00* ID_MODEL_FROM_DATABASE=Hub usb:v053Ap0B01* ID_MODEL_FROM_DATABASE=Preh MCI 3100 usb:v053B* ID_VENDOR_FROM_DATABASE=Global Village Communication usb:v053C* ID_VENDOR_FROM_DATABASE=Institut of Microelectronic & Mechatronic Systems usb:v053D* ID_VENDOR_FROM_DATABASE=Silicon Architect usb:v053E* ID_VENDOR_FROM_DATABASE=Mobility Electronics usb:v053F* ID_VENDOR_FROM_DATABASE=Synopsys, Inc. usb:v0540* ID_VENDOR_FROM_DATABASE=UniAccess AB usb:v0540p0101* ID_MODEL_FROM_DATABASE=Panache Surf ISDN TA usb:v0541* ID_VENDOR_FROM_DATABASE=Sirf Technology, Inc. usb:v0543* ID_VENDOR_FROM_DATABASE=ViewSonic Corp. usb:v0543p00FE* ID_MODEL_FROM_DATABASE=G773 Monitor Hub usb:v0543p00FF* ID_MODEL_FROM_DATABASE=P815 Monitor Hub usb:v0543p0BF2* ID_MODEL_FROM_DATABASE=airpanel V150 Wireless Smart Display usb:v0543p0BF3* ID_MODEL_FROM_DATABASE=airpanel V110 Wireless Smart Display usb:v0543p0ED9* ID_MODEL_FROM_DATABASE=Color Pocket PC V35 usb:v0543p0F01* ID_MODEL_FROM_DATABASE=airsync Wi-Fi Wireless Adapter usb:v0543p1527* ID_MODEL_FROM_DATABASE=Color Pocket PC V36 usb:v0543p1529* ID_MODEL_FROM_DATABASE=Color Pocket PC V37 usb:v0543p152B* ID_MODEL_FROM_DATABASE=Color Pocket PC V38 usb:v0543p152E* ID_MODEL_FROM_DATABASE=Pocket PC usb:v0543p1921* ID_MODEL_FROM_DATABASE=Communicator Pocket PC usb:v0543p1922* ID_MODEL_FROM_DATABASE=Smartphone usb:v0543p1923* ID_MODEL_FROM_DATABASE=Pocket PC V30 usb:v0543p1A11* ID_MODEL_FROM_DATABASE=Wireless 802.11g Adapter usb:v0543p1E60* ID_MODEL_FROM_DATABASE=TA310 - ATSC/NTSC/PAL Driver(PCM4) usb:v0543p4153* ID_MODEL_FROM_DATABASE=ViewSonic G773 Control (?) usb:v0544* ID_VENDOR_FROM_DATABASE=Cristie Electronics, Ltd usb:v0545* ID_VENDOR_FROM_DATABASE=Xirlink, Inc. usb:v0545p7333* ID_MODEL_FROM_DATABASE=Trution Web Camera usb:v0545p8002* ID_MODEL_FROM_DATABASE=IBM NetCamera usb:v0545p8009* ID_MODEL_FROM_DATABASE=Veo PC Camera usb:v0545p800C* ID_MODEL_FROM_DATABASE=Veo Stingray usb:v0545p800D* ID_MODEL_FROM_DATABASE=Veo PC Camera usb:v0545p8080* ID_MODEL_FROM_DATABASE=IBM C-It Webcam usb:v0545p808A* ID_MODEL_FROM_DATABASE=Veo PC Camera usb:v0545p808B* ID_MODEL_FROM_DATABASE=Veo Stingray usb:v0545p808D* ID_MODEL_FROM_DATABASE=Veo PC Camera usb:v0545p810A* ID_MODEL_FROM_DATABASE=Veo Advanced Connect Webcam usb:v0545p810B* ID_MODEL_FROM_DATABASE=Veo PC Camera usb:v0545p810C* ID_MODEL_FROM_DATABASE=Veo PC Camera usb:v0545p8135* ID_MODEL_FROM_DATABASE=Veo Mobile/Advanced Web Camera usb:v0545p813A* ID_MODEL_FROM_DATABASE=Veo PC Camera usb:v0545p813B* ID_MODEL_FROM_DATABASE=Veo PC Camera usb:v0545p813C* ID_MODEL_FROM_DATABASE=Veo Mobile/Advanced Web Camera usb:v0545p8333* ID_MODEL_FROM_DATABASE=Veo Stingray/Connect Web Camera usb:v0545p888C* ID_MODEL_FROM_DATABASE=eVision 123 digital camera usb:v0545p888D* ID_MODEL_FROM_DATABASE=eVision 123 digital camera usb:v0546* ID_VENDOR_FROM_DATABASE=Polaroid Corp. usb:v0546p0DAF* ID_MODEL_FROM_DATABASE=PDC 2300Z usb:v0546p1BED* ID_MODEL_FROM_DATABASE=PDC 1320 Camera usb:v0546p3097* ID_MODEL_FROM_DATABASE=PDC 310 usb:v0546p3155* ID_MODEL_FROM_DATABASE=PDC 3070 Camera usb:v0546p3187* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0546p3191* ID_MODEL_FROM_DATABASE=Ion 80 Camera usb:v0546p3273* ID_MODEL_FROM_DATABASE=PDC 2030 Camera usb:v0546p3304* ID_MODEL_FROM_DATABASE=a500 Digital Camera usb:v0546pDCCF* ID_MODEL_FROM_DATABASE=Sound Vision Stream Driver usb:v0547* ID_VENDOR_FROM_DATABASE=Anchor Chips, Inc. usb:v0547p0001* ID_MODEL_FROM_DATABASE=ICSI Bluetooth Device usb:v0547p1002* ID_MODEL_FROM_DATABASE=Python2 WDM Encoder usb:v0547p1006* ID_MODEL_FROM_DATABASE=Hantek DSO-2100 UF usb:v0547p2131* ID_MODEL_FROM_DATABASE=AN2131 EZUSB Microcontroller usb:v0547p2235* ID_MODEL_FROM_DATABASE=AN2235 EZUSB-FX Microcontroller usb:v0547p2710* ID_MODEL_FROM_DATABASE=EZ-Link Loader (EZLNKLDR.SYS) usb:v0547p2720* ID_MODEL_FROM_DATABASE=AN2720 USB-USB Bridge usb:v0547p2727* ID_MODEL_FROM_DATABASE=Xircom PGUNET USB-USB Bridge usb:v0547p2750* ID_MODEL_FROM_DATABASE=EZ-Link (EZLNKUSB.SYS) usb:v0547p2810* ID_MODEL_FROM_DATABASE=Cypress ATAPI Bridge usb:v0547p4D90* ID_MODEL_FROM_DATABASE=AmScope MD1900 camera usb:v0547p7000* ID_MODEL_FROM_DATABASE=PowerSpec MCE460 Front Panel LED Display usb:v0547p7777* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0547p9999* ID_MODEL_FROM_DATABASE=AN2131 uninitialized (?) usb:v0548* ID_VENDOR_FROM_DATABASE=Tyan Computer Corp. usb:v0548p1005* ID_MODEL_FROM_DATABASE=EZ Cart II GameBoy Flash Programmer usb:v0549* ID_VENDOR_FROM_DATABASE=Pixera Corp. usb:v054A* ID_VENDOR_FROM_DATABASE=Fujitsu Microelectronics, Inc. usb:v054B* ID_VENDOR_FROM_DATABASE=New Media Corp. usb:v054C* ID_VENDOR_FROM_DATABASE=Sony Corp. usb:v054Cp0001* ID_MODEL_FROM_DATABASE=HUB usb:v054Cp0002* ID_MODEL_FROM_DATABASE=Standard HUB usb:v054Cp0010* ID_MODEL_FROM_DATABASE=DSC-S30/S70/S75/F505V/F505/FD92/W1 Cybershot/Mavica Digital Camera usb:v054Cp0014* ID_MODEL_FROM_DATABASE=Nogatech USBVision (SY) usb:v054Cp0022* ID_MODEL_FROM_DATABASE=Storage Adapter V2 (TPP) usb:v054Cp0023* ID_MODEL_FROM_DATABASE=CD Writer usb:v054Cp0024* ID_MODEL_FROM_DATABASE=Mavica CD-1000 Camera usb:v054Cp0025* ID_MODEL_FROM_DATABASE=NW-MS7 Walkman MemoryStick Reader usb:v054Cp002B* ID_MODEL_FROM_DATABASE=Portable USB Harddrive V2 usb:v054Cp002C* ID_MODEL_FROM_DATABASE=USB Floppy Disk Drive usb:v054Cp002D* ID_MODEL_FROM_DATABASE=MSAC-US1 MemoryStick Reader usb:v054Cp002E* ID_MODEL_FROM_DATABASE=HandyCam MemoryStick Reader usb:v054Cp0030* ID_MODEL_FROM_DATABASE=Storage Adapter V2 (TPP) usb:v054Cp0032* ID_MODEL_FROM_DATABASE=MemoryStick MSC-U01 Reader usb:v054Cp0035* ID_MODEL_FROM_DATABASE=Network Walkman (E) usb:v054Cp0036* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0037* ID_MODEL_FROM_DATABASE=MG Memory Stick Reader/Writer usb:v054Cp0038* ID_MODEL_FROM_DATABASE=Clie PEG-S300/D PalmOS PDA usb:v054Cp0039* ID_MODEL_FROM_DATABASE=Network Walkman (MS) usb:v054Cp003C* ID_MODEL_FROM_DATABASE=VAIO-MX LCD Control usb:v054Cp0045* ID_MODEL_FROM_DATABASE=Digital Imaging Video usb:v054Cp0046* ID_MODEL_FROM_DATABASE=Network Walkman usb:v054Cp004A* ID_MODEL_FROM_DATABASE=Memory Stick Hi-Fi System usb:v054Cp004B* ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer usb:v054Cp004E* ID_MODEL_FROM_DATABASE=DSC-xxx (ptp) usb:v054Cp0056* ID_MODEL_FROM_DATABASE=MG Memory Stick Reader/Writer usb:v054Cp0058* ID_MODEL_FROM_DATABASE=Clie PEG-N7x0C PalmOS PDA Mass Storage usb:v054Cp0066* ID_MODEL_FROM_DATABASE=Clie PEG-N7x0C/PEG-T425 PalmOS PDA Serial usb:v054Cp0067* ID_MODEL_FROM_DATABASE=CMR-PC3 Webcam usb:v054Cp0069* ID_MODEL_FROM_DATABASE=Memorystick MSC-U03 Reader usb:v054Cp006C* ID_MODEL_FROM_DATABASE=FeliCa S310 [PaSoRi] usb:v054Cp006D* ID_MODEL_FROM_DATABASE=Clie PEG-T425 PDA Mass Storage usb:v054Cp006F* ID_MODEL_FROM_DATABASE=Network Walkman (EV) usb:v054Cp0073* ID_MODEL_FROM_DATABASE=Storage CRX1750U usb:v054Cp0075* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0076* ID_MODEL_FROM_DATABASE=Storage Adapter ACR-U20 usb:v054Cp007C* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp007F* ID_MODEL_FROM_DATABASE=IC Recorder (MS) usb:v054Cp0080* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0081* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0084* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0085* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0086* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp008B* ID_MODEL_FROM_DATABASE=Micro Vault 64M Mass Storage usb:v054Cp0095* ID_MODEL_FROM_DATABASE=Clie s360 usb:v054Cp0099* ID_MODEL_FROM_DATABASE=Clie NR70 PDA Mass Storage usb:v054Cp009A* ID_MODEL_FROM_DATABASE=Clie NR70 PDA Serial usb:v054Cp00AB* ID_MODEL_FROM_DATABASE=Visual Communication Camera (PCGA-UVC10) usb:v054Cp00AF* ID_MODEL_FROM_DATABASE=DPP-EX Series Digital Photo Printer usb:v054Cp00BF* ID_MODEL_FROM_DATABASE=IC Recorder (S) usb:v054Cp00C0* ID_MODEL_FROM_DATABASE=Handycam DCR-30 usb:v054Cp00C6* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp00C7* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp00C8* ID_MODEL_FROM_DATABASE=MZ-N710 Minidisc Walkman usb:v054Cp00C9* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp00CA* ID_MODEL_FROM_DATABASE=MZ-DN430 Minidisc Walkman usb:v054Cp00CB* ID_MODEL_FROM_DATABASE=MSAC-US20 Memory Stick Reader usb:v054Cp00DA* ID_MODEL_FROM_DATABASE=Clie nx60 usb:v054Cp00E8* ID_MODEL_FROM_DATABASE=Network Walkman (MS) usb:v054Cp00E9* ID_MODEL_FROM_DATABASE=Handheld usb:v054Cp00EB* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0101* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0103* ID_MODEL_FROM_DATABASE=IC Recorder (ST) usb:v054Cp0105* ID_MODEL_FROM_DATABASE=Micro Vault Hub usb:v054Cp0107* ID_MODEL_FROM_DATABASE=VCC-U01 Visual Communication Camera usb:v054Cp0110* ID_MODEL_FROM_DATABASE=Digital Imaging Video usb:v054Cp0113* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0116* ID_MODEL_FROM_DATABASE=IC Recorder (P) usb:v054Cp0144* ID_MODEL_FROM_DATABASE=Clie PEG-TH55 PDA usb:v054Cp0147* ID_MODEL_FROM_DATABASE=Visual Communication Camera (PCGA-UVC11) usb:v054Cp014C* ID_MODEL_FROM_DATABASE=Aiwa AM-NX9 Net MD Music Recorder MDLP usb:v054Cp014D* ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer usb:v054Cp0154* ID_MODEL_FROM_DATABASE=Eyetoy Audio Device usb:v054Cp015F* ID_MODEL_FROM_DATABASE=IC Recorder (BM) usb:v054Cp0169* ID_MODEL_FROM_DATABASE=Clie PEG-TJ35 PDA Serial usb:v054Cp016A* ID_MODEL_FROM_DATABASE=Clie PEG-TJ35 PDA Mass Storage usb:v054Cp016B* ID_MODEL_FROM_DATABASE=Mobile HDD usb:v054Cp016D* ID_MODEL_FROM_DATABASE=IC Recorder (SX) usb:v054Cp016E* ID_MODEL_FROM_DATABASE=DPP-EX50 Digital Photo Printer usb:v054Cp0171* ID_MODEL_FROM_DATABASE=Fingerprint Sensor 3500 usb:v054Cp017E* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp017F* ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN usb:v054Cp0180* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0181* ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN usb:v054Cp0182* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0183* ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN usb:v054Cp0184* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0185* ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN usb:v054Cp0186* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0187* ID_MODEL_FROM_DATABASE=Hi-MD MZ-NH600 WALKMAN usb:v054Cp0188* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp018A* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp018B* ID_MODEL_FROM_DATABASE=Hi-MD SOUND GATE usb:v054Cp019E* ID_MODEL_FROM_DATABASE=Micro Vault 1.0G Mass Storage usb:v054Cp01AD* ID_MODEL_FROM_DATABASE=ATRAC HDD PA usb:v054Cp01BB* ID_MODEL_FROM_DATABASE=FeliCa S320 [PaSoRi] usb:v054Cp01BD* ID_MODEL_FROM_DATABASE=MRW62E Multi-Card Reader/Writer usb:v054Cp01C3* ID_MODEL_FROM_DATABASE=NW-E55 Network Walkman usb:v054Cp01C6* ID_MODEL_FROM_DATABASE=MEMORY P-AUDIO usb:v054Cp01C7* ID_MODEL_FROM_DATABASE=Printing Support usb:v054Cp01C8* ID_MODEL_FROM_DATABASE=PSP Type A usb:v054Cp01C9* ID_MODEL_FROM_DATABASE=PSP Type B usb:v054Cp01D0* ID_MODEL_FROM_DATABASE=DVD+RW External Drive DRU-700A usb:v054Cp01D5* ID_MODEL_FROM_DATABASE=IC RECORDER usb:v054Cp01DE* ID_MODEL_FROM_DATABASE=VRD-VC10 [Video Capture] usb:v054Cp01E8* ID_MODEL_FROM_DATABASE=UP-DR150 Photo Printer usb:v054Cp01E9* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp01EA* ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN usb:v054Cp01EE* ID_MODEL_FROM_DATABASE=IC RECORDER usb:v054Cp01FA* ID_MODEL_FROM_DATABASE=IC Recorder (P) usb:v054Cp01FB* ID_MODEL_FROM_DATABASE=NW-E405 Network Walkman usb:v054Cp020F* ID_MODEL_FROM_DATABASE=Device usb:v054Cp0210* ID_MODEL_FROM_DATABASE=ATRAC HDD PA usb:v054Cp0219* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp021A* ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN usb:v054Cp021B* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp021C* ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN usb:v054Cp021D* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0227* ID_MODEL_FROM_DATABASE=Printing Support usb:v054Cp022C* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp022D* ID_MODEL_FROM_DATABASE=Hi-MD AUDIO usb:v054Cp0233* ID_MODEL_FROM_DATABASE=ATRAC HDD PA usb:v054Cp0236* ID_MODEL_FROM_DATABASE=Mobile HDD usb:v054Cp023B* ID_MODEL_FROM_DATABASE=DVD+RW External Drive DRU-800UL usb:v054Cp023C* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp023D* ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN usb:v054Cp0243* ID_MODEL_FROM_DATABASE=MicroVault Flash Drive usb:v054Cp024B* ID_MODEL_FROM_DATABASE=Vaio VGX Mouse usb:v054Cp0257* ID_MODEL_FROM_DATABASE=IFU-WLM2 USB Wireless LAN Module (Wireless Mode) usb:v054Cp0258* ID_MODEL_FROM_DATABASE=IFU-WLM2 USB Wireless LAN Module (Memory Mode) usb:v054Cp0259* ID_MODEL_FROM_DATABASE=IC RECORDER usb:v054Cp0267* ID_MODEL_FROM_DATABASE=Tachikoma Device usb:v054Cp0268* ID_MODEL_FROM_DATABASE=Batoh Device / PlayStation 3 Controller usb:v054Cp0269* ID_MODEL_FROM_DATABASE=HDD WALKMAN usb:v054Cp026A* ID_MODEL_FROM_DATABASE=HDD WALKMAN usb:v054Cp0271* ID_MODEL_FROM_DATABASE=IC Recorder (P) usb:v054Cp027C* ID_MODEL_FROM_DATABASE=NETWORK WALKMAN usb:v054Cp027E* ID_MODEL_FROM_DATABASE=SONY Communicator usb:v054Cp027F* ID_MODEL_FROM_DATABASE=IC RECORDER usb:v054Cp0286* ID_MODEL_FROM_DATABASE=Net MD usb:v054Cp0287* ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN usb:v054Cp0290* ID_MODEL_FROM_DATABASE=VGP-UVC100 Visual Communication Camera usb:v054Cp029B* ID_MODEL_FROM_DATABASE=PRS-500 eBook reader usb:v054Cp02A5* ID_MODEL_FROM_DATABASE=MicroVault Flash Drive usb:v054Cp02AF* ID_MODEL_FROM_DATABASE=Handycam DCR-DVD306E usb:v054Cp02C4* ID_MODEL_FROM_DATABASE=Device usb:v054Cp02D1* ID_MODEL_FROM_DATABASE=DVD RW usb:v054Cp02D2* ID_MODEL_FROM_DATABASE=PSP Slim usb:v054Cp02D8* ID_MODEL_FROM_DATABASE=SBAC-US10 SxS PRO memory card reader/writer usb:v054Cp02E1* ID_MODEL_FROM_DATABASE=FeliCa S330 [PaSoRi] usb:v054Cp02EA* ID_MODEL_FROM_DATABASE=PlayStation 3 Memory Card Adaptor usb:v054Cp02F9* ID_MODEL_FROM_DATABASE=DSC-H9 usb:v054Cp0317* ID_MODEL_FROM_DATABASE=WALKMAN usb:v054Cp031A* ID_MODEL_FROM_DATABASE=Walkman NWD-B103F usb:v054Cp031E* ID_MODEL_FROM_DATABASE=PRS-300/PRS-505 eBook reader usb:v054Cp0325* ID_MODEL_FROM_DATABASE=NWZ-A818 usb:v054Cp033E* ID_MODEL_FROM_DATABASE=DSC-W120/W290 usb:v054Cp0346* ID_MODEL_FROM_DATABASE=Handycam DCR-SR55E usb:v054Cp0348* ID_MODEL_FROM_DATABASE=HandyCam HDR-TG3E usb:v054Cp035B* ID_MODEL_FROM_DATABASE=Walkman NWZ-A828 usb:v054Cp035C* ID_MODEL_FROM_DATABASE=NWZ-A726/A728/A729 usb:v054Cp035F* ID_MODEL_FROM_DATABASE=UP-DR200 Photo Printer usb:v054Cp0382* ID_MODEL_FROM_DATABASE=Memory Stick PRO-HG Duo Adaptor (MSAC-UAH1) usb:v054Cp0385* ID_MODEL_FROM_DATABASE=Walkman NWZ-E436F usb:v054Cp0387* ID_MODEL_FROM_DATABASE=IC Recorder (P) usb:v054Cp03BC* ID_MODEL_FROM_DATABASE=Webbie HD - MHS-CM1 usb:v054Cp03D1* ID_MODEL_FROM_DATABASE=DPF-X95 usb:v054Cp03D3* ID_MODEL_FROM_DATABASE=DR-BT100CX usb:v054Cp03D5* ID_MODEL_FROM_DATABASE=PlayStation Move motion controller usb:v054Cp03FC* ID_MODEL_FROM_DATABASE=WALKMAN [NWZ-E345] usb:v054Cp03FD* ID_MODEL_FROM_DATABASE=Walkman NWZ-E443 usb:v054Cp042F* ID_MODEL_FROM_DATABASE=PlayStation Move navigation controller usb:v054Cp0440* ID_MODEL_FROM_DATABASE=DSC-H55 usb:v054Cp0485* ID_MODEL_FROM_DATABASE=MHS-PM5 HD camcorder usb:v054Cp04CB* ID_MODEL_FROM_DATABASE=WALKMAN NWZ-E354 usb:v054Cp0541* ID_MODEL_FROM_DATABASE=DSC-HX100V [Cybershot Digital Still Camera] usb:v054Cp05C4* ID_MODEL_FROM_DATABASE=DualShock 4 usb:v054Cp0689* ID_MODEL_FROM_DATABASE=Walkman NWZ-B173F usb:v054Cp06BB* ID_MODEL_FROM_DATABASE=WALKMAN NWZ-F805 usb:v054Cp088C* ID_MODEL_FROM_DATABASE=Portable Headphone Amplifier usb:v054Cp1000* ID_MODEL_FROM_DATABASE=Wireless Buzz! Receiver usb:v054D* ID_VENDOR_FROM_DATABASE=Try Corp. usb:v054E* ID_VENDOR_FROM_DATABASE=Proside Corp. usb:v054F* ID_VENDOR_FROM_DATABASE=WYSE Technology Taiwan usb:v0550* ID_VENDOR_FROM_DATABASE=Fuji Xerox Co., Ltd usb:v0550p0002* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v0550p0004* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v0550p0005* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v0550p000B* ID_MODEL_FROM_DATABASE=Workcentre 24 usb:v0550p014E* ID_MODEL_FROM_DATABASE=CM215b Printer usb:v0550p0165* ID_MODEL_FROM_DATABASE=DocuPrint M215b usb:v0551* ID_VENDOR_FROM_DATABASE=CompuTrend Systems, Inc. usb:v0552* ID_VENDOR_FROM_DATABASE=Philips Monitors usb:v0553* ID_VENDOR_FROM_DATABASE=STMicroelectronics Imaging Division (VLSI Vision) usb:v0553p0001* ID_MODEL_FROM_DATABASE=TerraCAM usb:v0553p0002* ID_MODEL_FROM_DATABASE=CPiA Webcam usb:v0553p0100* ID_MODEL_FROM_DATABASE=STV0672 Camera usb:v0553p0140* ID_MODEL_FROM_DATABASE=Video Camera usb:v0553p0150* ID_MODEL_FROM_DATABASE=CDE CAM 100 usb:v0553p0151* ID_MODEL_FROM_DATABASE=Digital Blue QX5 Microscope usb:v0553p0200* ID_MODEL_FROM_DATABASE=Dual-mode Camera0 usb:v0553p0201* ID_MODEL_FROM_DATABASE=Dual-mode Camera1 usb:v0553p0202* ID_MODEL_FROM_DATABASE=STV0680 Camera usb:v0553p0674* ID_MODEL_FROM_DATABASE=Multi-mode Camera usb:v0553p0679* ID_MODEL_FROM_DATABASE=NMS Video Camera (Webcam) usb:v0553p1002* ID_MODEL_FROM_DATABASE=Che-ez! Splash usb:v0554* ID_VENDOR_FROM_DATABASE=Dictaphone Corp. usb:v0555* ID_VENDOR_FROM_DATABASE=ANAM S&T Co., Ltd usb:v0556* ID_VENDOR_FROM_DATABASE=Asahi Kasei Microsystems Co., Ltd usb:v0556p0001* ID_MODEL_FROM_DATABASE=AK5370 I/F A/D Converter usb:v0557* ID_VENDOR_FROM_DATABASE=ATEN International Co., Ltd usb:v0557p2001* ID_MODEL_FROM_DATABASE=UC-1284 Printer Port usb:v0557p2002* ID_MODEL_FROM_DATABASE=10Mbps Ethernet [klsi] usb:v0557p2004* ID_MODEL_FROM_DATABASE=UC-100KM PS/2 Mouse and Keyboard adapter usb:v0557p2006* ID_MODEL_FROM_DATABASE=UC-1284B Printer Port usb:v0557p2007* ID_MODEL_FROM_DATABASE=UC-110T 100Mbps Ethernet [pegasus] usb:v0557p2008* ID_MODEL_FROM_DATABASE=UC-232A Serial Port [pl2303] usb:v0557p2009* ID_MODEL_FROM_DATABASE=UC-210T Ethernet usb:v0557p2011* ID_MODEL_FROM_DATABASE=UC-2324 4xSerial Ports [mos7840] usb:v0557p2202* ID_MODEL_FROM_DATABASE=CS124U Miniview II KVM Switch usb:v0557p2213* ID_MODEL_FROM_DATABASE=CS682 2-Port USB 2.0 DVI KVM Switch usb:v0557p2221* ID_MODEL_FROM_DATABASE=Winbond Hermon usb:v0557p2404* ID_MODEL_FROM_DATABASE=4-port switch usb:v0557p2600* ID_MODEL_FROM_DATABASE=IDE Bridge usb:v0557p2701* ID_MODEL_FROM_DATABASE=CE700A KVM Extender usb:v0557p4000* ID_MODEL_FROM_DATABASE=DSB-650 10Mbps Ethernet [klsi] usb:v0557p7000* ID_MODEL_FROM_DATABASE=Hub usb:v0557p7820* ID_MODEL_FROM_DATABASE=UC-2322 2xSerial Ports [mos7820] usb:v0557p8021* ID_MODEL_FROM_DATABASE=CS1764A [CubiQ DVI KVMP Switch] usb:v0558* ID_VENDOR_FROM_DATABASE=Truevision, Inc. usb:v0558p1009* ID_MODEL_FROM_DATABASE=GW Instek GDS-1000 Oscilloscope usb:v0558p100A* ID_MODEL_FROM_DATABASE=GW Instek GDS-1000A Oscilloscope usb:v0558p2009* ID_MODEL_FROM_DATABASE=GW Instek GDS-2000 Oscilloscope usb:v0559* ID_VENDOR_FROM_DATABASE=Cadence Design Systems, Inc. usb:v055A* ID_VENDOR_FROM_DATABASE=Kenwood USA usb:v055B* ID_VENDOR_FROM_DATABASE=KnowledgeTek, Inc. usb:v055C* ID_VENDOR_FROM_DATABASE=Proton Electronic Ind. usb:v055D* ID_VENDOR_FROM_DATABASE=Samsung Electro-Mechanics Co. usb:v055Dp0001* ID_MODEL_FROM_DATABASE=Keyboard usb:v055Dp0BB1* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v055Dp1030* ID_MODEL_FROM_DATABASE=Optical Wheel Mouse (OMS3CB/OMGB30) usb:v055Dp1031* ID_MODEL_FROM_DATABASE=Optical Wheel Mouse (OMA3CB/OMGI30) usb:v055Dp1040* ID_MODEL_FROM_DATABASE=Mouse HID Device usb:v055Dp1050* ID_MODEL_FROM_DATABASE=E-Mail Optical Wheel Mouse (OMS3CE) usb:v055Dp1080* ID_MODEL_FROM_DATABASE=Optical Wheel Mouse (OMS3CH) usb:v055Dp2020* ID_MODEL_FROM_DATABASE=Floppy Disk Drive usb:v055Dp6780* ID_MODEL_FROM_DATABASE=Keyboard V1 usb:v055Dp6781* ID_MODEL_FROM_DATABASE=Keyboard Mouse usb:v055Dp8001* ID_MODEL_FROM_DATABASE=E.M. Hub usb:v055Dp9000* ID_MODEL_FROM_DATABASE=AnyCam [pwc] usb:v055Dp9001* ID_MODEL_FROM_DATABASE=MPC-C30 AnyCam Premium for Notebooks [pwc] usb:v055DpA000* ID_MODEL_FROM_DATABASE=SWL-2100U usb:v055DpA010* ID_MODEL_FROM_DATABASE=WLAN Adapter(SWL-2300) usb:v055DpA011* ID_MODEL_FROM_DATABASE=Boot Device usb:v055DpA012* ID_MODEL_FROM_DATABASE=WLAN Adapter(SWL-2300) usb:v055DpA013* ID_MODEL_FROM_DATABASE=WLAN Adapter(SWL-2350) usb:v055DpA230* ID_MODEL_FROM_DATABASE=Boot Device usb:v055DpB000* ID_MODEL_FROM_DATABASE=11Mbps WLAN Mini Adapter usb:v055DpB230* ID_MODEL_FROM_DATABASE=Netopia 802.11b WLAN Adapter usb:v055DpB231* ID_MODEL_FROM_DATABASE=LG Wireless LAN 11b Adapter usb:v055E* ID_VENDOR_FROM_DATABASE=CTX Opto-Electronics Corp. usb:v055F* ID_VENDOR_FROM_DATABASE=Mustek Systems, Inc. usb:v055Fp0001* ID_MODEL_FROM_DATABASE=ScanExpress 1200 CU usb:v055Fp0002* ID_MODEL_FROM_DATABASE=ScanExpress 600 CU usb:v055Fp0003* ID_MODEL_FROM_DATABASE=ScanExpress 1200 USB usb:v055Fp0006* ID_MODEL_FROM_DATABASE=ScanExpress 1200 UB usb:v055Fp0007* ID_MODEL_FROM_DATABASE=ScanExpress 1200 USB Plus usb:v055Fp0008* ID_MODEL_FROM_DATABASE=ScanExpress 1200 CU Plus usb:v055Fp0010* ID_MODEL_FROM_DATABASE=BearPaw 1200F usb:v055Fp0210* ID_MODEL_FROM_DATABASE=ScanExpress A3 USB usb:v055Fp0218* ID_MODEL_FROM_DATABASE=BearPaw 2400 TA usb:v055Fp0219* ID_MODEL_FROM_DATABASE=BearPaw 2400 TA Plus usb:v055Fp021A* ID_MODEL_FROM_DATABASE=BearPaw 2448 TA Plus usb:v055Fp021B* ID_MODEL_FROM_DATABASE=BearPaw 1200 CU Plus usb:v055Fp021C* ID_MODEL_FROM_DATABASE=BearPaw 1200 CU Plus usb:v055Fp021D* ID_MODEL_FROM_DATABASE=BearPaw 2400 CU Plus usb:v055Fp021E* ID_MODEL_FROM_DATABASE=BearPaw 1200 TA/CS usb:v055Fp021F* ID_MODEL_FROM_DATABASE=SNAPSCAN e22 usb:v055Fp0400* ID_MODEL_FROM_DATABASE=BearPaw 2400 TA Pro usb:v055Fp0401* ID_MODEL_FROM_DATABASE=P 3600 A3 Pro usb:v055Fp0408* ID_MODEL_FROM_DATABASE=BearPaw 2448 CU Pro usb:v055Fp0409* ID_MODEL_FROM_DATABASE=BearPaw 2448 TA Pro usb:v055Fp040B* ID_MODEL_FROM_DATABASE=ScanExpress A3 USB 1200 PRO usb:v055Fp0873* ID_MODEL_FROM_DATABASE=ScanExpress 600 USB usb:v055Fp1000* ID_MODEL_FROM_DATABASE=BearPaw 4800 TA Pro usb:v055FpA350* ID_MODEL_FROM_DATABASE=gSmart 350 Camera usb:v055FpA800* ID_MODEL_FROM_DATABASE=MDC 800 Camera usb:v055FpB500* ID_MODEL_FROM_DATABASE=MDC 3000 Camera usb:v055FpC005* ID_MODEL_FROM_DATABASE=PC CAM 300A usb:v055FpC200* ID_MODEL_FROM_DATABASE=gSmart 300 usb:v055FpC211* ID_MODEL_FROM_DATABASE=Kowa Bs888e Microcamera usb:v055FpC220* ID_MODEL_FROM_DATABASE=gSmart mini usb:v055FpC230* ID_MODEL_FROM_DATABASE=Digicam 330K usb:v055FpC232* ID_MODEL_FROM_DATABASE=MDC3500 Camera usb:v055FpC360* ID_MODEL_FROM_DATABASE=DV 4000 Camera usb:v055FpC420* ID_MODEL_FROM_DATABASE=gSmart mini 2 Camera usb:v055FpC430* ID_MODEL_FROM_DATABASE=gSmart LCD 2 Camera usb:v055FpC440* ID_MODEL_FROM_DATABASE=DV 3000 Camera usb:v055FpC520* ID_MODEL_FROM_DATABASE=gSmart mini 3 Camera usb:v055FpC530* ID_MODEL_FROM_DATABASE=gSmart LCD 2 Camera usb:v055FpC540* ID_MODEL_FROM_DATABASE=gSmart D30 Camera usb:v055FpC630* ID_MODEL_FROM_DATABASE=MDC 4000 Camera usb:v055FpC631* ID_MODEL_FROM_DATABASE=MDC 4000 Camera usb:v055FpC650* ID_MODEL_FROM_DATABASE=MDC 5500Z Camera usb:v055FpD001* ID_MODEL_FROM_DATABASE=WCam 300 usb:v055FpD003* ID_MODEL_FROM_DATABASE=WCam 300A usb:v055FpD004* ID_MODEL_FROM_DATABASE=WCam 300AN usb:v0560* ID_VENDOR_FROM_DATABASE=Interface Corp. usb:v0561* ID_VENDOR_FROM_DATABASE=Oasis Design, Inc. usb:v0562* ID_VENDOR_FROM_DATABASE=Telex Communications, Inc. usb:v0562p0001* ID_MODEL_FROM_DATABASE=Enhanced Microphone usb:v0562p0002* ID_MODEL_FROM_DATABASE=Telex Microphone usb:v0563* ID_VENDOR_FROM_DATABASE=Immersion Corp. usb:v0564* ID_VENDOR_FROM_DATABASE=Kodak Digital Product Center, Japan Ltd. (formerly Chinon Industries Inc.) usb:v0565* ID_VENDOR_FROM_DATABASE=Peracom Networks, Inc. usb:v0565p0001* ID_MODEL_FROM_DATABASE=Serial Port [etek] usb:v0565p0002* ID_MODEL_FROM_DATABASE=Enet Ethernet [klsi] usb:v0565p0003* ID_MODEL_FROM_DATABASE=@Home Networks Ethernet [klsi] usb:v0565p0005* ID_MODEL_FROM_DATABASE=Enet2 Ethernet [klsi] usb:v0565p0041* ID_MODEL_FROM_DATABASE=Peracom Remote NDIS Ethernet Adapter usb:v0566* ID_VENDOR_FROM_DATABASE=Monterey International Corp. usb:v0566p0110* ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 usb:v0566p1001* ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 usb:v0566p1002* ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 usb:v0566p1003* ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 usb:v0566p1004* ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 usb:v0566p1005* ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 usb:v0566p1006* ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 usb:v0566p1007* ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 usb:v0566p2800* ID_MODEL_FROM_DATABASE=MIC K/B usb:v0566p2801* ID_MODEL_FROM_DATABASE=MIC K/B Mouse usb:v0566p2802* ID_MODEL_FROM_DATABASE=Kbd Hub usb:v0566p3002* ID_MODEL_FROM_DATABASE=Keyboard usb:v0566p3004* ID_MODEL_FROM_DATABASE=Genius KB-29E usb:v0566p3107* ID_MODEL_FROM_DATABASE=Keyboard usb:v0567* ID_VENDOR_FROM_DATABASE=Xyratex International, Ltd usb:v0568* ID_VENDOR_FROM_DATABASE=Quartz Ingenierie usb:v0569* ID_VENDOR_FROM_DATABASE=SegaSoft usb:v056A* ID_VENDOR_FROM_DATABASE=Wacom Co., Ltd usb:v056Ap0000* ID_MODEL_FROM_DATABASE=PenPartner usb:v056Ap0001* ID_MODEL_FROM_DATABASE=PenPartner 4x5 usb:v056Ap0002* ID_MODEL_FROM_DATABASE=PenPartner 6x8 usb:v056Ap0003* ID_MODEL_FROM_DATABASE=PTU-600 [Cintiq Partner] usb:v056Ap0010* ID_MODEL_FROM_DATABASE=ET-0405 [Graphire] usb:v056Ap0011* ID_MODEL_FROM_DATABASE=ET-0405A [Graphire2 (4x5)] usb:v056Ap0012* ID_MODEL_FROM_DATABASE=ET-0507A [Graphire2 (5x7)] usb:v056Ap0013* ID_MODEL_FROM_DATABASE=CTE-430 [Graphire3 (4x5)] usb:v056Ap0014* ID_MODEL_FROM_DATABASE=CTE-630 [Graphire3 (6x8)] usb:v056Ap0015* ID_MODEL_FROM_DATABASE=CTE-440 [Graphire4 (4x5)] usb:v056Ap0016* ID_MODEL_FROM_DATABASE=CTE-640 [Graphire4 (6x8)] usb:v056Ap0017* ID_MODEL_FROM_DATABASE=CTE-450 [Bamboo Fun (small)] usb:v056Ap0018* ID_MODEL_FROM_DATABASE=CTE-650 [Bamboo Fun (medium)] usb:v056Ap0019* ID_MODEL_FROM_DATABASE=CTE-631 [Bamboo One] usb:v056Ap0020* ID_MODEL_FROM_DATABASE=GD-0405 [Intuos (4x5)] usb:v056Ap0021* ID_MODEL_FROM_DATABASE=GD-0608 [Intuos (6x8)] usb:v056Ap0022* ID_MODEL_FROM_DATABASE=GD-0912 [Intuos (9x12)] usb:v056Ap0023* ID_MODEL_FROM_DATABASE=GD-1212 [Intuos (12x12)] usb:v056Ap0024* ID_MODEL_FROM_DATABASE=GD-1218 [Intuos (12x18)] usb:v056Ap0026* ID_MODEL_FROM_DATABASE=PTH-450 [Intuos5 touch (S)] usb:v056Ap0027* ID_MODEL_FROM_DATABASE=PTH-650 [Intuos5 touch (M)] usb:v056Ap0028* ID_MODEL_FROM_DATABASE=PTH-850 [Intuos5 touch (L)] usb:v056Ap0029* ID_MODEL_FROM_DATABASE=PTK-450 [Intuos5 (S)] usb:v056Ap002A* ID_MODEL_FROM_DATABASE=PTK-650 [Intuos5 (M)] usb:v056Ap0030* ID_MODEL_FROM_DATABASE=PL400 usb:v056Ap0031* ID_MODEL_FROM_DATABASE=PL500 usb:v056Ap0032* ID_MODEL_FROM_DATABASE=PL600 usb:v056Ap0033* ID_MODEL_FROM_DATABASE=PL600SX usb:v056Ap0034* ID_MODEL_FROM_DATABASE=PL550 usb:v056Ap0035* ID_MODEL_FROM_DATABASE=PL800 usb:v056Ap0037* ID_MODEL_FROM_DATABASE=PL700 usb:v056Ap0038* ID_MODEL_FROM_DATABASE=PL510 usb:v056Ap0039* ID_MODEL_FROM_DATABASE=DTU-710 usb:v056Ap003F* ID_MODEL_FROM_DATABASE=DTZ-2100 [Cintiq 21UX] usb:v056Ap0041* ID_MODEL_FROM_DATABASE=XD-0405-U [Intuos2 (4x5)] usb:v056Ap0042* ID_MODEL_FROM_DATABASE=XD-0608-U [Intuos2 (6x8)] usb:v056Ap0043* ID_MODEL_FROM_DATABASE=XD-0912-U [Intuos2 (9x12)] usb:v056Ap0044* ID_MODEL_FROM_DATABASE=XD-1212-U [Intuos2 (12x12)] usb:v056Ap0045* ID_MODEL_FROM_DATABASE=XD-1218-U [Intuos2 (12x18)] usb:v056Ap0047* ID_MODEL_FROM_DATABASE=Intuos2 6x8 usb:v056Ap0057* ID_MODEL_FROM_DATABASE=DTK-2241 usb:v056Ap0059* ID_MODEL_FROM_DATABASE=DTH-2242 tablet usb:v056Ap005B* ID_MODEL_FROM_DATABASE=DTH-2200 [Cintiq 22HD Touch] tablet usb:v056Ap005D* ID_MODEL_FROM_DATABASE=DTH-2242 touchscreen usb:v056Ap005E* ID_MODEL_FROM_DATABASE=DTH-2200 [Cintiq 22HD Touch] touchscreen usb:v056Ap0060* ID_MODEL_FROM_DATABASE=FT-0405 [Volito, PenPartner, PenStation (4x5)] usb:v056Ap0061* ID_MODEL_FROM_DATABASE=FT-0203 [Volito, PenPartner, PenStation (2x3)] usb:v056Ap0062* ID_MODEL_FROM_DATABASE=CTF-420 [Volito2] usb:v056Ap0063* ID_MODEL_FROM_DATABASE=CTF-220 [BizTablet] usb:v056Ap0064* ID_MODEL_FROM_DATABASE=CTF-221 [PenPartner2] usb:v056Ap0065* ID_MODEL_FROM_DATABASE=MTE-450 [Bamboo] usb:v056Ap0069* ID_MODEL_FROM_DATABASE=CTF-430 [Bamboo One] usb:v056Ap006A* ID_MODEL_FROM_DATABASE=CTE-460 [Bamboo One Pen (S)] usb:v056Ap006B* ID_MODEL_FROM_DATABASE=CTE-660 [Bamboo One Pen (M)] usb:v056Ap0081* ID_MODEL_FROM_DATABASE=CTE-630BT [Graphire Wireless (6x8)] usb:v056Ap0084* ID_MODEL_FROM_DATABASE=Wireless adapter for Bamboo tablets usb:v056Ap0090* ID_MODEL_FROM_DATABASE=TPC90 usb:v056Ap0093* ID_MODEL_FROM_DATABASE=TPC93 usb:v056Ap0097* ID_MODEL_FROM_DATABASE=TPC97 usb:v056Ap009A* ID_MODEL_FROM_DATABASE=TPC9A usb:v056Ap00B0* ID_MODEL_FROM_DATABASE=PTZ-430 [Intuos3 (4x5)] usb:v056Ap00B1* ID_MODEL_FROM_DATABASE=PTZ-630 [Intuos3 (6x8)] usb:v056Ap00B2* ID_MODEL_FROM_DATABASE=PTZ-930 [Intuos3 (9x12)] usb:v056Ap00B3* ID_MODEL_FROM_DATABASE=PTZ-1230 [Intuos3 (12x12)] usb:v056Ap00B4* ID_MODEL_FROM_DATABASE=PTZ-1231W [Intuos3 (12x19)] usb:v056Ap00B5* ID_MODEL_FROM_DATABASE=PTZ-631W [Intuos3 (6x11)] usb:v056Ap00B7* ID_MODEL_FROM_DATABASE=PTZ-431W [Intuos3 (4x6)] usb:v056Ap00B8* ID_MODEL_FROM_DATABASE=PTK-440 [Intuos4 (4x6)] usb:v056Ap00B9* ID_MODEL_FROM_DATABASE=PTK-640 [Intuos4 (6x9)] usb:v056Ap00BA* ID_MODEL_FROM_DATABASE=PTK-840 [Intuos4 (8x13)] usb:v056Ap00BB* ID_MODEL_FROM_DATABASE=PTK-1240 [Intuos4 (12x19)] usb:v056Ap00C0* ID_MODEL_FROM_DATABASE=DTF-521 usb:v056Ap00C4* ID_MODEL_FROM_DATABASE=DTF-720 usb:v056Ap00C5* ID_MODEL_FROM_DATABASE=DTZ-20WSX [Cintiq 20WSX] usb:v056Ap00C6* ID_MODEL_FROM_DATABASE=DTZ-12WX [Cintiq 12WX] usb:v056Ap00C7* ID_MODEL_FROM_DATABASE=DTU-1931 usb:v056Ap00CC* ID_MODEL_FROM_DATABASE=DTK-2100 [Cintiq 21UX] usb:v056Ap00CE* ID_MODEL_FROM_DATABASE=DTU-2231 usb:v056Ap00D0* ID_MODEL_FROM_DATABASE=CTT-460 [Bamboo Touch] usb:v056Ap00D1* ID_MODEL_FROM_DATABASE=CTH-460 [Bamboo Pen & Touch] usb:v056Ap00D2* ID_MODEL_FROM_DATABASE=CTH-461 [Bamboo Fun/Craft/Comic Pen & Touch (S)] usb:v056Ap00D3* ID_MODEL_FROM_DATABASE=CTH-661 [Bamboo Fun/Comic Pen & Touch (M)] usb:v056Ap00D4* ID_MODEL_FROM_DATABASE=CTL-460 [Bamboo Pen (S)] usb:v056Ap00D5* ID_MODEL_FROM_DATABASE=CTL-660 [Bamboo Pen (M)] usb:v056Ap00D6* ID_MODEL_FROM_DATABASE=CTH-460 [Bamboo Pen & Touch] usb:v056Ap00D7* ID_MODEL_FROM_DATABASE=CTH-461 [Bamboo Fun/Craft/Comic Pen & Touch (S)] usb:v056Ap00D8* ID_MODEL_FROM_DATABASE=CTH-661 [Bamboo Fun/Comic Pen & Touch (M)] usb:v056Ap00D9* ID_MODEL_FROM_DATABASE=CTT-460 [Bamboo Touch] usb:v056Ap00DA* ID_MODEL_FROM_DATABASE=CTH-461SE [Bamboo Pen & Touch Special Edition (S)] usb:v056Ap00DB* ID_MODEL_FROM_DATABASE=CTH-661SE [Bamboo Pen & Touch Special Edition (M)] usb:v056Ap00DC* ID_MODEL_FROM_DATABASE=CTT-470 [Bamboo Touch] usb:v056Ap00DD* ID_MODEL_FROM_DATABASE=CTL-470 [Bamboo Connect] usb:v056Ap00DE* ID_MODEL_FROM_DATABASE=CTH-470 [Bamboo Fun Pen & Touch] usb:v056Ap00DF* ID_MODEL_FROM_DATABASE=CTH-670 [Bamboo Create/Fun] usb:v056Ap00E2* ID_MODEL_FROM_DATABASE=TPCE2 usb:v056Ap00E3* ID_MODEL_FROM_DATABASE=TPCE3 usb:v056Ap00E5* ID_MODEL_FROM_DATABASE=TPCE5 usb:v056Ap00E6* ID_MODEL_FROM_DATABASE=TPCE6 usb:v056Ap00EC* ID_MODEL_FROM_DATABASE=TPCEC usb:v056Ap00ED* ID_MODEL_FROM_DATABASE=TPCED usb:v056Ap00EF* ID_MODEL_FROM_DATABASE=TPCEF usb:v056Ap00F4* ID_MODEL_FROM_DATABASE=DTK-2400 [Cintiq 24HD] tablet usb:v056Ap00F6* ID_MODEL_FROM_DATABASE=DTH-2400 [Cintiq 24HD touch] touchscreen usb:v056Ap00F8* ID_MODEL_FROM_DATABASE=DTH-2400 [Cintiq 24HD touch] tablet usb:v056Ap00FA* ID_MODEL_FROM_DATABASE=DTK-2200 [Cintiq 22HD] tablet usb:v056Ap00FB* ID_MODEL_FROM_DATABASE=DTU-1031 usb:v056Ap0100* ID_MODEL_FROM_DATABASE=TPC100 usb:v056Ap0101* ID_MODEL_FROM_DATABASE=TPC101 usb:v056Ap010D* ID_MODEL_FROM_DATABASE=TPC10D usb:v056Ap010E* ID_MODEL_FROM_DATABASE=TPC10E usb:v056Ap010F* ID_MODEL_FROM_DATABASE=TPC10F usb:v056Ap0116* ID_MODEL_FROM_DATABASE=TPC116 usb:v056Ap012C* ID_MODEL_FROM_DATABASE=TPC12C usb:v056Ap0300* ID_MODEL_FROM_DATABASE=CTL-471 [Bamboo Splash, One by Wacom (S)] usb:v056Ap0301* ID_MODEL_FROM_DATABASE=CTL-671 [One by Wacom (M)] usb:v056Ap0302* ID_MODEL_FROM_DATABASE=CTH-480 [Intuos Pen & Touch (S)] usb:v056Ap0303* ID_MODEL_FROM_DATABASE=CTH-680 [Intuos Pen & Touch (M)] usb:v056Ap0304* ID_MODEL_FROM_DATABASE=DTK-1300 [Cintiq 13HD] usb:v056Ap0307* ID_MODEL_FROM_DATABASE=DTH-A1300 [Cintiq Companion Hybrid] tablet usb:v056Ap0309* ID_MODEL_FROM_DATABASE=DTH-A1300 [Cintiq Companion Hybrid] touchscreen usb:v056Ap030E* ID_MODEL_FROM_DATABASE=CTL-480 [Intuos Pen (S)] usb:v056Ap0314* ID_MODEL_FROM_DATABASE=PTH-451 [Intuos pro (S)] usb:v056Ap0315* ID_MODEL_FROM_DATABASE=PTH-651 [Intuos pro (M)] usb:v056Ap0317* ID_MODEL_FROM_DATABASE=PTH-851 [Intuos pro (L)] usb:v056Ap032F* ID_MODEL_FROM_DATABASE=DTU-1031X usb:v056Ap0400* ID_MODEL_FROM_DATABASE=PenPartner 4x5 usb:v056Ap4001* ID_MODEL_FROM_DATABASE=TPC4001 usb:v056Ap4004* ID_MODEL_FROM_DATABASE=TPC4004 usb:v056Ap4850* ID_MODEL_FROM_DATABASE=PenPartner 6x8 usb:v056Ap5000* ID_MODEL_FROM_DATABASE=TPC5000 usb:v056Ap5002* ID_MODEL_FROM_DATABASE=TPC5002 usb:v056Ap5010* ID_MODEL_FROM_DATABASE=TPC5010 usb:v056B* ID_VENDOR_FROM_DATABASE=Decicon, Inc. usb:v056C* ID_VENDOR_FROM_DATABASE=eTEK Labs usb:v056Cp0006* ID_MODEL_FROM_DATABASE=KwikLink Host-Host Connector usb:v056Cp8007* ID_MODEL_FROM_DATABASE=Kwik232 Serial Port usb:v056Cp8100* ID_MODEL_FROM_DATABASE=KwikLink Host-Host Connector usb:v056Cp8101* ID_MODEL_FROM_DATABASE=KwikLink USB-USB Bridge usb:v056D* ID_VENDOR_FROM_DATABASE=EIZO Corp. usb:v056Dp0000* ID_MODEL_FROM_DATABASE=Hub usb:v056Dp0001* ID_MODEL_FROM_DATABASE=Monitor usb:v056Dp0002* ID_MODEL_FROM_DATABASE=HID Monitor Controls usb:v056Dp0003* ID_MODEL_FROM_DATABASE=Device Bay Controller usb:v056E* ID_VENDOR_FROM_DATABASE=Elecom Co., Ltd usb:v056Ep0002* ID_MODEL_FROM_DATABASE=29UO Mouse usb:v056Ep0072* ID_MODEL_FROM_DATABASE=Mouse usb:v056Ep200C* ID_MODEL_FROM_DATABASE=LD-USB/TX usb:v056Ep4002* ID_MODEL_FROM_DATABASE=Laneed 100Mbps Ethernet LD-USB/TX [pegasus] usb:v056Ep4005* ID_MODEL_FROM_DATABASE=LD-USBL/TX usb:v056Ep400B* ID_MODEL_FROM_DATABASE=LD-USB/TX usb:v056Ep4010* ID_MODEL_FROM_DATABASE=LD-USB20 usb:v056Ep5003* ID_MODEL_FROM_DATABASE=UC-SGT usb:v056Ep5004* ID_MODEL_FROM_DATABASE=UC-SGT usb:v056Ep6008* ID_MODEL_FROM_DATABASE=Flash Disk usb:v056EpABC1* ID_MODEL_FROM_DATABASE=LD-USB/TX usb:v056F* ID_VENDOR_FROM_DATABASE=Korea Data Systems Co., Ltd usb:v056FpCD00* ID_MODEL_FROM_DATABASE=CDM-751 CD organizer usb:v0570* ID_VENDOR_FROM_DATABASE=Epson America usb:v0571* ID_VENDOR_FROM_DATABASE=Interex, Inc. usb:v0571p0002* ID_MODEL_FROM_DATABASE=echoFX InterView Lite usb:v0572* ID_VENDOR_FROM_DATABASE=Conexant Systems (Rockwell), Inc. usb:v0572p0001* ID_MODEL_FROM_DATABASE=Ezcam II Webcam usb:v0572p0002* ID_MODEL_FROM_DATABASE=Ezcam II Webcam usb:v0572p0040* ID_MODEL_FROM_DATABASE=Wondereye CP-115 Webcam usb:v0572p0041* ID_MODEL_FROM_DATABASE=Webcam Notebook usb:v0572p0042* ID_MODEL_FROM_DATABASE=Webcam Notebook usb:v0572p0320* ID_MODEL_FROM_DATABASE=DVBSky T330 DVB-T2/C tuner usb:v0572p1232* ID_MODEL_FROM_DATABASE=V.90 modem usb:v0572p1234* ID_MODEL_FROM_DATABASE=Typhoon Redfun Modem V90 56k usb:v0572p1252* ID_MODEL_FROM_DATABASE=HCF V90 Data Fax Voice Modem usb:v0572p1253* ID_MODEL_FROM_DATABASE=Zoom V.92 Faxmodem usb:v0572p1300* ID_MODEL_FROM_DATABASE=SoftK56 Data Fax Voice CARP usb:v0572p1301* ID_MODEL_FROM_DATABASE=Modem Enumerator usb:v0572p1328* ID_MODEL_FROM_DATABASE=TrendNet TFM-561 modem usb:v0572p2000* ID_MODEL_FROM_DATABASE=SoftGate 802.11 Adapter usb:v0572p2002* ID_MODEL_FROM_DATABASE=SoftGate 802.11 Adapter usb:v0572p262A* ID_MODEL_FROM_DATABASE=tm5600 Video & Audio Grabber Capture usb:v0572p680C* ID_MODEL_FROM_DATABASE=DVBSky T680C DVB-T2/C tuner usb:v0572p6831* ID_MODEL_FROM_DATABASE=DVBSky S960 DVB-S2 tuner usb:v0572p8390* ID_MODEL_FROM_DATABASE=WinFast PalmTop/Novo TV Video usb:v0572p8392* ID_MODEL_FROM_DATABASE=WinFast PalmTop/Novo TV Video usb:v0572p960C* ID_MODEL_FROM_DATABASE=DVBSky S960C DVB-S2 tuner usb:v0572pC686* ID_MODEL_FROM_DATABASE=Geniatech T220A DVB-T2 TV Stick usb:v0572pC688* ID_MODEL_FROM_DATABASE=Geniatech T230 DVB-T2 TV Stick usb:v0572pCAFC* ID_MODEL_FROM_DATABASE=CX861xx ROM Boot Loader usb:v0572pCAFD* ID_MODEL_FROM_DATABASE=CX82310 ROM Boot Loader usb:v0572pCAFE* ID_MODEL_FROM_DATABASE=AccessRunner ADSL Modem usb:v0572pCB00* ID_MODEL_FROM_DATABASE=ADSL Modem usb:v0572pCB01* ID_MODEL_FROM_DATABASE=ADSL Modem usb:v0572pCB06* ID_MODEL_FROM_DATABASE=StarModem Network Interface usb:v0573* ID_VENDOR_FROM_DATABASE=Zoran Co. Personal Media Division (Nogatech) usb:v0573p0003* ID_MODEL_FROM_DATABASE=USBGear USBG-V1 usb:v0573p0400* ID_MODEL_FROM_DATABASE=D-Link V100 usb:v0573p0600* ID_MODEL_FROM_DATABASE=Dazzle USBVision (1006) usb:v0573p1300* ID_MODEL_FROM_DATABASE=leadtek USBVision (1006) usb:v0573p2000* ID_MODEL_FROM_DATABASE=X10 va10a Wireless Camera usb:v0573p2001* ID_MODEL_FROM_DATABASE=Dazzle EmMe (2001) usb:v0573p2101* ID_MODEL_FROM_DATABASE=Zoran Co. PMD (Nogatech) AV-grabber Manhattan usb:v0573p2D00* ID_MODEL_FROM_DATABASE=Osprey 50 usb:v0573p2D01* ID_MODEL_FROM_DATABASE=Hauppauge USB-Live Model 600 usb:v0573p3000* ID_MODEL_FROM_DATABASE=Dazzle MicroCam (NTSC) usb:v0573p3001* ID_MODEL_FROM_DATABASE=Dazzle MicroCam (PAL) usb:v0573p4000* ID_MODEL_FROM_DATABASE=Nogatech TV! (NTSC) usb:v0573p4001* ID_MODEL_FROM_DATABASE=Nogatech TV! (PAL) usb:v0573p4002* ID_MODEL_FROM_DATABASE=Nogatech TV! (PAL-I-) usb:v0573p4003* ID_MODEL_FROM_DATABASE=Nogatech TV! (MF-) usb:v0573p4008* ID_MODEL_FROM_DATABASE=Nogatech TV! (NTSC) (T) usb:v0573p4009* ID_MODEL_FROM_DATABASE=Nogatech TV! (PAL) (T) usb:v0573p4010* ID_MODEL_FROM_DATABASE=Nogatech TV! (NTSC) (A) usb:v0573p4100* ID_MODEL_FROM_DATABASE=USB-TV FM (NTSC) usb:v0573p4110* ID_MODEL_FROM_DATABASE=PNY USB-TV (NTSC) FM usb:v0573p4400* ID_MODEL_FROM_DATABASE=Nogatech TV! Pro (NTSC) usb:v0573p4401* ID_MODEL_FROM_DATABASE=Nogatech TV! Pro (PAL) usb:v0573p4450* ID_MODEL_FROM_DATABASE=PixelView PlayTv-USB PRO (PAL) FM usb:v0573p4451* ID_MODEL_FROM_DATABASE=Nogatech TV! Pro (PAL+) usb:v0573p4452* ID_MODEL_FROM_DATABASE=Nogatech TV! Pro (PAL-I+) usb:v0573p4500* ID_MODEL_FROM_DATABASE=Nogatech TV! Pro (NTSC) usb:v0573p4501* ID_MODEL_FROM_DATABASE=Nogatech TV! Pro (PAL) usb:v0573p4550* ID_MODEL_FROM_DATABASE=ZTV ZT-721 2.4GHz A/V Receiver usb:v0573p4551* ID_MODEL_FROM_DATABASE=Dazzle TV! Pro Audio (P+) usb:v0573p4D00* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB USA usb:v0573p4D01* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB usb:v0573p4D02* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB UK usb:v0573p4D03* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB France usb:v0573p4D04* ID_MODEL_FROM_DATABASE=Hauppauge WinTV (PAL D/K) usb:v0573p4D10* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB with FM USA radio usb:v0573p4D11* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB (PAL) with FM radio usb:v0573p4D12* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB UK with FM Radio usb:v0573p4D14* ID_MODEL_FROM_DATABASE=Hauppauge WinTV (PAL D/K FM) usb:v0573p4D20* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB II (PAL) with FM radio usb:v0573p4D21* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB II (PAL) usb:v0573p4D22* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB II (PAL) Model 566 usb:v0573p4D23* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB France 4D23 usb:v0573p4D24* ID_MODEL_FROM_DATABASE=Hauppauge WinTV Pro (PAL D/K) usb:v0573p4D25* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB Model 40209 rev B234 usb:v0573p4D26* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB Model 40209 rev B243 usb:v0573p4D27* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB Model 40204 Rev B281 usb:v0573p4D28* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB Model 40204 rev B283 usb:v0573p4D29* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB Model 40205 rev B298 usb:v0573p4D2A* ID_MODEL_FROM_DATABASE=Hauppague WinTV-USB Model 602 Rev B285 usb:v0573p4D2B* ID_MODEL_FROM_DATABASE=Hauppague WinTV-USB Model 602 Rev B282 usb:v0573p4D2C* ID_MODEL_FROM_DATABASE=Hauppauge WinTV Pro (PAL/SECAM) usb:v0573p4D30* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB FM Model 40211 Rev B123 usb:v0573p4D31* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB III (PAL) with FM radio Model 568 usb:v0573p4D32* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB III (PAL) FM Model 573 usb:v0573p4D34* ID_MODEL_FROM_DATABASE=Hauppauge WinTV Pro (PAL D/K FM) usb:v0573p4D35* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB III (PAL) FM Model 597 usb:v0573p4D36* ID_MODEL_FROM_DATABASE=Hauppauge WinTV Pro (PAL B/G FM) usb:v0573p4D37* ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB Model 40219 rev E189 usb:v0573p4D38* ID_MODEL_FROM_DATABASE=Hauppauge WinTV Pro (NTSC FM) usb:v0574* ID_VENDOR_FROM_DATABASE=City University of Hong Kong usb:v0575* ID_VENDOR_FROM_DATABASE=Philips Creative Display Solutions usb:v0576* ID_VENDOR_FROM_DATABASE=BAFO/Quality Computer Accessories usb:v0577* ID_VENDOR_FROM_DATABASE=ELSA usb:v0578* ID_VENDOR_FROM_DATABASE=Intrinsix Corp. usb:v0579* ID_VENDOR_FROM_DATABASE=GVC Corp. usb:v057A* ID_VENDOR_FROM_DATABASE=Samsung Electronics America usb:v057B* ID_VENDOR_FROM_DATABASE=Y-E Data, Inc. usb:v057Bp0000* ID_MODEL_FROM_DATABASE=FlashBuster-U Floppy usb:v057Bp0001* ID_MODEL_FROM_DATABASE=Tri-Media Reader Floppy usb:v057Bp0006* ID_MODEL_FROM_DATABASE=Tri-Media Reader Card Reader usb:v057Bp0010* ID_MODEL_FROM_DATABASE=Memory Stick Reader Writer usb:v057Bp0020* ID_MODEL_FROM_DATABASE=HEXA Media Drive 6-in-1 Card Reader Writer usb:v057Bp0030* ID_MODEL_FROM_DATABASE=Memory Card Viewer (TV) usb:v057C* ID_VENDOR_FROM_DATABASE=AVM GmbH usb:v057Cp0B00* ID_MODEL_FROM_DATABASE=ISDN-Controller B1 Family usb:v057Cp0C00* ID_MODEL_FROM_DATABASE=ISDN-Controller FRITZ!Card usb:v057Cp1000* ID_MODEL_FROM_DATABASE=ISDN-Controller FRITZ!Card v2.0 usb:v057Cp1900* ID_MODEL_FROM_DATABASE=ISDN-Controller FRITZ!Card v2.1 usb:v057Cp2000* ID_MODEL_FROM_DATABASE=ISDN-Connector FRITZ!X usb:v057Cp2200* ID_MODEL_FROM_DATABASE=BlueFRITZ! usb:v057Cp2300* ID_MODEL_FROM_DATABASE=Teledat X130 DSL usb:v057Cp2800* ID_MODEL_FROM_DATABASE=ISDN-Connector TA usb:v057Cp3200* ID_MODEL_FROM_DATABASE=Teledat X130 DSL usb:v057Cp3500* ID_MODEL_FROM_DATABASE=FRITZ!Card DSL SL usb:v057Cp3701* ID_MODEL_FROM_DATABASE=FRITZ!Box SL usb:v057Cp3702* ID_MODEL_FROM_DATABASE=FRITZ!Box usb:v057Cp3800* ID_MODEL_FROM_DATABASE=BlueFRITZ! Bluetooth Stick usb:v057Cp3A00* ID_MODEL_FROM_DATABASE=FRITZ!Box Fon usb:v057Cp3C00* ID_MODEL_FROM_DATABASE=FRITZ!Box WLAN usb:v057Cp3D00* ID_MODEL_FROM_DATABASE=Fritz!Box usb:v057Cp3E01* ID_MODEL_FROM_DATABASE=FRITZ!Box (Annex A) usb:v057Cp4001* ID_MODEL_FROM_DATABASE=FRITZ!Box Fon (Annex A) usb:v057Cp4101* ID_MODEL_FROM_DATABASE=FRITZ!Box WLAN (Annex A) usb:v057Cp4201* ID_MODEL_FROM_DATABASE=FRITZ!Box Fon WLAN (Annex A) usb:v057Cp4601* ID_MODEL_FROM_DATABASE=Eumex 5520PC (WinXP/2000) usb:v057Cp4602* ID_MODEL_FROM_DATABASE=Eumex 400 (WinXP/2000) usb:v057Cp4701* ID_MODEL_FROM_DATABASE=AVM FRITZ!Box Fon ata usb:v057Cp5401* ID_MODEL_FROM_DATABASE=Eumex 300 IP usb:v057Cp5601* ID_MODEL_FROM_DATABASE=AVM Fritz!WLAN [Texas Instruments TNETW1450] usb:v057Cp6201* ID_MODEL_FROM_DATABASE=AVM Fritz!WLAN v1.1 [Texas Instruments TNETW1450] usb:v057Cp62FF* ID_MODEL_FROM_DATABASE=AVM Fritz!WLAN USB (in CD-ROM-mode) usb:v057Cp8401* ID_MODEL_FROM_DATABASE=Fritz!WLAN N [Atheros AR9001U] usb:v057Cp8402* ID_MODEL_FROM_DATABASE=Fritz!WLAN N 2.4 [Atheros AR9001U] usb:v057Cp8403* ID_MODEL_FROM_DATABASE=Fritz!WLAN N v2 [Atheros AR9271] usb:v057Cp84FF* ID_MODEL_FROM_DATABASE=AVM Fritz!WLAN USB N (in CD-ROM-mode) usb:v057Cp8501* ID_MODEL_FROM_DATABASE=FRITZ WLAN N v2 [RT5572/rt2870.bin] usb:v057D* ID_VENDOR_FROM_DATABASE=Shark Multimedia, Inc. usb:v057E* ID_VENDOR_FROM_DATABASE=Nintendo Co., Ltd usb:v057Ep0305* ID_MODEL_FROM_DATABASE=Broadcom BCM2045A Bluetooth Radio [Nintendo Wii] usb:v057Ep0306* ID_MODEL_FROM_DATABASE=Wii Remote Controller RVL-003 usb:v057F* ID_VENDOR_FROM_DATABASE=QuickShot, Ltd usb:v057Fp6238* ID_MODEL_FROM_DATABASE=USB StrikePad usb:v0580* ID_VENDOR_FROM_DATABASE=Denron, Inc. usb:v0581* ID_VENDOR_FROM_DATABASE=Racal Data Group usb:v0582* ID_VENDOR_FROM_DATABASE=Roland Corp. usb:v0582p0000* ID_MODEL_FROM_DATABASE=UA-100(G) usb:v0582p0002* ID_MODEL_FROM_DATABASE=UM-4/MPU-64 MIDI Interface usb:v0582p0003* ID_MODEL_FROM_DATABASE=SoundCanvas SC-8850 usb:v0582p0004* ID_MODEL_FROM_DATABASE=U-8 usb:v0582p0005* ID_MODEL_FROM_DATABASE=UM-2(C/EX) usb:v0582p0007* ID_MODEL_FROM_DATABASE=SoundCanvas SC-8820 usb:v0582p0008* ID_MODEL_FROM_DATABASE=PC-300 usb:v0582p0009* ID_MODEL_FROM_DATABASE=UM-1(E/S/X) usb:v0582p000B* ID_MODEL_FROM_DATABASE=SK-500 usb:v0582p000C* ID_MODEL_FROM_DATABASE=SC-D70 usb:v0582p0010* ID_MODEL_FROM_DATABASE=EDIROL UA-5 usb:v0582p0011* ID_MODEL_FROM_DATABASE=Edirol UA-5 Sound Capture usb:v0582p0012* ID_MODEL_FROM_DATABASE=XV-5050 usb:v0582p0013* ID_MODEL_FROM_DATABASE=XV-5050 usb:v0582p0014* ID_MODEL_FROM_DATABASE=EDIROL UM-880 MIDI I/F (native) usb:v0582p0015* ID_MODEL_FROM_DATABASE=EDIROL UM-880 MIDI I/F (generic) usb:v0582p0016* ID_MODEL_FROM_DATABASE=EDIROL SD-90 usb:v0582p0017* ID_MODEL_FROM_DATABASE=EDIROL SD-90 usb:v0582p0018* ID_MODEL_FROM_DATABASE=UA-1A usb:v0582p001B* ID_MODEL_FROM_DATABASE=MMP-2 usb:v0582p001C* ID_MODEL_FROM_DATABASE=MMP-2 usb:v0582p001D* ID_MODEL_FROM_DATABASE=V-SYNTH usb:v0582p001E* ID_MODEL_FROM_DATABASE=V-SYNTH usb:v0582p0023* ID_MODEL_FROM_DATABASE=EDIROL UM-550 usb:v0582p0024* ID_MODEL_FROM_DATABASE=EDIROL UM-550 usb:v0582p0025* ID_MODEL_FROM_DATABASE=EDIROL UA-20 usb:v0582p0026* ID_MODEL_FROM_DATABASE=EDIROL UA-20 usb:v0582p0027* ID_MODEL_FROM_DATABASE=EDIROL SD-20 usb:v0582p0028* ID_MODEL_FROM_DATABASE=EDIROL SD-20 usb:v0582p0029* ID_MODEL_FROM_DATABASE=EDIROL SD-80 usb:v0582p002A* ID_MODEL_FROM_DATABASE=EDIROL SD-80 usb:v0582p002B* ID_MODEL_FROM_DATABASE=EDIROL UA-700 usb:v0582p002C* ID_MODEL_FROM_DATABASE=EDIROL UA-700 usb:v0582p002D* ID_MODEL_FROM_DATABASE=XV-2020 Synthesizer usb:v0582p002E* ID_MODEL_FROM_DATABASE=XV-2020 Synthesizer usb:v0582p002F* ID_MODEL_FROM_DATABASE=VariOS usb:v0582p0030* ID_MODEL_FROM_DATABASE=VariOS usb:v0582p0033* ID_MODEL_FROM_DATABASE=EDIROL PCR usb:v0582p0034* ID_MODEL_FROM_DATABASE=EDIROL PCR usb:v0582p0035* ID_MODEL_FROM_DATABASE=M-1000 usb:v0582p0037* ID_MODEL_FROM_DATABASE=Digital Piano usb:v0582p0038* ID_MODEL_FROM_DATABASE=Digital Piano usb:v0582p003B* ID_MODEL_FROM_DATABASE=BOSS GS-10 usb:v0582p003C* ID_MODEL_FROM_DATABASE=BOSS GS-10 usb:v0582p0040* ID_MODEL_FROM_DATABASE=GI-20 usb:v0582p0041* ID_MODEL_FROM_DATABASE=GI-20 usb:v0582p0042* ID_MODEL_FROM_DATABASE=RS-70 usb:v0582p0043* ID_MODEL_FROM_DATABASE=RS-70 usb:v0582p0044* ID_MODEL_FROM_DATABASE=EDIROL UA-1000 usb:v0582p0047* ID_MODEL_FROM_DATABASE=EDIROL UR-80 WAVE usb:v0582p0048* ID_MODEL_FROM_DATABASE=EDIROL UR-80 MIDI usb:v0582p0049* ID_MODEL_FROM_DATABASE=EDIROL UR-80 WAVE usb:v0582p004A* ID_MODEL_FROM_DATABASE=EDIROL UR-80 MIDI usb:v0582p004B* ID_MODEL_FROM_DATABASE=EDIROL M-100FX usb:v0582p004C* ID_MODEL_FROM_DATABASE=EDIROL PCR-A WAVE usb:v0582p004D* ID_MODEL_FROM_DATABASE=EDIROL PCR-A MIDI usb:v0582p004E* ID_MODEL_FROM_DATABASE=EDIROL PCR-A WAVE usb:v0582p004F* ID_MODEL_FROM_DATABASE=EDIROL PCR-A MIDI usb:v0582p0050* ID_MODEL_FROM_DATABASE=EDIROL UA-3FX usb:v0582p0052* ID_MODEL_FROM_DATABASE=EDIROL UM-1SX usb:v0582p0054* ID_MODEL_FROM_DATABASE=Digital Piano usb:v0582p0060* ID_MODEL_FROM_DATABASE=EXR Series usb:v0582p0064* ID_MODEL_FROM_DATABASE=EDIROL PCR-1 WAVE usb:v0582p0065* ID_MODEL_FROM_DATABASE=EDIROL PCR-1 MIDI usb:v0582p0066* ID_MODEL_FROM_DATABASE=EDIROL PCR-1 WAVE usb:v0582p0067* ID_MODEL_FROM_DATABASE=EDIROL PCR-1 MIDI usb:v0582p006A* ID_MODEL_FROM_DATABASE=SP-606 usb:v0582p006B* ID_MODEL_FROM_DATABASE=SP-606 usb:v0582p006D* ID_MODEL_FROM_DATABASE=FANTOM-X usb:v0582p006E* ID_MODEL_FROM_DATABASE=FANTOM-X usb:v0582p0073* ID_MODEL_FROM_DATABASE=EDIROL UA-25 usb:v0582p0074* ID_MODEL_FROM_DATABASE=EDIROL UA-25 usb:v0582p0075* ID_MODEL_FROM_DATABASE=BOSS DR-880 usb:v0582p0076* ID_MODEL_FROM_DATABASE=BOSS DR-880 usb:v0582p007A* ID_MODEL_FROM_DATABASE=RD usb:v0582p007B* ID_MODEL_FROM_DATABASE=RD usb:v0582p007D* ID_MODEL_FROM_DATABASE=EDIROL UA-101 usb:v0582p0080* ID_MODEL_FROM_DATABASE=G-70 usb:v0582p0081* ID_MODEL_FROM_DATABASE=G-70 usb:v0582p0084* ID_MODEL_FROM_DATABASE=V-SYNTH XT usb:v0582p0089* ID_MODEL_FROM_DATABASE=BOSS GT-PRO usb:v0582p008B* ID_MODEL_FROM_DATABASE=EDIROL PC-50 usb:v0582p008C* ID_MODEL_FROM_DATABASE=EDIROL PC-50 usb:v0582p008D* ID_MODEL_FROM_DATABASE=EDIROL UA-101 USB1 usb:v0582p0092* ID_MODEL_FROM_DATABASE=EDIROL PC-80 WAVE usb:v0582p0093* ID_MODEL_FROM_DATABASE=EDIROL PC-80 MIDI usb:v0582p0096* ID_MODEL_FROM_DATABASE=EDIROL UA-1EX usb:v0582p009A* ID_MODEL_FROM_DATABASE=EDIROL UM-3EX usb:v0582p009D* ID_MODEL_FROM_DATABASE=EDIROL UM-1 usb:v0582p00A0* ID_MODEL_FROM_DATABASE=MD-P1 usb:v0582p00A2* ID_MODEL_FROM_DATABASE=Digital Piano usb:v0582p00A3* ID_MODEL_FROM_DATABASE=EDIROL UA-4FX usb:v0582p00A6* ID_MODEL_FROM_DATABASE=Juno-G usb:v0582p00A9* ID_MODEL_FROM_DATABASE=MC-808 usb:v0582p00AD* ID_MODEL_FROM_DATABASE=SH-201 usb:v0582p00B2* ID_MODEL_FROM_DATABASE=VG-99 usb:v0582p00B3* ID_MODEL_FROM_DATABASE=VG-99 usb:v0582p00B7* ID_MODEL_FROM_DATABASE=BK-7m/VIMA JM-5/8 usb:v0582p00C2* ID_MODEL_FROM_DATABASE=SonicCell usb:v0582p00C4* ID_MODEL_FROM_DATABASE=EDIROL M-16DX usb:v0582p00C5* ID_MODEL_FROM_DATABASE=SP-555 usb:v0582p00C7* ID_MODEL_FROM_DATABASE=V-Synth GT usb:v0582p00D1* ID_MODEL_FROM_DATABASE=Music Atelier usb:v0582p00D3* ID_MODEL_FROM_DATABASE=M-380/400 usb:v0582p00DA* ID_MODEL_FROM_DATABASE=BOSS GT-10 usb:v0582p00DB* ID_MODEL_FROM_DATABASE=BOSS GT-10 Guitar Effects Processor usb:v0582p00DC* ID_MODEL_FROM_DATABASE=BOSS GT-10B usb:v0582p00DE* ID_MODEL_FROM_DATABASE=Fantom G usb:v0582p00E6* ID_MODEL_FROM_DATABASE=EDIROL UA-25EX (Advanced mode) usb:v0582p00E7* ID_MODEL_FROM_DATABASE=EDIROL UA-25EX usb:v0582p00E9* ID_MODEL_FROM_DATABASE=UA-1G usb:v0582p00EB* ID_MODEL_FROM_DATABASE=VS-100 usb:v0582p00F6* ID_MODEL_FROM_DATABASE=GW-8/AX-Synth usb:v0582p00F8* ID_MODEL_FROM_DATABASE=JUNO Series usb:v0582p00FC* ID_MODEL_FROM_DATABASE=VS-700C usb:v0582p00FD* ID_MODEL_FROM_DATABASE=VS-700 usb:v0582p00FE* ID_MODEL_FROM_DATABASE=VS-700 M1 usb:v0582p00FF* ID_MODEL_FROM_DATABASE=VS-700 M2 usb:v0582p0100* ID_MODEL_FROM_DATABASE=VS-700 usb:v0582p0101* ID_MODEL_FROM_DATABASE=VS-700 M2 usb:v0582p0102* ID_MODEL_FROM_DATABASE=VB-99 usb:v0582p0104* ID_MODEL_FROM_DATABASE=UM-1G usb:v0582p0106* ID_MODEL_FROM_DATABASE=UM-2G usb:v0582p0108* ID_MODEL_FROM_DATABASE=UM-3G usb:v0582p0109* ID_MODEL_FROM_DATABASE=eBand JS-8 usb:v0582p010D* ID_MODEL_FROM_DATABASE=A-500S usb:v0582p010F* ID_MODEL_FROM_DATABASE=A-PRO usb:v0582p0110* ID_MODEL_FROM_DATABASE=A-PRO usb:v0582p0111* ID_MODEL_FROM_DATABASE=GAIA SH-01 usb:v0582p0113* ID_MODEL_FROM_DATABASE=ME-25 usb:v0582p0114* ID_MODEL_FROM_DATABASE=SD-50 usb:v0582p0116* ID_MODEL_FROM_DATABASE=WAVE/MP3 RECORDER R-05 usb:v0582p0117* ID_MODEL_FROM_DATABASE=VS-20 usb:v0582p0119* ID_MODEL_FROM_DATABASE=OCTAPAD SPD-30 usb:v0582p011C* ID_MODEL_FROM_DATABASE=Lucina AX-09 usb:v0582p011E* ID_MODEL_FROM_DATABASE=BR-800 usb:v0582p0120* ID_MODEL_FROM_DATABASE=OCTA-CAPTURE usb:v0582p0121* ID_MODEL_FROM_DATABASE=OCTA-CAPTURE usb:v0582p0123* ID_MODEL_FROM_DATABASE=JUNO-Gi usb:v0582p0124* ID_MODEL_FROM_DATABASE=M-300 usb:v0582p0127* ID_MODEL_FROM_DATABASE=GR-55 usb:v0582p012A* ID_MODEL_FROM_DATABASE=UM-ONE usb:v0582p012B* ID_MODEL_FROM_DATABASE=DUO-CAPTURE usb:v0582p012F* ID_MODEL_FROM_DATABASE=QUAD-CAPTURE usb:v0582p0130* ID_MODEL_FROM_DATABASE=MICRO BR BR-80 usb:v0582p0132* ID_MODEL_FROM_DATABASE=TRI-CAPTURE usb:v0582p0134* ID_MODEL_FROM_DATABASE=V-Mixer usb:v0582p0138* ID_MODEL_FROM_DATABASE=Boss RC-300 (Audio mode) usb:v0582p0139* ID_MODEL_FROM_DATABASE=Boss RC-300 (Storage mode) usb:v0582p013A* ID_MODEL_FROM_DATABASE=JUPITER-80 usb:v0582p013E* ID_MODEL_FROM_DATABASE=R-26 usb:v0582p0145* ID_MODEL_FROM_DATABASE=SPD-SX usb:v0582p014B* ID_MODEL_FROM_DATABASE=eBand JS-10 usb:v0582p014D* ID_MODEL_FROM_DATABASE=GT-100 usb:v0582p0150* ID_MODEL_FROM_DATABASE=TD-15 usb:v0582p0151* ID_MODEL_FROM_DATABASE=TD-11 usb:v0582p0154* ID_MODEL_FROM_DATABASE=JUPITER-50 usb:v0582p0156* ID_MODEL_FROM_DATABASE=A-Series usb:v0582p0158* ID_MODEL_FROM_DATABASE=TD-30 usb:v0582p0159* ID_MODEL_FROM_DATABASE=DUO-CAPTURE EX usb:v0582p015B* ID_MODEL_FROM_DATABASE=INTEGRA-7 usb:v0582p015D* ID_MODEL_FROM_DATABASE=R-88 usb:v0582p0505* ID_MODEL_FROM_DATABASE=EDIROL UA-101 usb:v0583* ID_VENDOR_FROM_DATABASE=Padix Co., Ltd (Rockfire) usb:v0583p0001* ID_MODEL_FROM_DATABASE=4 Axis 12 button +POV usb:v0583p0002* ID_MODEL_FROM_DATABASE=4 Axis 12 button +POV usb:v0583p2030* ID_MODEL_FROM_DATABASE=RM-203 USB Nest [mode 1] usb:v0583p2031* ID_MODEL_FROM_DATABASE=RM-203 USB Nest [mode 2] usb:v0583p2032* ID_MODEL_FROM_DATABASE=RM-203 USB Nest [mode 3] usb:v0583p2033* ID_MODEL_FROM_DATABASE=RM-203 USB Nest [mode 4] usb:v0583p2050* ID_MODEL_FROM_DATABASE=PX-205 PSX Bridge usb:v0583p205F* ID_MODEL_FROM_DATABASE=PSX/USB converter usb:v0583p206F* ID_MODEL_FROM_DATABASE=USB, 2-axis 8-button gamepad usb:v0583p3050* ID_MODEL_FROM_DATABASE=QF-305u Gamepad usb:v0583p3379* ID_MODEL_FROM_DATABASE=Rockfire X-Force usb:v0583p337F* ID_MODEL_FROM_DATABASE=Rockfire USB RacingStar Vibra usb:v0583p509F* ID_MODEL_FROM_DATABASE=USB,4-Axis,12-Button with POV usb:v0583p5259* ID_MODEL_FROM_DATABASE=Rockfire USB SkyShuttle Vibra usb:v0583p525F* ID_MODEL_FROM_DATABASE=USB Vibration Pad usb:v0583p5308* ID_MODEL_FROM_DATABASE=USB Wireless VibrationPad usb:v0583p5359* ID_MODEL_FROM_DATABASE=Rockfire USB SkyShuttle Pro usb:v0583p535F* ID_MODEL_FROM_DATABASE=USB,real VibrationPad usb:v0583p5659* ID_MODEL_FROM_DATABASE=Rockfire USB SkyShuttle Vibra usb:v0583p565F* ID_MODEL_FROM_DATABASE=USB VibrationPad usb:v0583p6009* ID_MODEL_FROM_DATABASE=Revenger usb:v0583p600F* ID_MODEL_FROM_DATABASE=USB,GameBoard II usb:v0583p6258* ID_MODEL_FROM_DATABASE=USB, 4-axis, 6-button joystick w/view finder usb:v0583p6889* ID_MODEL_FROM_DATABASE=Windstorm Pro usb:v0583p688F* ID_MODEL_FROM_DATABASE=QF-688uv Windstorm Pro Joystick usb:v0583p7070* ID_MODEL_FROM_DATABASE=QF-707u Bazooka Joystick usb:v0583pA000* ID_MODEL_FROM_DATABASE=MaxFire G-08XU Gamepad usb:v0583pA015* ID_MODEL_FROM_DATABASE=4-Axis,16-Button with POV usb:v0583pA019* ID_MODEL_FROM_DATABASE=USB, Vibration ,4-axis, 8-button joystick w/view finder usb:v0583pA020* ID_MODEL_FROM_DATABASE=USB,4-Axis,10-Button with POV usb:v0583pA021* ID_MODEL_FROM_DATABASE=USB,4-Axis,12-Button with POV usb:v0583pA022* ID_MODEL_FROM_DATABASE=USB,4-Axis,14-Button with POV usb:v0583pA023* ID_MODEL_FROM_DATABASE=USB,4-Axis,16-Button with POV usb:v0583pA024* ID_MODEL_FROM_DATABASE=4axis,12button vibrition audio gamepad usb:v0583pA025* ID_MODEL_FROM_DATABASE=4axis,12button vibrition audio gamepad usb:v0583pA130* ID_MODEL_FROM_DATABASE=USB Wireless 2.4GHz Gamepad usb:v0583pA131* ID_MODEL_FROM_DATABASE=USB Wireless 2.4GHz Joystick usb:v0583pA132* ID_MODEL_FROM_DATABASE=USB Wireless 2.4GHz Wheelpad usb:v0583pA133* ID_MODEL_FROM_DATABASE=USB Wireless 2.4GHz Wheel&Gamepad usb:v0583pA202* ID_MODEL_FROM_DATABASE=ForceFeedbackWheel usb:v0583pA209* ID_MODEL_FROM_DATABASE=MetalStrike FF usb:v0583pB000* ID_MODEL_FROM_DATABASE=USB,4-Axis,12-Button with POV usb:v0583pB001* ID_MODEL_FROM_DATABASE=USB,4-Axis,12-Button with POV usb:v0583pB002* ID_MODEL_FROM_DATABASE=Vibration,12-Button USB Wheel usb:v0583pB005* ID_MODEL_FROM_DATABASE=USB,12-Button Wheel usb:v0583pB008* ID_MODEL_FROM_DATABASE=USB Wireless 2.4GHz Wheel usb:v0583pB009* ID_MODEL_FROM_DATABASE=USB,12-Button Wheel usb:v0583pB00A* ID_MODEL_FROM_DATABASE=PSX/USB converter usb:v0583pB00B* ID_MODEL_FROM_DATABASE=PSX/USB converter usb:v0583pB00C* ID_MODEL_FROM_DATABASE=PSX/USB converter usb:v0583pB00D* ID_MODEL_FROM_DATABASE=PSX/USB converter usb:v0583pB00E* ID_MODEL_FROM_DATABASE=4-Axis,12-Button with POV usb:v0583pB00F* ID_MODEL_FROM_DATABASE=USB,5-Axis,10-Button with POV usb:v0583pB010* ID_MODEL_FROM_DATABASE=MetalStrike Pro usb:v0583pB012* ID_MODEL_FROM_DATABASE=Wireless MetalStrike usb:v0583pB013* ID_MODEL_FROM_DATABASE=USB,Wiress 2.4GHZ Joystick usb:v0583pB016* ID_MODEL_FROM_DATABASE=USB,5-Axis,10-Button with POV usb:v0583pB018* ID_MODEL_FROM_DATABASE=TW6 Wheel usb:v0583pFF60* ID_MODEL_FROM_DATABASE=USB Wireless VibrationPad usb:v0584* ID_VENDOR_FROM_DATABASE=RATOC System, Inc. usb:v0584p0008* ID_MODEL_FROM_DATABASE=Fujifilm MemoryCard ReaderWriter usb:v0584p0220* ID_MODEL_FROM_DATABASE=U2SCX SCSI Converter usb:v0584p0304* ID_MODEL_FROM_DATABASE=U2SCX-LVD (SCSI Converter) usb:v0584pB000* ID_MODEL_FROM_DATABASE=REX-USB60 usb:v0584pB020* ID_MODEL_FROM_DATABASE=REX-USB60F usb:v0585* ID_VENDOR_FROM_DATABASE=FlashPoint Technology, Inc. usb:v0585p0001* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p0002* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p0003* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p0004* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p0005* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p0006* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p0007* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p0008* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p0009* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p000A* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p000B* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p000C* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p000D* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p000E* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0585p000F* ID_MODEL_FROM_DATABASE=Digital Camera usb:v0586* ID_VENDOR_FROM_DATABASE=ZyXEL Communications Corp. usb:v0586p0025* ID_MODEL_FROM_DATABASE=802.11b/g/n USB Wireless Network Adapter usb:v0586p0100* ID_MODEL_FROM_DATABASE=omni.net usb:v0586p0102* ID_MODEL_FROM_DATABASE=omni.net II ISDN TA [HFC-S] usb:v0586p0110* ID_MODEL_FROM_DATABASE=omni.net Plus usb:v0586p1000* ID_MODEL_FROM_DATABASE=omni.net LCD Plus - ISDN TA usb:v0586p1500* ID_MODEL_FROM_DATABASE=Omni 56K Plus usb:v0586p2011* ID_MODEL_FROM_DATABASE=Scorpion-980N keyboard usb:v0586p3304* ID_MODEL_FROM_DATABASE=LAN Modem usb:v0586p3309* ID_MODEL_FROM_DATABASE=ADSL Modem Prestige 600 series usb:v0586p330A* ID_MODEL_FROM_DATABASE=ADSL Modem Interface usb:v0586p330E* ID_MODEL_FROM_DATABASE=USB Broadband ADSL Modem Rev 1.10 usb:v0586p3400* ID_MODEL_FROM_DATABASE=ZyAIR B-220 IEEE 802.11b Adapter usb:v0586p3401* ID_MODEL_FROM_DATABASE=ZyAIR G-220 802.11bg usb:v0586p3402* ID_MODEL_FROM_DATABASE=ZyAIR G-220F 802.11bg usb:v0586p3403* ID_MODEL_FROM_DATABASE=AG-200 802.11abg Wireless Adapter [Atheros AR5523] usb:v0586p3407* ID_MODEL_FROM_DATABASE=G-200 v2 802.11bg usb:v0586p3408* ID_MODEL_FROM_DATABASE=G-260 802.11bg usb:v0586p3409* ID_MODEL_FROM_DATABASE=AG-225H 802.11bg usb:v0586p340A* ID_MODEL_FROM_DATABASE=M-202 802.11bg usb:v0586p340C* ID_MODEL_FROM_DATABASE=G-270S 802.11bg Wireless Adapter [Atheros AR5523] usb:v0586p340F* ID_MODEL_FROM_DATABASE=G-220 v2 802.11bg usb:v0586p3410* ID_MODEL_FROM_DATABASE=ZyAIR G-202 802.11bg usb:v0586p3412* ID_MODEL_FROM_DATABASE=802.11bg usb:v0586p3413* ID_MODEL_FROM_DATABASE=ZyAIR AG-225H v2 802.11bg usb:v0586p3415* ID_MODEL_FROM_DATABASE=G-210H 802.11g Wireless Adapter usb:v0586p3416* ID_MODEL_FROM_DATABASE=NWD-210N 802.11b/g/n-draft wireless adapter usb:v0586p3417* ID_MODEL_FROM_DATABASE=NWD271N 802.11n Wireless Adapter [Atheros AR9001U-(2)NG] usb:v0586p3418* ID_MODEL_FROM_DATABASE=NWD211AN 802.11abgn Wireless Adapter [Ralink RT2870] usb:v0586p3419* ID_MODEL_FROM_DATABASE=G-220 v3 802.11bg Wireless Adapter [ZyDAS ZD1211B] usb:v0586p341A* ID_MODEL_FROM_DATABASE=NWD-270N Wireless N-lite USB Adapter usb:v0586p341E* ID_MODEL_FROM_DATABASE=NWD2105 802.11bgn Wireless Adapter [Ralink RT3070] usb:v0586p341F* ID_MODEL_FROM_DATABASE=NWD2205 802.11n Wireless N Adapter [Realtek RTL8192CU] usb:v0586p3425* ID_MODEL_FROM_DATABASE=NWD6505 802.11a/b/g/n/ac Wireless Adapter [MediaTek MT7610U] usb:v0586p343E* ID_MODEL_FROM_DATABASE=N220 802.11bgn Wireless Adapter usb:v0587* ID_VENDOR_FROM_DATABASE=America Kotobuki Electronics Industries, Inc. usb:v0588* ID_VENDOR_FROM_DATABASE=Sapien Design usb:v0589* ID_VENDOR_FROM_DATABASE=Victron usb:v058A* ID_VENDOR_FROM_DATABASE=Nohau Corp. usb:v058B* ID_VENDOR_FROM_DATABASE=Infineon Technologies usb:v058Bp0015* ID_MODEL_FROM_DATABASE=Flash Loader utility usb:v058Bp001C* ID_MODEL_FROM_DATABASE=Flash Drive usb:v058Bp0041* ID_MODEL_FROM_DATABASE=Flash Loader utility usb:v058C* ID_VENDOR_FROM_DATABASE=In Focus Systems usb:v058Cp0007* ID_MODEL_FROM_DATABASE=Flash usb:v058Cp0008* ID_MODEL_FROM_DATABASE=LP130 usb:v058Cp000A* ID_MODEL_FROM_DATABASE=LP530 usb:v058Cp0010* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp0011* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp0012* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp0013* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp0014* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp0015* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp0016* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp0017* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp0018* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp0019* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp001A* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp001B* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp001C* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp001D* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp001E* ID_MODEL_FROM_DATABASE=Projector usb:v058Cp001F* ID_MODEL_FROM_DATABASE=Projector usb:v058CpFFE5* ID_MODEL_FROM_DATABASE=IN34 Projector usb:v058D* ID_VENDOR_FROM_DATABASE=Micrel Semiconductor usb:v058E* ID_VENDOR_FROM_DATABASE=Tripath Technology, Inc. usb:v058F* ID_VENDOR_FROM_DATABASE=Alcor Micro Corp. usb:v058Fp1234* ID_MODEL_FROM_DATABASE=Flash Drive usb:v058Fp2412* ID_MODEL_FROM_DATABASE=SCard R/W CSR-145 usb:v058Fp2802* ID_MODEL_FROM_DATABASE=Monterey Keyboard usb:v058Fp5492* ID_MODEL_FROM_DATABASE=Hub usb:v058Fp6232* ID_MODEL_FROM_DATABASE=Hi-Speed 16-in-1 Flash Card Reader/Writer usb:v058Fp6254* ID_MODEL_FROM_DATABASE=USB Hub usb:v058Fp6331* ID_MODEL_FROM_DATABASE=SD/MMC/MS Card Reader usb:v058Fp6332* ID_MODEL_FROM_DATABASE=Multi-Function Card Reader usb:v058Fp6335* ID_MODEL_FROM_DATABASE=SD/MMC Card Reader usb:v058Fp6360* ID_MODEL_FROM_DATABASE=Multimedia Card Reader usb:v058Fp6361* ID_MODEL_FROM_DATABASE=Multimedia Card Reader usb:v058Fp6362* ID_MODEL_FROM_DATABASE=Flash Card Reader/Writer usb:v058Fp6364* ID_MODEL_FROM_DATABASE=AU6477 Card Reader Controller usb:v058Fp6366* ID_MODEL_FROM_DATABASE=Multi Flash Reader usb:v058Fp6377* ID_MODEL_FROM_DATABASE=AU6375 4-LUN card reader usb:v058Fp6386* ID_MODEL_FROM_DATABASE=Memory Card usb:v058Fp6387* ID_MODEL_FROM_DATABASE=Flash Drive usb:v058Fp6390* ID_MODEL_FROM_DATABASE=USB 2.0-IDE bridge usb:v058Fp6391* ID_MODEL_FROM_DATABASE=IDE Bridge usb:v058Fp9213* ID_MODEL_FROM_DATABASE=MacAlly Kbd Hub usb:v058Fp9215* ID_MODEL_FROM_DATABASE=AU9814 Hub usb:v058Fp9254* ID_MODEL_FROM_DATABASE=Hub usb:v058Fp9310* ID_MODEL_FROM_DATABASE=Mass Storage (UID4/5A & UID7A) usb:v058Fp9320* ID_MODEL_FROM_DATABASE=Micro Storage Driver for Win98 usb:v058Fp9321* ID_MODEL_FROM_DATABASE=Micro Storage Driver for Win98 usb:v058Fp9330* ID_MODEL_FROM_DATABASE=SD Reader usb:v058Fp9331* ID_MODEL_FROM_DATABASE=Micro Storage Driver for Win98 usb:v058Fp9340* ID_MODEL_FROM_DATABASE=Delkin eFilm Reader-32 usb:v058Fp9350* ID_MODEL_FROM_DATABASE=Delkin eFilm Reader-32 usb:v058Fp9360* ID_MODEL_FROM_DATABASE=8-in-1 Media Card Reader usb:v058Fp9361* ID_MODEL_FROM_DATABASE=Multimedia Card Reader usb:v058Fp9368* ID_MODEL_FROM_DATABASE=Multimedia Card Reader usb:v058Fp9380* ID_MODEL_FROM_DATABASE=Flash Drive usb:v058Fp9381* ID_MODEL_FROM_DATABASE=Flash Drive usb:v058Fp9382* ID_MODEL_FROM_DATABASE=Acer/Sweex Flash drive usb:v058Fp9384* ID_MODEL_FROM_DATABASE=qdi U2Disk T209M usb:v058Fp9410* ID_MODEL_FROM_DATABASE=Keyboard usb:v058Fp9472* ID_MODEL_FROM_DATABASE=Keyboard Hub usb:v058Fp9510* ID_MODEL_FROM_DATABASE=ChunghwaTL USB02 Smartcard Reader usb:v058Fp9520* ID_MODEL_FROM_DATABASE=EMV Certified Smart Card Reader usb:v058Fp9540* ID_MODEL_FROM_DATABASE=AU9540 Smartcard Reader usb:v058Fp9720* ID_MODEL_FROM_DATABASE=USB-Serial Adapter usb:v058FpA014* ID_MODEL_FROM_DATABASE=Asus Integrated Webcam usb:v058FpB002* ID_MODEL_FROM_DATABASE=Acer Integrated Webcam usb:v0590* ID_VENDOR_FROM_DATABASE=Omron Corp. usb:v0590p0004* ID_MODEL_FROM_DATABASE=Cable Modem usb:v0590p000B* ID_MODEL_FROM_DATABASE=MR56SVS usb:v0590p0028* ID_MODEL_FROM_DATABASE=HJ-720IT / HEM-7080IT-E / HEM-790IT usb:v0591* ID_VENDOR_FROM_DATABASE=Questra Consulting usb:v0592* ID_VENDOR_FROM_DATABASE=Powerware Corp. usb:v0592p0002* ID_MODEL_FROM_DATABASE=UPS (X-Slot) usb:v0593* ID_VENDOR_FROM_DATABASE=Incite usb:v0594* ID_VENDOR_FROM_DATABASE=Princeton Graphic Systems usb:v0595* ID_VENDOR_FROM_DATABASE=Zoran Microelectronics, Ltd usb:v0595p1001* ID_MODEL_FROM_DATABASE=Digitrex DSC-1300/DSC-2100 (mass storage mode) usb:v0595p2002* ID_MODEL_FROM_DATABASE=DIGITAL STILL CAMERA 6M 4X usb:v0595p4343* ID_MODEL_FROM_DATABASE=Digital Camera EX-20 DSC usb:v0596* ID_VENDOR_FROM_DATABASE=MicroTouch Systems, Inc. usb:v0596p0001* ID_MODEL_FROM_DATABASE=Touchscreen usb:v0596p0002* ID_MODEL_FROM_DATABASE=Touch Screen Controller usb:v0596p0500* ID_MODEL_FROM_DATABASE=PCT Multitouch HID Controller usb:v0596p0543* ID_MODEL_FROM_DATABASE=DELL XPS touchscreen usb:v0597* ID_VENDOR_FROM_DATABASE=Trisignal Communications usb:v0598* ID_VENDOR_FROM_DATABASE=Niigata Canotec Co., Inc. usb:v0599* ID_VENDOR_FROM_DATABASE=Brilliance Semiconductor, Inc. usb:v059A* ID_VENDOR_FROM_DATABASE=Spectrum Signal Processing, Inc. usb:v059B* ID_VENDOR_FROM_DATABASE=Iomega Corp. usb:v059Bp0001* ID_MODEL_FROM_DATABASE=Zip 100 (Type 1) usb:v059Bp000B* ID_MODEL_FROM_DATABASE=Zip 100 (Type 2) usb:v059Bp0021* ID_MODEL_FROM_DATABASE=Win98 Disk Controller usb:v059Bp0030* ID_MODEL_FROM_DATABASE=Zip 250 (Ver 1) usb:v059Bp0031* ID_MODEL_FROM_DATABASE=Zip 100 (Type 3) usb:v059Bp0032* ID_MODEL_FROM_DATABASE=Zip 250 (Ver 2) usb:v059Bp0034* ID_MODEL_FROM_DATABASE=Zip 100 Driver usb:v059Bp0037* ID_MODEL_FROM_DATABASE=Zip 750 MB usb:v059Bp0040* ID_MODEL_FROM_DATABASE=SCSI Bridge usb:v059Bp0042* ID_MODEL_FROM_DATABASE=Rev 70 GB usb:v059Bp0050* ID_MODEL_FROM_DATABASE=Zip CD 650 Writer usb:v059Bp0053* ID_MODEL_FROM_DATABASE=CDRW55292EXT CD-RW External Drive usb:v059Bp0056* ID_MODEL_FROM_DATABASE=External CD-RW Drive Enclosure usb:v059Bp0057* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v059Bp005D* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v059Bp005F* ID_MODEL_FROM_DATABASE=CDRW64892EXT3-C CD-RW 52x24x52x External Drive usb:v059Bp0060* ID_MODEL_FROM_DATABASE=PCMCIA PocketZip Dock usb:v059Bp0061* ID_MODEL_FROM_DATABASE=Varo PocketZip 40 MP3 Player usb:v059Bp006D* ID_MODEL_FROM_DATABASE=HipZip MP3 Player usb:v059Bp0070* ID_MODEL_FROM_DATABASE=eGo Portable Hard Drive usb:v059Bp007C* ID_MODEL_FROM_DATABASE=Ultra Max USB/1394 usb:v059Bp007D* ID_MODEL_FROM_DATABASE=HTC42606 0G9AT00 [Iomega HDD] usb:v059Bp007E* ID_MODEL_FROM_DATABASE=Mini 256MB/512MB Flash Drive [IOM2D5] usb:v059Bp00DB* ID_MODEL_FROM_DATABASE=FotoShow Zip 250 Driver usb:v059Bp0150* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v059Bp015D* ID_MODEL_FROM_DATABASE=Super DVD Writer usb:v059Bp0173* ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller usb:v059Bp0174* ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller usb:v059Bp0176* ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller usb:v059Bp0177* ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller usb:v059Bp0178* ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller usb:v059Bp0179* ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller usb:v059Bp017A* ID_MODEL_FROM_DATABASE=HDD usb:v059Bp017B* ID_MODEL_FROM_DATABASE=HDD/1394A usb:v059Bp017C* ID_MODEL_FROM_DATABASE=HDD/1394B usb:v059Bp0251* ID_MODEL_FROM_DATABASE=Optical usb:v059Bp0252* ID_MODEL_FROM_DATABASE=Optical usb:v059Bp0278* ID_MODEL_FROM_DATABASE=LDHD-UPS [Professional Desktop Hard Drive eSATA / USB2.0] usb:v059Bp027A* ID_MODEL_FROM_DATABASE=LPHD250-U [Portable Hard Drive Silver Series 250 Go] usb:v059Bp0470* ID_MODEL_FROM_DATABASE=Prestige Portable Hard Drive usb:v059Bp047A* ID_MODEL_FROM_DATABASE=Select Portable Hard Drive usb:v059Bp0571* ID_MODEL_FROM_DATABASE=Prestige Portable Hard Drive usb:v059Bp0579* ID_MODEL_FROM_DATABASE=eGo Portable Hard Drive usb:v059Bp1052* ID_MODEL_FROM_DATABASE=DVD+RW External Drive usb:v059C* ID_VENDOR_FROM_DATABASE=A-Trend Technology Co., Ltd usb:v059D* ID_VENDOR_FROM_DATABASE=Advanced Input Devices usb:v059E* ID_VENDOR_FROM_DATABASE=Intelligent Instrumentation usb:v059F* ID_VENDOR_FROM_DATABASE=LaCie, Ltd usb:v059Fp0201* ID_MODEL_FROM_DATABASE=StudioDrive USB2 usb:v059Fp0202* ID_MODEL_FROM_DATABASE=StudioDrive USB2 usb:v059Fp0203* ID_MODEL_FROM_DATABASE=StudioDrive USB2 usb:v059Fp0211* ID_MODEL_FROM_DATABASE=PocketDrive usb:v059Fp0212* ID_MODEL_FROM_DATABASE=PocketDrive usb:v059Fp0213* ID_MODEL_FROM_DATABASE=PocketDrive USB2 usb:v059Fp0323* ID_MODEL_FROM_DATABASE=LaCie d2 Drive USB2 usb:v059Fp0421* ID_MODEL_FROM_DATABASE=Big Disk G465 usb:v059Fp0525* ID_MODEL_FROM_DATABASE=BigDisk Extreme 500 usb:v059Fp0641* ID_MODEL_FROM_DATABASE=Mobile Hard Drive usb:v059Fp0829* ID_MODEL_FROM_DATABASE=BigDisk Extreme+ usb:v059Fp100C* ID_MODEL_FROM_DATABASE=Rugged Triple Interface Mobile Hard Drive usb:v059Fp1010* ID_MODEL_FROM_DATABASE=Desktop Hard Drive usb:v059Fp1018* ID_MODEL_FROM_DATABASE=Desktop Hard Drive usb:v059Fp1019* ID_MODEL_FROM_DATABASE=Desktop Hard Drive usb:v059Fp1021* ID_MODEL_FROM_DATABASE=Little Disk usb:v059Fp1027* ID_MODEL_FROM_DATABASE=iamaKey V2 usb:v059Fp102A* ID_MODEL_FROM_DATABASE=Rikiki Hard Drive usb:v059Fp1049* ID_MODEL_FROM_DATABASE=rikiki Harddrive usb:v059Fp1052* ID_MODEL_FROM_DATABASE=P'9220 Mobile Drive usb:v059Fp1064* ID_MODEL_FROM_DATABASE=Rugged 16 and 32 GB usb:v059Fp106E* ID_MODEL_FROM_DATABASE=Porsche Design Desktop Drive usb:v059FpA601* ID_MODEL_FROM_DATABASE=HardDrive usb:v059FpA602* ID_MODEL_FROM_DATABASE=CD R/W usb:v05A0* ID_VENDOR_FROM_DATABASE=Vetronix Corp. usb:v05A1* ID_VENDOR_FROM_DATABASE=USC Corp. usb:v05A2* ID_VENDOR_FROM_DATABASE=Fuji Film Microdevices Co., Ltd usb:v05A3* ID_VENDOR_FROM_DATABASE=ARC International usb:v05A3p8388* ID_MODEL_FROM_DATABASE=Marvell 88W8388 802.11a/b/g WLAN usb:v05A4* ID_VENDOR_FROM_DATABASE=Ortek Technology, Inc. usb:v05A4p1000* ID_MODEL_FROM_DATABASE=WKB-1000S Wireless Ergo Keyboard with Touchpad usb:v05A4p2000* ID_MODEL_FROM_DATABASE=WKB-2000 Wireless Keyboard with Touchpad usb:v05A4p9720* ID_MODEL_FROM_DATABASE=Keyboard Mouse usb:v05A4p9722* ID_MODEL_FROM_DATABASE=Keyboard usb:v05A4p9731* ID_MODEL_FROM_DATABASE=MCK-600W/MCK-800USB Keyboard usb:v05A4p9783* ID_MODEL_FROM_DATABASE=Wireless Keypad usb:v05A4p9837* ID_MODEL_FROM_DATABASE=Targus Number Keypad usb:v05A4p9862* ID_MODEL_FROM_DATABASE=Targus Number Keypad (Composite Device) usb:v05A4p9881* ID_MODEL_FROM_DATABASE=IR receiver [VRC-1100 Vista MCE Remote Control] usb:v05A5* ID_VENDOR_FROM_DATABASE=Sampo Technology Corp. usb:v05A6* ID_VENDOR_FROM_DATABASE=Cisco Systems, Inc. usb:v05A6p0001* ID_MODEL_FROM_DATABASE=CVA124 Cable Voice Adapter (WDM) usb:v05A6p0002* ID_MODEL_FROM_DATABASE=CVA122 Cable Voice Adapter (WDM) usb:v05A6p0003* ID_MODEL_FROM_DATABASE=CVA124E Cable Voice Adapter (WDM) usb:v05A6p0004* ID_MODEL_FROM_DATABASE=CVA122E Cable Voice Adapter (WDM) usb:v05A7* ID_VENDOR_FROM_DATABASE=Bose Corp. usb:v05A7p4000* ID_MODEL_FROM_DATABASE=Bluetooth Headset usb:v05A7p4001* ID_MODEL_FROM_DATABASE=Bluetooth Headset in DFU mode usb:v05A7p4002* ID_MODEL_FROM_DATABASE=Bluetooth Headset Series 2 usb:v05A7p4003* ID_MODEL_FROM_DATABASE=Bluetooth Headset Series 2 in DFU mode usb:v05A7pBC50* ID_MODEL_FROM_DATABASE=SoundLink Wireless Mobile speaker usb:v05A7pBC51* ID_MODEL_FROM_DATABASE=SoundLink Wireless Mobile speaker in DFU mode usb:v05A8* ID_VENDOR_FROM_DATABASE=Spacetec IMC Corp. usb:v05A9* ID_VENDOR_FROM_DATABASE=OmniVision Technologies, Inc. usb:v05A9p0511* ID_MODEL_FROM_DATABASE=OV511 Webcam usb:v05A9p0518* ID_MODEL_FROM_DATABASE=OV518 Webcam usb:v05A9p0519* ID_MODEL_FROM_DATABASE=OV519 Microphone usb:v05A9p1550* ID_MODEL_FROM_DATABASE=VEHO Filmscanner usb:v05A9p2640* ID_MODEL_FROM_DATABASE=OV2640 Webcam usb:v05A9p2643* ID_MODEL_FROM_DATABASE=Monitor Webcam usb:v05A9p264B* ID_MODEL_FROM_DATABASE=Monitor Webcam usb:v05A9p2800* ID_MODEL_FROM_DATABASE=SuperCAM usb:v05A9p4519* ID_MODEL_FROM_DATABASE=Webcam Classic usb:v05A9p7670* ID_MODEL_FROM_DATABASE=OV7670 Webcam usb:v05A9p8065* ID_MODEL_FROM_DATABASE=GAIA Sensor FPGA Demo Board usb:v05A9p8519* ID_MODEL_FROM_DATABASE=OV519 Webcam usb:v05A9pA511* ID_MODEL_FROM_DATABASE=OV511+ Webcam usb:v05A9pA518* ID_MODEL_FROM_DATABASE=D-Link DSB-C310 Webcam usb:v05AA* ID_VENDOR_FROM_DATABASE=Utilux South China, Ltd usb:v05AB* ID_VENDOR_FROM_DATABASE=In-System Design usb:v05ABp0002* ID_MODEL_FROM_DATABASE=Parallel Port usb:v05ABp0030* ID_MODEL_FROM_DATABASE=Storage Adapter V2 (TPP) usb:v05ABp0031* ID_MODEL_FROM_DATABASE=ATA Bridge usb:v05ABp0060* ID_MODEL_FROM_DATABASE=USB 2.0 ATA Bridge usb:v05ABp0061* ID_MODEL_FROM_DATABASE=Storage Adapter V3 (TPP-I) usb:v05ABp0101* ID_MODEL_FROM_DATABASE=Storage Adapter (TPP) usb:v05ABp0130* ID_MODEL_FROM_DATABASE=Compact Flash and Microdrive Reader (TPP) usb:v05ABp0200* ID_MODEL_FROM_DATABASE=USS725 ATA Bridge usb:v05ABp0201* ID_MODEL_FROM_DATABASE=Storage Adapter (TPP) usb:v05ABp0202* ID_MODEL_FROM_DATABASE=ATA Bridge usb:v05ABp0300* ID_MODEL_FROM_DATABASE=Portable Hard Drive (TPP) usb:v05ABp0301* ID_MODEL_FROM_DATABASE=Portable Hard Drive V2 usb:v05ABp0350* ID_MODEL_FROM_DATABASE=Portable Hard Drive (TPP) usb:v05ABp0351* ID_MODEL_FROM_DATABASE=Portable Hard Drive V2 usb:v05ABp081A* ID_MODEL_FROM_DATABASE=ATA Bridge usb:v05ABp0CDA* ID_MODEL_FROM_DATABASE=ATA Bridge for CD-R/RW usb:v05ABp1001* ID_MODEL_FROM_DATABASE=BAYI Printer Class Support usb:v05ABp5700* ID_MODEL_FROM_DATABASE=Storage Adapter V2 (TPP) usb:v05ABp5701* ID_MODEL_FROM_DATABASE=USB Storage Adapter V2 usb:v05ABp5901* ID_MODEL_FROM_DATABASE=Smart Board (TPP) usb:v05ABp5A01* ID_MODEL_FROM_DATABASE=ATI Storage Adapter (TPP) usb:v05ABp5D01* ID_MODEL_FROM_DATABASE=DataBook Adapter (TPP) usb:v05AC* ID_VENDOR_FROM_DATABASE=Apple, Inc. usb:v05ACp0201* ID_MODEL_FROM_DATABASE=USB Keyboard [Alps or Logitech, M2452] usb:v05ACp0202* ID_MODEL_FROM_DATABASE=Keyboard [ALPS] usb:v05ACp0205* ID_MODEL_FROM_DATABASE=Extended Keyboard [Mitsumi] usb:v05ACp0206* ID_MODEL_FROM_DATABASE=Extended Keyboard [Mitsumi] usb:v05ACp020B* ID_MODEL_FROM_DATABASE=Pro Keyboard [Mitsumi, A1048/US layout] usb:v05ACp020C* ID_MODEL_FROM_DATABASE=Extended Keyboard [Mitsumi] usb:v05ACp020D* ID_MODEL_FROM_DATABASE=Pro Keyboard [Mitsumi, A1048/JIS layout] usb:v05ACp020E* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) usb:v05ACp020F* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) usb:v05ACp0214* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) usb:v05ACp0215* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) usb:v05ACp0216* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) usb:v05ACp0217* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) usb:v05ACp0218* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) usb:v05ACp0219* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) usb:v05ACp021A* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) usb:v05ACp021B* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) usb:v05ACp021C* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) usb:v05ACp021D* ID_MODEL_FROM_DATABASE=Aluminum Mini Keyboard (ANSI) usb:v05ACp021E* ID_MODEL_FROM_DATABASE=Aluminum Mini Keyboard (ISO) usb:v05ACp021F* ID_MODEL_FROM_DATABASE=Aluminum Mini Keyboard (JIS) usb:v05ACp0220* ID_MODEL_FROM_DATABASE=Aluminum Keyboard (ANSI) usb:v05ACp0221* ID_MODEL_FROM_DATABASE=Aluminum Keyboard (ISO) usb:v05ACp0222* ID_MODEL_FROM_DATABASE=Aluminum Keyboard (JIS) usb:v05ACp0223* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) usb:v05ACp0224* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) usb:v05ACp0225* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) usb:v05ACp0229* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) usb:v05ACp022A* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Pro) (ISO) usb:v05ACp022B* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Pro) (JIS) usb:v05ACp0230* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Pro 4,1) (ANSI) usb:v05ACp0231* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Pro 4,1) (ISO) usb:v05ACp0232* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Pro 4,1) (JIS) usb:v05ACp0236* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) usb:v05ACp0237* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) usb:v05ACp0238* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) usb:v05ACp023F* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) usb:v05ACp0240* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) usb:v05ACp0241* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) usb:v05ACp0242* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) usb:v05ACp0243* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) usb:v05ACp0244* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) usb:v05ACp0245* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) usb:v05ACp0246* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) usb:v05ACp0247* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) usb:v05ACp024A* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Air) (ISO) usb:v05ACp024D* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Air) (ISO) usb:v05ACp0250* ID_MODEL_FROM_DATABASE=Aluminium Keyboard (ISO) usb:v05ACp0252* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) usb:v05ACp0253* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) usb:v05ACp0254* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) usb:v05ACp0263* ID_MODEL_FROM_DATABASE=Apple Internal Keyboard / Trackpad (MacBook Retina) usb:v05ACp0301* ID_MODEL_FROM_DATABASE=USB Mouse [Mitsumi, M4848] usb:v05ACp0302* ID_MODEL_FROM_DATABASE=Optical Mouse [Fujitsu] usb:v05ACp0304* ID_MODEL_FROM_DATABASE=Mighty Mouse [Mitsumi, M1152] usb:v05ACp0306* ID_MODEL_FROM_DATABASE=Optical USB Mouse [Fujitsu] usb:v05ACp030A* ID_MODEL_FROM_DATABASE=Internal Trackpad usb:v05ACp030B* ID_MODEL_FROM_DATABASE=Internal Trackpad usb:v05ACp030D* ID_MODEL_FROM_DATABASE=Magic Mouse usb:v05ACp030E* ID_MODEL_FROM_DATABASE=MC380Z/A [Magic Trackpad] usb:v05ACp1000* ID_MODEL_FROM_DATABASE=Bluetooth HCI MacBookPro (HID mode) usb:v05ACp1001* ID_MODEL_FROM_DATABASE=Keyboard Hub [ALPS] usb:v05ACp1002* ID_MODEL_FROM_DATABASE=Extended Keyboard Hub [Mitsumi] usb:v05ACp1003* ID_MODEL_FROM_DATABASE=Hub in Pro Keyboard [Mitsumi, A1048] usb:v05ACp1006* ID_MODEL_FROM_DATABASE=Hub in Aluminum Keyboard usb:v05ACp1008* ID_MODEL_FROM_DATABASE=Mini DisplayPort to Dual-Link DVI Adapter usb:v05ACp1101* ID_MODEL_FROM_DATABASE=Speakers usb:v05ACp1105* ID_MODEL_FROM_DATABASE=Audio in LED Cinema Display usb:v05ACp1107* ID_MODEL_FROM_DATABASE=Thunderbolt Display Audio usb:v05ACp1112* ID_MODEL_FROM_DATABASE=FaceTime HD Camera (Display) usb:v05ACp1201* ID_MODEL_FROM_DATABASE=3G iPod usb:v05ACp1202* ID_MODEL_FROM_DATABASE=iPod 2G usb:v05ACp1203* ID_MODEL_FROM_DATABASE=iPod 4.Gen Grayscale 40G usb:v05ACp1204* ID_MODEL_FROM_DATABASE=iPod [Photo] usb:v05ACp1205* ID_MODEL_FROM_DATABASE=iPod Mini 1.Gen/2.Gen usb:v05ACp1206* ID_MODEL_FROM_DATABASE=iPod '06' usb:v05ACp1207* ID_MODEL_FROM_DATABASE=iPod '07' usb:v05ACp1208* ID_MODEL_FROM_DATABASE=iPod '08' usb:v05ACp1209* ID_MODEL_FROM_DATABASE=iPod Video usb:v05ACp120A* ID_MODEL_FROM_DATABASE=iPod Nano usb:v05ACp1223* ID_MODEL_FROM_DATABASE=iPod Classic/Nano 3.Gen (DFU mode) usb:v05ACp1224* ID_MODEL_FROM_DATABASE=iPod Nano 3.Gen (DFU mode) usb:v05ACp1225* ID_MODEL_FROM_DATABASE=iPod Nano 4.Gen (DFU mode) usb:v05ACp1227* ID_MODEL_FROM_DATABASE=Mobile Device (DFU Mode) usb:v05ACp1231* ID_MODEL_FROM_DATABASE=iPod Nano 5.Gen (DFU mode) usb:v05ACp1240* ID_MODEL_FROM_DATABASE=iPod Nano 2.Gen (DFU mode) usb:v05ACp1242* ID_MODEL_FROM_DATABASE=iPod Nano 3.Gen (WTF mode) usb:v05ACp1243* ID_MODEL_FROM_DATABASE=iPod Nano 4.Gen (WTF mode) usb:v05ACp1245* ID_MODEL_FROM_DATABASE=iPod Classic 3.Gen (WTF mode) usb:v05ACp1246* ID_MODEL_FROM_DATABASE=iPod Nano 5.Gen (WTF mode) usb:v05ACp1255* ID_MODEL_FROM_DATABASE=iPod Nano 4.Gen (DFU mode) usb:v05ACp1260* ID_MODEL_FROM_DATABASE=iPod Nano 2.Gen usb:v05ACp1261* ID_MODEL_FROM_DATABASE=iPod Classic usb:v05ACp1262* ID_MODEL_FROM_DATABASE=iPod Nano 3.Gen usb:v05ACp1263* ID_MODEL_FROM_DATABASE=iPod Nano 4.Gen usb:v05ACp1265* ID_MODEL_FROM_DATABASE=iPod Nano 5.Gen usb:v05ACp1266* ID_MODEL_FROM_DATABASE=iPod Nano 6.Gen usb:v05ACp1267* ID_MODEL_FROM_DATABASE=iPod Nano 7.Gen usb:v05ACp1281* ID_MODEL_FROM_DATABASE=Apple Mobile Device [Recovery Mode] usb:v05ACp1290* ID_MODEL_FROM_DATABASE=iPhone usb:v05ACp1291* ID_MODEL_FROM_DATABASE=iPod Touch 1.Gen usb:v05ACp1292* ID_MODEL_FROM_DATABASE=iPhone 3G usb:v05ACp1293* ID_MODEL_FROM_DATABASE=iPod Touch 2.Gen usb:v05ACp1294* ID_MODEL_FROM_DATABASE=iPhone 3GS usb:v05ACp1296* ID_MODEL_FROM_DATABASE=iPod Touch 3.Gen (8GB) usb:v05ACp1297* ID_MODEL_FROM_DATABASE=iPhone 4 usb:v05ACp1299* ID_MODEL_FROM_DATABASE=iPod Touch 3.Gen usb:v05ACp129A* ID_MODEL_FROM_DATABASE=iPad usb:v05ACp129C* ID_MODEL_FROM_DATABASE=iPhone 4(CDMA) usb:v05ACp129E* ID_MODEL_FROM_DATABASE=iPod Touch 4.Gen usb:v05ACp129F* ID_MODEL_FROM_DATABASE=iPad 2 usb:v05ACp12A0* ID_MODEL_FROM_DATABASE=iPhone 4S usb:v05ACp12A2* ID_MODEL_FROM_DATABASE=iPad 2 (3G; 64GB) usb:v05ACp12A3* ID_MODEL_FROM_DATABASE=iPad 2 (CDMA) usb:v05ACp12A4* ID_MODEL_FROM_DATABASE=iPad 3 (wifi) usb:v05ACp12A5* ID_MODEL_FROM_DATABASE=iPad 3 (CDMA) usb:v05ACp12A6* ID_MODEL_FROM_DATABASE=iPad 3 (3G, 16 GB) usb:v05ACp12A8* ID_MODEL_FROM_DATABASE=iPhone5/5C/5S/6 usb:v05ACp12A9* ID_MODEL_FROM_DATABASE=iPad 2 usb:v05ACp12AA* ID_MODEL_FROM_DATABASE=iPod Touch 5.Gen [A1421] usb:v05ACp12AB* ID_MODEL_FROM_DATABASE=iPad 4/Mini1 usb:v05ACp1300* ID_MODEL_FROM_DATABASE=iPod Shuffle usb:v05ACp1301* ID_MODEL_FROM_DATABASE=iPod Shuffle 2.Gen usb:v05ACp1302* ID_MODEL_FROM_DATABASE=iPod Shuffle 3.Gen usb:v05ACp1303* ID_MODEL_FROM_DATABASE=iPod Shuffle 4.Gen usb:v05ACp1401* ID_MODEL_FROM_DATABASE=Modem usb:v05ACp1402* ID_MODEL_FROM_DATABASE=Ethernet Adapter [A1277] usb:v05ACp1500* ID_MODEL_FROM_DATABASE=SuperDrive [A1379] usb:v05ACp8005* ID_MODEL_FROM_DATABASE=OHCI Root Hub Simulation usb:v05ACp8006* ID_MODEL_FROM_DATABASE=EHCI Root Hub Simulation usb:v05ACp8007* ID_MODEL_FROM_DATABASE=XHCI Root Hub USB 2.0 Simulation usb:v05ACp8202* ID_MODEL_FROM_DATABASE=HCF V.90 Data/Fax Modem usb:v05ACp8203* ID_MODEL_FROM_DATABASE=Bluetooth HCI usb:v05ACp8204* ID_MODEL_FROM_DATABASE=Built-in Bluetooth 2.0+EDR HCI usb:v05ACp8205* ID_MODEL_FROM_DATABASE=Bluetooth HCI usb:v05ACp8206* ID_MODEL_FROM_DATABASE=Bluetooth HCI usb:v05ACp820A* ID_MODEL_FROM_DATABASE=Bluetooth HID Keyboard usb:v05ACp820B* ID_MODEL_FROM_DATABASE=Bluetooth HID Mouse usb:v05ACp820F* ID_MODEL_FROM_DATABASE=Bluetooth HCI usb:v05ACp8213* ID_MODEL_FROM_DATABASE=Bluetooth Host Controller usb:v05ACp8215* ID_MODEL_FROM_DATABASE=Built-in Bluetooth 2.0+EDR HCI usb:v05ACp8216* ID_MODEL_FROM_DATABASE=Bluetooth USB Host Controller usb:v05ACp8217* ID_MODEL_FROM_DATABASE=Bluetooth USB Host Controller usb:v05ACp8218* ID_MODEL_FROM_DATABASE=Bluetooth Host Controller usb:v05ACp821A* ID_MODEL_FROM_DATABASE=Bluetooth Host Controller usb:v05ACp821F* ID_MODEL_FROM_DATABASE=Built-in Bluetooth 2.0+EDR HCI usb:v05ACp8240* ID_MODEL_FROM_DATABASE=Built-in IR Receiver usb:v05ACp8241* ID_MODEL_FROM_DATABASE=Built-in IR Receiver usb:v05ACp8242* ID_MODEL_FROM_DATABASE=Built-in IR Receiver usb:v05ACp8281* ID_MODEL_FROM_DATABASE=Bluetooth Host Controller usb:v05ACp8286* ID_MODEL_FROM_DATABASE=Bluetooth Host Controller usb:v05ACp828C* ID_MODEL_FROM_DATABASE=Bluetooth Host Controller usb:v05ACp8300* ID_MODEL_FROM_DATABASE=Built-in iSight (no firmware loaded) usb:v05ACp8403* ID_MODEL_FROM_DATABASE=Internal Memory Card Reader usb:v05ACp8404* ID_MODEL_FROM_DATABASE=Internal Memory Card Reader usb:v05ACp8501* ID_MODEL_FROM_DATABASE=Built-in iSight [Micron] usb:v05ACp8502* ID_MODEL_FROM_DATABASE=Built-in iSight usb:v05ACp8505* ID_MODEL_FROM_DATABASE=Built-in iSight usb:v05ACp8507* ID_MODEL_FROM_DATABASE=Built-in iSight usb:v05ACp8508* ID_MODEL_FROM_DATABASE=iSight in LED Cinema Display usb:v05ACp8509* ID_MODEL_FROM_DATABASE=FaceTime HD Camera usb:v05ACp850A* ID_MODEL_FROM_DATABASE=FaceTime Camera usb:v05ACp8510* ID_MODEL_FROM_DATABASE=FaceTime HD Camera (Built-in) usb:v05ACp911C* ID_MODEL_FROM_DATABASE=Hub in A1082 [Cinema HD Display 23"] usb:v05ACp9127* ID_MODEL_FROM_DATABASE=Hub in Thunderbolt Display usb:v05ACp912F* ID_MODEL_FROM_DATABASE=Hub in 30" Cinema Display usb:v05ACp9215* ID_MODEL_FROM_DATABASE=Studio Display 15" usb:v05ACp9217* ID_MODEL_FROM_DATABASE=Studio Display 17" usb:v05ACp9218* ID_MODEL_FROM_DATABASE=Cinema Display 23" usb:v05ACp9219* ID_MODEL_FROM_DATABASE=Cinema Display 20" usb:v05ACp921C* ID_MODEL_FROM_DATABASE=A1082 [Cinema HD Display 23"] usb:v05ACp921E* ID_MODEL_FROM_DATABASE=Cinema Display 24" usb:v05ACp9221* ID_MODEL_FROM_DATABASE=30" Cinema Display usb:v05ACp9226* ID_MODEL_FROM_DATABASE=LED Cinema Display usb:v05ACp9227* ID_MODEL_FROM_DATABASE=Thunderbolt Display usb:v05ACp9232* ID_MODEL_FROM_DATABASE=Cinema HD Display 30" usb:v05ACpFFFF* ID_MODEL_FROM_DATABASE=Bluetooth in DFU mode - Driver usb:v05AD* ID_VENDOR_FROM_DATABASE=Y.C. Cable U.S.A., Inc. usb:v05AE* ID_VENDOR_FROM_DATABASE=Synopsys, Inc. usb:v05AF* ID_VENDOR_FROM_DATABASE=Jing-Mold Enterprise Co., Ltd usb:v05AFp0806* ID_MODEL_FROM_DATABASE=HP SK806A Keyboard usb:v05AFp0809* ID_MODEL_FROM_DATABASE=Wireless Keyboard and Mouse usb:v05AFp0821* ID_MODEL_FROM_DATABASE=IDE to usb:v05AFp3062* ID_MODEL_FROM_DATABASE=Cordless Keyboard usb:v05AFp9167* ID_MODEL_FROM_DATABASE=KB 9151B - 678 usb:v05AFp9267* ID_MODEL_FROM_DATABASE=KB 9251B - 678 Mouse usb:v05B0* ID_VENDOR_FROM_DATABASE=Fountain Technologies, Inc. usb:v05B1* ID_VENDOR_FROM_DATABASE=First International Computer, Inc. usb:v05B1p1389* ID_MODEL_FROM_DATABASE=Bluetooth Wireless Adapter usb:v05B4* ID_VENDOR_FROM_DATABASE=LG Semicon Co., Ltd usb:v05B4p4857* ID_MODEL_FROM_DATABASE=M-Any DAH-210 usb:v05B4p6001* ID_MODEL_FROM_DATABASE=HYUNDAI GDS30C6001 SSFDC / MMC I/F Controller usb:v05B5* ID_VENDOR_FROM_DATABASE=Dialogic Corp. usb:v05B6* ID_VENDOR_FROM_DATABASE=Proxima Corp. usb:v05B7* ID_VENDOR_FROM_DATABASE=Medianix Semiconductor, Inc. usb:v05B8* ID_VENDOR_FROM_DATABASE=Agiler, Inc. usb:v05B8p3002* ID_MODEL_FROM_DATABASE=Scroll Mouse usb:v05B9* ID_VENDOR_FROM_DATABASE=Philips Research Laboratories usb:v05BA* ID_VENDOR_FROM_DATABASE=DigitalPersona, Inc. usb:v05BAp0007* ID_MODEL_FROM_DATABASE=Fingerprint Reader usb:v05BAp0008* ID_MODEL_FROM_DATABASE=Fingerprint Reader usb:v05BAp000A* ID_MODEL_FROM_DATABASE=Fingerprint Reader usb:v05BB* ID_VENDOR_FROM_DATABASE=Grey Cell Systems usb:v05BC* ID_VENDOR_FROM_DATABASE=3G Green Green Globe Co., Ltd usb:v05BCp0004* ID_MODEL_FROM_DATABASE=Trackball usb:v05BD* ID_VENDOR_FROM_DATABASE=RAFI GmbH & Co. KG usb:v05BE* ID_VENDOR_FROM_DATABASE=Tyco Electronics (Raychem) usb:v05BF* ID_VENDOR_FROM_DATABASE=S & S Research usb:v05C0* ID_VENDOR_FROM_DATABASE=Keil Software usb:v05C1* ID_VENDOR_FROM_DATABASE=Kawasaki Microelectronics, Inc. usb:v05C2* ID_VENDOR_FROM_DATABASE=Media Phonics (Suisse) S.A. usb:v05C5* ID_VENDOR_FROM_DATABASE=Digi International, Inc. usb:v05C5p0002* ID_MODEL_FROM_DATABASE=AccelePort USB 2 usb:v05C5p0004* ID_MODEL_FROM_DATABASE=AccelePort USB 4 usb:v05C5p0008* ID_MODEL_FROM_DATABASE=AccelePort USB 8 usb:v05C6* ID_VENDOR_FROM_DATABASE=Qualcomm, Inc. usb:v05C6p0114* ID_MODEL_FROM_DATABASE=Select RW-200 CDMA Wireless Modem usb:v05C6p1000* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v05C6p3100* ID_MODEL_FROM_DATABASE=CDMA Wireless Modem/Phone usb:v05C6p3196* ID_MODEL_FROM_DATABASE=CDMA Wireless Modem usb:v05C6p3197* ID_MODEL_FROM_DATABASE=CDMA Wireless Modem/Phone usb:v05C6p6000* ID_MODEL_FROM_DATABASE=Siemens SG75 usb:v05C6p6503* ID_MODEL_FROM_DATABASE=AnyData APE-540H usb:v05C6p6613* ID_MODEL_FROM_DATABASE=Onda H600/N501HS ZTE MF330 usb:v05C6p6764* ID_MODEL_FROM_DATABASE=A0001 Phone [OnePlus One] usb:v05C6p9000* ID_MODEL_FROM_DATABASE=SIMCom SIM5218 modem usb:v05C6p9001* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem usb:v05C6p9002* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem usb:v05C6p9003* ID_MODEL_FROM_DATABASE=Quectel UC20 usb:v05C6p9008* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) usb:v05C6p9018* ID_MODEL_FROM_DATABASE=Qualcomm HSUSB Device usb:v05C6p9025* ID_MODEL_FROM_DATABASE=Qualcomm HSUSB Device usb:v05C6p9201* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) usb:v05C6p9202* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem usb:v05C6p9203* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem usb:v05C6p9205* ID_MODEL_FROM_DATABASE=Gobi 2000 usb:v05C6p9211* ID_MODEL_FROM_DATABASE=Acer Gobi Wireless Modem (QDL mode) usb:v05C6p9212* ID_MODEL_FROM_DATABASE=Acer Gobi Wireless Modem usb:v05C6p9214* ID_MODEL_FROM_DATABASE=Acer Gobi 2000 Wireless Modem (QDL mode) usb:v05C6p9215* ID_MODEL_FROM_DATABASE=Acer Gobi 2000 Wireless Modem usb:v05C6p9221* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) usb:v05C6p9222* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem usb:v05C6p9224* ID_MODEL_FROM_DATABASE=Sony Gobi 2000 Wireless Modem (QDL mode) usb:v05C6p9225* ID_MODEL_FROM_DATABASE=Sony Gobi 2000 Wireless Modem usb:v05C6p9231* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) usb:v05C6p9234* ID_MODEL_FROM_DATABASE=Top Global Gobi 2000 Wireless Modem (QDL mode) usb:v05C6p9235* ID_MODEL_FROM_DATABASE=Top Global Gobi 2000 Wireless Modem usb:v05C6p9244* ID_MODEL_FROM_DATABASE=Samsung Gobi 2000 Wireless Modem (QDL mode) usb:v05C6p9245* ID_MODEL_FROM_DATABASE=Samsung Gobi 2000 Wireless Modem usb:v05C6p9264* ID_MODEL_FROM_DATABASE=Asus Gobi 2000 Wireless Modem (QDL mode) usb:v05C6p9265* ID_MODEL_FROM_DATABASE=Asus Gobi 2000 Wireless Modem usb:v05C6p9274* ID_MODEL_FROM_DATABASE=iRex Technologies Gobi 2000 Wireless Modem (QDL mode) usb:v05C6p9275* ID_MODEL_FROM_DATABASE=iRex Technologies Gobi 2000 Wireless Modem usb:v05C7* ID_VENDOR_FROM_DATABASE=Qtronix Corp. usb:v05C7p0113* ID_MODEL_FROM_DATABASE=PC Line Mouse usb:v05C7p1001* ID_MODEL_FROM_DATABASE=Lynx Mouse usb:v05C7p2001* ID_MODEL_FROM_DATABASE=Keyboard usb:v05C7p2011* ID_MODEL_FROM_DATABASE=SCorpius Keyboard usb:v05C7p6001* ID_MODEL_FROM_DATABASE=Ten-Keypad usb:v05C8* ID_VENDOR_FROM_DATABASE=Cheng Uei Precision Industry Co., Ltd (Foxlink) usb:v05C8p0103* ID_MODEL_FROM_DATABASE=FO13FF-65 PC-CAM usb:v05C8p021A* ID_MODEL_FROM_DATABASE=HP Webcam usb:v05C8p0318* ID_MODEL_FROM_DATABASE=Webcam usb:v05C8p0361* ID_MODEL_FROM_DATABASE=SunplusIT INC. HP Truevision HD Webcam usb:v05C8p036E* ID_MODEL_FROM_DATABASE=Webcam usb:v05C8p0403* ID_MODEL_FROM_DATABASE=Webcam usb:v05C8p041B* ID_MODEL_FROM_DATABASE=HP 2.0MP High Definition Webcam usb:v05C9* ID_VENDOR_FROM_DATABASE=Semtech Corp. usb:v05CA* ID_VENDOR_FROM_DATABASE=Ricoh Co., Ltd usb:v05CAp0101* ID_MODEL_FROM_DATABASE=RDC-5300 Camera usb:v05CAp0325* ID_MODEL_FROM_DATABASE=Caplio GX (ptp) usb:v05CAp032D* ID_MODEL_FROM_DATABASE=Caplio GX 8 (ptp) usb:v05CAp032F* ID_MODEL_FROM_DATABASE=Caplio R3 (ptp) usb:v05CAp03A1* ID_MODEL_FROM_DATABASE=IS200e usb:v05CAp0403* ID_MODEL_FROM_DATABASE=Printing Support usb:v05CAp0405* ID_MODEL_FROM_DATABASE=Type 101 usb:v05CAp0406* ID_MODEL_FROM_DATABASE=Type 102 usb:v05CAp1803* ID_MODEL_FROM_DATABASE=V5 camera [R5U870] usb:v05CAp1810* ID_MODEL_FROM_DATABASE=Pavilion Webcam [R5U870] usb:v05CAp1812* ID_MODEL_FROM_DATABASE=Pavilion Webcam usb:v05CAp1814* ID_MODEL_FROM_DATABASE=HD Webcam usb:v05CAp1815* ID_MODEL_FROM_DATABASE=Dell Laptop Integrated Webcam usb:v05CAp1820* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v05CAp1830* ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC2 [R5U870] usb:v05CAp1832* ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC3 [R5U870] usb:v05CAp1833* ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC2 [R5U870] usb:v05CAp1834* ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC2 [R5U870] usb:v05CAp1835* ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC5 [R5U870] usb:v05CAp1836* ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC4 [R5U870] usb:v05CAp1837* ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC4 [R5U870] usb:v05CAp1839* ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC6 [R5U870] usb:v05CAp183A* ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC7 [R5U870] usb:v05CAp183B* ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC8 [R5U870] usb:v05CAp183D* ID_MODEL_FROM_DATABASE=Sony Vaio Integrated Webcam usb:v05CAp183E* ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC9 [R5U870] usb:v05CAp1841* ID_MODEL_FROM_DATABASE=Fujitsu F01/ Lifebook U810 [R5U870] usb:v05CAp1870* ID_MODEL_FROM_DATABASE=Webcam 1000 usb:v05CAp18B0* ID_MODEL_FROM_DATABASE=Sony Vaio Integrated Webcam usb:v05CAp18B1* ID_MODEL_FROM_DATABASE=Sony Vaio Integrated Webcam usb:v05CAp18B3* ID_MODEL_FROM_DATABASE=Sony Vaio Integrated Webcam usb:v05CAp18B5* ID_MODEL_FROM_DATABASE=Sony Vaio Integrated Webcam usb:v05CAp2201* ID_MODEL_FROM_DATABASE=RDC-7 Camera usb:v05CAp2202* ID_MODEL_FROM_DATABASE=Caplio RR30 usb:v05CAp2203* ID_MODEL_FROM_DATABASE=Caplio 300G usb:v05CAp2204* ID_MODEL_FROM_DATABASE=Caplio G3 usb:v05CAp2205* ID_MODEL_FROM_DATABASE=Caplio RR30 / Medion MD 6126 Camera usb:v05CAp2206* ID_MODEL_FROM_DATABASE=Konica DG-3Z usb:v05CAp2207* ID_MODEL_FROM_DATABASE=Caplio Pro G3 usb:v05CAp2208* ID_MODEL_FROM_DATABASE=Caplio G4 usb:v05CAp2209* ID_MODEL_FROM_DATABASE=Caplio 400G wide usb:v05CAp220A* ID_MODEL_FROM_DATABASE=KONICA MINOLTA DG-4Wide usb:v05CAp220B* ID_MODEL_FROM_DATABASE=Caplio RX usb:v05CAp220C* ID_MODEL_FROM_DATABASE=Caplio GX usb:v05CAp220D* ID_MODEL_FROM_DATABASE=Caplio R1/RZ1 usb:v05CAp220E* ID_MODEL_FROM_DATABASE=Sea & Sea 5000G usb:v05CAp220F* ID_MODEL_FROM_DATABASE=Rollei dr5 / Rollei dr5 (PTP mode) usb:v05CAp2211* ID_MODEL_FROM_DATABASE=Caplio R1S usb:v05CAp2212* ID_MODEL_FROM_DATABASE=Caplio R1v Camera usb:v05CAp2213* ID_MODEL_FROM_DATABASE=Caplio R2 usb:v05CAp2214* ID_MODEL_FROM_DATABASE=Caplio GX 8 usb:v05CAp2215* ID_MODEL_FROM_DATABASE=DSC 725 usb:v05CAp2216* ID_MODEL_FROM_DATABASE=Caplio R3 usb:v05CAp2222* ID_MODEL_FROM_DATABASE=RDC-i500 usb:v05CB* ID_VENDOR_FROM_DATABASE=PowerVision Technologies, Inc. usb:v05CBp1483* ID_MODEL_FROM_DATABASE=PV8630 interface (scanners, webcams) usb:v05CC* ID_VENDOR_FROM_DATABASE=ELSA AG usb:v05CCp2100* ID_MODEL_FROM_DATABASE=MicroLink ISDN Office usb:v05CCp2219* ID_MODEL_FROM_DATABASE=MicroLink ISDN usb:v05CCp2265* ID_MODEL_FROM_DATABASE=MicroLink 56k usb:v05CCp2267* ID_MODEL_FROM_DATABASE=MicroLink 56k (V.250) usb:v05CCp2280* ID_MODEL_FROM_DATABASE=MicroLink 56k Fun usb:v05CCp3000* ID_MODEL_FROM_DATABASE=Micolink USB2Ethernet [pegasus] usb:v05CCp3100* ID_MODEL_FROM_DATABASE=AirLancer USB-11 usb:v05CCp3363* ID_MODEL_FROM_DATABASE=MicroLink ADSL Fun usb:v05CD* ID_VENDOR_FROM_DATABASE=Silicom, Ltd usb:v05CE* ID_VENDOR_FROM_DATABASE=sci-worx GmbH usb:v05CF* ID_VENDOR_FROM_DATABASE=Sung Forn Co., Ltd usb:v05D0* ID_VENDOR_FROM_DATABASE=GE Medical Systems Lunar usb:v05D1* ID_VENDOR_FROM_DATABASE=Brainboxes, Ltd usb:v05D1p0003* ID_MODEL_FROM_DATABASE=Bluetooth Adapter BL-554 usb:v05D2* ID_VENDOR_FROM_DATABASE=Wave Systems Corp. usb:v05D3* ID_VENDOR_FROM_DATABASE=Tohoku Ricoh Co., Ltd usb:v05D5* ID_VENDOR_FROM_DATABASE=Super Gate Technology Co., Ltd usb:v05D6* ID_VENDOR_FROM_DATABASE=Philips Semiconductors, CICT usb:v05D7* ID_VENDOR_FROM_DATABASE=Thomas & Betts Corp. usb:v05D7p0099* ID_MODEL_FROM_DATABASE=10Mbps Ethernet [klsi] usb:v05D8* ID_VENDOR_FROM_DATABASE=Ultima Electronics Corp. usb:v05D8p4001* ID_MODEL_FROM_DATABASE=Artec Ultima 2000 usb:v05D8p4002* ID_MODEL_FROM_DATABASE=Artec Ultima 2000 (GT6801 based)/Lifetec LT9385/ScanMagic 1200 UB Plus Scanner usb:v05D8p4003* ID_MODEL_FROM_DATABASE=Artec E+ 48U usb:v05D8p4004* ID_MODEL_FROM_DATABASE=Artec E+ Pro usb:v05D8p4005* ID_MODEL_FROM_DATABASE=MEM48U usb:v05D8p4006* ID_MODEL_FROM_DATABASE=TRUST EASY WEBSCAN 19200 usb:v05D8p4007* ID_MODEL_FROM_DATABASE=TRUST 240H EASY WEBSCAN GOLD usb:v05D8p4008* ID_MODEL_FROM_DATABASE=Trust Easy Webscan 19200 usb:v05D8p4009* ID_MODEL_FROM_DATABASE=Umax Astraslim usb:v05D8p4013* ID_MODEL_FROM_DATABASE=IT Scan 1200 usb:v05D8p8105* ID_MODEL_FROM_DATABASE=Artec T1 USB TVBOX (cold) usb:v05D8p8106* ID_MODEL_FROM_DATABASE=Artec T1 USB TVBOX (warm) usb:v05D8p8107* ID_MODEL_FROM_DATABASE=Artec T1 USB TVBOX with AN2235 (cold) usb:v05D8p8108* ID_MODEL_FROM_DATABASE=Artec T1 USB TVBOX with AN2235 (warm) usb:v05D8p8109* ID_MODEL_FROM_DATABASE=Artec T1 USB2.0 TVBOX (cold usb:v05D9* ID_VENDOR_FROM_DATABASE=Axiohm Transaction Solutions usb:v05D9pA225* ID_MODEL_FROM_DATABASE=A225 Printer usb:v05D9pA758* ID_MODEL_FROM_DATABASE=A758 Printer usb:v05D9pA794* ID_MODEL_FROM_DATABASE=A794 Printer usb:v05DA* ID_VENDOR_FROM_DATABASE=Microtek International, Inc. usb:v05DAp0091* ID_MODEL_FROM_DATABASE=ScanMaker X6u usb:v05DAp0093* ID_MODEL_FROM_DATABASE=ScanMaker V6USL usb:v05DAp0094* ID_MODEL_FROM_DATABASE=Phantom 336CX/C3 usb:v05DAp0099* ID_MODEL_FROM_DATABASE=ScanMaker X6/X6U usb:v05DAp009A* ID_MODEL_FROM_DATABASE=Phantom C6 usb:v05DAp00A0* ID_MODEL_FROM_DATABASE=Phantom 336CX/C3 (#2) usb:v05DAp00A3* ID_MODEL_FROM_DATABASE=ScanMaker V6USL usb:v05DAp00AC* ID_MODEL_FROM_DATABASE=ScanMaker V6UL usb:v05DAp00B6* ID_MODEL_FROM_DATABASE=ScanMaker V6UPL usb:v05DAp00EF* ID_MODEL_FROM_DATABASE=ScanMaker V6UPL usb:v05DAp1006* ID_MODEL_FROM_DATABASE=Jenoptik JD350 entrance usb:v05DAp1011* ID_MODEL_FROM_DATABASE=NHJ Che-ez! Kiss Digital Camera usb:v05DAp1018* ID_MODEL_FROM_DATABASE=Digital Dream Enigma 1.3 usb:v05DAp1020* ID_MODEL_FROM_DATABASE=Digital Dream l'espion xtra usb:v05DAp1025* ID_MODEL_FROM_DATABASE=Take-it Still Camera Device usb:v05DAp1026* ID_MODEL_FROM_DATABASE=Take-it usb:v05DAp1043* ID_MODEL_FROM_DATABASE=Take-It 1300 DSC Bulk Driver usb:v05DAp1045* ID_MODEL_FROM_DATABASE=Take-it D1 usb:v05DAp1047* ID_MODEL_FROM_DATABASE=Take-it Camera Composite Device usb:v05DAp1048* ID_MODEL_FROM_DATABASE=Take-it Q3 usb:v05DAp1049* ID_MODEL_FROM_DATABASE=3M Still Camera Device usb:v05DAp1051* ID_MODEL_FROM_DATABASE=Camcorder Series usb:v05DAp1052* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v05DAp1053* ID_MODEL_FROM_DATABASE=Take-it DV Composite Device usb:v05DAp1054* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v05DAp1055* ID_MODEL_FROM_DATABASE=Digital Camera Series(536) usb:v05DAp1056* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v05DAp1057* ID_MODEL_FROM_DATABASE=Take-it DSC Camera Device(536) usb:v05DAp1058* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v05DAp1059* ID_MODEL_FROM_DATABASE=Camcorder DSC Series usb:v05DAp1060* ID_MODEL_FROM_DATABASE=Microtek Take-it MV500 usb:v05DAp2007* ID_MODEL_FROM_DATABASE=ArtixScan DI 1210 usb:v05DAp200C* ID_MODEL_FROM_DATABASE=1394_USB2 Scanner usb:v05DAp200E* ID_MODEL_FROM_DATABASE=ArtixScan DI 810 usb:v05DAp2017* ID_MODEL_FROM_DATABASE=UF ICE Scanner usb:v05DAp201C* ID_MODEL_FROM_DATABASE=4800 Scanner usb:v05DAp201D* ID_MODEL_FROM_DATABASE=ArtixScan DI 1610 usb:v05DAp201F* ID_MODEL_FROM_DATABASE=4800 Scanner-ICE usb:v05DAp202E* ID_MODEL_FROM_DATABASE=ArtixScan DI 2020 usb:v05DAp208B* ID_MODEL_FROM_DATABASE=ScanMaker 6800 usb:v05DAp208F* ID_MODEL_FROM_DATABASE=ArtixScan DI 2010 usb:v05DAp209E* ID_MODEL_FROM_DATABASE=ScanMaker 4700LP usb:v05DAp20A7* ID_MODEL_FROM_DATABASE=ScanMaker 5600 usb:v05DAp20B0* ID_MODEL_FROM_DATABASE=ScanMaker X12USL usb:v05DAp20B1* ID_MODEL_FROM_DATABASE=ScanMaker 8700 usb:v05DAp20B4* ID_MODEL_FROM_DATABASE=ScanMaker 4700 usb:v05DAp20BD* ID_MODEL_FROM_DATABASE=ScanMaker 5700 usb:v05DAp20C9* ID_MODEL_FROM_DATABASE=ScanMaker 6700 usb:v05DAp20D2* ID_MODEL_FROM_DATABASE=Microtek ArtixScan 1800f usb:v05DAp20D6* ID_MODEL_FROM_DATABASE=PS4000 usb:v05DAp20DE* ID_MODEL_FROM_DATABASE=ScanMaker 9800XL usb:v05DAp20E0* ID_MODEL_FROM_DATABASE=ScanMaker 9700XL usb:v05DAp20ED* ID_MODEL_FROM_DATABASE=ScanMaker 4700 usb:v05DAp20EE* ID_MODEL_FROM_DATABASE=Micortek ScanMaker X12USL usb:v05DAp2838* ID_MODEL_FROM_DATABASE=RT2832U usb:v05DAp3008* ID_MODEL_FROM_DATABASE=Scanner usb:v05DAp300A* ID_MODEL_FROM_DATABASE=4800 ICE Scanner usb:v05DAp300B* ID_MODEL_FROM_DATABASE=4800 Scanner usb:v05DAp300F* ID_MODEL_FROM_DATABASE=MiniScan C5 usb:v05DAp3020* ID_MODEL_FROM_DATABASE=4800dpi Scanner usb:v05DAp3021* ID_MODEL_FROM_DATABASE=1200dpi Scanner usb:v05DAp3022* ID_MODEL_FROM_DATABASE=Scanner 4800dpi usb:v05DAp3023* ID_MODEL_FROM_DATABASE=USB1200II Scanner usb:v05DAp30C1* ID_MODEL_FROM_DATABASE=USB600 Scanner usb:v05DAp30CE* ID_MODEL_FROM_DATABASE=ScanMaker 3800 usb:v05DAp30CF* ID_MODEL_FROM_DATABASE=ScanMaker 4800 usb:v05DAp30D4* ID_MODEL_FROM_DATABASE=USB1200 Scanner usb:v05DAp30D8* ID_MODEL_FROM_DATABASE=Scanner usb:v05DAp30D9* ID_MODEL_FROM_DATABASE=USB2400 Scanner usb:v05DAp30E4* ID_MODEL_FROM_DATABASE=ScanMaker 4100 usb:v05DAp30E5* ID_MODEL_FROM_DATABASE=USB3200 Scanner usb:v05DAp30E6* ID_MODEL_FROM_DATABASE=ScanMaker i320 usb:v05DAp40B3* ID_MODEL_FROM_DATABASE=ScanMaker 3600 usb:v05DAp40B8* ID_MODEL_FROM_DATABASE=ScanMaker 3700 usb:v05DAp40C7* ID_MODEL_FROM_DATABASE=ScanMaker 4600 usb:v05DAp40CA* ID_MODEL_FROM_DATABASE=ScanMaker 3600 usb:v05DAp40CB* ID_MODEL_FROM_DATABASE=ScanMaker 3700 usb:v05DAp40DD* ID_MODEL_FROM_DATABASE=ScanMaker 3750i usb:v05DAp40FF* ID_MODEL_FROM_DATABASE=ScanMaker 3600 usb:v05DAp5003* ID_MODEL_FROM_DATABASE=Goya usb:v05DAp5013* ID_MODEL_FROM_DATABASE=3200 Scanner usb:v05DAp6072* ID_MODEL_FROM_DATABASE=XT-3500 A4 HD Scanner usb:v05DAp80A3* ID_MODEL_FROM_DATABASE=ScanMaker V6USL (#2) usb:v05DAp80AC* ID_MODEL_FROM_DATABASE=ScanMaker V6UL/SpicyU usb:v05DB* ID_VENDOR_FROM_DATABASE=Sun Corp. (Suntac?) usb:v05DBp0003* ID_MODEL_FROM_DATABASE=SUNTAC U-Cable type D2 usb:v05DBp0005* ID_MODEL_FROM_DATABASE=SUNTAC U-Cable type P1 usb:v05DBp0009* ID_MODEL_FROM_DATABASE=SUNTAC Slipper U usb:v05DBp000A* ID_MODEL_FROM_DATABASE=SUNTAC Ir-Trinity usb:v05DBp000B* ID_MODEL_FROM_DATABASE=SUNTAC U-Cable type A3 usb:v05DBp0011* ID_MODEL_FROM_DATABASE=SUNTAC U-Cable type A4 usb:v05DC* ID_VENDOR_FROM_DATABASE=Lexar Media, Inc. usb:v05DCp0001* ID_MODEL_FROM_DATABASE=jumpSHOT CompactFlash Reader usb:v05DCp0002* ID_MODEL_FROM_DATABASE=JumpShot usb:v05DCp0003* ID_MODEL_FROM_DATABASE=JumpShot usb:v05DCp0080* ID_MODEL_FROM_DATABASE=Jumpdrive Secure 64MB usb:v05DCp0081* ID_MODEL_FROM_DATABASE=RBC Compact Flash Drive usb:v05DCp00A7* ID_MODEL_FROM_DATABASE=JumpDrive Impact usb:v05DCp0100* ID_MODEL_FROM_DATABASE=JumpDrive PRO usb:v05DCp0200* ID_MODEL_FROM_DATABASE=JumpDrive 2.0 Pro usb:v05DCp0300* ID_MODEL_FROM_DATABASE=Jumpdrive Geysr usb:v05DCp0301* ID_MODEL_FROM_DATABASE=JumpDrive Classic usb:v05DCp0302* ID_MODEL_FROM_DATABASE=JD Micro usb:v05DCp0303* ID_MODEL_FROM_DATABASE=JD Micro Pro usb:v05DCp0304* ID_MODEL_FROM_DATABASE=JD Secure II usb:v05DCp0310* ID_MODEL_FROM_DATABASE=JumpDrive usb:v05DCp0311* ID_MODEL_FROM_DATABASE=JumpDrive Classic usb:v05DCp0312* ID_MODEL_FROM_DATABASE=JD Micro usb:v05DCp0313* ID_MODEL_FROM_DATABASE=JD Micro Pro usb:v05DCp0320* ID_MODEL_FROM_DATABASE=JumpDrive usb:v05DCp0321* ID_MODEL_FROM_DATABASE=JD Micro usb:v05DCp0322* ID_MODEL_FROM_DATABASE=JD Micro Pro usb:v05DCp0323* ID_MODEL_FROM_DATABASE=UFC usb:v05DCp0330* ID_MODEL_FROM_DATABASE=JumpDrive Expression usb:v05DCp0340* ID_MODEL_FROM_DATABASE=JumpDrive TAD usb:v05DCp0350* ID_MODEL_FROM_DATABASE=Express Card usb:v05DCp0400* ID_MODEL_FROM_DATABASE=UFDC usb:v05DCp0401* ID_MODEL_FROM_DATABASE=UFDC usb:v05DCp0403* ID_MODEL_FROM_DATABASE=Locked B Device usb:v05DCp0405* ID_MODEL_FROM_DATABASE=Locked C Device usb:v05DCp0407* ID_MODEL_FROM_DATABASE=Locked D Device usb:v05DCp0409* ID_MODEL_FROM_DATABASE=Locked E Device usb:v05DCp040B* ID_MODEL_FROM_DATABASE=Locked F Device usb:v05DCp040D* ID_MODEL_FROM_DATABASE=Locked G Device usb:v05DCp040F* ID_MODEL_FROM_DATABASE=Locked H Device usb:v05DCp0410* ID_MODEL_FROM_DATABASE=JumpDrive usb:v05DCp0411* ID_MODEL_FROM_DATABASE=JumpDrive usb:v05DCp0413* ID_MODEL_FROM_DATABASE=Locked J Device usb:v05DCp0415* ID_MODEL_FROM_DATABASE=Locked K Device usb:v05DCp0417* ID_MODEL_FROM_DATABASE=Locked L Device usb:v05DCp0419* ID_MODEL_FROM_DATABASE=Locked M Device usb:v05DCp041B* ID_MODEL_FROM_DATABASE=Locked N Device usb:v05DCp041D* ID_MODEL_FROM_DATABASE=Locked O Device usb:v05DCp041F* ID_MODEL_FROM_DATABASE=Locked P Device usb:v05DCp0420* ID_MODEL_FROM_DATABASE=JumpDrive usb:v05DCp0421* ID_MODEL_FROM_DATABASE=JumpDrive usb:v05DCp0423* ID_MODEL_FROM_DATABASE=Locked R Device usb:v05DCp0425* ID_MODEL_FROM_DATABASE=Locked S Device usb:v05DCp0427* ID_MODEL_FROM_DATABASE=Locked T Device usb:v05DCp0429* ID_MODEL_FROM_DATABASE=Locked U Device usb:v05DCp042B* ID_MODEL_FROM_DATABASE=Locked V Device usb:v05DCp042D* ID_MODEL_FROM_DATABASE=Locked W Device usb:v05DCp042F* ID_MODEL_FROM_DATABASE=Locked X Device usb:v05DCp0431* ID_MODEL_FROM_DATABASE=Locked Y Device usb:v05DCp0433* ID_MODEL_FROM_DATABASE=Locked Z Device usb:v05DCp4D02* ID_MODEL_FROM_DATABASE=MP3 Player usb:v05DCp4D12* ID_MODEL_FROM_DATABASE=MP3 Player usb:v05DCp4D30* ID_MODEL_FROM_DATABASE=MP3 Player usb:v05DCpA209* ID_MODEL_FROM_DATABASE=JumpDrive S70 usb:v05DCpA300* ID_MODEL_FROM_DATABASE=JumpDrive2 usb:v05DCpA400* ID_MODEL_FROM_DATABASE=JumpDrive trade; Pro 40-501 usb:v05DCpA410* ID_MODEL_FROM_DATABASE=JumpDrive 128MB/256MB usb:v05DCpA411* ID_MODEL_FROM_DATABASE=JumpDrive Traveler usb:v05DCpA420* ID_MODEL_FROM_DATABASE=JumpDrive Pro usb:v05DCpA421* ID_MODEL_FROM_DATABASE=JumpDrive Pro II usb:v05DCpA422* ID_MODEL_FROM_DATABASE=JumpDrive Micro Pro usb:v05DCpA430* ID_MODEL_FROM_DATABASE=JumpDrive Secure usb:v05DCpA431* ID_MODEL_FROM_DATABASE=JumpDrive Secure II usb:v05DCpA432* ID_MODEL_FROM_DATABASE=JumpDrive Classic usb:v05DCpA440* ID_MODEL_FROM_DATABASE=JumpDrive Lightning usb:v05DCpA450* ID_MODEL_FROM_DATABASE=JumpDrive TouchGuard usb:v05DCpA460* ID_MODEL_FROM_DATABASE=JD Mercury usb:v05DCpA501* ID_MODEL_FROM_DATABASE=JumpDrive Classic usb:v05DCpA510* ID_MODEL_FROM_DATABASE=JumpDrive Sport usb:v05DCpA530* ID_MODEL_FROM_DATABASE=JumpDrive Expression usb:v05DCpA531* ID_MODEL_FROM_DATABASE=JumpDrive Secure II usb:v05DCpA560* ID_MODEL_FROM_DATABASE=JumpDrive FireFly usb:v05DCpA701* ID_MODEL_FROM_DATABASE=JumpDrive FireFly usb:v05DCpA731* ID_MODEL_FROM_DATABASE=JumpDrive FireFly usb:v05DCpA768* ID_MODEL_FROM_DATABASE=JumpDrive Retrax usb:v05DCpA790* ID_MODEL_FROM_DATABASE=JumpDrive 2GB usb:v05DCpA811* ID_MODEL_FROM_DATABASE=16GB Gizmo! usb:v05DCpA813* ID_MODEL_FROM_DATABASE=16gB flash thumb drive usb:v05DCpA815* ID_MODEL_FROM_DATABASE=JumpDrive V10 usb:v05DCpA833* ID_MODEL_FROM_DATABASE=JumpDrive S23 64GB usb:v05DCpB002* ID_MODEL_FROM_DATABASE=USB CF Reader usb:v05DCpB018* ID_MODEL_FROM_DATABASE=Multi-Card Reader usb:v05DCpB047* ID_MODEL_FROM_DATABASE=SDHC Reader [RW047-7000] usb:v05DCpBA02* ID_MODEL_FROM_DATABASE=Workflow CFR1 usb:v05DCpC753* ID_MODEL_FROM_DATABASE=JumpDrive TwistTurn usb:v05DD* ID_VENDOR_FROM_DATABASE=Delta Electronics, Inc. usb:v05DDpFF31* ID_MODEL_FROM_DATABASE=AWU-120 usb:v05DDpFF32* ID_MODEL_FROM_DATABASE=FriendlyNET AeroLAN AL2011 usb:v05DDpFF35* ID_MODEL_FROM_DATABASE=PCW 100 - Wireless 802.11b Adapter usb:v05DDpFF91* ID_MODEL_FROM_DATABASE=2Wire PC Port Phoneline 10Mbps Adapter usb:v05DF* ID_VENDOR_FROM_DATABASE=Silicon Vision, Inc. usb:v05E0* ID_VENDOR_FROM_DATABASE=Symbol Technologies usb:v05E0p0700* ID_MODEL_FROM_DATABASE=Bar Code Scanner (CS1504) usb:v05E0p0800* ID_MODEL_FROM_DATABASE=Spectrum24 Wireless LAN Adapter usb:v05E0p1200* ID_MODEL_FROM_DATABASE=Bar Code Scanner usb:v05E0p1701* ID_MODEL_FROM_DATABASE=Bar Code Scanner (CDC) usb:v05E0p1900* ID_MODEL_FROM_DATABASE=SNAPI Imaging Device usb:v05E0p2000* ID_MODEL_FROM_DATABASE=MC3090 Rugged Mobile Computer usb:v05E0p200D* ID_MODEL_FROM_DATABASE=MC70 Rugged Mobile Computer usb:v05E1* ID_VENDOR_FROM_DATABASE=Syntek Semiconductor Co., Ltd usb:v05E1p0100* ID_MODEL_FROM_DATABASE=802.11g + Bluetooth Wireless Adapter usb:v05E1p0408* ID_MODEL_FROM_DATABASE=STK1160 Video Capture Device usb:v05E1p0500* ID_MODEL_FROM_DATABASE=DC-112X Webcam usb:v05E1p0501* ID_MODEL_FROM_DATABASE=DC-1125 Webcam usb:v05E1p0890* ID_MODEL_FROM_DATABASE=STK011 Camera usb:v05E1p0892* ID_MODEL_FROM_DATABASE=STK013 Camera usb:v05E1p0895* ID_MODEL_FROM_DATABASE=STK016 Camera usb:v05E1p0896* ID_MODEL_FROM_DATABASE=STK017 Camera usb:v05E1p2010* ID_MODEL_FROM_DATABASE=ARCTIC Sound P261 Headphones usb:v05E2* ID_VENDOR_FROM_DATABASE=ElecVision, Inc. usb:v05E3* ID_VENDOR_FROM_DATABASE=Genesys Logic, Inc. usb:v05E3p000A* ID_MODEL_FROM_DATABASE=Keyboard with PS/2 Port usb:v05E3p000B* ID_MODEL_FROM_DATABASE=Mouse usb:v05E3p0100* ID_MODEL_FROM_DATABASE=Nintendo Game Boy Advance SP usb:v05E3p0120* ID_MODEL_FROM_DATABASE=Pacific Image Electronics PrimeFilm 1800u slide/negative scanner usb:v05E3p0131* ID_MODEL_FROM_DATABASE=CF/SM Reader/Writer usb:v05E3p0142* ID_MODEL_FROM_DATABASE=Multiple Slides Scanner-3600 usb:v05E3p0143* ID_MODEL_FROM_DATABASE=Multiple Frames Film Scanner-36series usb:v05E3p0180* ID_MODEL_FROM_DATABASE=Plustek Scanner usb:v05E3p0182* ID_MODEL_FROM_DATABASE=Wize Media 1000 usb:v05E3p0189* ID_MODEL_FROM_DATABASE=ScanJet 4600 series usb:v05E3p018A* ID_MODEL_FROM_DATABASE=Xerox 6400 usb:v05E3p0300* ID_MODEL_FROM_DATABASE=GLUSB98PT Parallel Port usb:v05E3p0301* ID_MODEL_FROM_DATABASE=USB2LPT Cable Release2 usb:v05E3p0406* ID_MODEL_FROM_DATABASE=Hub usb:v05E3p0501* ID_MODEL_FROM_DATABASE=GL620USB Host-Host interface usb:v05E3p0502* ID_MODEL_FROM_DATABASE=GL620USB-A GeneLink USB-USB Bridge usb:v05E3p0503* ID_MODEL_FROM_DATABASE=Webcam usb:v05E3p0504* ID_MODEL_FROM_DATABASE=HID Keyboard Filter usb:v05E3p0604* ID_MODEL_FROM_DATABASE=USB 1.1 Hub usb:v05E3p0605* ID_MODEL_FROM_DATABASE=USB 2.0 Hub usb:v05E3p0606* ID_MODEL_FROM_DATABASE=USB 2.0 Hub / D-Link DUB-H4 USB 2.0 Hub usb:v05E3p0607* ID_MODEL_FROM_DATABASE=Logitech G110 Hub usb:v05E3p0608* ID_MODEL_FROM_DATABASE=Hub usb:v05E3p0610* ID_MODEL_FROM_DATABASE=4-port hub usb:v05E3p0616* ID_MODEL_FROM_DATABASE=hub usb:v05E3p0660* ID_MODEL_FROM_DATABASE=USB 2.0 Hub usb:v05E3p0700* ID_MODEL_FROM_DATABASE=SIIG US2256 CompactFlash Card Reader usb:v05E3p0701* ID_MODEL_FROM_DATABASE=USB 2.0 IDE Adapter usb:v05E3p0702* ID_MODEL_FROM_DATABASE=USB 2.0 IDE Adapter [GL811E] usb:v05E3p0703* ID_MODEL_FROM_DATABASE=Card Reader usb:v05E3p0704* ID_MODEL_FROM_DATABASE=Card Reader usb:v05E3p0705* ID_MODEL_FROM_DATABASE=Card Reader usb:v05E3p0706* ID_MODEL_FROM_DATABASE=Card Reader usb:v05E3p0707* ID_MODEL_FROM_DATABASE=Card Reader usb:v05E3p0708* ID_MODEL_FROM_DATABASE=Card Reader usb:v05E3p0709* ID_MODEL_FROM_DATABASE=Card Reader usb:v05E3p070A* ID_MODEL_FROM_DATABASE=Pen Flash usb:v05E3p070B* ID_MODEL_FROM_DATABASE=DMHS1B Rev 3 DFU Adapter usb:v05E3p070E* ID_MODEL_FROM_DATABASE=USB 2.0 Card Reader usb:v05E3p070F* ID_MODEL_FROM_DATABASE=Pen Flash usb:v05E3p0710* ID_MODEL_FROM_DATABASE=USB 2.0 33-in-1 Card Reader usb:v05E3p0711* ID_MODEL_FROM_DATABASE=Card Reader usb:v05E3p0712* ID_MODEL_FROM_DATABASE=Delkin Mass Storage Device usb:v05E3p0715* ID_MODEL_FROM_DATABASE=USB 2.0 microSD Reader usb:v05E3p0716* ID_MODEL_FROM_DATABASE=USB 2.0 Multislot Card Reader/Writer usb:v05E3p0717* ID_MODEL_FROM_DATABASE=All-in-1 Card Reader usb:v05E3p0718* ID_MODEL_FROM_DATABASE=IDE/SATA Adapter usb:v05E3p0719* ID_MODEL_FROM_DATABASE=SATA adapter usb:v05E3p0722* ID_MODEL_FROM_DATABASE=SD/MMC card reader usb:v05E3p0723* ID_MODEL_FROM_DATABASE=GL827L SD/MMC/MS Flash Card Reader usb:v05E3p0726* ID_MODEL_FROM_DATABASE=SD Card Reader usb:v05E3p0727* ID_MODEL_FROM_DATABASE=microSD Reader/Writer usb:v05E3p0731* ID_MODEL_FROM_DATABASE=GL3310 SATA 3Gb/s Bridge Controller usb:v05E3p0732* ID_MODEL_FROM_DATABASE=All-in-One Cardreader usb:v05E3p0736* ID_MODEL_FROM_DATABASE=microSD Reader/Writer usb:v05E3p0741* ID_MODEL_FROM_DATABASE=microSD Card Reader usb:v05E3p0743* ID_MODEL_FROM_DATABASE=SDXC and microSDXC CardReader usb:v05E3p0745* ID_MODEL_FROM_DATABASE=Logilink CR0012 usb:v05E3p0760* ID_MODEL_FROM_DATABASE=USB 2.0 Card Reader/Writer usb:v05E3p0761* ID_MODEL_FROM_DATABASE=Genesys Mass Storage Device usb:v05E3p0780* ID_MODEL_FROM_DATABASE=USBFS DFU Adapter usb:v05E3p07A0* ID_MODEL_FROM_DATABASE=Pen Flash usb:v05E3p0880* ID_MODEL_FROM_DATABASE=Wasp (SL-6612) usb:v05E3p0927* ID_MODEL_FROM_DATABASE=Card Reader usb:v05E3p1205* ID_MODEL_FROM_DATABASE=Afilias Optical Mouse H3003 / Trust Optical USB MultiColour Mouse MI-2330 usb:v05E3pA700* ID_MODEL_FROM_DATABASE=Pen Flash usb:v05E3pF102* ID_MODEL_FROM_DATABASE=VX7012 TV Box usb:v05E3pF103* ID_MODEL_FROM_DATABASE=VX7012 TV Box usb:v05E3pF104* ID_MODEL_FROM_DATABASE=VX7012 TV Box usb:v05E3pFD21* ID_MODEL_FROM_DATABASE=3M TL20 Temperature Logger usb:v05E3pFE00* ID_MODEL_FROM_DATABASE=Razer Mouse usb:v05E4* ID_VENDOR_FROM_DATABASE=Red Wing Corp. usb:v05E5* ID_VENDOR_FROM_DATABASE=Fuji Electric Co., Ltd usb:v05E6* ID_VENDOR_FROM_DATABASE=Keithley Instruments usb:v05E8* ID_VENDOR_FROM_DATABASE=ICC, Inc. usb:v05E9* ID_VENDOR_FROM_DATABASE=Kawasaki LSI usb:v05E9p0008* ID_MODEL_FROM_DATABASE=KL5KUSB101B Ethernet [klsi] usb:v05E9p0009* ID_MODEL_FROM_DATABASE=Sony 10Mbps Ethernet [pegasus] usb:v05E9p000C* ID_MODEL_FROM_DATABASE=USB-to-RS-232 usb:v05E9p000D* ID_MODEL_FROM_DATABASE=USB-to-RS-232 usb:v05E9p0014* ID_MODEL_FROM_DATABASE=RS-232 J104 usb:v05E9p0040* ID_MODEL_FROM_DATABASE=Ethernet Adapter usb:v05E9p2008* ID_MODEL_FROM_DATABASE=Ethernet Adapter usb:v05EB* ID_VENDOR_FROM_DATABASE=FFC, Ltd usb:v05EC* ID_VENDOR_FROM_DATABASE=COM21, Inc. usb:v05EE* ID_VENDOR_FROM_DATABASE=Cytechinfo Inc. usb:v05EF* ID_VENDOR_FROM_DATABASE=AVB, Inc. [anko?] usb:v05EFp020A* ID_MODEL_FROM_DATABASE=Top Shot Pegasus Joystick usb:v05EFp8884* ID_MODEL_FROM_DATABASE=Mag Turbo Force Wheel usb:v05EFp8888* ID_MODEL_FROM_DATABASE=Top Shot Force Feedback Racing Wheel usb:v05F0* ID_VENDOR_FROM_DATABASE=Canopus Co., Ltd usb:v05F0p0101* ID_MODEL_FROM_DATABASE=DA-Port DAC usb:v05F1* ID_VENDOR_FROM_DATABASE=Compass Communications usb:v05F2* ID_VENDOR_FROM_DATABASE=Dexin Corp., Ltd usb:v05F2p0010* ID_MODEL_FROM_DATABASE=AQ Mouse usb:v05F3* ID_VENDOR_FROM_DATABASE=PI Engineering, Inc. usb:v05F3p0007* ID_MODEL_FROM_DATABASE=Kinesis Advantage PRO MPC/USB Keyboard usb:v05F3p0081* ID_MODEL_FROM_DATABASE=Kinesis Integrated Hub usb:v05F3p00FF* ID_MODEL_FROM_DATABASE=VEC Footpedal usb:v05F3p0203* ID_MODEL_FROM_DATABASE=Y-mouse Keyboard & Mouse Adapter usb:v05F3p020B* ID_MODEL_FROM_DATABASE=PS2 Adapter usb:v05F3p0232* ID_MODEL_FROM_DATABASE=X-Keys Switch Interface, Programming Mode usb:v05F3p0261* ID_MODEL_FROM_DATABASE=X-Keys Switch Interface, SPLAT Mode usb:v05F3p0264* ID_MODEL_FROM_DATABASE=X-Keys Switch Interface, Composite Mode usb:v05F5* ID_VENDOR_FROM_DATABASE=Unixtar Technology, Inc. usb:v05F6* ID_VENDOR_FROM_DATABASE=AOC International usb:v05F7* ID_VENDOR_FROM_DATABASE=RFC Distribution(s) PTE, Ltd usb:v05F9* ID_VENDOR_FROM_DATABASE=PSC Scanning, Inc. usb:v05F9p1104* ID_MODEL_FROM_DATABASE=Magellan 2200VS usb:v05F9p1206* ID_MODEL_FROM_DATABASE=Gryphon series (OEM mode) usb:v05F9p2202* ID_MODEL_FROM_DATABASE=Point of Sale Handheld Scanner usb:v05F9p2206* ID_MODEL_FROM_DATABASE=Gryphon series (keyboard emulation mode) usb:v05F9p220C* ID_MODEL_FROM_DATABASE=Datalogic Gryphon GD4430 usb:v05F9p2601* ID_MODEL_FROM_DATABASE=Datalogic Magellan 1000i Barcode Scanner usb:v05F9p2602* ID_MODEL_FROM_DATABASE=Datalogic Magellan 1100i Barcode Scanner usb:v05F9p4204* ID_MODEL_FROM_DATABASE=Gryphon series (RS-232 emulation mode) usb:v05F9p5204* ID_MODEL_FROM_DATABASE=Datalogic Gryphon GFS4170 (config mode) usb:v05FA* ID_VENDOR_FROM_DATABASE=Siemens Telecommunications Systems, Ltd usb:v05FAp3301* ID_MODEL_FROM_DATABASE=Keyboard with PS/2 Mouse Port usb:v05FAp3302* ID_MODEL_FROM_DATABASE=Keyboard usb:v05FAp3303* ID_MODEL_FROM_DATABASE=Keyboard with PS/2 Mouse Port usb:v05FC* ID_VENDOR_FROM_DATABASE=Harman usb:v05FCp0001* ID_MODEL_FROM_DATABASE=Soundcraft Si Multi Digital Card usb:v05FCp7849* ID_MODEL_FROM_DATABASE=Harman/Kardon SoundSticks usb:v05FD* ID_VENDOR_FROM_DATABASE=InterAct, Inc. usb:v05FDp0239* ID_MODEL_FROM_DATABASE=SV-239 HammerHead Digital usb:v05FDp0251* ID_MODEL_FROM_DATABASE=Raider Pro usb:v05FDp0253* ID_MODEL_FROM_DATABASE=ProPad 8 Digital usb:v05FDp0286* ID_MODEL_FROM_DATABASE=SV-286 Cyclone Digital usb:v05FDp107A* ID_MODEL_FROM_DATABASE=PowerPad Pro X-Box pad usb:v05FDp262A* ID_MODEL_FROM_DATABASE=3dfx HammerHead FX usb:v05FDp262F* ID_MODEL_FROM_DATABASE=HammerHead Fx usb:v05FDpDAAE* ID_MODEL_FROM_DATABASE=Game Shark usb:v05FE* ID_VENDOR_FROM_DATABASE=Chic Technology Corp. usb:v05FEp0001* ID_MODEL_FROM_DATABASE=Mouse usb:v05FEp0003* ID_MODEL_FROM_DATABASE=Cypress USB Mouse usb:v05FEp0005* ID_MODEL_FROM_DATABASE=Viewmaster 4D Browser Mouse usb:v05FEp0007* ID_MODEL_FROM_DATABASE=Twinhead Mouse usb:v05FEp0009* ID_MODEL_FROM_DATABASE=Inland Pro 4500/5000 Mouse usb:v05FEp0011* ID_MODEL_FROM_DATABASE=Browser Mouse usb:v05FEp0014* ID_MODEL_FROM_DATABASE=Gamepad usb:v05FEp1010* ID_MODEL_FROM_DATABASE=Optical Wireless usb:v05FEp2001* ID_MODEL_FROM_DATABASE=Microsoft Wireless Receiver 700 usb:v05FF* ID_VENDOR_FROM_DATABASE=LeCroy Corp. usb:v0600* ID_VENDOR_FROM_DATABASE=Barco Display Systems usb:v0601* ID_VENDOR_FROM_DATABASE=Jazz Hipster Corp. usb:v0601p0003* ID_MODEL_FROM_DATABASE=Internet Security Co., Ltd. SecureKey usb:v0602* ID_VENDOR_FROM_DATABASE=Vista Imaging, Inc. usb:v0602p1001* ID_MODEL_FROM_DATABASE=ViCam Webcam usb:v0603* ID_VENDOR_FROM_DATABASE=Novatek Microelectronics Corp. usb:v0603p00F1* ID_MODEL_FROM_DATABASE=Keyboard (Labtec Ultra Flat Keyboard) usb:v0603p00F2* ID_MODEL_FROM_DATABASE=Keyboard (Labtec Ultra Flat Keyboard) usb:v0603p6871* ID_MODEL_FROM_DATABASE=Mouse usb:v0604* ID_VENDOR_FROM_DATABASE=Jean Co., Ltd usb:v0605* ID_VENDOR_FROM_DATABASE=Anchor C&C Co., Ltd usb:v0606* ID_VENDOR_FROM_DATABASE=Royal Information Electronics Co., Ltd usb:v0607* ID_VENDOR_FROM_DATABASE=Bridge Information Co., Ltd usb:v0608* ID_VENDOR_FROM_DATABASE=Genrad Ads usb:v0609* ID_VENDOR_FROM_DATABASE=SMK Manufacturing, Inc. usb:v0609p031D* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v0609p0322* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v0609p0334* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v0609pFF12* ID_MODEL_FROM_DATABASE=SMK Bluetooth Device usb:v060A* ID_VENDOR_FROM_DATABASE=Worthington Data Solutions, Inc. usb:v060B* ID_VENDOR_FROM_DATABASE=Solid Year usb:v060Bp0001* ID_MODEL_FROM_DATABASE=MacAlly Keyboard usb:v060Bp0230* ID_MODEL_FROM_DATABASE=KSK-8003 UX Keyboard usb:v060Bp1006* ID_MODEL_FROM_DATABASE=Japanese Keyboard - 260U usb:v060Bp2101* ID_MODEL_FROM_DATABASE=Keyboard usb:v060Bp2231* ID_MODEL_FROM_DATABASE=KSK-6001 UELX Keyboard usb:v060Bp2270* ID_MODEL_FROM_DATABASE=Gigabyte K8100 Aivia Gaming Keyboard usb:v060Bp5253* ID_MODEL_FROM_DATABASE=Thermaltake MEKA G-Unit Gaming Keyboard usb:v060Bp5811* ID_MODEL_FROM_DATABASE=ACK-571U Wireless Keyboard usb:v060Bp5903* ID_MODEL_FROM_DATABASE=Japanese Keyboard - 595U usb:v060Bp6001* ID_MODEL_FROM_DATABASE=SolidTek USB 2p HUB usb:v060Bp6002* ID_MODEL_FROM_DATABASE=SolidTek USB Keyboard usb:v060Bp6003* ID_MODEL_FROM_DATABASE=Japanese Keyboard - 600HM usb:v060Bp6231* ID_MODEL_FROM_DATABASE=Thermaltake eSPORTS Meka Keyboard usb:v060Bp8007* ID_MODEL_FROM_DATABASE=P-W1G1F12 VER:1 [Macally MegaCam] usb:v060BpA001* ID_MODEL_FROM_DATABASE=Maxwell Compact Pc PM3 usb:v060C* ID_VENDOR_FROM_DATABASE=EEH Datalink GmbH usb:v060D* ID_VENDOR_FROM_DATABASE=Auctor Corp. usb:v060E* ID_VENDOR_FROM_DATABASE=Transmonde Technologies, Inc. usb:v060F* ID_VENDOR_FROM_DATABASE=Joinsoon Electronics Mfg. Co., Ltd usb:v0610* ID_VENDOR_FROM_DATABASE=Costar Electronics, Inc. usb:v0611* ID_VENDOR_FROM_DATABASE=Totoku Electric Co., Ltd usb:v0613* ID_VENDOR_FROM_DATABASE=TransAct Technologies, Inc. usb:v0614* ID_VENDOR_FROM_DATABASE=Bio-Rad Laboratories usb:v0615* ID_VENDOR_FROM_DATABASE=Quabbin Wire & Cable Co., Inc. usb:v0616* ID_VENDOR_FROM_DATABASE=Future Techno Designs PVT, Ltd usb:v0617* ID_VENDOR_FROM_DATABASE=Swiss Federal Insitute of Technology usb:v0618* ID_VENDOR_FROM_DATABASE=MacAlly usb:v0618p0101* ID_MODEL_FROM_DATABASE=Mouse usb:v0619* ID_VENDOR_FROM_DATABASE=Seiko Instruments, Inc. usb:v0619p0101* ID_MODEL_FROM_DATABASE=SLP-100 Driver usb:v0619p0102* ID_MODEL_FROM_DATABASE=SLP-200 Driver usb:v0619p0103* ID_MODEL_FROM_DATABASE=SLP-100N Driver usb:v0619p0104* ID_MODEL_FROM_DATABASE=SLP-200N Driver usb:v0619p0105* ID_MODEL_FROM_DATABASE=SLP-240 Driver usb:v0619p0501* ID_MODEL_FROM_DATABASE=SLP-440 Driver usb:v0619p0502* ID_MODEL_FROM_DATABASE=SLP-450 Driver usb:v061A* ID_VENDOR_FROM_DATABASE=Veridicom International, Inc. usb:v061Ap0110* ID_MODEL_FROM_DATABASE=5thSense Fingerprint Sensor usb:v061Ap0200* ID_MODEL_FROM_DATABASE=FPS200 Fingerprint Sensor usb:v061Ap8200* ID_MODEL_FROM_DATABASE=VKI-A Fingerprint Sensor/Flash Storage (dumb) usb:v061Ap9200* ID_MODEL_FROM_DATABASE=VKI-B Fingerprint Sensor/Flash Storage (smart) usb:v061B* ID_VENDOR_FROM_DATABASE=Promptus Communications, Inc. usb:v061C* ID_VENDOR_FROM_DATABASE=Act Labs, Ltd usb:v061D* ID_VENDOR_FROM_DATABASE=Quatech, Inc. usb:v061DpC020* ID_MODEL_FROM_DATABASE=SSU-100 usb:v061E* ID_VENDOR_FROM_DATABASE=Nissei Electric Co. usb:v061Ep0001* ID_MODEL_FROM_DATABASE=nissei 128DE-USB - usb:v061Ep0010* ID_MODEL_FROM_DATABASE=nissei 128DE-PNA - usb:v0620* ID_VENDOR_FROM_DATABASE=Alaris, Inc. usb:v0620p0004* ID_MODEL_FROM_DATABASE=QuickVideo weeCam usb:v0620p0007* ID_MODEL_FROM_DATABASE=QuickVideo weeCam usb:v0620p000A* ID_MODEL_FROM_DATABASE=QuickVideo weeCam usb:v0620p000B* ID_MODEL_FROM_DATABASE=QuickVideo weeCam usb:v0621* ID_VENDOR_FROM_DATABASE=ODU-Steckverbindungssysteme GmbH & Co. KG usb:v0622* ID_VENDOR_FROM_DATABASE=Iotech, Inc. usb:v0623* ID_VENDOR_FROM_DATABASE=Littelfuse, Inc. usb:v0624* ID_VENDOR_FROM_DATABASE=Avocent Corp. usb:v0624p0248* ID_MODEL_FROM_DATABASE=Virtual Hub usb:v0624p0249* ID_MODEL_FROM_DATABASE=Virtual Keyboard/Mouse usb:v0624p0251* ID_MODEL_FROM_DATABASE=Virtual Mass Storage usb:v0624p0294* ID_MODEL_FROM_DATABASE=Dell 03R874 KVM dongle usb:v0624p0402* ID_MODEL_FROM_DATABASE=Cisco Virtual Keyboard and Mouse usb:v0624p0403* ID_MODEL_FROM_DATABASE=Cisco Virtual Mass Storage usb:v0625* ID_VENDOR_FROM_DATABASE=TiMedia Technology Co., Ltd usb:v0626* ID_VENDOR_FROM_DATABASE=Nippon Systems Development Co., Ltd usb:v0627* ID_VENDOR_FROM_DATABASE=Adomax Technology Co., Ltd usb:v0628* ID_VENDOR_FROM_DATABASE=Tasking Software, Inc. usb:v0629* ID_VENDOR_FROM_DATABASE=Zida Technologies, Ltd usb:v062A* ID_VENDOR_FROM_DATABASE=Creative Labs usb:v062Ap0000* ID_MODEL_FROM_DATABASE=Optical mouse usb:v062Ap0001* ID_MODEL_FROM_DATABASE=Notebook Optical Mouse usb:v062Ap0102* ID_MODEL_FROM_DATABASE=Wireless Keyboard/Mouse Combo [MK1152WC] usb:v062Ap0201* ID_MODEL_FROM_DATABASE=Defender Office Keyboard (K7310) S Zodiak KM-9010 usb:v062Ap0252* ID_MODEL_FROM_DATABASE=Emerge Uni-retractable Laser Mouse usb:v062Ap3286* ID_MODEL_FROM_DATABASE=Nano Receiver [Sandstrom Laser Mouse SMWLL11] usb:v062Ap4101* ID_MODEL_FROM_DATABASE=Wireless Keyboard/Mouse usb:v062Ap6301* ID_MODEL_FROM_DATABASE=Trust Wireless Optical Mouse MI-4150K usb:v062Ap9003* ID_MODEL_FROM_DATABASE=VoIP Conference Hub (A16GH) usb:v062Ap9004* ID_MODEL_FROM_DATABASE=USR9602 USB Internet Mini Phone usb:v062B* ID_VENDOR_FROM_DATABASE=Greatlink Electronics Taiwan, Ltd usb:v062C* ID_VENDOR_FROM_DATABASE=Institute for Information Industry usb:v062D* ID_VENDOR_FROM_DATABASE=Taiwan Tai-Hao Enterprises Co., Ltd usb:v062E* ID_VENDOR_FROM_DATABASE=Mainsuper Enterprises Co., Ltd usb:v062F* ID_VENDOR_FROM_DATABASE=Sin Sheng Terminal & Machine, Inc. usb:v0631* ID_VENDOR_FROM_DATABASE=JUJO Electronics Corp. usb:v0633* ID_VENDOR_FROM_DATABASE=Cyrix Corp. usb:v0634* ID_VENDOR_FROM_DATABASE=Micron Technology, Inc. usb:v0634p0655* ID_MODEL_FROM_DATABASE=Embedded Mass Storage Drive [RealSSD] usb:v0635* ID_VENDOR_FROM_DATABASE=Methode Electronics, Inc. usb:v0636* ID_VENDOR_FROM_DATABASE=Sierra Imaging, Inc. usb:v0636p0003* ID_MODEL_FROM_DATABASE=Vivicam 35Xx usb:v0638* ID_VENDOR_FROM_DATABASE=Avision, Inc. usb:v0638p0268* ID_MODEL_FROM_DATABASE=iVina 1200U Scanner usb:v0638p026A* ID_MODEL_FROM_DATABASE=Minolta Dimage Scan Dual II AF-2820U (2886) usb:v0638p0A10* ID_MODEL_FROM_DATABASE=iVina FB1600/UMAX Astra 4500 usb:v0638p0A13* ID_MODEL_FROM_DATABASE=AV600U usb:v0638p0A15* ID_MODEL_FROM_DATABASE=Konica Minolta SC-110 usb:v0638p0A16* ID_MODEL_FROM_DATABASE=Konica Minolta SC-215 usb:v0638p0A30* ID_MODEL_FROM_DATABASE=UMAX Astra 6700 Scanner usb:v0638p0A41* ID_MODEL_FROM_DATABASE=Avision AM3000/MF3000 Series usb:v0638p0F01* ID_MODEL_FROM_DATABASE=fi-4010CU usb:v0638p4004* ID_MODEL_FROM_DATABASE=Minolta Dimage Scan Elite II AF-2920 (2888) usb:v0639* ID_VENDOR_FROM_DATABASE=Chrontel, Inc. usb:v063A* ID_VENDOR_FROM_DATABASE=Techwin Corp. usb:v063B* ID_VENDOR_FROM_DATABASE=Taugagreining HF usb:v063C* ID_VENDOR_FROM_DATABASE=Yamaichi Electronics Co., Ltd (Sakura) usb:v063D* ID_VENDOR_FROM_DATABASE=Fong Kai Industrial Co., Ltd usb:v063E* ID_VENDOR_FROM_DATABASE=RealMedia Technology, Inc. usb:v063F* ID_VENDOR_FROM_DATABASE=New Technology Cable, Ltd usb:v0640* ID_VENDOR_FROM_DATABASE=Hitex Development Tools usb:v0640p0026* ID_MODEL_FROM_DATABASE=LPC-Stick usb:v0641* ID_VENDOR_FROM_DATABASE=Woods Industries, Inc. usb:v0642* ID_VENDOR_FROM_DATABASE=VIA Medical Corp. usb:v0644* ID_VENDOR_FROM_DATABASE=TEAC Corp. usb:v0644p0000* ID_MODEL_FROM_DATABASE=Floppy usb:v0644p0200* ID_MODEL_FROM_DATABASE=All-In-One Multi-Card Reader CA200/B/S usb:v0644p1000* ID_MODEL_FROM_DATABASE=CD-ROM Drive usb:v0644p800D* ID_MODEL_FROM_DATABASE=TASCAM Portastudio DP-01FX usb:v0644p800E* ID_MODEL_FROM_DATABASE=TASCAM US-122L usb:v0644p801D* ID_MODEL_FROM_DATABASE=TASCAM DR-100 usb:v0644p8021* ID_MODEL_FROM_DATABASE=TASCAM US-122mkII usb:v0644pD001* ID_MODEL_FROM_DATABASE=CD-R/RW Unit usb:v0644pD002* ID_MODEL_FROM_DATABASE=CD-R/RW Unit usb:v0644pD010* ID_MODEL_FROM_DATABASE=CD-RW/DVD Unit usb:v0645* ID_VENDOR_FROM_DATABASE=Who? Vision Systems, Inc. usb:v0646* ID_VENDOR_FROM_DATABASE=UMAX usb:v0647* ID_VENDOR_FROM_DATABASE=Acton Research Corp. usb:v0647p0100* ID_MODEL_FROM_DATABASE=ARC SpectraPro UV/VIS/IR Monochromator/Spectrograph usb:v0647p0101* ID_MODEL_FROM_DATABASE=ARC AM-VM Mono Airpath/Vacuum Monochromator/Spectrograph usb:v0647p0102* ID_MODEL_FROM_DATABASE=ARC Inspectrum Mono usb:v0647p0103* ID_MODEL_FROM_DATABASE=ARC Filterwheel usb:v0647p03E9* ID_MODEL_FROM_DATABASE=Inspectrum 128x1024 F VIS Spectrograph usb:v0647p03EA* ID_MODEL_FROM_DATABASE=Inspectrum 256x1024 F VIS Spectrograph usb:v0647p03EB* ID_MODEL_FROM_DATABASE=Inspectrum 128x1024 B VIS Spectrograph usb:v0647p03EC* ID_MODEL_FROM_DATABASE=Inspectrum 256x1024 B VIS Spectrograph usb:v0648* ID_VENDOR_FROM_DATABASE=Inside Out Networks usb:v0649* ID_VENDOR_FROM_DATABASE=Weli Science Co., Ltd usb:v064B* ID_VENDOR_FROM_DATABASE=Analog Devices, Inc. (White Mountain DSP) usb:v064Bp0165* ID_MODEL_FROM_DATABASE=Blackfin 535 [ADZS HPUSB ICE] usb:v064C* ID_VENDOR_FROM_DATABASE=Ji-Haw Industrial Co., Ltd usb:v064D* ID_VENDOR_FROM_DATABASE=TriTech Microelectronics, Ltd usb:v064E* ID_VENDOR_FROM_DATABASE=Suyin Corp. usb:v064Ep2100* ID_MODEL_FROM_DATABASE=Sony Visual Communication Camera usb:v064Ep9700* ID_MODEL_FROM_DATABASE=Asus Integrated Webcam usb:v064EpA100* ID_MODEL_FROM_DATABASE=Acer OrbiCam usb:v064EpA101* ID_MODEL_FROM_DATABASE=Acer CrystalEye Webcam usb:v064EpA102* ID_MODEL_FROM_DATABASE=Acer/Lenovo Webcam [CN0316] usb:v064EpA103* ID_MODEL_FROM_DATABASE=Acer/HP Integrated Webcam [CN0314] usb:v064EpA110* ID_MODEL_FROM_DATABASE=HP Webcam usb:v064EpA114* ID_MODEL_FROM_DATABASE=Lemote Webcam usb:v064EpA116* ID_MODEL_FROM_DATABASE=UVC 1.3MPixel WebCam usb:v064EpA136* ID_MODEL_FROM_DATABASE=Asus Integrated Webcam [CN031B] usb:v064EpA219* ID_MODEL_FROM_DATABASE=1.3M WebCam (notebook emachines E730, Acer sub-brand) usb:v064EpC107* ID_MODEL_FROM_DATABASE=HP webcam [dv6-1190en] usb:v064EpC335* ID_MODEL_FROM_DATABASE=HP TrueVision HD usb:v064EpD101* ID_MODEL_FROM_DATABASE=Acer CrystalEye Webcam usb:v064EpD217* ID_MODEL_FROM_DATABASE=HP TrueVision HD usb:v064EpE201* ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam usb:v064EpE203* ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam usb:v064EpE258* ID_MODEL_FROM_DATABASE=HP TrueVision HD Integrated Webcam usb:v064EpF102* ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam [R5U877] usb:v064EpF103* ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam [R5U877] usb:v064EpF300* ID_MODEL_FROM_DATABASE=UVC 0.3M Webcam usb:v064F* ID_VENDOR_FROM_DATABASE=WIBU-Systems AG usb:v064Fp03E9* ID_MODEL_FROM_DATABASE=CmStick (article no. 1001) usb:v064Fp03F2* ID_MODEL_FROM_DATABASE=CmStick/M (article no. 1010) usb:v064Fp03F3* ID_MODEL_FROM_DATABASE=CmStick/M (article no. 1011) usb:v064Fp0BD7* ID_MODEL_FROM_DATABASE=BOX/U usb:v064Fp0BD8* ID_MODEL_FROM_DATABASE=BOX/RU usb:v0650* ID_VENDOR_FROM_DATABASE=Dynapro Systems usb:v0651* ID_VENDOR_FROM_DATABASE=Likom Technology Sdn. Bhd. usb:v0652* ID_VENDOR_FROM_DATABASE=Stargate Solutions, Inc. usb:v0653* ID_VENDOR_FROM_DATABASE=CNF, Inc. usb:v0654* ID_VENDOR_FROM_DATABASE=Granite Microsystems, Inc. usb:v0654p0005* ID_MODEL_FROM_DATABASE=Device Bay Controller usb:v0654p0006* ID_MODEL_FROM_DATABASE=Hub usb:v0654p0007* ID_MODEL_FROM_DATABASE=Device Bay Controller usb:v0654p0016* ID_MODEL_FROM_DATABASE=Hub usb:v0655* ID_VENDOR_FROM_DATABASE=Space Shuttle Hi-Tech Co., Ltd usb:v0656* ID_VENDOR_FROM_DATABASE=Glory Mark Electronic, Ltd usb:v0657* ID_VENDOR_FROM_DATABASE=Tekcon Electronics Corp. usb:v0658* ID_VENDOR_FROM_DATABASE=Sigma Designs, Inc. usb:v0659* ID_VENDOR_FROM_DATABASE=Aethra usb:v065A* ID_VENDOR_FROM_DATABASE=Optoelectronics Co., Ltd usb:v065Ap0001* ID_MODEL_FROM_DATABASE=Opticon OPR-2001 / NLV-1001 (keyboard mode) usb:v065Ap0009* ID_MODEL_FROM_DATABASE=NLV-1001 (serial mode) / OPN-2001 [Opticon] usb:v065B* ID_VENDOR_FROM_DATABASE=Tracewell Systems usb:v065E* ID_VENDOR_FROM_DATABASE=Silicon Graphics usb:v065F* ID_VENDOR_FROM_DATABASE=Good Way Technology Co., Ltd & GWC technology Inc. usb:v0660* ID_VENDOR_FROM_DATABASE=TSAY-E (BVI) International, Inc. usb:v0661* ID_VENDOR_FROM_DATABASE=Hamamatsu Photonics K.K. usb:v0662* ID_VENDOR_FROM_DATABASE=Kansai Electric Co., Ltd usb:v0663* ID_VENDOR_FROM_DATABASE=Topmax Electronic Co., Ltd usb:v0663p0103* ID_MODEL_FROM_DATABASE=CobraPad usb:v0664* ID_VENDOR_FROM_DATABASE=ET&T Technology Co., Ltd. usb:v0664p0301* ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen usb:v0664p0302* ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen usb:v0664p0303* ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen usb:v0664p0304* ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen usb:v0664p0305* ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen usb:v0664p0306* ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen usb:v0664p0307* ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen usb:v0664p0309* ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen usb:v0665* ID_VENDOR_FROM_DATABASE=Cypress Semiconductor usb:v0665p5161* ID_MODEL_FROM_DATABASE=USB to Serial usb:v0667* ID_VENDOR_FROM_DATABASE=Aiwa Co., Ltd usb:v0667p0FA1* ID_MODEL_FROM_DATABASE=TD-U8000 Tape Drive usb:v0668* ID_VENDOR_FROM_DATABASE=WordWand usb:v0669* ID_VENDOR_FROM_DATABASE=Oce' Printing Systems GmbH usb:v066A* ID_VENDOR_FROM_DATABASE=Total Technologies, Ltd usb:v066B* ID_VENDOR_FROM_DATABASE=Linksys, Inc. usb:v066Bp0105* ID_MODEL_FROM_DATABASE=SCM eUSB SmartMedia Card Reader usb:v066Bp010A* ID_MODEL_FROM_DATABASE=Melco MCR-U2 SmartMedia / CompactFlash Reader usb:v066Bp200C* ID_MODEL_FROM_DATABASE=USB10TX usb:v066Bp2202* ID_MODEL_FROM_DATABASE=USB10TX Ethernet [pegasus] usb:v066Bp2203* ID_MODEL_FROM_DATABASE=USB100TX Ethernet [pegasus] usb:v066Bp2204* ID_MODEL_FROM_DATABASE=USB100TX HomePNA Ethernet [pegasus] usb:v066Bp2206* ID_MODEL_FROM_DATABASE=USB Ethernet [pegasus] usb:v066Bp2207* ID_MODEL_FROM_DATABASE=HomeLink Phoneline 10M Network Adapter usb:v066Bp2211* ID_MODEL_FROM_DATABASE=WUSB11 802.11b Adapter usb:v066Bp2212* ID_MODEL_FROM_DATABASE=WUSB11v2.5 802.11b Adapter usb:v066Bp2213* ID_MODEL_FROM_DATABASE=WUSB12v1.1 802.11b Adapter usb:v066Bp2219* ID_MODEL_FROM_DATABASE=Instant Wireless Network Adapter usb:v066Bp400B* ID_MODEL_FROM_DATABASE=USB10TX usb:v066D* ID_VENDOR_FROM_DATABASE=Entrega, Inc. usb:v066E* ID_VENDOR_FROM_DATABASE=Acer Semiconductor America, Inc. usb:v066F* ID_VENDOR_FROM_DATABASE=SigmaTel, Inc. usb:v066Fp003B* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp003E* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp003F* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp0040* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp0041* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp0042* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp0043* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp004B* ID_MODEL_FROM_DATABASE=A-Max PA11 MP3 Player usb:v066Fp3400* ID_MODEL_FROM_DATABASE=STMP3400 D-Major MP3 Player usb:v066Fp3410* ID_MODEL_FROM_DATABASE=STMP3410 D-Major MP3 Player usb:v066Fp3500* ID_MODEL_FROM_DATABASE=Player Recovery Device usb:v066Fp3780* ID_MODEL_FROM_DATABASE=STMP3780/i.MX23 SystemOnChip in RecoveryMode usb:v066Fp4200* ID_MODEL_FROM_DATABASE=STIr4200 IrDA Bridge usb:v066Fp4210* ID_MODEL_FROM_DATABASE=STIr4210 IrDA Bridge usb:v066Fp8000* ID_MODEL_FROM_DATABASE=MSCN MP3 Player usb:v066Fp8001* ID_MODEL_FROM_DATABASE=SigmaTel MSCN Audio Player usb:v066Fp8004* ID_MODEL_FROM_DATABASE=MSCNMMC MP3 Player usb:v066Fp8008* ID_MODEL_FROM_DATABASE=i-Bead 100 MP3 Player usb:v066Fp8020* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8034* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8036* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8038* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8056* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8060* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8066* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp807E* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8092* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8096* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp809A* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp80AA* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp80AC* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp80B8* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp80BA* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp80BC* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp80BF* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp80C5* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp80C8* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp80CA* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp80CC* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8104* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8106* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8108* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp810A* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp810C* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8122* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8124* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8126* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8128* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8134* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8136* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8138* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp813A* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp813E* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8140* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8142* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8144* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8146* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8148* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp814C* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8201* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8202* ID_MODEL_FROM_DATABASE=Jens of Sweden / I-BEAD 150M/150H MP3 player usb:v066Fp8203* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8204* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8205* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8206* ID_MODEL_FROM_DATABASE=Digital MP3 Music Player usb:v066Fp8207* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8208* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8209* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp820A* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp820B* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp820C* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp820D* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp820E* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp820F* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8210* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8211* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8212* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8213* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8214* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8215* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8216* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8217* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8218* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8219* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp821A* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp821B* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp821C* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp821D* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp821E* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp821F* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8220* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8221* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8222* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8223* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8224* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8225* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8226* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8227* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8228* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8229* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8230* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp829C* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp82E0* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp8320* ID_MODEL_FROM_DATABASE=TrekStor i.Beat fun usb:v066Fp835D* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp9000* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp9001* ID_MODEL_FROM_DATABASE=MP3 Player usb:v066Fp9002* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0670* ID_VENDOR_FROM_DATABASE=Sequel Imaging usb:v0670p0001* ID_MODEL_FROM_DATABASE=Calibrator usb:v0670p0005* ID_MODEL_FROM_DATABASE=Enable Cable usb:v0672* ID_VENDOR_FROM_DATABASE=Labtec, Inc. usb:v0672p1041* ID_MODEL_FROM_DATABASE=LCS1040 Speaker System usb:v0672p5000* ID_MODEL_FROM_DATABASE=SpaceBall 4000 FLX usb:v0673* ID_VENDOR_FROM_DATABASE=HCL usb:v0673p5000* ID_MODEL_FROM_DATABASE=Keyboard usb:v0674* ID_VENDOR_FROM_DATABASE=Key Mouse Electronic Enterprise Co., Ltd usb:v0675* ID_VENDOR_FROM_DATABASE=DrayTek Corp. usb:v0675p0110* ID_MODEL_FROM_DATABASE=Vigor 128 ISDN TA usb:v0675p0530* ID_MODEL_FROM_DATABASE=Vigor530 IEEE 802.11G Adapter (ISL3880+NET2280) usb:v0675p0550* ID_MODEL_FROM_DATABASE=Vigor550 usb:v0675p1688* ID_MODEL_FROM_DATABASE=miniVigor 128 ISDN TA [HFC-S] usb:v0675p6694* ID_MODEL_FROM_DATABASE=miniVigor 128 ISDN TA usb:v0676* ID_VENDOR_FROM_DATABASE=Teles AG usb:v0677* ID_VENDOR_FROM_DATABASE=Aiwa Co., Ltd usb:v0677p07D5* ID_MODEL_FROM_DATABASE=TM-ED1285(USB) usb:v0677p0FA1* ID_MODEL_FROM_DATABASE=TD-U8000 Tape Drive usb:v0678* ID_VENDOR_FROM_DATABASE=ACard Technology Corp. usb:v067B* ID_VENDOR_FROM_DATABASE=Prolific Technology, Inc. usb:v067Bp0000* ID_MODEL_FROM_DATABASE=PL2301 USB-USB Bridge usb:v067Bp0001* ID_MODEL_FROM_DATABASE=PL2302 USB-USB Bridge usb:v067Bp0307* ID_MODEL_FROM_DATABASE=Motorola Serial Adapter usb:v067Bp04BB* ID_MODEL_FROM_DATABASE=PL2303 Serial (IODATA USB-RSAQ2) usb:v067Bp0600* ID_MODEL_FROM_DATABASE=IDE Bridge usb:v067Bp0610* ID_MODEL_FROM_DATABASE=Onext EG210U MODEM usb:v067Bp0611* ID_MODEL_FROM_DATABASE=AlDiga AL-11U Quad-band GSM/GPRS/EDGE modem usb:v067Bp2303* ID_MODEL_FROM_DATABASE=PL2303 Serial Port usb:v067Bp2305* ID_MODEL_FROM_DATABASE=PL2305 Parallel Port usb:v067Bp2306* ID_MODEL_FROM_DATABASE=Raylink Bridge Controller usb:v067Bp2307* ID_MODEL_FROM_DATABASE=PL2307 USB-ATAPI4 Bridge usb:v067Bp2313* ID_MODEL_FROM_DATABASE=FITEL PHS U Cable Adaptor usb:v067Bp2315* ID_MODEL_FROM_DATABASE=Flash Disk Embedded Hub usb:v067Bp2316* ID_MODEL_FROM_DATABASE=Flash Disk Security Device usb:v067Bp2317* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v067Bp2501* ID_MODEL_FROM_DATABASE=PL2501 USB-USB Bridge (USB 2.0) usb:v067Bp2506* ID_MODEL_FROM_DATABASE=Kaser 8gB micro hard drive usb:v067Bp2507* ID_MODEL_FROM_DATABASE=PL2507 Hi-speed USB to IDE bridge controller usb:v067Bp2515* ID_MODEL_FROM_DATABASE=Flash Disk Embedded Hub usb:v067Bp2517* ID_MODEL_FROM_DATABASE=Flash Disk Mass Storage Device usb:v067Bp2528* ID_MODEL_FROM_DATABASE=Storage device (8gB thumb drive) usb:v067Bp25A1* ID_MODEL_FROM_DATABASE=PL25A1 Host-Host Bridge usb:v067Bp2773* ID_MODEL_FROM_DATABASE=PL2773 SATAII bridge controller usb:v067Bp3400* ID_MODEL_FROM_DATABASE=Hi-Speed Flash Disk with TruePrint AES3400 usb:v067Bp3500* ID_MODEL_FROM_DATABASE=Hi-Speed Flash Disk with TruePrint AES3500 usb:v067Bp3507* ID_MODEL_FROM_DATABASE=PL3507 ATAPI6 Bridge usb:v067BpAAA0* ID_MODEL_FROM_DATABASE=Prolific Pharos usb:v067BpAAA2* ID_MODEL_FROM_DATABASE=PL2303 Serial Adapter (IODATA USB-RSAQ3) usb:v067C* ID_VENDOR_FROM_DATABASE=Efficient Networks, Inc. usb:v067Cp1001* ID_MODEL_FROM_DATABASE=Siemens SpeedStream 100MBps Ethernet usb:v067Cp1022* ID_MODEL_FROM_DATABASE=Siemens SpeedStream 1022 802.11b Adapter usb:v067Cp1023* ID_MODEL_FROM_DATABASE=SpeedStream Wireless usb:v067Cp4020* ID_MODEL_FROM_DATABASE=SpeedStream 4020 ATM/ADSL Installer usb:v067Cp4031* ID_MODEL_FROM_DATABASE=Efficient ADSL Modem usb:v067Cp4032* ID_MODEL_FROM_DATABASE=SpeedStream 4031 ATM/ADSL Installer usb:v067Cp4033* ID_MODEL_FROM_DATABASE=SpeedStream 4031 ATM/ADSL Installer usb:v067Cp4060* ID_MODEL_FROM_DATABASE=Alcatel Speedstream 4060 ADSL Modem usb:v067Cp4062* ID_MODEL_FROM_DATABASE=Efficient Networks 4060 Loader usb:v067Cp5667* ID_MODEL_FROM_DATABASE=Efficient Networks Virtual Bus for ADSL Modem usb:v067CpC031* ID_MODEL_FROM_DATABASE=SpeedStream 4031 ATM/ADSL Installer usb:v067CpC032* ID_MODEL_FROM_DATABASE=SpeedStream 4031 ATM/ADSL Installer usb:v067CpC033* ID_MODEL_FROM_DATABASE=SpeedStream 4031 ATM/ADSL Installer usb:v067CpC060* ID_MODEL_FROM_DATABASE=SpeedStream 4060 Miniport ATM/ADSL Adapter usb:v067CpD667* ID_MODEL_FROM_DATABASE=Efficient Networks Virtual Bus for ADSL Modem usb:v067CpE240* ID_MODEL_FROM_DATABASE=Speedstream Ethernet Adapter E240 usb:v067CpE540* ID_MODEL_FROM_DATABASE=Speedstream Ethernet Adapter E240 usb:v067D* ID_VENDOR_FROM_DATABASE=Hohner Corp. usb:v067E* ID_VENDOR_FROM_DATABASE=Intermec Technologies Corp. usb:v067Ep0801* ID_MODEL_FROM_DATABASE=HID Keyboard, Barcode scanner usb:v067Ep0803* ID_MODEL_FROM_DATABASE=VCP, Barcode scanner usb:v067Ep0805* ID_MODEL_FROM_DATABASE=VCP + UVC, Barcode scanner usb:v067Ep1001* ID_MODEL_FROM_DATABASE=Mobile Computer usb:v067F* ID_VENDOR_FROM_DATABASE=Virata, Ltd usb:v067Fp4552* ID_MODEL_FROM_DATABASE=DSL-200 ADSL Modem usb:v067Fp6542* ID_MODEL_FROM_DATABASE=DSL Modem usb:v067Fp6549* ID_MODEL_FROM_DATABASE=DSL Modem usb:v067Fp7541* ID_MODEL_FROM_DATABASE=DSL Modem usb:v0680* ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Corp., CPP Div. (Avance Logic) usb:v0680p0002* ID_MODEL_FROM_DATABASE=Arowana Optical Wheel Mouse MSOP-01 usb:v0681* ID_VENDOR_FROM_DATABASE=Siemens Information and Communication Products usb:v0681p0001* ID_MODEL_FROM_DATABASE=Dect Base usb:v0681p0002* ID_MODEL_FROM_DATABASE=Gigaset 3075 Passive ISDN usb:v0681p0005* ID_MODEL_FROM_DATABASE=ID-Mouse with Fingerprint Reader usb:v0681p0012* ID_MODEL_FROM_DATABASE=I-Gate 802.11b Adapter usb:v0681p001B* ID_MODEL_FROM_DATABASE=WLL013 usb:v0681p001D* ID_MODEL_FROM_DATABASE=Hipath 1000 usb:v0681p0022* ID_MODEL_FROM_DATABASE=Gigaset SX353 ISDN usb:v0681p0026* ID_MODEL_FROM_DATABASE=DECT Data - Gigaset M34 usb:v0681p002B* ID_MODEL_FROM_DATABASE=A-100-I ADSL Modem usb:v0681p002E* ID_MODEL_FROM_DATABASE=ADSL Router_S-141 usb:v0681p0034* ID_MODEL_FROM_DATABASE=GSM module MC35/ES75 USB Modem usb:v0681p3C06* ID_MODEL_FROM_DATABASE=54g USB Network Adapter usb:v0682* ID_VENDOR_FROM_DATABASE=Victor Company of Japan, Ltd usb:v0684* ID_VENDOR_FROM_DATABASE=Actiontec Electronics, Inc. usb:v0685* ID_VENDOR_FROM_DATABASE=ZD Incorporated usb:v0685p7000* ID_MODEL_FROM_DATABASE=HSDPA Modem usb:v0686* ID_VENDOR_FROM_DATABASE=Minolta Co., Ltd usb:v0686p2001* ID_MODEL_FROM_DATABASE=PagePro 4110W usb:v0686p2004* ID_MODEL_FROM_DATABASE=PagePro 1200W usb:v0686p2005* ID_MODEL_FROM_DATABASE=Magicolor 2300 DL usb:v0686p3001* ID_MODEL_FROM_DATABASE=PagePro 4100 usb:v0686p3005* ID_MODEL_FROM_DATABASE=PagePro 1250E usb:v0686p3006* ID_MODEL_FROM_DATABASE=PagePro 1250W usb:v0686p3009* ID_MODEL_FROM_DATABASE=Magicolor 2300W usb:v0686p300B* ID_MODEL_FROM_DATABASE=PagePro 1350W usb:v0686p300C* ID_MODEL_FROM_DATABASE=PagePro 1300W usb:v0686p302E* ID_MODEL_FROM_DATABASE=Develop D 1650iD PCL usb:v0686p3034* ID_MODEL_FROM_DATABASE=Develop D 2050iD PCL usb:v0686p4001* ID_MODEL_FROM_DATABASE=Dimage 2300 usb:v0686p4003* ID_MODEL_FROM_DATABASE=Dimage 2330 Zoom Camera usb:v0686p4004* ID_MODEL_FROM_DATABASE=Dimage Scan Elite II AF-2920 (2888) usb:v0686p4005* ID_MODEL_FROM_DATABASE=Minolta DiMAGE E201 Mass Storage Device usb:v0686p4006* ID_MODEL_FROM_DATABASE=Dimage 7 Camera usb:v0686p4007* ID_MODEL_FROM_DATABASE=Dimage S304 Camera usb:v0686p4008* ID_MODEL_FROM_DATABASE=Dimage 5 Camera usb:v0686p4009* ID_MODEL_FROM_DATABASE=Dimage X Camera usb:v0686p400A* ID_MODEL_FROM_DATABASE=Dimage S404 Camera usb:v0686p400B* ID_MODEL_FROM_DATABASE=Dimage 7i Camera usb:v0686p400C* ID_MODEL_FROM_DATABASE=Dimage F100 Camera usb:v0686p400D* ID_MODEL_FROM_DATABASE=Dimage Scan Dual III AF-2840 (2889) usb:v0686p400E* ID_MODEL_FROM_DATABASE=Dimage Scan Elite 5400 (2890) usb:v0686p400F* ID_MODEL_FROM_DATABASE=Dimage 7Hi Camera usb:v0686p4010* ID_MODEL_FROM_DATABASE=Dimage Xi Camera usb:v0686p4011* ID_MODEL_FROM_DATABASE=Dimage F300 Camera usb:v0686p4012* ID_MODEL_FROM_DATABASE=Dimage F200 Camera usb:v0686p4014* ID_MODEL_FROM_DATABASE=Dimage S414 Camera usb:v0686p4015* ID_MODEL_FROM_DATABASE=Dimage XT Camera [storage] usb:v0686p4016* ID_MODEL_FROM_DATABASE=Dimage XT Camera [remote mode] usb:v0686p4017* ID_MODEL_FROM_DATABASE=Dimage E223 usb:v0686p4018* ID_MODEL_FROM_DATABASE=Dimage Z1 Camera usb:v0686p4019* ID_MODEL_FROM_DATABASE=Dimage A1 Camera [remote mode] usb:v0686p401A* ID_MODEL_FROM_DATABASE=Dimage A1 Camera [storage] usb:v0686p401C* ID_MODEL_FROM_DATABASE=Dimage X20 Camera usb:v0686p401E* ID_MODEL_FROM_DATABASE=Dimage E323 Camera usb:v068A* ID_VENDOR_FROM_DATABASE=Pertech, Inc. usb:v068B* ID_VENDOR_FROM_DATABASE=Potrans International, Inc. usb:v068E* ID_VENDOR_FROM_DATABASE=CH Products, Inc. usb:v068Ep00D3* ID_MODEL_FROM_DATABASE=OEM 3 axis 5 button joystick usb:v068Ep00E2* ID_MODEL_FROM_DATABASE=HFX OEM Joystick usb:v068Ep00F0* ID_MODEL_FROM_DATABASE=Multi-Function Panel usb:v068Ep00F1* ID_MODEL_FROM_DATABASE=Pro Throttle usb:v068Ep00F2* ID_MODEL_FROM_DATABASE=Flight Sim Pedals usb:v068Ep00F3* ID_MODEL_FROM_DATABASE=Fighterstick usb:v068Ep00F4* ID_MODEL_FROM_DATABASE=Combatstick usb:v068Ep00FA* ID_MODEL_FROM_DATABASE=Ch Throttle Quadrant usb:v068Ep00FF* ID_MODEL_FROM_DATABASE=Flight Sim Yoke usb:v068Ep0500* ID_MODEL_FROM_DATABASE=GameStick 3D usb:v068Ep0501* ID_MODEL_FROM_DATABASE=CH Pro Pedals usb:v068Ep0504* ID_MODEL_FROM_DATABASE=F-16 Combat Stick usb:v0690* ID_VENDOR_FROM_DATABASE=Golden Bridge Electech, Inc. usb:v0693* ID_VENDOR_FROM_DATABASE=Hagiwara Sys-Com Co., Ltd usb:v0693p0002* ID_MODEL_FROM_DATABASE=FlashGate SmartMedia Card Reader usb:v0693p0003* ID_MODEL_FROM_DATABASE=FlashGate CompactFlash Card Reader usb:v0693p0005* ID_MODEL_FROM_DATABASE=FlashGate usb:v0693p0006* ID_MODEL_FROM_DATABASE=SM PCCard R/W and SPD usb:v0693p0007* ID_MODEL_FROM_DATABASE=FlashGate ME (Authenticated) usb:v0693p000A* ID_MODEL_FROM_DATABASE=SDCard/MMC Reader/Writer usb:v0694* ID_VENDOR_FROM_DATABASE=Lego Group usb:v0694p0001* ID_MODEL_FROM_DATABASE=Mindstorms Tower usb:v0694p0002* ID_MODEL_FROM_DATABASE=Mindstorms NXT usb:v0698* ID_VENDOR_FROM_DATABASE=Chuntex (CTX) usb:v0698p1786* ID_MODEL_FROM_DATABASE=1300ex Monitor usb:v0698p2003* ID_MODEL_FROM_DATABASE=CTX M730V built in Camera usb:v0698p9999* ID_MODEL_FROM_DATABASE=VLxxxx Monitor+Hub usb:v0699* ID_VENDOR_FROM_DATABASE=Tektronix, Inc. usb:v0699p0347* ID_MODEL_FROM_DATABASE=AFG 3022B usb:v069A* ID_VENDOR_FROM_DATABASE=Askey Computer Corp. usb:v069Ap0001* ID_MODEL_FROM_DATABASE=VC010 Webcam [pwc] usb:v069Ap0303* ID_MODEL_FROM_DATABASE=Cable Modem usb:v069Ap0311* ID_MODEL_FROM_DATABASE=ADSL Router Remote NDIS Device usb:v069Ap0318* ID_MODEL_FROM_DATABASE=Remote NDIS Device usb:v069Ap0319* ID_MODEL_FROM_DATABASE=220V Remote NDIS Device usb:v069Ap0320* ID_MODEL_FROM_DATABASE=IEEE 802.11b Wireless LAN Card usb:v069Ap0321* ID_MODEL_FROM_DATABASE=Dynalink WLL013 / Compex WLU11A 802.11b Adapter usb:v069Ap0402* ID_MODEL_FROM_DATABASE=Scientific Atlanta WebSTAR 100 & 200 series Cable Modem usb:v069Ap0811* ID_MODEL_FROM_DATABASE=BT Virtual Bus for Helium usb:v069Ap0821* ID_MODEL_FROM_DATABASE=BT Voyager 1010 802.11b Adapter usb:v069Ap4402* ID_MODEL_FROM_DATABASE=Scientific Atlanta WebSTAR 2000 series Cable Modem usb:v069Ap4403* ID_MODEL_FROM_DATABASE=Scientific Atlanta WebSTAR 300 series Cable Modem usb:v069Ap4501* ID_MODEL_FROM_DATABASE=Scientific-Atlanta WebSTAR 2000 series Cable Modem usb:v069B* ID_VENDOR_FROM_DATABASE=Thomson, Inc. usb:v069Bp0704* ID_MODEL_FROM_DATABASE=DCM245 Cable Modem usb:v069Bp0705* ID_MODEL_FROM_DATABASE=THG540K Cable Modem usb:v069Bp0709* ID_MODEL_FROM_DATABASE=Lyra PDP2424 usb:v069Bp070C* ID_MODEL_FROM_DATABASE=MP3 Player usb:v069Bp070D* ID_MODEL_FROM_DATABASE=MP3 Player usb:v069Bp070E* ID_MODEL_FROM_DATABASE=MP3 Player usb:v069Bp070F* ID_MODEL_FROM_DATABASE=RCA Lyra RD1071 MP3 Player usb:v069Bp0731* ID_MODEL_FROM_DATABASE=Lyra M200E256 usb:v069Bp0761* ID_MODEL_FROM_DATABASE=RCA H100A usb:v069Bp0778* ID_MODEL_FROM_DATABASE=PEARL USB Device usb:v069Bp2220* ID_MODEL_FROM_DATABASE=RCA Kazoo RD1000 MP3 Player usb:v069Bp300A* ID_MODEL_FROM_DATABASE=RCA Lyra MP3 Player usb:v069Bp3012* ID_MODEL_FROM_DATABASE=MP3 Player usb:v069Bp3013* ID_MODEL_FROM_DATABASE=MP3 Player usb:v069Bp5557* ID_MODEL_FROM_DATABASE=RCA CDS6300 usb:v069D* ID_VENDOR_FROM_DATABASE=Hughes Network Systems (HNS) usb:v069Dp0001* ID_MODEL_FROM_DATABASE=Satellite Receiver Device usb:v069Dp0002* ID_MODEL_FROM_DATABASE=Satellite Device usb:v069E* ID_VENDOR_FROM_DATABASE=Welcat Inc. usb:v069Ep0005* ID_MODEL_FROM_DATABASE=Marx CryptoBox v1.2 usb:v069F* ID_VENDOR_FROM_DATABASE=Allied Data Technologies BV usb:v069Fp0010* ID_MODEL_FROM_DATABASE=Tornado Speakerphone FaxModem 56.0 usb:v069Fp0011* ID_MODEL_FROM_DATABASE=Tornado Speakerphone FaxModem 56.0 usb:v069Fp1000* ID_MODEL_FROM_DATABASE=ADT VvBus for CopperJet usb:v069Fp1004* ID_MODEL_FROM_DATABASE=CopperJet 821 RouterPlus usb:v06A2* ID_VENDOR_FROM_DATABASE=Topro Technology, Inc. usb:v06A2p0033* ID_MODEL_FROM_DATABASE=USB Mouse usb:v06A3* ID_VENDOR_FROM_DATABASE=Saitek PLC usb:v06A3p0006* ID_MODEL_FROM_DATABASE=Cyborg Gold Joystick usb:v06A3p0109* ID_MODEL_FROM_DATABASE=P880 Pad usb:v06A3p0160* ID_MODEL_FROM_DATABASE=ST290 Pro usb:v06A3p0200* ID_MODEL_FROM_DATABASE=Xbox Adrenalin Hub usb:v06A3p0241* ID_MODEL_FROM_DATABASE=Xbox Adrenalin Gamepad usb:v06A3p0255* ID_MODEL_FROM_DATABASE=X52 Flight Controller usb:v06A3p040B* ID_MODEL_FROM_DATABASE=P990 Dual Analog Pad usb:v06A3p040C* ID_MODEL_FROM_DATABASE=P2900 Wireless Pad usb:v06A3p0422* ID_MODEL_FROM_DATABASE=ST90 Joystick usb:v06A3p0460* ID_MODEL_FROM_DATABASE=ST290 Pro Flight Stick usb:v06A3p0463* ID_MODEL_FROM_DATABASE=ST290 usb:v06A3p0464* ID_MODEL_FROM_DATABASE=Cyborg Evo usb:v06A3p0471* ID_MODEL_FROM_DATABASE=Cyborg Graphite Stick usb:v06A3p0501* ID_MODEL_FROM_DATABASE=R100 Sports Wheel usb:v06A3p0502* ID_MODEL_FROM_DATABASE=ST200 Stick usb:v06A3p0506* ID_MODEL_FROM_DATABASE=R220 Digital Wheel usb:v06A3p051E* ID_MODEL_FROM_DATABASE=Cyborg Digital II Stick usb:v06A3p052D* ID_MODEL_FROM_DATABASE=P750 Gamepad usb:v06A3p053C* ID_MODEL_FROM_DATABASE=X45 Flight Controller usb:v06A3p053F* ID_MODEL_FROM_DATABASE=X36F Flightstick usb:v06A3p056C* ID_MODEL_FROM_DATABASE=P2000 Tilt Pad usb:v06A3p056F* ID_MODEL_FROM_DATABASE=P2000 Tilt Pad usb:v06A3p05D2* ID_MODEL_FROM_DATABASE=PC Dash 2 usb:v06A3p075C* ID_MODEL_FROM_DATABASE=X52 Flight Controller usb:v06A3p0762* ID_MODEL_FROM_DATABASE=Saitek X52 Pro Flight Control System usb:v06A3p0763* ID_MODEL_FROM_DATABASE=Pro Flight Rudder Pedals usb:v06A3p0764* ID_MODEL_FROM_DATABASE=Flight Pro Combat Rudder usb:v06A3p0805* ID_MODEL_FROM_DATABASE=R440 Force Wheel usb:v06A3p0B4E* ID_MODEL_FROM_DATABASE=Pro Flight Backlit Information Panel usb:v06A3p0BAC* ID_MODEL_FROM_DATABASE=Pro Flight Yoke usb:v06A3p0C2D* ID_MODEL_FROM_DATABASE=Pro Flight Quadrant usb:v06A3p0D05* ID_MODEL_FROM_DATABASE=Pro Flight Radio Panel usb:v06A3p0D06* ID_MODEL_FROM_DATABASE=Flight Pro Multi Panel usb:v06A3p0D67* ID_MODEL_FROM_DATABASE=Pro Flight Switch Panel usb:v06A3p1003* ID_MODEL_FROM_DATABASE=GM2 Action Pad usb:v06A3p1009* ID_MODEL_FROM_DATABASE=Action Pad usb:v06A3p100A* ID_MODEL_FROM_DATABASE=SP550 Pad and Joystick Combo usb:v06A3p100B* ID_MODEL_FROM_DATABASE=SP550 Pad usb:v06A3p1509* ID_MODEL_FROM_DATABASE=P3000 Wireless Pad usb:v06A3p1589* ID_MODEL_FROM_DATABASE=P3000 Wireless Pad usb:v06A3p2541* ID_MODEL_FROM_DATABASE=X45 Flight Controller usb:v06A3p3509* ID_MODEL_FROM_DATABASE=P3000 RF GamePad usb:v06A3p353E* ID_MODEL_FROM_DATABASE=Cyborg Evo Wireless usb:v06A3p3589* ID_MODEL_FROM_DATABASE=P3000 Wireless Pad usb:v06A3p35BE* ID_MODEL_FROM_DATABASE=Cyborg Evo usb:v06A3p5509* ID_MODEL_FROM_DATABASE=P3000 Wireless Pad usb:v06A3p712C* ID_MODEL_FROM_DATABASE=Pro Flight Yoke integrated hub usb:v06A3p8000* ID_MODEL_FROM_DATABASE=Gamers' Keyboard usb:v06A3p801E* ID_MODEL_FROM_DATABASE=Cyborg 3D Digital Stick II usb:v06A3p8020* ID_MODEL_FROM_DATABASE=Eclipse Keyboard usb:v06A3p8021* ID_MODEL_FROM_DATABASE=Eclipse II Keyboard usb:v06A3p802D* ID_MODEL_FROM_DATABASE=P750 Pad usb:v06A3p803F* ID_MODEL_FROM_DATABASE=X36 Flight Controller usb:v06A3p806F* ID_MODEL_FROM_DATABASE=P2000 Tilt Pad usb:v06A3p80C0* ID_MODEL_FROM_DATABASE=Pro Gamer Command Unit usb:v06A3p80C1* ID_MODEL_FROM_DATABASE=Cyborg Command Pad Unit usb:v06A3pA2AE* ID_MODEL_FROM_DATABASE=Pro Flight Instrument Panel usb:v06A3pA502* ID_MODEL_FROM_DATABASE=Gaming Mouse usb:v06A3pF518* ID_MODEL_FROM_DATABASE=P3200 Rumble Force Game Pad usb:v06A3pFF04* ID_MODEL_FROM_DATABASE=R440 Force Wheel usb:v06A3pFF0C* ID_MODEL_FROM_DATABASE=Cyborg Force Rumble Pad usb:v06A3pFF0D* ID_MODEL_FROM_DATABASE=P2600 Rumble Force Pad usb:v06A3pFF12* ID_MODEL_FROM_DATABASE=Cyborg 3D Force Stick usb:v06A3pFF17* ID_MODEL_FROM_DATABASE=ST 330 Rumble Force Stick usb:v06A3pFF52* ID_MODEL_FROM_DATABASE=Cyborg 3D Rumble Force Joystick usb:v06A3pFFB5* ID_MODEL_FROM_DATABASE=Cyborg Evo Force Joystick usb:v06A4* ID_VENDOR_FROM_DATABASE=Xiamen Doowell Electron Co., Ltd usb:v06A5* ID_VENDOR_FROM_DATABASE=Divio usb:v06A5p0000* ID_MODEL_FROM_DATABASE=Typhoon Webcam 100k [nw8000] usb:v06A5pD001* ID_MODEL_FROM_DATABASE=ProLink DS3303u Webcam usb:v06A5pD800* ID_MODEL_FROM_DATABASE=Chicony TwinkleCam usb:v06A5pD820* ID_MODEL_FROM_DATABASE=Wize Media 1000 usb:v06A7* ID_VENDOR_FROM_DATABASE=MicroStore, Inc. usb:v06A8* ID_VENDOR_FROM_DATABASE=Topaz Systems, Inc. usb:v06A8p0042* ID_MODEL_FROM_DATABASE=SignatureGem 1X5 Pad usb:v06A8p0043* ID_MODEL_FROM_DATABASE=SignatureGem 1X5-HID Pad usb:v06A9* ID_VENDOR_FROM_DATABASE=Westell usb:v06A9p0005* ID_MODEL_FROM_DATABASE=WireSpeed Dual Connect Modem usb:v06A9p0006* ID_MODEL_FROM_DATABASE=WireSpeed Dual Connect Modem usb:v06A9p000A* ID_MODEL_FROM_DATABASE=WireSpeed Dual Connect Modem usb:v06A9p000B* ID_MODEL_FROM_DATABASE=WireSpeed Dual Connect Modem usb:v06A9p000E* ID_MODEL_FROM_DATABASE=A90-211WG-01 802.11g Adapter [Intersil ISL3887] usb:v06AA* ID_VENDOR_FROM_DATABASE=Sysgration, Ltd usb:v06AC* ID_VENDOR_FROM_DATABASE=Fujitsu Laboratories of America, Inc. usb:v06AD* ID_VENDOR_FROM_DATABASE=Greatland Electronics Taiwan, Ltd usb:v06AE* ID_VENDOR_FROM_DATABASE=Professional Multimedia Testing Centre usb:v06AF* ID_VENDOR_FROM_DATABASE=Harting, Inc. of North America usb:v06B8* ID_VENDOR_FROM_DATABASE=Pixela Corp. usb:v06B9* ID_VENDOR_FROM_DATABASE=Alcatel Telecom usb:v06B9p0120* ID_MODEL_FROM_DATABASE=SpeedTouch 120g 802.11g Wireless Adapter [Intersil ISL3886] usb:v06B9p0121* ID_MODEL_FROM_DATABASE=SpeedTouch 121g Wireless Dongle usb:v06B9p2001* ID_MODEL_FROM_DATABASE=SPEED TOUCH Card usb:v06B9p4061* ID_MODEL_FROM_DATABASE=SpeedTouch ISDN or ADSL Modem usb:v06B9p4062* ID_MODEL_FROM_DATABASE=SpeedTouch ISDN or ADSL router usb:v06B9pA5A5* ID_MODEL_FROM_DATABASE=DynaMiTe Modem usb:v06BA* ID_VENDOR_FROM_DATABASE=Smooth Cord & Connector Co., Ltd usb:v06BB* ID_VENDOR_FROM_DATABASE=EDA, Inc. usb:v06BC* ID_VENDOR_FROM_DATABASE=Oki Data Corp. usb:v06BCp000B* ID_MODEL_FROM_DATABASE=Okipage 14ex Printer usb:v06BCp0027* ID_MODEL_FROM_DATABASE=Okipage 14e usb:v06BCp00F7* ID_MODEL_FROM_DATABASE=OKI B4600 Mono Printer usb:v06BCp015E* ID_MODEL_FROM_DATABASE=OKIPOS 411/412 POS Printer usb:v06BCp01C9* ID_MODEL_FROM_DATABASE=OKI B430 Mono Printer usb:v06BCp020B* ID_MODEL_FROM_DATABASE=OKI ES4140 Mono Printer usb:v06BCp02BB* ID_MODEL_FROM_DATABASE=OKI PT390 POS Printer usb:v06BCp0A91* ID_MODEL_FROM_DATABASE=B2500MFP (printer+scanner) usb:v06BCp3801* ID_MODEL_FROM_DATABASE=B6100 Laser Printer usb:v06BD* ID_VENDOR_FROM_DATABASE=AGFA-Gevaert NV usb:v06BDp0001* ID_MODEL_FROM_DATABASE=SnapScan 1212U usb:v06BDp0002* ID_MODEL_FROM_DATABASE=SnapScan 1236U usb:v06BDp0100* ID_MODEL_FROM_DATABASE=SnapScan Touch usb:v06BDp0101* ID_MODEL_FROM_DATABASE=SNAPSCAN ELITE usb:v06BDp0200* ID_MODEL_FROM_DATABASE=ScanMaker 8700 usb:v06BDp02BF* ID_MODEL_FROM_DATABASE=DUOSCAN f40 usb:v06BDp0400* ID_MODEL_FROM_DATABASE=CL30 usb:v06BDp0401* ID_MODEL_FROM_DATABASE=Mass Storage usb:v06BDp0403* ID_MODEL_FROM_DATABASE=ePhoto CL18 Camera usb:v06BDp0404* ID_MODEL_FROM_DATABASE=ePhoto CL20 Camera usb:v06BDp2061* ID_MODEL_FROM_DATABASE=SnapScan 1212U (?) usb:v06BDp208D* ID_MODEL_FROM_DATABASE=Snapscan e40 usb:v06BDp208F* ID_MODEL_FROM_DATABASE=SnapScan e50 usb:v06BDp2091* ID_MODEL_FROM_DATABASE=SnapScan e20 usb:v06BDp2093* ID_MODEL_FROM_DATABASE=SnapScan e10 usb:v06BDp2095* ID_MODEL_FROM_DATABASE=SnapScan e25 usb:v06BDp2097* ID_MODEL_FROM_DATABASE=SnapScan e26 usb:v06BDp20FD* ID_MODEL_FROM_DATABASE=SnapScan e52 usb:v06BDp20FF* ID_MODEL_FROM_DATABASE=SnapScan e42 usb:v06BE* ID_VENDOR_FROM_DATABASE=AME Optimedia Technology Co., Ltd usb:v06BEp0800* ID_MODEL_FROM_DATABASE=Optimedia Camera usb:v06BEp1005* ID_MODEL_FROM_DATABASE=Dazzle DPVM! (1005) usb:v06BEpD001* ID_MODEL_FROM_DATABASE=P35U Camera Capture usb:v06BF* ID_VENDOR_FROM_DATABASE=Leoco Corp. usb:v06C2* ID_VENDOR_FROM_DATABASE=Phidgets Inc. (formerly GLAB) usb:v06C2p0030* ID_MODEL_FROM_DATABASE=PhidgetRFID usb:v06C2p0031* ID_MODEL_FROM_DATABASE=RFID reader usb:v06C2p0038* ID_MODEL_FROM_DATABASE=4-Motor PhidgetServo v3.0 usb:v06C2p0039* ID_MODEL_FROM_DATABASE=1-Motor PhidgetServo v3.0 usb:v06C2p003A* ID_MODEL_FROM_DATABASE=8-Motor PhidgetAvancedServo usb:v06C2p0040* ID_MODEL_FROM_DATABASE=PhidgetInterface Kit 0-0-4 usb:v06C2p0044* ID_MODEL_FROM_DATABASE=PhidgetInterface Kit 0-16-16 usb:v06C2p0045* ID_MODEL_FROM_DATABASE=PhidgetInterface Kit 8-8-8 usb:v06C2p0048* ID_MODEL_FROM_DATABASE=PhidgetStepper (Under Development) usb:v06C2p0049* ID_MODEL_FROM_DATABASE=PhidgetTextLED Ver 1.0 usb:v06C2p004A* ID_MODEL_FROM_DATABASE=PhidgetLED Ver 1.0 usb:v06C2p004B* ID_MODEL_FROM_DATABASE=PhidgetEncoder Ver 1.0 usb:v06C2p0051* ID_MODEL_FROM_DATABASE=PhidgetInterface Kit 0-5-7 (Custom) usb:v06C2p0052* ID_MODEL_FROM_DATABASE=PhidgetTextLCD usb:v06C2p0053* ID_MODEL_FROM_DATABASE=PhidgetInterfaceKit 0-8-8 usb:v06C2p0058* ID_MODEL_FROM_DATABASE=PhidgetMotorControl Ver 1.0 usb:v06C2p0070* ID_MODEL_FROM_DATABASE=PhidgetTemperatureSensor Ver 1.0 usb:v06C2p0071* ID_MODEL_FROM_DATABASE=PhidgetAccelerometer Ver 1.0 usb:v06C2p0072* ID_MODEL_FROM_DATABASE=PhidgetWeightSensor Ver 1.0 usb:v06C2p0073* ID_MODEL_FROM_DATABASE=PhidgetHumiditySensor usb:v06C2p0074* ID_MODEL_FROM_DATABASE=PhidgetPHSensor usb:v06C2p0075* ID_MODEL_FROM_DATABASE=PhidgetGyroscope usb:v06C4* ID_VENDOR_FROM_DATABASE=Bizlink International Corp. usb:v06C5* ID_VENDOR_FROM_DATABASE=Hagenuk, GmbH usb:v06C6* ID_VENDOR_FROM_DATABASE=Infowave Software, Inc. usb:v06C8* ID_VENDOR_FROM_DATABASE=SIIG, Inc. usb:v06C9* ID_VENDOR_FROM_DATABASE=Taxan (Europe), Ltd usb:v06C9p0005* ID_MODEL_FROM_DATABASE=Monitor Control usb:v06C9p0007* ID_MODEL_FROM_DATABASE=Monitor Control usb:v06C9p0009* ID_MODEL_FROM_DATABASE=Monitor Control usb:v06CA* ID_VENDOR_FROM_DATABASE=Newer Technology, Inc. usb:v06CAp2003* ID_MODEL_FROM_DATABASE=uSCSI usb:v06CB* ID_VENDOR_FROM_DATABASE=Synaptics, Inc. usb:v06CBp0001* ID_MODEL_FROM_DATABASE=TouchPad usb:v06CBp0002* ID_MODEL_FROM_DATABASE=Integrated TouchPad usb:v06CBp0003* ID_MODEL_FROM_DATABASE=cPad usb:v06CBp0005* ID_MODEL_FROM_DATABASE=Touchpad/FPS usb:v06CBp0006* ID_MODEL_FROM_DATABASE=TouchScreen usb:v06CBp0007* ID_MODEL_FROM_DATABASE=USB Styk usb:v06CBp0008* ID_MODEL_FROM_DATABASE=WheelPad usb:v06CBp0009* ID_MODEL_FROM_DATABASE=Composite TouchPad and TrackPoint usb:v06CBp000E* ID_MODEL_FROM_DATABASE=HID Device usb:v06CBp0010* ID_MODEL_FROM_DATABASE=Wireless TouchPad usb:v06CBp0013* ID_MODEL_FROM_DATABASE=DisplayPad usb:v06CBp2970* ID_MODEL_FROM_DATABASE=touchpad usb:v06CC* ID_VENDOR_FROM_DATABASE=Terayon Communication Systems usb:v06CCp0101* ID_MODEL_FROM_DATABASE=Cable Modem usb:v06CCp0102* ID_MODEL_FROM_DATABASE=Cable Modem usb:v06CCp0103* ID_MODEL_FROM_DATABASE=Cable Modem usb:v06CCp0104* ID_MODEL_FROM_DATABASE=Cable Modem usb:v06CCp0304* ID_MODEL_FROM_DATABASE=Cable Modem usb:v06CD* ID_VENDOR_FROM_DATABASE=Keyspan usb:v06CDp0101* ID_MODEL_FROM_DATABASE=USA-28 PDA [no firmware] usb:v06CDp0102* ID_MODEL_FROM_DATABASE=USA-28X PDA [no firmware] usb:v06CDp0103* ID_MODEL_FROM_DATABASE=USA-19 PDA [no firmware] usb:v06CDp0104* ID_MODEL_FROM_DATABASE=PDA [prerenum] usb:v06CDp0105* ID_MODEL_FROM_DATABASE=USA-18X PDA [no firmware] usb:v06CDp0106* ID_MODEL_FROM_DATABASE=USA-19W PDA [no firmware] usb:v06CDp0107* ID_MODEL_FROM_DATABASE=USA-19 PDA usb:v06CDp0108* ID_MODEL_FROM_DATABASE=USA-19W PDA usb:v06CDp0109* ID_MODEL_FROM_DATABASE=USA-49W serial adapter [no firmware] usb:v06CDp010A* ID_MODEL_FROM_DATABASE=USA-49W serial adapter usb:v06CDp010B* ID_MODEL_FROM_DATABASE=USA-19Qi serial adapter [no firmware] usb:v06CDp010C* ID_MODEL_FROM_DATABASE=USA-19Qi serial adapter usb:v06CDp010D* ID_MODEL_FROM_DATABASE=USA-19Q serial Adapter (no firmware) usb:v06CDp010E* ID_MODEL_FROM_DATABASE=USA-19Q serial Adapter usb:v06CDp010F* ID_MODEL_FROM_DATABASE=USA-28 PDA usb:v06CDp0110* ID_MODEL_FROM_DATABASE=USA-28Xb PDA usb:v06CDp0111* ID_MODEL_FROM_DATABASE=USA-18 serial Adapter usb:v06CDp0112* ID_MODEL_FROM_DATABASE=USA-18X PDA usb:v06CDp0113* ID_MODEL_FROM_DATABASE=USA-28Xb PDA [no firmware] usb:v06CDp0114* ID_MODEL_FROM_DATABASE=USA-28Xa PDA [no firmware] usb:v06CDp0115* ID_MODEL_FROM_DATABASE=USA-28Xa PDA usb:v06CDp0116* ID_MODEL_FROM_DATABASE=USA-18XA serial Adapter (no firmware) usb:v06CDp0117* ID_MODEL_FROM_DATABASE=USA-18XA serial Adapter usb:v06CDp0118* ID_MODEL_FROM_DATABASE=USA-19QW PDA [no firmware] usb:v06CDp0119* ID_MODEL_FROM_DATABASE=USA-19QW PDA usb:v06CDp011A* ID_MODEL_FROM_DATABASE=USA-49Wlc serial adapter [no firmware] usb:v06CDp011B* ID_MODEL_FROM_DATABASE=MPR Serial Preloader (MPRQI) usb:v06CDp011C* ID_MODEL_FROM_DATABASE=MPR Serial (MPRQI) usb:v06CDp011D* ID_MODEL_FROM_DATABASE=MPR Serial Preloader (MPRQ) usb:v06CDp011E* ID_MODEL_FROM_DATABASE=MPR Serial (MPRQ) usb:v06CDp0121* ID_MODEL_FROM_DATABASE=USA-19hs serial adapter usb:v06CDp012A* ID_MODEL_FROM_DATABASE=USA-49Wlc serial adapter usb:v06CDp0201* ID_MODEL_FROM_DATABASE=UIA-10 Digital Media Remote [Cypress AN2131SC] usb:v06CDp0202* ID_MODEL_FROM_DATABASE=UIA-11 Digital Media Remote usb:v06CE* ID_VENDOR_FROM_DATABASE=Contec usb:v06CEp8311* ID_MODEL_FROM_DATABASE=COM-1(USB)H usb:v06CF* ID_VENDOR_FROM_DATABASE=SpheronVR AG usb:v06CFp1010* ID_MODEL_FROM_DATABASE=PanoCam 10 usb:v06CFp1012* ID_MODEL_FROM_DATABASE=PanoCam 12/12X usb:v06D0* ID_VENDOR_FROM_DATABASE=LapLink, Inc. usb:v06D0p0622* ID_MODEL_FROM_DATABASE=LapLink Gold USB-USB Bridge [net1080] usb:v06D1* ID_VENDOR_FROM_DATABASE=Daewoo Electronics Co., Ltd usb:v06D3* ID_VENDOR_FROM_DATABASE=Mitsubishi Electric Corp. usb:v06D3p0284* ID_MODEL_FROM_DATABASE=FX-USB-AW/-BD RS482 Converters usb:v06D3p0380* ID_MODEL_FROM_DATABASE=CP8000D Port usb:v06D3p0381* ID_MODEL_FROM_DATABASE=CP770D Port usb:v06D3p0385* ID_MODEL_FROM_DATABASE=CP900D Port usb:v06D3p0387* ID_MODEL_FROM_DATABASE=CP980D Port usb:v06D3p038B* ID_MODEL_FROM_DATABASE=CP3020D Port usb:v06D3p038C* ID_MODEL_FROM_DATABASE=CP900DW(ID) Port usb:v06D3p0393* ID_MODEL_FROM_DATABASE=CP9500D/DW Port usb:v06D3p0394* ID_MODEL_FROM_DATABASE=CP9000D/DW Port usb:v06D3p03A1* ID_MODEL_FROM_DATABASE=CP9550D/DW Port usb:v06D3p3B30* ID_MODEL_FROM_DATABASE=CP-D70DW / CP-D707DW usb:v06D3p3B31* ID_MODEL_FROM_DATABASE=CP-K60DW-S usb:v06D4* ID_VENDOR_FROM_DATABASE=Cisco Systems usb:v06D5* ID_VENDOR_FROM_DATABASE=Toshiba usb:v06D5p4000* ID_MODEL_FROM_DATABASE=Japanese Keyboard usb:v06D6* ID_VENDOR_FROM_DATABASE=Aashima Technology B.V. usb:v06D6p0025* ID_MODEL_FROM_DATABASE=Gamepad usb:v06D6p0026* ID_MODEL_FROM_DATABASE=Predator TH 400 Gamepad usb:v06D6p002D* ID_MODEL_FROM_DATABASE=Trust PowerC@m 350FT usb:v06D6p002E* ID_MODEL_FROM_DATABASE=Trust PowerC@m 350FS usb:v06D6p0030* ID_MODEL_FROM_DATABASE=Trust 710 LCD POWERC@M ZOOM - MSD usb:v06D6p0031* ID_MODEL_FROM_DATABASE=Trust 610/710 LCD POWERC@M ZOOM usb:v06D6p003A* ID_MODEL_FROM_DATABASE=Trust PowerC@m 770Z (mass storage mode) usb:v06D6p003B* ID_MODEL_FROM_DATABASE=Trust PowerC@m 770Z (webcam mode) usb:v06D6p003C* ID_MODEL_FROM_DATABASE=Trust 910z PowerC@m usb:v06D6p003F* ID_MODEL_FROM_DATABASE=Trust 735S POWERC@M ZOOM, WDM DSC Bulk Driver usb:v06D6p0050* ID_MODEL_FROM_DATABASE=Trust 738AV LCD PV Digital Camera usb:v06D6p0062* ID_MODEL_FROM_DATABASE=TRUST 782AV LCD P. V. Video Capture usb:v06D6p0066* ID_MODEL_FROM_DATABASE=TRUST Digital PCTV and Movie Editor usb:v06D6p0067* ID_MODEL_FROM_DATABASE=Trust 350FS POWERC@M FLASH usb:v06D6p006B* ID_MODEL_FROM_DATABASE=TRUST AUDIO VIDEO EDITOR usb:v06D7* ID_VENDOR_FROM_DATABASE=Network Computing Devices (NCD) usb:v06D8* ID_VENDOR_FROM_DATABASE=Technical Marketing Research, Inc. usb:v06DA* ID_VENDOR_FROM_DATABASE=Phoenixtec Power Co., Ltd usb:v06DAp0002* ID_MODEL_FROM_DATABASE=UPS usb:v06DAp0003* ID_MODEL_FROM_DATABASE=1300VA UPS usb:v06DB* ID_VENDOR_FROM_DATABASE=Paradyne usb:v06DC* ID_VENDOR_FROM_DATABASE=Foxlink Image Technology Co., Ltd usb:v06DCp0012* ID_MODEL_FROM_DATABASE=Scan 1200c Scanner usb:v06DCp0014* ID_MODEL_FROM_DATABASE=Prolink Winscan Pro 2448U usb:v06DE* ID_VENDOR_FROM_DATABASE=Heisei Electronics Co., Ltd usb:v06E0* ID_VENDOR_FROM_DATABASE=Multi-Tech Systems, Inc. usb:v06E0p0319* ID_MODEL_FROM_DATABASE=MT9234ZBA-USB MultiModem ZBA usb:v06E0pF101* ID_MODEL_FROM_DATABASE=MT5634ZBA-USB MultiModemUSB (old firmware) usb:v06E0pF103* ID_MODEL_FROM_DATABASE=MT5634MU MultiMobileUSB usb:v06E0pF104* ID_MODEL_FROM_DATABASE=MT5634ZBA-USB MultiModemUSB (new firmware) usb:v06E0pF107* ID_MODEL_FROM_DATABASE=MT5634ZBA-USB-V92 MultiModemUSB usb:v06E0pF120* ID_MODEL_FROM_DATABASE=MT9234ZBA-USB-CDC-ACM-XR MultiModem ZBA CDC-ACM-XR usb:v06E1* ID_VENDOR_FROM_DATABASE=ADS Technologies, Inc. usb:v06E1p0008* ID_MODEL_FROM_DATABASE=UBS-10BT Ethernet [klsi] usb:v06E1p0009* ID_MODEL_FROM_DATABASE=UBS-10BT Ethernet usb:v06E1p0833* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v06E1pA155* ID_MODEL_FROM_DATABASE=FM Radio Receiver/Instant FM Music (RDX-155-EF) usb:v06E1pA160* ID_MODEL_FROM_DATABASE=Instant Video-To-Go RDX-160 (no firmware) usb:v06E1pA161* ID_MODEL_FROM_DATABASE=Instant Video-To-Go RDX-160 usb:v06E1pA190* ID_MODEL_FROM_DATABASE=Instand VCD Capture usb:v06E1pA191* ID_MODEL_FROM_DATABASE=Instant VideoXpress usb:v06E1pA337* ID_MODEL_FROM_DATABASE=Mini DigitalTV usb:v06E1pA701* ID_MODEL_FROM_DATABASE=DVD Xpress usb:v06E1pA708* ID_MODEL_FROM_DATABASE=saa7114H video input card (Instant VideoMPX) usb:v06E1pB337* ID_MODEL_FROM_DATABASE=Mini DigitalTV usb:v06E1pB701* ID_MODEL_FROM_DATABASE=DVD Xpress B usb:v06E4* ID_VENDOR_FROM_DATABASE=Alcatel Microelectronics usb:v06E6* ID_VENDOR_FROM_DATABASE=Tiger Jet Network, Inc. usb:v06E6p0200* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6p0201* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6p0202* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6p0203* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6p0210* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6p0211* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6p0212* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6p031C* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6p031D* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6p031E* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6p3200* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6p3201* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6p3202* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6p3203* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6p7200* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6p7210* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6p7250* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6p825C* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6p831C* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6p831D* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6p831E* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pB200* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pB201* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pB202* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pB210* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pB211* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pB212* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pB250* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pB251* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pB252* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pC200* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pC201* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pC202* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pC203* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pC210* ID_MODEL_FROM_DATABASE=Personal PhoneGateway usb:v06E6pC211* ID_MODEL_FROM_DATABASE=Personal PhoneGateway usb:v06E6pC212* ID_MODEL_FROM_DATABASE=Personal PhoneGateway usb:v06E6pC213* ID_MODEL_FROM_DATABASE=PPG Device usb:v06E6pC25C* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pC290* ID_MODEL_FROM_DATABASE=PPG Device usb:v06E6pC291* ID_MODEL_FROM_DATABASE=PPG Device usb:v06E6pC292* ID_MODEL_FROM_DATABASE=PPG Device usb:v06E6pC293* ID_MODEL_FROM_DATABASE=Personal PhoneGateway usb:v06E6pC31C* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pC39C* ID_MODEL_FROM_DATABASE=Personal PhoneGateway usb:v06E6pC39D* ID_MODEL_FROM_DATABASE=PPG Device usb:v06E6pC39E* ID_MODEL_FROM_DATABASE=PPG Device usb:v06E6pC39F* ID_MODEL_FROM_DATABASE=PPG Device usb:v06E6pC700* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pC701* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pC702* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pC703* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pC710* ID_MODEL_FROM_DATABASE=VoIP Combo Device usb:v06E6pC711* ID_MODEL_FROM_DATABASE=VoIP Combo usb:v06E6pC712* ID_MODEL_FROM_DATABASE=VoIP Combo Device usb:v06E6pC713* ID_MODEL_FROM_DATABASE=VoIP Combo Device usb:v06E6pCF00* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pCF01* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pCF02* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pCF03* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pD210* ID_MODEL_FROM_DATABASE=Personal PhoneGateway usb:v06E6pD211* ID_MODEL_FROM_DATABASE=PPG Device usb:v06E6pD212* ID_MODEL_FROM_DATABASE=PPG Device usb:v06E6pD213* ID_MODEL_FROM_DATABASE=Personal PhoneGateway usb:v06E6pD700* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pD701* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pD702* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pD703* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pD710* ID_MODEL_FROM_DATABASE=VoIP Combo usb:v06E6pD711* ID_MODEL_FROM_DATABASE=VoIP Combo Device usb:v06E6pD712* ID_MODEL_FROM_DATABASE=VoIP Combo usb:v06E6pD713* ID_MODEL_FROM_DATABASE=VoIP Combo usb:v06E6pDF00* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pDF01* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pDF02* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pDF03* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pF200* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pF201* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pF202* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pF203* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pF210* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pF250* ID_MODEL_FROM_DATABASE=Composite Device usb:v06E6pF252* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pF310* ID_MODEL_FROM_DATABASE=Internet Phone usb:v06E6pF350* ID_MODEL_FROM_DATABASE=Composite Device usb:v06EA* ID_VENDOR_FROM_DATABASE=Sirius Technologies usb:v06EAp0001* ID_MODEL_FROM_DATABASE=NetCom Roadster II 56k usb:v06EAp0002* ID_MODEL_FROM_DATABASE=Roadster II 56k usb:v06EB* ID_VENDOR_FROM_DATABASE=PC Expert Tech. Co., Ltd usb:v06EF* ID_VENDOR_FROM_DATABASE=I.A.C. Geometrische Ingenieurs B.V. usb:v06F0* ID_VENDOR_FROM_DATABASE=T.N.C Industrial Co., Ltd usb:v06F0pDE01* ID_MODEL_FROM_DATABASE=DualCam Video Camera usb:v06F0pDE02* ID_MODEL_FROM_DATABASE=DualCam Still Camera usb:v06F1* ID_VENDOR_FROM_DATABASE=Opcode Systems, Inc. usb:v06F1pA011* ID_MODEL_FROM_DATABASE=SonicPort usb:v06F1pA021* ID_MODEL_FROM_DATABASE=SonicPort Optical usb:v06F2* ID_VENDOR_FROM_DATABASE=Emine Technology Co. usb:v06F2p0011* ID_MODEL_FROM_DATABASE=KVM Switch Keyboard usb:v06F6* ID_VENDOR_FROM_DATABASE=Wintrend Technology Co., Ltd usb:v06F7* ID_VENDOR_FROM_DATABASE=Wailly Technology Ltd usb:v06F7p0003* ID_MODEL_FROM_DATABASE=USB->Din 4 Adaptor usb:v06F8* ID_VENDOR_FROM_DATABASE=Guillemot Corp. usb:v06F8p3002* ID_MODEL_FROM_DATABASE=Hercules Blog Webcam usb:v06F8p3004* ID_MODEL_FROM_DATABASE=Hercules Classic Silver usb:v06F8p3005* ID_MODEL_FROM_DATABASE=Hercules Dualpix Exchange usb:v06F8p3007* ID_MODEL_FROM_DATABASE=Hercules Dualpix Chat and Show usb:v06F8p3020* ID_MODEL_FROM_DATABASE=Hercules Webcam EC300 usb:v06F8pA300* ID_MODEL_FROM_DATABASE=Dual Analog Leader GamePad usb:v06F8pB000* ID_MODEL_FROM_DATABASE=Hercules DJ Console usb:v06F8pC000* ID_MODEL_FROM_DATABASE=Hercules Muse Pocket usb:v06F8pD002* ID_MODEL_FROM_DATABASE=Hercules DJ Console usb:v06F8pE000* ID_MODEL_FROM_DATABASE=HWGUSB2-54 WLAN usb:v06F8pE010* ID_MODEL_FROM_DATABASE=HWGUSB2-54-LB usb:v06F8pE020* ID_MODEL_FROM_DATABASE=HWGUSB2-54V2-AP usb:v06F8pE031* ID_MODEL_FROM_DATABASE=Hercules HWNUm-300 Wireless N mini [Realtek RTL8191SU] usb:v06F8pE032* ID_MODEL_FROM_DATABASE=HWGUm-54 [Hercules Wireless G Ultra Mini Key] usb:v06F8pE033* ID_MODEL_FROM_DATABASE=Hercules HWNUp-150 802.11n Wireless N Pico [Realtek RTL8188CUS] usb:v06F9* ID_VENDOR_FROM_DATABASE=ASYST electronic d.o.o. usb:v06FA* ID_VENDOR_FROM_DATABASE=HSD S.r.L usb:v06FC* ID_VENDOR_FROM_DATABASE=Motorola Semiconductor Products Sector usb:v06FD* ID_VENDOR_FROM_DATABASE=Boston Acoustics usb:v06FDp0101* ID_MODEL_FROM_DATABASE=Audio Device usb:v06FDp0102* ID_MODEL_FROM_DATABASE=Audio Device usb:v06FDp0201* ID_MODEL_FROM_DATABASE=2-piece Audio Device usb:v06FE* ID_VENDOR_FROM_DATABASE=Gallant Computer, Inc. usb:v0701* ID_VENDOR_FROM_DATABASE=Supercomal Wire & Cable SDN. BHD. usb:v0703* ID_VENDOR_FROM_DATABASE=Bvtech Industry, Inc. usb:v0705* ID_VENDOR_FROM_DATABASE=NKK Corp. usb:v0706* ID_VENDOR_FROM_DATABASE=Ariel Corp. usb:v0707* ID_VENDOR_FROM_DATABASE=Standard Microsystems Corp. usb:v0707p0100* ID_MODEL_FROM_DATABASE=2202 Ethernet [klsi] usb:v0707p0200* ID_MODEL_FROM_DATABASE=2202 Ethernet [pegasus] usb:v0707p0201* ID_MODEL_FROM_DATABASE=EZ Connect USB Ethernet usb:v0707pEE04* ID_MODEL_FROM_DATABASE=SMCWUSB32 802.11b Wireless LAN Card usb:v0707pEE06* ID_MODEL_FROM_DATABASE=SMC2862W-G v1 EZ Connect 802.11g Adapter [Intersil ISL3886] usb:v0707pEE13* ID_MODEL_FROM_DATABASE=SMC2862W-G v2 EZ Connect 802.11g Adapter [Intersil ISL3887] usb:v0708* ID_VENDOR_FROM_DATABASE=Putercom Co., Ltd usb:v0708p047E* ID_MODEL_FROM_DATABASE=USB-1284 BRIDGE usb:v0709* ID_VENDOR_FROM_DATABASE=Silicon Systems, Ltd (SSL) usb:v070A* ID_VENDOR_FROM_DATABASE=Oki Electric Industry Co., Ltd usb:v070Ap4002* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v070Ap4003* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v070D* ID_VENDOR_FROM_DATABASE=Comoss Electronic Co., Ltd usb:v070E* ID_VENDOR_FROM_DATABASE=Excel Cell Electronic Co., Ltd usb:v0710* ID_VENDOR_FROM_DATABASE=Connect Tech, Inc. usb:v0710p0001* ID_MODEL_FROM_DATABASE=WhiteHeat (fake ID) usb:v0710p8001* ID_MODEL_FROM_DATABASE=WhiteHeat usb:v0711* ID_VENDOR_FROM_DATABASE=Magic Control Technology Corp. usb:v0711p0100* ID_MODEL_FROM_DATABASE=Hub usb:v0711p0180* ID_MODEL_FROM_DATABASE=IRXpress Infrared Device usb:v0711p0181* ID_MODEL_FROM_DATABASE=IRXpress Infrared Device usb:v0711p0200* ID_MODEL_FROM_DATABASE=BAY-3U1S1P Serial Port usb:v0711p0210* ID_MODEL_FROM_DATABASE=MCT1S Serial Port usb:v0711p0230* ID_MODEL_FROM_DATABASE=MCT-232 Serial Port usb:v0711p0231* ID_MODEL_FROM_DATABASE=PS/2 Mouse Port usb:v0711p0232* ID_MODEL_FROM_DATABASE=Serial On Port usb:v0711p0240* ID_MODEL_FROM_DATABASE=PS/2 to USB Converter usb:v0711p0300* ID_MODEL_FROM_DATABASE=BAY-3U1S1P Parallel Port usb:v0711p0302* ID_MODEL_FROM_DATABASE=Parallel Port usb:v0711p0900* ID_MODEL_FROM_DATABASE=SVGA Adapter usb:v0711p5001* ID_MODEL_FROM_DATABASE=Trigger UV-002BD[Startech USBVGAE] usb:v0711p5100* ID_MODEL_FROM_DATABASE=Magic Control Technology Corp. (USB2VGA dongle) usb:v0713* ID_VENDOR_FROM_DATABASE=Interval Research Corp. usb:v0714* ID_VENDOR_FROM_DATABASE=NewMotion, Inc. usb:v0714p0003* ID_MODEL_FROM_DATABASE=ADB to USB convertor usb:v0717* ID_VENDOR_FROM_DATABASE=ZNK Corp. usb:v0718* ID_VENDOR_FROM_DATABASE=Imation Corp. usb:v0718p0002* ID_MODEL_FROM_DATABASE=SuperDisk 120MB usb:v0718p0003* ID_MODEL_FROM_DATABASE=SuperDisk 120MB (Authenticated) usb:v0718p0060* ID_MODEL_FROM_DATABASE=Flash Drive usb:v0718p0061* ID_MODEL_FROM_DATABASE=Flash Drive usb:v0718p0062* ID_MODEL_FROM_DATABASE=Flash Drive usb:v0718p0063* ID_MODEL_FROM_DATABASE=Swivel Flash Drive usb:v0718p0064* ID_MODEL_FROM_DATABASE=Flash Drive usb:v0718p0065* ID_MODEL_FROM_DATABASE=Flash Drive usb:v0718p0066* ID_MODEL_FROM_DATABASE=Flash Drive usb:v0718p0067* ID_MODEL_FROM_DATABASE=Flash Drive usb:v0718p0068* ID_MODEL_FROM_DATABASE=Flash Drive usb:v0718p0084* ID_MODEL_FROM_DATABASE=Flash Drive Mini usb:v0718p043C* ID_MODEL_FROM_DATABASE=Flash drive 16GB [Nano Pro] usb:v0718p0582* ID_MODEL_FROM_DATABASE=Revo Flash Drive usb:v0718p0622* ID_MODEL_FROM_DATABASE=TDK Trans-It 4GB usb:v0718p0624* ID_MODEL_FROM_DATABASE=TDK Trans-It 16GB usb:v0718p1120* ID_MODEL_FROM_DATABASE=RDX External dock (redbud) usb:v0718pD000* ID_MODEL_FROM_DATABASE=Disc Stakka CD/DVD Manager usb:v0719* ID_VENDOR_FROM_DATABASE=Tremon Enterprises Co., Ltd usb:v071B* ID_VENDOR_FROM_DATABASE=Domain Technologies, Inc. usb:v071Bp0002* ID_MODEL_FROM_DATABASE=DTI-56362-USB Digital Interface Unit usb:v071Bp0101* ID_MODEL_FROM_DATABASE=Audio4-USB DSP Data Acquisition Unit usb:v071Bp0201* ID_MODEL_FROM_DATABASE=Audio4-5410 DSP Data Acquisition Unit usb:v071Bp0301* ID_MODEL_FROM_DATABASE=SB-USB JTAG Emulator usb:v071Bp3203* ID_MODEL_FROM_DATABASE=Rockchip Media Player usb:v071Bp32BB* ID_MODEL_FROM_DATABASE=Music Mediatouch usb:v071C* ID_VENDOR_FROM_DATABASE=Xionics Document Technologies, Inc. usb:v071D* ID_VENDOR_FROM_DATABASE=Eicon Networks Corp. usb:v071Dp1000* ID_MODEL_FROM_DATABASE=Diva 2.01 S/T [PSB2115F] usb:v071Dp1003* ID_MODEL_FROM_DATABASE=Diva ISDN 2.0 usb:v071Dp1005* ID_MODEL_FROM_DATABASE=Diva ISDN 4.0 [HFC-S] usb:v071Dp2000* ID_MODEL_FROM_DATABASE=Teledat Surf usb:v071E* ID_VENDOR_FROM_DATABASE=Ariston Technologies usb:v0723* ID_VENDOR_FROM_DATABASE=Centillium Communications Corp. usb:v0723p0002* ID_MODEL_FROM_DATABASE=Palladia 300/400 Adsl Modem usb:v0726* ID_VENDOR_FROM_DATABASE=Vanguard International Semiconductor-America usb:v0729* ID_VENDOR_FROM_DATABASE=Amitm usb:v0729p1000* ID_MODEL_FROM_DATABASE=USC-1000 Serial Port usb:v072E* ID_VENDOR_FROM_DATABASE=Sunix Co., Ltd usb:v072F* ID_VENDOR_FROM_DATABASE=Advanced Card Systems, Ltd usb:v072Fp0001* ID_MODEL_FROM_DATABASE=AC1030-based SmartCard Reader usb:v072Fp0008* ID_MODEL_FROM_DATABASE=ACR 80 Smart Card Reader usb:v072Fp0100* ID_MODEL_FROM_DATABASE=AET65 usb:v072Fp0101* ID_MODEL_FROM_DATABASE=AET65 usb:v072Fp0102* ID_MODEL_FROM_DATABASE=AET62 usb:v072Fp0103* ID_MODEL_FROM_DATABASE=AET62 usb:v072Fp0901* ID_MODEL_FROM_DATABASE=ACR1281U-C4 (BSI) usb:v072Fp1000* ID_MODEL_FROM_DATABASE=PLDT Drive usb:v072Fp1001* ID_MODEL_FROM_DATABASE=PLDT Drive usb:v072Fp2011* ID_MODEL_FROM_DATABASE=ACR88U usb:v072Fp2100* ID_MODEL_FROM_DATABASE=ACR128U usb:v072Fp2200* ID_MODEL_FROM_DATABASE=ACR122U usb:v072Fp220A* ID_MODEL_FROM_DATABASE=ACR1281U-C5 (BSI) usb:v072Fp220C* ID_MODEL_FROM_DATABASE=ACR1283 Bootloader usb:v072Fp220F* ID_MODEL_FROM_DATABASE=ACR1281U-C2 (qPBOC) usb:v072Fp2211* ID_MODEL_FROM_DATABASE=ACR1261 1S Dual Reader usb:v072Fp2214* ID_MODEL_FROM_DATABASE=ACR1222 1SAM PICC Reader usb:v072Fp2215* ID_MODEL_FROM_DATABASE=ACR1281 2S CL Reader usb:v072Fp221A* ID_MODEL_FROM_DATABASE=ACR1251U-A1 usb:v072Fp221B* ID_MODEL_FROM_DATABASE=ACR1251U-C usb:v072Fp2224* ID_MODEL_FROM_DATABASE=ACR1281 1S Dual Reader usb:v072Fp222B* ID_MODEL_FROM_DATABASE=ACR1222U-C8 usb:v072Fp222C* ID_MODEL_FROM_DATABASE=ACR1283L-D2 usb:v072Fp222D* ID_MODEL_FROM_DATABASE=[OEM Reader] usb:v072Fp222E* ID_MODEL_FROM_DATABASE=ACR123U usb:v072Fp2242* ID_MODEL_FROM_DATABASE=ACR1251 1S Dual Reader usb:v072Fp8002* ID_MODEL_FROM_DATABASE=AET63 BioTRUSTKey usb:v072Fp8003* ID_MODEL_FROM_DATABASE=ACR120 usb:v072Fp8103* ID_MODEL_FROM_DATABASE=ACR120 usb:v072Fp8201* ID_MODEL_FROM_DATABASE=APG8201 usb:v072Fp8900* ID_MODEL_FROM_DATABASE=ACR89U-A1 usb:v072Fp8901* ID_MODEL_FROM_DATABASE=ACR89U-A2 usb:v072Fp8902* ID_MODEL_FROM_DATABASE=ACR89U-A3 usb:v072Fp9000* ID_MODEL_FROM_DATABASE=ACR38 AC1038-based Smart Card Reader usb:v072Fp9006* ID_MODEL_FROM_DATABASE=CryptoMate usb:v072Fp90CC* ID_MODEL_FROM_DATABASE=ACR38 SmartCard Reader usb:v072Fp90CE* ID_MODEL_FROM_DATABASE=[OEM Reader] usb:v072Fp90CF* ID_MODEL_FROM_DATABASE=ACR38 SAM Smart Card Reader usb:v072Fp90D0* ID_MODEL_FROM_DATABASE=PertoSmart EMV - Card Reader usb:v072Fp90D2* ID_MODEL_FROM_DATABASE=ACR83U usb:v072Fp90D8* ID_MODEL_FROM_DATABASE=ACR3801 usb:v072Fp90DB* ID_MODEL_FROM_DATABASE=CryptoMate64 usb:v072FpB000* ID_MODEL_FROM_DATABASE=ACR3901U usb:v072FpB100* ID_MODEL_FROM_DATABASE=ACR39U usb:v072FpB101* ID_MODEL_FROM_DATABASE=ACR39K usb:v072FpB102* ID_MODEL_FROM_DATABASE=ACR39T usb:v072FpB103* ID_MODEL_FROM_DATABASE=ACR39F usb:v072FpB104* ID_MODEL_FROM_DATABASE=ACR39U-SAM usb:v072FpB106* ID_MODEL_FROM_DATABASE=ACOS5T2 usb:v072FpB200* ID_MODEL_FROM_DATABASE=ACOS5T1 usb:v072FpB301* ID_MODEL_FROM_DATABASE=ACR32-A1 usb:v0731* ID_VENDOR_FROM_DATABASE=Susteen, Inc. usb:v0731p0528* ID_MODEL_FROM_DATABASE=SonyEricsson DCU-11 Cable usb:v0732* ID_VENDOR_FROM_DATABASE=Goldfull Electronics & Telecommunications Corp. usb:v0733* ID_VENDOR_FROM_DATABASE=ViewQuest Technologies, Inc. usb:v0733p0101* ID_MODEL_FROM_DATABASE=Digital Video Camera usb:v0733p0110* ID_MODEL_FROM_DATABASE=VQ110 Video Camera usb:v0733p0401* ID_MODEL_FROM_DATABASE=CS330 Webcam usb:v0733p0402* ID_MODEL_FROM_DATABASE=M-318B Webcam usb:v0733p0430* ID_MODEL_FROM_DATABASE=Intel Pro Share Webcam usb:v0733p0630* ID_MODEL_FROM_DATABASE=VQ630 Dual Mode Digital Camera(Bulk) usb:v0733p0631* ID_MODEL_FROM_DATABASE=Hercules Dualpix usb:v0733p0780* ID_MODEL_FROM_DATABASE=Smart Cam Deluxe(composite) usb:v0733p1310* ID_MODEL_FROM_DATABASE=Epsilon 1.3/Jenoptik JD C1.3/UMAX AstraPix 470 usb:v0733p1311* ID_MODEL_FROM_DATABASE=Digital Dream Epsilon 1.3 usb:v0733p1314* ID_MODEL_FROM_DATABASE=Mercury 2.1MEG Deluxe Classic Cam usb:v0733p2211* ID_MODEL_FROM_DATABASE=Jenoptik jdc 21 LCD Camera usb:v0733p2221* ID_MODEL_FROM_DATABASE=Mercury Digital Pro 3.1p usb:v0733p3261* ID_MODEL_FROM_DATABASE=Concord 3045 spca536a Camera usb:v0733p3281* ID_MODEL_FROM_DATABASE=Cyberpix S550V usb:v0734* ID_VENDOR_FROM_DATABASE=Lasat Communications A/S usb:v0734p0001* ID_MODEL_FROM_DATABASE=560V Modem usb:v0734p0002* ID_MODEL_FROM_DATABASE=Lasat 560V Modem usb:v0734p043A* ID_MODEL_FROM_DATABASE=DVS Audio usb:v0734p043B* ID_MODEL_FROM_DATABASE=3DeMon USB Capture usb:v0735* ID_VENDOR_FROM_DATABASE=Asuscom Network usb:v0735p2100* ID_MODEL_FROM_DATABASE=ISDN Adapter usb:v0735p2101* ID_MODEL_FROM_DATABASE=ISDN Adapter usb:v0735p6694* ID_MODEL_FROM_DATABASE=ISDNlink 128K usb:v0735pC541* ID_MODEL_FROM_DATABASE=ISDN TA 280 usb:v0736* ID_VENDOR_FROM_DATABASE=Lorom Industrial Co., Ltd usb:v0738* ID_VENDOR_FROM_DATABASE=Mad Catz, Inc. usb:v0738p4507* ID_MODEL_FROM_DATABASE=XBox Device usb:v0738p4516* ID_MODEL_FROM_DATABASE=XBox Device usb:v0738p4520* ID_MODEL_FROM_DATABASE=XBox Device usb:v0738p4526* ID_MODEL_FROM_DATABASE=XBox Device usb:v0738p4536* ID_MODEL_FROM_DATABASE=XBox Device usb:v0738p4540* ID_MODEL_FROM_DATABASE=XBox Device usb:v0738p4556* ID_MODEL_FROM_DATABASE=XBox Device usb:v0738p4566* ID_MODEL_FROM_DATABASE=XBox Device usb:v0738p4576* ID_MODEL_FROM_DATABASE=XBox Device usb:v0738p4586* ID_MODEL_FROM_DATABASE=XBox Device usb:v0738p4588* ID_MODEL_FROM_DATABASE=XBox Device usb:v0738p8818* ID_MODEL_FROM_DATABASE=Street Fighter IV Arcade FightStick (PS3) usb:v073A* ID_VENDOR_FROM_DATABASE=Chaplet Systems, Inc. usb:v073Ap2230* ID_MODEL_FROM_DATABASE=infrared dongle for remote usb:v073B* ID_VENDOR_FROM_DATABASE=Suncom Technologies usb:v073C* ID_VENDOR_FROM_DATABASE=Industrial Electronic Engineers, Inc. usb:v073Cp0305* ID_MODEL_FROM_DATABASE=Pole Display (PC305-3415 2 x 20 Line Display) usb:v073Cp0322* ID_MODEL_FROM_DATABASE=Pole Display (PC322-3415 2 x 20 Line Display) usb:v073Cp0324* ID_MODEL_FROM_DATABASE=Pole Display (LB324-USB 4 x 20 Line Display) usb:v073Cp0330* ID_MODEL_FROM_DATABASE=Pole Display (P330-3415 2 x 20 Line Display) usb:v073Cp0424* ID_MODEL_FROM_DATABASE=Pole Display (SP324-4415 4 x 20 Line Display) usb:v073Cp0450* ID_MODEL_FROM_DATABASE=Pole Display (L450-USB Graphic Line Display) usb:v073Cp0505* ID_MODEL_FROM_DATABASE=Pole Display (SPC505-3415 2 x 20 Line Display) usb:v073Cp0522* ID_MODEL_FROM_DATABASE=Pole Display (SPC522-3415 2 x 20 Line Display) usb:v073Cp0624* ID_MODEL_FROM_DATABASE=Pole Display (SP324-3415 4 x 20 Line Display) usb:v073D* ID_VENDOR_FROM_DATABASE=Eutron S.p.a. usb:v073Dp0005* ID_MODEL_FROM_DATABASE=Crypto Token usb:v073Dp0007* ID_MODEL_FROM_DATABASE=CryptoIdentity CCID usb:v073Dp0025* ID_MODEL_FROM_DATABASE=SmartKey 3 usb:v073Dp0C00* ID_MODEL_FROM_DATABASE=Pocket Reader usb:v073Dp0D00* ID_MODEL_FROM_DATABASE=StarSign Bio Token 3.0 EU usb:v073E* ID_VENDOR_FROM_DATABASE=NEC, Inc. usb:v073Ep0301* ID_MODEL_FROM_DATABASE=Game Pad usb:v0742* ID_VENDOR_FROM_DATABASE=Stollmann usb:v0742p2008* ID_MODEL_FROM_DATABASE=ISDN TA [HFC-S] usb:v0742p2009* ID_MODEL_FROM_DATABASE=ISDN TA [HFC-S] usb:v0742p200A* ID_MODEL_FROM_DATABASE=ISDN TA [HFC-S] usb:v0745* ID_VENDOR_FROM_DATABASE=Syntech Information Co., Ltd usb:v0746* ID_VENDOR_FROM_DATABASE=Onkyo Corp. usb:v0746p5500* ID_MODEL_FROM_DATABASE=SE-U55 Audio Device usb:v0747* ID_VENDOR_FROM_DATABASE=Labway Corp. usb:v0748* ID_VENDOR_FROM_DATABASE=Strong Man Enterprise Co., Ltd usb:v0749* ID_VENDOR_FROM_DATABASE=EVer Electronics Corp. usb:v074A* ID_VENDOR_FROM_DATABASE=Ming Fortune Industry Co., Ltd usb:v074B* ID_VENDOR_FROM_DATABASE=Polestar Tech. Corp. usb:v074C* ID_VENDOR_FROM_DATABASE=C-C-C Group PLC usb:v074D* ID_VENDOR_FROM_DATABASE=Micronas GmbH usb:v074Dp3553* ID_MODEL_FROM_DATABASE=Composite USB-Device usb:v074Dp3554* ID_MODEL_FROM_DATABASE=Composite USB-Device usb:v074Dp3556* ID_MODEL_FROM_DATABASE=Composite USB-Device usb:v074E* ID_VENDOR_FROM_DATABASE=Digital Stream Corp. usb:v074Ep0001* ID_MODEL_FROM_DATABASE=PS/2 Adapter usb:v074Ep0002* ID_MODEL_FROM_DATABASE=PS/2 Adapter usb:v0755* ID_VENDOR_FROM_DATABASE=Aureal Semiconductor usb:v0757* ID_VENDOR_FROM_DATABASE=Network Technologies, Inc. usb:v075B* ID_VENDOR_FROM_DATABASE=Sophisticated Circuits, Inc. usb:v075Bp0001* ID_MODEL_FROM_DATABASE=Kick-off! Watchdog usb:v0763* ID_VENDOR_FROM_DATABASE=Midiman usb:v0763p0115* ID_MODEL_FROM_DATABASE=O2 / KeyRig 25 usb:v0763p0117* ID_MODEL_FROM_DATABASE=Trigger Finger usb:v0763p0119* ID_MODEL_FROM_DATABASE=MidAir usb:v0763p0150* ID_MODEL_FROM_DATABASE=M-Audio Uno usb:v0763p0160* ID_MODEL_FROM_DATABASE=M-Audio 1x1 usb:v0763p0192* ID_MODEL_FROM_DATABASE=M-Audio Keystation 88es usb:v0763p0193* ID_MODEL_FROM_DATABASE=ProKeys 88 usb:v0763p0194* ID_MODEL_FROM_DATABASE=ProKeys 88sx usb:v0763p0195* ID_MODEL_FROM_DATABASE=Oxygen 8 v2 usb:v0763p0196* ID_MODEL_FROM_DATABASE=Oxygen 49 usb:v0763p0197* ID_MODEL_FROM_DATABASE=Oxygen 61 usb:v0763p0198* ID_MODEL_FROM_DATABASE=Axiom 25 usb:v0763p0199* ID_MODEL_FROM_DATABASE=Axiom 49 usb:v0763p019A* ID_MODEL_FROM_DATABASE=Axiom 61 usb:v0763p019B* ID_MODEL_FROM_DATABASE=KeyRig 49 usb:v0763p019C* ID_MODEL_FROM_DATABASE=KeyStudio usb:v0763p1001* ID_MODEL_FROM_DATABASE=MidiSport 2x2 usb:v0763p1002* ID_MODEL_FROM_DATABASE=MidiSport 2x2 usb:v0763p1003* ID_MODEL_FROM_DATABASE=MidiSport 2x2 usb:v0763p1010* ID_MODEL_FROM_DATABASE=MidiSport 1x1 usb:v0763p1011* ID_MODEL_FROM_DATABASE=MidiSport 1x1 usb:v0763p1014* ID_MODEL_FROM_DATABASE=M-Audio Keystation Loader usb:v0763p1015* ID_MODEL_FROM_DATABASE=M-Audio Keystation usb:v0763p1020* ID_MODEL_FROM_DATABASE=Midisport 4x4 usb:v0763p1021* ID_MODEL_FROM_DATABASE=MidiSport 4x4 usb:v0763p1030* ID_MODEL_FROM_DATABASE=Midisport 8x8 usb:v0763p1031* ID_MODEL_FROM_DATABASE=MidiSport 8x8/s Loader usb:v0763p1033* ID_MODEL_FROM_DATABASE=MidiSport 8x8/s usb:v0763p1040* ID_MODEL_FROM_DATABASE=M-Audio MidiSport 2x4 Loader usb:v0763p1041* ID_MODEL_FROM_DATABASE=M-Audio MidiSport 2x4 usb:v0763p1110* ID_MODEL_FROM_DATABASE=MidiSport 1x1 usb:v0763p2001* ID_MODEL_FROM_DATABASE=M Audio Quattro usb:v0763p2002* ID_MODEL_FROM_DATABASE=M Audio Duo usb:v0763p2003* ID_MODEL_FROM_DATABASE=M Audio AudioPhile usb:v0763p2004* ID_MODEL_FROM_DATABASE=M-Audio MobilePre usb:v0763p2006* ID_MODEL_FROM_DATABASE=M-Audio Transit usb:v0763p2007* ID_MODEL_FROM_DATABASE=M-Audio Sonica Theater usb:v0763p2008* ID_MODEL_FROM_DATABASE=M-Audio Ozone usb:v0763p200D* ID_MODEL_FROM_DATABASE=M-Audio OmniStudio usb:v0763p200F* ID_MODEL_FROM_DATABASE=M-Audio MobilePre usb:v0763p2010* ID_MODEL_FROM_DATABASE=M-Audio Fast Track usb:v0763p2012* ID_MODEL_FROM_DATABASE=M-Audio Fast Track Pro usb:v0763p2013* ID_MODEL_FROM_DATABASE=M-Audio JamLab usb:v0763p2015* ID_MODEL_FROM_DATABASE=M-Audio RunTime DFU usb:v0763p2016* ID_MODEL_FROM_DATABASE=M-Audio RunTime DFU usb:v0763p2019* ID_MODEL_FROM_DATABASE=M-Audio Ozone Academic usb:v0763p201A* ID_MODEL_FROM_DATABASE=M-Audio Micro usb:v0763p201B* ID_MODEL_FROM_DATABASE=M-Audio RunTime DFU usb:v0763p201D* ID_MODEL_FROM_DATABASE=M-Audio Producer usb:v0763p2024* ID_MODEL_FROM_DATABASE=M-Audio Fast Track MKII usb:v0763p2080* ID_MODEL_FROM_DATABASE=M-Audio RunTime DFU usb:v0763p2081* ID_MODEL_FROM_DATABASE=M-Audio RunTime DFU / Fast Track Ultra 8R usb:v0763p2803* ID_MODEL_FROM_DATABASE=M-Audio Audiophile DFU usb:v0763p2804* ID_MODEL_FROM_DATABASE=M-Audio MobilePre DFU usb:v0763p2806* ID_MODEL_FROM_DATABASE=M-Audio Transit DFU usb:v0763p2815* ID_MODEL_FROM_DATABASE=M-Audio DFU usb:v0763p2816* ID_MODEL_FROM_DATABASE=M-Audio DFU usb:v0763p281B* ID_MODEL_FROM_DATABASE=M-Audio DFU usb:v0763p2880* ID_MODEL_FROM_DATABASE=M-Audio DFU usb:v0763p2881* ID_MODEL_FROM_DATABASE=M-Audio DFU usb:v0764* ID_VENDOR_FROM_DATABASE=Cyber Power System, Inc. usb:v0764p0005* ID_MODEL_FROM_DATABASE=Cyber Power UPS usb:v0764p0501* ID_MODEL_FROM_DATABASE=CP1500 AVR UPS usb:v0764p0601* ID_MODEL_FROM_DATABASE=PR1500LCDRT2U UPS usb:v0765* ID_VENDOR_FROM_DATABASE=X-Rite, Inc. usb:v0765p5001* ID_MODEL_FROM_DATABASE=Huey PRO Colorimeter usb:v0765p5020* ID_MODEL_FROM_DATABASE=i1 Display Pro usb:v0765p6003* ID_MODEL_FROM_DATABASE=ColorMunki Smile usb:v0765pD094* ID_MODEL_FROM_DATABASE=X-Rite DTP94 [Quato Silver Haze Pro] usb:v0766* ID_VENDOR_FROM_DATABASE=Jess-Link Products Co., Ltd usb:v0766p001B* ID_MODEL_FROM_DATABASE=Packard Bell Go usb:v0766p0204* ID_MODEL_FROM_DATABASE=TopSpeed Cyberlink Remote Control usb:v0767* ID_VENDOR_FROM_DATABASE=Tokheim Corp. usb:v0768* ID_VENDOR_FROM_DATABASE=Camtel Technology Corp. usb:v0768p0006* ID_MODEL_FROM_DATABASE=Camtel Technology USB TV Genie Pro FM Model TVB330 usb:v0768p0023* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v0769* ID_VENDOR_FROM_DATABASE=Surecom Technology Corp. usb:v0769p11F2* ID_MODEL_FROM_DATABASE=EP-9001-g 802.11g 54M WLAN Adapter usb:v0769p11F3* ID_MODEL_FROM_DATABASE=RT2570 usb:v0769p11F7* ID_MODEL_FROM_DATABASE=802.11g 54M WLAN Adapter usb:v0769p31F3* ID_MODEL_FROM_DATABASE=RT2573 usb:v076A* ID_VENDOR_FROM_DATABASE=Smart Technology Enablers, Inc. usb:v076B* ID_VENDOR_FROM_DATABASE=OmniKey AG usb:v076Bp0596* ID_MODEL_FROM_DATABASE=CardMan 2020 usb:v076Bp1021* ID_MODEL_FROM_DATABASE=CardMan 1021 usb:v076Bp1221* ID_MODEL_FROM_DATABASE=CardMan 1221 usb:v076Bp1784* ID_MODEL_FROM_DATABASE=CardMan 6020 usb:v076Bp3021* ID_MODEL_FROM_DATABASE=CardMan 3121 usb:v076Bp3022* ID_MODEL_FROM_DATABASE=CardMan 3021 usb:v076Bp3610* ID_MODEL_FROM_DATABASE=CardMan 3620 usb:v076Bp3621* ID_MODEL_FROM_DATABASE=CardMan 3621 usb:v076Bp3821* ID_MODEL_FROM_DATABASE=CardMan 3821 usb:v076Bp4321* ID_MODEL_FROM_DATABASE=CardMan 4321 usb:v076Bp5121* ID_MODEL_FROM_DATABASE=CardMan 5121 usb:v076Bp5125* ID_MODEL_FROM_DATABASE=CardMan 5125 usb:v076Bp5321* ID_MODEL_FROM_DATABASE=CardMan 5321 usb:v076Bp5340* ID_MODEL_FROM_DATABASE=CardMan 5021 CL usb:v076Bp6622* ID_MODEL_FROM_DATABASE=CardMan 6121 usb:v076BpA011* ID_MODEL_FROM_DATABASE=CCID Smart Card Reader Keyboard usb:v076BpA021* ID_MODEL_FROM_DATABASE=CCID Smart Card Reader usb:v076BpA022* ID_MODEL_FROM_DATABASE=CardMan Smart@Link usb:v076BpC000* ID_MODEL_FROM_DATABASE=CardMan 3x21 CS usb:v076BpC001* ID_MODEL_FROM_DATABASE=CardMan 5121 CS usb:v076C* ID_VENDOR_FROM_DATABASE=Partner Tech usb:v076D* ID_VENDOR_FROM_DATABASE=Denso Corp. usb:v076E* ID_VENDOR_FROM_DATABASE=Kuan Tech Enterprise Co., Ltd usb:v076F* ID_VENDOR_FROM_DATABASE=Jhen Vei Electronic Co., Ltd usb:v0770* ID_VENDOR_FROM_DATABASE=Welch Allyn, Inc - Medical Division usb:v0771* ID_VENDOR_FROM_DATABASE=Observator Instruments BV usb:v0771p4455* ID_MODEL_FROM_DATABASE=OMC45III usb:v0771pAE0F* ID_MODEL_FROM_DATABASE=OMC45III usb:v0772* ID_VENDOR_FROM_DATABASE=Your data Our Care usb:v0774* ID_VENDOR_FROM_DATABASE=AmTRAN Technology Co., Ltd usb:v0775* ID_VENDOR_FROM_DATABASE=Longshine Electronics Corp. usb:v0776* ID_VENDOR_FROM_DATABASE=Inalways Corp. usb:v0777* ID_VENDOR_FROM_DATABASE=Comda Enterprise Corp. usb:v0778* ID_VENDOR_FROM_DATABASE=Volex, Inc. usb:v0779* ID_VENDOR_FROM_DATABASE=Fairchild Semiconductor usb:v077A* ID_VENDOR_FROM_DATABASE=Sankyo Seiki Mfg. Co., Ltd usb:v077B* ID_VENDOR_FROM_DATABASE=Linksys usb:v077Bp08BE* ID_MODEL_FROM_DATABASE=BEFCMU10 v4 Cable Modem usb:v077Bp2219* ID_MODEL_FROM_DATABASE=WUSB11 V2.6 802.11b Adapter usb:v077Bp2226* ID_MODEL_FROM_DATABASE=USB200M 100baseTX Adapter usb:v077Bp2227* ID_MODEL_FROM_DATABASE=Network Everywhere NWU11B usb:v077C* ID_VENDOR_FROM_DATABASE=Forward Electronics Co., Ltd usb:v077Cp0005* ID_MODEL_FROM_DATABASE=NEC Keyboard usb:v077D* ID_VENDOR_FROM_DATABASE=Griffin Technology usb:v077Dp0223* ID_MODEL_FROM_DATABASE=IMic Audio In/Out usb:v077Dp0405* ID_MODEL_FROM_DATABASE=iMate, ADB Adapter usb:v077Dp0410* ID_MODEL_FROM_DATABASE=PowerMate usb:v077Dp041A* ID_MODEL_FROM_DATABASE=PowerWave usb:v077Dp04AA* ID_MODEL_FROM_DATABASE=SoundKnob usb:v077Dp07AF* ID_MODEL_FROM_DATABASE=iMic usb:v077Dp1016* ID_MODEL_FROM_DATABASE=AirClick usb:v077Dp627A* ID_MODEL_FROM_DATABASE=Radio SHARK usb:v077F* ID_VENDOR_FROM_DATABASE=Well Excellent & Most Corp. usb:v0780* ID_VENDOR_FROM_DATABASE=Sagem Monetel GmbH usb:v0780p1202* ID_MODEL_FROM_DATABASE=ORGA 900 Smart Card Terminal Virtual Com Port usb:v0780p1302* ID_MODEL_FROM_DATABASE=ORGA 6000 Smart Card Terminal Virtual Com Port usb:v0780p1303* ID_MODEL_FROM_DATABASE=ORGA 6000 Smart Card Terminal USB RNDIS usb:v0780pDF55* ID_MODEL_FROM_DATABASE=ORGA 900/6000 Smart Card Terminal DFU usb:v0781* ID_VENDOR_FROM_DATABASE=SanDisk Corp. usb:v0781p0001* ID_MODEL_FROM_DATABASE=SDDR-05a ImageMate CompactFlash Reader usb:v0781p0002* ID_MODEL_FROM_DATABASE=SDDR-31 ImageMate II CompactFlash Reader usb:v0781p0005* ID_MODEL_FROM_DATABASE=SDDR-05b (CF II) ImageMate CompactFlash Reader usb:v0781p0100* ID_MODEL_FROM_DATABASE=ImageMate SDDR-12 usb:v0781p0200* ID_MODEL_FROM_DATABASE=SDDR-09 (SSFDC) ImageMate SmartMedia Reader [eusb] usb:v0781p0400* ID_MODEL_FROM_DATABASE=SecureMate SD/MMC Reader usb:v0781p0621* ID_MODEL_FROM_DATABASE=SDDR-86 Imagemate 6-in-1 Reader usb:v0781p0720* ID_MODEL_FROM_DATABASE=Sansa C200 series in recovery mode usb:v0781p0729* ID_MODEL_FROM_DATABASE=Sansa E200 series in recovery mode usb:v0781p0810* ID_MODEL_FROM_DATABASE=SDDR-75 ImageMate CF-SM Reader usb:v0781p0830* ID_MODEL_FROM_DATABASE=ImageMate CF/MMC/SD Reader usb:v0781p1234* ID_MODEL_FROM_DATABASE=Cruzer Mini Flash Drive usb:v0781p5150* ID_MODEL_FROM_DATABASE=SDCZ2 Cruzer Mini Flash Drive (thin) usb:v0781p5151* ID_MODEL_FROM_DATABASE=Cruzer Micro Flash Drive usb:v0781p5153* ID_MODEL_FROM_DATABASE=Cruzer Flash Drive usb:v0781p5204* ID_MODEL_FROM_DATABASE=Cruzer Crossfire usb:v0781p5402* ID_MODEL_FROM_DATABASE=U3 Cruzer Micro usb:v0781p5406* ID_MODEL_FROM_DATABASE=Cruzer Micro U3 usb:v0781p5408* ID_MODEL_FROM_DATABASE=Cruzer Titanium U3 usb:v0781p540E* ID_MODEL_FROM_DATABASE=Cruzer Contour Flash Drive usb:v0781p5530* ID_MODEL_FROM_DATABASE=Cruzer usb:v0781p5567* ID_MODEL_FROM_DATABASE=Cruzer Blade usb:v0781p556C* ID_MODEL_FROM_DATABASE=Ultra usb:v0781p556D* ID_MODEL_FROM_DATABASE=Memory Vault usb:v0781p5571* ID_MODEL_FROM_DATABASE=Cruzer Fit usb:v0781p5576* ID_MODEL_FROM_DATABASE=Cruzer Facet usb:v0781p557D* ID_MODEL_FROM_DATABASE=Cruzer Force (64GB) usb:v0781p5580* ID_MODEL_FROM_DATABASE=SDCZ80 Flash Drive usb:v0781p5581* ID_MODEL_FROM_DATABASE=Ultra usb:v0781p5E10* ID_MODEL_FROM_DATABASE=Encrypted usb:v0781p6100* ID_MODEL_FROM_DATABASE=Ultra II SD Plus 2GB usb:v0781p7100* ID_MODEL_FROM_DATABASE=Cruzer Mini usb:v0781p7101* ID_MODEL_FROM_DATABASE=Pen Flash usb:v0781p7102* ID_MODEL_FROM_DATABASE=Cruzer Mini usb:v0781p7103* ID_MODEL_FROM_DATABASE=Cruzer Mini usb:v0781p7104* ID_MODEL_FROM_DATABASE=Cruzer Micro Mini 256MB Flash Drive usb:v0781p7105* ID_MODEL_FROM_DATABASE=Cruzer Mini usb:v0781p7106* ID_MODEL_FROM_DATABASE=Cruzer Mini usb:v0781p7112* ID_MODEL_FROM_DATABASE=Cruzer Micro 128MB Flash Drive usb:v0781p7113* ID_MODEL_FROM_DATABASE=Cruzer Micro 256MB Flash Drive usb:v0781p7114* ID_MODEL_FROM_DATABASE=Cruzer Mini usb:v0781p7115* ID_MODEL_FROM_DATABASE=Cruzer Mini usb:v0781p7301* ID_MODEL_FROM_DATABASE=Sansa e100 series (mtp) usb:v0781p7302* ID_MODEL_FROM_DATABASE=Sansa e100 series (msc) usb:v0781p7400* ID_MODEL_FROM_DATABASE=Sansa M200 series (mtp) usb:v0781p7401* ID_MODEL_FROM_DATABASE=Sansa M200 series (msc) usb:v0781p7420* ID_MODEL_FROM_DATABASE=Sansa E200 series (mtp) usb:v0781p7421* ID_MODEL_FROM_DATABASE=Sansa E200 Series (msc) usb:v0781p7422* ID_MODEL_FROM_DATABASE=Sansa E200 series v2 (mtp) usb:v0781p7423* ID_MODEL_FROM_DATABASE=Sansa E200 series v2 (msc) usb:v0781p7430* ID_MODEL_FROM_DATABASE=Sansa M200 series usb:v0781p7431* ID_MODEL_FROM_DATABASE=Sansa M200 series V4 (msc) usb:v0781p7432* ID_MODEL_FROM_DATABASE=Sansa Clip (mtp) usb:v0781p7433* ID_MODEL_FROM_DATABASE=Sansa Clip (msc) usb:v0781p7434* ID_MODEL_FROM_DATABASE=Sansa Clip V2 (mtp) usb:v0781p7435* ID_MODEL_FROM_DATABASE=Sansa Clip V2 (msc) usb:v0781p7450* ID_MODEL_FROM_DATABASE=Sansa C250 usb:v0781p7451* ID_MODEL_FROM_DATABASE=Sansa C240 usb:v0781p7460* ID_MODEL_FROM_DATABASE=Sansa Express usb:v0781p7480* ID_MODEL_FROM_DATABASE=Sansa Connect usb:v0781p7481* ID_MODEL_FROM_DATABASE=Sansa Connect (in recovery mode) usb:v0781p74B0* ID_MODEL_FROM_DATABASE=Sansa View (msc) usb:v0781p74B1* ID_MODEL_FROM_DATABASE=Sansa View (mtp) usb:v0781p74C0* ID_MODEL_FROM_DATABASE=Sansa Fuze (mtp) usb:v0781p74C1* ID_MODEL_FROM_DATABASE=Sansa Fuze (msc) usb:v0781p74C2* ID_MODEL_FROM_DATABASE=Sansa Fuze V2 (mtp) usb:v0781p74C3* ID_MODEL_FROM_DATABASE=Sansa Fuze V2 (msc) usb:v0781p74D0* ID_MODEL_FROM_DATABASE=Sansa Clip+ (mtp) usb:v0781p74D1* ID_MODEL_FROM_DATABASE=Sansa Clip+ (msc) usb:v0781p74E5* ID_MODEL_FROM_DATABASE=Sansa Clip Zip usb:v0781p8181* ID_MODEL_FROM_DATABASE=Pen Flash usb:v0781p8183* ID_MODEL_FROM_DATABASE=Hi-Speed Mass Storage Device usb:v0781p8185* ID_MODEL_FROM_DATABASE=SDCZ2 Cruzer Mini Flash Drive (older, thick) usb:v0781p8888* ID_MODEL_FROM_DATABASE=Card Reader usb:v0781p8889* ID_MODEL_FROM_DATABASE=SDDR-88 Imagemate 8-in-1 Reader usb:v0781p8919* ID_MODEL_FROM_DATABASE=Card Reader usb:v0781p8989* ID_MODEL_FROM_DATABASE=ImageMate 12-in-1 Reader usb:v0781p9191* ID_MODEL_FROM_DATABASE=ImageMate CF usb:v0781p9219* ID_MODEL_FROM_DATABASE=Card Reader usb:v0781p9292* ID_MODEL_FROM_DATABASE=ImageMate CF Reader/Writer usb:v0781p9393* ID_MODEL_FROM_DATABASE=ImageMate SD-MMC usb:v0781p9595* ID_MODEL_FROM_DATABASE=ImageMate xD-SM usb:v0781p9797* ID_MODEL_FROM_DATABASE=ImageMate MS-PRO usb:v0781p9919* ID_MODEL_FROM_DATABASE=Card Reader usb:v0781p9999* ID_MODEL_FROM_DATABASE=SDDR-99 5-in-1 Reader usb:v0781pA7C1* ID_MODEL_FROM_DATABASE=Storage device (SD card reader) usb:v0781pA7E8* ID_MODEL_FROM_DATABASE=SDDR-113 MicroMate SDHC Reader usb:v0781pB2B3* ID_MODEL_FROM_DATABASE=SDDR-103 MobileMate SD+ Reader usb:v0781pB4B5* ID_MODEL_FROM_DATABASE=SDDR-89 V4 ImageMate 12-in-1 Reader usb:v0782* ID_VENDOR_FROM_DATABASE=Trackerball usb:v0783* ID_VENDOR_FROM_DATABASE=C3PO usb:v0783p0003* ID_MODEL_FROM_DATABASE=LTC31 SmartCard Reader usb:v0783p0006* ID_MODEL_FROM_DATABASE=LTC31v2 usb:v0783p0009* ID_MODEL_FROM_DATABASE=KBR36 usb:v0783p0010* ID_MODEL_FROM_DATABASE=LTC32 usb:v0784* ID_VENDOR_FROM_DATABASE=Vivitar, Inc. usb:v0784p0100* ID_MODEL_FROM_DATABASE=Vivicam 2655 usb:v0784p1310* ID_MODEL_FROM_DATABASE=Vivicam 3305 usb:v0784p1688* ID_MODEL_FROM_DATABASE=Vivicam 3665 usb:v0784p1689* ID_MODEL_FROM_DATABASE=Gateway DC-M42/Labtec DC-505/Vivitar Vivicam 3705 usb:v0784p2620* ID_MODEL_FROM_DATABASE=AOL Photocam Plus usb:v0784p2888* ID_MODEL_FROM_DATABASE=Polaroid DC700 usb:v0784p3330* ID_MODEL_FROM_DATABASE=Nytec ND-3200 Camera usb:v0784p4300* ID_MODEL_FROM_DATABASE=Traveler D1 usb:v0784p5260* ID_MODEL_FROM_DATABASE=Werlisa Sport PX 100 / JVC GC-A33 Camera usb:v0784p5300* ID_MODEL_FROM_DATABASE=Pretec dc530 usb:v0785* ID_VENDOR_FROM_DATABASE=NTT-ME usb:v0785p0001* ID_MODEL_FROM_DATABASE=MN128mini-V ISDN TA usb:v0785p0003* ID_MODEL_FROM_DATABASE=MN128mini-J ISDN TA usb:v0789* ID_VENDOR_FROM_DATABASE=Logitec Corp. usb:v0789p0026* ID_MODEL_FROM_DATABASE=LHD Device usb:v0789p0033* ID_MODEL_FROM_DATABASE=DVD Multi-plus unit LDR-H443SU2 usb:v0789p0063* ID_MODEL_FROM_DATABASE=LDR Device usb:v0789p0064* ID_MODEL_FROM_DATABASE=LDR-R Device usb:v0789p00B3* ID_MODEL_FROM_DATABASE=DVD Multi-plus unit LDR-H443U2 usb:v0789p0105* ID_MODEL_FROM_DATABASE=LAN-TX/U1H2 10/100 Ethernet Adapter [pegasus II] usb:v0789p010C* ID_MODEL_FROM_DATABASE=Realtek RTL8187 Wireless 802.11g 54Mbps Network Adapter usb:v0789p0160* ID_MODEL_FROM_DATABASE=LAN-GTJ/U2A usb:v0789p0162* ID_MODEL_FROM_DATABASE=LAN-WN22/U2 Wireless LAN Adapter usb:v0789p0163* ID_MODEL_FROM_DATABASE=LAN-WN12/U2 Wireless LAN Adapter usb:v0789p0164* ID_MODEL_FROM_DATABASE=LAN-W150/U2M Wireless LAN Adapter usb:v0789p0166* ID_MODEL_FROM_DATABASE=LAN-W300N/U2 Wireless LAN Adapter usb:v0789p0168* ID_MODEL_FROM_DATABASE=LAN-W150N/U2 Wireless LAN Adapter usb:v0789p0170* ID_MODEL_FROM_DATABASE=LAN-W300AN/U2 Wireless LAN Adapter usb:v078B* ID_VENDOR_FROM_DATABASE=Happ Controls, Inc. usb:v078Bp0010* ID_MODEL_FROM_DATABASE=Driving UGCI usb:v078Bp0020* ID_MODEL_FROM_DATABASE=Flying UGCI usb:v078Bp0030* ID_MODEL_FROM_DATABASE=Fighting UGCI usb:v078C* ID_VENDOR_FROM_DATABASE=GTCO/CalComp usb:v078Cp0090* ID_MODEL_FROM_DATABASE=Tablet Adapter usb:v078Cp0100* ID_MODEL_FROM_DATABASE=Tablet Adapter usb:v078Cp0200* ID_MODEL_FROM_DATABASE=Tablet Adapter usb:v078Cp0300* ID_MODEL_FROM_DATABASE=Tablet Adapter usb:v078Cp0400* ID_MODEL_FROM_DATABASE=Digitizer (Whiteboard) usb:v078E* ID_VENDOR_FROM_DATABASE=Brincom, Inc. usb:v0790* ID_VENDOR_FROM_DATABASE=Pro-Image Manufacturing Co., Ltd usb:v0791* ID_VENDOR_FROM_DATABASE=Copartner Wire and Cable Mfg. Corp. usb:v0792* ID_VENDOR_FROM_DATABASE=Axis Communications AB usb:v0793* ID_VENDOR_FROM_DATABASE=Wha Yu Industrial Co., Ltd usb:v0794* ID_VENDOR_FROM_DATABASE=ABL Electronics Corp. usb:v0795* ID_VENDOR_FROM_DATABASE=RealChip, Inc. usb:v0796* ID_VENDOR_FROM_DATABASE=Certicom Corp. usb:v0797* ID_VENDOR_FROM_DATABASE=Grandtech Semiconductor Corp. usb:v0797p6801* ID_MODEL_FROM_DATABASE=Flatbed Scanner usb:v0797p6802* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v0797p8001* ID_MODEL_FROM_DATABASE=SmartCam usb:v0797p801A* ID_MODEL_FROM_DATABASE=Typhoon StyloCam usb:v0797p801C* ID_MODEL_FROM_DATABASE=Meade Binoculars/Camera usb:v0797p8901* ID_MODEL_FROM_DATABASE=ScanHex SX-35a usb:v0797p8909* ID_MODEL_FROM_DATABASE=ScanHex SX-35b usb:v0797p8911* ID_MODEL_FROM_DATABASE=ScanHex SX-35c usb:v0798* ID_VENDOR_FROM_DATABASE=Optelec usb:v0798p0001* ID_MODEL_FROM_DATABASE=Braille Voyager usb:v0798p0640* ID_MODEL_FROM_DATABASE=BC640 usb:v0798p0680* ID_MODEL_FROM_DATABASE=BC680 usb:v0799* ID_VENDOR_FROM_DATABASE=Altera usb:v0799p7651* ID_MODEL_FROM_DATABASE=Programming Unit usb:v079B* ID_VENDOR_FROM_DATABASE=Sagem usb:v079Bp0024* ID_MODEL_FROM_DATABASE=MSO300/MSO301 Fingerprint Sensor usb:v079Bp0026* ID_MODEL_FROM_DATABASE=MSO350/MSO351 Fingerprint Sensor & SmartCard Reader usb:v079Bp0027* ID_MODEL_FROM_DATABASE=USB-Serial Controller usb:v079Bp002F* ID_MODEL_FROM_DATABASE=Mobile usb:v079Bp0030* ID_MODEL_FROM_DATABASE=Mobile Communication Device usb:v079Bp0042* ID_MODEL_FROM_DATABASE=Mobile usb:v079Bp0047* ID_MODEL_FROM_DATABASE=CBM/MSO1300 Fingerprint Sensor usb:v079Bp004A* ID_MODEL_FROM_DATABASE=XG-760A 802.11bg usb:v079Bp004B* ID_MODEL_FROM_DATABASE=Wi-Fi 11g adapter usb:v079Bp0052* ID_MODEL_FROM_DATABASE=MSO1350 Fingerprint Sensor & SmartCard Reader usb:v079Bp0056* ID_MODEL_FROM_DATABASE=Agfa AP1100 Photo Printer usb:v079Bp005D* ID_MODEL_FROM_DATABASE=Mobile Mass Storage usb:v079Bp0062* ID_MODEL_FROM_DATABASE=XG-76NA 802.11bg usb:v079Bp0078* ID_MODEL_FROM_DATABASE=Laser Pro Monochrome MFP usb:v079D* ID_VENDOR_FROM_DATABASE=Alfadata Computer Corp. usb:v079Dp0201* ID_MODEL_FROM_DATABASE=GamePort Adapter usb:v07A1* ID_VENDOR_FROM_DATABASE=Digicom S.p.A. usb:v07A1pD952* ID_MODEL_FROM_DATABASE=Palladio USB V.92 Modem usb:v07A2* ID_VENDOR_FROM_DATABASE=National Technical Systems usb:v07A3* ID_VENDOR_FROM_DATABASE=Onnto Corp. usb:v07A4* ID_VENDOR_FROM_DATABASE=Be, Inc. usb:v07A6* ID_VENDOR_FROM_DATABASE=ADMtek, Inc. usb:v07A6p07C2* ID_MODEL_FROM_DATABASE=AN986A Ethernet usb:v07A6p0986* ID_MODEL_FROM_DATABASE=AN986 Pegasus Ethernet usb:v07A6p8266* ID_MODEL_FROM_DATABASE=Infineon WildCard-USB Wireless LAN Adapter usb:v07A6p8511* ID_MODEL_FROM_DATABASE=ADM8511 Pegasus II Ethernet usb:v07A6p8513* ID_MODEL_FROM_DATABASE=AN8513 Ethernet usb:v07A6p8515* ID_MODEL_FROM_DATABASE=AN8515 Ethernet usb:v07AA* ID_VENDOR_FROM_DATABASE=Corega K.K. usb:v07AAp0001* ID_MODEL_FROM_DATABASE=Ether USB-T Ethernet [klsi] usb:v07AAp0004* ID_MODEL_FROM_DATABASE=FEther USB-TX Ethernet [pegasus] usb:v07AAp000C* ID_MODEL_FROM_DATABASE=WirelessLAN USB-11 usb:v07AAp000D* ID_MODEL_FROM_DATABASE=FEther USB-TXS usb:v07AAp0011* ID_MODEL_FROM_DATABASE=Wireless LAN USB-11 mini usb:v07AAp0012* ID_MODEL_FROM_DATABASE=Stick-11 802.11b Adapter usb:v07AAp0017* ID_MODEL_FROM_DATABASE=FEther USB2-TX usb:v07AAp0018* ID_MODEL_FROM_DATABASE=Wireless LAN USB-11 mini 2 usb:v07AAp001A* ID_MODEL_FROM_DATABASE=ULUSB-11 Key usb:v07AAp001C* ID_MODEL_FROM_DATABASE=CG-WLUSB2GT 802.11g Wireless Adapter [Intersil ISL3880] usb:v07AAp0020* ID_MODEL_FROM_DATABASE=CG-WLUSB2GTST 802.11g Wireless Adapter [Intersil ISL3887] usb:v07AAp002E* ID_MODEL_FROM_DATABASE=CG-WLUSB2GPX [Ralink RT2571W] usb:v07AAp002F* ID_MODEL_FROM_DATABASE=CG-WLUSB2GNL usb:v07AAp0031* ID_MODEL_FROM_DATABASE=CG-WLUSB2GS 802.11bg [Atheros AR5523] usb:v07AAp003C* ID_MODEL_FROM_DATABASE=CG-WLUSB2GNL usb:v07AAp003F* ID_MODEL_FROM_DATABASE=CG-WLUSB300AGN usb:v07AAp0041* ID_MODEL_FROM_DATABASE=CG-WLUSB300GNS usb:v07AAp0042* ID_MODEL_FROM_DATABASE=CG-WLUSB300GNM usb:v07AAp0043* ID_MODEL_FROM_DATABASE=CG-WLUSB300N rev A2 [Realtek RTL8192U] usb:v07AAp0047* ID_MODEL_FROM_DATABASE=CG-WLUSBNM usb:v07AAp0051* ID_MODEL_FROM_DATABASE=CG-WLUSB300NM usb:v07AAp7613* ID_MODEL_FROM_DATABASE=Stick-11 V2 802.11b Adapter usb:v07AAp9601* ID_MODEL_FROM_DATABASE=FEther USB-TXC usb:v07AB* ID_VENDOR_FROM_DATABASE=Freecom Technologies usb:v07ABpFC01* ID_MODEL_FROM_DATABASE=IDE bridge usb:v07ABpFC02* ID_MODEL_FROM_DATABASE=Cable II USB-2 usb:v07ABpFC03* ID_MODEL_FROM_DATABASE=USB2-IDE IDE bridge usb:v07ABpFCD6* ID_MODEL_FROM_DATABASE=Freecom HD Classic usb:v07ABpFCF6* ID_MODEL_FROM_DATABASE=DataBar usb:v07ABpFCF8* ID_MODEL_FROM_DATABASE=Freecom Classic SL Network Drive usb:v07ABpFCFE* ID_MODEL_FROM_DATABASE=Hard Drive 80GB usb:v07AF* ID_VENDOR_FROM_DATABASE=Microtech usb:v07AFp0004* ID_MODEL_FROM_DATABASE=SCSI-DB25 SCSI Bridge [shuttle] usb:v07AFp0005* ID_MODEL_FROM_DATABASE=SCSI-HD50 SCSI Bridge [shuttle] usb:v07AFp0006* ID_MODEL_FROM_DATABASE=CameraMate SmartMedia and CompactFlash Card Reader [eusb/shuttle] usb:v07AFpFC01* ID_MODEL_FROM_DATABASE=Freecom USB-IDE usb:v07B0* ID_VENDOR_FROM_DATABASE=Trust Technologies usb:v07B0p0001* ID_MODEL_FROM_DATABASE=ISDN TA usb:v07B0p0002* ID_MODEL_FROM_DATABASE=ISDN TA128 Plus usb:v07B0p0003* ID_MODEL_FROM_DATABASE=ISDN TA128 Deluxe usb:v07B0p0005* ID_MODEL_FROM_DATABASE=ISDN TA128 SE usb:v07B0p0006* ID_MODEL_FROM_DATABASE=ISDN TA 128 [HFC-S] usb:v07B0p0007* ID_MODEL_FROM_DATABASE=ISDN TA [HFC-S] usb:v07B0p0008* ID_MODEL_FROM_DATABASE=ISDN TA usb:v07B1* ID_VENDOR_FROM_DATABASE=IMP, Inc. usb:v07B2* ID_VENDOR_FROM_DATABASE=Motorola BCS, Inc. usb:v07B2p0100* ID_MODEL_FROM_DATABASE=SURFboard Voice over IP Cable Modem usb:v07B2p0900* ID_MODEL_FROM_DATABASE=SURFboard Gateway usb:v07B2p0950* ID_MODEL_FROM_DATABASE=SURFboard SBG950 Gateway usb:v07B2p1000* ID_MODEL_FROM_DATABASE=SURFboard SBG1000 Gateway usb:v07B2p4100* ID_MODEL_FROM_DATABASE=SurfBoard SB4100 Cable Modem usb:v07B2p4200* ID_MODEL_FROM_DATABASE=SurfBoard SB4200 Cable Modem usb:v07B2p4210* ID_MODEL_FROM_DATABASE=SurfBoard 4210 Cable Modem usb:v07B2p4220* ID_MODEL_FROM_DATABASE=SURFboard SB4220 Cable Modem usb:v07B2p4500* ID_MODEL_FROM_DATABASE=CG4500 Communications Gateway usb:v07B2p450B* ID_MODEL_FROM_DATABASE=CG4501 Communications Gateway usb:v07B2p450E* ID_MODEL_FROM_DATABASE=CG4500E Communications Gateway usb:v07B2p5100* ID_MODEL_FROM_DATABASE=SurfBoard SB5100 Cable Modem usb:v07B2p5101* ID_MODEL_FROM_DATABASE=SurfBoard SB5101 Cable Modem usb:v07B2p5120* ID_MODEL_FROM_DATABASE=SurfBoard SB5120 Cable Modem (RNDIS) usb:v07B2p5121* ID_MODEL_FROM_DATABASE=Surfboard 5121 Cable Modem usb:v07B2p7030* ID_MODEL_FROM_DATABASE=WU830G 802.11bg Wireless Adapter [Envara WiND512] usb:v07B3* ID_VENDOR_FROM_DATABASE=Plustek, Inc. usb:v07B3p0001* ID_MODEL_FROM_DATABASE=OpticPro 1212U Scanner usb:v07B3p0003* ID_MODEL_FROM_DATABASE=Scanner usb:v07B3p0010* ID_MODEL_FROM_DATABASE=OpticPro U12 Scanner usb:v07B3p0011* ID_MODEL_FROM_DATABASE=OpticPro U24 Scanner usb:v07B3p0013* ID_MODEL_FROM_DATABASE=OpticPro UT12 Scanner usb:v07B3p0014* ID_MODEL_FROM_DATABASE=Scanner usb:v07B3p0015* ID_MODEL_FROM_DATABASE=OpticPro U24 Scanner usb:v07B3p0017* ID_MODEL_FROM_DATABASE=OpticPro UT12/16/24 Scanner usb:v07B3p0204* ID_MODEL_FROM_DATABASE=Scanner usb:v07B3p0400* ID_MODEL_FROM_DATABASE=OpticPro 1248U Scanner usb:v07B3p0401* ID_MODEL_FROM_DATABASE=OpticPro 1248U Scanner #2 usb:v07B3p0403* ID_MODEL_FROM_DATABASE=OpticPro U16B Scanner usb:v07B3p0404* ID_MODEL_FROM_DATABASE=Scanner usb:v07B3p0405* ID_MODEL_FROM_DATABASE=A8 Namecard-s Controller usb:v07B3p0406* ID_MODEL_FROM_DATABASE=A8 Namecard-D Controller usb:v07B3p0410* ID_MODEL_FROM_DATABASE=Scanner usb:v07B3p0412* ID_MODEL_FROM_DATABASE=Scanner usb:v07B3p0413* ID_MODEL_FROM_DATABASE=OpticSlim 1200 Scanner usb:v07B3p0601* ID_MODEL_FROM_DATABASE=OpticPro ST24 Scanner usb:v07B3p0800* ID_MODEL_FROM_DATABASE=OpticPro ST48 Scanner usb:v07B3p0900* ID_MODEL_FROM_DATABASE=OpticBook 3600 Scanner usb:v07B3p090C* ID_MODEL_FROM_DATABASE=OpticBook 3600 Plus Scanner usb:v07B3p0A06* ID_MODEL_FROM_DATABASE=TVcam VD100 usb:v07B3p0B00* ID_MODEL_FROM_DATABASE=SmartPhoto F50 usb:v07B3p0C00* ID_MODEL_FROM_DATABASE=OpticPro ST64 Scanner usb:v07B3p0C03* ID_MODEL_FROM_DATABASE=OpticPro ST64+ Scanner usb:v07B3p0C04* ID_MODEL_FROM_DATABASE=Optic Film 7200i scanner usb:v07B3p0C0C* ID_MODEL_FROM_DATABASE=PL806 Scanner usb:v07B3p0C26* ID_MODEL_FROM_DATABASE=OpticBook 4600 Scanner usb:v07B3p0C2B* ID_MODEL_FROM_DATABASE=Mobile Office D428 Scanner usb:v07B3p0E08* ID_MODEL_FROM_DATABASE=OpticBook A300 Scanner usb:v07B3p1300* ID_MODEL_FROM_DATABASE=OpticBook 3800 Scanner usb:v07B3p1301* ID_MODEL_FROM_DATABASE=OpticBook 4800 Scanner usb:v07B4* ID_VENDOR_FROM_DATABASE=Olympus Optical Co., Ltd usb:v07B4p0100* ID_MODEL_FROM_DATABASE=Camedia C-2100/C-3000 Ultra Zoom Camera usb:v07B4p0102* ID_MODEL_FROM_DATABASE=Camedia E-10/C-220/C-50 Camera usb:v07B4p0105* ID_MODEL_FROM_DATABASE=Camedia C-310Z/C-700/C-750UZ/C-755/C-765UZ/C-3040/C-4000/C-5050Z/D-560/C-3020Z Zoom Camera usb:v07B4p0109* ID_MODEL_FROM_DATABASE=C-370Z/C-500Z/D-535Z/X-450 usb:v07B4p010A* ID_MODEL_FROM_DATABASE=MAUSB-10 xD and SmartMedia Card Reader usb:v07B4p0112* ID_MODEL_FROM_DATABASE=MAUSB-100 xD Card Reader usb:v07B4p0113* ID_MODEL_FROM_DATABASE=Mju 500 / Stylus Digital Camera (PTP) usb:v07B4p0114* ID_MODEL_FROM_DATABASE=C-350Z Camera usb:v07B4p0118* ID_MODEL_FROM_DATABASE=Mju Mini Digital/Mju Digital 500 Camera / Stylus 850 SW usb:v07B4p0125* ID_MODEL_FROM_DATABASE=Tough TG-1 Camera usb:v07B4p0184* ID_MODEL_FROM_DATABASE=P-S100 port usb:v07B4p0202* ID_MODEL_FROM_DATABASE=Foot Switch RS-26 usb:v07B4p0203* ID_MODEL_FROM_DATABASE=Digital Voice Recorder DW-90 usb:v07B4p0206* ID_MODEL_FROM_DATABASE=Digital Voice Recorder DS-330 usb:v07B4p0207* ID_MODEL_FROM_DATABASE=Digital Voice Recorder & Camera W-10 usb:v07B4p0209* ID_MODEL_FROM_DATABASE=Digital Voice Recorder DM-20 usb:v07B4p020B* ID_MODEL_FROM_DATABASE=Digital Voice Recorder DS-4000 usb:v07B4p020D* ID_MODEL_FROM_DATABASE=Digital Voice Recorder VN-240PC usb:v07B4p0211* ID_MODEL_FROM_DATABASE=Digital Voice Recorder DS-2300 usb:v07B4p0218* ID_MODEL_FROM_DATABASE=Foot Switch RS-28 usb:v07B4p0244* ID_MODEL_FROM_DATABASE=Digital Voice Recorder VN-8500PC usb:v07B4p024F* ID_MODEL_FROM_DATABASE=Digital Voice Recorder DS-7000 usb:v07B4p0280* ID_MODEL_FROM_DATABASE=m:robe 100 usb:v07B5* ID_VENDOR_FROM_DATABASE=Mega World International, Ltd usb:v07B5p0017* ID_MODEL_FROM_DATABASE=Joystick usb:v07B5p0213* ID_MODEL_FROM_DATABASE=Thrustmaster Firestorm Digital 3 Gamepad usb:v07B5p0312* ID_MODEL_FROM_DATABASE=Gamepad usb:v07B5p9902* ID_MODEL_FROM_DATABASE=GamePad usb:v07B6* ID_VENDOR_FROM_DATABASE=Marubun Corp. usb:v07B7* ID_VENDOR_FROM_DATABASE=TIME Interconnect, Ltd usb:v07B8* ID_VENDOR_FROM_DATABASE=AboCom Systems Inc usb:v07B8p110C* ID_MODEL_FROM_DATABASE=XX1 usb:v07B8p1201* ID_MODEL_FROM_DATABASE=IEEE 802.11b Adapter usb:v07B8p200C* ID_MODEL_FROM_DATABASE=XX2 usb:v07B8p2573* ID_MODEL_FROM_DATABASE=Wireless LAN Card usb:v07B8p2770* ID_MODEL_FROM_DATABASE=802.11n/b/g Mini Wireless LAN USB2.0 Adapter usb:v07B8p2870* ID_MODEL_FROM_DATABASE=802.11n/b/g Wireless LAN USB2.0 Adapter usb:v07B8p3070* ID_MODEL_FROM_DATABASE=802.11n/b/g Mini Wireless LAN USB2.0 Adapter usb:v07B8p3071* ID_MODEL_FROM_DATABASE=802.11n/b/g Mini Wireless LAN USB2.0 Adapter usb:v07B8p3072* ID_MODEL_FROM_DATABASE=802.11n/b/g Mini Wireless LAN USB2.0 Adapter usb:v07B8p4000* ID_MODEL_FROM_DATABASE=DU-E10 Ethernet [klsi] usb:v07B8p4002* ID_MODEL_FROM_DATABASE=DU-E100 Ethernet [pegasus] usb:v07B8p4003* ID_MODEL_FROM_DATABASE=1/10/100 Ethernet Adapter usb:v07B8p4004* ID_MODEL_FROM_DATABASE=XX4 usb:v07B8p4007* ID_MODEL_FROM_DATABASE=XX5 usb:v07B8p400B* ID_MODEL_FROM_DATABASE=XX6 usb:v07B8p400C* ID_MODEL_FROM_DATABASE=XX7 usb:v07B8p401A* ID_MODEL_FROM_DATABASE=RTL8151 usb:v07B8p4102* ID_MODEL_FROM_DATABASE=USB 1.1 10/100M Fast Ethernet Adapter usb:v07B8p4104* ID_MODEL_FROM_DATABASE=XX9 usb:v07B8p420A* ID_MODEL_FROM_DATABASE=UF200 Ethernet usb:v07B8p5301* ID_MODEL_FROM_DATABASE=GW-US54ZGL 802.11bg usb:v07B8p6001* ID_MODEL_FROM_DATABASE=802.11bg usb:v07B8p8188* ID_MODEL_FROM_DATABASE=AboCom Systems Inc [WN2001 Prolink Wireless-N Nano Adapter] usb:v07B8pA001* ID_MODEL_FROM_DATABASE=WUG2200 802.11g Wireless Adapter [Envara WiND512] usb:v07B8pABC1* ID_MODEL_FROM_DATABASE=DU-E10 Ethernet [pegasus] usb:v07B8pB000* ID_MODEL_FROM_DATABASE=BWU613 usb:v07B8pB02A* ID_MODEL_FROM_DATABASE=AboCom Bluetooth Device usb:v07B8pB02B* ID_MODEL_FROM_DATABASE=Bluetooth dongle usb:v07B8pB02C* ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter usb:v07B8pB02D* ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter usb:v07B8pB02E* ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter usb:v07B8pB030* ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter usb:v07B8pB031* ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter usb:v07B8pB032* ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter usb:v07B8pB033* ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter usb:v07B8pB21A* ID_MODEL_FROM_DATABASE=WUG2400 802.11g Wireless Adapter [Texas Instruments TNETW1450] usb:v07B8pB21B* ID_MODEL_FROM_DATABASE=HWU54DM usb:v07B8pB21C* ID_MODEL_FROM_DATABASE=RT2573 usb:v07B8pB21D* ID_MODEL_FROM_DATABASE=RT2573 usb:v07B8pB21E* ID_MODEL_FROM_DATABASE=RT2573 usb:v07B8pB21F* ID_MODEL_FROM_DATABASE=WUG2700 usb:v07B8pD011* ID_MODEL_FROM_DATABASE=MP3 Player usb:v07B8pE001* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v07B8pE002* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v07B8pE003* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v07B8pE004* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v07B8pE005* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v07B8pE006* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v07B8pE007* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v07B8pE008* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v07B8pE009* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v07B8pE00A* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v07B8pE4F0* ID_MODEL_FROM_DATABASE=Card Reader Driver usb:v07B8pF101* ID_MODEL_FROM_DATABASE=DSB-560 Modem [atlas] usb:v07BC* ID_VENDOR_FROM_DATABASE=Canon Computer Systems, Inc. usb:v07BD* ID_VENDOR_FROM_DATABASE=Webgear, Inc. usb:v07BE* ID_VENDOR_FROM_DATABASE=Veridicom usb:v07C0* ID_VENDOR_FROM_DATABASE=Code Mercenaries Hard- und Software GmbH usb:v07C0p1113* ID_MODEL_FROM_DATABASE=JoyWarrior24F8 usb:v07C0p1116* ID_MODEL_FROM_DATABASE=JoyWarrior24F14 usb:v07C0p1121* ID_MODEL_FROM_DATABASE=The Claw usb:v07C0p1500* ID_MODEL_FROM_DATABASE=IO-Warrior 40 usb:v07C0p1501* ID_MODEL_FROM_DATABASE=IO-Warrior 24 usb:v07C0p1502* ID_MODEL_FROM_DATABASE=IO-Warrior 48 usb:v07C0p1503* ID_MODEL_FROM_DATABASE=IO-Warrior 28 usb:v07C0p1511* ID_MODEL_FROM_DATABASE=IO-Warrior 24 Power Vampire usb:v07C0p1512* ID_MODEL_FROM_DATABASE=IO-Warrior 24 Power Vampire usb:v07C1* ID_VENDOR_FROM_DATABASE=Keisokugiken usb:v07C1p0068* ID_MODEL_FROM_DATABASE=HKS-0200 USBDAQ usb:v07C4* ID_VENDOR_FROM_DATABASE=Datafab Systems, Inc. usb:v07C4p0102* ID_MODEL_FROM_DATABASE=USB to LS120 usb:v07C4p0103* ID_MODEL_FROM_DATABASE=USB to IDE usb:v07C4p1234* ID_MODEL_FROM_DATABASE=USB to ATAPI usb:v07C4pA000* ID_MODEL_FROM_DATABASE=CompactFlash Card Reader usb:v07C4pA001* ID_MODEL_FROM_DATABASE=CompactFlash & SmartMedia Card Reader [eusb] usb:v07C4pA002* ID_MODEL_FROM_DATABASE=Disk Drive usb:v07C4pA003* ID_MODEL_FROM_DATABASE=Datafab-based Reader usb:v07C4pA004* ID_MODEL_FROM_DATABASE=USB to MMC Class Drive usb:v07C4pA005* ID_MODEL_FROM_DATABASE=CompactFlash & SmartMedia Card Reader usb:v07C4pA006* ID_MODEL_FROM_DATABASE=SmartMedia Card Reader usb:v07C4pA007* ID_MODEL_FROM_DATABASE=Memory Stick Class Drive usb:v07C4pA103* ID_MODEL_FROM_DATABASE=MDSM-B reader usb:v07C4pA107* ID_MODEL_FROM_DATABASE=USB to Memory Stick (LC1) Drive usb:v07C4pA109* ID_MODEL_FROM_DATABASE=LC1 CompactFlash & SmartMedia Card Reader usb:v07C4pA10B* ID_MODEL_FROM_DATABASE=USB to CF+MS(LC1) usb:v07C4pA200* ID_MODEL_FROM_DATABASE=DF-UT-06 Hama MMC/SD Reader usb:v07C4pA400* ID_MODEL_FROM_DATABASE=CompactFlash & Microdrive Reader usb:v07C4pA600* ID_MODEL_FROM_DATABASE=Card Reader usb:v07C4pA604* ID_MODEL_FROM_DATABASE=12-in-1 Card Reader usb:v07C4pAD01* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v07C4pAE01* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v07C4pAF01* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v07C4pB000* ID_MODEL_FROM_DATABASE=USB to CF(LC1) usb:v07C4pB001* ID_MODEL_FROM_DATABASE=USB to CF+PCMCIA usb:v07C4pB004* ID_MODEL_FROM_DATABASE=MMC/SD Reader usb:v07C4pB006* ID_MODEL_FROM_DATABASE=USB to PCMCIA usb:v07C4pB00A* ID_MODEL_FROM_DATABASE=USB to CF+SD Drive(LC1) usb:v07C4pB00B* ID_MODEL_FROM_DATABASE=USB to Memory Stick(LC1) usb:v07C4pC010* ID_MODEL_FROM_DATABASE=Kingston FCR-HS2/ATA Card Reader usb:v07C5* ID_VENDOR_FROM_DATABASE=APG Cash Drawer usb:v07C5p0500* ID_MODEL_FROM_DATABASE=Cash Drawer usb:v07C6* ID_VENDOR_FROM_DATABASE=ShareWave, Inc. usb:v07C6p0002* ID_MODEL_FROM_DATABASE=Bodega Wireless Access Point usb:v07C6p0003* ID_MODEL_FROM_DATABASE=Bodega Wireless Network Adapter usb:v07C7* ID_VENDOR_FROM_DATABASE=Powertech Industrial Co., Ltd usb:v07C8* ID_VENDOR_FROM_DATABASE=B.U.G., Inc. usb:v07C8p0202* ID_MODEL_FROM_DATABASE=MN128-SOHO PAL usb:v07C9* ID_VENDOR_FROM_DATABASE=Allied Telesyn International usb:v07C9pB100* ID_MODEL_FROM_DATABASE=AT-USB100 usb:v07CA* ID_VENDOR_FROM_DATABASE=AVerMedia Technologies, Inc. usb:v07CAp0002* ID_MODEL_FROM_DATABASE=AVerTV PVR USB/EZMaker Pro Device usb:v07CAp0026* ID_MODEL_FROM_DATABASE=AVerTV usb:v07CAp0337* ID_MODEL_FROM_DATABASE=A867 DVB-T dongle usb:v07CAp0837* ID_MODEL_FROM_DATABASE=H837 Hybrid ATSC/QAM usb:v07CAp1228* ID_MODEL_FROM_DATABASE=MPEG-2 Capture Device (M038) usb:v07CAp1830* ID_MODEL_FROM_DATABASE=AVerTV Volar Video Capture (H830) usb:v07CAp3835* ID_MODEL_FROM_DATABASE=AVerTV Volar Green HD (A835B) usb:v07CAp850A* ID_MODEL_FROM_DATABASE=AverTV Volar Black HD (A850) usb:v07CAp850B* ID_MODEL_FROM_DATABASE=AverTV Red HD+ (A850T) usb:v07CApA309* ID_MODEL_FROM_DATABASE=AVerTV DVB-T (A309) usb:v07CApA801* ID_MODEL_FROM_DATABASE=AVerTV DVB-T (A800) usb:v07CApA815* ID_MODEL_FROM_DATABASE=AVerTV DVB-T Volar X (A815) usb:v07CApA827* ID_MODEL_FROM_DATABASE=AVerTV Hybrid Volar HX (A827) usb:v07CApA867* ID_MODEL_FROM_DATABASE=AVerTV DVB-T (A867) usb:v07CApB300* ID_MODEL_FROM_DATABASE=A300 DVB-T TV receiver usb:v07CApB800* ID_MODEL_FROM_DATABASE=MR800 FM Radio usb:v07CApE880* ID_MODEL_FROM_DATABASE=MPEG-2 Capture Device (E880) usb:v07CApE882* ID_MODEL_FROM_DATABASE=MPEG-2 Capture Device (E882) usb:v07CB* ID_VENDOR_FROM_DATABASE=Kingmax Technology, Inc. usb:v07CC* ID_VENDOR_FROM_DATABASE=Carry Computer Eng., Co., Ltd usb:v07CCp0000* ID_MODEL_FROM_DATABASE=CF Card Reader usb:v07CCp0001* ID_MODEL_FROM_DATABASE=Reader (UICSE) usb:v07CCp0002* ID_MODEL_FROM_DATABASE=Reader (UIS) usb:v07CCp0003* ID_MODEL_FROM_DATABASE=SM Card Reader usb:v07CCp0004* ID_MODEL_FROM_DATABASE=SM/CF/PCMCIA Card Reader usb:v07CCp0005* ID_MODEL_FROM_DATABASE=Reader (UISA2SE) usb:v07CCp0006* ID_MODEL_FROM_DATABASE=SM/CF/PCMCIA Card Reader usb:v07CCp0007* ID_MODEL_FROM_DATABASE=Reader (UISA6SE) usb:v07CCp000C* ID_MODEL_FROM_DATABASE=SM/CF Card Reader usb:v07CCp000D* ID_MODEL_FROM_DATABASE=SM/CF Card Reader usb:v07CCp000E* ID_MODEL_FROM_DATABASE=Reader (UISDA) usb:v07CCp000F* ID_MODEL_FROM_DATABASE=Reader (UICLIK) usb:v07CCp0010* ID_MODEL_FROM_DATABASE=Reader (UISMA) usb:v07CCp0012* ID_MODEL_FROM_DATABASE=Reader (UISC6SE-FLASH) usb:v07CCp0014* ID_MODEL_FROM_DATABASE=Litronic Fortezza Reader usb:v07CCp0030* ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC12S) usb:v07CCp0040* ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC13S) usb:v07CCp0100* ID_MODEL_FROM_DATABASE=Reader (UID) usb:v07CCp0101* ID_MODEL_FROM_DATABASE=Reader (UIM) usb:v07CCp0102* ID_MODEL_FROM_DATABASE=Reader (UISDMA) usb:v07CCp0103* ID_MODEL_FROM_DATABASE=Reader (UISDMC) usb:v07CCp0104* ID_MODEL_FROM_DATABASE=Reader (UISDM) usb:v07CCp0200* ID_MODEL_FROM_DATABASE=6-in-1 Card Reader usb:v07CCp0201* ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC1S & UISDMC3S) usb:v07CCp0202* ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC5S) usb:v07CCp0203* ID_MODEL_FROM_DATABASE=Mass Storage (UISMC5S) usb:v07CCp0204* ID_MODEL_FROM_DATABASE=Mass Storage (UIM4/5S & UIM7S) usb:v07CCp0205* ID_MODEL_FROM_DATABASE=Mass Storage (UIS4/5S & UIS7S) usb:v07CCp0206* ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC10S & UISDMC11S) usb:v07CCp0207* ID_MODEL_FROM_DATABASE=Mass Storage (UPIDMA) usb:v07CCp0208* ID_MODEL_FROM_DATABASE=Mass Storage (UCFC II) usb:v07CCp0210* ID_MODEL_FROM_DATABASE=Mass Storage (UPIXXA) usb:v07CCp0213* ID_MODEL_FROM_DATABASE=Mass Storage (UPIDA) usb:v07CCp0214* ID_MODEL_FROM_DATABASE=Mass Storage (UPIMA) usb:v07CCp0215* ID_MODEL_FROM_DATABASE=Mass Storage (UPISA) usb:v07CCp0217* ID_MODEL_FROM_DATABASE=Mass Storage (UPISDMA) usb:v07CCp0223* ID_MODEL_FROM_DATABASE=Mass Storage (UCIDA) usb:v07CCp0224* ID_MODEL_FROM_DATABASE=Mass Storage (UCIMA) usb:v07CCp0225* ID_MODEL_FROM_DATABASE=Mass Storage (UIS7S) usb:v07CCp0227* ID_MODEL_FROM_DATABASE=Mass Storage (UCIDMA) usb:v07CCp0234* ID_MODEL_FROM_DATABASE=Mass Storage (UIM7S) usb:v07CCp0235* ID_MODEL_FROM_DATABASE=Mass Storage (UIS4S-S) usb:v07CCp0237* ID_MODEL_FROM_DATABASE=Velper (UISDMC4S) usb:v07CCp0300* ID_MODEL_FROM_DATABASE=6-in-1 Card Reader usb:v07CCp0301* ID_MODEL_FROM_DATABASE=6-in-1 Card Reader usb:v07CCp0303* ID_MODEL_FROM_DATABASE=Mass Storage (UID10W) usb:v07CCp0304* ID_MODEL_FROM_DATABASE=Mass Storage (UIM10W) usb:v07CCp0305* ID_MODEL_FROM_DATABASE=Mass Storage (UIS10W) usb:v07CCp0308* ID_MODEL_FROM_DATABASE=Mass Storage (UIC10W) usb:v07CCp0309* ID_MODEL_FROM_DATABASE=Mass Storage (UISC3W) usb:v07CCp0310* ID_MODEL_FROM_DATABASE=Mass Storage (UISDMA2W) usb:v07CCp0311* ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC14W) usb:v07CCp0320* ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC4W) usb:v07CCp0321* ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC37W) usb:v07CCp0330* ID_MODEL_FROM_DATABASE=WINTERREADER Reader usb:v07CCp0350* ID_MODEL_FROM_DATABASE=9-in-1 Card Reader usb:v07CCp0500* ID_MODEL_FROM_DATABASE=Mass Storage usb:v07CCp0501* ID_MODEL_FROM_DATABASE=Mass Storage usb:v07CD* ID_VENDOR_FROM_DATABASE=Elektor usb:v07CDp0001* ID_MODEL_FROM_DATABASE=USBuart Serial Port usb:v07CF* ID_VENDOR_FROM_DATABASE=Casio Computer Co., Ltd usb:v07CFp1001* ID_MODEL_FROM_DATABASE=QV-8000SX/5700/3000EX Digicam; Exilim EX-M20 usb:v07CFp1003* ID_MODEL_FROM_DATABASE=Exilim EX-S500 usb:v07CFp1004* ID_MODEL_FROM_DATABASE=Exilim EX-Z120 usb:v07CFp1011* ID_MODEL_FROM_DATABASE=USB-CASIO PC CAMERA usb:v07CFp1116* ID_MODEL_FROM_DATABASE=EXILIM EX-Z19 usb:v07CFp1125* ID_MODEL_FROM_DATABASE=Exilim EX-H10 Digital Camera (mass storage mode) usb:v07CFp1133* ID_MODEL_FROM_DATABASE=Exilim EX-Z350 Digital Camera (mass storage mode) usb:v07CFp1225* ID_MODEL_FROM_DATABASE=Exilim EX-H10 Digital Camera (PictBridge mode) usb:v07CFp1233* ID_MODEL_FROM_DATABASE=Exilim EX-Z350 Digital Camera (PictBridge mode) usb:v07CFp2002* ID_MODEL_FROM_DATABASE=E-125 Cassiopeia Pocket PC usb:v07CFp3801* ID_MODEL_FROM_DATABASE=WMP-1 MP3-Watch usb:v07CFp4001* ID_MODEL_FROM_DATABASE=Label Printer KL-P1000 usb:v07CFp4007* ID_MODEL_FROM_DATABASE=CW50 Device usb:v07CFp4104* ID_MODEL_FROM_DATABASE=Cw75 Device usb:v07CFp4107* ID_MODEL_FROM_DATABASE=CW-L300 Device usb:v07CFp4500* ID_MODEL_FROM_DATABASE=LV-20 Digital Camera usb:v07CFp6101* ID_MODEL_FROM_DATABASE=fx-9750gII usb:v07CFp6801* ID_MODEL_FROM_DATABASE=PL-40R usb:v07CFp6802* ID_MODEL_FROM_DATABASE=MIDI Keyboard usb:v07D0* ID_VENDOR_FROM_DATABASE=Dazzle usb:v07D0p0001* ID_MODEL_FROM_DATABASE=Digital Video Creator I usb:v07D0p0002* ID_MODEL_FROM_DATABASE=Global Village VideoFX Grabber usb:v07D0p0003* ID_MODEL_FROM_DATABASE=Fusion Model DVC-50 Rev 1 (NTSC) usb:v07D0p0004* ID_MODEL_FROM_DATABASE=DVC-800 (PAL) Grabber usb:v07D0p0005* ID_MODEL_FROM_DATABASE=Fusion Video and Audio Ports usb:v07D0p0006* ID_MODEL_FROM_DATABASE=DVC 150 Loader Device usb:v07D0p0007* ID_MODEL_FROM_DATABASE=DVC 150 usb:v07D0p0327* ID_MODEL_FROM_DATABASE=Fusion Digital Media Reader usb:v07D0p1001* ID_MODEL_FROM_DATABASE=DM-FLEX DFU Adapter usb:v07D0p1002* ID_MODEL_FROM_DATABASE=DMHS2 DFU Adapter usb:v07D0p1102* ID_MODEL_FROM_DATABASE=CF Reader/Writer usb:v07D0p1103* ID_MODEL_FROM_DATABASE=SD Reader/Writer usb:v07D0p1104* ID_MODEL_FROM_DATABASE=SM Reader/Writer usb:v07D0p1105* ID_MODEL_FROM_DATABASE=MS Reader/Writer usb:v07D0p1106* ID_MODEL_FROM_DATABASE=xD/SM Reader/Writer usb:v07D0p1202* ID_MODEL_FROM_DATABASE=MultiSlot Reader/Writer usb:v07D0p2000* ID_MODEL_FROM_DATABASE=FX2 DFU Adapter usb:v07D0p2001* ID_MODEL_FROM_DATABASE=eUSB CompactFlash Reader usb:v07D0p4100* ID_MODEL_FROM_DATABASE=Kingsun SF-620 Infrared Adapter usb:v07D0p4101* ID_MODEL_FROM_DATABASE=Connectivity Cable (CA-42 clone) usb:v07D0p4959* ID_MODEL_FROM_DATABASE=Kingsun KS-959 Infrared Adapter usb:v07D1* ID_VENDOR_FROM_DATABASE=D-Link System usb:v07D1p13EC* ID_MODEL_FROM_DATABASE=VvBus for Helium 2xx usb:v07D1p13ED* ID_MODEL_FROM_DATABASE=VvBus for Helium 2xx usb:v07D1p13F1* ID_MODEL_FROM_DATABASE=DSL-302G Modem usb:v07D1p13F2* ID_MODEL_FROM_DATABASE=DSL-502G Router usb:v07D1p3300* ID_MODEL_FROM_DATABASE=DWA-130 802.11n Wireless N Adapter(rev.E) [Realtek RTL8191SU] usb:v07D1p3302* ID_MODEL_FROM_DATABASE=DWA-130 802.11n Wireless N Adapter(rev.C2) [Realtek RTL8191SU] usb:v07D1p3303* ID_MODEL_FROM_DATABASE=DWA-131 802.11n Wireless N Nano Adapter(rev.A1) [Realtek RTL8192SU] usb:v07D1p3304* ID_MODEL_FROM_DATABASE=FR-300USB 802.11bgn Wireless Adapter usb:v07D1p3A07* ID_MODEL_FROM_DATABASE=WUA-2340 RangeBooster G Adapter(rev.A) [Atheros AR5523] usb:v07D1p3A08* ID_MODEL_FROM_DATABASE=WUA-2340 RangeBooster G Adapter(rev.A) (no firmware) [Atheros AR5523] usb:v07D1p3A09* ID_MODEL_FROM_DATABASE=DWA-160 802.11abgn Xtreme N Dual Band Adapter(rev.A2) [Atheros AR9170+AR9104] usb:v07D1p3A0D* ID_MODEL_FROM_DATABASE=DWA-120 802.11g Wireless 108G Adapter [Atheros AR5523] usb:v07D1p3A0F* ID_MODEL_FROM_DATABASE=DWA-130 802.11n Wireless N Adapter(rev.D) [Atheros AR9170+AR9102] usb:v07D1p3A10* ID_MODEL_FROM_DATABASE=DWA-126 802.11n Wireless Adapter [Atheros AR9271] usb:v07D1p3B01* ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter(rev.D) [Marvell 88W8338+88W8010] usb:v07D1p3B10* ID_MODEL_FROM_DATABASE=DWA-142 RangeBooster N Adapter [Marvell 88W8362+88W8060] usb:v07D1p3B11* ID_MODEL_FROM_DATABASE=DWA-130 802.11n Wireless N Adapter(rev.A1) [Marvell 88W8362+88W8060] usb:v07D1p3C03* ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter(rev.C1) [Ralink RT2571W] usb:v07D1p3C04* ID_MODEL_FROM_DATABASE=WUA-1340 usb:v07D1p3C05* ID_MODEL_FROM_DATABASE=EH103 Wireless G Adapter usb:v07D1p3C06* ID_MODEL_FROM_DATABASE=DWA-111 802.11bg Wireless Adapter [Ralink RT2571W] usb:v07D1p3C07* ID_MODEL_FROM_DATABASE=DWA-110 Wireless G Adapter(rev.A1) [Ralink RT2571W] usb:v07D1p3C09* ID_MODEL_FROM_DATABASE=DWA-140 RangeBooster N Adapter(rev.B1) [Ralink RT2870] usb:v07D1p3C0A* ID_MODEL_FROM_DATABASE=DWA-140 RangeBooster N Adapter(rev.B2) [Ralink RT3072] usb:v07D1p3C0B* ID_MODEL_FROM_DATABASE=DWA-110 Wireless G Adapter(rev.B) [Ralink RT2870] usb:v07D1p3C0D* ID_MODEL_FROM_DATABASE=DWA-125 Wireless N 150 Adapter(rev.A1) [Ralink RT3070] usb:v07D1p3C0E* ID_MODEL_FROM_DATABASE=WUA-2340 RangeBooster G Adapter(rev.B) [Ralink RT2070] usb:v07D1p3C0F* ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter(rev.E1) [Ralink RT2070] usb:v07D1p3C10* ID_MODEL_FROM_DATABASE=DWA-160 802.11abgn Xtreme N Dual Band Adapter(rev.A1) [Atheros AR9170+AR9104] usb:v07D1p3C11* ID_MODEL_FROM_DATABASE=DWA-160 Xtreme N Dual Band USB Adapter(rev.B) [Ralink RT2870] usb:v07D1p3C13* ID_MODEL_FROM_DATABASE=DWA-130 802.11n Wireless N Adapter(rev.B) [Ralink RT2870] usb:v07D1p3C15* ID_MODEL_FROM_DATABASE=DWA-140 RangeBooster N Adapter(rev.B3) [Ralink RT2870] usb:v07D1p3C16* ID_MODEL_FROM_DATABASE=DWA-125 Wireless N 150 Adapter(rev.A2) [Ralink RT3070] usb:v07D1p3E02* ID_MODEL_FROM_DATABASE=DWM-156 3.75G HSUPA Adapter usb:v07D1p5100* ID_MODEL_FROM_DATABASE=Remote NDIS Device usb:v07D1pA800* ID_MODEL_FROM_DATABASE=DWM-152 3.75G HSUPA Adapter usb:v07D1pF101* ID_MODEL_FROM_DATABASE=DBT-122 Bluetooth usb:v07D1pFC01* ID_MODEL_FROM_DATABASE=DBT-120 Bluetooth Adapter usb:v07D2* ID_VENDOR_FROM_DATABASE=Aptio Products, Inc. usb:v07D3* ID_VENDOR_FROM_DATABASE=Cyberdata Corp. usb:v07D5* ID_VENDOR_FROM_DATABASE=Radiant Systems usb:v07D7* ID_VENDOR_FROM_DATABASE=GCC Technologies, Inc. usb:v07DA* ID_VENDOR_FROM_DATABASE=Arasan Chip Systems usb:v07DE* ID_VENDOR_FROM_DATABASE=Diamond Multimedia usb:v07DEp2820* ID_MODEL_FROM_DATABASE=VC500 Video Capture Dongle usb:v07DF* ID_VENDOR_FROM_DATABASE=David Electronics Co., Ltd usb:v07E1* ID_VENDOR_FROM_DATABASE=Ambient Technologies, Inc. usb:v07E1p5201* ID_MODEL_FROM_DATABASE=V.90 Modem usb:v07E2* ID_VENDOR_FROM_DATABASE=Elmeg GmbH & Co., Ltd usb:v07E3* ID_VENDOR_FROM_DATABASE=Planex Communications, Inc. usb:v07E4* ID_VENDOR_FROM_DATABASE=Movado Enterprise Co., Ltd usb:v07E4p0967* ID_MODEL_FROM_DATABASE=SCard R/W CSR-145 usb:v07E4p0968* ID_MODEL_FROM_DATABASE=SCard R/W CSR-145 usb:v07E5* ID_VENDOR_FROM_DATABASE=QPS, Inc. usb:v07E5p05C2* ID_MODEL_FROM_DATABASE=IDE-to-USB2.0 PCA usb:v07E5p5C01* ID_MODEL_FROM_DATABASE=Que! CDRW usb:v07E6* ID_VENDOR_FROM_DATABASE=Allied Cable Corp. usb:v07E7* ID_VENDOR_FROM_DATABASE=Mirvo Toys, Inc. usb:v07E8* ID_VENDOR_FROM_DATABASE=Labsystems usb:v07EA* ID_VENDOR_FROM_DATABASE=Iwatsu Electric Co., Ltd usb:v07EB* ID_VENDOR_FROM_DATABASE=Double-H Technology Co., Ltd usb:v07EC* ID_VENDOR_FROM_DATABASE=Taiyo Electric Wire & Cable Co., Ltd usb:v07EE* ID_VENDOR_FROM_DATABASE=Torex Retail (formerly Logware) usb:v07EEp0002* ID_MODEL_FROM_DATABASE=Cash Drawer I/F usb:v07EF* ID_VENDOR_FROM_DATABASE=STSN usb:v07EFp0001* ID_MODEL_FROM_DATABASE=Internet Access Device usb:v07F2* ID_VENDOR_FROM_DATABASE=Microcomputer Applications, Inc. usb:v07F2p0001* ID_MODEL_FROM_DATABASE=KEYLOK II usb:v07F6* ID_VENDOR_FROM_DATABASE=Circuit Assembly Corp. usb:v07F7* ID_VENDOR_FROM_DATABASE=Century Corp. usb:v07F7p0005* ID_MODEL_FROM_DATABASE=ScanLogic/Century Corporation uATA usb:v07F7p011E* ID_MODEL_FROM_DATABASE=Century USB Disk Enclosure usb:v07F9* ID_VENDOR_FROM_DATABASE=Dotop Technology, Inc. usb:v07FA* ID_VENDOR_FROM_DATABASE=DrayTek Corp. usb:v07FAp0778* ID_MODEL_FROM_DATABASE=miniVigor 128 ISDN TA usb:v07FAp0846* ID_MODEL_FROM_DATABASE=ISDN TA [HFC-S] usb:v07FAp0847* ID_MODEL_FROM_DATABASE=ISDN TA [HFC-S] usb:v07FAp1012* ID_MODEL_FROM_DATABASE=BeWAN ADSL USB ST (grey) usb:v07FAp1196* ID_MODEL_FROM_DATABASE=BWIFI-USB54AR 802.11bg usb:v07FApA904* ID_MODEL_FROM_DATABASE=BeWAN ADSL usb:v07FApA905* ID_MODEL_FROM_DATABASE=BeWAN ADSL ST usb:v07FD* ID_VENDOR_FROM_DATABASE=Mark of the Unicorn usb:v07FDp0000* ID_MODEL_FROM_DATABASE=FastLane MIDI Interface usb:v07FDp0001* ID_MODEL_FROM_DATABASE=FastLane Quad MIDI Interface usb:v07FDp0002* ID_MODEL_FROM_DATABASE=MOTU Audio for 64 bit usb:v07FF* ID_VENDOR_FROM_DATABASE=Unknown usb:v07FFp00FF* ID_MODEL_FROM_DATABASE=Portable Hard Drive usb:v0801* ID_VENDOR_FROM_DATABASE=MagTek usb:v0801p0001* ID_MODEL_FROM_DATABASE=Mini Swipe Reader (Keyboard Emulation) usb:v0801p0002* ID_MODEL_FROM_DATABASE=Mini Swipe Reader usb:v0801p0003* ID_MODEL_FROM_DATABASE=Magstripe Insert Reader usb:v0802* ID_VENDOR_FROM_DATABASE=Mako Technologies, LLC usb:v0803* ID_VENDOR_FROM_DATABASE=Zoom Telephonics, Inc. usb:v0803p1300* ID_MODEL_FROM_DATABASE=V92 Faxmodem usb:v0803p3095* ID_MODEL_FROM_DATABASE=V.92 56K Mini External Modem Model 3095 usb:v0803p4310* ID_MODEL_FROM_DATABASE=4410a Wireless-G Adapter [Intersil ISL3887] usb:v0803p4410* ID_MODEL_FROM_DATABASE=4410b Wireless-G Adapter [ZyDAS ZD1211B] usb:v0803p5241* ID_MODEL_FROM_DATABASE=Cable Modem usb:v0803p5551* ID_MODEL_FROM_DATABASE=DSL Modem usb:v0803p9700* ID_MODEL_FROM_DATABASE=2986L FaxModem usb:v0803p9800* ID_MODEL_FROM_DATABASE=Cable Modem usb:v0803pA312* ID_MODEL_FROM_DATABASE=Wireless-G usb:v0809* ID_VENDOR_FROM_DATABASE=Genicom Technology, Inc. usb:v080A* ID_VENDOR_FROM_DATABASE=Evermuch Technology Co., Ltd usb:v080B* ID_VENDOR_FROM_DATABASE=Cross Match Technologies usb:v080Bp0002* ID_MODEL_FROM_DATABASE=Fingerprint Scanner (After ReNumeration) usb:v080Bp0010* ID_MODEL_FROM_DATABASE=300LC Series Fingerprint Scanner (Before ReNumeration) usb:v080C* ID_VENDOR_FROM_DATABASE=Datalogic S.p.A. usb:v080Cp0300* ID_MODEL_FROM_DATABASE=Gryphon D120 Barcode Scanner usb:v080Cp0400* ID_MODEL_FROM_DATABASE=Gryphon D120 Barcode Scanner usb:v080Cp0500* ID_MODEL_FROM_DATABASE=Gryphon D120 Barcode Scanner usb:v080Cp0600* ID_MODEL_FROM_DATABASE=Gryphon M100 Barcode Scanner usb:v080D* ID_VENDOR_FROM_DATABASE=Teco Image Systems Co., Ltd usb:v080Dp0102* ID_MODEL_FROM_DATABASE=Hercules Scan@home 48 usb:v080Dp0104* ID_MODEL_FROM_DATABASE=3.2Slim usb:v080Dp0110* ID_MODEL_FROM_DATABASE=UMAX AstraSlim 1200 Scanner usb:v0810* ID_VENDOR_FROM_DATABASE=Personal Communication Systems, Inc. usb:v0810p0001* ID_MODEL_FROM_DATABASE=Dual PSX Adaptor usb:v0810p0002* ID_MODEL_FROM_DATABASE=Dual PCS Adaptor usb:v0810p0003* ID_MODEL_FROM_DATABASE=PlayStation Gamepad usb:v0813* ID_VENDOR_FROM_DATABASE=Mattel, Inc. usb:v0813p0001* ID_MODEL_FROM_DATABASE=Intel Play QX3 Microscope usb:v0813p0002* ID_MODEL_FROM_DATABASE=Dual Mode Camera Plus usb:v0819* ID_VENDOR_FROM_DATABASE=eLicenser usb:v0819p0101* ID_MODEL_FROM_DATABASE=License Management and Copy Protection usb:v081A* ID_VENDOR_FROM_DATABASE=MG Logic usb:v081Ap1000* ID_MODEL_FROM_DATABASE=Duo Pen Tablet usb:v081B* ID_VENDOR_FROM_DATABASE=Indigita Corp. usb:v081Bp0600* ID_MODEL_FROM_DATABASE=Storage Adapter usb:v081Bp0601* ID_MODEL_FROM_DATABASE=Storage Adapter usb:v081C* ID_VENDOR_FROM_DATABASE=Mipsys usb:v081E* ID_VENDOR_FROM_DATABASE=AlphaSmart, Inc. usb:v081EpDF00* ID_MODEL_FROM_DATABASE=Handheld usb:v0822* ID_VENDOR_FROM_DATABASE=Reudo Corp. usb:v0822p2001* ID_MODEL_FROM_DATABASE=IRXpress Infrared Device usb:v0825* ID_VENDOR_FROM_DATABASE=GC Protronics usb:v0826* ID_VENDOR_FROM_DATABASE=Data Transit usb:v0827* ID_VENDOR_FROM_DATABASE=BroadLogic, Inc. usb:v0828* ID_VENDOR_FROM_DATABASE=Sato Corp. usb:v0829* ID_VENDOR_FROM_DATABASE=DirecTV Broadband, Inc. (Telocity) usb:v082D* ID_VENDOR_FROM_DATABASE=Handspring usb:v082Dp0100* ID_MODEL_FROM_DATABASE=Visor usb:v082Dp0200* ID_MODEL_FROM_DATABASE=Treo usb:v082Dp0300* ID_MODEL_FROM_DATABASE=Treo 600 usb:v082Dp0400* ID_MODEL_FROM_DATABASE=Handheld usb:v082Dp0500* ID_MODEL_FROM_DATABASE=Handheld usb:v082Dp0600* ID_MODEL_FROM_DATABASE=Handheld usb:v0830* ID_VENDOR_FROM_DATABASE=Palm, Inc. usb:v0830p0001* ID_MODEL_FROM_DATABASE=m500 usb:v0830p0002* ID_MODEL_FROM_DATABASE=m505 usb:v0830p0003* ID_MODEL_FROM_DATABASE=m515 usb:v0830p0004* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0005* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0006* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0010* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0011* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0012* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0013* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0014* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0020* ID_MODEL_FROM_DATABASE=i705 usb:v0830p0021* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0022* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0023* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0024* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0030* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0031* ID_MODEL_FROM_DATABASE=Tungsten W usb:v0830p0032* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0033* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0034* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0040* ID_MODEL_FROM_DATABASE=m125 usb:v0830p0041* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0042* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0043* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0044* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0050* ID_MODEL_FROM_DATABASE=m130 usb:v0830p0051* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0052* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0053* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0054* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0060* ID_MODEL_FROM_DATABASE=Tungsten C/E/T/T2/T3 / Zire 71 usb:v0830p0061* ID_MODEL_FROM_DATABASE=Lifedrive / Treo 650/680 / Tunsten E2/T5/TX / Centro / Zire 21/31/72 / Z22 usb:v0830p0062* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0063* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0064* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0070* ID_MODEL_FROM_DATABASE=Zire usb:v0830p0071* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0072* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0080* ID_MODEL_FROM_DATABASE=Serial Adapter [for Palm III] usb:v0830p0081* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p0082* ID_MODEL_FROM_DATABASE=Handheld usb:v0830p00A0* ID_MODEL_FROM_DATABASE=Treo 800w usb:v0830p0101* ID_MODEL_FROM_DATABASE=Pre usb:v0832* ID_VENDOR_FROM_DATABASE=Kouwell Electronics Corp. usb:v0832p5850* ID_MODEL_FROM_DATABASE=Cable usb:v0833* ID_VENDOR_FROM_DATABASE=Sourcenext Corp. usb:v0833p012E* ID_MODEL_FROM_DATABASE=KeikaiDenwa 8 with charger usb:v0833p039F* ID_MODEL_FROM_DATABASE=KeikaiDenwa 8 usb:v0835* ID_VENDOR_FROM_DATABASE=Action Star Enterprise Co., Ltd usb:v0836* ID_VENDOR_FROM_DATABASE=TrekStor usb:v0836p2836* ID_MODEL_FROM_DATABASE=i.Beat mood usb:v0839* ID_VENDOR_FROM_DATABASE=Samsung Techwin Co., Ltd usb:v0839p0005* ID_MODEL_FROM_DATABASE=Digimax Camera usb:v0839p0008* ID_MODEL_FROM_DATABASE=Digimax 230 Camera usb:v0839p0009* ID_MODEL_FROM_DATABASE=Digimax 340 usb:v0839p000A* ID_MODEL_FROM_DATABASE=Digimax 410 usb:v0839p000E* ID_MODEL_FROM_DATABASE=Digimax 360 usb:v0839p0010* ID_MODEL_FROM_DATABASE=Digimax 300 usb:v0839p1003* ID_MODEL_FROM_DATABASE=Digimax 210SE usb:v0839p1005* ID_MODEL_FROM_DATABASE=Digimax 220 usb:v0839p1009* ID_MODEL_FROM_DATABASE=Digimax V4 usb:v0839p1012* ID_MODEL_FROM_DATABASE=6500 Document Camera usb:v0839p1058* ID_MODEL_FROM_DATABASE=S730 Camera usb:v0839p1064* ID_MODEL_FROM_DATABASE=Digimax D830 Camera usb:v0839p1542* ID_MODEL_FROM_DATABASE=Digimax 50 Duo usb:v0839p3000* ID_MODEL_FROM_DATABASE=Digimax 35 MP3 usb:v083A* ID_VENDOR_FROM_DATABASE=Accton Technology Corp. usb:v083Ap1046* ID_MODEL_FROM_DATABASE=10/100 Ethernet [pegasus] usb:v083Ap1060* ID_MODEL_FROM_DATABASE=HomeLine Adapter usb:v083Ap1F4D* ID_MODEL_FROM_DATABASE=SMC8013WG Broadband Remote NDIS Device usb:v083Ap3046* ID_MODEL_FROM_DATABASE=10/100 Series Adapter usb:v083Ap3060* ID_MODEL_FROM_DATABASE=1/10/100 Adapter usb:v083Ap3501* ID_MODEL_FROM_DATABASE=2664W usb:v083Ap3502* ID_MODEL_FROM_DATABASE=WN3501D Wireless Adapter usb:v083Ap3503* ID_MODEL_FROM_DATABASE=T-Sinus 111 Wireless Adapter usb:v083Ap4501* ID_MODEL_FROM_DATABASE=T-Sinus 154data usb:v083Ap4502* ID_MODEL_FROM_DATABASE=Siemens S30853-S1016-R107 802.11g Wireless Adapter [Intersil ISL3886] usb:v083Ap4505* ID_MODEL_FROM_DATABASE=SMCWUSB-G 802.11bg usb:v083Ap4507* ID_MODEL_FROM_DATABASE=SMCWUSBT-G2 802.11g Wireless Adapter [Atheros AR5523] usb:v083Ap4521* ID_MODEL_FROM_DATABASE=Siemens S30863-S1016-R107-2 802.11g Wireless Adapter [Intersil ISL3887] usb:v083Ap4531* ID_MODEL_FROM_DATABASE=T-Com Sinus 154 data II [Intersil ISL3887] usb:v083Ap5046* ID_MODEL_FROM_DATABASE=SpeedStream 10/100 Ethernet [pegasus] usb:v083Ap5501* ID_MODEL_FROM_DATABASE=Wireless Adapter 11g usb:v083Ap6500* ID_MODEL_FROM_DATABASE=Cable Modem usb:v083Ap6618* ID_MODEL_FROM_DATABASE=802.11n Wireless Adapter usb:v083Ap7511* ID_MODEL_FROM_DATABASE=Arcadyan 802.11N Wireless Adapter usb:v083Ap7512* ID_MODEL_FROM_DATABASE=Arcadyan 802.11N Wireless Adapter usb:v083Ap7522* ID_MODEL_FROM_DATABASE=Arcadyan 802.11N Wireless Adapter usb:v083Ap8522* ID_MODEL_FROM_DATABASE=Arcadyan 802.11N Wireless Adapter usb:v083Ap8541* ID_MODEL_FROM_DATABASE=WN4501F 802.11g Wireless Adapter [Intersil ISL3887] usb:v083ApA512* ID_MODEL_FROM_DATABASE=Arcadyan 802.11N Wireless Adapter usb:v083ApA618* ID_MODEL_FROM_DATABASE=SMCWUSBS-N EZ Connect N Draft 11n Wireless Adapter [Ralink RT2870] usb:v083ApA701* ID_MODEL_FROM_DATABASE=SMCWUSBS-N3 EZ Connect N Wireless Adapter [Ralink RT3070] usb:v083ApB004* ID_MODEL_FROM_DATABASE=CPWUE001 USB/Ethernet Adapter usb:v083ApB522* ID_MODEL_FROM_DATABASE=SMCWUSBS-N2 EZ Connect N Wireless Adapter [Ralink RT2870] usb:v083ApBB01* ID_MODEL_FROM_DATABASE=BlueExpert Bluetooth Device usb:v083ApC003* ID_MODEL_FROM_DATABASE=802.11b Wireless Adapter usb:v083ApC501* ID_MODEL_FROM_DATABASE=Zoom 4410 Wireless-G [Intersil ISL3887] usb:v083ApC561* ID_MODEL_FROM_DATABASE=802.11a/g Wireless Adapter usb:v083ApD522* ID_MODEL_FROM_DATABASE=Speedport W 102 Stick IEEE 802.11n USB 2.0 Adapter usb:v083ApE501* ID_MODEL_FROM_DATABASE=ZD1211B usb:v083ApE503* ID_MODEL_FROM_DATABASE=Arcadyan WN4501 802.11b/g usb:v083ApE506* ID_MODEL_FROM_DATABASE=WUS-201 802.11bg usb:v083ApF501* ID_MODEL_FROM_DATABASE=802.11g Wireless Adapter usb:v083ApF502* ID_MODEL_FROM_DATABASE=802.11g Wireless Adapter usb:v083ApF522* ID_MODEL_FROM_DATABASE=Arcadyan WN7512 802.11n usb:v083F* ID_VENDOR_FROM_DATABASE=Global Village usb:v083FpB100* ID_MODEL_FROM_DATABASE=TelePort V.90 Fax/Modem usb:v0840* ID_VENDOR_FROM_DATABASE=Argosy Research, Inc. usb:v0840p0060* ID_MODEL_FROM_DATABASE=Storage Adapter Bridge Module usb:v0841* ID_VENDOR_FROM_DATABASE=Rioport.com, Inc. usb:v0841p0001* ID_MODEL_FROM_DATABASE=Rio 500 usb:v0844* ID_VENDOR_FROM_DATABASE=Welland Industrial Co., Ltd usb:v0846* ID_VENDOR_FROM_DATABASE=NetGear, Inc. usb:v0846p1001* ID_MODEL_FROM_DATABASE=EA101 10 Mbps 10BASE-T Ethernet [Kawasaki LSI KL5KLUSB101B] usb:v0846p1002* ID_MODEL_FROM_DATABASE=Ethernet usb:v0846p1020* ID_MODEL_FROM_DATABASE=FA101 Fast Ethernet USB 1.1 usb:v0846p1040* ID_MODEL_FROM_DATABASE=FA120 Fast Ethernet USB 2.0 [Asix AX88172 / AX8817x] usb:v0846p1100* ID_MODEL_FROM_DATABASE=Managed Switch M4100 series, M5300 series, M7100 series usb:v0846p4110* ID_MODEL_FROM_DATABASE=MA111(v1) 802.11b Wireless [Intersil Prism 3.0] usb:v0846p4200* ID_MODEL_FROM_DATABASE=WG121(v1) 54 Mbps Wireless [Intersil ISL3886] usb:v0846p4210* ID_MODEL_FROM_DATABASE=WG121(v2) 54 Mbps Wireless [Intersil ISL3886] usb:v0846p4220* ID_MODEL_FROM_DATABASE=WG111(v1) 54 Mbps Wireless [Intersil ISL3886] usb:v0846p4230* ID_MODEL_FROM_DATABASE=MA111(v2) 802.11b Wireless [SIS SIS 162] usb:v0846p4240* ID_MODEL_FROM_DATABASE=WG111(v1) rev 2 54 Mbps Wireless [Intersil ISL3887] usb:v0846p4260* ID_MODEL_FROM_DATABASE=WG111v3 54 Mbps Wireless [realtek RTL8187B] usb:v0846p4300* ID_MODEL_FROM_DATABASE=WG111U Double 108 Mbps Wireless [Atheros AR5004X / AR5005UX] usb:v0846p4301* ID_MODEL_FROM_DATABASE=WG111U (no firmware) Double 108 Mbps Wireless [Atheros AR5004X / AR5005UX] usb:v0846p5F00* ID_MODEL_FROM_DATABASE=WPN111 802.11g Wireless Adapter [Atheros AR5523] usb:v0846p6A00* ID_MODEL_FROM_DATABASE=WG111v2 54 Mbps Wireless [RealTek RTL8187L] usb:v0846p7100* ID_MODEL_FROM_DATABASE=WN121T RangeMax Next Wireless-N [Marvell TopDog] usb:v0846p9000* ID_MODEL_FROM_DATABASE=WN111(v1) RangeMax Next Wireless [Marvell 88W8362+88W8060] usb:v0846p9001* ID_MODEL_FROM_DATABASE=WN111(v2) RangeMax Next Wireless [Atheros AR9170+AR9101] usb:v0846p9010* ID_MODEL_FROM_DATABASE=WNDA3100v1 802.11abgn [Atheros AR9170+AR9104] usb:v0846p9011* ID_MODEL_FROM_DATABASE=WNDA3100v2 802.11abgn [Broadcom BCM4323] usb:v0846p9012* ID_MODEL_FROM_DATABASE=WNDA4100 802.11abgn 3x3:3 [Ralink RT3573] usb:v0846p9018* ID_MODEL_FROM_DATABASE=WNDA3200 802.11abgn Wireless Adapter [Atheros AR7010+AR9280] usb:v0846p9020* ID_MODEL_FROM_DATABASE=WNA3100(v1) Wireless-N 300 [Broadcom BCM43231] usb:v0846p9021* ID_MODEL_FROM_DATABASE=WNA3100M(v1) Wireless-N 300 [Realtek RTL8192CU] usb:v0846p9030* ID_MODEL_FROM_DATABASE=WNA1100 Wireless-N 150 [Atheros AR9271] usb:v0846p9040* ID_MODEL_FROM_DATABASE=WNA1000 Wireless-N 150 [Atheros AR9170+AR9101] usb:v0846p9041* ID_MODEL_FROM_DATABASE=WNA1000M 802.11bgn [Realtek RTL8188CUS] usb:v0846p9042* ID_MODEL_FROM_DATABASE=On Networks N150MA 802.11bgn [Realtek RTL8188CUS] usb:v0846p9043* ID_MODEL_FROM_DATABASE=WNA1000Mv2 802.11bgn [Realtek RTL8188CUS?] usb:v0846p9050* ID_MODEL_FROM_DATABASE=A6200 802.11a/b/g/n/ac Wireless Adapter [Broadcom BCM43526] usb:v0846p9052* ID_MODEL_FROM_DATABASE=A6100 AC600 DB Wireless Adapter [Realtek RTL8811AU] usb:v0846pA001* ID_MODEL_FROM_DATABASE=PA101 10 Mbps HPNA Home Phoneline RJ-1 usb:v0846pF001* ID_MODEL_FROM_DATABASE=On Networks N300MA 802.11bgn [Realtek RTL8192CU] usb:v084D* ID_VENDOR_FROM_DATABASE=Minton Optic Industry Co., Inc. usb:v084Dp0001* ID_MODEL_FROM_DATABASE=Jenoptik JD800i usb:v084Dp0003* ID_MODEL_FROM_DATABASE=S-Cam F5/D-Link DSC-350 Digital Camera usb:v084Dp0011* ID_MODEL_FROM_DATABASE=Argus DC3500 Digital Camera usb:v084Dp0014* ID_MODEL_FROM_DATABASE=Praktica DC 32 usb:v084Dp0019* ID_MODEL_FROM_DATABASE=Praktica DPix3000 usb:v084Dp0025* ID_MODEL_FROM_DATABASE=Praktica DC 60 usb:v084Dp1001* ID_MODEL_FROM_DATABASE=ScanHex SX-35d usb:v084E* ID_VENDOR_FROM_DATABASE=KB Gear usb:v084Ep0001* ID_MODEL_FROM_DATABASE=JamCam Camera usb:v084Ep1001* ID_MODEL_FROM_DATABASE=Jam Studio Tablet usb:v084Ep1002* ID_MODEL_FROM_DATABASE=Pablo Tablet usb:v084F* ID_VENDOR_FROM_DATABASE=Empeg usb:v084Fp0001* ID_MODEL_FROM_DATABASE=Empeg-Car Mark I/II Player usb:v0850* ID_VENDOR_FROM_DATABASE=Fast Point Technologies, Inc. usb:v0851* ID_VENDOR_FROM_DATABASE=Macronix International Co., Ltd usb:v0851p1542* ID_MODEL_FROM_DATABASE=SiPix Blink usb:v0851p1543* ID_MODEL_FROM_DATABASE=Maxell WS30 Slim Digital Camera, or Pandigital PI8004W01 digital photo frame usb:v0851pA168* ID_MODEL_FROM_DATABASE=MXIC usb:v0852* ID_VENDOR_FROM_DATABASE=CSEM usb:v0853* ID_VENDOR_FROM_DATABASE=Topre Corporation usb:v0853p0100* ID_MODEL_FROM_DATABASE=HHKB Professional usb:v0854* ID_VENDOR_FROM_DATABASE=ActiveWire, Inc. usb:v0854p0100* ID_MODEL_FROM_DATABASE=I/O Board usb:v0854p0101* ID_MODEL_FROM_DATABASE=I/O Board, rev1 usb:v0856* ID_VENDOR_FROM_DATABASE=B&B Electronics usb:v0856pAC01* ID_MODEL_FROM_DATABASE=uLinks USOTL4 RS422/485 Adapter usb:v0858* ID_VENDOR_FROM_DATABASE=Hitachi Maxell, Ltd usb:v0858p3102* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0858pFFFF* ID_MODEL_FROM_DATABASE=Maxell module with BlueCore in DFU mode usb:v0859* ID_VENDOR_FROM_DATABASE=Minolta Systems Laboratory, Inc. usb:v085A* ID_VENDOR_FROM_DATABASE=Xircom usb:v085Ap0001* ID_MODEL_FROM_DATABASE=Portstation Dual Serial Port usb:v085Ap0003* ID_MODEL_FROM_DATABASE=Portstation Paraller Port usb:v085Ap0008* ID_MODEL_FROM_DATABASE=Ethernet usb:v085Ap0009* ID_MODEL_FROM_DATABASE=Ethernet usb:v085Ap000B* ID_MODEL_FROM_DATABASE=Portstation Dual PS/2 Port usb:v085Ap0021* ID_MODEL_FROM_DATABASE=1 port to Serial Converter usb:v085Ap0022* ID_MODEL_FROM_DATABASE=Parallel Port usb:v085Ap0023* ID_MODEL_FROM_DATABASE=2 port to Serial Converter usb:v085Ap0024* ID_MODEL_FROM_DATABASE=Parallel Port usb:v085Ap0026* ID_MODEL_FROM_DATABASE=PortGear SCSI usb:v085Ap0027* ID_MODEL_FROM_DATABASE=1 port to Serial Converter usb:v085Ap0028* ID_MODEL_FROM_DATABASE=PortGear to SCSI Converter usb:v085Ap0032* ID_MODEL_FROM_DATABASE=PortStation SCSI Module usb:v085Ap003C* ID_MODEL_FROM_DATABASE=Bluetooth Adapter usb:v085Ap0299* ID_MODEL_FROM_DATABASE=Colorvision, Inc. Monitor Spyder usb:v085Ap8021* ID_MODEL_FROM_DATABASE=1 port to Serial usb:v085Ap8023* ID_MODEL_FROM_DATABASE=2 port to Serial usb:v085Ap8027* ID_MODEL_FROM_DATABASE=PGSDB9 Serial Port usb:v085C* ID_VENDOR_FROM_DATABASE=ColorVision, Inc. usb:v085Cp0100* ID_MODEL_FROM_DATABASE=Spyder 1 usb:v085Cp0200* ID_MODEL_FROM_DATABASE=Spyder 2 usb:v085Cp0300* ID_MODEL_FROM_DATABASE=Spyder 3 usb:v085Cp0400* ID_MODEL_FROM_DATABASE=Spyder 4 usb:v0862* ID_VENDOR_FROM_DATABASE=Teletrol Systems, Inc. usb:v0863* ID_VENDOR_FROM_DATABASE=Filanet Corp. usb:v0864* ID_VENDOR_FROM_DATABASE=NetGear, Inc. usb:v0864p4100* ID_MODEL_FROM_DATABASE=MA101 802.11b Adapter usb:v0864p4102* ID_MODEL_FROM_DATABASE=MA101 802.11b Adapter usb:v0867* ID_VENDOR_FROM_DATABASE=Data Translation, Inc. usb:v0867p9812* ID_MODEL_FROM_DATABASE=ECON Data acquisition unit usb:v0867p9816* ID_MODEL_FROM_DATABASE=DT9816 ECON data acquisition module usb:v0867p9836* ID_MODEL_FROM_DATABASE=DT9836 data acquisition card usb:v086A* ID_VENDOR_FROM_DATABASE=Emagic Soft- und Hardware GmbH usb:v086Ap0001* ID_MODEL_FROM_DATABASE=Unitor8 usb:v086Ap0002* ID_MODEL_FROM_DATABASE=AMT8 usb:v086Ap0003* ID_MODEL_FROM_DATABASE=MT4 usb:v086C* ID_VENDOR_FROM_DATABASE=DeTeWe - Deutsche Telephonwerke AG & Co. usb:v086Cp1001* ID_MODEL_FROM_DATABASE=Eumex 504PC ISDN TA usb:v086Cp1002* ID_MODEL_FROM_DATABASE=Eumex 504PC (FlashLoad) usb:v086Cp1003* ID_MODEL_FROM_DATABASE=TA33 ISDN TA usb:v086Cp1004* ID_MODEL_FROM_DATABASE=TA33 (FlashLoad) usb:v086Cp1005* ID_MODEL_FROM_DATABASE=Eumex 604PC HomeNet usb:v086Cp1006* ID_MODEL_FROM_DATABASE=Eumex 604PC HomeNet (FlashLoad) usb:v086Cp1007* ID_MODEL_FROM_DATABASE=Eumex 704PC DSL usb:v086Cp1008* ID_MODEL_FROM_DATABASE=Eumex 704PC DSL (FlashLoad) usb:v086Cp1009* ID_MODEL_FROM_DATABASE=Eumex 724PC DSL usb:v086Cp100A* ID_MODEL_FROM_DATABASE=Eumex 724PC DSL (FlashLoad) usb:v086Cp100B* ID_MODEL_FROM_DATABASE=OpenCom 30 usb:v086Cp100C* ID_MODEL_FROM_DATABASE=OpenCom 30 (FlashLoad) usb:v086Cp100D* ID_MODEL_FROM_DATABASE=BeeTel Home 100 usb:v086Cp100E* ID_MODEL_FROM_DATABASE=BeeTel Home 100 (FlashLoad) usb:v086Cp1011* ID_MODEL_FROM_DATABASE=USB2DECT usb:v086Cp1012* ID_MODEL_FROM_DATABASE=USB2DECT (FlashLoad) usb:v086Cp1013* ID_MODEL_FROM_DATABASE=Eumex 704PC LAN usb:v086Cp1014* ID_MODEL_FROM_DATABASE=Eumex 704PC LAN (FlashLoad) usb:v086Cp1019* ID_MODEL_FROM_DATABASE=Eumex 504 SE usb:v086Cp101A* ID_MODEL_FROM_DATABASE=Eumex 504 SE (Flash-Mode) usb:v086Cp1021* ID_MODEL_FROM_DATABASE=OpenCom 40 usb:v086Cp1022* ID_MODEL_FROM_DATABASE=OpenCom 40 (FlashLoad) usb:v086Cp1023* ID_MODEL_FROM_DATABASE=OpenCom 45 usb:v086Cp1024* ID_MODEL_FROM_DATABASE=OpenCom 45 (FlashLoad) usb:v086Cp1025* ID_MODEL_FROM_DATABASE=Sinus 61 data usb:v086Cp1029* ID_MODEL_FROM_DATABASE=dect BOX usb:v086Cp102C* ID_MODEL_FROM_DATABASE=Eumex 604PC HomeNet [FlashLoad] usb:v086Cp1030* ID_MODEL_FROM_DATABASE=Eumex 704PC DSL [FlashLoad] usb:v086Cp1032* ID_MODEL_FROM_DATABASE=OpenCom 40 [FlashLoad] usb:v086Cp1033* ID_MODEL_FROM_DATABASE=OpenCom 30 plus usb:v086Cp1034* ID_MODEL_FROM_DATABASE=OpenCom 30 plus (FlashLoad) usb:v086Cp1041* ID_MODEL_FROM_DATABASE=Eumex 220PC usb:v086Cp1042* ID_MODEL_FROM_DATABASE=Eumex 220PC (FlashMode) usb:v086Cp1055* ID_MODEL_FROM_DATABASE=Eumex 220 Version 2 ISDN TA usb:v086Cp1056* ID_MODEL_FROM_DATABASE=Eumex 220 Version 2 ISDN TA (Flash-Mode) usb:v086Cp2000* ID_MODEL_FROM_DATABASE=OpenCom 1000 usb:v086E* ID_VENDOR_FROM_DATABASE=System TALKS, Inc. usb:v086Ep1920* ID_MODEL_FROM_DATABASE=SGC-X2UL usb:v086F* ID_VENDOR_FROM_DATABASE=MEC IMEX, Inc. usb:v0870* ID_VENDOR_FROM_DATABASE=Metricom usb:v0870p0001* ID_MODEL_FROM_DATABASE=Ricochet GS usb:v0871* ID_VENDOR_FROM_DATABASE=SanDisk, Inc. usb:v0871p0001* ID_MODEL_FROM_DATABASE=SDDR-01 Compact Flash Reader usb:v0871p0002* ID_MODEL_FROM_DATABASE=SDDR-31 Compact Flash Reader usb:v0871p0005* ID_MODEL_FROM_DATABASE=SDDR-05 Compact Flash Reader usb:v0873* ID_VENDOR_FROM_DATABASE=Xpeed, Inc. usb:v0874* ID_VENDOR_FROM_DATABASE=A-Tec Subsystem, Inc. usb:v0879* ID_VENDOR_FROM_DATABASE=Comtrol Corp. usb:v087C* ID_VENDOR_FROM_DATABASE=Adesso/Kbtek America, Inc. usb:v087D* ID_VENDOR_FROM_DATABASE=Jaton Corp. usb:v087Dp5704* ID_MODEL_FROM_DATABASE=Ethernet usb:v087E* ID_VENDOR_FROM_DATABASE=Fujitsu Computer Products of America usb:v087F* ID_VENDOR_FROM_DATABASE=QualCore Logic Inc. usb:v0880* ID_VENDOR_FROM_DATABASE=APT Technologies, Inc. usb:v0883* ID_VENDOR_FROM_DATABASE=Recording Industry Association of America (RIAA) usb:v0885* ID_VENDOR_FROM_DATABASE=Boca Research, Inc. usb:v0886* ID_VENDOR_FROM_DATABASE=XAC Automation Corp. usb:v0886p0630* ID_MODEL_FROM_DATABASE=Intel PC Camera CS630 usb:v0887* ID_VENDOR_FROM_DATABASE=Hannstar Electronics Corp. usb:v088A* ID_VENDOR_FROM_DATABASE=TechTools usb:v088Ap1002* ID_MODEL_FROM_DATABASE=DigiView DV3100 usb:v088B* ID_VENDOR_FROM_DATABASE=MassWorks, Inc. usb:v088Bp4944* ID_MODEL_FROM_DATABASE=MassWorks ID-75 TouchScreen usb:v088C* ID_VENDOR_FROM_DATABASE=Swecoin AB usb:v088Cp2030* ID_MODEL_FROM_DATABASE=Ticket Printer TTP 2030 usb:v088E* ID_VENDOR_FROM_DATABASE=iLok usb:v088Ep5036* ID_MODEL_FROM_DATABASE=Portable secure storage for software licenses usb:v0892* ID_VENDOR_FROM_DATABASE=DioGraphy, Inc. usb:v0892p0101* ID_MODEL_FROM_DATABASE=Smartdio Reader/Writer usb:v0894* ID_VENDOR_FROM_DATABASE=TSI Incorporated usb:v0894p0010* ID_MODEL_FROM_DATABASE=Remote NDIS Network Device usb:v0897* ID_VENDOR_FROM_DATABASE=Lauterbach usb:v0897p0002* ID_MODEL_FROM_DATABASE=Power Debug/Power Debug II usb:v089C* ID_VENDOR_FROM_DATABASE=United Technologies Research Cntr. usb:v089D* ID_VENDOR_FROM_DATABASE=Icron Technologies Corp. usb:v089E* ID_VENDOR_FROM_DATABASE=NST Co., Ltd usb:v089F* ID_VENDOR_FROM_DATABASE=Primex Aerospace Co. usb:v08A5* ID_VENDOR_FROM_DATABASE=e9, Inc. usb:v08A6* ID_VENDOR_FROM_DATABASE=Toshiba TEC usb:v08A6p0051* ID_MODEL_FROM_DATABASE=B-SV4 usb:v08A8* ID_VENDOR_FROM_DATABASE=Andrea Electronics usb:v08A9* ID_VENDOR_FROM_DATABASE=CWAV Inc. usb:v08A9p0005* ID_MODEL_FROM_DATABASE=USBee ZX usb:v08A9p0009* ID_MODEL_FROM_DATABASE=USBee SX usb:v08A9p0012* ID_MODEL_FROM_DATABASE=USBee AX-Standard usb:v08A9p0013* ID_MODEL_FROM_DATABASE=USBee AX-Plus usb:v08A9p0014* ID_MODEL_FROM_DATABASE=USBee AX-Pro usb:v08A9p0015* ID_MODEL_FROM_DATABASE=USBee DX usb:v08AC* ID_VENDOR_FROM_DATABASE=Macraigor Systems LLC usb:v08ACp2024* ID_MODEL_FROM_DATABASE=usbWiggler usb:v08AE* ID_VENDOR_FROM_DATABASE=Macally (Mace Group, Inc.) usb:v08B0* ID_VENDOR_FROM_DATABASE=Metrohm usb:v08B0p0006* ID_MODEL_FROM_DATABASE=814 Sample Processor usb:v08B0p0015* ID_MODEL_FROM_DATABASE=857 Titrando usb:v08B0p001A* ID_MODEL_FROM_DATABASE=852 Titrando usb:v08B4* ID_VENDOR_FROM_DATABASE=Sorenson Vision, Inc. usb:v08B7* ID_VENDOR_FROM_DATABASE=NATSU usb:v08B7p0001* ID_MODEL_FROM_DATABASE=Playstation adapter usb:v08B8* ID_VENDOR_FROM_DATABASE=J. Gordon Electronic Design, Inc. usb:v08B8p01F4* ID_MODEL_FROM_DATABASE=USBSIMM1 usb:v08B9* ID_VENDOR_FROM_DATABASE=RadioShack Corp. (Tandy) usb:v08BB* ID_VENDOR_FROM_DATABASE=Texas Instruments usb:v08BBp2702* ID_MODEL_FROM_DATABASE=Speakers usb:v08BBp2704* ID_MODEL_FROM_DATABASE=Audio Codec usb:v08BBp2706* ID_MODEL_FROM_DATABASE=PCM2706 Audio Codec usb:v08BBp2900* ID_MODEL_FROM_DATABASE=PCM2900 Audio Codec usb:v08BBp2901* ID_MODEL_FROM_DATABASE=PCM2901 Audio Codec usb:v08BBp2902* ID_MODEL_FROM_DATABASE=PCM2902 Audio Codec usb:v08BBp2904* ID_MODEL_FROM_DATABASE=PCM2904 Audio Codec usb:v08BBp2910* ID_MODEL_FROM_DATABASE=PCM2912 Audio Codec usb:v08BBp29B0* ID_MODEL_FROM_DATABASE=PCM2900B Audio CODEC usb:v08BBp29B2* ID_MODEL_FROM_DATABASE=PCM2902 Audio CODEC usb:v08BBp29B3* ID_MODEL_FROM_DATABASE=PCM2903B Audio CODEC usb:v08BBp29B6* ID_MODEL_FROM_DATABASE=PCM2906B Audio CODEC usb:v08BBp29C0* ID_MODEL_FROM_DATABASE=PCM2900C Audio CODEC usb:v08BBp29C2* ID_MODEL_FROM_DATABASE=PCM2902C Audio CODEC usb:v08BBp29C3* ID_MODEL_FROM_DATABASE=PCM2903C Audio CODEC usb:v08BBp29C6* ID_MODEL_FROM_DATABASE=PCM2906C Audio CODEC usb:v08BD* ID_VENDOR_FROM_DATABASE=Citizen Watch Co., Ltd usb:v08BDp0208* ID_MODEL_FROM_DATABASE=CLP-521 Label Printer usb:v08BDp1100* ID_MODEL_FROM_DATABASE=X1-USB Floppy usb:v08C3* ID_VENDOR_FROM_DATABASE=Precise Biometrics usb:v08C3p0001* ID_MODEL_FROM_DATABASE=100 SC usb:v08C3p0002* ID_MODEL_FROM_DATABASE=100 A usb:v08C3p0003* ID_MODEL_FROM_DATABASE=100 SC BioKeyboard usb:v08C3p0006* ID_MODEL_FROM_DATABASE=100 A BioKeyboard usb:v08C3p0100* ID_MODEL_FROM_DATABASE=100 MC ISP usb:v08C3p0101* ID_MODEL_FROM_DATABASE=100 MC FingerPrint and SmartCard Reader usb:v08C3p0300* ID_MODEL_FROM_DATABASE=100 AX usb:v08C3p0400* ID_MODEL_FROM_DATABASE=100 SC usb:v08C3p0401* ID_MODEL_FROM_DATABASE=150 MC usb:v08C3p0402* ID_MODEL_FROM_DATABASE=200 MC FingerPrint and SmartCard Reader usb:v08C3p0404* ID_MODEL_FROM_DATABASE=100 SC Upgrade usb:v08C3p0405* ID_MODEL_FROM_DATABASE=150 MC Upgrade usb:v08C3p0406* ID_MODEL_FROM_DATABASE=100 MC Upgrade usb:v08C4* ID_VENDOR_FROM_DATABASE=Proxim, Inc. usb:v08C4p0100* ID_MODEL_FROM_DATABASE=Skyline 802.11b Wireless Adapter usb:v08C4p02F2* ID_MODEL_FROM_DATABASE=Farallon Home Phoneline Adapter usb:v08C7* ID_VENDOR_FROM_DATABASE=Key Nice Enterprise Co., Ltd usb:v08C8* ID_VENDOR_FROM_DATABASE=2Wire, Inc. usb:v08C9* ID_VENDOR_FROM_DATABASE=Nippon Telegraph and Telephone Corp. usb:v08CA* ID_VENDOR_FROM_DATABASE=Aiptek International, Inc. usb:v08CAp0001* ID_MODEL_FROM_DATABASE=Tablet usb:v08CAp0010* ID_MODEL_FROM_DATABASE=Tablet usb:v08CAp0020* ID_MODEL_FROM_DATABASE=APT-6000U Tablet usb:v08CAp0021* ID_MODEL_FROM_DATABASE=APT-2 Tablet usb:v08CAp0022* ID_MODEL_FROM_DATABASE=Tablet usb:v08CAp0023* ID_MODEL_FROM_DATABASE=Tablet usb:v08CAp0024* ID_MODEL_FROM_DATABASE=Tablet usb:v08CAp0100* ID_MODEL_FROM_DATABASE=Pen Drive usb:v08CAp0102* ID_MODEL_FROM_DATABASE=DualCam usb:v08CAp0103* ID_MODEL_FROM_DATABASE=Pocket DV Digital Camera usb:v08CAp0104* ID_MODEL_FROM_DATABASE=Pocket DVII usb:v08CAp0105* ID_MODEL_FROM_DATABASE=Mega DV(Disk) usb:v08CAp0106* ID_MODEL_FROM_DATABASE=Pocket DV3100+ usb:v08CAp0107* ID_MODEL_FROM_DATABASE=Pocket DV3100 usb:v08CAp0109* ID_MODEL_FROM_DATABASE=Nisis DV4 Digital Camera usb:v08CAp010A* ID_MODEL_FROM_DATABASE=Trust 738AV LCD PV Mass Storage usb:v08CAp0111* ID_MODEL_FROM_DATABASE=PenCam VGA Plus usb:v08CAp2008* ID_MODEL_FROM_DATABASE=Mini PenCam 2 usb:v08CAp2010* ID_MODEL_FROM_DATABASE=Pocket CAM 3 Mega (webcam) usb:v08CAp2011* ID_MODEL_FROM_DATABASE=Pocket CAM 3 Mega (storage) usb:v08CAp2016* ID_MODEL_FROM_DATABASE=PocketCam 2 Mega usb:v08CAp2018* ID_MODEL_FROM_DATABASE=Pencam SD 2M usb:v08CAp2020* ID_MODEL_FROM_DATABASE=Slim 3000F usb:v08CAp2022* ID_MODEL_FROM_DATABASE=Slim 3200 usb:v08CAp2024* ID_MODEL_FROM_DATABASE=Pocket DV3500 usb:v08CAp2028* ID_MODEL_FROM_DATABASE=Pocket Cam4M usb:v08CAp2040* ID_MODEL_FROM_DATABASE=Pocket DV4100M usb:v08CAp2042* ID_MODEL_FROM_DATABASE=Pocket DV5100M Composite Device usb:v08CAp2043* ID_MODEL_FROM_DATABASE=Pocket DV5100M (Disk) usb:v08CAp2060* ID_MODEL_FROM_DATABASE=Pocket DV5300 usb:v08CD* ID_VENDOR_FROM_DATABASE=Jue Hsun Ind. Corp. usb:v08CE* ID_VENDOR_FROM_DATABASE=Long Well Electronics Corp. usb:v08CF* ID_VENDOR_FROM_DATABASE=Productivity Enhancement Products usb:v08D1* ID_VENDOR_FROM_DATABASE=smartBridges, Inc. usb:v08D1p0001* ID_MODEL_FROM_DATABASE=smartNIC Ethernet [catc] usb:v08D1p0003* ID_MODEL_FROM_DATABASE=smartNIC 2 PnP Ethernet usb:v08D3* ID_VENDOR_FROM_DATABASE=Virtual Ink usb:v08D4* ID_VENDOR_FROM_DATABASE=Fujitsu Siemens Computers usb:v08D4p0009* ID_MODEL_FROM_DATABASE=SCR SmartCard Reader usb:v08D8* ID_VENDOR_FROM_DATABASE=IXXAT Automation GmbH usb:v08D8p0002* ID_MODEL_FROM_DATABASE=USB-to-CAN compact usb:v08D8p0003* ID_MODEL_FROM_DATABASE=USB-to-CAN II usb:v08D8p0100* ID_MODEL_FROM_DATABASE=USB-to-CAN usb:v08D9* ID_VENDOR_FROM_DATABASE=Increment P Corp. usb:v08DD* ID_VENDOR_FROM_DATABASE=Billionton Systems, Inc. usb:v08DDp0112* ID_MODEL_FROM_DATABASE=Wireless LAN Adapter usb:v08DDp0113* ID_MODEL_FROM_DATABASE=Wireless LAN Adapter usb:v08DDp0986* ID_MODEL_FROM_DATABASE=USB-100N Ethernet [pegasus] usb:v08DDp0987* ID_MODEL_FROM_DATABASE=USBLP-100 HomePNA Ethernet [pegasus] usb:v08DDp0988* ID_MODEL_FROM_DATABASE=USBEL-100 Ethernet [pegasus] usb:v08DDp1986* ID_MODEL_FROM_DATABASE=10/100 LAN Adapter usb:v08DDp2103* ID_MODEL_FROM_DATABASE=DVB-T TV-Tuner Card-R usb:v08DDp8511* ID_MODEL_FROM_DATABASE=USBE-100 Ethernet [pegasus2] usb:v08DDp90FF* ID_MODEL_FROM_DATABASE=USB2AR Ethernet usb:v08DE* ID_VENDOR_FROM_DATABASE=??? usb:v08DEp7A01* ID_MODEL_FROM_DATABASE=802.11b Adapter usb:v08DF* ID_VENDOR_FROM_DATABASE=Spyrus, Inc. usb:v08DFp0001* ID_MODEL_FROM_DATABASE=Rosetta Token V1 usb:v08DFp0002* ID_MODEL_FROM_DATABASE=Rosetta Token V2 usb:v08DFp0003* ID_MODEL_FROM_DATABASE=Rosetta Token V3 usb:v08DFp0A00* ID_MODEL_FROM_DATABASE=Lynks Interface usb:v08E3* ID_VENDOR_FROM_DATABASE=Olitec, Inc. usb:v08E3p0002* ID_MODEL_FROM_DATABASE=USB-RS232 Bridge usb:v08E3p0100* ID_MODEL_FROM_DATABASE=Interface ADSL usb:v08E3p0101* ID_MODEL_FROM_DATABASE=Interface ADSL usb:v08E3p0102* ID_MODEL_FROM_DATABASE=ADSL usb:v08E3p0301* ID_MODEL_FROM_DATABASE=RNIS ISDN TA [HFC-S] usb:v08E4* ID_VENDOR_FROM_DATABASE=Pioneer Corp. usb:v08E4p0184* ID_MODEL_FROM_DATABASE=DDJ-WeGO usb:v08E4p0185* ID_MODEL_FROM_DATABASE=DDJ-WeGO2 usb:v08E5* ID_VENDOR_FROM_DATABASE=Litronic usb:v08E6* ID_VENDOR_FROM_DATABASE=Gemalto (was Gemplus) usb:v08E6p0001* ID_MODEL_FROM_DATABASE=GemPC-Touch 430 usb:v08E6p0430* ID_MODEL_FROM_DATABASE=GemPC430 SmartCard Reader usb:v08E6p0432* ID_MODEL_FROM_DATABASE=GemPC432 SmartCard Reader usb:v08E6p0435* ID_MODEL_FROM_DATABASE=GemPC435 SmartCard Reader usb:v08E6p0437* ID_MODEL_FROM_DATABASE=GemPC433 SL SmartCard Reader usb:v08E6p1359* ID_MODEL_FROM_DATABASE=UA SECURE STORAGE TOKEN usb:v08E6p2202* ID_MODEL_FROM_DATABASE=Gem e-Seal Pro Token usb:v08E6p3437* ID_MODEL_FROM_DATABASE=GemPC Twin SmartCard Reader usb:v08E6p3438* ID_MODEL_FROM_DATABASE=GemPC Key SmartCard Reader usb:v08E6p3478* ID_MODEL_FROM_DATABASE=PinPad Smart Card Reader usb:v08E6p34EC* ID_MODEL_FROM_DATABASE=Compact Smart Card Reader Writer usb:v08E6p4433* ID_MODEL_FROM_DATABASE=GemPC433-Swap usb:v08E6p5501* ID_MODEL_FROM_DATABASE=GemProx-PU Contactless Smart Card Reader usb:v08E6p5503* ID_MODEL_FROM_DATABASE=Prox-DU Contactless Interface usb:v08E6pACE0* ID_MODEL_FROM_DATABASE=UA HYBRID TOKEN usb:v08E7* ID_VENDOR_FROM_DATABASE=Pan-International Wire & Cable usb:v08E8* ID_VENDOR_FROM_DATABASE=Integrated Memory Logic usb:v08E9* ID_VENDOR_FROM_DATABASE=Extended Systems, Inc. usb:v08E9p0100* ID_MODEL_FROM_DATABASE=XTNDAccess IrDA Dongle usb:v08EA* ID_VENDOR_FROM_DATABASE=Ericsson, Inc., Blue Ridge Labs usb:v08EAp00C9* ID_MODEL_FROM_DATABASE=ADSL Modem HM120dp Loader usb:v08EAp00CA* ID_MODEL_FROM_DATABASE=ADSL WAN Modem HM120dp usb:v08EAp00CE* ID_MODEL_FROM_DATABASE=HM230d Virtual Bus for Helium usb:v08EApABBA* ID_MODEL_FROM_DATABASE=USB Driver for Bluetooth Wireless Technology usb:v08EApABBB* ID_MODEL_FROM_DATABASE=Bluetooth Device in DFU State usb:v08EC* ID_VENDOR_FROM_DATABASE=M-Systems Flash Disk Pioneers usb:v08ECp0001* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v08ECp0002* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v08ECp0005* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v08ECp0008* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v08ECp0010* ID_MODEL_FROM_DATABASE=DiskOnKey usb:v08ECp0011* ID_MODEL_FROM_DATABASE=DiskOnKey usb:v08ECp0012* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v08ECp0014* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v08ECp0015* ID_MODEL_FROM_DATABASE=Kingston DataTraveler ELITE usb:v08ECp0016* ID_MODEL_FROM_DATABASE=Kingston DataTraveler U3 usb:v08ECp0020* ID_MODEL_FROM_DATABASE=TravelDrive Intuix U3 2GB usb:v08ECp0021* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ECp0022* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ECp0023* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ECp0024* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ECp0025* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ECp0026* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ECp0027* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ECp0028* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ECp0029* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ECp0030* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ECp0822* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v08ECp0832* ID_MODEL_FROM_DATABASE=Hi-Speed Mass Storage Device usb:v08ECp0834* ID_MODEL_FROM_DATABASE=M-Disk 220 usb:v08ECp0998* ID_MODEL_FROM_DATABASE=Kingston Data Traveler2.0 Disk Driver usb:v08ECp0999* ID_MODEL_FROM_DATABASE=Kingston Data Traveler2.0 Disk Driver usb:v08ECp1000* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v08ECp2000* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v08ECp2038* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ECp2039* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ECp204A* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ECp204B* ID_MODEL_FROM_DATABASE=TravelDrive usb:v08ED* ID_VENDOR_FROM_DATABASE=MediaTek Inc. usb:v08EDp0002* ID_MODEL_FROM_DATABASE=CECT M800 memory card usb:v08EE* ID_VENDOR_FROM_DATABASE=CCSI/Hesso usb:v08F0* ID_VENDOR_FROM_DATABASE=Corex Technologies usb:v08F1* ID_VENDOR_FROM_DATABASE=CTI Electronics Corp. usb:v08F2* ID_VENDOR_FROM_DATABASE=Gotop Information Inc. usb:v08F2p007F* ID_MODEL_FROM_DATABASE=Super Q2 Tablet usb:v08F5* ID_VENDOR_FROM_DATABASE=SysTec Co., Ltd usb:v08F6* ID_VENDOR_FROM_DATABASE=Logic 3 International, Ltd usb:v08F7* ID_VENDOR_FROM_DATABASE=Vernier usb:v08F7p0001* ID_MODEL_FROM_DATABASE=LabPro usb:v08F7p0002* ID_MODEL_FROM_DATABASE=EasyTemp/Go!Temp usb:v08F7p0003* ID_MODEL_FROM_DATABASE=Go!Link usb:v08F7p0004* ID_MODEL_FROM_DATABASE=Go!Motion usb:v08F8* ID_VENDOR_FROM_DATABASE=Keen Top International Enterprise Co., Ltd usb:v08F9* ID_VENDOR_FROM_DATABASE=Wipro Technologies usb:v08FA* ID_VENDOR_FROM_DATABASE=Caere usb:v08FB* ID_VENDOR_FROM_DATABASE=Socket Communications usb:v08FC* ID_VENDOR_FROM_DATABASE=Sicon Cable Technology Co., Ltd usb:v08FD* ID_VENDOR_FROM_DATABASE=Digianswer A/S usb:v08FDp0001* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v08FF* ID_VENDOR_FROM_DATABASE=AuthenTec, Inc. usb:v08FFp1600* ID_MODEL_FROM_DATABASE=AES1600 usb:v08FFp1610* ID_MODEL_FROM_DATABASE=AES1600 usb:v08FFp1660* ID_MODEL_FROM_DATABASE=AES1660 Fingerprint Sensor usb:v08FFp1680* ID_MODEL_FROM_DATABASE=AES1660 Fingerprint Sensor usb:v08FFp168F* ID_MODEL_FROM_DATABASE=AES1660 Fingerprint Sensor usb:v08FFp2500* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp2501* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp2502* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp2503* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp2504* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp2505* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp2506* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp2507* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp2508* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp2509* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp250A* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp250B* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp250C* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp250D* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp250E* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp250F* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp2510* ID_MODEL_FROM_DATABASE=AES2510 usb:v08FFp2550* ID_MODEL_FROM_DATABASE=AES2550 Fingerprint Sensor usb:v08FFp2580* ID_MODEL_FROM_DATABASE=AES2501 Fingerprint Sensor usb:v08FFp2588* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp2589* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp258A* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp258B* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp258C* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp258D* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp258E* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp258F* ID_MODEL_FROM_DATABASE=AES2501 usb:v08FFp2660* ID_MODEL_FROM_DATABASE=AES2660 Fingerprint Sensor usb:v08FFp2680* ID_MODEL_FROM_DATABASE=AES2660 Fingerprint Sensor usb:v08FFp268F* ID_MODEL_FROM_DATABASE=AES2660 Fingerprint Sensor usb:v08FFp2810* ID_MODEL_FROM_DATABASE=AES2810 usb:v08FFp3400* ID_MODEL_FROM_DATABASE=AES3400 TruePrint Sensor usb:v08FFp3401* ID_MODEL_FROM_DATABASE=AES3400 Sensor usb:v08FFp3402* ID_MODEL_FROM_DATABASE=AES3400 Sensor usb:v08FFp3403* ID_MODEL_FROM_DATABASE=AES3400 Sensor usb:v08FFp3404* ID_MODEL_FROM_DATABASE=AES3400 TruePrint Sensor usb:v08FFp3405* ID_MODEL_FROM_DATABASE=AES3400 TruePrint Sensor usb:v08FFp3406* ID_MODEL_FROM_DATABASE=AES3400 TruePrint Sensor usb:v08FFp3407* ID_MODEL_FROM_DATABASE=AES3400 TruePrint Sensor usb:v08FFp4902* ID_MODEL_FROM_DATABASE=BioMV with TruePrint AES3500 usb:v08FFp4903* ID_MODEL_FROM_DATABASE=BioMV with TruePrint AES3400 usb:v08FFp5500* ID_MODEL_FROM_DATABASE=AES4000 usb:v08FFp5501* ID_MODEL_FROM_DATABASE=AES4000 TruePrint Sensor usb:v08FFp5503* ID_MODEL_FROM_DATABASE=AES4000 TruePrint Sensor usb:v08FFp5505* ID_MODEL_FROM_DATABASE=AES4000 TruePrint Sensor usb:v08FFp5507* ID_MODEL_FROM_DATABASE=AES4000 TruePrint Sensor usb:v08FFp55FF* ID_MODEL_FROM_DATABASE=AES4000 TruePrint Sensor. usb:v08FFp5700* ID_MODEL_FROM_DATABASE=AES3500 Fingerprint Reader usb:v08FFp5701* ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor usb:v08FFp5702* ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor usb:v08FFp5703* ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor usb:v08FFp5704* ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor usb:v08FFp5705* ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor usb:v08FFp5706* ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor usb:v08FFp5707* ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor usb:v08FFp5710* ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor usb:v08FFp5711* ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor usb:v08FFp5712* ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor usb:v08FFp5713* ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor usb:v08FFp5714* ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor usb:v08FFp5715* ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor usb:v08FFp5716* ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor usb:v08FFp5717* ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor usb:v08FFp5730* ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor usb:v08FFp5731* ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor usb:v08FFp5732* ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor usb:v08FFp5733* ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor usb:v08FFp5734* ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor usb:v08FFp5735* ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor usb:v08FFp5736* ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor usb:v08FFp5737* ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor usb:v08FFpAFE3* ID_MODEL_FROM_DATABASE=FingerLoc Sensor Module (Anchor) usb:v08FFpAFE4* ID_MODEL_FROM_DATABASE=FingerLoc Sensor Module (Anchor) usb:v08FFpAFE5* ID_MODEL_FROM_DATABASE=FingerLoc Sensor Module (Anchor) usb:v08FFpAFE6* ID_MODEL_FROM_DATABASE=FingerLoc Sensor Module (Anchor) usb:v08FFpFFFD* ID_MODEL_FROM_DATABASE=AES2510 Sensor (USB Emulator) usb:v08FFpFFFF* ID_MODEL_FROM_DATABASE=Sensor (Emulator) usb:v0900* ID_VENDOR_FROM_DATABASE=Pinnacle Systems, Inc. usb:v0901* ID_VENDOR_FROM_DATABASE=VST Technologies usb:v0901p0001* ID_MODEL_FROM_DATABASE=Hard Drive Adapter (TPP) usb:v0901p0002* ID_MODEL_FROM_DATABASE=SigmaDrive Adapter (TPP) usb:v0906* ID_VENDOR_FROM_DATABASE=Faraday Technology Corp. usb:v0908* ID_VENDOR_FROM_DATABASE=Siemens AG usb:v0908p01F4* ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5711 usb:v0908p01FE* ID_MODEL_FROM_DATABASE=SIMATIC NET PC Adapter A2 usb:v0908p04B1* ID_MODEL_FROM_DATABASE=MediSET usb:v0908p04B2* ID_MODEL_FROM_DATABASE=NC interface usb:v0908p2701* ID_MODEL_FROM_DATABASE=ShenZhen SANZHAI Technology Co.,Ltd Spy Pen VGA usb:v0909* ID_VENDOR_FROM_DATABASE=Audio-Technica Corp. usb:v090A* ID_VENDOR_FROM_DATABASE=Trumpion Microelectronics, Inc. usb:v090Ap1001* ID_MODEL_FROM_DATABASE=T33520 Flash Card Controller usb:v090Ap1100* ID_MODEL_FROM_DATABASE=Comotron C3310 MP3 player usb:v090Ap1200* ID_MODEL_FROM_DATABASE=MP3 player usb:v090Ap1540* ID_MODEL_FROM_DATABASE=Digitex Container Flash Disk usb:v090B* ID_VENDOR_FROM_DATABASE=Neurosmith usb:v090C* ID_VENDOR_FROM_DATABASE=Silicon Motion, Inc. - Taiwan (formerly Feiya Technology Corp.) usb:v090Cp0371* ID_MODEL_FROM_DATABASE=Silicon Motion SM371 Camera usb:v090Cp0373* ID_MODEL_FROM_DATABASE=Silicon Motion Camera usb:v090Cp037A* ID_MODEL_FROM_DATABASE=Silicon Motion Camera usb:v090Cp037B* ID_MODEL_FROM_DATABASE=Silicon Motion Camera usb:v090Cp037C* ID_MODEL_FROM_DATABASE=300k Pixel Camera usb:v090Cp1000* ID_MODEL_FROM_DATABASE=Flash Drive usb:v090Cp1132* ID_MODEL_FROM_DATABASE=5-in-1 Card Reader usb:v090Cp337B* ID_MODEL_FROM_DATABASE=Silicon Motion Camera usb:v090Cp3710* ID_MODEL_FROM_DATABASE=Silicon Motion Camera usb:v090Cp3720* ID_MODEL_FROM_DATABASE=Silicon Motion Camera usb:v090Cp37BC* ID_MODEL_FROM_DATABASE=HP Webcam-101 Integrated Camera usb:v090Cp37C0* ID_MODEL_FROM_DATABASE=Silicon Motion Camera usb:v090Cp6000* ID_MODEL_FROM_DATABASE=SD/SDHC Card Reader (SG365 / FlexiDrive XC+) usb:v090Cp6200* ID_MODEL_FROM_DATABASE=microSD card reader usb:v090Cp71B3* ID_MODEL_FROM_DATABASE=SM731 Camera usb:v090Cp837B* ID_MODEL_FROM_DATABASE=Silicon Motion Camera usb:v090Cp937B* ID_MODEL_FROM_DATABASE=Silicon Motion Camera usb:v090CpB370* ID_MODEL_FROM_DATABASE=Silicon Motion SM370 Camera usb:v090CpB371* ID_MODEL_FROM_DATABASE=Silicon Motion SM371 Camera usb:v090CpF37D* ID_MODEL_FROM_DATABASE=Endoscope camera usb:v090D* ID_VENDOR_FROM_DATABASE=Multiport Computer Vertriebs GmbH usb:v090E* ID_VENDOR_FROM_DATABASE=Shining Technology, Inc. usb:v090F* ID_VENDOR_FROM_DATABASE=Fujitsu Devices, Inc. usb:v0910* ID_VENDOR_FROM_DATABASE=Alation Systems, Inc. usb:v0911* ID_VENDOR_FROM_DATABASE=Philips Speech Processing usb:v0911p149A* ID_MODEL_FROM_DATABASE=SpeechMike II Pro Plus LFH5276 usb:v0911p2512* ID_MODEL_FROM_DATABASE=SpeechMike Pro usb:v0912* ID_VENDOR_FROM_DATABASE=Voquette, Inc. usb:v0915* ID_VENDOR_FROM_DATABASE=GlobeSpan, Inc. usb:v0915p0001* ID_MODEL_FROM_DATABASE=DSL Modem usb:v0915p0002* ID_MODEL_FROM_DATABASE=ADSL ATM Modem usb:v0915p0005* ID_MODEL_FROM_DATABASE=LAN Modem usb:v0915p2000* ID_MODEL_FROM_DATABASE=802.11 Adapter usb:v0915p2002* ID_MODEL_FROM_DATABASE=802.11 Adapter usb:v0915p8000* ID_MODEL_FROM_DATABASE=ADSL LAN Modem usb:v0915p8005* ID_MODEL_FROM_DATABASE=DSL-302G Modem usb:v0915p8101* ID_MODEL_FROM_DATABASE=ADSL WAN Modem usb:v0915p8102* ID_MODEL_FROM_DATABASE=DSL-200 ADSL Modem usb:v0915p8103* ID_MODEL_FROM_DATABASE=DSL-200 ADSL Modem usb:v0915p8104* ID_MODEL_FROM_DATABASE=DSL-200 Modem usb:v0915p8400* ID_MODEL_FROM_DATABASE=DSL Modem usb:v0915p8401* ID_MODEL_FROM_DATABASE=DSL Modem usb:v0915p8402* ID_MODEL_FROM_DATABASE=DSL Modem usb:v0915p8500* ID_MODEL_FROM_DATABASE=DSL Modem usb:v0915p8501* ID_MODEL_FROM_DATABASE=DSL Modem usb:v0917* ID_VENDOR_FROM_DATABASE=SmartDisk Corp. usb:v0917p0001* ID_MODEL_FROM_DATABASE=eFilm Reader-11 SM/CF usb:v0917p0002* ID_MODEL_FROM_DATABASE=eFilm Reader-11 SM usb:v0917p0003* ID_MODEL_FROM_DATABASE=eFilm Reader-11 CF usb:v0917p0200* ID_MODEL_FROM_DATABASE=FireFly usb:v0917p0201* ID_MODEL_FROM_DATABASE=FireLite usb:v0917p0202* ID_MODEL_FROM_DATABASE=STORAGE ADAPTER (FirePower) usb:v0917p0204* ID_MODEL_FROM_DATABASE=FlashTrax Storage usb:v0917p0205* ID_MODEL_FROM_DATABASE=STORAGE ADAPTER (CrossFire) usb:v0917p0206* ID_MODEL_FROM_DATABASE=FireFly 20G HDD usb:v0917p0207* ID_MODEL_FROM_DATABASE=FireLite usb:v0917p020F* ID_MODEL_FROM_DATABASE=STORAGE ADAPTER (FireLite) usb:v0917pDA01* ID_MODEL_FROM_DATABASE=eFilm Reader-11 Test usb:v0917pFFFF* ID_MODEL_FROM_DATABASE=eFilm Reader-11 (Class/PDR) usb:v0919* ID_VENDOR_FROM_DATABASE=Tiger Electronics usb:v0919p0100* ID_MODEL_FROM_DATABASE=Fast Flicks Digital Camera usb:v091E* ID_VENDOR_FROM_DATABASE=Garmin International usb:v091Ep0003* ID_MODEL_FROM_DATABASE=GPS (various models) usb:v091Ep0004* ID_MODEL_FROM_DATABASE=iQue 3600 usb:v091Ep0200* ID_MODEL_FROM_DATABASE=Data Card Programmer (install) usb:v091Ep1200* ID_MODEL_FROM_DATABASE=Data Card Programmer usb:v091Ep21A5* ID_MODEL_FROM_DATABASE=etrex Cx (msc) usb:v091Ep2236* ID_MODEL_FROM_DATABASE=nuvi 360 usb:v091Ep2271* ID_MODEL_FROM_DATABASE=Edge 605/705 usb:v091Ep2295* ID_MODEL_FROM_DATABASE=Colorado 300 usb:v091Ep22B6* ID_MODEL_FROM_DATABASE=eTrex Vista HCx (Mass Storage mode) usb:v091Ep231B* ID_MODEL_FROM_DATABASE=Oregon 400t usb:v091Ep2353* ID_MODEL_FROM_DATABASE=Nüvi 205T usb:v091Ep2380* ID_MODEL_FROM_DATABASE=Oregon series usb:v091Ep23CC* ID_MODEL_FROM_DATABASE=nüvi 1350 usb:v091Ep2459* ID_MODEL_FROM_DATABASE=GPSmap 62/78 series usb:v091Ep2491* ID_MODEL_FROM_DATABASE=Edge 800 usb:v091Ep2519* ID_MODEL_FROM_DATABASE=eTrex 30 usb:v091Ep2535* ID_MODEL_FROM_DATABASE=Edge 800 usb:v091Ep253C* ID_MODEL_FROM_DATABASE=GPSmap 62sc usb:v091Ep255B* ID_MODEL_FROM_DATABASE=Nuvi 2505LM usb:v0920* ID_VENDOR_FROM_DATABASE=Echelon Co. usb:v0920p7500* ID_MODEL_FROM_DATABASE=Network Interface usb:v0921* ID_VENDOR_FROM_DATABASE=GoHubs, Inc. usb:v0921p1001* ID_MODEL_FROM_DATABASE=GoCOM232 Serial usb:v0922* ID_VENDOR_FROM_DATABASE=Dymo-CoStar Corp. usb:v0922p0007* ID_MODEL_FROM_DATABASE=LabelWriter 330 usb:v0922p0009* ID_MODEL_FROM_DATABASE=LabelWriter 310 usb:v0922p0019* ID_MODEL_FROM_DATABASE=LabelWriter 400 usb:v0922p001A* ID_MODEL_FROM_DATABASE=LabelWriter 400 Turbo usb:v0922p0020* ID_MODEL_FROM_DATABASE=LabelWriter 450 usb:v0922p1001* ID_MODEL_FROM_DATABASE=LabelManager PnP usb:v0922p8004* ID_MODEL_FROM_DATABASE=M25 Digital Postal Scale usb:v0923* ID_VENDOR_FROM_DATABASE=IC Media Corp. usb:v0923p010F* ID_MODEL_FROM_DATABASE=SIIG MobileCam usb:v0924* ID_VENDOR_FROM_DATABASE=Xerox usb:v0924p23DD* ID_MODEL_FROM_DATABASE=DocuPrint M760 (X760_USB) usb:v0924p3CE8* ID_MODEL_FROM_DATABASE=Phaser 3428 Printer usb:v0924p3D5B* ID_MODEL_FROM_DATABASE=Phaser 6115MFP TWAIN Scanner usb:v0924p3D6D* ID_MODEL_FROM_DATABASE=WorkCentre 6015N/NI usb:v0924p420F* ID_MODEL_FROM_DATABASE=WorkCentre PE220 Series usb:v0924p421F* ID_MODEL_FROM_DATABASE=M20 Scanner usb:v0924p423B* ID_MODEL_FROM_DATABASE=Printing Support usb:v0924p4274* ID_MODEL_FROM_DATABASE=Xerox Phaser 3635MFPX usb:v0924pFFEF* ID_MODEL_FROM_DATABASE=WorkCenter M15 usb:v0924pFFFB* ID_MODEL_FROM_DATABASE=DocuPrint M750 (X750_USB) usb:v0925* ID_VENDOR_FROM_DATABASE=Lakeview Research usb:v0925p0005* ID_MODEL_FROM_DATABASE=Gamtec.,Ltd SmartJoy PLUS Adapter usb:v0925p03E8* ID_MODEL_FROM_DATABASE=Wii Classic Controller Adapter usb:v0925p3881* ID_MODEL_FROM_DATABASE=Saleae Logic usb:v0925p8101* ID_MODEL_FROM_DATABASE=Phidgets, Inc., 1-Motor PhidgetServo v2.0 usb:v0925p8104* ID_MODEL_FROM_DATABASE=Phidgets, Inc., 4-Motor PhidgetServo v2.0 usb:v0925p8800* ID_MODEL_FROM_DATABASE=WiseGroup Ltd, MP-8800 Quad Joypad usb:v0925p8866* ID_MODEL_FROM_DATABASE=WiseGroup Ltd, MP-8866 Dual Joypad usb:v0927* ID_VENDOR_FROM_DATABASE=Summus, Ltd usb:v0928* ID_VENDOR_FROM_DATABASE=PLX Technology, Inc. (formerly Oxford Semiconductor, Ltd) usb:v0928p8000* ID_MODEL_FROM_DATABASE=Firmware uploader usb:v0928pFFFF* ID_MODEL_FROM_DATABASE=Blank Oxford Device usb:v0929* ID_VENDOR_FROM_DATABASE=American Biometric Co. usb:v092A* ID_VENDOR_FROM_DATABASE=Toshiba Information & Industrial Sys. And Services usb:v092B* ID_VENDOR_FROM_DATABASE=Sena Technologies, Inc. usb:v092F* ID_VENDOR_FROM_DATABASE=Northern Embedded Science/CAVNEX usb:v092Fp0004* ID_MODEL_FROM_DATABASE=JTAG-4 usb:v092Fp0005* ID_MODEL_FROM_DATABASE=JTAG-5 usb:v0930* ID_VENDOR_FROM_DATABASE=Toshiba Corp. usb:v0930p0009* ID_MODEL_FROM_DATABASE=Gigabeat F/X (HDD audio player) usb:v0930p000C* ID_MODEL_FROM_DATABASE=Gigabeat F (mtp) usb:v0930p0010* ID_MODEL_FROM_DATABASE=Gigabeat S (mtp) usb:v0930p0200* ID_MODEL_FROM_DATABASE=Integrated Bluetooth (Taiyo Yuden) usb:v0930p021C* ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth usb:v0930p0301* ID_MODEL_FROM_DATABASE=PCX1100U Cable Modem (WDM) usb:v0930p0302* ID_MODEL_FROM_DATABASE=PCX2000 Cable Modem (WDM) usb:v0930p0305* ID_MODEL_FROM_DATABASE=Cable Modem PCX3000 usb:v0930p0307* ID_MODEL_FROM_DATABASE=Cable Modem PCX2500 usb:v0930p0308* ID_MODEL_FROM_DATABASE=PCX2200 Cable Modem (WDM) usb:v0930p0309* ID_MODEL_FROM_DATABASE=PCX5000 Cable Modem (WDM) usb:v0930p030B* ID_MODEL_FROM_DATABASE=Cable Modem PCX2600 usb:v0930p0501* ID_MODEL_FROM_DATABASE=Bluetooth Controller usb:v0930p0502* ID_MODEL_FROM_DATABASE=Integrated Bluetooth usb:v0930p0503* ID_MODEL_FROM_DATABASE=Bluetooth Controller usb:v0930p0505* ID_MODEL_FROM_DATABASE=Integrated Bluetooth usb:v0930p0506* ID_MODEL_FROM_DATABASE=Integrated Bluetooth usb:v0930p0507* ID_MODEL_FROM_DATABASE=Bluetooth Adapter usb:v0930p0508* ID_MODEL_FROM_DATABASE=Integrated Bluetooth HCI usb:v0930p0509* ID_MODEL_FROM_DATABASE=BT EDR Dongle usb:v0930p0706* ID_MODEL_FROM_DATABASE=PocketPC e740 usb:v0930p0707* ID_MODEL_FROM_DATABASE=Pocket PC e330 Series usb:v0930p0708* ID_MODEL_FROM_DATABASE=Pocket PC e350 Series usb:v0930p0709* ID_MODEL_FROM_DATABASE=Pocket PC e750 Series usb:v0930p070A* ID_MODEL_FROM_DATABASE=Pocket PC e400 Series usb:v0930p070B* ID_MODEL_FROM_DATABASE=Pocket PC e800 Series usb:v0930p0A07* ID_MODEL_FROM_DATABASE=WLM-10U1 802.11abgn Wireless Adapter [Ralink RT3572] usb:v0930p0A13* ID_MODEL_FROM_DATABASE=AX88179 Gigabit Ethernet [Toshiba] usb:v0930p0B05* ID_MODEL_FROM_DATABASE=PX1220E-1G25 External hard drive usb:v0930p0B09* ID_MODEL_FROM_DATABASE=PX1396E-3T01 External hard drive usb:v0930p0B1A* ID_MODEL_FROM_DATABASE=STOR.E ALU 2S usb:v0930p1300* ID_MODEL_FROM_DATABASE=Wireless Broadband (CDMA EV-DO) SM-Bus Minicard Status Port usb:v0930p1301* ID_MODEL_FROM_DATABASE=Wireless Broadband (CDMA EV-DO) Minicard Status Port usb:v0930p1302* ID_MODEL_FROM_DATABASE=Wireless Broadband (3G HSDPA) SM-Bus Minicard Status Port usb:v0930p1303* ID_MODEL_FROM_DATABASE=Wireless Broadband (3G HSDPA) Minicard Status Port usb:v0930p1308* ID_MODEL_FROM_DATABASE=Broadband (3G HSDPA) SM-Bus Minicard Diagnostics Port usb:v0930p130B* ID_MODEL_FROM_DATABASE=F3507g Mobile Broadband Module usb:v0930p130C* ID_MODEL_FROM_DATABASE=F3607gw Mobile Broadband Module usb:v0930p1311* ID_MODEL_FROM_DATABASE=F3607gw v2 Mobile Broadband Module usb:v0930p1400* ID_MODEL_FROM_DATABASE=Memory Stick 2GB usb:v0930p642F* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p6506* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p6507* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p6508* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p6509* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p6510* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p6517* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p6518* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p6519* ID_MODEL_FROM_DATABASE=Kingston DataTraveler 2.0 USB Stick usb:v0930p651A* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p651B* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p651C* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p651D* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p651E* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p651F* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p6520* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p6521* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p6522* ID_MODEL_FROM_DATABASE=TravelDrive 2C usb:v0930p6523* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p6524* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p6525* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p6526* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p6527* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p6528* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p6529* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p652A* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p652B* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p652C* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p652D* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p652F* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p6530* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p6531* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p6532* ID_MODEL_FROM_DATABASE=256M Stick usb:v0930p6533* ID_MODEL_FROM_DATABASE=512M Stick usb:v0930p6534* ID_MODEL_FROM_DATABASE=TravelDrive usb:v0930p653C* ID_MODEL_FROM_DATABASE=Kingston DataTraveler 2.0 Stick (512M) usb:v0930p653D* ID_MODEL_FROM_DATABASE=Kingston DataTraveler 2.0 Stick (1GB) usb:v0930p653E* ID_MODEL_FROM_DATABASE=Flash Memory usb:v0930p6540* ID_MODEL_FROM_DATABASE=TransMemory Flash Memory usb:v0930p6544* ID_MODEL_FROM_DATABASE=TransMemory-Mini / Kingston DataTraveler 2.0 Stick (2GB) usb:v0930p6545* ID_MODEL_FROM_DATABASE=Kingston DataTraveler 102/2.0 / HEMA Flash Drive 2 GB / PNY Attache 4GB Stick usb:v0931* ID_VENDOR_FROM_DATABASE=Harmonic Data Systems, Ltd usb:v0932* ID_VENDOR_FROM_DATABASE=Crescentec Corp. usb:v0932p0300* ID_MODEL_FROM_DATABASE=VideoAdvantage usb:v0932p0302* ID_MODEL_FROM_DATABASE=Syntek DC-112X usb:v0932p0320* ID_MODEL_FROM_DATABASE=VideoAdvantage usb:v0932p0482* ID_MODEL_FROM_DATABASE=USB2.0 TVBOX usb:v0932p1100* ID_MODEL_FROM_DATABASE=DC-1100 Video Enhamcement Device usb:v0932p1112* ID_MODEL_FROM_DATABASE=Veo Web Camera usb:v0932pA311* ID_MODEL_FROM_DATABASE=Video Enhancement Device usb:v0933* ID_VENDOR_FROM_DATABASE=Quantum Corp. usb:v0934* ID_VENDOR_FROM_DATABASE=Spirent Communications usb:v0936* ID_VENDOR_FROM_DATABASE=NuTesla usb:v0936p000C* ID_MODEL_FROM_DATABASE=Rhythmedics 6 BioData Integrator usb:v0936p0030* ID_MODEL_FROM_DATABASE=Composite Device, Mass Storage Device (Flash Drive) amd HID usb:v0936p003C* ID_MODEL_FROM_DATABASE=Rhythmedics HID Bootloader usb:v0939* ID_VENDOR_FROM_DATABASE=Lumberg, Inc. usb:v0939p0B15* ID_MODEL_FROM_DATABASE=Toshiba Stor.E Alu 2 usb:v093A* ID_VENDOR_FROM_DATABASE=Pixart Imaging, Inc. usb:v093Ap0007* ID_MODEL_FROM_DATABASE=CMOS 100K-R Rev. 1.90 usb:v093Ap010E* ID_MODEL_FROM_DATABASE=Digital camera, CD302N/Elta Medi@ digi-cam/HE-501A usb:v093Ap010F* ID_MODEL_FROM_DATABASE=Argus DC-1610/DC-1620/Emprex PCD3600/Philips P44417B keychain camera/Precision Mini,Model HA513A/Vivitar Vivicam 55 usb:v093Ap020F* ID_MODEL_FROM_DATABASE=Bullet Line Photo Viewer usb:v093Ap050F* ID_MODEL_FROM_DATABASE=Mars-Semi Pc-Camera usb:v093Ap2460* ID_MODEL_FROM_DATABASE=Q-TEC WEBCAM 100 usb:v093Ap2468* ID_MODEL_FROM_DATABASE=SoC PC-Camera usb:v093Ap2470* ID_MODEL_FROM_DATABASE=SoC PC-Camera usb:v093Ap2471* ID_MODEL_FROM_DATABASE=SoC PC-Camera usb:v093Ap2500* ID_MODEL_FROM_DATABASE=USB Optical Mouse usb:v093Ap2510* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v093Ap2521* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v093Ap2600* ID_MODEL_FROM_DATABASE=Typhoon Easycam USB 330K (newer)/Typhoon Easycam USB 2.0 VGA 1.3M/Sansun SN-508 usb:v093Ap2601* ID_MODEL_FROM_DATABASE=SPC 610NC Laptop Camera usb:v093Ap2603* ID_MODEL_FROM_DATABASE=PAC7312 Camera usb:v093Ap2608* ID_MODEL_FROM_DATABASE=PAC7311 Trust WB-3300p usb:v093Ap260E* ID_MODEL_FROM_DATABASE=PAC7311 Gigaware VGA PC Camera:Trust WB-3350p:SIGMA cam 2350 usb:v093Ap260F* ID_MODEL_FROM_DATABASE=PAC7311 SnakeCam usb:v093Ap2621* ID_MODEL_FROM_DATABASE=PAC731x Trust Webcam usb:v093Ap2622* ID_MODEL_FROM_DATABASE=Webcam Genius usb:v093Ap2624* ID_MODEL_FROM_DATABASE=Webcam usb:v093B* ID_VENDOR_FROM_DATABASE=Plextor Corp. usb:v093Bp0010* ID_MODEL_FROM_DATABASE=Storage Adapter usb:v093Bp0011* ID_MODEL_FROM_DATABASE=PlexWriter 40/12/40U usb:v093Bp0041* ID_MODEL_FROM_DATABASE=PX-708A DVD RW usb:v093Bp0042* ID_MODEL_FROM_DATABASE=PX-712UF DVD RW usb:v093BpA002* ID_MODEL_FROM_DATABASE=ConvertX M402U XLOADER usb:v093BpA003* ID_MODEL_FROM_DATABASE=ConvertX AV100U A/V Capture Audio usb:v093BpA004* ID_MODEL_FROM_DATABASE=ConvertX TV402U XLOADER usb:v093BpA005* ID_MODEL_FROM_DATABASE=ConvertX TV100U A/V Capture usb:v093BpA102* ID_MODEL_FROM_DATABASE=ConvertX M402U A/V Capture usb:v093BpA104* ID_MODEL_FROM_DATABASE=ConvertX PX-TV402U/NA usb:v093C* ID_VENDOR_FROM_DATABASE=Intrepid Control Systems, Inc. usb:v093Cp0601* ID_MODEL_FROM_DATABASE=ValueCAN usb:v093Cp0701* ID_MODEL_FROM_DATABASE=NeoVI Blue vehicle bus interface usb:v093D* ID_VENDOR_FROM_DATABASE=InnoSync, Inc. usb:v093E* ID_VENDOR_FROM_DATABASE=J.S.T. Mfg. Co., Ltd usb:v093F* ID_VENDOR_FROM_DATABASE=Olympia Telecom Vertriebs GmbH usb:v0940* ID_VENDOR_FROM_DATABASE=Japan Storage Battery Co., Ltd usb:v0941* ID_VENDOR_FROM_DATABASE=Photobit Corp. usb:v0942* ID_VENDOR_FROM_DATABASE=i2Go.com, LLC usb:v0943* ID_VENDOR_FROM_DATABASE=HCL Technologies India Private, Ltd usb:v0944* ID_VENDOR_FROM_DATABASE=KORG, Inc. usb:v0944p0001* ID_MODEL_FROM_DATABASE=PXR4 4-Track Digital Recorder usb:v0944p0020* ID_MODEL_FROM_DATABASE=KAOSS Pad KP3 Dynamic Effect/Sampler usb:v0944p0023* ID_MODEL_FROM_DATABASE=KAOSSILATOR PRO Dynamic Phrase Synthesizer usb:v0944p010D* ID_MODEL_FROM_DATABASE=nanoKEY MIDI keyboard usb:v0944p010E* ID_MODEL_FROM_DATABASE=nanoPAD pad controller usb:v0944p010F* ID_MODEL_FROM_DATABASE=nanoKONTROL studio controller usb:v0944p0117* ID_MODEL_FROM_DATABASE=nanoKONTROL2 MIDI Controller usb:v0944p0F03* ID_MODEL_FROM_DATABASE=K-Series K61P MIDI studio controller usb:v0945* ID_VENDOR_FROM_DATABASE=Pasco Scientific usb:v0948* ID_VENDOR_FROM_DATABASE=Kronauer music in digital usb:v0948p0301* ID_MODEL_FROM_DATABASE=USB Pro (24/48) usb:v0948p0302* ID_MODEL_FROM_DATABASE=USB Pro (24/96 playback) usb:v0948p0303* ID_MODEL_FROM_DATABASE=USB Pro (24/96 record) usb:v0948p0304* ID_MODEL_FROM_DATABASE=USB Pro (16/48) usb:v0948p1105* ID_MODEL_FROM_DATABASE=USB One usb:v094B* ID_VENDOR_FROM_DATABASE=Linkup Systems Corp. usb:v094Bp0001* ID_MODEL_FROM_DATABASE=neonode N2 usb:v094D* ID_VENDOR_FROM_DATABASE=Cable Television Laboratories usb:v094F* ID_VENDOR_FROM_DATABASE=Yano usb:v094Fp0101* ID_MODEL_FROM_DATABASE=U640MO-03 usb:v094Fp05FC* ID_MODEL_FROM_DATABASE=METALWEAR-HDD usb:v0951* ID_VENDOR_FROM_DATABASE=Kingston Technology usb:v0951p0008* ID_MODEL_FROM_DATABASE=Ethernet usb:v0951p000A* ID_MODEL_FROM_DATABASE=KNU101TX 100baseTX Ethernet usb:v0951p1600* ID_MODEL_FROM_DATABASE=DataTraveler II Pen Drive usb:v0951p1601* ID_MODEL_FROM_DATABASE=DataTraveler II+ Pen Drive usb:v0951p1602* ID_MODEL_FROM_DATABASE=DataTraveler Mini usb:v0951p1603* ID_MODEL_FROM_DATABASE=DataTraveler 1GB/2GB Pen Drive usb:v0951p1606* ID_MODEL_FROM_DATABASE=Eee PC 701 SD Card Reader [ENE UB6225] usb:v0951p1607* ID_MODEL_FROM_DATABASE=DataTraveler 100 usb:v0951p160D* ID_MODEL_FROM_DATABASE=DataTraveler Vault Privacy usb:v0951p160E* ID_MODEL_FROM_DATABASE=DT110P/1GB Capless usb:v0951p1613* ID_MODEL_FROM_DATABASE=DataTraveler DT101C Flash Drive usb:v0951p1616* ID_MODEL_FROM_DATABASE=DataTraveler Locker 4GB usb:v0951p161A* ID_MODEL_FROM_DATABASE=Dell HyperVisor internal flash drive usb:v0951p1621* ID_MODEL_FROM_DATABASE=DataTraveler 150 (32GB) usb:v0951p1624* ID_MODEL_FROM_DATABASE=DataTraveler G2 usb:v0951p1625* ID_MODEL_FROM_DATABASE=DataTraveler 101 II usb:v0951p162A* ID_MODEL_FROM_DATABASE=DataTraveler 112 4GB Pen Drive usb:v0951p162D* ID_MODEL_FROM_DATABASE=DataTraveler 102 usb:v0951p1630* ID_MODEL_FROM_DATABASE=DataTraveler 200 (32GB) usb:v0951p1642* ID_MODEL_FROM_DATABASE=DT101 G2 usb:v0951p1643* ID_MODEL_FROM_DATABASE=DataTraveler G3 usb:v0951p1653* ID_MODEL_FROM_DATABASE=Data Traveler 100 G2 8 GiB usb:v0951p1656* ID_MODEL_FROM_DATABASE=DataTraveler Ultimate G2 usb:v0951p1665* ID_MODEL_FROM_DATABASE=Digital DataTraveler SE9 64GB usb:v0951p1666* ID_MODEL_FROM_DATABASE=DataTraveler G4 usb:v0951p1689* ID_MODEL_FROM_DATABASE=DataTraveler SE9 usb:v0951p168A* ID_MODEL_FROM_DATABASE=DataTraveler Micro usb:v0951p168C* ID_MODEL_FROM_DATABASE=DT Elite 3.0 usb:v0954* ID_VENDOR_FROM_DATABASE=RPM Systems Corp. usb:v0955* ID_VENDOR_FROM_DATABASE=NVidia Corp. usb:v0955p7030* ID_MODEL_FROM_DATABASE=Tegra 3 (recovery mode) usb:v0955p7100* ID_MODEL_FROM_DATABASE=Tegra Device usb:v0955p7820* ID_MODEL_FROM_DATABASE=Tegra 2 AC100 developer mode usb:v0955pB400* ID_MODEL_FROM_DATABASE=SHIELD (debug) usb:v0955pB401* ID_MODEL_FROM_DATABASE=SHIELD usb:v0955pCF05* ID_MODEL_FROM_DATABASE=SHIELD Tablet (debug) usb:v0955pCF06* ID_MODEL_FROM_DATABASE=SHIELD Tablet usb:v0955pCF07* ID_MODEL_FROM_DATABASE=SHIELD Tablet usb:v0955pCF08* ID_MODEL_FROM_DATABASE=SHIELD Tablet usb:v0955pCF09* ID_MODEL_FROM_DATABASE=SHIELD Tablet usb:v0956* ID_VENDOR_FROM_DATABASE=BSquare Corp. usb:v0957* ID_VENDOR_FROM_DATABASE=Agilent Technologies, Inc. usb:v0957p0200* ID_MODEL_FROM_DATABASE=E-Video DC-350 Camera usb:v0957p0202* ID_MODEL_FROM_DATABASE=E-Video DC-350 Camera usb:v0957p0407* ID_MODEL_FROM_DATABASE=33220A Waveform Generator usb:v0957p0518* ID_MODEL_FROM_DATABASE=82357B GPIB Interface usb:v0957p0A07* ID_MODEL_FROM_DATABASE=34411A Multimeter usb:v0957p1507* ID_MODEL_FROM_DATABASE=33210A Waveform Generator usb:v0957p1745* ID_MODEL_FROM_DATABASE=Test and Measurement Device (IVI) usb:v0957p2918* ID_MODEL_FROM_DATABASE=U2702A oscilloscope usb:v0957pFB18* ID_MODEL_FROM_DATABASE=LC Device usb:v0958* ID_VENDOR_FROM_DATABASE=CompuLink Research, Inc. usb:v0959* ID_VENDOR_FROM_DATABASE=Cologne Chip AG usb:v0959p2BD0* ID_MODEL_FROM_DATABASE=Intelligent ISDN (Ver. 3.60.04) [HFC-S] usb:v095A* ID_VENDOR_FROM_DATABASE=Portsmith usb:v095Ap3003* ID_MODEL_FROM_DATABASE=Express Ethernet usb:v095B* ID_VENDOR_FROM_DATABASE=Medialogic Corp. usb:v095C* ID_VENDOR_FROM_DATABASE=K-Tec Electronics usb:v095D* ID_VENDOR_FROM_DATABASE=Polycom, Inc. usb:v095Dp0001* ID_MODEL_FROM_DATABASE=Polycom ViaVideo usb:v0967* ID_VENDOR_FROM_DATABASE=Acer NeWeb Corp. usb:v0967p0204* ID_MODEL_FROM_DATABASE=WarpLink 802.11b Adapter usb:v0968* ID_VENDOR_FROM_DATABASE=Catalyst Enterprises, Inc. usb:v096E* ID_VENDOR_FROM_DATABASE=Feitian Technologies, Inc. usb:v096Ep0120* ID_MODEL_FROM_DATABASE=Microcosm Ltd Dinkey usb:v096Ep0802* ID_MODEL_FROM_DATABASE=ePass2000 (G&D STARCOS SPK 2.4) usb:v096Ep0807* ID_MODEL_FROM_DATABASE=ePass2003 usb:v0971* ID_VENDOR_FROM_DATABASE=Gretag-Macbeth AG usb:v0971p2000* ID_MODEL_FROM_DATABASE=i1 Pro usb:v0971p2001* ID_MODEL_FROM_DATABASE=i1 Monitor usb:v0971p2003* ID_MODEL_FROM_DATABASE=Eye-One display usb:v0971p2005* ID_MODEL_FROM_DATABASE=Huey usb:v0971p2007* ID_MODEL_FROM_DATABASE=ColorMunki Photo usb:v0973* ID_VENDOR_FROM_DATABASE=Schlumberger usb:v0973p0001* ID_MODEL_FROM_DATABASE=e-gate Smart Card usb:v0974* ID_VENDOR_FROM_DATABASE=Datagraphix, a business unit of Anacomp usb:v0975* ID_VENDOR_FROM_DATABASE=OL'E Communications, Inc. usb:v0976* ID_VENDOR_FROM_DATABASE=Adirondack Wire & Cable usb:v0977* ID_VENDOR_FROM_DATABASE=Lightsurf Technologies usb:v0978* ID_VENDOR_FROM_DATABASE=Beckhoff GmbH usb:v0979* ID_VENDOR_FROM_DATABASE=Jeilin Technology Corp., Ltd usb:v0979p0222* ID_MODEL_FROM_DATABASE=Keychain Display usb:v0979p0224* ID_MODEL_FROM_DATABASE=JL2005A Toy Camera usb:v0979p0226* ID_MODEL_FROM_DATABASE=JL2005A Toy Camera usb:v0979p0227* ID_MODEL_FROM_DATABASE=JL2005B/C/D Toy Camera usb:v097A* ID_VENDOR_FROM_DATABASE=Minds At Work LLC usb:v097Ap0001* ID_MODEL_FROM_DATABASE=Digital Wallet usb:v097B* ID_VENDOR_FROM_DATABASE=Knudsen Engineering, Ltd usb:v097C* ID_VENDOR_FROM_DATABASE=Marunix Co., Ltd usb:v097D* ID_VENDOR_FROM_DATABASE=Rosun Technologies, Inc. usb:v097E* ID_VENDOR_FROM_DATABASE=Biopac Systems Inc. usb:v097Ep0035* ID_MODEL_FROM_DATABASE=MP35 v1.0 usb:v097F* ID_VENDOR_FROM_DATABASE=Barun Electronics Co., Ltd usb:v0981* ID_VENDOR_FROM_DATABASE=Oak Technology, Ltd usb:v0984* ID_VENDOR_FROM_DATABASE=Apricorn usb:v0984p0040* ID_MODEL_FROM_DATABASE=SATA Wire (2.5") usb:v0984p0200* ID_MODEL_FROM_DATABASE=Hard Drive Storage (TPP) usb:v0985* ID_VENDOR_FROM_DATABASE=cab Produkttechnik GmbH & Co KG usb:v0985p0045* ID_MODEL_FROM_DATABASE=Mach4/200 Label Printer usb:v0985p00A3* ID_MODEL_FROM_DATABASE=A3/200 or A3/300 Label Printer usb:v0986* ID_VENDOR_FROM_DATABASE=Matsushita Electric Works, Ltd. usb:v098C* ID_VENDOR_FROM_DATABASE=Vitana Corp. usb:v098D* ID_VENDOR_FROM_DATABASE=INDesign usb:v098E* ID_VENDOR_FROM_DATABASE=Integrated Intellectual Property, Inc. usb:v098F* ID_VENDOR_FROM_DATABASE=Kenwood TMI Corp. usb:v0993* ID_VENDOR_FROM_DATABASE=Gemstar eBook Group, Ltd usb:v0993p0001* ID_MODEL_FROM_DATABASE=REB1100 eBook Reader usb:v0993p0002* ID_MODEL_FROM_DATABASE=eBook usb:v0996* ID_VENDOR_FROM_DATABASE=Integrated Telecom Express, Inc. usb:v099A* ID_VENDOR_FROM_DATABASE=Zippy Technology Corp. usb:v099Ap0638* ID_MODEL_FROM_DATABASE=Sanwa Supply Inc. Small Keyboard usb:v099Ap610C* ID_MODEL_FROM_DATABASE=EL-610 Super Mini Electron luminescent Keyboard usb:v099Ap713A* ID_MODEL_FROM_DATABASE=WK-713 Multimedia Keyboard usb:v099Ap7160* ID_MODEL_FROM_DATABASE=Hyper Slim Keyboard usb:v09A3* ID_VENDOR_FROM_DATABASE=PairGain Technologies usb:v09A4* ID_VENDOR_FROM_DATABASE=Contech Research, Inc. usb:v09A5* ID_VENDOR_FROM_DATABASE=VCON Telecommunications usb:v09A6* ID_VENDOR_FROM_DATABASE=Poinchips usb:v09A6p8001* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v09A7* ID_VENDOR_FROM_DATABASE=Data Transmission Network Corp. usb:v09A8* ID_VENDOR_FROM_DATABASE=Lin Shiung Enterprise Co., Ltd usb:v09A9* ID_VENDOR_FROM_DATABASE=Smart Card Technologies Co., Ltd usb:v09AA* ID_VENDOR_FROM_DATABASE=Intersil Corp. usb:v09AAp1000* ID_MODEL_FROM_DATABASE=Prism GT 802.11b/g Adapter usb:v09AAp3642* ID_MODEL_FROM_DATABASE=Prism 2.x 802.11b Adapter usb:v09AB* ID_VENDOR_FROM_DATABASE=Japan Cash Machine Co., Ltd. usb:v09AE* ID_VENDOR_FROM_DATABASE=Tripp Lite usb:v09B2* ID_VENDOR_FROM_DATABASE=Franklin Electronic Publishers, Inc. usb:v09B2p0001* ID_MODEL_FROM_DATABASE=eBookman Palm Computer usb:v09B3* ID_VENDOR_FROM_DATABASE=Altius Solutions, Inc. usb:v09B4* ID_VENDOR_FROM_DATABASE=MDS Telephone Systems usb:v09B5* ID_VENDOR_FROM_DATABASE=Celltrix Technology Co., Ltd usb:v09BC* ID_VENDOR_FROM_DATABASE=Grundig usb:v09BCp0002* ID_MODEL_FROM_DATABASE=MPaxx MP150 MP3 Player usb:v09BE* ID_VENDOR_FROM_DATABASE=MySmart.Com usb:v09BEp0001* ID_MODEL_FROM_DATABASE=MySmartPad usb:v09BF* ID_VENDOR_FROM_DATABASE=Auerswald GmbH & Co. KG usb:v09BFp00C0* ID_MODEL_FROM_DATABASE=COMpact 2104 ISDN PBX usb:v09BFp00DB* ID_MODEL_FROM_DATABASE=COMpact 4410/2206 ISDN usb:v09BFp00DC* ID_MODEL_FROM_DATABASE=COMpact 4406 DSL (PBX) usb:v09BFp00DD* ID_MODEL_FROM_DATABASE=COMpact 2204 (PBX) usb:v09BFp00DE* ID_MODEL_FROM_DATABASE=COMpact 2104 (Rev.2 PBX) usb:v09BFp00E0* ID_MODEL_FROM_DATABASE=COMmander Business (PBX) usb:v09BFp00E2* ID_MODEL_FROM_DATABASE=COMmander Basic.2 (PBX) usb:v09BFp00F1* ID_MODEL_FROM_DATABASE=COMfort 2000 (System telephone) usb:v09BFp00F2* ID_MODEL_FROM_DATABASE=COMfort 1200 (System telephone) usb:v09BFp00F5* ID_MODEL_FROM_DATABASE=COMfortel 2500 (System telephone) usb:v09BFp8000* ID_MODEL_FROM_DATABASE=COMpact 2104 DSL (DSL modem) usb:v09BFp8001* ID_MODEL_FROM_DATABASE=COMpact 4406 DSL (DSL modem) usb:v09BFp8002* ID_MODEL_FROM_DATABASE=Analog/ISDN Converter (Line converter) usb:v09BFp8005* ID_MODEL_FROM_DATABASE=WG-640 (Automatic event dialer) usb:v09C0* ID_VENDOR_FROM_DATABASE=Genpix Electronics, LLC usb:v09C0p0136* ID_MODEL_FROM_DATABASE=Axon CNS, MultiClamp 700B usb:v09C0p0202* ID_MODEL_FROM_DATABASE=8PSK DVB-S tuner usb:v09C0p0203* ID_MODEL_FROM_DATABASE=Skywalker-1 DVB-S tuner usb:v09C0p0204* ID_MODEL_FROM_DATABASE=Skywalker-CW3K DVB-S tuner usb:v09C0p0205* ID_MODEL_FROM_DATABASE=Skywalker-CW3K DVB-S tuner usb:v09C0p0206* ID_MODEL_FROM_DATABASE=Skywalker-2 DVB-S tuner usb:v09C1* ID_VENDOR_FROM_DATABASE=Arris Interactive LLC usb:v09C1p1337* ID_MODEL_FROM_DATABASE=TOUCHSTONE DEVICE usb:v09C2* ID_VENDOR_FROM_DATABASE=Nisca Corp. usb:v09C3* ID_VENDOR_FROM_DATABASE=ActivCard, Inc. usb:v09C3p0007* ID_MODEL_FROM_DATABASE=Reader V2 usb:v09C3p0008* ID_MODEL_FROM_DATABASE=ZFG-9800-AC SmartCard Reader usb:v09C3p0014* ID_MODEL_FROM_DATABASE=ActivIdentity ActivKey SIM USB Token usb:v09C4* ID_VENDOR_FROM_DATABASE=ACTiSYS Corp. usb:v09C4p0011* ID_MODEL_FROM_DATABASE=ACT-IR2000U IrDA Dongle usb:v09C5* ID_VENDOR_FROM_DATABASE=Memory Corp. usb:v09CA* ID_VENDOR_FROM_DATABASE=BMC Messsysteme GmbH usb:v09CAp5544* ID_MODEL_FROM_DATABASE=PIO usb:v09CC* ID_VENDOR_FROM_DATABASE=Workbit Corp. usb:v09CCp0404* ID_MODEL_FROM_DATABASE=BAFO USB-ATA/ATAPI Bridge Controller usb:v09CD* ID_VENDOR_FROM_DATABASE=Psion Dacom Home Networks, Ltd usb:v09CDp2001* ID_MODEL_FROM_DATABASE=Psion WaveFinder DAB radio receiver usb:v09CE* ID_VENDOR_FROM_DATABASE=City Electronics, Ltd usb:v09CF* ID_VENDOR_FROM_DATABASE=Electronics Testing Center, Taiwan usb:v09D1* ID_VENDOR_FROM_DATABASE=NeoMagic, Inc. usb:v09D2* ID_VENDOR_FROM_DATABASE=Vreelin Engineering, Inc. usb:v09D3* ID_VENDOR_FROM_DATABASE=Com One usb:v09D3p0001* ID_MODEL_FROM_DATABASE=ISDN TA / Light Rider 128K usb:v09D3p000B* ID_MODEL_FROM_DATABASE=Bluetooth Adapter class 1 [BlueLight] usb:v09D7* ID_VENDOR_FROM_DATABASE=Novatel Wireless usb:v09D7p0100* ID_MODEL_FROM_DATABASE=NovAtel FlexPack GPS receiver usb:v09D9* ID_VENDOR_FROM_DATABASE=KRF Tech, Ltd usb:v09DA* ID_VENDOR_FROM_DATABASE=A4Tech Co., Ltd. usb:v09DAp0006* ID_MODEL_FROM_DATABASE=Optical Mouse WOP-35 / Trust 450L Optical Mouse usb:v09DAp000A* ID_MODEL_FROM_DATABASE=Optical Mouse Opto 510D / OP-620D usb:v09DAp000E* ID_MODEL_FROM_DATABASE=X-F710F Optical Mouse 3xFire Gaming Mouse usb:v09DAp0018* ID_MODEL_FROM_DATABASE=Trust Human Interface Device usb:v09DAp001A* ID_MODEL_FROM_DATABASE=Wireless Mouse & RXM-15 Receiver usb:v09DAp002A* ID_MODEL_FROM_DATABASE=Wireless Optical Mouse NB-30 usb:v09DAp022B* ID_MODEL_FROM_DATABASE=Wireless Mouse (Battery Free) usb:v09DAp024F* ID_MODEL_FROM_DATABASE=RF Receiver and G6-20D Wireless Optical Mouse usb:v09DAp0260* ID_MODEL_FROM_DATABASE=KV-300H Isolation Keyboard usb:v09DAp032B* ID_MODEL_FROM_DATABASE=Wireless Mouse (Battery Free) usb:v09DAp8090* ID_MODEL_FROM_DATABASE=X-718BK Oscar Optical Gaming Mouse usb:v09DAp9033* ID_MODEL_FROM_DATABASE=X-718BK Optical Mouse usb:v09DAp9066* ID_MODEL_FROM_DATABASE=F3 V-Track Gaming Mouse usb:v09DAp9090* ID_MODEL_FROM_DATABASE=XL-730K / XL-750BK / XL-755BK Mice usb:v09DB* ID_VENDOR_FROM_DATABASE=Measurement Computing Corp. usb:v09DBp0075* ID_MODEL_FROM_DATABASE=MiniLab 1008 usb:v09DBp0076* ID_MODEL_FROM_DATABASE=PMD-1024 usb:v09DBp007A* ID_MODEL_FROM_DATABASE=PMD-1208LS usb:v09DBp0081* ID_MODEL_FROM_DATABASE=USB-1616FS usb:v09DBp0082* ID_MODEL_FROM_DATABASE=USB-1208FS usb:v09DBp0088* ID_MODEL_FROM_DATABASE=USB-1616FS internal hub usb:v09DC* ID_VENDOR_FROM_DATABASE=Aimex Corp. usb:v09DD* ID_VENDOR_FROM_DATABASE=Fellowes, Inc. usb:v09DF* ID_VENDOR_FROM_DATABASE=Addonics Technologies Corp. usb:v09E1* ID_VENDOR_FROM_DATABASE=Intellon Corp. usb:v09E1p5121* ID_MODEL_FROM_DATABASE=MicroLink dLAN usb:v09E5* ID_VENDOR_FROM_DATABASE=Jo-Dan International, Inc. usb:v09E6* ID_VENDOR_FROM_DATABASE=Silutia, Inc. usb:v09E7* ID_VENDOR_FROM_DATABASE=Real 3D, Inc. usb:v09E8* ID_VENDOR_FROM_DATABASE=AKAI Professional M.I. Corp. usb:v09E8p0062* ID_MODEL_FROM_DATABASE=MPD16 MIDI Pad Controller Unit usb:v09E8p006D* ID_MODEL_FROM_DATABASE=EWI electronic wind instrument usb:v09E8p0071* ID_MODEL_FROM_DATABASE=MPK25 MIDI Keyboard usb:v09E8p0076* ID_MODEL_FROM_DATABASE=LPK25 MIDI Keyboard usb:v09E9* ID_VENDOR_FROM_DATABASE=Chen-Source, Inc. usb:v09EB* ID_VENDOR_FROM_DATABASE=IM Networks, Inc. usb:v09EBp4331* ID_MODEL_FROM_DATABASE=iRhythm Tuner Remote usb:v09EF* ID_VENDOR_FROM_DATABASE=Xitel usb:v09EFp0101* ID_MODEL_FROM_DATABASE=MD-Port DG2 MiniDisc Interface usb:v09F3* ID_VENDOR_FROM_DATABASE=GoFlight, Inc. usb:v09F3p0018* ID_MODEL_FROM_DATABASE=GF-46 Multi-Mode Display Module usb:v09F3p0028* ID_MODEL_FROM_DATABASE=RP-48 Combination Pushbutton-Rotary Module usb:v09F3p0048* ID_MODEL_FROM_DATABASE=LGTII - Landing Gear and Trim Control Module usb:v09F3p0064* ID_MODEL_FROM_DATABASE=MCPPro - Airliner Mode Control Panel (Autopilot) usb:v09F3p0300* ID_MODEL_FROM_DATABASE=EFIS - Electronic Flight Information System usb:v09F5* ID_VENDOR_FROM_DATABASE=AresCom usb:v09F5p0168* ID_MODEL_FROM_DATABASE=Network Adapter usb:v09F5p0188* ID_MODEL_FROM_DATABASE=LAN Adapter usb:v09F5p0850* ID_MODEL_FROM_DATABASE=Adapter usb:v09F6* ID_VENDOR_FROM_DATABASE=RocketChips, Inc. usb:v09F7* ID_VENDOR_FROM_DATABASE=Edu-Science (H.K.), Ltd usb:v09F8* ID_VENDOR_FROM_DATABASE=SoftConnex Technologies, Inc. usb:v09F9* ID_VENDOR_FROM_DATABASE=Bay Associates usb:v09FA* ID_VENDOR_FROM_DATABASE=Mtek Vision usb:v09FB* ID_VENDOR_FROM_DATABASE=Altera usb:v09FBp6001* ID_MODEL_FROM_DATABASE=Blaster usb:v09FF* ID_VENDOR_FROM_DATABASE=Gain Technology Corp. usb:v0A00* ID_VENDOR_FROM_DATABASE=Liquid Audio usb:v0A01* ID_VENDOR_FROM_DATABASE=ViA, Inc. usb:v0A05* ID_VENDOR_FROM_DATABASE=Unknown Manufacturer usb:v0A05p0001* ID_MODEL_FROM_DATABASE=Hub usb:v0A05p7211* ID_MODEL_FROM_DATABASE=hub usb:v0A07* ID_VENDOR_FROM_DATABASE=Ontrak Control Systems Inc. usb:v0A07p0064* ID_MODEL_FROM_DATABASE=ADU100 Data Acquisition Interface usb:v0A07p0078* ID_MODEL_FROM_DATABASE=ADU120 Data Acquisition Interface usb:v0A07p0082* ID_MODEL_FROM_DATABASE=ADU130 Data Acquisition Interface usb:v0A07p00C8* ID_MODEL_FROM_DATABASE=ADU200 Relay I/O Interface usb:v0A07p00D0* ID_MODEL_FROM_DATABASE=ADU208 Relay I/O Interface usb:v0A07p00DA* ID_MODEL_FROM_DATABASE=ADU218 Solid-State Relay I/O Interface usb:v0A0B* ID_VENDOR_FROM_DATABASE=Cybex Computer Products Co. usb:v0A0D* ID_VENDOR_FROM_DATABASE=Servergy, Inc usb:v0A0Dp2514* ID_MODEL_FROM_DATABASE=CTS-1000 Internal Hub usb:v0A11* ID_VENDOR_FROM_DATABASE=Xentec, Inc. usb:v0A12* ID_VENDOR_FROM_DATABASE=Cambridge Silicon Radio, Ltd usb:v0A12p0001* ID_MODEL_FROM_DATABASE=Bluetooth Dongle (HCI mode) usb:v0A12p0002* ID_MODEL_FROM_DATABASE=Frontline Test Equipment Bluetooth Device usb:v0A12p0003* ID_MODEL_FROM_DATABASE=Nanosira usb:v0A12p0004* ID_MODEL_FROM_DATABASE=Nanosira WHQL Reference Radio usb:v0A12p0005* ID_MODEL_FROM_DATABASE=Nanosira-Multimedia usb:v0A12p0006* ID_MODEL_FROM_DATABASE=Nanosira-Multimedia WHQL Reference Radio usb:v0A12p0007* ID_MODEL_FROM_DATABASE=Nanosira3-ROM usb:v0A12p0008* ID_MODEL_FROM_DATABASE=Nanosira3-ROM usb:v0A12p0009* ID_MODEL_FROM_DATABASE=Nanosira4-EDR WHQL Reference Radio usb:v0A12p000A* ID_MODEL_FROM_DATABASE=Nanosira4-EDR-ROM usb:v0A12p000B* ID_MODEL_FROM_DATABASE=Nanosira5-ROM usb:v0A12p0042* ID_MODEL_FROM_DATABASE=SPI Converter usb:v0A12p0043* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0A12p0100* ID_MODEL_FROM_DATABASE=Casira with BlueCore2-External Module usb:v0A12p0101* ID_MODEL_FROM_DATABASE=Casira with BlueCore2-Flash Module usb:v0A12p0102* ID_MODEL_FROM_DATABASE=Casira with BlueCore3-Multimedia Module usb:v0A12p0103* ID_MODEL_FROM_DATABASE=Casira with BlueCore3-Flash Module usb:v0A12p0104* ID_MODEL_FROM_DATABASE=Casira with BlueCore4-External Module usb:v0A12p0105* ID_MODEL_FROM_DATABASE=Casira with BlueCore4-Multimedia Module usb:v0A12p1000* ID_MODEL_FROM_DATABASE=Bluetooth Dongle (HID proxy mode) usb:v0A12p1010* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0A12p1011* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0A12p1012* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0A12pFFFF* ID_MODEL_FROM_DATABASE=USB Bluetooth Device in DFU State usb:v0A13* ID_VENDOR_FROM_DATABASE=Telebyte, Inc. usb:v0A14* ID_VENDOR_FROM_DATABASE=Spacelabs Medical, Inc. usb:v0A15* ID_VENDOR_FROM_DATABASE=Scalar Corp. usb:v0A16* ID_VENDOR_FROM_DATABASE=Trek Technology (S) PTE, Ltd usb:v0A16p1111* ID_MODEL_FROM_DATABASE=ThumbDrive usb:v0A16p8888* ID_MODEL_FROM_DATABASE=IBM USB Memory Key usb:v0A16p9988* ID_MODEL_FROM_DATABASE=Trek2000 TD-G2 usb:v0A17* ID_VENDOR_FROM_DATABASE=Pentax Corp. usb:v0A17p0004* ID_MODEL_FROM_DATABASE=Optio 330 usb:v0A17p0006* ID_MODEL_FROM_DATABASE=Optio S / S4 usb:v0A17p0007* ID_MODEL_FROM_DATABASE=Optio 550 usb:v0A17p0009* ID_MODEL_FROM_DATABASE=Optio 33WR usb:v0A17p000A* ID_MODEL_FROM_DATABASE=Optio 555 usb:v0A17p000C* ID_MODEL_FROM_DATABASE=Optio 43WR (mass storage mode) usb:v0A17p000D* ID_MODEL_FROM_DATABASE=Optio 43WR usb:v0A17p0015* ID_MODEL_FROM_DATABASE=Optio S40/S5i usb:v0A17p003B* ID_MODEL_FROM_DATABASE=Optio 50 (mass storage mode) usb:v0A17p003D* ID_MODEL_FROM_DATABASE=Optio S55 usb:v0A17p0041* ID_MODEL_FROM_DATABASE=Optio S5z usb:v0A17p0043* ID_MODEL_FROM_DATABASE=*ist DL usb:v0A17p0047* ID_MODEL_FROM_DATABASE=Optio S60 usb:v0A17p0052* ID_MODEL_FROM_DATABASE=Optio 60 Digital Camera usb:v0A17p006E* ID_MODEL_FROM_DATABASE=K10D usb:v0A17p0070* ID_MODEL_FROM_DATABASE=K100D usb:v0A17p0093* ID_MODEL_FROM_DATABASE=K200D usb:v0A17p00A7* ID_MODEL_FROM_DATABASE=Optio E50 usb:v0A17p1001* ID_MODEL_FROM_DATABASE=EI2000 Camera powered by Digita! usb:v0A18* ID_VENDOR_FROM_DATABASE=Heidelberger Druckmaschinen AG usb:v0A19* ID_VENDOR_FROM_DATABASE=Hua Geng Technologies, Inc. usb:v0A21* ID_VENDOR_FROM_DATABASE=Medtronic Physio Control Corp. usb:v0A21p8001* ID_MODEL_FROM_DATABASE=MMT-7305WW [Medtronic Minimed CareLink] usb:v0A22* ID_VENDOR_FROM_DATABASE=Century Semiconductor USA, Inc. usb:v0A27* ID_VENDOR_FROM_DATABASE=Datacard Group usb:v0A27p0102* ID_MODEL_FROM_DATABASE=SP35 usb:v0A2C* ID_VENDOR_FROM_DATABASE=AK-Modul-Bus Computer GmbH usb:v0A2Cp0008* ID_MODEL_FROM_DATABASE=GPIO Ports usb:v0A34* ID_VENDOR_FROM_DATABASE=TG3 Electronics, Inc. usb:v0A34p0101* ID_MODEL_FROM_DATABASE=TG82tp usb:v0A34p0110* ID_MODEL_FROM_DATABASE=Deck 82-key backlit keyboard usb:v0A35* ID_VENDOR_FROM_DATABASE=Radikal Technologies usb:v0A35p002A* ID_MODEL_FROM_DATABASE=SAC - Software Assigned Controller usb:v0A35p008A* ID_MODEL_FROM_DATABASE=SAC Hub usb:v0A39* ID_VENDOR_FROM_DATABASE=Gilat Satellite Networks, Ltd usb:v0A3A* ID_VENDOR_FROM_DATABASE=PentaMedia Co., Ltd usb:v0A3Ap0163* ID_MODEL_FROM_DATABASE=KN-W510U 1.0 Wireless LAN Adapter usb:v0A3C* ID_VENDOR_FROM_DATABASE=NTT DoCoMo, Inc. usb:v0A3D* ID_VENDOR_FROM_DATABASE=Varo Vision usb:v0A3F* ID_VENDOR_FROM_DATABASE=Swissonic AG usb:v0A43* ID_VENDOR_FROM_DATABASE=Boca Systems, Inc. usb:v0A46* ID_VENDOR_FROM_DATABASE=Davicom Semiconductor, Inc. usb:v0A46p0268* ID_MODEL_FROM_DATABASE=ST268 usb:v0A46p6688* ID_MODEL_FROM_DATABASE=ZT6688 Fast Ethernet Adapter usb:v0A46p8515* ID_MODEL_FROM_DATABASE=ADMtek ADM8515 NIC usb:v0A46p9000* ID_MODEL_FROM_DATABASE=DM9000E Fast Ethernet Adapter usb:v0A46p9601* ID_MODEL_FROM_DATABASE=DM9601 Fast Ethernet Adapter usb:v0A47* ID_VENDOR_FROM_DATABASE=Hirose Electric usb:v0A48* ID_VENDOR_FROM_DATABASE=I/O Interconnect usb:v0A48p3233* ID_MODEL_FROM_DATABASE=Multimedia Card Reader usb:v0A48p3239* ID_MODEL_FROM_DATABASE=Multimedia Card Reader usb:v0A48p3258* ID_MODEL_FROM_DATABASE=Dane Elec zMate SD Reader usb:v0A48p3259* ID_MODEL_FROM_DATABASE=Dane Elec zMate CF Reader usb:v0A48p5000* ID_MODEL_FROM_DATABASE=MediaGear xD-SM usb:v0A48p500A* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0A48p500F* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0A48p5010* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0A48p5011* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0A48p5014* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0A48p5020* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0A48p5021* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0A48p5022* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0A48p5023* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0A48p5024* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0A48p5025* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0A4A* ID_VENDOR_FROM_DATABASE=Ploytec GmbH usb:v0A4B* ID_VENDOR_FROM_DATABASE=Fujitsu Media Devices, Ltd usb:v0A4C* ID_VENDOR_FROM_DATABASE=Computex Co., Ltd usb:v0A4Cp15D9* ID_MODEL_FROM_DATABASE=OPTICAL MOUSE usb:v0A4D* ID_VENDOR_FROM_DATABASE=Evolution Electronics, Ltd usb:v0A4Dp0064* ID_MODEL_FROM_DATABASE=MK-225 Driver usb:v0A4Dp0065* ID_MODEL_FROM_DATABASE=MK-225C Driver usb:v0A4Dp0066* ID_MODEL_FROM_DATABASE=MK-225C Driver usb:v0A4Dp0067* ID_MODEL_FROM_DATABASE=MK-425C Driver usb:v0A4Dp0078* ID_MODEL_FROM_DATABASE=MK-37 Driver usb:v0A4Dp0079* ID_MODEL_FROM_DATABASE=MK-37C Driver usb:v0A4Dp007A* ID_MODEL_FROM_DATABASE=MK-37C Driver usb:v0A4Dp008C* ID_MODEL_FROM_DATABASE=TerraTec MIDI MASTER usb:v0A4Dp008D* ID_MODEL_FROM_DATABASE=MK-249C Driver usb:v0A4Dp008E* ID_MODEL_FROM_DATABASE=MK-249C MIDI Keyboard usb:v0A4Dp008F* ID_MODEL_FROM_DATABASE=MK-449C Driver usb:v0A4Dp0090* ID_MODEL_FROM_DATABASE=Keystation 49e Driver usb:v0A4Dp0091* ID_MODEL_FROM_DATABASE=Keystation 61es Driver usb:v0A4Dp00A0* ID_MODEL_FROM_DATABASE=MK-361 Driver usb:v0A4Dp00A1* ID_MODEL_FROM_DATABASE=MK-361C Driver usb:v0A4Dp00A2* ID_MODEL_FROM_DATABASE=MK-361C Driver usb:v0A4Dp00A3* ID_MODEL_FROM_DATABASE=MK-461C MIDI Keyboard usb:v0A4Dp00B5* ID_MODEL_FROM_DATABASE=Keystation Pro 88 Driver usb:v0A4Dp00D2* ID_MODEL_FROM_DATABASE=E-Keys Driver usb:v0A4Dp00F0* ID_MODEL_FROM_DATABASE=UC-16 Driver usb:v0A4Dp00F1* ID_MODEL_FROM_DATABASE=X-Session Driver usb:v0A4Dp00F5* ID_MODEL_FROM_DATABASE=UC-33e MIDI Controller usb:v0A4E* ID_VENDOR_FROM_DATABASE=Steinberg Soft-und Hardware GmbH usb:v0A4F* ID_VENDOR_FROM_DATABASE=Litton Systems, Inc. usb:v0A50* ID_VENDOR_FROM_DATABASE=Mimaki Engineering Co., Ltd usb:v0A51* ID_VENDOR_FROM_DATABASE=Sony Electronics, Inc. usb:v0A52* ID_VENDOR_FROM_DATABASE=Jebsee Electronics Co., Ltd usb:v0A53* ID_VENDOR_FROM_DATABASE=Portable Peripheral Co., Ltd usb:v0A53p1000* ID_MODEL_FROM_DATABASE=Scanner usb:v0A53p2000* ID_MODEL_FROM_DATABASE=Q-Scan A6 Scanner usb:v0A53p2001* ID_MODEL_FROM_DATABASE=Q-Scan A6 Scanner usb:v0A53p2013* ID_MODEL_FROM_DATABASE=Media Drive A6 Scanner usb:v0A53p2014* ID_MODEL_FROM_DATABASE=Media Drive A6 Scanner usb:v0A53p2015* ID_MODEL_FROM_DATABASE=BizCardReader 600C usb:v0A53p2016* ID_MODEL_FROM_DATABASE=BizCardReader 600C usb:v0A53p202A* ID_MODEL_FROM_DATABASE=Scanshell-CSSN usb:v0A53p3000* ID_MODEL_FROM_DATABASE=Q-Scan A8 Scanner usb:v0A53p3002* ID_MODEL_FROM_DATABASE=Q-Scan A8 Reader usb:v0A53p3015* ID_MODEL_FROM_DATABASE=BizCardReader 300G usb:v0A53p302A* ID_MODEL_FROM_DATABASE=LM9832 - PA570 Mini Business Card Scanner [Targus] usb:v0A53p5001* ID_MODEL_FROM_DATABASE=BizCardReader 900C usb:v0A5A* ID_VENDOR_FROM_DATABASE=Electronics For Imaging, Inc. usb:v0A5B* ID_VENDOR_FROM_DATABASE=EAsics NV usb:v0A5C* ID_VENDOR_FROM_DATABASE=Broadcom Corp. usb:v0A5Cp0201* ID_MODEL_FROM_DATABASE=iLine10(tm) Network Adapter usb:v0A5Cp2000* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0A5Cp2001* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0A5Cp2009* ID_MODEL_FROM_DATABASE=BCM2035 Bluetooth usb:v0A5Cp200A* ID_MODEL_FROM_DATABASE=BCM2035 Bluetooth dongle usb:v0A5Cp200F* ID_MODEL_FROM_DATABASE=Bluetooth Controller usb:v0A5Cp201D* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0A5Cp201E* ID_MODEL_FROM_DATABASE=IBM Integrated Bluetooth IV usb:v0A5Cp2020* ID_MODEL_FROM_DATABASE=Bluetooth dongle usb:v0A5Cp2021* ID_MODEL_FROM_DATABASE=BCM2035B3 Bluetooth Adapter usb:v0A5Cp2033* ID_MODEL_FROM_DATABASE=BCM2033 Bluetooth usb:v0A5Cp2035* ID_MODEL_FROM_DATABASE=BCM2035 Bluetooth usb:v0A5Cp2038* ID_MODEL_FROM_DATABASE=Blutonium Device usb:v0A5Cp2039* ID_MODEL_FROM_DATABASE=BCM2045 Bluetooth usb:v0A5Cp2045* ID_MODEL_FROM_DATABASE=Bluetooth Controller usb:v0A5Cp2046* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0A5Cp2047* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0A5Cp205E* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0A5Cp2100* ID_MODEL_FROM_DATABASE=Bluetooth 2.0+eDR dongle usb:v0A5Cp2101* ID_MODEL_FROM_DATABASE=BCM2045 Bluetooth usb:v0A5Cp2102* ID_MODEL_FROM_DATABASE=ANYCOM Blue USB-200/250 usb:v0A5Cp2110* ID_MODEL_FROM_DATABASE=BCM2045B (BDC-2) [Bluetooth Controller] usb:v0A5Cp2111* ID_MODEL_FROM_DATABASE=ANYCOM Blue USB-UHE 200/250 usb:v0A5Cp2120* ID_MODEL_FROM_DATABASE=2045 Bluetooth 2.0 USB-UHE Device with trace filter usb:v0A5Cp2121* ID_MODEL_FROM_DATABASE=BCM2210 Bluetooth usb:v0A5Cp2122* ID_MODEL_FROM_DATABASE=Bluetooth 2.0+EDR dongle usb:v0A5Cp2123* ID_MODEL_FROM_DATABASE=Bluetooth dongle usb:v0A5Cp2130* ID_MODEL_FROM_DATABASE=2045 Bluetooth 2.0 USB-UHE Device with trace filter usb:v0A5Cp2131* ID_MODEL_FROM_DATABASE=2045 Bluetooth 2.0 Device with trace filter usb:v0A5Cp2145* ID_MODEL_FROM_DATABASE=BCM2045B (BDC-2.1) [Bluetooth Controller] usb:v0A5Cp2148* ID_MODEL_FROM_DATABASE=BCM92046DG-CL1ROM Bluetooth 2.1 Adapter usb:v0A5Cp2150* ID_MODEL_FROM_DATABASE=BCM2046 Bluetooth Device usb:v0A5Cp2151* ID_MODEL_FROM_DATABASE=Bluetooth usb:v0A5Cp2154* ID_MODEL_FROM_DATABASE=BCM92046DG-CL1ROM Bluetooth 2.1 UHE Dongle usb:v0A5Cp216C* ID_MODEL_FROM_DATABASE=BCM43142A0 Bluetooth Device usb:v0A5Cp216F* ID_MODEL_FROM_DATABASE=BCM20702A0 Bluetooth usb:v0A5Cp217D* ID_MODEL_FROM_DATABASE=HP Bluethunder usb:v0A5Cp217F* ID_MODEL_FROM_DATABASE=BCM2045B (BDC-2.1) usb:v0A5Cp2198* ID_MODEL_FROM_DATABASE=Bluetooth 3.0 Device usb:v0A5Cp219B* ID_MODEL_FROM_DATABASE=Bluetooth 2.1 Device usb:v0A5Cp21B1* ID_MODEL_FROM_DATABASE=HP Bluetooth Module usb:v0A5Cp21B4* ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 2.1 + EDR usb:v0A5Cp21B9* ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 2.1 + EDR usb:v0A5Cp21BA* ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 2.1 + EDR usb:v0A5Cp21BB* ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 2.1 + EDR usb:v0A5Cp21BC* ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 2.1 + EDR usb:v0A5Cp21BD* ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 2.1 + EDR usb:v0A5Cp21D7* ID_MODEL_FROM_DATABASE=BCM43142 Bluetooth 4.0 usb:v0A5Cp21E1* ID_MODEL_FROM_DATABASE=HP Portable SoftSailing usb:v0A5Cp21E3* ID_MODEL_FROM_DATABASE=HP Portable Valentine usb:v0A5Cp21E6* ID_MODEL_FROM_DATABASE=BCM20702 Bluetooth 4.0 [ThinkPad] usb:v0A5Cp21E8* ID_MODEL_FROM_DATABASE=BCM20702A0 Bluetooth 4.0 usb:v0A5Cp21F1* ID_MODEL_FROM_DATABASE=HP Portable Bumble Bee usb:v0A5Cp22BE* ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 3.0 + HS usb:v0A5Cp4500* ID_MODEL_FROM_DATABASE=BCM2046B1 USB 2.0 Hub (part of BCM2046 Bluetooth) usb:v0A5Cp4502* ID_MODEL_FROM_DATABASE=Keyboard (Boot Interface Subclass) usb:v0A5Cp4503* ID_MODEL_FROM_DATABASE=Mouse (Boot Interface Subclass) usb:v0A5Cp5800* ID_MODEL_FROM_DATABASE=BCM5880 Secure Applications Processor usb:v0A5Cp5801* ID_MODEL_FROM_DATABASE=BCM5880 Secure Applications Processor with fingerprint swipe sensor usb:v0A5Cp5802* ID_MODEL_FROM_DATABASE=BCM5880 Secure Applications Processor with fingerprint touch sensor usb:v0A5Cp5803* ID_MODEL_FROM_DATABASE=BCM5880 Secure Applications Processor with secure keyboard usb:v0A5Cp5804* ID_MODEL_FROM_DATABASE=BCM5880 Secure Applications Processor with fingerprint swipe sensor usb:v0A5Cp6300* ID_MODEL_FROM_DATABASE=Pirelli Remote NDIS Device usb:v0A5CpBD11* ID_MODEL_FROM_DATABASE=TiVo AG0100 802.11bg Wireless Adapter [Broadcom BCM4320] usb:v0A5CpBD13* ID_MODEL_FROM_DATABASE=BCM4323 802.11abgn Wireless Adapter usb:v0A5CpBD16* ID_MODEL_FROM_DATABASE=BCM4319 802.11bgn Wireless Adapter usb:v0A5CpBD17* ID_MODEL_FROM_DATABASE=BCM43236 802.11abgn Wireless Adapter usb:v0A5CpD11B* ID_MODEL_FROM_DATABASE=Eminent EM4045 [Broadcom 4320 USB] usb:v0A5D* ID_VENDOR_FROM_DATABASE=Diatrend Corp. usb:v0A5F* ID_VENDOR_FROM_DATABASE=Zebra usb:v0A5Fp0009* ID_MODEL_FROM_DATABASE=LP2844 Printer usb:v0A5Fp0081* ID_MODEL_FROM_DATABASE=GK420t Label Printer usb:v0A5Fp008B* ID_MODEL_FROM_DATABASE=HC100 wristbands Printer usb:v0A5Fp008C* ID_MODEL_FROM_DATABASE=ZP 450 Printer usb:v0A5Fp00D1* ID_MODEL_FROM_DATABASE=Zebra GC420d Label Printer usb:v0A5Fp930A* ID_MODEL_FROM_DATABASE=Printer usb:v0A62* ID_VENDOR_FROM_DATABASE=MPMan usb:v0A62p0010* ID_MODEL_FROM_DATABASE=MPMan MP-F40 MP3 Player usb:v0A66* ID_VENDOR_FROM_DATABASE=ClearCube Technology usb:v0A67* ID_VENDOR_FROM_DATABASE=Medeli Electronics Co., Ltd usb:v0A68* ID_VENDOR_FROM_DATABASE=Comaide Corp. usb:v0A69* ID_VENDOR_FROM_DATABASE=Chroma ate, Inc. usb:v0A6B* ID_VENDOR_FROM_DATABASE=Green House Co., Ltd usb:v0A6Bp0001* ID_MODEL_FROM_DATABASE=Compact Flash R/W with MP3 player usb:v0A6Bp000F* ID_MODEL_FROM_DATABASE=FlashDisk usb:v0A6C* ID_VENDOR_FROM_DATABASE=Integrated Circuit Systems, Inc. usb:v0A6D* ID_VENDOR_FROM_DATABASE=UPS Manufacturing usb:v0A6E* ID_VENDOR_FROM_DATABASE=Benwin usb:v0A6F* ID_VENDOR_FROM_DATABASE=Core Technology, Inc. usb:v0A6Fp0400* ID_MODEL_FROM_DATABASE=Xanboo usb:v0A70* ID_VENDOR_FROM_DATABASE=International Game Technology usb:v0A71* ID_VENDOR_FROM_DATABASE=VIPColor Technologies USA, Inc. usb:v0A71p0001* ID_MODEL_FROM_DATABASE=VP485 Printer usb:v0A72* ID_VENDOR_FROM_DATABASE=Sanwa Denshi usb:v0A73* ID_VENDOR_FROM_DATABASE=Mackie Designs usb:v0A73p0002* ID_MODEL_FROM_DATABASE=XD-2 [Spike] usb:v0A7D* ID_VENDOR_FROM_DATABASE=NSTL, Inc. usb:v0A7E* ID_VENDOR_FROM_DATABASE=Octagon Systems Corp. usb:v0A80* ID_VENDOR_FROM_DATABASE=Rexon Technology Corp., Ltd usb:v0A81* ID_VENDOR_FROM_DATABASE=Chesen Electronics Corp. usb:v0A81p0101* ID_MODEL_FROM_DATABASE=Keyboard usb:v0A81p0103* ID_MODEL_FROM_DATABASE=Keyboard usb:v0A81p0203* ID_MODEL_FROM_DATABASE=Mouse usb:v0A81p0205* ID_MODEL_FROM_DATABASE=PS/2 Keyboard+Mouse Adapter usb:v0A81p0701* ID_MODEL_FROM_DATABASE=USB Missile Launcher usb:v0A81pFF01* ID_MODEL_FROM_DATABASE=Wireless Missile Launcher usb:v0A82* ID_VENDOR_FROM_DATABASE=Syscan usb:v0A82p4600* ID_MODEL_FROM_DATABASE=TravelScan 460/464 usb:v0A83* ID_VENDOR_FROM_DATABASE=NextComm, Inc. usb:v0A84* ID_VENDOR_FROM_DATABASE=Maui Innovative Peripherals usb:v0A85* ID_VENDOR_FROM_DATABASE=Idexx Labs usb:v0A86* ID_VENDOR_FROM_DATABASE=NITGen Co., Ltd usb:v0A89* ID_VENDOR_FROM_DATABASE=Aktiv usb:v0A89p0001* ID_MODEL_FROM_DATABASE=Guardant Stealth/Net usb:v0A89p0002* ID_MODEL_FROM_DATABASE=Guardant ID usb:v0A89p0003* ID_MODEL_FROM_DATABASE=Guardant Stealth 2 usb:v0A89p0004* ID_MODEL_FROM_DATABASE=Rutoken usb:v0A89p0005* ID_MODEL_FROM_DATABASE=Guardant Fidus usb:v0A89p0006* ID_MODEL_FROM_DATABASE=Guardant Stealth 3 usb:v0A89p0007* ID_MODEL_FROM_DATABASE=Guardant Stealth 2 usb:v0A89p0008* ID_MODEL_FROM_DATABASE=Guardant Stealth 3 Sign/Time usb:v0A89p0009* ID_MODEL_FROM_DATABASE=Guardant Code usb:v0A89p000A* ID_MODEL_FROM_DATABASE=Guardant Sign Pro usb:v0A89p000B* ID_MODEL_FROM_DATABASE=Guardant Sign Pro HID usb:v0A89p000C* ID_MODEL_FROM_DATABASE=Guardant Stealth 3 Sign/Time usb:v0A89p000D* ID_MODEL_FROM_DATABASE=Guardant Code HID usb:v0A89p000F* ID_MODEL_FROM_DATABASE=Guardant System Firmware Update usb:v0A89p0020* ID_MODEL_FROM_DATABASE=Rutoken S usb:v0A89p0025* ID_MODEL_FROM_DATABASE=Rutoken lite usb:v0A89p0026* ID_MODEL_FROM_DATABASE=Rutoken lite HID usb:v0A89p002A* ID_MODEL_FROM_DATABASE=Rutoken Mass Storage usb:v0A89p002B* ID_MODEL_FROM_DATABASE=Guardant Mass Storage usb:v0A89p0030* ID_MODEL_FROM_DATABASE=Rutoken ECP usb:v0A89p0040* ID_MODEL_FROM_DATABASE=Rutoken ECP HID usb:v0A89p0060* ID_MODEL_FROM_DATABASE=Rutoken Magistra usb:v0A89p0061* ID_MODEL_FROM_DATABASE=Rutoken Magistra usb:v0A89p0069* ID_MODEL_FROM_DATABASE=Reader usb:v0A89p0080* ID_MODEL_FROM_DATABASE=Rutoken PinPad Ex usb:v0A89p0081* ID_MODEL_FROM_DATABASE=Rutoken PinPad In usb:v0A89p0082* ID_MODEL_FROM_DATABASE=Rutoken PinPad 2 usb:v0A8D* ID_VENDOR_FROM_DATABASE=Picturetel usb:v0A8E* ID_VENDOR_FROM_DATABASE=Japan Aviation Electronics Industry, Ltd usb:v0A8Ep2011* ID_MODEL_FROM_DATABASE=Filter Driver For JAE XMC R/W usb:v0A90* ID_VENDOR_FROM_DATABASE=Candy Technology Co., Ltd usb:v0A91* ID_VENDOR_FROM_DATABASE=Globlink Technology, Inc. usb:v0A91p3801* ID_MODEL_FROM_DATABASE=Targus PAKP003 Mouse usb:v0A92* ID_VENDOR_FROM_DATABASE=EGO SYStems, Inc. usb:v0A92p0011* ID_MODEL_FROM_DATABASE=SYS WaveTerminal U2A usb:v0A92p0021* ID_MODEL_FROM_DATABASE=GIGAPort usb:v0A92p0031* ID_MODEL_FROM_DATABASE=GIGAPortAG usb:v0A92p0053* ID_MODEL_FROM_DATABASE=AudioTrak Optoplay usb:v0A92p0061* ID_MODEL_FROM_DATABASE=Waveterminal U24 usb:v0A92p0071* ID_MODEL_FROM_DATABASE=MAYA EX7 usb:v0A92p0091* ID_MODEL_FROM_DATABASE=Maya 44 usb:v0A92p00B1* ID_MODEL_FROM_DATABASE=MAYA EX5 usb:v0A92p1000* ID_MODEL_FROM_DATABASE=MIDI Mate usb:v0A92p1010* ID_MODEL_FROM_DATABASE=RoMI/O usb:v0A92p1020* ID_MODEL_FROM_DATABASE=M4U usb:v0A92p1030* ID_MODEL_FROM_DATABASE=M8U usb:v0A92p1090* ID_MODEL_FROM_DATABASE=KeyControl49 usb:v0A92p10A0* ID_MODEL_FROM_DATABASE=KeyControl25 usb:v0A93* ID_VENDOR_FROM_DATABASE=C Technologies AB usb:v0A93p0002* ID_MODEL_FROM_DATABASE=C-Pen 10 usb:v0A93p0005* ID_MODEL_FROM_DATABASE=MyPen Light usb:v0A93p000D* ID_MODEL_FROM_DATABASE=Input Pen usb:v0A93p0010* ID_MODEL_FROM_DATABASE=C-Pen 20 usb:v0A93p0A93* ID_MODEL_FROM_DATABASE=PayPen usb:v0A94* ID_VENDOR_FROM_DATABASE=Intersense usb:v0AA3* ID_VENDOR_FROM_DATABASE=Lava Computer Mfg., Inc. usb:v0AA4* ID_VENDOR_FROM_DATABASE=Develco Elektronik usb:v0AA5* ID_VENDOR_FROM_DATABASE=First International Digital usb:v0AA5p0002* ID_MODEL_FROM_DATABASE=irock! 500 Series usb:v0AA5p0801* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0AA6* ID_VENDOR_FROM_DATABASE=Perception Digital, Ltd usb:v0AA6p0101* ID_MODEL_FROM_DATABASE=Hercules Jukebox usb:v0AA6p1501* ID_MODEL_FROM_DATABASE=Store 'n' Go HD Drive usb:v0AA7* ID_VENDOR_FROM_DATABASE=Wincor Nixdorf International GmbH usb:v0AA7p0100* ID_MODEL_FROM_DATABASE=POS Keyboard, TA58P-USB usb:v0AA7p0101* ID_MODEL_FROM_DATABASE=POS Keyboard, TA85P-USB usb:v0AA7p0102* ID_MODEL_FROM_DATABASE=POS Keyboard, TA59-USB usb:v0AA7p0103* ID_MODEL_FROM_DATABASE=POS Keyboard, TA60-USB usb:v0AA7p0104* ID_MODEL_FROM_DATABASE=SNIkey Keyboard, SNIKey-KB-USB usb:v0AA7p0200* ID_MODEL_FROM_DATABASE=Operator Display, BA63-USB usb:v0AA7p0201* ID_MODEL_FROM_DATABASE=Operator Display, BA66-USB usb:v0AA7p0202* ID_MODEL_FROM_DATABASE=Operator Display & Scanner, XiCheck-BA63 usb:v0AA7p0203* ID_MODEL_FROM_DATABASE=Operator Display & Scanner, XiCheck-BA66 usb:v0AA7p0204* ID_MODEL_FROM_DATABASE=Graphics Operator Display, BA63GV usb:v0AA7p0300* ID_MODEL_FROM_DATABASE=POS Printer (printer class mode), TH210 usb:v0AA7p0301* ID_MODEL_FROM_DATABASE=POS Printer (native mode), TH210 usb:v0AA7p0302* ID_MODEL_FROM_DATABASE=POS Printer (printer class mode), TH220 usb:v0AA7p0303* ID_MODEL_FROM_DATABASE=POS Printer (native mode), TH220 usb:v0AA7p0304* ID_MODEL_FROM_DATABASE=POS Printer, TH230 usb:v0AA7p0305* ID_MODEL_FROM_DATABASE=Lottery Printer, XiPrintPlus usb:v0AA7p0306* ID_MODEL_FROM_DATABASE=POS Printer (printer class mode), TH320 usb:v0AA7p0307* ID_MODEL_FROM_DATABASE=POS Printer (native mode), TH320 usb:v0AA7p0308* ID_MODEL_FROM_DATABASE=POS Printer (printer class mode), TH420 usb:v0AA7p0309* ID_MODEL_FROM_DATABASE=POS Printer (native mode), TH420 usb:v0AA7p030A* ID_MODEL_FROM_DATABASE=POS Printer, TH200B usb:v0AA7p0400* ID_MODEL_FROM_DATABASE=Lottery Scanner, Xiscan S usb:v0AA7p0401* ID_MODEL_FROM_DATABASE=Lottery Scanner, Xiscan 3 usb:v0AA7p0402* ID_MODEL_FROM_DATABASE=Programmable Magnetic Swipe Card Reader, MSRP-USB usb:v0AA7p0500* ID_MODEL_FROM_DATABASE=IDE Adapter usb:v0AA7p0501* ID_MODEL_FROM_DATABASE=Hub Printer Interface usb:v0AA7p0502* ID_MODEL_FROM_DATABASE=Hub SNIKey Keyboard usb:v0AA7p4304* ID_MODEL_FROM_DATABASE=Banking Printer TP07 usb:v0AA7p4305* ID_MODEL_FROM_DATABASE=Banking Printer TP07c usb:v0AA7p4500* ID_MODEL_FROM_DATABASE=WN Central Special Electronics usb:v0AA8* ID_VENDOR_FROM_DATABASE=TriGem Computer, Inc. usb:v0AA8p0060* ID_MODEL_FROM_DATABASE=TG 11Mbps WLAN Mini Adapter usb:v0AA8p1001* ID_MODEL_FROM_DATABASE=DreamComboM4100 usb:v0AA8p3002* ID_MODEL_FROM_DATABASE=InkJet Color Printer usb:v0AA8p8001* ID_MODEL_FROM_DATABASE=TG_iMON usb:v0AA8p8002* ID_MODEL_FROM_DATABASE=TG_KLOSS usb:v0AA8pA001* ID_MODEL_FROM_DATABASE=TG_X2 usb:v0AA8pA002* ID_MODEL_FROM_DATABASE=TGVFD_KLOSS usb:v0AA8pFFDA* ID_MODEL_FROM_DATABASE=iMON_VFD usb:v0AA9* ID_VENDOR_FROM_DATABASE=Baromtec Co. usb:v0AA9pF01B* ID_MODEL_FROM_DATABASE=Medion MD 6242 MP3 Player usb:v0AAA* ID_VENDOR_FROM_DATABASE=Japan CBM Corp. usb:v0AAB* ID_VENDOR_FROM_DATABASE=Vision Shape Europe SA usb:v0AAC* ID_VENDOR_FROM_DATABASE=iCompression, Inc. usb:v0AAD* ID_VENDOR_FROM_DATABASE=Rohde & Schwarz GmbH & Co. KG usb:v0AADp0003* ID_MODEL_FROM_DATABASE=NRP-Z21 usb:v0AADp000C* ID_MODEL_FROM_DATABASE=NRP-Z11 usb:v0AADp0013* ID_MODEL_FROM_DATABASE=NRP-Z22 usb:v0AADp0014* ID_MODEL_FROM_DATABASE=NRP-Z23 usb:v0AADp0015* ID_MODEL_FROM_DATABASE=NRP-Z24 usb:v0AADp0016* ID_MODEL_FROM_DATABASE=NRP-Z51 usb:v0AADp0017* ID_MODEL_FROM_DATABASE=NRP-Z52 usb:v0AADp0018* ID_MODEL_FROM_DATABASE=NRP-Z55 usb:v0AADp0019* ID_MODEL_FROM_DATABASE=NRP-Z56 usb:v0AADp0021* ID_MODEL_FROM_DATABASE=NRP-Z91 usb:v0AADp0023* ID_MODEL_FROM_DATABASE=NRP-Z81 usb:v0AADp002C* ID_MODEL_FROM_DATABASE=NRP-Z31 usb:v0AADp002D* ID_MODEL_FROM_DATABASE=NRP-Z37 usb:v0AADp002F* ID_MODEL_FROM_DATABASE=NRP-Z27 usb:v0AADp0051* ID_MODEL_FROM_DATABASE=NRP-Z28 usb:v0AADp0052* ID_MODEL_FROM_DATABASE=NRP-Z98 usb:v0AADp0062* ID_MODEL_FROM_DATABASE=NRP-Z92 usb:v0AADp0070* ID_MODEL_FROM_DATABASE=NRP-Z57 usb:v0AADp0083* ID_MODEL_FROM_DATABASE=NRP-Z85 usb:v0AADp0095* ID_MODEL_FROM_DATABASE=NRP-Z86 usb:v0AAE* ID_VENDOR_FROM_DATABASE=NEC infrontia Corp. (Nitsuko) usb:v0AAF* ID_VENDOR_FROM_DATABASE=Digitalway Co., Ltd usb:v0AB0* ID_VENDOR_FROM_DATABASE=Arrow Strong Electronics Co., Ltd usb:v0AB1* ID_VENDOR_FROM_DATABASE=FEIG ELECTRONIC GmbH usb:v0AB1p0002* ID_MODEL_FROM_DATABASE=OBID RFID-Reader usb:v0AB1p0004* ID_MODEL_FROM_DATABASE=OBID classic-pro usb:v0ABA* ID_VENDOR_FROM_DATABASE=Ellisys usb:v0ABAp8001* ID_MODEL_FROM_DATABASE=Tracker 110 Protocol Analyzer usb:v0ABAp8002* ID_MODEL_FROM_DATABASE=Explorer 200 Protocol Analyzer usb:v0ABE* ID_VENDOR_FROM_DATABASE=Stereo-Link usb:v0ABEp0101* ID_MODEL_FROM_DATABASE=SL1200 DAC usb:v0ABF* ID_VENDOR_FROM_DATABASE=Diolan usb:v0ABFp3370* ID_MODEL_FROM_DATABASE=I2C/SPI Adapter - U2C-12 usb:v0AC3* ID_VENDOR_FROM_DATABASE=Sanyo Semiconductor Company Micro usb:v0AC4* ID_VENDOR_FROM_DATABASE=Leco Corp. usb:v0AC5* ID_VENDOR_FROM_DATABASE=I & C Corp. usb:v0AC6* ID_VENDOR_FROM_DATABASE=Singing Electrons, Inc. usb:v0AC7* ID_VENDOR_FROM_DATABASE=Panwest Corp. usb:v0AC8* ID_VENDOR_FROM_DATABASE=Z-Star Microelectronics Corp. usb:v0AC8p0301* ID_MODEL_FROM_DATABASE=Web Camera usb:v0AC8p0302* ID_MODEL_FROM_DATABASE=ZC0302 Webcam usb:v0AC8p0321* ID_MODEL_FROM_DATABASE=Vimicro generic vc0321 Camera usb:v0AC8p0323* ID_MODEL_FROM_DATABASE=Luxya WC-1200 USB 2.0 Webcam usb:v0AC8p0328* ID_MODEL_FROM_DATABASE=A4Tech PK-130MG usb:v0AC8p0336* ID_MODEL_FROM_DATABASE=Elecom UCAM-DLQ30 usb:v0AC8p301B* ID_MODEL_FROM_DATABASE=ZC0301 Webcam usb:v0AC8p303B* ID_MODEL_FROM_DATABASE=ZC0303 Webcam usb:v0AC8p305B* ID_MODEL_FROM_DATABASE=ZC0305 Webcam usb:v0AC8p307B* ID_MODEL_FROM_DATABASE=USB 1.1 Webcam usb:v0AC8p332D* ID_MODEL_FROM_DATABASE=Vega USB 2.0 Camera usb:v0AC8p3343* ID_MODEL_FROM_DATABASE=Sirius USB 2.0 Camera usb:v0AC8p3370* ID_MODEL_FROM_DATABASE=Traveler TV 6500 SF Dia-scanner usb:v0AC8p3420* ID_MODEL_FROM_DATABASE=Venus USB2.0 Camera usb:v0AC8pC001* ID_MODEL_FROM_DATABASE=Sony embedded vimicro Camera usb:v0AC8pC002* ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC1 usb:v0AC8pC302* ID_MODEL_FROM_DATABASE=Vega USB 2.0 Camera usb:v0AC8pC303* ID_MODEL_FROM_DATABASE=Saturn USB 2.0 Camera usb:v0AC8pC326* ID_MODEL_FROM_DATABASE=Namuga 1.3M Webcam usb:v0AC8pC33F* ID_MODEL_FROM_DATABASE=Webcam usb:v0AC8pC429* ID_MODEL_FROM_DATABASE=Lenovo ThinkCentre Web Camera usb:v0AC8pC42D* ID_MODEL_FROM_DATABASE=Lenovo IdeaCentre Web Camera usb:v0AC9* ID_VENDOR_FROM_DATABASE=Micro Solutions, Inc. usb:v0AC9p0000* ID_MODEL_FROM_DATABASE=Backpack CD-ReWriter usb:v0AC9p0001* ID_MODEL_FROM_DATABASE=BACKPACK 2 Cable usb:v0AC9p0010* ID_MODEL_FROM_DATABASE=BACKPACK usb:v0AC9p0011* ID_MODEL_FROM_DATABASE=Backpack 40GB Hard Drive usb:v0AC9p0110* ID_MODEL_FROM_DATABASE=BACKPACK usb:v0AC9p0111* ID_MODEL_FROM_DATABASE=BackPack usb:v0AC9p1234* ID_MODEL_FROM_DATABASE=BACKPACK usb:v0ACA* ID_VENDOR_FROM_DATABASE=OPEN Networks Ltd usb:v0ACAp1060* ID_MODEL_FROM_DATABASE=OPEN NT1 Plus II usb:v0ACC* ID_VENDOR_FROM_DATABASE=Koga Electronics Co. usb:v0ACD* ID_VENDOR_FROM_DATABASE=ID Tech usb:v0ACDp0300* ID_MODEL_FROM_DATABASE=IDT1221U RS-232 Adapter usb:v0ACDp0401* ID_MODEL_FROM_DATABASE=Spectrum III Hybrid Smartcard Reader usb:v0ACDp0630* ID_MODEL_FROM_DATABASE=Spectrum III Mag-Only Insert Reader (SPT3-355 Series) USB-CDC usb:v0ACDp0810* ID_MODEL_FROM_DATABASE=SecurePIN (IDPA-506100Y) PIN Pad usb:v0ACDp2030* ID_MODEL_FROM_DATABASE=ValueMag Magnetic Stripe Reader usb:v0ACE* ID_VENDOR_FROM_DATABASE=ZyDAS usb:v0ACEp1201* ID_MODEL_FROM_DATABASE=ZD1201 802.11b usb:v0ACEp1211* ID_MODEL_FROM_DATABASE=ZD1211 802.11g usb:v0ACEp1215* ID_MODEL_FROM_DATABASE=ZD1211B 802.11g usb:v0ACEp1221* ID_MODEL_FROM_DATABASE=ZD1221 802.11n usb:v0ACEp1602* ID_MODEL_FROM_DATABASE=ZyXEL Omni FaxModem 56K usb:v0ACEp1608* ID_MODEL_FROM_DATABASE=ZyXEL Omni FaxModem 56K UNO usb:v0ACEp1611* ID_MODEL_FROM_DATABASE=ZyXEL Omni FaxModem 56K Plus usb:v0ACEp2011* ID_MODEL_FROM_DATABASE=Virtual media for 802.11bg usb:v0ACEp20FF* ID_MODEL_FROM_DATABASE=Virtual media for 802.11bg usb:v0ACEpA211* ID_MODEL_FROM_DATABASE=ZD1211 802.11b/g Wireless Adapter usb:v0ACEpB215* ID_MODEL_FROM_DATABASE=802.11bg usb:v0ACF* ID_VENDOR_FROM_DATABASE=Intoto, Inc. usb:v0AD0* ID_VENDOR_FROM_DATABASE=Intellix Corp. usb:v0AD1* ID_VENDOR_FROM_DATABASE=Remotec Technology, Ltd usb:v0AD2* ID_VENDOR_FROM_DATABASE=Service & Quality Technology Co., Ltd usb:v0ADA* ID_VENDOR_FROM_DATABASE=Data Encryption Systems Ltd. usb:v0ADAp0005* ID_MODEL_FROM_DATABASE=DK2 usb:v0AE3* ID_VENDOR_FROM_DATABASE=Allion Computer, Inc. usb:v0AE4* ID_VENDOR_FROM_DATABASE=Taito Corp. usb:v0AE7* ID_VENDOR_FROM_DATABASE=Neodym Systems, Inc. usb:v0AE8* ID_VENDOR_FROM_DATABASE=System Support Co., Ltd usb:v0AE9* ID_VENDOR_FROM_DATABASE=North Shore Circuit Design L.L.P. usb:v0AEA* ID_VENDOR_FROM_DATABASE=SciEssence, LLC usb:v0AEB* ID_VENDOR_FROM_DATABASE=TTP Communications, Ltd usb:v0AEC* ID_VENDOR_FROM_DATABASE=Neodio Technologies Corp. usb:v0AECp2101* ID_MODEL_FROM_DATABASE=SmartMedia Card Reader usb:v0AECp2102* ID_MODEL_FROM_DATABASE=CompactFlash Card Reader usb:v0AECp2103* ID_MODEL_FROM_DATABASE=MMC/SD Card Reader usb:v0AECp2104* ID_MODEL_FROM_DATABASE=MemoryStick Card Reader usb:v0AECp2201* ID_MODEL_FROM_DATABASE=SmartMedia+CompactFlash Card Reader usb:v0AECp2202* ID_MODEL_FROM_DATABASE=SmartMedia+MMC/SD Card Reader usb:v0AECp2203* ID_MODEL_FROM_DATABASE=SmartMedia+MemoryStick Card Reader usb:v0AECp2204* ID_MODEL_FROM_DATABASE=CompactFlash+MMC/SD Card Reader usb:v0AECp2205* ID_MODEL_FROM_DATABASE=CompactFlash+MemoryStick Card Reader usb:v0AECp2206* ID_MODEL_FROM_DATABASE=MMC/SD+MemoryStick Card Reader usb:v0AECp2301* ID_MODEL_FROM_DATABASE=SmartMedia+CompactFlash+MMC/SD Card Reader usb:v0AECp2302* ID_MODEL_FROM_DATABASE=SmartMedia+CompactFlash+MemoryStick Card Reader usb:v0AECp2303* ID_MODEL_FROM_DATABASE=SmartMedia+MMC/SD+MemoryStick Card Reader usb:v0AECp2304* ID_MODEL_FROM_DATABASE=CompactFlash+MMC/SD+MemoryStick Card Reader usb:v0AECp3016* ID_MODEL_FROM_DATABASE=MMC/SD+Memory Stick Card Reader usb:v0AECp3050* ID_MODEL_FROM_DATABASE=ND3050 8-in-1 Card Reader usb:v0AECp3060* ID_MODEL_FROM_DATABASE=1.1 FS Card Reader usb:v0AECp3101* ID_MODEL_FROM_DATABASE=MMC/SD Card Reader usb:v0AECp3102* ID_MODEL_FROM_DATABASE=MemoryStick Card Reader usb:v0AECp3201* ID_MODEL_FROM_DATABASE=MMC/SD+MemoryStick Card Reader usb:v0AECp3216* ID_MODEL_FROM_DATABASE=HS Card Reader usb:v0AECp3260* ID_MODEL_FROM_DATABASE=7-in-1 Card Reader usb:v0AECp5010* ID_MODEL_FROM_DATABASE=ND5010 Card Reader usb:v0AF0* ID_VENDOR_FROM_DATABASE=Option usb:v0AF0p5000* ID_MODEL_FROM_DATABASE=UMTS Card usb:v0AF0p6000* ID_MODEL_FROM_DATABASE=GlobeTrotter 3G datacard usb:v0AF0p6300* ID_MODEL_FROM_DATABASE=GT 3G Quad UMTS/GPRS Card usb:v0AF0p6600* ID_MODEL_FROM_DATABASE=GlobeTrotter 3G+ datacard usb:v0AF0p6711* ID_MODEL_FROM_DATABASE=GlobeTrotter Express 7.2 v2 usb:v0AF0p6971* ID_MODEL_FROM_DATABASE=Globetrotter HSDPA Modem usb:v0AF0p7251* ID_MODEL_FROM_DATABASE=Globetrotter HSUPA Modem (aka iCON HSUPA E) usb:v0AF0p7501* ID_MODEL_FROM_DATABASE=Globetrotter HSUPA Modem (icon 411 aka "Vodafone K3760") usb:v0AF0p7601* ID_MODEL_FROM_DATABASE=Globetrotter MO40x 3G Modem (GTM 382) usb:v0AF0p7701* ID_MODEL_FROM_DATABASE=Globetrotter HSUPA Modem (aka icon 451) usb:v0AF0pD055* ID_MODEL_FROM_DATABASE=Globetrotter GI0505 [iCON 505] usb:v0AF6* ID_VENDOR_FROM_DATABASE=Silver I Co., Ltd usb:v0AF7* ID_VENDOR_FROM_DATABASE=B2C2, Inc. usb:v0AF7p0101* ID_MODEL_FROM_DATABASE=Digital TV USB Receiver (DVB-S/T/C / ATSC) usb:v0AF9* ID_VENDOR_FROM_DATABASE=Hama, Inc. usb:v0AF9p0010* ID_MODEL_FROM_DATABASE=USB SightCam 100 usb:v0AF9p0011* ID_MODEL_FROM_DATABASE=Micro Innovations IC50C Webcam usb:v0AFA* ID_VENDOR_FROM_DATABASE=DMC Co., Ltd. usb:v0AFAp07D2* ID_MODEL_FROM_DATABASE=Controller Board for Projected Capacitive Touch Screen DUS3000 usb:v0AFC* ID_VENDOR_FROM_DATABASE=Zaptronix Ltd usb:v0AFD* ID_VENDOR_FROM_DATABASE=Tateno Dennou, Inc. usb:v0AFE* ID_VENDOR_FROM_DATABASE=Cummins Engine Co. usb:v0AFF* ID_VENDOR_FROM_DATABASE=Jump Zone Network Products, Inc. usb:v0B00* ID_VENDOR_FROM_DATABASE=INGENICO usb:v0B05* ID_VENDOR_FROM_DATABASE=ASUSTek Computer, Inc. usb:v0B05p0001* ID_MODEL_FROM_DATABASE=MeMO Pad HD 7 (CD-ROM mode) usb:v0B05p1101* ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC4S) usb:v0B05p1706* ID_MODEL_FROM_DATABASE=WL-167G v1 802.11g Adapter [Ralink RT2571] usb:v0B05p1707* ID_MODEL_FROM_DATABASE=WL-167G v1 802.11g Adapter [Ralink RT2571] usb:v0B05p1708* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0B05p170B* ID_MODEL_FROM_DATABASE=Multi card reader usb:v0B05p170C* ID_MODEL_FROM_DATABASE=WL-159g 802.11bg usb:v0B05p170D* ID_MODEL_FROM_DATABASE=802.11b/g Wireless Network Adapter usb:v0B05p1712* ID_MODEL_FROM_DATABASE=BT-183 Bluetooth 2.0+EDR adapter usb:v0B05p1715* ID_MODEL_FROM_DATABASE=2045 Bluetooth 2.0 Device with trace filter usb:v0B05p1716* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0B05p1717* ID_MODEL_FROM_DATABASE=WL169gE 802.11g Adapter [Broadcom 4320 USB] usb:v0B05p171B* ID_MODEL_FROM_DATABASE=A9T wireless 802.11bg usb:v0B05p171C* ID_MODEL_FROM_DATABASE=802.11b/g Wireless Network Adapter usb:v0B05p171F* ID_MODEL_FROM_DATABASE=My Cinema U3000 Mini [DiBcom DiB7700P] usb:v0B05p1723* ID_MODEL_FROM_DATABASE=WL-167G v2 802.11g Adapter [Ralink RT2571W] usb:v0B05p1724* ID_MODEL_FROM_DATABASE=RT2573 usb:v0B05p1726* ID_MODEL_FROM_DATABASE=Laptop OLED Display usb:v0B05p172A* ID_MODEL_FROM_DATABASE=ASUS 802.11n Network Adapter usb:v0B05p172B* ID_MODEL_FROM_DATABASE=802.11n Network Adapter usb:v0B05p1731* ID_MODEL_FROM_DATABASE=802.11n Network Adapter usb:v0B05p1732* ID_MODEL_FROM_DATABASE=802.11n Network Adapter usb:v0B05p1734* ID_MODEL_FROM_DATABASE=ASUS AF-200 usb:v0B05p173C* ID_MODEL_FROM_DATABASE=BT-183 Bluetooth 2.0 usb:v0B05p173F* ID_MODEL_FROM_DATABASE=My Cinema U3100 Mini usb:v0B05p1742* ID_MODEL_FROM_DATABASE=802.11n Network Adapter usb:v0B05p1743* ID_MODEL_FROM_DATABASE=Xonar U1 Audio Station usb:v0B05p1751* ID_MODEL_FROM_DATABASE=BT-253 Bluetooth Adapter usb:v0B05p175B* ID_MODEL_FROM_DATABASE=Laptop OLED Display usb:v0B05p1760* ID_MODEL_FROM_DATABASE=802.11n Network Adapter usb:v0B05p1761* ID_MODEL_FROM_DATABASE=USB-N11 802.11n Network Adapter [Ralink RT2870] usb:v0B05p1774* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) usb:v0B05p1776* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem usb:v0B05p1779* ID_MODEL_FROM_DATABASE=My Cinema U3100 Mini Plus [AF9035A] usb:v0B05p1784* ID_MODEL_FROM_DATABASE=USB-N13 802.11n Network Adapter (rev. A1) [Ralink RT3072] usb:v0B05p1786* ID_MODEL_FROM_DATABASE=USB-N10 802.11n Network Adapter [Realtek RTL8188SU] usb:v0B05p1788* ID_MODEL_FROM_DATABASE=BT-270 Bluetooth Adapter usb:v0B05p1791* ID_MODEL_FROM_DATABASE=WL-167G v3 802.11n Adapter [Realtek RTL8188SU] usb:v0B05p179D* ID_MODEL_FROM_DATABASE=USB-N53 802.11abgn Network Adapter [Ralink RT3572] usb:v0B05p179E* ID_MODEL_FROM_DATABASE=Eee Note EA800 (network mode) usb:v0B05p179F* ID_MODEL_FROM_DATABASE=Eee Note EA800 (tablet mode) usb:v0B05p17A0* ID_MODEL_FROM_DATABASE=Xonar U3 sound card usb:v0B05p17A1* ID_MODEL_FROM_DATABASE=Eee Note EA800 (mass storage mode) usb:v0B05p17AB* ID_MODEL_FROM_DATABASE=USB-N13 802.11n Network Adapter (rev. B1) [Realtek RTL8192CU] usb:v0B05p17BA* ID_MODEL_FROM_DATABASE=N10 Nano 802.11n Network Adapter [Realtek RTL8192CU] usb:v0B05p17C7* ID_MODEL_FROM_DATABASE=WL-330NUL usb:v0B05p17C9* ID_MODEL_FROM_DATABASE=USB-AC53 802.11a/b/g/n/ac Wireless Adapter [Broadcom BCM43526] usb:v0B05p17CB* ID_MODEL_FROM_DATABASE=Broadcom BCM20702A0 Bluetooth usb:v0B05p17D1* ID_MODEL_FROM_DATABASE=AC51 802.11a/b/g/n/ac Wireless Adapter [Mediatek MT7610/Ralink RT2870] usb:v0B05p4C80* ID_MODEL_FROM_DATABASE=Transformer Pad TF300TG usb:v0B05p4C90* ID_MODEL_FROM_DATABASE=Transformer Pad Infinity TF700 usb:v0B05p4C91* ID_MODEL_FROM_DATABASE=Transformer Pad Infinity TF700 (Debug mode) usb:v0B05p4CA0* ID_MODEL_FROM_DATABASE=Transformer Pad TF701T usb:v0B05p4CA1* ID_MODEL_FROM_DATABASE=Transformer Pad TF701T (Debug mode) usb:v0B05p4D00* ID_MODEL_FROM_DATABASE=Transformer Prime TF201 usb:v0B05p4D01* ID_MODEL_FROM_DATABASE=Transformer Prime TF201 (debug mode) usb:v0B05p4DAF* ID_MODEL_FROM_DATABASE=Transformer Pad Infinity TF700 (Fastboot) usb:v0B05p5410* ID_MODEL_FROM_DATABASE=MeMO Pad HD 7 (MTP mode) usb:v0B05p5412* ID_MODEL_FROM_DATABASE=MeMO Pad HD 7 (PTP mode) usb:v0B05p550F* ID_MODEL_FROM_DATABASE=ASUS fonepad 7 usb:v0B05p6101* ID_MODEL_FROM_DATABASE=Cable Modem usb:v0B05p620A* ID_MODEL_FROM_DATABASE=Remote NDIS Device usb:v0B05pB700* ID_MODEL_FROM_DATABASE=Broadcom Bluetooth 2.1 usb:v0B0B* ID_VENDOR_FROM_DATABASE=Datamax-O'Neil usb:v0B0Bp106E* ID_MODEL_FROM_DATABASE=Datamax E-4304 usb:v0B0C* ID_VENDOR_FROM_DATABASE=Todos AB usb:v0B0Cp0009* ID_MODEL_FROM_DATABASE=Todos Argos Mini II Smart Card Reader usb:v0B0Cp001E* ID_MODEL_FROM_DATABASE=e.dentifier2 (ABN AMRO electronic banking card reader NL) usb:v0B0Cp002E* ID_MODEL_FROM_DATABASE=C200 smartcard controller (Nordea card reader) usb:v0B0Cp003F* ID_MODEL_FROM_DATABASE=Todos C400 smartcard controller (Handelsbanken card reader) usb:v0B0Cp0050* ID_MODEL_FROM_DATABASE=Argos Mini II Smart Card Reader (CCID) usb:v0B0D* ID_VENDOR_FROM_DATABASE=ProjectLab usb:v0B0Dp0000* ID_MODEL_FROM_DATABASE=CenturyCD usb:v0B0E* ID_VENDOR_FROM_DATABASE=GN Netcom usb:v0B0Ep034C* ID_MODEL_FROM_DATABASE=Jabra UC Voice 750 MS usb:v0B0Ep0420* ID_MODEL_FROM_DATABASE=Jabra SPEAK 510 usb:v0B0Ep094D* ID_MODEL_FROM_DATABASE=GN Netcom / Jabra REVO Wireless usb:v0B0Ep1022* ID_MODEL_FROM_DATABASE=Jabra PRO 9450, Type 9400BS (DECT Headset) usb:v0B0Ep2007* ID_MODEL_FROM_DATABASE=GN 2000 Stereo Corded Headset usb:v0B0Ep620C* ID_MODEL_FROM_DATABASE=Jabra BT620s usb:v0B0Ep9330* ID_MODEL_FROM_DATABASE=Jabra GN9330 Headset usb:v0B0F* ID_VENDOR_FROM_DATABASE=AVID Technology usb:v0B10* ID_VENDOR_FROM_DATABASE=Pcally usb:v0B11* ID_VENDOR_FROM_DATABASE=I Tech Solutions Co., Ltd usb:v0B1E* ID_VENDOR_FROM_DATABASE=Electronic Warfare Assoc., Inc. (EWA) usb:v0B1Ep8007* ID_MODEL_FROM_DATABASE=Blackhawk USB560-BP JTAG Emulator usb:v0B1F* ID_VENDOR_FROM_DATABASE=Insyde Software Corp. usb:v0B20* ID_VENDOR_FROM_DATABASE=TransDimension, Inc. usb:v0B21* ID_VENDOR_FROM_DATABASE=Yokogawa Electric Corp. usb:v0B22* ID_VENDOR_FROM_DATABASE=Japan System Development Co., Ltd usb:v0B23* ID_VENDOR_FROM_DATABASE=Pan-Asia Electronics Co., Ltd usb:v0B24* ID_VENDOR_FROM_DATABASE=Link Evolution Corp. usb:v0B27* ID_VENDOR_FROM_DATABASE=Ritek Corp. usb:v0B28* ID_VENDOR_FROM_DATABASE=Kenwood Corp. usb:v0B2C* ID_VENDOR_FROM_DATABASE=Village Center, Inc. usb:v0B30* ID_VENDOR_FROM_DATABASE=PNY Technologies, Inc. usb:v0B30p0006* ID_MODEL_FROM_DATABASE=SM Media-Shuttle Card Reader usb:v0B33* ID_VENDOR_FROM_DATABASE=Contour Design, Inc. usb:v0B33p0020* ID_MODEL_FROM_DATABASE=ShuttleXpress usb:v0B33p0700* ID_MODEL_FROM_DATABASE=RollerMouse Pro usb:v0B37* ID_VENDOR_FROM_DATABASE=Hitachi ULSI Systems Co., Ltd usb:v0B38* ID_VENDOR_FROM_DATABASE=Gear Head usb:v0B38p0003* ID_MODEL_FROM_DATABASE=Keyboard usb:v0B38p0010* ID_MODEL_FROM_DATABASE=107-Key Keyboard usb:v0B39* ID_VENDOR_FROM_DATABASE=Omnidirectional Control Technology, Inc. usb:v0B39p0001* ID_MODEL_FROM_DATABASE=Composite USB PS2 Converter usb:v0B39p0109* ID_MODEL_FROM_DATABASE=USB TO Ethernet usb:v0B39p0421* ID_MODEL_FROM_DATABASE=Serial usb:v0B39p0801* ID_MODEL_FROM_DATABASE=USB-Parallel Bridge usb:v0B39p0901* ID_MODEL_FROM_DATABASE=OCT To Fast Ethernet Converter usb:v0B39p0C03* ID_MODEL_FROM_DATABASE=LAN DOCK Serial Converter usb:v0B3A* ID_VENDOR_FROM_DATABASE=IPaxess usb:v0B3B* ID_VENDOR_FROM_DATABASE=Tekram Technology Co., Ltd usb:v0B3Bp0163* ID_MODEL_FROM_DATABASE=TL-WN320G 1.0 WLAN Adapter usb:v0B3Bp1601* ID_MODEL_FROM_DATABASE=Allnet 0193 802.11b Adapter usb:v0B3Bp1602* ID_MODEL_FROM_DATABASE=ZyXEL ZyAIR B200 802.11b Adapter usb:v0B3Bp1612* ID_MODEL_FROM_DATABASE=AIR.Mate 2@net 802.11b Adapter usb:v0B3Bp1613* ID_MODEL_FROM_DATABASE=802.11b Wireless LAN Adapter usb:v0B3Bp1620* ID_MODEL_FROM_DATABASE=Allnet Wireless Network Adapter [Envara WiND512] usb:v0B3Bp1630* ID_MODEL_FROM_DATABASE=QuickWLAN 802.11bg usb:v0B3Bp5630* ID_MODEL_FROM_DATABASE=802.11bg usb:v0B3Bp6630* ID_MODEL_FROM_DATABASE=ZD1211 usb:v0B3C* ID_VENDOR_FROM_DATABASE=Olivetti Techcenter usb:v0B3CpA010* ID_MODEL_FROM_DATABASE=Simple_Way Printer/Scanner/Copier usb:v0B3CpC000* ID_MODEL_FROM_DATABASE=Olicard 100 usb:v0B3CpC700* ID_MODEL_FROM_DATABASE=Olicard 100 (Mass Storage mode) usb:v0B3E* ID_VENDOR_FROM_DATABASE=Kikusui Electronics Corp. usb:v0B41* ID_VENDOR_FROM_DATABASE=Hal Corp. usb:v0B41p0011* ID_MODEL_FROM_DATABASE=Crossam2+USB IR commander usb:v0B43* ID_VENDOR_FROM_DATABASE=Play.com, Inc. usb:v0B43p0003* ID_MODEL_FROM_DATABASE=PS2 Controller Converter usb:v0B43p0005* ID_MODEL_FROM_DATABASE=GameCube Adaptor usb:v0B47* ID_VENDOR_FROM_DATABASE=Sportbug.com, Inc. usb:v0B48* ID_VENDOR_FROM_DATABASE=TechnoTrend AG usb:v0B48p1003* ID_MODEL_FROM_DATABASE=Technotrend/Hauppauge USB-Nova usb:v0B48p1004* ID_MODEL_FROM_DATABASE=TT-PCline usb:v0B48p1005* ID_MODEL_FROM_DATABASE=Technotrend/Hauppauge USB-Nova usb:v0B48p1006* ID_MODEL_FROM_DATABASE=Technotrend/Hauppauge DEC3000-s usb:v0B48p1007* ID_MODEL_FROM_DATABASE=TT-micro plus Device usb:v0B48p1008* ID_MODEL_FROM_DATABASE=Technotrend/Hauppauge DEC2000-t usb:v0B48p1009* ID_MODEL_FROM_DATABASE=Technotrend/Hauppauge DEC2540-t usb:v0B48p3001* ID_MODEL_FROM_DATABASE=DVB-S receiver usb:v0B48p3002* ID_MODEL_FROM_DATABASE=DVB-C receiver usb:v0B48p3003* ID_MODEL_FROM_DATABASE=DVB-T receiver usb:v0B48p3004* ID_MODEL_FROM_DATABASE=TT TV-Stick usb:v0B48p3005* ID_MODEL_FROM_DATABASE=TT TV-Stick (8kB EEPROM) usb:v0B48p3006* ID_MODEL_FROM_DATABASE=TT-connect S-2400 DVB-S receiver usb:v0B48p3007* ID_MODEL_FROM_DATABASE=TT-connect S2-3600 usb:v0B48p3008* ID_MODEL_FROM_DATABASE=TT-connect usb:v0B48p3009* ID_MODEL_FROM_DATABASE=TT-connect S-2400 DVB-S receiver (8kB EEPROM) usb:v0B48p300A* ID_MODEL_FROM_DATABASE=TT-connect S2-3650 CI usb:v0B48p300B* ID_MODEL_FROM_DATABASE=TT-connect C-3650 CI usb:v0B48p300C* ID_MODEL_FROM_DATABASE=TT-connect T-3650 CI usb:v0B48p300D* ID_MODEL_FROM_DATABASE=TT-connect CT-3650 CI usb:v0B48p300E* ID_MODEL_FROM_DATABASE=TT-connect C-2400 usb:v0B48p3011* ID_MODEL_FROM_DATABASE=TT-connect S2-4600 usb:v0B48p3012* ID_MODEL_FROM_DATABASE=TT-connect CT2-4650 CI usb:v0B48p3014* ID_MODEL_FROM_DATABASE=TT-TVStick CT2-4400 usb:v0B49* ID_VENDOR_FROM_DATABASE=ASCII Corp. usb:v0B49p064F* ID_MODEL_FROM_DATABASE=Trance Vibrator usb:v0B4B* ID_VENDOR_FROM_DATABASE=Pine Corp. Ltd. usb:v0B4Bp0100* ID_MODEL_FROM_DATABASE=D'music MP3 Player usb:v0B4D* ID_VENDOR_FROM_DATABASE=Graphtec America, Inc. usb:v0B4Dp110A* ID_MODEL_FROM_DATABASE=Graphtec CC200-20 usb:v0B4E* ID_VENDOR_FROM_DATABASE=Musical Electronics, Ltd usb:v0B4Ep6500* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0B4Ep8028* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0B4Ep8920* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0B50* ID_VENDOR_FROM_DATABASE=Dumpries Co., Ltd usb:v0B51* ID_VENDOR_FROM_DATABASE=Comfort Keyboard Co. usb:v0B51p0020* ID_MODEL_FROM_DATABASE=Comfort Keyboard usb:v0B52* ID_VENDOR_FROM_DATABASE=Colorado MicroDisplay, Inc. usb:v0B54* ID_VENDOR_FROM_DATABASE=Sinbon Electronics Co., Ltd usb:v0B56* ID_VENDOR_FROM_DATABASE=TYI Systems, Ltd usb:v0B57* ID_VENDOR_FROM_DATABASE=Beijing HanwangTechnology Co., Ltd usb:v0B59* ID_VENDOR_FROM_DATABASE=Lake Communications, Ltd usb:v0B5A* ID_VENDOR_FROM_DATABASE=Corel Corp. usb:v0B5F* ID_VENDOR_FROM_DATABASE=Green Electronics Co., Ltd usb:v0B60* ID_VENDOR_FROM_DATABASE=Nsine, Ltd usb:v0B61* ID_VENDOR_FROM_DATABASE=NEC Viewtechnology, Ltd usb:v0B62* ID_VENDOR_FROM_DATABASE=Orange Micro, Inc. usb:v0B62p000B* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0B62p0059* ID_MODEL_FROM_DATABASE=iBOT2 Webcam usb:v0B63* ID_VENDOR_FROM_DATABASE=ADLink Technology, Inc. usb:v0B64* ID_VENDOR_FROM_DATABASE=Wonderful Wire Cable Co., Ltd usb:v0B65* ID_VENDOR_FROM_DATABASE=Expert Magnetics Corp. usb:v0B66* ID_VENDOR_FROM_DATABASE=Cybiko Inc. usb:v0B66p0041* ID_MODEL_FROM_DATABASE=Xtreme usb:v0B67* ID_VENDOR_FROM_DATABASE=Fairbanks Scales usb:v0B67p555E* ID_MODEL_FROM_DATABASE=SCB-R9000 usb:v0B69* ID_VENDOR_FROM_DATABASE=CacheVision usb:v0B6A* ID_VENDOR_FROM_DATABASE=Maxim Integrated Products usb:v0B6ApA132* ID_MODEL_FROM_DATABASE=WUP-005 [Nintendo Wii U Pro Controller] usb:v0B6F* ID_VENDOR_FROM_DATABASE=Nagano Japan Radio Co., Ltd usb:v0B70* ID_VENDOR_FROM_DATABASE=PortalPlayer, Inc. usb:v0B70p00BA* ID_MODEL_FROM_DATABASE=iRiver H10 20GB usb:v0B71* ID_VENDOR_FROM_DATABASE=SHIN-EI Sangyo Co., Ltd usb:v0B72* ID_VENDOR_FROM_DATABASE=Embedded Wireless Technology Co., Ltd usb:v0B73* ID_VENDOR_FROM_DATABASE=Computone Corp. usb:v0B75* ID_VENDOR_FROM_DATABASE=Roland DG Corp. usb:v0B79* ID_VENDOR_FROM_DATABASE=Sunrise Telecom, Inc. usb:v0B7A* ID_VENDOR_FROM_DATABASE=Zeevo, Inc. usb:v0B7Ap07D0* ID_MODEL_FROM_DATABASE=Bluetooth Dongle usb:v0B7B* ID_VENDOR_FROM_DATABASE=Taiko Denki Co., Ltd usb:v0B7C* ID_VENDOR_FROM_DATABASE=ITRAN Communications, Ltd usb:v0B7D* ID_VENDOR_FROM_DATABASE=Astrodesign, Inc. usb:v0B81* ID_VENDOR_FROM_DATABASE=id3 Technologies usb:v0B81p0001* ID_MODEL_FROM_DATABASE=Biothentic II smartcard reader with fingerprint sensor usb:v0B81p0002* ID_MODEL_FROM_DATABASE=DFU-Enabled Devices (DFU) usb:v0B81p0012* ID_MODEL_FROM_DATABASE=BioPAD biometric module (DFU + CDC) usb:v0B81p0102* ID_MODEL_FROM_DATABASE=Certis V1 fingerprint reader usb:v0B81p0103* ID_MODEL_FROM_DATABASE=Certis V2 fingerprint reader usb:v0B81p0200* ID_MODEL_FROM_DATABASE=CL1356T / CL1356T5 / CL1356A smartcard readers (CCID) usb:v0B81p0201* ID_MODEL_FROM_DATABASE=CL1356T / CL1356T5 / CL1356A smartcard readers (DFU + CCID) usb:v0B81p0220* ID_MODEL_FROM_DATABASE=CL1356A FFPJP smartcard reader (CCID + HID) usb:v0B81p0221* ID_MODEL_FROM_DATABASE=CL1356A smartcard reader (DFU + CCID + HID) usb:v0B84* ID_VENDOR_FROM_DATABASE=Rextron Technology, Inc. usb:v0B85* ID_VENDOR_FROM_DATABASE=Elkat Electronics, Sdn., Bhd. usb:v0B86* ID_VENDOR_FROM_DATABASE=Exputer Systems, Inc. usb:v0B86p5100* ID_MODEL_FROM_DATABASE=XMC5100 Zippy Drive usb:v0B86p5110* ID_MODEL_FROM_DATABASE=XMC5110 Flash Drive usb:v0B86p5200* ID_MODEL_FROM_DATABASE=XMC5200 Zippy Drive usb:v0B86p5201* ID_MODEL_FROM_DATABASE=XMC5200 Zippy Drive usb:v0B86p5202* ID_MODEL_FROM_DATABASE=XMC5200 Zippy Drive usb:v0B86p5280* ID_MODEL_FROM_DATABASE=XMC5280 Storage Drive usb:v0B86pFFF0* ID_MODEL_FROM_DATABASE=ISP5200 Debugger usb:v0B87* ID_VENDOR_FROM_DATABASE=Plus-One I & T, Inc. usb:v0B88* ID_VENDOR_FROM_DATABASE=Sigma Koki Co., Ltd, Technology Center usb:v0B89* ID_VENDOR_FROM_DATABASE=Advanced Digital Broadcast, Ltd usb:v0B8C* ID_VENDOR_FROM_DATABASE=SMART Technologies Inc. usb:v0B8Cp0001* ID_MODEL_FROM_DATABASE=Interactive Whiteboard Controller (SB6) (HID) usb:v0B8Cp00C3* ID_MODEL_FROM_DATABASE=Sympodium ID350 usb:v0B95* ID_VENDOR_FROM_DATABASE=ASIX Electronics Corp. usb:v0B95p1720* ID_MODEL_FROM_DATABASE=10/100 Ethernet usb:v0B95p1780* ID_MODEL_FROM_DATABASE=AX88178 usb:v0B95p1790* ID_MODEL_FROM_DATABASE=AX88179 Gigabit Ethernet usb:v0B95p7720* ID_MODEL_FROM_DATABASE=AX88772 usb:v0B95p772A* ID_MODEL_FROM_DATABASE=AX88772A Fast Ethernet usb:v0B95p772B* ID_MODEL_FROM_DATABASE=AX88772B usb:v0B95p7E2B* ID_MODEL_FROM_DATABASE=AX88772B usb:v0B96* ID_VENDOR_FROM_DATABASE=Sewon Telecom usb:v0B97* ID_VENDOR_FROM_DATABASE=O2 Micro, Inc. usb:v0B97p7732* ID_MODEL_FROM_DATABASE=Smart Card Reader usb:v0B97p7761* ID_MODEL_FROM_DATABASE=Oz776 1.1 Hub usb:v0B97p7762* ID_MODEL_FROM_DATABASE=Oz776 SmartCard Reader usb:v0B97p7772* ID_MODEL_FROM_DATABASE=OZ776 CCID Smartcard Reader usb:v0B98* ID_VENDOR_FROM_DATABASE=Playmates Toys, Inc. usb:v0B99* ID_VENDOR_FROM_DATABASE=Audio International, Inc. usb:v0B9B* ID_VENDOR_FROM_DATABASE=Dipl.-Ing. Stefan Kunde usb:v0B9Bp4012* ID_MODEL_FROM_DATABASE=Reflex RC-controller Interface usb:v0B9D* ID_VENDOR_FROM_DATABASE=Softprotec Co. usb:v0B9F* ID_VENDOR_FROM_DATABASE=Chippo Technologies usb:v0BAF* ID_VENDOR_FROM_DATABASE=U.S. Robotics usb:v0BAFp00E5* ID_MODEL_FROM_DATABASE=USR6000 usb:v0BAFp00EB* ID_MODEL_FROM_DATABASE=USR1120 802.11b Adapter usb:v0BAFp00EC* ID_MODEL_FROM_DATABASE=56K Faxmodem usb:v0BAFp00F1* ID_MODEL_FROM_DATABASE=SureConnect ADSL ATM Adapter usb:v0BAFp00F2* ID_MODEL_FROM_DATABASE=SureConnect ADSL Loader usb:v0BAFp00F5* ID_MODEL_FROM_DATABASE=SureConnect ADSL ATM Adapter usb:v0BAFp00F6* ID_MODEL_FROM_DATABASE=SureConnect ADSL Loader usb:v0BAFp00F7* ID_MODEL_FROM_DATABASE=SureConnect ADSL ATM Adapter usb:v0BAFp00F8* ID_MODEL_FROM_DATABASE=SureConnect ADSL Loader usb:v0BAFp00F9* ID_MODEL_FROM_DATABASE=SureConnect ADSL ATM Adapter usb:v0BAFp00FA* ID_MODEL_FROM_DATABASE=SureConnect ADSL Loader usb:v0BAFp00FB* ID_MODEL_FROM_DATABASE=SureConnect ADSL Ethernet/USB Router usb:v0BAFp0111* ID_MODEL_FROM_DATABASE=USR5420 802.11g Adapter [Broadcom 4320 USB] usb:v0BAFp0118* ID_MODEL_FROM_DATABASE=U5 802.11g Adapter usb:v0BAFp011B* ID_MODEL_FROM_DATABASE=Wireless MAXg Adapter [Broadcom 4320] usb:v0BAFp0121* ID_MODEL_FROM_DATABASE=USR5423 802.11bg Wireless Adapter [ZyDAS ZD1211B] usb:v0BAFp0303* ID_MODEL_FROM_DATABASE=USR5637 56K Faxmodem usb:v0BAFp6112* ID_MODEL_FROM_DATABASE=FaxModem Model 5633 usb:v0BB0* ID_VENDOR_FROM_DATABASE=Concord Camera Corp. usb:v0BB0p0100* ID_MODEL_FROM_DATABASE=Sound Vision Stream usb:v0BB0p5007* ID_MODEL_FROM_DATABASE=3340z/Rollei DC3100 usb:v0BB1* ID_VENDOR_FROM_DATABASE=Infinilink Corp. usb:v0BB2* ID_VENDOR_FROM_DATABASE=Ambit Microsystems Corp. usb:v0BB2p0302* ID_MODEL_FROM_DATABASE=U10H010 802.11b Wireless Adapter [Intersil PRISM 3] usb:v0BB2p6098* ID_MODEL_FROM_DATABASE=USB Cable Modem usb:v0BB3* ID_VENDOR_FROM_DATABASE=Ofuji Technology usb:v0BB4* ID_VENDOR_FROM_DATABASE=HTC (High Tech Computer Corp.) usb:v0BB4p0001* ID_MODEL_FROM_DATABASE=Android Phone via mass storage [Wiko Cink Peax 2] usb:v0BB4p00CE* ID_MODEL_FROM_DATABASE=mmO2 XDA GSM/GPRS Pocket PC usb:v0BB4p00CF* ID_MODEL_FROM_DATABASE=SPV C500 Smart Phone usb:v0BB4p0A01* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A02* ID_MODEL_FROM_DATABASE=Himalaya GSM/GPRS Pocket PC usb:v0BB4p0A03* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A04* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A05* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A06* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A07* ID_MODEL_FROM_DATABASE=Magician PocketPC SmartPhone / O2 XDA usb:v0BB4p0A08* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A09* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A0A* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A0B* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A0C* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A0D* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A0E* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A0F* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A10* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A11* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A12* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A13* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A14* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A15* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A16* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A17* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A18* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A19* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A1A* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A1B* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A1C* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A1D* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A1E* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A1F* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A20* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A21* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A22* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A23* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A24* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A25* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A26* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A27* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A28* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A29* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A2A* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A2B* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A2C* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A2D* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A2E* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A2F* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A30* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A31* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A32* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A33* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A34* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A35* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A36* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A37* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A38* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A39* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A3A* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A3B* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A3C* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A3D* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A3E* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A3F* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A40* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A41* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A42* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A43* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A44* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A45* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A46* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A47* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A48* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A49* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A4A* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A4B* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A4C* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A4D* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A4E* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A4F* ID_MODEL_FROM_DATABASE=PocketPC Sync usb:v0BB4p0A50* ID_MODEL_FROM_DATABASE=SmartPhone (MTP) usb:v0BB4p0A51* ID_MODEL_FROM_DATABASE=SPV C400 / T-Mobile SDA GSM/GPRS Pocket PC usb:v0BB4p0A52* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A53* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A54* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A55* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A56* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A57* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A58* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A59* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A5A* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A5B* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A5C* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A5D* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A5E* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A5F* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A60* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A61* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A62* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A63* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A64* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A65* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A66* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A67* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A68* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A69* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A6A* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A6B* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A6C* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A6D* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A6E* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A6F* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A70* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A71* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A72* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A73* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A74* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A75* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A76* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A77* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A78* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A79* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A7A* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A7B* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A7C* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A7D* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A7E* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A7F* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A80* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A81* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A82* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A83* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A84* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A85* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A86* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A87* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A88* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A89* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A8A* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A8B* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A8C* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A8D* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A8E* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A8F* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A90* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A91* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A92* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A93* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A94* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A95* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A96* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A97* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A98* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A99* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A9A* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A9B* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A9C* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A9D* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A9E* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0A9F* ID_MODEL_FROM_DATABASE=SmartPhone Sync usb:v0BB4p0B03* ID_MODEL_FROM_DATABASE=Ozone Mobile Broadband usb:v0BB4p0B04* ID_MODEL_FROM_DATABASE=Hermes / TyTN / T-Mobile MDA Vario II / O2 Xda Trion usb:v0BB4p0B05* ID_MODEL_FROM_DATABASE=P3600 usb:v0BB4p0B06* ID_MODEL_FROM_DATABASE=Athena / Advantage x7500 / Dopod U1000 / T-Mobile AMEO usb:v0BB4p0B0C* ID_MODEL_FROM_DATABASE=Elf / Touch / P3450 / T-Mobile MDA Touch / O2 Xda Nova / Dopod S1 usb:v0BB4p0B1F* ID_MODEL_FROM_DATABASE=Sony Ericsson XPERIA X1 usb:v0BB4p0B2F* ID_MODEL_FROM_DATABASE=Rhodium usb:v0BB4p0B51* ID_MODEL_FROM_DATABASE=Qtek 8310 mobile phone [Tornado Noble] usb:v0BB4p0BCE* ID_MODEL_FROM_DATABASE=Vario MDA usb:v0BB4p0C01* ID_MODEL_FROM_DATABASE=Dream / ADP1 / G1 / Magic / Tattoo usb:v0BB4p0C02* ID_MODEL_FROM_DATABASE=Dream / ADP1 / G1 / Magic / Tattoo (Debug) usb:v0BB4p0C03* ID_MODEL_FROM_DATABASE=Android Phone [Fairphone First Edition (FP1)] usb:v0BB4p0C13* ID_MODEL_FROM_DATABASE=Diamond usb:v0BB4p0C1F* ID_MODEL_FROM_DATABASE=Sony Ericsson XPERIA X1 usb:v0BB4p0C5F* ID_MODEL_FROM_DATABASE=Snap usb:v0BB4p0C86* ID_MODEL_FROM_DATABASE=Sensation usb:v0BB4p0C87* ID_MODEL_FROM_DATABASE=Desire (debug) usb:v0BB4p0C8D* ID_MODEL_FROM_DATABASE=EVO 4G (debug) usb:v0BB4p0C91* ID_MODEL_FROM_DATABASE=Vision usb:v0BB4p0C94* ID_MODEL_FROM_DATABASE=Vision usb:v0BB4p0C97* ID_MODEL_FROM_DATABASE=Legend usb:v0BB4p0C99* ID_MODEL_FROM_DATABASE=Desire (debug) usb:v0BB4p0C9E* ID_MODEL_FROM_DATABASE=Incredible usb:v0BB4p0CA2* ID_MODEL_FROM_DATABASE=Desire HD (debug mode) usb:v0BB4p0CA5* ID_MODEL_FROM_DATABASE=Android Phone [Evo Shift 4G] usb:v0BB4p0CAE* ID_MODEL_FROM_DATABASE=T-Mobile MyTouch 4G Slide [Doubleshot] usb:v0BB4p0DEA* ID_MODEL_FROM_DATABASE=M7_UL [HTC One] usb:v0BB4p0F25* ID_MODEL_FROM_DATABASE=One M8 usb:v0BB4p0F64* ID_MODEL_FROM_DATABASE=Desire 601 usb:v0BB4p0FF8* ID_MODEL_FROM_DATABASE=Desire HD (Tethering Mode) usb:v0BB4p0FF9* ID_MODEL_FROM_DATABASE=Desire / Desire HD / Hero / Thunderbolt (Charge Mode) usb:v0BB4p0FFE* ID_MODEL_FROM_DATABASE=Desire HD (modem mode) usb:v0BB4p0FFF* ID_MODEL_FROM_DATABASE=Android Fastboot Bootloader usb:v0BB4p2008* ID_MODEL_FROM_DATABASE=Android Phone via MTP [Wiko Cink Peax 2] usb:v0BB4p200B* ID_MODEL_FROM_DATABASE=Android Phone via PTP [Wiko Cink Peax 2] usb:v0BB5* ID_VENDOR_FROM_DATABASE=Murata Manufacturing Co., Ltd usb:v0BB6* ID_VENDOR_FROM_DATABASE=Network Alchemy usb:v0BB7* ID_VENDOR_FROM_DATABASE=Joytech Computer Co., Ltd usb:v0BB8* ID_VENDOR_FROM_DATABASE=Hitachi Semiconductor and Devices Sales Co., Ltd usb:v0BB9* ID_VENDOR_FROM_DATABASE=Eiger M&C Co., Ltd usb:v0BBA* ID_VENDOR_FROM_DATABASE=ZAccess Systems usb:v0BBB* ID_VENDOR_FROM_DATABASE=General Meters Corp. usb:v0BBC* ID_VENDOR_FROM_DATABASE=Assistive Technology, Inc. usb:v0BBD* ID_VENDOR_FROM_DATABASE=System Connection, Inc. usb:v0BC0* ID_VENDOR_FROM_DATABASE=Knilink Technology, Inc. usb:v0BC1* ID_VENDOR_FROM_DATABASE=Fuw Yng Electronics Co., Ltd usb:v0BC2* ID_VENDOR_FROM_DATABASE=Seagate RSS LLC usb:v0BC2p0502* ID_MODEL_FROM_DATABASE=ST3300601CB-RK 300 GB External Hard Drive usb:v0BC2p0503* ID_MODEL_FROM_DATABASE=ST3250824A [Barracuda 7200.9] usb:v0BC2p2000* ID_MODEL_FROM_DATABASE=Storage Adapter V3 (TPP) usb:v0BC2p2100* ID_MODEL_FROM_DATABASE=FreeAgent Go usb:v0BC2p2200* ID_MODEL_FROM_DATABASE=FreeAgent Go FW usb:v0BC2p2300* ID_MODEL_FROM_DATABASE=Expansion Portable usb:v0BC2p2320* ID_MODEL_FROM_DATABASE=USB 3.0 bridge [Portable Expansion Drive] usb:v0BC2p2321* ID_MODEL_FROM_DATABASE=Expansion Portable usb:v0BC2p2340* ID_MODEL_FROM_DATABASE=FreeAgent External Hard Drive usb:v0BC2p3000* ID_MODEL_FROM_DATABASE=FreeAgent Desktop usb:v0BC2p3008* ID_MODEL_FROM_DATABASE=FreeAgent Desk 1TB usb:v0BC2p3101* ID_MODEL_FROM_DATABASE=FreeAgent XTreme 640GB usb:v0BC2p3312* ID_MODEL_FROM_DATABASE=SRD00F2 Expansion Desktop Drive (STBV) usb:v0BC2p3320* ID_MODEL_FROM_DATABASE=SRD00F2 [Expansion Desktop Drive] usb:v0BC2p3332* ID_MODEL_FROM_DATABASE=Expansion usb:v0BC2p5020* ID_MODEL_FROM_DATABASE=FreeAgent GoFlex usb:v0BC2p5021* ID_MODEL_FROM_DATABASE=FreeAgent GoFlex USB 2.0 usb:v0BC2p5030* ID_MODEL_FROM_DATABASE=FreeAgent GoFlex Upgrade Cable STAE104 usb:v0BC2p5031* ID_MODEL_FROM_DATABASE=FreeAgent GoFlex USB 3.0 usb:v0BC2p5070* ID_MODEL_FROM_DATABASE=FreeAgent GoFlex Desk usb:v0BC2p5071* ID_MODEL_FROM_DATABASE=FreeAgent GoFlex Desk usb:v0BC2p50A1* ID_MODEL_FROM_DATABASE=FreeAgent GoFlex Desk usb:v0BC2p50A5* ID_MODEL_FROM_DATABASE=FreeAgent GoFlex Desk USB 3.0 usb:v0BC2p5121* ID_MODEL_FROM_DATABASE=FreeAgent GoFlex usb:v0BC2p5161* ID_MODEL_FROM_DATABASE=FreeAgent GoFlex dock usb:v0BC2pA003* ID_MODEL_FROM_DATABASE=Backup Plus usb:v0BC2pA0A1* ID_MODEL_FROM_DATABASE=Backup Plus Desktop usb:v0BC2pA0A4* ID_MODEL_FROM_DATABASE=Backup Plus Desktop Drive usb:v0BC2pAB00* ID_MODEL_FROM_DATABASE=Slim Portable Drive usb:v0BC2pAB20* ID_MODEL_FROM_DATABASE=Backup Plus Portable Drive usb:v0BC2pAB21* ID_MODEL_FROM_DATABASE=Backup Plus Slim usb:v0BC2pAB31* ID_MODEL_FROM_DATABASE=Backup Plus Desktop Drive (5TB) usb:v0BC3* ID_VENDOR_FROM_DATABASE=IPWireless, Inc. usb:v0BC3p0001* ID_MODEL_FROM_DATABASE=UMTS-TDD (TD-CDMA) modem usb:v0BC4* ID_VENDOR_FROM_DATABASE=Microcube Corp. usb:v0BC5* ID_VENDOR_FROM_DATABASE=JCN Co., Ltd usb:v0BC6* ID_VENDOR_FROM_DATABASE=ExWAY, Inc. usb:v0BC7* ID_VENDOR_FROM_DATABASE=X10 Wireless Technology, Inc. usb:v0BC7p0001* ID_MODEL_FROM_DATABASE=ActiveHome (ACPI-compliant) usb:v0BC7p0002* ID_MODEL_FROM_DATABASE=Firecracker Interface (ACPI-compliant) usb:v0BC7p0003* ID_MODEL_FROM_DATABASE=VGA Video Sender (ACPI-compliant) usb:v0BC7p0004* ID_MODEL_FROM_DATABASE=X10 Receiver usb:v0BC7p0005* ID_MODEL_FROM_DATABASE=Wireless Transceiver (ACPI-compliant) usb:v0BC7p0006* ID_MODEL_FROM_DATABASE=Wireless Transceiver (ACPI-compliant) usb:v0BC7p0007* ID_MODEL_FROM_DATABASE=Wireless Transceiver (ACPI-compliant) usb:v0BC7p0008* ID_MODEL_FROM_DATABASE=Wireless Transceiver (ACPI-compliant) usb:v0BC7p0009* ID_MODEL_FROM_DATABASE=Wireless Transceiver (ACPI-compliant) usb:v0BC7p000A* ID_MODEL_FROM_DATABASE=Wireless Transceiver (ACPI-compliant) usb:v0BC7p000B* ID_MODEL_FROM_DATABASE=Transceiver (ACPI-compliant) usb:v0BC7p000C* ID_MODEL_FROM_DATABASE=Transceiver (ACPI-compliant) usb:v0BC7p000D* ID_MODEL_FROM_DATABASE=Transceiver (ACPI-compliant) usb:v0BC7p000E* ID_MODEL_FROM_DATABASE=Transceiver (ACPI-compliant) usb:v0BC7p000F* ID_MODEL_FROM_DATABASE=Transceiver (ACPI-compliant) usb:v0BC8* ID_VENDOR_FROM_DATABASE=Telmax Communications usb:v0BC9* ID_VENDOR_FROM_DATABASE=ECI Telecom, Ltd usb:v0BCA* ID_VENDOR_FROM_DATABASE=Startek Engineering, Inc. usb:v0BCB* ID_VENDOR_FROM_DATABASE=Perfect Technic Enterprise Co., Ltd usb:v0BD7* ID_VENDOR_FROM_DATABASE=Andrew Pargeter & Associates usb:v0BD7pA021* ID_MODEL_FROM_DATABASE=Amptek DP4 multichannel signal analyzer usb:v0BDA* ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Corp. usb:v0BDAp0103* ID_MODEL_FROM_DATABASE=USB 2.0 Card Reader usb:v0BDAp0104* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0106* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0107* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0108* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0111* ID_MODEL_FROM_DATABASE=RTS5111 Card Reader Controller usb:v0BDAp0113* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0115* ID_MODEL_FROM_DATABASE=Mass Storage Device (Multicard Reader) usb:v0BDAp0116* ID_MODEL_FROM_DATABASE=RTS5116 Card Reader Controller usb:v0BDAp0117* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0118* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0119* ID_MODEL_FROM_DATABASE=Storage Device (SD card reader) usb:v0BDAp0129* ID_MODEL_FROM_DATABASE=RTS5129 Card Reader Controller usb:v0BDAp0138* ID_MODEL_FROM_DATABASE=RTS5138 Card Reader Controller usb:v0BDAp0139* ID_MODEL_FROM_DATABASE=RTS5139 Card Reader Controller usb:v0BDAp0151* ID_MODEL_FROM_DATABASE=Mass Storage Device (Multicard Reader) usb:v0BDAp0152* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0153* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0156* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0157* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0158* ID_MODEL_FROM_DATABASE=USB 2.0 multicard reader usb:v0BDAp0159* ID_MODEL_FROM_DATABASE=RTS5159 Card Reader Controller usb:v0BDAp0161* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0168* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0169* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0171* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0176* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0178* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0179* ID_MODEL_FROM_DATABASE=RTL8188ETV Wireless LAN 802.11n Network Adapter usb:v0BDAp0184* ID_MODEL_FROM_DATABASE=RTS5182 Card Reader usb:v0BDAp0186* ID_MODEL_FROM_DATABASE=Card Reader usb:v0BDAp0301* ID_MODEL_FROM_DATABASE=multicard reader usb:v0BDAp1724* ID_MODEL_FROM_DATABASE=RTL8723AU 802.11n WLAN Adapter usb:v0BDAp2831* ID_MODEL_FROM_DATABASE=RTL2831U DVB-T usb:v0BDAp2832* ID_MODEL_FROM_DATABASE=RTL2832U DVB-T usb:v0BDAp2838* ID_MODEL_FROM_DATABASE=RTL2838 DVB-T usb:v0BDAp5401* ID_MODEL_FROM_DATABASE=RTL 8153 USB 3.0 hub with gigabit ethernet usb:v0BDAp5730* ID_MODEL_FROM_DATABASE=HP 2.0MP High Definition Webcam usb:v0BDAp5775* ID_MODEL_FROM_DATABASE=HP "Truevision HD" laptop camera usb:v0BDAp8150* ID_MODEL_FROM_DATABASE=RTL8150 Fast Ethernet Adapter usb:v0BDAp8151* ID_MODEL_FROM_DATABASE=RTL8151 Adapteon Business Mobile Networks BV usb:v0BDAp8171* ID_MODEL_FROM_DATABASE=RTL8188SU 802.11n WLAN Adapter usb:v0BDAp8172* ID_MODEL_FROM_DATABASE=RTL8191SU 802.11n WLAN Adapter usb:v0BDAp8174* ID_MODEL_FROM_DATABASE=RTL8192SU 802.11n WLAN Adapter usb:v0BDAp8176* ID_MODEL_FROM_DATABASE=RTL8188CUS 802.11n WLAN Adapter usb:v0BDAp8178* ID_MODEL_FROM_DATABASE=RTL8192CU 802.11n WLAN Adapter usb:v0BDAp8179* ID_MODEL_FROM_DATABASE=RTL8188EUS 802.11n Wireless Network Adapter usb:v0BDAp817F* ID_MODEL_FROM_DATABASE=RTL8188RU 802.11n WLAN Adapter usb:v0BDAp8187* ID_MODEL_FROM_DATABASE=RTL8187 Wireless Adapter usb:v0BDAp8189* ID_MODEL_FROM_DATABASE=RTL8187B Wireless 802.11g 54Mbps Network Adapter usb:v0BDAp8192* ID_MODEL_FROM_DATABASE=RTL8191SU 802.11n Wireless Adapter usb:v0BDAp8193* ID_MODEL_FROM_DATABASE=RTL8192DU 802.11an WLAN Adapter usb:v0BDAp8197* ID_MODEL_FROM_DATABASE=RTL8187B Wireless Adapter usb:v0BDAp8198* ID_MODEL_FROM_DATABASE=RTL8187B Wireless Adapter usb:v0BDAp8199* ID_MODEL_FROM_DATABASE=RTL8187SU 802.11g WLAN Adapter usb:v0BDAp8812* ID_MODEL_FROM_DATABASE=RTL8812AU 802.11a/b/g/n/ac WLAN Adapter usb:v0BDB* ID_VENDOR_FROM_DATABASE=Ericsson Business Mobile Networks BV usb:v0BDBp1000* ID_MODEL_FROM_DATABASE=BV Bluetooth Device usb:v0BDBp1002* ID_MODEL_FROM_DATABASE=Bluetooth Device 1.2 usb:v0BDBp1049* ID_MODEL_FROM_DATABASE=C3607w Mobile Broadband Module usb:v0BDBp1900* ID_MODEL_FROM_DATABASE=F3507g Mobile Broadband Module usb:v0BDBp1902* ID_MODEL_FROM_DATABASE=F3507g v2 Mobile Broadband Module usb:v0BDBp1904* ID_MODEL_FROM_DATABASE=F3607gw Mobile Broadband Module usb:v0BDBp1905* ID_MODEL_FROM_DATABASE=F3607gw v2 Mobile Broadband Module usb:v0BDBp1906* ID_MODEL_FROM_DATABASE=F3607gw v3 Mobile Broadband Module usb:v0BDBp1909* ID_MODEL_FROM_DATABASE=F3307 v2 Mobile Broadband Module usb:v0BDBp190A* ID_MODEL_FROM_DATABASE=F3307 Mobile Broadband Module usb:v0BDBp190B* ID_MODEL_FROM_DATABASE=C3607w v2 Mobile Broadband Module usb:v0BDC* ID_VENDOR_FROM_DATABASE=Y Media Corp. usb:v0BDD* ID_VENDOR_FROM_DATABASE=Orange PCS usb:v0BE2* ID_VENDOR_FROM_DATABASE=Kanda Tsushin Kogyo Co., Ltd usb:v0BE3* ID_VENDOR_FROM_DATABASE=TOYO Corp. usb:v0BE4* ID_VENDOR_FROM_DATABASE=Elka International, Ltd usb:v0BE5* ID_VENDOR_FROM_DATABASE=DOME imaging systems, Inc. usb:v0BE6* ID_VENDOR_FROM_DATABASE=Dong Guan Humen Wonderful Wire Cable Factory usb:v0BED* ID_VENDOR_FROM_DATABASE=MEI usb:v0BEDp1100* ID_MODEL_FROM_DATABASE=CASHFLOW SC usb:v0BEDp1101* ID_MODEL_FROM_DATABASE=Series 2000 Combo Acceptor usb:v0BEE* ID_VENDOR_FROM_DATABASE=LTK Industries, Ltd usb:v0BEF* ID_VENDOR_FROM_DATABASE=Way2Call Communications usb:v0BF0* ID_VENDOR_FROM_DATABASE=Pace Micro Technology PLC usb:v0BF1* ID_VENDOR_FROM_DATABASE=Intracom S.A. usb:v0BF1p0001* ID_MODEL_FROM_DATABASE=netMod Driver Ver 2.4.17 (CAPI) usb:v0BF1p0002* ID_MODEL_FROM_DATABASE=netMod Driver Ver 2.4 (CAPI) usb:v0BF1p0003* ID_MODEL_FROM_DATABASE=netMod Driver Ver 2.4 (CAPI) usb:v0BF2* ID_VENDOR_FROM_DATABASE=Konexx usb:v0BF6* ID_VENDOR_FROM_DATABASE=Addonics Technologies, Inc. usb:v0BF6p0103* ID_MODEL_FROM_DATABASE=Storage Device usb:v0BF6p1234* ID_MODEL_FROM_DATABASE=Storage Device usb:v0BF6pA000* ID_MODEL_FROM_DATABASE=Cable 205 (TPP) usb:v0BF6pA001* ID_MODEL_FROM_DATABASE=Cable 205 usb:v0BF6pA002* ID_MODEL_FROM_DATABASE=IDE Bridge usb:v0BF7* ID_VENDOR_FROM_DATABASE=Sunny Giken, Inc. usb:v0BF8* ID_VENDOR_FROM_DATABASE=Fujitsu Siemens Computers usb:v0BF8p1001* ID_MODEL_FROM_DATABASE=Fujitsu Pocket Loox 600 PDA usb:v0BF8p1006* ID_MODEL_FROM_DATABASE=SmartCard Reader 2A usb:v0BF8p1007* ID_MODEL_FROM_DATABASE=Connect2Air E-5400 802.11g Wireless Adapter usb:v0BF8p1009* ID_MODEL_FROM_DATABASE=Connect2Air E-5400 D1700 802.11g Wireless Adapter [Intersil ISL3887] usb:v0BF8p100C* ID_MODEL_FROM_DATABASE=Keyboard FSC KBPC PX usb:v0BF8p100F* ID_MODEL_FROM_DATABASE=miniCard D2301 802.11bg Wireless Module [SiS 163U] usb:v0BF8p1017* ID_MODEL_FROM_DATABASE=Keyboard KB SCR usb:v0BFD* ID_VENDOR_FROM_DATABASE=Kvaser AB usb:v0BFDp0004* ID_MODEL_FROM_DATABASE=USBcan II usb:v0BFDp000B* ID_MODEL_FROM_DATABASE=Leaf Light HS usb:v0BFDp000E* ID_MODEL_FROM_DATABASE=Leaf SemiPro HS usb:v0C04* ID_VENDOR_FROM_DATABASE=MOTO Development Group, Inc. usb:v0C05* ID_VENDOR_FROM_DATABASE=Appian Graphics usb:v0C06* ID_VENDOR_FROM_DATABASE=Hasbro Games, Inc. usb:v0C07* ID_VENDOR_FROM_DATABASE=Infinite Data Storage, Ltd usb:v0C08* ID_VENDOR_FROM_DATABASE=Agate usb:v0C08p0378* ID_MODEL_FROM_DATABASE=Q 16MB Storage Device usb:v0C09* ID_VENDOR_FROM_DATABASE=Comjet Information System usb:v0C09pA5A5* ID_MODEL_FROM_DATABASE=Litto Version USB2.0 usb:v0C0A* ID_VENDOR_FROM_DATABASE=Highpoint Technologies, Inc. usb:v0C0B* ID_VENDOR_FROM_DATABASE=Dura Micro, Inc. (Acomdata) usb:v0C0Bp27CB* ID_MODEL_FROM_DATABASE=6-in-1 Flash Reader and Writer usb:v0C0Bp27D7* ID_MODEL_FROM_DATABASE=Multi Memory reader/writer MD-005 usb:v0C0Bp27DA* ID_MODEL_FROM_DATABASE=Multi Memory reader/writer MD-005 usb:v0C0Bp27DC* ID_MODEL_FROM_DATABASE=Multi Memory reader/writer MD-005 usb:v0C0Bp27E7* ID_MODEL_FROM_DATABASE=3,5'' HDD case MD-231 usb:v0C0Bp27EE* ID_MODEL_FROM_DATABASE=3,5'' HDD case MD-231 usb:v0C0Bp2814* ID_MODEL_FROM_DATABASE=3,5'' HDD case MD-231 usb:v0C0Bp2815* ID_MODEL_FROM_DATABASE=3,5'' HDD case MD-231 usb:v0C0Bp281D* ID_MODEL_FROM_DATABASE=3,5'' HDD case MD-231 usb:v0C0Bp5FAB* ID_MODEL_FROM_DATABASE=Storage Adaptor usb:v0C0BpA109* ID_MODEL_FROM_DATABASE=CF/SM Reader and Writer usb:v0C0BpA10C* ID_MODEL_FROM_DATABASE=SD/MS Reader and Writer usb:v0C0BpB001* ID_MODEL_FROM_DATABASE=USB 2.0 Mass Storage IDE adapter usb:v0C0BpB004* ID_MODEL_FROM_DATABASE=MMC/SD Reader and Writer usb:v0C12* ID_VENDOR_FROM_DATABASE=Zeroplus usb:v0C12p0005* ID_MODEL_FROM_DATABASE=PSX Vibration Feedback Converter usb:v0C12p0030* ID_MODEL_FROM_DATABASE=PSX Vibration Feedback Converter usb:v0C12p700E* ID_MODEL_FROM_DATABASE=Logic Analyzer (LAP-C-16032) usb:v0C12p8801* ID_MODEL_FROM_DATABASE=Xbox Controller usb:v0C12p8802* ID_MODEL_FROM_DATABASE=Xbox Controller usb:v0C12p8809* ID_MODEL_FROM_DATABASE=Red Octane Ignition Xbox DDR Pad usb:v0C12p880A* ID_MODEL_FROM_DATABASE=Pelican Eclipse PL-2023 usb:v0C12p8810* ID_MODEL_FROM_DATABASE=Xbox Controller usb:v0C12p9902* ID_MODEL_FROM_DATABASE=VibraX usb:v0C15* ID_VENDOR_FROM_DATABASE=Iris Graphics usb:v0C16* ID_VENDOR_FROM_DATABASE=Gyration, Inc. usb:v0C16p0002* ID_MODEL_FROM_DATABASE=RF Technology Receiver usb:v0C16p0003* ID_MODEL_FROM_DATABASE=RF Technology Receiver usb:v0C16p0008* ID_MODEL_FROM_DATABASE=RF Technology Receiver usb:v0C16p0080* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v0C16p0081* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v0C17* ID_VENDOR_FROM_DATABASE=Cyberboard A/S usb:v0C18* ID_VENDOR_FROM_DATABASE=SynerTek Korea, Inc. usb:v0C19* ID_VENDOR_FROM_DATABASE=cyberPIXIE, Inc. usb:v0C1A* ID_VENDOR_FROM_DATABASE=Silicon Motion, Inc. usb:v0C1B* ID_VENDOR_FROM_DATABASE=MIPS Technologies usb:v0C1C* ID_VENDOR_FROM_DATABASE=Hang Zhou Silan Electronics Co., Ltd usb:v0C22* ID_VENDOR_FROM_DATABASE=Tally Printer Corp. usb:v0C23* ID_VENDOR_FROM_DATABASE=Lernout + Hauspie usb:v0C24* ID_VENDOR_FROM_DATABASE=Taiyo Yuden usb:v0C24p0001* ID_MODEL_FROM_DATABASE=Bluetooth Adaptor usb:v0C24p0002* ID_MODEL_FROM_DATABASE=Bluetooth Device2 usb:v0C24p0005* ID_MODEL_FROM_DATABASE=Bluetooth Device(BC04-External) usb:v0C24p000B* ID_MODEL_FROM_DATABASE=Bluetooth Device(BC04-External) usb:v0C24p000C* ID_MODEL_FROM_DATABASE=Bluetooth Adaptor usb:v0C24p000E* ID_MODEL_FROM_DATABASE=Bluetooth Device(BC04-External) usb:v0C24p000F* ID_MODEL_FROM_DATABASE=Bluetooth Device (V2.0+EDR) usb:v0C24p0010* ID_MODEL_FROM_DATABASE=Bluetooth Device(BC04-External) usb:v0C24p0012* ID_MODEL_FROM_DATABASE=Bluetooth Device(BC04-External) usb:v0C24p0018* ID_MODEL_FROM_DATABASE=Bluetooth Device(BC04-External) usb:v0C24p0019* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0C24p0021* ID_MODEL_FROM_DATABASE=Bluetooth Device (V2.1+EDR) usb:v0C24p0C24* ID_MODEL_FROM_DATABASE=Bluetooth Device(SAMPLE) usb:v0C24pFFFF* ID_MODEL_FROM_DATABASE=Bluetooth module with BlueCore in DFU mode usb:v0C25* ID_VENDOR_FROM_DATABASE=Sampo Corp. usb:v0C25p0310* ID_MODEL_FROM_DATABASE=Scream Cam usb:v0C26* ID_VENDOR_FROM_DATABASE=Prolific Technology Inc. usb:v0C26p0018* ID_MODEL_FROM_DATABASE=USB-Serial Controller [Icom Inc. OPC-478UC] usb:v0C27* ID_VENDOR_FROM_DATABASE=RFIDeas, Inc usb:v0C27p3BFA* ID_MODEL_FROM_DATABASE=pcProx Card Reader usb:v0C2E* ID_VENDOR_FROM_DATABASE=Metrologic Instruments usb:v0C2Ep0007* ID_MODEL_FROM_DATABASE=Metrologic MS7120 Barcode Scanner (IBM SurePOS mode) usb:v0C2Ep0200* ID_MODEL_FROM_DATABASE=MS7120 Barcode Scanner usb:v0C2Ep0204* ID_MODEL_FROM_DATABASE=Metrologic MS7120 Barcode Scanner (keyboard mode) usb:v0C2Ep0206* ID_MODEL_FROM_DATABASE=Metrologic MS4980 Barcode Scanner usb:v0C2Ep0700* ID_MODEL_FROM_DATABASE=Metrologic MS7120 Barcode Scanner (uni-directional serial mode) usb:v0C2Ep0720* ID_MODEL_FROM_DATABASE=Metrologic MS7120 Barcode Scanner (bi-directional serial mode) usb:v0C2Ep0B61* ID_MODEL_FROM_DATABASE=Vuquest 3310g usb:v0C2Ep0B6A* ID_MODEL_FROM_DATABASE=Vuquest 3310 Area-Imaging Scanner usb:v0C2Ep0B81* ID_MODEL_FROM_DATABASE=Barcode scanner Voyager 1400g Series usb:v0C35* ID_VENDOR_FROM_DATABASE=Eagletron, Inc. usb:v0C36* ID_VENDOR_FROM_DATABASE=E Ink Corp. usb:v0C37* ID_VENDOR_FROM_DATABASE=e.Digital usb:v0C38* ID_VENDOR_FROM_DATABASE=Der An Electric Wire & Cable Co., Ltd usb:v0C39* ID_VENDOR_FROM_DATABASE=IFR usb:v0C3A* ID_VENDOR_FROM_DATABASE=Furui Precise Component (Kunshan) Co., Ltd usb:v0C3B* ID_VENDOR_FROM_DATABASE=Komatsu, Ltd usb:v0C3C* ID_VENDOR_FROM_DATABASE=Radius Co., Ltd usb:v0C3D* ID_VENDOR_FROM_DATABASE=Innocom, Inc. usb:v0C3E* ID_VENDOR_FROM_DATABASE=Nextcell, Inc. usb:v0C44* ID_VENDOR_FROM_DATABASE=Motorola iDEN usb:v0C44p0021* ID_MODEL_FROM_DATABASE=iDEN P2k0 Device usb:v0C44p0022* ID_MODEL_FROM_DATABASE=iDEN P2k1 Device usb:v0C44p03A2* ID_MODEL_FROM_DATABASE=iDEN Smartphone usb:v0C44p41D9* ID_MODEL_FROM_DATABASE=i1 phone usb:v0C45* ID_VENDOR_FROM_DATABASE=Microdia usb:v0C45p0011* ID_MODEL_FROM_DATABASE=EBUDDY usb:v0C45p0520* ID_MODEL_FROM_DATABASE=MaxTrack Wireless Mouse usb:v0C45p1018* ID_MODEL_FROM_DATABASE=Compact Flash storage memory card reader usb:v0C45p1020* ID_MODEL_FROM_DATABASE=Mass Storage Reader usb:v0C45p1028* ID_MODEL_FROM_DATABASE=Mass Storage Reader usb:v0C45p1030* ID_MODEL_FROM_DATABASE=Mass Storage Reader usb:v0C45p1031* ID_MODEL_FROM_DATABASE=Sonix Mass Storage Device usb:v0C45p1032* ID_MODEL_FROM_DATABASE=Mass Storage Reader usb:v0C45p1033* ID_MODEL_FROM_DATABASE=Sonix Mass Storage Device usb:v0C45p1034* ID_MODEL_FROM_DATABASE=Mass Storage Reader usb:v0C45p1035* ID_MODEL_FROM_DATABASE=Mass Storage Reader usb:v0C45p1036* ID_MODEL_FROM_DATABASE=Mass Storage Reader usb:v0C45p1037* ID_MODEL_FROM_DATABASE=Sonix Mass Storage Device usb:v0C45p1050* ID_MODEL_FROM_DATABASE=CF Card Reader usb:v0C45p1058* ID_MODEL_FROM_DATABASE=HDD Reader usb:v0C45p1060* ID_MODEL_FROM_DATABASE=iFlash SM-Direct Card Reader usb:v0C45p1061* ID_MODEL_FROM_DATABASE=Mass Storage Reader usb:v0C45p1062* ID_MODEL_FROM_DATABASE=Mass Storage Reader usb:v0C45p1063* ID_MODEL_FROM_DATABASE=Sonix Mass Storage Device usb:v0C45p1064* ID_MODEL_FROM_DATABASE=Mass Storage Reader usb:v0C45p1065* ID_MODEL_FROM_DATABASE=Mass Storage Reader usb:v0C45p1066* ID_MODEL_FROM_DATABASE=Mass Storage Reader usb:v0C45p1067* ID_MODEL_FROM_DATABASE=Mass Storage Reader usb:v0C45p1158* ID_MODEL_FROM_DATABASE=A56AK usb:v0C45p184C* ID_MODEL_FROM_DATABASE=VoIP Phone usb:v0C45p6001* ID_MODEL_FROM_DATABASE=Genius VideoCAM NB usb:v0C45p6005* ID_MODEL_FROM_DATABASE=Sweex Mini Webcam usb:v0C45p6007* ID_MODEL_FROM_DATABASE=VideoCAM Eye usb:v0C45p6009* ID_MODEL_FROM_DATABASE=VideoCAM ExpressII usb:v0C45p600D* ID_MODEL_FROM_DATABASE=TwinkleCam USB camera usb:v0C45p6011* ID_MODEL_FROM_DATABASE=PC Camera (SN9C102) usb:v0C45p6019* ID_MODEL_FROM_DATABASE=PC Camera (SN9C102) usb:v0C45p6024* ID_MODEL_FROM_DATABASE=VideoCAM ExpressII usb:v0C45p6025* ID_MODEL_FROM_DATABASE=VideoCAM ExpressII usb:v0C45p6028* ID_MODEL_FROM_DATABASE=Typhoon Easycam USB 330K (older) usb:v0C45p6029* ID_MODEL_FROM_DATABASE=Triplex i-mini PC Camera usb:v0C45p602A* ID_MODEL_FROM_DATABASE=Meade ETX-105EC Camera usb:v0C45p602B* ID_MODEL_FROM_DATABASE=VideoCAM NB 300 usb:v0C45p602C* ID_MODEL_FROM_DATABASE=Clas Ohlson TWC-30XOP Webcam usb:v0C45p602D* ID_MODEL_FROM_DATABASE=VideoCAM ExpressII usb:v0C45p602E* ID_MODEL_FROM_DATABASE=VideoCAM Messenger usb:v0C45p6030* ID_MODEL_FROM_DATABASE=VideoCAM ExpressII usb:v0C45p603F* ID_MODEL_FROM_DATABASE=VideoCAM ExpressII usb:v0C45p6040* ID_MODEL_FROM_DATABASE=CCD PC Camera (PC390A) usb:v0C45p606A* ID_MODEL_FROM_DATABASE=CCD PC Camera (PC390A) usb:v0C45p607A* ID_MODEL_FROM_DATABASE=CCD PC Camera (PC390A) usb:v0C45p607B* ID_MODEL_FROM_DATABASE=Win2 PC Camera usb:v0C45p607C* ID_MODEL_FROM_DATABASE=CCD PC Camera (PC390A) usb:v0C45p607E* ID_MODEL_FROM_DATABASE=CCD PC Camera (PC390A) usb:v0C45p6080* ID_MODEL_FROM_DATABASE=Audio (Microphone) usb:v0C45p6082* ID_MODEL_FROM_DATABASE=VideoCAM Look usb:v0C45p6083* ID_MODEL_FROM_DATABASE=VideoCAM Look usb:v0C45p608C* ID_MODEL_FROM_DATABASE=VideoCAM Look usb:v0C45p608E* ID_MODEL_FROM_DATABASE=VideoCAM Look usb:v0C45p608F* ID_MODEL_FROM_DATABASE=PC Camera (SN9C103 + OV7630) usb:v0C45p60A8* ID_MODEL_FROM_DATABASE=VideoCAM Look usb:v0C45p60AA* ID_MODEL_FROM_DATABASE=VideoCAM Look usb:v0C45p60AB* ID_MODEL_FROM_DATABASE=PC Camera usb:v0C45p60AF* ID_MODEL_FROM_DATABASE=VideoCAM Look usb:v0C45p60B0* ID_MODEL_FROM_DATABASE=Genius VideoCam Look usb:v0C45p60C0* ID_MODEL_FROM_DATABASE=PC Camera with Mic (SN9C105) usb:v0C45p60C8* ID_MODEL_FROM_DATABASE=Win2 PC Camera usb:v0C45p60CC* ID_MODEL_FROM_DATABASE=PC Camera with Mic (SN9C105) usb:v0C45p60EC* ID_MODEL_FROM_DATABASE=PC Camera with Mic (SN9C105) usb:v0C45p60EF* ID_MODEL_FROM_DATABASE=Win2 PC Camera usb:v0C45p60FA* ID_MODEL_FROM_DATABASE=PC Camera with Mic (SN9C105) usb:v0C45p60FB* ID_MODEL_FROM_DATABASE=Composite Device usb:v0C45p60FC* ID_MODEL_FROM_DATABASE=PC Camera with Mic (SN9C105) usb:v0C45p60FE* ID_MODEL_FROM_DATABASE=Audio (Microphone) usb:v0C45p6108* ID_MODEL_FROM_DATABASE=Win2 PC Camera usb:v0C45p6122* ID_MODEL_FROM_DATABASE=PC Camera (SN9C110) usb:v0C45p6123* ID_MODEL_FROM_DATABASE=PC Camera (SN9C110) usb:v0C45p6128* ID_MODEL_FROM_DATABASE=PC Camera (SN9C325 + OM6802) usb:v0C45p612A* ID_MODEL_FROM_DATABASE=PC Camera (SN9C325) usb:v0C45p612C* ID_MODEL_FROM_DATABASE=PC Camera (SN9C110) usb:v0C45p612E* ID_MODEL_FROM_DATABASE=PC Camera (SN9C110) usb:v0C45p612F* ID_MODEL_FROM_DATABASE=PC Camera (SN9C110) usb:v0C45p6130* ID_MODEL_FROM_DATABASE=PC Camera (SN9C120) usb:v0C45p6138* ID_MODEL_FROM_DATABASE=Win2 PC Camera usb:v0C45p613A* ID_MODEL_FROM_DATABASE=PC Camera (SN9C120) usb:v0C45p613B* ID_MODEL_FROM_DATABASE=Win2 PC Camera usb:v0C45p613C* ID_MODEL_FROM_DATABASE=PC Camera (SN9C120) usb:v0C45p613E* ID_MODEL_FROM_DATABASE=PC Camera (SN9C120) usb:v0C45p6143* ID_MODEL_FROM_DATABASE=PC Camera (SN9C120 + SP80708) usb:v0C45p6240* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + MI1300) usb:v0C45p6242* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + MI1310) usb:v0C45p6243* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + S5K4AAFX) usb:v0C45p6248* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV9655) usb:v0C45p624B* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + CX1332) usb:v0C45p624C* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + MI1320) usb:v0C45p624E* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + SOI968) usb:v0C45p624F* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV9650) usb:v0C45p6251* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV9650) usb:v0C45p6253* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV9650) usb:v0C45p6260* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV7670ISP) usb:v0C45p6262* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OM6802) usb:v0C45p6270* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + MI0360/MT9V011 or MI0360SOC/MT9V111) U-CAM PC Camera NE878, Whitcom WHC017, ... usb:v0C45p627A* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + S5K53BEB) usb:v0C45p627B* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV7660) usb:v0C45p627C* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + HV7131R) usb:v0C45p627F* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV965x + EEPROM) usb:v0C45p6280* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + MI1300) usb:v0C45p6282* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + MI1310) usb:v0C45p6283* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + S5K4AAFX) usb:v0C45p6288* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OV9655) usb:v0C45p628A* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + ICM107) usb:v0C45p628B* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + CX1332) usb:v0C45p628C* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + MI1320) usb:v0C45p628E* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + SOI968) usb:v0C45p628F* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OV9650) usb:v0C45p62A0* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OV7670ISP) usb:v0C45p62A2* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OM6802) usb:v0C45p62B0* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + MI0360/MT9V011 or MI0360SOC/MT9V111) usb:v0C45p62B3* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OV9655) usb:v0C45p62BA* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + S5K53BEB) usb:v0C45p62BB* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OV7660) usb:v0C45p62BC* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + HV7131R) usb:v0C45p62BE* ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OV7663) usb:v0C45p62C0* ID_MODEL_FROM_DATABASE=Sonix USB 2.0 Camera usb:v0C45p62E0* ID_MODEL_FROM_DATABASE=MSI Starcam Racer usb:v0C45p6300* ID_MODEL_FROM_DATABASE=PC Microscope camera usb:v0C45p6310* ID_MODEL_FROM_DATABASE=Sonix USB 2.0 Camera usb:v0C45p6340* ID_MODEL_FROM_DATABASE=Camera usb:v0C45p6341* ID_MODEL_FROM_DATABASE=Defender G-Lens 2577 HD720p Camera usb:v0C45p63E0* ID_MODEL_FROM_DATABASE=Sonix Integrated Webcam usb:v0C45p63F1* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v0C45p63F8* ID_MODEL_FROM_DATABASE=Sonix Integrated Webcam usb:v0C45p6409* ID_MODEL_FROM_DATABASE=Webcam usb:v0C45p6413* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v0C45p6417* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v0C45p6419* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v0C45p641D* ID_MODEL_FROM_DATABASE=1.3 MPixel Integrated Webcam usb:v0C45p643F* ID_MODEL_FROM_DATABASE=Dell Integrated HD Webcam usb:v0C45p644D* ID_MODEL_FROM_DATABASE=1.3 MPixel Integrated Webcam usb:v0C45p6480* ID_MODEL_FROM_DATABASE=Sonix 1.3 MP Laptop Integrated Webcam usb:v0C45p648B* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v0C45p64BD* ID_MODEL_FROM_DATABASE=Sony Visual Communication Camera usb:v0C45p7401* ID_MODEL_FROM_DATABASE=TEMPer Temperature Sensor usb:v0C45p7402* ID_MODEL_FROM_DATABASE=TEMPerHUM Temperature & Humidity Sensor usb:v0C45p7403* ID_MODEL_FROM_DATABASE=Foot Switch usb:v0C45p8000* ID_MODEL_FROM_DATABASE=DC31VC usb:v0C45p8006* ID_MODEL_FROM_DATABASE=Dual Mode Camera (8006 VGA) usb:v0C45p800A* ID_MODEL_FROM_DATABASE=Vivitar Vivicam3350B usb:v0C46* ID_VENDOR_FROM_DATABASE=WaveRider Communications, Inc. usb:v0C4A* ID_VENDOR_FROM_DATABASE=ALGE-TIMING GmbH usb:v0C4Ap0889* ID_MODEL_FROM_DATABASE=Timy usb:v0C4Ap088A* ID_MODEL_FROM_DATABASE=Timy 2 usb:v0C4B* ID_VENDOR_FROM_DATABASE=Reiner SCT Kartensysteme GmbH usb:v0C4Bp0100* ID_MODEL_FROM_DATABASE=cyberJack e-com/pinpad usb:v0C4Bp0300* ID_MODEL_FROM_DATABASE=cyberJack pinpad(a) usb:v0C4Bp0400* ID_MODEL_FROM_DATABASE=cyberJack e-com(a) usb:v0C4Bp0401* ID_MODEL_FROM_DATABASE=cyberJack pinpad(a2) usb:v0C4Bp0500* ID_MODEL_FROM_DATABASE=cyberJack RFID standard dual interface smartcard reader usb:v0C4Bp0501* ID_MODEL_FROM_DATABASE=cyberJack RFID comfort dual interface smartcard reader usb:v0C4Bp0502* ID_MODEL_FROM_DATABASE=cyberJack compact usb:v0C4Bp0504* ID_MODEL_FROM_DATABASE=cyberJack go / go plus usb:v0C4Bp0505* ID_MODEL_FROM_DATABASE=cyberJack wave usb:v0C4Bp9102* ID_MODEL_FROM_DATABASE=cyberJack RFID basis contactless smartcard reader usb:v0C4C* ID_VENDOR_FROM_DATABASE=Needham's Electronics usb:v0C4Cp0021* ID_MODEL_FROM_DATABASE=EMP-21 Universal Programmer usb:v0C52* ID_VENDOR_FROM_DATABASE=Sealevel Systems, Inc. usb:v0C52p2101* ID_MODEL_FROM_DATABASE=SeaLINK+232 usb:v0C52p2102* ID_MODEL_FROM_DATABASE=SeaLINK+485 usb:v0C52p2103* ID_MODEL_FROM_DATABASE=SeaLINK+232I usb:v0C52p2104* ID_MODEL_FROM_DATABASE=SeaLINK+485I usb:v0C52p2211* ID_MODEL_FROM_DATABASE=SeaPORT+2/232 (Port 1) usb:v0C52p2212* ID_MODEL_FROM_DATABASE=SeaPORT+2/485 (Port 1) usb:v0C52p2213* ID_MODEL_FROM_DATABASE=SeaPORT+2 (Port 1) usb:v0C52p2221* ID_MODEL_FROM_DATABASE=SeaPORT+2/232 (Port 2) usb:v0C52p2222* ID_MODEL_FROM_DATABASE=SeaPORT+2/485 (Port 2) usb:v0C52p2223* ID_MODEL_FROM_DATABASE=SeaPORT+2 (Port 2) usb:v0C52p2411* ID_MODEL_FROM_DATABASE=SeaPORT+4/232 (Port 1) usb:v0C52p2412* ID_MODEL_FROM_DATABASE=SeaPORT+4/485 (Port 1) usb:v0C52p2413* ID_MODEL_FROM_DATABASE=SeaPORT+4 (Port 1) usb:v0C52p2421* ID_MODEL_FROM_DATABASE=SeaPORT+4/232 (Port 2) usb:v0C52p2422* ID_MODEL_FROM_DATABASE=SeaPORT+4/485 (Port 2) usb:v0C52p2423* ID_MODEL_FROM_DATABASE=SeaPORT+4 (Port 2) usb:v0C52p2431* ID_MODEL_FROM_DATABASE=SeaPORT+4/232 (Port 3) usb:v0C52p2432* ID_MODEL_FROM_DATABASE=SeaPORT+4/485 (Port 3) usb:v0C52p2433* ID_MODEL_FROM_DATABASE=SeaPORT+4 (Port 3) usb:v0C52p2441* ID_MODEL_FROM_DATABASE=SeaPORT+4/232 (Port 4) usb:v0C52p2442* ID_MODEL_FROM_DATABASE=SeaPORT+4/485 (Port 4) usb:v0C52p2443* ID_MODEL_FROM_DATABASE=SeaPORT+4 (Port 4) usb:v0C52p2811* ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 1) usb:v0C52p2812* ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 1) usb:v0C52p2813* ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 1) usb:v0C52p2821* ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 2) usb:v0C52p2822* ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 2) usb:v0C52p2823* ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 2) usb:v0C52p2831* ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 3) usb:v0C52p2832* ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 3) usb:v0C52p2833* ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 3) usb:v0C52p2841* ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 4) usb:v0C52p2842* ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 4) usb:v0C52p2843* ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 4) usb:v0C52p2851* ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 5) usb:v0C52p2852* ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 5) usb:v0C52p2853* ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 5) usb:v0C52p2861* ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 6) usb:v0C52p2862* ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 6) usb:v0C52p2863* ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 6) usb:v0C52p2871* ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 7) usb:v0C52p2872* ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 7) usb:v0C52p2873* ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 7) usb:v0C52p2881* ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 8) usb:v0C52p2882* ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 8) usb:v0C52p2883* ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 8) usb:v0C52p9020* ID_MODEL_FROM_DATABASE=SeaLINK+422 usb:v0C52pA02A* ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 1+2) usb:v0C52pA02B* ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 3+4) usb:v0C52pA02C* ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 5+6) usb:v0C52pA02D* ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 7+8) usb:v0C53* ID_VENDOR_FROM_DATABASE=ViewPLUS, Inc. usb:v0C54* ID_VENDOR_FROM_DATABASE=Glory, Ltd usb:v0C55* ID_VENDOR_FROM_DATABASE=Spectrum Digital, Inc. usb:v0C55p0510* ID_MODEL_FROM_DATABASE=Spectrum Digital XDS510 JTAG Debugger usb:v0C55p0540* ID_MODEL_FROM_DATABASE=SPI540 usb:v0C55p5416* ID_MODEL_FROM_DATABASE=TMS320C5416 DSK usb:v0C55p6416* ID_MODEL_FROM_DATABASE=TMS320C6416 DDB usb:v0C56* ID_VENDOR_FROM_DATABASE=Billion Bright, Ltd usb:v0C57* ID_VENDOR_FROM_DATABASE=Imaginative Design Operation Co., Ltd usb:v0C58* ID_VENDOR_FROM_DATABASE=Vidar Systems Corp. usb:v0C59* ID_VENDOR_FROM_DATABASE=Dong Guan Shinko Wire Co., Ltd usb:v0C5A* ID_VENDOR_FROM_DATABASE=TRS International Mfg., Inc. usb:v0C5E* ID_VENDOR_FROM_DATABASE=Xytronix Research & Design usb:v0C60* ID_VENDOR_FROM_DATABASE=Apogee Electronics Corp. usb:v0C60p0001* ID_MODEL_FROM_DATABASE=MiniMe usb:v0C60p0002* ID_MODEL_FROM_DATABASE=MiniDAC usb:v0C60p0003* ID_MODEL_FROM_DATABASE=ONE usb:v0C60p0004* ID_MODEL_FROM_DATABASE=GiO usb:v0C60p0007* ID_MODEL_FROM_DATABASE=Duet usb:v0C60p0009* ID_MODEL_FROM_DATABASE=Jam usb:v0C60p000A* ID_MODEL_FROM_DATABASE=Jam Bootloader usb:v0C60p000B* ID_MODEL_FROM_DATABASE=MiC usb:v0C60p000C* ID_MODEL_FROM_DATABASE=MiC Bootloader usb:v0C60p8007* ID_MODEL_FROM_DATABASE=Duet DFU Mode usb:v0C62* ID_VENDOR_FROM_DATABASE=Chant Sincere Co., Ltd usb:v0C63* ID_VENDOR_FROM_DATABASE=Toko, Inc. usb:v0C64* ID_VENDOR_FROM_DATABASE=Signality System Engineering Co., Ltd usb:v0C65* ID_VENDOR_FROM_DATABASE=Eminence Enterprise Co., Ltd usb:v0C66* ID_VENDOR_FROM_DATABASE=Rexon Electronics Corp. usb:v0C67* ID_VENDOR_FROM_DATABASE=Concept Telecom, Ltd usb:v0C6A* ID_VENDOR_FROM_DATABASE=ACS usb:v0C6Ap0005* ID_MODEL_FROM_DATABASE=Color 320 x 240 LCD Display Terminal with Touchscreen usb:v0C6C* ID_VENDOR_FROM_DATABASE=JETI Technische Instrumente GmbH usb:v0C6Cp04B2* ID_MODEL_FROM_DATABASE=Specbos 1201 usb:v0C70* ID_VENDOR_FROM_DATABASE=MCT Elektronikladen usb:v0C70p0000* ID_MODEL_FROM_DATABASE=USB08 Development board usb:v0C70p0747* ID_MODEL_FROM_DATABASE=Eye Movement Recorder [Visagraph]/[ReadAlyzer] usb:v0C72* ID_VENDOR_FROM_DATABASE=PEAK System usb:v0C72p000C* ID_MODEL_FROM_DATABASE=PCAN-USB usb:v0C72p000D* ID_MODEL_FROM_DATABASE=PCAN Pro usb:v0C74* ID_VENDOR_FROM_DATABASE=Optronic Laboratories Inc. usb:v0C74p0002* ID_MODEL_FROM_DATABASE=OL 700-30 Goniometer usb:v0C76* ID_VENDOR_FROM_DATABASE=JMTek, LLC. usb:v0C76p0001* ID_MODEL_FROM_DATABASE=Mass Storage Controller usb:v0C76p0002* ID_MODEL_FROM_DATABASE=Mass Storage Controller usb:v0C76p0003* ID_MODEL_FROM_DATABASE=USBdisk usb:v0C76p0004* ID_MODEL_FROM_DATABASE=Mass Storage Controller usb:v0C76p0005* ID_MODEL_FROM_DATABASE=Transcend Flash disk usb:v0C76p0006* ID_MODEL_FROM_DATABASE=Transcend JetFlash usb:v0C76p0007* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0C76p1600* ID_MODEL_FROM_DATABASE=Ion Quick Play LP turntable usb:v0C76p1605* ID_MODEL_FROM_DATABASE=SSS Headphone Set usb:v0C76p1607* ID_MODEL_FROM_DATABASE=audio controller usb:v0C77* ID_VENDOR_FROM_DATABASE=Sipix Group, Ltd usb:v0C77p1001* ID_MODEL_FROM_DATABASE=SiPix Web2 usb:v0C77p1002* ID_MODEL_FROM_DATABASE=SiPix SC2100 usb:v0C77p1010* ID_MODEL_FROM_DATABASE=SiPix Snap usb:v0C77p1011* ID_MODEL_FROM_DATABASE=SiPix Blink 2 usb:v0C77p1015* ID_MODEL_FROM_DATABASE=SiPix CAMeleon usb:v0C78* ID_VENDOR_FROM_DATABASE=Detto Corp. usb:v0C79* ID_VENDOR_FROM_DATABASE=NuConnex Technologies Pte., Ltd usb:v0C7A* ID_VENDOR_FROM_DATABASE=Wing-Span Enterprise Co., Ltd usb:v0C86* ID_VENDOR_FROM_DATABASE=NDA Technologies, Inc. usb:v0C88* ID_VENDOR_FROM_DATABASE=Kyocera Wireless Corp. usb:v0C88p0021* ID_MODEL_FROM_DATABASE=Handheld usb:v0C88p17DA* ID_MODEL_FROM_DATABASE=Qualcomm Kyocera CDMA Technologies MSM usb:v0C89* ID_VENDOR_FROM_DATABASE=Honda Tsushin Kogyo Co., Ltd usb:v0C8A* ID_VENDOR_FROM_DATABASE=Pathway Connectivity, Inc. usb:v0C8B* ID_VENDOR_FROM_DATABASE=Wavefly Corp. usb:v0C8C* ID_VENDOR_FROM_DATABASE=Coactive Networks usb:v0C8D* ID_VENDOR_FROM_DATABASE=Tempo usb:v0C8E* ID_VENDOR_FROM_DATABASE=Cesscom Co., Ltd usb:v0C8Ep6000* ID_MODEL_FROM_DATABASE=Luxian Series usb:v0C8F* ID_VENDOR_FROM_DATABASE=Applied Microsystems usb:v0C94* ID_VENDOR_FROM_DATABASE=Cryptera usb:v0C94pA000* ID_MODEL_FROM_DATABASE=EPP 1217 usb:v0C98* ID_VENDOR_FROM_DATABASE=Berkshire Products, Inc. usb:v0C98p1140* ID_MODEL_FROM_DATABASE=USB PC Watchdog usb:v0C99* ID_VENDOR_FROM_DATABASE=Innochips Co., Ltd usb:v0C9A* ID_VENDOR_FROM_DATABASE=Hanwool Robotics Corp. usb:v0C9B* ID_VENDOR_FROM_DATABASE=Jobin Yvon, Inc. usb:v0C9D* ID_VENDOR_FROM_DATABASE=SemTek usb:v0C9Dp0170* ID_MODEL_FROM_DATABASE=3873 Manual Insert card reader usb:v0CA2* ID_VENDOR_FROM_DATABASE=Zyfer usb:v0CA3* ID_VENDOR_FROM_DATABASE=Sega Corp. usb:v0CA4* ID_VENDOR_FROM_DATABASE=ST&T Instrument Corp. usb:v0CA5* ID_VENDOR_FROM_DATABASE=BAE Systems Canada, Inc. usb:v0CA6* ID_VENDOR_FROM_DATABASE=Castles Technology Co., Ltd usb:v0CA6p0010* ID_MODEL_FROM_DATABASE=EZUSB PC/SC Smart Card Reader usb:v0CA6p0050* ID_MODEL_FROM_DATABASE=EZ220PU Reader Controller usb:v0CA6p1077* ID_MODEL_FROM_DATABASE=Bludrive Family Smart Card Reader usb:v0CA6p107E* ID_MODEL_FROM_DATABASE=Reader Controller usb:v0CA6p2010* ID_MODEL_FROM_DATABASE=myPad110 PC/SC Smart Card Reader usb:v0CA6p3050* ID_MODEL_FROM_DATABASE=EZ710 Smart Card Reader usb:v0CA7* ID_VENDOR_FROM_DATABASE=Information Systems Laboratories usb:v0CAD* ID_VENDOR_FROM_DATABASE=Motorola CGISS usb:v0CADp9001* ID_MODEL_FROM_DATABASE=PowerPad Pocket PC Device usb:v0CAE* ID_VENDOR_FROM_DATABASE=Ascom Business Systems, Ltd usb:v0CAF* ID_VENDOR_FROM_DATABASE=Buslink usb:v0CAFp2507* ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller usb:v0CAFp2515* ID_MODEL_FROM_DATABASE=Flash Disk Embedded Hub usb:v0CAFp2516* ID_MODEL_FROM_DATABASE=Flash Disk Security Device usb:v0CAFp2517* ID_MODEL_FROM_DATABASE=Flash Disk Mass Storage Device usb:v0CAFp25C7* ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller usb:v0CAFp3A00* ID_MODEL_FROM_DATABASE=Hard Drive usb:v0CAFp3A20* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0CAFp3ACD* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0CB0* ID_VENDOR_FROM_DATABASE=Flying Pig Systems usb:v0CB1* ID_VENDOR_FROM_DATABASE=Innovonics, Inc. usb:v0CB6* ID_VENDOR_FROM_DATABASE=Celestix Networks, Pte., Ltd usb:v0CB7* ID_VENDOR_FROM_DATABASE=Singatron Enterprise Co., Ltd usb:v0CB8* ID_VENDOR_FROM_DATABASE=Opticis Co., Ltd usb:v0CBA* ID_VENDOR_FROM_DATABASE=Trust Electronic (Shanghai) Co., Ltd usb:v0CBB* ID_VENDOR_FROM_DATABASE=Shanghai Darong Electronics Co., Ltd usb:v0CBC* ID_VENDOR_FROM_DATABASE=Palmax Technology Co., Ltd usb:v0CBCp0101* ID_MODEL_FROM_DATABASE=Pocket PC P6C usb:v0CBCp0201* ID_MODEL_FROM_DATABASE=Personal Digital Assistant usb:v0CBCp0301* ID_MODEL_FROM_DATABASE=Personal Digital Assistant P6M+ usb:v0CBCp0401* ID_MODEL_FROM_DATABASE=Pocket PC usb:v0CBD* ID_VENDOR_FROM_DATABASE=Pentel Co., Ltd (Electronics Equipment Div.) usb:v0CBE* ID_VENDOR_FROM_DATABASE=Keryx Technologies, Inc. usb:v0CBF* ID_VENDOR_FROM_DATABASE=Union Genius Computer Co., Ltd usb:v0CC0* ID_VENDOR_FROM_DATABASE=Kuon Yi Industrial Corp. usb:v0CC1* ID_VENDOR_FROM_DATABASE=Given Imaging, Ltd usb:v0CC2* ID_VENDOR_FROM_DATABASE=Timex Corp. usb:v0CC3* ID_VENDOR_FROM_DATABASE=Rimage Corp. usb:v0CC4* ID_VENDOR_FROM_DATABASE=emsys GmbH usb:v0CC5* ID_VENDOR_FROM_DATABASE=Sendo usb:v0CC6* ID_VENDOR_FROM_DATABASE=Intermagic Corp. usb:v0CC7* ID_VENDOR_FROM_DATABASE=Kontron Medical AG usb:v0CC8* ID_VENDOR_FROM_DATABASE=Technotools Corp. usb:v0CC9* ID_VENDOR_FROM_DATABASE=BroadMAX Technologies, Inc. usb:v0CCA* ID_VENDOR_FROM_DATABASE=Amphenol usb:v0CCB* ID_VENDOR_FROM_DATABASE=SKNet Co., Ltd usb:v0CCC* ID_VENDOR_FROM_DATABASE=Domex Technology Corp. usb:v0CCD* ID_VENDOR_FROM_DATABASE=TerraTec Electronic GmbH usb:v0CCDp0012* ID_MODEL_FROM_DATABASE=PHASE 26 usb:v0CCDp0013* ID_MODEL_FROM_DATABASE=PHASE 26 usb:v0CCDp0014* ID_MODEL_FROM_DATABASE=PHASE 26 usb:v0CCDp0015* ID_MODEL_FROM_DATABASE=Flash Update for TerraTec PHASE 26 usb:v0CCDp0021* ID_MODEL_FROM_DATABASE=Cameo Grabster 200 usb:v0CCDp0023* ID_MODEL_FROM_DATABASE=Mystify Claw usb:v0CCDp0028* ID_MODEL_FROM_DATABASE=Aureon 5.1 MkII usb:v0CCDp0032* ID_MODEL_FROM_DATABASE=MIDI HUBBLE usb:v0CCDp0035* ID_MODEL_FROM_DATABASE=Miditech Play'n Roll usb:v0CCDp0036* ID_MODEL_FROM_DATABASE=Cinergy 250 Audio usb:v0CCDp0037* ID_MODEL_FROM_DATABASE=Cinergy 250 Audio usb:v0CCDp0038* ID_MODEL_FROM_DATABASE=Cinergy T² DVB-T Receiver usb:v0CCDp0039* ID_MODEL_FROM_DATABASE=Grabster AV 400 usb:v0CCDp003B* ID_MODEL_FROM_DATABASE=Cinergy 400 usb:v0CCDp003C* ID_MODEL_FROM_DATABASE=Grabster AV 250 usb:v0CCDp0042* ID_MODEL_FROM_DATABASE=Cinergy Hybrid T XS usb:v0CCDp0043* ID_MODEL_FROM_DATABASE=Cinergy T XS usb:v0CCDp004E* ID_MODEL_FROM_DATABASE=Cinergy T XS usb:v0CCDp004F* ID_MODEL_FROM_DATABASE=Cinergy Analog XS usb:v0CCDp0055* ID_MODEL_FROM_DATABASE=Cinergy T XE (Version 1, AF9005) usb:v0CCDp005C* ID_MODEL_FROM_DATABASE=Cinergy T² usb:v0CCDp0069* ID_MODEL_FROM_DATABASE=Cinergy T XE (Version 2, AF9015) usb:v0CCDp006B* ID_MODEL_FROM_DATABASE=Cinergy HT PVR (EU) usb:v0CCDp0072* ID_MODEL_FROM_DATABASE=Cinergy Hybrid T usb:v0CCDp0077* ID_MODEL_FROM_DATABASE=Aureon Dual USB usb:v0CCDp0078* ID_MODEL_FROM_DATABASE=Cinergy T XXS usb:v0CCDp0086* ID_MODEL_FROM_DATABASE=Cinergy Hybrid XE usb:v0CCDp008E* ID_MODEL_FROM_DATABASE=Cinergy HTC XS usb:v0CCDp0097* ID_MODEL_FROM_DATABASE=Cinergy T RC MKII usb:v0CCDp0099* ID_MODEL_FROM_DATABASE=AfaTech 9015 [Cinergy T Stick Dual] usb:v0CCDp00A5* ID_MODEL_FROM_DATABASE=Cinergy Hybrid Stick usb:v0CCDp00A9* ID_MODEL_FROM_DATABASE=RTL2838 DVB-T COFDM Demodulator [TerraTec Cinergy T Stick Black] usb:v0CCDp00B3* ID_MODEL_FROM_DATABASE=NOXON DAB/DAB+ Stick usb:v0CCDp00E0* ID_MODEL_FROM_DATABASE=NOXON DAB/DAB+ Stick V2 usb:v0CCDp10A7* ID_MODEL_FROM_DATABASE=TerraTec G3 usb:v0CD4* ID_VENDOR_FROM_DATABASE=Bang Olufsen usb:v0CD4p0101* ID_MODEL_FROM_DATABASE=BeolinkPC2 usb:v0CD5* ID_VENDOR_FROM_DATABASE=LabJack Corporation usb:v0CD5p0003* ID_MODEL_FROM_DATABASE=U3 usb:v0CD5p0009* ID_MODEL_FROM_DATABASE=UE9 usb:v0CD7* ID_VENDOR_FROM_DATABASE=NewChip S.r.l. usb:v0CD8* ID_VENDOR_FROM_DATABASE=JS Digitech, Inc. usb:v0CD8p2007* ID_MODEL_FROM_DATABASE=Smart Card Reader/JSTU-9700 usb:v0CD9* ID_VENDOR_FROM_DATABASE=Hitachi Shin Din Cable, Ltd usb:v0CDE* ID_VENDOR_FROM_DATABASE=Z-Com usb:v0CDEp0001* ID_MODEL_FROM_DATABASE=XI-750 802.11b Wireless Adapter [Atmel AT76C503A] usb:v0CDEp0002* ID_MODEL_FROM_DATABASE=XI-725/726 Prism2.5 802.11b Adapter usb:v0CDEp0003* ID_MODEL_FROM_DATABASE=Sagem 802.11b Dongle usb:v0CDEp0004* ID_MODEL_FROM_DATABASE=Sagem 802.11b Dongle usb:v0CDEp0005* ID_MODEL_FROM_DATABASE=XI-735 Prism3 802.11b Adapter usb:v0CDEp0006* ID_MODEL_FROM_DATABASE=XG-300 802.11b Adapter usb:v0CDEp0008* ID_MODEL_FROM_DATABASE=XG-703A 802.11g Wireless Adapter [Intersil ISL3887] usb:v0CDEp0009* ID_MODEL_FROM_DATABASE=(ZD1211)IEEE 802.11b+g Adapter usb:v0CDEp0011* ID_MODEL_FROM_DATABASE=ZD1211 usb:v0CDEp0012* ID_MODEL_FROM_DATABASE=AR5523 usb:v0CDEp0013* ID_MODEL_FROM_DATABASE=AR5523 driver (no firmware) usb:v0CDEp0014* ID_MODEL_FROM_DATABASE=NB 802.11g Wireless LAN Adapter(3887A) usb:v0CDEp0015* ID_MODEL_FROM_DATABASE=XG-705A 802.11g Wireless Adapter [Intersil ISL3887] usb:v0CDEp0016* ID_MODEL_FROM_DATABASE=NB 802.11g Wireless LAN Adapter(3887A) usb:v0CDEp0018* ID_MODEL_FROM_DATABASE=NB 802.11a/b/g Wireless LAN Adapter(3887A) usb:v0CDEp001A* ID_MODEL_FROM_DATABASE=802.11bg usb:v0CDEp001C* ID_MODEL_FROM_DATABASE=802.11b/g Wireless Network Adapter usb:v0CDEp0020* ID_MODEL_FROM_DATABASE=AG-760A 802.11abg Wireless Adapter [ZyDAS ZD1211B] usb:v0CDEp0022* ID_MODEL_FROM_DATABASE=802.11b/g/n Wireless Network Adapter usb:v0CDEp0023* ID_MODEL_FROM_DATABASE=UB81 802.11bgn usb:v0CDEp0025* ID_MODEL_FROM_DATABASE=802.11b/g/n USB Wireless Network Adapter usb:v0CDEp0026* ID_MODEL_FROM_DATABASE=UB82 802.11abgn usb:v0CDEp0027* ID_MODEL_FROM_DATABASE=Sphairon Homelink 1202 802.11n Wireless Adapter [Atheros AR9170] usb:v0CE5* ID_VENDOR_FROM_DATABASE=Validation Technologies International usb:v0CE5p0003* ID_MODEL_FROM_DATABASE=Matrix usb:v0CE9* ID_VENDOR_FROM_DATABASE=Pico Technology usb:v0CE9p1001* ID_MODEL_FROM_DATABASE=PicoScope3000 series PC Oscilloscope usb:v0CE9p1007* ID_MODEL_FROM_DATABASE=PicoScope 2000 series PC Oscilloscope usb:v0CE9p1008* ID_MODEL_FROM_DATABASE=PicoScope 5000 series PC Oscilloscope usb:v0CE9p1009* ID_MODEL_FROM_DATABASE=PicoScope 4000 series PC Oscilloscope usb:v0CE9p100E* ID_MODEL_FROM_DATABASE=PicoScope 6000 series PC Oscilloscope usb:v0CE9p1012* ID_MODEL_FROM_DATABASE=PicoScope 3000A series PC Oscilloscope usb:v0CE9p1016* ID_MODEL_FROM_DATABASE=PicoScope 2000A series PC Oscilloscope usb:v0CE9p1018* ID_MODEL_FROM_DATABASE=PicoScope 4000A series PC Oscilloscope usb:v0CE9p1200* ID_MODEL_FROM_DATABASE=PicoScope 2000 series PC Oscilloscope usb:v0CE9p1201* ID_MODEL_FROM_DATABASE=PicoScope 3000 series PC Oscilloscope usb:v0CE9p1202* ID_MODEL_FROM_DATABASE=PicoScope 4000 series PC Oscilloscope usb:v0CE9p1203* ID_MODEL_FROM_DATABASE=PicoScope 5000 series PC Oscilloscope usb:v0CE9p1204* ID_MODEL_FROM_DATABASE=PicoScope 6000 series PC Oscilloscope usb:v0CE9p1211* ID_MODEL_FROM_DATABASE=PicoScope 3000 series PC Oscilloscope usb:v0CE9p1212* ID_MODEL_FROM_DATABASE=PicoScope 4000 series PC Oscilloscope usb:v0CF1* ID_VENDOR_FROM_DATABASE=e-Conn Electronic Co., Ltd usb:v0CF2* ID_VENDOR_FROM_DATABASE=ENE Technology, Inc. usb:v0CF2p6220* ID_MODEL_FROM_DATABASE=SD Card Reader (SG361) usb:v0CF2p6225* ID_MODEL_FROM_DATABASE=SD card reader (UB6225) usb:v0CF2p6230* ID_MODEL_FROM_DATABASE=SD Card Reader (UB623X) usb:v0CF2p6250* ID_MODEL_FROM_DATABASE=SD card reader (UB6250) usb:v0CF3* ID_VENDOR_FROM_DATABASE=Atheros Communications, Inc. usb:v0CF3p0001* ID_MODEL_FROM_DATABASE=AR5523 usb:v0CF3p0002* ID_MODEL_FROM_DATABASE=AR5523 (no firmware) usb:v0CF3p0003* ID_MODEL_FROM_DATABASE=AR5523 usb:v0CF3p0004* ID_MODEL_FROM_DATABASE=AR5523 (no firmware) usb:v0CF3p0005* ID_MODEL_FROM_DATABASE=AR5523 usb:v0CF3p0006* ID_MODEL_FROM_DATABASE=AR5523 (no firmware) usb:v0CF3p1001* ID_MODEL_FROM_DATABASE=Thomson TG121N [Atheros AR9001U-(2)NG] usb:v0CF3p1002* ID_MODEL_FROM_DATABASE=TP-Link TL-WN821N v2 / TL-WN822N v1 802.11n [Atheros AR9170] usb:v0CF3p1006* ID_MODEL_FROM_DATABASE=TP-Link TL-WN322G v3 / TL-WN422G v2 802.11g [Atheros AR9271] usb:v0CF3p1010* ID_MODEL_FROM_DATABASE=3Com 3CRUSBN275 802.11abgn Wireless Adapter [Atheros AR9170] usb:v0CF3p20FF* ID_MODEL_FROM_DATABASE=AR7010 (no firmware) usb:v0CF3p3000* ID_MODEL_FROM_DATABASE=AR3011 Bluetooth (no firmware) usb:v0CF3p3002* ID_MODEL_FROM_DATABASE=AR3011 Bluetooth usb:v0CF3p3004* ID_MODEL_FROM_DATABASE=AR3012 Bluetooth 4.0 usb:v0CF3p3005* ID_MODEL_FROM_DATABASE=AR3011 Bluetooth usb:v0CF3p3008* ID_MODEL_FROM_DATABASE=Bluetooth (AR3011) usb:v0CF3p7015* ID_MODEL_FROM_DATABASE=TP-Link TL-WN821N v3 / TL-WN822N v2 802.11n [Atheros AR7010+AR9287] usb:v0CF3p9170* ID_MODEL_FROM_DATABASE=AR9170 802.11n usb:v0CF3p9271* ID_MODEL_FROM_DATABASE=AR9271 802.11n usb:v0CF3pB002* ID_MODEL_FROM_DATABASE=Ubiquiti WiFiStation 802.11n [Atheros AR9271] usb:v0CF3pB003* ID_MODEL_FROM_DATABASE=Ubiquiti WiFiStationEXT 802.11n [Atheros AR9271] usb:v0CF4* ID_VENDOR_FROM_DATABASE=Fomtex Corp. usb:v0CF5* ID_VENDOR_FROM_DATABASE=Cellink Co., Ltd usb:v0CF6* ID_VENDOR_FROM_DATABASE=Compucable Corp. usb:v0CF7* ID_VENDOR_FROM_DATABASE=ishoni Networks usb:v0CF8* ID_VENDOR_FROM_DATABASE=Clarisys, Inc. usb:v0CF8p0750* ID_MODEL_FROM_DATABASE=Claritel-i750 - vp usb:v0CF9* ID_VENDOR_FROM_DATABASE=Central System Research Co., Ltd usb:v0CFA* ID_VENDOR_FROM_DATABASE=Inviso, Inc. usb:v0CFC* ID_VENDOR_FROM_DATABASE=Minolta-QMS, Inc. usb:v0CFCp2301* ID_MODEL_FROM_DATABASE=Magicolor 2300 DL usb:v0CFCp2350* ID_MODEL_FROM_DATABASE=Magicolor 2350EN/3300 usb:v0CFCp3100* ID_MODEL_FROM_DATABASE=Magicolor 3100 usb:v0CFCp7300* ID_MODEL_FROM_DATABASE=Magicolor 5450/5550 usb:v0CFF* ID_VENDOR_FROM_DATABASE=SAFA MEDIA Co., Ltd. usb:v0CFFp0320* ID_MODEL_FROM_DATABASE=SR-380N usb:v0D06* ID_VENDOR_FROM_DATABASE=telos EDV Systementwicklung GmbH usb:v0D08* ID_VENDOR_FROM_DATABASE=UTStarcom usb:v0D08p0602* ID_MODEL_FROM_DATABASE=DV007 [serial] usb:v0D08p0603* ID_MODEL_FROM_DATABASE=DV007 [storage] usb:v0D0B* ID_VENDOR_FROM_DATABASE=Contemporary Controls usb:v0D0C* ID_VENDOR_FROM_DATABASE=Astron Electronics Co., Ltd usb:v0D0D* ID_VENDOR_FROM_DATABASE=MKNet Corp. usb:v0D0E* ID_VENDOR_FROM_DATABASE=Hybrid Networks, Inc. usb:v0D0F* ID_VENDOR_FROM_DATABASE=Feng Shin Cable Co., Ltd usb:v0D10* ID_VENDOR_FROM_DATABASE=Elastic Networks usb:v0D10p0001* ID_MODEL_FROM_DATABASE=StormPort (WDM) usb:v0D11* ID_VENDOR_FROM_DATABASE=Maspro Denkoh Corp. usb:v0D12* ID_VENDOR_FROM_DATABASE=Hansol Electronics, Inc. usb:v0D13* ID_VENDOR_FROM_DATABASE=BMF Corp. usb:v0D14* ID_VENDOR_FROM_DATABASE=Array Comm, Inc. usb:v0D15* ID_VENDOR_FROM_DATABASE=OnStream b.v. usb:v0D16* ID_VENDOR_FROM_DATABASE=Hi-Touch Imaging Technologies Co., Ltd usb:v0D16p0001* ID_MODEL_FROM_DATABASE=PhotoShuttle usb:v0D16p0002* ID_MODEL_FROM_DATABASE=Photo Printer 730 series usb:v0D16p0004* ID_MODEL_FROM_DATABASE=Photo Printer 63xPL/PS usb:v0D16p0100* ID_MODEL_FROM_DATABASE=Photo Printer 63xPL/PS usb:v0D16p0102* ID_MODEL_FROM_DATABASE=Photo Printer 64xPS usb:v0D16p0103* ID_MODEL_FROM_DATABASE=Photo Printer 730 series usb:v0D16p0104* ID_MODEL_FROM_DATABASE=Photo Printer 63xPL/PS usb:v0D16p0105* ID_MODEL_FROM_DATABASE=Photo Printer 64xPS usb:v0D16p0200* ID_MODEL_FROM_DATABASE=Photo Printer 64xDL usb:v0D17* ID_VENDOR_FROM_DATABASE=NALTEC, Inc. usb:v0D18* ID_VENDOR_FROM_DATABASE=coaXmedia usb:v0D19* ID_VENDOR_FROM_DATABASE=Hank Connection Industrial Co., Ltd usb:v0D28* ID_VENDOR_FROM_DATABASE=NXP usb:v0D28p0204* ID_MODEL_FROM_DATABASE=LPC1768 usb:v0D32* ID_VENDOR_FROM_DATABASE=Leo Hui Electric Wire & Cable Co., Ltd usb:v0D33* ID_VENDOR_FROM_DATABASE=AirSpeak, Inc. usb:v0D34* ID_VENDOR_FROM_DATABASE=Rearden Steel Technologies usb:v0D35* ID_VENDOR_FROM_DATABASE=Dah Kun Co., Ltd usb:v0D3A* ID_VENDOR_FROM_DATABASE=Posiflex Technologies, Inc. usb:v0D3Ap0206* ID_MODEL_FROM_DATABASE=Series 3xxx Cash Drawer usb:v0D3Ap0207* ID_MODEL_FROM_DATABASE=Series 3xxx Cash Drawer usb:v0D3Ap0500* ID_MODEL_FROM_DATABASE=Magnetic Stripe Reader usb:v0D3C* ID_VENDOR_FROM_DATABASE=Sri Cable Technology, Ltd usb:v0D3D* ID_VENDOR_FROM_DATABASE=Tangtop Technology Co., Ltd usb:v0D3Dp0001* ID_MODEL_FROM_DATABASE=HID Keyboard usb:v0D3Dp0040* ID_MODEL_FROM_DATABASE=PS/2 Adapter usb:v0D3E* ID_VENDOR_FROM_DATABASE=Fitcom, inc. usb:v0D3F* ID_VENDOR_FROM_DATABASE=MTS Systems Corp. usb:v0D40* ID_VENDOR_FROM_DATABASE=Ascor, Inc. usb:v0D41* ID_VENDOR_FROM_DATABASE=Ta Yun Terminals Industrial Co., Ltd usb:v0D42* ID_VENDOR_FROM_DATABASE=Full Der Co., Ltd usb:v0D46* ID_VENDOR_FROM_DATABASE=Kobil Systems GmbH usb:v0D46p2012* ID_MODEL_FROM_DATABASE=KAAN Standard Plus (Smartcard reader) usb:v0D46p3003* ID_MODEL_FROM_DATABASE=mIDentity Light / KAAN SIM III usb:v0D46p4000* ID_MODEL_FROM_DATABASE=mIDentity (mass storage) usb:v0D46p4001* ID_MODEL_FROM_DATABASE=mIDentity Basic/Classic (composite device) usb:v0D46p4081* ID_MODEL_FROM_DATABASE=mIDentity Basic/Classic (installationless) usb:v0D48* ID_VENDOR_FROM_DATABASE=Promethean Limited usb:v0D48p0001* ID_MODEL_FROM_DATABASE=ACTIVboard usb:v0D48p0004* ID_MODEL_FROM_DATABASE=ACTIVboard usb:v0D48p0100* ID_MODEL_FROM_DATABASE=Audio usb:v0D49* ID_VENDOR_FROM_DATABASE=Maxtor usb:v0D49p3000* ID_MODEL_FROM_DATABASE=Drive usb:v0D49p3010* ID_MODEL_FROM_DATABASE=3000LE Drive usb:v0D49p3100* ID_MODEL_FROM_DATABASE=Hi-Speed USB-IDE Bridge Controller usb:v0D49p3200* ID_MODEL_FROM_DATABASE=Personal Storage 3200 usb:v0D49p5000* ID_MODEL_FROM_DATABASE=5000XT Drive usb:v0D49p5010* ID_MODEL_FROM_DATABASE=5000LE Drive usb:v0D49p5020* ID_MODEL_FROM_DATABASE=Mobile Hard Disk Drive usb:v0D49p7000* ID_MODEL_FROM_DATABASE=OneTouch usb:v0D49p7010* ID_MODEL_FROM_DATABASE=OneTouch usb:v0D49p7100* ID_MODEL_FROM_DATABASE=OneTouch II 300GB External Hard Disk usb:v0D49p7310* ID_MODEL_FROM_DATABASE=OneTouch 4 usb:v0D49p7410* ID_MODEL_FROM_DATABASE=Mobile Hard Disk Drive (1TB) usb:v0D49p7450* ID_MODEL_FROM_DATABASE=Basics Portable USB Device usb:v0D4A* ID_VENDOR_FROM_DATABASE=NF Corp. usb:v0D4B* ID_VENDOR_FROM_DATABASE=Grape Systems, Inc. usb:v0D4C* ID_VENDOR_FROM_DATABASE=Tedas AG usb:v0D4D* ID_VENDOR_FROM_DATABASE=Coherent, Inc. usb:v0D4E* ID_VENDOR_FROM_DATABASE=Agere Systems Netherland BV usb:v0D4Ep047A* ID_MODEL_FROM_DATABASE=WLAN Card usb:v0D4Ep1000* ID_MODEL_FROM_DATABASE=Wireless Card Model 0801 usb:v0D4Ep1001* ID_MODEL_FROM_DATABASE=Wireless Card Model 0802 usb:v0D4F* ID_VENDOR_FROM_DATABASE=EADS Airbus France usb:v0D50* ID_VENDOR_FROM_DATABASE=Cleware GmbH usb:v0D50p0011* ID_MODEL_FROM_DATABASE=USB-Temp2 Thermometer usb:v0D50p0040* ID_MODEL_FROM_DATABASE=F4 foot switch usb:v0D51* ID_VENDOR_FROM_DATABASE=Volex (Asia) Pte., Ltd usb:v0D53* ID_VENDOR_FROM_DATABASE=HMI Co., Ltd usb:v0D54* ID_VENDOR_FROM_DATABASE=Holon Corp. usb:v0D55* ID_VENDOR_FROM_DATABASE=ASKA Technologies, Inc. usb:v0D56* ID_VENDOR_FROM_DATABASE=AVLAB Technology, Inc. usb:v0D57* ID_VENDOR_FROM_DATABASE=Solomon Microtech, Ltd usb:v0D5C* ID_VENDOR_FROM_DATABASE=SMC Networks, Inc. usb:v0D5CpA001* ID_MODEL_FROM_DATABASE=SMC2662W (v1) EZ Connect 802.11b Wireless Adapter [Atmel AT76C503A] usb:v0D5CpA002* ID_MODEL_FROM_DATABASE=SMC2662W v2 / SMC2662W-AR / Belkin F5D6050 [Atmel at76c503a] usb:v0D5E* ID_VENDOR_FROM_DATABASE=Myacom, Ltd usb:v0D5Ep2346* ID_MODEL_FROM_DATABASE=BT Digital Access adapter usb:v0D5F* ID_VENDOR_FROM_DATABASE=CSI, Inc. usb:v0D60* ID_VENDOR_FROM_DATABASE=IVL Technologies, Ltd usb:v0D61* ID_VENDOR_FROM_DATABASE=Meilu Electronics (Shenzhen) Co., Ltd usb:v0D62* ID_VENDOR_FROM_DATABASE=Darfon Electronics Corp. usb:v0D62p0003* ID_MODEL_FROM_DATABASE=Smartcard Reader usb:v0D62p0004* ID_MODEL_FROM_DATABASE=Keyboard usb:v0D62p001B* ID_MODEL_FROM_DATABASE=Keyboard usb:v0D62p001C* ID_MODEL_FROM_DATABASE=Benq X120 Internet Keyboard Pro usb:v0D62p0306* ID_MODEL_FROM_DATABASE=M530 Mouse usb:v0D62p0800* ID_MODEL_FROM_DATABASE=Magic Wheel usb:v0D62p2021* ID_MODEL_FROM_DATABASE=AM805 Keyboard usb:v0D62p2026* ID_MODEL_FROM_DATABASE=TECOM Bluetooth Device usb:v0D62p2050* ID_MODEL_FROM_DATABASE=Mouse usb:v0D62p2106* ID_MODEL_FROM_DATABASE=Dell L20U Multimedia Keyboard usb:v0D62pA100* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v0D63* ID_VENDOR_FROM_DATABASE=Fritz Gegauf AG usb:v0D64* ID_VENDOR_FROM_DATABASE=DXG Technology Corp. usb:v0D64p0105* ID_MODEL_FROM_DATABASE=Dual Mode Digital Camera 1.3M usb:v0D64p0107* ID_MODEL_FROM_DATABASE=Horus MT-409 Camera usb:v0D64p0108* ID_MODEL_FROM_DATABASE=Dual Mode Digital Camera usb:v0D64p0202* ID_MODEL_FROM_DATABASE=Dual Mode Video Camera Device usb:v0D64p0303* ID_MODEL_FROM_DATABASE=DXG-305V Camera usb:v0D64p1001* ID_MODEL_FROM_DATABASE=SiPix Stylecam/UMAX AstraPix 320s usb:v0D64p1002* ID_MODEL_FROM_DATABASE=Fashion Cam 01 Dual-Mode DSC (Video Camera) usb:v0D64p1003* ID_MODEL_FROM_DATABASE=Fashion Cam Dual-Mode DSC (Controller) usb:v0D64p1021* ID_MODEL_FROM_DATABASE=D-Link DSC 350F usb:v0D64p1208* ID_MODEL_FROM_DATABASE=Dual Mode Still Camera Device usb:v0D64p2208* ID_MODEL_FROM_DATABASE=Mass Storage usb:v0D64p3105* ID_MODEL_FROM_DATABASE=Dual Mode Digital Camera Disk usb:v0D64p3108* ID_MODEL_FROM_DATABASE=Digicam Mass Storage Device usb:v0D65* ID_VENDOR_FROM_DATABASE=KMJP Co., Ltd usb:v0D66* ID_VENDOR_FROM_DATABASE=TMT usb:v0D67* ID_VENDOR_FROM_DATABASE=Advanet, Inc. usb:v0D68* ID_VENDOR_FROM_DATABASE=Super Link Electronics Co., Ltd usb:v0D69* ID_VENDOR_FROM_DATABASE=NSI usb:v0D6A* ID_VENDOR_FROM_DATABASE=Megapower International Corp. usb:v0D6B* ID_VENDOR_FROM_DATABASE=And-Or Logic usb:v0D70* ID_VENDOR_FROM_DATABASE=Try Computer Co., Ltd usb:v0D71* ID_VENDOR_FROM_DATABASE=Hirakawa Hewtech Corp. usb:v0D72* ID_VENDOR_FROM_DATABASE=Winmate Communication, Inc. usb:v0D73* ID_VENDOR_FROM_DATABASE=Hit's Communications, Inc. usb:v0D76* ID_VENDOR_FROM_DATABASE=MFP Korea, Inc. usb:v0D77* ID_VENDOR_FROM_DATABASE=Power Sentry/Newpoint usb:v0D78* ID_VENDOR_FROM_DATABASE=Japan Distributor Corp. usb:v0D7A* ID_VENDOR_FROM_DATABASE=MARX Datentechnik GmbH usb:v0D7Ap0001* ID_MODEL_FROM_DATABASE=CrypToken usb:v0D7B* ID_VENDOR_FROM_DATABASE=Wellco Technology Co., Ltd usb:v0D7C* ID_VENDOR_FROM_DATABASE=Taiwan Line Tek Electronic Co., Ltd usb:v0D7D* ID_VENDOR_FROM_DATABASE=Phison Electronics Corp. usb:v0D7Dp0100* ID_MODEL_FROM_DATABASE=PS1001/1011/1006/1026 Flash Disk usb:v0D7Dp0110* ID_MODEL_FROM_DATABASE=Gigabyte FlexDrive usb:v0D7Dp0120* ID_MODEL_FROM_DATABASE=Disk Pro 64MB usb:v0D7Dp0124* ID_MODEL_FROM_DATABASE=GIGABYTE Disk usb:v0D7Dp0240* ID_MODEL_FROM_DATABASE=I/O-Magic/Transcend 6-in-1 Card Reader usb:v0D7Dp110E* ID_MODEL_FROM_DATABASE=NEC uPD720121/130 USB-ATA/ATAPI Bridge usb:v0D7Dp1240* ID_MODEL_FROM_DATABASE=Apacer 6-in-1 Card Reader 2.0 usb:v0D7Dp1270* ID_MODEL_FROM_DATABASE=Wolverine SixPac 6000 usb:v0D7Dp1300* ID_MODEL_FROM_DATABASE=Flash Disk usb:v0D7Dp1320* ID_MODEL_FROM_DATABASE=PS2031 Flash Disk usb:v0D7Dp1400* ID_MODEL_FROM_DATABASE=Attache 256MB USB 2.0 Flash Drive usb:v0D7Dp1420* ID_MODEL_FROM_DATABASE=PS2044 Pen Drive usb:v0D7Dp1470* ID_MODEL_FROM_DATABASE=Vosonic X's-Drive II+ VP2160 usb:v0D7Dp1620* ID_MODEL_FROM_DATABASE=USB Disk Pro usb:v0D7Dp1900* ID_MODEL_FROM_DATABASE=USB Thumb Drive usb:v0D7E* ID_VENDOR_FROM_DATABASE=American Computer & Digital Components usb:v0D7Ep2507* ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller usb:v0D7Ep2517* ID_MODEL_FROM_DATABASE=Hi-Speed Mass Storage Device usb:v0D7Ep25C7* ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller usb:v0D7F* ID_VENDOR_FROM_DATABASE=Essential Reality LLC usb:v0D7Fp0100* ID_MODEL_FROM_DATABASE=P5 Glove glove controller usb:v0D80* ID_VENDOR_FROM_DATABASE=H.R. Silvine Electronics, Inc. usb:v0D81* ID_VENDOR_FROM_DATABASE=TechnoVision usb:v0D83* ID_VENDOR_FROM_DATABASE=Think Outside, Inc. usb:v0D87* ID_VENDOR_FROM_DATABASE=Dolby Laboratories Inc. usb:v0D89* ID_VENDOR_FROM_DATABASE=Oz Software usb:v0D8A* ID_VENDOR_FROM_DATABASE=King Jim Co., Ltd usb:v0D8Ap0101* ID_MODEL_FROM_DATABASE=TEPRA PRO usb:v0D8B* ID_VENDOR_FROM_DATABASE=Ascom Telecommunications, Ltd usb:v0D8C* ID_VENDOR_FROM_DATABASE=C-Media Electronics, Inc. usb:v0D8Cp0001* ID_MODEL_FROM_DATABASE=Audio Device usb:v0D8Cp0002* ID_MODEL_FROM_DATABASE=Composite Device usb:v0D8Cp0003* ID_MODEL_FROM_DATABASE=Sound Device usb:v0D8Cp0006* ID_MODEL_FROM_DATABASE=Storm HP-USB500 5.1 Headset usb:v0D8Cp000C* ID_MODEL_FROM_DATABASE=Audio Adapter usb:v0D8Cp000D* ID_MODEL_FROM_DATABASE=Composite Device usb:v0D8Cp000E* ID_MODEL_FROM_DATABASE=Audio Adapter (Planet UP-100, Genius G-Talk) usb:v0D8Cp001F* ID_MODEL_FROM_DATABASE=CM108 Audio Controller usb:v0D8Cp0102* ID_MODEL_FROM_DATABASE=CM106 Like Sound Device usb:v0D8Cp0103* ID_MODEL_FROM_DATABASE=CM102-A+/102S+ Audio Controller usb:v0D8Cp0104* ID_MODEL_FROM_DATABASE=CM103+ Audio Controller usb:v0D8Cp0105* ID_MODEL_FROM_DATABASE=CM108 Audio Controller usb:v0D8Cp0107* ID_MODEL_FROM_DATABASE=CM108 Audio Controller usb:v0D8Cp010F* ID_MODEL_FROM_DATABASE=CM108 Audio Controller usb:v0D8Cp0115* ID_MODEL_FROM_DATABASE=CM108 Audio Controller usb:v0D8Cp0139* ID_MODEL_FROM_DATABASE=Multimedia Headset [Gigaware by Ignition L.P.] usb:v0D8Cp013C* ID_MODEL_FROM_DATABASE=CM108 Audio Controller usb:v0D8Cp0201* ID_MODEL_FROM_DATABASE=CM6501 usb:v0D8Cp5000* ID_MODEL_FROM_DATABASE=Mass Storage Controller usb:v0D8Cp5200* ID_MODEL_FROM_DATABASE=Mass Storage Controller(0D8C,5200) usb:v0D8CpB213* ID_MODEL_FROM_DATABASE=USB Phone CM109 (aka CT2000,VPT1000) usb:v0D8D* ID_VENDOR_FROM_DATABASE=Promotion & Display Technology, Ltd usb:v0D8Dp0234* ID_MODEL_FROM_DATABASE=V-234 Composite Device usb:v0D8Dp0550* ID_MODEL_FROM_DATABASE=V-550 Composite Device usb:v0D8Dp0551* ID_MODEL_FROM_DATABASE=V-551 Composite Device usb:v0D8Dp0552* ID_MODEL_FROM_DATABASE=V-552 Composite Device usb:v0D8Dp0651* ID_MODEL_FROM_DATABASE=V-651 Composite Device usb:v0D8Dp0652* ID_MODEL_FROM_DATABASE=V-652 Composite Device usb:v0D8Dp0653* ID_MODEL_FROM_DATABASE=V-653 Composite Device usb:v0D8Dp0654* ID_MODEL_FROM_DATABASE=V-654 Composite Device usb:v0D8Dp0655* ID_MODEL_FROM_DATABASE=V-655 Composite Device usb:v0D8Dp0656* ID_MODEL_FROM_DATABASE=V-656 Composite Device usb:v0D8Dp0657* ID_MODEL_FROM_DATABASE=V-657 Composite Device usb:v0D8Dp0658* ID_MODEL_FROM_DATABASE=V-658 Composite Device usb:v0D8Dp0659* ID_MODEL_FROM_DATABASE=V-659 Composite Device usb:v0D8Dp0660* ID_MODEL_FROM_DATABASE=V-660 Composite Device usb:v0D8Dp0661* ID_MODEL_FROM_DATABASE=V-661 Composite Device usb:v0D8Dp0662* ID_MODEL_FROM_DATABASE=V-662 Composite Device usb:v0D8Dp0850* ID_MODEL_FROM_DATABASE=V-850 Composite Device usb:v0D8Dp0851* ID_MODEL_FROM_DATABASE=V-851 Composite Device usb:v0D8Dp0852* ID_MODEL_FROM_DATABASE=V-852 Composite Device usb:v0D8Dp0901* ID_MODEL_FROM_DATABASE=V-901 Composite Device usb:v0D8Dp0902* ID_MODEL_FROM_DATABASE=V-902 Composite Device usb:v0D8Dp0903* ID_MODEL_FROM_DATABASE=V-903 Composite Device usb:v0D8Dp4754* ID_MODEL_FROM_DATABASE=Voyager DMP Composite Device usb:v0D8DpBB00* ID_MODEL_FROM_DATABASE=Bloomberg Composite Device usb:v0D8DpBB01* ID_MODEL_FROM_DATABASE=Bloomberg Composite Device usb:v0D8DpBB02* ID_MODEL_FROM_DATABASE=Bloomberg Composite Device usb:v0D8DpBB03* ID_MODEL_FROM_DATABASE=Bloomberg Composite Device usb:v0D8DpBB04* ID_MODEL_FROM_DATABASE=Bloomberg Composite Device usb:v0D8DpBB05* ID_MODEL_FROM_DATABASE=Bloomberg Composite Device usb:v0D8DpFFFE* ID_MODEL_FROM_DATABASE=Global Tuner Composite Device usb:v0D8DpFFFF* ID_MODEL_FROM_DATABASE=Voyager DMP Composite Device usb:v0D8E* ID_VENDOR_FROM_DATABASE=Global Sun Technology, Inc. usb:v0D8Ep0163* ID_MODEL_FROM_DATABASE=802.11g 54 Mbps Wireless Dongle usb:v0D8Ep1621* ID_MODEL_FROM_DATABASE=802.11b Wireless Adapter usb:v0D8Ep3762* ID_MODEL_FROM_DATABASE=Cohiba 802.11g Wireless Mini adapter [Intersil ISL3887] usb:v0D8Ep3763* ID_MODEL_FROM_DATABASE=802.11g Wireless dongle usb:v0D8Ep7100* ID_MODEL_FROM_DATABASE=802.11b Adapter usb:v0D8Ep7110* ID_MODEL_FROM_DATABASE=WL-210 / WU210P 802.11b Wireless Adapter [Atmel AT76C503A] usb:v0D8Ep7605* ID_MODEL_FROM_DATABASE=TRENDnet TEW-224UB 802.11b Wireless Adapter [Atmel AT76C503A] usb:v0D8Ep7801* ID_MODEL_FROM_DATABASE=AR5523 usb:v0D8Ep7802* ID_MODEL_FROM_DATABASE=AR5523 (no firmware) usb:v0D8Ep7811* ID_MODEL_FROM_DATABASE=AR5523 usb:v0D8Ep7812* ID_MODEL_FROM_DATABASE=AR5523 (no firmware) usb:v0D8Ep7A01* ID_MODEL_FROM_DATABASE=PRISM25 802.11b Adapter usb:v0D8F* ID_VENDOR_FROM_DATABASE=Pitney Bowes usb:v0D90* ID_VENDOR_FROM_DATABASE=Sure-Fire Electrical Corp. usb:v0D96* ID_VENDOR_FROM_DATABASE=Skanhex Technology, Inc. usb:v0D96p0000* ID_MODEL_FROM_DATABASE=Jenoptik JD350 video usb:v0D96p3300* ID_MODEL_FROM_DATABASE=SX330z Camera usb:v0D96p4100* ID_MODEL_FROM_DATABASE=SX410z Camera usb:v0D96p4102* ID_MODEL_FROM_DATABASE=MD 9700 Camera usb:v0D96p4104* ID_MODEL_FROM_DATABASE=Jenoptik JD-4100z3s usb:v0D96p410A* ID_MODEL_FROM_DATABASE=Medion 9801/Novatech SX-410z usb:v0D96p5200* ID_MODEL_FROM_DATABASE=SX-520z Camera usb:v0D97* ID_VENDOR_FROM_DATABASE=Santa Barbara Instrument Group usb:v0D97p0001* ID_MODEL_FROM_DATABASE=SBIG Astronomy Camera (without firmware) usb:v0D97p0101* ID_MODEL_FROM_DATABASE=SBIG Astronomy Camera (with firmware) usb:v0D98* ID_VENDOR_FROM_DATABASE=Mars Semiconductor Corp. usb:v0D98p0300* ID_MODEL_FROM_DATABASE=Avaya Wireless Card usb:v0D98p1007* ID_MODEL_FROM_DATABASE=Discovery Kids Digital Camera usb:v0D99* ID_VENDOR_FROM_DATABASE=Trazer Technologies, Inc. usb:v0D9A* ID_VENDOR_FROM_DATABASE=RTX Telecom AS usb:v0D9Ap0001* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0D9B* ID_VENDOR_FROM_DATABASE=Tat Shing Electrical Co. usb:v0D9C* ID_VENDOR_FROM_DATABASE=Chee Chen Hi-Technology Co., Ltd usb:v0D9D* ID_VENDOR_FROM_DATABASE=Sanwa Supply, Inc. usb:v0D9E* ID_VENDOR_FROM_DATABASE=Avaya usb:v0D9Ep0300* ID_MODEL_FROM_DATABASE=Wireless Card usb:v0D9F* ID_VENDOR_FROM_DATABASE=Powercom Co., Ltd usb:v0D9Fp0001* ID_MODEL_FROM_DATABASE=Uninterruptible Power Supply usb:v0D9Fp0002* ID_MODEL_FROM_DATABASE=Black Knight PRO / WOW Uninterruptible Power Supply (Cypress HID->COM RS232) usb:v0D9Fp00A2* ID_MODEL_FROM_DATABASE=Imperial Uninterruptible Power Supply (HID PDC) usb:v0D9Fp00A3* ID_MODEL_FROM_DATABASE=Smart King PRO Uninterruptible Power Supply (HID PDC) usb:v0D9Fp00A4* ID_MODEL_FROM_DATABASE=WOW Uninterruptible Power Supply (HID PDC) usb:v0D9Fp00A5* ID_MODEL_FROM_DATABASE=Vanguard Uninterruptible Power Supply (HID PDC) usb:v0D9Fp00A6* ID_MODEL_FROM_DATABASE=Black Knight PRO Uninterruptible Power Supply (HID PDC) usb:v0DA0* ID_VENDOR_FROM_DATABASE=Danger Research usb:v0DA1* ID_VENDOR_FROM_DATABASE=Suzhou Peter's Precise Industrial Co., Ltd usb:v0DA2* ID_VENDOR_FROM_DATABASE=Land Instruments International, Ltd usb:v0DA3* ID_VENDOR_FROM_DATABASE=Nippon Electro-Sensory Devices Corp. usb:v0DA4* ID_VENDOR_FROM_DATABASE=Polar Electro Oy usb:v0DA4p0001* ID_MODEL_FROM_DATABASE=Interface usb:v0DA4p0008* ID_MODEL_FROM_DATABASE=Loop usb:v0DA7* ID_VENDOR_FROM_DATABASE=IOGear, Inc. usb:v0DA8* ID_VENDOR_FROM_DATABASE=softDSP Co., Ltd usb:v0DA8p0001* ID_MODEL_FROM_DATABASE=SDS 200A Oscilloscope usb:v0DAB* ID_VENDOR_FROM_DATABASE=Cubig Group usb:v0DABp0100* ID_MODEL_FROM_DATABASE=DVR/CVR-M140 MP3 Player usb:v0DAD* ID_VENDOR_FROM_DATABASE=Westover Scientific usb:v0DB0* ID_VENDOR_FROM_DATABASE=Micro Star International usb:v0DB0p1020* ID_MODEL_FROM_DATABASE=PC2PC WLAN Card usb:v0DB0p1967* ID_MODEL_FROM_DATABASE=Bluetooth Dongle usb:v0DB0p3713* ID_MODEL_FROM_DATABASE=Primo 73 usb:v0DB0p3801* ID_MODEL_FROM_DATABASE=Motorola Bluetooth 2.1+EDR Device usb:v0DB0p4011* ID_MODEL_FROM_DATABASE=Medion Flash XL V2.0 Card Reader usb:v0DB0p4023* ID_MODEL_FROM_DATABASE=Lexar Mobile Card Reader usb:v0DB0p4600* ID_MODEL_FROM_DATABASE=802.11b/g Turbo Wireless Adapter usb:v0DB0p5501* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0DB0p5502* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0DB0p5513* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0DB0p5515* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0DB0p5516* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0DB0p5580* ID_MODEL_FROM_DATABASE=Mega Sky 580 DVB-T Tuner [M902x] usb:v0DB0p5581* ID_MODEL_FROM_DATABASE=Mega Sky 580 DVB-T Tuner [GL861] usb:v0DB0p6823* ID_MODEL_FROM_DATABASE=UB11B/MS-6823 802.11b Wi-Fi adapter usb:v0DB0p6826* ID_MODEL_FROM_DATABASE=IEEE 802.11g Wireless Network Adapter usb:v0DB0p6855* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0DB0p6861* ID_MODEL_FROM_DATABASE=MSI-6861 802.11g WiFi adapter usb:v0DB0p6865* ID_MODEL_FROM_DATABASE=RT2570 usb:v0DB0p6869* ID_MODEL_FROM_DATABASE=RT2570 usb:v0DB0p6874* ID_MODEL_FROM_DATABASE=RT2573 usb:v0DB0p6877* ID_MODEL_FROM_DATABASE=RT2573 usb:v0DB0p6881* ID_MODEL_FROM_DATABASE=Bluetooth Class I EDR Device usb:v0DB0p688A* ID_MODEL_FROM_DATABASE=Bluetooth Class I EDR Device usb:v0DB0p6899* ID_MODEL_FROM_DATABASE=802.11bgn 1T1R Mini Card Wireless Adapter usb:v0DB0p6970* ID_MODEL_FROM_DATABASE=MS-6970 BToes Bluetooth adapter usb:v0DB0p697A* ID_MODEL_FROM_DATABASE=Bluetooth Dongle usb:v0DB0p6982* ID_MODEL_FROM_DATABASE=Medion Flash XL Card Reader usb:v0DB0pA861* ID_MODEL_FROM_DATABASE=RT2573 usb:v0DB0pA874* ID_MODEL_FROM_DATABASE=RT2573 usb:v0DB0pA970* ID_MODEL_FROM_DATABASE=Bluetooth dongle usb:v0DB0pA97A* ID_MODEL_FROM_DATABASE=Bluetooth EDR Device usb:v0DB0pB970* ID_MODEL_FROM_DATABASE=Bluetooth EDR Device usb:v0DB0pB97A* ID_MODEL_FROM_DATABASE=Bluetooth EDR Device usb:v0DB1* ID_VENDOR_FROM_DATABASE=Wen Te Electronics Co., Ltd usb:v0DB2* ID_VENDOR_FROM_DATABASE=Shian Hwi Plug Parts, Plastic Factory usb:v0DB3* ID_VENDOR_FROM_DATABASE=Tekram Technology Co., Ltd usb:v0DB4* ID_VENDOR_FROM_DATABASE=Chung Fu Chen Yeh Enterprise Corp. usb:v0DB5* ID_VENDOR_FROM_DATABASE=Access IS usb:v0DB5p0139* ID_MODEL_FROM_DATABASE=Barcode Module - CDC serial usb:v0DB5p013A* ID_MODEL_FROM_DATABASE=Barcode Module - Virtual Keyboard usb:v0DB5p013B* ID_MODEL_FROM_DATABASE=Barcode Module - HID usb:v0DB5p0160* ID_MODEL_FROM_DATABASE=NFC and Smartcard Module (NSM) usb:v0DB7* ID_VENDOR_FROM_DATABASE=ELCON Systemtechnik usb:v0DB7p0002* ID_MODEL_FROM_DATABASE=Goldpfeil P-LAN usb:v0DBA* ID_VENDOR_FROM_DATABASE=Digidesign usb:v0DBAp1000* ID_MODEL_FROM_DATABASE=Mbox 1 [Mbox] usb:v0DBAp3000* ID_MODEL_FROM_DATABASE=Mbox 2 usb:v0DBC* ID_VENDOR_FROM_DATABASE=A&D Medical usb:v0DBCp0003* ID_MODEL_FROM_DATABASE=AND Serial Cable [AND Smart Cable] usb:v0DBE* ID_VENDOR_FROM_DATABASE=Jiuh Shiuh Precision Industry Co., Ltd usb:v0DBF* ID_VENDOR_FROM_DATABASE=Jess-Link International usb:v0DBFp0002* ID_MODEL_FROM_DATABASE=SmartDongle Security Key usb:v0DBFp0200* ID_MODEL_FROM_DATABASE=HDD Storage Solution usb:v0DBFp021B* ID_MODEL_FROM_DATABASE=USB-2.0 IDE Adapter usb:v0DBFp0300* ID_MODEL_FROM_DATABASE=Storage Adapter usb:v0DBFp0333* ID_MODEL_FROM_DATABASE=Storage Adapter usb:v0DBFp0707* ID_MODEL_FROM_DATABASE=ZIV Drive usb:v0DC0* ID_VENDOR_FROM_DATABASE=G7 Solutions (formerly Great Notions) usb:v0DC1* ID_VENDOR_FROM_DATABASE=Tamagawa Seiki Co., Ltd usb:v0DC3* ID_VENDOR_FROM_DATABASE=Athena Smartcard Solutions, Inc. usb:v0DC3p0801* ID_MODEL_FROM_DATABASE=ASEDrive III usb:v0DC3p0802* ID_MODEL_FROM_DATABASE=ASEDrive IIIe usb:v0DC3p1104* ID_MODEL_FROM_DATABASE=ASEDrive IIIe KB usb:v0DC3p1701* ID_MODEL_FROM_DATABASE=ASEKey usb:v0DC3p1702* ID_MODEL_FROM_DATABASE=ASEKey usb:v0DC4* ID_VENDOR_FROM_DATABASE=Macpower Peripherals, Ltd usb:v0DC4p0040* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0DC4p0041* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0DC4p0042* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0DC4p0101* ID_MODEL_FROM_DATABASE=Hi-Speed Mass Storage Device usb:v0DC4p0209* ID_MODEL_FROM_DATABASE=SK-3500 S2 usb:v0DC4p020A* ID_MODEL_FROM_DATABASE=Oyen Digital MiniPro 2.5" hard drive enclosure usb:v0DC5* ID_VENDOR_FROM_DATABASE=SDK Co., Ltd usb:v0DC6* ID_VENDOR_FROM_DATABASE=Precision Squared Technology Corp. usb:v0DC6p2301* ID_MODEL_FROM_DATABASE=Wireless Touchpad Keyboard usb:v0DC7* ID_VENDOR_FROM_DATABASE=First Cable Line, Inc. usb:v0DCD* ID_VENDOR_FROM_DATABASE=NetworkFab Corp. usb:v0DCDp0001* ID_MODEL_FROM_DATABASE=Remote Interface Adapter usb:v0DCDp0002* ID_MODEL_FROM_DATABASE=High Bandwidth Codec usb:v0DD0* ID_VENDOR_FROM_DATABASE=Access Solutions usb:v0DD0p1002* ID_MODEL_FROM_DATABASE=Triple Talk Speech Synthesizer usb:v0DD1* ID_VENDOR_FROM_DATABASE=Contek Electronics Co., Ltd usb:v0DD2* ID_VENDOR_FROM_DATABASE=Power Quotient International Co., Ltd usb:v0DD2p0003* ID_MODEL_FROM_DATABASE=Mass Storage (P) usb:v0DD3* ID_VENDOR_FROM_DATABASE=MediaQ usb:v0DD4* ID_VENDOR_FROM_DATABASE=Custom Engineering SPA usb:v0DD5* ID_VENDOR_FROM_DATABASE=California Micro Devices usb:v0DD7* ID_VENDOR_FROM_DATABASE=Kocom Co., Ltd usb:v0DD8* ID_VENDOR_FROM_DATABASE=Netac Technology Co., Ltd usb:v0DD8p1060* ID_MODEL_FROM_DATABASE=USB-CF-Card usb:v0DD8pE007* ID_MODEL_FROM_DATABASE=OnlyDisk U222 Pendrive usb:v0DD8pF607* ID_MODEL_FROM_DATABASE=OnlyDisk U208 1G flash drive [U-SAFE] usb:v0DD9* ID_VENDOR_FROM_DATABASE=HighSpeed Surfing usb:v0DDA* ID_VENDOR_FROM_DATABASE=Integrated Circuit Solution, Inc. usb:v0DDAp0001* ID_MODEL_FROM_DATABASE=Multi-Card Reader 6in1 usb:v0DDAp0002* ID_MODEL_FROM_DATABASE=Multi-Card Reader 7in1 usb:v0DDAp0003* ID_MODEL_FROM_DATABASE=Flash Disk usb:v0DDAp0005* ID_MODEL_FROM_DATABASE=Internal Multi-Card Reader 6in1 usb:v0DDAp0008* ID_MODEL_FROM_DATABASE=SD single card reader usb:v0DDAp0009* ID_MODEL_FROM_DATABASE=MS single card reader usb:v0DDAp000A* ID_MODEL_FROM_DATABASE=MS+SD Dual Card Reader usb:v0DDAp000B* ID_MODEL_FROM_DATABASE=SM single card reader usb:v0DDAp0101* ID_MODEL_FROM_DATABASE=All-In-One Card Reader usb:v0DDAp0102* ID_MODEL_FROM_DATABASE=All-In-One Card Reader usb:v0DDAp0301* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0DDAp0302* ID_MODEL_FROM_DATABASE=Multi-Card MP3 Player usb:v0DDAp1001* ID_MODEL_FROM_DATABASE=Multi-Flash Disk usb:v0DDAp2001* ID_MODEL_FROM_DATABASE=Multi-Card Reader usb:v0DDAp2002* ID_MODEL_FROM_DATABASE=Q018 default PID usb:v0DDAp2003* ID_MODEL_FROM_DATABASE=Multi-Card Reader usb:v0DDAp2005* ID_MODEL_FROM_DATABASE=Datalux DLX-1611 16in1 Card Reader usb:v0DDAp2006* ID_MODEL_FROM_DATABASE=All-In-One Card Reader usb:v0DDAp2007* ID_MODEL_FROM_DATABASE=USB to ATAPI bridge usb:v0DDAp2008* ID_MODEL_FROM_DATABASE=All-In-One Card Reader usb:v0DDAp2013* ID_MODEL_FROM_DATABASE=SD/MS Combo Card Reader usb:v0DDAp2014* ID_MODEL_FROM_DATABASE=SD/MS Single Card Reader usb:v0DDAp2023* ID_MODEL_FROM_DATABASE=card reader SD/MS DEMO board with ICSI brand name (MaskROM version) usb:v0DDAp2024* ID_MODEL_FROM_DATABASE=card reader SD/MS DEMO board with Generic brand name (MaskROM version) usb:v0DDAp2026* ID_MODEL_FROM_DATABASE=USB2.0 Card Reader usb:v0DDAp2027* ID_MODEL_FROM_DATABASE=USB 2.0 Card Reader usb:v0DDAp2315* ID_MODEL_FROM_DATABASE=UFD MP3 player (model 2) usb:v0DDAp2318* ID_MODEL_FROM_DATABASE=UFD MP3 player (model 1) usb:v0DDAp2321* ID_MODEL_FROM_DATABASE=UFD MP3 player usb:v0DDB* ID_VENDOR_FROM_DATABASE=Tamarack, Inc. usb:v0DDD* ID_VENDOR_FROM_DATABASE=Datelink Technology Co., Ltd usb:v0DDE* ID_VENDOR_FROM_DATABASE=Ubicom, Inc. usb:v0DE0* ID_VENDOR_FROM_DATABASE=BD Consumer Healthcare usb:v0DE7* ID_VENDOR_FROM_DATABASE=USBmicro usb:v0DE7p0191* ID_MODEL_FROM_DATABASE=U401 Interface card usb:v0DE7p01A5* ID_MODEL_FROM_DATABASE=U421 interface card usb:v0DE7p01C3* ID_MODEL_FROM_DATABASE=U451 relay interface card usb:v0DEA* ID_VENDOR_FROM_DATABASE=UTECH Electronic (D.G.) Co., Ltd. usb:v0DED* ID_VENDOR_FROM_DATABASE=Novasonics usb:v0DEE* ID_VENDOR_FROM_DATABASE=Lifetime Memory Products usb:v0DEEp4010* ID_MODEL_FROM_DATABASE=Storage Adapter usb:v0DEF* ID_VENDOR_FROM_DATABASE=Full Rise Electronic Co., Ltd usb:v0DF4* ID_VENDOR_FROM_DATABASE=NET&SYS usb:v0DF4p0201* ID_MODEL_FROM_DATABASE=MNG-2005 usb:v0DF6* ID_VENDOR_FROM_DATABASE=Sitecom Europe B.V. usb:v0DF6p0001* ID_MODEL_FROM_DATABASE=C-Media VOIP Device usb:v0DF6p0004* ID_MODEL_FROM_DATABASE=Bluetooth 2.0 Adapter 100m usb:v0DF6p0007* ID_MODEL_FROM_DATABASE=Bluetooth 2.0 Adapter 10m usb:v0DF6p000B* ID_MODEL_FROM_DATABASE=Bluetooth 2.0 Adapter DFU usb:v0DF6p000D* ID_MODEL_FROM_DATABASE=WL-168 Wireless Network Adapter 54g usb:v0DF6p0017* ID_MODEL_FROM_DATABASE=WL-182 Wireless-N Network USB Card usb:v0DF6p0019* ID_MODEL_FROM_DATABASE=Bluetooth 2.0 adapter 10m CN-512v2 001 usb:v0DF6p001A* ID_MODEL_FROM_DATABASE=Bluetooth 2.0 adapter 100m CN-521v2 001 usb:v0DF6p002B* ID_MODEL_FROM_DATABASE=WL-188 Wireless Network 300N USB Adapter usb:v0DF6p002C* ID_MODEL_FROM_DATABASE=WL-301 Wireless Network 300N USB Adapter usb:v0DF6p002D* ID_MODEL_FROM_DATABASE=WL-302 Wireless Network 300N USB dongle usb:v0DF6p0036* ID_MODEL_FROM_DATABASE=WL-603 Wireless Adapter usb:v0DF6p0039* ID_MODEL_FROM_DATABASE=WL-315 Wireless-N USB Adapter usb:v0DF6p003B* ID_MODEL_FROM_DATABASE=WL-321 Wireless USB Gaming Adapter 300N usb:v0DF6p003C* ID_MODEL_FROM_DATABASE=WL-323 Wireless-N USB Adapter usb:v0DF6p003D* ID_MODEL_FROM_DATABASE=WL-324 Wireless USB Adapter 300N usb:v0DF6p003E* ID_MODEL_FROM_DATABASE=WL-343 Wireless USB Adapter 150N X1 usb:v0DF6p003F* ID_MODEL_FROM_DATABASE=WL-608 Wireless USB Adapter 54g usb:v0DF6p0040* ID_MODEL_FROM_DATABASE=WL-344 Wireless Adapter 300N X2 [Ralink RT3071] usb:v0DF6p0041* ID_MODEL_FROM_DATABASE=WL-329 Wireless Dualband USB adapter 300N usb:v0DF6p0042* ID_MODEL_FROM_DATABASE=WL-345 Wireless USB adapter 300N X3 usb:v0DF6p0045* ID_MODEL_FROM_DATABASE=WL-353 Wireless USB Adapter 150N Nano usb:v0DF6p0047* ID_MODEL_FROM_DATABASE=WL-352v1 Wireless USB Adapter 300N 002 usb:v0DF6p0048* ID_MODEL_FROM_DATABASE=WL-349v1 Wireless Adapter 150N 002 [Ralink RT3070] usb:v0DF6p0049* ID_MODEL_FROM_DATABASE=WL-356 Wireless Adapter 300N usb:v0DF6p004A* ID_MODEL_FROM_DATABASE=WL-358v1 Wireless Micro USB Adapter 300N X3 002 usb:v0DF6p004B* ID_MODEL_FROM_DATABASE=WL-349v3 Wireless Micro Adapter 150N X1 [Realtek RTL8192SU] usb:v0DF6p004C* ID_MODEL_FROM_DATABASE=WL-352 802.11n Adapter [Realtek RTL8191SU] usb:v0DF6p0050* ID_MODEL_FROM_DATABASE=WL-349v4 Wireless Micro Adapter 150N X1 [Ralink RT3370] usb:v0DF6p0056* ID_MODEL_FROM_DATABASE=LN-031 10/100/1000 Ethernet Adapter usb:v0DF6p005D* ID_MODEL_FROM_DATABASE=WLA-2000 v1.001 WLAN [RTL8191SU] usb:v0DF6p0060* ID_MODEL_FROM_DATABASE=WLA-4000 802.11bgn [Ralink RT3072] usb:v0DF6p0062* ID_MODEL_FROM_DATABASE=WLA-5000 802.11abgn [Ralink RT3572] usb:v0DF6p0072* ID_MODEL_FROM_DATABASE=AX88179 Gigabit Ethernet [Sitecom] usb:v0DF6p061C* ID_MODEL_FROM_DATABASE=LN-028 Network USB 2.0 Adapter usb:v0DF6p21F4* ID_MODEL_FROM_DATABASE=44 St Bluetooth Device usb:v0DF6p2200* ID_MODEL_FROM_DATABASE=Sitecom bluetooth2.0 class 2 dongle CN-512 usb:v0DF6p2208* ID_MODEL_FROM_DATABASE=Sitecom bluetooth2.0 class 2 dongle CN-520 usb:v0DF6p2209* ID_MODEL_FROM_DATABASE=Sitecom bluetooth2.0 class 1 dongle CN-521 usb:v0DF6p3068* ID_MODEL_FROM_DATABASE=DC-104v2 ISDN Adapter [HFC-S] usb:v0DF6p9071* ID_MODEL_FROM_DATABASE=WL-113 rev 1 Wireless Network USB Adapter usb:v0DF6p9075* ID_MODEL_FROM_DATABASE=WL-117 Hi-Speed USB Adapter usb:v0DF6p90AC* ID_MODEL_FROM_DATABASE=WL-172 Wireless Network USB Adapter 54g Turbo usb:v0DF6p9712* ID_MODEL_FROM_DATABASE=WL-113 rev 2 Wireless Network USB Adapter usb:v0DF7* ID_VENDOR_FROM_DATABASE=Mobile Action Technology, Inc. usb:v0DF7p0620* ID_MODEL_FROM_DATABASE=MA-620 Infrared Adapter usb:v0DF7p0700* ID_MODEL_FROM_DATABASE=MA-700 Bluetooth Adapter usb:v0DF7p0720* ID_MODEL_FROM_DATABASE=MA-720 Bluetooth Adapter usb:v0DF7p0722* ID_MODEL_FROM_DATABASE=Bluetooth Dongle usb:v0DF7p0730* ID_MODEL_FROM_DATABASE=MA-730/MA-730G Bluetooth Adapter usb:v0DF7p0800* ID_MODEL_FROM_DATABASE=Data Cable usb:v0DF7p0820* ID_MODEL_FROM_DATABASE=Data Cable usb:v0DF7p0900* ID_MODEL_FROM_DATABASE=MA i-gotU Travel Logger GPS usb:v0DF7p1800* ID_MODEL_FROM_DATABASE=Generic Card Reader usb:v0DF7p1802* ID_MODEL_FROM_DATABASE=Card Reader usb:v0DFA* ID_VENDOR_FROM_DATABASE=Toyo Communication Equipment Co., Ltd usb:v0DFC* ID_VENDOR_FROM_DATABASE=GeneralTouch Technology Co., Ltd usb:v0DFCp0001* ID_MODEL_FROM_DATABASE=Touchscreen usb:v0E03* ID_VENDOR_FROM_DATABASE=Nippon Systemware Co., Ltd usb:v0E08* ID_VENDOR_FROM_DATABASE=Winbest Technology Co., Ltd usb:v0E0B* ID_VENDOR_FROM_DATABASE=Amigo Technology Inc. usb:v0E0Bp9031* ID_MODEL_FROM_DATABASE=802.11n Wireless USB Card usb:v0E0Bp9041* ID_MODEL_FROM_DATABASE=802.11n Wireless USB Card usb:v0E0C* ID_VENDOR_FROM_DATABASE=Gesytec usb:v0E0Cp0101* ID_MODEL_FROM_DATABASE=LonUSB LonTalk Network Adapter usb:v0E0D* ID_VENDOR_FROM_DATABASE=PicoQuant GmbH usb:v0E0Dp0003* ID_MODEL_FROM_DATABASE=PicoHarp 300 usb:v0E0F* ID_VENDOR_FROM_DATABASE=VMware, Inc. usb:v0E0Fp0001* ID_MODEL_FROM_DATABASE=Device usb:v0E0Fp0002* ID_MODEL_FROM_DATABASE=Virtual USB Hub usb:v0E0Fp0003* ID_MODEL_FROM_DATABASE=Virtual Mouse usb:v0E0Fp0004* ID_MODEL_FROM_DATABASE=Virtual CCID usb:v0E0Fp0005* ID_MODEL_FROM_DATABASE=Virtual Mass Storage usb:v0E0Fp0006* ID_MODEL_FROM_DATABASE=Virtual Keyboard usb:v0E0FpF80A* ID_MODEL_FROM_DATABASE=Smoker FX2 usb:v0E16* ID_VENDOR_FROM_DATABASE=JMTek, LLC usb:v0E17* ID_VENDOR_FROM_DATABASE=Walex Electronic, Ltd usb:v0E1A* ID_VENDOR_FROM_DATABASE=Unisys usb:v0E1B* ID_VENDOR_FROM_DATABASE=Crewave usb:v0E20* ID_VENDOR_FROM_DATABASE=Pegasus Technologies Ltd. usb:v0E20p0101* ID_MODEL_FROM_DATABASE=NoteTaker usb:v0E20p0200* ID_MODEL_FROM_DATABASE=Seiko Instruments InkLink Handwriting System usb:v0E21* ID_VENDOR_FROM_DATABASE=Cowon Systems, Inc. usb:v0E21p0300* ID_MODEL_FROM_DATABASE=iAudio CW200 usb:v0E21p0400* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0E21p0500* ID_MODEL_FROM_DATABASE=iAudio M3 usb:v0E21p0510* ID_MODEL_FROM_DATABASE=iAudio X5, subpack USB port usb:v0E21p0513* ID_MODEL_FROM_DATABASE=iAudio X5, side USB port usb:v0E21p0520* ID_MODEL_FROM_DATABASE=iAudio M5, side USB port usb:v0E21p0601* ID_MODEL_FROM_DATABASE=iAudio G3 usb:v0E21p0681* ID_MODEL_FROM_DATABASE=iAUDIO E2 usb:v0E21p0700* ID_MODEL_FROM_DATABASE=iAudio U3 usb:v0E21p0751* ID_MODEL_FROM_DATABASE=iAudio 7 usb:v0E21p0760* ID_MODEL_FROM_DATABASE=iAUDIO U5 / iAUDIO G2 usb:v0E21p0800* ID_MODEL_FROM_DATABASE=Cowon D2 (UMS mode) usb:v0E21p0801* ID_MODEL_FROM_DATABASE=Cowon D2 (MTP mode) usb:v0E21p0910* ID_MODEL_FROM_DATABASE=iAUDIO 9 usb:v0E21p0920* ID_MODEL_FROM_DATABASE=J3 usb:v0E22* ID_VENDOR_FROM_DATABASE=Symbian Ltd. usb:v0E23* ID_VENDOR_FROM_DATABASE=Liou Yuane Enterprise Co., Ltd usb:v0E25* ID_VENDOR_FROM_DATABASE=VinChip Systems, Inc. usb:v0E26* ID_VENDOR_FROM_DATABASE=J-Phone East Co., Ltd usb:v0E30* ID_VENDOR_FROM_DATABASE=HeartMath LLC usb:v0E34* ID_VENDOR_FROM_DATABASE=Micro Computer Control Corp. usb:v0E35* ID_VENDOR_FROM_DATABASE=3Pea Technologies, Inc. usb:v0E36* ID_VENDOR_FROM_DATABASE=TiePie engineering usb:v0E36p0008* ID_MODEL_FROM_DATABASE=Handyscope HS3 usb:v0E36p0009* ID_MODEL_FROM_DATABASE=Handyscope HS3 (br) usb:v0E36p000A* ID_MODEL_FROM_DATABASE=Handyscope HS4 usb:v0E36p000B* ID_MODEL_FROM_DATABASE=Handyscope HS4 (br) usb:v0E36p000E* ID_MODEL_FROM_DATABASE=Handyscope HS4-DIFF usb:v0E36p000F* ID_MODEL_FROM_DATABASE=Handyscope HS4-DIFF (br) usb:v0E36p0010* ID_MODEL_FROM_DATABASE=Handyscope HS2 usb:v0E36p0011* ID_MODEL_FROM_DATABASE=TiePieSCOPE HS805 (br) usb:v0E36p0012* ID_MODEL_FROM_DATABASE=TiePieSCOPE HS805 usb:v0E36p0013* ID_MODEL_FROM_DATABASE=Handyprobe HP3 usb:v0E36p0014* ID_MODEL_FROM_DATABASE=Handyprobe HP3 usb:v0E36p0018* ID_MODEL_FROM_DATABASE=Handyprobe HP2 usb:v0E36p001B* ID_MODEL_FROM_DATABASE=Handyscope HS5 usb:v0E36p0042* ID_MODEL_FROM_DATABASE=TiePieSCOPE HS801 usb:v0E36p00FD* ID_MODEL_FROM_DATABASE=USB To Parallel adapter usb:v0E36p00FE* ID_MODEL_FROM_DATABASE=USB To Parallel adapter usb:v0E38* ID_VENDOR_FROM_DATABASE=Stratitec, Inc. usb:v0E39* ID_VENDOR_FROM_DATABASE=Smart Modular Technologies, Inc. usb:v0E39p0137* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v0E3A* ID_VENDOR_FROM_DATABASE=Neostar Technology Co., Ltd usb:v0E3Ap1100* ID_MODEL_FROM_DATABASE=CW-1100 Wireless Network Adapter usb:v0E3B* ID_VENDOR_FROM_DATABASE=Mansella, Ltd usb:v0E41* ID_VENDOR_FROM_DATABASE=Line6, Inc. usb:v0E41p4147* ID_MODEL_FROM_DATABASE=TonePort GX usb:v0E41p414D* ID_MODEL_FROM_DATABASE=Pod HD500 usb:v0E41p4156* ID_MODEL_FROM_DATABASE=POD HD Desktop usb:v0E41p4250* ID_MODEL_FROM_DATABASE=BassPODxt usb:v0E41p4252* ID_MODEL_FROM_DATABASE=BassPODxt Pro usb:v0E41p4642* ID_MODEL_FROM_DATABASE=BassPODxt Live usb:v0E41p4650* ID_MODEL_FROM_DATABASE=PODxt Live usb:v0E41p4750* ID_MODEL_FROM_DATABASE=GuitarPort usb:v0E41p5044* ID_MODEL_FROM_DATABASE=PODxt usb:v0E41p5050* ID_MODEL_FROM_DATABASE=PODxt Pro usb:v0E41p534D* ID_MODEL_FROM_DATABASE=SeaMonkey usb:v0E44* ID_VENDOR_FROM_DATABASE=Sun-Riseful Technology Co., Ltd. usb:v0E48* ID_VENDOR_FROM_DATABASE=Julia Corp., Ltd usb:v0E48p0100* ID_MODEL_FROM_DATABASE=CardPro SmartCard Reader usb:v0E4A* ID_VENDOR_FROM_DATABASE=Shenzhen Bao Hing Electric Wire & Cable Mfr. Co. usb:v0E4C* ID_VENDOR_FROM_DATABASE=Radica Games, Ltd usb:v0E4Cp1097* ID_MODEL_FROM_DATABASE=Gamester Controller usb:v0E4Cp2390* ID_MODEL_FROM_DATABASE=Games Jtech Controller usb:v0E4Cp7288* ID_MODEL_FROM_DATABASE=funkey reader usb:v0E50* ID_VENDOR_FROM_DATABASE=TechnoData Interware usb:v0E50p0002* ID_MODEL_FROM_DATABASE=Matrixlock Dongle (HID) usb:v0E55* ID_VENDOR_FROM_DATABASE=Speed Dragon Multimedia, Ltd usb:v0E55p110A* ID_MODEL_FROM_DATABASE=Tanic S110-SG1 + ISSC IS1002N [Slow Infra-Red (SIR) & Bluetooth 1.2 (Class 2) Adapter] usb:v0E55p110B* ID_MODEL_FROM_DATABASE=MS3303H USB-to-Serial Bridge usb:v0E56* ID_VENDOR_FROM_DATABASE=Kingston Technology Company, Inc. usb:v0E56p6021* ID_MODEL_FROM_DATABASE=K-PEX 100 usb:v0E5A* ID_VENDOR_FROM_DATABASE=Active Co., Ltd usb:v0E5B* ID_VENDOR_FROM_DATABASE=Union Power Information Industrial Co., Ltd usb:v0E5C* ID_VENDOR_FROM_DATABASE=Bitland Information Technology Co., Ltd usb:v0E5Cp6118* ID_MODEL_FROM_DATABASE=LCD Device usb:v0E5Cp6119* ID_MODEL_FROM_DATABASE=remote receive and control device usb:v0E5Cp6441* ID_MODEL_FROM_DATABASE=C-Media Sound Device usb:v0E5D* ID_VENDOR_FROM_DATABASE=Neltron Industrial Co., Ltd usb:v0E5E* ID_VENDOR_FROM_DATABASE=Conwise Technology Co., Ltd. usb:v0E5Ep6622* ID_MODEL_FROM_DATABASE=CW6622 usb:v0E66* ID_VENDOR_FROM_DATABASE=Hawking Technologies usb:v0E66p0001* ID_MODEL_FROM_DATABASE=HWUN1 Hi-Gain Wireless-300N Adapter w/ Upgradable Antenna [Ralink RT2870] usb:v0E66p0003* ID_MODEL_FROM_DATABASE=HWDN1 Hi-Gain Wireless-300N Dish Adapter [Ralink RT2870] usb:v0E66p0009* ID_MODEL_FROM_DATABASE=HWUN2 Hi-Gain Wireless-150N Adapter w/ Upgradable Antenna [Ralink RT2770] usb:v0E66p000B* ID_MODEL_FROM_DATABASE=HWDN2 Hi-Gain Wireless-150N Dish Adapter [Ralink RT2770] usb:v0E66p0013* ID_MODEL_FROM_DATABASE=HWUN3 Hi-Gain Wireless-N Adapter [Ralink RT3070] usb:v0E66p0015* ID_MODEL_FROM_DATABASE=HWDN2 Rev. E Hi-Gain Wireless-150N Dish Adapter [Realtek RTL8191SU] usb:v0E66p0017* ID_MODEL_FROM_DATABASE=HAWNU1 Hi-Gain Wireless-150N Network Adapter with Range Amplifier [Ralink RT3070] usb:v0E66p0018* ID_MODEL_FROM_DATABASE=Wireless-N Network Adapter [Ralink RT2870] usb:v0E66p400B* ID_MODEL_FROM_DATABASE=UF100 10/100 Network Adapter usb:v0E66p400C* ID_MODEL_FROM_DATABASE=UF100 Ethernet [pegasus2] usb:v0E67* ID_VENDOR_FROM_DATABASE=Fossil, Inc. usb:v0E67p0002* ID_MODEL_FROM_DATABASE=Wrist PDA usb:v0E6A* ID_VENDOR_FROM_DATABASE=Megawin Technology Co., Ltd usb:v0E6Ap0101* ID_MODEL_FROM_DATABASE=MA100 [USB-UART Bridge IC] usb:v0E6Ap030B* ID_MODEL_FROM_DATABASE=Truly Ergonomic Computer Keyboard (Device Firmware Update mode) usb:v0E6Ap030C* ID_MODEL_FROM_DATABASE=Truly Ergonomic Computer Keyboard usb:v0E6Ap6001* ID_MODEL_FROM_DATABASE=GEMBIRD Flexible keyboard KB-109F-B-DE usb:v0E6F* ID_VENDOR_FROM_DATABASE=Logic3 usb:v0E6Fp0003* ID_MODEL_FROM_DATABASE=Freebird wireless Controller usb:v0E6Fp0005* ID_MODEL_FROM_DATABASE=Eclipse wireless Controller usb:v0E6Fp0006* ID_MODEL_FROM_DATABASE=Edge wireless Controller usb:v0E6Fp0128* ID_MODEL_FROM_DATABASE=Wireless PS3 Controller usb:v0E70* ID_VENDOR_FROM_DATABASE=Tokyo Electronic Industry Co., Ltd usb:v0E72* ID_VENDOR_FROM_DATABASE=Hsi-Chin Electronics Co., Ltd usb:v0E75* ID_VENDOR_FROM_DATABASE=TVS Electronics, Ltd usb:v0E79* ID_VENDOR_FROM_DATABASE=Archos, Inc. usb:v0E79p1106* ID_MODEL_FROM_DATABASE=Pocket Media Assistant - PMA400 usb:v0E79p1204* ID_MODEL_FROM_DATABASE=Gmini XS 200 usb:v0E79p1306* ID_MODEL_FROM_DATABASE=504 Portable Multimedia Player usb:v0E79p1330* ID_MODEL_FROM_DATABASE=5 Tablet usb:v0E79p1332* ID_MODEL_FROM_DATABASE=5 IMT usb:v0E79p1416* ID_MODEL_FROM_DATABASE=32 IT usb:v0E79p1417* ID_MODEL_FROM_DATABASE=A43 IT usb:v0E79p14AD* ID_MODEL_FROM_DATABASE=97 Titanium HD usb:v0E79p150E* ID_MODEL_FROM_DATABASE=80 G9 usb:v0E79p3001* ID_MODEL_FROM_DATABASE=40 Titanium usb:v0E7B* ID_VENDOR_FROM_DATABASE=On-Tech Industry Co., Ltd usb:v0E7E* ID_VENDOR_FROM_DATABASE=Gmate, Inc. usb:v0E7Ep0001* ID_MODEL_FROM_DATABASE=Yopy 3000 PDA usb:v0E7Ep1001* ID_MODEL_FROM_DATABASE=YP3X00 PDA usb:v0E82* ID_VENDOR_FROM_DATABASE=Ching Tai Electric Wire & Cable Co., Ltd usb:v0E83* ID_VENDOR_FROM_DATABASE=Shin An Wire & Cable Co. usb:v0E8C* ID_VENDOR_FROM_DATABASE=Well Force Electronic Co., Ltd usb:v0E8D* ID_VENDOR_FROM_DATABASE=MediaTek Inc. usb:v0E8Dp0003* ID_MODEL_FROM_DATABASE=MT6227 phone usb:v0E8Dp0004* ID_MODEL_FROM_DATABASE=MT6227 phone usb:v0E8Dp0023* ID_MODEL_FROM_DATABASE=S103 usb:v0E8Dp1806* ID_MODEL_FROM_DATABASE=Samsung SE-208 Slim Portable DVD Writer usb:v0E8Dp1836* ID_MODEL_FROM_DATABASE=Samsung SE-S084 Super WriteMaster Slim External DVD writer usb:v0E8Dp2000* ID_MODEL_FROM_DATABASE=MT65xx Preloader usb:v0E8Dp3329* ID_MODEL_FROM_DATABASE=Qstarz BT-Q1000XT usb:v0E8Dp763E* ID_MODEL_FROM_DATABASE=MT7630e Bluetooth Adapter usb:v0E8F* ID_VENDOR_FROM_DATABASE=GreenAsia Inc. usb:v0E8Fp0003* ID_MODEL_FROM_DATABASE=MaxFire Blaze2 usb:v0E8Fp0012* ID_MODEL_FROM_DATABASE=Joystick/Gamepad usb:v0E8Fp0016* ID_MODEL_FROM_DATABASE=4 port USB 1.1 hub UH-174 usb:v0E8Fp0020* ID_MODEL_FROM_DATABASE=USB to PS/2 Adapter usb:v0E8Fp0021* ID_MODEL_FROM_DATABASE=Multimedia Keyboard Controller usb:v0E8Fp0022* ID_MODEL_FROM_DATABASE=multimedia keyboard controller usb:v0E8Fp0201* ID_MODEL_FROM_DATABASE=SmartJoy Frag Xpad/PS2 adaptor usb:v0E90* ID_VENDOR_FROM_DATABASE=WiebeTech, LLC usb:v0E90p0100* ID_MODEL_FROM_DATABASE=Storage Adapter V1 usb:v0E91* ID_VENDOR_FROM_DATABASE=VTech Engineering Canada, Ltd usb:v0E92* ID_VENDOR_FROM_DATABASE=C's Glory Enterprise Co., Ltd usb:v0E93* ID_VENDOR_FROM_DATABASE=eM Technics Co., Ltd usb:v0E95* ID_VENDOR_FROM_DATABASE=Future Technology Co., Ltd usb:v0E96* ID_VENDOR_FROM_DATABASE=Aplux Communications, Ltd usb:v0E96pC001* ID_MODEL_FROM_DATABASE=TRUST 380 USB2 SPACEC@M usb:v0E97* ID_VENDOR_FROM_DATABASE=Fingerworks, Inc. usb:v0E97p0908* ID_MODEL_FROM_DATABASE=Composite HID (Keyboard and Mouse) usb:v0E98* ID_VENDOR_FROM_DATABASE=Advanced Analogic Technologies, Inc. usb:v0E99* ID_VENDOR_FROM_DATABASE=Parallel Dice Co., Ltd usb:v0E9A* ID_VENDOR_FROM_DATABASE=TA HSING Industries, Ltd usb:v0E9B* ID_VENDOR_FROM_DATABASE=ADTEC Corp. usb:v0E9C* ID_VENDOR_FROM_DATABASE=Streamzap, Inc. usb:v0E9Cp0000* ID_MODEL_FROM_DATABASE=Streamzap Remote Control usb:v0E9F* ID_VENDOR_FROM_DATABASE=Tamura Corp. usb:v0EA0* ID_VENDOR_FROM_DATABASE=Ours Technology, Inc. usb:v0EA0p2126* ID_MODEL_FROM_DATABASE=7-in-1 Card Reader usb:v0EA0p2153* ID_MODEL_FROM_DATABASE=SD Card Reader Key usb:v0EA0p2168* ID_MODEL_FROM_DATABASE=Transcend JetFlash 2.0 / Astone USB Drive / Intellegent Stick 2.0 usb:v0EA0p6803* ID_MODEL_FROM_DATABASE=OTI-6803 Flash Disk usb:v0EA0p6808* ID_MODEL_FROM_DATABASE=OTI-6808 Flash Disk usb:v0EA0p6828* ID_MODEL_FROM_DATABASE=OTI-6828 Flash Disk usb:v0EA0p6858* ID_MODEL_FROM_DATABASE=OTi-6858 serial adapter usb:v0EA6* ID_VENDOR_FROM_DATABASE=Nihon Computer Co., Ltd usb:v0EA7* ID_VENDOR_FROM_DATABASE=MSL Enterprises Corp. usb:v0EA8* ID_VENDOR_FROM_DATABASE=CenDyne, Inc. usb:v0EAD* ID_VENDOR_FROM_DATABASE=Humax Co., Ltd usb:v0EB0* ID_VENDOR_FROM_DATABASE=NovaTech usb:v0EB0p9020* ID_MODEL_FROM_DATABASE=NovaTech NV-902W usb:v0EB0p9021* ID_MODEL_FROM_DATABASE=RT2573 usb:v0EB1* ID_VENDOR_FROM_DATABASE=WIS Technologies, Inc. usb:v0EB1p6666* ID_MODEL_FROM_DATABASE=WinFast WalkieTV TV Loader usb:v0EB1p6668* ID_MODEL_FROM_DATABASE=WinFast WalkieTV TV Loader usb:v0EB1p7007* ID_MODEL_FROM_DATABASE=WinFast WalkieTV WDM Capture usb:v0EB2* ID_VENDOR_FROM_DATABASE=Y-S Electronic Co., Ltd usb:v0EB3* ID_VENDOR_FROM_DATABASE=Saint Technology Corp. usb:v0EB7* ID_VENDOR_FROM_DATABASE=Endor AG usb:v0EB8* ID_VENDOR_FROM_DATABASE=Mettler Toledo usb:v0EB8p2200* ID_MODEL_FROM_DATABASE=Ariva Scale usb:v0EB8pF000* ID_MODEL_FROM_DATABASE=PS60 Scale usb:v0EBB* ID_VENDOR_FROM_DATABASE=Thermo Fisher Scientific usb:v0EBBp0002* ID_MODEL_FROM_DATABASE=FT-IR Spectrometer usb:v0EBE* ID_VENDOR_FROM_DATABASE=VWeb Corp. usb:v0EBF* ID_VENDOR_FROM_DATABASE=Omega Technology of Taiwan, Inc. usb:v0EC0* ID_VENDOR_FROM_DATABASE=LHI Technology (China) Co., Ltd usb:v0EC1* ID_VENDOR_FROM_DATABASE=Abit Computer Corp. usb:v0EC2* ID_VENDOR_FROM_DATABASE=Sweetray Industrial, Ltd usb:v0EC3* ID_VENDOR_FROM_DATABASE=Axell Co., Ltd usb:v0EC4* ID_VENDOR_FROM_DATABASE=Ballracing Developments, Ltd usb:v0EC5* ID_VENDOR_FROM_DATABASE=GT Information System Co., Ltd usb:v0EC6* ID_VENDOR_FROM_DATABASE=InnoVISION Multimedia, Ltd usb:v0EC7* ID_VENDOR_FROM_DATABASE=Theta Link Corp. usb:v0EC7p1008* ID_MODEL_FROM_DATABASE=So., Show 301 Digital Camera usb:v0ECD* ID_VENDOR_FROM_DATABASE=Lite-On IT Corp. usb:v0ECDp1400* ID_MODEL_FROM_DATABASE=CD\RW 40X usb:v0ECDpA100* ID_MODEL_FROM_DATABASE=LDW-411SX DVD/CD Rewritable Drive usb:v0ECE* ID_VENDOR_FROM_DATABASE=TaiSol Electronics Co., Ltd usb:v0ECF* ID_VENDOR_FROM_DATABASE=Phogenix Imaging, LLC usb:v0ED1* ID_VENDOR_FROM_DATABASE=WinMaxGroup usb:v0ED1p6660* ID_MODEL_FROM_DATABASE=Flash Disk 64M-C usb:v0ED1p6680* ID_MODEL_FROM_DATABASE=Flash Disk 64M-B usb:v0ED1p7634* ID_MODEL_FROM_DATABASE=MP3 Player usb:v0ED2* ID_VENDOR_FROM_DATABASE=Kyoto Micro Computer Co., Ltd usb:v0ED3* ID_VENDOR_FROM_DATABASE=Wing-Tech Enterprise Co., Ltd usb:v0ED5* ID_VENDOR_FROM_DATABASE=Fiberbyte usb:v0ED5pE000* ID_MODEL_FROM_DATABASE=USB-inSync Device usb:v0ED5pF000* ID_MODEL_FROM_DATABASE=Fiberbyte USB-inSync Device usb:v0ED5pF201* ID_MODEL_FROM_DATABASE=Fiberbyte USB-inSync DAQ-2500X usb:v0EDA* ID_VENDOR_FROM_DATABASE=Noriake Itron Corp. usb:v0EDF* ID_VENDOR_FROM_DATABASE=e-MDT Co., Ltd usb:v0EDFp2060* ID_MODEL_FROM_DATABASE=FID irock! 100 Series usb:v0EE0* ID_VENDOR_FROM_DATABASE=Shima Seiki Mfg., Ltd usb:v0EE1* ID_VENDOR_FROM_DATABASE=Sarotech Co., Ltd usb:v0EE2* ID_VENDOR_FROM_DATABASE=AMI Semiconductor, Inc. usb:v0EE3* ID_VENDOR_FROM_DATABASE=ComTrue Technology Corp. usb:v0EE3p1000* ID_MODEL_FROM_DATABASE=Image Tank 1.5 usb:v0EE4* ID_VENDOR_FROM_DATABASE=Sunrich Technology, Ltd usb:v0EE4p0690* ID_MODEL_FROM_DATABASE=SATA 3 Adapter usb:v0EEE* ID_VENDOR_FROM_DATABASE=Digital Stream Technology, Inc. usb:v0EEEp8810* ID_MODEL_FROM_DATABASE=Mass Storage Drive usb:v0EEF* ID_VENDOR_FROM_DATABASE=D-WAV Scientific Co., Ltd usb:v0EEFp0001* ID_MODEL_FROM_DATABASE=eGalax TouchScreen usb:v0EEFp0002* ID_MODEL_FROM_DATABASE=Touchscreen Controller(Professional) usb:v0EEFp7200* ID_MODEL_FROM_DATABASE=Touchscreen Controller usb:v0EEFpA802* ID_MODEL_FROM_DATABASE=eGalaxTouch EXC7920 usb:v0EF0* ID_VENDOR_FROM_DATABASE=Hitachi Cable, Ltd usb:v0EF1* ID_VENDOR_FROM_DATABASE=Aichi Micro Intelligent Corp. usb:v0EF2* ID_VENDOR_FROM_DATABASE=I/O Magic Corp. usb:v0EF3* ID_VENDOR_FROM_DATABASE=Lynn Products, Inc. usb:v0EF4* ID_VENDOR_FROM_DATABASE=DSI Datotech usb:v0EF5* ID_VENDOR_FROM_DATABASE=PointChips usb:v0EF5p2202* ID_MODEL_FROM_DATABASE=Flash Disk usb:v0EF5p2366* ID_MODEL_FROM_DATABASE=Flash Disk usb:v0EF6* ID_VENDOR_FROM_DATABASE=Yield Microelectronics Corp. usb:v0EF7* ID_VENDOR_FROM_DATABASE=SM Tech Co., Ltd (Tulip) usb:v0EFD* ID_VENDOR_FROM_DATABASE=Oasis Semiconductor usb:v0EFE* ID_VENDOR_FROM_DATABASE=Wem Technology, Inc. usb:v0F03* ID_VENDOR_FROM_DATABASE=Unitek UPS Systems usb:v0F03p0001* ID_MODEL_FROM_DATABASE=Alpha 1200Sx usb:v0F06* ID_VENDOR_FROM_DATABASE=Visual Frontier Enterprise Co., Ltd usb:v0F08* ID_VENDOR_FROM_DATABASE=CSL Wire & Plug (Shen Zhen) Co. usb:v0F0C* ID_VENDOR_FROM_DATABASE=CAS Corp. usb:v0F0D* ID_VENDOR_FROM_DATABASE=Hori Co., Ltd usb:v0F0Dp0011* ID_MODEL_FROM_DATABASE=Real Arcade Pro 3 usb:v0F0E* ID_VENDOR_FROM_DATABASE=Energy Full Corp. usb:v0F11* ID_VENDOR_FROM_DATABASE=LD Didactic GmbH usb:v0F11p1000* ID_MODEL_FROM_DATABASE=CASSY-S usb:v0F11p1010* ID_MODEL_FROM_DATABASE=Pocket-CASSY usb:v0F11p1020* ID_MODEL_FROM_DATABASE=Mobile-CASSY usb:v0F11p1080* ID_MODEL_FROM_DATABASE=Joule and Wattmeter usb:v0F11p1081* ID_MODEL_FROM_DATABASE=Digital Multimeter P usb:v0F11p1090* ID_MODEL_FROM_DATABASE=UMI P usb:v0F11p1100* ID_MODEL_FROM_DATABASE=X-Ray Apparatus usb:v0F11p1101* ID_MODEL_FROM_DATABASE=X-Ray Apparatus usb:v0F11p1200* ID_MODEL_FROM_DATABASE=VideoCom usb:v0F11p2000* ID_MODEL_FROM_DATABASE=COM3LAB usb:v0F11p2010* ID_MODEL_FROM_DATABASE=Terminal Adapter usb:v0F11p2020* ID_MODEL_FROM_DATABASE=Network Analyser usb:v0F11p2030* ID_MODEL_FROM_DATABASE=Converter Control Unit usb:v0F11p2040* ID_MODEL_FROM_DATABASE=Machine Test System usb:v0F12* ID_VENDOR_FROM_DATABASE=Mars Engineering Corp. usb:v0F13* ID_VENDOR_FROM_DATABASE=Acetek Technology Co., Ltd usb:v0F14* ID_VENDOR_FROM_DATABASE=Ingenico usb:v0F14p0012* ID_MODEL_FROM_DATABASE=Vital'Act 3S usb:v0F18* ID_VENDOR_FROM_DATABASE=Finger Lakes Instrumentation usb:v0F18p0002* ID_MODEL_FROM_DATABASE=CCD usb:v0F18p0006* ID_MODEL_FROM_DATABASE=Focuser usb:v0F18p0007* ID_MODEL_FROM_DATABASE=Filter Wheel usb:v0F18p000A* ID_MODEL_FROM_DATABASE=ProLine CCD usb:v0F18p000B* ID_MODEL_FROM_DATABASE=Color Filter Wheel 4 usb:v0F18p000C* ID_MODEL_FROM_DATABASE=PDF2 usb:v0F18p000D* ID_MODEL_FROM_DATABASE=Guider usb:v0F19* ID_VENDOR_FROM_DATABASE=Oracom Co., Ltd usb:v0F1B* ID_VENDOR_FROM_DATABASE=Onset Computer Corp. usb:v0F1C* ID_VENDOR_FROM_DATABASE=Funai Electric Co., Ltd usb:v0F1D* ID_VENDOR_FROM_DATABASE=Iwill Corp. usb:v0F21* ID_VENDOR_FROM_DATABASE=IOI Technology Corp. usb:v0F22* ID_VENDOR_FROM_DATABASE=Senior Industries, Inc. usb:v0F23* ID_VENDOR_FROM_DATABASE=Leader Tech Manufacturer Co., Ltd usb:v0F24* ID_VENDOR_FROM_DATABASE=Flex-P Industries, Snd., Bhd. usb:v0F2D* ID_VENDOR_FROM_DATABASE=ViPower, Inc. usb:v0F2E* ID_VENDOR_FROM_DATABASE=Geniality Maple Technology Co., Ltd usb:v0F2F* ID_VENDOR_FROM_DATABASE=Priva Design Services usb:v0F30* ID_VENDOR_FROM_DATABASE=Jess Technology Co., Ltd usb:v0F30p001C* ID_MODEL_FROM_DATABASE=PS3 Guitar Controller Dongle usb:v0F30p0110* ID_MODEL_FROM_DATABASE=Dual Analog Rumble Pad usb:v0F30p0111* ID_MODEL_FROM_DATABASE=Colour Rumble Pad usb:v0F30p0208* ID_MODEL_FROM_DATABASE=Xbox & PC Gamepad usb:v0F31* ID_VENDOR_FROM_DATABASE=Chrysalis Development usb:v0F32* ID_VENDOR_FROM_DATABASE=YFC-BonEagle Electric Co., Ltd usb:v0F37* ID_VENDOR_FROM_DATABASE=Kokuyo Co., Ltd usb:v0F38* ID_VENDOR_FROM_DATABASE=Nien-Yi Industrial Corp. usb:v0F39* ID_VENDOR_FROM_DATABASE=TG3 Electronics usb:v0F39p0876* ID_MODEL_FROM_DATABASE=Keyboard [87 Francium Pro] usb:v0F39p1086* ID_MODEL_FROM_DATABASE=DK2108SZ Keyboard [Ducky Zero] usb:v0F3D* ID_VENDOR_FROM_DATABASE=Airprime, Incorporated usb:v0F3Dp0112* ID_MODEL_FROM_DATABASE=CDMA 1xEVDO PC Card, PC 5220 usb:v0F41* ID_VENDOR_FROM_DATABASE=RDC Semiconductor Co., Ltd usb:v0F42* ID_VENDOR_FROM_DATABASE=Nital Consulting Services, Inc. usb:v0F44* ID_VENDOR_FROM_DATABASE=Polhemus usb:v0F44pEF11* ID_MODEL_FROM_DATABASE=Patriot (firmware not loaded) usb:v0F44pEF12* ID_MODEL_FROM_DATABASE=Patriot usb:v0F44pFF11* ID_MODEL_FROM_DATABASE=Liberty (firmware not loaded) usb:v0F44pFF12* ID_MODEL_FROM_DATABASE=Liberty usb:v0F4B* ID_VENDOR_FROM_DATABASE=St. John Technology Co., Ltd usb:v0F4C* ID_VENDOR_FROM_DATABASE=WorldWide Cable Opto Corp. usb:v0F4D* ID_VENDOR_FROM_DATABASE=Microtune, Inc. usb:v0F4Dp1000* ID_MODEL_FROM_DATABASE=Bluetooth Dongle usb:v0F4E* ID_VENDOR_FROM_DATABASE=Freedom Scientific usb:v0F52* ID_VENDOR_FROM_DATABASE=Wing Key Electrical Co., Ltd usb:v0F53* ID_VENDOR_FROM_DATABASE=Dongguan White Horse Cable Factory, Ltd usb:v0F54* ID_VENDOR_FROM_DATABASE=Kawai Musical Instruments Mfg. Co., Ltd usb:v0F54p0101* ID_MODEL_FROM_DATABASE=MP6 Stage Piano usb:v0F55* ID_VENDOR_FROM_DATABASE=AmbiCom, Inc. usb:v0F5C* ID_VENDOR_FROM_DATABASE=Prairiecomm, Inc. usb:v0F5D* ID_VENDOR_FROM_DATABASE=NewAge International, LLC usb:v0F5Dp9455* ID_MODEL_FROM_DATABASE=Compact Drive usb:v0F5F* ID_VENDOR_FROM_DATABASE=Key Technology Corp. usb:v0F60* ID_VENDOR_FROM_DATABASE=NTK, Ltd usb:v0F61* ID_VENDOR_FROM_DATABASE=Varian, Inc. usb:v0F62* ID_VENDOR_FROM_DATABASE=Acrox Technologies Co., Ltd usb:v0F62p1001* ID_MODEL_FROM_DATABASE=Targus Mini Trackball Optical Mouse usb:v0F63* ID_VENDOR_FROM_DATABASE=LeapFrog Enterprises usb:v0F63p0010* ID_MODEL_FROM_DATABASE=Leapster Explorer usb:v0F63p0022* ID_MODEL_FROM_DATABASE=Leap Reader usb:v0F63p0500* ID_MODEL_FROM_DATABASE=Fly Fusion usb:v0F63p0600* ID_MODEL_FROM_DATABASE=Leap Port Turbo usb:v0F63p0700* ID_MODEL_FROM_DATABASE=POGO usb:v0F63p0800* ID_MODEL_FROM_DATABASE=Didj usb:v0F63p0900* ID_MODEL_FROM_DATABASE=TAGSchool usb:v0F63p0A00* ID_MODEL_FROM_DATABASE=Leapster 2 usb:v0F63p0B00* ID_MODEL_FROM_DATABASE=Crammer usb:v0F63p0C00* ID_MODEL_FROM_DATABASE=Tag Jr usb:v0F63p0D00* ID_MODEL_FROM_DATABASE=My Pal Scout usb:v0F63p0E00* ID_MODEL_FROM_DATABASE=Tag32 usb:v0F63p0F00* ID_MODEL_FROM_DATABASE=Tag64 usb:v0F63p1000* ID_MODEL_FROM_DATABASE=Kiwi16 usb:v0F63p1100* ID_MODEL_FROM_DATABASE=Leapster L2x usb:v0F63p1111* ID_MODEL_FROM_DATABASE=Fly Fusion usb:v0F63p1300* ID_MODEL_FROM_DATABASE=Didj UK/France (Leapster Advance) usb:v0F68* ID_VENDOR_FROM_DATABASE=Kobe Steel, Ltd usb:v0F69* ID_VENDOR_FROM_DATABASE=Dionex Corp. usb:v0F6A* ID_VENDOR_FROM_DATABASE=Vibren Technologies, Inc. usb:v0F6E* ID_VENDOR_FROM_DATABASE=INTELLIGENT SYSTEMS usb:v0F6Ep0100* ID_MODEL_FROM_DATABASE=GameBoy Color Emulator usb:v0F6Ep0201* ID_MODEL_FROM_DATABASE=GameBoy Advance Flash Gang Writer usb:v0F6Ep0202* ID_MODEL_FROM_DATABASE=GameBoy Advance Capture usb:v0F6Ep0300* ID_MODEL_FROM_DATABASE=Gamecube DOL Viewer usb:v0F6Ep0400* ID_MODEL_FROM_DATABASE=NDS Emulator usb:v0F6Ep0401* ID_MODEL_FROM_DATABASE=NDS UIC usb:v0F6Ep0402* ID_MODEL_FROM_DATABASE=NDS Writer usb:v0F6Ep0403* ID_MODEL_FROM_DATABASE=NDS Capture usb:v0F6Ep0404* ID_MODEL_FROM_DATABASE=NDS Emulator (Lite) usb:v0F73* ID_VENDOR_FROM_DATABASE=DFI usb:v0F78* ID_VENDOR_FROM_DATABASE=Guntermann & Drunck GmbH usb:v0F7C* ID_VENDOR_FROM_DATABASE=DQ Technology, Inc. usb:v0F7D* ID_VENDOR_FROM_DATABASE=NetBotz, Inc. usb:v0F7E* ID_VENDOR_FROM_DATABASE=Fluke Corp. usb:v0F88* ID_VENDOR_FROM_DATABASE=VTech Holdings, Ltd usb:v0F88p3012* ID_MODEL_FROM_DATABASE=RT2570 usb:v0F88p3014* ID_MODEL_FROM_DATABASE=ZD1211B usb:v0F8B* ID_VENDOR_FROM_DATABASE=Yazaki Corp. usb:v0F8C* ID_VENDOR_FROM_DATABASE=Young Generation International Corp. usb:v0F8D* ID_VENDOR_FROM_DATABASE=Uniwill Computer Corp. usb:v0F8E* ID_VENDOR_FROM_DATABASE=Kingnet Technology Co., Ltd usb:v0F8F* ID_VENDOR_FROM_DATABASE=Soma Networks usb:v0F97* ID_VENDOR_FROM_DATABASE=CviLux Corp. usb:v0F98* ID_VENDOR_FROM_DATABASE=CyberBank Corp. usb:v0F9C* ID_VENDOR_FROM_DATABASE=Hyun Won, Inc. usb:v0F9Cp0301* ID_MODEL_FROM_DATABASE=M-Any Premium DAH-610 MP3/WMA Player usb:v0F9Cp0332* ID_MODEL_FROM_DATABASE=mobiBLU DAH-1200 MP3/Ogg Player usb:v0F9E* ID_VENDOR_FROM_DATABASE=Lucent Technologies usb:v0FA3* ID_VENDOR_FROM_DATABASE=Starconn Electronic Co., Ltd usb:v0FA4* ID_VENDOR_FROM_DATABASE=ATL Technology usb:v0FA5* ID_VENDOR_FROM_DATABASE=Sotec Co., Ltd usb:v0FA7* ID_VENDOR_FROM_DATABASE=Epox Computer Co., Ltd usb:v0FA8* ID_VENDOR_FROM_DATABASE=Logic Controls, Inc. usb:v0FAF* ID_VENDOR_FROM_DATABASE=Winpoint Electronic Corp. usb:v0FB0* ID_VENDOR_FROM_DATABASE=Haurtian Wire & Cable Co., Ltd usb:v0FB1* ID_VENDOR_FROM_DATABASE=Inclose Design, Inc. usb:v0FB2* ID_VENDOR_FROM_DATABASE=Juan-Chern Industrial Co., Ltd usb:v0FB6* ID_VENDOR_FROM_DATABASE=Heber Ltd usb:v0FB6p3FC3* ID_MODEL_FROM_DATABASE=Firefly X10i I/O Board (with firmware) usb:v0FB6p3FC4* ID_MODEL_FROM_DATABASE=Firefly X10i I/O Board (without firmware) usb:v0FB8* ID_VENDOR_FROM_DATABASE=Wistron Corp. usb:v0FB8p0002* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v0FB9* ID_VENDOR_FROM_DATABASE=AACom Corp. usb:v0FBA* ID_VENDOR_FROM_DATABASE=San Shing Electronics Co., Ltd usb:v0FBB* ID_VENDOR_FROM_DATABASE=Bitwise Systems, Inc. usb:v0FC1* ID_VENDOR_FROM_DATABASE=Mitac Internatinal Corp. usb:v0FC2* ID_VENDOR_FROM_DATABASE=Plug and Jack Industrial, Inc. usb:v0FC5* ID_VENDOR_FROM_DATABASE=Delcom Engineering usb:v0FC5p1222* ID_MODEL_FROM_DATABASE=I/O Development Board usb:v0FC6* ID_VENDOR_FROM_DATABASE=Dataplus Supplies, Inc. usb:v0FCA* ID_VENDOR_FROM_DATABASE=Research In Motion, Ltd. usb:v0FCAp0001* ID_MODEL_FROM_DATABASE=Blackberry Handheld usb:v0FCAp0004* ID_MODEL_FROM_DATABASE=Blackberry Handheld usb:v0FCAp0006* ID_MODEL_FROM_DATABASE=Blackberry Pearl usb:v0FCAp0008* ID_MODEL_FROM_DATABASE=Blackberry Pearl usb:v0FCAp8001* ID_MODEL_FROM_DATABASE=Blackberry Handheld usb:v0FCAp8004* ID_MODEL_FROM_DATABASE=Blackberry usb:v0FCAp8007* ID_MODEL_FROM_DATABASE=Blackberry Handheld usb:v0FCAp8010* ID_MODEL_FROM_DATABASE=Blackberry Playbook (Connect to Windows mode) usb:v0FCAp8011* ID_MODEL_FROM_DATABASE=Blackberry Playbook (Connect to Mac mode) usb:v0FCAp8020* ID_MODEL_FROM_DATABASE=Blackberry Playbook (CD-Rom mode) usb:v0FCE* ID_VENDOR_FROM_DATABASE=Sony Ericsson Mobile Communications AB usb:v0FCEp0076* ID_MODEL_FROM_DATABASE=W910i (Multimedia mode) usb:v0FCEp00AF* ID_MODEL_FROM_DATABASE=V640i Phone [PTP Camera] usb:v0FCEp00D4* ID_MODEL_FROM_DATABASE=C902 [MTP] usb:v0FCEp00D9* ID_MODEL_FROM_DATABASE=C702 Phone usb:v0FCEp0112* ID_MODEL_FROM_DATABASE=W995 Walkman Phone usb:v0FCEp014E* ID_MODEL_FROM_DATABASE=J108i Cedar (MTP mode) usb:v0FCEp015A* ID_MODEL_FROM_DATABASE=Xperia Pro [Media Transfer Protocol] usb:v0FCEp0166* ID_MODEL_FROM_DATABASE=Xperia Mini Pro usb:v0FCEp0167* ID_MODEL_FROM_DATABASE=ST15i (Xperia mini) usb:v0FCEp0169* ID_MODEL_FROM_DATABASE=Xperia S usb:v0FCEp0172* ID_MODEL_FROM_DATABASE=Xperia P usb:v0FCEp0177* ID_MODEL_FROM_DATABASE=Xperia Ion [Mass Storage] usb:v0FCEp01BB* ID_MODEL_FROM_DATABASE=D5803 [Xperia Z3 Compact] (MTP mode) usb:v0FCEp0DDE* ID_MODEL_FROM_DATABASE=Xperia Mini Pro Bootloader usb:v0FCEp1010* ID_MODEL_FROM_DATABASE=WMC Modem usb:v0FCEp10AF* ID_MODEL_FROM_DATABASE=V640i Phone [PictBridge] usb:v0FCEp10D4* ID_MODEL_FROM_DATABASE=C902 Phone [PictBridge] usb:v0FCEp2105* ID_MODEL_FROM_DATABASE=W715 Phone usb:v0FCEp2137* ID_MODEL_FROM_DATABASE=Xperia X10 mini (USB debug) usb:v0FCEp2138* ID_MODEL_FROM_DATABASE=Xperia X10 mini pro (Debug) usb:v0FCEp2149* ID_MODEL_FROM_DATABASE=Xperia X8 (debug) usb:v0FCEp214E* ID_MODEL_FROM_DATABASE=J108i Cedar (Windows-driver mode) usb:v0FCEp3137* ID_MODEL_FROM_DATABASE=Xperia X10 mini usb:v0FCEp3138* ID_MODEL_FROM_DATABASE=Xperia X10 mini pro usb:v0FCEp3149* ID_MODEL_FROM_DATABASE=Xperia X8 usb:v0FCEp514F* ID_MODEL_FROM_DATABASE=Xperia arc S [Adb-Enable Mode] usb:v0FCEp5169* ID_MODEL_FROM_DATABASE=Xperia S [Adb-Enable Mode] usb:v0FCEp5177* ID_MODEL_FROM_DATABASE=Xperia Ion [Debug Mode] usb:v0FCEp518C* ID_MODEL_FROM_DATABASE=C1605 [Xperia E dual] MTD mode usb:v0FCEp614F* ID_MODEL_FROM_DATABASE=Xperia X12 (debug mode) usb:v0FCEp6166* ID_MODEL_FROM_DATABASE=Xperia Mini Pro usb:v0FCEp618C* ID_MODEL_FROM_DATABASE=C1605 [Xperia E dual] MSC mode usb:v0FCEp715A* ID_MODEL_FROM_DATABASE=Xperia Pro [Tethering] usb:v0FCEp7166* ID_MODEL_FROM_DATABASE=Xperia Mini Pro (Tethering mode) usb:v0FCEp7177* ID_MODEL_FROM_DATABASE=Xperia Ion [Tethering] usb:v0FCEp8004* ID_MODEL_FROM_DATABASE=9000 Phone [Mass Storage] usb:v0FCEpADDE* ID_MODEL_FROM_DATABASE=C2005 (Xperia M dual) in service mode usb:v0FCEpD008* ID_MODEL_FROM_DATABASE=V800-Vodafone 802SE Phone usb:v0FCEpD016* ID_MODEL_FROM_DATABASE=K750i Phone usb:v0FCEpD017* ID_MODEL_FROM_DATABASE=K608i Phone usb:v0FCEpD019* ID_MODEL_FROM_DATABASE=VDC EGPRS Modem usb:v0FCEpD025* ID_MODEL_FROM_DATABASE=520 WMC Data Modem usb:v0FCEpD028* ID_MODEL_FROM_DATABASE=W800i usb:v0FCEpD038* ID_MODEL_FROM_DATABASE=W850i Phone usb:v0FCEpD039* ID_MODEL_FROM_DATABASE=K800i (phone mode) usb:v0FCEpD041* ID_MODEL_FROM_DATABASE=K510i Phone usb:v0FCEpD042* ID_MODEL_FROM_DATABASE=W810i Phone usb:v0FCEpD043* ID_MODEL_FROM_DATABASE=V630i Phone usb:v0FCEpD046* ID_MODEL_FROM_DATABASE=K610i Phone usb:v0FCEpD065* ID_MODEL_FROM_DATABASE=W960i Phone (PC Suite) usb:v0FCEpD076* ID_MODEL_FROM_DATABASE=W910i (Phone mode) usb:v0FCEpD089* ID_MODEL_FROM_DATABASE=W580i Phone (mass storage) usb:v0FCEpD0A1* ID_MODEL_FROM_DATABASE=K810 usb:v0FCEpD0AF* ID_MODEL_FROM_DATABASE=V640i Phone usb:v0FCEpD0CF* ID_MODEL_FROM_DATABASE=MD300 Mobile Broadband Modem usb:v0FCEpD0D4* ID_MODEL_FROM_DATABASE=C902 Phone [Modem] usb:v0FCEpD0E1* ID_MODEL_FROM_DATABASE=MD400 Mobile Broadband Modem usb:v0FCEpD12A* ID_MODEL_FROM_DATABASE=U100i Yari Phone usb:v0FCEpD12E* ID_MODEL_FROM_DATABASE=Xperia X10 usb:v0FCEpD14E* ID_MODEL_FROM_DATABASE=J108i Cedar (modem mode) usb:v0FCEpE000* ID_MODEL_FROM_DATABASE=K810 (PictBridge mode) usb:v0FCEpE039* ID_MODEL_FROM_DATABASE=K800i (msc mode) usb:v0FCEpE042* ID_MODEL_FROM_DATABASE=W810i Phone usb:v0FCEpE043* ID_MODEL_FROM_DATABASE=V630i Phone [Mass Storage] usb:v0FCEpE075* ID_MODEL_FROM_DATABASE=K850i usb:v0FCEpE076* ID_MODEL_FROM_DATABASE=W910i (Mass storage) usb:v0FCEpE089* ID_MODEL_FROM_DATABASE=W580i Phone usb:v0FCEpE090* ID_MODEL_FROM_DATABASE=W200 Phone (Mass Storage) usb:v0FCEpE0A1* ID_MODEL_FROM_DATABASE=K810 (Mass Storage mode) usb:v0FCEpE0A3* ID_MODEL_FROM_DATABASE=W660i usb:v0FCEpE0AF* ID_MODEL_FROM_DATABASE=V640i Phone [Mass Storage] usb:v0FCEpE0D4* ID_MODEL_FROM_DATABASE=C902 Phone [Mass Storage] usb:v0FCEpE0EF* ID_MODEL_FROM_DATABASE=C905 Phone [Mass Storage] usb:v0FCEpE0F3* ID_MODEL_FROM_DATABASE=W595 usb:v0FCEpE105* ID_MODEL_FROM_DATABASE=W705 usb:v0FCEpE112* ID_MODEL_FROM_DATABASE=W995 Phone (Mass Storage) usb:v0FCEpE12E* ID_MODEL_FROM_DATABASE=X10i Phone usb:v0FCEpE133* ID_MODEL_FROM_DATABASE=Vivaz usb:v0FCEpE14E* ID_MODEL_FROM_DATABASE=J108i Cedar (mass-storage mode) usb:v0FCEpE14F* ID_MODEL_FROM_DATABASE=Xperia Arc/X12 usb:v0FCEpE15A* ID_MODEL_FROM_DATABASE=Xperia Pro [Mass Storage Class] usb:v0FCEpE161* ID_MODEL_FROM_DATABASE=Xperia Ray usb:v0FCEpE166* ID_MODEL_FROM_DATABASE=Xperia Mini Pro usb:v0FCEpE167* ID_MODEL_FROM_DATABASE=XPERIA mini usb:v0FCEpE19B* ID_MODEL_FROM_DATABASE=C2005 [Xperia M dual] (Mass Storage) usb:v0FCEpF0FA* ID_MODEL_FROM_DATABASE=MN800 / Smartwatch 2 (DFU mode) usb:v0FCF* ID_VENDOR_FROM_DATABASE=Dynastream Innovations, Inc. usb:v0FCFp1003* ID_MODEL_FROM_DATABASE=ANT Development Board usb:v0FCFp1004* ID_MODEL_FROM_DATABASE=ANTUSB Stick usb:v0FCFp1006* ID_MODEL_FROM_DATABASE=ANT Development Board usb:v0FCFp1008* ID_MODEL_FROM_DATABASE=ANTUSB2 Stick usb:v0FCFp1009* ID_MODEL_FROM_DATABASE=ANTUSB-m Stick usb:v0FD0* ID_VENDOR_FROM_DATABASE=Tulip Computers B.V. usb:v0FD1* ID_VENDOR_FROM_DATABASE=Giant Electronics Ltd. usb:v0FD2* ID_VENDOR_FROM_DATABASE=Seac Banche usb:v0FD2p0001* ID_MODEL_FROM_DATABASE=RDS 6000 usb:v0FD4* ID_VENDOR_FROM_DATABASE=Tenovis GmbH & Co., KG usb:v0FD5* ID_VENDOR_FROM_DATABASE=Direct Access Technology, Inc. usb:v0FD9* ID_VENDOR_FROM_DATABASE=Elgato Systems GmbH usb:v0FD9p0011* ID_MODEL_FROM_DATABASE=EyeTV Diversity usb:v0FD9p0018* ID_MODEL_FROM_DATABASE=EyeTV Hybrid usb:v0FD9p0020* ID_MODEL_FROM_DATABASE=EyeTV DTT Deluxe usb:v0FD9p0021* ID_MODEL_FROM_DATABASE=EyeTV DTT usb:v0FD9p002A* ID_MODEL_FROM_DATABASE=EyeTV Sat usb:v0FD9p002C* ID_MODEL_FROM_DATABASE=EyeTV DTT Deluxe v2 usb:v0FD9p0033* ID_MODEL_FROM_DATABASE=Video Capture usb:v0FD9p0037* ID_MODEL_FROM_DATABASE=Video Capture v2 usb:v0FDA* ID_VENDOR_FROM_DATABASE=Quantec Networks GmbH usb:v0FDAp0100* ID_MODEL_FROM_DATABASE=quanton flight control usb:v0FDC* ID_VENDOR_FROM_DATABASE=Micro Plus usb:v0FDE* ID_VENDOR_FROM_DATABASE=Oregon Scientific usb:v0FDEpCA01* ID_MODEL_FROM_DATABASE=WMRS200 weather station usb:v0FDEpCA05* ID_MODEL_FROM_DATABASE=CM160 usb:v0FE0* ID_VENDOR_FROM_DATABASE=Osterhout Design Group usb:v0FE0p0100* ID_MODEL_FROM_DATABASE=Bluetooth Mouse usb:v0FE0p0101* ID_MODEL_FROM_DATABASE=Bluetooth IMU usb:v0FE0p0200* ID_MODEL_FROM_DATABASE=Bluetooth Keypad usb:v0FE4* ID_VENDOR_FROM_DATABASE=IN-Tech Electronics, Ltd usb:v0FE5* ID_VENDOR_FROM_DATABASE=Greenconn (U.S.A.), Inc. usb:v0FE6* ID_VENDOR_FROM_DATABASE=Kontron (Industrial Computer Source / ICS Advent) usb:v0FE6p8101* ID_MODEL_FROM_DATABASE=DM9601 Fast Ethernet Adapter usb:v0FE6p811E* ID_MODEL_FROM_DATABASE=Parallel Adapter usb:v0FE6p9700* ID_MODEL_FROM_DATABASE=DM9601 Fast Ethernet Adapter usb:v0FE9* ID_VENDOR_FROM_DATABASE=DVICO usb:v0FE9p4020* ID_MODEL_FROM_DATABASE=TViX M-6500 usb:v0FE9pDB00* ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T (MT352+LgZ201) (uninitialized) usb:v0FE9pDB01* ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T (MT352+LgZ201) (initialized) usb:v0FE9pDB10* ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T (MT352+Thomson7579) (uninitialized) usb:v0FE9pDB11* ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T (MT352+Thomson7579) (initialized) usb:v0FE9pDB78* ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T Dual Digital 4 (ZL10353+xc2028/xc3028) (initialized) usb:v0FEA* ID_VENDOR_FROM_DATABASE=United Computer Accessories usb:v0FEB* ID_VENDOR_FROM_DATABASE=CRS Electronic Co., Ltd usb:v0FEC* ID_VENDOR_FROM_DATABASE=UMC Electronics Co., Ltd usb:v0FED* ID_VENDOR_FROM_DATABASE=Access Co., Ltd usb:v0FEE* ID_VENDOR_FROM_DATABASE=Xsido Corp. usb:v0FEF* ID_VENDOR_FROM_DATABASE=MJ Research, Inc. usb:v0FF6* ID_VENDOR_FROM_DATABASE=Core Valley Co., Ltd usb:v0FF7* ID_VENDOR_FROM_DATABASE=CHI SHING Computer Accessories Co., Ltd usb:v0FFC* ID_VENDOR_FROM_DATABASE=Clavia DMI AB usb:v0FFCp0021* ID_MODEL_FROM_DATABASE=Nord Stage 2 usb:v0FFD* ID_VENDOR_FROM_DATABASE=EarlySense usb:v0FFDpFF00* ID_MODEL_FROM_DATABASE=OEM usb:v0FFF* ID_VENDOR_FROM_DATABASE=Aopen, Inc. usb:v1000* ID_VENDOR_FROM_DATABASE=Speed Tech Corp. usb:v1000p153B* ID_MODEL_FROM_DATABASE=TerraTec Electronic GmbH usb:v1001* ID_VENDOR_FROM_DATABASE=Ritronics Components (S) Pte., Ltd usb:v1003* ID_VENDOR_FROM_DATABASE=Sigma Corp. usb:v1003p0003* ID_MODEL_FROM_DATABASE=SD14 usb:v1003p0100* ID_MODEL_FROM_DATABASE=SD9/SD10 usb:v1004* ID_VENDOR_FROM_DATABASE=LG Electronics, Inc. usb:v1004p1FAE* ID_MODEL_FROM_DATABASE=U8120 3G Cellphone usb:v1004p6000* ID_MODEL_FROM_DATABASE=Various Mobile Phones usb:v1004p6005* ID_MODEL_FROM_DATABASE=T5100 usb:v1004p6018* ID_MODEL_FROM_DATABASE=GM360/GD510/GW520/KP501 usb:v1004p618E* ID_MODEL_FROM_DATABASE=Ally/Optimus One/Vortex (debug mode) usb:v1004p618F* ID_MODEL_FROM_DATABASE=Ally/Optimus One usb:v1004p61C5* ID_MODEL_FROM_DATABASE=P880 / Charge only usb:v1004p61C6* ID_MODEL_FROM_DATABASE=Vortex (msc) usb:v1004p61CC* ID_MODEL_FROM_DATABASE=Optimus S usb:v1004p61DA* ID_MODEL_FROM_DATABASE=G2 Android Phone [tethering mode] usb:v1004p61F1* ID_MODEL_FROM_DATABASE=Optimus Android Phone [LG Software mode] usb:v1004p61F9* ID_MODEL_FROM_DATABASE=Optimus (Various Models) MTP Mode usb:v1004p61FC* ID_MODEL_FROM_DATABASE=Optimus 3 usb:v1004p61FE* ID_MODEL_FROM_DATABASE=Optimus Android Phone [USB tethering mode] usb:v1004p6300* ID_MODEL_FROM_DATABASE=G2/Optimus Android Phone usb:v1004p631C* ID_MODEL_FROM_DATABASE=G2/Optimus Android Phone [MTP mode] usb:v1004p631D* ID_MODEL_FROM_DATABASE=Optimus Android Phone (Camera/PTP Mode) usb:v1004p631E* ID_MODEL_FROM_DATABASE=G2/Optimus Android Phone [Camera/PTP mode] usb:v1004p631F* ID_MODEL_FROM_DATABASE=Optimus Android Phone (Charge Mode) usb:v1004p633E* ID_MODEL_FROM_DATABASE=G2 Android Phone [MTP mode] usb:v1004p6344* ID_MODEL_FROM_DATABASE=G2 Android Phone [tethering mode] usb:v1004p6356* ID_MODEL_FROM_DATABASE=Optimus Android Phone [Virtual CD mode] usb:v1004p6800* ID_MODEL_FROM_DATABASE=CDMA Modem usb:v1004p7000* ID_MODEL_FROM_DATABASE=LG LDP-7024D(LD)USB usb:v1004p91C8* ID_MODEL_FROM_DATABASE=P880 / USB tethering usb:v1004pA400* ID_MODEL_FROM_DATABASE=Renoir (KC910) usb:v1005* ID_VENDOR_FROM_DATABASE=Apacer Technology, Inc. usb:v1005p1001* ID_MODEL_FROM_DATABASE=MP3 Player usb:v1005p1004* ID_MODEL_FROM_DATABASE=MP3 Player usb:v1005p1006* ID_MODEL_FROM_DATABASE=MP3 Player usb:v1005pB113* ID_MODEL_FROM_DATABASE=Handy Steno/AH123 / Handy Steno 2.0/HT203 usb:v1005pB223* ID_MODEL_FROM_DATABASE=CD-RW + 6in1 Card Reader Digital Storage / Converter usb:v1006* ID_VENDOR_FROM_DATABASE=iRiver, Ltd. usb:v1006p3001* ID_MODEL_FROM_DATABASE=iHP-100 usb:v1006p3002* ID_MODEL_FROM_DATABASE=iHP-120/140 MP3 Player usb:v1006p3003* ID_MODEL_FROM_DATABASE=H320/H340 usb:v1006p3004* ID_MODEL_FROM_DATABASE=H340 (mtp) usb:v1009* ID_VENDOR_FROM_DATABASE=Emuzed, Inc. usb:v1009p000E* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v1009p0013* ID_MODEL_FROM_DATABASE=Angel MPEG Device usb:v1009p0015* ID_MODEL_FROM_DATABASE=Lumanate Wave PAL SECAM DVBT Device usb:v1009p0016* ID_MODEL_FROM_DATABASE=Lumanate Wave NTSC/ATSC Combo Device usb:v100A* ID_VENDOR_FROM_DATABASE=AV Chaseway, Ltd usb:v100Ap2402* ID_MODEL_FROM_DATABASE=MP3 Player usb:v100Ap2404* ID_MODEL_FROM_DATABASE=MP3 Player usb:v100Ap2405* ID_MODEL_FROM_DATABASE=MP3 Player usb:v100Ap2406* ID_MODEL_FROM_DATABASE=MP3 Player usb:v100ApA0C0* ID_MODEL_FROM_DATABASE=MP3 Player usb:v100B* ID_VENDOR_FROM_DATABASE=Chou Chin Industrial Co., Ltd usb:v100D* ID_VENDOR_FROM_DATABASE=Netopia, Inc. usb:v100Dp3342* ID_MODEL_FROM_DATABASE=Cayman 3352 DSL Modem usb:v100Dp3382* ID_MODEL_FROM_DATABASE=3380 Series Network Interface usb:v100Dp6072* ID_MODEL_FROM_DATABASE=DSL Modem usb:v100Dp9031* ID_MODEL_FROM_DATABASE=Motorola 802.11n Dualband USB Wireless Adapter usb:v100Dp9032* ID_MODEL_FROM_DATABASE=Motorola 802.11n 5G USB Wireless Adapter usb:v100DpCB01* ID_MODEL_FROM_DATABASE=Cayman 3341 Ethernet DSL Router usb:v1010* ID_VENDOR_FROM_DATABASE=Fukuda Denshi Co., Ltd usb:v1011* ID_VENDOR_FROM_DATABASE=Mobile Media Tech. usb:v1011p0001* ID_MODEL_FROM_DATABASE=AccFast Mp3 usb:v1012* ID_VENDOR_FROM_DATABASE=SDKM Fibres, Wires & Cables Berhad usb:v1013* ID_VENDOR_FROM_DATABASE=TST-Touchless Sensor Technology AG usb:v1014* ID_VENDOR_FROM_DATABASE=Densitron Technologies PLC usb:v1015* ID_VENDOR_FROM_DATABASE=Softronics Pty., Ltd usb:v1016* ID_VENDOR_FROM_DATABASE=Xiamen Hung's Enterprise Co., Ltd usb:v1017* ID_VENDOR_FROM_DATABASE=Speedy Industrial Supplies, Pte., Ltd usb:v1019* ID_VENDOR_FROM_DATABASE=Elitegroup Computer Systems (ECS) usb:v1019p0C55* ID_MODEL_FROM_DATABASE=Flash Reader, Desknote UCR-61S2B usb:v1019p0F38* ID_MODEL_FROM_DATABASE=Infrared Receiver usb:v1020* ID_VENDOR_FROM_DATABASE=Labtec usb:v1020p0006* ID_MODEL_FROM_DATABASE=Wireless Keyboard usb:v1020p000A* ID_MODEL_FROM_DATABASE=Wireless Optical Mouse usb:v1020p0106* ID_MODEL_FROM_DATABASE=Wireless Optical Mouse usb:v1022* ID_VENDOR_FROM_DATABASE=Shinko Shoji Co., Ltd usb:v1025* ID_VENDOR_FROM_DATABASE=Hyper-Paltek usb:v1025p005E* ID_MODEL_FROM_DATABASE=USB DVB-T device usb:v1025p005F* ID_MODEL_FROM_DATABASE=USB DVB-T device usb:v1025p0300* ID_MODEL_FROM_DATABASE=MP3 Player usb:v1025p0350* ID_MODEL_FROM_DATABASE=MP3 Player usb:v1026* ID_VENDOR_FROM_DATABASE=Newly Corp. usb:v1027* ID_VENDOR_FROM_DATABASE=Time Domain usb:v1028* ID_VENDOR_FROM_DATABASE=Inovys Corp. usb:v1029* ID_VENDOR_FROM_DATABASE=Atlantic Coast Telesys usb:v102A* ID_VENDOR_FROM_DATABASE=Ramos Technology Co., Ltd usb:v102B* ID_VENDOR_FROM_DATABASE=Infotronic America, Inc. usb:v102C* ID_VENDOR_FROM_DATABASE=Etoms Electronics Corp. usb:v102Cp6151* ID_MODEL_FROM_DATABASE=Q-Cam Sangha CIF usb:v102Cp6251* ID_MODEL_FROM_DATABASE=Q-Cam VGA usb:v102D* ID_VENDOR_FROM_DATABASE=Winic Corp. usb:v1031* ID_VENDOR_FROM_DATABASE=Comax Technology, Inc. usb:v1032* ID_VENDOR_FROM_DATABASE=C-One Technology Corp. usb:v1033* ID_VENDOR_FROM_DATABASE=Nucam Corp. usb:v1033p0068* ID_MODEL_FROM_DATABASE=3,5'' HDD case MD-231 usb:v1038* ID_VENDOR_FROM_DATABASE=SteelSeries ApS usb:v1038p0100* ID_MODEL_FROM_DATABASE=Ideazon Zboard usb:v1038p1361* ID_MODEL_FROM_DATABASE=Ideazon Sensei usb:v1039* ID_VENDOR_FROM_DATABASE=devolo AG usb:v1039p0824* ID_MODEL_FROM_DATABASE=1866 802.11bg [Texas Instruments TNETW1450] usb:v1039p2140* ID_MODEL_FROM_DATABASE=dsl+ 1100 duo usb:v103A* ID_VENDOR_FROM_DATABASE=PSA usb:v103ApF000* ID_MODEL_FROM_DATABASE=Actia Evo XS usb:v103D* ID_VENDOR_FROM_DATABASE=Stanton usb:v103Dp0100* ID_MODEL_FROM_DATABASE=ScratchAmp usb:v103Dp0101* ID_MODEL_FROM_DATABASE=ScratchAmp usb:v1043* ID_VENDOR_FROM_DATABASE=iCreate Technologies Corp. usb:v1043p160F* ID_MODEL_FROM_DATABASE=Wireless Network Adapter usb:v1043p4901* ID_MODEL_FROM_DATABASE=AV-836 Video Capture Device usb:v1043p8006* ID_MODEL_FROM_DATABASE=Flash Disk 32-256 MB usb:v1043p8012* ID_MODEL_FROM_DATABASE=Flash Disk 256 MB usb:v1044* ID_VENDOR_FROM_DATABASE=Chu Yuen Enterprise Co., Ltd usb:v1044p7001* ID_MODEL_FROM_DATABASE=Gigabyte U7000 DVB-T tuner usb:v1044p7002* ID_MODEL_FROM_DATABASE=Gigabyte U8000 DVB-T tuner usb:v1044p7004* ID_MODEL_FROM_DATABASE=Gigabyte U7100 DVB-T tuner usb:v1044p7005* ID_MODEL_FROM_DATABASE=Gigabyte U7200 DVB-T tuner [AF9035] usb:v1044p7006* ID_MODEL_FROM_DATABASE=Gigabyte U6000 DVB-T tuner [em2863] usb:v1044p8001* ID_MODEL_FROM_DATABASE=GN-54G usb:v1044p8002* ID_MODEL_FROM_DATABASE=GN-BR402W usb:v1044p8003* ID_MODEL_FROM_DATABASE=GN-WLBM101 usb:v1044p8004* ID_MODEL_FROM_DATABASE=GN-WLBZ101 802.11b Adapter usb:v1044p8005* ID_MODEL_FROM_DATABASE=GN-WLBZ201 802.11b Adapter usb:v1044p8006* ID_MODEL_FROM_DATABASE=GN-WBZB-M 802.11b Adapter usb:v1044p8007* ID_MODEL_FROM_DATABASE=GN-WBKG usb:v1044p8008* ID_MODEL_FROM_DATABASE=GN-WB01GS usb:v1044p800A* ID_MODEL_FROM_DATABASE=GN-WI05GS usb:v1044p800B* ID_MODEL_FROM_DATABASE=GN-WB30N 802.11n WLAN Card usb:v1044p800C* ID_MODEL_FROM_DATABASE=GN-WB31N 802.11n USB WLAN Card usb:v1044p800D* ID_MODEL_FROM_DATABASE=GN-WB32L 802.11n USB WLAN Card usb:v1046* ID_VENDOR_FROM_DATABASE=Winbond Electronics Corp. [hex] usb:v1046p6694* ID_MODEL_FROM_DATABASE=Generic W6694 USB usb:v1046p8901* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v1046p9967* ID_MODEL_FROM_DATABASE=W9967CF/W9968CF Webcam IC usb:v1048* ID_VENDOR_FROM_DATABASE=Targus Group International usb:v1048p2010* ID_MODEL_FROM_DATABASE=4-Port hub usb:v104B* ID_VENDOR_FROM_DATABASE=Mylex / Buslogic usb:v104C* ID_VENDOR_FROM_DATABASE=AMCO TEC International, Inc. usb:v104D* ID_VENDOR_FROM_DATABASE=Newport Corporation usb:v104Dp1003* ID_MODEL_FROM_DATABASE=Model-52 LED Light Source Power Supply and Driver usb:v104F* ID_VENDOR_FROM_DATABASE=WB Electronics usb:v104Fp0001* ID_MODEL_FROM_DATABASE=Infinity Phoenix usb:v104Fp0002* ID_MODEL_FROM_DATABASE=Smartmouse usb:v104Fp0003* ID_MODEL_FROM_DATABASE=FunProgrammer usb:v104Fp0004* ID_MODEL_FROM_DATABASE=Infinity Unlimited usb:v104Fp0006* ID_MODEL_FROM_DATABASE=Infinity Smart usb:v104Fp0007* ID_MODEL_FROM_DATABASE=Infinity Smart module usb:v104Fp0008* ID_MODEL_FROM_DATABASE=Infinity CryptoKey usb:v104Fp0009* ID_MODEL_FROM_DATABASE=RE-BL PlayStation 3 IR-to-Bluetooth converter usb:v1050* ID_VENDOR_FROM_DATABASE=Yubico.com usb:v1050p0010* ID_MODEL_FROM_DATABASE=Yubikey usb:v1050p0110* ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) OTP usb:v1050p0111* ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) OTP+CCID usb:v1050p0112* ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) CCID usb:v1050p0113* ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) U2F usb:v1050p0114* ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) OTP+U2F usb:v1050p0115* ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) U2F+CCID usb:v1050p0116* ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) OTP+U2F+CCID usb:v1050p0120* ID_MODEL_FROM_DATABASE=Yubikey Touch U2F Security Key usb:v1050p0200* ID_MODEL_FROM_DATABASE=U2F Gnubby usb:v1050p0211* ID_MODEL_FROM_DATABASE=Gnubby usb:v1053* ID_VENDOR_FROM_DATABASE=Immanuel Electronics Co., Ltd usb:v1054* ID_VENDOR_FROM_DATABASE=BMS International Beheer N.V. usb:v1054p5004* ID_MODEL_FROM_DATABASE=DSL 7420 Loader usb:v1054p5005* ID_MODEL_FROM_DATABASE=DSL 7420 LAN Modem usb:v1055* ID_VENDOR_FROM_DATABASE=Complex Micro Interconnection Co., Ltd usb:v1056* ID_VENDOR_FROM_DATABASE=Hsin Chen Ent Co., Ltd usb:v1057* ID_VENDOR_FROM_DATABASE=ON Semiconductor usb:v1058* ID_VENDOR_FROM_DATABASE=Western Digital Technologies, Inc. usb:v1058p0200* ID_MODEL_FROM_DATABASE=FireWire USB Combo usb:v1058p0400* ID_MODEL_FROM_DATABASE=External HDD usb:v1058p0500* ID_MODEL_FROM_DATABASE=hub usb:v1058p0701* ID_MODEL_FROM_DATABASE=WD Passport (WDXMS) usb:v1058p0702* ID_MODEL_FROM_DATABASE=WD Passport (WDXMS) usb:v1058p0704* ID_MODEL_FROM_DATABASE=My Passport Essential (WDME) usb:v1058p0705* ID_MODEL_FROM_DATABASE=My Passport Elite (WDML) usb:v1058p070A* ID_MODEL_FROM_DATABASE=My Passport Essential (WDBAAA), My Passport for Mac (WDBAAB), My Passport Essential SE (WDBABM), My Passport SE for Mac (WDBABW) usb:v1058p070B* ID_MODEL_FROM_DATABASE=My Passport Elite (WDBAAC) usb:v1058p070C* ID_MODEL_FROM_DATABASE=My Passport Studio (WDBAAE) usb:v1058p071A* ID_MODEL_FROM_DATABASE=My Passport Essential (WDBAAA) usb:v1058p071D* ID_MODEL_FROM_DATABASE=My Passport Studio (WDBALG) usb:v1058p0730* ID_MODEL_FROM_DATABASE=My Passport Essential (WDBACY) usb:v1058p0732* ID_MODEL_FROM_DATABASE=My Passport Essential SE (WDBGYS) usb:v1058p0740* ID_MODEL_FROM_DATABASE=My Passport Essential (WDBACY) usb:v1058p0741* ID_MODEL_FROM_DATABASE=My Passport Ultra usb:v1058p0742* ID_MODEL_FROM_DATABASE=My Passport Essential SE (WDBGYS) usb:v1058p0748* ID_MODEL_FROM_DATABASE=My Passport (WDBKXH, WDBY8L) usb:v1058p07A8* ID_MODEL_FROM_DATABASE=My Passport (WDBBEP), My Passport for Mac (WDBLUZ) usb:v1058p0810* ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBZFP) usb:v1058p0820* ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBMWV, WDBZFP) usb:v1058p0830* ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBZFP) usb:v1058p0900* ID_MODEL_FROM_DATABASE=MyBook Essential External HDD usb:v1058p0901* ID_MODEL_FROM_DATABASE=My Book Essential Edition (Green Ring) (WDG1U) usb:v1058p0902* ID_MODEL_FROM_DATABASE=My Book Pro Edition (WDG1T) usb:v1058p0903* ID_MODEL_FROM_DATABASE=My Book Premium Edition usb:v1058p0910* ID_MODEL_FROM_DATABASE=My Book Essential Edition (Green Ring) (WDG1U) usb:v1058p1001* ID_MODEL_FROM_DATABASE=Elements Desktop (WDE1U) usb:v1058p1003* ID_MODEL_FROM_DATABASE=WD Elements Desktop (WDE1UBK) usb:v1058p1010* ID_MODEL_FROM_DATABASE=Elements Portable (WDBAAR) usb:v1058p1021* ID_MODEL_FROM_DATABASE=Elements Desktop (WDBAAU) usb:v1058p1023* ID_MODEL_FROM_DATABASE=Elements SE Portable (WDBABV) usb:v1058p1042* ID_MODEL_FROM_DATABASE=Elements SE Portable (WDBPCK) usb:v1058p1048* ID_MODEL_FROM_DATABASE=Elements Portable (WDBU6Y) usb:v1058p107C* ID_MODEL_FROM_DATABASE=Elements Desktop (WDBWLG) usb:v1058p10A2* ID_MODEL_FROM_DATABASE=Elements SE Portable (WDBPCK) usb:v1058p10A8* ID_MODEL_FROM_DATABASE=Elements Portable (WDBUZG) usb:v1058p10B8* ID_MODEL_FROM_DATABASE=Elements Portable (WDBU6Y, WDBUZG) usb:v1058p1100* ID_MODEL_FROM_DATABASE=My Book Essential Edition 2.0 (WDH1U) usb:v1058p1102* ID_MODEL_FROM_DATABASE=My Book Home Edition (WDH1CS) usb:v1058p1103* ID_MODEL_FROM_DATABASE=My Book Studio usb:v1058p1104* ID_MODEL_FROM_DATABASE=My Book Mirror Edition (WDH2U) usb:v1058p1105* ID_MODEL_FROM_DATABASE=My Book Studio II usb:v1058p1110* ID_MODEL_FROM_DATABASE=My Book Essential (WDBAAF), My Book for Mac (WDBAAG) usb:v1058p1111* ID_MODEL_FROM_DATABASE=My Book Elite (WDBAAH) usb:v1058p1112* ID_MODEL_FROM_DATABASE=My Book Studio (WDBAAJ), My Book Studio LX (WDBACH) usb:v1058p1123* ID_MODEL_FROM_DATABASE=My Book 3.0 (WDBABP) usb:v1058p1130* ID_MODEL_FROM_DATABASE=My Book Essential (WDBACW) usb:v1058p1140* ID_MODEL_FROM_DATABASE=My Book Essential (WDBACW) usb:v1058p1230* ID_MODEL_FROM_DATABASE=My Book (WDBFJK0030HBK) usb:v1059* ID_VENDOR_FROM_DATABASE=Giesecke & Devrient GmbH usb:v1059p000B* ID_MODEL_FROM_DATABASE=StarSign Bio Token 3.0 usb:v105B* ID_VENDOR_FROM_DATABASE=Foxconn International, Inc. usb:v105BpE065* ID_MODEL_FROM_DATABASE=BCM43142A0 Bluetooth module usb:v105C* ID_VENDOR_FROM_DATABASE=Hong Ji Electric Wire & Cable (Dongguan) Co., Ltd usb:v105D* ID_VENDOR_FROM_DATABASE=Delkin Devices, Inc. usb:v105E* ID_VENDOR_FROM_DATABASE=Valence Semiconductor Design, Ltd usb:v105F* ID_VENDOR_FROM_DATABASE=Chin Shong Enterprise Co., Ltd usb:v1060* ID_VENDOR_FROM_DATABASE=Easthome Industrial Co., Ltd usb:v1063* ID_VENDOR_FROM_DATABASE=Motorola Electronics Taiwan, Ltd [hex] usb:v1063p1555* ID_MODEL_FROM_DATABASE=MC141555 Hub usb:v1063p4100* ID_MODEL_FROM_DATABASE=SB4100 USB Cable Modem usb:v1065* ID_VENDOR_FROM_DATABASE=CCYU Technology usb:v1065p0020* ID_MODEL_FROM_DATABASE=USB-DVR2 Dev Board usb:v1065p2136* ID_MODEL_FROM_DATABASE=EasyDisk ED1064 usb:v106A* ID_VENDOR_FROM_DATABASE=Loyal Legend, Ltd usb:v106C* ID_VENDOR_FROM_DATABASE=Curitel Communications, Inc. usb:v106Cp1101* ID_MODEL_FROM_DATABASE=CDMA 2000 1xRTT USB modem (HX-550C) usb:v106Cp1102* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp1103* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp1104* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp1105* ID_MODEL_FROM_DATABASE=Composite Device usb:v106Cp1106* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp1301* ID_MODEL_FROM_DATABASE=Composite Device usb:v106Cp1302* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp1303* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp1304* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp1401* ID_MODEL_FROM_DATABASE=Composite Device usb:v106Cp1402* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp1403* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp1501* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp1502* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp1503* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp1601* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp1602* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp1603* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp2101* ID_MODEL_FROM_DATABASE=AudioVox 8900 Cell Phone usb:v106Cp2102* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp2103* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp2301* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp2302* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp2303* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp2401* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp2402* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp2403* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp2501* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp2502* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp2503* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp2601* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp2602* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp2603* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp3701* ID_MODEL_FROM_DATABASE=Broadband Wireless modem usb:v106Cp3702* ID_MODEL_FROM_DATABASE=Pantech PX-500 usb:v106Cp3714* ID_MODEL_FROM_DATABASE=PANTECH USB MODEM [UM175] usb:v106Cp3716* ID_MODEL_FROM_DATABASE=UMW190 Modem usb:v106Cp3721* ID_MODEL_FROM_DATABASE=Option Beemo (GI0801) LTE surfstick usb:v106Cp3B14* ID_MODEL_FROM_DATABASE=Option Beemo (GI0801) LTE surfstick usb:v106Cp3EB4* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp4101* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp4102* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp4301* ID_MODEL_FROM_DATABASE=Composite Device usb:v106Cp4302* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp4401* ID_MODEL_FROM_DATABASE=Composite Device usb:v106Cp4402* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp4501* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp4502* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp4601* ID_MODEL_FROM_DATABASE=Composite Device usb:v106Cp4602* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp5101* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp5102* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp5301* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp5302* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp5401* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp5402* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp5501* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp5502* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp5601* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106Cp5602* ID_MODEL_FROM_DATABASE=Packet Service usb:v106Cp7101* ID_MODEL_FROM_DATABASE=Composite Device usb:v106Cp7102* ID_MODEL_FROM_DATABASE=Packet Service usb:v106CpA000* ID_MODEL_FROM_DATABASE=Packet Service usb:v106CpA001* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106CpC100* ID_MODEL_FROM_DATABASE=Packet Service usb:v106CpC200* ID_MODEL_FROM_DATABASE=Packet Service usb:v106CpC500* ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) usb:v106CpE200* ID_MODEL_FROM_DATABASE=Packet Service usb:v106D* ID_VENDOR_FROM_DATABASE=San Chieh Manufacturing, Ltd usb:v106E* ID_VENDOR_FROM_DATABASE=ConectL usb:v106F* ID_VENDOR_FROM_DATABASE=Money Controls usb:v106Fp0009* ID_MODEL_FROM_DATABASE=CT10x Coin Transaction usb:v106Fp000A* ID_MODEL_FROM_DATABASE=CR10x Coin Recycler usb:v106Fp000C* ID_MODEL_FROM_DATABASE=Xchange usb:v1076* ID_VENDOR_FROM_DATABASE=GCT Semiconductor, Inc. usb:v1076p0031* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v1076p0032* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v1076p8002* ID_MODEL_FROM_DATABASE=LU150 LTE Modem [Yota LU150] usb:v107B* ID_VENDOR_FROM_DATABASE=Gateway, Inc. usb:v107Bp3009* ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver usb:v107Bp55B2* ID_MODEL_FROM_DATABASE=WBU-110 802.11b Wireless Adapter [Intersil PRISM 3] usb:v107Bp55F2* ID_MODEL_FROM_DATABASE=WGU-210 802.11g Adapter [Intersil ISL3886] usb:v107D* ID_VENDOR_FROM_DATABASE=Arlec Australia, Ltd usb:v107E* ID_VENDOR_FROM_DATABASE=Midoriya Electric Co., Ltd usb:v107F* ID_VENDOR_FROM_DATABASE=KidzMouse, Inc. usb:v1082* ID_VENDOR_FROM_DATABASE=Shin-Etsukaken Co., Ltd usb:v1083* ID_VENDOR_FROM_DATABASE=Canon Electronics, Inc. usb:v1083p161B* ID_MODEL_FROM_DATABASE=DR-2010C Scanner usb:v1083p162C* ID_MODEL_FROM_DATABASE=P-150 Scanner usb:v1084* ID_VENDOR_FROM_DATABASE=Pantech Co., Ltd usb:v108A* ID_VENDOR_FROM_DATABASE=Chloride Power Protection usb:v108B* ID_VENDOR_FROM_DATABASE=Grand-tek Technology Co., Ltd usb:v108Bp0005* ID_MODEL_FROM_DATABASE=HID Keyboard/Mouse PS/2 Translator usb:v108C* ID_VENDOR_FROM_DATABASE=Robert Bosch GmbH usb:v108E* ID_VENDOR_FROM_DATABASE=Lotes Co., Ltd. usb:v1099* ID_VENDOR_FROM_DATABASE=Surface Optics Corp. usb:v109A* ID_VENDOR_FROM_DATABASE=DATASOFT Systems GmbH usb:v109B* ID_VENDOR_FROM_DATABASE=Hisense usb:v109Bp9118* ID_MODEL_FROM_DATABASE=Medion P4013 Mobile usb:v109F* ID_VENDOR_FROM_DATABASE=eSOL Co., Ltd usb:v109Fp3163* ID_MODEL_FROM_DATABASE=Trigem Mobile SmartDisplay84 usb:v109Fp3164* ID_MODEL_FROM_DATABASE=Trigem Mobile SmartDisplay121 usb:v10A0* ID_VENDOR_FROM_DATABASE=Hirotech, Inc. usb:v10A3* ID_VENDOR_FROM_DATABASE=Mitsubishi Materials Corp. usb:v10A9* ID_VENDOR_FROM_DATABASE=SK Teletech Co., Ltd usb:v10A9p1102* ID_MODEL_FROM_DATABASE=Sky Love Actually IM-U460K usb:v10A9p1104* ID_MODEL_FROM_DATABASE=Sky Vega IM-A650S usb:v10A9p1105* ID_MODEL_FROM_DATABASE=VEGA Android composite usb:v10A9p1106* ID_MODEL_FROM_DATABASE=VEGA Android composite usb:v10A9p1107* ID_MODEL_FROM_DATABASE=VEGA Android composite usb:v10A9p1108* ID_MODEL_FROM_DATABASE=VEGA Android composite usb:v10A9p1109* ID_MODEL_FROM_DATABASE=VEGA Android composite usb:v10A9p6021* ID_MODEL_FROM_DATABASE=SIRIUS alpha usb:v10A9p6031* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6032* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6033* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6034* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6035* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6036* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6037* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6050* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6051* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6052* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6053* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6054* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6055* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6056* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6057* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6058* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6059* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p6080* ID_MODEL_FROM_DATABASE=MHS291LVW LTE Modem [Verizon Jetpack 4G LTE Mobile Hotspot MHS291L] (Zero CD Mode) usb:v10A9p6085* ID_MODEL_FROM_DATABASE=MHS291LVW LTE Modem [Verizon Jetpack 4G LTE Mobile Hotspot MHS291L] (Modem Mode) usb:v10A9p7031* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p7032* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p7033* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p7034* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p7035* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p7036* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10A9p7037* ID_MODEL_FROM_DATABASE=Pantech Android composite usb:v10AA* ID_VENDOR_FROM_DATABASE=Cables To Go usb:v10AB* ID_VENDOR_FROM_DATABASE=USI Co., Ltd usb:v10ABp1002* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v10ABp1003* ID_MODEL_FROM_DATABASE=BC02-EXT in DFU usb:v10ABp1005* ID_MODEL_FROM_DATABASE=Bluetooth Adptr usb:v10ABp1006* ID_MODEL_FROM_DATABASE=BC04-EXT in DFU usb:v10ABp10C5* ID_MODEL_FROM_DATABASE=Sony-Ericsson / Samsung DataCable usb:v10AC* ID_VENDOR_FROM_DATABASE=Honeywell, Inc. usb:v10AE* ID_VENDOR_FROM_DATABASE=Princeton Technology Corp. usb:v10AF* ID_VENDOR_FROM_DATABASE=Liebert Corp. usb:v10AFp0000* ID_MODEL_FROM_DATABASE=UPS usb:v10AFp0001* ID_MODEL_FROM_DATABASE=PowerSure PSA UPS usb:v10AFp0002* ID_MODEL_FROM_DATABASE=PowerSure PST UPS usb:v10AFp0003* ID_MODEL_FROM_DATABASE=PowerSure PSP UPS usb:v10AFp0004* ID_MODEL_FROM_DATABASE=PowerSure PSI UPS usb:v10AFp0005* ID_MODEL_FROM_DATABASE=UPStation GXT 2U UPS usb:v10AFp0006* ID_MODEL_FROM_DATABASE=UPStation GXT UPS usb:v10AFp0007* ID_MODEL_FROM_DATABASE=Nfinity Power Systems UPS usb:v10AFp0008* ID_MODEL_FROM_DATABASE=PowerSure Interactive UPS usb:v10B5* ID_VENDOR_FROM_DATABASE=Comodo (PLX?) usb:v10B5p9060* ID_MODEL_FROM_DATABASE=Test Board usb:v10B8* ID_VENDOR_FROM_DATABASE=DiBcom usb:v10B8p0BB8* ID_MODEL_FROM_DATABASE=DiBcom USB DVB-T reference design (MOD300) (cold) usb:v10B8p0BB9* ID_MODEL_FROM_DATABASE=DiBcom USB DVB-T reference design (MOD300) (warm) usb:v10B8p0BC6* ID_MODEL_FROM_DATABASE=DiBcom USB2.0 DVB-T reference design (MOD3000P) (cold) usb:v10B8p0BC7* ID_MODEL_FROM_DATABASE=DiBcom USB2.0 DVB-T reference design (MOD3000P) (warm) usb:v10BB* ID_VENDOR_FROM_DATABASE=TM Technology, Inc. usb:v10BC* ID_VENDOR_FROM_DATABASE=Dinging Technology Co., Ltd usb:v10BD* ID_VENDOR_FROM_DATABASE=TMT Technology, Inc. usb:v10BDp1427* ID_MODEL_FROM_DATABASE=Ethernet usb:v10BF* ID_VENDOR_FROM_DATABASE=SmartHome usb:v10BFp0001* ID_MODEL_FROM_DATABASE=SmartHome PowerLinc usb:v10C3* ID_VENDOR_FROM_DATABASE=Universal Laser Systems, Inc. usb:v10C3p00A4* ID_MODEL_FROM_DATABASE=ULS PLS Series Laser Engraver Firmware Loader usb:v10C3p00A5* ID_MODEL_FROM_DATABASE=ULS Print Support usb:v10C4* ID_VENDOR_FROM_DATABASE=Cygnal Integrated Products, Inc. usb:v10C4p0002* ID_MODEL_FROM_DATABASE=F32x USBXpress Device usb:v10C4p0003* ID_MODEL_FROM_DATABASE=CommandIR usb:v10C4p8030* ID_MODEL_FROM_DATABASE=K4JRG Ham Radio devices usb:v10C4p8044* ID_MODEL_FROM_DATABASE=USB Debug Adapter usb:v10C4p804E* ID_MODEL_FROM_DATABASE=Software Bisque Paramount ME usb:v10C4p80A9* ID_MODEL_FROM_DATABASE=CP210x to UART Bridge Controller usb:v10C4p80CA* ID_MODEL_FROM_DATABASE=ATM2400 Sensor Device usb:v10C4p813F* ID_MODEL_FROM_DATABASE=tams EasyControl usb:v10C4p8149* ID_MODEL_FROM_DATABASE=West Mountain Radio Computerized Battery Analyzer usb:v10C4p814A* ID_MODEL_FROM_DATABASE=West Mountain Radio RIGblaster P&P usb:v10C4p814B* ID_MODEL_FROM_DATABASE=West Mountain Radio RIGtalk usb:v10C4p818A* ID_MODEL_FROM_DATABASE=Silicon Labs FM Radio Reference Design usb:v10C4p81E8* ID_MODEL_FROM_DATABASE=Zephyr BioHarness usb:v10C4p8460* ID_MODEL_FROM_DATABASE=Sangoma Wanpipe VoiceTime usb:v10C4p8461* ID_MODEL_FROM_DATABASE=Sangoma U100 usb:v10C4p8477* ID_MODEL_FROM_DATABASE=Balluff RFID Reader usb:v10C4p8496* ID_MODEL_FROM_DATABASE=SiLabs Cypress FW downloader usb:v10C4p8497* ID_MODEL_FROM_DATABASE=SiLabs Cypress EVB usb:v10C4p8605* ID_MODEL_FROM_DATABASE=dilitronics ESoLUX solar lighting controller usb:v10C4p86BC* ID_MODEL_FROM_DATABASE=C8051F34x AudioDelay [AD-340] usb:v10C4p8789* ID_MODEL_FROM_DATABASE=C8051F34x Extender & EDID MGR [EMX-DVI] usb:v10C4p87BE* ID_MODEL_FROM_DATABASE=C8051F34x HDMI Audio Extractor [EMX-HD-AUD] usb:v10C4p8863* ID_MODEL_FROM_DATABASE=C8051F34x Bootloader usb:v10C4p8897* ID_MODEL_FROM_DATABASE=C8051F38x HDMI Splitter [UHBX] usb:v10C4p8918* ID_MODEL_FROM_DATABASE=C8051F38x HDMI Audio Extractor [VSA-HA-DP] usb:v10C4p8973* ID_MODEL_FROM_DATABASE=C8051F38x HDMI Extender [UHBX-8X] usb:v10C4p89E1* ID_MODEL_FROM_DATABASE=C8051F38x HDMI Extender [UHBX-SW3-WP] usb:v10C4pEA60* ID_MODEL_FROM_DATABASE=CP210x UART Bridge / myAVR mySmartUSB light usb:v10C4pEA61* ID_MODEL_FROM_DATABASE=CP210x UART Bridge usb:v10C4pEA70* ID_MODEL_FROM_DATABASE=CP210x UART Bridge usb:v10C4pEA80* ID_MODEL_FROM_DATABASE=CP210x UART Bridge usb:v10C5* ID_VENDOR_FROM_DATABASE=Sanei Electric, Inc. usb:v10C5p819A* ID_MODEL_FROM_DATABASE=FM Radio usb:v10C6* ID_VENDOR_FROM_DATABASE=Intec, Inc. usb:v10CB* ID_VENDOR_FROM_DATABASE=Eratech usb:v10CC* ID_VENDOR_FROM_DATABASE=GBM Connector Co., Ltd usb:v10CCp1101* ID_MODEL_FROM_DATABASE=MP3 Player usb:v10CD* ID_VENDOR_FROM_DATABASE=Kycon, Inc. usb:v10CE* ID_VENDOR_FROM_DATABASE=Silicon Labs usb:v10CEp000E* ID_MODEL_FROM_DATABASE=Shinko/Sinfonia CHC-S2145 usb:v10CEpEA6A* ID_MODEL_FROM_DATABASE=MobiData EDGE USB Modem usb:v10CF* ID_VENDOR_FROM_DATABASE=Velleman Components, Inc. usb:v10CFp2011* ID_MODEL_FROM_DATABASE=R-Engine MPEG2 encoder/decoder usb:v10CFp5500* ID_MODEL_FROM_DATABASE=8055 Experiment Interface Board (address=0) usb:v10CFp5501* ID_MODEL_FROM_DATABASE=8055 Experiment Interface Board (address=1) usb:v10CFp5502* ID_MODEL_FROM_DATABASE=8055 Experiment Interface Board (address=2) usb:v10CFp5503* ID_MODEL_FROM_DATABASE=8055 Experiment Interface Board (address=3) usb:v10D1* ID_VENDOR_FROM_DATABASE=Hottinger Baldwin Measurement usb:v10D1p0101* ID_MODEL_FROM_DATABASE=USB-Module for Spider8, CP32 usb:v10D1p0202* ID_MODEL_FROM_DATABASE=CP22 - Communication Processor usb:v10D1p0301* ID_MODEL_FROM_DATABASE=CP42 - Communication Processor usb:v10D2* ID_VENDOR_FROM_DATABASE=RayComposer - R. Adams usb:v10D2p5243* ID_MODEL_FROM_DATABASE=RayComposer usb:v10D4* ID_VENDOR_FROM_DATABASE=Man Boon Manufactory, Ltd usb:v10D5* ID_VENDOR_FROM_DATABASE=Uni Class Technology Co., Ltd usb:v10D5p0004* ID_MODEL_FROM_DATABASE=PS/2 Converter usb:v10D5p5552* ID_MODEL_FROM_DATABASE=KVM Human Interface Composite Device (Keyboard/Mouse ports) usb:v10D5p55A2* ID_MODEL_FROM_DATABASE=2Port KVMSwitcher usb:v10D6* ID_VENDOR_FROM_DATABASE=Actions Semiconductor Co., Ltd usb:v10D6p0C02* ID_MODEL_FROM_DATABASE=BioniQ 1001 Tablet usb:v10D6p1000* ID_MODEL_FROM_DATABASE=MP3 Player usb:v10D6p1100* ID_MODEL_FROM_DATABASE=MPMan MP-Ki 128 MP3 Player/Recorder usb:v10D6p1101* ID_MODEL_FROM_DATABASE=D-Wave 2GB MP4 Player / AK1025 MP3/MP4 Player usb:v10D6p2200* ID_MODEL_FROM_DATABASE=Acer MP-120 MP3 player usb:v10D6p8888* ID_MODEL_FROM_DATABASE=ADFU Device usb:v10D6pFF51* ID_MODEL_FROM_DATABASE=ADFU Device usb:v10D6pFF61* ID_MODEL_FROM_DATABASE=MP4 Player usb:v10D6pFF66* ID_MODEL_FROM_DATABASE=Craig 2GB MP3/Video Player usb:v10DE* ID_VENDOR_FROM_DATABASE=Authenex, Inc. usb:v10DF* ID_VENDOR_FROM_DATABASE=In-Win Development, Inc. usb:v10DFp0500* ID_MODEL_FROM_DATABASE=iAPP CR-e500 Card reader usb:v10E0* ID_VENDOR_FROM_DATABASE=Post-Op Video, Inc. usb:v10E1* ID_VENDOR_FROM_DATABASE=CablePlus, Ltd usb:v10E2* ID_VENDOR_FROM_DATABASE=Nada Electronics, Ltd usb:v10EC* ID_VENDOR_FROM_DATABASE=Vast Technologies, Inc. usb:v10F0* ID_VENDOR_FROM_DATABASE=Nexio Co., Ltd usb:v10F0p2002* ID_MODEL_FROM_DATABASE=iNexio Touchscreen controller usb:v10F1* ID_VENDOR_FROM_DATABASE=Importek usb:v10F1p1A08* ID_MODEL_FROM_DATABASE=Internal Webcam usb:v10F1p1A1E* ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam 1.3M usb:v10F1p1A2A* ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam usb:v10F5* ID_VENDOR_FROM_DATABASE=Turtle Beach usb:v10F5p0200* ID_MODEL_FROM_DATABASE=Audio Advantage Roadie usb:v10FB* ID_VENDOR_FROM_DATABASE=Pictos Technologies, Inc. usb:v10FD* ID_VENDOR_FROM_DATABASE=Anubis Electronics, Ltd usb:v10FDp7E50* ID_MODEL_FROM_DATABASE=FlyCam Usb 100 usb:v10FDp804D* ID_MODEL_FROM_DATABASE=Typhoon Webshot II Webcam [zc0301] usb:v10FDp8050* ID_MODEL_FROM_DATABASE=FlyCAM-USB 300 XP2 usb:v10FDpDE00* ID_MODEL_FROM_DATABASE=WinFast WalkieTV WDM Capture Driver. usb:v10FE* ID_VENDOR_FROM_DATABASE=Thrane & Thrane usb:v10FEp000C* ID_MODEL_FROM_DATABASE=TT-3750 BGAN-XL Radio Module usb:v1100* ID_VENDOR_FROM_DATABASE=VirTouch, Ltd usb:v1100p0001* ID_MODEL_FROM_DATABASE=VTPlayer VTP-1 Braille Mouse usb:v1101* ID_VENDOR_FROM_DATABASE=EasyPass Industrial Co., Ltd usb:v1101p0001* ID_MODEL_FROM_DATABASE=FSK Electronics Super GSM Reader usb:v1108* ID_VENDOR_FROM_DATABASE=Brightcom Technologies, Ltd usb:v110A* ID_VENDOR_FROM_DATABASE=Moxa Technologies Co., Ltd. usb:v110Ap1250* ID_MODEL_FROM_DATABASE=UPort 1250 2-Port RS-232/422/485 usb:v110Ap1251* ID_MODEL_FROM_DATABASE=UPort 1250I 2-Port RS-232/422/485 with Isolation usb:v110Ap1410* ID_MODEL_FROM_DATABASE=UPort 1410 4-Port RS-232 usb:v110Ap1450* ID_MODEL_FROM_DATABASE=UPort 1450 4-Port RS-232/422/485 usb:v110Ap1451* ID_MODEL_FROM_DATABASE=UPort 1450I 4-Port RS-232/422/485 with Isolation usb:v110Ap1613* ID_MODEL_FROM_DATABASE=UPort 1610-16 16-Port RS-232 usb:v110Ap1618* ID_MODEL_FROM_DATABASE=UPort 1610-8 8-Port RS-232 usb:v110Ap1653* ID_MODEL_FROM_DATABASE=UPort 1650-16 16-Port RS-232/422/485 usb:v110Ap1658* ID_MODEL_FROM_DATABASE=UPort 1650-8 8-Port RS-232/422/485 usb:v1110* ID_VENDOR_FROM_DATABASE=Analog Devices Canada, Ltd (Allied Telesyn) usb:v1110p5C01* ID_MODEL_FROM_DATABASE=Huawei MT-882 Remote NDIS Network Device usb:v1110p6489* ID_MODEL_FROM_DATABASE=ADSL ETH/USB RTR usb:v1110p9000* ID_MODEL_FROM_DATABASE=ADSL LAN Adapter usb:v1110p9001* ID_MODEL_FROM_DATABASE=ADSL Loader usb:v1110p900F* ID_MODEL_FROM_DATABASE=AT-AR215 DSL Modem usb:v1110p9010* ID_MODEL_FROM_DATABASE=AT-AR215 DSL Modem usb:v1110p9021* ID_MODEL_FROM_DATABASE=ADSL WAN Adapter usb:v1110p9022* ID_MODEL_FROM_DATABASE=ADSL Loader usb:v1110p9023* ID_MODEL_FROM_DATABASE=ADSL WAN Adapter usb:v1110p9024* ID_MODEL_FROM_DATABASE=ADSL Loader usb:v1110p9031* ID_MODEL_FROM_DATABASE=ADSL LAN Adapter usb:v1110p9032* ID_MODEL_FROM_DATABASE=ADSL Loader usb:v1111* ID_VENDOR_FROM_DATABASE=Pandora International Ltd. usb:v1111p8888* ID_MODEL_FROM_DATABASE=Evolution Device usb:v1112* ID_VENDOR_FROM_DATABASE=YM ELECTRIC CO., Ltd usb:v1113* ID_VENDOR_FROM_DATABASE=Medion AG usb:v1113pA0A2* ID_MODEL_FROM_DATABASE=Active Sync device usb:v111E* ID_VENDOR_FROM_DATABASE=VSO Electric Co., Ltd usb:v112A* ID_VENDOR_FROM_DATABASE=RedRat usb:v112Ap0001* ID_MODEL_FROM_DATABASE=RedRat3 IR Transceiver usb:v112Ap0005* ID_MODEL_FROM_DATABASE=RedRat3II IR Transceiver usb:v112E* ID_VENDOR_FROM_DATABASE=Master Hill Electric Wire and Cable Co., Ltd usb:v112F* ID_VENDOR_FROM_DATABASE=Cellon International, Inc. usb:v1130* ID_VENDOR_FROM_DATABASE=Tenx Technology, Inc. usb:v1130p0001* ID_MODEL_FROM_DATABASE=BlyncLight usb:v1130p0002* ID_MODEL_FROM_DATABASE=iBuddy usb:v1130p0202* ID_MODEL_FROM_DATABASE=Rocket Launcher usb:v1130p6604* ID_MODEL_FROM_DATABASE=MCE IR-Receiver usb:v1130p660C* ID_MODEL_FROM_DATABASE=Foot Pedal/Thermometer usb:v1130p6806* ID_MODEL_FROM_DATABASE=Keychain photo frame usb:v1130pC301* ID_MODEL_FROM_DATABASE=Digital Photo viewer [Wallet Pix] usb:v1130pF211* ID_MODEL_FROM_DATABASE=TP6911 Audio Headset usb:v1131* ID_VENDOR_FROM_DATABASE=Integrated System Solution Corp. usb:v1131p1001* ID_MODEL_FROM_DATABASE=KY-BT100 Bluetooth Adapter usb:v1131p1002* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v1131p1003* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v1131p1004* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v1132* ID_VENDOR_FROM_DATABASE=Toshiba Corp., Digital Media Equipment [hex] usb:v1132p4331* ID_MODEL_FROM_DATABASE=PDR-M4/M5/M70 Digital Camera usb:v1132p4332* ID_MODEL_FROM_DATABASE=PDR-M60 Digital Camera usb:v1132p4333* ID_MODEL_FROM_DATABASE=PDR-M2300/PDR-M700 usb:v1132p4334* ID_MODEL_FROM_DATABASE=PDR-M65 usb:v1132p4335* ID_MODEL_FROM_DATABASE=PDR-M61 usb:v1132p4337* ID_MODEL_FROM_DATABASE=PDR-M11 usb:v1132p4338* ID_MODEL_FROM_DATABASE=PDR-M25 usb:v1136* ID_VENDOR_FROM_DATABASE=CTS Electronincs usb:v1136p3131* ID_MODEL_FROM_DATABASE=CTS LS515 usb:v113C* ID_VENDOR_FROM_DATABASE=Arin Tech Co., Ltd usb:v113D* ID_VENDOR_FROM_DATABASE=Mapower Electronics Co., Ltd usb:v1141* ID_VENDOR_FROM_DATABASE=V One Multimedia, Pte., Ltd usb:v1142* ID_VENDOR_FROM_DATABASE=CyberScan Technologies, Inc. usb:v1142p0709* ID_MODEL_FROM_DATABASE=Cyberview High Speed Scanner usb:v1145* ID_VENDOR_FROM_DATABASE=Japan Radio Company usb:v1145p0001* ID_MODEL_FROM_DATABASE=AirH PHONE AH-J3001V/J3002V usb:v1146* ID_VENDOR_FROM_DATABASE=Shimane SANYO Electric Co., Ltd. usb:v1147* ID_VENDOR_FROM_DATABASE=Ever Great Electric Wire and Cable Co., Ltd usb:v114B* ID_VENDOR_FROM_DATABASE=Sphairon Access Systems GmbH usb:v114Bp0110* ID_MODEL_FROM_DATABASE=Turbolink UB801R WLAN Adapter usb:v114Bp0150* ID_MODEL_FROM_DATABASE=Turbolink UB801RE Wireless 802.11g 54Mbps Network Adapter [RTL8187] usb:v114C* ID_VENDOR_FROM_DATABASE=Tinius Olsen Testing Machine Co., Inc. usb:v114D* ID_VENDOR_FROM_DATABASE=Alpha Imaging Technology Corp. usb:v114F* ID_VENDOR_FROM_DATABASE=Wavecom usb:v114Fp1234* ID_MODEL_FROM_DATABASE=Fastrack Xtend FXT001 Modem usb:v115B* ID_VENDOR_FROM_DATABASE=Salix Technology Co., Ltd. usb:v1162* ID_VENDOR_FROM_DATABASE=Secugen Corp. usb:v1163* ID_VENDOR_FROM_DATABASE=DeLorme Publishing, Inc. usb:v1163p0100* ID_MODEL_FROM_DATABASE=Earthmate GPS (orig) usb:v1163p0200* ID_MODEL_FROM_DATABASE=Earthmate GPS (LT-20, LT-40) usb:v1163p2020* ID_MODEL_FROM_DATABASE=Earthmate GPS (PN-40) usb:v1164* ID_VENDOR_FROM_DATABASE=YUAN High-Tech Development Co., Ltd usb:v1164p0300* ID_MODEL_FROM_DATABASE=ELSAVISION 460D usb:v1164p0601* ID_MODEL_FROM_DATABASE=Analog TV Tuner usb:v1164p0900* ID_MODEL_FROM_DATABASE=TigerBird BMP837 USB2.0 WDM Encoder usb:v1164p0BC7* ID_MODEL_FROM_DATABASE=Digital TV Tuner usb:v1164p521B* ID_MODEL_FROM_DATABASE=MC521A mini Card ATSC Tuner usb:v1164p6601* ID_MODEL_FROM_DATABASE=Digital TV Tuner Card [RTL2832U] usb:v1165* ID_VENDOR_FROM_DATABASE=Telson Electronics Co., Ltd usb:v1166* ID_VENDOR_FROM_DATABASE=Bantam Interactive Technologies usb:v1167* ID_VENDOR_FROM_DATABASE=Salient Systems Corp. usb:v1168* ID_VENDOR_FROM_DATABASE=BizConn International Corp. usb:v116E* ID_VENDOR_FROM_DATABASE=Gigastorage Corp. usb:v116F* ID_VENDOR_FROM_DATABASE=Silicon 10 Technology Corp. usb:v116Fp0005* ID_MODEL_FROM_DATABASE=Flash Card Reader usb:v116FpC108* ID_MODEL_FROM_DATABASE=Flash Card Reader usb:v116FpC109* ID_MODEL_FROM_DATABASE=Flash Card Reader usb:v1175* ID_VENDOR_FROM_DATABASE=Shengyih Steel Mold Co., Ltd usb:v117D* ID_VENDOR_FROM_DATABASE=Santa Electronic, Inc. usb:v117E* ID_VENDOR_FROM_DATABASE=JNC, Inc. usb:v1182* ID_VENDOR_FROM_DATABASE=Venture Corp., Ltd usb:v1183* ID_VENDOR_FROM_DATABASE=Compaq Computer Corp. [hex] (Digital Dream ??) usb:v1183p0001* ID_MODEL_FROM_DATABASE=DigitalDream l'espion XS usb:v1183p19C7* ID_MODEL_FROM_DATABASE=ISDN TA usb:v1183p4008* ID_MODEL_FROM_DATABASE=56k FaxModem usb:v1183p504A* ID_MODEL_FROM_DATABASE=PJB-100 Personal Jukebox usb:v1184* ID_VENDOR_FROM_DATABASE=Kyocera Elco Corp. usb:v1188* ID_VENDOR_FROM_DATABASE=Bloomberg L.P. usb:v1189* ID_VENDOR_FROM_DATABASE=Acer Communications & Multimedia usb:v1189p0893* ID_MODEL_FROM_DATABASE=EP-1427X-2 Ethernet Adapter [Acer] usb:v118F* ID_VENDOR_FROM_DATABASE=You Yang Technology Co., Ltd usb:v1190* ID_VENDOR_FROM_DATABASE=Tripace usb:v1191* ID_VENDOR_FROM_DATABASE=Loyalty Founder Enterprise Co., Ltd usb:v1196* ID_VENDOR_FROM_DATABASE=Yankee Robotics, LLC usb:v1196p0010* ID_MODEL_FROM_DATABASE=Trifid Camera without code usb:v1196p0011* ID_MODEL_FROM_DATABASE=Trifid Camera usb:v1197* ID_VENDOR_FROM_DATABASE=Technoimagia Co., Ltd usb:v1198* ID_VENDOR_FROM_DATABASE=StarShine Technology Corp. usb:v1199* ID_VENDOR_FROM_DATABASE=Sierra Wireless, Inc. usb:v1199p0019* ID_MODEL_FROM_DATABASE=AC595U usb:v1199p0021* ID_MODEL_FROM_DATABASE=AC597E usb:v1199p0024* ID_MODEL_FROM_DATABASE=MC5727 CDMA modem usb:v1199p0110* ID_MODEL_FROM_DATABASE=Composite Device usb:v1199p0112* ID_MODEL_FROM_DATABASE=CDMA 1xEVDO PC Card, AirCard 580 usb:v1199p0120* ID_MODEL_FROM_DATABASE=AC595U usb:v1199p0218* ID_MODEL_FROM_DATABASE=MC5720 Wireless Modem usb:v1199p6467* ID_MODEL_FROM_DATABASE=MP Series Network Adapter usb:v1199p6468* ID_MODEL_FROM_DATABASE=MP Series Network Adapter usb:v1199p6469* ID_MODEL_FROM_DATABASE=MP Series Network Adapter usb:v1199p6802* ID_MODEL_FROM_DATABASE=MC8755 Device usb:v1199p6803* ID_MODEL_FROM_DATABASE=MC8765 Device usb:v1199p6804* ID_MODEL_FROM_DATABASE=MC8755 Device usb:v1199p6805* ID_MODEL_FROM_DATABASE=MC8765 Device usb:v1199p6812* ID_MODEL_FROM_DATABASE=MC8775 Device usb:v1199p6820* ID_MODEL_FROM_DATABASE=AC875 Device usb:v1199p6832* ID_MODEL_FROM_DATABASE=MC8780 Device usb:v1199p6833* ID_MODEL_FROM_DATABASE=MC8781 Device usb:v1199p683A* ID_MODEL_FROM_DATABASE=MC8785 Device usb:v1199p683C* ID_MODEL_FROM_DATABASE=Mobile Broadband 3G/UMTS (MC8790 Device) usb:v1199p6850* ID_MODEL_FROM_DATABASE=AirCard 880 Device usb:v1199p6851* ID_MODEL_FROM_DATABASE=AirCard 881 Device usb:v1199p6852* ID_MODEL_FROM_DATABASE=AirCard 880E Device usb:v1199p6853* ID_MODEL_FROM_DATABASE=AirCard 881E Device usb:v1199p6854* ID_MODEL_FROM_DATABASE=AirCard 885 Device usb:v1199p6856* ID_MODEL_FROM_DATABASE=ATT "USB Connect 881" usb:v1199p6870* ID_MODEL_FROM_DATABASE=MC8780 Device usb:v1199p6871* ID_MODEL_FROM_DATABASE=MC8781 Device usb:v1199p6893* ID_MODEL_FROM_DATABASE=MC8777 Device usb:v1199p68A3* ID_MODEL_FROM_DATABASE=MC8700 Modem usb:v1199p68AA* ID_MODEL_FROM_DATABASE=4G LTE adapter usb:v1199p9000* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem (QDL mode) usb:v1199p9001* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem usb:v1199p9002* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem usb:v1199p9003* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem usb:v1199p9004* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem usb:v1199p9005* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem usb:v1199p9006* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem usb:v1199p9007* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem usb:v1199p9008* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem usb:v1199p9009* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem usb:v1199p900A* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem usb:v1199p9055* ID_MODEL_FROM_DATABASE=Gobi 9x15 Multimode 3G/4G LTE Modem (NAT mode) usb:v1199p9057* ID_MODEL_FROM_DATABASE=Gobi 9x15 Multimode 3G/4G LTE Modem (IP passthrough mode) usb:v119A* ID_VENDOR_FROM_DATABASE=ZHAN QI Technology Co., Ltd usb:v119B* ID_VENDOR_FROM_DATABASE=ruwido austria GmbH usb:v119Bp0400* ID_MODEL_FROM_DATABASE=Infrared Keyboard V2.01 usb:v11A0* ID_VENDOR_FROM_DATABASE=Chipcon AS usb:v11A0pEB11* ID_MODEL_FROM_DATABASE=CC2400EB 2.0 ZigBee Sniffer usb:v11A3* ID_VENDOR_FROM_DATABASE=Technovas Co., Ltd usb:v11A3p8031* ID_MODEL_FROM_DATABASE=MP3 Player usb:v11A3p8032* ID_MODEL_FROM_DATABASE=MP3 Player usb:v11AA* ID_VENDOR_FROM_DATABASE=GlobalMedia Group, LLC usb:v11AAp1518* ID_MODEL_FROM_DATABASE=iREZ K2 usb:v11AB* ID_VENDOR_FROM_DATABASE=Exito Electronics Co., Ltd usb:v11AC* ID_VENDOR_FROM_DATABASE=Nike usb:v11ACp6565* ID_MODEL_FROM_DATABASE=FuelBand usb:v11B0* ID_VENDOR_FROM_DATABASE=ATECH FLASH TECHNOLOGY usb:v11B0p6208* ID_MODEL_FROM_DATABASE=PRO-28U usb:v11BE* ID_VENDOR_FROM_DATABASE=R&D International NV usb:v11BEpF0A0* ID_MODEL_FROM_DATABASE=Martin Maxxyz DMX usb:v11C5* ID_VENDOR_FROM_DATABASE=Inmax usb:v11C5p0521* ID_MODEL_FROM_DATABASE=IMT-0521 Smartcard Reader usb:v11CA* ID_VENDOR_FROM_DATABASE=VeriFone Inc usb:v11CAp0207* ID_MODEL_FROM_DATABASE=PIN Pad VX 810 usb:v11CAp0220* ID_MODEL_FROM_DATABASE=PIN Pad VX 805 usb:v11DB* ID_VENDOR_FROM_DATABASE=Topfield Co., Ltd. usb:v11DBp1000* ID_MODEL_FROM_DATABASE=PVR usb:v11DBp1100* ID_MODEL_FROM_DATABASE=PVR usb:v11E6* ID_VENDOR_FROM_DATABASE=K.I. Technology Co. Ltd. usb:v11F5* ID_VENDOR_FROM_DATABASE=Siemens AG usb:v11F5p0001* ID_MODEL_FROM_DATABASE=SX1 usb:v11F5p0003* ID_MODEL_FROM_DATABASE=Mobile phone USB cable usb:v11F5p0004* ID_MODEL_FROM_DATABASE=X75 usb:v11F5p0005* ID_MODEL_FROM_DATABASE=SXG75/EF81 usb:v11F5p0008* ID_MODEL_FROM_DATABASE=UMTS/HSDPA Data Card usb:v11F5p0101* ID_MODEL_FROM_DATABASE=RCU Connect usb:v11F6* ID_VENDOR_FROM_DATABASE=Prolific usb:v11F6p2001* ID_MODEL_FROM_DATABASE=Willcom WSIM usb:v11F7* ID_VENDOR_FROM_DATABASE=Alcatel (?) usb:v11F7p02DF* ID_MODEL_FROM_DATABASE=Serial cable (v2) for TD-10 Mobile Phone usb:v1203* ID_VENDOR_FROM_DATABASE=TSC Auto ID Technology Co., Ltd usb:v1203p0140* ID_MODEL_FROM_DATABASE=TTP-245C usb:v1209* ID_VENDOR_FROM_DATABASE=InterBiometrics usb:v1209p1001* ID_MODEL_FROM_DATABASE=USB Hub usb:v1209p1002* ID_MODEL_FROM_DATABASE=USB Relais usb:v1209p1003* ID_MODEL_FROM_DATABASE=IBSecureCam-P usb:v1209p1004* ID_MODEL_FROM_DATABASE=IBSecureCam-O usb:v1209p1005* ID_MODEL_FROM_DATABASE=IBSecureCam-N usb:v1209p1006* ID_MODEL_FROM_DATABASE=Mini IO-Board usb:v1209p2000* ID_MODEL_FROM_DATABASE=Zygmunt Krynicki Lantern Brightness Sensor usb:v1209p2048* ID_MODEL_FROM_DATABASE=Housedillon.com MRF49XA Transciever usb:v1209p2222* ID_MODEL_FROM_DATABASE=LabConnect Signalgenerator usb:v1209p2300* ID_MODEL_FROM_DATABASE=Keyboardio Keyboardio Model 01 Bootloader usb:v1209p2301* ID_MODEL_FROM_DATABASE=Keyboardio Keyboardio Model 01 usb:v1209p2337* ID_MODEL_FROM_DATABASE=/Dev or SlashDev /Net usb:v1209p3000* ID_MODEL_FROM_DATABASE=lloyd3000 usb:v1209p3333* ID_MODEL_FROM_DATABASE=LabConnect Digitalnetzteil usb:v1209p5222* ID_MODEL_FROM_DATABASE=telavivmakers attami usb:v1209p5A22* ID_MODEL_FROM_DATABASE=ikari_01 sd2snes usb:v1209p7BD0* ID_MODEL_FROM_DATABASE=pokey9000 Tiny Bit Dingus usb:v1209pABD0* ID_MODEL_FROM_DATABASE=tibounise ADB converter usb:v1209pBEEF* ID_MODEL_FROM_DATABASE=Modal MC-USB usb:v1209pC0F5* ID_MODEL_FROM_DATABASE=unethi PERswitch usb:v1209pCA1C* ID_MODEL_FROM_DATABASE=KnightOS Hub usb:v1209pCA1D* ID_MODEL_FROM_DATABASE=KnightOS MTP Device usb:v1209pCAFE* ID_MODEL_FROM_DATABASE=ii iigadget usb:v1209pDADA* ID_MODEL_FROM_DATABASE=Rebel Technology OWL usb:v1209pDEAD* ID_MODEL_FROM_DATABASE=chaosfield.at AVR-Ruler usb:v1209pFA11* ID_MODEL_FROM_DATABASE=moonglow OpenXHC usb:v1209pFEED* ID_MODEL_FROM_DATABASE=ProgramGyar AVR-IR Sender usb:v120E* ID_VENDOR_FROM_DATABASE=Hudson Soft Co., Ltd usb:v120F* ID_VENDOR_FROM_DATABASE=Magellan usb:v120Fp524E* ID_MODEL_FROM_DATABASE=RoadMate 1475T usb:v120Fp5260* ID_MODEL_FROM_DATABASE=Triton Handheld GPS Receiver (300/400/500/1500/2000) usb:v1210* ID_VENDOR_FROM_DATABASE=DigiTech usb:v1210p0016* ID_MODEL_FROM_DATABASE=RP500 Guitar Multi-Effects Processor usb:v1210p001B* ID_MODEL_FROM_DATABASE=RP155 Guitar Multi-Effects Processor usb:v1210p001C* ID_MODEL_FROM_DATABASE=RP255 Guitar Multi-Effects Processor usb:v121E* ID_VENDOR_FROM_DATABASE=Jungsoft Co., Ltd usb:v121Ep3403* ID_MODEL_FROM_DATABASE=Muzio JM250 Audio Player usb:v1221* ID_VENDOR_FROM_DATABASE=Unknown manufacturer usb:v1221p3234* ID_MODEL_FROM_DATABASE=Disk (Thumb drive) usb:v1223* ID_VENDOR_FROM_DATABASE=SKYCABLE ENTERPRISE. CO., LTD. usb:v1228* ID_VENDOR_FROM_DATABASE=Datapaq Limited usb:v1228p0012* ID_MODEL_FROM_DATABASE=Q18 Data Logger usb:v1228p0015* ID_MODEL_FROM_DATABASE=TPaq21/MPaq21 Datalogger usb:v1228p584C* ID_MODEL_FROM_DATABASE=XL2 Logger usb:v1230* ID_VENDOR_FROM_DATABASE=Chipidea-Microelectronica, S.A. usb:v1233* ID_VENDOR_FROM_DATABASE=Denver Electronics usb:v1233p5677* ID_MODEL_FROM_DATABASE=FUSB200 mp3 player usb:v1234* ID_VENDOR_FROM_DATABASE=Brain Actuated Technologies usb:v1234p0000* ID_MODEL_FROM_DATABASE=Neural Impulse Actuator Prototype 1.0 [NIA] usb:v1234p4321* ID_MODEL_FROM_DATABASE=Human Interface Device usb:v1234pED02* ID_MODEL_FROM_DATABASE=Emotiv EPOC Developer Headset Wireless Dongle usb:v1235* ID_VENDOR_FROM_DATABASE=Focusrite-Novation usb:v1235p0001* ID_MODEL_FROM_DATABASE=ReMOTE Audio/XStation First Edition usb:v1235p0002* ID_MODEL_FROM_DATABASE=Speedio usb:v1235p0003* ID_MODEL_FROM_DATABASE=RemoteSL + ZeroSL usb:v1235p0004* ID_MODEL_FROM_DATABASE=ReMOTE LE usb:v1235p0005* ID_MODEL_FROM_DATABASE=XIOSynth [First Edition] usb:v1235p0006* ID_MODEL_FROM_DATABASE=XStation usb:v1235p0007* ID_MODEL_FROM_DATABASE=XIOSynth usb:v1235p0008* ID_MODEL_FROM_DATABASE=ReMOTE SL Compact usb:v1235p0009* ID_MODEL_FROM_DATABASE=nIO usb:v1235p000A* ID_MODEL_FROM_DATABASE=Nocturn usb:v1235p000B* ID_MODEL_FROM_DATABASE=ReMOTE SL MkII usb:v1235p000C* ID_MODEL_FROM_DATABASE=ZeRO MkII usb:v1235p000E* ID_MODEL_FROM_DATABASE=Launchpad usb:v1235p0010* ID_MODEL_FROM_DATABASE=Saffire 6 usb:v1235p0011* ID_MODEL_FROM_DATABASE=Ultranova usb:v1235p0012* ID_MODEL_FROM_DATABASE=Nocturn Keyboard usb:v1235p0013* ID_MODEL_FROM_DATABASE=VRM Box usb:v1235p0014* ID_MODEL_FROM_DATABASE=VRM Box Audio Class (2-out) usb:v1235p0015* ID_MODEL_FROM_DATABASE=Dicer usb:v1235p0016* ID_MODEL_FROM_DATABASE=Ultranova usb:v1235p0018* ID_MODEL_FROM_DATABASE=Twitch usb:v1235p0019* ID_MODEL_FROM_DATABASE=Impulse 25 usb:v1235p001A* ID_MODEL_FROM_DATABASE=Impulse 49 usb:v1235p001B* ID_MODEL_FROM_DATABASE=Impulse 61 usb:v1235p4661* ID_MODEL_FROM_DATABASE=ReMOTE25 usb:v1235p8000* ID_MODEL_FROM_DATABASE=Scarlett 18i6 usb:v1235p8002* ID_MODEL_FROM_DATABASE=Scarlett 8i6 usb:v1235p8006* ID_MODEL_FROM_DATABASE=Focusrite Scarlett 2i2 usb:v1235p8008* ID_MODEL_FROM_DATABASE=Saffire 6 usb:v1235p800A* ID_MODEL_FROM_DATABASE=Scarlett 2i4 usb:v1235p800C* ID_MODEL_FROM_DATABASE=Scarlett 18i20 usb:v1235p800E* ID_MODEL_FROM_DATABASE=iTrack Solo usb:v1235p8010* ID_MODEL_FROM_DATABASE=Forte usb:v1235p8012* ID_MODEL_FROM_DATABASE=Scarlett 6i6 usb:v1235p8014* ID_MODEL_FROM_DATABASE=Scarlett 18i8 usb:v1241* ID_VENDOR_FROM_DATABASE=Belkin usb:v1241p0504* ID_MODEL_FROM_DATABASE=Wireless Trackball Keyboard usb:v1241p1111* ID_MODEL_FROM_DATABASE=Mouse usb:v1241p1122* ID_MODEL_FROM_DATABASE=Typhoon Stream Optical Mouse USB+PS/2 usb:v1241p1155* ID_MODEL_FROM_DATABASE=Memorex Optical ScrollPro Mouse SE MX4600 usb:v1241p1166* ID_MODEL_FROM_DATABASE=MI-2150 Trust Mouse usb:v1241p1177* ID_MODEL_FROM_DATABASE=Mouse [HT82M21A] usb:v1241p1503* ID_MODEL_FROM_DATABASE=Keyboard usb:v1241p1603* ID_MODEL_FROM_DATABASE=Keyboard usb:v1241pF767* ID_MODEL_FROM_DATABASE=Keyboard usb:v124A* ID_VENDOR_FROM_DATABASE=AirVast usb:v124Ap168B* ID_MODEL_FROM_DATABASE=PRISM3 WLAN Adapter usb:v124Ap4017* ID_MODEL_FROM_DATABASE=PC-Chips 802.11b Adapter usb:v124Ap4023* ID_MODEL_FROM_DATABASE=WM168g 802.11bg Wireless Adapter [Intersil ISL3886] usb:v124Ap4025* ID_MODEL_FROM_DATABASE=IOGear GWU513 v2 802.11bg Wireless Adapter [Intersil ISL3887] usb:v124B* ID_VENDOR_FROM_DATABASE=Nyko (Honey Bee) usb:v124Bp4D01* ID_MODEL_FROM_DATABASE=Airflo EX Joystick usb:v124C* ID_VENDOR_FROM_DATABASE=MXI - Memory Experts International, Inc. usb:v124Cp3200* ID_MODEL_FROM_DATABASE=Stealth MXP 1GB usb:v125C* ID_VENDOR_FROM_DATABASE=Apogee Inc. usb:v125Cp0010* ID_MODEL_FROM_DATABASE=Alta series CCD usb:v125F* ID_VENDOR_FROM_DATABASE=A-DATA Technology Co., Ltd. usb:v125Fp312A* ID_MODEL_FROM_DATABASE=Superior S102 usb:v125Fp312B* ID_MODEL_FROM_DATABASE=Superior S102 Pro usb:v125FpA15A* ID_MODEL_FROM_DATABASE=DashDrive Durable HD710 portable HDD various size usb:v125FpA22A* ID_MODEL_FROM_DATABASE=DashDrive Elite HE720 500GB usb:v125FpA91A* ID_MODEL_FROM_DATABASE=Portable HDD CH91 usb:v125FpC08A* ID_MODEL_FROM_DATABASE=C008 Flash Drive usb:v125FpC81A* ID_MODEL_FROM_DATABASE=Flash drive usb:v125FpC93A* ID_MODEL_FROM_DATABASE=4GB Pen Drive usb:v125FpC96A* ID_MODEL_FROM_DATABASE=C906 Flash Drive usb:v125FpCB10* ID_MODEL_FROM_DATABASE=Dash Drive UV100 usb:v1260* ID_VENDOR_FROM_DATABASE=Standard Microsystems Corp. usb:v1260pEE22* ID_MODEL_FROM_DATABASE=SMC2862W-G v3 EZ Connect 802.11g Adapter [Intersil ISL3887] usb:v1264* ID_VENDOR_FROM_DATABASE=Covidien Energy-based Devices usb:v1266* ID_VENDOR_FROM_DATABASE=Pirelli Broadband Solutions usb:v1266p6302* ID_MODEL_FROM_DATABASE=Fastweb DRG A226M ADSL Router usb:v1267* ID_VENDOR_FROM_DATABASE=Logic3 / SpectraVideo plc usb:v1267p0103* ID_MODEL_FROM_DATABASE=G-720 Keyboard usb:v1267p0201* ID_MODEL_FROM_DATABASE=A4Tech SWOP-3 Mouse usb:v1267p0210* ID_MODEL_FROM_DATABASE=LG Optical Mouse 3D-310 usb:v1267pA001* ID_MODEL_FROM_DATABASE=JP260 PC Game Pad usb:v1267pC002* ID_MODEL_FROM_DATABASE=Wireless Optical Mouse usb:v126C* ID_VENDOR_FROM_DATABASE=Aristocrat Technologies usb:v126D* ID_VENDOR_FROM_DATABASE=Bel Stewart usb:v126E* ID_VENDOR_FROM_DATABASE=Strobe Data, Inc. usb:v126F* ID_VENDOR_FROM_DATABASE=TwinMOS usb:v126Fp0163* ID_MODEL_FROM_DATABASE=Storage device (2gB thumb drive) usb:v126Fp1325* ID_MODEL_FROM_DATABASE=Mobile Disk usb:v126Fp2168* ID_MODEL_FROM_DATABASE=Mobile Disk III usb:v126FpA006* ID_MODEL_FROM_DATABASE=G240 802.11bg usb:v1274* ID_VENDOR_FROM_DATABASE=Ensoniq usb:v1275* ID_VENDOR_FROM_DATABASE=Xaxero Marine Software Engineering, Ltd. usb:v1275p0002* ID_MODEL_FROM_DATABASE=WeatherFax 2000 Demodulator usb:v1275p0080* ID_MODEL_FROM_DATABASE=SkyEye Weather Satellite Receiver usb:v1278* ID_VENDOR_FROM_DATABASE=Starlight Xpress usb:v1278p0105* ID_MODEL_FROM_DATABASE=SXV-M5 usb:v1278p0107* ID_MODEL_FROM_DATABASE=SXV-M7 usb:v1278p0109* ID_MODEL_FROM_DATABASE=SXV-M9 usb:v1278p0110* ID_MODEL_FROM_DATABASE=SXVF-H16 usb:v1278p0115* ID_MODEL_FROM_DATABASE=SXVF-H5 usb:v1278p0119* ID_MODEL_FROM_DATABASE=SXV-H9 usb:v1278p0135* ID_MODEL_FROM_DATABASE=SXVF-H35 usb:v1278p0136* ID_MODEL_FROM_DATABASE=SXVF-H36 usb:v1278p0200* ID_MODEL_FROM_DATABASE=SXV interface for paraller MX cameras usb:v1278p0305* ID_MODEL_FROM_DATABASE=SXV-M5C usb:v1278p0307* ID_MODEL_FROM_DATABASE=SXV-M7C usb:v1278p0319* ID_MODEL_FROM_DATABASE=SXV-H9C usb:v1278p0325* ID_MODEL_FROM_DATABASE=SXV-M25C usb:v1278p0326* ID_MODEL_FROM_DATABASE=SXVR-M26C usb:v1278p0507* ID_MODEL_FROM_DATABASE=Lodestar autoguider usb:v1278p0517* ID_MODEL_FROM_DATABASE=CoStar usb:v1283* ID_VENDOR_FROM_DATABASE=zebris Medical GmbH usb:v1283p0100* ID_MODEL_FROM_DATABASE=USB-RS232 Adaptor usb:v1283p0110* ID_MODEL_FROM_DATABASE=CMS20 usb:v1283p0111* ID_MODEL_FROM_DATABASE=CMS 10 usb:v1283p0112* ID_MODEL_FROM_DATABASE=CMS 05 usb:v1283p0114* ID_MODEL_FROM_DATABASE=ARCUS digma PC-Interface usb:v1283p0115* ID_MODEL_FROM_DATABASE=SAM Axioquick recorder usb:v1283p0116* ID_MODEL_FROM_DATABASE=SAM Axioquick recorder usb:v1283p0120* ID_MODEL_FROM_DATABASE=emed-X usb:v1283p0121* ID_MODEL_FROM_DATABASE=emed-AT usb:v1283p0130* ID_MODEL_FROM_DATABASE=PDM usb:v1283p0150* ID_MODEL_FROM_DATABASE=CMS10GI (Golf) usb:v1286* ID_VENDOR_FROM_DATABASE=Marvell Semiconductor, Inc. usb:v1286p00BC* ID_MODEL_FROM_DATABASE=Marvell JTAG Probe usb:v1286p1FAB* ID_MODEL_FROM_DATABASE=88W8338 [Libertas] 802.11g usb:v1286p2001* ID_MODEL_FROM_DATABASE=88W8388 802.11a/b/g WLAN usb:v1286p2006* ID_MODEL_FROM_DATABASE=88W8362 802.11n WLAN usb:v1286p8001* ID_MODEL_FROM_DATABASE=BLOB boot loader firmware usb:v1291* ID_VENDOR_FROM_DATABASE=Qualcomm Flarion Technologies, Inc. / Leadtek Research, Inc. usb:v1291p0010* ID_MODEL_FROM_DATABASE=FDM 2xxx Flash-OFDM modem usb:v1291p0011* ID_MODEL_FROM_DATABASE=LR7F06/LR7F14 Flash-OFDM modem usb:v1292* ID_VENDOR_FROM_DATABASE=Innomedia usb:v1292p0258* ID_MODEL_FROM_DATABASE=Creative Labs VoIP Blaster usb:v1293* ID_VENDOR_FROM_DATABASE=Belkin Components [hex] usb:v1293p0002* ID_MODEL_FROM_DATABASE=F5U002 Parallel Port [uss720] usb:v1293p2101* ID_MODEL_FROM_DATABASE=104-key keyboard usb:v1294* ID_VENDOR_FROM_DATABASE=RISO KAGAKU CORP. usb:v1294p1320* ID_MODEL_FROM_DATABASE=Webmail Notifier usb:v129B* ID_VENDOR_FROM_DATABASE=CyberTAN Technology usb:v129Bp160B* ID_MODEL_FROM_DATABASE=Siemens S30853-S1031-R351 802.11g Wireless Adapter [Atheros AR5523] usb:v129Bp160C* ID_MODEL_FROM_DATABASE=Siemens S30853-S1038-R351 802.11g Wireless Adapter [Atheros AR5523] usb:v129Bp1666* ID_MODEL_FROM_DATABASE=TG54USB 802.11bg usb:v129Bp1667* ID_MODEL_FROM_DATABASE=802.11bg usb:v129Bp1828* ID_MODEL_FROM_DATABASE=Gigaset USB Adapter 300 usb:v12A7* ID_VENDOR_FROM_DATABASE=Trendchip Technologies Corp. usb:v12AB* ID_VENDOR_FROM_DATABASE=Honey Bee Electronic International Ltd. usb:v12B8* ID_VENDOR_FROM_DATABASE=Zhejiang Xinya Electronic Technology Co., Ltd. usb:v12B9* ID_VENDOR_FROM_DATABASE=E28 usb:v12BA* ID_VENDOR_FROM_DATABASE=Licensed by Sony Computer Entertainment America usb:v12BAp00FF* ID_MODEL_FROM_DATABASE=Rocksmith Guitar Adapter usb:v12BAp0100* ID_MODEL_FROM_DATABASE=RedOctane Guitar for PlayStation(R)3 usb:v12BAp0120* ID_MODEL_FROM_DATABASE=RedOctane Drum Kit for PlayStation(R)3 usb:v12BAp0200* ID_MODEL_FROM_DATABASE=Harmonix Guitar for PlayStation(R)3 usb:v12BAp0210* ID_MODEL_FROM_DATABASE=Harmonix Drum Kit for PlayStation(R)3 usb:v12BD* ID_VENDOR_FROM_DATABASE=Gembird usb:v12BDpD012* ID_MODEL_FROM_DATABASE=JPD Shockforce gamepad usb:v12C4* ID_VENDOR_FROM_DATABASE=Autocue Group Ltd usb:v12C4p0006* ID_MODEL_FROM_DATABASE=Teleprompter Two-button Hand Control (v1) usb:v12C4p0008* ID_MODEL_FROM_DATABASE=Teleprompter Foot Control (v1) usb:v12CF* ID_VENDOR_FROM_DATABASE=DEXIN usb:v12CFp0170* ID_MODEL_FROM_DATABASE=Tt eSPORTS BLACK Gaming mouse usb:v12D1* ID_VENDOR_FROM_DATABASE=Huawei Technologies Co., Ltd. usb:v12D1p1001* ID_MODEL_FROM_DATABASE=E169/E620/E800 HSDPA Modem usb:v12D1p1003* ID_MODEL_FROM_DATABASE=E220 HSDPA Modem / E230/E270/E870 HSDPA/HSUPA Modem usb:v12D1p1004* ID_MODEL_FROM_DATABASE=E220 (bis) usb:v12D1p1009* ID_MODEL_FROM_DATABASE=U120 usb:v12D1p1010* ID_MODEL_FROM_DATABASE=ETS2252+ CDMA Fixed Wireless Terminal usb:v12D1p1021* ID_MODEL_FROM_DATABASE=U8520 usb:v12D1p1035* ID_MODEL_FROM_DATABASE=U8120 usb:v12D1p1037* ID_MODEL_FROM_DATABASE=Ideos usb:v12D1p1038* ID_MODEL_FROM_DATABASE=Ideos (debug mode) usb:v12D1p1039* ID_MODEL_FROM_DATABASE=Ideos (tethering mode) usb:v12D1p1404* ID_MODEL_FROM_DATABASE=EM770W miniPCI WCDMA Modem usb:v12D1p1406* ID_MODEL_FROM_DATABASE=E1750 usb:v12D1p140B* ID_MODEL_FROM_DATABASE=EC1260 Wireless Data Modem HSD USB Card usb:v12D1p140C* ID_MODEL_FROM_DATABASE=E180v usb:v12D1p1412* ID_MODEL_FROM_DATABASE=EC168c usb:v12D1p1436* ID_MODEL_FROM_DATABASE=Broadband stick usb:v12D1p1446* ID_MODEL_FROM_DATABASE=Broadband stick (modem on) usb:v12D1p1465* ID_MODEL_FROM_DATABASE=K3765 HSPA usb:v12D1p14C3* ID_MODEL_FROM_DATABASE=K5005 Vodafone LTE/UMTS/GSM Modem/Networkcard usb:v12D1p14C8* ID_MODEL_FROM_DATABASE=K5005 Vodafone LTE/UMTS/GSM MOdem/Networkcard usb:v12D1p14C9* ID_MODEL_FROM_DATABASE=K3770 3G Modem usb:v12D1p14CF* ID_MODEL_FROM_DATABASE=K3772 usb:v12D1p14D1* ID_MODEL_FROM_DATABASE=K3770 3G Modem (Mass Storage Mode) usb:v12D1p14DB* ID_MODEL_FROM_DATABASE=E353/E3131 usb:v12D1p14F1* ID_MODEL_FROM_DATABASE=Gobi 3000 HSPA+ Modem usb:v12D1p14FE* ID_MODEL_FROM_DATABASE=Modem (Mass Storage Mode) usb:v12D1p1501* ID_MODEL_FROM_DATABASE=Pulse usb:v12D1p1505* ID_MODEL_FROM_DATABASE=E398 LTE/UMTS/GSM Modem/Networkcard usb:v12D1p1506* ID_MODEL_FROM_DATABASE=Modem/Networkcard usb:v12D1p150A* ID_MODEL_FROM_DATABASE=E398 LTE/UMTS/GSM Modem/Networkcard usb:v12D1p1520* ID_MODEL_FROM_DATABASE=K3765 HSPA usb:v12D1p1521* ID_MODEL_FROM_DATABASE=K4505 HSPA+ usb:v12D1p155A* ID_MODEL_FROM_DATABASE=R205 Mobile WiFi (CD-ROM mode) usb:v12D1p1575* ID_MODEL_FROM_DATABASE=K5150 LTE modem usb:v12D1p15CA* ID_MODEL_FROM_DATABASE=E3131 3G/UMTS/HSPA+ Modem (Mass Storage Mode) usb:v12D1p1805* ID_MODEL_FROM_DATABASE=AT&T Go Phone U2800A phone usb:v12D1p1C05* ID_MODEL_FROM_DATABASE=Broadband stick (modem on) usb:v12D1p1C0B* ID_MODEL_FROM_DATABASE=E173s 3G broadband stick (modem off) usb:v12D1p1C20* ID_MODEL_FROM_DATABASE=R205 Mobile WiFi (Charging) usb:v12D1p1D50* ID_MODEL_FROM_DATABASE=ET302s TD-SCDMA/TD-HSDPA Mobile Broadband usb:v12D1p1F01* ID_MODEL_FROM_DATABASE=E353/E3131 (Mass storage mode) usb:v12D1p1F16* ID_MODEL_FROM_DATABASE=K5150 LTE modem (Mass Storage Mode) usb:v12D1p380B* ID_MODEL_FROM_DATABASE=WiMAX USB modem(s) usb:v12D2* ID_VENDOR_FROM_DATABASE=LINE TECH INDUSTRIAL CO., LTD. usb:v12D6* ID_VENDOR_FROM_DATABASE=EMS Dr. Thomas Wuensche usb:v12D6p0444* ID_MODEL_FROM_DATABASE=CPC-USB/ARM7 usb:v12D6p0888* ID_MODEL_FROM_DATABASE=CPC-USB/M16C usb:v12D7* ID_VENDOR_FROM_DATABASE=BETTER WIRE FACTORY CO., LTD. usb:v12D8* ID_VENDOR_FROM_DATABASE=Araneus Information Systems Oy usb:v12D8p0001* ID_MODEL_FROM_DATABASE=Alea I True Random Number Generator usb:v12E6* ID_VENDOR_FROM_DATABASE=Waldorf Music GmbH usb:v12E6p0013* ID_MODEL_FROM_DATABASE=Blofeld usb:v12EF* ID_VENDOR_FROM_DATABASE=Tapwave, Inc. usb:v12EFp0100* ID_MODEL_FROM_DATABASE=Tapwave Handheld [Tapwave Zodiac] usb:v12F5* ID_VENDOR_FROM_DATABASE=Dynamic System Electronics Corp. usb:v12F7* ID_VENDOR_FROM_DATABASE=Memorex Products, Inc. usb:v12F7p1A00* ID_MODEL_FROM_DATABASE=TD Classic 003B usb:v12F7p1E23* ID_MODEL_FROM_DATABASE=TravelDrive 2007 Flash Drive usb:v12FD* ID_VENDOR_FROM_DATABASE=AIN Comm. Technology Co., Ltd usb:v12FDp1001* ID_MODEL_FROM_DATABASE=AWU2000b 802.11b Stick usb:v12FF* ID_VENDOR_FROM_DATABASE=Fascinating Electronics, Inc. usb:v12FFp0101* ID_MODEL_FROM_DATABASE=Advanced RC Servo Controller usb:v1307* ID_VENDOR_FROM_DATABASE=Transcend Information, Inc. usb:v1307p0163* ID_MODEL_FROM_DATABASE=256MB/512MB/1GB Flash Drive usb:v1307p0165* ID_MODEL_FROM_DATABASE=2GB/4GB/8GB Flash Drive usb:v1307p0190* ID_MODEL_FROM_DATABASE=Ut190 8 GB Flash Drive with MicroSD reader usb:v1307p0310* ID_MODEL_FROM_DATABASE=SD/MicroSD CardReader [hama] usb:v1307p0330* ID_MODEL_FROM_DATABASE=63-in-1 Multi-Card Reader/Writer usb:v1307p0361* ID_MODEL_FROM_DATABASE=CR-75: 51-in-1 Card Reader/Writer [Sakar] usb:v1307p1169* ID_MODEL_FROM_DATABASE=TS2GJF210 JetFlash 210 2GB usb:v1307p1171* ID_MODEL_FROM_DATABASE=Fingerprint Reader usb:v1308* ID_VENDOR_FROM_DATABASE=Shuttle, Inc. usb:v1308p0003* ID_MODEL_FROM_DATABASE=VFD Module usb:v1308pC001* ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver usb:v1310* ID_VENDOR_FROM_DATABASE=Roper usb:v1310p0001* ID_MODEL_FROM_DATABASE=Class 1 Bluetooth Dongle usb:v1312* ID_VENDOR_FROM_DATABASE=ICS Electronics usb:v1313* ID_VENDOR_FROM_DATABASE=ThorLabs usb:v1313p0010* ID_MODEL_FROM_DATABASE=LC1 Linear Camera (Jungo) usb:v1313p0011* ID_MODEL_FROM_DATABASE=SP1 Spectrometer (Jungo) usb:v1313p0012* ID_MODEL_FROM_DATABASE=SP2 Spectrometer (Jungo) usb:v1313p0110* ID_MODEL_FROM_DATABASE=LC1 Linear Camera (VISA) usb:v1313p0111* ID_MODEL_FROM_DATABASE=SP1 Spectrometer (VISA) usb:v1313p0112* ID_MODEL_FROM_DATABASE=SP2 Spectrometer (VISA) usb:v1313p8001* ID_MODEL_FROM_DATABASE=TXP-Series Slot (TXP5001, TXP5004) usb:v1313p8012* ID_MODEL_FROM_DATABASE=BC106 Camera Beam Profiler usb:v1313p8013* ID_MODEL_FROM_DATABASE=WFS10 Wavefront Sensor usb:v1313p8017* ID_MODEL_FROM_DATABASE=BC206 Camera Beam Profiler usb:v1313p8019* ID_MODEL_FROM_DATABASE=BP2 Multi Slit Beam Profiler usb:v1313p8020* ID_MODEL_FROM_DATABASE=PM300 Optical Power Meter usb:v1313p8021* ID_MODEL_FROM_DATABASE=PM300E Optical Power and Energy Meter usb:v1313p8022* ID_MODEL_FROM_DATABASE=PM320E Optical Power and Energy Meter usb:v1313p8030* ID_MODEL_FROM_DATABASE=ER100 Extinction Ratio Meter usb:v1313p8070* ID_MODEL_FROM_DATABASE=PM100D usb:v131D* ID_VENDOR_FROM_DATABASE=Natural Point usb:v131Dp0155* ID_MODEL_FROM_DATABASE=TrackIR 3 Pro Head Tracker usb:v131Dp0156* ID_MODEL_FROM_DATABASE=TrackIR 4 Pro Head Tracker usb:v132A* ID_VENDOR_FROM_DATABASE=Envara Inc. usb:v132Ap1502* ID_MODEL_FROM_DATABASE=WiND 802.11abg / 802.11bg WLAN usb:v132B* ID_VENDOR_FROM_DATABASE=Konica Minolta usb:v132Bp0000* ID_MODEL_FROM_DATABASE=Dimage A2 Camera usb:v132Bp0001* ID_MODEL_FROM_DATABASE=Minolta DiMAGE A2 (ptp) usb:v132Bp0003* ID_MODEL_FROM_DATABASE=Dimage Xg Camera usb:v132Bp0006* ID_MODEL_FROM_DATABASE=Dimage Z2 Camera usb:v132Bp0007* ID_MODEL_FROM_DATABASE=Minolta DiMAGE Z2 (PictBridge mode) usb:v132Bp0008* ID_MODEL_FROM_DATABASE=Dimage X21 Camera usb:v132Bp000A* ID_MODEL_FROM_DATABASE=Dimage Scan Dual IV AF-3200 (2891) usb:v132Bp000B* ID_MODEL_FROM_DATABASE=Dimage Z10 Camera usb:v132Bp000D* ID_MODEL_FROM_DATABASE=Dimage X50 Camera [storage?] usb:v132Bp000F* ID_MODEL_FROM_DATABASE=Dimage X50 Camera [p2p?] usb:v132Bp0010* ID_MODEL_FROM_DATABASE=Dimage G600 Camera usb:v132Bp0012* ID_MODEL_FROM_DATABASE=Dimage Scan Elite 5400 II (2892) usb:v132Bp0013* ID_MODEL_FROM_DATABASE=Dimage X31 Camera usb:v132Bp0015* ID_MODEL_FROM_DATABASE=Dimage G530 Camera usb:v132Bp0017* ID_MODEL_FROM_DATABASE=Dimage Z3 Camera usb:v132Bp0018* ID_MODEL_FROM_DATABASE=Minolta DiMAGE Z3 (PictBridge mode) usb:v132Bp0019* ID_MODEL_FROM_DATABASE=Dimage A200 Camera usb:v132Bp0021* ID_MODEL_FROM_DATABASE=Dimage Z5 Camera usb:v132Bp0022* ID_MODEL_FROM_DATABASE=Minolta DiMAGE Z5 (PictBridge mode) usb:v132Bp002C* ID_MODEL_FROM_DATABASE=Dynax 5D camera usb:v132Bp2001* ID_MODEL_FROM_DATABASE=Magicolor 2400w usb:v132Bp2004* ID_MODEL_FROM_DATABASE=Magicolor 5430DL usb:v132Bp2005* ID_MODEL_FROM_DATABASE=Magicolor 2430 DL usb:v132Bp2029* ID_MODEL_FROM_DATABASE=Magicolor 5440DL usb:v132Bp2030* ID_MODEL_FROM_DATABASE=PagePro 1350E(N) usb:v132Bp2033* ID_MODEL_FROM_DATABASE=PagePro 1400W usb:v132Bp2043* ID_MODEL_FROM_DATABASE=Magicolor 2530DL usb:v132Bp2045* ID_MODEL_FROM_DATABASE=Magicolor 2500W usb:v132Bp2049* ID_MODEL_FROM_DATABASE=Magicolor 2490MF usb:v133E* ID_VENDOR_FROM_DATABASE=Kemper Digital GmbH usb:v133Ep0815* ID_MODEL_FROM_DATABASE=Virus TI Desktop usb:v1342* ID_VENDOR_FROM_DATABASE=Mobility usb:v1342p0200* ID_MODEL_FROM_DATABASE=EasiDock 200 Hub usb:v1342p0201* ID_MODEL_FROM_DATABASE=EasiDock 200 Keyboard and Mouse Port usb:v1342p0202* ID_MODEL_FROM_DATABASE=EasiDock 200 Serial Port usb:v1342p0203* ID_MODEL_FROM_DATABASE=EasiDock 200 Printer Port usb:v1342p0204* ID_MODEL_FROM_DATABASE=Ethernet usb:v1342p0304* ID_MODEL_FROM_DATABASE=EasiDock Ethernet usb:v1343* ID_VENDOR_FROM_DATABASE=Citizen Systems usb:v1343p0003* ID_MODEL_FROM_DATABASE=CX / DNP DS40 usb:v1343p0004* ID_MODEL_FROM_DATABASE=CX-W / DNP DS80 usb:v1343p0005* ID_MODEL_FROM_DATABASE=CY / DNP DSRX usb:v1345* ID_VENDOR_FROM_DATABASE=Sino Lite Technology Corp. usb:v1345p001C* ID_MODEL_FROM_DATABASE=Xbox Controller Hub usb:v1345p6006* ID_MODEL_FROM_DATABASE=Defender Wireless Controller usb:v1347* ID_VENDOR_FROM_DATABASE=Moravian Instruments usb:v1347p0400* ID_MODEL_FROM_DATABASE=G2CCD USB 1.1 obsolete usb:v1347p0401* ID_MODEL_FROM_DATABASE=G2CCD-S with Sony ICX285 CCD usb:v1347p0402* ID_MODEL_FROM_DATABASE=G2CCD2 usb:v1347p0403* ID_MODEL_FROM_DATABASE=G2/G3CCD-I KAI CCD usb:v1347p0404* ID_MODEL_FROM_DATABASE=G2/G3/G4 CCD-F KAF CCD usb:v1347p0405* ID_MODEL_FROM_DATABASE=Gx CCD-I CCD usb:v1347p0406* ID_MODEL_FROM_DATABASE=Gx CCD-F CCD usb:v1347p0410* ID_MODEL_FROM_DATABASE=G1-0400 CCD usb:v1347p0411* ID_MODEL_FROM_DATABASE=G1-0800 CCD usb:v1347p0412* ID_MODEL_FROM_DATABASE=G1-0300 CCD usb:v1347p0413* ID_MODEL_FROM_DATABASE=G1-2000 CCD usb:v1347p0414* ID_MODEL_FROM_DATABASE=G1-1400 CCD usb:v1348* ID_VENDOR_FROM_DATABASE=Katsuragawa Electric Co., Ltd. usb:v134C* ID_VENDOR_FROM_DATABASE=PanJit International Inc. usb:v134Cp0001* ID_MODEL_FROM_DATABASE=Touch Panel Controller usb:v134Cp0002* ID_MODEL_FROM_DATABASE=Touch Panel Controller usb:v134Cp0003* ID_MODEL_FROM_DATABASE=Touch Panel Controller usb:v134Cp0004* ID_MODEL_FROM_DATABASE=Touch Panel Controller usb:v134E* ID_VENDOR_FROM_DATABASE=Digby's Bitpile, Inc. DBA D Bit usb:v1357* ID_VENDOR_FROM_DATABASE=P&E Microcomputer Systems usb:v1357p0089* ID_MODEL_FROM_DATABASE=OpenSDA - CDC Serial Port usb:v1357p0503* ID_MODEL_FROM_DATABASE=USB-ML-12 HCS08/HCS12 Multilink usb:v1357p0504* ID_MODEL_FROM_DATABASE=DEMOJM usb:v135F* ID_VENDOR_FROM_DATABASE=Control Development Inc. usb:v135Fp0110* ID_MODEL_FROM_DATABASE=Linear Spectrograph usb:v135Fp0111* ID_MODEL_FROM_DATABASE=Spectrograph - Renumerated usb:v135Fp0200* ID_MODEL_FROM_DATABASE=Linear Spectrograph usb:v135Fp0201* ID_MODEL_FROM_DATABASE=Spectrograph - Renumerated usb:v135Fp0240* ID_MODEL_FROM_DATABASE=MPP Spectrograph usb:v1366* ID_VENDOR_FROM_DATABASE=SEGGER usb:v1366p0101* ID_MODEL_FROM_DATABASE=J-Link PLUS usb:v136B* ID_VENDOR_FROM_DATABASE=STEC usb:v136E* ID_VENDOR_FROM_DATABASE=Andor Technology Ltd. usb:v136Ep0014* ID_MODEL_FROM_DATABASE=Zyla 5.5 sCMOS camera usb:v1370* ID_VENDOR_FROM_DATABASE=Swissbit usb:v1370p0323* ID_MODEL_FROM_DATABASE=Swissmemory cirrusWHITE usb:v1370p6828* ID_MODEL_FROM_DATABASE=Victorinox Flash Drive usb:v1371* ID_VENDOR_FROM_DATABASE=CNet Technology Inc. usb:v1371p0001* ID_MODEL_FROM_DATABASE=CNUSB-611AR Wireless Adapter-G [AT76C503] usb:v1371p0002* ID_MODEL_FROM_DATABASE=CNUSB-611AR Wireless Adapter-G [AT76C503] (FiberLine WL-240U) usb:v1371p0013* ID_MODEL_FROM_DATABASE=CNUSB-611 Wireless Adapter [AT76C505] usb:v1371p0014* ID_MODEL_FROM_DATABASE=CNUSB-611 Wireless Adapter [AT76C505] (FiberLine WL-240U) usb:v1371p5743* ID_MODEL_FROM_DATABASE=CNUSB-611 (D) Wireless Adapter [AT76C503] usb:v1371p9022* ID_MODEL_FROM_DATABASE=CWD-854 [RT2573] usb:v1371p9032* ID_MODEL_FROM_DATABASE=CWD-854 rev F usb:v1371p9401* ID_MODEL_FROM_DATABASE=CWD-854 Wireless 802.11g 54Mbps Network Adapter [RTL8187] usb:v1376* ID_VENDOR_FROM_DATABASE=Vimtron Electronics Co., Ltd. usb:v137B* ID_VENDOR_FROM_DATABASE=SCAPS GmbH usb:v137Bp0002* ID_MODEL_FROM_DATABASE=SCAPS USC-2 Scanner Controller usb:v1385* ID_VENDOR_FROM_DATABASE=Netgear, Inc usb:v1385p4250* ID_MODEL_FROM_DATABASE=WG111T usb:v1385p4251* ID_MODEL_FROM_DATABASE=WG111T (no firmware) usb:v1385p5F00* ID_MODEL_FROM_DATABASE=WPN111 RangeMax(TM) Wireless USB 2.0 Adapter usb:v1385p5F01* ID_MODEL_FROM_DATABASE=WPN111 (no firmware) usb:v1385p5F02* ID_MODEL_FROM_DATABASE=WPN111 (no firmware) usb:v1385p6E00* ID_MODEL_FROM_DATABASE=WPNT121 802.11g 240Mbps Wireless Adapter [Airgo AGN300] usb:v138A* ID_VENDOR_FROM_DATABASE=Validity Sensors, Inc. usb:v138Ap0001* ID_MODEL_FROM_DATABASE=VFS101 Fingerprint Reader usb:v138Ap0005* ID_MODEL_FROM_DATABASE=VFS301 Fingerprint Reader usb:v138Ap0007* ID_MODEL_FROM_DATABASE=VFS451 Fingerprint Reader usb:v138Ap0008* ID_MODEL_FROM_DATABASE=VFS300 Fingerprint Reader usb:v138Ap0010* ID_MODEL_FROM_DATABASE=VFS Fingerprint sensor usb:v138Ap0011* ID_MODEL_FROM_DATABASE=VFS5011 Fingerprint Reader usb:v138Ap0017* ID_MODEL_FROM_DATABASE=Fingerprint Reader usb:v138Ap0018* ID_MODEL_FROM_DATABASE=Fingerprint scanner usb:v138Ap003C* ID_MODEL_FROM_DATABASE=VFS471 Fingerprint Reader usb:v138Ap003D* ID_MODEL_FROM_DATABASE=VFS491 usb:v138Ap003F* ID_MODEL_FROM_DATABASE=VFS495 Fingerprint Reader usb:v138Ap0050* ID_MODEL_FROM_DATABASE=Swipe Fingerprint Sensor usb:v138E* ID_VENDOR_FROM_DATABASE=Jungo LTD usb:v138Ep9000* ID_MODEL_FROM_DATABASE=Raisonance S.A. STM32 ARM evaluation board usb:v1390* ID_VENDOR_FROM_DATABASE=TOMTOM B.V. usb:v1390p0001* ID_MODEL_FROM_DATABASE=GO 520 T/GO 630/ONE XL (v9) usb:v1390p5454* ID_MODEL_FROM_DATABASE=Blue & Me 2 usb:v1390p7474* ID_MODEL_FROM_DATABASE=GPS Sport Watch [Runner, Multi-Sport] usb:v1391* ID_VENDOR_FROM_DATABASE=IdealTEK, Inc. usb:v1391p1000* ID_MODEL_FROM_DATABASE=URTC-1000 usb:v1395* ID_VENDOR_FROM_DATABASE=Sennheiser Communications usb:v1395p3556* ID_MODEL_FROM_DATABASE=USB Headset usb:v1397* ID_VENDOR_FROM_DATABASE=BEHRINGER International GmbH usb:v1397p00BC* ID_MODEL_FROM_DATABASE=BCF2000 usb:v1398* ID_VENDOR_FROM_DATABASE=Q-tec usb:v1398p2103* ID_MODEL_FROM_DATABASE=USB 2.0 Storage Device usb:v13AD* ID_VENDOR_FROM_DATABASE=Baltech usb:v13ADp9999* ID_MODEL_FROM_DATABASE=Card reader usb:v13B0* ID_VENDOR_FROM_DATABASE=PerkinElmer Optoelectronics usb:v13B0p000A* ID_MODEL_FROM_DATABASE=Alesis Photon X25 MIDI Controller usb:v13B1* ID_VENDOR_FROM_DATABASE=Linksys usb:v13B1p000A* ID_MODEL_FROM_DATABASE=WUSB54G v2 802.11g Adapter [Intersil ISL3887] usb:v13B1p000B* ID_MODEL_FROM_DATABASE=WUSB11 v4.0 802.11b Adapter [ALi M4301] usb:v13B1p000C* ID_MODEL_FROM_DATABASE=WUSB54AG 802.11a/g Adapter [Intersil ISL3887] usb:v13B1p000D* ID_MODEL_FROM_DATABASE=WUSB54G v4 802.11g Adapter [Ralink RT2500USB] usb:v13B1p000E* ID_MODEL_FROM_DATABASE=WUSB54GS v1 802.11g Adapter [Broadcom 4320 USB] usb:v13B1p0011* ID_MODEL_FROM_DATABASE=WUSB54GP v4.0 802.11g Adapter [Ralink RT2500USB] usb:v13B1p0014* ID_MODEL_FROM_DATABASE=WUSB54GS v2 802.11g Adapter [Broadcom 4320 USB] usb:v13B1p0018* ID_MODEL_FROM_DATABASE=USB200M 10/100 Ethernet Adapter usb:v13B1p001A* ID_MODEL_FROM_DATABASE=HU200TS Wireless Adapter usb:v13B1p001E* ID_MODEL_FROM_DATABASE=WUSBF54G 802.11bg usb:v13B1p0020* ID_MODEL_FROM_DATABASE=WUSB54GC v1 802.11g Adapter [Ralink RT73] usb:v13B1p0022* ID_MODEL_FROM_DATABASE=WUSB54GX4 802.11g 240Mbps Wireless Adapter [Airgo AGN300] usb:v13B1p0023* ID_MODEL_FROM_DATABASE=WUSB54GR usb:v13B1p0024* ID_MODEL_FROM_DATABASE=WUSBF54G v1.1 802.11bg usb:v13B1p0026* ID_MODEL_FROM_DATABASE=WUSB54GSC v1 802.11g Adapter [Broadcom 4320 USB] usb:v13B1p0028* ID_MODEL_FROM_DATABASE=WUSB200 802.11g Adapter [Ralink RT2671] usb:v13B1p0029* ID_MODEL_FROM_DATABASE=WUSB300N 802.11bgn Wireless Adapter [Marvell 88W8362+88W8060] usb:v13B1p002F* ID_MODEL_FROM_DATABASE=AE1000 v1 802.11n [Ralink RT3572] usb:v13B1p0031* ID_MODEL_FROM_DATABASE=AM10 v1 802.11n [Ralink RT3072] usb:v13B1p0039* ID_MODEL_FROM_DATABASE=AE1200 802.11bgn Wireless Adapter [Broadcom BCM43235] usb:v13B1p003A* ID_MODEL_FROM_DATABASE=AE2500 802.11abgn Wireless Adapter [Broadcom BCM43236] usb:v13B1p003B* ID_MODEL_FROM_DATABASE=AE3000 802.11abgn (3x3) Wireless Adapter [Ralink RT3573] usb:v13B1p003E* ID_MODEL_FROM_DATABASE=AE6000 802.11a/b/g/n/ac Wireless Adapter [MediaTek MT7610U] usb:v13B1p003F* ID_MODEL_FROM_DATABASE=WUSB6300 802.11a/b/g/n/ac Wireless Adapter [Realtek RTL8812AU] usb:v13B1p13B1* ID_MODEL_FROM_DATABASE=WUSB200: Wireless-G Business Network Adapter with Rangebooster usb:v13B2* ID_VENDOR_FROM_DATABASE=Alesis usb:v13B2p0030* ID_MODEL_FROM_DATABASE=Multimix 8 usb:v13B3* ID_VENDOR_FROM_DATABASE=Nippon Dics Co., Ltd. usb:v13BA* ID_VENDOR_FROM_DATABASE=PCPlay usb:v13BAp0001* ID_MODEL_FROM_DATABASE=Konig Electronic CMP-KEYPAD12 Numeric Keypad usb:v13BAp0017* ID_MODEL_FROM_DATABASE=PS/2 Keyboard+Mouse Adapter usb:v13BAp0018* ID_MODEL_FROM_DATABASE=Barcode PCP-BCG4209 usb:v13BE* ID_VENDOR_FROM_DATABASE=Ricoh Printing Systems, Ltd. usb:v13CA* ID_VENDOR_FROM_DATABASE=JyeTai Precision Industrial Co., Ltd. usb:v13CF* ID_VENDOR_FROM_DATABASE=Wisair Ltd. usb:v13CFp1200* ID_MODEL_FROM_DATABASE=Olidata Wireless Multimedia Adapter usb:v13D0* ID_VENDOR_FROM_DATABASE=Techsan Electronics Co., Ltd. usb:v13D0p2282* ID_MODEL_FROM_DATABASE=TechniSat DVB-PC TV Star 2 usb:v13D1* ID_VENDOR_FROM_DATABASE=A-Max Technology Macao Commercial Offshore Co. Ltd. usb:v13D1p7019* ID_MODEL_FROM_DATABASE=MD 82288 usb:v13D1pABE6* ID_MODEL_FROM_DATABASE=Wireless 802.11g 54Mbps Network Adapter [RTL8187] usb:v13D2* ID_VENDOR_FROM_DATABASE=Shark Multimedia usb:v13D2p0400* ID_MODEL_FROM_DATABASE=Pocket Ethernet [klsi] usb:v13D3* ID_VENDOR_FROM_DATABASE=IMC Networks usb:v13D3p3201* ID_MODEL_FROM_DATABASE=VisionDTV USB-Ter/HAMA USB DVB-T device cold usb:v13D3p3202* ID_MODEL_FROM_DATABASE=VisionDTV USB-Ter/HAMA USB DVB-T device warm usb:v13D3p3203* ID_MODEL_FROM_DATABASE=DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) usb:v13D3p3204* ID_MODEL_FROM_DATABASE=DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) usb:v13D3p3205* ID_MODEL_FROM_DATABASE=DNTV Live! Tiny USB2 BDA (No Remote) usb:v13D3p3206* ID_MODEL_FROM_DATABASE=DNTV Live! Tiny USB2 BDA (No Remote) usb:v13D3p3207* ID_MODEL_FROM_DATABASE=DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) usb:v13D3p3208* ID_MODEL_FROM_DATABASE=DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) usb:v13D3p3209* ID_MODEL_FROM_DATABASE=DTV-DVB UDST7022BDA DVB-S Box(Without HID) usb:v13D3p3211* ID_MODEL_FROM_DATABASE=DTV-DVB Hybrid Analog/Capture / Pinnacle PCTV 310e usb:v13D3p3212* ID_MODEL_FROM_DATABASE=DTV-DVB UDTT704C - DVBT/NTSC/PAL Driver(PCM4) usb:v13D3p3213* ID_MODEL_FROM_DATABASE=DTV-DVB UDTT704D - DVBT/NTSC/PAL Driver (PCM4) usb:v13D3p3214* ID_MODEL_FROM_DATABASE=DTV-DVB UDTT704F -(MiniCard) DVBT/NTSC/PAL Driver(Without HID) usb:v13D3p3215* ID_MODEL_FROM_DATABASE=DTV-DVB UDAT7240 - ATSC/NTSC/PAL Driver(PCM4) usb:v13D3p3216* ID_MODEL_FROM_DATABASE=DTV-DVB UDTT 7047-USB 2.0 DVB-T Driver usb:v13D3p3217* ID_MODEL_FROM_DATABASE=Digital-TV Receiver. usb:v13D3p3219* ID_MODEL_FROM_DATABASE=DTV-DVB UDTT7049 - DVB-T Driver(Without HID) usb:v13D3p3220* ID_MODEL_FROM_DATABASE=DTV-DVB UDTT 7047M-USB 2.0 DVB-T Driver usb:v13D3p3223* ID_MODEL_FROM_DATABASE=DNTV Live! Tiny USB2 BDA (No Remote) usb:v13D3p3224* ID_MODEL_FROM_DATABASE=DNTV Live! Tiny USB2 BDA (No Remote) usb:v13D3p3226* ID_MODEL_FROM_DATABASE=DigitalNow TinyTwin DVB-T Receiver usb:v13D3p3234* ID_MODEL_FROM_DATABASE=DVB-T FTA Half Minicard [RTL2832U] usb:v13D3p3236* ID_MODEL_FROM_DATABASE=DTV-DVB UDTT 7047A-USB 2.0 DVB-T Driver usb:v13D3p3237* ID_MODEL_FROM_DATABASE=DTV-DVB UDTT 704J - dual DVB-T Driver usb:v13D3p3239* ID_MODEL_FROM_DATABASE=DTV-DVB UDTT704D - DVBT/NTSC/PAL Driver(Without HID) usb:v13D3p3240* ID_MODEL_FROM_DATABASE=DTV-DVB UDXTTM6010 - A/D Driver(Without HID) usb:v13D3p3241* ID_MODEL_FROM_DATABASE=DTV-DVB UDXTTM6010 - A/D Driver(Without HID) usb:v13D3p3242* ID_MODEL_FROM_DATABASE=DTV-DVB UDAT7240LP - ATSC/NTSC/PAL Driver(Without HID) usb:v13D3p3243* ID_MODEL_FROM_DATABASE=DTV-DVB UDXTTM6010 - A/D Driver(Without HID) usb:v13D3p3244* ID_MODEL_FROM_DATABASE=DTV-DVB UDTT 7047Z-USB 2.0 DVB-T Driver usb:v13D3p3247* ID_MODEL_FROM_DATABASE=802.11 n/g/b Wireless LAN Adapter usb:v13D3p3249* ID_MODEL_FROM_DATABASE=Internal Bluetooth usb:v13D3p3262* ID_MODEL_FROM_DATABASE=802.11 n/g/b Wireless LAN USB Adapter usb:v13D3p3273* ID_MODEL_FROM_DATABASE=802.11 n/g/b Wireless LAN USB Mini-Card usb:v13D3p3274* ID_MODEL_FROM_DATABASE=DVB-T Dongle [RTL2832U] usb:v13D3p3282* ID_MODEL_FROM_DATABASE=DVB-T + GPS Minicard [RTL2832U] usb:v13D3p3284* ID_MODEL_FROM_DATABASE=Wireless LAN USB Mini-Card usb:v13D3p3304* ID_MODEL_FROM_DATABASE=Asus Integrated Bluetooth module [AR3011] usb:v13D3p3306* ID_MODEL_FROM_DATABASE=Mediao 802.11n WLAN [Realtek RTL8191SU] usb:v13D3p3315* ID_MODEL_FROM_DATABASE=Bluetooth module usb:v13D3p3362* ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth 4.0 Adapter usb:v13D3p3375* ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth 4.0 Adapter usb:v13D3p3392* ID_MODEL_FROM_DATABASE=Azurewave 43228+20702 usb:v13D3p3394* ID_MODEL_FROM_DATABASE=Bluetooth usb:v13D3p3474* ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth usb:v13D3p5070* ID_MODEL_FROM_DATABASE=Webcam usb:v13D3p5111* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v13D3p5115* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v13D3p5116* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v13D3p5122* ID_MODEL_FROM_DATABASE=2M Integrated Webcam usb:v13D3p5126* ID_MODEL_FROM_DATABASE=PC Cam usb:v13D3p5130* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v13D3p5702* ID_MODEL_FROM_DATABASE=UVC VGA Webcam usb:v13D3p5710* ID_MODEL_FROM_DATABASE=UVC VGA Webcam usb:v13D3p5716* ID_MODEL_FROM_DATABASE=UVC VGA Webcam usb:v13D3p7020* ID_MODEL_FROM_DATABASE=DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) usb:v13D3p7022* ID_MODEL_FROM_DATABASE=DTV-DVB UDST7022BDA DVB-S Box(Without HID) usb:v13D7* ID_VENDOR_FROM_DATABASE=Guidance Software, Inc. usb:v13D7p0001* ID_MODEL_FROM_DATABASE=T5 PATA forensic bridge usb:v13DC* ID_VENDOR_FROM_DATABASE=ALEREON, INC. usb:v13DD* ID_VENDOR_FROM_DATABASE=i.Tech Dynamic Limited usb:v13E1* ID_VENDOR_FROM_DATABASE=Kaibo Wire & Cable (Shenzhen) Co., Ltd. usb:v13E5* ID_VENDOR_FROM_DATABASE=Rane usb:v13E5p0001* ID_MODEL_FROM_DATABASE=SL-1 usb:v13E5p0003* ID_MODEL_FROM_DATABASE=TTM 57SL usb:v13E6* ID_VENDOR_FROM_DATABASE=TechnoScope Co., Ltd. usb:v13EA* ID_VENDOR_FROM_DATABASE=Hengstler usb:v13EAp0001* ID_MODEL_FROM_DATABASE=C-56 Thermal Printer usb:v13EC* ID_VENDOR_FROM_DATABASE=Zydacron usb:v13ECp0006* ID_MODEL_FROM_DATABASE=HID Remote Control usb:v13EE* ID_VENDOR_FROM_DATABASE=MosArt usb:v13EEp0001* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v13EEp0003* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v13FD* ID_VENDOR_FROM_DATABASE=Initio Corporation usb:v13FDp0840* ID_MODEL_FROM_DATABASE=INIC-1618L SATA usb:v13FDp0841* ID_MODEL_FROM_DATABASE=Samsung SE-T084M DVD-RW usb:v13FDp1040* ID_MODEL_FROM_DATABASE=INIC-1511L PATA Bridge usb:v13FDp1340* ID_MODEL_FROM_DATABASE=Hi-Speed USB to SATA Bridge usb:v13FDp160F* ID_MODEL_FROM_DATABASE=RocketFish SATA Bridge [INIC-1611] usb:v13FDp1640* ID_MODEL_FROM_DATABASE=INIC-1610L SATA Bridge usb:v13FDp1669* ID_MODEL_FROM_DATABASE=INIC-1609PN usb:v13FDp1840* ID_MODEL_FROM_DATABASE=INIC-1608 SATA bridge usb:v13FDp1E40* ID_MODEL_FROM_DATABASE=INIC-1610P SATA bridge usb:v13FE* ID_VENDOR_FROM_DATABASE=Kingston Technology Company Inc. usb:v13FEp1A00* ID_MODEL_FROM_DATABASE=512MB/1GB Flash Drive usb:v13FEp1A23* ID_MODEL_FROM_DATABASE=512MB Flash Drive usb:v13FEp1D00* ID_MODEL_FROM_DATABASE=DataTraveler 2.0 1GB/4GB Flash Drive / Patriot Xporter 4GB Flash Drive usb:v13FEp1E00* ID_MODEL_FROM_DATABASE=Flash Drive 2 GB [ICIDU 2 GB] usb:v13FEp1E50* ID_MODEL_FROM_DATABASE=U3 Smart Drive usb:v13FEp1F00* ID_MODEL_FROM_DATABASE=Kingston DataTraveler / Patriot Xporter usb:v13FEp1F23* ID_MODEL_FROM_DATABASE=PS2232 flash drive controller usb:v13FEp2240* ID_MODEL_FROM_DATABASE=microSD card reader usb:v13FEp3100* ID_MODEL_FROM_DATABASE=2/4 GB stick usb:v13FEp3123* ID_MODEL_FROM_DATABASE=Verbatim STORE N GO 4GB usb:v13FEp3600* ID_MODEL_FROM_DATABASE=flash drive (4GB, EMTEC) usb:v13FEp3800* ID_MODEL_FROM_DATABASE=Rage XT Flash Drive usb:v13FEp3E00* ID_MODEL_FROM_DATABASE=Flash Drive usb:v13FEp4100* ID_MODEL_FROM_DATABASE=Flash drive usb:v13FEp5000* ID_MODEL_FROM_DATABASE=USB flash drive (32 GB SHARKOON Accelerate) usb:v13FEp5100* ID_MODEL_FROM_DATABASE=Flash Drive usb:v1400* ID_VENDOR_FROM_DATABASE=Axxion Group Corp. usb:v1402* ID_VENDOR_FROM_DATABASE=Bowe Bell & Howell usb:v1403* ID_VENDOR_FROM_DATABASE=Sitronix usb:v1403p0001* ID_MODEL_FROM_DATABASE=Digital Photo Frame usb:v1409* ID_VENDOR_FROM_DATABASE=IDS Imaging Development Systems GmbH usb:v1409p1000* ID_MODEL_FROM_DATABASE=generic (firmware not loaded yet) usb:v1409p1485* ID_MODEL_FROM_DATABASE=uEye UI1485 usb:v140E* ID_VENDOR_FROM_DATABASE=Telechips, Inc. usb:v140EpB011* ID_MODEL_FROM_DATABASE=TCC780X-based player (USB Boot mode) usb:v140EpB021* ID_MODEL_FROM_DATABASE=TCC77X-based players (USB Boot mode) usb:v1410* ID_VENDOR_FROM_DATABASE=Novatel Wireless usb:v1410p1110* ID_MODEL_FROM_DATABASE=Merlin S620 usb:v1410p1120* ID_MODEL_FROM_DATABASE=Merlin EX720 usb:v1410p1130* ID_MODEL_FROM_DATABASE=Merlin S720 usb:v1410p1400* ID_MODEL_FROM_DATABASE=Merlin U730/U740 (Vodafone) usb:v1410p1410* ID_MODEL_FROM_DATABASE=Merlin U740 (non-Vodafone) usb:v1410p1430* ID_MODEL_FROM_DATABASE=Merlin XU870 usb:v1410p1450* ID_MODEL_FROM_DATABASE=Merlin X950D usb:v1410p2110* ID_MODEL_FROM_DATABASE=Ovation U720/MCD3000 usb:v1410p2410* ID_MODEL_FROM_DATABASE=Expedite EU740 usb:v1410p2420* ID_MODEL_FROM_DATABASE=Expedite EU850D/EU860D/EU870D usb:v1410p4100* ID_MODEL_FROM_DATABASE=U727 usb:v1410p4400* ID_MODEL_FROM_DATABASE=Ovation MC930D/MC950D usb:v1410p9010* ID_MODEL_FROM_DATABASE=Expedite E362 usb:v1410pA001* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem usb:v1410pA008* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) usb:v1410pB001* ID_MODEL_FROM_DATABASE=Ovation MC551 usb:v1415* ID_VENDOR_FROM_DATABASE=Nam Tai E&E Products Ltd. or OmniVision Technologies, Inc. usb:v1415p0000* ID_MODEL_FROM_DATABASE=Sony SingStar USBMIC usb:v1415p0020* ID_MODEL_FROM_DATABASE=Sony Wireless SingStar usb:v1415p2000* ID_MODEL_FROM_DATABASE=Sony Playstation Eye usb:v1419* ID_VENDOR_FROM_DATABASE=ABILITY ENTERPRISE CO., LTD. usb:v1421* ID_VENDOR_FROM_DATABASE=Sensor Technology usb:v1421p0605* ID_MODEL_FROM_DATABASE=Sentech Camera usb:v1429* ID_VENDOR_FROM_DATABASE=Vega Technologies Industrial (Austria) Co. usb:v142A* ID_VENDOR_FROM_DATABASE=Thales E-Transactions usb:v142Ap0003* ID_MODEL_FROM_DATABASE=Artema Hybrid usb:v142Ap0005* ID_MODEL_FROM_DATABASE=Artema Modular usb:v142Ap0043* ID_MODEL_FROM_DATABASE=medCompact usb:v142B* ID_VENDOR_FROM_DATABASE=Arbiter Systems, Inc. usb:v142Bp03A5* ID_MODEL_FROM_DATABASE=933A Portable Power Sentinel usb:v1430* ID_VENDOR_FROM_DATABASE=RedOctane usb:v1430p0150* ID_MODEL_FROM_DATABASE=wireless receiver for skylanders wii usb:v1430p4734* ID_MODEL_FROM_DATABASE=Guitar Hero4 hub usb:v1430p474B* ID_MODEL_FROM_DATABASE=Guitar Hero MIDI interface usb:v1431* ID_VENDOR_FROM_DATABASE=Pertech Resources, Inc. usb:v1435* ID_VENDOR_FROM_DATABASE=Wistron NeWeb usb:v1435p0427* ID_MODEL_FROM_DATABASE=UR054g 802.11g Wireless Adapter [Intersil ISL3887] usb:v1435p0711* ID_MODEL_FROM_DATABASE=UR055G 802.11bg usb:v1435p0804* ID_MODEL_FROM_DATABASE=AR9170+AR9104 802.11abgn Wireless Adapter usb:v1435p0826* ID_MODEL_FROM_DATABASE=AR5523 usb:v1435p0827* ID_MODEL_FROM_DATABASE=AR5523 (no firmware) usb:v1435p0828* ID_MODEL_FROM_DATABASE=AR5523 usb:v1435p0829* ID_MODEL_FROM_DATABASE=AR5523 (no firmware) usb:v1436* ID_VENDOR_FROM_DATABASE=Denali Software, Inc. usb:v143C* ID_VENDOR_FROM_DATABASE=Altek Corporation usb:v1443* ID_VENDOR_FROM_DATABASE=Digilent usb:v1443p0007* ID_MODEL_FROM_DATABASE=Development board JTAG usb:v1446* ID_VENDOR_FROM_DATABASE=X.J.GROUP usb:v1446p6A73* ID_MODEL_FROM_DATABASE=Stamps.com Model 510 5LB Scale usb:v1446p6A78* ID_MODEL_FROM_DATABASE=DYMO Endicia 75lb Digital Scale usb:v1453* ID_VENDOR_FROM_DATABASE=Radio Shack usb:v1453p4026* ID_MODEL_FROM_DATABASE=26-183 Serial Cable usb:v1456* ID_VENDOR_FROM_DATABASE=Extending Wire & Cable Co., Ltd. usb:v1457* ID_VENDOR_FROM_DATABASE=First International Computer, Inc. usb:v1457p5117* ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 kernel usbnet (g_ether, CDC Ethernet) mode usb:v1457p5118* ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 Debug board (V2+) usb:v1457p5119* ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 u-boot cdc_acm serial port usb:v1457p511A* ID_MODEL_FROM_DATABASE=HXD8 u-boot usbtty CDC ACM Mode usb:v1457p511B* ID_MODEL_FROM_DATABASE=SMDK2440 u-boot usbtty CDC ACM mode usb:v1457p511C* ID_MODEL_FROM_DATABASE=SMDK2443 u-boot usbtty CDC ACM mode usb:v1457p511D* ID_MODEL_FROM_DATABASE=QT2410 u-boot usbtty CDC ACM mode usb:v1457p5120* ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 u-boot usbtty generic serial usb:v1457p5121* ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 kernel mass storage (g_storage) mode usb:v1457p5122* ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 / Neo Freerunner kernel cdc_ether USB network usb:v1457p5123* ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 internal USB CSR4 module usb:v1457p5124* ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 Bluetooth Device ID service usb:v145F* ID_VENDOR_FROM_DATABASE=Trust usb:v145Fp0106* ID_MODEL_FROM_DATABASE=Trust K56 V92 USB Modem usb:v145Fp013D* ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV7660) usb:v145Fp013F* ID_MODEL_FROM_DATABASE=Megapixel Auto Focus Webcam usb:v145Fp0142* ID_MODEL_FROM_DATABASE=WB-6250X Webcam usb:v145Fp015A* ID_MODEL_FROM_DATABASE=WB-8300X 2MP Webcam usb:v145Fp0161* ID_MODEL_FROM_DATABASE=15901 802.11bg Wireless Adapter [Realtek RTL8187L] usb:v145Fp0167* ID_MODEL_FROM_DATABASE=Widescreen 3MP Webcam usb:v145Fp0176* ID_MODEL_FROM_DATABASE=Isla Keyboard usb:v1460* ID_VENDOR_FROM_DATABASE=Tatung Co. usb:v1460p9150* ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver usb:v1461* ID_VENDOR_FROM_DATABASE=Staccato Communications usb:v1462* ID_VENDOR_FROM_DATABASE=Micro Star International usb:v1462p5512* ID_MODEL_FROM_DATABASE=MegaStick-1 Flash Stick usb:v1462p8807* ID_MODEL_FROM_DATABASE=DIGIVOX mini III [af9015] usb:v1472* ID_VENDOR_FROM_DATABASE=Huawei-3Com usb:v1472p0007* ID_MODEL_FROM_DATABASE=Aolynk WUB300g [ZyDAS ZD1211] usb:v1472p0009* ID_MODEL_FROM_DATABASE=Aolynk WUB320g usb:v147A* ID_VENDOR_FROM_DATABASE=Formosa Industrial Computing, Inc. usb:v147ApE015* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v147ApE016* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v147ApE017* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v147ApE018* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v147ApE02C* ID_MODEL_FROM_DATABASE=Infrared Receiver usb:v147ApE03A* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v147ApE03C* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v147ApE03D* ID_MODEL_FROM_DATABASE=2 Channel Audio usb:v147ApE03E* ID_MODEL_FROM_DATABASE=Infrared Receiver [IR605A/Q] usb:v147E* ID_VENDOR_FROM_DATABASE=Upek usb:v147Ep1000* ID_MODEL_FROM_DATABASE=Biometric Touchchip/Touchstrip Fingerprint Sensor usb:v147Ep1001* ID_MODEL_FROM_DATABASE=TCS5B Fingerprint sensor usb:v147Ep1002* ID_MODEL_FROM_DATABASE=Biometric Touchchip/Touchstrip Fingerprint Sensor usb:v147Ep2016* ID_MODEL_FROM_DATABASE=Biometric Touchchip/Touchstrip Fingerprint Sensor usb:v147Ep2020* ID_MODEL_FROM_DATABASE=TouchChip Fingerprint Coprocessor (WBF advanced mode) usb:v147Ep3000* ID_MODEL_FROM_DATABASE=TCS1C EIM/Cypress Fingerprint sensor usb:v147Ep3001* ID_MODEL_FROM_DATABASE=TCS1C EIM/STM32 Fingerprint sensor usb:v147F* ID_VENDOR_FROM_DATABASE=Hama GmbH & Co., KG usb:v1482* ID_VENDOR_FROM_DATABASE=Vaillant usb:v1482p1005* ID_MODEL_FROM_DATABASE=VRD PC-Interface usb:v1484* ID_VENDOR_FROM_DATABASE=Elsa AG [hex] usb:v1484p1746* ID_MODEL_FROM_DATABASE=Ecomo 19H99 Monitor usb:v1484p7616* ID_MODEL_FROM_DATABASE=Elsa Hub usb:v1485* ID_VENDOR_FROM_DATABASE=Silicom usb:v1485p0001* ID_MODEL_FROM_DATABASE=U2E usb:v1485p0002* ID_MODEL_FROM_DATABASE=Psion Gold Port Ethernet usb:v1487* ID_VENDOR_FROM_DATABASE=DSP Group, Ltd. usb:v148E* ID_VENDOR_FROM_DATABASE=EVATRONIX SA usb:v148F* ID_VENDOR_FROM_DATABASE=Ralink Technology, Corp. usb:v148Fp1000* ID_MODEL_FROM_DATABASE=Motorola BC4 Bluetooth 3.0+HS Adapter usb:v148Fp1706* ID_MODEL_FROM_DATABASE=RT2500USB Wireless Adapter usb:v148Fp2070* ID_MODEL_FROM_DATABASE=RT2070 Wireless Adapter usb:v148Fp2570* ID_MODEL_FROM_DATABASE=RT2570 Wireless Adapter usb:v148Fp2573* ID_MODEL_FROM_DATABASE=RT2501/RT2573 Wireless Adapter usb:v148Fp2671* ID_MODEL_FROM_DATABASE=RT2601/RT2671 Wireless Adapter usb:v148Fp2770* ID_MODEL_FROM_DATABASE=RT2770 Wireless Adapter usb:v148Fp2870* ID_MODEL_FROM_DATABASE=RT2870 Wireless Adapter usb:v148Fp3070* ID_MODEL_FROM_DATABASE=RT2870/RT3070 Wireless Adapter usb:v148Fp3071* ID_MODEL_FROM_DATABASE=RT3071 Wireless Adapter usb:v148Fp3072* ID_MODEL_FROM_DATABASE=RT3072 Wireless Adapter usb:v148Fp3370* ID_MODEL_FROM_DATABASE=RT3370 Wireless Adapter usb:v148Fp3572* ID_MODEL_FROM_DATABASE=RT3572 Wireless Adapter usb:v148Fp3573* ID_MODEL_FROM_DATABASE=RT3573 Wireless Adapter usb:v148Fp5370* ID_MODEL_FROM_DATABASE=RT5370 Wireless Adapter usb:v148Fp5372* ID_MODEL_FROM_DATABASE=RT5372 Wireless Adapter usb:v148Fp5572* ID_MODEL_FROM_DATABASE=RT5572 Wireless Adapter usb:v148Fp7601* ID_MODEL_FROM_DATABASE=MT7601U Wireless Adapter usb:v148Fp760B* ID_MODEL_FROM_DATABASE=MT7601U Wireless Adapter usb:v148Fp9020* ID_MODEL_FROM_DATABASE=RT2500USB Wireless Adapter usb:v148Fp9021* ID_MODEL_FROM_DATABASE=RT2501USB Wireless Adapter usb:v1491* ID_VENDOR_FROM_DATABASE=Futronic Technology Co. Ltd. usb:v1491p0020* ID_MODEL_FROM_DATABASE=FS81 Fingerprint Scanner Module usb:v1493* ID_VENDOR_FROM_DATABASE=Suunto usb:v1493p0010* ID_MODEL_FROM_DATABASE=Bluebird [Ambit] usb:v1493p0019* ID_MODEL_FROM_DATABASE=Duck [Ambit2] usb:v1493p001A* ID_MODEL_FROM_DATABASE=Colibri [Ambit2 S] usb:v1493p001B* ID_MODEL_FROM_DATABASE=Emu [Ambit3 Peak] usb:v1493p001C* ID_MODEL_FROM_DATABASE=Finch [Ambit3 Sport] usb:v1493p001D* ID_MODEL_FROM_DATABASE=Greentit [Ambit2 R] usb:v1497* ID_VENDOR_FROM_DATABASE=Panstrong Company Ltd. usb:v1498* ID_VENDOR_FROM_DATABASE=Microtek International Inc. usb:v1498pA090* ID_MODEL_FROM_DATABASE=DVB-T Tuner usb:v149A* ID_VENDOR_FROM_DATABASE=Imagination Technologies usb:v149Ap2107* ID_MODEL_FROM_DATABASE=DBX1 DSP core usb:v14AA* ID_VENDOR_FROM_DATABASE=WideView Technology Inc. usb:v14AAp0001* ID_MODEL_FROM_DATABASE=Avermedia AverTV DVBT USB1.1 (cold) usb:v14AAp0002* ID_MODEL_FROM_DATABASE=Avermedia AverTV DVBT USB1.1 (warm) usb:v14AAp0201* ID_MODEL_FROM_DATABASE=AVermedia/Yakumo/Hama/Typhoon DVB-T USB2.0 (cold) usb:v14AAp0221* ID_MODEL_FROM_DATABASE=WT-220U DVB-T dongle usb:v14AAp022B* ID_MODEL_FROM_DATABASE=WT-220U DVB-T dongle usb:v14AAp0301* ID_MODEL_FROM_DATABASE=AVermedia/Yakumo/Hama/Typhoon DVB-T USB2.0 (warm) usb:v14AD* ID_VENDOR_FROM_DATABASE=CTK Corporation usb:v14AE* ID_VENDOR_FROM_DATABASE=Printronix Inc. usb:v14AF* ID_VENDOR_FROM_DATABASE=ATP Electronics Inc. usb:v14B0* ID_VENDOR_FROM_DATABASE=StarTech.com Ltd. usb:v14B2* ID_VENDOR_FROM_DATABASE=Ralink Technology, Corp. usb:v14B2p3A93* ID_MODEL_FROM_DATABASE=Topcom 802.11bg Wireless Adapter [Atheros AR5523] usb:v14B2p3A95* ID_MODEL_FROM_DATABASE=Toshiba WUS-G06G-JT 802.11bg Wireless Adapter [Atheros AR5523] usb:v14B2p3A98* ID_MODEL_FROM_DATABASE=Airlink101 AWLL4130 802.11bg Wireless Adapter [Atheros AR5523] usb:v14B2p3C02* ID_MODEL_FROM_DATABASE=Conceptronic C54RU v2 802.11bg Wireless Adapter [Ralink RT2571] usb:v14B2p3C05* ID_MODEL_FROM_DATABASE=rt2570 802.11g WLAN usb:v14B2p3C06* ID_MODEL_FROM_DATABASE=Conceptronic C300RU v1 802.11bgn Wireless Adapter [Ralink RT2870] usb:v14B2p3C07* ID_MODEL_FROM_DATABASE=802.11n adapter usb:v14B2p3C09* ID_MODEL_FROM_DATABASE=802.11n adapter usb:v14B2p3C22* ID_MODEL_FROM_DATABASE=Conceptronic C54RU v3 802.11bg Wireless Adapter [Ralink RT2571W] usb:v14B2p3C23* ID_MODEL_FROM_DATABASE=Airlink101 AWLL6080 802.11bgn Wireless Adapter [Ralink RT2870] usb:v14B2p3C24* ID_MODEL_FROM_DATABASE=NEC NP01LM 802.11abg Wireless Adapter [Ralink RT2571W] usb:v14B2p3C25* ID_MODEL_FROM_DATABASE=DrayTek Vigor N61 802.11bgn Wireless Adapter [Ralink RT2870] usb:v14B2p3C27* ID_MODEL_FROM_DATABASE=Airlink101 AWLL6070 802.11bgn Wireless Adapter [Ralink RT2770] usb:v14B2p3C28* ID_MODEL_FROM_DATABASE=Conceptronic C300RU v2 802.11bgn Wireless Adapter [Ralink RT2770] usb:v14B2p3C2B* ID_MODEL_FROM_DATABASE=NEC NP02LM 802.11bgn Wireless Adapter [Ralink RT3072] usb:v14B2p3C2C* ID_MODEL_FROM_DATABASE=Keebox W150NU 802.11bgn Wireless Adapter [Ralink RT3070] usb:v14C0* ID_VENDOR_FROM_DATABASE=Rockwell Automation, Inc. usb:v14C2* ID_VENDOR_FROM_DATABASE=Gemlight Computer, Ltd usb:v14C2p0250* ID_MODEL_FROM_DATABASE=Storage Adapter V2 usb:v14C2p0350* ID_MODEL_FROM_DATABASE=Storage Adapter V2 usb:v14C8* ID_VENDOR_FROM_DATABASE=Zytronic usb:v14CD* ID_VENDOR_FROM_DATABASE=Super Top usb:v14CDp1212* ID_MODEL_FROM_DATABASE=microSD card reader (SY-T18) usb:v14CDp121C* ID_MODEL_FROM_DATABASE=microSD card reader usb:v14CDp121F* ID_MODEL_FROM_DATABASE=microSD CardReader SY-T18 usb:v14CDp123A* ID_MODEL_FROM_DATABASE=SD/MMC/RS-MMC Card Reader usb:v14CDp125C* ID_MODEL_FROM_DATABASE=SD card reader usb:v14CDp127B* ID_MODEL_FROM_DATABASE=SDXC Reader usb:v14CDp6116* ID_MODEL_FROM_DATABASE=M6116 SATA Bridge usb:v14CDp6600* ID_MODEL_FROM_DATABASE=M110E PATA bridge usb:v14CDp6700* ID_MODEL_FROM_DATABASE=Card Reader usb:v14CDp6900* ID_MODEL_FROM_DATABASE=Card Reader usb:v14CDp8123* ID_MODEL_FROM_DATABASE=SD MMC Reader usb:v14CDp8125* ID_MODEL_FROM_DATABASE=SD MMC Reader usb:v14D8* ID_VENDOR_FROM_DATABASE=JAMER INDUSTRIES CO., LTD. usb:v14DD* ID_VENDOR_FROM_DATABASE=Raritan Computer, Inc. usb:v14DDp1007* ID_MODEL_FROM_DATABASE=D2CIM-VUSB KVM connector usb:v14E0* ID_VENDOR_FROM_DATABASE=WiNRADiO Communications usb:v14E0p0501* ID_MODEL_FROM_DATABASE=WR-G528e 'CHEETAH' usb:v14E1* ID_VENDOR_FROM_DATABASE=Dialogue Technology Corp. usb:v14E1p5000* ID_MODEL_FROM_DATABASE=PenMount 5000 Touch Controller usb:v14E5* ID_VENDOR_FROM_DATABASE=SAIN Information & Communications Co., Ltd. usb:v14EA* ID_VENDOR_FROM_DATABASE=Planex Communications usb:v14EApAB10* ID_MODEL_FROM_DATABASE=GW-US54GZ usb:v14EApAB11* ID_MODEL_FROM_DATABASE=GU-1000T usb:v14EApAB13* ID_MODEL_FROM_DATABASE=GW-US54Mini 802.11bg usb:v14ED* ID_VENDOR_FROM_DATABASE=Shure Inc. usb:v14EDp29B6* ID_MODEL_FROM_DATABASE=X2u Adapter usb:v14F7* ID_VENDOR_FROM_DATABASE=TechniSat Digital GmbH usb:v14F7p0001* ID_MODEL_FROM_DATABASE=SkyStar 2 HD CI usb:v14F7p0002* ID_MODEL_FROM_DATABASE=SkyStar 2 HD CI usb:v14F7p0003* ID_MODEL_FROM_DATABASE=CableStar Combo HD CI usb:v14F7p0004* ID_MODEL_FROM_DATABASE=AirStar TeleStick 2 usb:v14F7p0500* ID_MODEL_FROM_DATABASE=DVB-PC TV Star HD usb:v1500* ID_VENDOR_FROM_DATABASE=Ellisys usb:v1501* ID_VENDOR_FROM_DATABASE=Pine-Tum Enterprise Co., Ltd. usb:v1509* ID_VENDOR_FROM_DATABASE=First International Computer, Inc. usb:v1509p0A01* ID_MODEL_FROM_DATABASE=LI-3100 Area Meter usb:v1509p0A02* ID_MODEL_FROM_DATABASE=LI-7000 CO2/H2O Gas Analyzer usb:v1509p0A03* ID_MODEL_FROM_DATABASE=C-DiGit Blot Scanner usb:v1509p9242* ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver usb:v1513* ID_VENDOR_FROM_DATABASE=medMobile usb:v1513p0444* ID_MODEL_FROM_DATABASE=medMobile usb:v1514* ID_VENDOR_FROM_DATABASE=Actel usb:v1514p2003* ID_MODEL_FROM_DATABASE=FlashPro3 Programmer usb:v1514p2004* ID_MODEL_FROM_DATABASE=FlashPro3 Programmer usb:v1514p2005* ID_MODEL_FROM_DATABASE=FlashPro3 Programmer usb:v1516* ID_VENDOR_FROM_DATABASE=CompUSA usb:v1516p1603* ID_MODEL_FROM_DATABASE=Flash Drive usb:v1516p8628* ID_MODEL_FROM_DATABASE=Pen Drive usb:v1518* ID_VENDOR_FROM_DATABASE=Cheshire Engineering Corp. usb:v1518p0001* ID_MODEL_FROM_DATABASE=HDReye High Dynamic Range Camera usb:v1518p0002* ID_MODEL_FROM_DATABASE=HDReye (before firmware loads) usb:v1519* ID_VENDOR_FROM_DATABASE=Comneon usb:v1519p0020* ID_MODEL_FROM_DATABASE=HSIC Device usb:v1519p0443* ID_MODEL_FROM_DATABASE=Telit LN930 usb:v1520* ID_VENDOR_FROM_DATABASE=Bitwire Corp. usb:v1524* ID_VENDOR_FROM_DATABASE=ENE Technology Inc usb:v1524p6680* ID_MODEL_FROM_DATABASE=UTS 6680 usb:v1527* ID_VENDOR_FROM_DATABASE=Silicon Portals usb:v1527p0200* ID_MODEL_FROM_DATABASE=YAP Phone (no firmware) usb:v1527p0201* ID_MODEL_FROM_DATABASE=YAP Phone usb:v1529* ID_VENDOR_FROM_DATABASE=UBIQUAM Co., Ltd. usb:v1529p3100* ID_MODEL_FROM_DATABASE=CDMA 1xRTT USB Modem (U-100/105/200/300/520) usb:v152A* ID_VENDOR_FROM_DATABASE=Thesycon Systemsoftware & Consulting GmbH usb:v152Ap8350* ID_MODEL_FROM_DATABASE=NET Gmbh iCube Camera usb:v152Ap8400* ID_MODEL_FROM_DATABASE=INI DVS128 usb:v152Ap840D* ID_MODEL_FROM_DATABASE=INI DAViS usb:v152Ap841A* ID_MODEL_FROM_DATABASE=INI DAViS FX3 usb:v152B* ID_VENDOR_FROM_DATABASE=MIR Srl usb:v152Bp0001* ID_MODEL_FROM_DATABASE=spirobank II usb:v152Bp0002* ID_MODEL_FROM_DATABASE=spirolab III usb:v152Bp0003* ID_MODEL_FROM_DATABASE=MiniSpir usb:v152Bp0004* ID_MODEL_FROM_DATABASE=Oxi usb:v152Bp0005* ID_MODEL_FROM_DATABASE=spiros II usb:v152Bp0006* ID_MODEL_FROM_DATABASE=smiths spirobank II usb:v152Bp0007* ID_MODEL_FROM_DATABASE=smiths spirobank G-USB usb:v152Bp0008* ID_MODEL_FROM_DATABASE=smiths MiniSpir usb:v152Bp0009* ID_MODEL_FROM_DATABASE=spirobank G-USB usb:v152Bp000A* ID_MODEL_FROM_DATABASE=smiths Oxi usb:v152Bp000B* ID_MODEL_FROM_DATABASE=smiths spirolab III usb:v152Bp000C* ID_MODEL_FROM_DATABASE=chorus III usb:v152Bp000D* ID_MODEL_FROM_DATABASE=spirolab III Bw usb:v152Bp000E* ID_MODEL_FROM_DATABASE=spirolab III usb:v152Bp000F* ID_MODEL_FROM_DATABASE=easySpiro usb:v152Bp0010* ID_MODEL_FROM_DATABASE=Spirotel converter usb:v152Bp0011* ID_MODEL_FROM_DATABASE=spirobank usb:v152Bp0012* ID_MODEL_FROM_DATABASE=spiro3 Zimmer usb:v152Bp0013* ID_MODEL_FROM_DATABASE=spirotel serial usb:v152Bp0014* ID_MODEL_FROM_DATABASE=spirotel II usb:v152Bp0015* ID_MODEL_FROM_DATABASE=spirodoc usb:v152D* ID_VENDOR_FROM_DATABASE=JMicron Technology Corp. / JMicron USA Technology Corp. usb:v152Dp0539* ID_MODEL_FROM_DATABASE=JMS539/567 SuperSpeed SATA II/III 3.0G/6.0G Bridge usb:v152Dp0567* ID_MODEL_FROM_DATABASE=JMS567 SATA 6Gb/s bridge usb:v152Dp0770* ID_MODEL_FROM_DATABASE=Alienware Integrated Webcam usb:v152Dp2329* ID_MODEL_FROM_DATABASE=JM20329 SATA Bridge usb:v152Dp2335* ID_MODEL_FROM_DATABASE=ATA/ATAPI Bridge usb:v152Dp2336* ID_MODEL_FROM_DATABASE=Hard Disk Drive usb:v152Dp2337* ID_MODEL_FROM_DATABASE=ATA/ATAPI Bridge usb:v152Dp2338* ID_MODEL_FROM_DATABASE=JM20337 Hi-Speed USB to SATA & PATA Combo Bridge usb:v152Dp2339* ID_MODEL_FROM_DATABASE=JM20339 SATA Bridge usb:v152Dp2352* ID_MODEL_FROM_DATABASE=ATA/ATAPI Bridge usb:v152Dp2509* ID_MODEL_FROM_DATABASE=JMS539 SuperSpeed SATA II 3.0G Bridge usb:v152Dp2551* ID_MODEL_FROM_DATABASE=JMS551 SATA 3Gb/s bridge usb:v152Dp2566* ID_MODEL_FROM_DATABASE=JMS566 SATA 3Gb/s bridge usb:v152Dp2590* ID_MODEL_FROM_DATABASE=Seatay ATA/ATAPI Bridge usb:v152Dp3562* ID_MODEL_FROM_DATABASE=JMS567 SATA 6Gb/s bridge usb:v152Dp3569* ID_MODEL_FROM_DATABASE=JMS566 SATA 3Gb/s bridge usb:v152E* ID_VENDOR_FROM_DATABASE=LG (HLDS) usb:v152Ep2507* ID_MODEL_FROM_DATABASE=PL-2507 IDE Controller usb:v152EpE001* ID_MODEL_FROM_DATABASE=GSA-5120D DVD-RW usb:v1532* ID_VENDOR_FROM_DATABASE=Razer USA, Ltd usb:v1532p0001* ID_MODEL_FROM_DATABASE=RZ01-020300 Optical Mouse [Diamondback] usb:v1532p0003* ID_MODEL_FROM_DATABASE=Krait Mouse usb:v1532p0007* ID_MODEL_FROM_DATABASE=DeathAdder Mouse usb:v1532p0013* ID_MODEL_FROM_DATABASE=Orochi mouse usb:v1532p0015* ID_MODEL_FROM_DATABASE=Naga Mouse usb:v1532p0016* ID_MODEL_FROM_DATABASE=DeathAdder Mouse usb:v1532p0017* ID_MODEL_FROM_DATABASE=RZ01-0035 Laser Gaming Mouse [Imperator] usb:v1532p001C* ID_MODEL_FROM_DATABASE=RZ01-0036 Optical Gaming Mouse [Abyssus] usb:v1532p0024* ID_MODEL_FROM_DATABASE=Razer Mamba usb:v1532p002E* ID_MODEL_FROM_DATABASE=RZ01-0058 Gaming Mouse [Naga] usb:v1532p0036* ID_MODEL_FROM_DATABASE=RZ01-0075, Gaming Mouse [Naga Hex] usb:v1532p0101* ID_MODEL_FROM_DATABASE=Copperhead Mouse usb:v1532p0102* ID_MODEL_FROM_DATABASE=Tarantula Keyboard usb:v1532p0109* ID_MODEL_FROM_DATABASE=Lycosa Keyboard usb:v1532p0113* ID_MODEL_FROM_DATABASE=RZ07-0074 Gaming Keypad [Orbweaver] usb:v1532p0300* ID_MODEL_FROM_DATABASE=RZ06-0063 Motion Sensing Controllers [Hydra] usb:v153B* ID_VENDOR_FROM_DATABASE=TerraTec Electronic GmbH usb:v153Bp1181* ID_MODEL_FROM_DATABASE=Cinergy S2 PCIe Dual Port 1 usb:v153Bp1182* ID_MODEL_FROM_DATABASE=Cinergy S2 PCIe Dual Port 2 usb:v1546* ID_VENDOR_FROM_DATABASE=U-Blox AG usb:v1546p01A5* ID_MODEL_FROM_DATABASE=NL-402U usb:v1547* ID_VENDOR_FROM_DATABASE=SG Intec Ltd & Co KG usb:v1547p1000* ID_MODEL_FROM_DATABASE=SG-Lock[U2] usb:v154A* ID_VENDOR_FROM_DATABASE=Celectronic GmbH usb:v154Ap8180* ID_MODEL_FROM_DATABASE=CARD STAR/medic2 usb:v154B* ID_VENDOR_FROM_DATABASE=PNY usb:v154Bp0010* ID_MODEL_FROM_DATABASE=USB 2.0 Flash Drive usb:v154Bp0048* ID_MODEL_FROM_DATABASE=Flash Drive usb:v154Bp004D* ID_MODEL_FROM_DATABASE=8 GB Flash Drive usb:v154Bp0053* ID_MODEL_FROM_DATABASE=Flash Drive usb:v154Bp0057* ID_MODEL_FROM_DATABASE=32GB Micro Slide Attache Flash Drive usb:v154Bp005B* ID_MODEL_FROM_DATABASE=Flash Drive usb:v154Bp0062* ID_MODEL_FROM_DATABASE=Flash Drive usb:v154Bp007A* ID_MODEL_FROM_DATABASE=Classic Attache Flash Drive usb:v154Bp6545* ID_MODEL_FROM_DATABASE=FD Device usb:v154BpFA05* ID_MODEL_FROM_DATABASE=Flash Drive usb:v154D* ID_VENDOR_FROM_DATABASE=ConnectCounty Holdings Berhad usb:v154E* ID_VENDOR_FROM_DATABASE=D&M Holdings, Inc. (Denon/Marantz) usb:v154Ep3000* ID_MODEL_FROM_DATABASE=Marantz RC9001 Remote Control usb:v154F* ID_VENDOR_FROM_DATABASE=SNBC CO., Ltd usb:v1554* ID_VENDOR_FROM_DATABASE=Prolink Microsystems Corp. usb:v1554p5010* ID_MODEL_FROM_DATABASE=PV-D231U(RN)-F [PixelView PlayTV SBTVD Full-Seg] usb:v1557* ID_VENDOR_FROM_DATABASE=OQO usb:v1557p0002* ID_MODEL_FROM_DATABASE=model 01 WiFi interface usb:v1557p0003* ID_MODEL_FROM_DATABASE=model 01 Bluetooth interface usb:v1557p0A80* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) usb:v1557p7720* ID_MODEL_FROM_DATABASE=model 01+ Ethernet usb:v1557p8150* ID_MODEL_FROM_DATABASE=model 01 Ethernet interface usb:v1568* ID_VENDOR_FROM_DATABASE=Sunf Pu Technology Co., Ltd usb:v156F* ID_VENDOR_FROM_DATABASE=Quantum Corporation usb:v1570* ID_VENDOR_FROM_DATABASE=ALLTOP TECHNOLOGY CO., LTD. usb:v157B* ID_VENDOR_FROM_DATABASE=Ketron SRL usb:v157E* ID_VENDOR_FROM_DATABASE=TRENDnet usb:v157Ep3006* ID_MODEL_FROM_DATABASE=TEW-444UB EU [TRENDnet] usb:v157Ep3007* ID_MODEL_FROM_DATABASE=TEW-444UB EU (no firmware) usb:v157Ep300A* ID_MODEL_FROM_DATABASE=TEW-429UB 802.11bg usb:v157Ep300B* ID_MODEL_FROM_DATABASE=TEW-429UB 802.11bg usb:v157Ep300C* ID_MODEL_FROM_DATABASE=TEW-429UF A1 802.11bg Wireless Adapter [ZyDAS ZD1211B] usb:v157Ep300D* ID_MODEL_FROM_DATABASE=TEW-429UB C1 802.11bg usb:v157Ep300E* ID_MODEL_FROM_DATABASE=SMC SMCWUSB-N 802.11bgn 2x2:2 Wireless Adapter [Ralink RT2870] usb:v157Ep3012* ID_MODEL_FROM_DATABASE=TEW-604UB 802.11bg Wireless Adapter [Atheros AR5523] usb:v157Ep3013* ID_MODEL_FROM_DATABASE=TEW-645UB 802.11bgn 1x2:2 Wireless Adapter [Ralink RT2770] usb:v157Ep3204* ID_MODEL_FROM_DATABASE=Allnet ALL0298 v2 802.11bg usb:v157Ep3205* ID_MODEL_FROM_DATABASE=Allnet ALL0283 [AR5523] usb:v157Ep3206* ID_MODEL_FROM_DATABASE=Allnet ALL0283 [AR5523](no firmware) usb:v157Ep3207* ID_MODEL_FROM_DATABASE=TEW-509UB A1 802.11abg Wireless Adapter [ZyDAS ZD1211] usb:v157Ep3208* ID_MODEL_FROM_DATABASE=TEW-509UB 1.1R 802.11abg Wireless Adapter usb:v1582* ID_VENDOR_FROM_DATABASE=Fiberline usb:v1582p6003* ID_MODEL_FROM_DATABASE=WL-430U 802.11bg usb:v1587* ID_VENDOR_FROM_DATABASE=SMA Technologie AG usb:v158D* ID_VENDOR_FROM_DATABASE=Oakley Inc. usb:v158E* ID_VENDOR_FROM_DATABASE=JDS Uniphase Corporation (JDSU) usb:v158Ep0820* ID_MODEL_FROM_DATABASE=SmartPocket Class Device usb:v1598* ID_VENDOR_FROM_DATABASE=Kunshan Guoji Electronics Co., Ltd. usb:v15A2* ID_VENDOR_FROM_DATABASE=Freescale Semiconductor, Inc. usb:v15A2p0038* ID_MODEL_FROM_DATABASE=9S08JS Bootloader usb:v15A2p003B* ID_MODEL_FROM_DATABASE=USB2CAN Application for ColdFire DEMOJM board usb:v15A2p0042* ID_MODEL_FROM_DATABASE=OSBDM - Debug Port usb:v15A2p004F* ID_MODEL_FROM_DATABASE=i.MX28 SystemOnChip in RecoveryMode usb:v15A2p0052* ID_MODEL_FROM_DATABASE=i.MX50 SystemOnChip in RecoveryMode usb:v15A2p0054* ID_MODEL_FROM_DATABASE=i.MX 6Dual/6Quad SystemOnChip in RecoveryMode usb:v15A2p0061* ID_MODEL_FROM_DATABASE=i.MX 6Solo/6DualLite SystemOnChip in RecoveryMode usb:v15A4* ID_VENDOR_FROM_DATABASE=Afatech Technologies, Inc. usb:v15A4p1000* ID_MODEL_FROM_DATABASE=AF9015/AF9035 DVB-T stick usb:v15A4p1001* ID_MODEL_FROM_DATABASE=AF9015/AF9035 DVB-T stick usb:v15A4p1336* ID_MODEL_FROM_DATABASE=SDHC/MicroSD/MMC/MS/M2/CF/XD Flash Card Reader usb:v15A4p9015* ID_MODEL_FROM_DATABASE=AF9015 DVB-T USB2.0 stick usb:v15A4p9016* ID_MODEL_FROM_DATABASE=AF9015 DVB-T USB2.0 stick usb:v15A8* ID_VENDOR_FROM_DATABASE=Teams Power Limited usb:v15A9* ID_VENDOR_FROM_DATABASE=Gemtek usb:v15A9p0002* ID_MODEL_FROM_DATABASE=SparkLAN WL-682 802.11bg Wireless Adapter [Intersil ISL3887] usb:v15A9p0004* ID_MODEL_FROM_DATABASE=WUBR-177G [Ralink RT2571W] usb:v15A9p0006* ID_MODEL_FROM_DATABASE=Wireless 11n USB Adapter usb:v15A9p0010* ID_MODEL_FROM_DATABASE=802.11n USB Wireless Card usb:v15A9p0012* ID_MODEL_FROM_DATABASE=WUBR-208N 802.11abgn Wireless Adapter [Ralink RT2870] usb:v15A9p002D* ID_MODEL_FROM_DATABASE=WLTUBA-107 [Yota 4G LTE] usb:v15AA* ID_VENDOR_FROM_DATABASE=Gearway Electronics (Dong Guan) Co., Ltd. usb:v15AD* ID_VENDOR_FROM_DATABASE=VMware Inc. usb:v15BA* ID_VENDOR_FROM_DATABASE=Olimex Ltd. usb:v15BAp0003* ID_MODEL_FROM_DATABASE=OpenOCD JTAG usb:v15BAp0004* ID_MODEL_FROM_DATABASE=OpenOCD JTAG TINY usb:v15BAp002A* ID_MODEL_FROM_DATABASE=ARM-USB-TINY-H JTAG interface usb:v15BAp002B* ID_MODEL_FROM_DATABASE=ARM-USB-OCD-H JTAG+RS232 usb:v15C0* ID_VENDOR_FROM_DATABASE=XL Imaging usb:v15C0p0001* ID_MODEL_FROM_DATABASE=2M pixel Microscope Camera usb:v15C0p0002* ID_MODEL_FROM_DATABASE=3M pixel Microscope Camera usb:v15C0p0003* ID_MODEL_FROM_DATABASE=1.3M pixel Microscope Camera (mono) usb:v15C0p0004* ID_MODEL_FROM_DATABASE=1.3M pixel Microscope Camera (colour) usb:v15C0p0005* ID_MODEL_FROM_DATABASE=3M pixel Microscope Camera (Mk 2) usb:v15C0p0006* ID_MODEL_FROM_DATABASE=2M pixel Microscope Camera (with capture button) usb:v15C0p0007* ID_MODEL_FROM_DATABASE=3M pixel Microscope Camera (with capture button) usb:v15C0p0008* ID_MODEL_FROM_DATABASE=1.3M pixel Microscope Camera (colour, with capture button) usb:v15C0p0009* ID_MODEL_FROM_DATABASE=1.3M pixel Microscope Camera (colour, with capture button) usb:v15C0p000A* ID_MODEL_FROM_DATABASE=2M pixel Microscope Camera (Mk 2) usb:v15C0p0010* ID_MODEL_FROM_DATABASE=1.3M pixel "Tinycam" usb:v15C0p0101* ID_MODEL_FROM_DATABASE=3M pixel Microscope Camera usb:v15C2* ID_VENDOR_FROM_DATABASE=SoundGraph Inc. usb:v15C2p0036* ID_MODEL_FROM_DATABASE=LC16M VFD Display/IR Receiver usb:v15C2p0038* ID_MODEL_FROM_DATABASE=GD01 MX LCD Display/IR Receiver usb:v15C2p0042* ID_MODEL_FROM_DATABASE=Antec Veris Multimedia Station E-Z IR Receiver usb:v15C2pFFDA* ID_MODEL_FROM_DATABASE=iMON PAD Remote Controller usb:v15C2pFFDC* ID_MODEL_FROM_DATABASE=iMON PAD Remote Controller usb:v15C5* ID_VENDOR_FROM_DATABASE=Advance Multimedia Internet Technology Inc. (AMIT) usb:v15C5p0008* ID_MODEL_FROM_DATABASE=WL532U 802.11g Adapter usb:v15C6* ID_VENDOR_FROM_DATABASE=Laboratoires MXM usb:v15C6p1000* ID_MODEL_FROM_DATABASE=DigistimSP (cold) usb:v15C6p1001* ID_MODEL_FROM_DATABASE=DigistimSP (warm) usb:v15C6p1002* ID_MODEL_FROM_DATABASE=DigimapSP USB (cold) usb:v15C6p1003* ID_MODEL_FROM_DATABASE=DigimapSP USB (warm) usb:v15C6p1004* ID_MODEL_FROM_DATABASE=DigistimSP (cold) usb:v15C6p1005* ID_MODEL_FROM_DATABASE=DigistimSP (warm) usb:v15C6p1100* ID_MODEL_FROM_DATABASE=Odyssee (cold) usb:v15C6p1101* ID_MODEL_FROM_DATABASE=Odyssee (warm) usb:v15C6p1200* ID_MODEL_FROM_DATABASE=Digispy usb:v15C8* ID_VENDOR_FROM_DATABASE=KTF Technologies usb:v15C8p3201* ID_MODEL_FROM_DATABASE=EVER EV-W100/EV-W250 usb:v15C9* ID_VENDOR_FROM_DATABASE=D-Box Technologies usb:v15CA* ID_VENDOR_FROM_DATABASE=Textech International Ltd. usb:v15CAp00C3* ID_MODEL_FROM_DATABASE=Mini Optical Mouse usb:v15CAp0101* ID_MODEL_FROM_DATABASE=MIDI Interface cable usb:v15CAp1806* ID_MODEL_FROM_DATABASE=MIDI Interface cable usb:v15D5* ID_VENDOR_FROM_DATABASE=Coulomb Electronics Ltd. usb:v15D9* ID_VENDOR_FROM_DATABASE=Trust International B.V. usb:v15D9p0A33* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v15D9p0A37* ID_MODEL_FROM_DATABASE=Mouse usb:v15D9p0A41* ID_MODEL_FROM_DATABASE=MI-2540D [Optical mouse] usb:v15D9p0A4C* ID_MODEL_FROM_DATABASE=USB+PS/2 Optical Mouse usb:v15D9p0A4D* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v15D9p0A4F* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v15DC* ID_VENDOR_FROM_DATABASE=Hynix Semiconductor Inc. usb:v15E0* ID_VENDOR_FROM_DATABASE=Seong Ji Industrial Co., Ltd. usb:v15E1* ID_VENDOR_FROM_DATABASE=RSA usb:v15E1p2007* ID_MODEL_FROM_DATABASE=RSA SecurID (R) Authenticator usb:v15E4* ID_VENDOR_FROM_DATABASE=Numark usb:v15E4p0024* ID_MODEL_FROM_DATABASE=Mixtrack usb:v15E4p0140* ID_MODEL_FROM_DATABASE=ION VCR 2 PC / Video 2 PC usb:v15E8* ID_VENDOR_FROM_DATABASE=SohoWare usb:v15E8p9100* ID_MODEL_FROM_DATABASE=NUB100 Ethernet [pegasus] usb:v15E8p9110* ID_MODEL_FROM_DATABASE=10/100 USB Ethernet usb:v15E9* ID_VENDOR_FROM_DATABASE=Pacific Digital Corp. usb:v15E9p04CE* ID_MODEL_FROM_DATABASE=MemoryFrame MF-570 usb:v15E9p1968* ID_MODEL_FROM_DATABASE=MemoryFrame MF-570 usb:v15E9p1969* ID_MODEL_FROM_DATABASE=Digital Frame usb:v15EC* ID_VENDOR_FROM_DATABASE=Belcarra Technologies Corp. usb:v15F4* ID_VENDOR_FROM_DATABASE=HanfTek usb:v15F4p0001* ID_MODEL_FROM_DATABASE=HanfTek UMT-010 USB2.0 DVB-T (cold) usb:v15F4p0025* ID_MODEL_FROM_DATABASE=HanfTek UMT-010 USB2.0 DVB-T (warm) usb:v1604* ID_VENDOR_FROM_DATABASE=Tascam usb:v1604p8000* ID_MODEL_FROM_DATABASE=US-428 Audio/Midi Controller (without fw) usb:v1604p8001* ID_MODEL_FROM_DATABASE=US-428 Audio/Midi Controller usb:v1604p8004* ID_MODEL_FROM_DATABASE=US-224 Audio/Midi Controller (without fw) usb:v1604p8005* ID_MODEL_FROM_DATABASE=US-224 Audio/Midi Controller usb:v1604p8006* ID_MODEL_FROM_DATABASE=US-122 Audio/Midi Interface (without fw) usb:v1604p8007* ID_MODEL_FROM_DATABASE=US-122 Audio/Midi Interface usb:v1606* ID_VENDOR_FROM_DATABASE=Umax usb:v1606p0002* ID_MODEL_FROM_DATABASE=Astra 1236U Scanner usb:v1606p0010* ID_MODEL_FROM_DATABASE=Astra 1220U usb:v1606p0030* ID_MODEL_FROM_DATABASE=Astra 1600U/2000U usb:v1606p0050* ID_MODEL_FROM_DATABASE=Scanner usb:v1606p0060* ID_MODEL_FROM_DATABASE=Astra 3400/3450 usb:v1606p0070* ID_MODEL_FROM_DATABASE=Astra 4400/4450 usb:v1606p0130* ID_MODEL_FROM_DATABASE=Astra 2100U usb:v1606p0160* ID_MODEL_FROM_DATABASE=Astra 5400U usb:v1606p0170* ID_MODEL_FROM_DATABASE=Uniscan D50 usb:v1606p0230* ID_MODEL_FROM_DATABASE=Astra 2200/2200SU usb:v1606p0350* ID_MODEL_FROM_DATABASE=Astra 4800/4850 Scanner usb:v1606p1030* ID_MODEL_FROM_DATABASE=Astra 4000U usb:v1606p1220* ID_MODEL_FROM_DATABASE=Genesys Logic Scanner Controller NT5.0 usb:v1606p2010* ID_MODEL_FROM_DATABASE=AstraCam Digital Camera usb:v1606p2020* ID_MODEL_FROM_DATABASE=AstraCam 1000 usb:v1606p2030* ID_MODEL_FROM_DATABASE=AstraCam 1800 Digital Camera usb:v1608* ID_VENDOR_FROM_DATABASE=Inside Out Networks [hex] usb:v1608p0001* ID_MODEL_FROM_DATABASE=EdgePort/4 Serial Port usb:v1608p0002* ID_MODEL_FROM_DATABASE=Edgeport/8 usb:v1608p0003* ID_MODEL_FROM_DATABASE=Rapidport/4 usb:v1608p0004* ID_MODEL_FROM_DATABASE=Edgeport/4 usb:v1608p0005* ID_MODEL_FROM_DATABASE=Edgeport/2 usb:v1608p0006* ID_MODEL_FROM_DATABASE=Edgeport/4i usb:v1608p0007* ID_MODEL_FROM_DATABASE=Edgeport/2i usb:v1608p0008* ID_MODEL_FROM_DATABASE=Edgeport/8 usb:v1608p000C* ID_MODEL_FROM_DATABASE=Edgeport/421 usb:v1608p000D* ID_MODEL_FROM_DATABASE=Edgeport/21 usb:v1608p000E* ID_MODEL_FROM_DATABASE=Edgeport/4 usb:v1608p000F* ID_MODEL_FROM_DATABASE=Edgeport/8 usb:v1608p0010* ID_MODEL_FROM_DATABASE=Edgeport/2 usb:v1608p0011* ID_MODEL_FROM_DATABASE=Edgeport/4 usb:v1608p0012* ID_MODEL_FROM_DATABASE=Edgeport/416 usb:v1608p0014* ID_MODEL_FROM_DATABASE=Edgeport/8i usb:v1608p0018* ID_MODEL_FROM_DATABASE=Edgeport/412 usb:v1608p0019* ID_MODEL_FROM_DATABASE=Edgeport/412 usb:v1608p001A* ID_MODEL_FROM_DATABASE=Edgeport/2+2i usb:v1608p0101* ID_MODEL_FROM_DATABASE=Edgeport/4 usb:v1608p0105* ID_MODEL_FROM_DATABASE=Edgeport/2 usb:v1608p0106* ID_MODEL_FROM_DATABASE=Edgeport/4i usb:v1608p0107* ID_MODEL_FROM_DATABASE=Edgeport/2i usb:v1608p010C* ID_MODEL_FROM_DATABASE=Edgeport/421 usb:v1608p010D* ID_MODEL_FROM_DATABASE=Edgeport/21 usb:v1608p0110* ID_MODEL_FROM_DATABASE=Edgeport/2 usb:v1608p0111* ID_MODEL_FROM_DATABASE=Edgeport/4 usb:v1608p0112* ID_MODEL_FROM_DATABASE=Edgeport/416 usb:v1608p0114* ID_MODEL_FROM_DATABASE=Edgeport/8i usb:v1608p0201* ID_MODEL_FROM_DATABASE=Edgeport/4 usb:v1608p0203* ID_MODEL_FROM_DATABASE=Rapidport/4 usb:v1608p0204* ID_MODEL_FROM_DATABASE=Edgeport/4 usb:v1608p0205* ID_MODEL_FROM_DATABASE=Edgeport/2 usb:v1608p0206* ID_MODEL_FROM_DATABASE=Edgeport/4i usb:v1608p0207* ID_MODEL_FROM_DATABASE=Edgeport/2i usb:v1608p020C* ID_MODEL_FROM_DATABASE=Edgeport/421 usb:v1608p020D* ID_MODEL_FROM_DATABASE=Edgeport/21 usb:v1608p020E* ID_MODEL_FROM_DATABASE=Edgeport/4 usb:v1608p020F* ID_MODEL_FROM_DATABASE=Edgeport/8 usb:v1608p0210* ID_MODEL_FROM_DATABASE=Edgeport/2 usb:v1608p0211* ID_MODEL_FROM_DATABASE=Edgeport/4 usb:v1608p0212* ID_MODEL_FROM_DATABASE=Edgeport/416 usb:v1608p0214* ID_MODEL_FROM_DATABASE=Edgeport/8i usb:v1608p0215* ID_MODEL_FROM_DATABASE=Edgeport/1 usb:v1608p0216* ID_MODEL_FROM_DATABASE=EPOS/44 usb:v1608p0217* ID_MODEL_FROM_DATABASE=Edgeport/42 usb:v1608p021A* ID_MODEL_FROM_DATABASE=Edgeport/2+2i usb:v1608p021B* ID_MODEL_FROM_DATABASE=Edgeport/2c usb:v1608p021C* ID_MODEL_FROM_DATABASE=Edgeport/221c usb:v1608p021D* ID_MODEL_FROM_DATABASE=Edgeport/22c usb:v1608p021E* ID_MODEL_FROM_DATABASE=Edgeport/21c usb:v1608p021F* ID_MODEL_FROM_DATABASE=Edgeport/62 usb:v1608p0240* ID_MODEL_FROM_DATABASE=Edgeport/1 usb:v1608p0241* ID_MODEL_FROM_DATABASE=Edgeport/1i usb:v1608p0242* ID_MODEL_FROM_DATABASE=Edgeport/4s usb:v1608p0243* ID_MODEL_FROM_DATABASE=Edgeport/8s usb:v1608p0244* ID_MODEL_FROM_DATABASE=Edgeport/8 usb:v1608p0245* ID_MODEL_FROM_DATABASE=Edgeport/22c usb:v1608p0301* ID_MODEL_FROM_DATABASE=Watchport/P usb:v1608p0302* ID_MODEL_FROM_DATABASE=Watchport/M usb:v1608p0303* ID_MODEL_FROM_DATABASE=Watchport/W usb:v1608p0304* ID_MODEL_FROM_DATABASE=Watchport/T usb:v1608p0305* ID_MODEL_FROM_DATABASE=Watchport/H usb:v1608p0306* ID_MODEL_FROM_DATABASE=Watchport/E usb:v1608p0307* ID_MODEL_FROM_DATABASE=Watchport/L usb:v1608p0308* ID_MODEL_FROM_DATABASE=Watchport/R usb:v1608p0309* ID_MODEL_FROM_DATABASE=Watchport/A usb:v1608p030A* ID_MODEL_FROM_DATABASE=Watchport/D usb:v1608p030B* ID_MODEL_FROM_DATABASE=Watchport/D usb:v1608p030C* ID_MODEL_FROM_DATABASE=Power Management Port usb:v1608p030E* ID_MODEL_FROM_DATABASE=Power Management Port usb:v1608p030F* ID_MODEL_FROM_DATABASE=Watchport/G usb:v1608p0310* ID_MODEL_FROM_DATABASE=Watchport/Tc usb:v1608p0311* ID_MODEL_FROM_DATABASE=Watchport/Hc usb:v1608p1403* ID_MODEL_FROM_DATABASE=MultiTech Systems MT4X56 Modem usb:v1608p1A17* ID_MODEL_FROM_DATABASE=Agilent Technologies (E6473) usb:v160A* ID_VENDOR_FROM_DATABASE=VIA Technologies, Inc. usb:v160Ap3184* ID_MODEL_FROM_DATABASE=VIA VNT-6656 [WiFi 802.11b/g USB Dongle] usb:v160E* ID_VENDOR_FROM_DATABASE=INRO usb:v160Ep0001* ID_MODEL_FROM_DATABASE=E2USBKey usb:v1614* ID_VENDOR_FROM_DATABASE=Amoi Electronics usb:v1614p0404* ID_MODEL_FROM_DATABASE=WMA9109 UMTS Phone usb:v1614p0600* ID_MODEL_FROM_DATABASE=Vodafone VDA GPS / Toschiba Protege G710 usb:v1614p0804* ID_MODEL_FROM_DATABASE=WP-S1 Phone usb:v1617* ID_VENDOR_FROM_DATABASE=Sony Corp. usb:v1617p2002* ID_MODEL_FROM_DATABASE=NVX-P1 Personal Navigation System usb:v1619* ID_VENDOR_FROM_DATABASE=L & K Precision Technology Co., Ltd. usb:v1621* ID_VENDOR_FROM_DATABASE=Wionics Research usb:v1628* ID_VENDOR_FROM_DATABASE=Stonestreet One, Inc. usb:v162A* ID_VENDOR_FROM_DATABASE=Airgo Networks Inc. usb:v162F* ID_VENDOR_FROM_DATABASE=WiQuest Communications, Inc. usb:v1630* ID_VENDOR_FROM_DATABASE=2Wire, Inc. usb:v1630p0005* ID_MODEL_FROM_DATABASE=802.11g Wireless Adapter [Intersil ISL3886] usb:v1630p0011* ID_MODEL_FROM_DATABASE=PC Port 10 Mps Adapter usb:v1630pFF81* ID_MODEL_FROM_DATABASE=802.11b Wireless Adapter [Lucent/Agere Hermes I] usb:v1631* ID_VENDOR_FROM_DATABASE=Good Way Technology usb:v1631p6200* ID_MODEL_FROM_DATABASE=GWUSB2E usb:v1631pC019* ID_MODEL_FROM_DATABASE=RT2573 usb:v1645* ID_VENDOR_FROM_DATABASE=Entrega [hex] usb:v1645p0001* ID_MODEL_FROM_DATABASE=1S Serial Port usb:v1645p0002* ID_MODEL_FROM_DATABASE=2S Serial Port usb:v1645p0003* ID_MODEL_FROM_DATABASE=1S25 Serial Port usb:v1645p0004* ID_MODEL_FROM_DATABASE=4S Serial Port usb:v1645p0005* ID_MODEL_FROM_DATABASE=E45 Ethernet [klsi] usb:v1645p0006* ID_MODEL_FROM_DATABASE=Parallel Port usb:v1645p0007* ID_MODEL_FROM_DATABASE=U1-SC25 SCSI usb:v1645p0008* ID_MODEL_FROM_DATABASE=Ethernet usb:v1645p0016* ID_MODEL_FROM_DATABASE=Bi-directional to Parallel Printer Converter usb:v1645p0080* ID_MODEL_FROM_DATABASE=1 port to Serial Converter usb:v1645p0081* ID_MODEL_FROM_DATABASE=1 port to Serial Converter usb:v1645p0093* ID_MODEL_FROM_DATABASE=1S9 Serial Port usb:v1645p8000* ID_MODEL_FROM_DATABASE=EZ-USB usb:v1645p8001* ID_MODEL_FROM_DATABASE=1 port to Serial usb:v1645p8002* ID_MODEL_FROM_DATABASE=2x Serial Port usb:v1645p8003* ID_MODEL_FROM_DATABASE=1 port to Serial usb:v1645p8004* ID_MODEL_FROM_DATABASE=2U4S serial/usb hub usb:v1645p8005* ID_MODEL_FROM_DATABASE=Ethernet usb:v1645p8080* ID_MODEL_FROM_DATABASE=1 port to Serial usb:v1645p8081* ID_MODEL_FROM_DATABASE=1 port to Serial usb:v1645p8093* ID_MODEL_FROM_DATABASE=PortGear Serial Port usb:v1649* ID_VENDOR_FROM_DATABASE=SofTec Microsystems usb:v1649p0102* ID_MODEL_FROM_DATABASE=uDART In-Circuit Debugger usb:v1649p0200* ID_MODEL_FROM_DATABASE=SpYder USBSPYDER08 usb:v164A* ID_VENDOR_FROM_DATABASE=ChipX usb:v164C* ID_VENDOR_FROM_DATABASE=Matrix Vision GmbH usb:v164Cp0101* ID_MODEL_FROM_DATABASE=mvBlueFOX camera (no firmware) usb:v164Cp0103* ID_MODEL_FROM_DATABASE=mvBlueFOX camera usb:v164Cp0201* ID_MODEL_FROM_DATABASE=mvBlueLYNX-X intelligent camera (bootloader) usb:v164Cp0203* ID_MODEL_FROM_DATABASE=mvBlueLYNX-X intelligent camera usb:v1657* ID_VENDOR_FROM_DATABASE=Struck Innovative Systeme GmbH usb:v1657p3150* ID_MODEL_FROM_DATABASE=SIS3150 USB2.0 to VME interface usb:v165B* ID_VENDOR_FROM_DATABASE=Frontier Design Group usb:v165Bp8101* ID_MODEL_FROM_DATABASE=Tranzport Control Surface usb:v165BpFAD1* ID_MODEL_FROM_DATABASE=Alphatrack Control Surface usb:v165C* ID_VENDOR_FROM_DATABASE=Kondo Kagaku usb:v165Cp0002* ID_MODEL_FROM_DATABASE=Serial Adapter usb:v1660* ID_VENDOR_FROM_DATABASE=Creatix Polymedia GmbH usb:v1667* ID_VENDOR_FROM_DATABASE=GIGA-TMS INC. usb:v1667p0005* ID_MODEL_FROM_DATABASE=PCR330A RFID Reader (125 kHz, keyboard emulation) usb:v1668* ID_VENDOR_FROM_DATABASE=Actiontec Electronics, Inc. [hex] usb:v1668p0009* ID_MODEL_FROM_DATABASE=Gateway usb:v1668p0333* ID_MODEL_FROM_DATABASE=Modem usb:v1668p0358* ID_MODEL_FROM_DATABASE=InternetPhoneWizard usb:v1668p0405* ID_MODEL_FROM_DATABASE=Gateway usb:v1668p0408* ID_MODEL_FROM_DATABASE=Prism2.5 802.11b Adapter usb:v1668p0413* ID_MODEL_FROM_DATABASE=Gateway usb:v1668p0421* ID_MODEL_FROM_DATABASE=Prism2.5 802.11b Adapter usb:v1668p0441* ID_MODEL_FROM_DATABASE=IBM Integrated Bluetooth II usb:v1668p0500* ID_MODEL_FROM_DATABASE=BTM200B BlueTooth Adapter usb:v1668p1050* ID_MODEL_FROM_DATABASE=802UIG-1 802.11g Wireless Mini Adapter [Intersil ISL3887] usb:v1668p1200* ID_MODEL_FROM_DATABASE=802AIN Wireless N Network Adapter [Atheros AR9170+AR9101] usb:v1668p1441* ID_MODEL_FROM_DATABASE=IBM Integrated Bluetooth II usb:v1668p2441* ID_MODEL_FROM_DATABASE=BMDC-2 IBM Bluetooth III w.56k usb:v1668p3441* ID_MODEL_FROM_DATABASE=IBM Integrated Bluetooth III usb:v1668p6010* ID_MODEL_FROM_DATABASE=Gateway usb:v1668p6097* ID_MODEL_FROM_DATABASE=802.11b Wireless Adapter usb:v1668p6106* ID_MODEL_FROM_DATABASE=802UI3(B) 802.11b Wireless Adapter [Intersil PRISM 3] usb:v1668p7605* ID_MODEL_FROM_DATABASE=UAT1 Wireless Ethernet Adapter usb:v1669* ID_VENDOR_FROM_DATABASE=PiKRON Ltd. [hex] usb:v1669p1001* ID_MODEL_FROM_DATABASE=uLan2USB Converter - PS1 protocol usb:v166A* ID_VENDOR_FROM_DATABASE=Clipsal usb:v166Ap0101* ID_MODEL_FROM_DATABASE=C-Bus Multi-room Audio Matrix Switcher usb:v166Ap0201* ID_MODEL_FROM_DATABASE=C-Bus Pascal Automation Controller usb:v166Ap0301* ID_MODEL_FROM_DATABASE=C-Bus Wireless PC Interface usb:v166Ap0303* ID_MODEL_FROM_DATABASE=C-Bus interface usb:v166Ap0304* ID_MODEL_FROM_DATABASE=C-Bus Black and White Touchscreen usb:v166Ap0305* ID_MODEL_FROM_DATABASE=C-Bus Spectrum Colour Touchscreen usb:v166Ap0401* ID_MODEL_FROM_DATABASE=C-Bus Architectural Dimmer usb:v1677* ID_VENDOR_FROM_DATABASE=China Huada Integrated Circuit Design (Group) Co., Ltd. (CIDC Group) usb:v1677p0103* ID_MODEL_FROM_DATABASE=Token usb:v1679* ID_VENDOR_FROM_DATABASE=Total Phase usb:v1679p2001* ID_MODEL_FROM_DATABASE=Beagle Protocol Analyzer usb:v1679p2002* ID_MODEL_FROM_DATABASE=Cheetah SPI Host Adapter usb:v1680* ID_VENDOR_FROM_DATABASE=Golden Bridge Electech Inc. usb:v1680pA332* ID_MODEL_FROM_DATABASE=DVB-T Dongle [RTL2832U] usb:v1681* ID_VENDOR_FROM_DATABASE=Prevo Technologies, Inc. usb:v1681p0001* ID_MODEL_FROM_DATABASE=Tuner's Dashboard usb:v1681p0002* ID_MODEL_FROM_DATABASE=Tubachron usb:v1682* ID_VENDOR_FROM_DATABASE=Maxwise Production Enterprise Ltd. usb:v1684* ID_VENDOR_FROM_DATABASE=Godspeed Computer Corp. usb:v1685* ID_VENDOR_FROM_DATABASE=Delock usb:v1685p0200* ID_MODEL_FROM_DATABASE=Infrared adapter usb:v1686* ID_VENDOR_FROM_DATABASE=ZOOM Corporation usb:v1686p0045* ID_MODEL_FROM_DATABASE=H4 Digital Recorder usb:v1687* ID_VENDOR_FROM_DATABASE=Kingmax Digital Inc. usb:v1687p5289* ID_MODEL_FROM_DATABASE=FlashDisk usb:v1687p6211* ID_MODEL_FROM_DATABASE=FlashDisk usb:v1687p6213* ID_MODEL_FROM_DATABASE=FlashDisk usb:v1688* ID_VENDOR_FROM_DATABASE=Saab AB usb:v1689* ID_VENDOR_FROM_DATABASE=Razer USA, Ltd usb:v1689pFD00* ID_MODEL_FROM_DATABASE=Onza Tournament Edition controller usb:v168C* ID_VENDOR_FROM_DATABASE=Atheros Communications usb:v168Cp0001* ID_MODEL_FROM_DATABASE=AR5523 usb:v168Cp0002* ID_MODEL_FROM_DATABASE=AR5523 (no firmware) usb:v1690* ID_VENDOR_FROM_DATABASE=Askey Computer Corp. [hex] usb:v1690p0001* ID_MODEL_FROM_DATABASE=Arcaze Gamepad usb:v1690p0101* ID_MODEL_FROM_DATABASE=Creative Modem Blaster DE5670 usb:v1690p0102* ID_MODEL_FROM_DATABASE=V1456 VQE-R2 Modem [conexant] usb:v1690p0103* ID_MODEL_FROM_DATABASE=1456 VQE-R3 Modem [conexant] usb:v1690p0104* ID_MODEL_FROM_DATABASE=HCF V90 Data Fax RTAD Modem usb:v1690p0107* ID_MODEL_FROM_DATABASE=HCF V.90 Data,Fax,RTAD Modem usb:v1690p0109* ID_MODEL_FROM_DATABASE=MagicXpress V.90 Pocket Modem [conexant] usb:v1690p0203* ID_MODEL_FROM_DATABASE=Voyager ADSL Modem Loader usb:v1690p0204* ID_MODEL_FROM_DATABASE=Voyager ADSL Modem usb:v1690p0205* ID_MODEL_FROM_DATABASE=DSL Modem usb:v1690p0206* ID_MODEL_FROM_DATABASE=GlobeSpan ADSL WAN Modem usb:v1690p0208* ID_MODEL_FROM_DATABASE=DSL Modem usb:v1690p0209* ID_MODEL_FROM_DATABASE=Voyager 100 ADSL Modem usb:v1690p0211* ID_MODEL_FROM_DATABASE=Globespan Virata ADSL LAN Modem usb:v1690p0212* ID_MODEL_FROM_DATABASE=DSL Modem usb:v1690p0213* ID_MODEL_FROM_DATABASE=HM121d DSL Modem usb:v1690p0214* ID_MODEL_FROM_DATABASE=HM121d DSL Modem usb:v1690p0215* ID_MODEL_FROM_DATABASE=Voyager 105 ADSL Modem usb:v1690p0701* ID_MODEL_FROM_DATABASE=WLAN usb:v1690p0710* ID_MODEL_FROM_DATABASE=SMCWUSBT-G usb:v1690p0711* ID_MODEL_FROM_DATABASE=SMCWUSBT-G (no firmware) usb:v1690p0712* ID_MODEL_FROM_DATABASE=AR5523 usb:v1690p0713* ID_MODEL_FROM_DATABASE=AR5523 (no firmware) usb:v1690p0715* ID_MODEL_FROM_DATABASE=Name: Voyager 1055 Laptop 802.11g Adapter [Broadcom 4320] usb:v1690p0722* ID_MODEL_FROM_DATABASE=RT2573 usb:v1690p0726* ID_MODEL_FROM_DATABASE=Wi-Fi Wireless LAN Adapter usb:v1690p0740* ID_MODEL_FROM_DATABASE=802.11n Wireless LAN Card usb:v1690p0901* ID_MODEL_FROM_DATABASE=Voyager 205 ADSL Router usb:v1690p2000* ID_MODEL_FROM_DATABASE=naturaSign Pad Standard usb:v1690p2001* ID_MODEL_FROM_DATABASE=naturaSign Pad Standard usb:v1690pFE12* ID_MODEL_FROM_DATABASE=Bootloader usb:v1696* ID_VENDOR_FROM_DATABASE=Hitachi Video and Information System, Inc. usb:v1697* ID_VENDOR_FROM_DATABASE=VTec Test, Inc. usb:v16A5* ID_VENDOR_FROM_DATABASE=Shenzhen Zhengerya Cable Co., Ltd. usb:v16A6* ID_VENDOR_FROM_DATABASE=Unigraf usb:v16A6p3000* ID_MODEL_FROM_DATABASE=VTG-3xxx Video Test Generator family usb:v16A6p4000* ID_MODEL_FROM_DATABASE=VTG-4xxx Video Test Generator family usb:v16A6p5000* ID_MODEL_FROM_DATABASE=VTG-5xxx Video Test Generator family usb:v16A6p5001* ID_MODEL_FROM_DATABASE=VTG-5xxx Special (update) mode of VTG-5xxx family usb:v16AB* ID_VENDOR_FROM_DATABASE=Global Sun Technology usb:v16ABp7801* ID_MODEL_FROM_DATABASE=AR5523 usb:v16ABp7802* ID_MODEL_FROM_DATABASE=AR5523 (no firmware) usb:v16ABp7811* ID_MODEL_FROM_DATABASE=AR5523 usb:v16ABp7812* ID_MODEL_FROM_DATABASE=AR5523 (no firmware) usb:v16AC* ID_VENDOR_FROM_DATABASE=Dongguan ChingLung Wire & Cable Co., Ltd. usb:v16B4* ID_VENDOR_FROM_DATABASE=iStation usb:v16B4p0801* ID_MODEL_FROM_DATABASE=U43 usb:v16B5* ID_VENDOR_FROM_DATABASE=Persentec, Inc. usb:v16B5p0002* ID_MODEL_FROM_DATABASE=Otto driving companion usb:v16C0* ID_VENDOR_FROM_DATABASE=Van Ooijen Technische Informatica usb:v16C0p03E8* ID_MODEL_FROM_DATABASE=free for internal lab use 1000 usb:v16C0p03E9* ID_MODEL_FROM_DATABASE=free for internal lab use 1001 usb:v16C0p03EA* ID_MODEL_FROM_DATABASE=free for internal lab use 1002 usb:v16C0p03EB* ID_MODEL_FROM_DATABASE=free for internal lab use 1003 usb:v16C0p03EC* ID_MODEL_FROM_DATABASE=free for internal lab use 1004 usb:v16C0p03ED* ID_MODEL_FROM_DATABASE=free for internal lab use 1005 usb:v16C0p03EE* ID_MODEL_FROM_DATABASE=free for internal lab use 1006 usb:v16C0p03EF* ID_MODEL_FROM_DATABASE=free for internal lab use 1007 usb:v16C0p03F0* ID_MODEL_FROM_DATABASE=free for internal lab use 1008 usb:v16C0p03F1* ID_MODEL_FROM_DATABASE=free for internal lab use 1009 usb:v16C0p0477* ID_MODEL_FROM_DATABASE=Teensy Rebootor usb:v16C0p0478* ID_MODEL_FROM_DATABASE=Teensy Halfkay Bootloader usb:v16C0p0479* ID_MODEL_FROM_DATABASE=Teensy Debug usb:v16C0p047A* ID_MODEL_FROM_DATABASE=Teensy Serial usb:v16C0p047B* ID_MODEL_FROM_DATABASE=Teensy Serial+Debug usb:v16C0p047C* ID_MODEL_FROM_DATABASE=Teensy Keyboard usb:v16C0p047D* ID_MODEL_FROM_DATABASE=Teensy Keyboard+Debug usb:v16C0p047E* ID_MODEL_FROM_DATABASE=Teensy Mouse usb:v16C0p047F* ID_MODEL_FROM_DATABASE=Teensy Mouse+Debug usb:v16C0p0480* ID_MODEL_FROM_DATABASE=Teensy RawHID usb:v16C0p0481* ID_MODEL_FROM_DATABASE=Teensy RawHID+Debug usb:v16C0p0482* ID_MODEL_FROM_DATABASE=Teensyduino Keyboard+Mouse+Joystick usb:v16C0p0483* ID_MODEL_FROM_DATABASE=Teensyduino Serial usb:v16C0p0484* ID_MODEL_FROM_DATABASE=Teensyduino Disk usb:v16C0p0485* ID_MODEL_FROM_DATABASE=Teensyduino MIDI usb:v16C0p0486* ID_MODEL_FROM_DATABASE=Teensyduino RawHID usb:v16C0p0487* ID_MODEL_FROM_DATABASE=Teensyduino Serial+Keyboard+Mouse+Joystick usb:v16C0p0488* ID_MODEL_FROM_DATABASE=Teensyduino Flight Sim Controls usb:v16C0p05DC* ID_MODEL_FROM_DATABASE=shared ID for use with libusb usb:v16C0p05DD* ID_MODEL_FROM_DATABASE=BlackcatUSB2 usb:v16C0p05DF* ID_MODEL_FROM_DATABASE=HID device except mice, keyboards, and joysticks usb:v16C0p05E1* ID_MODEL_FROM_DATABASE=Free shared USB VID/PID pair for CDC devices usb:v16C0p05E4* ID_MODEL_FROM_DATABASE=Free shared USB VID/PID pair for MIDI devices usb:v16C0p06B4* ID_MODEL_FROM_DATABASE=USB2LPT with 2 interfaces usb:v16C0p06B5* ID_MODEL_FROM_DATABASE=USB2LPT with 3 interfaces (native, HID, printer) usb:v16C0p074E* ID_MODEL_FROM_DATABASE=DSP-Weuffen USB-HPI-Programmer usb:v16C0p074F* ID_MODEL_FROM_DATABASE=DSP-Weuffen USB2-HPI-Programmer usb:v16C0p0762* ID_MODEL_FROM_DATABASE=Osmocom SIMtrace usb:v16C0p076B* ID_MODEL_FROM_DATABASE=OpenPCD 13.56MHz RFID Reader usb:v16C0p076C* ID_MODEL_FROM_DATABASE=OpenPICC 13.56MHz RFID Simulator (native) usb:v16C0p08AC* ID_MODEL_FROM_DATABASE=OpenBeacon USB stick usb:v16C0p08CA* ID_MODEL_FROM_DATABASE=Alpermann+Velte Universal Display usb:v16C0p08CB* ID_MODEL_FROM_DATABASE=Alpermann+Velte Studio Clock usb:v16C0p08CC* ID_MODEL_FROM_DATABASE=Alpermann+Velte SAM7S MT Boot Loader usb:v16C0p08CD* ID_MODEL_FROM_DATABASE=Alpermann+Velte SAM7X MT Boot Loader usb:v16C0p0A32* ID_MODEL_FROM_DATABASE=jbmedia Light-Manager Pro usb:v16C0p27D8* ID_MODEL_FROM_DATABASE=libusb-bound devices usb:v16C0p27D9* ID_MODEL_FROM_DATABASE=HID device except mice, keyboards, and joysticks usb:v16C0p27DA* ID_MODEL_FROM_DATABASE=Mouse usb:v16C0p27DB* ID_MODEL_FROM_DATABASE=Keyboard usb:v16C0p27DC* ID_MODEL_FROM_DATABASE=Joystick usb:v16C0p27DD* ID_MODEL_FROM_DATABASE=CDC-ACM class devices (modems) usb:v16C0p27DE* ID_MODEL_FROM_DATABASE=MIDI class devices usb:v16C0p294A* ID_MODEL_FROM_DATABASE=Eye Movement Recorder [Visagraph] usb:v16C0p294B* ID_MODEL_FROM_DATABASE=Eye Movement Recorder [ReadAlyzer] usb:v16CA* ID_VENDOR_FROM_DATABASE=Wireless Cables, Inc. usb:v16CAp1502* ID_MODEL_FROM_DATABASE=Bluetooth Dongle usb:v16CC* ID_VENDOR_FROM_DATABASE=silex technology, Inc. usb:v16D0* ID_VENDOR_FROM_DATABASE=MCS usb:v16D0p0498* ID_MODEL_FROM_DATABASE=Braintechnology USB-LPS usb:v16D0p0504* ID_MODEL_FROM_DATABASE=RETRO Innovations ZoomFloppy usb:v16D0p054B* ID_MODEL_FROM_DATABASE=GrauTec ReelBox OLED Display (external) usb:v16D0p05BE* ID_MODEL_FROM_DATABASE=EasyLogic Board usb:v16D0p06F9* ID_MODEL_FROM_DATABASE=Gabotronics Xminilab usb:v16D0p0753* ID_MODEL_FROM_DATABASE=Digistump DigiSpark usb:v16D0p075C* ID_MODEL_FROM_DATABASE=AB-1.x UAC1 [Audio Widget] usb:v16D0p075D* ID_MODEL_FROM_DATABASE=AB-1.x UAC2 [Audio Widget] usb:v16D0p080A* ID_MODEL_FROM_DATABASE=S2E1 Interface usb:v16D0p0870* ID_MODEL_FROM_DATABASE=Kaufmann Automotive GmbH, RKS+CAN Interface usb:v16D1* ID_VENDOR_FROM_DATABASE=Suprema Inc. usb:v16D1p0401* ID_MODEL_FROM_DATABASE=SUP-SFR400(A) BioMini Fingerprint Reader usb:v16D3* ID_VENDOR_FROM_DATABASE=Frontline Test Equipment, Inc. usb:v16D5* ID_VENDOR_FROM_DATABASE=AnyDATA Corporation usb:v16D5p6202* ID_MODEL_FROM_DATABASE=CDMA/UMTS/GPRS modem usb:v16D5p6501* ID_MODEL_FROM_DATABASE=CDMA 2000 1xRTT/EV-DO Modem usb:v16D5p6502* ID_MODEL_FROM_DATABASE=CDMA/UMTS/GPRS modem usb:v16D5p6603* ID_MODEL_FROM_DATABASE=ADU-890WH modem usb:v16D6* ID_VENDOR_FROM_DATABASE=JABLOCOM s.r.o. usb:v16D6p8000* ID_MODEL_FROM_DATABASE=GDP-04 desktop phone usb:v16D6p8001* ID_MODEL_FROM_DATABASE=EYE-02 usb:v16D6p8003* ID_MODEL_FROM_DATABASE=GDP-04 modem usb:v16D6p8004* ID_MODEL_FROM_DATABASE=Bootloader usb:v16D6p8005* ID_MODEL_FROM_DATABASE=GDP-04i usb:v16D6p8007* ID_MODEL_FROM_DATABASE=BTP-06 modem usb:v16D8* ID_VENDOR_FROM_DATABASE=CMOTECH Co., Ltd. usb:v16D8p5141* ID_MODEL_FROM_DATABASE=CMOTECH CDMA Technologies modem usb:v16D8p5533* ID_MODEL_FROM_DATABASE=CCU-550 CDMA EV-DO modem usb:v16D8p5543* ID_MODEL_FROM_DATABASE=CDMA 2000 1xRTT/1xEVDO modem usb:v16D8p6280* ID_MODEL_FROM_DATABASE=CMOTECH CDMA Technologies modem usb:v16D8p6803* ID_MODEL_FROM_DATABASE=CNU-680 CDMA EV-DO modem usb:v16D8p8001* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem (QDL mode) usb:v16D8p8002* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem usb:v16DC* ID_VENDOR_FROM_DATABASE=Wiener, Plein & Baus usb:v16DCp0001* ID_MODEL_FROM_DATABASE=CC usb:v16DCp000B* ID_MODEL_FROM_DATABASE=VM usb:v16DCp0010* ID_MODEL_FROM_DATABASE=PL512 Power Supply System usb:v16DCp0011* ID_MODEL_FROM_DATABASE=MARATON Power Supply System usb:v16DCp0012* ID_MODEL_FROM_DATABASE=MPOD Multi Channel Power Supply System usb:v16DCp0015* ID_MODEL_FROM_DATABASE=CML Control, Measurement and Data Logging System usb:v16DF* ID_VENDOR_FROM_DATABASE=King Billion Electronics Co., Ltd. usb:v16F0* ID_VENDOR_FROM_DATABASE=GN ReSound A/S usb:v16F0p0001* ID_MODEL_FROM_DATABASE=Speedlink Programming Interface usb:v16F0p0003* ID_MODEL_FROM_DATABASE=Airlink Wireless Programming Interface usb:v16F5* ID_VENDOR_FROM_DATABASE=Futurelogic Inc. usb:v1706* ID_VENDOR_FROM_DATABASE=BlueView Technologies, Inc. usb:v1707* ID_VENDOR_FROM_DATABASE=ARTIMI usb:v170B* ID_VENDOR_FROM_DATABASE=Swissonic usb:v170Bp0011* ID_MODEL_FROM_DATABASE=MIDI-USB 1x1 usb:v170D* ID_VENDOR_FROM_DATABASE=Avnera usb:v1711* ID_VENDOR_FROM_DATABASE=Leica Microsystems usb:v1711p0101* ID_MODEL_FROM_DATABASE=DFC-365FX camera usb:v1711p3020* ID_MODEL_FROM_DATABASE=IC80 HD Camera usb:v1724* ID_VENDOR_FROM_DATABASE=Meyer Instruments (MIS) usb:v1724p0115* ID_MODEL_FROM_DATABASE=PAXcam5 usb:v1725* ID_VENDOR_FROM_DATABASE=Vitesse Semiconductor usb:v1726* ID_VENDOR_FROM_DATABASE=Axesstel, Inc. usb:v1726p1000* ID_MODEL_FROM_DATABASE=wireless modem usb:v1726p2000* ID_MODEL_FROM_DATABASE=wireless modem usb:v1726p3000* ID_MODEL_FROM_DATABASE=wireless modem usb:v172F* ID_VENDOR_FROM_DATABASE=Waltop International Corp. usb:v172Fp0022* ID_MODEL_FROM_DATABASE=Tablet usb:v172Fp0024* ID_MODEL_FROM_DATABASE=Tablet usb:v172Fp0025* ID_MODEL_FROM_DATABASE=Tablet usb:v172Fp0026* ID_MODEL_FROM_DATABASE=Tablet usb:v172Fp0031* ID_MODEL_FROM_DATABASE=Slim Tablet 12.1" usb:v172Fp0032* ID_MODEL_FROM_DATABASE=Slim Tablet 5.8" usb:v172Fp0034* ID_MODEL_FROM_DATABASE=Slim Tablet 12.1" usb:v172Fp0038* ID_MODEL_FROM_DATABASE=Genius G-Pen F509 usb:v172Fp0500* ID_MODEL_FROM_DATABASE=Media Tablet 14.1" usb:v172Fp0501* ID_MODEL_FROM_DATABASE=Media Tablet 10.6" usb:v172Fp0502* ID_MODEL_FROM_DATABASE=Sirius Battery Free Tablet usb:v1733* ID_VENDOR_FROM_DATABASE=Cellink Technology Co., Ltd usb:v1733p0101* ID_MODEL_FROM_DATABASE=RF Wireless Optical Mouse OP-701 usb:v1736* ID_VENDOR_FROM_DATABASE=CANON IMAGING SYSTEM TECHNOLOGIES INC. usb:v1737* ID_VENDOR_FROM_DATABASE=Linksys usb:v1737p0039* ID_MODEL_FROM_DATABASE=USB1000 Gigabit Notebook Adapter usb:v1737p0070* ID_MODEL_FROM_DATABASE=WUSB100 v1 RangePlus Wireless Network Adapter [Ralink RT2870] usb:v1737p0071* ID_MODEL_FROM_DATABASE=WUSB600N v1 Dual-Band Wireless-N Network Adapter [Ralink RT2870] usb:v1737p0073* ID_MODEL_FROM_DATABASE=WUSB54GC v2 802.11g Adapter [Realtek RTL8187B] usb:v1737p0075* ID_MODEL_FROM_DATABASE=WUSB54GSC v2 802.11g Adapter [Broadcom 4326U] usb:v1737p0077* ID_MODEL_FROM_DATABASE=WUSB54GC v3 802.11g Adapter [Ralink RT2070L] usb:v1737p0078* ID_MODEL_FROM_DATABASE=WUSB100 v2 RangePlus Wireless Network Adapter [Ralink RT3070] usb:v1737p0079* ID_MODEL_FROM_DATABASE=WUSB600N v2 Dual-Band Wireless-N Network Adapter [Ralink RT3572] usb:v173D* ID_VENDOR_FROM_DATABASE=QSENN usb:v173Dp0002* ID_MODEL_FROM_DATABASE=GP-K7000 keyboard usb:v1740* ID_VENDOR_FROM_DATABASE=Senao usb:v1740p0100* ID_MODEL_FROM_DATABASE=EUB1200AC AC1200 DB Wireless Adapter [Realtek RTL8812AU] usb:v1740p0600* ID_MODEL_FROM_DATABASE=EUB600v1 802.11abgn Wireless Adapter [Ralink RT3572] usb:v1740p0605* ID_MODEL_FROM_DATABASE=LevelOne WUA-0605 N_Max Wireless USB Adapter usb:v1740p0615* ID_MODEL_FROM_DATABASE=LevelOne WUA-0615 N_Max Wireless USB Adapter usb:v1740p1000* ID_MODEL_FROM_DATABASE=NUB-350 802.11g Wireless Adapter [Intersil ISL3887] usb:v1740p2000* ID_MODEL_FROM_DATABASE=NUB-8301 802.11bg usb:v1740p3701* ID_MODEL_FROM_DATABASE=EUB-3701 EXT 802.11g Wireless Adapter [Ralink RT2571W] usb:v1740p9603* ID_MODEL_FROM_DATABASE=RTL8188S WLAN Adapter usb:v1740p9701* ID_MODEL_FROM_DATABASE=EnGenius 802.11n Wireless USB Adapter usb:v1740p9702* ID_MODEL_FROM_DATABASE=EnGenius 802.11n Wireless USB Adapter usb:v1740p9703* ID_MODEL_FROM_DATABASE=EnGenius 802.11n Wireless USB Adapter usb:v1740p9705* ID_MODEL_FROM_DATABASE=EnGenius 802.11n Wireless USB Adapter usb:v1740p9706* ID_MODEL_FROM_DATABASE=EUB9706 802.11n Wireless Adapter [Ralink RT3072] usb:v1740p9801* ID_MODEL_FROM_DATABASE=EUB9801 802.11abgn Wireless Adapter [Ralink RT3572] usb:v1743* ID_VENDOR_FROM_DATABASE=General Atomics usb:v1748* ID_VENDOR_FROM_DATABASE=MQP Electronics usb:v1748p0101* ID_MODEL_FROM_DATABASE=Packet-Master USB12 usb:v174C* ID_VENDOR_FROM_DATABASE=ASMedia Technology Inc. usb:v174Cp1153* ID_MODEL_FROM_DATABASE=ASM2115 SATA 6Gb/s bridge usb:v174Cp2074* ID_MODEL_FROM_DATABASE=ASM1074 High-Speed hub usb:v174Cp3074* ID_MODEL_FROM_DATABASE=ASM1074 SuperSpeed hub usb:v174Cp5106* ID_MODEL_FROM_DATABASE=ASM1051 SATA 3Gb/s bridge usb:v174Cp5136* ID_MODEL_FROM_DATABASE=ASM1053 SATA 6Gb/s bridge usb:v174Cp55AA* ID_MODEL_FROM_DATABASE=ASM1051E SATA 6Gb/s bridge, ASM1053E SATA 6Gb/s bridge, ASM1153 SATA 3Gb/s bridge usb:v174F* ID_VENDOR_FROM_DATABASE=Syntek usb:v174Fp1105* ID_MODEL_FROM_DATABASE=SM-MS/Pro-MMC-XD Card Reader usb:v174Fp110B* ID_MODEL_FROM_DATABASE=HP Webcam usb:v174Fp1403* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v174Fp1404* ID_MODEL_FROM_DATABASE=USB Camera device, 1.3 MPixel Web Cam usb:v174Fp5212* ID_MODEL_FROM_DATABASE=USB 2.0 UVC PC Camera usb:v174Fp5A11* ID_MODEL_FROM_DATABASE=PC Camera usb:v174Fp5A31* ID_MODEL_FROM_DATABASE=Sonix USB 2.0 Camera usb:v174Fp5A35* ID_MODEL_FROM_DATABASE=Sonix 1.3MPixel USB 2.0 Camera usb:v174Fp6A31* ID_MODEL_FROM_DATABASE=Web Cam - Asus A8J, F3S, F5R, VX2S, V1S usb:v174Fp6A33* ID_MODEL_FROM_DATABASE=Web Cam - Asus F3SA, F9J, F9S usb:v174Fp6A51* ID_MODEL_FROM_DATABASE=2.0MPixel Web Cam - Asus Z96J, Z96S, S96S usb:v174Fp6A54* ID_MODEL_FROM_DATABASE=Web Cam usb:v174Fp6D51* ID_MODEL_FROM_DATABASE=2.0Mpixel Web Cam - Eurocom D900C usb:v174Fp8A12* ID_MODEL_FROM_DATABASE=Syntek 0.3MPixel USB 2.0 UVC PC Camera usb:v174Fp8A33* ID_MODEL_FROM_DATABASE=Syntek USB 2.0 UVC PC Camera usb:v174FpA311* ID_MODEL_FROM_DATABASE=1.3MPixel Web Cam - Asus A3A, A6J, A6K, A6M, A6R, A6T, A6V, A7T, A7sv, A7U usb:v174FpA312* ID_MODEL_FROM_DATABASE=1.3MPixel Web Cam usb:v174FpA821* ID_MODEL_FROM_DATABASE=Web Cam - Packard Bell BU45, PB Easynote MX66-208W usb:v174FpAA11* ID_MODEL_FROM_DATABASE=Web Cam usb:v1753* ID_VENDOR_FROM_DATABASE=GERTEC Telecomunicacoes Ltda. usb:v1753pC901* ID_MODEL_FROM_DATABASE=PPC900 Pinpad Terminal usb:v1756* ID_VENDOR_FROM_DATABASE=ENENSYS Technologies usb:v1756p0006* ID_MODEL_FROM_DATABASE=DiviPitch usb:v1759* ID_VENDOR_FROM_DATABASE=LucidPort Technology, Inc. usb:v1761* ID_VENDOR_FROM_DATABASE=ASUSTek Computer, Inc. (wrong ID) usb:v1761p0B05* ID_MODEL_FROM_DATABASE=802.11n Network Adapter (wrong ID - swapped vendor and device) usb:v1772* ID_VENDOR_FROM_DATABASE=System Level Solutions, Inc. usb:v1776* ID_VENDOR_FROM_DATABASE=Arowana usb:v1776p501C* ID_MODEL_FROM_DATABASE=300K CMOS Camera usb:v177F* ID_VENDOR_FROM_DATABASE=Sweex usb:v177Fp0004* ID_MODEL_FROM_DATABASE=MM004V5 Photo Key Chain (Digital Photo Frame) 1.5" usb:v177Fp0153* ID_MODEL_FROM_DATABASE=LW153 802.11n Adapter [ralink rt3070] usb:v177Fp0154* ID_MODEL_FROM_DATABASE=LW154 802.11bgn (1x1:1) Wireless Adapter [Realtek RTL8188SU] usb:v177Fp0313* ID_MODEL_FROM_DATABASE=LW313 802.11n Adapter [ralink rt2770 + rt2720] usb:v1781* ID_VENDOR_FROM_DATABASE=Multiple Vendors usb:v1781p083E* ID_MODEL_FROM_DATABASE=MetaGeek Wi-Spy usb:v1781p083F* ID_MODEL_FROM_DATABASE=MetaGeek Wi-Spy 2.4x usb:v1781p0938* ID_MODEL_FROM_DATABASE=Iguanaworks USB IR Transceiver usb:v1781p0A96* ID_MODEL_FROM_DATABASE=raphnet.net usb_game12 usb:v1781p0A97* ID_MODEL_FROM_DATABASE=raphnet.net SNES mouse adapter usb:v1781p0A98* ID_MODEL_FROM_DATABASE=raphnet.net USBTenki usb:v1781p0A99* ID_MODEL_FROM_DATABASE=raphnet.net NES usb:v1781p0A9A* ID_MODEL_FROM_DATABASE=raphnet.net Gamecube/N64 controller usb:v1781p0A9B* ID_MODEL_FROM_DATABASE=raphnet.net DB9Joy usb:v1781p0A9C* ID_MODEL_FROM_DATABASE=raphnet.net Intellivision usb:v1781p0A9D* ID_MODEL_FROM_DATABASE=raphnet.net 4nes4snes usb:v1781p0A9E* ID_MODEL_FROM_DATABASE=raphnet.net Megadrive multitap usb:v1781p0A9F* ID_MODEL_FROM_DATABASE=raphnet.net MultiDB9joy usb:v1781p0C30* ID_MODEL_FROM_DATABASE=Telldus TellStick usb:v1781p0C31* ID_MODEL_FROM_DATABASE=Telldus TellStick Duo usb:v1781p0C9F* ID_MODEL_FROM_DATABASE=USBtiny usb:v1781p1EEF* ID_MODEL_FROM_DATABASE=OpenAPC SecuKey usb:v1781p1EF0* ID_MODEL_FROM_DATABASE=E1701 Modular Controller Card usb:v1781p1EF1* ID_MODEL_FROM_DATABASE=E1701 Modular Controller Card usb:v1782* ID_VENDOR_FROM_DATABASE=Spreadtrum Communications Inc. usb:v1784* ID_VENDOR_FROM_DATABASE=TopSeed Technology Corp. usb:v1784p0001* ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver usb:v1784p0004* ID_MODEL_FROM_DATABASE=RF Combo Device usb:v1784p0006* ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver usb:v1784p0007* ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver usb:v1784p0008* ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver usb:v1784p000A* ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver usb:v1784p0011* ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver usb:v1787* ID_VENDOR_FROM_DATABASE=ATI AIB usb:v1788* ID_VENDOR_FROM_DATABASE=ShenZhen Litkconn Technology Co., Ltd. usb:v1796* ID_VENDOR_FROM_DATABASE=Printrex, Inc. usb:v1797* ID_VENDOR_FROM_DATABASE=JALCO CO., LTD. usb:v1799* ID_VENDOR_FROM_DATABASE=Thales Norway A/S usb:v1799p7051* ID_MODEL_FROM_DATABASE=Belkin F5D7051 802.11g Adapter v1000 [Broadcom 4320] usb:v1799p8051* ID_MODEL_FROM_DATABASE=Belkin F5D8051 v2 802.11bgn Wireless Adapter [Marvell 88W8362] usb:v179D* ID_VENDOR_FROM_DATABASE=Ricavision International, Inc. usb:v179Dp0010* ID_MODEL_FROM_DATABASE=Internal Infrared Transceiver usb:v17A0* ID_VENDOR_FROM_DATABASE=Samson Technologies Corp. usb:v17A0p0001* ID_MODEL_FROM_DATABASE=C01U condenser microphone usb:v17A0p0002* ID_MODEL_FROM_DATABASE=Q1U dynamic microphone usb:v17A0p0100* ID_MODEL_FROM_DATABASE=C03U multi-pattern microphone usb:v17A0p0101* ID_MODEL_FROM_DATABASE=UB1 boundary microphone usb:v17A0p0120* ID_MODEL_FROM_DATABASE=Meteorite condenser microphone usb:v17A0p0200* ID_MODEL_FROM_DATABASE=StudioDock monitors (internal hub) usb:v17A0p0201* ID_MODEL_FROM_DATABASE=StudioDock monitors (audio) usb:v17A0p0210* ID_MODEL_FROM_DATABASE=StudioGT monitors usb:v17A0p0301* ID_MODEL_FROM_DATABASE=Q2U handheld microphone with XLR usb:v17A0p0302* ID_MODEL_FROM_DATABASE=GoMic compact condenser microphone usb:v17A0p0303* ID_MODEL_FROM_DATABASE=C01U Pro condenser microphone usb:v17A0p0304* ID_MODEL_FROM_DATABASE=Q2U handheld mic with XLR usb:v17A0p0305* ID_MODEL_FROM_DATABASE=GoMic compact condenser mic usb:v17A0p0310* ID_MODEL_FROM_DATABASE=Meteor condenser microphone usb:v17A4* ID_VENDOR_FROM_DATABASE=Concept2 usb:v17A4p0001* ID_MODEL_FROM_DATABASE=Performance Monitor 3 usb:v17A4p0002* ID_MODEL_FROM_DATABASE=Performance Monitor 4 usb:v17A5* ID_VENDOR_FROM_DATABASE=Advanced Connection Technology Inc. usb:v17A7* ID_VENDOR_FROM_DATABASE=MICOMSOFT CO., LTD. usb:v17A8* ID_VENDOR_FROM_DATABASE=Kamstrup A/S usb:v17A8p0001* ID_MODEL_FROM_DATABASE=Optical Eye/3-wire usb:v17A8p0005* ID_MODEL_FROM_DATABASE=M-Bus Master MultiPort 250D usb:v17B3* ID_VENDOR_FROM_DATABASE=Grey Innovation usb:v17B3p0004* ID_MODEL_FROM_DATABASE=Linux-USB Midi Gadget usb:v17B5* ID_VENDOR_FROM_DATABASE=Lunatone usb:v17B5p0010* ID_MODEL_FROM_DATABASE=MFT Sensor usb:v17BA* ID_VENDOR_FROM_DATABASE=SAURIS GmbH usb:v17BAp0001* ID_MODEL_FROM_DATABASE=SAU510-USB [no firmware] usb:v17BAp0510* ID_MODEL_FROM_DATABASE=SAU510-USB and SAU510-USB plus JTAG Emulators usb:v17BAp0511* ID_MODEL_FROM_DATABASE=SAU510-USB Iso Plus JTAG Emulator usb:v17BAp0520* ID_MODEL_FROM_DATABASE=SAU510-USB Nano JTAG Emulator usb:v17BAp1511* ID_MODEL_FROM_DATABASE=Onboard Emulator on SAUModule development kit usb:v17C3* ID_VENDOR_FROM_DATABASE=Singim International Corp. usb:v17CC* ID_VENDOR_FROM_DATABASE=Native Instruments usb:v17CCp041C* ID_MODEL_FROM_DATABASE=Audio 2 DJ usb:v17CCp0808* ID_MODEL_FROM_DATABASE=Maschine Controller usb:v17CCp0815* ID_MODEL_FROM_DATABASE=Audio Kontrol 1 usb:v17CCp0839* ID_MODEL_FROM_DATABASE=Audio 4 DJ usb:v17CCp0D8D* ID_MODEL_FROM_DATABASE=Guitarrig Mobile usb:v17CCp1915* ID_MODEL_FROM_DATABASE=Session I/O usb:v17CCp1940* ID_MODEL_FROM_DATABASE=RigKontrol3 usb:v17CCp1969* ID_MODEL_FROM_DATABASE=RigKontrol2 usb:v17CCp1978* ID_MODEL_FROM_DATABASE=Audio 8 DJ usb:v17CCp2280* ID_MODEL_FROM_DATABASE=Medion MDPNA1500 in card reader mode usb:v17CCp2305* ID_MODEL_FROM_DATABASE=Traktor Kontrol X1 usb:v17CCp4711* ID_MODEL_FROM_DATABASE=Kore Controller usb:v17CCp4712* ID_MODEL_FROM_DATABASE=Kore Controller 2 usb:v17CCpBAFF* ID_MODEL_FROM_DATABASE=Traktor Kontrol S4 usb:v17CF* ID_VENDOR_FROM_DATABASE=Hip Hing Cable & Plug Mfy. Ltd. usb:v17D0* ID_VENDOR_FROM_DATABASE=Sanford L.P. usb:v17D3* ID_VENDOR_FROM_DATABASE=Korea Techtron Co., Ltd. usb:v17E9* ID_VENDOR_FROM_DATABASE=DisplayLink usb:v17E9p0051* ID_MODEL_FROM_DATABASE=USB VGA Adaptor usb:v17E9p030B* ID_MODEL_FROM_DATABASE=HP T100 usb:v17E9p0377* ID_MODEL_FROM_DATABASE=Plugable UD-160-A (M) usb:v17E9p0378* ID_MODEL_FROM_DATABASE=Plugable UGA-2K-A usb:v17E9p0379* ID_MODEL_FROM_DATABASE=Plugable UGA-125 usb:v17E9p037A* ID_MODEL_FROM_DATABASE=Plugable UGA-165 usb:v17E9p037B* ID_MODEL_FROM_DATABASE=Plugable USB-VGA-165 usb:v17E9p037C* ID_MODEL_FROM_DATABASE=Plugable DC-125 usb:v17E9p037D* ID_MODEL_FROM_DATABASE=Plugable USB2-HDMI-165 usb:v17E9p410A* ID_MODEL_FROM_DATABASE=HDMI Adapter usb:v17E9p430A* ID_MODEL_FROM_DATABASE=HP Port Replicator (Composite Device) usb:v17E9p4312* ID_MODEL_FROM_DATABASE=S2340T usb:v17EB* ID_VENDOR_FROM_DATABASE=Cornice, Inc. usb:v17EF* ID_VENDOR_FROM_DATABASE=Lenovo usb:v17EFp1000* ID_MODEL_FROM_DATABASE=Hub usb:v17EFp1003* ID_MODEL_FROM_DATABASE=Integrated Smart Card Reader usb:v17EFp1004* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v17EFp1008* ID_MODEL_FROM_DATABASE=Hub usb:v17EFp100A* ID_MODEL_FROM_DATABASE=ThinkPad Mini Dock Plus Series 3 usb:v17EFp304B* ID_MODEL_FROM_DATABASE=AX88179 Gigabit Ethernet [ThinkPad OneLink GigaLAN] usb:v17EFp3815* ID_MODEL_FROM_DATABASE=ChipsBnk 2GB USB Stick usb:v17EFp4802* ID_MODEL_FROM_DATABASE=Lenovo Vc0323+MI1310_SOC Camera usb:v17EFp4807* ID_MODEL_FROM_DATABASE=UVC Camera usb:v17EFp480C* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v17EFp480D* ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] usb:v17EFp480E* ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] usb:v17EFp480F* ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] usb:v17EFp4810* ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] usb:v17EFp4811* ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] usb:v17EFp4812* ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] usb:v17EFp4813* ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] usb:v17EFp4814* ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] usb:v17EFp4815* ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] usb:v17EFp4816* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v17EFp481C* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v17EFp481D* ID_MODEL_FROM_DATABASE=Integrated Webcam usb:v17EFp6004* ID_MODEL_FROM_DATABASE=ISD-V4 Tablet Pen usb:v17EFp6007* ID_MODEL_FROM_DATABASE=Smartcard Keyboard usb:v17EFp6009* ID_MODEL_FROM_DATABASE=ThinkPad Keyboard with TrackPoint usb:v17EFp6014* ID_MODEL_FROM_DATABASE=Mini Wireless Keyboard N5901 usb:v17EFp6025* ID_MODEL_FROM_DATABASE=ThinkPad Travel Mouse usb:v17EFp7203* ID_MODEL_FROM_DATABASE=Ethernet adapter [U2L 100P-Y1] usb:v17EFp7423* ID_MODEL_FROM_DATABASE=IdeaPad A1 Tablet usb:v17EFp7435* ID_MODEL_FROM_DATABASE=A789 (Mass Storage mode, with debug) usb:v17EFp743A* ID_MODEL_FROM_DATABASE=A789 (Mass Storage mode) usb:v17EFp7497* ID_MODEL_FROM_DATABASE=A789 (MTP mode) usb:v17EFp7498* ID_MODEL_FROM_DATABASE=A789 (MTP mode, with debug) usb:v17EFp749A* ID_MODEL_FROM_DATABASE=A789 (PTP mode) usb:v17EFp749B* ID_MODEL_FROM_DATABASE=A789 (PTP mode, with debug) usb:v17F4* ID_VENDOR_FROM_DATABASE=WaveSense usb:v17F4pAAAA* ID_MODEL_FROM_DATABASE=Jazz Blood Glucose Meter usb:v17F5* ID_VENDOR_FROM_DATABASE=K.K. Rocky usb:v17F6* ID_VENDOR_FROM_DATABASE=Unicomp, Inc usb:v17F6p0709* ID_MODEL_FROM_DATABASE=Model M Keyboard usb:v1809* ID_VENDOR_FROM_DATABASE=Advantech usb:v1809p4604* ID_MODEL_FROM_DATABASE=USB-4604 usb:v1809p4761* ID_MODEL_FROM_DATABASE=USB-4761 Portable Data Acquisition Module usb:v1822* ID_VENDOR_FROM_DATABASE=Twinhan usb:v1822p3201* ID_MODEL_FROM_DATABASE=VisionDTV USB-Ter/HAMA USB DVB-T device cold usb:v1822p3202* ID_MODEL_FROM_DATABASE=VisionDTV USB-Ter/HAMA USB DVB-T device warm usb:v1831* ID_VENDOR_FROM_DATABASE=Gwo Jinn Industries Co., Ltd. usb:v1832* ID_VENDOR_FROM_DATABASE=Huizhou Shenghua Industrial Co., Ltd. usb:v183D* ID_VENDOR_FROM_DATABASE=VIVOphone usb:v183Dp0010* ID_MODEL_FROM_DATABASE=VoiceKey usb:v1843* ID_VENDOR_FROM_DATABASE=Vaisala usb:v1849* ID_VENDOR_FROM_DATABASE=ASRock Incorporation usb:v1852* ID_VENDOR_FROM_DATABASE=GYROCOM C&C Co., LTD usb:v1852p7922* ID_MODEL_FROM_DATABASE=Audiotrak DR.DAC2 DX [GYROCOM C&C] usb:v1854* ID_VENDOR_FROM_DATABASE=Memory Devices Ltd. usb:v185B* ID_VENDOR_FROM_DATABASE=Compro usb:v185Bp3020* ID_MODEL_FROM_DATABASE=K100 Infrared Receiver usb:v185Bp3082* ID_MODEL_FROM_DATABASE=K100 Infrared Receiver v2 usb:v185BpD000* ID_MODEL_FROM_DATABASE=Compro Videomate DVB-U2000 - DVB-T USB cold usb:v185BpD001* ID_MODEL_FROM_DATABASE=Compro Videomate DVB-U2000 - DVB-T USB warm usb:v1861* ID_VENDOR_FROM_DATABASE=Tech Technology Industrial Company usb:v1862* ID_VENDOR_FROM_DATABASE=Teridian Semiconductor Corp. usb:v1870* ID_VENDOR_FROM_DATABASE=Nexio Co., Ltd usb:v1870p0001* ID_MODEL_FROM_DATABASE=iNexio Touchscreen controller usb:v1871* ID_VENDOR_FROM_DATABASE=Aveo Technology Corp. usb:v1871p0101* ID_MODEL_FROM_DATABASE=UVC camera (Bresser microscope) usb:v1871p0141* ID_MODEL_FROM_DATABASE=Camera usb:v1871p0D01* ID_MODEL_FROM_DATABASE=USB2.0 Camera usb:v1873* ID_VENDOR_FROM_DATABASE=Navilock usb:v1873pEE93* ID_MODEL_FROM_DATABASE=EasyLogger usb:v187C* ID_VENDOR_FROM_DATABASE=Alienware Corporation usb:v187Cp0511* ID_MODEL_FROM_DATABASE=AlienFX Mobile lighting usb:v187Cp0600* ID_MODEL_FROM_DATABASE=Dual Compatible Game Pad usb:v187F* ID_VENDOR_FROM_DATABASE=Siano Mobile Silicon usb:v187Fp0010* ID_MODEL_FROM_DATABASE=Stallar Board usb:v187Fp0100* ID_MODEL_FROM_DATABASE=Stallar Board usb:v187Fp0200* ID_MODEL_FROM_DATABASE=Nova A usb:v187Fp0201* ID_MODEL_FROM_DATABASE=Nova B usb:v187Fp0202* ID_MODEL_FROM_DATABASE=Nice usb:v187Fp0300* ID_MODEL_FROM_DATABASE=Vega usb:v187Fp0301* ID_MODEL_FROM_DATABASE=VeNice usb:v1892* ID_VENDOR_FROM_DATABASE=Vast Technologies, Inc. usb:v1894* ID_VENDOR_FROM_DATABASE=Topseed usb:v1894p5632* ID_MODEL_FROM_DATABASE=Atek Tote Remote usb:v1894p5641* ID_MODEL_FROM_DATABASE=TSAM-004 Presentation Remote usb:v1897* ID_VENDOR_FROM_DATABASE=Evertop Wire Cable Co. usb:v189F* ID_VENDOR_FROM_DATABASE=3Shape A/S usb:v189Fp0002* ID_MODEL_FROM_DATABASE=Legato2 3D Scanner usb:v18A4* ID_VENDOR_FROM_DATABASE=CSSN usb:v18A4p0001* ID_MODEL_FROM_DATABASE=Snapshell IDR usb:v18A5* ID_VENDOR_FROM_DATABASE=Verbatim, Ltd usb:v18A5p0214* ID_MODEL_FROM_DATABASE=Portable Hard Drive usb:v18A5p0216* ID_MODEL_FROM_DATABASE=External Hard Drive usb:v18A5p0218* ID_MODEL_FROM_DATABASE=External Hard Drive usb:v18A5p0224* ID_MODEL_FROM_DATABASE=Store 'n' Go Micro Plus usb:v18A5p0227* ID_MODEL_FROM_DATABASE=Pocket Hard Drive usb:v18A5p022B* ID_MODEL_FROM_DATABASE=Portable Hard Drive (Store'n'Go) usb:v18A5p0237* ID_MODEL_FROM_DATABASE=Portable Harddrive usb:v18A5p0243* ID_MODEL_FROM_DATABASE=Flash Drive (Store'n'Go) usb:v18A5p0302* ID_MODEL_FROM_DATABASE=Flash Drive usb:v18A5p0304* ID_MODEL_FROM_DATABASE=Store 'n' Go usb:v18A5p4123* ID_MODEL_FROM_DATABASE=Store N Go usb:v18B1* ID_VENDOR_FROM_DATABASE=Petalynx usb:v18B1p0037* ID_MODEL_FROM_DATABASE=Maxter Remote Control usb:v18B4* ID_VENDOR_FROM_DATABASE=e3C Technologies usb:v18B4p1001* ID_MODEL_FROM_DATABASE=DUTV007 usb:v18B4p1002* ID_MODEL_FROM_DATABASE=EC168 (v5) based USB DVB-T receiver usb:v18B4p1689* ID_MODEL_FROM_DATABASE=DUTV009 usb:v18B4pFFFA* ID_MODEL_FROM_DATABASE=EC168 (v2) based USB DVB-T receiver usb:v18B4pFFFB* ID_MODEL_FROM_DATABASE=EC168 (v3) based USB DVB-T receiver usb:v18B6* ID_VENDOR_FROM_DATABASE=Mikkon Technology Limited usb:v18B7* ID_VENDOR_FROM_DATABASE=Zotek Electronic Co., Ltd. usb:v18C5* ID_VENDOR_FROM_DATABASE=AMIT Technology, Inc. usb:v18C5p0002* ID_MODEL_FROM_DATABASE=CG-WLUSB2GO usb:v18C5p0008* ID_MODEL_FROM_DATABASE=CG-WLUSB2GNR Corega Wireless USB Adapter usb:v18C5p0012* ID_MODEL_FROM_DATABASE=CG-WLUSB10 Corega Wireless USB Adapter usb:v18CD* ID_VENDOR_FROM_DATABASE=Ecamm usb:v18CDpCAFE* ID_MODEL_FROM_DATABASE=Pico iMage usb:v18D1* ID_VENDOR_FROM_DATABASE=Google Inc. usb:v18D1p0001* ID_MODEL_FROM_DATABASE=Onda V972 (storage access) usb:v18D1p0003* ID_MODEL_FROM_DATABASE=Android-powered device using AllWinner Technology SoC usb:v18D1p0006* ID_MODEL_FROM_DATABASE=Onda V972 MTP usb:v18D1p0008* ID_MODEL_FROM_DATABASE=Onda V972 PTP (camera) usb:v18D1p0D02* ID_MODEL_FROM_DATABASE=Celkon A88 usb:v18D1p2D00* ID_MODEL_FROM_DATABASE=Android-powered device in accessory mode usb:v18D1p2D01* ID_MODEL_FROM_DATABASE=Android-powered device in accessory mode with ADB support usb:v18D1p4E11* ID_MODEL_FROM_DATABASE=Nexus One usb:v18D1p4E12* ID_MODEL_FROM_DATABASE=Nexus One (debug) usb:v18D1p4E13* ID_MODEL_FROM_DATABASE=Nexus One (tether) usb:v18D1p4E20* ID_MODEL_FROM_DATABASE=Nexus S (fastboot) usb:v18D1p4E21* ID_MODEL_FROM_DATABASE=Nexus S usb:v18D1p4E22* ID_MODEL_FROM_DATABASE=Nexus S (debug) usb:v18D1p4E24* ID_MODEL_FROM_DATABASE=Nexus S (tether) usb:v18D1p4E30* ID_MODEL_FROM_DATABASE=Galaxy Nexus (fastboot) usb:v18D1p4E40* ID_MODEL_FROM_DATABASE=Nexus 7 (fastboot) usb:v18D1p4E41* ID_MODEL_FROM_DATABASE=Nexus 7 (MTP) usb:v18D1p4E42* ID_MODEL_FROM_DATABASE=Nexus 7 (debug) usb:v18D1p4E43* ID_MODEL_FROM_DATABASE=Nexus 7 (PTP) usb:v18D1p4E44* ID_MODEL_FROM_DATABASE=Nexus 7 2012 (PTP) usb:v18D1p4EE0* ID_MODEL_FROM_DATABASE=Nexus 4 (bootloader) usb:v18D1p4EE1* ID_MODEL_FROM_DATABASE=Nexus Device (MTP) usb:v18D1p4EE2* ID_MODEL_FROM_DATABASE=Nexus Device (debug) usb:v18D1p4EE3* ID_MODEL_FROM_DATABASE=Nexus 4/5/7/10 (tether) usb:v18D1p4EE4* ID_MODEL_FROM_DATABASE=Nexus 4/5/7/10 (debug + tether) usb:v18D1p4EE5* ID_MODEL_FROM_DATABASE=Nexus 4 (PTP) usb:v18D1p4EE6* ID_MODEL_FROM_DATABASE=Nexus 4/5 (PTP + debug) usb:v18D1p7102* ID_MODEL_FROM_DATABASE=Toshiba Thrive tablet usb:v18D1pB004* ID_MODEL_FROM_DATABASE=Pandigital / B&N Novel 9" tablet usb:v18D1pD001* ID_MODEL_FROM_DATABASE=Nexus 4 (fastboot) usb:v18D1pD002* ID_MODEL_FROM_DATABASE=Nexus 4 (debug) usb:v18D1pD109* ID_MODEL_FROM_DATABASE=LG G2x MTP usb:v18D1pD10A* ID_MODEL_FROM_DATABASE=LG G2x MTP (debug) usb:v18D5* ID_VENDOR_FROM_DATABASE=Starline International Group Limited usb:v18D9* ID_VENDOR_FROM_DATABASE=Kaba usb:v18D9p01A0* ID_MODEL_FROM_DATABASE=B-Net 91 07 usb:v18DC* ID_VENDOR_FROM_DATABASE=LKC Technologies, Inc. usb:v18DD* ID_VENDOR_FROM_DATABASE=Planon System Solutions Inc. usb:v18DDp1000* ID_MODEL_FROM_DATABASE=DocuPen RC800 usb:v18E3* ID_VENDOR_FROM_DATABASE=Fitipower Integrated Technology Inc usb:v18E3p7102* ID_MODEL_FROM_DATABASE=Multi Card Reader (Internal) usb:v18E3p9101* ID_MODEL_FROM_DATABASE=All-in-1 Card Reader usb:v18E3p9102* ID_MODEL_FROM_DATABASE=Multi Card Reader usb:v18E3p9512* ID_MODEL_FROM_DATABASE=Webcam usb:v18E8* ID_VENDOR_FROM_DATABASE=Qcom usb:v18E8p6144* ID_MODEL_FROM_DATABASE=LR802UA 802.11b Wireless Adapter [ALi M4301AU] usb:v18E8p6196* ID_MODEL_FROM_DATABASE=RT2573 usb:v18E8p6229* ID_MODEL_FROM_DATABASE=RT2573 usb:v18E8p6232* ID_MODEL_FROM_DATABASE=Wireless 802.11g 54Mbps Network Adapter [RTL8187] usb:v18EA* ID_VENDOR_FROM_DATABASE=Matrox Graphics, Inc. usb:v18EAp0002* ID_MODEL_FROM_DATABASE=DualHead2Go [Analog Edition] usb:v18EAp0004* ID_MODEL_FROM_DATABASE=TripleHead2Go [Digital Edition] usb:v18EC* ID_VENDOR_FROM_DATABASE=Arkmicro Technologies Inc. usb:v18ECp3118* ID_MODEL_FROM_DATABASE=USB to IrDA adapter [ARK3116T] usb:v18ECp3188* ID_MODEL_FROM_DATABASE=ARK3188 UVC Webcam usb:v18ECp3299* ID_MODEL_FROM_DATABASE=Webcam Carrefour usb:v18ECp3366* ID_MODEL_FROM_DATABASE=Bresser Biolux NV usb:v18FD* ID_VENDOR_FROM_DATABASE=FineArch Inc. usb:v1908* ID_VENDOR_FROM_DATABASE=GEMBIRD usb:v1908p1320* ID_MODEL_FROM_DATABASE=PhotoFrame PF-15-1 usb:v190D* ID_VENDOR_FROM_DATABASE=Motorola GSG usb:v1914* ID_VENDOR_FROM_DATABASE=Alco Digital Devices Limited usb:v1915* ID_VENDOR_FROM_DATABASE=Nordic Semiconductor ASA usb:v1915p000C* ID_MODEL_FROM_DATABASE=Wireless Desktop nRF24L01 CX-1766 usb:v1915p2233* ID_MODEL_FROM_DATABASE=Linksys WUSB11 v2.8 802.11b Adapter [Atmel AT76C505] usb:v1915p2234* ID_MODEL_FROM_DATABASE=Linksys WUSB54G v1 OEM 802.11g Adapter [Intersil ISL3886] usb:v1915p2235* ID_MODEL_FROM_DATABASE=Linksys WUSB54GP v1 OEM 802.11g Adapter [Intersil ISL3886] usb:v1915p2236* ID_MODEL_FROM_DATABASE=Linksys WUSB11 v3.0 802.11b Adapter [Intersil PRISM 3] usb:v1923* ID_VENDOR_FROM_DATABASE=FitLinxx usb:v1923p0002* ID_MODEL_FROM_DATABASE=Personal SyncPoint usb:v1926* ID_VENDOR_FROM_DATABASE=NextWindow usb:v1926p0003* ID_MODEL_FROM_DATABASE=1900 HID Touchscreen usb:v1926p0006* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0064* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0065* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0066* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0067* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0068* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0069* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0071* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0072* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0073* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0074* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0075* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0076* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0077* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0078* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0079* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p007A* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p007E* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p007F* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0080* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0081* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0082* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0083* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0084* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0085* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0086* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0087* ID_MODEL_FROM_DATABASE=1950 HID Touchscreen usb:v1926p0DC2* ID_MODEL_FROM_DATABASE=HID Touchscreen usb:v192F* ID_VENDOR_FROM_DATABASE=Avago Technologies, Pte. usb:v192Fp0000* ID_MODEL_FROM_DATABASE=Mouse usb:v192Fp0416* ID_MODEL_FROM_DATABASE=ADNS-5700 Optical Mouse Controller (3-button) usb:v192Fp0616* ID_MODEL_FROM_DATABASE=ADNS-5700 Optical Mouse Controller (5-button) usb:v1930* ID_VENDOR_FROM_DATABASE=Shenzhen Xianhe Technology Co., Ltd. usb:v1931* ID_VENDOR_FROM_DATABASE=Ningbo Broad Telecommunication Co., Ltd. usb:v1934* ID_VENDOR_FROM_DATABASE=Feature Integration Technology Inc. (Fintek) usb:v1934p0602* ID_MODEL_FROM_DATABASE=F71610 or F71612 Consumer Infrared Receiver/Transceiver usb:v1934p0702* ID_MODEL_FROM_DATABASE=Integrated Consumer Infrared Receiver/Transceiver usb:v1934p5168* ID_MODEL_FROM_DATABASE=F71610A or F71612A Consumer Infrared Receiver/Transceiver usb:v1941* ID_VENDOR_FROM_DATABASE=Dream Link usb:v1941p8021* ID_MODEL_FROM_DATABASE=WH1080 Weather Station / USB Missile Launcher usb:v1943* ID_VENDOR_FROM_DATABASE=Sensoray Co., Inc. usb:v1943p2250* ID_MODEL_FROM_DATABASE=Model 2250 MPEG and JPEG Capture Card usb:v1943p2253* ID_MODEL_FROM_DATABASE=Model 2253 Audio/Video Codec Card usb:v1943p2255* ID_MODEL_FROM_DATABASE=Model 2255 4 Channel Capture Card usb:v1943p2257* ID_MODEL_FROM_DATABASE=Model 2257 4 Channel Capture Card usb:v1943pA250* ID_MODEL_FROM_DATABASE=Model 2250 MPEG and JPEG Capture Card (cold) usb:v1943pA253* ID_MODEL_FROM_DATABASE=Model 2253 Audio/Video Codec Card (cold) usb:v1949* ID_VENDOR_FROM_DATABASE=Lab126, Inc. usb:v1949p0002* ID_MODEL_FROM_DATABASE=Amazon Kindle usb:v1949p0004* ID_MODEL_FROM_DATABASE=Amazon Kindle 3/4/Paperwhite usb:v1949p0006* ID_MODEL_FROM_DATABASE=Kindle Fire usb:v1949p0008* ID_MODEL_FROM_DATABASE=Amazon Kindle Fire HD 8.9" usb:v194F* ID_VENDOR_FROM_DATABASE=PreSonus Audio Electronics, Inc. usb:v194Fp0101* ID_MODEL_FROM_DATABASE=AudioBox 22 VSL usb:v194Fp0102* ID_MODEL_FROM_DATABASE=AudioBox 44 VSL usb:v194Fp0103* ID_MODEL_FROM_DATABASE=AudioBox 1818 VSL usb:v194Fp0301* ID_MODEL_FROM_DATABASE=AudioBox usb:v1951* ID_VENDOR_FROM_DATABASE=Hyperstone AG usb:v1953* ID_VENDOR_FROM_DATABASE=Ironkey Inc. usb:v1953p0202* ID_MODEL_FROM_DATABASE=S200 2GB Rev. 1 usb:v1954* ID_VENDOR_FROM_DATABASE=Radiient Technologies usb:v195D* ID_VENDOR_FROM_DATABASE=Itron Technology iONE usb:v195Dp7002* ID_MODEL_FROM_DATABASE=Libra-Q11 IR remote usb:v195Dp7006* ID_MODEL_FROM_DATABASE=Libra-Q26 / 1.0 Remote usb:v195Dp7777* ID_MODEL_FROM_DATABASE=Scorpius wireless keyboard usb:v195Dp7779* ID_MODEL_FROM_DATABASE=Scorpius-P20MT usb:v1965* ID_VENDOR_FROM_DATABASE=Uniden Corporation usb:v1965p0016* ID_MODEL_FROM_DATABASE=HomePatrol-1 usb:v1967* ID_VENDOR_FROM_DATABASE=CASIO HITACHI Mobile Communications Co., Ltd. usb:v196B* ID_VENDOR_FROM_DATABASE=Wispro Technology Inc. usb:v1970* ID_VENDOR_FROM_DATABASE=Dane-Elec Corp. USA usb:v1970p0000* ID_MODEL_FROM_DATABASE=Z Mate 16GB usb:v1975* ID_VENDOR_FROM_DATABASE=Dongguan Guneetal Wire & Cable Co., Ltd. usb:v1976* ID_VENDOR_FROM_DATABASE=Chipsbrand Microelectronics (HK) Co., Ltd. usb:v1976p6025* ID_MODEL_FROM_DATABASE=Flash Drive 512 MB usb:v1977* ID_VENDOR_FROM_DATABASE=T-Logic usb:v1977p0111* ID_MODEL_FROM_DATABASE=TL203 MP3 Player and Voice Recorder usb:v197D* ID_VENDOR_FROM_DATABASE=Leuze electronic usb:v197Dp0222* ID_MODEL_FROM_DATABASE=BCL 508i usb:v1989* ID_VENDOR_FROM_DATABASE=Nuconn Technology Corp. usb:v198F* ID_VENDOR_FROM_DATABASE=Beceem Communications Inc. usb:v198Fp0210* ID_MODEL_FROM_DATABASE=BCS200 WiMAX Adapter usb:v198Fp0220* ID_MODEL_FROM_DATABASE=BCSM250 WiMAX Adapter usb:v1990* ID_VENDOR_FROM_DATABASE=Acron Precision Industrial Co., Ltd. usb:v1995* ID_VENDOR_FROM_DATABASE=Trillium Technology Pty. Ltd. usb:v1995p3202* ID_MODEL_FROM_DATABASE=REC-ADPT-USB (recorder) usb:v1995p3203* ID_MODEL_FROM_DATABASE=REC-A-ADPT-USB (recorder) usb:v1996* ID_VENDOR_FROM_DATABASE=PixeLINK usb:v1996p3010* ID_MODEL_FROM_DATABASE=Camera Release 4 usb:v1996p3011* ID_MODEL_FROM_DATABASE=OEM Camera usb:v1996p3012* ID_MODEL_FROM_DATABASE=e-ImageData Corp. ScanPro usb:v199B* ID_VENDOR_FROM_DATABASE=MicroStrain, Inc. usb:v199Bp3065* ID_MODEL_FROM_DATABASE=3DM-GX3-25 Orientation Sensor usb:v199E* ID_VENDOR_FROM_DATABASE=The Imaging Source Europe GmbH usb:v199Ep8101* ID_MODEL_FROM_DATABASE=DFx 21BU04 Camera usb:v199F* ID_VENDOR_FROM_DATABASE=Benica Corporation usb:v19A8* ID_VENDOR_FROM_DATABASE=Biforst Technology Inc. usb:v19AB* ID_VENDOR_FROM_DATABASE=Bodelin usb:v19ABp1000* ID_MODEL_FROM_DATABASE=ProScope HR usb:v19AF* ID_VENDOR_FROM_DATABASE=S Life usb:v19AFp6611* ID_MODEL_FROM_DATABASE=Celestia VoIP Phone usb:v19B2* ID_VENDOR_FROM_DATABASE=Batronix usb:v19B2p0010* ID_MODEL_FROM_DATABASE=BX32 Batupo usb:v19B2p0011* ID_MODEL_FROM_DATABASE=BX32P Barlino usb:v19B2p0012* ID_MODEL_FROM_DATABASE=BX40 Bagero usb:v19B2p0013* ID_MODEL_FROM_DATABASE=BX48 Batego usb:v19B4* ID_VENDOR_FROM_DATABASE=Celestron usb:v19B4p0002* ID_MODEL_FROM_DATABASE=SkyScout Personal Planetarium usb:v19B4p0101* ID_MODEL_FROM_DATABASE=Handheld Digital Microscope 44302 usb:v19B5* ID_VENDOR_FROM_DATABASE=B & W Group usb:v19B6* ID_VENDOR_FROM_DATABASE=Infotech Logistic, LLC usb:v19B9* ID_VENDOR_FROM_DATABASE=Data Robotics usb:v19B9p8D20* ID_MODEL_FROM_DATABASE=Drobo Elite usb:v19C2* ID_VENDOR_FROM_DATABASE=Futuba usb:v19C2p6A11* ID_MODEL_FROM_DATABASE=MDM166A Fluorescent Display usb:v19CA* ID_VENDOR_FROM_DATABASE=Mindtribe usb:v19CAp0001* ID_MODEL_FROM_DATABASE=Sandio 3D HID Mouse usb:v19CF* ID_VENDOR_FROM_DATABASE=Parrot SA usb:v19D2* ID_VENDOR_FROM_DATABASE=ZTE WCDMA Technologies MSM usb:v19D2p0001* ID_MODEL_FROM_DATABASE=CDMA Wireless Modem usb:v19D2p0002* ID_MODEL_FROM_DATABASE=MF632/ONDA ET502HS/MT505UP usb:v19D2p0007* ID_MODEL_FROM_DATABASE=TU25 WiMAX Adapter [Beceem BCS200] usb:v19D2p0031* ID_MODEL_FROM_DATABASE=MF110/MF627/MF636 usb:v19D2p0063* ID_MODEL_FROM_DATABASE=K3565-Z HSDPA usb:v19D2p0064* ID_MODEL_FROM_DATABASE=MF627 AU usb:v19D2p0083* ID_MODEL_FROM_DATABASE=MF190 usb:v19D2p0103* ID_MODEL_FROM_DATABASE=MF112 usb:v19D2p0104* ID_MODEL_FROM_DATABASE=K4505-Z usb:v19D2p0146* ID_MODEL_FROM_DATABASE=MF 195E (HSPA+ Modem) usb:v19D2p0167* ID_MODEL_FROM_DATABASE=MF820 4G LTE usb:v19D2p0172* ID_MODEL_FROM_DATABASE=AX226 WIMAX MODEM (After Modeswitch) usb:v19D2p0325* ID_MODEL_FROM_DATABASE=LTE4G O2 ZTE MF821D LTE/UMTS/GSM Modem/Networkcard usb:v19D2p0326* ID_MODEL_FROM_DATABASE=LTE4G O2 ZTE MF821D LTE/UMTS/GSM Modem/Networkcard usb:v19D2p1008* ID_MODEL_FROM_DATABASE=K3570-Z usb:v19D2p1010* ID_MODEL_FROM_DATABASE=K3571-Z usb:v19D2p1017* ID_MODEL_FROM_DATABASE=K5006-Z vodafone LTE/UMTS/GSM Modem/Networkcard usb:v19D2p1018* ID_MODEL_FROM_DATABASE=K5006-Z vodafone LTE/UMTS/GSM Modem/Networkcard usb:v19D2p1203* ID_MODEL_FROM_DATABASE=MF691 [ T-Mobile webConnect Rocket 2.0] usb:v19D2p1217* ID_MODEL_FROM_DATABASE=MF652 usb:v19D2p1218* ID_MODEL_FROM_DATABASE=MF652 usb:v19D2p2000* ID_MODEL_FROM_DATABASE=MF627/MF628/MF628+/MF636+ HSDPA/HSUPA usb:v19D2pFFF2* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) usb:v19D2pFFF3* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem usb:v19DB* ID_VENDOR_FROM_DATABASE=KFI Printers usb:v19DBp02F1* ID_MODEL_FROM_DATABASE=NAUT324C usb:v19E1* ID_VENDOR_FROM_DATABASE=WeiDuan Electronic Accessory (S.Z.) Co., Ltd. usb:v19E8* ID_VENDOR_FROM_DATABASE=Industrial Technology Research Institute usb:v19EF* ID_VENDOR_FROM_DATABASE=Pak Heng Technology (Shenzhen) Co., Ltd. usb:v19F7* ID_VENDOR_FROM_DATABASE=RODE Microphones usb:v19F7p0001* ID_MODEL_FROM_DATABASE=Podcaster usb:v19FA* ID_VENDOR_FROM_DATABASE=Gampaq Co.Ltd usb:v19FAp0703* ID_MODEL_FROM_DATABASE=Steering Wheel usb:v19FF* ID_VENDOR_FROM_DATABASE=Dynex usb:v19FFp0102* ID_MODEL_FROM_DATABASE=1.3MP Webcam usb:v19FFp0201* ID_MODEL_FROM_DATABASE=Rocketfish Wireless 2.4G Laser Mouse usb:v19FFp0238* ID_MODEL_FROM_DATABASE=DX-WRM1401 Mouse usb:v1A08* ID_VENDOR_FROM_DATABASE=Bellwood International, Inc. usb:v1A0A* ID_VENDOR_FROM_DATABASE=USB-IF non-workshop usb:v1A0ApBADD* ID_MODEL_FROM_DATABASE=USB OTG Compliance test device usb:v1A12* ID_VENDOR_FROM_DATABASE=KES Co., Ltd. usb:v1A1D* ID_VENDOR_FROM_DATABASE=Veho usb:v1A1Dp0407* ID_MODEL_FROM_DATABASE=Mimi WiFi speakers usb:v1A25* ID_VENDOR_FROM_DATABASE=Amphenol East Asia Ltd. usb:v1A2A* ID_VENDOR_FROM_DATABASE=Seagate Branded Solutions usb:v1A2C* ID_VENDOR_FROM_DATABASE=China Resource Semico Co., Ltd usb:v1A2Cp0021* ID_MODEL_FROM_DATABASE=Keyboard usb:v1A2Cp0024* ID_MODEL_FROM_DATABASE=Multimedia Keyboard usb:v1A32* ID_VENDOR_FROM_DATABASE=Quanta Microsystems, Inc. usb:v1A32p0304* ID_MODEL_FROM_DATABASE=802.11n Wireless LAN Card usb:v1A34* ID_VENDOR_FROM_DATABASE=ACRUX usb:v1A34p0802* ID_MODEL_FROM_DATABASE=Gamepad usb:v1A36* ID_VENDOR_FROM_DATABASE=Biwin Technology Ltd. usb:v1A40* ID_VENDOR_FROM_DATABASE=Terminus Technology Inc. usb:v1A40p0101* ID_MODEL_FROM_DATABASE=Hub usb:v1A40p0201* ID_MODEL_FROM_DATABASE=FE 2.1 7-port Hub usb:v1A41* ID_VENDOR_FROM_DATABASE=Action Electronics Co., Ltd. usb:v1A44* ID_VENDOR_FROM_DATABASE=VASCO Data Security International usb:v1A44p0001* ID_MODEL_FROM_DATABASE=Digipass 905 SmartCard Reader usb:v1A4A* ID_VENDOR_FROM_DATABASE=Silicon Image usb:v1A4B* ID_VENDOR_FROM_DATABASE=SafeBoot International B.V. usb:v1A5A* ID_VENDOR_FROM_DATABASE=Tandberg Data usb:v1A61* ID_VENDOR_FROM_DATABASE=Abbott Diabetes Care usb:v1A61p3410* ID_MODEL_FROM_DATABASE=CoPilot System Cable usb:v1A6A* ID_VENDOR_FROM_DATABASE=Spansion Inc. usb:v1A6D* ID_VENDOR_FROM_DATABASE=SamYoung Electronics Co., Ltd usb:v1A6E* ID_VENDOR_FROM_DATABASE=Global Unichip Corp. usb:v1A6F* ID_VENDOR_FROM_DATABASE=Sagem Orga GmbH usb:v1A72* ID_VENDOR_FROM_DATABASE=Physik Instrumente usb:v1A72p1008* ID_MODEL_FROM_DATABASE=E-861 PiezoWalk NEXACT Controller usb:v1A79* ID_VENDOR_FROM_DATABASE=Bayer Health Care LLC usb:v1A79p6002* ID_MODEL_FROM_DATABASE=Contour usb:v1A79p7410* ID_MODEL_FROM_DATABASE=Contour Next usb:v1A7B* ID_VENDOR_FROM_DATABASE=Lumberg Connect GmbH & Co. KG usb:v1A7C* ID_VENDOR_FROM_DATABASE=Evoluent usb:v1A7Cp0068* ID_MODEL_FROM_DATABASE=VerticalMouse 3 usb:v1A7Cp0168* ID_MODEL_FROM_DATABASE=VerticalMouse 3 Wireless usb:v1A7Cp0191* ID_MODEL_FROM_DATABASE=VerticalMouse 4 usb:v1A81* ID_VENDOR_FROM_DATABASE=Holtek Semiconductor, Inc. usb:v1A81p2203* ID_MODEL_FROM_DATABASE=Laser Gaming mouse usb:v1A81p2204* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v1A81p2205* ID_MODEL_FROM_DATABASE=Laser Mouse usb:v1A86* ID_VENDOR_FROM_DATABASE=QinHeng Electronics usb:v1A86p5512* ID_MODEL_FROM_DATABASE=CH341 in EPP/MEM/I2C mode, EPP/I2C adapter usb:v1A86p5523* ID_MODEL_FROM_DATABASE=CH341 in serial mode, usb to serial port converter usb:v1A86p5584* ID_MODEL_FROM_DATABASE=CH341 in parallel mode, usb to printer port converter usb:v1A86p7523* ID_MODEL_FROM_DATABASE=HL-340 USB-Serial adapter usb:v1A86p752D* ID_MODEL_FROM_DATABASE=CH345 MIDI adapter usb:v1A86p7584* ID_MODEL_FROM_DATABASE=CH340S usb:v1A86pE008* ID_MODEL_FROM_DATABASE=HID-based serial adapater usb:v1A89* ID_VENDOR_FROM_DATABASE=Dynalith Systems Co., Ltd. usb:v1A8B* ID_VENDOR_FROM_DATABASE=SGS Taiwan Ltd. usb:v1A8D* ID_VENDOR_FROM_DATABASE=BandRich, Inc. usb:v1A8Dp1002* ID_MODEL_FROM_DATABASE=BandLuxe 3.5G HSDPA Adapter usb:v1A8Dp1009* ID_MODEL_FROM_DATABASE=BandLuxe 3.5G HSPA Adapter usb:v1A8Dp100D* ID_MODEL_FROM_DATABASE=4G LTE adapter usb:v1A98* ID_VENDOR_FROM_DATABASE=Leica Camera AG usb:v1AA4* ID_VENDOR_FROM_DATABASE=Data Drive Thru, Inc. usb:v1AA5* ID_VENDOR_FROM_DATABASE=UBeacon Technologies, Inc. usb:v1AA6* ID_VENDOR_FROM_DATABASE=eFortune Technology Corp. usb:v1AAD* ID_VENDOR_FROM_DATABASE=KeeTouch usb:v1AADp0001* ID_MODEL_FROM_DATABASE=Touchscreen usb:v1AB1* ID_VENDOR_FROM_DATABASE=Rigol Technologies usb:v1AB1p0588* ID_MODEL_FROM_DATABASE=DS1000 SERIES usb:v1ACB* ID_VENDOR_FROM_DATABASE=Salcomp Plc usb:v1ACC* ID_VENDOR_FROM_DATABASE=Midiplus Co, Ltd. usb:v1ACCp0103* ID_MODEL_FROM_DATABASE=AudioLink plus 4x4 2.9.28 usb:v1AD1* ID_VENDOR_FROM_DATABASE=Desay Wire Co., Ltd. usb:v1AD4* ID_VENDOR_FROM_DATABASE=APS usb:v1AD4p0002* ID_MODEL_FROM_DATABASE=KM290-HRS usb:v1ADB* ID_VENDOR_FROM_DATABASE=SEL C662 Serial Cable usb:v1AE4* ID_VENDOR_FROM_DATABASE=ic-design Reinhard Gottinger GmbH usb:v1AE7* ID_VENDOR_FROM_DATABASE=X-TENSIONS usb:v1AE7p0381* ID_MODEL_FROM_DATABASE=VS-DVB-T 380U (af9015 based) usb:v1AE7p2001* ID_MODEL_FROM_DATABASE=SpeedLink Snappy Mic webcam (SL-6825-SBK) usb:v1AE7p9003* ID_MODEL_FROM_DATABASE=SpeedLink Vicious And Devine Laplace webcam, white (VD-1504-SWT) usb:v1AE7p9004* ID_MODEL_FROM_DATABASE=SpeedLink Vicious And Devine Laplace webcam, black (VD-1504-SBK) usb:v1AED* ID_VENDOR_FROM_DATABASE=High Top Precision Electronic Co., Ltd. usb:v1AEF* ID_VENDOR_FROM_DATABASE=Conntech Electronic (Suzhou) Corporation usb:v1AF1* ID_VENDOR_FROM_DATABASE=Connect One Ltd. usb:v1AFE* ID_VENDOR_FROM_DATABASE=A. Eberle GmbH & Co. KG usb:v1AFEp0001* ID_MODEL_FROM_DATABASE=PQ Box 100 usb:v1B04* ID_VENDOR_FROM_DATABASE=Meilhaus Electronic GmbH usb:v1B04p0630* ID_MODEL_FROM_DATABASE=ME-630 usb:v1B04p0940* ID_MODEL_FROM_DATABASE=ME-94 usb:v1B04p0950* ID_MODEL_FROM_DATABASE=ME-95 usb:v1B04p0960* ID_MODEL_FROM_DATABASE=ME-96 usb:v1B04p1000* ID_MODEL_FROM_DATABASE=ME-1000 usb:v1B04p100A* ID_MODEL_FROM_DATABASE=ME-1000 usb:v1B04p100B* ID_MODEL_FROM_DATABASE=ME-1000 usb:v1B04p1400* ID_MODEL_FROM_DATABASE=ME-1400 usb:v1B04p140A* ID_MODEL_FROM_DATABASE=ME-1400A usb:v1B04p140B* ID_MODEL_FROM_DATABASE=ME-1400B usb:v1B04p140C* ID_MODEL_FROM_DATABASE=ME-1400C usb:v1B04p140D* ID_MODEL_FROM_DATABASE=ME-1400D usb:v1B04p140E* ID_MODEL_FROM_DATABASE=ME-1400E usb:v1B04p14EA* ID_MODEL_FROM_DATABASE=ME-1400EA usb:v1B04p14EB* ID_MODEL_FROM_DATABASE=ME-1400EB usb:v1B04p1604* ID_MODEL_FROM_DATABASE=ME-1600/4U usb:v1B04p1608* ID_MODEL_FROM_DATABASE=ME-1600/8U usb:v1B04p160C* ID_MODEL_FROM_DATABASE=ME-1600/12U usb:v1B04p160F* ID_MODEL_FROM_DATABASE=ME-1600/16U usb:v1B04p168F* ID_MODEL_FROM_DATABASE=ME-1600/16U8I usb:v1B04p4610* ID_MODEL_FROM_DATABASE=ME-4610 usb:v1B04p4650* ID_MODEL_FROM_DATABASE=ME-4650 usb:v1B04p4660* ID_MODEL_FROM_DATABASE=ME-4660 usb:v1B04p4661* ID_MODEL_FROM_DATABASE=ME-4660I usb:v1B04p4662* ID_MODEL_FROM_DATABASE=ME-4660 usb:v1B04p4663* ID_MODEL_FROM_DATABASE=ME-4660I usb:v1B04p4670* ID_MODEL_FROM_DATABASE=ME-4670 usb:v1B04p4671* ID_MODEL_FROM_DATABASE=ME-4670I usb:v1B04p4672* ID_MODEL_FROM_DATABASE=ME-4670S usb:v1B04p4673* ID_MODEL_FROM_DATABASE=ME-4670IS usb:v1B04p4680* ID_MODEL_FROM_DATABASE=ME-4680 usb:v1B04p4681* ID_MODEL_FROM_DATABASE=ME-4680I usb:v1B04p4682* ID_MODEL_FROM_DATABASE=ME-4680S usb:v1B04p4683* ID_MODEL_FROM_DATABASE=ME-4680IS usb:v1B04p6004* ID_MODEL_FROM_DATABASE=ME-6000/4 usb:v1B04p6008* ID_MODEL_FROM_DATABASE=ME-6000/8 usb:v1B04p600F* ID_MODEL_FROM_DATABASE=ME-6000/16 usb:v1B04p6014* ID_MODEL_FROM_DATABASE=ME-6000I/4 usb:v1B04p6018* ID_MODEL_FROM_DATABASE=ME-6000I/8 usb:v1B04p601F* ID_MODEL_FROM_DATABASE=ME-6000I/16 usb:v1B04p6034* ID_MODEL_FROM_DATABASE=ME-6000ISLE/4 usb:v1B04p6038* ID_MODEL_FROM_DATABASE=ME-6000ISLE/8 usb:v1B04p603F* ID_MODEL_FROM_DATABASE=ME-6000ISLE/16 usb:v1B04p6044* ID_MODEL_FROM_DATABASE=ME-6000/4/DIO usb:v1B04p6048* ID_MODEL_FROM_DATABASE=ME-6000/8/DIO usb:v1B04p604F* ID_MODEL_FROM_DATABASE=ME-6000/16/DIO usb:v1B04p6054* ID_MODEL_FROM_DATABASE=ME-6000I/4/DIO usb:v1B04p6058* ID_MODEL_FROM_DATABASE=ME-6000I/8/DIO usb:v1B04p605F* ID_MODEL_FROM_DATABASE=ME-6000I/16/DIO usb:v1B04p6074* ID_MODEL_FROM_DATABASE=ME-6000ISLE/4/DIO usb:v1B04p6078* ID_MODEL_FROM_DATABASE=ME-6000ISLE/8/DIO usb:v1B04p607F* ID_MODEL_FROM_DATABASE=ME-6000ISLE/16/DIO usb:v1B04p6104* ID_MODEL_FROM_DATABASE=ME-6100/4 usb:v1B04p6108* ID_MODEL_FROM_DATABASE=ME-6100/8 usb:v1B04p610F* ID_MODEL_FROM_DATABASE=ME-6100/16 usb:v1B04p6114* ID_MODEL_FROM_DATABASE=ME-6100I/4 usb:v1B04p6118* ID_MODEL_FROM_DATABASE=ME-6100I/8 usb:v1B04p611F* ID_MODEL_FROM_DATABASE=ME-6100I/16 usb:v1B04p6134* ID_MODEL_FROM_DATABASE=ME-6100ISLE/4 usb:v1B04p6138* ID_MODEL_FROM_DATABASE=ME-6100ISLE/8 usb:v1B04p613F* ID_MODEL_FROM_DATABASE=ME-6100ISLE/16 usb:v1B04p6144* ID_MODEL_FROM_DATABASE=ME-6100/4/DIO usb:v1B04p6148* ID_MODEL_FROM_DATABASE=ME-6100/8/DIO usb:v1B04p614F* ID_MODEL_FROM_DATABASE=ME-6100/16/DIO usb:v1B04p6154* ID_MODEL_FROM_DATABASE=ME-6100I/4/DIO usb:v1B04p6158* ID_MODEL_FROM_DATABASE=ME-6100I/8/DIO usb:v1B04p615F* ID_MODEL_FROM_DATABASE=ME-6100I/16/DIO usb:v1B04p6174* ID_MODEL_FROM_DATABASE=ME-6100ISLE/4/DIO usb:v1B04p6178* ID_MODEL_FROM_DATABASE=ME-6100ISLE/8/DIO usb:v1B04p617F* ID_MODEL_FROM_DATABASE=ME-6100ISLE/16/DIO usb:v1B04p6259* ID_MODEL_FROM_DATABASE=ME-6200I/9/DIO usb:v1B04p6359* ID_MODEL_FROM_DATABASE=ME-6300I/9/DIO usb:v1B04p810A* ID_MODEL_FROM_DATABASE=ME-8100A usb:v1B04p810B* ID_MODEL_FROM_DATABASE=ME-8100B usb:v1B04p820A* ID_MODEL_FROM_DATABASE=ME-8200A usb:v1B04p820B* ID_MODEL_FROM_DATABASE=ME-8200B usb:v1B0E* ID_VENDOR_FROM_DATABASE=BLUTRONICS S.r.l. usb:v1B0Ep1078* ID_MODEL_FROM_DATABASE=BLUDRIVE II CCID usb:v1B0Ep1079* ID_MODEL_FROM_DATABASE=BLUDRIVE II CCID usb:v1B0Ep1080* ID_MODEL_FROM_DATABASE=WRITECHIP II CCID usb:v1B1C* ID_VENDOR_FROM_DATABASE=Corsair usb:v1B1Cp0890* ID_MODEL_FROM_DATABASE=Flash Padlock usb:v1B1Cp0A00* ID_MODEL_FROM_DATABASE=SP2500 Speakers usb:v1B1Cp0A60* ID_MODEL_FROM_DATABASE=Vengeance K60 Keyboard usb:v1B1Cp1A01* ID_MODEL_FROM_DATABASE=Flash Voyager GT usb:v1B1Cp1A0A* ID_MODEL_FROM_DATABASE=Survivor Stealth Flash Drive usb:v1B1Cp1A90* ID_MODEL_FROM_DATABASE=Flash Voyager GT usb:v1B20* ID_VENDOR_FROM_DATABASE=MStar Semiconductor, Inc. usb:v1B22* ID_VENDOR_FROM_DATABASE=WiLinx Corp. usb:v1B26* ID_VENDOR_FROM_DATABASE=Cellex Power Products, Inc. usb:v1B27* ID_VENDOR_FROM_DATABASE=Current Electronics Inc. usb:v1B28* ID_VENDOR_FROM_DATABASE=NAVIsis Inc. usb:v1B32* ID_VENDOR_FROM_DATABASE=Ugobe Life Forms, Inc. usb:v1B32p0064* ID_MODEL_FROM_DATABASE=Pleo robotic dinosaur usb:v1B36* ID_VENDOR_FROM_DATABASE=ViXS Systems, Inc. usb:v1B3B* ID_VENDOR_FROM_DATABASE=iPassion Technology Inc. usb:v1B3Bp2933* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2935* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2936* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2937* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2938* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2939* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2950* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2951* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2952* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2953* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2955* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2956* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2957* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2958* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2959* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2960* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2961* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2962* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2963* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2965* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2966* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2967* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2968* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3Bp2969* ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller usb:v1B3F* ID_VENDOR_FROM_DATABASE=Generalplus Technology Inc. usb:v1B3Fp0C52* ID_MODEL_FROM_DATABASE=808 Camera #9 (mass storage mode) usb:v1B3Fp2002* ID_MODEL_FROM_DATABASE=808 Camera #9 (web-cam mode) usb:v1B47* ID_VENDOR_FROM_DATABASE=Energizer Holdings, Inc. usb:v1B47p0001* ID_MODEL_FROM_DATABASE=CHUSB Duo Charger (NiMH AA/AAA USB smart charger) usb:v1B48* ID_VENDOR_FROM_DATABASE=Plastron Precision Co., Ltd. usb:v1B52* ID_VENDOR_FROM_DATABASE=ARH Inc. usb:v1B52p2101* ID_MODEL_FROM_DATABASE=FXMC Neural Network Controller usb:v1B52p2102* ID_MODEL_FROM_DATABASE=FXMC Neural Network Controller V2 usb:v1B52p2103* ID_MODEL_FROM_DATABASE=FXMC Neural Network Controller V3 usb:v1B52p4101* ID_MODEL_FROM_DATABASE=Passport Reader CLR device usb:v1B52p4201* ID_MODEL_FROM_DATABASE=Passport Reader PRM device usb:v1B52p4202* ID_MODEL_FROM_DATABASE=Passport Reader PRM extension device usb:v1B52p4203* ID_MODEL_FROM_DATABASE=Passport Reader PRM DSP device usb:v1B52p4204* ID_MODEL_FROM_DATABASE=Passport Reader PRMC device usb:v1B52p4205* ID_MODEL_FROM_DATABASE=Passport Reader CSHR device usb:v1B52p4206* ID_MODEL_FROM_DATABASE=Passport Reader PRMC V2 device usb:v1B52p4301* ID_MODEL_FROM_DATABASE=Passport Reader MRZ device usb:v1B52p4302* ID_MODEL_FROM_DATABASE=Passport Reader MRZ DSP device usb:v1B52p4303* ID_MODEL_FROM_DATABASE=Passport Reader CSLR device usb:v1B52p4401* ID_MODEL_FROM_DATABASE=Card Reader usb:v1B52p4501* ID_MODEL_FROM_DATABASE=Passport Reader RFID device usb:v1B52p4502* ID_MODEL_FROM_DATABASE=Passport Reader RFID AIG device usb:v1B52p6101* ID_MODEL_FROM_DATABASE=Neural Network Controller usb:v1B52p6202* ID_MODEL_FROM_DATABASE=Fingerprint Reader device usb:v1B52p6203* ID_MODEL_FROM_DATABASE=Fingerprint Scanner device usb:v1B52p8101* ID_MODEL_FROM_DATABASE=Camera V1 usb:v1B52p8102* ID_MODEL_FROM_DATABASE=Recovery / Camera V2 usb:v1B52p8103* ID_MODEL_FROM_DATABASE=Camera V3 usb:v1B59* ID_VENDOR_FROM_DATABASE=K.S. Terminals Inc. usb:v1B5A* ID_VENDOR_FROM_DATABASE=Chao Zhou Kai Yuan Electric Co., Ltd. usb:v1B65* ID_VENDOR_FROM_DATABASE=The Hong Kong Standards and Testing Centre Ltd. usb:v1B71* ID_VENDOR_FROM_DATABASE=Fushicai usb:v1B71p3002* ID_MODEL_FROM_DATABASE=USBTV007 Video Grabber [EasyCAP] usb:v1B72* ID_VENDOR_FROM_DATABASE=ATERGI TECHNOLOGY CO., LTD. usb:v1B73* ID_VENDOR_FROM_DATABASE=Fresco Logic usb:v1B73p1000* ID_MODEL_FROM_DATABASE=xHC1 Controller usb:v1B75* ID_VENDOR_FROM_DATABASE=Ovislink Corp. usb:v1B75p3072* ID_MODEL_FROM_DATABASE=AirLive WN-360USB adapter usb:v1B75p8171* ID_MODEL_FROM_DATABASE=WN-370USB 802.11bgn Wireless Adapter [Realtek RTL8188SU] usb:v1B75p8187* ID_MODEL_FROM_DATABASE=AirLive WL-1600USB 802.11g Adapter [Realtek RTL8187L] usb:v1B75p9170* ID_MODEL_FROM_DATABASE=AirLive X.USB 802.11abgn [Atheros AR9170+AR9104] usb:v1B75pA200* ID_MODEL_FROM_DATABASE=AirLive WN-200USB wireless 11b/g/n dongle usb:v1B76* ID_VENDOR_FROM_DATABASE=Legend Silicon Corp. usb:v1B80* ID_VENDOR_FROM_DATABASE=Afatech usb:v1B80pC810* ID_MODEL_FROM_DATABASE=MC810 [af9015] usb:v1B80pD393* ID_MODEL_FROM_DATABASE=DVB-T receiver [RTL2832U] usb:v1B80pD396* ID_MODEL_FROM_DATABASE=UB396-T [RTL2832U] usb:v1B80pD397* ID_MODEL_FROM_DATABASE=DVB-T receiver [RTL2832U] usb:v1B80pD398* ID_MODEL_FROM_DATABASE=DVB-T receiver [RTL2832U] usb:v1B80pD700* ID_MODEL_FROM_DATABASE=FM Radio SnapMusic Mobile 700 (FM700) usb:v1B80pE297* ID_MODEL_FROM_DATABASE=Conceptronic DVB-T CTVDIGRCU V3.0 usb:v1B80pE383* ID_MODEL_FROM_DATABASE=DVB-T UB383-T [af9015] usb:v1B80pE385* ID_MODEL_FROM_DATABASE=DVB-T UB385-T [af9015] usb:v1B80pE386* ID_MODEL_FROM_DATABASE=DVB-T UB385-T [af9015] usb:v1B80pE399* ID_MODEL_FROM_DATABASE=DVB-T KWorld PlusTV 399U [af9015] usb:v1B80pE39A* ID_MODEL_FROM_DATABASE=DVB-T395U [af9015] usb:v1B80pE39B* ID_MODEL_FROM_DATABASE=DVB-T395U [af9015] usb:v1B80pE401* ID_MODEL_FROM_DATABASE=Sveon STV22 DVB-T [af9015] usb:v1B80pE409* ID_MODEL_FROM_DATABASE=IT9137FN Dual DVB-T [KWorld UB499-2T] usb:v1B86* ID_VENDOR_FROM_DATABASE=Dongguan Guanshang Electronics Co., Ltd. usb:v1B88* ID_VENDOR_FROM_DATABASE=ShenMing Electron (Dong Guan) Co., Ltd. usb:v1B8C* ID_VENDOR_FROM_DATABASE=Altium Limited usb:v1B8D* ID_VENDOR_FROM_DATABASE=e-MOVE Technology Co., Ltd. usb:v1B8E* ID_VENDOR_FROM_DATABASE=Amlogic, Inc. usb:v1B8F* ID_VENDOR_FROM_DATABASE=MA LABS, Inc. usb:v1B96* ID_VENDOR_FROM_DATABASE=N-Trig usb:v1B96p0001* ID_MODEL_FROM_DATABASE=Duosense Transparent Electromagnetic Digitizer usb:v1B98* ID_VENDOR_FROM_DATABASE=YMax Communications Corp. usb:v1B99* ID_VENDOR_FROM_DATABASE=Shenzhen Yuanchuan Electronic usb:v1BA1* ID_VENDOR_FROM_DATABASE=JINQ CHERN ENTERPRISE CO., LTD. usb:v1BA2* ID_VENDOR_FROM_DATABASE=Lite Metals & Plastic (Shenzhen) Co., Ltd. usb:v1BA4* ID_VENDOR_FROM_DATABASE=Ember Corporation usb:v1BA4p0001* ID_MODEL_FROM_DATABASE=InSight USB Link usb:v1BA6* ID_VENDOR_FROM_DATABASE=Abilis Systems usb:v1BA8* ID_VENDOR_FROM_DATABASE=China Telecommunication Technology Labs usb:v1BAD* ID_VENDOR_FROM_DATABASE=Harmonix Music usb:v1BADp0002* ID_MODEL_FROM_DATABASE=Guitar for Xbox 360 usb:v1BADp0003* ID_MODEL_FROM_DATABASE=Drum Kit for Xbox 360 usb:v1BAE* ID_VENDOR_FROM_DATABASE=Vuzix Corporation usb:v1BAEp0002* ID_MODEL_FROM_DATABASE=VR920 Immersive Eyewear usb:v1BBB* ID_VENDOR_FROM_DATABASE=T & A Mobile Phones usb:v1BBBp011E* ID_MODEL_FROM_DATABASE=Alcatel One Touch L100V / Telekom Speedstick LTE II usb:v1BBBpF017* ID_MODEL_FROM_DATABASE=Alcatel One Touch L100V / Telekom Speedstick LTE II usb:v1BC4* ID_VENDOR_FROM_DATABASE=Ford Motor Co. usb:v1BC5* ID_VENDOR_FROM_DATABASE=AVIXE Technology (China) Ltd. usb:v1BC7* ID_VENDOR_FROM_DATABASE=Telit Wireless Solutions usb:v1BC7p0020* ID_MODEL_FROM_DATABASE=HE863 usb:v1BC7p0021* ID_MODEL_FROM_DATABASE=HE910 usb:v1BC7p0023* ID_MODEL_FROM_DATABASE=HE910-D ECM usb:v1BC7p1003* ID_MODEL_FROM_DATABASE=UC864-E usb:v1BC7p1004* ID_MODEL_FROM_DATABASE=UC864-G usb:v1BC7p1005* ID_MODEL_FROM_DATABASE=CC864-DUAL usb:v1BC7p1006* ID_MODEL_FROM_DATABASE=CC864-SINGLE usb:v1BC7p1010* ID_MODEL_FROM_DATABASE=DE910-DUAL usb:v1BC7p1011* ID_MODEL_FROM_DATABASE=CE910-DUAL usb:v1BC7p1200* ID_MODEL_FROM_DATABASE=LE920 usb:v1BCE* ID_VENDOR_FROM_DATABASE=Contac Cable Industrial Limited usb:v1BCF* ID_VENDOR_FROM_DATABASE=Sunplus Innovation Technology Inc. usb:v1BCFp0005* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v1BCFp0007* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v1BCFp053A* ID_MODEL_FROM_DATABASE=Targa Silvercrest OMC807-C optische Funkmaus usb:v1BCFp05C5* ID_MODEL_FROM_DATABASE=SPRF2413A [2.4GHz Wireless Keyboard/Mouse Receiver] usb:v1BCFp05CF* ID_MODEL_FROM_DATABASE=Micro keyboard & mouse receiver usb:v1BCFp0C31* ID_MODEL_FROM_DATABASE=SPIF30x Serial-ATA bridge usb:v1BCFp2880* ID_MODEL_FROM_DATABASE=Dell HD Webcam usb:v1BCFp2885* ID_MODEL_FROM_DATABASE=ASUS Webcam usb:v1BCFp2888* ID_MODEL_FROM_DATABASE=HP Universal Camera usb:v1BCFp28A2* ID_MODEL_FROM_DATABASE=Dell Integrated Webcam usb:v1BCFp28A6* ID_MODEL_FROM_DATABASE=DELL XPS Integrated Webcam usb:v1BCFp28AE* ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam HD usb:v1BCFp28BD* ID_MODEL_FROM_DATABASE=Dell Integrated HD Webcam usb:v1BCFp2985* ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam HD usb:v1BCFp2B83* ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam FHD usb:v1BD0* ID_VENDOR_FROM_DATABASE=Hangzhou Riyue Electronic Co., Ltd. usb:v1BD5* ID_VENDOR_FROM_DATABASE=BG Systems, Inc. usb:v1BDE* ID_VENDOR_FROM_DATABASE=P-TWO INDUSTRIES, INC. usb:v1BEF* ID_VENDOR_FROM_DATABASE=Shenzhen Tongyuan Network-Communication Cables Co., Ltd usb:v1BF0* ID_VENDOR_FROM_DATABASE=RealVision Inc. usb:v1BF5* ID_VENDOR_FROM_DATABASE=Extranet Systems Inc. usb:v1BF6* ID_VENDOR_FROM_DATABASE=Orient Semiconductor Electronics, Ltd. usb:v1BFD* ID_VENDOR_FROM_DATABASE=TouchPack usb:v1BFDp1268* ID_MODEL_FROM_DATABASE=Touch Screen usb:v1BFDp1368* ID_MODEL_FROM_DATABASE=Touch Screen usb:v1BFDp1568* ID_MODEL_FROM_DATABASE=Capacitive Touch Screen usb:v1BFDp1668* ID_MODEL_FROM_DATABASE=IR Touch Screen usb:v1BFDp1688* ID_MODEL_FROM_DATABASE=Resistive Touch Screen usb:v1BFDp2968* ID_MODEL_FROM_DATABASE=Touch Screen usb:v1BFDp5968* ID_MODEL_FROM_DATABASE=Touch Screen usb:v1BFDp6968* ID_MODEL_FROM_DATABASE=Touch Screen usb:v1C02* ID_VENDOR_FROM_DATABASE=Kreton Corporation usb:v1C04* ID_VENDOR_FROM_DATABASE=QNAP System Inc. usb:v1C0C* ID_VENDOR_FROM_DATABASE=Ionics EMS, Inc. usb:v1C0Cp0102* ID_MODEL_FROM_DATABASE=Plug Computer usb:v1C0D* ID_VENDOR_FROM_DATABASE=Relm Wireless usb:v1C10* ID_VENDOR_FROM_DATABASE=Lanterra Industrial Co., Ltd. usb:v1C13* ID_VENDOR_FROM_DATABASE=ALECTRONIC LIMITED usb:v1C1A* ID_VENDOR_FROM_DATABASE=Datel Electronics Ltd. usb:v1C1B* ID_VENDOR_FROM_DATABASE=Volkswagen of America, Inc. usb:v1C1F* ID_VENDOR_FROM_DATABASE=Goldvish S.A. usb:v1C20* ID_VENDOR_FROM_DATABASE=Fuji Electric Device Technology Co., Ltd. usb:v1C21* ID_VENDOR_FROM_DATABASE=ADDMM LLC usb:v1C22* ID_VENDOR_FROM_DATABASE=ZHONGSHAN CHIANG YU ELECTRIC CO., LTD. usb:v1C26* ID_VENDOR_FROM_DATABASE=Shanghai Haiying Electronics Co., Ltd. usb:v1C27* ID_VENDOR_FROM_DATABASE=HuiYang D & S Cable Co., Ltd. usb:v1C29* ID_VENDOR_FROM_DATABASE=Elster GmbH usb:v1C29p0001* ID_MODEL_FROM_DATABASE=ExMFE5 Simulator usb:v1C29p10FC* ID_MODEL_FROM_DATABASE=enCore device usb:v1C31* ID_VENDOR_FROM_DATABASE=LS Cable Ltd. usb:v1C34* ID_VENDOR_FROM_DATABASE=SpringCard usb:v1C34p7241* ID_MODEL_FROM_DATABASE=Prox'N'Roll RFID Scanner usb:v1C37* ID_VENDOR_FROM_DATABASE=Authorizer Technologies, Inc. usb:v1C3D* ID_VENDOR_FROM_DATABASE=NONIN MEDICAL INC. usb:v1C3E* ID_VENDOR_FROM_DATABASE=Wep Peripherals usb:v1C40* ID_VENDOR_FROM_DATABASE=EZPrototypes usb:v1C40p0533* ID_MODEL_FROM_DATABASE=TiltStick usb:v1C40p0534* ID_MODEL_FROM_DATABASE=i2c-tiny-usb interface usb:v1C40p0535* ID_MODEL_FROM_DATABASE=glcd2usb interface usb:v1C40p0536* ID_MODEL_FROM_DATABASE=Swiss ColorPAL usb:v1C49* ID_VENDOR_FROM_DATABASE=Cherng Weei Technology Corp. usb:v1C4F* ID_VENDOR_FROM_DATABASE=SiGma Micro usb:v1C4Fp0002* ID_MODEL_FROM_DATABASE=Keyboard TRACER Gamma Ivory usb:v1C4Fp0003* ID_MODEL_FROM_DATABASE=HID controller usb:v1C4Fp000E* ID_MODEL_FROM_DATABASE=Genius KB-120 Keyboard usb:v1C4Fp0026* ID_MODEL_FROM_DATABASE=Keyboard usb:v1C4Fp3000* ID_MODEL_FROM_DATABASE=Micro USB Web Camera usb:v1C4Fp3002* ID_MODEL_FROM_DATABASE=WebCam SiGma Micro usb:v1C6B* ID_VENDOR_FROM_DATABASE=Philips & Lite-ON Digital Solutions Corporation usb:v1C6BpA222* ID_MODEL_FROM_DATABASE=DVD Writer Slimtype eTAU108 usb:v1C6C* ID_VENDOR_FROM_DATABASE=Skydigital Inc. usb:v1C73* ID_VENDOR_FROM_DATABASE=AMT usb:v1C73p861F* ID_MODEL_FROM_DATABASE=Anysee E30 USB 2.0 DVB-T Receiver usb:v1C77* ID_VENDOR_FROM_DATABASE=Kaetat Industrial Co., Ltd. usb:v1C78* ID_VENDOR_FROM_DATABASE=Datascope Corp. usb:v1C79* ID_VENDOR_FROM_DATABASE=Unigen Corporation usb:v1C7A* ID_VENDOR_FROM_DATABASE=LighTuning Technology Inc. usb:v1C7Ap0801* ID_MODEL_FROM_DATABASE=Fingerprint Reader usb:v1C7B* ID_VENDOR_FROM_DATABASE=LUXSHARE PRECISION INDUSTRY (SHENZHEN) CO., LTD. usb:v1C83* ID_VENDOR_FROM_DATABASE=Schomaecker GmbH usb:v1C83p0001* ID_MODEL_FROM_DATABASE=RS150 V2 usb:v1C87* ID_VENDOR_FROM_DATABASE=2N TELEKOMUNIKACE a.s. usb:v1C88* ID_VENDOR_FROM_DATABASE=Somagic, Inc. usb:v1C88p0007* ID_MODEL_FROM_DATABASE=SMI Grabber (EasyCAP DC60+ clone) (no firmware) [SMI-2021CBE] usb:v1C88p003C* ID_MODEL_FROM_DATABASE=SMI Grabber (EasyCAP DC60+ clone) [SMI-2021CBE] usb:v1C89* ID_VENDOR_FROM_DATABASE=HONGKONG WEIDIDA ELECTRON LIMITED usb:v1C8E* ID_VENDOR_FROM_DATABASE=ASTRON INTERNATIONAL CORP. usb:v1C98* ID_VENDOR_FROM_DATABASE=ALPINE ELECTRONICS, INC. usb:v1C9E* ID_VENDOR_FROM_DATABASE=OMEGA TECHNOLOGY usb:v1C9Ep6061* ID_MODEL_FROM_DATABASE=WL-72B 3.5G MODEM usb:v1CA0* ID_VENDOR_FROM_DATABASE=ACCARIO Inc. usb:v1CA1* ID_VENDOR_FROM_DATABASE=Symwave usb:v1CA1p18AB* ID_MODEL_FROM_DATABASE=SATA bridge usb:v1CAC* ID_VENDOR_FROM_DATABASE=Kinstone usb:v1CACpA332* ID_MODEL_FROM_DATABASE=C8 Webcam usb:v1CACpB288* ID_MODEL_FROM_DATABASE=C18 Webcam usb:v1CB3* ID_VENDOR_FROM_DATABASE=Aces Electronic Co., Ltd. usb:v1CB4* ID_VENDOR_FROM_DATABASE=OPEX CORPORATION usb:v1CB6* ID_VENDOR_FROM_DATABASE=IdeaCom Technology Inc. usb:v1CB6p6681* ID_MODEL_FROM_DATABASE=IDC6681 usb:v1CBE* ID_VENDOR_FROM_DATABASE=Luminary Micro Inc. usb:v1CBEp00FD* ID_MODEL_FROM_DATABASE=In-Circuit Debug Interface usb:v1CBEp00FF* ID_MODEL_FROM_DATABASE=Stellaris ROM DFU Bootloader usb:v1CBEp0166* ID_MODEL_FROM_DATABASE=CANAL USB2CAN usb:v1CBF* ID_VENDOR_FROM_DATABASE=FORTAT SKYMARK INDUSTRIAL COMPANY usb:v1CC0* ID_VENDOR_FROM_DATABASE=PlantSense usb:v1CCA* ID_VENDOR_FROM_DATABASE=NextWave Broadband Inc. usb:v1CCD* ID_VENDOR_FROM_DATABASE=Bodatong Technology (Shenzhen) Co., Ltd. usb:v1CD4* ID_VENDOR_FROM_DATABASE=adp corporation usb:v1CD5* ID_VENDOR_FROM_DATABASE=Firecomms Ltd. usb:v1CD6* ID_VENDOR_FROM_DATABASE=Antonio Precise Products Manufactory Ltd. usb:v1CDE* ID_VENDOR_FROM_DATABASE=Telecommunications Technology Association (TTA) usb:v1CDF* ID_VENDOR_FROM_DATABASE=WonTen Technology Co., Ltd. usb:v1CE0* ID_VENDOR_FROM_DATABASE=EDIMAX TECHNOLOGY CO., LTD. usb:v1CE1* ID_VENDOR_FROM_DATABASE=Amphenol KAE usb:v1CF1* ID_VENDOR_FROM_DATABASE=Dresden Elektronik usb:v1CF1p0001* ID_MODEL_FROM_DATABASE=Sensor Terminal Board usb:v1CF1p0004* ID_MODEL_FROM_DATABASE=Wireless Handheld Terminal usb:v1CF1p0017* ID_MODEL_FROM_DATABASE=deRFusbSniffer 2.4 GHz usb:v1CF1p0018* ID_MODEL_FROM_DATABASE=deRFusb24E001 usb:v1CF1p0019* ID_MODEL_FROM_DATABASE=deRFusb14E001 usb:v1CF1p001A* ID_MODEL_FROM_DATABASE=deRFusb23E00 usb:v1CF1p001B* ID_MODEL_FROM_DATABASE=deRFusb13E00 usb:v1CF1p001C* ID_MODEL_FROM_DATABASE=deRFnode usb:v1CF1p001D* ID_MODEL_FROM_DATABASE=deRFnode / gateway usb:v1CF1p0022* ID_MODEL_FROM_DATABASE=deUSB level shifter usb:v1CF1p0023* ID_MODEL_FROM_DATABASE=deRFusbSniffer Sub-GHz usb:v1CF1p0025* ID_MODEL_FROM_DATABASE=deRFusb23E06 usb:v1CF1p0027* ID_MODEL_FROM_DATABASE=deRFusb13E06 usb:v1CFC* ID_VENDOR_FROM_DATABASE=ANDES TECHNOLOGY CORPORATION usb:v1CFD* ID_VENDOR_FROM_DATABASE=Flextronics Digital Design Japan, LTD. usb:v1D03* ID_VENDOR_FROM_DATABASE=iCON usb:v1D03p0028* ID_MODEL_FROM_DATABASE=iCreativ MIDI Controller usb:v1D07* ID_VENDOR_FROM_DATABASE=Solid-Motion usb:v1D08* ID_VENDOR_FROM_DATABASE=NINGBO HENTEK DRAGON ELECTRONICS CO., LTD. usb:v1D09* ID_VENDOR_FROM_DATABASE=TechFaith Wireless Technology Limited usb:v1D09p1026* ID_MODEL_FROM_DATABASE=HSUPA Modem FLYING-LARK46-VER0.07 [Flying Angel] usb:v1D0A* ID_VENDOR_FROM_DATABASE=Johnson Controls, Inc. The Automotive Business Unit usb:v1D0B* ID_VENDOR_FROM_DATABASE=HAN HUA CABLE & WIRE TECHNOLOGY (J.X.) CO., LTD. usb:v1D0F* ID_VENDOR_FROM_DATABASE=Sonix Technology Co., Ltd. usb:v1D14* ID_VENDOR_FROM_DATABASE=ALPHA-SAT TECHNOLOGY LIMITED usb:v1D17* ID_VENDOR_FROM_DATABASE=C-Thru Music Ltd. usb:v1D17p0001* ID_MODEL_FROM_DATABASE=AXiS-49 Harmonic Table MIDI Keyboard usb:v1D19* ID_VENDOR_FROM_DATABASE=Dexatek Technology Ltd. usb:v1D19p1101* ID_MODEL_FROM_DATABASE=DK DVB-T Dongle usb:v1D19p1102* ID_MODEL_FROM_DATABASE=DK mini DVB-T Dongle usb:v1D19p1103* ID_MODEL_FROM_DATABASE=DK 5217 DVB-T Dongle usb:v1D19p6105* ID_MODEL_FROM_DATABASE=Video grabber usb:v1D19p8202* ID_MODEL_FROM_DATABASE=DK DVBC/T DONGLE usb:v1D1F* ID_VENDOR_FROM_DATABASE=Diostech Co., Ltd. usb:v1D20* ID_VENDOR_FROM_DATABASE=SAMTACK INC. usb:v1D27* ID_VENDOR_FROM_DATABASE=ASUS usb:v1D34* ID_VENDOR_FROM_DATABASE=Dream Cheeky usb:v1D34p0001* ID_MODEL_FROM_DATABASE=Dream Cheeky Fidget usb:v1D34p0004* ID_MODEL_FROM_DATABASE=Dream Cheeky Webmail Notifier usb:v1D34p0008* ID_MODEL_FROM_DATABASE=Dream Cheeky button usb:v1D34p000A* ID_MODEL_FROM_DATABASE=Dream Cheeky Mailbox Friends Alert usb:v1D34p000D* ID_MODEL_FROM_DATABASE=Dream Cheeky Big Red Button usb:v1D34p0013* ID_MODEL_FROM_DATABASE=Dream Cheeky LED Message Board usb:v1D45* ID_VENDOR_FROM_DATABASE=Touch usb:v1D45p1D45* ID_MODEL_FROM_DATABASE=Foxlink Optical touch sensor usb:v1D4D* ID_VENDOR_FROM_DATABASE=PEGATRON CORPORATION usb:v1D4Dp0002* ID_MODEL_FROM_DATABASE=Ralink RT2770/2720 802.11b/g/n Wireless LAN Mini-USB Device usb:v1D4Dp000C* ID_MODEL_FROM_DATABASE=Ralink RT3070 802.11b/g/n Wireless Lan USB Device usb:v1D4Dp000E* ID_MODEL_FROM_DATABASE=Ralink RT3070 802.11b/g/n Wireless Lan USB Device usb:v1D50* ID_VENDOR_FROM_DATABASE=OpenMoko, Inc. usb:v1D50p5119* ID_MODEL_FROM_DATABASE=GTA01/GTA02 U-Boot Bootloader usb:v1D50p602B* ID_MODEL_FROM_DATABASE=FPGALink usb:v1D50p6053* ID_MODEL_FROM_DATABASE=Darkgame Controller usb:v1D57* ID_VENDOR_FROM_DATABASE=Xenta usb:v1D57p0005* ID_MODEL_FROM_DATABASE=Wireless Receiver (Keyboard and Mouse) usb:v1D57p0006* ID_MODEL_FROM_DATABASE=Wireless Receiver (RC Laser Pointer) usb:v1D57p000C* ID_MODEL_FROM_DATABASE=Optical Mouse usb:v1D57p2400* ID_MODEL_FROM_DATABASE=Wireless Mouse Receiver usb:v1D57p32DA* ID_MODEL_FROM_DATABASE=2.4GHz Receiver (Keyboard and Mouse) usb:v1D57p83D0* ID_MODEL_FROM_DATABASE=Click-mouse! usb:v1D57pAC01* ID_MODEL_FROM_DATABASE=Wireless Receiver (Keyboard and Mouse) usb:v1D57pAD02* ID_MODEL_FROM_DATABASE=SE340D PC Remote Control usb:v1D57pAF01* ID_MODEL_FROM_DATABASE=AUVIO Universal Remote Receiver for PlayStation 3 usb:v1D5B* ID_VENDOR_FROM_DATABASE=Smartronix, Inc. usb:v1D6B* ID_VENDOR_FROM_DATABASE=Linux Foundation usb:v1D6Bp0001* ID_MODEL_FROM_DATABASE=1.1 root hub usb:v1D6Bp0002* ID_MODEL_FROM_DATABASE=2.0 root hub usb:v1D6Bp0003* ID_MODEL_FROM_DATABASE=3.0 root hub usb:v1D6Bp0100* ID_MODEL_FROM_DATABASE=PTP Gadget usb:v1D6Bp0101* ID_MODEL_FROM_DATABASE=Audio Gadget usb:v1D6Bp0102* ID_MODEL_FROM_DATABASE=EEM Gadget usb:v1D6Bp0103* ID_MODEL_FROM_DATABASE=NCM (Ethernet) Gadget usb:v1D6Bp0104* ID_MODEL_FROM_DATABASE=Multifunction Composite Gadget usb:v1D6Bp0105* ID_MODEL_FROM_DATABASE=FunctionFS Gadget usb:v1D6Bp0200* ID_MODEL_FROM_DATABASE=Qemu Audio Device usb:v1D90* ID_VENDOR_FROM_DATABASE=Citizen usb:v1D90p201E* ID_MODEL_FROM_DATABASE=PPU-700 usb:v1DE1* ID_VENDOR_FROM_DATABASE=Actions Microelectronics Co. usb:v1DE1p1101* ID_MODEL_FROM_DATABASE=Generic Display Device (Mass storage mode) usb:v1DE1pC101* ID_MODEL_FROM_DATABASE=Generic Display Device usb:v1E0E* ID_VENDOR_FROM_DATABASE=Qualcomm / Option usb:v1E0EpF000* ID_MODEL_FROM_DATABASE=iCON 210 UMTS Surfstick usb:v1E10* ID_VENDOR_FROM_DATABASE=Point Grey Research, Inc. usb:v1E10p2004* ID_MODEL_FROM_DATABASE=Sony 1.3MP 1/3" ICX445 IIDC video camera [Chameleon] usb:v1E17* ID_VENDOR_FROM_DATABASE=Mirion Technologies Dosimetry Services Division usb:v1E17p0001* ID_MODEL_FROM_DATABASE=instadose dosimeter usb:v1E1D* ID_VENDOR_FROM_DATABASE=Lumension Security usb:v1E1Dp0165* ID_MODEL_FROM_DATABASE=Secure Pen drive usb:v1E1F* ID_VENDOR_FROM_DATABASE=INVIA usb:v1E29* ID_VENDOR_FROM_DATABASE=Festo AG & Co. KG usb:v1E29p0101* ID_MODEL_FROM_DATABASE=CPX Adapter usb:v1E29p0102* ID_MODEL_FROM_DATABASE=CPX Adapter >=HW10.09 [CP2102] usb:v1E29p0401* ID_MODEL_FROM_DATABASE=iL3-TP [AT90USB646] usb:v1E29p0402* ID_MODEL_FROM_DATABASE=FTDI232 [EasyPort] usb:v1E29p0403* ID_MODEL_FROM_DATABASE=FTDI232 [EasyPort Mini] usb:v1E29p0404* ID_MODEL_FROM_DATABASE=FTDI232 [Netzteil-GL] usb:v1E29p0405* ID_MODEL_FROM_DATABASE=FTDI232 [MotorPrüfstand] usb:v1E29p0406* ID_MODEL_FROM_DATABASE=STM32F103 [EasyKit] usb:v1E29p0407* ID_MODEL_FROM_DATABASE=LPC2378 [Robotino] usb:v1E29p0408* ID_MODEL_FROM_DATABASE=LPC2378 [Robotino-Arm] usb:v1E29p0409* ID_MODEL_FROM_DATABASE=LPC2378 [Robotino-Arm Bootloader] usb:v1E29p040A* ID_MODEL_FROM_DATABASE=LPC2378 [Robotino Bootloader] usb:v1E29p040B* ID_MODEL_FROM_DATABASE=LPC2378 [Robotino XT] usb:v1E29p040C* ID_MODEL_FROM_DATABASE=LPC2378 [Robotino XT Bootloader] usb:v1E29p040D* ID_MODEL_FROM_DATABASE=LPC2378 [Robotino 3] usb:v1E29p040E* ID_MODEL_FROM_DATABASE=LPC2378 [Robotino 3 Bootloader] usb:v1E29p0501* ID_MODEL_FROM_DATABASE=CP2102 [CMSP] usb:v1E29p0601* ID_MODEL_FROM_DATABASE=CMMP-AS usb:v1E3D* ID_VENDOR_FROM_DATABASE=Chipsbank Microelectronics Co., Ltd usb:v1E3Dp2093* ID_MODEL_FROM_DATABASE=CBM209x Flash Drive (OEM) usb:v1E3Dp4082* ID_MODEL_FROM_DATABASE=CBM4082 SD Card Reader usb:v1E41* ID_VENDOR_FROM_DATABASE=Cleverscope usb:v1E41p0001* ID_MODEL_FROM_DATABASE=CS328A PC Oscilloscope usb:v1E4E* ID_VENDOR_FROM_DATABASE=Cubeternet usb:v1E4Ep0100* ID_MODEL_FROM_DATABASE=WebCam usb:v1E4Ep0102* ID_MODEL_FROM_DATABASE=GL-UPC822 UVC WebCam usb:v1E54* ID_VENDOR_FROM_DATABASE=TypeMatrix usb:v1E54p2030* ID_MODEL_FROM_DATABASE=2030 USB Keyboard usb:v1E68* ID_VENDOR_FROM_DATABASE=TrekStor GmbH & Co. KG usb:v1E68p001B* ID_MODEL_FROM_DATABASE=DataStation maxi g.u usb:v1E68p0050* ID_MODEL_FROM_DATABASE=DataStation maxi light usb:v1E71* ID_VENDOR_FROM_DATABASE=NZXT usb:v1E71p0001* ID_MODEL_FROM_DATABASE=Avatar Optical Mouse usb:v1E74* ID_VENDOR_FROM_DATABASE=Coby Electronics Corporation usb:v1E74p2211* ID_MODEL_FROM_DATABASE=MP300 usb:v1E74p2647* ID_MODEL_FROM_DATABASE=2 GB 2 Go Video MP3 Player [MP601-2G] usb:v1E74p2659* ID_MODEL_FROM_DATABASE=Coby 4GB Go Video MP3 Player [MP620-4G] usb:v1E74p4641* ID_MODEL_FROM_DATABASE=A8705 MP3/Video Player usb:v1E74p6511* ID_MODEL_FROM_DATABASE=MP705-8G MP3 player usb:v1E74p6512* ID_MODEL_FROM_DATABASE=MP705-4G usb:v1E74p7111* ID_MODEL_FROM_DATABASE=MP957 Music and Video Player usb:v1E7D* ID_VENDOR_FROM_DATABASE=ROCCAT usb:v1E7Dp2C24* ID_MODEL_FROM_DATABASE=Pyra Mouse (wired) usb:v1E7Dp2CED* ID_MODEL_FROM_DATABASE=Kone Mouse usb:v1E7Dp2CF6* ID_MODEL_FROM_DATABASE=Pyra Mouse (wireless) usb:v1E7Dp2D50* ID_MODEL_FROM_DATABASE=Kova+ Mouse usb:v1E7Dp2D51* ID_MODEL_FROM_DATABASE=Kone+ Mouse usb:v1E7Dp30D4* ID_MODEL_FROM_DATABASE=Arvo Keyboard usb:v1EBB* ID_VENDOR_FROM_DATABASE=NuCORE Technology, Inc. usb:v1EDA* ID_VENDOR_FROM_DATABASE=AirTies Wireless Networks usb:v1EDAp2012* ID_MODEL_FROM_DATABASE=Air2210 54 Mbps Wireless Adapter usb:v1EDAp2210* ID_MODEL_FROM_DATABASE=Air2210 54 Mbps Wireless Adapter usb:v1EDAp2310* ID_MODEL_FROM_DATABASE=Air2310 150 Mbps Wireless Adapter usb:v1EDAp2410* ID_MODEL_FROM_DATABASE=Air2410 300 Mbps Wireless Adapter usb:v1EDB* ID_VENDOR_FROM_DATABASE=Blackmagic design usb:v1EDBpBD3B* ID_MODEL_FROM_DATABASE=Intensity Shuttle usb:v1EE8* ID_VENDOR_FROM_DATABASE=ONDA COMMUNICATION S.p.a. usb:v1EE8p0014* ID_MODEL_FROM_DATABASE=MT833UP usb:v1EF6* ID_VENDOR_FROM_DATABASE=EADS Deutschland GmbH usb:v1EF6p2233* ID_MODEL_FROM_DATABASE=Cassidian NH90 STTE usb:v1EF6p5064* ID_MODEL_FROM_DATABASE=FDR Interface usb:v1EF6p5523* ID_MODEL_FROM_DATABASE=Cassidian SSDC Adapter II usb:v1EF6p5545* ID_MODEL_FROM_DATABASE=Cassidian SSDC Adapter III usb:v1EF6p5648* ID_MODEL_FROM_DATABASE=RIU CSMU/BSD usb:v1EF6p564A* ID_MODEL_FROM_DATABASE=Cassidian RIU CSMU/BSD Simulator usb:v1F28* ID_VENDOR_FROM_DATABASE=Cal-Comp usb:v1F28p0020* ID_MODEL_FROM_DATABASE=CDMA USB Modem A600 usb:v1F28p0021* ID_MODEL_FROM_DATABASE=CD INSTALLER USB Device usb:v1F3A* ID_VENDOR_FROM_DATABASE=Onda (unverified) usb:v1F3ApEFE8* ID_MODEL_FROM_DATABASE=V972 tablet in flashing mode usb:v1F44* ID_VENDOR_FROM_DATABASE=The Neat Company usb:v1F44p0001* ID_MODEL_FROM_DATABASE=NM-1000 scanner usb:v1F48* ID_VENDOR_FROM_DATABASE=H-TRONIC GmbH usb:v1F48p0627* ID_MODEL_FROM_DATABASE=Data capturing system usb:v1F48p0628* ID_MODEL_FROM_DATABASE=Data capturing and control module usb:v1F4D* ID_VENDOR_FROM_DATABASE=G-Tek Electronics Group usb:v1F4DpB803* ID_MODEL_FROM_DATABASE=Lifeview LV5TDLX DVB-T [RTL2832U] usb:v1F4DpD220* ID_MODEL_FROM_DATABASE=Geniatech T220 DVB-T2 TV Stick usb:v1F6F* ID_VENDOR_FROM_DATABASE=Aliph usb:v1F6Fp0023* ID_MODEL_FROM_DATABASE=Jawbone Jambox usb:v1F6Fp8000* ID_MODEL_FROM_DATABASE=Jawbone Jambox - Updating usb:v1F75* ID_VENDOR_FROM_DATABASE=Innostor Technology Corporation usb:v1F75p0888* ID_MODEL_FROM_DATABASE=IS888 SATA Storage Controller usb:v1F75p0902* ID_MODEL_FROM_DATABASE=IS902 UFD controller usb:v1F82* ID_VENDOR_FROM_DATABASE=TANDBERG usb:v1F82p0001* ID_MODEL_FROM_DATABASE=PrecisionHD Camera usb:v1F84* ID_VENDOR_FROM_DATABASE=Alere, Inc. usb:v1F87* ID_VENDOR_FROM_DATABASE=Stantum usb:v1F87p0002* ID_MODEL_FROM_DATABASE=Multi-touch HID Controller usb:v1F9B* ID_VENDOR_FROM_DATABASE=Ubiquiti Networks, Inc. usb:v1F9Bp0241* ID_MODEL_FROM_DATABASE=AirView2-EXT usb:v1FAB* ID_VENDOR_FROM_DATABASE=Samsung Opto-Electroncs Co., Ltd. usb:v1FABp104D* ID_MODEL_FROM_DATABASE=ES65 usb:v1FBD* ID_VENDOR_FROM_DATABASE=Delphin Technology AG usb:v1FBDp0001* ID_MODEL_FROM_DATABASE=Expert Key - Data aquisition system usb:v1FC9* ID_VENDOR_FROM_DATABASE=NXP Semiconductors usb:v1FC9p0003* ID_MODEL_FROM_DATABASE=LPC1343 usb:v1FC9p010B* ID_MODEL_FROM_DATABASE=PR533 usb:v1FDE* ID_VENDOR_FROM_DATABASE=ILX Lightwave Corporation usb:v1FDEp0001* ID_MODEL_FROM_DATABASE=UART Bridge usb:v1FE7* ID_VENDOR_FROM_DATABASE=Vertex Wireless Co., Ltd. usb:v1FE7p1000* ID_MODEL_FROM_DATABASE=VW100 series CDMA EV-DO Rev.A modem usb:v1FF7* ID_VENDOR_FROM_DATABASE=CVT Electronics.Co.,Ltd usb:v1FF7p0013* ID_MODEL_FROM_DATABASE=CVTouch Screen (HID) usb:v1FF7p001A* ID_MODEL_FROM_DATABASE=Human Interface Device usb:v1FFF* ID_VENDOR_FROM_DATABASE=Ideofy Inc. usb:v2001* ID_VENDOR_FROM_DATABASE=D-Link Corp. usb:v2001p0001* ID_MODEL_FROM_DATABASE=DWL-120 WIRELESS ADAPTER usb:v2001p0201* ID_MODEL_FROM_DATABASE=DHN-120 10Mb Home Phoneline Adapter usb:v2001p1A00* ID_MODEL_FROM_DATABASE=DUB-E100 Fast Ethernet Adapter(rev.A) [ASIX AX88172] usb:v2001p1A02* ID_MODEL_FROM_DATABASE=DUB-E100 Fast Ethernet Adapter(rev.C1) [ASIX AX88772] usb:v2001p200C* ID_MODEL_FROM_DATABASE=10/100 Ethernet usb:v2001p3200* ID_MODEL_FROM_DATABASE=DWL-120 802.11b Wireless Adapter(rev.E1) [Atmel at76c503a] usb:v2001p3301* ID_MODEL_FROM_DATABASE=DWA-130 802.11n Wireless N Adapter(rev.C1) [Realtek RTL8192U] usb:v2001p3306* ID_MODEL_FROM_DATABASE=DWL-G122 Wireless Adapter(rev.F1) [Realtek RTL8188SU] usb:v2001p3308* ID_MODEL_FROM_DATABASE=DWA-121 802.11n Wireless N 150 Pico Adapter [Realtek RTL8188CUS] usb:v2001p3309* ID_MODEL_FROM_DATABASE=DWA-135 802.11n Wireless N Adapter(rev.A1) [Realtek RTL8192CU] usb:v2001p330A* ID_MODEL_FROM_DATABASE=DWA-133 802.11n Wireless N Adapter [Realtek RTL8192CU] usb:v2001p3500* ID_MODEL_FROM_DATABASE=Elitegroup Computer Systems WLAN card WL-162 usb:v2001p3700* ID_MODEL_FROM_DATABASE=DWL-122 802.11b [Intersil Prism 3] usb:v2001p3701* ID_MODEL_FROM_DATABASE=DWL-G120 Spinnaker 802.11g [Intersil ISL3886] usb:v2001p3702* ID_MODEL_FROM_DATABASE=DWL-120 802.11b Wireless Adapter(rev.F) [Intersil ISL3871] usb:v2001p3703* ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter(rev.A1) [Intersil ISL3880] usb:v2001p3704* ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter(rev.A2) [Intersil ISL3887] usb:v2001p3705* ID_MODEL_FROM_DATABASE=AirPlus G DWL-G120 Wireless Adapter(rev.C) [Intersil ISL3887] usb:v2001p3761* ID_MODEL_FROM_DATABASE=IEEE 802.11g USB2.0 Wireless Network Adapter-PN usb:v2001p3A00* ID_MODEL_FROM_DATABASE=DWL-AG132 [Atheros AR5523] usb:v2001p3A01* ID_MODEL_FROM_DATABASE=DWL-AG132 (no firmware) [Atheros AR5523] usb:v2001p3A02* ID_MODEL_FROM_DATABASE=DWL-G132 [Atheros AR5523] usb:v2001p3A03* ID_MODEL_FROM_DATABASE=DWL-G132 (no firmware) [Atheros AR5523] usb:v2001p3A04* ID_MODEL_FROM_DATABASE=DWL-AG122 [Atheros AR5523] usb:v2001p3A05* ID_MODEL_FROM_DATABASE=DWL-AG122 (no firmware) [Atheros AR5523] usb:v2001p3A80* ID_MODEL_FROM_DATABASE=AirPlus Xtreme G DWL-G132 Wireless Adapter usb:v2001p3A81* ID_MODEL_FROM_DATABASE=predator Bootloader Download usb:v2001p3A82* ID_MODEL_FROM_DATABASE=AirPremier AG DWL-AG132 Wireless Adapter usb:v2001p3A83* ID_MODEL_FROM_DATABASE=predator Bootloader Download usb:v2001p3B00* ID_MODEL_FROM_DATABASE=AirPlus DWL-120+ Wireless Adapter [Texas Instruments ACX100USB] usb:v2001p3B01* ID_MODEL_FROM_DATABASE=WLAN Boot Device usb:v2001p3C00* ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter(rev.B1) [Ralink RT2571] usb:v2001p3C01* ID_MODEL_FROM_DATABASE=AirPlus AG DWL-AG122 Wireless Adapter usb:v2001p3C02* ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter usb:v2001p3C05* ID_MODEL_FROM_DATABASE=DUB-E100 Fast Ethernet Adapter(rev.B1) [ASIX AX88772] usb:v2001p3C15* ID_MODEL_FROM_DATABASE=DWA-140 RangeBooster N Adapter(rev.B3) [Ralink RT5372] usb:v2001p3C17* ID_MODEL_FROM_DATABASE=DWA-123 Wireless N 150 Adapter(rev.A1) [Ralink RT3370] usb:v2001p3C19* ID_MODEL_FROM_DATABASE=DWA-125 Wireless N 150 Adapter(rev.A3) [Ralink RT5370] usb:v2001p3C1A* ID_MODEL_FROM_DATABASE=DWA-160 802.11abgn Xtreme N Dual Band Adapter(rev.B2) [Ralink RT5572] usb:v2001p3C1B* ID_MODEL_FROM_DATABASE=DWA-127 Wireless N 150 High-Gain Adapter(rev.A1) [Ralink RT3070] usb:v2001p4000* ID_MODEL_FROM_DATABASE=DSB-650C Ethernet [klsi] usb:v2001p4001* ID_MODEL_FROM_DATABASE=DSB-650TX Ethernet [pegasus] usb:v2001p4002* ID_MODEL_FROM_DATABASE=DSB-650TX Ethernet [pegasus] usb:v2001p4003* ID_MODEL_FROM_DATABASE=DSB-650TX-PNA Ethernet [pegasus] usb:v2001p400B* ID_MODEL_FROM_DATABASE=10/100 Ethernet usb:v2001p4102* ID_MODEL_FROM_DATABASE=10/100 Ethernet usb:v2001p5100* ID_MODEL_FROM_DATABASE=DSL-200 ADSL ATM Modem usb:v2001p5102* ID_MODEL_FROM_DATABASE=DSL-200 ADSL Loader usb:v2001p5B00* ID_MODEL_FROM_DATABASE=Remote NDIS Network Device usb:v2001p9414* ID_MODEL_FROM_DATABASE=Cable Modem usb:v2001p9B00* ID_MODEL_FROM_DATABASE=Broadband Cable Modem Remote NDIS Device usb:v2001pABC1* ID_MODEL_FROM_DATABASE=DSB-650 Ethernet [pegasus] usb:v2001pF013* ID_MODEL_FROM_DATABASE=DLink 7 port USB2.0 Hub usb:v2001pF103* ID_MODEL_FROM_DATABASE=DUB-H7 7-port USB 2.0 hub usb:v2001pF10D* ID_MODEL_FROM_DATABASE=Accent Communications Modem usb:v2001pF110* ID_MODEL_FROM_DATABASE=DUB-AV300 A/V Capture usb:v2001pF111* ID_MODEL_FROM_DATABASE=DBT-122 Bluetooth adapter usb:v2001pF112* ID_MODEL_FROM_DATABASE=DUB-T210 Audio Device usb:v2001pF116* ID_MODEL_FROM_DATABASE=Formosa 2 usb:v2001pF117* ID_MODEL_FROM_DATABASE=Formosa 3 usb:v2001pF118* ID_MODEL_FROM_DATABASE=Formosa 4 usb:v2002* ID_VENDOR_FROM_DATABASE=DAP Technologies usb:v2003* ID_VENDOR_FROM_DATABASE=detectomat usb:v2003pEA61* ID_MODEL_FROM_DATABASE=dc3500 usb:v200C* ID_VENDOR_FROM_DATABASE=Reloop usb:v200Cp100B* ID_MODEL_FROM_DATABASE=Play audio soundcard usb:v2013* ID_VENDOR_FROM_DATABASE=PCTV Systems usb:v2013p0245* ID_MODEL_FROM_DATABASE=PCTV 73ESE usb:v2013p0246* ID_MODEL_FROM_DATABASE=PCTV 74E usb:v2013p0248* ID_MODEL_FROM_DATABASE=PCTV 282E usb:v2013p024F* ID_MODEL_FROM_DATABASE=nanoStick T2 290e usb:v2019* ID_VENDOR_FROM_DATABASE=PLANEX usb:v2019p3220* ID_MODEL_FROM_DATABASE=GW-US11S WLAN [Atmel AT76C503A] usb:v2019p4901* ID_MODEL_FROM_DATABASE=GW-USSuper300 802.11bgn Wireless Adapter [Realtek RTL8191SU] usb:v2019p4903* ID_MODEL_FROM_DATABASE=GW-USFang300 802.11abgn Wireless Adapter [Realtek RTL8192DU] usb:v2019p4904* ID_MODEL_FROM_DATABASE=GW-USUltra300 802.11abgn Wireless Adapter [Realtek RTL8192DU] usb:v2019p5303* ID_MODEL_FROM_DATABASE=GW-US54GXS 802.11bg usb:v2019p5304* ID_MODEL_FROM_DATABASE=GWUS300 802.11n usb:v2019pAB01* ID_MODEL_FROM_DATABASE=GW-US54HP usb:v2019pAB24* ID_MODEL_FROM_DATABASE=GW-US300MiniS usb:v2019pAB25* ID_MODEL_FROM_DATABASE=GW-USMini2N 802.11n Wireless Adapter [Ralink RT2870] usb:v2019pAB28* ID_MODEL_FROM_DATABASE=GW-USNano usb:v2019pAB29* ID_MODEL_FROM_DATABASE=GW-USMicro300 usb:v2019pAB2A* ID_MODEL_FROM_DATABASE=GW-USNano2 802.11n Wireless Adapter [Realtek RTL8188CUS] usb:v2019pAB2B* ID_MODEL_FROM_DATABASE=GW-USEco300 802.11bgn Wireless Adapter [Realtek RTL8192CU] usb:v2019pAB2C* ID_MODEL_FROM_DATABASE=GW-USDual300 802.11abgn Wireless Adapter [Realtek RTL8192DU] usb:v2019pAB50* ID_MODEL_FROM_DATABASE=GW-US54Mini2 usb:v2019pC002* ID_MODEL_FROM_DATABASE=GW-US54SG usb:v2019pC007* ID_MODEL_FROM_DATABASE=GW-US54GZL usb:v2019pED02* ID_MODEL_FROM_DATABASE=GW-USMM usb:v2019pED06* ID_MODEL_FROM_DATABASE=GW-US300MiniW 802.11bgn Wireless Adapter usb:v2019pED10* ID_MODEL_FROM_DATABASE=GW-US300Mini2 usb:v2019pED14* ID_MODEL_FROM_DATABASE=GW-USMicroN usb:v2019pED16* ID_MODEL_FROM_DATABASE=GW-USMicroN2W 802.11bgn Wireless Adapter [Realtek RTL8188SU] usb:v2019pED17* ID_MODEL_FROM_DATABASE=GW-USValue-EZ 802.11n Wireless Adapter [Realtek RTL8188CUS] usb:v2019pED18* ID_MODEL_FROM_DATABASE=GW-USHyper300 / GW-USH300N 802.11bgn Wireless Adapter [Realtek RTL8191SU] usb:v203D* ID_VENDOR_FROM_DATABASE=Encore Electronics Inc. usb:v203Dp1480* ID_MODEL_FROM_DATABASE=ENUWI-N3 [802.11n Wireless N150 Adapter] usb:v2040* ID_VENDOR_FROM_DATABASE=Hauppauge usb:v2040p0C80* ID_MODEL_FROM_DATABASE=Windham usb:v2040p0C90* ID_MODEL_FROM_DATABASE=Windham usb:v2040p1700* ID_MODEL_FROM_DATABASE=CataMount usb:v2040p1800* ID_MODEL_FROM_DATABASE=Okemo A usb:v2040p1801* ID_MODEL_FROM_DATABASE=Okemo B usb:v2040p2000* ID_MODEL_FROM_DATABASE=Tiger Minicard usb:v2040p2009* ID_MODEL_FROM_DATABASE=Tiger Minicard R2 usb:v2040p200A* ID_MODEL_FROM_DATABASE=Tiger Minicard usb:v2040p2010* ID_MODEL_FROM_DATABASE=Tiger Minicard usb:v2040p2011* ID_MODEL_FROM_DATABASE=WinTV MiniCard [Dell Digital TV Receiver] usb:v2040p2019* ID_MODEL_FROM_DATABASE=Tiger Minicard usb:v2040p2400* ID_MODEL_FROM_DATABASE=WinTV PVR USB2 (Model 24019) usb:v2040p4700* ID_MODEL_FROM_DATABASE=WinTV Nova-S-USB2 usb:v2040p4902* ID_MODEL_FROM_DATABASE=HD PVR usb:v2040p4903* ID_MODEL_FROM_DATABASE=HS PVR usb:v2040p4982* ID_MODEL_FROM_DATABASE=HD PVR usb:v2040p5500* ID_MODEL_FROM_DATABASE=Windham usb:v2040p5510* ID_MODEL_FROM_DATABASE=Windham usb:v2040p5520* ID_MODEL_FROM_DATABASE=Windham usb:v2040p5530* ID_MODEL_FROM_DATABASE=Windham usb:v2040p5580* ID_MODEL_FROM_DATABASE=Windham usb:v2040p5590* ID_MODEL_FROM_DATABASE=Windham usb:v2040p6500* ID_MODEL_FROM_DATABASE=WinTV HVR-900 usb:v2040p6502* ID_MODEL_FROM_DATABASE=WinTV HVR-900 usb:v2040p6503* ID_MODEL_FROM_DATABASE=WinTV HVR-930 usb:v2040p6513* ID_MODEL_FROM_DATABASE=WinTV HVR-980 usb:v2040p7050* ID_MODEL_FROM_DATABASE=Nova-T Stick usb:v2040p7060* ID_MODEL_FROM_DATABASE=Nova-T Stick 2 usb:v2040p7070* ID_MODEL_FROM_DATABASE=Nova-T Stick 3 usb:v2040p7240* ID_MODEL_FROM_DATABASE=WinTV HVR-850 usb:v2040p8400* ID_MODEL_FROM_DATABASE=WinTV Nova-T-500 usb:v2040p9300* ID_MODEL_FROM_DATABASE=WinTV NOVA-T USB2 (cold) usb:v2040p9301* ID_MODEL_FROM_DATABASE=WinTV NOVA-T USB2 (warm) usb:v2040p9941* ID_MODEL_FROM_DATABASE=WinTV Nova-T-500 usb:v2040p9950* ID_MODEL_FROM_DATABASE=WinTV Nova-T-500 usb:v2040pB910* ID_MODEL_FROM_DATABASE=Windham usb:v2040pB980* ID_MODEL_FROM_DATABASE=Windham usb:v2040pB990* ID_MODEL_FROM_DATABASE=Windham usb:v2040pC000* ID_MODEL_FROM_DATABASE=Windham usb:v2040pC010* ID_MODEL_FROM_DATABASE=Windham usb:v2047* ID_VENDOR_FROM_DATABASE=Texas Instruments usb:v2047p0200* ID_MODEL_FROM_DATABASE=MSP430 USB HID Bootstrap Loader usb:v2047p0855* ID_MODEL_FROM_DATABASE=Invensense Embedded MotionApp HID Sensor usb:v2047p0964* ID_MODEL_FROM_DATABASE=Inventio Software MSP430 usb:v2058* ID_VENDOR_FROM_DATABASE=Nano River Technology usb:v2058p2058* ID_MODEL_FROM_DATABASE=ViperBoard I2C, SPI, GPIO interface usb:v2077* ID_VENDOR_FROM_DATABASE=Taicang T&W Electronics Co. Ltd usb:v2077p9002* ID_MODEL_FROM_DATABASE=W1M100 HSPA/WCDMA Module usb:v2080* ID_VENDOR_FROM_DATABASE=Barnes & Noble usb:v2080p0001* ID_MODEL_FROM_DATABASE=nook usb:v2080p0002* ID_MODEL_FROM_DATABASE=NOOKcolor usb:v2080p0003* ID_MODEL_FROM_DATABASE=NOOK Simple Touch usb:v2080p0004* ID_MODEL_FROM_DATABASE=NOOK Tablet usb:v2086* ID_VENDOR_FROM_DATABASE=SIMPASS usb:v2087* ID_VENDOR_FROM_DATABASE=Cando usb:v2087p0A01* ID_MODEL_FROM_DATABASE=Multi Touch Panel usb:v2087p0A02* ID_MODEL_FROM_DATABASE=Multi Touch Panel usb:v2087p0B03* ID_MODEL_FROM_DATABASE=Multi Touch Panel usb:v20A0* ID_VENDOR_FROM_DATABASE=Clay Logic usb:v20A0p4123* ID_MODEL_FROM_DATABASE=IKALOGIC SCANALOGIC 2 usb:v20A0p414A* ID_MODEL_FROM_DATABASE=MDE SPI Interface usb:v20A0p415A* ID_MODEL_FROM_DATABASE=OpenPilot usb:v20A0p415B* ID_MODEL_FROM_DATABASE=CopterControl usb:v20A0p415C* ID_MODEL_FROM_DATABASE=PipXtreme usb:v20B1* ID_VENDOR_FROM_DATABASE=XMOS Ltd usb:v20B1p10AD* ID_MODEL_FROM_DATABASE=XUSB Loader usb:v20B1pF7D1* ID_MODEL_FROM_DATABASE=XTAG2 - JTAG Adapter usb:v20B3* ID_VENDOR_FROM_DATABASE=Hanvon usb:v20B3p0A18* ID_MODEL_FROM_DATABASE=10.1 Touch screen overlay usb:v20B7* ID_VENDOR_FROM_DATABASE=Qi Hardware usb:v20B7p0713* ID_MODEL_FROM_DATABASE=Milkymist JTAG/serial usb:v20B7p1540* ID_MODEL_FROM_DATABASE=ben-wpan, AT86RF230-based usb:v20B7p1DB5* ID_MODEL_FROM_DATABASE=IDBG in DFU mode usb:v20B7p1DB6* ID_MODEL_FROM_DATABASE=IDBG in normal mode usb:v20B7pC25B* ID_MODEL_FROM_DATABASE=C2 Dongle usb:v20B7pCB72* ID_MODEL_FROM_DATABASE=ben-wpan, cntr usb:v20CE* ID_VENDOR_FROM_DATABASE=Minicircuits usb:v20CEp0012* ID_MODEL_FROM_DATABASE=RF Sythesizer 250-4200MHz model SSG-4000LH usb:v20CEp0021* ID_MODEL_FROM_DATABASE=RF Switch Matrix usb:v20CEp0022* ID_MODEL_FROM_DATABASE=I/O Controller usb:v20DF* ID_VENDOR_FROM_DATABASE=Simtec Electronics usb:v20DFp0001* ID_MODEL_FROM_DATABASE=Entropy Key [UDEKEY01] usb:v20F1* ID_VENDOR_FROM_DATABASE=NET New Electronic Technology GmbH usb:v20F1p0101* ID_MODEL_FROM_DATABASE=iCube3 Camera usb:v20F4* ID_VENDOR_FROM_DATABASE=TRENDnet usb:v20F4p648B* ID_MODEL_FROM_DATABASE=TEW-648UBM 802.11n 150Mbps Micro Wireless N Adapter [Realtek RTL8188CUS] usb:v20F7* ID_VENDOR_FROM_DATABASE=XIMEA usb:v20F7p3001* ID_MODEL_FROM_DATABASE=Camera with CMOS sensor [MQ] usb:v20F7p3021* ID_MODEL_FROM_DATABASE=Camera with CCD sensor [MD] usb:v20F7p30B3* ID_MODEL_FROM_DATABASE=Camera with CMOS sensor in Vision mode [MQ] usb:v20F7pA003* ID_MODEL_FROM_DATABASE=Subminiature 5Mpix B/W Camera, MU9PM-MH usb:v2100* ID_VENDOR_FROM_DATABASE=RT Systems usb:v2100p9E52* ID_MODEL_FROM_DATABASE=Yaesu VX-7 usb:v2100p9E54* ID_MODEL_FROM_DATABASE=CT29B Radio Cable usb:v2100p9E57* ID_MODEL_FROM_DATABASE=RTS01 Radio Cable usb:v2100p9E5D* ID_MODEL_FROM_DATABASE=K4Y Radio Cable usb:v2100p9E5F* ID_MODEL_FROM_DATABASE=FT232RL [RTS05 Serial Cable] usb:v2101* ID_VENDOR_FROM_DATABASE=ActionStar usb:v2101p0201* ID_MODEL_FROM_DATABASE=SIIG 4-to-2 Printer Switch usb:v2109* ID_VENDOR_FROM_DATABASE=VIA Labs, Inc. usb:v2109p0700* ID_MODEL_FROM_DATABASE=VL700 SATA 3Gb/s bridge usb:v2109p0701* ID_MODEL_FROM_DATABASE=VL701 SATA 3Gb/s bridge usb:v2109p0810* ID_MODEL_FROM_DATABASE=VL81x Hub usb:v2109p0811* ID_MODEL_FROM_DATABASE=Hub usb:v2109p0812* ID_MODEL_FROM_DATABASE=VL812 Hub usb:v2109p2811* ID_MODEL_FROM_DATABASE=Hub usb:v2109p2812* ID_MODEL_FROM_DATABASE=VL812 Hub usb:v2109p3431* ID_MODEL_FROM_DATABASE=Hub usb:v2109p8110* ID_MODEL_FROM_DATABASE=Hub usb:v2113* ID_VENDOR_FROM_DATABASE=Softkinetic usb:v2113p0137* ID_MODEL_FROM_DATABASE=DepthSense 311 (3D) usb:v2113p0145* ID_MODEL_FROM_DATABASE=DepthSense 325 usb:v2113p8000* ID_MODEL_FROM_DATABASE=DepthSense 311 (Color) usb:v2149* ID_VENDOR_FROM_DATABASE=Advanced Silicon S.A. usb:v2149p211B* ID_MODEL_FROM_DATABASE=Touchscreen Controller usb:v2149p2703* ID_MODEL_FROM_DATABASE=TS58xxA/TC56xxA [CoolTouch] usb:v2162* ID_VENDOR_FROM_DATABASE=Creative (?) usb:v2162p2031* ID_MODEL_FROM_DATABASE=Network Blaster Wireless Adapter usb:v2162p500C* ID_MODEL_FROM_DATABASE=DE5771 Modem Blaster usb:v2162p8001* ID_MODEL_FROM_DATABASE=Broadxent BritePort DSL Bridge 8010U usb:v2184* ID_VENDOR_FROM_DATABASE=GW Instek usb:v2184p0005* ID_MODEL_FROM_DATABASE=GDS-3000 Oscilloscope usb:v2184p0006* ID_MODEL_FROM_DATABASE=GDS-3000 Oscilloscope usb:v2184p0011* ID_MODEL_FROM_DATABASE=AFG Function Generator (CDC) usb:v21A1* ID_VENDOR_FROM_DATABASE=Emotiv Systems Pty. Ltd. usb:v21A1p0001* ID_MODEL_FROM_DATABASE=EPOC Consumer Headset Wireless Dongle usb:v21D6* ID_VENDOR_FROM_DATABASE=Agecodagis SARL usb:v21D6p0002* ID_MODEL_FROM_DATABASE=Seismic recorder [Tellus] usb:v2222* ID_VENDOR_FROM_DATABASE=MacAlly usb:v2222p0004* ID_MODEL_FROM_DATABASE=iWebKey Keyboard usb:v2222p2520* ID_MODEL_FROM_DATABASE=Mini Tablet usb:v2222p4050* ID_MODEL_FROM_DATABASE=AirStick joystick usb:v2227* ID_VENDOR_FROM_DATABASE=SAMWOO Enterprise usb:v2227p3105* ID_MODEL_FROM_DATABASE=SKYDATA SKD-U100 usb:v2232* ID_VENDOR_FROM_DATABASE=Silicon Motion usb:v2232p1005* ID_MODEL_FROM_DATABASE=WebCam SCB-0385N usb:v2232p1028* ID_MODEL_FROM_DATABASE=WebCam SC-03FFL11939N usb:v2232p1029* ID_MODEL_FROM_DATABASE=WebCam SC-13HDL11939N usb:v2232p1037* ID_MODEL_FROM_DATABASE=WebCam SC-03FFM12339N usb:v2233* ID_VENDOR_FROM_DATABASE=RadioShack Corporation usb:v2233p6323* ID_MODEL_FROM_DATABASE=USB Electronic Scale usb:v2237* ID_VENDOR_FROM_DATABASE=Kobo Inc. usb:v2237p4161* ID_MODEL_FROM_DATABASE=eReader White usb:v225D* ID_VENDOR_FROM_DATABASE=Morpho usb:v225Dp0001* ID_MODEL_FROM_DATABASE=FINGER VP Multimodal Biometric Sensor usb:v225Dp0008* ID_MODEL_FROM_DATABASE=CBM-E3 Fingerprint Sensor usb:v225Dp0009* ID_MODEL_FROM_DATABASE=CBM Fingerprint Sensor [CBM-V3] usb:v225Dp000A* ID_MODEL_FROM_DATABASE=MSO1300-E3 Fingerprint Sensor usb:v225Dp000B* ID_MODEL_FROM_DATABASE=MSO1300 Fingerprint Sensor [MSO1300-V3] usb:v225Dp000C* ID_MODEL_FROM_DATABASE=MSO1350-E3 Fingerprint Sensor & SmartCard Reader usb:v225Dp000D* ID_MODEL_FROM_DATABASE=MSO1350 Fingerprint Sensor & SmartCard Reader [MSO1350-V3] usb:v225Dp000E* ID_MODEL_FROM_DATABASE=MorphoAccess SIGMA Biometric Access Control Terminal usb:v228D* ID_VENDOR_FROM_DATABASE=8D Technologies inc. usb:v228Dp0001* ID_MODEL_FROM_DATABASE=Terminal Bike Key Reader usb:v22A6* ID_VENDOR_FROM_DATABASE=Pie Digital, Inc. usb:v22A6pFFFF* ID_MODEL_FROM_DATABASE=PieKey "beta" 4GB model 4E4F41482E4F5247 (SM3251Q BB) usb:v22B8* ID_VENDOR_FROM_DATABASE=Motorola PCS usb:v22B8p0001* ID_MODEL_FROM_DATABASE=Wally 2.2 chipset usb:v22B8p0002* ID_MODEL_FROM_DATABASE=Wally 2.4 chipset usb:v22B8p0005* ID_MODEL_FROM_DATABASE=V.60c/V.60i GSM Phone usb:v22B8p0830* ID_MODEL_FROM_DATABASE=2386C-HT820 usb:v22B8p0833* ID_MODEL_FROM_DATABASE=2386C-HT820 [Flash Mode] usb:v22B8p0850* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v22B8p1001* ID_MODEL_FROM_DATABASE=Patriot 1.0 (GSM) chipset usb:v22B8p1002* ID_MODEL_FROM_DATABASE=Patriot 2.0 chipset usb:v22B8p1005* ID_MODEL_FROM_DATABASE=T280e GSM/GPRS Phone usb:v22B8p1101* ID_MODEL_FROM_DATABASE=Patriot 1.0 (TDMA) chipset usb:v22B8p1801* ID_MODEL_FROM_DATABASE=Rainbow chipset flash usb:v22B8p2035* ID_MODEL_FROM_DATABASE=Bluetooth Device usb:v22B8p2805* ID_MODEL_FROM_DATABASE=GSM Modem usb:v22B8p2821* ID_MODEL_FROM_DATABASE=T720 GSM Phone usb:v22B8p2822* ID_MODEL_FROM_DATABASE=V.120e GSM Phone usb:v22B8p2823* ID_MODEL_FROM_DATABASE=Flash Interface usb:v22B8p2A01* ID_MODEL_FROM_DATABASE=MSM6050 chipset usb:v22B8p2A02* ID_MODEL_FROM_DATABASE=CDMA modem usb:v22B8p2A03* ID_MODEL_FROM_DATABASE=MSM6050 chipset flash usb:v22B8p2A21* ID_MODEL_FROM_DATABASE=V710 GSM Phone (P2K) usb:v22B8p2A22* ID_MODEL_FROM_DATABASE=V710 GSM Phone (AT) usb:v22B8p2A23* ID_MODEL_FROM_DATABASE=MSM6100 chipset flash usb:v22B8p2A41* ID_MODEL_FROM_DATABASE=MSM6300 chipset usb:v22B8p2A42* ID_MODEL_FROM_DATABASE=Usb Modem usb:v22B8p2A43* ID_MODEL_FROM_DATABASE=MSM6300 chipset flash usb:v22B8p2A61* ID_MODEL_FROM_DATABASE=E815 GSM Phone (P2K) usb:v22B8p2A62* ID_MODEL_FROM_DATABASE=E815 GSM Phone (AT) usb:v22B8p2A63* ID_MODEL_FROM_DATABASE=MSM6500 chipset flash usb:v22B8p2A81* ID_MODEL_FROM_DATABASE=MSM6025 chipset usb:v22B8p2A83* ID_MODEL_FROM_DATABASE=MSM6025 chipset flash usb:v22B8p2AC1* ID_MODEL_FROM_DATABASE=MSM6100 chipset usb:v22B8p2AC3* ID_MODEL_FROM_DATABASE=MSM6100 chipset flash usb:v22B8p2D78* ID_MODEL_FROM_DATABASE=XT300[SPICE] usb:v22B8p3001* ID_MODEL_FROM_DATABASE=A835/E1000 GSM Phone (P2K) usb:v22B8p3002* ID_MODEL_FROM_DATABASE=A835/E1000 GSM Phone (AT) usb:v22B8p3801* ID_MODEL_FROM_DATABASE=C350L/C450 (P2K) usb:v22B8p3802* ID_MODEL_FROM_DATABASE=C330/C350L/C450/EZX GSM Phone (AT) usb:v22B8p3803* ID_MODEL_FROM_DATABASE=Neptune LT chipset flash usb:v22B8p4001* ID_MODEL_FROM_DATABASE=OMAP 1.0 chipset usb:v22B8p4002* ID_MODEL_FROM_DATABASE=A920/A925 UMTS Phone usb:v22B8p4003* ID_MODEL_FROM_DATABASE=OMAP 1.0 chipset flash usb:v22B8p4008* ID_MODEL_FROM_DATABASE=OMAP 1.0 chipset RDL usb:v22B8p41D6* ID_MODEL_FROM_DATABASE=Droid X (Windows media mode) usb:v22B8p41D9* ID_MODEL_FROM_DATABASE=Droid/Milestone usb:v22B8p41DB* ID_MODEL_FROM_DATABASE=Droid/Milestone (Debug mode) usb:v22B8p41DE* ID_MODEL_FROM_DATABASE=Droid X (PC mode) usb:v22B8p4204* ID_MODEL_FROM_DATABASE=MPx200 Smartphone usb:v22B8p4214* ID_MODEL_FROM_DATABASE=MPc GSM usb:v22B8p4224* ID_MODEL_FROM_DATABASE=MPx220 Smartphone usb:v22B8p4234* ID_MODEL_FROM_DATABASE=MPc CDMA usb:v22B8p4244* ID_MODEL_FROM_DATABASE=MPx100 Smartphone usb:v22B8p4285* ID_MODEL_FROM_DATABASE=Droid X (Mass storage) usb:v22B8p4801* ID_MODEL_FROM_DATABASE=Neptune LTS chipset usb:v22B8p4803* ID_MODEL_FROM_DATABASE=Neptune LTS chipset flash usb:v22B8p4810* ID_MODEL_FROM_DATABASE=Triplet GSM Phone (storage) usb:v22B8p4901* ID_MODEL_FROM_DATABASE=Triplet GSM Phone (P2K) usb:v22B8p4902* ID_MODEL_FROM_DATABASE=Triplet GSM Phone (AT) usb:v22B8p4903* ID_MODEL_FROM_DATABASE=Neptune LTE chipset flash usb:v22B8p4A01* ID_MODEL_FROM_DATABASE=Neptune LTX chipset usb:v22B8p4A03* ID_MODEL_FROM_DATABASE=Neptune LTX chipset flash usb:v22B8p4A32* ID_MODEL_FROM_DATABASE=L6-imode Phone usb:v22B8p5801* ID_MODEL_FROM_DATABASE=Neptune ULS chipset usb:v22B8p5803* ID_MODEL_FROM_DATABASE=Neptune ULS chipset flash usb:v22B8p5901* ID_MODEL_FROM_DATABASE=Neptune VLT chipset usb:v22B8p5903* ID_MODEL_FROM_DATABASE=Neptune VLT chipset flash usb:v22B8p6001* ID_MODEL_FROM_DATABASE=Dalhart EZX usb:v22B8p6003* ID_MODEL_FROM_DATABASE=Dalhart flash usb:v22B8p6004* ID_MODEL_FROM_DATABASE=EZX GSM Phone (CDC Net) usb:v22B8p6006* ID_MODEL_FROM_DATABASE=MOTOROKR E6 usb:v22B8p6008* ID_MODEL_FROM_DATABASE=Dalhart RDL usb:v22B8p6009* ID_MODEL_FROM_DATABASE=EZX GSM Phone (P2K) usb:v22B8p600A* ID_MODEL_FROM_DATABASE=Dalhart EZX config 17 usb:v22B8p600B* ID_MODEL_FROM_DATABASE=Dalhart EZX config 18 usb:v22B8p600C* ID_MODEL_FROM_DATABASE=EZX GSM Phone (USBLAN) usb:v22B8p6021* ID_MODEL_FROM_DATABASE=JUIX chipset usb:v22B8p6023* ID_MODEL_FROM_DATABASE=JUIX chipset flash usb:v22B8p6026* ID_MODEL_FROM_DATABASE=Flash RAM Downloader/miniOS usb:v22B8p6027* ID_MODEL_FROM_DATABASE=USBLAN usb:v22B8p604C* ID_MODEL_FROM_DATABASE=EZX GSM Phone (Storage) usb:v22B8p6101* ID_MODEL_FROM_DATABASE=Talon integrated chipset usb:v22B8p6401* ID_MODEL_FROM_DATABASE=Argon chipset usb:v22B8p6403* ID_MODEL_FROM_DATABASE=Argon chipset flash usb:v22B8p6415* ID_MODEL_FROM_DATABASE=ROKR Z6 (MTP mode) usb:v22B8p6604* ID_MODEL_FROM_DATABASE=Washington CDMA Phone usb:v22B8p6631* ID_MODEL_FROM_DATABASE=CDC Modem usb:v22B8p7001* ID_MODEL_FROM_DATABASE=Q Smartphone usb:v22B8pFE01* ID_MODEL_FROM_DATABASE=StarTAC III MS900 usb:v22B9* ID_VENDOR_FROM_DATABASE=eTurboTouch Technology, Inc. usb:v22B9p0006* ID_MODEL_FROM_DATABASE=Touch Screen usb:v22BA* ID_VENDOR_FROM_DATABASE=Technology Innovation Holdings, Ltd usb:v2304* ID_VENDOR_FROM_DATABASE=Pinnacle Systems, Inc. usb:v2304p0109* ID_MODEL_FROM_DATABASE=Studio PCTV USB (SECAM) usb:v2304p0110* ID_MODEL_FROM_DATABASE=Studio PCTV USB (PAL) usb:v2304p0111* ID_MODEL_FROM_DATABASE=Miro PCTV USB usb:v2304p0112* ID_MODEL_FROM_DATABASE=Studio PCTV USB (NTSC) with FM radio usb:v2304p0201* ID_MODEL_FROM_DATABASE=Systems MovieBox Device usb:v2304p0204* ID_MODEL_FROM_DATABASE=MovieBox USB_B usb:v2304p0205* ID_MODEL_FROM_DATABASE=DVC 150B usb:v2304p0206* ID_MODEL_FROM_DATABASE=Systems MovieBox Deluxe Device usb:v2304p0207* ID_MODEL_FROM_DATABASE=Dazzle DVC90 Video Device usb:v2304p0208* ID_MODEL_FROM_DATABASE=Studio PCTV USB2 usb:v2304p020E* ID_MODEL_FROM_DATABASE=PCTV 200e usb:v2304p020F* ID_MODEL_FROM_DATABASE=PCTV 400e BDA Device usb:v2304p0210* ID_MODEL_FROM_DATABASE=Studio PCTV USB (PAL) with FM radio usb:v2304p0212* ID_MODEL_FROM_DATABASE=Studio PCTV USB (NTSC) usb:v2304p0213* ID_MODEL_FROM_DATABASE=500-USB Device usb:v2304p0214* ID_MODEL_FROM_DATABASE=Studio PCTV USB (PAL) with FM radio usb:v2304p0216* ID_MODEL_FROM_DATABASE=PCTV 60e usb:v2304p0219* ID_MODEL_FROM_DATABASE=PCTV 260e usb:v2304p021A* ID_MODEL_FROM_DATABASE=Dazzle DVC100 Audio Device usb:v2304p021B* ID_MODEL_FROM_DATABASE=Dazzle DVC130/DVC170 usb:v2304p021D* ID_MODEL_FROM_DATABASE=Dazzle DVC130 usb:v2304p021E* ID_MODEL_FROM_DATABASE=Dazzle DVC170 usb:v2304p021F* ID_MODEL_FROM_DATABASE=PCTV Sat HDTV Pro BDA Device usb:v2304p0222* ID_MODEL_FROM_DATABASE=PCTV Sat Pro BDA Device usb:v2304p0223* ID_MODEL_FROM_DATABASE=DazzleTV Sat BDA Device usb:v2304p0225* ID_MODEL_FROM_DATABASE=Remote Kit Infrared Transceiver usb:v2304p0226* ID_MODEL_FROM_DATABASE=PCTV 330e usb:v2304p0227* ID_MODEL_FROM_DATABASE=PCTV for Mac, HD Stick usb:v2304p0228* ID_MODEL_FROM_DATABASE=PCTV DVB-T Flash Stick usb:v2304p0229* ID_MODEL_FROM_DATABASE=PCTV Dual DVB-T 2001e usb:v2304p022A* ID_MODEL_FROM_DATABASE=PCTV 160e usb:v2304p022B* ID_MODEL_FROM_DATABASE=PCTV 71e [Afatech AF9015] usb:v2304p0232* ID_MODEL_FROM_DATABASE=PCTV 170e usb:v2304p0236* ID_MODEL_FROM_DATABASE=PCTV 72e [DiBcom DiB7000PC] usb:v2304p0237* ID_MODEL_FROM_DATABASE=PCTV 73e [DiBcom DiB7000PC] usb:v2304p023A* ID_MODEL_FROM_DATABASE=PCTV 801e usb:v2304p023B* ID_MODEL_FROM_DATABASE=PCTV 801e SE usb:v2304p023D* ID_MODEL_FROM_DATABASE=PCTV 340e usb:v2304p023E* ID_MODEL_FROM_DATABASE=PCTV 340e SE usb:v2304p0300* ID_MODEL_FROM_DATABASE=Studio Linx Video input cable (NTSC) usb:v2304p0301* ID_MODEL_FROM_DATABASE=Studio Linx Video input cable (PAL) usb:v2304p0302* ID_MODEL_FROM_DATABASE=Dazzle DVC120 usb:v2304p0419* ID_MODEL_FROM_DATABASE=PCTV Bungee USB (PAL) with FM radio usb:v2304p061D* ID_MODEL_FROM_DATABASE=PCTV Deluxe (NTSC) Device usb:v2304p061E* ID_MODEL_FROM_DATABASE=PCTV Deluxe (PAL) Device usb:v2318* ID_VENDOR_FROM_DATABASE=Shining Technologies, Inc. [hex] usb:v2318p0011* ID_MODEL_FROM_DATABASE=CitiDISK Jr. IDE Enclosure usb:v2341* ID_VENDOR_FROM_DATABASE=Arduino SA usb:v2341p0001* ID_MODEL_FROM_DATABASE=Uno (CDC ACM) usb:v2341p0010* ID_MODEL_FROM_DATABASE=Mega 2560 (CDC ACM) usb:v2341p003B* ID_MODEL_FROM_DATABASE=Serial Adapter (CDC ACM) usb:v2341p003F* ID_MODEL_FROM_DATABASE=Mega ADK (CDC ACM) usb:v2341p0042* ID_MODEL_FROM_DATABASE=Mega 2560 R3 (CDC ACM) usb:v2341p0043* ID_MODEL_FROM_DATABASE=Uno R3 (CDC ACM) usb:v2341p0044* ID_MODEL_FROM_DATABASE=Mega ADK R3 (CDC ACM) usb:v2341p0045* ID_MODEL_FROM_DATABASE=Serial R3 (CDC ACM) usb:v2341p8036* ID_MODEL_FROM_DATABASE=Leonardo (CDC ACM, HID) usb:v2373* ID_VENDOR_FROM_DATABASE=Pumatronix Ltda usb:v2373p0001* ID_MODEL_FROM_DATABASE=5 MegaPixel Digital Still Camera [DSC5M] usb:v2375* ID_VENDOR_FROM_DATABASE=Digit@lway, Inc. usb:v2375p0001* ID_MODEL_FROM_DATABASE=Digital Audio Player usb:v2406* ID_VENDOR_FROM_DATABASE=SANHO Digital Electronics Co., Ltd. usb:v2406p6688* ID_MODEL_FROM_DATABASE=PD7X Portable Storage usb:v2443* ID_VENDOR_FROM_DATABASE=Aessent Technology Ltd usb:v2443p00DC* ID_MODEL_FROM_DATABASE=aes220 FPGA Mini-Module usb:v2478* ID_VENDOR_FROM_DATABASE=Tripp-Lite usb:v2478p2008* ID_MODEL_FROM_DATABASE=U209-000-R Serial Port usb:v248A* ID_VENDOR_FROM_DATABASE=Maxxter usb:v248Ap8366* ID_MODEL_FROM_DATABASE=Wireless Optical Mouse ACT-MUSW-002 usb:v249C* ID_VENDOR_FROM_DATABASE=M2Tech s.r.l. usb:v24E1* ID_VENDOR_FROM_DATABASE=Paratronic usb:v24E1p3001* ID_MODEL_FROM_DATABASE=Adp-usb usb:v24E1p3005* ID_MODEL_FROM_DATABASE=Radius usb:v2632* ID_VENDOR_FROM_DATABASE=TwinMOS usb:v2632p3209* ID_MODEL_FROM_DATABASE=7-in-1 Card Reader usb:v2639* ID_VENDOR_FROM_DATABASE=Xsens usb:v2639p0001* ID_MODEL_FROM_DATABASE=MTi-10 IMU usb:v2639p0002* ID_MODEL_FROM_DATABASE=MTi-20 VRU usb:v2639p0003* ID_MODEL_FROM_DATABASE=MTi-30 AHRS usb:v2639p0011* ID_MODEL_FROM_DATABASE=MTi-100 IMU usb:v2639p0012* ID_MODEL_FROM_DATABASE=MTi-200 VRU usb:v2639p0013* ID_MODEL_FROM_DATABASE=MTi-300 AHRS usb:v2639p0017* ID_MODEL_FROM_DATABASE=MTi-G 7xx GNSS/INS usb:v2639p0100* ID_MODEL_FROM_DATABASE=Body Pack usb:v2639p0101* ID_MODEL_FROM_DATABASE=Awinda Station usb:v2639p0102* ID_MODEL_FROM_DATABASE=Awinda Dongle usb:v2639p0103* ID_MODEL_FROM_DATABASE=Sync Station usb:v2639p0200* ID_MODEL_FROM_DATABASE=MTw usb:v2639pD00D* ID_MODEL_FROM_DATABASE=Wireless Receiver usb:v2650* ID_VENDOR_FROM_DATABASE=Electronics For Imaging, Inc. [hex] usb:v2659* ID_VENDOR_FROM_DATABASE=Sundtek usb:v2659p1101* ID_MODEL_FROM_DATABASE=TNT DVB-T/DAB/DAB+/FM usb:v2659p1201* ID_MODEL_FROM_DATABASE=FM Transmitter/Receiver usb:v2659p1202* ID_MODEL_FROM_DATABASE=MediaTV Analog/FM/DVB-T usb:v2659p1203* ID_MODEL_FROM_DATABASE=MediaTV Analog/FM/DVB-T MiniPCIe usb:v2659p1204* ID_MODEL_FROM_DATABASE=MediaTV Analog/FM/ATSC usb:v2659p1205* ID_MODEL_FROM_DATABASE=SkyTV Ultimate V usb:v2659p1206* ID_MODEL_FROM_DATABASE=MediaTV DVB-T MiniPCIe usb:v2659p1207* ID_MODEL_FROM_DATABASE=Sundtek HD Capture usb:v2659p1208* ID_MODEL_FROM_DATABASE=Sundtek SkyTV Ultimate III usb:v2659p1209* ID_MODEL_FROM_DATABASE=MediaTV Analog/FM/ATSC MiniPCIe usb:v2659p1210* ID_MODEL_FROM_DATABASE=MediaTV Pro III (EU) usb:v2659p1211* ID_MODEL_FROM_DATABASE=MediaTV Pro III (US) usb:v2659p1212* ID_MODEL_FROM_DATABASE=MediaTV Pro III MiniPCIe (EU) usb:v2659p1213* ID_MODEL_FROM_DATABASE=MediaTV Pro III MiniPCIe (US) usb:v2676* ID_VENDOR_FROM_DATABASE=Basler AG usb:v2676pBA02* ID_MODEL_FROM_DATABASE=ace usb:v2730* ID_VENDOR_FROM_DATABASE=Citizen usb:v2730p200F* ID_MODEL_FROM_DATABASE=CT-S310 Label printer usb:v2735* ID_VENDOR_FROM_DATABASE=DigitalWay usb:v2735p0003* ID_MODEL_FROM_DATABASE=MPIO HS100 usb:v2735p1001* ID_MODEL_FROM_DATABASE=MPIO FY200 usb:v2735p1002* ID_MODEL_FROM_DATABASE=MPIO FL100 usb:v2735p1003* ID_MODEL_FROM_DATABASE=MPIO FD100 usb:v2735p1004* ID_MODEL_FROM_DATABASE=MPIO HD200 usb:v2735p1005* ID_MODEL_FROM_DATABASE=MPIO HD300 usb:v2735p1006* ID_MODEL_FROM_DATABASE=MPIO FG100 usb:v2735p1007* ID_MODEL_FROM_DATABASE=MPIO FG130 usb:v2735p1008* ID_MODEL_FROM_DATABASE=MPIO FY300 usb:v2735p1009* ID_MODEL_FROM_DATABASE=MPIO FY400 usb:v2735p100A* ID_MODEL_FROM_DATABASE=MPIO FL300 usb:v2735p100B* ID_MODEL_FROM_DATABASE=MPIO HS200 usb:v2735p100C* ID_MODEL_FROM_DATABASE=MPIO FL350 usb:v2735p100D* ID_MODEL_FROM_DATABASE=MPIO FY500 usb:v2735p100E* ID_MODEL_FROM_DATABASE=MPIO FY500 usb:v2735p100F* ID_MODEL_FROM_DATABASE=MPIO FY600 usb:v2735p1012* ID_MODEL_FROM_DATABASE=MPIO FL400 usb:v2735p1013* ID_MODEL_FROM_DATABASE=MPIO HD400 usb:v2735p1014* ID_MODEL_FROM_DATABASE=MPIO HD400 usb:v2735p1016* ID_MODEL_FROM_DATABASE=MPIO FY700 usb:v2735p1017* ID_MODEL_FROM_DATABASE=MPIO FY700 usb:v2735p1018* ID_MODEL_FROM_DATABASE=MPIO FY800 usb:v2735p1019* ID_MODEL_FROM_DATABASE=MPIO FY800 usb:v2735p101A* ID_MODEL_FROM_DATABASE=MPIO FY900 usb:v2735p101B* ID_MODEL_FROM_DATABASE=MPIO FY900 usb:v2735p102B* ID_MODEL_FROM_DATABASE=MPIO FL500 usb:v2735p102C* ID_MODEL_FROM_DATABASE=MPIO FL500 usb:v2735p103F* ID_MODEL_FROM_DATABASE=MPIO FY570 usb:v2735p1040* ID_MODEL_FROM_DATABASE=MPIO FY570 usb:v2735p1041* ID_MODEL_FROM_DATABASE=MPIO FY670 usb:v2735p1042* ID_MODEL_FROM_DATABASE=MPIO FY670 usb:v2735p1043* ID_MODEL_FROM_DATABASE=HCT HMD-180A usb:v2735p1044* ID_MODEL_FROM_DATABASE=HCT HMD-180A usb:v2770* ID_VENDOR_FROM_DATABASE=NHJ, Ltd usb:v2770p0A01* ID_MODEL_FROM_DATABASE=ScanJet 4600 series usb:v2770p905C* ID_MODEL_FROM_DATABASE=Che-Ez Snap SNAP-U/Digigr8/Soundstar TDC-35 usb:v2770p9060* ID_MODEL_FROM_DATABASE=A130 usb:v2770p9120* ID_MODEL_FROM_DATABASE=Che-ez! Snap / iClick Tiny VGA Digital Camera usb:v2770p9130* ID_MODEL_FROM_DATABASE=TCG 501 usb:v2770p913C* ID_MODEL_FROM_DATABASE=Argus DC-1730 usb:v2770p9150* ID_MODEL_FROM_DATABASE=Mini Cam usb:v2770p9153* ID_MODEL_FROM_DATABASE=iClick 5X usb:v2770p915D* ID_MODEL_FROM_DATABASE=Cyberpix S-210S / Little Tikes My Real Digital Camera usb:v2770p930B* ID_MODEL_FROM_DATABASE=CCD Webcam(PC370R) usb:v2770p930C* ID_MODEL_FROM_DATABASE=CCD Webcam(PC370R) usb:v27B8* ID_VENDOR_FROM_DATABASE=ThingM usb:v27B8p01ED* ID_MODEL_FROM_DATABASE=blink(1) usb:v2821* ID_VENDOR_FROM_DATABASE=ASUSTek Computer Inc. usb:v2821p0161* ID_MODEL_FROM_DATABASE=WL-161 802.11b Wireless Adapter [SiS 162U] usb:v2821p160F* ID_MODEL_FROM_DATABASE=WL-160g 802.11g Wireless Adapter [Envara WiND512] usb:v2821p3300* ID_MODEL_FROM_DATABASE=WL-140 / Hawking HWU36D 802.11b Wireless Adapter [Intersil PRISM 3] usb:v2899* ID_VENDOR_FROM_DATABASE=Toptronic Industrial Co., Ltd usb:v2899p012C* ID_MODEL_FROM_DATABASE=Camera Device usb:v289B* ID_VENDOR_FROM_DATABASE=Dracal/Raphnet technologies usb:v289Bp0001* ID_MODEL_FROM_DATABASE=Gamecube/N64 controller v2.2 usb:v289Bp0002* ID_MODEL_FROM_DATABASE=2nes2snes usb:v289Bp0003* ID_MODEL_FROM_DATABASE=4nes4snes usb:v289Bp0004* ID_MODEL_FROM_DATABASE=Gamecube/N64 controller v2.3 usb:v289Bp0005* ID_MODEL_FROM_DATABASE=Saturn (Joystick mode) usb:v289Bp0006* ID_MODEL_FROM_DATABASE=Saturn (Mouse mode) usb:v289Bp0007* ID_MODEL_FROM_DATABASE=Famicom controller usb:v289Bp0008* ID_MODEL_FROM_DATABASE=Dreamcast (Joystick mode) usb:v289Bp0009* ID_MODEL_FROM_DATABASE=Dreamcast (Mouse mode) usb:v289Bp000A* ID_MODEL_FROM_DATABASE=Dreamcast (Keyboard mode) usb:v289Bp000B* ID_MODEL_FROM_DATABASE=Gamecube/N64 controller v2.9 (Keyboard mode) usb:v289Bp000C* ID_MODEL_FROM_DATABASE=Gamecube/N64 controller v2.9 (Joystick mode) usb:v289Bp0100* ID_MODEL_FROM_DATABASE=Dual-relay board usb:v289Bp0500* ID_MODEL_FROM_DATABASE=Energy meter usb:v289Bp0502* ID_MODEL_FROM_DATABASE=Precision barometer usb:v2931* ID_VENDOR_FROM_DATABASE=Jolla Oy usb:v2931p0A01* ID_MODEL_FROM_DATABASE=Jolla Phone MTP usb:v2931p0A02* ID_MODEL_FROM_DATABASE=Jolla Phone Developer usb:v2931p0A05* ID_MODEL_FROM_DATABASE=Jolla PC connection usb:v2931p0AFE* ID_MODEL_FROM_DATABASE=Jolla charging only usb:v2A03* ID_VENDOR_FROM_DATABASE=dog hunter AG usb:v2A03p0001* ID_MODEL_FROM_DATABASE=Linino ONE (bootloader) usb:v2A03p0036* ID_MODEL_FROM_DATABASE=Arduino Leonardo (bootloader) usb:v2A03p0037* ID_MODEL_FROM_DATABASE=Arduino Micro (bootloader) usb:v2A03p0038* ID_MODEL_FROM_DATABASE=Arduino Robot Control (bootloader) usb:v2A03p0039* ID_MODEL_FROM_DATABASE=Arduino Robot Motor (bootloader) usb:v2A03p003A* ID_MODEL_FROM_DATABASE=Arduino Micro ADK rev3 (bootloader) usb:v2A03p003B* ID_MODEL_FROM_DATABASE=Arduino Serial usb:v2A03p003C* ID_MODEL_FROM_DATABASE=Arduino Explora (bootloader) usb:v2A03p003D* ID_MODEL_FROM_DATABASE=Arduino Due (usb2serial) usb:v2A03p003E* ID_MODEL_FROM_DATABASE=Arduino Due usb:v2A03p0041* ID_MODEL_FROM_DATABASE=Arduino Yun (bootloader) usb:v2A03p0042* ID_MODEL_FROM_DATABASE=Arduino Mega 2560 Rev3 usb:v2A03p0043* ID_MODEL_FROM_DATABASE=Arduino Uno Rev3 usb:v2A03p004D* ID_MODEL_FROM_DATABASE=Arduino Zero Pro (bootloader) usb:v2A03p8001* ID_MODEL_FROM_DATABASE=Linino ONE (CDC ACM) usb:v2A03p8036* ID_MODEL_FROM_DATABASE=Arduino Leonardo (CDC ACM) usb:v2A03p8037* ID_MODEL_FROM_DATABASE=Arduino Micro (CDC ACM) usb:v2A03p8038* ID_MODEL_FROM_DATABASE=Arduino Robot Control (CDC ACM) usb:v2A03p8039* ID_MODEL_FROM_DATABASE=Arduino Robot Motor (CDC ACM) usb:v2A03p803A* ID_MODEL_FROM_DATABASE=Arduino Micro ADK rev3 (CDC ACM) usb:v2A03p803C* ID_MODEL_FROM_DATABASE=Arduino Explora (CDC ACM) usb:v2A03p8041* ID_MODEL_FROM_DATABASE=Arduino Yun (CDC ACM) usb:v2A03p804D* ID_MODEL_FROM_DATABASE=Arduino Zero Pro (CDC ACM) usb:v2A37* ID_VENDOR_FROM_DATABASE=RTD Embedded Technologies, Inc. usb:v2A37p5110* ID_MODEL_FROM_DATABASE=UPS35110/UPS25110 usb:v2A45* ID_VENDOR_FROM_DATABASE=Meizu Corp. usb:v2A45p0001* ID_MODEL_FROM_DATABASE=MX Phone (BICR) usb:v2A45p0C02* ID_MODEL_FROM_DATABASE=MX Phone (MTP & ADB) usb:v2A45p0C03* ID_MODEL_FROM_DATABASE=MX Phone (BICR & ADB) usb:v2A45p2008* ID_MODEL_FROM_DATABASE=MX Phone (MTP) usb:v2A45p200A* ID_MODEL_FROM_DATABASE=MX Phone (MTP & ACM & ADB) usb:v2A45p200B* ID_MODEL_FROM_DATABASE=MX Phone (PTP) usb:v2A45p200C* ID_MODEL_FROM_DATABASE=MX Phone (PTP & ADB) usb:v2A45p2012* ID_MODEL_FROM_DATABASE=MX Phone (MTP & ACM) usb:v2C02* ID_VENDOR_FROM_DATABASE=Planex Communications usb:v2C02p14EA* ID_MODEL_FROM_DATABASE=GW-US11H WLAN usb:v2C1A* ID_VENDOR_FROM_DATABASE=Dolphin Peripherals usb:v2C1Ap0000* ID_MODEL_FROM_DATABASE=Wireless Optical Mouse usb:v2FB2* ID_VENDOR_FROM_DATABASE=Fujitsu, Ltd usb:v3125* ID_VENDOR_FROM_DATABASE=Eagletron usb:v3125p0001* ID_MODEL_FROM_DATABASE=TrackerPod Camera Stand usb:v3136* ID_VENDOR_FROM_DATABASE=Navini Networks usb:v3176* ID_VENDOR_FROM_DATABASE=Whanam Electronics Co., Ltd usb:v3195* ID_VENDOR_FROM_DATABASE=Link Instruments usb:v3195pF190* ID_MODEL_FROM_DATABASE=MSO-19 usb:v3195pF280* ID_MODEL_FROM_DATABASE=MSO-28 usb:v3195pF281* ID_MODEL_FROM_DATABASE=MSO-28 usb:v3275* ID_VENDOR_FROM_DATABASE=VidzMedia Pte Ltd usb:v3275p4FB1* ID_MODEL_FROM_DATABASE=MonsterTV P2H usb:v3333* ID_VENDOR_FROM_DATABASE=InLine usb:v3333p3333* ID_MODEL_FROM_DATABASE=2 port KVM switch model 60652K usb:v3334* ID_VENDOR_FROM_DATABASE=AEI usb:v3334p1701* ID_MODEL_FROM_DATABASE=Fast Ethernet usb:v3340* ID_VENDOR_FROM_DATABASE=Yakumo usb:v3340p043A* ID_MODEL_FROM_DATABASE=Mio A701 DigiWalker PPCPhone usb:v3340p0E3A* ID_MODEL_FROM_DATABASE=Pocket PC 300 GPS SL / Typhoon MyGuide 3500 usb:v3340pA0A3* ID_MODEL_FROM_DATABASE=deltaX 5 BT (D) PDA usb:v3344* ID_VENDOR_FROM_DATABASE=Leaguer Microelectronics (LME) usb:v3344p3744* ID_MODEL_FROM_DATABASE=OEM PC Remote usb:v3504* ID_VENDOR_FROM_DATABASE=Micro Star usb:v3504pF110* ID_MODEL_FROM_DATABASE=Security Key usb:v3538* ID_VENDOR_FROM_DATABASE=Power Quotient International Co., Ltd usb:v3538p0001* ID_MODEL_FROM_DATABASE=Travel Flash usb:v3538p0015* ID_MODEL_FROM_DATABASE=Mass Storge Device usb:v3538p0022* ID_MODEL_FROM_DATABASE=Hi-Speed Mass Storage Device usb:v3538p0042* ID_MODEL_FROM_DATABASE=Cool Drive U339 Flash Disk usb:v3538p0054* ID_MODEL_FROM_DATABASE=Flash Drive (2GB) usb:v3579* ID_VENDOR_FROM_DATABASE=DIVA usb:v3579p6901* ID_MODEL_FROM_DATABASE=Media Reader usb:v357D* ID_VENDOR_FROM_DATABASE=Sharkoon usb:v357Dp7788* ID_MODEL_FROM_DATABASE=QuickPort XT usb:v3636* ID_VENDOR_FROM_DATABASE=InVibro usb:v3838* ID_VENDOR_FROM_DATABASE=WEM usb:v3838p0001* ID_MODEL_FROM_DATABASE=5-in-1 Card Reader usb:v3923* ID_VENDOR_FROM_DATABASE=National Instruments Corp. usb:v3923p12C0* ID_MODEL_FROM_DATABASE=DAQPad-6020E usb:v3923p12D0* ID_MODEL_FROM_DATABASE=DAQPad-6507 usb:v3923p12E0* ID_MODEL_FROM_DATABASE=NI 4350 usb:v3923p12F0* ID_MODEL_FROM_DATABASE=NI 5102 usb:v3923p1750* ID_MODEL_FROM_DATABASE=DAQPad-6508 usb:v3923p17B0* ID_MODEL_FROM_DATABASE=USB-ISA-Bridge usb:v3923p1820* ID_MODEL_FROM_DATABASE=DAQPad-6020E (68 pin I/O) usb:v3923p1830* ID_MODEL_FROM_DATABASE=DAQPad-6020E (BNC) usb:v3923p1F00* ID_MODEL_FROM_DATABASE=DAQPad-6024E usb:v3923p1F10* ID_MODEL_FROM_DATABASE=DAQPad-6024E usb:v3923p1F20* ID_MODEL_FROM_DATABASE=DAQPad-6025E usb:v3923p1F30* ID_MODEL_FROM_DATABASE=DAQPad-6025E usb:v3923p1F40* ID_MODEL_FROM_DATABASE=DAQPad-6036E usb:v3923p1F50* ID_MODEL_FROM_DATABASE=DAQPad-6036E usb:v3923p2F80* ID_MODEL_FROM_DATABASE=DAQPad-6052E usb:v3923p2F90* ID_MODEL_FROM_DATABASE=DAQPad-6052E usb:v3923p702B* ID_MODEL_FROM_DATABASE=GPIB-USB-B usb:v3923p703C* ID_MODEL_FROM_DATABASE=USB-485 RS485 Cable usb:v3923p709B* ID_MODEL_FROM_DATABASE=GPIB-USB-HS usb:v3923p7254* ID_MODEL_FROM_DATABASE=NI MIO (data acquisition card) firmware updater usb:v3923p729E* ID_MODEL_FROM_DATABASE=USB-6251 (OEM) data acquisition card usb:v40BB* ID_VENDOR_FROM_DATABASE=I-O Data usb:v40BBp0A09* ID_MODEL_FROM_DATABASE=USB2.0-SCSI Bridge USB2-SC usb:v4101* ID_VENDOR_FROM_DATABASE=i-rocks usb:v4101p1301* ID_MODEL_FROM_DATABASE=IR-2510 usb phone usb:v4102* ID_VENDOR_FROM_DATABASE=iRiver, Ltd. usb:v4102p1001* ID_MODEL_FROM_DATABASE=iFP-100 series mp3 player usb:v4102p1003* ID_MODEL_FROM_DATABASE=iFP-300 series mp3 player usb:v4102p1005* ID_MODEL_FROM_DATABASE=iFP-500 series mp3 player usb:v4102p1007* ID_MODEL_FROM_DATABASE=iFP-700 series mp3/ogg vorbis player usb:v4102p1008* ID_MODEL_FROM_DATABASE=iFP-800 series mp3/ogg vorbis player usb:v4102p100A* ID_MODEL_FROM_DATABASE=iFP-1000 series mp3/ogg vorbis player usb:v4102p1014* ID_MODEL_FROM_DATABASE=T20 series mp3/ogg vorbis player (ums firmware) usb:v4102p1019* ID_MODEL_FROM_DATABASE=T30 usb:v4102p1034* ID_MODEL_FROM_DATABASE=T60 usb:v4102p1040* ID_MODEL_FROM_DATABASE=M1Player usb:v4102p1041* ID_MODEL_FROM_DATABASE=E100 (ums) usb:v4102p1101* ID_MODEL_FROM_DATABASE=iFP-100 series mp3 player (ums firmware) usb:v4102p1103* ID_MODEL_FROM_DATABASE=iFP-300 series mp3 player (ums firmware) usb:v4102p1105* ID_MODEL_FROM_DATABASE=iFP-500 series mp3 player (ums firmware) usb:v4102p1113* ID_MODEL_FROM_DATABASE=T10 (alternate) usb:v4102p1117* ID_MODEL_FROM_DATABASE=T10 usb:v4102p1119* ID_MODEL_FROM_DATABASE=T30 series mp3/ogg/wma player usb:v4102p1141* ID_MODEL_FROM_DATABASE=E100 (mtp) usb:v4102p2002* ID_MODEL_FROM_DATABASE=H10 6GB usb:v4102p2101* ID_MODEL_FROM_DATABASE=H10 20GB (mtp) usb:v4102p2102* ID_MODEL_FROM_DATABASE=H10 5GB (mtp) usb:v4102p2105* ID_MODEL_FROM_DATABASE=H10 5/6GB (mtp) usb:v413C* ID_VENDOR_FROM_DATABASE=Dell Computer Corp. usb:v413Cp0000* ID_MODEL_FROM_DATABASE=DRAC 5 Virtual Keyboard and Mouse usb:v413Cp0001* ID_MODEL_FROM_DATABASE=DRAC 5 Virtual Media usb:v413Cp0058* ID_MODEL_FROM_DATABASE=Port Replicator usb:v413Cp1001* ID_MODEL_FROM_DATABASE=Keyboard Hub usb:v413Cp1002* ID_MODEL_FROM_DATABASE=Keyboard Hub usb:v413Cp1003* ID_MODEL_FROM_DATABASE=Keyboard Hub usb:v413Cp1005* ID_MODEL_FROM_DATABASE=Multimedia Pro Keyboard Hub usb:v413Cp2001* ID_MODEL_FROM_DATABASE=Keyboard HID Support usb:v413Cp2002* ID_MODEL_FROM_DATABASE=SK-8125 Keyboard usb:v413Cp2003* ID_MODEL_FROM_DATABASE=Keyboard usb:v413Cp2005* ID_MODEL_FROM_DATABASE=RT7D50 Keyboard usb:v413Cp2010* ID_MODEL_FROM_DATABASE=Keyboard usb:v413Cp2011* ID_MODEL_FROM_DATABASE=Multimedia Pro Keyboard usb:v413Cp2100* ID_MODEL_FROM_DATABASE=SK-3106 Keyboard usb:v413Cp2101* ID_MODEL_FROM_DATABASE=SmartCard Reader Keyboard usb:v413Cp2105* ID_MODEL_FROM_DATABASE=Model L100 Keyboard usb:v413Cp2106* ID_MODEL_FROM_DATABASE=Dell QuietKey Keyboard usb:v413Cp2500* ID_MODEL_FROM_DATABASE=DRAC4 Remote Access Card usb:v413Cp2513* ID_MODEL_FROM_DATABASE=internal USB Hub of E-Port Replicator usb:v413Cp3010* ID_MODEL_FROM_DATABASE=Optical Wheel Mouse usb:v413Cp3012* ID_MODEL_FROM_DATABASE=Optical Wheel Mouse usb:v413Cp3016* ID_MODEL_FROM_DATABASE=Optical 5-Button Wheel Mouse usb:v413Cp3200* ID_MODEL_FROM_DATABASE=Mouse usb:v413Cp4001* ID_MODEL_FROM_DATABASE=Axim X5 usb:v413Cp4002* ID_MODEL_FROM_DATABASE=Axim X3 usb:v413Cp4003* ID_MODEL_FROM_DATABASE=Axim X30 usb:v413Cp4004* ID_MODEL_FROM_DATABASE=Axim Sync usb:v413Cp4005* ID_MODEL_FROM_DATABASE=Axim Sync usb:v413Cp4006* ID_MODEL_FROM_DATABASE=Axim Sync usb:v413Cp4007* ID_MODEL_FROM_DATABASE=Axim Sync usb:v413Cp4008* ID_MODEL_FROM_DATABASE=Axim Sync usb:v413Cp4009* ID_MODEL_FROM_DATABASE=Axim Sync usb:v413Cp4011* ID_MODEL_FROM_DATABASE=Axim X51v usb:v413Cp5103* ID_MODEL_FROM_DATABASE=AIO Printer A940 usb:v413Cp5105* ID_MODEL_FROM_DATABASE=AIO Printer A920 usb:v413Cp5107* ID_MODEL_FROM_DATABASE=AIO Printer A960 usb:v413Cp5109* ID_MODEL_FROM_DATABASE=Photo AIO Printer 922 usb:v413Cp5110* ID_MODEL_FROM_DATABASE=Photo AIO Printer 962 usb:v413Cp5111* ID_MODEL_FROM_DATABASE=Photo AIO Printer 942 usb:v413Cp5112* ID_MODEL_FROM_DATABASE=Photo AIO Printer 924 usb:v413Cp5113* ID_MODEL_FROM_DATABASE=Photo AIO Printer 944 usb:v413Cp5114* ID_MODEL_FROM_DATABASE=Photo AIO Printer 964 usb:v413Cp5115* ID_MODEL_FROM_DATABASE=Photo AIO Printer 926 usb:v413Cp5116* ID_MODEL_FROM_DATABASE=AIO Printer 946 usb:v413Cp5117* ID_MODEL_FROM_DATABASE=Photo AIO Printer 966 usb:v413Cp5118* ID_MODEL_FROM_DATABASE=AIO 810 usb:v413Cp5124* ID_MODEL_FROM_DATABASE=Laser MFP 1815 usb:v413Cp5128* ID_MODEL_FROM_DATABASE=Photo AIO 928 usb:v413Cp5200* ID_MODEL_FROM_DATABASE=Laser Printer usb:v413Cp5202* ID_MODEL_FROM_DATABASE=Printing Support usb:v413Cp5203* ID_MODEL_FROM_DATABASE=Printing Support usb:v413Cp5210* ID_MODEL_FROM_DATABASE=Printing Support usb:v413Cp5211* ID_MODEL_FROM_DATABASE=1110 Laser Printer usb:v413Cp5220* ID_MODEL_FROM_DATABASE=Laser MFP 1600n usb:v413Cp5225* ID_MODEL_FROM_DATABASE=Printing Support usb:v413Cp5226* ID_MODEL_FROM_DATABASE=Printing Support usb:v413Cp5300* ID_MODEL_FROM_DATABASE=Laser Printer usb:v413Cp5400* ID_MODEL_FROM_DATABASE=Laser Printer usb:v413Cp5401* ID_MODEL_FROM_DATABASE=Laser Printer usb:v413Cp5513* ID_MODEL_FROM_DATABASE=WLA3310 Wireless Adapter [Intersil ISL3887] usb:v413Cp5601* ID_MODEL_FROM_DATABASE=Laser Printer 3100cn usb:v413Cp5602* ID_MODEL_FROM_DATABASE=Laser Printer 3000cn usb:v413Cp5631* ID_MODEL_FROM_DATABASE=Laser Printer 5100cn usb:v413Cp5905* ID_MODEL_FROM_DATABASE=Printing Support usb:v413Cp8000* ID_MODEL_FROM_DATABASE=BC02 Bluetooth Adapter usb:v413Cp8010* ID_MODEL_FROM_DATABASE=TrueMobile Bluetooth Module in usb:v413Cp8100* ID_MODEL_FROM_DATABASE=TrueMobile 1180 802.11b Adapter [Intersil PRISM 3] usb:v413Cp8102* ID_MODEL_FROM_DATABASE=TrueMobile 1300 802.11g Wireless Adapter [Intersil ISL3880] usb:v413Cp8103* ID_MODEL_FROM_DATABASE=Wireless 350 Bluetooth usb:v413Cp8104* ID_MODEL_FROM_DATABASE=Wireless 1450 Dual-band (802.11a/b/g) Adapter [Intersil ISL3887] usb:v413Cp8105* ID_MODEL_FROM_DATABASE=U2 in HID - Driver usb:v413Cp8106* ID_MODEL_FROM_DATABASE=Wireless 350 Bluetooth Internal Card in usb:v413Cp8110* ID_MODEL_FROM_DATABASE=Wireless 3xx Bluetooth Internal Card usb:v413Cp8111* ID_MODEL_FROM_DATABASE=Wireless 3xx Bluetooth Internal Card in usb:v413Cp8114* ID_MODEL_FROM_DATABASE=Wireless 5700 Mobile Broadband (CDMA EV-DO) Minicard Modem usb:v413Cp8115* ID_MODEL_FROM_DATABASE=Wireless 5500 Mobile Broadband (3G HSDPA) Minicard Modem usb:v413Cp8116* ID_MODEL_FROM_DATABASE=Wireless 5505 Mobile Broadband (3G HSDPA) Minicard Modem usb:v413Cp8117* ID_MODEL_FROM_DATABASE=Wireless 5700 Mobile Broadband (CDMA EV-DO) Expresscard Modem usb:v413Cp8118* ID_MODEL_FROM_DATABASE=Wireless 5510 Mobile Broadband (3G HSDPA) Expresscard Status Port usb:v413Cp8120* ID_MODEL_FROM_DATABASE=Bluetooth adapter usb:v413Cp8121* ID_MODEL_FROM_DATABASE=Eastfold in HID usb:v413Cp8122* ID_MODEL_FROM_DATABASE=Eastfold in DFU usb:v413Cp8123* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v413Cp8124* ID_MODEL_FROM_DATABASE=eHome Infrared Receiver usb:v413Cp8126* ID_MODEL_FROM_DATABASE=Wireless 355 Bluetooth usb:v413Cp8127* ID_MODEL_FROM_DATABASE=Wireless 355 Module with Bluetooth 2.0 + EDR Technology. usb:v413Cp8128* ID_MODEL_FROM_DATABASE=Wireless 5700-Sprint Mobile Broadband (CDMA EV-DO) Mini-Card Status Port usb:v413Cp8129* ID_MODEL_FROM_DATABASE=Wireless 5700-Telus Mobile Broadband (CDMA EV-DO) Mini-Card Status Port usb:v413Cp8131* ID_MODEL_FROM_DATABASE=Wireless 360 Bluetooth 2.0 + EDR module. usb:v413Cp8133* ID_MODEL_FROM_DATABASE=Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port usb:v413Cp8134* ID_MODEL_FROM_DATABASE=Wireless 5720 Sprint Mobile Broadband (EVDO Rev-A) Minicard Status Port usb:v413Cp8135* ID_MODEL_FROM_DATABASE=Wireless 5720 TELUS Mobile Broadband (EVDO Rev-A) Minicard Diagnostics Port usb:v413Cp8136* ID_MODEL_FROM_DATABASE=Wireless 5520 Cingular Mobile Broadband (3G HSDPA) Minicard Diagnostics Port usb:v413Cp8137* ID_MODEL_FROM_DATABASE=Wireless 5520 Voda L Mobile Broadband (3G HSDPA) Minicard Status Port usb:v413Cp8138* ID_MODEL_FROM_DATABASE=Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard EAP-SIM Port usb:v413Cp8140* ID_MODEL_FROM_DATABASE=Wireless 360 Bluetooth usb:v413Cp8142* ID_MODEL_FROM_DATABASE=Mobile 360 in DFU usb:v413Cp8147* ID_MODEL_FROM_DATABASE=F3507g Mobile Broadband Module usb:v413Cp8156* ID_MODEL_FROM_DATABASE=Wireless 370 Bluetooth Mini-card usb:v413Cp8157* ID_MODEL_FROM_DATABASE=Integrated Keyboard usb:v413Cp8158* ID_MODEL_FROM_DATABASE=Integrated Touchpad / Trackstick usb:v413Cp8160* ID_MODEL_FROM_DATABASE=Wireless 365 Bluetooth usb:v413Cp8161* ID_MODEL_FROM_DATABASE=Integrated Keyboard usb:v413Cp8162* ID_MODEL_FROM_DATABASE=Integrated Touchpad [Synaptics] usb:v413Cp8171* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) usb:v413Cp8172* ID_MODEL_FROM_DATABASE=Gobi Wireless Modem usb:v413Cp8183* ID_MODEL_FROM_DATABASE=F3607gw Mobile Broadband Module usb:v413Cp8184* ID_MODEL_FROM_DATABASE=F3607gw v2 Mobile Broadband Module usb:v413Cp8185* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem (QDL mode) usb:v413Cp8186* ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem usb:v413Cp8187* ID_MODEL_FROM_DATABASE=DW375 Bluetooth Module usb:v413Cp8501* ID_MODEL_FROM_DATABASE=Bluetooth Adapter usb:v413Cp9500* ID_MODEL_FROM_DATABASE=USB CP210x UART Bridge Controller [DW700] usb:v413CpA001* ID_MODEL_FROM_DATABASE=Hub usb:v413CpA005* ID_MODEL_FROM_DATABASE=Internal 2.0 Hub usb:v413CpA700* ID_MODEL_FROM_DATABASE=Hub (in 1905FP LCD Monitor) usb:v4146* ID_VENDOR_FROM_DATABASE=USBest Technology usb:v4146p9281* ID_MODEL_FROM_DATABASE=Iomega Micro Mini 128MB Flash Drive usb:v4146pBA01* ID_MODEL_FROM_DATABASE=Intuix Flash Drive usb:v4168* ID_VENDOR_FROM_DATABASE=Targus usb:v4168p1010* ID_MODEL_FROM_DATABASE=Wireless Compact Laser Mouse usb:v4242* ID_VENDOR_FROM_DATABASE=USB Design by Example usb:v4242p4201* ID_MODEL_FROM_DATABASE=Buttons and Lights HID device usb:v4242p4220* ID_MODEL_FROM_DATABASE=Echo 1 Camera usb:v4255* ID_VENDOR_FROM_DATABASE=GoPro usb:v4255p1000* ID_MODEL_FROM_DATABASE=9FF2 [Digital Photo Display] usb:v4255p2000* ID_MODEL_FROM_DATABASE=HD2-14 [Hero 2 Camera] usb:v4317* ID_VENDOR_FROM_DATABASE=Broadcom Corp. usb:v4317p0700* ID_MODEL_FROM_DATABASE=U.S. Robotics USR5426 802.11g Adapter usb:v4317p0701* ID_MODEL_FROM_DATABASE=U.S. Robotics USR5425 Wireless MAXg Adapter usb:v4317p0711* ID_MODEL_FROM_DATABASE=Belkin F5D7051 v3000 802.11g usb:v4317p0720* ID_MODEL_FROM_DATABASE=Dynex DX-BUSB usb:v4348* ID_VENDOR_FROM_DATABASE=WinChipHead usb:v4348p5523* ID_MODEL_FROM_DATABASE=USB->RS 232 adapter with Prolifec PL 2303 chipset usb:v4348p5537* ID_MODEL_FROM_DATABASE=13.56Mhz RFID Card Reader and Writer usb:v4348p5584* ID_MODEL_FROM_DATABASE=CH34x printer adapter cable usb:v4572* ID_VENDOR_FROM_DATABASE=Shuttle, Inc. usb:v4572p4572* ID_MODEL_FROM_DATABASE=Shuttle PN31 Remote usb:v4586* ID_VENDOR_FROM_DATABASE=Panram usb:v4586p1026* ID_MODEL_FROM_DATABASE=Crystal Bar Flash Drive usb:v4670* ID_VENDOR_FROM_DATABASE=EMS Production usb:v4670p9394* ID_MODEL_FROM_DATABASE=Game Cube USB Memory Adaptor 64M usb:v4752* ID_VENDOR_FROM_DATABASE=Miditech usb:v4752p0011* ID_MODEL_FROM_DATABASE=Midistart-2 usb:v4757* ID_VENDOR_FROM_DATABASE=GW Instek usb:v4757p2009* ID_MODEL_FROM_DATABASE=PEL-2000 Series Electronic Load (CDC) usb:v4757p2010* ID_MODEL_FROM_DATABASE=PEL-2000 Series Electronic Load (CDC) usb:v4766* ID_VENDOR_FROM_DATABASE=Aceeca usb:v4766p0001* ID_MODEL_FROM_DATABASE=MEZ1000 RDA usb:v4855* ID_VENDOR_FROM_DATABASE=Memorex usb:v4855p7288* ID_MODEL_FROM_DATABASE=Ultra Traveldrive 160G 2.5" HDD usb:v4971* ID_VENDOR_FROM_DATABASE=SimpleTech usb:v4971pCB01* ID_MODEL_FROM_DATABASE=SP-U25/120G usb:v4971pCE17* ID_MODEL_FROM_DATABASE=1TB SimpleDrive II USB External Hard Drive usb:v4D46* ID_VENDOR_FROM_DATABASE=Musical Fidelity usb:v4D46p0001* ID_MODEL_FROM_DATABASE=V-Link usb:v4D46p0002* ID_MODEL_FROM_DATABASE=V-DAC II usb:v5032* ID_VENDOR_FROM_DATABASE=Grandtec usb:v5032p0BB8* ID_MODEL_FROM_DATABASE=Grandtec USB1.1 DVB-T (cold) usb:v5032p0BB9* ID_MODEL_FROM_DATABASE=Grandtec USB1.1 DVB-T (warm) usb:v5032p0FA0* ID_MODEL_FROM_DATABASE=Grandtec USB1.1 DVB-T (cold) usb:v5032p0FA1* ID_MODEL_FROM_DATABASE=Grandtec USB1.1 DVB-T (warm) usb:v5041* ID_VENDOR_FROM_DATABASE=Linksys (?) usb:v5041p2234* ID_MODEL_FROM_DATABASE=WUSB54G v1 802.11g Adapter [Intersil ISL3886] usb:v5041p2235* ID_MODEL_FROM_DATABASE=WUSB54GP v1 802.11g Adapter [Intersil ISL3886] usb:v50C2* ID_VENDOR_FROM_DATABASE=Averatec (?) usb:v50C2p4013* ID_MODEL_FROM_DATABASE=WLAN Adapter usb:v5173* ID_VENDOR_FROM_DATABASE=Sweex usb:v5173p1809* ID_MODEL_FROM_DATABASE=ZD1211 usb:v5219* ID_VENDOR_FROM_DATABASE=I-Tetra usb:v5219p1001* ID_MODEL_FROM_DATABASE=Cetus CDC Device usb:v5345* ID_VENDOR_FROM_DATABASE=Owon usb:v5345p1234* ID_MODEL_FROM_DATABASE=PDS6062T Oscilloscope usb:v534C* ID_VENDOR_FROM_DATABASE=SatoshiLabs usb:v534Cp0001* ID_MODEL_FROM_DATABASE=Bitcoin Wallet [TREZOR] usb:v5354* ID_VENDOR_FROM_DATABASE=Meyer Instruments (MIS) usb:v5354p0017* ID_MODEL_FROM_DATABASE=PAXcam2 usb:v544D* ID_VENDOR_FROM_DATABASE=Transmeta Corp. usb:v5543* ID_VENDOR_FROM_DATABASE=UC-Logic Technology Corp. usb:v5543p0002* ID_MODEL_FROM_DATABASE=SuperPen WP3325U Tablet usb:v5543p0003* ID_MODEL_FROM_DATABASE=Tablet WP4030U usb:v5543p0004* ID_MODEL_FROM_DATABASE=Tablet WP5540U usb:v5543p0005* ID_MODEL_FROM_DATABASE=Tablet WP8060U usb:v5543p0041* ID_MODEL_FROM_DATABASE=Genius PenSketch 6x8 Tablet usb:v5543p0042* ID_MODEL_FROM_DATABASE=Tablet PF1209 usb:v5543p0064* ID_MODEL_FROM_DATABASE=Aiptek HyperPen 10000U usb:v5555* ID_VENDOR_FROM_DATABASE=Epiphan Systems Inc. usb:v5555p1110* ID_MODEL_FROM_DATABASE=VGA2USB usb:v5555p1120* ID_MODEL_FROM_DATABASE=KVM2USB usb:v5555p2222* ID_MODEL_FROM_DATABASE=DVI2USB usb:v5555p3333* ID_MODEL_FROM_DATABASE=VGA2USB Pro usb:v5555p3337* ID_MODEL_FROM_DATABASE=KVM2USB Pro usb:v5555p3340* ID_MODEL_FROM_DATABASE=VGA2USB LR usb:v5555p3344* ID_MODEL_FROM_DATABASE=KVM2USB LR usb:v5555p3411* ID_MODEL_FROM_DATABASE=DVI2USB Solo usb:v5555p3422* ID_MODEL_FROM_DATABASE=DVI2USB Duo usb:v55AA* ID_VENDOR_FROM_DATABASE=OnSpec Electronic, Inc. usb:v55AAp0015* ID_MODEL_FROM_DATABASE=Hard Drive usb:v55AAp0102* ID_MODEL_FROM_DATABASE=SuperDisk usb:v55AAp0103* ID_MODEL_FROM_DATABASE=IDE Hard Drive usb:v55AAp0201* ID_MODEL_FROM_DATABASE=DDI to Reader-19 usb:v55AAp1234* ID_MODEL_FROM_DATABASE=ATAPI Bridge usb:v55AApA103* ID_MODEL_FROM_DATABASE=Sandisk SDDR-55 SmartMedia Card Reader usb:v55AApB000* ID_MODEL_FROM_DATABASE=USB to CompactFlash Card Reader usb:v55AApB004* ID_MODEL_FROM_DATABASE=OnSpec MMC/SD Reader/Writer usb:v55AApB00B* ID_MODEL_FROM_DATABASE=USB to Memory Stick Card Reader usb:v55AApB00C* ID_MODEL_FROM_DATABASE=USB to SmartMedia Card Reader usb:v55AApB012* ID_MODEL_FROM_DATABASE=Mitsumi FA402M 8-in-2 Card Reader usb:v55AApB200* ID_MODEL_FROM_DATABASE=Compact Flash Reader usb:v55AApB204* ID_MODEL_FROM_DATABASE=MMC/ SD Reader usb:v55AApB207* ID_MODEL_FROM_DATABASE=Memory Stick Reader usb:v5654* ID_VENDOR_FROM_DATABASE=Gotview usb:v5654pCA42* ID_MODEL_FROM_DATABASE=MasterHD 3 usb:v5656* ID_VENDOR_FROM_DATABASE=Uni-Trend Group Limited usb:v5656p0832* ID_MODEL_FROM_DATABASE=UT2000/UT3000 Digital Storage Oscilloscope usb:v595A* ID_VENDOR_FROM_DATABASE=IRTOUCHSYSTEMS Co. Ltd. usb:v595Ap0001* ID_MODEL_FROM_DATABASE=Touchscreen usb:v5986* ID_VENDOR_FROM_DATABASE=Acer, Inc usb:v5986p0100* ID_MODEL_FROM_DATABASE=Orbicam usb:v5986p0101* ID_MODEL_FROM_DATABASE=USB2.0 Camera usb:v5986p0102* ID_MODEL_FROM_DATABASE=Crystal Eye Webcam usb:v5986p01A6* ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam usb:v5986p01A7* ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam usb:v5986p01A9* ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam usb:v5986p0200* ID_MODEL_FROM_DATABASE=OrbiCam usb:v5986p0203* ID_MODEL_FROM_DATABASE=BisonCam NB Pro 1300 usb:v5986p0241* ID_MODEL_FROM_DATABASE=BisonCam, NB Pro usb:v5986p02D0* ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam [R5U877] usb:v5986p03D0* ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam [R5U877] usb:v59E3* ID_VENDOR_FROM_DATABASE=Nonolith Labs usb:v5A57* ID_VENDOR_FROM_DATABASE=Zinwell usb:v5A57p0260* ID_MODEL_FROM_DATABASE=RT2570 usb:v5A57p0280* ID_MODEL_FROM_DATABASE=802.11a/b/g/n USB Wireless LAN Card usb:v5A57p0282* ID_MODEL_FROM_DATABASE=802.11b/g/n USB Wireless LAN Card usb:v5A57p0283* ID_MODEL_FROM_DATABASE=802.11b/g/n USB Wireless LAN Card usb:v5A57p0284* ID_MODEL_FROM_DATABASE=802.11a/b/g/n USB Wireless LAN Card usb:v5A57p0290* ID_MODEL_FROM_DATABASE=ZW-N290 802.11n [Realtek RTL8192SU] usb:v5A57p5257* ID_MODEL_FROM_DATABASE=Metronic 495257 wifi 802.11ng usb:v6000* ID_VENDOR_FROM_DATABASE=Beholder International Ltd. usb:v6000pDEC0* ID_MODEL_FROM_DATABASE=TV Wander usb:v6000pDEC1* ID_MODEL_FROM_DATABASE=TV Voyage usb:v601A* ID_VENDOR_FROM_DATABASE=Ingenic Semiconductor Ltd. usb:v601Ap4740* ID_MODEL_FROM_DATABASE=XBurst Jz4740 boot mode usb:v6189* ID_VENDOR_FROM_DATABASE=Sitecom usb:v6189p182D* ID_MODEL_FROM_DATABASE=USB 2.0 Ethernet usb:v6189p2068* ID_MODEL_FROM_DATABASE=USB to serial cable (v2) usb:v6244* ID_VENDOR_FROM_DATABASE=LightingSoft AG usb:v6244p0101* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI5A usb:v6244p0201* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI5C usb:v6244p0300* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI6 Firmware download usb:v6244p0301* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI6C usb:v6244p0302* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI6A usb:v6244p0303* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI6D usb:v6244p0400* ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK1A usb:v6244p0401* ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK1A usb:v6244p0410* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI7 Firmware Download usb:v6244p0411* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI7A usb:v6244p0420* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI8A Firmware Download usb:v6244p0421* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI8A usb:v6244p0430* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI8C Firmware Download usb:v6244p0431* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI8C usb:v6244p0440* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI9A Firmware Download usb:v6244p0441* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI9A usb:v6244p0450* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI9C Firmware Download usb:v6244p0451* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI9C usb:v6244p0460* ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK2 Firmware download usb:v6244p0461* ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK2 usb:v6244p0470* ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK1B Firmware download usb:v6244p0471* ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK1B usb:v6244p0480* ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK3 Firmware download usb:v6244p0481* ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK3 usb:v6244p0490* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI9D Firmware Download usb:v6244p0491* ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI9D usb:v6244p0500* ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK2B Firmware download usb:v6244p0501* ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK2B usb:v6253* ID_VENDOR_FROM_DATABASE=TwinHan Technology Co., Ltd usb:v6253p0100* ID_MODEL_FROM_DATABASE=Ir reciver f. remote control usb:v636C* ID_VENDOR_FROM_DATABASE=CoreLogic, Inc. usb:v6472* ID_VENDOR_FROM_DATABASE=Unknown (Sony?) usb:v6472p01C8* ID_MODEL_FROM_DATABASE=PlayStation Portable [Mass Storage] usb:v6547* ID_VENDOR_FROM_DATABASE=Arkmicro Technologies Inc. usb:v6547p0232* ID_MODEL_FROM_DATABASE=ARK3116 Serial usb:v6615* ID_VENDOR_FROM_DATABASE=IRTOUCHSYSTEMS Co. Ltd. usb:v6615p0001* ID_MODEL_FROM_DATABASE=Touchscreen usb:v6666* ID_VENDOR_FROM_DATABASE=Prototype product Vendor ID usb:v6666p0667* ID_MODEL_FROM_DATABASE=WiseGroup Smart Joy PSX, PS-PC Smart JoyPad usb:v6666p2667* ID_MODEL_FROM_DATABASE=JCOP BlueZ Smartcard reader usb:v6666p8802* ID_MODEL_FROM_DATABASE=SmartJoy Dual Plus PS2 converter usb:v6666p8804* ID_MODEL_FROM_DATABASE=WiseGroup SuperJoy Box 5 usb:v6677* ID_VENDOR_FROM_DATABASE=WiseGroup, Ltd. usb:v6677p8802* ID_MODEL_FROM_DATABASE=SmartJoy Dual Plus PS2 converter usb:v6677p8811* ID_MODEL_FROM_DATABASE=Deluxe Dance Mat usb:v6891* ID_VENDOR_FROM_DATABASE=3Com usb:v6891pA727* ID_MODEL_FROM_DATABASE=3CRUSB10075 802.11bg [ZyDAS ZD1211] usb:v695C* ID_VENDOR_FROM_DATABASE=Opera1 usb:v695Cp3829* ID_MODEL_FROM_DATABASE=Opera1 DVB-S (warm state) usb:v6993* ID_VENDOR_FROM_DATABASE=Yealink Network Technology Co., Ltd. usb:v6993pB001* ID_MODEL_FROM_DATABASE=VoIP Phone usb:v6A75* ID_VENDOR_FROM_DATABASE=Shanghai Jujo Electronics Co., Ltd usb:v7104* ID_VENDOR_FROM_DATABASE=CME (Central Music Co.) usb:v7104p2202* ID_MODEL_FROM_DATABASE=UF5/UF6/UF7/UF8 MIDI Master Keyboard usb:v726C* ID_VENDOR_FROM_DATABASE=StackFoundry LLC usb:v726Cp2149* ID_MODEL_FROM_DATABASE=EntropyKing Random Number Generator usb:v734C* ID_VENDOR_FROM_DATABASE=TBS Technologies China usb:v734Cp5920* ID_MODEL_FROM_DATABASE=Q-Box II DVB-S2 HD usb:v734Cp5928* ID_MODEL_FROM_DATABASE=Q-Box II DVB-S2 HD usb:v7373* ID_VENDOR_FROM_DATABASE=Beijing STONE Technology Co. Ltd. usb:v7373p5740* ID_MODEL_FROM_DATABASE=Intelligent TFT-LCD Module usb:v7392* ID_VENDOR_FROM_DATABASE=Edimax Technology Co., Ltd usb:v7392p7711* ID_MODEL_FROM_DATABASE=EW-7711UTn nLite Wireless Adapter [Ralink RT2870] usb:v7392p7717* ID_MODEL_FROM_DATABASE=EW-7717UN 802.11n Wireless Adapter [Ralink RT2870] usb:v7392p7718* ID_MODEL_FROM_DATABASE=EW-7718UN 802.11n Wireless Adapter [Ralink RT2870] usb:v7392p7722* ID_MODEL_FROM_DATABASE=EW-7722UTn 802.11n Wireless Adapter [Ralink RT307x] usb:v7392p7811* ID_MODEL_FROM_DATABASE=EW-7811Un 802.11n Wireless Adapter [Realtek RTL8188CUS] usb:v8086* ID_VENDOR_FROM_DATABASE=Intel Corp. usb:v8086p0001* ID_MODEL_FROM_DATABASE=AnyPoint (TM) Home Network 1.6 Mbps Wireless Adapter usb:v8086p0044* ID_MODEL_FROM_DATABASE=CPU DRAM Controller usb:v8086p0046* ID_MODEL_FROM_DATABASE=HD Graphics usb:v8086p0100* ID_MODEL_FROM_DATABASE=Personal Audio Player 3000 usb:v8086p0101* ID_MODEL_FROM_DATABASE=Personal Audio Player 3000 usb:v8086p0110* ID_MODEL_FROM_DATABASE=Easy PC Camera usb:v8086p0120* ID_MODEL_FROM_DATABASE=PC Camera CS120 usb:v8086p0180* ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m usb:v8086p0181* ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m usb:v8086p0182* ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m usb:v8086p0186* ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m usb:v8086p0188* ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m usb:v8086p0200* ID_MODEL_FROM_DATABASE=AnyPoint(TM) Wireless II Network 11Mbps Adapter [Atmel AT76C503A] usb:v8086p0431* ID_MODEL_FROM_DATABASE=Intel Pro Video PC Camera usb:v8086p0510* ID_MODEL_FROM_DATABASE=Digital Movie Creator usb:v8086p0630* ID_MODEL_FROM_DATABASE=Pocket PC Camera usb:v8086p0780* ID_MODEL_FROM_DATABASE=CS780 Microphone Input usb:v8086p07D3* ID_MODEL_FROM_DATABASE=BLOB boot loader firmware usb:v8086p0DAD* ID_MODEL_FROM_DATABASE=Cherry MiniatureCard Keyboard usb:v8086p1010* ID_MODEL_FROM_DATABASE=AnyPoint(TM) Home Network 10 Mbps Phoneline Adapter usb:v8086p110A* ID_MODEL_FROM_DATABASE=Bluetooth Controller from (Ericsson P4A) usb:v8086p110B* ID_MODEL_FROM_DATABASE=Bluetooth Controller from (Intel/CSR) usb:v8086p1110* ID_MODEL_FROM_DATABASE=PRO/Wireless LAN Module usb:v8086p1111* ID_MODEL_FROM_DATABASE=PRO/Wireless 2011B 802.11b Adapter [Intersil PRISM 2.5] usb:v8086p1134* ID_MODEL_FROM_DATABASE=Hollister Mobile Monitor usb:v8086p1139* ID_MODEL_FROM_DATABASE=In-Target Probe (ITP) usb:v8086p1234* ID_MODEL_FROM_DATABASE=Prototype Reader/Writer usb:v8086p1403* ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m usb:v8086p1405* ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m usb:v8086p1406* ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m usb:v8086p2448* ID_MODEL_FROM_DATABASE=82801 PCI Bridge usb:v8086p3100* ID_MODEL_FROM_DATABASE=PRO/DSL 3220 Modem - WAN usb:v8086p3101* ID_MODEL_FROM_DATABASE=PRO/DSL 3220 Modem usb:v8086p3240* ID_MODEL_FROM_DATABASE=AnyPoint® 3240 Modem - WAN usb:v8086p3241* ID_MODEL_FROM_DATABASE=AnyPoint® 3240 Modem usb:v8086p8602* ID_MODEL_FROM_DATABASE=Miniature Card Slot usb:v8086p9303* ID_MODEL_FROM_DATABASE=Intel 8x930Hx Hub usb:v8086p9500* ID_MODEL_FROM_DATABASE=CE 9500 DVB-T usb:v8086p9890* ID_MODEL_FROM_DATABASE=82930 Test Board usb:v8086pBEEF* ID_MODEL_FROM_DATABASE=SCM Miniature Card Reader/Writer usb:v8086pC013* ID_MODEL_FROM_DATABASE=Wireless HID Station usb:v8086pF001* ID_MODEL_FROM_DATABASE=XScale PXA27x Bulverde flash usb:v8086pF1A5* ID_MODEL_FROM_DATABASE=Z-U130 [Value Solid State Drive] usb:v8087* ID_VENDOR_FROM_DATABASE=Intel Corp. usb:v8087p0020* ID_MODEL_FROM_DATABASE=Integrated Rate Matching Hub usb:v8087p0024* ID_MODEL_FROM_DATABASE=Integrated Rate Matching Hub usb:v80EE* ID_VENDOR_FROM_DATABASE=VirtualBox usb:v80EEp0021* ID_MODEL_FROM_DATABASE=USB Tablet usb:v8282* ID_VENDOR_FROM_DATABASE=Keio usb:v8282p3201* ID_MODEL_FROM_DATABASE=Retro Adapter usb:v8282p3301* ID_MODEL_FROM_DATABASE=Retro Adapter Mouse usb:v8341* ID_VENDOR_FROM_DATABASE=EGO Systems, Inc. usb:v8341p2000* ID_MODEL_FROM_DATABASE=Flashdisk usb:v8564* ID_VENDOR_FROM_DATABASE=Transcend Information, Inc. usb:v8564p1000* ID_MODEL_FROM_DATABASE=JetFlash usb:v8564p4000* ID_MODEL_FROM_DATABASE=RDF8 usb:v8644* ID_VENDOR_FROM_DATABASE=Intenso GmbG usb:v8644p8003* ID_MODEL_FROM_DATABASE=Micro Line usb:v8644p800B* ID_MODEL_FROM_DATABASE=Micro Line (4GB) usb:v8E06* ID_VENDOR_FROM_DATABASE=CH Products, Inc. usb:v8E06pF700* ID_MODEL_FROM_DATABASE=DT225 Trackball usb:v9016* ID_VENDOR_FROM_DATABASE=Sitecom usb:v9016p182D* ID_MODEL_FROM_DATABASE=WL-022 802.11b Adapter usb:v9022* ID_VENDOR_FROM_DATABASE=TeVii Technology Ltd. usb:v9022pD630* ID_MODEL_FROM_DATABASE=DVB-S S630 usb:v9022pD650* ID_MODEL_FROM_DATABASE=DVB-S2 S650 usb:v9022pD660* ID_MODEL_FROM_DATABASE=DVB-S2 S660 usb:v9148* ID_VENDOR_FROM_DATABASE=GeoLab, Ltd usb:v9148p0004* ID_MODEL_FROM_DATABASE=R3 Compatible Device usb:v9710* ID_VENDOR_FROM_DATABASE=MosChip Semiconductor usb:v9710p7703* ID_MODEL_FROM_DATABASE=MCS7703 Serial Port Adapter usb:v9710p7705* ID_MODEL_FROM_DATABASE=MCS7705 Parallel port adapter usb:v9710p7715* ID_MODEL_FROM_DATABASE=MCS7715 Parallel and serial port adapter usb:v9710p7717* ID_MODEL_FROM_DATABASE=MCS7717 3-port hub with serial and parallel adapter usb:v9710p7720* ID_MODEL_FROM_DATABASE=MCS7720 Dual serial port adapter usb:v9710p7730* ID_MODEL_FROM_DATABASE=MCS7730 10/100 Mbps Ethernet adapter usb:v9710p7780* ID_MODEL_FROM_DATABASE=MCS7780 4Mbps Fast IrDA Adapter usb:v9710p7830* ID_MODEL_FROM_DATABASE=MCS7830 10/100 Mbps Ethernet adapter usb:v9710p7832* ID_MODEL_FROM_DATABASE=MCS7832 10/100 Mbps Ethernet adapter usb:v9710p7840* ID_MODEL_FROM_DATABASE=MCS7820/MCS7840 2/4 port serial adapter usb:v9849* ID_VENDOR_FROM_DATABASE=Bestmedia CD Recordable GmbH & Co. KG usb:v9849p0701* ID_MODEL_FROM_DATABASE=Platinum MyDrive HP usb:v9999* ID_VENDOR_FROM_DATABASE=Odeon usb:v9999p0001* ID_MODEL_FROM_DATABASE=JAF Mobile Phone Flasher Interface usb:v99FA* ID_VENDOR_FROM_DATABASE=Grandtec usb:v99FAp8988* ID_MODEL_FROM_DATABASE=V.cap Camera Device usb:v9AC4* ID_VENDOR_FROM_DATABASE=J. Westhues usb:v9AC4p4B8F* ID_MODEL_FROM_DATABASE=ProxMark-3 RFID Instrument usb:v9E88* ID_VENDOR_FROM_DATABASE=Marvell Semiconductor, Inc. usb:v9E88p9E8F* ID_MODEL_FROM_DATABASE=Plug Computer Basic [SheevaPlug] usb:vA128* ID_VENDOR_FROM_DATABASE=AnMo Electronics Corp. / Dino-Lite (?) usb:vA128p0610* ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + HV7131R) usb:vA128p0611* ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + HV7131R) usb:vA128p0612* ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C120 + HV7131R) usb:vA128p0613* ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + HV7131R) usb:vA128p0614* ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + MI1310/MT9M111) usb:vA128p0615* ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + MI1310/MT9M111) usb:vA128p0616* ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C120 + HV7131R) usb:vA128p0617* ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + MI1310/MT9M111) usb:vA128p0618* ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + HV7131R) usb:vA168* ID_VENDOR_FROM_DATABASE=AnMo Electronics Corporation usb:vA168p0610* ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope usb:vA168p0611* ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope usb:vA168p0613* ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope usb:vA168p0614* ID_MODEL_FROM_DATABASE=Dino-Lite Pro Digital Microscope usb:vA168p0615* ID_MODEL_FROM_DATABASE=Dino-Lite Pro Digital Microscope usb:vA168p0617* ID_MODEL_FROM_DATABASE=Dino-Lite Pro Digital Microscope usb:vA168p0618* ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope usb:vA600* ID_VENDOR_FROM_DATABASE=Asix usb:vA600pE110* ID_MODEL_FROM_DATABASE=OK1ZIA Davac 4.x usb:vA727* ID_VENDOR_FROM_DATABASE=3Com usb:vA727p6893* ID_MODEL_FROM_DATABASE=3CRUSB20075 OfficeConnect Wireless 108Mbps 11g Adapter [Atheros AR5523] usb:vA727p6895* ID_MODEL_FROM_DATABASE=AR5523 usb:vA727p6897* ID_MODEL_FROM_DATABASE=AR5523 usb:vAAAA* ID_VENDOR_FROM_DATABASE=MXT usb:vAAAAp8815* ID_MODEL_FROM_DATABASE=microSD CardReader usb:vABCD* ID_VENDOR_FROM_DATABASE=Unknown usb:vABCDpCDEE* ID_MODEL_FROM_DATABASE=Petcam usb:vB58E* ID_VENDOR_FROM_DATABASE=Blue Microphones usb:vB58Ep9E84* ID_MODEL_FROM_DATABASE=Yeti Stereo Microphone usb:vC216* ID_VENDOR_FROM_DATABASE=Card Device Expert Co., LTD usb:vC216p0180* ID_MODEL_FROM_DATABASE=MSR90 MagStripe reader usb:vC251* ID_VENDOR_FROM_DATABASE=Keil Software, Inc. usb:vC251p2710* ID_MODEL_FROM_DATABASE=ULink usb:vCACE* ID_VENDOR_FROM_DATABASE=CACE Technologies Inc. usb:vCACEp0002* ID_MODEL_FROM_DATABASE=AirPCAP Classic 802.11 packet capture adapter usb:vCACEp0300* ID_MODEL_FROM_DATABASE=AirPcap NX [Atheros AR9001U-(2)NG] usb:vCD12* ID_VENDOR_FROM_DATABASE=SMART TECHNOLOGY INDUSTRIAL LTD. usb:vD208* ID_VENDOR_FROM_DATABASE=Ultimarc usb:vD208p0310* ID_MODEL_FROM_DATABASE=Mini-PAC Arcade Control Interface usb:vD209* ID_VENDOR_FROM_DATABASE=Ultimarc usb:vD209p0301* ID_MODEL_FROM_DATABASE=I-PAC Arcade Control Interface usb:vD209p0501* ID_MODEL_FROM_DATABASE=Ultra-Stik Ultimarc Ultra-Stik Player 1 usb:vD904* ID_VENDOR_FROM_DATABASE=LogiLink usb:vD904p0003* ID_MODEL_FROM_DATABASE=Laser Mouse (ID0009A) usb:vE4E4* ID_VENDOR_FROM_DATABASE=Xorcom Ltd. usb:vE4E4p1130* ID_MODEL_FROM_DATABASE=Astribank series usb:vE4E4p1131* ID_MODEL_FROM_DATABASE=Astribank series usb:vE4E4p1132* ID_MODEL_FROM_DATABASE=Astribank series usb:vE4E4p1140* ID_MODEL_FROM_DATABASE=Astribank series usb:vE4E4p1141* ID_MODEL_FROM_DATABASE=Astribank series usb:vE4E4p1142* ID_MODEL_FROM_DATABASE=Astribank series usb:vE4E4p1150* ID_MODEL_FROM_DATABASE=Astribank series usb:vE4E4p1151* ID_MODEL_FROM_DATABASE=Astribank series usb:vE4E4p1152* ID_MODEL_FROM_DATABASE=Astribank series usb:vE4E4p1160* ID_MODEL_FROM_DATABASE=Astribank 2 series usb:vE4E4p1161* ID_MODEL_FROM_DATABASE=Astribank 2 series usb:vE4E4p1162* ID_MODEL_FROM_DATABASE=Astribank 2 series usb:vEB03* ID_VENDOR_FROM_DATABASE=MakingThings usb:vEB03p0920* ID_MODEL_FROM_DATABASE=Make Controller Kit usb:vEB1A* ID_VENDOR_FROM_DATABASE=eMPIA Technology, Inc. usb:vEB1Ap17DE* ID_MODEL_FROM_DATABASE=KWorld V-Stream XPERT DTV - DVB-T USB cold usb:vEB1Ap17DF* ID_MODEL_FROM_DATABASE=KWorld V-Stream XPERT DTV - DVB-T USB warm usb:vEB1Ap2571* ID_MODEL_FROM_DATABASE=M035 Compact Web Cam usb:vEB1Ap2710* ID_MODEL_FROM_DATABASE=SilverCrest Webcam usb:vEB1Ap2750* ID_MODEL_FROM_DATABASE=ECS Elitegroup G220 integrated Webcam usb:vEB1Ap2761* ID_MODEL_FROM_DATABASE=EeePC 701 integrated Webcam usb:vEB1Ap2776* ID_MODEL_FROM_DATABASE=Combined audio and video input device usb:vEB1Ap2800* ID_MODEL_FROM_DATABASE=Terratec Cinergy 200 usb:vEB1Ap2801* ID_MODEL_FROM_DATABASE=GrabBeeX+ Video Encoder usb:vEB1Ap2863* ID_MODEL_FROM_DATABASE=Video Grabber usb:vEB1Ap2870* ID_MODEL_FROM_DATABASE=Pinnacle PCTV Stick usb:vEB1Ap2881* ID_MODEL_FROM_DATABASE=EM2881 Video Controller usb:vEB1Ap50A3* ID_MODEL_FROM_DATABASE=Gadmei UTV380 TV Box usb:vEB1Ap50A6* ID_MODEL_FROM_DATABASE=Gadmei UTV330 TV Box usb:vEB1ApE355* ID_MODEL_FROM_DATABASE=KWorld DVB-T 355U Digital TV Dongle usb:vEB2A* ID_VENDOR_FROM_DATABASE=KWorld usb:vEF18* ID_VENDOR_FROM_DATABASE=SMART TECHNOLOGY INDUSTRIAL LTD. usb:vF003* ID_VENDOR_FROM_DATABASE=Hewlett Packard usb:vF003p6002* ID_MODEL_FROM_DATABASE=PhotoSmart C500 usb:vF182* ID_VENDOR_FROM_DATABASE=Leap Motion usb:vF182p0003* ID_MODEL_FROM_DATABASE=Controller usb:vF4EC* ID_VENDOR_FROM_DATABASE=Atten Electronics / Siglent Technologies usb:vF4ECpEE38* ID_MODEL_FROM_DATABASE=Digital Storage Oscilloscope usb:vF4ED* ID_VENDOR_FROM_DATABASE=Shenzhen Siglent Co., Ltd. usb:vF4EDpEE37* ID_MODEL_FROM_DATABASE=SDG1010 Waveform Generator usb:vF4EDpEE3A* ID_MODEL_FROM_DATABASE=SDG1010 Waveform Generator (TMC mode) usb:vF766* ID_VENDOR_FROM_DATABASE=Hama usb:vF766p0001* ID_MODEL_FROM_DATABASE=PC-Gamepad "Greystorm" usb:vFC08* ID_VENDOR_FROM_DATABASE=Conrad Electronic SE usb:vFC08p0101* ID_MODEL_FROM_DATABASE=MIDI Cable UA0037 usb:vFFEE* ID_VENDOR_FROM_DATABASE=FNK Tech usb:vFFEEp0100* ID_MODEL_FROM_DATABASE=Card Reader Controller RTS5101/RTS5111/RTS5116 systemd-229/hwdb/60-evdev.hwdb000066400000000000000000000114331265713322000162110ustar00rootroot00000000000000# This file is part of systemd. # # The lookup keys are composed in: # 60-evdev.rules # # Note: The format of the "evdev:" prefix match key is a # contract between the rules file and the hardware data, it might # change in later revisions to support more or better matches, it # is not necessarily expected to be a stable ABI. # # Match string formats: # evdev: # evdev:name::dmi: # # To add local entries, create a new file # /etc/udev/hwdb.d/61-evdev-local.hwdb # and add your rules there. To load the new rules execute (as root): # udevadm hwdb --update # udevadm trigger /dev/input/eventXX # where /dev/input/eventXX is the device in question. If in # doubt, simply use /dev/input/event* to reload all input rules. # # If your changes are generally applicable, preferably send them as a pull # request to # https://github.com/systemd/systemd # or create a bug report on https://github.com/systemd/systemd/issues and # include your new rules, a description of the device, and the output of # udevadm info /dev/input/eventXX. # # Allowed properties are: # EVDEV_ABS_=:::: # # where is the hexadecimal EV_ABS code as listed in linux/input.h # and min, max, res, fuzz, flat are the decimal values to the respective # fields of the struct input_absinfo as listed in linux/input.h. # If a field is missing the field will be left as-is. Not all fields need to # be present. e.g. ::45 sets the resolution to 45 units/mm. # # Sort by brand, model ######################################### # Apple ######################################### # Macbook2,1 (late 2006), single-button touchpad evdev:input:b0003v05ACp021B* EVDEV_ABS_00=256:1471:12 EVDEV_ABS_01=256:831:12 # Macbook5,1 (unibody), aka wellspring3 evdev:input:b0003v05ACp0236* evdev:input:b0003v05ACp0237* evdev:input:b0003v05ACp0238* EVDEV_ABS_00=::92 EVDEV_ABS_01=::90 EVDEV_ABS_35=::92 EVDEV_ABS_36=::90 # Macbook8 (unibody, March 2011) evdev:input:b0003v05ACp0245* evdev:input:b0003v05ACp0246* evdev:input:b0003v05ACp0247* EVDEV_ABS_00=::92 EVDEV_ABS_01=::91 EVDEV_ABS_35=::92 EVDEV_ABS_36=::91 # Macbook8,2 (unibody) evdev:input:b0003v05ACp0252* evdev:input:b0003v05ACp0253* evdev:input:b0003v05ACp0254* EVDEV_ABS_00=::94 EVDEV_ABS_01=::92 EVDEV_ABS_35=::94 EVDEV_ABS_36=::92 # MacbookPro10,1 (unibody, June 2012) evdev:input:b0003v05ACp0259* evdev:input:b0003v05ACp025A* evdev:input:b0003v05ACp025B* # MacbookPro10,2 (unibody, October 2012) evdev:input:b0003v05ACp0259* evdev:input:b0003v05ACp025A* evdev:input:b0003v05ACp025B* EVDEV_ABS_00=::94 EVDEV_ABS_01=::92 EVDEV_ABS_35=::94 EVDEV_ABS_36=::92 ######################################### # ASUS ######################################### # Asus K52JT evdev:name:ETPS/2 Elantech Touchpad:dmi:bvn*:bvr*:bd*:svnASUSTeKComputerInc.:pnK52JT:* EVDEV_ABS_00=::18 EVDEV_ABS_01=::16 EVDEV_ABS_35=::18 EVDEV_ABS_36=::16 ######################################### # Dell ######################################### # Dell Vostro 1510 evdev:name:AlpsPS/2 ALPS GlidePoint*:dmi:bvn*:bvr*:bd*:svnDellInc.:pnVostro1510* EVDEV_ABS_00=::14 EVDEV_ABS_01=::18 # Dell Inspiron N5040 evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnInspironN5040* EVDEV_ABS_00=25:2000:22 EVDEV_ABS_01=0:1351:28 EVDEV_ABS_35=25:2000:22 EVDEV_ABS_36=0:1351:28 # Dell Latitude E6220 evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6220* EVDEV_ABS_00=76:1815:22 EVDEV_ABS_01=131:1330:30 EVDEV_ABS_35=76:1815:22 EVDEV_ABS_36=131:1330:30 ######################################### # Google ######################################### # Chromebook Pixel (2015) - Samus evdev:name:Atmel maXTouch Touch*:dmi:bvn*:bvr*:bd*:svnGOOGLE:pnSamus* EVDEV_ABS_00=::10 EVDEV_ABS_01=::10 EVDEV_ABS_35=::10 EVDEV_ABS_36=::10 ######################################### # HP ######################################### # HP Pavilion dm4 evdev:name:SynPS/2 Synaptics TouchPad*:dmi:*svnHewlett-Packard:pnHPPaviliondm4* EVDEV_ABS_00=1360:5563:47 EVDEV_ABS_01=1269:4618:61 EVDEV_ABS_35=1360:5563:47 EVDEV_ABS_36=1269:4618:61 ######################################### # Lenovo ######################################### # Lenovo X230 series evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*X230* EVDEV_ABS_01=::100 EVDEV_ABS_36=::100 # Lenovo T510 evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*T510* EVDEV_ABS_00=778:6239:72 EVDEV_ABS_01=841:5330:100 EVDEV_ABS_35=778:6239:72 EVDEV_ABS_36=841:5330:100 ######################################### # Samsung ######################################### # Samsung 305V4 evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn305V4A/305V5A* EVDEV_ABS_00=0:2480:28 EVDEV_ABS_01=0:1116:24 EVDEV_ABS_35=0:2480:28 EVDEV_ABS_36=0:1116:24 systemd-229/hwdb/60-keyboard.hwdb000066400000000000000000001501431265713322000167020ustar00rootroot00000000000000# This file is part of systemd. # # Keyboard mapping of scan codes to key codes, and # scan codes to add to the AT keyboard's 'force-release' list. # # The lookup keys are composed in: # 60-keyboard.rules # # Note: The format of the "evdev:" prefix match key is a # contract between the rules file and the hardware data, it might # change in later revisions to support more or better matches, it # is not necessarily expected to be a stable ABI. # # Supported hardware matches are: # - Generic input devices match: # evdev:input:bZZZZvYYYYpXXXXeWWWW-VVVV # This matches on the kernel modalias of the input-device, mainly: # ZZZZ is the bus-id (see /usr/include/linux/input.h BUS_*), YYYY, XXXX and # WWW are the 4-digit hex uppercase vendor, product and version ID and VVVV # is an arbitrary length input-modalias describing the device capabilities. # # - AT keyboard DMI data matches: # evdev:atkbd:dmi:bvn*:bvr*:bd*:svn:pn:pvr* # and are the firmware-provided strings # exported by the kernel DMI modalias. # # - Input driver device name and DMI data match: # evdev:name::dmi:bvn*:bvr*:bd*:svn:pn* # is the name device specified by the # driver, is the firmware-provided string exported # by the kernel DMI modalias. # # Scan codes are specified as: # KEYBOARD_KEY_= # The scan code should be expressed in hex lowercase. The key codes # are retrieved and normalized from the kernel input API header. # # An '!' as the first character of the key identifier string # will add the scan code to the AT keyboard's list of scan codes # where the driver will synthesize a release event and not expect # it to be generated by the hardware. # # To debug key presses and access scan code mapping data of # an input device use the commonly available tool: evtest(1). # # To update this file, create a new file # /etc/udev/hwdb.d/70-keyboard.hwdb # and add your rules there. To load the new rules execute (as root): # udevadm hwdb --update # udevadm trigger /dev/input/eventXX # where /dev/input/eventXX is the keyboard in question. If in # doubt, simply use /dev/input/event* to reload all input rules. # # If your changes are generally applicable, preferably send them as a pull # request to # https://github.com/systemd/systemd # or create a bug report on https://github.com/systemd/systemd/issues and # include your new rules, a description of the device, and the output of # udevadm info /dev/input/eventXX. ########################################## # Acer ########################################## # common keys evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGateway*:pnA0A1*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svneMachines:pneMachines*E725:pvr* KEYBOARD_KEY_a5=help # Fn+F1 KEYBOARD_KEY_a6=setup # Fn+F2 Acer eSettings KEYBOARD_KEY_a7=battery # Fn+F3 Power Management KEYBOARD_KEY_a9=switchvideomode # Fn+F5 KEYBOARD_KEY_b2=www KEYBOARD_KEY_b3=euro KEYBOARD_KEY_b4=dollar KEYBOARD_KEY_ce=brightnessup # Fn+Right KEYBOARD_KEY_d4=bluetooth # (toggle) off-to-on KEYBOARD_KEY_d5=wlan # (toggle) on-to-off KEYBOARD_KEY_d6=wlan # (toggle) off-to-on KEYBOARD_KEY_d7=bluetooth # (toggle) on-to-off KEYBOARD_KEY_d8=bluetooth # (toggle) off-to-on KEYBOARD_KEY_d9=brightnessup # Fn+Right KEYBOARD_KEY_ee=brightnessup # Fn+Right KEYBOARD_KEY_ef=brightnessdown # Fn+Left KEYBOARD_KEY_f1=f22 # Fn+F7 Touchpad toggle (off-to-on) KEYBOARD_KEY_f2=f23 # Fn+F7 Touchpad toggle (on-to-off) KEYBOARD_KEY_f3=prog2 # "P2" programmable button KEYBOARD_KEY_f4=prog1 # "P1" programmable button KEYBOARD_KEY_f5=presentation KEYBOARD_KEY_f8=fn KEYBOARD_KEY_f9=prog1 # Launch NTI shadow # Acer kernel driver evdev:name:Acer WMI hotkeys:dmi:bvn*:bvr*:bd*:svn*:pnAcer*:pvr* KEYBOARD_KEY_82=f21 # Touchpad toggle # Aspire models evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*:pvr* KEYBOARD_KEY_84=bluetooth # sent when bluetooth module missing, and key pressed KEYBOARD_KEY_d9=bluetooth # Bluetooth off KEYBOARD_KEY_92=media # Acer arcade evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*5720*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnZG8*:pvr* KEYBOARD_KEY_f4=prog3 # e-key evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*5920G:* KEYBOARD_KEY_8a=media KEYBOARD_KEY_a6=setup evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*6920:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*8930:* KEYBOARD_KEY_ca=prog3 # key 'HOLD' on CineDash Media Console KEYBOARD_KEY_83=rewind KEYBOARD_KEY_89=fastforward KEYBOARD_KEY_9e=back # Travelmate C300 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*C3[01]0*:pvr* KEYBOARD_KEY_67=f24 # FIXME: rotate screen KEYBOARD_KEY_68=up KEYBOARD_KEY_69=down KEYBOARD_KEY_6b=fn KEYBOARD_KEY_6c=screenlock # FIXME: lock tablet device/buttons # on some models this isn't brightnessup evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5210*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5220*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5610*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5620*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5720*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*4720*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*6593:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*1640:* KEYBOARD_KEY_ee=screenlock evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAOA*:pvr* KEYBOARD_KEY_a9=!switchvideomode # Fn+F5 ########################################################### # Alienware ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAlienware*:pn* KEYBOARD_KEY_8a=ejectcd # Alienware/Dell reserves these keys; safe to apply on all their devices evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAlienware*:pn*:pvr* KEYBOARD_KEY_bf=!prog1 #graphics amplifier, cable plug-in event KEYBOARD_KEY_c1=!prog2 #graphics amplifier, undock-button event KEYBOARD_KEY_c2=!power #graphics amplifier, surprise undock event ########################################################### # Asus ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svnASUS:pn* KEYBOARD_KEY_ed=volumeup KEYBOARD_KEY_ee=volumedown KEYBOARD_KEY_ef=mute evdev:name:Asus WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:pvr* evdev:name:Eee PC WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:pvr* evdev:name:Asus Laptop extra buttons:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:pvr* KEYBOARD_KEY_6b=f21 # Touchpad Toggle ########################################################### # BenQ ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*BenQ*:pn*Joybook*R22*:pvr* KEYBOARD_KEY_6e=wlan ########################################################### # Compal ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svnCOMPAL:pnHEL80I:* KEYBOARD_KEY_84=wlan ########################################################### # COMPAQ ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svnCompaq*:pn*E500*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnCompaq*:pn*Evo*N*:pvr* KEYBOARD_KEY_a3=www # I key KEYBOARD_KEY_9a=search KEYBOARD_KEY_9e=email KEYBOARD_KEY_9f=homepage evdev:input:b0003v049Fp0051* KEYBOARD_KEY_0c0011=presentation KEYBOARD_KEY_0c0012=addressbook KEYBOARD_KEY_0c0013=info KEYBOARD_KEY_0c0014=prog1 KEYBOARD_KEY_0c0015=messenger ########################################################### # Dell ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pn* KEYBOARD_KEY_81=playpause # Play/Pause KEYBOARD_KEY_82=stopcd # Stop KEYBOARD_KEY_83=previoussong # Previous song KEYBOARD_KEY_84=nextsong # Next song KEYBOARD_KEY_85=brightnessdown # Fn+Down Brightness Down KEYBOARD_KEY_86=brightnessup # Fn+Up Brightness Up KEYBOARD_KEY_87=battery # Fn+F3 battery icon KEYBOARD_KEY_88=unknown # Fn+F2 Turn On/Off Wireless - handled in hardware KEYBOARD_KEY_89=ejectclosecd # Fn+F10 Eject CD KEYBOARD_KEY_8a=suspend # Fn+F1 hibernate KEYBOARD_KEY_8b=switchvideomode # Fn+F8 CRT/LCD (high keycode: "displaytoggle") KEYBOARD_KEY_8c=unknown # Fn+Right Auto Brightness KEYBOARD_KEY_8F=switchvideomode # Fn+F7 aspect ratio KEYBOARD_KEY_90=previoussong # Front panel previous song KEYBOARD_KEY_91=prog1 # Wi-Fi Catcher (Dell-specific) KEYBOARD_KEY_92=media # MediaDirect button (house icon) KEYBOARD_KEY_93=unknown # FIXME Fn+Left Auto Brightness KEYBOARD_KEY_95=camera # Shutter button - Takes a picture if optional camera available KEYBOARD_KEY_97=email # Tablet email button KEYBOARD_KEY_98=f21 # FIXME: Tablet screen rotation KEYBOARD_KEY_99=nextsong # Front panel next song KEYBOARD_KEY_9a=setup # Tablet tools button KEYBOARD_KEY_9b=switchvideomode # Display toggle button KEYBOARD_KEY_9e=f21 # Touchpad toggle KEYBOARD_KEY_a2=playpause # Front panel play/pause KEYBOARD_KEY_a4=stopcd # Front panel stop KEYBOARD_KEY_ed=media # MediaDirect button KEYBOARD_KEY_d8=screenlock # FIXME: Tablet lock button KEYBOARD_KEY_d9=f21 # Touchpad toggle # evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*910:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*101[012]:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1110:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1210:pvr* KEYBOARD_KEY_84=wlan # Dell Inspiron 1520 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1520:pvr* KEYBOARD_KEY_85=unknown # Brightness Down, also emitted by acpi-video, ignore KEYBOARD_KEY_86=unknown # Brightness Up, also emitted by acpi-video, ignore # Latitude XT2 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*XT2:pvr* KEYBOARD_KEY_9b=up # tablet rocker up KEYBOARD_KEY_9e=enter # tablet rocker press KEYBOARD_KEY_9f=back # tablet back KEYBOARD_KEY_a3=down # tablet rocker down evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnStudio*155[78]:pvr* KEYBOARD_KEY_a0=! # mute KEYBOARD_KEY_ae=! # volume down KEYBOARD_KEY_b0=! # volume up # Dell Touchpad evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnPrecision*:pvr* KEYBOARD_KEY_88=! # wireless switch KEYBOARD_KEY_9e=!f21 # Dell XPS evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnXPS*:pvr* KEYBOARD_KEY_8c=!unknown # Dell XPS12 9Q33 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnXPS12-9Q33*:pvr* KEYBOARD_KEY_88=wlan KEYBOARD_KEY_65=direction # Screen Rotate # Dell Latitude microphone mute evdev:name:Dell WMI hotkeys:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude* # Dell Precision microphone mute evdev:name:Dell WMI hotkeys:dmi:bvn*:bvr*:bd*:svnDell*:pnPrecision* KEYBOARD_KEY_150=f20 # Mic mute toggle, should be micmute ########################################################### # Everex ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svnEverex:pnXT5000*:pvr* KEYBOARD_KEY_5c=media KEYBOARD_KEY_65=f21 # Fn+F5 Touchpad toggle KEYBOARD_KEY_67=prog3 # Fan speed control button KEYBOARD_KEY_6f=brightnessup KEYBOARD_KEY_7f=brightnessdown KEYBOARD_KEY_b2=www KEYBOARD_KEY_ec=mail ########################################## # Fujitsu ########################################## evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pnAMILO*M*:pvr* KEYBOARD_KEY_97=prog2 KEYBOARD_KEY_9f=prog1 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pnAmilo*Li*1718:* KEYBOARD_KEY_d6=wlan # Amilo Li 2732 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pnAMILO*Li*2732:* KEYBOARD_KEY_d9=brightnessdown # Fn+F8 brightness down KEYBOARD_KEY_ef=brightnessup # Fn+F9 brightness up KEYBOARD_KEY_a9=switchvideomode # Fn+F10 Cycle between available video outputs # Amilo Pa 2548 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pa*2548*:pvr* KEYBOARD_KEY_e0=volumedown KEYBOARD_KEY_e1=volumeup KEYBOARD_KEY_e5=prog1 # Amilo Pro Edition V3505 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pro*Edition*V3505*:pvr* KEYBOARD_KEY_a5=help # Fn+F1 KEYBOARD_KEY_a9=switchvideomode # Fn+F3 KEYBOARD_KEY_d9=brightnessdown # Fn+F8 KEYBOARD_KEY_e0=brightnessup # Fn+F9 # Amilo Pro v3205 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pro*V3205*:pvr* KEYBOARD_KEY_f4=f21 # FIXME: silent-mode decrease CPU/GPU clock KEYBOARD_KEY_f7=switchvideomode # Fn+F3 # Amilo Si 1520 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*Amilo*Si*1520*:pvr* KEYBOARD_KEY_e1=wlan KEYBOARD_KEY_f3=wlan KEYBOARD_KEY_ee=brightnessdown KEYBOARD_KEY_e0=brightnessup KEYBOARD_KEY_e2=bluetooth KEYBOARD_KEY_f7=video # Esprimo Mobile V5 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*ESPRIMO*Mobile*V5*:pvr* KEYBOARD_KEY_a9=switchvideomode KEYBOARD_KEY_d9=brightnessdown KEYBOARD_KEY_df=sleep KEYBOARD_KEY_ef=brightnessup # Esprimo Mobile V6 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*ESPRIMO*Mobile*V6*:pvr* KEYBOARD_KEY_ce=brightnessup KEYBOARD_KEY_ef=brightnessdown ########################################################### # GIGABYTE ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGIGABYTE:pnU2442:* KEYBOARD_KEY_a0=! # mute ########################################################### # Genius ########################################################### # Slimstar 320 evdev:input:b0003v0458p0708* KEYBOARD_KEY_0900f0=scrollup KEYBOARD_KEY_0900f1=scrolldown KEYBOARD_KEY_0900f3=back KEYBOARD_KEY_0900f2=forward KEYBOARD_KEY_0900f5=wordprocessor KEYBOARD_KEY_0900f6=spreadsheet KEYBOARD_KEY_0900f4=presentation KEYBOARD_KEY_0c0223=www KEYBOARD_KEY_0900f7=chat KEYBOARD_KEY_0900fb=prog1 KEYBOARD_KEY_0900f8=close KEYBOARD_KEY_0900f9=graphicseditor KEYBOARD_KEY_0900fd=scale KEYBOARD_KEY_0900fc=screenlock ########################################################### # Hewlett Packard ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*:pvr* KEYBOARD_KEY_81=fn_esc KEYBOARD_KEY_89=battery # Fn+F8 KEYBOARD_KEY_8a=screenlock # Fn+F6 KEYBOARD_KEY_8b=camera KEYBOARD_KEY_8c=media # music KEYBOARD_KEY_8e=dvd KEYBOARD_KEY_b1=help KEYBOARD_KEY_b3=unknown # FIXME: Auto brightness KEYBOARD_KEY_d7=wlan KEYBOARD_KEY_92=brightnessdown # Fn+F7 (Fn+F9 on 6730b) KEYBOARD_KEY_97=brightnessup # Fn+F8 (Fn+F10 on 6730b) KEYBOARD_KEY_ee=switchvideomode # Fn+F4 # Tablet evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[tT][aA][bB][lL][eE][tT]*:pvr* KEYBOARD_KEY_82=prog2 # Funny Key KEYBOARD_KEY_83=prog1 # Q KEYBOARD_KEY_84=tab KEYBOARD_KEY_85=esc KEYBOARD_KEY_86=pageup KEYBOARD_KEY_87=pagedown # Pavilion evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[pP][aA][vV][iI][lL][iI][oO][nN]*:pvr* KEYBOARD_KEY_88=media # FIXME: quick play KEYBOARD_KEY_b7=print KEYBOARD_KEY_d8=!f23 # touchpad off KEYBOARD_KEY_d9=!f22 # touchpad on evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*Pavilion*dv7*Notebook*PC:pvr* KEYBOARD_KEY_b7=print KEYBOARD_KEY_c2=media # FIXME: quick play KEYBOARD_KEY_c6=break KEYBOARD_KEY_94=reserved # Elitebook evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*Compaq*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*EliteBook*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2230s*:pvr* KEYBOARD_KEY_88=presentation KEYBOARD_KEY_d9=help # I key (high keycode: "info") # Presario evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*Presario*CQ*:pvr* KEYBOARD_KEY_d8=f21 KEYBOARD_KEY_d9=f21 # 2510p 2530p evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2510p*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2530p*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*G60*Notebook*PC:pvr* KEYBOARD_KEY_d8=!f23 # touchpad off KEYBOARD_KEY_d9=!f22 # touchpad on # 2570p evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2570p*:pvr* KEYBOARD_KEY_f8=wlan # Wireless HW switch button # TX2 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[tT][xX]2*:pvr* KEYBOARD_KEY_c2=media KEYBOARD_KEY_d8=!f23 # Toggle touchpad button on tx2 (OFF) KEYBOARD_KEY_d9=!f22 # Toggle touchpad button on tx2 (ON) # Presario 2100 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnPresario*2100*:pvr* KEYBOARD_KEY_f0=help KEYBOARD_KEY_f1=screenlock KEYBOARD_KEY_f3=search # Elitebook 8440p evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*EliteBook*8440p:pvr* KEYBOARD_KEY_88=www KEYBOARD_KEY_a0=mute KEYBOARD_KEY_ae=volumedown KEYBOARD_KEY_b0=volumeup KEYBOARD_KEY_ec=mail # Elitebook 8460p evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*EliteBook*8460p:pvr* KEYBOARD_KEY_f8=wlan # Wireless HW switch button KEYBOARD_KEY_b3=prog1 # Fn+F11 - Ambient Light Sensor button KEYBOARD_KEY_b1=prog2 # Fn+ESC - System information button # HDX9494nr evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHDX9494NR:pvr* KEYBOARD_KEY_b2=www # Fn+F3 KEYBOARD_KEY_d8=!f23 # touchpad off KEYBOARD_KEY_d9=!f22 # touchpad on # Chromebook 14 # Top row keys (between ESC and power button) evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnFalco:pvr* KEYBOARD_KEY_3b=back KEYBOARD_KEY_3c=forward KEYBOARD_KEY_3d=refresh KEYBOARD_KEY_3f=switchvideomode KEYBOARD_KEY_40=brightnessdown KEYBOARD_KEY_41=brightnessup KEYBOARD_KEY_42=mute KEYBOARD_KEY_43=volumedown KEYBOARD_KEY_44=volumeup KEYBOARD_KEY_db=search # Same position as caps lock key on most keyboards # KEYBOARD_KEY_3e=fullscreen, no defined key sym # HP EliteBook 725 G2 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPLicrice:pvr* # HP ProBook 440 G2 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP440G2:pvr* # HP ProBook 445 G1 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPProBook445G1NotebookPC:pvr* # HP ProBook 450 G0 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPProBook450G0:pvr* KEYBOARD_KEY_81=f20 # Fn+F8; Microphone mute button, should be micmute # HP ProBook 6555b evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard:pnHPProBook6555b:* KEYBOARD_KEY_b2=www # Earth # HP ProBook 440 G3 evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*440*G3* KEYBOARD_KEY_92=brightnessdown KEYBOARD_KEY_97=brightnessup KEYBOARD_KEY_ee=switchvideomode KEYBOARD_KEY_81=f20 # micmute ########################################################### # IBM ########################################################### # thinkpad_acpi driver evdev:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnIBM*:pn*:pvr* KEYBOARD_KEY_01=battery # Fn+F2 KEYBOARD_KEY_02=screenlock # Fn+F3 KEYBOARD_KEY_03=sleep # Fn+F4 KEYBOARD_KEY_04=wlan # Fn+F5 KEYBOARD_KEY_06=switchvideomode # Fn+F7 KEYBOARD_KEY_07=zoom # Fn+F8 screen expand KEYBOARD_KEY_08=f24 # Fn+F9 undock KEYBOARD_KEY_0b=suspend # Fn+F12 KEYBOARD_KEY_0f=brightnessup # Fn+Home KEYBOARD_KEY_10=brightnessdown # Fn+End KEYBOARD_KEY_11=kbdillumtoggle # Fn+PgUp - ThinkLight KEYBOARD_KEY_13=zoom # Fn+Space KEYBOARD_KEY_14=volumeup KEYBOARD_KEY_15=volumedown KEYBOARD_KEY_16=mute KEYBOARD_KEY_17=prog1 # ThinkPad/ThinkVantage button (high keycode: "vendor") # IBM Thinkpad USB Keyboard Trackpoint evdev:input:b0003v04B3p301[89]* KEYBOARD_KEY_900f0=screenlock KEYBOARD_KEY_900f1=wlan KEYBOARD_KEY_900f2=switchvideomode KEYBOARD_KEY_900f3=suspend KEYBOARD_KEY_900f4=brightnessup KEYBOARD_KEY_900f5=brightnessdown KEYBOARD_KEY_900f8=zoom ########################################################### # Inventec ########################################################### # Symphony evdev:atkbd:dmi:bvn*:bvr*:bd*:svnINVENTEC:pnSYMPHONY*6.0/7.0:pvr* KEYBOARD_KEY_f3=prog2 KEYBOARD_KEY_f4=prog1 ########################################################### # Lenovo ########################################################### # thinkpad_acpi driver evdev:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn* KEYBOARD_KEY_01=screenlock KEYBOARD_KEY_02=battery KEYBOARD_KEY_03=sleep KEYBOARD_KEY_04=wlan KEYBOARD_KEY_06=switchvideomode KEYBOARD_KEY_07=f21 KEYBOARD_KEY_08=f24 KEYBOARD_KEY_0b=suspend KEYBOARD_KEY_0f=brightnessup KEYBOARD_KEY_10=brightnessdown KEYBOARD_KEY_11=kbdillumtoggle KEYBOARD_KEY_13=zoom KEYBOARD_KEY_14=volumeup KEYBOARD_KEY_15=volumedown KEYBOARD_KEY_16=mute KEYBOARD_KEY_17=prog1 KEYBOARD_KEY_1a=f20 # Microphone mute button; should be micmute # ThinkPad Keyboard with TrackPoint evdev:input:b0003v17EFp6009* KEYBOARD_KEY_090012=screenlock # Fn+F2 KEYBOARD_KEY_090013=battery # Fn+F3 KEYBOARD_KEY_090014=wlan # Fn+F5 KEYBOARD_KEY_090016=switchvideomode # Fn+F7 KEYBOARD_KEY_090017=f21 # Fn+F8 touchpad toggle KEYBOARD_KEY_090019=suspend # Fn+F12 KEYBOARD_KEY_09001a=brightnessup # Fn+Home KEYBOARD_KEY_09001b=brightnessdown # Fn+End KEYBOARD_KEY_09001d=zoom # Fn+Space KEYBOARD_KEY_090011=prog1 # ThinkVantage button KEYBOARD_KEY_090015=camera # Fn+F6 headset/camera VoIP key ?? KEYBOARD_KEY_090010=f20 # Microphone mute button; should be micmute # Lenovo 3000 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*3000*:pvr* KEYBOARD_KEY_8b=switchvideomode # Fn+F7 video KEYBOARD_KEY_96=wlan # Fn+F5 wireless KEYBOARD_KEY_97=sleep # Fn+F4 suspend KEYBOARD_KEY_98=suspend # Fn+F12 hibernate KEYBOARD_KEY_b4=prog1 # Lenovo Care # "Lenovo Care" Key of the 3000 N200 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn0769AP2:pvr3000N200:* KEYBOARD_KEY_b4=prog1 # lenovo-ideapad evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pnS10-*:pvr* KEYBOARD_KEY_81=rfkill # does nothing in BIOS KEYBOARD_KEY_83=display_off # BIOS toggles screen state KEYBOARD_KEY_b9=brightnessup # does nothing in BIOS KEYBOARD_KEY_ba=brightnessdown # does nothing in BIOS KEYBOARD_KEY_f1=camera # BIOS toggles camera power KEYBOARD_KEY_f2=f21 # touchpad toggle (key alternately emits F2 and F3) KEYBOARD_KEY_f3=f21 # Thinkpad X200_Tablet evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:pvrThinkPad*X2*Tablet* KEYBOARD_KEY_5d=menu KEYBOARD_KEY_63=fn KEYBOARD_KEY_66=screenlock KEYBOARD_KEY_67=cyclewindows # bezel circular arrow KEYBOARD_KEY_68=setup # bezel setup / menu KEYBOARD_KEY_6c=direction # rotate screen # ThinkPad X6 Tablet evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:pvrThinkPad*X6*Tablet* KEYBOARD_KEY_6c=direction # rotate KEYBOARD_KEY_68=leftmeta # toolbox KEYBOARD_KEY_6b=esc # escape KEYBOARD_KEY_6d=right # right on d-pad KEYBOARD_KEY_6e=left # left on d-pad KEYBOARD_KEY_71=up # up on d-pad KEYBOARD_KEY_6f=down # down on d-pad KEYBOARD_KEY_69=enter # enter on d-pad # ThinkPad X41 Tablet evdev:atkbd:dmi:bvn*:bvr*:bd*:svnIBM*:pn18666TU:pvr* KEYBOARD_KEY_6c=direction # rotate KEYBOARD_KEY_68=leftmeta # toolbox KEYBOARD_KEY_6b=esc # escape KEYBOARD_KEY_69=enter # enter on d-pad # IdeaPad evdev:name:Ideapad extra buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn* KEYBOARD_KEY_42=f23 KEYBOARD_KEY_43=f22 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*Y550*:pvr* KEYBOARD_KEY_95=media KEYBOARD_KEY_a3=play evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*U300s*:pvr* KEYBOARD_KEY_f1=f21 KEYBOARD_KEY_ce=f20 # micmute evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO*:pn*IdeaPad*Z370*:pvr* KEYBOARD_KEY_a0=!mute KEYBOARD_KEY_ae=!volumedown KEYBOARD_KEY_b0=!volumeup # V480 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*Lenovo*V480*:pvr* KEYBOARD_KEY_f1=f21 # Lenovo Thinkcentre M800z AIO machine # key_scancode 00 is KEY_MICMUTE keyboard:name:Microphone Mute Button:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn* KEYBOARD_KEY_00=f20 # enhanced USB keyboard evdev:input:b0003v04B3p301B* KEYBOARD_KEY_90001=prog1 # ThinkVantage KEYBOARD_KEY_90002=screenlock KEYBOARD_KEY_90003=file KEYBOARD_KEY_90004=wordprocessor KEYBOARD_KEY_90005=spreadsheet KEYBOARD_KEY_90006=calc KEYBOARD_KEY_90007=mail KEYBOARD_KEY_90008=www ########################################################### # Logitech ########################################################### # iTouch evdev:input:b0003v046DpC308* KEYBOARD_KEY_90001=shop # Shopping KEYBOARD_KEY_90002=config # iTouch KEYBOARD_KEY_90003=finance # Finance KEYBOARD_KEY_90004=prog1 # My Sites KEYBOARD_KEY_90005=prog2 # Community KEYBOARD_KEY_C0183=media # Media # Cordless Desktop S510 evdev:input:b0003v046DpC50C* KEYBOARD_KEY_d4=zoomin KEYBOARD_KEY_cc=zoomout # Wave cordless evdev:input:b0003v046DpC317* KEYBOARD_KEY_9001c=scale # expo KEYBOARD_KEY_9001f=zoomout KEYBOARD_KEY_90020=zoomin KEYBOARD_KEY_9003d=prog1 # gadget KEYBOARD_KEY_90005=camera KEYBOARD_KEY_90018=media KEYBOARD_KEY_90041=wordprocessor KEYBOARD_KEY_90042=spreadsheet KEYBOARD_KEY_90043=calendar KEYBOARD_KEY_90044=prog2 # fn+f4 (program a) KEYBOARD_KEY_90045=prog3 # fn+f5 (program b) KEYBOARD_KEY_90046=prog4 # fn+f6 (program c) KEYBOARD_KEY_90048=messenger # fn+f8 (msn messenger) KEYBOARD_KEY_9002d=search # fn+f10 (search www) KEYBOARD_KEY_9004b=find # fn+f11 (search pc) KEYBOARD_KEY_9004c=ejectclosecd # Wave cordless evdev:input:b0003v046DpC517* KEYBOARD_KEY_c101f=zoomout KEYBOARD_KEY_c1020=zoomin KEYBOARD_KEY_c1005=camera KEYBOARD_KEY_c0183=media KEYBOARD_KEY_c1041=wordprocessor KEYBOARD_KEY_c1042=spreadsheet KEYBOARD_KEY_c1043=calendar KEYBOARD_KEY_c1044=prog2 # fn+f4 (program a) KEYBOARD_KEY_c1045=prog3 # fn+f5 (program b) KEYBOARD_KEY_c1046=prog4 # fn+f6 (program c) KEYBOARD_KEY_c1048=messenger # fn+f8 (msn messenger) KEYBOARD_KEY_c104a=find # fn+f10 (search www) KEYBOARD_KEY_c104c=ejectclosecd # Cordless Wave Pro evdev:input:b0003v046DpC52[9B]* KEYBOARD_KEY_0c01b6=camera KEYBOARD_KEY_0c0183=media KEYBOARD_KEY_0c0184=wordprocessor KEYBOARD_KEY_0c0186=spreadsheet KEYBOARD_KEY_0c018e=calendar KEYBOARD_KEY_0c0223=homepage KEYBOARD_KEY_0c01bc=messenger KEYBOARD_KEY_0c018a=mail KEYBOARD_KEY_0c0221=search KEYBOARD_KEY_0c00b8=ejectcd KEYBOARD_KEY_0c022d=zoomin KEYBOARD_KEY_0c022e=zoomout # Logitech Presenter R400 evdev:input:b0003v046DpC52D* KEYBOARD_KEY_070029=presentation KEYBOARD_KEY_07003e=presentation KEYBOARD_KEY_070037=displaytoggle # Internet Navigator evdev:input:b0003v046DpC309* KEYBOARD_KEY_90001=chat # Messenger/SMS KEYBOARD_KEY_90002=camera # webcam KEYBOARD_KEY_90003=prog1 # iTouch KEYBOARD_KEY_90004=shop # Shopping KEYBOARD_KEY_C0201=new # New (F1) KEYBOARD_KEY_C0289=reply # Reply mail (F2) KEYBOARD_KEY_C028B=forwardmail # Forward mail (F3) KEYBOARD_KEY_C028C=send # Send (F4) KEYBOARD_KEY_C021A=undo # Undo (F5). KEYBOARD_KEY_C0279=redo # Redo (F6). KEYBOARD_KEY_C0208=print # Print (F7) KEYBOARD_KEY_C0207=save # Save (F8) KEYBOARD_KEY_C0194=file # My Computer (F9) KEYBOARD_KEY_C01A7=documents # My Documents (F10) KEYBOARD_KEY_C01B6=images # My Pictures (F11) ?? KEYBOARD_KEY_C01B7=sound # My Music (F12) ?? ########################################################### # Maxdata ########################################################### # Pro 7000 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMAXDATA:pnPro*7000*:pvr* KEYBOARD_KEY_97=prog2 KEYBOARD_KEY_9f=prog1 KEYBOARD_KEY_a0=mute # Fn+F5 KEYBOARD_KEY_82=www KEYBOARD_KEY_ec=email KEYBOARD_KEY_ae=volumedown # Fn+Down KEYBOARD_KEY_b0=volumeup # Fn+Up KEYBOARD_KEY_df=suspend # Fn+F2 KEYBOARD_KEY_f5=help ########################################################### # Medion ########################################################### # FID2060 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMEDION*:pn*FID2060*:pvr* KEYBOARD_KEY_6b=channeldown # Thottle Down KEYBOARD_KEY_6d=channelup # Thottle Up # NB-A555 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMEDIONNB:pnA555*:pvr* KEYBOARD_KEY_63=www # N button KEYBOARD_KEY_66=prog1 # link 1 button KEYBOARD_KEY_67=email # envelope button KEYBOARD_KEY_69=prog2 # link 2 button ########################################################### # Microsoft ########################################################### # Microsoft Natural Ergonomic Keyboard 4000 evdev:input:b0003v045Ep00DB* KEYBOARD_KEY_c022d=zoomin KEYBOARD_KEY_c022e=zoomout ########################################################### # Micro Star ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn* KEYBOARD_KEY_a0=mute # Fn+F9 KEYBOARD_KEY_ae=volumedown # Fn+F7 KEYBOARD_KEY_b0=volumeup # Fn+F8 KEYBOARD_KEY_b2=www # e button KEYBOARD_KEY_df=sleep # Fn+F12 KEYBOARD_KEY_e2=bluetooth # satellite dish2 KEYBOARD_KEY_e4=f21 # Fn+F3 Touchpad disable KEYBOARD_KEY_ec=email # envelope button KEYBOARD_KEY_ee=camera # Fn+F6 camera disable KEYBOARD_KEY_f6=wlan # satellite dish1 KEYBOARD_KEY_f7=brightnessdown # Fn+F4 KEYBOARD_KEY_f8=brightnessup # Fn+F5 KEYBOARD_KEY_f9=search # evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnGE60*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnGE70*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*:pvr* KEYBOARD_KEY_c2=ejectcd # some MSI models generate ACPI/input events on the LNXVIDEO input devices, # plus some extra synthesized ones on atkbd as an echo of actually changing the # brightness; so ignore those atkbd ones, to avoid loops evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*U-100*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*U100*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*N033:* KEYBOARD_KEY_f7=reserved KEYBOARD_KEY_f8=reserved # MSI Wind U90/U100 generates separate touchpad on/off keycodes so ignore touchpad toggle keycode evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnU90/U100:* KEYBOARD_KEY_e4=reserved ########################################################### # MSI ########################################################### evdev:name:MSI Laptop hotkeys:dmi:bvn*:bvr*:bd*:svn*:pnM[iI][cC][rR][oO]-S[tT][aA][rR]*:pvr* KEYBOARD_KEY_0213=f22 KEYBOARD_KEY_0214=f23 ########################################################### # OLPC ########################################################### # XO evdev:atkbd:dmi:bvn*:bvr*:bd*:svnOLPC:pnXO:* KEYBOARD_KEY_59=fn KEYBOARD_KEY_81=fn_esc KEYBOARD_KEY_f9=camera KEYBOARD_KEY_f8=sound # Fn+CAMERA = Mic KEYBOARD_KEY_43=brightnessdown KEYBOARD_KEY_44=brightnessup KEYBOARD_KEY_57=volumedown KEYBOARD_KEY_58=volumeup KEYBOARD_KEY_bb=f1 KEYBOARD_KEY_bc=f2 KEYBOARD_KEY_bd=f3 KEYBOARD_KEY_be=f4 KEYBOARD_KEY_bf=f5 KEYBOARD_KEY_c0=f6 KEYBOARD_KEY_c1=f7 KEYBOARD_KEY_c2=f8 KEYBOARD_KEY_c3=f9 KEYBOARD_KEY_c4=f10 KEYBOARD_KEY_c7=f11 KEYBOARD_KEY_d8=f12 KEYBOARD_KEY_f7=f13 KEYBOARD_KEY_f6=f14 KEYBOARD_KEY_f5=f15 KEYBOARD_KEY_f4=f16 KEYBOARD_KEY_f3=f17 KEYBOARD_KEY_f2=f18 KEYBOARD_KEY_f1=f19 KEYBOARD_KEY_f0=f20 # micmute KEYBOARD_KEY_ef=f21 KEYBOARD_KEY_ee=chat KEYBOARD_KEY_e4=chat KEYBOARD_KEY_dd=menu # Frame KEYBOARD_KEY_da=prog1 # Fn+Frame KEYBOARD_KEY_d3=delete KEYBOARD_KEY_d2=insert KEYBOARD_KEY_c9=pageup KEYBOARD_KEY_d1=pagedown KEYBOARD_KEY_c7=home KEYBOARD_KEY_cF=end KEYBOARD_KEY_73=hp KEYBOARD_KEY_7e=hp KEYBOARD_KEY_db=leftmeta # left grab KEYBOARD_KEY_dc=rightmeta # right grab KEYBOARD_KEY_85=rightmeta # Right grab releases on a different scancode KEYBOARD_KEY_d6=kbdillumtoggle # Fn+Space KEYBOARD_KEY_69=switchvideomode # Brightness key KEYBOARD_KEY_65=kp8 # up KEYBOARD_KEY_66=kp2 # down KEYBOARD_KEY_67=kp4 # left KEYBOARD_KEY_68=kp6 # right KEYBOARD_KEY_e5=kp9 # pgup KEYBOARD_KEY_e6=kp3 # pgdn KEYBOARD_KEY_e7=kp7 # home KEYBOARD_KEY_e8=kp1 # end ########################################################### # Onkyo ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svnONKYO*CORPORATION:pnONKYOPC:* KEYBOARD_KEY_a0=mute # Fn+D KEYBOARD_KEY_ae=volumedown # Fn+F KEYBOARD_KEY_b0=volumeup # Fn+G KEYBOARD_KEY_df=sleep # Fn+W KEYBOARD_KEY_e0=bluetooth # Fn+H KEYBOARD_KEY_e2=cyclewindows # Fn+Esc KEYBOARD_KEY_ee=battery # Fn+Q KEYBOARD_KEY_f0=media # Fn+R KEYBOARD_KEY_f5=switchvideomode # Fn+E KEYBOARD_KEY_f6=camera # Fn+T KEYBOARD_KEY_f7=f21 # Fn+Y (touchpad toggle) KEYBOARD_KEY_f8=brightnessup # Fn+S KEYBOARD_KEY_f9=brightnessdown # Fn+A KEYBOARD_KEY_fb=wlan # Fn+J ########################################################### # OQO ########################################################### # Model 2 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnOQO*Inc.*:pnOQO*Model*2*:pvr* KEYBOARD_KEY_8e=wlan KEYBOARD_KEY_f0=switchvideomode KEYBOARD_KEY_f1=mute KEYBOARD_KEY_f2=volumedown KEYBOARD_KEY_f3=volumeup ########################################################### # Plantronics ########################################################### # Plantronics .Audio 626 DSP evdev:input:b0003v047FpC006* KEYBOARD_KEY_b002f=f20 # Microphone mute button; should be micmute ########################################################### # Quanta ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*:pn*:pvr*:rvnQuanta:rn30B7:rvr65.2B:* KEYBOARD_KEY_88=media # "quick play ########################################################### # Samsung ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn* KEYBOARD_KEY_74=prog1 # User key KEYBOARD_KEY_75=www KEYBOARD_KEY_78=mail KEYBOARD_KEY_82=!switchvideomode # Fn+F4 CRT/LCD (high keycode: "displaytoggle") KEYBOARD_KEY_83=!battery # Fn+F2 KEYBOARD_KEY_84=!prog1 # Fn+F5 backlight on/off KEYBOARD_KEY_86=!wlan # Fn+F9 KEYBOARD_KEY_88=!brightnessup # Fn+Up KEYBOARD_KEY_89=!brightnessdown # Fn+Down KEYBOARD_KEY_b1=!prog2 # Fn+F7 run Samsung Magic Doctor (keypressed event is generated twice) KEYBOARD_KEY_b3=!prog3 # Fn+F8 switch power mode (battery/dynamic/performance) KEYBOARD_KEY_b4=!wlan # Fn+F9 (X60P) KEYBOARD_KEY_c5=!prog3 # Fn+F8 switch power mode (battery/dynamic/performance) KEYBOARD_KEY_d5=!wlan # Fn+F12 wlan/airplane switch KEYBOARD_KEY_f7=!f22 # Fn+F10 Touchpad on KEYBOARD_KEY_f9=!f23 # Fn+F10 Touchpad off # Series 3 evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*300E[457]*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*200E[45]*:pvr* KEYBOARD_KEY_ce=! # Fn+F1 launch control setting # Series 5 evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*530U*:pvr* KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings KEYBOARD_KEY_a8=! # Fn Lock - Function lock on KEYBOARD_KEY_a9=! # Fn Lock - Function lock off evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*550P*:pvr* KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings KEYBOARD_KEY_a8=! # Fn Lock - Function lock on KEYBOARD_KEY_a9=! # Fn Lock - Function lock off # Series 7 / 9 evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*350V*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*670Z*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700G*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*900X[34]*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*940X3G*:pvr* KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings KEYBOARD_KEY_a0=!mute # Fn+F6 mute KEYBOARD_KEY_ae=!volumedown # Fn+F7 KEYBOARD_KEY_b0=!volumeup # Fn+F8 KEYBOARD_KEY_97=!kbdillumdown # Fn+F9 keyboard backlight down KEYBOARD_KEY_96=!kbdillumup # Fn+F10 keyboard backlight up KEYBOARD_KEY_b3=!prog3 # Fn+F11 fan/cooling mode changer evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*900X[34][AB]*:pvr* KEYBOARD_KEY_ce=! # Fn+F8 keyboard backlight up KEYBOARD_KEY_8d=! # Fn+F7 keyboard backlight down KEYBOARD_KEY_96=! # Fn+F1 performance mode (?) KEYBOARD_KEY_97=! # Fn+F12 Wi-Fi toggle KEYBOARD_KEY_d5=! # Fn+F6 battery life extender evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*90X3A*:pvr* KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings KEYBOARD_KEY_8d=!prog3 # Fn+F6 performance mode KEYBOARD_KEY_97=!kbdillumdown # Fn+F7 keyboard backlight down KEYBOARD_KEY_96=!kbdillumup # Fn+F8 keyboard backlight up KEYBOARD_KEY_d5=!wlan # Fn+F12 Wi-Fi toggle # Series 7 Ultra evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*7[34]0U3E*:pvr* KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings KEYBOARD_KEY_97=!kbdillumdown # Fn+F9 keyboard backlight down KEYBOARD_KEY_96=!kbdillumup # Fn+F10 keyboard backlight up KEYBOARD_KEY_b3=!prog3 # Fn+F11 fan/cooling mode changer KEYBOARD_KEY_d5=!wlan # Fn+F12 wlan/airplane switch # ATIV Book 6 / 8 evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*[68][78]0Z*:pvr* KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings KEYBOARD_KEY_96=!kbdillumup # Fn+F10 keyboard backlight up KEYBOARD_KEY_97=!kbdillumdown # Fn+F9 keyboard backlight down # SQ1US evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pnSQ1US:pvr* KEYBOARD_KEY_d4=menu KEYBOARD_KEY_d8=f1 KEYBOARD_KEY_d9=f10 KEYBOARD_KEY_d6=f3 KEYBOARD_KEY_d7=f9 KEYBOARD_KEY_e4=f5 KEYBOARD_KEY_ee=f11 # SX20S evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*SX20S*:pvr* KEYBOARD_KEY_74=mute KEYBOARD_KEY_75=mute KEYBOARD_KEY_77=f22 # Touchpad on KEYBOARD_KEY_79=f23 # Touchpad off evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700T*:pvr* KEYBOARD_KEY_ad=leftmeta ########################################################### # SONY ########################################################### # sony-laptop driver evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn* KEYBOARD_KEY_06=mute # Fn+F2 KEYBOARD_KEY_07=volumedown # Fn+F3 KEYBOARD_KEY_08=volumeup # Fn+F4 KEYBOARD_KEY_09=brightnessdown # Fn+F5 KEYBOARD_KEY_0a=brightnessup # Fn+F6 KEYBOARD_KEY_0b=switchvideomode # Fn+F7 KEYBOARD_KEY_0e=zoom # Fn+F10 KEYBOARD_KEY_10=suspend # Fn+F12 evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-C1*:pvr* evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-K25*:pvr* evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-F[1-6]*:pvr* evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-FX*:pvr* evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-FRV*:pvr* evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-GR*:pvr* evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-TR*:pvr* evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-NV*:pvr* evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-Z*:pvr* evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*VGN-S360*:pvr* KEYBOARD_KEY_06=battery KEYBOARD_KEY_07=mute evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-AR71*:pvr* evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-FW*:pvr* evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-Z21*:pvr* KEYBOARD_KEY_00=brightnessdown # Fn+F5 KEYBOARD_KEY_10=brightnessup # Fn+F6 KEYBOARD_KEY_11=switchvideomode # Fn+F7 KEYBOARD_KEY_12=zoomout KEYBOARD_KEY_14=zoomin KEYBOARD_KEY_15=suspend # Fn+F12 KEYBOARD_KEY_17=prog1 KEYBOARD_KEY_20=media evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-FW250*:pvr* KEYBOARD_KEY_10=suspend # Fn+F12 evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVPC*:pvr* KEYBOARD_KEY_05=f21 # Fn+F1 -> KEY_F21 (The actual touchpad toggle) KEYBOARD_KEY_0d=zoomout # Fn+F9 KEYBOARD_KEY_0e=zoomin # Fn+F10 ########################################################### # Toshiba ########################################################### # Satellite A100 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSATELLITE*A100:pvr* KEYBOARD_KEY_a4=stopcd KEYBOARD_KEY_b2=www # Satellite A110 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*A110:pvr* KEYBOARD_KEY_92=stop KEYBOARD_KEY_93=www KEYBOARD_KEY_94=media KEYBOARD_KEY_9e=f22 # Touchpad on KEYBOARD_KEY_9f=f23 # Touchpad off KEYBOARD_KEY_b9=nextsong KEYBOARD_KEY_d9=brightnessup KEYBOARD_KEY_ee=screenlock KEYBOARD_KEY_f4=previoussong KEYBOARD_KEY_f7=playpause # Satellite M30X evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*M30X:pvr* KEYBOARD_KEY_ef=brightnessdown KEYBOARD_KEY_d9=brightnessup KEYBOARD_KEY_ee=screenlock KEYBOARD_KEY_93=media KEYBOARD_KEY_9e=f22 # touchpad enable KEYBOARD_KEY_9f=f23 # touchpad disable # Satellite P75-A evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*P75-A:pvr* KEYBOARD_KEY_ef=brightnessdown KEYBOARD_KEY_ee=brightnessup KEYBOARD_KEY_a9=switchvideomode # switch display outputs KEYBOARD_KEY_d4=wlan # RF Switch Off # Satellite U940 evdev:name:Toshiba*input*device:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSATELLITEU940:pvr* KEYBOARD_KEY_13c=brightnessdown KEYBOARD_KEY_13d=brightnessup KEYBOARD_KEY_13e=switchvideomode KEYBOARD_KEY_13f=f21 # Touchpad toggle # Satellite P75-A7200 evdev:name:Toshiba*input*device:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*P75-A:pvr* KEYBOARD_KEY_13c=brightnessdown KEYBOARD_KEY_13d=brightnessup KEYBOARD_KEY_13e=switchvideomode KEYBOARD_KEY_13f=f21 # Touchpad toggle KEYBOARD_KEY_9e=wlan ########################################################### # VIA ########################################################### evdev:atkbd:dmi:bvn*:bvr*:bd*:svnVIA:pnK8N800:pvr* KEYBOARD_KEY_81=prog1 ########################################################### # Zepto ########################################################### # Znote evdev:atkbd:dmi:bvn*:bvr*:bd*:svnZepto:pnZnote:* KEYBOARD_KEY_93=switchvideomode # Fn+F3 Toggle Video Output KEYBOARD_KEY_95=brightnessdown # Fn+F4 Brightness Down KEYBOARD_KEY_91=brightnessup # Fn+F5 Brightness Up KEYBOARD_KEY_a5=f23 # Fn+F6 Disable Touchpad KEYBOARD_KEY_a6=f22 # Fn+F6 Enable Touchpad KEYBOARD_KEY_a7=bluetooth # Fn+F10 Enable Bluetooth KEYBOARD_KEY_a9=bluetooth # Fn+F10 Disable Bluetooth KEYBOARD_KEY_f1=wlan # RF Switch Off KEYBOARD_KEY_f2=wlan # RF Switch On KEYBOARD_KEY_f4=prog1 # P1 Button KEYBOARD_KEY_f3=prog2 # P2 Button KEYBOARD_KEY_a0=! # mute KEYBOARD_KEY_ae=! # volume down KEYBOARD_KEY_b0=! # volume up # Znote 6615WD evdev:atkbd:dmi:bvn*:bvr*:bd*:svnZepto:pnZnote*6615WD:* KEYBOARD_KEY_a0=! # mute KEYBOARD_KEY_ae=! # volume down KEYBOARD_KEY_b0=! # volume up ########################################################### # Other ########################################################### # Common Volume Keys evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*SIEMENS:pnAMILO*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFOXCONN:pnQBOOK:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMTC:pn*:pvrA0:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMio*Technology:pnN890:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPEGATRON*CORP.:pnSpring*Peak:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSatellite*[uU][35]0[05]*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSATELLITE*[uU][35]0[05]*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSatellite*Pro*[uU]300*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnEQUIUM [uU][35]0[05]*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnViooo*Corporation:pnPT17:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHANNspree:pnSN10E100:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGIGABYTE:pni1520M:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnBenQ:pn*nScreen*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnBenQ:pnJoybook*Lite*:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDIXONSP:pnDIXON*:pvr* KEYBOARD_KEY_a0=! # mute KEYBOARD_KEY_ae=! # volume down KEYBOARD_KEY_b0=! # volume up systemd-229/hwdb/70-mouse.hwdb000066400000000000000000000340061265713322000162320ustar00rootroot00000000000000# This file is part of systemd. # # Database for the DPI setting of mice, trackballs, other pointer devices that # cannot be queried directly. # # The lookup keys are composed in: # 70-mouse.rules # # Note: The format of the "mouse:" prefix match key is a # contract between the rules file and the hardware data, it might # change in later revisions to support more or better matches, it # is not necessarily expected to be a stable ABI. # # Match string format: # mouse::vp:name:: # # Supported subsystems: usb, bluetooth # vid/pid as 4-digit hex lowercase vendor/product # # if vid/pid is unavailable, use # mouse:*:name:: # if name is unavailable, use # mouse::vp:* # # For example, the following 5 matches all match the same mouse: # mouse:usb:v17efp6019:name:Lenovo Optical USB Mouse: # mouse:usb:*:name:Lenovo Optical USB Mouse: # mouse:usb:v17efp6019:* # mouse:*:name:Lenovo Optical USB Mouse: # # To add local entries, create a new file # /etc/udev/hwdb.d/71-mouse-local.hwdb # and add your rules there. To load the new rules execute (as root): # udevadm hwdb --update # udevadm trigger /dev/input/eventXX # where /dev/input/eventXX is the mouse in question. If in # doubt, simply use /dev/input/event* to reload all input rules. # # If your changes are generally applicable, preferably send them as a pull # request to # https://github.com/systemd/systemd # or create a bug report on https://github.com/systemd/systemd/issues and # include your new rules, a description of the device, and the output of # udevadm info /dev/input/eventXX. # # Allowed properties are: # MOUSE_DPI # MOUSE_WHEEL_CLICK_ANGLE # ######################################### # MOUSE_DPI # ######################################### # # DPI settings are specified as # MOUSE_DPI=[@] # # Where is the resolution in dots per inch, and the # sampling frequency in Hz (optional). If a device supports dynamic # frequency scaling, the maximum frequency should be used. For devices # supporting multiple fixed frequencies, see below. # # The value of MOUSE_DPI is: # - a single integer for single-resolution mice, e.g. # MOUSE_DPI=800 # or, if the frequency is known: # MOUSE_DPI=800@120 # - a space-separated list of resolutions for multi-resolution mice. # The default resolution must be prefixed by an asterisk, the resolutions # in the database must be as shipped by the manufacturer. e.g. # MOUSE_DPI=400 *800 2000 # # The order of resolutions is as configured by the HW manufacturer or in # ascending order, whichever appropriate. # # The frequency must be given to either none or all resolutions. If the # device supports multiple fixed frequencies, the order of items is # MOUSE_DPI=r1@f1 r2@f1 r3@f1 r1@f2 r2@f2 r3@f2 # # If the default manufacturer-set resolution is unclear, a resolution of # 800 or 1000 should be set as default, if available. If neither is # available, choose the "middle" resolution value of those available. # # The list may contain a single item which must be marked with an # asterisk. # # Local changes to the a non-default resolution of the mouse (e.g. through # third-party software) must not be entered into this file, use a local # hwdb instead. # ######################################### # MOUSE_WHEEL_CLICK_ANGLE # ######################################### # # The angle in degrees per mouse wheel 'click', specified as # MOUSE_WHEEL_CLICK_ANGLE= # # Most mice have a 15 degree click stop (24 clicks per full rotation). # # # Sort by brand, type (usb, bluetooth), DPI, frequency. # For mice with switchable resolution, sort by the starred entry. ########################################## # Apple ########################################## # Apple MagicMouse # Note: this device changes name once connected to a mac, the name ends up # as $username`s mouse mouse:bluetooth:v05acp030d:name:*: MOUSE_DPI=1300@1000 ########################################## # Chicony ########################################## # Chicony 2.4G Multimedia Wireless Kit MG-0919 mouse:usb:v04f2p0963:name:Chicony 2.4G Multimedia Wireless Kit: MOUSE_DPI=1000@142 ########################################## # Dell ########################################## # Dell MUAR DEL7 mouse:usb:v413cp3012:name:Dell Dell USB Optical Mouse: MOUSE_DPI=400@166 # Dell USB Laser Mouse mouse:usb:v046dpc063:name:DELL DELL USB Laser Mouse: MOUSE_DPI=1000@125 ########################################## # Fujitsu Siemens ########################################## mouse:usb:v0461p4d16:name:USB Optical Mouse: MOUSE_DPI=500@125 ########################################## # HandShoe Mouse ########################################## # HandShoe Mouse mouse:usb:v192fp0916:name:USB Optical Mouse: MOUSE_DPI=1000@128 ########################################## # HoverStop ########################################## # Hoverstop active ergonomic mouse mouse:usb:v088dp1234:name:HoverStop NL Hoverstop active ergonomic mouse: MOUSE_DPI=400@129 ########################################## # HP ########################################## # HP USB 1000dpi Laser Mouse mouse:usb:v0458p0133:name:Mouse Laser Mouse: MOUSE_DPI=1000@125 MOUSE_WHEEL_CLICK_ANGLE=15 # HP X1000 mouse:usb:v093ap2510:name:PixArt USB Optical Mouse: mouse:usb:v093ap2510:name:PIXART USB OPTICAL MOUSE: MOUSE_DPI=1000@125 ########################################## # Lenovo ########################################## # Lenovo Optical USB Mouse mouse:usb:v17efp6019:name:Lenovo Optical USB Mouse: MOUSE_DPI=1000@125 # Lenovo M-U0025-O mouse:usb:v17efp6019:name:Logitech Lenovo USB Optical Mouse: MOUSE_DPI=1000@166 # ThinkPad USB Laser Mouse mouse:usb:v17efp6044:name:ThinkPad USB Laser Mouse: MOUSE_DPI=1200@125 # Lenovo Precision USB Mouse mouse:usb:v17efp6050:name:Lenovo Precision USB Mouse: MOUSE_DPI=1200@127 # Lenovo MOBGUL mouse:usb:v17efp601d:name:Primax Lenovo Laser Mouse: # Lenovo MOBGULA mouse:usb:v17efp6045:name:Lenovo USB Laser Mouse: MOUSE_DPI=1600@125 ########################################## # Logitech ########################################## # Note: devices using the Logitech Unifying receiver will need two entries, # one for pre 3.19 with the wireless PID in the name, one for 3.19 with the # model name. The usb vid/pid is the same for all those devices. # Until 3.19 is available, this list just has the Wireless PID entry. # Logitech M-BJ58 Optical Mouse mouse:usb:v046dpc00e:name:Logitech USB-PS/2 Optical Mouse: # Logitech Mini Optical Mouse mouse:usb:v046dpc016:name:Logitech Optical USB Mouse: # Logitech MX310 Optical Mouse mouse:usb:v046dpc01b:name:Logitech USB-PS/2 Optical Mouse: # Logitech USB-PS/2 M-BT58 mouse:usb:v046dpc03e:name:Logitech USB-PS/2 Optical Mouse: # Logitech TrackMan Marble Wheel USB mouse:usb:v046dpc401:name:Logitech USB-PS/2 Trackball: MOUSE_DPI=400@125 # Lenovo USB mouse model MO28UOL mouse:usb:v04b3p310c:name:USB Optical Mouse: MOUSE_DPI=400@142 # Logitech M570 trackball mouse:usb:v046dp1028:name:Logitech M570: MOUSE_DPI=540@167 # Logitech USB-PS/2 M-BZ96C mouse:usb:v046dpc045:name:Logitech USB-PS/2 Optical Mouse: MOUSE_DPI=600@125 # Logitech Wireless Mouse M325 mouse:usb:v046dp400a:name:Logitech M325: mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:400a: MOUSE_DPI=600@166 MOUSE_WHEEL_CLICK_ANGLE=20 # Logitech MX400 Performance Laser Mouse mouse:usb:v046dpc043:name:Logitech USB-PS/2 Optical Mouse: # Logitech MX1000 Laser Cordless Mouse mouse:usb:v046dpc50e:name:Logitech USB RECEIVER: # Logitech Cordless Click! Plus mouse:usb:v046dpc50e:name:Logitech USB Receiver: # Logitech, Inc. RX 300 Optical Mouse mouse:usb:v046dpc040:name:Logitech USB-PS/2 Optical Mouse: MOUSE_DPI=800@125 # Logitech MX 518 mouse:usb:v046dpc01e:name:Logitech USB-PS/2 Optical Mouse: MOUSE_DPI=400@125 *800@125 1600@125 # Logitech, Inc. RX 250 Optical Mouse mouse:usb:v046dpc050:name:Logitech USB-PS/2 Optical Mouse: MOUSE_DPI=1000@142 # Logitech Wireless Mouse M185 mouse:usb:v046dp4008:name:Logitech M185: mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4008: # Logitech Wireless Mouse M510 mouse:usb:v046dp1025:name:Logitech M510: # Logitech M705 (marathon mouse) mouse:usb:v046dp101b:name:Logitech M705: mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:101b: MOUSE_DPI=800@166 # Logitech MX Revolution mouse:usb:v046dpc51a:name:Logitech USB Receiver: MOUSE_DPI=800@200 # Logitech G5 Laser Mouse mouse:usb:v046dpc049:name:Logitech USB Gaming Mouse: # Logitech G500s Laser Gaming Mouse mouse:usb:v046dpc24e:name:Logitech G500s Laser Gaming Mouse: MOUSE_DPI=400@500 *800@500 2000@500 # Logitech G9 mouse:usb:v046dpc048:name:Logitech G9 Laser Mouse: MOUSE_DPI=400@1000 800@1000 *1600@1000 # Logitech G9x [Call of Duty MW3 Edition] mouse:usb:v046dpc249:name:Logitech G9x Laser Mouse: MOUSE_DPI=400@1000 800@1000 *1600@1000 3200@1000 # Logitech G400 (Wired) mouse:usb:v046dpc245:name:Logitech Gaming Mouse G400: MOUSE_DPI=400@1000 *800@1000 1800@1000 3600@1000 # Logitech G400s (Wired) mouse:usb:v046dpc24c:name:Logitech G400s Optical Gaming Mouse: MOUSE_DPI=400@1000 *800@1000 2000@1000 4000@1000 # Logitech G402 Hyperion Fury mouse:usb:v046dpc07e:name:Logitech Gaming Mouse G402: MOUSE_DPI=400@1000 *800@1000 1600@1000 3200@1000 # Logitech B605 Wireless Mouse (also M505) mouse:usb:v046dp101d:name:Logitech B605: mouse:usb:v046dp101d:name:Logitech M505: mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:101d: MOUSE_DPI=900@166 # Logitech Cordless Desktop Wave Mouse mouse:usb:v046dpc517:name:Logitech USB Receiver: MOUSE_DPI=950@125 # Logitech RX1000 Laser Mouse mouse:usb:v046dpc046:name:Logitech USB Optical Mouse: # Logitech M100 Optical Mouse mouse:usb:v046dpc05a:name:Logitech USB Optical Mouse: # Logitech USB Laser Mouse M-U0011-O rebranded as "terra Laser" mouse:usb:v046dpc065:name:Logitech USB Laser Mouse: # Logitech USB Laser Mouse M-U0007 [M500] mouse:usb:v046dpc069:name:Logitech USB Laser Mouse: # Logitech V500 Cordless Notebook Mouse mouse:usb:v046dpc510:name:Logitech USB Receiver: # Logitech M560 Wireless Mouse mouse:usb:v046dp402d:name:Logitech M560: mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:402d: MOUSE_DPI=1000@125 # Logitech V220 Cordless Optical Mouse mouse:usb:v046dpc51b:name:Logitech USB Receiver: # Logitech Performance MX mouse:usb:v046dp101a:name:Logitech Performance MX: # Logitech MX Master mouse:usb:v046dp4041:name:Logitech MX Master: MOUSE_DPI=1000@166 # Logitech MK260 Wireless Combo Receiver aka M-R0011 mouse:usb:v046dpc52e:name:Logitech USB Receiver: MOUSE_DPI=1000@200 # Logitech G700 Laser Mouse (Wired) mouse:usb:v046dpc06b:name:Logitech G700 Laser Mouse: # Logitech G700 Laser Mouse (Wireless) mouse:usb:v046dpc531:name:Logitech USB Receiver: MOUSE_DPI=*1000@500 3800@500 500@1000 1500@1000 2000@1000 # Logitech Wireless Mouse M310 mouse:usb:v046dp1024:name:Logitech M310: MOUSE_DPI=1100@168 # Logitech USB Laser Mouse M-UAS144 [LS1 Laser Mouse] mouse:usb:v046dpc062:name:Logitech USB Laser Mouse: MOUSE_DPI=1200@125 # Logitech T620 (or, the soap) mouse:usb:v046dp4027:name:Logitech T620: mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4027: MOUSE_DPI=1200@250 # Logitech LX8 Cordless Laser Mouse mouse:usb:v046dpc51b:name:Logitech USB Receiver: MOUSE_DPI=1300@125 MOUSE_WHEEL_CLICK_ANGLE=15 # Logitech ZoneTouch Mouse T400 mouse:usb:v046dp4026:name:Logitech T400: mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4026: MOUSE_DPI=1300@166 # Logitech G500 Mouse mouse:usb:v046dpc068:name:Logitech G500: MOUSE_DPI=*1600@500 2600@500 3600@500 # Logitech MX1000 Laser Cordless Mouse mouse:bluetooth:v046dpb003:name:Logitech MX1000 mouse: MOUSE_DPI=800@80 # Logitech Ultrathin Touch Mouse mouse:bluetooth:v046dpb00d:name:Ultrathin Touch Mouse: MOUSE_DPI=1000@1000 # ImPS/2 Logitech Wheel Mouse mouse:ps2:*:name:ImPS/2 Logitech Wheel Mouse: MOUSE_DPI=400@100 # ImExPS/2 Logitech Wheel Mouse mouse:ps2:*:name:ImExPS/2 Logitech Wheel Mouse: MOUSE_DPI=400@250 ########################################## # Microsoft ########################################## mouse:usb:v045ep0040:name:Microsoft Microsoft 3-Button Mouse with IntelliEye(TM): MOUSE_DPI=400@125 # Note: unsure that these work, it's likely that all devices on these # receivers show up with the same vid/pid/name # Microsoft Wireless Mouse 5000 mouse:usb:v045ep0745:name:Microsoft Microsoft® 2.4GHz Transceiver v6.0: MOUSE_DPI=800@142 # Microsoft Wireless Mobile Mouse 4000 mouse:usb:v045ep0745:name:Microsoft Microsoft® Nano Transceiver v2.0: # Microsoft Sculpt Ergonomic Mouse mouse:usb:v045ep07a5:name:Microsoft Microsoft® 2.4GHz Transceiver v9.0: MOUSE_DPI=1000@142 # Microsoft Arc Touch Mouse USB mouse:usb:v045ep07b1:name:Microsoft Microsoft® Nano Transceiver v1.0: MOUSE_DPI=1400@142 # Microsoft Wireless Laser Mouse 8000 mouse:bluetooth:v045ep0702:name:Microsoft Wireless Laser Mouse 8000: MOUSE_DPI=1000@1000 # Microsoft Arc Touch Mouse SE: mouse:bluetooth:v045ep07f3:name:Arc Touch Mouse SE: MOUSE_DPI=1000@2000 ########################################## # Mionix ########################################## #Mionix Avior 7000 mouse:usb:v22d4p1308:name:Laview Technology Mionix Avior 7000: MOUSE_DPI=400@1000 *1600@1000 7000@1000 MOUSE_WHEEL_CLICK_ANGLE=15 ########################################## # Oklick ########################################## # Oklick 406S Bluetooth Laser Mouse mouse:bluetooth:v056ep0061:name:Laser BTmouse: MOUSE_DPI=*800@333 1600@333 ########################################## # Razer ########################################## # Razer Abyssus mouse:usb:v1532p0042:name:Razer Razer Abyssus: MOUSE_DPI=3500@1000 ########################################## # Roccat ########################################## # Roccat Lua (ROC-11-310) mouse:usb:v1e7dp2c2e:name:ROCCAT ROCCAT Lua: MOUSE_DPI=250@125 500@125 1000@125 1250@125 1500@125 1750@125 2000@125 250@250 500@250 1000@250 1250@250 1500@250 1750@250 2000@250 250@500 500@500 1000@500 1250@500 1500@500 1750@500 2000@500 250@1000 500@1000 *1000@1000 1250@1000 1500@1000 1750@1000 2000@1000 MOUSE_WHEEL_CLICK_ANGLE=15 systemd-229/hwdb/70-pointingstick.hwdb000066400000000000000000000111741265713322000177700ustar00rootroot00000000000000# This file is part of systemd. # # Pointingstick const-accel configuration, to make different brand / model # laptop pointingsticks have the same speed / feel, and per model adjustment # of the IBM TrackPoint driver's sensitivity setting # # The lookup keys are composed in: # 60-evdev.rules # # Note: The format of the "evdev:" prefix match key is a contract between the # rules file and the hardware data, it might change in later revisions to # support more or better matches, it is not necessarily a stable ABI. # # Supported hardware matches are: # - Generic input devices match: # evdev:input:bZZZZvYYYYpXXXXeWWWW-VVVV # This matches on the kernel modalias of the input-device, mainly: # ZZZZ is the bus-id (see /usr/include/linux/input.h BUS_*), YYYY, XXXX and # WWW are the 4-digit hex uppercase vendor, product and version ID and VVVV # is an arbitrary length input-modalias describing the device capabilities. # # - Input driver device name and DMI data match: # evdev:name::dmi:bvn*:bvr*:bd*:svn:pn* # is the name device specified by the driver, # is the firmware-provided string from the kernel DMI modalias. # # To add local entries, create a new file # /etc/udev/hwdb.d/71-pointingstick-local.hwdb # and add your rules there. To load the new rules execute (as root): # udevadm hwdb --update # udevadm trigger /dev/input/eventXX # where /dev/input/eventXX is the pointingstick in question. If in # doubt, simply use /dev/input/event* to reload all input rules. # # If your changes are generally applicable, preferably send them as a pull # request to # https://github.com/systemd/systemd # or create a bug report on https://github.com/systemd/systemd/issues and # include your new rules, a description of the device, and the output of # udevadm info /dev/input/eventXX. # # Allowed properties are: # POINTINGSTICK_CONST_ACCEL # POINTINGSTICK_SENSITIVITY # # Entries should be sorted with growing _SENSITIVITY and _CONST_ACCEL. # ######################################### # POINTINGSTICK_CONST_ACCEL # ######################################### # # Trackpoint const accel settings are specified as # POINTINGSTICK_CONST_ACCEL= # # Where is a floating point number, using a '.' seperator, specifying # by how much to multiply deltas generated by the pointingstick to get # normalized deltas. # ######################################### # POINTINGSTICK_SENSITIVITY # ######################################### # # TPPS/2 IBM TrackPoint driver sensitivity sysfs setting # POINTINGSTICK_SENSITIVITY= # # Where is a number between 0 and 255, note this property # only applies to TPPS/2 IBM TrackPoint devices, see # drivers/input/mouse/trackpoint.c in the Linux kernel sources. # # # Sort by by brand, model ######################################### # Dell ######################################### # Latitude D620 evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeD620*:pvr* POINTINGSTICK_CONST_ACCEL=0.5 # Latitude E6320 evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6320*:pvr* POINTINGSTICK_CONST_ACCEL=2.0 # Latitude E6400 evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6400*:pvr* POINTINGSTICK_CONST_ACCEL=1.5 ######################################### # Lenovo ######################################### # Lenovo Thinkpad X230 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX230:* # Lenovo Thinkpad X230 tablet evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX230Tablet:* # Lenovo Thinkpad X240 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX240:* # Lenovo Thinkpad T440s evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT440s:* # Lenovo Thinkpad T540p evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT540p:* # Lenovo Thinkpad T550 / W550s evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT550:* # Lenovo Thinkpad X1 Carbon 3rd gen evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd:* POINTINGSTICK_SENSITIVITY=200 POINTINGSTICK_CONST_ACCEL=1.0 # Lenovo Thinkpad X200s / X201s # Note these come with 2 revisions of keyboard, with the trackpoints having a # different sensitivity in the different revisions. 1.25 is a bit slow for the # least sensitive revision, but it is better to be a bit slow than too fast. evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX20?s:* POINTINGSTICK_SENSITIVITY=200 POINTINGSTICK_CONST_ACCEL=1.25 systemd-229/hwdb/Makefile000077700000000000000000000000001265713322000201022../src/Makefileustar00rootroot00000000000000systemd-229/hwdb/ids-update.pl000077500000000000000000000312131265713322000164040ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; sub usb_vendor { my $vendor; open(IN, "<", "usb.ids"); open(OUT, ">", "20-usb-vendor-model.hwdb"); print(OUT "# This file is part of systemd.\n" . "#\n" . "# Data imported from: http://www.linux-usb.org/usb.ids\n"); while (my $line = ) { $line =~ s/\s+$//; $line =~ m/^([0-9a-f]{4})\s*(.+)$/; if (defined $1) { $vendor = uc $1; my $text = $2; print(OUT "\n"); print(OUT "usb:v" . $vendor . "*\n"); print(OUT " ID_VENDOR_FROM_DATABASE=" . $text . "\n"); next; } $line =~ m/^\t([0-9a-f]{4})\s*(.+)$/; if (defined $1) { my $model = uc $1; my $text = $2; print(OUT "\n"); print(OUT "usb:v" . $vendor . "p" . $model . "*\n"); print(OUT " ID_MODEL_FROM_DATABASE=" . $text . "\n"); } } close(IN); close(OUT); } sub usb_classes { my $class; my $subclass; my $protocol; open(IN, "<", "usb.ids"); open(OUT, ">", "20-usb-classes.hwdb"); print(OUT "# This file is part of systemd.\n" . "#\n" . "# Data imported from: http://www.linux-usb.org/usb.ids\n"); while (my $line = ) { $line =~ s/\s+$//; $line =~ m/^C\ ([0-9a-f]{2})\s*(.+)$/; if (defined $1) { $class = uc $1; if ($class =~ m/^00$/) { next; } my $text = $2; print(OUT "\n"); print(OUT "usb:v*p*d*dc" . $class . "*\n"); print(OUT " ID_USB_CLASS_FROM_DATABASE=" . $text . "\n"); next; } if (not defined $class) { next; } elsif ($line =~ m/^$/) { last; } $line =~ m/^\t([0-9a-f]{2})\s*(.+)$/; if (defined $1) { $subclass = uc $1; if ($subclass =~ m/^00$/) { next; } my $text = $2; if ($text =~ m/^(\?|None|Unused)$/) { next; } print(OUT "\n"); print(OUT "usb:v*p*d*dc" . $class . "dsc" . $subclass . "*\n"); print(OUT " ID_USB_SUBCLASS_FROM_DATABASE=" . $text . "\n"); next; } $line =~ m/^\t\t([0-9a-f]{2})\s*(.+)$/; if (defined $1) { $protocol = uc $1; my $text = $2; if ($text =~ m/^(\?|None|Unused)$/) { next; } print(OUT "\n"); print(OUT "usb:v*p*d*dc" . $class . "dsc" . $subclass . "dp" . $protocol . "*\n"); print(OUT " ID_USB_PROTOCOL_FROM_DATABASE=" . $text . "\n"); } } close(IN); close(OUT); } sub pci_vendor { my $vendor; my $device; my $device_text; open(IN, "<", "pci.ids"); open(OUT, ">", "20-pci-vendor-model.hwdb"); print(OUT "# This file is part of systemd.\n" . "#\n" . "# Data imported from: http://pci-ids.ucw.cz/v2.2/pci.ids\n"); while (my $line = ) { $line =~ s/\s+$//; $line =~ m/^([0-9a-f]{4})\s*(.+)$/; if (defined $1) { $vendor = uc $1; my $text = $2; print(OUT "\n"); print(OUT "pci:v0000" . $vendor . "*\n"); print(OUT " ID_VENDOR_FROM_DATABASE=" . $text . "\n"); next; } $line =~ m/^\t([0-9a-f]{4})\s*(.+)$/; if (defined $1) { $device = uc $1; $device_text = $2; print(OUT "\n"); print(OUT "pci:v0000" . $vendor . "d0000" . $device . "*\n"); print(OUT " ID_MODEL_FROM_DATABASE=" . $device_text . "\n"); next; } $line =~ m/^\t\t([0-9a-f]{4})\s*([0-9a-f]{4})\s*(.*)$/; if (defined $1) { my $sub_vendor = uc $1; my $sub_device = uc $2; my $sub_text = $3; $sub_text =~ s/^\Q$device_text\E\s*//; $sub_text =~ s/(.+)/\ ($1)/; print(OUT "\n"); print(OUT "pci:v0000" . $vendor . "d0000" . $device . "sv0000" . $sub_vendor . "sd0000" . $sub_device . "*\n"); print(OUT " ID_MODEL_FROM_DATABASE=" . $device_text . $sub_text . "\n"); } } close(IN); close(OUT); } sub pci_classes { my $class; my $subclass; my $interface; open(IN, "<", "pci.ids"); open(OUT, ">", "20-pci-classes.hwdb"); print(OUT "# This file is part of systemd.\n" . "#\n" . "# Data imported from: http://pci-ids.ucw.cz/v2.2/pci.ids\n"); while (my $line = ) { $line =~ s/\s+$//; $line =~ m/^C\ ([0-9a-f]{2})\s*(.+)$/; if (defined $1) { $class = uc $1; my $text = $2; print(OUT "\n"); print(OUT "pci:v*d*sv*sd*bc" . $class . "*\n"); print(OUT " ID_PCI_CLASS_FROM_DATABASE=" . $text . "\n"); next; } if (not defined $class) { next; } elsif ($line =~ m/^$/) { last; } $line =~ m/^\t([0-9a-f]{2})\s*(.+)$/; if (defined $1) { $subclass = uc $1; my $text = $2; print(OUT "\n"); print(OUT "pci:v*d*sv*sd*bc" . $class . "sc" . $subclass . "*\n"); print(OUT " ID_PCI_SUBCLASS_FROM_DATABASE=" . $text . "\n"); next; } $line =~ m/^\t\t([0-9a-f]{2})\s*(.+)$/; if (defined $1) { $interface = uc $1; my $text = $2; print(OUT "\n"); print(OUT "pci:v*d*sv*sd*bc" . $class . "sc" . $subclass . "i" . $interface . "*\n"); print(OUT " ID_PCI_INTERFACE_FROM_DATABASE=" . $text . "\n"); } } close(IN); close(OUT); } sub sdio_vendor { my $vendor; my $device; open(IN, "<", "sdio.ids"); open(OUT, ">", "20-sdio-vendor-model.hwdb"); print(OUT "# This file is part of systemd.\n" . "#\n" . "# Data imported from: hwdb/sdio.ids\n"); while (my $line = ) { $line =~ s/\s+$//; $line =~ m/^([0-9a-f]{4})\s*(.+)$/; if (defined $1) { $vendor = uc $1; my $text = $2; print(OUT "\n"); print(OUT "sdio:c*v" . $vendor . "*\n"); print(OUT " ID_VENDOR_FROM_DATABASE=" . $text . "\n"); next; } $line =~ m/^\t([0-9a-f]{4})\s*(.+)$/; if (defined $1) { $device = uc $1; my $text = $2; print(OUT "\n"); print(OUT "sdio:c*v" . $vendor . "d" . $device . "*\n"); print(OUT " ID_MODEL_FROM_DATABASE=" . $text . "\n"); next; } } close(IN); close(OUT); } sub sdio_classes { my $class; my $subclass; my $interface; open(IN, "<", "sdio.ids"); open(OUT, ">", "20-sdio-classes.hwdb"); print(OUT "# This file is part of systemd.\n" . "#\n" . "# Data imported from: hwdb/sdio.ids\n"); while (my $line = ) { $line =~ s/\s+$//; $line =~ m/^C\ ([0-9a-f]{2})\s*(.+)$/; if (defined $1) { $class = uc $1; my $text = $2; print(OUT "\n"); print(OUT "sdio:c" . $class . "v*d*\n"); print(OUT " ID_SDIO_CLASS_FROM_DATABASE=" . $text . "\n"); next; } } close(IN); close(OUT); } # MAC Address Block Large/Medium/Small # Large MA-L 24/24 bit (OUI) # Medium MA-M 28/20 bit (OUI prefix owned by IEEE) # Small MA-S 36/12 bit (OUI prefix owned by IEEE) sub oui { my $prefix; my %ieee_prefixes = (); open(OUT, ">", "20-OUI.hwdb"); print(OUT "# This file is part of systemd.\n" . "#\n" . "# Data imported from:\n" . "# https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-L&format=txt\n" . "# https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-M&format=txt\n" . "# https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-S&format=txt\n"); open(IN, "<", "ma-small.txt"); while (my $line = ) { $line =~ s/^ +//; $line =~ s/\s+$//; $line =~ m/^([0-9A-F]{2})-([0-9A-F]{2})-([0-9A-F]{2})\s*\(hex\)\s*.+$/; if (defined $1) { $prefix = $1 . $2 . $3; $ieee_prefixes{ $prefix } = 1; next; } $line =~ m/^([0-9A-F]{3})000-\g1FFF\s*\(base 16\)\s*(.+)$/; if (defined $1) { my $vendor = uc $1; my $text = $2; print(OUT "\n"); print(OUT "OUI:" . $prefix . $vendor . "*\n"); print(OUT " ID_OUI_FROM_DATABASE=" . $text . "\n"); } } close(IN); open(IN, "<", "ma-medium.txt"); while (my $line = ) { $line =~ s/^ +//; $line =~ s/\s+$//; $line =~ m/^([0-9A-F]{2})-([0-9A-F]{2})-([0-9A-F]{2})\s*\(hex\)\s*.+$/; if (defined $1) { $prefix = $1 . $2 . $3; $ieee_prefixes{ $prefix } = 1; next; } $line =~ m/^([0-9A-F])00000-\g1FFFFF\s*\(base 16\)\s*(.+)$/; if (defined $1) { my $vendor = uc $1; my $text = $2; print(OUT "\n"); print(OUT "OUI:" . $prefix . $vendor . "*\n"); print(OUT " ID_OUI_FROM_DATABASE=" . $text . "\n"); } } open(IN, "<", "ma-large.txt"); while (my $line = ) { $line =~ s/^ +//; $line =~ s/\s+$//; $line =~ m/^([0-9A-F]{6})\s*\(base 16\)\s*(.+)$/; if (defined $1) { my $vendor = uc $1; my $text = $2; if ($text =~ m/^IEEE REGISTRATION AUTHORITY/) { next; } # skip the IEEE owned prefixes if (! exists $ieee_prefixes{ $vendor }) { print(OUT "\n"); print(OUT "OUI:" . $vendor . "*\n"); print(OUT " ID_OUI_FROM_DATABASE=" . $text . "\n"); } } } close(IN); close(OUT); } usb_vendor(); usb_classes(); pci_vendor(); pci_classes(); sdio_vendor(); sdio_classes(); oui(); systemd-229/hwdb/sdio.ids000066400000000000000000000040511265713322000154440ustar00rootroot00000000000000# # List of SDIO ID's # # Vendors and devices. Please keep sorted. # Syntax: # vendor vendor_name # device device_name <-- single tab 0020 ST-Ericsson 2280 CW1200 0089 Intel Corp. 0092 C-guys, Inc. 0001 SD-Link11b WiFi Card (TI ACX100) 0004 EW-CG1102GC 0005 SD FM Radio 2 5544 SD FM Radio 0097 Texas Instruments, Inc. 4076 WL1271 0098 Toshiba Corp. 0001 SD BT Card 1 0002 SD BT Card 2 0003 SD BT Card 3 0104 Socket Communications, Inc. 005e SD Scanner 00c5 Bluetooth SDIO Card 0271 Atheros Communications, Inc. 0108 AR6001 0109 AR6001 010a AR6001 010b AR6001 0296 GCT Semiconductor, Inc. 5347 GDM72xx WiMAX 02d0 Broadcom Corp. 044b Nintendo Wii WLAN daughter card a887 BCM43143 WLAN card 4324 BCM43241 WLAN card 4329 BCM4329 WLAN card 4330 BCM4330 WLAN card 4334 BCM4334 WLAN card a94c BCM43340 WLAN card a94d BCM43341 WLAN card 4335 BCM4335/BCM4339 WLAN card a962 BCM43362 WLAN card 4354 BCM4354 WLAN card 02db SyChip Inc. 0002 Pegasus WLAN SDIO Card (6060SD) 02df Marvell Technology Group Ltd. 9103 Libertas 9104 SD8688 WLAN 9105 SD8688 BT 9116 SD8786 WLAN 9119 SD8787 WLAN 911a SD8787 BT 911b SD8787 BT AMP 9129 SD8797 WLAN 912a SD8797 BT 912e SD8897 BT 912d SD8897 WLAN 02fe Spectec Computer Co., Ltd 2128 SDIO WLAN Card (SDW820) 032a Cambridge Silicon Radio 0001 UniFi 1 0002 UniFi 2 0007 UniFi 3 0008 UniFi 4 037a MediaTek Inc. 5911 Spectec WLAN-11b/g 039a Siano Mobile Silicon 0501 Globalsat Technology Co. f501 SD-501 GPS Card 104c Texas Instruments, Inc. 9066 WL1251 1180 Ricoh Co., Ltd e823 MMC card reader 13d1 AboCom Systems, Inc. ac02 SDW11G # List of known interface classes # # Syntax: # C class class_name C 00 Not a SDIO standard interface C 01 UART standard interface C 02 Bluetooth Type-A standard interface C 03 Bluetooth Type-B standard interface C 04 GPS standard interface C 05 Camera standard interface C 06 PHS standard interface C 07 WLAN interface C 08 Embedded SDIO-ATA standard interface C 09 Bluetooth AMP standard interface systemd-229/m4/000077500000000000000000000000001265713322000134015ustar00rootroot00000000000000systemd-229/m4/.gitignore000066400000000000000000000001131265713322000153640ustar00rootroot00000000000000intltool.m4 libtool.m4 ltoptions.m4 ltsugar.m4 ltversion.m4 lt~obsolete.m4 systemd-229/m4/arch.m4000066400000000000000000000004351265713322000145620ustar00rootroot00000000000000 dnl SET_ARCH(ARCHNAME, PATTERN) dnl dnl Define ARCH_ condition if the pattern match with the current dnl architecture dnl AC_DEFUN([SET_ARCH], [ cpu_$1=false case "$host" in $2) cpu_$1=true ;; esac AM_CONDITIONAL(AS_TR_CPP(ARCH_$1), [test "x$cpu_$1" = xtrue]) ]) systemd-229/m4/attributes.m4000066400000000000000000000240211265713322000160300ustar00rootroot00000000000000dnl Macros to check the presence of generic (non-typed) symbols. dnl Copyright (c) 2006-2008 Diego Pettenò dnl Copyright (c) 2006-2008 xine project dnl Copyright (c) 2012 Lucas De Marchi dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2, or (at your option) dnl any later version. dnl dnl This program is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dnl GNU General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA dnl 02110-1301, USA. dnl dnl As a special exception, the copyright owners of the dnl macro gives unlimited permission to copy, distribute and modify the dnl configure scripts that are the output of Autoconf when processing the dnl Macro. You need not follow the terms of the GNU General Public dnl License when using or distributing such scripts, even though portions dnl of the text of the Macro appear in them. The GNU General Public dnl License (GPL) does govern all other use of the material that dnl constitutes the Autoconf Macro. dnl dnl This special exception to the GPL applies to versions of the dnl Autoconf Macro released by this project. When you make and dnl distribute a modified version of the Autoconf Macro, you may extend dnl this special exception to the GPL to apply to your modified version as dnl well. dnl Check if FLAG in ENV-VAR is supported by compiler and append it dnl to WHERE-TO-APPEND variable. Note that we invert -Wno-* checks to dnl -W* as gcc cannot test for negated warnings. If a C snippet is passed, dnl use it, otherwise use a simple main() definition that just returns 0. dnl CC_CHECK_FLAG_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG], [C-SNIPPET]) AC_DEFUN([CC_CHECK_FLAG_APPEND], [ AC_CACHE_CHECK([if $CC supports flag $3 in envvar $2], AS_TR_SH([cc_cv_$2_$3]), [eval "AS_TR_SH([cc_save_$2])='${$2}'" eval "AS_TR_SH([$2])='${cc_save_$2} -Werror `echo "$3" | sed 's/^-Wno-/-W/'`'" AC_LINK_IFELSE([AC_LANG_SOURCE(ifelse([$4], [], [int main(void) { return 0; } ], [$4]))], [eval "AS_TR_SH([cc_cv_$2_$3])='yes'"], [eval "AS_TR_SH([cc_cv_$2_$3])='no'"]) eval "AS_TR_SH([$2])='$cc_save_$2'"]) AS_IF([eval test x$]AS_TR_SH([cc_cv_$2_$3])[ = xyes], [eval "$1='${$1} $3'"]) ]) dnl CC_CHECK_FLAGS_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG1 FLAG2], [C-SNIPPET]) AC_DEFUN([CC_CHECK_FLAGS_APPEND], [ for flag in [$3]; do CC_CHECK_FLAG_APPEND([$1], [$2], $flag, [$4]) done ]) dnl Check if the flag is supported by linker (cacheable) dnl CC_CHECK_LDFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) AC_DEFUN([CC_CHECK_LDFLAGS], [ AC_CACHE_CHECK([if $CC supports $1 flag], AS_TR_SH([cc_cv_ldflags_$1]), [ac_save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $1" AC_LINK_IFELSE([int main() { return 1; }], [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"], [eval "AS_TR_SH([cc_cv_ldflags_$1])="]) LDFLAGS="$ac_save_LDFLAGS" ]) AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes], [$2], [$3]) ]) dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for dnl the current linker to avoid undefined references in a shared object. AC_DEFUN([CC_NOUNDEFINED], [ dnl We check $host for which systems to enable this for. AC_REQUIRE([AC_CANONICAL_HOST]) case $host in dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads dnl are requested, as different implementations are present; to avoid problems dnl use -Wl,-z,defs only for those platform not behaving this way. *-freebsd* | *-openbsd*) ;; *) dnl First of all check for the --no-undefined variant of GNU ld. This allows dnl for a much more readable command line, so that people can understand what dnl it does without going to look for what the heck -z defs does. for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"]) break done ;; esac AC_SUBST([LDFLAGS_NOUNDEFINED]) ]) dnl Check for a -Werror flag or equivalent. -Werror is the GCC dnl and ICC flag that tells the compiler to treat all the warnings dnl as fatal. We usually need this option to make sure that some dnl constructs (like attributes) are not simply ignored. dnl dnl Other compilers don't support -Werror per se, but they support dnl an equivalent flag: dnl - Sun Studio compiler supports -errwarn=%all AC_DEFUN([CC_CHECK_WERROR], [ AC_CACHE_CHECK( [for $CC way to treat warnings as errors], [cc_cv_werror], [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror], [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])]) ]) ]) AC_DEFUN([CC_CHECK_ATTRIBUTE], [ AC_REQUIRE([CC_CHECK_WERROR]) AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))], AS_TR_SH([cc_cv_attribute_$1]), [ac_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $cc_cv_werror" AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])], [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"], [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"]) CFLAGS="$ac_save_CFLAGS" ]) AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes], [AC_DEFINE( AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1, [Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))] ) $4], [$5]) ]) AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [ CC_CHECK_ATTRIBUTE( [constructor],, [void __attribute__((constructor)) ctor() { int a; }], [$1], [$2]) ]) AC_DEFUN([CC_ATTRIBUTE_FORMAT], [ CC_CHECK_ATTRIBUTE( [format], [format(printf, n, n)], [void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }], [$1], [$2]) ]) AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [ CC_CHECK_ATTRIBUTE( [format_arg], [format_arg(printf)], [char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }], [$1], [$2]) ]) AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [ CC_CHECK_ATTRIBUTE( [visibility_$1], [visibility("$1")], [void __attribute__((visibility("$1"))) $1_function() { }], [$2], [$3]) ]) AC_DEFUN([CC_ATTRIBUTE_NONNULL], [ CC_CHECK_ATTRIBUTE( [nonnull], [nonnull()], [void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }], [$1], [$2]) ]) AC_DEFUN([CC_ATTRIBUTE_UNUSED], [ CC_CHECK_ATTRIBUTE( [unused], , [void some_function(void *foo, __attribute__((unused)) void *bar);], [$1], [$2]) ]) AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [ CC_CHECK_ATTRIBUTE( [sentinel], , [void some_function(void *foo, ...) __attribute__((sentinel));], [$1], [$2]) ]) AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [ CC_CHECK_ATTRIBUTE( [deprecated], , [void some_function(void *foo, ...) __attribute__((deprecated));], [$1], [$2]) ]) AC_DEFUN([CC_ATTRIBUTE_ALIAS], [ CC_CHECK_ATTRIBUTE( [alias], [weak, alias], [void other_function(void *foo) { } void some_function(void *foo) __attribute__((weak, alias("other_function")));], [$1], [$2]) ]) AC_DEFUN([CC_ATTRIBUTE_MALLOC], [ CC_CHECK_ATTRIBUTE( [malloc], , [void * __attribute__((malloc)) my_alloc(int n);], [$1], [$2]) ]) AC_DEFUN([CC_ATTRIBUTE_PACKED], [ CC_CHECK_ATTRIBUTE( [packed], , [struct astructure { char a; int b; long c; void *d; } __attribute__((packed));], [$1], [$2]) ]) AC_DEFUN([CC_ATTRIBUTE_CONST], [ CC_CHECK_ATTRIBUTE( [const], , [int __attribute__((const)) twopow(int n) { return 1 << n; } ], [$1], [$2]) ]) AC_DEFUN([CC_FLAG_VISIBILITY], [ AC_REQUIRE([CC_CHECK_WERROR]) AC_CACHE_CHECK([if $CC supports -fvisibility=hidden], [cc_cv_flag_visibility], [cc_flag_visibility_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $cc_cv_werror" CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden], cc_cv_flag_visibility='yes', cc_cv_flag_visibility='no') CFLAGS="$cc_flag_visibility_save_CFLAGS"]) AS_IF([test "x$cc_cv_flag_visibility" = "xyes"], [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1, [Define this if the compiler supports the -fvisibility flag]) $1], [$2]) ]) AC_DEFUN([CC_FUNC_EXPECT], [ AC_REQUIRE([CC_CHECK_WERROR]) AC_CACHE_CHECK([if compiler has __builtin_expect function], [cc_cv_func_expect], [ac_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $cc_cv_werror" AC_COMPILE_IFELSE([AC_LANG_SOURCE( [int some_function() { int a = 3; return (int)__builtin_expect(a, 3); }])], [cc_cv_func_expect=yes], [cc_cv_func_expect=no]) CFLAGS="$ac_save_CFLAGS" ]) AS_IF([test "x$cc_cv_func_expect" = "xyes"], [AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1, [Define this if the compiler supports __builtin_expect() function]) $1], [$2]) ]) AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [ AC_REQUIRE([CC_CHECK_WERROR]) AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported], [cc_cv_attribute_aligned], [ac_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $cc_cv_werror" for cc_attribute_align_try in 64 32 16 8 4 2; do AC_COMPILE_IFELSE([AC_LANG_SOURCE([ int main() { static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0; return c; }])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break]) done CFLAGS="$ac_save_CFLAGS" ]) if test "x$cc_cv_attribute_aligned" != "x"; then AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned], [Define the highest alignment supported]) fi ]) systemd-229/m4/ax_compiler_vendor.m4000066400000000000000000000070241265713322000175250ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html # =========================================================================== # # SYNOPSIS # # AX_COMPILER_VENDOR # # DESCRIPTION # # Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun, # hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft, # watcom, etc. The vendor is returned in the cache variable # $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2008 Matteo Frigo # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 15 AC_DEFUN([AX_COMPILER_VENDOR], [AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, dnl Please add if possible support to ax_compiler_version.m4 [# note: don't check for gcc first since some other compilers define __GNUC__ vendors="intel: __ICC,__ECC,__INTEL_COMPILER ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__ pathscale: __PATHCC__,__PATHSCALE__ clang: __clang__ cray: _CRAYC fujitsu: __FUJITSU gnu: __GNUC__ sun: __SUNPRO_C,__SUNPRO_CC hp: __HP_cc,__HP_aCC dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland: __BORLANDC__,__CODEGEARC__,__TURBOC__ comeau: __COMO__ kai: __KCC lcc: __LCC__ sgi: __sgi,sgi microsoft: _MSC_VER metrowerks: __MWERKS__ watcom: __WATCOMC__ portland: __PGI tcc: __TINYC__ unknown: UNKNOWN" for ventest in $vendors; do case $ventest in *:) vendor=$ventest; continue ;; *) vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;; esac AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ #if !($vencpp) thisisanerror; #endif ])], [break]) done ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1` ]) ]) systemd-229/m4/ax_normalize_path.m4000066400000000000000000000113401265713322000173460ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_normalize_path.html # =========================================================================== # # SYNOPSIS # # AX_NORMALIZE_PATH(VARNAME, [REFERENCE_STRING]) # # DESCRIPTION # # Perform some cleanups on the value of $VARNAME (interpreted as a path): # # - empty paths are changed to '.' # - trailing slashes are removed # - repeated slashes are squeezed except a leading doubled slash '//' # (which might indicate a networked disk on some OS). # # REFERENCE_STRING is used to turn '/' into '\' and vice-versa: if # REFERENCE_STRING contains some backslashes, all slashes and backslashes # are turned into backslashes, otherwise they are all turned into slashes. # # This makes processing of DOS filenames quite easier, because you can # turn a filename to the Unix notation, make your processing, and turn it # back to original notation. # # filename='A:\FOO\\BAR\' # old_filename="$filename" # # Switch to the unix notation # AX_NORMALIZE_PATH([filename], ["/"]) # # now we have $filename = 'A:/FOO/BAR' and we can process it as if # # it was a Unix path. For instance let's say that you want # # to append '/subpath': # filename="$filename/subpath" # # finally switch back to the original notation # AX_NORMALIZE_PATH([filename], ["$old_filename"]) # # now $filename equals to 'A:\FOO\BAR\subpath' # # One good reason to make all path processing with the unix convention is # that backslashes have a special meaning in many cases. For instance # # expr 'A:\FOO' : 'A:\Foo' # # will return 0 because the second argument is a regex in which # backslashes have to be backslashed. In other words, to have the two # strings to match you should write this instead: # # expr 'A:\Foo' : 'A:\\Foo' # # Such behavior makes DOS filenames extremely unpleasant to work with. So # temporary turn your paths to the Unix notation, and revert them to the # original notation after the processing. See the macro # AX_COMPUTE_RELATIVE_PATHS for a concrete example of this. # # REFERENCE_STRING defaults to $VARIABLE, this means that slashes will be # converted to backslashes if $VARIABLE already contains some backslashes # (see $thirddir below). # # firstdir='/usr/local//share' # seconddir='C:\Program Files\\' # thirddir='C:\home/usr/' # AX_NORMALIZE_PATH([firstdir]) # AX_NORMALIZE_PATH([seconddir]) # AX_NORMALIZE_PATH([thirddir]) # # $firstdir = '/usr/local/share' # # $seconddir = 'C:\Program Files' # # $thirddir = 'C:\home\usr' # # LICENSE # # Copyright (c) 2008 Alexandre Duret-Lutz # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 5 AU_ALIAS([ADL_NORMALIZE_PATH], [AX_NORMALIZE_PATH]) AC_DEFUN([AX_NORMALIZE_PATH], [case ":[$]$1:" in # change empty paths to '.' ::) $1='.' ;; # strip trailing slashes :*[[\\/]]:) $1=`echo "[$]$1" | sed 's,[[\\/]]*[$],,'` ;; :*:) ;; esac # squeze repeated slashes case ifelse($2,,"[$]$1",$2) in # if the path contains any backslashes, turn slashes into backslashes *\\*) $1=`echo "[$]$1" | sed 's,\(.\)[[\\/]][[\\/]]*,\1\\\\,g'` ;; # if the path contains slashes, also turn backslashes into slashes *) $1=`echo "[$]$1" | sed 's,\(.\)[[\\/]][[\\/]]*,\1/,g'` ;; esac]) systemd-229/man/000077500000000000000000000000001265713322000136345ustar00rootroot00000000000000systemd-229/man/.gitignore000066400000000000000000000001231265713322000156200ustar00rootroot00000000000000/systemd.directives.xml /systemd.index.xml /*.[13578] /*.html /custom-entities.ent systemd-229/man/Makefile000077700000000000000000000000001265713322000177312../src/Makefileustar00rootroot00000000000000systemd-229/man/binfmt.d.xml000066400000000000000000000066141265713322000160660ustar00rootroot00000000000000 binfmt.d systemd Developer Lennart Poettering lennart@poettering.net binfmt.d 5 binfmt.d Configure additional binary formats for executables at boot /etc/binfmt.d/*.conf /run/binfmt.d/*.conf /usr/lib/binfmt.d/*.conf Description At boot, systemd-binfmt.service8 reads configuration files from the above directories to register in the kernel additional binary formats for executables. Configuration Format Each file contains a list of binfmt_misc kernel binary format rules. Consult binfmt_misc.txt for more information on registration of additional binary formats and how to write rules. Empty lines and lines beginning with ; and # are ignored. Note that this means you may not use ; and # as delimiter in binary format rules. Example /etc/binfmt.d/wine.conf example: # Start WINE on Windows executables :DOSWin:M::MZ::/usr/bin/wine: See Also systemd1, systemd-binfmt.service8, systemd-delta1, wine8 systemd-229/man/bootchart.conf.xml000066400000000000000000000141771265713322000173010ustar00rootroot00000000000000 bootchart.conf systemd Developer Auke Kok auke-jan.h.kok@intel.com bootchart.conf 5 bootchart.conf bootchart.conf.d Boot performance analysis graphing tool configuration files /etc/systemd/bootchart.conf /etc/systemd/bootchart.conf.d/*.conf /run/systemd/bootchart.conf.d/*.conf /usr/lib/systemd/bootchart.conf.d/*.conf Description When starting, systemd-bootchart will read the configuration file /etc/systemd/bootchart.conf, followed by the files in the bootchart.conf.d directories. These configuration files determine logging parameters and graph output. Options Samples=500 Configure the amount of samples to record in total before bootchart exits. Each sample will record at intervals defined by Frequency=. Frequency=25 Configure the sample log frequency. This can be a fractional number, but must be larger than 0.0. Most systems can cope with values under 25–50 without impacting boot time severely. Relative=no Configures whether the left axis of the output graph equals time=0.0 (CLOCK_MONOTONIC start). This is useful for using bootchart at post-boot time to profile an already booted system, otherwise the graph would become extremely large. If set to yes, the horizontal axis starts at the first recorded sample instead of time=0.0. Filter=no Configures whether the resulting graph should omit tasks that did not contribute significantly to the boot. Processes that are too short-lived (only seen in one sample) or that do not consume any significant CPU time (less than 0.001sec) will not be displayed in the output graph. Output=[path] Configures the output directory for writing the graphs. By default, bootchart writes the graphs to /run/log. Init=[path] Configures bootchart to run a non-standard binary instead of /usr/lib/systemd/systemd. This option is only relevant if bootchart was invoked from the kernel command line with init=/usr/lib/systemd/systemd-bootchart. PlotMemoryUsage=no If set to yes, enables logging and graphing of processes' PSS memory consumption. PlotEntropyGraph=no If set to yes, enables logging and graphing of the kernel random entropy pool size. ScaleX=100 Horizontal scaling factor for all variable graph components. ScaleY=20 Vertical scaling factor for all variable graph components. ControlGroup=no Display process control group. See Also systemd-bootchart1, systemd.directives7 systemd-229/man/bootctl.xml000066400000000000000000000106731265713322000160330ustar00rootroot00000000000000 bootctl systemd Developer Kay Sievers kay@vrfy.org bootctl 1 bootctl Control the firmware and boot manager settings bootctl OPTIONSstatus bootctl OPTIONSupdate bootctl OPTIONSinstall bootctl OPTIONSremove Description bootctl checks, updates, installs or removes the boot loader from the current system. bootctl status checks and prints the currently installed versions of the boot loader binaries and all current EFI boot variables. bootctl update updates all installed versions of systemd-boot, if the current version is newer than the version installed in the EFI system partition. This also includes the EFI default/fallback loader at /EFI/Boot/boot*.efi. A systemd-boot entry in the EFI boot variables is created if there is no current entry. The created entry will be added to the end of the boot order list. bootctl install installs systemd-boot into the EFI system partition. A copy of systemd-boot will be stored as the EFI default/fallback loader at /EFI/Boot/boot*.efi. A systemd-boot entry in the EFI boot variables is created and added to the top of the boot order list. bootctl remove removes all installed versions of systemd-boot from the EFI system partition, and removes systemd-boot from the EFI boot variables. If no command is passed, status is implied. Options The following options are understood: Path to the EFI system partition. The default is /boot. Do not touch the EFI boot variables. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also Boot loader specification Systemd boot loader interface systemd-229/man/bootup.xml000066400000000000000000000370531265713322000156760ustar00rootroot00000000000000 bootup systemd Developer Lennart Poettering lennart@poettering.net bootup 7 bootup System bootup process Description A number of different components are involved in the system boot. Immediately after power-up, the system BIOS will do minimal hardware initialization, and hand control over to a boot loader stored on a persistent storage device. This boot loader will then invoke an OS kernel from disk (or the network). In the Linux case, this kernel (optionally) extracts and executes an initial RAM disk image (initrd), such as generated by dracut8, which looks for the root file system (possibly using systemd1 for this). After the root file system is found and mounted, the initrd hands over control to the host's system manager (such as systemd1) stored on the OS image, which is then responsible for probing all remaining hardware, mounting all necessary file systems and spawning all configured services. On shutdown, the system manager stops all services, unmounts all file systems (detaching the storage technologies backing them), and then (optionally) jumps back into the initrd code which unmounts/detaches the root file system and the storage it resides on. As a last step, the system is powered down. Additional information about the system boot process may be found in boot7. System Manager Bootup At boot, the system manager on the OS image is responsible for initializing the required file systems, services and drivers that are necessary for operation of the system. On systemd1 systems, this process is split up in various discrete steps which are exposed as target units. (See systemd.target5 for detailed information about target units.) The boot-up process is highly parallelized so that the order in which specific target units are reached is not deterministic, but still adheres to a limited amount of ordering structure. When systemd starts up the system, it will activate all units that are dependencies of default.target (as well as recursively all dependencies of these dependencies). Usually, default.target is simply an alias of graphical.target or multi-user.target, depending on whether the system is configured for a graphical UI or only for a text console. To enforce minimal ordering between the units pulled in, a number of well-known target units are available, as listed on systemd.special7. The following chart is a structural overview of these well-known units and their position in the boot-up logic. The arrows describe which units are pulled in and ordered before which other units. Units near the top are started before units nearer to the bottom of the chart. local-fs-pre.target | v (various mounts and (various swap (various cryptsetup fsck services...) devices...) devices...) (various low-level (various low-level | | | services: udevd, API VFS mounts: v v v tmpfiles, random mqueue, configfs, local-fs.target swap.target cryptsetup.target seed, sysctl, ...) debugfs, ...) | | | | | \__________________|_________________ | ___________________|____________________/ \|/ v sysinit.target | ____________________________________/|\________________________________________ / | | | \ | | | | | v v | v v (various (various | (various rescue.service timers...) paths...) | sockets...) | | | | | v v v | v rescue.target timers.target paths.target | sockets.target | | | | v \_________________ | ___________________/ \|/ v basic.target | ____________________________________/| emergency.service / | | | | | | v v v v emergency.target display- (various system (various system manager.service services services) | required for | | graphical UIs) v | | multi-user.target | | | \_________________ | _________________/ \|/ v graphical.target Target units that are commonly used as boot targets are emphasized. These units are good choices as goal targets, for example by passing them to the systemd.unit= kernel command line option (see systemd1) or by symlinking default.target to them. timers.target is pulled-in by basic.target asynchronously. This allows timers units to depend on services which become only available later in boot. Bootup in the Initial RAM Disk (initrd) The initial RAM disk implementation (initrd) can be set up using systemd as well. In this case, boot up inside the initrd follows the following structure. The default target in the initrd is initrd.target. The bootup process begins identical to the system manager bootup (see above) until it reaches basic.target. From there, systemd approaches the special target initrd.target. If the root device can be mounted at /sysroot, the sysroot.mount unit becomes active and initrd-root-fs.target is reached. The service initrd-parse-etc.service scans /sysroot/etc/fstab for a possible /usr mount point and additional entries marked with the x-initrd.mount option. All entries found are mounted below /sysroot, and initrd-fs.target is reached. The service initrd-cleanup.service isolates to the initrd-switch-root.target, where cleanup services can run. As the very last step, the initrd-switch-root.service is activated, which will cause the system to switch its root to /sysroot. : (beginning identical to above) : v basic.target | emergency.service ______________________/| | / | v | sysroot.mount emergency.target | | | v | initrd-root-fs.target | | | v v initrd-parse-etc.service (custom initrd | services...) v | (sysroot-usr.mount and | various mounts marked | with fstab option | x-initrd.mount...) | | | v | initrd-fs.target \______________________ | \| v initrd.target | v initrd-cleanup.service isolates to initrd-switch-root.target | v ______________________/| / v | initrd-udevadm-cleanup-db.service v | (custom initrd | services...) | \______________________ | \| v initrd-switch-root.target | v initrd-switch-root.service | v Transition to Host OS System Manager Shutdown System shutdown with systemd also consists of various target units with some minimal ordering structure applied: (conflicts with (conflicts with all system all file system services) mounts, swaps, | cryptsetup | devices, ...) | | v v shutdown.target umount.target | | \_______ ______/ \ / v (various low-level services) | v final.target | _____________________________________/ \_________________________________ / | | \ | | | | v v v v systemd-reboot.service systemd-poweroff.service systemd-halt.service systemd-kexec.service | | | | v v v v reboot.target poweroff.target halt.target kexec.target Commonly used system shutdown targets are emphasized. See Also systemd1, boot7, systemd.special7, systemd.target5, dracut8 systemd-229/man/busctl.xml000066400000000000000000000505601265713322000156600ustar00rootroot00000000000000 busctl systemd A monkey with a typewriter Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl busctl 1 busctl Introspect the bus busctl OPTIONS COMMAND NAME Description busctl may be used to introspect and monitor the D-Bus bus. Options The following options are understood: Connect to the bus specified by ADDRESS instead of using suitable defaults for either the system or user bus (see and options). When showing the list of peers, show a column containing the names of containers they belong to. See systemd-machined.service8. When showing the list of peers, show only "unique" names (of the form :number.number). The opposite of — only "well-known" names will be shown. When showing the list of peers, show only peers which have actually not been activated yet, but may be started automatically if accessed. When showing messages being exchanged, show only the subset matching MATCH. When used with the capture command, specifies the maximum bus message size to capture ("snaplen"). Defaults to 4096 bytes. When used with the tree command, shows a flat list of object paths instead of a tree. When used with the call command, suppresses display of the response message payload. Note that even if this option is specified, errors returned will still be printed and the tool will indicate success or failure with the process exit code. When used with the call or get-property command, shows output in a more verbose format. BOOL When used with the call command, specifies whether busctl shall wait for completion of the method call, output the returned method response data, and return success or failure via the process exit code. If this is set to no, the method call will be issued but no response is expected, the tool terminates immediately, and thus no response can be shown, and no success or failure is returned via the exit code. To only suppress output of the reply message payload, use above. Defaults to yes. BOOL When used with the call command, specifies whether the method call should implicitly activate the called service, should it not be running yet but is configured to be auto-started. Defaults to yes. BOOL When used with the call command, specifies whether the services may enforce interactive authorization while executing the operation, if the security policy is configured for this. Defaults to yes. SECS When used with the call command, specifies the maximum time to wait for method call completion. If no time unit is specified, assumes seconds. The usual other units are understood, too (ms, us, s, min, h, d, w, month, y). Note that this timeout does not apply if is used, as the tool does not wait for any reply message then. When not specified or when set to 0, the default of 25s is assumed. BOOL Controls whether credential data reported by list or status shall be augmented with data from /proc. When this is turned on, the data shown is possibly inconsistent, as the data read from /proc might be more recent than the rest of the credential information. Defaults to yes. Commands The following commands are understood: list Show all peers on the bus, by their service names. By default, shows both unique and well-known names, but this may be changed with the and switches. This is the default operation if no command is specified. status SERVICE Show process information and credentials of a bus service (if one is specified by its unique or well-known name), a process (if one is specified by its numeric PID), or the owner of the bus (if no parameter is specified). monitor SERVICE Dump messages being exchanged. If SERVICE is specified, show messages to or from this peer, identified by its well-known or unique name. Otherwise, show all messages on the bus. Use Ctrl-C to terminate the dump. capture SERVICE Similar to monitor but writes the output in pcap format (for details, see the Libpcap File Format description. Make sure to redirect the output to STDOUT to a file. Tools like wireshark1 may be used to dissect and view the generated files. tree SERVICE Shows an object tree of one or more services. If SERVICE is specified, show object tree of the specified services only. Otherwise, show all object trees of all services on the bus that acquired at least one well-known name. introspect SERVICE OBJECT INTERFACE Show interfaces, methods, properties and signals of the specified object (identified by its path) on the specified service. If the interface argument is passed, the output is limited to members of the specified interface. call SERVICE OBJECT INTERFACE METHOD SIGNATURE ARGUMENT Invoke a method and show the response. Takes a service name, object path, interface name and method name. If parameters shall be passed to the method call, a signature string is required, followed by the arguments, individually formatted as strings. For details on the formatting used, see below. To suppress output of the returned data, use the option. get-property SERVICE OBJECT INTERFACE PROPERTY Retrieve the current value of one or more object properties. Takes a service name, object path, interface name and property name. Multiple properties may be specified at once, in which case their values will be shown one after the other, separated by newlines. The output is, by default, in terse format. Use for a more elaborate output format. set-property SERVICE OBJECT INTERFACE PROPERTY SIGNATURE ARGUMENT Set the current value of an object property. Takes a service name, object path, interface name, property name, property signature, followed by a list of parameters formatted as strings. help Show command syntax help. Parameter Formatting The call and set-property commands take a signature string followed by a list of parameters formatted as string (for details on D-Bus signature strings, see the Type system chapter of the D-Bus specification). For simple types, each parameter following the signature should simply be the parameter's value formatted as string. Positive boolean values may be formatted as true, yes, on, or 1; negative boolean values may be specified as false, no, off, or 0. For arrays, a numeric argument for the number of entries followed by the entries shall be specified. For variants, the signature of the contents shall be specified, followed by the contents. For dictionaries and structs, the contents of them shall be directly specified. For example, s jawoll is the formatting of a single string jawoll. as 3 hello world foobar is the formatting of a string array with three entries, hello, world and foobar. a{sv} 3 One s Eins Two u 2 Yes b true is the formatting of a dictionary array that maps strings to variants, consisting of three entries. The string One is assigned the string Eins. The string Two is assigned the 32-bit unsigned integer 2. The string Yes is assigned a positive boolean. Note that the call, get-property, introspect commands will also generate output in this format for the returned data. Since this format is sometimes too terse to be easily understood, the call and get-property commands may generate a more verbose, multi-line output when passed the option. Examples Write and Read a Property The following two commands first write a property and then read it back. The property is found on the /org/freedesktop/systemd1 object of the org.freedesktop.systemd1 service. The name of the property is LogLevel on the org.freedesktop.systemd1.Manager interface. The property contains a single string: # busctl set-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager LogLevel s debug # busctl get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager LogLevel s "debug" Terse and Verbose Output The following two commands read a property that contains an array of strings, and first show it in terse format, followed by verbose format: $ busctl get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager Environment as 2 "LANG=en_US.UTF-8" "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin" $ busctl get-property --verbose org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager Environment ARRAY "s" { STRING "LANG=en_US.UTF-8"; STRING "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"; }; Invoking a Method The following command invokes the StartUnit method on the org.freedesktop.systemd1.Manager interface of the /org/freedesktop/systemd1 object of the org.freedesktop.systemd1 service, and passes it two strings cups.service and replace. As a result of the method call, a single object path parameter is received and shown: # busctl call org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager StartUnit ss "cups.service" "replace" o "/org/freedesktop/systemd1/job/42684" See Also dbus-daemon1, D-Bus, sd-bus3, systemd1, systemd-bus-proxyd8, machinectl1, wireshark1 systemd-229/man/coredump.conf.xml000066400000000000000000000134571265713322000171320ustar00rootroot00000000000000 coredump.conf systemd Developer Lennart Poettering lennart@poettering.net coredump.conf 5 coredump.conf coredump.conf.d Coredump storage configuration files /etc/systemd/coredump.conf /etc/systemd/coredump.conf.d/*.conf /run/systemd/coredump.conf.d/*.conf /usr/lib/systemd/coredump.conf.d/*.conf Description These files configure the behavior of systemd-coredump8, a handler for core dumps invoked by the kernel. Options All options are configured in the [Coredump] section: Storage= Controls where to store cores. One of none, external, journal, and both. When none, the coredumps will be logged but not stored permanently. When external (the default), cores will be stored in /var/lib/systemd/coredump. When journal, cores will be stored in the journal and rotated following normal journal rotation patterns. When both, cores will be stored in both locations. When cores are stored in the journal, they might be compressed following journal compression settings, see journald.conf5. When cores are stored externally, they will be compressed by default, see below. Compress= Controls compression for external storage. Takes a boolean argument, which defaults to yes. ProcessSizeMax= The maximum size in bytes of a core which will be processed. Coredumps exceeding this size will be logged, but the backtrace will not be generated and the core will not be stored. ExternalSizeMax= JournalSizeMax= The maximum (uncompressed) size in bytes of a core to be saved. MaxUse= KeepFree= Enforce limits on the disk space taken up by externally stored coredumps. makes sure that old coredumps are removed as soon as the total disk space taken up by coredumps grows beyond this limit (defaults to 10% of the total disk size). controls how much disk space to keep free at least (defaults to 15% of the total disk size). Note that the disk space used by coredumps might temporarily exceed these limits while coredumps are processed. Note that old coredumps are also removed based on time via systemd-tmpfiles8. Set either value to 0 to turn off size-based clean-up. See Also systemd-journald.service8, coredumpctl1, systemd-tmpfiles8 systemd-229/man/coredumpctl.xml000066400000000000000000000167601265713322000167110ustar00rootroot00000000000000 coredumpctl systemd Developer Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl coredumpctl 1 coredumpctl Retrieve coredumps from the journal coredumpctl OPTIONS COMMAND PID|COMM|EXE|MATCH Description coredumpctl may be used to retrieve coredumps from systemd-journald8. Options The following options are understood: Do not print column headers. Show information of a single coredump only, instead of listing all known coredumps. FIELD FIELD Print all possible data values the specified field takes in matching coredump entries of the journal. FILE FILE Write the core to . DIR DIR Use the journal files in the specified . The following commands are understood: list List coredumps captured in the journal matching specified characteristics. If no command is specified, this is the implied default. info Show detailed information about coredumps captured in the journal. dump Extract the last coredump matching specified characteristics. The coredump will be written on standard output, unless an output file is specified with . gdb Invoke the GNU debugger on the last coredump matching specified characteristics. Matching A match can be: PID Process ID of the process that dumped core. An integer. COMM Name of the executable (matches ). Must not contain slashes. EXE Path to the executable (matches ). Must contain at least one slash. MATCH General journalctl predicates (see journalctl1). Must contain an equal sign. Exit status On success, 0 is returned; otherwise, a non-zero failure code is returned. Not finding any matching coredumps is treated as failure. Examples List all the coredumps of a program named foo # coredumpctl list foo Invoke gdb on the last coredump # coredumpctl gdb Show information about a process that dumped core, matching by its PID 6654 # coredumpctl info 6654 Extract the last coredump of /usr/bin/bar to a file named <filename noindex="true">bar.coredump</filename> # coredumpctl -o bar.coredump dump /usr/bin/bar See Also systemd-coredump8, coredump.conf5, systemd-journald.service8, gdb1 systemd-229/man/crypttab.xml000066400000000000000000000410531265713322000162110ustar00rootroot00000000000000 crypttab systemd Documentation Miloslav Trmac mitr@redhat.com Documentation Lennart Poettering lennart@poettering.net crypttab 5 crypttab Configuration for encrypted block devices /etc/crypttab Description The /etc/crypttab file describes encrypted block devices that are set up during system boot. Empty lines and lines starting with the # character are ignored. Each of the remaining lines describes one encrypted block device, fields on the line are delimited by white space. The first two fields are mandatory, the remaining two are optional. Setting up encrypted block devices using this file supports three encryption modes: LUKS, TrueCrypt and plain. See cryptsetup8 for more information about each mode. When no mode is specified in the options field and the block device contains a LUKS signature, it is opened as a LUKS device; otherwise, it is assumed to be in raw dm-crypt (plain mode) format. The first field contains the name of the resulting encrypted block device; the device is set up within /dev/mapper/. The second field contains a path to the underlying block device or file, or a specification of a block device via UUID= followed by the UUID. The third field specifies the encryption password. If the field is not present or the password is set to none or -, the password has to be manually entered during system boot. Otherwise, the field is interpreted as a absolute path to a file containing the encryption password. For swap encryption, /dev/urandom or the hardware device /dev/hw_random can be used as the password file; using /dev/random may prevent boot completion if the system does not have enough entropy to generate a truly random encryption key. The fourth field, if present, is a comma-delimited list of options. The following options are recognized: Allow discard requests to be passed through the encrypted block device. This improves performance on SSD storage but has security implications. Specifies the cipher to use. See cryptsetup8 for possible values and the default value of this option. A cipher with unpredictable IV values, such as aes-cbc-essiv:sha256, is recommended. Specifies the hash to use for password hashing. See cryptsetup8 for possible values and the default value of this option. Use a detached (separated) metadata device or file where the LUKS header is stored. This option is only relevant for LUKS devices. See cryptsetup8 for possible values and the default value of this option. Start offset in the backend device, in 512-byte sectors. This option is only relevant for plain devices. How many 512-byte sectors of the encrypted data to skip at the beginning. This is different from the option with respect to the sector numbers used in initialization vector (IV) calculation. Using will shift the IV calculation by the same negative amount. Hence, if is given, sector n will get a sector number of 0 for the IV calculation. Using causes sector n to also be the first sector of the mapped device, but with its number for IV generation being n. This option is only relevant for plain devices. Specifies the number of bytes to skip at the start of the key file. See cryptsetup8 for possible values and the default value of this option. Specifies the maximum number of bytes to read from the key file. See cryptsetup8 for possible values and the default value of this option. This option is ignored in plain encryption mode, as the key file size is then given by the key size. Specifies the key slot to compare the passphrase or key against. If the key slot does not match the given passphrase or key, but another would, the setup of the device will fail regardless. This option implies . See cryptsetup8 for possible values. The default is to try all key slots in sequential order. Force LUKS mode. When this mode is used, the following options are ignored since they are provided by the LUKS header on the device: , , . This device will not be automatically unlocked on boot. The system will not wait for the device to show up and be unlocked at boot, and not fail the boot if it does not show up. Force plain encryption mode. Set up the encrypted block device in read-only mode. Specifies the key size in bits. See cryptsetup8 for possible values and the default value of this option. The encrypted block device will be used as a swap device, and will be formatted accordingly after setting up the encrypted block device, with mkswap8. This option implies . WARNING: Using the option will destroy the contents of the named partition during every boot, so make sure the underlying block device is specified correctly. Use TrueCrypt encryption mode. When this mode is used, the following options are ignored since they are provided by the TrueCrypt header on the device or do not apply: , , , , . When this mode is used, the passphrase is read from the key file given in the third field. Only the first line of this file is read, excluding the new line character. Note that the TrueCrypt format uses both passphrase and key files to derive a password for the volume. Therefore, the passphrase and all key files need to be provided. Use to provide the absolute path to all key files. When using an empty passphrase in combination with one or more key files, use /dev/null as the password file in the third field. Use the hidden TrueCrypt volume. This option implies . This will map the hidden volume that is inside of the volume provided in the second field. Please note that there is no protection for the hidden volume if the outer volume is mounted instead. See cryptsetup8 for more information on this limitation. Specifies the absolute path to a key file to use for a TrueCrypt volume. This implies and can be used more than once to provide several key files. See the entry for on the behavior of the passphrase and key files when using TrueCrypt encryption mode. Use TrueCrypt in system encryption mode. This option implies . Specifies the timeout for querying for a password. If no unit is specified, seconds is used. Supported units are s, ms, us, min, h, d. A timeout of 0 waits indefinitely (which is the default). Specifies how long systemd should wait for a device to show up before giving up on the entry. The argument is a time in seconds or explicitly specified units of s, min, h, ms. The encrypted block device will be prepared for using it as /tmp; it will be formatted using mke2fs8. This option implies . WARNING: Using the option will destroy the contents of the named partition during every boot, so make sure the underlying block device is specified correctly. Specifies the maximum number of times the user is queried for a password. The default is 3. If set to 0, the user is queried for a password indefinitely. If the encryption password is read from console, it has to be entered twice to prevent typos. At early boot and when the system manager configuration is reloaded, this file is translated into native systemd units by systemd-cryptsetup-generator8. Example /etc/crypttab example Set up four encrypted block devices. One using LUKS for normal storage, another one for usage as a swap device and two TrueCrypt volumes. luks UUID=2505567a-9e27-4efe-a4d5-15ad146c258b swap /dev/sda7 /dev/urandom swap truecrypt /dev/sda2 /etc/container_password tcrypt hidden /mnt/tc_hidden /dev/null tcrypt-hidden,tcrypt-keyfile=/etc/keyfile See Also systemd1, systemd-cryptsetup@.service8, systemd-cryptsetup-generator8, cryptsetup8, mkswap8, mke2fs8 systemd-229/man/custom-html.xsl000066400000000000000000000266261265713322000166540ustar00rootroot00000000000000 .html# http://man7.org/linux/man-pages/man / . .html http://linux.die.net/man/ / https://www.mankier.com/ / https://www.archlinux.org/ / . .html https://www.freebsd.org/cgi/man.cgi? ( ) http://dbus.freedesktop.org/doc/ . .html
index.html Index · systemd.directives.html Directives systemd
" "
systemd-229/man/custom-man.xsl000066400000000000000000000042121265713322000164460ustar00rootroot00000000000000 .TH " " " " "" "systemd " " " " " systemd-229/man/daemon.xml000066400000000000000000001112631265713322000156250ustar00rootroot00000000000000 daemon systemd Developer Lennart Poettering lennart@poettering.net daemon 7 daemon Writing and packaging system daemons Description A daemon is a service process that runs in the background and supervises the system or provides functionality to other processes. Traditionally, daemons are implemented following a scheme originating in SysV Unix. Modern daemons should follow a simpler yet more powerful scheme (here called "new-style" daemons), as implemented by systemd1. This manual page covers both schemes, and in particular includes recommendations for daemons that shall be included in the systemd init system. SysV Daemons When a traditional SysV daemon starts, it should execute the following steps as part of the initialization. Note that these steps are unnecessary for new-style daemons (see below), and should only be implemented if compatibility with SysV is essential. Close all open file descriptors except standard input, output, and error (i.e. the first three file descriptors 0, 1, 2). This ensures that no accidentally passed file descriptor stays around in the daemon process. On Linux, this is best implemented by iterating through /proc/self/fd, with a fallback of iterating from file descriptor 3 to the value returned by getrlimit() for RLIMIT_NOFILE. Reset all signal handlers to their default. This is best done by iterating through the available signals up to the limit of _NSIG and resetting them to SIG_DFL. Reset the signal mask using sigprocmask(). Sanitize the environment block, removing or resetting environment variables that might negatively impact daemon runtime. Call fork(), to create a background process. In the child, call setsid() to detach from any terminal and create an independent session. In the child, call fork() again, to ensure that the daemon can never re-acquire a terminal again. Call exit() in the first child, so that only the second child (the actual daemon process) stays around. This ensures that the daemon process is re-parented to init/PID 1, as all daemons should be. In the daemon process, connect /dev/null to standard input, output, and error. In the daemon process, reset the umask to 0, so that the file modes passed to open(), mkdir() and suchlike directly control the access mode of the created files and directories. In the daemon process, change the current directory to the root directory (/), in order to avoid that the daemon involuntarily blocks mount points from being unmounted. In the daemon process, write the daemon PID (as returned by getpid()) to a PID file, for example /run/foobar.pid (for a hypothetical daemon "foobar") to ensure that the daemon cannot be started more than once. This must be implemented in race-free fashion so that the PID file is only updated when it is verified at the same time that the PID previously stored in the PID file no longer exists or belongs to a foreign process. In the daemon process, drop privileges, if possible and applicable. From the daemon process, notify the original process started that initialization is complete. This can be implemented via an unnamed pipe or similar communication channel that is created before the first fork() and hence available in both the original and the daemon process. Call exit() in the original process. The process that invoked the daemon must be able to rely on that this exit() happens after initialization is complete and all external communication channels are established and accessible. The BSD daemon() function should not be used, as it implements only a subset of these steps. A daemon that needs to provide compatibility with SysV systems should implement the scheme pointed out above. However, it is recommended to make this behavior optional and configurable via a command line argument to ease debugging as well as to simplify integration into systems using systemd. New-Style Daemons Modern services for Linux should be implemented as new-style daemons. This makes it easier to supervise and control them at runtime and simplifies their implementation. For developing a new-style daemon, none of the initialization steps recommended for SysV daemons need to be implemented. New-style init systems such as systemd make all of them redundant. Moreover, since some of these steps interfere with process monitoring, file descriptor passing and other functionality of the init system, it is recommended not to execute them when run as new-style service. Note that new-style init systems guarantee execution of daemon processes in a clean process context: it is guaranteed that the environment block is sanitized, that the signal handlers and mask is reset and that no left-over file descriptors are passed. Daemons will be executed in their own session, with standard input/output/error connected to /dev/null unless otherwise configured. The umask is reset. It is recommended for new-style daemons to implement the following: If SIGTERM is received, shut down the daemon and exit cleanly. If SIGHUP is received, reload the configuration files, if this applies. Provide a correct exit code from the main daemon process, as this is used by the init system to detect service errors and problems. It is recommended to follow the exit code scheme as defined in the LSB recommendations for SysV init scripts. If possible and applicable, expose the daemon's control interface via the D-Bus IPC system and grab a bus name as last step of initialization. For integration in systemd, provide a .service unit file that carries information about starting, stopping and otherwise maintaining the daemon. See systemd.service5 for details. As much as possible, rely on the init system's functionality to limit the access of the daemon to files, services and other resources, i.e. in the case of systemd, rely on systemd's resource limit control instead of implementing your own, rely on systemd's privilege dropping code instead of implementing it in the daemon, and similar. See systemd.exec5 for the available controls. If D-Bus is used, make your daemon bus-activatable by supplying a D-Bus service activation configuration file. This has multiple advantages: your daemon may be started lazily on-demand; it may be started in parallel to other daemons requiring it -- which maximizes parallelization and boot-up speed; your daemon can be restarted on failure without losing any bus requests, as the bus queues requests for activatable services. See below for details. If your daemon provides services to other local processes or remote clients via a socket, it should be made socket-activatable following the scheme pointed out below. Like D-Bus activation, this enables on-demand starting of services as well as it allows improved parallelization of service start-up. Also, for state-less protocols (such as syslog, DNS), a daemon implementing socket-based activation can be restarted without losing a single request. See below for details. If applicable, a daemon should notify the init system about startup completion or status updates via the sd_notify3 interface. Instead of using the syslog() call to log directly to the system syslog service, a new-style daemon may choose to simply log to standard error via fprintf(), which is then forwarded to syslog by the init system. If log levels are necessary, these can be encoded by prefixing individual log lines with strings like <4> (for log level 4 "WARNING" in the syslog priority scheme), following a similar style as the Linux kernel's printk() level system. For details, see sd-daemon3 and systemd.exec5. These recommendations are similar but not identical to the Apple MacOS X Daemon Requirements. Activation New-style init systems provide multiple additional mechanisms to activate services, as detailed below. It is common that services are configured to be activated via more than one mechanism at the same time. An example for systemd: bluetoothd.service might get activated either when Bluetooth hardware is plugged in, or when an application accesses its programming interfaces via D-Bus. Or, a print server daemon might get activated when traffic arrives at an IPP port, or when a printer is plugged in, or when a file is queued in the printer spool directory. Even for services that are intended to be started on system bootup unconditionally, it is a good idea to implement some of the various activation schemes outlined below, in order to maximize parallelization. If a daemon implements a D-Bus service or listening socket, implementing the full bus and socket activation scheme allows starting of the daemon with its clients in parallel (which speeds up boot-up), since all its communication channels are established already, and no request is lost because client requests will be queued by the bus system (in case of D-Bus) or the kernel (in case of sockets) until the activation is completed. Activation on Boot Old-style daemons are usually activated exclusively on boot (and manually by the administrator) via SysV init scripts, as detailed in the LSB Linux Standard Base Core Specification. This method of activation is supported ubiquitously on Linux init systems, both old-style and new-style systems. Among other issues, SysV init scripts have the disadvantage of involving shell scripts in the boot process. New-style init systems generally employ updated versions of activation, both during boot-up and during runtime and using more minimal service description files. In systemd, if the developer or administrator wants to make sure that a service or other unit is activated automatically on boot, it is recommended to place a symlink to the unit file in the .wants/ directory of either multi-user.target or graphical.target, which are normally used as boot targets at system startup. See systemd.unit5 for details about the .wants/ directories, and systemd.special7 for details about the two boot targets. Socket-Based Activation In order to maximize the possible parallelization and robustness and simplify configuration and development, it is recommended for all new-style daemons that communicate via listening sockets to employ socket-based activation. In a socket-based activation scheme, the creation and binding of the listening socket as primary communication channel of daemons to local (and sometimes remote) clients is moved out of the daemon code and into the init system. Based on per-daemon configuration, the init system installs the sockets and then hands them off to the spawned process as soon as the respective daemon is to be started. Optionally, activation of the service can be delayed until the first inbound traffic arrives at the socket to implement on-demand activation of daemons. However, the primary advantage of this scheme is that all providers and all consumers of the sockets can be started in parallel as soon as all sockets are established. In addition to that, daemons can be restarted with losing only a minimal number of client transactions, or even any client request at all (the latter is particularly true for state-less protocols, such as DNS or syslog), because the socket stays bound and accessible during the restart, and all requests are queued while the daemon cannot process them. New-style daemons which support socket activation must be able to receive their sockets from the init system instead of creating and binding them themselves. For details about the programming interfaces for this scheme provided by systemd, see sd_listen_fds3 and sd-daemon3. For details about porting existing daemons to socket-based activation, see below. With minimal effort, it is possible to implement socket-based activation in addition to traditional internal socket creation in the same codebase in order to support both new-style and old-style init systems from the same daemon binary. systemd implements socket-based activation via .socket units, which are described in systemd.socket5. When configuring socket units for socket-based activation, it is essential that all listening sockets are pulled in by the special target unit sockets.target. It is recommended to place a WantedBy=sockets.target directive in the [Install] section to automatically add such a dependency on installation of a socket unit. Unless DefaultDependencies=no is set, the necessary ordering dependencies are implicitly created for all socket units. For more information about sockets.target, see systemd.special7. It is not necessary or recommended to place any additional dependencies on socket units (for example from multi-user.target or suchlike) when one is installed in sockets.target. Bus-Based Activation When the D-Bus IPC system is used for communication with clients, new-style daemons should employ bus activation so that they are automatically activated when a client application accesses their IPC interfaces. This is configured in D-Bus service files (not to be confused with systemd service unit files!). To ensure that D-Bus uses systemd to start-up and maintain the daemon, use the SystemdService= directive in these service files to configure the matching systemd service for a D-Bus service. e.g.: For a D-Bus service whose D-Bus activation file is named org.freedesktop.RealtimeKit.service, make sure to set SystemdService=rtkit-daemon.service in that file to bind it to the systemd service rtkit-daemon.service. This is needed to make sure that the daemon is started in a race-free fashion when activated via multiple mechanisms simultaneously. Device-Based Activation Often, daemons that manage a particular type of hardware should be activated only when the hardware of the respective kind is plugged in or otherwise becomes available. In a new-style init system, it is possible to bind activation to hardware plug/unplug events. In systemd, kernel devices appearing in the sysfs/udev device tree can be exposed as units if they are tagged with the string systemd. Like any other kind of unit, they may then pull in other units when activated (i.e. plugged in) and thus implement device-based activation. systemd dependencies may be encoded in the udev database via the SYSTEMD_WANTS= property. See systemd.device5 for details. Often, it is nicer to pull in services from devices only indirectly via dedicated targets. Example: Instead of pulling in bluetoothd.service from all the various bluetooth dongles and other hardware available, pull in bluetooth.target from them and bluetoothd.service from that target. This provides for nicer abstraction and gives administrators the option to enable bluetoothd.service via controlling a bluetooth.target.wants/ symlink uniformly with a command like enable of systemctl1 instead of manipulating the udev ruleset. Path-Based Activation Often, runtime of daemons processing spool files or directories (such as a printing system) can be delayed until these file system objects change state, or become non-empty. New-style init systems provide a way to bind service activation to file system changes. systemd implements this scheme via path-based activation configured in .path units, as outlined in systemd.path5. Timer-Based Activation Some daemons that implement clean-up jobs that are intended to be executed in regular intervals benefit from timer-based activation. In systemd, this is implemented via .timer units, as described in systemd.timer5. Other Forms of Activation Other forms of activation have been suggested and implemented in some systems. However, there are often simpler or better alternatives, or they can be put together of combinations of the schemes above. Example: Sometimes, it appears useful to start daemons or .socket units when a specific IP address is configured on a network interface, because network sockets shall be bound to the address. However, an alternative to implement this is by utilizing the Linux IP_FREEBIND socket option, as accessible via FreeBind=yes in systemd socket files (see systemd.socket5 for details). This option, when enabled, allows sockets to be bound to a non-local, not configured IP address, and hence allows bindings to a particular IP address before it actually becomes available, making such an explicit dependency to the configured address redundant. Another often suggested trigger for service activation is low system load. However, here too, a more convincing approach might be to make proper use of features of the operating system, in particular, the CPU or I/O scheduler of Linux. Instead of scheduling jobs from userspace based on monitoring the OS scheduler, it is advisable to leave the scheduling of processes to the OS scheduler itself. systemd provides fine-grained access to the CPU and I/O schedulers. If a process executed by the init system shall not negatively impact the amount of CPU or I/O bandwidth available to other processes, it should be configured with CPUSchedulingPolicy=idle and/or IOSchedulingClass=idle. Optionally, this may be combined with timer-based activation to schedule background jobs during runtime and with minimal impact on the system, and remove it from the boot phase itself. Integration with Systemd Writing Systemd Unit Files When writing systemd unit files, it is recommended to consider the following suggestions: If possible, do not use the Type=forking setting in service files. But if you do, make sure to set the PID file path using PIDFile=. See systemd.service5 for details. If your daemon registers a D-Bus name on the bus, make sure to use Type=dbus in the service file if possible. Make sure to set a good human-readable description string with Description=. Do not disable DefaultDependencies=, unless you really know what you do and your unit is involved in early boot or late system shutdown. Normally, little if any dependencies should need to be defined explicitly. However, if you do configure explicit dependencies, only refer to unit names listed on systemd.special7 or names introduced by your own package to keep the unit file operating system-independent. Make sure to include an [Install] section including installation information for the unit file. See systemd.unit5 for details. To activate your service on boot, make sure to add a WantedBy=multi-user.target or WantedBy=graphical.target directive. To activate your socket on boot, make sure to add WantedBy=sockets.target. Usually, you also want to make sure that when your service is installed, your socket is installed too, hence add Also=foo.socket in your service file foo.service, for a hypothetical program foo. Installing Systemd Service Files At the build installation time (e.g. make install during package build), packages are recommended to install their systemd unit files in the directory returned by pkg-config systemd --variable=systemdsystemunitdir (for system services) or pkg-config systemd --variable=systemduserunitdir (for user services). This will make the services available in the system on explicit request but not activate them automatically during boot. Optionally, during package installation (e.g. rpm -i by the administrator), symlinks should be created in the systemd configuration directories via the enable command of the systemctl1 tool to activate them automatically on boot. Packages using autoconf1 are recommended to use a configure script excerpt like the following to determine the unit installation path during source configuration: PKG_PROG_PKG_CONFIG AC_ARG_WITH([systemdsystemunitdir], [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],, [with_systemdsystemunitdir=auto]) AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [ def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd) AS_IF([test "x$def_systemdsystemunitdir" = "x"], [AS_IF([test "x$with_systemdsystemunitdir" = "xyes"], [AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])]) with_systemdsystemunitdir=no], [with_systemdsystemunitdir="$def_systemdsystemunitdir"])]) AS_IF([test "x$with_systemdsystemunitdir" != "xno"], [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])]) AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"]) This snippet allows automatic installation of the unit files on systemd machines, and optionally allows their installation even on machines lacking systemd. (Modification of this snippet for the user unit directory is left as an exercise for the reader.) Additionally, to ensure that make distcheck continues to work, it is recommended to add the following to the top-level Makefile.am file in automake1-based projects: DISTCHECK_CONFIGURE_FLAGS = \ --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir) Finally, unit files should be installed in the system with an automake excerpt like the following: if HAVE_SYSTEMD systemdsystemunit_DATA = \ foobar.socket \ foobar.service endif In the rpm8 .spec file, use snippets like the following to enable/disable the service during installation/deinstallation. This makes use of the RPM macros shipped along systemd. Consult the packaging guidelines of your distribution for details and the equivalent for other package managers. At the top of the file: BuildRequires: systemd %{?systemd_requires} And as scriptlets, further down: %post %systemd_post foobar.service foobar.socket %preun %systemd_preun foobar.service foobar.socket %postun %systemd_postun If the service shall be restarted during upgrades, replace the %postun scriptlet above with the following: %postun %systemd_postun_with_restart foobar.service Note that %systemd_post and %systemd_preun expect the names of all units that are installed/removed as arguments, separated by spaces. %systemd_postun expects no arguments. %systemd_postun_with_restart expects the units to restart as arguments. To facilitate upgrades from a package version that shipped only SysV init scripts to a package version that ships both a SysV init script and a native systemd service file, use a fragment like the following: %triggerun -- foobar < 0.47.11-1 if /sbin/chkconfig --level 5 foobar ; then /bin/systemctl --no-reload enable foobar.service foobar.socket >/dev/null 2>&1 || : fi Where 0.47.11-1 is the first package version that includes the native unit file. This fragment will ensure that the first time the unit file is installed, it will be enabled if and only if the SysV init script is enabled, thus making sure that the enable status is not changed. Note that chkconfig is a command specific to Fedora which can be used to check whether a SysV init script is enabled. Other operating systems will have to use different commands here. Porting Existing Daemons Since new-style init systems such as systemd are compatible with traditional SysV init systems, it is not strictly necessary to port existing daemons to the new style. However, doing so offers additional functionality to the daemons as well as simplifying integration into new-style init systems. To port an existing SysV compatible daemon, the following steps are recommended: If not already implemented, add an optional command line switch to the daemon to disable daemonization. This is useful not only for using the daemon in new-style init systems, but also to ease debugging. If the daemon offers interfaces to other software running on the local system via local AF_UNIX sockets, consider implementing socket-based activation (see above). Usually, a minimal patch is sufficient to implement this: Extend the socket creation in the daemon code so that sd_listen_fds3 is checked for already passed sockets first. If sockets are passed (i.e. when sd_listen_fds() returns a positive value), skip the socket creation step and use the passed sockets. Secondly, ensure that the file system socket nodes for local AF_UNIX sockets used in the socket-based activation are not removed when the daemon shuts down, if sockets have been passed. Third, if the daemon normally closes all remaining open file descriptors as part of its initialization, the sockets passed from the init system must be spared. Since new-style init systems guarantee that no left-over file descriptors are passed to executed processes, it might be a good choice to simply skip the closing of all remaining open file descriptors if sockets are passed. Write and install a systemd unit file for the service (and the sockets if socket-based activation is used, as well as a path unit file, if the daemon processes a spool directory), see above for details. If the daemon exposes interfaces via D-Bus, write and install a D-Bus activation file for the service, see above for details. Placing Daemon Data It is recommended to follow the general guidelines for placing package files, as discussed in file-hierarchy7. See Also systemd1, sd-daemon3, sd_listen_fds3, sd_notify3, daemon3, systemd.service5, file-hierarchy7 systemd-229/man/dnssec-trust-anchors.d.xml000066400000000000000000000221371265713322000206760ustar00rootroot00000000000000 dnssec-trust-anchors.d systemd Developer Lennart Poettering lennart@poettering.net dnssec-trust-anchors.d 5 dnssec-trust-anchors.d systemd.positive systemd.negative DNSSEC trust anchor configuration files /etc/dnssec-trust-anchors.d/*.positive /run/dnssec-trust-anchors.d/*.positive /usr/lib/dnssec-trust-anchors.d/*.positive /etc/dnssec-trust-anchors.d/*.negative /run/dnssec-trust-anchors.d/*.negative /usr/lib/dnssec-trust-anchors.d/*.negative Description The DNSSEC trust anchor configuration files define positive and negative trust anchors systemd-resolved.service8 bases DNSSEC integrity proofs on. Positive Trust Anchors Positive trust anchor configuration files contain DNSKEY and DS resource record definitions to use as base for DNSSEC integrity proofs. See RFC 4035, Section 4.4 for more information about DNSSEC trust anchors. Positive trust anchors are read from files with the suffix .positive located in /etc/dnssec-trust-anchors.d/, /run/dnssec-trust-anchors.d/ and /usr/lib/dnssec-trust-anchors.d/. These directories are searched in the specified order, and a trust anchor file of the same name in an earlier path overrides a trust anchor files in a later path. To disable a trust anchor file shipped in /usr/lib/dnssec-trust-anchors.d/ it is sufficient to provide an identically-named file in /etc/dnssec-trust-anchors.d/ or /run/dnssec-trust-anchors.d/ that is either empty or a symlink to /dev/null ("masked"). Positive trust anchor files are simple text files resembling DNS zone files, as documented in RFC 1035, Section 5. One DS or DNSKEY resource record may be listed per line. Empty lines and lines starting with a semicolon (;) are ignored and considered comments. A DS resource record is specified like in the following example: . IN DS 19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5 The first word specifies the domain, use . for the root domain. The domain may be specified with or without trailing dot, which is considered equivalent. The second word must be IN the third word DS. The following words specify the key tag, signature algorithm, digest algorithm, followed by the hex-encoded key fingerprint. See RFC 4034, Section 5 for details about the precise syntax and meaning of these fields. Alternatively, DNSKEY resource records may be used to define trust anchors, like in the following example: . IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0= The first word specifies the domain again, the second word must be IN, followed by DNSKEY. The subsequent words encode the DNSKEY flags, protocol and algorithm fields, followed by the key data encoded in Base64. See RFC 4034, Section 2 for details about the precise syntax and meaning of these fields. If multiple DS or DNSKEY records are defined for the same domain (possibly even in different trust anchor files), all keys are used and are considered equivalent as base for DNSSEC proofs. Note that systemd-resolved will automatically use a built-in trust anchor key for the Internet root domain if no positive trust anchors are defined for the root domain. In most cases it is hence unnecessary to define an explicit key with trust anchor files. The built-in key is disabled as soon as at least one trust anchor key for the root domain is defined in trust anchor files. It is generally recommended to encode trust anchors in DS resource records, rather than DNSKEY resource records. If a trust anchor specified via a DS record is found revoked it is automatically removed from the trust anchor database for the runtime. See RFC 5011 for details about revoked trust anchors. Note that systemd-resolved will not update its trust anchor database from DNS servers automatically. Instead, it is recommended to update the resolver software or update the new trust anchor via adding in new trust anchor files. The current DNSSEC trust anchor for the Internet's root domain is available at the IANA Trust Anchor and Keys page. Negative Trust Anchors Negative trust anchors define domains where DNSSEC validation shall be turned off. Negative trust anchor files are found at the same location as positive trust anchor files, and follow the same overriding rules. They are text files with the .negative suffix. Empty lines and lines whose first character is ; are ignored. Each line specifies one domain name where DNSSEC validation shall be disabled on. Negative trust anchors are useful to support private DNS subtrees that are not referenced from the Internet DNS hierarchy, and not signed. RFC 7646 for details on negative trust anchors. If no negative trust anchor files are configured a built-in set of well-known private DNS zone domains is used as negative trust anchors. It is also possibly to define per-interface negative trust anchors using the DNSSECNegativeTrustAnchors= setting in systemd.network5 files. See Also systemd1, systemd-resolved.service8, resolved.conf5, systemd.network5 systemd-229/man/file-hierarchy.xml000066400000000000000000001134051265713322000172550ustar00rootroot00000000000000 file-hierarchy systemd Developer Lennart Poettering lennart@poettering.net file-hierarchy 7 file-hierarchy File system hierarchy overview Description Operating systems using the systemd1 system and service manager are organized based on a file system hierarchy inspired by UNIX, more specifically the hierarchy described in the File System Hierarchy specification and hier7. This manual page describes a more minimal, modernized subset of these specifications that defines more strictly the suggestions and restrictions systemd makes on the file system hierarchy. Many of the paths described here can be queried with the systemd-path1 tool. General Structure / The file system root. Usually writable, but this is not required. Possibly a temporary file system (tmpfs). Not shared with other hosts (unless read-only). /boot The boot partition used for bringing up the system. On EFI systems, this is possibly the EFI System Partition, also see systemd-gpt-auto-generator8. This directory is usually strictly local to the host, and should be considered read-only, except when a new kernel or boot loader is installed. This directory only exists on systems that run on physical or emulated hardware that requires boot loaders. /etc System-specific configuration. This directory may or may not be read-only. Frequently, this directory is pre-populated with vendor-supplied configuration files, but applications should not make assumptions about this directory being fully populated or populated at all, and should fall back to defaults if configuration is missing. /home The location for normal user's home directories. Possibly shared with other systems, and never read-only. This directory should only be used for normal users, never for system users. This directory and possibly the directories contained within it might only become available or writable in late boot or even only after user authentication. This directory might be placed on limited-functionality network file systems, hence applications should not assume the full set of file API is available on this directory. Applications should generally not reference this directory directly, but via the per-user $HOME environment variable, or via the home directory field of the user database. /root The home directory of the root user. The root user's home directory is located outside of /home in order to make sure the root user may log in even without /home being available and mounted. /srv The place to store general server payload, managed by the administrator. No restrictions are made how this directory is organized internally. Generally writable, and possibly shared among systems. This directory might become available or writable only very late during boot. /tmp The place for small temporary files. This directory is usually mounted as a tmpfs instance, and should hence not be used for larger files. (Use /var/tmp for larger files.) Since the directory is accessible to other users of the system, it is essential that this directory is only written to with the mkstemp3, mkdtemp3 and related calls. This directory is usually flushed at boot-up. Also, files that are not accessed within a certain time are usually automatically deleted. If applications find the environment variable $TMPDIR set, they should prefer using the directory specified in it over directly referencing /tmp (see environ7 and IEEE Std 1003.1 for details). Runtime Data /run A tmpfs file system for system packages to place runtime data in. This directory is flushed on boot, and generally writable for privileged programs only. Always writable. /run/log Runtime system logs. System components may place private logs in this directory. Always writable, even when /var/log might not be accessible yet. /run/user Contains per-user runtime directories, each usually individually mounted tmpfs instances. Always writable, flushed at each reboot and when the user logs out. User code should not reference this directory directly, but via the $XDG_RUNTIME_DIR environment variable, as documented in the XDG Base Directory Specification. Vendor-supplied Operating System Resources /usr Vendor-supplied operating system resources. Usually read-only, but this is not required. Possibly shared between multiple hosts. This directory should not be modified by the administrator, except when installing or removing vendor-supplied packages. /usr/bin Binaries and executables for user commands that shall appear in the $PATH search path. It is recommended not to place binaries in this directory that are not useful for invocation from a shell (such as daemon binaries); these should be placed in a subdirectory of /usr/lib instead. /usr/include C and C++ API header files of system libraries. /usr/lib Static, private vendor data that is compatible with all architectures (though not necessarily architecture-independent). Note that this includes internal executables or other binaries that are not regularly invoked from a shell. Such binaries may be for any architecture supported by the system. Do not place public libraries in this directory, use $libdir (see below), instead. /usr/lib/arch-id Location for placing dynamic libraries into, also called $libdir. The architecture identifier to use is defined on Multiarch Architecture Specifiers (Tuples) list. Legacy locations of $libdir are /usr/lib, /usr/lib64. This directory should not be used for package-specific data, unless this data is architecture-dependent, too. To query $libdir for the primary architecture of the system, invoke: # systemd-path system-library-arch /usr/share Resources shared between multiple packages, such as documentation, man pages, time zone information, fonts and other resources. Usually, the precise location and format of files stored below this directory is subject to specifications that ensure interoperability. /usr/share/doc Documentation for the operating system or system packages. /usr/share/factory/etc Repository for vendor-supplied default configuration files. This directory should be populated with pristine vendor versions of all configuration files that may be placed in /etc. This is useful to compare the local configuration of a system with vendor defaults and to populate the local configuration with defaults. /usr/share/factory/var Similar to /usr/share/factory/etc, but for vendor versions of files in the variable, persistent data directory /var. Persistent Variable System Data /var Persistent, variable system data. Must be writable. This directory might be pre-populated with vendor-supplied data, but applications should be able to reconstruct necessary files and directories in this subhierarchy should they be missing, as the system might start up without this directory being populated. Persistency is recommended, but optional, to support ephemeral systems. This directory might become available or writable only very late during boot. Components that are required to operate during early boot hence shall not unconditionally rely on this directory. /var/cache Persistent system cache data. System components may place non-essential data in this directory. Flushing this directory should have no effect on operation of programs, except for increased runtimes necessary to rebuild these caches. /var/lib Persistent system data. System components may place private data in this directory. /var/log Persistent system logs. System components may place private logs in this directory, though it is recommended to do most logging via the syslog3 and sd_journal_print3 calls. /var/spool Persistent system spool data, such as printer or mail queues. /var/tmp The place for larger and persistent temporary files. In contrast to /tmp, this directory is usually mounted from a persistent physical file system and can thus accept larger files. (Use /tmp for smaller files.) This directory is generally not flushed at boot-up, but time-based cleanup of files that have not been accessed for a certain time is applied. The same security restrictions as with /tmp apply, and hence only mkstemp3, mkdtemp3 or similar calls should be used to make use of this directory. If applications find the environment variable $TMPDIR set, they should prefer using the directory specified in it over directly referencing /var/tmp (see environ7 for details). Virtual Kernel and API File Systems /dev The root directory for device nodes. Usually, this directory is mounted as a devtmpfs instance, but might be of a different type in sandboxed/containerized setups. This directory is managed jointly by the kernel and systemd-udevd8, and should not be written to by other components. A number of special purpose virtual file systems might be mounted below this directory. /dev/shm Place for POSIX shared memory segments, as created via shm_open3. This directory is flushed on boot, and is a tmpfs file system. Since all users have write access to this directory, special care should be taken to avoid name clashes and vulnerabilities. For normal users, shared memory segments in this directory are usually deleted when the user logs out. Usually, it is a better idea to use memory mapped files in /run (for system programs) or $XDG_RUNTIME_DIR (for user programs) instead of POSIX shared memory segments, since these directories are not world-writable and hence not vulnerable to security-sensitive name clashes. /proc A virtual kernel file system exposing the process list and other functionality. This file system is mostly an API to interface with the kernel and not a place where normal files may be stored. For details, see proc5. A number of special purpose virtual file systems might be mounted below this directory. /proc/sys A hierarchy below /proc that exposes a number of kernel tunables. The primary way to configure the settings in this API file tree is via sysctl.d5 files. In sandboxed/containerized setups, this directory is generally mounted read-only. /sys A virtual kernel file system exposing discovered devices and other functionality. This file system is mostly an API to interface with the kernel and not a place where normal files may be stored. In sandboxed/containerized setups, this directory is generally mounted read-only. A number of special purpose virtual file systems might be mounted below this directory. Compatibility Symlinks /bin /sbin /usr/sbin These compatibility symlinks point to /usr/bin, ensuring that scripts and binaries referencing these legacy paths correctly find their binaries. /lib This compatibility symlink points to /usr/lib, ensuring that programs referencing this legacy path correctly find their resources. /lib64 On some architecture ABIs, this compatibility symlink points to $libdir, ensuring that binaries referencing this legacy path correctly find their dynamic loader. This symlink only exists on architectures whose ABI places the dynamic loader in this path. /var/run This compatibility symlink points to /run, ensuring that programs referencing this legacy path correctly find their runtime data. Home Directory User applications may want to place files and directories in the user's home directory. They should follow the following basic structure. Note that some of these directories are also standardized (though more weakly) by the XDG Base Directory Specification. Additional locations for high-level user resources are defined by xdg-user-dirs. ~/.cache Persistent user cache data. User programs may place non-essential data in this directory. Flushing this directory should have no effect on operation of programs, except for increased runtimes necessary to rebuild these caches. If an application finds $XDG_CACHE_HOME set, it should use the directory specified in it instead of this directory. ~/.config Application configuration and state. When a new user is created, this directory will be empty or not exist at all. Applications should fall back to defaults should their configuration or state in this directory be missing. If an application finds $XDG_CONFIG_HOME set, it should use the directory specified in it instead of this directory. ~/.local/bin Executables that shall appear in the user's $PATH search path. It is recommended not to place executables in this directory that are not useful for invocation from a shell; these should be placed in a subdirectory of ~/.local/lib instead. Care should be taken when placing architecture-dependent binaries in this place, which might be problematic if the home directory is shared between multiple hosts with different architectures. ~/.local/lib Static, private vendor data that is compatible with all architectures. ~/.local/lib/arch-id Location for placing public dynamic libraries. The architecture identifier to use is defined on Multiarch Architecture Specifiers (Tuples) list. ~/.local/share Resources shared between multiple packages, such as fonts or artwork. Usually, the precise location and format of files stored below this directory is subject to specifications that ensure interoperability. If an application finds $XDG_DATA_HOME set, it should use the directory specified in it instead of this directory. Unprivileged Write Access Unprivileged processes generally lack write access to most of the hierarchy. The exceptions for normal users are /tmp, /var/tmp, /dev/shm, as well as the home directory $HOME (usually found below /home) and the runtime directory $XDG_RUNTIME_DIR (found below /run/user) of the user, which are all writable. For unprivileged system processes, only /tmp, /var/tmp and /dev/shm are writable. If an unprivileged system process needs a private writable directory in /var or /run, it is recommended to either create it before dropping privileges in the daemon code, to create it via tmpfiles.d5 fragments during boot, or via the RuntimeDirectory= directive of service units (see systemd.unit5 for details). Node Types Unix file systems support different types of file nodes, including regular files, directories, symlinks, character and block device nodes, sockets and FIFOs. It is strongly recommended that /dev is the only location below which device nodes shall be placed. Similarly, /run shall be the only location to place sockets and FIFOs. Regular files, directories and symlinks may be used in all directories. System Packages Developers of system packages should follow strict rules when placing their own files in the file system. The following table lists recommended locations for specific types of files supplied by the vendor. System Package Vendor Files Locations Directory Purpose /usr/bin Package executables that shall appear in the $PATH executable search path, compiled for any of the supported architectures compatible with the operating system. It is not recommended to place internal binaries or binaries that are not commonly invoked from the shell in this directory, such as daemon binaries. As this directory is shared with most other packages of the system, special care should be taken to pick unique names for files placed here, that are unlikely to clash with other package's files. /usr/lib/arch-id Public shared libraries of the package. As above, be careful with using too generic names, and pick unique names for your libraries to place here to avoid name clashes. /usr/lib/package Private static vendor resources of the package, including private binaries and libraries, or any other kind of read-only vendor data. /usr/lib/arch-id/package Private other vendor resources of the package that are architecture-specific and cannot be shared between architectures. Note that this generally does not include private executables since binaries of a specific architecture may be freely invoked from any other supported system architecture. /usr/include/package Public C/C++ APIs of public shared libraries of the package.
Additional static vendor files may be installed in the /usr/share hierarchy to the locations defined by the various relevant specifications. During runtime, and for local configuration and state, additional directories are defined: System Package Variable Files Locations Directory Purpose /etc/package System-specific configuration for the package. It is recommended to default to safe fallbacks if this configuration is missing, if this is possible. Alternatively, a tmpfiles.d5 fragment may be used to copy or symlink the necessary files and directories from /usr/share/factory during boot, via the L or C directives. /run/package Runtime data for the package. Packages must be able to create the necessary subdirectories in this tree on their own, since the directory is flushed automatically on boot. Alternatively, a tmpfiles.d5 fragment may be used to create the necessary directories during boot. Alternatively, the RuntimeDirectory= directive of service units may be used (see systemd.unit5 for details.) /run/log/package Runtime log data for the package. As above, the package needs to make sure to create this directory if necessary, as it will be flushed on every boot. /var/cache/package Persistent cache data of the package. If this directory is flushed, the application should work correctly on next invocation, though possibly slowed down due to the need to rebuild any local cache files. The application must be capable of recreating this directory should it be missing and necessary. /var/lib/package Persistent private data of the package. This is the primary place to put persistent data that does not fall into the other categories listed. Packages should be able to create the necessary subdirectories in this tree on their own, since the directory might be missing on boot. Alternatively, a tmpfiles.d5 fragment may be used to create the necessary directories during boot. /var/log/package Persistent log data of the package. As above, the package should make sure to create this directory if necessary, as it might be missing. /var/spool/package Persistent spool/queue data of the package. As above, the package should make sure to create this directory if necessary, as it might be missing.
User Packages Programs running in user context should follow strict rules when placing their own files in the user's home directory. The following table lists recommended locations in the home directory for specific types of files supplied by the vendor if the application is installed in the home directory. (Note, however, that user applications installed system-wide should follow the rules outlined above regarding placing vendor files.) User Package Vendor File Locations Directory Purpose ~/.local/bin Package executables that shall appear in the $PATH executable search path. It is not recommended to place internal executables or executables that are not commonly invoked from the shell in this directory, such as daemon executables. As this directory is shared with most other packages of the user, special care should be taken to pick unique names for files placed here, that are unlikely to clash with other package's files. ~/.local/lib/arch-id Public shared libraries of the package. As above, be careful with using too generic names, and pick unique names for your libraries to place here to avoid name clashes. ~/.local/lib/package Private, static vendor resources of the package, compatible with any architecture, or any other kind of read-only vendor data. ~/.local/lib/arch-id/package Private other vendor resources of the package that are architecture-specific and cannot be shared between architectures.
Additional static vendor files may be installed in the ~/.local/share hierarchy to the locations defined by the various relevant specifications. During runtime, and for local configuration and state, additional directories are defined: User Package Variable File Locations Directory Purpose ~/.config/package User-specific configuration and state for the package. It is required to default to safe fallbacks if this configuration is missing. $XDG_RUNTIME_DIR/package User runtime data for the package. ~/.cache/package Persistent cache data of the package. If this directory is flushed, the application should work correctly on next invocation, though possibly slowed down due to the need to rebuild any local cache files. The application must be capable of recreating this directory should it be missing and necessary.
See Also systemd1, hier7, systemd-path1, systemd-gpt-auto-generator8, sysctl.d5, tmpfiles.d5, pkg-config1, systemd.unit5
systemd-229/man/glib-event-glue.c000066400000000000000000000045211265713322000167700ustar00rootroot00000000000000/*** Copyright 2014 Tom Gundersen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ***/ #include typedef struct SDEventSource { GSource source; GPollFD pollfd; sd_event *event; } SDEventSource; static gboolean event_prepare(GSource *source, gint *timeout_) { return sd_event_prepare(((SDEventSource *)source)->event) > 0; } static gboolean event_check(GSource *source) { return sd_event_wait(((SDEventSource *)source)->event, 0) > 0; } static gboolean event_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { return sd_event_dispatch(((SDEventSource *)source)->event) > 0; } static void event_finalize(GSource *source) { sd_event_unref(((SDEventSource *)source)->event); } static GSourceFuncs event_funcs = { .prepare = event_prepare, .check = event_check, .dispatch = event_dispatch, .finalize = event_finalize, }; GSource *g_sd_event_create_source(sd_event *event) { SDEventSource *source; source = (SDEventSource *)g_source_new(&event_funcs, sizeof(SDEventSource)); source->event = sd_event_ref(event); source->pollfd.fd = sd_event_get_fd(event); source->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR; g_source_add_poll((GSource *)source, &source->pollfd); return (GSource *)source; } systemd-229/man/halt.xml000066400000000000000000000114571265713322000153160ustar00rootroot00000000000000 halt systemd Developer Lennart Poettering lennart@poettering.net halt 8 halt poweroff reboot Halt, power-off or reboot the machine halt OPTIONS poweroff OPTIONS reboot OPTIONS Description halt, poweroff, reboot may be used to halt, power-off or reboot the machine. Options The following options are understood: Halt the machine, regardless of which one of the three commands is invoked. Power-off the machine, regardless of which one of the three commands is invoked. Reboot the machine, regardless of which one of the three commands is invoked. Force immediate halt, power-off, reboot. Do not contact the init system. Only write wtmp shutdown entry, do not actually halt, power-off, reboot. Do not write wtmp shutdown entry. Do not send wall message before halt, power-off, reboot. Exit status On success, 0 is returned, a non-zero failure code otherwise. Notes These are legacy commands available for compatibility only. See Also systemd1, systemctl1, shutdown8, wall1 systemd-229/man/hostname.xml000066400000000000000000000075261265713322000162060ustar00rootroot00000000000000 hostname systemd Developer Lennart Poettering lennart@poettering.net hostname 5 hostname Local hostname configuration file /etc/hostname Description The /etc/hostname file configures the name of the local system that is set during boot using the sethostname2 system call. It should contain a single newline-terminated hostname string. Comments (lines starting with a `#') are ignored. The hostname may be a free-form string up to 64 characters in length; however, it is recommended that it consists only of 7-bit ASCII lower-case characters and no spaces or dots, and limits itself to the format allowed for DNS domain name labels, even though this is not a strict requirement. You may use hostnamectl1 to change the value of this file during runtime from the command line. Use systemd-firstboot1 to initialize it on mounted (but not booted) system images. History The simple configuration file format of /etc/hostname originates from Debian GNU/Linux. See Also systemd1, sethostname2, hostname1, hostname7, machine-id5, machine-info5, hostnamectl1, systemd-hostnamed.service8, systemd-firstboot1 systemd-229/man/hostnamectl.xml000066400000000000000000000240521265713322000167020ustar00rootroot00000000000000 hostnamectl systemd Developer Lennart Poettering lennart@poettering.net hostnamectl 1 hostnamectl Control the system hostname hostnamectl OPTIONS COMMAND Description hostnamectl may be used to query and change the system hostname and related settings. This tool distinguishes three different hostnames: the high-level "pretty" hostname which might include all kinds of special characters (e.g. "Lennart's Laptop"), the static hostname which is used to initialize the kernel hostname at boot (e.g. "lennarts-laptop"), and the transient hostname which is a fallback value received from network configuration. If a static hostname is set, and is valid (something other than localhost), then the transient hostname is not used. Note that the pretty hostname has little restrictions on the characters used, while the static and transient hostnames are limited to the usually accepted characters of Internet domain names. The static hostname is stored in /etc/hostname, see hostname5 for more information. The pretty hostname, chassis type, and icon name are stored in /etc/machine-info, see machine-info5. Use systemd-firstboot1 to initialize the system host name for mounted (but not booted) system images. Options The following options are understood: Do not query the user for authentication for privileged operations. If status is used (or no explicit command is given) and one of those fields is given, hostnamectl will print out just this selected hostname. If used with set-hostname, only the selected hostname(s) will be updated. When more than one of those options is used, all the specified hostnames will be updated. The following commands are understood: status Show current system hostname and related information. set-hostname NAME Set the system hostname to NAME. By default, this will alter the pretty, the static, and the transient hostname alike; however, if one or more of , , are used, only the selected hostnames are changed. If the pretty hostname is being set, and static or transient are being set as well, the specified hostname will be simplified in regards to the character set used before the latter are updated. This is done by replacing spaces with - and removing special characters. This ensures that the pretty and the static hostname are always closely related while still following the validity rules of the specific name. This simplification of the hostname string is not done if only the transient and/or static host names are set, and the pretty host name is left untouched. Pass the empty string as the hostname to reset the selected hostnames to their default (usually localhost). set-icon-name NAME Set the system icon name to NAME. The icon name is used by some graphical applications to visualize this host. The icon name should follow the Icon Naming Specification. Pass an empty string to reset the icon name to the default value, which is determined from chassis type (see below) and possibly other parameters. set-chassis TYPE Set the chassis type to TYPE. The chassis type is used by some graphical applications to visualize the host or alter user interaction. Currently, the following chassis types are defined: desktop, laptop, server, tablet, handset, watch, embedded, as well as the special chassis types vm and container for virtualized systems that lack an immediate physical chassis. Pass an empty string to reset the chassis type to the default value which is determined from the firmware and possibly other parameters. set-deployment ENVIRONMENT Set the deployment environment description. ENVIRONMENT must be a single word without any control characters. One of the following is suggested: development, integration, staging, production. Pass an empty string to reset to the default empty value. set-location LOCATION Set the location string for the system, if it is known. LOCATION should be a human-friendly, free-form string describing the physical location of the system, if it is known and applicable. This may be as generic as Berlin, Germany or as specific as Left Rack, 2nd Shelf. Pass an empty string to reset to the default empty value. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, hostname1, hostname5, machine-info5, systemctl1, systemd-hostnamed.service8, systemd-firstboot1 systemd-229/man/hwdb.xml000066400000000000000000000072521265713322000153100ustar00rootroot00000000000000 hwdb systemd Developer Kay Sievers kay@vrfy.org Developer Tom Gundersen teg@jklm.no hwdb 7 hwdb Hardware Database Description The hardware database is a key-value store for associating modalias-like keys to udev-property-like values. It is used primarily by udev to add the relevant properties to matching devices, but it can also be queried directly. Hardware Database Files The hwdb files are read from the files located in the system hwdb directory /usr/lib/udev/hwdb.d and the local administration directory /etc/udev/hwdb.d. All hwdb files are collectively sorted and processed in lexical order, regardless of the directories in which they live. However, files with identical filenames replace each other. Files in /etc have the highest priority and take precedence over files with the same name in /usr/lib. This can be used to override a system-supplied hwdb file with a local file if needed; a symlink in /etc with the same name as a hwdb file in /usr/lib, pointing to /dev/null, disables the hwdb file entirely. hwdb files must have the extension .hwdb; other extensions are ignored. The hwdb file contains data records consisting of matches and associated key-value pairs. Every record in the hwdb starts with one or more match strings, specifying a shell glob to compare the database lookup string against. Multiple match lines are specified in additional consecutive lines. Every match line is compared individually, and they are combined by OR. Every match line must start at the first character of the line. The match lines are followed by one or more key-value pair lines, which are recognized by a leading space character. The key name and value are separated by =. An empty line signifies the end of a record. Lines beginning with # are ignored. The content of all hwdb files is read by systemd-hwdb8 and compiled to a binary database located at /etc/udev/hwdb.bin, or alternatively /usr/lib/udev/hwdb.bin if you want ship the compiled database in an immutable image. During runtime, only the binary database is used. See Also systemd-hwdb8 systemd-229/man/journal-remote.conf.xml000066400000000000000000000074331265713322000202540ustar00rootroot00000000000000 journal-remote.conf systemd Developer Chris Morgan chmorgan@gmail.com journal-remote.conf 5 journal-remote.conf journal-remote.conf.d Journal remote service configuration files /etc/systemd/journal-remote.conf /etc/systemd/journald.conf.d/*.conf /run/systemd/journald.conf.d/*.conf /usr/lib/systemd/journald.conf.d/*.conf Description These files configure various parameters of the systemd-remote-journal application, systemd-journal-remote8. Options All options are configured in the [Remote] section: Seal= Periodically sign the data in the journal using Forward Secure Sealing. SplitMode= One of host or none. ServerKeyFile= SSL key in PEM format. ServerCertificateFile= SSL CA certificate in PEM format. TrustedCertificateFile= SSL CA certificate. See Also systemd-journal-remote8, systemd1, systemd-journald.service8 systemd-229/man/journalctl.xml000066400000000000000000001104061265713322000165350ustar00rootroot00000000000000 journalctl systemd Developer Lennart Poettering lennart@poettering.net journalctl 1 journalctl Query the systemd journal journalctl OPTIONS MATCHES Description journalctl may be used to query the contents of the systemd1 journal as written by systemd-journald.service8. If called without parameters, it will show the full contents of the journal, starting with the oldest entry collected. If one or more match arguments are passed, the output is filtered accordingly. A match is in the format FIELD=VALUE, e.g. _SYSTEMD_UNIT=httpd.service, referring to the components of a structured journal entry. See systemd.journal-fields7 for a list of well-known fields. If multiple matches are specified matching different fields, the log entries are filtered by both, i.e. the resulting output will show only entries matching all the specified matches of this kind. If two matches apply to the same field, then they are automatically matched as alternatives, i.e. the resulting output will show entries matching any of the specified matches for the same field. Finally, the character + may appear as a separate word between other terms on the command line. This causes all matches before and after to be combined in a disjunction (i.e. logical OR). As shortcuts for a few types of field/value matches, file paths may be specified. If a file path refers to an executable file, this is equivalent to an _EXE= match for the canonicalized binary path. Similarly, if a path refers to a device node then match is added for the kernel name of the device (_KERNEL_DEVICE=). Also, matches for the kernel names of all the parent devices are added automatically. Device node paths are not stable across reboots, therefore match for the current boot id (_BOOT_ID=) is always added as well. Note that only the log entries for the existing device nodes maybe queried by providing path to the device node. Additional constraints may be added using options , , etc., to further limit what entries will be shown (logical AND). Output is interleaved from all accessible journal files, whether they are rotated or currently being written, and regardless of whether they belong to the system itself or are accessible user journals. The set of journal files which will be used can be modified using the , , , and options, see below. All users are granted access to their private per-user journals. However, by default, only root and users who are members of a few special groups are granted access to the system journal and the journals of other users. Members of the groups systemd-journal, adm, and wheel can read all journal files. Note that the two latter groups traditionally have additional privileges specified by the distribution. Members of the wheel group can often perform administrative tasks. The output is paged through less by default, and long lines are "truncated" to screen width. The hidden part can be viewed by using the left-arrow and right-arrow keys. Paging can be disabled; see the option and the "Environment" section below. When outputting to a tty, lines are colored according to priority: lines of level ERROR and higher are colored red; lines of level NOTICE and higher are highlighted; other lines are displayed normally. Options The following options are understood: Ellipsize fields when they do not fit in available columns. The default is to show full fields, allowing them to wrap or be truncated by the pager, if one is used. The old options / are not useful anymore, except to undo . Show all fields in full, even if they include unprintable characters or are very long. Show only the most recent journal entries, and continuously print new entries as they are appended to the journal. Immediately jump to the end of the journal inside the implied pager tool. This implies to guarantee that the pager will not buffer logs of unbounded size. This may be overridden with an explicit with some other numeric value, while will disable this cap. Note that this option is only supported for the less1 pager. Show the most recent journal events and limit the number of events shown. If is used, this option is implied. The argument is a positive integer or all to disable line limiting. The default value is 10 if no argument is given. Show all stored output lines, even in follow mode. Undoes the effect of . Reverse output so that the newest entries are displayed first. Controls the formatting of the journal entries that are shown. Takes one of the following options: is the default and generates an output that is mostly identical to the formatting of classic syslog files, showing one line per journal entry. is very similar, but shows ISO 8601 wallclock timestamps. is very similar, but shows timestamps with full microsecond precision. is very similar, but shows monotonic timestamps instead of wallclock timestamps. shows the full-structured entry items with all fields. serializes the journal into a binary (but mostly text-based) stream suitable for backups and network transfer (see Journal Export Format for more information). formats entries as JSON data structures, one per line (see Journal JSON Format for more information). formats entries as JSON data structures, but formats them in multiple lines in order to make them more readable by humans. formats entries as JSON data structures, but wraps them in a format suitable for Server-Sent Events. generates a very terse output, only showing the actual message of each journal entry with no metadata, not even a timestamp. Express time in Coordinated Universal Time (UTC). Augment log lines with explanation texts from the message catalog. This will add explanatory help texts to log messages in the output where this is available. These short help texts will explain the context of an error or log event, possible solutions, as well as pointers to support forums, developer documentation, and any other relevant manuals. Note that help texts are not available for all messages, but only for selected ones. For more information on the message catalog, please refer to the Message Catalog Developer Documentation. Note: when attaching journalctl output to bug reports, please do not use . Suppresses all info messages (i.e. "-- Logs begin at ...", "-- Reboot --"), any warning messages regarding inaccessible system journals when run as a normal user. Show entries interleaved from all available journals, including remote ones. Show messages from a specific boot. This will add a match for _BOOT_ID=. The argument may be empty, in which case logs for the current boot will be shown. If the boot ID is omitted, a positive offset will look up the boots starting from the beginning of the journal, and an equal-or-less-than zero offset will look up boots starting from the end of the journal. Thus, 1 means the first boot found in the journal in chronological order, 2 the second and so on; while -0 is the last boot, -1 the boot before last, and so on. An empty offset is equivalent to specifying -0, except when the current boot is not the last boot (e.g. because was specified to look at logs from a different machine). If the 32-character ID is specified, it may optionally be followed by offset which identifies the boot relative to the one given by boot ID. Negative values mean earlier boots and positive values mean later boots. If offset is not specified, a value of zero is assumed, and the logs for the boot given by ID are shown. Show a tabular list of boot numbers (relative to the current boot), their IDs, and the timestamps of the first and last message pertaining to the boot. Show only kernel messages. This implies and adds the match _TRANSPORT=kernel. Show messages for the specified syslog identifier SYSLOG_IDENTIFIER. This parameter can be specified multiple times. Show messages for the specified systemd unit UNIT (such as a service unit), or for any of the units matched by PATTERN. If a pattern is specified, a list of unit names found in the journal is compared with the specified pattern and all that match are used. For each unit name, a match is added for messages from the unit (_SYSTEMD_UNIT=UNIT), along with additional matches for messages from systemd and messages about coredumps for the specified unit. This parameter can be specified multiple times. Show messages for the specified user session unit. This will add a match for messages from the unit (_SYSTEMD_USER_UNIT= and _UID=) and additional matches for messages from session systemd and messages about coredumps for the specified unit. This parameter can be specified multiple times. Filter output by message priorities or priority ranges. Takes either a single numeric or textual log level (i.e. between 0/emerg and 7/debug), or a range of numeric/text log levels in the form FROM..TO. The log levels are the usual syslog log levels as documented in syslog3, i.e. emerg (0), alert (1), crit (2), err (3), warning (4), notice (5), info (6), debug (7). If a single log level is specified, all messages with this log level or a lower (hence more important) log level are shown. If a range is specified, all messages within the range are shown, including both the start and the end value of the range. This will add PRIORITY= matches for the specified priorities. Start showing entries from the location in the journal specified by the passed cursor. Start showing entries from the location in the journal after the location specified by the passed cursor. The cursor is shown when the option is used. The cursor is shown after the last entry after two dashes: -- cursor: s=0639... The format of the cursor is private and subject to change. Start showing entries on or newer than the specified date, or on or older than the specified date, respectively. Date specifications should be of the format 2012-10-30 18:17:16. If the time part is omitted, 00:00:00 is assumed. If only the seconds component is omitted, :00 is assumed. If the date component is omitted, the current day is assumed. Alternatively the strings yesterday, today, tomorrow are understood, which refer to 00:00:00 of the day before the current day, the current day, or the day after the current day, respectively. now refers to the current time. Finally, relative times may be specified, prefixed with - or +, referring to times before or after the current time, respectively. For complete time and date specification, see systemd.time7. Print all possible data values the specified field can take in all entries of the journal. Print all field names currently used in all entries of the journal. Show messages from system services and the kernel (with ). Show messages from service of current user (with ). If neither is specified, show all messages that the user can see. Show messages from a running, local container. Specify a container name to connect to. Takes a directory path as argument. If specified, journalctl will operate on the specified journal directory DIR instead of the default runtime and system journal paths. Takes a file glob as an argument. If specified, journalctl will operate on the specified journal files matching GLOB instead of the default runtime and system journal paths. May be specified multiple times, in which case files will be suitably interleaved. Takes a directory path as an argument. If specified, journalctl will operate on catalog file hierarchy underneath the specified directory instead of the root directory (e.g. will create ROOT/var/lib/systemd/catalog/database). Instead of showing journal contents, generate a new 128-bit ID suitable for identifying messages. This is intended for usage by developers who need a new identifier for a new message they introduce and want to make recognizable. This will print the new ID in three different formats which can be copied into source code or similar. Instead of showing journal contents, show internal header information of the journal fields accessed. Shows the current disk usage of all journal files. This shows the sum of the disk usage of all archived and active journal files. Removes archived journal files until the disk space they use falls below the specified size (specified with the usual K, M, G and T suffixes), or all journal files contain no data older than the specified timespan (specified with the usual s, min, h, days, months, weeks and years suffixes), or no more than the specified number of separate journal files remain. Note that running has only an indirect effect on the output shown by , as the latter includes active journal files, while the vacuuming operation only operates on archived journal files. Similarly, might not actually reduce the number of journal files to below the specified number, as it will not remove active journal files. , and may be combined in a single invocation to enforce any combination of a size, a time and a number of files limit on the archived journal files. Specifying any of these three parameters as zero is equivalent to not enforcing the specific limit, and is thus redundant. List the contents of the message catalog as a table of message IDs, plus their short description strings. If any 128-bit-IDs are specified, only those entries are shown. Show the contents of the message catalog, with entries separated by a line consisting of two dashes and the ID (the format is the same as .catalog files). If any 128-bit-IDs are specified, only those entries are shown. Update the message catalog index. This command needs to be executed each time new catalog files are installed, removed, or updated to rebuild the binary catalog index. Instead of showing journal contents, generate a new key pair for Forward Secure Sealing (FSS). This will generate a sealing key and a verification key. The sealing key is stored in the journal data directory and shall remain on the host. The verification key should be stored externally. Refer to the option in journald.conf5 for information on Forward Secure Sealing and for a link to a refereed scholarly paper detailing the cryptographic theory it is based on. When is passed and Forward Secure Sealing (FSS) has already been configured, recreate FSS keys. Specifies the change interval for the sealing key when generating an FSS key pair with . Shorter intervals increase CPU consumption but shorten the time range of undetectable journal alterations. Defaults to 15min. Check the journal file for internal consistency. If the file has been generated with FSS enabled and the FSS verification key has been specified with , authenticity of the journal file is verified. Specifies the FSS verification key to use for the operation. Asks the journal daemon to write all yet unwritten journal data to the backing file system and synchronize all journals. This call does not return until the synchronization operation is complete. This command guarantees that any log messages written before its invocation are safely stored on disk at the time it returns. Asks the journal daemon to flush any log data stored in /run/log/journal into /var/log/journal, if persistent storage is enabled. This call does not return until the operation is complete. Note that this call is idempotent: the data is only flushed from /run/log/journal into /var/log/journal once during system runtime, and this command exits cleanly without executing any operation if this has already has happened. This command effectively guarantees that all data is flushed to /var/log/journal at the time it returns. Asks the journal daemon to rotate journal files. This call does not return until the rotation operation is complete. Exit status On success, 0 is returned; otherwise, a non-zero failure code is returned. Examples Without arguments, all collected logs are shown unfiltered: journalctl With one match specified, all entries with a field matching the expression are shown: journalctl _SYSTEMD_UNIT=avahi-daemon.service If two different fields are matched, only entries matching both expressions at the same time are shown: journalctl _SYSTEMD_UNIT=avahi-daemon.service _PID=28097 If two matches refer to the same field, all entries matching either expression are shown: journalctl _SYSTEMD_UNIT=avahi-daemon.service _SYSTEMD_UNIT=dbus.service If the separator + is used, two expressions may be combined in a logical OR. The following will show all messages from the Avahi service process with the PID 28097 plus all messages from the D-Bus service (from any of its processes): journalctl _SYSTEMD_UNIT=avahi-daemon.service _PID=28097 + _SYSTEMD_UNIT=dbus.service Show all logs generated by the D-Bus executable: journalctl /usr/bin/dbus-daemon Show all kernel logs from previous boot: journalctl -k -b -1 Show a live log display from a system service apache.service: journalctl -f -u apache See Also systemd1, systemd-journald.service8, systemctl1, coredumpctl1, systemd.journal-fields7, journald.conf5, systemd.time7 systemd-229/man/journald.conf.xml000066400000000000000000000455411265713322000171310ustar00rootroot00000000000000 journald.conf systemd Developer Lennart Poettering lennart@poettering.net journald.conf 5 journald.conf journald.conf.d Journal service configuration files /etc/systemd/journald.conf /etc/systemd/journald.conf.d/*.conf /run/systemd/journald.conf.d/*.conf /usr/lib/systemd/journald.conf.d/*.conf Description These files configure various parameters of the systemd journal service, systemd-journald.service8. Options All options are configured in the [Journal] section: Storage= Controls where to store journal data. One of volatile, persistent, auto and none. If volatile, journal log data will be stored only in memory, i.e. below the /run/log/journal hierarchy (which is created if needed). If persistent, data will be stored preferably on disk, i.e. below the /var/log/journal hierarchy (which is created if needed), with a fallback to /run/log/journal (which is created if needed), during early boot and if the disk is not writable. auto is similar to persistent but the directory /var/log/journal is not created if needed, so that its existence controls where log data goes. none turns off all storage, all log data received will be dropped. Forwarding to other targets, such as the console, the kernel log buffer, or a syslog socket will still work however. Defaults to auto. Compress= Takes a boolean value. If enabled (the default), data objects that shall be stored in the journal and are larger than a certain threshold are compressed before they are written to the file system. Seal= Takes a boolean value. If enabled (the default), and a sealing key is available (as created by journalctl1's command), Forward Secure Sealing (FSS) for all persistent journal files is enabled. FSS is based on Seekable Sequential Key Generators by G. A. Marson and B. Poettering (doi:10.1007/978-3-642-40203-6_7) and may be used to protect journal files from unnoticed alteration. SplitMode= Controls whether to split up journal files per user. One of uid, login and none. If uid, all users will get each their own journal files regardless of whether they possess a login session or not, however system users will log into the system journal. If login, actually logged-in users will get each their own journal files, but users without login session and system users will log into the system journal. If none, journal files are not split up by user and all messages are instead stored in the single system journal. Note that splitting up journal files by user is only available for journals stored persistently. If journals are stored on volatile storage (see above), only a single journal file for all user IDs is kept. Defaults to uid. RateLimitInterval= RateLimitBurst= Configures the rate limiting that is applied to all messages generated on the system. If, in the time interval defined by RateLimitInterval=, more messages than specified in RateLimitBurst= are logged by a service, all further messages within the interval are dropped until the interval is over. A message about the number of dropped messages is generated. This rate limiting is applied per-service, so that two services which log do not interfere with each other's limits. Defaults to 1000 messages in 30s. The time specification for RateLimitInterval= may be specified in the following units: s, min, h, ms, us. To turn off any kind of rate limiting, set either value to 0. SystemMaxUse= SystemKeepFree= SystemMaxFileSize= SystemMaxFiles= RuntimeMaxUse= RuntimeKeepFree= RuntimeMaxFileSize= RuntimeMaxFiles= Enforce size limits on the journal files stored. The options prefixed with System apply to the journal files when stored on a persistent file system, more specifically /var/log/journal. The options prefixed with Runtime apply to the journal files when stored on a volatile in-memory file system, more specifically /run/log/journal. The former is used only when /var is mounted, writable, and the directory /var/log/journal exists. Otherwise, only the latter applies. Note that this means that during early boot and if the administrator disabled persistent logging, only the latter options apply, while the former apply if persistent logging is enabled and the system is fully booted up. journalctl and systemd-journald ignore all files with names not ending with .journal or .journal~, so only such files, located in the appropriate directories, are taken into account when calculating current disk usage. SystemMaxUse= and RuntimeMaxUse= control how much disk space the journal may use up at most. SystemKeepFree= and RuntimeKeepFree= control how much disk space systemd-journald shall leave free for other uses. systemd-journald will respect both limits and use the smaller of the two values. The first pair defaults to 10% and the second to 15% of the size of the respective file system, but each value is capped to 4G. If the file system is nearly full and either SystemKeepFree= or RuntimeKeepFree= are violated when systemd-journald is started, the limit will be raised to the percentage that is actually free. This means that if there was enough free space before and journal files were created, and subsequently something else causes the file system to fill up, journald will stop using more space, but it will not be removing existing files to reduce the footprint again, either. SystemMaxFileSize= and RuntimeMaxFileSize= control how large individual journal files may grow at most. This influences the granularity in which disk space is made available through rotation, i.e. deletion of historic data. Defaults to one eighth of the values configured with SystemMaxUse= and RuntimeMaxUse=, so that usually seven rotated journal files are kept as history. Specify values in bytes or use K, M, G, T, P, E as units for the specified sizes (equal to 1024, 1024², ... bytes). Note that size limits are enforced synchronously when journal files are extended, and no explicit rotation step triggered by time is needed. SystemMaxFiles= and RuntimeMaxFiles= control how many individual journal files to keep at most. Note that only archived files are deleted to reduce the number of files until this limit is reached; active files will stay around. This means that, in effect, there might still be more journal files around in total than this limit after a vacuuming operation is complete. This setting defaults to 100. MaxFileSec= The maximum time to store entries in a single journal file before rotating to the next one. Normally, time-based rotation should not be required as size-based rotation with options such as SystemMaxFileSize= should be sufficient to ensure that journal files do not grow without bounds. However, to ensure that not too much data is lost at once when old journal files are deleted, it might make sense to change this value from the default of one month. Set to 0 to turn off this feature. This setting takes time values which may be suffixed with the units year, month, week, day, h or m to override the default time unit of seconds. MaxRetentionSec= The maximum time to store journal entries. This controls whether journal files containing entries older then the specified time span are deleted. Normally, time-based deletion of old journal files should not be required as size-based deletion with options such as SystemMaxUse= should be sufficient to ensure that journal files do not grow without bounds. However, to enforce data retention policies, it might make sense to change this value from the default of 0 (which turns off this feature). This setting also takes time values which may be suffixed with the units year, month, week, day, h or m to override the default time unit of seconds. SyncIntervalSec= The timeout before synchronizing journal files to disk. After syncing, journal files are placed in the OFFLINE state. Note that syncing is unconditionally done immediately after a log message of priority CRIT, ALERT or EMERG has been logged. This setting hence applies only to messages of the levels ERR, WARNING, NOTICE, INFO, DEBUG. The default timeout is 5 minutes. ForwardToSyslog= ForwardToKMsg= ForwardToConsole= ForwardToWall= Control whether log messages received by the journal daemon shall be forwarded to a traditional syslog daemon, to the kernel log buffer (kmsg), to the system console, or sent as wall messages to all logged-in users. These options take boolean arguments. If forwarding to syslog is enabled but nothing reads messages from the socket, forwarding to syslog has no effect. By default, only forwarding to wall is enabled. These settings may be overridden at boot time with the kernel command line options systemd.journald.forward_to_syslog=, systemd.journald.forward_to_kmsg=, systemd.journald.forward_to_console=, and systemd.journald.forward_to_wall=. When forwarding to the console, the TTY to log to can be changed with TTYPath=, described below. MaxLevelStore= MaxLevelSyslog= MaxLevelKMsg= MaxLevelConsole= MaxLevelWall= Controls the maximum log level of messages that are stored on disk, forwarded to syslog, kmsg, the console or wall (if that is enabled, see above). As argument, takes one of emerg, alert, crit, err, warning, notice, info, debug, or integer values in the range of 0–7 (corresponding to the same levels). Messages equal or below the log level specified are stored/forwarded, messages above are dropped. Defaults to debug for MaxLevelStore= and MaxLevelSyslog=, to ensure that the all messages are written to disk and forwarded to syslog. Defaults to notice for MaxLevelKMsg=, info for MaxLevelConsole=, and emerg for MaxLevelWall=. TTYPath= Change the console TTY to use if ForwardToConsole=yes is used. Defaults to /dev/console. Forwarding to traditional syslog daemons Journal events can be transferred to a different logging daemon in two different ways. With the first method, messages are immediately forwarded to a socket (/run/systemd/journal/syslog), where the traditional syslog daemon can read them. This method is controlled by the ForwardToSyslog= option. With a second method, a syslog daemon behaves like a normal journal client, and reads messages from the journal files, similarly to journalctl1. With this, messages do not have to be read immediately, which allows a logging daemon which is only started late in boot to access all messages since the start of the system. In addition, full structured meta-data is available to it. This method of course is available only if the messages are stored in a journal file at all. So it will not work if Storage=none is set. It should be noted that usually the second method is used by syslog daemons, so the Storage= option, and not the ForwardToSyslog= option, is relevant for them. See Also systemd1, systemd-journald.service8, journalctl1, systemd.journal-fields7, systemd-system.conf5 systemd-229/man/kernel-command-line.xml000066400000000000000000000402651265713322000202060ustar00rootroot00000000000000 kernel-command-line systemd Developer Lennart Poettering lennart@poettering.net kernel-command-line 7 kernel-command-line Kernel command line parameters /proc/cmdline Description The kernel, the initial RAM disk (initrd) and basic userspace functionality may be configured at boot via kernel command line arguments. For command line parameters understood by the kernel, please see kernel-parameters.txt and bootparam7. For command line parameters understood by the initial RAM disk, please see dracut.cmdline7, or the documentation of the specific initrd implementation of your installation. Core OS Command Line Arguments systemd.unit= rd.systemd.unit= systemd.dump_core= systemd.crash_chvt= systemd.crash_shell= systemd.crash_reboot= systemd.confirm_spawn= systemd.show_status= systemd.log_target= systemd.log_level= systemd.log_color= systemd.log_location= systemd.default_standard_output= systemd.default_standard_error= systemd.setenv= systemd.machine_id= Parameters understood by the system and service manager to control system behavior. For details, see systemd1. systemd.mask= systemd.wants= systemd.debug-shell Additional parameters understood by systemd-debug-generator8, to mask or start specific units at boot, or invoke a debug shell on tty9. systemd.restore_state= This parameter is understood by several system tools to control whether or not they should restore system state from the previous boot. For details, see systemd-backlight@.service8 and systemd-rfkill.service8. quiet Parameter understood by both the kernel and the system and service manager to control console log verbosity. For details, see systemd1. debug Parameter understood by both the kernel and the system and service manager to control console log verbosity. For details, see systemd1. -b emergency rescue single s S 1 2 3 4 5 Parameters understood by the system and service manager, as compatibility options. For details, see systemd1. locale.LANG= locale.LANGUAGE= locale.LC_CTYPE= locale.LC_NUMERIC= locale.LC_TIME= locale.LC_COLLATE= locale.LC_MONETARY= locale.LC_MESSAGES= locale.LC_PAPER= locale.LC_NAME= locale.LC_ADDRESS= locale.LC_TELEPHONE= locale.LC_MEASUREMENT= locale.LC_IDENTIFICATION= Parameters understood by the system and service manager to control locale and language settings. For details, see systemd1. fsck.mode= fsck.repair= Parameters understood by the file system checker services. For details, see systemd-fsck@.service8. quotacheck.mode= Parameter understood by the file quota checker service. For details, see systemd-quotacheck.service8. systemd.journald.forward_to_syslog= systemd.journald.forward_to_kmsg= systemd.journald.forward_to_console= systemd.journald.forward_to_wall= Parameters understood by the journal service. For details, see systemd-journald.service8. vconsole.keymap= vconsole.keymap.toggle= vconsole.font= vconsole.font.map= vconsole.font.unimap= Parameters understood by the virtual console setup logic. For details, see systemd-vconsole-setup.service8. udev.log-priority= rd.udev.log-priority= udev.children-max= rd.udev.children-max= udev.exec-delay= rd.udev.exec-delay= udev.event-timeout= rd.udev.event-timeout= net.ifnames= Parameters understood by the device event managing daemon. For details, see systemd-udevd.service8. plymouth.enable= May be used to disable the Plymouth boot splash. For details, see plymouth8. luks= rd.luks= luks.crypttab= rd.luks.crypttab= luks.name= rd.luks.name= luks.uuid= rd.luks.uuid= luks.options= rd.luks.options= luks.key= rd.luks.key= Configures the LUKS full-disk encryption logic at boot. For details, see systemd-cryptsetup-generator8. fstab= rd.fstab= Configures the /etc/fstab logic at boot. For details, see systemd-fstab-generator8. root= rootfstype= rootflags= ro rw Configures the root file system and its file system type and mount options, as well as whether it shall be mounted read-only or read-writable initially. For details, see systemd-fstab-generator8. systemd.gpt_auto= rd.systemd.gpt_auto= Configures whether GPT based partition auto-discovery shall be attempted. For details, see systemd-gpt-auto-generator8. modules-load= rd.modules-load= Load a specific kernel module early at boot. For details, see systemd-modules-load.service8. resume= Enables resume from hibernation using the specified device. All fstab5-like paths are supported. For details, see systemd-hibernate-resume-generator8. See Also systemd1, bootparam7, dracut.cmdline7, systemd-debug-generator8, systemd-fsck@.service8, systemd-quotacheck.service8, systemd-journald.service8, systemd-vconsole-setup.service8, systemd-udevd.service8, plymouth8, systemd-cryptsetup-generator8, systemd-fstab-generator8, systemd-gpt-auto-generator8, systemd-modules-load.service8, systemd-backlight@.service8, systemd-rfkill.service8, systemd-hibernate-resume-generator8 systemd-229/man/kernel-install.xml000066400000000000000000000201441265713322000173030ustar00rootroot00000000000000 kernel-install systemd Developer Harald Hoyer harald@redhat.com kernel-install 8 kernel-install Add and remove kernel and initramfs images to and from /boot kernel-install COMMAND KERNEL-VERSION KERNEL-IMAGE Description kernel-install is used to install and remove kernel and initramfs images to and from /boot. kernel-install will execute the files located in the directory /usr/lib/kernel/install.d/ and the local administration directory /etc/kernel/install.d/. All files are collectively sorted and executed in lexical order, regardless of the directory in which they live. However, files with identical filenames replace each other. Files in /etc/kernel/install.d/ take precedence over files with the same name in /usr/lib/kernel/install.d/. This can be used to override a system-supplied executables with a local file if needed; a symbolic link in /etc/kernel/install.d/ with the same name as an executable in /usr/lib/kernel/install.d/, pointing to /dev/null, disables the executable entirely. Executables must have the extension .install; other extensions are ignored. Commands The following commands are understood: add KERNEL-VERSION KERNEL-IMAGE kernel-install creates the directory /boot/MACHINE-ID/KERNEL-VERSION/ and calls every executable /usr/lib/kernel/install.d/*.install and /etc/kernel/install.d/*.install with the arguments add KERNEL-VERSION /boot/MACHINE-ID/KERNEL-VERSION/ The kernel-install plugin 50-depmod.install runs depmod for the KERNEL-VERSION. The kernel-install plugin 90-loaderentry.install copies KERNEL-IMAGE to /boot/MACHINE-ID/KERNEL-VERSION/linux. It also creates a boot loader entry according to the boot loader specification in /boot/loader/entries/MACHINE-ID-KERNEL-VERSION.conf. The title of the entry is the PRETTY_NAME parameter specified in /etc/os-release or /usr/lib/os-release (if the former is missing), or "Linux KERNEL-VERSION", if unset. If the file initrd is found next to the linux file, the initrd will be added to the configuration. remove KERNEL-VERSION Calls every executable /usr/lib/kernel/install.d/*.install and /etc/kernel/install.d/*.install with the arguments remove KERNEL-VERSION /boot/MACHINE-ID/KERNEL-VERSION/ kernel-install removes the entire directory /boot/MACHINE-ID/KERNEL-VERSION/ afterwards. The kernel-install plugin 90-loaderentry.install removes the file /boot/loader/entries/MACHINE-ID-KERNEL-VERSION.conf. Exit status If every executable returns with 0, 0 is returned, a non-zero failure code otherwise. Files /usr/lib/kernel/install.d/*.install /etc/kernel/install.d/*.install Drop-in files which are executed by kernel-install. /etc/kernel/cmdline /proc/cmdline The content of the file /etc/kernel/cmdline specifies the kernel command line to use. If that file does not exist, /proc/cmdline is used. /etc/machine-id The content of the file specifies the machine identification MACHINE-ID. /etc/os-release /usr/lib/os-release The content of the file specifies the operating system title PRETTY_NAME. See Also machine-id5, os-release5, Boot loader specification systemd-229/man/less-variables.xml000066400000000000000000000022641265713322000172760ustar00rootroot00000000000000 Environment $SYSTEMD_PAGER Pager to use when is not given; overrides $PAGER. Setting this to an empty string or the value cat is equivalent to passing . $SYSTEMD_LESS Override the default options passed to less (FRSXMK). systemd-229/man/libsystemd-pkgconfig.xml000066400000000000000000000007431265713322000205060ustar00rootroot00000000000000 Notes These APIs are implemented as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. systemd-229/man/libudev.xml000066400000000000000000000123071265713322000160130ustar00rootroot00000000000000 %entities; ]> libudev systemd Developer David Herrmann dh.herrmann@gmail.com libudev 3 libudev API for enumerating and introspecting local devices #include <libudev.h> pkg-config --cflags --libs libudev Description libudev.h provides APIs to introspect and enumerate devices on the local system. All functions require a libudev context to operate. This context can be create via udev_new3. It is used to track library state and link objects together. No global state is used by libudev, everything is always linked to a udev context. Furthermore, multiple different udev contexts can be used in parallel by multiple threads. However, a single context must not be accessed by multiple threads in parallel. The caller is responsible for providing suitable locking if they intend to use it from multiple threads. To introspect a local device on a system, a udev device object can be created via udev_device_new_from_syspath3 and friends. The device object allows to query current state, read and write attributes and lookup properties of the device in question. To enumerate local devices on the system, an enumeration object can be created via udev_enumerate_new3. To monitor the local system for hotplugged or unplugged devices, a monitor can be created via udev_monitor_new_from_netlink3. Whenever libudev returns a list of objects, the udev_list_entry3 API should be used to iterate, access and modify those lists. Furthermore, libudev also exports legacy APIs that should not be used by new software (and as such are not documented as part of this manual). This includes the hardware database known as udev_hwdb (please use the new sd-hwdb3 API instead) and the udev_queue object to query the udev daemon (which should not be used by new software at all). See Also udev_new3, udev_device_new_from_syspath3, udev_enumerate_new3, udev_monitor_new_from_netlink3, udev_list_entry3, systemd1, sd-device3, sd-hwdb3, pkg-config1 systemd-229/man/locale.conf.xml000066400000000000000000000130771265713322000165510ustar00rootroot00000000000000 locale.conf systemd Developer Lennart Poettering lennart@poettering.net locale.conf 5 locale.conf Configuration file for locale settings /etc/locale.conf Description The /etc/locale.conf file configures system-wide locale settings. It is read at early boot by systemd1. The basic file format of locale.conf is a newline-separated list of environment-like shell-compatible variable assignments. It is possible to source the configuration from shell scripts, however, beyond mere variable assignments, no shell features are supported, allowing applications to read the file without implementing a shell compatible execution engine. Note that the kernel command line options locale.LANG=, locale.LANGUAGE=, locale.LC_CTYPE=, locale.LC_NUMERIC=, locale.LC_TIME=, locale.LC_COLLATE=, locale.LC_MONETARY=, locale.LC_MESSAGES=, locale.LC_PAPER=, locale.LC_NAME=, locale.LC_ADDRESS=, locale.LC_TELEPHONE=, locale.LC_MEASUREMENT=, locale.LC_IDENTIFICATION= may be used to override the locale settings at boot. The locale settings configured in /etc/locale.conf are system-wide and are inherited by every service or user, unless overridden or unset by individual programs or individual users. Depending on the operating system, other configuration files might be checked for locale configuration as well, however only as fallback. localectl1 may be used to alter the settings in this file during runtime from the command line. Use systemd-firstboot1 to initialize them on mounted (but not booted) system images. Options The following locale settings may be set using /etc/locale.conf: LANG=, LANGUAGE=, LC_CTYPE=, LC_NUMERIC=, LC_TIME=, LC_COLLATE=, LC_MONETARY=, LC_MESSAGES=, LC_PAPER=, LC_NAME=, LC_ADDRESS=, LC_TELEPHONE=, LC_MEASUREMENT=, LC_IDENTIFICATION=. Note that LC_ALL may not be configured in this file. For details about the meaning and semantics of these settings, refer to locale7. Example German locale with English messages /etc/locale.conf: LANG=de_DE.UTF-8 LC_MESSAGES=en_US.UTF-8 See Also systemd1, locale7, localectl1, systemd-localed.service8, systemd-firstboot1 systemd-229/man/localectl.xml000066400000000000000000000205061265713322000163230ustar00rootroot00000000000000 localectl systemd Developer Lennart Poettering lennart@poettering.net localectl 1 localectl Control the system locale and keyboard layout settings localectl OPTIONS COMMAND Description localectl may be used to query and change the system locale and keyboard layout settings. The system locale controls the language settings of system services and of the UI before the user logs in, such as the display manager, as well as the default for users after login. The keyboard settings control the keyboard layout used on the text console and of the graphical UI before the user logs in, such as the display manager, as well as the default for users after login. Use systemd-firstboot1 to initialize the system locale for mounted (but not booted) system images. Options The following options are understood: Do not query the user for authentication for privileged operations. If set-keymap or set-x11-keymap is invoked and this option is passed, then the keymap will not be converted from the console to X11, or X11 to console, respectively. The following commands are understood: status Show current settings of the system locale and keyboard mapping. set-locale LOCALE... Set the system locale. This takes one or more assignments such as "LANG=de_DE.utf8", "LC_MESSAGES=en_GB.utf8", and so on. See locale7 for details on the available settings and their meanings. Use list-locales for a list of available locales (see below). list-locales List available locales useful for configuration with set-locale. set-keymap MAP [TOGGLEMAP] Set the system keyboard mapping for the console and X11. This takes a mapping name (such as "de" or "us"), and possibly a second one to define a toggle keyboard mapping. Unless is passed, the selected setting is also applied as the default system keyboard mapping of X11, after converting it to the closest matching X11 keyboard mapping. Use list-keymaps for a list of available keyboard mappings (see below). list-keymaps List available keyboard mappings for the console, useful for configuration with set-keymap. set-x11-keymap LAYOUT [MODEL [VARIANT [OPTIONS]]] Set the system default keyboard mapping for X11 and the virtual console. This takes a keyboard mapping name (such as de or us), and possibly a model, variant, and options, see kbd4 for details. Unless is passed, the selected setting is also applied as the system console keyboard mapping, after converting it to the closest matching console keyboard mapping. list-x11-keymap-models list-x11-keymap-layouts list-x11-keymap-variants [LAYOUT] list-x11-keymap-options List available X11 keymap models, layouts, variants and options, useful for configuration with set-keymap. The command list-x11-keymap-variants optionally takes a layout parameter to limit the output to the variants suitable for the specific layout. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, locale7, locale.conf5, vconsole.conf5, loadkeys1, kbd4, The XKB Configuration Guide , systemctl1, systemd-localed.service8, systemd-firstboot1 systemd-229/man/localtime.xml000066400000000000000000000100371265713322000163300ustar00rootroot00000000000000 localtime systemd Developer Lennart Poettering lennart@poettering.net Developer Shawn Landden shawnlandden@gmail.com localtime 5 localtime Local timezone configuration file /etc/localtime -> ../usr/share/zoneinfo/… Description The /etc/localtime file configures the system-wide timezone of the local system that is used by applications for presentation to the user. It should be an absolute or relative symbolic link pointing to /usr/share/zoneinfo/, followed by a timezone identifier such as Europe/Berlin or Etc/UTC. The resulting link should lead to the corresponding binary tzfile5 timezone data for the configured timezone. Because the timezone identifier is extracted from the symlink target name of /etc/localtime, this file may not be a normal file or hardlink. The timezone may be overridden for individual programs by using the $TZ environment variable. See environ7. You may use timedatectl1 to change the settings of this file from the command line during runtime. Use systemd-firstboot1 to initialize the time zone on mounted (but not booted) system images. See Also systemd1, tzset3, localtime3, timedatectl1, systemd-timedated.service8, systemd-firstboot1 systemd-229/man/loginctl.xml000066400000000000000000000407221265713322000161760ustar00rootroot00000000000000 loginctl systemd Developer Lennart Poettering lennart@poettering.net loginctl 1 loginctl Control the systemd login manager loginctl OPTIONS COMMAND NAME Description loginctl may be used to introspect and control the state of the systemd1 login manager systemd-logind.service8. Options The following options are understood: Do not query the user for authentication for privileged operations. When showing session/user/seat properties, limit display to certain properties as specified as argument. If not specified, all set properties are shown. The argument should be a property name, such as Sessions. If specified more than once, all properties with the specified names are shown. When showing session/user/seat properties, show all properties regardless of whether they are set or not. Do not ellipsize process tree entries. When used with kill-session, choose which processes to kill. Must be one of , or to select whether to kill only the leader process of the session or all processes of the session. If omitted, defaults to . When used with kill-session or kill-user, choose which signal to send to selected processes. Must be one of the well known signal specifiers, such as SIGTERM, SIGINT or SIGSTOP. If omitted, defaults to SIGTERM. When used with user-status and session-status, controls the number of journal lines to show, counting from the most recent ones. Takes a positive integer argument. Defaults to 10. When used with user-status and session-status, controls the formatting of the journal entries that are shown. For the available choices, see journalctl1. Defaults to short. Commands The following commands are understood: Session Commands list-sessions List current sessions. session-status ID... Show terse runtime status information about one or more sessions, followed by the most recent log data from the journal. Takes one or more session identifiers as parameters. If no session identifiers are passed, the status of the caller's session is shown. This function is intended to generate human-readable output. If you are looking for computer-parsable output, use show-session instead. show-session ID... Show properties of one or more sessions or the manager itself. If no argument is specified, properties of the manager will be shown. If a session ID is specified, properties of the session are shown. By default, empty properties are suppressed. Use to show those too. To select specific properties to show, use . This command is intended to be used whenever computer-parsable output is required. Use session-status if you are looking for formatted human-readable output. activate ID Activate a session. This brings a session into the foreground if another session is currently in the foreground on the respective seat. Takes a session identifier as argument. If no argument is specified, the session of the caller is put into foreground. lock-session ID... unlock-session ID... Activates/deactivates the screen lock on one or more sessions, if the session supports it. Takes one or more session identifiers as arguments. If no argument is specified, the session of the caller is locked/unlocked. lock-sessions unlock-sessions Activates/deactivates the screen lock on all current sessions supporting it. terminate-session ID... Terminates a session. This kills all processes of the session and deallocates all resources attached to the session. kill-session ID... Send a signal to one or more processes of the session. Use to select which process to kill. Use to select the signal to send. User Commands list-users List currently logged in users. user-status USER... Show terse runtime status information about one or more logged in users, followed by the most recent log data from the journal. Takes one or more user names or numeric user IDs as parameters. If no parameters are passed, the status of the caller's user is shown. This function is intended to generate human-readable output. If you are looking for computer-parsable output, use show-user instead. Users may be specified by their usernames or numeric user IDs. show-user USER... Show properties of one or more users or the manager itself. If no argument is specified, properties of the manager will be shown. If a user is specified, properties of the user are shown. By default, empty properties are suppressed. Use to show those too. To select specific properties to show, use . This command is intended to be used whenever computer-parsable output is required. Use user-status if you are looking for formatted human-readable output. enable-linger USER... disable-linger USER... Enable/disable user lingering for one or more users. If enabled for a specific user, a user manager is spawned for the user at boot and kept around after logouts. This allows users who are not logged in to run long-running services. Takes one or more user names or numeric UIDs as argument. If no argument is specified, enables/disables lingering for the user of the session of the caller. terminate-user USER... Terminates all sessions of a user. This kills all processes of all sessions of the user and deallocates all runtime resources attached to the user. kill-user USER... Send a signal to all processes of a user. Use to select the signal to send. Seat Commands list-seats List currently available seats on the local system. seat-status NAME... Show terse runtime status information about one or more seats. Takes one or more seat names as parameters. If no seat names are passed the status of the caller's session's seat is shown. This function is intended to generate human-readable output. If you are looking for computer-parsable output, use show-seat instead. show-seat NAME... Show properties of one or more seats or the manager itself. If no argument is specified, properties of the manager will be shown. If a seat is specified, properties of the seat are shown. By default, empty properties are suppressed. Use to show those too. To select specific properties to show, use . This command is intended to be used whenever computer-parsable output is required. Use seat-status if you are looking for formatted human-readable output. attach NAME DEVICE... Persistently attach one or more devices to a seat. The devices should be specified via device paths in the /sys file system. To create a new seat, attach at least one graphics card to a previously unused seat name. Seat names may consist only of a–z, A–Z, 0–9, - and _ and must be prefixed with seat. To drop assignment of a device to a specific seat, just reassign it to a different seat, or use flush-devices. flush-devices Removes all device assignments previously created with attach. After this call, only automatically generated seats will remain, and all seat hardware is assigned to them. terminate-seat NAME... Terminates all sessions on a seat. This kills all processes of all sessions on the seat and deallocates all runtime resources attached to them. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, systemctl1, systemd-logind.service8, logind.conf5 systemd-229/man/logind.conf.xml000066400000000000000000000333641265713322000165670ustar00rootroot00000000000000 logind.conf systemd Developer Lennart Poettering lennart@poettering.net logind.conf 5 logind.conf logind.conf.d Login manager configuration files /etc/systemd/logind.conf /etc/systemd/logind.conf.d/*.conf /run/systemd/logind.conf.d/*.conf /usr/lib/systemd/logind.conf.d/*.conf Description These files configure various parameters of the systemd login manager, systemd-logind.service8. Options All options are configured in the [Login] section: NAutoVTs= Takes a positive integer. Configures how many virtual terminals (VTs) to allocate by default that, when switched to and are previously unused, autovt services are automatically spawned on. These services are instantiated from the template unit autovt@.service for the respective VT TTY name, for example, autovt@tty4.service. By default, autovt@.service is linked to getty@.service. In other words, login prompts are started dynamically as the user switches to unused virtual terminals. Hence, this parameter controls how many login gettys are available on the VTs. If a VT is already used by some other subsystem (for example, a graphical login), this kind of activation will not be attempted. Note that the VT configured in ReserveVT= is always subject to this kind of activation, even if it is not one of the VTs configured with the NAutoVTs= directive. Defaults to 6. When set to 0, automatic spawning of autovt services is disabled. ReserveVT= Takes a positive integer. Identifies one virtual terminal that shall unconditionally be reserved for autovt@.service activation (see above). The VT selected with this option will be marked busy unconditionally, so that no other subsystem will allocate it. This functionality is useful to ensure that, regardless of how many VTs are allocated by other subsystems, one login getty is always available. Defaults to 6 (in other words, there will always be a getty available on Alt-F6.). When set to 0, VT reservation is disabled. KillUserProcesses= Takes a boolean argument. Configures whether the processes of a user should be killed when the user completely logs out (i.e. after the user's last session ended). Defaults to no. Note that setting KillUserProcesses=1 will break tools like screen1. KillOnlyUsers= KillExcludeUsers= These settings take space-separated lists of usernames that influence the effect of KillUserProcesses=. If not empty, only processes of users listed in KillOnlyUsers= will be killed when they log out entirely. Processes of users listed in KillExcludeUsers= are excluded from being killed. KillExcludeUsers= defaults to root and takes precedence over KillOnlyUsers=, which defaults to the empty list. IdleAction= Configures the action to take when the system is idle. Takes one of ignore, poweroff, reboot, halt, kexec, suspend, hibernate, hybrid-sleep, and lock. Defaults to ignore. Note that this requires that user sessions correctly report the idle status to the system. The system will execute the action after all sessions report that they are idle, no idle inhibitor lock is active, and subsequently, the time configured with IdleActionSec= (see below) has expired. IdleActionSec= Configures the delay after which the action configured in IdleAction= (see above) is taken after the system is idle. InhibitDelayMaxSec= Specifies the maximum time a system shutdown or sleep request is delayed due to an inhibitor lock of type delay being active before the inhibitor is ignored and the operation executes anyway. Defaults to 5. HandlePowerKey= HandleSuspendKey= HandleHibernateKey= HandleLidSwitch= HandleLidSwitchDocked= Controls whether logind shall handle the system power and sleep keys and the lid switch to trigger actions such as system power-off or suspend. Can be one of ignore, poweroff, reboot, halt, kexec, suspend, hibernate, hybrid-sleep, and lock. If ignore, logind will never handle these keys. If lock, all running sessions will be screen-locked; otherwise, the specified action will be taken in the respective event. Only input devices with the power-switch udev tag will be watched for key/lid switch events. HandlePowerKey= defaults to poweroff. HandleSuspendKey= and HandleLidSwitch= default to suspend. HandleLidSwitchDocked= defaults to ignore. HandleHibernateKey= defaults to hibernate. If the system is inserted in a docking station, or if more than one display is connected, the action specified by HandleLidSwitchDocked= occurs; otherwise the HandleLidSwitch= action occurs. PowerKeyIgnoreInhibited= SuspendKeyIgnoreInhibited= HibernateKeyIgnoreInhibited= LidSwitchIgnoreInhibited= Controls whether actions triggered by the power and sleep keys and the lid switch are subject to inhibitor locks. These settings take boolean arguments. If no, the inhibitor locks taken by applications in order to block the requested operation are respected. If yes, the requested operation is executed in any case. PowerKeyIgnoreInhibited=, SuspendKeyIgnoreInhibited= and HibernateKeyIgnoreInhibited= default to no. LidSwitchIgnoreInhibited= defaults to yes. This means that the lid switch does not respect suspend blockers by default, but the power and sleep keys do. HoldoffTimeoutSec= Specifies the timeout after system startup or system resume in which systemd will hold off on reacting to lid events. This is required for the system to properly detect any hotplugged devices so systemd can ignore lid events if external monitors, or docks, are connected. If set to 0, systemd will always react immediately, possibly before the kernel fully probed all hotplugged devices. This is safe, as long as you do not care for systemd to account for devices that have been plugged or unplugged while the system was off. Defaults to 30s. RuntimeDirectorySize= Sets the size limit on the $XDG_RUNTIME_DIR runtime directory for each user who logs in. Takes a size in bytes, optionally suffixed with the usual K, G, M, and T suffixes, to the base 1024 (IEC). Alternatively, a numerical percentage suffixed by % may be specified, which sets the size limit relative to the amount of physical RAM. Defaults to 10%. Note that this size is a safety limit only. As each runtime directory is a tmpfs file system, it will only consume as much memory as is needed. UserTasksMax= Sets the maximum number of OS tasks each user may run concurrently. This controls the TasksMax= setting of the per-user slice unit, see systemd.resource-control5 for details. Defaults to 12288 (12K). RemoveIPC= Controls whether System V and POSIX IPC objects belonging to the user shall be removed when the user fully logs out. Takes a boolean argument. If enabled, the user may not consume IPC resources after the last of the user's sessions terminated. This covers System V semaphores, shared memory and message queues, as well as POSIX shared memory and message queues. Note that IPC objects of the root user and other system users are excluded from the effect of this setting. Defaults to yes. See Also systemd1, systemd-logind.service8, loginctl1, systemd-system.conf5 systemd-229/man/machine-id.xml000066400000000000000000000135561265713322000163660ustar00rootroot00000000000000 machine-id systemd Developer Lennart Poettering lennart@poettering.net machine-id 5 machine-id Local machine ID configuration file /etc/machine-id Description The /etc/machine-id file contains the unique machine ID of the local system that is set during installation. The machine ID is a single newline-terminated, hexadecimal, 32-character, lowercase machine ID string. When decoded from hexadecimal, this corresponds with a 16-byte/128-bit string. The machine ID is usually generated from a random source during system installation and stays constant for all subsequent boots. Optionally, for stateless systems, it is generated during runtime at early boot if it is found to be empty. The machine ID does not change based on user configuration or when hardware is replaced. This machine ID adheres to the same format and logic as the D-Bus machine ID. Programs may use this ID to identify the host with a globally unique ID in the network, which does not change even if the local network configuration changes. Due to this and its greater length, it is a more useful replacement for the gethostid3 call that POSIX specifies. The systemd-machine-id-setup1 tool may be used by installer tools to initialize the machine ID at install time. Use systemd-firstboot1 to initialize it on mounted (but not booted) system images. The machine-id may also be set, for example when network booting, by setting the systemd.machine_id= kernel command line parameter or passing the option to systemd. A machine-id may not be set to all zeros. Relation to OSF UUIDs Note that the machine ID historically is not an OSF UUID as defined by RFC 4122, nor a Microsoft GUID; however, starting with systemd v30, newly generated machine IDs do qualify as v4 UUIDs. In order to maintain compatibility with existing installations, an application requiring a UUID should decode the machine ID, and then apply the following operations to turn it into a valid OSF v4 UUID. With id being an unsigned character array: /* Set UUID version to 4 --- truly random generation */ id[6] = (id[6] & 0x0F) | 0x40; /* Set the UUID variant to DCE */ id[8] = (id[8] & 0x3F) | 0x80; (This code is inspired by generate_random_uuid() of drivers/char/random.c from the Linux kernel sources.) History The simple configuration file format of /etc/machine-id originates in the /var/lib/dbus/machine-id file introduced by D-Bus. In fact, this latter file might be a symlink to /etc/machine-id. See Also systemd1, systemd-machine-id-setup1, gethostid3, hostname5, machine-info5, os-release5, sd-id1283, sd_id128_get_machine3, systemd-firstboot1 systemd-229/man/machine-info.xml000066400000000000000000000154371265713322000167250ustar00rootroot00000000000000 machine-info systemd Developer Lennart Poettering lennart@poettering.net machine-info 5 machine-info Local machine information file /etc/machine-info Description The /etc/machine-info file contains machine metadata. The basic file format of machine-info is a newline-separated list of environment-like shell-compatible variable assignments. It is possible to source the configuration from shell scripts, however, beyond mere variable assignments no shell features are supported, allowing applications to read the file without implementing a shell compatible execution engine. /etc/machine-info contains metadata about the machine that is set by the user or administrator. Depending on the operating system other configuration files might be checked for machine information as well, however only as fallback. You may use hostnamectl1 to change the settings of this file from the command line. Options The following machine metadata parameters may be set using /etc/machine-info: PRETTY_HOSTNAME= A pretty human-readable UTF-8 machine identifier string. This should contain a name like Lennart's Laptop which is useful to present to the user and does not suffer by the syntax limitations of internet domain names. If possible, the internet hostname as configured in /etc/hostname should be kept similar to this one. Example: if this value is Lennart's Computer an Internet hostname of lennarts-computer might be a good choice. If this parameter is not set, an application should fall back to the Internet host name for presentation purposes. ICON_NAME= An icon identifying this machine according to the XDG Icon Naming Specification. If this parameter is not set, an application should fall back to computer or a similar icon name. CHASSIS= The chassis type. Currently, the following chassis types are defined: desktop, laptop, server, tablet, handset, watch, and embedded, as well as the special chassis types vm and container for virtualized systems that lack an immediate physical chassis. Note that many systems allow detection of the chassis type automatically (based on firmware information or suchlike). This setting (if set) shall take precedence over automatically detected information and is useful to override misdetected configuration or to manually configure the chassis type where automatic detection is not available. DEPLOYMENT= Describes the system deployment environment. One of the following is suggested: development, integration, staging, production. LOCATION= Describes the system location if applicable and known. Takes a human-friendly, free-form string. This may be as generic as Berlin, Germany or as specific as Left Rack, 2nd Shelf. Example PRETTY_HOSTNAME="Lennart's Tablet" ICON_NAME=computer-tablet CHASSIS=tablet DEPLOYMENT=production See Also systemd1, os-release5, hostname5, machine-id5, hostnamectl1, systemd-hostnamed.service8 systemd-229/man/machinectl.xml000066400000000000000000001317351265713322000164770ustar00rootroot00000000000000 machinectl systemd Developer Lennart Poettering lennart@poettering.net machinectl 1 machinectl Control the systemd machine manager machinectl OPTIONS COMMAND NAME Description machinectl may be used to introspect and control the state of the systemd1 virtual machine and container registration manager systemd-machined.service8. machinectl may be used to execute operations on machines and images. Machines in this sense are considered running instances of: Virtual Machines (VMs) that virtualize hardware to run full operating system (OS) instances (including their kernels) in a virtualized environment on top of the host OS. Containers that share the hardware and OS kernel with the host OS, in order to run OS userspace instances on top the host OS. The host system itself Machines are identified by names that follow the same rules as UNIX and DNS host names, for details, see below. Machines are instantiated from disk or file system images that frequently — but not necessarily — carry the same name as machines running from them. Images in this sense are considered: Directory trees containing an OS, including its top-level directories /usr, /etc, and so on. btrfs subvolumes containing OS trees, similar to normal directory trees. Binary "raw" disk images containing MBR or GPT partition tables and Linux file system partitions. The file system tree of the host OS itself. Options The following options are understood: When showing machine or image properties, limit the output to certain properties as specified by the argument. If not specified, all set properties are shown. The argument should be a property name, such as Name. If specified more than once, all properties with the specified names are shown. When showing machine or image properties, show all properties regardless of whether they are set or not. When listing VM or container images, do not suppress images beginning in a dot character (.). Do not ellipsize process tree entries. Do not query the user for authentication for privileged operations. When used with kill, choose which processes to kill. Must be one of , or to select whether to kill only the leader process of the machine or all processes of the machine. If omitted, defaults to . When used with kill, choose which signal to send to selected processes. Must be one of the well-known signal specifiers, such as SIGTERM, SIGINT or SIGSTOP. If omitted, defaults to SIGTERM. When used with the shell command, chooses the user ID to open the interactive shell session as. If this switch is not specified, defaults to root. Note that this switch is not supported for the login command (see below). When used with the shell command, sets an environment variable to pass to the executed shell. Takes a pair of environment variable name and value, separated by = as argument. This switch may be used multiple times to set multiple environment variables. Note that this switch is not supported for the login command (see below). When used with bind, creates the destination directory before applying the bind mount. When used with bind, applies a read-only bind mount. When used with status, controls the number of journal lines to show, counting from the most recent ones. Takes a positive integer argument. Defaults to 10. When used with status, controls the formatting of the journal entries that are shown. For the available choices, see journalctl1. Defaults to short. When downloading a container or VM image, specify whether the image shall be verified before it is made available. Takes one of no, checksum and signature. If no, no verification is done. If checksum is specified, the download is checked for integrity after the transfer is complete, but no signatures are verified. If signature is specified, the checksum is verified and the image's signature is checked against a local keyring of trustable vendors. It is strongly recommended to set this option to signature if the server and protocol support this. Defaults to signature. When downloading a container or VM image, and a local copy by the specified local machine name already exists, delete it first and replace it by the newly downloaded image. When used with the or commands, specifies the compression format to use for the resulting file. Takes one of uncompressed, xz, gzip, bzip2. By default, the format is determined automatically from the image file name passed. Commands The following commands are understood: Machine Commands list List currently running (online) virtual machines and containers. To enumerate machine images that can be started, use list-images (see below). Note that this command hides the special .host machine by default. Use the switch to show it. status NAME... Show runtime status information about one or more virtual machines and containers, followed by the most recent log data from the journal. This function is intended to generate human-readable output. If you are looking for computer-parsable output, use show instead. Note that the log data shown is reported by the virtual machine or container manager, and frequently contains console output of the machine, but not necessarily journal contents of the machine itself. show [NAME...] Show properties of one or more registered virtual machines or containers or the manager itself. If no argument is specified, properties of the manager will be shown. If an NAME is specified, properties of this virtual machine or container are shown. By default, empty properties are suppressed. Use to show those too. To select specific properties to show, use . This command is intended to be used whenever computer-parsable output is required, and does not print the cgroup tree or journal entries. Use status if you are looking for formatted human-readable output. start NAME... Start a container as a system service, using systemd-nspawn1. This starts systemd-nspawn@.service, instantiated for the specified machine name, similar to the effect of systemctl start on the service name. systemd-nspawn looks for a container image by the specified name in /var/lib/machines/ (and other search paths, see below) and runs it. Use list-images (see below) for listing available container images to start. Note that systemd-machined.service8 also interfaces with a variety of other container and VM managers, systemd-nspawn is just one implementation of it. Most of the commands available in machinectl may be used on containers or VMs controlled by other managers, not just systemd-nspawn. Starting VMs and container images on those managers requires manager-specific tools. To interactively start a container on the command line with full access to the container's console, please invoke systemd-nspawn directly. To stop a running container use machinectl poweroff, see below. login [NAME] Open an interactive terminal login session in a container or on the local host. If an argument is supplied, it refers to the container machine to connect to. If none is specified, or the container name is specified as the empty string, or the special machine name .host (see below) is specified, the connection is made to the local host instead. This will create a TTY connection to a specific container or the local host and asks for the execution of a getty on it. Note that this is only supported for containers running systemd1 as init system. This command will open a full login prompt on the container or the local host, which then asks for username and password. Use shell (see below) or systemd-run1 with the switch to directly invoke a single command, either interactively or in the background. shell [[NAME@]NAME [PATH [ARGUMENTS...]]] Open an interactive shell session in a container or on the local host. The first argument refers to the container machine to connect to. If none is specified, or the machine name is specified as the empty string, or the special machine name .host (see below) is specified, the connection is made to the local host instead. This works similar to login but immediately invokes a user process. This command runs the specified executable with the specified arguments, or /bin/sh if none is specified. By default, opens a root shell, but by using , or by prefixing the machine name with a username and an @ character, a different user may be selected. Use to set environment variables for the executed process. When using the shell command without arguments, (thus invoking the executed shell or command on the local host), it is in many ways similar to a su1 session, but, unlike su, completely isolates the new session from the originating session, so that it shares no process or session properties, and is in a clean and well-defined state. It will be tracked in a new utmp, login, audit, security and keyring session, and will not inherit any environment variables or resource limits, among other properties. Note that systemd-run1 may be used in place of the shell command, and allows more detailed, low-level configuration of the invoked unit. However, it is frequently more privileged than the shell command. enable NAME... disable NAME... Enable or disable a container as a system service to start at system boot, using systemd-nspawn1. This enables or disables systemd-nspawn@.service, instantiated for the specified machine name, similar to the effect of systemctl enable or systemctl disable on the service name. poweroff NAME... Power off one or more containers. This will trigger a reboot by sending SIGRTMIN+4 to the container's init process, which causes systemd-compatible init systems to shut down cleanly. This operation does not work on containers that do not run a systemd1-compatible init system, such as sysvinit. Use terminate (see below) to immediately terminate a container or VM, without cleanly shutting it down. reboot NAME... Reboot one or more containers. This will trigger a reboot by sending SIGINT to the container's init process, which is roughly equivalent to pressing Ctrl+Alt+Del on a non-containerized system, and is compatible with containers running any system manager. terminate NAME... Immediately terminates a virtual machine or container, without cleanly shutting it down. This kills all processes of the virtual machine or container and deallocates all resources attached to that instance. Use poweroff to issue a clean shutdown request. kill NAME... Send a signal to one or more processes of the virtual machine or container. This means processes as seen by the host, not the processes inside the virtual machine or container. Use to select which process to kill. Use to select the signal to send. bind NAME PATH [PATH] Bind mounts a directory from the host into the specified container. The first directory argument is the source directory on the host, the second directory argument is the destination directory in the container. When the latter is omitted, the destination path in the container is the same as the source path on the host. When combined with the switch, a ready-only bind mount is created. When combined with the switch, the destination path is first created before the mount is applied. Note that this option is currently only supported for systemd-nspawn1 containers. copy-to NAME PATH [PATH] Copies files or directories from the host system into a running container. Takes a container name, followed by the source path on the host and the destination path in the container. If the destination path is omitted, the same as the source path is used. copy-from NAME PATH [PATH] Copies files or directories from a container into the host system. Takes a container name, followed by the source path in the container the destination path on the host. If the destination path is omitted, the same as the source path is used. Image Commands list-images Show a list of locally installed container and VM images. This enumerates all raw disk images and container directories and subvolumes in /var/lib/machines/ (and other search paths, see below). Use start (see above) to run a container off one of the listed images. Note that, by default, containers whose name begins with a dot (.) are not shown. To show these too, specify . Note that a special image .host always implicitly exists and refers to the image the host itself is booted from. image-status [NAME...] Show terse status information about one or more container or VM images. This function is intended to generate human-readable output. Use show-image (see below) to generate computer-parsable output instead. show-image [NAME...] Show properties of one or more registered virtual machine or container images, or the manager itself. If no argument is specified, properties of the manager will be shown. If an NAME is specified, properties of this virtual machine or container image are shown. By default, empty properties are suppressed. Use to show those too. To select specific properties to show, use . This command is intended to be used whenever computer-parsable output is required. Use image-status if you are looking for formatted human-readable output. clone NAME NAME Clones a container or VM image. The arguments specify the name of the image to clone and the name of the newly cloned image. Note that plain directory container images are cloned into subvolume images with this command. Note that cloning a container or VM image is optimized for btrfs file systems, and might not be efficient on others, due to file system limitations. Note that this command leaves host name, machine ID and all other settings that could identify the instance unmodified. The original image and the cloned copy will hence share these credentials, and it might be necessary to manually change them in the copy. rename NAME NAME Renames a container or VM image. The arguments specify the name of the image to rename and the new name of the image. read-only NAME [BOOL] Marks or (unmarks) a container or VM image read-only. Takes a VM or container image name, followed by a boolean as arguments. If the boolean is omitted, positive is implied, i.e. the image is marked read-only. remove NAME... Removes one or more container or VM images. The special image .host, which refers to the host's own directory tree, may not be removed. set-limit [NAME] BYTES Sets the maximum size in bytes that a specific container or VM image, or all images, may grow up to on disk (disk quota). Takes either one or two parameters. The first, optional parameter refers to a container or VM image name. If specified, the size limit of the specified image is changed. If omitted, the overall size limit of the sum of all images stored locally is changed. The final argument specifies the size limit in bytes, possibly suffixed by the usual K, M, G, T units. If the size limit shall be disabled, specify - as size. Note that per-container size limits are only supported on btrfs file systems. Also note that, if set-limit is invoked without an image parameter, and /var/lib/machines is empty, and the directory is not located on btrfs, a btrfs loopback file is implicitly created as /var/lib/machines.raw with the given size, and mounted to /var/lib/machines. The size of the loopback may later be readjusted with set-limit, as well. If such a loopback-mounted /var/lib/machines directory is used, set-limit without an image name alters both the quota setting within the file system as well as the loopback file and file system size itself. Image Transfer Commands pull-tar URL [NAME] Downloads a .tar container image from the specified URL, and makes it available under the specified local machine name. The URL must be of type http:// or https://, and must refer to a .tar, .tar.gz, .tar.xz or .tar.bz2 archive file. If the local machine name is omitted, it is automatically derived from the last component of the URL, with its suffix removed. The image is verified before it is made available, unless is specified. Verification is done via SHA256SUMS and SHA256SUMS.gpg files that need to be made available on the same web server, under the same URL as the .tar file, but with the last component (the filename) of the URL replaced. With , only the SHA256 checksum for the file is verified, based on the SHA256SUMS file. With , the SHA256SUMS file is first verified with detached GPG signature file SHA256SUMS.gpg. The public key for this verification step needs to be available in /usr/lib/systemd/import-pubring.gpg or /etc/systemd/import-pubring.gpg. The container image will be downloaded and stored in a read-only subvolume in /var/lib/machines/ that is named after the specified URL and its HTTP etag. A writable snapshot is then taken from this subvolume, and named after the specified local name. This behavior ensures that creating multiple container instances of the same URL is efficient, as multiple downloads are not necessary. In order to create only the read-only image, and avoid creating its writable snapshot, specify - as local machine name. Note that the read-only subvolume is prefixed with .tar-, and is thus not shown by list-images, unless is passed. Note that pressing C-c during execution of this command will not abort the download. Use cancel-transfer, described below. pull-raw URL [NAME] Downloads a .raw container or VM disk image from the specified URL, and makes it available under the specified local machine name. The URL must be of type http:// or https://. The container image must either be a .qcow2 or raw disk image, optionally compressed as .gz, .xz, or .bz2. If the local machine name is omitted, it is automatically derived from the last component of the URL, with its suffix removed. Image verification is identical for raw and tar images (see above). If the downloaded image is in .qcow2 format it is converted into a raw image file before it is made available. Downloaded images of this type will be placed as read-only .raw file in /var/lib/machines/. A local, writable (reflinked) copy is then made under the specified local machine name. To omit creation of the local, writable copy pass - as local machine name. Similar to the behavior of pull-tar, the read-only image is prefixed with .raw-, and thus not shown by list-images, unless is passed. Note that pressing C-c during execution of this command will not abort the download. Use cancel-transfer, described below. import-tar FILE [NAME] import-raw FILE [NAME] Imports a TAR or RAW container or VM image, and places it under the specified name in /var/lib/machines/. When import-tar is used, the file specified as the first argument should be a tar archive, possibly compressed with xz, gzip or bzip2. It will then be unpacked into its own subvolume in /var/lib/machines. When import-raw is used, the file should be a qcow2 or raw disk image, possibly compressed with xz, gzip or bzip2. If the second argument (the resulting image name) is not specified, it is automatically derived from the file name. If the file name is passed as -, the image is read from standard input, in which case the second argument is mandatory. Both pull-tar and pull-raw will resize /var/lib/machines.raw and the filesystem therein as necessary. Optionally, the switch may be used to create a read-only container or VM image. No cryptographic validation is done when importing the images. Much like image downloads, ongoing imports may be listed with list-transfers and aborted with cancel-transfer. export-tar NAME [FILE] export-raw NAME [FILE] Exports a TAR or RAW container or VM image and stores it in the specified file. The first parameter should be a VM or container image name. The second parameter should be a file path the TAR or RAW image is written to. If the path ends in .gz, the file is compressed with gzip, if it ends in .xz, with xz, and if it ends in .bz2, with bzip2. If the path ends in neither, the file is left uncompressed. If the second argument is missing, the image is written to standard output. The compression may also be explicitly selected with the switch. This is in particular useful if the second parameter is left unspecified. Much like image downloads and imports, ongoing exports may be listed with list-transfers and aborted with cancel-transfer. Note that, currently, only directory and subvolume images may be exported as TAR images, and only raw disk images as RAW images. list-transfers Shows a list of container or VM image downloads, imports and exports that are currently in progress. cancel-transfers ID... Aborts a download, import or export of the container or VM image with the specified ID. To list ongoing transfers and their IDs, use list-transfers. Machine and Image Names The machinectl tool operates on machines and images whose names must be chosen following strict rules. Machine names must be suitable for use as host names following a conservative subset of DNS and UNIX/Linux semantics. Specifically, they must consist of one or more non-empty label strings, separated by dots. No leading or trailing dots are allowed. No sequences of multiple dots are allowed. The label strings may only consist of alphanumeric characters as well as the dash and underscore. The maximum length of a machine name is 64 characters. A special machine with the name .host refers to the running host system itself. This is useful for execution operations or inspecting the host system as well. Note that machinectl list will not show this special machine unless the switch is specified. Requirements on image names are less strict, however, they must be valid UTF-8, must be suitable as file names (hence not be the single or double dot, and not include a slash), and may not contain control characters. Since many operations search for an image by the name of a requested machine, it is recommended to name images in the same strict fashion as machines. A special image with the name .host refers to the image of the running host system. It hence conceptually maps to the special .host machine name described above. Note that machinectl list-images will not show this special image either, unless is specified. Files and Directories Machine images are preferably stored in /var/lib/machines/, but are also searched for in /usr/local/lib/machines/ and /usr/lib/machines/. For compatibility reasons, the directory /var/lib/container/ is searched, too. Note that images stored below /usr are always considered read-only. It is possible to symlink machines images from other directories into /var/lib/machines/ to make them available for control with machinectl. Note that many image operations are only supported, efficient or atomic on btrfs file systems. Due to this, if the pull-tar, pull-raw, import-tar, import-raw and set-limit commands notice that /var/lib/machines is empty and not located on btrfs, they will implicitly set up a loopback file /var/lib/machines.raw containing a btrfs file system that is mounted to /var/lib/machines. The size of this loopback file may be controlled dynamically with set-limit. Disk images are understood by systemd-nspawn1 and machinectl in three formats: A simple directory tree, containing the files and directories of the container to boot. Subvolumes (on btrfs file systems), which are similar to the simple directories, described above. However, they have additional benefits, such as efficient cloning and quota reporting. "Raw" disk images, i.e. binary images of disks with a GPT or MBR partition table. Images of this type are regular files with the suffix .raw. See systemd-nspawn1 for more information on image formats, in particular its and options. Examples Download an Ubuntu image and open a shell in it # machinectl pull-tar https://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-root.tar.gz # systemd-nspawn -M trusty-server-cloudimg-amd64-root This downloads and verifies the specified .tar image, and then uses systemd-nspawn1 to open a shell in it. Download a Fedora image, set a root password in it, start it as service # machinectl pull-raw --verify=no http://ftp.halifax.rwth-aachen.de/fedora/linux/releases/21/Cloud/Images/x86_64/Fedora-Cloud-Base-20141203-21.x86_64.raw.xz # systemd-nspawn -M Fedora-Cloud-Base-20141203-21 # passwd # exit # machinectl start Fedora-Cloud-Base-20141203-21 # machinectl login Fedora-Cloud-Base-20141203-21 This downloads the specified .raw image with verification disabled. Then, a shell is opened in it and a root password is set. Afterwards the shell is left, and the machine started as system service. With the last command a login prompt into the container is requested. Exports a container image as tar file # machinectl export-tar fedora myfedora.tar.xz Exports the container fedora as an xz-compressed tar file myfedora.tar.xz into the current directory. Create a new shell session # machinectl shell --uid=lennart This creates a new shell session on the local host for the user ID lennart, in a su1-like fashion. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd-machined.service8, systemd-nspawn1, systemd.special7, tar1, xz1, gzip1, bzip21 systemd-229/man/modules-load.d.xml000066400000000000000000000071231265713322000171700ustar00rootroot00000000000000 modules-load.d systemd Developer Lennart Poettering lennart@poettering.net modules-load.d 5 modules-load.d Configure kernel modules to load at boot /etc/modules-load.d/*.conf /run/modules-load.d/*.conf /usr/lib/modules-load.d/*.conf Description systemd-modules-load.service8 reads files from the above directories which contain kernel modules to load during boot in a static list. Each configuration file is named in the style of /etc/modules-load.d/program.conf. Note that it is usually a better idea to rely on the automatic module loading by PCI IDs, USB IDs, DMI IDs or similar triggers encoded in the kernel modules themselves instead of static configuration like this. In fact, most modern kernel modules are prepared for automatic loading already. Configuration Format The configuration files should simply contain a list of kernel module names to load, separated by newlines. Empty lines and lines whose first non-whitespace character is # or ; are ignored. Example /etc/modules-load.d/virtio-net.conf example: # Load virtio-net.ko at boot virtio-net See Also systemd1, systemd-modules-load.service8, systemd-delta1, modprobe8 systemd-229/man/networkctl.xml000066400000000000000000000124101265713322000165500ustar00rootroot00000000000000 networkctl systemd Documentation Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl networkctl 1 networkctl Query the status of network links networkctl OPTIONS COMMAND LINK Description networkctl may be used to introspect the state of the network links as seen by systemd-networkd. Please refer to systemd-networkd.service8 for an introduction to the basic concepts, functionality, and configuration syntax. Options The following options are understood: Show all links with status. Commands The following commands are understood: list Show a list of existing links and their status. Produces output similar to IDX LINK TYPE OPERATIONAL SETUP 1 lo loopback carrier unmanaged 2 eth0 ether routable configured 3 virbr0 ether no-carrier unmanaged 4 virbr0-nic ether off unmanaged 4 links listed. status LINK... Show information about the specified links: type, state, kernel module driver, hardware and IP address, configured DNS servers, etc. When no links are specified, routable links are shown. Also see the option . Produces output similar to ● State: routable Address: 10.193.76.5 on eth0 192.168.122.1 on virbr0 169.254.190.105 on eth0 fe80::5054:aa:bbbb:cccc on eth0 Gateway: 10.193.11.1 (CISCO SYSTEMS, INC.) on eth0 DNS: 8.8.8.8 8.8.4.4 lldp Show LLDP (Link Layer Discovery Protocol) status. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd-networkd.service8, systemd.network5, systemd.netdev5 systemd-229/man/nss-myhostname.xml000066400000000000000000000132721265713322000173500ustar00rootroot00000000000000 nss-myhostname systemd Developer Lennart Poettering lennart@poettering.net nss-myhostname 8 nss-myhostname libnss_myhostname.so.2 Provide hostname resolution for the locally configured system hostname. libnss_myhostname.so.2 Description nss-myhostname is a plugin for the GNU Name Service Switch (NSS) functionality of the GNU C Library (glibc), primarily providing hostname resolution for the locally configured system hostname as returned by gethostname2. The precise hostnames resolved by this module are: The local, configured hostname is resolved to all locally configured IP addresses ordered by their scope, or — if none are configured — the IPv4 address 127.0.0.2 (which is on the local loopback) and the IPv6 address ::1 (which is the local host). The hostname localhost (as well as any hostname ending in .localhost, .localdomain or equal to localdomain) is resolved to the IP addresses 127.0.0.1 and ::1. The hostname gateway is resolved to all current default routing gateway addresses, ordered by their metric. This assigns a stable hostname to the current gateway, useful for referencing it independently of the current network configuration state. Various software relies on an always-resolvable local hostname. When using dynamic hostnames, this is traditionally achieved by patching /etc/hosts at the same time as changing the hostname. This is problematic since it requires a writable /etc file system and is fragile because the file might be edited by the administrator at the same time. With nss-myhostname enabled, changing /etc/hosts is unnecessary, and on many systems, the file becomes entirely optional. To activate the NSS modules, myhostname has to be added to the line starting with hosts: in /etc/nsswitch.conf. It is recommended to place myhostname last in the nsswitch.conf line to make sure that this mapping is only used as fallback, and that any DNS or /etc/hosts based mapping takes precedence. Example Here is an example /etc/nsswitch.conf file that enables myhostname correctly: passwd: compat mymachines group: compat mymachines shadow: compat hosts: files resolve mymachines myhostname networks: files protocols: db files services: db files ethers: db files rpc: db files netgroup: nis To test, use glibc's getent tool: $ getent ahosts `hostname` ::1 STREAM omega ::1 DGRAM ::1 RAW 127.0.0.2 STREAM 127.0.0.2 DGRAM 127.0.0.2 RAW In this case, the local hostname is omega. See Also systemd1, nss-resolve8, nss-mymachines8, nsswitch.conf5, getent1 systemd-229/man/nss-mymachines.xml000066400000000000000000000103321265713322000173130ustar00rootroot00000000000000 nss-mymachines systemd Developer Lennart Poettering lennart@poettering.net nss-mymachines 8 nss-mymachines libnss_mymachines.so.2 Provide hostname resolution for local container instances. libnss_mymachines.so.2 Description nss-mymachines is a plugin for the GNU Name Service Switch (NSS) functionality of the GNU C Library (glibc), providing hostname resolution for container names of containers running locally that are registered with systemd-machined.service8. The container names are resolved to the IP addresses of the specific container, ordered by their scope. The module also resolves user IDs used by containers to user names indicating the container name, and back. To activate the NSS modules, mymachines has to be added to the lines starting with hosts:, passwd: and group: in /etc/nsswitch.conf. It is recommended to place mymachines near the end of the nsswitch.conf lines to make sure that its mappings are only used as fallback, and that any other mappings, such as DNS or /etc/hosts based mappings, take precedence. Example Here is an example /etc/nsswitch.conf file that enables mymachines correctly: passwd: compat mymachines group: compat mymachines shadow: compat hosts: files resolve mymachines myhostname networks: files protocols: db files services: db files ethers: db files rpc: db files netgroup: nis See Also systemd1, systemd-machined.service8, nss-resolve8, nss-myhostname8, nsswitch.conf5, getent1 systemd-229/man/nss-resolve.xml000066400000000000000000000102011265713322000166300ustar00rootroot00000000000000 nss-resolve systemd Developer Lennart Poettering lennart@poettering.net nss-resolve 8 nss-resolve libnss_resolve.so.2 Provide hostname resolution via systemd-resolved.service libnss_resolve.so.2 Description nss-resolve is a plugin module for the GNU Name Service Switch (NSS) functionality of the GNU C Library (glibc) enabling it to resolve host names via the systemd-resolved8 local network name resolution service. To activate the NSS module, resolve has to be added to the line starting with hosts: in /etc/nsswitch.conf. It is recommended to place resolve early in the nsswitch.conf line (but after the files entry), replacing the dns entry if it exists, to ensure DNS queries are always routed via systemd-resolved8. Example Here is an example /etc/nsswitch.conf file that enables resolve correctly: passwd: compat mymachines group: compat mymachines shadow: compat hosts: files resolve mymachines myhostname networks: files protocols: db files services: db files ethers: db files rpc: db files netgroup: nis Note that nss-resolve will chain-load nss-dns if systemd-resolved.service is not running, ensuring that basic DNS resolution continues to work if the service is down. See Also systemd1, systemd-resolved8, nss-mymachines8, nss-myhostname8, nsswitch.conf5 systemd-229/man/os-release.xml000066400000000000000000000371411265713322000164230ustar00rootroot00000000000000 os-release systemd Developer Lennart Poettering lennart@poettering.net os-release 5 os-release Operating system identification /etc/os-release /usr/lib/os-release Description The /etc/os-release and /usr/lib/os-release files contain operating system identification data. The basic file format of os-release is a newline-separated list of environment-like shell-compatible variable assignments. It is possible to source the configuration from shell scripts, however, beyond mere variable assignments, no shell features are supported (this means variable expansion is explicitly not supported), allowing applications to read the file without implementing a shell compatible execution engine. Variable assignment values must be enclosed in double or single quotes if they include spaces, semicolons or other special characters outside of A–Z, a–z, 0–9. Shell special characters ("$", quotes, backslash, backtick) must be escaped with backslashes, following shell style. All strings should be in UTF-8 format, and non-printable characters should not be used. It is not supported to concatenate multiple individually quoted strings. Lines beginning with "#" shall be ignored as comments. The file /etc/os-release takes precedence over /usr/lib/os-release. Applications should check for the former, and exclusively use its data if it exists, and only fall back to /usr/lib/os-release if it is missing. Applications should not read data from both files at the same time. /usr/lib/os-release is the recommended place to store OS release information as part of vendor trees. /etc/os-release should be a relative symlink to /usr/lib/os-release, to provide compatibility with applications only looking at /etc. A relative symlink instead of an absolute symlink is necessary to avoid breaking the link in a chroot or initrd environment such as dracut. os-release contains data that is defined by the operating system vendor and should generally not be changed by the administrator. As this file only encodes names and identifiers it should not be localized. The /etc/os-release and /usr/lib/os-release files might be symlinks to other files, but it is important that the file is available from earliest boot on, and hence must be located on the root file system. For a longer rationale for os-release please refer to the Announcement of /etc/os-release. Options The following OS identifications parameters may be set using os-release: NAME= A string identifying the operating system, without a version component, and suitable for presentation to the user. If not set, defaults to NAME=Linux. Example: NAME=Fedora or NAME="Debian GNU/Linux". VERSION= A string identifying the operating system version, excluding any OS name information, possibly including a release code name, and suitable for presentation to the user. This field is optional. Example: VERSION=17 or VERSION="17 (Beefy Miracle)". ID= A lower-case string (no spaces or other characters outside of 0–9, a–z, ".", "_" and "-") identifying the operating system, excluding any version information and suitable for processing by scripts or usage in generated filenames. If not set, defaults to ID=linux. Example: ID=fedora or ID=debian. ID_LIKE= A space-separated list of operating system identifiers in the same syntax as the ID= setting. It should list identifiers of operating systems that are closely related to the local operating system in regards to packaging and programming interfaces, for example listing one or more OS identifiers the local OS is a derivative from. An OS should generally only list other OS identifiers it itself is a derivative of, and not any OSes that are derived from it, though symmetric relationships are possible. Build scripts and similar should check this variable if they need to identify the local operating system and the value of ID= is not recognized. Operating systems should be listed in order of how closely the local operating system relates to the listed ones, starting with the closest. This field is optional. Example: for an operating system with ID=centos, an assignment of ID_LIKE="rhel fedora" would be appropriate. For an operating system with ID=ubuntu, an assignment of ID_LIKE=debian is appropriate. VERSION_ID= A lower-case string (mostly numeric, no spaces or other characters outside of 0–9, a–z, ".", "_" and "-") identifying the operating system version, excluding any OS name information or release code name, and suitable for processing by scripts or usage in generated filenames. This field is optional. Example: VERSION_ID=17 or VERSION_ID=11.04. PRETTY_NAME= A pretty operating system name in a format suitable for presentation to the user. May or may not contain a release code name or OS version of some kind, as suitable. If not set, defaults to PRETTY_NAME="Linux". Example: PRETTY_NAME="Fedora 17 (Beefy Miracle)". ANSI_COLOR= A suggested presentation color when showing the OS name on the console. This should be specified as string suitable for inclusion in the ESC [ m ANSI/ECMA-48 escape code for setting graphical rendition. This field is optional. Example: ANSI_COLOR="0;31" for red, or ANSI_COLOR="1;34" for light blue. CPE_NAME= A CPE name for the operating system, in URI binding syntax, following the Common Platform Enumeration Specification as proposed by the NIST. This field is optional. Example: CPE_NAME="cpe:/o:fedoraproject:fedora:17" HOME_URL= SUPPORT_URL= BUG_REPORT_URL= PRIVACY_POLICY_URL= Links to resources on the Internet related the operating system. HOME_URL= should refer to the homepage of the operating system, or alternatively some homepage of the specific version of the operating system. SUPPORT_URL= should refer to the main support page for the operating system, if there is any. This is primarily intended for operating systems which vendors provide support for. BUG_REPORT_URL= should refer to the main bug reporting page for the operating system, if there is any. This is primarily intended for operating systems that rely on community QA. PRIVACY_POLICY_URL= should refer to the main privacy policy page for the operation system, if there is any. These settings are optional, and providing only some of these settings is common. These URLs are intended to be exposed in "About this system" UIs behind links with captions such as "About this Operating System", "Obtain Support", "Report a Bug", or "Privacy Policy". The values should be in RFC3986 format, and should be http: or https: URLs, and possibly mailto: or tel:. Only one URL shall be listed in each setting. If multiple resources need to be referenced, it is recommended to provide an online landing page linking all available resources. Examples: HOME_URL="https://fedoraproject.org/" and BUG_REPORT_URL="https://bugzilla.redhat.com/" BUILD_ID= A string uniquely identifying the system image used as the origin for a distribution (it is not updated with system updates). The field can be identical between different VERSION_IDs as BUILD_ID is an only a unique identifier to a specific version. Distributions that release each update as a new version would only need to use VERSION_ID as each build is already distinct based on the VERSION_ID. This field is optional. Example: BUILD_ID="2013-03-20.3" or BUILD_ID=201303203. VARIANT= A string identifying a specific variant or edition of the operating system suitable for presentation to the user. This field may be used to inform the user that the configuration of this system is subject to a specific divergent set of rules or default configuration settings. This field is optional and may not be implemented on all systems. Examples: VARIANT="Server Edition", VARIANT="Smart Refrigerator Edition" Note: this field is for display purposes only. The VARIANT_ID field should be used for making programmatic decisions. VARIANT_ID= A lower-case string (no spaces or other characters outside of 0–9, a–z, ".", "_" and "-"), identifying a specific variant or edition of the operating system. This may be interpreted by other packages in order to determine a divergent default configuration. This field is optional and may not be implemented on all systems. Examples: VARIANT_ID=server, VARIANT_ID=embedded If you are reading this file from C code or a shell script to determine the OS or a specific version of it, use the ID and VERSION_ID fields, possibly with ID_LIKE as fallback for ID. When looking for an OS identification string for presentation to the user use the PRETTY_NAME field. Note that operating system vendors may choose not to provide version information, for example to accommodate for rolling releases. In this case, VERSION and VERSION_ID may be unset. Applications should not rely on these fields to be set. Operating system vendors may extend the file format and introduce new fields. It is highly recommended to prefix new fields with an OS specific name in order to avoid name clashes. Applications reading this file must ignore unknown fields. Example: DEBIAN_BTS="debbugs://bugs.debian.org/" Example NAME=Fedora VERSION="17 (Beefy Miracle)" ID=fedora VERSION_ID=17 PRETTY_NAME="Fedora 17 (Beefy Miracle)" ANSI_COLOR="0;34" CPE_NAME="cpe:/o:fedoraproject:fedora:17" HOME_URL="https://fedoraproject.org/" BUG_REPORT_URL="https://bugzilla.redhat.com/" See Also systemd1, lsb_release1, hostname5, machine-id5, machine-info5 systemd-229/man/pam_systemd.xml000066400000000000000000000271701265713322000167120ustar00rootroot00000000000000 pam_systemd systemd Developer Lennart Poettering lennart@poettering.net pam_systemd 8 pam_systemd Register user sessions in the systemd login manager pam_systemd.so Description pam_systemd registers user sessions with the systemd login manager systemd-logind.service8, and hence the systemd control group hierarchy. On login, this module ensures the following: If it does not exist yet, the user runtime directory /run/user/$USER is created and its ownership changed to the user that is logging in. The $XDG_SESSION_ID environment variable is initialized. If auditing is available and pam_loginuid.so was run before this module (which is highly recommended), the variable is initialized from the auditing session id (/proc/self/sessionid). Otherwise, an independent session counter is used. A new systemd scope unit is created for the session. If this is the first concurrent session of the user, an implicit slice below user.slice is automatically created and the scope placed into it. An instance of the system service user@.service, which runs the systemd user manager instance, is started. On logout, this module ensures the following: If enabled in logind.conf 5, all processes of the session are terminated. If the last concurrent session of a user ends, the user's systemd instance will be terminated too, and so will the user's slice unit. If the last concurrent session of a user ends, the $XDG_RUNTIME_DIR directory and all its contents are removed, too. If the system was not booted up with systemd as init system, this module does nothing and immediately returns PAM_SUCCESS. Options The following options are understood: Takes a string argument which sets the session class. The XDG_SESSION_CLASS environmental variable takes precedence. One of user, greeter, lock-screen or background. See sd_session_get_class3 for details about the session class. Takes a string argument which sets the session type. The XDG_SESSION_TYPE environmental variable takes precedence. One of unspecified, tty, x11, wayland or mir. See sd_session_get_type3 for details about the session type. Takes an optional boolean argument. If yes or without the argument, the module will log debugging information as it operates. Module Types Provided Only is provided. Environment The following environment variables are set for the processes of the user's session: $XDG_SESSION_ID A session identifier, suitable to be used in filenames. The string itself should be considered opaque, although often it is just the audit session ID as reported by /proc/self/sessionid. Each ID will be assigned only once during machine uptime. It may hence be used to uniquely label files or other resources of this session. $XDG_RUNTIME_DIR Path to a user-private user-writable directory that is bound to the user login time on the machine. It is automatically created the first time a user logs in and removed on the user's final logout. If a user logs in twice at the same time, both sessions will see the same $XDG_RUNTIME_DIR and the same contents. If a user logs in once, then logs out again, and logs in again, the directory contents will have been lost in between, but applications should not rely on this behavior and must be able to deal with stale files. To store session-private data in this directory, the user should include the value of $XDG_SESSION_ID in the filename. This directory shall be used for runtime file system objects such as AF_UNIX sockets, FIFOs, PID files and similar. It is guaranteed that this directory is local and offers the greatest possible file system feature set the operating system provides. For further details, see the XDG Base Directory Specification. The following environment variables are read by the module and may be used by the PAM service to pass metadata to the module: $XDG_SESSION_TYPE The session type. This may be used instead of on the module parameter line, and is usually preferred. $XDG_SESSION_CLASS The session class. This may be used instead of on the module parameter line, and is usually preferred. $XDG_SESSION_DESKTOP A single, short identifier string for the desktop environment. This may be used to indicate the session desktop used, where this applies and if this information is available. For example: GNOME, or KDE. It is recommended to use the same identifiers and capitalization as for $XDG_CURRENT_DESKTOP, as defined by the Desktop Entry Specification. (However, note that $XDG_SESSION_DESKTOP only takes a single item, and not a colon-separated list like $XDG_CURRENT_DESKTOP.) See sd_session_get_desktop3 for more details. $XDG_SEAT The seat name the session shall be registered for, if any. $XDG_VTNR The VT number the session shall be registered for, if any. (Only applies to seats with a VT available, such as seat0) Example #%PAM-1.0 auth required pam_unix.so auth required pam_nologin.so account required pam_unix.so password required pam_unix.so session required pam_unix.so session required pam_loginuid.so session required pam_systemd.so See Also systemd1, systemd-logind.service8, logind.conf5, loginctl1, pam.conf5, pam.d5, pam8, pam_loginuid8, systemd.scope5, systemd.slice5, systemd.service5 systemd-229/man/resolved.conf.xml000066400000000000000000000256571265713322000171440ustar00rootroot00000000000000 resolved.conf systemd Developer Tom Gundersen teg@jklm.no resolved.conf 5 resolved.conf resolved.conf.d Network Name Resolution configuration files /etc/systemd/resolved.conf /etc/systemd/resolved.conf.d/*.conf /run/systemd/resolved.conf.d/*.conf /usr/lib/systemd/resolved.conf.d/*.conf Description These configuration files control local DNS and LLMNR name resolution. Options The following options are available in the [Resolve] section: DNS= A space-separated list of IPv4 and IPv6 addresses to use as system DNS servers. DNS requests are sent to one of the listed DNS servers in parallel to suitable per-link DNS servers acquired from systemd-networkd.service8 or set at runtime by external applications. For compatibility reasons, if this setting is not specified, the DNS servers listed in /etc/resolv.conf are used instead, if that file exists and any servers are configured in it. This setting defaults to the empty list. FallbackDNS= A space-separated list of IPv4 and IPv6 addresses to use as the fallback DNS servers. Any per-link DNS servers obtained from systemd-networkd.service8 take precedence over this setting, as do any servers set via DNS= above or /etc/resolv.conf. This setting is hence only used if no other DNS server information is known. If this option is not given, a compiled-in list of DNS servers is used instead. Domains= A space-separated list of domains. These domains are used as search suffixes when resolving single-label host names (domain names which contain no dot), in order to qualify them into fully-qualified domain names (FQDNs). Search domains are strictly processed in the order they are specified, until the name with the suffix appended is found. For compatibility reasons, if this setting is not specified, the search domains listed in /etc/resolv.conf are used instead, if that file exists and any domains are configured in it. This setting defaults to the empty list. Specified domain names may optionally be prefixed with ~. In this case they do not define a search path, but preferably direct DNS queries for the indicated domains to the DNS servers configured with the system DNS= setting (see above), in case additional, suitable per-link DNS servers are known. If no per-link DNS servers are known using the ~ syntax has no effect. Use the construct ~. (which is composed of ~ to indicate a routing domain and . to indicate the DNS root domain that is the implied suffix of all DNS domains) to use the system DNS server defined with DNS= preferably for all domains. LLMNR= Takes a boolean argument or resolve. Controls Link-Local Multicast Name Resolution support (RFC 4794) on the local host. If true, enables full LLMNR responder and resolver support. If false, disables both. If set to resolve, only resolution support is enabled, but responding is disabled. Note that systemd-networkd.service8 also maintains per-link LLMNR settings. LLMNR will be enabled on a link only if the per-link and the global setting is on. DNSSEC= Takes a boolean argument or allow-downgrade. If true all DNS lookups are DNSSEC-validated locally (excluding LLMNR and Multicast DNS). If the response to a lookup request is detected to be invalid a lookup failure is returned to applications. Note that this mode requires a DNS server that supports DNSSEC. If the DNS server does not properly support DNSSEC all validations will fail. If set to allow-downgrade DNSSEC validation is attempted, but if the server does not support DNSSEC properly, DNSSEC mode is automatically disabled. Note that this mode makes DNSSEC validation vulnerable to "downgrade" attacks, where an attacker might be able to trigger a downgrade to non-DNSSEC mode by synthesizing a DNS response that suggests DNSSEC was not supported. If set to false, DNS lookups are not DNSSEC validated. Note that DNSSEC validation requires retrieval of additional DNS data, and thus results in a small DNS look-up time penalty. DNSSEC requires knowledge of "trust anchors" to prove data integrity. The trust anchor for the Internet root domain is built into the resolver, additional trust anchors may be defined with dnssec-trust-anchors.d5. Trust anchors may change at regular intervals, and old trust anchors may be revoked. In such a case DNSSEC validation is not possible until new trust anchors are configured locally or the resolver software package is updated with the new root trust anchor. In effect, when the built-in trust anchor is revoked and DNSSEC= is true, all further lookups will fail, as it cannot be proved anymore whether lookups are correctly signed, or validly unsigned. If DNSSEC= is set to allow-downgrade the resolver will automatically turn off DNSSEC validation in such a case. Client programs looking up DNS data will be informed whether lookups could be verified using DNSSEC, or whether the returned data could not be verified (either because the data was found unsigned in the DNS, or the DNS server did not support DNSSEC or no appropriate trust anchors were known). In the latter case it is assumed that client programs employ a secondary scheme to validate the returned DNS data, should this be required. It is recommended to set DNSSEC= to true on systems where it is known that the DNS server supports DNSSEC correctly, and where software or trust anchor updates happen regularly. On other systems it is recommended to set DNSSEC= to allow-downgrade. In addition to this global DNSSEC setting systemd-networkd.service8 also maintains per-link DNSSEC settings. For system DNS servers (see above), only the global DNSSEC setting is in effect. For per-link DNS servers the per-link setting is in effect, unless it is unset in which case the global setting is used instead. Site-private DNS zones generally conflict with DNSSEC operation, unless a negative (if the private zone is not signed) or positive (if the private zone is signed) trust anchor is configured for them. If allow-downgrade mode is selected, it is attempted to detect site-private DNS zones using top-level domains (TLDs) that are not known by the DNS root server. This logic does not work in all private zone setups. Defaults to off. See Also systemd1, systemd-resolved.service8, systemd-networkd.service8, dnssec-trust-anchors.d5, resolv.conf4 systemd-229/man/runlevel.xml000066400000000000000000000133311265713322000162130ustar00rootroot00000000000000 runlevel systemd Developer Lennart Poettering lennart@poettering.net runlevel 8 runlevel Print previous and current SysV runlevel runlevel options Overview "Runlevels" are an obsolete way to start and stop groups of services used in SysV init. systemd provides a compatibility layer that maps runlevels to targets, and associated binaries like runlevel. Nevertheless, only one runlevel can be "active" at a given time, while systemd can activate multiple targets concurrently, so the mapping to runlevels is confusing and only approximate. Runlevels should not be used in new code, and are mostly useful as a shorthand way to refer the matching systemd targets in kernel boot parameters. Mapping between runlevels and systemd targets Runlevel Target 0 poweroff.target 1 rescue.target 2, 3, 4 multi-user.target 5 graphical.target 6 reboot.target
Description runlevel prints the previous and current SysV runlevel if they are known. The two runlevel characters are separated by a single space character. If a runlevel cannot be determined, N is printed instead. If neither can be determined, the word "unknown" is printed. Unless overridden in the environment, this will check the utmp database for recent runlevel changes. Options The following option is understood: Exit status If one or both runlevels could be determined, 0 is returned, a non-zero failure code otherwise. Environment $RUNLEVEL If $RUNLEVEL is set, runlevel will print this value as current runlevel and ignore utmp. $PREVLEVEL If $PREVLEVEL is set, runlevel will print this value as previous runlevel and ignore utmp. Files /var/run/utmp The utmp database runlevel reads the previous and current runlevel from. See Also systemd1, systemd.target5, systemctl1
systemd-229/man/sd-bus-errors.xml000066400000000000000000000350141265713322000170700ustar00rootroot00000000000000 sd-bus-errors systemd Developer Lennart Poettering lennart@poettering.net sd-bus-errors 3 sd-bus-errors SD_BUS_ERROR_FAILED SD_BUS_ERROR_NO_MEMORY SD_BUS_ERROR_SERVICE_UNKNOWN SD_BUS_ERROR_NAME_HAS_NO_OWNER SD_BUS_ERROR_NO_REPLY SD_BUS_ERROR_IO_ERROR SD_BUS_ERROR_BAD_ADDRESS SD_BUS_ERROR_NOT_SUPPORTED SD_BUS_ERROR_LIMITS_EXCEEDED SD_BUS_ERROR_ACCESS_DENIED SD_BUS_ERROR_AUTH_FAILED SD_BUS_ERROR_NO_SERVER SD_BUS_ERROR_TIMEOUT SD_BUS_ERROR_NO_NETWORK SD_BUS_ERROR_ADDRESS_IN_USE SD_BUS_ERROR_DISCONNECTED SD_BUS_ERROR_INVALID_ARGS SD_BUS_ERROR_FILE_NOT_FOUND SD_BUS_ERROR_FILE_EXISTS SD_BUS_ERROR_UNKNOWN_METHOD SD_BUS_ERROR_UNKNOWN_OBJECT SD_BUS_ERROR_UNKNOWN_INTERFACE SD_BUS_ERROR_UNKNOWN_PROPERTY SD_BUS_ERROR_PROPERTY_READ_ONLY SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN SD_BUS_ERROR_INVALID_SIGNATURE SD_BUS_ERROR_INCONSISTENT_MESSAGE SD_BUS_ERROR_MATCH_RULE_NOT_FOUND SD_BUS_ERROR_MATCH_RULE_INVALID SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED Standard D-Bus error names #include <systemd/sd-bus.h> #define SD_BUS_ERROR_FAILED "org.freedesktop.DBus.Error.Failed" #define SD_BUS_ERROR_NO_MEMORY "org.freedesktop.DBus.Error.NoMemory" #define SD_BUS_ERROR_SERVICE_UNKNOWN "org.freedesktop.DBus.Error.ServiceUnknown" #define SD_BUS_ERROR_NAME_HAS_NO_OWNER "org.freedesktop.DBus.Error.NameHasNoOwner" #define SD_BUS_ERROR_NO_REPLY "org.freedesktop.DBus.Error.NoReply" #define SD_BUS_ERROR_IO_ERROR "org.freedesktop.DBus.Error.IOError" #define SD_BUS_ERROR_BAD_ADDRESS "org.freedesktop.DBus.Error.BadAddress" #define SD_BUS_ERROR_NOT_SUPPORTED "org.freedesktop.DBus.Error.NotSupported" #define SD_BUS_ERROR_LIMITS_EXCEEDED "org.freedesktop.DBus.Error.LimitsExceeded" #define SD_BUS_ERROR_ACCESS_DENIED "org.freedesktop.DBus.Error.AccessDenied" #define SD_BUS_ERROR_AUTH_FAILED "org.freedesktop.DBus.Error.AuthFailed" #define SD_BUS_ERROR_NO_SERVER "org.freedesktop.DBus.Error.NoServer" #define SD_BUS_ERROR_TIMEOUT "org.freedesktop.DBus.Error.Timeout" #define SD_BUS_ERROR_NO_NETWORK "org.freedesktop.DBus.Error.NoNetwork" #define SD_BUS_ERROR_ADDRESS_IN_USE "org.freedesktop.DBus.Error.AddressInUse" #define SD_BUS_ERROR_DISCONNECTED "org.freedesktop.DBus.Error.Disconnected" #define SD_BUS_ERROR_INVALID_ARGS "org.freedesktop.DBus.Error.InvalidArgs" #define SD_BUS_ERROR_FILE_NOT_FOUND "org.freedesktop.DBus.Error.FileNotFound" #define SD_BUS_ERROR_FILE_EXISTS "org.freedesktop.DBus.Error.FileExists" #define SD_BUS_ERROR_UNKNOWN_METHOD "org.freedesktop.DBus.Error.UnknownMethod" #define SD_BUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject" #define SD_BUS_ERROR_UNKNOWN_INTERFACE "org.freedesktop.DBus.Error.UnknownInterface" #define SD_BUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty" #define SD_BUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly" #define SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN "org.freedesktop.DBus.Error.UnixProcessIdUnknown" #define SD_BUS_ERROR_INVALID_SIGNATURE "org.freedesktop.DBus.Error.InvalidSignature" #define SD_BUS_ERROR_INCONSISTENT_MESSAGE "org.freedesktop.DBus.Error.InconsistentMessage" #define SD_BUS_ERROR_MATCH_RULE_NOT_FOUND "org.freedesktop.DBus.Error.MatchRuleNotFound" #define SD_BUS_ERROR_MATCH_RULE_INVALID "org.freedesktop.DBus.Error.MatchRuleInvalid" #define SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED \ "org.freedesktop.DBus.Error.InteractiveAuthorizationRequired" Description In addition to the error names user programs define, D-Bus knows a number of generic, standardized error names that are listed below. In addition to this list, in sd-bus, the special error namespace System.Error. is used to map arbitrary Linux system errors (as defined by errno3) to D-Bus errors and back. For example, the error EUCLEAN is mapped to System.Error.EUCLEAN and back. SD_BUS_ERROR_FAILED A generic error indication. See the error message for further details. This error name should be avoided, in favor of a more expressive error name. SD_BUS_ERROR_NO_MEMORY A memory allocation failed, and the requested operation could not be completed. SD_BUS_ERROR_SERVICE_UNKNOWN The contacted bus service is unknown and cannot be activated. SD_BUS_ERROR_NAME_HAS_NO_OWNER The specified bus service name currently has no owner. SD_BUS_ERROR_NO_REPLY A message did not receive a reply. This error is usually generated after a timeout. SD_BUS_ERROR_IO_ERROR Generic input/output error, for example when accessing a socket or other I/O context. SD_BUS_ERROR_BAD_ADDRESS The specified D-Bus bus address string is malformed. SD_BUS_ERROR_NOT_SUPPORTED The requested operation is not supported on the local system. SD_BUS_ERROR_LIMITS_EXCEEDED Some limited resource has been exhausted. SD_BUS_ERROR_ACCESS_DENIED Access to a resource has been denied due to security restrictions. SD_BUS_ERROR_AUTH_FAILED Authentication did not complete successfully. SD_BUS_ERROR_NO_SERVER Unable to connect to the specified server. SD_BUS_ERROR_TIMEOUT An operation timed out. Note that method calls which timeout generate a SD_BUS_ERROR_NO_REPLY. SD_BUS_ERROR_NO_NETWORK No network available to execute requested network operation on. SD_BUS_ERROR_ADDRESS_IN_USE The specified network address is already being listened on. SD_BUS_ERROR_DISCONNECTED The connection has been terminated. SD_BUS_ERROR_INVALID_ARGS One or more invalid arguments have been passed. SD_BUS_ERROR_FILE_NOT_FOUND The requested file could not be found. SD_BUS_ERROR_FILE_EXISTS The requested file already exists. SD_BUS_ERROR_UNKNOWN_METHOD The requested method does not exist in the selected interface. SD_BUS_ERROR_UNKNOWN_OBJECT The requested object does not exist in the selected service. SD_BUS_ERROR_UNKNOWN_INTERFACE The requested interface does not exist on the selected object. SD_BUS_ERROR_UNKNOWN_PROPERTY The requested property does not exist in the selected interface. SD_BUS_ERROR_PROPERTY_READ_ONLY A write operation was requested on a read-only property. SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN The requested PID is not known. SD_BUS_ERROR_INVALID_SIGNATURE The specified message signature is not valid. SD_BUS_ERROR_INCONSISTENT_MESSAGE The passed message does not validate correctly. SD_BUS_ERROR_MATCH_RULE_NOT_FOUND The specified match rule does not exist. SD_BUS_ERROR_MATCH_RULE_INVALID The specified match rule is invalid. SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED Access to the requested operation is not permitted. However, it might be available after interactive authentication. This is usually returned by method calls supporting a framework for additional interactive authorization, when interactive authorization was not enabled with the sd_bus_message_set_allow_interactive_authorization3 for the method call message. Notes The various error definitions described here are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_error3, sd_bus_message_set_allow_interactive_authorization3, errno3, strerror3 systemd-229/man/sd-bus.xml000066400000000000000000000141761265713322000155640ustar00rootroot00000000000000 sd-bus systemd Documentation Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd-bus 3 sd-bus A lightweight D-Bus and kdbus client library #include <systemd/sd-bus.h> pkg-config --cflags --libs libsystemd Description sd-bus.h provides an implementation of a D-Bus client. It can interoperate both with the traditional dbus-daemon1, and with kdbus. See for more information about the big picture. Interfaces described here have not been declared stable yet, and are not accessible from libsystemd.so. This documentation is provided in hope it might be useful for developers, without any guarantees of availability or stability. See sd_bus_default3, sd_bus_new3, sd_bus_request_name3, sd_bus_start3, sd_bus_message_append3, sd_bus_message_append_basic3, sd_bus_message_append_array3, sd_bus_message_append_string_memfd3, sd_bus_message_append_strv3, sd_bus_message_can_send3, sd_bus_message_get_cookie3, sd_bus_message_get_monotonic_usec3, sd_bus_send3, sd_bus_set_address3, sd_bus_set_description3, sd_bus_set_prepare3, sd_bus_creds_get_pid3, sd_bus_creds_new_from_pid3, sd_bus_get_name_creds3, sd_bus_get_owner_creds3, sd_bus_negotiate_fds3, sd_bus_path_encode3, sd-bus-errors3, sd_bus_error3, sd_bus_error_add_map3, sd_bus_set_allow_interactive_authorization3 for more information about the functions available. See Also systemd1, sd-event3, dbus-daemon1, dbus-send1, gdbus systemd-229/man/sd-daemon.xml000066400000000000000000000135741265713322000162370ustar00rootroot00000000000000 sd-daemon systemd Developer Lennart Poettering lennart@poettering.net sd-daemon 3 sd-daemon SD_EMERG SD_ALERT SD_CRIT SD_ERR SD_WARNING SD_NOTICE SD_INFO SD_DEBUG APIs for new-style daemons #include <systemd/sd-daemon.h> pkg-config --cflags --libs libsystemd Description sd-daemon.h provides APIs for new-style daemons, as implemented by the systemd1 service manager. See sd_listen_fds3, sd_notify3, sd_booted3, sd_is_fifo3, sd_watchdog_enabled3 for more information about the functions implemented. In addition to these functions, a couple of logging prefixes are defined as macros: #define SD_EMERG "<0>" /* system is unusable */ #define SD_ALERT "<1>" /* action must be taken immediately */ #define SD_CRIT "<2>" /* critical conditions */ #define SD_ERR "<3>" /* error conditions */ #define SD_WARNING "<4>" /* warning conditions */ #define SD_NOTICE "<5>" /* normal but significant condition */ #define SD_INFO "<6>" /* informational */ #define SD_DEBUG "<7>" /* debug-level messages */ These prefixes are intended to be used in conjunction with stderr-based logging as implemented by systemd. If a systemd service definition file is configured with StandardError=journal, StandardError=syslog or StandardError=kmsg, these prefixes can be used to encode a log level in lines printed. This is similar to the kernel printk()-style logging. See klogctl2 for more information. The log levels are identical to syslog3's log level system. To use these prefixes simply prefix every line with one of these strings. A line that is not prefixed will be logged at the default log level SD_INFO. Hello World A daemon may log with the log level NOTICE by issuing this call: fprintf(stderr, SD_NOTICE "Hello World!\n"); See Also systemd1, sd_listen_fds3, sd_notify3, sd_booted3, sd_is_fifo3, sd_watchdog_enabled3, daemon7, systemd.service5, systemd.socket5, fprintf3, pkg-config1 systemd-229/man/sd-event.xml000066400000000000000000000261631265713322000161130ustar00rootroot00000000000000 sd-event systemd Developer Lennart Poettering lennart@poettering.net sd-event 3 sd-event A generic event loop implementation #include <systemd/sd-event.h> pkg-config --cflags --libs libsystemd Description sd-event.h provides a generic event loop implementation, based on Linux epoll7. See sd_event_new3, sd_event_run3, sd_event_add_io3, sd_event_add_time3, sd_event_add_signal3, sd_event_add_child3, sd_event_add_defer3, sd_event_source_unref3, sd_event_source_set_priority3, sd_event_source_set_enabled3, sd_event_source_set_userdata3, sd_event_source_get_event3, sd_event_source_get_pending3, sd_event_source_set_description3, sd_event_source_set_prepare3, sd_event_wait3, sd_event_get_fd3, sd_event_set_watchdog3, sd_event_exit3, sd_event_now3 for more information about the functions available. The event loop design is targeted on running a separate instance of the event loop in each thread; it has no concept of distributing events from a single event loop instance onto multiple worker threads. Dispatching events is strictly ordered and subject to configurable priorities. In each event loop iteration a single event source is dispatched. Each time an event source is dispatched the kernel is polled for new events, before the next event source is dispatched. The event loop is designed to honour priorities and provide fairness within each priority. It is not designed to provide optimal throughput, as this contradicts these goals due the limitations of the underlying epoll7 primitives. The event loop implementation provides the following features: I/O event sources, based on epoll7's file descriptor watching, including edge triggered events (EPOLLET). See sd_event_add_io3. Timer event sources, based on timerfd_create2, supporting the CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_BOOTIME clocks, as well as the CLOCK_REALTIME_ALARM and CLOCK_BOOTTIME_ALARM clocks that can resume the system from suspend. When creating timer events a required accuracy parameter may be specified which allows coalescing of timer events to minimize power consumption. See sd_event_add_time3. UNIX process signal events, based on signalfd2, including full support for real-time signals, and queued parameters. See sd_event_add_signal3. Child process state change events, based on waitid2. See sd_event_add_child3. Static event sources, of three types: defer, post and exit, for invoking calls in each event loop, after other event sources or at event loop termination. See sd_event_add_defer3. Event sources may be assigned a 64bit priority value, that controls the order in which event sources are dispatched if multiple are pending simultaneously. See sd_event_source_set_priority3. The event loop may automatically send watchdog notification messages to the service manager. See sd_event_set_watchdog3. The event loop may be integrated into foreign event loops, such as the GLib one. See sd_event_get_fd3 for an example. See Also systemd1, sd_event_new3, sd_event_run3, sd_event_add_io3, sd_event_add_time3, sd_event_add_signal3, sd_event_add_child3, sd_event_add_defer3, sd_event_source_unref3, sd_event_source_set_priority3, sd_event_source_set_enabled3, sd_event_source_set_userdata3, sd_event_source_get_event3, sd_event_source_get_pending3, sd_event_source_set_description3, sd_event_source_set_prepare3, sd_event_wait3, sd_event_get_fd3, sd_event_set_watchdog3, sd_event_exit3, sd_event_now3, epoll7, timerfd_create2, signalfd2, waitid2 systemd-229/man/sd-id128.xml000066400000000000000000000147361265713322000156240ustar00rootroot00000000000000 sd-id128 systemd Developer Lennart Poettering lennart@poettering.net sd-id128 3 sd-id128 sd_id128_t SD_ID128_MAKE SD_ID128_CONST_STR SD_ID128_FORMAT_STR SD_ID128_FORMAT_VAL sd_id128_equal APIs for processing 128-bit IDs #include <systemd/sd-id128.h> pkg-config --cflags --libs libsystemd Description sd-id128.h provides APIs to process and generate 128-bit ID values. The 128-bit ID values processed and generated by these APIs are a generalization of OSF UUIDs as defined by RFC 4122 but use a simpler string format. These functions impose no structure on the used IDs, much unlike OSF UUIDs or Microsoft GUIDs, but are fully compatible with those types of IDs. See sd_id128_to_string3, sd_id128_randomize3 and sd_id128_get_machine3 for more information about the implemented functions. A 128-bit ID is implemented as the following union type: typedef union sd_id128 { uint8_t bytes[16]; uint64_t qwords[2]; } sd_id128_t; This union type allows accessing the 128-bit ID as 16 separate bytes or two 64-bit words. It is generally safer to access the ID components by their 8-bit array to avoid endianness issues. This union is intended to be passed call-by-value (as opposed to call-by-reference) and may be directly manipulated by clients. A couple of macros are defined to denote and decode 128-bit IDs: SD_ID128_MAKE() may be used to denote a constant 128-bit ID in source code. A commonly used idiom is to assign a name to a 128-bit ID using this macro: #define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) SD_ID128_CONST_STR() may be used to convert constant 128-bit IDs into constant strings for output. The following example code will output the string "fc2e22bc6ee647b6b90729ab34a250b1": int main(int argc, char *argv[]) { puts(SD_ID128_CONST_STR(SD_MESSAGE_COREDUMP)); } SD_ID128_FORMAT_STR and SD_ID128_FORMAT_VAL() may be used to format a 128-bit ID in a printf3 format string, as shown in the following example: int main(int argc, char *argv[]) { sd_id128_t id; id = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07); printf("The ID encoded in this C file is " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(id)); return 0; } Use sd_id128_equal() to compare two 128-bit IDs: int main(int argc, char *argv[]) { sd_id128_t a, b, c; a = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07); b = SD_ID128_MAKE(f2,28,88,9c,5f,09,44,15,9d,d7,04,77,58,cb,e7,3e); c = a; assert(sd_id128_equal(a, c)); assert(!sd_id128_equal(a, b)); return 0; } Note that new, randomized IDs may be generated with journalctl1's option. See Also systemd1, sd_id128_to_string3, sd_id128_randomize3, sd_id128_get_machine3, printf3, journalctl1, sd-journal7, pkg-config1, machine-id5 systemd-229/man/sd-journal.xml000066400000000000000000000163151265713322000164420ustar00rootroot00000000000000 sd-journal systemd Developer Lennart Poettering lennart@poettering.net sd-journal 3 sd-journal APIs for submitting and querying log entries to and from the journal #include <systemd/sd-journal.h> pkg-config --cflags --libs libsystemd Description sd-journal.h provides APIs to submit and query log entries. The APIs exposed act both as client for the systemd-journald.service8 journal service and as parser for the journal files on disk. See sd_journal_print3, sd_journal_stream_fd3, sd_journal_open3, sd_journal_next3, sd_journal_get_realtime_usec3, sd_journal_add_match3, sd_journal_seek_head3, sd_journal_query_enumerate3, sd_journal_enumerate_fields3, sd_journal_get_cursor3, sd_journal_get_cutoff_realtime_usec3, sd_journal_get_cutoff_monotonic_usec3, sd_journal_get_usage3, sd_journal_get_catalog3, sd_journal_get_fd3, sd_journal_has_runtime_files3 and sd_journal_has_persistent_files3 for more information about the functions implemented. Command line access for submitting entries to the journal is available with the systemd-cat1 tool. Command line access for querying entries from the journal is available with the journalctl1 tool. See Also systemd1, sd_journal_print3, sd_journal_stream_fd3, sd_journal_open3, sd_journal_next3, sd_journal_get_data3, sd_journal_get_realtime_usec3, sd_journal_add_match3, sd_journal_seek_head3, sd_journal_query_enumerate3, sd_journal_enumerate_fields3, sd_journal_get_cursor3, sd_journal_get_cutoff_realtime_usec3, sd_journal_get_cutoff_monotonic_usec3, sd_journal_get_usage3, sd_journal_get_fd3, sd_journal_query_unique3, sd_journal_get_catalog3, sd_journal_has_runtime_files3, sd_journal_has_persistent_files3, journalctl1, sd-id1283, pkg-config1 systemd-229/man/sd-login.xml000066400000000000000000000131371265713322000160770ustar00rootroot00000000000000 sd-login systemd Developer Lennart Poettering lennart@poettering.net sd-login 3 sd-login APIs for tracking logins #include <systemd/sd-login.h> pkg-config --cflags --libs libsystemd Description sd-login.h provides APIs to introspect and monitor seat, login session and user status information on the local system. See Multi-Seat on Linux for an introduction into multi-seat support on Linux, the background for this set of APIs. Note that these APIs only allow purely passive access and monitoring of seats, sessions and users. To actively make changes to the seat configuration, terminate login sessions, or switch session on a seat you need to utilize the D-Bus API of systemd-logind, instead. These functions synchronously access data in /proc, /sys/fs/cgroup and /run. All of these are virtual file systems, hence the runtime cost of the accesses is relatively cheap. It is possible (and often a very good choice) to mix calls to the synchronous interface of sd-login.h with the asynchronous D-Bus interface of systemd-logind. However, if this is done you need to think a bit about possible races since the stream of events from D-Bus and from sd-login.h interfaces such as the login monitor are asynchronous and not ordered against each other. If the functions return string arrays, these are generally NULL terminated and need to be freed by the caller with the libc free3 call after use, including the strings referenced therein. Similarly, individual strings returned need to be freed, as well. As a special exception, instead of an empty string array NULL may be returned, which should be treated equivalent to an empty string array. See sd_pid_get_session3, sd_uid_get_state3, sd_session_is_active3, sd_seat_get_active3, sd_get_seats3, sd_login_monitor_new3 for more information about the functions implemented. See Also systemd1, sd_pid_get_session3, sd_uid_get_state3, sd_session_is_active3, sd_seat_get_active3, sd_get_seats3, sd_login_monitor_new3, sd-daemon3, pkg-config1 systemd-229/man/sd_booted.xml000066400000000000000000000055701265713322000163270ustar00rootroot00000000000000 sd_booted systemd Developer Lennart Poettering lennart@poettering.net sd_booted 3 sd_booted Test whether the system is running the systemd init system #include <systemd/sd-daemon.h> int sd_booted void Description sd_booted() checks whether the system was booted up using the systemd init system. Return Value On failure, this call returns a negative errno-style error code. If the system was booted up with systemd as init system, this call returns a positive return value, zero otherwise. Notes Internally, this function checks whether the directory /run/systemd/system/ exists. A simple check like this can also be implemented trivially in shell or any other language. See Also systemd1, sd-daemon3 systemd-229/man/sd_bus_creds_get_pid.xml000066400000000000000000000613541265713322000205210ustar00rootroot00000000000000 sd_bus_creds_get_pid systemd A monkey with a typewriter Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_bus_creds_get_pid 3 sd_bus_creds_get_pid sd_bus_creds_get_ppid sd_bus_creds_get_tid sd_bus_creds_get_uid sd_bus_creds_get_euid sd_bus_creds_get_suid sd_bus_creds_get_fsuid sd_bus_creds_get_gid sd_bus_creds_get_egid sd_bus_creds_get_sgid sd_bus_creds_get_fsgid sd_bus_creds_get_supplementary_gids sd_bus_creds_get_comm sd_bus_creds_get_tid_comm sd_bus_creds_get_exe sd_bus_creds_get_cmdline sd_bus_creds_get_cgroup sd_bus_creds_get_unit sd_bus_creds_get_slice sd_bus_creds_get_user_unit sd_bus_creds_get_user_slice sd_bus_creds_get_session sd_bus_creds_get_owner_uid sd_bus_creds_has_effective_cap sd_bus_creds_has_permitted_cap sd_bus_creds_has_inheritable_cap sd_bus_creds_has_bounding_cap sd_bus_creds_get_selinux_context sd_bus_creds_get_audit_session_id sd_bus_creds_get_audit_login_uid sd_bus_creds_get_tty sd_bus_creds_get_unique_name sd_bus_creds_get_well_known_names sd_bus_creds_get_description Retrieve fields from a credentials object #include <systemd/sd-bus.h> int sd_bus_creds_get_pid sd_bus_creds *c pid_t *pid int sd_bus_creds_get_ppid sd_bus_creds *c pid_t *ppid int sd_bus_creds_get_tid sd_bus_creds *c pid_t *tid int sd_bus_creds_get_uid sd_bus_creds *c uid_t *uid int sd_bus_creds_get_euid sd_bus_creds *c uid_t *uid int sd_bus_creds_get_suid sd_bus_creds *c uid_t *uid int sd_bus_creds_get_fsuid sd_bus_creds *c uid_t *uid int sd_bus_creds_get_gid sd_bus_creds *c gid_t *gid int sd_bus_creds_get_egid sd_bus_creds *c gid_t *gid int sd_bus_creds_get_sgid sd_bus_creds *c gid_t *gid int sd_bus_creds_get_fsgid sd_bus_creds *c gid_t *gid int sd_bus_creds_get_supplementary_gids sd_bus_creds *c const gid_t **gids int sd_bus_creds_get_comm sd_bus_creds *c const char **comm int sd_bus_creds_get_tid_comm sd_bus_creds *c const char **comm int sd_bus_creds_get_exe sd_bus_creds *c const char **exe int sd_bus_creds_get_cmdline sd_bus_creds *c char ***cmdline int sd_bus_creds_get_cgroup sd_bus_creds *c const char **cgroup int sd_bus_creds_get_unit sd_bus_creds *c const char **unit int sd_bus_creds_get_slice sd_bus_creds *c const char **slice int sd_bus_creds_get_user_unit sd_bus_creds *c const char **unit int sd_bus_creds_get_user_slice sd_bus_creds *c const char **slice int sd_bus_creds_get_session sd_bus_creds *c const char **slice int sd_bus_creds_get_owner_uid sd_bus_creds *c uid_t *uid int sd_bus_creds_has_effective_cap sd_bus_creds *c int capability int sd_bus_creds_has_permitted_cap sd_bus_creds *c int capability int sd_bus_creds_has_inheritable_cap sd_bus_creds *c int capability int sd_bus_creds_has_bounding_cap sd_bus_creds *c int capability int sd_bus_creds_get_selinux_context sd_bus_creds *c const char **context int sd_bus_creds_get_audit_session_id sd_bus_creds *c uint32_t *sessionid int sd_bus_creds_get_audit_login_uid sd_bus_creds *c uid_t *loginuid int sd_bus_creds_get_tty sd_bus_creds *c const char **tty int sd_bus_creds_get_unique_name sd_bus_creds *c const char **name int sd_bus_creds_get_well_known_names sd_bus_creds *c char ***name int sd_bus_creds_get_description sd_bus_creds *c const char **name Description These functions return credential information from an sd_bus_creds object. Credential objects may be created with sd_bus_creds_new_from_pid3, in which case they describe the credentials of the process identified by the specified PID, with sd_bus_get_name_creds3, in which case they describe the credentials of a bus peer identified by the specified bus name, with sd_bus_get_owner_creds3, in which case they describe the credentials of the creator of a bus, or with sd_bus_message_get_creds3, in which case they describe the credentials of the sender of the message. Not all credential fields are part of every sd_bus_creds object. Use sd_bus_creds_get_mask3 to determine the mask of fields available. sd_bus_creds_get_pid() will retrieve the PID (process identifier). Similarly, sd_bus_creds_get_ppid() will retrieve the parent PID. Note that PID 1 has no parent process, in which case -ENXIO is returned. sd_bus_creds_get_tid() will retrieve the TID (thread identifier). sd_bus_creds_get_uid() will retrieve the numeric UID (user identifier). Similarly, sd_bus_creds_get_euid() returns the effective UID, sd_bus_creds_get_suid() the saved UID and sd_bus_creds_get_fsuid() the file system UID. sd_bus_creds_get_gid() will retrieve the numeric GID (group identifier). Similarly, sd_bus_creds_get_egid() returns the effective GID, sd_bus_creds_get_sgid() the saved GID and sd_bus_creds_get_fsgid() the file system GID. sd_bus_creds_get_supplementary_gids() will retrieve the supplementary GIDs list. sd_bus_creds_get_comm() will retrieve the comm field (truncated name of the executable, as stored in /proc/pid/comm). sd_bus_creds_get_tid_comm() will retrieve the comm field of the thread (as stored in /proc/pid/task/tid/comm). sd_bus_creds_get_exe() will retrieve the path to the program executable (as stored in the /proc/pid/exe link, but with the (deleted) suffix removed). Note that kernel threads do not have an executable path, in which case -ENXIO is returned. sd_bus_creds_get_cmdline() will retrieve an array of command line arguments (as stored in /proc/pid/cmdline). Note that kernel threads do not have a command line, in which case -ENXIO is returned. sd_bus_creds_get_cgroup() will retrieve the cgroup path. See cgroups.txt. sd_bus_creds_get_unit() will retrieve the systemd unit name (in the system instance of systemd) that the process is a part of. See systemd.unit5. For processes that are not part of a unit, returns -ENXIO. sd_bus_creds_get_user_unit() will retrieve the systemd unit name (in the user instance of systemd) that the process is a part of. See systemd.unit5. For processes that are not part of a user unit, returns -ENXIO. sd_bus_creds_get_slice() will retrieve the systemd slice (a unit in the system instance of systemd) that the process is a part of. See systemd.slice5. Similarly, sd_bus_creds_get_user_slice() retrieves the systemd slice of the process, in the user instance of systemd. sd_bus_creds_get_session() will retrieve the identifier of the login session that the process is a part of. See systemd-logind.service8. For processes that are not part of a session, returns -ENXIO. sd_bus_creds_get_owner_uid() will retrieve the numeric UID (user identifier) of the user who owns the login session that the process is a part of. See systemd-logind.service8. For processes that are not part of a session, returns -ENXIO. sd_bus_creds_has_effective_cap() will check whether the capability specified by capability was set in the effective capabilities mask. A positive return value means that is was set, zero means that it was not set, and a negative return value indicates an error. See capabilities7 and Capabilities= and CapabilityBoundingSet= settings in systemd.exec5. sd_bus_creds_has_permitted_cap() is similar to sd_bus_creds_has_effective_cap(), but will check the permitted capabilities mask. sd_bus_creds_has_inheritable_cap() is similar to sd_bus_creds_has_effective_cap(), but will check the inheritable capabilities mask. sd_bus_creds_has_bounding_cap() is similar to sd_bus_creds_has_effective_cap(), but will check the bounding capabilities mask. sd_bus_creds_get_selinux_context() will retrieve the SELinux security context (label) of the process. sd_bus_creds_get_audit_session_id() will retrieve the audit session identifier of the process. Returns -ENXIO for processes that are not part of an audit session. sd_bus_creds_get_audit_login_uid() will retrieve the audit user login identifier (the identifier of the user who is "responsible" for the session). Returns -ENXIO for processes that are not part of an audit session. sd_bus_creds_get_tty() will retrieve the controlling TTY, without the prefixing "/dev/". Returns -ENXIO for processes that have no controlling TTY. sd_bus_creds_get_unique_name() will retrieve the D-Bus unique name. See The D-Bus specification. sd_bus_creds_get_well_known_names() will retrieve the set of D-Bus well-known names. See The D-Bus specification. sd_bus_creds_get_description() will retrieve a descriptive name of the bus connection of the peer. This name is useful to discern multiple bus connections by the same peer, and may be altered by the peer with the sd_bus_set_description3 call. All functions that take a const char** parameter will store the answer there as an address of a NUL-terminated string. It will be valid as long as c remains valid, and should not be freed or modified by the caller. All functions that take a char*** parameter will store the answer there as an address of an array of strings. Each individual string is NUL-terminated, and the array is NULL-terminated as a whole. It will be valid as long as c remains valid, and should not be freed or modified by the caller. Return Value On success, these calls return 0 or a positive integer. On failure, these calls return a negative errno-style error code. Errors Returned errors may indicate the following problems: -ENODATA The given field is not available in the credentials object c. -ENXIO The given field is not specified for the described process or peer. This will be returned by sd_bus_get_unit(), sd_bus_get_slice(), sd_bus_get_user_unit(), sd_bus_get_user_slice(), sd_bus_get_session(), and sd_bus_get_owner_uid() if the process is not part of a systemd system unit, systemd user unit, systemd slice, or logind session. It will also be returned by sd_bus_creds_get_exe() and sd_bus_creds_get_cmdline() for kernel threads (since these are not started from an executable binary, nor have a command line), and by sd_bus_creds_get_audit_session_id() and sd_bus_creds_get_audit_login_uid() when the process is not part of an audit session, and sd_bus_creds_get_tty() if the process has no controlling TTY. -EINVAL Specified pointer parameter is NULL. -ENOMEM Memory allocation failed. Notes sd_bus_creds_get_pid() and the other functions described here are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_creds_new_from_pid2, fork2, execve2, credentials7, free3, proc5, systemd.journal-fields7 systemd-229/man/sd_bus_creds_new_from_pid.xml000066400000000000000000000353421265713322000215540ustar00rootroot00000000000000 sd_bus_creds_new_from_pid systemd A monkey with a typewriter Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_bus_creds_new_from_pid 3 sd_bus_creds_new_from_pid sd_bus_creds_get_mask sd_bus_creds_get_augmented_mask sd_bus_creds_ref sd_bus_creds_unref sd_bus_creds_unrefp Retrieve credentials object for the specified PID #include <systemd/sd-bus.h> int sd_bus_creds_new_from_pid pid_t pid uint64_t creds_mask sd_bus_creds **ret uint64_t sd_bus_creds_get_mask const sd_bus_creds *c uint64_t sd_bus_creds_get_augmented_mask const sd_bus_creds *c sd_bus_creds *sd_bus_creds_ref sd_bus_creds *c sd_bus_creds *sd_bus_creds_unref sd_bus_creds *c void sd_bus_creds_unrefp sd_bus_creds **c SD_BUS_CREDS_PID, SD_BUS_CREDS_PPID, SD_BUS_CREDS_TID, SD_BUS_CREDS_UID, SD_BUS_CREDS_EUID, SD_BUS_CREDS_SUID, SD_BUS_CREDS_FSUID, SD_BUS_CREDS_GID, SD_BUS_CREDS_EGID, SD_BUS_CREDS_SGID, SD_BUS_CREDS_FSGID, SD_BUS_CREDS_SUPPLEMENTARY_GIDS, SD_BUS_CREDS_COMM, SD_BUS_CREDS_TID_COMM, SD_BUS_CREDS_EXE, SD_BUS_CREDS_CMDLINE, SD_BUS_CREDS_CGROUP, SD_BUS_CREDS_UNIT, SD_BUS_CREDS_SLICE, SD_BUS_CREDS_USER_UNIT, SD_BUS_CREDS_USER_SLICE, SD_BUS_CREDS_SESSION, SD_BUS_CREDS_OWNER_UID, SD_BUS_CREDS_EFFECTIVE_CAPS, SD_BUS_CREDS_PERMITTED_CAPS, SD_BUS_CREDS_INHERITABLE_CAPS, SD_BUS_CREDS_BOUNDING_CAPS, SD_BUS_CREDS_SELINUX_CONTEXT, SD_BUS_CREDS_AUDIT_SESSION_ID, SD_BUS_CREDS_AUDIT_LOGIN_UID, SD_BUS_CREDS_TTY, SD_BUS_CREDS_UNIQUE_NAME, SD_BUS_CREDS_WELL_KNOWN_NAMES, SD_BUS_CREDS_DESCRIPTION, SD_BUS_CREDS_AUGMENT, _SD_BUS_CREDS_ALL Description sd_bus_creds_new_from_pid() creates a new credentials object and fills it with information about the process pid. The pointer to this object will be stored in the ret pointer. Note that credential objects may also be created and retrieved via sd_bus_get_name_creds3, sd_bus_get_owner_creds3 and sd_bus_message_get_creds3. The information that will be stored is determined by creds_mask. It may contain a subset of ORed constants SD_BUS_CREDS_PID, SD_BUS_CREDS_PPID, SD_BUS_CREDS_TID, SD_BUS_CREDS_UID, SD_BUS_CREDS_EUID, SD_BUS_CREDS_SUID, SD_BUS_CREDS_FSUID, SD_BUS_CREDS_GID, SD_BUS_CREDS_EGID, SD_BUS_CREDS_SGID, SD_BUS_CREDS_FSGID, SD_BUS_CREDS_SUPPLEMENTARY_GIDS, SD_BUS_CREDS_COMM, SD_BUS_CREDS_TID_COMM, SD_BUS_CREDS_EXE, SD_BUS_CREDS_CMDLINE, SD_BUS_CREDS_CGROUP, SD_BUS_CREDS_UNIT, SD_BUS_CREDS_SLICE, SD_BUS_CREDS_USER_UNIT, SD_BUS_CREDS_USER_SLICE, SD_BUS_CREDS_SESSION, SD_BUS_CREDS_OWNER_UID, SD_BUS_CREDS_EFFECTIVE_CAPS, SD_BUS_CREDS_PERMITTED_CAPS, SD_BUS_CREDS_INHERITABLE_CAPS, SD_BUS_CREDS_BOUNDING_CAPS, SD_BUS_CREDS_SELINUX_CONTEXT, SD_BUS_CREDS_AUDIT_SESSION_ID, SD_BUS_CREDS_AUDIT_LOGIN_UID, SD_BUS_CREDS_TTY, SD_BUS_CREDS_UNIQUE_NAME, SD_BUS_CREDS_WELL_KNOWN_NAMES, and SD_BUS_CREDS_DESCRIPTION. Use the special value _SD_BUS_CREDS_ALL to request all supported fields. The SD_BUS_CREDS_AUGMENT constant may not be ORed into the mask for invocations of sd_bus_creds_new_from_pid(). Fields can be retrieved from the credentials object using sd_bus_creds_get_pid3 and other functions which correspond directly to the constants listed above. A mask of fields which were actually successfully retrieved can be retrieved with sd_bus_creds_get_mask(). If the credentials object was created with sd_bus_creds_new_from_pid(), this will be a subset of fields requested in creds_mask. Similar to sd_bus_creds_get_mask(), the function sd_bus_creds_get_augmented_mask() returns a bitmask of field constants. The mask indicates which credential fields have been retrieved in a non-atomic fashion. For credential objects created via sd_bus_creds_new_from_pid(), this mask will be identical to the mask returned by sd_bus_creds_get_mask(). However, for credential objects retrieved via sd_bus_get_name_creds(), this mask will be set for the credential fields that could not be determined atomically at peer connection time, and which were later added by reading augmenting credential data from /proc. Similarly, for credential objects retrieved via sd_bus_get_owner_creds(), the mask is set for the fields that could not be determined atomically at bus creation time, but have been augmented. Similarly, for credential objects retrieved via sd_bus_message_get_creds(), the mask is set for the fields that could not be determined atomically at message sending time, but have been augmented. The mask returned by sd_bus_creds_get_augmented_mask() is always a subset of (or identical to) the mask returned by sd_bus_creds_get_mask() for the same object. The latter call hence returns all credential fields available in the credential object, the former then marks the subset of those that have been augmented. Note that augmented fields are unsuitable for authorization decisions, as they may be retrieved at different times, thus being subject to races. Hence, augmented fields should be used exclusively for informational purposes. sd_bus_creds_ref() creates a new reference to the credentials object c. This object will not be destroyed until sd_bus_creds_unref() has been called as many times plus once more. Once the reference count has dropped to zero, c cannot be used anymore, so further calls to sd_bus_creds_ref(c) or sd_bus_creds_unref(c) are illegal. sd_bus_creds_unref() destroys a reference to c. sd_bus_creds_unrefp() is similar to sd_bus_creds_unref() but takes a pointer to a pointer to an sd_bus_creds object. This call is useful in conjunction with GCC's and LLVM's Clean-up Variable Attribute. Note that this function is defined as inline function. sd_bus_creds_ref(), sd_bus_creds_unref() and sd_bus_creds_unrefp() execute no operation if the passed in bus credentials object is NULL. Return Value On success, sd_bus_creds_new_from_pid() returns 0 or a positive integer. On failure, it returns a negative errno-style error code. sd_bus_creds_get_mask() returns the mask of successfully acquired fields. sd_bus_creds_get_augmented_mask() returns the mask of fields that have been augmented from data in /proc, and are thus not suitable for authorization decisions. sd_bus_creds_ref() always returns the argument. sd_bus_creds_unref() always returns NULL. Reference ownership Function sd_bus_creds_new_from_pid() creates a new object and the caller owns the sole reference. When not needed anymore, this reference should be destroyed with sd_bus_creds_unref3. Errors Returned errors may indicate the following problems: -ESRCH Specified pid could not be found. -EINVAL Specified parameter is invalid (NULL in case of output parameters). -ENOMEM Memory allocation failed. -EOPNOTSUPP One of the requested fields is unknown to the local system. Notes sd_bus_creds_new_from_pid() and the other calls described here are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_creds_get_pid3, sd_bus_get_name_creds3, sd_bus_get_owner_creds3, sd_bus_message_get_creds3 systemd-229/man/sd_bus_default.xml000066400000000000000000000322721265713322000173470ustar00rootroot00000000000000 sd_bus_default systemd A monkey with a typewriter Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_bus_default 3 sd_bus_default sd_bus_default_user sd_bus_default_system sd_bus_open sd_bus_open_user sd_bus_open_system sd_bus_open_system_remote sd_bus_open_system_machine Acquire a connection to a system or user bus #include <systemd/sd-bus.h> int sd_bus_default sd_bus **bus int sd_bus_default_user sd_bus **bus int sd_bus_default_system sd_bus **bus int sd_bus_open sd_bus **bus int sd_bus_open_user sd_bus **bus int sd_bus_open_system sd_bus **bus int sd_bus_open_system_remote sd_bus **bus const char *host int sd_bus_open_system_machine sd_bus **bus const char *machine Description sd_bus_default() acquires a bus connection object to the user bus when invoked in user context, or to the system bus otherwise. The connection object is associated with the calling thread. Each time the function is invoked from the same thread, the same object is returned, but its reference count is increased by one, as long as at least one reference is kept. When the last reference to the connection is dropped (using the sd_bus_unref3 call), the connection is terminated. Note that the connection is not automatically terminated when the associated thread ends. It is important to drop the last reference to the bus connection explicitly before the thread ends, as otherwise, the connection will leak. Also, queued but unread or unwritten messages keep the bus referenced, see below. sd_bus_default_user() returns a user bus connection object associated with the calling thread. sd_bus_default_system() is similar, but connects to the system bus. Note that sd_bus_default() is identical to these two calls, depending on the execution context. sd_bus_open() creates a new, independent bus connection to the user bus when invoked in user context, or the system bus otherwise. sd_bus_open_user() is similar, but connects only to the user bus. sd_bus_open_system() does the same, but connects to the system bus. In contrast to sd_bus_default(), sd_bus_default_user(), and sd_bus_default_system(), these calls return new, independent connection objects that are not associated with the invoking thread and are not shared between multiple invocations. It is recommended to share connections per thread to efficiently make use the available resources. Thus, it is recommended to use sd_bus_default(), sd_bus_default_user() and sd_bus_default_system() to connect to the user or system buses. If the $DBUS_SESSION_BUS_ADDRESS environment variable is set (cf. environ7), it will be used as the address of the user bus. This variable can contain multiple addresses separated by ;. If this variable is not set, a suitable default for the default user D-Bus instance will be used. If the $DBUS_SYSTEM_BUS_ADDRESS environment variable is set, it will be used as the address of the system bus. This variable uses the same syntax as $DBUS_SESSION_BUS_ADDRESS. If this variable is not set, a suitable default for the default system D-Bus instance will be used. sd_bus_open_system_remote() connects to the system bus on the specified host using ssh1. host consists of an optional user name followed by the @ symbol, and the hostname. sd_bus_open_system_machine() connects to the system bus in the specified machine, where machine is the name of a local container. See machinectl1 for more information about the "machine" concept. Note that connections into local containers are only available to privileged processes at this time. These calls allocate a bus connection object and initiate the connection to a well-known bus of some form. An alternative to using these high-level calls is to create an unconnected bus object with sd_bus_new3 and to connect it with sd_bus_start3. Reference ownership The functions sd_bus_open(), sd_bus_open_user(), sd_bus_open_system(), sd_bus_open_system_remote(), and sd_bus_open_system_machine() return a new connection object and the caller owns the sole reference. When not needed anymore, this reference should be destroyed with sd_bus_unref3. The functions sd_bus_default(), sd_bus_default_user() and sd_bus_default_system() do not necessarily create a new object, but increase the connection reference of an existing connection object by one. Use sd_bus_unref3 to drop the reference. Queued but unwritten/unread messages also keep a reference to their bus connection object. For this reason, even if an application dropped all references to a bus connection, it might not get destroyed right away. Until all incoming queued messages are read, and until all outgoing unwritten messages are written, the bus object will stay alive. sd_bus_flush() may be used to write all outgoing queued messages so they drop their references. To flush the unread incoming messages, use sd_bus_close(), which will also close the bus connection. When using the default bus logic, it is a good idea to first invoke sd_bus_flush() followed by sd_bus_close() when a thread or process terminates, and thus its bus connection object should be freed. The life cycle of the default bus connection should be the responsibility of the code that creates/owns the thread the default bus connection object is associated with. Library code should neither call sd_bus_flush() nor sd_bus_close() on default bus objects unless it does so in its own private, self-allocated thread. Library code should not use the default bus object in other threads unless it is clear that the program using it will life cycle the bus connection object and flush and close it before exiting from the thread. In libraries where it is not clear that the calling program will life cycle the bus connection object, it is hence recommended to use sd_bus_open_system() instead of sd_bus_default_system() and related calls. Return Value On success, these calls return 0 or a positive integer. On failure, these calls return a negative errno-style error code. Errors Returned errors may indicate the following problems: -EINVAL The specified parameters are invalid. -ENOMEM Memory allocation failed. -ESOCKTNOSUPPORT The protocol version required to connect to the selected bus is not supported. In addition, any further connection-related errors may be by returned. See sd_bus_send3. Notes sd_bus_open_user() and the other functions described here are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_new3, sd_bus_ref3, sd_bus_unref3, ssh1, systemd-machined.service8, machinectl1 systemd-229/man/sd_bus_error.xml000066400000000000000000000424231265713322000170530ustar00rootroot00000000000000 sd_bus_error systemd A monkey with a typewriter Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_bus_error 3 sd_bus_error SD_BUS_ERROR_MAKE_CONST SD_BUS_ERROR_NULL sd_bus_error_free sd_bus_error_set sd_bus_error_setf sd_bus_error_set_const sd_bus_error_set_errno sd_bus_error_set_errnof sd_bus_error_set_errnofv sd_bus_error_get_errno sd_bus_error_copy sd_bus_error_is_set sd_bus_error_has_name sd-bus error handling #include <systemd/sd-bus.h> typedef struct { const char *name; const char *message; ... } sd_bus_error; SD_BUS_ERROR_MAKE_CONST(name, message) SD_BUS_ERROR_NULL void sd_bus_error_free sd_bus_error *e int sd_bus_error_set sd_bus_error *e const char *name const char *message int sd_bus_error_setf sd_bus_error *e const char *name const char *format ... int sd_bus_error_set_const sd_bus_error *e const char *name const char *message int sd_bus_error_set_errno sd_bus_error *e int error int sd_bus_error_set_errnof sd_bus_error *e int error const char *format ... int sd_bus_error_set_errnofv sd_bus_error *e int error const char *format va_list ap int sd_bus_error_get_errno const sd_bus_error *e int sd_bus_error_copy sd_bus_error *dst const sd_bus_error *e int sd_bus_error_is_set const sd_bus_error *e int sd_bus_error_has_name const sd_bus_error *e const char *name Description The sd_bus_error structure carries information about a D-Bus error condition. The functions described below may be used to set and query fields in this structure. The name field contains a short identifier of an error. It should follow the rules for error names described in the D-Bus specification, subsection Valid Names. A number of common, standardized error names are described in sd-bus-errors3, but additional domain-specific errors may be defined by applications. The message field usually contains a human-readable string describing the details, but might be NULL. An unset sd_bus_error structure should have both fields initialized to NULL. Set an error structure to SD_BUS_ERROR_NULL in order to reset both fields to NULL. When no longer necessary, resources held by the sd_bus_errorstructure should be destroyed with sd_bus_error_free(). sd_bus_error_set() sets an error structure to the specified name and message strings. The strings will be copied into internal, newly allocated memory. It is essential to free the error structure again when it is not required anymore (see above). The function will return an errno-like negative value (see errno3) determined from the specified error name. Various well-known D-Bus errors are converted to well-known errno counterparts, and the other ones to -EIO. See sd-bus-errors3 for a list of well-known error names. Additional error mappings may be defined with sd_bus_error_add_map3. If e is NULL, no error structure is initialized, but the error is still converted into an errno-style error. If name is NULL, it is assumed that no error occurred, and 0 is returned. This means that this function may be conveniently used in a return statement. If message is NULL, no message is set. This call can fail if no memory may be allocated for the name and message strings, in which case an SD_BUS_ERROR_NO_MEMORY error might be set instead and -ENOMEM be returned. Do not use this call on error structures that are already initialized. If you intend to reuse an error structure, free the old data stored in it with sd_bus_error_free() first. sd_bus_error_setf() is similar to sd_bus_error_set(), but takes a printf3 format string and corresponding arguments to generate the message field. sd_bus_error_set_const() is similar to sd_bus_error_set(), but the string parameters are not copied internally, and must hence remain constant and valid for the lifetime of e. Use this call to avoid memory allocations when setting error structures. Since this call does not allocate memory, it will not fail with an out-of-memory condition as sd_bus_error_set() can, as described above. Alternatively, the SD_BUS_ERROR_MAKE_CONST() macro may be used to generate a literal, constant bus error structure on-the-fly. sd_bus_error_set_errno() will set name from an errno-like value that is converted to a D-Bus error. strerror_r3 will be used to set message. Well-known D-Bus error names will be used for name if applicable, otherwise a name in the System.Error. namespace will be generated. The sign of the specified error number is ignored. The absolute value is used implicitly. The call always returns a negative value, for convenient usage in return statements. This call might fail due to lack of memory, in which case an SD_BUS_ERROR_NO_MEMORY error is set instead, and -ENOMEM is returned. sd_bus_error_set_errnof() is similar to sd_bus_error_set_errno(), but in addition to error, takes a printf3 format string and corresponding arguments. The message field will be generated from format and the arguments. sd_bus_error_set_errnofv() is similar to sd_bus_error_set_errnof(), but takes the format string parameters as va_arg3 parameter list. sd_bus_error_get_errno() converts the name field of an error structure to an errno-like (positive) value using the same rules as sd_bus_error_set(). If e is NULL, 0 will be returned. sd_bus_error_copy() will initialize dst using the values in e. If the strings in e were set using sd_bus_set_error_const(), they will be shared. Otherwise, they will be copied. Returns a converted errno-like, negative error code. sd_bus_error_is_set() will return a non-zero value if e is non-NULL and an error has been set, false otherwise. sd_bus_error_has_name() will return a non-zero value if e is non-NULL and an error with the same name has been set, false otherwise. sd_bus_error_free() will destroy resources held by e. The parameter itself will not be deallocated, and must be free3d by the caller if necessary. The function may also be called safely on unset errors (error structures with both fields set to NULL), in which case it performs no operation. This call will reset the error structure after freeing the data, so that all fields are set to NULL. The structure may be reused afterwards. Return Value The functions sd_bus_error_set(), sd_bus_error_setf(), and sd_bus_error_set_const(), when successful, return the negative errno value corresponding to the name parameter. The functions sd_bus_error_set_errno(), sd_bus_error_set_errnof() and sd_bus_error_set_errnofv(), when successful, return the negative value of the error parameter. If an error occurs, one of the negative error values listed below will be returned. sd_bus_error_get_errno() returns false when e is NULL, and a positive errno value mapped from e->name otherwise. sd_bus_error_copy() returns 0 or a positive integer on success, and a negative error value converted from the error name otherwise. sd_bus_error_is_set() returns a non-zero value when e and the name field are non-NULL, zero otherwise. sd_bus_error_has_name() returns a non-zero value when e is non-NULL and the name field is equal to name, zero otherwise. Reference ownership sd_bus_error is not reference counted. Users should destroy resources held by it by calling sd_bus_error_free(). Usually, error structures are allocated on the stack or passed in as function parameters, but they may also be allocated dynamically, in which case it is the duty of the caller to free3 the memory held by the structure itself after freeing its contents with sd_bus_error_free(). Errors Returned errors may indicate the following problems: -EINVAL Error was already set in sd_bus_error structure when one the error-setting functions was called. -ENOMEM Memory allocation failed. Notes sd_bus_set_error() and other functions described here are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd-bus-errors3, sd_bus_error_add_map3, errno3, strerror_r3 systemd-229/man/sd_bus_error_add_map.xml000066400000000000000000000143111265713322000205130ustar00rootroot00000000000000 sd_bus_error_add_map systemd Developer Lennart Poettering lennart@poettering.net sd_bus_error_add_map 3 sd_bus_error_add_map sd_bus_error_map SD_BUS_ERROR_MAP SD_BUS_ERROR_END Additional sd-dbus error mappings #include <systemd/sd-bus.h> typedef struct { const char *name; int code; ... } sd_bus_error_map; SD_BUS_ERROR_MAP(name, code) SD_BUS_ERROR_MAP_END int sd_bus_error_add_map const sd_bus_map *map Description The sd_bus_error_add_map() call may be used to register additional mappings for converting D-Bus errors to Linux errno-style errors. The mappings defined with this call are consulted by calls such as sd_bus_error_set3 or sd_bus_error_get_errno3. By default, a number of generic, standardized mappings are known, as documented in sd-bus-errors3. Use this call to add further, application-specific mappings. The function takes a pointer to an array of sd_bus_error_map structures. A reference to the specified array is added to the lookup tables for error mappings. Note that the structure is not copied, and that it is hence essential that the array stays available and constant during the entire remaining runtime of the process. The mapping array should be put together with a series of SD_BUS_ERROR_MAP() macro invocations that take a literal name string and a (positive) errno-style error number. The last entry of the array should be an invocation of the SD_BUS_ERROR_MAP_END macro. The array should not be put together without use of these two macros. Note that the call is idempotent: it is safe to invoke it multiple times with the parameter, which will only add the passed mapping array once. Note that the memory allocated by this call is not intended to be freed during the lifetime of the process. It should not be freed explicitly. Return Value sd_bus_error_add_map() returns a positive value when the new array was added to the lookup tables. It returns zero when the same array was already added before. On error, a negative errno-style error code is returned. See below for known error codes. Errors Returned errors may indicate the following problems: -EINVAL The specified mapping array is invalid. -ENOMEM Memory allocation failed. Notes The various error definitions described here are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_error3, sd-bus-errors3, errno3, strerror_r3 systemd-229/man/sd_bus_message_append.xml000066400000000000000000000227441265713322000207010ustar00rootroot00000000000000 sd_bus_message_append systemd A monkey with a typewriter Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_bus_message_append 3 sd_bus_message_append Attach fields to a D-Bus message based on a type string #include <systemd/sd-bus.h> int sd_bus_message_append sd_bus_message *m const char *types ... Description The sd_bus_message_append() function appends a sequence of fields to the D-Bus message object m. The type string types describes the types of the field arguments that follow. For each type specified in the type string, one or more arguments need to be specified, in the same order as declared in the type string. The type string is composed of the elements shown in the table below. It contains zero or more single "complete types". Each complete type may be one of the basic types or a fully described container type. A container type may be a structure with the contained types, a variant, an array with its element type, or a dictionary entry with the contained types. The type string is NUL-terminated. In case of a basic type, one argument of the corresponding type is expected. A structure is denoted by a sequence of complete types between ( and ). This sequence cannot be empty — it must contain at least one type. Arguments corresponding to this nested sequence follow the same rules as if they were not nested. A variant is denoted by v. Corresponding arguments must begin with a type string denoting a complete type, and following that, arguments corresponding to the specified type. An array is denoted by a followed by a complete type. Corresponding arguments must begin with the number of entries in the array, followed by the entries themselves, matching the element type of the array. A dictionary is an array of dictionary entries, denoted by a followed by a pair of complete types between { and }. The first of those types must be a basic type. Corresponding arguments must begin with the number of dictionary entries, followed by a pair of values for each entry matching the element type of the dictionary entries. For further details on the D-Bus type system, please consult the D-Bus Specification. Item type specifiers a SD_BUS_TYPE_ARRAY array determined by array type and size int, followed by array contents v SD_BUS_TYPE_VARIANT variant determined by the type argument signature string, followed by variant contents ( SD_BUS_TYPE_STRUCT_BEGIN array start determined by the nested types structure contents ) SD_BUS_TYPE_STRUCT_END array end { SD_BUS_TYPE_DICT_ENTRY_BEGIN dictionary entry start determined by the nested types dictionary contents } SD_BUS_TYPE_DICT_ENTRY_END dictionary entry end
Types String Grammar types ::= complete_type* complete_type ::= basic_type | variant | structure | array | dictionary basic_type ::= "y" | "n" | "q" | "u" | "i" | "x" | "t" | "d" | "b" | "h" | "s" | "o" | "g" variant ::= "v" structure ::= "(" complete_type+ ")" array ::= "a" complete_type dictionary ::= "a" "{" basic_type complete_type "}" Examples Append a single basic type (the string a string): sd_bus_message *m; ... sd_bus_message_append(m, "s", "a string"); Append all types of integers: uint8_t y = 1; int16_t n = 2; uint16_t q = 3; int32_t i = 4; uint32_t u = 5; int32_t x = 6; uint32_t t = 7; double d = 8.0; sd_bus_message_append(m, "ynqiuxtd", y, n, q, i, u, x, t, d); Append a structure composed of a string and a D-Bus path: sd_bus_message_append(m, "(so)", "a string", "/a/path"); Append an array of UNIX file descriptors: sd_bus_message_append(m, "ah", 3, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO); Append a variant, with the real type "g" (signature), and value "sdbusisgood": sd_bus_message_append(m, "v", "g", "sdbusisgood"); Append a dictionary containing the mapping {1=>"a", 2=>"b", 3=>""}: sd_bus_message_append(m, "a{is}", 3, 1, "a", 2, "b", 3, NULL); Return Value On success, this call returns 0 or a positive integer. On failure, this call returns a negative errno-style error code. Notes sd_bus_open_user() and other functions described here are available as a shared library, which can be compiled and linked to with the libsystemd-bus pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_message_append_basic3, sd_bus_message_append_array3
systemd-229/man/sd_bus_message_append_array.xml000066400000000000000000000233171265713322000220740ustar00rootroot00000000000000 sd_bus_message_append_array systemd A monkey with a typewriter Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_bus_message_append_array 3 sd_bus_message_append_array sd_bus_message_append_array_memfd sd_bus_message_append_array_iovec sd_bus_message_append_array_space Append an array of fields to a D-Bus message #include <systemd/sd-bus.h> int sd_bus_message_append_array sd_bus_message *m char type char void *ptr size_t size int sd_bus_message_append_array_memfd sd_bus_message *m char type int memfd uint64_t offset uint64_t size int sd_bus_message_append_array_iovec sd_bus_message *m char type const struct iovec *iov unsigned n int sd_bus_message_append_array_space char type size_t size void **ptr Description The sd_bus_message_append_array() function appends an array to a D-Bus message m. A container will be opened, the array contents appended, and the container closed. The parameter type determines how the pointer p is interpreted. type must be one of the "trivial" types y, n, q, i, u, x, t, d (but not b), as defined by the Basic Types section of the D-Bus specification, and listed in sd_bus_message_append_basic3. Pointer p must point to an array of size size bytes containing items of the respective type. Size size must be a multiple of the size of the type type. As a special case, p may be NULL, if size is 0. The memory pointed to by p is copied into the memory area containing the message and stays in possession of the caller. The caller may hence freely change the data after this call without affecting the message the array was appended to. The sd_bus_message_append_array_memfd() function appends an array of a trivial type to message m, similar to sd_bus_message_append_array(). The contents of the memory file descriptor memfd starting at the specified offset and of the specified size is used as the contents of the array. The offset and size must be a multiple of the size of the type type. However, as a special exception, if the offset is specified as zero and the size specified as UINT64_MAX the full memory file descriptor contents is used. The memory file descriptor is sealed by this call if it has not been sealed yet, and cannot be modified after this call. See memfd_create2 for details about memory file descriptors. Appending arrays with memory file descriptors enables efficient zero-copy data transfer, as the memory file descriptor may be passed as-is to the destination, without copying the memory in it to the destination process. Not all protocol transports support passing memory file descriptors between participants, in which case this call will automatically fall back to copying. Also, as memory file descriptor passing is inefficient for smaller amounts of data, copying might still be enforced even where memory file descriptor passing is supported. The sd_bus_message_append_array_iovec() function appends an array of a trivial type to the message m, similar to sd_bus_message_append_array(). Contents of the I/O vector array iov are used as the contents of the array. The total size of iov payload (the sum of iov_len fields) must be a multiple of the size of the type type. The iov argument must point to n I/O vector structures. Each structure may have the iov_base field set, in which case the memory pointed to will be copied into the message, or unset (set to zero), in which case a block of zeros of length iov_len bytes will be inserted. The memory pointed at by iov may be changed after this call. The sd_bus_message_append_array_space() function appends space for an array of a trivial type to message m. It behaves the same as sd_bus_message_append_array(), but instead of copying items to the message, it returns a pointer to the destination area to the caller in pointer p. The caller should subsequently write the array contents to this memory. Modifications to the memory pointed to should only occur until the next operation on the bus message is invoked. Most importantly, the memory should not be altered anymore when another field has been added to the message or the message has been sealed. Return Value On success, these calls return 0 or a positive integer. On failure, they return a negative errno-style error code. Notes sd_bus_append_array() and other functions described here are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_message_append3, sd_bus_message_append_basic3, memfd_create2, The D-Bus specification systemd-229/man/sd_bus_message_append_basic.xml000066400000000000000000000232001265713322000220260ustar00rootroot00000000000000 sd_bus_message_append_basic systemd A monkey with a typewriter Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_bus_message_append_basic 3 sd_bus_message_append_basic Attach a single field to a message #include <systemd/sd-bus.h> int sd_bus_message_append_basic sd_bus_message *m char type const void *p Description sd_bus_message_append_basic() appends a single field to the message m. The parameter type determines how the pointer p is interpreted. type must be one of the basic types as defined by the Basic Types section of the D-Bus specification, and listed in the table below. Item type specifiers Specifier Constant Description Size Expected C Type y SD_BUS_TYPE_BYTE unsigned integer 1 byte uint8_t b SD_BUS_TYPE_BOOLEAN boolean 4 bytes int n SD_BUS_TYPE_INT16 signed integer 2 bytes int16_t q SD_BUS_TYPE_UINT16 unsigned integer 2 bytes uint16_t i SD_BUS_TYPE_INT32 signed integer 4 bytes int32_t u SD_BUS_TYPE_UINT32 unsigned integer 4 bytes uint32_t x SD_BUS_TYPE_INT64 signed integer 8 bytes int64_t t SD_BUS_TYPE_UINT64 unsigned integer 8 bytes uint64_t d SD_BUS_TYPE_DOUBLE floating-point 8 bytes double s SD_BUS_TYPE_STRING Unicode string variable char[] o SD_BUS_TYPE_OBJECT_PATH object path variable char[] g SD_BUS_TYPE_SIGNATURE signature variable char[] h SD_BUS_TYPE_UNIX_FD UNIX file descriptor 4 bytes int
The value of the parameter is copied into a memory area held by the message object, stays in the possession of the caller and may hence be freely changed after this call without affecting the bus message it has been added to. If type is h (UNIX file descriptor), the descriptor is duplicated by this call and the passed descriptor stays in possession of the caller. For types s, o, and g, the parameter p is interpreted as a pointer to a NUL-terminated character sequence. As a special case, a NULL pointer is interpreted as an empty string. The string should be valid Unicode string encoded as UTF-8. In case of the two latter types, the additional requirements for a D-Bus object path or type signature should be satisfied. Those requirements should be verified by the recipient of the message.
Return Value On success, this call returns 0 or a positive integer. On failure, it returns a negative errno-style error code. Errors Returned errors may indicate the following problems: -EINVAL Specified parameter is invalid. -EPERM Message has been sealed. -ESTALE Message is in invalid state. -ENXIO Message cannot be appended to. -ENOMEM Memory allocation failed. Notes The sd_bus_append_basic() function described here is available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_message_append3, The D-Bus specification
systemd-229/man/sd_bus_message_append_string_memfd.xml000066400000000000000000000137401265713322000234330ustar00rootroot00000000000000 sd_bus_message_append_string_memfd systemd A monkey with a typewriter Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_bus_message_append_string_memfd 3 sd_bus_message_append_string_memfd sd_bus_message_append_string_iovec sd_bus_message_append_string_space Attach a string to a message #include <systemd/sd-bus.h> int sd_bus_message_append_string_memfd sd_bus_message *m int memfd int sd_bus_message_append_string_iovec sd_bus_message *m const struct iovec *iov unsigned n int sd_bus_message_append_string_space sd_bus_message *m size_t size char **s Description The functions sd_bus_message_append_string_memfd and sd_bus_message_append_string_iovec can be used to append a single string (item of type s) to message m. In case of sd_bus_message_append_string_memfd, the contents of memfd are the string. They must satisfy the same constraints as described for the s type in sd_bus_message_append_basic3. In case of sd_bus_message_append_string_iovec, the payload of iov is the string. It must satisfy the same constraints as described for the s type in sd_bus_message_append_basic3. The iov argument must point to n struct iovec structures. Each structure may have the iov_base field set, in which case the memory pointed to will be copied into the message, or unset, in which case a block of spaces (ASCII 32) of length iov_len will be inserted. The memory pointed at by iov may be changed after this call. The sd_bus_message_append_string_space function appends space for a string to message m. It behaves similar to sd_bus_message_append_basic with type s, but instead of copying a string into the message, it returns a pointer to the destination area to the caller in pointer p. Space for the string of length size plus the terminating NUL is allocated. Return Value On success, those calls return 0 or a positive integer. On failure, they returns a negative errno-style error code. Notes The functions described here are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_message_append_basic3, The D-Bus specification systemd-229/man/sd_bus_message_append_strv.xml000066400000000000000000000104041265713322000217450ustar00rootroot00000000000000 sd_bus_message_append_strv systemd A monkey with a typewriter Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_bus_message_append_strv 3 sd_bus_message_append_strv Attach an array of strings to a message #include <systemd/sd-bus.h> int sd_bus_message_append_strv sd_bus_message *m char **l Description The sd_bus_message_append function can be used to append an array of strings to message m. The parameter l shall point to a NULL-terminated array of pointers to NUL-terminated strings. Each string must satisfy the same constraints as described for the s type in sd_bus_message_append_basic3. The memory pointed at by p and the contents of the strings themselves are copied into the memory area containing the message and may be changed after this call. Note that the signature of l parameter is to be treated as const char *const *, and the contents will not be modified. Return Value On success, this call returns 0 or a positive integer. On failure, a negative errno-style error code is returned. Notes The sd_bus_append_append_strv() function described here is available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_message_append3, sd_bus_message_append_array3, The D-Bus specification systemd-229/man/sd_bus_message_get_cookie.xml000066400000000000000000000117011265713322000215310ustar00rootroot00000000000000 sd_bus_message_get_cookie systemd Developer Lennart Poettering lennart@poettering.net sd_bus_message_get_cookie 3 sd_bus_message_get_cookie sd_bus_message_get_reply_cookie Returns the transaction cookie of a message #include <systemd/sd-bus.h> int sd_bus_message_get_cookie sd_bus_message *message uint64_t *cookie int sd_bus_message_get_reply_cookie sd_bus_message *message uint64_t *cookie Description sd_bus_message_get_cookie() returns the transaction cookie of a message. The cookie uniquely identifies a message within each bus peer, but is not globally unique. It is assigned when a message is sent. sd_bus_message_get_reply_cookie() returns the transaction cookie of the message the specified message is a response to. When a reply message is generated for a method call message, its cookie is copied over into this field. Note that while every message that is transferred is identified by a cookie, only response messages carry a reply cookie field. Both functions take a message object as first parameter and a place to store the 64-bit cookie in. Return Value On success, these calls return 0 or a positive integer. On failure, these calls return a negative errno-style error code. On success, the cookie/reply cookie is returned in the specified 64-bit unsigned integer variable. Errors Returned errors may indicate the following problems: -EINVAL A specified parameter is invalid. -ENODATA No cookie has been assigned to this message. This either indicates that the message has not been sent yet and hence has no cookie assigned, or that the message is not a method response message and hence carries a reply cookie field. Notes The sd_bus_message_get_cookie() and sd_bus_message_get_reply_cookie() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_new3 systemd-229/man/sd_bus_message_get_monotonic_usec.xml000066400000000000000000000160321265713322000233060ustar00rootroot00000000000000 sd_bus_message_get_monotonic_usec systemd Developer Lennart Poettering lennart@poettering.net sd_bus_message_get_monotonic_usec 3 sd_bus_message_get_monotonic_usec sd_bus_message_get_realtime_usec sd_bus_message_get_seqnum Retrieve the sender timestamps and sequence number of a message #include <systemd/sd-bus.h> int sd_bus_message_get_monotonic_usec sd_bus_message *message uint64_t *usec int sd_bus_message_get_realtime_usec sd_bus_message *message uint64_t *usec int sd_bus_message_get_seqnum sd_bus_message *message uint64_t *seqnum Description sd_bus_message_get_monotonic_usec() returns the monotonic timestamp of the time the message was sent. This value is in microseconds since the CLOCK_MONOTONIC epoch, see clock_gettime2 for details. Similarly, sd_bus_message_get_realtime_usec() returns the realtime (wallclock) timestamp of the time the message was sent. This value is in microseconds since Jan 1st, 1970, i.e. in the CLOCK_REALTIME clock. sd_bus_message_get_seqnum() returns the kernel-assigned sequence number of the message. The kernel assigns a global, monotonically increasing sequence number to all messages transmitted on the local system, at the time the message was sent. This sequence number is useful for determining message send order, even across different buses of the local system. The sequence number combined with the boot ID of the system (as returned by sd_id128_get_boot3) is a suitable globally unique identifier for bus messages. Note that the sending order and receiving order of messages might differ, in particular for broadcast messages. This means that the sequence number and the timestamps of messages a client reads are not necessarily monotonically increasing. These timestamps and the sequence number are attached to each message by the kernel and cannot be manipulated by the sender. Note that these timestamps are only available on some bus transports, and only after support for them has been negotiated with the sd_bus_negotiate_timestamp3 call. Return Value On success, these calls return 0 or a positive integer. On failure, these calls return a negative errno-style error code. On success, the timestamp or sequence number is returned in the specified 64-bit unsigned integer variable. Errors Returned errors may indicate the following problems: -EINVAL A specified parameter is invalid. -ENODATA No timestamp or sequence number information is attached to the passed message. This error is returned if the underlying transport does not support timestamping or assigning of sequence numbers, or if this feature has not been negotiated with sd_bus_negotiate_timestamp3. Notes The sd_bus_message_get_monotonic_usec(), sd_bus_message_get_realtime_usec(), and sd_bus_message_get_seqnum() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_new3, sd_bus_negotiate_timestamp3, clock_gettime2, sd_id128_get_boot3 systemd-229/man/sd_bus_negotiate_fds.xml000066400000000000000000000215731265713322000205400ustar00rootroot00000000000000 sd_bus_negotiate_fds systemd Developer Lennart Poettering lennart@poettering.net sd_bus_negotiate_fds 3 sd_bus_negotiate_fds sd_bus_negotiate_timestamp sd_bus_negotiate_creds Control feature negotiation on bus connections #include <systemd/sd-bus.h> int sd_bus_negotiate_fds sd_bus *bus int b int sd_bus_negotiate_timestamp sd_bus *bus int b int sd_bus_negotiate_creds sd_bus *bus int b uint64_t mask Description sd_bus_negotiate_fds() controls whether file descriptor passing shall be negotiated for the specified bus connection. It takes a bus object and a boolean, which, when true, enables file descriptor passing, and, when false, disables it. Note that not all transports and servers support file descriptor passing. In particular, networked transports generally do not support file descriptor passing. To find out whether file descriptor passing is available after negotiation, use sd_bus_can_send3 and pass SD_BUS_TYPE_UNIX_FD. Note that file descriptor passing is always enabled for both sending and receiving or for neither, but never only in one direction. By default, file descriptor passing is negotiated for all connections. Note that when bus activation is used, it is highly recommended to set the setting in the .busname unit file to the same setting as negotiated by the program ultimately activated. By default, file descriptor passing is enabled for both. sd_bus_negotiate_timestamps() controls whether implicit sender timestamps shall be attached automatically to all incoming messages. Takes a bus object and a boolean, which, when true, enables timestamping, and, when false, disables it. Use sd_bus_message_get_monotonic_usec3, sd_bus_message_get_realtime_usec3, sd_bus_message_get_seqnum3 to query the timestamps of incoming messages. If negotiation is disabled or not supported, these calls will fail with -ENODATA. Note that not all transports support timestamping of messages. Specifically, timestamping is only available on the kdbus transport, but not on dbus1. The timestamping is applied by the kernel and cannot be manipulated by userspace. By default, message timestamping is not negotiated for connections. sd_bus_negotiate_creds() controls whether and which implicit sender credentials shall be attached automatically to all incoming messages. Takes a bus object and a boolean indicating whether to enable or disable the credential parts encoded in the bit mask value argument. Note that not all transports support attaching sender credentials to messages, or do not support all types of sender credential parameters, or might suppress them under certain circumstances for individual messages. Specifically, implicit sender credentials on messages are only fully supported on kdbus transports, and dbus1 only supports SD_BUS_CREDS_UNIQUE_NAME. The sender credentials are attached by the kernel and cannot be manipulated by userspace, and are thus suitable for authorization decisions. By default, only SD_BUS_CREDS_WELL_KNOWN_NAMES and SD_BUS_CREDS_UNIQUE_NAME are enabled. In fact, these two credential fields are always sent along and cannot be turned off. The sd_bus_negotiate_fds() function may be called only before the connection has been started with sd_bus_start3. Both sd_bus_negotiate_timestamp() and sd_bus_negotiate_creds() may also be called after a connection has been set up. Note that, when operating on a connection that is shared between multiple components of the same program (for example via sd_bus_default3), it is highly recommended to only enable additional per message metadata fields, but never disable them again, in order not to disable functionality needed by other components. Return Value On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style error code. Errors Returned errors may indicate the following problems: -EPERM The bus connection has already been started. Notes sd_bus_negotiate_fds() and the other functions described here are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_start3, sd_bus_message_can_send3, sd_bus_message_get_monotonic_usec3, sd_bus_message_get_realtime_usec3, sd_bus_message_get_seqnum3, sd_bus_message_get_creds3, systemd.busname5 systemd-229/man/sd_bus_new.xml000066400000000000000000000160541265713322000165140ustar00rootroot00000000000000 sd_bus_new systemd A monkey with a typewriter Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_bus_new 3 sd_bus_new sd_bus_ref sd_bus_unref sd_bus_unrefp Create a new bus object and create or destroy references to it #include <systemd/sd-bus.h> int sd_bus_new sd_bus **bus sd_bus *sd_bus_ref sd_bus *bus sd_bus *sd_bus_unref sd_bus *bus void sd_bus_unrefp sd_bus **bus Description sd_bus_new() creates a new bus object. This object is reference-counted, and will be destroyed when all references are gone. Initially, the caller of this function owns the sole reference and the bus object will not be connected to any bus. To connect it to a bus, make sure to set an address with sd_bus_set_address3 or a related call, and then start the connection with sd_bus_start3. In most cases, it is a better idea to invoke sd_bus_default_user3, sd_bus_default_system3 or related calls instead of the more low-level sd_bus_new() and sd_bus_start(). The higher-level calls not only allocate a bus object but also start the connection to a well-known bus in a single function invocation. sd_bus_ref() increases the reference counter of bus by one. sd_bus_unref() decreases the reference counter of bus by one. Once the reference count has dropped to zero, bus is destroyed and cannot be used anymore, so further calls to sd_bus_ref() or sd_bus_unref() are illegal. sd_bus_unrefp() is similar to sd_bus_unref() but takes a pointer to a pointer to an sd_bus object. This call is useful in conjunction with GCC's and LLVM's Clean-up Variable Attribute. Note that this function is defined as inline function. Use a declaration like the following, in order to allocate a bus object that is freed automatically as the code block is left: { __attribute__((cleanup(sd_bus_unrefp)) sd_bus *bus = NULL; int r; … r = sd_bus_default(&bus); if (r < 0) fprintf(stderr, "Failed to allocate bus: %s\n", strerror(-r)); … } sd_bus_ref(), sd_bus_unref() and sd_bus_unrefp() execute no operation if the passed in bus object is NULL. Return Value On success, sd_bus_new() returns 0 or a positive integer. On failure, it returns a negative errno-style error code. sd_bus_ref() always returns the argument. sd_bus_unref() always returns NULL. Errors Returned errors may indicate the following problems: -ENOMEM Memory allocation failed. Notes sd_bus_new() and other functions described here are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_default_user3, sd_bus_default_system3, sd_bus_open_user3, sd_bus_open_system3 systemd-229/man/sd_bus_path_encode.xml000066400000000000000000000200221265713322000201620ustar00rootroot00000000000000 sd_bus_path_encode systemd A monkey with a typewriter Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_bus_path_encode 3 sd_bus_path_encode sd_bus_path_encode_many sd_bus_path_decode sd_bus_path_decode_many Convert an external identifier into an object path and back #include <systemd/sd-bus.h> int sd_bus_path_encode const char *prefix const char *external_id char **ret_path int sd_bus_path_encode_many char **out const char *path_template ... int sd_bus_path_decode const char *path const char *prefix char **ret_external_id int sd_bus_path_decode_many const char *path const char *path_template ... Description sd_bus_path_encode() and sd_bus_path_decode() convert external identifier strings into object paths and back. These functions are useful to map application-specific string identifiers of any kind into bus object paths in a simple, reversible and safe way. sd_bus_path_encode() takes a bus path prefix and an external identifier string as arguments, plus a place to store the returned bus path string. The bus path prefix must be a valid bus path, starting with a slash /, and not ending in one. The external identifier string may be in any format, may be the empty string, and has no restrictions on the charset — however, it must always be NUL-terminated. The returned string will be the concatenation of the bus path prefix plus an escaped version of the external identifier string. This operation may be reversed with sd_bus_decode(). It is recommended to only use external identifiers that generally require little escaping to be turned into valid bus path identifiers (for example, by sticking to a 7-bit ASCII character set), in order to ensure the resulting bus path is still short and easily processed. sd_bus_path_decode() reverses the operation of sd_bus_path_encode() and thus regenerates an external identifier string from a bus path. It takes a bus path and a prefix string, plus a place to store the returned external identifier string. If the bus path does not start with the specified prefix, 0 is returned and the returned string is set to NULL. Otherwise, the string following the prefix is unescaped and returned in the external identifier string. The escaping used will replace all characters which are invalid in a bus object path by _, followed by a hexadecimal value. As a special case, the empty string will be replaced by a lone _. sd_bus_path_encode_many() works like its counterpart sd_bus_path_encode(), but takes a path template as argument and encodes multiple labels according to its embedded directives. For each % character found in the template, the caller must provide a string via varargs, which will be encoded and embedded at the position of the % character. Any other character in the template is copied verbatim into the encoded path. sd_bus_path_decode_many() does the reverse of sd_bus_path_encode_many(). It decodes the passed object path according to the given path template. For each % character in the template, the caller must provide an output storage (char **) via varargs. The decoded label will be stored there. Each % character will only match the current label. It will never match across labels. Furthermore, only a single directive is allowed per label. If NULL is passed as output storage, the label is verified but not returned to the caller. Return Value On success, sd_bus_path_encode() returns positive or 0, and a valid bus path in the return argument. On success, sd_bus_path_decode() returns a positive value if the prefixed matched, or 0 if it did not. If the prefix matched, the external identifier is returned in the return parameter. If it did not match, NULL is returned in the return parameter. On failure, a negative errno-style error number is returned by either function. The returned strings must be free3'd by the caller. Notes sd_bus_path_encode() and sd_bus_path_decode() are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, free3 systemd-229/man/sd_bus_request_name.xml000066400000000000000000000164161265713322000204150ustar00rootroot00000000000000 sd_bus_request_name systemd Developer Lennart Poettering lennart@poettering.net sd_bus_request_name 3 sd_bus_request_name sd_bus_release_name Request or release a well-known service name on a bus #include <systemd/sd-bus.h> int sd_bus_request_name sd_bus *bus const char *name uint64_t flags int sd_bus_release_name sd_bus *bus const char *name Description sd_bus_request_name() requests a well-known service name on a bus. It takes a bus connection, a valid bus name and a flags parameter. The flags parameter is a combination of the following flags: SD_BUS_NAME_ALLOW_REPLACEMENT After acquiring the name successfully, permit other peers to take over the name when they try to acquire it with the SD_BUS_NAME_REPLACE_EXISTING flag set. If SD_BUS_NAME_ALLOW_REPLACEMENT is not set on the original request, such a request by other peers will be denied. SD_BUS_NAME_REPLACE_EXISTING Take over the name if it is already acquired by another peer, and that other peer has permitted takeover by setting SD_BUS_NAME_ALLOW_REPLACEMENT while acquiring it. SD_BUS_NAME_QUEUE Queue the acquisition of the name when the name is already taken. sd_bus_release_name() releases an acquired well-known name. It takes a bus connection and a valid bus name as parameters. Return Value On success, these calls return 0 or a positive integer. On failure, these calls return a negative errno-style error code. If SD_BUS_NAME_QUEUE is specified, sd_bus_request_name() will return 0 when the name is already taken by another peer and the client has been added to the queue for the name. In that case, the caller can subscribe to NameOwnerChanged signals to be notified when the name is successfully acquired. sd_bus_request_name() returns > 0 when the name has immediately been acquired successfully. Errors Returned errors may indicate the following problems: -EALREADY The caller already is the owner of the specified name. -EEXIST The name has already been acquired by a different peer, and SD_BUS_NAME_REPLACE_EXISTING was not specified or the other peer did not specify SD_BUS_NAME_ALLOW_REPLACEMENT while acquiring the name. -ESRCH It was attempted to release a name that is currently not registered on the bus. -EADDRINUSE It was attempted to release a name that is owned by a different peer on the bus. -EINVAL A specified parameter is invalid. This is also generated when the requested name is a special service name reserved by the D-Bus specification, or when the operation is requested on a connection that does not refer to a bus. -ENOTCONN The bus connection has been disconnected. -ECHILD The bus connection has been created in a different process than the current one. Notes The sd_bus_acquire_name() and sd_bus_release_name() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-bus3, sd_bus_new3 systemd-229/man/sd_event_add_child.xml000066400000000000000000000245341265713322000201500ustar00rootroot00000000000000 sd_event_add_child systemd More text Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_event_add_child 3 sd_event_add_child sd_event_source_get_child_pid sd_event_child_handler_t Add a child process state change event source to an event loop #include <systemd/sd-event.h> typedef struct sd_event_source sd_event_source; typedef int (*sd_event_child_handler_t) sd_event_source *s const siginfo_t *si void *userdata int sd_event_add_child sd_event *event sd_event_source **source pid_t pid int options sd_event_child_handler_t handler void *userdata int sd_event_source_get_child_pid sd_event_source *source pid_t *pid Description sd_event_add_child() adds a new child process state change event source to an event loop. The event loop object is specified in the event parameter, the event source object is returned in the source parameter. The pid parameter specifies the PID of the process to watch. The handler must reference a function to call when the process changes state. The handler function will be passed the userdata pointer, which may be chosen freely by the caller. The handler also receives a pointer to a siginfo_t structure containing information about the child process event. The options parameter determines which state changes will be watched for. It must contain an OR-ed mask of WEXITED (watch for the child process terminating), WSTOPPED (watch for the child process being stopped by a signal), and WCONTINUED (watch for the child process being resumed by a signal). See waitid2 for further information. Only a single handler may be installed for a specific child process. The handler is enabled for a single event (SD_EVENT_ONESHOT), but this may be changed with sd_event_source_set_enabled3. If the handler function returns a negative error code, it will be disabled after the invocation, even if the SD_EVENT_ON mode was requested before. To destroy an event source object use sd_event_source_unref3, but note that the event source is only removed from the event loop when all references to the event source are dropped. To make sure an event source does not fire anymore, even when there's still a reference to it kept, consider setting the event source to SD_EVENT_OFF with sd_event_source_set_enabled3. If the second parameter of sd_event_add_child() is passed as NULL no reference to the event source object is returned. In this case the event source is considered "floating", and will be destroyed implicitly when the event loop itself is destroyed. Note that the handler function is invoked at a time where the child process is not reaped yet (and thus still is exposed as a zombie process by the kernel). However, the child will be reaped automatically after the function returns. Child processes for which no child process state change event sources are installed will not be reaped by the event loop implementation. If both a child process state change event source and a SIGCHLD signal event source is installed in the same event loop, the configured event source priorities decide which event source is dispatched first. If the signal handler is processed first, it should leave the child processes for which child process state change event sources are installed unreaped. sd_event_source_get_child_pid() retrieves the configured PID of a child process state change event source created previously with sd_event_add_child(). It takes the event source object as the source parameter and a pointer to a pid_t variable to return the process ID in. Return Value On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style error code. Errors Returned errors may indicate the following problems: -ENOMEM Not enough memory to allocate an object. -EINVAL An invalid argument has been passed. This includes specifying an empty mask in options or a mask which contains values different than a combination of WEXITED, WSTOPPED, and WCONTINUED. -EBUSY A handler is already installed for this child process. -ESTALE The event loop is already terminated. -ECHILD The event loop has been created in a different process. -EDOM The passed event source is not a child process event source. See Also systemd1, sd-event3, sd_event_new3, sd_event_now3, sd_event_add_io3, sd_event_add_time3, sd_event_add_signal3, sd_event_add_defer3, sd_event_source_set_enabled3, sd_event_source_set_priority3, sd_event_source_set_userdata3, sd_event_source_set_description3, waitid2 systemd-229/man/sd_event_add_defer.xml000066400000000000000000000223101265713322000201400ustar00rootroot00000000000000 sd_event_add_defer systemd More text Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_event_add_defer 3 sd_event_add_defer sd_event_add_post sd_event_add_exit sd_event_handler_t Add static event sources to an event loop #include <systemd/sd-event.h> typedef struct sd_event_source sd_event_source; typedef int (*sd_event_handler_t) sd_event_source *s void *userdata int sd_event_add_defer sd_event *event sd_event_source **source sd_event_handler_t handler void *userdata int sd_event_add_post sd_event *event sd_event_source **source sd_event_handler_t handler void *userdata int sd_event_add_exit sd_event *event sd_event_source **source sd_event_handler_t handler void *userdata Description These three functions add new static event sources to an event loop. The event loop object is specified in the event parameter, the event source object is returned in the source parameter. The event sources are enabled statically and will "fire" when the event loop is run and the conditions described below are met. The handler function will be passed the userdata pointer, which may be chosen freely by the caller. sd_event_add_defer() adds a new event source that will be dispatched instantly, before the event loop goes to sleep again and waits for new events. By default, the handler will be called once (SD_EVENT_ONESHOT). Note that if the event source is set to SD_EVENT_ON the event loop will never go to sleep again, but continuously call the handler, possibly interleaved with other event sources. sd_event_add_post() adds a new event source that is run before the event loop will sleep and wait for new events, but only after at least one other non-post event source was dispatched. By default, the source is enabled permanently (SD_EVENT_ON). Note that this event source type will still allow the event loop to go to sleep again, even if set to SD_EVENT_ON, as long as no other event source is ever triggered. sd_event_add_exit() adds a new event source that will be dispatched when the event loop is terminated with sd_event_exit3. The sd_event_source_set_enabled3 function may be used to enable the event source permanently (SD_EVENT_ON) or to make it fire just once (SD_EVENT_ONESHOT). If the handler function returns a negative error code, it will be disabled after the invocation, even if the SD_EVENT_ON mode was requested before. To destroy an event source object use sd_event_source_unref3, but note that the event source is only removed from the event loop when all references to the event source are dropped. To make sure an event source does not fire anymore, even when there's still a reference to it kept, consider setting the event source to SD_EVENT_OFF with sd_event_source_set_enabled3. If the second parameter of these functions is passed as NULL no reference to the event source object is returned. In this case the event source is considered "floating", and will be destroyed implicitly when the event loop itself is destroyed. Return Value On success, this functions return 0 or a positive integer. On failure, they return a negative errno-style error code. Errors Returned errors may indicate the following problems: -ENOMEM Not enough memory to allocate an object. -EINVAL An invalid argument has been passed. -ESTALE The event loop is already terminated. -ECHILD The event loop has been created in a different process. See Also systemd1, sd-event3, sd_event_new3, sd_event_now3, sd_event_add_io3, sd_event_add_time3, sd_event_add_signal3, sd_event_add_child3, sd_event_source_set_enabled3, sd_event_source_set_priority3, sd_event_source_set_userdata3, sd_event_source_set_description3, sd_event_exit3 systemd-229/man/sd_event_add_io.xml000066400000000000000000000332361265713322000174730ustar00rootroot00000000000000 sd_event_add_io systemd Developer Lennart Poettering lennart@poettering.net sd_event_add_io 3 sd_event_add_io sd_event_source_get_io_events sd_event_source_set_io_events sd_event_source_get_io_revents sd_event_source_get_io_fd sd_event_source_set_io_fd sd_event_source sd_event_io_handler_t Add an I/O event source to an event loop #include <systemd/sd-event.h> typedef struct sd_event_source sd_event_source; typedef int (*sd_event_io_handler_t) sd_event_source *s int fd uint32_t revents void *userdata int sd_event_add_io sd_event *event sd_event_source **source int fd uint32_t events sd_event_io_handler_t handler void *userdata int sd_event_source_get_io_events sd_event_source *source uint32_t *events int sd_event_source_set_io_events sd_event_source *source uint32_t events int sd_event_source_get_io_revents sd_event_source *source uint32_t *revents int sd_event_source_get_io_fd sd_event_source *source int sd_event_source_set_io_fd sd_event_source *source int fd Description sd_event_add_io() adds a new I/O event source to an event loop. The event loop object is specified in the event parameter, the event source object is returned in the source parameter. The fd parameter takes the UNIX file descriptor to watch, which may refer to a socket, a FIFO, a message queue, a serial connection, a character device, or any other file descriptor compatible with Linux epoll7. The events parameter takes a bit mask of events to watch for, a combination of the following event flags: EPOLLIN, EPOLLOUT, EPOLLRDHUP, EPOLLPRI, and EPOLLET, see epoll_ctl2 for details. The handler shall reference a function to call when the event source is triggered. The userdata pointer will be passed to the handler function, and may be chosen freely by the caller. The handler will also be passed the file descriptor the event was seen on, as well as the actual event flags. It's generally a subset of the events watched, however may additionally include EPOLLERR and EPOLLHUP. By default, an event source will stay enabled continuously (SD_EVENT_ON), but this may be changed with sd_event_source_set_enabled3. If the handler function returns a negative error code, it will be disabled after the invocation, even if the SD_EVENT_ON mode was requested before. Note that an event source set to SD_EVENT_ON will fire continuously unless data is read from or written to the file descriptor to reset the mask of events seen. Setting the I/O event mask to watch for to 0 does not mean that the event source won't be triggered anymore, as EPOLLHUP and EPOLLERR may be triggered even with a zero event mask. To temporarily disable an I/O event source use sd_event_source_set_enabled3 with SD_EVENT_OFF instead. To destroy an event source object use sd_event_source_unref3, but note that the event source is only removed from the event loop when all references to the event source are dropped. To make sure an event source does not fire anymore, even if it is still referenced, disable the event source using sd_event_source_set_enabled3 with SD_EVENT_OFF. If the second parameter of sd_event_add_io() is NULL no reference to the event source object is returned. In this case the event source is considered "floating", and will be destroyed implicitly when the event loop itself is destroyed. It is recommended to use sd_event_add_io() only in conjunction with file descriptors that have O_NONBLOCK set, to ensure that all I/O operations from invoked handlers are properly asynchronous and non-blocking. Using file descriptors without O_NONBLOCK might result in unexpected starvation of other event sources. See fcntl2 for details on enabling O_NONBLOCK mode. sd_event_source_get_io_events() retrieves the configured mask of watched I/O events of an event source created previously with sd_event_add_io(). It takes the event source object and a pointer to a variable to store the mask in. sd_event_source_set_io_events() configures the mask of watched I/O events of an event source created previously with sd_event_add_io(). It takes the event source object and the new event mask. sd_event_source_get_io_revents() retrieves the I/O event mask of currently seen but undispatched events from an event source created previously with sd_event_add_io(). It takes the event source object and a pointer to a variable to store the event mask in. When called from a handler function on the handler's event source object this will return the same mask as passed to the handler's revents parameter. This call is primarily useful to check for undispatched events of an event source from the handler of an unrelated (possibly higher priority) event source. Note the relation between sd_event_source_get_pending() and sd_event_source_get_io_revents(): both functions will report non-zero results when there's an event pending for the event source, but the former applies to all event source types, the latter only to I/O event sources. sd_event_source_get_io_fd() retrieves the UNIX file descriptor of an event source created previously with sd_event_add_io(). It takes the event source object and returns the non-negative file descriptor or a negative error number on error (see below). sd_event_source_set_io_fd() changes the UNIX file descriptor of an I/O event source created previously with sd_event_add_io(). It takes the event source object and the new file descriptor. Return Value On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style error code. Errors Returned values may indicate the following problems: -ENOMEM Not enough memory to allocate an object. -EINVAL An invalid argument has been passed. -ESTALE The event loop is already terminated. -ECHILD The event loop has been created in a different process. -EDOM The passed event source is not an I/O event source. See Also systemd1, sd-event3, sd_event_new3, sd_event_now3, sd_event_add_time3, sd_event_add_signal3, sd_event_add_child3, sd_event_add_defer3, sd_event_source_set_enabled3, sd_event_source_set_priority3, sd_event_source_set_userdata3, sd_event_source_set_description3, sd_event_source_get_pending3, epoll_ctl3, epoll7 systemd-229/man/sd_event_add_signal.xml000066400000000000000000000223551265713322000203410ustar00rootroot00000000000000 sd_event_add_signal systemd More text Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_event_add_signal 3 sd_event_add_signal sd_event_source_get_signal sd_event_signal_handler_t Add a UNIX process signal event source to an event loop #include <systemd/sd-event.h> typedef struct sd_event_source sd_event_source; typedef int (*sd_event_signal_handler_t) sd_event_source *s const struct signalfd_siginfo *si void *userdata int sd_event_add_signal sd_event *event sd_event_source **source int signal sd_event_signal_handler_t handler void *userdata int sd_event_source_get_signal sd_event_source *source Description sd_event_add_signal() adds a new UNIX process signal event source to an event loop. The event loop object is specified in the event parameter, and the event source object is returned in the source parameter. The signal parameter specifies the numeric signal to be handled (see signal7). The handler parameter must reference a function to call when the signal is received or be NULL. The handler function will be passed the userdata pointer, which may be chosen freely by the caller. The handler also receives a pointer to a signalfd_siginfo structure containing information about the received signal. See signalfd2 for further information. Only a single handler may be installed for a specific signal. The signal will be unblocked by this call, and must be blocked before this function is called in all threads (using sigprocmask2). If the handler is not specified (handler is NULL), a default handler which causes the program to exit cleanly will be used. By default, the event source is enabled permanently (SD_EVENT_ON), but this may be changed with sd_event_source_set_enabled3. If the handler function returns a negative error code, it will be disabled after the invocation, even if the SD_EVENT_ON mode was requested before. To destroy an event source object use sd_event_source_unref3, but note that the event source is only removed from the event loop when all references to the event source are dropped. To make sure an event source does not fire anymore, even if it is still referenced, disable the event source using sd_event_source_set_enabled3 with SD_EVENT_OFF. If the second parameter of sd_event_add_signal() is NULL no reference to the event source object is returned. In this case the event source is considered "floating", and will be destroyed implicitly when the event loop itself is destroyed. sd_event_source_get_signal() returns the configured signal number of an event source created previously with sd_event_add_signal(). It takes the event source object as the source parameter. Return Value On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style error code. Errors Returned errors may indicate the following problems: -ENOMEM Not enough memory to allocate an object. -EINVAL An invalid argument has been passed. -EBUSY A handler is already installed for this signal or the signal was not blocked previously. -ESTALE The event loop is already terminated. -ECHILD The event loop has been created in a different process. -EDOM The passed event source is not a signal event source. See Also systemd1, sd-event3, sd_event_new3, sd_event_now3, sd_event_add_io3, sd_event_add_time3, sd_event_add_child3, sd_event_add_defer3, sd_event_source_set_enabled3, sd_event_source_set_description3, sd_event_source_set_userdata3, signal7, signalfd2 systemd-229/man/sd_event_add_time.xml000066400000000000000000000360261265713322000200220ustar00rootroot00000000000000 sd_event_add_time systemd Developer Lennart Poettering lennart@poettering.net sd_event_add_time 3 sd_event_add_time sd_event_source_get_time sd_event_source_set_time sd_event_source_get_time_accuracy sd_event_source_set_time_accuracy sd_event_source_get_time_clock sd_event_time_handler_t Add a timer event source to an event loop #include <systemd/sd-event.h> typedef struct sd_event_source sd_event_source; typedef int (*sd_event_time_handler_t) sd_event_source *s uint64_t usec void *userdata int sd_event_add_time sd_event *event sd_event_source **source clockid_t clock uint64_t usec uint64_t accuracy sd_event_time_handler_t handler void *userdata int sd_event_source_get_time sd_event_source *source uint64_t *usec int sd_event_source_set_time sd_event_source *source uint64_t usec int sd_event_source_get_time_accuracy sd_event_source *source uint64_t *usec int sd_event_source_set_time_accuracy sd_event_source *source uint64_t usec int sd_event_source_get_time_clock sd_event_source *source clockid_t *clock Description sd_event_add_time() adds a new timer event source to an event loop. The event loop object is specified in the event parameter, the event source object is returned in the source parameter. The clock parameter takes a clock identifier, one of CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_REALTIME_ALARM, or CLOCK_BOOTTIME_ALARM. See timerfd_create2 for details regarding the various types of clocks. The usec parameter specifies the earliest time, in microseconds (µs), relative to the clock's epoch, when the timer shall be triggered. If a time already in the past is specified (including 0), this timer source "fires" immediately and is ready to be dispatched. If the paramater is specified as UINT64_MAX the timer event will never elapse, which may be used as an alternative to explicitly disabling a timer event source with sd_event_source_set_enabled3. The accuracy parameter specifies an additional accuracy value in µs specifying how much the timer event may be delayed. Use 0 to select the default accuracy (250ms). Use 1µs for maximum accuracy. Consider specifying 60000000µs (1min) or larger for long-running events that may be delayed substantially. Picking higher accuracy values allows the system to coalesce timer events more aggressively, improving power efficiency. The handler parameter shall reference a function to call when the timer elapses. The handler function will be passed the userdata pointer, which may be chosen freely by the caller. The handler is also passed the configured trigger time, even if it is actually called slightly later, subject to the specified accuracy value, the kernel timer slack (see prctl2), and additional scheduling latencies. To query the actual time the handler was called use sd_event_now3. By default, the timer will elapse once (SD_EVENT_ONESHOT), but this may be changed with sd_event_source_set_enabled3. If the handler function returns a negative error code, it will be disabled after the invocation, even if the SD_EVENT_ON mode was requested before. Note that a timer event set to SD_EVENT_ON will fire continuously unless its configured time is updated using sd_event_source_set_time(). To destroy an event source object use sd_event_source_unref3, but note that the event source is only removed from the event loop when all references to the event source are dropped. To make sure an event source does not fire anymore, even if it is still referenced, disable the event source using sd_event_source_set_enabled3 with SD_EVENT_OFF. If the second parameter of sd_event_add_time() is NULL no reference to the event source object is returned. In this case the event source is considered "floating", and will be destroyed implicitly when the event loop itself is destroyed. If the handler to sd_event_add_time() is NULL, and the event source fires, this will be considered a request to exit the event loop. In this case, the userdata parameter, cast to an integer, is used for the exit code passed to sd_event_exit3. Use CLOCK_BOOTTIME_ALARM and CLOCK_REALTIME_ALARM to define event sources that may wake up the system from suspend. In order to set up relative timers (that is, relative to the current time), retrieve the current time via sd_event_now3, add the desired timespan to it, and use the result as the usec parameter to sd_event_add_time(). In order to set up repetitive timers (that is, timers that are triggered in regular intervals), set up the timer normally, for the first invocation. Each time the event handler is invoked, update the timer's trigger time with sd_event_source_set_time3 for the next timer iteration, and reenable the timer using sd_event_source_set_enabled(). To calculate the next point in time to pass to sd_event_source_set_time(), either use as base the usec parameter passed to the timer callback, or the timestamp returned by sd_event_now(). In the former case timer events will be regular, while in the latter case the scheduling latency will keep accumulating on the timer. sd_event_source_get_time() retrieves the configured time value of an event source created previously with sd_event_add_time(). It takes the event source object and a pointer to a variable to store the time in, relative to the selected clock's epoch, in µs. sd_event_source_set_time() changes the time of an event source created previously with sd_event_add_time(). It takes the event source object and a time relative to the selected clock's epoch, in µs. sd_event_source_get_time_accuracy() retrieves the configured accuracy value of a event source created previously with sd_event_add_time(). It takes the event source object and a pointer to a variable to store the accuracy in. The accuracy is specified in µs. sd_event_source_set_time_accuracy() changes the configured accuracy of a timer event source created previously with sd_event_add_time(). It takes the event source object and accuracy, in µs. sd_event_source_get_time_clock() retrieves the configured clock of a event source created previously with sd_event_add_time(). It takes the event source object and a pointer to a variable to store the clock identifier in. Return Value On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style error code. Errors Returned values may indicate the following problems: -ENOMEM Not enough memory to allocate an object. -EINVAL An invalid argument has been passed. -ESTALE The event loop is already terminated. -ECHILD The event loop has been created in a different process. -EOPNOTSUPP The selected clock is not supported by the event loop implementation. -EDOM The passed event source is not a timer event source. See Also systemd1, sd-event3, sd_event_new3, sd_event_now3, sd_event_add_io3, sd_event_add_signal3, sd_event_add_child3, sd_event_add_defer3, sd_event_source_set_enabled3, sd_event_source_set_priority3, sd_event_source_set_userdata3, sd_event_source_set_description3, clock_gettime2, timerfd_create2, prctl2 systemd-229/man/sd_event_exit.xml000066400000000000000000000132071265713322000172210ustar00rootroot00000000000000 sd_event_exit systemd Developer Lennart Poettering lennart@poettering.net sd_event_exit 3 sd_event_exit sd_event_get_exit_code Ask the event loop to exit #include <systemd/sd-event.h> int sd_event_exit sd_event *event int code int sd_event_get_exit_code sd_event *event int *code Description sd_event_exit() requests the event loop specified in the event event loop object to exit. The code parameter may be any integer value and is returned as-is by sd_event_loop3 after the last event loop iteration. It may also be queried using sd_event_get_exit_code(), see below. When exiting is requested the event loop will stop listening for and dispatching regular event sources. Instead it will proceed with executing only event sources registered with sd_event_add_exit3 in the order defined by their priority. After all exit event sources have been dispatched the event loop is terminated. If sd_event_exit() is invoked a second time while the event loop is still processing exit event sources, the exit code stored in the event loop object is updated, but otherwise no further operation is executed. sd_event_get_exit_code() may be used to query the exit code passed into sd_event_exit() earlier. While the full positive and negative integer ranges may be used for the exit code, care should be taken not pick exit codes that conflict with regular exit codes returned by sd_event_loop(), if these exit codes shall be distinguishable. Return Value On success, sd_event_exit() and sd_event_get_exit_code() return 0 or a positive integer. On failure, they return a negative errno-style error code. Errors Returned errors may indicate the following problems: -EINVAL The event loop object or error code pointer are invalid. -ECHILD The event loop was created in a different process. -ESTALE The event loop has exited already and all exit handlers are already processed. -ENODATA The event loop has not been requested to exit yet. See Also systemd1, sd-event3, sd_event_new3, sd_event_add_exit3 systemd-229/man/sd_event_get_fd.xml000066400000000000000000000113371265713322000175020ustar00rootroot00000000000000 sd_event_get_fd systemd More text Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_event_get_fd 3 sd_event_get_fd Obtain a file descriptor to poll for event loop events #include <systemd/sd-event.h> int sd_event_get_fd sd_event *event Description sd_event_get_fd() returns the file descriptor that an event loop object returned by the sd_event_new3 function uses to wait for events. This file descriptor may itself be polled for POLLIN/EPOLLIN events. This makes it possible to embed an sd-event3 event loop into another, possibly foreign, event loop. The returned file descriptor refers to an epoll7 object. It is recommended not to alter it by invoking epoll_ctl2 on it, in order to avoid interference with the event loop's inner logic and assumptions. Return Value On success, sd_event_get_fd() returns a non-negative file descriptor. On failure, it returns a negative errno-style error code. Errors Returned errors may indicate the following problems: -EINVAL event is not a valid pointer to an sd_event structure. -ECHILD The event loop has been created in a different process. Examples Integration in the GLib event loop See Also sd-event3, sd_event_new3, sd_event_wait3, epoll_ctl3, epoll7 systemd-229/man/sd_event_new.xml000066400000000000000000000242231265713322000170410ustar00rootroot00000000000000 sd_event_new systemd Developer Lennart Poettering lennart@poettering.net sd_event_new 3 sd_event_new sd_event_default sd_event_ref sd_event_unref sd_event_unrefp sd_event_get_tid sd_event Acquire and release an event loop object #include <systemd/sd-event.h> typedef struct sd_event sd_event; int sd_event_new sd_event **event int sd_event_default sd_event **event sd_event *sd_event_ref sd_event *event sd_event *sd_event_unref sd_event *event void sd_event_unrefp sd_event **event int sd_event_get_tid sd_event *event pid_t *tid Description sd_event_new() allocates a new event loop object. The event loop object is returned in the event parameter. After use, drop the returned reference with sd_event_unref(). When the last reference is dropped, the object is freed. sd_event_default() acquires a reference to the default event loop object of the calling thread, possibly allocating a new object if no default event loop object has been allocated yet for the thread. After use, drop the returned reference with sd_event_unref(). When the last reference is dropped, the event loop is freed. If this function is called while the object returned from a previous call from the same thread is still referenced, the same object is returned again, but the reference is increased by one. It is recommended to use this call instead of sd_event_new() in order to share event loop objects between various components that are dispatched in the same thread. All threads have exactly either zero or one default event loop objects associated, but never more. After allocating an event loop object, add event sources to it with sd_event_add_io3, sd_event_add_time3, sd_event_add_signal3, sd_event_add_child3 or sd_event_add_defer3, and then execute the event loop using sd_event_run3. sd_event_ref() increases the reference count of the specified event loop object by one. sd_event_unref() decreases the reference count of the specified event loop object by one. If the count hits zero, the object is freed. Note that it is freed regardless of whether it is the default event loop object for a thread or not. This means that allocating an event loop with sd_event_default(), then releasing it, and then acquiring a new one with sd_event_default() will result in two distinct objects. Note that, in order to free an event loop object, all remaining event sources of the event loop also need to be freed as each keeps a reference to it. sd_event_unrefp() is similar to sd_event_unref() but takes a pointer to a pointer to an sd_event object. This call is useful in conjunction with GCC's and LLVM's Clean-up Variable Attribute. Note that this function is defined as inline function. Use a declaration like the following, in order to allocate an event loop object that is freed automatically as the code block is left: { __attribute__((cleanup(sd_event_unrefp)) sd_event *event = NULL; int r; … r = sd_event_default(&event); if (r < 0) fprintf(stderr, "Failed to allocate event loop: %s\n", strerror(-r)); … } sd_event_ref(), sd_event_unref() and sd_event_unrefp() execute no operation if the passed in event loop object is NULL. sd_event_get_tid() retrieves the thread identifier ("TID") of the thread the specified event loop object is associated with. This call is only supported for event loops allocated with sd_event_default(), and returns the identifier for the thread the event loop is the default event loop of. See gettid2 for more information on thread identifiers. Return Value On success, sd_event_new() and sd_event_default() return 0 or a positive integer. On failure, they return a negative errno-style error code. sd_event_ref() always returns a pointer to the event loop object passed in. sd_event_unref() always returns NULL. Errors Returned errors may indicate the following problems: -ENOMEM Not enough memory to allocate the object. -EMFILE The maximum number of event loops has been allocated. -ENXIO sd_event_get_tid() was invoked on an event loop object that was not allocated with sd_event_default(). See Also systemd1, sd-event3, sd_event_add_io3, sd_event_add_time3, sd_event_add_signal3, sd_event_add_child3, sd_event_add_defer3, sd_event_add_post3, sd_event_add_exit3, sd_event_run3, gettid2 systemd-229/man/sd_event_now.xml000066400000000000000000000122631265713322000170540ustar00rootroot00000000000000 sd_event_now systemd Developer Lennart Poettering lennart@poettering.net sd_event_now 3 sd_event_now Retrieve current event loop iteration timestamp #include <systemd/sd-event.h> int sd_event_now sd_event *event clockid_t clock uint64_t *usec Description sd_event_now() returns the time when the most recent event loop iteration began. A timestamp is taken right after returning from the event sleep, and before dispatching any event sources. The event parameter specifies the event loop object to retrieve the timestamp from. The clock parameter specifies the clock to retrieve the timestamp for, and is one of CLOCK_REALTIME (or equivalently CLOCK_REALTIME_ALARM), CLOCK_MONOTONIC, or CLOCK_BOOTTIME (or equivalently CLOCK_BOOTTIME_ALARM), see clock_gettime2 for more information on the various clocks. The retrieved timestamp is stored in the usec parameter, in µs since the clock's epoch. If this function is invoked before the first event loop iteration, the current time is returned, as reported by clock_gettime(). To distinguish this case from a regular invocation the return value will be positive, and zero when the returned timestamp refers to an actual event loop iteration. Return Value If the first event loop iteration has not run yet sd_event_now() writes current time to usec and returns a positive return value. Otherwise, it will write the requested timestamp to usec and return 0. On failure, the call returns a negative errno-style error code. Errors Returned values may indicate the following problems: -EINVAL An invalid parameter was passed. -EOPNOTSUPP Unsupported clock type. -ECHILD The event loop object was created in a different process. See Also systemd1, sd-event3, sd_event_new3, sd_event_add_time3, clock_gettime2 systemd-229/man/sd_event_run.xml000066400000000000000000000174431265713322000170620ustar00rootroot00000000000000 sd_event_run systemd Developer Tom Gundersen teg@jklm.no sd_event_run 3 sd_event_run sd_event_loop Run an event loop #include <systemd/sd-event.h> int sd_event_run sd_event *event uint64_t usec int sd_event_loop sd_event *event Description sd_event_run() may be used to run a single iteration of the event loop specified in the event parameter. The function waits until an event to process is available, and dispatches the registered handler for it. The usec parameter specifies the maximum time (in microseconds) to wait for an event. Use (uint64_t) -1 to specify an infinite timeout. sd_event_loop() invokes sd_event_run() in a loop, thus implementing the actual event loop. The call returns as soon as exiting was requested using sd_event_exit3. The event loop object event is created with sd_event_new3. Events sources to wait for and their handlers may be registered with sd_event_add_io3, sd_event_add_time3, sd_event_add_signal3, sd_event_add_child3, sd_event_add_defer3, sd_event_add_post3 and sd_event_add_exit3. For low-level control of event loop execution, use sd_event_prepare3, sd_event_wait3 and sd_event_dispatch3 which are wrapped by sd_event_run(). Along with sd_event_get_fd3, these functions allow integration of an sd-event3 event loop into foreign event loop implementations. Return Value On failure, these functions return a negative errno-style error code. sd_event_run() returns a positive, non-zero integer if an event source was dispatched, and zero when the specified timeout hit before an event source has seen any event, and hence no event source was dispatched. sd_event_loop() returns the exit code specified when invoking sd_event_exit(). Errors Returned errors may indicate the following problems: -EINVAL The event parameter is invalid or NULL. -EBUSY The event loop object is not in the right state (see sd_event_prepare3 for an explanation of possible states). -ESTALE The event loop is already terminated. -ECHILD The event loop has been created in a different process. Other errors are possible, too. See Also systemd1, sd_event_new3, sd_event_add_io3, sd_event_add_time3, sd_event_add_signal3, sd_event_add_defer3, sd_event_add_exit3, sd_event_add_post3, sd_event_exit3, sd_event_get_fd3, sd_event_wait3, GLib Main Event Loop. systemd-229/man/sd_event_set_watchdog.xml000066400000000000000000000167101265713322000207250ustar00rootroot00000000000000 sd_event_set_watchdog systemd Developer Lennart Poettering lennart@poettering.net sd_event_set_watchdog 3 sd_event_set_watchdog sd_event_get_watchdog Enable event loop watchdog support #include <systemd/sd-event.h> int sd_event_set_watchdog sd_event *event int b int sd_event_get_watchdog sd_event *event Description sd_event_set_watchdog() may be used to enable or disable automatic watchdog notification support in the event loop object specified in the event parameter. Specifically, depending on the b boolean argument this will make sure the event loop wakes up in regular intervals and sends watchdog notification messages to the service manager, if this was requested by the service manager. Watchdog support is determined with sd_watchdog_enabled3, and watchdog messages are sent with sd_notify3. See the WatchdogSec= setting in systemd.service5 for details on how to enable watchdog support for a service and the protocol used. The wake-up interval is chosen as half the watchdog timeout declared by the service manager via the $WATCHDOG_USEC environment variable. If the service manager did not request watchdog notifications, or if the process was not invoked by the service manager this call with a true b parameter executes no operation. Passing a false b parameter will disable the automatic sending of watchdog notification messages if it was enabled before. Newly allocated event loop objects have this feature disabled. The first watchdog notification message is sent immediately when set_event_set_watchdog() is invoked with a true b parameter. The watchdog logic is designed to allow the service manager to automatically detect services that ceased processing of incoming events, and thus appear "hung". Watchdog notifications are sent out only at the beginning of each event loop iteration. If an event source dispatch function blocks for an excessively long time and does not return execution to the event loop quickly, this might hence cause the notification message to be delayed, and possibly result in abnormal program termination, as configured in the service unit file. sd_event_get_watchdog() may be used to determine whether watchdog support was previously requested by a call to sd_event_set_watchdog() with a true b parameter and successfully enabled. Return Value On success, sd_event_set_watchdog() and sd_event_get_watchdog() return a non-zero positive integer if the service manager requested watchdog support and watchdog support was successfully enabled. They return zero if the service manager did not request watchdog support, or if watchdog support was explicitly disabled with a false b parameter. On failure, they return a negative errno-style error code. Errors Returned errors may indicate the following problems: -ECHILD The event loop has been created in a different process. -EINVAL The passed event loop object was invalid. See Also systemd1, sd-event3, sd_event_new3, sd_event_add_io3, sd_event_add_time3, sd_event_add_signal3, sd_event_add_child3, sd_event_add_defer3, sd_event_add_post3, sd_event_add_exit3, sd_watchdog_enabled3, sd_notify3, systemd.service5 systemd-229/man/sd_event_source_get_event.xml000066400000000000000000000071771265713322000216210ustar00rootroot00000000000000 sd_event_source_get_event systemd Developer Lennart Poettering lennart@poettering.net sd_event_source_get_event 3 sd_event_source_get_event Retrieve the event loop of an event source #include <systemd/sd-event.h> sd_event* sd_event_source_get_event sd_event_source *source Description sd_event_source_get_event() may be used to retrieve the event loop object the event source object specified as source is associated with. The event loop object is specified when creating an event source object with calls such as sd_event_add_io3 or sd_event_add_time3. Return Value On success, sd_event_source_get_event() returns the associated event loop object. On failure, it returns NULL. See Also sd-event3, sd_event_add_io3, sd_event_add_time3, sd_event_add_child3, sd_event_add_signal3, sd_event_add_defer3, sd_event_source_set_userdata3 systemd-229/man/sd_event_source_get_pending.xml000066400000000000000000000141461265713322000221160ustar00rootroot00000000000000 sd_event_source_get_pending systemd Developer Lennart Poettering lennart@poettering.net sd_event_source_get_pending 3 sd_event_source_get_pending Determine pending state of event sources #include <systemd/sd-event.h> int sd_event_source_get_pending sd_event_source *source Description sd_event_source_get_pending() may be used to determine whether the event source object specified as source has seen events but has not been dispatched yet (and thus is marked "pending"). Event source objects initially are not marked pending, when they are created with calls such as sd_event_add_io3, sd_event_add_time3, with the exception of those created with sd_event_add_defer3 which are immediately marked pending, and sd_event_add_exit3 for which the "pending" concept is not defined. For details see the respective manual pages. In each event loop iteration one event source of those marked pending is dispatched, in the order defined by the event source priority, as set with sd_event_source_set_priority3. For I/O event sources, as created with sd_event_add_io3, the call sd_event_source_get_io_revents3 may be used to query the type of event pending in more detail. Return Value On success, sd_event_source_get_pending() returns an integer greater than zero when the event source is marked pending, and zero when the event source is not marked pending. On failure, it returns a negative errno-style error code. Errors Returned errors may indicate the following problems: -EINVAL source is not a valid pointer to an sd_event_source object. -EDOM source refers to an event source object created with sd_event_add_exit3. -ENOMEM Not enough memory. -ESTALE The event loop is already terminated. -ECHILD The event loop has been created in a different process. See Also sd-event3, sd_event_add_io3, sd_event_add_time3, sd_event_add_child3, sd_event_add_signal3, sd_event_add_defer3, sd_event_source_unref3 systemd-229/man/sd_event_source_set_description.xml000066400000000000000000000146531265713322000230340ustar00rootroot00000000000000 sd_event_source_set_description systemd More text Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl sd_event_source_set_description 3 sd_event_source_set_description sd_event_source_get_description Set or retrieve descriptive names of event sources #include <systemd/sd-event.h> int sd_event_source_set_description sd_event_source *source const char *description int sd_event_source_get_description sd_event_source *source const char **description Description sd_event_source_set_description() may be used to set an arbitrary descriptive name for the event source object specified as source. This name will be used in debugging messages generated by sd-event3 for this event source, and may be queried using sd_event_source_get_description() for debugging purposes. The description parameter shall point to a NUL-terminated string or be NULL. In the latter case, the descriptive name will be unset. The string is copied internally, hence the description argument is not referenced after the function returns. sd_event_source_get_description() may be used to query the current descriptive name assigned to the event source object source. It returns a pointer to the current name in description, stored in memory internal to the event source. The memory is invalidated when the event source is destroyed or the descriptive name is changed. Event source objects generally have no description set when they are created, except for UNIX signal event sources created with sd_event_add_signal3, whose descriptive name is initialized to the signal's C constant name (e.g. SIGINT or SIGTERM). Return Value On success, sd_event_source_set_description() and sd_event_source_get_description() return a non-negative integer. On failure, they return a negative errno-style error code. Errors Returned errors may indicate the following problems: -EINVAL source is not a valid pointer to an sd_event_source object or the description argument for sd_event_source_get_description() is NULL. -ENOMEM Not enough memory to copy the name. -ECHILD The event loop has been created in a different process. -ENXIO No name was set for the event source. See Also sd-event3, sd_event_add_io3, sd_event_add_time3, sd_event_add_child3, sd_event_add_signal3, sd_event_add_defer3, sd_event_source_set_userdata3 systemd-229/man/sd_event_source_set_enabled.xml000066400000000000000000000153151265713322000220770ustar00rootroot00000000000000 sd_event_source_set_enabled systemd Developer Lennart Poettering lennart@poettering.net sd_event_source_set_enabled 3 sd_event_source_set_enabled sd_event_source_get_enabled SD_EVENT_ON SD_EVENT_OFF SD_EVENT_ONESHOT Enable or disable event sources #include <systemd/sd-event.h> enum { SD_EVENT_OFF = 0, SD_EVENT_ON = 1, SD_EVENT_ONESHOT = -1, }; int sd_event_source_set_enabled sd_event_source *source int enabled int sd_event_source_get_enabled sd_event_source *source int *enabled Description sd_event_source_set_enabled() may be used to enable or disable the event source object specified as source. The enabled parameter takes one of SD_EVENT_ON (to enable), SD_EVENT_OFF (to disable) or SD_EVENT_ONESHOT. If invoked with SD_EVENT_ONESHOT the event source will be enabled but automatically reset to SD_EVENT_OFF after the event source was dispatched once. Event sources that are disabled will not result in event loop wakeups and will not be dispatched, until they are enabled again. sd_event_source_get_enabled() may be used to query whether the event source object source is currently enabled or not. It returns the enablement state in enabled. Event source objects are enabled when they are first created with calls such as sd_event_add_io3, sd_event_add_time3. However, depending on the event source type they are enabled continuously (SD_EVENT_ON) or only for a single invocation of the event source handler (SD_EVENT_ONESHOT). For details see the respective manual pages. As event source objects stay active and may be dispatched as long as there is at least one reference to them, in many cases it is a good idea to combine a call to sd_event_source_unref3 with a prior call to sd_event_source_set_enabled() with SD_EVENT_OFF, to ensure the event source is not dispatched again until all other remaining references are dropped. Return Value On success, sd_event_source_set_enabled() and sd_event_source_get_enabled() return a non-negative integer. On failure, they return a negative errno-style error code. Errors Returned errors may indicate the following problems: -EINVAL source is not a valid pointer to an sd_event_source object. -ENOMEM Not enough memory. -ECHILD The event loop has been created in a different process. See Also sd-event3, sd_event_add_io3, sd_event_add_time3, sd_event_add_child3, sd_event_add_signal3, sd_event_add_defer3, sd_event_source_unref3 systemd-229/man/sd_event_source_set_prepare.xml000066400000000000000000000150661265713322000221460ustar00rootroot00000000000000 sd_event_source_set_prepare systemd Developer Lennart Poettering lennart@poettering.net sd_event_source_set_prepare 3 sd_event_source_set_prepare Set a preparation callback for event sources #include <systemd/sd-event.h> int sd_event_source_set_prepare sd_event_source *source sd_event_handler_t callback typedef int (*sd_event_handler_t) sd_event_source *s void *userdata Description sd_event_source_set_prepare() may be used to set a preparation callback for the event source object specified as source. The callback function specified as callback will be invoked immediately before the event loop goes to sleep to wait for incoming events. It is invoked with the user data pointer passed when the event source was created. The callback function may be used to reconfigure the precise events to wait for. If the callback parameter is passed as NULL the callback function is reset. Event source objects have no preparation callback associated when they are first created with calls such as sd_event_add_io3, sd_event_add_time3. Preparation callback functions are supported for all event source types with the exception of those created with sd_event_add_exit3. Preparation callback functions are dispatched in the order indicated by the event source's priority field, as set with sd_event_source_set_priority3. Preparation callbacks of disabled event sources (see sd_event_source_set_enabled3) are not invoked. Return Value On success, sd_event_source_set_prepare() returns a non-negative integer. On failure, it returns a negative errno-style error code. Errors Returned errors may indicate the following problems: -EINVAL source is not a valid pointer to an sd_event_source object. -ESTALE The event loop is already terminated. -ENOMEM Not enough memory. -ECHILD The event loop has been created in a different process. -EDOM The specified event source has been created with sd_event_add_exit3. See Also sd-event3, sd_event_add_io3, sd_event_add_time3, sd_event_add_child3, sd_event_add_signal3, sd_event_add_defer3, sd_event_source_set_enabled3, sd_event_source_set_priority3, sd_event_source_set_userdata3 systemd-229/man/sd_event_source_set_priority.xml000066400000000000000000000164721265713322000223730ustar00rootroot00000000000000 sd_event_source_set_priority systemd Developer Lennart Poettering lennart@poettering.net sd_event_source_set_priority 3 sd_event_source_set_priority sd_event_source_get_priority SD_EVENT_PRIORITY_IMPORTANT SD_EVENT_PRIORITY_NORMAL SD_EVENT_PRIORITY_IDLE Set or retrieve the priority of event sources #include <systemd/sd-event.h> enum { SD_EVENT_SOURCE_IMPORTANT = -100, SD_EVENT_SOURCE_NORMAL = 0, SD_EVENT_SOURCE_IDLE = 100, }; int sd_event_source_set_priority sd_event_source *source int64_t priority int sd_event_source_get_priority sd_event_source *source int64_t *priority Description sd_event_source_set_priority() may be used to set the priority for the event source object specified as source. The priority is specified as an arbitrary signed 64bit integer. The priority is initialized to SD_EVENT_PRIORITY_NORMAL (0) when the event source is allocated with a call such as sd_event_add_io3 or sd_event_add_time3, and may be changed with this call. If multiple event sources have seen events at the same time, they are dispatched in the order indicated by the event sources' priorities. Event sources with smaller priority values are dispatched first. As well-known points of reference, the constants SD_EVENT_PRIORITY_IMPORTANT (-100), SD_EVENT_PRIORITY_NORMAL (0) and SD_EVENT_PRIORITY_IDLE (100) may be used to indicate event sources that shall be dispatched early, normally or late. It is recommended to specify priorities based on these definitions, and relative to them -- however, the full 64bit signed integer range is available for ordering event sources. Priorities define the order in which event sources that have seen events are dispatched. Care should be taken to ensure that high-priority event sources (those with negative priority values assigned) do not cause starvation of low-priority event sources (those with positive priority values assigned). The order in which event sources with the same priority are dispatched is undefined, but the event loop generally tries to dispatch them in the order it learnt about events on them. As the backing kernel primitives do not provide accurate information about the order in which events occurred this is not necessarily reliable. However, it is guaranteed that if events are seen on multiple same-priority event sources at the same time, each one is not dispatched again until all others have been dispatched once. This behaviour guarantees that within each priority particular event sources do not starve or dominate the event loop. sd_event_source_get_priority() may be used to query the current priority assigned to the event source object source. Return Value On success, sd_event_source_set_priority() and sd_event_source_get_priority() return a non-negative integer. On failure, they return a negative errno-style error code. Errors Returned errors may indicate the following problems: -EINVAL source is not a valid pointer to an sd_event_source object. -ENOMEM Not enough memory. -ESTALE The event loop is already terminated. -ECHILD The event loop has been created in a different process. See Also sd-event3, sd_event_add_io3, sd_event_add_time3, sd_event_add_child3, sd_event_add_signal3, sd_event_add_defer3 systemd-229/man/sd_event_source_set_userdata.xml000066400000000000000000000111311265713322000223050ustar00rootroot00000000000000 sd_event_source_set_userdata systemd Developer Lennart Poettering lennart@poettering.net sd_event_source_set_userdata 3 sd_event_source_set_userdata sd_event_source_get_userdata Set or retrieve user data pointer of event sources #include <systemd/sd-event.h> void* sd_event_source_set_userdata sd_event_source *source void *userdata void* sd_event_source_get_userdata sd_event_source *source Description sd_event_source_set_userdata() may be used to set an arbitrary user data pointer for the event source object specified as source. The user data pointer is usually specified when creating an event source object with calls such as sd_event_add_io3 or sd_event_add_time3, and may be updated with this call. The user data pointer is also passed to all handler callback functions associated with the event source. The userdata parameter specifies the new user data pointer to set, the function returns the previous user data pointer. Note that NULL is a valid user data pointer. sd_event_source_get_userdata() may be used to query the current user data pointer assigned to the event source object source. Return Value On success, sd_event_source_set_userdata() and sd_event_source_get_userdata() return the previously set user data pointer. On failure, they return NULL. See Also sd-event3, sd_event_add_io3, sd_event_add_time3, sd_event_add_child3, sd_event_add_signal3, sd_event_add_defer3, sd_event_source_set_description3 systemd-229/man/sd_event_source_unref.xml000066400000000000000000000131621265713322000207470ustar00rootroot00000000000000 sd_event_source_unref systemd Developer Lennart Poettering lennart@poettering.net sd_event_source_unref 3 sd_event_source_unref sd_event_source_unrefp sd_event_source_ref Increase or decrease event source reference counters #include <systemd/sd-event.h> sd_event_source* sd_event_source_unref sd_event_source *source void sd_event_source_unrefp sd_event_source **source sd_event_source* sd_event_source_ref sd_event_source *source Description sd_event_source_unref() may be used to decrement by one the reference counter of the event source object specified as source. The reference counter is initially set to one, when the event source is created with calls such as sd_event_add_io3 or sd_event_add_time3. When the reference counter reaches zero it is removed from its event loop object and destroyed. sd_event_source_unrefp() is similar to sd_event_source_unref() but takes a pointer to a pointer to an sd_event_source object. This call is useful in conjunction with GCC's and LLVM's Clean-up Variable Attribute. Note that this function is defined as inline function. sd_event_source_ref() may be used to increase by one the reference counter of the event source object specified as source. sd_event_source_unref(), sd_bus_creds_unrefp() and sd_bus_creds_ref() execute no operation if the passed event source object is NULL. Note that event source objects stay alive and may be dispatched as long as they have a reference counter greater than zero. In order to drop a reference of an event source and make sure the associated event source handler function is not called anymore it is recommended to combine a call of sd_event_source_unref() with a prior call to sd_event_source_set_enabled() with SD_EVENT_OFF. Return Value sd_event_source_unref() always returns NULL. sd_event_source_ref() always returns the event source object passed in. See Also sd-event3, sd_event_add_io3, sd_event_add_time3, sd_event_add_child3, sd_event_add_signal3, sd_event_add_defer3, sd_event_source_set_enabled3 systemd-229/man/sd_event_wait.xml000066400000000000000000000343221265713322000172150ustar00rootroot00000000000000 sd_event_wait systemd Developer Tom Gundersen teg@jklm.no sd_event_wait 3 sd_event_wait sd_event_prepare sd_event_dispatch sd_event_get_state SD_EVENT_INITIAL SD_EVENT_PREPARING SD_EVENT_ARMED SD_EVENT_PENDING SD_EVENT_RUNNING SD_EVENT_EXITING SD_EVENT_FINISHED Low-level event loop operations #include <systemd/sd-event.h> enum { SD_EVENT_INITIAL, SD_EVENT_PREPARING, SD_EVENT_ARMED, SD_EVENT_PENDING, SD_EVENT_RUNNING, SD_EVENT_EXITING, SD_EVENT_FINISHED, }; int sd_event_prepare sd_event *event int sd_event_wait sd_event *event uint64_t usec int sd_event_dispatch sd_event *event int sd_event_get_state sd_event *event Description The low-level sd_event_prepare(), sd_event_wait() and sd_event_dispatch() functions may be used to execute specific phases of an event loop. See sd_event_run3 and sd_event_loop3 for higher-level functions that execute individual but complete iterations of an event loop or run it continuously. sd_event_prepare() checks for pending events and arms necessary timers. If any events are ready to be processed ("pending"), it returns a positive, non-zero value, and the caller should process these events with sd_event_dispatch(). sd_event_dispatch() dispatches the highest priority event source that has a pending event. On success, sd_event_dispatch() returns either zero, which indicates that no further event sources may be dispatched and exiting of the event loop was requested via sd_event_exit3; or a positive non-zero value, which means that an event source was dispatched and the loop returned to its initial state, and the caller should initiate the next event loop iteration by invoking sd_event_prepare() again. In case sd_event_prepare() returned zero, sd_event_wait() should be called to wait for further events or a timeout. If any events are ready to be processed, it returns a positive, non-zero value, and the events should be dispatched with sd_event_dispatch(). Otherwise, the event loop returned to its initial state and the next event loop iteration should be initiated by invoking sd_event_prepare() again. sd_event_get_state() may be used to determine the state the event loop is currently in. It returns one of the states described below. All four functions take, as the first argument, the event loop object event that has been created with sd_event_new(). The timeout for sd_event_wait() is specified in usec in milliseconds. (uint64_t) -1 may be used to specify an infinite timeout. State Machine The event loop knows the following states, that may be queried with sd_event_get_state(). SD_EVENT_INITIAL The initial state the event loop is in, before each event loop iteration. Use sd_event_prepare() to transition the event loop into the SD_EVENT_ARMED or SD_EVENT_PENDING states. SD_EVENT_PREPARING An event source is currently being prepared, i.e. the preparation handler is currently being executed, as set with sd_event_set_prepare3. This state is only seen in the event source preparation handler that is invoked from the sd_event_prepare() call and is immediately followed by SD_EVENT_ARMED or SD_EVENT_PENDING. SD_EVENT_ARMED sd_event_prepare() has been called and no event sources were ready to be dispatched. Use sd_event_wait() to wait for new events, and transition into SD_EVENT_PENDING or back into SD_EVENT_INITIAL. SD_EVENT_PENDING sd_event_prepare() or sd_event_wait() have been called and there were event sources with events pending. Use sd_event_dispatch() to dispatch the highest priority event source and transition back to SD_EVENT_INITIAL, or SD_EVENT_FINISHED. SD_EVENT_RUNNING A regular event source is currently being dispatched. This state is only seen in the event source handler that is invoked from the sd_event_dispatch() call, and is immediately followed by SD_EVENT_INITIAL or SD_EVENT_FINISHED as soon the event source handler returns. Note that during dispatching of exit event sources the SD_EVENT_EXITING state is seen instead. SD_EVENT_EXITING Similar to SD_EVENT_RUNNING but is the state in effect while dispatching exit event sources. It is followed by SD_EVENT_INITIAL or SD_EVENT_FINISHED as soon as the event handler returns. SD_EVENT_FINISHED The event loop has exited. All exit event sources have run. If the event loop is in this state it serves no purpose anymore, and should be freed. A simplified flow chart of the states and the calls to transition between them is shown below. Note that SD_EVENT_PREPARING, SD_EVENT_RUNNING and SD_EVENT_EXITING are not shown here. INITIAL -<---<---<---<---<---<---<---<---<---<---<---<---\ | | | ^ | | v ret == 0 | sd_event_prepare() >--->--->--->--->- ARMED | | | ^ | ret > 0 | | | | | v v ret == 0 | PENDING <---<---<---<---<---< sd_event_wait() >--->--->--+ | ret > 0 ^ | | | | v | sd_event_dispatch() >--->--->--->--->--->--->--->--->--->--->/ | ret > 0 | ret == 0 | v FINISHED Return Value On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style error code. In case of sd_event_prepare() and sd_event_wait(), a positive, non-zero return code indicates that events are ready to be processed and zero indicates that no events are ready. In case of sd_event_dispatch(), a positive, non-zero return code indicates that the event loop returned to its initial state and zero indicates the event loop has exited. sd_event_get_state() returns a positive or zero state on success. Errors Returned errors may indicate the following problems: -EINVAL The event parameter is invalid or NULL. -EBUSY The event loop object is not in the right state. -ESTALE The event loop is already terminated. -ECHILD The event loop has been created in a different process. Other errors are possible, too. See Also systemd1, sd_event_new3, sd_event_add_io3, sd_event_add_time3, sd_event_add_signal3, sd_event_add_defer3, sd_event_add_exit3, sd_event_add_post3, sd_event_run3, sd_event_get_fd3, sd_event_source_set_prepare3 systemd-229/man/sd_get_seats.xml000066400000000000000000000126511265713322000170270ustar00rootroot00000000000000 sd_get_seats systemd Developer Lennart Poettering lennart@poettering.net sd_get_seats 3 sd_get_seats sd_get_sessions sd_get_uids sd_get_machine_names Determine available seats, sessions, logged in users and virtual machines/containers #include <systemd/sd-login.h> int sd_get_seats char ***seats int sd_get_sessions char ***sessions int sd_get_uids uid_t **users int sd_get_machine_names char ***machines Description sd_get_seats() may be used to determine all currently available local seats. Returns a NULL terminated array of seat identifiers. The returned array and all strings it references need to be freed with the libc free3 call after use. Note that instead of an empty array NULL may be returned and should be considered equivalent to an empty array. Similarly, sd_get_sessions() may be used to determine all current login sessions. Similarly, sd_get_uids() may be used to determine all Unix users who currently have login sessions. Similarly, sd_get_machine_names() may be used to determine all current virtual machines and containers on the system. Note that the returned lists are not sorted and in an undefined order. Return Value On success, sd_get_seats(), sd_get_sessions(), sd_get_uids() and sd_get_machine_names() return the number of entries in the arrays. On failure, these calls return a negative errno-style error code. Errors Returned errors may indicate the following problems: -EINVAL An input parameter was invalid (out of range, or NULL, where that is not accepted). -ENOMEM Memory allocation failed. Notes The sd_get_seats(), sd_get_sessions(), sd_get_uids() and sd_get_machine_names() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-login3, sd_session_get_seat3 systemd-229/man/sd_id128_get_machine.xml000066400000000000000000000114651265713322000202250ustar00rootroot00000000000000 sd_id128_get_machine systemd Developer Lennart Poettering lennart@poettering.net sd_id128_get_machine 3 sd_id128_get_machine sd_id128_get_boot Retrieve 128-bit IDs #include <systemd/sd-id128.h> int sd_id128_get_machine sd_id128_t *ret int sd_id128_get_boot sd_id128_t *ret Description sd_id128_get_machine() returns the machine ID of the executing host. This reads and parses the machine-id5 file. This function caches the machine ID internally to make retrieving the machine ID a cheap operation. sd_id128_get_boot() returns the boot ID of the executing kernel. This reads and parses the /proc/sys/kernel/random/boot_id file exposed by the kernel. It is randomly generated early at boot and is unique for every running kernel instance. See random4 for more information. This function also internally caches the returned ID to make this call a cheap operation. Note that sd_id128_get_boot() always returns a UUID v4 compatible ID. sd_id128_get_machine() will also return a UUID v4-compatible ID on new installations but might not on older. It is possible to convert the machine ID into a UUID v4-compatible one. For more information, see machine-id5. For more information about the sd_id128_t type see sd-id1283. Return Value The two calls return 0 on success (in which case ret is filled in), or a negative errno-style error code. Notes The sd_id128_get_machine() and sd_id128_get_boot() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-id1283, machine-id5, random4, sd_id128_randomize3 systemd-229/man/sd_id128_randomize.xml000066400000000000000000000075251265713322000177540ustar00rootroot00000000000000 sd_id128_randomize systemd Developer Lennart Poettering lennart@poettering.net sd_id128_randomize 3 sd_id128_randomize Generate 128-bit IDs #include <systemd/sd-id128.h> int sd_id128_randomize sd_id128_t *ret Description sd_id128_randomize() generates a new randomized 128-bit ID and returns it in ret. Every invocation returns a new randomly generated ID. This uses the /dev/urandom kernel random number generator. Note that sd_id128_randomize() always returns a UUID v4-compatible ID. For more information about the sd_id128_t type, see sd-id1283. journalctl1's option may be used as a command line front-end for sd_id128_randomize(). Return Value The call returns 0 on success (in which case ret is filled in), or a negative errno-style error code. Notes The sd_id128_randomize() interface is available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-id1283, machine-id5, random4, sd_id128_get_machine3 systemd-229/man/sd_id128_to_string.xml000066400000000000000000000115271265713322000177710ustar00rootroot00000000000000 sd_id128_to_string systemd Developer Lennart Poettering lennart@poettering.net sd_id128_to_string 3 sd_id128_to_string sd_id128_from_string Format or parse 128-bit IDs as strings #include <systemd/sd-id128.h> char *sd_id128_to_string sd_id128_t id, char s[33] int sd_id128_from_string const char *s, sd_id128_t *ret Description sd_id128_to_string() formats a 128-bit ID as a character string. It expects the ID and a string array capable of storing 33 characters. The ID will be formatted as 32 lowercase hexadecimal digits and be terminated by a NUL byte. sd_id128_from_string() implements the reverse operation: it takes a 33 character string with 32 hexadecimal digits (either lowercase or uppercase, terminated by NUL) and parses them back into a 128-bit ID returned in ret. Alternatively, this call can also parse a 37-character string with a 128-bit ID formatted as RFC UUID. For more information about the sd_id128_t type see sd-id1283. Note that these calls operate the same way on all architectures, i.e. the results do not depend on endianness. When formatting a 128-bit ID into a string, it is often easier to use a format string for printf3. This is easily done using the SD_ID128_FORMAT_STR and SD_ID128_FORMAT_VAL() macros. For more information see sd-id1283. Return Value sd_id128_to_string() always succeeds and returns a pointer to the string array passed in. sd_id128_from_string returns 0 on success, in which case ret is filled in, or a negative errno-style error code. Notes The sd_id128_to_string() and sd_id128_from_string() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-id1283, printf3 systemd-229/man/sd_is_fifo.xml000066400000000000000000000201241265713322000164610ustar00rootroot00000000000000 sd_is_fifo systemd Developer Lennart Poettering lennart@poettering.net sd_is_fifo 3 sd_is_fifo sd_is_socket sd_is_socket_inet sd_is_socket_unix sd_is_mq sd_is_special Check the type of a file descriptor #include <systemd/sd-daemon.h> int sd_is_fifo int fd const char *path int sd_is_socket int fd int family int type int listening int sd_is_socket_inet int fd int family int type int listening uint16_t port int sd_is_socket_unix int fd int type int listening const char *path size_t length int sd_is_mq int fd const char *path int sd_is_special int fd const char *path Description sd_is_fifo() may be called to check whether the specified file descriptor refers to a FIFO or pipe. If the path parameter is not NULL, it is checked whether the FIFO is bound to the specified file system path. sd_is_socket() may be called to check whether the specified file descriptor refers to a socket. If the family parameter is not AF_UNSPEC, it is checked whether the socket is of the specified family (AF_UNIX, AF_INET, ...). If the type parameter is not 0, it is checked whether the socket is of the specified type (SOCK_STREAM, SOCK_DGRAM, ...). If the listening parameter is positive, it is checked whether the socket is in accepting mode, i.e. listen() has been called for it. If listening is 0, it is checked whether the socket is not in this mode. If the parameter is negative, no such check is made. The listening parameter should only be used for stream sockets and should be set to a negative value otherwise. sd_is_socket_inet() is similar to sd_is_socket(), but optionally checks the IPv4 or IPv6 port number the socket is bound to, unless port is zero. For this call family must be passed as either AF_UNSPEC, AF_INET, or AF_INET6. sd_is_socket_unix() is similar to sd_is_socket() but optionally checks the AF_UNIX path the socket is bound to, unless the path parameter is NULL. For normal file system AF_UNIX sockets, set the length parameter to 0. For Linux abstract namespace sockets, set the length to the size of the address, including the initial 0 byte, and set the path to the initial 0 byte of the socket address. sd_is_mq() may be called to check whether the specified file descriptor refers to a POSIX message queue. If the path parameter is not NULL, it is checked whether the message queue is bound to the specified name. sd_is_special() may be called to check whether the specified file descriptor refers to a special file. If the path parameter is not NULL, it is checked whether the file descriptor is bound to the specified file name. Special files in this context are character device nodes and files in /proc or /sys. Return Value On failure, these calls return a negative errno-style error code. If the file descriptor is of the specified type and bound to the specified address, a positive return value is returned, otherwise zero. Notes Internally, these function use a combination of fstat() and getsockname() to check the file descriptor type and where it is bound to. See Also systemd1, sd-daemon3, sd_listen_fds3, systemd.service5, systemd.socket5 systemd-229/man/sd_journal_add_match.xml000066400000000000000000000212741265713322000205100ustar00rootroot00000000000000 sd_journal_add_match systemd Developer Lennart Poettering lennart@poettering.net sd_journal_add_match 3 sd_journal_add_match sd_journal_add_disjunction sd_journal_add_conjunction sd_journal_flush_matches Add or remove entry matches #include <systemd/sd-journal.h> int sd_journal_add_match sd_journal *j const void *data size_t size int sd_journal_add_disjunction sd_journal *j int sd_journal_add_conjunction sd_journal *j void sd_journal_flush_matches sd_journal *j Description sd_journal_add_match() adds a match by which to filter the entries of the journal file. Matches applied with this call will filter what can be iterated through and read from the journal file via calls like sd_journal_next3 and sd_journal_get_data3. Matches are of the form FIELD=value, where the field part is a short uppercase string consisting only of 0–9, A–Z and the underscore. It may not begin with two underscores or be the empty string. The value part may be any value, including binary. If a match is applied, only entries with this field set will be iterated. Multiple matches may be active at the same time: If they apply to different fields, only entries with both fields set like this will be iterated. If they apply to the same fields, only entries where the field takes one of the specified values will be iterated. Well known fields are documented in systemd.journal-fields7. Whenever a new match is added the current entry position is reset, and sd_journal_next3 (or a similar call) needs to be called before entries can be read again. sd_journal_add_disjunction() may be used to insert a disjunction (i.e. logical OR) in the match list. If this call is invoked, all previously added matches since the last invocation of sd_journal_add_disjunction() or sd_journal_add_conjunction() are combined in an OR with all matches added afterwards, until sd_journal_add_disjunction() or sd_journal_add_conjunction() is invoked again to begin the next OR or AND term. sd_journal_add_conjunction() may be used to insert a conjunction (i.e. logical AND) in the match list. If this call is invoked, all previously added matches since the last invocation of sd_journal_add_conjunction() are combined in an AND with all matches added afterwards, until sd_journal_add_conjunction() is invoked again to begin the next AND term. The combination of sd_journal_add_match(), sd_journal_add_disjunction() and sd_journal_add_conjunction() may be used to build complex search terms, even though full logical expressions are not available. Note that sd_journal_add_conjunction() operates one level 'higher' than sd_journal_add_disjunction(). It is hence possible to build an expression of AND terms, consisting of OR terms, consisting of AND terms, consisting of OR terms of matches (the latter OR expression is implicitly created for matches with the same field name, see above). sd_journal_flush_matches() may be used to flush all matches, disjunction and conjunction terms again. After this call all filtering is removed and all entries in the journal will be iterated again. Note that filtering via matches only applies to the way the journal is read, it has no effect on storage on disk. Return Value sd_journal_add_match(), sd_journal_add_disjunction() and sd_journal_add_conjunction() return 0 on success or a negative errno-style error code. sd_journal_flush_matches() returns nothing. Notes The sd_journal_add_match(), sd_journal_add_disjunction(), sd_journal_add_conjunction() and sd_journal_flush_matches() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. Examples The following example adds matches to a journal context object to iterate only through messages generated by the Avahi service at the four error log levels, plus all messages of the message ID 03bb1dab98ab4ecfbf6fff2738bdd964 coming from any service (this example lacks the necessary error checking): ... int add_matches(sd_journal *j) { sd_journal_add_match(j, "_SYSTEMD_UNIT=avahi-daemon.service", 0); sd_journal_add_match(j, "PRIORITY=0", 0); sd_journal_add_match(j, "PRIORITY=1", 0); sd_journal_add_match(j, "PRIORITY=2", 0); sd_journal_add_match(j, "PRIORITY=3", 0); sd_journal_add_disjunction(j); sd_journal_add_match(j, "MESSAGE_ID=03bb1dab98ab4ecfbf6fff2738bdd964", 0); } See Also systemd1, sd-journal3, sd_journal_open3, sd_journal_next3, sd_journal_get_data3, systemd.journal-fields7 systemd-229/man/sd_journal_enumerate_fields.xml000066400000000000000000000145751265713322000221250ustar00rootroot00000000000000 sd_journal_enumerate_fields systemd Developer Lennart Poettering lennart@poettering.net sd_journal_enumerate_fields 3 sd_journal_enumerate_fields sd_journal_restart_fields SD_JOURNAL_FOREACH_FIELD Read used field names from the journal #include <systemd/sd-journal.h> int sd_journal_enumerate_fields sd_journal *j const char **field void sd_journal_restart_fields sd_journal *j SD_JOURNAL_FOREACH_FIELD sd_journal *j const char *field Description sd_journal_enumerate_fields() may be used to iterate through all field names used in the opened journal files. On each invocation the next field name is returned. The order of the returned field names is not defined. It takes two arguments: the journal context object, plus a pointer to a constant string pointer where the field name is stored in. The returned data is in a read-only memory map and is only valid until the next invocation of sd_journal_enumerate_fields(). Note that this call is subject to the data field size threshold as controlled by sd_journal_set_data_threshold(). sd_journal_restart_fields() resets the field name enumeration index to the beginning of the list. The next invocation of sd_journal_enumerate_fields() will return the first field name again. The SD_JOURNAL_FOREACH_FIELD() macro may be used as a handy wrapper around sd_journal_restart_fields() and sd_journal_enumerate_fields(). These functions currently are not influenced by matches set with sd_journal_add_match() but this might change in a later version of this software. To retrieve the possible values a specific field can take use sd_journal_query_unique3. Return Value sd_journal_enumerate_fields() returns a positive integer if the next field name has been read, 0 when no more field names are known, or a negative errno-style error code. sd_journal_restart_fields() returns nothing. Notes The sd_journal_enumerate_fields() and sd_journal_restart_fields() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. Examples Use the SD_JOURNAL_FOREACH_FIELD macro to iterate through all field names in use in the current journal. #include <stdio.h> #include <string.h> #include <systemd/sd-journal.h> int main(int argc, char *argv[]) { sd_journal *j; const char *field; int r; r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); if (r < 0) { fprintf(stderr, "Failed to open journal: %s\n", strerror(-r)); return 1; } SD_JOURNAL_FOREACH_FIELD(j, field) printf("%s\n", field); sd_journal_close(j); return 0; } See Also systemd1, systemd.journal-fields7, sd-journal3, sd_journal_open3, sd_journal_query_unique3, sd_journal_get_data3, sd_journal_add_match3 systemd-229/man/sd_journal_get_catalog.xml000066400000000000000000000123361265713322000210540ustar00rootroot00000000000000 sd_journal_get_catalog systemd Developer Lennart Poettering lennart@poettering.net sd_journal_get_catalog 3 sd_journal_get_catalog sd_journal_get_catalog_for_message_id Retrieve message catalog entry #include <systemd/sd-journal.h> int sd_journal_get_catalog sd_journal *j char **ret int sd_journal_get_catalog_for_message_id sd_id128_t id char **ret Description sd_journal_get_catalog() retrieves a message catalog entry for the current journal entry. This will look up an entry in the message catalog by using the MESSAGE_ID= field of the current journal entry. Before returning the entry all journal field names in the catalog entry text enclosed in "@" will be replaced by the respective field values of the current entry. If a field name referenced in the message catalog entry does not exist, in the current journal entry, the "@" will be removed, but the field name otherwise left untouched. sd_journal_get_catalog_for_message_id() works similar to sd_journal_get_catalog() but the entry is looked up by the specified message ID (no open journal context is necessary for this), and no field substitution is performed. For more information about the journal message catalog please refer to the Journal Message Catalogs documentation page. Return Value sd_journal_get_catalog() and sd_journal_get_catalog_for_message_id() return 0 on success or a negative errno-style error code. If no matching message catalog entry is found, -ENOENT is returned. On successful return, ret points to a new string, which must be freed with free3. Notes The sd_journal_get_catalog() and sd_journal_get_catalog_for_message_id() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, systemd.journal-fields7, sd-journal3, sd_journal_open3, sd_journal_next3, sd_journal_get_data3, malloc3 systemd-229/man/sd_journal_get_cursor.xml000066400000000000000000000133611265713322000207560ustar00rootroot00000000000000 sd_journal_get_cursor systemd Developer Lennart Poettering lennart@poettering.net sd_journal_get_cursor 3 sd_journal_get_cursor sd_journal_test_cursor Get cursor string for or test cursor string against the current journal entry #include <systemd/sd-journal.h> int sd_journal_get_cursor sd_journal *j char **cursor int sd_journal_test_cursor sd_journal *j const char *cursor Description sd_journal_get_cursor() returns a cursor string for the current journal entry. A cursor is a serialization of the current journal position formatted as text. The string only contains printable characters and can be passed around in text form. The cursor identifies a journal entry globally and in a stable way and may be used to later seek to it via sd_journal_seek_cursor3. The cursor string should be considered opaque and not be parsed by clients. Seeking to a cursor position without the specific entry being available locally will seek to the next closest (in terms of time) available entry. The call takes two arguments: a journal context object and a pointer to a string pointer where the cursor string will be placed. The string is allocated via libc malloc3 and should be freed after use with free3. Note that sd_journal_get_cursor() will not work before sd_journal_next3 (or related call) has been called at least once, in order to position the read pointer at a valid entry. sd_journal_test_cursor() may be used to check whether the current position in the journal matches the specified cursor. This is useful since cursor strings do not uniquely identify an entry: the same entry might be referred to by multiple different cursor strings, and hence string comparing cursors is not possible. Use this call to verify after an invocation of sd_journal_seek_cursor3 whether the entry being sought to was actually found in the journal or the next closest entry was used instead. Return Value sd_journal_get_cursor() returns 0 on success or a negative errno-style error code. sd_journal_test_cursor() returns positive if the current entry matches the specified cursor, 0 if it does not match the specified cursor or a negative errno-style error code on failure. Notes The sd_journal_get_cursor() and sd_journal_test_cursor() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-journal3, sd_journal_open3, sd_journal_seek_cursor3 systemd-229/man/sd_journal_get_cutoff_realtime_usec.xml000066400000000000000000000137721265713322000236360ustar00rootroot00000000000000 sd_journal_get_cutoff_realtime_usec systemd Developer Lennart Poettering lennart@poettering.net sd_journal_get_cutoff_realtime_usec 3 sd_journal_get_cutoff_realtime_usec sd_journal_get_cutoff_monotonic_usec Read cut-off timestamps from the current journal entry #include <systemd/sd-journal.h> int sd_journal_get_cutoff_realtime_usec sd_journal *j uint64_t *from uint64_t *to int sd_journal_get_cutoff_monotonic_usec sd_journal *j sd_id128_t boot_id uint64_t *from uint64_t *to Description sd_journal_get_cutoff_realtime_usec() retrieves the realtime (wallclock) timestamps of the first and last entries accessible in the journal. It takes three arguments: the journal context object j and two pointers from and to pointing at 64-bit unsigned integers to store the timestamps in. The timestamps are in microseconds since the epoch, i.e. CLOCK_REALTIME. Either one of the two timestamp arguments may be passed as NULL in case the timestamp is not needed, but not both. sd_journal_get_cutoff_monotonic_usec() retrieves the monotonic timestamps of the first and last entries accessible in the journal. It takes three arguments: the journal context object j, a 128-bit identifier for the boot boot_id, and two pointers to 64-bit unsigned integers to store the timestamps, from and to. The timestamps are in microseconds since boot-up of the specific boot, i.e. CLOCK_MONOTONIC. Since the monotonic clock begins new with every reboot it only defines a well-defined point in time when used together with an identifier identifying the boot, see sd_id128_get_boot3 for more information. The function will return the timestamps for the boot identified by the passed boot ID. Either one of the two timestamp arguments may be passed as NULL in case the timestamp is not needed, but not both. Return Value sd_journal_get_cutoff_realtime_usec() and sd_journal_get_cutoff_monotonic_usec() return 1 on success, 0 if not suitable entries are in the journal or a negative errno-style error code. Locations pointed to by parameters from and to will be set only if the return value is positive, and obviously, the parameters are non-null. Notes The sd_journal_get_cutoff_realtime_usec() and sd_journal_get_cutoff_monotonic_usec() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-journal3, sd_journal_open3, sd_journal_get_realtime_usec3, sd_id128_get_boot3, clock_gettime2 systemd-229/man/sd_journal_get_data.xml000066400000000000000000000237331265713322000203560ustar00rootroot00000000000000 sd_journal_get_data systemd Developer Lennart Poettering lennart@poettering.net sd_journal_get_data 3 sd_journal_get_data sd_journal_enumerate_data sd_journal_restart_data SD_JOURNAL_FOREACH_DATA sd_journal_set_data_threshold sd_journal_get_data_threshold Read data fields from the current journal entry #include <systemd/sd-journal.h> int sd_journal_get_data sd_journal *j const char *field const void **data size_t *length int sd_journal_enumerate_data sd_journal *j const void **data size_t *length void sd_journal_restart_data sd_journal *j SD_JOURNAL_FOREACH_DATA sd_journal *j const void *data size_t length int sd_journal_set_data_threshold sd_journal *j size_t sz int sd_journal_get_data_threshold sd_journal *j size_t *sz Description sd_journal_get_data() gets the data object associated with a specific field from the current journal entry. It takes four arguments: the journal context object, a string with the field name to request, plus a pair of pointers to pointer/size variables where the data object and its size shall be stored in. The field name should be an entry field name. Well-known field names are listed in systemd.journal-fields7. The returned data is in a read-only memory map and is only valid until the next invocation of sd_journal_get_data() or sd_journal_enumerate_data(), or the read pointer is altered. Note that the data returned will be prefixed with the field name and '='. Also note that, by default, data fields larger than 64K might get truncated to 64K. This threshold may be changed and turned off with sd_journal_set_data_threshold() (see below). sd_journal_enumerate_data() may be used to iterate through all fields of the current entry. On each invocation the data for the next field is returned. The order of these fields is not defined. The data returned is in the same format as with sd_journal_get_data() and also follows the same life-time semantics. sd_journal_restart_data() resets the data enumeration index to the beginning of the entry. The next invocation of sd_journal_enumerate_data() will return the first field of the entry again. Note that the SD_JOURNAL_FOREACH_DATA() macro may be used as a handy wrapper around sd_journal_restart_data() and sd_journal_enumerate_data(). Note that these functions will not work before sd_journal_next3 (or related call) has been called at least once, in order to position the read pointer at a valid entry. sd_journal_set_data_threshold() may be used to change the data field size threshold for data returned by sd_journal_get_data(), sd_journal_enumerate_data() and sd_journal_enumerate_unique(). This threshold is a hint only: it indicates that the client program is interested only in the initial parts of the data fields, up to the threshold in size -- but the library might still return larger data objects. That means applications should not rely exclusively on this setting to limit the size of the data fields returned, but need to apply a explicit size limit on the returned data as well. This threshold defaults to 64K by default. To retrieve the complete data fields this threshold should be turned off by setting it to 0, so that the library always returns the complete data objects. It is recommended to set this threshold as low as possible since this relieves the library from having to decompress large compressed data objects in full. sd_journal_get_data_threshold() returns the currently configured data field size threshold. Return Value sd_journal_get_data() returns 0 on success or a negative errno-style error code. If the current entry does not include the specified field, -ENOENT is returned. If sd_journal_next3 has not been called at least once, -EADDRNOTAVAIL is returned. sd_journal_enumerate_data() returns a positive integer if the next field has been read, 0 when no more fields are known, or a negative errno-style error code. sd_journal_restart_data() returns nothing. sd_journal_set_data_threshold() and sd_journal_get_threshold() return 0 on success or a negative errno-style error code. Notes The sd_journal_get_data(), sd_journal_enumerate_data(), sd_journal_restart_data(), sd_journal_set_data_threshold() and sd_journal_get_data_threshold() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. Examples See sd_journal_next3 for a complete example how to use sd_journal_get_data(). Use the SD_JOURNAL_FOREACH_DATA macro to iterate through all fields of the current journal entry: ... int print_fields(sd_journal *j) { const void *data; size_t length; SD_JOURNAL_FOREACH_DATA(j, data, length) printf("%.*s\n", (int) length, data); } ... See Also systemd1, systemd.journal-fields7, sd-journal3, sd_journal_open3, sd_journal_next3, sd_journal_get_realtime_usec3, sd_journal_query_unique3 systemd-229/man/sd_journal_get_fd.xml000066400000000000000000000312611265713322000200310ustar00rootroot00000000000000 sd_journal_get_fd systemd Developer Lennart Poettering lennart@poettering.net sd_journal_get_fd 3 sd_journal_get_fd sd_journal_get_events sd_journal_get_timeout sd_journal_process sd_journal_wait sd_journal_reliable_fd SD_JOURNAL_NOP SD_JOURNAL_APPEND SD_JOURNAL_INVALIDATE Journal change notification interface #include <systemd/sd-journal.h> int sd_journal_get_fd sd_journal *j int sd_journal_get_events sd_journal *j int sd_journal_get_timeout sd_journal *j uint64_t *timeout_usec int sd_journal_process sd_journal *j int sd_journal_wait sd_journal *j uint64_t timeout_usec int sd_journal_reliable_fd sd_journal *j Description sd_journal_get_fd() returns a file descriptor that may be asynchronously polled in an external event loop and is signaled as soon as the journal changes, because new entries or files were added, rotation took place, or files have been deleted, and similar. The file descriptor is suitable for usage in poll2. Use sd_journal_get_events() for an events mask to watch for. The call takes one argument: the journal context object. Note that not all file systems are capable of generating the necessary events for wakeups from this file descriptor for changes to be noticed immediately. In particular network files systems do not generate suitable file change events in all cases. Cases like this can be detected with sd_journal_reliable_fd(), below. sd_journal_get_timeout() will ensure in these cases that wake-ups happen frequently enough for changes to be noticed, although with a certain latency. sd_journal_get_events() will return the poll() mask to wait for. This function will return a combination of POLLIN and POLLOUT and similar to fill into the .events field of struct pollfd. sd_journal_get_timeout() will return a timeout value for usage in poll(). This returns a value in microseconds since the epoch of CLOCK_MONOTONIC for timing out poll() in timeout_usec. See clock_gettime2 for details about CLOCK_MONOTONIC. If there is no timeout to wait for, this will fill in (uint64_t) -1 instead. Note that poll() takes a relative timeout in milliseconds rather than an absolute timeout in microseconds. To convert the absolute 'us' timeout into relative 'ms', use code like the following: uint64_t t; int msec; sd_journal_get_timeout(m, &t); if (t == (uint64_t) -1) msec = -1; else { struct timespec ts; uint64_t n; clock_getttime(CLOCK_MONOTONIC, &ts); n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000; msec = t > n ? (int) ((t - n + 999) / 1000) : 0; } The code above does not do any error checking for brevity's sake. The calculated msec integer can be passed directly as poll()'s timeout parameter. After each poll() wake-up sd_journal_process() needs to be called to process events. This call will also indicate what kind of change has been detected (see below; note that spurious wake-ups are possible). A synchronous alternative for using sd_journal_get_fd(), sd_journal_get_events(), sd_journal_get_timeout() and sd_journal_process() is sd_journal_wait(). It will synchronously wait until the journal gets changed. The maximum time this call sleeps may be controlled with the timeout_usec parameter. Pass (uint64_t) -1 to wait indefinitely. Internally this call simply combines sd_journal_get_fd(), sd_journal_get_events(), sd_journal_get_timeout(), poll() and sd_journal_process() into one. sd_journal_reliable_fd() may be used to check whether the wakeup events from the file descriptor returned by sd_journal_get_fd() are known to be immediately triggered. On certain file systems where file change events from the OS are not available (such as NFS) changes need to be polled for repeatedly, and hence are detected only with a certain latency. This call will return a positive value if the journal changes are detected immediately and zero when they need to be polled for and hence might be noticed only with a certain latency. Note that there is usually no need to invoke this function directly as sd_journal_get_timeout() on these file systems will ask for timeouts explicitly anyway. Return Value sd_journal_get_fd() returns a valid file descriptor on success or a negative errno-style error code. sd_journal_get_events() returns a combination of POLLIN, POLLOUT and suchlike on success or a negative errno-style error code. sd_journal_reliable_fd() returns a positive integer if the file descriptor returned by sd_journal_get_fd() will generate wake-ups immediately for all journal changes. Returns 0 if there might be a latency involved. sd_journal_process() and sd_journal_wait() return one of SD_JOURNAL_NOP, SD_JOURNAL_APPEND or SD_JOURNAL_INVALIDATE on success or a negative errno-style error code. If SD_JOURNAL_NOP is returned, the journal did not change since the last invocation. If SD_JOURNAL_APPEND is returned, new entries have been appended to the end of the journal. If SD_JOURNAL_INVALIDATE, journal files were added or removed (possibly due to rotation). In the latter event, live-view UIs should probably refresh their entire display, while in the case of SD_JOURNAL_APPEND, it is sufficient to simply continue reading at the previous end of the journal. Notes The sd_journal_get_fd(), sd_journal_get_events(), sd_journal_reliable_fd(), sd_journal_process() and sd_journal_wait() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. Examples Iterating through the journal, in a live view tracking all changes: #include <stdio.h> #include <string.h> #include <systemd/sd-journal.h> int main(int argc, char *argv[]) { int r; sd_journal *j; r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); if (r < 0) { fprintf(stderr, "Failed to open journal: %s\n", strerror(-r)); return 1; } for (;;) { const void *d; size_t l; r = sd_journal_next(j); if (r < 0) { fprintf(stderr, "Failed to iterate to next entry: %s\n", strerror(-r)); break; } if (r == 0) { /* Reached the end, let's wait for changes, and try again */ r = sd_journal_wait(j, (uint64_t) -1); if (r < 0) { fprintf(stderr, "Failed to wait for changes: %s\n", strerror(-r)); break; } continue; } r = sd_journal_get_data(j, "MESSAGE", &d, &l); if (r < 0) { fprintf(stderr, "Failed to read message field: %s\n", strerror(-r)); continue; } printf("%.*s\n", (int) l, (const char*) d); } sd_journal_close(j); return 0; } Waiting with poll() (this example lacks all error checking for the sake of simplicity): #include <poll.h> #include <systemd/sd-journal.h> int wait_for_changes(sd_journal *j) { struct pollfd pollfd; int msec; sd_journal_get_timeout(m, &t); if (t == (uint64_t) -1) msec = -1; else { struct timespec ts; uint64_t n; clock_getttime(CLOCK_MONOTONIC, &ts); n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000; msec = t > n ? (int) ((t - n + 999) / 1000) : 0; } pollfd.fd = sd_journal_get_fd(j); pollfd.events = sd_journal_get_events(j); poll(&pollfd, 1, msec); return sd_journal_process(j); } See Also systemd1, sd-journal3, sd_journal_open3, sd_journal_next3, poll2, clock_gettime2 systemd-229/man/sd_journal_get_realtime_usec.xml000066400000000000000000000135101265713322000222560ustar00rootroot00000000000000 sd_journal_get_realtime_usec systemd Developer Lennart Poettering lennart@poettering.net sd_journal_get_realtime_usec 3 sd_journal_get_realtime_usec sd_journal_get_monotonic_usec Read timestamps from the current journal entry #include <systemd/sd-journal.h> int sd_journal_get_realtime_usec sd_journal *j uint64_t *usec int sd_journal_get_monotonic_usec sd_journal *j uint64_t *usec sd_id128_t *boot_id Description sd_journal_get_realtime_usec() gets the realtime (wallclock) timestamp of the current journal entry. It takes two arguments: the journal context object and a pointer to a 64-bit unsigned integer to store the timestamp in. The timestamp is in microseconds since the epoch, i.e. CLOCK_REALTIME. sd_journal_get_monotonic_usec() gets the monotonic timestamp of the current journal entry. It takes three arguments: the journal context object, a pointer to a 64-bit unsigned integer to store the timestamp in, as well as a 128-bit ID buffer to store the boot ID of the monotonic timestamp. The timestamp is in microseconds since boot-up of the specific boot, i.e. CLOCK_MONOTONIC. Since the monotonic clock begins new with every reboot, it only defines a well-defined point in time when used together with an identifier identifying the boot. See sd_id128_get_boot3 for more information. If the boot ID parameter is passed NULL, the function will fail if the monotonic timestamp of the current entry is not of the current system boot. Note that these functions will not work before sd_journal_next3 (or related call) has been called at least once, in order to position the read pointer at a valid entry. Return Value sd_journal_get_realtime_usec() and sd_journal_get_monotonic_usec() returns 0 on success or a negative errno-style error code. If the boot ID parameter was passed NULL and the monotonic timestamp of the current journal entry is not of the current system boot, -ESTALE is returned by sd_journal_get_monotonic_usec(). Notes The sd_journal_get_realtime_usec() and sd_journal_get_monotonic_usec() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-journal3, sd_journal_open3, sd_journal_next3, sd_journal_get_data3, sd_id128_get_boot3, clock_gettime2, sd_journal_get_cutoff_realtime_usec3 systemd-229/man/sd_journal_get_usage.xml000066400000000000000000000063021265713322000205420ustar00rootroot00000000000000 sd_journal_get_usage systemd Developer Lennart Poettering lennart@poettering.net sd_journal_get_usage 3 sd_journal_get_usage Journal disk usage #include <systemd/sd-journal.h> int sd_journal_get_usage sd_journal *j uint64_t *bytes Description sd_journal_get_usage() determines the total disk space currently used by journal files (in bytes). If SD_JOURNAL_LOCAL_ONLY was passed when opening the journal, this value will only reflect the size of journal files of the local host, otherwise of all hosts. Return Value sd_journal_get_usage() returns 0 on success or a negative errno-style error code. Notes The sd_journal_get_usage() interface is available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-journal3, sd_journal_open3, systemd-229/man/sd_journal_has_runtime_files.xml000066400000000000000000000057721265713322000223110ustar00rootroot00000000000000 sd_journal_has_runtime_files systemd Developer Jan Synáček jan.synacek@gmail.com sd_journal_has_runtime_files 3 sd_journal_has_runtime_files sd_journal_has_persistent_files Query availability of runtime or persistent journal files. #include <systemd/sd-journal.h> int sd_journal_has_runtime_files sd_journal *j int sd_journal_has_persistent_files sd_journal *j Description sd_journal_has_runtime_files() returns a positive value if runtime journal files (present in /run/systemd/journal/) have been found. Otherwise returns 0. sd_journal_has_persistent_files() returns a positive value if persistent journal files (present in /var/log/journal/) have been found. Otherwise returns 0. Return value Both sd_journal_has_runtime_files() and sd_journal_has_persistent_files() return -EINVAL if their argument is NULL. See Also sd-journal3 systemd-229/man/sd_journal_next.xml000066400000000000000000000167761265713322000175750ustar00rootroot00000000000000 sd_journal_next systemd Developer Lennart Poettering lennart@poettering.net sd_journal_next 3 sd_journal_next sd_journal_previous sd_journal_next_skip sd_journal_previous_skip SD_JOURNAL_FOREACH SD_JOURNAL_FOREACH_BACKWARDS Advance or set back the read pointer in the journal #include <systemd/sd-journal.h> int sd_journal_next sd_journal *j int sd_journal_previous sd_journal *j int sd_journal_next_skip sd_journal *j uint64_t skip int sd_journal_previous_skip sd_journal *j uint64_t skip SD_JOURNAL_FOREACH sd_journal *j SD_JOURNAL_FOREACH_BACKWARDS sd_journal *j Description sd_journal_next() advances the read pointer into the journal by one entry. The only argument taken is a journal context object as allocated via sd_journal_open3. After successful invocation the entry may be read with functions such as sd_journal_get_data3. Similarly, sd_journal_previous() sets the read pointer back one entry. sd_journal_next_skip() and sd_journal_previous_skip() advance/set back the read pointer by multiple entries at once, as specified in the skip parameter. The journal is strictly ordered by reception time, and hence advancing to the next entry guarantees that the entry then pointing to is later in time than then previous one, or has the same timestamp. Note that sd_journal_get_data3 and related calls will fail unless sd_journal_next() has been invoked at least once in order to position the read pointer on a journal entry. Note that the SD_JOURNAL_FOREACH() macro may be used as a wrapper around sd_journal_seek_head3 and sd_journal_next() in order to make iterating through the journal easier. See below for an example. Similarly, SD_JOURNAL_FOREACH_BACKWARDS() may be used for iterating the journal in reverse order. Return Value The four calls return the number of entries advanced/set back on success or a negative errno-style error code. When the end or beginning of the journal is reached, a number smaller than requested is returned. More specifically, if sd_journal_next() or sd_journal_previous() reach the end/beginning of the journal they will return 0, instead of 1 when they are successful. This should be considered an EOF marker. Notes The sd_journal_next(), sd_journal_previous(), sd_journal_next_skip() and sd_journal_previous_skip() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. Examples Iterating through the journal: #include <stdio.h> #include <string.h> #include <systemd/sd-journal.h> int main(int argc, char *argv[]) { int r; sd_journal *j; r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); if (r < 0) { fprintf(stderr, "Failed to open journal: %s\n", strerror(-r)); return 1; } SD_JOURNAL_FOREACH(j) { const char *d; size_t l; r = sd_journal_get_data(j, "MESSAGE", (const void **)&d, &l); if (r < 0) { fprintf(stderr, "Failed to read message field: %s\n", strerror(-r)); continue; } printf("%.*s\n", (int) l, d); } sd_journal_close(j); return 0; } See Also systemd1, sd-journal3, sd_journal_open3, sd_journal_get_data3, sd_journal_get_realtime_usec3, sd_journal_get_cursor3 systemd-229/man/sd_journal_open.xml000066400000000000000000000241761265713322000175510ustar00rootroot00000000000000 sd_journal_open systemd Developer Lennart Poettering lennart@poettering.net sd_journal_open 3 sd_journal_open sd_journal_open_directory sd_journal_open_files sd_journal_open_container sd_journal_close sd_journal SD_JOURNAL_LOCAL_ONLY SD_JOURNAL_RUNTIME_ONLY SD_JOURNAL_SYSTEM SD_JOURNAL_CURRENT_USER Open the system journal for reading #include <systemd/sd-journal.h> int sd_journal_open sd_journal **ret int flags int sd_journal_open_directory sd_journal **ret const char *path int flags int sd_journal_open_files sd_journal **ret const char **paths int flags int sd_journal_open_container sd_journal **ret const char *machine int flags void sd_journal_close sd_journal *j Description sd_journal_open() opens the log journal for reading. It will find all journal files automatically and interleave them automatically when reading. As first argument it takes a pointer to a sd_journal pointer, which, on success, will contain a journal context object. The second argument is a flags field, which may consist of the following flags ORed together: SD_JOURNAL_LOCAL_ONLY makes sure only journal files generated on the local machine will be opened. SD_JOURNAL_RUNTIME_ONLY makes sure only volatile journal files will be opened, excluding those which are stored on persistent storage. SD_JOURNAL_SYSTEM will cause journal files of system services and the kernel (in opposition to user session processes) to be opened. SD_JOURNAL_CURRENT_USER will cause journal files of the current user to be opened. If neither SD_JOURNAL_SYSTEM nor SD_JOURNAL_CURRENT_USER are specified, all journal file types will be opened. sd_journal_open_directory() is similar to sd_journal_open() but takes an absolute directory path as argument. All journal files in this directory will be opened and interleaved automatically. This call also takes a flags argument, but it must be passed as 0 as no flags are currently understood for this call. sd_journal_open_files() is similar to sd_journal_open() but takes a NULL-terminated list of file paths to open. All files will be opened and interleaved automatically. This call also takes a flags argument, but it must be passed as 0 as no flags are currently understood for this call. Please note that in the case of a live journal, this function is only useful for debugging, because individual journal files can be rotated at any moment, and the opening of specific files is inherently racy. sd_journal_open_container() is similar to sd_journal_open() but opens the journal files of a running OS container. The specified machine name refers to a container that is registered with systemd-machined8. sd_journal objects cannot be used in the child after a fork. Functions which take a journal object as an argument (sd_journal_next() and others) will return -ECHILD after a fork. sd_journal_close() will close the journal context allocated with sd_journal_open() or sd_journal_open_directory() and free its resources. When opening the journal only journal files accessible to the calling user will be opened. If journal files are not accessible to the caller, this will be silently ignored. See sd_journal_next3 for an example of how to iterate through the journal after opening it with sd_journal_open(). A journal context object returned by sd_journal_open() references a specific journal entry as current entry, similar to a file seek index in a classic file system file, but without absolute positions. It may be altered with sd_journal_next3 and sd_journal_seek_head3 and related calls. The current entry position may be exported in cursor strings, as accessible via sd_journal_get_cursor3. Cursor strings may be used to globally identify a specific journal entry in a stable way and then later to seek to it (or if the specific entry is not available locally, to its closest entry in time) sd_journal_seek_cursor3. Notification of journal changes is available via sd_journal_get_fd() and related calls. Return Value The sd_journal_open(), sd_journal_open_directory(), and sd_journal_open_files() calls return 0 on success or a negative errno-style error code. sd_journal_close() returns nothing. Notes The sd_journal_open(), sd_journal_open_directory() and sd_journal_close() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. History sd_journal_open(), sd_journal_close(), SD_JOURNAL_LOCAL_ONLY, SD_JOURNAL_RUNTIME_ONLY, SD_JOURNAL_SYSTEM_ONLY were added in systemd-38. sd_journal_open_directory() was added in systemd-187. SD_JOURNAL_SYSTEM, SD_JOURNAL_CURRENT_USER, and sd_journal_open_files() were added in systemd-205. SD_JOURNAL_SYSTEM_ONLY was deprecated. See Also systemd1, sd-journal3, sd_journal_next3, sd_journal_get_data3, systemd-machined8 systemd-229/man/sd_journal_print.xml000066400000000000000000000267071265713322000177460ustar00rootroot00000000000000 sd_journal_print systemd Developer Lennart Poettering lennart@poettering.net sd_journal_print 3 sd_journal_print sd_journal_printv sd_journal_send sd_journal_sendv sd_journal_perror SD_JOURNAL_SUPPRESS_LOCATION Submit log entries to the journal #include <systemd/sd-journal.h> int sd_journal_print int priority const char *format ... int sd_journal_printv int priority const char *format va_list ap int sd_journal_send const char *format ... int sd_journal_sendv const struct iovec *iov int n int sd_journal_perror const char *message Description sd_journal_print() may be used to submit simple, plain text log entries to the system journal. The first argument is a priority value. This is followed by a format string and its parameters, similar to printf3 or syslog3. The priority value is one of LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG, as defined in syslog.h, see syslog3 for details. It is recommended to use this call to submit log messages in the application locale or system locale and in UTF-8 format, but no such restrictions are enforced. sd_journal_printv() is similar to sd_journal_print() but takes a variable argument list encapsulated in an object of type va_list (see stdarg3 for more information) instead of the format string. It is otherwise equivalent in behavior. sd_journal_send() may be used to submit structured log entries to the system journal. It takes a series of format strings, each immediately followed by their associated parameters, terminated by NULL. The strings passed should be of the format VARIABLE=value. The variable name must be in uppercase and consist only of characters, numbers and underscores, and may not begin with an underscore. (All assignments that do not follow this syntax will be ignored.) The value can be of any size and format. It is highly recommended to submit text strings formatted in the UTF-8 character encoding only, and submit binary fields only when formatting in UTF-8 strings is not sensible. A number of well-known fields are defined, see systemd.journal-fields7 for details, but additional application defined fields may be used. A variable may be assigned more than one value per entry. sd_journal_sendv() is similar to sd_journal_send() but takes an array of struct iovec (as defined in uio.h, see readv3 for details) instead of the format string. Each structure should reference one field of the entry to submit. The second argument specifies the number of structures in the array. sd_journal_sendv() is particularly useful to submit binary objects to the journal where that is necessary. sd_journal_perror() is a similar to perror3 and writes a message to the journal that consists of the passed string, suffixed with ": " and a human-readable representation of the current error code stored in errno3. If the message string is passed as NULL or empty string, only the error string representation will be written, prefixed with nothing. An additional journal field ERRNO= is included in the entry containing the numeric error code formatted as decimal string. The log priority used is LOG_ERR (3). Note that sd_journal_send() is a wrapper around sd_journal_sendv() to make it easier to use when only text strings shall be submitted. Also, the following two calls are mostly equivalent: sd_journal_print(LOG_INFO, "Hello World, this is PID %lu!", (unsigned long) getpid()); sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(), "PRIORITY=%i", LOG_INFO, NULL); Note that these calls implicitly add fields for the source file, function name and code line where invoked. This is implemented with macros. If this is not desired, it can be turned off by defining SD_JOURNAL_SUPPRESS_LOCATION before including sd-journal.h. syslog3 and sd_journal_print() may largely be used interchangeably functionality-wise. However, note that log messages logged via the former take a different path to the journal server than the later, and hence global chronological ordering between the two streams cannot be guaranteed. Using sd_journal_print() has the benefit of logging source code line, filenames, and functions as metadata along all entries, and guaranteeing chronological ordering with structured log entries that are generated via sd_journal_send(). Using syslog() has the benefit of being more portable. Return Value The four calls return 0 on success or a negative errno-style error code. The errno3 variable itself is not altered. If systemd-journald8 is not running (the socket is not present), those functions do nothing, and also return 0. Async signal safety sd_journal_sendv() is "async signal safe" in the meaning of signal7. sd_journal_print, sd_journal_printv, sd_journal_send, and sd_journal_perror are not async signal safe. Notes The sd_journal_print(), sd_journal_printv(), sd_journal_send() and sd_journal_sendv() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-journal3, sd_journal_stream_fd3, syslog3, perror3, errno3, systemd.journal-fields7, signal7, socket7 systemd-229/man/sd_journal_query_unique.xml000066400000000000000000000205751265713322000213420ustar00rootroot00000000000000 sd_journal_query_unique systemd Developer Lennart Poettering lennart@poettering.net sd_journal_query_unique 3 sd_journal_query_unique sd_journal_enumerate_unique sd_journal_restart_unique SD_JOURNAL_FOREACH_UNIQUE Read unique data fields from the journal #include <systemd/sd-journal.h> int sd_journal_query_unique sd_journal *j const char *field int sd_journal_enumerate_unique sd_journal *j const void **data size_t *length void sd_journal_restart_unique sd_journal *j SD_JOURNAL_FOREACH_UNIQUE sd_journal *j const void *data size_t length Description sd_journal_query_unique() queries the journal for all unique values the specified field can take. It takes two arguments: the journal to query and the field name to look for. Well-known field names are listed on systemd.journal-fields7. Field names must be specified without a trailing '='. After this function has been executed successfully the field values may be queried using sd_journal_enumerate_unique(). Invoking this call a second time will change the field name being queried and reset the enumeration index to the first field value that matches. sd_journal_enumerate_unique() may be used to iterate through all data fields which match the previously selected field name as set with sd_journal_query_unique(). On each invocation the next field data matching the field name is returned. The order of the returned data fields is not defined. It takes three arguments: the journal context object, plus a pair of pointers to pointer/size variables where the data object and its size shall be stored in. The returned data is in a read-only memory map and is only valid until the next invocation of sd_journal_enumerate_unique(). Note that the data returned will be prefixed with the field name and '='. Note that this call is subject to the data field size threshold as controlled by sd_journal_set_data_threshold(). sd_journal_restart_unique() resets the data enumeration index to the beginning of the list. The next invocation of sd_journal_enumerate_unique() will return the first field data matching the field name again. Note that the SD_JOURNAL_FOREACH_UNIQUE() macro may be used as a handy wrapper around sd_journal_restart_unique() and sd_journal_enumerate_unique(). Note that these functions currently are not influenced by matches set with sd_journal_add_match() but this might change in a later version of this software. To enumerate all field names currently in use (and thus all suitable field parameters for sd_journal_query_unique()), use the sd_journal_enumerate_fields3 call. Return Value sd_journal_query_unique() returns 0 on success or a negative errno-style error code. sd_journal_enumerate_unique() returns a positive integer if the next field data has been read, 0 when no more fields are known, or a negative errno-style error code. sd_journal_restart_unique() returns nothing. Notes The sd_journal_query_unique(), sd_journal_enumerate_unique() and sd_journal_restart_unique() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. Examples Use the SD_JOURNAL_FOREACH_UNIQUE macro to iterate through all values a field of the journal can take. The following example lists all unit names referenced in the journal: #include <stdio.h> #include <string.h> #include <systemd/sd-journal.h> int main(int argc, char *argv[]) { sd_journal *j; const void *d; size_t l; int r; r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); if (r < 0) { fprintf(stderr, "Failed to open journal: %s\n", strerror(-r)); return 1; } r = sd_journal_query_unique(j, "_SYSTEMD_UNIT"); if (r < 0) { fprintf(stderr, "Failed to query journal: %s\n", strerror(-r)); return 1; } SD_JOURNAL_FOREACH_UNIQUE(j, d, l) printf("%.*s\n", (int) l, (const char*) d); sd_journal_close(j); return 0; } See Also systemd1, systemd.journal-fields7, sd-journal3, sd_journal_open3, sd_journal_enumerate_fields3, sd_journal_get_data3, sd_journal_add_match3 systemd-229/man/sd_journal_seek_head.xml000066400000000000000000000160051265713322000205100ustar00rootroot00000000000000 sd_journal_seek_head systemd Developer Lennart Poettering lennart@poettering.net sd_journal_seek_head 3 sd_journal_seek_head sd_journal_seek_tail sd_journal_seek_monotonic_usec sd_journal_seek_realtime_usec sd_journal_seek_cursor Seek to a position in the journal #include <systemd/sd-journal.h> int sd_journal_seek_head sd_journal *j int sd_journal_seek_tail sd_journal *j int sd_journal_seek_monotonic_usec sd_journal *j sd_id128_t boot_id uint64_t usec int sd_journal_seek_realtime_usec sd_journal *j uint64_t usec int sd_journal_seek_cursor sd_journal *j const char *cursor Description sd_journal_seek_head() seeks to the beginning of the journal, i.e. the oldest available entry. Similarly, sd_journal_seek_tail() may be used to seek to the end of the journal, i.e. the most recent available entry. sd_journal_seek_monotonic_usec() seeks to the entry with the specified monotonic timestamp, i.e. CLOCK_MONOTONIC. Since monotonic time restarts on every reboot a boot ID needs to be specified as well. sd_journal_seek_realtime_usec() seeks to the entry with the specified realtime (wallclock) timestamp, i.e. CLOCK_REALTIME. Note that the realtime clock is not necessarily monotonic. If a realtime timestamp is ambiguous, it is not defined which position is sought to. sd_journal_seek_cursor() seeks to the entry located at the specified cursor string. For details on cursors, see sd_journal_get_cursor3. If no entry matching the specified cursor is found the call will seek to the next closest entry (in terms of time) instead. To verify whether the newly selected entry actually matches the cursor, use sd_journal_test_cursor3. Note that these calls do not actually make any entry the new current entry, this needs to be done in a separate step with a subsequent sd_journal_next3 invocation (or a similar call). Only then, entry data may be retrieved via sd_journal_get_data3. If no entry exists that matches exactly the specified seek address, the next closest is sought to. If sd_journal_next3 is used, the closest following entry will be sought to, if sd_journal_previous3 is used the closest preceding entry is sought to. Return Value The functions return 0 on success or a negative errno-style error code. Notes The sd_journal_seek_head(), sd_journal_seek_tail(), sd_journal_seek_monotonic_usec(), sd_journal_seek_realtime_usec(), and sd_journal_seek_cursor() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-journal3, sd_journal_open3, sd_journal_next3, sd_journal_get_data3, sd_journal_get_cursor3, sd_journal_get_realtime_usec3 systemd-229/man/sd_journal_stream_fd.xml000066400000000000000000000137111265713322000205450ustar00rootroot00000000000000 sd_journal_stream_fd systemd Developer Lennart Poettering lennart@poettering.net sd_journal_stream_fd 3 sd_journal_stream_fd Create log stream file descriptor to the journal #include <systemd/sd-journal.h> int sd_journal_stream_fd const char *identifier int priority int level_prefix Description sd_journal_stream_fd() may be used to create a log stream file descriptor. Log messages written to this file descriptor as simple newline-separated text strings are written to the journal. This file descriptor can be used internally by applications or be made standard output or standard error of other processes executed. sd_journal_stream_fd() takes a short program identifier string as first argument, which will be written to the journal as _SYSLOG_IDENTIFIER= field for each log entry (see systemd.journal-fields7 for more information). The second argument shall be the default priority level for all messages. The priority level is one of LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG, as defined in syslog.h, see syslog3 for details. The third argument is a boolean: if true kernel-style log level prefixes (such as SD_WARNING) are interpreted, see sd-daemon3 for more information. It is recommended that applications log UTF-8 messages only with this API, but this is not enforced. Return Value The call returns a valid write-only file descriptor on success or a negative errno-style error code. Notes The sd_journal_stream_fd() interface is available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. Examples Creating a log stream suitable for fprintf3: #include <syslog.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <systemd/sd-journal.h> #include <systemd/sd-daemon.h> int main(int argc, char *argv[]) { int fd; FILE *log; fd = sd_journal_stream_fd("test", LOG_INFO, 1); if (fd < 0) { fprintf(stderr, "Failed to create stream fd: %s\n", strerror(-fd)); return 1; } log = fdopen(fd, "w"); if (!log) { fprintf(stderr, "Failed to create file object: %m\n"); close(fd); return 1; } fprintf(log, "Hello World!\n"); fprintf(log, SD_WARNING "This is a warning!\n"); fclose(log); return 0; } See Also systemd1, sd-journal3, sd-daemon3, sd_journal_print3, syslog3, fprintf3, systemd.journal-fields7 systemd-229/man/sd_listen_fds.xml000066400000000000000000000263161265713322000172060ustar00rootroot00000000000000 sd_listen_fds systemd Developer Lennart Poettering lennart@poettering.net sd_listen_fds 3 sd_listen_fds sd_listen_fds_with_names SD_LISTEN_FDS_START Check for file descriptors passed by the system manager #include <systemd/sd-daemon.h> #define SD_LISTEN_FDS_START 3 int sd_listen_fds int unset_environment int sd_listen_fds_with_names int unset_environment char*** names Description sd_listen_fds() may be invoked by a daemon to check for file descriptors passed by the service manager as part of the socket-based activation logic. It returns the number of received file descriptors. If no file descriptors have been received, zero is returned. The first file descriptor may be found at file descriptor number 3 (i.e. SD_LISTEN_FDS_START), the remaining descriptors follow at 4, 5, 6, ..., if any. If a daemon receives more than one file descriptor, they will be passed in the same order as configured in the systemd socket unit file (see systemd.socket5 for details). Nonetheless, it is recommended to verify the correct socket types before using them. To simplify this checking, the functions sd_is_fifo3, sd_is_socket3, sd_is_socket_inet3, sd_is_socket_unix3 are provided. In order to maximize flexibility, it is recommended to make these checks as loose as possible without allowing incorrect setups. i.e. often, the actual port number a socket is bound to matters little for the service to work, hence it should not be verified. On the other hand, whether a socket is a datagram or stream socket matters a lot for the most common program logics and should be checked. This function call will set the FD_CLOEXEC flag for all passed file descriptors to avoid further inheritance to children of the calling process. If multiple socket units activate the same service, the order of the file descriptors passed to its main process is undefined. If additional file descriptors have been passed to the service manager using sd_pid_notify_with_fds3's FDSTORE=1 messages, these file descriptors are passed last, in arbitrary order, and with duplicates removed. If the unset_environment parameter is non-zero, sd_listen_fds() will unset the $LISTEN_FDS, $LISTEN_PID and $LISTEN_FDNAMES environment variables before returning (regardless of whether the function call itself succeeded or not). Further calls to sd_listen_fds() will then return zero, but the variables are no longer inherited by child processes. sd_listen_fds_with_names() is like sd_listen_fds(), but optionally also returns an array of strings with identification names for the passed file descriptors, if that is available and the names parameter is non-NULL. This information is read from the $LISTEN_FDNAMES variable, which may contain a colon-separated list of names. For socket-activated services, these names may be configured with the FileDescriptorName= setting in socket unit files, see systemd.socket5 for details. For file descriptors pushed into the file descriptor store (see above), the name is set via the FDNAME= field transmitted via sd_pid_notify_with_fds(). The primary usecase for these names are services which accept a variety of file descriptors which are not recognizable with functions like sd_is_socket() alone, and thus require identification via a name. It is recommended to rely on named file descriptors only if identification via sd_is_socket() and related calls is not sufficient. Note that the names used are not unique in any way. The returned array of strings has as many entries as file descriptors have been received, plus a final NULL pointer terminating the array. The caller needs to free the array itself and each of its elements with libc's free() call after use. If the names parameter is NULL, the call is entirely equivalent to sd_listen_fds(). Under specific conditions, the following automatic file descriptor names are returned: <command>Special names</command> Name Description unknown The process received no name for the specific file descriptor from the service manager. stored The file descriptor originates in the service manager's per-service file descriptor store, and the FDNAME= field was absent when the file descriptor was submitted to the service manager. connection The service was activated in per-connection style using Accept=yes in the socket unit file, and the file descriptor is the connection socket.
Return Value On failure, these calls returns a negative errno-style error code. If $LISTEN_FDS/$LISTEN_PID was not set or was not correctly set for this daemon and hence no file descriptors were received, 0 is returned. Otherwise, the number of file descriptors passed is returned. The application may find them starting with file descriptor SD_LISTEN_FDS_START, i.e. file descriptor 3. Notes Internally, sd_listen_fds() checks whether the $LISTEN_PID environment variable equals the daemon PID. If not, it returns immediately. Otherwise, it parses the number passed in the $LISTEN_FDS environment variable, then sets the FD_CLOEXEC flag for the parsed number of file descriptors starting from SD_LISTEN_FDS_START. Finally, it returns the parsed number. sd_listen_fds_with_names() does the same but also parses $LISTEN_FDNAMES if set. Environment $LISTEN_PID $LISTEN_FDS $LISTEN_FDNAMES Set by the service manager for supervised processes that use socket-based activation. This environment variable specifies the data sd_listen_fds() and sd_listen_fds_with_names() parses. See above for details. See Also systemd1, sd-daemon3, sd_is_fifo3, sd_is_socket3, sd_is_socket_inet3, sd_is_socket_unix3, sd_pid_notify_with_fds3, daemon7, systemd.service5, systemd.socket5
systemd-229/man/sd_login_monitor_new.xml000066400000000000000000000273161265713322000206050ustar00rootroot00000000000000 sd_login_monitor_new systemd Developer Lennart Poettering lennart@poettering.net sd_login_monitor_new 3 sd_login_monitor_new sd_login_monitor_unref sd_login_monitor_unrefp sd_login_monitor_flush sd_login_monitor_get_fd sd_login_monitor_get_events sd_login_monitor_get_timeout sd_login_monitor Monitor login sessions, seats, users and virtual machines/containers #include <systemd/sd-login.h> int sd_login_monitor_new const char *category sd_login_monitor **ret sd_login_monitor *sd_login_monitor_unref sd_login_monitor *m void sd_login_monitor_unrefp sd_login_monitor **m int sd_login_monitor_flush sd_login_monitor *m int sd_login_monitor_get_fd sd_login_monitor *m int sd_login_monitor_get_events sd_login_monitor *m int sd_login_monitor_get_timeout sd_login_monitor *m uint64_t *timeout_usec Description sd_login_monitor_new() may be used to monitor login sessions, users, seats, and virtual machines/containers. Via a monitor object a file descriptor can be integrated into an application defined event loop which is woken up each time a user logs in, logs out or a seat is added or removed, or a session, user, seat or virtual machine/container changes state otherwise. The first parameter takes a string which can be seat (to get only notifications about seats being added, removed or changed), session (to get only notifications about sessions being created or removed or changed), uid (to get only notifications when a user changes state in respect to logins) or machine (to get only notifications when a virtual machine or container is started or stopped). If notifications shall be generated in all these conditions, NULL may be passed. Note that in the future additional categories may be defined. The second parameter returns a monitor object and needs to be freed with the sd_login_monitor_unref() call after use. sd_login_monitor_unref() may be used to destroy a monitor object. Note that this will invalidate any file descriptor returned by sd_login_monitor_get_fd(). sd_login_monitor_unrefp() is similar to sd_login_monitor_unref() but takes a pointer to a pointer to an sd_login_monitor object. This call is useful in conjunction with GCC's and LLVM's Clean-up Variable Attribute. Note that this function is defined as inline function. Use a declaration like the following, in order to allocate a login monitor object that is freed automatically as the code block is left: { __attribute__((cleanup(sd_login_monitor_unrefp)) sd_login_monitor *m = NULL; int r; … r = sd_login_monitor_default(&m); if (r < 0) fprintf(stderr, "Failed to allocate login monitor object: %s\n", strerror(-r)); … } sd_login_monitor_flush() may be used to reset the wakeup state of the monitor object. Whenever an event causes the monitor to wake up the event loop via the file descriptor this function needs to be called to reset the wake-up state. If this call is not invoked, the file descriptor will immediately wake up the event loop again. sd_login_monitor_unref() and sd_login_monitor_unrefp() execute no operation if the passed in monitor object is NULL. sd_login_monitor_get_fd() may be used to retrieve the file descriptor of the monitor object that may be integrated in an application defined event loop, based around poll2 or a similar interface. The application should include the returned file descriptor as wake-up source for the events mask returned by sd_login_monitor_get_events(). It should pass a timeout value as returned by sd_login_monitor_get_timeout(). Whenever a wake-up is triggered the file descriptor needs to be reset via sd_login_monitor_flush(). An application needs to reread the login state with a function like sd_get_seats3 or similar to determine what changed. sd_login_monitor_get_events() will return the poll() mask to wait for. This function will return a combination of POLLIN, POLLOUT and similar to fill into the .events field of struct pollfd. sd_login_monitor_get_timeout() will return a timeout value for usage in poll(). This returns a value in microseconds since the epoch of CLOCK_MONOTONIC for timing out poll() in timeout_usec. See clock_gettime2 for details about CLOCK_MONOTONIC. If there is no timeout to wait for this will fill in (uint64_t) -1 instead. Note that poll() takes a relative timeout in milliseconds rather than an absolute timeout in microseconds. To convert the absolute 'µs' timeout into relative 'ms', use code like the following: uint64_t t; int msec; sd_login_monitor_get_timeout(m, &t); if (t == (uint64_t) -1) msec = -1; else { struct timespec ts; uint64_t n; clock_getttime(CLOCK_MONOTONIC, &ts); n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000; msec = t > n ? (int) ((t - n + 999) / 1000) : 0; } The code above does not do any error checking for brevity's sake. The calculated msec integer can be passed directly as poll()'s timeout parameter. Return Value On success, sd_login_monitor_new(), sd_login_monitor_flush() and sd_login_monitor_get_timeout() return 0 or a positive integer. On success, sd_login_monitor_get_fd() returns a Unix file descriptor. On success, sd_login_monitor_get_events() returns a combination of POLLIN, POLLOUT and suchlike. On failure, these calls return a negative errno-style error code. sd_login_monitor_unref() always returns NULL. Errors Returned errors may indicate the following problems: -EINVAL An input parameter was invalid (out of range, or NULL, where that is not accepted). The specified category to watch is not known. -ENOMEM Memory allocation failed. Notes The sd_login_monitor_new(), sd_login_monitor_unref(), sd_login_monitor_flush(), sd_login_monitor_get_fd(), sd_login_monitor_get_events() and sd_login_monitor_get_timeout() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-login3, sd_get_seats3, poll2, clock_gettime2 systemd-229/man/sd_machine_get_class.xml000066400000000000000000000125051265713322000204770ustar00rootroot00000000000000 sd_machine_get_class systemd Developer Lennart Poettering lennart@poettering.net sd_machine_get_class 3 sd_machine_get_class sd_machine_get_ifindices Determine the class and network interface indices of a locally running virtual machine or container. #include <systemd/sd-login.h> int sd_machine_get_class const char* machine char **class int sd_machine_get_ifindices const char* machine int **ifindices Description sd_machine_get_class() may be used to determine the class of a locally running virtual machine or container that is registered with systemd-machined.service8. The string returned is either vm or container. The returned string needs to be freed with the libc free3 call after use. sd_machine_get_ifindices() may be used to determine the numeric indices of the network interfaces on the host that are pointing towards the specified locally running virtual machine or container that is registered with systemd-machined.service8. The returned array needs to be freed with the libc free3 call after use. Return Value On success, these calls return 0 or a positive integer. On failure, these calls return a negative errno-style error code. Errors Returned errors may indicate the following problems: -ENXIO The specified machine does not exist or is currently not running. -EINVAL An input parameter was invalid (out of range, or NULL, where that is not accepted). -ENOMEM Memory allocation failed. Notes The sd_machine_get_class() and sd_machine_get_ifindices() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-login3, systemd-machined.service8, sd_pid_get_machine_name3 systemd-229/man/sd_notify.xml000066400000000000000000000406371265713322000163660ustar00rootroot00000000000000 sd_notify systemd Developer Lennart Poettering lennart@poettering.net sd_notify 3 sd_notify sd_notifyf sd_pid_notify sd_pid_notifyf sd_pid_notify_with_fds Notify service manager about start-up completion and other service status changes #include <systemd/sd-daemon.h> int sd_notify int unset_environment const char *state int sd_notifyf int unset_environment const char *format ... int sd_pid_notify pid_t pid int unset_environment const char *state int sd_pid_notifyf pid_t pid int unset_environment const char *format ... int sd_pid_notify_with_fds pid_t pid int unset_environment const char *state const int *fds unsigned n_fds Description sd_notify() may be called by a service to notify the service manager about state changes. It can be used to send arbitrary information, encoded in an environment-block-like string. Most importantly, it can be used for start-up completion notification. If the unset_environment parameter is non-zero, sd_notify() will unset the $NOTIFY_SOCKET environment variable before returning (regardless of whether the function call itself succeeded or not). Further calls to sd_notify() will then fail, but the variable is no longer inherited by child processes. The state parameter should contain a newline-separated list of variable assignments, similar in style to an environment block. A trailing newline is implied if none is specified. The string may contain any kind of variable assignments, but the following shall be considered well-known: READY=1 Tells the service manager that service startup is finished. This is only used by systemd if the service definition file has Type=notify set. Since there is little value in signaling non-readiness, the only value services should send is READY=1 (i.e. READY=0 is not defined). RELOADING=1 Tells the service manager that the service is reloading its configuration. This is useful to allow the service manager to track the service's internal state, and present it to the user. Note that a service that sends this notification must also send a READY=1 notification when it completed reloading its configuration. STOPPING=1 Tells the service manager that the service is beginning its shutdown. This is useful to allow the service manager to track the service's internal state, and present it to the user. STATUS=... Passes a single-line UTF-8 status string back to the service manager that describes the service state. This is free-form and can be used for various purposes: general state feedback, fsck-like programs could pass completion percentages and failing programs could pass a human-readable error message. Example: STATUS=Completed 66% of file system check... ERRNO=... If a service fails, the errno-style error code, formatted as string. Example: ERRNO=2 for ENOENT. BUSERROR=... If a service fails, the D-Bus error-style error code. Example: BUSERROR=org.freedesktop.DBus.Error.TimedOut MAINPID=... The main process ID (PID) of the service, in case the service manager did not fork off the process itself. Example: MAINPID=4711 WATCHDOG=1 Tells the service manager to update the watchdog timestamp. This is the keep-alive ping that services need to issue in regular intervals if WatchdogSec= is enabled for it. See systemd.service5 for information how to enable this functionality and sd_watchdog_enabled3 for the details of how the service can check whether the watchdog is enabled. FDSTORE=1 Stores additional file descriptors in the service manager. File descriptors sent this way will be maintained per-service by the service manager and be passed again using the usual file descriptor passing logic on the next invocation of the service (see sd_listen_fds3). This is useful for implementing service restart schemes where services serialize their state to /run, push their file descriptors to the system manager, and are then restarted, retrieving their state again via socket passing and /run. Note that the service manager will accept messages for a service only if FileDescriptorStoreMax= is set to non-zero for it (defaults to zero). See systemd.service5 for details. Multiple arrays of file descriptors may be sent in separate messages, in which case the arrays are combined. Note that the service manager removes duplicate file descriptors before passing them to the service. Use sd_pid_notify_with_fds() to send messages with FDSTORE=1, see below. FDNAME=... When used in combination with FDSTORE=1, specifies a name for the submitted file descriptors. This name is passed to the service during activation, and may be queried using sd_listen_fds_with_names3. File descriptors submitted without this field set, will implicitly get the name stored assigned. Note that, if multiple file descriptors are submitted at once, the specified name will be assigned to all of them. In order to assign different names to submitted file descriptors, submit them in separate invocations of sd_pid_notify_with_fds(). The name may consist of any ASCII character, but must not contain control characters or :. It may not be longer than 255 characters. If a submitted name does not follow these restrictions, it is ignored. It is recommended to prefix variable names that are not listed above with X_ to avoid namespace clashes. Note that systemd will accept status data sent from a service only if the NotifyAccess= option is correctly set in the service definition file. See systemd.service5 for details. sd_notifyf() is similar to sd_notify() but takes a printf()-like format string plus arguments. sd_pid_notify() and sd_pid_notifyf() are similar to sd_notify() and sd_notifyf() but take a process ID (PID) to use as originating PID for the message as first argument. This is useful to send notification messages on behalf of other processes, provided the appropriate privileges are available. If the PID argument is specified as 0, the process ID of the calling process is used, in which case the calls are fully equivalent to sd_notify() and sd_notifyf(). sd_pid_notify_with_fds() is similar to sd_pid_notify() but takes an additional array of file descriptors. These file descriptors are sent along the notification message to the service manager. This is particularly useful for sending FDSTORE=1 messages, as described above. The additional arguments are a pointer to the file descriptor array plus the number of file descriptors in the array. If the number of file descriptors is passed as 0, the call is fully equivalent to sd_pid_notify(), i.e. no file descriptors are passed. Note that sending file descriptors to the service manager on messages that do not expect them (i.e. without FDSTORE=1) they are immediately closed on reception. Return Value On failure, these calls return a negative errno-style error code. If $NOTIFY_SOCKET was not set and hence no status data could be sent, 0 is returned. If the status was sent, these functions return with a positive return value. In order to support both, init systems that implement this scheme and those which do not, it is generally recommended to ignore the return value of this call. Notes These functions send a single datagram with the state string as payload to the AF_UNIX socket referenced in the $NOTIFY_SOCKET environment variable. If the first character of $NOTIFY_SOCKET is @, the string is understood as Linux abstract namespace socket. The datagram is accompanied by the process credentials of the sending service, using SCM_CREDENTIALS. Environment $NOTIFY_SOCKET Set by the service manager for supervised processes for status and start-up completion notification. This environment variable specifies the socket sd_notify() talks to. See above for details. Examples Start-up Notification When a service finished starting up, it might issue the following call to notify the service manager: sd_notify(0, "READY=1"); Extended Start-up Notification A service could send the following after completing initialization: sd_notifyf(0, "READY=1\n" "STATUS=Processing requests...\n" "MAINPID=%lu", (unsigned long) getpid()); Error Cause Notification A service could send the following shortly before exiting, on failure: sd_notifyf(0, "STATUS=Failed to start up: %s\n" "ERRNO=%i", strerror(errno), errno); Store a File Descriptor in the Service Manager To store an open file descriptor in the service manager, in order to continue operation after a service restart without losing state, use FDSTORE=1: sd_pid_notify_with_fds(0, 0, "FDSTORE=1\nFDNAME=foobar", &fd, 1); See Also systemd1, sd-daemon3, sd_listen_fds3, sd_listen_fds_with_names3, sd_watchdog_enabled3, daemon7, systemd.service5 systemd-229/man/sd_pid_get_session.xml000066400000000000000000000347721265713322000202370ustar00rootroot00000000000000 sd_pid_get_session systemd Developer Lennart Poettering lennart@poettering.net sd_pid_get_session 3 sd_pid_get_session sd_pid_get_unit sd_pid_get_user_unit sd_pid_get_owner_uid sd_pid_get_machine_name sd_pid_get_slice sd_pid_get_user_slice sd_pid_get_cgroup sd_peer_get_session sd_peer_get_unit sd_peer_get_user_unit sd_peer_get_owner_uid sd_peer_get_machine_name sd_peer_get_slice sd_peer_get_user_slice sd_peer_get_cgroup Determine session, unit, owner of a session, container/VM or slice of a specific PID or socket peer #include <systemd/sd-login.h> int sd_pid_get_session pid_t pid char **session int sd_pid_get_unit pid_t pid char **unit int sd_pid_get_user_unit pid_t pid char **unit int sd_pid_get_owner_uid pid_t pid uid_t *uid int sd_pid_get_machine_name pid_t pid char **name int sd_pid_get_slice pid_t pid char **slice int sd_pid_get_user_slice pid_t pid char **slice int sd_pid_get_cgroup pid_t pid char **cgroup int sd_peer_get_session int fd char **session int sd_peer_get_unit int fd char **unit int sd_peer_get_user_unit int fd char **unit int sd_peer_get_owner_uid int fd uid_t *uid int sd_peer_get_machine_name int fd char **name int sd_peer_get_slice int fd char **slice int sd_peer_get_user_slice int fd char **slice int sd_peer_get_cgroup int fd char **cgroup Description sd_pid_get_session() may be used to determine the login session identifier of a process identified by the specified process identifier. The session identifier is a short string, suitable for usage in file system paths. Note that not all processes are part of a login session (e.g. system service processes, user processes that are shared between multiple sessions of the same user, or kernel threads). For processes not being part of a login session, this function will fail with -ENODATA. The returned string needs to be freed with the libc free3 call after use. sd_pid_get_unit() may be used to determine the systemd system unit (i.e. system service or scope unit) identifier of a process identified by the specified PID. The unit name is a short string, suitable for usage in file system paths. Note that not all processes are part of a system unit/service (e.g. user processes, or kernel threads). For processes not being part of a systemd system unit, this function will fail with -ENODATA. (More specifically, this call will not work for kernel threads.) The returned string needs to be freed with the libc free3 call after use. sd_pid_get_user_unit() may be used to determine the systemd user unit (i.e. user service or scope unit) identifier of a process identified by the specified PID. This is similar to sd_pid_get_unit(), but applies to user units instead of system units. sd_pid_get_owner_uid() may be used to determine the Unix UID (user identifier) of the owner of the session of a process identified the specified PID. Note that this function will succeed for user processes which are shared between multiple login sessions of the same user, whereas sd_pid_get_session() will fail. For processes not being part of a login session and not being a shared process of a user, this function will fail with -ENODATA. sd_pid_get_machine_name() may be used to determine the name of the VM or container is a member of. The machine name is a short string, suitable for usage in file system paths. The returned string needs to be freed with the libc free3 call after use. For processes not part of a VM or containers, this function fails with -ENODATA. sd_pid_get_slice() may be used to determine the slice unit the process is a member of. See systemd.slice5 for details about slices. The returned string needs to be freed with the libc free3 call after use. Similarly, sd_pid_get_user_slice() returns the user slice (as managed by the user's systemd instance) of a process. sd_pid_get_cgroup() returns the control group path of the specified process, relative to the root of the hierarchy. Returns the path without trailing slash, except for processes located in the root control group, where "/" is returned. To find the actual control group path in the file system, the returned path needs to be prefixed with /sys/fs/cgroup/ (if the unified control group setup is used), or /sys/fs/cgroup/HIERARCHY/ (if the legacy multi-hierarchy control group setup is used). If the pid parameter of any of these functions is passed as 0, the operation is executed for the calling process. The sd_peer_get_session(), sd_peer_get_unit(), sd_peer_get_user_unit(), sd_peer_get_owner_uid(), sd_peer_get_machine_name(), sd_peer_get_slice(), sd_peer_get_user_slice() and sd_peer_get_cgroup() calls operate similar to their PID counterparts, but operate on a connected AF_UNIX socket and retrieve information about the connected peer process. Note that these fields are retrieved via /proc, and hence are not suitable for authorization purposes, as they are subject to races. Return Value On success, these calls return 0 or a positive integer. On failure, these calls return a negative errno-style error code. Errors Returned errors may indicate the following problems: -ESRCH The specified PID does not refer to a running process. -BADF The specified socket file descriptor was invalid. -ENODATA The given field is not specified for the described process or peer. -EINVAL An input parameter was invalid (out of range, or NULL, where that is not accepted). -ENOMEM Memory allocation failed. Notes The sd_pid_get_session(), sd_pid_get_unit(), sd_pid_get_user_unit(), sd_pid_get_owner_uid(), sd_pid_get_machine_name(), sd_pid_get_slice(), sd_pid_get_user_slice(), sd_peer_get_session(), sd_peer_get_unit(), sd_peer_get_user_unit(), sd_peer_get_owner_uid(), sd_peer_get_machine_name(), sd_peer_get_slice() and sd_peer_get_user_slice() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. Note that the login session identifier as returned by sd_pid_get_session() is completely unrelated to the process session identifier as returned by getsid2. See Also systemd1, sd-login3, sd_session_is_active3, getsid2, systemd.slice5, systemd-machined.service8 systemd-229/man/sd_seat_get_active.xml000066400000000000000000000175731265713322000202070ustar00rootroot00000000000000 sd_seat_get_active systemd Developer Lennart Poettering lennart@poettering.net sd_seat_get_active 3 sd_seat_get_active sd_seat_get_sessions sd_seat_can_multi_session sd_seat_can_tty sd_seat_can_graphical Determine state of a specific seat #include <systemd/sd-login.h> int sd_seat_get_active const char *seat char **session uid_t *uid int sd_seat_get_sessions const char *seat char ***sessions uid_t **uid unsigned int *n_uids int sd_seat_can_multi_session const char *seat int sd_seat_can_tty const char *seat int sd_seat_can_graphical const char *seat Description sd_seat_get_active() may be used to determine which session is currently active on a seat, if there is any. Returns the session identifier and the user identifier of the Unix user the session is belonging to. Either the session or the user identifier parameter can be passed NULL, in case only one of the parameters shall be queried. The returned string needs to be freed with the libc free3 call after use. sd_seat_get_sessions() may be used to determine all sessions on the specified seat. Returns two arrays, one (NULL terminated) with the session identifiers of the sessions and one with the user identifiers of the Unix users the sessions belong to. An additional parameter may be used to return the number of entries in the latter array. The two arrays and the latter parameter may be passed as NULL in case these values need not to be determined. The arrays and the strings referenced by them need to be freed with the libc free3 call after use. Note that instead of an empty array NULL may be returned and should be considered equivalent to an empty array. sd_seat_can_multi_session() may be used to determine whether a specific seat is capable of multi-session, i.e. allows multiple login sessions in parallel (with only one being active at a time). sd_seat_can_tty() may be used to determine whether a specific seat provides TTY functionality, i.e. is useful as a text console. sd_seat_can_graphical() may be used to determine whether a specific seat provides graphics functionality, i.e. is useful as a graphics display. If the seat parameter of any of these functions is passed as NULL, the operation is executed for the seat of the session of the calling process, if there is any. Return Value On success, sd_seat_get_active() returns 0 or a positive integer. On success, sd_seat_get_sessions() returns the number of entries in the session identifier array. If the test succeeds, sd_seat_can_multi_session, sd_seat_can_tty and sd_seat_can_graphical return a positive integer, if it fails 0. On failure, these calls return a negative errno-style error code. Errors Returned errors may indicate the following problems: -ENODATA The given field is not specified for the described seat. -ENXIO The specified seat is unknown. -EINVAL An input parameter was invalid (out of range, or NULL, where that is not accepted). -ENOMEM Memory allocation failed. Notes The sd_seat_get_active(), sd_seat_get_sessions(), sd_seat_can_multi_session(), sd_seat_can_tty() and sd_seat_can_graphical() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-login3, sd_session_get_seat3 systemd-229/man/sd_session_is_active.xml000066400000000000000000000356661265713322000205750ustar00rootroot00000000000000 sd_session_is_active systemd Developer Lennart Poettering lennart@poettering.net sd_session_is_active 3 sd_session_is_active sd_session_is_remote sd_session_get_state sd_session_get_uid sd_session_get_seat sd_session_get_service sd_session_get_type sd_session_get_class sd_session_get_desktop sd_session_get_display sd_session_get_tty sd_session_get_vt sd_session_get_remote_host sd_session_get_remote_user Determine state of a specific session #include <systemd/sd-login.h> int sd_session_is_active const char *session int sd_session_is_remote const char *session int sd_session_get_state const char *session char **state int sd_session_get_uid const char *session uid_t *uid int sd_session_get_seat const char *session char **seat int sd_session_get_service const char *session char **service int sd_session_get_type const char *session char **type int sd_session_get_class const char *session char **class int sd_session_get_desktop const char *session char **desktop int sd_session_get_display const char *session char **display int sd_session_get_remote_host const char *session char **remote_host int sd_session_get_remote_user const char *session char **remote_user int sd_session_get_tty const char *session char **tty int sd_session_get_vt const char *session unsigned int *vt Description sd_session_is_active() may be used to determine whether the session identified by the specified session identifier is currently active (i.e. currently in the foreground and available for user input) or not. sd_session_is_remote() may be used to determine whether the session identified by the specified session identifier is a remote session (i.e. its remote host is known) or not. sd_session_get_state() may be used to determine the state of the session identified by the specified session identifier. The following states are currently known: online (session logged in, but session not active, i.e. not in the foreground), active (session logged in and active, i.e. in the foreground), closing (session nominally logged out, but some processes belonging to it are still around). In the future additional states might be defined, client code should be written to be robust in regards to additional state strings being returned. This function is a more generic version of sd_session_is_active(). The returned string needs to be freed with the libc free3 call after use. sd_session_get_uid() may be used to determine the user identifier of the Unix user the session identified by the specified session identifier belongs to. sd_session_get_seat() may be used to determine the seat identifier of the seat the session identified by the specified session identifier belongs to. Note that not all sessions are attached to a seat, this call will fail for them. The returned string needs to be freed with the libc free3 call after use. sd_session_get_service() may be used to determine the name of the service (as passed during PAM session setup) that registered the session identified by the specified session identifier. The returned string needs to be freed with the libc free3 call after use. sd_session_get_type() may be used to determine the type of the session identified by the specified session identifier. The returned string is one of x11, wayland, tty, mir or unspecified and needs to be freed with the libc free3 call after use. sd_session_get_class() may be used to determine the class of the session identified by the specified session identifier. The returned string is one of user, greeter, lock-screen, or background and needs to be freed with the libc free3 call after use. sd_session_get_desktop() may be used to determine the brand of the desktop running on the session identified by the specified session identifier. This field can be set freely by desktop environments and does not follow any special formatting. However, desktops are strongly recommended to use the same identifiers and capitalization as for $XDG_CURRENT_DESKTOP, as defined by the Desktop Entry Specification. The returned string needs to be freed with the libc free3 call after use. sd_session_get_display() may be used to determine the X11 display of the session identified by the specified session identifier. The returned string needs to be freed with the libc free3 call after use. sd_session_get_remote_host() may be used to determine the remote hostname of the session identified by the specified session identifier. The returned string needs to be freed with the libc free3 call after use. sd_session_get_remote_user() may be used to determine the remote username of the session identified by the specified session identifier. The returned string needs to be freed with the libc free3 call after use. Note that this value is rarely known to the system, and even then should not be relied on. sd_session_get_tty() may be used to determine the TTY device of the session identified by the specified session identifier. The returned string needs to be freed with the libc free3 call after use. sd_session_get_vt() may be used to determine the VT number of the session identified by the specified session identifier. This function will return an error if the seat does not support VTs. If the session parameter of any of these functions is passed as NULL, the operation is executed for the session the calling process is a member of, if there is any. Return Value If the test succeeds, sd_session_is_active() and sd_session_is_remote() return a positive integer; if it fails, 0. On success, sd_session_get_state(), sd_session_get_uid(), sd_session_get_seat(), sd_session_get_service(), sd_session_get_type(), sd_session_get_class(), sd_session_get_display(), sd_session_get_remote_user(), sd_session_get_remote_host() and sd_session_get_tty() return 0 or a positive integer. On failure, these calls return a negative errno-style error code. Errors Returned errors may indicate the following problems: -ENXIO The specified session does not exist. -ENODATA The given field is not specified for the described session. -EINVAL An input parameter was invalid (out of range, or NULL, where that is not accepted). -ENOMEM Memory allocation failed. Notes The sd_session_is_active(), sd_session_get_state(), sd_session_get_uid(), sd_session_get_seat(), sd_session_get_service(), sd_session_get_type(), sd_session_get_class(), sd_session_get_display(), sd_session_get_remote_host(), sd_session_get_remote_user() and sd_session_get_tty() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd pkg-config1 file. See Also systemd1, sd-login3, sd_pid_get_session3 systemd-229/man/sd_uid_get_state.xml000066400000000000000000000226431265713322000176730ustar00rootroot00000000000000 sd_uid_get_state systemd Developer Lennart Poettering lennart@poettering.net sd_uid_get_state 3 sd_uid_get_state sd_uid_is_on_seat sd_uid_get_sessions sd_uid_get_seats sd_uid_get_display Determine login state of a specific Unix user ID #include <systemd/sd-login.h> int sd_uid_get_state uid_t uid char **state int sd_uid_is_on_seat uid_t uid int require_active const char *seat int sd_uid_get_sessions uid_t uid int require_active char ***sessions int sd_uid_get_seats uid_t uid int require_active char ***seats int sd_uid_get_display uid_t uid char **session Description sd_uid_get_state() may be used to determine the login state of a specific Unix user identifier. The following states are currently known: offline (user not logged in at all), lingering (user not logged in, but some user services running), online (user logged in, but not active, i.e. has no session in the foreground), active (user logged in, and has at least one active session, i.e. one session in the foreground), closing (user not logged in, and not lingering, but some processes are still around). In the future additional states might be defined, client code should be written to be robust in regards to additional state strings being returned. The returned string needs to be freed with the libc free3 call after use. sd_uid_is_on_seat() may be used to determine whether a specific user is logged in or active on a specific seat. Accepts a Unix user identifier and a seat identifier string as parameters. The require_active parameter is a boolean value. If non-zero (true), this function will test if the user is active (i.e. has a session that is in the foreground and accepting user input) on the specified seat, otherwise (false) only if the user is logged in (and possibly inactive) on the specified seat. sd_uid_get_sessions() may be used to determine the current sessions of the specified user. Accepts a Unix user identifier as parameter. The require_active parameter controls whether the returned list shall consist of only those sessions where the user is currently active (> 0), where the user is currently online but possibly inactive (= 0), or logged in at all but possibly closing the session (< 0). The call returns a NULL terminated string array of session identifiers in sessions which needs to be freed by the caller with the libc free3 call after use, including all the strings referenced. If the string array parameter is passed as NULL, the array will not be filled in, but the return code still indicates the number of current sessions. Note that instead of an empty array NULL may be returned and should be considered equivalent to an empty array. Similarly, sd_uid_get_seats() may be used to determine the list of seats on which the user currently has sessions. Similar semantics apply, however note that the user may have multiple sessions on the same seat as well as sessions with no attached seat and hence the number of entries in the returned array may differ from the one returned by sd_uid_get_sessions(). sd_uid_get_display() returns the name of the "primary" session of a user. If the user has graphical sessions, it will be the oldest graphical session. Otherwise, it will be the oldest open session. Return Value On success, sd_uid_get_state() returns 0 or a positive integer. If the test succeeds, sd_uid_is_on_seat() returns a positive integer; if it fails, 0. sd_uid_get_sessions() and sd_uid_get_seats() return the number of entries in the returned arrays. sd_uid_get_display() returns a non-negative code on success. On failure, these calls return a negative errno-style error code. Errors Returned errors may indicate the following problems: -ENODATA The given field is not specified for the described user. -ENXIO The specified seat is unknown. -EINVAL An input parameter was invalid (out of range, or NULL, where that is not accepted). This is also returned if the passed user ID is 0xFFFF or 0xFFFFFFFF, which are undefined on Linux. -ENOMEM Memory allocation failed. Notes Functions described here are available as a shared library, and can be compiled and linked to using the libsystemd pkg-config1 entry. History sd_uid_get_state(), sd_uid_is_on_seat(), sd_uid_get_sessions(), and sd_uid_get_seats() functions were added in systemd-31. sd_uid_get_display() was added in systemd-213. See Also systemd1, sd-login3, sd_pid_get_owner_uid3 systemd-229/man/sd_watchdog_enabled.xml000066400000000000000000000160171265713322000203230ustar00rootroot00000000000000 sd_watchdog_enabled systemd Developer Lennart Poettering lennart@poettering.net sd_watchdog_enabled 3 sd_watchdog_enabled Check whether the service manager expects watchdog keep-alive notifications from a service #include <systemd/sd-daemon.h> int sd_watchdog_enabled int unset_environment uint64_t *usec Description sd_watchdog_enabled() may be called by a service to detect whether the service manager expects regular keep-alive watchdog notification events from it, and the timeout after which the manager will act on the service if it did not get such a notification. If the $WATCHDOG_USEC environment variable is set, and the $WATCHDOG_PID variable is unset or set to the PID of the current process, the service manager expects notifications from this process. The manager will usually terminate a service when it does not get a notification message within the specified time after startup and after each previous message. It is recommended that a daemon sends a keep-alive notification message to the service manager every half of the time returned here. Notification messages may be sent with sd_notify3 with a message string of WATCHDOG=1. If the unset_environment parameter is non-zero, sd_watchdog_enabled() will unset the $WATCHDOG_USEC and $WATCHDOG_PID environment variables before returning (regardless of whether the function call itself succeeded or not). Those variables are no longer inherited by child processes. Further calls to sd_watchdog_enabled() will also return with zero. If the usec parameter is non-NULL, sd_watchdog_enabled() will write the timeout in µs for the watchdog logic to it. To enable service supervision with the watchdog logic, use WatchdogSec= in service files. See systemd.service5 for details. Use sd_event_set_watchdog3 to enable automatic watchdog support in sd-event3-based event loops. Return Value On failure, this call returns a negative errno-style error code. If the service manager expects watchdog keep-alive notification messages to be sent, > 0 is returned, otherwise 0 is returned. Only if the return value is > 0, the usec parameter is valid after the call. Notes Internally, this functions parses the $WATCHDOG_PID and $WATCHDOG_USEC environment variable. The call will ignore these variables if $WATCHDOG_PID does not contain the PID of the current process, under the assumption that in that case, the variables were set for a different process further up the process tree. Environment $WATCHDOG_PID Set by the system manager for supervised process for which watchdog support is enabled, and contains the PID of that process. See above for details. $WATCHDOG_USEC Set by the system manager for supervised process for which watchdog support is enabled, and contains the watchdog timeout in µs See above for details. History The watchdog functionality and the $WATCHDOG_USEC variable were added in systemd-41. sd_watchdog_enabled() function was added in systemd-209. Since that version, the $WATCHDOG_PID variable is also set. See Also systemd1, sd-daemon3, daemon7, systemd.service5, sd_notify3, sd_event_set_watchdog3 systemd-229/man/shutdown.xml000066400000000000000000000125611265713322000162360ustar00rootroot00000000000000 shutdown systemd Developer Lennart Poettering lennart@poettering.net shutdown 8 shutdown Halt, power-off or reboot the machine shutdown OPTIONS TIME WALL Description shutdown may be used to halt, power-off or reboot the machine. The first argument may be a time string (which is usually now). Optionally, this may be followed by a wall message to be sent to all logged-in users before going down. The time string may either be in the format hh:mm for hour/minutes specifying the time to execute the shutdown at, specified in 24h clock format. Alternatively it may be in the syntax +m referring to the specified number of minutes m from now. now is an alias for +0, i.e. for triggering an immediate shutdown. If no time argument is specified, +1 is implied. Note that to specify a wall message you must specify a time argument, too. If the time argument is used, 5 minutes before the system goes down the /run/nologin file is created to ensure that further logins shall not be allowed. Options The following options are understood: Halt the machine. Power-off the machine (the default). Reboot the machine. Equivalent to , unless is specified. Do not halt, power-off, reboot, just write wall message. Do not send wall message before halt, power-off, reboot. Cancel a pending shutdown. This may be used cancel the effect of an invocation of shutdown with a time argument that is not +0 or now. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, systemctl1, halt8, wall1 systemd-229/man/standard-conf.xml000066400000000000000000000074751265713322000171160ustar00rootroot00000000000000 Configuration Directories and Precedence Configuration files are read from directories in /etc/, /run/, and /usr/lib/, in order of precedence. Each configuration file in these configuration directories shall be named in the style of filename.conf. Files in /etc/ override files with the same name in /run/ and /usr/lib/. Files in /run/ override files with the same name in /usr/lib/. Packages should install their configuration files in /usr/lib/. Files in /etc/ are reserved for the local administrator, who may use this logic to override the configuration files installed by vendor packages. All configuration files are sorted by their filename in lexicographic order, regardless of which of the directories they reside in. If multiple files specify the same option, the entry in the file with the lexicographically latest name will take precedence. It is recommended to prefix all filenames with a two-digit number and a dash, to simplify the ordering of the files. If the administrator wants to disable a configuration file supplied by the vendor, the recommended way is to place a symlink to /dev/null in the configuration directory in /etc/, with the same filename as the vendor configuration file. If the vendor configuration file is included in the initrd image, the image has to be regenerated. Configuration Directories and Precedence The default configuration is defined during compilation, so a configuration file is only needed when it is necessary to deviate from those defaults. By default, the configuration file in /etc/systemd/ contains commented out entries showing the defaults as a guide to the administrator. This file can be edited to create local overrides. When packages need to customize the configuration, they can install configuration snippets in /usr/lib/systemd/*.conf.d/. Files in /etc/ are reserved for the local administrator, who may use this logic to override the configuration files installed by vendor packages. The main configuration file is read before any of the configuration directories, and has the lowest precedence; entries in a file in any configuration directory override entries in the single configuration file. Files in the *.conf.d/ configuration subdirectories are sorted by their filename in lexicographic order, regardless of which of the subdirectories they reside in. If multiple files specify the same option, the entry in the file with the lexicographically latest name takes precedence. It is recommended to prefix all filenames in those subdirectories with a two-digit number and a dash, to simplify the ordering of the files. To disable a configuration file supplied by the vendor, the recommended way is to place a symlink to /dev/null in the configuration directory in /etc/, with the same filename as the vendor configuration file. systemd-229/man/standard-options.xml000066400000000000000000000020671265713322000176540ustar00rootroot00000000000000 Print a short help text and exit. Print a short version string and exit. Do not pipe output into a pager. Do not print the legend, i.e. column headers and the footer with hints. systemd-229/man/sysctl.d.xml000066400000000000000000000164631265713322000161330ustar00rootroot00000000000000 sysctl.d systemd Developer Lennart Poettering lennart@poettering.net sysctl.d 5 sysctl.d Configure kernel parameters at boot /etc/sysctl.d/*.conf /run/sysctl.d/*.conf /usr/lib/sysctl.d/*.conf Description At boot, systemd-sysctl.service8 reads configuration files from the above directories to configure sysctl8 kernel parameters. Configuration Format The configuration files contain a list of variable assignments, separated by newlines. Empty lines and lines whose first non-whitespace character is # or ; are ignored. Note that either / or . may be used as separators within sysctl variable names. If the first separator is a slash, remaining slashes and dots are left intact. If the first separator is a dot, dots and slashes are interchanged. kernel.domainname=foo and kernel/domainname=foo are equivalent and will cause foo to be written to /proc/sys/kernel/domainname. Either net.ipv4.conf.enp3s0/200.forwarding or net/ipv4/conf/enp3s0.200/forwarding may be used to refer to /proc/sys/net/ipv4/conf/enp3s0.200/forwarding. The settings configured with sysctl.d files will be applied early on boot. The network interface-specific options will also be applied individually for each network interface as it shows up in the system. (More specifically, net.ipv4.conf.*, net.ipv6.conf.*, net.ipv4.neigh.* and net.ipv6.neigh.*). Many sysctl parameters only become available when certain kernel modules are loaded. Modules are usually loaded on demand, e.g. when certain hardware is plugged in or network brought up. This means that systemd-sysctl.service8 which runs during early boot will not configure such parameters if they become available after it has run. To set such parameters, it is recommended to add an udev7 rule to set those parameters when they become available. Alternatively, a slightly simpler and less efficient option is to add the module to modules-load.d5, causing it to be loaded statically before sysctl settings are applied (see example below). Examples Set kernel YP domain name /etc/sysctl.d/domain-name.conf: kernel.domainname=example.com Apply settings available only when a certain module is loaded (method one) /etc/udev/rules.d/99-bridge.rules: ACTION=="add", SUBSYSTEM=="module", KERNEL=="br_netfilter", \ RUN+="/usr/lib/systemd/systemd-sysctl --prefix=/net/bridge" /etc/sysctl.d/bridge.conf: net.bridge.bridge-nf-call-ip6tables = 0 net.bridge.bridge-nf-call-iptables = 0 net.bridge.bridge-nf-call-arptables = 0 This method applies settings when the module is loaded. Please note that, unless the br_netfilter module is loaded, bridged packets will not be filtered by Netfilter (starting with kernel 3.18), so simply not loading the module is sufficient to avoid filtering. Apply settings available only when a certain module is loaded (method two) /etc/modules-load.d/bridge.conf: br_netfilter /etc/sysctl.d/bridge.conf: net.bridge.bridge-nf-call-ip6tables = 0 net.bridge.bridge-nf-call-iptables = 0 net.bridge.bridge-nf-call-arptables = 0 This method forces the module to be always loaded. Please note that, unless the br_netfilter module is loaded, bridged packets will not be filtered with Netfilter (starting with kernel 3.18), so simply not loading the module is sufficient to avoid filtering. See Also systemd1, systemd-sysctl.service8, systemd-delta1, sysctl8, sysctl.conf5, modprobe8 systemd-229/man/systemctl.xml000066400000000000000000002322111265713322000164060ustar00rootroot00000000000000 %entities; ]> systemctl systemd Developer Lennart Poettering lennart@poettering.net systemctl 1 systemctl Control the systemd system and service manager systemctl OPTIONS COMMAND NAME Description systemctl may be used to introspect and control the state of the systemd system and service manager. Please refer to systemd1 for an introduction into the basic concepts and functionality this tool manages. Options The following options are understood: The argument should be a comma-separated list of unit types such as and . If one of the arguments is a unit type, when listing units, limit display to certain unit types. Otherwise, units of all types will be shown. As a special case, if one of the arguments is , a list of allowed values will be printed and the program will exit. The argument should be a comma-separated list of unit LOAD, SUB, or ACTIVE states. When listing units, show only those in the specified states. Use to show only failed units. As a special case, if one of the arguments is , a list of allowed values will be printed and the program will exit. When showing unit/job/manager properties with the show command, limit display to properties specified in the argument. The argument should be a comma-separated list of property names, such as MainPID. Unless specified, all known properties are shown. If specified more than once, all properties with the specified names are shown. Shell completion is implemented for property names. For the manager itself, systemctl show will show all available properties. Those properties are documented in systemd-system.conf5. Properties for units vary by unit type, so showing any unit (even a non-existent one) is a way to list properties pertaining to this type. Similarly, showing any job will list properties pertaining to all jobs. Properties for units are documented in systemd.unit5, and the pages for individual unit types systemd.service5, systemd.socket5, etc. When listing units, show all loaded units, regardless of their state, including inactive units. When showing unit/job/manager properties, show all properties regardless whether they are set or not. To list all units installed on the system, use the list-unit-files command instead. When listing units, also show units of local containers. Units of local containers will be prefixed with the container name, separated by a single colon character (:). Show reverse dependencies between units with list-dependencies, i.e. follow dependencies of type WantedBy=, RequiredBy=, PartOf=, BoundBy=, instead of Wants= and similar. With list-dependencies, show the units that are ordered before the specified unit. In other words, recursively list units following the After= dependency. Note that any After= dependency is automatically mirrored to create a Before= dependency. Temporal dependencies may be specified explicitly, but are also created implicitly for units which are WantedBy= targets (see systemd.target5), and as a result of other directives (for example RequiresMountsFor=). Both explicitly and implicitly introduced dependencies are shown with list-dependencies. With list-dependencies, show the units that are ordered after the specified unit. In other words, recursively list units following the Before= dependency. Do not ellipsize unit names, process tree entries, journal output, or truncate unit descriptions in the output of status, list-units, list-jobs, and list-timers. When showing sockets, show the type of the socket. When queuing a new job, this option controls how to deal with already queued jobs. It takes one of fail, replace, replace-irreversibly, isolate, ignore-dependencies, ignore-requirements or flush. Defaults to replace, except when the isolate command is used which implies the isolate job mode. If fail is specified and a requested operation conflicts with a pending job (more specifically: causes an already pending start job to be reversed into a stop job or vice versa), cause the operation to fail. If replace (the default) is specified, any conflicting pending job will be replaced, as necessary. If replace-irreversibly is specified, operate like replace, but also mark the new jobs as irreversible. This prevents future conflicting transactions from replacing these jobs (or even being enqueued while the irreversible jobs are still pending). Irreversible jobs can still be cancelled using the cancel command. isolate is only valid for start operations and causes all other units to be stopped when the specified unit is started. This mode is always used when the isolate command is used. flush will cause all queued jobs to be canceled when the new job is enqueued. If ignore-dependencies is specified, then all unit dependencies are ignored for this new job and the operation is executed immediately. If passed, no required units of the unit passed will be pulled in, and no ordering dependencies will be honored. This is mostly a debugging and rescue tool for the administrator and should not be used by applications. ignore-requirements is similar to ignore-dependencies, but only causes the requirement dependencies to be ignored, the ordering dependencies will still be honoured. Shorthand for fail. When used with the kill command, if no units were killed, the operation results in an error. When system shutdown or a sleep state is requested, ignore inhibitor locks. Applications can establish inhibitor locks to avoid that certain important operations (such as CD burning or suchlike) are interrupted by system shutdown or a sleep state. Any user may take these locks and privileged users may override these locks. If any locks are taken, shutdown and sleep state requests will normally fail (regardless of whether privileged or not) and a list of active locks is printed. However, if is specified, the locks are ignored and not printed, and the operation attempted anyway, possibly requiring additional privileges. Suppress printing of the results of various commands and also the hints about truncated log lines. This does not suppress output of commands for which the printed output is the only result (like show). Errors are always printed. Do not synchronously wait for the requested operation to finish. If this is not specified, the job will be verified, enqueued and systemctl will wait until the unit's start-up is completed. By passing this argument, it is only verified and enqueued. Do not send wall message before halt, power-off, reboot. When used with enable and disable, operate on the global user configuration directory, thus enabling or disabling a unit file globally for all future logins of all users. When used with enable and disable, do not implicitly reload daemon configuration after executing the changes. When used with start and related commands, disables asking for passwords. Background services may require input of a password or passphrase string, for example to unlock system hard disks or cryptographic certificates. Unless this option is specified and the command is invoked from a terminal, systemctl will query the user on the terminal for the necessary secrets. Use this option to switch this behavior off. In this case, the password must be supplied by some other means (for example graphical password agents) or the service might fail. This also disables querying the user for authentication for privileged operations. When used with kill, choose which processes to send a signal to. Must be one of , or to select whether to kill only the main process, the control process or all processes of the unit. The main process of the unit is the one that defines the life-time of it. A control process of a unit is one that is invoked by the manager to induce state changes of it. For example, all processes started due to the ExecStartPre=, ExecStop= or ExecReload= settings of service units are control processes. Note that there is only one control process per unit at a time, as only one state change is executed at a time. For services of type Type=forking, the initial process started by the manager for ExecStart= is a control process, while the process ultimately forked off by that one is then considered the main process of the unit (if it can be determined). This is different for service units of other types, where the process forked off by the manager for ExecStart= is always the main process itself. A service unit consists of zero or one main process, zero or one control process plus any number of additional processes. Not all unit types manage processes of these types however. For example, for mount units, control processes are defined (which are the invocations of &MOUNT_PATH; and &UMOUNT_PATH;), but no main process is defined. If omitted, defaults to . When used with kill, choose which signal to send to selected processes. Must be one of the well-known signal specifiers such as SIGTERM, SIGINT or SIGSTOP. If omitted, defaults to . When used with enable, overwrite any existing conflicting symlinks. When used with halt, poweroff, reboot or kexec, execute the selected operation without shutting down all units. However, all processes will be killed forcibly and all file systems are unmounted or remounted read-only. This is hence a drastic but relatively safe option to request an immediate reboot. If is specified twice for these operations, they will be executed immediately without terminating any processes or unmounting any file systems. Warning: specifying twice with any of these operations might result in data loss. When used with halt, poweroff, reboot or kexec, set a short message explaining the reason for the operation. The message will be logged together with the default shutdown message. When used with enable, the units will also be started. When used with disable or mask, the units will also be stopped. The start or stop operation is only carried out when the respective enable or disable operation has been successful. When used with enable/disable/is-enabled (and related commands), use an alternate root path when looking for unit files. When used with enable, disable, edit, (and related commands), make changes only temporarily, so that they are lost on the next reboot. This will have the effect that changes are not made in subdirectories of /etc but in /run, with identical immediate effects, however, since the latter is lost on reboot, the changes are lost too. Similarly, when used with set-property, make changes only temporarily, so that they are lost on the next reboot. Takes one of full (the default), enable-only, disable-only. When used with the preset or preset-all commands, controls whether units shall be disabled and enabled according to the preset rules, or only enabled, or only disabled. When used with status, controls the number of journal lines to show, counting from the most recent ones. Takes a positive integer argument. Defaults to 10. When used with status, controls the formatting of the journal entries that are shown. For the available choices, see journalctl1. Defaults to short. When used with the reboot command, indicate to the system's firmware to boot into setup mode. Note that this is currently only supported on some EFI systems and only if the system was booted in EFI mode. When used with list-dependencies, list-units or list-machines, the the output is printed as a list instead of a tree, and the bullet circles are omitted. Commands The following commands are understood: Unit Commands list-units PATTERN... List known units (subject to limitations specified with ). If one or more PATTERNs are specified, only units matching one of them are shown. This is the default command. list-sockets PATTERN... List socket units ordered by listening address. If one or more PATTERNs are specified, only socket units matching one of them are shown. Produces output similar to LISTEN UNIT ACTIVATES /dev/initctl systemd-initctl.socket systemd-initctl.service ... [::]:22 sshd.socket sshd.service kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service 5 sockets listed. Note: because the addresses might contains spaces, this output is not suitable for programmatic consumption. See also the options , , and . list-timers PATTERN... List timer units ordered by the time they elapse next. If one or more PATTERNs are specified, only units matching one of them are shown. See also the options and . start PATTERN... Start (activate) one or more units specified on the command line. Note that glob patterns operate on the set of primary names of currently loaded units. Units which are not active and are not in a failed state usually are not loaded, and will not be matched by any pattern. In addition, in case of instantiated units, systemd is often unaware of the instance name until the instance has been started. Therefore, using glob patterns with start has limited usefulness. Also, secondary alias names of units are not considered. stop PATTERN... Stop (deactivate) one or more units specified on the command line. reload PATTERN... Asks all units listed on the command line to reload their configuration. Note that this will reload the service-specific configuration, not the unit configuration file of systemd. If you want systemd to reload the configuration file of a unit, use the daemon-reload command. In other words: for the example case of Apache, this will reload Apache's httpd.conf in the web server, not the apache.service systemd unit file. This command should not be confused with the daemon-reload command. restart PATTERN... Restart one or more units specified on the command line. If the units are not running yet, they will be started. try-restart PATTERN... Restart one or more units specified on the command line if the units are running. This does nothing if units are not running. reload-or-restart PATTERN... Reload one or more units if they support it. If not, restart them instead. If the units are not running yet, they will be started. try-reload-or-restart PATTERN... Reload one or more units if they support it. If not, restart them instead. This does nothing if the units are not running. isolate NAME Start the unit specified on the command line and its dependencies and stop all others. If a unit name with no extension is given, an extension of .target will be assumed. This is similar to changing the runlevel in a traditional init system. The isolate command will immediately stop processes that are not enabled in the new unit, possibly including the graphical environment or terminal you are currently using. Note that this is allowed only on units where is enabled. See systemd.unit5 for details. kill PATTERN... Send a signal to one or more processes of the unit. Use to select which process to kill. Use to select the signal to send. is-active PATTERN... Check whether any of the specified units are active (i.e. running). Returns an exit code 0 if at least one is active, or non-zero otherwise. Unless is specified, this will also print the current unit state to standard output. is-failed PATTERN... Check whether any of the specified units are in a "failed" state. Returns an exit code 0 if at least one has failed, non-zero otherwise. Unless is specified, this will also print the current unit state to standard output. status PATTERN...|PID...] Show terse runtime status information about one or more units, followed by most recent log data from the journal. If no units are specified, show system status. If combined with , also show the status of all units (subject to limitations specified with ). If a PID is passed, show information about the unit the process belongs to. This function is intended to generate human-readable output. If you are looking for computer-parsable output, use show instead. By default, this function only shows 10 lines of output and ellipsizes lines to fit in the terminal window. This can be changed with and , see above. In addition, journalctl --unit=NAME or journalctl --user-unit=NAME use a similar filter for messages and might be more convenient. show PATTERN...|JOB... Show properties of one or more units, jobs, or the manager itself. If no argument is specified, properties of the manager will be shown. If a unit name is specified, properties of the unit is shown, and if a job ID is specified, properties of the job is shown. By default, empty properties are suppressed. Use to show those too. To select specific properties to show, use . This command is intended to be used whenever computer-parsable output is required. Use status if you are looking for formatted human-readable output. cat PATTERN... Show backing files of one or more units. Prints the "fragment" and "drop-ins" (source files) of units. Each file is preceded by a comment which includes the file name. set-property NAME ASSIGNMENT... Set the specified unit properties at runtime where this is supported. This allows changing configuration parameter properties such as resource control settings at runtime. Not all properties may be changed at runtime, but many resource control settings (primarily those in systemd.resource-control5) may. The changes are applied instantly, and stored on disk for future boots, unless is passed, in which case the settings only apply until the next reboot. The syntax of the property assignment follows closely the syntax of assignments in unit files. Example: systemctl set-property foobar.service CPUShares=777 If the specified unit appears to be inactive, the changes will be only stored on disk as described previously hence they will be effective when the unit will be started. Note that this command allows changing multiple properties at the same time, which is preferable over setting them individually. Like unit file configuration settings, assigning the empty list to list parameters will reset the list. help PATTERN...|PID... Show manual pages for one or more units, if available. If a PID is given, the manual pages for the unit the process belongs to are shown. reset-failed [PATTERN...] Reset the failed state of the specified units, or if no unit name is passed, reset the state of all units. When a unit fails in some way (i.e. process exiting with non-zero error code, terminating abnormally or timing out), it will automatically enter the failed state and its exit code and status is recorded for introspection by the administrator until the service is restarted or reset with this command. list-dependencies NAME Shows units required and wanted by the specified unit. This recursively lists units following the Requires=, Requisite=, ConsistsOf=, Wants=, BindsTo= dependencies. If no unit is specified, default.target is implied. By default, only target units are recursively expanded. When is passed, all other units are recursively expanded as well. Options , , may be used to change what types of dependencies are shown. Unit File Commands list-unit-files PATTERN... List installed unit files and their enablement state (as reported by is-enabled). If one or more PATTERNs are specified, only units whose filename (just the last component of the path) matches one of them are shown. enable NAME... Enable one or more unit files or unit file instances, as specified on the command line. This will create a number of symlinks as encoded in the [Install] sections of the unit files. After the symlinks have been created, the systemd configuration is reloaded (in a way that is equivalent to daemon-reload) to ensure the changes are taken into account immediately. Note that this does not have the effect of also starting any of the units being enabled. If this is desired, either should be used together with this command, or an additional start command must be invoked for the unit. Also note that, in case of instance enablement, symlinks named the same as instances are created in the install location, however they all point to the same template unit file. This command will print the actions executed. This output may be suppressed by passing . Note that this operation creates only the suggested symlinks for the units. While this command is the recommended way to manipulate the unit configuration directory, the administrator is free to make additional changes manually by placing or removing symlinks in the directory. This is particularly useful to create configurations that deviate from the suggested default installation. In this case, the administrator must make sure to invoke daemon-reload manually as necessary to ensure the changes are taken into account. Enabling units should not be confused with starting (activating) units, as done by the start command. Enabling and starting units is orthogonal: units may be enabled without being started and started without being enabled. Enabling simply hooks the unit into various suggested places (for example, so that the unit is automatically started on boot or when a particular kind of hardware is plugged in). Starting actually spawns the daemon process (in case of service units), or binds the socket (in case of socket units), and so on. Depending on whether , , , or is specified, this enables the unit for the system, for the calling user only, for only this boot of the system, or for all future logins of all users, or only this boot. Note that in the last case, no systemd daemon configuration is reloaded. Using enable on masked units results in an error. disable NAME... Disables one or more units. This removes all symlinks to the specified unit files from the unit configuration directory, and hence undoes the changes made by enable. Note however that this removes all symlinks to the unit files (i.e. including manual additions), not just those actually created by enable. This call implicitly reloads the systemd daemon configuration after completing the disabling of the units. Note that this command does not implicitly stop the units that are being disabled. If this is desired, either should be used together with this command, or an additional stop command should be executed afterwards. This command will print the actions executed. This output may be suppressed by passing . This command honors , , and in a similar way as enable. reenable NAME... Reenable one or more unit files, as specified on the command line. This is a combination of disable and enable and is useful to reset the symlinks a unit is enabled with to the defaults configured in the [Install] section of the unit file. preset NAME... Reset one or more unit files, as specified on the command line, to the defaults configured in the preset policy files. This has the same effect as disable or enable, depending how the unit is listed in the preset files. Use to control whether units shall be enabled and disabled, or only enabled, or only disabled. For more information on the preset policy format, see systemd.preset5. For more information on the concept of presets, please consult the Preset document. preset-all Resets all installed unit files to the defaults configured in the preset policy file (see above). Use to control whether units shall be enabled and disabled, or only enabled, or only disabled. is-enabled NAME... Checks whether any of the specified unit files are enabled (as with enable). Returns an exit code of 0 if at least one is enabled, non-zero otherwise. Prints the current enable status (see table). To suppress this output, use . <command>is-enabled</command> output Name Description Exit Code enabled Enabled via .wants/, .requires/ or alias symlinks (permanently in /etc/systemd/system/, or transiently in /run/systemd/system/). 0 enabled-runtime linked Made available through one or more symlinks to the unit file (permanently in /etc/systemd/system/ or transiently in /run/systemd/system/), even though the unit file might reside outside of the unit file search path. > 0 linked-runtime masked Completely disabled, so that any start operation on it fails (permanently in /etc/systemd/system/ or transiently in /run/systemd/systemd/). > 0 masked-runtime static The unit file is not enabled, and has no provisions for enabling in the [Install] section. 0 indirect The unit file itself is not enabled, but it has a non-empty Also= setting in the [Install] section, listing other unit files that might be enabled. 0 disabled Unit file is not enabled, but contains an [Install] section with installation instructions. > 0 bad Unit file is invalid or another error occurred. Note that is-enabled will not actually return this state, but print an error message instead. However the unit file listing printed by list-unit-files might show it. > 0
mask NAME... Mask one or more unit files, as specified on the command line. This will link these units to /dev/null, making it impossible to start them. This is a stronger version of disable, since it prohibits all kinds of activation of the unit, including enablement and manual activation. Use this option with care. This honors the option to only mask temporarily until the next reboot of the system. The option can be used to ensure that the units are also stopped. unmask NAME... Unmask one or more unit files, as specified on the command line. This will undo the effect of mask. link FILENAME... Link a unit file that is not in the unit file search paths into the unit file search path. This requires an absolute path to a unit file. The effect of this can be undone with disable. The effect of this command is that a unit file is available for start and other commands although it is not installed directly in the unit search path. add-wants TARGET NAME... add-requires TARGET NAME... Adds Wants= or Requires= dependencies, respectively, to the specified TARGET for one or more units. This command honors , , and in a way similar to enable. edit NAME... Edit a drop-in snippet or a whole replacement file if is specified, to extend or override the specified unit. Depending on whether (the default), , or is specified, this command creates a drop-in file for each unit either for the system, for the calling user, or for all futures logins of all users. Then, the editor (see the "Environment" section below) is invoked on temporary files which will be written to the real location if the editor exits successfully. If is specified, this will copy the original units instead of creating drop-in files. If is specified, the changes will be made temporarily in /run and they will be lost on the next reboot. If the temporary file is empty upon exit, the modification of the related unit is canceled. After the units have been edited, systemd configuration is reloaded (in a way that is equivalent to daemon-reload). Note that this command cannot be used to remotely edit units and that you cannot temporarily edit units which are in /etc, since they take precedence over /run. get-default Return the default target to boot into. This returns the target unit name default.target is aliased (symlinked) to. set-default NAME Set the default target to boot into. This sets (symlinks) the default.target alias to the given target unit.
Machine Commands list-machines PATTERN... List the host and all running local containers with their state. If one or more PATTERNs are specified, only containers matching one of them are shown. Job Commands list-jobs PATTERN... List jobs that are in progress. If one or more PATTERNs are specified, only jobs for units matching one of them are shown. cancel JOB... Cancel one or more jobs specified on the command line by their numeric job IDs. If no job ID is specified, cancel all pending jobs. Environment Commands show-environment Dump the systemd manager environment block. The environment block will be dumped in straight-forward form suitable for sourcing into a shell script. This environment block will be passed to all processes the manager spawns. set-environment VARIABLE=VALUE... Set one or more systemd manager environment variables, as specified on the command line. unset-environment VARIABLE... Unset one or more systemd manager environment variables. If only a variable name is specified, it will be removed regardless of its value. If a variable and a value are specified, the variable is only removed if it has the specified value. import-environment VARIABLE... Import all, one or more environment variables set on the client into the systemd manager environment block. If no arguments are passed, the entire environment block is imported. Otherwise, a list of one or more environment variable names should be passed, whose client-side values are then imported into the manager's environment block. Manager Lifecycle Commands daemon-reload Reload the systemd manager configuration. This will rerun all generators (see systemd.generator7), reload all unit files, and recreate the entire dependency tree. While the daemon is being reloaded, all sockets systemd listens on behalf of user configuration will stay accessible. This command should not be confused with the reload command. daemon-reexec Reexecute the systemd manager. This will serialize the manager state, reexecute the process and deserialize the state again. This command is of little use except for debugging and package upgrades. Sometimes, it might be helpful as a heavy-weight daemon-reload. While the daemon is being reexecuted, all sockets systemd listening on behalf of user configuration will stay accessible. System Commands is-system-running Checks whether the system is operational. This returns success (exit code 0) when the system is fully up and running, specifically not in startup, shutdown or maintenance mode, and with no failed services. Failure is returned otherwise (exit code non-zero). In addition, the current state is printed in a short string to standard output, see the table below. Use to suppress this output. <command>is-system-running</command> output Name Description Exit Code initializing Early bootup, before basic.target is reached or the maintenance state entered. > 0 starting Late bootup, before the job queue becomes idle for the first time, or one of the rescue targets are reached. > 0 running The system is fully operational. 0 degraded The system is operational but one or more units failed. > 0 maintenance The rescue or emergency target is active. > 0 stopping The manager is shutting down. > 0 offline The manager is not running. Specifically, this is the operational state if an incompatible program is running as system manager (PID 1). > 0 unknown The operational state could not be determined, due to lack of resources or another error cause. > 0
default Enter default mode. This is mostly equivalent to isolate default.target. rescue Enter rescue mode. This is mostly equivalent to isolate rescue.target, but also prints a wall message to all users. emergency Enter emergency mode. This is mostly equivalent to isolate emergency.target, but also prints a wall message to all users. halt Shut down and halt the system. This is mostly equivalent to start halt.target --job-mode=replace-irreversibly, but also prints a wall message to all users. If combined with , shutdown of all running services is skipped, however all processes are killed and all file systems are unmounted or mounted read-only, immediately followed by the system halt. If is specified twice, the operation is immediately executed without terminating any processes or unmounting any file systems. This may result in data loss. poweroff Shut down and power-off the system. This is mostly equivalent to start poweroff.target --job-mode=replace-irreversibly, but also prints a wall message to all users. If combined with , shutdown of all running services is skipped, however all processes are killed and all file systems are unmounted or mounted read-only, immediately followed by the powering off. If is specified twice, the operation is immediately executed without terminating any processes or unmounting any file systems. This may result in data loss. reboot arg Shut down and reboot the system. This is mostly equivalent to start reboot.target --job-mode=replace-irreversibly, but also prints a wall message to all users. If combined with , shutdown of all running services is skipped, however all processes are killed and all file systems are unmounted or mounted read-only, immediately followed by the reboot. If is specified twice, the operation is immediately executed without terminating any processes or unmounting any file systems. This may result in data loss. If the optional argument arg is given, it will be passed as the optional argument to the reboot2 system call. The value is architecture and firmware specific. As an example, recovery might be used to trigger system recovery, and fota might be used to trigger a firmware over the air update. kexec Shut down and reboot the system via kexec. This is mostly equivalent to start kexec.target --job-mode=replace-irreversibly, but also prints a wall message to all users. If combined with , shutdown of all running services is skipped, however all processes are killed and all file systems are unmounted or mounted read-only, immediately followed by the reboot. exit EXIT_CODE Ask the systemd manager to quit. This is only supported for user service managers (i.e. in conjunction with the option) or in containers and is equivalent to poweroff otherwise. The systemd manager can exit with a non-zero exit code if the optional argument EXIT_CODE is given. switch-root ROOT INIT Switches to a different root directory and executes a new system manager process below it. This is intended for usage in initial RAM disks ("initrd"), and will transition from the initrd's system manager process (a.k.a. "init" process) to the main system manager process. This call takes two arguments: the directory that is to become the new root directory, and the path to the new system manager binary below it to execute as PID 1. If the latter is omitted or the empty string, a systemd binary will automatically be searched for and used as init. If the system manager path is omitted or equal to the empty string, the state of the initrd's system manager process is passed to the main system manager, which allows later introspection of the state of the services involved in the initrd boot. suspend Suspend the system. This will trigger activation of the special suspend.target target. hibernate Hibernate the system. This will trigger activation of the special hibernate.target target. hybrid-sleep Hibernate and suspend the system. This will trigger activation of the special hybrid-sleep.target target.
Parameter Syntax Unit commands listed above take either a single unit name (designated as NAME), or multiple unit specifications (designated as PATTERN...). In the first case, the unit name with or without a suffix must be given. If the suffix is not specified (unit name is "abbreviated"), systemctl will append a suitable suffix, .service by default, and a type-specific suffix in case of commands which operate only on specific unit types. For example, # systemctl start sshd and # systemctl start sshd.service are equivalent, as are # systemctl isolate default and # systemctl isolate default.target Note that (absolute) paths to device nodes are automatically converted to device unit names, and other (absolute) paths to mount unit names. # systemctl status /dev/sda # systemctl status /home are equivalent to: # systemctl status dev-sda.device # systemctl status home.mount In the second case, shell-style globs will be matched against the primary names of all currently loaded units; literal unit names, with or without a suffix, will be treated as in the first case. This means that literal unit names always refer to exactly one unit, but globs may match zero units and this is not considered an error. Glob patterns use fnmatch3, so normal shell-style globbing rules are used, and *, ?, [] may be used. See glob7 for more details. The patterns are matched against the primary names of currently loaded units, and patterns which do not match anything are silently skipped. For example: # systemctl stop sshd@*.service will stop all sshd@.service instances. Note that alias names of units, and units that aren't loaded are not considered for glob expansion. For unit file commands, the specified NAME should be the name of the unit file (possibly abbreviated, see above), or the absolute path to the unit file: # systemctl enable foo.service or # systemctl link /path/to/foo.service
Exit status On success, 0 is returned, a non-zero failure code otherwise. Environment $SYSTEMD_EDITOR Editor to use when editing units; overrides $EDITOR and $VISUAL. If neither $SYSTEMD_EDITOR nor $EDITOR nor $VISUAL are present or if it is set to an empty string or if their execution failed, systemctl will try to execute well known editors in this order: editor1, nano1, vim1, vi1. See Also systemd1, journalctl1, loginctl1, machinectl1, systemd.unit5, systemd.resource-control5, systemd.special7, wall1, systemd.preset5, systemd.generator7, glob7
systemd-229/man/systemd-activate.xml000066400000000000000000000204541265713322000176510ustar00rootroot00000000000000 systemd-activate systemd Developer Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl systemd-activate 8 systemd-activate Test socket activation of daemons /usr/lib/systemd/systemd-activate OPTIONS daemon OPTIONS Description systemd-activate may be used to launch a socket-activated service binary from the command line for testing purposes. It may also be used to launch individual instances of the service binary per connection. The daemon to launch and its options should be specified after options intended for systemd-activate. If the option is given, the socket file descriptor will be used as the standard input and output of the launched process. Otherwise, standard input and output will be inherited, and sockets will be passed through file descriptors 3 and higher. Sockets passed through $LISTEN_FDS to systemd-activate will be passed through to the daemon, in the original positions. Other sockets specified with will use consecutive descriptors. By default, systemd-activate listens on a stream socket, use and to listen on datagram or sequential packet sockets instead (see below). Options Listen on this address. Takes a string like 2000 or 127.0.0.1:2001. Launch an instance of the service binary for each connection and pass the connection socket. Listen on a datagram socket (SOCK_DGRAM), instead of a stream socket (SOCK_STREAM). May not be combined with . Listen on a sequential packet socket (SOCK_SEQPACKET), instead of a stream socket (SOCK_STREAM). May not be combined with . Use the inetd protocol for passing file descriptors, i.e. as standard input and standard output, instead of the new-style protocol for passing file descriptors using $LISTEN_FDS (see above). Add this variable to the environment of the launched process. If VAR is followed by =, assume that it is a variable–value pair. Otherwise, obtain the value from the environment of systemd-activate itself. NAME Specify a name for the activation file descriptors. This is equivalent to setting FileDescriptorName= in socket unit files, and enables use of sd_listen_fds_with_names3. Environment variables $LISTEN_FDS $LISTEN_PID $LISTEN_FDNAMES See sd_listen_fds3. $SYSTEMD_LOG_TARGET $SYSTEMD_LOG_LEVEL $SYSTEMD_LOG_COLOR $SYSTEMD_LOG_LOCATION Same as in systemd1. Examples Run an echo server on port 2000 $ /usr/lib/systemd/systemd-activate -l 2000 --inetd -a cat Run a socket-activated instance of <citerefentry><refentrytitle>systemd-journal-gatewayd</refentrytitle><manvolnum>8</manvolnum></citerefentry> $ /usr/lib/systemd/systemd-activate -l 19531 /usr/lib/systemd/systemd-journal-gatewayd See Also systemd1, systemd.socket5, systemd.service5, sd_listen_fds3, sd_listen_fds_with_names3, cat1 systemd-229/man/systemd-analyze.xml000066400000000000000000000346711265713322000175220ustar00rootroot00000000000000 systemd-analyze systemd Developer Lennart Poettering lennart@poettering.net Developer Harald Hoyer harald@redhat.com systemd-analyze 1 systemd-analyze Analyze system boot-up performance systemd-analyze OPTIONS time systemd-analyze OPTIONS blame systemd-analyze OPTIONS critical-chain UNIT systemd-analyze OPTIONS plot > file.svg systemd-analyze OPTIONS dot PATTERN > file.dot systemd-analyze OPTIONS dump systemd-analyze OPTIONS set-log-level LEVEL systemd-analyze OPTIONS set-log-target TARGET systemd-analyze OPTIONS verify FILES Description systemd-analyze may be used to determine system boot-up performance statistics and retrieve other state and tracing information from the system and service manager, and to verify the correctness of unit files. systemd-analyze time prints the time spent in the kernel before userspace has been reached, the time spent in the initial RAM disk (initrd) before normal system userspace has been reached, and the time normal system userspace took to initialize. Note that these measurements simply measure the time passed up to the point where all system services have been spawned, but not necessarily until they fully finished initialization or the disk is idle. systemd-analyze blame prints a list of all running units, ordered by the time they took to initialize. This information may be used to optimize boot-up times. Note that the output might be misleading as the initialization of one service might be slow simply because it waits for the initialization of another service to complete. systemd-analyze critical-chain [UNIT...] prints a tree of the time-critical chain of units (for each of the specified UNITs or for the default target otherwise). The time after the unit is active or started is printed after the "@" character. The time the unit takes to start is printed after the "+" character. Note that the output might be misleading as the initialization of one service might depend on socket activation and because of the parallel execution of units. systemd-analyze plot prints an SVG graphic detailing which system services have been started at what time, highlighting the time they spent on initialization. systemd-analyze dot generates textual dependency graph description in dot format for further processing with the GraphViz dot1 tool. Use a command line like systemd-analyze dot | dot -Tsvg > systemd.svg to generate a graphical dependency tree. Unless or is passed, the generated graph will show both ordering and requirement dependencies. Optional pattern globbing style specifications (e.g. *.target) may be given at the end. A unit dependency is included in the graph if any of these patterns match either the origin or destination node. systemd-analyze dump outputs a (usually very long) human-readable serialization of the complete server state. Its format is subject to change without notice and should not be parsed by applications. systemd-analyze set-log-level LEVEL changes the current log level of the systemd daemon to LEVEL (accepts the same values as described in systemd1). systemd-analyze set-log-target TARGET changes the current log target of the systemd daemon to TARGET (accepts the same values as , described in systemd1). systemd-analyze verify will load unit files and print warnings if any errors are detected. Files specified on the command line will be loaded, but also any other units referenced by them. This command works by prepending the directories for all command line arguments at the beginning of the unit load path, which means that all units files found in those directories will be used in preference to the unit files found in the standard locations, even if not listed explicitly. If no command is passed, systemd-analyze time is implied. Options The following options are understood: Operates on the user systemd instance. Operates on the system systemd instance. This is the implied default. When used in conjunction with the dot command (see above), selects which dependencies are shown in the dependency graph. If is passed, only dependencies of type After= or Before= are shown. If is passed, only dependencies of type Requires=, Requisite=, Wants= and Conflicts= are shown. If neither is passed, this shows dependencies of all these types. When used in conjunction with the dot command (see above), this selects which relationships are shown in the dependency graph. Both options require a glob7 pattern as an argument, which will be matched against the left-hand and the right-hand, respectively, nodes of a relationship. Each of these can be used more than once, in which case the unit name must match one of the values. When tests for both sides of the relation are present, a relation must pass both tests to be shown. When patterns are also specified as positional arguments, they must match at least one side of the relation. In other words, patterns specified with those two options will trim the list of edges matched by the positional arguments, if any are given, and fully determine the list of edges shown otherwise. timespan When used in conjunction with the critical-chain command (see above), also show units, which finished timespan earlier, than the latest unit in the same level. The unit of timespan is seconds unless specified with a different unit, e.g. "50ms". Do not invoke man to verify the existence of man pages listed in Documentation=. Exit status On success, 0 is returned, a non-zero failure code otherwise. Examples for <command>dot</command> Plots all dependencies of any unit whose name starts with <literal>avahi-daemon</literal> $ systemd-analyze dot 'avahi-daemon.*' | dot -Tsvg > avahi.svg $ eog avahi.svg Plots the dependencies between all known target units systemd-analyze dot --to-pattern='*.target' --from-pattern='*.target' | dot -Tsvg > targets.svg $ eog targets.svg Examples for <command>verify</command> The following errors are currently detected: unknown sections and directives, missing dependencies which are required to start the given unit, man pages listed in Documentation= which are not found in the system, commands listed in ExecStart= and similar which are not found in the system or not executable. Misspelt directives $ cat ./user.slice [Unit] WhatIsThis=11 Documentation=man:nosuchfile(1) Requires=different.service [Service] Desription=x $ systemd-analyze verify ./user.slice [./user.slice:9] Unknown lvalue 'WhatIsThis' in section 'Unit' [./user.slice:13] Unknown section 'Service'. Ignoring. Error: org.freedesktop.systemd1.LoadFailed: Unit different.service failed to load: No such file or directory. Failed to create user.slice/start: Invalid argument user.slice: man nosuchfile(1) command failed with code 16 Missing service units $ tail ./a.socket ./b.socket ==> ./a.socket <== [Socket] ListenStream=100 ==> ./b.socket <== [Socket] ListenStream=100 Accept=yes $ systemd-analyze verify ./a.socket ./b.socket Service a.service not loaded, a.socket cannot be started. Service b@0.service not loaded, b.socket cannot be started. See Also systemd1, systemctl1 systemd-229/man/systemd-ask-password-console.service.xml000066400000000000000000000072621265713322000235700ustar00rootroot00000000000000 systemd-ask-password-console.service systemd Developer Lennart Poettering lennart@poettering.net systemd-ask-password-console.service 8 systemd-ask-password-console.service systemd-ask-password-console.path systemd-ask-password-wall.service systemd-ask-password-wall.path Query the user for system passwords on the console and via wall systemd-ask-password-console.service systemd-ask-password-console.path systemd-ask-password-wall.service systemd-ask-password-wall.path Description systemd-ask-password-console.service is a system service that queries the user for system passwords (such as hard disk encryption keys and SSL certificate passphrases) on the console. It is intended to be used during boot to ensure proper handling of passwords necessary for boot. systemd-ask-password-wall.service is a system service that informs all logged in users for system passwords via wall1. It is intended to be used after boot to ensure that users are properly notified. See the developer documentation for more information about the system password logic. Note that these services invoke systemd-tty-ask-password-agent1 with either the --watch --console or --watch --wall command line parameters. See Also systemd1, systemd-tty-ask-password-agent1, wall1 systemd-229/man/systemd-ask-password.xml000066400000000000000000000204161265713322000204650ustar00rootroot00000000000000 systemd-ask-password systemd Developer Lennart Poettering lennart@poettering.net systemd-ask-password 1 systemd-ask-password Query the user for a system password systemd-ask-password OPTIONS MESSAGE Description systemd-ask-password may be used to query a system password or passphrase from the user, using a question message specified on the command line. When run from a TTY it will query a password on the TTY and print it to standard output. When run with no TTY or with it will query the password system-wide and allow active users to respond via several agents. The latter is only available to privileged processes. The purpose of this tool is to query system-wide passwords -- that is passwords not attached to a specific user account. Examples include: unlocking encrypted hard disks when they are plugged in or at boot, entering an SSL certificate passphrase for web and VPN servers. Existing agents are: A boot-time password agent asking the user for passwords using Plymouth A boot-time password agent querying the user directly on the console An agent requesting password input via a wall1 message A command line agent which can be started temporarily to process queued password requests A TTY agent that is temporarily spawned during systemctl1 invocations Additional password agents may be implemented according to the systemd Password Agent Specification. If a password is queried on a TTY, the user may press TAB to hide the asterisks normally shown for each character typed. Pressing Backspace as first key achieves the same effect. Options The following options are understood: Specify an icon name alongside the password query, which may be used in all agents supporting graphical display. The icon name should follow the XDG Icon Naming Specification. Specify an identifier for this password query. This identifier is freely choosable and allows recognition of queries by involved agents. It should include the subsystem doing the query and the specific object the query is done for. Example: --id=cryptsetup:/dev/sda5. Configure a kernel keyring key name to use as cache for the password. If set, then the tool will try to push any collected passwords into the kernel keyring of the root user, as a key of the specified name. If combined with , it will also try to retrieve such cached passwords from the key in the kernel keyring instead of querying the user right away. By using this option, the kernel keyring may be used as effective cache to avoid repeatedly asking users for passwords, if there are multiple objects that may be unlocked with the same password. The cached key will have a timeout of 2.5min set, after which it will be purged from the kernel keyring. Note that it is possible to cache multiple passwords under the same keyname, in which case they will be stored as NUL-separated list of passwords. Use keyctl1 to access the cached key via the kernel keyring directly. Example: --keyname=cryptsetup Specify the query timeout in seconds. Defaults to 90s. A timeout of 0 waits indefinitely. Echo the user input instead of masking it. This is useful when using systemd-ask-password to query for usernames. Never ask for password on current TTY even if one is available. Always use agent system. If passed, accept cached passwords, i.e. passwords previously entered. When used in conjunction with accept multiple passwords. This will output one password per line. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, systemctl1, keyctl1, plymouth8, wall1 systemd-229/man/systemd-backlight@.service.xml000066400000000000000000000063661265713322000215460ustar00rootroot00000000000000 systemd-backlight@.service systemd Developer Lennart Poettering lennart@poettering.net systemd-backlight@.service 8 systemd-backlight@.service systemd-backlight Load and save the display backlight brightness at boot and shutdown systemd-backlight@.service /usr/lib/systemd/systemd-backlight Description systemd-backlight@.service is a service that restores the display backlight brightness at early boot and saves it at shutdown. On disk, the backlight brightness is stored in /var/lib/systemd/backlight/. During loading, if the udev property is not set to false, the brightness is clamped to a value of at least 1 or 5% of maximum brightness, whichever is greater. This restriction will be removed when the kernel allows user space to reliably set a brightness value which does not turn off the display. Kernel Command Line systemd-backlight understands the following kernel command line parameter: systemd.restore_state= Takes a boolean argument. Defaults to 1. If 0, does not restore the backlight settings on boot. However, settings will still be stored on shutdown. See Also systemd1 systemd-229/man/systemd-binfmt.service.xml000066400000000000000000000050341265713322000207640ustar00rootroot00000000000000 systemd-binfmt.service systemd Developer Lennart Poettering lennart@poettering.net systemd-binfmt.service 8 systemd-binfmt.service systemd-binfmt Configure additional binary formats for executables at boot systemd-binfmt.service /usr/lib/systemd/systemd-binfmt Description systemd-binfmt.service is an early boot service that registers additional binary formats for executables in the kernel. See binfmt.d5 for information about the configuration of this service. See Also systemd1, binfmt.d5, wine8 systemd-229/man/systemd-bootchart.xml000066400000000000000000000275211265713322000200400ustar00rootroot00000000000000 systemd-bootchart systemd Developer Auke Kok auke-jan.h.kok@intel.com systemd-bootchart 1 systemd-bootchart Boot performance graphing tool Description systemd-bootchart is a tool, usually run at system startup, that collects the CPU load, disk load, memory usage, as well as per-process information from a running system. Collected results are output as an SVG graph. Normally, systemd-bootchart is invoked by the kernel by passing on the kernel command line. systemd-bootchart will then fork the real init off to resume normal system startup, while monitoring and logging startup information in the background. After collecting a certain amount of data (usually 15–30 seconds, default 20 s) the logging stops and a graph is generated from the logged information. This graph contains vital clues as to which resources are being used, in which order, and where possible problems exist in the startup sequence of the system. It is essentially a more detailed version of the systemd-analyze plot function. Of course, bootchart can also be used at any moment in time to collect and graph some data for an amount of time. It is recommended to use the switch in this case. Bootchart does not require root privileges, and will happily run as a normal user. Bootchart graphs are by default written time-stamped in /run/log and saved to the journal with MESSAGE_ID=9f26aa562cf440c2b16c773d0479b518. Journal field BOOTCHART= contains the bootchart in SVG format. Invocation systemd-bootchart can be invoked in several different ways: Kernel invocation The kernel can invoke systemd-bootchart instead of the init process. In turn, systemd-bootchart will invoke /usr/lib/systemd/systemd. Started as a standalone program One can execute systemd-bootchart as normal application from the command line. In this mode, it is highly recommended to pass the flag in order to not graph the time elapsed since boot and before systemd-bootchart was started, as it may result in extremely large graphs. The time elapsed since boot might also include any time that the system was suspended. Options These options can also be set in the /etc/systemd/bootchart.conf file. See bootchart.conf5. Specify the number of samples, N, to record. Samples will be recorded at intervals defined with . Specify the sample log frequency, a positive real f, in Hz. Most systems can cope with values up to 25–50 without creating too much overhead. Use relative times instead of absolute times. This is useful for using bootchart at post-boot time to profile an already booted system. Without this option the graph would become extremely large. If set, the horizontal axis starts at the first recorded sample instead of time 0.0. Disable filtering of tasks that did not contribute significantly to the boot. Processes that are too short-lived (only seen in one sample) or that do not consume any significant CPU time (less than 0.001 s) will not be displayed in the output graph. Display the full command line with arguments of processes, instead of only the process name. Display process control group Specify the output directory for the graphs. By default, bootchart writes the graphs to /run/log. Use this init binary. Defaults to /usr/lib/systemd/systemd. Enable logging and graphing of processes' PSS (Proportional Set Size) memory consumption. See filesystems/proc.txt in the kernel documentation for an explanation of this field. Enable logging and graphing of the kernel random entropy pool size. Horizontal scaling factor for all variable graph components. Vertical scaling factor for all variable graph components. Output systemd-bootchart generates SVG graphs. In order to render those on a graphical display any SVG capable viewer can be used. It should be noted that the SVG render engines in most browsers (including Chrome and Firefox) are many times faster than dedicated graphical applications like Gimp and Inkscape. Just point your browser at ! History This version of bootchart was implemented from scratch, but is inspired by former bootchart incantations: Original bash The original bash/shell code implemented bootchart. This version created a compressed tarball for processing with external applications. This version did not graph anything, only generated data. Ubuntu C Implementation This version replaced the shell version with a fast and efficient data logger, but also did not graph the data. Java bootchart This was the original graphing application for charting the data, written in java. pybootchartgui.py pybootchart created a graph from the data collected by either the bash or C version. The version of bootchart you are using now combines both the data collection and the charting into a single application, making it more efficient and simpler. There are no longer any timing issues with the data collector and the grapher, as the graphing cannot be run until the data has been collected. Also, the data kept in memory is reduced to the absolute minimum needed. See Also bootchart.conf5 Bugs systemd-bootchart does not get the model information for the hard drive unless the root device is specified with root=/dev/sdxY. Using UUIDs or PARTUUIDs will boot fine, but the hard drive model will not be added to the chart. For bugs, please contact the author and current maintainer: Auke Kok auke-jan.h.kok@intel.com systemd-229/man/systemd-bus-proxyd.service.xml000066400000000000000000000053321265713322000216220ustar00rootroot00000000000000 systemd-bus-proxyd.service systemd Developer Lennart Poettering lennart@poettering.net systemd-bus-proxyd.service 8 systemd-bus-proxyd.service systemd-bus-proxyd.socket Proxy classic D-Bus clients to kdbus systemd-bus-proxyd.service systemd-bus-proxyd.socket Description systemd-bus-proxyd.socket will launch systemd-bus-proxyd.service for connections to the classic D-Bus socket in /var/run/dbus/system_bus_socket. systemd-bus-proxyd.service is launched for an existing D-Bus connection and will use systemd-bus-proxyd to proxy messages from this connection to the system bus (either kdbus or classic D-Bus). See Also systemd-bus-proxyd8, dbus-daemon1, D-Bus systemd-229/man/systemd-bus-proxyd.xml000066400000000000000000000072141265713322000201640ustar00rootroot00000000000000 systemd-bus-proxyd systemd Developer Lennart Poettering lennart@poettering.net systemd-bus-proxyd 8 systemd-bus-proxyd Connect STDIO or a socket to a given bus address /usr/lib/systemd/systemd-bus-proxyd OPTIONS PLACEHOLDER Description systemd-bus-proxyd will proxy D-Bus messages to and from a bus. The will be either the system bus or the bus specified with when that option is given. Messages will be proxied to/from standard input and output, or the socket received through socket activation. This program can be used to connect a program using classic D-Bus to kdbus. Options and Arguments The following options are understood: Connect to the bus specified by ADDRESS. Multiple colon-separated addresses can be specified, in which case systemd-bus-proxyd will attempt to connect to them in turn. PLACEHOLDER, if given, must be a string of x and will be used to display information about the process that systemd-bus-proxyd is forwarding messages for. See Also dbus-daemon1, D-Bus systemd-229/man/systemd-cat.xml000066400000000000000000000137751265713322000166300ustar00rootroot00000000000000 systemd-cat systemd Developer Lennart Poettering lennart@poettering.net systemd-cat 1 systemd-cat Connect a pipeline or program's output with the journal systemd-cat OPTIONS COMMAND ARGUMENTS systemd-cat OPTIONS Description systemd-cat may be used to connect the standard input and output of a process to the journal, or as a filter tool in a shell pipeline to pass the output the previous pipeline element generates to the journal. If no parameter is passed, systemd-cat will write everything it reads from standard input (stdin) to the journal. If parameters are passed, they are executed as command line with standard output (stdout) and standard error output (stderr) connected to the journal, so that all it writes is stored in the journal. Options The following options are understood: Specify a short string that is used to identify the logging tool. If not specified, no identification string is written to the journal. Specify the default priority level for the logged messages. Pass one of emerg, alert, crit, err, warning, notice, info, debug, or a value between 0 and 7 (corresponding to the same named levels). These priority values are the same as defined by syslog3. Defaults to info. Note that this simply controls the default, individual lines may be logged with different levels if they are prefixed accordingly. For details, see below. Controls whether lines read are parsed for syslog priority level prefixes. If enabled (the default), a line prefixed with a priority prefix such as <5> is logged at priority 5 (notice), and similar for the other priority levels. Takes a boolean argument. Exit status On success, 0 is returned, a non-zero failure code otherwise. Examples Invoke a program This calls /bin/ls with standard output and error connected to the journal: # systemd-cat ls Usage in a shell pipeline This builds a shell pipeline also invoking /bin/ls and writes the output it generates to the journal: # ls | systemd-cat Even though the two examples have very similar effects the first is preferable since only one process is running at a time, and both stdout and stderr are captured while in the second example, only stdout is captured. See Also systemd1, systemctl1, logger1 systemd-229/man/systemd-cgls.xml000066400000000000000000000110401265713322000167700ustar00rootroot00000000000000 systemd-cgls systemd Developer Lennart Poettering lennart@poettering.net systemd-cgls 1 systemd-cgls Recursively show control group contents systemd-cgls OPTIONS CGROUP Description systemd-cgls recursively shows the contents of the selected Linux control group hierarchy in a tree. If arguments are specified, shows all member processes of the specified control groups plus all their subgroups and their members. The control groups may either be specified by their full file paths or are assumed in the systemd control group hierarchy. If no argument is specified and the current working directory is beneath the control group mount point /sys/fs/cgroup, shows the contents of the control group the working directory refers to. Otherwise, the full systemd control group hierarchy is shown. By default, empty control groups are not shown. Options The following options are understood: Do not hide empty control groups in the output. Do not ellipsize process tree members. Include kernel threads in output. Limit control groups shown to the part corresponding to the container MACHINE. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, systemctl1, systemd-cgtop1, systemd-nspawn1, ps1 systemd-229/man/systemd-cgtop.xml000066400000000000000000000332661265713322000171720ustar00rootroot00000000000000 systemd-cgtop systemd Developer Lennart Poettering lennart@poettering.net systemd-cgtop 1 systemd-cgtop Show top control groups by their resource usage systemd-cgtop OPTIONS Description systemd-cgtop shows the top control groups of the local Linux control group hierarchy, ordered by their CPU, memory, or disk I/O load. The display is refreshed in regular intervals (by default every 1s), similar in style to top1. If systemd-cgtop is not connected to a tty, no column headers are printed and the default is to only run one iteration. The --iterations= argument, if given, is honored. This mode is suitable for scripting. Resource usage is only accounted for control groups in the relevant hierarchy, i.e. CPU usage is only accounted for control groups in the cpuacct hierarchy, memory usage only for those in memory and disk I/O usage for those in blkio. If resource monitoring for these resources is required, it is recommended to add the CPUAccounting=1, MemoryAccounting=1 and BlockIOAccounting=1 settings in the unit files in question. See systemd.resource-control5 for details. The CPU load value can be between 0 and 100 times the number of processors the system has. For example, if the system has 8 processors, the CPU load value is going to be between 0% and 800%. The number of processors can be found in /proc/cpuinfo. To emphasize this: unless CPUAccounting=1, MemoryAccounting=1 and BlockIOAccounting=1 are enabled for the services in question, no resource accounting will be available for system services and the data shown by systemd-cgtop will be incomplete. Options The following options are understood: Order by control group path name. Order by number of tasks/processes in the control group. Order by CPU load. Order by memory usage. Order by disk I/O load. Run in "batch" mode: do not accept input and run until the iteration limit set with is exhausted or until killed. This mode could be useful for sending output from systemd-cgtop to other programs or to a file. Format byte counts (as in memory usage and I/O metrics) with raw numeric values rather than human-readable numbers. Controls whether the CPU usage is shown as percentage or time. By default, the CPU usage is shown as percentage. This setting may also be toggled at runtime by pressing the % key. Count only userspace processes instead of all tasks. By default, all tasks are counted: each kernel thread and each userspace thread individually. With this setting, kernel threads are excluded from the counting and each userspace process only counts as one, regardless how many threads it consists of. This setting may also be toggled at runtime by pressing the P key. This option may not be combined with . Count only userspace processes and kernel threads instead of all tasks. By default, all tasks are counted: each kernel thread and each userspace thread individually. With this setting, kernel threads are included in the counting and each userspace process only counts as on one, regardless how many threads it consists of. This setting may also be toggled at runtime by pressing the k key. This option may not be combined with . Controls whether the number of processes shown for a control group shall include all processes that are contained in any of the child control groups as well. Takes a boolean argument, which defaults to yes. If enabled, the processes in child control groups are included, if disabled, only the processes in the control group itself are counted. This setting may also be toggled at runtime by pressing the r key. Note that this setting only applies to process counting, i.e. when the or options are used. It has not effect if all tasks are counted, in which case the counting is always recursive. Perform only this many iterations. A value of 0 indicates that the program should run indefinitely. Specify refresh delay in seconds (or if one of ms, us, min is specified as unit in this time unit). This setting may also be increased and decreased at runtime by pressing the + and - keys. Maximum control group tree traversal depth. Specifies how deep systemd-cgtop shall traverse the control group hierarchies. If 0 is specified, only the root group is monitored. For 1, only the first level of control groups is monitored, and so on. Defaults to 3. Limit control groups shown to the part corresponding to the container MACHINE. Keys systemd-cgtop is an interactive tool and may be controlled via user input using the following keys: h Shows a short help text. Immediately refresh output. q Terminate the program. p t c m i Sort the control groups by path, number of tasks, CPU load, memory usage, or I/O load, respectively. This setting may also be controlled using the command line switch. % Toggle between showing CPU time as time or percentage. This setting may also be controlled using the command line switch. + - Increase or decrease refresh delay, respectively. This setting may also be controlled using the command line switch. P Toggle between counting all tasks, or only userspace processes. This setting may also be controlled using the command line switch (see above). k Toggle between counting all tasks, or only userspace processes and kernel threads. This setting may also be controlled using the command line switch (see above). r Toggle between recursively including or excluding processes in child control groups in control group process counts. This setting may also be controlled using the command line switch. This key is not available if all tasks are counted, it is only available if processes are counted, as enabled with the P or k keys. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, systemctl1, systemd-cgls1, systemd.resource-control5, top1 systemd-229/man/systemd-coredump.xml000066400000000000000000000110661265713322000176660ustar00rootroot00000000000000 systemd-coredump systemd Developer Lennart Poettering lennart@poettering.net systemd-coredump 8 systemd-coredump Log and store core dumps /usr/lib/systemd/systemd-coredump Description systemd-coredump can be used as a helper binary by the kernel when a user space program receives a fatal signal and dumps core. For it to be used in this capacity, it must be specified by the kernel.core_pattern sysctl8 setting. Systemd installs /usr/lib/sysctl.d/50-coredump.conf which configures kernel.core_pattern to invoke systemd-coredump. This file may be masked or overridden to use a different setting following normal sysctl.d5 rules. The behavior of a specific program upon reception of a signal is governed by a few factors which are described in detail in core5. In particular, the coredump will only be processed when the related resource limits are high enough. For programs started by systemd, those may be set using LimitCore= (see systemd.exec5). systemd-coredump will log the coredump including a backtrace if possible, and store the core (contents of process' memory contents) in an external file on disk in /var/lib/systemd/coredump, or directly in the journal. This behavior may be modified using coredump.conf5. Apart from the journalctl1 log viewer, coredumpctl1 may be used to list and extract coredumps. See Also coredump.conf5, coredumpctl1, systemd-journald.service8, core5, sysctl.d5, systemd-sysctl.service8. systemd-229/man/systemd-cryptsetup-generator.xml000066400000000000000000000174661265713322000222700ustar00rootroot00000000000000 systemd-cryptsetup-generator systemd Developer Lennart Poettering lennart@poettering.net systemd-cryptsetup-generator 8 systemd-cryptsetup-generator Unit generator for /etc/crypttab /usr/lib/systemd/system-generators/systemd-cryptsetup-generator Description systemd-cryptsetup-generator is a generator that translates /etc/crypttab into native systemd units early at boot and when configuration of the system manager is reloaded. This will create systemd-cryptsetup@.service8 units as necessary. systemd-cryptsetup-generator implements systemd.generator7. Kernel Command Line systemd-cryptsetup-generator understands the following kernel command line parameters: luks= rd.luks= Takes a boolean argument. Defaults to yes. If no, disables the generator entirely. rd.luks= is honored only by initial RAM disk (initrd) while luks= is honored by both the main system and the initrd. luks.crypttab= rd.luks.crypttab= Takes a boolean argument. Defaults to yes. If no, causes the generator to ignore any devices configured in /etc/crypttab (luks.uuid= will still work however). rd.luks.crypttab= is honored only by initial RAM disk (initrd) while luks.crypttab= is honored by both the main system and the initrd. luks.uuid= rd.luks.uuid= Takes a LUKS superblock UUID as argument. This will activate the specified device as part of the boot process as if it was listed in /etc/crypttab. This option may be specified more than once in order to set up multiple devices. rd.luks.uuid= is honored only by initial RAM disk (initrd) while luks.uuid= is honored by both the main system and the initrd. If /etc/crypttab contains entries with the same UUID, then the name, keyfile and options specified there will be used. Otherwise, the device will have the name luks-UUID. If /etc/crypttab exists, only those UUIDs specified on the kernel command line will be activated in the initrd or the real root. luks.name= rd.luks.name= Takes a LUKS super block UUID followed by an = and a name. This implies rd.luks.uuid= or luks.uuid= and will additionally make the LUKS device given by the UUID appear under the provided name. rd.luks.name= is honored only by initial RAM disk (initrd) while luks.name= is honored by both the main system and the initrd. luks.options= rd.luks.options= Takes a LUKS super block UUID followed by an = and a string of options separated by commas as argument. This will override the options for the given UUID. If only a list of options, without an UUID, is specified, they apply to any UUIDs not specified elsewhere, and without an entry in /etc/crypttab. rd.luks.options= is honored only by initial RAM disk (initrd) while luks.options= is honored by both the main system and the initrd. luks.key= rd.luks.key= Takes a password file name as argument or a LUKS super block UUID followed by a = and a password file name. For those entries specified with rd.luks.uuid= or luks.uuid=, the password file will be set to the one specified by rd.luks.key= or luks.key= of the corresponding UUID, or the password file that was specified without a UUID. rd.luks.key= is honored only by initial RAM disk (initrd) while luks.key= is honored by both the main system and the initrd. See Also systemd1, crypttab5, systemd-cryptsetup@.service8, cryptsetup8, systemd-fstab-generator8 systemd-229/man/systemd-cryptsetup@.service.xml000066400000000000000000000062641265713322000220350ustar00rootroot00000000000000 systemd-cryptsetup@.service systemd Developer Lennart Poettering lennart@poettering.net systemd-cryptsetup@.service 8 systemd-cryptsetup@.service systemd-cryptsetup Full disk decryption logic systemd-cryptsetup@.service /usr/lib/systemd/systemd-cryptsetup Description systemd-cryptsetup@.service is a service responsible for setting up encrypted block devices. It is instantiated for each device that requires decryption for access. systemd-cryptsetup@.service will ask for hard disk passwords via the password agent logic, in order to query the user for the password using the right mechanism at boot and during runtime. At early boot and when the system manager configuration is reloaded this /etc/crypttab is translated into systemd-cryptsetup@.service units by systemd-cryptsetup-generator8. See Also systemd1, systemd-cryptsetup-generator8, crypttab5, cryptsetup8 systemd-229/man/systemd-debug-generator.xml000066400000000000000000000072151265713322000211230ustar00rootroot00000000000000 systemd-debug-generator systemd Developer Lennart Poettering lennart@poettering.net systemd-debug-generator 8 systemd-debug-generator Generator for enabling a runtime debug shell and masking specific units at boot /usr/lib/systemd/system-generators/systemd-debug-generator Description systemd-debug-generator is a generator that reads the kernel command line and understands three options: If the option is specified and followed by a unit name, this unit is masked for the runtime, similar to the effect of systemctl1's mask command. This is useful to boot with certain units removed from the initial boot transaction for debugging system startup. May be specified more than once. If the option is specified and followed by a unit name, a start job for this unit is added to the initial transaction. This is useful to start one or more additional units at boot. May be specified more than once. If the option is specified, the debug shell service debug-shell.service is pulled into the boot transaction. It will spawn a debug shell on tty9 during early system startup. Note that the shell may also be turned on persistently by enabling it with systemctl1's enable command. systemd-debug-generator implements systemd.generator7. See Also systemd1, systemctl1, kernel-command-line7 systemd-229/man/systemd-delta.xml000066400000000000000000000163321265713322000171420ustar00rootroot00000000000000 systemd-delta systemd Developer Lennart Poettering lennart@poettering.net systemd-delta 1 systemd-delta Find overridden configuration files systemd-delta OPTIONS PREFIX/SUFFIX|SUFFIX Description systemd-delta may be used to identify and compare configuration files that override other configuration files. Files in /etc have highest priority, files in /run have the second highest priority, ..., files in /lib have lowest priority. Files in a directory with higher priority override files with the same name in directories of lower priority. In addition, certain configuration files can have .d directories which contain "drop-in" files with configuration snippets which augment the main configuration file. "Drop-in" files can be overridden in the same way by placing files with the same name in a directory of higher priority (except that, in case of "drop-in" files, both the "drop-in" file name and the name of the containing directory, which corresponds to the name of the main configuration file, must match). For a fuller explanation, see systemd.unit5. The command line argument will be split into a prefix and a suffix. Either is optional. The prefix must be one of the directories containing configuration files (/etc, /run, /usr/lib, ...). If it is given, only overriding files contained in this directory will be shown. Otherwise, all overriding files will be shown. The suffix must be a name of a subdirectory containing configuration files like tmpfiles.d, sysctl.d or systemd/system. If it is given, only configuration files in this subdirectory (across all configuration paths) will be analyzed. Otherwise, all configuration files will be analyzed. If the command line argument is not given at all, all configuration files will be analyzed. See below for some examples. Options The following options are understood: When listing the differences, only list those that are asked for. The list itself is a comma-separated list of desired difference types. Recognized types are: masked Show masked files equivalent Show overridden files that while overridden, do not differ in content. redirected Show files that are redirected to another. overridden Show overridden, and changed files. extended Show *.conf files in drop-in directories for units. unchanged Show unmodified files too. When showing modified files, when a file is overridden show a diff as well. This option takes a boolean argument. If omitted, it defaults to . Examples To see all local configuration: systemd-delta To see all runtime configuration: systemd-delta /run To see all system unit configuration changes: systemd-delta systemd/system To see all runtime "drop-in" changes for system units: systemd-delta --type=extended /run/systemd/system Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, systemd.unit5 systemd-229/man/systemd-detect-virt.xml000066400000000000000000000176711265713322000203120ustar00rootroot00000000000000 systemd-detect-virt systemd Developer Lennart Poettering lennart@poettering.net systemd-detect-virt 1 systemd-detect-virt Detect execution in a virtualized environment systemd-detect-virt OPTIONS Description systemd-detect-virt detects execution in a virtualized environment. It identifies the virtualization technology and can distinguish full machine virtualization from container virtualization. systemd-detect-virt exits with a return value of 0 (success) if a virtualization technology is detected, and non-zero (error) otherwise. By default, any type of virtualization is detected, and the options and can be used to limit what types of virtualization are detected. When executed without will print a short identifier for the detected virtualization technology. The following technologies are currently identified: Known virtualization technologies (both VM, i.e. full hardware virtualization, and container, i.e. shared kernel virtualization) Type ID Product VM qemu QEMU software virtualization kvm Linux KVM kernel virtual machine zvm s390 z/VM vmware VMware Workstation or Server, and related products microsoft Hyper-V, also known as Viridian or Windows Server Virtualization oracle Oracle VM VirtualBox (historically marketed by innotek and Sun Microsystems) xen Xen hypervisor (only domU, not dom0) bochs Bochs Emulator uml User-mode Linux parallels Parallels Desktop, Parallels Server Container openvz OpenVZ/Virtuozzo lxc Linux container implementation by LXC lxc-libvirt Linux container implementation by libvirt systemd-nspawn systemd's minimal container implementation, see systemd-nspawn1 docker Docker container manager rkt rkt app container runtime
If multiple virtualization solutions are used, only the "innermost" is detected and identified. That means if both machine and container virtualization are used in conjunction, only the latter will be identified (unless is passed).
Options The following options are understood: Only detects container virtualization (i.e. shared kernel virtualization). Only detects hardware virtualization). Detect whether invoked in a chroot2 environment. In this mode, no output is written, but the return value indicates whether the process was invoked in a chroot() environment or not. Suppress output of the virtualization technology identifier. Exit status If a virtualization technology is detected, 0 is returned, a non-zero code otherwise. See Also systemd1, systemd-nspawn1, chroot2
systemd-229/man/systemd-escape.xml000066400000000000000000000142141265713322000173060ustar00rootroot00000000000000 systemd-escape systemd Developer Lennart Poettering lennart@poettering.net systemd-escape 1 systemd-escape Escape strings for usage in system unit names systemd-escape OPTIONS STRING Description systemd-escape may be used to escape strings for inclusion in systemd unit names. The command may be used to escape and to undo escaping of strings. The command takes any number of strings on the command line, and will process them individually, one after another. It will output them separated by spaces to stdout. By default, this command will escape the strings passed, unless is passed which results in the inverse operation being applied. If is given, a special mode of escaping is applied instead, which assumes the string is already escaped but will escape everything that appears obviously non-escaped. Options The following options are understood: Appends the specified unit type suffix to the escaped string. Takes one of the unit types supported by systemd, such as .service or .mount. May not be used in conjunction with , or . Inserts the escaped strings in a unit name template. Takes a unit name template such as foobar@.service May not be used in conjunction with , or . When escaping or unescaping a string, assume it refers to a file system path. This enables special processing of the initial / of the path. Instead of escaping the specified strings, undo the escaping, reversing the operation. May not be used in conjunction with , or . Like , but only escape characters that are obviously not escaped yet, and possibly automatically append an appropriate unit type suffix to the string. May not be used in conjunction with , or . Examples Escape a single string: $ systemd-escape 'Hallöchen, Meister' Hall\xc3\xb6chen\x2c\x20Meister To undo escaping on a single string: $ systemd-escape -u 'Hall\xc3\xb6chen\x2c\x20Meister' Hallöchen, Meister To generate the mount unit for a path: $ systemd-escape -p --suffix=mount "/tmp//waldi/foobar/" tmp-waldi-foobar.mount To generate instance names of three strings $ systemd-escape --template=systemd-nspawn@.service 'My Container 1' 'containerb' 'container/III' systemd-nspawn@My\x20Container\x201.service systemd-nspawn@containerb.service systemd-nspawn@container-III.service Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, systemctl1 systemd-229/man/systemd-firstboot.xml000066400000000000000000000246251265713322000200700ustar00rootroot00000000000000 systemd-firstboot systemd Developer Lennart Poettering lennart@poettering.net systemd-firstboot 1 systemd-firstboot systemd-firstboot.service Initialize basic system settings on or before the first boot-up of a system systemd-firstboot OPTIONS systemd-firstboot.service Description systemd-firstboot initializes the most basic system settings interactively on the first boot, or optionally non-interactively when a system image is created. The following settings may be set up: The system locale, more specifically the two locale variables LANG= and LC_MESSAGES The system time zone The system host name The machine ID of the system The root user's password Each of the fields may either be queried interactively by users, set non-interactively on the tool's command line, or be copied from a host system that is used to set up the system image. If a setting is already initialized, it will not be overwritten and the user will not be prompted for the setting. Note that this tool operates directly on the file system and does not involve any running system services, unlike localectl1, timedatectl1 or hostnamectl1. This allows systemd-firstboot to operate on mounted but not booted disk images and in early boot. It is not recommended to use systemd-firstboot on the running system while it is up. Options The following options are understood: Takes a directory path as an argument. All paths will be prefixed with the given alternate root path, including config search paths. This is useful to operate on a system image mounted to the specified directory instead of the host system itself. Sets the system locale, more specifically the LANG= and LC_MESSAGES settings. The argument should be a valid locale identifier, such as de_DE.UTF-8. This controls the locale.conf5 configuration file. Sets the system time zone. The argument should be a valid time zone identifier, such as Europe/Berlin. This controls the localtime5 symlink. Sets the system hostname. The argument should be a host name, compatible with DNS. This controls the hostname5 configuration file. Sets the system's machine ID. This controls the machine-id5 file. Sets the password of the system's root user. This creates a shadow5 file. This setting exists in two forms: accepts the password to set directly on the command line, and reads it from a file. Note that it is not recommended to specify passwords on the command line, as other users might be able to see them simply by invoking ps1. Prompt the user interactively for a specific basic setting. Note that any explicit configuration settings specified on the command line take precedence, and the user is not prompted for it. Query the user for locale, timezone, hostname and root password. This is equivalent to specifying , , , in combination. Copy a specific basic setting from the host. This only works in combination with (see above). Copy locale, time zone and root password from the host. This is equivalent to specifying , , in combination. Initialize the system's machine ID to a random ID. This only works in combination with . Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, locale.conf5, localtime5, hostname5, machine-id5, shadow5, systemd-machine-id-setup1, localectl1, timedatectl1, hostnamectl1 systemd-229/man/systemd-fsck@.service.xml000066400000000000000000000137671265713322000205470ustar00rootroot00000000000000 systemd-fsck@.service systemd Developer Lennart Poettering lennart@poettering.net systemd-fsck@.service 8 systemd-fsck@.service systemd-fsck-root.service systemd-fsck File system checker logic systemd-fsck@.service systemd-fsck-root.service /usr/lib/systemd/systemd-fsck Description systemd-fsck@.service and systemd-fsck-root.service are services responsible for file system checks. They are instantiated for each device that is configured for file system checking. systemd-fsck-root.service is responsible for file system checks on the root file system, but only if the root filesystem was not checked in the initramfs. systemd-fsck@.service is used for all other file systems and for the root file system in the initramfs. These services are started at boot if in /etc/fstab for the file system is set to a value greater than zero. The file system check for root is performed before the other file systems. Other file systems may be checked in parallel, except when they are on the same rotating disk. systemd-fsck does not know any details about specific filesystems, and simply executes file system checkers specific to each filesystem type (/sbin/fsck.*). This helper will decide if the filesystem should actually be checked based on the time since last check, number of mounts, unclean unmount, etc. If a file system check fails for a service without , emergency mode is activated, by isolating to emergency.target. Kernel Command Line systemd-fsck understands one kernel command line parameter: fsck.mode= One of auto, force, skip. Controls the mode of operation. The default is auto, and ensures that file system checks are done when the file system checker deems them necessary. force unconditionally results in full file system checks. skip skips any file system checks. fsck.repair= One of preen, yes, no. Controls the mode of operation. The default is preen, and will automatically repair problems that can be safely fixed. yes will answer yes to all questions by fsck and no will answer no to all questions. See Also systemd1, fsck8, systemd-quotacheck.service8, fsck.btrfs8, fsck.cramfs8, fsck.ext48, fsck.fat8, fsck.hfsplus8, fsck.minix8, fsck.ntfs8, fsck.xfs8 systemd-229/man/systemd-fstab-generator.xml000066400000000000000000000161721265713322000211360ustar00rootroot00000000000000 systemd-fstab-generator systemd Developer Lennart Poettering lennart@poettering.net systemd-fstab-generator 8 systemd-fstab-generator Unit generator for /etc/fstab /usr/lib/systemd/system-generators/systemd-fstab-generator Description systemd-fstab-generator is a generator that translates /etc/fstab (see fstab5 for details) into native systemd units early at boot and when configuration of the system manager is reloaded. This will instantiate mount and swap units as necessary. The passno field is treated like a simple boolean, and the ordering information is discarded. However, if the root file system is checked, it is checked before all the other file systems. See systemd.mount5 and systemd.swap5 for more information about special /etc/fstab mount options this generator understands. systemd-fstab-generator implements systemd.generator7. Kernel Command Line systemd-fstab-generator understands the following kernel command line parameters: fstab= rd.fstab= Takes a boolean argument. Defaults to yes. If no, causes the generator to ignore any mounts or swaps configured in /etc/fstab. rd.fstab= is honored only by initial RAM disk (initrd) while fstab= is honored by both the main system and the initrd. root= Takes the root filesystem to mount in the initrd. root= is honored by the initrd. rootfstype= Takes the root filesystem type that will be passed to the mount command. rootfstype= is honored by the initrd. rootflags= Takes the root filesystem mount options to use. rootflags= is honored by the initrd. mount.usr= Takes the /usr filesystem to be mounted by the initrd. If mount.usrfstype= or mount.usrflags= is set, then mount.usr= will default to the value set in root=. Otherwise, this parameter defaults to the /usr entry found in /etc/fstab on the root filesystem. mount.usr= is honored by the initrd. mount.usrfstype= Takes the /usr filesystem type that will be passed to the mount command. If mount.usr= or mount.usrflags= is set, then mount.usrfstype= will default to the value set in rootfstype=. Otherwise, this value will be read from the /usr entry in /etc/fstab on the root filesystem. mount.usrfstype= is honored by the initrd. mount.usrflags= Takes the /usr filesystem mount options to use. If mount.usr= or mount.usrfstype= is set, then mount.usrflags= will default to the value set in rootflags=. Otherwise, this value will be read from the /usr entry in /etc/fstab on the root filesystem. mount.usrflags= is honored by the initrd. See Also systemd1, fstab5, systemd.mount5, systemd.swap5, systemd-cryptsetup-generator8 systemd-229/man/systemd-getty-generator.xml000066400000000000000000000073601265713322000211720ustar00rootroot00000000000000 systemd-getty-generator systemd Developer Lennart Poettering lennart@poettering.net systemd-getty-generator 8 systemd-getty-generator Generator for enabling getty instances on the console /usr/lib/systemd/system-generators/systemd-getty-generator Description systemd-getty-generator is a generator that automatically instantiates serial-getty@.service on the kernel console /dev/console if that is not directed to the virtual console subsystem. It will also instantiate serial-getty@.service instances for virtualizer consoles, if execution in a virtualized environment is detected. Finally, it will instantiate container-getty@.service instances for additional container pseudo TTYs as requested by the container manager (see Container Interface). This should ensure that the user is shown a login prompt at the right place, regardless of which environment the system is started in. For example, it is sufficient to redirect the kernel console with a kernel command line argument such as console= to get both kernel messages and a getty prompt on a serial TTY. See kernel-parameters.txt for more information on the console= kernel parameter. systemd-getty-generator implements systemd.generator7. Further information about configuration of gettys you may find in systemd for Administrators, Part XVI: Gettys on Serial Consoles (and Elsewhere). See Also systemd1, agetty8 systemd-229/man/systemd-gpt-auto-generator.xml000066400000000000000000000212011265713322000215640ustar00rootroot00000000000000 systemd-gpt-auto-generator systemd Developer Lennart Poettering lennart@poettering.net systemd-gpt-auto-generator 8 systemd-gpt-auto-generator Generator for automatically discovering and mounting root, /home and /srv partitions, as well as discovering and enabling swap partitions, based on GPT partition type GUIDs. /usr/lib/systemd/system-generators/systemd-gpt-auto-generator Description systemd-gpt-auto-generator is a unit generator that automatically discovers root, /home, /srv and swap partitions and creates mount and swap units for them, based on the partition type GUIDs of GUID partition tables (GPT). It implements the Discoverable Partitions Specification. Note that this generator has no effect on non-GPT systems, or where the directories under the mount points are already non-empty. Also, on systems where the units are explicitly configured (for example, listed in fstab5), the units this generator creates are overridden, but additional automatic dependencies might be created. This generator will only look for root partitions on the same physical disk the EFI System Partition (ESP) is located on. It will only look for the other partitions on the same physical disk the root file system is located on. These partitions will not be searched on systems where the root file system is distributed on multiple disks, for example via btrfs RAID. systemd-gpt-auto-generator is useful for centralizing file system configuration in the partition table and making manual configuration in /etc/fstab or suchlike unnecessary. This generator looks for the partitions based on their partition type GUID. The following partition type GUIDs are identified: Partition Type GUIDs Partition Type GUID Name Explanation 44479540-f297-41b2-9af7-d131d5f0458a Root Partition (x86) On 32-bit x86 systems, the first x86 root partition on the disk the EFI ESP is located on is mounted to the root directory /. 4f68bce3-e8cd-4db1-96e7-fbcaf984b709 Root Partition (x86-64) On 64-bit x86 systems, the first x86-64 root partition on the disk the EFI ESP is located on is mounted to the root directory /. 69dad710-2ce4-4e3c-b16c-21a1d49abed3 Root Partition (32-bit ARM) On 32-bit ARM systems, the first ARM root partition on the disk the EFI ESP is located on is mounted to the root directory /. b921b045-1df0-41c3-af44-4c6f280d3fae Root Partition (64-bit ARM) On 64-bit ARM systems, the first ARM root partition on the disk the EFI ESP is located on is mounted to the root directory /. 933ac7e1-2eb4-4f13-b844-0e14e2aef915 Home Partition The first home partition on the disk the root partition is located on is mounted to /home. 3b8f8425-20e0-4f3b-907f-1a25a76f98e8 Server Data Partition The first server data partition on the disk the root partition is located on is mounted to /srv. 0657fd6d-a4ab-43c4-84e5-0933c84b4f4f Swap All swap partitions located on the disk the root partition is located on are enabled.
The /home and /srv partitions may be encrypted in LUKS format. In this case, a device mapper device is set up under the names /dev/mapper/home and /dev/mapper/srv. Note that this might create conflicts if the same partition is listed in /etc/crypttab with a different device mapper device name. Mount and automount units for the EFI System Partition (ESP), mounting it to /boot, are generated on EFI systems where the boot loader communicates the used ESP to the operating system. Since this generator creates an automount unit, the mount will only be activated on-demand, when accessed. On systems where /boot is an explicitly configured mount (for example, listed in fstab5) or where the /boot mount point is non-empty, no mount units are generated. When using this generator in conjunction with btrfs file systems, make sure to set the correct default subvolumes on them, using btrfs subvolume set-default. systemd-gpt-auto-generator implements systemd.generator7.
See Also systemd1, systemd.mount5, systemd.swap5, systemd-fstab-generator8, systemd-cryptsetup@.service8, cryptsetup8, fstab5, btrfs8
systemd-229/man/systemd-halt.service.xml000066400000000000000000000112451265713322000204360ustar00rootroot00000000000000 systemd-halt.service systemd Developer Lennart Poettering lennart@poettering.net systemd-halt.service 8 systemd-halt.service systemd-poweroff.service systemd-reboot.service systemd-kexec.service systemd-shutdown System shutdown logic systemd-halt.service systemd-poweroff.service systemd-reboot.service systemd-kexec.service /usr/lib/systemd/systemd-shutdown Description systemd-halt.service is a system service that is pulled in by halt.target and is responsible for the actual system halt. Similarly, systemd-poweroff.service is pulled in by poweroff.target, systemd-reboot.service by reboot.target and systemd-kexec.service by kexec.target to execute the respective actions. When these services are run, they ensure that PID 1 is replaced by the /usr/lib/systemd/systemd-shutdown tool which is then responsible for the actual shutdown. Before shutting down, this binary will try to unmount all remaining file systems, disable all remaining swap devices, detach all remaining storage devices and kill all remaining processes. It is necessary to have this code in a separate binary because otherwise rebooting after an upgrade might be broken — the running PID 1 could still depend on libraries which are not available any more, thus keeping the file system busy, which then cannot be re-mounted read-only. Immediately before executing the actual system halt/poweroff/reboot/kexec systemd-shutdown will run all executables in /usr/lib/systemd/system-shutdown/ and pass one arguments to them: either halt, poweroff, reboot or kexec, depending on the chosen action. All executables in this directory are executed in parallel, and execution of the action is not continued before all executables finished. Note that systemd-halt.service (and the related units) should never be executed directly. Instead, trigger system shutdown with a command such as systemctl halt or suchlike. See Also systemd1, systemctl1, systemd.special7, reboot2, systemd-suspend.service8 systemd-229/man/systemd-hibernate-resume-generator.xml000066400000000000000000000063341265713322000232750ustar00rootroot00000000000000 systemd-hibernate-resume-generator systemd Developer Ivan Shapovalov intelfx100@gmail.com systemd-hibernate-resume-generator 8 systemd-hibernate-resume-generator Unit generator for resume= kernel parameter /usr/lib/systemd/system-generators/systemd-hibernate-resume-generator Description systemd-hibernate-resume-generator is a generator that instantiates systemd-hibernate-resume@.service8 unit according to the value of parameter specified on the kernel command line. Kernel Command Line systemd-hibernate-resume-generator understands the following kernel command line parameters: resume= Takes a path to the resume device. Both persistent block device paths like /dev/disk/by-foo/bar and fstab5-style specifiers like FOO=bar are supported. See Also systemd1, systemd-hibernate-resume@.service8, kernel-command-line7 systemd-229/man/systemd-hibernate-resume@.service.xml000066400000000000000000000056031265713322000230460ustar00rootroot00000000000000 systemd-hibernate-resume@.service systemd Developer Ivan Shapovalov intelfx100@gmail.com systemd-hibernate-resume@.service 8 systemd-hibernate-resume@.service systemd-hibernate-resume Resume from hibernation systemd-hibernate-resume@.service /usr/lib/systemd/systemd-hibernate-resume Description systemd-hibernate-resume@.service initiates the resume from hibernation. It is instantiated with the device to resume from as the template argument. systemd-hibernate-resume only supports the in-kernel hibernation implementation, known as swsusp. Internally, it works by writing the major:minor of specified device node to /sys/power/resume. Failing to initiate a resume is not an error condition. It may mean that there was no resume image (e. g. if the system has been simply powered off and not hibernated). In such case, the boot is ordinarily continued. See Also systemd1, systemd-hibernate-resume-generator8 systemd-229/man/systemd-hostnamed.service.xml000066400000000000000000000060311265713322000214650ustar00rootroot00000000000000 systemd-hostnamed.service systemd Developer Lennart Poettering lennart@poettering.net systemd-hostnamed.service 8 systemd-hostnamed.service systemd-hostnamed Host name bus mechanism systemd-hostnamed.service /usr/lib/systemd/systemd-hostnamed Description systemd-hostnamed is a system service that may be used as a mechanism to change the system's hostname. systemd-hostnamed is automatically activated on request and terminates itself when it is unused. The tool hostnamectl1 is a command line client to this service. See the developer documentation for information about the APIs systemd-hostnamed provides. See Also systemd1, hostname5, machine-info5, hostnamectl1, sethostname2 systemd-229/man/systemd-hwdb.xml000066400000000000000000000054551265713322000170010ustar00rootroot00000000000000 systemd-hwdb systemd Developer Kay Sievers kay@vrfy.org Developer Tom Gundersen teg@jklm.no systemd-hwdb 8 systemd-hwdbhardware database management tool systemd-hwdb options update systemd-hwdb options query modalias Description systemd-hwdb expects a command and command specific arguments. It manages the binary hardware database. Options Print help text. Generate in /usr/lib/udev instead of /etc/udev. Alternate root path in the filesystem. systemd-hwdb <arg choice="opt"><replaceable>options</replaceable></arg> update Update the binary database. systemd-hwdb <arg choice="opt"><replaceable>options</replaceable></arg> query <arg><replaceable>MODALIAS</replaceable></arg> Query database and print result. See Also hwdb7 systemd-229/man/systemd-inhibit.xml000066400000000000000000000141701265713322000174750ustar00rootroot00000000000000 systemd-inhibit systemd Developer Lennart Poettering lennart@poettering.net systemd-inhibit 1 systemd-inhibit Execute a program with an inhibition lock taken systemd-inhibit OPTIONS COMMAND ARGUMENTS systemd-inhibit OPTIONS --list Description systemd-inhibit may be used to execute a program with a shutdown, sleep or idle inhibitor lock taken. The lock will be acquired before the specified command line is executed and released afterwards. Inhibitor locks may be used to block or delay system sleep and shutdown requests from the user, as well as automatic idle handling of the OS. This is useful to avoid system suspends while an optical disc is being recorded, or similar operations that should not be interrupted. For more information see the Inhibitor Lock Developer Documentation. Options The following options are understood: Takes a colon-separated list of one or more operations to inhibit: shutdown, sleep, idle, handle-power-key, handle-suspend-key, handle-hibernate-key, handle-lid-switch, for inhibiting reboot/power-off/halt/kexec, suspending/hibernating, the automatic idle detection, or the low-level handling of the power/sleep key and the lid switch, respectively. If omitted, defaults to idle:sleep:shutdown. Takes a short, human-readable descriptive string for the program taking the lock. If not passed, defaults to the command line string. Takes a short, human-readable descriptive string for the reason for taking the lock. Defaults to "Unknown reason". Takes either block or delay and describes how the lock is applied. If block is used (the default), the lock prohibits any of the requested operations without time limit, and only privileged users may override it. If delay is used, the lock can only delay the requested operations for a limited time. If the time elapses, the lock is ignored and the operation executed. The time limit may be specified in logind.conf5. Note that delay is only available for sleep and shutdown. Lists all active inhibition locks instead of acquiring one. Exit status Returns the exit status of the executed program. Example # systemd-inhibit wodim foobar.iso This burns the ISO image foobar.iso on a CD using wodim1, and inhibits system sleeping, shutdown and idle while doing so. See Also systemd1, logind.conf5 systemd-229/man/systemd-initctl.service.xml000066400000000000000000000046011265713322000211520ustar00rootroot00000000000000 systemd-initctl.service systemd Developer Lennart Poettering lennart@poettering.net systemd-initctl.service 8 systemd-initctl.service systemd-initctl.socket systemd-initctl /dev/initctl compatibility systemd-initctl.service systemd-initctl.socket /usr/lib/systemd/systemd-initctl Description systemd-initctl is a system service that implements compatibility with the /dev/initctl FIFO file system object, as implemented by the SysV init system. systemd-initctl is automatically activated on request and terminates itself when it is unused. See Also systemd1 systemd-229/man/systemd-journal-gatewayd.service.xml000066400000000000000000000237401265713322000227660ustar00rootroot00000000000000 systemd-journal-gatewayd.service systemd Developer Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl systemd-journal-gatewayd.service 8 systemd-journal-gatewayd.service systemd-journal-gatewayd.socket systemd-journal-gatewayd HTTP server for journal events systemd-journal-gatewayd.service systemd-journal-gatewayd.socket /usr/lib/systemd/systemd-journal-gatewayd OPTIONS Description systemd-journal-gatewayd serves journal events over the network. Clients must connect using HTTP. The server listens on port 19531 by default. If is specified, the server expects HTTPS connections. The program is started by systemd1 and expects to receive a single socket. Use systemctl start systemd-journal-gatewayd.socket to start the service, and systemctl enable systemd-journal-gatewayd.socket to have it started on boot. Options The following options are understood: Specify the path to a file containing a server certificate in PEM format. This option switches systemd-journal-gatewayd into HTTPS mode and must be used together with . Specify the path to a file containing a server key in PEM format corresponding to the certificate specified with . Supported URLs The following URLs are recognized: /browse Interactive browsing. /entries[?option1&option2=value...] Retrieval of events in various formats. The part of the HTTP header determines the format. Supported values are described below. The part of the HTTP header determines the range of events returned. Supported values are described below. GET parameters can be used to modify what events are returned. Supported parameters are described below. /machine Return a JSON structure describing the machine. Example: { "machine_id" : "8cf7ed9d451ea194b77a9f118f3dc446", "boot_id" : "3d3c9efaf556496a9b04259ee35df7f7", "hostname" : "fedora", "os_pretty_name" : "Fedora 19 (Rawhide)", "virtualization" : "kvm", ...} /fields/FIELD_NAME Return a list of values of this field present in the logs. Accept header Recognized formats: text/plain The default. Plaintext syslog-like output, one line per journal entry (like journalctl --output short). application/json Entries are formatted as JSON data structures, one per line (like journalctl --output json). See Journal JSON Format for more information. text/event-stream Entries are formatted as JSON data structures, wrapped in a format suitable for Server-Sent Events (like journalctl --output json-sse). application/vnd.fdo.journal Entries are serialized into a binary (but mostly text-based) stream suitable for backups and network transfer (like journalctl --output export). See Journal Export Format for more information. Range header where is a cursor string, is an integer, is an unsigned integer. Range defaults to all available events. URL GET parameters Following parameters can be used as part of the URL: follow wait for new events (like journalctl --follow, except that the number of events returned is not limited). discrete Test that the specified cursor refers to an entry in the journal. Returns just this entry. boot Limit events to the current boot of the system (like journalctl --this--boot). KEY=match Match journal fields. See systemd.journal-fields7. Examples Retrieve events from this boot from local journal in Journal Export Format: curl --silent -H'Accept: application/vnd.fdo.journal' \ 'http://localhost:19531/entries?boot' Listen for core dumps: curl 'http://localhost:19531/entries?follow&MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1' See Also systemd1, journalctl1, systemd-journald.service8, systemd.journal-fields7, systemd-229/man/systemd-journal-remote.xml000066400000000000000000000312151265713322000210110ustar00rootroot00000000000000 systemd-journal-remote systemd Developer Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl systemd-journal-remote 8 systemd-journal-remote Receive journal messages over the network systemd-journal-remote OPTIONS -o/--output=DIR|FILE SOURCES Description systemd-journal-remote is a command to receive serialized journal events and store them to the journal. Input streams are in the Journal Export Format , i.e. like the output from journalctl --output=export. For transport over the network, this serialized stream is usually carried over an HTTPS connection. Sources Sources can be either "active" (systemd-journal-remote requests and pulls the data), or "passive" (systemd-journal-remote waits for a connection and then receives events pushed by the other side). systemd-journal-remote can read more than one event stream at a time. They will be interleaved in the output file. In case of "active" connections, each "source" is one stream, and in case of "passive" connections, each connection can result in a separate stream. Sockets can be configured in "accept" mode (i.e. only one connection), or "listen" mode (i.e. multiple connections, each resulting in a stream). When there are no more connections, and no more can be created (there are no listening sockets), then systemd-journal-remote will exit. Active sources can be specified in the following ways: When is given as a positional argument, events will be read from standard input. Other positional arguments will be treated as filenames to open and read from. With the option, events will be retrieved using HTTP from ADDRESS. This URL should refer to the root of a remote systemd-journal-gatewayd8 instance (e.g. http://some.host:19531/ or https://some.host:19531/). Passive sources can be specified in the following ways: ADDRESS must be an address suitable for (cf. systemd.socket5). systemd-journal-remote will listen on this socket for connections. Each connection is expected to be a stream of journal events. ADDRESS must be either a negative integer, in which case it will be interpreted as the (negated) file descriptor number, or an address suitable for (c.f. systemd.socket5). In the first case, matching file descriptor must be inherited through $LISTEN_FDS/$LISTEN_PID. In the second case, an HTTP or HTTPS server will be spawned on this port, respectively for and . Currently, only POST requests to /upload with Content-Type: application/vnd.fdo.journal are supported. $LISTEN_FDS systemd-journal-remote supports the $LISTEN_FDS/$LISTEN_PID protocol. Open sockets inherited through socket activation behave like those opened with described above, unless they are specified as an argument in or above. In the latter case, an HTTP or HTTPS server will be spawned using this descriptor and connections must be made over the HTTP protocol. Sinks The location of the output journal can be specified with or . For "active" sources, this option is required. Will write to this journal file. The filename must end with .journal. The file will be created if it does not exist. If necessary (journal file full, or corrupted), the file will be renamed following normal journald rules and a new journal file will be created in its stead. Will create journal files underneath directory DIR. The directory must exist. If necessary (journal files over size, or corrupted), journal files will be rotated following normal journald rules. Names of files underneath DIR will be generated using the rules described below. If is not used, the output directory /var/log/journal/remote/ will be used. In case the output file is not specified, journal files will be created underneath the selected directory. Files will be called remote-hostname.journal, where the hostname part is the escaped hostname of the source endpoint of the connection, or the numerical address if the hostname cannot be determined. In case of "active" sources, the output file name must always be given explicitly. Options The following options are understood: One of none or host. For the first, only one output journal file is used. For the latter, a separate output file is used, based on the hostname of the other endpoint of a connection. In case of "active" sources, the output file name must always be given explicitly and only none is allowed. Compress or not, respectively, the data in the journal using XZ. Periodically sign or not, respectively, the data in the journal using Forward Secure Sealing. Program to invoke to retrieve data. The journal event stream must be generated on standard output. Examples: --getter='curl "-HAccept: application/vnd.fdo.journal" https://some.host:19531/' --getter='wget --header="Accept: application/vnd.fdo.journal" -O- https://some.host:19531/' Examples Copy local journal events to a different journal directory: journalctl -o export | systemd-journal-remote -o /tmp/dir - Retrieve all available events from a remote systemd-journal-gatewayd8 instance and store them in /var/log/journal/remote/remote-some.host.journal: systemd-journal-remote --url http://some.host:19531/ Retrieve current boot events and wait for new events from a remote systemd-journal-gatewayd8 instance, and store them in /var/log/journal/remote/remote-some.host.journal: systemd-journal-remote --url http://some.host:19531/entries?boot&follow See Also systemd-journal-upload8, journalctl1, systemd-journald.service8, systemd-journal-gatewayd.service8 journal-remote.conf5 systemd-229/man/systemd-journal-upload.xml000066400000000000000000000233751265713322000210120ustar00rootroot00000000000000 systemd-journal-upload systemd Developer Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl systemd-journal-upload 8 systemd-journal-upload Send journal messages over the network systemd-journal-upload OPTIONS -u/--url=URL SOURCES Description systemd-journal-upload will upload journal entries to the URL specified with . Unless limited by one of the options specified below, all journal entries accessible to the user the program is running as will be uploaded, and then the program will wait and send new entries as they become available. Options Upload to the specified address. URL may specify either just the hostname or both the protocol and hostname. https is the default. Limit uploaded entries to entries from system services and the kernel, or to entries from services of current user. This has the same meaning as and options for journalctl1. If neither is specified, all accessible entries are uploaded. Upload entries interleaved from all available journals, including other machines. This has the same meaning as option for journalctl1. Takes a directory path as argument. Upload entries from the specified journal directory DIR instead of the default runtime and system journal paths. This has the same meaning as option for journalctl1. Takes a file glob as an argument. Upload entries from the specified journal files matching GLOB instead of the default runtime and system journal paths. May be specified multiple times, in which case files will be suitably interleaved. This has the same meaning as option for journalctl1. Upload entries from the location in the journal specified by the passed cursor. This has the same meaning as option for journalctl1. Upload entries from the location in the journal after the location specified by the this cursor. This has the same meaning as option for journalctl1. =PATH Upload entries from the location in the journal after the location specified by the cursor saved in file at PATH (/var/lib/systemd/journal-upload/state by default). After an entry is successfully uploaded, update this file with the cursor of that entry. Exit status On success, 0 is returned; otherwise, a non-zero failure code is returned. Examples Setting up certificates for authentication Certificates signed by a trusted authority are used to verify that the server to which messages are uploaded is legitimate, and vice versa, that the client is trusted. A suitable set of certificates can be generated with openssl: openssl req -newkey rsa:2048 -days 3650 -x509 -nodes \ -out ca.pem -keyout ca.key -subj '/CN=Certificate authority/' cat >ca.conf <<EOF [ ca ] default_ca = this [ this ] new_certs_dir = . certificate = ca.pem database = ./index private_key = ca.key serial = ./serial default_days = 3650 default_md = default policy = policy_anything [ policy_anything ] countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional EOF touch index echo 0001 >serial SERVER=server CLIENT=client openssl req -newkey rsa:1024 -nodes -out $SERVER.csr -keyout $SERVER.key -subj "/CN=$SERVER/" openssl ca -batch -config ca.conf -notext -in $SERVER.csr -out $SERVER.pem openssl req -newkey rsa:1024 -nodes -out $CLIENT.csr -keyout $CLIENT.key -subj "/CN=$CLIENT/" openssl ca -batch -config ca.conf -notext -in $CLIENT.csr -out $CLIENT.pem Generated files ca.pem, server.pem, and server.key should be installed on server, and ca.pem, client.pem, and client.key on the client. The location of those files can be specified using TrustedCertificateFile=, ServerCertificateFile=, ServerKeyFile=, in /etc/systemd/journal-remote.conf and /etc/systemd/journal-upload.conf, respectively. The default locations can be queried by using systemd-journal-remote --help and systemd-journal-upload --help. See Also systemd-journal-remote8, journalctl1, systemd-journald.service8, systemd-journal-gatewayd.service8 systemd-229/man/systemd-journald.service.xml000066400000000000000000000264321265713322000213300ustar00rootroot00000000000000 systemd-journald.service systemd Developer Lennart Poettering lennart@poettering.net systemd-journald.service 8 systemd-journald.service systemd-journald.socket systemd-journald-dev-log.socket systemd-journald-audit.socket systemd-journald Journal service systemd-journald.service systemd-journald.socket systemd-journald-dev-log.socket systemd-journald-audit.socket /usr/lib/systemd/systemd-journald Description systemd-journald is a system service that collects and stores logging data. It creates and maintains structured, indexed journals based on logging information that is received from a variety of sources: Kernel log messages, via kmsg Simple system log messages, via the libc syslog3 call Structured system log messages via the native Journal API, see sd_journal_print4 Standard output and standard error of system services Audit records, via the audit subsystem The daemon will implicitly collect numerous metadata fields for each log messages in a secure and unfakeable way. See systemd.journal-fields7 for more information about the collected metadata. Log data collected by the journal is primarily text-based but can also include binary data where necessary. All objects stored in the journal can be up to 2^64-1 bytes in size. By default, the journal stores log data in /run/log/journal/. Since /run/ is volatile, log data is lost at reboot. To make the data persistent, it is sufficient to create /var/log/journal/ where systemd-journald will then store the data: mkdir -p /var/log/journal systemd-tmpfiles --create --prefix /var/log/journal See journald.conf5 for information about the configuration of this service. Signals SIGUSR1 Request that journal data from /run/ is flushed to /var/ in order to make it persistent (if this is enabled). This must be used after /var/ is mounted, as otherwise log data from /run is never flushed to /var regardless of the configuration. The journalctl --flush command uses this signal to request flushing of the journal files, and then waits for the operation to complete. See journalctl1 for details. SIGUSR2 Request immediate rotation of the journal files. The journalctl --rotate command uses this signal to request journal file rotation. SIGRTMIN+1 Request that all unwritten log data is written to disk. The journalctl --sync command uses this signal to trigger journal synchronization, and then waits for the operation to complete. Kernel Command Line A few configuration parameters from journald.conf may be overridden on the kernel command line: systemd.journald.forward_to_syslog= systemd.journald.forward_to_kmsg= systemd.journald.forward_to_console= systemd.journald.forward_to_wall= Enables/disables forwarding of collected log messages to syslog, the kernel log buffer, the system console or wall. See journald.conf5 for information about these settings. Access Control Journal files are, by default, owned and readable by the systemd-journal system group but are not writable. Adding a user to this group thus enables her/him to read the journal files. By default, each logged in user will get her/his own set of journal files in /var/log/journal/. These files will not be owned by the user, however, in order to avoid that the user can write to them directly. Instead, file system ACLs are used to ensure the user gets read access only. Additional users and groups may be granted access to journal files via file system access control lists (ACL). Distributions and administrators may choose to grant read access to all members of the wheel and adm system groups with a command such as the following: # setfacl -Rnm g:wheel:rx,d:g:wheel:rx,g:adm:rx,d:g:adm:rx /var/log/journal/ Note that this command will update the ACLs both for existing journal files and for future journal files created in the /var/log/journal/ directory. Files /etc/systemd/journald.conf Configure systemd-journald behavior. See journald.conf5. /run/log/journal/machine-id/*.journal /run/log/journal/machine-id/*.journal~ /var/log/journal/machine-id/*.journal /var/log/journal/machine-id/*.journal~ systemd-journald writes entries to files in /run/log/journal/machine-id/ or /var/log/journal/machine-id/ with the .journal suffix. If the daemon is stopped uncleanly, or if the files are found to be corrupted, they are renamed using the .journal~ suffix, and systemd-journald starts writing to a new file. /run is used when /var/log/journal is not available, or when is set in the journald.conf5 configuration file. /dev/kmsg /dev/log /run/systemd/journal/dev-log /run/systemd/journal/socket /run/systemd/journal/stdout Sockets and other paths that systemd-journald will listen on that are visible in the file system. In addition to these, journald can listen for audit events using netlink. See Also systemd1, journalctl1, journald.conf5, systemd.journal-fields7, sd-journal3, systemd-coredump8, setfacl1, sd_journal_print4, pydoc systemd.journal systemd-229/man/systemd-localed.service.xml000066400000000000000000000062241265713322000211120ustar00rootroot00000000000000 systemd-localed.service systemd Developer Lennart Poettering lennart@poettering.net systemd-localed.service 8 systemd-localed.service systemd-localed Locale bus mechanism systemd-localed.service /usr/lib/systemd/systemd-localed Description systemd-localed is a system service that may be used as mechanism to change the system locale settings, as well as the console key mapping and default X11 key mapping. systemd-localed is automatically activated on request and terminates itself when it is unused. The tool localectl1 is a command line client to this service. See the developer documentation for information about the APIs systemd-localed provides. See Also systemd1, locale.conf5, vconsole.conf5, localectl1, loadkeys1 systemd-229/man/systemd-logind.service.xml000066400000000000000000000104721265713322000207630ustar00rootroot00000000000000 systemd-logind.service systemd Developer Lennart Poettering lennart@poettering.net systemd-logind.service 8 systemd-logind.service systemd-logind Login manager systemd-logind.service /usr/lib/systemd/systemd-logind Description systemd-logind is a system service that manages user logins. It is responsible for: Keeping track of users and sessions, their processes and their idle state Providing PolicyKit-based access for users to operations such as system shutdown or sleep Implementing a shutdown/sleep inhibition logic for applications Handling of power/sleep hardware keys Multi-seat management Session switch management Device access management for users Automatic spawning of text logins (gettys) on virtual console activation and user runtime directory management User sessions are registered in logind via the pam_systemd8 PAM module. See logind.conf5 for information about the configuration of this service. See Multi-Seat on Linux for an introduction into basic concepts of logind such as users, sessions and seats. See the logind D-Bus API Documentation for information about the APIs systemd-logind provides. For more information on the inhibition logic see the Inhibitor Lock Developer Documentation. See Also systemd1, systemd-user-sessions.service8, loginctl1, logind.conf5, pam_systemd8 systemd-229/man/systemd-machine-id-commit.service.xml000066400000000000000000000074141265713322000227750ustar00rootroot00000000000000 systemd-machine-id-commit.service systemd Developer Didier Roche didrocks@ubuntu.com systemd-machine-id-commit.service 8 systemd-machine-id-commit.service Commit a transient machine ID to disk systemd-machine-id-commit.service Description systemd-machine-id-commit.service is an early boot service responsible for committing transient /etc/machine-id files to a writable disk file system. See machine-id5 for more information about machine IDs. This service is started after local-fs.target in case /etc/machine-id is a mount point of its own (usually from a memory file system such as tmpfs) and /etc is writable. The service will invoke systemd-machine-id-setup --commit, which writes the current transient machine ID to disk and unmount the /etc/machine-id file in a race-free manner to ensure that file is always valid and accessible for other processes. See systemd-machine-id-setup1 for details. The main use case of this service are systems where /etc/machine-id is read-only and initially not initialized. In this case, the system manager will generate a transient machine ID file on a memory file system, and mount it over /etc/machine-id, during the early boot phase. This service is then invoked in a later boot phase, as soon as /etc has been remounted writable and the ID may thus be committed to disk to make it permanent. See Also systemd1, systemd-machine-id-setup1, machine-id5, systemd-firstboot1 systemd-229/man/systemd-machine-id-setup.xml000066400000000000000000000154041265713322000212040ustar00rootroot00000000000000 systemd-machine-id-setup systemd Developer Lennart Poettering lennart@poettering.net Developer Didier Roche didrocks@ubuntu.com systemd-machine-id-setup 1 systemd-machine-id-setup Initialize the machine ID in /etc/machine-id systemd-machine-id-setup Description systemd-machine-id-setup may be used by system installer tools to initialize the machine ID stored in /etc/machine-id at install time, with a provisioned or randomly generated ID. See machine-id5 for more information about this file. If the tool is invoked without the switch, /etc/machine-id is initialized with a valid, new machined ID if it is missing or empty. The new machine ID will be acquired in the following fashion: If a valid D-Bus machine ID is already configured for the system, the D-Bus machine ID is copied and used to initialize the machine ID in /etc/machine-id. If run inside a KVM virtual machine and a UUID is was configured (via the option), this UUID is used to initialize the machine ID. The caller must ensure that the UUID passed is sufficiently unique and is different for every booted instance of the VM. Similarly, if run inside a Linux container environment and a UUID is configured for the container, this is used to initialize the machine ID. For details, see the documentation of the Container Interface. Otherwise, a new ID is randomly generated. The switch may be used to commit a transient machined ID to disk, making it persistent. For details, see below. Use systemd-firstboot1 to initialize the machine ID on mounted (but not booted) system images. Options The following options are understood: Takes a directory path as argument. All paths operated will be prefixed with the given alternate root path, including the path for /etc/machine-id itself. Commit a transient machine ID to disk. This command may be used to convert a transient machine ID into a persistent one. A transient machine ID file is one that was bind mounted from a memory file system (usually tmpfs) to /etc/machine-id during the early phase of the boot process. This may happen because /etc is initially read-only and was missing a valid machine ID file at that point. This command will execute no operation if /etc/machine-id is not mounted from a memory file system, or if /etc is read-only. The command will write the current transient machine ID to disk and unmount the /etc/machine-id mount point in a race-free manner to ensure that this file is always valid and accessible for other processes. This command is primarily used by the systemd-machine-id-commit.service8 early boot service. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, machine-id5, systemd-machine-id-commit.service8, dbus-uuidgen1, systemd-firstboot1 systemd-229/man/systemd-machined.service.xml000066400000000000000000000063541265713322000212630ustar00rootroot00000000000000 systemd-machined.service systemd Developer Lennart Poettering lennart@poettering.net systemd-machined.service 8 systemd-machined.service systemd-machined Virtual machine and container registration manager systemd-machined.service /usr/lib/systemd/systemd-machined Description systemd-machined is a system service that keeps track of virtual machines and containers, and processes belonging to them. See systemd-nspawn1 for some examples on how to run containers with OS tools. Use nss-mymachines8 to make the names of local containers known to systemd-machined locally resolvable as host names. See the machined D-Bus API Documentation for information about the APIs systemd-machined provides. See Also systemd1, machinectl1, systemd-nspawn1, nss-mymachines8, systemd.special7 systemd-229/man/systemd-modules-load.service.xml000066400000000000000000000061171265713322000220750ustar00rootroot00000000000000 systemd-modules-load.service systemd Developer Lennart Poettering lennart@poettering.net systemd-modules-load.service 8 systemd-modules-load.service systemd-modules-load Load kernel modules at boot systemd-modules-load.service /usr/lib/systemd/systemd-modules-load Description systemd-modules-load.service is an early boot service that loads kernel modules based on static configuration. See modules-load.d5 for information about the configuration of this service. Kernel Command Line systemd-modules-load.service understands the following kernel command line parameters: modules-load= rd.modules-load= Takes a comma-separated list of kernel modules to statically load during early boot. The option prefixed with rd. is read by the initial RAM disk only. See Also systemd1, modules-load.d5, systemd-229/man/systemd-networkd-wait-online.service.xml000066400000000000000000000076251265713322000235760ustar00rootroot00000000000000 systemd-networkd.service systemd Developer Tom Gundersen teg@jklm.no systemd-networkd-wait-online.service 8 systemd-networkd-wait-online.service systemd-networkd-wait-online Wait for network to come online systemd-networkd-wait-online.service /usr/lib/systemd/systemd-networkd-wait-online Description systemd-networkd-wait-online is a one-shot system service that waits for the network to be configured. By default, it will wait for all links it is aware of and which are managed by systemd-networkd.service8 to be fully configured or failed, and for at least one link to gain a carrier. Options The following options are understood: Network interface to wait for before deciding if the system is online. This is useful when a system has several interfaces which will be configured, but a particular one is necessary to access some network resources. This option may be used more than once to wait for multiple network interfaces. When used, all other interfaces are ignored. Network interfaces to be ignored when deciding if the system is online. By default, only the loopback interface is ignored. This option may be used more than once to ignore multiple network interfaces. Fail the service if the network is not online by the time the timeout elapses. A timeout of 0 disables the timeout. Defaults to 120 seconds. See Also systemd1, systemd-networkd.service8 systemd-229/man/systemd-networkd.service.xml000066400000000000000000000077641265713322000213560ustar00rootroot00000000000000 systemd-networkd.service systemd Developer Tom Gundersen teg@jklm.no systemd-networkd.service 8 systemd-networkd.service systemd-networkd Network manager systemd-networkd.service /usr/lib/systemd/systemd-networkd Description systemd-networkd is a system service that manages networks. It detects and configures network devices as they appear, as well as creating virtual network devices. To configure low-level link settings independently of networks, see systemd.link5. Network configurations applied before networkd is started are not removed, and static configuration applied by networkd is not removed when networkd exits. Dynamic configuration applied by networkd may also optionally be left in place on shutdown. This ensures restarting networkd does not cut the network connection, and, in particular, that it is safe to transition between the initrd and the real root, and back. Configuration Files The configuration files are read from the files located in the system network directory /usr/lib/systemd/network, the volatile runtime network directory /run/systemd/network and the local administration network directory /etc/systemd/network. Networks are configured in .network files, see systemd.network5, and virtual network devices are configured in .netdev files, see systemd.netdev5. See Also systemd1, systemd.link5, systemd.network5, systemd.netdev5, systemd-networkd-wait-online.service8 systemd-229/man/systemd-notify.xml000066400000000000000000000152101265713322000173530ustar00rootroot00000000000000 systemd-notify systemd Developer Lennart Poettering lennart@poettering.net systemd-notify 1 systemd-notify Notify service manager about start-up completion and other daemon status changes systemd-notify OPTIONS VARIABLE=VALUE Description systemd-notify may be called by daemon scripts to notify the init system about status changes. It can be used to send arbitrary information, encoded in an environment-block-like list of strings. Most importantly, it can be used for start-up completion notification. This is mostly just a wrapper around sd_notify() and makes this functionality available to shell scripts. For details see sd_notify3. The command line may carry a list of environment variables to send as part of the status update. Note that systemd will refuse reception of status updates from this command unless NotifyAccess=all is set for the service unit this command is called from. Options The following options are understood: Inform the init system about service start-up completion. This is equivalent to systemd-notify READY=1. For details about the semantics of this option see sd_notify3. Inform the init system about the main PID of the daemon. Takes a PID as argument. If the argument is omitted, the PID of the process that invoked systemd-notify is used. This is equivalent to systemd-notify MAINPID=$PID. For details about the semantics of this option see sd_notify3. Send a free-form status string for the daemon to the init systemd. This option takes the status string as argument. This is equivalent to systemd-notify STATUS=.... For details about the semantics of this option see sd_notify3. Returns 0 if the system was booted up with systemd, non-zero otherwise. If this option is passed, no message is sent. This option is hence unrelated to the other options. For details about the semantics of this option, see sd_booted3. An alternate way to check for this state is to call systemctl1 with the is-system-running command. It will return offline if the system was not booted with systemd. Exit status On success, 0 is returned, a non-zero failure code otherwise. Example Start-up Notification and Status Updates A simple shell daemon that sends start-up notifications after having set up its communication channel. During runtime it sends further status updates to the init system: #!/bin/bash mkfifo /tmp/waldo systemd-notify --ready --status="Waiting for data..." while : ; do read a < /tmp/waldo systemd-notify --status="Processing $a" # Do something with $a ... systemd-notify --status="Waiting for data..." done See Also systemd1, systemctl1, systemd.unit5, sd_notify3, sd_booted3 systemd-229/man/systemd-nspawn.xml000066400000000000000000001350521265713322000173600ustar00rootroot00000000000000 systemd-nspawn systemd Developer Lennart Poettering lennart@poettering.net systemd-nspawn 1 systemd-nspawn Spawn a namespace container for debugging, testing and building systemd-nspawn OPTIONS COMMAND ARGS systemd-nspawn -b OPTIONS ARGS Description systemd-nspawn may be used to run a command or OS in a light-weight namespace container. In many ways it is similar to chroot1, but more powerful since it fully virtualizes the file system hierarchy, as well as the process tree, the various IPC subsystems and the host and domain name. systemd-nspawn limits access to various kernel interfaces in the container to read-only, such as /sys, /proc/sys or /sys/fs/selinux. Network interfaces and the system clock may not be changed from within the container. Device nodes may not be created. The host system cannot be rebooted and kernel modules may not be loaded from within the container. Note that even though these security precautions are taken systemd-nspawn is not suitable for fully secure container setups. Many of the security features may be circumvented and are hence primarily useful to avoid accidental changes to the host system from the container. In contrast to chroot1 systemd-nspawn may be used to boot full Linux-based operating systems in a container. Use a tool like dnf8, debootstrap8, or pacman8 to set up an OS directory tree suitable as file system hierarchy for systemd-nspawn containers. Note that systemd-nspawn will mount file systems private to the container to /dev, /run and similar. These will not be visible outside of the container, and their contents will be lost when the container exits. Note that running two systemd-nspawn containers from the same directory tree will not make processes in them see each other. The PID namespace separation of the two containers is complete and the containers will share very few runtime objects except for the underlying file system. Use machinectl1's login command to request an additional login prompt in a running container. systemd-nspawn implements the Container Interface specification. As a safety check systemd-nspawn will verify the existence of /usr/lib/os-release or /etc/os-release in the container tree before starting the container (see os-release5). It might be necessary to add this file to the container tree manually if the OS of the container is too old to contain this file out-of-the-box. Options If option is specified, the arguments are used as arguments for the init binary. Otherwise, COMMAND specifies the program to launch in the container, and the remaining arguments are used as arguments for this program. If is not used and no arguments are specified, a shell is launched in the container. The following options are understood: Directory to use as file system root for the container. If neither , nor is specified the directory is determined by searching for a directory named the same as the machine name specified with . See machinectl1 section "Files and Directories" for the precise search path. If neither , , nor are specified, the current directory will be used. May not be specified together with . Directory or btrfs subvolume to use as template for the container's root directory. If this is specified and the container's root directory (as configured by ) does not yet exist it is created as btrfs subvolume and populated from this template tree. Ideally, the specified template path refers to the root of a btrfs subvolume, in which case a simple copy-on-write snapshot is taken, and populating the root directory is instant. If the specified template path does not refer to the root of a btrfs subvolume (or not even to a btrfs file system at all), the tree is copied, which can be substantially more time-consuming. Note that if this option is used the container's root directory (in contrast to the template directory!) must be located on a btrfs file system, so that the btrfs subvolume may be created. May not be specified together with or . Note that this switch leaves host name, machine ID and all other settings that could identify the instance unmodified. If specified, the container is run with a temporary btrfs snapshot of its root directory (as configured with ), that is removed immediately when the container terminates. This option is only supported if the root file system is btrfs. May not be specified together with or . Note that this switch leaves host name, machine ID and all other settings that could identify the instance unmodified. Disk image to mount the root directory for the container from. Takes a path to a regular file or to a block device node. The file or block device must contain either: An MBR partition table with a single partition of type 0x83 that is marked bootable. A GUID partition table (GPT) with a single partition of type 0fc63daf-8483-4772-8e79-3d69d8477de4. A GUID partition table (GPT) with a marked root partition which is mounted as the root directory of the container. Optionally, GPT images may contain a home and/or a server data partition which are mounted to the appropriate places in the container. All these partitions must be identified by the partition types defined by the Discoverable Partitions Specification. Any other partitions, such as foreign partitions, swap partitions or EFI system partitions are not mounted. May not be specified together with , or . Invoke the shell or specified program as process ID (PID) 2 instead of PID 1 (init). By default, if neither this option nor is used, the selected binary is run as process with PID 1, a mode only suitable for programs that are aware of the special semantics that the process with PID 1 has on UNIX. For example, it needs to reap all processes reparented to it, and should implement sysvinit compatible signal handling (specifically: it needs to reboot on SIGINT, reexecute on SIGTERM, reload configuration on SIGHUP, and so on). With a minimal stub init process is run as PID 1 and the selected binary is executed as PID 2 (and hence does not need to implement any special semantics). The stub init process will reap processes as necessary and react appropriately to signals. It is recommended to use this mode to invoke arbitrary commands in containers, unless they have been modified to run correctly as PID 1. Or in other words: this switch should be used for pretty much all commands, except when the command refers to an init or shell implementation, as these are generally capable of running correctly as PID 1). This option may not be combined with or . Automatically search for an init binary and invoke it as PID 1, instead of a shell or a user supplied program. If this option is used, arguments specified on the command line are used as arguments for the init binary. This option may not be combined with or . The following table explains the different modes of invocation and relationship to (see above): Invocation Mode Switch Explanation Neither nor specified The passed parameters are interpreted as command line, which is executed as PID 1 in the container. specified The passed parameters are interpreted as command line, which are executed as PID 2 in the container. A stub init process is run as PID 1. specified An init binary as automatically searched and run as PID 1 in the container. The passed parameters are used as invocation parameters for this process.
Change to the specified working directory before invoking the process in the container. Expects an absolute path in the container's file system namespace. After transitioning into the container, change to the specified user-defined in the container's user database. Like all other systemd-nspawn features, this is not a security feature and provides protection against accidental destructive operations only. Sets the machine name for this container. This name may be used to identify this container during its runtime (for example in tools like machinectl1 and similar), and is used to initialize the container's hostname (which the container can choose to override, however). If not specified, the last component of the root directory path of the container is used, possibly suffixed with a random identifier in case mode is selected. If the root directory selected is the host's root directory the host's hostname is used as default instead. Set the specified UUID for the container. The init system will initialize /etc/machine-id from this if this file is not set yet. Make the container part of the specified slice, instead of the default machine.slice. This is only applies if the machine is run in its own scope unit, i.e. if is not used. Set a unit property on the scope unit to register for the machine. This only applies if the machine is run in its own scope unit, i.e. if is not used. Takes unit property assignments in the same format as systemctl set-property. This is useful to set memory limits and similar for machines. Enables user namespacing. If enabled, the container will run with its own private set of Unix user and group ids (UIDs and GIDs). Takes none, one or two colon-separated parameters: the first parameter specifies the first host UID to assign to the container, the second parameter specifies the number of host UIDs to assign to the container. If the second parameter is omitted, 65536 UIDs are assigned. If the first parameter is also omitted (and hence no parameter passed at all), the first UID assigned to the container is read from the owner of the root directory of the container's directory tree. By default, no user namespacing is applied. Note that user namespacing currently requires OS trees that are prepared for the UID shift that is being applied: UIDs and GIDs used for file ownership or in file ACL entries must be shifted to the container UID base that is used during container runtime. It is recommended to assign at least 65536 UIDs to each container, so that the usable UID range in the container covers 16 bit. For best security, do not assign overlapping UID ranges to multiple containers. It is hence a good idea to use the upper 16 bit of the host 32-bit UIDs as container identifier, while the lower 16 bit encode the container UID used. When user namespaces are used, the GID range assigned to each container is always chosen identical to the UID range. Disconnect networking of the container from the host. This makes all network interfaces unavailable in the container, with the exception of the loopback device and those specified with and configured with . If this option is specified, the CAP_NET_ADMIN capability will be added to the set of capabilities the container retains. The latter may be disabled by using . Assign the specified network interface to the container. This will remove the specified interface from the calling namespace and place it in the container. When the container terminates, it is moved back to the host namespace. Note that implies . This option may be used more than once to add multiple network interfaces to the container. Create a macvlan interface of the specified Ethernet network interface and add it to the container. A macvlan interface is a virtual interface that adds a second MAC address to an existing physical Ethernet link. The interface in the container will be named after the interface on the host, prefixed with mv-. Note that implies . This option may be used more than once to add multiple network interfaces to the container. Create an ipvlan interface of the specified Ethernet network interface and add it to the container. An ipvlan interface is a virtual interface, similar to a macvlan interface, which uses the same MAC address as the underlying interface. The interface in the container will be named after the interface on the host, prefixed with iv-. Note that implies . This option may be used more than once to add multiple network interfaces to the container. Create a virtual Ethernet link (veth) between host and container. The host side of the Ethernet link will be available as a network interface named after the container's name (as specified with ), prefixed with ve-. The container side of the Ethernet link will be named host0. Note that implies . Adds an additional virtual Ethernet link between host and container. Takes a colon-separated pair of host interface name and container interface name. The latter may be omitted in which case the container and host sides will be assigned the same name. This switch is independent of , and -- in contrast -- may be used multiple times, and allows configuration of the network interface names. Note that has no effect on interfaces created with . Adds the host side of the Ethernet link created with to the specified bridge. Note that implies . If this option is used, the host side of the Ethernet link will use the vb- prefix instead of ve-. If private networking is enabled, maps an IP port on the host onto an IP port on the container. Takes a protocol specifier (either tcp or udp), separated by a colon from a host port number in the range 1 to 65535, separated by a colon from a container port number in the range from 1 to 65535. The protocol specifier and its separating colon may be omitted, in which case tcp is assumed. The container port number and its colon may be omitted, in which case the same port as the host port is implied. This option is only supported if private networking is used, such as with or . Sets the SELinux security context to be used to label processes in the container. Sets the SELinux security context to be used to label files in the virtual API file systems in the container. List one or more additional capabilities to grant the container. Takes a comma-separated list of capability names, see capabilities7 for more information. Note that the following capabilities will be granted in any way: CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER, CAP_FSETID, CAP_IPC_OWNER, CAP_KILL, CAP_LEASE, CAP_LINUX_IMMUTABLE, CAP_NET_BIND_SERVICE, CAP_NET_BROADCAST, CAP_NET_RAW, CAP_SETGID, CAP_SETFCAP, CAP_SETPCAP, CAP_SETUID, CAP_SYS_ADMIN, CAP_SYS_CHROOT, CAP_SYS_NICE, CAP_SYS_PTRACE, CAP_SYS_TTY_CONFIG, CAP_SYS_RESOURCE, CAP_SYS_BOOT, CAP_AUDIT_WRITE, CAP_AUDIT_CONTROL. Also CAP_NET_ADMIN is retained if is specified. If the special value all is passed, all capabilities are retained. Specify one or more additional capabilities to drop for the container. This allows running the container with fewer capabilities than the default (see above). Specify the process signal to send to the container's PID 1 when nspawn itself receives SIGTERM, in order to trigger an orderly shutdown of the container. Defaults to SIGRTMIN+3 if is used (on systemd-compatible init systems SIGRTMIN+3 triggers an orderly shutdown). Takes a signal name like SIGHUP, SIGTERM or similar as argument. Control whether the container's journal shall be made visible to the host system. If enabled, allows viewing the container's journal files from the host (but not vice versa). Takes one of no, host, try-host, guest, try-guest, auto. If no, the journal is not linked. If host, the journal files are stored on the host file system (beneath /var/log/journal/machine-id) and the subdirectory is bind-mounted into the container at the same location. If guest, the journal files are stored on the guest file system (beneath /var/log/journal/machine-id) and the subdirectory is symlinked into the host at the same location. try-host and try-guest do the same but do not fail if the host does not have persistent journalling enabled. If auto (the default), and the right subdirectory of /var/log/journal exists, it will be bind mounted into the container. If the subdirectory does not exist, no linking is performed. Effectively, booting a container once with guest or host will link the journal persistently if further on the default of auto is used. Equivalent to . Mount the root file system read-only for the container. Bind mount a file or directory from the host into the container. Takes one of: a path argument — in which case the specified path will be mounted from the host to the same path in the container —, or a colon-separated pair of paths — in which case the first specified path is the source in the host, and the second path is the destination in the container —, or a colon-separated triple of source path, destination path and mount options. Mount options are comma-separated and currently, only "rbind" and "norbind" are allowed. Defaults to "rbind". Backslash escapes are interpreted, so \: may be used to embed colons in either path. This option may be specified multiple times for creating multiple independent bind mount points. The option creates read-only bind mounts. Mount a tmpfs file system into the container. Takes a single absolute path argument that specifies where to mount the tmpfs instance to (in which case the directory access mode will be chosen as 0755, owned by root/root), or optionally a colon-separated pair of path and mount option string that is used for mounting (in which case the kernel default for access mode and owner will be chosen, unless otherwise specified). This option is particularly useful for mounting directories such as /var as tmpfs, to allow state-less systems, in particular when combined with . Backslash escapes are interpreted in the path, so \: may be used to embed colons in the path. Combine multiple directory trees into one overlay file system and mount it into the container. Takes a list of colon-separated paths to the directory trees to combine and the destination mount point. Backslash escapes are interpreted in the paths, so \: may be used to embed colons in the paths. If three or more paths are specified, then the last specified path is the destination mount point in the container, all paths specified before refer to directory trees on the host and are combined in the specified order into one overlay file system. The left-most path is hence the lowest directory tree, the second-to-last path the highest directory tree in the stacking order. If is used instead of , a read-only overlay file system is created. If a writable overlay file system is created, all changes made to it are written to the highest directory tree in the stacking order, i.e. the second-to-last specified. If only two paths are specified, then the second specified path is used both as the top-level directory tree in the stacking order as seen from the host, as well as the mount point for the overlay file system in the container. At least two paths have to be specified. For details about overlay file systems, see overlayfs.txt. Note that the semantics of overlay file systems are substantially different from normal file systems, in particular regarding reported device and inode information. Device and inode information may change for a file while it is being written to, and processes might see out-of-date versions of files at times. Note that this switch automatically derives the workdir= mount option for the overlay file system from the top-level directory tree, making it a sibling of it. It is hence essential that the top-level directory tree is not a mount point itself (since the working directory must be on the same file system as the top-most directory tree). Also note that the lowerdir= mount option receives the paths to stack in the opposite order of this switch. Specifies an environment variable assignment to pass to the init process in the container, in the format NAME=VALUE. This may be used to override the default variables or to set additional variables. This parameter may be used more than once. Allows the container to share certain system facilities with the host. More specifically, this turns off PID namespacing, UTS namespacing and IPC namespacing, and thus allows the guest to see and interact more easily with processes outside of the container. Note that using this option makes it impossible to start up a full Operating System in the container, as an init system cannot operate in this mode. It is only useful to run specific programs or applications this way, without involving an init system in the container. This option implies . This option may not be combined with . Controls whether the container is registered with systemd-machined8. Takes a boolean argument, which defaults to yes. This option should be enabled when the container runs a full Operating System (more specifically: an init system), and is useful to ensure that the container is accessible via machinectl1 and shown by tools such as ps1. If the container does not run an init system, it is recommended to set this option to no. Note that implies . Instead of creating a transient scope unit to run the container in, simply register the service or scope unit systemd-nspawn has been invoked in with systemd-machined8. This has no effect if is used. This switch should be used if systemd-nspawn is invoked from within a service unit, and the service unit's sole purpose is to run a single systemd-nspawn container. This option is not available if run from a user session. Control the architecture ("personality") reported by uname2 in the container. Currently, only x86 and x86-64 are supported. This is useful when running a 32-bit container on a 64-bit host. If this setting is not used, the personality reported in the container is the same as the one reported on the host. Turns off any status output by the tool itself. When this switch is used, the only output from nspawn will be the console output of the container OS itself. MODE Boots the container in volatile mode. When no mode parameter is passed or when mode is specified as , full volatile mode is enabled. This means the root directory is mounted as a mostly unpopulated tmpfs instance, and /usr from the OS tree is mounted into it in read-only mode (the system thus starts up with read-only OS resources, but pristine state and configuration, any changes to the either are lost on shutdown). When the mode parameter is specified as , the OS tree is mounted read-only, but /var is mounted as a tmpfs instance into it (the system thus starts up with read-only OS resources and configuration, but pristine state, and any changes to the latter are lost on shutdown). When the mode parameter is specified as (the default), the whole OS tree is made available writable. Note that setting this to or will only work correctly with operating systems in the container that can boot up with only /usr mounted, and are able to populate /var automatically, as needed. MODE Controls whether systemd-nspawn shall search for and use additional per-container settings from .nspawn files. Takes a boolean or the special values or . If enabled (the default), a settings file named after the machine (as specified with the setting, or derived from the directory or image file name) with the suffix .nspawn is searched in /etc/systemd/nspawn/ and /run/systemd/nspawn/. If it is found there, its settings are read and used. If it is not found there, it is subsequently searched in the same directory as the image file or in the immediate parent of the root directory of the container. In this case, if the file is found, its settings will be also read and used, but potentially unsafe settings are ignored. Note that in both these cases, settings on the command line take precedence over the corresponding settings from loaded .nspawn files, if both are specified. Unsafe settings are considered all settings that elevate the container's privileges or grant access to additional resources such as files or directories of the host. For details about the format and contents of .nspawn files, consult systemd.nspawn5. If this option is set to , the file is searched, read and used the same way, however, the order of precedence is reversed: settings read from the .nspawn file will take precedence over the corresponding command line options, if both are specified. If this option is set to , the file is searched, read and used the same way, but regardless of being found in /etc/systemd/nspawn/, /run/systemd/nspawn/ or next to the image file or container root directory, all settings will take effect, however, command line arguments still take precedence over corresponding settings. If disabled, no .nspawn file is read and no settings except the ones on the command line are in effect.
Examples Download a Fedora image and start a shell in it # machinectl pull-raw --verify=no http://ftp.halifax.rwth-aachen.de/fedora/linux/releases/21/Cloud/Images/x86_64/Fedora-Cloud-Base-20141203-21.x86_64.raw.xz # systemd-nspawn -M Fedora-Cloud-Base-20141203-21 This downloads an image using machinectl1 and opens a shell in it. Build and boot a minimal Fedora distribution in a container # dnf -y --releasever=23 --installroot=/srv/mycontainer --disablerepo='*' --enablerepo=fedora --enablerepo=updates install systemd passwd dnf fedora-release vim-minimal # systemd-nspawn -bD /srv/mycontainer This installs a minimal Fedora distribution into the directory /srv/mycontainer/ and then boots an OS in a namespace container in it. Spawn a shell in a container of a minimal Debian unstable distribution # debootstrap --arch=amd64 unstable ~/debian-tree/ # systemd-nspawn -D ~/debian-tree/ This installs a minimal Debian unstable distribution into the directory ~/debian-tree/ and then spawns a shell in a namespace container in it. Boot a minimal Arch Linux distribution in a container # pacstrap -c -d ~/arch-tree/ base # systemd-nspawn -bD ~/arch-tree/ This installs a minimal Arch Linux distribution into the directory ~/arch-tree/ and then boots an OS in a namespace container in it. Boot into an ephemeral <literal>btrfs</literal> snapshot of the host system # systemd-nspawn -D / -xb This runs a copy of the host system in a btrfs snapshot which is removed immediately when the container exits. All file system changes made during runtime will be lost on shutdown, hence. Run a container with SELinux sandbox security contexts # chcon system_u:object_r:svirt_sandbox_file_t:s0:c0,c1 -R /srv/container # systemd-nspawn -L system_u:object_r:svirt_sandbox_file_t:s0:c0,c1 -Z system_u:system_r:svirt_lxc_net_t:s0:c0,c1 -D /srv/container /bin/sh Exit status The exit code of the program executed in the container is returned. See Also systemd1, systemd.nspawn5, chroot1, dnf8, debootstrap8, pacman8, systemd.slice5, machinectl1, btrfs8
systemd-229/man/systemd-path.xml000066400000000000000000000065001265713322000170010ustar00rootroot00000000000000 systemd-path systemd Developer Lennart Poettering lennart@poettering.net systemd-path 1 systemd-path List and query system and user paths systemd-path OPTIONS NAME Description systemd-path may be used to query system and user paths. The tool makes many of the paths described in file-hierarchy7 available for querying. When invoked without arguments, a list of known paths and their current values is shown. When at least one argument is passed, the path with this name is queried and its value shown. The variables whose name begins with search- do not refer to individual paths, but instead to a list of colon-separated search paths, in their order of precedence. Options The following options are understood: The printed paths are suffixed by the specified string. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, file-hierarchy7 systemd-229/man/systemd-quotacheck.service.xml000066400000000000000000000064771265713322000216500ustar00rootroot00000000000000 systemd-quotacheck.service systemd Developer Lennart Poettering lennart@poettering.net systemd-quotacheck.service 8 systemd-quotacheck.service systemd-quotacheck File system quota checker logic systemd-quotacheck.service /usr/lib/systemd/systemd-quotacheck Description systemd-quotacheck.service is a service responsible for file system quota checks. It is run once at boot after all necessary file systems are mounted. It is pulled in only if at least one file system has quotas enabled. Kernel Command Line systemd-quotacheck understands one kernel command line parameter: quotacheck.mode= One of auto, force, skip. Controls the mode of operation. The default is auto, and ensures that file system quota checks are done when the file system quota checker deems them necessary. force unconditionally results in full file system quota checks. skip skips any file system quota checks. See Also systemd1, quotacheck8, systemd-fsck@.service8 systemd-229/man/systemd-random-seed.service.xml000066400000000000000000000051351265713322000217050ustar00rootroot00000000000000 systemd-random-seed.service systemd Developer Lennart Poettering lennart@poettering.net systemd-random-seed.service 8 systemd-random-seed.service systemd-random-seed Load and save the system random seed at boot and shutdown systemd-random-seed.service /usr/lib/systemd/systemd-random-seed Description systemd-random-seed.service is a service that restores the random seed of the system at early boot and saves it at shutdown. See random4 for details. Saving/restoring the random seed across boots increases the amount of available entropy early at boot. On disk the random seed is stored in /var/lib/systemd/random-seed. See Also systemd1, random4 systemd-229/man/systemd-remount-fs.service.xml000066400000000000000000000066141265713322000216110ustar00rootroot00000000000000 systemd-remount-fs.service systemd Developer Lennart Poettering lennart@poettering.net systemd-remount-fs.service 8 systemd-remount-fs.service systemd-remount-fs Remount root and kernel file systems systemd-remount-fs.service /usr/lib/systemd/systemd-remount-fs Description systemd-remount-fs.service is an early boot service that applies mount options listed in fstab5 to the root file system, the /usr file system, and the kernel API file systems. This is required so that the mount options of these file systems — which are pre-mounted by the kernel, the initial RAM disk, container environments or system manager code — are updated to those listed in /etc/fstab. This service ignores normal file systems and only changes the root file system (i.e. /), /usr and the virtual kernel API file systems such as /proc, /sys or /dev. This service executes no operation if /etc/fstab does not exist or lists no entries for the mentioned file systems. For a longer discussion of kernel API file systems see API File Systems. See Also systemd1, fstab5, mount8 systemd-229/man/systemd-resolve.xml000066400000000000000000000301671265713322000175320ustar00rootroot00000000000000 systemd-resolve systemd Developer Lennart Poettering lennart@poettering.net systemd-resolve 1 systemd-resolve Resolve domain names, IPV4 and IPv6 addresses, DNS resource records, and services systemd-resolve OPTIONS HOSTNAME systemd-resolve OPTIONS ADDRESS systemd-resolve OPTIONS --type=TYPE RRDOMAIN systemd-resolve OPTIONS --service NAME TYPE DOMAIN systemd-resolve OPTIONS --statistics systemd-resolve OPTIONS --reset-statistics Description systemd-resolve may be used to resolve domain names, IPv4 and IPv6 addresses, DNS resource records and services with the systemd-resolved.service8 resolver service. By default, the specified list of parameters will be resolved as hostnames, retrieving their IPv4 and IPv6 addresses. If the parameters specified are formatted as IPv4 or IPv6 operation the reverse operation is done, and a hostname is retrieved for the specified addresses. The switch may be used to specify a DNS resource record type (A, AAAA, SOA, MX, ...) in order to request a specific DNS resource record, instead of the address or reverse address lookups. The special value help may be used to list known values. The switch may be used to resolve SRV and DNS-SD services (see below). In this mode, between one and three arguments are required. If three parameters are passed the first is assumed to be the DNS-SD service name, the second the SRV service type, and the third the domain to search in. In this case a full DNS-SD style SRV and TXT lookup is executed. If only two parameters are specified, the first is assumed to be the SRV service type, and the second the domain to look in. In this case no TXT RR is requested. Finally, if only one parameter is specified, it is assumed to be a domain name, that is already prefixed with an SRV type, and an SRV lookup is done (no TXT). The switch may be used to show resolver statistics, including information about the number of succesful and failed DNSSEC validations. The may be used to reset various statistics counters maintained the resolver, including those shown in the output. This operation requires root privileges. Options By default, when resolving a hostname, both IPv4 and IPv6 addresses are acquired. By specifying only IPv4 addresses are requested, by specifying only IPv6 addresses are requested. INTERFACE INTERFACE Specifies the network interface to execute the query on. This may either be specified as numeric interface index or as network interface string (e.g. en0). Note that this option has no effect if system-wide DNS configuration (as configured in /etc/resolv.conf or /etc/systemd/resolve.conf) in place of per-link configuration is used. PROTOCOL PROTOCOL Specifies the network protocol for the query. May be one of dns (i.e. classic unicast DNS), llmnr (Link-Local Multicast Name Resolution), llmr-ipv4, llmnr-ipv6 (LLMNR via the indicated underlying IP protocols). By default the lookup is done via all protocols suitable for the lookup. If used, limits the set of protocols that may be used. Use this option multiple times to enable resolving via multiple protocols at the same time. The setting llmnr is identical to specifying this switch once with llmnr-ipv4 and once via llmnr-ipv6. Note that this option does not force the service to resolve the operation with the specified protocol, as that might require a suitable network interface and configuration. The special value help may be used to list known values. TYPE TYPE CLASS CLASS Specifies the DNS resource record type (e.g. A, AAAA, MX, …) and class (e.g. IN, ANY, …) to look up. If these options are used a DNS resource record set matching the specified class and type is requested. The class defaults to IN if only a type is specified. The special value help may be used to list known values. Enables service resolution. This enables DNS-SD and simple SRV service resolution, depending on the specified list of parameters (see above). BOOL Takes a boolean parameter. If true (the default), when doing a service lookup with the hostnames contained in the SRV resource records are resolved as well. BOOL Takes a boolean parameter. If true (the default), when doing a DNS-SD service lookup with the TXT service metadata record is resolved as well. BOOL Takes a boolean parameter. If true (the default), DNS CNAME or DNAME redirections are followed. Otherwise, if a CNAME or DNAME record is encountered while resolving, an error is returned. BOOL Takes a boolean parameter. If true (the default), any specified single-label hostnames will be searched in the domains configured in the search domain list, if it is non-empty. Otherwise, the search domain logic is disabled. BOOL Takes a boolean parameter. If true (the default), column headers and meta information about the query response are shown. Otherwise, this output is suppressed. If specified general resolver statistics are shown, including information whether DNSSEC is enabled and available, as well as resolution and validation statistics. Resets the statistics counters shown in to zero. Examples Retrieve the addresses of the <literal>www.0pointer.net</literal> domain $ systemd-resolve www.0pointer.net Retrieve the domain of the <literal>85.214.157.71</literal> IP address $ systemd-resolve 85.214.157.71 Retrieve the MX record of the <literal>0pointer.net</literal> domain $ systemd-resolve -t MX 0pointer.net Resolve an SRV service $ systemd-resolve --service _xmpp-server._tcp gmail.com See Also systemd1, systemd-resolved.service8 systemd-229/man/systemd-resolved.service.xml000066400000000000000000000171711265713322000213350ustar00rootroot00000000000000 systemd-resolved.service systemd Developer Tom Gundersen teg@jklm.no systemd-resolved.service 8 systemd-resolved.service systemd-resolved Network Name Resolution manager systemd-resolved.service /usr/lib/systemd/systemd-resolved Description systemd-resolved is a system service that provides network name resolution to local applications. It implements a caching and validating DNS/DNSSEC stub resolver, as well as an LLMNR resolver and responder. In addition it maintains the /run/systemd/resolve/resolv.conf file for compatibility with traditional Linux programs. This file may be symlinked from /etc/resolv.conf. The glibc NSS module nss-resolve8 is required to permit glibc's NSS resolver functions to resolve host names via systemd-resolved. The DNS servers contacted are determined from the global settings in /etc/systemd/resolved.conf, the per-link static settings in /etc/systemd/network/*.network files, and the per-link dynamic settings received over DHCP. See resolved.conf5 and systemd.network5 for details. To improve compatibility, /etc/resolv.conf is read in order to discover configured system DNS servers, but only if it is not a symlink to /run/systemd/resolve/resolv.conf (see above). systemd-resolved synthesizes DNS RRs for the following cases: The local, configured hostname is resolved to all locally configured IP addresses ordered by their scope, or — if none are configured — the IPv4 address 127.0.0.2 (which is on the local loopback) and the IPv6 address ::1 (which is the local host). The hostname localhost (as well as any hostname ending in .localhost, .localdomain or equal to localdomain) is resolved to the IP addresses 127.0.0.1 and ::1. The hostname gateway is resolved to all current default routing gateway addresses, ordered by their metric. This assigns a stable hostname to the current gateway, useful for referencing it independently of the current network configuration state. The mappings defined in /etc/hosts are resolved to their configured addresses and back. Lookup requests are routed to the available DNS servers and LLMNR interfaces according to the following rules: Lookups for the special hostname localhost are never routed to the network. (A few other, special domains are handled the same way.) Single-label names are routed to all local interfaces capable of IP multicasting, using the LLMNR protocol. Lookups for IPv4 addresses are only sent via LLMNR on IPv4, and lookups for IPv6 addresses are only sent via LLMNR on IPv6. Lookups for the locally configured host name and the gateway host name are never routed to LLMNR. Multi-label names are routed to all local interfaces that have a DNS sever configured, plus the globally configured DNS server if there is one. Address lookups from the link-local address range are never routed to DNS. If lookups are routed to multiple interfaces, the first successful response is returned (thus effectively merging the lookup zones on all matching interfaces). If the lookup failed on all interfaces, the last failing response is returned. Routing of lookups may be influenced by configuring per-interface domain names. See systemd.network5 for details. Lookups for a hostname ending in one of the per-interface domains are exclusively routed to the matching interfaces. Note that /run/systemd/resolve/resolv.conf should not be used directly by applications, but only through a symlink from /etc/resolv.conf. See the resolved D-Bus API Documentation for information about the APIs systemd-resolved provides. See Also systemd1, resolved.conf5, dnssec-trust-anchors.d5, nss-resolve8, systemd-resolve1, resolv.conf5, hosts5, systemd.network5, systemd-networkd.service8 systemd-229/man/systemd-rfkill.service.xml000066400000000000000000000056771265713322000210050ustar00rootroot00000000000000 systemd-rfkill.service systemd Developer Lennart Poettering lennart@poettering.net systemd-rfkill.service 8 systemd-rfkill.service systemd-rfkill.socket systemd-rfkill Load and save the RF kill switch state at boot and change systemd-rfkill.service systemd-rfkill.socket /usr/lib/systemd/systemd-rfkill Description systemd-rfkill.service is a service that restores the RF kill switch state at early boot and saves it on each change. On disk, the RF kill switch state is stored in /var/lib/systemd/rfkill/. Kernel Command Line systemd-rfkill understands the following kernel command line parameter: systemd.restore_state= Takes a boolean argument. Defaults to 1. If 0, does not restore the rfkill settings on boot. However, settings will still be stored on shutdown. See Also systemd1 systemd-229/man/systemd-run.xml000066400000000000000000000404201265713322000166500ustar00rootroot00000000000000 systemd-run systemd Developer Lennart Poettering lennart@poettering.net systemd-run 1 systemd-run Run programs in transient scope or service or timer units systemd-run OPTIONS COMMAND ARGS systemd-run OPTIONS TIMER OPTIONS COMMAND ARGS Description systemd-run may be used to create and start a transient .service or .scope unit and run the specified COMMAND in it. It may also be used to create and start transient .timer units. If a command is run as transient service unit, it will be started and managed by the service manager like any other service, and thus shows up in the output of systemctl list-units like any other unit. It will run in a clean and detached execution environment, with the service manager as its parent process. In this mode, systemd-run will start the service asynchronously in the background and return after the command has begun execution. If a command is run as transient scope unit, it will be started by systemd-run itself as parent process and will thus inherit the execution environment of the caller. However, the processes of the command are managed by the service manager similar to normal services, and will show up in the output of systemctl list-units. Execution in this case is synchronous, and will return only when the command finishes. This mode is enabled via the switch (see below). If a command is run with timer options such as (see below), a transient timer unit is created alongside the service unit for the specified command. Only the transient timer unit is started immediately, the transient service unit will be started when the transient timer elapses. If the is specified, the COMMAND may be omitted. In this case, systemd-run only creates a .timer unit that invokes the specified unit when elapsing. Options The following options are understood: Do not query the user for authentication for privileged operations. Create a transient .scope unit instead of the default transient .service unit. Use this unit name instead of an automatically generated one. Sets a unit property for the scope or service unit that is created. This takes an assignment in the same format as systemctl1's set-property command. Provide a description for the service or scope unit. If not specified, the command itself will be used as a description. See Description= in systemd.unit5. Make the new .service or .scope unit part of the specified slice, instead of the system.slice. After the service or scope process has terminated, keep the service around until it is explicitly stopped. This is useful to collect runtime information about the service after it finished running. Also see RemainAfterExit= in systemd.service5. When terminating the scope or service unit, send a SIGHUP immediately after SIGTERM. This is useful to indicate to shells and shell-like processes that the connection has been severed. Also see SendSIGHUP= in systemd.kill5. Sets the service type. Also see Type= in systemd.service5. This option has no effect in conjunction with . Defaults to simple. Runs the service process under the UNIX user and group. Also see User= and Group= in systemd.exec5. Runs the service process with the specified nice level. Also see Nice= in systemd.exec5. Runs the service process with the specified environment variables set. Also see Environment= in systemd.exec5. When invoking a command, the service connects its standard input and output to the invoking tty via a pseudo TTY device. This allows invoking binaries as services that expect interactive user input, such as interactive command shells. Suppresses additional informational output while running. This is particularly useful in combination with when it will suppress the initial message explaining how to terminate the TTY connection. Defines monotonic timers relative to different starting points. Also see OnActiveSec=, OnBootSec=, OnStartupSec=, OnUnitActiveSec= and OnUnitInactiveSec= in systemd.timer5. This options have no effect in conjunction with . Defines realtime (i.e. wallclock) timers with calendar event expressions. Also see OnCalendar= in systemd.timer5. This option has no effect in conjunction with . Sets a timer unit property for the timer unit that is created. It is similar with but only for created timer unit. This option only has effect in conjunction with , , , , , . This takes an assignment in the same format as systemctl1's set-property command. Do not synchronously wait for the requested operation to finish. If this is not specified, the job will be verified, enqueued and systemd-run will wait until the unit's start-up is completed. By passing this argument, it is only verified and enqueued. All command line arguments after the first non-option argument become part of the command line of the launched process. If a command is run as service unit, its first argument needs to be an absolute binary path. Exit status On success, 0 is returned, a non-zero failure code otherwise. Examples The following command will log the environment variables provided by systemd to services: # systemd-run env Running as unit run-19945.service. # journalctl -u run-19945.service Sep 08 07:37:21 bupkis systemd[1]: Starting /usr/bin/env... Sep 08 07:37:21 bupkis systemd[1]: Started /usr/bin/env. Sep 08 07:37:21 bupkis env[19948]: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin Sep 08 07:37:21 bupkis env[19948]: LANG=en_US.UTF-8 Sep 08 07:37:21 bupkis env[19948]: BOOT_IMAGE=/vmlinuz-3.11.0-0.rc5.git6.2.fc20.x86_64 The following command invokes the updatedb8 tool, but lowers the block I/O weight for it to 10. See systemd.resource-control5 for more information on the BlockIOWeight= property. # systemd-run -p BlockIOWeight=10 updatedb The following command will touch a file after 30 seconds. # date; systemd-run --on-active=30 --timer-property=AccuracySec=100ms /bin/touch /tmp/foo Mon Dec 8 20:44:24 KST 2014 Running as unit run-71.timer. Will run as unit run-71.service. # journalctl -b -u run-71.timer -- Logs begin at Fri 2014-12-05 19:09:21 KST, end at Mon 2014-12-08 20:44:54 KST. -- Dec 08 20:44:38 container systemd[1]: Starting /bin/touch /tmp/foo. Dec 08 20:44:38 container systemd[1]: Started /bin/touch /tmp/foo. # journalctl -b -u run-71.service -- Logs begin at Fri 2014-12-05 19:09:21 KST, end at Mon 2014-12-08 20:44:54 KST. -- Dec 08 20:44:48 container systemd[1]: Starting /bin/touch /tmp/foo... Dec 08 20:44:48 container systemd[1]: Started /bin/touch /tmp/foo. The following command invokes /bin/bash as a service passing its standard input, output and error to the calling TTY. # systemd-run -t --send-sighup /bin/bash See Also systemd1, systemctl1, systemd.unit5, systemd.service5, systemd.scope5, systemd.slice5, systemd.exec5, systemd.resource-control5, systemd.timer5, machinectl1 systemd-229/man/systemd-sleep.conf.xml000066400000000000000000000157561265713322000201160ustar00rootroot00000000000000 systemd-sleep.conf systemd Developer Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl systemd-sleep.conf 5 systemd-sleep.conf sleep.conf.d Suspend and hibernation configuration file /etc/systemd/sleep.conf /etc/systemd/sleep.conf.d/*.conf /run/systemd/sleep.conf.d/*.conf /usr/lib/systemd/sleep.conf.d/*.conf Description systemd supports three general power-saving modes: suspend a low-power state where execution of the OS is paused, and complete power loss might result in lost data, and which is fast to enter and exit. This corresponds to suspend, standby, or freeze states as understood by the kernel. hibernate a low-power state where execution of the OS is paused, and complete power loss does not result in lost data, and which might be slow to enter and exit. This corresponds to the hibernation as understood by the kernel. hybrid-sleep a low-power state where execution of the OS is paused, which might be slow to enter, and on complete power loss does not result in lost data but might be slower to exit in that case. This mode is called suspend-to-both by the kernel. Settings in these files determine what strings will be written to /sys/power/disk and /sys/power/state by systemd-sleep8 when systemd1 attempts to suspend or hibernate the machine. Options The following options can be configured in the [Sleep] section of /etc/systemd/sleep.conf or a sleep.conf.d file: SuspendMode= HibernateMode= HybridSleepMode= The string to be written to /sys/power/disk by, respectively, systemd-suspend.service8, systemd-hibernate.service8, or systemd-hybrid-sleep.service8. More than one value can be specified by separating multiple values with whitespace. They will be tried in turn, until one is written without error. If neither succeeds, the operation will be aborted. SuspendState= HibernateState= HybridSleepState= The string to be written to /sys/power/state by, respectively, systemd-suspend.service8, systemd-hibernate.service8, or systemd-hybrid-sleep.service8. More than one value can be specified by separating multiple values with whitespace. They will be tried in turn, until one is written without error. If neither succeeds, the operation will be aborted. Example: freeze Example: to exploit the freeze mode added in Linux 3.9, one can use systemctl suspend with [Sleep] SuspendState=freeze See Also systemd-sleep8, systemd-suspend.service8, systemd-hibernate.service8, systemd-hybrid-sleep.service8, systemd1, systemd.directives7 systemd-229/man/systemd-socket-proxyd.xml000066400000000000000000000154351265713322000206670ustar00rootroot00000000000000 systemd-socket-proxyd systemd Developer David Strauss david@davidstrauss.net systemd-socket-proxyd 8 systemd-socket-proxyd Bidirectionally proxy local sockets to another (possibly remote) socket. systemd-socket-proxyd OPTIONS HOST:PORT systemd-socket-proxyd OPTIONS UNIX-DOMAIN-SOCKET-PATH Description systemd-socket-proxyd is a generic socket-activated network socket forwarder proxy daemon for IPv4, IPv6 and UNIX stream sockets. It may be used to bi-directionally forward traffic from a local listening socket to a local or remote destination socket. One use of this tool is to provide socket activation support for services that do not natively support socket activation. On behalf of the service to activate, the proxy inherits the socket from systemd, accepts each client connection, opens a connection to a configured server for each client, and then bidirectionally forwards data between the two. This utility's behavior is similar to socat1. The main differences for systemd-socket-proxyd are support for socket activation with Accept=false and an event-driven design that scales better with the number of connections. Options The following options are understood: Exit status On success, 0 is returned, a non-zero failure code otherwise. Examples Simple Example Use two services with a dependency and no namespace isolation. proxy-to-nginx.socket proxy-to-nginx.service nginx.conf Enabling the proxy Namespace Example Similar as above, but runs the socket proxy and the main service in the same private namespace, assuming that nginx.service has PrivateTmp= and PrivateNetwork= set, too. proxy-to-nginx.socket proxy-to-nginx.service nginx.conf Enabling the proxy See Also systemd1, systemd.socket5, systemd.service5, systemctl1, socat1, nginx1, curl1 systemd-229/man/systemd-suspend.service.xml000066400000000000000000000133241265713322000211670ustar00rootroot00000000000000 systemd-suspend.service systemd Developer Lennart Poettering lennart@poettering.net systemd-suspend.service 8 systemd-suspend.service systemd-hibernate.service systemd-hybrid-sleep.service systemd-sleep System sleep state logic systemd-suspend.service systemd-hibernate.service systemd-hybrid-sleep.service /usr/lib/systemd/system-sleep Description systemd-suspend.service is a system service that is pulled in by suspend.target and is responsible for the actual system suspend. Similarly, systemd-hibernate.service is pulled in by hibernate.target to execute the actual hibernation. Finally, systemd-hybrid-sleep.service is pulled in by hybrid-sleep.target to execute hybrid hibernation with system suspend. Immediately before entering system suspend and/or hibernation systemd-suspend.service (and the other mentioned units, respectively) will run all executables in /usr/lib/systemd/system-sleep/ and pass two arguments to them. The first argument will be pre, the second either suspend, hibernate, or hybrid-sleep depending on the chosen action. Immediately after leaving system suspend and/or hibernation the same executables are run, but the first argument is now post. All executables in this directory are executed in parallel, and execution of the action is not continued until all executables have finished. Note that scripts or binaries dropped in /usr/lib/systemd/system-sleep/ are intended for local use only and should be considered hacks. If applications want to be notified of system suspend/hibernation and resume, there are much nicer interfaces available. Note that systemd-suspend.service, systemd-hibernate.service, and systemd-hybrid-sleep.service should never be executed directly. Instead, trigger system sleep states with a command such as systemctl suspend or similar. Internally, this service will echo a string like mem into /sys/power/state, to trigger the actual system suspend. What exactly is written where can be configured in the [Sleep] section of /etc/systemd/sleep.conf or a sleep.conf.d file. See systemd-sleep.conf5. Options systemd-sleep understands the following commands: Suspend, hibernate, or put the system to hybrid sleep. See Also systemd-sleep.conf5, systemd1, systemctl1, systemd.special7, systemd-halt.service8 systemd-229/man/systemd-sysctl.service.xml000066400000000000000000000071021265713322000210240ustar00rootroot00000000000000 systemd-sysctl.service systemd Developer Lennart Poettering lennart@poettering.net systemd-sysctl.service 8 systemd-sysctl.service systemd-sysctl Configure kernel parameters at boot /usr/lib/systemd/systemd-sysctl OPTIONS CONFIGFILE systemd-sysctl.service Description systemd-sysctl.service is an early boot service that configures sysctl8 kernel parameters. If invoked with no arguments, it applies all directives from all configuration files in sysctl.d5 are searched for a matching file. If one or more filenames are passed on the command line, only the directives in these files are applied. See sysctl.d5 for information about the configuration of this service. Options Only apply rules with the specified prefix. See Also systemd1, sysctl.d5, sysctl8, systemd-229/man/systemd-system-update-generator.xml000066400000000000000000000051711265713322000226400ustar00rootroot00000000000000 systemd-system-update-generator systemd Developer Lennart Poettering lennart@poettering.net systemd-system-update-generator 8 systemd-system-update-generator Generator for redirecting boot to offline update mode /usr/lib/systemd/system-generators/systemd-system-update-generator Description systemd-system-update-generator is a generator that automatically redirects the boot process to system-update.target if /system-update exists. This is required to implement the logic explained in the System Updates Specification. systemd-system-update-generator implements systemd.generator7. See Also systemd1, systemd.special7 systemd-229/man/systemd-system.conf.xml000066400000000000000000000455031265713322000203230ustar00rootroot00000000000000 systemd-system.conf systemd Developer Lennart Poettering lennart@poettering.net systemd-system.conf 5 systemd-system.conf system.conf.d systemd-user.conf user.conf.d System and session service manager configuration files /etc/systemd/system.conf, /etc/systemd/system.conf.d/*.conf, /run/systemd/system.conf.d/*.conf, /usr/lib/systemd/system.conf.d/*.conf /etc/systemd/user.conf, /etc/systemd/user.conf.d/*.conf, /run/systemd/user.conf.d/*.conf, /usr/lib/systemd/user.conf.d/*.conf Description When run as a system instance, systemd interprets the configuration file system.conf and the files in system.conf.d directories; when run as a user instance, systemd interprets the configuration file user.conf and the files in user.conf.d directories. These configuration files contain a few settings controlling basic manager operations. Options All options are configured in the [Manager] section: LogLevel= LogTarget= LogColor= LogLocation= DumpCore=yes CrashChangeVT=no CrashShell=no CrashReboot=no ShowStatus=yes DefaultStandardOutput=journal DefaultStandardError=inherit Configures various parameters of basic manager operation. These options may be overridden by the respective command line arguments. See systemd1 for details about these command line arguments. CPUAffinity= Configures the initial CPU affinity for the init process. Takes a list of CPU indices or ranges separated by either whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated by a dash. JoinControllers=cpu,cpuacct net_cls,netprio Configures controllers that shall be mounted in a single hierarchy. By default, systemd will mount all controllers which are enabled in the kernel in individual hierarchies, with the exception of those listed in this setting. Takes a space-separated list of comma-separated controller names, in order to allow multiple joined hierarchies. Defaults to 'cpu,cpuacct'. Pass an empty string to ensure that systemd mounts all controllers in separate hierarchies. Note that this option is only applied once, at very early boot. If you use an initial RAM disk (initrd) that uses systemd, it might hence be necessary to rebuild the initrd if this option is changed, and make sure the new configuration file is included in it. Otherwise, the initrd might mount the controller hierarchies in a different configuration than intended, and the main system cannot remount them anymore. RuntimeWatchdogSec= ShutdownWatchdogSec= Configure the hardware watchdog at runtime and at reboot. Takes a timeout value in seconds (or in other time units if suffixed with ms, min, h, d, w). If RuntimeWatchdogSec= is set to a non-zero value, the watchdog hardware (/dev/watchdog) will be programmed to automatically reboot the system if it is not contacted within the specified timeout interval. The system manager will ensure to contact it at least once in half the specified timeout interval. This feature requires a hardware watchdog device to be present, as it is commonly the case in embedded and server systems. Not all hardware watchdogs allow configuration of the reboot timeout, in which case the closest available timeout is picked. ShutdownWatchdogSec= may be used to configure the hardware watchdog when the system is asked to reboot. It works as a safety net to ensure that the reboot takes place even if a clean reboot attempt times out. By default RuntimeWatchdogSec= defaults to 0 (off), and ShutdownWatchdogSec= to 10min. These settings have no effect if a hardware watchdog is not available. CapabilityBoundingSet= Controls which capabilities to include in the capability bounding set for PID 1 and its children. See capabilities7 for details. Takes a whitespace-separated list of capability names as read by cap_from_name3. Capabilities listed will be included in the bounding set, all others are removed. If the list of capabilities is prefixed with ~, all but the listed capabilities will be included, the effect of the assignment inverted. Note that this option also affects the respective capabilities in the effective, permitted and inheritable capability sets. The capability bounding set may also be individually configured for units using the CapabilityBoundingSet= directive for units, but note that capabilities dropped for PID 1 cannot be regained in individual units, they are lost for good. SystemCallArchitectures= Takes a space-separated list of architecture identifiers. Selects from which architectures system calls may be invoked on this system. This may be used as an effective way to disable invocation of non-native binaries system-wide, for example to prohibit execution of 32-bit x86 binaries on 64-bit x86-64 systems. This option operates system-wide, and acts similar to the SystemCallArchitectures= setting of unit files, see systemd.exec5 for details. This setting defaults to the empty list, in which case no filtering of system calls based on architecture is applied. Known architecture identifiers are x86, x86-64, x32, arm and the special identifier native. The latter implicitly maps to the native architecture of the system (or more specifically, the architecture the system manager was compiled for). Set this setting to native to prohibit execution of any non-native binaries. When a binary executes a system call of an architecture that is not listed in this setting, it will be immediately terminated with the SIGSYS signal. TimerSlackNSec= Sets the timer slack in nanoseconds for PID 1, which is inherited by all executed processes, unless overridden individually, for example with the TimerSlackNSec= setting in service units (for details see systemd.exec5). The timer slack controls the accuracy of wake-ups triggered by system timers. See prctl2 for more information. Note that in contrast to most other time span definitions this parameter takes an integer value in nano-seconds if no unit is specified. The usual time units are understood too. DefaultTimerAccuracySec= Sets the default accuracy of timer units. This controls the global default for the AccuracySec= setting of timer units, see systemd.timer5 for details. AccuracySec= set in individual units override the global default for the specific unit. Defaults to 1min. Note that the accuracy of timer units is also affected by the configured timer slack for PID 1, see TimerSlackNSec= above. DefaultTimeoutStartSec= DefaultTimeoutStopSec= DefaultRestartSec= Configures the default timeouts for starting and stopping of units, as well as the default time to sleep between automatic restarts of units, as configured per-unit in TimeoutStartSec=, TimeoutStopSec= and RestartSec= (for services, see systemd.service5 for details on the per-unit settings). For non-service units, DefaultTimeoutStartSec= sets the default TimeoutSec= value. DefaultTimeoutStartSec= and DefaultTimeoutStopSec= default to 90s. DefaultRestartSec= defaults to 100ms. DefaultStartLimitInterval= DefaultStartLimitBurst= Configure the default unit start rate limiting, as configured per-service by StartLimitInterval= and StartLimitBurst=. See systemd.service5 for details on the per-service settings. DefaultStartLimitInterval= defaults to 10s. DefaultStartLimitBurst= defaults to 5. DefaultEnvironment= Sets manager environment variables passed to all executed processes. Takes a space-separated list of variable assignments. See environ7 for details about environment variables. Example: DefaultEnvironment="VAR1=word1 word2" VAR2=word3 "VAR3=word 5 6" Sets three variables VAR1, VAR2, VAR3. DefaultCPUAccounting= DefaultBlockIOAccounting= DefaultMemoryAccounting= DefaultTasksAccounting= Configure the default resource accounting settings, as configured per-unit by CPUAccounting=, BlockIOAccounting=, MemoryAccounting= and TasksAccounting=. See systemd.resource-control5 for details on the per-unit settings. DefaulTasksAccounting= defaults to on, the other three settings to off. DefaultTasksMax= Configure the default value for the per-unit TasksMax= setting. See systemd.resource-control5 for details. This setting applies to all unit types that support resource control settings, with the exception of slice units. Defaults to 512. DefaultLimitCPU= DefaultLimitFSIZE= DefaultLimitDATA= DefaultLimitSTACK= DefaultLimitCORE= DefaultLimitRSS= DefaultLimitNOFILE= DefaultLimitAS= DefaultLimitNPROC= DefaultLimitMEMLOCK= DefaultLimitLOCKS= DefaultLimitSIGPENDING= DefaultLimitMSGQUEUE= DefaultLimitNICE= DefaultLimitRTPRIO= DefaultLimitRTTIME= These settings control various default resource limits for units. See setrlimit2 for details. The resource limit is possible to specify in two formats, to set soft and hard limits to the same value, or to set both limits individually (e.g. DefaultLimitAS=4G:16G). Use the string infinity to configure no limit on a specific resource. The multiplicative suffixes K (=1024), M (=1024*1024) and so on for G, T, P and E may be used for resource limits measured in bytes (e.g. DefaultLimitAS=16G). For the limits referring to time values, the usual time units ms, s, min, h and so on may be used (see systemd.time7 for details). Note that if no time unit is specified for DefaultLimitCPU= the default unit of seconds is implied, while for DefaultLimitRTTIME= the default unit of microseconds is implied. Also, note that the effective granularity of the limits might influence their enforcement. For example, time limits specified for DefaultLimitCPU= will be rounded up implicitly to multiples of 1s. These settings may be overridden in individual units using the corresponding LimitXXX= directives. Note that these resource limits are only defaults for units, they are not applied to PID 1 itself. See Also systemd1, systemd.directives7, systemd.exec5, systemd.service5, environ7, capabilities7 systemd-229/man/systemd-sysusers.xml000066400000000000000000000073751265713322000177600ustar00rootroot00000000000000 systemd-sysusers systemd Developer Lennart Poettering lennart@poettering.net systemd-sysusers 8 systemd-sysusers systemd-sysusers.service Allocate system users and groups systemd-sysusers OPTIONS CONFIGFILE systemd-sysusers.service Description systemd-sysusers creates system users and groups, based on the file format and location specified in sysusers.d5. If invoked with no arguments, it applies all directives from all files found. If one or more filenames are passed on the command line, only the directives in these files are applied. If only the basename of a file is specified, all directories as specified in sysusers.d5 are searched for a matching file. If the string - is specified as filename, entries from the standard input of the process are read. Options The following options are understood: Takes a directory path as an argument. All paths will be prefixed with the given alternate root path, including config search paths. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, sysusers.d5 systemd-229/man/systemd-sysv-generator.xml000066400000000000000000000076251265713322000210460ustar00rootroot00000000000000 systemd-sysv-generator systemd Documentation Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl systemd-sysv-generator 8 systemd-sysv-generator Unit generator for SysV init scripts /usr/lib/systemd/system-generators/systemd-sysv-generator Description systemd-sysv-generator is a generator that creates wrapper .service units for SysV init scripts in /etc/init.d/* at boot and when configuration of the system manager is reloaded. This will allow systemd1 to support them similarly to native units. LSB headers in SysV init scripts are interpreted, and the ordering specified in the header is turned into dependencies between the generated unit and other units. The LSB facilities $remote_fs, $network, $named, $portmap, $time are supported and will be turned into dependencies on specific native systemd targets. See systemd.special5 for more details. SysV runlevels have corresponding systemd targets (runlevelX.target). The wrapper unit that is generated will be wanted by those targets which correspond to runlevels for which the script is enabled. systemd does not supports SysV scripts as part of early boot, so all wrapper units are ordered after basic.target. systemd-sysv-generator implements systemd.generator7. See Also systemd1, systemd.service5, systemd.target5 systemd-229/man/systemd-timedated.service.xml000066400000000000000000000060111265713322000214410ustar00rootroot00000000000000 systemd-timedated.service systemd Developer Lennart Poettering lennart@poettering.net systemd-timedated.service 8 systemd-timedated.service systemd-timedated Time and date bus mechanism systemd-timedated.service /usr/lib/systemd/systemd-timedated Description systemd-timedated is a system service that may be used as a mechanism to change the system clock and timezone, as well as to enable/disable NTP time synchronization. systemd-timedated is automatically activated on request and terminates itself when it is unused. The tool timedatectl1 is a command line client to this service. See the developer documentation for information about the APIs systemd-timedated provides. See Also systemd1, timedatectl1, localtime5, hwclock8 systemd-229/man/systemd-timesyncd.service.xml000066400000000000000000000100451265713322000215020ustar00rootroot00000000000000 systemd-timesyncd.service systemd Developer Kay Sievers kay@vrfy.org systemd-timesyncd.service 8 systemd-timesyncd.service systemd-timesyncd Network Time Synchronization systemd-timesyncd.service /usr/lib/systemd/systemd-timesyncd Description systemd-timesyncd is a system service that may be used to synchronize the local system clock with a remote Network Time Protocol server. It also saves the local time to disk every time the clock has been synchronized and uses this to possibly advance the system realtime clock on subsequent reboots to ensure it monotonically advances even if the system lacks a battery-buffered RTC chip. The NTP servers contacted are determined from the global settings in timesyncd.conf5, the per-link static settings in .network files, and the per-link dynamic settings received over DHCP. See systemd.network5 for more details. timedatectl1's set-ntp command may be used to enable and start, or disable and stop this service. Files /var/lib/systemd/clock This file contains the timestamp of the last successful synchronization. See Also systemd1, timesyncd.conf5, systemd.network5, systemd-networkd.service8, timedatectl1, localtime5, hwclock8 systemd-229/man/systemd-tmpfiles.xml000066400000000000000000000163651265713322000177020ustar00rootroot00000000000000 systemd-tmpfiles systemd Developer Lennart Poettering lennart@poettering.net systemd-tmpfiles 8 systemd-tmpfiles systemd-tmpfiles-setup.service systemd-tmpfiles-setup-dev.service systemd-tmpfiles-clean.service systemd-tmpfiles-clean.timer Creates, deletes and cleans up volatile and temporary files and directories systemd-tmpfiles OPTIONS CONFIGFILE systemd-tmpfiles-setup.service systemd-tmpfiles-setup-dev.service systemd-tmpfiles-clean.service systemd-tmpfiles-clean.timer Description systemd-tmpfiles creates, deletes, and cleans up volatile and temporary files and directories, based on the configuration file format and location specified in tmpfiles.d5. If invoked with no arguments, it applies all directives from all configuration files. If one or more absolute filenames are passed on the command line, only the directives in these files are applied. If only the basename of a configuration file is specified, all configuration directories as specified in tmpfiles.d5 are searched for a matching file. Options The following options are understood: If this option is passed, all files and directories marked with f, F, w, d, D, v, p, L, c, b, m in the configuration files are created or written to. Files and directories marked with z, Z, t, T, a, and A have their ownership, access mode and security labels set. If this option is passed, all files and directories with an age parameter configured will be cleaned up. If this option is passed, the contents of directories marked with D or R, and files or directories themselves marked with r or R are removed. Also execute lines with an exclamation mark. Only apply rules with paths that start with the specified prefix. This option can be specified multiple times. Ignore rules with paths that start with the specified prefix. This option can be specified multiple times. Takes a directory path as an argument. All paths will be prefixed with the given alternate root path, including config search paths. It is possible to combine , , and in one invocation. For example, during boot the following command line is executed to ensure that all temporary and volatile directories are removed and created according to the configuration file: systemd-tmpfiles --remove --create Unprivileged --cleanup operation systemd-tmpfiles tries to avoid changing the access and modification times on the directories it accesses, which requires CAP_ADMIN privileges. When running as non-root, directories which are checked for files to clean up will have their access time bumped, which might prevent their cleanup. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, tmpfiles.d5 systemd-229/man/systemd-tty-ask-password-agent.xml000066400000000000000000000116321265713322000223770ustar00rootroot00000000000000 systemd-tty-ask-password-agent systemd Developer Lennart Poettering lennart@poettering.net systemd-tty-ask-password-agent 1 systemd-tty-ask-password-agent List or process pending systemd password requests systemd-tty-ask-password-agent OPTIONS VARIABLE=VALUE Description systemd-tty-ask-password-agent is a password agent that handles password requests of the system, for example for hard disk encryption passwords or SSL certificate passwords that need to be queried at boot-time or during runtime. systemd-tty-ask-password-agent implements the Password Agents Specification. Options The following options are understood: Lists all currently pending system password requests. Process all currently pending system password requests by querying the user on the calling TTY. Continuously process password requests. Forward password requests to wall1 instead of querying the user on the calling TTY. Ask question with plymouth8 instead of querying the user on the calling TTY. Ask question on /dev/console instead of querying the user on the calling TTY. Exit status On success, 0 is returned, a non-zero failure code otherwise. See Also systemd1, systemctl1, systemd-ask-password-console.service8, wall1, plymouth8 systemd-229/man/systemd-udevd.service.xml000066400000000000000000000155511265713322000206210ustar00rootroot00000000000000 systemd-udevd.service systemd Developer Kay Sievers kay@vrfy.org systemd-udevd.service 8 systemd-udevd.service systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd Device event managing daemon systemd-udevd.service systemd-udevd-control.socket systemd-udevd-kernel.socket /usr/lib/systemd/systemd-udevd Description systemd-udevd listens to kernel uevents. For every event, systemd-udevd executes matching instructions specified in udev rules. See udev7 . The behavior of the daemon can be configured using udev.conf5, its command line options, environment variables, and on the kernel command line, or changed dynamically with udevadm control. Options Detach and run in the background. Print debug messages to standard error. Limit the number of events executed in parallel. Delay the execution of RUN instructions by the given number of seconds. This option might be useful when debugging system crashes during coldplug caused by loading non-working kernel modules. Set the number of seconds to wait for events to finish. After this time, the event will be terminated. The default is 180 seconds. Specify when systemd-udevd should resolve names of users and groups. When set to (the default), names will be resolved when the rules are parsed. When set to , names will be resolved for every event. When set to , names will never be resolved and all devices will be owned by root. Kernel command line Parameters starting with "rd." will be read when systemd-udevd is used in an initrd. udev.log-priority= rd.udev.log-priority= Set the log level. udev.children-max= rd.udev.children-max= Limit the number of events executed in parallel. udev.exec-delay= rd.udev.exec-delay= Delay the execution of RUN instructions by the given number of seconds. This option might be useful when debugging system crashes during coldplug caused by loading non-working kernel modules. udev.event-timeout= rd.udev.event-timeout= Wait for events to finish up to the given number of seconds. This option might be useful if events are terminated due to kernel drivers taking too long to initialize. net.ifnames= Network interfaces are renamed to give them predictable names when possible. It is enabled by default; specifying 0 disables it. See Also udev.conf5, udev7, udevadm8 systemd-229/man/systemd-update-done.service.xml000066400000000000000000000074561265713322000217240ustar00rootroot00000000000000 systemd-update-done.service systemd Developer Lennart Poettering lennart@poettering.net systemd-update-done.service 8 systemd-update-done.service systemd-update-done Mark /etc and /var fully updated systemd-update-done.service /usr/lib/systemd/systemd-update-done Description systemd-update-done.service is a service that is invoked as part of the first boot after the vendor operating system resources in /usr have been updated. This is useful to implement offline updates of /usr which might require updates to /etc or /var on the following boot. systemd-update-done.service updates the file modification time (mtime) of the stamp files /etc/.updated and /var/.updated to the modification time of the /usr directory, unless the stamp files are already newer. Services that shall run after offline upgrades of /usr should order themselves before systemd-update-done.service, and use the ConditionNeedsUpdate= (see systemd.unit5) condition to make sure to run when /etc or /var are older than /usr according to the modification times of the files described above. This requires that updates to /usr are always followed by an update of the modification time of /usr, for example by invoking touch1 on it. See Also systemd1, systemd.unit5, touch1 systemd-229/man/systemd-update-utmp.service.xml000066400000000000000000000052711265713322000217550ustar00rootroot00000000000000 systemd-update-utmp.service systemd Developer Lennart Poettering lennart@poettering.net systemd-update-utmp.service 8 systemd-update-utmp.service systemd-update-utmp-runlevel.service systemd-update-utmp Write audit and utmp updates at bootup, runlevel changes and shutdown systemd-update-utmp.service systemd-update-utmp-runlevel.service /usr/lib/systemd/systemd-update-utmp Description systemd-update-utmp-runlevel.service is a service that writes SysV runlevel changes to utmp and wtmp, as well as the audit logs, as they occur. systemd-update-utmp.service does the same for system reboots and shutdown requests. See Also systemd1, utmp5, auditd8 systemd-229/man/systemd-user-sessions.service.xml000066400000000000000000000053451265713322000223340ustar00rootroot00000000000000 systemd-user-sessions.service systemd Developer Lennart Poettering lennart@poettering.net systemd-user-sessions.service 8 systemd-user-sessions.service systemd-user-sessions Permit user logins after boot, prohibit user logins at shutdown systemd-user-sessions.service /usr/lib/systemd/systemd-user-sessions Description systemd-user-sessions.service is a service that controls user logins through pam_nologin8. After basic system initialization is complete, it removes /run/nologin, thus permitting logins. Before system shutdown, it creates /run/nologin, thus prohibiting further logins. See Also systemd1, systemd-logind.service8, pam_nologin8 systemd-229/man/systemd-vconsole-setup.service.xml000066400000000000000000000102141265713322000224670ustar00rootroot00000000000000 systemd-vconsole-setup.service systemd Developer Lennart Poettering lennart@poettering.net systemd-vconsole-setup.service 8 systemd-vconsole-setup.service systemd-vconsole-setup Configure the virtual console at boot systemd-vconsole-setup.service /usr/lib/systemd/systemd-vconsole-setup Description systemd-vconsole-setup.service is an early boot service that configures the virtual console font and console keymap. Internally it calls loadkeys1 and setfont8. See vconsole.conf5 for information about the configuration files understood by this service. Kernel Command Line A few configuration parameters from vconsole.conf may be overridden on the kernel command line: vconsole.keymap= vconsole.keymap.toggle= Overrides the key mapping table for the keyboard and the second toggle keymap. vconsole.font= vconsole.font.map= vconsole.font.unimap= Configures the console font, the console map, and the unicode font map. See vconsole.conf5 for information about these settings. See Also systemd1, vconsole.conf5, loadkeys1, setfont8, systemd-localed.service8 systemd-229/man/systemd.automount.xml000066400000000000000000000162021265713322000201010ustar00rootroot00000000000000 systemd.automount systemd Developer Lennart Poettering lennart@poettering.net systemd.automount 5 systemd.automount Automount unit configuration automount.automount Description A unit configuration file whose name ends in .automount encodes information about a file system automount point controlled and supervised by systemd. This man page lists the configuration options specific to this unit type. See systemd.unit5 for the common options of all unit configuration files. The common configuration items are configured in the generic [Unit] and [Install] sections. The automount specific configuration options are configured in the [Automount] section. Automount units must be named after the automount directories they control. Example: the automount point /home/lennart must be configured in a unit file home-lennart.automount. For details about the escaping logic used to convert a file system path to a unit name see systemd.unit5. For each automount unit file a matching mount unit file (see systemd.mount5 for details) must exist which is activated when the automount path is accessed. Example: if an automount unit home-lennart.automount is active and the user accesses /home/lennart the mount unit home-lennart.mount will be activated. Automount units may be used to implement on-demand mounting as well as parallelized mounting of file systems. Automatic Dependencies If an automount unit is beneath another mount unit in the file system hierarchy, both a requirement and an ordering dependency between both units are created automatically. An implicit Before= dependency is created between an automount unit and the mount unit it activates. Automount units acquire automatic Before= and Conflicts= on umount.target in order to be stopped during shutdown, unless DefaultDependencies=no is set. <filename>fstab</filename> Automount units may either be configured via unit files, or via /etc/fstab (see fstab5 for details). For details how systemd parses /etc/fstab see systemd.mount5. If an automount point is configured in both /etc/fstab and a unit file, the configuration in the latter takes precedence. Options Automount files must include an [Automount] section, which carries information about the file system automount points it supervises. The options specific to the [Automount] section of automount units are the following: Where= Takes an absolute path of a directory of the automount point. If the automount point does not exist at time that the automount point is installed, it is created. This string must be reflected in the unit filename. (See above.) This option is mandatory. DirectoryMode= Directories of automount points (and any parent directories) are automatically created if needed. This option specifies the file system access mode used when creating these directories. Takes an access mode in octal notation. Defaults to 0755. TimeoutIdleSec= Configures an idle timeout. Once the mount has been idle for the specified time, systemd will attempt to unmount. Takes a unit-less value in seconds, or a time span value such as "5min 20s". Pass 0 to disable the timeout logic. The timeout is disabled by default. See Also systemd1, systemctl1, systemd.unit5, systemd.mount5, mount8, automount8, systemd.directives7 systemd-229/man/systemd.device.xml000066400000000000000000000164361265713322000173160ustar00rootroot00000000000000 systemd.device systemd Developer Lennart Poettering lennart@poettering.net systemd.device 5 systemd.device Device unit configuration device.device Description A unit configuration file whose name ends in .device encodes information about a device unit as exposed in the sysfs/udev7 device tree. This unit type has no specific options. See systemd.unit5 for the common options of all unit configuration files. The common configuration items are configured in the generic [Unit] and [Install] sections. A separate [Device] section does not exist, since no device-specific options may be configured. systemd will dynamically create device units for all kernel devices that are marked with the "systemd" udev tag (by default all block and network devices, and a few others). This may be used to define dependencies between devices and other units. To tag a udev device, use TAG+="systemd" in the udev rules file, see udev7 for details. Device units are named after the /sys and /dev paths they control. Example: the device /dev/sda5 is exposed in systemd as dev-sda5.device. For details about the escaping logic used to convert a file system path to a unit name see systemd.unit5. Automatic Dependencies Many unit types automatically acquire dependencies on device units of devices they require. For example, .socket unit acquire dependencies on the device units of the network interface specified in BindToDevice=. Similar, swap and mount units acquire dependencies on the units encapsulating their backing block devices. The udev Database The settings of device units may either be configured via unit files, or directly from the udev database (which is recommended). The following udev device properties are understood by systemd: SYSTEMD_WANTS= SYSTEMD_USER_WANTS= Adds dependencies of type Wants from the device unit to all listed units. The first form is used by the system systemd instance, the second by user systemd instances. Those settings may be used to activate arbitrary units when a specific device becomes available. Note that this and the other tags are not taken into account unless the device is tagged with the systemd string in the udev database, because otherwise the device is not exposed as a systemd unit (see above). Note that systemd will only act on Wants dependencies when a device first becomes active. It will not act on them if they are added to devices that are already active. Use SYSTEMD_READY= (see below) to influence on which udev event to trigger the dependencies. SYSTEMD_ALIAS= Adds an additional alias name to the device unit. This must be an absolute path that is automatically transformed into a unit name. (See above.) SYSTEMD_READY= If set to 0, systemd will consider this device unplugged even if it shows up in the udev tree. If this property is unset or set to 1, the device will be considered plugged if it is visible in the udev tree. This property has no influence on the behavior when a device disappears from the udev tree. This option is useful to support devices that initially show up in an uninitialized state in the tree, and for which a changed event is generated the moment they are fully set up. Note that SYSTEMD_WANTS= (see above) is not acted on as long as SYSTEMD_READY=0 is set for a device. ID_MODEL_FROM_DATABASE= ID_MODEL= If set, this property is used as description string for the device unit. See Also systemd1, systemctl1, systemd.unit5, udev7, systemd.directives7 systemd-229/man/systemd.exec.xml000066400000000000000000002166201265713322000170000ustar00rootroot00000000000000 systemd.exec systemd Developer Lennart Poettering lennart@poettering.net systemd.exec 5 systemd.exec Execution environment configuration service.service, socket.socket, mount.mount, swap.swap Description Unit configuration files for services, sockets, mount points, and swap devices share a subset of configuration options which define the execution environment of spawned processes. This man page lists the configuration options shared by these four unit types. See systemd.unit5 for the common options of all unit configuration files, and systemd.service5, systemd.socket5, systemd.swap5, and systemd.mount5 for more information on the specific unit configuration files. The execution specific configuration options are configured in the [Service], [Socket], [Mount], or [Swap] sections, depending on the unit type. Automatic Dependencies A few execution parameters result in additional, automatic dependencies to be added. Units with WorkingDirectory= or RootDirectory= set automatically gain dependencies of type Requires= and After= on all mount units required to access the specified paths. This is equivalent to having them listed explicitly in RequiresMountsFor=. Similar, units with PrivateTmp= enabled automatically get mount unit dependencies for all mounts required to access /tmp and /var/tmp. Units whose output standard output or error output is connected to any other sink but , and automatically acquire dependencies of type After= on journald.socket. Options WorkingDirectory= Takes an absolute directory path, or the special value ~. Sets the working directory for executed processes. If set to ~, the home directory of the user specified in User= is used. If not set, defaults to the root directory when systemd is running as a system instance and the respective user's home directory if run as user. If the setting is prefixed with the - character, a missing working directory is not considered fatal. Note that setting this parameter might result in additional dependencies to be added to the unit (see above). RootDirectory= Takes an absolute directory path. Sets the root directory for executed processes, with the chroot2 system call. If this is used, it must be ensured that the process binary and all its auxiliary files are available in the chroot() jail. Note that setting this parameter might result in additional dependencies to be added to the unit (see above). User= Group= Sets the Unix user or group that the processes are executed as, respectively. Takes a single user or group name or ID as argument. If no group is set, the default group of the user is chosen. SupplementaryGroups= Sets the supplementary Unix groups the processes are executed as. This takes a space-separated list of group names or IDs. This option may be specified more than once, in which case all listed groups are set as supplementary groups. When the empty string is assigned, the list of supplementary groups is reset, and all assignments prior to this one will have no effect. In any way, this option does not override, but extends the list of supplementary groups configured in the system group database for the user. Nice= Sets the default nice level (scheduling priority) for executed processes. Takes an integer between -20 (highest priority) and 19 (lowest priority). See setpriority2 for details. OOMScoreAdjust= Sets the adjustment level for the Out-Of-Memory killer for executed processes. Takes an integer between -1000 (to disable OOM killing for this process) and 1000 (to make killing of this process under memory pressure very likely). See proc.txt for details. IOSchedulingClass= Sets the I/O scheduling class for executed processes. Takes an integer between 0 and 3 or one of the strings , , or . See ioprio_set2 for details. IOSchedulingPriority= Sets the I/O scheduling priority for executed processes. Takes an integer between 0 (highest priority) and 7 (lowest priority). The available priorities depend on the selected I/O scheduling class (see above). See ioprio_set2 for details. CPUSchedulingPolicy= Sets the CPU scheduling policy for executed processes. Takes one of , , , or . See sched_setscheduler2 for details. CPUSchedulingPriority= Sets the CPU scheduling priority for executed processes. The available priority range depends on the selected CPU scheduling policy (see above). For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority) can be used. See sched_setscheduler2 for details. CPUSchedulingResetOnFork= Takes a boolean argument. If true, elevated CPU scheduling priorities and policies will be reset when the executed processes fork, and can hence not leak into child processes. See sched_setscheduler2 for details. Defaults to false. CPUAffinity= Controls the CPU affinity of the executed processes. Takes a list of CPU indices or ranges separated by either whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated by a dash. This option may be specified more than once, in which case the specified CPU affinity masks are merged. If the empty string is assigned, the mask is reset, all assignments prior to this will have no effect. See sched_setaffinity2 for details. UMask= Controls the file mode creation mask. Takes an access mode in octal notation. See umask2 for details. Defaults to 0022. Environment= Sets environment variables for executed processes. Takes a space-separated list of variable assignments. This option may be specified more than once, in which case all listed variables will be set. If the same variable is set twice, the later setting will override the earlier setting. If the empty string is assigned to this option, the list of environment variables is reset, all prior assignments have no effect. Variable expansion is not performed inside the strings, however, specifier expansion is possible. The $ character has no special meaning. If you need to assign a value containing spaces to a variable, use double quotes (") for the assignment. Example: Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" gives three variables VAR1, VAR2, VAR3 with the values word1 word2, word3, $word 5 6. See environ7 for details about environment variables. EnvironmentFile= Similar to Environment= but reads the environment variables from a text file. The text file should contain new-line-separated variable assignments. Empty lines, lines without an = separator, or lines starting with ; or # will be ignored, which may be used for commenting. A line ending with a backslash will be concatenated with the following one, allowing multiline variable definitions. The parser strips leading and trailing whitespace from the values of assignments, unless you use double quotes ("). The argument passed should be an absolute filename or wildcard expression, optionally prefixed with -, which indicates that if the file does not exist, it will not be read and no error or warning message is logged. This option may be specified more than once in which case all specified files are read. If the empty string is assigned to this option, the list of file to read is reset, all prior assignments have no effect. The files listed with this directive will be read shortly before the process is executed (more specifically, after all processes from a previous unit state terminated. This means you can generate these files in one unit state, and read it with this option in the next). Settings from these files override settings made with Environment=. If the same variable is set twice from these files, the files will be read in the order they are specified and the later setting will override the earlier setting. PassEnvironment= Pass environment variables from the systemd system manager to executed processes. Takes a space-separated list of variable names. This option may be specified more than once, in which case all listed variables will be set. If the empty string is assigned to this option, the list of environment variables is reset, all prior assignments have no effect. Variables that are not set in the system manager will not be passed and will be silently ignored. Variables passed from this setting are overridden by those passed from Environment= or EnvironmentFile=. Example: PassEnvironment=VAR1 VAR2 VAR3 passes three variables VAR1, VAR2, VAR3 with the values set for those variables in PID1. See environ7 for details about environment variables. StandardInput= Controls where file descriptor 0 (STDIN) of the executed processes is connected to. Takes one of , , , or . If is selected, standard input will be connected to /dev/null, i.e. all read attempts by the process will result in immediate EOF. If is selected, standard input is connected to a TTY (as configured by TTYPath=, see below) and the executed process becomes the controlling process of the terminal. If the terminal is already being controlled by another process, the executed process waits until the current controlling process releases the terminal. is similar to , but the executed process is forcefully and immediately made the controlling process of the terminal, potentially removing previous controlling processes from the terminal. is similar to but if the terminal already has a controlling process start-up of the executed process fails. The option is only valid in socket-activated services, and only when the socket configuration file (see systemd.socket5 for details) specifies a single socket only. If this option is set, standard input will be connected to the socket the service was activated from, which is primarily useful for compatibility with daemons designed for use with the traditional inetd8 daemon. This setting defaults to . StandardOutput= Controls where file descriptor 1 (STDOUT) of the executed processes is connected to. Takes one of , , , , , , , , or . duplicates the file descriptor of standard input for standard output. connects standard output to /dev/null, i.e. everything written to it will be lost. connects standard output to a tty (as configured via TTYPath=, see below). If the TTY is used for output only, the executed process will not become the controlling process of the terminal, and will not fail or wait for other processes to release the terminal. connects standard output with the journal which is accessible via journalctl1. Note that everything that is written to syslog or kmsg (see below) is implicitly stored in the journal as well, the specific two options listed below are hence supersets of this one. connects standard output to the syslog3 system syslog service, in addition to the journal. Note that the journal daemon is usually configured to forward everything it receives to syslog anyway, in which case this option is no different from . connects standard output with the kernel log buffer which is accessible via dmesg1, in addition to the journal. The journal daemon might be configured to send all logs to kmsg anyway, in which case this option is no different from . , and work in a similar way as the three options above but copy the output to the system console as well. connects standard output to a socket acquired via socket activation. The semantics are similar to the same option of StandardInput=. This setting defaults to the value set with in systemd-system.conf5, which defaults to . Note that setting this parameter might result in additional dependencies to be added to the unit (see above). StandardError= Controls where file descriptor 2 (STDERR) of the executed processes is connected to. The available options are identical to those of StandardOutput=, with one exception: if set to the file descriptor used for standard output is duplicated for standard error. This setting defaults to the value set with in systemd-system.conf5, which defaults to . Note that setting this parameter might result in additional dependencies to be added to the unit (see above). TTYPath= Sets the terminal device node to use if standard input, output, or error are connected to a TTY (see above). Defaults to /dev/console. TTYReset= Reset the terminal device specified with TTYPath= before and after execution. Defaults to no. TTYVHangup= Disconnect all clients which have opened the terminal device specified with TTYPath= before and after execution. Defaults to no. TTYVTDisallocate= If the terminal device specified with TTYPath= is a virtual console terminal, try to deallocate the TTY before and after execution. This ensures that the screen and scrollback buffer is cleared. Defaults to no. SyslogIdentifier= Sets the process name to prefix log lines sent to the logging system or the kernel log buffer with. If not set, defaults to the process name of the executed process. This option is only useful when StandardOutput= or StandardError= are set to , or (or to the same settings in combination with ). SyslogFacility= Sets the syslog facility to use when logging to syslog. One of , , , , , , , , , , , , , , , , , , or . See syslog3 for details. This option is only useful when StandardOutput= or StandardError= are set to . Defaults to . SyslogLevel= The default syslog level to use when logging to syslog or the kernel log buffer. One of , , , , , , , . See syslog3 for details. This option is only useful when StandardOutput= or StandardError= are set to or . Note that individual lines output by the daemon might be prefixed with a different log level which can be used to override the default log level specified here. The interpretation of these prefixes may be disabled with SyslogLevelPrefix=, see below. For details, see sd-daemon3. Defaults to . SyslogLevelPrefix= Takes a boolean argument. If true and StandardOutput= or StandardError= are set to , or , log lines written by the executed process that are prefixed with a log level will be passed on to syslog with this log level set but the prefix removed. If set to false, the interpretation of these prefixes is disabled and the logged lines are passed on as-is. For details about this prefixing see sd-daemon3. Defaults to true. TimerSlackNSec= Sets the timer slack in nanoseconds for the executed processes. The timer slack controls the accuracy of wake-ups triggered by timers. See prctl2 for more information. Note that in contrast to most other time span definitions this parameter takes an integer value in nano-seconds if no unit is specified. The usual time units are understood too. LimitCPU= LimitFSIZE= LimitDATA= LimitSTACK= LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC= LimitMEMLOCK= LimitLOCKS= LimitSIGPENDING= LimitMSGQUEUE= LimitNICE= LimitRTPRIO= LimitRTTIME= These settings set both soft and hard limits of various resources for executed processes. See setrlimit2 for details. The resource limit is possible to specify in two formats, to set soft and hard limits to the same value, or to set both limits individually (e.g. LimitAS=4G:16G). Use the string infinity to configure no limit on a specific resource. The multiplicative suffixes K (=1024), M (=1024*1024) and so on for G, T, P and E may be used for resource limits measured in bytes (e.g. LimitAS=16G). For the limits referring to time values, the usual time units ms, s, min, h and so on may be used (see systemd.time7 for details). Note that if no time unit is specified for LimitCPU= the default unit of seconds is implied, while for LimitRTTIME= the default unit of microseconds is implied. Also, note that the effective granularity of the limits might influence their enforcement. For example, time limits specified for LimitCPU= will be rounded up implicitly to multiples of 1s. Note that most process resource limits configured with these options are per-process, and processes may fork in order to acquire a new set of resources that are accounted independently of the original process, and may thus escape limits set. Also note that LimitRSS= is not implemented on Linux, and setting it has no effect. Often it is advisable to prefer the resource controls listed in systemd.resource-control5 over these per-process limits, as they apply to services as a whole, may be altered dynamically at runtime, and are generally more expressive. For example, MemoryLimit= is a more powerful (and working) replacement for LimitRSS=. Limit directives and their equivalent with ulimit Directive ulimit equivalent Unit LimitCPU= ulimit -t Seconds LimitFSIZE= ulimit -f Bytes LimitDATA= ulimit -d Bytes LimitSTACK= ulimit -s Bytes LimitCORE= ulimit -c Bytes LimitRSS= ulimit -m Bytes LimitNOFILE= ulimit -n Number of File Descriptors LimitAS= ulimit -v Bytes LimitNPROC= ulimit -u Number of Processes LimitMEMLOCK= ulimit -l Bytes LimitLOCKS= ulimit -x Number of Locks LimitSIGPENDING= ulimit -i Number of Queued Signals LimitMSGQUEUE= ulimit -q Bytes LimitNICE= ulimit -e Nice Level LimitRTPRIO= ulimit -r Realtime Priority LimitRTTIME= No equivalent Microseconds
PAMName= Sets the PAM service name to set up a session as. If set, the executed process will be registered as a PAM session under the specified service name. This is only useful in conjunction with the User= setting. If not set, no PAM session will be opened for the executed processes. See pam8 for details. CapabilityBoundingSet= Controls which capabilities to include in the capability bounding set for the executed process. See capabilities7 for details. Takes a whitespace-separated list of capability names as read by cap_from_name3, e.g. CAP_SYS_ADMIN, CAP_DAC_OVERRIDE, CAP_SYS_PTRACE. Capabilities listed will be included in the bounding set, all others are removed. If the list of capabilities is prefixed with ~, all but the listed capabilities will be included, the effect of the assignment inverted. Note that this option also affects the respective capabilities in the effective, permitted and inheritable capability sets, on top of what Capabilities= does. If this option is not used, the capability bounding set is not modified on process execution, hence no limits on the capabilities of the process are enforced. This option may appear more than once, in which case the bounding sets are merged. If the empty string is assigned to this option, the bounding set is reset to the empty capability set, and all prior settings have no effect. If set to ~ (without any further argument), the bounding set is reset to the full set of available capabilities, also undoing any previous settings. AmbientCapabilities= Controls which capabilities to include in the ambient capability set for the executed process. Takes a whitespace-separated list of capability names as read by cap_from_name3, e.g. CAP_SYS_ADMIN, CAP_DAC_OVERRIDE, CAP_SYS_PTRACE. This option may appear more than once in which case the ambient capability sets are merged. If the list of capabilities is prefixed with ~, all but the listed capabilities will be included, the effect of the assignment inverted. If the empty string is assigned to this option, the ambient capability set is reset to the empty capability set, and all prior settings have no effect. If set to ~ (without any further argument), the ambient capability set is reset to the full set of available capabilities, also undoing any previous settings. Note that adding capabilities to ambient capability set adds them to the process's inherited capability set. Ambient capability sets are useful if you want to execute a process as a non-privileged user but still want to give it some capabilities. Note that in this case option keep-caps is automatically added to SecureBits= to retain the capabilities over the user change. SecureBits= Controls the secure bits set for the executed process. Takes a space-separated combination of options from the following list: , , , , , and . This option may appear more than once, in which case the secure bits are ORed. If the empty string is assigned to this option, the bits are reset to 0. See capabilities7 for details. Capabilities= Controls the capabilities7 set for the executed process. Take a capability string describing the effective, permitted and inherited capability sets as documented in cap_from_text3. Note that these capability sets are usually influenced (and filtered) by the capabilities attached to the executed file. Due to that CapabilityBoundingSet= is probably a much more useful setting. ReadWriteDirectories= ReadOnlyDirectories= InaccessibleDirectories= Sets up a new file system namespace for executed processes. These options may be used to limit access a process might have to the main file system hierarchy. Each setting takes a space-separated list of absolute directory paths. Directories listed in ReadWriteDirectories= are accessible from within the namespace with the same access rights as from outside. Directories listed in ReadOnlyDirectories= are accessible for reading only, writing will be refused even if the usual file access controls would permit this. Directories listed in InaccessibleDirectories= will be made inaccessible for processes inside the namespace. Note that restricting access with these options does not extend to submounts of a directory that are created later on. These options may be specified more than once, in which case all directories listed will have limited access from within the namespace. If the empty string is assigned to this option, the specific list is reset, and all prior assignments have no effect. Paths in ReadOnlyDirectories= and InaccessibleDirectories= may be prefixed with -, in which case they will be ignored when they do not exist. Note that using this setting will disconnect propagation of mounts from the service to the host (propagation in the opposite direction continues to work). This means that this setting may not be used for services which shall be able to install mount points in the main mount namespace. PrivateTmp= Takes a boolean argument. If true, sets up a new file system namespace for the executed processes and mounts private /tmp and /var/tmp directories inside it that is not shared by processes outside of the namespace. This is useful to secure access to temporary files of the process, but makes sharing between processes via /tmp or /var/tmp impossible. If this is enabled, all temporary files created by a service in these directories will be removed after the service is stopped. Defaults to false. It is possible to run two or more units within the same private /tmp and /var/tmp namespace by using the JoinsNamespaceOf= directive, see systemd.unit5 for details. Note that using this setting will disconnect propagation of mounts from the service to the host (propagation in the opposite direction continues to work). This means that this setting may not be used for services which shall be able to install mount points in the main mount namespace. PrivateDevices= Takes a boolean argument. If true, sets up a new /dev namespace for the executed processes and only adds API pseudo devices such as /dev/null, /dev/zero or /dev/random (as well as the pseudo TTY subsystem) to it, but no physical devices such as /dev/sda. This is useful to securely turn off physical device access by the executed process. Defaults to false. Enabling this option will also remove CAP_MKNOD from the capability bounding set for the unit (see above), and set DevicePolicy=closed (see systemd.resource-control5 for details). Note that using this setting will disconnect propagation of mounts from the service to the host (propagation in the opposite direction continues to work). This means that this setting may not be used for services which shall be able to install mount points in the main mount namespace. PrivateNetwork= Takes a boolean argument. If true, sets up a new network namespace for the executed processes and configures only the loopback network device lo inside it. No other network devices will be available to the executed process. This is useful to securely turn off network access by the executed process. Defaults to false. It is possible to run two or more units within the same private network namespace by using the JoinsNamespaceOf= directive, see systemd.unit5 for details. Note that this option will disconnect all socket families from the host, this includes AF_NETLINK and AF_UNIX. The latter has the effect that AF_UNIX sockets in the abstract socket namespace will become unavailable to the processes (however, those located in the file system will continue to be accessible). ProtectSystem= Takes a boolean argument or full. If true, mounts the /usr and /boot directories read-only for processes invoked by this unit. If set to full, the /etc directory is mounted read-only, too. This setting ensures that any modification of the vendor-supplied operating system (and optionally its configuration) is prohibited for the service. It is recommended to enable this setting for all long-running services, unless they are involved with system updates or need to modify the operating system in other ways. Note however that processes retaining the CAP_SYS_ADMIN capability can undo the effect of this setting. This setting is hence particularly useful for daemons which have this capability removed, for example with CapabilityBoundingSet=. Defaults to off. ProtectHome= Takes a boolean argument or read-only. If true, the directories /home, /root and /run/user are made inaccessible and empty for processes invoked by this unit. If set to read-only, the three directories are made read-only instead. It is recommended to enable this setting for all long-running services (in particular network-facing ones), to ensure they cannot get access to private user data, unless the services actually require access to the user's private data. Note however that processes retaining the CAP_SYS_ADMIN capability can undo the effect of this setting. This setting is hence particularly useful for daemons which have this capability removed, for example with CapabilityBoundingSet=. Defaults to off. MountFlags= Takes a mount propagation flag: , or , which control whether mounts in the file system namespace set up for this unit's processes will receive or propagate mounts or unmounts. See mount2 for details. Defaults to . Use to ensure that mounts and unmounts are propagated from the host to the container and vice versa. Use to run processes so that none of their mounts and unmounts will propagate to the host. Use to also ensure that no mounts and unmounts from the host will propagate into the unit processes' namespace. Note that means that file systems mounted on the host might stay mounted continuously in the unit's namespace, and thus keep the device busy. Note that the file system namespace related options (PrivateTmp=, PrivateDevices=, ProtectSystem=, ProtectHome=, ReadOnlyDirectories=, InaccessibleDirectories= and ReadWriteDirectories=) require that mount and unmount propagation from the unit's file system namespace is disabled, and hence downgrade to . UtmpIdentifier= Takes a four character identifier string for an utmp5 and wtmp entry for this service. This should only be set for services such as getty implementations (such as agetty8) where utmp/wtmp entries must be created and cleared before and after execution, or for services that shall be executed as if they were run by a getty process (see below). If the configured string is longer than four characters, it is truncated and the terminal four characters are used. This setting interprets %I style string replacements. This setting is unset by default, i.e. no utmp/wtmp entries are created or cleaned up for this service. UtmpMode= Takes one of init, login or user. If UtmpIdentifier= is set, controls which type of utmp5/wtmp entries for this service are generated. This setting has no effect unless UtmpIdentifier= is set too. If init is set, only an INIT_PROCESS entry is generated and the invoked process must implement a getty-compatible utmp/wtmp logic. If login is set, first an INIT_PROCESS entry, followed by a LOGIN_PROCESS entry is generated. In this case, the invoked process must implement a login1-compatible utmp/wtmp logic. If user is set, first an INIT_PROCESS entry, then a LOGIN_PROCESS entry and finally a USER_PROCESS entry is generated. In this case, the invoked process may be any process that is suitable to be run as session leader. Defaults to init. SELinuxContext= Set the SELinux security context of the executed process. If set, this will override the automated domain transition. However, the policy still needs to authorize the transition. This directive is ignored if SELinux is disabled. If prefixed by -, all errors will be ignored. See setexeccon3 for details. AppArmorProfile= Takes a profile name as argument. The process executed by the unit will switch to this profile when started. Profiles must already be loaded in the kernel, or the unit will fail. This result in a non operation if AppArmor is not enabled. If prefixed by -, all errors will be ignored. SmackProcessLabel= Takes a security label as argument. The process executed by the unit will be started under this label and SMACK will decide whether the process is allowed to run or not, based on it. The process will continue to run under the label specified here unless the executable has its own label, in which case the process will transition to run under that label. When not specified, the label that systemd is running under is used. This directive is ignored if SMACK is disabled. The value may be prefixed by -, in which case all errors will be ignored. An empty value may be specified to unset previous assignments. IgnoreSIGPIPE= Takes a boolean argument. If true, causes SIGPIPE to be ignored in the executed process. Defaults to true because SIGPIPE generally is useful only in shell pipelines. NoNewPrivileges= Takes a boolean argument. If true, ensures that the service process and all its children can never gain new privileges. This option is more powerful than the respective secure bits flags (see above), as it also prohibits UID changes of any kind. This is the simplest, most effective way to ensure that a process and its children can never elevate privileges again. SystemCallFilter= Takes a space-separated list of system call names. If this setting is used, all system calls executed by the unit processes except for the listed ones will result in immediate process termination with the SIGSYS signal (whitelisting). If the first character of the list is ~, the effect is inverted: only the listed system calls will result in immediate process termination (blacklisting). If running in user mode and this option is used, NoNewPrivileges=yes is implied. This feature makes use of the Secure Computing Mode 2 interfaces of the kernel ('seccomp filtering') and is useful for enforcing a minimal sandboxing environment. Note that the execve, rt_sigreturn, sigreturn, exit_group, exit system calls are implicitly whitelisted and do not need to be listed explicitly. This option may be specified more than once, in which case the filter masks are merged. If the empty string is assigned, the filter is reset, all prior assignments will have no effect. If you specify both types of this option (i.e. whitelisting and blacklisting), the first encountered will take precedence and will dictate the default action (termination or approval of a system call). Then the next occurrences of this option will add or delete the listed system calls from the set of the filtered system calls, depending of its type and the default action. (For example, if you have started with a whitelisting of read and write, and right after it add a blacklisting of write, then write will be removed from the set.) SystemCallErrorNumber= Takes an errno error number name to return when the system call filter configured with SystemCallFilter= is triggered, instead of terminating the process immediately. Takes an error name such as EPERM, EACCES or EUCLEAN. When this setting is not used, or when the empty string is assigned, the process will be terminated immediately when the filter is triggered. SystemCallArchitectures= Takes a space-separated list of architecture identifiers to include in the system call filter. The known architecture identifiers are x86, x86-64, x32, arm as well as the special identifier native. Only system calls of the specified architectures will be permitted to processes of this unit. This is an effective way to disable compatibility with non-native architectures for processes, for example to prohibit execution of 32-bit x86 binaries on 64-bit x86-64 systems. The special native identifier implicitly maps to the native architecture of the system (or more strictly: to the architecture the system manager is compiled for). If running in user mode and this option is used, NoNewPrivileges=yes is implied. Note that setting this option to a non-empty list implies that native is included too. By default, this option is set to the empty list, i.e. no architecture system call filtering is applied. RestrictAddressFamilies= Restricts the set of socket address families accessible to the processes of this unit. Takes a space-separated list of address family names to whitelist, such as AF_UNIX, AF_INET or AF_INET6. When prefixed with ~ the listed address families will be applied as blacklist, otherwise as whitelist. Note that this restricts access to the socket2 system call only. Sockets passed into the process by other means (for example, by using socket activation with socket units, see systemd.socket5) are unaffected. Also, sockets created with socketpair() (which creates connected AF_UNIX sockets only) are unaffected. Note that this option has no effect on 32-bit x86 and is ignored (but works correctly on x86-64). If running in user mode and this option is used, NoNewPrivileges=yes is implied. By default, no restriction applies, all address families are accessible to processes. If assigned the empty string, any previous list changes are undone. Use this option to limit exposure of processes to remote systems, in particular via exotic network protocols. Note that in most cases, the local AF_UNIX address family should be included in the configured whitelist as it is frequently used for local communication, including for syslog2 logging. Personality= Controls which kernel architecture uname2 shall report, when invoked by unit processes. Takes one of x86 and x86-64. This is useful when running 32-bit services on a 64-bit host system. If not specified, the personality is left unmodified and thus reflects the personality of the host system's kernel. RuntimeDirectory= RuntimeDirectoryMode= Takes a list of directory names. If set, one or more directories by the specified names will be created below /run (for system services) or below $XDG_RUNTIME_DIR (for user services) when the unit is started, and removed when the unit is stopped. The directories will have the access mode specified in RuntimeDirectoryMode=, and will be owned by the user and group specified in User= and Group=. Use this to manage one or more runtime directories of the unit and bind their lifetime to the daemon runtime. The specified directory names must be relative, and may not include a /, i.e. must refer to simple directories to create or remove. This is particularly useful for unprivileged daemons that cannot create runtime directories in /run due to lack of privileges, and to make sure the runtime directory is cleaned up automatically after use. For runtime directories that require more complex or different configuration or lifetime guarantees, please consider using tmpfiles.d5.
Environment variables in spawned processes Processes started by the system are executed in a clean environment in which select variables listed below are set. System processes started by systemd do not inherit variables from PID 1, but processes started by user systemd instances inherit all environment variables from the user systemd instance. $PATH Colon-separated list of directories to use when launching executables. Systemd uses a fixed value of /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin. $LANG Locale. Can be set in locale.conf5 or on the kernel command line (see systemd1 and kernel-command-line7). $USER $LOGNAME $HOME $SHELL User name (twice), home directory, and the login shell. The variables are set for the units that have User= set, which includes user systemd instances. See passwd5. $XDG_RUNTIME_DIR The directory for volatile state. Set for the user systemd instance, and also in user sessions. See pam_systemd8. $XDG_SESSION_ID $XDG_SEAT $XDG_VTNR The identifier of the session, the seat name, and virtual terminal of the session. Set by pam_systemd8 for login sessions. $XDG_SEAT and $XDG_VTNR will only be set when attached to a seat and a tty. $MAINPID The PID of the units main process if it is known. This is only set for control processes as invoked by ExecReload= and similar. $MANAGERPID The PID of the user systemd instance, set for processes spawned by it. $LISTEN_FDS $LISTEN_PID $LISTEN_FDNAMES Information about file descriptors passed to a service for socket activation. See sd_listen_fds3. $NOTIFY_SOCKET The socket sd_notify() talks to. See sd_notify3. $WATCHDOG_PID $WATCHDOG_USEC Information about watchdog keep-alive notifications. See sd_watchdog_enabled3. $TERM Terminal type, set only for units connected to a terminal (StandardInput=tty, StandardOutput=tty, or StandardError=tty). See termcap5. Additional variables may be configured by the following means: for processes spawned in specific units, use the Environment=, EnvironmentFile= and PassEnvironment= options above; to specify variables globally, use DefaultEnvironment= (see systemd-system.conf5) or the kernel option systemd.setenv= (see systemd1). Additional variables may also be set through PAM, cf. pam_env8. See Also systemd1, systemctl1, journalctl8, systemd.unit5, systemd.service5, systemd.socket5, systemd.swap5, systemd.mount5, systemd.kill5, systemd.resource-control5, systemd.time7, systemd.directives7, tmpfiles.d5, exec3
systemd-229/man/systemd.generator.xml000066400000000000000000000347001265713322000200370ustar00rootroot00000000000000 %entities; ]> systemd.generator systemd Developer Lennart Poettering lennart@poettering.net systemd.generator 7 systemd.generator Systemd unit generators /path/to/generator normal-dir early-dir late-dir /run/systemd/system-generators/* /etc/systemd/system-generators/* /usr/local/lib/systemd/system-generators/* &systemgeneratordir;/* /run/systemd/user-generators/* /etc/systemd/user-generators/* /usr/local/lib/systemd/user-generators/* &usergeneratordir;/* Description Generators are small binaries that live in &usergeneratordir;/ and other directories listed above. systemd1 will execute those binaries very early at bootup and at configuration reload time — before unit files are loaded. Generators can dynamically generate unit files or create symbolic links to unit files to add additional dependencies, thus extending or overriding existing definitions. Their main purpose is to convert configuration files that are not native unit files dynamically into native unit files. Generators are loaded from a set of paths determined during compilation, as listed above. System and user generators are loaded from directories with names ending in system-generators/ and user-generators/, respectively. Generators found in directories listed earlier override the ones with the same name in directories lower in the list. A symlink to /dev/null or an empty file can be used to mask a generator, thereby preventing it from running. Please note that the order of the two directories with the highest priority is reversed with respect to the unit load path, and generators in /run overwrite those in /etc. After installing new generators or updating the configuration, systemctl daemon-reload may be executed. This will delete the previous configuration created by generators, re-run all generators, and cause systemd to reload units from disk. See systemctl1 for more information. Writing generators Generators are invoked with three arguments: paths to runtime directories where generators can place their generated unit files or symlinks. normal-dir argv[1] may be used to override unit files in /usr, but not those in /etc. This means that unit files placed in this directory take precedence over vendor unit configuration but not over native user/administrator unit configuration. early-dir argv[2] may be used to override unit files in /usr and in /etc. This means that unit files placed in this directory take precedence over all configuration, both vendor and user/administrator. late-dir argv[3] may be used to extend the unit file tree without overriding any other unit files. Any native configuration files supplied by the vendor or user/administrator take precedence over the generated ones placed in this directory. Notes All generators are executed in parallel. That means all executables are started at the very same time and need to be able to cope with this parallelism. Generators are run very early at boot and cannot rely on any external services. They may not talk to any other process. That includes simple things such as logging to syslog3, or systemd itself (this means: no systemctl1)!. Non-essential file systems like /var and /home are mounted after generators have run. Generators can however rely on the most basic kernel functionality to be available, including a mounted /sys, /proc, /dev, /usr. Units written by generators are removed when the configuration is reloaded. That means the lifetime of the generated units is closely bound to the reload cycles of systemd itself. Generators should only be used to generate unit files, not any other kind of configuration. Due to the lifecycle logic mentioned above, generators are not a good fit to generate dynamic configuration for other services. If you need to generate dynamic configuration for other services, do so in normal services you order before the service in question. Since syslog3 is not available (see above), log messages have to be written to /dev/kmsg instead. It is a good idea to use the SourcePath= directive in generated unit files to specify the source configuration file you are generating the unit from. This makes things more easily understood by the user and also has the benefit that systemd can warn the user about configuration files that changed on disk but have not been read yet by systemd. Generators may write out dynamic unit files or just hook unit files into other units with the usual .wants/ or .requires/ symlinks. Often, it is nicer to simply instantiate a template unit file from /usr with a generator instead of writing out entirely dynamic unit files. Of course, this works only if a single parameter is to be used. If you are careful, you can implement generators in shell scripts. We do recommend C code however, since generators are executed synchronously and hence delay the entire boot if they are slow. Regarding overriding semantics: there are two rules we try to follow when thinking about the overriding semantics: User configuration should override vendor configuration. This (mostly) means that stuff from /etc should override stuff from /usr. Native configuration should override non-native configuration. This (mostly) means that stuff you generate should never override native unit files for the same purpose. Of these two rules the first rule is probably the more important one and breaks the second one sometimes. Hence, when deciding whether to user argv[1], argv[2], or argv[3], your default choice should probably be argv[1]. Instead of heading off now and writing all kind of generators for legacy configuration file formats, please think twice! It is often a better idea to just deprecate old stuff instead of keeping it artificially alive. Examples systemd-fstab-generator systemd-fstab-generator8 converts /etc/fstab into native mount units. It uses argv[1] as location to place the generated unit files in order to allow the user to override /etc/fstab with her own native unit files, but also to ensure that /etc/fstab overrides any vendor default from /usr. After editing /etc/fstab, the user should invoke systemctl daemon-reload. This will re-run all generators and cause systemd to reload units from disk. To actually mount new directories added to fstab, systemctl start /path/to/mountpoint or systemctl start local-fs.target may be used. systemd-system-update-generator systemd-system-update-generator8 temporarily redirects default.target to system-update.target if a system update is scheduled. Since this needs to override the default user configuration for default.target, it uses argv[2]. For details about this logic, see Implementing Offline System Updates. Debugging a generator dir=$(mktemp -d) SYSTEMD_LOG_LEVEL=debug &systemgeneratordir;/systemd-fstab-generator \ "$dir" "$dir" "$dir" find $dir See also systemd1, systemd-cryptsetup-generator8, systemd-debug-generator8, systemd-fstab-generator8, fstab5, systemd-getty-generator8, systemd-gpt-auto-generator8, systemd-hibernate-resume-generator8, systemd-system-update-generator8, systemd-sysv-generator8, systemd.unit5, systemctl1 systemd-229/man/systemd.journal-fields.xml000066400000000000000000000461531265713322000207740ustar00rootroot00000000000000 systemd.journal-fields systemd Developer Lennart Poettering lennart@poettering.net systemd.journal-fields 7 systemd.journal-fields Special journal fields Description Entries in the journal resemble an environment block in their syntax but with fields that can include binary data. Primarily, fields are formatted UTF-8 text strings, and binary formatting is used only where formatting as UTF-8 text strings makes little sense. New fields may freely be defined by applications, but a few fields have special meaning. All fields with special meanings are optional. In some cases, fields may appear more than once per entry. User Journal Fields User fields are fields that are directly passed from clients and stored in the journal. MESSAGE= The human-readable message string for this entry. This is supposed to be the primary text shown to the user. It is usually not translated (but might be in some cases), and is not supposed to be parsed for metadata. MESSAGE_ID= A 128-bit message identifier ID for recognizing certain message types, if this is desirable. This should contain a 128-bit ID formatted as a lower-case hexadecimal string, without any separating dashes or suchlike. This is recommended to be a UUID-compatible ID, but this is not enforced, and formatted differently. Developers can generate a new ID for this purpose with journalctl . PRIORITY= A priority value between 0 (emerg) and 7 (debug) formatted as a decimal string. This field is compatible with syslog's priority concept. CODE_FILE= CODE_LINE= CODE_FUNC= The code location generating this message, if known. Contains the source filename, the line number and the function name. ERRNO= The low-level Unix error number causing this entry, if any. Contains the numeric value of errno3 formatted as a decimal string. SYSLOG_FACILITY= SYSLOG_IDENTIFIER= SYSLOG_PID= Syslog compatibility fields containing the facility (formatted as decimal string), the identifier string (i.e. "tag"), and the client PID. (Note that the tag is usually derived from glibc's program_invocation_short_name variable, see program_invocation_short_name3.) Trusted Journal Fields Fields prefixed with an underscore are trusted fields, i.e. fields that are implicitly added by the journal and cannot be altered by client code. _PID= _UID= _GID= The process, user, and group ID of the process the journal entry originates from formatted as a decimal string. _COMM= _EXE= _CMDLINE= The name, the executable path, and the command line of the process the journal entry originates from. _CAP_EFFECTIVE= The effective capabilities7 of the process the journal entry originates from. _AUDIT_SESSION= _AUDIT_LOGINUID= The session and login UID of the process the journal entry originates from, as maintained by the kernel audit subsystem. _SYSTEMD_CGROUP= _SYSTEMD_SESSION= _SYSTEMD_UNIT= _SYSTEMD_USER_UNIT= _SYSTEMD_OWNER_UID= _SYSTEMD_SLICE= The control group path in the systemd hierarchy, the systemd session ID (if any), the systemd unit name (if any), the systemd user session unit name (if any), the owner UID of the systemd session (if any) and the systemd slice unit of the process the journal entry originates from. _SELINUX_CONTEXT= The SELinux security context (label) of the process the journal entry originates from. _SOURCE_REALTIME_TIMESTAMP= The earliest trusted timestamp of the message, if any is known that is different from the reception time of the journal. This is the time in microseconds since the epoch UTC, formatted as a decimal string. _BOOT_ID= The kernel boot ID for the boot the message was generated in, formatted as a 128-bit hexadecimal string. _MACHINE_ID= The machine ID of the originating host, as available in machine-id5. _HOSTNAME= The name of the originating host. _TRANSPORT= How the entry was received by the journal service. Valid transports are: for those read from the kernel audit subsystem for internally generated messages for those received via the local syslog socket with the syslog protocol for those received via the native journal protocol for those read from a service's standard output or error output for those read from the kernel Kernel Journal Fields Kernel fields are fields that are used by messages originating in the kernel and stored in the journal. _KERNEL_DEVICE= The kernel device name. If the entry is associated to a block device, the major and minor of the device node, separated by : and prefixed by b. Similar for character devices but prefixed by c. For network devices, this is the interface index prefixed by n. For all other devices, this is the subsystem name prefixed by +, followed by :, followed by the kernel device name. _KERNEL_SUBSYSTEM= The kernel subsystem name. _UDEV_SYSNAME= The kernel device name as it shows up in the device tree below /sys. _UDEV_DEVNODE= The device node path of this device in /dev. _UDEV_DEVLINK= Additional symlink names pointing to the device node in /dev. This field is frequently set more than once per entry. Fields to log on behalf of a different program Fields in this section are used by programs to specify that they are logging on behalf of another program or unit. Fields used by the systemd-coredump coredump kernel helper: COREDUMP_UNIT= COREDUMP_USER_UNIT= Used to annotate messages containing coredumps from system and session units. See coredumpctl1. Privileged programs (currently UID 0) may attach OBJECT_PID= to a message. This will instruct systemd-journald to attach additional fields on behalf of the caller: OBJECT_PID=PID PID of the program that this message pertains to. OBJECT_UID= OBJECT_GID= OBJECT_COMM= OBJECT_EXE= OBJECT_CMDLINE= OBJECT_AUDIT_SESSION= OBJECT_AUDIT_LOGINUID= OBJECT_SYSTEMD_CGROUP= OBJECT_SYSTEMD_SESSION= OBJECT_SYSTEMD_OWNER_UID= OBJECT_SYSTEMD_UNIT= OBJECT_SYSTEMD_USER_UNIT= These are additional fields added automatically by systemd-journald. Their meaning is the same as _UID=, _GID=, _COMM=, _EXE=, _CMDLINE=, _AUDIT_SESSION=, _AUDIT_LOGINUID=, _SYSTEMD_CGROUP=, _SYSTEMD_SESSION=, _SYSTEMD_UNIT=, _SYSTEMD_USER_UNIT=, and _SYSTEMD_OWNER_UID= as described above, except that the process identified by PID is described, instead of the process which logged the message. Address Fields During serialization into external formats, such as the Journal Export Format or the Journal JSON Format, the addresses of journal entries are serialized into fields prefixed with double underscores. Note that these are not proper fields when stored in the journal but for addressing metadata of entries. They cannot be written as part of structured log entries via calls such as sd_journal_send3. They may also not be used as matches for sd_journal_add_match3 __CURSOR= The cursor for the entry. A cursor is an opaque text string that uniquely describes the position of an entry in the journal and is portable across machines, platforms and journal files. __REALTIME_TIMESTAMP= The wallclock time (CLOCK_REALTIME) at the point in time the entry was received by the journal, in microseconds since the epoch UTC, formatted as a decimal string. This has different properties from _SOURCE_REALTIME_TIMESTAMP=, as it is usually a bit later but more likely to be monotonic. __MONOTONIC_TIMESTAMP= The monotonic time (CLOCK_MONOTONIC) at the point in time the entry was received by the journal in microseconds, formatted as a decimal string. To be useful as an address for the entry, this should be combined with the boot ID in _BOOT_ID=. See Also systemd1, journalctl1, journald.conf5, sd-journal3, coredumpctl1, systemd.directives7 systemd-229/man/systemd.kill.xml000066400000000000000000000206001265713322000167760ustar00rootroot00000000000000 systemd.kill systemd Developer Lennart Poettering lennart@poettering.net systemd.kill 5 systemd.kill Process killing procedure configuration service.service, socket.socket, mount.mount, swap.swap, scope.scope Description Unit configuration files for services, sockets, mount points, swap devices and scopes share a subset of configuration options which define the killing procedure of processes belonging to the unit. This man page lists the configuration options shared by these five unit types. See systemd.unit5 for the common options shared by all unit configuration files, and systemd.service5, systemd.socket5, systemd.swap5, systemd.mount5 and systemd.scope5 for more information on the configuration file options specific to each unit type. The kill procedure configuration options are configured in the [Service], [Socket], [Mount] or [Swap] section, depending on the unit type. Options KillMode= Specifies how processes of this unit shall be killed. One of , , , . If set to , all remaining processes in the control group of this unit will be killed on unit stop (for services: after the stop command is executed, as configured with ExecStop=). If set to , only the main process itself is killed. If set to , the SIGTERM signal (see below) is sent to the main process while the subsequent SIGKILL signal (see below) is sent to all remaining processes of the unit's control group. If set to , no process is killed. In this case, only the stop command will be executed on unit stop, but no process be killed otherwise. Processes remaining alive after stop are left in their control group and the control group continues to exist after stop unless it is empty. Processes will first be terminated via SIGTERM (unless the signal to send is changed via KillSignal=). Optionally, this is immediately followed by a SIGHUP (if enabled with SendSIGHUP=). If then, after a delay (configured via the TimeoutStopSec= option), processes still remain, the termination request is repeated with the SIGKILL signal (unless this is disabled via the SendSIGKILL= option). See kill2 for more information. Defaults to . KillSignal= Specifies which signal to use when killing a service. This controls the signal that is sent as first step of shutting down a unit (see above), and is usually followed by SIGKILL (see above and below). For a list of valid signals, see signal7. Defaults to SIGTERM. Note that, right after sending the signal specified in this setting, systemd will always send SIGCONT, to ensure that even suspended tasks can be terminated cleanly. SendSIGHUP= Specifies whether to send SIGHUP to remaining processes immediately after sending the signal configured with KillSignal=. This is useful to indicate to shells and shell-like programs that their connection has been severed. Takes a boolean value. Defaults to "no". SendSIGKILL= Specifies whether to send SIGKILL to remaining processes after a timeout, if the normal shutdown procedure left processes of the service around. Takes a boolean value. Defaults to "yes". See Also systemd1, systemctl1, journalctl8, systemd.unit5, systemd.service5, systemd.socket5, systemd.swap5, systemd.mount5, systemd.exec5, systemd.directives7, kill2, signal7 systemd-229/man/systemd.link.xml000066400000000000000000000422341265713322000170070ustar00rootroot00000000000000 systemd.link systemd Developer Tom Gundersen systemd.link 5 systemd.link Network device configuration link.link Description Network link configuration is performed by the net_setup_link udev builtin. The link files are read from the files located in the system network directory /usr/lib/systemd/network, the volatile runtime network directory /run/systemd/network, and the local administration network directory /etc/systemd/network. Link files must have the extension .link; other extensions are ignored. All link files are collectively sorted and processed in lexical order, regardless of the directories in which they live. However, files with identical filenames replace each other. Files in /etc have the highest priority, files in /run take precedence over files with the same name in /usr/lib. This can be used to override a system-supplied link file with a local file if needed. As a special case, an empty file (file size 0) or symlink with the same name pointing to /dev/null disables the configuration file entirely (it is "masked"). The link file contains a [Match] section, which determines if a given link file may be applied to a given device, as well as a [Link] section specifying how the device should be configured. The first (in lexical order) of the link files that matches a given device is applied. Note that a default file 99-default.link is shipped by the system, any user-supplied .link should hence have a lexically earlier name to be considered at all. [Match] Section Options A link file is said to match a device if each of the entries in the [Match] section matches, or if the section is empty. The following keys are accepted: MACAddress= The hardware address. OriginalName= A whitespace-separated list of shell-style globs matching the device name, as exposed by the udev property "INTERFACE". This can not be used to match on names that have already been changed from userspace. Caution is advised when matching on kernel-assigned names, as they are known to be unstable between reboots. Path= A whitespace-separated list of shell-style globs matching the persistent path, as exposed by the udev property ID_PATH. Driver= A whitespace-separated list of shell-style globs matching the driver currently bound to the device, as exposed by the udev property DRIVER of its parent device, or if that is not set, the driver as exposed by ethtool -i of the device itself. Type= A whitespace-separated list of shell-style globs matching the device type, as exposed by the udev property DEVTYPE. Host= Matches against the hostname or machine ID of the host. See ConditionHost= in systemd.unit5 for details. Virtualization= Checks whether the system is executed in a virtualized environment and optionally test whether it is a specific implementation. See ConditionVirtualization= in systemd.unit5 for details. KernelCommandLine= Checks whether a specific kernel command line option is set (or if prefixed with the exclamation mark unset). See ConditionKernelCommandLine= in systemd.unit5 for details. Architecture= Checks whether the system is running on a specific architecture. See ConditionArchitecture= in systemd.unit5 for details. [Link] Section Options The [Link] section accepts the following keys: Description= A description of the device. Alias= The ifalias is set to this value. MACAddressPolicy= The policy by which the MAC address should be set. The available policies are: persistent If the hardware has a persistent MAC address, as most hardware should, and if it is used by the kernel, nothing is done. Otherwise, a new MAC address is generated which is guaranteed to be the same on every boot for the given machine and the given device, but which is otherwise random. This feature depends on ID_NET_NAME_* properties to exist for the link. On hardware where these properties are not set, the generation of a persistent MAC address will fail. random If the kernel is using a random MAC address, nothing is done. Otherwise, a new address is randomly generated each time the device appears, typically at boot. Either way, the random address will have the unicast and locally administered bits set. none Keeps the MAC address assigned by the kernel. MACAddress= The MAC address to use, if no MACAddressPolicy= is specified. NamePolicy= An ordered, space-separated list of policies by which the interface name should be set. NamePolicy may be disabled by specifying net.ifnames=0 on the kernel command line. Each of the policies may fail, and the first successful one is used. The name is not set directly, but is exported to udev as the property ID_NET_NAME, which is, by default, used by a udev rule to set NAME. If the name has already been set by userspace, no renaming is performed. The available policies are: kernel If the kernel claims that the name it has set for a device is predictable, then no renaming is performed. database The name is set based on entries in the udev's Hardware Database with the key ID_NET_NAME_FROM_DATABASE. onboard The name is set based on information given by the firmware for on-board devices, as exported by the udev property ID_NET_NAME_ONBOARD. slot The name is set based on information given by the firmware for hot-plug devices, as exported by the udev property ID_NET_NAME_SLOT. path The name is set based on the device's physical location, as exported by the udev property ID_NET_NAME_PATH. mac The name is set based on the device's persistent MAC address, as exported by the udev property ID_NET_NAME_MAC. Name= The interface name to use in case all the policies specified in NamePolicy= fail, or in case NamePolicy= is missing or disabled. MTUBytes= The maximum transmission unit in bytes to set for the device. The usual suffixes K, M, G, are supported and are understood to the base of 1024. BitsPerSecond= The speed to set for the device, the value is rounded down to the nearest Mbps. The usual suffixes K, M, G, are supported and are understood to the base of 1000. Duplex= The duplex mode to set for the device. The accepted values are half and full. WakeOnLan= The Wake-on-LAN policy to set for the device. The supported values are: phy Wake on PHY activity. magic Wake on receipt of a magic packet. off Never wake. Examples /usr/lib/systemd/network/99-default.link The link file 99-default.link that is shipped with systemd defines the default naming policy for links. [Link] NamePolicy=kernel database onboard slot path MACAddressPolicy=persistent /etc/systemd/network/10-dmz.link This example assigns the fixed name dmz0 to the interface with the MAC address 00:a0:de:63:7a:e6: [Match] MACAddress=00:a0:de:63:7a:e6 [Link] Name=dmz0 /etc/systemd/network/10-internet.link This example assigns the fixed name internet0 to the interface with the device path pci-0000:00:1a.0-*: [Match] Path=pci-0000:00:1a.0-* [Link] Name=internet0 /etc/systemd/network/25-wireless.link Here's an overly complex example that shows the use of a large number of [Match] and [Link] settings. [Match] MACAddress=12:34:56:78:9a:bc Driver=brcmsmac Path=pci-0000:02:00.0-* Type=wlan Virtualization=no Host=my-laptop Architecture=x86-64 [Link] Name=wireless0 MTUBytes=1450 BitsPerSecond=10M WakeOnLan=magic MACAddress=cb:a9:87:65:43:21 See Also systemd-udevd.service8 , udevadm8 , systemd.netdev5 , systemd.network5 systemd-229/man/systemd.mount.xml000066400000000000000000000457121265713322000172200ustar00rootroot00000000000000 systemd.mount systemd Developer Lennart Poettering lennart@poettering.net systemd.mount 5 systemd.mount Mount unit configuration mount.mount Description A unit configuration file whose name ends in .mount encodes information about a file system mount point controlled and supervised by systemd. This man page lists the configuration options specific to this unit type. See systemd.unit5 for the common options of all unit configuration files. The common configuration items are configured in the generic [Unit] and [Install] sections. The mount specific configuration options are configured in the [Mount] section. Additional options are listed in systemd.exec5, which define the execution environment the mount8 binary is executed in, and in systemd.kill5, which define the way the processes are terminated, and in systemd.resource-control5, which configure resource control settings for the processes of the service. Note that the User= and Group= options are not particularly useful for mount units specifying a Type= option or using configuration not specified in /etc/fstab; mount8 will refuse options that are not listed in /etc/fstab if it is not run as UID 0. Mount units must be named after the mount point directories they control. Example: the mount point /home/lennart must be configured in a unit file home-lennart.mount. For details about the escaping logic used to convert a file system path to a unit name, see systemd.unit5. Note that mount units cannot be templated. Optionally, a mount unit may be accompanied by an automount unit, to allow on-demand or parallelized mounting. See systemd.automount5. Mount points created at runtime (independently of unit files or /etc/fstab) will be monitored by systemd and appear like any other mount unit in systemd. See /proc/self/mountinfo description in proc5. Some file systems have special semantics as API file systems for kernel-to-userspace and userspace-to-userspace interfaces. Some of them may not be changed via mount units, and cannot be disabled. For a longer discussion see API File Systems. Automatic Dependencies If a mount unit is beneath another mount unit in the file system hierarchy, both a requirement dependency and an ordering dependency between both units are created automatically. Block device backed file systems automatically gain BindsTo= and After= type dependencies on the device unit encapsulating the block device (see below). If traditional file system quota is enabled for a mount unit, automatic Wants= and Before= dependencies on systemd-quotacheck.service and quotaon.service are added. For mount units with DefaultDependencies=yes (the default) a couple additional dependencies are added. Mount units referring to local file systems automatically gain an After= dependency on local-fs-pre.target. Network mount units automatically acquire After= dependencies on remote-fs-pre.target, network.target and network-online.target. Towards the latter a Wants= unit is added as well. Mount units referring to local and network file systems are distinguished by their file system type specification. In some cases this is not sufficient (for example network block device based mounts, such as iSCSI), in which case may be added to the mount option string of the unit, which forces systemd to consider the mount unit a network mount. Mount units (regardless if local or network) also acquire automatic Before= and Conflicts= on umount.target in order to be stopped during shutdown. Additional implicit dependencies may be added as result of execution and resource control parameters as documented in systemd.exec5 and systemd.resource-control5. <filename>fstab</filename> Mount units may either be configured via unit files, or via /etc/fstab (see fstab5 for details). Mounts listed in /etc/fstab will be converted into native units dynamically at boot and when the configuration of the system manager is reloaded. In general, configuring mount points through /etc/fstab is the preferred approach. See systemd-fstab-generator8 for details about the conversion. When reading /etc/fstab a few special mount options are understood by systemd which influence how dependencies are created for mount points. systemd will create a dependency of type Wants= or (see option below), from either local-fs.target or remote-fs.target, depending whether the file system is local or remote. Configures a Requires= and an After= dependency between the created mount unit and another systemd unit, such as a device or mount unit. The argument should be a unit name, or an absolute path to a device node or mount point. This option may be specified more than once. This option is particularly useful for mount point declarations that need an additional device to be around (such as an external journal device for journal file systems) or an additional mount to be in place (such as an overlay file system that merges multiple mount points). See After= and Requires= in systemd.unit5 for details. Configures a RequiresMountsFor= dependency between the created mount unit and other mount units. The argument must be an absolute path. This option may be specified more than once. See RequiresMountsFor= in systemd.unit5 for details. An automount unit will be created for the file system. See systemd.automount5 for details. Configures the idle timeout of the automount unit. See TimeoutIdleSec= in systemd.automount5 for details. Configure how long systemd should wait for a device to show up before giving up on an entry from /etc/fstab. Specify a time in seconds or explicitly append a unit such as s, min, h, ms. Note that this option can only be used in /etc/fstab, and will be ignored when part of the Options= setting in a unit file. With , this mount will not be added as a dependency for local-fs.target or remote-fs.target. This means that it will not be mounted automatically during boot, unless it is pulled in by some other unit. The option has the opposite meaning and is the default. With , this mount will be only wanted, not required, by local-fs.target or remote-fs.target. This means that the boot will continue even if this mount point is not mounted successfully. An additional filesystem to be mounted in the initramfs. See initrd-fs.target description in systemd.special7. If a mount point is configured in both /etc/fstab and a unit file that is stored below /usr, the former will take precedence. If the unit file is stored below /etc, it will take precedence. This means: native unit files take precedence over traditional configuration files, but this is superseded by the rule that configuration in /etc will always take precedence over configuration in /usr. Options Mount files must include a [Mount] section, which carries information about the file system mount points it supervises. A number of options that may be used in this section are shared with other unit types. These options are documented in systemd.exec5 and systemd.kill5. The options specific to the [Mount] section of mount units are the following: What= Takes an absolute path of a device node, file or other resource to mount. See mount8 for details. If this refers to a device node, a dependency on the respective device unit is automatically created. (See systemd.device5 for more information.) This option is mandatory. Where= Takes an absolute path of a directory of the mount point. If the mount point does not exist at the time of mounting, it is created. This string must be reflected in the unit filename. (See above.) This option is mandatory. Type= Takes a string for the file system type. See mount8 for details. This setting is optional. Options= Mount options to use when mounting. This takes a comma-separated list of options. This setting is optional. SloppyOptions= Takes a boolean argument. If true, parsing of the options specified in Options= is relaxed, and unknown mount options are tolerated. This corresponds with mount8's -s switch. Defaults to off. DirectoryMode= Directories of mount points (and any parent directories) are automatically created if needed. This option specifies the file system access mode used when creating these directories. Takes an access mode in octal notation. Defaults to 0755. TimeoutSec= Configures the time to wait for the mount command to finish. If a command does not exit within the configured time, the mount will be considered failed and be shut down again. All commands still running will be terminated forcibly via SIGTERM, and after another delay of this time with SIGKILL. (See in systemd.kill5.) Takes a unit-less value in seconds, or a time span value such as "5min 20s". Pass 0 to disable the timeout logic. The default value is set from the manager configuration file's DefaultTimeoutStart= variable. Check systemd.exec5 and systemd.kill5 for more settings. See Also systemd1, systemctl1, systemd.unit5, systemd.exec5, systemd.kill5, systemd.resource-control5, systemd.service5, systemd.device5, proc5, mount8, systemd-fstab-generator8, systemd.directives7 systemd-229/man/systemd.netdev.xml000066400000000000000000001165641265713322000173470ustar00rootroot00000000000000 systemd.network systemd Developer Tom Gundersen teg@jklm.no systemd.netdev 5 systemd.netdev Virtual Network Device configuration netdev.netdev Description Network setup is performed by systemd-networkd8. Virtual Network Device files must have the extension .netdev; other extensions are ignored. Virtual network devices are created as soon as networkd is started. If a netdev with the specified name already exists, networkd will use that as-is rather than create its own. Note that the settings of the pre-existing netdev will not be changed by networkd. The .netdev files are read from the files located in the system network directory /usr/lib/systemd/network, the volatile runtime network directory /run/systemd/network and the local administration network directory /etc/systemd/network. All configuration files are collectively sorted and processed in lexical order, regardless of the directories in which they live. However, files with identical filenames replace each other. Files in /etc have the highest priority, files in /run take precedence over files with the same name in /usr/lib. This can be used to override a system-supplied configuration file with a local file if needed. As a special case, an empty file (file size 0) or symlink with the same name pointing to /dev/null disables the configuration file entirely (it is "masked"). Supported netdev kinds The following kinds of virtual network devices may be configured in .netdev files: Supported kinds of virtual network devices Kind Description bond A bond device is an aggregation of all its slave devices. See Linux Ethernet Bonding Driver HOWTO for details.Local configurationbridge A bridge device is a software switch, and each of its slave devices and the bridge itself are ports of the switch.dummy A dummy device drops all packets sent to it.gre A Level 3 GRE tunnel over IPv4. See RFC 2784 for details.gretap A Level 2 GRE tunnel over IPv4.ip6gre A Level 3 GRE tunnel over IPv6.ip6tnl An IPv4 or IPv6 tunnel over IPv6ip6gretap An Level 2 GRE tunnel over IPv6.ipip An IPv4 over IPv4 tunnel.ipvlan An ipvlan device is a stacked device which receives packets from its underlying device based on IP address filtering.macvlan A macvlan device is a stacked device which receives packets from its underlying device based on MAC address filtering.macvtap A macvtap device is a stacked device which receives packets from its underlying device based on MAC address filtering.sit An IPv6 over IPv4 tunnel.tap A persistent Level 2 tunnel between a network device and a device node.tun A persistent Level 3 tunnel between a network device and a device node.veth An Ethernet tunnel between a pair of network devices.vlan A VLAN is a stacked device which receives packets from its underlying device based on VLAN tagging. See IEEE 802.1Q for details.vti An IPv4 over IPSec tunnel.vti6 An IPv6 over IPSec tunnel.vxlan A virtual extensible LAN (vxlan), for connecting Cloud computing deployments.
[Match] Section Options A virtual network device is only created if the [Match] section matches the current environment, or if the section is empty. The following keys are accepted: Host= Matches against the hostname or machine ID of the host. See ConditionHost= in systemd.unit5 for details. Virtualization= Checks whether the system is executed in a virtualized environment and optionally test whether it is a specific implementation. See ConditionVirtualization= in systemd.unit5 for details. KernelCommandLine= Checks whether a specific kernel command line option is set (or if prefixed with the exclamation mark unset). See ConditionKernelCommandLine= in systemd.unit5 for details. Architecture= Checks whether the system is running on a specific architecture. See ConditionArchitecture= in systemd.unit5 for details. [NetDev] Section Options The [NetDev] section accepts the following keys: Description= A free-form description of the netdev. Name= The interface name used when creating the netdev. This option is compulsory. Kind= The netdev kind. This option is compulsory. See the Supported netdev kinds section for the valid keys. MTUBytes= The maximum transmission unit in bytes to set for the device. The usual suffixes K, M, G, are supported and are understood to the base of 1024. This key is not currently supported for tun or tap devices. MACAddress= The MAC address to use for the device. If none is given, one is generated based on the interface name and the machine-id5. This key is not currently supported for tun or tap devices. [Bridge] Section Options The [Bridge] section only applies for netdevs of kind bridge, and accepts the following keys: HelloTimeSec= HelloTimeSec specifies the number of seconds between two hello packets sent out by the root bridge and the designated bridges. Hello packets are used to communicate information about the topology throughout the entire bridged local area network. MaxAgeSec= MaxAgeSec specifies the number of seconds of maximum message age. If the last seen (received) hello packet is more than this number of seconds old, the bridge in question will start the takeover procedure in attempt to become the Root Bridge itself. ForwardDelaySec= ForwardDelaySec specifies the number of seconds spent in each of the Listening and Learning states before the Forwarding state is entered. [VLAN] Section Options The [VLAN] section only applies for netdevs of kind vlan, and accepts the following key: Id= The VLAN ID to use. An integer in the range 0–4094. This option is compulsory. [MACVLAN] Section Options The [MACVLAN] section only applies for netdevs of kind macvlan, and accepts the following key: Mode= The MACVLAN mode to use. The supported options are private, vepa, bridge, and passthru. [MACVTAP] Section Options The [MACVTAP] section applies for netdevs of kind macvtap and accepts the same key as [MACVLAN]. [IPVLAN] Section Options The [IPVLAN] section only applies for netdevs of kind ipvlan, and accepts the following key: Mode= The IPVLAN mode to use. The supported options are L2 and L3. [VXLAN] Section Options The [VXLAN] section only applies for netdevs of kind vxlan, and accepts the following keys: Id= The VXLAN ID to use. Group= An assigned multicast group IP address. TOS= The Type Of Service byte value for a vxlan interface. TTL= A fixed Time To Live N on Virtual eXtensible Local Area Network packets. N is a number in the range 1–255. 0 is a special value meaning that packets inherit the TTL value. MacLearning= A boolean. When true, enables dynamic MAC learning to discover remote MAC addresses. FDBAgeingSec= The lifetime of Forwarding Database entry learnt by the kernel, in seconds. MaximumFDBEntries= Configures maximum number of FDB entries. ARPProxy= A boolean. When true, enables ARP proxying. L2MissNotification= A boolean. When true, enables netlink LLADDR miss notifications. L3MissNotification= A boolean. When true, enables netlink IP address miss notifications. RouteShortCircuit= A boolean. When true, route short circuiting is turned on. UDPCheckSum= A boolean. When true, transmitting UDP checksums when doing VXLAN/IPv4 is turned on. UDP6ZeroChecksumTx= A boolean. When true, sending zero checksums in VXLAN/IPv6 is turned on. UDP6ZeroCheckSumRx= A boolean. When true, receiving zero checksums in VXLAN/IPv6 is turned on. GroupPolicyExtension= A boolean. When true, it enables Group Policy VXLAN extension security label mechanism across network peers based on VXLAN. For details about the Group Policy VXLAN, see the VXLAN Group Policy document. Defaults to false. DestinationPort= Configures the default destination UDP port on a per-device basis. If destination port is not specified then Linux kernel default will be used. Set destination port 4789 to get the IANA assigned value, and destination port 0 to get default values. PortRange= Configures VXLAN port range. VXLAN bases source UDP port based on flow to help the receiver to be able to load balance based on outer header flow. It restricts the port range to the normal UDP local ports, and allows overriding via configuration. [Tunnel] Section Options The [Tunnel] section only applies for netdevs of kind ipip, sit, gre, gretap, ip6gre, ip6gretap, vti, vti6, and ip6tnl and accepts the following keys: Local= A static local address for tunneled packets. It must be an address on another interface of this host. Remote= The remote endpoint of the tunnel. TOS= The Type Of Service byte value for a tunnel interface. For details about the TOS, see the Type of Service in the Internet Protocol Suite document. TTL= A fixed Time To Live N on tunneled packets. N is a number in the range 1–255. 0 is a special value meaning that packets inherit the TTL value. The default value for IPv4 tunnels is: inherit. The default value for IPv6 tunnels is 64. DiscoverPathMTU= A boolean. When true, enables Path MTU Discovery on the tunnel. IPv6FlowLabel= Configures the 20-bit flow label (see RFC 6437) field in the IPv6 header (see RFC 2460), which is used by a node to label packets of a flow. It is only used for IPv6 tunnels. A flow label of zero is used to indicate packets that have not been labeled. It can be configured to a value in the range 0–0xFFFFF, or be set to inherit, in which case the original flowlabel is used. CopyDSCP= A boolean. When true, the Differentiated Service Code Point (DSCP) field will be copied to the inner header from outer header during the decapsulation of an IPv6 tunnel packet. DSCP is a field in an IP packet that enables different levels of service to be assigned to network traffic. Defaults to no. EncapsulationLimit= The Tunnel Encapsulation Limit option specifies how many additional levels of encapsulation are permitted to be prepended to the packet. For example, a Tunnel Encapsulation Limit option containing a limit value of zero means that a packet carrying that option may not enter another tunnel before exiting the current tunnel. (see RFC 2473). The valid range is 0–255 and none. Defaults to 4. Mode= An ip6tnl tunnel can be in one of three modes ip6ip6 for IPv6 over IPv6, ipip6 for IPv4 over IPv6 or any for either. [Peer] Section Options The [Peer] section only applies for netdevs of kind veth and accepts the following keys: Name= The interface name used when creating the netdev. This option is compulsory. MACAddress= The peer MACAddress, if not set, it is generated in the same way as the MAC address of the main interface. [Tun] Section Options The [Tun] section only applies for netdevs of kind tun, and accepts the following keys: OneQueue= Takes a boolean argument. Configures whether all packets are queued at the device (enabled), or a fixed number of packets are queued at the device and the rest at the qdisc. Defaults to no. MultiQueue= Takes a boolean argument. Configures whether to use multiple file descriptors (queues) to parallelize packets sending and receiving. Defaults to no. PacketInfo= Takes a boolean argument. Configures whether packets should be prepended with four extra bytes (two flag bytes and two protocol bytes). If disabled, it indicates that the packets will be pure IP packets. Defaults to no. VNetHeader= Takes a boolean argument. Configures IFF_VNET_HDR flag for a tap device. It allows sending and receiving larger Generic Segmentation Offload (GSO) packets. This may increase throughput significantly. Defaults to no. User= User to grant access to the /dev/net/tun device. Group= Group to grant access to the /dev/net/tun device. [Tap] Section Options The [Tap] section only applies for netdevs of kind tap, and accepts the same keys as the [Tun] section. [Bond] Section Options The [Bond] section accepts the following key: Mode= Specifies one of the bonding policies. The default is balance-rr (round robin). Possible values are balance-rr, active-backup, balance-xor, broadcast, 802.3ad, balance-tlb, and balance-alb. TransmitHashPolicy= Selects the transmit hash policy to use for slave selection in balance-xor, 802.3ad, and tlb modes. Possible values are layer2, layer3+4, layer2+3, encap2+3, 802.3ad, and encap3+4. LACPTransmitRate= Specifies the rate with which link partner transmits Link Aggregation Control Protocol Data Unit packets in 802.3ad mode. Possible values are slow, which requests partner to transmit LACPDUs every 30 seconds, and fast, which requests partner to transmit LACPDUs every second. The default value is slow. MIIMonitorSec= Specifies the frequency that Media Independent Interface link monitoring will occur. A value of zero disables MII link monitoring. This value is rounded down to the nearest millisecond. The default value is 0. UpDelaySec= Specifies the delay before a link is enabled after a link up status has been detected. This value is rounded down to a multiple of MIIMonitorSec. The default value is 0. DownDelaySec= Specifies the delay before a link is disabled after a link down status has been detected. This value is rounded down to a multiple of MIIMonitorSec. The default value is 0. LearnPacketIntervalSec= Specifies the number of seconds between instances where the bonding driver sends learning packets to each slave peer switch. The valid range is 1–0x7fffffff; the default value is 1. This option has an effect only for the balance-tlb and balance-alb modes. AdSelect= Specifies the 802.3ad aggregation selection logic to use. Possible values are stable, bandwidth and count. FailOverMACPolicy= Specifies whether the active-backup mode should set all slaves to the same MAC address at the time of enslavement or, when enabled, to perform special handling of the bond's MAC address in accordance with the selected policy. The default policy is none. Possible values are none, active and follow. ARPValidate= Specifies whether or not ARP probes and replies should be validated in any mode that supports ARP monitoring, or whether non-ARP traffic should be filtered (disregarded) for link monitoring purposes. Possible values are none, active, backup and all. ARPIntervalSec= Specifies the ARP link monitoring frequency in milliseconds. A value of 0 disables ARP monitoring. The default value is 0. ARPIPTargets= Specifies the IP addresses to use as ARP monitoring peers when ARPIntervalSec is greater than 0. These are the targets of the ARP request sent to determine the health of the link to the targets. Specify these values in IPv4 dotted decimal format. At least one IP address must be given for ARP monitoring to function. The maximum number of targets that can be specified is 16. The default value is no IP addresses. ARPAllTargets= Specifies the quantity of ARPIPTargets that must be reachable in order for the ARP monitor to consider a slave as being up. This option affects only active-backup mode for slaves with ARPValidate enabled. Possible values are any and all. PrimaryReselectPolicy= Specifies the reselection policy for the primary slave. This affects how the primary slave is chosen to become the active slave when failure of the active slave or recovery of the primary slave occurs. This option is designed to prevent flip-flopping between the primary slave and other slaves. Possible values are always, better and failure. ResendIGMP= Specifies the number of IGMP membership reports to be issued after a failover event. One membership report is issued immediately after the failover, subsequent packets are sent in each 200ms interval. The valid range is 0–255. Defaults to 1. A value of 0 prevents the IGMP membership report from being issued in response to the failover event. PacketsPerSlave= Specify the number of packets to transmit through a slave before moving to the next one. When set to 0, then a slave is chosen at random. The valid range is 0–65535. Defaults to 1. This option only has effect when in balance-rr mode. GratuitousARP= Specify the number of peer notifications (gratuitous ARPs and unsolicited IPv6 Neighbor Advertisements) to be issued after a failover event. As soon as the link is up on the new slave, a peer notification is sent on the bonding device and each VLAN sub-device. This is repeated at each link monitor interval (ARPIntervalSec or MIIMonitorSec, whichever is active) if the number is greater than 1. The valid range is 0–255. The default value is 1. These options affect only the active-backup mode. AllSlavesActive= A boolean. Specifies that duplicate frames (received on inactive ports) should be dropped when false, or delivered when true. Normally, bonding will drop duplicate frames (received on inactive ports), which is desirable for most users. But there are some times it is nice to allow duplicate frames to be delivered. The default value is false (drop duplicate frames received on inactive ports). MinLinks= Specifies the minimum number of links that must be active before asserting carrier. The default value is 0. For more detail information see Linux Ethernet Bonding Driver HOWTO Example /etc/systemd/network/25-bridge.netdev [NetDev] Name=bridge0 Kind=bridge /etc/systemd/network/25-vlan1.netdev [Match] Virtualization=no [NetDev] Name=vlan1 Kind=vlan [VLAN] Id=1 /etc/systemd/network/25-ipip.netdev [NetDev] Name=ipip-tun Kind=ipip MTUBytes=1480 [Tunnel] Local=192.168.223.238 Remote=192.169.224.239 TTL=64 /etc/systemd/network/25-tap.netdev [NetDev] Name=tap-test Kind=tap [Tap] MultiQueue=true PacketInfo=true /etc/systemd/network/25-sit.netdev [NetDev] Name=sit-tun Kind=sit MTUBytes=1480 [Tunnel] Local=10.65.223.238 Remote=10.65.223.239 /etc/systemd/network/25-gre.netdev [NetDev] Name=gre-tun Kind=gre MTUBytes=1480 [Tunnel] Local=10.65.223.238 Remote=10.65.223.239 /etc/systemd/network/25-vti.netdev [NetDev] Name=vti-tun Kind=vti MTUBytes=1480 [Tunnel] Local=10.65.223.238 Remote=10.65.223.239 /etc/systemd/network/25-veth.netdev [NetDev] Name=veth-test Kind=veth [Peer] Name=veth-peer /etc/systemd/network/25-bond.netdev [NetDev] Name=bond1 Kind=bond [Bond] Mode=802.3ad TransmitHashPolicy=layer3+4 MIIMonitorSec=1s LACPTransmitRate=fast /etc/systemd/network/25-dummy.netdev [NetDev] Name=dummy-test Kind=dummy MACAddress=12:34:56:78:9a:bc See Also systemd1, systemd-networkd8, systemd.link5, systemd.network5
systemd-229/man/systemd.network.xml000066400000000000000000001333161265713322000175450ustar00rootroot00000000000000 systemd.network systemd Developer Tom Gundersen teg@jklm.no systemd.network 5 systemd.network Network configuration network.network Description Network setup is performed by systemd-networkd8. Network files must have the extension .network; other extensions are ignored. Networks are applied to links whenever the links appear. The .network files are read from the files located in the system network directory /usr/lib/systemd/network, the volatile runtime network directory /run/systemd/network and the local administration network directory /etc/systemd/network. All configuration files are collectively sorted and processed in lexical order, regardless of the directories in which they live. However, files with identical filenames replace each other. Files in /etc have the highest priority, files in /run take precedence over files with the same name in /usr/lib. This can be used to override a system-supplied configuration file with a local file if needed. As a special case, an empty file (file size 0) or symlink with the same name pointing to /dev/null disables the configuration file entirely (it is "masked"). [Match] Section Options The network file contains a [Match] section, which determines if a given network file may be applied to a given device; and a [Network] section specifying how the device should be configured. The first (in lexical order) of the network files that matches a given device is applied, all later files are ignored, even if they match as well. A network file is said to match a device if each of the entries in the [Match] section matches, or if the section is empty. The following keys are accepted: MACAddress= The hardware address. Path= A whitespace-separated list of shell-style globs matching the persistent path, as exposed by the udev property ID_PATH. Driver= A whitespace-separated list of shell-style globs matching the driver currently bound to the device, as exposed by the udev property DRIVER of its parent device, or if that is not set the driver as exposed by ethtool -i of the device itself. Type= A whitespace-separated list of shell-style globs matching the device type, as exposed by the udev property DEVTYPE. Name= A whitespace-separated list of shell-style globs matching the device name, as exposed by the udev property INTERFACE. Host= Matches against the hostname or machine ID of the host. See ConditionHost= in systemd.unit5 for details. Virtualization= Checks whether the system is executed in a virtualized environment and optionally test whether it is a specific implementation. See ConditionVirtualization= in systemd.unit5 for details. KernelCommandLine= Checks whether a specific kernel command line option is set (or if prefixed with the exclamation mark unset). See ConditionKernelCommandLine= in systemd.unit5 for details. Architecture= Checks whether the system is running on a specific architecture. See ConditionArchitecture= in systemd.unit5 for details. [Link] Section Options The [Link] section accepts the following keys: MACAddress= The hardware address. MTUBytes= The maximum transmission unit in bytes to set for the device. The usual suffixes K, M, G, are supported and are understood to the base of 1024. [Network] Section Options The [Network] section accepts the following keys: Description= A description of the device. This is only used for presentation purposes. DHCP= Enables DHCPv4 and/or DHCPv6 client support. Accepts yes, no, ipv4, or ipv6. Note that DHCPv6 will by default be triggered by Router Advertisement, if that is enabled, regardless of this parameter. By enabling DHCPv6 support explicitly, the DHCPv6 client will be started regardless of the presence of routers on the link, or what flags the routers pass. See IPv6AcceptRouterAdvertisements=. Furthermore, note that by default the domain name specified through DHCP is not used for name resolution. See option below. DHCPServer= A boolean. Enables DHCPv4 server support. Defaults to no. Further settings for the DHCP server may be set in the [DHCPServer] section described below. LinkLocalAddressing= Enables link-local address autoconfiguration. Accepts yes, no, ipv4, or ipv6. Defaults to ipv6. IPv4LLRoute= A boolean. When true, sets up the route needed for non-IPv4LL hosts to communicate with IPv4LL-only hosts. Defaults to false. IPv6Token= An IPv6 address with the top 64 bits unset. When set, indicates the 64-bit interface part of SLAAC IPv6 addresses for this link. By default, it is autogenerated. LLMNR= A boolean or resolve. When true, enables Link-Local Multicast Name Resolution on the link. When set to resolve, only resolution is enabled, but not host registration and announcement. Defaults to true. This setting is read by systemd-resolved.service8. MulticastDNS= A boolean or resolve. When true, enables Multicast DNS support on the link. When set to resolve, only resolution is enabled, but not host or service registration and announcement. Defaults to false. This setting is read by systemd-resolved.service8. DNSSEC= A boolean or allow-downgrade. When true, enables DNSSEC DNS validation support on the link. When set to allow-downgrade, compatibility with non-DNSSEC capable networks is increased, by automatically turning off DNSEC in this case. This option defines a per-interface setting for resolved.conf5's global DNSSEC= option. Defaults to false. This setting is read by systemd-resolved.service8. DNSSECNegativeTrustAnchors= A space-separated list of DNSSEC negative trust anchor domains. If specified and DNSSEC is enabled, look-ups done via the interface's DNS server will be subject to the list of negative trust anchors, and not require authentication for the specified domains, or anything below it. Use this to disable DNSSEC authentication for specific private domains, that cannot be proven valid using the Internet DNS hierarchy. Defaults to the empty list. This setting is read by systemd-resolved.service8. LLDP= A boolean. When true, enables LLDP link receive support. BindCarrier= A port or a list of ports. When set, controls the behavior of the current interface. When all ports in the list are in an operational down state, the current interface is brought down. When at least one port has carrier, the current interface is brought up. Address= A static IPv4 or IPv6 address and its prefix length, separated by a / character. Specify this key more than once to configure several addresses. The format of the address must be as described in inet_pton3. This is a short-hand for an [Address] section only containing an Address key (see below). This option may be specified more than once. If the specified address is 0.0.0.0 (for IPv4) or [::] (for IPv6), a new address range of the requested size is automatically allocated from a system-wide pool of unused ranges. The allocated range is checked against all current network interfaces and all known network configuration files to avoid address range conflicts. The default system-wide pool consists of 192.168.0.0/16, 172.16.0.0/12 and 10.0.0.0/8 for IPv4, and fc00::/7 for IPv6. This functionality is useful to manage a large number of dynamically created network interfaces with the same network configuration and automatic address range assignment. Gateway= The gateway address, which must be in the format described in inet_pton3. This is a short-hand for a [Route] section only containing a Gateway key. This option may be specified more than once. DNS= A DNS server address, which must be in the format described in inet_pton3. This option may be specified more than once. This setting is read by systemd-resolved.service8. Domains= The domains used for DNS host name resolution on this link. Takes a list of DNS domain names which are used as search suffixes for extending single-label host names (host names containing no dots) to become fully qualified domain names (FQDNs). If a single-label host name is resolved on this interface, each of the specified search domains are appended to it in turn, converting it into a fully qualified domain name, until one of them may be successfully resolved. The specified domains are also used for routing of DNS queries: look-ups for host names ending in the domains specified here are preferably routed to the DNS servers configured for this interface. If a domain name is prefixed with ~, the domain name becomes a pure "routing" domain, is used for DNS query routing purposes only and is not used in the described domain search logic. By specifying a routing domain of ~. (the tilda indicating definition of a routing domain, the dot referring to the DNS root domain which is the implied suffix of all valid DNS names) it is possible to route all DNS traffic preferably to the DNS server specified for this interface. The route domain logic is particularly useful on multi-homed hosts with DNS servers serving particular private DNS zones on each interface. This setting is read by systemd-resolved.service8. NTP= An NTP server address. This option may be specified more than once. This setting is read by systemd-timesyncd.service8. IPForward= Configures IP packet forwarding for the system. If enabled, incoming packets on any network interface will be forwarded to any other interfaces according to the routing table. Takes either a boolean argument, or the values ipv4 or ipv6, which only enable IP packet forwarding for the specified address family. This controls the net.ipv4.ip_forward and net.ipv6.conf.all.forwarding sysctl options of the network interface (see ip-sysctl.txt for details about sysctl options). Defaults to no. Note: this setting controls a global kernel option, and does so one way only: if a network that has this setting enabled is set up the global setting is turned on. However, it is never turned off again, even after all networks with this setting enabled are shut down again. To allow IP packet forwarding only between specific network interfaces use a firewall. IPMasquerade= Configures IP masquerading for the network interface. If enabled, packets forwarded from the network interface will be appear as coming from the local host. Takes a boolean argument. Implies IPForward=ipv4. Defaults to no. IPv6PrivacyExtensions= Configures use of stateless temporary addresses that change over time (see RFC 4941, Privacy Extensions for Stateless Address Autoconfiguration in IPv6). Takes a boolean or the special values prefer-public and kernel. When true, enables the privacy extensions and prefers temporary addresses over public addresses. When prefer-public, enables the privacy extensions, but prefers public addresses over temporary addresses. When false, the privacy extensions remain disabled. When kernel, the kernel's default setting will be left in place. Defaults to no. IPv6AcceptRouterAdvertisements= Force the setting of the accept_ra (router advertisements) setting for the interface. When unset, the kernel default is used, and router advertisements are accepted only when local forwarding is disabled for that interface. When router advertisements are accepted, they will trigger the start of the DHCPv6 client if the relevant flags are passed, or if no routers are found on the link. Takes a boolean. If true, router advertisements are accepted, when false, router advertisements are ignored, independently of the local forwarding state. See ip-sysctl.txt in the kernel documentation, but note that systemd's setting of 1 corresponds to kernel's setting of 2. IPv6DuplicateAddressDetection= Configures the amount of IPv6 Duplicate Address Detection (DAD) probes to send. Defaults to unset. IPv6HopLimit= Configures IPv6 Hop Limit. For each router that forwards the packet, the hop limit is decremented by 1. When the hop limit field reaches zero, the packet is discarded. Defaults to unset. Bridge= The name of the bridge to add the link to. Bond= The name of the bond to add the link to. VLAN= The name of a VLAN to create on the link. This option may be specified more than once. MACVLAN= The name of a MACVLAN to create on the link. This option may be specified more than once. VXLAN= The name of a VXLAN to create on the link. This option may be specified more than once. Tunnel= The name of a Tunnel to create on the link. This option may be specified more than once. [Address] Section Options An [Address] section accepts the following keys. Specify several [Address] sections to configure several addresses. Address= As in the [Network] section. This key is mandatory. Peer= The peer address in a point-to-point connection. Accepts the same format as the Address key. Broadcast= The broadcast address, which must be in the format described in inet_pton3. This key only applies to IPv4 addresses. If it is not given, it is derived from the Address key. Label= An address label. [Route] Section Options The [Route] section accepts the following keys. Specify several [Route] sections to configure several routes. Gateway= As in the [Network] section. Destination= The destination prefix of the route. Possibly followed by a slash and the prefix length. If omitted, a full-length host route is assumed. Source= The source prefix of the route. Possibly followed by a slash and the prefix length. If omitted, a full-length host route is assumed. Metric= The metric of the route (an unsigned integer). Scope= The scope of the route, which can be global, link or host. Defaults to global. PreferredSource= The preferred source address of the route. The address must be in the format described in inet_pton3. [DHCP] Section Options The [DHCP] section configures the DHCPv4 and DHCP6 client, if it is enabled with the DHCP= setting described above: UseDNS= When true (the default), the DNS servers received from the DHCP server will be used and take precedence over any statically configured ones. This corresponds to the option in resolv.conf5. UseNTP= When true (the default), the NTP servers received from the DHCP server will be used by systemd-timesyncd and take precedence over any statically configured ones. UseMTU= When true, the interface maximum transmission unit from the DHCP server will be used on the current link. Defaults to false. SendHostname= When true (the default), the machine's hostname will be sent to the DHCP server. UseHostname= When true (the default), the hostname received from the DHCP server will be set as the transient hostname of the system Hostname= Use this value for the hostname which is sent to the DHCP server, instead of machine's hostname. UseDomains= Takes a boolean argument, or a the special value route. When true, the domain name received from the DHCP server will be used as DNS search domain over this link, similar to the effect of the setting. If set to route, the domain name received from the DHCP server will be used for routing DNS queries only, but not for searching, similar to the effect of the setting when the argument is prefixed with ~. Defaults to false. It is recommended to enable this option only on trusted networks, as setting this affects resolution of all host names, in particular to single-label names. It is generally safer to use the supplied domain only as routing domain, rather than as search domain, in order to not have it affect local resolution of single-label names. When set to true, this setting corresponds to the option in resolv.conf5. UseRoutes= When true (the default), the static routes will be requested from the DHCP server and added to the routing table with a metric of 1024. UseTimezone= When true, the timezone received from the DHCP server will be set as timezone of the local system. Defaults to no. CriticalConnection= When true, the connection will never be torn down even if the DHCP lease expires. This is contrary to the DHCP specification, but may be the best choice if, say, the root filesystem relies on this connection. Defaults to false. ClientIdentifier= DHCP client identifier to use. Either mac to use the MAC address of the link or duid (the default) to use a RFC4361-compliant Client ID. VendorClassIdentifier= The vendor class identifier used to identify vendor type and configuration. RequestBroadcast= Request the server to use broadcast messages before the IP address has been configured. This is necessary for devices that cannot receive RAW packets, or that cannot receive packets at all before an IP address has been configured. On the other hand, this must not be enabled on networks where broadcasts are filtered out. RouteMetric= Set the routing metric for routes specified by the DHCP server. [DHCPServer] Section Options The [DHCPServer] section contains settings for the DHCP server, if enabled via the DHCPServer= option described above: PoolOffset= PoolSize= Configures the pool of addresses to hand out. The pool is a contiguous sequence of IP addresses in the subnet configured for the server address, which does not include the subnet nor the broadcast address. PoolOffset= takes the offset of the pool from the start of subnet, or zero to use the default value. PoolSize= takes the number of IP addresses in the pool or zero to use the default value. By default, the pool starts at the first address after the subnet address and takes up the rest of the subnet, excluding the broadcast address. If the pool includes the server address (the default), this is reserved and not handed out to clients. DefaultLeaseTimeSec= MaxLeaseTimeSec= Control the default and maximum DHCP lease time to pass to clients. These settings take time values in seconds or another common time unit, depending on the suffix. The default lease time is used for clients that did not ask for a specific lease time. If a client asks for a lease time longer than the maximum lease time, it is automatically shortened to the specified time. The default lease time defaults to 1h, the maximum lease time to 12h. Shorter lease times are beneficial if the configuration data in DHCP leases changes frequently and clients shall learn the new settings with shorter latencies. Longer lease times reduce the generated DHCP network traffic. EmitDNS= DNS= Configures whether the DHCP leases handed out to clients shall contain DNS server information. The EmitDNS= setting takes a boolean argument and defaults to yes. The DNS servers to pass to clients may be configured with the DNS= option, which takes a list of IPv4 addresses. If the EmitDNS= option is enabled but no servers configured, the servers are automatically propagated from an "uplink" interface that has appropriate servers set. The "uplink" interface is determined by the default route of the system with the highest priority. Note that this information is acquired at the time the lease is handed out, and does not take uplink interfaces into account that acquire DNS or NTP server information at a later point. DNS server propagation does not take /etc/resolv.conf into account. Also, note that the leases are not refreshed if the uplink network configuration changes. To ensure clients regularly acquire the most current uplink DNS server information, it is thus advisable to shorten the DHCP lease time via MaxLeaseTimeSec= described above. EmitNTP= NTP= Similar to the EmitDNS= and DNS= settings described above, these settings configure whether and what NTP server information shall be emitted as part of the DHCP lease. The same syntax, propagation semantics and defaults apply as for EmitDNS= and DNS=. EmitTimezone= Timezone= Configures whether the DHCP leases handed out to clients shall contain timezone information. The EmitTimezone= setting takes a boolean argument and defaults to yes. The Timezone= setting takes a timezone string (such as Europe/Berlin or UTC) to pass to clients. If no explicit timezone is set, the system timezone of the local host is propagated, as determined by the /etc/localtime symlink. [Bridge] Section Options The [Bridge] section accepts the following keys. UnicastFlood= A boolean. Controls whether the bridge should flood traffic for which an FDB entry is missing and the destination is unknown through this port. Defaults to on. HairPin= A boolean. Configures whether traffic may be sent back out of the port on which it was received. By default, this flag is false, and the bridge will not forward traffic back out of the receiving port. UseBPDU= A boolean. Configures whether STP Bridge Protocol Data Units will be processed by the bridge port. Defaults to yes. FastLeave= A boolean. This flag allows the bridge to immediately stop multicast traffic on a port that receives an IGMP Leave message. It is only used with IGMP snooping if enabled on the bridge. Defaults to off. AllowPortToBeRoot= A boolean. Configures whether a given port is allowed to become a root port. Only used when STP is enabled on the bridge. Defaults to on. Cost= Sets the "cost" of sending packets of this interface. Each port in a bridge may have a different speed and the cost is used to decide which link to use. Faster interfaces should have lower costs. [BridgeFDB] Section Options The [BridgeFDB] section manages the forwarding database table of a port and accepts the following keys. Specify several [BridgeFDB] sections to configure several static MAC table entries. MACAddress= As in the [Network] section. This key is mandatory. VLANId= The VLAN ID for the new static MAC table entry. If omitted, no VLAN ID info is appended to the new static MAC table entry. Example /etc/systemd/network/50-static.network [Match] Name=enp2s0 [Network] Address=192.168.0.15/24 Gateway=192.168.0.1 /etc/systemd/network/80-dhcp.network [Match] Name=en* [Network] DHCP=yes /etc/systemd/network/25-bridge-static.network [Match] Name=bridge0 [Network] Address=192.168.0.15/24 Gateway=192.168.0.1 DNS=192.168.0.1 /etc/systemd/network/25-bridge-slave-interface.network [Match] Name=enp2s0 [Network] Bridge=bridge0 /etc/systemd/network/25-ipip.network [Match] Name=em1 [Network] Tunnel=ipip-tun /etc/systemd/network/25-sit.network [Match] Name=em1 [Network] Tunnel=sit-tun /etc/systemd/network/25-gre.network [Match] Name=em1 [Network] Tunnel=gre-tun /etc/systemd/network/25-vti.network [Match] Name=em1 [Network] Tunnel=vti-tun /etc/systemd/network/25-bond.network [Match] Name=bond1 [Network] DHCP=yes See Also systemd1, systemd-networkd.service8, systemd.link5, systemd.netdev5, systemd-resolved.service8 systemd-229/man/systemd.nspawn.xml000066400000000000000000000433731265713322000173650ustar00rootroot00000000000000 %entities; ]> systemd.nspawn systemd Developer Lennart Poettering lennart@poettering.net systemd.nspawn 5 systemd.nspawn Container settings /etc/systemd/nspawn/machine.nspawn /run/systemd/nspawn/machine.nspawn /var/lib/machines/machine.nspawn Description An nspawn container settings file (suffix .nspawn) encodes additional runtime information about a local container, and is searched, read and used by systemd-nspawn1 when starting a container. Files of this type are named after the containers they define settings for. They are optional, and only required for containers whose execution environment shall differ from the defaults. Files of this type mostly contain settings that may also be set on the systemd-nspawn command line, and make it easier to persistently attach specific settings to specific containers. The syntax of these files is inspired by .desktop files following the XDG Desktop Entry Specification, which in turn are inspired by Microsoft Windows .ini files. Boolean arguments used in these settings files can be written in various formats. For positive settings, the strings , , and are equivalent. For negative settings, the strings , , and are equivalent. Empty lines and lines starting with # or ; are ignored. This may be used for commenting. Lines ending in a backslash are concatenated with the following line while reading and the backslash is replaced by a space character. This may be used to wrap long lines. <filename>.nspawn</filename> File Discovery Files are searched by appending the .nspawn suffix to the machine name of the container, as specified with the switch of systemd-nspawn, or derived from the directory or image file name. This file is first searched in /etc/systemd/nspawn/ and /run/systemd/nspawn/. If found in these directories, its settings are read and all of them take full effect (but are possibly overridden by corresponding command line arguments). If not found, the file will then be searched next to the image file or in the immediate parent of the root directory of the container. If the file is found there, only a subset of the settings will take effect however. All settings that possibly elevate privileges or grant additional access to resources of the host (such as files or directories) are ignored. To which options this applies is documented below. Persistent settings files created and maintained by the administrator (and thus trusted) should be placed in /etc/systemd/nspawn/, while automatically downloaded (and thus potentially untrusted) settings files are placed in /var/lib/machines/ instead (next to the container images), where their security impact is limited. In order to add privileged settings to .nspawn files acquired from the image vendor, it is recommended to copy the settings files into /etc/systemd/nspawn/ and edit them there, so that the privileged options become available. The precise algorithm for how the files are searched and interpreted may be configured with systemd-nspawn's switch, see systemd-nspawn1 for details. [Exec] Section Options Settings files may include an [Exec] section, which carries various execution parameters: Boot= Takes a boolean argument, which defaults to off. If enabled, systemd-nspawn will automatically search for an init executable and invoke it. In this case, the specified parameters using Parameters= are passed as additional arguments to the init process. This setting corresponds to the switch on the systemd-nspawn command line. This option may not be combined with ProcessTwo=yes. ProcessTwo= Takes a boolean argument, which defaults to off. If enabled, the specified program is run as PID 2. A stub init process is run as PID 1. This setting corresponds to the switch on the systemd-nspawn command line. This option may not be combined with Boot=yes. Parameters= Takes a space-separated list of arguments. This is either a command line, beginning with the binary name to execute, or – if Boot= is enabled – the list of arguments to pass to the init process. This setting corresponds to the command line parameters passed on the systemd-nspawn command line. Environment= Takes an environment variable assignment consisting of key and value, separated by =. Sets an environment variable for the main process invoked in the container. This setting may be used multiple times to set multiple environment variables. It corresponds to the command line switch. User= Takes a UNIX user name. Specifies the user name to invoke the main process of the container as. This user must be known in the container's user database. This corresponds to the command line switch. WorkingDirectory= Selects the working directory for the process invoked in the container. Expects an absolute path in the container's file system namespace. This corresponds to the command line switch. Capability= DropCapability= Takes a space-separated list of Linux process capabilities (see capabilities7 for details). The Capability= setting specifies additional capabilities to pass on top of the default set of capabilities. The DropCapability= setting specifies capabilities to drop from the default set. These settings correspond to the and command line switches. Note that Capability= is a privileged setting, and only takes effect in .nspawn files in /etc/systemd/nspawn/ and /run/system/nspawn/ (see above). On the other hand, DropCapability= takes effect in all cases. Personality= Configures the kernel personality for the container. This is equivalent to the switch. MachineID= Configures the 128-bit machine ID (UUID) to pass to the container. This is equivalent to the command line switch. This option is privileged (see above). [Files] Section Options Settings files may include a [Files] section, which carries various parameters configuring the file system of the container: ReadOnly= Takes a boolean argument, which defaults to off. If specified, the container will be run with a read-only file system. This setting corresponds to the command line switch. Volatile= Takes a boolean argument, or the special value state. This configures whether to run the container with volatile state and/or configuration. This option is equivalent to , see systemd-nspawn1 for details about the specific options supported. Bind= BindReadOnly= Adds a bind mount from the host into the container. Takes a single path, a pair of two paths separated by a colon, or a triplet of two paths plus an option string separated by colons. This option may be used multiple times to configure multiple bind mounts. This option is equivalent to the command line switches and , see systemd-nspawn1 for details about the specific options supported. This setting is privileged (see above). TemporaryFileSystem= Adds a tmpfs mount to the container. Takes a path or a pair of path and option string, separated by a colon. This option may be used multiple times to configure multiple tmpfs mounts. This option is equivalent to the command line switch , see systemd-nspawn1 for details about the specific options supported. This setting is privileged (see above). [Network] Section Options Settings files may include a [Network] section, which carries various parameters configuring the network connectivity of the container: Private= Takes a boolean argument, which defaults to off. If enabled, the container will run in its own network namespace and not share network interfaces and configuration with the host. This setting corresponds to the command line switch. VirtualEthernet= Takes a boolean argument. Configures whether to create a virtual Ethernet connection (veth) between host and the container. This setting implies Private=yes. This setting corresponds to the command line switch. This option is privileged (see above). VirtualEthernetExtra= Takes a colon-separated pair of interface names. Configures an additional virtual Ethernet connection (veth) between host and the container. The first specified name is the interface name on the host, the second the interface name in the container. The latter may be omitted in which case it is set to the same name as the host side interface. This setting implies Private=yes. This setting corresponds to the command line switch, and maybe be used multiple times. It is independent of VirtualEthernet=. This option is privileged (see above). Interface= Takes a space-separated list of interfaces to add to the container. This option corresponds to the command line switch and implies Private=yes. This option is privileged (see above). MACVLAN= IPVLAN= Takes a space-separated list of interfaces to add MACLVAN or IPVLAN interfaces to, which are then added to the container. These options correspond to the and command line switches and imply Private=yes. These options are privileged (see above). Bridge= Takes an interface name. This setting implies VirtualEthernet=yes and Private=yes and has the effect that the host side of the created virtual Ethernet link is connected to the specified bridge interface. This option corresponds to the command line switch. This option is privileged (see above). Port= Exposes a TCP or UDP port of the container on the host. This option corresponds to the command line switch, see systemd-nspawn1 for the precise syntax of the argument this option takes. This option is privileged (see above). See Also systemd1, systemd-nspawn1, systemd.directives7 systemd-229/man/systemd.path.xml000066400000000000000000000214701265713322000170050ustar00rootroot00000000000000 systemd.path systemd Developer Lennart Poettering lennart@poettering.net systemd.path 5 systemd.path Path unit configuration path.path Description A unit configuration file whose name ends in .path encodes information about a path monitored by systemd, for path-based activation. This man page lists the configuration options specific to this unit type. See systemd.unit5 for the common options of all unit configuration files. The common configuration items are configured in the generic [Unit] and [Install] sections. The path specific configuration options are configured in the [Path] section. For each path file, a matching unit file must exist, describing the unit to activate when the path changes. By default, a service by the same name as the path (except for the suffix) is activated. Example: a path file foo.path activates a matching service foo.service. The unit to activate may be controlled by Unit= (see below). Internally, path units use the inotify7 API to monitor file systems. Due to that, it suffers by the same limitations as inotify, and for example cannot be used to monitor files or directories changed by other machines on remote NFS file systems. Automatic Dependencies If a path unit is beneath another mount unit in the file system hierarchy, both a requirement and an ordering dependency between both units are created automatically. An implicit Before= dependency is added between a path unit and the unit it is supposed to activate. Unless DefaultDependencies=false is used, path units will implicitly have dependencies of type Before= on paths.target, dependencies of type After= and Requires= on sysinit.target, and have dependencies of type Conflicts= and Before= on shutdown.target. These ensure that path units are terminated cleanly prior to system shutdown. Only path units involved with early boot or late system shutdown should disable this option. Options Path files must include a [Path] section, which carries information about the path(s) it monitors. The options specific to the [Path] section of path units are the following: PathExists= PathExistsGlob= PathChanged= PathModified= DirectoryNotEmpty= Defines paths to monitor for certain changes: PathExists= may be used to watch the mere existence of a file or directory. If the file specified exists, the configured unit is activated. PathExistsGlob= works similar, but checks for the existence of at least one file matching the globbing pattern specified. PathChanged= may be used to watch a file or directory and activate the configured unit whenever it changes. It is not activated on every write to the watched file but it is activated if the file which was open for writing gets closed. PathModified= is similar, but additionally it is activated also on simple writes to the watched file. DirectoryNotEmpty= may be used to watch a directory and activate the configured unit whenever it contains at least one file. The arguments of these directives must be absolute file system paths. Multiple directives may be combined, of the same and of different types, to watch multiple paths. If the empty string is assigned to any of these options, the list of paths to watch is reset, and any prior assignments of these options will not have any effect. If a path already exists (in case of PathExists= and PathExistsGlob=) or a directory already is not empty (in case of DirectoryNotEmpty=) at the time the path unit is activated, then the configured unit is immediately activated as well. Something similar does not apply to PathChanged= and PathModified=. If the path itself or any of the containing directories are not accessible, systemd will watch for permission changes and notice that conditions are satisfied when permissions allow that. Unit= The unit to activate when any of the configured paths changes. The argument is a unit name, whose suffix is not .path. If not specified, this value defaults to a service that has the same name as the path unit, except for the suffix. (See above.) It is recommended that the unit name that is activated and the unit name of the path unit are named identical, except for the suffix. MakeDirectory= Takes a boolean argument. If true, the directories to watch are created before watching. This option is ignored for PathExists= settings. Defaults to . DirectoryMode= If MakeDirectory= is enabled, use the mode specified here to create the directories in question. Takes an access mode in octal notation. Defaults to . See Also systemd1, systemctl1, systemd.unit5, systemd.service5, inotify7, systemd.directives7 systemd-229/man/systemd.preset.xml000066400000000000000000000171721265713322000173570ustar00rootroot00000000000000 systemd.preset systemd Developer Lennart Poettering lennart@poettering.net systemd.preset 5 systemd.preset Service enablement presets /etc/systemd/system-preset/*.preset /run/systemd/system-preset/*.preset /usr/lib/systemd/system-preset/*.preset /etc/systemd/user-preset/*.preset /run/systemd/user-preset/*.preset /usr/lib/systemd/user-preset/*.preset Description Preset files may be used to encode policy which units shall be enabled by default and which ones shall be disabled. They are read by systemctl preset (for more information see systemctl1) which uses this information to enable or disable a unit according to preset policy. systemctl preset is used by the post install scriptlets of RPM packages (or other OS package formats), to enable/disable specific units by default on package installation, enforcing distribution, spin or administrator preset policy. This allows choosing a certain set of units to be enabled/disabled even before installing the actual package. For more information on the preset logic please have a look at the Presets document. It is not recommended to ship preset files within the respective software packages implementing the units, but rather centralize them in a distribution or spin default policy, which can be amended by administrator policy. If no preset files exist, systemctl preset will enable all units that are installed by default. If this is not desired and all units shall rather be disabled, it is necessary to ship a preset file with a single, catchall "disable *" line. (See example 1, below.) Preset File Format The preset files contain a list of directives consisting of either the word enable or disable followed by a space and a unit name (possibly with shell style wildcards), separated by newlines. Empty lines and lines whose first non-whitespace character is # or ; are ignored. Two different directives are understood: enable may be used to enable units by default, disable to disable units by default. If multiple lines apply to a unit name, the first matching one takes precedence over all others. Each preset file shall be named in the style of <priority>-<policy-name>.preset. Files in /etc/ override files with the same name in /usr/lib/ and /run/. Files in /run/ override files with the same name in /usr/lib/. Packages should install their preset files in /usr/lib/. Files in /etc/ are reserved for the local administrator, who may use this logic to override the preset files installed by vendor packages. All preset files are sorted by their filename in lexicographic order, regardless of which of the directories they reside in. If multiple files specify the same unit name, the entry in the file with the lexicographically earliest name will be applied. It is recommended to prefix all filenames with a two-digit number and a dash, to simplify the ordering of the files. If the administrator wants to disable a preset file supplied by the vendor, the recommended way is to place a symlink to /dev/null in /etc/systemd/system-preset/ bearing the same filename. Example Default off example <filename>/usr/lib/systemd/system-preset/99-default.preset</filename>: disable * This disables all units. Due to the filename prefix 99-, it will be read last and hence can easily be overridden by spin or administrator preset policy or suchlike. A GNOME spin example <filename>/usr/lib/systemd/system-preset/50-gnome.preset</filename>: enable gdm.service enable colord.service enable accounts-daemon.service enable avahi-daemon.* This enables the three mentioned units, plus all avahi-daemon regardless of which unit type. A file like this could be useful for inclusion in a GNOME spin of a distribution. It will ensure that the units necessary for GNOME are properly enabled as they are installed. It leaves all other units untouched, and subject to other (later) preset files, for example like the one from the first example above. Administrator policy <filename>/etc/systemd/system-preset/00-lennart.preset</filename>: enable httpd.service enable sshd.service enable postfix.service disable * This enables three specific services and disables all others. This is useful for administrators to specifically select the units to enable, and disable all others. Due to the filename prefix 00- it will be read early and hence overrides all other preset policy files. See Also systemd1, systemctl1, systemd-delta1 systemd-229/man/systemd.resource-control.xml000066400000000000000000000551001265713322000213530ustar00rootroot00000000000000 systemd.resource-control systemd Developer Lennart Poettering lennart@poettering.net systemd.resource-control 5 systemd.resource-control Resource control unit settings slice.slice, scope.scope, service.service, socket.socket, mount.mount, swap.swap Description Unit configuration files for services, slices, scopes, sockets, mount points, and swap devices share a subset of configuration options for resource control of spawned processes. Internally, this relies on the Control Groups kernel concept for organizing processes in a hierarchical tree of named groups for the purpose of resource management. This man page lists the configuration options shared by those six unit types. See systemd.unit5 for the common options of all unit configuration files, and systemd.slice5, systemd.scope5, systemd.service5, systemd.socket5, systemd.mount5, and systemd.swap5 for more information on the specific unit configuration files. The resource control configuration options are configured in the [Slice], [Scope], [Service], [Socket], [Mount], or [Swap] sections, depending on the unit type. See the New Control Group Interfaces for an introduction on how to make use of resource control APIs from programs. Automatic Dependencies Units with the Slice= setting set get automatic Requires= and After= dependencies on the specified slice unit. Options Units of the types listed above can have settings for resource control configuration: CPUAccounting= Turn on CPU usage accounting for this unit. Takes a boolean argument. Note that turning on CPU accounting for one unit will also implicitly turn it on for all units contained in the same slice and for all its parent slices and the units contained therein. The system default for this setting may be controlled with DefaultCPUAccounting= in systemd-system.conf5. CPUShares=weight StartupCPUShares=weight Assign the specified CPU time share weight to the processes executed. These options take an integer value and control the cpu.shares control group attribute. The allowed range is 2 to 262144. Defaults to 1024. For details about this control group attribute, see sched-design-CFS.txt. The available CPU time is split up among all units within one slice relative to their CPU time share weight. While StartupCPUShares= only applies to the startup phase of the system, CPUShares= applies to normal runtime of the system, and if the former is not set also to the startup phase. Using StartupCPUShares= allows prioritizing specific services at boot-up differently than during normal runtime. These options imply CPUAccounting=true. CPUQuota= Assign the specified CPU time quota to the processes executed. Takes a percentage value, suffixed with "%". The percentage specifies how much CPU time the unit shall get at maximum, relative to the total CPU time available on one CPU. Use values > 100% for allotting CPU time on more than one CPU. This controls the cpu.cfs_quota_us control group attribute. For details about this control group attribute, see sched-design-CFS.txt. Example: CPUQuota=20% ensures that the executed processes will never get more than 20% CPU time on one CPU. Implies CPUAccounting=true. MemoryAccounting= Turn on process and kernel memory accounting for this unit. Takes a boolean argument. Note that turning on memory accounting for one unit will also implicitly turn it on for all units contained in the same slice and for all its parent slices and the units contained therein. The system default for this setting may be controlled with DefaultMemoryAccounting= in systemd-system.conf5. MemoryLimit=bytes Specify the limit on maximum memory usage of the executed processes. The limit specifies how much process and kernel memory can be used by tasks in this unit. Takes a memory size in bytes. If the value is suffixed with K, M, G or T, the specified memory size is parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. If assigned the special value infinity, no memory limit is applied. This controls the memory.limit_in_bytes control group attribute. For details about this control group attribute, see memory.txt. Implies MemoryAccounting=true. TasksAccounting= Turn on task accounting for this unit. Takes a boolean argument. If enabled, the system manager will keep track of the number of tasks in the unit. The number of tasks accounted this way includes both kernel threads and userspace processes, with each thread counting individually. Note that turning on tasks accounting for one unit will also implicitly turn it on for all units contained in the same slice and for all its parent slices and the units contained therein. The system default for this setting may be controlled with DefaultTasksAccounting= in systemd-system.conf5. TasksMax=N Specify the maximum number of tasks that may be created in the unit. This ensures that the number of tasks accounted for the unit (see above) stays below a specific limit. If assigned the special value infinity, no tasks limit is applied. This controls the pids.max control group attribute. For details about this control group attribute, see pids.txt. Implies TasksAccounting=true. The system default for this setting may be controlled with DefaultTasksMax= in systemd-system.conf5. BlockIOAccounting= Turn on Block I/O accounting for this unit. Takes a boolean argument. Note that turning on block I/O accounting for one unit will also implicitly turn it on for all units contained in the same slice and all for its parent slices and the units contained therein. The system default for this setting may be controlled with DefaultBlockIOAccounting= in systemd-system.conf5. BlockIOWeight=weight StartupBlockIOWeight=weight Set the default overall block I/O weight for the executed processes. Takes a single weight value (between 10 and 1000) to set the default block I/O weight. This controls the blkio.weight control group attribute, which defaults to 500. For details about this control group attribute, see blkio-controller.txt. The available I/O bandwidth is split up among all units within one slice relative to their block I/O weight. While StartupBlockIOWeight= only applies to the startup phase of the system, BlockIOWeight= applies to the later runtime of the system, and if the former is not set also to the startup phase. This allows prioritizing specific services at boot-up differently than during runtime. Implies BlockIOAccounting=true. BlockIODeviceWeight=device weight Set the per-device overall block I/O weight for the executed processes. Takes a space-separated pair of a file path and a weight value to specify the device specific weight value, between 10 and 1000. (Example: "/dev/sda 500"). The file path may be specified as path to a block device node or as any other file, in which case the backing block device of the file system of the file is determined. This controls the blkio.weight_device control group attribute, which defaults to 1000. Use this option multiple times to set weights for multiple devices. For details about this control group attribute, see blkio-controller.txt. Implies BlockIOAccounting=true. BlockIOReadBandwidth=device bytes BlockIOWriteBandwidth=device bytes Set the per-device overall block I/O bandwidth limit for the executed processes. Takes a space-separated pair of a file path and a bandwidth value (in bytes per second) to specify the device specific bandwidth. The file path may be a path to a block device node, or as any other file in which case the backing block device of the file system of the file is used. If the bandwidth is suffixed with K, M, G, or T, the specified bandwidth is parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes, respectively, to the base of 1000. (Example: "/dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0 5M"). This controls the blkio.read_bps_device and blkio.write_bps_device control group attributes. Use this option multiple times to set bandwidth limits for multiple devices. For details about these control group attributes, see blkio-controller.txt. Implies BlockIOAccounting=true. DeviceAllow= Control access to specific device nodes by the executed processes. Takes two space-separated strings: a device node specifier followed by a combination of r, w, m to control reading, writing, or creation of the specific device node(s) by the unit (mknod), respectively. This controls the devices.allow and devices.deny control group attributes. For details about these control group attributes, see devices.txt. The device node specifier is either a path to a device node in the file system, starting with /dev/, or a string starting with either char- or block- followed by a device group name, as listed in /proc/devices. The latter is useful to whitelist all current and future devices belonging to a specific device group at once. The device group is matched according to file name globbing rules, you may hence use the * and ? wildcards. Examples: /dev/sda5 is a path to a device node, referring to an ATA or SCSI block device. char-pts and char-alsa are specifiers for all pseudo TTYs and all ALSA sound devices, respectively. char-cpu/* is a specifier matching all CPU related device groups. DevicePolicy=auto|closed|strict Control the policy for allowing device access: means to only allow types of access that are explicitly specified. in addition, allows access to standard pseudo devices including /dev/null, /dev/zero, /dev/full, /dev/random, and /dev/urandom. in addition, allows access to all devices if no explicit DeviceAllow= is present. This is the default. Slice= The name of the slice unit to place the unit in. Defaults to system.slice for all non-instantiated units of all unit types (except for slice units themselves see below). Instance units are by default placed in a subslice of system.slice that is named after the template name. This option may be used to arrange systemd units in a hierarchy of slices each of which might have resource settings applied. For units of type slice, the only accepted value for this setting is the parent slice. Since the name of a slice unit implies the parent slice, it is hence redundant to ever set this parameter directly for slice units. Special care should be taken when relying on the default slice assignment in templated service units that have DefaultDependencies=no set, see systemd.service5, section "Automatic Dependencies" for details. Delegate= Turns on delegation of further resource control partitioning to processes of the unit. For unprivileged services (i.e. those using the User= setting), this allows processes to create a subhierarchy beneath its control group path. For privileged services and scopes, this ensures the processes will have all control group controllers enabled. See Also systemd1, systemd.unit5, systemd.service5, systemd.slice5, systemd.scope5, systemd.socket5, systemd.mount5, systemd.swap5, systemd.directives7, systemd.special7, The documentation for control groups and specific controllers in the Linux kernel: cgroups.txt, cpuacct.txt, memory.txt, blkio-controller.txt. systemd-229/man/systemd.scope.xml000066400000000000000000000101161265713322000171550ustar00rootroot00000000000000 systemd.scope systemd Developer Lennart Poettering lennart@poettering.net systemd.scope 5 systemd.scope Scope unit configuration scope.scope Description Scope units are not configured via unit configuration files, but are only created programmatically using the bus interfaces of systemd. They are named similar to filenames. A unit whose name ends in .scope refers to a scope unit. Scopes units manage a set of system processes. Unlike service units, scope units manage externally created processes, and do not fork off processes on its own. The main purpose of scope units is grouping worker processes of a system service for organization and for managing resources. systemd-run may be used to easily launch a command in a new scope unit from the command line. See the New Control Group Interfaces for an introduction on how to make use of scope units from programs. Automatic Dependencies Unless DefaultDependencies=false is used, scope units will implicitly have dependencies of type Conflicts= and Before= on shutdown.target. These ensure that scope units are removed prior to system shutdown. Only scope units involved with early boot or late system shutdown should disable this option. Additional implicit dependencies may be added as result of resource control parameters as documented in systemd.resource-control5. See Also systemd1, systemd-run1, systemd.unit5, systemd.resource-control5, systemd.service5, systemd.directives7. systemd-229/man/systemd.service.xml000066400000000000000000002002031265713322000175020ustar00rootroot00000000000000 systemd.service systemd Developer Lennart Poettering lennart@poettering.net systemd.service 5 systemd.service Service unit configuration service.service Description A unit configuration file whose name ends in .service encodes information about a process controlled and supervised by systemd. This man page lists the configuration options specific to this unit type. See systemd.unit5 for the common options of all unit configuration files. The common configuration items are configured in the generic [Unit] and [Install] sections. The service specific configuration options are configured in the [Service] section. Additional options are listed in systemd.exec5, which define the execution environment the commands are executed in, and in systemd.kill5, which define the way the processes of the service are terminated, and in systemd.resource-control5, which configure resource control settings for the processes of the service. If a service is requested under a certain name but no unit configuration file is found, systemd looks for a SysV init script by the same name (with the .service suffix removed) and dynamically creates a service unit from that script. This is useful for compatibility with SysV. Note that this compatibility is quite comprehensive but not 100%. For details about the incompatibilities, see the Incompatibilities with SysV document. Automatic Dependencies Services with Type=dbus set automatically acquire dependencies of type Requires= and After= on dbus.socket. Socket activated service are automatically ordered after their activated .socket units via an automatic After= dependency. Unless DefaultDependencies= is set to , service units will implicitly have dependencies of type Requires= and After= on sysinit.target, a dependency of type After= on basic.target as well as dependencies of type Conflicts= and Before= on shutdown.target. These ensure that normal service units pull in basic system initialization, and are terminated cleanly prior to system shutdown. Only services involved with early boot or late system shutdown should disable this option. Instanced service units (i.e. service units with an @ in their name) are assigned by default a per-template slice unit (see systemd.slice5), named after the template unit, containing all instances of the specific template. This slice is normally stopped at shutdown, together with all template instances. If that is not desired, set DefaultDependencies=no in the template unit, and either define your own per-template slice unit file that also sets DefaultDependencies=no, or set Slice=system.slice (or another suitable slice) in the template unit. Also see systemd.resource-control5. Additional implicit dependencies may be added as result of execution and resource control parameters as documented in systemd.exec5 and systemd.resource-control5. Options Service files must include a [Service] section, which carries information about the service and the process it supervises. A number of options that may be used in this section are shared with other unit types. These options are documented in systemd.exec5 and systemd.kill5. The options specific to the [Service] section of service units are the following: Type= Configures the process start-up type for this service unit. One of , , , , or . If set to (the default if neither Type= nor BusName=, but ExecStart= are specified), it is expected that the process configured with ExecStart= is the main process of the service. In this mode, if the process offers functionality to other processes on the system, its communication channels should be installed before the daemon is started up (e.g. sockets set up by systemd, via socket activation), as systemd will immediately proceed starting follow-up units. If set to , it is expected that the process configured with ExecStart= will call fork() as part of its start-up. The parent process is expected to exit when start-up is complete and all communication channels are set up. The child continues to run as the main daemon process. This is the behavior of traditional UNIX daemons. If this setting is used, it is recommended to also use the PIDFile= option, so that systemd can identify the main process of the daemon. systemd will proceed with starting follow-up units as soon as the parent process exits. Behavior of is similar to ; however, it is expected that the process has to exit before systemd starts follow-up units. RemainAfterExit= is particularly useful for this type of service. This is the implied default if neither Type= or ExecStart= are specified. Behavior of is similar to ; however, it is expected that the daemon acquires a name on the D-Bus bus, as configured by BusName=. systemd will proceed with starting follow-up units after the D-Bus bus name has been acquired. Service units with this option configured implicitly gain dependencies on the dbus.socket unit. This type is the default if BusName= is specified. Behavior of is similar to ; however, it is expected that the daemon sends a notification message via sd_notify3 or an equivalent call when it has finished starting up. systemd will proceed with starting follow-up units after this notification message has been sent. If this option is used, NotifyAccess= (see below) should be set to open access to the notification socket provided by systemd. If NotifyAccess= is not set, it will be implicitly set to . Note that currently Type= will not work if used in combination with PrivateNetwork=. Behavior of is very similar to ; however, actual execution of the service binary is delayed until all jobs are dispatched. This may be used to avoid interleaving of output of shell services with the status output on the console. RemainAfterExit= Takes a boolean value that specifies whether the service shall be considered active even when all its processes exited. Defaults to . GuessMainPID= Takes a boolean value that specifies whether systemd should try to guess the main PID of a service if it cannot be determined reliably. This option is ignored unless is set and is unset because for the other types or with an explicitly configured PID file, the main PID is always known. The guessing algorithm might come to incorrect conclusions if a daemon consists of more than one process. If the main PID cannot be determined, failure detection and automatic restarting of a service will not work reliably. Defaults to . PIDFile= Takes an absolute file name pointing to the PID file of this daemon. Use of this option is recommended for services where Type= is set to . systemd will read the PID of the main process of the daemon after start-up of the service. systemd will not write to the file configured here, although it will remove the file after the service has shut down if it still exists. BusName= Takes a D-Bus bus name that this service is reachable as. This option is mandatory for services where Type= is set to . BusPolicy= If specified, a custom kdbus endpoint will be created and installed as the default bus node for the service. Such a custom endpoint can hold an own set of policy rules that are enforced on top of the bus-wide ones. The custom endpoint is named after the service it was created for, and its node will be bind-mounted over the default bus node location, so the service can only access the bus through its own endpoint. Note that custom bus endpoints default to a "deny all" policy. Hence, if at least one BusPolicy= directive is given, you have to make sure to add explicit rules for everything the service should be able to do. The value of this directive is comprised of two parts; the bus name, and a verb to specify to granted access, which is one of , , or . implies , and implies both and . If multiple access levels are specified for the same bus name, the most powerful one takes effect. Examples: BusPolicy=org.freedesktop.systemd1 talk BusPolicy=org.foo.bar see This option is only available on kdbus enabled systems. ExecStart= Commands with their arguments that are executed when this service is started. The value is split into zero or more command lines according to the rules described below (see section "Command Lines" below). When Type= is not , only one command may and must be given. When Type=oneshot is used, zero or more commands may be specified. This can be specified by providing multiple command lines in the same directive, or alternatively, this directive may be specified more than once with the same effect. If the empty string is assigned to this option, the list of commands to start is reset, prior assignments of this option will have no effect. If no ExecStart= is specified, then the service must have RemainAfterExit=yes set. For each of the specified commands, the first argument must be an absolute path to an executable. Optionally, if this file name is prefixed with @, the second token will be passed as argv[0] to the executed process, followed by the further arguments specified. If the absolute filename is prefixed with -, an exit code of the command normally considered a failure (i.e. non-zero exit status or abnormal exit due to signal) is ignored and considered success. If both - and @ are used, they can appear in either order. If more than one command is specified, the commands are invoked sequentially in the order they appear in the unit file. If one of the commands fails (and is not prefixed with -), other lines are not executed, and the unit is considered failed. Unless Type=forking is set, the process started via this command line will be considered the main process of the daemon. ExecStartPre= ExecStartPost= Additional commands that are executed before or after the command in ExecStart=, respectively. Syntax is the same as for ExecStart=, except that multiple command lines are allowed and the commands are executed one after the other, serially. If any of those commands (not prefixed with -) fail, the rest are not executed and the unit is considered failed. ExecStart= commands are only run after all ExecStartPre= commands that were not prefixed with a - exit successfully. ExecStartPost= commands are only run after the service has started successfully, as determined by Type= (i.e. the process has been started for Type=simple or Type=idle, the process exits successfully for Type=oneshot, the initial process exits successfully for Type=forking, READY=1 is sent for Type=notify, or the BusName= has been taken for Type=dbus). Note that ExecStartPre= may not be used to start long-running processes. All processes forked off by processes invoked via ExecStartPre= will be killed before the next service process is run. Note that if any of the commands specified in ExecStartPre=, ExecStart=, or ExecStartPost= fail (and are not prefixed with -, see above) or time out before the service is fully up, execution continues with commands specified in ExecStopPost=, the commands in ExecStop= are skipped. ExecReload= Commands to execute to trigger a configuration reload in the service. This argument takes multiple command lines, following the same scheme as described for ExecStart= above. Use of this setting is optional. Specifier and environment variable substitution is supported here following the same scheme as for ExecStart=. One additional, special environment variable is set: if known, $MAINPID is set to the main process of the daemon, and may be used for command lines like the following: /bin/kill -HUP $MAINPID Note however that reloading a daemon by sending a signal (as with the example line above) is usually not a good choice, because this is an asynchronous operation and hence not suitable to order reloads of multiple services against each other. It is strongly recommended to set ExecReload= to a command that not only triggers a configuration reload of the daemon, but also synchronously waits for it to complete. ExecStop= Commands to execute to stop the service started via ExecStart=. This argument takes multiple command lines, following the same scheme as described for ExecStart= above. Use of this setting is optional. After the commands configured in this option are run, all processes remaining for a service are terminated according to the KillMode= setting (see systemd.kill5). If this option is not specified, the process is terminated by sending the signal specified in KillSignal= when service stop is requested. Specifier and environment variable substitution is supported (including $MAINPID, see above). Note that it is usually not sufficient to specify a command for this setting that only asks the service to terminate (for example, by queuing some form of termination signal for it), but does not wait for it to do so. Since the remaining processes of the services are killed using SIGKILL immediately after the command exited, this would not result in a clean stop. The specified command should hence be a synchronous operation, not an asynchronous one. Note that the commands specified in ExecStop= are only executed when the service started successfuly first. They are not invoked if the service was never started at all, or in case its start-up failed, for example because any of the commands specified in ExecStart=, ExecStartPre= or ExecStartPost= failed (and weren't prefixed with -, see above) or timed out. Use ExecStopPost= to invoke commands when a service failed to start up correctly and is shut down again. It is recommended to use this setting for commands that communicate with the service requesting clean termination. When the commands specified with this option are executed it should be assumed that the service is still fully up and is able to react correctly to all commands. For post-mortem clean-up steps use ExecStopPost= instead. ExecStopPost= Additional commands that are executed after the service is stopped. This includes cases where the commands configured in ExecStop= were used, where the service does not have any ExecStop= defined, or where the service exited unexpectedly. This argument takes multiple command lines, following the same scheme as described for ExecStart=. Use of these settings is optional. Specifier and environment variable substitution is supported. Note that – unlike ExecStop= – commands specified with this setting are invoked when a service failed to start up correctly and is shut down again. It is recommended to use this setting for clean-up operations that shall be executed even when the service failed to start up correctly. Commands configured with this setting need to be able to operate even if the service failed starting up half-way and left incompletely initialized data around. As the service's processes have been terminated already when the commands specified with this setting are executed they should not attempt to communicate with them. RestartSec= Configures the time to sleep before restarting a service (as configured with Restart=). Takes a unit-less value in seconds, or a time span value such as "5min 20s". Defaults to 100ms. TimeoutStartSec= Configures the time to wait for start-up. If a daemon service does not signal start-up completion within the configured time, the service will be considered failed and will be shut down again. Takes a unit-less value in seconds, or a time span value such as "5min 20s". Pass infinity to disable the timeout logic. Defaults to DefaultTimeoutStartSec= from the manager configuration file, except when Type=oneshot is used, in which case the timeout is disabled by default (see systemd-system.conf5). TimeoutStopSec= Configures the time to wait for stop. If a service is asked to stop, but does not terminate in the specified time, it will be terminated forcibly via SIGTERM, and after another timeout of equal duration with SIGKILL (see KillMode= in systemd.kill5). Takes a unit-less value in seconds, or a time span value such as "5min 20s". Pass infinity to disable the timeout logic. Defaults to DefaultTimeoutStopSec= from the manager configuration file (see systemd-system.conf5). TimeoutSec= A shorthand for configuring both TimeoutStartSec= and TimeoutStopSec= to the specified value. RuntimeMaxSec= Configures a maximum time for the service to run. If this is used and the service has been active for longer than the specified time it is terminated and put into a failure state. Note that this setting does not have any effect on Type=oneshot services, as they terminate immediately after activation completed. Pass infinity (the default) to configure no runtime limit. WatchdogSec= Configures the watchdog timeout for a service. The watchdog is activated when the start-up is completed. The service must call sd_notify3 regularly with WATCHDOG=1 (i.e. the "keep-alive ping"). If the time between two such calls is larger than the configured time, then the service is placed in a failed state and it will be terminated with SIGABRT. By setting Restart= to , , or , the service will be automatically restarted. The time configured here will be passed to the executed service process in the WATCHDOG_USEC= environment variable. This allows daemons to automatically enable the keep-alive pinging logic if watchdog support is enabled for the service. If this option is used, NotifyAccess= (see below) should be set to open access to the notification socket provided by systemd. If NotifyAccess= is not set, it will be implicitly set to . Defaults to 0, which disables this feature. The service can check whether the service manager expects watchdog keep-alive notifications. See sd_watchdog_enabled3 for details. sd_event_set_watchdog3 may be used to enable automatic watchdog notification support. Restart= Configures whether the service shall be restarted when the service process exits, is killed, or a timeout is reached. The service process may be the main service process, but it may also be one of the processes specified with ExecStartPre=, ExecStartPost=, ExecStop=, ExecStopPost=, or ExecReload=. When the death of the process is a result of systemd operation (e.g. service stop or restart), the service will not be restarted. Timeouts include missing the watchdog "keep-alive ping" deadline and a service start, reload, and stop operation timeouts. Takes one of , , , , , , or . If set to (the default), the service will not be restarted. If set to , it will be restarted only when the service process exits cleanly. In this context, a clean exit means an exit code of 0, or one of the signals SIGHUP, SIGINT, SIGTERM or SIGPIPE, and additionally, exit statuses and signals specified in SuccessExitStatus=. If set to , the service will be restarted when the process exits with a non-zero exit code, is terminated by a signal (including on core dump, but excluding the aforementioned four signals), when an operation (such as service reload) times out, and when the configured watchdog timeout is triggered. If set to , the service will be restarted when the process is terminated by a signal (including on core dump, excluding the aforementioned four signals), when an operation times out, or when the watchdog timeout is triggered. If set to , the service will be restarted only if the service process exits due to an uncaught signal not specified as a clean exit status. If set to , the service will be restarted only if the watchdog timeout for the service expires. If set to , the service will be restarted regardless of whether it exited cleanly or not, got terminated abnormally by a signal, or hit a timeout. Exit causes and the effect of the <varname>Restart=</varname> settings on them Restart settings/Exit causes Clean exit code or signal X X Unclean exit code X X Unclean signal X X X X Timeout X X X Watchdog X X X X
As exceptions to the setting above, the service will not be restarted if the exit code or signal is specified in RestartPreventExitStatus= (see below). Also, the services will always be restarted if the exit code or signal is specified in RestartForceExitStatus= (see below). Setting this to is the recommended choice for long-running services, in order to increase reliability by attempting automatic recovery from errors. For services that shall be able to terminate on their own choice (and avoid immediate restarting), is an alternative choice.
SuccessExitStatus= Takes a list of exit status definitions that, when returned by the main service process, will be considered successful termination, in addition to the normal successful exit code 0 and the signals SIGHUP, SIGINT, SIGTERM, and SIGPIPE. Exit status definitions can either be numeric exit codes or termination signal names, separated by spaces. For example: SuccessExitStatus=1 2 8 SIGKILL ensures that exit codes 1, 2, 8 and the termination signal SIGKILL are considered clean service terminations. Note that if a process has a signal handler installed and exits by calling _exit2 in response to a signal, the information about the signal is lost. Programs should instead perform cleanup and kill themselves with the same signal instead. See Proper handling of SIGINT/SIGQUIT — How to be a proper program. This option may appear more than once, in which case the list of successful exit statuses is merged. If the empty string is assigned to this option, the list is reset, all prior assignments of this option will have no effect. RestartPreventExitStatus= Takes a list of exit status definitions that, when returned by the main service process, will prevent automatic service restarts, regardless of the restart setting configured with Restart=. Exit status definitions can either be numeric exit codes or termination signal names, and are separated by spaces. Defaults to the empty list, so that, by default, no exit status is excluded from the configured restart logic. For example: RestartPreventExitStatus=1 6 SIGABRT ensures that exit codes 1 and 6 and the termination signal SIGABRT will not result in automatic service restarting. This option may appear more than once, in which case the list of restart-preventing statuses is merged. If the empty string is assigned to this option, the list is reset and all prior assignments of this option will have no effect. RestartForceExitStatus= Takes a list of exit status definitions that, when returned by the main service process, will force automatic service restarts, regardless of the restart setting configured with Restart=. The argument format is similar to RestartPreventExitStatus=. PermissionsStartOnly= Takes a boolean argument. If true, the permission-related execution options, as configured with User= and similar options (see systemd.exec5 for more information), are only applied to the process started with ExecStart=, and not to the various other ExecStartPre=, ExecStartPost=, ExecReload=, ExecStop=, and ExecStopPost= commands. If false, the setting is applied to all configured commands the same way. Defaults to false. RootDirectoryStartOnly= Takes a boolean argument. If true, the root directory, as configured with the RootDirectory= option (see systemd.exec5 for more information), is only applied to the process started with ExecStart=, and not to the various other ExecStartPre=, ExecStartPost=, ExecReload=, ExecStop=, and ExecStopPost= commands. If false, the setting is applied to all configured commands the same way. Defaults to false. NonBlocking= Set the O_NONBLOCK flag for all file descriptors passed via socket-based activation. If true, all file descriptors >= 3 (i.e. all except stdin, stdout, and stderr) will have the O_NONBLOCK flag set and hence are in non-blocking mode. This option is only useful in conjunction with a socket unit, as described in systemd.socket5. Defaults to false. NotifyAccess= Controls access to the service status notification socket, as accessible via the sd_notify3 call. Takes one of (the default), or . If , no daemon status updates are accepted from the service processes, all status update messages are ignored. If , only service updates sent from the main process of the service are accepted. If , all services updates from all members of the service's control group are accepted. This option should be set to open access to the notification socket when using Type=notify or WatchdogSec= (see above). If those options are used but NotifyAccess= is not configured, it will be implicitly set to . Sockets= Specifies the name of the socket units this service shall inherit socket file descriptors from when the service is started. Normally, it should not be necessary to use this setting, as all socket file descriptors whose unit shares the same name as the service (subject to the different unit name suffix of course) are passed to the spawned process. Note that the same socket file descriptors may be passed to multiple processes simultaneously. Also note that a different service may be activated on incoming socket traffic than the one which is ultimately configured to inherit the socket file descriptors. Or, in other words: the Service= setting of .socket units does not have to match the inverse of the Sockets= setting of the .service it refers to. This option may appear more than once, in which case the list of socket units is merged. If the empty string is assigned to this option, the list of sockets is reset, and all prior uses of this setting will have no effect. FailureAction= Configure the action to take when the service enters a failed state. Takes the same values as the unit setting StartLimitAction= and executes the same actions (see systemd.unit5). Defaults to . FileDescriptorStoreMax= Configure how many file descriptors may be stored in the service manager for the service using sd_pid_notify_with_fds3's FDSTORE=1 messages. This is useful for implementing service restart schemes where the state is serialized to /run and the file descriptors passed to the service manager, to allow restarts without losing state. Defaults to 0, i.e. no file descriptors may be stored in the service manager by default. All file descriptors passed to the service manager from a specific service are passed back to the service's main process on the next service restart. Any file descriptors passed to the service manager are automatically closed when POLLHUP or POLLERR is seen on them, or when the service is fully stopped and no job queued or being executed for it. USBFunctionDescriptors= Configure the location of a file containing USB FunctionFS descriptors, for implementation of USB gadget functions. This is used only in conjunction with a socket unit with ListenUSBFunction= configured. The contents of this file are written to the ep0 file after it is opened. USBFunctionStrings= Configure the location of a file containing USB FunctionFS strings. Behavior is similar to USBFunctionDescriptors= above.
Check systemd.exec5 and systemd.kill5 for more settings.
Command lines This section describes command line parsing and variable and specifier substitutions for ExecStart=, ExecStartPre=, ExecStartPost=, ExecReload=, ExecStop=, and ExecStopPost= options. Multiple command lines may be concatenated in a single directive by separating them with semicolons (these semicolons must be passed as separate words). Lone semicolons may be escaped as \;. Each command line is split on whitespace, with the first item being the command to execute, and the subsequent items being the arguments. Double quotes ("...") and single quotes ('...') may be used, in which case everything until the next matching quote becomes part of the same argument. C-style escapes are also supported. The table below contains the list of allowed escape patterns. Only patterns which match the syntax in the table are allowed; others will result in an error, and must be escaped by doubling the backslash. Quotes themselves are removed after parsing and escape sequences substituted. In addition, a trailing backslash (\) may be used to merge lines. This syntax is intended to be very similar to shell syntax, but only the meta-characters and expansions described in the following paragraphs are understood. Specifically, redirection using <, <<, >, and >>, pipes using |, running programs in the background using &, and other elements of shell syntax are not supported. The command to execute must be an absolute path name. It may contain spaces, but control characters are not allowed. The command line accepts % specifiers as described in systemd.unit5. Note that the first argument of the command line (i.e. the program to execute) may not include specifiers. Basic environment variable substitution is supported. Use ${FOO} as part of a word, or as a word of its own, on the command line, in which case it will be replaced by the value of the environment variable including all whitespace it contains, resulting in a single argument. Use $FOO as a separate word on the command line, in which case it will be replaced by the value of the environment variable split at whitespace, resulting in zero or more arguments. For this type of expansion, quotes are respected when splitting into words, and afterwards removed. Example: Environment="ONE=one" 'TWO=two two' ExecStart=/bin/echo $ONE $TWO ${TWO} This will execute /bin/echo with four arguments: one, two, two, and two two. Example: Environment=ONE='one' "TWO='two two' too" THREE= ExecStart=/bin/echo ${ONE} ${TWO} ${THREE} ExecStart=/bin/echo $ONE $TWO $THREE This results in echo being called twice, the first time with arguments 'one', 'two two' too, , and the second time with arguments one, two two, too. To pass a literal dollar sign, use $$. Variables whose value is not known at expansion time are treated as empty strings. Note that the first argument (i.e. the program to execute) may not be a variable. Variables to be used in this fashion may be defined through Environment= and EnvironmentFile=. In addition, variables listed in the section "Environment variables in spawned processes" in systemd.exec5, which are considered "static configuration", may be used (this includes e.g. $USER, but not $TERM). Note that shell command lines are not directly supported. If shell command lines are to be used, they need to be passed explicitly to a shell implementation of some kind. Example: ExecStart=/bin/sh -c 'dmesg | tac' Example: ExecStart=/bin/echo one ; /bin/echo "two two" This will execute /bin/echo two times, each time with one argument: one and two two, respectively. Because two commands are specified, Type=oneshot must be used. Example: ExecStart=/bin/echo / >/dev/null & \; \ /bin/ls This will execute /bin/echo with five arguments: /, >/dev/null, &, ;, and /bin/ls. C escapes supported in command lines and environment variables Literal Actual value \a bell \b backspace \f form feed \n newline \r carriage return \t tab \v vertical tab \\ backslash \" double quotation mark \' single quotation mark \s space \xxx character number xx in hexadecimal encoding \nnn character number nnn in octal encoding
Examples Simple service The following unit file creates a service that will execute /usr/sbin/foo-daemon. Since no Type= is specified, the default Type= will be assumed. systemd will assume the unit to be started immediately after the program has begun executing. [Unit] Description=Foo [Service] ExecStart=/usr/sbin/foo-daemon [Install] WantedBy=multi-user.target Note that systemd assumes here that the process started by systemd will continue running until the service terminates. If the program daemonizes itself (i.e. forks), please use Type= instead. Since no ExecStop= was specified, systemd will send SIGTERM to all processes started from this service, and after a timeout also SIGKILL. This behavior can be modified, see systemd.kill5 for details. Note that this unit type does not include any type of notification when a service has completed initialization. For this, you should use other unit types, such as Type= if the service understands systemd's notification protocol, Type= if the service can background itself or Type= if the unit acquires a DBus name once initialization is complete. See below. Oneshot service Sometimes, units should just execute an action without keeping active processes, such as a filesystem check or a cleanup action on boot. For this, Type= exists. Units of this type will wait until the process specified terminates and then fall back to being inactive. The following unit will perform a cleanup action: [Unit] Description=Cleanup old Foo data [Service] Type=oneshot ExecStart=/usr/sbin/foo-cleanup [Install] WantedBy=multi-user.target Note that systemd will consider the unit to be in the state "starting" until the program has terminated, so ordered dependencies will wait for the program to finish before starting themselves. The unit will revert to the "inactive" state after the execution is done, never reaching the "active" state. That means another request to start the unit will perform the action again. Type= are the only service units that may have more than one ExecStart= specified. They will be executed in order until either they are all successful or one of them fails. Stoppable oneshot service Similarly to the oneshot services, there are sometimes units that need to execute a program to set up something and then execute another to shut it down, but no process remains active while they are considered "started". Network configuration can sometimes fall into this category. Another use case is if a oneshot service shall not be executed each time when they are pulled in as a dependency, but only the first time. For this, systemd knows the setting RemainAfterExit=, which causes systemd to consider the unit to be active if the start action exited successfully. This directive can be used with all types, but is most useful with Type= and Type=. With Type=, systemd waits until the start action has completed before it considers the unit to be active, so dependencies start only after the start action has succeeded. With Type=, dependencies will start immediately after the start action has been dispatched. The following unit provides an example for a simple static firewall. [Unit] Description=Simple firewall [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/sbin/simple-firewall-start ExecStop=/usr/local/sbin/simple-firewall-stop [Install] WantedBy=multi-user.target Since the unit is considered to be running after the start action has exited, invoking systemctl start on that unit again will cause no action to be taken. Traditional forking services Many traditional daemons/services background (i.e. fork, daemonize) themselves when starting. Set Type= in the service's unit file to support this mode of operation. systemd will consider the service to be in the process of initialization while the original program is still running. Once it exits successfully and at least a process remains (and RemainAfterExit=), the service is considered started. Often, a traditional daemon only consists of one process. Therefore, if only one process is left after the original process terminates, systemd will consider that process the main process of the service. In that case, the $MAINPID variable will be available in ExecReload=, ExecStop=, etc. In case more than one process remains, systemd will be unable to determine the main process, so it will not assume there is one. In that case, $MAINPID will not expand to anything. However, if the process decides to write a traditional PID file, systemd will be able to read the main PID from there. Please set PIDFile= accordingly. Note that the daemon should write that file before finishing with its initialization. Otherwise, systemd might try to read the file before it exists. The following example shows a simple daemon that forks and just starts one process in the background: [Unit] Description=Some simple daemon [Service] Type=forking ExecStart=/usr/sbin/my-simple-daemon -d [Install] WantedBy=multi-user.target Please see systemd.kill5 for details on how you can influence the way systemd terminates the service. DBus services For services that acquire a name on the DBus system bus, use Type= and set BusName= accordingly. The service should not fork (daemonize). systemd will consider the service to be initialized once the name has been acquired on the system bus. The following example shows a typical DBus service: [Unit] Description=Simple DBus service [Service] Type=dbus BusName=org.example.simple-dbus-service ExecStart=/usr/sbin/simple-dbus-service [Install] WantedBy=multi-user.target For bus-activatable services, do not include a [Install] section in the systemd service file, but use the SystemdService= option in the corresponding DBus service file, for example (/usr/share/dbus-1/system-services/org.example.simple-dbus-service.service): [D-BUS Service] Name=org.example.simple-dbus-service Exec=/usr/sbin/simple-dbus-service User=root SystemdService=simple-dbus-service.service Please see systemd.kill5 for details on how you can influence the way systemd terminates the service. Services that notify systemd about their initialization Type= services are really easy to write, but have the major disadvantage of systemd not being able to tell when initialization of the given service is complete. For this reason, systemd supports a simple notification protocol that allows daemons to make systemd aware that they are done initializing. Use Type= for this. A typical service file for such a daemon would look like this: [Unit] Description=Simple notifying service [Service] Type=notify ExecStart=/usr/sbin/simple-notifying-service [Install] WantedBy=multi-user.target Note that the daemon has to support systemd's notification protocol, else systemd will think the service has not started yet and kill it after a timeout. For an example of how to update daemons to support this protocol transparently, take a look at sd_notify3. systemd will consider the unit to be in the 'starting' state until a readiness notification has arrived. Please see systemd.kill5 for details on how you can influence the way systemd terminates the service. See Also systemd1, systemctl1, systemd.unit5, systemd.exec5, systemd.resource-control5, systemd.kill5, systemd.directives7
systemd-229/man/systemd.slice.xml000066400000000000000000000130651265713322000171510ustar00rootroot00000000000000 systemd.slice systemd Developer Lennart Poettering lennart@poettering.net systemd.slice 5 systemd.slice Slice unit configuration slice.slice Description A unit configuration file whose name ends in .slice encodes information about a slice which is a concept for hierarchically managing resources of a group of processes. This management is performed by creating a node in the Linux Control Group (cgroup) tree. Units that manage processes (primarily scope and service units) may be assigned to a specific slice. For each slice, certain resource limits may be set that apply to all processes of all units contained in that slice. Slices are organized hierarchically in a tree. The name of the slice encodes the location in the tree. The name consists of a dash-separated series of names, which describes the path to the slice from the root slice. The root slice is named, -.slice. Example: foo-bar.slice is a slice that is located within foo.slice, which in turn is located in the root slice -.slice. By default, service and scope units are placed in system.slice, virtual machines and containers registered with systemd-machined1 are found in machine.slice, and user sessions handled by systemd-logind1 in user.slice. See systemd.special5 for more information. See systemd.unit5 for the common options of all unit configuration files. The common configuration items are configured in the generic [Unit] and [Install] sections. The slice specific configuration options are configured in the [Slice] section. Currently, only generic resource control settings as described in systemd.resource-control5 are allowed. See the New Control Group Interfaces for an introduction on how to make use of slice units from programs. Automatic Dependencies Slice units automatically gain dependencies of type After= and Requires= on their immediate parent slice unit. Unless DefaultDependencies=false is used, slice units will implicitly have dependencies of type Conflicts= and Before= on shutdown.target. These ensure that slice units are removed prior to system shutdown. Only slice units involved with early boot or late system shutdown should disable this option. See Also systemd1, systemd.unit5, systemd.resource-control5, systemd.service5, systemd.scope5, systemd.special7, systemd.directives7 systemd-229/man/systemd.socket.xml000066400000000000000000001225021265713322000173370ustar00rootroot00000000000000 systemd.socket systemd Developer Lennart Poettering lennart@poettering.net systemd.socket 5 systemd.socket Socket unit configuration socket.socket Description A unit configuration file whose name ends in .socket encodes information about an IPC or network socket or a file system FIFO controlled and supervised by systemd, for socket-based activation. This man page lists the configuration options specific to this unit type. See systemd.unit5 for the common options of all unit configuration files. The common configuration items are configured in the generic [Unit] and [Install] sections. The socket specific configuration options are configured in the [Socket] section. Additional options are listed in systemd.exec5, which define the execution environment the , , and commands are executed in, and in systemd.kill5, which define the way the processes are terminated, and in systemd.resource-control5, which configure resource control settings for the processes of the socket. For each socket file, a matching service file must exist, describing the service to start on incoming traffic on the socket (see systemd.service5 for more information about .service files). The name of the .service unit is by default the same as the name of the .socket unit, but can be altered with the option described below. Depending on the setting of the option described below, this .service unit must either be named like the .socket unit, but with the suffix replaced, unless overridden with ; or it must be a template unit named the same way. Example: a socket file foo.socket needs a matching service foo.service if is set. If is set, a service template file foo@.service must exist from which services are instantiated for each incoming connection. Unless DefaultDependencies= is set to , socket units will implicitly have dependencies of type Requires= and After= on sysinit.target as well as dependencies of type Conflicts= and Before= on shutdown.target. These ensure that socket units pull in basic system initialization, and are terminated cleanly prior to system shutdown. Only sockets involved with early boot or late system shutdown should disable this option. Socket units will have a Before= dependency on the service which they trigger added implicitly. No implicit WantedBy= or RequiredBy= dependency from the socket to the service is added. This means that the service may be started without the socket, in which case it must be able to open sockets by itself. To prevent this, an explicit Requires= dependency may be added. Socket units may be used to implement on-demand starting of services, as well as parallelized starting of services. See the blog stories linked at the end for an introduction. Note that the daemon software configured for socket activation with socket units needs to be able to accept sockets from systemd, either via systemd's native socket passing interface (see sd_listen_fds3 for details) or via the traditional inetd8-style socket passing (i.e. sockets passed in via standard input and output, using StandardInput=socket in the service file). Automatic Dependencies Socket units automatically gain a Before= dependency on the service units they activate. Socket units referring to file system paths (such as AF_UNIX sockets or FIFOs) implicitly gain Requires= and After= dependencies on all mount units necessary to access those paths. Socket units using the BindToDevice= setting automatically gain a BindsTo= and After= dependency on the device unit encapsulating the specified network interface. If DefaultDependencies=yes is set (the default), socket units automatically gain a Before= dependency on sockets.target. They also gain a pair of After= and Requires= dependency on sysinit.target, and a pair of Before= and Conflicts= dependencies on shutdown.target. These dependencies ensure that the socket unit is started before normal services at boot, and is stopped on shutdown. Additional implicit dependencies may be added as result of execution and resource control parameters as documented in systemd.exec5 and systemd.resource-control5. Options Socket files must include a [Socket] section, which carries information about the socket or FIFO it supervises. A number of options that may be used in this section are shared with other unit types. These options are documented in systemd.exec5 and systemd.kill5. The options specific to the [Socket] section of socket units are the following: ListenStream= ListenDatagram= ListenSequentialPacket= Specifies an address to listen on for a stream (SOCK_STREAM), datagram (SOCK_DGRAM), or sequential packet (SOCK_SEQPACKET) socket, respectively. The address can be written in various formats: If the address starts with a slash (/), it is read as file system socket in the AF_UNIX socket family. If the address starts with an at symbol (@), it is read as abstract namespace socket in the AF_UNIX family. The @ is replaced with a NUL character before binding. For details, see unix7. If the address string is a single number, it is read as port number to listen on via IPv6. Depending on the value of BindIPv6Only= (see below) this might result in the service being available via both IPv6 and IPv4 (default) or just via IPv6. If the address string is a string in the format v.w.x.y:z, it is read as IPv4 specifier for listening on an address v.w.x.y on a port z. If the address string is a string in the format [x]:y, it is read as IPv6 address x on a port y. Note that this might make the service available via IPv4, too, depending on the BindIPv6Only= setting (see below). Note that SOCK_SEQPACKET (i.e. ListenSequentialPacket=) is only available for AF_UNIX sockets. SOCK_STREAM (i.e. ListenStream=) when used for IP sockets refers to TCP sockets, SOCK_DGRAM (i.e. ListenDatagram=) to UDP. These options may be specified more than once, in which case incoming traffic on any of the sockets will trigger service activation, and all listed sockets will be passed to the service, regardless of whether there is incoming traffic on them or not. If the empty string is assigned to any of these options, the list of addresses to listen on is reset, all prior uses of any of these options will have no effect. It is also possible to have more than one socket unit for the same service when using Service=, and the service will receive all the sockets configured in all the socket units. Sockets configured in one unit are passed in the order of configuration, but no ordering between socket units is specified. If an IP address is used here, it is often desirable to listen on it before the interface it is configured on is up and running, and even regardless of whether it will be up and running at any point. To deal with this, it is recommended to set the FreeBind= option described below. ListenFIFO= Specifies a file system FIFO to listen on. This expects an absolute file system path as argument. Behavior otherwise is very similar to the ListenDatagram= directive above. ListenSpecial= Specifies a special file in the file system to listen on. This expects an absolute file system path as argument. Behavior otherwise is very similar to the ListenFIFO= directive above. Use this to open character device nodes as well as special files in /proc and /sys. ListenNetlink= Specifies a Netlink family to create a socket for to listen on. This expects a short string referring to the AF_NETLINK family name (such as audit or kobject-uevent) as argument, optionally suffixed by a whitespace followed by a multicast group integer. Behavior otherwise is very similar to the ListenDatagram= directive above. ListenMessageQueue= Specifies a POSIX message queue name to listen on. This expects a valid message queue name (i.e. beginning with /). Behavior otherwise is very similar to the ListenFIFO= directive above. On Linux message queue descriptors are actually file descriptors and can be inherited between processes. ListenUSBFunction= Specifies a USB FunctionFS endpoint location to listen on, for implementation of USB gadget functions. This expects an absolute file system path as the argument. Behavior otherwise is very similar to the ListenFIFO= directive above. Use this to open the FunctionFS endpoint ep0. When using this option, the activated service has to have the USBFunctionDescriptors= and USBFunctionStrings= options set. SocketProtocol= Takes a one of or . Specifies a socket protocol (IPPROTO_UDPLITE) UDP-Lite (IPPROTO_SCTP) SCTP socket respectively. BindIPv6Only= Takes a one of , or . Controls the IPV6_V6ONLY socket option (see ipv67 for details). If , IPv6 sockets bound will be accessible via both IPv4 and IPv6. If , they will be accessible via IPv6 only. If (which is the default, surprise!), the system wide default setting is used, as controlled by /proc/sys/net/ipv6/bindv6only, which in turn defaults to the equivalent of . Backlog= Takes an unsigned integer argument. Specifies the number of connections to queue that have not been accepted yet. This setting matters only for stream and sequential packet sockets. See listen2 for details. Defaults to SOMAXCONN (128). BindToDevice= Specifies a network interface name to bind this socket to. If set, traffic will only be accepted from the specified network interfaces. This controls the SO_BINDTODEVICE socket option (see socket7 for details). If this option is used, an automatic dependency from this socket unit on the network interface device unit (systemd.device5 is created. Note that setting this parameter might result in additional dependencies to be added to the unit (see above). SocketUser= SocketGroup= Takes a UNIX user/group name. When specified, all AF_UNIX sockets and FIFO nodes in the file system are owned by the specified user and group. If unset (the default), the nodes are owned by the root user/group (if run in system context) or the invoking user/group (if run in user context). If only a user is specified but no group, then the group is derived from the user's default group. SocketMode= If listening on a file system socket or FIFO, this option specifies the file system access mode used when creating the file node. Takes an access mode in octal notation. Defaults to 0666. DirectoryMode= If listening on a file system socket or FIFO, the parent directories are automatically created if needed. This option specifies the file system access mode used when creating these directories. Takes an access mode in octal notation. Defaults to 0755. Accept= Takes a boolean argument. If true, a service instance is spawned for each incoming connection and only the connection socket is passed to it. If false, all listening sockets themselves are passed to the started service unit, and only one service unit is spawned for all connections (also see above). This value is ignored for datagram sockets and FIFOs where a single service unit unconditionally handles all incoming traffic. Defaults to . For performance reasons, it is recommended to write new daemons only in a way that is suitable for . A daemon listening on an AF_UNIX socket may, but does not need to, call close2 on the received socket before exiting. However, it must not unlink the socket from a file system. It should not invoke shutdown2 on sockets it got with Accept=false, but it may do so for sockets it got with Accept=true set. Setting Accept=true is mostly useful to allow daemons designed for usage with inetd8 to work unmodified with systemd socket activation. For IPv4 and IPv6 connections, the REMOTE_ADDR environment variable will contain the remote IP address, and REMOTE_PORT will contain the remote port. This is the same as the format used by CGI. For SOCK_RAW, the port is the IP protocol. Writable= Takes a boolean argument. May only be used in conjunction with ListenSpecial=. If true, the specified special file is opened in read-write mode, if false, in read-only mode. Defaults to false. MaxConnections= The maximum number of connections to simultaneously run services instances for, when is set. If more concurrent connections are coming in, they will be refused until at least one existing connection is terminated. This setting has no effect on sockets configured with or datagram sockets. Defaults to 64. KeepAlive= Takes a boolean argument. If true, the TCP/IP stack will send a keep alive message after 2h (depending on the configuration of /proc/sys/net/ipv4/tcp_keepalive_time) for all TCP streams accepted on this socket. This controls the SO_KEEPALIVE socket option (see socket7 and the TCP Keepalive HOWTO for details.) Defaults to . KeepAliveTimeSec= Takes time (in seconds) as argument. The connection needs to remain idle before TCP starts sending keepalive probes. This controls the TCP_KEEPIDLE socket option (see socket7 and the TCP Keepalive HOWTO for details.) Defaults value is 7200 seconds (2 hours). KeepAliveIntervalSec= Takes time (in seconds) as argument between individual keepalive probes, if the socket option SO_KEEPALIVE has been set on this socket. This controls the TCP_KEEPINTVL socket option (see socket7 and the TCP Keepalive HOWTO for details.) Defaults value is 75 seconds. KeepAliveProbes= Takes an integer as argument. It is the number of unacknowledged probes to send before considering the connection dead and notifying the application layer. This controls the TCP_KEEPCNT socket option (see socket7 and the TCP Keepalive HOWTO for details.) Defaults value is 9. NoDelay= Takes a boolean argument. TCP Nagle's algorithm works by combining a number of small outgoing messages, and sending them all at once. This controls the TCP_NODELAY socket option (see tcp7 Defaults to . Priority= Takes an integer argument controlling the priority for all traffic sent from this socket. This controls the SO_PRIORITY socket option (see socket7 for details.). DeferAcceptSec= Takes time (in seconds) as argument. If set, the listening process will be awakened only when data arrives on the socket, and not immediately when connection is established. When this option is set, the TCP_DEFER_ACCEPT socket option will be used (see tcp7), and the kernel will ignore initial ACK packets without any data. The argument specifies the approximate amount of time the kernel should wait for incoming data before falling back to the normal behavior of honouring empty ACK packets. This option is beneficial for protocols where the client sends the data first (e.g. HTTP, in contrast to SMTP), because the server process will not be woken up unnecessarily before it can take any action. If the client also uses the TCP_DEFER_ACCEPT option, the latency of the initial connection may be reduced, because the kernel will send data in the final packet establishing the connection (the third packet in the "three-way handshake"). Disabled by default. ReceiveBuffer= SendBuffer= Takes an integer argument controlling the receive or send buffer sizes of this socket, respectively. This controls the SO_RCVBUF and SO_SNDBUF socket options (see socket7 for details.). The usual suffixes K, M, G are supported and are understood to the base of 1024. IPTOS= Takes an integer argument controlling the IP Type-Of-Service field for packets generated from this socket. This controls the IP_TOS socket option (see ip7 for details.). Either a numeric string or one of , , or may be specified. IPTTL= Takes an integer argument controlling the IPv4 Time-To-Live/IPv6 Hop-Count field for packets generated from this socket. This sets the IP_TTL/IPV6_UNICAST_HOPS socket options (see ip7 and ipv67 for details.) Mark= Takes an integer value. Controls the firewall mark of packets generated by this socket. This can be used in the firewall logic to filter packets from this socket. This sets the SO_MARK socket option. See iptables8 for details. ReusePort= Takes a boolean value. If true, allows multiple bind2s to this TCP or UDP port. This controls the SO_REUSEPORT socket option. See socket7 for details. SmackLabel= SmackLabelIPIn= SmackLabelIPOut= Takes a string value. Controls the extended attributes security.SMACK64, security.SMACK64IPIN and security.SMACK64IPOUT, respectively, i.e. the security label of the FIFO, or the security label for the incoming or outgoing connections of the socket, respectively. See Smack.txt for details. SELinuxContextFromNet= Takes a boolean argument. When true, systemd will attempt to figure out the SELinux label used for the instantiated service from the information handed by the peer over the network. Note that only the security level is used from the information provided by the peer. Other parts of the resulting SELinux context originate from either the target binary that is effectively triggered by socket unit or from the value of the SELinuxContext= option. This configuration option only affects sockets with Accept= mode set to true. Also note that this option is useful only when MLS/MCS SELinux policy is deployed. Defaults to false. PipeSize= Takes a size in bytes. Controls the pipe buffer size of FIFOs configured in this socket unit. See fcntl2 for details. The usual suffixes K, M, G are supported and are understood to the base of 1024. MessageQueueMaxMessages=, MessageQueueMessageSize= These two settings take integer values and control the mq_maxmsg field or the mq_msgsize field, respectively, when creating the message queue. Note that either none or both of these variables need to be set. See mq_setattr3 for details. FreeBind= Takes a boolean value. Controls whether the socket can be bound to non-local IP addresses. This is useful to configure sockets listening on specific IP addresses before those IP addresses are successfully configured on a network interface. This sets the IP_FREEBIND socket option. For robustness reasons it is recommended to use this option whenever you bind a socket to a specific IP address. Defaults to . Transparent= Takes a boolean value. Controls the IP_TRANSPARENT socket option. Defaults to . Broadcast= Takes a boolean value. This controls the SO_BROADCAST socket option, which allows broadcast datagrams to be sent from this socket. Defaults to . PassCredentials= Takes a boolean value. This controls the SO_PASSCRED socket option, which allows AF_UNIX sockets to receive the credentials of the sending process in an ancillary message. Defaults to . PassSecurity= Takes a boolean value. This controls the SO_PASSSEC socket option, which allows AF_UNIX sockets to receive the security context of the sending process in an ancillary message. Defaults to . TCPCongestion= Takes a string value. Controls the TCP congestion algorithm used by this socket. Should be one of "westwood", "veno", "cubic", "lp" or any other available algorithm supported by the IP stack. This setting applies only to stream sockets. ExecStartPre= ExecStartPost= Takes one or more command lines, which are executed before or after the listening sockets/FIFOs are created and bound, respectively. The first token of the command line must be an absolute filename, then followed by arguments for the process. Multiple command lines may be specified following the same scheme as used for ExecStartPre= of service unit files. ExecStopPre= ExecStopPost= Additional commands that are executed before or after the listening sockets/FIFOs are closed and removed, respectively. Multiple command lines may be specified following the same scheme as used for ExecStartPre= of service unit files. TimeoutSec= Configures the time to wait for the commands specified in ExecStartPre=, ExecStartPost=, ExecStopPre= and ExecStopPost= to finish. If a command does not exit within the configured time, the socket will be considered failed and be shut down again. All commands still running will be terminated forcibly via SIGTERM, and after another delay of this time with SIGKILL. (See in systemd.kill5.) Takes a unit-less value in seconds, or a time span value such as "5min 20s". Pass 0 to disable the timeout logic. Defaults to DefaultTimeoutStartSec= from the manager configuration file (see systemd-system.conf5). Service= Specifies the service unit name to activate on incoming traffic. This setting is only allowed for sockets with Accept=no. It defaults to the service that bears the same name as the socket (with the suffix replaced). In most cases, it should not be necessary to use this option. Note that setting this parameter might result in additional dependencies to be added to the unit (see above). RemoveOnStop= Takes a boolean argument. If enabled, any file nodes created by this socket unit are removed when it is stopped. This applies to AF_UNIX sockets in the file system, POSIX message queues, FIFOs, as well as any symlinks to them configured with Symlinks=. Normally, it should not be necessary to use this option, and is not recommended as services might continue to run after the socket unit has been terminated and it should still be possible to communicate with them via their file system node. Defaults to off. Symlinks= Takes a list of file system paths. The specified paths will be created as symlinks to the AF_UNIX socket path or FIFO path of this socket unit. If this setting is used, only one AF_UNIX socket in the file system or one FIFO may be configured for the socket unit. Use this option to manage one or more symlinked alias names for a socket, binding their lifecycle together. Defaults to the empty list. FileDescriptorName= Assigns a name to all file descriptors this socket unit encapsulates. This is useful to help activated services identify specific file descriptors, if multiple fds are passed. Services may use the sd_listen_fds_with_names3 call to acquire the names configured for the received file descriptors. Names may contain any ASCII character, but must exclude control characters and :, and must be at most 255 characters in length. If this setting is not used, the file descriptor name defaults to the name of the socket unit, including its .socket suffix. Check systemd.exec5 and systemd.kill5 for more settings. See Also systemd1, systemctl1, systemd.unit5, systemd.exec5, systemd.kill5, systemd.resource-control5, systemd.service5, systemd.directives7, sd_listen_fds3, sd_listen_fds_with_names3 For more extensive descriptions see the "systemd for Developers" series: Socket Activation, Socket Activation, part II, Converting inetd Services, Socket Activated Internet Services and OS Containers. systemd-229/man/systemd.special.xml000066400000000000000000001175171265713322000175010ustar00rootroot00000000000000 systemd.special systemd Developer Lennart Poettering lennart@poettering.net systemd.special 7 systemd.special Special systemd units basic.target, bluetooth.target, ctrl-alt-del.target, cryptsetup.target, cryptsetup-pre.target, dbus.service, dbus.socket, default.target, display-manager.service, emergency.target, exit.target, final.target, getty.target, graphical.target, halt.target, hibernate.target, hybrid-sleep.target, initrd-fs.target, kbrequest.target, kexec.target, local-fs.target, local-fs-pre.target, multi-user.target, network.target, network-online.target, network-pre.target, nss-lookup.target, nss-user-lookup.target, paths.target, poweroff.target, printer.target, reboot.target, remote-fs.target, remote-fs-pre.target, rescue.target, initrd-root-fs.target, rpcbind.target, runlevel2.target, runlevel3.target, runlevel4.target, runlevel5.target, shutdown.target, sigpwr.target, sleep.target, slices.target, smartcard.target, sockets.target, sound.target, suspend.target, swap.target, sysinit.target, syslog.socket, system-update.target, time-sync.target, timers.target, umount.target, -.slice, system.slice, user.slice, machine.slice Description A few units are treated specially by systemd. They have special internal semantics and cannot be renamed. Special System Units basic.target A special target unit covering basic boot-up. systemd automatically adds dependencies of the types Requires= and After= for this target unit to all services (except for those with DefaultDependencies=no). Usually, this should pull-in all local mount points plus /var, /tmp and /var/tmp, swap devices, sockets, timers, path units and other basic initialization necessary for general purpose daemons. The mentioned mount points are special cased to allow them to be remote. This target usually does not pull in any non-target units directly, but rather does so indirectly via other early boot targets. It is instead meant as a synchronization point for late boot services. Refer to bootup7 for details on the targets involved. ctrl-alt-del.target systemd starts this target whenever Control+Alt+Del is pressed on the console. Usually, this should be aliased (symlinked) to reboot.target. cryptsetup.target A target that pulls in setup services for all encrypted block devices. dbus.service A special unit for the D-Bus bus daemon. As soon as this service is fully started up systemd will connect to it and register its service. dbus.socket A special unit for the D-Bus system bus socket. All units with Type=dbus automatically gain a dependency on this unit. default.target The default unit systemd starts at bootup. Usually, this should be aliased (symlinked) to multi-user.target or graphical.target. The default unit systemd starts at bootup can be overridden with the systemd.unit= kernel command line option. display-manager.service The display manager service. Usually, this should be aliased (symlinked) to gdm.service or a similar display manager service. emergency.target A special target unit that starts an emergency shell on the main console. This target does not pull in any serices or mounts. It is the most minimal version of starting the system in order to acquire an interactive shell; the only processes running are usually just the system manager (PID 1) and the shell process. This unit is supposed to be used with the kernel command line option systemd.unit=; it is also used when a file system check on a required file system fails, and boot-up cannot continue. Compare with rescue.target, which serves a similar purpose, but also starts the most basic services and mounts all file systems. Use the systemd.unit=emergency.target kernel command line option to boot into this mode. A short alias for this kernel command line option is emergency, for compatibility with SysV. In many ways booting into emergency.target is similar to the effect of booting with init=/bin/sh on the kernel command line, except that emergency mode provides you with the full system and service manager, and allows starting individual units in order to continue the boot process in steps. exit.target A special service unit for shutting down the system or user service manager. It is equivalent to poweroff.target on non-container systems, and also works in containers. systemd will start this unit when it receives a request to shut down over D-Bus or a SIGTERM or SIGINT signal when running as user service daemon. Normally, this (indirectly) pulls in shutdown.target, which in turn should be conflicted by all units that want to be scheduled for shutdown when the service manager starts to exit. final.target A special target unit that is used during the shutdown logic and may be used to pull in late services after all normal services are already terminated and all mounts unmounted. getty.target A special target unit that pulls in statically configured local TTY getty instances. graphical.target A special target unit for setting up a graphical login screen. This pulls in multi-user.target. Units that are needed for graphical logins shall add Wants= dependencies for their unit to this unit (or multi-user.target) during installation. This is best configured via WantedBy=graphical.target in the unit's [Install] section. hibernate.target A special target unit for hibernating the system. This pulls in sleep.target. hybrid-sleep.target A special target unit for hibernating and suspending the system at the same time. This pulls in sleep.target. halt.target A special target unit for shutting down and halting the system. Note that this target is distinct from poweroff.target in that it generally really just halts the system rather than powering it down. Applications wanting to halt the system should start this unit. initrd-fs.target systemd-fstab-generator3 automatically adds dependencies of type Before= to sysroot-usr.mount and all mount points found in /etc/fstab that have and not have mount options set. kbrequest.target systemd starts this target whenever Alt+ArrowUp is pressed on the console. This is a good candidate to be aliased (symlinked) to rescue.target. kexec.target A special target unit for shutting down and rebooting the system via kexec. Applications wanting to reboot the system with kexec should start this unit. local-fs.target systemd-fstab-generator3 automatically adds dependencies of type Before= to all mount units that refer to local mount points for this target unit. In addition, it adds dependencies of type Wants= to this target unit for those mounts listed in /etc/fstab that have the mount option set. multi-user.target A special target unit for setting up a multi-user system (non-graphical). This is pulled in by graphical.target. Units that are needed for a multi-user system shall add Wants= dependencies for their unit to this unit during installation. This is best configured via WantedBy=multi-user.target in the unit's [Install] section. network-online.target Units that strictly require a configured network connection should pull in network-online.target (via a Wants= type dependency) and order themselves after it. This target unit is intended to pull in a service that delays further execution until the network is sufficiently set up. What precisely this requires is left to the implementation of the network managing service. Note the distinction between this unit and network.target. This unit is an active unit (i.e. pulled in by the consumer rather than the provider of this functionality) and pulls in a service which possibly adds substantial delays to further execution. In contrast, network.target is a passive unit (i.e. pulled in by the provider of the functionality, rather than the consumer) that usually does not delay execution much. Usually, network.target is part of the boot of most systems, while network-online.target is not, except when at least one unit requires it. Also see Running Services After the Network is up for more information. All mount units for remote network file systems automatically pull in this unit, and order themselves after it. Note that networking daemons that simply provide functionality to other hosts generally do not need to pull this in. paths.target A special target unit that sets up all path units (see systemd.path5 for details) that shall be active after boot. It is recommended that path units installed by applications get pulled in via Wants= dependencies from this unit. This is best configured via a WantedBy=paths.target in the path unit's [Install] section. poweroff.target A special target unit for shutting down and powering off the system. Applications wanting to power off the system should start this unit. runlevel0.target is an alias for this target unit, for compatibility with SysV. reboot.target A special target unit for shutting down and rebooting the system. Applications wanting to reboot the system should start this unit. runlevel6.target is an alias for this target unit, for compatibility with SysV. remote-fs.target Similar to local-fs.target, but for remote mount points. systemd automatically adds dependencies of type After= for this target unit to all SysV init script service units with an LSB header referring to the $remote_fs facility. rescue.target A special target unit that pulls in the base system (including system mounts) and spawns a rescue shell. Isolate to this target in order to administer the system in single-user mode with all file systems mounted but with no services running, except for the most basic. Compare with emergency.target, which is much more reduced and does not provide the file systems or most basic services. runlevel1.target is an alias for this target unit, for compatibility with SysV. Use the systemd.unit=rescue.target kernel command line option to boot into this mode. A short alias for this kernel command line option is 1, for compatibility with SysV. initrd-root-fs.target systemd-fstab-generator3 automatically adds dependencies of type Before= to the sysroot.mount unit, which is generated from the kernel command line. runlevel2.target runlevel3.target runlevel4.target runlevel5.target These are targets that are called whenever the SysV compatibility code asks for runlevel 2, 3, 4, 5, respectively. It is a good idea to make this an alias for (i.e. symlink to) multi-user.target (for runlevel 2) or graphical.target (the others). shutdown.target A special target unit that terminates the services on system shutdown. Services that shall be terminated on system shutdown shall add Conflicts= dependencies to this unit for their service unit, which is implicitly done when DefaultDependencies=yes is set (the default). sigpwr.target A special target that is started when systemd receives the SIGPWR process signal, which is normally sent by the kernel or UPS daemons when power fails. sleep.target A special target unit that is pulled in by suspend.target, hibernate.target and hybrid-sleep.target and may be used to hook units into the sleep state logic. slices.target A special target unit that sets up all slice units (see systemd.slice5 for details) that shall be active after boot. By default the generic user.slice, system.slice, machines.slice slice units, as well as the the root slice unit -.slice are pulled in and ordered before this unit (see below). It's a good idea to add WantedBy=slices.target lines to the [Install] section of all slices units that may be installed dynamically. sockets.target A special target unit that sets up all socket units (see systemd.socket5 for details) that shall be active after boot. Services that can be socket-activated shall add Wants= dependencies to this unit for their socket unit during installation. This is best configured via a WantedBy=sockets.target in the socket unit's [Install] section. suspend.target A special target unit for suspending the system. This pulls in sleep.target. swap.target Similar to local-fs.target, but for swap partitions and swap files. sysinit.target This target pulls in the services required for system initialization. System services pulled in by this target should declare DefaultDependencies=no and specify all their dependencies manually, including access to anything more than a read only root filesystem. For details on the dependencies of this target, refer to bootup7. syslog.socket The socket unit syslog implementations should listen on. All userspace log messages will be made available on this socket. For more information about syslog integration, please consult the Syslog Interface document. system-update.target A special target unit that is used for off-line system updates. systemd-system-update-generator8 will redirect the boot process to this target if /system-update exists. For more information see the System Updates Specification. timers.target A special target unit that sets up all timer units (see systemd.timer5 for details) that shall be active after boot. It is recommended that timer units installed by applications get pulled in via Wants= dependencies from this unit. This is best configured via WantedBy=timers.target in the timer unit's [Install] section. umount.target A special target unit that unmounts all mount and automount points on system shutdown. Mounts that shall be unmounted on system shutdown shall add Conflicts dependencies to this unit for their mount unit, which is implicitly done when DefaultDependencies=yes is set (the default). Special System Units for Devices Some target units are automatically pulled in as devices of certain kinds show up in the system. These may be used to automatically activate various services based on the specific type of the available hardware. bluetooth.target This target is started automatically as soon as a Bluetooth controller is plugged in or becomes available at boot. This may be used to pull in Bluetooth management daemons dynamically when Bluetooth hardware is found. printer.target This target is started automatically as soon as a printer is plugged in or becomes available at boot. This may be used to pull in printer management daemons dynamically when printer hardware is found. smartcard.target This target is started automatically as soon as a smartcard controller is plugged in or becomes available at boot. This may be used to pull in smartcard management daemons dynamically when smartcard hardware is found. sound.target This target is started automatically as soon as a sound card is plugged in or becomes available at boot. This may be used to pull in audio management daemons dynamically when audio hardware is found. Special Passive System Units A number of special system targets are defined that can be used to properly order boot-up of optional services. These targets are generally not part of the initial boot transaction, unless they are explicitly pulled in by one of the implementing services. Note specifically that these passive target units are generally not pulled in by the consumer of a service, but by the provider of the service. This means: a consuming service should order itself after these targets (as appropriate), but not pull it in. A providing service should order itself before these targets (as appropriate) and pull it in (via a Wants= type dependency). Note that these passive units cannot be started manually, i.e. systemctl start time-sync.target will fail with an error. They can only be pulled in by dependency. This is enforced since they exist for ordering purposes only and thus are not useful as only unit within a transaction. cryptsetup-pre.target This passive target unit may be pulled in by services that want to run before any encrypted block device is set up. All encrypted block devices are set up after this target has been reached. Since the shutdown order is implicitly the reverse start-up order between units, this target is particularly useful to ensure that a service is shut down only after all encrypted block devices are fully stopped. local-fs-pre.target This target unit is automatically ordered before all local mount points marked with (see above). It can be used to execute certain units before all local mounts. network.target This unit is supposed to indicate when network functionality is available, but it is only very weakly defined what that is supposed to mean, with one exception: at shutdown, a unit that is ordered after network.target will be stopped before the network -- to whatever level it might be set up then -- is shut down. It is hence useful when writing service files that require network access on shutdown, which should order themselves after this target, but not pull it in. Also see Running Services After the Network is up for more information. Also see network-online.target described above. systemd automatically adds dependencies of type After= for this target unit to all SysV init script service units with an LSB header referring to the $network facility. network-pre.target This passive target unit may be pulled in by services that want to run before any network is set up, for example for the purpose of setting up a firewall. All network management software orders itself after this target, but does not pull it in. nss-lookup.target A target that should be used as synchronization point for all host/network name service lookups. Note that this is independent of user/group name lookups for which nss-user-lookup.target should be used. All services for which the availability of full host/network name resolution is essential should be ordered after this target, but not pull it in. systemd automatically adds dependencies of type After= for this target unit to all SysV init script service units with an LSB header referring to the $named facility. nss-user-lookup.target A target that should be used as synchronization point for all user/group name service lookups. Note that this is independent of host/network name lookups for which nss-lookup.target should be used. All services for which the availability of the full user/group database is essential should be ordered after this target, but not pull it in. Note that system users are always resolvable, and hence do not require any special ordering against this target. remote-fs-pre.target This target unit is automatically ordered before all remote mount point units (see above). It can be used to run certain units before the remote mounts are established. Note that this unit is generally not part of the initial transaction, unless the unit that wants to be ordered before all remote mounts pulls it in via a Wants= type dependency. If the unit wants to be pulled in by the first remote mount showing up, it should use network-online.target (see above). rpcbind.target The portmapper/rpcbind pulls in this target and orders itself before it, to indicate its availability. systemd automatically adds dependencies of type After= for this target unit to all SysV init script service units with an LSB header referring to the $portmap facility. time-sync.target Services responsible for synchronizing the system clock from a remote source (such as NTP client implementations) should pull in this target and order themselves before it. All services where correct time is essential should be ordered after this unit, but not pull it in. systemd automatically adds dependencies of type After= for this target unit to all SysV init script service units with an LSB header referring to the $time facility. Special User Units When systemd runs as a user instance, the following special units are available, which have similar definitions as their system counterparts: exit.target, default.target, shutdown.target, sockets.target, timers.target, paths.target, bluetooth.target, printer.target, smartcard.target, sound.target. Special Slice Units There are four .slice units which form the basis of the hierarchy for assignment of resources for services, users, and virtual machines or containers. -.slice The root slice is the root of the hierarchy. It usually does not contain units directly, but may be used to set defaults for the whole tree. system.slice By default, all system services started by systemd are found in this slice. user.slice By default, all user processes and services started on behalf of the user, including the per-user systemd instance are found in this slice. machine.slice By default, all virtual machines and containers registered with systemd-machined are found in this slice. See Also systemd1, systemd.unit5, systemd.service5, systemd.socket5, systemd.target5, systemd.slice5, bootup7, systemd-fstab-generator8 systemd-229/man/systemd.swap.xml000066400000000000000000000263011265713322000170210ustar00rootroot00000000000000 systemd.swap systemd Developer Lennart Poettering lennart@poettering.net systemd.swap 5 systemd.swap Swap unit configuration swap.swap Description A unit configuration file whose name ends in .swap encodes information about a swap device or file for memory paging controlled and supervised by systemd. This man page lists the configuration options specific to this unit type. See systemd.unit5 for the common options of all unit configuration files. The common configuration items are configured in the generic [Unit] and [Install] sections. The swap specific configuration options are configured in the [Swap] section. Additional options are listed in systemd.exec5, which define the execution environment the swapon8 binary is executed in, in systemd.kill5, which define the way the these processes are terminated, and in systemd.resource-control5, which configure resource control settings for these processes of the unit. Swap units must be named after the devices or files they control. Example: the swap device /dev/sda5 must be configured in a unit file dev-sda5.swap. For details about the escaping logic used to convert a file system path to a unit name, see systemd.unit5. Automatic Dependencies All swap units automatically get the BindsTo= and After= dependencies on the device units or the mount units of the files they are activated from. Swap units with DefaultDependencies= enabled implicitly acquire a Conflicts= and an After= dependency on umount.target so that they are deactivated at shutdown, unless DefaultDependencies=no is specified. Additional implicit dependencies may be added as result of execution and resource control parameters as documented in systemd.exec5 and systemd.resource-control5. <filename>fstab</filename> Swap units may either be configured via unit files, or via /etc/fstab (see fstab5 for details). Swaps listed in /etc/fstab will be converted into native units dynamically at boot and when the configuration of the system manager is reloaded. See systemd-fstab-generator8 for details about the conversion. If a swap device or file is configured in both /etc/fstab and a unit file, the configuration in the latter takes precedence. When reading /etc/fstab, a few special options are understood by systemd which influence how dependencies are created for swap units. With , the swap unit will not be added as a dependency for swap.target. This means that it will not be activated automatically during boot, unless it is pulled in by some other unit. The option has the opposite meaning and is the default. With , the swap unit will be only wanted, not required by swap.target. This means that the boot will continue even if this swap device is not activated successfully. Options Swap files must include a [Swap] section, which carries information about the swap device it supervises. A number of options that may be used in this section are shared with other unit types. These options are documented in systemd.exec5 and systemd.kill5. The options specific to the [Swap] section of swap units are the following: What= Takes an absolute path of a device node or file to use for paging. See swapon8 for details. If this refers to a device node, a dependency on the respective device unit is automatically created. (See systemd.device5 for more information.) If this refers to a file, a dependency on the respective mount unit is automatically created. (See systemd.mount5 for more information.) This option is mandatory. Priority= Swap priority to use when activating the swap device or file. This takes an integer. This setting is optional and ignored when the priority is set by in the Options= key. Options= May contain an option string for the swap device. This may be used for controlling discard options among other functionality, if the swap backing device supports the discard or trim operation. (See swapon8 for more information.) TimeoutSec= Configures the time to wait for the swapon command to finish. If a command does not exit within the configured time, the swap will be considered failed and be shut down again. All commands still running will be terminated forcibly via SIGTERM, and after another delay of this time with SIGKILL. (See in systemd.kill5.) Takes a unit-less value in seconds, or a time span value such as "5min 20s". Pass 0 to disable the timeout logic. Defaults to DefaultTimeoutStartSec= from the manager configuration file (see systemd-system.conf5). Check systemd.exec5 and systemd.kill5 for more settings. See Also systemd1, systemctl1, systemd.unit5, systemd.exec5, systemd.kill5, systemd.resource-control5, systemd.device5, systemd.mount5, swapon8, systemd-fstab-generator8, systemd.directives7 systemd-229/man/systemd.target.xml000066400000000000000000000103071265713322000173340ustar00rootroot00000000000000 systemd.target systemd Developer Lennart Poettering lennart@poettering.net systemd.target 5 systemd.target Target unit configuration target.target Description A unit configuration file whose name ends in .target encodes information about a target unit of systemd, which is used for grouping units and as well-known synchronization points during start-up. This unit type has no specific options. See systemd.unit5 for the common options of all unit configuration files. The common configuration items are configured in the generic [Unit] and [Install] sections. A separate [Target] section does not exist, since no target-specific options may be configured. Target units do not offer any additional functionality on top of the generic functionality provided by units. They exist merely to group units via dependencies (useful as boot targets), and to establish standardized names for synchronization points used in dependencies between units. Among other things, target units are a more flexible replacement for SysV runlevels in the classic SysV init system. (And for compatibility reasons special target units such as runlevel3.target exist which are used by the SysV runlevel compatibility code in systemd. See systemd.special7 for details). Automatic Dependencies Unless DefaultDependencies= is set to , target units will implicitly complement all configured dependencies of type Wants=, Requires= with dependencies of type After=, unless an ordering dependency of any kind between the target and the respective other unit is already in place. Note that this behaviour is disabled if either unit has DefaultDependencies=no. See Also systemd1, systemctl1, systemd.unit5, systemd.special7, systemd.directives7 systemd-229/man/systemd.time.xml000066400000000000000000000312631265713322000170100ustar00rootroot00000000000000 systemd.time systemd Developer Lennart Poettering lennart@poettering.net systemd.time 7 systemd.time Time and date specifications Description In systemd, timestamps, time spans, and calendar events are displayed and may be specified in closely related syntaxes. Displaying Time Spans Time spans refer to time durations. On display, systemd will present time spans as a space-separated series of time values each suffixed by a time unit. 2h 30min All specified time values are meant to be added up. The above hence refers to 150 minutes. Parsing Time Spans When parsing, systemd will accept the same time span syntax. Separating spaces may be omitted. The following time units are understood: usec, us msec, ms seconds, second, sec, s minutes, minute, min, m hours, hour, hr, h days, day, d weeks, week, w months, month, M (defined as 30.44 days) years, year, y (define as 365.25 days) If no time unit is specified, generally seconds are assumed, but some exceptions exist and are marked as such. In a few cases ns, nsec is accepted too, where the granularity of the time span allows for this. Examples for valid time span specifications: 2 h 2hours 48hr 1y 12month 55s500ms 300ms20s 5day Displaying Timestamps Timestamps refer to specific, unique points in time. On display, systemd will format these in the local timezone as follows: Fri 2012-11-23 23:02:15 CET The weekday is printed according to the locale choice of the user. Parsing Timestamps When parsing, systemd will accept a similar syntax, but expects no timezone specification, unless it is given as the literal string "UTC". In this case, the time is considered in UTC, otherwise in the local timezone. The weekday specification is optional, but when the weekday is specified, it must either be in the abbreviated (Wed) or non-abbreviated (Wednesday) English language form (case does not matter), and is not subject to the locale choice of the user. Either the date, or the time part may be omitted, in which case the current date or 00:00:00, respectively, is assumed. The seconds component of the time may also be omitted, in which case ":00" is assumed. Year numbers may be specified in full or may be abbreviated (omitting the century). A timestamp is considered invalid if a weekday is specified and the date does not actually match the specified day of the week. When parsing, systemd will also accept a few special placeholders instead of timestamps: now may be used to refer to the current time (or of the invocation of the command that is currently executed). today, yesterday, and tomorrow refer to 00:00:00 of the current day, the day before, or the next day, respectively. When parsing, systemd will also accept relative time specifications. A time span (see above) that is prefixed with + is evaluated to the current time plus the specified time span. Correspondingly, a time span that is prefixed with - is evaluated to the current time minus the specified time span. Instead of prefixing the time span with + or -, it may also be suffixed with a space and the word left or ago. Finally, a timespan prefixed with @ is evaluated relative to the UNIX time epoch 1st Jan, 1970, 00:00. Examples for valid timestamps and their normalized form (assuming the current time was 2012-11-23 18:15:22 and the timezone was UTC+8, for example TZ=Asia/Shanghai): Fri 2012-11-23 11:12:13 → Fri 2012-11-23 11:12:13 2012-11-23 11:12:13 → Fri 2012-11-23 11:12:13 2012-11-23 11:12:13 UTC → Fri 2012-11-23 19:12:13 2012-11-23 → Fri 2012-11-23 00:00:00 12-11-23 → Fri 2012-11-23 00:00:00 11:12:13 → Fri 2012-11-23 11:12:13 11:12:13.9900009 → Fri 2012-11-23 11:12:13 format_timestamp_us: Fri 2012-11-23 11:12:13.990000 11:12 → Fri 2012-11-23 11:12:00 now → Fri 2012-11-23 18:15:22 today → Fri 2012-11-23 00:00:00 today UTC → Fri 2012-11-23 16:00:00 yesterday → Fri 2012-11-22 00:00:00 tomorrow → Fri 2012-11-24 00:00:00 +3h30min → Fri 2012-11-23 21:45:22 +3h30min UTC → -EINVAL -5s → Fri 2012-11-23 18:15:17 11min ago → Fri 2012-11-23 18:04:22 11min ago UTC → -EINVAL @1395716396 → Tue 2014-03-25 03:59:56 Note that timestamps printed by systemd will not be parsed correctly by systemd, as the timezone specification is not accepted, and printing timestamps is subject to locale settings for the weekday, while parsing only accepts English weekday names. In some cases, systemd will display a relative timestamp (relative to the current time, or the time of invocation of the command) instead or in addition to an absolute timestamp as described above. A relative timestamp is formatted as follows: 2 months 5 days ago Note that any relative timestamp will also parse correctly where a timestamp is expected. (see above) Calendar Events Calendar events may be used to refer to one or more points in time in a single expression. They form a superset of the absolute timestamps explained above: Thu,Fri 2012-*-1,5 11:12:13 The above refers to 11:12:13 of the first or fifth day of any month of the year 2012, but only if that day is a Thursday or Friday. The weekday specification is optional. If specified, it should consist of one or more English language weekday names, either in the abbreviated (Wed) or non-abbreviated (Wednesday) form (case does not matter), separated by commas. Specifying two weekdays separated by - refers to a range of continuous weekdays. , and - may be combined freely. In the date and time specifications, any component may be specified as * in which case any value will match. Alternatively, each component can be specified as a list of values separated by commas. Values may also be suffixed with / and a repetition value, which indicates that the value and all values plus multiples of the repetition value are matched. The seconds component may contain decimal fractions both in the value and the repetition. All fractions are rounded to 6 decimal places. Either time or date specification may be omitted, in which case the current day and 00:00:00 is implied, respectively. If the second component is not specified, :00 is assumed. A timezone specification is not expected, unless it is given as the literal string "UTC", similarly to timestamps. The special expressions minutely, hourly, daily, monthly, weekly, yearly, quarterly, semiannually may be used as calendar events which refer to *-*-* *:*:00, *-*-* *:00:00, *-*-* 00:00:00, *-*-01 00:00:00, Mon *-*-* 00:00:00, *-01-01 00:00:00, *-01,04,07,10-01 00:00:00 and *-01,07-01 00:00:00, respectively. Examples for valid timestamps and their normalized form: Sat,Thu,Mon-Wed,Sat-Sun → Mon-Thu,Sat,Sun *-*-* 00:00:00 Mon,Sun 12-*-* 2,1:23 → Mon,Sun 2012-*-* 01,02:23:00 Wed *-1 → Wed *-*-01 00:00:00 Wed-Wed,Wed *-1 → Wed *-*-01 00:00:00 Wed, 17:48 → Wed *-*-* 17:48:00 Wed-Sat,Tue 12-10-15 1:2:3 → Tue-Sat 2012-10-15 01:02:03 *-*-7 0:0:0 → *-*-07 00:00:00 10-15 → *-10-15 00:00:00 monday *-12-* 17:00 → Mon *-12-* 17:00:00 Mon,Fri *-*-3,1,2 *:30:45 → Mon,Fri *-*-01,02,03 *:30:45 12,14,13,12:20,10,30 → *-*-* 12,13,14:10,20,30:00 mon,fri *-1/2-1,3 *:30:45 → Mon,Fri *-01/2-01,03 *:30:45 03-05 08:05:40 → *-03-05 08:05:40 08:05:40 → *-*-* 08:05:40 05:40 → *-*-* 05:40:00 Sat,Sun 12-05 08:05:40 → Sat,Sun *-12-05 08:05:40 Sat,Sun 08:05:40 → Sat,Sun *-*-* 08:05:40 2003-03-05 05:40 → 2003-03-05 05:40:00 05:40:23.4200004/3.1700005 → 05:40:23.420000/3.170001 2003-03-05 05:40 UTC → 2003-03-05 05:40:00 UTC 2003-03-05 → 2003-03-05 00:00:00 03-05 → *-03-05 00:00:00 hourly → *-*-* *:00:00 daily → *-*-* 00:00:00 daily UTC → *-*-* 00:00:00 UTC monthly → *-*-01 00:00:00 weekly → Mon *-*-* 00:00:00 yearly → *-01-01 00:00:00 annually → *-01-01 00:00:00 *:2/3 → *-*-* *:02/3:00 Calendar events are used by timer units, see systemd.timer5 for details. See Also systemd1, journalctl1, systemd.timer5, systemd.unit5, systemd.directives7 systemd-229/man/systemd.timer.xml000066400000000000000000000345021265713322000171710ustar00rootroot00000000000000 systemd.timer systemd Developer Lennart Poettering lennart@poettering.net systemd.timer 5 systemd.timer Timer unit configuration timer.timer Description A unit configuration file whose name ends in .timer encodes information about a timer controlled and supervised by systemd, for timer-based activation. This man page lists the configuration options specific to this unit type. See systemd.unit5 for the common options of all unit configuration files. The common configuration items are configured in the generic [Unit] and [Install] sections. The timer specific configuration options are configured in the [Timer] section. For each timer file, a matching unit file must exist, describing the unit to activate when the timer elapses. By default, a service by the same name as the timer (except for the suffix) is activated. Example: a timer file foo.timer activates a matching service foo.service. The unit to activate may be controlled by Unit= (see below). Automatic Dependencies Timer units automatically gain a Before= dependency on the service they are supposed to activate. Unless DefaultDependencies= is set to , all timer units will implicitly have dependencies of type Requires= and After= on sysinit.target, a dependency of type Before= on timers.target, as well as Conflicts= and Before= on shutdown.target to ensure that they are stopped cleanly prior to system shutdown. Timer units with at least one OnCalendar= directive will have an additional After= dependency on timer-sync.target to avoid being started before the system clock has been correctly set. Only timer units involved with early boot or late system shutdown should disable the DefaultDependencies= option. Options Timer files must include a [Timer] section, which carries information about the timer it defines. The options specific to the [Timer] section of timer units are the following: OnActiveSec= OnBootSec= OnStartupSec= OnUnitActiveSec= OnUnitInactiveSec= Defines monotonic timers relative to different starting points: OnActiveSec= defines a timer relative to the moment the timer itself is activated. OnBootSec= defines a timer relative to when the machine was booted up. OnStartupSec= defines a timer relative to when systemd was first started. OnUnitActiveSec= defines a timer relative to when the unit the timer is activating was last activated. OnUnitInactiveSec= defines a timer relative to when the unit the timer is activating was last deactivated. Multiple directives may be combined of the same and of different types. For example, by combining OnBootSec= and OnUnitActiveSec=, it is possible to define a timer that elapses in regular intervals and activates a specific service each time. The arguments to the directives are time spans configured in seconds. Example: "OnBootSec=50" means 50s after boot-up. The argument may also include time units. Example: "OnBootSec=5h 30min" means 5 hours and 30 minutes after boot-up. For details about the syntax of time spans, see systemd.time7. If a timer configured with OnBootSec= or OnStartupSec= is already in the past when the timer unit is activated, it will immediately elapse and the configured unit is started. This is not the case for timers defined in the other directives. These are monotonic timers, independent of wall-clock time and timezones. If the computer is temporarily suspended, the monotonic clock stops too. If the empty string is assigned to any of these options, the list of timers is reset, and all prior assignments will have no effect. Note that timers do not necessarily expire at the precise time configured with these settings, as they are subject to the AccuracySec= setting below. OnCalendar= Defines realtime (i.e. wallclock) timers with calendar event expressions. See systemd.time7 for more information on the syntax of calendar event expressions. Otherwise, the semantics are similar to OnActiveSec= and related settings. Note that timers do not necessarily expire at the precise time configured with this setting, as it is subject to the AccuracySec= setting below. AccuracySec= Specify the accuracy the timer shall elapse with. Defaults to 1min. The timer is scheduled to elapse within a time window starting with the time specified in OnCalendar=, OnActiveSec=, OnBootSec=, OnStartupSec=, OnUnitActiveSec= or OnUnitInactiveSec= and ending the time configured with AccuracySec= later. Within this time window, the expiry time will be placed at a host-specific, randomized, but stable position that is synchronized between all local timer units. This is done in order to optimize power consumption to suppress unnecessary CPU wake-ups. To get best accuracy, set this option to 1us. Note that the timer is still subject to the timer slack configured via systemd-system.conf5's TimerSlackNSec= setting. See prctl2 for details. To optimize power consumption, make sure to set this value as high as possible and as low as necessary. RandomizedDelaySec= Delay the timer by a randomly selected, evenly distributed amount of time between 0 and the specified time value. Defaults to 0, indicating that no randomized delay shall be applied. Each timer unit will determine this delay randomly each time it is started, and the delay will simply be added on top of the next determined elapsing time. This is useful to stretch dispatching of similarly configured timer events over a certain amount time, to avoid that they all fire at the same time, possibly resulting in resource congestion. Note the relation to AccuracySec= above: the latter allows the service manager to coalesce timer events within a specified time range in order to minimize wakeups, the former does the opposite: it stretches timer events over a time range, to make it unlikely that they fire simultaneously. If RandomizedDelaySec= and AccuracySec= are used in conjunction, first the randomized delay is added, and then the result is possibly further shifted to coalesce it with other timer events happening on the system. As mentioned above AccuracySec= defaults to 1min and RandomizedDelaySec= to 0, thus encouraging coalescing of timer events. In order to optimally stretch timer events over a certain range of time, make sure to set RandomizedDelaySec= to a higher value, and AccuracySec=1us. Unit= The unit to activate when this timer elapses. The argument is a unit name, whose suffix is not .timer. If not specified, this value defaults to a service that has the same name as the timer unit, except for the suffix. (See above.) It is recommended that the unit name that is activated and the unit name of the timer unit are named identically, except for the suffix. Persistent= Takes a boolean argument. If true, the time when the service unit was last triggered is stored on disk. When the timer is activated, the service unit is triggered immediately if it would have been triggered at least once during the time when the timer was inactive. This is useful to catch up on missed runs of the service when the machine was off. Note that this setting only has an effect on timers configured with OnCalendar=. WakeSystem= Takes a boolean argument. If true, an elapsing timer will cause the system to resume from suspend, should it be suspended and if the system supports this. Note that this option will only make sure the system resumes on the appropriate times, it will not take care of suspending it again after any work that is to be done is finished. Defaults to false. RemainAfterElapse= Takes a boolean argument. If true, an elapsed timer will stay loaded, and its state remains queriable. If false, an elapsed timer unit that cannot elapse anymore is unloaded. Turning this off is particularly useful for transient timer units that shall disappear after they first elapse. Note that this setting has an effect on repeatedly starting a timer unit that only elapses once: if RemainAfterElapse= is on, it will not be started again, and is guaranteed to elapse only once. However, if RemainAfterLeapse= is off, it might be started again if it is already elapsed, and thus be triggered multiple times. Defaults to yes. See Also systemd1, systemctl1, systemd.unit5, systemd.service5, systemd.time7, systemd.directives7, systemd-system.conf5, prctl2 systemd-229/man/systemd.unit.xml000066400000000000000000002200541265713322000170270ustar00rootroot00000000000000 %entities; ]> systemd.unit systemd Developer Lennart Poettering lennart@poettering.net systemd.unit 5 systemd.unit Unit configuration service.service, socket.socket, device.device, mount.mount, automount.automount, swap.swap, target.target, path.path, timer.timer, slice.slice, scope.scope /etc/systemd/system/* /run/systemd/system/* /usr/lib/systemd/system/* ... $XDG_CONFIG_HOME/systemd/user/* $HOME/.config/systemd/user/* /etc/systemd/user/* $XDG_RUNTIME_DIR/systemd/user/* /run/systemd/user/* $XDG_DATA_HOME/systemd/user/* $HOME/.local/share/systemd/user/* /usr/lib/systemd/user/* ... Description A unit configuration file encodes information about a service, a socket, a device, a mount point, an automount point, a swap file or partition, a start-up target, a watched file system path, a timer controlled and supervised by systemd1, a resource management slice or a group of externally created processes. The syntax is inspired by XDG Desktop Entry Specification .desktop files, which are in turn inspired by Microsoft Windows .ini files. This man page lists the common configuration options of all the unit types. These options need to be configured in the [Unit] or [Install] sections of the unit files. In addition to the generic [Unit] and [Install] sections described here, each unit may have a type-specific section, e.g. [Service] for a service unit. See the respective man pages for more information: systemd.service5, systemd.socket5, systemd.device5, systemd.mount5, systemd.automount5, systemd.swap5, systemd.target5, systemd.path5, systemd.timer5, systemd.slice5, systemd.scope5. Various settings are allowed to be specified more than once, in which case the interpretation depends on the setting. Often, multiple settings form a list, and setting to an empty value "resets", which means that previous assignments are ignored. When this is allowed, it is mentioned in the description of the setting. Note that using multiple assignments to the same value makes the unit file incompatible with parsers for the XDG .desktop file format. Unit files are loaded from a set of paths determined during compilation, described in the next section. Unit files may contain additional options on top of those listed here. If systemd encounters an unknown option, it will write a warning log message but continue loading the unit. If an option or section name is prefixed with , it is ignored completely by systemd. Options within an ignored section do not need the prefix. Applications may use this to include additional information in the unit files. Boolean arguments used in unit files can be written in various formats. For positive settings the strings , , and are equivalent. For negative settings, the strings , , and are equivalent. Time span values encoded in unit files can be written in various formats. A stand-alone number specifies a time in seconds. If suffixed with a time unit, the unit is honored. A concatenation of multiple values with units is supported, in which case the values are added up. Example: "50" refers to 50 seconds; "2min 200ms" refers to 2 minutes plus 200 milliseconds, i.e. 120200ms. The following time units are understood: s, min, h, d, w, ms, us. For details see systemd.time7. Empty lines and lines starting with # or ; are ignored. This may be used for commenting. Lines ending in a backslash are concatenated with the following line while reading and the backslash is replaced by a space character. This may be used to wrap long lines. Along with a unit file foo.service, the directory foo.service.wants/ may exist. All unit files symlinked from such a directory are implicitly added as dependencies of type Wants= to the unit. This is useful to hook units into the start-up of other units, without having to modify their unit files. For details about the semantics of Wants=, see below. The preferred way to create symlinks in the .wants/ directory of a unit file is with the enable command of the systemctl1 tool which reads information from the [Install] section of unit files (see below). A similar functionality exists for Requires= type dependencies as well, the directory suffix is .requires/ in this case. Along with a unit file foo.service, a "drop-in" directory foo.service.d/ may exist. All files with the suffix .conf from this directory will be parsed after the file itself is parsed. This is useful to alter or add configuration settings for a unit, without having to modify unit files. Each drop-in file must have appropriate section headers. Note that for instantiated units, this logic will first look for the instance .d/ subdirectory and read its .conf files, followed by the template .d/ subdirectory and the .conf files there. Also note that settings from the [Install] section are not honoured in drop-in unit files, and have no effect. In addition to /etc/systemd/system, the drop-in .conf files for system services can be placed in /usr/lib/systemd/system or /run/systemd/system directories. Drop-in files in /etc take precedence over those in /run which in turn take precedence over those in /usr/lib. Drop-in files under any of these directories take precedence over unit files wherever located. (Of course, since /run is temporary and /usr/lib is for vendors, it is unlikely drop-ins should be used in either of those places.) Some unit names reflect paths existing in the file system namespace. Example: a device unit dev-sda.device refers to a device with the device node /dev/sda in the file system namespace. If this applies, a special way to escape the path name is used, so that the result is usable as part of a filename. Basically, given a path, "/" is replaced by "-", and all other characters which are not ASCII alphanumerics are replaced by C-style "\x2d" escapes (except that "_" is never replaced and "." is only replaced when it would be the first character in the escaped path). The root directory "/" is encoded as single dash, while otherwise the initial and ending "/" are removed from all paths during transformation. This escaping is reversible. Properly escaped paths can be generated using the systemd-escape1 command. Optionally, units may be instantiated from a template file at runtime. This allows creation of multiple units from a single configuration file. If systemd looks for a unit configuration file, it will first search for the literal unit name in the file system. If that yields no success and the unit name contains an @ character, systemd will look for a unit template that shares the same name but with the instance string (i.e. the part between the @ character and the suffix) removed. Example: if a service getty@tty3.service is requested and no file by that name is found, systemd will look for getty@.service and instantiate a service from that configuration file if it is found. To refer to the instance string from within the configuration file you may use the special %i specifier in many of the configuration options. See below for details. If a unit file is empty (i.e. has the file size 0) or is symlinked to /dev/null, its configuration will not be loaded and it appears with a load state of masked, and cannot be activated. Use this as an effective way to fully disable a unit, making it impossible to start it even manually. The unit file format is covered by the Interface Stability Promise. Automatic Dependencies Note that while systemd offers a flexible dependency system between units it is recommended to use this functionality only sparingly and instead rely on techniques such as bus-based or socket-based activation which make dependencies implicit, resulting in a both simpler and more flexible system. A number of unit dependencies are automatically established, depending on unit configuration. On top of that, for units with DefaultDependencies=yes (the default) a couple of additional dependencies are added. The precise effect of DefaultDependencies=yes depends on the unit type (see below). If DefaultDependencies=yes is set, units that are referenced by other units of type .target via a Wants= or Requires= dependency might automatically gain an Before= dependency too. See systemd.target5 for details. Unit File Load Path Unit files are loaded from a set of paths determined during compilation, described in the two tables below. Unit files found in directories listed earlier override files with the same name in directories lower in the list. When the variable $SYSTEMD_UNIT_PATH is set, the contents of this variable overrides the unit load path. If $SYSTEMD_UNIT_PATH ends with an empty component (:), the usual unit load path will be appended to the contents of the variable. Load path when running in system mode (<option>--system</option>). Path Description /etc/systemd/system Local configuration /run/systemd/system Runtime units /usr/lib/systemd/system Units of installed packages
Load path when running in user mode (<option>--user</option>). Path Description $XDG_CONFIG_HOME/systemd/user User configuration (only used when $XDG_CONFIG_HOME is set) $HOME/.config/systemd/user User configuration (only used when $XDG_CONFIG_HOME is not set) /etc/systemd/user Local configuration $XDG_RUNTIME_DIR/systemd/user Runtime units (only used when $XDG_RUNTIME_DIR is set) /run/systemd/user Runtime units $XDG_DATA_HOME/systemd/user Units of packages that have been installed in the home directory (only used when $XDG_DATA_HOME is set) $HOME/.local/share/systemd/user Units of packages that have been installed in the home directory (only used when $XDG_DATA_HOME is not set) /usr/lib/systemd/user Units of packages that have been installed system-wide
Additional units might be loaded into systemd ("linked") from directories not on the unit load path. See the link command for systemctl1. Also, some units are dynamically created via a systemd.generator7.
[Unit] Section Options The unit file may include a [Unit] section, which carries generic information about the unit that is not dependent on the type of unit: Description= A free-form string describing the unit. This is intended for use in UIs to show descriptive information along with the unit name. The description should contain a name that means something to the end user. Apache2 Web Server is a good example. Bad examples are high-performance light-weight HTTP server (too generic) or Apache2 (too specific and meaningless for people who do not know Apache). Documentation= A space-separated list of URIs referencing documentation for this unit or its configuration. Accepted are only URIs of the types http://, https://, file:, info:, man:. For more information about the syntax of these URIs, see uri7. The URIs should be listed in order of relevance, starting with the most relevant. It is a good idea to first reference documentation that explains what the unit's purpose is, followed by how it is configured, followed by any other related documentation. This option may be specified more than once, in which case the specified list of URIs is merged. If the empty string is assigned to this option, the list is reset and all prior assignments will have no effect. Requires= Configures requirement dependencies on other units. If this unit gets activated, the units listed here will be activated as well. If one of the other units gets deactivated or its activation fails, this unit will be deactivated. This option may be specified more than once or multiple space-separated units may be specified in one option in which case requirement dependencies for all listed names will be created. Note that requirement dependencies do not influence the order in which services are started or stopped. This has to be configured independently with the After= or Before= options. If a unit foo.service requires a unit bar.service as configured with Requires= and no ordering is configured with After= or Before=, then both units will be started simultaneously and without any delay between them if foo.service is activated. Often, it is a better choice to use Wants= instead of Requires= in order to achieve a system that is more robust when dealing with failing services. Note that dependencies of this type may also be configured outside of the unit configuration file by adding a symlink to a .requires/ directory accompanying the unit file. For details, see above. Requisite= Similar to Requires=. However, if the units listed here are not started already, they will not be started and the transaction will fail immediately. Wants= A weaker version of Requires=. Units listed in this option will be started if the configuring unit is. However, if the listed units fail to start or cannot be added to the transaction, this has no impact on the validity of the transaction as a whole. This is the recommended way to hook start-up of one unit to the start-up of another unit. Note that dependencies of this type may also be configured outside of the unit configuration file by adding symlinks to a .wants/ directory accompanying the unit file. For details, see above. BindsTo= Configures requirement dependencies, very similar in style to Requires=, however in addition to this behavior, it also declares that this unit is stopped when any of the units listed suddenly disappears. Units can suddenly, unexpectedly disappear if a service terminates on its own choice, a device is unplugged or a mount point unmounted without involvement of systemd. PartOf= Configures dependencies similar to Requires=, but limited to stopping and restarting of units. When systemd stops or restarts the units listed here, the action is propagated to this unit. Note that this is a one-way dependency — changes to this unit do not affect the listed units. Conflicts= A space-separated list of unit names. Configures negative requirement dependencies. If a unit has a Conflicts= setting on another unit, starting the former will stop the latter and vice versa. Note that this setting is independent of and orthogonal to the After= and Before= ordering dependencies. If a unit A that conflicts with a unit B is scheduled to be started at the same time as B, the transaction will either fail (in case both are required part of the transaction) or be modified to be fixed (in case one or both jobs are not a required part of the transaction). In the latter case, the job that is not the required will be removed, or in case both are not required, the unit that conflicts will be started and the unit that is conflicted is stopped. Before= After= A space-separated list of unit names. Configures ordering dependencies between units. If a unit foo.service contains a setting and both units are being started, bar.service's start-up is delayed until foo.service is started up. Note that this setting is independent of and orthogonal to the requirement dependencies as configured by Requires=. It is a common pattern to include a unit name in both the After= and Requires= option, in which case the unit listed will be started before the unit that is configured with these options. This option may be specified more than once, in which case ordering dependencies for all listed names are created. After= is the inverse of Before=, i.e. while After= ensures that the configured unit is started after the listed unit finished starting up, Before= ensures the opposite, i.e. that the configured unit is fully started up before the listed unit is started. Note that when two units with an ordering dependency between them are shut down, the inverse of the start-up order is applied. i.e. if a unit is configured with After= on another unit, the former is stopped before the latter if both are shut down. If one unit with an ordering dependency on another unit is shut down while the latter is started up, the shut down is ordered before the start-up regardless of whether the ordering dependency is actually of type After= or Before=. If two units have no ordering dependencies between them, they are shut down or started up simultaneously, and no ordering takes place. OnFailure= A space-separated list of one or more units that are activated when this unit enters the failed state. PropagatesReloadTo= ReloadPropagatedFrom= A space-separated list of one or more units where reload requests on this unit will be propagated to, or reload requests on the other unit will be propagated to this unit, respectively. Issuing a reload request on a unit will automatically also enqueue a reload request on all units that the reload request shall be propagated to via these two settings. JoinsNamespaceOf= For units that start processes (such as service units), lists one or more other units whose network and/or temporary file namespace to join. This only applies to unit types which support the PrivateNetwork= and PrivateTmp= directives (see systemd.exec5 for details). If a unit that has this setting set is started, its processes will see the same /tmp, /tmp/var and network namespace as one listed unit that is started. If multiple listed units are already started, it is not defined which namespace is joined. Note that this setting only has an effect if PrivateNetwork= and/or PrivateTmp= is enabled for both the unit that joins the namespace and the unit whose namespace is joined. RequiresMountsFor= Takes a space-separated list of absolute paths. Automatically adds dependencies of type Requires= and After= for all mount units required to access the specified path. Mount points marked with are not mounted automatically and will be ignored for the purposes of this option. If such a mount should be a requirement for this unit, direct dependencies on the mount units may be added (Requires= and After= or some other combination). OnFailureJobMode= Takes a value of fail, replace, replace-irreversibly, isolate, flush, ignore-dependencies or ignore-requirements. Defaults to replace. Specifies how the units listed in OnFailure= will be enqueued. See systemctl1's option for details on the possible values. If this is set to isolate, only a single unit may be listed in OnFailure=.. IgnoreOnIsolate= Takes a boolean argument. If , this unit will not be stopped when isolating another unit. Defaults to . StopWhenUnneeded= Takes a boolean argument. If , this unit will be stopped when it is no longer used. Note that, in order to minimize the work to be executed, systemd will not stop units by default unless they are conflicting with other units, or the user explicitly requested their shut down. If this option is set, a unit will be automatically cleaned up if no other active unit requires it. Defaults to . RefuseManualStart= RefuseManualStop= Takes a boolean argument. If , this unit can only be activated or deactivated indirectly. In this case, explicit start-up or termination requested by the user is denied, however if it is started or stopped as a dependency of another unit, start-up or termination will succeed. This is mostly a safety feature to ensure that the user does not accidentally activate units that are not intended to be activated explicitly, and not accidentally deactivate units that are not intended to be deactivated. These options default to . AllowIsolate= Takes a boolean argument. If , this unit may be used with the systemctl isolate command. Otherwise, this will be refused. It probably is a good idea to leave this disabled except for target units that shall be used similar to runlevels in SysV init systems, just as a precaution to avoid unusable system states. This option defaults to . DefaultDependencies= Takes a boolean argument. If , (the default), a few default dependencies will implicitly be created for the unit. The actual dependencies created depend on the unit type. For example, for service units, these dependencies ensure that the service is started only after basic system initialization is completed and is properly terminated on system shutdown. See the respective man pages for details. Generally, only services involved with early boot or late shutdown should set this option to . It is highly recommended to leave this option enabled for the majority of common units. If set to , this option does not disable all implicit dependencies, just non-essential ones. JobTimeoutSec= JobTimeoutAction= JobTimeoutRebootArgument= When a job for this unit is queued, a time-out may be configured. If this time limit is reached, the job will be cancelled, the unit however will not change state or even enter the failed mode. This value defaults to infinity (job timeouts disabled), except for device units. NB: this timeout is independent from any unit-specific timeout (for example, the timeout set with TimeoutStartSec= in service units) as the job timeout has no effect on the unit itself, only on the job that might be pending for it. Or in other words: unit-specific timeouts are useful to abort unit state changes, and revert them. The job timeout set with this option however is useful to abort only the job waiting for the unit state to change. JobTimeoutAction= optionally configures an additional action to take when the time-out is hit. It takes the same values as the per-service StartLimitAction= setting, see systemd.service5 for details. Defaults to . JobTimeoutRebootArgument= configures an optional reboot string to pass to the reboot2 system call. StartLimitInterval= StartLimitBurst= Configure unit start rate limiting. By default, units which are started more than 5 times within 10 seconds are not permitted to start any more times until the 10 second interval ends. With these two options, this rate limiting may be modified. Use StartLimitInterval= to configure the checking interval (defaults to DefaultStartLimitInterval= in manager configuration file, set to 0 to disable any kind of rate limiting). Use StartLimitBurst= to configure how many starts per interval are allowed (defaults to DefaultStartLimitBurst= in manager configuration file). These configuration options are particularly useful in conjunction with the service setting Restart= (see systemd.service5); however, they apply to all kinds of starts (including manual), not just those triggered by the Restart= logic. Note that units which are configured for Restart= and which reach the start limit are not attempted to be restarted anymore; however, they may still be restarted manually at a later point, from which point on, the restart logic is again activated. Note that systemctl reset-failed will cause the restart rate counter for a service to be flushed, which is useful if the administrator wants to manually start a unit and the start limit interferes with that. StartLimitAction= Configure the action to take if the rate limit configured with StartLimitInterval= and StartLimitBurst= is hit. Takes one of , , , , , or . If is set, hitting the rate limit will trigger no action besides that the start will not be permitted. causes a reboot following the normal shutdown procedure (i.e. equivalent to systemctl reboot). causes a forced reboot which will terminate all processes forcibly but should cause no dirty file systems on reboot (i.e. equivalent to systemctl reboot -f) and causes immediate execution of the reboot2 system call, which might result in data loss. Similarly, , , have the effect of powering down the system with similar semantics. Defaults to . RebootArgument= Configure the optional argument for the reboot2 system call if StartLimitAction= or a service's FailureAction= is a reboot action. This works just like the optional argument to systemctl reboot command. ConditionArchitecture= ConditionVirtualization= ConditionHost= ConditionKernelCommandLine= ConditionSecurity= ConditionCapability= ConditionACPower= ConditionNeedsUpdate= ConditionFirstBoot= ConditionPathExists= ConditionPathExistsGlob= ConditionPathIsDirectory= ConditionPathIsSymbolicLink= ConditionPathIsMountPoint= ConditionPathIsReadWrite= ConditionDirectoryNotEmpty= ConditionFileNotEmpty= ConditionFileIsExecutable= Before starting a unit, verify that the specified condition is true. If it is not true, the starting of the unit will be (mostly silently) skipped, however all ordering dependencies of it are still respected. A failing condition will not result in the unit being moved into a failure state. The condition is checked at the time the queued start job is to be executed. Use condition expressions in order to silently skip units that do not apply to the local running system, for example because the kernel or runtime environment doesn't require its functionality. Use the various AssertArchitecture=, AssertVirtualization=, … options for a similar mechanism that puts the unit in a failure state and logs about the failed check (see below). ConditionArchitecture= may be used to check whether the system is running on a specific architecture. Takes one of x86, x86-64, ppc, ppc-le, ppc64, ppc64-le, ia64, parisc, parisc64, s390, s390x, sparc, sparc64, mips, mips-le, mips64, mips64-le, alpha, arm, arm-be, arm64, arm64-be, sh, sh64, m86k, tilegx, cris to test against a specific architecture. The architecture is determined from the information returned by uname2 and is thus subject to personality2. Note that a Personality= setting in the same unit file has no effect on this condition. A special architecture name native is mapped to the architecture the system manager itself is compiled for. The test may be negated by prepending an exclamation mark. ConditionVirtualization= may be used to check whether the system is executed in a virtualized environment and optionally test whether it is a specific implementation. Takes either boolean value to check if being executed in any virtualized environment, or one of vm and container to test against a generic type of virtualization solution, or one of qemu, kvm, zvm, vmware, microsoft, oracle, xen, bochs, uml, openvz, lxc, lxc-libvirt, systemd-nspawn, docker, rkt to test against a specific implementation. See systemd-detect-virt1 for a full list of known virtualization technologies and their identifiers. If multiple virtualization technologies are nested, only the innermost is considered. The test may be negated by prepending an exclamation mark. ConditionHost= may be used to match against the hostname or machine ID of the host. This either takes a hostname string (optionally with shell style globs) which is tested against the locally set hostname as returned by gethostname2, or a machine ID formatted as string (see machine-id5). The test may be negated by prepending an exclamation mark. ConditionKernelCommandLine= may be used to check whether a specific kernel command line option is set (or if prefixed with the exclamation mark unset). The argument must either be a single word, or an assignment (i.e. two words, separated =). In the former case the kernel command line is searched for the word appearing as is, or as left hand side of an assignment. In the latter case, the exact assignment is looked for with right and left hand side matching. ConditionSecurity= may be used to check whether the given security module is enabled on the system. Currently, the recognized values are selinux, apparmor, ima, smack and audit. The test may be negated by prepending an exclamation mark. ConditionCapability= may be used to check whether the given capability exists in the capability bounding set of the service manager (i.e. this does not check whether capability is actually available in the permitted or effective sets, see capabilities7 for details). Pass a capability name such as CAP_MKNOD, possibly prefixed with an exclamation mark to negate the check. ConditionACPower= may be used to check whether the system has AC power, or is exclusively battery powered at the time of activation of the unit. This takes a boolean argument. If set to true, the condition will hold only if at least one AC connector of the system is connected to a power source, or if no AC connectors are known. Conversely, if set to false, the condition will hold only if there is at least one AC connector known and all AC connectors are disconnected from a power source. ConditionNeedsUpdate= takes one of /var or /etc as argument, possibly prefixed with a ! (for inverting the condition). This condition may be used to conditionalize units on whether the specified directory requires an update because /usr's modification time is newer than the stamp file .updated in the specified directory. This is useful to implement offline updates of the vendor operating system resources in /usr that require updating of /etc or /var on the next following boot. Units making use of this condition should order themselves before systemd-update-done.service8, to make sure they run before the stamp file's modification time gets reset indicating a completed update. ConditionFirstBoot= takes a boolean argument. This condition may be used to conditionalize units on whether the system is booting up with an unpopulated /etc directory. This may be used to populate /etc on the first boot after factory reset, or when a new system instances boots up for the first time. With ConditionPathExists= a file existence condition is checked before a unit is started. If the specified absolute path name does not exist, the condition will fail. If the absolute path name passed to ConditionPathExists= is prefixed with an exclamation mark (!), the test is negated, and the unit is only started if the path does not exist. ConditionPathExistsGlob= is similar to ConditionPathExists=, but checks for the existence of at least one file or directory matching the specified globbing pattern. ConditionPathIsDirectory= is similar to ConditionPathExists= but verifies whether a certain path exists and is a directory. ConditionPathIsSymbolicLink= is similar to ConditionPathExists= but verifies whether a certain path exists and is a symbolic link. ConditionPathIsMountPoint= is similar to ConditionPathExists= but verifies whether a certain path exists and is a mount point. ConditionPathIsReadWrite= is similar to ConditionPathExists= but verifies whether the underlying file system is readable and writable (i.e. not mounted read-only). ConditionDirectoryNotEmpty= is similar to ConditionPathExists= but verifies whether a certain path exists and is a non-empty directory. ConditionFileNotEmpty= is similar to ConditionPathExists= but verifies whether a certain path exists and refers to a regular file with a non-zero size. ConditionFileIsExecutable= is similar to ConditionPathExists= but verifies whether a certain path exists, is a regular file and marked executable. If multiple conditions are specified, the unit will be executed if all of them apply (i.e. a logical AND is applied). Condition checks can be prefixed with a pipe symbol (|) in which case a condition becomes a triggering condition. If at least one triggering condition is defined for a unit, then the unit will be executed if at least one of the triggering conditions apply and all of the non-triggering conditions. If you prefix an argument with the pipe symbol and an exclamation mark, the pipe symbol must be passed first, the exclamation second. Except for ConditionPathIsSymbolicLink=, all path checks follow symlinks. If any of these options is assigned the empty string, the list of conditions is reset completely, all previous condition settings (of any kind) will have no effect. AssertArchitecture= AssertVirtualization= AssertHost= AssertKernelCommandLine= AssertSecurity= AssertCapability= AssertACPower= AssertNeedsUpdate= AssertFirstBoot= AssertPathExists= AssertPathExistsGlob= AssertPathIsDirectory= AssertPathIsSymbolicLink= AssertPathIsMountPoint= AssertPathIsReadWrite= AssertDirectoryNotEmpty= AssertFileNotEmpty= AssertFileIsExecutable= Similar to the ConditionArchitecture=, ConditionVirtualization=, …, condition settings described above, these settings add assertion checks to the start-up of the unit. However, unlike the conditions settings, any assertion setting that is not met results in failure of the start job (which means this is logged loudly). Use assertion expressions for units that cannot operate when specific requirements are not met, and when this is something the administrator or user should look into. SourcePath= A path to a configuration file this unit has been generated from. This is primarily useful for implementation of generator tools that convert configuration from an external configuration file format into native unit files. This functionality should not be used in normal units. [Install] Section Options Unit files may include an [Install] section, which carries installation information for the unit. This section is not interpreted by systemd1 during runtime; it is used by the enable and disable commands of the systemctl1 tool during installation of a unit. Note that settings in the [Install] section may not appear in .d/*.conf unit file drop-ins (see above). Alias= A space-separated list of additional names this unit shall be installed under. The names listed here must have the same suffix (i.e. type) as the unit file name. This option may be specified more than once, in which case all listed names are used. At installation time, systemctl enable will create symlinks from these names to the unit filename. WantedBy= RequiredBy= This option may be used more than once, or a space-separated list of unit names may be given. A symbolic link is created in the .wants/ or .requires/ directory of each of the listed units when this unit is installed by systemctl enable. This has the effect that a dependency of type Wants= or Requires= is added from the listed unit to the current unit. The primary result is that the current unit will be started when the listed unit is started. See the description of Wants= and Requires= in the [Unit] section for details. WantedBy=foo.service in a service bar.service is mostly equivalent to Alias=foo.service.wants/bar.service in the same file. In case of template units, systemctl enable must be called with an instance name, and this instance will be added to the .wants/ or .requires/ list of the listed unit. E.g. WantedBy=getty.target in a service getty@.service will result in systemctl enable getty@tty2.service creating a getty.target.wants/getty@tty2.service link to getty@.service. Also= Additional units to install/deinstall when this unit is installed/deinstalled. If the user requests installation/deinstallation of a unit with this option configured, systemctl enable and systemctl disable will automatically install/uninstall units listed in this option as well. This option may be used more than once, or a space-separated list of unit names may be given. DefaultInstance= In template unit files, this specifies for which instance the unit shall be enabled if the template is enabled without any explicitly set instance. This option has no effect in non-template unit files. The specified string must be usable as instance identifier. The following specifiers are interpreted in the Install section: %n, %N, %p, %i, %U, %u, %m, %H, %b, %v. For their meaning see the next section. Specifiers Many settings resolve specifiers which may be used to write generic unit files referring to runtime or unit parameters that are replaced when the unit files are loaded. The following specifiers are understood: Specifiers available in unit files Specifier Meaning Details %n Full unit name %N Unescaped full unit name Same as %n, but with escaping undone %p Prefix name For instantiated units, this refers to the string before the @ character of the unit name. For non-instantiated units, this refers to the name of the unit with the type suffix removed. %P Unescaped prefix name Same as %p, but with escaping undone %i Instance name For instantiated units: this is the string between the @ character and the suffix of the unit name. %I Unescaped instance name Same as %i, but with escaping undone %f Unescaped filename This is either the unescaped instance name (if applicable) with / prepended (if applicable), or the prefix name prepended with /. %c Control group path of the unit This path does not include the /sys/fs/cgroup/systemd/ prefix. %r Control group path of the slice the unit is placed in This usually maps to the parent cgroup path of %c. %R Root control group path below which slices and units are placed For system instances, this resolves to /, except in containers, where this maps to the container's root control group path. %t Runtime directory This is either /run (for the system manager) or the path $XDG_RUNTIME_DIR resolves to (for user managers). %u User name This is the name of the user running the service manager instance. In case of the system manager this resolves to root. %U User UID This is the numeric UID of the user running the service manager instance. In case of the system manager this resolves to 0. %h User home directory This is the home directory of the user running the service manager instance. In case of the system manager this resolves to /root. %s User shell This is the shell of the user running the service manager instance. In case of the system manager this resolves to /bin/sh. %m Machine ID The machine ID of the running system, formatted as string. See machine-id5 for more information. %b Boot ID The boot ID of the running system, formatted as string. See random4 for more information. %H Host name The hostname of the running system at the point in time the unit configuration is loaded. %v Kernel release Identical to uname -r output %% Single percent sign Use %% in place of % to specify a single percent sign.
Please note that specifiers %U, %h, %s are mostly useless when systemd is running in system mode. PID 1 cannot query the user account database for information, so the specifiers only work as shortcuts for things which are already specified in a different way in the unit file. They are fully functional when systemd is running in mode.
Examples Allowing units to be enabled The following snippet (highlighted) allows a unit (e.g. foo.service) to be enabled via systemctl enable: [Unit] Description=Foo [Service] ExecStart=/usr/sbin/foo-daemon [Install] WantedBy=multi-user.target After running systemctl enable, a symlink /etc/systemd/system/multi-user.target.wants/foo.service linking to the actual unit will be created. It tells systemd to pull in the unit when starting multi-user.target. The inverse systemctl disable will remove that symlink again. Overriding vendor settings There are two methods of overriding vendor settings in unit files: copying the unit file from /usr/lib/systemd/system to /etc/systemd/system and modifying the chosen settings. Alternatively, one can create a directory named unit.d/ within /etc/systemd/system and place a drop-in file name.conf there that only changes the specific settings one is interested in. Note that multiple such drop-in files are read if present. The advantage of the first method is that one easily overrides the complete unit, the vendor unit is not parsed at all anymore. It has the disadvantage that improvements to the unit file by the vendor are not automatically incorporated on updates. The advantage of the second method is that one only overrides the settings one specifically wants, where updates to the unit by the vendor automatically apply. This has the disadvantage that some future updates by the vendor might be incompatible with the local changes. Note that for drop-in files, if one wants to remove entries from a setting that is parsed as a list (and is not a dependency), such as ConditionPathExists= (or e.g. ExecStart= in service units), one needs to first clear the list before re-adding all entries except the one that is to be removed. See below for an example. This also applies for user instances of systemd, but with different locations for the unit files. See the section on unit load paths for further details. Suppose there is a vendor-supplied unit /usr/lib/systemd/system/httpd.service with the following contents: [Unit] Description=Some HTTP server After=remote-fs.target sqldb.service Requires=sqldb.service AssertPathExists=/srv/webserver [Service] Type=notify ExecStart=/usr/sbin/some-fancy-httpd-server Nice=5 [Install] WantedBy=multi-user.target Now one wants to change some settings as an administrator: firstly, in the local setup, /srv/webserver might not exist, because the HTTP server is configured to use /srv/www instead. Secondly, the local configuration makes the HTTP server also depend on a memory cache service, memcached.service, that should be pulled in (Requires=) and also be ordered appropriately (After=). Thirdly, in order to harden the service a bit more, the administrator would like to set the PrivateTmp= setting (see systemd.service5 for details). And lastly, the administrator would like to reset the niceness of the service to its default value of 0. The first possibility is to copy the unit file to /etc/systemd/system/httpd.service and change the chosen settings: [Unit] Description=Some HTTP server After=remote-fs.target sqldb.service memcached.service Requires=sqldb.service memcached.service AssertPathExists=/srv/www [Service] Type=notify ExecStart=/usr/sbin/some-fancy-httpd-server Nice=0 PrivateTmp=yes [Install] WantedBy=multi-user.target Alternatively, the administrator could create a drop-in file /etc/systemd/system/httpd.service.d/local.conf with the following contents: [Unit] After=memcached.service Requires=memcached.service # Reset all assertions and then re-add the condition we want AssertPathExists= AssertPathExists=/srv/www [Service] Nice=0 PrivateTmp=yes Note that dependencies (After=, etc.) cannot be reset to an empty list, so dependencies can only be added in drop-ins. If you want to remove dependencies, you have to override the entire unit. See Also systemd1, systemctl1, systemd.special7, systemd.service5, systemd.socket5, systemd.device5, systemd.mount5, systemd.automount5, systemd.swap5, systemd.target5, systemd.path5, systemd.timer5, systemd.scope5, systemd.slice5, systemd.time7, systemd-analyze1, capabilities7, systemd.directives7, uname1
systemd-229/man/systemd.xml000066400000000000000000001422331265713322000160530ustar00rootroot00000000000000 systemd systemd Developer Lennart Poettering lennart@poettering.net systemd 1 systemd init systemd system and service manager systemd OPTIONS init OPTIONS COMMAND Description systemd is a system and service manager for Linux operating systems. When run as first process on boot (as PID 1), it acts as init system that brings up and maintains userspace services. For compatibility with SysV, if systemd is called as init and a PID that is not 1, it will execute telinit and pass all command line arguments unmodified. That means init and telinit are mostly equivalent when invoked from normal login sessions. See telinit8 for more information. When run as a system instance, systemd interprets the configuration file system.conf and the files in system.conf.d directories; when run as a user instance, systemd interprets the configuration file user.conf and the files in user.conf.d directories. See systemd-system.conf5 for more information. Options The following options are understood: Determine startup sequence, dump it and exit. This is an option useful for debugging only. Dump understood unit configuration items. This outputs a terse but complete list of configuration items understood in unit definition files. Set default unit to activate on startup. If not specified, defaults to default.target. For , tell systemd to run a system instance, even if the process ID is not 1, i.e. systemd is not run as init process. does the opposite, running a user instance even if the process ID is 1. Normally, it should not be necessary to pass these options, as systemd automatically detects the mode it is started in. These options are hence of little use except for debugging. Note that it is not supported booting and maintaining a full system with systemd running in mode, but PID not 1. In practice, passing explicitly is only useful in conjunction with . Enable core dumping on crash. This switch has no effect when running as user instance. This setting may also be enabled during boot on the kernel command line via the systemd.dump_core= option, see below. VT Switch to a specific virtual console (VT) on crash. Takes a positive integer in the range 1–63, or a boolean argument. If an integer is passed, selects which VT to switch to. If yes, the VT kernel messages are written to is selected. If no, no VT switch is attempted. This switch has no effect when running as user instance. This setting may also be enabled during boot, on the kernel command line via the systemd.crash_vt= option, see below. Run a shell on crash. This switch has no effect when running as user instance. This setting may also be enabled during boot, on the kernel command line via the systemd.crash_shell= option, see below. Automatically reboot the system on crash. This switch has no effect when running as user instance. This setting may also be enabled during boot, on the kernel command line via the systemd.crash_reboot= option, see below. Ask for confirmation when spawning processes. This switch has no effect when run as user instance. Show terse service status information while booting. This switch has no effect when run as user instance. Takes a boolean argument which may be omitted which is interpreted as . Set log target. Argument must be one of , , , , . Set log level. As argument this accepts a numerical log level or the well-known syslog3 symbolic names (lowercase): , , , , , , , . Highlight important log messages. Argument is a boolean value. If the argument is omitted, it defaults to . Include code location in log messages. This is mostly relevant for debugging purposes. Argument is a boolean value. If the argument is omitted it defaults to . Sets the default output or error output for all services and sockets, respectively. That is, controls the default for and (see systemd.exec5 for details). Takes one of , , , , , , , , . If the argument is omitted defaults to and to . Override the machine-id set on the hard drive, useful for network booting or for containers. May not be set to all zeros. Concepts systemd provides a dependency system between various entities called "units" of 12 different types. Units encapsulate various objects that are relevant for system boot-up and maintenance. The majority of units are configured in unit configuration files, whose syntax and basic set of options is described in systemd.unit5, however some are created automatically from other configuration, dynamically from system state or programmatically at runtime. Units may be "active" (meaning started, bound, plugged in, ..., depending on the unit type, see below), or "inactive" (meaning stopped, unbound, unplugged, ...), as well as in the process of being activated or deactivated, i.e. between the two states (these states are called "activating", "deactivating"). A special "failed" state is available as well, which is very similar to "inactive" and is entered when the service failed in some way (process returned error code on exit, or crashed, or an operation timed out). If this state is entered, the cause will be logged, for later reference. Note that the various unit types may have a number of additional substates, which are mapped to the five generalized unit states described here. The following unit types are available: Service units, which start and control daemons and the processes they consist of. For details, see systemd.service5. Socket units, which encapsulate local IPC or network sockets in the system, useful for socket-based activation. For details about socket units, see systemd.socket5, for details on socket-based activation and other forms of activation, see daemon7. Target units are useful to group units, or provide well-known synchronization points during boot-up, see systemd.target5. Device units expose kernel devices in systemd and may be used to implement device-based activation. For details, see systemd.device5. Mount units control mount points in the file system, for details see systemd.mount5. Automount units provide automount capabilities, for on-demand mounting of file systems as well as parallelized boot-up. See systemd.automount5. Timer units are useful for triggering activation of other units based on timers. You may find details in systemd.timer5. Swap units are very similar to mount units and encapsulate memory swap partitions or files of the operating system. They are described in systemd.swap5. Path units may be used to activate other services when file system objects change or are modified. See systemd.path5. Slice units may be used to group units which manage system processes (such as service and scope units) in a hierarchical tree for resource management purposes. See systemd.slice5. Scope units are similar to service units, but manage foreign processes instead of starting them as well. See systemd.scope5. Units are named as their configuration files. Some units have special semantics. A detailed list is available in systemd.special7. systemd knows various kinds of dependencies, including positive and negative requirement dependencies (i.e. Requires= and Conflicts=) as well as ordering dependencies (After= and Before=). NB: ordering and requirement dependencies are orthogonal. If only a requirement dependency exists between two units (e.g. foo.service requires bar.service), but no ordering dependency (e.g. foo.service after bar.service) and both are requested to start, they will be started in parallel. It is a common pattern that both requirement and ordering dependencies are placed between two units. Also note that the majority of dependencies are implicitly created and maintained by systemd. In most cases, it should be unnecessary to declare additional dependencies manually, however it is possible to do this. Application programs and units (via dependencies) may request state changes of units. In systemd, these requests are encapsulated as 'jobs' and maintained in a job queue. Jobs may succeed or can fail, their execution is ordered based on the ordering dependencies of the units they have been scheduled for. On boot systemd activates the target unit default.target whose job is to activate on-boot services and other on-boot units by pulling them in via dependencies. Usually, the unit name is just an alias (symlink) for either graphical.target (for fully-featured boots into the UI) or multi-user.target (for limited console-only boots for use in embedded or server environments, or similar; a subset of graphical.target). However, it is at the discretion of the administrator to configure it as an alias to any other target unit. See systemd.special7 for details about these target units. Processes systemd spawns are placed in individual Linux control groups named after the unit which they belong to in the private systemd hierarchy. (see cgroups.txt for more information about control groups, or short "cgroups"). systemd uses this to effectively keep track of processes. Control group information is maintained in the kernel, and is accessible via the file system hierarchy (beneath /sys/fs/cgroup/systemd/), or in tools such as systemd-cgls1 or ps1 (ps xawf -eo pid,user,cgroup,args is particularly useful to list all processes and the systemd units they belong to.). systemd is compatible with the SysV init system to a large degree: SysV init scripts are supported and simply read as an alternative (though limited) configuration file format. The SysV /dev/initctl interface is provided, and compatibility implementations of the various SysV client tools are available. In addition to that, various established Unix functionality such as /etc/fstab or the utmp database are supported. systemd has a minimal transaction system: if a unit is requested to start up or shut down it will add it and all its dependencies to a temporary transaction. Then, it will verify if the transaction is consistent (i.e. whether the ordering of all units is cycle-free). If it is not, systemd will try to fix it up, and removes non-essential jobs from the transaction that might remove the loop. Also, systemd tries to suppress non-essential jobs in the transaction that would stop a running service. Finally it is checked whether the jobs of the transaction contradict jobs that have already been queued, and optionally the transaction is aborted then. If all worked out and the transaction is consistent and minimized in its impact it is merged with all already outstanding jobs and added to the run queue. Effectively this means that before executing a requested operation, systemd will verify that it makes sense, fixing it if possible, and only failing if it really cannot work. Systemd contains native implementations of various tasks that need to be executed as part of the boot process. For example, it sets the hostname or configures the loopback network device. It also sets up and mounts various API file systems, such as /sys or /proc. For more information about the concepts and ideas behind systemd, please refer to the Original Design Document. Note that some but not all interfaces provided by systemd are covered by the Interface Stability Promise. Units may be generated dynamically at boot and system manager reload time, for example based on other configuration files or parameters passed on the kernel command line. For details, see systemd.generator7. Systems which invoke systemd in a container or initrd environment should implement the Container Interface or initrd Interface specifications, respectively. Directories System unit directories The systemd system manager reads unit configuration from various directories. Packages that want to install unit files shall place them in the directory returned by pkg-config systemd --variable=systemdsystemunitdir. Other directories checked are /usr/local/lib/systemd/system and /usr/lib/systemd/system. User configuration always takes precedence. pkg-config systemd --variable=systemdsystemconfdir returns the path of the system configuration directory. Packages should alter the content of these directories only with the enable and disable commands of the systemctl1 tool. Full list of directories is provided in systemd.unit5. User unit directories Similar rules apply for the user unit directories. However, here the XDG Base Directory specification is followed to find units. Applications should place their unit files in the directory returned by pkg-config systemd --variable=systemduserunitdir. Global configuration is done in the directory reported by pkg-config systemd --variable=systemduserconfdir. The enable and disable commands of the systemctl1 tool can handle both global (i.e. for all users) and private (for one user) enabling/disabling of units. Full list of directories is provided in systemd.unit5. SysV init scripts directory The location of the SysV init script directory varies between distributions. If systemd cannot find a native unit file for a requested service, it will look for a SysV init script of the same name (with the .service suffix removed). SysV runlevel link farm directory The location of the SysV runlevel link farm directory varies between distributions. systemd will take the link farm into account when figuring out whether a service shall be enabled. Note that a service unit with a native unit configuration file cannot be started by activating it in the SysV runlevel link farm. Signals SIGTERM Upon receiving this signal the systemd system manager serializes its state, reexecutes itself and deserializes the saved state again. This is mostly equivalent to systemctl daemon-reexec. systemd user managers will start the exit.target unit when this signal is received. This is mostly equivalent to systemctl --user start exit.target. SIGINT Upon receiving this signal the systemd system manager will start the ctrl-alt-del.target unit. This is mostly equivalent to systemctl start ctl-alt-del.target. If this signal is received more than 7 times per 2s, an immediate reboot is triggered. Note that pressing Ctrl-Alt-Del on the console will trigger this signal. Hence, if a reboot is hanging, pressing Ctrl-Alt-Del more than 7 times in 2s is a relatively safe way to trigger an immediate reboot. systemd user managers treat this signal the same way as SIGTERM. SIGWINCH When this signal is received the systemd system manager will start the kbrequest.target unit. This is mostly equivalent to systemctl start kbrequest.target. This signal is ignored by systemd user managers. SIGPWR When this signal is received the systemd manager will start the sigpwr.target unit. This is mostly equivalent to systemctl start sigpwr.target. SIGUSR1 When this signal is received the systemd manager will try to reconnect to the D-Bus bus. SIGUSR2 When this signal is received the systemd manager will log its complete state in human-readable form. The data logged is the same as printed by systemd-analyze dump. SIGHUP Reloads the complete daemon configuration. This is mostly equivalent to systemctl daemon-reload. SIGRTMIN+0 Enters default mode, starts the default.target unit. This is mostly equivalent to systemctl start default.target. SIGRTMIN+1 Enters rescue mode, starts the rescue.target unit. This is mostly equivalent to systemctl isolate rescue.target. SIGRTMIN+2 Enters emergency mode, starts the emergency.service unit. This is mostly equivalent to systemctl isolate emergency.service. SIGRTMIN+3 Halts the machine, starts the halt.target unit. This is mostly equivalent to systemctl start halt.target. SIGRTMIN+4 Powers off the machine, starts the poweroff.target unit. This is mostly equivalent to systemctl start poweroff.target. SIGRTMIN+5 Reboots the machine, starts the reboot.target unit. This is mostly equivalent to systemctl start reboot.target. SIGRTMIN+6 Reboots the machine via kexec, starts the kexec.target unit. This is mostly equivalent to systemctl start kexec.target. SIGRTMIN+13 Immediately halts the machine. SIGRTMIN+14 Immediately powers off the machine. SIGRTMIN+15 Immediately reboots the machine. SIGRTMIN+16 Immediately reboots the machine with kexec. SIGRTMIN+20 Enables display of status messages on the console, as controlled via systemd.show_status=1 on the kernel command line. SIGRTMIN+21 Disables display of status messages on the console, as controlled via systemd.show_status=0 on the kernel command line. SIGRTMIN+22 SIGRTMIN+23 Sets the log level to debug (or info on SIGRTMIN+23), as controlled via systemd.log_level=debug (or systemd.log_level=info on SIGRTMIN+23) on the kernel command line. SIGRTMIN+24 Immediately exits the manager (only available for --user instances). SIGRTMIN+26 SIGRTMIN+27 SIGRTMIN+28 Sets the log level to journal-or-kmsg (or console on SIGRTMIN+27, kmsg on SIGRTMIN+28), as controlled via systemd.log_target=journal-or-kmsg (or systemd.log_target=console on SIGRTMIN+27 or systemd.log_target=kmsg on SIGRTMIN+28) on the kernel command line. Environment $SYSTEMD_LOG_LEVEL systemd reads the log level from this environment variable. This can be overridden with . $SYSTEMD_LOG_TARGET systemd reads the log target from this environment variable. This can be overridden with . $SYSTEMD_LOG_COLOR Controls whether systemd highlights important log messages. This can be overridden with . $SYSTEMD_LOG_LOCATION Controls whether systemd prints the code location along with log messages. This can be overridden with . $XDG_CONFIG_HOME $XDG_CONFIG_DIRS $XDG_DATA_HOME $XDG_DATA_DIRS The systemd user manager uses these variables in accordance to the XDG Base Directory specification to find its configuration. $SYSTEMD_UNIT_PATH Controls where systemd looks for unit files. $SYSTEMD_SYSVINIT_PATH Controls where systemd looks for SysV init scripts. $SYSTEMD_SYSVRCND_PATH Controls where systemd looks for SysV init script runlevel link farms. $SYSTEMD_COLORS Controls whether colorized output should be generated. $LISTEN_PID $LISTEN_FDS $LISTEN_FDNAMES Set by systemd for supervised processes during socket-based activation. See sd_listen_fds3 for more information. $NOTIFY_SOCKET Set by systemd for supervised processes for status and start-up completion notification. See sd_notify3 for more information. Kernel Command Line When run as system instance systemd parses a number of kernel command line argumentsIf run inside a Linux container these arguments may be passed as command line arguments to systemd itself, next to any of the command line options listed in the Options section above. If run outside of Linux containers, these arguments are parsed from /proc/cmdline instead.: systemd.unit= rd.systemd.unit= Overrides the unit to activate on boot. Defaults to default.target. This may be used to temporarily boot into a different boot unit, for example rescue.target or emergency.service. See systemd.special7 for details about these units. The option prefixed with rd. is honored only in the initial RAM disk (initrd), while the one that is not prefixed only in the main system. systemd.dump_core= Takes a boolean argument. If , the systemd manager (PID 1) dumps core when it crashes. Otherwise, no core dump is created. Defaults to . systemd.crash_chvt= Takes a positive integer, or a boolean argument. If a positive integer (in the range 1–63) is specified, the system manager (PID 1) will activate the specified virtual terminal (VT) when it crashes. Defaults to no, meaning that no such switch is attempted. If set to yes, the VT the kernel messages are written to is selected. systemd.crash_shell= Takes a boolean argument. If , the system manager (PID 1) spawns a shell when it crashes, after a 10s delay. Otherwise, no shell is spawned. Defaults to , for security reasons, as the shell is not protected by password authentication. systemd.crash_reboot= Takes a boolean argument. If , the system manager (PID 1) will reboot the machine automatically when it crashes, after a 10s delay. Otherwise, the system will hang indefinitely. Defaults to , in order to avoid a reboot loop. If combined with systemd.crash_shell=, the system is rebooted after the shell exits. systemd.confirm_spawn= Takes a boolean argument. If , the system manager (PID 1) asks for confirmation when spawning processes. Defaults to . systemd.show_status= Takes a boolean argument or the constant auto. If , the systemd manager (PID 1) shows terse service status updates on the console during bootup. auto behaves like until a service fails or there is a significant delay in boot. Defaults to , unless is passed as kernel command line option, in which case it defaults to auto. systemd.log_target= systemd.log_level= systemd.log_color= systemd.log_location= Controls log output, with the same effect as the $SYSTEMD_LOG_TARGET, $SYSTEMD_LOG_LEVEL, $SYSTEMD_LOG_COLOR, $SYSTEMD_LOG_LOCATION environment variables described above. systemd.default_standard_output= systemd.default_standard_error= Controls default standard output and error output for services, with the same effect as the and command line arguments described above, respectively. systemd.setenv= Takes a string argument in the form VARIABLE=VALUE. May be used to set default environment variables to add to forked child processes. May be used more than once to set multiple variables. systemd.machine_id= Takes a 32 character hex value to be used for setting the machine-id. Intended mostly for network booting where the same machine-id is desired for every boot. quiet Turn off status output at boot, much like systemd.show_status=false would. Note that this option is also read by the kernel itself and disables kernel log output. Passing this option hence turns off the usual output from both the system manager and the kernel. debug Turn on debugging output. This is equivalent to systemd.log_level=debug. Note that this option is also read by the kernel itself and enables kernel debug output. Passing this option hence turns on the debug output from both the system manager and the kernel. emergency -b Boot into emergency mode. This is equivalent to systemd.unit=emergency.target and provided for compatibility reasons and to be easier to type. rescue single s S 1 Boot into rescue mode. This is equivalent to systemd.unit=rescue.target and provided for compatibility reasons and to be easier to type. 2 3 4 5 Boot into the specified legacy SysV runlevel. These are equivalent to systemd.unit=runlevel2.target, systemd.unit=runlevel3.target, systemd.unit=runlevel4.target, and systemd.unit=runlevel5.target, respectively, and provided for compatibility reasons and to be easier to type. locale.LANG= locale.LANGUAGE= locale.LC_CTYPE= locale.LC_NUMERIC= locale.LC_TIME= locale.LC_COLLATE= locale.LC_MONETARY= locale.LC_MESSAGES= locale.LC_PAPER= locale.LC_NAME= locale.LC_ADDRESS= locale.LC_TELEPHONE= locale.LC_MEASUREMENT= locale.LC_IDENTIFICATION= Set the system locale to use. This overrides the settings in /etc/locale.conf. For more information, see locale.conf5 and locale7. For other kernel command line parameters understood by components of the core OS, please refer to kernel-command-line7. Sockets and FIFOs /run/systemd/notify Daemon status notification socket. This is an AF_UNIX datagram socket and is used to implement the daemon notification logic as implemented by sd_notify3. /run/systemd/private Used internally as communication channel between systemctl1 and the systemd process. This is an AF_UNIX stream socket. This interface is private to systemd and should not be used in external projects. /dev/initctl Limited compatibility support for the SysV client interface, as implemented by the systemd-initctl.service unit. This is a named pipe in the file system. This interface is obsolete and should not be used in new applications. See Also The systemd Homepage, systemd-system.conf5, locale.conf5, systemctl1, journalctl1, systemd-notify1, daemon7, sd-daemon3, systemd.unit5, systemd.special5, pkg-config1, kernel-command-line7, bootup7, systemd.directives7 systemd-229/man/sysusers.d.xml000066400000000000000000000202351265713322000165020ustar00rootroot00000000000000 sysusers.d systemd Developer Lennart Poettering lennart@poettering.net sysusers.d 5 sysusers.d Declarative allocation of system users and groups /usr/lib/sysusers.d/*.conf Description systemd-sysusers uses the files from sysusers.d directory to create system users and groups at package installation or boot time. This tool may be used to allocate system users and groups only, it is not useful for creating non-system users and groups, as it accesses /etc/passwd and /etc/group directly, bypassing any more complex user databases, for example any database involving NIS or LDAP. Configuration Format Each configuration file shall be named in the style of package.conf or package-part.conf. The second variant should be used when it is desirable to make it easy to override just this part of configuration. The file format is one line per user or group containing name, ID, GECOS field description and home directory: # Type Name ID GECOS u httpd 440 "HTTP User" u authd /usr/bin/authd "Authorization user" g input - - m authd input u root 0 "Superuser" /root Type The type consists of a single letter. The following line types are understood: u Create a system user and group of the specified name should they not exist yet. The user's primary group will be set to the group bearing the same name. The user's shell will be set to /sbin/nologin, the home directory to the specified home directory, or / if none is given. The account will be created disabled, so that logins are not allowed. g Create a system group of the specified name should it not exist yet. Note that u implicitly create a matching group. The group will be created with no password set. m Add a user to a group. If the user or group do not exist yet, they will be implicitly created. r Add a range of numeric UIDs/GIDs to the pool to allocate new UIDs and GIDs from. If no line of this type is specified, the range of UIDs/GIDs is set to some compiled-in default. Note that both UIDs and GIDs are allocated from the same pool, in order to ensure that users and groups of the same name are likely to carry the same numeric UID and GID. Name The name field specifies the user or group name. It should be shorter than 31 characters and avoid any non-ASCII characters, and not begin with a numeric character. It is strongly recommended to pick user and group names that are unlikely to clash with normal users created by the administrator. A good scheme to guarantee this is by prefixing all system and group names with the underscore, and avoiding too generic names. For m lines, this field should contain the user name to add to a group. For lines of type r, this field should be set to -. ID For u and g, the numeric 32-bit UID or GID of the user/group. Do not use IDs 65535 or 4294967295, as they have special placeholder meanings. Specify - for automatic UID/GID allocation for the user or group. Alternatively, specify an absolute path in the file system. In this case, the UID/GID is read from the path's owner/group. This is useful to create users whose UID/GID match the owners of pre-existing files (such as SUID or SGID binaries). For m lines, this field should contain the group name to add to a user to. For lines of type r, this field should be set to a UID/GID range in the format FROM-TO, where both values are formatted as decimal ASCII numbers. Alternatively, a single UID/GID may be specified formatted as decimal ASCII numbers. GECOS A short, descriptive string for users to be created, enclosed in quotation marks. Note that this field may not contain colons. Only applies to lines of type u and should otherwise be left unset, or be set to -. Home Directory The home directory for a new system user. If omitted, defaults to the root directory. It is recommended to not unnecessarily specify home directories for system users, unless software strictly requires one to be set. Only applies to lines of type u and should otherwise be left unset, or be set to -. Idempotence Note that systemd-sysusers will do nothing if the specified users or groups already exist, so normally, there is no reason to override sysusers.d vendor configuration, except to block certain users or groups from being created. See Also systemd1, systemd-sysusers8 systemd-229/man/telinit.xml000066400000000000000000000127371265713322000160400ustar00rootroot00000000000000 telinit systemd Developer Lennart Poettering lennart@poettering.net telinit 8 telinit Change SysV runlevel telinit OPTIONS COMMAND Description telinit may be used to change the SysV system runlevel. Since the concept of SysV runlevels is obsolete the runlevel requests will be transparently translated into systemd unit activation requests. Options The following options are understood: Do not send wall message before reboot/halt/power-off. The following commands are understood: 0 Power-off the machine. This is translated into an activation request for poweroff.target and is equivalent to systemctl poweroff. 6 Reboot the machine. This is translated into an activation request for reboot.target and is equivalent to systemctl reboot. 2 3 4 5 Change the SysV runlevel. This is translated into an activation request for runlevel2.target, runlevel3.target, ... and is equivalent to systemctl isolate runlevel2.target, systemctl isolate runlevel3.target, ... 1 s S Change into system rescue mode. This is translated into an activation request for rescue.target and is equivalent to systemctl rescue. q Q Reload daemon configuration. This is equivalent to systemctl daemon-reload. u U Serialize state, reexecute daemon and deserialize state again. This is equivalent to systemctl daemon-reexec. Exit status On success, 0 is returned, a non-zero failure code otherwise. Notes This is a legacy command available for compatibility only. It should not be used anymore, as the concept of runlevels is obsolete. See Also systemd1, systemctl1, wall1 systemd-229/man/timedatectl.xml000066400000000000000000000234111265713322000166560ustar00rootroot00000000000000 timedatectl systemd Developer Lennart Poettering lennart@poettering.net timedatectl 1 timedatectl Control the system time and date timedatectl OPTIONS COMMAND Description timedatectl may be used to query and change the system clock and its settings. Use systemd-firstboot1 to initialize the system time zone for mounted (but not booted) system images. Options The following options are understood: Do not query the user for authentication for privileged operations. If set-local-rtc is invoked and this option is passed, the system clock is synchronized from the RTC again, taking the new setting into account. Otherwise, the RTC is synchronized from the system clock. The following commands are understood: status Show current settings of the system clock and RTC, including whether network time synchronization is on. Note that whether network time synchronization is on simply reflects whether the systemd-timesyncd.service unit is enabled. Even if this command shows the status as off, a different service might still synchronize the clock with the network. set-time [TIME] Set the system clock to the specified time. This will also update the RTC time accordingly. The time may be specified in the format "2012-10-30 18:17:16". set-timezone [TIMEZONE] Set the system time zone to the specified value. Available timezones can be listed with list-timezones. If the RTC is configured to be in the local time, this will also update the RTC time. This call will alter the /etc/localtime symlink. See localtime5 for more information. list-timezones List available time zones, one per line. Entries from the list can be set as the system timezone with set-timezone. set-local-rtc [BOOL] Takes a boolean argument. If 0, the system is configured to maintain the RTC in universal time. If 1, it will maintain the RTC in local time instead. Note that maintaining the RTC in the local timezone is not fully supported and will create various problems with time zone changes and daylight saving adjustments. If at all possible, keep the RTC in UTC mode. Note that invoking this will also synchronize the RTC from the system clock, unless is passed (see above). This command will change the 3rd line of /etc/adjtime, as documented in hwclock8. set-ntp [BOOL] Takes a boolean argument. Controls whether network time synchronization is active and enabled (if available). This enables and starts, or disables and stops the systemd-timesyncd.service unit. It does not affect the state of any other, unrelated network time synchronization services that might be installed on the system. This command is hence mostly equivalent to: systemctl enable --now systemd-timesyncd.service and systemctl disable --now systemd-timesyncd.service, but is protected by a different access policy. Note that even if time synchronization is turned off with this command, another unrelated system service might still synchronize the clock with the network. Also note that, strictly speaking, systemd-timesyncd.service does more than just network time synchronization, as it ensures a monotonic clock on systems without RTC even if no network is available. See systemd-timesyncd.service8 for details about this. Exit status On success, 0 is returned, a non-zero failure code otherwise. Examples Show current settings: $ timedatectl Local time: Di 2015-04-07 16:26:56 CEST Universal time: Di 2015-04-07 14:26:56 UTC RTC time: Di 2015-04-07 14:26:56 Time zone: Europe/Berlin (CEST, +0200) Network time on: yes NTP synchronized: yes RTC in local TZ: no Enable network time synchronization: $ timedatectl set-ntp true ==== AUTHENTICATING FOR org.freedesktop.timedate1.set-ntp === Authentication is required to control whether network time synchronization shall be enabled. Authenticating as: user Password: ******** ==== AUTHENTICATION COMPLETE === $ systemctl status systemd-timesyncd.service ● systemd-timesyncd.service - Network Time Synchronization Loaded: loaded (/usr/lib/systemd/system/systemd-timesyncd.service; enabled) Active: active (running) since Mo 2015-03-30 14:20:38 CEST; 5s ago Docs: man:systemd-timesyncd.service(8) Main PID: 595 (systemd-timesyn) Status: "Using Time Server 216.239.38.15:123 (time4.google.com)." CGroup: /system.slice/systemd-timesyncd.service └─595 /usr/lib/systemd/systemd-timesyncd ... See Also systemd1, hwclock8, date1, localtime5, systemctl1, systemd-timedated.service8, systemd-timesyncd.service8, systemd-firstboot1 systemd-229/man/timesyncd.conf.xml000066400000000000000000000100471265713322000173030ustar00rootroot00000000000000 timesyncd.conf systemd Developer Lennart Poettering lennart@poettering.net timesyncd.conf 5 timesyncd.conf timesyncd.conf.d Network Time Synchronization configuration files /etc/systemd/timesyncd.conf /etc/systemd/timesyncd.conf.d/*.conf /run/systemd/timesyncd.conf.d/*.conf /usr/lib/systemd/timesyncd.conf.d/*.conf Description These configuration files control NTP network time synchronization. Options The following settings are configured in the [Time] section: NTP= A space-separated list of NTP server host names or IP addresses. During runtime this list is combined with any per-interface NTP servers acquired from systemd-networkd.service8. systemd-timesyncd will contact all configured system or per-interface servers in turn until one is found that responds. This setting defaults to an empty list. FallbackNTP= A space-separated list of NTP server host names or IP addresses to be used as the fallback NTP servers. Any per-interface NTP servers obtained from systemd-networkd.service8 take precedence over this setting, as do any servers set via NTP= above. This setting is hence only used if no other NTP server information is known. If this option is not given, a compiled-in list of NTP servers is used instead. See Also systemd1, systemd-timesyncd.service8, systemd-networkd.service8 systemd-229/man/tmpfiles.d.xml000066400000000000000000000734401265713322000164330ustar00rootroot00000000000000 tmpfiles.d systemd Documentation Brandon Philips brandon@ifup.org tmpfiles.d 5 tmpfiles.d Configuration for creation, deletion and cleaning of volatile and temporary files /etc/tmpfiles.d/*.conf /run/tmpfiles.d/*.conf /usr/lib/tmpfiles.d/*.conf Description systemd-tmpfiles uses the configuration files from the above directories to describe the creation, cleaning and removal of volatile and temporary files and directories which usually reside in directories such as /run or /tmp. Volatile and temporary files and directories are those located in /run (and its alias /var/run), /tmp, /var/tmp, the API file systems such as /sys or /proc, as well as some other directories below /var. System daemons frequently require private runtime directories below /run to place communication sockets and similar in. For these, consider declaring them in their unit files using RuntimeDirectory= (see systemd.exec5 for details), if this is feasible. Configuration Format Each configuration file shall be named in the style of package.conf or package-part.conf. The second variant should be used when it is desirable to make it easy to override just this part of configuration. Files in /etc/tmpfiles.d override files with the same name in /usr/lib/tmpfiles.d and /run/tmpfiles.d. Files in /run/tmpfiles.d override files with the same name in /usr/lib/tmpfiles.d. Packages should install their configuration files in /usr/lib/tmpfiles.d. Files in /etc/tmpfiles.d are reserved for the local administrator, who may use this logic to override the configuration files installed by vendor packages. All configuration files are sorted by their filename in lexicographic order, regardless of which of the directories they reside in. If multiple files specify the same path, the entry in the file with the lexicographically earliest name will be applied. All other conflicting entries will be logged as errors. When two lines are prefix and suffix of each other, then the prefix is always processed first, the suffix later. Lines that take globs are applied after those accepting no globs. If multiple operations shall be applied on the same file, (such as ACL, xattr, file attribute adjustments), these are always done in the same fixed order. Otherwise, the files/directories are processed in the order they are listed. If the administrator wants to disable a configuration file supplied by the vendor, the recommended way is to place a symlink to /dev/null in /etc/tmpfiles.d/ bearing the same filename. The configuration format is one line per path containing type, path, mode, ownership, age, and argument fields: #Type Path Mode UID GID Age Argument d /run/user 0755 root root 10d - L /tmp/foobar - - - - /dev/null Fields may be enclosed within quotes and contain C-style escapes. Type The type consists of a single letter and optionally an exclamation mark. The following line types are understood: f Create a file if it does not exist yet. If the argument parameter is given, it will be written to the file. Does not follow symlinks. F Create or truncate a file. If the argument parameter is given, it will be written to the file. Does not follow symlinks. w Write the argument parameter to a file, if the file exists. Lines of this type accept shell-style globs in place of normal path names. The argument parameter will be written without a trailing newline. C-style backslash escapes are interpreted. Follows symlinks. d Create a directory if it does not exist yet. D Create or empty a directory. v Create a subvolume if the path does not exist yet, the file system supports subvolumes (btrfs), and the system itself is installed into a subvolume (specifically: the root directory / is itself a subvolume). Otherwise, create a normal directory, in the same way as d. A subvolume created with this line type is not assigned to any higher-level quota group. For that, use q or Q, which allow creating simple quota group hierarchies, see below. q Similar to v. However, makes sure that the subvolume will be assigned to the same higher-level quota groups as the subvolume it has been created in. This ensures that higher-level limits and accounting applied to the parent subvolume also include the specified subvolume. On non-btrfs file systems, this line type is identical to d. If the subvolume already exists and is already assigned to one or more higher level quota groups, no change to the quota hierarchy is made. Also see Q below. See btrfs-qgroup8 for details about the btrfs quota group concept. Q Similar to q. However, instead of copying the higher-level quota group assignments from the parent as-is, the lowest quota group of the parent subvolume is determined that is not the leaf quota group. Then, an "intermediary" quota group is inserted that is one level below this level, and shares the same ID part as the specified subvolume. If no higher-level quota group exists for the parent subvolume, a new quota group at level 255 sharing the same ID as the specified subvolume is inserted instead. This new intermediary quota group is then assigned to the parent subvolume's higher-level quota groups, and the specified subvolume's leaf quota group is assigned to it. Effectively, this has a similar effect as q, however introduces a new higher-level quota group for the specified subvolume that may be used to enforce limits and accounting to the specified subvolume and children subvolume created within it. Thus, by creating subvolumes only via q and Q, a concept of "subtree quotas" is implemented. Each subvolume for which Q is set will get a "subtree" quota group created, and all child subvolumes created within it will be assigned to it. Each subvolume for which q is set will not get such a "subtree" quota group, but it is ensured that they are added to the same "subtree" quota group as their immediate parents. It is recommended to use Q for subvolumes that typically contain further subvolumes, and where it is desirable to have accounting and quota limits on all child subvolumes together. Examples for Q are typically /home or /var/lib/machines. In contrast, q should be used for subvolumes that either usually do not include further subvolumes or where no accounting and quota limits are needed that apply to all child subvolumes together. Examples for q are typically /var or /var/tmp. As with Q, q has no effect on the quota group hierarchy if the subvolume exists and already has at least one higher-level quota group assigned. p p+ Create a named pipe (FIFO) if it does not exist yet. If suffixed with + and a file already exists where the pipe is to be created, it will be removed and be replaced by the pipe. L L+ Create a symlink if it does not exist yet. If suffixed with + and a file already exists where the symlink is to be created, it will be removed and be replaced by the symlink. If the argument is omitted, symlinks to files with the same name residing in the directory /usr/share/factory/ are created. Note that permissions and ownership on symlinks are ignored. c c+ Create a character device node if it does not exist yet. If suffixed with + and a file already exists where the device node is to be created, it will be removed and be replaced by the device node. It is recommended to suffix this entry with an exclamation mark to only create static device nodes at boot, as udev will not manage static device nodes that are created at runtime. b b+ Create a block device node if it does not exist yet. If suffixed with + and a file already exists where the device node is to be created, it will be removed and be replaced by the device node. It is recommended to suffix this entry with an exclamation mark to only create static device nodes at boot, as udev will not manage static device nodes that are created at runtime. C Recursively copy a file or directory, if the destination files or directories do not exist yet. Note that this command will not descend into subdirectories if the destination directory already exists. Instead, the entire copy operation is skipped. If the argument is omitted, files from the source directory /usr/share/factory/ with the same name are copied. Does not follow symlinks. x Ignore a path during cleaning. Use this type to exclude paths from clean-up as controlled with the Age parameter. Note that lines of this type do not influence the effect of r or R lines. Lines of this type accept shell-style globs in place of normal path names. X Ignore a path during cleaning. Use this type to exclude paths from clean-up as controlled with the Age parameter. Unlike x, this parameter will not exclude the content if path is a directory, but only directory itself. Note that lines of this type do not influence the effect of r or R lines. Lines of this type accept shell-style globs in place of normal path names. r Remove a file or directory if it exists. This may not be used to remove non-empty directories, use R for that. Lines of this type accept shell-style globs in place of normal path names. Does not follow symlinks. R Recursively remove a path and all its subdirectories (if it is a directory). Lines of this type accept shell-style globs in place of normal path names. Does not follow symlinks. z Adjust the access mode, group and user, and restore the SELinux security context of a file or directory, if it exists. Lines of this type accept shell-style globs in place of normal path names. Does not follow symlinks. Z Recursively set the access mode, group and user, and restore the SELinux security context of a file or directory if it exists, as well as of its subdirectories and the files contained therein (if applicable). Lines of this type accept shell-style globs in place of normal path names. Does not follow symlinks. t Set extended attributes. Lines of this type accept shell-style globs in place of normal path names. This can be useful for setting SMACK labels. Does not follow symlinks. T Recursively set extended attributes. Lines of this type accept shell-style globs in place of normal path names. This can be useful for setting SMACK labels. Does not follow symlinks. h Set file/directory attributes. Lines of this type accept shell-style globs in place of normal path names. The format of the argument field is [+-=][aAcCdDeijsStTu] . The prefix + (the default one) causes the attribute(s) to be added; - causes the attribute(s) to be removed; = causes the attributes to be set exactly as the following letters. The letters aAcCdDeijsStTu select the new attributes for the files, see chattr 1 for further information. Passing only = as argument resets all the file attributes listed above. It has to be pointed out that the = prefix limits itself to the attributes corresponding to the letters listed here. All other attributes will be left untouched. Does not follow symlinks. H Recursively set file/directory attributes. Lines of this type accept shell-style globs in place of normal path names. Does not follow symlinks. a a+ Set POSIX ACLs (access control lists). If suffixed with +, the specified entries will be added to the existing set. systemd-tmpfiles will automatically add the required base entries for user and group based on the access mode of the file, unless base entries already exist or are explicitly specified. The mask will be added if not specified explicitly or already present. Lines of this type accept shell-style globs in place of normal path names. This can be useful for allowing additional access to certain files. Does not follow symlinks. A A+ Same as a and a+, but recursive. Does not follow symlinks. If the exclamation mark is used, this line is only safe of execute during boot, and can break a running system. Lines without the exclamation mark are presumed to be safe to execute at any time, e.g. on package upgrades. systemd-tmpfiles will execute line with an exclamation mark only if option is given. For example: # Make sure these are created by default so that nobody else can d /tmp/.X11-unix 1777 root root 10d # Unlink the X11 lock files r! /tmp/.X[0-9]*-lock The second line in contrast to the first one would break a running system, and will only be executed with . Path The file system path specification supports simple specifier expansion. The following expansions are understood: Specifiers available Specifier Meaning Details %m Machine ID The machine ID of the running system, formatted as string. See machine-id5 for more information. %b Boot ID The boot ID of the running system, formatted as string. See random4 for more information. %H Host name The hostname of the running system. %v Kernel release Identical to uname -r output. %% Escaped % Single percent sign.
Mode The file access mode to use when creating this file or directory. If omitted or when set to -, the default is used: 0755 for directories, 0644 for all other file objects. For z, Z lines, if omitted or when set to -, the file access mode will not be modified. This parameter is ignored for x, r, R, L, t, and a lines. Optionally, if prefixed with ~, the access mode is masked based on the already set access bits for existing file or directories: if the existing file has all executable bits unset, all executable bits are removed from the new access mode, too. Similarly, if all read bits are removed from the old access mode, they will be removed from the new access mode too, and if all write bits are removed, they will be removed from the new access mode too. In addition, the sticky/SUID/SGID bit is removed unless applied to a directory. This functionality is particularly useful in conjunction with Z. UID, GID The user and group to use for this file or directory. This may either be a numeric user/group ID or a user or group name. If omitted or when set to -, the default 0 (root) is used. For z and Z lines, when omitted or when set to -, the file ownership will not be modified. These parameters are ignored for x, r, R, L, t, and a lines. Age The date field, when set, is used to decide what files to delete when cleaning. If a file or directory is older than the current time minus the age field, it is deleted. The field format is a series of integers each followed by one of the following suffixes for the respective time units: s, m or min, h, d, w, ms, and us, meaning seconds, minutes, hours, days, weeks, milliseconds, and microseconds, respectively. Full names of the time units can be used too. If multiple integers and units are specified, the time values are summed. If an integer is given without a unit, s is assumed. When the age is set to zero, the files are cleaned unconditionally. The age field only applies to lines starting with d, D, v, q, Q, C, x and X. If omitted or set to -, no automatic clean-up is done. If the age field starts with a tilde character ~, the clean-up is only applied to files and directories one level inside the directory specified, but not the files and directories immediately inside it. Argument For L lines determines the destination path of the symlink. For c and b, determines the major/minor of the device node, with major and minor formatted as integers, separated by :, e.g. 1:3. For f, F, and w, the argument may be used to specify a short string that is written to the file, suffixed by a newline. For C, specifies the source file or directory. For t and T, determines extended attributes to be set. For a and A, determines ACL attributes to be set. For h and H, determines the file attributes to set. Ignored for all other lines.
Example /etc/tmpfiles.d/screen.conf example screen needs two directories created at boot with specific modes and ownership. d /run/screens 1777 root root 10d d /run/uscreens 0755 root root 10d12h t /run/screen - - - - user.name="John Smith" security.SMACK64=screen /etc/tmpfiles.d/abrt.conf example abrt needs a directory created at boot with specific mode and ownership and its content should be preserved. d /var/tmp/abrt 0755 abrt abrt x /var/tmp/abrt/* See Also systemd1, systemd-tmpfiles8, systemd-delta1, systemd.exec5, attr5, getfattr1, setfattr1, setfacl1, getfacl1, chattr1, btrfs-subvolume8, btrfs-qgroup8
systemd-229/man/udev.conf.xml000066400000000000000000000060751265713322000162550ustar00rootroot00000000000000 udev.conf systemd Developer Kay Sievers kay@vrfy.org udev.conf 5 udev.conf Configuration for device event managing daemon /etc/udev/udev.conf Description systemd-udevd8 expects its main configuration file at /etc/udev/udev.conf. It consists of a set of variables allowing the user to override default udev values. All empty lines or lines beginning with '#' are ignored. The following variables can be set: udev_log The log level. Valid values are the numerical syslog priorities or their textual representations: , and . In addition, systemd-udevd can be configured by command line options and the kernel command line (see systemd-udevd8). See Also systemd-udevd8, udev7, udevadm8 systemd-229/man/udev.xml000066400000000000000000000765311265713322000153350ustar00rootroot00000000000000 udev systemd Developer Greg Kroah-Hartmann greg@kroah.com Developer Kay Sievers kay@vrfy.org udev 7 udev Dynamic device management Description udev supplies the system software with device events, manages permissions of device nodes and may create additional symlinks in the /dev directory, or renames network interfaces. The kernel usually just assigns unpredictable device names based on the order of discovery. Meaningful symlinks or network device names provide a way to reliably identify devices based on their properties or current configuration. The udev daemon, systemd-udevd.service 8, receives device uevents directly from the kernel whenever a device is added or removed from the system, or it changes its state. When udev receives a device event, it matches its configured set of rules against various device attributes to identify the device. Rules that match may provide additional device information to be stored in the udev database or to be used to create meaningful symlink names. All device information udev processes is stored in the udev database and sent out to possible event subscribers. Access to all stored data and the event sources is provided by the library libudev. Rules Files The udev rules are read from the files located in the system rules directory /usr/lib/udev/rules.d, the volatile runtime directory /run/udev/rules.d and the local administration directory /etc/udev/rules.d. All rules files are collectively sorted and processed in lexical order, regardless of the directories in which they live. However, files with identical filenames replace each other. Files in /etc have the highest priority, files in /run take precedence over files with the same name in /usr/lib. This can be used to override a system-supplied rules file with a local file if needed; a symlink in /etc with the same name as a rules file in /usr/lib, pointing to /dev/null, disables the rules file entirely. Rule files must have the extension .rules; other extensions are ignored. Every line in the rules file contains at least one key-value pair. Except for empty lines or lines beginning with #, which are ignored. There are two kinds of keys: match and assignment. If all match keys match against their values, the rule gets applied and the assignment keys get the specified values assigned. A matching rule may rename a network interface, add symlinks pointing to the device node, or run a specified program as part of the event handling. A rule consists of a comma-separated list of one or more key-value pairs. Each key has a distinct operation, depending on the used operator. Valid operators are: == Compare for equality. != Compare for inequality. = Assign a value to a key. Keys that represent a list are reset and only this single value is assigned. += Add the value to a key that holds a list of entries. -= Remove the value from a key that holds a list of entries. := Assign a value to a key finally; disallow any later changes. The following key names can be used to match against device properties. Some of the keys also match against properties of the parent devices in sysfs, not only the device that has generated the event. If multiple keys that match a parent device are specified in a single rule, all these keys must match at one and the same parent device. ACTION Match the name of the event action. DEVPATH Match the devpath of the event device. KERNEL Match the name of the event device. NAME Match the name of a network interface. It can be used once the NAME key has been set in one of the preceding rules. SYMLINK Match the name of a symlink targeting the node. It can be used once a SYMLINK key has been set in one of the preceding rules. There may be multiple symlinks; only one needs to match. SUBSYSTEM Match the subsystem of the event device. DRIVER Match the driver name of the event device. Only set this key for devices which are bound to a driver at the time the event is generated. ATTR{filename} Match sysfs attribute values of the event device. Trailing whitespace in the attribute values is ignored unless the specified match value itself contains trailing whitespace. SYSCTL{kernel parameter} Match a kernel parameter value. KERNELS Search the devpath upwards for a matching device name. SUBSYSTEMS Search the devpath upwards for a matching device subsystem name. DRIVERS Search the devpath upwards for a matching device driver name. ATTRS{filename} Search the devpath upwards for a device with matching sysfs attribute values. If multiple ATTRS matches are specified, all of them must match on the same device. Trailing whitespace in the attribute values is ignored unless the specified match value itself contains trailing whitespace. TAGS Search the devpath upwards for a device with matching tag. ENV{key} Match against a device property value. TAG Match against a device tag. TEST{octal mode mask} Test the existence of a file. An octal mode mask can be specified if needed. PROGRAM Execute a program to determine whether there is a match; the key is true if the program returns successfully. The device properties are made available to the executed program in the environment. The program's standard output is available in the RESULT key. This can only be used for very short-running foreground tasks. For details, see RUN. RESULT Match the returned string of the last PROGRAM call. This key can be used in the same or in any later rule after a PROGRAM call. Most of the fields support shell glob pattern matching and alternate patterns. The following special characters are supported: * Matches zero or more characters. ? Matches any single character. [] Matches any single character specified within the brackets. For example, the pattern string tty[SR] would match either ttyS or ttyR. Ranges are also supported via the - character. For example, to match on the range of all digits, the pattern [0-9] could be used. If the first character following the [ is a !, any characters not enclosed are matched. | Separates alternative patterns. For example, the pattern string abc|x* would match either abc or x*. The following keys can get values assigned: NAME The name to use for a network interface. See systemd.link5 for a higher-level mechanism for setting the interface name. The name of a device node cannot be changed by udev, only additional symlinks can be created. SYMLINK The name of a symlink targeting the node. Every matching rule adds this value to the list of symlinks to be created. The set of characters to name a symlink is limited. Allowed characters are 0-9A-Za-z#+-.:=@_/, valid UTF-8 character sequences, and \x00 hex encoding. All other characters are replaced by a _ character. Multiple symlinks may be specified by separating the names by the space character. In case multiple devices claim the same name, the link always points to the device with the highest link_priority. If the current device goes away, the links are re-evaluated and the device with the next highest link_priority becomes the owner of the link. If no link_priority is specified, the order of the devices (and which one of them owns the link) is undefined. Symlink names must never conflict with the kernel's default device node names, as that would result in unpredictable behavior. OWNER, GROUP, MODE The permissions for the device node. Every specified value overrides the compiled-in default value. SECLABEL{module} Applies the specified Linux Security Module label to the device node. ATTR{key} The value that should be written to a sysfs attribute of the event device. SYSCTL{kernel parameter} The value that should be written to kernel parameter. ENV{key} Set a device property value. Property names with a leading . are neither stored in the database nor exported to events or external tools (run by, for example, the PROGRAM match key). TAG Attach a tag to a device. This is used to filter events for users of libudev's monitor functionality, or to enumerate a group of tagged devices. The implementation can only work efficiently if only a few tags are attached to a device. It is only meant to be used in contexts with specific device filter requirements, and not as a general-purpose flag. Excessive use might result in inefficient event handling. RUN{type} Add a program to the list of programs to be executed after processing all the rules for a specific event, depending on type: program Execute an external program specified as the assigned value. If no absolute path is given, the program is expected to live in /usr/lib/udev; otherwise, the absolute path must be specified. This is the default if no type is specified. builtin As program, but use one of the built-in programs rather than an external one. The program name and following arguments are separated by spaces. Single quotes can be used to specify arguments with spaces. This can only be used for very short-running foreground tasks. Running an event process for a long period of time may block all further events for this or a dependent device. Starting daemons or other long-running processes is not appropriate for udev; the forked processes, detached or not, will be unconditionally killed after the event handling has finished. LABEL A named label to which a GOTO may jump. GOTO Jumps to the next LABEL with a matching name. IMPORT{type} Import a set of variables as device properties, depending on type: program Execute an external program specified as the assigned value and, if it returns successfully, import its output, which must be in environment key format. Path specification, command/argument separation, and quoting work like in RUN. builtin Similar to program, but use one of the built-in programs rather than an external one. file Import a text file specified as the assigned value, the content of which must be in environment key format. db Import a single property specified as the assigned value from the current device database. This works only if the database is already populated by an earlier event. cmdline Import a single property from the kernel command line. For simple flags the value of the property is set to 1. parent Import the stored keys from the parent device by reading the database entry of the parent device. The value assigned to is used as a filter of key names to import (with the same shell glob pattern matching used for comparisons). This can only be used for very short-running foreground tasks. For details see . OPTIONS Rule and device options: Specify the priority of the created symlinks. Devices with higher priorities overwrite existing symlinks of other devices. The default is 0. Usually, control and other possibly unsafe characters are replaced in strings used for device naming. The mode of replacement can be specified with this option. Apply the permissions specified in this rule to the static device node with the specified name. Also, for every tag specified in this rule, create a symlink in the directory /run/udev/static_node-tags/tag pointing at the static device node with the specified name. Static device node creation is performed by systemd-tmpfiles before systemd-udevd is started. The static nodes might not have a corresponding kernel device; they are used to trigger automatic kernel module loading when they are accessed. Watch the device node with inotify; when the node is closed after being opened for writing, a change uevent is synthesized. Disable the watching of a device node with inotify. The NAME, SYMLINK, PROGRAM, OWNER, GROUP, MODE, and RUN fields support simple string substitutions. The RUN substitutions are performed after all rules have been processed, right before the program is executed, allowing for the use of device properties set by earlier matching rules. For all other fields, substitutions are performed while the individual rule is being processed. The available substitutions are: , The kernel name for this device. , The kernel number for this device. For example, sda3 has kernel number 3. , The devpath of the device. , The name of the device matched while searching the devpath upwards for , , , and . The driver name of the device matched while searching the devpath upwards for , , , and . , The value of a sysfs attribute found at the device where all keys of the rule have matched. If the matching device does not have such an attribute, and a previous , , , or test selected a parent device, then the attribute from that parent device is used. If the attribute is a symlink, the last element of the symlink target is returned as the value. , A device property value. , The kernel major number for the device. , The kernel minor number for the device. , The string returned by the external program requested with PROGRAM. A single part of the string, separated by a space character, may be selected by specifying the part number as an attribute: %c{N}. If the number is followed by the + character, this part plus all remaining parts of the result string are substituted: %c{N+}. , The node name of the parent device. The current name of the device. If not changed by a rule, it is the name of the kernel device. A space-separated list of the current symlinks. The value is only set during a remove event or if an earlier rule assigned a value. , The udev_root value. , The sysfs mount point. , The name of the device node. The % character itself. The $ character itself. See Also systemd-udevd.service8 , udevadm8 , systemd.link5 systemd-229/man/udev_device_get_syspath.xml000066400000000000000000000202661265713322000212600ustar00rootroot00000000000000 %entities; ]> udev_device_get_syspath systemd Developer David Herrmann dh.herrmann@gmail.com udev_device_get_syspath 3 udev_device_get_syspath udev_device_get_sysname udev_device_get_sysnum udev_device_get_devpath udev_device_get_devnode udev_device_get_devnum udev_device_get_devtype udev_device_get_subsystem udev_device_get_driver udev_device_get_udev udev_device_get_parent udev_device_get_parent_with_subsystem_devtype udev_device_get_is_initialized udev_device_get_action Query device properties #include <libudev.h> const char *udev_device_get_syspath struct udev_device *udev_device const char *udev_device_get_sysname struct udev_device *udev_device const char *udev_device_get_sysnum struct udev_device *udev_device const char *udev_device_get_devpath struct udev_device *udev_device const char *udev_device_get_devnode struct udev_device *udev_device dev_t udev_device_get_devnum struct udev_device *udev_device const char *udev_device_get_devtype struct udev_device *udev_device const char *udev_device_get_subsystem struct udev_device *udev_device const char *udev_device_get_driver struct udev_device *udev_device struct udev *udev_device_get_udev struct udev_device *udev_device struct udev_device *udev_device_get_parent struct udev_device *udev_device struct udev_device *udev_device_get_parent_with_subsystem_devtype struct udev_device *udev_device int udev_device_get_is_initialized struct udev_device *udev_device const char *udev_device_get_action struct udev_device *udev_device const char *subsystem const char *devtype Return Value On success, udev_device_get_syspath(), udev_device_get_sysname(), udev_device_get_sysnum(), udev_device_get_devpath(), udev_device_get_devnode(), udev_device_get_devtype(), udev_device_get_subsystem(), udev_device_get_driver() and udev_device_get_action() return a pointer to a constant string that describes the requested property. The lifetime of this string is bound to the device it was requested on. On failure, each function may return NULL. On success, udev_device_get_devnum() returns the device type of the passed device. On failure, a device type with minor and major number set to 0 is returned. udev_device_get_udev() always returns a valid pointer to the udev context that this device belongs to. On success, udev_device_get_parent() and udev_device_get_parent_with_subsystem_devtype() return a pointer to the parent device. No additional reference to this device is acquired, but the child device owns a reference to such a parent device. On failure, NULL is returned. On success, udev_device_get_is_initialized() returns either 1 or 0, depending on whether the passed device is initialized or not. On failure, a negative error code is returned. See Also udev_new3, udev_device_new_from_syspath3, udev_device_has_tag3, udev_enumerate_new3, udev_monitor_new_from_netlink3, udev_list_entry3, systemd1, systemd-229/man/udev_device_has_tag.xml000066400000000000000000000146131265713322000203330ustar00rootroot00000000000000 %entities; ]> udev_device_has_tag systemd Developer David Herrmann dh.herrmann@gmail.com udev_device_has_tag 3 udev_device_has_tag udev_device_get_devlinks_list_entry udev_device_get_properties_list_entry udev_device_get_tags_list_entry udev_device_get_sysattr_list_entry udev_device_get_property_value udev_device_get_sysattr_value udev_device_set_sysattr_value Retrieve or set device attributes #include <libudev.h> struct udev_list_entry *udev_device_get_devlinks_list_entry struct udev_device *udev_device struct udev_list_entry *udev_device_get_properties_list_entry struct udev_device *udev_device struct udev_list_entry *udev_device_get_tags_list_entry struct udev_device *udev_device struct udev_list_entry *udev_device_get_sysattr_list_entry struct udev_device *udev_device const char *udev_device_get_property_value struct udev_device *udev_device const char *key int udev_device_has_tag struct udev_device *udev_device const char *tag const char *udev_device_get_sysattr_value struct udev_device *udev_device const char *sysattr int udev_device_set_sysattr_value struct udev_device *udev_device const char *sysattr const char *value Return Value On success, udev_device_get_devlinks_list_entry(), udev_device_get_properties_list_entry(), udev_device_get_tags_list_entry() and udev_device_get_sysattr_list_entry() return a pointer to the first entry of the retrieved list. If that list is empty, or if an error occurred, NULL is returned. On success, udev_device_get_property_value() and udev_device_get_sysattr_value() return a pointer to a constant string of the requested value. On error, NULL is returned. On success, udev_device_set_sysattr_value() returns an integer greater than, or equal to, 0. On failure, a negative error code is returned. On success, udev_device_has_tag() returns 1 or 0, depending on whether the device has the given tag or not. On failure, a negative error code is returned. See Also udev_new3, udev_device_new_from_syspath3, udev_device_get_syspath3, udev_enumerate_new3, udev_monitor_new_from_netlink3, udev_list_entry3, systemd1, systemd-229/man/udev_device_new_from_syspath.xml000066400000000000000000000223671265713322000223210ustar00rootroot00000000000000 %entities; ]> udev_device_new_from_syspath systemd Developer David Herrmann dh.herrmann@gmail.com udev_device_new_from_syspath 3 udev_device_new_from_syspath udev_device_new_from_devnum udev_device_new_from_subsystem_sysname udev_device_new_from_device_id udev_device_new_from_environment udev_device_ref udev_device_unref Create, acquire and release a udev device object #include <libudev.h> struct udev_device *udev_device_new_from_syspath struct udev *udev const char *syspath struct udev_device *udev_device_new_from_devnum struct udev *udev char type dev_t devnum struct udev_device *udev_device_new_from_subsystem_sysname struct udev *udev const char *subsystem const char *sysname struct udev_device *udev_device_new_from_device_id struct udev *udev const char *id struct udev_device *udev_device_new_from_environment struct udev *udev struct udev_device *udev_device_ref struct udev_device *udev_device struct udev_device *udev_device_unref struct udev_device *udev_device Description udev_device_new_from_syspath, udev_device_new_from_devnum, udev_device_new_from_subsystem_sysname, udev_device_new_from_device_id, and udev_device_new_from_environment allocate a new udev device object and returns a pointer to it. This object is opaque and must not be accessed by the caller via different means than functions provided by libudev. Initially, the reference count of the device is 1. You can acquire further references, and drop gained references via udev_device_ref() and udev_device_unref(). Once the reference count hits 0, the device object is destroyed and freed. udev_device_new_from_syspath, udev_device_new_from_devnum, udev_device_new_from_subsystem_sysname, and udev_device_new_from_device_id create the device object based on information found in /sys, annotated with properties from the udev-internal device database. A syspath is any subdirectory of /sys, with the restriction that a subdirectory of /sys/devices (or a symlink to one) represents a real device and as such must contain a uevent file. udev_device_new_from_devnum takes a device type, which can be b for block devices or c for character devices, as well as a devnum (see makedev3). udev_device_new_from_subsystem_sysname looks up devices based on the provided subsystem and sysname (see udev_device_get_subsystem3 and udev_device_get_sysname3) and udev_device_new_from_device_id looks up devices based on the provided device ID, which is a special string in one of the following four forms: Device ID strings Example Explanation b8:2 block device major:minorc128:1 char device major:minorn3 network device ifindex+sound:card29 kernel driver core subsystem:device name
udev_device_new_from_environment creates a device from the current environment (see environ7). Each key-value pair is interpreted in the same way as if it was received in an uevent (see udev_monitor_receive_device3). The keys DEVPATH, SUBSYSTEM, ACTION, and SEQNUM are mandatory.
Return Value On success, udev_device_new_from_syspath(), udev_device_new_from_devnum(), udev_device_new_from_subsystem_sysname(), udev_device_new_from_device_id() and udev_device_new_from_environment() return a pointer to the allocated udev device. On failure, NULL is returned, and errno is set appropriately. udev_device_ref() returns the argument that it was passed, unmodified. udev_device_unref() always returns NULL. See Also udev_new3, udev_device_get_syspath3, udev_device_has_tag3, udev_enumerate_new3, udev_monitor_new_from_netlink3, udev_list_entry3, systemd1,
systemd-229/man/udev_enumerate_add_match_subsystem.xml000066400000000000000000000151601265713322000234730ustar00rootroot00000000000000 %entities; ]> udev_enumerate_add_match_subsystem systemd Developer David Herrmann dh.herrmann@gmail.com udev_enumerate_add_match_subsystem 3 udev_enumerate_add_match_subsystem udev_enumerate_add_nomatch_subsystem udev_enumerate_add_match_sysattr udev_enumerate_add_nomatch_sysattr udev_enumerate_add_match_property udev_enumerate_add_match_sysname udev_enumerate_add_match_tag udev_enumerate_add_match_parent udev_enumerate_add_match_is_initialized Modify filters #include <libudev.h> int udev_enumerate_add_match_subsystem struct udev_enumerate *udev_enumerate const char *subsystem int udev_enumerate_add_nomatch_subsystem struct udev_enumerate *udev_enumerate const char *subsystem int udev_enumerate_add_match_sysattr struct udev_enumerate *udev_enumerate const char *sysattr const char *value int udev_enumerate_add_nomatch_sysattr struct udev_enumerate *udev_enumerate const char *sysattr const char *value int udev_enumerate_add_match_property struct udev_enumerate *udev_enumerate const char *property const char *value int udev_enumerate_add_match_sysname struct udev_enumerate *udev_enumerate const char *sysname int udev_enumerate_add_match_tag struct udev_enumerate *udev_enumerate const char *tag int udev_enumerate_add_match_parent struct udev_enumerate *udev_enumerate struct udev_device *parent int udev_enumerate_add_match_is_initialized struct udev_enumerate *udev_enumerate Return Value On success, udev_enumerate_add_match_subsystem, udev_enumerate_add_nomatch_subsystem, udev_enumerate_add_match_sysattr, udev_enumerate_add_nomatch_sysattr, udev_enumerate_add_match_property, udev_enumerate_add_match_sysname, udev_enumerate_add_match_tag, udev_enumerate_add_match_parent and udev_enumerate_add_match_is_initialized return an integer greater than, or equal to, 0. See Also udev_new3, udev_device_new_from_syspath3, udev_enumerate_new3, udev_enumerate_scan_devices3, udev_monitor_new_from_netlink3, udev_list_entry3, systemd1, systemd-229/man/udev_enumerate_new.xml000066400000000000000000000076121265713322000202450ustar00rootroot00000000000000 %entities; ]> udev_enumerate_new systemd Developer David Herrmann dh.herrmann@gmail.com udev_enumerate_new 3 udev_enumerate_new udev_enumerate_ref udev_enumerate_unref Create, acquire and release a udev enumerate object #include <libudev.h> struct udev_enumerate *udev_enumerate_new struct udev *udev struct udev_enumerate *udev_enumerate_ref struct udev_enumerate *udev_enumerate struct udev_enumerate *udev_enumerate_unref struct udev_enumerate *udev_enumerate Return Value On success, udev_enumerate_new() returns a pointer to the allocated udev monitor. On failure, NULL is returned. udev_enumerate_ref() returns the argument that it was passed, unmodified. udev_enumerate_unref() always returns NULL. See Also udev_new3, udev_device_new_from_syspath3, udev_enumerate_add_match_subsystem3, udev_enumerate_scan_devices3, udev_monitor_new_from_netlink3, udev_list_entry3, systemd1, systemd-229/man/udev_enumerate_scan_devices.xml000066400000000000000000000115161265713322000221000ustar00rootroot00000000000000 %entities; ]> udev_enumerate_scan_devices systemd Developer David Herrmann dh.herrmann@gmail.com udev_enumerate_scan_devices 3 udev_enumerate_scan_devices udev_enumerate_scan_subsystems udev_enumerate_get_list_entry udev_enumerate_add_syspath udev_enumerate_get_udev Query or modify a udev enumerate object #include <libudev.h> int udev_enumerate_scan_devices struct udev_enumerate *udev_enumerate int udev_enumerate_scan_subsystems struct udev_enumerate *udev_enumerate struct udev_list_entry *udev_enumerate_get_list_entry struct udev_enumerate *udev_enumerate int udev_enumerate_add_syspath struct udev_enumerate *udev_enumerate const char *syspath struct udev *udev_enumerate_get_udev struct udev_enumerate *udev_enumerate Return Value On success, udev_enumerate_scan_devices(), udev_enumerate_scan_subsystems() and udev_enumerate_add_syspath() return an integer greater than, or equal to, 0. On success, udev_enumerate_get_list_entry() returns a pointer to the first entry in the list of found devices. If the list is empty, or on failure, NULL is returned. udev_enumerate_get_udev() always returns a pointer to the udev context that this enumerated object is associated with. See Also udev_new3, udev_device_new_from_syspath3, udev_enumerate_new3, udev_enumerate_add_match_subsystem3, udev_monitor_new_from_netlink3, udev_list_entry3, systemd1, systemd-229/man/udev_list_entry.xml000066400000000000000000000104141265713322000175750ustar00rootroot00000000000000 %entities; ]> udev_list_entry systemd Developer David Herrmann dh.herrmann@gmail.com udev_list_entry 3 udev_list_entry udev_list_entry_get_next udev_list_entry_get_by_name udev_list_entry_get_name udev_list_entry_get_value Iterate and access udev lists #include <libudev.h> struct udev_list_entry *udev_list_entry_get_next struct udev_list_entry *list_entry struct udev_list_entry *udev_list_entry_get_by_name struct udev_list_entry *list_entry const char *name const char *udev_list_entry_get_name struct udev_list_entry *list_entry const char *udev_list_entry_get_value struct udev_list_entry *list_entry Return Value On success, udev_list_entry_get_next() and udev_list_entry_get_by_name() return a pointer to the requested list entry. If no such entry can be found, or on failure, NULL is returned. On success, udev_list_entry_get_name() and udev_list_entry_get_value() return a pointer to a constant string representing the requested value. The string is bound to the lifetime of the list entry itself. On failure, NULL is returned. See Also udev_new3, udev_device_new_from_syspath3, udev_enumerate_new3, udev_monitor_new_from_netlink3, systemd1, systemd-229/man/udev_monitor_filter_update.xml000066400000000000000000000106361265713322000220050ustar00rootroot00000000000000 %entities; ]> udev_monitor_filter_update systemd Developer David Herrmann dh.herrmann@gmail.com udev_monitor_filter_update 3 udev_monitor_filter_update udev_monitor_filter_remove udev_monitor_filter_add_match_subsystem_devtype udev_monitor_filter_add_match_tag Modify filters #include <libudev.h> int udev_monitor_filter_update struct udev_monitor *udev_monitor int udev_monitor_filter_remove struct udev_monitor *udev_monitor int udev_monitor_filter_add_match_subsystem_devtype struct udev_monitor *udev_monitor const char *subsystem const char *devtype int udev_monitor_filter_add_match_tag struct udev_monitor *udev_monitor const char *tag Return Value On success, udev_monitor_filter_update(), udev_monitor_filter_remove(), udev_monitor_filter_add_match_subsystem_devtype() and udev_monitor_filter_add_match_tag() return an integer greater than, or equal to, 0. On failure, a negative error code is returned. See Also udev_new3, udev_device_new_from_syspath3, udev_enumerate_new3, udev_monitor_new_from_netlink3, udev_monitor_receive_device3, udev_list_entry3, systemd1, systemd-229/man/udev_monitor_new_from_netlink.xml000066400000000000000000000077461265713322000225260ustar00rootroot00000000000000 %entities; ]> udev_monitor_new_from_netlink systemd Developer David Herrmann dh.herrmann@gmail.com udev_monitor_new_from_netlink 3 udev_monitor_new_from_netlink udev_monitor_ref udev_monitor_unref Create, acquire and release a udev monitor object #include <libudev.h> struct udev_monitor *udev_monitor_new_from_netlink struct udev *udev const char *name struct udev_monitor *udev_monitor_ref struct udev_monitor *udev_monitor struct udev_monitor *udev_monitor_unref struct udev_monitor *udev_monitor Return Value On success, udev_monitor_new_from_netlink() returns a pointer to the allocated udev monitor. On failure, NULL is returned. udev_monitor_ref() returns the argument that it was passed, unmodified. udev_monitor_unref() always returns NULL. See Also udev_new3, udev_device_new_from_syspath3, udev_enumerate_new3, udev_monitor_filter_update3, udev_monitor_receive_device3, udev_list_entry3, systemd1, systemd-229/man/udev_monitor_receive_device.xml000066400000000000000000000117571265713322000221240ustar00rootroot00000000000000 %entities; ]> udev_monitor_receive_device systemd Developer David Herrmann dh.herrmann@gmail.com udev_monitor_receive_device 3 udev_monitor_receive_device udev_monitor_enable_receiving udev_monitor_set_receive_buffer_size udev_monitor_get_fd udev_monitor_get_udev Query and modify device monitor #include <libudev.h> struct udev_device *udev_monitor_receive_device struct udev_monitor *udev_monitor int udev_monitor_enable_receiving struct udev_monitor *udev_monitor int udev_monitor_set_receive_buffer_size struct udev_monitor *udev_monitor int size int udev_monitor_get_fd struct udev_monitor *udev_monitor struct udev *udev_monitor_get_udev struct udev_monitor *udev_monitor Return Value On success, udev_monitor_receive_device() returns a pointer to a newly referenced device that was received via the monitor. The caller is responsible to drop this reference when done. On failure, NULL is returned. On success, udev_monitor_enable_receiving() and udev_monitor_set_receive_buffer_size() return an integer greater than, or equal to, 0. On failure, a negative error code is returned. On success, udev_monitor_get_fd() returns the file descriptor used by this monitor. On failure, a negative error code is returned. udev_monitor_get_udev() always returns a pointer to the udev context that this monitor is associated with. See Also udev_new3, udev_device_new_from_syspath3, udev_enumerate_new3, udev_monitor_new_from_netlink3, udev_monitor_filter_update3, udev_list_entry3, systemd1, systemd-229/man/udev_new.xml000066400000000000000000000067311265713322000162010ustar00rootroot00000000000000 %entities; ]> udev_new systemd Developer David Herrmann dh.herrmann@gmail.com udev_new 3 udev_new udev_ref udev_unref Create, acquire and release a udev context object #include <libudev.h> struct udev *udev_new void struct udev *udev_ref struct udev *udev struct udev *udev_unref struct udev *udev Description udev_new() allocates a new udev context object and returns a pointer to it. This object is opaque and must not be accessed by the caller via different means than functions provided by libudev. Initially, the reference count of the context is 1. You can acquire further references, and drop gained references via udev_ref() and udev_unref(). Once the reference count hits 0, the context object is destroyed and freed. Return Value On success, udev_new() returns a pointer to the allocated udev context. On failure, NULL is returned. udev_ref() returns the argument that it was passed, unmodified. udev_unref() always returns NULL. See Also systemd1, systemd-229/man/udevadm.xml000066400000000000000000000555741265713322000160230ustar00rootroot00000000000000 udevadm systemd Developer Kay Sievers kay@vrfy.org udevadm 8 udevadmudev management tool udevadm udevadm info options udevadm trigger options udevadm settle options udevadm control command udevadm monitor options udevadm test options devpath udevadm test-builtin options command devpath Description udevadm expects a command and command specific options. It controls the runtime behavior of systemd-udevd, requests kernel events, manages the event queue, and provides simple debugging mechanisms. Options Print debug messages to standard error. Print version number. Print help text. udevadm info <arg choice="opt"><replaceable>options</replaceable></arg> <arg choice="opt"><replaceable>devpath</replaceable>|<replaceable>file</replaceable></arg> Queries the udev database for device information stored in the udev database. It can also query the properties of a device from its sysfs representation to help creating udev rules that match this device. Query the database for the specified type of device data. It needs the or to identify the specified device. Valid TYPEs are: name, symlink, path, property, all. The /sys path of the device to query, e.g. /sys/class/block/sda. Note that this option usually is not very useful, since udev can guess the type of the argument, so udevadm --devpath=/class/block/sda is equivalent to udevadm /sys/class/block/sda. The name of the device node or a symlink to query, e.g. /dev/sda. Note that this option usually is not very useful, since udev can guess the type of the argument, so udevadm --name=sda is equivalent to udevadm /dev/sda. Print absolute paths in name or symlink query. Print all sysfs properties of the specified device that can be used in udev rules to match the specified device. It prints all devices along the chain, up to the root of sysfs that can be used in udev rules. Print output as key/value pairs. Values are enclosed in single quotes. Add a prefix to the key name of exported values. Print major/minor numbers of the underlying device, where the file lives on. Export the content of the udev database. Cleanup the udev database. Print version. Print help text. In addition, an optional positional argument can be used to specify a device name or a sys path. It must start with /dev or /sys respectively. udevadm trigger <arg choice="opt"><replaceable>options</replaceable></arg> <arg choice="opt" rep="repeat"><replaceable>devpath</replaceable>|<replaceable>file</replaceable></arg> Request device events from the kernel. Primarily used to replay events at system coldplug time. Print the list of devices which will be triggered. Do not actually trigger the event. Trigger a specific type of devices. Valid types are: devices, subsystems. The default value is devices. Type of event to be triggered. The default value is change. Trigger events for devices which belong to a matching subsystem. This option can be specified multiple times and supports shell style pattern matching. Do not trigger events for devices which belong to a matching subsystem. This option can be specified multiple times and supports shell style pattern matching. Trigger events for devices with a matching sysfs attribute. If a value is specified along with the attribute name, the content of the attribute is matched against the given value using shell style pattern matching. If no value is specified, the existence of the sysfs attribute is checked. This option can be specified multiple times. Do not trigger events for devices with a matching sysfs attribute. If a value is specified along with the attribute name, the content of the attribute is matched against the given value using shell style pattern matching. If no value is specified, the existence of the sysfs attribute is checked. This option can be specified multiple times. Trigger events for devices with a matching property value. This option can be specified multiple times and supports shell style pattern matching. Trigger events for devices with a matching tag. This option can be specified multiple times. Trigger events for devices with a matching sys device path. This option can be specified multiple times and supports shell style pattern matching. Trigger events for devices with a matching device path. This option can be specified multiple times. Trigger events for all children of a given device. Print help text. In addition, optional positional arguments can be used to specify device names or sys paths. They must start with /dev or /sys respectively. udevadm settle <arg choice="opt"><replaceable>options</replaceable></arg> Watches the udev event queue, and exits if all current events are handled. Maximum number of seconds to wait for the event queue to become empty. The default value is 120 seconds. A value of 0 will check if the queue is empty and always return immediately. Stop waiting if file exists. Print help text. udevadm control <replaceable>command</replaceable> Modify the internal state of the running udev daemon. Signal and wait for systemd-udevd to exit. Set the internal log level of systemd-udevd. Valid values are the numerical syslog priorities or their textual representations: , , , , , , , and . Signal systemd-udevd to stop executing new events. Incoming events will be queued. Signal systemd-udevd to enable the execution of events. Signal systemd-udevd to reload the rules files and other databases like the kernel module index. Reloading rules and databases does not apply any changes to already existing devices; the new configuration will only be applied to new events. Set a global property for all events. value Set the maximum number of events, systemd-udevd will handle at the same time. seconds The maximum number of seconds to wait for a reply from systemd-udevd. Print help text. udevadm monitor <arg choice="opt"><replaceable>options</replaceable></arg> Listens to the kernel uevents and events sent out by a udev rule and prints the devpath of the event to the console. It can be used to analyze the event timing, by comparing the timestamps of the kernel uevent and the udev event. Print the kernel uevents. Print the udev event after the rule processing. Also print the properties of the event. Filter events by subsystem[/devtype]. Only udev events with a matching subsystem value will pass. Filter events by property. Only udev events with a given tag attached will pass. Print help text. udevadm test <arg choice="opt"><replaceable>options</replaceable></arg> <arg><replaceable>devpath</replaceable></arg> Simulate a udev event run for the given device, and print debug output. The action string. Specify when udevadm should resolve names of users and groups. When set to early (the default), names will be resolved when the rules are parsed. When set to late, names will be resolved for every event. When set to never, names will never be resolved and all devices will be owned by root. Print help text. udevadm test-builtin <arg choice="opt"><replaceable>options</replaceable></arg> <arg><replaceable>command</replaceable></arg> <arg><replaceable>devpath</replaceable></arg> Run a built-in command COMMAND for device DEVPATH, and print debug output. Print help text. See Also udev7 , systemd-udevd.service8 systemd-229/man/user-system-options.xml000066400000000000000000000032001265713322000203420ustar00rootroot00000000000000 Talk to the service manager of the calling user, rather than the service manager of the system. Talk to the service manager of the system. This is the implied default. Execute the operation remotely. Specify a hostname, or a username and hostname separated by @, to connect to. The hostname may optionally be suffixed by a container name, separated by :, which connects directly to a specific container on the specified host. This will use SSH to talk to the remote machine manager instance. Container names may be enumerated with machinectl -H HOST. Execute operation on a local container. Specify a container name to connect to. systemd-229/man/vconsole.conf.xml000066400000000000000000000114601265713322000171340ustar00rootroot00000000000000 vconsole.conf systemd Developer Lennart Poettering lennart@poettering.net vconsole.conf 5 vconsole.conf Configuration file for the virtual console /etc/vconsole.conf Description The /etc/vconsole.conf file configures the virtual console, i.e. keyboard mapping and console font. It is applied at boot by systemd-vconsole-setup.service8. The basic file format of the vconsole.conf is a newline-separated list of environment-like shell-compatible variable assignments. It is possible to source the configuration from shell scripts, however, beyond mere variable assignments no shell features are supported, allowing applications to read the file without implementing a shell compatible execution engine. Note that the kernel command line options vconsole.keymap=, vconsole.keymap.toggle=, vconsole.font=, vconsole.font.map=, vconsole.font.unimap= may be used to override the console settings at boot. Depending on the operating system other configuration files might be checked for configuration of the virtual console as well, however only as fallback. Options The following options are understood: KEYMAP= KEYMAP_TOGGLE= Configures the key mapping table for the keyboard. KEYMAP= defaults to us if not set. The KEYMAP_TOGGLE= can be used to configure a second toggle keymap and is by default unset. FONT= FONT_MAP= FONT_UNIMAP= Configures the console font, the console map and the unicode font map. Example German keyboard and console /etc/vconsole.conf: KEYMAP=de-latin1 FONT=eurlatgr See Also systemd1, systemd-vconsole-setup.service8, loadkeys1, setfont8, locale.conf5, systemd-localed.service8 systemd-229/network/000077500000000000000000000000001265713322000145525ustar00rootroot00000000000000systemd-229/network/80-container-host0.network000066400000000000000000000006241265713322000214310ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Match] Virtualization=container Name=host0 [Network] DHCP=yes LinkLocalAddressing=yes [DHCP] UseTimezone=yes systemd-229/network/80-container-ve.network000066400000000000000000000007421265713322000210070ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Match] Name=ve-* Driver=veth [Network] # Default to using a /28 prefix, giving up to 13 addresses per container. Address=0.0.0.0/28 LinkLocalAddressing=yes DHCPServer=yes IPMasquerade=yes systemd-229/network/99-default.link000066400000000000000000000001201265713322000173050ustar00rootroot00000000000000[Link] NamePolicy=kernel database onboard slot path MACAddressPolicy=persistent systemd-229/network/Makefile000077700000000000000000000000001265713322000206472../src/Makefileustar00rootroot00000000000000systemd-229/po/000077500000000000000000000000001265713322000134775ustar00rootroot00000000000000systemd-229/po/.gitignore000066400000000000000000000001121265713322000154610ustar00rootroot00000000000000POTFILES Makefile.in.in .intltool-merge-cache Makefile systemd.pot /*.gmo systemd-229/po/LINGUAS000066400000000000000000000001131265713322000145170ustar00rootroot00000000000000de el fr gl hu it ko pl pt_BR ru uk sv sr es zh_CN zh_TW be be@latin tr da systemd-229/po/POTFILES.in000066400000000000000000000005321265713322000152540ustar00rootroot00000000000000src/core/org.freedesktop.systemd1.policy.in.in src/hostname/org.freedesktop.hostname1.policy.in src/import/org.freedesktop.import1.policy.in src/locale/org.freedesktop.locale1.policy.in src/login/org.freedesktop.login1.policy.in src/machine/org.freedesktop.machine1.policy.in src/timedate/org.freedesktop.timedate1.policy.in src/core/dbus-unit.c systemd-229/po/POTFILES.skip000066400000000000000000000007411265713322000156160ustar00rootroot00000000000000src/core/dbus-automount.c src/core/dbus-device.c src/core/dbus-job.c src/core/dbus-manager.c src/core/dbus-mount.c src/core/dbus-path.c src/core/dbus-service.c src/core/dbus-slice.c src/core/dbus-socket.c src/core/dbus-swap.c src/core/dbus-target.c src/core/dbus-timer.c src/core/dbus-unit.c src/core/dbus-scope.c src/hostname/hostnamed.c src/locale/localed.c src/core/org.freedesktop.systemd1.policy.in src/timedate/timedated.c units/user@.service.in units/debug-shell.service.in systemd-229/po/be.po000066400000000000000000000672331265713322000144400ustar00rootroot00000000000000# Belarusian translation for systemd. # Copyright (C) 2015 systemd's COPYRIGHT HOLDER # This file is distributed under the same license as the systemd package. # # # Viktar Vaŭčkievič , 2015. msgid "" msgstr "" "Project-Id-Version: systemd master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-12 13:42+0300\n" "PO-Revision-Date: 2015-09-12 16:25+0300\n" "Last-Translator: Viktar Vaŭčkievič \n" "Language-Team: \n" "Language: be\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" "X-Generator: Lokalize 2.0\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Адправіць пароль назад сістэме" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "Неабходна аўтэнтыфікацыя для адпраўкі пароля назад сістэме." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Кіраваць сэрвісамі і іншымі сістэмнымі адзінкамі" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Неабходна аўтэнтыфікацыя для кіравання сэрвісамі і іншымі сістэмнымі " "адзінкамі." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Кіраваць файламі сэрвісаў і іншых сістэмных адзінак" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Неабходна аўтэнтыфікацыя для кіравання файламі сэрвісаў і іншых сістэмных " "адзінак." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "Усталяваць або скінуць зменныя асяроддзя сістэмнага мэнэджэра" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Неабходна аўтэнтыфікацыя для ўсталявання або скіду зменных асяроддзя " "сістэмнага мэнэджэра." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Перачытаць стан systemd" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "Неабходна аўтэнтыфікацыя для перачытання стану systemd." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Усталяваць імя вузла" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Неабходна аўтэнтыфікацыя для ўсталявання імя вузла." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Усталяваць статычнае імя вузла" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Неабходна аўтэнтыфікацыя для ўсталявання як статычнага так і прыгожага імя " "вузла." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Усталяваць інфармацыю аб машыне" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "" "Неабходна аўтэнтыфікацыя для ўсталявання інфармацыі аб лакальнай машыне." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Імпартаваць вобраз ВМ або кантэйнера" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "Неабходна аўтэнтыфікацыя для імпарту вобраза ВМ або кантэйнера" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Экспартаваць вобраз ВМ або кантэйнера" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "Неабходна аўтэнтыфікацыя для экспарту вобраза ВМ або кантэйнера" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Спампаваць вобраз ВМ або кантэйнера" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "Неабходна аўтэнтыфікацыя для спампоўкі вобраза ВМ або кантэйнера" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Усталяваць сістэмную лакаль" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнай лакалі." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Усталяваць сістэмныя налады клавіятуры" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмных налад клавіятуры." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Дазволіць праграмам перашкаджаць выключэнню сістэмы" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць выключэнню " "сістэмы." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Дазволіць праграмам затрымліваць выключэнне сістэмы" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Неабходна аўтэнтыфікацыя для дазволу праграмам затрымліваць выключэнне " "сістэмы." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Дазволіць праграмам перашкаджаць засыпанню сістэмы" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць засыпанню " "сістэмы." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Дазволіць праграмам затрымліваць засыпанне сістэмы" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Неабходна аўтэнтыфікацыя для дазволу праграмам затрымліваць засыпанне " "сістэмы." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "Дазволіць праграмам перашкаджаць аўтаматычнаму прыпыненню сістэмы" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць аўтаматычнаму " "прыпыненню сістэмы." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "" "Дазволіць праграмам перашкаджаць сістэме апрацоўваць клавішу выключэння" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць сістэме " "апрацоўваць клавішу выключэння." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Дазволіць праграмам перашкаджаць сістэме апрацоўваць клавішу прыпынення" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць сістэме " "апрацоўваць клавішу прыпынення." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Дазволіць праграмам перашкаджаць сістэме апрацоўваць клавішу гібернацыі" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць сістэме " "апрацоўваць клавішу гібернацыі." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Дазволіць праграмам перашкаджаць сістэме апрацоўваць закрыццё крышкі ноўтбука" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць сістэме " "апрацоўваць закрыццё крышкі ноўтбука." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "" "Дазволіць карыстальнікам, якія яшчэ не ўвайшлі ў сістэму, выконваць праграмы" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Неабходна аўтэнтыфікацыя для выканання праграм карыстальніка, які яшчэ не " "ўвайшоў у сістэму." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Дазволіць далучаць прылады да працоўных месцаў" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "Неабходна аўтэнтыфікацыя для далучэння прылад да працоўных месцаў." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Адключаць прылады ад працоўных месцаў" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "Неабходна аўтэнтыфікацыя для адключэння прылад ад працоўных месцаў." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Выключыць сістэму" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Неабходна аўтэнтыфікацыя для выключэння сістэмы." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Выключыць сістэму пры прысутнасці іншых карыстальнікаў" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Неабходна аўтэнтыфікацыя для выключэння сістэмы пры прысутнасці іншых " "карыстальнікаў." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "Выключыць сістэму, калі праграмы перашкаджаюць гэтаму" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Неабходна аўтэнтыфікацыя для выключэння сістэмы, калі праграмы перашкаджаюць " "гэтаму." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Перазагрузіць сістэму" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Неабходна аўтэнтыфікацыя для перазагрузкі сістэмы." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Перазагрузіць сістэму пры прысутнасці іншых карыстальнікаў" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Неабходна аўтэнтыфікацыя для перазагрузкі сістэмы пры прысутнасці іншых " "карыстальнікаў." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "Перазагрузіць сістэму, калі праграмы перашкаджаюць гэтаму" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Неабходна аўтэнтыфікацыя для перазагрузкі сістэмы, калі праграмы " "перашкаджаюць гэтаму." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Прыпыніць сістэму" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Неабходна аўтэнтыфікацыя для прыпынення сістэмы." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "Прыпыніць сістэму пры прысутнасці іншых карыстальнікаў" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Неабходна аўтэнтыфікацыя для прыпынення сістэмы пры прысутнасці іншых " "карыстальнікаў." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "Прыпыніць сістэму, калі праграмы перашкаджаюць гэтаму" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Неабходна аўтэнтыфікацыя для прыпынення сістэмы, калі праграмы перашкаджаюць " "гэтаму." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Гібернаваць сістэму" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "Неабходна аўтэнтыфікацыя для гібернацыі сістэмы." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "Гібернаваць сістэму пры прысутнасці іншых карыстальнікаў" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Неабходна аўтэнтыфікацыя для гібернацыі сістэмы пры прысутнасці іншых " "карыстальнікаў." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "Гібернаваць сістэму, калі праграмы перашкаджаюць гэтаму" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Неабходна аўтэнтыфікацыя для гібернацыі сістэмы, калі праграмы перашкаджаюць " "гэтаму." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Кіраваць актыўнымі сесіямі, карыстальнікамі і працоўнымі месцамі" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Неабходна аўтэнтыфікацыя для кіравання актыўнымі сесіямі, карыстальнікамі і " "месцамі." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Блакаваць або разблакаваць актыўную сесію" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "" "Неабходна аўтэнтыфікацыя для блакіроўкі або разблакіроўкі актыўнай сесіі." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "Дазволіць указанне прашыўцы на загрузку інтэрфейсу налад" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "" "Неабходна аўтэнтыфікацыя для ўказання прашыўцы на загрузку інтэрфейсу налад." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "Усталяваць усеагульнае паведамленне" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "Неабходна аўтэнтыфікацыя для ўсталявання усеагульнага паведамлення." #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Увайсці ў лакальны кантэйнер" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "Неабходна аўтэнтыфікацыя для ўваходу ў лакальны кантэйнер." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "Увайсці ў лакальны вузел" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "Неабходна аўтэнтыфікацыя для ўваходу ў лакальны вузел." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "Атрымаць абалонку на лакальным кантэйнеры" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "" "Неабходна аўтэнтыфікацыя для атрымання абалонкі на лакальным кантэйнеры." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "Атрымаць абалонку на лакальным вузле" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "Неабходна аўтэнтыфікацыя для атрымання абалонкі на лакальным вузле." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "Атрымаць псеўда TTY на лакальным кантэйнеры" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "" "Неабходна аўтэнтыфікацыя для атрымання псеўда TTY на лакальным кантэйнеры." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "Атрымаць псеўда TTY на лакальным вузле" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "Неабходна аўтэнтыфікацыя для атрымання псеўда TTY на лакальным вузле." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Кіраваць лакальнымі віртуальнымі машынамі або кантэйнерамі" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Неабходна аўтэнтыфікацыя для кіравання лакальнымі віртуальнымі машынамі і " "кантэйнерамі." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Кіраваць вобразамі лакальных віртуальных машын і кантэйнераў" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Неабходна аўтэнтыфікацыя для кіравання вобразамі лакальных віртуальных машын " "і кантэйнераў." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Усталяваць сістэмны час" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часу." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Усталяваць сістэмны часавы пояс" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часавога поясу." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Усталяваць часавы пояс (мясцовы або UTC), у якім RTC захоўвае час" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Неабходна аўтэнтыфікацыя для ўсталявання часавога поясу (мясцовы або UTC), у " "якім захоўваецца час у RTC." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Уключыць або выключыць сінхранізацыю часу па сетцы" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Неабходна аўтэнтыфікацыя для ўключэння або выключэння сінхранізацыі часу па " "сетцы." #: ../src/core/dbus-unit.c:428 msgid "Authentication is required to start '$(unit)'." msgstr "Неабходна аўтэнтыфікацыя для запуску '$(unit)'." #: ../src/core/dbus-unit.c:429 msgid "Authentication is required to stop '$(unit)'." msgstr "Неабходна аўтэнтыфікацыя для ." #: ../src/core/dbus-unit.c:430 msgid "Authentication is required to reload '$(unit)'." msgstr "Неабходна аўтэнтыфікацыя для перачытання стану '$(unit)'." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 msgid "Authentication is required to restart '$(unit)'." msgstr "Неабходна аўтэнтыфікацыя для перазапуску '$(unit)'." #: ../src/core/dbus-unit.c:535 msgid "Authentication is required to kill '$(unit)'." msgstr "Неабходна аўтэнтыфікацыя для забойства '$(unit)'." #: ../src/core/dbus-unit.c:565 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "Неабходна аўтэнтыфікацыя для анулявання памылковага стану '$(unit)'." #: ../src/core/dbus-unit.c:597 msgid "Authentication is required to set properties on '$(unit)'." msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўласцівасцей '$(unit)'." systemd-229/po/be@latin.po000066400000000000000000000552611265713322000155660ustar00rootroot00000000000000# Belarusian translation for systemd. # Copyright (C) 2015 systemd's COPYRIGHT HOLDER # This file is distributed under the same license as the systemd package. # # # Viktar Vaŭčkievič , 2015. msgid "" msgstr "" "Project-Id-Version: systemd master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-12 13:42+0300\n" "PO-Revision-Date: 2015-09-12 16:25+0300\n" "Last-Translator: Viktar Vaŭčkievič \n" "Language-Team: \n" "Language: be@latin\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" "X-Generator: Lokalize 2.0\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Adpravić paroĺ nazad sistemie" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "Nieabchodna aŭtentyfikacyja dlia adpraŭki parolia nazad sistemie." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Kiravać servisami i inšymi sistemnymi adzinkami" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Nieabchodna aŭtentyfikacyja dlia kiravannia servisami i inšymi sistemnymi " "adzinkami." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Kiravać fajlami servisaŭ i inšych sistemnych adzinak" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Nieabchodna aŭtentyfikacyja dlia kiravannia fajlami servisaŭ i inšych " "sistemnych adzinak." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "Ustaliavać abo skinuć zmiennyja asiaroddzia sistemnaha menedžera" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia abo skidu zmiennych " "asiaroddzia sistemnaha menedžera." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Pieračytać stan systemd" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "Nieabchodna aŭtentyfikacyja dlia pieračytannia stanu systemd." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Ustaliavać imia vuzla" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia imia vuzla." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Ustaliavać statyčnaje imia vuzla" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia jak statyčnaha tak i " "pryhožaha imia vuzla." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Ustaliavać infarmacyju ab mašynie" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "" "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia infarmacyi ab lakaĺnaj " "mašynie." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Impartavać vobraz VM abo kantejniera" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "Nieabchodna aŭtentyfikacyja dlia impartu vobraza VM abo kantejniera" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Ekspartavać vobraz VM abo kantejniera" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "Nieabchodna aŭtentyfikacyja dlia ekspartu vobraza VM abo kantejniera" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Spampavać vobraz VM abo kantejniera" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "Nieabchodna aŭtentyfikacyja dlia spampoŭki vobraza VM abo kantejniera" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Ustaliavać sistemnuju lakaĺ" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaj lakali." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Ustaliavać sistemnyja nalady klavijatury" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "" "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnych nalad klavijatury." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Dazvolić prahramam pieraškadžać vykliučenniu sistemy" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać vykliučenniu " "sistemy." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Dazvolić prahramam zatrymlivać vykliučennie sistemy" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam zatrymlivać vykliučennie " "sistemy." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Dazvolić prahramam pieraškadžać zasypanniu sistemy" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać zasypanniu " "sistemy." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Dazvolić prahramam zatrymlivać zasypannie sistemy" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam zatrymlivać zasypannie " "sistemy." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "Dazvolić prahramam pieraškadžać aŭtamatyčnamu prypynienniu sistemy" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać " "aŭtamatyčnamu prypynienniu sistemy." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "" "Dazvolić prahramam pieraškadžać sistemie apracoŭvać klavišu vykliučennia" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać sistemie " "apracoŭvać klavišu vykliučennia." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Dazvolić prahramam pieraškadžać sistemie apracoŭvać klavišu prypyniennia" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać sistemie " "apracoŭvać klavišu prypyniennia." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Dazvolić prahramam pieraškadžać sistemie apracoŭvać klavišu hibiernacyi" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać sistemie " "apracoŭvać klavišu hibiernacyi." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Dazvolić prahramam pieraškadžać sistemie apracoŭvać zakryccio kryški noŭtbuka" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać sistemie " "apracoŭvać zakryccio kryški noŭtbuka." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "" "Dazvolić karystaĺnikam, jakija jašče nie ŭvajšli ŭ sistemu, vykonvać prahramy" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Nieabchodna aŭtentyfikacyja dlia vykanannia prahram karystaĺnika, jaki jašče " "nie ŭvajšoŭ u sistemu." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Dazvolić dalučać prylady da pracoŭnych miescaŭ" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "" "Nieabchodna aŭtentyfikacyja dlia dalučennia prylad da pracoŭnych miescaŭ." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Adkliučać prylady ad pracoŭnych miescaŭ" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Nieabchodna aŭtentyfikacyja dlia adkliučennia prylad ad pracoŭnych miescaŭ." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Vykliučyć sistemu" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Nieabchodna aŭtentyfikacyja dlia vykliučennia sistemy." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Vykliučyć sistemu pry prysutnasci inšych karystaĺnikaŭ" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Nieabchodna aŭtentyfikacyja dlia vykliučennia sistemy pry prysutnasci inšych " "karystaĺnikaŭ." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "Vykliučyć sistemu, kali prahramy pieraškadžajuć hetamu" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Nieabchodna aŭtentyfikacyja dlia vykliučennia sistemy, kali prahramy " "pieraškadžajuć hetamu." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Pierazahruzić sistemu" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Nieabchodna aŭtentyfikacyja dlia pierazahruzki sistemy." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Pierazahruzić sistemu pry prysutnasci inšych karystaĺnikaŭ" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Nieabchodna aŭtentyfikacyja dlia pierazahruzki sistemy pry prysutnasci " "inšych karystaĺnikaŭ." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "Pierazahruzić sistemu, kali prahramy pieraškadžajuć hetamu" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Nieabchodna aŭtentyfikacyja dlia pierazahruzki sistemy, kali prahramy " "pieraškadžajuć hetamu." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Prypynić sistemu" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Nieabchodna aŭtentyfikacyja dlia prypyniennia sistemy." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "Prypynić sistemu pry prysutnasci inšych karystaĺnikaŭ" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Nieabchodna aŭtentyfikacyja dlia prypyniennia sistemy pry prysutnasci inšych " "karystaĺnikaŭ." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "Prypynić sistemu, kali prahramy pieraškadžajuć hetamu" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Nieabchodna aŭtentyfikacyja dlia prypyniennia sistemy, kali prahramy " "pieraškadžajuć hetamu." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Hibiernavać sistemu" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "Hibiernavać sistemu pry prysutnasci inšych karystaĺnikaŭ" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy pry prysutnasci inšych " "karystaĺnikaŭ." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "Hibiernavać sistemu, kali prahramy pieraškadžajuć hetamu" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy, kali prahramy " "pieraškadžajuć hetamu." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Kiravać aktyŭnymi siesijami, karystaĺnikami i pracoŭnymi miescami" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Nieabchodna aŭtentyfikacyja dlia kiravannia aktyŭnymi siesijami, " "karystaĺnikami i miescami." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Blakavać abo razblakavać aktyŭnuju siesiju" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "" "Nieabchodna aŭtentyfikacyja dlia blakiroŭki abo razblakiroŭki aktyŭnaj " "siesii." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "Dazvolić ukazannie prašyŭcy na zahruzku interfiejsu nalad" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "" "Nieabchodna aŭtentyfikacyja dlia ŭkazannia prašyŭcy na zahruzku interfiejsu " "nalad." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "Ustaliavać usieahuĺnaje paviedamliennie" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "" "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia usieahuĺnaha paviedamliennia." #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Uvajsci ŭ lakaĺny kantejnier" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "Nieabchodna aŭtentyfikacyja dlia ŭvachodu ŭ lakaĺny kantejnier." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "Uvajsci ŭ lakaĺny vuziel" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "Nieabchodna aŭtentyfikacyja dlia ŭvachodu ŭ lakaĺny vuziel." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "Atrymać abalonku na lakaĺnym kantejniery" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "" "Nieabchodna aŭtentyfikacyja dlia atrymannia abalonki na lakaĺnym kantejniery." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "Atrymać abalonku na lakaĺnym vuzlie" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "" "Nieabchodna aŭtentyfikacyja dlia atrymannia abalonki na lakaĺnym vuzlie." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "Atrymać psieŭda TTY na lakaĺnym kantejniery" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "" "Nieabchodna aŭtentyfikacyja dlia atrymannia psieŭda TTY na lakaĺnym " "kantejniery." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "Atrymać psieŭda TTY na lakaĺnym vuzlie" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "" "Nieabchodna aŭtentyfikacyja dlia atrymannia psieŭda TTY na lakaĺnym vuzlie." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Kiravać lakaĺnymi virtuaĺnymi mašynami abo kantejnierami" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Nieabchodna aŭtentyfikacyja dlia kiravannia lakaĺnymi virtuaĺnymi mašynami i " "kantejnierami." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Kiravać vobrazami lakaĺnych virtuaĺnych mašyn i kantejnieraŭ" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Nieabchodna aŭtentyfikacyja dlia kiravannia vobrazami lakaĺnych virtuaĺnych " "mašyn i kantejnieraŭ." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Ustaliavać sistemny čas" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaha času." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Ustaliavać sistemny časavy pojas" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "" "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaha časavoha pojasu." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Ustaliavać časavy pojas (miascovy abo UTC), u jakim RTC zachoŭvaje čas" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia časavoha pojasu (miascovy abo " "UTC), u jakim zachoŭvajecca čas u RTC." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Ukliučyć abo vykliučyć sinchranizacyju času pa sietcy" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Nieabchodna aŭtentyfikacyja dlia ŭkliučennia abo vykliučennia sinchranizacyi " "času pa sietcy." #: ../src/core/dbus-unit.c:428 msgid "Authentication is required to start '$(unit)'." msgstr "Nieabchodna aŭtentyfikacyja dlia zapusku '$(unit)'." #: ../src/core/dbus-unit.c:429 msgid "Authentication is required to stop '$(unit)'." msgstr "Nieabchodna aŭtentyfikacyja dlia ." #: ../src/core/dbus-unit.c:430 msgid "Authentication is required to reload '$(unit)'." msgstr "Nieabchodna aŭtentyfikacyja dlia pieračytannia stanu '$(unit)'." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 msgid "Authentication is required to restart '$(unit)'." msgstr "Nieabchodna aŭtentyfikacyja dlia pierazapusku '$(unit)'." #: ../src/core/dbus-unit.c:535 msgid "Authentication is required to kill '$(unit)'." msgstr "Nieabchodna aŭtentyfikacyja dlia zabojstva '$(unit)'." #: ../src/core/dbus-unit.c:565 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "" "Nieabchodna aŭtentyfikacyja dlia anuliavannia pamylkovaha stanu '$(unit)'." #: ../src/core/dbus-unit.c:597 msgid "Authentication is required to set properties on '$(unit)'." msgstr "" "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭlascivasciej '$(unit)'." systemd-229/po/da.po000066400000000000000000000560351265713322000144340ustar00rootroot00000000000000# Danish translation for systemd. # Copyright (C) 2014 systemd's COPYRIGHT HOLDER # This file is distributed under the same license as the systemd package. # Daniel Machon , 2015. # msgid "" msgstr "" "Project-Id-Version: systemd master\n" "Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" "POT-Creation-Date: 2015-10-07 19:30+0000\n" "PO-Revision-Date: 2015-10-07 19:30+0200\n" "Last-Translator: Daniel Machon \n" "Language-Team: danish\n" "Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Send adgangssætning tilbage til systemet" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "" "Autentificering er nødvendig for at sende adgangssætning tilbage til systemet." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Håndtér system services eller andre enheder" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Autentificering er nødvendig for at håndtere system services og andre enheder." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Håndtér system services eller enhedsfiler" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Autentificering er nødvendig for at håndtere system service eller enhedsfiler." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "" "Sæt eller fjern system- og service-forvalter miljøvariabler" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "Autentificering er nødvendig for at sætte eller fjerne system- " "og service-forvalter miljøvariabler." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Genindlæs systemd tilstand" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "Autentificering er nødvendig for at genindlæse systemd tilstanden." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Sæt værtsnavn" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Autentificering er nødvendig for at sætte værtsnavn." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Sæt statisk værstnavn" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Autentificering er nødvendig for at sætte det statisk konfigurerede lokale " "værtsnavn, lige så vel som det pæne værtsnavn." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Sæt maskininformation." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "Autentificering er nødvendig for at sætte lokal maskininformation." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Importér en VM eller container billede" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "" "Autentificering er nødvendig for at importére en VM eller " "container billeder." #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Exportér en VM eller container billede" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "Autentificering er nødvendig for at exportére en VM eller container billede" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Hent en VM eller container billede" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "Autentificering er nødvendig for at hente en VM eller container billede" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Sæt sprogindstillinger for systemet" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "" "Autentificering er nødvendig for at sætte sprogindstillinger " "for systemet." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Sæt tastaturindstillinger for systemet." #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "" "Autentificering er nødvendig for at sætte tastaturindstillinger " "for systemet." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Tillad applikationer at hæmme system nedlukning" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Autentificering er nødvendig for at en applikation kan hæmme " "system nedlukning." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Tillad applikationer at forsinke system nedlukning" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Autentificering er nødvendig for at en applikation kan forsinke " "system nedlukning." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Tillad applikationer at hæmme system dvale" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep" msgstr "Autentificering er nødvendig for at en applikation kan hæmme system dvale" #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Tillad applikationer at forsinke system dvale" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Autentificering er nødvendig for at en applikation kan forsinke system " "dvale." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "Tillad applikationer at hæmme automatisk system standby" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Autentificering er nødvendig for at en applikation kan hæmme automatisk " "system standby." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "Tillad applikationer at hæmme systemhåndtering af tænd/sluk-knappen" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering " "af tænd/sluk-knappen." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "Tillad applikationer at hæmme systemhåndtering af standby-knappen" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering " "af standby-knappen." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "Tillad applikationer at hæmme systemhåndtering af dvale-knappen" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Autentificering er nødvendig for at en applikation kan hæmme " "systemhåndtering af dvale-knappen." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Tillad applikationer at hæmme systemhåndtering af skærmlukning" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering " "af skærmlukning." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "Tillad brugere der ikke er logget ind, at køre programmer" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Autentificering er nødvendig for at brugere, som ikke er logget ind, kan " "køre programmer." # www.freedesktop.org/wiki/Software/systemd/multiseat/ #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Tillad at montere af enheder til arbejdsstationer" # www.freedesktop.org/wiki/Software/systemd/multiseat/ #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "" "Autentificering er nødvendig for at montere en enhed til en " "arbejdsstation." # www.freedesktop.org/wiki/Software/systemd/multiseat/ #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Nulstil enhed monteret til en arbejdsstation" # www.freedesktop.org/wiki/Software/systemd/multiseat/ #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Autentificering er nødvendig for at nulstille måden enheder er monteret " "arbejdsstationer." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Sluk for systemet" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Autentificering er nødvendig for at slukke systemet" #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Sluk systemet mens andre brugere er logget på" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Autentificering er nødvendig for at slukke systemet mens andre brugere " "er logget på." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "" "Sluk for systemet mens en applikation har forespurgt at hæmme det" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Autentificering er nødvendig for at slukke systemet mens en applikation har " "forespurgt at hæmme det." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Genstart systemet" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Autentificering er nødvendig for at genstarte systemet." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Genstart systemet mens andre brugere er logget ind" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Autentificering er nødvendig for at genstarte systemet mens andre brugere " "er logget ind." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "" "Genstart systemet mens en applikation har forespurgt at hæmme det" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Autentificering er nødvendig for at genstarte systemet mens en applikation " "har forespurgt at hæmme det." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Sæt systemet på standby" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Autentificering er nødvendig for at sætte systemet på standby" #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "Sæt systemet på standby mens andre brugere er logget på" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Autentificering er nødvendig for at sætte systemet på standby, mens andre " "brugere er logget på." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "" "Sæt systemet på standby mens en applikation har forespurgt at hæmme" "det" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Autentificering er nødvendig for at sætte systemet på standby, mens en " "applikation har forespurgt at hæmme det." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Sæt systemet i dvale" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "" "Autentificering er nødvendig for at sætte systemet i dvale-tilstand." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "" "Sæt systemet i dvale-tilstand mens andre brugere er logget på" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Autentificering er nødvendig for at sætte systemet i dvale-tilstand, mens " "andre brugere er logget på." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "Sæt systemet i dvale-tilstand mens en applikation har forespurgt at " "hæmme det" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Autentificering er nødvendig for at sætte systemet i dvale tilstand, mens " "en applikation har forespurgt at hæmme det." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Håndtér aktive sessioner, brugere og arbejdsstationer" # www.freedesktop.org/wiki/Software/systemd/multiseat/ #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Autentificering er nødvendig for at håndtere aktive sessioner, brugere " "og arbejdsstationer." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Lås eller oplås aktive sessioner" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "" "Autentificering er nødvendig for at låse eller oplåse aktive sessioner." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "Tillad meddelelse til firmwaren om at starte op i opsætningsgrænseflade" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "Autentificering er nødvendig for at meddele firmwaren om at starte " "op i opsætningsgrænseflade." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "Sæt broadcast-besked" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "Autentificering er nødvendig for at sætte en broadcast-besked" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Log på en lokal container" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "Autentificering er nødvendig for at logge på en lokal container." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "Log på den lokale vært" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "Auitentificering er nødvendig for at logge på den lokale vært." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "Anskaf en shell i en lokal container" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "" "Autentificering er nødvendig for at anskaffe en shell i en lokal " "container." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "Anskaf en shell på den lokale vært" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "" "Autentificering er nødvendig for at anskaffe en shell på den lokale vært." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "Anskaf en pseudo-TTY i en lokal container" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "" "Autentificering er nødvendig for at anskaffe en pseudo-TTY i en lokal " "container." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "Anskaf en pseudo-TTY på den lokale vært" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "" "Autentificering er nødvendig for at anskaffe en pseudo-TTY på den " "lokale vært." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Håndtér lokale virtuelle maskiner og containere" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Autentificering er nødvendig for at håndtere lokale virtuelle maskiner og " "containere." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Håndtér lokal virtuel maskine- og container billeder" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Autentificering er nødvendig for at håndtere lokal virtuel maskine- og " "container billeder." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Sæt tiden for systemet" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Autentificering er nødvendig for at sætte tiden for systemet." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Sæt tidszone for systemet" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Autentificering er nødvendig for at sætte tidszonen for systemet." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Sæt RTC til lokal tidszone eller UTC" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Autentificering er nødvendig for at kontrollere hvorvidt RTC'en gemmer " "den lokale tid eller UTC tid." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Slå synkronisering af netværkstid til eller fra" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Autentificering er nødvendig for at kontrollere hvorvidt synkronisering af " "netværkstid skal aktiveres" #: ../src/core/dbus-unit.c:428 msgid "Authentication is required to start '$(unit)'." msgstr "Autentificering er nødvendig for at starte '$(unit)'." #: ../src/core/dbus-unit.c:429 msgid "Authentication is required to stop '$(unit)'." msgstr "Autentificering er nødvendig for at stoppe '$(unit)'." #: ../src/core/dbus-unit.c:430 msgid "Authentication is required to reload '$(unit)'." msgstr "Autentificering er nødvendig for at genindlæse '$(unit)'." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 msgid "Authentication is required to restart '$(unit)'." msgstr "Autentificering at nødvendig for at genstarte '$(unit)'." #: ../src/core/dbus-unit.c:535 msgid "Authentication is required to kill '$(unit)'." msgstr "Autentificering er nødvendig for at eliminere '$(unit)'." #: ../src/core/dbus-unit.c:565 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "" "Autentificering er nødvendig for at nulstille \"fejl\" tilstanden på '$(unit)'." #: ../src/core/dbus-unit.c:597 msgid "Authentication is required to set properties on '$(unit)'." msgstr "" "Autentificering er nødvendig for at sætte egenskaber på '$(unit)'." #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" #~ msgstr "" #~ "Tryk Ctrl-C for at annulere alle igangværende kontrolleringer af " #~ "filsystemet" #~ msgid "Checking in progress on %d disk (%3.1f%% complete)" #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" #~ msgstr[0] "Igangværende kontrollering på %d disk (%3.1f%% færdig)" #~ msgstr[1] "Igangværende kontrollering på %d diske (%3.1f%% færdig)" systemd-229/po/de.po000066400000000000000000000576751265713322000144530ustar00rootroot00000000000000# German translation for systemd. # Copyright (C) 2014 systemd's COPYRIGHT HOLDER # This file is distributed under the same license as the systemd package. # Christian Kirbach , 2014, 2015. # Benjamin Steinwender , 2014. # Bernd Homuth , 2015. # msgid "" msgstr "" "Project-Id-Version: systemd master\n" "Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" "POT-Creation-Date: 2015-09-19 12:09+0000\n" "PO-Revision-Date: 2015-09-19 20:02+0200\n" "Last-Translator: Bernd Homuth \n" "Language-Team: Deutsch \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Gtranslator 2.91.6\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Passphrase zurück an das System senden" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "" "Legitimierung ist zum Senden des eingegebenen Kennworts zurück an das System " "notwendig." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Systemdienste und andere Einheiten verwalten" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Legitimierung ist notwendig für die Verwaltung von Systemdiensten und " "anderen Einheiten." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Systemdienste und Einheitendateien verwalten" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Legitimierung ist notwendig für die Verwaltung von Systemdiensten und " "Einheitendateien." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "" "Umgebungsvariablen der System- und Dienstverwaltung festlegen oder entfernen" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "Legitimierung ist notwendig für die System- und Dienstverwaltung." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Den systemd-Zustand neu laden" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "Legitimierung ist zum erneuten Laden des systemd-Zustands notwendig." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Rechnername festlegen" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Legitimierung ist zum Festlegen des lokalen Rechnernamens notwendig" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Statischen Rechnernamen festlegen" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Authentifizierung ist erforderlich, um den statisch geänderten, lokalen " "Rechnernamen, sowie den beschönigten Rechnernamen festzulegen." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Maschinen-Information festlegen" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "" "Legitimierung ist zum Festlegen der lokalen Maschinen-Information " "erforderlich." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Abbild einer VM oder eines Containers importieren" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "" "Legitimierung ist zum Importieren eines VM- oder Containerabbilds " "erforderlich" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Abbild einer VM oder eines Containers exportieren" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "" "Legitimierung ist zum Exportieren eines VM- oder Containerabbilds " "erforderlich" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Abbild einer VM oder eines Containers herunterladen" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "" "Legitimierung ist zum Herunterladen eines VM- oder Containerabbilds " "erforderlich" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Die lokale Sprachumgebung festlegen" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "" "Legitimierung ist zum Festlegen der systemweiten Spracheinstellungen " "erforderlich." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Tastatureinstellungen des Systems festlegen" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "" "Legitimierung ist zum Festlegen der Tastatureinstellungen des Systems " "erforderlich." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Anwendungen dürfen das Herunterfahren des Systems unterbinden" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Legitimierung ist notwendig, um Anwendungen das Herunterfahren des Systems " "zu erlauben." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Anwendungen dürfen das Herunterfahren des Systems verzögern" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Legitimierung ist notwendig, um Anwendungen das Verzögern des Herunterfahren " "des Systems zu erlauben." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Anwendungen dürfen den Bereitschaftsmodus unterbinden" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Legitimierung ist erforderlich, um Anwendungen das Unterbinden des " "Bereitschaftsmodus zu erlauben." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Anwendungen dürfen den Bereitschaftsmodus verzögern" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Legitimierung ist erforderlich, um Anwendungen das Verzögern des " "Bereitschaftsmodus zu erlauben." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "Anwendungen dürfen den automatischen Bereitschaftsmodus unterbinden" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Legitimierung ist notwendig, um Anwendungen das Unterbinden des " "automatischen Bereitschaftsmodus zu erlauben." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "" "Anwendungen dürfen das Auswerten des Ein-/Ausschaltknopfs des Systems " "unterbinden" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Legitmierung ist erforderlich, um Anwendungen das Unterbinden der Auswertung " "der Ein-/Ausschaltknopfs des Systems zu erlauben." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Anwendungen dürfen das Auswerten des Bereitschaftsknopfs des Systems " "unterbinden" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Legitimierung ist erforderlich, um Anwendungen das Unterbinden der " "Auswertung des Bereitschaftsknopfes des Systems zu erlauben." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Anwendungen dürfen das Auswerten des Knopfs für den Ruhezustand unterbinden" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Legitimierung ist erforderlich, um Anwendungen das Unterbinden der " "Auswertung des Knopfs für den Ruhezustand zu erlauben." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Anwendungen dürfen das Auswerten des Notebookdeckelschalters unterbinden" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Legitimierung ist erforderlich, um Anwendungen das Unterbinden der " "Auswertung des Notebookdeckelschalters des Systems zu erlauben." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "Nicht angemeldete Benutzer dürfen Programme ausführen" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Legitimierung ist erforderlich, damit nicht angemeldete Benutzer Programme " "ausführen dürfen." # www.freedesktop.org/wiki/Software/systemd/multiseat/ #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Das Anschließen von Geräten an Arbeitsstationen erlauben" # www.freedesktop.org/wiki/Software/systemd/multiseat/ #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "" "Legitimierung ist zum Anschließen eines Geräts an eine Arbeitsstation " "notwendig." # www.freedesktop.org/wiki/Software/systemd/multiseat/ #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Zurücksetzen der an eine Arbeitsstation angeschlossenen Geräte" # www.freedesktop.org/wiki/Software/systemd/multiseat/ #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Legitimierung ist zum Zurücksetzen notwendig, wie Geräte an eine " "Arbeitsstation angeschlossen werden." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Das System ausschalten" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Legitimierung ist zum Ausschalten des Systems notwendig." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Das System herunter fahren, während andere Benutzer angemeldet sind" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Legitimierung ist zum Herunterfahren des Systems notwendig, während andere " "Benutzer angemeldet sind." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "" "Das System ausschalten, während eine Anwendung anfordert es zu unterbinden" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Legitimierung ist zum Ausschalten des Systems notwendig, während eine " "Anwendung anfordert es zu unterbinden." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Das System neu starten" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Legitimierung ist zum Neustart des Systems notwendig." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Das Systems neu starten, während andere Benutzer angemeldet sind" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Legitimierung ist zum Neustart des Systems notwendig, während andere " "Benutzer angemeldet sind." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "" "Das System neu starten, während eine Anwendung anfordert es zu unterbinden" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Legitimierung ist zum Neustart des Systems notwendig, während eine Anwendung " "anforderte es zu unterbinden." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Das System in Bereitschaft versetzen" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Legitimierung ist zum Versetzen des Systems in Bereitschaft notwendig." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "" "Das System in Bereitschaft versetzen, während andere Benutzer angemeldet " "sind." #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Legitimierung ist zum Versetzen des Systems in Bereitschaft notwendig, " "während andere Benutzer angemeldet sind." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "" "Das System in Bereitschaft versetzen, während eine Anwendung anfordert dies " "zu unterbinden" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Legitimierung ist zum Versetzen des Systems in Bereitschaft notwendig, " "während eine Anwendung anfordert dies zu unterbinden." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Den Ruhezustand des Systems aktivieren" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "" "Legitimierung ist zum Aktivieren des Ruhezustands des Systems notwendig." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "" "Den Ruhezustand des Systems aktivieren, während andere Benutzer angemeldet " "sind" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Legitimierung ist zum Aktivieren des Ruhezustands des Systems notwendig, " "während andere Benutzer angemeldet sind." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "" "Das System in den Ruhezustand versetzen, während eine Anwendung wünscht dies " "zu verhindern" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Legitimierung ist zum Versetzen des System in den Ruhezustand notwendig, " "während eine Anwendung wünscht dies zu verhindern." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Aktive Sitzungen, Benutzer und Arbeitsstationen verwalten" # www.freedesktop.org/wiki/Software/systemd/multiseat/ #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Legitimierung ist zur Verwaltung aktiver Sitzungen, Benutzern und " "Arbeitsstationen notwendig." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Aktive Sitzungen sperren und entsperren" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "" "Legitimierung ist zum Sperren und Entsperren aktiver Sitzungen notwendig." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "" "Mitteilungen an die Firmware zum Starten in die Einrichtungsoberfläche " "zulassen" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "" "Legitimierung ist zum Starten der Firmware in die Einrichtungsoberfläche " "notwendig." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "Nachricht an alle einstellen" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "Legitimierung ist zum Einstellen einer Nachricht an alle notwendig" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "In einem lokalen Container anmelden" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "Legitimierung ist zum Anmelden in einem lokalen Container notwendig." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "Am lokalen Rechner anmelden" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "Legitimierung ist zum Anmelden am lokalen Rechner notwendig." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "Eine Shell in einem lokalen Container erhalten" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "" "Legitimierung ist zum Erhalten einer Shell in einem lokalen Container " "notwendig." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "Eine Shell auf dem lokalen Rechner erhalten" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "" "Legitimierung ist zum Erhalten einer Shell auf dem lokalen Rechner notwendig." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "Ein Pseudo-TTY in einem lokalen Container erhalten" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "" "Legitimierung ist zum Erhalten eines Pseudo-TTY in einem lokalen Container " "notwendig." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "Ein Pseudo-TTY auf dem lokalen Rechner erhalten" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "" "Legitimierung ist zum Erhalten eines Pseudo-TTY auf dem lokalen Rechner " "notwendig." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Lokale virtuelle Maschinen und Container verwalten" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Legitimierung ist zum Verwalten lokaler virtueller Maschinen und Container " "erforderlich." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Lokale virtuelle Maschinen und Containerabbilder verwalten" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Legitimierung ist zum Verwalten lokaler virtueller Maschinen und " "Containerabbildern erforderlich." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Die Systemzeit festlegen" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Legitimierung ist zum Festlegen der Systemzeit notwendig." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Die Systemzeitzone festlegen" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Legitimierung ist zum Festlegen der Systemzeitzone notwendig." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Echtzeituhr auf lokale Zeitzone oder UTC setzen" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Legitimierung ist notwendig zum Festlegen, ob die Echtzeituhr auf lokale " "Zeitzone oder UTC eingestellt ist." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Netzwerkzeitabgeich ein- oder ausschalten" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Legitimierung ist zum Festlegen, ob Netzwerkzeitabgeich eingeschaltet sein " "soll, erforderlich." #: ../src/core/dbus-unit.c:428 msgid "Authentication is required to start '$(unit)'." msgstr "Legitimierung ist zum Starten von »$(unit)« notwendig." #: ../src/core/dbus-unit.c:429 msgid "Authentication is required to stop '$(unit)'." msgstr "Legitimierung ist zum Stoppen von »$(unit)« notwendig." #: ../src/core/dbus-unit.c:430 msgid "Authentication is required to reload '$(unit)'." msgstr "Legitimierung ist zum erneuten Laden von »$(unit)« notwendig." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 msgid "Authentication is required to restart '$(unit)'." msgstr "Legitimierung ist zum Neustarten von »$(unit)« notwendig." #: ../src/core/dbus-unit.c:535 msgid "Authentication is required to kill '$(unit)'." msgstr "Legitimierung ist zum Eliminieren von »$(unit)« notwendig." #: ../src/core/dbus-unit.c:565 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "" "Legitimierung ist zum Zurücksetzen des Status »fehlgeschlagen« von »$(unit)« " "notwendig" #: ../src/core/dbus-unit.c:597 msgid "Authentication is required to set properties on '$(unit)'." msgstr "" "Legitimierung ist zum Festlegen der Eigenschaften von »$(unit)« notwendig." #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" #~ msgstr "Strl+C drücken um laufende Dateisystem-Prüfungen abzubrechen" #~ msgid "Checking in progress on %d disk (%3.1f%% complete)" #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" #~ msgstr[0] "Prüfe %d Laufwerk (%3.1f%% fertig)" #~ msgstr[1] "Prüfe %d Laufwerke (%3.1f%% fertig)" systemd-229/po/el.po000066400000000000000000000700721265713322000144450ustar00rootroot00000000000000# Greek translation for systemd. # Copyright (C) 2014 systemd's COPYRIGHT HOLDER # This file is distributed under the same license as the systemd package. # Dimitris Spingos , 2014. # Dimitris Spingos (Δημήτρης Σπίγγος) , 2014. msgid "" msgstr "" "Project-Id-Version: systemd master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-22 16:37+0100\n" "PO-Revision-Date: 2014-04-29 09:17+0300\n" "Last-Translator: Dimitris Spingos (Δημήτρης Σπίγγος) \n" "Language-Team: team@lists.gnome.gr\n" "Language: el\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Virtaal 0.7.0\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Αποστολή του συνθηματικού πίσω στο σύστημα" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "" "Απαιτείται πιστοποίηση για αποστολή του εισερχόμενου συνθηματικού πίσω στο " "σύστημα." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 #, fuzzy msgid "Authentication is required to manage system services or other units." msgstr "" "Απαιτείται πιστοποίηση για να προσπελάσετε τον διαχειριστή συστήματος και " "υπηρεσιών." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 #, fuzzy msgid "Authentication is required to manage system service or unit files." msgstr "" "Απαιτείται πιστοποίηση για να προσπελάσετε τον διαχειριστή συστήματος και " "υπηρεσιών." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 #, fuzzy msgid "Set or unset system and service manager environment variables" msgstr "Προνομιούχος πρόσβαση διαχειριστή συστήματος και υπηρεσίας" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 #, fuzzy msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Απαιτείται πιστοποίηση για να προσπελάσετε τον διαχειριστή συστήματος και " "υπηρεσιών." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 #, fuzzy msgid "Reload the systemd state" msgstr "Επανεκκίνηση του συστήματος" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 #, fuzzy msgid "Authentication is required to reload the systemd state." msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Ορισμός ονόματος οικοδεσπότη" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Ορισμός στατικού ονόματος οικοδεσπότη" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Απαιτείται πιστοποίηση για να ορίσετε το στατικά ρυθμισμένο όνομα τοπικού " "οικοδεσπότη, καθώς και το pretty όνομα οικοδεσπότη." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Ορισμός πληροφοριών μηχανής" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "" #: ../src/import/org.freedesktop.import1.policy.in.h:2 #, fuzzy msgid "Authentication is required to import a VM or container image" msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "" #: ../src/import/org.freedesktop.import1.policy.in.h:4 #, fuzzy msgid "Authentication is required to export a VM or container image" msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "" #: ../src/import/org.freedesktop.import1.policy.in.h:6 #, fuzzy msgid "Authentication is required to download a VM or container image" msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Ορισμός τοπικών ρυθμίσεων συστήματος" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "" "Απαιτείται πιστοποίηση για να ορίσετε τις τοπικές ρυθμίσεις του συστήματος." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Ορισμός ρυθμίσεων πληκτρολογίου συστήματος" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "" "Απαιτείται πιστοποίηση για να ορίσετε τις ρυθμίσεις πληκτρολογίου του " "συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "" "Να επιτρέπεται στις εφαρμογές να αποτρέπουν τον τερματισμό του συστήματος" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει τον " "τερματισμό του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "" "Να επιτρέπεται στις εφαρμογές να καθυστερούν τον τερματισμό του συστήματος" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να καθυστερήσει " "τον τερματισμό του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Να επιτρέπεται στις εφαρμογές να αποτρέπουν την ύπνωση του συστήματος" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " "ύπνωση του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Να επιτρέπεται στις εφαρμογές να καθυστερούν την ύπνωση του συστήματος" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να καθυστερήσει " "την ύπνωση του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "" "Να επιτρέπεται στις εφαρμογές να αποτρέπουν την αυτόματη αναστολή του " "συστήματος" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " "αυτόματη αναστολή του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "" "Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του πλήκτρου " "ενεργοποίησης του συστήματος" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " "διαχείριση του πλήκτρου ενεργοποίησης του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του πλήκτρου " "αναστολής του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " "διαχείριση του πλήκτρου αναστολής του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του πλήκτρου " "αδρανοποίησης του συστήματος" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " "διαχείριση του πλήκτρου αδρανοποίησης του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του διακόπτη " "καλύμματος του συστήματος" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " "διαχείριση του διακόπτη καλύμματος του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "Να επιτρέπεται σε μη συνδεμένους χρήστες να εκτελούν προγράμματα" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Απαιτείται πιστοποίηση για να επιτρέπεται σε μη συνδεμένους χρήστες να " "εκτελούν προγράμματα." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Να επιτρέπεται η προσάρτηση συσκευών στους σταθμούς εργασίας" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "" "Απαιτείται πιστοποίηση για προσάρτηση μιας συσκευής σε έναν σταθμό εργασίας." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Αφαίρεση συσκευής από προσαρτήσεις σταθμού εργασίας" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Απαιτείται πιστοποίηση για επαναφορά του τρόπου που οι συσκευές προσαρτώνται " "στους σταθμούς εργασίας." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Σβήσιμο του συστήματος" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Απαιτείται πιστοποίηση για την σβήσιμο του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Σβήσιμο του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Απαιτείται πιστοποίηση για σβήσιμο του συστήματος ενώ άλλοι χρήστες είναι " "συνδεμένοι." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "Απενεργοποίηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί." #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Απαιτείται πιστοποίηση για απενεργοποίηση του συστήματος ενώ μια εφαρμογή " "ζήτησε να αποτραπεί." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Επανεκκίνηση του συστήματος" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Απαιτείται πιστοποίηση για επανεκκίνηση του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Επανεκκίνηση του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Απαιτείται πιστοποίηση για επανεκκίνηση του συστήματος ενώ άλλοι χρήστες " "είναι συνδεμένοι." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "Επανεκκίνηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Απαιτείται πιστοποίηση για επανεκκίνηση του συστήματος ενώ μια εφαρμογή " "ζήτησε να αποτραπεί." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Αναστολή του συστήματος" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Απαιτείται πιστοποίηση για την αναστολή του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "Αναστολή του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Απαιτείται πιστοποίηση για αναστολή του συστήματος ενώ άλλοι χρήστες είναι " "συνδεμένοι." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "Αναστολή του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Απαιτείται πιστοποίηση για αναστολή του συστήματος ενώ μια εφαρμογή ζήτησε " "να αποτραπεί." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Αδρανοποίηση του συτήματος" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "Αδρανοποίηση του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος ενώ άλλοι χρήστες " "είναι συνδεμένοι." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "Αδρανοποίηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος ενώ μια εφαρμογή " "ζήτησε να αποτραπεί." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:50 #, fuzzy msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Απαιτείται πιστοποίηση για προσάρτηση μιας συσκευής σε έναν σταθμό εργασίας." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:52 #, fuzzy msgid "Authentication is required to lock or unlock active sessions." msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:54 #, fuzzy msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:56 #, fuzzy msgid "Authentication is required to set a wall message" msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 #, fuzzy msgid "Authentication is required to log into a local container." msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 #, fuzzy msgid "Authentication is required to log into the local host." msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 #, fuzzy msgid "Acquire a shell in a local container" msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 #, fuzzy msgid "Authentication is required to acquire a shell in a local container." msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 #, fuzzy msgid "Authentication is required to acquire a shell on the local host." msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 #, fuzzy msgid "Acquire a pseudo TTY in a local container" msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 #, fuzzy msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 #, fuzzy msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 #, fuzzy msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 #, fuzzy msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Ορισμός ώρας συστήματος" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Ορισμός ζώνης ώρας συστήματος" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα ζώνης του συστήματος." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Ορισμός RTC στην τοπική ζώνη ώρας ή UTC" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Απαιτείται πιστοποίηση για να ελέγξετε αν το RTC αποθηκεύει την τοπική ή την " "ώρα UTC." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Ενεργοποίηση/Απενεργοποίηση συγχρονισμού ώρας δικτύου" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Απαιτείται πιστοποίηση για να ελέγξετε αν ο συγχρονισμός ώρας δικτύου θα " "ενεργοποιηθεί." #: ../src/core/dbus-unit.c:428 #, fuzzy msgid "Authentication is required to start '$(unit)'." msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." #: ../src/core/dbus-unit.c:429 #, fuzzy msgid "Authentication is required to stop '$(unit)'." msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." #: ../src/core/dbus-unit.c:430 #, fuzzy msgid "Authentication is required to reload '$(unit)'." msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 #, fuzzy msgid "Authentication is required to restart '$(unit)'." msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." #: ../src/core/dbus-unit.c:535 #, fuzzy msgid "Authentication is required to kill '$(unit)'." msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." #: ../src/core/dbus-unit.c:565 #, fuzzy msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." #: ../src/core/dbus-unit.c:597 #, fuzzy msgid "Authentication is required to set properties on '$(unit)'." msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." systemd-229/po/es.po000066400000000000000000000566171265713322000144650ustar00rootroot00000000000000# Spanish translation for systemd. # Copyright (C) 2015 systemd's COPYRIGHT HOLDER # This file is distributed under the same license as the systemd package. # Alex Puchades , 2015. # Daniel Mustieles , 2015. # Álex Puchades , 2015. # msgid "" msgstr "" "Project-Id-Version: systemd master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-22 16:37+0100\n" "PO-Revision-Date: 2015-04-24 13:26+0200\n" "Last-Translator: Álex Puchades \n" "Language-Team: Español; Castellano \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Gtranslator 2.91.7\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Devolver contraseña al sistema" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "" "Se requiere autenticación para devolver la contraseña introducida al sistema." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Administrar servicios del sistema u otras unidades" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Se requiere autenticación para administrar los servicios de sistema u otras " "unidades." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Administrar servicio del sistema o archivos de unidad" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Se requiere autenticación para administrar el servicio de sistema o los " "archivos de unidad." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "Administrar variables de entorno del sistema y del gestor de servicios" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Se requiere autenticación para administrar las variables de entorno del " "sistema y del gestor de servicios." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Recargar el estado de systemd" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "Se requiere autenticación para recargar el estado de systemd." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Establecer nombre del equipo" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Se requiere autenticación para establecer el nombre de equipo local." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Establecer nombre estático del equipo" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Se requiere autenticación para establecer el nombre estático de equipo " "local, así como el nombre visible del equipo." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Establecer información del sistema" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "" "Se requiere autenticación para establecer la información de sistema local." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Importar una imagen de máquina virtual o de contenedor" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "" "Se requiere autenticación para importar una imagen de máquina virtual o de " "contenedor" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Exportar imagen de máquina virtual o de contenedor" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "" "Se requiere autenticación para exportar una imagen de máquina virtual o de " "contenedor" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Descargar una imagen de máquina virtual o de contenedor" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "" "Se requiere autenticación para descargar una imagen de máquina virtual o de " "contenedor" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Establecer región del sistema" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "Se requiere autenticación para establecer la región del sistema" #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Configurar teclado" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "Se requiere autenticación para configurar el teclado del sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Permitir que las aplicaciones impidan el apagado del sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Se requiere autenticación para que una aplicación impida el apagado del " "sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Permitir a las aplicaciones retrasar el apagado del sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Se requiere autenticación para que una aplicación retrase el apagado del " "sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Permitir a las aplicaciones impedir la hibernación del sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Se requiere autenticación para que una aplicación impida la hibernación del " "sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Permitir a las aplicaciones retrasar la hibernación del sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Se requiere autenticación para que una aplicación retrase la hibernación del " "sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "" "Permitir a las aplicaciones impedir la suspensión automática del sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Se requiere autenticación para que una aplicación impida la suspensión " "automática del sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "" "Permitir a las aplicaciones impedir el manejo de la tecla de encendido/" "apagado por parte del sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Se requiere autenticación para que una aplicación impida el manejo de la " "tecla de encendido/apagado por parte del sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Permitir a las aplicaciones impedir el manejo de la tecla de suspensión por " "parte del sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Se requiere autenticación para que una aplicación impida el manejo de la " "tecla de suspensión por parte del sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Permitir a las aplicaciones impedir el manejo de la tecla de hibernación por " "parte del sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Se requiere autenticación para que una aplicación impida el manejo de la " "tecla de hibernación por parte del sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Permitir a las aplicaciones impedir el manejo del cierre de la tapa del " "portátil por parte del sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Se requiere autenticación para que una aplicación impida el manejo del " "cierre de la tapa del portátil por parte del sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "Permitir la ejecución de programas a usuarios no conectados" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Se requiere autenticación para la ejecución de programas por usuarios no " "conectados." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Permitir la conexión de dispositivos a los puestos de trabajo" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "" "Se requiere autenticación para conectar un dispositivo a un puesto de " "trabajo." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Refrescar los dispositivos asociados a cada puesto de trabajo" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Se requiere autenticación para reconfigurar los dispositivos asociados a " "cada puesto de trabajo." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Apagar el sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Se requiere autenticación para apagar el sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Apagar el sistema mientras todavía hay usuarios conectados" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Se requiere autenticación para apagar el sistema mientras todavía hay " "usuarios conectados." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "Apagar el sistema a pesar de que una aplicación lo impide" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Se requiere autenticación para apagar el sistema a pesar de que una " "aplicación lo impide." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Reiniciar el sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Se requiere autenticación para reiniciar el sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Reiniciar el sistema mientras todavía hay usuarios conectados" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Se requiere autenticación para reiniciar el sistema mientras todavía hay " "usuarios conectados." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "Reiniciar el sistema a pesar de que una aplicación lo impide" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Se requiere autenticación para reiniciar el sistema a pesar de que una " "aplicación lo impide." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Suspender el sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Se requiere autenticación para suspender el sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "Suspender el sistema mientras todavía hay usuarios conectados" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Se requiere autenticación para suspender el sistema mientras todavía hay " "usuarios conectados." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "Suspender el sistema a pesar de que una aplicación lo impide" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Se requiere autenticación para suspender el sistema a pesar de que una " "aplicación lo impide." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Hibernar el sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "Se requiere autenticación para hibernar el sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "Hibernar el sistema mientras todavía hay usuarios conectados" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Se requiere autenticación para hibernar el sistema mientras todavía hay " "usuarios conectados." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "Hibernar el sistema a pesar de que una aplicación lo impide" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Se requiere autenticación para hibernar el sistema a pesar de que una " "aplicación lo impide" #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Administrar sesiones activas, usuarios y puestos de trabajo" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Se requiere autenticación para administrar las sesiones activas, usuarios y " "puestos de trabajo." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Bloquear/desbloquear sesiones activas" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "Se requiere autenticación para bloquear/desbloquear sesiones activas." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "" "Permitir indicación al firmware para arrancar la interfaz de configuración" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "" "Se requiere autenticación para indicar al firmware que arranque la interfaz " "de configuración." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:56 #, fuzzy msgid "Authentication is required to set a wall message" msgstr "Se requiere autenticación para establecer el nombre de equipo local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Conectarse a un contenedor local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "Se requiere autenticación para conectarse a un contenedor local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 #, fuzzy msgid "Log into the local host" msgstr "Conectarse a un contenedor local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 #, fuzzy msgid "Authentication is required to log into the local host." msgstr "Se requiere autenticación para conectarse a un contenedor local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 #, fuzzy msgid "Acquire a shell in a local container" msgstr "Conectarse a un contenedor local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 #, fuzzy msgid "Authentication is required to acquire a shell in a local container." msgstr "Se requiere autenticación para conectarse a un contenedor local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 #, fuzzy msgid "Authentication is required to acquire a shell on the local host." msgstr "Se requiere autenticación para establecer el nombre de equipo local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 #, fuzzy msgid "Acquire a pseudo TTY in a local container" msgstr "Conectarse a un contenedor local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 #, fuzzy msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "Se requiere autenticación para conectarse a un contenedor local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 #, fuzzy msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "Se requiere autenticación para establecer el nombre de equipo local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Administrar máquinas virtuales y contenedores locales" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Se requiere autenticación para administrar las máquinas virtuales y los " "contenedores locales." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Administrar imágenes de máquina virtual y de contenedor locales" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Se requiere autenticación para administrar las imágenes de máquina virtual y " "de contenedor locales." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Establecer fecha y hora del sistema" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Se requiere autenticación para establecer la fecha y hora del sistema." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Establecer la zona horaria del sistema" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Se requiere autenticación para establecer la zona horaria del sistema." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Establecer reloj del sistema en formato de hora local/tiempo UTC" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Se requiere autenticación para establecer el reloj del sistema en formato de " "hora local / tiempo UTC." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Activar/desactivar la sincronización de hora por red" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Se requiere autenticación para activar/desactivar la sincronización de hora " "por red." #: ../src/core/dbus-unit.c:428 #, fuzzy msgid "Authentication is required to start '$(unit)'." msgstr "Se requiere autenticación para establecer la fecha y hora del sistema." #: ../src/core/dbus-unit.c:429 #, fuzzy msgid "Authentication is required to stop '$(unit)'." msgstr "Se requiere autenticación para establecer la fecha y hora del sistema." #: ../src/core/dbus-unit.c:430 #, fuzzy msgid "Authentication is required to reload '$(unit)'." msgstr "Se requiere autenticación para recargar el estado de systemd." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 #, fuzzy msgid "Authentication is required to restart '$(unit)'." msgstr "Se requiere autenticación para establecer la fecha y hora del sistema." #: ../src/core/dbus-unit.c:535 #, fuzzy msgid "Authentication is required to kill '$(unit)'." msgstr "Se requiere autenticación para conectarse a un contenedor local." #: ../src/core/dbus-unit.c:565 #, fuzzy msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "Se requiere autenticación para establecer el nombre de equipo local." #: ../src/core/dbus-unit.c:597 #, fuzzy msgid "Authentication is required to set properties on '$(unit)'." msgstr "Se requiere autenticación para establecer la fecha y hora del sistema." #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" #~ msgstr "" #~ "Presione Ctrl+C para cancelar todas las comprobaciones del sistema de " #~ "archivos en curso" #~ msgid "Checking in progress on %d disk (%3.1f%% complete)" #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" #~ msgstr[0] "Comprobando progreso en %d disco (%3.1f %% completado)" #~ msgstr[1] "Comprobando progreso en %d discos (%3.1f %% completado)" systemd-229/po/fr.po000066400000000000000000000574021265713322000144560ustar00rootroot00000000000000# French translations for systemd package # Traductions françaises du paquet systemd. # This file is distributed under the same license as the systemd package. # Sylvain Plantefève , 2013-2015 # msgid "" msgstr "" "Project-Id-Version: systemd\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-21 20:11+0200\n" "PO-Revision-Date: 2014-12-28 13:04+0100\n" "Last-Translator: Sylvain Plantefève \n" "Language-Team: French\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Renvoyer la phrase secrète au système" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "Authentification requise pour renvoyer la phrase secrète au système." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Gérer les services système ou les unités" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Authentification requise pour gérer les services système ou les unités." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Gérer le service système ou ses fichiers unités" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Authentification requise pour gérer le service système ou ses fichiers " "unités." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "" "Définir ou supprimer des variables d'environnement du système ou du " "gestionnaire de services" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Authentification requise pour définir ou supprimer des variables " "d'environnement du système ou du gestionnaire de services." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Recharger l'état de systemd" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "Authentification requise pour recharger l'état de systemd" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Définir le nom d'hôte" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Authentification requise pour définir le nom d'hôte local." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Définir le nom d'hôte statique" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Authentification requise pour définir le nom d'hôte local de manière " "statique, tout comme le nom d'hôte familier." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Définir les informations sur la machine" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "" "Authentification requise pour définir les informations sur la machine locale." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Importer une image de machine virtuelle (VM) ou de conteneur" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "" "Authentification requise pour importer une image de machine virtuelle (VM) " "ou de conteneur." #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Exporter une image de machine virtuelle (VM) ou de conteneur" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "" "Authentification requise pour exporter une image de machine virtuelle (VM) " "ou de conteneur." #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Télécharger une image de machine virtuelle (VM) ou de conteneur" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "" "Authentification requise pour télécharger une image de machine virtuelle " "(VM) ou de conteneur." #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Définir la langue du système" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "Authentification requise pour définir la langue du système." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Définir les paramètres de clavier du système" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "" "Authentification requise pour définir les paramètres de clavier du système." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Permet aux applications d'empêcher l'arrêt du système" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Authentification requise pour permettre à une application d'empêcher l'arrêt " "du système." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Permet aux applications de retarder l'arrêt du système" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Authentification requise pour permettre à une application de retarder " "l'arrêt du système." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Permet aux applications d'empêcher la mise en veille du système" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Authentification requise pour permettre à une application d'empêcher la mise " "en veille du système." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Permet aux applications de retarder la mise en veille du système" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Authentification requise pour permettre à une application de retarder la " "mise en veille du système." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "" "Permet aux applications d'empêcher l'hibernation automatique du système" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Authentification requise pour permettre à une application d'empêcher " "l'hibernation automatique du système." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "" "Permet aux applications d'empêcher la gestion du bouton d'alimentation du " "système" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Authentification requise pour permettre à une application d'empêcher la " "gestion du bouton d'alimentation du système." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Permet aux applications d'empêcher la gestion du bouton de mise en veille du " "système" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Authentification requise pour permettre à une application d'empêcher la " "gestion du bouton de mise en veille du système." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Permet aux applications d'empêcher la gestion du bouton d'hibernation du " "système" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Authentification requise pour permettre à une application d'empêcher la " "gestion du bouton d'hibernation du système." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Permet aux applications d'empêcher la gestion par le système du rabat de " "l'écran" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Authentification requise pour permettre à une application d'empêcher la " "gestion par le système du rabat de l'écran." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "Permet aux utilisateurs non connectés d'exécuter des programmes" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Authentification requise pour permettre aux utilisateurs non connectés " "d'exécuter des programmes." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Permet d'associer des périphériques à des postes (seats)" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "" "Authentification requise pour associer un périphérique à un poste (seat)." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Révoquer les associations de périphériques aux postes (seats)" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Authentification requise pour révoquer les associations de périphériques aux " "postes (seats)." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Éteindre le système" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Authentification requise pour éteindre le système." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Éteindre le système alors que d'autres utilisateurs sont connectés" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Authentification requise pour éteindre le système alors que d'autres " "utilisateurs sont connectés." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "Éteindre le système alors qu'une application a demandé de l'empêcher" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Authentification requise pour éteindre le système alors qu'une application a " "demandé de l'empêcher." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Redémarrer le système" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Authentification requise pour redémarrer le système." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Redémarrer le système alors que d'autres utilisateurs sont connectés" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Authentification requise pour redémarrer le système alors que d'autres " "utilisateurs sont connectés." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "Redémarrer le système alors qu'une application a demandé de l'empêcher" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Authentification requise pour redémarrer le système alors qu'une application " "a demandé de l'empêcher." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Mettre le système en veille" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Authentification requise pour mettre le système en veille." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "" "Mettre le système en veille alors que d'autres utilisateurs sont connectés" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Authentification requise pour mettre le système en veille alors que d'autres " "utilisateurs sont connectés." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "" "Mettre le système en veille alors qu'une application a demandé de l'empêcher" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Authentification requise pour mettre le système en veille alors qu'une " "application a demandé de l'empêcher." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Mettre le système en hibernation" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "Authentification requise pour mettre le système en hibernation." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "" "Mettre le système en hibernation alors que d'autres utilisateurs sont " "connectés" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Authentification requise pour mettre le système en hibernation alors que " "d'autres utilisateurs sont connectés." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "" "Mettre le système en hibernation alors qu'une application a demandé de " "l'empêcher" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Authentification requise pour mettre le système en hibernation alors qu'une " "application a demandé de l'empêcher." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Gérer les sessions actives, les utilisateurs et les postes (seats)" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Authentification requise pour gérer les sessions actives, les utilisateurs " "et les postes (seats)." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Verrouiller ou déverrouiller des sessions actives" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "" "Authentification requise pour verrouiller ou déverrouiller des sessions " "actives." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "" "Permet d'indiquer au micrologiciel de démarrer sur l'interface de " "configuration" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "" "Authentification requise pour indiquer au micrologiciel de démarrer sur " "l'interface de configuration." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "Définir un message wall" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "Authentification requise pour définir un message wall." #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Connexion dans un conteneur local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "" "Authentification requise pour permettre la connexion dans un conteneur local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "Connexion à l'hôte local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "Authentification requise pour permettre la connexion à l'hôte local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "Obtenir une interface système dans un conteneur local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "" "Authentification requise pour obtenir une interface système dans un " "conteneur local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "Obtenir une interface système sur l'hôte local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "" "Authentification requise pour obtenir une interface système sur l'hôte local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "Obtenir un pseudo terminal dans un conteneur local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "" "Authentification requise pour obtenir un pseudo terminal dans un conteneur " "local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "Obtenir un pseudo terminal sur l'hôte local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "" "Authentification requise pour obtenir un pseudo terminal sur l'hôte local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Gérer les machines virtuelles (VM) et conteneurs locaux" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Authentification requise pour gérer les machines virtuelles (VM) et les " "conteneurs locaux." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Gérer les images locales de machines virtuelles (VM) et de conteneurs" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Authentification requise pour gérer les images locales de machines " "virtuelles (VM) et de conteneurs." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Définir l'heure du système" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Authentification requise pour définir l'heure du système." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Définir le fuseau horaire du système" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Authentification requise pour définir le fuseau horaire du système." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "" "Positionner l'horloge matérielle à l'heure locale ou sur le temps universel " "coordonné (UTC)" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Authentification requise pour positionner l'horloge matérielle à l'heure " "locale ou sur le temps universel coordonné (UTC)." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Activer ou désactiver la synchronisation de l'heure avec le réseau" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Authentification requise pour activer ou désactiver la synchronisation de " "l'heure avec le réseau." #: ../src/core/dbus-unit.c:428 msgid "Authentication is required to start '$(unit)'." msgstr "Authentification requise pour démarrer « $(unit) »." #: ../src/core/dbus-unit.c:429 msgid "Authentication is required to stop '$(unit)'." msgstr "Authentification requise pour arrêter « $(unit) »." #: ../src/core/dbus-unit.c:430 msgid "Authentication is required to reload '$(unit)'." msgstr "Authentification requise pour recharger « $(unit) »." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 msgid "Authentication is required to restart '$(unit)'." msgstr "Authentification requise pour redémarrer « $(unit) »." #: ../src/core/dbus-unit.c:535 msgid "Authentication is required to kill '$(unit)'." msgstr "Authentification requise pour tuer « $(unit) »." #: ../src/core/dbus-unit.c:565 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "" "Authentification requise pour réinitialiser l'état d'« échec » de " "« $(unit) »." #: ../src/core/dbus-unit.c:597 msgid "Authentication is required to set properties on '$(unit)'." msgstr "Authentification requise pour définir des propriétés de « $(unit) »." #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" #~ msgstr "" #~ "Appuyez sur Ctrl+C pour annuler toutes vérifications en cours du système " #~ "de fichiers" #~ msgid "Checking in progress on %d disk (%3.1f%% complete)" #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" #~ msgstr[0] "Vérification en cours sur %d disque (%3.1f%% complété)" #~ msgstr[1] "Vérification en cours sur %d disques (%3.1f%% complété)" systemd-229/po/gl.po000066400000000000000000000550111265713322000144430ustar00rootroot00000000000000# Copyright (C) 2015 # This file is distributed under the same license as the systemd package. # Fran Dieguez , 2015. msgid "" msgstr "" "Project-Id-Version: systemd\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-14 23:55+0200\n" "PO-Revision-Date: 2015-09-15 00:20+0200\n" "Last-Translator: Fran Dieguez \n" "Language-Team: gnome-l10n-gl@gnome.org\n" "Language: gl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Virtaal 0.7.1\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Enviar frase de paso de volta ao sistema" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "" "Requírese autenticación para enviar a frase de paso escrita de volta ao " "sistema." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Xestionar os servizos do sistema ou outras unidades" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Requírese autenticación para xestionar os servizos do sistema ou outras " "unidades" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Xestionar os servizos do sistema ou outros ficheiros" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Requírese autenticación para xestionar os servizos do sistema ou outros " "ficheiros." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "" "Estabelecer ou desestabelecer as variables de ambiente do sistema ou do " "xestor de servizos" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Requírese autenticación para estabelecer ou desestabelecer as variables de " "ambiente do sistema ou do xestor de servizos" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Recargar o estado de systemd" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "Requírese autenticación para recargar o estado de systemd." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Estabelecer o nome do equipo" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Requírese autenticación para estabelecer o nome local do equiupo." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Estabelecer o nome do equipo estático" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Requírese autenticación para estabelecer de forma o nome do equipo local " "estabelecido de forma estática, así como o nome do equipo lexíbel por " "persoas." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Estabelecer a información da máquina" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "Requírese autenticación para estabelecer a información da máquina local" #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Importar unha imaxe de MV ou contenedor" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "Requírese autenticación para imporar unha imaxe de MV ou contenedor" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Exportar unha imaxe de MV ou contenedor" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "Requírese autenticación para exportar unha imaxe de MV ou contenedor" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Descargar unha imaxe de MV ou contenedor" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "Requírese autenticación para descargar unha imaxe de MV ou contenedor" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Estabelecer a configuración rexional do sistema" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "" "Requírese autenticación para estabelecer a configuración rexional do sistema" #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Estabelecer as preferencias do teclado do sistema" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "" "Requírese autenticación para estabelecer as preferencias do teclado do " "sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Permitir aos aplicativos inhibit o apagado do sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Requírese autenticación para permitirlle a un aplicativo poida inhibir o " "apagado do sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Permitir aos aplicativos retrasar o apagado do sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Requírese autenticación para permitirlle a un aplicativo retrasar o apagado " "do sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Permitir aos aplicativos inhibir a suspensión do sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Requírese autenticación para permitirlle a un aplicativo inhibir a " "suspensión do sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Permitir aos aplicativos retrasar a suspensión do sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Requírese autenticación para permitirlle a un aplicativo retrasar a " "suspensión do sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "Permitir aos aplicativos inhibir a suspensión automática do sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Requírese autenticación para permitirlle a un aplicativo inhibir a " "suspensión automática do sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "" "Permitir aos aplicativos inhibir a xestión do sistema da tecla de acendido" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Requírese autenticación para permitirlle a un aplicativo inhibir a xestión " "do sistema da tecla de acendido." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Permitir aos aplicativos inhibir a xestión do sistema da tecla de suspensión" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Requírese autenticación para permitirlle a un aplicativo inhibir a xestión " "do sistema da tecla de suspensión." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Permitir aos aplicativos inhibir a xestión do sistema da tecla de hibernado" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Requírese autenticación para permitirlle a un aplicativo inhibir a xestión " "do sistema da tecla de hibernado." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Permitir aos aplicativos inhibir a xestión do sistema do interruptor da tapa." #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Requírese autenticación para permitirlle a un aplicativo inhibir a xestión " "do sistema do interruptor da tapa." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "Permitirlle a usuarios sen unha sesión iniciada executar programas" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Requírese autenticación para permitirlle executar programas a un usuario sen " "unha sesión iniciada." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Permitir conectar anexar a asentos" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "Requírese autenticación para anexar un dispositivo a un asento." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Reiniciar os anexos do dispositivo aos asentos" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Requírese autenticación para reiniciar como os dispositivos están anexados " "aos asentos." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Apagar o sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Requírese autenticación para apagar o sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Apagar o sistema mentres hai usuarios con unha sesión iniciada" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Requírese autenticación para apagar o sistema mentres hai usuarios con unha " "sesión iniciada." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "Apagar o sistema cando un aplicativo solicitou a súa inhibición" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Requírese autenticación para apagar o sistema mentres un aplicativo " "solicitou a súa inhibición." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Reiniciar o sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Requírese autenticación para reiniciar o sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Reiniciar o sistema mentres outros usuarios teñen unha sesión iniciada" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Requírese autenticación para reiniciar o sistema mentres outros usuarios " "teñen unha sesión iniciada." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "Reiniciar o sistema cando un aplicativo solicitou a súa inhibición" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Requírese autenticación para reiniciar o sistema mentres un aplicativo " "solicitou a súa inhibición." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Suspender o sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Requírese autenticación para suspender o sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "Suspender o sistema mentres outros usuarios teñen unha sesión iniciada" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Requírese autenticación para suspender o sistema mentres outros usuarios " "teñen unha sesión iniciada." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "Suspender o sistema cando un aplicativo solicitou a súa inhibición" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Requírese autenticación para suspender o sistema mentres un aplicativo " "solicitou a súa inhibición." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Hibernar o sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "Requírese autenticación para hibernar o sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "Hibernar o sistema mentres outros usuarios teñen unha sesión iniciada" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Requírese autenticación para hibernar o sistema mentres outros usuarios " "teñen unha sesión iniciada." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "Hibernar o sistema cando un aplicativo solicitou a súa inhibición" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Requírese autenticación para hibernar o sistema mentres un aplicativo " "solicitou a súa inhibición." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Xestionar as sesións, usuarios e asentos activos" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Requírese autenticación para xestionar as sesións, usuariso e asentos activos" #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Bloquear ou desbloquear sesión activas" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "" "Requírese autenticación para bloquear ou desbloquear as sesións activas." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "Permitir indicarlle ao firmware arrincar para configurar unha interface" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "" "Requírese autenticación para indicarlle ao firmware arrincar para configurar " "unha interface." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "Estabelecer a mensaxe do muro" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "Requírese autenticación para estabelecer unha mensaxe de muro" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Iniciar sesión nun contenedor local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "Requírese autenticación para iniciar sesión nun contenedor local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "Iniciar sesión nun equipo local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "Requírese autenticación para iniciar sesión nun equipo local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "Adquirir unha shell nun contenedor local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "Requírese autenticación para adquirir unha shell nun contenedor local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "Adquirir unha shell nun equipo local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "Requírese autenticación para adquirir unha shell nun equipo local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "Adquirir unha pseudo TTY nun contenedor local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "" "Requírese autenticación para adquirir unha pseudo TTY nun contenedor local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "Adquirir unha pseudo TTY nun equipo local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "Requírese autenticación para adquirir unha pseudo TTY nun equipo local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Xestionar máquinas virtuais e contenedores locais" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Requírese autenticación para xestionar máquinas virtuais e contenedores " "locais." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Xestionar imaxes locais virtuais e contenedores locais" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Requírese autenticación para xestionar imaxes de máquinas virtuais e " "contenedores locais." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Estabelecer a hora do sistema" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Requírese autenticación para estabelecer a hora do sistema." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Estabelecer o fuso horario" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Requírese autenticación para estabelecer o fuso horario do sistema." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Estabelecer o RTC ao fuso horario ou UTC" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Requírese autenticación para controlar se o RTC almacena a hora local ou a " "UTC." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Activar ou desactivar a sincronización de hora por rede" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Requírese autenticación para controlar se a sincronización de hora por rede " "debería activarse." #: ../src/core/dbus-unit.c:428 msgid "Authentication is required to start '$(unit)'." msgstr "Requírese autenticación para inciar '$(unit)'." #: ../src/core/dbus-unit.c:429 msgid "Authentication is required to stop '$(unit)'." msgstr "Requírese autenticación para deter '$(unit)'." #: ../src/core/dbus-unit.c:430 msgid "Authentication is required to reload '$(unit)'." msgstr "Requírese autenticación para recargar '$(unit)'." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 msgid "Authentication is required to restart '$(unit)'." msgstr "Requírese autenticación para reiniciar '$(unit)'." #: ../src/core/dbus-unit.c:535 msgid "Authentication is required to kill '$(unit)'." msgstr "Requírese autenticación para matar '$(unit)'." #: ../src/core/dbus-unit.c:565 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "Requírese autenticación para reinicair o estado «fallido» de '$(unit)'." #: ../src/core/dbus-unit.c:597 msgid "Authentication is required to set properties on '$(unit)'." msgstr "Requírese autenticación para estabelecer as propiedades en '$(unit)'." systemd-229/po/hu.po000066400000000000000000000561341265713322000144640ustar00rootroot00000000000000# Hungarian translation of systemd # Copyright (C) 2015, 2016. Free Software Foundation, Inc. # This file is distributed under the same license as the systemd package. # # Gabor Kelemen , 2015, 2016. msgid "" msgstr "" "Project-Id-Version: systemd master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-01-02 13:41+0100\n" "PO-Revision-Date: 2016-01-02 13:45+0100\n" "Last-Translator: Gabor Kelemen \n" "Language-Team: Hungarian \n" "Language: hu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Lokalize 1.5\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Jelmondat visszaküldése a rendszernek" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "" "Hitelesítés szükséges a bevitt jelmondat visszaküldéséhez a rendszernek." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Rendszerszolgáltatások vagy más egységek kezelése" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Hitelesítés szükséges a rendszerszolgáltatások vagy más egységek kezeléséhez." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Rendszerszolgáltatás- vagy egységfájlok kezelése" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Hitelesítés szükséges a rendszerszolgáltatás- vagy egységfájlok kezeléséhez." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "" "Rendszer- és szolgáltatáskezelő környezeti változóinak beállítása vagy " "törlése" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Hitelesítés szükséges a rendszer- és szolgáltatáskezelő környezeti " "változóinak beállításához vagy törléséhez." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "A systemd állapotának újratöltése" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "Hitelesítés szükséges a systemd állapotának újratöltéséhez." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Gépnév beállítása" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Hitelesítés szükséges a helyi gépnév beállításához." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Statikus gépnév beállítása" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Hitelesítés szükséges a statikusan megadott helyi gépnév, valamint a szép " "gépnév beállításához." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Gépinformációk beállítása" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "Hitelesítés szükséges a helyi gép információinak beállításához." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "VM vagy konténer lemezkép importálása" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép importálásához." #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "VM vagy konténer lemezkép exportálása" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép exportálásához." #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "VM vagy konténer lemezkép letöltése" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép letöltéséhez." #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Területi beállítás megadása" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "Hitelesítés szükséges a rendszer területi beállításainak megadásához." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Rendszer billentyűzetbeállítások megadása" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "" "Hitelesítés szükséges a rendszer billentyűzetbeállításainak megadásához." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Alkalmazások meggátolhatják a rendszer leállítását" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Hitelesítés szükséges egy alkalmazás számára a rendszerleállítás " "meggátlásához." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Alkalmazások késleltethetik a rendszer leállítását" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Hitelesítés szükséges egy alkalmazás számára a rendszerleállítás " "késleltetéséhez." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Alkalmazások meggátolhatják a rendszer altatását" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Hitelesítés szükséges egy alkalmazás számára a rendszeraltatás meggátlásához." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Alkalmazások késleltethetik a rendszer altatását" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Hitelesítés szükséges egy alkalmazás számára a rendszeraltatás " "késleltetéséhez." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "Alkalmazások meggátolhatják a rendszer automatikus felfüggesztését" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Hitelesítés szükséges egy alkalmazás számára az automatikus " "rendszerfelfüggesztés meggátlásához." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "" "Alkalmazások meggátolhatják a bekapcsoló gomb rendszer általi kezelését" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Hitelesítés szükséges egy alkalmazás számára a bekapcsoló gomb rendszer " "általi kezelésének meggátlásához." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Alkalmazások meggátolhatják a felfüggesztés gomb rendszer általi kezelését" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Hitelesítés szükséges egy alkalmazás számára a felfüggesztés gomb rendszer " "általi kezelésének meggátlásához." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Alkalmazások meggátolhatják a hibernálás gomb rendszer általi kezelését" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Hitelesítés szükséges egy alkalmazás számára a hibernálás gomb rendszer " "általi kezelésének meggátlásához." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "Alkalmazások meggátolhatják a fedélkapcsoló rendszer általi kezelését" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Hitelesítés szükséges egy alkalmazás számára a fedélkapcsoló rendszer általi " "kezelésének meggátlásához." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "Programfuttatás engedélyezése be nem jelentkezett felhasználók számára" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Hitelesítés szükséges a programfuttatáshoz be nem jelentkezett " "felhasználóként." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Eszközök csatolásának engedélyezése munkaállomásokhoz" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "" "Hitelesítés szükséges eszköz csatolásának engedélyezéséhez egy " "munkaállomáshoz" #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Eszközök és munkaállomások csatolásainak törlése" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Hitelesítés szükséges az eszközök munkaállomásokhoz csatolásainak " "alaphelyzetbe állításához." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "A rendszer kikapcsolása" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Hitelesítés szükséges a rendszer kikapcsolásához." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "" "A rendszer kikapcsolása miközben be vannak jelentkezve más felhasználók" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Hitelesítés szükséges a rendszer kikapcsolásához miközben be vannak " "jelentkezve más felhasználók." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "" "A rendszer kikapcsolása miközben egy alkalmazás ennek meggátlását kérte" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Hitelesítés szükséges a rendszer kikapcsolásához miközben egy alkalmazás " "ennek meggátlását kérte." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "A rendszer újraindítása" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Hitelesítés szükséges a rendszer újraindításához." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "A rendszer újraindítása mialatt be vannak jelentkezve más felhasználók" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Hitelesítés szükséges a rendszer újraindításához miközben be vannak " "jelentkezve más felhasználók." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "" "A rendszer újraindítása miközben egy alkalmazás ennek meggátlását kérte" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Hitelesítés szükséges a rendszer újraindításához miközben egy alkalmazás " "ennek meggátlását kérte." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "A rendszer felfüggesztése" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Hitelesítés szükséges a rendszer felfüggesztéséhez." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "" "A rendszer felfüggesztése mialatt be vannak jelentkezve más felhasználók" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Hitelesítés szükséges a rendszer felfüggesztéséhez miközben be vannak " "jelentkezve más felhasználók." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "" "A rendszer felfüggesztése miközben egy alkalmazás ennek meggátlását kérte" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Hitelesítés szükséges a rendszer felfüggesztéséhez miközben egy alkalmazás " "ennek meggátlását kérte." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "A rendszer hibernálása" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "Hitelesítés szükséges a rendszer hibernálásához." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "A rendszer hibernálása mialatt be vannak jelentkezve más felhasználók" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Hitelesítés szükséges a rendszer hibernálásához miközben be vannak " "jelentkezve más felhasználók." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "A rendszer hibernálása miközben egy alkalmazás ennek meggátlását kérte" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Hitelesítés szükséges a rendszer hibernálásához miközben egy alkalmazás " "ennek meggátlását kérte." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Aktív munkamenetek, felhasználók és munkaállomások kezelése" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Hitelesítés szükséges az aktív munkamenetek, felhasználók és munkaállomások " "kezeléséhez." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Aktív munkamenetek zárolása vagy feloldása" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "" "Hitelesítés szükséges az aktív munkamenetek zárolásához vagy feloldásához." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "A firmware-nek jelezhető, hogy a beállítófelületet bootolja" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "" "Hitelesítés szükséges a firmware-nek jelzéshez, hogy a beállítófelületet " "bootolja" #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "Falüzenet beállítása" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "Hitelesítés szükséges a falüzenet beállításához" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Bejelentkezés helyi konténerbe" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "Bejelentkezés a helyi gépre" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "Hitelesítés szükséges a bejelentkezéshez a helyi gépre." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "Parancsértelmező elérése helyi konténerben" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "Hitelesítés szükséges a parancsértelmező eléréséhez helyi konténerben." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "Parancsértelmező elérése a helyi gépen" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "Hitelesítés szükséges a parancsértelmező eléréséhez a helyi gépen." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "Pszeudoterminál elérése helyi konténerben" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "Hitelesítés szükséges a pszeudoterminál eléréséhez helyi konténerben." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "Pszeudoterminál elérése helyi gépen" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "Hitelesítés szükséges a pszeudoterminál eléréséhez a helyi gépen." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Virtuális gépek és konténerek kezelése" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "Hitelesítés szükséges helyi virtuális gépek és konténerek kezeléséhez." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Helyi virtuális gép és konténer lemezképek kezelése" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Hitelesítés szükséges a helyi virtuális gép és konténer lemezképek " "kezeléséhez." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Rendszeridő beállítása" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Hitelesítés szükséges a rendszeridő beállításához." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Rendszer időzónájának beállítása" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Hitelesítés szükséges a rendszer időzónájának beállításához." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Az RTC beállítása helyi időzónára vagy UTC-re" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Hitelesítés szükséges az RTC beállításához a helyi időzóna vagy UTC " "tárolására." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Hálózati időszinkronizáció be- vagy kikapcsolása" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "Hitelesítés szükséges a hálózati időszinkronizáció engedélyezéséhez." #: ../src/core/dbus-unit.c:449 msgid "Authentication is required to start '$(unit)'." msgstr "Hitelesítés szükséges a következő elindításához: „$(unit)”." #: ../src/core/dbus-unit.c:450 msgid "Authentication is required to stop '$(unit)'." msgstr "Hitelesítés szükséges a következő leállításához: „$(unit)”." #: ../src/core/dbus-unit.c:451 msgid "Authentication is required to reload '$(unit)'." msgstr "Hitelesítés szükséges a következő újratöltéséhez: „$(unit)”." #: ../src/core/dbus-unit.c:452 ../src/core/dbus-unit.c:453 msgid "Authentication is required to restart '$(unit)'." msgstr "Hitelesítés szükséges a következő újraindításához: „$(unit)”." #: ../src/core/dbus-unit.c:556 msgid "Authentication is required to kill '$(unit)'." msgstr "Hitelesítés szükséges a következő kilövéséhez: „$(unit)”." #: ../src/core/dbus-unit.c:586 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "" "Hitelesítés szükséges a következő „sikertelen” állapotának törléséhez: " "„$(unit)”." #: ../src/core/dbus-unit.c:618 msgid "Authentication is required to set properties on '$(unit)'." msgstr "" "Hitelesítés szükséges a következő tulajdonságainak beállításához: „$(unit)”." systemd-229/po/it.po000066400000000000000000000546211265713322000144630ustar00rootroot00000000000000# Italian translations for systemd package # Traduzione in italiano per il pacchetto systemd # This file is distributed under the same license as the systemd package. # Daniele Medri , 2013-2015. # msgid "" msgstr "" "Project-Id-Version: systemd\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-22 16:37+0100\n" "PO-Revision-Date: 2015-11-22 16:54+0100\n" "Last-Translator: Daniele Medri \n" "Language-Team: Italian\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 1.8.5\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Inviare la frase segreta (passphrase) al sistema" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "" "Autenticazione richiesta per inviare la frase segreta (passphrase) al " "sistema." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Gestisci i servizi o le altre unità di sistema" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Autenticazione richiesta per gestire i servizi o le altre unità di sistema." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Gestisci i file dei servizi o delle unità di sistema" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Autenticazione richiesta per gestire i file dei servizi o delle unità di " "sistema." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "" "Configura le variabili d'ambiente per la gestione dei servizi e del sistema" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Autenticazione richiesta per configurare le variabili d'ambiente per la " "gestione dei servizi e del sistema" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Riavviare lo stato di systemd" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "Autenticazione richiesta per riavviare lo stato di sistemd." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Configura il nome host" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Autenticazione richiesta per configurare il nome host locale." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Configura il nome host statico" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Autenticazione richiesta per configurare staticamente il nome host locale e " "il nome host descrittivo." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Configura le informazioni sulla macchina" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "" "Autenticazione richiesta per configurare le informazioni sulla macchina " "locale." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Importa un'immagine VM o un container" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "Autenticazione richiesta per importare un'immagine VM o un container" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Esporta un'immagine VM o un container" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "Autenticazione richiesta per esportare un'immagine VM o un container" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Scarica un'immagine VM o un container" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "Autenticazione richiesta per scaricare un'immagine VM o un container" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Configura le impostazioni regionali di sistema" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "" "Autenticazione richiesta per configurare le impostazioni regionali di " "sistema." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Configura la tastiera di sistema" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "Autenticazione richiesta per configurare la tastiera di sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Consenti alle applicazioni di inibire lo spegnimento del sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Autenticazione richiesta per un'applicazione per inibire lo spegnimento del " "sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Consenti alle applicazioni di ritardare lo spegnimento del sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Autenticazione richiesta per un'applicazione per ritardare lo spegnimento " "del sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Consenti alle applicazioni di inibire il sistema in pausa" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Autenticazione richiesta per un'applicazione per inibire il sistema in pausa." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Consenti alle applicazioni di ritardare il sistema in pausa" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Autenticazione richiesta per un'applicazione per ritardare il sistema in " "pausa." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "" "Consenti alle applicazioni di inibire la sospesione automatica del sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Autenticazione richiesta per un'applicazione per inibire la sospensione " "automatica del sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "" "Consenti alle applicazioni di inibire la gestione di sistema del tasto di " "accensione" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Autenticazione richiesta per un'applicazione per inibire la gestione di " "sistema del tasto di accensione." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Consenti alle applicazioni di inibire la gestione di sistema del tasto di " "sospensione" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Autenticazione richiesta per un'applicazione per inibire la gestione di " "sistema del tasto di sospensione." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Consenti alle applicazioni di inibire la gestione di sistema del tasto di " "ibernazione" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Autenticazione richiesta per un'applicazione per inibire la gestione di " "sistema del tasto di ibernazione." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Consenti alle applicazioni di inibire la gestione di sistema alla apertura/" "chiusura del portatile" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Autenticazione richiesta per consentire ad un'applicazione di inibire la " "gestione di sistema alla apertura/chiusura del portatile." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "Consenti agli utenti non connessi di eseguire programmi" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Autenticazione richiesta per consentire agli utenti non connessi di eseguire " "programmi." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Consenti di collegare dispositivi alle postazioni" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "" "Autenticazione richiesta per collegare un dispositivo ad una postazione." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Scollega i dispositivi dalla postazione" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Autenticazione richiesta per ripristinare come i dispositivi sono collegati " "alle postazioni." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Spegnere il sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Autenticazione richiesta per spegnere il sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Spegnere il sistema mentre altri utenti sono connessi" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Autenticazione richiesta per spegnere il sistema mentre altri utenti sono " "connessi." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "Spegnere il sistema mentre un'applicazione chiede di inibirne l'azione" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Autenticazione richiesta per spegnere il sistema mentre un'applicazione " "chiede di inibirne l'azione." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Riavviare il sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Autenticazione richiesta per riavviare il sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Riavviare il sistema mentre altri utenti sono connessi" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Autenticazione richiesta per riavviare il sistema mentre altri utenti sono " "connessi." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "" "Riavviare il sistema mentre un'applicazione chiede di inibirne l'azione" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Autenticazione richiesta per riavviare il sistema mentre un'applicazione " "chiede di inibirne l'azione." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Sospendere il sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Autenticazione richiesta per sospendere il sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "Sospendere il sistema mentre altri utenti sono connessi" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Autenticazione richiesta per sospendere il sistema mentre altri utenti sono " "connessi." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "" "Sospendere il sistema mentre un'applicazione chiede di inibirne l'azione" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Autenticazione richiesta per sospendere il sistema mentre un'applicazione " "chiede di inibirne l'azione." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Ibernare il sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "Autenticazione richiesta per ibernare il sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "Ibernare il sistema mentre altri utenti sono connessi" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Autenticazione richiesta per ibernare il sistema mentre altri utenti sono " "connessi." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "Ibernare il sistema mentre un'applicazione chiede di inibirne l'azione" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Autenticazione richiesta per ibernare il sistema mentre un'applicazione " "chiede di inibirne l'azione." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Gestione delle sessioni attive, utenti e postazioni" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Autenticazione richiesta per gestire le sessioni attive, gli utenti e le " "postazioni." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Blocca/sblocca sessioni attive" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "Autenticazione richiesta per bloccare o sbloccare le sessioni attive." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "" "Permette indicazioni per il firmware per avviare l'interfaccia di " "configurazione" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "" "Autenticazione richiesta per indicare al firmware di avviare l'interfaccia " "di configurazione." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "Configura un messaggio per gli utenti" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "Autenticazione richiesta per configurare un messaggio per gli utenti" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Accedi in un container locale" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "Autenticazione richiesta per accedere in un container locale." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "Accedi in un host locale" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "Autenticazione richiesta per accedere in un host locale." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "Apri una shell in un container locale" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "Autenticazione richiesta per aprire una shell in un container locale." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "Apri una shell in un host locale" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "Autenticazione richiesta per aprire una shell in un host locale." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "Apri un pseudo TTY in un container locale" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "" "Autenticazione richiesta per aprire un pseudo TTY in un container locale." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "Apri un pseudo TTY in un host locale" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "Autenticazione richiesta per aprire un pseudo TTY in un host locale." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Gestisci le virtual machine e i container locali" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Autenticazione richiesta per gestire le virtual machine e i container locali." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Gestisci le immagini locali delle virtual machine e dei container" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Autenticazione richiesta per gestire le immagini delle virtual machine e dei " "container locali." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Configura l'orario di sistema" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Autenticazione richiesta per configurare l'orario di sistema." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Configura il fuso orario di sistema" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Autenticazione richiesta per configurare il fuso orario di sistema." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "" "Configura l'orologio di sistema (RTC) al fuso orario locale o al tempo " "civile (UTC)" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Autenticazione richiesta per verificare se l'orologio di sistema (RTC) è " "configurato all'orario locale o al tempo civile (UTC)." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Abilita o meno la sincronizzazione dell'orario in rete" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Autenticazione richiesta per verificare se la sincronizzazione dell'orario " "in rete possa essere attivata." #: ../src/core/dbus-unit.c:428 msgid "Authentication is required to start '$(unit)'." msgstr "Autenticazione richiesta per avviare '$(unit)'." #: ../src/core/dbus-unit.c:429 msgid "Authentication is required to stop '$(unit)'." msgstr "Autenticazione richiesta per fermare '$(unit)'." #: ../src/core/dbus-unit.c:430 msgid "Authentication is required to reload '$(unit)'." msgstr "Autenticazione richiesta per ricaricare '$(unit)'." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 msgid "Authentication is required to restart '$(unit)'." msgstr "Autenticazione richiesta per riavviare '$(unit)'." #: ../src/core/dbus-unit.c:535 msgid "Authentication is required to kill '$(unit)'." msgstr "Autenticazione richiesta per terminare '$(unit)'." #: ../src/core/dbus-unit.c:565 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "" "Autenticazione richiesta per riconfigurare lo stato \"fallito\" di '$(unit)'." #: ../src/core/dbus-unit.c:597 msgid "Authentication is required to set properties on '$(unit)'." msgstr "Autenticazione richiesta per configurare le proprietà di '$(unit)'." systemd-229/po/ko.po000066400000000000000000000557131265713322000144630ustar00rootroot00000000000000# Korean translation for the systemd. # Copyright (C) 2015 systemd author and translators. # This file is distributed under the same license as the systemd package. # Seong-ho Cho , 2015. # Dongsu Park , 2015. # msgid "" msgstr "" "Project-Id-Version: systemd\n" "Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" "POT-Creation-Date: 2015-09-25 22:52+0900\n" "PO-Revision-Date: 2015-11-03 13:19+0100\n" "Last-Translator: Dongsu Park \n" "Language-Team: GNOME Korea \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Gtranslator 2.91.7\n" "Plural-Forms: nplurals=1; plural=0;\n" "Language: ko\n" "X-Poedit-SourceCharset: UTF-8\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "시스템에 암호문 보내기" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "시스템에 입력한 암호를 보내려면 인증이 필요합니다." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "시스템 서비스 또는 기타 유닛 관리" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "시스템 서비스 또는 기타 유닛을 관리하려면 인증이 필요합니다." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "시스템 서비스 또는 유닛 파일 관리" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "시스템 서비스 또는 유닛 파일을 관리하려면 인증이 필요합니다." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "시스템 및 서비스 관리자 환경 변수 설정 또는 설정 해제" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "시스템 및 서비스 관리자 환경 변수를 설정하거나 설정 해제하려면 인증이 필요합" "니다." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "systemd 상태 다시 불러오기" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "systemd 상태를 다시 불러오려면 인증이 필요합니다." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "호스트 이름 설정" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "로컬 호스트 이름을 설정하려면 인증이 필요합니다." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "정적 호스트 이름 설정" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "로컬 호스트 이름을 모양새를 갖춘 호스트 이름 처럼 정적으로 설정하려면 인증" "이 필요합니다." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "머신 정보 설정" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "로컬 머신 정보를 설정하려면 인증이 필요합니다." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "VM 또는 컨테이너의 이미지 가져오기" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "VM 또는 컨테이너의 이미지를 가져오려면 인증이 필요합니다" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "가상 머신 또는 컨테이너의 이미지 내보내기" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "가상 머신 또는 컨테이너의 이미지를 내보내려면 인증이 필요합니다" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "가상머신 또는 컨테이너 이미지 다운로드" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "가상머신 또는 컨테이너 이미지를 다운로드하려면 인증이 필요합니다" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "시스템 로캘 설정" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "시스템 로캘을 설정하려면 인증이 필요합니다." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "시스템 키보드 설정" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "시스템 키보드를 설정하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "프로그램의 시스템 전원 끄기 방지 요청 허용" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "프로그램의 시스템 전원 끄기 방지 요청을 허용하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "프로그램의 시스템 전원 끄기 지연 허용" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "프로그램의 시스템 전원 끄기 지연 동작을 허용하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "프로그램의 시스템 대기 상태 진입 방지 요청 허용" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "프로그램의 시스템 대기 상태 진입 방지 요청을 허용하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "프로그램의 시스템 대기 상태 진입 지연 허용" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "프로그램의 시스템 대기 상태 진입 지연 동작을 허용하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "프로그램의 시스템 자동 절전 상태 진입 방지 요청 허용" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "프로그램의 시스템 자동 절전 상태 진입 방지 요청을 허용하려면 인증이 필요합니" "다." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "프로그램의 시스템 전원 키 처리 방지 요청 허용" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "프로그램의 시스템 전원 키 처리 방지 요청을 허용하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "프로그램의 시스템 절전 키 처리 방지 요청 허용" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "프로그램의 시스템 절전 키 처리 방지 요청을 허용하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "프로그램의 시스템 최대 절전 키 처리 방지 요청 허용" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "프로그램의 시스템 최대 절전 키 처리 방지 요청을 허용하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "프로그램의 시스템 랩톱 덮개 스위치 처리 방지 요청 허용" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "프로그램의 시스템 랩톱 덮개 스위치 처리 방지 요청을 허용하려면 인증이 필요합" "니다." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "비 로그인 사용자 프로그램 실행 허용" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "비 로그인 사용자에게 프로그램 실행을 허용하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "시트에 장치 부착 허용" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "시트에 장치 부착을 허용하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "시트로부터 장치 해제 허용" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "시트에 붙인 장치 상태를 초기화하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "시스템 끄기" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "시스템을 끄려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "다른 사용자가 로그인 했을 때 시스템 끄기" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "다른 사용자가 로그인 했을 때 시스템 전원을 끄려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "프로그램이 시스템을 끄지 못하게 요청할 때 시스템 전원 끄기" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "프로그램이 시스템을 끄지 못하게 요청할 때 시스템 전원을 끄려면 인증이 필요합" "니다." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "시스템 다시 시작" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "시스템을 다시 시작하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "다른 사용자가 로그인 했을 때 시스템 다시 시작" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "다른 사용자가 로그인 했을 때 시스템을 다시 시작하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "프로그램이 시스템을 다시 시작하지 못하게 요청할 때 시스템 다시 시작" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "프로그램이 시스템을 다시 시작하지 못하게 요청할 때 시스템을 다시 시작하려면 " "인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "시스템 절전 상태 진입" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "시스템을 절전 상태로 놓으려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "다른 사용자가 로그인 했을 때 시스템 절전 상태 진입" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "다른 사용자가 로그인 했을 때 시스템을 절전 상태로 놓으려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "프로그램이 절전 상태 진입을 못하게 요청할 때 시스템 절전 상태 진입" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "프로그램이 절전 상태 진입을 못하게 요청할 때 시스템을 절전 상태로 놓으려면 인" "증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "시스템 최대 절전 상태 진입" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "시스템을 최대 절전 상태로 놓으려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "다른 사용자가 로그인 했을 때 시스템 최대 절전 상태 진입" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "다른 사용자가 로그인 했을 때 시스템을 최대 절전 상태로 놓으려면 인증이 필요합" "니다." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "" "프로그램이 최대 절전 상태 진입을 못하게 요청할 때 시스템 최대 절전 상태 진입" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "프로그램이 최대 절전 상태 진입을 못하게 요청할 때 시스템을 최대 절전 상태로 " "놓으려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "활성 세션, 사용자, 시트 관리" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "활성 세션, 사용자 시트를 관리하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "활성 세션 잠금 또는 잠금 해제" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "활성화 세션을 잠금 또는 잠금 해제하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "설정 화면으로 부팅하도록 펌웨어에게 지시 허용" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "설정 화면으로 부팅하도록 펌웨어에게 지시하려면 인증이 필요합니다." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "wall 메시지 설정" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "wall 메시지를 설정하려면 인증이 필요합니다" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "로컬 컨테이너 로그인" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "로컬 컨테이너로 로그인하려면 인증이 필요합니다." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "로컬 호스트 로그인" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "로컬 호스트로 로그인하려면 인증이 필요합니다." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "로컬 컨테이너의 쉘 획득" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "로컬 컨테이너에서 쉘을 획득하려면 인증이 필요합니다." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "로컬 호스트 쉘 획득" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "로컬 호스트의 쉘을 획득하려면 인증이 필요합니다." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "로컬 컨테이너에서 의사 TTY 획득" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "로컬 컨테이너에서 의사 TTY를 획득하려면 인증이 필요합니다." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "로컬 호스트에서 유사 TTY 획득" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "로컬 호스트에서 의사 TTY를 획득하려면 인증이 필요합니다." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "로컬 가상 머신 및 컨테이너 관리" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "로컬 가상 머신 및 컨테이너를 관리하려면 인증이 필요합니다." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "로컬 가상 머신 및 컨테이너 이미지 관리" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "로컬 가상 머신 및 컨테이너 이미지를 관리하려면 인증이 필요합니다." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "시스템 시간 설정" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "시스템 시간을 설정하려면 인증이 필요합니다." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "시스템 시간대 설정" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "시스템 시간대를 설정하려면 인증이 필요합니다." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "RTC를 로컬 시간대 또는 UTC로 설정" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "RTC를 로컬 시간 또는 UTC 시간으로 저장할 지 여부를 제어하려면 인증이 필요합니" "다." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "네트워크 시간 동기화 켜거나 끄기" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "네트워크 시간 동기화의 활성화 여부를 제어하려면 인증이 필요합니다." #: ../src/core/dbus-unit.c:428 msgid "Authentication is required to start '$(unit)'." msgstr "'$(unit)' 서비스 유닛을 시작하려면 인증이 필요합니다." #: ../src/core/dbus-unit.c:429 msgid "Authentication is required to stop '$(unit)'." msgstr "'$(unit)' 서비스 유닛을 멈추려면 인증이 필요합니다." #: ../src/core/dbus-unit.c:430 msgid "Authentication is required to reload '$(unit)'." msgstr "'$(unit)' 서비스 유닛을 다시 불러오려면 인증이 필요합니다." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 msgid "Authentication is required to restart '$(unit)'." msgstr "'$(unit)' 서비스 유닛을 다시 시작하려면 인증이 필요합니다." #: ../src/core/dbus-unit.c:535 msgid "Authentication is required to kill '$(unit)'." msgstr "'$(unit)' 서비스 유닛을 강제로 끝내려면 인증이 필요합니다." #: ../src/core/dbus-unit.c:565 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "'$(unit)' 서비스 유닛의 \"실패\" 상태를 되돌리려면 인증이 필요합니다." #: ../src/core/dbus-unit.c:597 msgid "Authentication is required to set properties on '$(unit)'." msgstr "'$(unit)' 서비스 유닛 속성을 설정하려면 인증이 필요합니다." systemd-229/po/pl.po000066400000000000000000000563221265713322000144620ustar00rootroot00000000000000# translation of pl.po to Polish # Piotr Drąg , 2011, 2013, 2014, 2015. # Zbigniew Jędrzejewski-Szmek , 2011. # msgid "" msgstr "" "Project-Id-Version: systemd\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-06 20:39+0200\n" "PO-Revision-Date: 2015-09-06 20:40+0200\n" "Last-Translator: Piotr Drąg \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Wysłanie hasła z powrotem do systemu" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "" "Wymagane jest uwierzytelnienie, aby wysłać podane hasło z powrotem do " "systemu." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Zarządzanie usługami lub innymi jednostkami systemu" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Wymagane jest uwierzytelnienie, aby zarządzać usługami lub innymi " "jednostkami systemu." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Zarządzanie plikami usług lub jednostek systemu" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Wymagane jest uwierzytelnienie, aby zarządzać plikami usług lub jednostek " "systemu." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "" "Ustawienie lub usunięcie zmiennych środowiskowych menedżera systemu i usług" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Wymagane jest uwierzytelnienie, aby ustawić lub usunąć zmienne środowiskowe " "menedżera systemu i usług." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Ponowne wczytanie stanu systemd" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "Wymagane jest uwierzytelnienie, aby ponownie wczytać stan systemd." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Ustawienie nazwy komputera" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Wymagane jest uwierzytelnienie, aby ustawić nazwę lokalnego komputera." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Ustawienie statycznej nazwy komputera" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Wymagane jest uwierzytelnienie, aby ustawić statycznie skonfigurowaną nazwę " "lokalnego komputera, a także jego ładną nazwę." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Ustawienie informacji o komputerze" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "" "Wymagane jest uwierzytelnienie, aby ustawić informacje o lokalnym komputerze." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Import obrazu maszyny wirtualnej lub kontenera" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "" "Wymagane jest uwierzytelnienie, aby zaimportować obraz maszyny wirtualnej " "lub kontenera" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Eksport obrazu maszyny wirtualnej lub kontenera" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "" "Wymagane jest uwierzytelnienie, aby wyeksportować obraz maszyny wirtualnej " "lub kontenera" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Pobranie obrazu maszyny wirtualnej lub kontenera" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "" "Wymagane jest uwierzytelnienie, aby pobrać obraz maszyny wirtualnej lub " "kontenera" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Ustawienie lokalizacji systemu" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "Wymagane jest uwierzytelnienie, aby ustawić lokalizację systemu." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Ustawienie klawiatury systemu" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "Wymagane jest uwierzytelnienie, aby ustawić klawiaturę systemu." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Zezwolenie programom na wstrzymywanie wyłączenia systemu" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "Program wymaga uwierzytelnienia, aby wstrzymać wyłączenie systemu." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Zezwolenie programom na opóźnienie wyłączenia systemu" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "Program wymaga uwierzytelnienia, aby opóźnić wyłączenie systemu." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Zezwolenie programom na wstrzymanie uśpienia systemu" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "Program wymaga uwierzytelnienia, aby wstrzymać uśpienie systemu." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Zezwolenie programom na opóźnienie uśpienia systemu" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "Program wymaga uwierzytelnienia, aby opóźnić uśpienie systemu." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "Zezwolenie programom na wstrzymanie automatycznego uśpienia systemu" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Program wymaga uwierzytelnienia, aby wstrzymać automatyczne uśpienie systemu." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "" "Zezwolenie programom na wstrzymanie obsługi klawisza zasilania przez system" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Program wymaga uwierzytelnienia, aby wstrzymać obsługę klawisza zasilania " "przez system." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Zezwolenie programom na wstrzymanie obsługi klawisza uśpienia przez system" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Program wymaga uwierzytelnienia, aby wstrzymać obsługę klawisza uśpienia " "przez system." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Zezwolenie programom na wstrzymanie obsługi klawisza hibernacji przez system" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Program wymaga uwierzytelnienia, aby wstrzymać obsługę klawisza hibernacji " "przez system." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Zezwolenie programom na wstrzymanie obsługi przełącznika pokrywy przez system" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Program wymaga uwierzytelnienia, aby wstrzymać obsługę przełącznika pokrywy " "przez system." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "Zezwolenie niezalogowanym użytkownikom na uruchamianie programów" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Wymagane jest uwierzytelnienie, aby uruchamiać programy jako niezalogowany " "użytkownik." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Zezwolenie na podłączanie urządzeń do stanowisk" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "" "Wymagane jest uwierzytelnienie, aby podłączyć urządzenie do stanowiska." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Usunięcie podłączenia urządzeń do stanowisk" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Wymagane jest uwierzytelnienie, aby ponownie ustawić sposób podłączenia " "urządzeń do stanowisk." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Wyłączenie systemu" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Wymagane jest uwierzytelnienie, aby wyłączyć system." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Wyłączenie systemu, kiedy są zalogowani inni użytkownicy" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Wymagane jest uwierzytelnienie, aby wyłączyć system, kiedy są zalogowani " "inni użytkownicy." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "Wyłączenie systemu, kiedy program zażądał jego wstrzymania" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Wymagane jest uwierzytelnienie, aby wyłączyć system, kiedy program zażądał " "jego wstrzymania." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Ponowne uruchomienie systemu" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Wymagane jest uwierzytelnienie, aby ponownie uruchomić system." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Ponowne uruchomienie systemu, kiedy są zalogowani inni użytkownicy" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Wymagane jest uwierzytelnienie, aby ponownie uruchomić system, kiedy są " "zalogowani inni użytkownicy." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "Ponowne uruchomienie systemu, kiedy program zażądał jego wstrzymania" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Wymagane jest uwierzytelnienie, aby ponownie uruchomić system, kiedy program " "zażądał jego wstrzymania." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Uśpienie systemu" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Wymagane jest uwierzytelnienie, aby uśpić system." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "Uśpienie systemu, kiedy są zalogowani inni użytkownicy" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Wymagane jest uwierzytelnienie, aby uśpić system, kiedy są zalogowani inni " "użytkownicy." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "Uśpienie systemu, kiedy program zażądał jego wstrzymania" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Wymagane jest uwierzytelnienie, aby uśpić system, kiedy program zażądał jego " "wstrzymania." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Hibernacja systemu" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "Wymagane jest uwierzytelnienie, aby zahibernować system." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "Hibernacja systemu, kiedy są zalogowani inni użytkownicy" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy są zalogowani " "inni użytkownicy." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "Hibernacja systemu, kiedy program zażądał jej wstrzymania" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy program " "zażądał jej wstrzymania." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Zarządzanie aktywnymi sesjami, użytkownikami i stanowiskami" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Wymagane jest uwierzytelnienie, aby zarządzać aktywnymi sesjami, " "użytkownikami i stanowiskami." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Zablokowanie lub odblokowanie aktywnych sesji" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "" "Wymagane jest uwierzytelnienie, aby zablokować lub odblokować aktywne sesje." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "Wskazanie oprogramowaniu sprzętowemu, aby uruchomić interfejs ustawień" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "" "Wymagane jest uwierzytelnienie, aby wskazać oprogramowaniu sprzętowemu, że " "należy uruchomić interfejs ustawień." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "Ustawienie komunikatu wall" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "Wymagane jest uwierzytelnienie, aby ustawić komunikat wall" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Logowanie do lokalnego kontenera" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "" "Wymagane jest uwierzytelnienie, aby zalogować się do lokalnego kontenera." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "Logowanie do lokalnego komputera" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "" "Wymagane jest uwierzytelnienie, aby zalogować się do lokalnego komputera." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "Uzyskanie powłoki w lokalnym kontenerze" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "" "Wymagane jest uwierzytelnienie, aby uzyskać powłokę w lokalnym kontenerze." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "Uzyskanie powłoki na lokalnym komputerze" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "" "Wymagane jest uwierzytelnienie, aby uzyskać powłokę na lokalnym komputerze." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "Uzyskanie pseudo-TTY w lokalnym kontenerze" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "" "Wymagane jest uwierzytelnienie, aby uzyskać pseudo-TTY w lokalnym kontenerze." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "Uzyskanie pseudo-TTY na lokalnym komputerze" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "" "Wymagane jest uwierzytelnienie, aby uzyskać pseudo-TTY na lokalnym " "komputerze." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Zarządzanie lokalnymi maszynami wirtualnymi i kontenerami" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Wymagane jest uwierzytelnienie, aby zarządzać lokalnymi maszynami " "wirtualnymi i kontenerami." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Zarządzanie lokalnymi obrazami maszyn wirtualnych i kontenerów" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Wymagane jest uwierzytelnienie, aby zarządzać lokalnymi obrazami maszyn " "wirtualnych i kontenerów." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Ustawienie czasu systemu" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Wymagane jest uwierzytelnienie, aby ustawić czas systemu." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Ustawienie strefy czasowej systemu" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Wymagane jest uwierzytelnienie, aby ustawić strefę czasową systemu." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Ustawienie RTC na lokalną strefę czasową lub strefę UTC" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Wymagane jest uwierzytelnienie, aby kontrolować, czy RTC przechowuje czas " "lokalny lub czas UTC." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Włączenie lub wyłączenie synchronizacji czasu przez sieć" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Wymagane jest uwierzytelnienie, aby kontrolować, czy włączyć synchronizację " "czasu przez sieć." #: ../src/core/dbus-unit.c:428 msgid "Authentication is required to start '$(unit)'." msgstr "Wymagane jest uwierzytelnienie, aby uruchomić jednostkę „$(unit)”." #: ../src/core/dbus-unit.c:429 msgid "Authentication is required to stop '$(unit)'." msgstr "Wymagane jest uwierzytelnienie, aby zatrzymać jednostkę „$(unit)”." #: ../src/core/dbus-unit.c:430 msgid "Authentication is required to reload '$(unit)'." msgstr "" "Wymagane jest uwierzytelnienie, aby ponownie wczytać jednostkę „$(unit)”." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 msgid "Authentication is required to restart '$(unit)'." msgstr "" "Wymagane jest uwierzytelnienie, aby ponownie uruchomić jednostkę „$(unit)”." #: ../src/core/dbus-unit.c:535 msgid "Authentication is required to kill '$(unit)'." msgstr "" "Wymagane jest uwierzytelnienie, aby wymusić wyłączenie jednostki „$(unit)”." #: ../src/core/dbus-unit.c:565 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "" "Wymagane jest uwierzytelnienie, aby przywrócić stan „failed” (niepowodzenia) " "jednostki „$(unit)”." #: ../src/core/dbus-unit.c:597 msgid "Authentication is required to set properties on '$(unit)'." msgstr "" "Wymagane jest uwierzytelnienie, aby ustawić właściwości jednostki „$(unit)”." #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" #~ msgstr "" #~ "Naciśnięcie klawiszy Ctrl+C anuluje wszystkie trwające procesy " #~ "sprawdzania systemów plików" #~ msgid "Checking in progress on %d disk (%3.1f%% complete)" #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" #~ msgstr[0] "Trwa sprawdzanie %d dysku (ukończono %3.1f%%)" #~ msgstr[1] "Trwa sprawdzanie %d dysków (ukończono %3.1f%%)" #~ msgstr[2] "Trwa sprawdzanie %d dysków (ukończono %3.1f%%)" systemd-229/po/pt_BR.po000066400000000000000000000546021265713322000150540ustar00rootroot00000000000000# Brazilian Portuguese translation for systemd. # Copyright (C) 2015 systemd's COPYRIGHT HOLDER # This file is distributed under the same license as the systemd package. # Rafael Ferreira , 2014. # Enrico Nicoletto , 2014. # msgid "" msgstr "" "Project-Id-Version: systemd master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-22 16:37+0100\n" "PO-Revision-Date: 2015-01-10 12:23-0300\n" "Last-Translator: Rafael Ferreira \n" "Language-Team: Brazilian Portuguese \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Generator: Poedit 1.7.1\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Enviar frase secreta de volta ao sistema" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "" "É necessária autenticação para enviar a frase secreta informada de volta ao " "sistema." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 #, fuzzy msgid "Manage system services or other units" msgstr "Gerenciar unidades e serviços do sistema" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 #, fuzzy msgid "Authentication is required to manage system services or other units." msgstr "" "É necessária autenticação para gerenciar unidades e serviços do sistema." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Gerenciar arquivos de unidades e serviços do sistema" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "É necessária autenticação para gerenciar arquivos \"unit\" e \"service\" do " "sistema." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 #, fuzzy msgid "Set or unset system and service manager environment variables" msgstr "Acesso privilegiado ao gerenciador de serviço e de sistema" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 #, fuzzy msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "É necessária autenticação para gerenciar arquivos \"unit\" e \"service\" do " "sistema." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Recarregar o estado do sistema" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "É necessária autenticação para recarregar o estado do sistema." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Definir nome de máquina" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "É necessária autenticação para definir nome de máquina local." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Definir nome estático de máquina" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "É necessária autenticação para definir o nome de máquina local configurado " "estaticamente, assim como o nome apresentável de máquina." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Definir informações da máquina" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "É necessária autenticação para definir informações de máquina local." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "" #: ../src/import/org.freedesktop.import1.policy.in.h:2 #, fuzzy msgid "Authentication is required to import a VM or container image" msgstr "É necessária autenticação para se conectar a um contêiner local." #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "" #: ../src/import/org.freedesktop.import1.policy.in.h:4 #, fuzzy msgid "Authentication is required to export a VM or container image" msgstr "É necessária autenticação para se conectar a um contêiner local." #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "" #: ../src/import/org.freedesktop.import1.policy.in.h:6 #, fuzzy msgid "Authentication is required to download a VM or container image" msgstr "É necessária autenticação para se conectar a um contêiner local." #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Definir configurações regionais do sistema" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "" "É necessária autenticação para definir as configurações regionais do sistema." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Definir configurações de teclado do sistema" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "" "É necessária autenticação para definir as configurações de teclado do " "sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Permitir que aplicativos inibam o desligamento do sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "É necessária autenticação para que um aplicativo iniba o desligamento do " "sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Permitir que aplicativos atrasem o desligamento do sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "É necessária autenticação para que um aplicativo atrase o desligamento do " "sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Permitir que aplicativos inibam a suspensão do sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "É necessária autenticação para que um aplicativo iniba a suspensão do " "sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Permite que aplicativos atrasem a suspensão do sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "É necessária autenticação para que um aplicativo atrase a suspensão do " "sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "Permitir que aplicativos inibam a suspensão automática do sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "É necessária autenticação para que um aplicativo iniba a suspensão " "automática do sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "" "Permitir que aplicativos inibam o sistema de gerenciar o botão de energia" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "É necessária autenticação para que um aplicativo iniba a manipulação do " "sistema sobre a chave de ligar/desligar." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Permitir que aplicativos inibam o sistema de gerenciar o botão de suspensão" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "É necessária autenticação para que um aplicativo iniba a manipulação do " "sistema sobre a chave de suspensão." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Permitir que aplicativos inibam o sistema de gerenciar o botão de hibernação" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "É necessária autenticação para que um aplicativo iniba a manipulação do " "sistema sobre a chave de hibernar." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Permitir que aplicativos inibam o sistema de gerenciar a abertura/fechamento " "da tampa do dispositivo portátil" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "É necessária autenticação para que um aplicativo iniba a manipulação do " "sistema sobre o interruptor da tela." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "" "Permitir que programas sejam executados por usuários que não possuem sessão" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "É necessária autenticação para executar programas como usuário sem sessão " "aberta." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Permitir conectar dispositivos em estações" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "É necessária autenticação para conectar um dispositivo em uma estação." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Liberar dispositivo para conexões da estação" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "É necessária autenticação para redefinir a quantidade de dispositivos " "conectados na estação." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Desligar o sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "É necessária autenticação para desligar o sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Desligar o sistema enquanto outros usuários estão conectados" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "É necessária autenticação para desligar o sistema enquanto outros usuários " "estão conectados." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "Desligar o sistema enquanto um aplicativo solicitou inibição" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "É necessária autenticação para desligar o sistema enquanto um aplicativo " "solicitou inibição." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Reiniciar o sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "É necessária autenticação para reiniciar o sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Reiniciar o sistema enquanto outros usuários estiverem conectados" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "É necessária autenticação para reiniciar o sistema enquanto outros usuários " "estiverem conectados." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "Reiniciar o sistema enquanto um aplicativo solicitou inibição" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "É necessária autenticação para reiniciar o sistema enquanto um aplicativo " "solicitou inibição." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Suspender o sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "É necessária autenticação para suspender o sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "Suspender o sistema enquanto outros usuários estiverem conectados" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "É necessária autenticação para suspender o sistema enquanto outros usuários " "estiverem conectados." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "Suspender o sistema enquanto um aplicativo solicitou inibição" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "É necessária autenticação para suspender o sistema enquanto um aplicativo " "solicitou inibição." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Hibernar o sistema" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "É necessária autenticação para hibernar o sistema." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "Hibernar o sistema enquanto outros usuários estiverem conectados" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "É necessária autenticação para hibernar o sistema enquanto outros usuários " "estiverem conectados." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "Hibernar o sistema enquanto um aplicativo solicitou inibição" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "É necessária autenticação para hibernar o sistema enquanto um aplicativo " "solicitou inibição." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:50 #, fuzzy msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "É necessária autenticação para conectar um dispositivo em uma estação." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:52 #, fuzzy msgid "Authentication is required to lock or unlock active sessions." msgstr "É necessária autenticação para se conectar a um contêiner local." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:54 #, fuzzy msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "É necessária autenticação para definir nome de máquina local." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:56 #, fuzzy msgid "Authentication is required to set a wall message" msgstr "É necessária autenticação para definir nome de máquina local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Conectar a um contêiner local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 #, fuzzy msgid "Authentication is required to log into a local container." msgstr "É necessária autenticação para se conectar a um contêiner local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 #, fuzzy msgid "Log into the local host" msgstr "Conectar a um contêiner local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 #, fuzzy msgid "Authentication is required to log into the local host." msgstr "É necessária autenticação para se conectar a um contêiner local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 #, fuzzy msgid "Acquire a shell in a local container" msgstr "Conectar a um contêiner local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 #, fuzzy msgid "Authentication is required to acquire a shell in a local container." msgstr "É necessária autenticação para se conectar a um contêiner local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 #, fuzzy msgid "Authentication is required to acquire a shell on the local host." msgstr "É necessária autenticação para definir nome de máquina local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 #, fuzzy msgid "Acquire a pseudo TTY in a local container" msgstr "Conectar a um contêiner local" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 #, fuzzy msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "É necessária autenticação para se conectar a um contêiner local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 #, fuzzy msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "É necessária autenticação para definir nome de máquina local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 #, fuzzy msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "É necessária autenticação para definir informações de máquina local." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 #, fuzzy msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "É necessária autenticação para definir informações de máquina local." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Definir horário do sistema" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "É necessária autenticação para definir o horário do sistema." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Definir fuso horário do sistema" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "É necessária autenticação para definir o fuso horário do sistema." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Definir o relógio do sistema (RTC) para fuso horário local ou UTC" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "É necessária autenticação para controlar se o RTC deve, ou não, armazenar o " "horário local ou de UTC." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Ligar/desligar a sincronização do horário em rede" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "É necessária autenticação para controlar se deve ser habilitada, ou não, a " "sincronização de horário através de rede." #: ../src/core/dbus-unit.c:428 #, fuzzy msgid "Authentication is required to start '$(unit)'." msgstr "É necessária autenticação para definir o horário do sistema." #: ../src/core/dbus-unit.c:429 #, fuzzy msgid "Authentication is required to stop '$(unit)'." msgstr "É necessária autenticação para definir o horário do sistema." #: ../src/core/dbus-unit.c:430 #, fuzzy msgid "Authentication is required to reload '$(unit)'." msgstr "É necessária autenticação para recarregar o estado do sistema." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 #, fuzzy msgid "Authentication is required to restart '$(unit)'." msgstr "É necessária autenticação para definir o horário do sistema." #: ../src/core/dbus-unit.c:535 #, fuzzy msgid "Authentication is required to kill '$(unit)'." msgstr "É necessária autenticação para se conectar a um contêiner local." #: ../src/core/dbus-unit.c:565 #, fuzzy msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "É necessária autenticação para definir nome de máquina local." #: ../src/core/dbus-unit.c:597 #, fuzzy msgid "Authentication is required to set properties on '$(unit)'." msgstr "É necessária autenticação para definir o horário do sistema." systemd-229/po/ru.po000066400000000000000000000772371265713322000145050ustar00rootroot00000000000000# translation of ru.po to Rissian # Julia Dronova , 2013. # Sergey Ptashnick <0comffdiz@inbox.ru>, 2013-2016. # msgid "" msgstr "" "Project-Id-Version: systemd\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-22 16:37+0100\n" "PO-Revision-Date: 2016-02-02 20:22+0300\n" "Last-Translator: Sergey Ptashnick <0comffdiz@inbox.ru>\n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Отправить пароль системе" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "Чтобы отправить пароль системе, необходимо пройти аутентификацию." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Управление системными службами и юнитами" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Для управления системными службами и юнитами, необходимо пройти " "аутентификацию." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Управление файлами конфигурации системных служб и юнитов" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Для управления файлами конфигурации системных служб и юнитов, необходимо " "пройти аутентификацию." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "Настроить переменные окружения для системного менеджера" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Чтобы настроить переменные окружения для системного менеджера, необходимо " "пройти аутентификацию." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Перечитать конфигурацию systemd" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "" "Чтобы заставить systemd перечитать конфигурацию, необходимо пройти " "аутентификацию." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Настроить имя компьютера" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Чтобы настроить имя компьютера, необходимо пройти аутентификацию." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Настроить статическое имя компьютера" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Чтобы настроить статическое имя компьютера, а также его «красивое» имя, " "необходимо пройти аутентификацию." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Настроить информацию о компьютере" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "" "Чтобы настроить информацию о компьютере, необходимо пройти аутентификацию." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Импортировать образ виртуальной машины или контейнера" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "" "Чтобы импортировать образ виртуальной машины или контейнера, необходимо " "пройти аутентификацию." #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Экспортировать образ виртуальной машины или контейнера" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "" "Чтобы экспортировать образ виртуальной машины или контейнера, необходимо " "пройти аутентификацию." #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Загрузить образ виртуальной машины или контейнера" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "" "Чтобы загрузить образ виртуальной машины или контейнера, необходимо пройти " "аутентификацию." #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Настроить системную локаль" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "Чтобы настроить системную локаль, необходимо пройти аутентификацию." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Настроить параметры клавиатуры" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "" "Чтобы настроить параметры клавиатуры, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Разрешить приложениям устанавливать блокировку на выключение системы" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Чтобы разрешить приложениям устанавливать блокировку на выключение системы, " "необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Разрешить приложениям устанавливать задержку на выключение системы" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Чтобы разрешить приложениям устанавливать задержку на выключение системы, " "необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Разрешить приложениям устанавливать блокировку на засыпание системы" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Чтобы разрешить приложениям устанавливать блокировку на засыпание системы, " "необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Разрешить приложениям устанавливать задержку на засыпание системы" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Чтобы разрешить приложениям устанавливать задержку на засыпание системы, " "необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "" "Разрешить приложениям устанавливать блокировку на автоматический переход " "системы в ждущий режим" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Чтобы разрешить приложениям устанавливать блокировку на автоматический " "переход системы в ждущий режим, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "" "Разрешить приложениям устанавливать блокировку обработки нажатий на кнопку " "выключения" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Чтобы разрешить приложениям устанавливать блокировку обработки нажатий на " "кнопку выключения, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Разрешить приложениям устанавливать блокировку обработки нажатий на кнопку " "перехода в ждущий режим" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Чтобы разрешить приложениям устанавливать блокировку обработки нажатий на " "кнопку перехода в ждущий режим, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Разрешить приложениям устанавливать блокировку обработки нажатий на кнопку " "перехода в спящий режим" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Чтобы разрешить приложениям устанавливать блокировку обработки нажатий на " "кнопку перехода в спящий режим, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Разрешить приложениям устанавливать блокировку на обработку закрытия крышки " "ноутбука" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Чтобы разрешить приложениям устанавливать блокировку на обработку закрытия " "крышки ноутбука, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "" "Разрешить пользователям оставлять программы в фоновом режиме после " "завершения сеанса" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Чтобы разрешить пользователям оставлять программы в фоновом режиме после " "завершения сеанса, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Разрешить подключение устройств к рабочим местам" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "" "Чтобы разрешить подключение устройств к рабочим местам, необходимо пройти " "аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Сбросить привязки устройств к рабочим местам" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Чтобы сбросить привязки устройств к рабочим местам, необходимо пройти " "аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Выключить систему" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Чтобы выключить систему, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "" "Выключить систему, несмотря на то, что в ней работают другие пользователи" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Чтобы выключить систему, несмотря на то, что в ней работают другие " "пользователи, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "" "Выключить систему, несмотря на то, что приложение запросило блокировку " "выключения" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Чтобы выключить систему, несмотря на то, что приложение запросило блокировку " "выключения, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Перезагрузить систему" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Чтобы перезагрузить систему, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "" "Перезагрузить систему, несмотря на то, что в ней работают другие пользователи" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Чтобы перезагрузить систему, несмотря на то, что в ней работают другие " "пользователи, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "" "Перезагрузить систему, несмотря на то, что приложение запросило блокировку " "выключения" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Чтобы перезагрузить систему, несмотря на то, что приложение запросило " "блокировку выключения, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Перевести систему в ждущий режим" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "" "Чтобы перевести систему в ждущий режим, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "" "Перевести систему в ждущий режим, несмотря на то, что в ней работают другие " "пользователи" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Чтобы перевести систему в ждущий режим, несмотря на то, что в ней работают " "другие пользователи, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "" "Перевести систему в ждущий режим, несмотря на то, что приложение запросило " "блокировку" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Чтобы перевести систему в ждущий режим, несмотря на то, что приложение " "запросило блокировку, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Перевести систему в спящий режим" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "" "Чтобы перевести систему в спящий режим, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "" "Перевести систему в спящий режим, несмотря на то, что в ней работают другие " "пользователи" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Чтобы перевести систему в спящий режим, несмотря на то, что в ней работают " "другие пользователи, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "" "Перевести систему в спящий режим, несмотря на то, что приложение запросило " "блокировку" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Чтобы перевести систему в спящий режим, несмотря на то, что приложение " "запросило блокировку, необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Управление текущими сеансами, пользователями и рабочими местами" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Для управления текущими сеансами, пользователями и рабочими местами, " "необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Заблокировать или разблокировать текущие сеансы" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "" "Чтобы заблокировать или разблокировать текущие сеансы, необходимо пройти " "аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "Разрешить загрузку в режиме настройки прошивки материнской платы" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "" "Чтобы разрешить загрузку в режиме настройки прошивки материнской платы, " "необходимо пройти аутентификацию." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "Отправить сообщение на все терминалы" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "" "Чтобы отправить сообщение на все терминалы, необходимо пройти аутентификацию." #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Зайти в локальный контейнер" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "Чтобы зайти в локальный контейнер, необходимо пройти аутентификацию." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "Зайти на этот компьютер" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "Чтобы зайти на этот компьютер, необходимо пройти аутентификацию." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "Получить командную оболочку в локальном контейнере" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "" "Чтобы получить командную оболочку в локальном контейнере, необходимо пройти " "аутентификацию." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "Запустить командную оболочку на этом компьютере" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "" "Чтобы запустить командную оболочку на этом компьютере, необходимо пройти " "аутентификацию." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "Получить псевдо-терминал в локальном контейнере" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "" "Чтобы получить псевдо-терминал в локальном контейнере, необходимо пройти " "аутентификацию." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "Получить псевдо-терминал на этом компьютере" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "" "Чтобы получить псевдо-терминал на этом компьютере, необходимо пройти " "аутентификацию." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Управление виртуальными машинами и контейнерами" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Для управления виртуальными машинами и контейнерами, необходимо пройти " "аутентификацию." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Управление образами виртуальных машин и контейнеров" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Для управления образами виртуальных машин и контейнеров, необходимо пройти " "аутентификацию." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Настроить системное время" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Чтобы настроить системное время, необходимо пройти аутентификацию." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Настроить часовой пояс" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Чтобы настроить часовой пояс, необходимо пройти аутентификацию." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Установить аппаратные часы по местному времени или по Гринвичу" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Чтобы контролировать, установлены аппаратные часы по местному времени или по " "Гринвичу, необходимо пройти аутентификацию." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Включить или выключить синхронизацию времени по сети" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Чтобы включить или выключить синхронизацию времени по сети, необходимо " "пройти аутентификацию." #: ../src/core/dbus-unit.c:428 msgid "Authentication is required to start '$(unit)'." msgstr "Чтобы запустить «$(unit)», необходимо пройти аутентификацию." #: ../src/core/dbus-unit.c:429 msgid "Authentication is required to stop '$(unit)'." msgstr "Чтобы остановить «$(unit)», необходимо пройти аутентификацию." #: ../src/core/dbus-unit.c:430 msgid "Authentication is required to reload '$(unit)'." msgstr "" "Чтобы заставить «$(unit)» перечитать конфигурацию, необходимо пройти " "аутентификацию." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 msgid "Authentication is required to restart '$(unit)'." msgstr "Чтобы перезапустить «$(unit)», необходимо пройти аутентификацию." #: ../src/core/dbus-unit.c:535 msgid "Authentication is required to kill '$(unit)'." msgstr "Чтобы убить юнит «$(unit)», необходимо пройти аутентификацию." #: ../src/core/dbus-unit.c:565 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "" "Чтобы сбросить состояние «failed» у юнита «$(unit)», необходимо пройти " "аутентификацию." #: ../src/core/dbus-unit.c:597 msgid "Authentication is required to set properties on '$(unit)'." msgstr "Чтобы изменить параметры юнита «$(unit)», необходимо пройти " "аутентификацию." #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" #~ msgstr "" #~ "Чтобы прервать все запущенные проверки файловых систем, нажмите Ctrl+C" # There is no difference between "на 2 дисках" (plural==1) and "на 5 дисках" (plural==2) #~ msgid "Checking in progress on %d disk (%3.1f%% complete)" #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" #~ msgstr[0] "" #~ "Проверяется целостность файловой системы на %d диске (выполнено %3.1f%%)" #~ msgstr[1] "" #~ "Проверяется целостность файловых систем на %d дисках (выполнено %3.1f%%)" #~ msgstr[2] "" #~ "Проверяется целостность файловых систем на %d дисках (выполнено %3.1f%%)" systemd-229/po/sr.po000066400000000000000000000723521265713322000144740ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" "POT-Creation-Date: 2015-10-03 18:14+0200\n" "PO-Revision-Date: 2015-10-03 21:01+0200\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.8.4\n" "Last-Translator: Марко М. Костић (Marko M. Kostić) \n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "Language: sr\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Пошаљите фразу ка систему" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "" "Потребно је да се идентификујете да бисте послали фразу назад у систем." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Управљајте системским услугама и другим јединицама" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Потребно је да се идентификујете да бисте управљали системским услугама или " "другим јединицама." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Управљајте системском услугом или јединичним датотекама" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Потребно је да се идентификујете да бисте управљали системском услугом или " "јединичним датотекама." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "Мењајте променљиве окружења на систему и унутар управника услуга" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Потребно је да се идентификујете да бисте мењали променљиве окружења на " "систему и унутар управника услуга." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Поново учитајте стање систем-деа" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "" "Потребно је да се идентификујете да бисте поново учитали стање систем-деа." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Поставите назив машине" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Потребно је да се идентификујете да бисте поставили назив машине." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Поставите статички назив машине" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Потребно је да се идентификујете да бисте поставили статички назив машине и " "да бисте поставили леп назив машине." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Поставите податке о машини" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "" "Потребно је да се идентификујете да бисте поставили податке о локалној " "машини." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Увезите ВМ или слику контејнера" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "" "Потребно је да се идентификујете да бисте увезли виртуелну машину или слику " "контејнера" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Извезите ВМ или слику контејнера" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "" "Потребно је да се идентификујете да бисте извезли виртуелну машину или слику " "контејнера" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Преузмите ВМ или слику контејнера" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "" "Потребно је да се идентификујете да бисте преузели виртуелну машину или " "слику контејнера" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Поставите основни језик система" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "" "Потребно је да се идентификујете да бисте поставили основни језик система." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Поставите подешавање системске тастатуре" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "" "Потребно је да се идентификујете да бисте поставили подешавања системске " "тастатуре." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Дозволите програмима да спрече гашење система" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Потребно је да се идентификујете да бисте дозволили програму да спречи " "гашење система." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Дозволите програмима да одложе гашење система" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Потребно је да се идентификујете да бисте дозволили програму да одложи " "гашење система." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Дозволите програмима да спрече спавање система" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Потребно је да се идентификујете да бисте дозволили програму да спречи " "спавање система." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Дозволите програмима да одложе спавање система" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Потребно је да се идентификујете да бисте дозволили програму да одложи " "спавање система." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "Дозволите програмима да спрече самосталну обуставу система" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Потребно је да се идентификујете да бисте дозволили програму да спречи " "самосталну обуставу система." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "Дозволите програмима да спрече систему управљање дугметом за напајање" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Потребно је да се идентификујете да бисте дозволили програму да спречи " "систему управљање дугметом за напајање." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "Дозволите програмима да спрече систему управљање дугметом за обуставу" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Потребно је да се идентификујете да бисте дозволили програму да спречи " "систему управљање дугметом за обуставу." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "Дозволите програмима да спрече систему управљање дугметом за спавање" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Потребно је да се идентификујете да бисте дозволили програму да спречи " "систему управљање дугметом за спавање." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Дозволите програмима да спрече систему да уради било шта приликом заклапања " "екрана" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Потребно је да се идентификујете да бисте дозволили програму да спречи " "систему да уради било шта приликом заклапања екрана." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "Дозволите непријављеним корисницима да покрећу програме" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Потребно је да се идентификујете да бисте покретали програме као непријављен " "корисник." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Дозволите качење уређаја на седишта" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "Потребно је да се идентификујете да бисте закачили уређај на седиште." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Испери уређај да би уседиштио закачено" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Потребно је да се идентификујете да бисте поново подесили како се уређаји " "каче на седишта." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Искључите систем" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Потребно је да се идентификујете да бисте искључили систем." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Искључите систем док су други корисници пријављени" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Потребно је да се идентификујете да бисте искључили систем док су други " "корисници пријављени." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "Искључите систем иако је програм затражио да се спречи гашење" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Потребно је да се идентификујете да бисте искључили систем иако је програм " "затражио да се спречи гашење система." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Поново покрените систем" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Потребно је да се идентификујете да бисте поново покренули систем." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Поново покрените систем док су други корисници пријављени" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Потребно је да се идентификујете да бисте поново покренули систем док су " "други корисници пријављени." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "Поново покрените систем иако је програм затражио да се спречи гашење" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Потребно је да се идентификујете да бисте поново покренули систем иако је " "програм затражио да се спречи гашење система." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Обуставите систем" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Потребно је да се идентификујете да бисте обуставили систем." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "Обуставите систем док су други корисници пријављени" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Потребно је да се идентификујете да бисте обуставили систем док су други " "корисници пријављени." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "Обуставите систем иако је програм затражио да се спречи обустава" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Потребно је да се идентификујете да бисте обуставили систем иако је програм " "затражио да се спречи обустава система." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Успавајте систем" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "Потребно је да се идентификујете да бисте успавали систем." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "Успавајте систем док су други корисници пријављени" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Потребно је да се идентификујете да бисте успавали систем док су други " "корисници пријављени." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "Успавајте систем иако је програм затражио да се спречи спавање" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Потребно је да се идентификујете да бисте успавали систем иако је програм " "затражио да се спречи успављивање система." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Управљајте покренутим сесијама, корисницима и седиштима" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Потребно је да се идентификујете да бисте управљали покренутим сесијама, " "корисницима и седиштима." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Закључајте или откључајте покренуте сесије" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "" "Потребно је да се идентификујете да бисте закључавали или откључавали " "покренуте сесије." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "Напомените фирмверу да се подигне у режим подешавања интерфејса" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "" "Потребно је да се идентификујете да бисте напоменули фирмверу да се подигне " "у режиму подешавања интерфејса." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "Поставите зидну поруку" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "Потребно је да се идентификујете да бисте поставили зидну поруку" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Пријавите се у локални контејнер" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "" "Потребно је да се идентификујете да бисте се пријавили у локални контејнер." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "Пријавите се у локалног домаћина" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "" "Потребно је да се идентификујете да бисте се пријавили у локалног домаћина." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "Добијте приступ шкољци унутар локалног контејнера" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "" "Потребно је да се идентификујете да бисте добили приступ шкољци унутар " "локалног контејнера." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "Добијте приступ шкољци на локалном домаћину" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "" "Потребно је да се идентификујете да бисте добили приступ шкољци на локалном " "домаћину." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "Добијте приступ псеудо писаћој машини унутар локалног контејнера" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "" "Потребно је да се идентификујете да бисте добили приступ псеудо писаћој " "машини унутар локалног контејнера." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "Добијте приступ псеудо писаћој машини на локалном домаћину" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "" "Потребно је да се идентификујете да бисте добили приступ псеудо писаћој " "машини на локалном домаћину." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Управљајте локалним виртуелним машинама и контејнерима" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Потребно је да се идентификујете да бисте управљали локалним виртуелним " "машинама и контејнерима." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Управљајте локалним виртуелним машинама и сликама контејнера" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Потребно је да се идентификујете да бисте управљали локалним виртуелним " "машинама и сликама контејнера." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Поставите системско време" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Потребно је да се идентификујете да бисте поставили системско време." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Поставите системску временску зону" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "" "Потребно је да се идентификујете да бисте поставили системску временску зону." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Поставите RTC на локалну временску зону или UTC зону" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Потребно је да се идентификујете да бисте подесили да ли RTC чува локално " "или UTC време." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Укључите или искључите усклађивање времена са мреже" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Потребно је да се идентификујете да бисте подесили да ли се време усклађује " "са мреже." #: ../src/core/dbus-unit.c:428 msgid "Authentication is required to start '$(unit)'." msgstr "Потребно је да се идентификујете да бисте покренули „$(unit)“." #: ../src/core/dbus-unit.c:429 msgid "Authentication is required to stop '$(unit)'." msgstr "Потребно је да се идентификујете да бисте зауставили „$(unit)“." #: ../src/core/dbus-unit.c:430 msgid "Authentication is required to reload '$(unit)'." msgstr "Потребно је да се идентификујете да бисте поново учитали „$(unit)“." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 msgid "Authentication is required to restart '$(unit)'." msgstr "Потребно је да се идентификујете да бисте поново покренули „$(unit)“." #: ../src/core/dbus-unit.c:535 msgid "Authentication is required to kill '$(unit)'." msgstr "Потребно је да се идентификујете да бисте убили „$(unit)“." #: ../src/core/dbus-unit.c:565 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "" "Потребно је да се идентификујете да бисте поново поставили „неуспешно“ стање " "за „$(unit)“." #: ../src/core/dbus-unit.c:597 msgid "Authentication is required to set properties on '$(unit)'." msgstr "" "Потребно је да се идентификујете да бисте поставили својства за „$(unit)“." systemd-229/po/sv.po000066400000000000000000000544101265713322000144730ustar00rootroot00000000000000# Swedish translation for systemd. # Copyright © 2015 systemd's COPYRIGHT HOLDER # This file is distributed under the same license as the systemd package. # Josef Andersson , 2015. # Sebastian Rasmussen , 2015. msgid "" msgstr "" "Project-Id-Version: systemd master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-22 16:37+0100\n" "PO-Revision-Date: 2015-03-14 11:09+0100\n" "Last-Translator: Sebastian Rasmussen \n" "Language-Team: Swedish\n" "Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 1.6.10\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Skicka tillbaka lösenfras till system" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "" "Autentisering krävs för att skicka tillbaka den angivna lösenfrasen till " "systemet." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Hantera systemtjänster eller andra enheter" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Autentisering krävs för att hantera systemtjänster eller andra enheter." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Hantera systemtjänster eller enhetsfiler" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "Autentisering krävs för att hantera systemtjänster eller enhetsfiler." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "Ställ in eller ta bort miljövariabler för system- och servicehanterare" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Autentisering krävs för att ställa in eller ta bort miljövariabler för " "system- och servicehanterare." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Läs om tillståndet för systemd" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "Autentisering krävs för att läsa om tillståndet för systemd." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Ange värdnamn" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Autentisering krävs för att ange lokalt värdnamn." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Ange statiskt värdnamn" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Autentisering krävs för att ange det statiskt konfigurerade lokala " "värdnamnet såväl som det stiliga värdnamnet." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Ange datorinformation" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "Autentisering krävs för att ange lokal datorinformation." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Importera en VM eller behållaravbildning" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "Autentisering krävs för att importera en VM eller behållaravbildning" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Exportera en VM eller behållaravbildning" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "Autentisering krävs för att exportera en VM eller behållaravbildning" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Hämta ner en VM eller behållaravbildning" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "Autentisering krävs för att hämta ner en VM eller behållaravbildning" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Ange systemlokal" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "Autentisering krävs för att ange systemlokal." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Ange systeminställningar för tangentbord" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "Autentisering krävs för att ange systeminställningar för tangentbord." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Tillåt program att hindra systemavstängning" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Autentisering krävs för att tillåta ett program att hindra systemavstängning." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Tillåt program att fördröja systemavstängning" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Autentisering krävs för att tillåta ett program att fördröja " "systemavstängning." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Tillåt program att hindra system att försättas i viloläge" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Autentisering krävs för att tillåta ett program att hindra ett system att " "försättas i viloläge." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Tillåt program att fördröja att system försätts i viloläge" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Autentisering krävs för att tillåta ett program att fördröja ett system att " "försättas i viloläge." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "Tillåt program att hindra automatiskt systemvänteläge" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Autentisering krävs för att tillåta ett program att hindra automatiskt " "systemvänteläge." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "Tillåt program att hindra systemhantering av strömknappen" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Autentisering krävs för att tillåta ett program att hindra systemhantering " "av strömknappen." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "Tillåt program att hindra systemhantering av väntelägesknappen" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Autentisering krävs för att tillåta ett program att hindra systemhantering " "av väntelägesknappen." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "Tillåt program att hindra systemhantering av vilolägesknappen" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Autentisering krävs för att tillåta ett program att hindra systemhantering " "av vilolägesknappen." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "Tillåt program att hindra systemhantering av växel för datorhölje" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Autentisering krävs för att tillåta ett program att hindra systemhantering " "av brytaren för datorhöljet." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "Tillåt ej inloggade användare att köra program" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Autentisering krävs för att köra program som en icke inloggad användare." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Tillåt att binda enheter till platser" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "Autentisering krävs för att binda en enhet till en plats." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Töm bindningar för enhet-till-plats" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Autentisering krävs för att återställa hur enheter är bundna till platser." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Stäng av systemet" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Autentisering krävs för att stänga av systemet." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Stäng av systemet medan andra användare är inloggade" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Autentisering krävs för att stänga av systemet medan andra användare är " "inloggade." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "Stäng av systemet även då ett program hindrar det" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Autentisering krävs för att stänga av systemet även då ett program hindrar " "det." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Starta om systemet" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Autentisering krävs för att starta om systemet." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Starta om systemet medan andra användare är inloggade" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Autentisering krävs för att starta om systemet medan andra användare är " "inloggade." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "Starta om systemet även då ett program hindrar det" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Autentisering krävs för att starta om systemet även då ett program hindrar " "det." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Försätt system i vänteläge" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Autentisering krävs för att försätta system i vänteläge." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "Försätt systemet i vänteläge medan andra användare är inloggade" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Autentisering krävs för att försätta systemet i vänteläge medan andra " "användare är inloggade." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "Försätt systemet i vänteläge även då ett program hindrar det" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Autentisering krävs för att försätta ett program i vänteläge även då ett " "program hindrar det." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Försätt systemet i viloläge" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "Autentisering krävs för att försätta systemet i viloläge." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "Försätt systemet i viloläge medan andra användare är inloggade" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Autentisering krävs för att försätta systemet i viloläge medan andra " "användare är inloggade." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "Försätt systemet i viloläge även då ett program hindrar det" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Autentisering krävs för att försätta ett program i viloläge även då ett " "program hindrar det." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Hantera aktiva sessioner, användare och platser" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Autentisering krävs för att hantera aktiva sessioner, användare och platser." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Lås eller lås upp aktiva sessioner" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "Autentisering krävs för att låsa eller låsa upp aktiva sessioner." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:54 #, fuzzy msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "Autentisering krävs för att ange lokalt värdnamn." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:56 #, fuzzy msgid "Authentication is required to set a wall message" msgstr "Autentisering krävs för att ange lokalt värdnamn." #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Logga till en lokal behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "Autentisering krävs för att logga till en lokal behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 #, fuzzy msgid "Log into the local host" msgstr "Logga till en lokal behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 #, fuzzy msgid "Authentication is required to log into the local host." msgstr "Autentisering krävs för att logga till en lokal behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 #, fuzzy msgid "Acquire a shell in a local container" msgstr "Logga till en lokal behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 #, fuzzy msgid "Authentication is required to acquire a shell in a local container." msgstr "Autentisering krävs för att logga till en lokal behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 #, fuzzy msgid "Authentication is required to acquire a shell on the local host." msgstr "Autentisering krävs för att ange lokalt värdnamn." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 #, fuzzy msgid "Acquire a pseudo TTY in a local container" msgstr "Logga till en lokal behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 #, fuzzy msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "Autentisering krävs för att logga till en lokal behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 #, fuzzy msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "Autentisering krävs för att ange lokalt värdnamn." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Hantera lokala virtuella maskiner och behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Autentisering krävs för att hantera lokala virtuella maskiner och behållare." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Hantera lokala virtuella maskin- och behållaravbildningar" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Autentisering krävs för att hantera lokala virtuella maskin- och " "behållaravbildningar." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Ange systemtid" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Autentisering krävs för ange systemtiden." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Ange systemets tidszon" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Autentisering krävs för att ange systemets tidszon." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "" "Sätt realtidsklocka (RTC) till lokal tidszon eller koordinerad universell " "tid (UTC)" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Autentisering krävs för att kunna kontrollera huruvida realtidsklockan (RTC) " "lagrar den lokala eller koordinerade universella tiden (UTC)." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Växla synkronisering av nätverkstid på och av" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Autentisering krävs för att kontrollera huruvida synkronisering av " "nätverkstid ska vara aktiverat." #: ../src/core/dbus-unit.c:428 #, fuzzy msgid "Authentication is required to start '$(unit)'." msgstr "Autentisering krävs för ange systemtiden." #: ../src/core/dbus-unit.c:429 #, fuzzy msgid "Authentication is required to stop '$(unit)'." msgstr "Autentisering krävs för ange systemtiden." #: ../src/core/dbus-unit.c:430 #, fuzzy msgid "Authentication is required to reload '$(unit)'." msgstr "Autentisering krävs för att läsa om tillståndet för systemd." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 #, fuzzy msgid "Authentication is required to restart '$(unit)'." msgstr "Autentisering krävs för ange systemtiden." #: ../src/core/dbus-unit.c:535 #, fuzzy msgid "Authentication is required to kill '$(unit)'." msgstr "Autentisering krävs för att logga till en lokal behållare" #: ../src/core/dbus-unit.c:565 #, fuzzy msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "Autentisering krävs för att ange lokalt värdnamn." #: ../src/core/dbus-unit.c:597 #, fuzzy msgid "Authentication is required to set properties on '$(unit)'." msgstr "Autentisering krävs för ange systemtiden." #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" #~ msgstr "Tryck Ctrl+C för att avbryta alla pågående filsystemskontroller." #~ msgid "Checking in progress on %d disk (%3.1f%% complete)" #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" #~ msgstr[0] "Kontroll pågår på %d disk (%3.1f%% klart)" #~ msgstr[1] "Kontroll pågår på %d diskar (%3.1f%% klart)" systemd-229/po/tr.po000066400000000000000000000556531265713322000145020ustar00rootroot00000000000000# Turkish translation for systemd. # Copyright (C) 2014-2015 systemd's COPYRIGHT HOLDER # This file is distributed under the same license as the systemd package. # Necdet Yücel , 2014. # Gökhan Gurbetoğlu , 2015. # Muhammet Kara , 2015. # msgid "" msgstr "" "Project-Id-Version: systemd master\n" "Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" "POT-Creation-Date: 2015-09-18 00:07+0000\n" "PO-Revision-Date: 2015-09-19 08:31+0300\n" "Last-Translator: Muhammet Kara \n" "Language-Team: Türkçe \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: tr_TR\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Gtranslator 2.91.7\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Sisteme parolayı geri gönder" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "Sisteme parolayı geri göndermek kimlik doğrulaması gerektiriyor." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Sistem servislerini veya diğer birimlerini yönet" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Sistem servislerini veya diğer birimlerini yönetmek kimlik doğrulaması " "gerektiriyor." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Sistem servislerini veya birim dosyalarını yönet" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Sistem servislerini veya birim dosyalarını yönetmek kimlik doğrulaması " "gerektiriyor." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "Sistem ve servis yöneticisi ortam değişkenlerini ayarla ya da kaldır" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Sistem ve servis yöneticisi ortam değişkenlerini ayarlamak ya da kaldırmak " "kimlik doğrulaması gerektiriyor." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "systemd durumunu yeniden yükle" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "systemd durumunu yeniden yüklemek kimlik doğrulaması gerektiriyor." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Makine adını ayarla" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Yerel makine adını ayarlamak kimlik doğrulaması gerektiriyor." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Statik makine adı ayarla" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Statik olarak yapılandırılmış konak makine adını ve yerel makine adını " "ayarlamak kimlik doğrulaması gerektiriyor." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Makine bilgisini ayarla" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "Yerel makine bilgisini ayarlamak kimlik doğrulaması gerektiriyor." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Bir SM ya da kapsayıcı kalıbını içe aktar" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "" "Bir SM ya da kapsayıcı kalıbını içe aktarmak için kimlik doğrulaması " "gereklidir" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Bir SM ya da kapsayıcı kalıbını dışa aktar" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "" "Bir SM ya da kapsayıcı kalıbını dışa aktarmak için kimlik doğrulaması " "gereklidir" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Bir SM ya da kapsayıcı kalıbını indir" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "" "Bir SM ya da kapsayıcı kalıbını indirmek için kimlik doğrulaması gereklidir" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Sistem yerelini ayarla" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "Sistem yerelini ayarlamak kimlik doğrulaması gerektiriyor." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Sistem klavye ayarlarını ayarla" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "Sistem klavye ayarlarını ayarlamak kimlik doğrulaması gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Uygulamaların sistemin kapanmasına engel olmasına izin ver" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Bir uygulamanın sistemin kapanmasına engel olması için kimlik doğrulaması " "gereklidir." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Uygulamaların sistemin kapanmasını geciktirmelerine izin ver" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Bir uygulamanın sistemin kapanmasını geciktirmesi için kimlik doğrulaması " "gereklidir." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Uygulamaların sistemin beklemeye geçmesini engellemesine izin ver" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Bir uygulamanın sistemin uykuya geçmesine engel olması için kimlik " "doğrulaması gereklidir." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Uygulamaların sistemin beklemeye geçmesini ertelemesine izin ver" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Bir uygulamanın sistemin uykuya geçmesini geciktirmesi için kimlik " "doğrulaması gereklidir." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "" "Uygulamaların sistemin otomatik bekletmeye geçmesini engellemesine izin ver" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Bir uygulamanın sistemin otomatik olarak askıya alınmasına engel olması için " "kimlik doğrulaması gereklidir." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "Uygulamaların sistemin güç tuşunun kullanımını engellemesine izin ver" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Bir uygulamanın sistemin güç tuşunu idare etmesine engel olması için kimlik " "doğrulaması gereklidir." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Uygulamaların sistemin beklet tuşunun kullanımını engellemesine izin ver" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Bir uygulamanın sistemin askıya alma tuşunu idare etmesine engel olması için " "kimlik doğrulaması gereklidir." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Uygulamaların sistemin uykuya geçme tuşunun kullanımını engellemesine izin " "ver" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Bir uygulamanın sistemin hazırda bekletme tuşunu idare etmesine engel olması " "için kimlik doğrulaması gereklidir." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Uygulamaların sistemin kapak anahtarının kullanımını engellemesine izin ver" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Bir uygulamanın sistemin kapak anahtarını idare etmesine engel olması için " "kimlik doğrulaması gereklidir." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "Oturum açmamış kullanıcıların program çalıştırmasına izin ver" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Oturum açmamış bir kullanıcı olarak program çalıştırmak için kimlik " "doğrulaması gereklidir." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Aygıtların yuvaya takılmasına izin ver" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "" "Bir aygıtın yuvaya takılmasına izin vermek kimlik doğrulaması gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Aygıtın yuvaya eklenmesini sıfırla" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Aygıtların yuvalara nasıl takıldığını sıfırlamak kimlik doğrulama " "gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Sistemi kapat" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Sistemi kapatmak için kimlik doğrulaması gerekiyor." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Diğer kullanıcılar oturum açmışken sistemi kapat" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Diğer kullanıcılar oturum açmışken sistemi kapatmak kimlik doğrulaması " "gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "Bir uygulama engellenmesini isterken sistemi kapat" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Bir uygulama engellenmesini isterken sistemi kapatmak kimlik doğrulaması " "gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Sistemi yeniden başlat" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Sistemi yeniden başlatmak kimlik doğrulaması gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Diğer kullanıcılar oturum açmışken sistemi yeniden başlat" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Diğer kullanıcılar oturum açmışken sistemi yeniden başlatmak kimlik " "doğrulaması gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "Bir uygulama engellenmesini isterken sistemi yeniden başlat" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Bir uygulama engellenmesini isterken sistemi yeniden başlatmak kimlik " "doğrulaması gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Sistemi askıya al" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Sistemi askıya almak kimlik doğrulaması gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "Diğer kullanıcılar oturum açmışken sistemi askıya al" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Diğer kullanıcılar oturum açmışken sistemi askıya almak kimlik doğrulaması " "gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "Bir uygulama engellenmesini isterken sistemi askıya al" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Bir uygulama engellenmesini isterken sistemi askıya almak kimlik doğrulaması " "gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Sistemi hazırda beklet" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "Sistemi hazırda bekletmek kimlik doğrulaması gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "Diğer kullanıcılar oturum açmışken sistemi hazırda beklet" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Diğer kullanıcılar oturum açmışken sistemi hazırda bekletmek kimlik " "doğrulaması gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "Bir uygulama engellenmesini isterken sistemi hazırda beklet" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Bir uygulama engellenmesini isterken sistemi hazırda bekletmek kimlik " "doğrulaması gerektiriyor." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Aktif oturumları, kullanıcıları ve yuvaları yönet" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Aktif oturumları, kullanıcıları ve yuvaları yönetmek için kimlik doğrulaması " "gereklidir." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Aktif oturumları kilitle ya da kilidini aç" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "" "Aktif oturumları kilitlemek ve bunların kilidini açmak için kimlik " "doğrulaması gereklidir." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "" "Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesine izin ver" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "" "Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesi için kimlik " "doğrulaması gereklidir." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "Bir duvar mesajı ayarla" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "Duvar mesajı ayarlamak için kimlik doğrulaması gereklidir" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Yerel kapsayıcıya giriş yap" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "Yerel kapsayıcıda oturum açmak için kimlik doğrulaması gereklidir." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "Yerel (ana) makineye giriş yap" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "Yerel (ana) makinede oturum açmak için kimlik doğrulaması gereklidir." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "Yerel kapsayıcıda kabuk (shell) aç" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "" "Yerel kapsayıcıda kabuk (shell) açmak için kimlik doğrulaması gereklidir." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "Yerel (ana) makinede kabuk (shell) aç" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "" "Yerel (ana) makinede kabuk (shell) açmak için kimlik doğrulaması gereklidir." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "Yerel kapsayıcıda sözde (pseudo) TTY al" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "" "Yerel kapsayıcıda sözde (pseudo) TTY almak için kimlik doğrulaması " "gereklidir." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "Yerel (ana) makinede sözde (pseudo) TTY al" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "" "Yerel (ana) makinede sözde (pseudo) TTY almak için kimlik doğrulaması " "gereklidir." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Yerel sanal makineleri ve kapsayıcıları yönet" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Yerel sanal makineleri ve kapsayıcıları yönetmek için kimlik doğrulaması " "gereklidir." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Yerel sanal makine ve kapsayıcı kalıplarını yönet" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Yerel sanal makineler ve kapsayıcı kalıplarını yönetmek için kimlik " "doğrulaması gereklidir." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Sistem zamanını ayarla" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Sistem zamanını ayarlamak kimlik doğrulaması gerektiriyor." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Sistem zaman dilimini ayarla" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Sistem zaman dilimini ayarlamak kimlik doğrulaması gerektiriyor." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Gerçek zamanlı saat olarak yerel zaman dilimini veya UTC'yi ayarla" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "" "Gerçek zamanlı saat olarak yerel zaman dilimini veya UTC'yi ayarlamak kimlik " "doğrulaması gerektiriyor." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Ağ zaman eş zamanlamasını aç veya kapat" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Ağ zaman eş zamanlamasını kontrol etmek kimlik doğrulaması gerektiriyor." #: ../src/core/dbus-unit.c:428 msgid "Authentication is required to start '$(unit)'." msgstr "'$(unit)' başlatmak için kimlik doğrulaması gereklidir." #: ../src/core/dbus-unit.c:429 msgid "Authentication is required to stop '$(unit)'." msgstr "'$(unit)' durdurmak için kimlik doğrulaması gereklidir." #: ../src/core/dbus-unit.c:430 msgid "Authentication is required to reload '$(unit)'." msgstr "'$(unit)' yeniden yüklemek için kimlik doğrulaması gereklidir." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 msgid "Authentication is required to restart '$(unit)'." msgstr "'$(unit)' yeniden başlatmak için kimlik doğrulaması gereklidir." #: ../src/core/dbus-unit.c:535 msgid "Authentication is required to kill '$(unit)'." msgstr "'$(unit)' sonlandırmak için kimlik doğrulaması gereklidir." #: ../src/core/dbus-unit.c:565 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "" "'$(unit)'in \"failed\" (başarısız) durumunu sıfırlamak için kimlik " "doğrulaması gereklidir." #: ../src/core/dbus-unit.c:597 msgid "Authentication is required to set properties on '$(unit)'." msgstr "" "'$(unit)' üzerindeki özellikleri ayarlamak için kimlik doğrulaması " "gereklidir." systemd-229/po/uk.po000066400000000000000000000667451265713322000145000ustar00rootroot00000000000000# Ukrainian translation for systemd. # Copyright (C) 2014 systemd's COPYRIGHT HOLDER # This file is distributed under the same license as the systemd package. # Eugene Melnik , 2014. # Daniel Korostil , 2014, 2016. msgid "" msgstr "" "Project-Id-Version: systemd master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-01-11 09:21+0200\n" "PO-Revision-Date: 2016-01-11 11:00+0300\n" "Last-Translator: Daniel Korostil \n" "Language-Team: linux.org.ua\n" "Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "X-Generator: Virtaal 0.7.1\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "Надіслати пароль назад у систему" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "Засвідчення потрібно, щоб надіслати введений пароль назад у систему." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "Керувати системними службами й іншими одиницями" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Засвідчення потрібно, щоб керувати системними службами й іншими одиницями." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "Керувати системними службами й файлами одиниць" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "" "Засвідчення потрібно, щоб керувати системними службами й файлами одиниць." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "" "Встановити або забрати змінну середовища з керування службами і системою" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "" "Засвідчення потрібно, щоб установити або забрати змінні середовища з " "керування службами і системою." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "Перезапустити стан системи" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "Засвідчення потрібно, щоб перезапустити стан системи." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "Встановити назву вузла" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "Засвідчення потрібне, щоб встановити назву локального вузла." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "Встановити статичну назву вузла" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" "Засвідчення потрібне, щоб вказати статично налаштовану назву локального " "вузла, так само й форматовану." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "Встановити інформацію про машину" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "Засвідчення потрібно, щоб вказати локальну інформацію про машини." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "Імпортувати образ контейнера або віртуальної машини" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "" "Засвідчення потрібно, щоб імпортувати образ контейнера або віртуальної машини" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "Експортувати образ контейнера або віртуальної машини" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "" "Засвідчення потрібно, щоб експортувати образ контейнера або віртуальної " "машини" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "Звантажити образ контейнера або віртуальної машини" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "" "Засвідчення потрібно, щоб звантажити образ контейнера або віртуальної машини" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "Вказати системну локаль" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "Засвідчення потрібно, щоб встановити системну локаль." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "Вказати налаштування системної клавіатури" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "Засвідчення потрібно, щоб вказати налаштування системної клавіатури." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "Дозволити програмам перешкоджати вимкненню системи" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" "Засвідчення потрібно, щоб дозволити програмам перешкоджати вимкненню системи." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "Дозволити програмам затримувати вимкнення системи" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" "Засвідчення потрібно, щоб дозволити програмам затримувати вимкнення системи." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "Дозволити програмам перешкоджати засинанню системи" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" "Засвідчення потрібно, щоб дозволити програмам перешкоджати засинанню системи." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "Дозволити програмами затримувати засинання системи" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" "Засвідчення потрібно, щоб дозволити програмам затримувати засинання системи." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "Дозволити програмам перешкоджати автоматичному призупиненню системи" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "" "Засвідчення потрібно, щоб дозволити програмам перешкоджати автоматичному " "призупиненню системи." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "Дозволити програмам перешкоджати обробленню системою клавіші живлення" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "" "Засвідчення потрібно, щоб дозволити програмам перешкоджати обробленню " "системою клавіші живлення." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" "Дозволити програмам перешкоджати обробленню системою клавіші призупинення" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "" "Засвідчення потрібно, щоб дозволити програмам перешкоджати обробленню " "системою клавіші призупинення." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "" "Дозволити програмам перешкоджати обробленню системою клавіші присипання" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "" "Засвідчення потрібно, щоб дозволити програмам перешкоджати обробленню " "системою клавіші присипання." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "" "Дозволити програмам перешкоджати обробленню системою клавіші перемикання " "кришки" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "" "Засвідчення потрібно, щоб дозволити програмам перешкоджати обробленню " "системою клавіші перемикання кришки." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "Дозволити незареєстрованим користувачам запускати програми" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Засвідчення потрібно, щоб дозволити незареєстрованим користувачам запускати " "програми." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "Дозволити під'єднання пристроїв до місць" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "Засвідчення потрібно, щоб під'єднувати пристрої до місць." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "Очисний пристрій для під'єднань до місця" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "Засвідчення потрібно, щоб перезапустити спосіб під'єднання до місць." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "Вимкнути систему" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "Засвідчення потрібно, щоб вимкнути систему." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "Вимкнути систему, коли інші користувачі ще в ній" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" "Засвідчення потрібно, щоб вимкнути систему, коли інші користувачі в ній." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "Вимкнути систему, коли програми намагаються перешкодити цьому" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" "Засвідчення потрібно, щоб вимкнути систему, коли програми намагаються " "перешкодити цьому." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "Перезавантажити систему" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "Для перезавантаження системи необхідна ідентифікація." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "Перезавантажити, якщо інші користувачі в системі" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" "Засвідчення потрібно, щоб перезапустити систему, коли інші користувачі в ній." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "Перезапустити систему, коли програми намагаються перешкодити цьому" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" "Засвідчення потрібно, щоб перезапустити систему, коли програми намагаються " "перешкодити цьому." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "Призупинити систему" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "Засвідчення потрібно, щоб призупинити систему." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "Призупинити систему, коли інші користувачі в ній" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" "Засвідчення потрібно, щоб призупинити систему, коли інші користувачі в ній." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "Призупинити систему, коли програми намагаються перешкодити цьому" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" "Засвідчення потрібно, щоб призупинити систему, коли програми намагаються " "перешкодити цьому." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "Приспати систему" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "Засвідчення потрібно, щоб приспати систему." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "Приспати систему, коли інші користувачі в ній" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" "Засвідчення потрібно, щоб присипання систему, коли інші користувачі в ній." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "Приспати систему, коли програми намагаються перешкодити цьому" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "" "Засвідчення потрібно, щоб приспати систему, коли програми намагаються " "перешкодити цьому." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "Керувати сеансами, користувачами і робочими місцями" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Засвідчення потрібно, щоб керувати сеансами, користувачами і робочими " "місцями." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "Заблокувати або розблокувати сеанси" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "Засвідчення потрібно, щоб заблокувати або розблокувати сеанси." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "Дозволити мікрокоду визначати, чи завантажувати інтерфейс встановлення" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "" "Засвідчення потрібне, щоб дозволити мікрокоду визначати, чи завантажувати " "інтерфейс встановлення." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "Вказати повідомлення на стіні" #: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "Authentication is required to set a wall message" msgstr "Засвідчення потрібне, щоб вказати повідомлення на стіні" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "Увійти в локальний контейнер" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "Засвідчення потрібне, щоб увійти в локальний контейнер." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "Увійти в локальний вузол" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "Засвідчення потрібне, щоб увійти в локальний вузол." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "Перейняти оболонку в локальному контейнері" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "Засвідчення потрібне, щоб перейняти оболонку в локальному контейнері." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "Перейняти оболонку на локальному вузлі" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "Засвідчення потрібне, щоб перейняти оболонку на локальному вузлі." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "Перейняти псевдо TTY в локальному контейнері" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "Засвідчення потрібне, щоб перейняти псевдо TTY в локальному контейнері." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "Перейняти псевдо TTY на локальному вузлі" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "Засвідчення потрібне, щоб перейняти псевдо TTY на локальному вузлі." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "Керувати локальними віртуальними машинами і контейнерами" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Засвідчення потрібно, щоб керувати локальними віртуальними машинами і " "контейнерами." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "Керувати локальними образами віртуальних машин і контейнерів" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" "Засвідчення потрібно, щоб керувати локальними образами віртуальних машин і " "контейнерів." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "Вказати системний час" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "Засвідчення потрібно, щоб вказати системний час." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "Вказати системний часовий пояс" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "Засвідчення потрібно, щоб вказати системний часовий пояс." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "Вкажіть RTC для локального часового поясу або UTC" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "Засвідчення потрібно, щоб контролювати, чи RTC зберігає час, чи UTC." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "Увімкнути або вимкнути синхронізування через мережу" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "" "Засвідчення потрібно, щоб контролювати, чи синхронізування часу через мережу " "запущено." #: ../src/core/dbus-unit.c:449 msgid "Authentication is required to start '$(unit)'." msgstr "Засвідчення потрібно, щоб запустити «$(unit)»." #: ../src/core/dbus-unit.c:450 msgid "Authentication is required to stop '$(unit)'." msgstr "Засвідчення потрібно, щоб зупинити «$(unit)»." #: ../src/core/dbus-unit.c:451 msgid "Authentication is required to reload '$(unit)'." msgstr "Засвідчення потрібно, щоб перезавантажити «$(unit)»." #: ../src/core/dbus-unit.c:452 ../src/core/dbus-unit.c:453 msgid "Authentication is required to restart '$(unit)'." msgstr "Засвідчення потрібно, щоб перезапустити «$(unit)»." #: ../src/core/dbus-unit.c:556 msgid "Authentication is required to kill '$(unit)'." msgstr "Засвідчення потрібне, щоб вбити «$(unit)»." #: ../src/core/dbus-unit.c:586 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "Засвідчення потрібне, щоб скинути «пошкоджений» стан з «$(unit)»." #: ../src/core/dbus-unit.c:618 msgid "Authentication is required to set properties on '$(unit)'." msgstr "Засвідчення потрібно, щоб вказати властивості на «$(unit)»." systemd-229/po/zh_CN.po000066400000000000000000000501131265713322000150400ustar00rootroot00000000000000# Simplified Chinese translation for systemd. # Copyright (C) 2015 systemd's COPYRIGHT HOLDER # This file is distributed under the same license as the systemd package. # # Frank Hill , 2014. # Boyuan Yang <073plan@gmail.com>, 2015. msgid "" msgstr "" "Project-Id-Version: systemd\n" "Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" "POT-Creation-Date: 2015-10-27 02:24+0000\n" "PO-Revision-Date: 2015-10-28 15:00+0800\n" "Last-Translator: Boyuan Yang <073plan@gmail.com>\n" "Language-Team: Chinese \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 2.0\n" "Plural-Forms: nplurals=1; plural=0;\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "将密码发回系统" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "将输入的密码发回系统需要验证。" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "管理系统服务或其它单元" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "管理系统服务或其它单元需要验证。" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "管理系统服务或单元文件" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "管理系统服务或单元文件需要验证。" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "设置或清除系统及服务管理器的环境变量" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "设置或清除系统及服务管理器的环境变量需要验证。" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "重新载入 systemd 状态" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "重新载入 systemd 状态需要验证。" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "设置主机名" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "设置本地主机名需要验证。" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "设置静态主机名" # For pretty hostname, the zh_CN/zh_TW translation should be discussed again. # # There were some discussions, like https://lists.fedoraprojects.org/pipermail/trans-zh_cn/2012-December/001347.html #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 #, fuzzy msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "设置静态本地主机名或漂亮的主机名需要验证。" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "设置机器信息" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "设置本地机器信息需要验证。" #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "导入虚拟机或容器镜像" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "导入虚拟机或容器镜像需要验证" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "导出虚拟机或容器镜像" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "导出虚拟机或容器镜像需要验证" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "下载虚拟机或容器镜像" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "下载虚拟机或容器镜像需要验证。" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "设置系统区域和语言" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "设置系统区域和语言需要验证。" #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "设置系统键盘" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "设置系统键盘需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "允许应用程序阻止系统关机" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "要允许应用程序阻止系统关机需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "允许应用程序延迟系统关机" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "要允许应用程序延迟系统关机需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "允许应用程序阻止系统睡眠" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "要允许应用程序阻止系统睡眠需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "允许应用程序延迟系统睡眠" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "要允许应用程序延迟系统睡眠需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "允许应用程序阻止系统自动挂起" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "要允许应用程序阻止系统自动挂起需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "允许应用程序阻止系统响应电源键" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "要允许应用程序阻止系统响应电源键需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "允许应用程序阻止系统响应挂起键" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "要允许应用程序阻止系统响应挂起键需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "允许应用程序阻止系统响应挂起键" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "要允许应用程序阻止系统响应挂起键需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:17 #, fuzzy msgid "Allow applications to inhibit system handling of the lid switch" msgstr "允许应用程序阻止系统响应笔记本上盖开关事件" #: ../src/login/org.freedesktop.login1.policy.in.h:18 #, fuzzy msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "要允许应用程序阻止系统响应笔记本上盖开关事件需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "允许未登录用户运行程序" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "要允许未登录用户运行程序需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "允许将设备附加至会话座位" # Pay attention to the concept of "seat". # # To fully understand the meaning, please refer to session management in old ConsoleKit and new systemd-logind. #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "要允许将设备附加至某个会话座位需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "刷新设备至会话座位间的连接" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "重新设定设备的会话座位接入方式时需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "关闭系统" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "关闭系统需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "存在其他已登录用户时仍然关机" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "存在其他已登录用户时关闭系统需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "有其它应用程序阻止时仍然关机" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "要在其它应用程序阻止关机时关闭系统需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "重启系统" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "重启系统需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "存在其他已登录用户时仍然重启" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "存在其他已登录用户时重启系统需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "有其它应用程序阻止时仍然重启" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "要在其它应用程序阻止重启时重启系统需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "挂起系统" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "挂起系统需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "存在其他已登录用户时仍然挂起系统" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "存在其他已登录用户时挂起系统需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "有其它应用程序阻止时仍然挂起系统" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "要在其它应用程序阻止挂起时挂起系统需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "休眠" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "休眠需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "存在其他已登录用户时仍然休眠" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "存在其他已登录用户时进行休眠需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "有其它应用程序阻止时仍然休眠" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "要在其它应用程序阻止休眠时进行休眠需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "管理活动会话、用户与会话座位" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "要管理活动会话、用户与会话座位需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "活动会话锁定与解锁" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "要对活动会话进行锁定或解锁需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "允许向固件发出指示以启动至固件设置界面" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "要允许向固件发出启动时进入设置界面的指令需要验证。" #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:56 #, fuzzy msgid "Authentication is required to set a wall message" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "登入一个本地容器" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "要登入一个本地容器需要验证。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" msgstr "登入本地主机" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." msgstr "要登入本地主机需要验证。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" msgstr "在本地容器中获取一个 shell" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "要在本地容器中获取 shell 需要验证。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "在本地主机中获取一个 shell" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." msgstr "要在本地主机中获取 shell 需要验证。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" msgstr "在本地容器中获取一个假 TTY" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "要在本地容器中获取假 TTY 需要验证。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "在本地主机中获取一个假 TTY" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "要在本地主机中获取假 TTY 需要验证。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "管理本地虚拟机和容器" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "要管理本地虚拟机和容器需要验证。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "管理本地虚拟机和容器的镜像" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "要管理本地的虚拟机和容器镜像需要验证。" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "设置系统时间" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "设置系统时间需要验证。" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "设置系统时区" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "设置系统时区需要验证。" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "设置硬件时钟使用本地时间或 UTC" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "设置硬件时钟使用本地时间或 UTC 需要验证。" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "打开或关闭网络时间同步" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "设置是否启用网络时间同步需要验证。" #: ../src/core/dbus-unit.c:430 msgid "Authentication is required to start '$(unit)'." msgstr "启动“$(unit)”需要验证。" #: ../src/core/dbus-unit.c:431 msgid "Authentication is required to stop '$(unit)'." msgstr "停止“$(unit)”需要验证。" #: ../src/core/dbus-unit.c:432 msgid "Authentication is required to reload '$(unit)'." msgstr "重新载入“$(unit)”需要验证。" #: ../src/core/dbus-unit.c:433 ../src/core/dbus-unit.c:434 msgid "Authentication is required to restart '$(unit)'." msgstr "重新启动“$(unit)”需要验证。" #: ../src/core/dbus-unit.c:537 msgid "Authentication is required to kill '$(unit)'." msgstr "杀死“$(unit)”需要验证。" #: ../src/core/dbus-unit.c:567 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "重置“$(unit)”的失败(\"failed\")状态需要验证。" #: ../src/core/dbus-unit.c:599 msgid "Authentication is required to set properties on '$(unit)'." msgstr "设置“$(unit)”的属性需要验证。" systemd-229/po/zh_TW.po000066400000000000000000000471761265713322000151110ustar00rootroot00000000000000# Traditional Chinese translation for systemd. # Copyright (C) 2015 systemd's COPYRIGHT HOLDER # This file is distributed under the same license as the systemd package. # Jeff Huang , 2015. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-22 16:37+0100\n" "PO-Revision-Date: 2015-06-11 12:44+0800\n" "Last-Translator: Jeff Huang \n" "Language-Team: chinese-l10n \n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Lokalize 1.5\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" msgstr "傳回密碼片語到系統" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "傳回已輸入的密碼片語到系統需要驗證。" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" msgstr "管理系統服務或其他單位" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "管理系統服務或其他單位需要驗證。" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" msgstr "管理系統服務或單位檔案" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." msgstr "管理系統服務或單位檔案需要驗證。" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "設定或取消設定系統及服務管理員環境變量" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" "Authentication is required to set or unset system and service manager " "environment variables." msgstr "設定或取消設定系統及服務管理員環境變量時需要驗證" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" msgstr "重新載入 systemd 狀態" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." msgstr "重新載入 systemd 狀態需要驗證。" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" msgstr "設定主機名稱" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." msgstr "設定主機名稱需要驗證。" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" msgstr "設定靜態主機名稱" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "設定靜態設定的本機主機名稱時需要驗證,同時也需要漂亮的主機名稱" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" msgstr "設定機器資訊" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "設定機器資訊需要驗證" #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" msgstr "匯入虛擬機器或容器映像" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "匯入虛擬機器或容器映像需要驗證" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" msgstr "匯出虛擬機器或容器映像" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "匯出虛擬機器或容器映像需要驗證" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" msgstr "下載虛擬機器或容器映像" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "下載虛擬機器或容器映像需要驗證" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" msgstr "設定系統語系" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." msgstr "設定系統語系需要驗證。" #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" msgstr "設定系統鍵盤設定" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "設定系統鍵盤設定需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" msgstr "允許應用程式阻止系統關機" #: ../src/login/org.freedesktop.login1.policy.in.h:2 msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "要讓應用程式阻止系統關機需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" msgstr "允許應用程式延遲系統關機" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "要讓應用程式延遲系統關機需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" msgstr "允許應用程式阻止系統睡眠" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "要讓應用程式阻止系統睡眠需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" msgstr "允許應用程式延遲系統睡眠" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "要讓應用程式延遲系統睡眠需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" msgstr "允許應用程式阻止自動系統暫停" #: ../src/login/org.freedesktop.login1.policy.in.h:10 msgid "" "Authentication is required for an application to inhibit automatic system " "suspend." msgstr "要讓應用程式阻止自動系統暫停需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" msgstr "允許應用程式阻止系統處理電源鍵" #: ../src/login/org.freedesktop.login1.policy.in.h:12 msgid "" "Authentication is required for an application to inhibit system handling of " "the power key." msgstr "要讓應用程式阻止系統處理電源鍵需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "允許應用程式阻止系統處理暫停鍵" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" "Authentication is required for an application to inhibit system handling of " "the suspend key." msgstr "要讓應用程式阻止系統處理暫停鍵需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" msgstr "允許應用程式阻止系統處理冬眠鍵" #: ../src/login/org.freedesktop.login1.policy.in.h:16 msgid "" "Authentication is required for an application to inhibit system handling of " "the hibernate key." msgstr "要讓應用程式阻止系統處理冬眠鍵需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" msgstr "允許應用程式阻止系統處理上蓋開關" #: ../src/login/org.freedesktop.login1.policy.in.h:18 msgid "" "Authentication is required for an application to inhibit system handling of " "the lid switch." msgstr "要讓應用程式阻止系統處理上蓋開關需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in users to run programs" msgstr "允許未登入的使用者執行程式" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "要讓未登入的使用者執行程式需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow attaching devices to seats" msgstr "允許將設備連接到座位" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required for attaching a device to a seat." msgstr "將設備連接到座位需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Flush device to seat attachments" msgstr "暴露裝置以安裝附件" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "要重置裝置如何連接到座位需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Power off the system" msgstr "關閉系統電源" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "Authentication is required for powering off the system." msgstr "關閉系統電源需要驗證" #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system while other users are logged in" msgstr "在有其他使用者登入時關閉系統電源" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "在有其他使用者登入時關閉系統電源需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while an application asked to inhibit it" msgstr "當應用程式阻止系統電源關閉時將其關閉" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "當應用程式阻止系統電源關閉時將系統電源關閉需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Reboot the system" msgstr "重新啟動系統" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "Authentication is required for rebooting the system." msgstr "重新啟動系統需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system while other users are logged in" msgstr "在有其他使用者登入時重新啟動系統" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "在有其他使用者登入時重新啟動系統需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while an application asked to inhibit it" msgstr "當應用程式阻止重新啟動系統時將系統重新啟動" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "當應用程式阻止系統重新啟動時將系統重新啟動需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Suspend the system" msgstr "暫停系統" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "Authentication is required for suspending the system." msgstr "暫停系統需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system while other users are logged in" msgstr "在有其他使用者登入時暫停系統" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "在有其他使用者登入時暫停系統需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while an application asked to inhibit it" msgstr "當應用程式阻止暫停系統時將系統暫停" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "當應用程式阻止系統暫停時將系統暫停需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Hibernate the system" msgstr "系統冬眠" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "Authentication is required for hibernating the system." msgstr "系統冬眠需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system while other users are logged in" msgstr "在有其他使用者登入時冬眠系統" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "在有其他使用者登入時冬眠系統需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while an application asked to inhibit it" msgstr "當應用程式阻止冬眠系統時將系統冬眠" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." msgstr "當應用程式阻止系統冬眠時將系統冬眠需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Manage active sessions, users and seats" msgstr "管理活躍的工作階段、使用者與座位" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "管理活躍的工作階段、使用者與座位需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Lock or unlock active sessions" msgstr "鎖定或解鎖活躍的工作階段" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "Authentication is required to lock or unlock active sessions." msgstr "鎖定或解鎖活躍的工作階段需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "允許對韌體的指示以開始設定介面" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." msgstr "對韌體的指示以開始設定介面需要驗證。" #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:56 #, fuzzy msgid "Authentication is required to set a wall message" msgstr "設定主機名稱需要驗證。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" msgstr "登入到本機容器" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." msgstr "登入到本機容器需要驗證。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 #, fuzzy msgid "Log into the local host" msgstr "登入到本機容器" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 #, fuzzy msgid "Authentication is required to log into the local host." msgstr "登入到本機容器需要驗證。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 #, fuzzy msgid "Acquire a shell in a local container" msgstr "登入到本機容器" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 #, fuzzy msgid "Authentication is required to acquire a shell in a local container." msgstr "登入到本機容器需要驗證。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 #, fuzzy msgid "Authentication is required to acquire a shell on the local host." msgstr "設定主機名稱需要驗證。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 #, fuzzy msgid "Acquire a pseudo TTY in a local container" msgstr "登入到本機容器" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 #, fuzzy msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "登入到本機容器需要驗證。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 #, fuzzy msgid "Authentication is required to acquire a pseudo TTY on the local host." msgstr "設定主機名稱需要驗證。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" msgstr "管理本機虛擬機器及容器" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "管理本機虛擬機器及容器需要驗證。" #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" msgstr "管理本機虛擬機器及容器映像" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "管理本機虛擬機器及容器映像需要驗證。" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" msgstr "設定系統時間" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." msgstr "設定系統時間需要驗證。" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" msgstr "設定系統時區" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." msgstr "設定系統時區需要驗證。" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" msgstr "將 RTC 設定為本地時區或 UTC" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 msgid "" "Authentication is required to control whether the RTC stores the local or " "UTC time." msgstr "控制 RTC 儲存本地或 UTC 時間需要驗證。" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" msgstr "打開或關閉網路時間同步" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." msgstr "控制網路時間同步是否啟用需要驗證。" #: ../src/core/dbus-unit.c:428 #, fuzzy msgid "Authentication is required to start '$(unit)'." msgstr "設定系統時間需要驗證。" #: ../src/core/dbus-unit.c:429 #, fuzzy msgid "Authentication is required to stop '$(unit)'." msgstr "設定系統時間需要驗證。" #: ../src/core/dbus-unit.c:430 #, fuzzy msgid "Authentication is required to reload '$(unit)'." msgstr "重新載入 systemd 狀態需要驗證。" #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 #, fuzzy msgid "Authentication is required to restart '$(unit)'." msgstr "設定系統時間需要驗證。" #: ../src/core/dbus-unit.c:535 #, fuzzy msgid "Authentication is required to kill '$(unit)'." msgstr "登入到本機容器需要驗證。" #: ../src/core/dbus-unit.c:565 #, fuzzy msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "設定主機名稱需要驗證。" #: ../src/core/dbus-unit.c:597 #, fuzzy msgid "Authentication is required to set properties on '$(unit)'." msgstr "設定系統時間需要驗證。" systemd-229/rules/000077500000000000000000000000001265713322000142135ustar00rootroot00000000000000systemd-229/rules/.gitignore000066400000000000000000000000221265713322000161750ustar00rootroot00000000000000/99-systemd.rules systemd-229/rules/50-udev-default.rules000066400000000000000000000063561265713322000201100ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update # run a command on remove events ACTION=="remove", ENV{REMOVE_CMD}!="", RUN+="$env{REMOVE_CMD}" ACTION=="remove", GOTO="default_end" SUBSYSTEM=="virtio-ports", KERNEL=="vport*", ATTR{name}=="?*", SYMLINK+="virtio-ports/$attr{name}" # select "system RTC" or just use the first one SUBSYSTEM=="rtc", ATTR{hctosys}=="1", SYMLINK+="rtc" SUBSYSTEM=="rtc", KERNEL=="rtc0", SYMLINK+="rtc", OPTIONS+="link_priority=-100" SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb" SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id" ENV{MODALIAS}!="", IMPORT{builtin}="hwdb --subsystem=$env{SUBSYSTEM}" ACTION!="add", GOTO="default_end" SUBSYSTEM=="tty", KERNEL=="ptmx", GROUP="tty", MODE="0666" SUBSYSTEM=="tty", KERNEL=="tty", GROUP="tty", MODE="0666" SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", GROUP="tty", MODE="0620" SUBSYSTEM=="tty", KERNEL=="sclp_line[0-9]*", GROUP="tty", MODE="0620" SUBSYSTEM=="tty", KERNEL=="ttysclp[0-9]*", GROUP="tty", MODE="0620" SUBSYSTEM=="tty", KERNEL=="3270/tty[0-9]*", GROUP="tty", MODE="0620" SUBSYSTEM=="vc", KERNEL=="vcs*|vcsa*", GROUP="tty" KERNEL=="tty[A-Z]*[0-9]|pppox[0-9]*|ircomm[0-9]*|noz[0-9]*|rfcomm[0-9]*", GROUP="dialout" SUBSYSTEM=="mem", KERNEL=="mem|kmem|port", GROUP="kmem", MODE="0640" SUBSYSTEM=="input", GROUP="input" SUBSYSTEM=="input", KERNEL=="js[0-9]*", MODE="0664" SUBSYSTEM=="video4linux", GROUP="video" SUBSYSTEM=="graphics", GROUP="video" SUBSYSTEM=="drm", GROUP="video" SUBSYSTEM=="dvb", GROUP="video" SUBSYSTEM=="sound", GROUP="audio", \ OPTIONS+="static_node=snd/seq", OPTIONS+="static_node=snd/timer" SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0664" SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*", GROUP="video" SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", GROUP="video" SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", GROUP="video" SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", GROUP="video" KERNEL=="parport[0-9]*", GROUP="lp" SUBSYSTEM=="printer", KERNEL=="lp*", GROUP="lp" SUBSYSTEM=="ppdev", GROUP="lp" KERNEL=="lp[0-9]*", GROUP="lp" KERNEL=="irlpt[0-9]*", GROUP="lp" SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", GROUP="lp" SUBSYSTEM=="block", GROUP="disk" SUBSYSTEM=="block", KERNEL=="sr[0-9]*", GROUP="cdrom" SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", GROUP="cdrom" KERNEL=="sch[0-9]*", GROUP="cdrom" KERNEL=="pktcdvd[0-9]*", GROUP="cdrom" KERNEL=="pktcdvd", GROUP="cdrom" SUBSYSTEM=="scsi_generic|scsi_tape", SUBSYSTEMS=="scsi", ATTRS{type}=="1|8", GROUP="tape" SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="0", GROUP="disk" KERNEL=="qft[0-9]*|nqft[0-9]*|zqft[0-9]*|nzqft[0-9]*|rawqft[0-9]*|nrawqft[0-9]*", GROUP="disk" KERNEL=="loop-control", GROUP="disk", OPTIONS+="static_node=loop-control" KERNEL=="btrfs-control", GROUP="disk" KERNEL=="rawctl", GROUP="disk" SUBSYSTEM=="raw", KERNEL=="raw[0-9]*", GROUP="disk" SUBSYSTEM=="aoe", GROUP="disk", MODE="0220" SUBSYSTEM=="aoe", KERNEL=="err", MODE="0440" KERNEL=="rfkill", MODE="0664" KERNEL=="tun", MODE="0666", OPTIONS+="static_node=net/tun" KERNEL=="fuse", MODE="0666", OPTIONS+="static_node=fuse" LABEL="default_end" systemd-229/rules/60-block.rules000066400000000000000000000011361265713322000166050ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update # enable in-kernel media-presence polling ACTION=="add", SUBSYSTEM=="module", KERNEL=="block", ATTR{parameters/events_dfl_poll_msecs}=="0", \ ATTR{parameters/events_dfl_poll_msecs}="2000" # forward scsi device event to corresponding block device ACTION=="change", SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", TEST=="block", ATTR{block/*/uevent}="change" # watch metadata changes, caused by tools closing the device node which was opened for writing ACTION!="remove", SUBSYSTEM=="block", KERNEL=="loop*|nvme*|sd*|vd*|xvd*", OPTIONS+="watch" systemd-229/rules/60-cdrom_id.rules000066400000000000000000000016161265713322000172760ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update ACTION=="remove", GOTO="cdrom_end" SUBSYSTEM!="block", GOTO="cdrom_end" KERNEL!="sr[0-9]*|xvd*", GOTO="cdrom_end" ENV{DEVTYPE}!="disk", GOTO="cdrom_end" # unconditionally tag device as CDROM KERNEL=="sr[0-9]*", ENV{ID_CDROM}="1" # media eject button pressed ENV{DISK_EJECT_REQUEST}=="?*", RUN+="cdrom_id --eject-media $devnode", GOTO="cdrom_end" # import device and media properties and lock tray to # enable the receiving of media eject button events IMPORT{program}="cdrom_id --lock-media $devnode" # ejecting a CD does not remove the device node, so mark the systemd device # unit as inactive while there is no medium; this automatically cleans up of # stale mounts after ejecting ENV{DISK_MEDIA_CHANGE}=="?*", ENV{ID_CDROM_MEDIA}!="?*", ENV{SYSTEMD_READY}="0" KERNEL=="sr0", SYMLINK+="cdrom", OPTIONS+="link_priority=-100" LABEL="cdrom_end" systemd-229/rules/60-drm.rules000066400000000000000000000002311265713322000162700ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update ACTION!="remove", SUBSYSTEM=="drm", SUBSYSTEMS=="pci|usb|platform", IMPORT{builtin}="path_id" systemd-229/rules/60-evdev.rules000066400000000000000000000013421265713322000166230ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update ACTION=="remove", GOTO="evdev_end" KERNEL!="event*", GOTO="evdev_end" # skip later rules when we find something for this input device IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=evdev:", \ RUN{builtin}+="keyboard", GOTO="evdev_end" # AT keyboard matching by the machine's DMI data ENV{ID_INPUT_KEY}=="?*", DRIVERS=="atkbd", \ IMPORT{builtin}="hwdb 'evdev:atkbd:$attr{[dmi/id]modalias}'", \ RUN{builtin}+="keyboard", GOTO="evdev_end" # device matching the input device name and the machine's DMI data KERNELS=="input*", IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:$attr{[dmi/id]modalias}'", \ RUN{builtin}+="keyboard", GOTO="evdev_end" LABEL="evdev_end" systemd-229/rules/60-persistent-alsa.rules000066400000000000000000000011501265713322000206250ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update ACTION=="remove", GOTO="persistent_alsa_end" SUBSYSTEM!="sound", GOTO="persistent_alsa_end" KERNEL!="controlC[0-9]*", GOTO="persistent_alsa_end" SUBSYSTEMS=="usb", ENV{ID_MODEL}=="", IMPORT{builtin}="usb_id" ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="?*", SYMLINK+="snd/by-id/$env{ID_BUS}-$env{ID_SERIAL}-$env{ID_USB_INTERFACE_NUM}" ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="", SYMLINK+="snd/by-id/$env{ID_BUS}-$env{ID_SERIAL}" IMPORT{builtin}="path_id" ENV{ID_PATH}=="?*", SYMLINK+="snd/by-path/$env{ID_PATH}" LABEL="persistent_alsa_end" systemd-229/rules/60-persistent-input.rules000066400000000000000000000046401265713322000210530ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update ACTION=="remove", GOTO="persistent_input_end" SUBSYSTEM!="input", GOTO="persistent_input_end" SUBSYSTEMS=="bluetooth", GOTO="persistent_input_end" SUBSYSTEMS=="usb", ENV{ID_BUS}=="", IMPORT{builtin}="usb_id" # determine class name for persistent symlinks ENV{ID_INPUT_KEYBOARD}=="?*", ENV{.INPUT_CLASS}="kbd" ENV{ID_INPUT_MOUSE}=="?*", ENV{.INPUT_CLASS}="mouse" ENV{ID_INPUT_TOUCHPAD}=="?*", ENV{.INPUT_CLASS}="mouse" ENV{ID_INPUT_TABLET}=="?*", ENV{.INPUT_CLASS}="mouse" ENV{ID_INPUT_JOYSTICK}=="?*", ENV{.INPUT_CLASS}="joystick" DRIVERS=="pcspkr", ENV{.INPUT_CLASS}="spkr" ATTRS{name}=="*dvb*|*DVB*|* IR *", ENV{.INPUT_CLASS}="ir" # fill empty serial number ENV{.INPUT_CLASS}=="?*", ENV{ID_SERIAL}=="", ENV{ID_SERIAL}="noserial" # by-id links KERNEL=="mouse*|js*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="|00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-$env{.INPUT_CLASS}" KERNEL=="mouse*|js*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="?*", ATTRS{bInterfaceNumber}!="00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$attr{bInterfaceNumber}-$env{.INPUT_CLASS}" KERNEL=="event*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="|00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-event-$env{.INPUT_CLASS}" KERNEL=="event*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="?*", ATTRS{bInterfaceNumber}!="00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$attr{bInterfaceNumber}-event-$env{.INPUT_CLASS}" # allow empty class for USB devices, by appending the interface number SUBSYSTEMS=="usb", ENV{ID_BUS}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="", ATTRS{bInterfaceNumber}=="?*", \ SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-event-if$attr{bInterfaceNumber}" # by-path SUBSYSTEMS=="pci|usb|platform|acpi", IMPORT{builtin}="path_id" ENV{ID_PATH}=="?*", KERNEL=="mouse*|js*", ENV{.INPUT_CLASS}=="?*", SYMLINK+="input/by-path/$env{ID_PATH}-$env{.INPUT_CLASS}" ENV{ID_PATH}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="?*", SYMLINK+="input/by-path/$env{ID_PATH}-event-$env{.INPUT_CLASS}" # allow empty class for platform and usb devices; platform supports only a single interface that way SUBSYSTEMS=="usb|platform", ENV{ID_PATH}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="", \ SYMLINK+="input/by-path/$env{ID_PATH}-event" LABEL="persistent_input_end" systemd-229/rules/60-persistent-storage-tape.rules000066400000000000000000000026141265713322000223060ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update # persistent storage links: /dev/tape/{by-id,by-path} ACTION=="remove", GOTO="persistent_storage_tape_end" # type 8 devices are "Medium Changers" SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{program}="scsi_id --sg-version=3 --export --whitelisted -d $devnode", \ SYMLINK+="tape/by-id/scsi-$env{ID_SERIAL}" SUBSYSTEM!="scsi_tape", GOTO="persistent_storage_tape_end" KERNEL=="st*[0-9]|nst*[0-9]", ATTRS{ieee1394_id}=="?*", ENV{ID_SERIAL}="$attr{ieee1394_id}", ENV{ID_BUS}="ieee1394" KERNEL=="st*[0-9]|nst*[0-9]", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" KERNEL=="st*[0-9]|nst*[0-9]", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", KERNELS=="[0-9]*:*[0-9]", ENV{.BSG_DEV}="$root/bsg/$id" KERNEL=="st*[0-9]|nst*[0-9]", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --whitelisted --export --device=$env{.BSG_DEV}", ENV{ID_BUS}="scsi" KERNEL=="st*[0-9]", ENV{ID_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SERIAL}" KERNEL=="nst*[0-9]", ENV{ID_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SERIAL}-nst" # by-path (parent device path) KERNEL=="st*[0-9]|nst*[0-9]", IMPORT{builtin}="path_id" KERNEL=="st*[0-9]", ENV{ID_PATH}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH}" KERNEL=="nst*[0-9]", ENV{ID_PATH}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH}-nst" LABEL="persistent_storage_tape_end" systemd-229/rules/60-persistent-storage.rules000066400000000000000000000114471265713322000213630ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update # persistent storage links: /dev/disk/{by-id,by-uuid,by-label,by-path} # scheme based on "Linux persistent device names", 2004, Hannes Reinecke ACTION=="remove", GOTO="persistent_storage_end" SUBSYSTEM!="block", GOTO="persistent_storage_end" KERNEL!="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|sr*|vd*|xvd*|bcache*|cciss*|dasd*|ubd*", GOTO="persistent_storage_end" # ignore partitions that span the entire disk TEST=="whole_disk", GOTO="persistent_storage_end" # for partitions import parent information ENV{DEVTYPE}=="partition", IMPORT{parent}="ID_*" # virtio-blk KERNEL=="vd*[!0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}" KERNEL=="vd*[0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}-part%n" # ATA KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", IMPORT{program}="ata_id --export $devnode" # ATAPI devices (SPC-3 or later) KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{type}=="5", ATTRS{scsi_level}=="[6-9]*", IMPORT{program}="ata_id --export $devnode" # Run ata_id on non-removable USB Mass Storage (SATA/PATA disks in enclosures) KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", ATTR{removable}=="0", SUBSYSTEMS=="usb", IMPORT{program}="ata_id --export $devnode" # Fall back usb_id for USB devices KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" # SCSI devices KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $devnode", ENV{ID_BUS}="scsi" KERNEL=="cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $devnode", ENV{ID_BUS}="cciss" KERNEL=="sd*|sr*|cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}" KERNEL=="sd*|cciss*", ENV{DEVTYPE}=="partition", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}-part%n" # FireWire KERNEL=="sd*[!0-9]|sr*", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394-$attr{ieee1394_id}" KERNEL=="sd*[0-9]", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394-$attr{ieee1394_id}-part%n" # MMC KERNEL=="mmcblk[0-9]", SUBSYSTEMS=="mmc", ATTRS{name}=="?*", ATTRS{serial}=="?*", \ ENV{ID_NAME}="$attr{name}", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/mmc-$env{ID_NAME}_$env{ID_SERIAL}" KERNEL=="mmcblk[0-9]p[0-9]", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/mmc-$env{ID_NAME}_$env{ID_SERIAL}-part%n" # Memstick KERNEL=="msblk[0-9]|mspblk[0-9]", SUBSYSTEMS=="memstick", ATTRS{name}=="?*", ATTRS{serial}=="?*", \ ENV{ID_NAME}="$attr{name}", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/memstick-$env{ID_NAME}_$env{ID_SERIAL}" KERNEL=="msblk[0-9]p[0-9]|mspblk[0-9]p[0-9]", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/memstick-$env{ID_NAME}_$env{ID_SERIAL}-part%n" # by-path ENV{DEVTYPE}=="disk", DEVPATH!="*/virtual/*", IMPORT{builtin}="path_id" ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}" ENV{DEVTYPE}=="partition", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-part%n" # probe filesystem metadata of optical drives which have a media inserted KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="?*", \ IMPORT{builtin}="blkid --offset=$env{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}" # single-session CDs do not have ID_CDROM_MEDIA_SESSION_LAST_OFFSET KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="", \ IMPORT{builtin}="blkid --noraid" # probe filesystem metadata of disks KERNEL!="sr*", IMPORT{builtin}="blkid" # by-label/by-uuid links (filesystem metadata) ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}" ENV{ID_FS_USAGE}=="filesystem|other", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}" # by-id (World Wide Name) ENV{DEVTYPE}=="disk", ENV{ID_WWN_WITH_EXTENSION}=="?*", SYMLINK+="disk/by-id/wwn-$env{ID_WWN_WITH_EXTENSION}" ENV{DEVTYPE}=="partition", ENV{ID_WWN_WITH_EXTENSION}=="?*", SYMLINK+="disk/by-id/wwn-$env{ID_WWN_WITH_EXTENSION}-part%n" # by-partlabel/by-partuuid links (partition metadata) ENV{ID_PART_ENTRY_SCHEME}=="gpt", ENV{ID_PART_ENTRY_UUID}=="?*", SYMLINK+="disk/by-partuuid/$env{ID_PART_ENTRY_UUID}" ENV{ID_PART_ENTRY_SCHEME}=="gpt", ENV{ID_PART_ENTRY_NAME}=="?*", SYMLINK+="disk/by-partlabel/$env{ID_PART_ENTRY_NAME}" # add symlink to GPT root disk ENV{ID_PART_ENTRY_SCHEME}=="gpt", ENV{ID_PART_GPT_AUTO_ROOT}=="1", SYMLINK+="gpt-auto-root" LABEL="persistent_storage_end" systemd-229/rules/60-persistent-v4l.rules000066400000000000000000000014011265713322000204110ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update ACTION=="remove", GOTO="persistent_v4l_end" SUBSYSTEM!="video4linux", GOTO="persistent_v4l_end" ENV{MAJOR}=="", GOTO="persistent_v4l_end" IMPORT{program}="v4l_id $devnode" SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" KERNEL=="video*", ENV{ID_SERIAL}=="?*", SYMLINK+="v4l/by-id/$env{ID_BUS}-$env{ID_SERIAL}-video-index$attr{index}" # check for valid "index" number TEST!="index", GOTO="persistent_v4l_end" ATTR{index}!="?*", GOTO="persistent_v4l_end" IMPORT{builtin}="path_id" ENV{ID_PATH}=="?*", KERNEL=="video*|vbi*", SYMLINK+="v4l/by-path/$env{ID_PATH}-video-index$attr{index}" ENV{ID_PATH}=="?*", KERNEL=="audio*", SYMLINK+="v4l/by-path/$env{ID_PATH}-audio-index$attr{index}" LABEL="persistent_v4l_end" systemd-229/rules/60-serial.rules000066400000000000000000000022461265713322000167750ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update ACTION=="remove", GOTO="serial_end" SUBSYSTEM!="tty", GOTO="serial_end" SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}" SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci" SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb" # /dev/serial/by-path/, /dev/serial/by-id/ for USB devices KERNEL!="ttyUSB[0-9]*|ttyACM[0-9]*", GOTO="serial_end" SUBSYSTEMS=="usb-serial", ENV{.ID_PORT}="$attr{port_number}" IMPORT{builtin}="path_id" ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="", SYMLINK+="serial/by-path/$env{ID_PATH}" ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-path/$env{ID_PATH}-port$env{.ID_PORT}" IMPORT{builtin}="usb_id" ENV{ID_SERIAL}=="", GOTO="serial_end" SUBSYSTEMS=="usb", ENV{ID_USB_INTERFACE_NUM}="$attr{bInterfaceNumber}" ENV{ID_USB_INTERFACE_NUM}=="", GOTO="serial_end" ENV{.ID_PORT}=="", SYMLINK+="serial/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$env{ID_USB_INTERFACE_NUM}" ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$env{ID_USB_INTERFACE_NUM}-port$env{.ID_PORT}" LABEL="serial_end" systemd-229/rules/64-btrfs.rules000066400000000000000000000006421265713322000166400ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update SUBSYSTEM!="block", GOTO="btrfs_end" ACTION=="remove", GOTO="btrfs_end" ENV{ID_FS_TYPE}!="btrfs", GOTO="btrfs_end" # let the kernel know about this btrfs filesystem, and check if it is complete IMPORT{builtin}="btrfs ready $devnode" # mark the device as not ready to be used by the system ENV{ID_BTRFS_READY}=="0", ENV{SYSTEMD_READY}="0" LABEL="btrfs_end" systemd-229/rules/70-mouse.rules000066400000000000000000000013361265713322000166460ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update ACTION=="remove", GOTO="mouse_end" KERNEL!="event*", GOTO="mouse_end" ENV{ID_INPUT_MOUSE}=="", GOTO="mouse_end" # mouse::vp:name::* KERNELS=="input*", ENV{ID_BUS}=="usb", \ IMPORT{builtin}="hwdb 'mouse:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \ GOTO="mouse_end" KERNELS=="input*", ENV{ID_BUS}=="bluetooth", \ IMPORT{builtin}="hwdb 'mouse:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \ GOTO="mouse_end" DRIVERS=="psmouse", SUBSYSTEMS=="serio", \ IMPORT{builtin}="hwdb 'mouse:ps2::name:$attr{device/name}:'", \ GOTO="mouse_end" LABEL="mouse_end" systemd-229/rules/75-net-description.rules000066400000000000000000000007041265713322000206300ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update ACTION=="remove", GOTO="net_end" SUBSYSTEM!="net", GOTO="net_end" IMPORT{builtin}="net_id" SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb" SUBSYSTEMS=="usb", GOTO="net_end" SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}" SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci" LABEL="net_end" systemd-229/rules/75-probe_mtd.rules000066400000000000000000000002561265713322000174760ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update ACTION!="add", GOTO="mtd_probe_end" KERNEL=="mtd*ro", IMPORT{program}="mtd_probe $devnode" LABEL="mtd_probe_end" systemd-229/rules/78-sound-card.rules000066400000000000000000000106311265713322000175630ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update SUBSYSTEM!="sound", GOTO="sound_end" ACTION=="add|change", KERNEL=="controlC*", ATTR{../uevent}="change" ACTION!="change", GOTO="sound_end" # Ok, we probably need a little explanation here for what the two lines above # are good for. # # The story goes like this: when ALSA registers a new sound card it emits a # series of 'add' events to userspace, for the main card device and for all the # child device nodes that belong to it. udev relays those to applications, # however only maintains the order between father and child, but not between # the siblings. The control device node creation can be used as synchronization # point. All other devices that belong to a card are created in the kernel # before it. However unfortunately due to the fact that siblings are forwarded # out of order by udev this fact is lost to applications. # # OTOH before an application can open a device it needs to make sure that all # its device nodes are completely created and set up. # # As a workaround for this issue we have added the udev rule above which will # generate a 'change' event on the main card device from the 'add' event of the # card's control device. Due to the ordering semantics of udev this event will # only be relayed after all child devices have finished processing properly. # When an application needs to listen for appearing devices it can hence look # for 'change' events only, and ignore the actual 'add' events. # # When the application is initialized at the same time as a device is plugged # in it may need to figure out if the 'change' event has already been triggered # or not for a card. To find that out we store the flag environment variable # SOUND_INITIALIZED on the device which simply tells us if the card 'change' # event has already been processed. KERNEL!="card*", GOTO="sound_end" ENV{SOUND_INITIALIZED}="1" IMPORT{builtin}="hwdb" SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" SUBSYSTEMS=="usb", GOTO="skip_pci" SUBSYSTEMS=="firewire", ATTRS{guid}=="?*", \ ENV{ID_BUS}="firewire", ENV{ID_SERIAL}="$attr{guid}", ENV{ID_SERIAL_SHORT}="$attr{guid}", \ ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{model}", \ ENV{ID_VENDOR}="$attr{vendor_name}", ENV{ID_MODEL}="$attr{model_name}" SUBSYSTEMS=="firewire", GOTO="skip_pci" SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}" LABEL="skip_pci" # Define ID_ID if ID_BUS and ID_SERIAL are set. This will work for both # USB and firewire. ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="?*", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}-$env{ID_USB_INTERFACE_NUM}" ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}" IMPORT{builtin}="path_id" # The values used here for $SOUND_FORM_FACTOR and $SOUND_CLASS should be kept # in sync with those defined for PulseAudio's src/pulse/proplist.h # PA_PROP_DEVICE_FORM_FACTOR, PA_PROP_DEVICE_CLASS properties. # If the first PCM device of this card has the pcm class 'modem', then the card is a modem ATTR{pcmC%nD0p/pcm_class}=="modem", ENV{SOUND_CLASS}="modem", GOTO="sound_end" # Identify cards on the internal PCI bus as internal SUBSYSTEMS=="pci", DEVPATH=="*/0000:00:??.?/sound/*", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end" # Devices that also support Image/Video interfaces are most likely webcams SUBSYSTEMS=="usb", ENV{ID_USB_INTERFACES}=="*:0e????:*", ENV{SOUND_FORM_FACTOR}="webcam", GOTO="sound_end" # Matching on the model strings is a bit ugly, I admit ENV{ID_MODEL}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end" ENV{ID_MODEL_FROM_DATABASE}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end" ENV{ID_MODEL}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end" ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end" ENV{ID_MODEL}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end" ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end" ENV{ID_MODEL}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end" ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end" ENV{ID_MODEL}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end" ENV{ID_MODEL_FROM_DATABASE}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end" LABEL="sound_end" systemd-229/rules/80-drivers.rules000066400000000000000000000011521265713322000171710ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update ACTION=="remove", GOTO="drivers_end" ENV{MODALIAS}=="?*", RUN{builtin}+="kmod load $env{MODALIAS}" SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="SD", RUN{builtin}+="kmod load tifm_sd" SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="MS", RUN{builtin}+="kmod load tifm_ms" SUBSYSTEM=="memstick", RUN{builtin}+="kmod load ms_block mspro_block" SUBSYSTEM=="i2o", RUN{builtin}+="kmod load i2o_block" SUBSYSTEM=="module", KERNEL=="parport_pc", RUN{builtin}+="kmod load ppdev" KERNEL=="mtd*ro", ENV{MTD_FTL}=="smartmedia", RUN{builtin}+="kmod load sm_ftl" LABEL="drivers_end" systemd-229/rules/80-net-setup-link.rules000066400000000000000000000004441265713322000203750ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update SUBSYSTEM!="net", GOTO="net_setup_link_end" IMPORT{builtin}="path_id" ACTION!="add", GOTO="net_setup_link_end" IMPORT{builtin}="net_setup_link" NAME=="", ENV{ID_NET_NAME}!="", NAME="$env{ID_NET_NAME}" LABEL="net_setup_link_end" systemd-229/rules/99-systemd.rules.in000066400000000000000000000074171265713322000176340ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. ACTION=="remove", GOTO="systemd_end" SUBSYSTEM=="tty", KERNEL=="tty[a-zA-Z]*|hvc*|xvc*|hvsi*|ttysclp*|sclp_line*|3270/tty[0-9]*", TAG+="systemd" KERNEL=="vport*", TAG+="systemd" SUBSYSTEM=="block", TAG+="systemd" SUBSYSTEM=="block", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0" # Ignore encrypted devices with no identified superblock on it, since # we are probably still calling mke2fs or mkswap on it. SUBSYSTEM=="block", ENV{DM_UUID}=="CRYPT-*", ENV{ID_PART_TABLE_TYPE}=="", ENV{ID_FS_USAGE}=="", ENV{SYSTEMD_READY}="0" # Ignore raid devices that are not yet assembled and started SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", TEST!="md/array_state", ENV{SYSTEMD_READY}="0" SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", ATTR{md/array_state}=="|clear|inactive", ENV{SYSTEMD_READY}="0" # Ignore loop devices that don't have any file attached SUBSYSTEM=="block", KERNEL=="loop[0-9]*", ENV{DEVTYPE}=="disk", TEST!="loop/backing_file", ENV{SYSTEMD_READY}="0" # Ignore nbd devices in the "add" event, with "change" the nbd is ready ACTION=="add", SUBSYSTEM=="block", KERNEL=="nbd*", ENV{SYSTEMD_READY}="0" # We need a hardware independent way to identify network devices. We # use the /sys/subsystem/ path for this. Kernel "bus" and "class" names # should be treated as one namespace, like udev handles it. This is mostly # just an identification string for systemd, so whether the path actually is # accessible or not does not matter as long as it is unique and in the # filesystem namespace. # # http://cgit.freedesktop.org/systemd/systemd/tree/src/libudev/libudev-enumerate.c#n955 SUBSYSTEM=="net", KERNEL!="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/net/devices/$name" SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/bluetooth/devices/%k" SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_WANTS}+="bluetooth.target" ENV{ID_SMARTCARD_READER}=="?*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="smartcard.target" SUBSYSTEM=="sound", KERNEL=="card*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sound.target" SUBSYSTEM=="printer", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target" SUBSYSTEM=="usb", KERNEL=="lp*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target" SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target" # Apply sysctl variables to network devices (and only to those) as they appear. ACTION=="add", SUBSYSTEM=="net", KERNEL!="lo", RUN+="@rootlibexecdir@/systemd-sysctl --prefix=/net/ipv4/conf/$name --prefix=/net/ipv4/neigh/$name --prefix=/net/ipv6/conf/$name --prefix=/net/ipv6/neigh/$name" # Pull in backlight save/restore for all backlight devices and # keyboard backlights SUBSYSTEM=="backlight", TAG+="systemd", IMPORT{builtin}="path_id", ENV{SYSTEMD_WANTS}+="systemd-backlight@backlight:$name.service" SUBSYSTEM=="leds", KERNEL=="*kbd_backlight", TAG+="systemd", IMPORT{builtin}="path_id", ENV{SYSTEMD_WANTS}+="systemd-backlight@leds:$name.service" # Pull in rfkill save/restore for all rfkill devices SUBSYSTEM=="rfkill", IMPORT{builtin}="path_id" SUBSYSTEM=="misc", KERNEL=="rfkill", TAG+="systemd", ENV{SYSTEMD_WANTS}+="systemd-rfkill.socket" # Asynchronously mount file systems implemented by these modules as soon as they are loaded. SUBSYSTEM=="module", KERNEL=="fuse", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sys-fs-fuse-connections.mount" SUBSYSTEM=="module", KERNEL=="configfs", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sys-kernel-config.mount" LABEL="systemd_end" systemd-229/rules/Makefile000077700000000000000000000000001265713322000203102../src/Makefileustar00rootroot00000000000000systemd-229/shell-completion/000077500000000000000000000000001265713322000163375ustar00rootroot00000000000000systemd-229/shell-completion/Makefile000077700000000000000000000000001265713322000224342../src/Makefileustar00rootroot00000000000000systemd-229/shell-completion/bash/000077500000000000000000000000001265713322000172545ustar00rootroot00000000000000systemd-229/shell-completion/bash/.gitignore000066400000000000000000000000131265713322000212360ustar00rootroot00000000000000/systemctl systemd-229/shell-completion/bash/Makefile000077700000000000000000000000001265713322000225622../Makefileustar00rootroot00000000000000systemd-229/shell-completion/bash/bootctl000066400000000000000000000034541265713322000206530ustar00rootroot00000000000000# bootctl(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2014 Thomas H.P. Andersen # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } _bootctl() { local i verb comps local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local -A OPTS=( [STANDALONE]='-h --help --version' ) if [[ "$cur" = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 fi local -A VERBS=( [STANDALONE]='status' ) for ((i=0; i < COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then verb=${COMP_WORDS[i]} break fi done if [[ -z $verb ]]; then comps=${VERBS[*]} elif __contains_word "$verb" ${VERBS[STANDALONE]}; then comps='' fi COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _bootctl bootctl systemd-229/shell-completion/bash/busctl000066400000000000000000000170531265713322000205010ustar00rootroot00000000000000# busctl(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2013 Zbigniew Jędrzejewski-Szmek # Copyright 2014 Thomas H.P. Andersen # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } __get_machines() { local a b machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; }; } __get_busnames() { local mode=$1 local a b busctl $mode list --no-legend --no-pager | { while read a b; do echo " $a"; done; }; } __get_objects() { local mode=$1 local busname=$2 local a b busctl $mode tree --list --no-legend --no-pager $busname | { while read a b; do echo " $a"; done; }; } __get_interfaces() { local mode=$1 local busname=$2 local path=$3 local a b busctl $mode introspect --list --no-legend --no-pager $busname $path | { while read a b c; do [[ "$b" == "interface" ]] && echo " $a"; done; }; } __get_members() { local mode=$1 local busname=$2 local path=$3 local interface=$4 local type=$5 local a b busctl $mode introspect --list --no-legend --no-pager $busname $path $interface | sed -e 's/^\.//' | { while read a b c; do [[ "$b" == "$type" ]] && echo " $a"; done; }; } __get_signature() { local mode=$1 local busname=$2 local path=$3 local interface=$4 local member=$5 local a b busctl $mode introspect --list --no-legend --no-pager $busname $path $interface | sed -e 's/^\.//' | { while read a b c d; do [[ "$a" == "$member" ]] && echo " \"$c\""; done; }; } _busctl() { local i verb comps mode local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local -A OPTS=( [STANDALONE]='-h --help --version --no-pager --no-legend --system --user --show-machine --unique --acquired --activatable --list --quiet --verbose --expect-reply=no --auto-start=no --allow-interactive-authorization=yes --augment-creds=no' [ARG]='-H --host -M --machine --address --match --timeout' ) if __contains_word "--user" ${COMP_WORDS[*]}; then mode=--user else mode=--system fi if __contains_word "$prev" ${OPTS[ARG]}; then case $prev in --host|-H) comps=$(compgen -A hostname) ;; --machine|-M) comps=$( __get_machines ) esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ "$cur" = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 fi local -A VERBS=( [STANDALONE]='list help' [BUSNAME]='status monitor capture tree' [OBJECT]='introspect' [METHOD]='call' [PROPERTY_GET]='get-property' [PROPERTY_SET]='set-property' ) for ((i=0; i < COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then verb=${COMP_WORDS[i]} break fi done n=$(($COMP_CWORD - $i)) if [[ -z $verb ]]; then comps=${VERBS[*]} elif __contains_word "$verb" ${VERBS[STANDALONE]}; then comps='' elif __contains_word "$verb" ${VERBS[BUSNAME]}; then comps=$( __get_busnames $mode) elif __contains_word "$verb" ${VERBS[OBJECT]}; then if [[ $n -eq 1 ]] ; then comps=$( __get_busnames $mode) elif [[ $n -eq 2 ]] ; then comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) elif [[ $n -eq 3 ]] ; then comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) else comps='' fi elif __contains_word "$verb" ${VERBS[METHOD]}; then if [[ $n -eq 1 ]] ; then comps=$( __get_busnames $mode) elif [[ $n -eq 2 ]] ; then comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) elif [[ $n -eq 3 ]] ; then comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) elif [[ $n -eq 4 ]] ; then comps=$( __get_members $mode ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]} method) elif [[ $n -eq 5 ]] ; then comps=$( __get_signature $mode ${COMP_WORDS[COMP_CWORD-4]} ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) else comps='' fi elif __contains_word "$verb" ${VERBS[PROPERTY_GET]}; then if [[ $n -eq 1 ]] ; then comps=$( __get_busnames $mode) elif [[ $n -eq 2 ]] ; then comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) elif [[ $n -eq 3 ]] ; then comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) elif [[ $n -eq 4 ]] ; then comps=$( __get_members $mode ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]} property) else comps='' fi elif __contains_word "$verb" ${VERBS[PROPERTY_SET]}; then if [[ $n -eq 1 ]] ; then comps=$( __get_busnames $mode) elif [[ $n -eq 2 ]] ; then comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) elif [[ $n -eq 3 ]] ; then comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) elif [[ $n -eq 4 ]] ; then comps=$( __get_members $mode ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]} property) elif [[ $n -eq 5 ]] ; then comps=$( __get_signature $mode ${COMP_WORDS[COMP_CWORD-4]} ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) else comps='' fi fi COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _busctl busctl systemd-229/shell-completion/bash/coredumpctl000066400000000000000000000065331265713322000215270ustar00rootroot00000000000000# coredumpctl(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2010 Ran Benita # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } __journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC} ERRNO SYSLOG_{FACILITY,IDENTIFIER,PID} COREDUMP_EXE _{P,U,G}ID _COMM _EXE _CMDLINE _AUDIT_{SESSION,LOGINUID} _SYSTEMD_{CGROUP,SESSION,UNIT,OWNER_UID} _SELINUX_CONTEXT _SOURCE_REALTIME_TIMESTAMP _{BOOT,MACHINE}_ID _HOSTNAME _TRANSPORT _KERNEL_{DEVICE,SUBSYSTEM} _UDEV_{SYSNAME,DEVNODE,DEVLINK} __CURSOR __{REALTIME,MONOTONIC}_TIMESTAMP) _coredumpctl() { local i verb comps local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local OPTS='-h --help --version --no-pager --no-legend -o --output -F --field -1' local -A VERBS=( [LIST]='list' [DUMP]='dump gdb' ) if __contains_word "$prev" '--output -o'; then comps=$( compgen -A file -- "$cur" ) compopt -o filenames elif __contains_word "$prev" '--FIELD -F'; then comps=$( compgen -W '${__journal_fields[*]}' -- "$cur" ) elif [[ $cur = -* ]]; then comps=${OPTS} elif __contains_word "$prev" ${VERBS[*]} && ! __contains_word ${COMP_WORDS[COMP_CWORD-2]} '--output -o -F --field'; then compopt -o nospace COMPREPLY=( $(compgen -W '${__journal_fields[*]}' -S= -- "$cur") ) return 0 elif [[ $cur = *=* ]]; then mapfile -t field_vals < <(coredumpctl -F "${prev%=}" 2>/dev/null) COMPREPLY=( $(compgen -W '${field_vals[*]}' -- "${cur#=}") ) return 0 elif [[ $prev = '=' ]]; then mapfile -t field_vals < <(coredumpctl -F "${COMP_WORDS[COMP_CWORD-2]}" 2>/dev/null) comps=${field_vals[*]} else for ((i=0; i <= COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then verb=${COMP_WORDS[i]} break fi done if [[ -z $verb ]]; then comps=${VERBS[*]} elif __contains_word "$verb" ${VERBS[LIST]} ${VERBS[DUMP]}; then comps='' fi fi COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _coredumpctl coredumpctl systemd-229/shell-completion/bash/hostnamectl000066400000000000000000000042621265713322000215240ustar00rootroot00000000000000# hostnamectl(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2010 Ran Benita # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } _hostnamectl() { local i verb comps local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local OPTS='-h --help --version --transient --static --pretty --no-ask-password -H --host --machine' if [[ $cur = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 fi local -A VERBS=( [STANDALONE]='status' [ICONS]='set-icon-name' [NAME]='set-hostname set-deployment set-location' [CHASSIS]='set-chassis' ) for ((i=0; i < COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then verb=${COMP_WORDS[i]} break fi done if [[ -z $verb ]]; then comps=${VERBS[*]} elif __contains_word "$verb" ${VERBS[CHASSIS]}; then comps='desktop laptop server tablet handset watch embedded vm container' elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[ICONS]} ${VERBS[NAME]}; then comps='' fi COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _hostnamectl hostnamectl systemd-229/shell-completion/bash/journalctl000066400000000000000000000137521265713322000213640ustar00rootroot00000000000000# journalctl(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2010 Ran Benita # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } __get_machines() { local a b (machinectl list-images --no-legend --no-pager; machinectl list --no-legend --no-pager; echo ".host") | \ { while read a b; do echo " $a"; done; } | sort -u; } __journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC} ERRNO SYSLOG_{FACILITY,IDENTIFIER,PID} COREDUMP_EXE _{P,U,G}ID _COMM _EXE _CMDLINE _CAP_EFFECTIVE _AUDIT_{SESSION,LOGINUID} _SYSTEMD_{CGROUP,SESSION,{,USER_}UNIT,OWNER_UID,SLICE} _SELINUX_CONTEXT _SOURCE_REALTIME_TIMESTAMP _{BOOT,MACHINE}_ID _HOSTNAME _TRANSPORT _KERNEL_{DEVICE,SUBSYSTEM} _UDEV_{SYSNAME,DEVNODE,DEVLINK} __CURSOR __{REALTIME,MONOTONIC}_TIMESTAMP) __syslog_priorities=(emerg alert crit err warning notice info debug) _journalctl() { local field_vals= cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local -A OPTS=( [STANDALONE]='-a --all --full --system --user --disk-usage -f --follow --header -h --help -l --local --new-id128 -m --merge --no-pager --no-tail -q --quiet --setup-keys --this-boot --verify --version --list-catalog --update-catalog --list-boots --show-cursor --dmesg -k --pager-end -e -r --reverse --utc -x --catalog --no-full --force --dump-catalog --flush --rotate --sync' [ARG]='-b --boot --this-boot -D --directory --file -F --field -M --machine -o --output -u --unit --user-unit -p --priority --vacuum-size --vacuum-time' [ARGUNKNOWN]='-c --cursor --interval -n --lines -S --since -U --until --after-cursor --verify-key -t --identifier --root' ) if __contains_word "$prev" ${OPTS[ARG]} ${OPTS[ARGUNKNOWN]}; then case $prev in --boot|--this-boot|-b) comps=$(journalctl -F '_BOOT_ID' 2>/dev/null) ;; --directory|-D) comps=$(compgen -d -- "$cur") compopt -o filenames ;; --file) comps=$(compgen -f -- "$cur") compopt -o filenames ;; --output|-o) comps='short short-iso short-precise short-monotonic verbose export json json-pretty json-sse cat' ;; --field|-F) comps=${__journal_fields[*]} ;; --machine|-M) comps=$( __get_machines ) ;; --priority|-p) comps=${__syslog_priorities[*]} ;; --unit|-u) comps=$(journalctl -F '_SYSTEMD_UNIT' 2>/dev/null) ;; --user-unit) comps=$(journalctl -F '_SYSTEMD_USER_UNIT' 2>/dev/null) ;; *) return 0 ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ $cur = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 elif [[ $cur = *=* ]]; then mapfile -t field_vals < <(journalctl -F "${prev%=}" 2>/dev/null) COMPREPLY=( $(compgen -W '${field_vals[*]}' -- "${cur#=}") ) elif [[ $cur = /dev* ]]; then compopt -o filenames COMPREPLY=( $(compgen -f -- "${cur}") ) elif [[ $cur = /* ]]; then # Append /dev/ to the list of completions, so that # after typing / the user sees /dev/ as one # of the alternatives. Later on the rule above will # take care of showing device files in /dev/. mapfile -t field_vals < <(journalctl -F "_EXE" 2>/dev/null; echo '/dev/') COMPREPLY=( $(compgen -W '${field_vals[*]}' -- "${cur}") ) if [[ "${COMPREPLY[@]}" = '/dev/' ]]; then compopt -o filenames COMPREPLY=( $(compgen -f -- "${cur}") ) fi elif [[ $prev = '=' ]]; then mapfile -t field_vals < <(journalctl -F "${COMP_WORDS[COMP_CWORD-2]}" 2>/dev/null) COMPREPLY=( $(compgen -W '${field_vals[*]}' -- "$cur") ) else compopt -o nospace COMPREPLY=( $(compgen -W '${__journal_fields[*]}' -S= -- "$cur") ) fi } complete -F _journalctl journalctl systemd-229/shell-completion/bash/kernel-install000066400000000000000000000034001265713322000221200ustar00rootroot00000000000000# kernel-install(8) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2013 Kay Sievers # Copyright 2013 Harald Hoyer # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . _kernel_install() { local comps local MACHINE_ID local cur=${COMP_WORDS[COMP_CWORD]} case $COMP_CWORD in 1) comps="add remove" ;; 2) comps=$(cd /lib/modules; echo [0-9]*) if [[ ${COMP_WORDS[1]} == "remove" ]] && [[ -f /etc/machine-id ]]; then read MACHINE_ID < /etc/machine-id if [[ $MACHINE_ID ]] && ( [[ -d /boot/$MACHINE_ID ]] || [[ -L /boot/$MACHINE_ID ]] ); then comps=$(cd "/boot/$MACHINE_ID"; echo [0-9]*) fi fi ;; 3) [[ "$cur" ]] || cur=/boot/vmlinuz-${COMP_WORDS[2]} comps=$(compgen -f -- "$cur") compopt -o filenames ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _kernel_install kernel-install systemd-229/shell-completion/bash/localectl000066400000000000000000000065541265713322000211530ustar00rootroot00000000000000# localectl(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2010 Ran Benita # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } __locale_fields=( LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME \ LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER \ LC_NAME LC_ADDRESS LC_TELEPHONE \ LC_MEASUREMENT LC_IDENTIFICATION ) # LC_ALL is omitted on purpose _localectl() { local i verb comps locale_vals local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local OPTS='-h --help --version --no-convert --no-pager --no-ask-password -H --host --machine' if __contains_word "$prev" $OPTS; then case $prev in --host|-H) comps='' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ $cur = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 fi local -A VERBS=( [STANDALONE]='status list-locales list-keymaps' [LOCALES]='set-locale' [KEYMAPS]='set-keymap' [X11]='set-x11-keymap' ) for ((i=0; i < COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then verb=${COMP_WORDS[i]} break fi done if [[ -z $verb ]]; then comps=${VERBS[*]} elif __contains_word "$verb" ${VERBS[LOCALES]}; then if [[ $cur = *=* ]]; then mapfile -t locale_vals < <(command localectl list-locales 2>/dev/null) COMPREPLY=( $(compgen -W '${locale_vals[*]}' -- "${cur#=}") ) elif [[ $prev = "=" ]]; then mapfile -t locale_vals < <(command localectl list-locales 2>/dev/null) COMPREPLY=( $(compgen -W '${locale_vals[*]}' -- "$cur") ) else compopt -o nospace COMPREPLY=( $(compgen -W '${__locale_fields[*]}' -S= -- "$cur") ) fi return 0 elif __contains_word "$verb" ${VERBS[KEYMAPS]}; then comps=$(command localectl list-keymaps) elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[X11]}; then comps='' fi COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _localectl localectl systemd-229/shell-completion/bash/loginctl000066400000000000000000000100641265713322000210130ustar00rootroot00000000000000# loginctl(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2010 Ran Benita # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } __get_all_sessions () { loginctl --no-legend list-sessions | { while read -r a b; do printf "%s\n" "$a"; done; } ; } __get_all_users () { loginctl --no-legend list-users | { while read -r a b; do printf "%s\n" "$b"; done; } ; } __get_all_seats () { loginctl --no-legend list-seats | { while read -r a b; do printf "%s\n" "$a"; done; } ; } _loginctl () { local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local i verb comps local -A OPTS=( [STANDALONE]='--all -a --help -h --no-pager --privileged -P --version --no-legend --no-ask-password -l --full' [ARG]='--host -H --kill-who --property -p --signal -s --machine' ) if __contains_word "$prev" ${OPTS[ARG]}; then case $prev in --signal|-s) _signals return ;; --kill-who) comps='all leader' ;; --host|-H) comps=$(compgen -A hostname) ;; --property|-p) comps='' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ "$cur" = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 fi local -A VERBS=( [SESSIONS]='session-status show-session activate lock-session unlock-session terminate-session kill-session' [USERS]='user-status show-user enable-linger disable-linger terminate-user kill-user' [SEATS]='seat-status show-seat terminate-seat' [STANDALONE]='list-sessions list-users list-seats flush-devices' [ATTACH]='attach' ) for ((i=0; i < COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then verb=${COMP_WORDS[i]} break fi done if [[ -z $verb ]]; then comps="${VERBS[*]}" elif __contains_word "$verb" ${VERBS[SESSIONS]}; then comps=$( __get_all_sessions ) elif __contains_word "$verb" ${VERBS[USERS]}; then comps=$( __get_all_users ) elif __contains_word "$verb" ${VERBS[SEATS]}; then comps=$( __get_all_seats ) elif __contains_word "$verb" ${VERBS[STANDALONE]}; then comps='' elif __contains_word "$verb" ${VERBS[ATTACH]}; then if [[ $prev = $verb ]]; then comps=$( __get_all_seats ) else comps=$(compgen -A file -- "$cur" ) compopt -o filenames fi fi COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _loginctl loginctl systemd-229/shell-completion/bash/machinectl000066400000000000000000000066731265713322000213220ustar00rootroot00000000000000# machinectl(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2014 Thomas H.P. Andersen # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word() { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } __get_machines() { local a b (machinectl list-images --no-legend --no-pager; machinectl list --no-legend --no-pager; echo ".host") | \ { while read a b; do echo " $a"; done; } | sort -u; } _machinectl() { local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local i verb comps local -A OPTS=( [STANDALONE]='--all -a --full --help -h --no-ask-password --no-legend --no-pager --version' [ARG]='--host -H --kill-who -M --machine --property -p --signal -s' ) local -A VERBS=( [STANDALONE]='list list-images pull-tar pull-raw import-tar import-raw export-tar export-raw list-transfers cancel-transfer' [MACHINES]='status show start login shell enable disable poweroff reboot terminate kill copy-to copy-from image-status show-image clone rename read-only remove set-limit' ) _init_completion || return for ((i=0; i <= COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then verb=${COMP_WORDS[i]} break fi done if __contains_word "$prev" ${OPTS[ARG]}; then case $prev in --signal|-s) _signals return ;; --kill-who) comps='all leader' ;; --host|-H) comps=$(compgen -A hostname) ;; --machine|-M) comps=$( __get_machines ) ;; --property|-p) comps='' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ "$cur" = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 fi if [[ -z $verb ]]; then comps=${VERBS[*]} elif __contains_word "$verb" ${VERBS[STANDALONE]}; then comps='' elif __contains_word "$verb" ${VERBS[MACHINES]}; then comps=$( __get_machines ) fi COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _machinectl machinectl systemd-229/shell-completion/bash/networkctl000066400000000000000000000043131265713322000213740ustar00rootroot00000000000000# networkctl(1) completion -*- shell-script -*- # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done return 1 } __get_links() { networkctl list --no-legend --no-pager --all | { while read -r a b c; do echo " $b"; done; }; } _networkctl() { local i verb comps local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local -A OPTS=( [STANDALONE]='-a --all -h --help --version --no-pager --no-legend' [ARG]='' ) local -A VERBS=( [STANDALONE]='list lldp' [LINKS]='status' ) _init_completion || return for ((i=0; i < COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then verb=${COMP_WORDS[i]} break fi done if [[ "$cur" = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 fi if [[ -z $verb ]]; then comps=${VERBS[*]} elif __contains_word "$verb" ${VERBS[STANDALONE]}; then comps='' elif __contains_word "$verb" ${VERBS[LINKS]}; then comps=$( __get_links ) fi COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _networkctl networkctl systemd-229/shell-completion/bash/systemctl.in000066400000000000000000000300561265713322000216370ustar00rootroot00000000000000# systemctl(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2010 Ran Benita # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __systemctl() { local mode=$1; shift 1 systemctl $mode --full --no-legend "$@" } __systemd_properties() { local mode=$1 { __systemctl $mode show --all; @rootlibexecdir@/systemd --dump-configuration-items; } | while IFS='=' read -r key value; do [[ $value ]] && echo "$key" done } __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } __filter_units_by_property () { local mode=$1 property=$2 value=$3 ; shift 3 local units=("$@") local props IFS=$'\n' read -rd '' -a props < \ <(__systemctl $mode show --property "$property" -- "${units[@]}") for ((i=0; $i < ${#units[*]}; i++)); do if [[ "${props[i]}" = "$property=$value" ]]; then echo " ${units[i]}" fi done } __get_all_units () { { __systemctl $1 list-unit-files; __systemctl $1 list-units --all; } \ | { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; }; } __get_template_names () { __systemctl $1 list-unit-files \ | { while read -r a b; do [[ $a =~ @\. ]] && echo " ${a%%@.*}@"; done; }; } __get_active_units () { __systemctl $1 list-units \ | { while read -r a b; do echo " $a"; done; }; } __get_startable_units () { # find startable inactive units __filter_units_by_property $mode ActiveState inactive $( __filter_units_by_property $mode CanStart yes $( __systemctl $mode list-unit-files --state enabled,disabled,static | \ { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; } __systemctl $mode list-units --state inactive,failed | \ { while read -r a b; do echo " $a"; done; } )) } __get_restartable_units () { # filter out masked and not-found __filter_units_by_property $mode CanStart yes $( __systemctl $mode list-unit-files --state enabled,disabled,static | \ { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; } __systemctl $mode list-units | \ { while read -r a b; do echo " $a"; done; } ) } __get_failed_units () { __systemctl $1 list-units \ | { while read -r a b c d; do [[ $c == "failed" ]] && echo " $a"; done; }; } __get_enabled_units () { __systemctl $1 list-unit-files \ | { while read -r a b c ; do [[ $b == "enabled" ]] && echo " $a"; done; }; } __get_disabled_units () { __systemctl $1 list-unit-files \ | { while read -r a b c ; do [[ $b == "disabled" ]] && echo " $a"; done; }; } __get_masked_units () { __systemctl $1 list-unit-files \ | { while read -r a b c ; do [[ $b == "masked" ]] && echo " $a"; done; }; } __get_all_unit_files () { { __systemctl $1 list-unit-files; } | { while read -r a b; do echo " $a"; done; }; } __get_machines() { local a b { machinectl list-images --no-legend --no-pager; machinectl list --no-legend --no-pager; } | \ { while read a b; do echo " $a"; done; } } _systemctl () { local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local i verb comps mode local -A OPTS=( [STANDALONE]='--all -a --reverse --after --before --defaults --failed --force -f --full -l --global --help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall --quiet -q --privileged -P --system --user --version --runtime --recursive -r --firmware-setup --show-types -i --ignore-inhibitors --plain' [ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --job-mode --root --preset-mode -n --lines -o --output -M --machine' ) if __contains_word "--user" ${COMP_WORDS[*]}; then mode=--user elif __contains_word "--global" ${COMP_WORDS[*]}; then mode=--user else mode=--system fi if __contains_word "$prev" ${OPTS[ARG]}; then case $prev in --signal|-s) _signals return ;; --type|-t) comps=$(__systemctl $mode -t help) ;; --state) comps=$(__systemctl $mode --state=help) ;; --job-mode) comps='fail replace replace-irreversibly isolate ignore-dependencies ignore-requirements flush' ;; --kill-who) comps='all control main' ;; --root) comps=$(compgen -A directory -- "$cur" ) compopt -o filenames ;; --host|-H) comps=$(compgen -A hostname) ;; --property|-p) comps=$(__systemd_properties $mode) ;; --preset-mode) comps='full enable-only disable-only' ;; --output|-o) comps='short short-iso short-precise short-monotonic verbose export json json-pretty json-sse cat' ;; --machine|-M) comps=$( __get_machines ) ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ "$cur" = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 fi local -A VERBS=( [ALL_UNITS]='is-active is-failed is-enabled status show cat mask preset help list-dependencies edit set-property' [ENABLED_UNITS]='disable' [DISABLED_UNITS]='enable' [REENABLABLE_UNITS]='reenable' [FAILED_UNITS]='reset-failed' [STARTABLE_UNITS]='start' [STOPPABLE_UNITS]='stop condstop kill try-restart condrestart' [ISOLATABLE_UNITS]='isolate' [RELOADABLE_UNITS]='reload condreload try-reload-or-restart force-reload' [RESTARTABLE_UNITS]='restart reload-or-restart' [TARGET_AND_UNITS]='add-wants add-requires' [MASKED_UNITS]='unmask' [JOBS]='cancel' [ENVS]='set-environment unset-environment' [STANDALONE]='daemon-reexec daemon-reload default emergency exit halt hibernate hybrid-sleep kexec list-jobs list-sockets list-timers list-units list-unit-files poweroff reboot rescue show-environment suspend get-default is-system-running' [FILE]='link switch-root' [TARGETS]='set-default' ) for ((i=0; i < COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then verb=${COMP_WORDS[i]} break fi done if [[ -z $verb ]]; then comps="${VERBS[*]}" elif __contains_word "$verb" ${VERBS[ALL_UNITS]}; then comps=$( __get_all_units $mode ) compopt -o filenames elif __contains_word "$verb" ${VERBS[ENABLED_UNITS]}; then comps=$( __get_enabled_units $mode ) compopt -o filenames elif __contains_word "$verb" ${VERBS[DISABLED_UNITS]}; then comps=$( __get_disabled_units $mode; __get_template_names $mode) compopt -o filenames elif __contains_word "$verb" ${VERBS[REENABLABLE_UNITS]}; then comps=$( __get_disabled_units $mode; __get_enabled_units $mode; __get_template_names $mode) compopt -o filenames elif __contains_word "$verb" ${VERBS[STARTABLE_UNITS]}; then comps=$( __get_startable_units $mode; __get_template_names $mode) compopt -o filenames elif __contains_word "$verb" ${VERBS[RESTARTABLE_UNITS]}; then comps=$( __get_restartable_units $mode; __get_template_names $mode) compopt -o filenames elif __contains_word "$verb" ${VERBS[STOPPABLE_UNITS]}; then comps=$( __filter_units_by_property $mode CanStop yes \ $( __get_active_units $mode ) ) compopt -o filenames elif __contains_word "$verb" ${VERBS[RELOADABLE_UNITS]}; then comps=$( __filter_units_by_property $mode CanReload yes \ $( __get_active_units $mode ) ) compopt -o filenames elif __contains_word "$verb" ${VERBS[ISOLATABLE_UNITS]}; then comps=$( __filter_units_by_property $mode AllowIsolate yes \ $( __get_all_units $mode ) ) compopt -o filenames elif __contains_word "$verb" ${VERBS[FAILED_UNITS]}; then comps=$( __get_failed_units $mode ) compopt -o filenames elif __contains_word "$verb" ${VERBS[MASKED_UNITS]}; then comps=$( __get_masked_units $mode ) compopt -o filenames elif __contains_word "$verb" ${VERBS[TARGET_AND_UNITS]}; then if __contains_word "$prev" ${VERBS[TARGET_AND_UNITS]} \ || __contains_word "$prev" ${OPTS[STANDALONE]}; then comps=$( __systemctl $mode list-unit-files --type target --all \ | { while read -r a b; do echo " $a"; done; } ) else comps=$( __get_all_unit_files $mode ) fi compopt -o filenames elif __contains_word "$verb" ${VERBS[STANDALONE]}; then comps='' elif __contains_word "$verb" ${VERBS[JOBS]}; then comps=$( __systemctl $mode list-jobs | { while read -r a b; do echo " $a"; done; } ) elif __contains_word "$verb" ${VERBS[ENVS]}; then comps=$( __systemctl $mode show-environment \ | while read -r line; do echo " ${line%%=*}=";done ) compopt -o nospace elif __contains_word "$verb" ${VERBS[FILE]}; then comps=$( compgen -A file -- "$cur" ) compopt -o filenames elif __contains_word "$verb" ${VERBS[TARGETS]}; then comps=$( __systemctl $mode list-unit-files --type target --full --all \ | { while read -r a b; do echo " $a"; done; } ) fi COMPREPLY=( $(compgen -o filenames -W '$comps' -- "$cur") ) return 0 } complete -F _systemctl systemctl systemd-229/shell-completion/bash/systemd-analyze000066400000000000000000000076741265713322000223460ustar00rootroot00000000000000# systemd-analyze(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2010 Ran Benita # Copyright 2013 Harald Hoyer # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } __get_machines() { local a b machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; }; } _systemd_analyze() { local i verb comps local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local -A OPTS=( [STANDALONE]='--help --version --system --user --order --require --no-pager --man' [ARG]='-H --host -M --machine --fuzz --from-pattern --to-pattern ' ) local -A VERBS=( [STANDALONE]='time blame plot dump' [CRITICAL_CHAIN]='critical-chain' [DOT]='dot' [LOG_LEVEL]='set-log-level' [VERIFY]='verify' ) _init_completion || return for ((i=0; i < COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then verb=${COMP_WORDS[i]} break fi done if __contains_word "$prev" ${OPTS[ARG]}; then case $prev in --host|-H) comps=$(compgen -A hostname) ;; --machine|-M) comps=$( __get_machines ) ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ -z $verb && $cur = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 fi if [[ -z $verb ]]; then comps=${VERBS[*]} elif __contains_word "$verb" ${VERBS[STANDALONE]}; then if [[ $cur = -* ]]; then comps='--help --version --system --user' fi elif __contains_word "$verb" ${VERBS[CRITICAL_CHAIN]}; then if [[ $cur = -* ]]; then comps='--help --version --system --user --fuzz' fi elif __contains_word "$verb" ${VERBS[DOT]}; then if [[ $cur = -* ]]; then comps='--help --version --system --user --from-pattern --to-pattern --order --require' fi elif __contains_word "$verb" ${VERBS[LOG_LEVEL]}; then if [[ $cur = -* ]]; then comps='--help --version --system --user' else comps='debug info notice warning err crit alert emerg' fi elif __contains_word "$verb" ${VERBS[VERIFY]}; then if [[ $cur = -* ]]; then comps='--help --version --system --user --man' else comps=$( compgen -A file -- "$cur" ) compopt -o filenames fi fi COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _systemd_analyze systemd-analyze systemd-229/shell-completion/bash/systemd-cat000066400000000000000000000035701265713322000214410ustar00rootroot00000000000000# systemd-cat(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2014 Thomas H.P. Andersen # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word() { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } _systemd_cat() { local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local i verb comps local -A OPTS=( [STANDALONE]='-h --help --version' [ARG]='-t --identifier -p --priority --level-prefix' ) _init_completion || return if __contains_word "$prev" ${OPTS[ARG]}; then case $prev in --identifier|-t) comps='' ;; --priority|-p) comps='emerg alert crit err warning notice info debug' ;; --level-prefix) comps='yes no' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) } complete -F _systemd_cat systemd-cat systemd-229/shell-completion/bash/systemd-cgls000066400000000000000000000034001265713322000216120ustar00rootroot00000000000000# systemd-cgls(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2014 Thomas H.P. Andersen # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word() { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } __get_machines() { local a b machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; }; } _systemd_cgls() { local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local i verb comps local -A OPTS=( [STANDALONE]='-h --help --version --all -l --full -k --no-pager' [ARG]='-M --machine' ) _init_completion || return if __contains_word "$prev" ${OPTS[ARG]}; then case $prev in --machine|-M) comps=$( __get_machines ) ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) } complete -F _systemd_cgls systemd-cgls systemd-229/shell-completion/bash/systemd-cgtop000066400000000000000000000040611265713322000220020ustar00rootroot00000000000000# systemd-cgtop(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2014 Thomas H.P. Andersen # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word() { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } __get_machines() { local a b machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; }; } _systemd_cgtop() { local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local comps local -A OPTS=( [STANDALONE]='-h --help --version -p -t -c -m -i -b --batch -r --raw -k -P' [ARG]='--cpu --depth -M --machine --recursive -n --iterations -d --delay --order' ) _init_completion || return if __contains_word "$prev" ${OPTS[ARG]}; then case $prev in --machine|-M) comps=$( __get_machines ) ;; --recursive) comps='yes no' ;; --order) comps='path tasks cpu memory io' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) } complete -F _systemd_cgtop systemd-cgtop systemd-229/shell-completion/bash/systemd-delta000066400000000000000000000036401265713322000217610ustar00rootroot00000000000000# systemd-delta(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2014 Thomas H.P. Andersen # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word() { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } _systemd-delta() { local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local comps local -A OPTS=( [STANDALONE]='--help -h --no-pager --version' [ARG]='--diff --type -t' ) _init_completion || return if __contains_word "$prev" ${OPTS[ARG]}; then case $prev in --diff) comps='yes no' ;; --type|-t) comps='masked equivalent redirected overridden unchanged extended default' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ "$cur" = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 fi COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _systemd-delta systemd-delta systemd-229/shell-completion/bash/systemd-detect-virt000066400000000000000000000024451265713322000231240ustar00rootroot00000000000000# systemd-detect-virt(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2014 Thomas H.P. Andersen # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word() { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } _systemd_detect_virt() { local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local i verb comps local -A OPTS=( [STANDALONE]='-h --help --version -c --container -v --vm -q --quiet' ) _init_completion || return COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) } complete -F _systemd_detect_virt systemd-detect-virt systemd-229/shell-completion/bash/systemd-nspawn000066400000000000000000000136471265713322000222060ustar00rootroot00000000000000# systemd-nspawn(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2014 Thomas H.P. Andersen # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word() { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } __get_users() { local a b loginctl list-users --no-legend --no-pager | { while read a b; do echo " $b"; done; }; } __get_slices() { local a b systemctl list-units -t slice --no-legend --no-pager | { while read a b; do echo " $a"; done; }; } __get_machines() { local a b machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; }; } __get_env() { local a env | { while read a; do echo " ${a%%=*}"; done; }; } __get_interfaces(){ cut -f 1 -d ' ' /proc/net/dev | tail -n +3 | tr -s '\n' | tr -d ':' | xargs } _systemd_nspawn() { local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local i verb comps local -A OPTS=( [STANDALONE]='-h --help --version --private-network -b --boot --read-only -q --quiet --share-system --keep-unit --network-veth -j' [ARG]='-D --directory -u --user --uuid --capability --drop-capability --link-journal --bind --bind-ro -M --machine -S --slice --setenv -Z --selinux-context -L --selinux-apifs-context --register --network-interface --network-bridge --personality -i --image --tmpfs --volatile --network-macvlan --kill-signal' ) _init_completion || return if __contains_word "$prev" ${OPTS[ARG]}; then case $prev in --directory|-D) compopt -o nospace comps=$(compgen -S/ -A directory -- "$cur" ) ;; --user|-u) comps=$( __get_users ) ;; --uuid) comps='' ;; --capability) comps='CAP_BLOCK_SUSPEND CAP_IPC_LOCK CAP_MAC_ADMIN CAP_MAC_OVERRIDE CAP_SYS_MODULE CAP_SYS_PACCT CAP_SYS_RAWIO CAP_SYS_TIME CAP_SYSLOG CAP_WAKE_ALARM CAP_NET_ADMIN' ;; --drop-capability) comps='CAP_AUDIT_CONTROL CAP_AUDIT_WRITE CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_FSETID CAP_IPC_OWNER CAP_KILL CAP_LEASE CAP_LINUX_IMMUTABLE CAP_MKNOD CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETFCAP CAP_SETGID CAP_SETPCAP CAP_SETUID CAP_SYS_ADMIN CAP_SYS_BOOT CAP_SYS_CHROOT CAP_SYS_NICE CAP_SYS_PTRACE CAP_SYS_RESOURCE CAP_SYS_TTY_CONFIG' ;; --link-journal) comps='no auto guest try-guest host try-host' ;; --bind|--bind-ro) compopt -o nospace comps=$(compgen -S/ -A directory -- "$cur" ) ;; --tmpfs) compopt -o nospace comps=$(compgen -S/ -A directory -- "$cur" ) ;; --machine|-M) comps=$( __get_machines ) ;; --slice|-S) comps=$( __get_slices ) ;; --setenv) comps=$( __get_env ) ;; --selinux-context|-Z) comps='' ;; --selinux-apifs-context|-L) comps='' ;; --register) comps='yes no' ;; --network-interface) comps=$(__get_interfaces) ;; --network-bridge) comps='' ;; --network-macvlan) comps='' ;; --personality) comps='x86 x86-64' ;; --volatile) comps='yes state no' ;; --image|-i) compopt -o nospace comps=$( compgen -A file -- "$cur" ) ;; --kill-signal) _signals return ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) } complete -F _systemd_nspawn systemd-nspawn systemd-229/shell-completion/bash/systemd-path000066400000000000000000000035101265713322000216200ustar00rootroot00000000000000# systemd-path(1) completion -*- shell-script -*- # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done return 1 } __get_names() { systemd-path | { while IFS=: read -r a b; do echo " $a"; done; } } _systemd_path() { local comps local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local -A OPTS=( [STANDALONE]='-h --help --version' [ARG]='--suffix' ) _init_completion || return if __contains_word "$prev" ${OPTS[ARG]}; then case $prev in --suffix) comps='' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ "$cur" = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 fi comps=$( __get_names ) COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _systemd_path systemd-path systemd-229/shell-completion/bash/systemd-run000066400000000000000000000112061265713322000214710ustar00rootroot00000000000000# systemd-run(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2013 Zbigniew Jędrzejewski-Szmek # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __systemctl() { local mode=$1; shift 1 systemctl $mode --full --no-legend "$@" } __get_slice_units () { __systemctl $1 list-units --all -t slice \ | { while read -r a b c d; do echo " $a"; done; }; } __get_machines() { local a b machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; }; } _systemd_run() { local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local OPTS='-h --help --version --user --system --scope --unit --description --slice -r --remain-after-exit --send-sighup -H --host -M --machine --service-type --on-active --on-boot --on-startup --on-unit-active --on-unit-inactive --on-calendar --timer-property -t --pty -q --quiet --no-block --uid --gid --nice --setenv -p --property --no-ask-password' local mode=--system local i local opts_with_values=( --unit --description --slice --service-type -H --host -M --machine -p --property --on-active --on-boot --on-startup --on-unit-active --on-unit-inactive --on-calendar --timer-property ) for (( i=1; i <= COMP_CWORD; i++ )); do if [[ ${COMP_WORDS[i]} != -* ]]; then local root_command=${COMP_WORDS[i]} _command_offset $i return fi [[ ${COMP_WORDS[i]} == "--user" ]] && mode=--user [[ $i -lt $COMP_CWORD && " ${opts_with_values[@]} " =~ " ${COMP_WORDS[i]} " ]] && ((i++)) done case "$prev" in --unit|--description|--on-active|--on-boot|--on-startup|--on-unit-active|--on-unit-inactive|--on-calendar) # argument required but no completions available return ;; --slice) local comps=$(__get_slice_units $mode) COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 ;; --service-type) local comps='simple forking oneshot dbus notify idle' COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 ;; -p|--property) local comps='CPUAccounting= MemoryAccounting= BlockIOAccounting= SendSIGHUP= SendSIGKILL= MemoryLimit= CPUShares= BlockIOWeight= User= Group= DevicePolicy= KillMode= DeviceAllow= BlockIOReadBandwidth= BlockIOWriteBandwidth= BlockIODeviceWeight= Nice= Environment= KillSignal= LimitCPU= LimitFSIZE= LimitDATA= LimitSTACK= LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC= LimitMEMLOCK= LimitLOCKS= LimitSIGPENDING= LimitMSGQUEUE= LimitNICE= LimitRTPRIO= LimitRTTIME= PrivateTmp= PrivateDevices= PrivateNetwork= NoNewPrivileges= WorkingDirectory= RootDirectory= TTYPath= SyslogIdentifier= SyslogLevelPrefix= SyslogLevel= SyslogFacility= TimerSlackNSec= OOMScoreAdjust= ReadWriteDirectories= ReadOnlyDirectories= InaccessibleDirectories= EnvironmentFile= ProtectSystem= ProtectHome= RuntimeDirectory= PassEnvironment=' COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 ;; -H|--host) local comps=$(compgen -A hostname) COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 ;; -M|--machine) local comps=$( __get_machines ) COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 ;; --timer-property) local comps='AccuracySec= WakeSystem=' COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 ;; esac COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 } complete -F _systemd_run systemd-run systemd-229/shell-completion/bash/timedatectl000066400000000000000000000050241265713322000214770ustar00rootroot00000000000000# timedatectl(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2010 Ran Benita # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } _timedatectl() { local i verb comps local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local OPTS='-h --help --version --adjust-system-clock --no-pager --no-ask-password -H --host --machine' if __contains_word "$prev" $OPTS; then case $prev in --host|-H) comps='' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ $cur = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) return 0 fi local -A VERBS=( [BOOLEAN]='set-local-rtc set-ntp' [STANDALONE]='status set-time list-timezones' [TIMEZONES]='set-timezone' [TIME]='set-time' ) for ((i=0; i < COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then verb=${COMP_WORDS[i]} break fi done if [[ -z $verb ]]; then comps=${VERBS[*]} elif __contains_word "$verb" ${VERBS[BOOLEAN]}; then comps='true false' elif __contains_word "$verb" ${VERBS[TIMEZONES]}; then comps=$(command timedatectl list-timezones) elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[TIME]}; then comps='' fi COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _timedatectl timedatectl systemd-229/shell-completion/bash/udevadm000066400000000000000000000072161265713322000206320ustar00rootroot00000000000000# udevadm(8) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2010 Ran Benita # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } __get_all_sysdevs() { local -a devs=(/sys/bus/*/devices/*/ /sys/class/*/*/) printf '%s\n' "${devs[@]%/}" } _udevadm() { local i verb comps local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local OPTS='-h --help --version --debug' local verbs=(info trigger settle control monitor hwdb test-builtin test) for ((i=0; i < COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" "${verbs[@]}" && ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then verb=${COMP_WORDS[i]} break fi done if [[ -z $verb ]]; then COMPREPLY=( $(compgen -W '${OPTS[*]} ${verbs[*]}' -- "$cur") ) return 0 fi case $verb in 'info') if [[ $cur = -* ]]; then comps='--help --query= --path= --name= --root --attribute-walk --export-db --cleanup-db' else comps=$( __get_all_sysdevs ) fi ;; 'trigger') comps='--help --verbose --dry-run --type= --action= --subsystem-match= --subsystem-nomatch= --attr-match= --attr-nomatch= --property-match= --tag-match= --sysname-match= --parent-match=' ;; 'settle') comps='--help --timeout= --seq-start= --seq-end= --exit-if-exists= --quiet' ;; 'control') comps='--help --exit --log-priority= --stop-exec-queue --start-exec-queue --reload --property= --children-max= --timeout=' ;; 'monitor') comps='--help --kernel --udev --property --subsystem-match= --tag-match=' ;; 'hwdb') comps='--help --update --test=' ;; 'test') if [[ $cur = -* ]]; then comps='--help --action=' else comps=$( __get_all_sysdevs ) fi ;; 'test-builtin') comps='blkid btrfs hwdb input_id keyboard kmod net_id net_setup_link path_id usb_id uaccess' ;; *) comps=${VERBS[*]} ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _udevadm udevadm systemd-229/shell-completion/zsh/000077500000000000000000000000001265713322000171435ustar00rootroot00000000000000systemd-229/shell-completion/zsh/.gitignore000066400000000000000000000000141265713322000211260ustar00rootroot00000000000000/_systemctl systemd-229/shell-completion/zsh/Makefile000077700000000000000000000000001265713322000224512../Makefileustar00rootroot00000000000000systemd-229/shell-completion/zsh/_bootctl000066400000000000000000000020501265713322000206700ustar00rootroot00000000000000#compdef bootctl (( $+functions[_bootctl_command] )) || _bootctl_command() { local -a _bootctl_cmds _bootctl_cmds=( "status:Show status of installed systemd-boot and EFI variables" "install:Install systemd-boot to the ESP and EFI variables" "update:Update systemd-boot in the ESP and EFI variables" "remove:Remove systemd-boot from the ESP and EFI variables" ) if (( CURRENT == 1 )); then _describe -t commands 'bootctl command' _bootctl_cmds || compadd "$@" else local curcontext="$curcontext" cmd="${${_bootctl_cmds[(r)$words[1]:*]%%:*}}" if (( $+functions[_bootctl_$cmd] )); then _bootctl_$cmd else _message "no more options" fi fi } _arguments \ {-h,--help}'[Prints a short help text and exits.]' \ '--version[Prints a short version string and exits.]' \ '--path=[Path to the EFI System Partition (ESP)]:path:_directories' \ '--no-variables[Do not touch EFI variables]' \ '*::bootctl command:_bootctl_command' systemd-229/shell-completion/zsh/_busctl000066400000000000000000000057741265713322000205360ustar00rootroot00000000000000#compdef busctl # busctl(1) completion -*- shell-script -*- # # This file is part of systemd. # # Copyright 2013 Zbigniew Jędrzejewski-Szmek # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . (( $+functions[_busctl_command] )) || _busctl_command() { local -a _busctl_cmds _busctl_cmds=( "list:List bus names" "status:Show bus service, process or bus owner credentials" "monitor:Show bus traffic" "capture:Capture bus traffix as pcap" "tree:Show object tree of service" "introspect:Introspect object" "call:Call a method" "get-property:Get property value" "set-property:Set property value" ) if (( CURRENT == 1 )); then _describe -t commands 'busctl command' _busctl_cmds || compadd "$@" else local curcontext="$curcontext" cmd="${${_busctl_cmds[(r)$words[1]:*]%%:*}}" if (( $+functions[_busctl_$cmd] )); then _busctl_$cmd else _message "no more options" fi fi } _arguments \ {-h,--help}'[Prints a short help text and exits.]' \ '--version[Prints a short version string and exits.]' \ '--no-pager[Do not pipe output into a pager]' \ '--no-legend[Do not show the headers and footers]' \ '--system[Connect to system manager]' \ '--user[Connect to user service manager]' \ {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ {-M+,--machine=}'[Operate on local container]:machines:_sd_machines' \ '--address=[Connect to the bus specified by address]:address' \ '--show-machine[Show machine ID column in list]' \ '--unique[Only show unique names]' \ '--acquired[Only show acquired names]' \ '--activatable[Only show activatable names]' \ '--match=[Only show matching messages]:match' \ '--list[Do not show tree, but simple object path list]' \ '--quiet[Do not show method call reply]'\ '--verbose[Show result values in long format]' \ '--expect-reply=[Expect a method call reply]:boolean:(1 0)' \ '--auto-start=[Auto-start destination service]:boolean:(1 0)' \ '--allow-interactive-authorization=[Allow interactive authorization for operation]:boolean:(1 0)' \ '--timeout=[Maximum time to wait for method call completion]:timeout (seconds)' \ '--augment-creds=[Extend credential data with data read from /proc/$PID]:boolean:(1 0)' \ '*::busctl command:_busctl_command' systemd-229/shell-completion/zsh/_coredumpctl000066400000000000000000000027431265713322000215540ustar00rootroot00000000000000#compdef coredumpctl _coredumpctl_command(){ local -a _coredumpctl_cmds _coredumpctl_cmds=( 'list:List available coredumps' 'info:Show detailed information about one or more coredumps' 'dump:Print coredump to stdout' 'gdb:Start gdb on a coredump' ) if (( CURRENT == 1 )); then _describe -t commands 'coredumpctl command' _coredumpctl_cmds else local curcontext="$curcontext" local -a _dumps cmd="${${_coredumpctl_cmds[(r)$words[1]:*]%%:*}}" if (( $#cmd )); then # user can set zstyle ':completion:*:*:coredumpctl:*' sort no for coredumps to be ordered by date, otherwise they get ordered by pid _dumps=( "${(foa)$(coredumpctl list | awk 'BEGIN{OFS=":"} /^\s/ {sub(/[[ \t]+/, ""); print $5,$0}' 2>/dev/null)}" ) if [[ -n "$_dumps" ]]; then _describe -t pids 'coredumps' _dumps else _message "no coredumps" fi else _message "no more options" fi fi } _arguments \ {-o+,--output=}'[Write output to FILE]:output file:_files' \ {-F+,--field=}'[Show field in list output]:field' \ '-1[Show information about most recent entry only]' \ '--no-pager[Do not pipe output into a pager]' \ '--no-legend[Do not print the column headers]' \ {-h,--help}'[Show this help]' \ '--version[Show package version]' \ '*::coredumpctl commands:_coredumpctl_command' systemd-229/shell-completion/zsh/_hostnamectl000066400000000000000000000042551265713322000215540ustar00rootroot00000000000000#compdef hostnamectl _hostnamectl_set-hostname() { if (( CURRENT <= 3 )); then _message "new hostname" else _message "no more options" fi } _hostnamectl_set-icon-name() { if (( CURRENT <= 3 )); then _message "new icon name" else _message "no more options" fi } _hostnamectl_set-chassis() { if (( CURRENT <= 3 )); then _chassis=( desktop laptop server tablet handset watch embedded vm container ) _describe chassis _chassis else _message "no more options" fi } _hostnamectl_set-deployment() { if (( CURRENT <= 3 )); then _message "new environment" else _message "no more options" fi } _hostnamectl_set-location() { if (( CURRENT <= 3 )); then _message "new location" else _message "no more options" fi } _hostnamectl_command() { local -a _hostnamectl_cmds _hostnamectl_cmds=( "status:Show current hostname settings" "set-hostname:Set system hostname" "set-icon-name:Set icon name for host" "set-chassis:Set chassis type for host" "set-deployment:Set deployment environment for host" "set-location:Set location for host" ) if (( CURRENT == 1 )); then _describe -t commands 'hostnamectl commands' _hostnamectl_cmds || compadd "$@" else local curcontext="$curcontext" cmd="${${_hostnamectl_cmds[(r)$words[1]:*]%%:*}}" if (( $#cmd )); then if [[ $cmd == status ]]; then _message "no options" else _hostnamectl_$cmd fi else _message "unknown hostnamectl command: $words[1]" fi fi } _arguments -s \ {-h,--help}'[Show this help]' \ '--version[Show package version]' \ '--transient[Only set transient hostname]' \ '--static[Only set static hostname]' \ '--pretty[Only set pretty hostname]' \ '--no-ask-password[Do not prompt for password]' \ {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ {-M+,--machine=}'[Operate on local container]:machines:_sd_machines' \ '*::hostnamectl commands:_hostnamectl_command' systemd-229/shell-completion/zsh/_journalctl000066400000000000000000000114171265713322000214060ustar00rootroot00000000000000#compdef journalctl _list_fields() { local -a journal_fields journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC} ERRNO SYSLOG_{FACILITY,IDENTIFIER,PID} _{P,U,G}ID _COMM _EXE _CMDLINE _AUDIT_{SESSION,LOGINUID} _SYSTEMD_{CGROUP,SESSION,UNIT,OWNER_UID} _SYSTEMD_USER_UNIT USER_UNIT _SELINUX_CONTEXT _SOURCE_REALTIME_TIMESTAMP _{BOOT,MACHINE}_ID _HOSTNAME _TRANSPORT _KERNEL_{DEVICE,SUBSYSTEM} _UDEV_{SYSNAME,DEVNODE,DEVLINK} __CURSOR __{REALTIME,MONOTONIC}_TIMESTAMP) case $_jrnl_none in yes) _values -s '=' 'possible fields' \ "${journal_fields[@]}:value:_journal_fields ${words[CURRENT]%%=*}" ;; *) _describe 'possible fields' journal_fields ;; esac } _journal_none() { local -a _commands _files _jrnl_none # Setting use-cache will slow this down considerably _commands=( ${"$(_call_program commands "$service" -F _EXE 2>/dev/null)"} ) _jrnl_none='yes' _alternative : \ 'files:/dev files:_files -W /dev -P /dev/' \ "commands:commands:($_commands[@])" \ 'fields:fields:_list_fields' } _journal_fields() { local -a _fields cmd cmd=("journalctl" "-F ${@[-1]}" "2>/dev/null" ) _fields=$(_call_program fields $cmd[@]) _fields=${_fields//'\'/'\\'} _fields=${_fields//':'/'\:'} _fields=( ${(f)_fields} ) typeset -U _fields _describe 'possible values' _fields } _journal_boots() { local -a _bootid _previousboots _bootid=( ${(f)"$(_call_program bootid "$service -F _BOOT_ID")"} ) _previousboots=( -{1..${#_bootid}} ) _alternative : \ "offsets:boot offsets:compadd -a '_previousboots[1,-2]'" \ "bootid:boot ids:compadd -a _bootid" } _arguments -s \ {-h,--help}'[Show this help]' \ '--version[Show package version]' \ '--no-pager[Do not pipe output into a pager]' \ {-l,--full}'[Show long fields in full]' \ {-a,--all}'[Show all fields, including long and unprintable]' \ {-f,--follow}'[Follow journal]' \ {-e,--pager-end}'[Jump to the end of the journal in the pager]' \ {-n+,--lines=}'[Number of journal entries to show]:integer' \ '--no-tail[Show all lines, even in follow mode]' \ {-r,--reverse}'[Reverse output]' \ {-o+,--output=}'[Change journal output mode]:output modes:_sd_outputmodes' \ {-x,--catalog}'[Show explanatory texts with each log line]' \ {-q,--quiet}"[Don't show privilege warning]" \ {-m,--merge}'[Show entries from all available journals]' \ {-b+,--boot=}'[Show data only from the specified boot or offset]::boot id or offset:_journal_boots' \ '--list-boots[List boots ordered by time]' \ {-k,--dmesg}'[Show only kernel messages from the current boot]' \ {-u+,--unit=}'[Show data only from the specified unit]:units:_journal_fields _SYSTEMD_UNIT' \ '--user-unit=[Show data only from the specified user session unit]:units:_journal_fields USER_UNIT' \ {-p+,--priority=}'[Show only messages within the specified priority range]:priority:_journal_fields PRIORITY' \ {-t+,--identifier=}'[Show only messages with the specified syslog identifier]:identifier:_journal_fields SYSLOG_IDENTIFIER' \ {-c+,--cursor=}'[Start showing entries from the specified cursor]:cursors:_journal_fields __CURSORS' \ '--after-cursor=[Start showing entries from after the specified cursor]:cursors:_journal_fields __CURSORS' \ '--since=[Start showing entries on or newer than the specified date]:YYYY-MM-DD HH\:MM\:SS' \ '--until=[Stop showing entries on or older than the specified date]:YYYY-MM-DD HH\:MM\:SS' \ {-F,--field=}'[List all values a certain field takes]:Fields:_list_fields' \ '--system[Show system and kernel messages]' \ '--user[Show messages from user services]' \ {-M+,--machine=}'[Operate on local container]:machines:_sd_machines' \ {-D+,--directory=}'[Show journal files from directory]:directories:_directories' \ '--file=[Operate on specified journal files]:file:_files' \ '--root=[Operate on catalog hierarchy under specified directory]:directories:_directories' \ '--new-id128[Generate a new 128 Bit ID]' \ '--header[Show journal header information]' \ '--disk-usage[Show total disk usage]' \ '--list-catalog[List messages in catalog]' \ '--dump-catalog[Dump messages in catalog]' \ '--update-catalog[Update binary catalog database]' \ '--setup-keys[Generate a new FSS key pair]' \ '--force[Force recreation of the FSS keys]' \ '--interval=[Time interval for changing the FSS sealing key]:time interval' \ '--verify[Verify journal file consistency]' \ '--verify-key=[Specify FSS verification key]:FSS key' \ '*::default: _journal_none' systemd-229/shell-completion/zsh/_kernel-install000066400000000000000000000011461265713322000221530ustar00rootroot00000000000000#compdef kernel-install _images(){ if [[ "$words[2]" == "remove" ]]; then _message 'No more options' else _path_files -W /boot/ -P /boot/ -g "vmlinuz-*" fi } _kernels(){ read _MACHINE_ID < /etc/machine-id _kernel=( /lib/modules/[0-9]* ) if [[ "$cmd" == "remove" && -n "$_MACHINE_ID" ]]; then _kernel=( "/boot/$_MACHINE_ID"/[0-9]* ) fi _kernel=( ${_kernel##*/} ) _describe "installed kernels" _kernel } _arguments \ '1::add or remove:(add remove)' \ '2::kernel versions:_kernels' \ '3::kernel images:_images' #vim: set ft=zsh sw=4 ts=4 et systemd-229/shell-completion/zsh/_localectl000066400000000000000000000067341265713322000212010ustar00rootroot00000000000000#compdef localectl _localectl_set-locale() { local -a _locales locale_fields locale_fields=(LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME \ LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER \ LC_NAME LC_ADDRESS LC_TELEPHONE \ LC_MEASUREMENT LC_IDENTIFICATION) # LC_ALL is omitted on purpose local expl suf _locales=( ${(f)"$(_call_program locales "$service" list-locales)"} ) compset -P1 '*=' if [[ -prefix 1 *\= ]]; then local conf=${PREFIX%%\=*} _wanted locales expl "locales configs" \ _combination localeconfs confs=$conf locales "$@" - else compadd -S '=' $locale_fields fi } _localectl_set-keymap() { local -a _keymaps if (( CURRENT <= 3 )); then _keymaps=( ${(f)"$(_call_program locales "$service" list-keymaps)"} ) _describe keymaps _keymaps else _message "no more options" fi } _localectl_set-x11-keymap() { if (( $+commands[pkg-config] )); then local -a _file _layout _model _variant _options local _xorg_lst _xorg_lst=${"$($commands[pkg-config] xkeyboard-config --variable=xkb_base)"} _file=( ${(ps:\n\!:)"$(<$_xorg_lst/rules/xorg.lst)"} ) _layout=( ${${${(M)${(f)_file[1]}:# *}# }%% *} ) _model=( ${${${(M)${(f)_file[2]}:# *}# }%% *} ) _variant=( ${${${(M)${(f)_file[3]}:# *}# }%% *} ) _options=( ${${${(M)${(f)_file[4]}:# *}# }%% *} ) #_layout=( ${(f)"$( echo $_file[1] | awk '/^ / {print $1}' )"} ) #_model=( ${(f)"$(echo $_file[2] | awk '/^ / {print $1}')"} ) #_variant=( ${(f)"$(echo $_file[3] | awk '/^ / {print $1}')"} ) #_options=( ${(f)"$(echo ${_file[4]//:/\\:} | awk '/^ / {print $1}')"} ) case $CURRENT in 2) _describe layouts _layout ;; 3) _describe models _model;; 4) _describe variants _variant;; 5) _describe options _options;; *) _message "no more options" esac fi } _localectl_command() { local -a _localectl_cmds _localectl_cmds=( 'status:Show current locale settings' 'set-locale:Set system locale' 'list-locales:Show known locales' 'set-keymap:Set virtual console keyboard mapping' 'list-keymaps:Show known virtual console keyboard mappings' 'set-x11-keymap:Set X11 keyboard mapping' 'list-x11-keymap-models:Show known X11 keyboard mapping models' 'list-x11-keymap-layouts:Show known X11 keyboard mapping layouts' 'list-x11-keymap-variants:Show known X11 keyboard mapping variants' 'list-x11-keymap-options:Show known X11 keyboard mapping options' ) if (( CURRENT == 1 )); then _describe -t commands 'localectl command' _localectl_cmds else local curcontext="$curcontext" cmd="${${_localectl_cmds[(r)$words[1]:*]%%:*}}" if (( $+functions[_localectl_$cmd] )); then _localectl_$cmd else _message "unknown localectl command: $words[1]" fi fi } _arguments \ {-h,--help}'[Show this help]' \ '--version[Show package version]' \ "--no-convert[Don't convert keyboard mappings]" \ '--no-pager[Do not pipe output into a pager]' \ '--no-ask-password[Do not prompt for password]' \ {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ {-M+,--machine=}'[Operate on local container]:machine' \ '*::localectl commands:_localectl_command' systemd-229/shell-completion/zsh/_loginctl000066400000000000000000000132071265713322000210430ustar00rootroot00000000000000#compdef loginctl _loginctl_all_sessions() { local session description loginctl --no-legend list-sessions | while read -r session description; do _sys_all_sessions+=( "$session" ) _sys_all_sessions_descr+=( "${session}:$description" ) done } _loginctl_all_users() { local uid description loginctl --no-legend list-users | while read -r uid description; do _sys_all_users+=( "$uid" ) _sys_all_users_descr+=( "${uid}:$description" ) done } _loginctl_all_seats() { local seat description loginctl --no-legend list-seats | while read -r seat description; do _sys_all_seats+=( "$seat" ) _sys_all_seats_descr+=( "${seat}:$description" ) done } local fun # Completion functions for SESSIONS for fun in session-status show-session activate lock-session unlock-session terminate-session kill-session ; do (( $+functions[_loginctl_$fun] )) || _loginctl_$fun() { local -a _sys_all_sessions{,_descr} _loginctl_all_sessions for _ignore in $words[2,-1]; do _sys_all_sessions[(i)$_ignore]=() _sys_all_sessions_descr[(i)$_ignore:*]=() done if zstyle -T ":completion:${curcontext}:systemd-sessions" verbose; then _describe -t systemd-sessions session _sys_all_sessions_descr _sys_all_sessions "$@" else local expl _wanted systemd-sessions expl session compadd "$@" -a _sys_all_sessions fi } done # Completion functions for USERS for fun in user-status show-user enable-linger disable-linger terminate-user kill-user ; do (( $+functions[_loginctl_$fun] )) || _loginctl_$fun() { local -a _sys_all_users{,_descr} zstyle -a ":completion:${curcontext}:users" users _sys_all_users if ! (( $#_sys_all_users )); then _loginctl_all_users fi for _ignore in $words[2,-1]; do _sys_all_users[(i)$_ignore]=() _sys_all_users_descr[(i)$_ignore:*]=() done # using the common tag `users' here, not rolling our own `systemd-users' tag if zstyle -T ":completion:${curcontext}:users" verbose; then _describe -t users user ${_sys_all_users_descr:+_sys_all_users_descr} _sys_all_users "$@" else local expl _wanted users expl user compadd "$@" -a _sys_all_users fi } done # Completion functions for SEATS (( $+functions[_loginctl_seats] )) || _loginctl_seats() { local -a _sys_all_seats{,_descr} _loginctl_all_seats for _ignore in $words[2,-1]; do _sys_all_seats[(i)$_ignore]=() _sys_all_seats_descr[(i)$_ignore:*]=() done if zstyle -T ":completion:${curcontext}:systemd-seats" verbose; then _describe -t systemd-seats seat _sys_all_seats_descr _sys_all_seats "$@" else local expl _wanted systemd-seats expl seat compadd "$@" -a _sys_all_seats fi } for fun in seat-status show-seat terminate-seat ; do (( $+functions[_loginctl_$fun] )) || _loginctl_$fun() { _loginctl_seats } done # Completion functions for ATTACH (( $+functions[_loginctl_attach] )) || _loginctl_attach() { _arguments -w -C -S -s \ ':seat:_loginctl_seats' \ '*:device:_files' } # no loginctl completion for: # [STANDALONE]='list-sessions list-users list-seats flush-devices' (( $+functions[_loginctl_command] )) || _loginctl_command() { local -a _loginctl_cmds _loginctl_cmds=( "list-sessions:List sessions" "session-status:Show session status" "show-session:Show properties of one or more sessions" "activate:Activate a session" "lock-session:Screen lock one or more sessions" "unlock-session:Screen unlock one or more sessions" "lock-sessions:Screen lock all current sessions" "unlock-sessions:Screen unlock all current sessions" "terminate-session:Terminate one or more sessions" "kill-session:Send signal to processes of a session" "list-users:List users" "user-status:Show user status" "show-user:Show properties of one or more users" "enable-linger:Enable linger state of one or more users" "disable-linger:Disable linger state of one or more users" "terminate-user:Terminate all sessions of one or more users" "kill-user:Send signal to processes of a user" "list-seats:List seats" "seat-status:Show seat status" "show-seat:Show properties of one or more seats" "attach:Attach one or more devices to a seat" "flush-devices:Flush all device associations" "terminate-seat:Terminate all sessions on one or more seats" ) if (( CURRENT == 1 )); then _describe -t commands 'loginctl command' _loginctl_cmds || compadd "$@" else local curcontext="$curcontext" _ignore cmd="${${_loginctl_cmds[(r)$words[1]:*]%%:*}}" if (( $#cmd )); then curcontext="${curcontext%:*:*}:loginctl-${cmd}:" _call_function ret _loginctl_$cmd || _message 'no more arguments' else _message "unknown loginctl command: $words[1]" fi return ret fi } _arguments -s \ {-h,--help}'[Show help]' \ '--version[Show package version]' \ \*{-p+,--property=}'[Show only properties by this name]:unit property' \ {-a,--all}'[Show all properties, including empty ones]' \ '--kill-who=[Who to send signal to]:killwho:(main control all)' \ {-s+,--signal=}'[Which signal to send]:signal:_signals' \ {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ {-M+,--machine=}'[Operate on local container]:machine:_sd_machines' \ {-l,--full}'[Do not ellipsize output]' \ '--no-pager[Do not pipe output into a pager]' \ '--no-legend[Do not show the headers and footers]' \ '--no-ask-password[Do not ask for system passwords]' \ {-n+,--lines=}'[Number of journal entries to show]' \ {-o+,--output=}'[Change journal output mode]:output modes:_sd_outputmodes' \ '*::loginctl command:_loginctl_command' systemd-229/shell-completion/zsh/_machinectl000066400000000000000000000071071265713322000213410ustar00rootroot00000000000000#compdef machinectl __get_available_machines () { machinectl --no-legend list-images | {while read -r a b; do echo $a; done;} } _available_machines() { local -a _machines _machines=("${(fo)$(__get_available_machines)}") typeset -U _machines if [[ -n "$_machines" ]]; then _describe 'machines' _machines else _message 'no machines' fi } (( $+functions[_machinectl_command] )) || _machinectl_command() { local -a _machinectl_cmds _machinectl_cmds=( "list:List currently running VMs/containers" "status:Show VM/container status" "show:Show properties of one or more VMs/containers" "start:Start container as a service" "login:Get a login prompt on a VM/container" "enable:Enable automatic container start at boot" "disable:Disable automatic container start at boot" "poweroff:Power off one or more VMs/containers" "reboot:Reboot one or more VMs/containers" "terminate:Terminate one or more VMs/containers" "kill:Send signal to process or a VM/container" "copy-to:Copy files from the host to a container" "copy-from:Copy files from a container to the host" "bind:Bind mount a path from the host into a container" "list-images:Show available container and VM images" "image-status:Show image details" "show-image:Show properties of image" "clone:Clone an image" "rename:Rename an image" "read-only:Mark or unmark image read-only" "remove:Remove an image" "pull-tar:Download a TAR container image" "pull-raw:Download a RAW container or VM image" "list-transfers:Show list of downloads in progress" "cancel-transfer:Cancel a download" ) if (( CURRENT == 1 )); then _describe -t commands 'machinectl command' _machinectl_cmds || compadd "$@" else local curcontext="$curcontext" cmd="${${_machinectl_cmds[(r)$words[1]:*]%%:*}}" if (( $#cmd )); then if (( CURRENT == 2 )); then case $cmd in list*|cancel-transfer|pull-tar|pull-raw) msg="no options" ;; start) _available_machines ;; *) _sd_machines esac else case $cmd in copy-to|copy-from|bind) _files ;; *) msg="no options" esac fi else _message "no more options" fi fi } _arguments \ {-h,--help}'[Prints a short help text and exits.]' \ '--version[Prints a short version string and exits.]' \ '--no-pager[Do not pipe output into a pager.]' \ '--no-legend[Do not show the headers and footers.]' \ '--no-ask-password[Do not ask for system passwords.]' \ {-H+,--host=}'[Operate on remote host.]:userathost:_sd_hosts_or_user_at_host' \ {-M+,--machine=}'[Operate on local container.]:machine:_sd_machines' \ {-p+,--property=}'[Limit output to specified property.]:property:(Name Id Timestamp TimestampMonotonic Service Scope Leader Class State RootDirectory)' \ {-a,--all}'[Show all proerties.]' \ {-q,--quiet}'[Suppress output.]' \ {-l,--full}'[Do not ellipsize cgroup members.]' \ '--kill-who=[Who to send signal to.]:killwho:(leader all)' \ {-s+,--signal=}'[Which signal to send.]:signal:_signals' \ '--read-only[Create read-only bind mount.]' \ '--mkdir[Create directory before bind mounting, if missing.]' \ {-n+,--lines=}'[Number of journal entries to show.]:integer' \ {-o+,--output=}'[Change journal output mode.]:output modes:_sd_outputmodes' \ '--verify=[Verification mode for downloaded images.]:verify:(no checksum signature)' \ '--force[Download image even if already exists.]' \ '*::machinectl command:_machinectl_command' systemd-229/shell-completion/zsh/_sd_hosts_or_user_at_host000066400000000000000000000001171265713322000243310ustar00rootroot00000000000000#autoload _alternative \ 'users-hosts:: _user_at_host' \ 'hosts:: _hosts' systemd-229/shell-completion/zsh/_sd_machines000066400000000000000000000004761265713322000215110ustar00rootroot00000000000000#autoload __get_machines () { machinectl --full --no-legend --no-pager list | {while read -r a b; do echo $a; done;}; } local -a _machines _machines=("${(fo)$(__get_machines)}") typeset -U _machines if [[ -n "$_machines" ]]; then _describe 'machines' _machines else _message 'no machines' fi systemd-229/shell-completion/zsh/_sd_outputmodes000066400000000000000000000003121265713322000222770ustar00rootroot00000000000000#autoload local -a _output_opts _output_opts=(short short-iso short-precise short-monotonic verbose export json json-pretty json-sse cat) _describe -t output 'output mode' _output_opts || compadd "$@" systemd-229/shell-completion/zsh/_sd_unit_files000066400000000000000000000003421265713322000220530ustar00rootroot00000000000000#autoload _sd_unit_files() { local files expl files=( '*:files:->files' ) _description files expl 'unit file' _files "$expl[@]" -g '*.(automount|busname|device|mount|path|service|socket|swap|target|timer)' } systemd-229/shell-completion/zsh/_systemctl.in000066400000000000000000000346211265713322000216670ustar00rootroot00000000000000#compdef systemctl (( $+functions[_systemctl_command] )) || _systemctl_command() { local -a _systemctl_cmds _systemctl_cmds=( "list-sockets:List sockets" "list-timers:List timers" "list-units:List units" "start:Start (activate) one or more units" "stop:Stop (deactivate) one or more units" "reload:Reload one or more units" "restart:Start or restart one or more units" "condrestart:Restart one or more units if active" "try-restart:Restart one or more units if active" "reload-or-restart:Reload one or more units if possible, otherwise start or restart" "force-reload:Reload one or more units if possible, otherwise restart if active" "hibernate:Hibernate the system" "hybrid-sleep:Hibernate and suspend the system" "try-reload-or-restart:Reload one or more units if possible, otherwise restart if active" "isolate:Start one unit and stop all others" "kill:Send signal to processes of a unit" "is-active:Check whether units are active" "is-failed:Check whether units are failed" "status:Show runtime status of one or more units" "show:Show properties of one or more units/jobs or the manager" "cat:Show the source unit files and drop-ins" "reset-failed:Reset failed state for all, one, or more units" "list-unit-files:List installed unit files" "enable:Enable one or more unit files" "disable:Disable one or more unit files" "reenable:Reenable one or more unit files" "preset:Enable/disable one or more unit files based on preset configuration" "set-default:Set the default target" "get-default:Query the default target" "edit:Edit one or more unit files" "is-system-running:Query overall status of the system" "help:Show documentation for specified units" "list-dependencies:Show unit dependency tree" "mask:Mask one or more units" "unmask:Unmask one or more units" "link:Link one or more units files into the search path" "is-enabled:Check whether unit files are enabled" "list-jobs:List jobs" "cancel:Cancel all, one, or more jobs" "show-environment:Dump environment" "set-environment:Set one or more environment variables" "unset-environment:Unset one or more environment variables" "daemon-reload:Reload systemd manager configuration" "daemon-reexec:Reexecute systemd manager" "default:Enter system default mode" "rescue:Enter system rescue mode" "emergency:Enter system emergency mode" "halt:Shut down and halt the system" "suspend:Suspend the system" "poweroff:Shut down and power-off the system" "reboot:Shut down and reboot the system" "kexec:Shut down and reboot the system with kexec" "exit:Ask for user instance termination" "switch-root:Change root directory" ) if (( CURRENT == 1 )); then _describe -t commands 'systemctl command' _systemctl_cmds || compadd "$@" else local curcontext="$curcontext" expl cmd="${${_systemctl_cmds[(r)$words[1]:*]%%:*}}" # Deal with any aliases case $cmd in condrestart) cmd="try-restart";; force-reload) cmd="try-reload-or-restart";; esac if (( $#cmd )); then curcontext="${curcontext%:*:*}:systemctl-${cmd}:" local update_policy zstyle -s ":completion:${curcontext}:" cache-policy update_policy if [[ -z "$update_policy" ]]; then zstyle ":completion:${curcontext}:" cache-policy _systemctl_caching_policy fi _call_function ret _systemctl_$cmd || _message 'no more arguments' else _message "unknown systemctl command: $words[1]" fi return ret fi } __systemctl() { systemctl $_sys_service_mgr --full --no-legend --no-pager "$@" } # Fills the unit list _systemctl_all_units() { if ( [[ ${+_sys_all_units} -eq 0 ]] || _cache_invalid SYS_ALL_UNITS ) && ! _retrieve_cache SYS_ALL_UNITS; then _sys_all_units=( ${${(f)"$(__systemctl list-units --all)"}%% *} ) _store_cache SYS_ALL_UNITS _sys_all_units fi } # Fills the unit list including all file units _systemctl_really_all_units() { local -a all_unit_files; local -a really_all_units; if ( [[ ${+_sys_really_all_units} -eq 0 ]] || _cache_invalid SYS_REALLY_ALL_UNITS ) && ! _retrieve_cache SYS_REALLY_ALL_UNITS; then all_unit_files=( ${${(f)"$(__systemctl list-unit-files)"}%% *} ) _systemctl_all_units really_all_units=($_sys_all_units $all_unit_files) _sys_really_all_units=(${(u)really_all_units}) _store_cache SYS_REALLY_ALL_UNITS _sys_really_all_units fi } _filter_units_by_property() { local property=$1 value=$2 ; shift ; shift local -a units ; units=($*) local props for props in ${(ps:\n\n:)"$(_call_program units "$service show --no-pager --property="Id,$property" -- ${units} 2>/dev/null")"}; do props=(${(f)props}) if [[ "${props[2]}" = "$property=$value" ]]; then echo -E - " ${props[1]#Id=}" fi done } _systemctl_get_template_names() { echo -E - ${^${(M)${(f)"$(__systemctl list-unit-files)"}##*@.[^[:space:]]##}%%@.*}\@ } _systemctl_active_units() {_sys_active_units=( ${${(f)"$(__systemctl list-units)"}%% *} )} _systemctl_startable_units(){ _sys_startable_units=( $( _filter_units_by_property ActiveState inactive $( _filter_units_by_property CanStart yes $( __systemctl $mode list-unit-files --state enabled,disabled,static | \ { while read -r a b; do [[ $a =~ @\. ]] || echo -E - " $a"; done; } __systemctl $mode list-units --state inactive,failed | \ { while read -r a b; do echo -E - " $a"; done; } )) ) ) } _systemctl_restartable_units(){ _sys_restartable_units=( $(_filter_units_by_property CanStart yes $( __systemctl $mode list-unit-files --state enabled,disabled,static | \ { while read -r a b; do [[ $a =~ @\. ]] || echo -E - " $a"; done; } __systemctl $mode list-units | \ { while read -r a b; do echo -E - " $a"; done; } )) ) } _systemctl_failed_units() {_sys_failed_units=( ${${(f)"$(__systemctl list-units --failed)"}%% *} ) } _systemctl_unit_state() { typeset -gA _sys_unit_state; _sys_unit_state=( $(__systemctl list-unit-files) ) } local fun # Completion functions for ALL_UNITS for fun in is-active is-failed is-enabled status show cat mask preset help list-dependencies edit ; do (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() { _systemctl_really_all_units _wanted systemd-units expl unit \ compadd "$@" -a - _sys_really_all_units } done # Completion functions for ENABLED_UNITS (( $+functions[_systemctl_disable] )) || _systemctl_disable() { local _sys_unit_state; _systemctl_unit_state _wanted systemd-units expl 'enabled unit' \ compadd "$@" - ${(k)_sys_unit_state[(R)enabled]} } (( $+functions[_systemctl_reenable] )) || _systemctl_reenable() { local _sys_unit_state; _systemctl_unit_state _wanted systemd-units expl 'enabled/disabled unit' \ compadd "$@" - ${(k)_sys_unit_state[(R)(enabled|disabled)]} $(_systemctl_get_template_names) } # Completion functions for DISABLED_UNITS (( $+functions[_systemctl_enable] )) || _systemctl_enable() { local _sys_unit_state; _systemctl_unit_state _wanted systemd-units expl 'disabled unit' \ compadd "$@" - ${(k)_sys_unit_state[(R)disabled]} $(_systemctl_get_template_names) } # Completion functions for FAILED_UNITS (( $+functions[_systemctl_reset-failed] )) || _systemctl_reset-failed() { local _sys_failed_units; _systemctl_failed_units _wanted systemd-units expl 'failed unit' \ compadd "$@" -a - _sys_failed_units || _message "no failed unit found" } # Completion functions for STARTABLE_UNITS (( $+functions[_systemctl_start] )) || _systemctl_start() { local _sys_startable_units; _systemctl_startable_units _wanted systemd-units expl 'startable unit' \ compadd "$@" - ${_sys_startable_units[*]} $(_systemctl_get_template_names) } # Completion functions for STOPPABLE_UNITS for fun in stop kill try-restart condrestart ; do (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() { local _sys_active_units; _systemctl_active_units _wanted systemd-units expl 'stoppable unit' \ compadd "$@" - $( _filter_units_by_property CanStop yes \ ${_sys_active_units[*]} ) } done # Completion functions for ISOLATABLE_UNITS (( $+functions[_systemctl_isolate] )) || _systemctl_isolate() { _systemctl_all_units _wanted systemd-units expl 'isolatable unit' \ compadd "$@" - $( _filter_units_by_property AllowIsolate yes \ ${_sys_all_units[*]} ) } # Completion functions for RELOADABLE_UNITS for fun in reload try-reload-or-restart force-reload ; do (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() { local _sys_active_units; _systemctl_active_units _wanted systemd-units expl 'reloadable unit' \ compadd "$@" - $( _filter_units_by_property CanReload yes \ ${_sys_active_units[*]} ) } done # Completion functions for RESTARTABLE_UNITS for fun in restart reload-or-restart ; do (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() { local _sys_restartable_units; _systemctl_restartable_units _wanted systemd-units expl 'restartable unit' \ compadd "$@" - ${_sys_restartable_units[*]} $(_systemctl_get_template_names) } done # Completion functions for MASKED_UNITS (( $+functions[_systemctl_unmask] )) || _systemctl_unmask() { local _sys_unit_state; _systemctl_unit_state _wanted systemd-units expl 'masked unit' \ compadd "$@" - ${(k)_sys_unit_state[(R)masked]} || _message "no masked units found" } # Completion functions for JOBS (( $+functions[_systemctl_cancel] )) || _systemctl_cancel() { _wanted systemd-jobs expl job \ compadd "$@" - ${${(f)"$(__systemctl list-jobs)"}%% *} || _message "no jobs found" } # Completion functions for TARGETS (( $+functions[_systemctl_set-default] )) || _systemctl_set-default() { _wanted systemd-targets expl target \ compadd "$@" - ${${(f)"$(__systemctl list-unit-files --type target --all)"}%% *} || _message "no targets found" } # Completion functions for ENVS for fun in set-environment unset-environment ; do (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() { local fun=$0 ; fun=${fun##_systemctl_} local suf if [[ "${fun}" = "set-environment" ]]; then suf='-S=' fi _wanted systemd-environment expl 'environment variable' \ compadd "$@" ${suf} - ${${(f)"$(systemctl show-environment)"}%%=*} } done (( $+functions[_systemctl_link] )) || _systemctl_link() { _sd_unit_files } (( $+functions[_systemctl_switch-root] )) || _systemctl_switch-root() { _files } # no systemctl completion for: # [STANDALONE]='daemon-reexec daemon-reload default # emergency exit halt kexec list-jobs list-units # list-unit-files poweroff reboot rescue show-environment' _systemctl_caching_policy() { local _sysunits local -a oldcache # rebuild if cache is more than a day old oldcache=( "$1"(mh+1) ) (( $#oldcache )) && return 0 _sysunits=(${${(f)"$(__systemctl --all)"}%% *}) if (( $#_sysunits )); then for unit in $_sysunits; do [[ "$unit" -nt "$1" ]] && return 0 done fi return 1 } _unit_states() { local -a _states _states=("${(fo)$(__systemctl --state=help)}") _values -s , "${_states[@]}" } _unit_types() { local -a _types _types=("${(fo)$(__systemctl -t help)}") _values -s , "${_types[@]}" } _unit_properties() { if ( [[ ${+_sys_all_properties} -eq 0 ]] || _cache_invalid SYS_ALL_PROPERTIES ) && ! _retrieve_cache SYS_ALL_PROPERTIES; then _sys_all_properties=( ${${(M)${(f)"$(__systemctl show --all; @rootlibexecdir@/systemd --dump-configuration-items)"}##[[:alnum:]]##=*}%%=*} ) _store_cache SYS_ALL_PROPRTIES _sys_all_properties fi _values -s , "${_sys_all_properties[@]}" } _job_modes() { local -a _modes _modes=(fail replace replace-irreversibly isolate ignore-dependencies ignore-requirements flush) _values -s , "${_modes[@]}" } local -a _modes; _modes=("--user" "--system") local _sys_service_mgr=${${words:*_modes}[(R)(${(j.|.)_modes})]:---system} _arguments -s \ {-h,--help}'[Show help]' \ '--version[Show package version]' \ {-t+,--type=}'[List only units of a particular type]:unit type:_unit_types' \ '--state=[Display units in the specified state]:unit state:_unit_states' \ '--job-mode=[Specify how to deal with other jobs]:mode:_job_modes' \ {-p+,--property=}'[Show only properties by specific name]:unit property:_unit_properties' \ {-a,--all}'[Show all units/properties, including dead/empty ones]' \ '--reverse[Show reverse dependencies]' \ '--after[Show units ordered after]' \ '--before[Show units ordered before]' \ '--failed[Show only failed units]' \ {-l,--full}"[Don't ellipsize unit names on output]" \ '--show-types[When showing sockets, show socket type]' \ {-i,--ignore-inhibitors}'[When executing a job, ignore jobs dependencies]' \ {-q,--quiet}'[Suppress output]' \ '--no-block[Do not wait until operation finished]' \ '--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \ '--no-pager[Do not pipe output into a pager]' \ '--system[Connect to system manager]' \ '--user[Connect to user service manager]' \ "--no-wall[Don't send wall message before halt/power-off/reboot]" \ '--global[Enable/disable unit files globally]' \ "--no-reload[When enabling/disabling unit files, don't reload daemon configuration]" \ '--no-ask-password[Do not ask for system passwords]' \ '--kill-who=[Who to send signal to]:killwho:(main control all)' \ {-s+,--signal=}'[Which signal to send]:signal:_signals' \ {-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \ '--root=[Enable unit files in the specified root directory]:directory:_directories' \ '--runtime[Enable unit files only temporarily until next reboot]' \ {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ {-P,--privileged}'[Acquire privileges before execution]' \ {-n+,--lines=}'[Journal entries to show]:number of entries' \ {-o+,--output=}'[Change journal output mode]:modes:_sd_outputmodes' \ '--firmware-setup[Tell the firmware to show the setup menu on next boot]' \ '--plain[When used with list-dependencies, print output as a list]' \ '*::systemctl command:_systemctl_command' systemd-229/shell-completion/zsh/_systemd000066400000000000000000000073321265713322000207220ustar00rootroot00000000000000#compdef systemd-cat systemd-ask-password systemd-cgls systemd-cgtop systemd-detect-virt systemd-machine-id-setup systemd-notify systemd-tty-ask-password-agent local curcontext="$curcontext" state lstate line case "$service" in systemd-ask-password) _arguments \ {-h,--help}'[Show this help]' \ '--icon=[Icon name]:icon name:' \ '--timeout=[Timeout in sec]:timeout (seconds):' \ '--no-tty[Ask question via agent even on TTY]' \ '--accept-cached[Accept cached passwords]' \ '--multiple[List multiple passwords if available]' ;; systemd-cat) _arguments \ {-h,--help}'[Show this help]' \ '--version[Show package version.]' \ {-t+,--identifier=}'[Set syslog identifier.]:syslog identifier:' \ {-p+,--priority=}'[Set priority value.]:value:({0..7})' \ '--level-prefix=[Control whether level prefix shall be parsed.]:boolean:(1 0)' \ ':Message' ;; systemd-cgls) _arguments \ {-h,--help}'[Show this help]' \ '--version[Show package version]' \ '--no-pager[Do not pipe output into a pager]' \ {-a,--all}'[Show all groups, including empty]' \ '-k[Include kernel threads in output]' \ ':cgroups:(cpuset cpu cpuacct memory devices freezer blkio)' ;; systemd-cgtop) _arguments \ {-h,--help}'[Show this help]' \ '--version[Print version and exit]' \ '(-c -m -i -t)-p[Order by path]' \ '(-c -p -m -i)-t[Order by number of tasks]' \ '(-m -p -i -t)-c[Order by CPU load]' \ '(-c -p -i -t)-m[Order by memory load]' \ '(-c -m -p -t)-i[Order by IO load]' \ {-d+,--delay=}'[Specify delay]:delay:' \ {-n+,--iterations=}'[Run for N iterations before exiting]:number of iterations:' \ {-b,--batch}'[Run in batch mode, accepting no input]' \ '--depth=[Maximum traversal depth]:maximum depth:' ;; systemd-detect-virt) _arguments \ {-h,--help}'[Show this help]' \ '--version[Show package version]' \ {-c,--container}'[Only detect whether we are run in a container]' \ {-v,--vm}'[Only detect whether we are run in a VM]' \ {-q,--quiet}"[Don't output anything, just set return value]" ;; systemd-machine-id-setup) _arguments \ {-h,--help}'[Show this help]' \ '--version[Show package version]' ;; systemd-notify) _arguments \ {-h,--help}'[Show this help]' \ '--version[Show package version]' \ '--ready[Inform the init system about service start-up completion.]' \ '--pid=[Inform the init system about the main PID of the daemon]:daemon main PID:_pids' \ '--status=[Send a free-form status string for the daemon to the init systemd]:status string:' \ '--booted[Returns 0 if the system was booted up with systemd]' ;; systemd-tty-ask-password-agent) _arguments \ {-h,--help}'[Prints a short help text and exits.]' \ '--version[Prints a short version string and exits.]' \ '--list[Lists all currently pending system password requests.]' \ '--query[Process all currently pending system password requests by querying the user on the calling TTY.]' \ '--watch[Continuously process password requests.]' \ '--wall[Forward password requests to wall(1).]' \ '--plymouth[Ask question with plymouth(8).]' \ '--console[Ask question on /dev/console.]' ;; *) _message 'eh?' ;; esac #vim: set ft=zsh sw=4 ts=4 et systemd-229/shell-completion/zsh/_systemd-analyze000066400000000000000000000045331265713322000223630ustar00rootroot00000000000000#compdef systemd-analyze _systemd_analyze_set-log-level() { local -a _levels _levels=(debug info notice warning err crit alert emerg) _describe -t level 'logging level' _levels || compadd "$@" } _systemd_analyze_verify() { _sd_unit_files } _systemd_analyze_command(){ local -a _systemd_analyze_cmds # Descriptions taken from systemd-analyze --help. _systemd_analyze_cmds=( 'time:Print time spent in the kernel before reaching userspace' 'blame:Print list of running units ordered by time to init' 'critical-chain:Print a tree of the time critical chain of units' 'plot:Output SVG graphic showing service initialization' 'dot:Dump dependency graph (in dot(1) format)' 'dump:Dump server status' 'set-log-level:Set systemd log threshold' 'verify:Check unit files for correctness' ) if (( CURRENT == 1 )); then _describe "options" _systemd_analyze_cmds else local curcontext="$curcontext" cmd="${${_systemd_analyze_cmds[(r)$words[1]:*]%%:*}}" if (( $#cmd )); then if (( $+functions[_systemd_analyze_$cmd] )) && (( CURRENT == 2 )); then _systemd_analyze_$cmd else _message "no more options" fi else _message "unknown systemd-analyze command: $words[1]" fi fi } _arguments \ {-h,--help}'[Show help text]' \ '--version[Show package version]' \ '--system[Operate on system systemd instance]' \ '--user[Operate on user systemd instance]' \ '--no-pager[Do not pipe output into a pager]' \ '--man=[Do (not) check for existence of man pages]:boolean:(1 0)' \ '--order[When generating graph for dot, show only order]' \ '--require[When generating graph for dot, show only requirement]' \ '--fuzz=[When printing the tree of the critical chain, print also services, which finished TIMESPAN earlier, than the latest in the branch]:TIMESPAN' \ '--from-pattern=[When generating a dependency graph, filter only origins]:GLOB' \ '--to-pattern=[When generating a dependency graph, filter only destinations]:GLOB' \ {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ {-M+,--machine=}'[Operate on local container]:machine:_sd_machines' \ '*::systemd-analyze commands:_systemd_analyze_command' systemd-229/shell-completion/zsh/_systemd-delta000066400000000000000000000010171265713322000220030ustar00rootroot00000000000000#compdef systemd-delta _delta_type() { local -a _delta_types _delta_types=(masked equivalent redirected overridden unchanged) _values -s , "${_delta_types[@]}" } _arguments \ {-h,--help}'[Show this help]' \ '--version[Show package version]' \ '--no-pager[Do not pipe output into a pager]' \ '--diff=[Show a diff when overridden files differ]:boolean:(1 0)' \ {-t+,--type=}'[Only display a selected set of override types]:types:_delta_type' \ ':SUFFIX:(tmpfiles.d sysctl.d systemd/system)' systemd-229/shell-completion/zsh/_systemd-inhibit000066400000000000000000000020001265713322000223310ustar00rootroot00000000000000#compdef systemd-inhibit _systemd_inhibit_command(){ if (( CURRENT == 1 )); then compset -q _normal else local n=${words[(b:2:i)[^-]*]} if (( n <= CURRENT )); then compset -n $n _alternative \ 'files:file:_files' \ 'commands:command:_normal' && return 0 fi _default fi } _inhibit_what() { local _inhibit _inhibit=(shutdown sleep idle handle-power-key handle-suspend-key handle-hibernate-key handle-lid-switch) _values -s : "${_inhibit[@]}" } _arguments \ {-h,--help}'[Show this help]' \ '--version[Show package version]' \ '--what=[Operations to inhibit]:options:_inhibit_what' \ '--who=[A descriptive string who is inhibiting]:who is inhibiting:' \ '--why=[A descriptive string why is being inhibited]:reason for the lock:' \ '--mode=[One of block or delay]:lock mode:( block delay )' \ '--list[List active inhibitors]' \ '*:commands:_systemd_inhibit_command' systemd-229/shell-completion/zsh/_systemd-nspawn000066400000000000000000000104661265713322000222300ustar00rootroot00000000000000#compdef systemd-nspawn _nspawn-caps(){ local -a _caps _caps=( CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_FSETID CAP_IPC_OWNER CAP_KILL CAP_LEASE CAP_LINUX_IMMUTABLE CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETGID CAP_SETFCAP CAP_SETPCAP CAP_SETUID CAP_SYS_ADMIN CAP_SYS_CHROOT CAP_SYS_NICE CAP_SYS_PTRACE CAP_SYS_TTY_CONFIG CAP_SYS_RESOURCE CAP_SYS_BOOT ) _values -s , 'capabilities' "$_caps[@]" } _arguments \ {-h,--help}'[Show this help.]' \ '--version[Print a short version string and exit.]' \ {--quiet,-q}'[Turns off any status output by the tool itself.]' \ {--directory=,-D+}'[Directory to use as file system root for the namespace container. If omitted the current directory will be used.]:directories:_directories' \ '--template=[Initialize root directory from template directory, if missing.]:template:_directories' \ {--ephemeral,-x}'[Run container with snapshot of root directory, and remove it after exit.]' \ {--image=,-i+}'[Disk image to mount the root directory for the container from.]:disk image: _files' \ {--boot,-b}'[Automatically search for an init binary and invoke it instead of a shell or a user supplied program.]' \ {--user=,-u+}'[Run the command under specified user, create home directory and cd into it.]:user:_users' \ {--machine=,-M+}'[Sets the machine name for this container.]: : _message "container name"' \ '--uuid=[Set the specified uuid for the container.]: : _message "container UUID"' \ {--slice=,-S+}'[Make the container part of the specified slice, instead of the default machine.slice.]: : _message slice' \ '--private-network[Disconnect networking of the container from the host.]' \ '--network-interface=[Assign the specified network interface to the container.]: : _net_interfaces' \ '--network-macvlan=[Create a "macvlan" interface of the specified Ethernet network interface and add it to the container.]: : _net_interfaces' \ '--network-ipvlan=[Create a ipvlan network interface based on an existing network interface to the container.]: : _net_interfaces' \ {--network-veth,-n}'[Create a virtual Ethernet link (veth) between host and container.]' \ '--network-bridge=[Adds the host side of the Ethernet link created with --network-veth to the specified bridge.]: : _net_interfaces' \ {--port=,-p+}'[Expose a container IP port on the host.]: : _message port' \ {--selinux-context=,-Z+}'[Sets the SELinux security context to be used to label processes in the container.]: : _message "SELinux context"' \ {--selinux-apifs-context=,-L+}'[Sets the SELinux security context to be used to label files in the virtual API file systems in the container.]: : _message "SELinux context"' \ '--capability=[List one or more additional capabilities to grant the container.]:capabilities:_nspawn-caps' \ '--drop-capability=[Specify one or more additional capabilities to drop for the containerm]:capabilities:_nspawn-caps' \ "--link-journal=[Control whether the container's journal shall be made visible to the host system.]:options:(no host guest auto)" \ '-j[Equivalent to --link-journal=guest.]' \ '--read-only[Mount the root file system read only for the container.]' \ '--bind=[Bind mount a file or directory from the host into the container.]: : _files' \ '--bind-ro=[Bind mount a file or directory from the host into the container (read-only).]: : _files' \ '--tmpfs=[Mount an empty tmpfs to the specified directory.]: : _files' \ '--setenv=[Specifies an environment variable assignment to pass to the init process in the container, in the format "NAME=VALUE".]: : _message "environment variables"' \ '--share-system[Allows the container to share certain system facilities with the host.]' \ '--register=[Controls whether the container is registered with systemd-machined(8).]:systemd-machined registration:( yes no )' \ '--keep-unit[Instead of creating a transient scope unit to run the container in, simply register the service or scope unit systemd-nspawn has been invoked in with systemd-machined(8).]' \ '--personality=[Control the architecture ("personality") reported by uname(2) in the container.]:architecture:(x86 x86-64)' \ '--volatile=[Run the system in volatile mode.]:volatile:(no yes state)' \ '*:: : _normal' systemd-229/shell-completion/zsh/_systemd-run000066400000000000000000000060121265713322000215160ustar00rootroot00000000000000#compdef systemd-run __systemctl() { local -a _modes _modes=("--user" "--system") systemctl ${words:*_modes} --full --no-legend --no-pager "$@" 2>/dev/null } __get_slices () { __systemctl list-units --all -t slice \ | { while read -r a b; do echo $a; done; }; } __slices () { local -a _slices _slices=(${(fo)"$(__get_slices)"}) typeset -U _slices _describe 'slices' _slices } _arguments \ {-h,--help}'[Show help message]' \ '--version[Show package version]' \ '--user[Run as user unit]' \ {-H+,--host=}'[Operate on remote host]:[user@]host:_sd_hosts_or_user_at_host' \ {-M+,--machine=}'[Operate on local container]:machines:_sd_machines' \ '--scope[Run this as scope rather than service]' \ '--unit=[Run under the specified unit name]:unit name' \ {-p+,--property=}'[Set unit property]:NAME=VALUE:(( \ CPUAccounting= MemoryAccounting= BlockIOAccounting= SendSIGHUP= \ SendSIGKILL= MemoryLimit= CPUShares= BlockIOWeight= User= Group= \ DevicePolicy= KillMode= DeviceAllow= BlockIOReadBandwidth= \ BlockIOWriteBandwidth= BlockIODeviceWeight= Nice= Environment= \ KillSignal= LimitCPU= LimitFSIZE= LimitDATA= LimitSTACK= \ LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC= \ LimitMEMLOCK= LimitLOCKS= LimitSIGPENDING= LimitMSGQUEUE= \ LimitNICE= LimitRTPRIO= LimitRTTIME= PrivateTmp= PrivateDevices= \ PrivateNetwork= NoNewPrivileges= WorkingDirectory= RootDirectory= \ TTYPath= SyslogIdentifier= SyslogLevelPrefix= SyslogLevel= \ SyslogFacility= TimerSlackNSec= OOMScoreAdjust= ReadWriteDirectories= \ ReadOnlyDirectories= InaccessibleDirectories= EnvironmentFile= \ ProtectSystem= ProtectHome= RuntimeDirectory= PassEnvironment= \ ))' \ '--description=[Description for unit]:description' \ '--slice=[Run in the specified slice]:slices:__slices' \ {-r,--remain-after-exit}'[Leave service around until explicitly stopped]' \ '--send-sighup[Send SIGHUP when terminating]' \ '--service-type=[Service type]:type:(simple forking oneshot dbus notify idle)' \ '--uid=[Run as system user]:user:_users' \ '--gid=[Run as system group]:group:_groups' \ '--nice=[Nice level]:nice level' \ '--setenv=[Set environment]:NAME=VALUE' \ '--on-active=[Run after SEC seconds]:SEC' \ '--on-boot=[Run after SEC seconds from machine was booted up]:SEC' \ '--on-statup=[Run after SEC seconds from systemd was first started]:SEC' \ '--on-unit-active=[Run after SEC seconds from the last activation]:SEC' \ '--on-unit-inactive=[Run after SEC seconds from the last deactivation]:SEC' \ '--on-calendar=[Realtime timer]:SPEC' \ '--timer-property=[Set timer unit property]:NAME=VALUE' \ '*::command:_command' systemd-229/shell-completion/zsh/_systemd-tmpfiles000066400000000000000000000012731265713322000225410ustar00rootroot00000000000000#compdef systemd-tmpfiles _arguments \ {-h,--help}'[Show help]' \ '--version[Show package version]' \ '--create[Create, set ownership/permissions based on the config files.]' \ '--clean[Clean up all files and directories with an age parameter configured.]' \ '--remove[All files and directories marked with r, R in the configuration files are removed.]' \ '--boot[Execute actions only safe at boot]' \ '--prefix=[Only apply rules that apply to paths with the specified prefix.]' \ '--exclude-prefix=[Ignore rules that apply to paths with the specified prefix.]' \ '--root=[Operate on an alternate filesystem root]:directory:_directories' \ '*::files:_files' systemd-229/shell-completion/zsh/_timedatectl000066400000000000000000000037251265713322000215330ustar00rootroot00000000000000#compdef timedatectl _timedatectl_set-timezone(){ local -a _timezones _timezones=( ${(f)"$(_call_program timezones "${service}" list-timezones)"} ) compadd "$_timezones[@]" } _timedatectl_set-time(){ _message "YYYY-MM-DD HH:MM:SS" } _timedatectl_set-local-rtc(){ local -a _options _options=( '0:Maintain RTC in universal time' '1:Maintain RTC in local time' ) _describe options _options } _timedatectl_set-ntp(){ local -a _options _options=( '0:Disable NTP based network time configuration' '1:Enable NTP based network time configuration' ) _describe options _options } _timedatectl_command(){ local -a _timedatectl_cmds _timedatectl_cmds=( 'status:Show current time settings' 'set-time:Set system time' 'set-timezone:Set system timezone' 'list-timezones:Show known timezones' 'set-local-rtc:Control whether RTC is in local time' 'set-ntp:Control whether NTP is enabled' ) if (( CURRENT == 1 )); then _describe -t commands 'timedatectl command' _timedatectl_cmds else local curcontext="$curcontext" cmd="${${_timedatectl_cmds[(r)$words[1]:*]%%:*}}" if (( $#cmd )); then if (( $+functions[_timedatectl_$cmd] )); then _timedatectl_$cmd else _message "no more options" fi else _message "unknown timedatectl command: $words[1]" fi fi } _arguments -s \ {-h,--help}'[Show this help]' \ '--version[Show package version]' \ '--adjust-system-clock[Adjust system clock when changing local RTC mode]' \ '--no-pager[Do not pipe output into a pager]' \ '--no-ask-password[Do not prompt for password]' \ {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ {-M+,--machine=}'[Operate on local container]:machines:_sd_machines' \ '*::timedatectl commands:_timedatectl_command' systemd-229/shell-completion/zsh/_udevadm000066400000000000000000000135101265713322000206520ustar00rootroot00000000000000#compdef udevadm _udevadm_info(){ _arguments \ '--query=[Query the database for specified type of device data. It needs the --path or --name to identify the specified device.]:type:(name symlink path property all)' \ '--path=[The devpath of the device to query.]:sys files:_files -P /sys/ -W /sys' \ '--name=[The name of the device node or a symlink to query]:device files:_files -P /dev/ -W /dev' \ '--root[Print absolute paths in name or symlink query.]' \ '--attribute-walk[Print all sysfs properties of the specified device that can be used in udev rules to match the specified device]' \ '--export[Print output as key/value pairs.]' \ '--export-prefix=[Add a prefix to the key name of exported values.]:prefix' \ '--device-id-of-file=[Print major/minor numbers of the underlying device, where the file lives on.]:files:_udevadm_mounts' \ '--export-db[Export the content of the udev database.]' \ '--cleanup-db[Cleanup the udev database.]' } _udevadm_trigger(){ _arguments \ '--verbose[Print the list of devices which will be triggered.]' \ '--dry-run[Do not actually trigger the event.]' \ '--type=[Trigger a specific type of devices.]:types:(devices subsystems failed)' \ '--action=[Type of event to be triggered.]:actions:(add change remove)' \ '--subsystem-match=[Trigger events for devices which belong to a matching subsystem.]' \ '--subsystem-nomatch=[Do not trigger events for devices which belong to a matching subsystem.]' \ '--attr-match=attribute=[Trigger events for devices with a matching sysfs attribute.]' \ '--attr-nomatch=attribute=[Do not trigger events for devices with a matching sysfs attribute.]' \ '--property-match=[Trigger events for devices with a matching property value.]' \ '--tag-match=property[Trigger events for devices with a matching tag.]' \ '--sysname-match=[Trigger events for devices with a matching sys device name.]' \ '--parent-match=[Trigger events for all children of a given device.]' } _udevadm_settle(){ _arguments \ '--timeout=[Maximum number of seconds to wait for the event queue to become empty.]' \ '--seq-start=[Wait only for events after the given sequence number.]' \ '--seq-end=[Wait only for events before the given sequence number.]' \ '--exit-if-exists=[Stop waiting if file exists.]:files:_files' \ '--quiet[Do not print any output, like the remaining queue entries when reaching the timeout.]' \ '--help[Print help text.]' } _udevadm_control(){ _arguments \ '--exit[Signal and wait for systemd-udevd to exit.]' \ '--log-priority=[Set the internal log level of systemd-udevd.]:priorities:(err info debug)' \ '--stop-exec-queue[Signal systemd-udevd to stop executing new events. Incoming events will be queued.]' \ '--start-exec-queue[Signal systemd-udevd to enable the execution of events.]' \ '--reload[Signal systemd-udevd to reload the rules files and other databases like the kernel module index.]' \ '--property=[Set a global property for all events.]' \ '--children-max=[Set the maximum number of events.]' \ '--timeout=[The maximum number of seconds to wait for a reply from systemd-udevd.]' \ '--help[Print help text.]' } _udevadm_monitor(){ _arguments \ '--kernel[Print the kernel uevents.]' \ '--udev[Print the udev event after the rule processing.]' \ '--property[Also print the properties of the event.]' \ '--subsystem-match=[Filter events by subsystem/\[devtype\].]' \ '--tag-match=[Filter events by property.]' \ '--help[Print help text.]' } _udevadm_test(){ _arguments \ '--action=[The action string.]:actions:(add change remove)' \ '--subsystem=[The subsystem string.]' \ '--help[Print help text.]' \ '*::devpath:_files -P /sys/ -W /sys' } _udevadm_test-builtin(){ if (( CURRENT == 2 )); then _arguments \ '--help[Print help text]' \ '*::builtins:(blkid btrfs hwdb input_id net_id net_setup_link kmod path_id usb_id uaccess)' elif (( CURRENT == 3 )); then _arguments \ '--help[Print help text]' \ '*::syspath:_files -P /sys -W /sys' else _arguments \ '--help[Print help text]' fi } _udevadm_mounts(){ local dev_tmp dpath_tmp mp_tmp mline tmp=( "${(@f)$(< /proc/self/mounts)}" ) dev_tmp=( "${(@)${(@)tmp%% *}:#none}" ) mp_tmp=( "${(@)${(@)tmp#* }%% *}" ) local MATCH mp_tmp=("${(@q)mp_tmp//(#m)\\[0-7](#c3)/${(#)$(( 8#${MATCH[2,-1]} ))}}") dpath_tmp=( "${(@Mq)dev_tmp:#/*}" ) dev_tmp=( "${(@q)dev_tmp:#/*}" ) _alternative \ 'device-paths: device path:compadd -a dpath_tmp' \ 'directories:mount point:compadd -a mp_tmp' } _udevadm_command(){ local -a _udevadm_cmds _udevadm_cmds=( 'info:query sysfs or the udev database' 'trigger:request events from the kernel' 'settle:wait for the event queue to finish' 'control:control the udev daemon' 'monitor:listen to kernel and udev events' 'test:test an event run' 'test-builtin:test a built-in command' ) if ((CURRENT == 1)); then _describe -t commands 'udevadm commands' _udevadm_cmds else local curcontext="$curcontext" cmd="${${_udevadm_cmds[(r)$words[1]:*]%%:*}}" if (($#cmd)); then if (( $+functions[_udevadm_$cmd] )); then _udevadm_$cmd else _message "no options for $cmd" fi else _message "no more options" fi fi } _arguments \ '--debug[Print debug messages to stderr]' \ '--version[Print version number]' \ '--help[Print help text]' \ '*::udevadm commands:_udevadm_command' systemd-229/src/000077500000000000000000000000001265713322000136505ustar00rootroot00000000000000systemd-229/src/.gitignore000066400000000000000000000002571265713322000156440ustar00rootroot00000000000000load-fragment-gperf-nulstr.c load-fragment-gperf.c load-fragment-gperf.gperf org.freedesktop.systemd1.policy.in org.freedesktop.systemd1.policy 99-systemd.rules *.gcno *.gcda systemd-229/src/Makefile000066400000000000000000000016761265713322000153220ustar00rootroot00000000000000# This file is part of systemd. # # Copyright 2010 Lennart Poettering # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # This file is a dirty trick to simplify compilation from within # emacs. This file is not intended to be distributed. So, don't touch # it, even better ignore it! all: $(MAKE) -C .. clean: $(MAKE) -C .. clean .PHONY: all clean systemd-229/src/ac-power/000077500000000000000000000000001265713322000153655ustar00rootroot00000000000000systemd-229/src/ac-power/Makefile000077700000000000000000000000001265713322000206732../Makefileustar00rootroot00000000000000systemd-229/src/ac-power/ac-power.c000066400000000000000000000021651265713322000172520ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "util.h" int main(int argc, char *argv[]) { int r; /* This is mostly intended to be used for scripts which want * to detect whether AC power is plugged in or not. */ r = on_ac_power(); if (r < 0) { log_error_errno(r, "Failed to read AC status: %m"); return EXIT_FAILURE; } return r != 0 ? EXIT_SUCCESS : EXIT_FAILURE; } systemd-229/src/activate/000077500000000000000000000000001265713322000154505ustar00rootroot00000000000000systemd-229/src/activate/Makefile000077700000000000000000000000001265713322000207562../Makefileustar00rootroot00000000000000systemd-229/src/activate/activate.c000066400000000000000000000403621265713322000174210ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "sd-daemon.h" #include "alloc-util.h" #include "fd-util.h" #include "log.h" #include "macro.h" #include "signal-util.h" #include "socket-util.h" #include "string-util.h" #include "strv.h" static char** arg_listen = NULL; static bool arg_accept = false; static int arg_socket_type = SOCK_STREAM; static char** arg_args = NULL; static char** arg_setenv = NULL; static const char *arg_fdname = NULL; static bool arg_inetd = false; static int add_epoll(int epoll_fd, int fd) { struct epoll_event ev = { .events = EPOLLIN }; int r; assert(epoll_fd >= 0); assert(fd >= 0); ev.data.fd = fd; r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev); if (r < 0) return log_error_errno(errno, "Failed to add event on epoll fd:%d for fd:%d: %m", epoll_fd, fd); return 0; } static int open_sockets(int *epoll_fd, bool accept) { char **address; int n, fd, r; int count = 0; n = sd_listen_fds(true); if (n < 0) return log_error_errno(n, "Failed to read listening file descriptors from environment: %m"); if (n > 0) { log_info("Received %i descriptors via the environment.", n); for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { r = fd_cloexec(fd, arg_accept); if (r < 0) return r; count ++; } } /* Close logging and all other descriptors */ if (arg_listen) { int except[3 + n]; for (fd = 0; fd < SD_LISTEN_FDS_START + n; fd++) except[fd] = fd; log_close(); close_all_fds(except, 3 + n); } /** Note: we leak some fd's on error here. I doesn't matter * much, since the program will exit immediately anyway, but * would be a pain to fix. */ STRV_FOREACH(address, arg_listen) { fd = make_socket_fd(LOG_DEBUG, *address, arg_socket_type, (arg_accept*SOCK_CLOEXEC)); if (fd < 0) { log_open(); return log_error_errno(fd, "Failed to open '%s': %m", *address); } assert(fd == SD_LISTEN_FDS_START + count); count ++; } if (arg_listen) log_open(); *epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (*epoll_fd < 0) return log_error_errno(errno, "Failed to create epoll object: %m"); for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + count; fd++) { _cleanup_free_ char *name = NULL; getsockname_pretty(fd, &name); log_info("Listening on %s as %i.", strna(name), fd); r = add_epoll(*epoll_fd, fd); if (r < 0) return r; } return count; } static int exec_process(const char* name, char **argv, char **env, int start_fd, int n_fds) { _cleanup_strv_free_ char **envp = NULL; _cleanup_free_ char *joined = NULL; unsigned n_env = 0, length; const char *tocopy; unsigned i; char **s; int r; if (arg_inetd && n_fds != 1) { log_error("--inetd only supported for single file descriptors."); return -EINVAL; } length = strv_length(arg_setenv); /* PATH, TERM, HOME, USER, LISTEN_FDS, LISTEN_PID, LISTEN_FDNAMES, NULL */ envp = new0(char *, length + 8); if (!envp) return log_oom(); STRV_FOREACH(s, arg_setenv) { if (strchr(*s, '=')) { char *k; k = strdup(*s); if (!k) return log_oom(); envp[n_env++] = k; } else { _cleanup_free_ char *p; const char *n; p = strappend(*s, "="); if (!p) return log_oom(); n = strv_find_prefix(env, p); if (!n) continue; envp[n_env] = strdup(n); if (!envp[n_env]) return log_oom(); n_env ++; } } FOREACH_STRING(tocopy, "TERM=", "PATH=", "USER=", "HOME=") { const char *n; n = strv_find_prefix(env, tocopy); if (!n) continue; envp[n_env] = strdup(n); if (!envp[n_env]) return log_oom(); n_env ++; } if (arg_inetd) { assert(n_fds == 1); r = dup2(start_fd, STDIN_FILENO); if (r < 0) return log_error_errno(errno, "Failed to dup connection to stdin: %m"); r = dup2(start_fd, STDOUT_FILENO); if (r < 0) return log_error_errno(errno, "Failed to dup connection to stdout: %m"); start_fd = safe_close(start_fd); } else { if (start_fd != SD_LISTEN_FDS_START) { assert(n_fds == 1); r = dup2(start_fd, SD_LISTEN_FDS_START); if (r < 0) return log_error_errno(errno, "Failed to dup connection: %m"); safe_close(start_fd); start_fd = SD_LISTEN_FDS_START; } if (asprintf((char**)(envp + n_env++), "LISTEN_FDS=%i", n_fds) < 0) return log_oom(); if (asprintf((char**)(envp + n_env++), "LISTEN_PID=" PID_FMT, getpid()) < 0) return log_oom(); if (arg_fdname) { char *e; e = strappend("LISTEN_FDNAMES=", arg_fdname); if (!e) return log_oom(); for (i = 1; i < (unsigned) n_fds; i++) { char *c; c = strjoin(e, ":", arg_fdname, NULL); if (!c) { free(e); return log_oom(); } free(e); e = c; } envp[n_env++] = e; } } joined = strv_join(argv, " "); if (!joined) return log_oom(); log_info("Execing %s (%s)", name, joined); execvpe(name, argv, envp); return log_error_errno(errno, "Failed to execp %s (%s): %m", name, joined); } static int fork_and_exec_process(const char* child, char** argv, char **env, int fd) { _cleanup_free_ char *joined = NULL; pid_t parent_pid, child_pid; joined = strv_join(argv, " "); if (!joined) return log_oom(); parent_pid = getpid(); child_pid = fork(); if (child_pid < 0) return log_error_errno(errno, "Failed to fork: %m"); /* In the child */ if (child_pid == 0) { (void) reset_all_signal_handlers(); (void) reset_signal_mask(); /* Make sure the child goes away when the parent dies */ if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) _exit(EXIT_FAILURE); /* Check whether our parent died before we were able * to set the death signal */ if (getppid() != parent_pid) _exit(EXIT_SUCCESS); exec_process(child, argv, env, fd, 1); _exit(EXIT_FAILURE); } log_info("Spawned %s (%s) as PID %d", child, joined, child_pid); return 0; } static int do_accept(const char* name, char **argv, char **envp, int fd) { _cleanup_free_ char *local = NULL, *peer = NULL; _cleanup_close_ int fd_accepted = -1; fd_accepted = accept4(fd, NULL, NULL, 0); if (fd_accepted < 0) return log_error_errno(errno, "Failed to accept connection on fd:%d: %m", fd); getsockname_pretty(fd_accepted, &local); getpeername_pretty(fd_accepted, true, &peer); log_info("Connection from %s to %s", strna(peer), strna(local)); return fork_and_exec_process(name, argv, envp, fd_accepted); } /* SIGCHLD handler. */ static void sigchld_hdl(int sig, siginfo_t *t, void *data) { PROTECT_ERRNO; log_info("Child %d died with code %d", t->si_pid, t->si_status); /* Wait for a dead child. */ (void) waitpid(t->si_pid, NULL, 0); } static int install_chld_handler(void) { static const struct sigaction act = { .sa_flags = SA_SIGINFO, .sa_sigaction = sigchld_hdl, }; int r; r = sigaction(SIGCHLD, &act, 0); if (r < 0) return log_error_errno(errno, "Failed to install SIGCHLD handler: %m"); return 0; } static void help(void) { printf("%s [OPTIONS...]\n\n" "Listen on sockets and launch child on connection.\n\n" "Options:\n" " -h --help Show this help and exit\n" " --version Print version string and exit\n" " -l --listen=ADDR Listen for raw connections at ADDR\n" " -d --datagram Listen on datagram instead of stream socket\n" " --seqpacket Listen on SOCK_SEQPACKET instead of stream socket\n" " -a --accept Spawn separate child for each connection\n" " -E --setenv=NAME[=VALUE] Pass an environment variable to children\n" " --inetd Enable inetd file descriptor passing protocol\n" "\n" "Note: file descriptors from sd_listen_fds() will be passed through.\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_FDNAME, ARG_SEQPACKET, ARG_INETD, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "datagram", no_argument, NULL, 'd' }, { "seqpacket", no_argument, NULL, ARG_SEQPACKET }, { "listen", required_argument, NULL, 'l' }, { "accept", no_argument, NULL, 'a' }, { "setenv", required_argument, NULL, 'E' }, { "environment", required_argument, NULL, 'E' }, /* legacy alias */ { "fdname", required_argument, NULL, ARG_FDNAME }, { "inetd", no_argument, NULL, ARG_INETD }, {} }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "+hl:aEd", options, NULL)) >= 0) switch(c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case 'l': r = strv_extend(&arg_listen, optarg); if (r < 0) return log_oom(); break; case 'd': if (arg_socket_type == SOCK_SEQPACKET) { log_error("--datagram may not be combined with --seqpacket."); return -EINVAL; } arg_socket_type = SOCK_DGRAM; break; case ARG_SEQPACKET: if (arg_socket_type == SOCK_DGRAM) { log_error("--seqpacket may not be combined with --datagram."); return -EINVAL; } arg_socket_type = SOCK_SEQPACKET; break; case 'a': arg_accept = true; break; case 'E': r = strv_extend(&arg_setenv, optarg); if (r < 0) return log_oom(); break; case ARG_FDNAME: if (!fdname_is_valid(optarg)) { log_error("File descriptor name %s is not valid, refusing.", optarg); return -EINVAL; } arg_fdname = optarg; break; case ARG_INETD: arg_inetd = true; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (optind == argc) { log_error("%s: command to execute is missing.", program_invocation_short_name); return -EINVAL; } if (arg_socket_type == SOCK_DGRAM && arg_accept) { log_error("Datagram sockets do not accept connections. " "The --datagram and --accept options may not be combined."); return -EINVAL; } arg_args = argv + optind; return 1 /* work to do */; } int main(int argc, char **argv, char **envp) { int r, n; int epoll_fd = -1; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; r = install_chld_handler(); if (r < 0) return EXIT_FAILURE; n = open_sockets(&epoll_fd, arg_accept); if (n < 0) return EXIT_FAILURE; if (n == 0) { log_error("No sockets to listen on specified or passed in."); return EXIT_FAILURE; } for (;;) { struct epoll_event event; r = epoll_wait(epoll_fd, &event, 1, -1); if (r < 0) { if (errno == EINTR) continue; log_error_errno(errno, "epoll_wait() failed: %m"); return EXIT_FAILURE; } log_info("Communication attempt on fd %i.", event.data.fd); if (arg_accept) { r = do_accept(argv[optind], argv + optind, envp, event.data.fd); if (r < 0) return EXIT_FAILURE; } else break; } exec_process(argv[optind], argv + optind, envp, SD_LISTEN_FDS_START, n); return EXIT_SUCCESS; } systemd-229/src/analyze/000077500000000000000000000000001265713322000153135ustar00rootroot00000000000000systemd-229/src/analyze/.gitignore000066400000000000000000000000211265713322000172740ustar00rootroot00000000000000/systemd-analyze systemd-229/src/analyze/Makefile000077700000000000000000000000001265713322000206212../Makefileustar00rootroot00000000000000systemd-229/src/analyze/analyze-verify.c000066400000000000000000000214221265713322000204250ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "analyze-verify.h" #include "bus-error.h" #include "bus-util.h" #include "log.h" #include "manager.h" #include "pager.h" #include "path-util.h" #include "strv.h" #include "unit-name.h" static int prepare_filename(const char *filename, char **ret) { int r; const char *name; _cleanup_free_ char *abspath = NULL; _cleanup_free_ char *dir = NULL; _cleanup_free_ char *with_instance = NULL; char *c; assert(filename); assert(ret); r = path_make_absolute_cwd(filename, &abspath); if (r < 0) return r; name = basename(abspath); if (!unit_name_is_valid(name, UNIT_NAME_ANY)) return -EINVAL; if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) { r = unit_name_replace_instance(name, "i", &with_instance); if (r < 0) return r; } dir = dirname_malloc(abspath); if (!dir) return -ENOMEM; if (with_instance) c = path_join(NULL, dir, with_instance); else c = path_join(NULL, dir, name); if (!c) return -ENOMEM; *ret = c; return 0; } static int generate_path(char **var, char **filenames) { char **filename; _cleanup_strv_free_ char **ans = NULL; int r; STRV_FOREACH(filename, filenames) { char *t; t = dirname_malloc(*filename); if (!t) return -ENOMEM; r = strv_consume(&ans, t); if (r < 0) return r; } assert_se(strv_uniq(ans)); r = strv_extend(&ans, ""); if (r < 0) return r; *var = strv_join(ans, ":"); if (!*var) return -ENOMEM; return 0; } static int verify_socket(Unit *u) { int r; assert(u); if (u->type != UNIT_SOCKET) return 0; /* Cannot run this without the service being around */ /* This makes sure instance is created if necessary. */ r = socket_instantiate_service(SOCKET(u)); if (r < 0) { log_unit_error_errno(u, r, "Socket cannot be started, failed to create instance: %m"); return r; } /* This checks both type of sockets */ if (UNIT_ISSET(SOCKET(u)->service)) { Service *service; service = SERVICE(UNIT_DEREF(SOCKET(u)->service)); log_unit_debug(u, "Using %s", UNIT(service)->id); if (UNIT(service)->load_state != UNIT_LOADED) { log_unit_error(u, "Service %s not loaded, %s cannot be started.", UNIT(service)->id, u->id); return -ENOENT; } } return 0; } static int verify_executable(Unit *u, ExecCommand *exec) { if (exec == NULL) return 0; if (access(exec->path, X_OK) < 0) return log_unit_error_errno(u, errno, "Command %s is not executable: %m", exec->path); return 0; } static int verify_executables(Unit *u) { ExecCommand *exec; int r = 0, k; unsigned i; assert(u); exec = u->type == UNIT_SOCKET ? SOCKET(u)->control_command : u->type == UNIT_MOUNT ? MOUNT(u)->control_command : u->type == UNIT_SWAP ? SWAP(u)->control_command : NULL; k = verify_executable(u, exec); if (k < 0 && r == 0) r = k; if (u->type == UNIT_SERVICE) for (i = 0; i < ELEMENTSOF(SERVICE(u)->exec_command); i++) { k = verify_executable(u, SERVICE(u)->exec_command[i]); if (k < 0 && r == 0) r = k; } if (u->type == UNIT_SOCKET) for (i = 0; i < ELEMENTSOF(SOCKET(u)->exec_command); i++) { k = verify_executable(u, SOCKET(u)->exec_command[i]); if (k < 0 && r == 0) r = k; } return r; } static int verify_documentation(Unit *u, bool check_man) { char **p; int r = 0, k; STRV_FOREACH(p, u->documentation) { log_unit_debug(u, "Found documentation item: %s", *p); if (check_man && startswith(*p, "man:")) { k = show_man_page(*p + 4, true); if (k != 0) { if (k < 0) log_unit_error_errno(u, r, "Can't show %s: %m", *p); else { log_unit_error_errno(u, r, "man %s command failed with code %d", *p + 4, k); k = -ENOEXEC; } if (r == 0) r = k; } } } /* Check remote URLs? */ return r; } static int verify_unit(Unit *u, bool check_man) { _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL; int r, k; assert(u); if (log_get_max_level() >= LOG_DEBUG) unit_dump(u, stdout, "\t"); log_unit_debug(u, "Creating %s/start job", u->id); r = manager_add_job(u->manager, JOB_START, u, JOB_REPLACE, &err, NULL); if (r < 0) log_unit_error_errno(u, r, "Failed to create %s/start: %s", u->id, bus_error_message(&err, r)); k = verify_socket(u); if (k < 0 && r == 0) r = k; k = verify_executables(u); if (k < 0 && r == 0) r = k; k = verify_documentation(u, check_man); if (k < 0 && r == 0) r = k; return r; } int verify_units(char **filenames, ManagerRunningAs running_as, bool check_man) { _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL; Manager *m = NULL; FILE *serial = NULL; FDSet *fdset = NULL; _cleanup_free_ char *var = NULL; char **filename; int r = 0, k; Unit *units[strv_length(filenames)]; int i, count = 0; if (strv_isempty(filenames)) return 0; /* set the path */ r = generate_path(&var, filenames); if (r < 0) return log_error_errno(r, "Failed to generate unit load path: %m"); assert_se(set_unit_path(var) >= 0); r = manager_new(running_as, true, &m); if (r < 0) return log_error_errno(r, "Failed to initialize manager: %m"); log_debug("Starting manager..."); r = manager_startup(m, serial, fdset); if (r < 0) { log_error_errno(r, "Failed to start manager: %m"); goto finish; } manager_clear_jobs(m); log_debug("Loading remaining units from the command line..."); STRV_FOREACH(filename, filenames) { _cleanup_free_ char *prepared = NULL; log_debug("Handling %s...", *filename); k = prepare_filename(*filename, &prepared); if (k < 0) { log_error_errno(k, "Failed to prepare filename %s: %m", *filename); if (r == 0) r = k; continue; } k = manager_load_unit(m, NULL, prepared, &err, &units[count]); if (k < 0) { log_error_errno(k, "Failed to load %s: %m", *filename); if (r == 0) r = k; } else count ++; } for (i = 0; i < count; i++) { k = verify_unit(units[i], check_man); if (k < 0 && r == 0) r = k; } finish: manager_free(m); return r; } systemd-229/src/analyze/analyze-verify.h000066400000000000000000000015501265713322000204320ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include #include "path-lookup.h" int verify_units(char **filenames, ManagerRunningAs running_as, bool check_man); systemd-229/src/analyze/analyze.c000066400000000000000000001567001265713322000171330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010-2013 Lennart Poettering Copyright 2013 Simon Peeters systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "analyze-verify.h" #include "bus-error.h" #include "bus-util.h" #include "glob-util.h" #include "hashmap.h" #include "locale-util.h" #include "log.h" #include "pager.h" #include "parse-util.h" #include "special.h" #include "strv.h" #include "strxcpyx.h" #include "terminal-util.h" #include "unit-name.h" #include "util.h" #define SCALE_X (0.1 / 1000.0) /* pixels per us */ #define SCALE_Y (20.0) #define compare(a, b) (((a) > (b))? 1 : (((b) > (a))? -1 : 0)) #define svg(...) printf(__VA_ARGS__) #define svg_bar(class, x1, x2, y) \ svg(" \n", \ (class), \ SCALE_X * (x1), SCALE_Y * (y), \ SCALE_X * ((x2) - (x1)), SCALE_Y - 1.0) #define svg_text(b, x, y, format, ...) \ do { \ svg(" ", (b) ? "left" : "right", SCALE_X * (x) + (b ? 5.0 : -5.0), SCALE_Y * (y) + 14.0); \ svg(format, ## __VA_ARGS__); \ svg("\n"); \ } while(false) static enum dot { DEP_ALL, DEP_ORDER, DEP_REQUIRE } arg_dot = DEP_ALL; static char** arg_dot_from_patterns = NULL; static char** arg_dot_to_patterns = NULL; static usec_t arg_fuzz = 0; static bool arg_no_pager = false; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static char *arg_host = NULL; static bool arg_user = false; static bool arg_man = true; struct boot_times { usec_t firmware_time; usec_t loader_time; usec_t kernel_time; usec_t kernel_done_time; usec_t initrd_time; usec_t userspace_time; usec_t finish_time; usec_t security_start_time; usec_t security_finish_time; usec_t generators_start_time; usec_t generators_finish_time; usec_t unitsload_start_time; usec_t unitsload_finish_time; /* * If we're analyzing the user instance, all timestamps will be offset * by its own start-up timestamp, which may be arbitrarily big. * With "plot", this causes arbitrarily wide output SVG files which almost * completely consist of empty space. Thus we cancel out this offset. * * This offset is subtracted from times above by acquire_boot_times(), * but it still needs to be subtracted from unit-specific timestamps * (so it is stored here for reference). */ usec_t reverse_offset; }; struct unit_times { char *name; usec_t activating; usec_t activated; usec_t deactivated; usec_t deactivating; usec_t time; }; struct host_info { char *hostname; char *kernel_name; char *kernel_release; char *kernel_version; char *os_pretty_name; char *virtualization; char *architecture; }; static void pager_open_if_enabled(void) { if (arg_no_pager) return; pager_open(false); } static int bus_get_uint64_property(sd_bus *bus, const char *path, const char *interface, const char *property, uint64_t *val) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); assert(path); assert(interface); assert(property); assert(val); r = sd_bus_get_property_trivial( bus, "org.freedesktop.systemd1", path, interface, property, &error, 't', val); if (r < 0) { log_error("Failed to parse reply: %s", bus_error_message(&error, -r)); return r; } return 0; } static int bus_get_unit_property_strv(sd_bus *bus, const char *path, const char *property, char ***strv) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); assert(path); assert(property); assert(strv); r = sd_bus_get_property_strv( bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Unit", property, &error, strv); if (r < 0) { log_error("Failed to get unit property %s: %s", property, bus_error_message(&error, -r)); return r; } return 0; } static int compare_unit_time(const void *a, const void *b) { return compare(((struct unit_times *)b)->time, ((struct unit_times *)a)->time); } static int compare_unit_start(const void *a, const void *b) { return compare(((struct unit_times *)a)->activating, ((struct unit_times *)b)->activating); } static void free_unit_times(struct unit_times *t, unsigned n) { struct unit_times *p; for (p = t; p < t + n; p++) free(p->name); free(t); } static void subtract_timestamp(usec_t *a, usec_t b) { assert(a); if (*a > 0) { assert(*a >= b); *a -= b; } } static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) { static struct boot_times times; static bool cached = false; if (cached) goto finish; assert_cc(sizeof(usec_t) == sizeof(uint64_t)); if (bus_get_uint64_property(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "FirmwareTimestampMonotonic", ×.firmware_time) < 0 || bus_get_uint64_property(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "LoaderTimestampMonotonic", ×.loader_time) < 0 || bus_get_uint64_property(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "KernelTimestamp", ×.kernel_time) < 0 || bus_get_uint64_property(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "InitRDTimestampMonotonic", ×.initrd_time) < 0 || bus_get_uint64_property(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UserspaceTimestampMonotonic", ×.userspace_time) < 0 || bus_get_uint64_property(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "FinishTimestampMonotonic", ×.finish_time) < 0 || bus_get_uint64_property(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "SecurityStartTimestampMonotonic", ×.security_start_time) < 0 || bus_get_uint64_property(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "SecurityFinishTimestampMonotonic", ×.security_finish_time) < 0 || bus_get_uint64_property(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "GeneratorsStartTimestampMonotonic", ×.generators_start_time) < 0 || bus_get_uint64_property(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "GeneratorsFinishTimestampMonotonic", ×.generators_finish_time) < 0 || bus_get_uint64_property(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitsLoadStartTimestampMonotonic", ×.unitsload_start_time) < 0 || bus_get_uint64_property(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitsLoadFinishTimestampMonotonic", ×.unitsload_finish_time) < 0) return -EIO; if (times.finish_time <= 0) { log_error("Bootup is not yet finished. Please try again later."); return -EINPROGRESS; } if (arg_user) { /* * User-instance-specific timestamps processing * (see comment to reverse_offset in struct boot_times). */ times.reverse_offset = times.userspace_time; times.firmware_time = times.loader_time = times.kernel_time = times.initrd_time = times.userspace_time = 0; subtract_timestamp(×.finish_time, times.reverse_offset); subtract_timestamp(×.security_start_time, times.reverse_offset); subtract_timestamp(×.security_finish_time, times.reverse_offset); subtract_timestamp(×.generators_start_time, times.reverse_offset); subtract_timestamp(×.generators_finish_time, times.reverse_offset); subtract_timestamp(×.unitsload_start_time, times.reverse_offset); subtract_timestamp(×.unitsload_finish_time, times.reverse_offset); } else { if (times.initrd_time) times.kernel_done_time = times.initrd_time; else times.kernel_done_time = times.userspace_time; } cached = true; finish: *bt = × return 0; } static void free_host_info(struct host_info *hi) { if (!hi) return; free(hi->hostname); free(hi->kernel_name); free(hi->kernel_release); free(hi->kernel_version); free(hi->os_pretty_name); free(hi->virtualization); free(hi->architecture); free(hi); } DEFINE_TRIVIAL_CLEANUP_FUNC(struct host_info*, free_host_info); static int acquire_time_data(sd_bus *bus, struct unit_times **out) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r, c = 0; struct boot_times *boot_times = NULL; struct unit_times *unit_times = NULL; size_t size = 0; UnitInfo u; r = acquire_boot_times(bus, &boot_times); if (r < 0) goto fail; r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "ListUnits", &error, &reply, NULL); if (r < 0) { log_error("Failed to list units: %s", bus_error_message(&error, -r)); goto fail; } r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)"); if (r < 0) { bus_log_parse_error(r); goto fail; } while ((r = bus_parse_unit_info(reply, &u)) > 0) { struct unit_times *t; if (!GREEDY_REALLOC(unit_times, size, c+1)) { r = log_oom(); goto fail; } t = unit_times+c; t->name = NULL; assert_cc(sizeof(usec_t) == sizeof(uint64_t)); if (bus_get_uint64_property(bus, u.unit_path, "org.freedesktop.systemd1.Unit", "InactiveExitTimestampMonotonic", &t->activating) < 0 || bus_get_uint64_property(bus, u.unit_path, "org.freedesktop.systemd1.Unit", "ActiveEnterTimestampMonotonic", &t->activated) < 0 || bus_get_uint64_property(bus, u.unit_path, "org.freedesktop.systemd1.Unit", "ActiveExitTimestampMonotonic", &t->deactivating) < 0 || bus_get_uint64_property(bus, u.unit_path, "org.freedesktop.systemd1.Unit", "InactiveEnterTimestampMonotonic", &t->deactivated) < 0) { r = -EIO; goto fail; } subtract_timestamp(&t->activating, boot_times->reverse_offset); subtract_timestamp(&t->activated, boot_times->reverse_offset); subtract_timestamp(&t->deactivating, boot_times->reverse_offset); subtract_timestamp(&t->deactivated, boot_times->reverse_offset); if (t->activated >= t->activating) t->time = t->activated - t->activating; else if (t->deactivated >= t->activating) t->time = t->deactivated - t->activating; else t->time = 0; if (t->activating == 0) continue; t->name = strdup(u.id); if (t->name == NULL) { r = log_oom(); goto fail; } c++; } if (r < 0) { bus_log_parse_error(r); goto fail; } *out = unit_times; return c; fail: if (unit_times) free_unit_times(unit_times, (unsigned) c); return r; } static int acquire_host_info(sd_bus *bus, struct host_info **hi) { static const struct bus_properties_map hostname_map[] = { { "Hostname", "s", NULL, offsetof(struct host_info, hostname) }, { "KernelName", "s", NULL, offsetof(struct host_info, kernel_name) }, { "KernelRelease", "s", NULL, offsetof(struct host_info, kernel_release) }, { "KernelVersion", "s", NULL, offsetof(struct host_info, kernel_version) }, { "OperatingSystemPrettyName", "s", NULL, offsetof(struct host_info, os_pretty_name) }, {} }; static const struct bus_properties_map manager_map[] = { { "Virtualization", "s", NULL, offsetof(struct host_info, virtualization) }, { "Architecture", "s", NULL, offsetof(struct host_info, architecture) }, {} }; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(free_host_infop) struct host_info *host; int r; host = new0(struct host_info, 1); if (!host) return log_oom(); r = bus_map_all_properties(bus, "org.freedesktop.hostname1", "/org/freedesktop/hostname1", hostname_map, host); if (r < 0) log_debug_errno(r, "Failed to get host information from systemd-hostnamed: %s", bus_error_message(&error, r)); r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", manager_map, host); if (r < 0) return log_error_errno(r, "Failed to get host information from systemd: %s", bus_error_message(&error, r)); *hi = host; host = NULL; return 0; } static int pretty_boot_time(sd_bus *bus, char **_buf) { char ts[FORMAT_TIMESPAN_MAX]; struct boot_times *t; static char buf[4096]; size_t size; char *ptr; int r; r = acquire_boot_times(bus, &t); if (r < 0) return r; ptr = buf; size = sizeof(buf); size = strpcpyf(&ptr, size, "Startup finished in "); if (t->firmware_time) size = strpcpyf(&ptr, size, "%s (firmware) + ", format_timespan(ts, sizeof(ts), t->firmware_time - t->loader_time, USEC_PER_MSEC)); if (t->loader_time) size = strpcpyf(&ptr, size, "%s (loader) + ", format_timespan(ts, sizeof(ts), t->loader_time, USEC_PER_MSEC)); if (t->kernel_time) size = strpcpyf(&ptr, size, "%s (kernel) + ", format_timespan(ts, sizeof(ts), t->kernel_done_time, USEC_PER_MSEC)); if (t->initrd_time > 0) size = strpcpyf(&ptr, size, "%s (initrd) + ", format_timespan(ts, sizeof(ts), t->userspace_time - t->initrd_time, USEC_PER_MSEC)); size = strpcpyf(&ptr, size, "%s (userspace) ", format_timespan(ts, sizeof(ts), t->finish_time - t->userspace_time, USEC_PER_MSEC)); strpcpyf(&ptr, size, "= %s", format_timespan(ts, sizeof(ts), t->firmware_time + t->finish_time, USEC_PER_MSEC)); ptr = strdup(buf); if (!ptr) return log_oom(); *_buf = ptr; return 0; } static void svg_graph_box(double height, double begin, double end) { long long i; /* outside box, fill */ svg("\n", SCALE_X * (end - begin), SCALE_Y * height); for (i = ((long long) (begin / 100000)) * 100000; i <= end; i+=100000) { /* lines for each second */ if (i % 5000000 == 0) svg(" \n" " %.01fs\n", SCALE_X * i, SCALE_X * i, SCALE_Y * height, SCALE_X * i, -5.0, 0.000001 * i); else if (i % 1000000 == 0) svg(" \n" " %.01fs\n", SCALE_X * i, SCALE_X * i, SCALE_Y * height, SCALE_X * i, -5.0, 0.000001 * i); else svg(" \n", SCALE_X * i, SCALE_X * i, SCALE_Y * height); } } static int analyze_plot(sd_bus *bus) { _cleanup_(free_host_infop) struct host_info *host = NULL; struct unit_times *times; struct boot_times *boot; int n, m = 1, y=0; double width; _cleanup_free_ char *pretty_times = NULL; struct unit_times *u; n = acquire_boot_times(bus, &boot); if (n < 0) return n; n = pretty_boot_time(bus, &pretty_times); if (n < 0) return n; n = acquire_host_info(bus, &host); if (n < 0) return n; n = acquire_time_data(bus, ×); if (n <= 0) return n; qsort(times, n, sizeof(struct unit_times), compare_unit_start); width = SCALE_X * (boot->firmware_time + boot->finish_time); if (width < 800.0) width = 800.0; if (boot->firmware_time > boot->loader_time) m++; if (boot->loader_time) { m++; if (width < 1000.0) width = 1000.0; } if (boot->initrd_time) m++; if (boot->kernel_time) m++; for (u = times; u < times + n; u++) { double text_start, text_width; if (u->activating < boot->userspace_time || u->activating > boot->finish_time) { u->name = mfree(u->name); continue; } /* If the text cannot fit on the left side then * increase the svg width so it fits on the right. * TODO: calculate the text width more accurately */ text_width = 8.0 * strlen(u->name); text_start = (boot->firmware_time + u->activating) * SCALE_X; if (text_width > text_start && text_width + text_start > width) width = text_width + text_start; if (u->deactivated > u->activating && u->deactivated <= boot->finish_time && u->activated == 0 && u->deactivating == 0) u->activated = u->deactivating = u->deactivated; if (u->activated < u->activating || u->activated > boot->finish_time) u->activated = boot->finish_time; if (u->deactivating < u->activated || u->activated > boot->finish_time) u->deactivating = boot->finish_time; if (u->deactivated < u->deactivating || u->deactivated > boot->finish_time) u->deactivated = boot->finish_time; m++; } svg("\n" "\n"); svg("\n\n", 80.0 + width, 150.0 + (m * SCALE_Y) + 5 * SCALE_Y /* legend */); /* write some basic info as a comment, including some help */ svg("\n" "\n" "\n" "\n" "\n\n" "\n\n", VERSION); /* style sheet */ svg("\n \n\n\n"); svg("\n"); svg("%s", pretty_times); svg("%s %s (%s %s %s) %s %s", isempty(host->os_pretty_name) ? "Linux" : host->os_pretty_name, strempty(host->hostname), strempty(host->kernel_name), strempty(host->kernel_release), strempty(host->kernel_version), strempty(host->architecture), strempty(host->virtualization)); svg("\n", 20.0 + (SCALE_X * boot->firmware_time)); svg_graph_box(m, -(double) boot->firmware_time, boot->finish_time); if (boot->firmware_time) { svg_bar("firmware", -(double) boot->firmware_time, -(double) boot->loader_time, y); svg_text(true, -(double) boot->firmware_time, y, "firmware"); y++; } if (boot->loader_time) { svg_bar("loader", -(double) boot->loader_time, 0, y); svg_text(true, -(double) boot->loader_time, y, "loader"); y++; } if (boot->kernel_time) { svg_bar("kernel", 0, boot->kernel_done_time, y); svg_text(true, 0, y, "kernel"); y++; } if (boot->initrd_time) { svg_bar("initrd", boot->initrd_time, boot->userspace_time, y); svg_text(true, boot->initrd_time, y, "initrd"); y++; } svg_bar("active", boot->userspace_time, boot->finish_time, y); svg_bar("security", boot->security_start_time, boot->security_finish_time, y); svg_bar("generators", boot->generators_start_time, boot->generators_finish_time, y); svg_bar("unitsload", boot->unitsload_start_time, boot->unitsload_finish_time, y); svg_text(true, boot->userspace_time, y, "systemd"); y++; for (u = times; u < times + n; u++) { char ts[FORMAT_TIMESPAN_MAX]; bool b; if (!u->name) continue; svg_bar("activating", u->activating, u->activated, y); svg_bar("active", u->activated, u->deactivating, y); svg_bar("deactivating", u->deactivating, u->deactivated, y); /* place the text on the left if we have passed the half of the svg width */ b = u->activating * SCALE_X < width / 2; if (u->time) svg_text(b, u->activating, y, "%s (%s)", u->name, format_timespan(ts, sizeof(ts), u->time, USEC_PER_MSEC)); else svg_text(b, u->activating, y, "%s", u->name); y++; } svg("\n"); /* Legend */ svg("\n"); y++; svg_bar("activating", 0, 300000, y); svg_text(true, 400000, y, "Activating"); y++; svg_bar("active", 0, 300000, y); svg_text(true, 400000, y, "Active"); y++; svg_bar("deactivating", 0, 300000, y); svg_text(true, 400000, y, "Deactivating"); y++; svg_bar("security", 0, 300000, y); svg_text(true, 400000, y, "Setting up security module"); y++; svg_bar("generators", 0, 300000, y); svg_text(true, 400000, y, "Generators"); y++; svg_bar("unitsload", 0, 300000, y); svg_text(true, 400000, y, "Loading unit files"); y++; svg("\n\n"); svg("\n"); free_unit_times(times, (unsigned) n); n = 0; return n; } static int list_dependencies_print(const char *name, unsigned int level, unsigned int branches, bool last, struct unit_times *times, struct boot_times *boot) { unsigned int i; char ts[FORMAT_TIMESPAN_MAX], ts2[FORMAT_TIMESPAN_MAX]; for (i = level; i != 0; i--) printf("%s", draw_special_char(branches & (1 << (i-1)) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE)); printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH)); if (times) { if (times->time) printf("%s%s @%s +%s%s", ANSI_HIGHLIGHT_RED, name, format_timespan(ts, sizeof(ts), times->activating - boot->userspace_time, USEC_PER_MSEC), format_timespan(ts2, sizeof(ts2), times->time, USEC_PER_MSEC), ANSI_NORMAL); else if (times->activated > boot->userspace_time) printf("%s @%s", name, format_timespan(ts, sizeof(ts), times->activated - boot->userspace_time, USEC_PER_MSEC)); else printf("%s", name); } else printf("%s", name); printf("\n"); return 0; } static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) { _cleanup_free_ char *path = NULL; assert(bus); assert(name); assert(deps); path = unit_dbus_path_from_name(name); if (path == NULL) return -ENOMEM; return bus_get_unit_property_strv(bus, path, "After", deps); } static Hashmap *unit_times_hashmap; static int list_dependencies_compare(const void *_a, const void *_b) { const char **a = (const char**) _a, **b = (const char**) _b; usec_t usa = 0, usb = 0; struct unit_times *times; times = hashmap_get(unit_times_hashmap, *a); if (times) usa = times->activated; times = hashmap_get(unit_times_hashmap, *b); if (times) usb = times->activated; return usb - usa; } static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int level, char ***units, unsigned int branches) { _cleanup_strv_free_ char **deps = NULL; char **c; int r = 0; usec_t service_longest = 0; int to_print = 0; struct unit_times *times; struct boot_times *boot; if (strv_extend(units, name)) return log_oom(); r = list_dependencies_get_dependencies(bus, name, &deps); if (r < 0) return r; qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare); r = acquire_boot_times(bus, &boot); if (r < 0) return r; STRV_FOREACH(c, deps) { times = hashmap_get(unit_times_hashmap, *c); if (times && times->activated && times->activated <= boot->finish_time && (times->activated >= service_longest || service_longest == 0)) { service_longest = times->activated; break; } } if (service_longest == 0 ) return r; STRV_FOREACH(c, deps) { times = hashmap_get(unit_times_hashmap, *c); if (times && times->activated && times->activated <= boot->finish_time && (service_longest - times->activated) <= arg_fuzz) to_print++; } if (!to_print) return r; STRV_FOREACH(c, deps) { times = hashmap_get(unit_times_hashmap, *c); if (!times || !times->activated || times->activated > boot->finish_time || service_longest - times->activated > arg_fuzz) continue; to_print--; r = list_dependencies_print(*c, level, branches, to_print == 0, times, boot); if (r < 0) return r; if (strv_contains(*units, *c)) { r = list_dependencies_print("...", level + 1, (branches << 1) | (to_print ? 1 : 0), true, NULL, boot); if (r < 0) return r; continue; } r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (to_print ? 1 : 0)); if (r < 0) return r; if (!to_print) break; } return 0; } static int list_dependencies(sd_bus *bus, const char *name) { _cleanup_strv_free_ char **units = NULL; char ts[FORMAT_TIMESPAN_MAX]; struct unit_times *times; int r; const char *id; _cleanup_free_ char *path = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; struct boot_times *boot; assert(bus); path = unit_dbus_path_from_name(name); if (path == NULL) return -ENOMEM; r = sd_bus_get_property( bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Unit", "Id", &error, &reply, "s"); if (r < 0) { log_error("Failed to get ID: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_read(reply, "s", &id); if (r < 0) return bus_log_parse_error(r); times = hashmap_get(unit_times_hashmap, id); r = acquire_boot_times(bus, &boot); if (r < 0) return r; if (times) { if (times->time) printf("%s%s +%s%s\n", ANSI_HIGHLIGHT_RED, id, format_timespan(ts, sizeof(ts), times->time, USEC_PER_MSEC), ANSI_NORMAL); else if (times->activated > boot->userspace_time) printf("%s @%s\n", id, format_timespan(ts, sizeof(ts), times->activated - boot->userspace_time, USEC_PER_MSEC)); else printf("%s\n", id); } return list_dependencies_one(bus, name, 0, &units, 0); } static int analyze_critical_chain(sd_bus *bus, char *names[]) { struct unit_times *times; unsigned int i; Hashmap *h; int n, r; n = acquire_time_data(bus, ×); if (n <= 0) return n; h = hashmap_new(&string_hash_ops); if (!h) return -ENOMEM; for (i = 0; i < (unsigned)n; i++) { r = hashmap_put(h, times[i].name, ×[i]); if (r < 0) return r; } unit_times_hashmap = h; pager_open_if_enabled(); puts("The time after the unit is active or started is printed after the \"@\" character.\n" "The time the unit takes to start is printed after the \"+\" character.\n"); if (!strv_isempty(names)) { char **name; STRV_FOREACH(name, names) list_dependencies(bus, *name); } else list_dependencies(bus, SPECIAL_DEFAULT_TARGET); hashmap_free(h); free_unit_times(times, (unsigned) n); return 0; } static int analyze_blame(sd_bus *bus) { struct unit_times *times; unsigned i; int n; n = acquire_time_data(bus, ×); if (n <= 0) return n; qsort(times, n, sizeof(struct unit_times), compare_unit_time); pager_open_if_enabled(); for (i = 0; i < (unsigned) n; i++) { char ts[FORMAT_TIMESPAN_MAX]; if (times[i].time > 0) printf("%16s %s\n", format_timespan(ts, sizeof(ts), times[i].time, USEC_PER_MSEC), times[i].name); } free_unit_times(times, (unsigned) n); return 0; } static int analyze_time(sd_bus *bus) { _cleanup_free_ char *buf = NULL; int r; r = pretty_boot_time(bus, &buf); if (r < 0) return r; puts(buf); return 0; } static int graph_one_property(sd_bus *bus, const UnitInfo *u, const char* prop, const char *color, char* patterns[], char* from_patterns[], char* to_patterns[]) { _cleanup_strv_free_ char **units = NULL; char **unit; int r; bool match_patterns; assert(u); assert(prop); assert(color); match_patterns = strv_fnmatch(patterns, u->id, 0); if (!strv_isempty(from_patterns) && !match_patterns && !strv_fnmatch(from_patterns, u->id, 0)) return 0; r = bus_get_unit_property_strv(bus, u->unit_path, prop, &units); if (r < 0) return r; STRV_FOREACH(unit, units) { bool match_patterns2; match_patterns2 = strv_fnmatch(patterns, *unit, 0); if (!strv_isempty(to_patterns) && !match_patterns2 && !strv_fnmatch(to_patterns, *unit, 0)) continue; if (!strv_isempty(patterns) && !match_patterns && !match_patterns2) continue; printf("\t\"%s\"->\"%s\" [color=\"%s\"];\n", u->id, *unit, color); } return 0; } static int graph_one(sd_bus *bus, const UnitInfo *u, char *patterns[], char *from_patterns[], char *to_patterns[]) { int r; assert(bus); assert(u); if (IN_SET(arg_dot, DEP_ORDER, DEP_ALL)) { r = graph_one_property(bus, u, "After", "green", patterns, from_patterns, to_patterns); if (r < 0) return r; } if (IN_SET(arg_dot, DEP_REQUIRE, DEP_ALL)) { r = graph_one_property(bus, u, "Requires", "black", patterns, from_patterns, to_patterns); if (r < 0) return r; r = graph_one_property(bus, u, "Requisite", "darkblue", patterns, from_patterns, to_patterns); if (r < 0) return r; r = graph_one_property(bus, u, "Wants", "grey66", patterns, from_patterns, to_patterns); if (r < 0) return r; r = graph_one_property(bus, u, "Conflicts", "red", patterns, from_patterns, to_patterns); if (r < 0) return r; } return 0; } static int expand_patterns(sd_bus *bus, char **patterns, char ***ret) { _cleanup_strv_free_ char **expanded_patterns = NULL; char **pattern; int r; STRV_FOREACH(pattern, patterns) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *unit = NULL, *unit_id = NULL; if (strv_extend(&expanded_patterns, *pattern) < 0) return log_oom(); if (string_is_glob(*pattern)) continue; unit = unit_dbus_path_from_name(*pattern); if (!unit) return log_oom(); r = sd_bus_get_property_string( bus, "org.freedesktop.systemd1", unit, "org.freedesktop.systemd1.Unit", "Id", &error, &unit_id); if (r < 0) return log_error_errno(r, "Failed to get ID: %s", bus_error_message(&error, r)); if (!streq(*pattern, unit_id)) { if (strv_extend(&expanded_patterns, unit_id) < 0) return log_oom(); } } *ret = expanded_patterns; expanded_patterns = NULL; /* do not free */ return 0; } static int dot(sd_bus *bus, char* patterns[]) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_strv_free_ char **expanded_patterns = NULL; _cleanup_strv_free_ char **expanded_from_patterns = NULL; _cleanup_strv_free_ char **expanded_to_patterns = NULL; int r; UnitInfo u; r = expand_patterns(bus, patterns, &expanded_patterns); if (r < 0) return r; r = expand_patterns(bus, arg_dot_from_patterns, &expanded_from_patterns); if (r < 0) return r; r = expand_patterns(bus, arg_dot_to_patterns, &expanded_to_patterns); if (r < 0) return r; r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "ListUnits", &error, &reply, ""); if (r < 0) { log_error("Failed to list units: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)"); if (r < 0) return bus_log_parse_error(r); printf("digraph systemd {\n"); while ((r = bus_parse_unit_info(reply, &u)) > 0) { r = graph_one(bus, &u, expanded_patterns, expanded_from_patterns, expanded_to_patterns); if (r < 0) return r; } if (r < 0) return bus_log_parse_error(r); printf("}\n"); log_info(" Color legend: black = Requires\n" " dark blue = Requisite\n" " dark grey = Wants\n" " red = Conflicts\n" " green = After\n"); if (on_tty()) log_notice("-- You probably want to process this output with graphviz' dot tool.\n" "-- Try a shell pipeline like 'systemd-analyze dot | dot -Tsvg > systemd.svg'!\n"); return 0; } static int dump(sd_bus *bus, char **args) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *text = NULL; int r; if (!strv_isempty(args)) { log_error("Too many arguments."); return -E2BIG; } pager_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Dump", &error, &reply, ""); if (r < 0) return log_error_errno(r, "Failed issue method call: %s", bus_error_message(&error, r)); r = sd_bus_message_read(reply, "s", &text); if (r < 0) return bus_log_parse_error(r); fputs(text, stdout); return 0; } static int set_log_level(sd_bus *bus, char **args) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); assert(args); if (strv_length(args) != 1) { log_error("This command expects one argument only."); return -E2BIG; } r = sd_bus_set_property( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "LogLevel", &error, "s", args[0]); if (r < 0) return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r)); return 0; } static int set_log_target(sd_bus *bus, char **args) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); assert(args); if (strv_length(args) != 1) { log_error("This command expects one argument only."); return -E2BIG; } r = sd_bus_set_property( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "LogTarget", &error, "s", args[0]); if (r < 0) return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r)); return 0; } static void help(void) { pager_open_if_enabled(); printf("%s [OPTIONS...] {COMMAND} ...\n\n" "Profile systemd, show unit dependencies, check unit files.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " --system Operate on system systemd instance\n" " --user Operate on user systemd instance\n" " -H --host=[USER@]HOST Operate on remote host\n" " -M --machine=CONTAINER Operate on local container\n" " --order Show only order in the graph\n" " --require Show only requirement in the graph\n" " --from-pattern=GLOB Show only origins in the graph\n" " --to-pattern=GLOB Show only destinations in the graph\n" " --fuzz=SECONDS Also print also services which finished SECONDS\n" " earlier than the latest in the branch\n" " --man[=BOOL] Do [not] check for existence of man pages\n\n" "Commands:\n" " time Print time spent in the kernel\n" " blame Print list of running units ordered by time to init\n" " critical-chain Print a tree of the time critical chain of units\n" " plot Output SVG graphic showing service initialization\n" " dot Output dependency graph in dot(1) format\n" " set-log-level LEVEL Set logging threshold for manager\n" " set-log-target TARGET Set logging target for manager\n" " dump Output state serialization of service manager\n" " verify FILE... Check unit files for correctness\n" , program_invocation_short_name); /* When updating this list, including descriptions, apply * changes to shell-completion/bash/systemd-analyze and * shell-completion/zsh/_systemd-analyze too. */ } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_ORDER, ARG_REQUIRE, ARG_USER, ARG_SYSTEM, ARG_DOT_FROM_PATTERN, ARG_DOT_TO_PATTERN, ARG_FUZZ, ARG_NO_PAGER, ARG_MAN, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "order", no_argument, NULL, ARG_ORDER }, { "require", no_argument, NULL, ARG_REQUIRE }, { "user", no_argument, NULL, ARG_USER }, { "system", no_argument, NULL, ARG_SYSTEM }, { "from-pattern", required_argument, NULL, ARG_DOT_FROM_PATTERN }, { "to-pattern", required_argument, NULL, ARG_DOT_TO_PATTERN }, { "fuzz", required_argument, NULL, ARG_FUZZ }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "man", optional_argument, NULL, ARG_MAN }, { "host", required_argument, NULL, 'H' }, { "machine", required_argument, NULL, 'M' }, {} }; int r, c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_USER: arg_user = true; break; case ARG_SYSTEM: arg_user = false; break; case ARG_ORDER: arg_dot = DEP_ORDER; break; case ARG_REQUIRE: arg_dot = DEP_REQUIRE; break; case ARG_DOT_FROM_PATTERN: if (strv_extend(&arg_dot_from_patterns, optarg) < 0) return log_oom(); break; case ARG_DOT_TO_PATTERN: if (strv_extend(&arg_dot_to_patterns, optarg) < 0) return log_oom(); break; case ARG_FUZZ: r = parse_sec(optarg, &arg_fuzz); if (r < 0) return r; break; case ARG_NO_PAGER: arg_no_pager = true; break; case 'H': arg_transport = BUS_TRANSPORT_REMOTE; arg_host = optarg; break; case 'M': arg_transport = BUS_TRANSPORT_MACHINE; arg_host = optarg; break; case ARG_MAN: if (optarg) { r = parse_boolean(optarg); if (r < 0) { log_error("Failed to parse --man= argument."); return -EINVAL; } arg_man = !!r; } else arg_man = true; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option code."); } return 1; /* work to do */ } int main(int argc, char *argv[]) { int r; setlocale(LC_ALL, ""); setlocale(LC_NUMERIC, "C"); /* we want to format/parse floats in C style */ log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; if (streq_ptr(argv[optind], "verify")) r = verify_units(argv+optind+1, arg_user ? MANAGER_USER : MANAGER_SYSTEM, arg_man); else { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; } if (!argv[optind] || streq(argv[optind], "time")) r = analyze_time(bus); else if (streq(argv[optind], "blame")) r = analyze_blame(bus); else if (streq(argv[optind], "critical-chain")) r = analyze_critical_chain(bus, argv+optind+1); else if (streq(argv[optind], "plot")) r = analyze_plot(bus); else if (streq(argv[optind], "dot")) r = dot(bus, argv+optind+1); else if (streq(argv[optind], "dump")) r = dump(bus, argv+optind+1); else if (streq(argv[optind], "set-log-level")) r = set_log_level(bus, argv+optind+1); else if (streq(argv[optind], "set-log-target")) r = set_log_target(bus, argv+optind+1); else log_error("Unknown operation '%s'.", argv[optind]); } finish: pager_close(); strv_free(arg_dot_from_patterns); strv_free(arg_dot_to_patterns); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/ask-password/000077500000000000000000000000001265713322000162665ustar00rootroot00000000000000systemd-229/src/ask-password/Makefile000077700000000000000000000000001265713322000215742../Makefileustar00rootroot00000000000000systemd-229/src/ask-password/ask-password.c000066400000000000000000000132411265713322000210510ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "ask-password-api.h" #include "def.h" #include "log.h" #include "macro.h" #include "strv.h" static const char *arg_icon = NULL; static const char *arg_id = NULL; static const char *arg_keyname = NULL; static char *arg_message = NULL; static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC; static bool arg_multiple = false; static AskPasswordFlags arg_flags = ASK_PASSWORD_PUSH_CACHE; static void help(void) { printf("%s [OPTIONS...] MESSAGE\n\n" "Query the user for a system passphrase, via the TTY or an UI agent.\n\n" " -h --help Show this help\n" " --icon=NAME Icon name\n" " --id=ID Query identifier (e.g. \"cryptsetup:/dev/sda5\")\n" " --keyname=NAME Kernel key name for caching passwords (e.g. \"cryptsetup\")\n" " --timeout=SEC Timeout in seconds\n" " --echo Do not mask input (useful for usernames)\n" " --no-tty Ask question via agent even on TTY\n" " --accept-cached Accept cached passwords\n" " --multiple List multiple passwords if available\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_ICON = 0x100, ARG_TIMEOUT, ARG_ECHO, ARG_NO_TTY, ARG_ACCEPT_CACHED, ARG_MULTIPLE, ARG_ID, ARG_KEYNAME, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "icon", required_argument, NULL, ARG_ICON }, { "timeout", required_argument, NULL, ARG_TIMEOUT }, { "echo", no_argument, NULL, ARG_ECHO }, { "no-tty", no_argument, NULL, ARG_NO_TTY }, { "accept-cached", no_argument, NULL, ARG_ACCEPT_CACHED }, { "multiple", no_argument, NULL, ARG_MULTIPLE }, { "id", required_argument, NULL, ARG_ID }, { "keyname", required_argument, NULL, ARG_KEYNAME }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_ICON: arg_icon = optarg; break; case ARG_TIMEOUT: if (parse_sec(optarg, &arg_timeout) < 0) { log_error("Failed to parse --timeout parameter %s", optarg); return -EINVAL; } break; case ARG_ECHO: arg_flags |= ASK_PASSWORD_ECHO; break; case ARG_NO_TTY: arg_flags |= ASK_PASSWORD_NO_TTY; break; case ARG_ACCEPT_CACHED: arg_flags |= ASK_PASSWORD_ACCEPT_CACHED; break; case ARG_MULTIPLE: arg_multiple = true; break; case ARG_ID: arg_id = optarg; break; case ARG_KEYNAME: arg_keyname = optarg; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (argc > optind) { arg_message = strv_join(argv + optind, " "); if (!arg_message) return log_oom(); } return 1; } int main(int argc, char *argv[]) { _cleanup_strv_free_erase_ char **l = NULL; usec_t timeout; char **p; int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; if (arg_timeout > 0) timeout = now(CLOCK_MONOTONIC) + arg_timeout; else timeout = 0; r = ask_password_auto(arg_message, arg_icon, arg_id, arg_keyname, timeout, arg_flags, &l); if (r < 0) { log_error_errno(r, "Failed to query password: %m"); goto finish; } STRV_FOREACH(p, l) { puts(*p); if (!arg_multiple) break; } finish: free(arg_message); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/backlight/000077500000000000000000000000001265713322000156005ustar00rootroot00000000000000systemd-229/src/backlight/Makefile000077700000000000000000000000001265713322000211062../Makefileustar00rootroot00000000000000systemd-229/src/backlight/backlight.c000066400000000000000000000361521265713322000177030ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "libudev.h" #include "alloc-util.h" #include "def.h" #include "escape.h" #include "fileio.h" #include "mkdir.h" #include "parse-util.h" #include "proc-cmdline.h" #include "string-util.h" #include "udev-util.h" #include "util.h" static struct udev_device *find_pci_or_platform_parent(struct udev_device *device) { struct udev_device *parent; const char *subsystem, *sysname; assert(device); parent = udev_device_get_parent(device); if (!parent) return NULL; subsystem = udev_device_get_subsystem(parent); if (!subsystem) return NULL; sysname = udev_device_get_sysname(parent); if (!sysname) return NULL; if (streq(subsystem, "drm")) { const char *c; c = startswith(sysname, "card"); if (!c) return NULL; c += strspn(c, DIGITS); if (*c == '-') { /* A connector DRM device, let's ignore all but LVDS and eDP! */ if (!startswith(c, "-LVDS-") && !startswith(c, "-Embedded DisplayPort-")) return NULL; } } else if (streq(subsystem, "pci")) { const char *value; value = udev_device_get_sysattr_value(parent, "class"); if (value) { unsigned long class = 0; if (safe_atolu(value, &class) < 0) { log_warning("Cannot parse PCI class %s of device %s:%s.", value, subsystem, sysname); return NULL; } /* Graphics card */ if (class == 0x30000) return parent; } } else if (streq(subsystem, "platform")) return parent; return find_pci_or_platform_parent(parent); } static bool same_device(struct udev_device *a, struct udev_device *b) { assert(a); assert(b); if (!streq_ptr(udev_device_get_subsystem(a), udev_device_get_subsystem(b))) return false; if (!streq_ptr(udev_device_get_sysname(a), udev_device_get_sysname(b))) return false; return true; } static bool validate_device(struct udev *udev, struct udev_device *device) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *enumerate = NULL; struct udev_list_entry *item = NULL, *first = NULL; struct udev_device *parent; const char *v, *subsystem; int r; assert(udev); assert(device); /* Verify whether we should actually care for a specific * backlight device. For backlight devices there might be * multiple ways to access the same control: "firmware" * (i.e. ACPI), "platform" (i.e. via the machine's EC) and * "raw" (via the graphics card). In general we should prefer * "firmware" (i.e. ACPI) or "platform" access over "raw" * access, in order not to confuse the BIOS/EC, and * compatibility with possible low-level hotkey handling of * screen brightness. The kernel will already make sure to * expose only one of "firmware" and "platform" for the same * device to userspace. However, we still need to make sure * that we use "raw" only if no "firmware" or "platform" * device for the same device exists. */ subsystem = udev_device_get_subsystem(device); if (!streq_ptr(subsystem, "backlight")) return true; v = udev_device_get_sysattr_value(device, "type"); if (!streq_ptr(v, "raw")) return true; parent = find_pci_or_platform_parent(device); if (!parent) return true; subsystem = udev_device_get_subsystem(parent); if (!subsystem) return true; enumerate = udev_enumerate_new(udev); if (!enumerate) return true; r = udev_enumerate_add_match_subsystem(enumerate, "backlight"); if (r < 0) return true; r = udev_enumerate_scan_devices(enumerate); if (r < 0) return true; first = udev_enumerate_get_list_entry(enumerate); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *other; struct udev_device *other_parent; const char *other_subsystem; other = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!other) return true; if (same_device(device, other)) continue; v = udev_device_get_sysattr_value(other, "type"); if (!streq_ptr(v, "platform") && !streq_ptr(v, "firmware")) continue; /* OK, so there's another backlight device, and it's a * platform or firmware device, so, let's see if we * can verify it belongs to the same device as * ours. */ other_parent = find_pci_or_platform_parent(other); if (!other_parent) continue; if (same_device(parent, other_parent)) { /* Both have the same PCI parent, that means * we are out. */ log_debug("Skipping backlight device %s, since device %s is on same PCI device and takes precedence.", udev_device_get_sysname(device), udev_device_get_sysname(other)); return false; } other_subsystem = udev_device_get_subsystem(other_parent); if (streq_ptr(other_subsystem, "platform") && streq_ptr(subsystem, "pci")) { /* The other is connected to the platform bus * and we are a PCI device, that also means we * are out. */ log_debug("Skipping backlight device %s, since device %s is a platform device and takes precedence.", udev_device_get_sysname(device), udev_device_get_sysname(other)); return false; } } return true; } static unsigned get_max_brightness(struct udev_device *device) { int r; const char *max_brightness_str; unsigned max_brightness; max_brightness_str = udev_device_get_sysattr_value(device, "max_brightness"); if (!max_brightness_str) { log_warning("Failed to read 'max_brightness' attribute."); return 0; } r = safe_atou(max_brightness_str, &max_brightness); if (r < 0) { log_warning_errno(r, "Failed to parse 'max_brightness' \"%s\": %m", max_brightness_str); return 0; } if (max_brightness <= 0) { log_warning("Maximum brightness is 0, ignoring device."); return 0; } return max_brightness; } /* Some systems turn the backlight all the way off at the lowest levels. * clamp_brightness clamps the saved brightness to at least 1 or 5% of * max_brightness in case of 'backlight' subsystem. This avoids preserving * an unreadably dim screen, which would otherwise force the user to * disable state restoration. */ static void clamp_brightness(struct udev_device *device, char **value, unsigned max_brightness) { int r; unsigned brightness, new_brightness, min_brightness; const char *subsystem; r = safe_atou(*value, &brightness); if (r < 0) { log_warning_errno(r, "Failed to parse brightness \"%s\": %m", *value); return; } subsystem = udev_device_get_subsystem(device); if (streq_ptr(subsystem, "backlight")) min_brightness = MAX(1U, max_brightness/20); else min_brightness = 0; new_brightness = CLAMP(brightness, min_brightness, max_brightness); if (new_brightness != brightness) { char *old_value = *value; r = asprintf(value, "%u", new_brightness); if (r < 0) { log_oom(); return; } log_info("Saved brightness %s %s to %s.", old_value, new_brightness > brightness ? "too low; increasing" : "too high; decreasing", *value); free(old_value); } } int main(int argc, char *argv[]) { _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_udev_device_unref_ struct udev_device *device = NULL; _cleanup_free_ char *saved = NULL, *ss = NULL, *escaped_ss = NULL, *escaped_sysname = NULL, *escaped_path_id = NULL; const char *sysname, *path_id; unsigned max_brightness; int r; if (argc != 3) { log_error("This program requires two arguments."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); r = mkdir_p("/var/lib/systemd/backlight", 0755); if (r < 0) { log_error_errno(r, "Failed to create backlight directory /var/lib/systemd/backlight: %m"); return EXIT_FAILURE; } udev = udev_new(); if (!udev) { log_oom(); return EXIT_FAILURE; } sysname = strchr(argv[2], ':'); if (!sysname) { log_error("Requires a subsystem and sysname pair specifying a backlight device."); return EXIT_FAILURE; } ss = strndup(argv[2], sysname - argv[2]); if (!ss) { log_oom(); return EXIT_FAILURE; } sysname++; if (!streq(ss, "backlight") && !streq(ss, "leds")) { log_error("Not a backlight or LED device: '%s:%s'", ss, sysname); return EXIT_FAILURE; } errno = 0; device = udev_device_new_from_subsystem_sysname(udev, ss, sysname); if (!device) { if (errno > 0) log_error_errno(errno, "Failed to get backlight or LED device '%s:%s': %m", ss, sysname); else log_oom(); return EXIT_FAILURE; } /* If max_brightness is 0, then there is no actual backlight * device. This happens on desktops with Asus mainboards * that load the eeepc-wmi module. */ max_brightness = get_max_brightness(device); if (max_brightness == 0) return EXIT_SUCCESS; escaped_ss = cescape(ss); if (!escaped_ss) { log_oom(); return EXIT_FAILURE; } escaped_sysname = cescape(sysname); if (!escaped_sysname) { log_oom(); return EXIT_FAILURE; } path_id = udev_device_get_property_value(device, "ID_PATH"); if (path_id) { escaped_path_id = cescape(path_id); if (!escaped_path_id) { log_oom(); return EXIT_FAILURE; } saved = strjoin("/var/lib/systemd/backlight/", escaped_path_id, ":", escaped_ss, ":", escaped_sysname, NULL); } else saved = strjoin("/var/lib/systemd/backlight/", escaped_ss, ":", escaped_sysname, NULL); if (!saved) { log_oom(); return EXIT_FAILURE; } /* If there are multiple conflicting backlight devices, then * their probing at boot-time might happen in any order. This * means the validity checking of the device then is not * reliable, since it might not see other devices conflicting * with a specific backlight. To deal with this, we will * actively delete backlight state files at shutdown (where * device probing should be complete), so that the validity * check at boot time doesn't have to be reliable. */ if (streq(argv[1], "load")) { _cleanup_free_ char *value = NULL; const char *clamp; if (shall_restore_state() == 0) return EXIT_SUCCESS; if (!validate_device(udev, device)) return EXIT_SUCCESS; r = read_one_line_file(saved, &value); if (r < 0) { if (r == -ENOENT) return EXIT_SUCCESS; log_error_errno(r, "Failed to read %s: %m", saved); return EXIT_FAILURE; } clamp = udev_device_get_property_value(device, "ID_BACKLIGHT_CLAMP"); if (!clamp || parse_boolean(clamp) != 0) /* default to clamping */ clamp_brightness(device, &value, max_brightness); r = udev_device_set_sysattr_value(device, "brightness", value); if (r < 0) { log_error_errno(r, "Failed to write system 'brightness' attribute: %m"); return EXIT_FAILURE; } } else if (streq(argv[1], "save")) { const char *value; if (!validate_device(udev, device)) { unlink(saved); return EXIT_SUCCESS; } value = udev_device_get_sysattr_value(device, "brightness"); if (!value) { log_error("Failed to read system 'brightness' attribute"); return EXIT_FAILURE; } r = write_string_file(saved, value, WRITE_STRING_FILE_CREATE); if (r < 0) { log_error_errno(r, "Failed to write %s: %m", saved); return EXIT_FAILURE; } } else { log_error("Unknown verb %s.", argv[1]); return EXIT_FAILURE; } return EXIT_SUCCESS; } systemd-229/src/basic/000077500000000000000000000000001265713322000147315ustar00rootroot00000000000000systemd-229/src/basic/.gitignore000066400000000000000000000004341265713322000167220ustar00rootroot00000000000000/cap-from-name.gperf /cap-from-name.h /cap-list.txt /cap-to-name.h /errno-from-name.gperf /errno-from-name.h /errno-list.txt /errno-to-name.h /af-from-name.gperf /af-from-name.h /af-list.txt /af-to-name.h /arphrd-from-name.gperf /arphrd-from-name.h /arphrd-list.txt /arphrd-to-name.h systemd-229/src/basic/Makefile000077700000000000000000000000001265713322000202372../Makefileustar00rootroot00000000000000systemd-229/src/basic/MurmurHash2.c000066400000000000000000000035351265713322000172600ustar00rootroot00000000000000//----------------------------------------------------------------------------- // MurmurHash2 was written by Austin Appleby, and is placed in the public // domain. The author hereby disclaims copyright to this source code. // Note - This code makes a few assumptions about how your machine behaves - // 1. We can read a 4-byte value from any address without crashing // 2. sizeof(int) == 4 // And it has a few limitations - // 1. It will not work incrementally. // 2. It will not produce the same results on little-endian and big-endian // machines. #include "MurmurHash2.h" //----------------------------------------------------------------------------- // Platform-specific functions and macros // Microsoft Visual Studio #if defined(_MSC_VER) #define BIG_CONSTANT(x) (x) // Other compilers #else // defined(_MSC_VER) #define BIG_CONSTANT(x) (x##LLU) #endif // !defined(_MSC_VER) //----------------------------------------------------------------------------- uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed ) { // 'm' and 'r' are mixing constants generated offline. // They're not really 'magic', they just happen to work well. const uint32_t m = 0x5bd1e995; const int r = 24; // Initialize the hash to a 'random' value uint32_t h = seed ^ len; // Mix 4 bytes at a time into the hash const unsigned char * data = (const unsigned char *)key; while(len >= 4) { uint32_t k = *(uint32_t*)data; k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; data += 4; len -= 4; } // Handle the last few bytes of the input array switch(len) { case 3: h ^= data[2] << 16; case 2: h ^= data[1] << 8; case 1: h ^= data[0]; h *= m; }; // Do a few final mixes of the hash to ensure the last few // bytes are well-incorporated. h ^= h >> 13; h *= m; h ^= h >> 15; return h; } systemd-229/src/basic/MurmurHash2.h000066400000000000000000000016151265713322000172620ustar00rootroot00000000000000//----------------------------------------------------------------------------- // MurmurHash2 was written by Austin Appleby, and is placed in the public // domain. The author hereby disclaims copyright to this source code. #ifndef _MURMURHASH2_H_ #define _MURMURHASH2_H_ //----------------------------------------------------------------------------- // Platform-specific functions and macros // Microsoft Visual Studio #if defined(_MSC_VER) typedef unsigned char uint8_t; typedef unsigned long uint32_t; typedef unsigned __int64 uint64_t; // Other compilers #else // defined(_MSC_VER) #include #endif // !defined(_MSC_VER) //----------------------------------------------------------------------------- uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed ); //----------------------------------------------------------------------------- #endif // _MURMURHASH2_H_ systemd-229/src/basic/af-list.c000066400000000000000000000026121265713322000164350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "af-list.h" #include "macro.h" static const struct af_name* lookup_af(register const char *str, register unsigned int len); #include "af-from-name.h" #include "af-to-name.h" const char *af_to_name(int id) { if (id <= 0) return NULL; if (id >= (int) ELEMENTSOF(af_names)) return NULL; return af_names[id]; } int af_from_name(const char *name) { const struct af_name *sc; assert(name); sc = lookup_af(name, strlen(name)); if (!sc) return AF_UNSPEC; return sc->id; } int af_max(void) { return ELEMENTSOF(af_names); } systemd-229/src/basic/af-list.h000066400000000000000000000014641265713322000164460ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ const char *af_to_name(int id); int af_from_name(const char *name); int af_max(void); systemd-229/src/basic/alloc-util.c000066400000000000000000000036671265713322000171560ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "macro.h" #include "util.h" void* memdup(const void *p, size_t l) { void *r; assert(p); r = malloc(l); if (!r) return NULL; memcpy(r, p, l); return r; } void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) { size_t a, newalloc; void *q; assert(p); assert(allocated); if (*allocated >= need) return *p; newalloc = MAX(need * 2, 64u / size); a = newalloc * size; /* check for overflows */ if (a < size * need) return NULL; q = realloc(*p, a); if (!q) return NULL; *p = q; *allocated = newalloc; return q; } void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) { size_t prev; uint8_t *q; assert(p); assert(allocated); prev = *allocated; q = greedy_realloc(p, allocated, need, size); if (!q) return NULL; if (*allocated > prev) memzero(q + prev * size, (*allocated - prev) * size); return q; } systemd-229/src/basic/alloc-util.h000066400000000000000000000074261265713322000171600ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "macro.h" #define new(t, n) ((t*) malloc_multiply(sizeof(t), (n))) #define new0(t, n) ((t*) calloc((n), sizeof(t))) #define newa(t, n) ((t*) alloca(sizeof(t)*(n))) #define newa0(t, n) ((t*) alloca0(sizeof(t)*(n))) #define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n))) #define malloc0(n) (calloc(1, (n))) static inline void *mfree(void *memory) { free(memory); return NULL; } void* memdup(const void *p, size_t l) _alloc_(2); static inline void freep(void *p) { free(*(void**) p); } #define _cleanup_free_ _cleanup_(freep) _malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) { if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) return NULL; return malloc(a * b); } _alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) { if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) return NULL; return realloc(p, a * b); } _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_t b) { if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) return NULL; return memdup(p, a * b); } void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size); void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); #define GREEDY_REALLOC(array, allocated, need) \ greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0])) #define GREEDY_REALLOC0(array, allocated, need) \ greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0])) #define alloca0(n) \ ({ \ char *_new_; \ size_t _len_ = n; \ _new_ = alloca(_len_); \ (void *) memset(_new_, 0, _len_); \ }) /* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */ #define alloca_align(size, align) \ ({ \ void *_ptr_; \ size_t _mask_ = (align) - 1; \ _ptr_ = alloca((size) + _mask_); \ (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \ }) #define alloca0_align(size, align) \ ({ \ void *_new_; \ size_t _size_ = (size); \ _new_ = alloca_align(_size_, (align)); \ (void*)memset(_new_, 0, _size_); \ }) systemd-229/src/basic/arphrd-list.c000066400000000000000000000026661265713322000173400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "arphrd-list.h" #include "macro.h" static const struct arphrd_name* lookup_arphrd(register const char *str, register unsigned int len); #include "arphrd-from-name.h" #include "arphrd-to-name.h" const char *arphrd_to_name(int id) { if (id <= 0) return NULL; if (id >= (int) ELEMENTSOF(arphrd_names)) return NULL; return arphrd_names[id]; } int arphrd_from_name(const char *name) { const struct arphrd_name *sc; assert(name); sc = lookup_arphrd(name, strlen(name)); if (!sc) return 0; return sc->id; } int arphrd_max(void) { return ELEMENTSOF(arphrd_names); } systemd-229/src/basic/arphrd-list.h000066400000000000000000000015001265713322000173270ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ const char *arphrd_to_name(int id); int arphrd_from_name(const char *name); int arphrd_max(void); systemd-229/src/basic/async.c000066400000000000000000000051531265713322000162160ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "async.h" #include "fd-util.h" #include "log.h" #include "macro.h" #include "util.h" int asynchronous_job(void* (*func)(void *p), void *arg) { pthread_attr_t a; pthread_t t; int r; /* It kinda sucks that we have to resort to threads to * implement an asynchronous sync(), but well, such is * life. * * Note that issuing this command right before exiting a * process will cause the process to wait for the sync() to * complete. This function hence is nicely asynchronous really * only in long running processes. */ r = pthread_attr_init(&a); if (r > 0) return -r; r = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED); if (r > 0) goto finish; r = pthread_create(&t, &a, func, arg); finish: pthread_attr_destroy(&a); return -r; } static void *sync_thread(void *p) { sync(); return NULL; } int asynchronous_sync(void) { log_debug("Spawning new thread for sync"); return asynchronous_job(sync_thread, NULL); } static void *close_thread(void *p) { assert_se(close_nointr(PTR_TO_FD(p)) != -EBADF); return NULL; } int asynchronous_close(int fd) { int r; /* This is supposed to behave similar to safe_close(), but * actually invoke close() asynchronously, so that it will * never block. Ideally the kernel would have an API for this, * but it doesn't, so we work around it, and hide this as a * far away as we can. */ if (fd >= 0) { PROTECT_ERRNO; r = asynchronous_job(close_thread, FD_TO_PTR(fd)); if (r < 0) assert_se(close_nointr(fd) != -EBADF); } return -1; } systemd-229/src/basic/async.h000066400000000000000000000015241265713322000162210ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int asynchronous_job(void* (*func)(void *p), void *arg); int asynchronous_sync(void); int asynchronous_close(int fd); systemd-229/src/basic/audit-util.c000066400000000000000000000052531265713322000171630ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "audit-util.h" #include "fd-util.h" #include "fileio.h" #include "macro.h" #include "parse-util.h" #include "process-util.h" #include "user-util.h" int audit_session_from_pid(pid_t pid, uint32_t *id) { _cleanup_free_ char *s = NULL; const char *p; uint32_t u; int r; assert(id); /* We don't convert ENOENT to ESRCH here, since we can't * really distuingish between "audit is not available in the * kernel" and "the process does not exist", both which will * result in ENOENT. */ p = procfs_file_alloca(pid, "sessionid"); r = read_one_line_file(p, &s); if (r < 0) return r; r = safe_atou32(s, &u); if (r < 0) return r; if (u == AUDIT_SESSION_INVALID || u <= 0) return -ENODATA; *id = u; return 0; } int audit_loginuid_from_pid(pid_t pid, uid_t *uid) { _cleanup_free_ char *s = NULL; const char *p; uid_t u; int r; assert(uid); p = procfs_file_alloca(pid, "loginuid"); r = read_one_line_file(p, &s); if (r < 0) return r; r = parse_uid(s, &u); if (r == -ENXIO) /* the UID was -1 */ return -ENODATA; if (r < 0) return r; *uid = (uid_t) u; return 0; } bool use_audit(void) { static int cached_use = -1; if (cached_use < 0) { int fd; fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT); if (fd < 0) cached_use = errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT; else { cached_use = true; safe_close(fd); } } return cached_use; } systemd-229/src/basic/audit-util.h000066400000000000000000000017151265713322000171670ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #define AUDIT_SESSION_INVALID ((uint32_t) -1) int audit_session_from_pid(pid_t pid, uint32_t *id); int audit_loginuid_from_pid(pid_t pid, uid_t *uid); bool use_audit(void); systemd-229/src/basic/barrier.c000066400000000000000000000356051265713322000165340ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 David Herrmann systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include "barrier.h" #include "fd-util.h" #include "macro.h" /** * Barriers * This barrier implementation provides a simple synchronization method based * on file-descriptors that can safely be used between threads and processes. A * barrier object contains 2 shared counters based on eventfd. Both processes * can now place barriers and wait for the other end to reach a random or * specific barrier. * Barriers are numbered, so you can either wait for the other end to reach any * barrier or the last barrier that you placed. This way, you can use barriers * for one-way *and* full synchronization. Note that even-though barriers are * numbered, these numbers are internal and recycled once both sides reached the * same barrier (implemented as a simple signed counter). It is thus not * possible to address barriers by their ID. * * Barrier-API: Both ends can place as many barriers via barrier_place() as * they want and each pair of barriers on both sides will be implicitly linked. * Each side can use the barrier_wait/sync_*() family of calls to wait for the * other side to place a specific barrier. barrier_wait_next() waits until the * other side calls barrier_place(). No links between the barriers are * considered and this simply serves as most basic asynchronous barrier. * barrier_sync_next() is like barrier_wait_next() and waits for the other side * to place their next barrier via barrier_place(). However, it only waits for * barriers that are linked to a barrier we already placed. If the other side * already placed more barriers than we did, barrier_sync_next() returns * immediately. * barrier_sync() extends barrier_sync_next() and waits until the other end * placed as many barriers via barrier_place() as we did. If they already placed * as many as we did (or more), it returns immediately. * * Additionally to basic barriers, an abortion event is available. * barrier_abort() places an abortion event that cannot be undone. An abortion * immediately cancels all placed barriers and replaces them. Any running and * following wait/sync call besides barrier_wait_abortion() will immediately * return false on both sides (otherwise, they always return true). * barrier_abort() can be called multiple times on both ends and will be a * no-op if already called on this side. * barrier_wait_abortion() can be used to wait for the other side to call * barrier_abort() and is the only wait/sync call that does not return * immediately if we aborted outself. It only returns once the other side * called barrier_abort(). * * Barriers can be used for in-process and inter-process synchronization. * However, for in-process synchronization you could just use mutexes. * Therefore, main target is IPC and we require both sides to *not* share the FD * table. If that's given, barriers provide target tracking: If the remote side * exit()s, an abortion event is implicitly queued on the other side. This way, * a sync/wait call will be woken up if the remote side crashed or exited * unexpectedly. However, note that these abortion events are only queued if the * barrier-queue has been drained. Therefore, it is safe to place a barrier and * exit. The other side can safely wait on the barrier even though the exit * queued an abortion event. Usually, the abortion event would overwrite the * barrier, however, that's not true for exit-abortion events. Those are only * queued if the barrier-queue is drained (thus, the receiving side has placed * more barriers than the remote side). */ /** * barrier_create() - Initialize a barrier object * @obj: barrier to initialize * * This initializes a barrier object. The caller is responsible of allocating * the memory and keeping it valid. The memory does not have to be zeroed * beforehand. * Two eventfd objects are allocated for each barrier. If allocation fails, an * error is returned. * * If this function fails, the barrier is reset to an invalid state so it is * safe to call barrier_destroy() on the object regardless whether the * initialization succeeded or not. * * The caller is responsible to destroy the object via barrier_destroy() before * releasing the underlying memory. * * Returns: 0 on success, negative error code on failure. */ int barrier_create(Barrier *b) { _cleanup_(barrier_destroyp) Barrier *staging = b; int r; assert(b); b->me = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); if (b->me < 0) return -errno; b->them = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); if (b->them < 0) return -errno; r = pipe2(b->pipe, O_CLOEXEC | O_NONBLOCK); if (r < 0) return -errno; staging = NULL; return 0; } /** * barrier_destroy() - Destroy a barrier object * @b: barrier to destroy or NULL * * This destroys a barrier object that has previously been passed to * barrier_create(). The object is released and reset to invalid * state. Therefore, it is safe to call barrier_destroy() multiple * times or even if barrier_create() failed. However, barrier must be * always initialized with BARRIER_NULL. * * If @b is NULL, this is a no-op. */ void barrier_destroy(Barrier *b) { if (!b) return; b->me = safe_close(b->me); b->them = safe_close(b->them); safe_close_pair(b->pipe); b->barriers = 0; } /** * barrier_set_role() - Set the local role of the barrier * @b: barrier to operate on * @role: role to set on the barrier * * This sets the roles on a barrier object. This is needed to know * which side of the barrier you're on. Usually, the parent creates * the barrier via barrier_create() and then calls fork() or clone(). * Therefore, the FDs are duplicated and the child retains the same * barrier object. * * Both sides need to call barrier_set_role() after fork() or clone() * are done. If this is not done, barriers will not work correctly. * * Note that barriers could be supported without fork() or clone(). However, * this is currently not needed so it hasn't been implemented. */ void barrier_set_role(Barrier *b, unsigned int role) { int fd; assert(b); assert(role == BARRIER_PARENT || role == BARRIER_CHILD); /* make sure this is only called once */ assert(b->pipe[0] >= 0 && b->pipe[1] >= 0); if (role == BARRIER_PARENT) b->pipe[1] = safe_close(b->pipe[1]); else { b->pipe[0] = safe_close(b->pipe[0]); /* swap me/them for children */ fd = b->me; b->me = b->them; b->them = fd; } } /* places barrier; returns false if we aborted, otherwise true */ static bool barrier_write(Barrier *b, uint64_t buf) { ssize_t len; /* prevent new sync-points if we already aborted */ if (barrier_i_aborted(b)) return false; assert(b->me >= 0); do { len = write(b->me, &buf, sizeof(buf)); } while (len < 0 && IN_SET(errno, EAGAIN, EINTR)); if (len != sizeof(buf)) goto error; /* lock if we aborted */ if (buf >= (uint64_t)BARRIER_ABORTION) { if (barrier_they_aborted(b)) b->barriers = BARRIER_WE_ABORTED; else b->barriers = BARRIER_I_ABORTED; } else if (!barrier_is_aborted(b)) b->barriers += buf; return !barrier_i_aborted(b); error: /* If there is an unexpected error, we have to make this fatal. There * is no way we can recover from sync-errors. Therefore, we close the * pipe-ends and treat this as abortion. The other end will notice the * pipe-close and treat it as abortion, too. */ safe_close_pair(b->pipe); b->barriers = BARRIER_WE_ABORTED; return false; } /* waits for barriers; returns false if they aborted, otherwise true */ static bool barrier_read(Barrier *b, int64_t comp) { if (barrier_they_aborted(b)) return false; while (b->barriers > comp) { struct pollfd pfd[2] = { { .fd = b->pipe[0] >= 0 ? b->pipe[0] : b->pipe[1], .events = POLLHUP }, { .fd = b->them, .events = POLLIN }}; uint64_t buf; int r; r = poll(pfd, 2, -1); if (r < 0 && IN_SET(errno, EAGAIN, EINTR)) continue; else if (r < 0) goto error; if (pfd[1].revents) { ssize_t len; /* events on @them signal new data for us */ len = read(b->them, &buf, sizeof(buf)); if (len < 0 && IN_SET(errno, EAGAIN, EINTR)) continue; if (len != sizeof(buf)) goto error; } else if (pfd[0].revents & (POLLHUP | POLLERR | POLLNVAL)) /* POLLHUP on the pipe tells us the other side exited. * We treat this as implicit abortion. But we only * handle it if there's no event on the eventfd. This * guarantees that exit-abortions do not overwrite real * barriers. */ buf = BARRIER_ABORTION; else continue; /* lock if they aborted */ if (buf >= (uint64_t)BARRIER_ABORTION) { if (barrier_i_aborted(b)) b->barriers = BARRIER_WE_ABORTED; else b->barriers = BARRIER_THEY_ABORTED; } else if (!barrier_is_aborted(b)) b->barriers -= buf; } return !barrier_they_aborted(b); error: /* If there is an unexpected error, we have to make this fatal. There * is no way we can recover from sync-errors. Therefore, we close the * pipe-ends and treat this as abortion. The other end will notice the * pipe-close and treat it as abortion, too. */ safe_close_pair(b->pipe); b->barriers = BARRIER_WE_ABORTED; return false; } /** * barrier_place() - Place a new barrier * @b: barrier object * * This places a new barrier on the barrier object. If either side already * aborted, this is a no-op and returns "false". Otherwise, the barrier is * placed and this returns "true". * * Returns: true if barrier was placed, false if either side aborted. */ bool barrier_place(Barrier *b) { assert(b); if (barrier_is_aborted(b)) return false; barrier_write(b, BARRIER_SINGLE); return true; } /** * barrier_abort() - Abort the synchronization * @b: barrier object to abort * * This aborts the barrier-synchronization. If barrier_abort() was already * called on this side, this is a no-op. Otherwise, the barrier is put into the * ABORT-state and will stay there. The other side is notified about the * abortion. Any following attempt to place normal barriers or to wait on normal * barriers will return immediately as "false". * * You can wait for the other side to call barrier_abort(), too. Use * barrier_wait_abortion() for that. * * Returns: false if the other side already aborted, true otherwise. */ bool barrier_abort(Barrier *b) { assert(b); barrier_write(b, BARRIER_ABORTION); return !barrier_they_aborted(b); } /** * barrier_wait_next() - Wait for the next barrier of the other side * @b: barrier to operate on * * This waits until the other side places its next barrier. This is independent * of any barrier-links and just waits for any next barrier of the other side. * * If either side aborted, this returns false. * * Returns: false if either side aborted, true otherwise. */ bool barrier_wait_next(Barrier *b) { assert(b); if (barrier_is_aborted(b)) return false; barrier_read(b, b->barriers - 1); return !barrier_is_aborted(b); } /** * barrier_wait_abortion() - Wait for the other side to abort * @b: barrier to operate on * * This waits until the other side called barrier_abort(). This can be called * regardless whether the local side already called barrier_abort() or not. * * If the other side has already aborted, this returns immediately. * * Returns: false if the local side aborted, true otherwise. */ bool barrier_wait_abortion(Barrier *b) { assert(b); barrier_read(b, BARRIER_THEY_ABORTED); return !barrier_i_aborted(b); } /** * barrier_sync_next() - Wait for the other side to place a next linked barrier * @b: barrier to operate on * * This is like barrier_wait_next() and waits for the other side to call * barrier_place(). However, this only waits for linked barriers. That means, if * the other side already placed more barriers than (or as much as) we did, this * returns immediately instead of waiting. * * If either side aborted, this returns false. * * Returns: false if either side aborted, true otherwise. */ bool barrier_sync_next(Barrier *b) { assert(b); if (barrier_is_aborted(b)) return false; barrier_read(b, MAX((int64_t)0, b->barriers - 1)); return !barrier_is_aborted(b); } /** * barrier_sync() - Wait for the other side to place as many barriers as we did * @b: barrier to operate on * * This is like barrier_sync_next() but waits for the other side to call * barrier_place() as often as we did (in total). If they already placed as much * as we did (or more), this returns immediately instead of waiting. * * If either side aborted, this returns false. * * Returns: false if either side aborted, true otherwise. */ bool barrier_sync(Barrier *b) { assert(b); if (barrier_is_aborted(b)) return false; barrier_read(b, 0); return !barrier_is_aborted(b); } systemd-229/src/basic/barrier.h000066400000000000000000000050751265713322000165370ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 David Herrmann systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "macro.h" /* See source file for an API description. */ typedef struct Barrier Barrier; enum { BARRIER_SINGLE = 1LL, BARRIER_ABORTION = INT64_MAX, /* bias values to store state; keep @WE < @THEY < @I */ BARRIER_BIAS = INT64_MIN, BARRIER_WE_ABORTED = BARRIER_BIAS + 1LL, BARRIER_THEY_ABORTED = BARRIER_BIAS + 2LL, BARRIER_I_ABORTED = BARRIER_BIAS + 3LL, }; enum { BARRIER_PARENT, BARRIER_CHILD, }; struct Barrier { int me; int them; int pipe[2]; int64_t barriers; }; #define BARRIER_NULL {-1, -1, {-1, -1}, 0} int barrier_create(Barrier *obj); void barrier_destroy(Barrier *b); DEFINE_TRIVIAL_CLEANUP_FUNC(Barrier*, barrier_destroy); void barrier_set_role(Barrier *b, unsigned int role); bool barrier_place(Barrier *b); bool barrier_abort(Barrier *b); bool barrier_wait_next(Barrier *b); bool barrier_wait_abortion(Barrier *b); bool barrier_sync_next(Barrier *b); bool barrier_sync(Barrier *b); static inline bool barrier_i_aborted(Barrier *b) { return b->barriers == BARRIER_I_ABORTED || b->barriers == BARRIER_WE_ABORTED; } static inline bool barrier_they_aborted(Barrier *b) { return b->barriers == BARRIER_THEY_ABORTED || b->barriers == BARRIER_WE_ABORTED; } static inline bool barrier_we_aborted(Barrier *b) { return b->barriers == BARRIER_WE_ABORTED; } static inline bool barrier_is_aborted(Barrier *b) { return b->barriers == BARRIER_I_ABORTED || b->barriers == BARRIER_THEY_ABORTED || b->barriers == BARRIER_WE_ABORTED; } static inline bool barrier_place_and_sync(Barrier *b) { (void) barrier_place(b); return barrier_sync(b); } systemd-229/src/basic/bitmap.c000066400000000000000000000122521265713322000163530ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "bitmap.h" #include "hashmap.h" #include "macro.h" struct Bitmap { uint64_t *bitmaps; size_t n_bitmaps; size_t bitmaps_allocated; }; /* Bitmaps are only meant to store relatively small numbers * (corresponding to, say, an enum), so it is ok to limit * the max entry. 64k should be plenty. */ #define BITMAPS_MAX_ENTRY 0xffff /* This indicates that we reached the end of the bitmap */ #define BITMAP_END ((unsigned) -1) #define BITMAP_NUM_TO_OFFSET(n) ((n) / (sizeof(uint64_t) * 8)) #define BITMAP_NUM_TO_REM(n) ((n) % (sizeof(uint64_t) * 8)) #define BITMAP_OFFSET_TO_NUM(offset, rem) ((offset) * sizeof(uint64_t) * 8 + (rem)) Bitmap *bitmap_new(void) { return new0(Bitmap, 1); } void bitmap_free(Bitmap *b) { if (!b) return; free(b->bitmaps); free(b); } int bitmap_ensure_allocated(Bitmap **b) { Bitmap *a; assert(b); if (*b) return 0; a = bitmap_new(); if (!a) return -ENOMEM; *b = a; return 0; } int bitmap_set(Bitmap *b, unsigned n) { uint64_t bitmask; unsigned offset; assert(b); /* we refuse to allocate huge bitmaps */ if (n > BITMAPS_MAX_ENTRY) return -ERANGE; offset = BITMAP_NUM_TO_OFFSET(n); if (offset >= b->n_bitmaps) { if (!GREEDY_REALLOC0(b->bitmaps, b->bitmaps_allocated, offset + 1)) return -ENOMEM; b->n_bitmaps = offset + 1; } bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n); b->bitmaps[offset] |= bitmask; return 0; } void bitmap_unset(Bitmap *b, unsigned n) { uint64_t bitmask; unsigned offset; if (!b) return; offset = BITMAP_NUM_TO_OFFSET(n); if (offset >= b->n_bitmaps) return; bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n); b->bitmaps[offset] &= ~bitmask; } bool bitmap_isset(Bitmap *b, unsigned n) { uint64_t bitmask; unsigned offset; if (!b) return false; offset = BITMAP_NUM_TO_OFFSET(n); if (offset >= b->n_bitmaps) return false; bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n); return !!(b->bitmaps[offset] & bitmask); } bool bitmap_isclear(Bitmap *b) { unsigned i; if (!b) return true; for (i = 0; i < b->n_bitmaps; i++) if (b->bitmaps[i] != 0) return false; return true; } void bitmap_clear(Bitmap *b) { if (!b) return; b->bitmaps = mfree(b->bitmaps); b->n_bitmaps = 0; b->bitmaps_allocated = 0; } bool bitmap_iterate(Bitmap *b, Iterator *i, unsigned *n) { uint64_t bitmask; unsigned offset, rem; assert(i); assert(n); if (!b || i->idx == BITMAP_END) return false; offset = BITMAP_NUM_TO_OFFSET(i->idx); rem = BITMAP_NUM_TO_REM(i->idx); bitmask = UINT64_C(1) << rem; for (; offset < b->n_bitmaps; offset ++) { if (b->bitmaps[offset]) { for (; bitmask; bitmask <<= 1, rem ++) { if (b->bitmaps[offset] & bitmask) { *n = BITMAP_OFFSET_TO_NUM(offset, rem); i->idx = *n + 1; return true; } } } rem = 0; bitmask = 1; } i->idx = BITMAP_END; return false; } bool bitmap_equal(Bitmap *a, Bitmap *b) { size_t common_n_bitmaps; Bitmap *c; unsigned i; if (a == b) return true; if (!a != !b) return false; if (!a) return true; common_n_bitmaps = MIN(a->n_bitmaps, b->n_bitmaps); if (memcmp(a->bitmaps, b->bitmaps, sizeof(uint64_t) * common_n_bitmaps) != 0) return false; c = a->n_bitmaps > b->n_bitmaps ? a : b; for (i = common_n_bitmaps; i < c->n_bitmaps; i++) if (c->bitmaps[i] != 0) return false; return true; } systemd-229/src/basic/bitmap.h000066400000000000000000000026151265713322000163620ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "hashmap.h" #include "macro.h" typedef struct Bitmap Bitmap; Bitmap *bitmap_new(void); void bitmap_free(Bitmap *b); int bitmap_ensure_allocated(Bitmap **b); int bitmap_set(Bitmap *b, unsigned n); void bitmap_unset(Bitmap *b, unsigned n); bool bitmap_isset(Bitmap *b, unsigned n); bool bitmap_isclear(Bitmap *b); void bitmap_clear(Bitmap *b); bool bitmap_iterate(Bitmap *b, Iterator *i, unsigned *n); bool bitmap_equal(Bitmap *a, Bitmap *b); #define BITMAP_FOREACH(n, b, i) \ for ((i).idx = 0; bitmap_iterate((b), &(i), (unsigned*)&(n)); ) DEFINE_TRIVIAL_CLEANUP_FUNC(Bitmap*, bitmap_free); #define _cleanup_bitmap_free_ _cleanup_(bitmap_freep) systemd-229/src/basic/blkid-util.h000066400000000000000000000016701265713322000171460ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #ifdef HAVE_BLKID #include #endif #include "util.h" #ifdef HAVE_BLKID DEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe); #define _cleanup_blkid_free_probe_ _cleanup_(blkid_free_probep) #endif systemd-229/src/basic/btrfs-ctree.h000066400000000000000000000045221265713322000173250ustar00rootroot00000000000000#pragma once #include "macro.h" #include "sparse-endian.h" /* Stolen from btrfs' ctree.h */ struct btrfs_timespec { le64_t sec; le32_t nsec; } _packed_; struct btrfs_disk_key { le64_t objectid; uint8_t type; le64_t offset; } _packed_; struct btrfs_inode_item { le64_t generation; le64_t transid; le64_t size; le64_t nbytes; le64_t block_group; le32_t nlink; le32_t uid; le32_t gid; le32_t mode; le64_t rdev; le64_t flags; le64_t sequence; le64_t reserved[4]; struct btrfs_timespec atime; struct btrfs_timespec ctime; struct btrfs_timespec mtime; struct btrfs_timespec otime; } _packed_; struct btrfs_root_item { struct btrfs_inode_item inode; le64_t generation; le64_t root_dirid; le64_t bytenr; le64_t byte_limit; le64_t bytes_used; le64_t last_snapshot; le64_t flags; le32_t refs; struct btrfs_disk_key drop_progress; uint8_t drop_level; uint8_t level; le64_t generation_v2; uint8_t uuid[BTRFS_UUID_SIZE]; uint8_t parent_uuid[BTRFS_UUID_SIZE]; uint8_t received_uuid[BTRFS_UUID_SIZE]; le64_t ctransid; le64_t otransid; le64_t stransid; le64_t rtransid; struct btrfs_timespec ctime; struct btrfs_timespec otime; struct btrfs_timespec stime; struct btrfs_timespec rtime; le64_t reserved[8]; } _packed_; #define BTRFS_ROOT_SUBVOL_RDONLY (1ULL << 0) struct btrfs_qgroup_info_item { le64_t generation; le64_t rfer; le64_t rfer_cmpr; le64_t excl; le64_t excl_cmpr; } _packed_; #define BTRFS_QGROUP_LIMIT_MAX_RFER (1ULL << 0) #define BTRFS_QGROUP_LIMIT_MAX_EXCL (1ULL << 1) #define BTRFS_QGROUP_LIMIT_RSV_RFER (1ULL << 2) #define BTRFS_QGROUP_LIMIT_RSV_EXCL (1ULL << 3) #define BTRFS_QGROUP_LIMIT_RFER_CMPR (1ULL << 4) #define BTRFS_QGROUP_LIMIT_EXCL_CMPR (1ULL << 5) struct btrfs_qgroup_limit_item { le64_t flags; le64_t max_rfer; le64_t max_excl; le64_t rsv_rfer; le64_t rsv_excl; } _packed_; struct btrfs_root_ref { le64_t dirid; le64_t sequence; le16_t name_len; } _packed_; systemd-229/src/basic/btrfs-util.c000066400000000000000000002032721265713322000171760ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LINUX_BTRFS_H #include #endif #include "alloc-util.h" #include "btrfs-ctree.h" #include "btrfs-util.h" #include "copy.h" #include "fd-util.h" #include "fileio.h" #include "io-util.h" #include "macro.h" #include "missing.h" #include "path-util.h" #include "selinux-util.h" #include "smack-util.h" #include "sparse-endian.h" #include "stat-util.h" #include "string-util.h" #include "time-util.h" #include "util.h" /* WARNING: Be careful with file system ioctls! When we get an fd, we * need to make sure it either refers to only a regular file or * directory, or that it is located on btrfs, before invoking any * btrfs ioctls. The ioctl numbers are reused by some device drivers * (such as DRM), and hence might have bad effects when invoked on * device nodes (that reference drivers) rather than fds to normal * files or directories. */ static int validate_subvolume_name(const char *name) { if (!filename_is_valid(name)) return -EINVAL; if (strlen(name) > BTRFS_SUBVOL_NAME_MAX) return -E2BIG; return 0; } static int open_parent(const char *path, int flags) { _cleanup_free_ char *parent = NULL; int fd; assert(path); parent = dirname_malloc(path); if (!parent) return -ENOMEM; fd = open(parent, flags); if (fd < 0) return -errno; return fd; } static int extract_subvolume_name(const char *path, const char **subvolume) { const char *fn; int r; assert(path); assert(subvolume); fn = basename(path); r = validate_subvolume_name(fn); if (r < 0) return r; *subvolume = fn; return 0; } int btrfs_is_filesystem(int fd) { struct statfs sfs; assert(fd >= 0); if (fstatfs(fd, &sfs) < 0) return -errno; return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC); } int btrfs_is_subvol_fd(int fd) { struct stat st; assert(fd >= 0); /* On btrfs subvolumes always have the inode 256 */ if (fstat(fd, &st) < 0) return -errno; if (!S_ISDIR(st.st_mode) || st.st_ino != 256) return 0; return btrfs_is_filesystem(fd); } int btrfs_is_subvol(const char *path) { _cleanup_close_ int fd = -1; assert(path); fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); if (fd < 0) return -errno; return btrfs_is_subvol_fd(fd); } int btrfs_subvol_make(const char *path) { struct btrfs_ioctl_vol_args args = {}; _cleanup_close_ int fd = -1; const char *subvolume; int r; assert(path); r = extract_subvolume_name(path, &subvolume); if (r < 0) return r; fd = open_parent(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); if (fd < 0) return fd; strncpy(args.name, subvolume, sizeof(args.name)-1); if (ioctl(fd, BTRFS_IOC_SUBVOL_CREATE, &args) < 0) return -errno; return 0; } int btrfs_subvol_make_label(const char *path) { int r; assert(path); r = mac_selinux_create_file_prepare(path, S_IFDIR); if (r < 0) return r; r = btrfs_subvol_make(path); mac_selinux_create_file_clear(); if (r < 0) return r; return mac_smack_fix(path, false, false); } int btrfs_subvol_set_read_only_fd(int fd, bool b) { uint64_t flags, nflags; struct stat st; assert(fd >= 0); if (fstat(fd, &st) < 0) return -errno; if (!S_ISDIR(st.st_mode) || st.st_ino != 256) return -EINVAL; if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0) return -errno; if (b) nflags = flags | BTRFS_SUBVOL_RDONLY; else nflags = flags & ~BTRFS_SUBVOL_RDONLY; if (flags == nflags) return 0; if (ioctl(fd, BTRFS_IOC_SUBVOL_SETFLAGS, &nflags) < 0) return -errno; return 0; } int btrfs_subvol_set_read_only(const char *path, bool b) { _cleanup_close_ int fd = -1; fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); if (fd < 0) return -errno; return btrfs_subvol_set_read_only_fd(fd, b); } int btrfs_subvol_get_read_only_fd(int fd) { uint64_t flags; struct stat st; assert(fd >= 0); if (fstat(fd, &st) < 0) return -errno; if (!S_ISDIR(st.st_mode) || st.st_ino != 256) return -EINVAL; if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0) return -errno; return !!(flags & BTRFS_SUBVOL_RDONLY); } int btrfs_reflink(int infd, int outfd) { struct stat st; int r; assert(infd >= 0); assert(outfd >= 0); /* Make sure we invoke the ioctl on a regular file, so that no * device driver accidentally gets it. */ if (fstat(outfd, &st) < 0) return -errno; if (!S_ISREG(st.st_mode)) return -EINVAL; r = ioctl(outfd, BTRFS_IOC_CLONE, infd); if (r < 0) return -errno; return 0; } int btrfs_clone_range(int infd, uint64_t in_offset, int outfd, uint64_t out_offset, uint64_t sz) { struct btrfs_ioctl_clone_range_args args = { .src_fd = infd, .src_offset = in_offset, .src_length = sz, .dest_offset = out_offset, }; struct stat st; int r; assert(infd >= 0); assert(outfd >= 0); assert(sz > 0); if (fstat(outfd, &st) < 0) return -errno; if (!S_ISREG(st.st_mode)) return -EINVAL; r = ioctl(outfd, BTRFS_IOC_CLONE_RANGE, &args); if (r < 0) return -errno; return 0; } int btrfs_get_block_device_fd(int fd, dev_t *dev) { struct btrfs_ioctl_fs_info_args fsi = {}; uint64_t id; int r; assert(fd >= 0); assert(dev); r = btrfs_is_filesystem(fd); if (r < 0) return r; if (!r) return -ENOTTY; if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0) return -errno; /* We won't do this for btrfs RAID */ if (fsi.num_devices != 1) return 0; for (id = 1; id <= fsi.max_id; id++) { struct btrfs_ioctl_dev_info_args di = { .devid = id, }; struct stat st; if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) { if (errno == ENODEV) continue; return -errno; } if (stat((char*) di.path, &st) < 0) return -errno; if (!S_ISBLK(st.st_mode)) return -ENODEV; if (major(st.st_rdev) == 0) return -ENODEV; *dev = st.st_rdev; return 1; } return -ENODEV; } int btrfs_get_block_device(const char *path, dev_t *dev) { _cleanup_close_ int fd = -1; assert(path); assert(dev); fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) return -errno; return btrfs_get_block_device_fd(fd, dev); } int btrfs_subvol_get_id_fd(int fd, uint64_t *ret) { struct btrfs_ioctl_ino_lookup_args args = { .objectid = BTRFS_FIRST_FREE_OBJECTID }; int r; assert(fd >= 0); assert(ret); r = btrfs_is_filesystem(fd); if (r < 0) return r; if (!r) return -ENOTTY; if (ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args) < 0) return -errno; *ret = args.treeid; return 0; } int btrfs_subvol_get_id(int fd, const char *subvol, uint64_t *ret) { _cleanup_close_ int subvol_fd = -1; assert(fd >= 0); assert(ret); subvol_fd = openat(fd, subvol, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (subvol_fd < 0) return -errno; return btrfs_subvol_get_id_fd(subvol_fd, ret); } static bool btrfs_ioctl_search_args_inc(struct btrfs_ioctl_search_args *args) { assert(args); /* the objectid, type, offset together make up the btrfs key, * which is considered a single 136byte integer when * comparing. This call increases the counter by one, dealing * with the overflow between the overflows */ if (args->key.min_offset < (uint64_t) -1) { args->key.min_offset++; return true; } if (args->key.min_type < (uint8_t) -1) { args->key.min_type++; args->key.min_offset = 0; return true; } if (args->key.min_objectid < (uint64_t) -1) { args->key.min_objectid++; args->key.min_offset = 0; args->key.min_type = 0; return true; } return 0; } static void btrfs_ioctl_search_args_set(struct btrfs_ioctl_search_args *args, const struct btrfs_ioctl_search_header *h) { assert(args); assert(h); args->key.min_objectid = h->objectid; args->key.min_type = h->type; args->key.min_offset = h->offset; } static int btrfs_ioctl_search_args_compare(const struct btrfs_ioctl_search_args *args) { assert(args); /* Compare min and max */ if (args->key.min_objectid < args->key.max_objectid) return -1; if (args->key.min_objectid > args->key.max_objectid) return 1; if (args->key.min_type < args->key.max_type) return -1; if (args->key.min_type > args->key.max_type) return 1; if (args->key.min_offset < args->key.max_offset) return -1; if (args->key.min_offset > args->key.max_offset) return 1; return 0; } #define FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) \ for ((i) = 0, \ (sh) = (const struct btrfs_ioctl_search_header*) (args).buf; \ (i) < (args).key.nr_items; \ (i)++, \ (sh) = (const struct btrfs_ioctl_search_header*) ((uint8_t*) (sh) + sizeof(struct btrfs_ioctl_search_header) + (sh)->len)) #define BTRFS_IOCTL_SEARCH_HEADER_BODY(sh) \ ((void*) ((uint8_t*) sh + sizeof(struct btrfs_ioctl_search_header))) int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *ret) { struct btrfs_ioctl_search_args args = { /* Tree of tree roots */ .key.tree_id = BTRFS_ROOT_TREE_OBJECTID, /* Look precisely for the subvolume items */ .key.min_type = BTRFS_ROOT_ITEM_KEY, .key.max_type = BTRFS_ROOT_ITEM_KEY, .key.min_offset = 0, .key.max_offset = (uint64_t) -1, /* No restrictions on the other components */ .key.min_transid = 0, .key.max_transid = (uint64_t) -1, }; bool found = false; int r; assert(fd >= 0); assert(ret); if (subvol_id == 0) { r = btrfs_subvol_get_id_fd(fd, &subvol_id); if (r < 0) return r; } else { r = btrfs_is_filesystem(fd); if (r < 0) return r; if (!r) return -ENOTTY; } args.key.min_objectid = args.key.max_objectid = subvol_id; while (btrfs_ioctl_search_args_compare(&args) <= 0) { const struct btrfs_ioctl_search_header *sh; unsigned i; args.key.nr_items = 256; if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) return -errno; if (args.key.nr_items <= 0) break; FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { const struct btrfs_root_item *ri; /* Make sure we start the next search at least from this entry */ btrfs_ioctl_search_args_set(&args, sh); if (sh->objectid != subvol_id) continue; if (sh->type != BTRFS_ROOT_ITEM_KEY) continue; /* Older versions of the struct lacked the otime setting */ if (sh->len < offsetof(struct btrfs_root_item, otime) + sizeof(struct btrfs_timespec)) continue; ri = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); ret->otime = (usec_t) le64toh(ri->otime.sec) * USEC_PER_SEC + (usec_t) le32toh(ri->otime.nsec) / NSEC_PER_USEC; ret->subvol_id = subvol_id; ret->read_only = !!(le64toh(ri->flags) & BTRFS_ROOT_SUBVOL_RDONLY); assert_cc(sizeof(ri->uuid) == sizeof(ret->uuid)); memcpy(&ret->uuid, ri->uuid, sizeof(ret->uuid)); memcpy(&ret->parent_uuid, ri->parent_uuid, sizeof(ret->parent_uuid)); found = true; goto finish; } /* Increase search key by one, to read the next item, if we can. */ if (!btrfs_ioctl_search_args_inc(&args)) break; } finish: if (!found) return -ENODATA; return 0; } int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *ret) { struct btrfs_ioctl_search_args args = { /* Tree of quota items */ .key.tree_id = BTRFS_QUOTA_TREE_OBJECTID, /* The object ID is always 0 */ .key.min_objectid = 0, .key.max_objectid = 0, /* Look precisely for the quota items */ .key.min_type = BTRFS_QGROUP_STATUS_KEY, .key.max_type = BTRFS_QGROUP_LIMIT_KEY, /* No restrictions on the other components */ .key.min_transid = 0, .key.max_transid = (uint64_t) -1, }; bool found_info = false, found_limit = false; int r; assert(fd >= 0); assert(ret); if (qgroupid == 0) { r = btrfs_subvol_get_id_fd(fd, &qgroupid); if (r < 0) return r; } else { r = btrfs_is_filesystem(fd); if (r < 0) return r; if (!r) return -ENOTTY; } args.key.min_offset = args.key.max_offset = qgroupid; while (btrfs_ioctl_search_args_compare(&args) <= 0) { const struct btrfs_ioctl_search_header *sh; unsigned i; args.key.nr_items = 256; if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) { if (errno == ENOENT) /* quota tree is missing: quota disabled */ break; return -errno; } if (args.key.nr_items <= 0) break; FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { /* Make sure we start the next search at least from this entry */ btrfs_ioctl_search_args_set(&args, sh); if (sh->objectid != 0) continue; if (sh->offset != qgroupid) continue; if (sh->type == BTRFS_QGROUP_INFO_KEY) { const struct btrfs_qgroup_info_item *qii = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); ret->referenced = le64toh(qii->rfer); ret->exclusive = le64toh(qii->excl); found_info = true; } else if (sh->type == BTRFS_QGROUP_LIMIT_KEY) { const struct btrfs_qgroup_limit_item *qli = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); if (le64toh(qli->flags) & BTRFS_QGROUP_LIMIT_MAX_RFER) ret->referenced_max = le64toh(qli->max_rfer); else ret->referenced_max = (uint64_t) -1; if (le64toh(qli->flags) & BTRFS_QGROUP_LIMIT_MAX_EXCL) ret->exclusive_max = le64toh(qli->max_excl); else ret->exclusive_max = (uint64_t) -1; found_limit = true; } if (found_info && found_limit) goto finish; } /* Increase search key by one, to read the next item, if we can. */ if (!btrfs_ioctl_search_args_inc(&args)) break; } finish: if (!found_limit && !found_info) return -ENODATA; if (!found_info) { ret->referenced = (uint64_t) -1; ret->exclusive = (uint64_t) -1; } if (!found_limit) { ret->referenced_max = (uint64_t) -1; ret->exclusive_max = (uint64_t) -1; } return 0; } int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *ret) { _cleanup_close_ int fd = -1; fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd < 0) return -errno; return btrfs_qgroup_get_quota_fd(fd, qgroupid, ret); } int btrfs_subvol_find_subtree_qgroup(int fd, uint64_t subvol_id, uint64_t *ret) { uint64_t level, lowest = (uint64_t) -1, lowest_qgroupid = 0; _cleanup_free_ uint64_t *qgroups = NULL; int r, n, i; assert(fd >= 0); assert(ret); /* This finds the "subtree" qgroup for a specific * subvolume. This only works for subvolumes that have been * prepared with btrfs_subvol_auto_qgroup_fd() with * insert_intermediary_qgroup=true (or equivalent). For others * it will return the leaf qgroup instead. The two cases may * be distuingished via the return value, which is 1 in case * an appropriate "subtree" qgroup was found, and 0 * otherwise. */ if (subvol_id == 0) { r = btrfs_subvol_get_id_fd(fd, &subvol_id); if (r < 0) return r; } r = btrfs_qgroupid_split(subvol_id, &level, NULL); if (r < 0) return r; if (level != 0) /* Input must be a leaf qgroup */ return -EINVAL; n = btrfs_qgroup_find_parents(fd, subvol_id, &qgroups); if (n < 0) return n; for (i = 0; i < n; i++) { uint64_t id; r = btrfs_qgroupid_split(qgroups[i], &level, &id); if (r < 0) return r; if (id != subvol_id) continue; if (lowest == (uint64_t) -1 || level < lowest) { lowest_qgroupid = qgroups[i]; lowest = level; } } if (lowest == (uint64_t) -1) { /* No suitable higher-level qgroup found, let's return * the leaf qgroup instead, and indicate that with the * return value. */ *ret = subvol_id; return 0; } *ret = lowest_qgroupid; return 1; } int btrfs_subvol_get_subtree_quota_fd(int fd, uint64_t subvol_id, BtrfsQuotaInfo *ret) { uint64_t qgroupid; int r; assert(fd >= 0); assert(ret); /* This determines the quota data of the qgroup with the * lowest level, that shares the id part with the specified * subvolume. This is useful for determining the quota data * for entire subvolume subtrees, as long as the subtrees have * been set up with btrfs_qgroup_subvol_auto_fd() or in a * compatible way */ r = btrfs_subvol_find_subtree_qgroup(fd, subvol_id, &qgroupid); if (r < 0) return r; return btrfs_qgroup_get_quota_fd(fd, qgroupid, ret); } int btrfs_subvol_get_subtree_quota(const char *path, uint64_t subvol_id, BtrfsQuotaInfo *ret) { _cleanup_close_ int fd = -1; fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd < 0) return -errno; return btrfs_subvol_get_subtree_quota_fd(fd, subvol_id, ret); } int btrfs_defrag_fd(int fd) { struct stat st; assert(fd >= 0); if (fstat(fd, &st) < 0) return -errno; if (!S_ISREG(st.st_mode)) return -EINVAL; if (ioctl(fd, BTRFS_IOC_DEFRAG, NULL) < 0) return -errno; return 0; } int btrfs_defrag(const char *p) { _cleanup_close_ int fd = -1; fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd < 0) return -errno; return btrfs_defrag_fd(fd); } int btrfs_quota_enable_fd(int fd, bool b) { struct btrfs_ioctl_quota_ctl_args args = { .cmd = b ? BTRFS_QUOTA_CTL_ENABLE : BTRFS_QUOTA_CTL_DISABLE, }; int r; assert(fd >= 0); r = btrfs_is_filesystem(fd); if (r < 0) return r; if (!r) return -ENOTTY; if (ioctl(fd, BTRFS_IOC_QUOTA_CTL, &args) < 0) return -errno; return 0; } int btrfs_quota_enable(const char *path, bool b) { _cleanup_close_ int fd = -1; fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd < 0) return -errno; return btrfs_quota_enable_fd(fd, b); } int btrfs_qgroup_set_limit_fd(int fd, uint64_t qgroupid, uint64_t referenced_max) { struct btrfs_ioctl_qgroup_limit_args args = { .lim.max_rfer = referenced_max, .lim.flags = BTRFS_QGROUP_LIMIT_MAX_RFER, }; unsigned c; int r; assert(fd >= 0); if (qgroupid == 0) { r = btrfs_subvol_get_id_fd(fd, &qgroupid); if (r < 0) return r; } else { r = btrfs_is_filesystem(fd); if (r < 0) return r; if (!r) return -ENOTTY; } args.qgroupid = qgroupid; for (c = 0;; c++) { if (ioctl(fd, BTRFS_IOC_QGROUP_LIMIT, &args) < 0) { if (errno == EBUSY && c < 10) { (void) btrfs_quota_scan_wait(fd); continue; } return -errno; } break; } return 0; } int btrfs_qgroup_set_limit(const char *path, uint64_t qgroupid, uint64_t referenced_max) { _cleanup_close_ int fd = -1; fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd < 0) return -errno; return btrfs_qgroup_set_limit_fd(fd, qgroupid, referenced_max); } int btrfs_subvol_set_subtree_quota_limit_fd(int fd, uint64_t subvol_id, uint64_t referenced_max) { uint64_t qgroupid; int r; assert(fd >= 0); r = btrfs_subvol_find_subtree_qgroup(fd, subvol_id, &qgroupid); if (r < 0) return r; return btrfs_qgroup_set_limit_fd(fd, qgroupid, referenced_max); } int btrfs_subvol_set_subtree_quota_limit(const char *path, uint64_t subvol_id, uint64_t referenced_max) { _cleanup_close_ int fd = -1; fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd < 0) return -errno; return btrfs_subvol_set_subtree_quota_limit_fd(fd, subvol_id, referenced_max); } int btrfs_resize_loopback_fd(int fd, uint64_t new_size, bool grow_only) { struct btrfs_ioctl_vol_args args = {}; _cleanup_free_ char *p = NULL, *loop = NULL, *backing = NULL; _cleanup_close_ int loop_fd = -1, backing_fd = -1; struct stat st; dev_t dev = 0; int r; /* In contrast to btrfs quota ioctls ftruncate() cannot make sense of "infinity" or file sizes > 2^31 */ if (!FILE_SIZE_VALID(new_size)) return -EINVAL; /* btrfs cannot handle file systems < 16M, hence use this as minimum */ if (new_size < 16*1024*1024) new_size = 16*1024*1024; r = btrfs_get_block_device_fd(fd, &dev); if (r < 0) return r; if (r == 0) return -ENODEV; if (asprintf(&p, "/sys/dev/block/%u:%u/loop/backing_file", major(dev), minor(dev)) < 0) return -ENOMEM; r = read_one_line_file(p, &backing); if (r == -ENOENT) return -ENODEV; if (r < 0) return r; if (isempty(backing) || !path_is_absolute(backing)) return -ENODEV; backing_fd = open(backing, O_RDWR|O_CLOEXEC|O_NOCTTY); if (backing_fd < 0) return -errno; if (fstat(backing_fd, &st) < 0) return -errno; if (!S_ISREG(st.st_mode)) return -ENODEV; if (new_size == (uint64_t) st.st_size) return 0; if (grow_only && new_size < (uint64_t) st.st_size) return -EINVAL; if (asprintf(&loop, "/dev/block/%u:%u", major(dev), minor(dev)) < 0) return -ENOMEM; loop_fd = open(loop, O_RDWR|O_CLOEXEC|O_NOCTTY); if (loop_fd < 0) return -errno; if (snprintf(args.name, sizeof(args.name), "%" PRIu64, new_size) >= (int) sizeof(args.name)) return -EINVAL; if (new_size < (uint64_t) st.st_size) { /* Decrease size: first decrease btrfs size, then shorten loopback */ if (ioctl(fd, BTRFS_IOC_RESIZE, &args) < 0) return -errno; } if (ftruncate(backing_fd, new_size) < 0) return -errno; if (ioctl(loop_fd, LOOP_SET_CAPACITY, 0) < 0) return -errno; if (new_size > (uint64_t) st.st_size) { /* Increase size: first enlarge loopback, then increase btrfs size */ if (ioctl(fd, BTRFS_IOC_RESIZE, &args) < 0) return -errno; } /* Make sure the free disk space is correctly updated for both file systems */ (void) fsync(fd); (void) fsync(backing_fd); return 1; } int btrfs_resize_loopback(const char *p, uint64_t new_size, bool grow_only) { _cleanup_close_ int fd = -1; fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) return -errno; return btrfs_resize_loopback_fd(fd, new_size, grow_only); } int btrfs_qgroupid_make(uint64_t level, uint64_t id, uint64_t *ret) { assert(ret); if (level >= (UINT64_C(1) << (64 - BTRFS_QGROUP_LEVEL_SHIFT))) return -EINVAL; if (id >= (UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT)) return -EINVAL; *ret = (level << BTRFS_QGROUP_LEVEL_SHIFT) | id; return 0; } int btrfs_qgroupid_split(uint64_t qgroupid, uint64_t *level, uint64_t *id) { assert(level || id); if (level) *level = qgroupid >> BTRFS_QGROUP_LEVEL_SHIFT; if (id) *id = qgroupid & ((UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT) - 1); return 0; } static int qgroup_create_or_destroy(int fd, bool b, uint64_t qgroupid) { struct btrfs_ioctl_qgroup_create_args args = { .create = b, .qgroupid = qgroupid, }; unsigned c; int r; r = btrfs_is_filesystem(fd); if (r < 0) return r; if (r == 0) return -ENOTTY; for (c = 0;; c++) { if (ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args) < 0) { /* If quota is not enabled, we get EINVAL. Turn this into a recognizable error */ if (errno == EINVAL) return -ENOPROTOOPT; if (errno == EBUSY && c < 10) { (void) btrfs_quota_scan_wait(fd); continue; } return -errno; } break; } return 0; } int btrfs_qgroup_create(int fd, uint64_t qgroupid) { return qgroup_create_or_destroy(fd, true, qgroupid); } int btrfs_qgroup_destroy(int fd, uint64_t qgroupid) { return qgroup_create_or_destroy(fd, false, qgroupid); } int btrfs_qgroup_destroy_recursive(int fd, uint64_t qgroupid) { _cleanup_free_ uint64_t *qgroups = NULL; uint64_t subvol_id; int i, n, r; /* Destroys the specified qgroup, but unassigns it from all * its parents first. Also, it recursively destroys all * qgroups it is assgined to that have the same id part of the * qgroupid as the specified group. */ r = btrfs_qgroupid_split(qgroupid, NULL, &subvol_id); if (r < 0) return r; n = btrfs_qgroup_find_parents(fd, qgroupid, &qgroups); if (n < 0) return n; for (i = 0; i < n; i++) { uint64_t id; r = btrfs_qgroupid_split(qgroups[i], NULL, &id); if (r < 0) return r; r = btrfs_qgroup_unassign(fd, qgroupid, qgroups[i]); if (r < 0) return r; if (id != subvol_id) continue; /* The parent qgroupid shares the same id part with * us? If so, destroy it too. */ (void) btrfs_qgroup_destroy_recursive(fd, qgroups[i]); } return btrfs_qgroup_destroy(fd, qgroupid); } int btrfs_quota_scan_start(int fd) { struct btrfs_ioctl_quota_rescan_args args = {}; assert(fd >= 0); if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN, &args) < 0) return -errno; return 0; } int btrfs_quota_scan_wait(int fd) { assert(fd >= 0); if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN_WAIT) < 0) return -errno; return 0; } int btrfs_quota_scan_ongoing(int fd) { struct btrfs_ioctl_quota_rescan_args args = {}; assert(fd >= 0); if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN_STATUS, &args) < 0) return -errno; return !!args.flags; } static int qgroup_assign_or_unassign(int fd, bool b, uint64_t child, uint64_t parent) { struct btrfs_ioctl_qgroup_assign_args args = { .assign = b, .src = child, .dst = parent, }; unsigned c; int r; r = btrfs_is_filesystem(fd); if (r < 0) return r; if (r == 0) return -ENOTTY; for (c = 0;; c++) { r = ioctl(fd, BTRFS_IOC_QGROUP_ASSIGN, &args); if (r < 0) { if (errno == EBUSY && c < 10) { (void) btrfs_quota_scan_wait(fd); continue; } return -errno; } if (r == 0) return 0; /* If the return value is > 0, we need to request a rescan */ (void) btrfs_quota_scan_start(fd); return 1; } } int btrfs_qgroup_assign(int fd, uint64_t child, uint64_t parent) { return qgroup_assign_or_unassign(fd, true, child, parent); } int btrfs_qgroup_unassign(int fd, uint64_t child, uint64_t parent) { return qgroup_assign_or_unassign(fd, false, child, parent); } static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol_id, BtrfsRemoveFlags flags) { struct btrfs_ioctl_search_args args = { .key.tree_id = BTRFS_ROOT_TREE_OBJECTID, .key.min_objectid = BTRFS_FIRST_FREE_OBJECTID, .key.max_objectid = BTRFS_LAST_FREE_OBJECTID, .key.min_type = BTRFS_ROOT_BACKREF_KEY, .key.max_type = BTRFS_ROOT_BACKREF_KEY, .key.min_transid = 0, .key.max_transid = (uint64_t) -1, }; struct btrfs_ioctl_vol_args vol_args = {}; _cleanup_close_ int subvol_fd = -1; struct stat st; bool made_writable = false; int r; assert(fd >= 0); assert(subvolume); if (fstat(fd, &st) < 0) return -errno; if (!S_ISDIR(st.st_mode)) return -EINVAL; subvol_fd = openat(fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); if (subvol_fd < 0) return -errno; if (subvol_id == 0) { r = btrfs_subvol_get_id_fd(subvol_fd, &subvol_id); if (r < 0) return r; } /* First, try to remove the subvolume. If it happens to be * already empty, this will just work. */ strncpy(vol_args.name, subvolume, sizeof(vol_args.name)-1); if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) >= 0) { (void) btrfs_qgroup_destroy_recursive(fd, subvol_id); /* for the leaf subvolumes, the qgroup id is identical to the subvol id */ return 0; } if (!(flags & BTRFS_REMOVE_RECURSIVE) || errno != ENOTEMPTY) return -errno; /* OK, the subvolume is not empty, let's look for child * subvolumes, and remove them, first */ args.key.min_offset = args.key.max_offset = subvol_id; while (btrfs_ioctl_search_args_compare(&args) <= 0) { const struct btrfs_ioctl_search_header *sh; unsigned i; args.key.nr_items = 256; if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) return -errno; if (args.key.nr_items <= 0) break; FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { _cleanup_free_ char *p = NULL; const struct btrfs_root_ref *ref; struct btrfs_ioctl_ino_lookup_args ino_args; btrfs_ioctl_search_args_set(&args, sh); if (sh->type != BTRFS_ROOT_BACKREF_KEY) continue; if (sh->offset != subvol_id) continue; ref = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); p = strndup((char*) ref + sizeof(struct btrfs_root_ref), le64toh(ref->name_len)); if (!p) return -ENOMEM; zero(ino_args); ino_args.treeid = subvol_id; ino_args.objectid = htole64(ref->dirid); if (ioctl(fd, BTRFS_IOC_INO_LOOKUP, &ino_args) < 0) return -errno; if (!made_writable) { r = btrfs_subvol_set_read_only_fd(subvol_fd, false); if (r < 0) return r; made_writable = true; } if (isempty(ino_args.name)) /* Subvolume is in the top-level * directory of the subvolume. */ r = subvol_remove_children(subvol_fd, p, sh->objectid, flags); else { _cleanup_close_ int child_fd = -1; /* Subvolume is somewhere further down, * hence we need to open the * containing directory first */ child_fd = openat(subvol_fd, ino_args.name, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); if (child_fd < 0) return -errno; r = subvol_remove_children(child_fd, p, sh->objectid, flags); } if (r < 0) return r; } /* Increase search key by one, to read the next item, if we can. */ if (!btrfs_ioctl_search_args_inc(&args)) break; } /* OK, the child subvolumes should all be gone now, let's try * again to remove the subvolume */ if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) < 0) return -errno; (void) btrfs_qgroup_destroy_recursive(fd, subvol_id); return 0; } int btrfs_subvol_remove(const char *path, BtrfsRemoveFlags flags) { _cleanup_close_ int fd = -1; const char *subvolume; int r; assert(path); r = extract_subvolume_name(path, &subvolume); if (r < 0) return r; fd = open_parent(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); if (fd < 0) return fd; return subvol_remove_children(fd, subvolume, 0, flags); } int btrfs_subvol_remove_fd(int fd, const char *subvolume, BtrfsRemoveFlags flags) { return subvol_remove_children(fd, subvolume, 0, flags); } int btrfs_qgroup_copy_limits(int fd, uint64_t old_qgroupid, uint64_t new_qgroupid) { struct btrfs_ioctl_search_args args = { /* Tree of quota items */ .key.tree_id = BTRFS_QUOTA_TREE_OBJECTID, /* The object ID is always 0 */ .key.min_objectid = 0, .key.max_objectid = 0, /* Look precisely for the quota items */ .key.min_type = BTRFS_QGROUP_LIMIT_KEY, .key.max_type = BTRFS_QGROUP_LIMIT_KEY, /* For our qgroup */ .key.min_offset = old_qgroupid, .key.max_offset = old_qgroupid, /* No restrictions on the other components */ .key.min_transid = 0, .key.max_transid = (uint64_t) -1, }; int r; r = btrfs_is_filesystem(fd); if (r < 0) return r; if (!r) return -ENOTTY; while (btrfs_ioctl_search_args_compare(&args) <= 0) { const struct btrfs_ioctl_search_header *sh; unsigned i; args.key.nr_items = 256; if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) { if (errno == ENOENT) /* quota tree missing: quota is not enabled, hence nothing to copy */ break; return -errno; } if (args.key.nr_items <= 0) break; FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { const struct btrfs_qgroup_limit_item *qli = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); struct btrfs_ioctl_qgroup_limit_args qargs; unsigned c; /* Make sure we start the next search at least from this entry */ btrfs_ioctl_search_args_set(&args, sh); if (sh->objectid != 0) continue; if (sh->type != BTRFS_QGROUP_LIMIT_KEY) continue; if (sh->offset != old_qgroupid) continue; /* We found the entry, now copy things over. */ qargs = (struct btrfs_ioctl_qgroup_limit_args) { .qgroupid = new_qgroupid, .lim.max_rfer = le64toh(qli->max_rfer), .lim.max_excl = le64toh(qli->max_excl), .lim.rsv_rfer = le64toh(qli->rsv_rfer), .lim.rsv_excl = le64toh(qli->rsv_excl), .lim.flags = le64toh(qli->flags) & (BTRFS_QGROUP_LIMIT_MAX_RFER| BTRFS_QGROUP_LIMIT_MAX_EXCL| BTRFS_QGROUP_LIMIT_RSV_RFER| BTRFS_QGROUP_LIMIT_RSV_EXCL), }; for (c = 0;; c++) { if (ioctl(fd, BTRFS_IOC_QGROUP_LIMIT, &qargs) < 0) { if (errno == EBUSY && c < 10) { (void) btrfs_quota_scan_wait(fd); continue; } return -errno; } break; } return 1; } /* Increase search key by one, to read the next item, if we can. */ if (!btrfs_ioctl_search_args_inc(&args)) break; } return 0; } static int copy_quota_hierarchy(int fd, uint64_t old_subvol_id, uint64_t new_subvol_id) { _cleanup_free_ uint64_t *old_qgroups = NULL, *old_parent_qgroups = NULL; bool copy_from_parent = false, insert_intermediary_qgroup = false; int n_old_qgroups, n_old_parent_qgroups, r, i; uint64_t old_parent_id; assert(fd >= 0); /* Copies a reduced form of quota information from the old to * the new subvolume. */ n_old_qgroups = btrfs_qgroup_find_parents(fd, old_subvol_id, &old_qgroups); if (n_old_qgroups <= 0) /* Nothing to copy */ return n_old_qgroups; r = btrfs_subvol_get_parent(fd, old_subvol_id, &old_parent_id); if (r == -ENXIO) /* We have no parent, hence nothing to copy. */ n_old_parent_qgroups = 0; else if (r < 0) return r; else { n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups); if (n_old_parent_qgroups < 0) return n_old_parent_qgroups; } for (i = 0; i < n_old_qgroups; i++) { uint64_t id; int j; r = btrfs_qgroupid_split(old_qgroups[i], NULL, &id); if (r < 0) return r; if (id == old_subvol_id) { /* The old subvolume was member of a qgroup * that had the same id, but a different level * as it self. Let's set up something similar * in the destination. */ insert_intermediary_qgroup = true; break; } for (j = 0; j < n_old_parent_qgroups; j++) if (old_parent_qgroups[j] == old_qgroups[i]) { /* The old subvolume shared a common * parent qgroup with its parent * subvolume. Let's set up something * similar in the destination. */ copy_from_parent = true; } } if (!insert_intermediary_qgroup && !copy_from_parent) return 0; return btrfs_subvol_auto_qgroup_fd(fd, new_subvol_id, insert_intermediary_qgroup); } static int copy_subtree_quota_limits(int fd, uint64_t old_subvol, uint64_t new_subvol) { uint64_t old_subtree_qgroup, new_subtree_qgroup; bool changed; int r; /* First copy the leaf limits */ r = btrfs_qgroup_copy_limits(fd, old_subvol, new_subvol); if (r < 0) return r; changed = r > 0; /* Then, try to copy the subtree limits, if there are any. */ r = btrfs_subvol_find_subtree_qgroup(fd, old_subvol, &old_subtree_qgroup); if (r < 0) return r; if (r == 0) return changed; r = btrfs_subvol_find_subtree_qgroup(fd, new_subvol, &new_subtree_qgroup); if (r < 0) return r; if (r == 0) return changed; r = btrfs_qgroup_copy_limits(fd, old_subtree_qgroup, new_subtree_qgroup); if (r != 0) return r; return changed; } static int subvol_snapshot_children(int old_fd, int new_fd, const char *subvolume, uint64_t old_subvol_id, BtrfsSnapshotFlags flags) { struct btrfs_ioctl_search_args args = { .key.tree_id = BTRFS_ROOT_TREE_OBJECTID, .key.min_objectid = BTRFS_FIRST_FREE_OBJECTID, .key.max_objectid = BTRFS_LAST_FREE_OBJECTID, .key.min_type = BTRFS_ROOT_BACKREF_KEY, .key.max_type = BTRFS_ROOT_BACKREF_KEY, .key.min_transid = 0, .key.max_transid = (uint64_t) -1, }; struct btrfs_ioctl_vol_args_v2 vol_args = { .flags = flags & BTRFS_SNAPSHOT_READ_ONLY ? BTRFS_SUBVOL_RDONLY : 0, .fd = old_fd, }; _cleanup_close_ int subvolume_fd = -1; uint64_t new_subvol_id; int r; assert(old_fd >= 0); assert(new_fd >= 0); assert(subvolume); strncpy(vol_args.name, subvolume, sizeof(vol_args.name)-1); if (ioctl(new_fd, BTRFS_IOC_SNAP_CREATE_V2, &vol_args) < 0) return -errno; if (!(flags & BTRFS_SNAPSHOT_RECURSIVE) && !(flags & BTRFS_SNAPSHOT_QUOTA)) return 0; if (old_subvol_id == 0) { r = btrfs_subvol_get_id_fd(old_fd, &old_subvol_id); if (r < 0) return r; } r = btrfs_subvol_get_id(new_fd, vol_args.name, &new_subvol_id); if (r < 0) return r; if (flags & BTRFS_SNAPSHOT_QUOTA) (void) copy_quota_hierarchy(new_fd, old_subvol_id, new_subvol_id); if (!(flags & BTRFS_SNAPSHOT_RECURSIVE)) { if (flags & BTRFS_SNAPSHOT_QUOTA) (void) copy_subtree_quota_limits(new_fd, old_subvol_id, new_subvol_id); return 0; } args.key.min_offset = args.key.max_offset = old_subvol_id; while (btrfs_ioctl_search_args_compare(&args) <= 0) { const struct btrfs_ioctl_search_header *sh; unsigned i; args.key.nr_items = 256; if (ioctl(old_fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) return -errno; if (args.key.nr_items <= 0) break; FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { _cleanup_free_ char *p = NULL, *c = NULL, *np = NULL; struct btrfs_ioctl_ino_lookup_args ino_args; const struct btrfs_root_ref *ref; _cleanup_close_ int old_child_fd = -1, new_child_fd = -1; btrfs_ioctl_search_args_set(&args, sh); if (sh->type != BTRFS_ROOT_BACKREF_KEY) continue; /* Avoid finding the source subvolume a second * time */ if (sh->offset != old_subvol_id) continue; /* Avoid running into loops if the new * subvolume is below the old one. */ if (sh->objectid == new_subvol_id) continue; ref = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); p = strndup((char*) ref + sizeof(struct btrfs_root_ref), le64toh(ref->name_len)); if (!p) return -ENOMEM; zero(ino_args); ino_args.treeid = old_subvol_id; ino_args.objectid = htole64(ref->dirid); if (ioctl(old_fd, BTRFS_IOC_INO_LOOKUP, &ino_args) < 0) return -errno; /* The kernel returns an empty name if the * subvolume is in the top-level directory, * and otherwise appends a slash, so that we * can just concatenate easily here, without * adding a slash. */ c = strappend(ino_args.name, p); if (!c) return -ENOMEM; old_child_fd = openat(old_fd, c, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); if (old_child_fd < 0) return -errno; np = strjoin(subvolume, "/", ino_args.name, NULL); if (!np) return -ENOMEM; new_child_fd = openat(new_fd, np, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); if (new_child_fd < 0) return -errno; if (flags & BTRFS_SNAPSHOT_READ_ONLY) { /* If the snapshot is read-only we * need to mark it writable * temporarily, to put the subsnapshot * into place. */ if (subvolume_fd < 0) { subvolume_fd = openat(new_fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); if (subvolume_fd < 0) return -errno; } r = btrfs_subvol_set_read_only_fd(subvolume_fd, false); if (r < 0) return r; } /* When btrfs clones the subvolumes, child * subvolumes appear as empty directories. Remove * them, so that we can create a new snapshot * in their place */ if (unlinkat(new_child_fd, p, AT_REMOVEDIR) < 0) { int k = -errno; if (flags & BTRFS_SNAPSHOT_READ_ONLY) (void) btrfs_subvol_set_read_only_fd(subvolume_fd, true); return k; } r = subvol_snapshot_children(old_child_fd, new_child_fd, p, sh->objectid, flags & ~BTRFS_SNAPSHOT_FALLBACK_COPY); /* Restore the readonly flag */ if (flags & BTRFS_SNAPSHOT_READ_ONLY) { int k; k = btrfs_subvol_set_read_only_fd(subvolume_fd, true); if (r >= 0 && k < 0) return k; } if (r < 0) return r; } /* Increase search key by one, to read the next item, if we can. */ if (!btrfs_ioctl_search_args_inc(&args)) break; } if (flags & BTRFS_SNAPSHOT_QUOTA) (void) copy_subtree_quota_limits(new_fd, old_subvol_id, new_subvol_id); return 0; } int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlags flags) { _cleanup_close_ int new_fd = -1; const char *subvolume; int r; assert(old_fd >= 0); assert(new_path); r = btrfs_is_subvol_fd(old_fd); if (r < 0) return r; if (r == 0) { if (!(flags & BTRFS_SNAPSHOT_FALLBACK_COPY)) return -EISDIR; r = btrfs_subvol_make(new_path); if (r < 0) return r; r = copy_directory_fd(old_fd, new_path, true); if (r < 0) { (void) btrfs_subvol_remove(new_path, BTRFS_REMOVE_QUOTA); return r; } if (flags & BTRFS_SNAPSHOT_READ_ONLY) { r = btrfs_subvol_set_read_only(new_path, true); if (r < 0) { (void) btrfs_subvol_remove(new_path, BTRFS_REMOVE_QUOTA); return r; } } return 0; } r = extract_subvolume_name(new_path, &subvolume); if (r < 0) return r; new_fd = open_parent(new_path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); if (new_fd < 0) return new_fd; return subvol_snapshot_children(old_fd, new_fd, subvolume, 0, flags); } int btrfs_subvol_snapshot(const char *old_path, const char *new_path, BtrfsSnapshotFlags flags) { _cleanup_close_ int old_fd = -1; assert(old_path); assert(new_path); old_fd = open(old_path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); if (old_fd < 0) return -errno; return btrfs_subvol_snapshot_fd(old_fd, new_path, flags); } int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret) { struct btrfs_ioctl_search_args args = { /* Tree of quota items */ .key.tree_id = BTRFS_QUOTA_TREE_OBJECTID, /* Look precisely for the quota relation items */ .key.min_type = BTRFS_QGROUP_RELATION_KEY, .key.max_type = BTRFS_QGROUP_RELATION_KEY, /* No restrictions on the other components */ .key.min_offset = 0, .key.max_offset = (uint64_t) -1, .key.min_transid = 0, .key.max_transid = (uint64_t) -1, }; _cleanup_free_ uint64_t *items = NULL; size_t n_items = 0, n_allocated = 0; int r; assert(fd >= 0); assert(ret); if (qgroupid == 0) { r = btrfs_subvol_get_id_fd(fd, &qgroupid); if (r < 0) return r; } else { r = btrfs_is_filesystem(fd); if (r < 0) return r; if (!r) return -ENOTTY; } args.key.min_objectid = args.key.max_objectid = qgroupid; while (btrfs_ioctl_search_args_compare(&args) <= 0) { const struct btrfs_ioctl_search_header *sh; unsigned i; args.key.nr_items = 256; if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) { if (errno == ENOENT) /* quota tree missing: quota is disabled */ break; return -errno; } if (args.key.nr_items <= 0) break; FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { /* Make sure we start the next search at least from this entry */ btrfs_ioctl_search_args_set(&args, sh); if (sh->type != BTRFS_QGROUP_RELATION_KEY) continue; if (sh->offset < sh->objectid) continue; if (sh->objectid != qgroupid) continue; if (!GREEDY_REALLOC(items, n_allocated, n_items+1)) return -ENOMEM; items[n_items++] = sh->offset; } /* Increase search key by one, to read the next item, if we can. */ if (!btrfs_ioctl_search_args_inc(&args)) break; } if (n_items <= 0) { *ret = NULL; return 0; } *ret = items; items = NULL; return (int) n_items; } int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermediary_qgroup) { _cleanup_free_ uint64_t *qgroups = NULL; uint64_t parent_subvol; bool changed = false; int n = 0, r; assert(fd >= 0); /* * Sets up the specified subvolume's qgroup automatically in * one of two ways: * * If insert_intermediary_qgroup is false, the subvolume's * leaf qgroup will be assigned to the same parent qgroups as * the subvolume's parent subvolume. * * If insert_intermediary_qgroup is true a new intermediary * higher-level qgroup is created, with a higher level number, * but reusing the id of the subvolume. The level number is * picked as one smaller than the lowest level qgroup the * parent subvolume is a member of. If the parent subvolume's * leaf qgroup is assigned to no higher-level qgroup a new * qgroup of level 255 is created instead. Either way, the new * qgroup is then assigned to the parent's higher-level * qgroup, and the subvolume itself is assigned to it. * * If the subvolume is already assigned to a higher level * qgroup, no operation is executed. * * Effectively this means: regardless if * insert_intermediary_qgroup is true or not, after this * function is invoked the subvolume will be accounted within * the same qgroups as the parent. However, if it is true, it * will also get its own higher-level qgroup, which may in * turn be used by subvolumes created beneath this subvolume * later on. * * This hence defines a simple default qgroup setup for * subvolumes, as long as this function is invoked on each * created subvolume: each subvolume is always accounting * together with its immediate parents. Optionally, if * insert_intermediary_qgroup is true, it will also get a * qgroup that then includes all its own child subvolumes. */ if (subvol_id == 0) { r = btrfs_is_subvol_fd(fd); if (r < 0) return r; if (!r) return -ENOTTY; r = btrfs_subvol_get_id_fd(fd, &subvol_id); if (r < 0) return r; } n = btrfs_qgroup_find_parents(fd, subvol_id, &qgroups); if (n < 0) return n; if (n > 0) /* already parent qgroups set up, let's bail */ return 0; qgroups = mfree(qgroups); r = btrfs_subvol_get_parent(fd, subvol_id, &parent_subvol); if (r == -ENXIO) /* No parent, hence no qgroup memberships */ n = 0; else if (r < 0) return r; else { n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups); if (n < 0) return n; } if (insert_intermediary_qgroup) { uint64_t lowest = 256, new_qgroupid; bool created = false; int i; /* Determine the lowest qgroup that the parent * subvolume is assigned to. */ for (i = 0; i < n; i++) { uint64_t level; r = btrfs_qgroupid_split(qgroups[i], &level, NULL); if (r < 0) return r; if (level < lowest) lowest = level; } if (lowest <= 1) /* There are no levels left we could use insert an intermediary qgroup at */ return -EBUSY; r = btrfs_qgroupid_make(lowest - 1, subvol_id, &new_qgroupid); if (r < 0) return r; /* Create the new intermediary group, unless it already exists */ r = btrfs_qgroup_create(fd, new_qgroupid); if (r < 0 && r != -EEXIST) return r; if (r >= 0) changed = created = true; for (i = 0; i < n; i++) { r = btrfs_qgroup_assign(fd, new_qgroupid, qgroups[i]); if (r < 0 && r != -EEXIST) { if (created) (void) btrfs_qgroup_destroy_recursive(fd, new_qgroupid); return r; } if (r >= 0) changed = true; } r = btrfs_qgroup_assign(fd, subvol_id, new_qgroupid); if (r < 0 && r != -EEXIST) { if (created) (void) btrfs_qgroup_destroy_recursive(fd, new_qgroupid); return r; } if (r >= 0) changed = true; } else { int i; /* Assign our subvolume to all the same qgroups as the parent */ for (i = 0; i < n; i++) { r = btrfs_qgroup_assign(fd, subvol_id, qgroups[i]); if (r < 0 && r != -EEXIST) return r; if (r >= 0) changed = true; } } return changed; } int btrfs_subvol_auto_qgroup(const char *path, uint64_t subvol_id, bool create_intermediary_qgroup) { _cleanup_close_ int fd = -1; fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); if (fd < 0) return -errno; return btrfs_subvol_auto_qgroup_fd(fd, subvol_id, create_intermediary_qgroup); } int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret) { struct btrfs_ioctl_search_args args = { /* Tree of tree roots */ .key.tree_id = BTRFS_ROOT_TREE_OBJECTID, /* Look precisely for the subvolume items */ .key.min_type = BTRFS_ROOT_BACKREF_KEY, .key.max_type = BTRFS_ROOT_BACKREF_KEY, /* No restrictions on the other components */ .key.min_offset = 0, .key.max_offset = (uint64_t) -1, .key.min_transid = 0, .key.max_transid = (uint64_t) -1, }; int r; assert(fd >= 0); assert(ret); if (subvol_id == 0) { r = btrfs_subvol_get_id_fd(fd, &subvol_id); if (r < 0) return r; } else { r = btrfs_is_filesystem(fd); if (r < 0) return r; if (!r) return -ENOTTY; } args.key.min_objectid = args.key.max_objectid = subvol_id; while (btrfs_ioctl_search_args_compare(&args) <= 0) { const struct btrfs_ioctl_search_header *sh; unsigned i; args.key.nr_items = 256; if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) return negative_errno(); if (args.key.nr_items <= 0) break; FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { if (sh->type != BTRFS_ROOT_BACKREF_KEY) continue; if (sh->objectid != subvol_id) continue; *ret = sh->offset; return 0; } } return -ENXIO; } systemd-229/src/basic/btrfs-util.h000066400000000000000000000112351265713322000171770ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include #include #include #include "sd-id128.h" #include "time-util.h" typedef struct BtrfsSubvolInfo { uint64_t subvol_id; usec_t otime; sd_id128_t uuid; sd_id128_t parent_uuid; bool read_only; } BtrfsSubvolInfo; typedef struct BtrfsQuotaInfo { uint64_t referenced; uint64_t exclusive; uint64_t referenced_max; uint64_t exclusive_max; } BtrfsQuotaInfo; typedef enum BtrfsSnapshotFlags { BTRFS_SNAPSHOT_FALLBACK_COPY = 1, BTRFS_SNAPSHOT_READ_ONLY = 2, BTRFS_SNAPSHOT_RECURSIVE = 4, BTRFS_SNAPSHOT_QUOTA = 8, } BtrfsSnapshotFlags; typedef enum BtrfsRemoveFlags { BTRFS_REMOVE_RECURSIVE = 1, BTRFS_REMOVE_QUOTA = 2, } BtrfsRemoveFlags; int btrfs_is_filesystem(int fd); int btrfs_is_subvol_fd(int fd); int btrfs_is_subvol(const char *path); int btrfs_reflink(int infd, int outfd); int btrfs_clone_range(int infd, uint64_t in_offset, int ofd, uint64_t out_offset, uint64_t sz); int btrfs_get_block_device_fd(int fd, dev_t *dev); int btrfs_get_block_device(const char *path, dev_t *dev); int btrfs_defrag_fd(int fd); int btrfs_defrag(const char *p); int btrfs_quota_enable_fd(int fd, bool b); int btrfs_quota_enable(const char *path, bool b); int btrfs_quota_scan_start(int fd); int btrfs_quota_scan_wait(int fd); int btrfs_quota_scan_ongoing(int fd); int btrfs_resize_loopback_fd(int fd, uint64_t size, bool grow_only); int btrfs_resize_loopback(const char *path, uint64_t size, bool grow_only); int btrfs_subvol_make(const char *path); int btrfs_subvol_make_label(const char *path); int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlags flags); int btrfs_subvol_snapshot(const char *old_path, const char *new_path, BtrfsSnapshotFlags flags); int btrfs_subvol_remove(const char *path, BtrfsRemoveFlags flags); int btrfs_subvol_remove_fd(int fd, const char *subvolume, BtrfsRemoveFlags flags); int btrfs_subvol_set_read_only_fd(int fd, bool b); int btrfs_subvol_set_read_only(const char *path, bool b); int btrfs_subvol_get_read_only_fd(int fd); int btrfs_subvol_get_id(int fd, const char *subvolume, uint64_t *ret); int btrfs_subvol_get_id_fd(int fd, uint64_t *ret); int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret); int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *info); int btrfs_subvol_find_subtree_qgroup(int fd, uint64_t subvol_id, uint64_t *ret); int btrfs_subvol_get_subtree_quota(const char *path, uint64_t subvol_id, BtrfsQuotaInfo *quota); int btrfs_subvol_get_subtree_quota_fd(int fd, uint64_t subvol_id, BtrfsQuotaInfo *quota); int btrfs_subvol_set_subtree_quota_limit(const char *path, uint64_t subvol_id, uint64_t referenced_max); int btrfs_subvol_set_subtree_quota_limit_fd(int fd, uint64_t subvol_id, uint64_t referenced_max); int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool new_qgroup); int btrfs_subvol_auto_qgroup(const char *path, uint64_t subvol_id, bool create_intermediary_qgroup); int btrfs_qgroupid_make(uint64_t level, uint64_t id, uint64_t *ret); int btrfs_qgroupid_split(uint64_t qgroupid, uint64_t *level, uint64_t *id); int btrfs_qgroup_create(int fd, uint64_t qgroupid); int btrfs_qgroup_destroy(int fd, uint64_t qgroupid); int btrfs_qgroup_destroy_recursive(int fd, uint64_t qgroupid); int btrfs_qgroup_set_limit_fd(int fd, uint64_t qgroupid, uint64_t referenced_max); int btrfs_qgroup_set_limit(const char *path, uint64_t qgroupid, uint64_t referenced_max); int btrfs_qgroup_copy_limits(int fd, uint64_t old_qgroupid, uint64_t new_qgroupid); int btrfs_qgroup_assign(int fd, uint64_t child, uint64_t parent); int btrfs_qgroup_unassign(int fd, uint64_t child, uint64_t parent); int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret); int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *quota); int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *quota); systemd-229/src/basic/build.h000066400000000000000000000077451265713322000162160ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #ifdef HAVE_PAM #define _PAM_FEATURE_ "+PAM" #else #define _PAM_FEATURE_ "-PAM" #endif #ifdef HAVE_AUDIT #define _AUDIT_FEATURE_ "+AUDIT" #else #define _AUDIT_FEATURE_ "-AUDIT" #endif #ifdef HAVE_SELINUX #define _SELINUX_FEATURE_ "+SELINUX" #else #define _SELINUX_FEATURE_ "-SELINUX" #endif #ifdef HAVE_APPARMOR #define _APPARMOR_FEATURE_ "+APPARMOR" #else #define _APPARMOR_FEATURE_ "-APPARMOR" #endif #ifdef HAVE_IMA #define _IMA_FEATURE_ "+IMA" #else #define _IMA_FEATURE_ "-IMA" #endif #ifdef HAVE_SMACK #define _SMACK_FEATURE_ "+SMACK" #else #define _SMACK_FEATURE_ "-SMACK" #endif #ifdef HAVE_SYSV_COMPAT #define _SYSVINIT_FEATURE_ "+SYSVINIT" #else #define _SYSVINIT_FEATURE_ "-SYSVINIT" #endif #ifdef HAVE_UTMP #define _UTMP_FEATURE_ "+UTMP" #else #define _UTMP_FEATURE_ "-UTMP" #endif #ifdef HAVE_LIBCRYPTSETUP #define _LIBCRYPTSETUP_FEATURE_ "+LIBCRYPTSETUP" #else #define _LIBCRYPTSETUP_FEATURE_ "-LIBCRYPTSETUP" #endif #ifdef HAVE_GCRYPT #define _GCRYPT_FEATURE_ "+GCRYPT" #else #define _GCRYPT_FEATURE_ "-GCRYPT" #endif #ifdef HAVE_GNUTLS #define _GNUTLS_FEATURE_ "+GNUTLS" #else #define _GNUTLS_FEATURE_ "-GNUTLS" #endif #ifdef HAVE_ACL #define _ACL_FEATURE_ "+ACL" #else #define _ACL_FEATURE_ "-ACL" #endif #ifdef HAVE_XZ #define _XZ_FEATURE_ "+XZ" #else #define _XZ_FEATURE_ "-XZ" #endif #ifdef HAVE_LZ4 #define _LZ4_FEATURE_ "+LZ4" #else #define _LZ4_FEATURE_ "-LZ4" #endif #ifdef HAVE_SECCOMP #define _SECCOMP_FEATURE_ "+SECCOMP" #else #define _SECCOMP_FEATURE_ "-SECCOMP" #endif #ifdef HAVE_BLKID #define _BLKID_FEATURE_ "+BLKID" #else #define _BLKID_FEATURE_ "-BLKID" #endif #ifdef HAVE_ELFUTILS #define _ELFUTILS_FEATURE_ "+ELFUTILS" #else #define _ELFUTILS_FEATURE_ "-ELFUTILS" #endif #ifdef HAVE_KMOD #define _KMOD_FEATURE_ "+KMOD" #else #define _KMOD_FEATURE_ "-KMOD" #endif #ifdef HAVE_LIBIDN #define _IDN_FEATURE_ "+IDN" #else #define _IDN_FEATURE_ "-IDN" #endif #define SYSTEMD_FEATURES \ _PAM_FEATURE_ " " \ _AUDIT_FEATURE_ " " \ _SELINUX_FEATURE_ " " \ _IMA_FEATURE_ " " \ _APPARMOR_FEATURE_ " " \ _SMACK_FEATURE_ " " \ _SYSVINIT_FEATURE_ " " \ _UTMP_FEATURE_ " " \ _LIBCRYPTSETUP_FEATURE_ " " \ _GCRYPT_FEATURE_ " " \ _GNUTLS_FEATURE_ " " \ _ACL_FEATURE_ " " \ _XZ_FEATURE_ " " \ _LZ4_FEATURE_ " " \ _SECCOMP_FEATURE_ " " \ _BLKID_FEATURE_ " " \ _ELFUTILS_FEATURE_ " " \ _KMOD_FEATURE_ " " \ _IDN_FEATURE_ systemd-229/src/basic/bus-label.c000066400000000000000000000054211265713322000167450ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "bus-label.h" #include "hexdecoct.h" #include "macro.h" char *bus_label_escape(const char *s) { char *r, *t; const char *f; assert_return(s, NULL); /* Escapes all chars that D-Bus' object path cannot deal * with. Can be reversed with bus_path_unescape(). We special * case the empty string. */ if (*s == 0) return strdup("_"); r = new(char, strlen(s)*3 + 1); if (!r) return NULL; for (f = s, t = r; *f; f++) { /* Escape everything that is not a-zA-Z0-9. We also * escape 0-9 if it's the first character */ if (!(*f >= 'A' && *f <= 'Z') && !(*f >= 'a' && *f <= 'z') && !(f > s && *f >= '0' && *f <= '9')) { *(t++) = '_'; *(t++) = hexchar(*f >> 4); *(t++) = hexchar(*f); } else *(t++) = *f; } *t = 0; return r; } char *bus_label_unescape_n(const char *f, size_t l) { char *r, *t; size_t i; assert_return(f, NULL); /* Special case for the empty string */ if (l == 1 && *f == '_') return strdup(""); r = new(char, l + 1); if (!r) return NULL; for (i = 0, t = r; i < l; ++i) { if (f[i] == '_') { int a, b; if (l - i < 3 || (a = unhexchar(f[i + 1])) < 0 || (b = unhexchar(f[i + 2])) < 0) { /* Invalid escape code, let's take it literal then */ *(t++) = '_'; } else { *(t++) = (char) ((a << 4) | b); i += 2; } } else *(t++) = f[i]; } *t = 0; return r; } systemd-229/src/basic/bus-label.h000066400000000000000000000017541265713322000167570ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include char *bus_label_escape(const char *s); char *bus_label_unescape_n(const char *f, size_t l); static inline char *bus_label_unescape(const char *f) { return bus_label_unescape_n(f, f ? strlen(f) : 0); } systemd-229/src/basic/c-rbtree.c000066400000000000000000000634451265713322000166140ustar00rootroot00000000000000/*** This file is part of systemd. See COPYING for details. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* * RB-Tree Implementation * This implements the insertion/removal of elements in RB-Trees. You're highly * recommended to have an RB-Tree documentation at hand when reading this. Both * insertion and removal can be split into a handful of situations that can * occur. Those situations are enumerated as "Case 1" to "Case n" here, and * follow closely the cases described in most RB-Tree documentations. This file * does not explain why it is enough to handle just those cases, nor does it * provide a proof of correctness. Dig out your algorithm 101 handbook if * you're interested. * * This implementation is *not* straightforward. Usually, a handful of * rotation, reparent, swap and link helpers can be used to implement the * rebalance operations. However, those often perform unnecessary writes. * Therefore, this implementation hard-codes all the operations. You're highly * recommended to look at the two basic helpers before reading the code: * c_rbtree_swap_child() * c_rbtree_set_parent_and_color() * Those are the only helpers used, hence, you should really know what they do * before digging into the code. * * For a highlevel documentation of the API, see the header file and docbook * comments. */ #include #include #include "c-rbtree.h" enum { C_RBNODE_RED = 0, C_RBNODE_BLACK = 1, }; static inline unsigned long c_rbnode_color(CRBNode *n) { return (unsigned long)n->__parent_and_color & 1UL; } static inline _Bool c_rbnode_is_red(CRBNode *n) { return c_rbnode_color(n) == C_RBNODE_RED; } static inline _Bool c_rbnode_is_black(CRBNode *n) { return c_rbnode_color(n) == C_RBNODE_BLACK; } /** * c_rbnode_leftmost() - return leftmost child * @n: current node, or NULL * * This returns the leftmost child of @n. If @n is NULL, this will return NULL. * In all other cases, this function returns a valid pointer. That is, if @n * does not have any left children, this returns @n. * * Worst case runtime (n: number of elements in tree): O(log(n)) * * Return: Pointer to leftmost child, or NULL. */ CRBNode *c_rbnode_leftmost(CRBNode *n) { if (n) while (n->left) n = n->left; return n; } /** * c_rbnode_rightmost() - return rightmost child * @n: current node, or NULL * * This returns the rightmost child of @n. If @n is NULL, this will return * NULL. In all other cases, this function returns a valid pointer. That is, if * @n does not have any right children, this returns @n. * * Worst case runtime (n: number of elements in tree): O(log(n)) * * Return: Pointer to rightmost child, or NULL. */ CRBNode *c_rbnode_rightmost(CRBNode *n) { if (n) while (n->right) n = n->right; return n; } /** * c_rbnode_next() - return next node * @n: current node, or NULL * * An RB-Tree always defines a linear order of its elements. This function * returns the logically next node to @n. If @n is NULL, the last node or * unlinked, this returns NULL. * * Worst case runtime (n: number of elements in tree): O(log(n)) * * Return: Pointer to next node, or NULL. */ CRBNode *c_rbnode_next(CRBNode *n) { CRBNode *p; if (!c_rbnode_is_linked(n)) return NULL; if (n->right) return c_rbnode_leftmost(n->right); while ((p = c_rbnode_parent(n)) && n == p->right) n = p; return p; } /** * c_rbnode_prev() - return previous node * @n: current node, or NULL * * An RB-Tree always defines a linear order of its elements. This function * returns the logically previous node to @n. If @n is NULL, the first node or * unlinked, this returns NULL. * * Worst case runtime (n: number of elements in tree): O(log(n)) * * Return: Pointer to previous node, or NULL. */ CRBNode *c_rbnode_prev(CRBNode *n) { CRBNode *p; if (!c_rbnode_is_linked(n)) return NULL; if (n->left) return c_rbnode_rightmost(n->left); while ((p = c_rbnode_parent(n)) && n == p->left) n = p; return p; } /** * c_rbtree_first() - return first node * @t: tree to operate on * * An RB-Tree always defines a linear order of its elements. This function * returns the logically first node in @t. If @t is empty, NULL is returned. * * Fixed runtime (n: number of elements in tree): O(log(n)) * * Return: Pointer to first node, or NULL. */ CRBNode *c_rbtree_first(CRBTree *t) { assert(t); return c_rbnode_leftmost(t->root); } /** * c_rbtree_last() - return last node * @t: tree to operate on * * An RB-Tree always defines a linear order of its elements. This function * returns the logically last node in @t. If @t is empty, NULL is returned. * * Fixed runtime (n: number of elements in tree): O(log(n)) * * Return: Pointer to last node, or NULL. */ CRBNode *c_rbtree_last(CRBTree *t) { assert(t); return c_rbnode_rightmost(t->root); } /* * Set the color and parent of a node. This should be treated as a simple * assignment of the 'color' and 'parent' fields of the node. No other magic is * applied. But since both fields share its backing memory, this helper * function is provided. */ static inline void c_rbnode_set_parent_and_color(CRBNode *n, CRBNode *p, unsigned long c) { assert(!((unsigned long)p & 1)); assert(c < 2); n->__parent_and_color = (CRBNode*)((unsigned long)p | c); } /* same as c_rbnode_set_parent_and_color(), but keeps the current parent */ static inline void c_rbnode_set_color(CRBNode *n, unsigned long c) { c_rbnode_set_parent_and_color(n, c_rbnode_parent(n), c); } /* same as c_rbnode_set_parent_and_color(), but keeps the current color */ static inline void c_rbnode_set_parent(CRBNode *n, CRBNode *p) { c_rbnode_set_parent_and_color(n, p, c_rbnode_color(n)); } /* * This function partially replaces an existing child pointer to a new one. The * existing child must be given as @old, the new child as @new. @p must be the * parent of @old (or NULL if it has no parent). * This function ensures that the parent of @old now points to @new. However, * it does *NOT* change the parent pointer of @new. The caller must ensure * this. * If @p is NULL, this function ensures that the root-pointer is adjusted * instead (given as @t). */ static inline void c_rbtree_swap_child(CRBTree *t, CRBNode *p, CRBNode *old, CRBNode *new) { if (p) { if (p->left == old) p->left = new; else p->right = new; } else { t->root = new; } } static inline CRBNode *c_rbtree_paint_one(CRBTree *t, CRBNode *n) { CRBNode *p, *g, *gg, *u, *x; /* * Paint a single node according to RB-Tree rules. The node must * already be linked into the tree and painted red. * We repaint the node or rotate the tree, if required. In case a * recursive repaint is required, the next node to be re-painted * is returned. * p: parent * g: grandparent * gg: grandgrandparent * u: uncle * x: temporary */ /* node is red, so we can access the parent directly */ p = n->__parent_and_color; if (!p) { /* Case 1: * We reached the root. Mark it black and be done. As all * leaf-paths share the root, the ratio of black nodes on each * path stays the same. */ c_rbnode_set_parent_and_color(n, p, C_RBNODE_BLACK); n = NULL; } else if (c_rbnode_is_black(p)) { /* Case 2: * The parent is already black. As our node is red, we did not * change the number of black nodes on any path, nor do we have * multiple consecutive red nodes. */ n = NULL; } else if (p == p->__parent_and_color->left) { /* parent is red, so grandparent exists */ g = p->__parent_and_color; gg = c_rbnode_parent(g); u = g->right; if (u && c_rbnode_is_red(u)) { /* Case 3: * Parent and uncle are both red. We know the * grandparent must be black then. Repaint parent and * uncle black, the grandparent red and recurse into * the grandparent. */ c_rbnode_set_parent_and_color(p, g, C_RBNODE_BLACK); c_rbnode_set_parent_and_color(u, g, C_RBNODE_BLACK); c_rbnode_set_parent_and_color(g, gg, C_RBNODE_RED); n = g; } else { /* parent is red, uncle is black */ if (n == p->right) { /* Case 4: * We're the right child. Rotate on parent to * become left child, so we can handle it the * same as case 5. */ x = n->left; p->right = n->left; n->left = p; if (x) c_rbnode_set_parent_and_color(x, p, C_RBNODE_BLACK); c_rbnode_set_parent_and_color(p, n, C_RBNODE_RED); p = n; } /* 'n' is invalid from here on! */ n = NULL; /* Case 5: * We're the red left child or a red parent, black * grandparent and uncle. Rotate on grandparent and * switch color with parent. Number of black nodes on * each path stays the same, but we got rid of the * double red path. As the grandparent is still black, * we're done. */ x = p->right; g->left = x; p->right = g; if (x) c_rbnode_set_parent_and_color(x, g, C_RBNODE_BLACK); c_rbnode_set_parent_and_color(p, gg, C_RBNODE_BLACK); c_rbnode_set_parent_and_color(g, p, C_RBNODE_RED); c_rbtree_swap_child(t, gg, g, p); } } else /* if (p == p->__parent_and_color->left) */ { /* same as above, but mirrored */ g = p->__parent_and_color; gg = c_rbnode_parent(g); u = g->left; if (u && c_rbnode_is_red(u)) { c_rbnode_set_parent_and_color(p, g, C_RBNODE_BLACK); c_rbnode_set_parent_and_color(u, g, C_RBNODE_BLACK); c_rbnode_set_parent_and_color(g, gg, C_RBNODE_RED); n = g; } else { if (n == p->left) { x = n->right; p->left = n->right; n->right = p; if (x) c_rbnode_set_parent_and_color(x, p, C_RBNODE_BLACK); c_rbnode_set_parent_and_color(p, n, C_RBNODE_RED); p = n; } n = NULL; x = p->left; g->right = x; p->left = g; if (x) c_rbnode_set_parent_and_color(x, g, C_RBNODE_BLACK); c_rbnode_set_parent_and_color(p, gg, C_RBNODE_BLACK); c_rbnode_set_parent_and_color(g, p, C_RBNODE_RED); c_rbtree_swap_child(t, gg, g, p); } } return n; } static inline void c_rbtree_paint(CRBTree *t, CRBNode *n) { assert(t); assert(n); while (n) n = c_rbtree_paint_one(t, n); } /** * c_rbtree_add() - add node to tree * @t: tree to operate one * @p: parent node to link under, or NULL * @l: left/right slot of @p (or root) to link at * @n: node to add * * This links @n into the tree given as @t. The caller must provide the exact * spot where to link the node. That is, the caller must traverse the tree * based on their search order. Once they hit a leaf where to insert the node, * call this function to link it and rebalance the tree. * * A typical insertion would look like this (@t is your tree, @n is your node): * * CRBNode **i, *p; * * i = &t->root; * p = NULL; * while (*i) { * p = *i; * if (compare(n, *i) < 0) * i = &(*i)->left; * else * i = &(*i)->right; * } * * c_rbtree_add(t, p, i, n); * * Once the node is linked into the tree, a simple lookup on the same tree can * be coded like this: * * CRBNode *i; * * i = t->root; * while (i) { * int v = compare(n, i); * if (v < 0) * i = (*i)->left; * else if (v > 0) * i = (*i)->right; * else * break; * } * * When you add nodes to a tree, the memory contents of the node do not matter. * That is, there is no need to initialize the node via c_rbnode_init(). * However, if you relink nodes multiple times during their lifetime, it is * usually very convenient to use c_rbnode_init() and c_rbtree_remove_init(). * In those cases, you should validate that a node is unlinked before you call * c_rbtree_add(). */ void c_rbtree_add(CRBTree *t, CRBNode *p, CRBNode **l, CRBNode *n) { assert(t); assert(l); assert(n); assert(!p || l == &p->left || l == &p->right); assert(p || l == &t->root); c_rbnode_set_parent_and_color(n, p, C_RBNODE_RED); n->left = n->right = NULL; *l = n; c_rbtree_paint(t, n); } static inline CRBNode *c_rbtree_rebalance_one(CRBTree *t, CRBNode *p, CRBNode *n) { CRBNode *s, *x, *y, *g; /* * Rebalance tree after a node was removed. This happens only if you * remove a black node and one path is now left with an unbalanced * number or black nodes. * This function assumes all paths through p and n have one black node * less than all other paths. If recursive fixup is required, the * current node is returned. */ if (n == p->left) { s = p->right; if (c_rbnode_is_red(s)) { /* Case 3: * We have a red node as sibling. Rotate it onto our * side so we can later on turn it black. This way, we * gain the additional black node in our path. */ g = c_rbnode_parent(p); x = s->left; p->right = x; s->left = p; c_rbnode_set_parent_and_color(x, p, C_RBNODE_BLACK); c_rbnode_set_parent_and_color(s, g, c_rbnode_color(p)); c_rbnode_set_parent_and_color(p, s, C_RBNODE_RED); c_rbtree_swap_child(t, g, p, s); s = x; } x = s->right; if (!x || c_rbnode_is_black(x)) { y = s->left; if (!y || c_rbnode_is_black(y)) { /* Case 4: * Our sibling is black and has only black * children. Flip it red and turn parent black. * This way we gained a black node in our path, * or we fix it recursively one layer up, which * will rotate the red sibling as parent. */ c_rbnode_set_parent_and_color(s, p, C_RBNODE_RED); if (c_rbnode_is_black(p)) return p; c_rbnode_set_parent_and_color(p, c_rbnode_parent(p), C_RBNODE_BLACK); return NULL; } /* Case 5: * Left child of our sibling is red, right one is black. * Rotate on parent so the right child of our sibling is * now red, and we can fall through to case 6. */ x = y->right; s->left = y->right; y->right = s; p->right = y; if (x) c_rbnode_set_parent_and_color(x, s, C_RBNODE_BLACK); x = s; s = y; } /* Case 6: * The right child of our sibling is red. Rotate left and flip * colors, which gains us an additional black node in our path, * that was previously on our sibling. */ g = c_rbnode_parent(p); y = s->left; p->right = y; s->left = p; c_rbnode_set_parent_and_color(x, s, C_RBNODE_BLACK); if (y) c_rbnode_set_parent_and_color(y, p, c_rbnode_color(y)); c_rbnode_set_parent_and_color(s, g, c_rbnode_color(p)); c_rbnode_set_parent_and_color(p, s, C_RBNODE_BLACK); c_rbtree_swap_child(t, g, p, s); } else /* if (!n || n == p->right) */ { /* same as above, but mirrored */ s = p->left; if (c_rbnode_is_red(s)) { g = c_rbnode_parent(p); x = s->right; p->left = x; s->right = p; c_rbnode_set_parent_and_color(x, p, C_RBNODE_BLACK); c_rbnode_set_parent_and_color(s, g, C_RBNODE_BLACK); c_rbnode_set_parent_and_color(p, s, C_RBNODE_RED); c_rbtree_swap_child(t, g, p, s); s = x; } x = s->left; if (!x || c_rbnode_is_black(x)) { y = s->right; if (!y || c_rbnode_is_black(y)) { c_rbnode_set_parent_and_color(s, p, C_RBNODE_RED); if (c_rbnode_is_black(p)) return p; c_rbnode_set_parent_and_color(p, c_rbnode_parent(p), C_RBNODE_BLACK); return NULL; } x = y->left; s->right = y->left; y->left = s; p->left = y; if (x) c_rbnode_set_parent_and_color(x, s, C_RBNODE_BLACK); x = s; s = y; } g = c_rbnode_parent(p); y = s->right; p->left = y; s->right = p; c_rbnode_set_parent_and_color(x, s, C_RBNODE_BLACK); if (y) c_rbnode_set_parent_and_color(y, p, c_rbnode_color(y)); c_rbnode_set_parent_and_color(s, g, c_rbnode_color(p)); c_rbnode_set_parent_and_color(p, s, C_RBNODE_BLACK); c_rbtree_swap_child(t, g, p, s); } return NULL; } static inline void c_rbtree_rebalance(CRBTree *t, CRBNode *p) { CRBNode *n = NULL; assert(t); assert(p); do { n = c_rbtree_rebalance_one(t, p, n); p = n ? c_rbnode_parent(n) : NULL; } while (p); } /** * c_rbtree_remove() - remove node from tree * @t: tree to operate one * @n: node to remove * * This removes the given node from its tree. Once unlinked, the tree is * rebalanced. * The caller *must* ensure that the given tree is actually the tree it is * linked on. Otherwise, behavior is undefined. * * This does *NOT* reset @n to being unlinked (for performance reason, this * function *never* modifies @n at all). If you need this, use * c_rbtree_remove_init(). */ void c_rbtree_remove(CRBTree *t, CRBNode *n) { CRBNode *p, *s, *gc, *x, *next = NULL; unsigned long c; assert(t); assert(n); assert(c_rbnode_is_linked(n)); /* * There are three distinct cases during node removal of a tree: * * The node has no children, in which case it can simply be removed. * * The node has exactly one child, in which case the child displaces * its parent. * * The node has two children, in which case there is guaranteed to * be a successor to the node (successor being the node ordered * directly after it). This successor cannot have two children by * itself (two interior nodes can never be successive). Therefore, * we can simply swap the node with its successor (including color) * and have reduced this case to either of the first two. * * Whenever the node we removed was black, we have to rebalance the * tree. Note that this affects the actual node we _remove_, not @n (in * case we swap it). * * p: parent * s: successor * gc: grand-...-child * x: temporary * next: next node to rebalance on */ if (!n->left) { /* * Case 1: * The node has no left child. If it neither has a right child, * it is a leaf-node and we can simply unlink it. If it also * was black, we have to rebalance, as always if we remove a * black node. * But if the node has a right child, the child *must* be red * (otherwise, the right path has more black nodes as the * non-existing left path), and the node to be removed must * hence be black. We simply replace the node with its child, * turning the red child black, and thus no rebalancing is * required. */ p = c_rbnode_parent(n); c = c_rbnode_color(n); c_rbtree_swap_child(t, p, n, n->right); if (n->right) c_rbnode_set_parent_and_color(n->right, p, c); else next = (c == C_RBNODE_BLACK) ? p : NULL; } else if (!n->right) { /* * Case 1.1: * The node has exactly one child, and it is on the left. Treat * it as mirrored case of Case 1 (i.e., replace the node by its * child). */ p = c_rbnode_parent(n); c = c_rbnode_color(n); c_rbtree_swap_child(t, p, n, n->left); c_rbnode_set_parent_and_color(n->left, p, c); } else { /* * Case 2: * We are dealing with a full interior node with a child not on * both sides. Find its successor and swap it. Then remove the * node similar to Case 1. For performance reasons we don't * perform the full swap, but skip links that are about to be * removed, anyway. */ s = n->right; if (!s->left) { /* right child is next, no need to touch grandchild */ p = s; gc = s->right; } else { /* find successor and swap partially */ s = c_rbnode_leftmost(s); p = c_rbnode_parent(s); gc = s->right; p->left = s->right; s->right = n->right; c_rbnode_set_parent(n->right, s); } /* node is partially swapped, now remove as in Case 1 */ s->left = n->left; c_rbnode_set_parent(n->left, s); x = c_rbnode_parent(n); c = c_rbnode_color(n); c_rbtree_swap_child(t, x, n, s); if (gc) c_rbnode_set_parent_and_color(gc, p, C_RBNODE_BLACK); else next = c_rbnode_is_black(s) ? p : NULL; c_rbnode_set_parent_and_color(s, x, c); } if (next) c_rbtree_rebalance(t, next); } systemd-229/src/basic/c-rbtree.h000066400000000000000000000247701265713322000166170ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. See COPYING for details. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* * Standalone Red-Black-Tree Implementation in Standard ISO-C11 * * This header provides an RB-Tree API, that is fully implemented in ISO-C11 * and has no external dependencies. Furthermore, tree traversal, memory * allocations, and key comparisons a fully in control of the API user. The * implementation only provides the RB-Tree specific rebalancing and coloring. * * A tree is represented by the "CRBTree" structure. It contains a *singly* * field, which is a pointer to the root node. If NULL, the tree is empty. If * non-NULL, there is at least a single element in the tree. * * Each node of the tree is represented by the "CRBNode" structure. It has * three fields. The @left and @right members can be accessed by the API user * directly to traverse the tree. The third member is an implementation detail * and encodes the parent pointer and color of the node. * API users are required to embed the CRBNode object into their own objects * and then use offsetof() (i.e., container_of() and friends) to turn CRBNode * pointers into pointers to their own structure. */ #ifdef __cplusplus extern "C" { #endif typedef struct CRBNode CRBNode; typedef struct CRBTree CRBTree; /** * struct CRBNode - Node of a Red-Black Tree * @__parent_and_color: internal state * @left: left child, or NULL * @right: right child, or NULL * * Each node in an RB-Tree must embed an CRBNode object. This object contains * pointers to its left and right child, which can be freely accessed by the * API user at any time. They are NULL, if the node does not have a left/right * child. * * The @__parent_and_color field must never be accessed directly. It encodes * the pointer to the parent node, and the color of the node. Use the accessor * functions instead. * * There is no reason to initialize a CRBNode object before linking it. * However, if you need a boolean state that tells you whether the node is * linked or not, you should initialize the node via c_rbnode_init() or * C_RBNODE_INIT. */ struct CRBNode { CRBNode *__parent_and_color; CRBNode *left; CRBNode *right; }; #define C_RBNODE_INIT(_var) { .__parent_and_color = &(_var) } CRBNode *c_rbnode_leftmost(CRBNode *n); CRBNode *c_rbnode_rightmost(CRBNode *n); CRBNode *c_rbnode_next(CRBNode *n); CRBNode *c_rbnode_prev(CRBNode *n); /** * struct CRBTree - Red-Black Tree * @root: pointer to the root node, or NULL * * Each Red-Black Tree is rooted in an CRBTree object. This object contains a * pointer to the root node of the tree. The API user is free to access the * @root member at any time, and use it to traverse the tree. * * To initialize an RB-Tree, set it to NULL / all zero. */ struct CRBTree { CRBNode *root; }; CRBNode *c_rbtree_first(CRBTree *t); CRBNode *c_rbtree_last(CRBTree *t); void c_rbtree_add(CRBTree *t, CRBNode *p, CRBNode **l, CRBNode *n); void c_rbtree_remove(CRBTree *t, CRBNode *n); /** * c_rbnode_init() - mark a node as unlinked * @n: node to operate on * * This marks the node @n as unlinked. The node will be set to a valid state * that can never happen if the node is linked in a tree. Furthermore, this * state is fully known to the implementation, and as such handled gracefully * in all cases. * * You are *NOT* required to call this on your node. c_rbtree_add() can handle * uninitialized nodes just fine. However, calling this allows to use * c_rbnode_is_linked() to check for the state of a node. Furthermore, * iterators and accessors can be called on initialized (yet unlinked) nodes. * * Use the C_RBNODE_INIT macro if you want to initialize static variables. */ static inline void c_rbnode_init(CRBNode *n) { *n = (CRBNode)C_RBNODE_INIT(*n); } /** * c_rbnode_is_linked() - check whether a node is linked * @n: node to check, or NULL * * This checks whether the passed node is linked. If you pass NULL, or if the * node is not linked into a tree, this will return false. Otherwise, this * returns true. * * Note that you must have either linked the node or initialized it, before * calling this function. Never call this function on uninitialized nodes. * Furthermore, removing a node via c_rbtree_remove() does *NOT* mark the node * as unlinked. You have to call c_rbnode_init() yourself after removal, or use * the c_rbtree_remove_init() helper. * * Return: true if the node is linked, false if not. */ static inline _Bool c_rbnode_is_linked(CRBNode *n) { return n && n->__parent_and_color != n; } /** * c_rbnode_parent() - return parent pointer * @n node to access * * This returns a pointer to the parent of the given node @n. If @n does not * have a parent, NULL is returned. If @n is not linked, @n itself is returned. * * You should not call this on unlinked or uninitialized nodes! If you do, you * better know how its semantics. * * Return: Pointer to parent. */ static inline CRBNode *c_rbnode_parent(CRBNode *n) { return (CRBNode*)((unsigned long)n->__parent_and_color & ~1UL); } /** * c_rbtree_remove_init() - safely remove node from tree and reinitialize it * @t: tree to operate on * @n: node to remove, or NULL * * This is almost the same as c_rbtree_remove(), but extends it slightly, to be * more convenient to use in many cases: * - if @n is unlinked or NULL, this is a no-op * - @n is reinitialized after being removed */ static inline void c_rbtree_remove_init(CRBTree *t, CRBNode *n) { if (c_rbnode_is_linked(n)) { c_rbtree_remove(t, n); c_rbnode_init(n); } } /** * CRBCompareFunc - compare a node to a key * @t: tree where the node is linked to * @k: key to compare * @n: node to compare * * If you use the tree-traversal helpers (which are optional), you need to * provide this callback so they can compare nodes in a tree to the key you * look for. * * The tree @t is provided as optional context to this callback. The key you * look for is provided as @k, the current node that should be compared to is * provided as @n. This function should work like strcmp(), that is, return -1 * if @key orders before @n, 0 if both compare equal, and 1 if it orders after * @n. */ typedef int (*CRBCompareFunc) (CRBTree *t, void *k, CRBNode *n); /** * c_rbtree_find_node() - find node * @t: tree to search through * @f: comparison function * @k: key to search for * * This searches through @t for a node that compares equal to @k. The function * @f must be provided by the caller, which is used to compare nodes to @k. See * the documentation of CRBCompareFunc for details. * * If there are multiple entries that compare equal to @k, this will return a * pseudo-randomly picked node. If you need stable lookup functions for trees * where duplicate entries are allowed, you better code your own lookup. * * Return: Pointer to matching node, or NULL. */ static inline CRBNode *c_rbtree_find_node(CRBTree *t, CRBCompareFunc f, const void *k) { CRBNode *i; assert(t); assert(f); i = t->root; while (i) { int v = f(t, (void *)k, i); if (v < 0) i = i->left; else if (v > 0) i = i->right; else return i; } return NULL; } /** * c_rbtree_find_entry() - find entry * @_t: tree to search through * @_f: comparison function * @_k: key to search for * @_t: type of the structure that embeds the nodes * @_o: name of the node-member in type @_t * * This is very similar to c_rbtree_find_node(), but instead of returning a * pointer to the CRBNode, it returns a pointer to the surrounding object. This * object must embed the CRBNode object. The type of the surrounding object * must be given as @_t, and the name of the embedded CRBNode member as @_o. * * See c_rbtree_find_node() for more details. * * Return: Pointer to found entry, NULL if not found. */ #define c_rbtree_find_entry(_m, _f, _k, _t, _o) \ ((_t *)(((char *)c_rbtree_find_node((_m), (_f), (_k)) ?: \ (char *)NULL + offsetof(_t, _o)) - offsetof(_t, _o))) /** * c_rbtree_find_slot() - find slot to insert new node * @t: tree to search through * @f: comparison function * @k: key to search for * @p: output storage for parent pointer * * This searches through @t just like c_rbtree_find_node() does. However, * instead of returning a pointer to a node that compares equal to @k, this * searches for a slot to insert a node with key @k. A pointer to the slot is * returned, and a pointer to the parent of the slot is stored in @p. Both * can be passed directly to c_rbtree_add(), together with your node to insert. * * If there already is a node in the tree, that compares equal to @k, this will * return NULL and store the conflicting node in @p. In all other cases, * this will return a pointer (non-NULL) to the empty slot to insert the node * at. @p will point to the parent node of that slot. * * If you want trees that allow duplicate nodes, you better code your own * insertion function. * * Return: Pointer to slot to insert node, or NULL on conflicts. */ static inline CRBNode **c_rbtree_find_slot(CRBTree *t, CRBCompareFunc f, const void *k, CRBNode **p) { CRBNode **i; assert(t); assert(f); assert(p); i = &t->root; *p = NULL; while (*i) { int v = f(t, (void *)k, *i); *p = *i; if (v < 0) i = &(*i)->left; else if (v > 0) i = &(*i)->right; else return NULL; } return i; } #ifdef __cplusplus } #endif systemd-229/src/basic/calendarspec.c000066400000000000000000000705541265713322000175340ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "alloc-util.h" #include "calendarspec.h" #include "fileio.h" #include "macro.h" #include "parse-util.h" #include "string-util.h" #define BITS_WEEKDAYS 127 static void free_chain(CalendarComponent *c) { CalendarComponent *n; while (c) { n = c->next; free(c); c = n; } } void calendar_spec_free(CalendarSpec *c) { if (!c) return; free_chain(c->year); free_chain(c->month); free_chain(c->day); free_chain(c->hour); free_chain(c->minute); free_chain(c->microsecond); free(c); } static int component_compare(const void *_a, const void *_b) { CalendarComponent * const *a = _a, * const *b = _b; if ((*a)->value < (*b)->value) return -1; if ((*a)->value > (*b)->value) return 1; if ((*a)->repeat < (*b)->repeat) return -1; if ((*a)->repeat > (*b)->repeat) return 1; return 0; } static void sort_chain(CalendarComponent **c) { unsigned n = 0, k; CalendarComponent **b, *i, **j, *next; assert(c); for (i = *c; i; i = i->next) n++; if (n <= 1) return; j = b = alloca(sizeof(CalendarComponent*) * n); for (i = *c; i; i = i->next) *(j++) = i; qsort(b, n, sizeof(CalendarComponent*), component_compare); b[n-1]->next = NULL; next = b[n-1]; /* Drop non-unique entries */ for (k = n-1; k > 0; k--) { if (b[k-1]->value == next->value && b[k-1]->repeat == next->repeat) { free(b[k-1]); continue; } b[k-1]->next = next; next = b[k-1]; } *c = next; } static void fix_year(CalendarComponent *c) { /* Turns 12 → 2012, 89 → 1989 */ while(c) { CalendarComponent *n = c->next; if (c->value >= 0 && c->value < 70) c->value += 2000; if (c->value >= 70 && c->value < 100) c->value += 1900; c = n; } } int calendar_spec_normalize(CalendarSpec *c) { assert(c); if (c->weekdays_bits <= 0 || c->weekdays_bits >= BITS_WEEKDAYS) c->weekdays_bits = -1; fix_year(c->year); sort_chain(&c->year); sort_chain(&c->month); sort_chain(&c->day); sort_chain(&c->hour); sort_chain(&c->minute); sort_chain(&c->microsecond); return 0; } _pure_ static bool chain_valid(CalendarComponent *c, int from, int to) { if (!c) return true; if (c->value < from || c->value > to) return false; if (c->value + c->repeat > to) return false; if (c->next) return chain_valid(c->next, from, to); return true; } _pure_ bool calendar_spec_valid(CalendarSpec *c) { assert(c); if (c->weekdays_bits > BITS_WEEKDAYS) return false; if (!chain_valid(c->year, 1970, 2199)) return false; if (!chain_valid(c->month, 1, 12)) return false; if (!chain_valid(c->day, 1, 31)) return false; if (!chain_valid(c->hour, 0, 23)) return false; if (!chain_valid(c->minute, 0, 59)) return false; if (!chain_valid(c->microsecond, 0, 60*USEC_PER_SEC-1)) return false; return true; } static void format_weekdays(FILE *f, const CalendarSpec *c) { static const char *const days[] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; int l, x; bool need_colon = false; assert(f); assert(c); assert(c->weekdays_bits > 0 && c->weekdays_bits <= BITS_WEEKDAYS); for (x = 0, l = -1; x < (int) ELEMENTSOF(days); x++) { if (c->weekdays_bits & (1 << x)) { if (l < 0) { if (need_colon) fputc(',', f); else need_colon = true; fputs(days[x], f); l = x; } } else if (l >= 0) { if (x > l + 1) { fputc(x > l + 2 ? '-' : ',', f); fputs(days[x-1], f); } l = -1; } } if (l >= 0 && x > l + 1) { fputc(x > l + 2 ? '-' : ',', f); fputs(days[x-1], f); } } static void format_chain(FILE *f, int space, const CalendarComponent *c, bool usec) { assert(f); if (!c) { fputc('*', f); return; } assert(c->value >= 0); if (!usec) fprintf(f, "%0*i", space, c->value); else if (c->value % USEC_PER_SEC == 0) fprintf(f, "%0*i", space, (int) (c->value / USEC_PER_SEC)); else fprintf(f, "%0*i.%06i", space, (int) (c->value / USEC_PER_SEC), (int) (c->value % USEC_PER_SEC)); if (c->repeat > 0) { if (!usec) fprintf(f, "/%i", c->repeat); else if (c->repeat % USEC_PER_SEC == 0) fprintf(f, "/%i", (int) (c->repeat / USEC_PER_SEC)); else fprintf(f, "/%i.%06i", (int) (c->repeat / USEC_PER_SEC), (int) (c->repeat % USEC_PER_SEC)); } if (c->next) { fputc(',', f); format_chain(f, space, c->next, usec); } } int calendar_spec_to_string(const CalendarSpec *c, char **p) { char *buf = NULL; size_t sz = 0; FILE *f; int r; assert(c); assert(p); f = open_memstream(&buf, &sz); if (!f) return -ENOMEM; if (c->weekdays_bits > 0 && c->weekdays_bits <= BITS_WEEKDAYS) { format_weekdays(f, c); fputc(' ', f); } format_chain(f, 4, c->year, false); fputc('-', f); format_chain(f, 2, c->month, false); fputc('-', f); format_chain(f, 2, c->day, false); fputc(' ', f); format_chain(f, 2, c->hour, false); fputc(':', f); format_chain(f, 2, c->minute, false); fputc(':', f); format_chain(f, 2, c->microsecond, true); if (c->utc) fputs(" UTC", f); r = fflush_and_check(f); if (r < 0) { free(buf); fclose(f); return r; } fclose(f); *p = buf; return 0; } static int parse_weekdays(const char **p, CalendarSpec *c) { static const struct { const char *name; const int nr; } day_nr[] = { { "Monday", 0 }, { "Mon", 0 }, { "Tuesday", 1 }, { "Tue", 1 }, { "Wednesday", 2 }, { "Wed", 2 }, { "Thursday", 3 }, { "Thu", 3 }, { "Friday", 4 }, { "Fri", 4 }, { "Saturday", 5 }, { "Sat", 5 }, { "Sunday", 6 }, { "Sun", 6 } }; int l = -1; bool first = true; assert(p); assert(*p); assert(c); for (;;) { unsigned i; if (!first && **p == ' ') return 0; for (i = 0; i < ELEMENTSOF(day_nr); i++) { size_t skip; if (!startswith_no_case(*p, day_nr[i].name)) continue; skip = strlen(day_nr[i].name); if ((*p)[skip] != '-' && (*p)[skip] != ',' && (*p)[skip] != ' ' && (*p)[skip] != 0) return -EINVAL; c->weekdays_bits |= 1 << day_nr[i].nr; if (l >= 0) { int j; if (l > day_nr[i].nr) return -EINVAL; for (j = l + 1; j < day_nr[i].nr; j++) c->weekdays_bits |= 1 << j; } *p += skip; break; } /* Couldn't find this prefix, so let's assume the weekday was not specified and let's continue with the date */ if (i >= ELEMENTSOF(day_nr)) return first ? 0 : -EINVAL; /* We reached the end of the string */ if (**p == 0) return 0; /* We reached the end of the weekday spec part */ if (**p == ' ') { *p += strspn(*p, " "); return 0; } if (**p == '-') { if (l >= 0) return -EINVAL; l = day_nr[i].nr; } else l = -1; *p += 1; first = false; } } static int parse_component_decimal(const char **p, bool usec, unsigned long *res) { unsigned long value; const char *e = NULL; char *ee = NULL; int r; errno = 0; value = strtoul(*p, &ee, 10); if (errno > 0) return -errno; if (ee == *p) return -EINVAL; if ((unsigned long) (int) value != value) return -ERANGE; e = ee; if (usec) { if (value * USEC_PER_SEC / USEC_PER_SEC != value) return -ERANGE; value *= USEC_PER_SEC; if (*e == '.') { unsigned add; e++; r = parse_fractional_part_u(&e, 6, &add); if (r < 0) return r; if (add + value < value) return -ERANGE; value += add; } } *p = e; *res = value; return 0; } static int prepend_component(const char **p, bool usec, CalendarComponent **c) { unsigned long value, repeat = 0; CalendarComponent *cc; int r; const char *e; assert(p); assert(c); e = *p; r = parse_component_decimal(&e, usec, &value); if (r < 0) return r; if (*e == '/') { e++; r = parse_component_decimal(&e, usec, &repeat); if (r < 0) return r; if (repeat == 0) return -ERANGE; } if (*e != 0 && *e != ' ' && *e != ',' && *e != '-' && *e != ':') return -EINVAL; cc = new0(CalendarComponent, 1); if (!cc) return -ENOMEM; cc->value = value; cc->repeat = repeat; cc->next = *c; *p = e; *c = cc; if (*e ==',') { *p += 1; return prepend_component(p, usec, c); } return 0; } static int const_chain(int value, CalendarComponent **c) { CalendarComponent *cc = NULL; assert(c); cc = new0(CalendarComponent, 1); if (!cc) return -ENOMEM; cc->value = value; cc->repeat = 0; cc->next = *c; *c = cc; return 0; } static int parse_chain(const char **p, bool usec, CalendarComponent **c) { const char *t; CalendarComponent *cc = NULL; int r; assert(p); assert(c); t = *p; if (t[0] == '*') { if (usec) { r = const_chain(0, c); if (r < 0) return r; (*c)->repeat = USEC_PER_SEC; } else *c = NULL; *p = t + 1; return 0; } r = prepend_component(&t, usec, &cc); if (r < 0) { free_chain(cc); return r; } *p = t; *c = cc; return 0; } static int parse_date(const char **p, CalendarSpec *c) { const char *t; int r; CalendarComponent *first, *second, *third; assert(p); assert(*p); assert(c); t = *p; if (*t == 0) return 0; r = parse_chain(&t, false, &first); if (r < 0) return r; /* Already the end? A ':' as separator? In that case this was a time, not a date */ if (*t == 0 || *t == ':') { free_chain(first); return 0; } if (*t != '-') { free_chain(first); return -EINVAL; } t++; r = parse_chain(&t, false, &second); if (r < 0) { free_chain(first); return r; } /* Got two parts, hence it's month and day */ if (*t == ' ' || *t == 0) { *p = t + strspn(t, " "); c->month = first; c->day = second; return 0; } if (*t != '-') { free_chain(first); free_chain(second); return -EINVAL; } t++; r = parse_chain(&t, false, &third); if (r < 0) { free_chain(first); free_chain(second); return r; } /* Got tree parts, hence it is year, month and day */ if (*t == ' ' || *t == 0) { *p = t + strspn(t, " "); c->year = first; c->month = second; c->day = third; return 0; } free_chain(first); free_chain(second); free_chain(third); return -EINVAL; } static int parse_calendar_time(const char **p, CalendarSpec *c) { CalendarComponent *h = NULL, *m = NULL, *s = NULL; const char *t; int r; assert(p); assert(*p); assert(c); t = *p; if (*t == 0) { /* If no time is specified at all, but a date of some * kind, then this means 00:00:00 */ if (c->day || c->weekdays_bits > 0) goto null_hour; goto finish; } r = parse_chain(&t, false, &h); if (r < 0) goto fail; if (*t != ':') { r = -EINVAL; goto fail; } t++; r = parse_chain(&t, false, &m); if (r < 0) goto fail; /* Already at the end? Then it's hours and minutes, and seconds are 0 */ if (*t == 0) { if (m != NULL) goto null_second; goto finish; } if (*t != ':') { r = -EINVAL; goto fail; } t++; r = parse_chain(&t, true, &s); if (r < 0) goto fail; /* At the end? Then it's hours, minutes and seconds */ if (*t == 0) goto finish; r = -EINVAL; goto fail; null_hour: r = const_chain(0, &h); if (r < 0) goto fail; r = const_chain(0, &m); if (r < 0) goto fail; null_second: r = const_chain(0, &s); if (r < 0) goto fail; finish: *p = t; c->hour = h; c->minute = m; c->microsecond = s; return 0; fail: free_chain(h); free_chain(m); free_chain(s); return r; } int calendar_spec_from_string(const char *p, CalendarSpec **spec) { CalendarSpec *c; int r; const char *utc; assert(p); assert(spec); if (isempty(p)) return -EINVAL; c = new0(CalendarSpec, 1); if (!c) return -ENOMEM; utc = endswith_no_case(p, " UTC"); if (utc) { c->utc = true; p = strndupa(p, utc - p); } if (strcaseeq(p, "minutely")) { r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "hourly")) { r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "daily")) { r = const_chain(0, &c->hour); if (r < 0) goto fail; r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "monthly")) { r = const_chain(1, &c->day); if (r < 0) goto fail; r = const_chain(0, &c->hour); if (r < 0) goto fail; r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "annually") || strcaseeq(p, "yearly") || strcaseeq(p, "anually") /* backwards compatibility */ ) { r = const_chain(1, &c->month); if (r < 0) goto fail; r = const_chain(1, &c->day); if (r < 0) goto fail; r = const_chain(0, &c->hour); if (r < 0) goto fail; r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "weekly")) { c->weekdays_bits = 1; r = const_chain(0, &c->hour); if (r < 0) goto fail; r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "quarterly")) { r = const_chain(1, &c->month); if (r < 0) goto fail; r = const_chain(4, &c->month); if (r < 0) goto fail; r = const_chain(7, &c->month); if (r < 0) goto fail; r = const_chain(10, &c->month); if (r < 0) goto fail; r = const_chain(1, &c->day); if (r < 0) goto fail; r = const_chain(0, &c->hour); if (r < 0) goto fail; r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else if (strcaseeq(p, "biannually") || strcaseeq(p, "bi-annually") || strcaseeq(p, "semiannually") || strcaseeq(p, "semi-annually")) { r = const_chain(1, &c->month); if (r < 0) goto fail; r = const_chain(7, &c->month); if (r < 0) goto fail; r = const_chain(1, &c->day); if (r < 0) goto fail; r = const_chain(0, &c->hour); if (r < 0) goto fail; r = const_chain(0, &c->minute); if (r < 0) goto fail; r = const_chain(0, &c->microsecond); if (r < 0) goto fail; } else { r = parse_weekdays(&p, c); if (r < 0) goto fail; r = parse_date(&p, c); if (r < 0) goto fail; r = parse_calendar_time(&p, c); if (r < 0) goto fail; if (*p != 0) { r = -EINVAL; goto fail; } } r = calendar_spec_normalize(c); if (r < 0) goto fail; if (!calendar_spec_valid(c)) { r = -EINVAL; goto fail; } *spec = c; return 0; fail: calendar_spec_free(c); return r; } static int find_matching_component(const CalendarComponent *c, int *val) { const CalendarComponent *n; int d = -1; bool d_set = false; int r; assert(val); if (!c) return 0; while (c) { n = c->next; if (c->value >= *val) { if (!d_set || c->value < d) { d = c->value; d_set = true; } } else if (c->repeat > 0) { int k; k = c->value + c->repeat * ((*val - c->value + c->repeat -1) / c->repeat); if (!d_set || k < d) { d = k; d_set = true; } } c = n; } if (!d_set) return -ENOENT; r = *val != d; *val = d; return r; } static bool tm_out_of_bounds(const struct tm *tm, bool utc) { struct tm t; assert(tm); t = *tm; if (mktime_or_timegm(&t, utc) == (time_t) -1) return true; /* Did any normalization take place? If so, it was out of bounds before */ return t.tm_year != tm->tm_year || t.tm_mon != tm->tm_mon || t.tm_mday != tm->tm_mday || t.tm_hour != tm->tm_hour || t.tm_min != tm->tm_min || t.tm_sec != tm->tm_sec; } static bool matches_weekday(int weekdays_bits, const struct tm *tm, bool utc) { struct tm t; int k; if (weekdays_bits < 0 || weekdays_bits >= BITS_WEEKDAYS) return true; t = *tm; if (mktime_or_timegm(&t, utc) == (time_t) -1) return false; k = t.tm_wday == 0 ? 6 : t.tm_wday - 1; return (weekdays_bits & (1 << k)); } static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { struct tm c; int tm_usec; int r; assert(spec); assert(tm); c = *tm; tm_usec = *usec; for (;;) { /* Normalize the current date */ mktime_or_timegm(&c, spec->utc); c.tm_isdst = -1; c.tm_year += 1900; r = find_matching_component(spec->year, &c.tm_year); c.tm_year -= 1900; if (r > 0) { c.tm_mon = 0; c.tm_mday = 1; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; } if (r < 0 || tm_out_of_bounds(&c, spec->utc)) return r; c.tm_mon += 1; r = find_matching_component(spec->month, &c.tm_mon); c.tm_mon -= 1; if (r > 0) { c.tm_mday = 1; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; } if (r < 0 || tm_out_of_bounds(&c, spec->utc)) { c.tm_year ++; c.tm_mon = 0; c.tm_mday = 1; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; continue; } r = find_matching_component(spec->day, &c.tm_mday); if (r > 0) c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; if (r < 0 || tm_out_of_bounds(&c, spec->utc)) { c.tm_mon ++; c.tm_mday = 1; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; continue; } if (!matches_weekday(spec->weekdays_bits, &c, spec->utc)) { c.tm_mday++; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; continue; } r = find_matching_component(spec->hour, &c.tm_hour); if (r > 0) c.tm_min = c.tm_sec = 0; if (r < 0 || tm_out_of_bounds(&c, spec->utc)) { c.tm_mday ++; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; continue; } r = find_matching_component(spec->minute, &c.tm_min); if (r > 0) c.tm_sec = 0; if (r < 0 || tm_out_of_bounds(&c, spec->utc)) { c.tm_hour ++; c.tm_min = c.tm_sec = tm_usec = 0; continue; } c.tm_sec = c.tm_sec * USEC_PER_SEC + tm_usec; r = find_matching_component(spec->microsecond, &c.tm_sec); tm_usec = c.tm_sec % USEC_PER_SEC; c.tm_sec /= USEC_PER_SEC; if (r < 0 || tm_out_of_bounds(&c, spec->utc)) { c.tm_min ++; c.tm_sec = tm_usec = 0; continue; } *tm = c; *usec = tm_usec; return 0; } } int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next) { struct tm tm; time_t t; int r; usec_t tm_usec; assert(spec); assert(next); usec++; t = (time_t) (usec / USEC_PER_SEC); assert_se(localtime_or_gmtime_r(&t, &tm, spec->utc)); tm_usec = usec % USEC_PER_SEC; r = find_next(spec, &tm, &tm_usec); if (r < 0) return r; t = mktime_or_timegm(&tm, spec->utc); if (t == (time_t) -1) return -EINVAL; *next = (usec_t) t * USEC_PER_SEC + tm_usec; return 0; } systemd-229/src/basic/calendarspec.h000066400000000000000000000032231265713322000175260ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* A structure for specifying (possibly repetitive) points in calendar * time, a la cron */ #include #include "time-util.h" #include "util.h" typedef struct CalendarComponent { int value; int repeat; struct CalendarComponent *next; } CalendarComponent; typedef struct CalendarSpec { int weekdays_bits; bool utc; CalendarComponent *year; CalendarComponent *month; CalendarComponent *day; CalendarComponent *hour; CalendarComponent *minute; CalendarComponent *microsecond; } CalendarSpec; void calendar_spec_free(CalendarSpec *c); int calendar_spec_normalize(CalendarSpec *spec); bool calendar_spec_valid(CalendarSpec *spec); int calendar_spec_to_string(const CalendarSpec *spec, char **p); int calendar_spec_from_string(const char *p, CalendarSpec **spec); int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next); systemd-229/src/basic/cap-list.c000066400000000000000000000033511265713322000166130ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "cap-list.h" #include "macro.h" #include "missing.h" #include "parse-util.h" #include "util.h" static const struct capability_name* lookup_capability(register const char *str, register unsigned int len); #include "cap-from-name.h" #include "cap-to-name.h" const char *capability_to_name(int id) { if (id < 0) return NULL; if (id >= (int) ELEMENTSOF(capability_names)) return NULL; return capability_names[id]; } int capability_from_name(const char *name) { const struct capability_name *sc; int r, i; assert(name); /* Try to parse numeric capability */ r = safe_atoi(name, &i); if (r >= 0 && i >= 0) return i; /* Try to parse string capability */ sc = lookup_capability(name, strlen(name)); if (!sc) return -EINVAL; return sc->id; } int capability_list_length(void) { return (int) ELEMENTSOF(capability_names); } systemd-229/src/basic/cap-list.h000066400000000000000000000015231265713322000166170ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ const char *capability_to_name(int id); int capability_from_name(const char *name); int capability_list_length(void); systemd-229/src/basic/capability-util.c000066400000000000000000000260531265713322000201770ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "alloc-util.h" #include "capability-util.h" #include "fileio.h" #include "log.h" #include "macro.h" #include "parse-util.h" #include "util.h" int have_effective_cap(int value) { _cleanup_cap_free_ cap_t cap; cap_flag_value_t fv; cap = cap_get_proc(); if (!cap) return -errno; if (cap_get_flag(cap, value, CAP_EFFECTIVE, &fv) < 0) return -errno; else return fv == CAP_SET; } unsigned long cap_last_cap(void) { static thread_local unsigned long saved; static thread_local bool valid = false; _cleanup_free_ char *content = NULL; unsigned long p = 0; int r; if (valid) return saved; /* available since linux-3.2 */ r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content); if (r >= 0) { r = safe_atolu(content, &p); if (r >= 0) { saved = p; valid = true; return p; } } /* fall back to syscall-probing for pre linux-3.2 */ p = (unsigned long) CAP_LAST_CAP; if (prctl(PR_CAPBSET_READ, p) < 0) { /* Hmm, look downwards, until we find one that * works */ for (p--; p > 0; p --) if (prctl(PR_CAPBSET_READ, p) >= 0) break; } else { /* Hmm, look upwards, until we find one that doesn't * work */ for (;; p++) if (prctl(PR_CAPBSET_READ, p+1) < 0) break; } saved = p; valid = true; return p; } int capability_update_inherited_set(cap_t caps, uint64_t set) { unsigned long i; /* Add capabilities in the set to the inherited caps. Do not apply * them yet. */ for (i = 0; i < cap_last_cap(); i++) { if (set & (UINT64_C(1) << i)) { cap_value_t v; v = (cap_value_t) i; /* Make the capability inheritable. */ if (cap_set_flag(caps, CAP_INHERITABLE, 1, &v, CAP_SET) < 0) return -errno; } } return 0; } int capability_ambient_set_apply(uint64_t set, bool also_inherit) { unsigned long i; _cleanup_cap_free_ cap_t caps = NULL; /* Add the capabilities to the ambient set. */ if (also_inherit) { int r; caps = cap_get_proc(); if (!caps) return -errno; r = capability_update_inherited_set(caps, set); if (r < 0) return -errno; if (cap_set_proc(caps) < 0) return -errno; } for (i = 0; i < cap_last_cap(); i++) { if (set & (UINT64_C(1) << i)) { /* Add the capability to the ambient set. */ if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0) < 0) return -errno; } } return 0; } int capability_bounding_set_drop(uint64_t keep, bool right_now) { _cleanup_cap_free_ cap_t after_cap = NULL; cap_flag_value_t fv; unsigned long i; int r; /* If we are run as PID 1 we will lack CAP_SETPCAP by default * in the effective set (yes, the kernel drops that when * executing init!), so get it back temporarily so that we can * call PR_CAPBSET_DROP. */ after_cap = cap_get_proc(); if (!after_cap) return -errno; if (cap_get_flag(after_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) return -errno; if (fv != CAP_SET) { _cleanup_cap_free_ cap_t temp_cap = NULL; static const cap_value_t v = CAP_SETPCAP; temp_cap = cap_dup(after_cap); if (!temp_cap) { r = -errno; goto finish; } if (cap_set_flag(temp_cap, CAP_EFFECTIVE, 1, &v, CAP_SET) < 0) { r = -errno; goto finish; } if (cap_set_proc(temp_cap) < 0) { r = -errno; goto finish; } } for (i = 0; i <= cap_last_cap(); i++) { if (!(keep & (UINT64_C(1) << i))) { cap_value_t v; /* Drop it from the bounding set */ if (prctl(PR_CAPBSET_DROP, i) < 0) { r = -errno; goto finish; } v = (cap_value_t) i; /* Also drop it from the inheritable set, so * that anything we exec() loses the * capability for good. */ if (cap_set_flag(after_cap, CAP_INHERITABLE, 1, &v, CAP_CLEAR) < 0) { r = -errno; goto finish; } /* If we shall apply this right now drop it * also from our own capability sets. */ if (right_now) { if (cap_set_flag(after_cap, CAP_PERMITTED, 1, &v, CAP_CLEAR) < 0 || cap_set_flag(after_cap, CAP_EFFECTIVE, 1, &v, CAP_CLEAR) < 0) { r = -errno; goto finish; } } } } r = 0; finish: if (cap_set_proc(after_cap) < 0) return -errno; return r; } static int drop_from_file(const char *fn, uint64_t keep) { int r, k; uint32_t hi, lo; uint64_t current, after; char *p; r = read_one_line_file(fn, &p); if (r < 0) return r; assert_cc(sizeof(hi) == sizeof(unsigned)); assert_cc(sizeof(lo) == sizeof(unsigned)); k = sscanf(p, "%u %u", &lo, &hi); free(p); if (k != 2) return -EIO; current = (uint64_t) lo | ((uint64_t) hi << 32ULL); after = current & keep; if (current == after) return 0; lo = (unsigned) (after & 0xFFFFFFFFULL); hi = (unsigned) ((after >> 32ULL) & 0xFFFFFFFFULL); if (asprintf(&p, "%u %u", lo, hi) < 0) return -ENOMEM; r = write_string_file(fn, p, WRITE_STRING_FILE_CREATE); free(p); return r; } int capability_bounding_set_drop_usermode(uint64_t keep) { int r; r = drop_from_file("/proc/sys/kernel/usermodehelper/inheritable", keep); if (r < 0) return r; r = drop_from_file("/proc/sys/kernel/usermodehelper/bset", keep); if (r < 0) return r; return r; } int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) { _cleanup_cap_free_ cap_t d = NULL; unsigned i, j = 0; int r; /* Unfortunately we cannot leave privilege dropping to PID 1 * here, since we want to run as user but want to keep some * capabilities. Since file capabilities have been introduced * this cannot be done across exec() anymore, unless our * binary has the capability configured in the file system, * which we want to avoid. */ if (setresgid(gid, gid, gid) < 0) return log_error_errno(errno, "Failed to change group ID: %m"); if (setgroups(0, NULL) < 0) return log_error_errno(errno, "Failed to drop auxiliary groups list: %m"); /* Ensure we keep the permitted caps across the setresuid() */ if (prctl(PR_SET_KEEPCAPS, 1) < 0) return log_error_errno(errno, "Failed to enable keep capabilities flag: %m"); r = setresuid(uid, uid, uid); if (r < 0) return log_error_errno(errno, "Failed to change user ID: %m"); if (prctl(PR_SET_KEEPCAPS, 0) < 0) return log_error_errno(errno, "Failed to disable keep capabilities flag: %m"); /* Drop all caps from the bounding set, except the ones we want */ r = capability_bounding_set_drop(keep_capabilities, true); if (r < 0) return log_error_errno(r, "Failed to drop capabilities: %m"); /* Now upgrade the permitted caps we still kept to effective caps */ d = cap_init(); if (!d) return log_oom(); if (keep_capabilities) { cap_value_t bits[u64log2(keep_capabilities) + 1]; for (i = 0; i < ELEMENTSOF(bits); i++) if (keep_capabilities & (1ULL << i)) bits[j++] = i; /* use enough bits */ assert(i == 64 || (keep_capabilities >> i) == 0); /* don't use too many bits */ assert(keep_capabilities & (1ULL << (i - 1))); if (cap_set_flag(d, CAP_EFFECTIVE, j, bits, CAP_SET) < 0 || cap_set_flag(d, CAP_PERMITTED, j, bits, CAP_SET) < 0) return log_error_errno(errno, "Failed to enable capabilities bits: %m"); if (cap_set_proc(d) < 0) return log_error_errno(errno, "Failed to increase capabilities: %m"); } return 0; } int drop_capability(cap_value_t cv) { _cleanup_cap_free_ cap_t tmp_cap = NULL; tmp_cap = cap_get_proc(); if (!tmp_cap) return -errno; if ((cap_set_flag(tmp_cap, CAP_INHERITABLE, 1, &cv, CAP_CLEAR) < 0) || (cap_set_flag(tmp_cap, CAP_PERMITTED, 1, &cv, CAP_CLEAR) < 0) || (cap_set_flag(tmp_cap, CAP_EFFECTIVE, 1, &cv, CAP_CLEAR) < 0)) return -errno; if (cap_set_proc(tmp_cap) < 0) return -errno; return 0; } systemd-229/src/basic/capability-util.h000066400000000000000000000033221265713322000201760ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "macro.h" #include "util.h" #define CAP_ALL (uint64_t) -1 unsigned long cap_last_cap(void); int have_effective_cap(int value); int capability_bounding_set_drop(uint64_t keep, bool right_now); int capability_bounding_set_drop_usermode(uint64_t keep); int capability_ambient_set_apply(uint64_t set, bool also_inherit); int capability_update_inherited_set(cap_t caps, uint64_t ambient_set); int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities); int drop_capability(cap_value_t cv); DEFINE_TRIVIAL_CLEANUP_FUNC(cap_t, cap_free); #define _cleanup_cap_free_ _cleanup_(cap_freep) static inline void cap_free_charpp(char **p) { if (*p) cap_free(*p); } #define _cleanup_cap_free_charp_ _cleanup_(cap_free_charpp) static inline bool cap_test_all(uint64_t caps) { uint64_t m; m = (UINT64_C(1) << (cap_last_cap() + 1)) - 1; return (caps & m) == m; } systemd-229/src/basic/cgroup-util.c000066400000000000000000001652021265713322000173550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "cgroup-util.h" #include "def.h" #include "dirent-util.h" #include "extract-word.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "log.h" #include "login-util.h" #include "macro.h" #include "missing.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" #include "process-util.h" #include "set.h" #include "special.h" #include "stat-util.h" #include "stdio-util.h" #include "string-table.h" #include "string-util.h" #include "unit-name.h" #include "user-util.h" int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) { _cleanup_free_ char *fs = NULL; FILE *f; int r; assert(_f); r = cg_get_path(controller, path, "cgroup.procs", &fs); if (r < 0) return r; f = fopen(fs, "re"); if (!f) return -errno; *_f = f; return 0; } int cg_read_pid(FILE *f, pid_t *_pid) { unsigned long ul; /* Note that the cgroup.procs might contain duplicates! See * cgroups.txt for details. */ assert(f); assert(_pid); errno = 0; if (fscanf(f, "%lu", &ul) != 1) { if (feof(f)) return 0; return errno > 0 ? -errno : -EIO; } if (ul <= 0) return -EIO; *_pid = (pid_t) ul; return 1; } int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) { _cleanup_free_ char *fs = NULL; int r; DIR *d; assert(_d); /* This is not recursive! */ r = cg_get_path(controller, path, NULL, &fs); if (r < 0) return r; d = opendir(fs); if (!d) return -errno; *_d = d; return 0; } int cg_read_subgroup(DIR *d, char **fn) { struct dirent *de; assert(d); assert(fn); FOREACH_DIRENT_ALL(de, d, return -errno) { char *b; if (de->d_type != DT_DIR) continue; if (streq(de->d_name, ".") || streq(de->d_name, "..")) continue; b = strdup(de->d_name); if (!b) return -ENOMEM; *fn = b; return 1; } return 0; } int cg_rmdir(const char *controller, const char *path) { _cleanup_free_ char *p = NULL; int r; r = cg_get_path(controller, path, NULL, &p); if (r < 0) return r; r = rmdir(p); if (r < 0 && errno != ENOENT) return -errno; return 0; } int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) { _cleanup_set_free_ Set *allocated_set = NULL; bool done = false; int r, ret = 0; pid_t my_pid; assert(sig >= 0); /* This goes through the tasks list and kills them all. This * is repeated until no further processes are added to the * tasks list, to properly handle forking processes */ if (!s) { s = allocated_set = set_new(NULL); if (!s) return -ENOMEM; } my_pid = getpid(); do { _cleanup_fclose_ FILE *f = NULL; pid_t pid = 0; done = true; r = cg_enumerate_processes(controller, path, &f); if (r < 0) { if (ret >= 0 && r != -ENOENT) return r; return ret; } while ((r = cg_read_pid(f, &pid)) > 0) { if (ignore_self && pid == my_pid) continue; if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid)) continue; /* If we haven't killed this process yet, kill * it */ if (kill(pid, sig) < 0) { if (ret >= 0 && errno != ESRCH) ret = -errno; } else { if (sigcont && sig != SIGKILL) (void) kill(pid, SIGCONT); if (ret == 0) ret = 1; } done = false; r = set_put(s, PID_TO_PTR(pid)); if (r < 0) { if (ret >= 0) return r; return ret; } } if (r < 0) { if (ret >= 0) return r; return ret; } /* To avoid racing against processes which fork * quicker than we can kill them we repeat this until * no new pids need to be killed. */ } while (!done); return ret; } int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) { _cleanup_set_free_ Set *allocated_set = NULL; _cleanup_closedir_ DIR *d = NULL; int r, ret; char *fn; assert(path); assert(sig >= 0); if (!s) { s = allocated_set = set_new(NULL); if (!s) return -ENOMEM; } ret = cg_kill(controller, path, sig, sigcont, ignore_self, s); r = cg_enumerate_subgroups(controller, path, &d); if (r < 0) { if (ret >= 0 && r != -ENOENT) return r; return ret; } while ((r = cg_read_subgroup(d, &fn)) > 0) { _cleanup_free_ char *p = NULL; p = strjoin(path, "/", fn, NULL); free(fn); if (!p) return -ENOMEM; r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s); if (r != 0 && ret >= 0) ret = r; } if (ret >= 0 && r < 0) ret = r; if (rem) { r = cg_rmdir(controller, path); if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY) return r; } return ret; } int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self) { bool done = false; _cleanup_set_free_ Set *s = NULL; int r, ret = 0; pid_t my_pid; assert(cfrom); assert(pfrom); assert(cto); assert(pto); s = set_new(NULL); if (!s) return -ENOMEM; my_pid = getpid(); do { _cleanup_fclose_ FILE *f = NULL; pid_t pid = 0; done = true; r = cg_enumerate_processes(cfrom, pfrom, &f); if (r < 0) { if (ret >= 0 && r != -ENOENT) return r; return ret; } while ((r = cg_read_pid(f, &pid)) > 0) { /* This might do weird stuff if we aren't a * single-threaded program. However, we * luckily know we are not */ if (ignore_self && pid == my_pid) continue; if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid)) continue; /* Ignore kernel threads. Since they can only * exist in the root cgroup, we only check for * them there. */ if (cfrom && (isempty(pfrom) || path_equal(pfrom, "/")) && is_kernel_thread(pid) > 0) continue; r = cg_attach(cto, pto, pid); if (r < 0) { if (ret >= 0 && r != -ESRCH) ret = r; } else if (ret == 0) ret = 1; done = false; r = set_put(s, PID_TO_PTR(pid)); if (r < 0) { if (ret >= 0) return r; return ret; } } if (r < 0) { if (ret >= 0) return r; return ret; } } while (!done); return ret; } int cg_migrate_recursive( const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem) { _cleanup_closedir_ DIR *d = NULL; int r, ret = 0; char *fn; assert(cfrom); assert(pfrom); assert(cto); assert(pto); ret = cg_migrate(cfrom, pfrom, cto, pto, ignore_self); r = cg_enumerate_subgroups(cfrom, pfrom, &d); if (r < 0) { if (ret >= 0 && r != -ENOENT) return r; return ret; } while ((r = cg_read_subgroup(d, &fn)) > 0) { _cleanup_free_ char *p = NULL; p = strjoin(pfrom, "/", fn, NULL); free(fn); if (!p) return -ENOMEM; r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem); if (r != 0 && ret >= 0) ret = r; } if (r < 0 && ret >= 0) ret = r; if (rem) { r = cg_rmdir(cfrom, pfrom); if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY) return r; } return ret; } int cg_migrate_recursive_fallback( const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem) { int r; assert(cfrom); assert(pfrom); assert(cto); assert(pto); r = cg_migrate_recursive(cfrom, pfrom, cto, pto, ignore_self, rem); if (r < 0) { char prefix[strlen(pto) + 1]; /* This didn't work? Then let's try all prefixes of the destination */ PATH_FOREACH_PREFIX(prefix, pto) { int q; q = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem); if (q >= 0) return q; } } return r; } static const char *controller_to_dirname(const char *controller) { const char *e; assert(controller); /* Converts a controller name to the directory name below * /sys/fs/cgroup/ we want to mount it to. Effectively, this * just cuts off the name= prefixed used for named * hierarchies, if it is specified. */ e = startswith(controller, "name="); if (e) return e; return controller; } static int join_path_legacy(const char *controller, const char *path, const char *suffix, char **fs) { const char *dn; char *t = NULL; assert(fs); assert(controller); dn = controller_to_dirname(controller); if (isempty(path) && isempty(suffix)) t = strappend("/sys/fs/cgroup/", dn); else if (isempty(path)) t = strjoin("/sys/fs/cgroup/", dn, "/", suffix, NULL); else if (isempty(suffix)) t = strjoin("/sys/fs/cgroup/", dn, "/", path, NULL); else t = strjoin("/sys/fs/cgroup/", dn, "/", path, "/", suffix, NULL); if (!t) return -ENOMEM; *fs = t; return 0; } static int join_path_unified(const char *path, const char *suffix, char **fs) { char *t; assert(fs); if (isempty(path) && isempty(suffix)) t = strdup("/sys/fs/cgroup"); else if (isempty(path)) t = strappend("/sys/fs/cgroup/", suffix); else if (isempty(suffix)) t = strappend("/sys/fs/cgroup/", path); else t = strjoin("/sys/fs/cgroup/", path, "/", suffix, NULL); if (!t) return -ENOMEM; *fs = t; return 0; } int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) { int unified, r; assert(fs); if (!controller) { char *t; /* If no controller is specified, we return the path * *below* the controllers, without any prefix. */ if (!path && !suffix) return -EINVAL; if (!suffix) t = strdup(path); else if (!path) t = strdup(suffix); else t = strjoin(path, "/", suffix, NULL); if (!t) return -ENOMEM; *fs = path_kill_slashes(t); return 0; } if (!cg_controller_is_valid(controller)) return -EINVAL; unified = cg_unified(); if (unified < 0) return unified; if (unified > 0) r = join_path_unified(path, suffix, fs); else r = join_path_legacy(controller, path, suffix, fs); if (r < 0) return r; path_kill_slashes(*fs); return 0; } static int controller_is_accessible(const char *controller) { int unified; assert(controller); /* Checks whether a specific controller is accessible, * i.e. its hierarchy mounted. In the unified hierarchy all * controllers are considered accessible, except for the named * hierarchies */ if (!cg_controller_is_valid(controller)) return -EINVAL; unified = cg_unified(); if (unified < 0) return unified; if (unified > 0) { /* We don't support named hierarchies if we are using * the unified hierarchy. */ if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) return 0; if (startswith(controller, "name=")) return -EOPNOTSUPP; } else { const char *cc, *dn; dn = controller_to_dirname(controller); cc = strjoina("/sys/fs/cgroup/", dn); if (laccess(cc, F_OK) < 0) return -errno; } return 0; } int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) { int r; assert(controller); assert(fs); /* Check if the specified controller is actually accessible */ r = controller_is_accessible(controller); if (r < 0) return r; return cg_get_path(controller, path, suffix, fs); } static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { assert(path); assert(sb); assert(ftwbuf); if (typeflag != FTW_DP) return 0; if (ftwbuf->level < 1) return 0; (void) rmdir(path); return 0; } int cg_trim(const char *controller, const char *path, bool delete_root) { _cleanup_free_ char *fs = NULL; int r = 0; assert(path); r = cg_get_path(controller, path, NULL, &fs); if (r < 0) return r; errno = 0; if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0) { if (errno == ENOENT) r = 0; else if (errno > 0) r = -errno; else r = -EIO; } if (delete_root) { if (rmdir(fs) < 0 && errno != ENOENT) return -errno; } return r; } int cg_create(const char *controller, const char *path) { _cleanup_free_ char *fs = NULL; int r; r = cg_get_path_and_check(controller, path, NULL, &fs); if (r < 0) return r; r = mkdir_parents(fs, 0755); if (r < 0) return r; if (mkdir(fs, 0755) < 0) { if (errno == EEXIST) return 0; return -errno; } return 1; } int cg_create_and_attach(const char *controller, const char *path, pid_t pid) { int r, q; assert(pid >= 0); r = cg_create(controller, path); if (r < 0) return r; q = cg_attach(controller, path, pid); if (q < 0) return q; /* This does not remove the cgroup on failure */ return r; } int cg_attach(const char *controller, const char *path, pid_t pid) { _cleanup_free_ char *fs = NULL; char c[DECIMAL_STR_MAX(pid_t) + 2]; int r; assert(path); assert(pid >= 0); r = cg_get_path_and_check(controller, path, "cgroup.procs", &fs); if (r < 0) return r; if (pid == 0) pid = getpid(); xsprintf(c, PID_FMT "\n", pid); return write_string_file(fs, c, 0); } int cg_attach_fallback(const char *controller, const char *path, pid_t pid) { int r; assert(controller); assert(path); assert(pid >= 0); r = cg_attach(controller, path, pid); if (r < 0) { char prefix[strlen(path) + 1]; /* This didn't work? Then let's try all prefixes of * the destination */ PATH_FOREACH_PREFIX(prefix, path) { int q; q = cg_attach(controller, prefix, pid); if (q >= 0) return q; } } return r; } int cg_set_group_access( const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) { _cleanup_free_ char *fs = NULL; int r; if (mode == MODE_INVALID && uid == UID_INVALID && gid == GID_INVALID) return 0; if (mode != MODE_INVALID) mode &= 0777; r = cg_get_path(controller, path, NULL, &fs); if (r < 0) return r; return chmod_and_chown(fs, mode, uid, gid); } int cg_set_task_access( const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) { _cleanup_free_ char *fs = NULL, *procs = NULL; int r, unified; assert(path); if (mode == MODE_INVALID && uid == UID_INVALID && gid == GID_INVALID) return 0; if (mode != MODE_INVALID) mode &= 0666; r = cg_get_path(controller, path, "cgroup.procs", &fs); if (r < 0) return r; r = chmod_and_chown(fs, mode, uid, gid); if (r < 0) return r; unified = cg_unified(); if (unified < 0) return unified; if (unified) return 0; /* Compatibility, Always keep values for "tasks" in sync with * "cgroup.procs" */ if (cg_get_path(controller, path, "tasks", &procs) >= 0) (void) chmod_and_chown(procs, mode, uid, gid); return 0; } int cg_pid_get_path(const char *controller, pid_t pid, char **path) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; const char *fs; size_t cs = 0; int unified; assert(path); assert(pid >= 0); unified = cg_unified(); if (unified < 0) return unified; if (unified == 0) { if (controller) { if (!cg_controller_is_valid(controller)) return -EINVAL; } else controller = SYSTEMD_CGROUP_CONTROLLER; cs = strlen(controller); } fs = procfs_file_alloca(pid, "cgroup"); f = fopen(fs, "re"); if (!f) return errno == ENOENT ? -ESRCH : -errno; FOREACH_LINE(line, f, return -errno) { char *e, *p; truncate_nl(line); if (unified) { e = startswith(line, "0:"); if (!e) continue; e = strchr(e, ':'); if (!e) continue; } else { char *l; size_t k; const char *word, *state; bool found = false; l = strchr(line, ':'); if (!l) continue; l++; e = strchr(l, ':'); if (!e) continue; *e = 0; FOREACH_WORD_SEPARATOR(word, k, l, ",", state) { if (k == cs && memcmp(word, controller, cs) == 0) { found = true; break; } } if (!found) continue; } p = strdup(e + 1); if (!p) return -ENOMEM; *path = p; return 0; } return -ENODATA; } int cg_install_release_agent(const char *controller, const char *agent) { _cleanup_free_ char *fs = NULL, *contents = NULL; const char *sc; int r, unified; assert(agent); unified = cg_unified(); if (unified < 0) return unified; if (unified) /* doesn't apply to unified hierarchy */ return -EOPNOTSUPP; r = cg_get_path(controller, NULL, "release_agent", &fs); if (r < 0) return r; r = read_one_line_file(fs, &contents); if (r < 0) return r; sc = strstrip(contents); if (isempty(sc)) { r = write_string_file(fs, agent, 0); if (r < 0) return r; } else if (!path_equal(sc, agent)) return -EEXIST; fs = mfree(fs); r = cg_get_path(controller, NULL, "notify_on_release", &fs); if (r < 0) return r; contents = mfree(contents); r = read_one_line_file(fs, &contents); if (r < 0) return r; sc = strstrip(contents); if (streq(sc, "0")) { r = write_string_file(fs, "1", 0); if (r < 0) return r; return 1; } if (!streq(sc, "1")) return -EIO; return 0; } int cg_uninstall_release_agent(const char *controller) { _cleanup_free_ char *fs = NULL; int r, unified; unified = cg_unified(); if (unified < 0) return unified; if (unified) /* Doesn't apply to unified hierarchy */ return -EOPNOTSUPP; r = cg_get_path(controller, NULL, "notify_on_release", &fs); if (r < 0) return r; r = write_string_file(fs, "0", 0); if (r < 0) return r; fs = mfree(fs); r = cg_get_path(controller, NULL, "release_agent", &fs); if (r < 0) return r; r = write_string_file(fs, "", 0); if (r < 0) return r; return 0; } int cg_is_empty(const char *controller, const char *path) { _cleanup_fclose_ FILE *f = NULL; pid_t pid; int r; assert(path); r = cg_enumerate_processes(controller, path, &f); if (r == -ENOENT) return 1; if (r < 0) return r; r = cg_read_pid(f, &pid); if (r < 0) return r; return r == 0; } int cg_is_empty_recursive(const char *controller, const char *path) { int unified, r; assert(path); /* The root cgroup is always populated */ if (controller && (isempty(path) || path_equal(path, "/"))) return false; unified = cg_unified(); if (unified < 0) return unified; if (unified > 0) { _cleanup_free_ char *populated = NULL, *t = NULL; /* On the unified hierarchy we can check empty state * via the "cgroup.populated" attribute. */ r = cg_get_path(controller, path, "cgroup.populated", &populated); if (r < 0) return r; r = read_one_line_file(populated, &t); if (r == -ENOENT) return 1; if (r < 0) return r; return streq(t, "0"); } else { _cleanup_closedir_ DIR *d = NULL; char *fn; r = cg_is_empty(controller, path); if (r <= 0) return r; r = cg_enumerate_subgroups(controller, path, &d); if (r == -ENOENT) return 1; if (r < 0) return r; while ((r = cg_read_subgroup(d, &fn)) > 0) { _cleanup_free_ char *p = NULL; p = strjoin(path, "/", fn, NULL); free(fn); if (!p) return -ENOMEM; r = cg_is_empty_recursive(controller, p); if (r <= 0) return r; } if (r < 0) return r; return true; } } int cg_split_spec(const char *spec, char **controller, char **path) { char *t = NULL, *u = NULL; const char *e; assert(spec); if (*spec == '/') { if (!path_is_safe(spec)) return -EINVAL; if (path) { t = strdup(spec); if (!t) return -ENOMEM; *path = path_kill_slashes(t); } if (controller) *controller = NULL; return 0; } e = strchr(spec, ':'); if (!e) { if (!cg_controller_is_valid(spec)) return -EINVAL; if (controller) { t = strdup(spec); if (!t) return -ENOMEM; *controller = t; } if (path) *path = NULL; return 0; } t = strndup(spec, e-spec); if (!t) return -ENOMEM; if (!cg_controller_is_valid(t)) { free(t); return -EINVAL; } if (isempty(e+1)) u = NULL; else { u = strdup(e+1); if (!u) { free(t); return -ENOMEM; } if (!path_is_safe(u) || !path_is_absolute(u)) { free(t); free(u); return -EINVAL; } path_kill_slashes(u); } if (controller) *controller = t; else free(t); if (path) *path = u; else free(u); return 0; } int cg_mangle_path(const char *path, char **result) { _cleanup_free_ char *c = NULL, *p = NULL; char *t; int r; assert(path); assert(result); /* First, check if it already is a filesystem path */ if (path_startswith(path, "/sys/fs/cgroup")) { t = strdup(path); if (!t) return -ENOMEM; *result = path_kill_slashes(t); return 0; } /* Otherwise, treat it as cg spec */ r = cg_split_spec(path, &c, &p); if (r < 0) return r; return cg_get_path(c ?: SYSTEMD_CGROUP_CONTROLLER, p ?: "/", NULL, result); } int cg_get_root_path(char **path) { char *p, *e; int r; assert(path); r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p); if (r < 0) return r; e = endswith(p, "/" SPECIAL_INIT_SCOPE); if (!e) e = endswith(p, "/" SPECIAL_SYSTEM_SLICE); /* legacy */ if (!e) e = endswith(p, "/system"); /* even more legacy */ if (e) *e = 0; *path = p; return 0; } int cg_shift_path(const char *cgroup, const char *root, const char **shifted) { _cleanup_free_ char *rt = NULL; char *p; int r; assert(cgroup); assert(shifted); if (!root) { /* If the root was specified let's use that, otherwise * let's determine it from PID 1 */ r = cg_get_root_path(&rt); if (r < 0) return r; root = rt; } p = path_startswith(cgroup, root); if (p && p > cgroup) *shifted = p - 1; else *shifted = cgroup; return 0; } int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) { _cleanup_free_ char *raw = NULL; const char *c; int r; assert(pid >= 0); assert(cgroup); r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &raw); if (r < 0) return r; r = cg_shift_path(raw, root, &c); if (r < 0) return r; if (c == raw) { *cgroup = raw; raw = NULL; } else { char *n; n = strdup(c); if (!n) return -ENOMEM; *cgroup = n; } return 0; } int cg_path_decode_unit(const char *cgroup, char **unit){ char *c, *s; size_t n; assert(cgroup); assert(unit); n = strcspn(cgroup, "/"); if (n < 3) return -ENXIO; c = strndupa(cgroup, n); c = cg_unescape(c); if (!unit_name_is_valid(c, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) return -ENXIO; s = strdup(c); if (!s) return -ENOMEM; *unit = s; return 0; } static bool valid_slice_name(const char *p, size_t n) { if (!p) return false; if (n < strlen("x.slice")) return false; if (memcmp(p + n - 6, ".slice", 6) == 0) { char buf[n+1], *c; memcpy(buf, p, n); buf[n] = 0; c = cg_unescape(buf); return unit_name_is_valid(c, UNIT_NAME_PLAIN); } return false; } static const char *skip_slices(const char *p) { assert(p); /* Skips over all slice assignments */ for (;;) { size_t n; p += strspn(p, "/"); n = strcspn(p, "/"); if (!valid_slice_name(p, n)) return p; p += n; } } int cg_path_get_unit(const char *path, char **ret) { const char *e; char *unit; int r; assert(path); assert(ret); e = skip_slices(path); r = cg_path_decode_unit(e, &unit); if (r < 0) return r; /* We skipped over the slices, don't accept any now */ if (endswith(unit, ".slice")) { free(unit); return -ENXIO; } *ret = unit; return 0; } int cg_pid_get_unit(pid_t pid, char **unit) { _cleanup_free_ char *cgroup = NULL; int r; assert(unit); r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; return cg_path_get_unit(cgroup, unit); } /** * Skip session-*.scope, but require it to be there. */ static const char *skip_session(const char *p) { size_t n; if (isempty(p)) return NULL; p += strspn(p, "/"); n = strcspn(p, "/"); if (n < strlen("session-x.scope")) return NULL; if (memcmp(p, "session-", 8) == 0 && memcmp(p + n - 6, ".scope", 6) == 0) { char buf[n - 8 - 6 + 1]; memcpy(buf, p + 8, n - 8 - 6); buf[n - 8 - 6] = 0; /* Note that session scopes never need unescaping, * since they cannot conflict with the kernel's own * names, hence we don't need to call cg_unescape() * here. */ if (!session_id_valid(buf)) return false; p += n; p += strspn(p, "/"); return p; } return NULL; } /** * Skip user@*.service, but require it to be there. */ static const char *skip_user_manager(const char *p) { size_t n; if (isempty(p)) return NULL; p += strspn(p, "/"); n = strcspn(p, "/"); if (n < strlen("user@x.service")) return NULL; if (memcmp(p, "user@", 5) == 0 && memcmp(p + n - 8, ".service", 8) == 0) { char buf[n - 5 - 8 + 1]; memcpy(buf, p + 5, n - 5 - 8); buf[n - 5 - 8] = 0; /* Note that user manager services never need unescaping, * since they cannot conflict with the kernel's own * names, hence we don't need to call cg_unescape() * here. */ if (parse_uid(buf, NULL) < 0) return NULL; p += n; p += strspn(p, "/"); return p; } return NULL; } static const char *skip_user_prefix(const char *path) { const char *e, *t; assert(path); /* Skip slices, if there are any */ e = skip_slices(path); /* Skip the user manager, if it's in the path now... */ t = skip_user_manager(e); if (t) return t; /* Alternatively skip the user session if it is in the path... */ return skip_session(e); } int cg_path_get_user_unit(const char *path, char **ret) { const char *t; assert(path); assert(ret); t = skip_user_prefix(path); if (!t) return -ENXIO; /* And from here on it looks pretty much the same as for a * system unit, hence let's use the same parser from here * on. */ return cg_path_get_unit(t, ret); } int cg_pid_get_user_unit(pid_t pid, char **unit) { _cleanup_free_ char *cgroup = NULL; int r; assert(unit); r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; return cg_path_get_user_unit(cgroup, unit); } int cg_path_get_machine_name(const char *path, char **machine) { _cleanup_free_ char *u = NULL; const char *sl; int r; r = cg_path_get_unit(path, &u); if (r < 0) return r; sl = strjoina("/run/systemd/machines/unit:", u); return readlink_malloc(sl, machine); } int cg_pid_get_machine_name(pid_t pid, char **machine) { _cleanup_free_ char *cgroup = NULL; int r; assert(machine); r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; return cg_path_get_machine_name(cgroup, machine); } int cg_path_get_session(const char *path, char **session) { _cleanup_free_ char *unit = NULL; char *start, *end; int r; assert(path); r = cg_path_get_unit(path, &unit); if (r < 0) return r; start = startswith(unit, "session-"); if (!start) return -ENXIO; end = endswith(start, ".scope"); if (!end) return -ENXIO; *end = 0; if (!session_id_valid(start)) return -ENXIO; if (session) { char *rr; rr = strdup(start); if (!rr) return -ENOMEM; *session = rr; } return 0; } int cg_pid_get_session(pid_t pid, char **session) { _cleanup_free_ char *cgroup = NULL; int r; r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; return cg_path_get_session(cgroup, session); } int cg_path_get_owner_uid(const char *path, uid_t *uid) { _cleanup_free_ char *slice = NULL; char *start, *end; int r; assert(path); r = cg_path_get_slice(path, &slice); if (r < 0) return r; start = startswith(slice, "user-"); if (!start) return -ENXIO; end = endswith(start, ".slice"); if (!end) return -ENXIO; *end = 0; if (parse_uid(start, uid) < 0) return -ENXIO; return 0; } int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) { _cleanup_free_ char *cgroup = NULL; int r; r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; return cg_path_get_owner_uid(cgroup, uid); } int cg_path_get_slice(const char *p, char **slice) { const char *e = NULL; assert(p); assert(slice); /* Finds the right-most slice unit from the beginning, but * stops before we come to the first non-slice unit. */ for (;;) { size_t n; p += strspn(p, "/"); n = strcspn(p, "/"); if (!valid_slice_name(p, n)) { if (!e) { char *s; s = strdup("-.slice"); if (!s) return -ENOMEM; *slice = s; return 0; } return cg_path_decode_unit(e, slice); } e = p; p += n; } } int cg_pid_get_slice(pid_t pid, char **slice) { _cleanup_free_ char *cgroup = NULL; int r; assert(slice); r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; return cg_path_get_slice(cgroup, slice); } int cg_path_get_user_slice(const char *p, char **slice) { const char *t; assert(p); assert(slice); t = skip_user_prefix(p); if (!t) return -ENXIO; /* And now it looks pretty much the same as for a system * slice, so let's just use the same parser from here on. */ return cg_path_get_slice(t, slice); } int cg_pid_get_user_slice(pid_t pid, char **slice) { _cleanup_free_ char *cgroup = NULL; int r; assert(slice); r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; return cg_path_get_user_slice(cgroup, slice); } char *cg_escape(const char *p) { bool need_prefix = false; /* This implements very minimal escaping for names to be used * as file names in the cgroup tree: any name which might * conflict with a kernel name or is prefixed with '_' is * prefixed with a '_'. That way, when reading cgroup names it * is sufficient to remove a single prefixing underscore if * there is one. */ /* The return value of this function (unlike cg_unescape()) * needs free()! */ if (p[0] == 0 || p[0] == '_' || p[0] == '.' || streq(p, "notify_on_release") || streq(p, "release_agent") || streq(p, "tasks") || startswith(p, "cgroup.")) need_prefix = true; else { const char *dot; dot = strrchr(p, '.'); if (dot) { CGroupController c; size_t l = dot - p; for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { const char *n; n = cgroup_controller_to_string(c); if (l != strlen(n)) continue; if (memcmp(p, n, l) != 0) continue; need_prefix = true; break; } } } if (need_prefix) return strappend("_", p); return strdup(p); } char *cg_unescape(const char *p) { assert(p); /* The return value of this function (unlike cg_escape()) * doesn't need free()! */ if (p[0] == '_') return (char*) p+1; return (char*) p; } #define CONTROLLER_VALID \ DIGITS LETTERS \ "_" bool cg_controller_is_valid(const char *p) { const char *t, *s; if (!p) return false; s = startswith(p, "name="); if (s) p = s; if (*p == 0 || *p == '_') return false; for (t = p; *t; t++) if (!strchr(CONTROLLER_VALID, *t)) return false; if (t - p > FILENAME_MAX) return false; return true; } int cg_slice_to_path(const char *unit, char **ret) { _cleanup_free_ char *p = NULL, *s = NULL, *e = NULL; const char *dash; int r; assert(unit); assert(ret); if (streq(unit, "-.slice")) { char *x; x = strdup(""); if (!x) return -ENOMEM; *ret = x; return 0; } if (!unit_name_is_valid(unit, UNIT_NAME_PLAIN)) return -EINVAL; if (!endswith(unit, ".slice")) return -EINVAL; r = unit_name_to_prefix(unit, &p); if (r < 0) return r; dash = strchr(p, '-'); /* Don't allow initial dashes */ if (dash == p) return -EINVAL; while (dash) { _cleanup_free_ char *escaped = NULL; char n[dash - p + sizeof(".slice")]; /* Don't allow trailing or double dashes */ if (dash[1] == 0 || dash[1] == '-') return -EINVAL; strcpy(stpncpy(n, p, dash - p), ".slice"); if (!unit_name_is_valid(n, UNIT_NAME_PLAIN)) return -EINVAL; escaped = cg_escape(n); if (!escaped) return -ENOMEM; if (!strextend(&s, escaped, "/", NULL)) return -ENOMEM; dash = strchr(dash+1, '-'); } e = cg_escape(unit); if (!e) return -ENOMEM; if (!strextend(&s, e, NULL)) return -ENOMEM; *ret = s; s = NULL; return 0; } int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) { _cleanup_free_ char *p = NULL; int r; r = cg_get_path(controller, path, attribute, &p); if (r < 0) return r; return write_string_file(p, value, 0); } int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret) { _cleanup_free_ char *p = NULL; int r; r = cg_get_path(controller, path, attribute, &p); if (r < 0) return r; return read_one_line_file(p, ret); } int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path) { CGroupController c; int r, unified; /* This one will create a cgroup in our private tree, but also * duplicate it in the trees specified in mask, and remove it * in all others */ /* First create the cgroup in our own hierarchy. */ r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path); if (r < 0) return r; /* If we are in the unified hierarchy, we are done now */ unified = cg_unified(); if (unified < 0) return unified; if (unified > 0) return 0; /* Otherwise, do the same in the other hierarchies */ for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); const char *n; n = cgroup_controller_to_string(c); if (mask & bit) (void) cg_create(n, path); else if (supported & bit) (void) cg_trim(n, path, true); } return 0; } int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_migrate_callback_t path_callback, void *userdata) { CGroupController c; int r, unified; r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid); if (r < 0) return r; unified = cg_unified(); if (unified < 0) return unified; if (unified > 0) return 0; for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); const char *p = NULL; if (!(supported & bit)) continue; if (path_callback) p = path_callback(bit, userdata); if (!p) p = path; (void) cg_attach_fallback(cgroup_controller_to_string(c), p, pid); } return 0; } int cg_attach_many_everywhere(CGroupMask supported, const char *path, Set* pids, cg_migrate_callback_t path_callback, void *userdata) { Iterator i; void *pidp; int r = 0; SET_FOREACH(pidp, pids, i) { pid_t pid = PTR_TO_PID(pidp); int q; q = cg_attach_everywhere(supported, path, pid, path_callback, userdata); if (q < 0 && r >= 0) r = q; } return r; } int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to, cg_migrate_callback_t to_callback, void *userdata) { CGroupController c; int r = 0, unified; if (!path_equal(from, to)) { r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true); if (r < 0) return r; } unified = cg_unified(); if (unified < 0) return unified; if (unified > 0) return r; for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); const char *p = NULL; if (!(supported & bit)) continue; if (to_callback) p = to_callback(bit, userdata); if (!p) p = to; (void) cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, cgroup_controller_to_string(c), p, false, false); } return 0; } int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root) { CGroupController c; int r, unified; r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root); if (r < 0) return r; unified = cg_unified(); if (unified < 0) return unified; if (unified > 0) return r; for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); if (!(supported & bit)) continue; (void) cg_trim(cgroup_controller_to_string(c), path, delete_root); } return 0; } int cg_mask_supported(CGroupMask *ret) { CGroupMask mask = 0; int r, unified; /* Determines the mask of supported cgroup controllers. Only * includes controllers we can make sense of and that are * actually accessible. */ unified = cg_unified(); if (unified < 0) return unified; if (unified > 0) { _cleanup_free_ char *root = NULL, *controllers = NULL, *path = NULL; const char *c; /* In the unified hierarchy we can read the supported * and accessible controllers from a the top-level * cgroup attribute */ r = cg_get_root_path(&root); if (r < 0) return r; r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, "cgroup.controllers", &path); if (r < 0) return r; r = read_one_line_file(path, &controllers); if (r < 0) return r; c = controllers; for (;;) { _cleanup_free_ char *n = NULL; CGroupController v; r = extract_first_word(&c, &n, NULL, 0); if (r < 0) return r; if (r == 0) break; v = cgroup_controller_from_string(n); if (v < 0) continue; mask |= CGROUP_CONTROLLER_TO_MASK(v); } /* Currently, we only support the memory and pids * controller in the unified hierarchy, mask * everything else off. */ mask &= CGROUP_MASK_MEMORY | CGROUP_MASK_PIDS; } else { CGroupController c; /* In the legacy hierarchy, we check whether which * hierarchies are mounted. */ for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { const char *n; n = cgroup_controller_to_string(c); if (controller_is_accessible(n) >= 0) mask |= CGROUP_CONTROLLER_TO_MASK(c); } } *ret = mask; return 0; } int cg_kernel_controllers(Set *controllers) { _cleanup_fclose_ FILE *f = NULL; char buf[LINE_MAX]; int r; assert(controllers); /* Determines the full list of kernel-known controllers. Might * include controllers we don't actually support, arbitrary * named hierarchies and controllers that aren't currently * accessible (because not mounted). */ f = fopen("/proc/cgroups", "re"); if (!f) { if (errno == ENOENT) return 0; return -errno; } /* Ignore the header line */ (void) fgets(buf, sizeof(buf), f); for (;;) { char *controller; int enabled = 0; errno = 0; if (fscanf(f, "%ms %*i %*i %i", &controller, &enabled) != 2) { if (feof(f)) break; if (ferror(f) && errno > 0) return -errno; return -EBADMSG; } if (!enabled) { free(controller); continue; } if (!cg_controller_is_valid(controller)) { free(controller); return -EBADMSG; } r = set_consume(controllers, controller); if (r < 0) return r; } return 0; } static thread_local int unified_cache = -1; int cg_unified(void) { struct statfs fs; /* Checks if we support the unified hierarchy. Returns an * error when the cgroup hierarchies aren't mounted yet or we * have any other trouble determining if the unified hierarchy * is supported. */ if (unified_cache >= 0) return unified_cache; if (statfs("/sys/fs/cgroup/", &fs) < 0) return -errno; if (F_TYPE_EQUAL(fs.f_type, CGROUP_SUPER_MAGIC)) unified_cache = true; else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC)) unified_cache = false; else return -ENOMEDIUM; return unified_cache; } void cg_unified_flush(void) { unified_cache = -1; } int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p) { _cleanup_free_ char *fs = NULL; CGroupController c; int r, unified; assert(p); if (supported == 0) return 0; unified = cg_unified(); if (unified < 0) return unified; if (!unified) /* on the legacy hiearchy there's no joining of controllers defined */ return 0; r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, p, "cgroup.subtree_control", &fs); if (r < 0) return r; for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); const char *n; if (!(supported & bit)) continue; n = cgroup_controller_to_string(c); { char s[1 + strlen(n) + 1]; s[0] = mask & bit ? '+' : '-'; strcpy(s + 1, n); r = write_string_file(fs, s, 0); if (r < 0) log_debug_errno(r, "Failed to enable controller %s for %s (%s): %m", n, p, fs); } } return 0; } bool cg_is_unified_wanted(void) { static thread_local int wanted = -1; int r, unified; /* If the hierarchy is already mounted, then follow whatever * was chosen for it. */ unified = cg_unified(); if (unified >= 0) return unified; /* Otherwise, let's see what the kernel command line has to * say. Since checking that is expensive, let's cache the * result. */ if (wanted >= 0) return wanted; r = get_proc_cmdline_key("systemd.unified_cgroup_hierarchy", NULL); if (r > 0) return (wanted = true); else { _cleanup_free_ char *value = NULL; r = get_proc_cmdline_key("systemd.unified_cgroup_hierarchy=", &value); if (r < 0) return false; if (r == 0) return (wanted = false); return (wanted = parse_boolean(value) > 0); } } bool cg_is_legacy_wanted(void) { return !cg_is_unified_wanted(); } int cg_cpu_shares_parse(const char *s, uint64_t *ret) { uint64_t u; int r; if (isempty(s)) { *ret = CGROUP_CPU_SHARES_INVALID; return 0; } r = safe_atou64(s, &u); if (r < 0) return r; if (u < CGROUP_CPU_SHARES_MIN || u > CGROUP_CPU_SHARES_MAX) return -ERANGE; *ret = u; return 0; } int cg_blkio_weight_parse(const char *s, uint64_t *ret) { uint64_t u; int r; if (isempty(s)) { *ret = CGROUP_BLKIO_WEIGHT_INVALID; return 0; } r = safe_atou64(s, &u); if (r < 0) return r; if (u < CGROUP_BLKIO_WEIGHT_MIN || u > CGROUP_BLKIO_WEIGHT_MAX) return -ERANGE; *ret = u; return 0; } static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = { [CGROUP_CONTROLLER_CPU] = "cpu", [CGROUP_CONTROLLER_CPUACCT] = "cpuacct", [CGROUP_CONTROLLER_BLKIO] = "blkio", [CGROUP_CONTROLLER_MEMORY] = "memory", [CGROUP_CONTROLLER_DEVICES] = "devices", [CGROUP_CONTROLLER_PIDS] = "pids", }; DEFINE_STRING_TABLE_LOOKUP(cgroup_controller, CGroupController); systemd-229/src/basic/cgroup-util.h000066400000000000000000000174441265713322000173660ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "def.h" #include "hashmap.h" #include "macro.h" #include "set.h" /* An enum of well known cgroup controllers */ typedef enum CGroupController { CGROUP_CONTROLLER_CPU, CGROUP_CONTROLLER_CPUACCT, CGROUP_CONTROLLER_BLKIO, CGROUP_CONTROLLER_MEMORY, CGROUP_CONTROLLER_DEVICES, CGROUP_CONTROLLER_PIDS, _CGROUP_CONTROLLER_MAX, _CGROUP_CONTROLLER_INVALID = -1, } CGroupController; #define CGROUP_CONTROLLER_TO_MASK(c) (1 << (c)) /* A bit mask of well known cgroup controllers */ typedef enum CGroupMask { CGROUP_MASK_CPU = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPU), CGROUP_MASK_CPUACCT = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUACCT), CGROUP_MASK_BLKIO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BLKIO), CGROUP_MASK_MEMORY = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_MEMORY), CGROUP_MASK_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_DEVICES), CGROUP_MASK_PIDS = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_PIDS), _CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1 } CGroupMask; /* Special values for the cpu.shares attribute */ #define CGROUP_CPU_SHARES_INVALID ((uint64_t) -1) #define CGROUP_CPU_SHARES_MIN UINT64_C(2) #define CGROUP_CPU_SHARES_MAX UINT64_C(262144) #define CGROUP_CPU_SHARES_DEFAULT UINT64_C(1024) static inline bool CGROUP_CPU_SHARES_IS_OK(uint64_t x) { return x == CGROUP_CPU_SHARES_INVALID || (x >= CGROUP_CPU_SHARES_MIN && x <= CGROUP_CPU_SHARES_MAX); } /* Special values for the blkio.weight attribute */ #define CGROUP_BLKIO_WEIGHT_INVALID ((uint64_t) -1) #define CGROUP_BLKIO_WEIGHT_MIN UINT64_C(10) #define CGROUP_BLKIO_WEIGHT_MAX UINT64_C(1000) #define CGROUP_BLKIO_WEIGHT_DEFAULT UINT64_C(500) static inline bool CGROUP_BLKIO_WEIGHT_IS_OK(uint64_t x) { return x == CGROUP_BLKIO_WEIGHT_INVALID || (x >= CGROUP_BLKIO_WEIGHT_MIN && x <= CGROUP_BLKIO_WEIGHT_MAX); } /* * General rules: * * We accept named hierarchies in the syntax "foo" and "name=foo". * * We expect that named hierarchies do not conflict in name with a * kernel hierarchy, modulo the "name=" prefix. * * We always generate "normalized" controller names, i.e. without the * "name=" prefix. * * We require absolute cgroup paths. When returning, we will always * generate paths with multiple adjacent / removed. */ int cg_enumerate_processes(const char *controller, const char *path, FILE **_f); int cg_read_pid(FILE *f, pid_t *_pid); int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d); int cg_read_subgroup(DIR *d, char **fn); int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s); int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool remove, Set *s); int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self); int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool remove); int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem); int cg_split_spec(const char *spec, char **controller, char **path); int cg_mangle_path(const char *path, char **result); int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs); int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs); int cg_pid_get_path(const char *controller, pid_t pid, char **path); int cg_trim(const char *controller, const char *path, bool delete_root); int cg_rmdir(const char *controller, const char *path); int cg_create(const char *controller, const char *path); int cg_attach(const char *controller, const char *path, pid_t pid); int cg_attach_fallback(const char *controller, const char *path, pid_t pid); int cg_create_and_attach(const char *controller, const char *path, pid_t pid); int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value); int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret); int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid); int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid); int cg_install_release_agent(const char *controller, const char *agent); int cg_uninstall_release_agent(const char *controller); int cg_is_empty(const char *controller, const char *path); int cg_is_empty_recursive(const char *controller, const char *path); int cg_get_root_path(char **path); int cg_path_get_session(const char *path, char **session); int cg_path_get_owner_uid(const char *path, uid_t *uid); int cg_path_get_unit(const char *path, char **unit); int cg_path_get_user_unit(const char *path, char **unit); int cg_path_get_machine_name(const char *path, char **machine); int cg_path_get_slice(const char *path, char **slice); int cg_path_get_user_slice(const char *path, char **slice); int cg_shift_path(const char *cgroup, const char *cached_root, const char **shifted); int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **cgroup); int cg_pid_get_session(pid_t pid, char **session); int cg_pid_get_owner_uid(pid_t pid, uid_t *uid); int cg_pid_get_unit(pid_t pid, char **unit); int cg_pid_get_user_unit(pid_t pid, char **unit); int cg_pid_get_machine_name(pid_t pid, char **machine); int cg_pid_get_slice(pid_t pid, char **slice); int cg_pid_get_user_slice(pid_t pid, char **slice); int cg_path_decode_unit(const char *cgroup, char **unit); char *cg_escape(const char *p); char *cg_unescape(const char *p) _pure_; bool cg_controller_is_valid(const char *p); int cg_slice_to_path(const char *unit, char **ret); typedef const char* (*cg_migrate_callback_t)(CGroupMask mask, void *userdata); int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path); int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_migrate_callback_t callback, void *userdata); int cg_attach_many_everywhere(CGroupMask supported, const char *path, Set* pids, cg_migrate_callback_t callback, void *userdata); int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to, cg_migrate_callback_t callback, void *userdata); int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root); int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p); int cg_mask_supported(CGroupMask *ret); int cg_kernel_controllers(Set *controllers); int cg_unified(void); void cg_unified_flush(void); bool cg_is_unified_wanted(void); bool cg_is_legacy_wanted(void); const char* cgroup_controller_to_string(CGroupController c) _const_; CGroupController cgroup_controller_from_string(const char *s) _pure_; int cg_cpu_shares_parse(const char *s, uint64_t *ret); int cg_blkio_weight_parse(const char *s, uint64_t *ret); systemd-229/src/basic/chattr-util.c000066400000000000000000000054461265713322000173460ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "chattr-util.h" #include "fd-util.h" #include "macro.h" int chattr_fd(int fd, unsigned value, unsigned mask) { unsigned old_attr, new_attr; struct stat st; assert(fd >= 0); if (fstat(fd, &st) < 0) return -errno; /* Explicitly check whether this is a regular file or * directory. If it is anything else (such as a device node or * fifo), then the ioctl will not hit the file systems but * possibly drivers, where the ioctl might have different * effects. Notably, DRM is using the same ioctl() number. */ if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) return -ENOTTY; if (mask == 0) return 0; if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0) return -errno; new_attr = (old_attr & ~mask) | (value & mask); if (new_attr == old_attr) return 0; if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0) return -errno; return 1; } int chattr_path(const char *p, unsigned value, unsigned mask) { _cleanup_close_ int fd = -1; assert(p); if (mask == 0) return 0; fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd < 0) return -errno; return chattr_fd(fd, value, mask); } int read_attr_fd(int fd, unsigned *ret) { struct stat st; assert(fd >= 0); if (fstat(fd, &st) < 0) return -errno; if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) return -ENOTTY; if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0) return -errno; return 0; } int read_attr_path(const char *p, unsigned *ret) { _cleanup_close_ int fd = -1; assert(p); assert(ret); fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd < 0) return -errno; return read_attr_fd(fd, ret); } systemd-229/src/basic/chattr-util.h000066400000000000000000000016561265713322000173520ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int chattr_fd(int fd, unsigned value, unsigned mask); int chattr_path(const char *p, unsigned value, unsigned mask); int read_attr_fd(int fd, unsigned *ret); int read_attr_path(const char *p, unsigned *ret); systemd-229/src/basic/clock-util.c000066400000000000000000000103101265713322000171360ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010-2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include "clock-util.h" #include "fd-util.h" #include "macro.h" #include "string-util.h" #include "util.h" int clock_get_hwclock(struct tm *tm) { _cleanup_close_ int fd = -1; assert(tm); fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC); if (fd < 0) return -errno; /* This leaves the timezone fields of struct tm * uninitialized! */ if (ioctl(fd, RTC_RD_TIME, tm) < 0) return -errno; /* We don't know daylight saving, so we reset this in order not * to confuse mktime(). */ tm->tm_isdst = -1; return 0; } int clock_set_hwclock(const struct tm *tm) { _cleanup_close_ int fd = -1; assert(tm); fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC); if (fd < 0) return -errno; if (ioctl(fd, RTC_SET_TIME, tm) < 0) return -errno; return 0; } int clock_is_localtime(void) { _cleanup_fclose_ FILE *f; /* * The third line of adjtime is "UTC" or "LOCAL" or nothing. * # /etc/adjtime * 0.0 0 0 * 0 * UTC */ f = fopen("/etc/adjtime", "re"); if (f) { char line[LINE_MAX]; bool b; b = fgets(line, sizeof(line), f) && fgets(line, sizeof(line), f) && fgets(line, sizeof(line), f); if (!b) return -EIO; truncate_nl(line); return streq(line, "LOCAL"); } else if (errno != ENOENT) return -errno; return 0; } int clock_set_timezone(int *min) { const struct timeval *tv_null = NULL; struct timespec ts; struct tm *tm; int minutesdelta; struct timezone tz; assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0); assert_se(tm = localtime(&ts.tv_sec)); minutesdelta = tm->tm_gmtoff / 60; tz.tz_minuteswest = -minutesdelta; tz.tz_dsttime = 0; /* DST_NONE */ /* * If the RTC does not run in UTC but in local time, the very first * call to settimeofday() will set the kernel's timezone and will warp the * system clock, so that it runs in UTC instead of the local time we * have read from the RTC. */ if (settimeofday(tv_null, &tz) < 0) return negative_errno(); if (min) *min = minutesdelta; return 0; } int clock_reset_timewarp(void) { const struct timeval *tv_null = NULL; struct timezone tz; tz.tz_minuteswest = 0; tz.tz_dsttime = 0; /* DST_NONE */ /* * The very first call to settimeofday() does time warp magic. Do a * dummy call here, so the time warping is sealed and all later calls * behave as expected. */ if (settimeofday(tv_null, &tz) < 0) return -errno; return 0; } #define TIME_EPOCH_USEC ((usec_t) TIME_EPOCH * USEC_PER_SEC) int clock_apply_epoch(void) { struct timespec ts; if (now(CLOCK_REALTIME) >= TIME_EPOCH_USEC) return 0; if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, TIME_EPOCH_USEC)) < 0) return -errno; return 1; } systemd-229/src/basic/clock-util.h000066400000000000000000000017041265713322000171520ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010-2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include int clock_is_localtime(void); int clock_set_timezone(int *min); int clock_reset_timewarp(void); int clock_get_hwclock(struct tm *tm); int clock_set_hwclock(const struct tm *tm); int clock_apply_epoch(void); systemd-229/src/basic/conf-files.c000066400000000000000000000110201265713322000171140ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "conf-files.h" #include "dirent-util.h" #include "fd-util.h" #include "hashmap.h" #include "log.h" #include "macro.h" #include "missing.h" #include "path-util.h" #include "string-util.h" #include "strv.h" #include "util.h" static int files_add(Hashmap *h, const char *root, const char *path, const char *suffix) { _cleanup_closedir_ DIR *dir = NULL; const char *dirpath; struct dirent *de; int r; assert(path); assert(suffix); dirpath = prefix_roota(root, path); dir = opendir(dirpath); if (!dir) { if (errno == ENOENT) return 0; return -errno; } FOREACH_DIRENT(de, dir, return -errno) { char *p; if (!dirent_is_file_with_suffix(de, suffix)) continue; p = strjoin(dirpath, "/", de->d_name, NULL); if (!p) return -ENOMEM; r = hashmap_put(h, basename(p), p); if (r == -EEXIST) { log_debug("Skipping overridden file: %s.", p); free(p); } else if (r < 0) { free(p); return r; } else if (r == 0) { log_debug("Duplicate file %s", p); free(p); } } return 0; } static int base_cmp(const void *a, const void *b) { const char *s1, *s2; s1 = *(char * const *)a; s2 = *(char * const *)b; return strcmp(basename(s1), basename(s2)); } static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, char **dirs) { _cleanup_hashmap_free_ Hashmap *fh = NULL; char **files, **p; int r; assert(strv); assert(suffix); /* This alters the dirs string array */ if (!path_strv_resolve_uniq(dirs, root)) return -ENOMEM; fh = hashmap_new(&string_hash_ops); if (!fh) return -ENOMEM; STRV_FOREACH(p, dirs) { r = files_add(fh, root, *p, suffix); if (r == -ENOMEM) return r; if (r < 0) log_debug_errno(r, "Failed to search for files in %s, ignoring: %m", *p); } files = hashmap_get_strv(fh); if (!files) return -ENOMEM; qsort_safe(files, hashmap_size(fh), sizeof(char *), base_cmp); *strv = files; return 0; } int conf_files_list_strv(char ***strv, const char *suffix, const char *root, const char* const* dirs) { _cleanup_strv_free_ char **copy = NULL; assert(strv); assert(suffix); copy = strv_copy((char**) dirs); if (!copy) return -ENOMEM; return conf_files_list_strv_internal(strv, suffix, root, copy); } int conf_files_list(char ***strv, const char *suffix, const char *root, const char *dir, ...) { _cleanup_strv_free_ char **dirs = NULL; va_list ap; assert(strv); assert(suffix); va_start(ap, dir); dirs = strv_new_ap(dir, ap); va_end(ap); if (!dirs) return -ENOMEM; return conf_files_list_strv_internal(strv, suffix, root, dirs); } int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, const char *d) { _cleanup_strv_free_ char **dirs = NULL; assert(strv); assert(suffix); dirs = strv_split_nulstr(d); if (!dirs) return -ENOMEM; return conf_files_list_strv_internal(strv, suffix, root, dirs); } systemd-229/src/basic/conf-files.h000066400000000000000000000020511265713322000171250ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010-2012 Lennart Poettering Copyright 2010-2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int conf_files_list(char ***ret, const char *suffix, const char *root, const char *dir, ...); int conf_files_list_strv(char ***ret, const char *suffix, const char *root, const char* const* dirs); int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, const char *dirs); systemd-229/src/basic/copy.c000066400000000000000000000362321265713322000160550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "btrfs-util.h" #include "chattr-util.h" #include "copy.h" #include "dirent-util.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "io-util.h" #include "macro.h" #include "string-util.h" #include "strv.h" #include "time-util.h" #include "umask-util.h" #include "xattr-util.h" #define COPY_BUFFER_SIZE (16*1024) int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) { bool try_sendfile = true, try_splice = true; int r; assert(fdf >= 0); assert(fdt >= 0); /* Try btrfs reflinks first. */ if (try_reflink && max_bytes == (uint64_t) -1 && lseek(fdf, 0, SEEK_CUR) == 0 && lseek(fdt, 0, SEEK_CUR) == 0) { r = btrfs_reflink(fdf, fdt); if (r >= 0) return 0; /* we copied the whole thing, hence hit EOF, return 0 */ } for (;;) { size_t m = COPY_BUFFER_SIZE; ssize_t n; if (max_bytes != (uint64_t) -1) { if (max_bytes <= 0) return 1; /* return > 0 if we hit the max_bytes limit */ if ((uint64_t) m > max_bytes) m = (size_t) max_bytes; } /* First try sendfile(), unless we already tried */ if (try_sendfile) { n = sendfile(fdt, fdf, NULL, m); if (n < 0) { if (errno != EINVAL && errno != ENOSYS) return -errno; try_sendfile = false; /* use fallback below */ } else if (n == 0) /* EOF */ break; else if (n > 0) /* Success! */ goto next; } /* The try splice, unless we already tried */ if (try_splice) { n = splice(fdf, NULL, fdt, NULL, m, 0); if (n < 0) { if (errno != EINVAL && errno != ENOSYS) return -errno; try_splice = false; /* use fallback below */ } else if (n == 0) /* EOF */ break; else if (n > 0) /* Success! */ goto next; } /* As a fallback just copy bits by hand */ { uint8_t buf[m]; n = read(fdf, buf, m); if (n < 0) return -errno; if (n == 0) /* EOF */ break; r = loop_write(fdt, buf, (size_t) n, false); if (r < 0) return r; } next: if (max_bytes != (uint64_t) -1) { assert(max_bytes >= (uint64_t) n); max_bytes -= n; } } return 0; /* return 0 if we hit EOF earlier than the size limit */ } static int fd_copy_symlink(int df, const char *from, const struct stat *st, int dt, const char *to) { _cleanup_free_ char *target = NULL; int r; assert(from); assert(st); assert(to); r = readlinkat_malloc(df, from, &target); if (r < 0) return r; if (symlinkat(target, dt, to) < 0) return -errno; if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0) return -errno; return 0; } static int fd_copy_regular(int df, const char *from, const struct stat *st, int dt, const char *to) { _cleanup_close_ int fdf = -1, fdt = -1; struct timespec ts[2]; int r, q; assert(from); assert(st); assert(to); fdf = openat(df, from, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fdf < 0) return -errno; fdt = openat(dt, to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, st->st_mode & 07777); if (fdt < 0) return -errno; r = copy_bytes(fdf, fdt, (uint64_t) -1, true); if (r < 0) { unlinkat(dt, to, 0); return r; } if (fchown(fdt, st->st_uid, st->st_gid) < 0) r = -errno; if (fchmod(fdt, st->st_mode & 07777) < 0) r = -errno; ts[0] = st->st_atim; ts[1] = st->st_mtim; (void) futimens(fdt, ts); (void) copy_xattr(fdf, fdt); q = close(fdt); fdt = -1; if (q < 0) { r = -errno; unlinkat(dt, to, 0); } return r; } static int fd_copy_fifo(int df, const char *from, const struct stat *st, int dt, const char *to) { int r; assert(from); assert(st); assert(to); r = mkfifoat(dt, to, st->st_mode & 07777); if (r < 0) return -errno; if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0) r = -errno; if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0) r = -errno; return r; } static int fd_copy_node(int df, const char *from, const struct stat *st, int dt, const char *to) { int r; assert(from); assert(st); assert(to); r = mknodat(dt, to, st->st_mode, st->st_rdev); if (r < 0) return -errno; if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0) r = -errno; if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0) r = -errno; return r; } static int fd_copy_directory( int df, const char *from, const struct stat *st, int dt, const char *to, dev_t original_device, bool merge) { _cleanup_close_ int fdf = -1, fdt = -1; _cleanup_closedir_ DIR *d = NULL; struct dirent *de; bool created; int r; assert(st); assert(to); if (from) fdf = openat(df, from, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); else fdf = fcntl(df, F_DUPFD_CLOEXEC, 3); d = fdopendir(fdf); if (!d) return -errno; fdf = -1; r = mkdirat(dt, to, st->st_mode & 07777); if (r >= 0) created = true; else if (errno == EEXIST && merge) created = false; else return -errno; fdt = openat(dt, to, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fdt < 0) return -errno; r = 0; if (created) { struct timespec ut[2] = { st->st_atim, st->st_mtim }; if (fchown(fdt, st->st_uid, st->st_gid) < 0) r = -errno; if (fchmod(fdt, st->st_mode & 07777) < 0) r = -errno; (void) futimens(fdt, ut); (void) copy_xattr(dirfd(d), fdt); } FOREACH_DIRENT_ALL(de, d, return -errno) { struct stat buf; int q; if (STR_IN_SET(de->d_name, ".", "..")) continue; if (fstatat(dirfd(d), de->d_name, &buf, AT_SYMLINK_NOFOLLOW) < 0) { r = -errno; continue; } if (buf.st_dev != original_device) continue; if (S_ISREG(buf.st_mode)) q = fd_copy_regular(dirfd(d), de->d_name, &buf, fdt, de->d_name); else if (S_ISDIR(buf.st_mode)) q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, merge); else if (S_ISLNK(buf.st_mode)) q = fd_copy_symlink(dirfd(d), de->d_name, &buf, fdt, de->d_name); else if (S_ISFIFO(buf.st_mode)) q = fd_copy_fifo(dirfd(d), de->d_name, &buf, fdt, de->d_name); else if (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode)) q = fd_copy_node(dirfd(d), de->d_name, &buf, fdt, de->d_name); else q = -EOPNOTSUPP; if (q == -EEXIST && merge) q = 0; if (q < 0) r = q; } return r; } int copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge) { struct stat st; assert(from); assert(to); if (fstatat(fdf, from, &st, AT_SYMLINK_NOFOLLOW) < 0) return -errno; if (S_ISREG(st.st_mode)) return fd_copy_regular(fdf, from, &st, fdt, to); else if (S_ISDIR(st.st_mode)) return fd_copy_directory(fdf, from, &st, fdt, to, st.st_dev, merge); else if (S_ISLNK(st.st_mode)) return fd_copy_symlink(fdf, from, &st, fdt, to); else if (S_ISFIFO(st.st_mode)) return fd_copy_fifo(fdf, from, &st, fdt, to); else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) return fd_copy_node(fdf, from, &st, fdt, to); else return -EOPNOTSUPP; } int copy_tree(const char *from, const char *to, bool merge) { return copy_tree_at(AT_FDCWD, from, AT_FDCWD, to, merge); } int copy_directory_fd(int dirfd, const char *to, bool merge) { struct stat st; assert(dirfd >= 0); assert(to); if (fstat(dirfd, &st) < 0) return -errno; if (!S_ISDIR(st.st_mode)) return -ENOTDIR; return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, merge); } int copy_file_fd(const char *from, int fdt, bool try_reflink) { _cleanup_close_ int fdf = -1; int r; assert(from); assert(fdt >= 0); fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fdf < 0) return -errno; r = copy_bytes(fdf, fdt, (uint64_t) -1, try_reflink); (void) copy_times(fdf, fdt); (void) copy_xattr(fdf, fdt); return r; } int copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned chattr_flags) { int fdt = -1, r; assert(from); assert(to); RUN_WITH_UMASK(0000) { fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode); if (fdt < 0) return -errno; } if (chattr_flags != 0) (void) chattr_fd(fdt, chattr_flags, (unsigned) -1); r = copy_file_fd(from, fdt, true); if (r < 0) { close(fdt); unlink(to); return r; } if (close(fdt) < 0) { unlink_noerrno(to); return -errno; } return 0; } int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace, unsigned chattr_flags) { _cleanup_free_ char *t = NULL; int r; assert(from); assert(to); r = tempfn_random(to, NULL, &t); if (r < 0) return r; r = copy_file(from, t, O_NOFOLLOW|O_EXCL, mode, chattr_flags); if (r < 0) return r; if (replace) { r = renameat(AT_FDCWD, t, AT_FDCWD, to); if (r < 0) r = -errno; } else r = rename_noreplace(AT_FDCWD, t, AT_FDCWD, to); if (r < 0) { (void) unlink_noerrno(t); return r; } return 0; } int copy_times(int fdf, int fdt) { struct timespec ut[2]; struct stat st; usec_t crtime = 0; assert(fdf >= 0); assert(fdt >= 0); if (fstat(fdf, &st) < 0) return -errno; ut[0] = st.st_atim; ut[1] = st.st_mtim; if (futimens(fdt, ut) < 0) return -errno; if (fd_getcrtime(fdf, &crtime) >= 0) (void) fd_setcrtime(fdt, crtime); return 0; } int copy_xattr(int fdf, int fdt) { _cleanup_free_ char *bufa = NULL, *bufb = NULL; size_t sza = 100, szb = 100; ssize_t n; int ret = 0; const char *p; for (;;) { bufa = malloc(sza); if (!bufa) return -ENOMEM; n = flistxattr(fdf, bufa, sza); if (n == 0) return 0; if (n > 0) break; if (errno != ERANGE) return -errno; sza *= 2; bufa = mfree(bufa); } p = bufa; while (n > 0) { size_t l; l = strlen(p); assert(l < (size_t) n); if (startswith(p, "user.")) { ssize_t m; if (!bufb) { bufb = malloc(szb); if (!bufb) return -ENOMEM; } m = fgetxattr(fdf, p, bufb, szb); if (m < 0) { if (errno == ERANGE) { szb *= 2; bufb = mfree(bufb); continue; } return -errno; } if (fsetxattr(fdt, p, bufb, m, 0) < 0) ret = -errno; } p += l + 1; n -= l + 1; } return ret; } systemd-229/src/basic/copy.h000066400000000000000000000026251265713322000160610ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include int copy_file_fd(const char *from, int to, bool try_reflink); int copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned chattr_flags); int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace, unsigned chattr_flags); int copy_tree(const char *from, const char *to, bool merge); int copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge); int copy_directory_fd(int dirfd, const char *to, bool merge); int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink); int copy_times(int fdf, int fdt); int copy_xattr(int fdf, int fdt); systemd-229/src/basic/cpu-set-util.c000066400000000000000000000070701265713322000174340ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010-2015 Lennart Poettering Copyright 2015 Filipe Brandenburger systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "cpu-set-util.h" #include "extract-word.h" #include "log.h" #include "macro.h" #include "parse-util.h" #include "string-util.h" cpu_set_t* cpu_set_malloc(unsigned *ncpus) { cpu_set_t *c; unsigned n = 1024; /* Allocates the cpuset in the right size */ for (;;) { c = CPU_ALLOC(n); if (!c) return NULL; if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0) { CPU_ZERO_S(CPU_ALLOC_SIZE(n), c); if (ncpus) *ncpus = n; return c; } CPU_FREE(c); if (errno != EINVAL) return NULL; n *= 2; } } int parse_cpu_set_and_warn( const char *rvalue, cpu_set_t **cpu_set, const char *unit, const char *filename, unsigned line, const char *lvalue) { const char *whole_rvalue = rvalue; _cleanup_cpu_free_ cpu_set_t *c = NULL; unsigned ncpus = 0; assert(lvalue); assert(rvalue); for (;;) { _cleanup_free_ char *word = NULL; unsigned cpu, cpu_lower, cpu_upper; int r; r = extract_first_word(&rvalue, &word, WHITESPACE ",", EXTRACT_QUOTES); if (r < 0) return log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue); if (r == 0) break; if (!c) { c = cpu_set_malloc(&ncpus); if (!c) return log_oom(); } r = parse_range(word, &cpu_lower, &cpu_upper); if (r < 0) return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", word); if (cpu_lower >= ncpus || cpu_upper >= ncpus) return log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU out of range '%s' ncpus is %u", word, ncpus); if (cpu_lower > cpu_upper) log_syntax(unit, LOG_WARNING, filename, line, 0, "Range '%s' is invalid, %u > %u", word, cpu_lower, cpu_upper); else for (cpu = cpu_lower; cpu <= cpu_upper; cpu++) CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c); } /* On success, sets *cpu_set and returns ncpus for the system. */ if (c) { *cpu_set = c; c = NULL; } return (int) ncpus; } systemd-229/src/basic/cpu-set-util.h000066400000000000000000000021211265713322000174310ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010-2015 Lennart Poettering Copyright 2015 Filipe Brandenburger systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" DEFINE_TRIVIAL_CLEANUP_FUNC(cpu_set_t*, CPU_FREE); #define _cleanup_cpu_free_ _cleanup_(CPU_FREEp) cpu_set_t* cpu_set_malloc(unsigned *ncpus); int parse_cpu_set_and_warn(const char *rvalue, cpu_set_t **cpu_set, const char *unit, const char *filename, unsigned line, const char *lvalue); systemd-229/src/basic/def.h000066400000000000000000000061601265713322000156430ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "util.h" #define DEFAULT_TIMEOUT_USEC (90*USEC_PER_SEC) #define DEFAULT_RESTART_USEC (100*USEC_PER_MSEC) #define DEFAULT_CONFIRM_USEC (30*USEC_PER_SEC) #define DEFAULT_START_LIMIT_INTERVAL (10*USEC_PER_SEC) #define DEFAULT_START_LIMIT_BURST 5 /* The default time after which exit-on-idle services exit. This * should be kept lower than the watchdog timeout, because otherwise * the watchdog pings will keep the loop busy. */ #define DEFAULT_EXIT_USEC (30*USEC_PER_SEC) /* The default value for the net.unix.max_dgram_qlen sysctl */ #define DEFAULT_UNIX_MAX_DGRAM_QLEN 512UL #define SYSTEMD_CGROUP_CONTROLLER "name=systemd" #define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT #define SIGNALS_IGNORE SIGPIPE #define REBOOT_PARAM_FILE "/run/systemd/reboot-param" #ifdef HAVE_SPLIT_USR #define KBD_KEYMAP_DIRS \ "/usr/share/keymaps/\0" \ "/usr/share/kbd/keymaps/\0" \ "/usr/lib/kbd/keymaps/\0" \ "/lib/kbd/keymaps/\0" #else #define KBD_KEYMAP_DIRS \ "/usr/share/keymaps/\0" \ "/usr/share/kbd/keymaps/\0" \ "/usr/lib/kbd/keymaps/\0" #endif #define UNIX_SYSTEM_BUS_ADDRESS "unix:path=/var/run/dbus/system_bus_socket" #define KERNEL_SYSTEM_BUS_ADDRESS "kernel:path=/sys/fs/kdbus/0-system/bus" #define DEFAULT_SYSTEM_BUS_ADDRESS KERNEL_SYSTEM_BUS_ADDRESS ";" UNIX_SYSTEM_BUS_ADDRESS #define UNIX_USER_BUS_ADDRESS_FMT "unix:path=%s/bus" #define KERNEL_USER_BUS_ADDRESS_FMT "kernel:path=/sys/fs/kdbus/"UID_FMT"-user/bus" #define PLYMOUTH_SOCKET { \ .un.sun_family = AF_UNIX, \ .un.sun_path = "\0/org/freedesktop/plymouthd", \ } #ifndef TTY_GID #define TTY_GID 5 #endif #define NOTIFY_FD_MAX 768 #define NOTIFY_BUFFER_MAX PIPE_BUF #ifdef HAVE_SPLIT_USR #define _CONF_PATHS_SPLIT_USR(n) "/lib/" n "\0" #else #define _CONF_PATHS_SPLIT_USR(n) #endif /* Return a nulstr for a standard cascade of configuration paths, * suitable to pass to conf_files_list_nulstr() or config_parse_many() * to implement drop-in directories for extending configuration * files. */ #define CONF_PATHS_NULSTR(n) \ "/etc/" n "\0" \ "/run/" n "\0" \ "/usr/local/lib/" n "\0" \ "/usr/lib/" n "\0" \ _CONF_PATHS_SPLIT_USR(n) systemd-229/src/basic/device-nodes.c000066400000000000000000000044551265713322000174520ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2011 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "device-nodes.h" #include "utf8.h" int whitelisted_char_for_devnode(char c, const char *white) { if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || strchr("#+-.:=@_", c) != NULL || (white != NULL && strchr(white, c) != NULL)) return 1; return 0; } int encode_devnode_name(const char *str, char *str_enc, size_t len) { size_t i, j; if (str == NULL || str_enc == NULL) return -EINVAL; for (i = 0, j = 0; str[i] != '\0'; i++) { int seqlen; seqlen = utf8_encoded_valid_unichar(&str[i]); if (seqlen > 1) { if (len-j < (size_t)seqlen) return -EINVAL; memcpy(&str_enc[j], &str[i], seqlen); j += seqlen; i += (seqlen-1); } else if (str[i] == '\\' || !whitelisted_char_for_devnode(str[i], NULL)) { if (len-j < 4) return -EINVAL; sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]); j += 4; } else { if (len-j < 1) return -EINVAL; str_enc[j] = str[i]; j++; } } if (len-j < 1) return -EINVAL; str_enc[j] = '\0'; return 0; } systemd-229/src/basic/device-nodes.h000066400000000000000000000016201265713322000174460ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include int encode_devnode_name(const char *str, char *str_enc, size_t len); int whitelisted_char_for_devnode(char c, const char *additional); systemd-229/src/basic/dirent-util.c000066400000000000000000000042721265713322000173420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010-2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "dirent-util.h" #include "path-util.h" #include "string-util.h" int dirent_ensure_type(DIR *d, struct dirent *de) { struct stat st; assert(d); assert(de); if (de->d_type != DT_UNKNOWN) return 0; if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) return -errno; de->d_type = S_ISREG(st.st_mode) ? DT_REG : S_ISDIR(st.st_mode) ? DT_DIR : S_ISLNK(st.st_mode) ? DT_LNK : S_ISFIFO(st.st_mode) ? DT_FIFO : S_ISSOCK(st.st_mode) ? DT_SOCK : S_ISCHR(st.st_mode) ? DT_CHR : S_ISBLK(st.st_mode) ? DT_BLK : DT_UNKNOWN; return 0; } bool dirent_is_file(const struct dirent *de) { assert(de); if (hidden_file(de->d_name)) return false; if (de->d_type != DT_REG && de->d_type != DT_LNK && de->d_type != DT_UNKNOWN) return false; return true; } bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) { assert(de); if (de->d_type != DT_REG && de->d_type != DT_LNK && de->d_type != DT_UNKNOWN) return false; if (hidden_file_allow_backup(de->d_name)) return false; return endswith(de->d_name, suffix); } systemd-229/src/basic/dirent-util.h000066400000000000000000000043211265713322000173420ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "macro.h" #include "path-util.h" int dirent_ensure_type(DIR *d, struct dirent *de); bool dirent_is_file(const struct dirent *de) _pure_; bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_; #define FOREACH_DIRENT(de, d, on_error) \ for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \ if (!de) { \ if (errno > 0) { \ on_error; \ } \ break; \ } else if (hidden_file((de)->d_name)) \ continue; \ else #define FOREACH_DIRENT_ALL(de, d, on_error) \ for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \ if (!de) { \ if (errno > 0) { \ on_error; \ } \ break; \ } else systemd-229/src/basic/env-util.c000066400000000000000000000366731265713322000166570ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "alloc-util.h" #include "env-util.h" #include "extract-word.h" #include "macro.h" #include "parse-util.h" #include "string-util.h" #include "strv.h" #include "utf8.h" #define VALID_CHARS_ENV_NAME \ DIGITS LETTERS \ "_" #ifndef ARG_MAX #define ARG_MAX ((size_t) sysconf(_SC_ARG_MAX)) #endif static bool env_name_is_valid_n(const char *e, size_t n) { const char *p; if (!e) return false; if (n <= 0) return false; if (e[0] >= '0' && e[0] <= '9') return false; /* POSIX says the overall size of the environment block cannot * be > ARG_MAX, an individual assignment hence cannot be * either. Discounting the equal sign and trailing NUL this * hence leaves ARG_MAX-2 as longest possible variable * name. */ if (n > ARG_MAX - 2) return false; for (p = e; p < e + n; p++) if (!strchr(VALID_CHARS_ENV_NAME, *p)) return false; return true; } bool env_name_is_valid(const char *e) { if (!e) return false; return env_name_is_valid_n(e, strlen(e)); } bool env_value_is_valid(const char *e) { if (!e) return false; if (!utf8_is_valid(e)) return false; /* bash allows tabs in environment variables, and so should * we */ if (string_has_cc(e, "\t")) return false; /* POSIX says the overall size of the environment block cannot * be > ARG_MAX, an individual assignment hence cannot be * either. Discounting the shortest possible variable name of * length 1, the equal sign and trailing NUL this hence leaves * ARG_MAX-3 as longest possible variable value. */ if (strlen(e) > ARG_MAX - 3) return false; return true; } bool env_assignment_is_valid(const char *e) { const char *eq; eq = strchr(e, '='); if (!eq) return false; if (!env_name_is_valid_n(e, eq - e)) return false; if (!env_value_is_valid(eq + 1)) return false; /* POSIX says the overall size of the environment block cannot * be > ARG_MAX, hence the individual variable assignments * cannot be either, but let's leave room for one trailing NUL * byte. */ if (strlen(e) > ARG_MAX - 1) return false; return true; } bool strv_env_is_valid(char **e) { char **p, **q; STRV_FOREACH(p, e) { size_t k; if (!env_assignment_is_valid(*p)) return false; /* Check if there are duplicate assginments */ k = strcspn(*p, "="); STRV_FOREACH(q, p + 1) if (strneq(*p, *q, k) && (*q)[k] == '=') return false; } return true; } bool strv_env_name_is_valid(char **l) { char **p, **q; STRV_FOREACH(p, l) { if (!env_name_is_valid(*p)) return false; STRV_FOREACH(q, p + 1) if (streq(*p, *q)) return false; } return true; } bool strv_env_name_or_assignment_is_valid(char **l) { char **p, **q; STRV_FOREACH(p, l) { if (!env_assignment_is_valid(*p) && !env_name_is_valid(*p)) return false; STRV_FOREACH(q, p + 1) if (streq(*p, *q)) return false; } return true; } static int env_append(char **r, char ***k, char **a) { assert(r); assert(k); if (!a) return 0; /* Add the entries of a to *k unless they already exist in *r * in which case they are overridden instead. This assumes * there is enough space in the r array. */ for (; *a; a++) { char **j; size_t n; n = strcspn(*a, "="); if ((*a)[n] == '=') n++; for (j = r; j < *k; j++) if (strneq(*j, *a, n)) break; if (j >= *k) (*k)++; else free(*j); *j = strdup(*a); if (!*j) return -ENOMEM; } return 0; } char **strv_env_merge(unsigned n_lists, ...) { size_t n = 0; char **l, **k, **r; va_list ap; unsigned i; /* Merges an arbitrary number of environment sets */ va_start(ap, n_lists); for (i = 0; i < n_lists; i++) { l = va_arg(ap, char**); n += strv_length(l); } va_end(ap); r = new(char*, n+1); if (!r) return NULL; k = r; va_start(ap, n_lists); for (i = 0; i < n_lists; i++) { l = va_arg(ap, char**); if (env_append(r, &k, l) < 0) goto fail; } va_end(ap); *k = NULL; return r; fail: va_end(ap); strv_free(r); return NULL; } _pure_ static bool env_match(const char *t, const char *pattern) { assert(t); assert(pattern); /* pattern a matches string a * a matches a= * a matches a=b * a= matches a= * a=b matches a=b * a= does not match a * a=b does not match a= * a=b does not match a * a=b does not match a=c */ if (streq(t, pattern)) return true; if (!strchr(pattern, '=')) { size_t l = strlen(pattern); return strneq(t, pattern, l) && t[l] == '='; } return false; } char **strv_env_delete(char **x, unsigned n_lists, ...) { size_t n, i = 0; char **k, **r; va_list ap; /* Deletes every entry from x that is mentioned in the other * string lists */ n = strv_length(x); r = new(char*, n+1); if (!r) return NULL; STRV_FOREACH(k, x) { unsigned v; va_start(ap, n_lists); for (v = 0; v < n_lists; v++) { char **l, **j; l = va_arg(ap, char**); STRV_FOREACH(j, l) if (env_match(*k, *j)) goto skip; } va_end(ap); r[i] = strdup(*k); if (!r[i]) { strv_free(r); return NULL; } i++; continue; skip: va_end(ap); } r[i] = NULL; assert(i <= n); return r; } char **strv_env_unset(char **l, const char *p) { char **f, **t; if (!l) return NULL; assert(p); /* Drops every occurrence of the env var setting p in the * string list. Edits in-place. */ for (f = t = l; *f; f++) { if (env_match(*f, p)) { free(*f); continue; } *(t++) = *f; } *t = NULL; return l; } char **strv_env_unset_many(char **l, ...) { char **f, **t; if (!l) return NULL; /* Like strv_env_unset() but applies many at once. Edits in-place. */ for (f = t = l; *f; f++) { bool found = false; const char *p; va_list ap; va_start(ap, l); while ((p = va_arg(ap, const char*))) { if (env_match(*f, p)) { found = true; break; } } va_end(ap); if (found) { free(*f); continue; } *(t++) = *f; } *t = NULL; return l; } char **strv_env_set(char **x, const char *p) { char **k, **r; char* m[2] = { (char*) p, NULL }; /* Overrides the env var setting of p, returns a new copy */ r = new(char*, strv_length(x)+2); if (!r) return NULL; k = r; if (env_append(r, &k, x) < 0) goto fail; if (env_append(r, &k, m) < 0) goto fail; *k = NULL; return r; fail: strv_free(r); return NULL; } char *strv_env_get_n(char **l, const char *name, size_t k) { char **i; assert(name); if (k <= 0) return NULL; STRV_FOREACH(i, l) if (strneq(*i, name, k) && (*i)[k] == '=') return *i + k + 1; return NULL; } char *strv_env_get(char **l, const char *name) { assert(name); return strv_env_get_n(l, name, strlen(name)); } char **strv_env_clean_with_callback(char **e, void (*invalid_callback)(const char *p, void *userdata), void *userdata) { char **p, **q; int k = 0; STRV_FOREACH(p, e) { size_t n; bool duplicate = false; if (!env_assignment_is_valid(*p)) { if (invalid_callback) invalid_callback(*p, userdata); free(*p); continue; } n = strcspn(*p, "="); STRV_FOREACH(q, p + 1) if (strneq(*p, *q, n) && (*q)[n] == '=') { duplicate = true; break; } if (duplicate) { free(*p); continue; } e[k++] = *p; } if (e) e[k] = NULL; return e; } char *replace_env(const char *format, char **env) { enum { WORD, CURLY, VARIABLE } state = WORD; const char *e, *word = format; char *r = NULL, *k; assert(format); for (e = format; *e; e ++) { switch (state) { case WORD: if (*e == '$') state = CURLY; break; case CURLY: if (*e == '{') { k = strnappend(r, word, e-word-1); if (!k) goto fail; free(r); r = k; word = e-1; state = VARIABLE; } else if (*e == '$') { k = strnappend(r, word, e-word); if (!k) goto fail; free(r); r = k; word = e+1; state = WORD; } else state = WORD; break; case VARIABLE: if (*e == '}') { const char *t; t = strempty(strv_env_get_n(env, word+2, e-word-2)); k = strappend(r, t); if (!k) goto fail; free(r); r = k; word = e+1; state = WORD; } break; } } k = strnappend(r, word, e-word); if (!k) goto fail; free(r); return k; fail: free(r); return NULL; } char **replace_env_argv(char **argv, char **env) { char **ret, **i; unsigned k = 0, l = 0; l = strv_length(argv); ret = new(char*, l+1); if (!ret) return NULL; STRV_FOREACH(i, argv) { /* If $FOO appears as single word, replace it by the split up variable */ if ((*i)[0] == '$' && (*i)[1] != '{' && (*i)[1] != '$') { char *e; char **w, **m = NULL; unsigned q; e = strv_env_get(env, *i+1); if (e) { int r; r = strv_split_extract(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_QUOTES); if (r < 0) { ret[k] = NULL; strv_free(ret); return NULL; } } else m = NULL; q = strv_length(m); l = l + q - 1; w = realloc(ret, sizeof(char*) * (l+1)); if (!w) { ret[k] = NULL; strv_free(ret); strv_free(m); return NULL; } ret = w; if (m) { memcpy(ret + k, m, q * sizeof(char*)); free(m); } k += q; continue; } /* If ${FOO} appears as part of a word, replace it by the variable as-is */ ret[k] = replace_env(*i, env); if (!ret[k]) { strv_free(ret); return NULL; } k++; } ret[k] = NULL; return ret; } int getenv_bool(const char *p) { const char *e; e = getenv(p); if (!e) return -ENXIO; return parse_boolean(e); } systemd-229/src/basic/env-util.h000066400000000000000000000034061265713322000166500ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "macro.h" bool env_name_is_valid(const char *e); bool env_value_is_valid(const char *e); bool env_assignment_is_valid(const char *e); char *replace_env(const char *format, char **env); char **replace_env_argv(char **argv, char **env); bool strv_env_is_valid(char **e); #define strv_env_clean(l) strv_env_clean_with_callback(l, NULL, NULL) char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const char *p, void *userdata), void *userdata); bool strv_env_name_is_valid(char **l); bool strv_env_name_or_assignment_is_valid(char **l); char **strv_env_merge(unsigned n_lists, ...); char **strv_env_delete(char **x, unsigned n_lists, ...); /* New copy */ char **strv_env_set(char **x, const char *p); /* New copy ... */ char **strv_env_unset(char **l, const char *p); /* In place ... */ char **strv_env_unset_many(char **l, ...) _sentinel_; char *strv_env_get_n(char **l, const char *name, size_t k) _pure_; char *strv_env_get(char **x, const char *n) _pure_; int getenv_bool(const char *p); systemd-229/src/basic/errno-list.c000066400000000000000000000027341265713322000172010ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "errno-list.h" #include "macro.h" static const struct errno_name* lookup_errno(register const char *str, register unsigned int len); #include "errno-from-name.h" #include "errno-to-name.h" const char *errno_to_name(int id) { if (id < 0) id = -id; if (id >= (int) ELEMENTSOF(errno_names)) return NULL; return errno_names[id]; } int errno_from_name(const char *name) { const struct errno_name *sc; assert(name); sc = lookup_errno(name, strlen(name)); if (!sc) return -EINVAL; assert(sc->id > 0); return sc->id; } int errno_max(void) { return ELEMENTSOF(errno_names); } systemd-229/src/basic/errno-list.h000066400000000000000000000014751265713322000172070ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ const char *errno_to_name(int id); int errno_from_name(const char *name); int errno_max(void); systemd-229/src/basic/escape.c000066400000000000000000000313251265713322000163410ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "escape.h" #include "hexdecoct.h" #include "macro.h" #include "utf8.h" size_t cescape_char(char c, char *buf) { char * buf_old = buf; switch (c) { case '\a': *(buf++) = '\\'; *(buf++) = 'a'; break; case '\b': *(buf++) = '\\'; *(buf++) = 'b'; break; case '\f': *(buf++) = '\\'; *(buf++) = 'f'; break; case '\n': *(buf++) = '\\'; *(buf++) = 'n'; break; case '\r': *(buf++) = '\\'; *(buf++) = 'r'; break; case '\t': *(buf++) = '\\'; *(buf++) = 't'; break; case '\v': *(buf++) = '\\'; *(buf++) = 'v'; break; case '\\': *(buf++) = '\\'; *(buf++) = '\\'; break; case '"': *(buf++) = '\\'; *(buf++) = '"'; break; case '\'': *(buf++) = '\\'; *(buf++) = '\''; break; default: /* For special chars we prefer octal over * hexadecimal encoding, simply because glib's * g_strescape() does the same */ if ((c < ' ') || (c >= 127)) { *(buf++) = '\\'; *(buf++) = octchar((unsigned char) c >> 6); *(buf++) = octchar((unsigned char) c >> 3); *(buf++) = octchar((unsigned char) c); } else *(buf++) = c; break; } return buf - buf_old; } char *cescape_length(const char *s, size_t n) { const char *f; char *r, *t; assert(s || n == 0); /* Does C style string escaping. May be reversed with * cunescape(). */ r = new(char, n*4 + 1); if (!r) return NULL; for (f = s, t = r; f < s + n; f++) t += cescape_char(*f, t); *t = 0; return r; } char *cescape(const char *s) { assert(s); return cescape_length(s, strlen(s)); } int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit) { int r = 1; assert(p); assert(*p); assert(ret); /* Unescapes C style. Returns the unescaped character in ret. * Sets *eight_bit to true if the escaped sequence either fits in * one byte in UTF-8 or is a non-unicode literal byte and should * instead be copied directly. */ if (length != (size_t) -1 && length < 1) return -EINVAL; switch (p[0]) { case 'a': *ret = '\a'; break; case 'b': *ret = '\b'; break; case 'f': *ret = '\f'; break; case 'n': *ret = '\n'; break; case 'r': *ret = '\r'; break; case 't': *ret = '\t'; break; case 'v': *ret = '\v'; break; case '\\': *ret = '\\'; break; case '"': *ret = '"'; break; case '\'': *ret = '\''; break; case 's': /* This is an extension of the XDG syntax files */ *ret = ' '; break; case 'x': { /* hexadecimal encoding */ int a, b; if (length != (size_t) -1 && length < 3) return -EINVAL; a = unhexchar(p[1]); if (a < 0) return -EINVAL; b = unhexchar(p[2]); if (b < 0) return -EINVAL; /* Don't allow NUL bytes */ if (a == 0 && b == 0) return -EINVAL; *ret = (a << 4U) | b; *eight_bit = true; r = 3; break; } case 'u': { /* C++11 style 16bit unicode */ int a[4]; unsigned i; uint32_t c; if (length != (size_t) -1 && length < 5) return -EINVAL; for (i = 0; i < 4; i++) { a[i] = unhexchar(p[1 + i]); if (a[i] < 0) return a[i]; } c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3]; /* Don't allow 0 chars */ if (c == 0) return -EINVAL; *ret = c; r = 5; break; } case 'U': { /* C++11 style 32bit unicode */ int a[8]; unsigned i; char32_t c; if (length != (size_t) -1 && length < 9) return -EINVAL; for (i = 0; i < 8; i++) { a[i] = unhexchar(p[1 + i]); if (a[i] < 0) return a[i]; } c = ((uint32_t) a[0] << 28U) | ((uint32_t) a[1] << 24U) | ((uint32_t) a[2] << 20U) | ((uint32_t) a[3] << 16U) | ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] << 8U) | ((uint32_t) a[6] << 4U) | (uint32_t) a[7]; /* Don't allow 0 chars */ if (c == 0) return -EINVAL; /* Don't allow invalid code points */ if (!unichar_is_valid(c)) return -EINVAL; *ret = c; r = 9; break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { /* octal encoding */ int a, b, c; char32_t m; if (length != (size_t) -1 && length < 3) return -EINVAL; a = unoctchar(p[0]); if (a < 0) return -EINVAL; b = unoctchar(p[1]); if (b < 0) return -EINVAL; c = unoctchar(p[2]); if (c < 0) return -EINVAL; /* don't allow NUL bytes */ if (a == 0 && b == 0 && c == 0) return -EINVAL; /* Don't allow bytes above 255 */ m = ((uint32_t) a << 6U) | ((uint32_t) b << 3U) | (uint32_t) c; if (m > 255) return -EINVAL; *ret = m; *eight_bit = true; r = 3; break; } default: return -EINVAL; } return r; } int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) { char *r, *t; const char *f; size_t pl; assert(s); assert(ret); /* Undoes C style string escaping, and optionally prefixes it. */ pl = prefix ? strlen(prefix) : 0; r = new(char, pl+length+1); if (!r) return -ENOMEM; if (prefix) memcpy(r, prefix, pl); for (f = s, t = r + pl; f < s + length; f++) { size_t remaining; bool eight_bit = false; char32_t u; int k; remaining = s + length - f; assert(remaining > 0); if (*f != '\\') { /* A literal literal, copy verbatim */ *(t++) = *f; continue; } if (remaining == 1) { if (flags & UNESCAPE_RELAX) { /* A trailing backslash, copy verbatim */ *(t++) = *f; continue; } free(r); return -EINVAL; } k = cunescape_one(f + 1, remaining - 1, &u, &eight_bit); if (k < 0) { if (flags & UNESCAPE_RELAX) { /* Invalid escape code, let's take it literal then */ *(t++) = '\\'; continue; } free(r); return k; } f += k; if (eight_bit) /* One byte? Set directly as specified */ *(t++) = u; else /* Otherwise encode as multi-byte UTF-8 */ t += utf8_encode_unichar(t, u); } *t = 0; *ret = r; return t - r; } int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret) { return cunescape_length_with_prefix(s, length, NULL, flags, ret); } int cunescape(const char *s, UnescapeFlags flags, char **ret) { return cunescape_length(s, strlen(s), flags, ret); } char *xescape(const char *s, const char *bad) { char *r, *t; const char *f; /* Escapes all chars in bad, in addition to \ and all special * chars, in \xFF style escaping. May be reversed with * cunescape(). */ r = new(char, strlen(s) * 4 + 1); if (!r) return NULL; for (f = s, t = r; *f; f++) { if ((*f < ' ') || (*f >= 127) || (*f == '\\') || strchr(bad, *f)) { *(t++) = '\\'; *(t++) = 'x'; *(t++) = hexchar(*f >> 4); *(t++) = hexchar(*f); } else *(t++) = *f; } *t = 0; return r; } static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) { assert(bad); for (; *s; s++) { if (*s == '\\' || strchr(bad, *s)) *(t++) = '\\'; *(t++) = *s; } return t; } char *shell_escape(const char *s, const char *bad) { char *r, *t; r = new(char, strlen(s)*2+1); if (!r) return NULL; t = strcpy_backslash_escaped(r, s, bad); *t = 0; return r; } char *shell_maybe_quote(const char *s) { const char *p; char *r, *t; assert(s); /* Encloses a string in double quotes if necessary to make it * OK as shell string. */ for (p = s; *p; p++) if (*p <= ' ' || *p >= 127 || strchr(SHELL_NEED_QUOTES, *p)) break; if (!*p) return strdup(s); r = new(char, 1+strlen(s)*2+1+1); if (!r) return NULL; t = r; *(t++) = '"'; t = mempcpy(t, s, p - s); t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE); *(t++)= '"'; *t = 0; return r; } systemd-229/src/basic/escape.h000066400000000000000000000034201265713322000163410ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "string-util.h" #include "missing.h" /* What characters are special in the shell? */ /* must be escaped outside and inside double-quotes */ #define SHELL_NEED_ESCAPE "\"\\`$" /* can be escaped or double-quoted */ #define SHELL_NEED_QUOTES SHELL_NEED_ESCAPE GLOB_CHARS "'()<>|&;" typedef enum UnescapeFlags { UNESCAPE_RELAX = 1, } UnescapeFlags; char *cescape(const char *s); char *cescape_length(const char *s, size_t n); size_t cescape_char(char c, char *buf); int cunescape(const char *s, UnescapeFlags flags, char **ret); int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret); int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret); int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit); char *xescape(const char *s, const char *bad); char *shell_escape(const char *s, const char *bad); char *shell_maybe_quote(const char *s); systemd-229/src/basic/ether-addr-util.c000066400000000000000000000027351265713322000200760ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "ether-addr-util.h" #include "macro.h" char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) { assert(addr); assert(buffer); /* Like ether_ntoa() but uses %02x instead of %x to print * ethernet addresses, which makes them look less funny. Also, * doesn't use a static buffer. */ sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", addr->ether_addr_octet[0], addr->ether_addr_octet[1], addr->ether_addr_octet[2], addr->ether_addr_octet[3], addr->ether_addr_octet[4], addr->ether_addr_octet[5]); return buffer; } systemd-229/src/basic/ether-addr-util.h000066400000000000000000000021551265713322000200770ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X" #define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5] #define ETHER_ADDR_TO_STRING_MAX (3*6) char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]); systemd-229/src/basic/exit-status.c000066400000000000000000000152701265713322000173740ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "exit-status.h" #include "macro.h" #include "set.h" const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) { /* We cast to int here, so that -Wenum doesn't complain that * EXIT_SUCCESS/EXIT_FAILURE aren't in the enum */ switch ((int) status) { case EXIT_SUCCESS: return "SUCCESS"; case EXIT_FAILURE: return "FAILURE"; } if (level == EXIT_STATUS_SYSTEMD || level == EXIT_STATUS_LSB) { switch ((int) status) { case EXIT_CHDIR: return "CHDIR"; case EXIT_NICE: return "NICE"; case EXIT_FDS: return "FDS"; case EXIT_EXEC: return "EXEC"; case EXIT_MEMORY: return "MEMORY"; case EXIT_LIMITS: return "LIMITS"; case EXIT_OOM_ADJUST: return "OOM_ADJUST"; case EXIT_SIGNAL_MASK: return "SIGNAL_MASK"; case EXIT_STDIN: return "STDIN"; case EXIT_STDOUT: return "STDOUT"; case EXIT_CHROOT: return "CHROOT"; case EXIT_IOPRIO: return "IOPRIO"; case EXIT_TIMERSLACK: return "TIMERSLACK"; case EXIT_SECUREBITS: return "SECUREBITS"; case EXIT_SETSCHEDULER: return "SETSCHEDULER"; case EXIT_CPUAFFINITY: return "CPUAFFINITY"; case EXIT_GROUP: return "GROUP"; case EXIT_USER: return "USER"; case EXIT_CAPABILITIES: return "CAPABILITIES"; case EXIT_CGROUP: return "CGROUP"; case EXIT_SETSID: return "SETSID"; case EXIT_CONFIRM: return "CONFIRM"; case EXIT_STDERR: return "STDERR"; case EXIT_PAM: return "PAM"; case EXIT_NETWORK: return "NETWORK"; case EXIT_NAMESPACE: return "NAMESPACE"; case EXIT_NO_NEW_PRIVILEGES: return "NO_NEW_PRIVILEGES"; case EXIT_SECCOMP: return "SECCOMP"; case EXIT_SELINUX_CONTEXT: return "SELINUX_CONTEXT"; case EXIT_PERSONALITY: return "PERSONALITY"; case EXIT_APPARMOR_PROFILE: return "APPARMOR"; case EXIT_ADDRESS_FAMILIES: return "ADDRESS_FAMILIES"; case EXIT_RUNTIME_DIRECTORY: return "RUNTIME_DIRECTORY"; case EXIT_CHOWN: return "CHOWN"; case EXIT_MAKE_STARTER: return "MAKE_STARTER"; case EXIT_BUS_ENDPOINT: return "BUS_ENDPOINT"; case EXIT_SMACK_PROCESS_LABEL: return "SMACK_PROCESS_LABEL"; } } if (level == EXIT_STATUS_LSB) { switch ((int) status) { case EXIT_INVALIDARGUMENT: return "INVALIDARGUMENT"; case EXIT_NOTIMPLEMENTED: return "NOTIMPLEMENTED"; case EXIT_NOPERMISSION: return "NOPERMISSION"; case EXIT_NOTINSTALLED: return "NOTINSTALLED"; case EXIT_NOTCONFIGURED: return "NOTCONFIGURED"; case EXIT_NOTRUNNING: return "NOTRUNNING"; } } return NULL; } bool is_clean_exit(int code, int status, ExitStatusSet *success_status) { if (code == CLD_EXITED) return status == 0 || (success_status && set_contains(success_status->status, INT_TO_PTR(status))); /* If a daemon does not implement handlers for some of the * signals that's not considered an unclean shutdown */ if (code == CLD_KILLED) return status == SIGHUP || status == SIGINT || status == SIGTERM || status == SIGPIPE || (success_status && set_contains(success_status->signal, INT_TO_PTR(status))); return false; } bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status) { if (is_clean_exit(code, status, success_status)) return true; return code == CLD_EXITED && (status == EXIT_NOTINSTALLED || status == EXIT_NOTCONFIGURED); } void exit_status_set_free(ExitStatusSet *x) { assert(x); set_free(x->status); set_free(x->signal); x->status = x->signal = NULL; } bool exit_status_set_is_empty(ExitStatusSet *x) { if (!x) return true; return set_isempty(x->status) && set_isempty(x->signal); } bool exit_status_set_test(ExitStatusSet *x, int code, int status) { if (exit_status_set_is_empty(x)) return false; if (code == CLD_EXITED && set_contains(x->status, INT_TO_PTR(status))) return true; if (IN_SET(code, CLD_KILLED, CLD_DUMPED) && set_contains(x->signal, INT_TO_PTR(status))) return true; return false; } systemd-229/src/basic/exit-status.h000066400000000000000000000060061265713322000173760ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "hashmap.h" #include "macro.h" #include "set.h" typedef enum ExitStatus { /* EXIT_SUCCESS defined by libc */ /* EXIT_FAILURE defined by libc */ EXIT_INVALIDARGUMENT = 2, EXIT_NOTIMPLEMENTED = 3, EXIT_NOPERMISSION = 4, EXIT_NOTINSTALLED = 5, EXIT_NOTCONFIGURED = 6, EXIT_NOTRUNNING = 7, /* The LSB suggests that error codes >= 200 are "reserved". We * use them here under the assumption that they hence are * unused by init scripts. * * http://refspecs.linuxfoundation.org/LSB_3.2.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html */ EXIT_CHDIR = 200, EXIT_NICE, EXIT_FDS, EXIT_EXEC, EXIT_MEMORY, EXIT_LIMITS, EXIT_OOM_ADJUST, EXIT_SIGNAL_MASK, EXIT_STDIN, EXIT_STDOUT, EXIT_CHROOT, /* 210 */ EXIT_IOPRIO, EXIT_TIMERSLACK, EXIT_SECUREBITS, EXIT_SETSCHEDULER, EXIT_CPUAFFINITY, EXIT_GROUP, EXIT_USER, EXIT_CAPABILITIES, EXIT_CGROUP, EXIT_SETSID, /* 220 */ EXIT_CONFIRM, EXIT_STDERR, _EXIT_RESERVED, /* used to be tcpwrap, don't reuse! */ EXIT_PAM, EXIT_NETWORK, EXIT_NAMESPACE, EXIT_NO_NEW_PRIVILEGES, EXIT_SECCOMP, EXIT_SELINUX_CONTEXT, EXIT_PERSONALITY, /* 230 */ EXIT_APPARMOR_PROFILE, EXIT_ADDRESS_FAMILIES, EXIT_RUNTIME_DIRECTORY, EXIT_MAKE_STARTER, EXIT_CHOWN, EXIT_BUS_ENDPOINT, EXIT_SMACK_PROCESS_LABEL, } ExitStatus; typedef enum ExitStatusLevel { EXIT_STATUS_MINIMAL, EXIT_STATUS_SYSTEMD, EXIT_STATUS_LSB, EXIT_STATUS_FULL = EXIT_STATUS_LSB } ExitStatusLevel; typedef struct ExitStatusSet { Set *status; Set *signal; } ExitStatusSet; const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) _const_; bool is_clean_exit(int code, int status, ExitStatusSet *success_status); bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status); void exit_status_set_free(ExitStatusSet *x); bool exit_status_set_is_empty(ExitStatusSet *x); bool exit_status_set_test(ExitStatusSet *x, int code, int status); systemd-229/src/basic/extract-word.c000066400000000000000000000260541265713322000175270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "escape.h" #include "extract-word.h" #include "log.h" #include "macro.h" #include "string-util.h" #include "utf8.h" int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) { _cleanup_free_ char *s = NULL; size_t allocated = 0, sz = 0; char c; int r; char quote = 0; /* 0 or ' or " */ bool backslash = false; /* whether we've just seen a backslash */ assert(p); assert(ret); /* Bail early if called after last value or with no input */ if (!*p) goto finish_force_terminate; c = **p; if (!separators) separators = WHITESPACE; /* Parses the first word of a string, and returns it in * *ret. Removes all quotes in the process. When parsing fails * (because of an uneven number of quotes or similar), leaves * the pointer *p at the first invalid character. */ if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) if (!GREEDY_REALLOC(s, allocated, sz+1)) return -ENOMEM; for (;; (*p) ++, c = **p) { if (c == 0) goto finish_force_terminate; else if (strchr(separators, c)) { if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) { (*p) ++; goto finish_force_next; } } else { /* We found a non-blank character, so we will always * want to return a string (even if it is empty), * allocate it here. */ if (!GREEDY_REALLOC(s, allocated, sz+1)) return -ENOMEM; break; } } for (;; (*p) ++, c = **p) { if (backslash) { if (!GREEDY_REALLOC(s, allocated, sz+7)) return -ENOMEM; if (c == 0) { if ((flags & EXTRACT_CUNESCAPE_RELAX) && (!quote || flags & EXTRACT_RELAX)) { /* If we find an unquoted trailing backslash and we're in * EXTRACT_CUNESCAPE_RELAX mode, keep it verbatim in the * output. * * Unbalanced quotes will only be allowed in EXTRACT_RELAX * mode, EXTRACT_CUNESCAPE_RELAX mode does not allow them. */ s[sz++] = '\\'; goto finish_force_terminate; } if (flags & EXTRACT_RELAX) goto finish_force_terminate; return -EINVAL; } if (flags & EXTRACT_CUNESCAPE) { bool eight_bit = false; char32_t u; r = cunescape_one(*p, (size_t) -1, &u, &eight_bit); if (r < 0) { if (flags & EXTRACT_CUNESCAPE_RELAX) { s[sz++] = '\\'; s[sz++] = c; } else return -EINVAL; } else { (*p) += r - 1; if (eight_bit) s[sz++] = u; else sz += utf8_encode_unichar(s + sz, u); } } else s[sz++] = c; backslash = false; } else if (quote) { /* inside either single or double quotes */ for (;; (*p) ++, c = **p) { if (c == 0) { if (flags & EXTRACT_RELAX) goto finish_force_terminate; return -EINVAL; } else if (c == quote) { /* found the end quote */ quote = 0; break; } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) { backslash = true; break; } else { if (!GREEDY_REALLOC(s, allocated, sz+2)) return -ENOMEM; s[sz++] = c; } } } else { for (;; (*p) ++, c = **p) { if (c == 0) goto finish_force_terminate; else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) { quote = c; break; } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) { backslash = true; break; } else if (strchr(separators, c)) { if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) { (*p) ++; goto finish_force_next; } /* Skip additional coalesced separators. */ for (;; (*p) ++, c = **p) { if (c == 0) goto finish_force_terminate; if (!strchr(separators, c)) break; } goto finish; } else { if (!GREEDY_REALLOC(s, allocated, sz+2)) return -ENOMEM; s[sz++] = c; } } } } finish_force_terminate: *p = NULL; finish: if (!s) { *p = NULL; *ret = NULL; return 0; } finish_force_next: s[sz] = 0; *ret = s; s = NULL; return 1; } int extract_first_word_and_warn( const char **p, char **ret, const char *separators, ExtractFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue) { /* Try to unquote it, if it fails, warn about it and try again * but this time using EXTRACT_CUNESCAPE_RELAX to keep the * backslashes verbatim in invalid escape sequences. */ const char *save; int r; save = *p; r = extract_first_word(p, ret, separators, flags); if (r >= 0) return r; if (r == -EINVAL && !(flags & EXTRACT_CUNESCAPE_RELAX)) { /* Retry it with EXTRACT_CUNESCAPE_RELAX. */ *p = save; r = extract_first_word(p, ret, separators, flags|EXTRACT_CUNESCAPE_RELAX); if (r >= 0) { /* It worked this time, hence it must have been an invalid escape sequence we could correct. */ log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Invalid escape sequences in line, correcting: \"%s\"", rvalue); return r; } /* If it's still EINVAL; then it must be unbalanced quoting, report this. */ if (r == -EINVAL) return log_syntax(unit, LOG_ERR, filename, line, r, "Unbalanced quoting, ignoring: \"%s\"", rvalue); } /* Can be any error, report it */ return log_syntax(unit, LOG_ERR, filename, line, r, "Unable to decode word \"%s\", ignoring: %m", rvalue); } int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) { va_list ap; char **l; int n = 0, i, c, r; /* Parses a number of words from a string, stripping any * quotes if necessary. */ assert(p); /* Count how many words are expected */ va_start(ap, flags); for (;;) { if (!va_arg(ap, char **)) break; n++; } va_end(ap); if (n <= 0) return 0; /* Read all words into a temporary array */ l = newa0(char*, n); for (c = 0; c < n; c++) { r = extract_first_word(p, &l[c], separators, flags); if (r < 0) { int j; for (j = 0; j < c; j++) free(l[j]); return r; } if (r == 0) break; } /* If we managed to parse all words, return them in the passed * in parameters */ va_start(ap, flags); for (i = 0; i < n; i++) { char **v; v = va_arg(ap, char **); assert(v); *v = l[i]; } va_end(ap); return c; } systemd-229/src/basic/extract-word.h000066400000000000000000000026541265713322000175340ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "macro.h" typedef enum ExtractFlags { EXTRACT_RELAX = 1, EXTRACT_CUNESCAPE = 2, EXTRACT_CUNESCAPE_RELAX = 4, EXTRACT_QUOTES = 8, EXTRACT_DONT_COALESCE_SEPARATORS = 16, EXTRACT_RETAIN_ESCAPE = 32, } ExtractFlags; int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags); int extract_first_word_and_warn(const char **p, char **ret, const char *separators, ExtractFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue); int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) _sentinel_; systemd-229/src/basic/fd-util.c000066400000000000000000000226631265713322000164520ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "fd-util.h" #include "macro.h" #include "missing.h" #include "parse-util.h" #include "path-util.h" #include "socket-util.h" #include "util.h" int close_nointr(int fd) { assert(fd >= 0); if (close(fd) >= 0) return 0; /* * Just ignore EINTR; a retry loop is the wrong thing to do on * Linux. * * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html * https://bugzilla.gnome.org/show_bug.cgi?id=682819 * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain */ if (errno == EINTR) return 0; return -errno; } int safe_close(int fd) { /* * Like close_nointr() but cannot fail. Guarantees errno is * unchanged. Is a NOP with negative fds passed, and returns * -1, so that it can be used in this syntax: * * fd = safe_close(fd); */ if (fd >= 0) { PROTECT_ERRNO; /* The kernel might return pretty much any error code * via close(), but the fd will be closed anyway. The * only condition we want to check for here is whether * the fd was invalid at all... */ assert_se(close_nointr(fd) != -EBADF); } return -1; } void safe_close_pair(int p[]) { assert(p); if (p[0] == p[1]) { /* Special case pairs which use the same fd in both * directions... */ p[0] = p[1] = safe_close(p[0]); return; } p[0] = safe_close(p[0]); p[1] = safe_close(p[1]); } void close_many(const int fds[], unsigned n_fd) { unsigned i; assert(fds || n_fd <= 0); for (i = 0; i < n_fd; i++) safe_close(fds[i]); } int fclose_nointr(FILE *f) { assert(f); /* Same as close_nointr(), but for fclose() */ if (fclose(f) == 0) return 0; if (errno == EINTR) return 0; return -errno; } FILE* safe_fclose(FILE *f) { /* Same as safe_close(), but for fclose() */ if (f) { PROTECT_ERRNO; assert_se(fclose_nointr(f) != EBADF); } return NULL; } DIR* safe_closedir(DIR *d) { if (d) { PROTECT_ERRNO; assert_se(closedir(d) >= 0 || errno != EBADF); } return NULL; } int fd_nonblock(int fd, bool nonblock) { int flags, nflags; assert(fd >= 0); flags = fcntl(fd, F_GETFL, 0); if (flags < 0) return -errno; if (nonblock) nflags = flags | O_NONBLOCK; else nflags = flags & ~O_NONBLOCK; if (nflags == flags) return 0; if (fcntl(fd, F_SETFL, nflags) < 0) return -errno; return 0; } int fd_cloexec(int fd, bool cloexec) { int flags, nflags; assert(fd >= 0); flags = fcntl(fd, F_GETFD, 0); if (flags < 0) return -errno; if (cloexec) nflags = flags | FD_CLOEXEC; else nflags = flags & ~FD_CLOEXEC; if (nflags == flags) return 0; if (fcntl(fd, F_SETFD, nflags) < 0) return -errno; return 0; } _pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) { unsigned i; assert(n_fdset == 0 || fdset); for (i = 0; i < n_fdset; i++) if (fdset[i] == fd) return true; return false; } int close_all_fds(const int except[], unsigned n_except) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0; assert(n_except == 0 || except); d = opendir("/proc/self/fd"); if (!d) { int fd; struct rlimit rl; /* When /proc isn't available (for example in chroots) * the fallback is brute forcing through the fd * table */ assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0); for (fd = 3; fd < (int) rl.rlim_max; fd ++) { if (fd_in_set(fd, except, n_except)) continue; if (close_nointr(fd) < 0) if (errno != EBADF && r == 0) r = -errno; } return r; } while ((de = readdir(d))) { int fd = -1; if (hidden_file(de->d_name)) continue; if (safe_atoi(de->d_name, &fd) < 0) /* Let's better ignore this, just in case */ continue; if (fd < 3) continue; if (fd == dirfd(d)) continue; if (fd_in_set(fd, except, n_except)) continue; if (close_nointr(fd) < 0) { /* Valgrind has its own FD and doesn't want to have it closed */ if (errno != EBADF && r == 0) r = -errno; } } return r; } int same_fd(int a, int b) { struct stat sta, stb; pid_t pid; int r, fa, fb; assert(a >= 0); assert(b >= 0); /* Compares two file descriptors. Note that semantics are * quite different depending on whether we have kcmp() or we * don't. If we have kcmp() this will only return true for * dup()ed file descriptors, but not otherwise. If we don't * have kcmp() this will also return true for two fds of the same * file, created by separate open() calls. Since we use this * call mostly for filtering out duplicates in the fd store * this difference hopefully doesn't matter too much. */ if (a == b) return true; /* Try to use kcmp() if we have it. */ pid = getpid(); r = kcmp(pid, pid, KCMP_FILE, a, b); if (r == 0) return true; if (r > 0) return false; if (errno != ENOSYS) return -errno; /* We don't have kcmp(), use fstat() instead. */ if (fstat(a, &sta) < 0) return -errno; if (fstat(b, &stb) < 0) return -errno; if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT)) return false; /* We consider all device fds different, since two device fds * might refer to quite different device contexts even though * they share the same inode and backing dev_t. */ if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode)) return false; if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino) return false; /* The fds refer to the same inode on disk, let's also check * if they have the same fd flags. This is useful to * distinguish the read and write side of a pipe created with * pipe(). */ fa = fcntl(a, F_GETFL); if (fa < 0) return -errno; fb = fcntl(b, F_GETFL); if (fb < 0) return -errno; return fa == fb; } void cmsg_close_all(struct msghdr *mh) { struct cmsghdr *cmsg; assert(mh); CMSG_FOREACH(cmsg, mh) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int)); } bool fdname_is_valid(const char *s) { const char *p; /* Validates a name for $LISTEN_FDNAMES. We basically allow * everything ASCII that's not a control character. Also, as * special exception the ":" character is not allowed, as we * use that as field separator in $LISTEN_FDNAMES. * * Note that the empty string is explicitly allowed * here. However, we limit the length of the names to 255 * characters. */ if (!s) return false; for (p = s; *p; p++) { if (*p < ' ') return false; if (*p >= 127) return false; if (*p == ':') return false; } return p - s < 256; } systemd-229/src/basic/fd-util.h000066400000000000000000000042131265713322000164460ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "macro.h" /* Make sure we can distinguish fd 0 and NULL */ #define FD_TO_PTR(fd) INT_TO_PTR((fd)+1) #define PTR_TO_FD(p) (PTR_TO_INT(p)-1) int close_nointr(int fd); int safe_close(int fd); void safe_close_pair(int p[]); void close_many(const int fds[], unsigned n_fd); int fclose_nointr(FILE *f); FILE* safe_fclose(FILE *f); DIR* safe_closedir(DIR *f); static inline void closep(int *fd) { safe_close(*fd); } static inline void close_pairp(int (*p)[2]) { safe_close_pair(*p); } static inline void fclosep(FILE **f) { safe_fclose(*f); } DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose); DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir); #define _cleanup_close_ _cleanup_(closep) #define _cleanup_fclose_ _cleanup_(fclosep) #define _cleanup_pclose_ _cleanup_(pclosep) #define _cleanup_closedir_ _cleanup_(closedirp) #define _cleanup_close_pair_ _cleanup_(close_pairp) int fd_nonblock(int fd, bool nonblock); int fd_cloexec(int fd, bool cloexec); int close_all_fds(const int except[], unsigned n_except); int same_fd(int a, int b); void cmsg_close_all(struct msghdr *mh); bool fdname_is_valid(const char *s); /* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */ #define ERRNO_IS_DISCONNECT(r) \ IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH) systemd-229/src/basic/fdset.c000066400000000000000000000143041265713322000162040ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-daemon.h" #include "fd-util.h" #include "fdset.h" #include "log.h" #include "macro.h" #include "parse-util.h" #include "path-util.h" #include "set.h" #define MAKE_SET(s) ((Set*) s) #define MAKE_FDSET(s) ((FDSet*) s) FDSet *fdset_new(void) { return MAKE_FDSET(set_new(NULL)); } int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds) { unsigned i; FDSet *s; int r; assert(ret); s = fdset_new(); if (!s) return -ENOMEM; for (i = 0; i < n_fds; i++) { r = fdset_put(s, fds[i]); if (r < 0) { set_free(MAKE_SET(s)); return r; } } *ret = s; return 0; } FDSet* fdset_free(FDSet *s) { void *p; while ((p = set_steal_first(MAKE_SET(s)))) { /* Valgrind's fd might have ended up in this set here, * due to fdset_new_fill(). We'll ignore all failures * here, so that the EBADFD that valgrind will return * us on close() doesn't influence us */ /* When reloading duplicates of the private bus * connection fds and suchlike are closed here, which * has no effect at all, since they are only * duplicates. So don't be surprised about these log * messages. */ log_debug("Closing left-over fd %i", PTR_TO_FD(p)); close_nointr(PTR_TO_FD(p)); } set_free(MAKE_SET(s)); return NULL; } int fdset_put(FDSet *s, int fd) { assert(s); assert(fd >= 0); return set_put(MAKE_SET(s), FD_TO_PTR(fd)); } int fdset_consume(FDSet *s, int fd) { int r; assert(s); assert(fd >= 0); r = fdset_put(s, fd); if (r <= 0) safe_close(fd); return r; } int fdset_put_dup(FDSet *s, int fd) { int copy, r; assert(s); assert(fd >= 0); copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (copy < 0) return -errno; r = fdset_put(s, copy); if (r < 0) { safe_close(copy); return r; } return copy; } bool fdset_contains(FDSet *s, int fd) { assert(s); assert(fd >= 0); return !!set_get(MAKE_SET(s), FD_TO_PTR(fd)); } int fdset_remove(FDSet *s, int fd) { assert(s); assert(fd >= 0); return set_remove(MAKE_SET(s), FD_TO_PTR(fd)) ? fd : -ENOENT; } int fdset_new_fill(FDSet **_s) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0; FDSet *s; assert(_s); /* Creates an fdset and fills in all currently open file * descriptors. */ d = opendir("/proc/self/fd"); if (!d) return -errno; s = fdset_new(); if (!s) { r = -ENOMEM; goto finish; } while ((de = readdir(d))) { int fd = -1; if (hidden_file(de->d_name)) continue; r = safe_atoi(de->d_name, &fd); if (r < 0) goto finish; if (fd < 3) continue; if (fd == dirfd(d)) continue; r = fdset_put(s, fd); if (r < 0) goto finish; } r = 0; *_s = s; s = NULL; finish: /* We won't close the fds here! */ if (s) set_free(MAKE_SET(s)); return r; } int fdset_cloexec(FDSet *fds, bool b) { Iterator i; void *p; int r; assert(fds); SET_FOREACH(p, MAKE_SET(fds), i) { r = fd_cloexec(PTR_TO_FD(p), b); if (r < 0) return r; } return 0; } int fdset_new_listen_fds(FDSet **_s, bool unset) { int n, fd, r; FDSet *s; assert(_s); /* Creates an fdset and fills in all passed file descriptors */ s = fdset_new(); if (!s) { r = -ENOMEM; goto fail; } n = sd_listen_fds(unset); for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) { r = fdset_put(s, fd); if (r < 0) goto fail; } *_s = s; return 0; fail: if (s) set_free(MAKE_SET(s)); return r; } int fdset_close_others(FDSet *fds) { void *e; Iterator i; int *a; unsigned j, m; j = 0, m = fdset_size(fds); a = alloca(sizeof(int) * m); SET_FOREACH(e, MAKE_SET(fds), i) a[j++] = PTR_TO_FD(e); assert(j == m); return close_all_fds(a, j); } unsigned fdset_size(FDSet *fds) { return set_size(MAKE_SET(fds)); } bool fdset_isempty(FDSet *fds) { return set_isempty(MAKE_SET(fds)); } int fdset_iterate(FDSet *s, Iterator *i) { void *p; if (!set_iterate(MAKE_SET(s), i, &p)) return -ENOENT; return PTR_TO_FD(p); } int fdset_steal_first(FDSet *fds) { void *p; p = set_steal_first(MAKE_SET(fds)); if (!p) return -ENOENT; return PTR_TO_FD(p); } systemd-229/src/basic/fdset.h000066400000000000000000000032531265713322000162120ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "hashmap.h" #include "macro.h" #include "set.h" typedef struct FDSet FDSet; FDSet* fdset_new(void); FDSet* fdset_free(FDSet *s); int fdset_put(FDSet *s, int fd); int fdset_put_dup(FDSet *s, int fd); int fdset_consume(FDSet *s, int fd); bool fdset_contains(FDSet *s, int fd); int fdset_remove(FDSet *s, int fd); int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds); int fdset_new_fill(FDSet **ret); int fdset_new_listen_fds(FDSet **ret, bool unset); int fdset_cloexec(FDSet *fds, bool b); int fdset_close_others(FDSet *fds); unsigned fdset_size(FDSet *fds); bool fdset_isempty(FDSet *fds); int fdset_iterate(FDSet *s, Iterator *i); int fdset_steal_first(FDSet *fds); #define FDSET_FOREACH(fd, fds, i) \ for ((i) = ITERATOR_FIRST, (fd) = fdset_iterate((fds), &(i)); (fd) >= 0; (fd) = fdset_iterate((fds), &(i))) DEFINE_TRIVIAL_CLEANUP_FUNC(FDSet*, fdset_free); #define _cleanup_fdset_free_ _cleanup_(fdset_freep) systemd-229/src/basic/fileio-label.c000066400000000000000000000034451265713322000174270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2010 Harald Hoyer systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "fileio-label.h" #include "fileio.h" #include "selinux-util.h" int write_string_file_atomic_label(const char *fn, const char *line) { int r; r = mac_selinux_create_file_prepare(fn, S_IFREG); if (r < 0) return r; r = write_string_file(fn, line, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC); mac_selinux_create_file_clear(); return r; } int write_env_file_label(const char *fname, char **l) { int r; r = mac_selinux_create_file_prepare(fname, S_IFREG); if (r < 0) return r; r = write_env_file(fname, l); mac_selinux_create_file_clear(); return r; } int fopen_temporary_label(const char *target, const char *path, FILE **f, char **temp_path) { int r; r = mac_selinux_create_file_prepare(target, S_IFREG); if (r < 0) return r; r = fopen_temporary(path, f, temp_path); mac_selinux_create_file_clear(); return r; } systemd-229/src/basic/fileio-label.h000066400000000000000000000020301265713322000174210ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2010 Harald Hoyer systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "fileio.h" int write_string_file_atomic_label(const char *fn, const char *line); int write_env_file_label(const char *fname, char **l); int fopen_temporary_label(const char *target, const char *path, FILE **f, char **temp_path); systemd-229/src/basic/fileio.c000066400000000000000000001045711265713322000163540ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "ctype.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "hexdecoct.h" #include "log.h" #include "macro.h" #include "parse-util.h" #include "path-util.h" #include "random-util.h" #include "stdio-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" #include "umask-util.h" #include "utf8.h" int write_string_stream(FILE *f, const char *line, bool enforce_newline) { assert(f); assert(line); fputs(line, f); if (enforce_newline && !endswith(line, "\n")) fputc('\n', f); return fflush_and_check(f); } static int write_string_file_atomic(const char *fn, const char *line, bool enforce_newline) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; int r; assert(fn); assert(line); r = fopen_temporary(fn, &f, &p); if (r < 0) return r; (void) fchmod_umask(fileno(f), 0644); r = write_string_stream(f, line, enforce_newline); if (r >= 0) { if (rename(p, fn) < 0) r = -errno; } if (r < 0) (void) unlink(p); return r; } int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) { _cleanup_fclose_ FILE *f = NULL; int q, r; assert(fn); assert(line); if (flags & WRITE_STRING_FILE_ATOMIC) { assert(flags & WRITE_STRING_FILE_CREATE); r = write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE)); if (r < 0) goto fail; return r; } if (flags & WRITE_STRING_FILE_CREATE) { f = fopen(fn, "we"); if (!f) { r = -errno; goto fail; } } else { int fd; /* We manually build our own version of fopen(..., "we") that * works without O_CREAT */ fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) { r = -errno; goto fail; } f = fdopen(fd, "we"); if (!f) { r = -errno; safe_close(fd); goto fail; } } r = write_string_stream(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE)); if (r < 0) goto fail; return 0; fail: if (!(flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE)) return r; f = safe_fclose(f); /* OK, the operation failed, but let's see if the right * contents in place already. If so, eat up the error. */ q = verify_file(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE)); if (q <= 0) return r; return 0; } int read_one_line_file(const char *fn, char **line) { _cleanup_fclose_ FILE *f = NULL; char t[LINE_MAX], *c; assert(fn); assert(line); f = fopen(fn, "re"); if (!f) return -errno; if (!fgets(t, sizeof(t), f)) { if (ferror(f)) return errno > 0 ? -errno : -EIO; t[0] = 0; } c = strdup(t); if (!c) return -ENOMEM; truncate_nl(c); *line = c; return 0; } int verify_file(const char *fn, const char *blob, bool accept_extra_nl) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *buf = NULL; size_t l, k; assert(fn); assert(blob); l = strlen(blob); if (accept_extra_nl && endswith(blob, "\n")) accept_extra_nl = false; buf = malloc(l + accept_extra_nl + 1); if (!buf) return -ENOMEM; f = fopen(fn, "re"); if (!f) return -errno; /* We try to read one byte more than we need, so that we know whether we hit eof */ errno = 0; k = fread(buf, 1, l + accept_extra_nl + 1, f); if (ferror(f)) return errno > 0 ? -errno : -EIO; if (k != l && k != l + accept_extra_nl) return 0; if (memcmp(buf, blob, l) != 0) return 0; if (k > l && buf[l] != '\n') return 0; return 1; } int read_full_stream(FILE *f, char **contents, size_t *size) { size_t n, l; _cleanup_free_ char *buf = NULL; struct stat st; assert(f); assert(contents); if (fstat(fileno(f), &st) < 0) return -errno; n = LINE_MAX; if (S_ISREG(st.st_mode)) { /* Safety check */ if (st.st_size > 4*1024*1024) return -E2BIG; /* Start with the right file size, but be prepared for * files from /proc which generally report a file size * of 0 */ if (st.st_size > 0) n = st.st_size; } l = 0; for (;;) { char *t; size_t k; t = realloc(buf, n+1); if (!t) return -ENOMEM; buf = t; k = fread(buf + l, 1, n - l, f); if (k <= 0) { if (ferror(f)) return -errno; break; } l += k; n *= 2; /* Safety check */ if (n > 4*1024*1024) return -E2BIG; } buf[l] = 0; *contents = buf; buf = NULL; /* do not free */ if (size) *size = l; return 0; } int read_full_file(const char *fn, char **contents, size_t *size) { _cleanup_fclose_ FILE *f = NULL; assert(fn); assert(contents); f = fopen(fn, "re"); if (!f) return -errno; return read_full_stream(f, contents, size); } static int parse_env_file_internal( FILE *f, const char *fname, const char *newline, int (*push) (const char *filename, unsigned line, const char *key, char *value, void *userdata, int *n_pushed), void *userdata, int *n_pushed) { _cleanup_free_ char *contents = NULL, *key = NULL; size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1; char *p, *value = NULL; int r; unsigned line = 1; enum { PRE_KEY, KEY, PRE_VALUE, VALUE, VALUE_ESCAPE, SINGLE_QUOTE_VALUE, SINGLE_QUOTE_VALUE_ESCAPE, DOUBLE_QUOTE_VALUE, DOUBLE_QUOTE_VALUE_ESCAPE, COMMENT, COMMENT_ESCAPE } state = PRE_KEY; assert(newline); if (f) r = read_full_stream(f, &contents, NULL); else r = read_full_file(fname, &contents, NULL); if (r < 0) return r; for (p = contents; *p; p++) { char c = *p; switch (state) { case PRE_KEY: if (strchr(COMMENTS, c)) state = COMMENT; else if (!strchr(WHITESPACE, c)) { state = KEY; last_key_whitespace = (size_t) -1; if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) { r = -ENOMEM; goto fail; } key[n_key++] = c; } break; case KEY: if (strchr(newline, c)) { state = PRE_KEY; line ++; n_key = 0; } else if (c == '=') { state = PRE_VALUE; last_value_whitespace = (size_t) -1; } else { if (!strchr(WHITESPACE, c)) last_key_whitespace = (size_t) -1; else if (last_key_whitespace == (size_t) -1) last_key_whitespace = n_key; if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) { r = -ENOMEM; goto fail; } key[n_key++] = c; } break; case PRE_VALUE: if (strchr(newline, c)) { state = PRE_KEY; line ++; key[n_key] = 0; if (value) value[n_value] = 0; /* strip trailing whitespace from key */ if (last_key_whitespace != (size_t) -1) key[last_key_whitespace] = 0; r = push(fname, line, key, value, userdata, n_pushed); if (r < 0) goto fail; n_key = 0; value = NULL; value_alloc = n_value = 0; } else if (c == '\'') state = SINGLE_QUOTE_VALUE; else if (c == '\"') state = DOUBLE_QUOTE_VALUE; else if (c == '\\') state = VALUE_ESCAPE; else if (!strchr(WHITESPACE, c)) { state = VALUE; if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { r = -ENOMEM; goto fail; } value[n_value++] = c; } break; case VALUE: if (strchr(newline, c)) { state = PRE_KEY; line ++; key[n_key] = 0; if (value) value[n_value] = 0; /* Chomp off trailing whitespace from value */ if (last_value_whitespace != (size_t) -1) value[last_value_whitespace] = 0; /* strip trailing whitespace from key */ if (last_key_whitespace != (size_t) -1) key[last_key_whitespace] = 0; r = push(fname, line, key, value, userdata, n_pushed); if (r < 0) goto fail; n_key = 0; value = NULL; value_alloc = n_value = 0; } else if (c == '\\') { state = VALUE_ESCAPE; last_value_whitespace = (size_t) -1; } else { if (!strchr(WHITESPACE, c)) last_value_whitespace = (size_t) -1; else if (last_value_whitespace == (size_t) -1) last_value_whitespace = n_value; if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { r = -ENOMEM; goto fail; } value[n_value++] = c; } break; case VALUE_ESCAPE: state = VALUE; if (!strchr(newline, c)) { /* Escaped newlines we eat up entirely */ if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { r = -ENOMEM; goto fail; } value[n_value++] = c; } break; case SINGLE_QUOTE_VALUE: if (c == '\'') state = PRE_VALUE; else if (c == '\\') state = SINGLE_QUOTE_VALUE_ESCAPE; else { if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { r = -ENOMEM; goto fail; } value[n_value++] = c; } break; case SINGLE_QUOTE_VALUE_ESCAPE: state = SINGLE_QUOTE_VALUE; if (!strchr(newline, c)) { if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { r = -ENOMEM; goto fail; } value[n_value++] = c; } break; case DOUBLE_QUOTE_VALUE: if (c == '\"') state = PRE_VALUE; else if (c == '\\') state = DOUBLE_QUOTE_VALUE_ESCAPE; else { if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { r = -ENOMEM; goto fail; } value[n_value++] = c; } break; case DOUBLE_QUOTE_VALUE_ESCAPE: state = DOUBLE_QUOTE_VALUE; if (!strchr(newline, c)) { if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) { r = -ENOMEM; goto fail; } value[n_value++] = c; } break; case COMMENT: if (c == '\\') state = COMMENT_ESCAPE; else if (strchr(newline, c)) { state = PRE_KEY; line ++; } break; case COMMENT_ESCAPE: state = COMMENT; break; } } if (state == PRE_VALUE || state == VALUE || state == VALUE_ESCAPE || state == SINGLE_QUOTE_VALUE || state == SINGLE_QUOTE_VALUE_ESCAPE || state == DOUBLE_QUOTE_VALUE || state == DOUBLE_QUOTE_VALUE_ESCAPE) { key[n_key] = 0; if (value) value[n_value] = 0; if (state == VALUE) if (last_value_whitespace != (size_t) -1) value[last_value_whitespace] = 0; /* strip trailing whitespace from key */ if (last_key_whitespace != (size_t) -1) key[last_key_whitespace] = 0; r = push(fname, line, key, value, userdata, n_pushed); if (r < 0) goto fail; } return 0; fail: free(value); return r; } static int parse_env_file_push( const char *filename, unsigned line, const char *key, char *value, void *userdata, int *n_pushed) { const char *k; va_list aq, *ap = userdata; if (!utf8_is_valid(key)) { _cleanup_free_ char *p; p = utf8_escape_invalid(key); log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename), line, p); return -EINVAL; } if (value && !utf8_is_valid(value)) { _cleanup_free_ char *p; p = utf8_escape_invalid(value); log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, p); return -EINVAL; } va_copy(aq, *ap); while ((k = va_arg(aq, const char *))) { char **v; v = va_arg(aq, char **); if (streq(key, k)) { va_end(aq); free(*v); *v = value; if (n_pushed) (*n_pushed)++; return 1; } } va_end(aq); free(value); return 0; } int parse_env_file( const char *fname, const char *newline, ...) { va_list ap; int r, n_pushed = 0; if (!newline) newline = NEWLINE; va_start(ap, newline); r = parse_env_file_internal(NULL, fname, newline, parse_env_file_push, &ap, &n_pushed); va_end(ap); return r < 0 ? r : n_pushed; } static int load_env_file_push( const char *filename, unsigned line, const char *key, char *value, void *userdata, int *n_pushed) { char ***m = userdata; char *p; int r; if (!utf8_is_valid(key)) { _cleanup_free_ char *t = utf8_escape_invalid(key); log_error("%s:%u: invalid UTF-8 for key '%s', ignoring.", strna(filename), line, t); return -EINVAL; } if (value && !utf8_is_valid(value)) { _cleanup_free_ char *t = utf8_escape_invalid(value); log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, t); return -EINVAL; } p = strjoin(key, "=", strempty(value), NULL); if (!p) return -ENOMEM; r = strv_consume(m, p); if (r < 0) return r; if (n_pushed) (*n_pushed)++; free(value); return 0; } int load_env_file(FILE *f, const char *fname, const char *newline, char ***rl) { char **m = NULL; int r; if (!newline) newline = NEWLINE; r = parse_env_file_internal(f, fname, newline, load_env_file_push, &m, NULL); if (r < 0) { strv_free(m); return r; } *rl = m; return 0; } static int load_env_file_push_pairs( const char *filename, unsigned line, const char *key, char *value, void *userdata, int *n_pushed) { char ***m = userdata; int r; if (!utf8_is_valid(key)) { _cleanup_free_ char *t = utf8_escape_invalid(key); log_error("%s:%u: invalid UTF-8 for key '%s', ignoring.", strna(filename), line, t); return -EINVAL; } if (value && !utf8_is_valid(value)) { _cleanup_free_ char *t = utf8_escape_invalid(value); log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, t); return -EINVAL; } r = strv_extend(m, key); if (r < 0) return -ENOMEM; if (!value) { r = strv_extend(m, ""); if (r < 0) return -ENOMEM; } else { r = strv_push(m, value); if (r < 0) return r; } if (n_pushed) (*n_pushed)++; return 0; } int load_env_file_pairs(FILE *f, const char *fname, const char *newline, char ***rl) { char **m = NULL; int r; if (!newline) newline = NEWLINE; r = parse_env_file_internal(f, fname, newline, load_env_file_push_pairs, &m, NULL); if (r < 0) { strv_free(m); return r; } *rl = m; return 0; } static void write_env_var(FILE *f, const char *v) { const char *p; p = strchr(v, '='); if (!p) { /* Fallback */ fputs(v, f); fputc('\n', f); return; } p++; fwrite(v, 1, p-v, f); if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) { fputc('\"', f); for (; *p; p++) { if (strchr(SHELL_NEED_ESCAPE, *p)) fputc('\\', f); fputc(*p, f); } fputc('\"', f); } else fputs(p, f); fputc('\n', f); } int write_env_file(const char *fname, char **l) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; char **i; int r; assert(fname); r = fopen_temporary(fname, &f, &p); if (r < 0) return r; fchmod_umask(fileno(f), 0644); STRV_FOREACH(i, l) write_env_var(f, *i); r = fflush_and_check(f); if (r >= 0) { if (rename(p, fname) >= 0) return 0; r = -errno; } unlink(p); return r; } int executable_is_script(const char *path, char **interpreter) { int r; _cleanup_free_ char *line = NULL; int len; char *ans; assert(path); r = read_one_line_file(path, &line); if (r < 0) return r; if (!startswith(line, "#!")) return 0; ans = strstrip(line + 2); len = strcspn(ans, " \t"); if (len == 0) return 0; ans = strndup(ans, len); if (!ans) return -ENOMEM; *interpreter = ans; return 1; } /** * Retrieve one field from a file like /proc/self/status. pattern * should not include whitespace or the delimiter (':'). pattern matches only * the beginning of a line. Whitespace before ':' is skipped. Whitespace and * zeros after the ':' will be skipped. field must be freed afterwards. * terminator specifies the terminating characters of the field value (not * included in the value). */ int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field) { _cleanup_free_ char *status = NULL; char *t, *f; size_t len; int r; assert(terminator); assert(filename); assert(pattern); assert(field); r = read_full_file(filename, &status, NULL); if (r < 0) return r; t = status; do { bool pattern_ok; do { t = strstr(t, pattern); if (!t) return -ENOENT; /* Check that pattern occurs in beginning of line. */ pattern_ok = (t == status || t[-1] == '\n'); t += strlen(pattern); } while (!pattern_ok); t += strspn(t, " \t"); if (!*t) return -ENOENT; } while (*t != ':'); t++; if (*t) { t += strspn(t, " \t"); /* Also skip zeros, because when this is used for * capabilities, we don't want the zeros. This way the * same capability set always maps to the same string, * irrespective of the total capability set size. For * other numbers it shouldn't matter. */ t += strspn(t, "0"); /* Back off one char if there's nothing but whitespace and zeros */ if (!*t || isspace(*t)) t --; } len = strcspn(t, terminator); f = strndup(t, len); if (!f) return -ENOMEM; *field = f; return 0; } DIR *xopendirat(int fd, const char *name, int flags) { int nfd; DIR *d; assert(!(flags & O_CREAT)); nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0); if (nfd < 0) return NULL; d = fdopendir(nfd); if (!d) { safe_close(nfd); return NULL; } return d; } static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) { char **i; assert(path); assert(mode); assert(_f); if (!path_strv_resolve_uniq(search, root)) return -ENOMEM; STRV_FOREACH(i, search) { _cleanup_free_ char *p = NULL; FILE *f; if (root) p = strjoin(root, *i, "/", path, NULL); else p = strjoin(*i, "/", path, NULL); if (!p) return -ENOMEM; f = fopen(p, mode); if (f) { *_f = f; return 0; } if (errno != ENOENT) return -errno; } return -ENOENT; } int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) { _cleanup_strv_free_ char **copy = NULL; assert(path); assert(mode); assert(_f); if (path_is_absolute(path)) { FILE *f; f = fopen(path, mode); if (f) { *_f = f; return 0; } return -errno; } copy = strv_copy((char**) search); if (!copy) return -ENOMEM; return search_and_fopen_internal(path, mode, root, copy, _f); } int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) { _cleanup_strv_free_ char **s = NULL; if (path_is_absolute(path)) { FILE *f; f = fopen(path, mode); if (f) { *_f = f; return 0; } return -errno; } s = strv_split_nulstr(search); if (!s) return -ENOMEM; return search_and_fopen_internal(path, mode, root, s, _f); } int fopen_temporary(const char *path, FILE **_f, char **_temp_path) { FILE *f; char *t; int r, fd; assert(path); assert(_f); assert(_temp_path); r = tempfn_xxxxxx(path, NULL, &t); if (r < 0) return r; fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC); if (fd < 0) { free(t); return -errno; } f = fdopen(fd, "we"); if (!f) { unlink_noerrno(t); free(t); safe_close(fd); return -errno; } *_f = f; *_temp_path = t; return 0; } int fflush_and_check(FILE *f) { assert(f); errno = 0; fflush(f); if (ferror(f)) return errno > 0 ? -errno : -EIO; return 0; } /* This is much like like mkostemp() but is subject to umask(). */ int mkostemp_safe(char *pattern, int flags) { _cleanup_umask_ mode_t u; int fd; assert(pattern); u = umask(077); fd = mkostemp(pattern, flags); if (fd < 0) return -errno; return fd; } int open_tmpfile(const char *path, int flags) { char *p; int fd; assert(path); #ifdef O_TMPFILE /* Try O_TMPFILE first, if it is supported */ fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR); if (fd >= 0) return fd; #endif /* Fall back to unguessable name + unlinking */ p = strjoina(path, "/systemd-tmp-XXXXXX"); fd = mkostemp_safe(p, flags); if (fd < 0) return fd; unlink(p); return fd; } int tempfn_xxxxxx(const char *p, const char *extra, char **ret) { const char *fn; char *t; assert(p); assert(ret); /* * Turns this: * /foo/bar/waldo * * Into this: * /foo/bar/.#waldoXXXXXX */ fn = basename(p); if (!filename_is_valid(fn)) return -EINVAL; if (extra == NULL) extra = ""; t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1); if (!t) return -ENOMEM; strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX"); *ret = path_kill_slashes(t); return 0; } int tempfn_random(const char *p, const char *extra, char **ret) { const char *fn; char *t, *x; uint64_t u; unsigned i; assert(p); assert(ret); /* * Turns this: * /foo/bar/waldo * * Into this: * /foo/bar/.#waldobaa2a261115984a9 */ fn = basename(p); if (!filename_is_valid(fn)) return -EINVAL; if (!extra) extra = ""; t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1); if (!t) return -ENOMEM; x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn); u = random_u64(); for (i = 0; i < 16; i++) { *(x++) = hexchar(u & 0xF); u >>= 4; } *x = 0; *ret = path_kill_slashes(t); return 0; } int tempfn_random_child(const char *p, const char *extra, char **ret) { char *t, *x; uint64_t u; unsigned i; assert(p); assert(ret); /* Turns this: * /foo/bar/waldo * Into this: * /foo/bar/waldo/.#3c2b6219aa75d7d0 */ if (!extra) extra = ""; t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1); if (!t) return -ENOMEM; x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra); u = random_u64(); for (i = 0; i < 16; i++) { *(x++) = hexchar(u & 0xF); u >>= 4; } *x = 0; *ret = path_kill_slashes(t); return 0; } int write_timestamp_file_atomic(const char *fn, usec_t n) { char ln[DECIMAL_STR_MAX(n)+2]; /* Creates a "timestamp" file, that contains nothing but a * usec_t timestamp, formatted in ASCII. */ if (n <= 0 || n >= USEC_INFINITY) return -ERANGE; xsprintf(ln, USEC_FMT "\n", n); return write_string_file(fn, ln, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC); } int read_timestamp_file(const char *fn, usec_t *ret) { _cleanup_free_ char *ln = NULL; uint64_t t; int r; r = read_one_line_file(fn, &ln); if (r < 0) return r; r = safe_atou64(ln, &t); if (r < 0) return r; if (t <= 0 || t >= (uint64_t) USEC_INFINITY) return -ERANGE; *ret = (usec_t) t; return 0; } int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) { int r; assert(s); /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter * when specified shall initially point to a boolean variable initialized to false. It is set to true after the * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each * element, but not before the first one. */ if (!f) f = stdout; if (space) { if (!separator) separator = " "; if (*space) { r = fputs(separator, f); if (r < 0) return r; } *space = true; } return fputs(s, f); } systemd-229/src/basic/fileio.h000066400000000000000000000064021265713322000163530ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "macro.h" #include "time-util.h" typedef enum { WRITE_STRING_FILE_CREATE = 1, WRITE_STRING_FILE_ATOMIC = 2, WRITE_STRING_FILE_AVOID_NEWLINE = 4, WRITE_STRING_FILE_VERIFY_ON_FAILURE = 8, } WriteStringFileFlags; int write_string_stream(FILE *f, const char *line, bool enforce_newline); int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags); int read_one_line_file(const char *fn, char **line); int read_full_file(const char *fn, char **contents, size_t *size); int read_full_stream(FILE *f, char **contents, size_t *size); int verify_file(const char *fn, const char *blob, bool accept_extra_nl); int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; int load_env_file(FILE *f, const char *fname, const char *separator, char ***l); int load_env_file_pairs(FILE *f, const char *fname, const char *separator, char ***l); int write_env_file(const char *fname, char **l); int executable_is_script(const char *path, char **interpreter); int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field); DIR *xopendirat(int dirfd, const char *name, int flags); int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f); int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f); #define FOREACH_LINE(line, f, on_error) \ for (;;) \ if (!fgets(line, sizeof(line), f)) { \ if (ferror(f)) { \ on_error; \ } \ break; \ } else int fflush_and_check(FILE *f); int fopen_temporary(const char *path, FILE **_f, char **_temp_path); int mkostemp_safe(char *pattern, int flags); int open_tmpfile(const char *path, int flags); int tempfn_xxxxxx(const char *p, const char *extra, char **ret); int tempfn_random(const char *p, const char *extra, char **ret); int tempfn_random_child(const char *p, const char *extra, char **ret); int write_timestamp_file_atomic(const char *fn, usec_t n); int read_timestamp_file(const char *fn, usec_t *ret); int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space); systemd-229/src/basic/formats-util.h000066400000000000000000000027401265713322000175330ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #if SIZEOF_PID_T == 4 # define PID_PRI PRIi32 #elif SIZEOF_PID_T == 2 # define PID_PRI PRIi16 #else # error Unknown pid_t size #endif #define PID_FMT "%" PID_PRI #if SIZEOF_UID_T == 4 # define UID_FMT "%" PRIu32 #elif SIZEOF_UID_T == 2 # define UID_FMT "%" PRIu16 #else # error Unknown uid_t size #endif #if SIZEOF_GID_T == 4 # define GID_FMT "%" PRIu32 #elif SIZEOF_GID_T == 2 # define GID_FMT "%" PRIu16 #else # error Unknown gid_t size #endif #if SIZEOF_TIME_T == 8 # define PRI_TIME PRIi64 #elif SIZEOF_TIME_T == 4 # define PRI_TIME PRIu32 #else # error Unknown time_t size #endif #if SIZEOF_RLIM_T == 8 # define RLIM_FMT "%" PRIu64 #elif SIZEOF_RLIM_T == 4 # define RLIM_FMT "%" PRIu32 #else # error Unknown rlim_t size #endif systemd-229/src/basic/fs-util.c000066400000000000000000000313001265713322000164550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "dirent-util.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "log.h" #include "macro.h" #include "missing.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" #include "user-util.h" #include "util.h" int unlink_noerrno(const char *path) { PROTECT_ERRNO; int r; r = unlink(path); if (r < 0) return -errno; return 0; } int rmdir_parents(const char *path, const char *stop) { size_t l; int r = 0; assert(path); assert(stop); l = strlen(path); /* Skip trailing slashes */ while (l > 0 && path[l-1] == '/') l--; while (l > 0) { char *t; /* Skip last component */ while (l > 0 && path[l-1] != '/') l--; /* Skip trailing slashes */ while (l > 0 && path[l-1] == '/') l--; if (l <= 0) break; t = strndup(path, l); if (!t) return -ENOMEM; if (path_startswith(stop, t)) { free(t); return 0; } r = rmdir(t); free(t); if (r < 0) if (errno != ENOENT) return -errno; } return 0; } int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { struct stat buf; int ret; ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE); if (ret >= 0) return 0; /* renameat2() exists since Linux 3.15, btrfs added support for it later. * If it is not implemented, fallback to another method. */ if (!IN_SET(errno, EINVAL, ENOSYS)) return -errno; /* The link()/unlink() fallback does not work on directories. But * renameat() without RENAME_NOREPLACE gives the same semantics on * directories, except when newpath is an *empty* directory. This is * good enough. */ ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW); if (ret >= 0 && S_ISDIR(buf.st_mode)) { ret = renameat(olddirfd, oldpath, newdirfd, newpath); return ret >= 0 ? 0 : -errno; } /* If it is not a directory, use the link()/unlink() fallback. */ ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0); if (ret < 0) return -errno; ret = unlinkat(olddirfd, oldpath, 0); if (ret < 0) { /* backup errno before the following unlinkat() alters it */ ret = errno; (void) unlinkat(newdirfd, newpath, 0); errno = ret; return -errno; } return 0; } int readlinkat_malloc(int fd, const char *p, char **ret) { size_t l = 100; int r; assert(p); assert(ret); for (;;) { char *c; ssize_t n; c = new(char, l); if (!c) return -ENOMEM; n = readlinkat(fd, p, c, l-1); if (n < 0) { r = -errno; free(c); return r; } if ((size_t) n < l-1) { c[n] = 0; *ret = c; return 0; } free(c); l *= 2; } } int readlink_malloc(const char *p, char **ret) { return readlinkat_malloc(AT_FDCWD, p, ret); } int readlink_value(const char *p, char **ret) { _cleanup_free_ char *link = NULL; char *value; int r; r = readlink_malloc(p, &link); if (r < 0) return r; value = basename(link); if (!value) return -ENOENT; value = strdup(value); if (!value) return -ENOMEM; *ret = value; return 0; } int readlink_and_make_absolute(const char *p, char **r) { _cleanup_free_ char *target = NULL; char *k; int j; assert(p); assert(r); j = readlink_malloc(p, &target); if (j < 0) return j; k = file_in_same_dir(p, target); if (!k) return -ENOMEM; *r = k; return 0; } int readlink_and_canonicalize(const char *p, char **r) { char *t, *s; int j; assert(p); assert(r); j = readlink_and_make_absolute(p, &t); if (j < 0) return j; s = canonicalize_file_name(t); if (s) { free(t); *r = s; } else *r = t; path_kill_slashes(*r); return 0; } int readlink_and_make_absolute_root(const char *root, const char *path, char **ret) { _cleanup_free_ char *target = NULL, *t = NULL; const char *full; int r; full = prefix_roota(root, path); r = readlink_malloc(full, &target); if (r < 0) return r; t = file_in_same_dir(path, target); if (!t) return -ENOMEM; *ret = t; t = NULL; return 0; } int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) { assert(path); /* Under the assumption that we are running privileged we * first change the access mode and only then hand out * ownership to avoid a window where access is too open. */ if (mode != MODE_INVALID) if (chmod(path, mode) < 0) return -errno; if (uid != UID_INVALID || gid != GID_INVALID) if (chown(path, uid, gid) < 0) return -errno; return 0; } int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) { assert(fd >= 0); /* Under the assumption that we are running privileged we * first change the access mode and only then hand out * ownership to avoid a window where access is too open. */ if (mode != MODE_INVALID) if (fchmod(fd, mode) < 0) return -errno; if (uid != UID_INVALID || gid != GID_INVALID) if (fchown(fd, uid, gid) < 0) return -errno; return 0; } int fchmod_umask(int fd, mode_t m) { mode_t u; int r; u = umask(0777); r = fchmod(fd, m & (~u)) < 0 ? -errno : 0; umask(u); return r; } int fd_warn_permissions(const char *path, int fd) { struct stat st; if (fstat(fd, &st) < 0) return -errno; if (st.st_mode & 0111) log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path); if (st.st_mode & 0002) log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path); if (getpid() == 1 && (st.st_mode & 0044) != 0044) log_warning("Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway.", path); return 0; } int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) { _cleanup_close_ int fd; int r; assert(path); if (parents) mkdir_parents(path, 0755); fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, (mode == 0 || mode == MODE_INVALID) ? 0644 : mode); if (fd < 0) return -errno; if (mode != MODE_INVALID) { r = fchmod(fd, mode); if (r < 0) return -errno; } if (uid != UID_INVALID || gid != GID_INVALID) { r = fchown(fd, uid, gid); if (r < 0) return -errno; } if (stamp != USEC_INFINITY) { struct timespec ts[2]; timespec_store(&ts[0], stamp); ts[1] = ts[0]; r = futimens(fd, ts); } else r = futimens(fd, NULL); if (r < 0) return -errno; return 0; } int touch(const char *path) { return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID); } int symlink_idempotent(const char *from, const char *to) { _cleanup_free_ char *p = NULL; int r; assert(from); assert(to); if (symlink(from, to) < 0) { if (errno != EEXIST) return -errno; r = readlink_malloc(to, &p); if (r < 0) return r; if (!streq(p, from)) return -EINVAL; } return 0; } int symlink_atomic(const char *from, const char *to) { _cleanup_free_ char *t = NULL; int r; assert(from); assert(to); r = tempfn_random(to, NULL, &t); if (r < 0) return r; if (symlink(from, t) < 0) return -errno; if (rename(t, to) < 0) { unlink_noerrno(t); return -errno; } return 0; } int mknod_atomic(const char *path, mode_t mode, dev_t dev) { _cleanup_free_ char *t = NULL; int r; assert(path); r = tempfn_random(path, NULL, &t); if (r < 0) return r; if (mknod(t, mode, dev) < 0) return -errno; if (rename(t, path) < 0) { unlink_noerrno(t); return -errno; } return 0; } int mkfifo_atomic(const char *path, mode_t mode) { _cleanup_free_ char *t = NULL; int r; assert(path); r = tempfn_random(path, NULL, &t); if (r < 0) return r; if (mkfifo(t, mode) < 0) return -errno; if (rename(t, path) < 0) { unlink_noerrno(t); return -errno; } return 0; } int get_files_in_directory(const char *path, char ***list) { _cleanup_closedir_ DIR *d = NULL; size_t bufsize = 0, n = 0; _cleanup_strv_free_ char **l = NULL; assert(path); /* Returns all files in a directory in *list, and the number * of files as return value. If list is NULL returns only the * number. */ d = opendir(path); if (!d) return -errno; for (;;) { struct dirent *de; errno = 0; de = readdir(d); if (!de && errno > 0) return -errno; if (!de) break; dirent_ensure_type(d, de); if (!dirent_is_file(de)) continue; if (list) { /* one extra slot is needed for the terminating NULL */ if (!GREEDY_REALLOC(l, bufsize, n + 2)) return -ENOMEM; l[n] = strdup(de->d_name); if (!l[n]) return -ENOMEM; l[++n] = NULL; } else n++; } if (list) { *list = l; l = NULL; /* avoid freeing */ } return n; } systemd-229/src/basic/fs-util.h000066400000000000000000000051101265713322000164620ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "time-util.h" int unlink_noerrno(const char *path); int rmdir_parents(const char *path, const char *stop); int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); int readlinkat_malloc(int fd, const char *p, char **ret); int readlink_malloc(const char *p, char **r); int readlink_value(const char *p, char **ret); int readlink_and_make_absolute(const char *p, char **r); int readlink_and_canonicalize(const char *p, char **r); int readlink_and_make_absolute_root(const char *root, const char *path, char **ret); int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid); int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid); int fchmod_umask(int fd, mode_t mode); int fd_warn_permissions(const char *path, int fd); #define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW) int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode); int touch(const char *path); int symlink_idempotent(const char *from, const char *to); int symlink_atomic(const char *from, const char *to); int mknod_atomic(const char *path, mode_t mode, dev_t dev); int mkfifo_atomic(const char *path, mode_t mode); int get_files_in_directory(const char *path, char ***list); #define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1) #define FOREACH_INOTIFY_EVENT(e, buffer, sz) \ for ((e) = &buffer.ev; \ (uint8_t*) (e) < (uint8_t*) (buffer.raw) + (sz); \ (e) = (struct inotify_event*) ((uint8_t*) (e) + sizeof(struct inotify_event) + (e)->len)) union inotify_event_buffer { struct inotify_event ev; uint8_t raw[INOTIFY_EVENT_MAX]; }; systemd-229/src/basic/glob-util.c000066400000000000000000000035451265713322000170020ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "glob-util.h" #include "macro.h" #include "strv.h" int glob_exists(const char *path) { _cleanup_globfree_ glob_t g = {}; int k; assert(path); errno = 0; k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g); if (k == GLOB_NOMATCH) return 0; if (k == GLOB_NOSPACE) return -ENOMEM; if (k != 0) return errno > 0 ? -errno : -EIO; return !strv_isempty(g.gl_pathv); } int glob_extend(char ***strv, const char *path) { _cleanup_globfree_ glob_t g = {}; int k; char **p; errno = 0; k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g); if (k == GLOB_NOMATCH) return -ENOENT; if (k == GLOB_NOSPACE) return -ENOMEM; if (k != 0) return errno > 0 ? -errno : -EIO; if (strv_isempty(g.gl_pathv)) return -ENOENT; STRV_FOREACH(p, g.gl_pathv) { k = strv_extend(strv, *p); if (k < 0) return k; } return 0; } systemd-229/src/basic/glob-util.h000066400000000000000000000021321265713322000167760ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "macro.h" #include "string-util.h" int glob_exists(const char *path); int glob_extend(char ***strv, const char *path); #define _cleanup_globfree_ _cleanup_(globfree) _pure_ static inline bool string_is_glob(const char *p) { /* Check if a string contains any glob patterns. */ return !!strpbrk(p, GLOB_CHARS); } systemd-229/src/basic/gunicode.c000066400000000000000000000063501265713322000166760ustar00rootroot00000000000000/* gunicode.c - Unicode manipulation functions * * Copyright (C) 1999, 2000 Tom Tromey * Copyright 2000, 2005 Red Hat, Inc. */ #include #include "gunicode.h" #define unichar uint32_t /** * g_utf8_prev_char: * @p: a pointer to a position within a UTF-8 encoded string * * Finds the previous UTF-8 character in the string before @p. * * @p does not have to be at the beginning of a UTF-8 character. No check * is made to see if the character found is actually valid other than * it starts with an appropriate byte. If @p might be the first * character of the string, you must use g_utf8_find_prev_char() instead. * * Return value: a pointer to the found character. **/ char * utf8_prev_char (const char *p) { while (1) { p--; if ((*p & 0xc0) != 0x80) return (char *)p; } } struct Interval { unichar start, end; }; static int interval_compare (const void *key, const void *elt) { unichar c = (unichar) (long) (key); struct Interval *interval = (struct Interval *)elt; if (c < interval->start) return -1; if (c > interval->end) return +1; return 0; } /* * NOTE: * * The tables for g_unichar_iswide() and g_unichar_iswide_cjk() are * generated from the Unicode Character Database's file * extracted/DerivedEastAsianWidth.txt using the gen-iswide-table.py * in this way: * * ./gen-iswide-table.py < path/to/ucd/extracted/DerivedEastAsianWidth.txt | fmt * * Last update for Unicode 6.0. */ /** * g_unichar_iswide: * @c: a Unicode character * * Determines if a character is typically rendered in a double-width * cell. * * Return value: %TRUE if the character is wide **/ bool unichar_iswide (unichar c) { /* See NOTE earlier for how to update this table. */ static const struct Interval wide[] = { {0x1100, 0x115F}, {0x2329, 0x232A}, {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, {0x3000, 0x303E}, {0x3041, 0x3096}, {0x3099, 0x30FF}, {0x3105, 0x312D}, {0x3131, 0x318E}, {0x3190, 0x31BA}, {0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247}, {0x3250, 0x32FE}, {0x3300, 0x4DBF}, {0x4E00, 0xA48C}, {0xA490, 0xA4C6}, {0xA960, 0xA97C}, {0xAC00, 0xD7A3}, {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, {0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6}, {0x1B000, 0x1B001}, {0x1F200, 0x1F202}, {0x1F210, 0x1F23A}, {0x1F240, 0x1F248}, {0x1F250, 0x1F251}, {0x1F300, 0x1F567}, /* Miscellaneous Symbols and Pictographs */ {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD}, }; if (bsearch ((void *)(uintptr_t)c, wide, (sizeof (wide) / sizeof ((wide)[0])), sizeof wide[0], interval_compare)) return true; return false; } const char utf8_skip_data[256] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1 }; systemd-229/src/basic/gunicode.h000066400000000000000000000015601265713322000167010ustar00rootroot00000000000000/* gunicode.h - Unicode manipulation functions * * Copyright (C) 1999, 2000 Tom Tromey * Copyright 2000, 2005 Red Hat, Inc. */ #pragma once #include #include #include char *utf8_prev_char (const char *p); extern const char utf8_skip_data[256]; /** * g_utf8_next_char: * @p: Pointer to the start of a valid UTF-8 character * * Skips to the next character in a UTF-8 string. The string must be * valid; this macro is as fast as possible, and has no error-checking. * You would use this macro to iterate over a string character by * character. The macro returns the start of the next UTF-8 character. * Before using this macro, use g_utf8_validate() to validate strings * that may contain invalid UTF-8. */ #define utf8_next_char(p) (char *)((p) + utf8_skip_data[*(const unsigned char *)(p)]) bool unichar_iswide (uint32_t c); systemd-229/src/basic/hash-funcs.c000066400000000000000000000044301265713322000171350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2014 Michal Schmidt systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "hash-funcs.h" void string_hash_func(const void *p, struct siphash *state) { siphash24_compress(p, strlen(p) + 1, state); } int string_compare_func(const void *a, const void *b) { return strcmp(a, b); } const struct hash_ops string_hash_ops = { .hash = string_hash_func, .compare = string_compare_func }; void trivial_hash_func(const void *p, struct siphash *state) { siphash24_compress(&p, sizeof(p), state); } int trivial_compare_func(const void *a, const void *b) { return a < b ? -1 : (a > b ? 1 : 0); } const struct hash_ops trivial_hash_ops = { .hash = trivial_hash_func, .compare = trivial_compare_func }; void uint64_hash_func(const void *p, struct siphash *state) { siphash24_compress(p, sizeof(uint64_t), state); } int uint64_compare_func(const void *_a, const void *_b) { uint64_t a, b; a = *(const uint64_t*) _a; b = *(const uint64_t*) _b; return a < b ? -1 : (a > b ? 1 : 0); } const struct hash_ops uint64_hash_ops = { .hash = uint64_hash_func, .compare = uint64_compare_func }; #if SIZEOF_DEV_T != 8 void devt_hash_func(const void *p, struct siphash *state) { siphash24_compress(p, sizeof(dev_t), state); } int devt_compare_func(const void *_a, const void *_b) { dev_t a, b; a = *(const dev_t*) _a; b = *(const dev_t*) _b; return a < b ? -1 : (a > b ? 1 : 0); } const struct hash_ops devt_hash_ops = { .hash = devt_hash_func, .compare = devt_compare_func }; #endif systemd-229/src/basic/hash-funcs.h000066400000000000000000000045421265713322000171460ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2014 Michal Schmidt systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "macro.h" #include "siphash24.h" typedef void (*hash_func_t)(const void *p, struct siphash *state); typedef int (*compare_func_t)(const void *a, const void *b); struct hash_ops { hash_func_t hash; compare_func_t compare; }; void string_hash_func(const void *p, struct siphash *state); int string_compare_func(const void *a, const void *b) _pure_; extern const struct hash_ops string_hash_ops; /* This will compare the passed pointers directly, and will not * dereference them. This is hence not useful for strings or * suchlike. */ void trivial_hash_func(const void *p, struct siphash *state); int trivial_compare_func(const void *a, const void *b) _const_; extern const struct hash_ops trivial_hash_ops; /* 32bit values we can always just embed in the pointer itself, but * in order to support 32bit archs we need store 64bit values * indirectly, since they don't fit in a pointer. */ void uint64_hash_func(const void *p, struct siphash *state); int uint64_compare_func(const void *a, const void *b) _pure_; extern const struct hash_ops uint64_hash_ops; /* On some archs dev_t is 32bit, and on others 64bit. And sometimes * it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */ #if SIZEOF_DEV_T != 8 void devt_hash_func(const void *p, struct siphash *state) _pure_; int devt_compare_func(const void *a, const void *b) _pure_; extern const struct hash_ops devt_hash_ops = { .hash = devt_hash_func, .compare = devt_compare_func }; #else #define devt_hash_func uint64_hash_func #define devt_compare_func uint64_compare_func #define devt_hash_ops uint64_hash_ops #endif systemd-229/src/basic/hashmap.c000066400000000000000000001605231265713322000165250ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2014 Michal Schmidt systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "hashmap.h" #include "macro.h" #include "mempool.h" #include "process-util.h" #include "random-util.h" #include "set.h" #include "siphash24.h" #include "strv.h" #include "util.h" #ifdef ENABLE_DEBUG_HASHMAP #include #include "list.h" #endif /* * Implementation of hashmaps. * Addressing: open * - uses less RAM compared to closed addressing (chaining), because * our entries are small (especially in Sets, which tend to contain * the majority of entries in systemd). * Collision resolution: Robin Hood * - tends to equalize displacement of entries from their optimal buckets. * Probe sequence: linear * - though theoretically worse than random probing/uniform hashing/double * hashing, it is good for cache locality. * * References: * Celis, P. 1986. Robin Hood Hashing. * Ph.D. Dissertation. University of Waterloo, Waterloo, Ont., Canada, Canada. * https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf * - The results are derived for random probing. Suggests deletion with * tombstones and two mean-centered search methods. None of that works * well for linear probing. * * Janson, S. 2005. Individual displacements for linear probing hashing with different insertion policies. * ACM Trans. Algorithms 1, 2 (October 2005), 177-213. * DOI=10.1145/1103963.1103964 http://doi.acm.org/10.1145/1103963.1103964 * http://www.math.uu.se/~svante/papers/sj157.pdf * - Applies to Robin Hood with linear probing. Contains remarks on * the unsuitability of mean-centered search with linear probing. * * Viola, A. 2005. Exact distribution of individual displacements in linear probing hashing. * ACM Trans. Algorithms 1, 2 (October 2005), 214-242. * DOI=10.1145/1103963.1103965 http://doi.acm.org/10.1145/1103963.1103965 * - Similar to Janson. Note that Viola writes about C_{m,n} (number of probes * in a successful search), and Janson writes about displacement. C = d + 1. * * Goossaert, E. 2013. Robin Hood hashing: backward shift deletion. * http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/ * - Explanation of backward shift deletion with pictures. * * Khuong, P. 2013. The Other Robin Hood Hashing. * http://www.pvk.ca/Blog/2013/11/26/the-other-robin-hood-hashing/ * - Short summary of random vs. linear probing, and tombstones vs. backward shift. */ /* * XXX Ideas for improvement: * For unordered hashmaps, randomize iteration order, similarly to Perl: * http://blog.booking.com/hardening-perls-hash-function.html */ /* INV_KEEP_FREE = 1 / (1 - max_load_factor) * e.g. 1 / (1 - 0.8) = 5 ... keep one fifth of the buckets free. */ #define INV_KEEP_FREE 5U /* Fields common to entries of all hashmap/set types */ struct hashmap_base_entry { const void *key; }; /* Entry types for specific hashmap/set types * hashmap_base_entry must be at the beginning of each entry struct. */ struct plain_hashmap_entry { struct hashmap_base_entry b; void *value; }; struct ordered_hashmap_entry { struct plain_hashmap_entry p; unsigned iterate_next, iterate_previous; }; struct set_entry { struct hashmap_base_entry b; }; /* In several functions it is advantageous to have the hash table extended * virtually by a couple of additional buckets. We reserve special index values * for these "swap" buckets. */ #define _IDX_SWAP_BEGIN (UINT_MAX - 3) #define IDX_PUT (_IDX_SWAP_BEGIN + 0) #define IDX_TMP (_IDX_SWAP_BEGIN + 1) #define _IDX_SWAP_END (_IDX_SWAP_BEGIN + 2) #define IDX_FIRST (UINT_MAX - 1) /* special index for freshly initialized iterators */ #define IDX_NIL UINT_MAX /* special index value meaning "none" or "end" */ assert_cc(IDX_FIRST == _IDX_SWAP_END); assert_cc(IDX_FIRST == _IDX_ITERATOR_FIRST); /* Storage space for the "swap" buckets. * All entry types can fit into a ordered_hashmap_entry. */ struct swap_entries { struct ordered_hashmap_entry e[_IDX_SWAP_END - _IDX_SWAP_BEGIN]; }; /* Distance from Initial Bucket */ typedef uint8_t dib_raw_t; #define DIB_RAW_OVERFLOW ((dib_raw_t)0xfdU) /* indicates DIB value is greater than representable */ #define DIB_RAW_REHASH ((dib_raw_t)0xfeU) /* entry yet to be rehashed during in-place resize */ #define DIB_RAW_FREE ((dib_raw_t)0xffU) /* a free bucket */ #define DIB_RAW_INIT ((char)DIB_RAW_FREE) /* a byte to memset a DIB store with when initializing */ #define DIB_FREE UINT_MAX #ifdef ENABLE_DEBUG_HASHMAP struct hashmap_debug_info { LIST_FIELDS(struct hashmap_debug_info, debug_list); unsigned max_entries; /* high watermark of n_entries */ /* who allocated this hashmap */ int line; const char *file; const char *func; /* fields to detect modification while iterating */ unsigned put_count; /* counts puts into the hashmap */ unsigned rem_count; /* counts removals from hashmap */ unsigned last_rem_idx; /* remembers last removal index */ }; /* Tracks all existing hashmaps. Get at it from gdb. See sd_dump_hashmaps.py */ static LIST_HEAD(struct hashmap_debug_info, hashmap_debug_list); static pthread_mutex_t hashmap_debug_list_mutex = PTHREAD_MUTEX_INITIALIZER; #define HASHMAP_DEBUG_FIELDS struct hashmap_debug_info debug; #else /* !ENABLE_DEBUG_HASHMAP */ #define HASHMAP_DEBUG_FIELDS #endif /* ENABLE_DEBUG_HASHMAP */ enum HashmapType { HASHMAP_TYPE_PLAIN, HASHMAP_TYPE_ORDERED, HASHMAP_TYPE_SET, _HASHMAP_TYPE_MAX }; struct _packed_ indirect_storage { char *storage; /* where buckets and DIBs are stored */ uint8_t hash_key[HASH_KEY_SIZE]; /* hash key; changes during resize */ unsigned n_entries; /* number of stored entries */ unsigned n_buckets; /* number of buckets */ unsigned idx_lowest_entry; /* Index below which all buckets are free. Makes "while(hashmap_steal_first())" loops O(n) instead of O(n^2) for unordered hashmaps. */ uint8_t _pad[3]; /* padding for the whole HashmapBase */ /* The bitfields in HashmapBase complete the alignment of the whole thing. */ }; struct direct_storage { /* This gives us 39 bytes on 64bit, or 35 bytes on 32bit. * That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64bit, * or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32bit. */ char storage[sizeof(struct indirect_storage)]; }; #define DIRECT_BUCKETS(entry_t) \ (sizeof(struct direct_storage) / (sizeof(entry_t) + sizeof(dib_raw_t))) /* We should be able to store at least one entry directly. */ assert_cc(DIRECT_BUCKETS(struct ordered_hashmap_entry) >= 1); /* We have 3 bits for n_direct_entries. */ assert_cc(DIRECT_BUCKETS(struct set_entry) < (1 << 3)); /* Hashmaps with directly stored entries all use this shared hash key. * It's no big deal if the key is guessed, because there can be only * a handful of directly stored entries in a hashmap. When a hashmap * outgrows direct storage, it gets its own key for indirect storage. */ static uint8_t shared_hash_key[HASH_KEY_SIZE]; static bool shared_hash_key_initialized; /* Fields that all hashmap/set types must have */ struct HashmapBase { const struct hash_ops *hash_ops; /* hash and compare ops to use */ union _packed_ { struct indirect_storage indirect; /* if has_indirect */ struct direct_storage direct; /* if !has_indirect */ }; enum HashmapType type:2; /* HASHMAP_TYPE_* */ bool has_indirect:1; /* whether indirect storage is used */ unsigned n_direct_entries:3; /* Number of entries in direct storage. * Only valid if !has_indirect. */ bool from_pool:1; /* whether was allocated from mempool */ HASHMAP_DEBUG_FIELDS /* optional hashmap_debug_info */ }; /* Specific hash types * HashmapBase must be at the beginning of each hashmap struct. */ struct Hashmap { struct HashmapBase b; }; struct OrderedHashmap { struct HashmapBase b; unsigned iterate_list_head, iterate_list_tail; }; struct Set { struct HashmapBase b; }; DEFINE_MEMPOOL(hashmap_pool, Hashmap, 8); DEFINE_MEMPOOL(ordered_hashmap_pool, OrderedHashmap, 8); /* No need for a separate Set pool */ assert_cc(sizeof(Hashmap) == sizeof(Set)); struct hashmap_type_info { size_t head_size; size_t entry_size; struct mempool *mempool; unsigned n_direct_buckets; }; static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = { [HASHMAP_TYPE_PLAIN] = { .head_size = sizeof(Hashmap), .entry_size = sizeof(struct plain_hashmap_entry), .mempool = &hashmap_pool, .n_direct_buckets = DIRECT_BUCKETS(struct plain_hashmap_entry), }, [HASHMAP_TYPE_ORDERED] = { .head_size = sizeof(OrderedHashmap), .entry_size = sizeof(struct ordered_hashmap_entry), .mempool = &ordered_hashmap_pool, .n_direct_buckets = DIRECT_BUCKETS(struct ordered_hashmap_entry), }, [HASHMAP_TYPE_SET] = { .head_size = sizeof(Set), .entry_size = sizeof(struct set_entry), .mempool = &hashmap_pool, .n_direct_buckets = DIRECT_BUCKETS(struct set_entry), }, }; static unsigned n_buckets(HashmapBase *h) { return h->has_indirect ? h->indirect.n_buckets : hashmap_type_info[h->type].n_direct_buckets; } static unsigned n_entries(HashmapBase *h) { return h->has_indirect ? h->indirect.n_entries : h->n_direct_entries; } static void n_entries_inc(HashmapBase *h) { if (h->has_indirect) h->indirect.n_entries++; else h->n_direct_entries++; } static void n_entries_dec(HashmapBase *h) { if (h->has_indirect) h->indirect.n_entries--; else h->n_direct_entries--; } static char *storage_ptr(HashmapBase *h) { return h->has_indirect ? h->indirect.storage : h->direct.storage; } static uint8_t *hash_key(HashmapBase *h) { return h->has_indirect ? h->indirect.hash_key : shared_hash_key; } static unsigned base_bucket_hash(HashmapBase *h, const void *p) { struct siphash state; uint64_t hash; siphash24_init(&state, hash_key(h)); h->hash_ops->hash(p, &state); hash = siphash24_finalize(&state); return (unsigned) (hash % n_buckets(h)); } #define bucket_hash(h, p) base_bucket_hash(HASHMAP_BASE(h), p) static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) { static uint8_t current[HASH_KEY_SIZE]; static bool current_initialized = false; /* Returns a hash function key to use. In order to keep things * fast we will not generate a new key each time we allocate a * new hash table. Instead, we'll just reuse the most recently * generated one, except if we never generated one or when we * are rehashing an entire hash table because we reached a * fill level */ if (!current_initialized || !reuse_is_ok) { random_bytes(current, sizeof(current)); current_initialized = true; } memcpy(hash_key, current, sizeof(current)); } static struct hashmap_base_entry *bucket_at(HashmapBase *h, unsigned idx) { return (struct hashmap_base_entry*) (storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size); } static struct plain_hashmap_entry *plain_bucket_at(Hashmap *h, unsigned idx) { return (struct plain_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx); } static struct ordered_hashmap_entry *ordered_bucket_at(OrderedHashmap *h, unsigned idx) { return (struct ordered_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx); } static struct set_entry *set_bucket_at(Set *h, unsigned idx) { return (struct set_entry*) bucket_at(HASHMAP_BASE(h), idx); } static struct ordered_hashmap_entry *bucket_at_swap(struct swap_entries *swap, unsigned idx) { return &swap->e[idx - _IDX_SWAP_BEGIN]; } /* Returns a pointer to the bucket at index idx. * Understands real indexes and swap indexes, hence "_virtual". */ static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_entries *swap, unsigned idx) { if (idx < _IDX_SWAP_BEGIN) return bucket_at(h, idx); if (idx < _IDX_SWAP_END) return &bucket_at_swap(swap, idx)->p.b; assert_not_reached("Invalid index"); } static dib_raw_t *dib_raw_ptr(HashmapBase *h) { return (dib_raw_t*) (storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h)); } static unsigned bucket_distance(HashmapBase *h, unsigned idx, unsigned from) { return idx >= from ? idx - from : n_buckets(h) + idx - from; } static unsigned bucket_calculate_dib(HashmapBase *h, unsigned idx, dib_raw_t raw_dib) { unsigned initial_bucket; if (raw_dib == DIB_RAW_FREE) return DIB_FREE; if (_likely_(raw_dib < DIB_RAW_OVERFLOW)) return raw_dib; /* * Having an overflow DIB value is very unlikely. The hash function * would have to be bad. For example, in a table of size 2^24 filled * to load factor 0.9 the maximum observed DIB is only about 60. * In theory (assuming I used Maxima correctly), for an infinite size * hash table with load factor 0.8 the probability of a given entry * having DIB > 40 is 1.9e-8. * This returns the correct DIB value by recomputing the hash value in * the unlikely case. XXX Hitting this case could be a hint to rehash. */ initial_bucket = bucket_hash(h, bucket_at(h, idx)->key); return bucket_distance(h, idx, initial_bucket); } static void bucket_set_dib(HashmapBase *h, unsigned idx, unsigned dib) { dib_raw_ptr(h)[idx] = dib != DIB_FREE ? MIN(dib, DIB_RAW_OVERFLOW) : DIB_RAW_FREE; } static unsigned skip_free_buckets(HashmapBase *h, unsigned idx) { dib_raw_t *dibs; dibs = dib_raw_ptr(h); for ( ; idx < n_buckets(h); idx++) if (dibs[idx] != DIB_RAW_FREE) return idx; return IDX_NIL; } static void bucket_mark_free(HashmapBase *h, unsigned idx) { memzero(bucket_at(h, idx), hashmap_type_info[h->type].entry_size); bucket_set_dib(h, idx, DIB_FREE); } static void bucket_move_entry(HashmapBase *h, struct swap_entries *swap, unsigned from, unsigned to) { struct hashmap_base_entry *e_from, *e_to; assert(from != to); e_from = bucket_at_virtual(h, swap, from); e_to = bucket_at_virtual(h, swap, to); memcpy(e_to, e_from, hashmap_type_info[h->type].entry_size); if (h->type == HASHMAP_TYPE_ORDERED) { OrderedHashmap *lh = (OrderedHashmap*) h; struct ordered_hashmap_entry *le, *le_to; le_to = (struct ordered_hashmap_entry*) e_to; if (le_to->iterate_next != IDX_NIL) { le = (struct ordered_hashmap_entry*) bucket_at_virtual(h, swap, le_to->iterate_next); le->iterate_previous = to; } if (le_to->iterate_previous != IDX_NIL) { le = (struct ordered_hashmap_entry*) bucket_at_virtual(h, swap, le_to->iterate_previous); le->iterate_next = to; } if (lh->iterate_list_head == from) lh->iterate_list_head = to; if (lh->iterate_list_tail == from) lh->iterate_list_tail = to; } } static unsigned next_idx(HashmapBase *h, unsigned idx) { return (idx + 1U) % n_buckets(h); } static unsigned prev_idx(HashmapBase *h, unsigned idx) { return (n_buckets(h) + idx - 1U) % n_buckets(h); } static void *entry_value(HashmapBase *h, struct hashmap_base_entry *e) { switch (h->type) { case HASHMAP_TYPE_PLAIN: case HASHMAP_TYPE_ORDERED: return ((struct plain_hashmap_entry*)e)->value; case HASHMAP_TYPE_SET: return (void*) e->key; default: assert_not_reached("Unknown hashmap type"); } } static void base_remove_entry(HashmapBase *h, unsigned idx) { unsigned left, right, prev, dib; dib_raw_t raw_dib, *dibs; dibs = dib_raw_ptr(h); assert(dibs[idx] != DIB_RAW_FREE); #ifdef ENABLE_DEBUG_HASHMAP h->debug.rem_count++; h->debug.last_rem_idx = idx; #endif left = idx; /* Find the stop bucket ("right"). It is either free or has DIB == 0. */ for (right = next_idx(h, left); ; right = next_idx(h, right)) { raw_dib = dibs[right]; if (raw_dib == 0 || raw_dib == DIB_RAW_FREE) break; /* The buckets are not supposed to be all occupied and with DIB > 0. * That would mean we could make everyone better off by shifting them * backward. This scenario is impossible. */ assert(left != right); } if (h->type == HASHMAP_TYPE_ORDERED) { OrderedHashmap *lh = (OrderedHashmap*) h; struct ordered_hashmap_entry *le = ordered_bucket_at(lh, idx); if (le->iterate_next != IDX_NIL) ordered_bucket_at(lh, le->iterate_next)->iterate_previous = le->iterate_previous; else lh->iterate_list_tail = le->iterate_previous; if (le->iterate_previous != IDX_NIL) ordered_bucket_at(lh, le->iterate_previous)->iterate_next = le->iterate_next; else lh->iterate_list_head = le->iterate_next; } /* Now shift all buckets in the interval (left, right) one step backwards */ for (prev = left, left = next_idx(h, left); left != right; prev = left, left = next_idx(h, left)) { dib = bucket_calculate_dib(h, left, dibs[left]); assert(dib != 0); bucket_move_entry(h, NULL, left, prev); bucket_set_dib(h, prev, dib - 1); } bucket_mark_free(h, prev); n_entries_dec(h); } #define remove_entry(h, idx) base_remove_entry(HASHMAP_BASE(h), idx) static unsigned hashmap_iterate_in_insertion_order(OrderedHashmap *h, Iterator *i) { struct ordered_hashmap_entry *e; unsigned idx; assert(h); assert(i); if (i->idx == IDX_NIL) goto at_end; if (i->idx == IDX_FIRST && h->iterate_list_head == IDX_NIL) goto at_end; if (i->idx == IDX_FIRST) { idx = h->iterate_list_head; e = ordered_bucket_at(h, idx); } else { idx = i->idx; e = ordered_bucket_at(h, idx); /* * We allow removing the current entry while iterating, but removal may cause * a backward shift. The next entry may thus move one bucket to the left. * To detect when it happens, we remember the key pointer of the entry we were * going to iterate next. If it does not match, there was a backward shift. */ if (e->p.b.key != i->next_key) { idx = prev_idx(HASHMAP_BASE(h), idx); e = ordered_bucket_at(h, idx); } assert(e->p.b.key == i->next_key); } #ifdef ENABLE_DEBUG_HASHMAP i->prev_idx = idx; #endif if (e->iterate_next != IDX_NIL) { struct ordered_hashmap_entry *n; i->idx = e->iterate_next; n = ordered_bucket_at(h, i->idx); i->next_key = n->p.b.key; } else i->idx = IDX_NIL; return idx; at_end: i->idx = IDX_NIL; return IDX_NIL; } static unsigned hashmap_iterate_in_internal_order(HashmapBase *h, Iterator *i) { unsigned idx; assert(h); assert(i); if (i->idx == IDX_NIL) goto at_end; if (i->idx == IDX_FIRST) { /* fast forward to the first occupied bucket */ if (h->has_indirect) { i->idx = skip_free_buckets(h, h->indirect.idx_lowest_entry); h->indirect.idx_lowest_entry = i->idx; } else i->idx = skip_free_buckets(h, 0); if (i->idx == IDX_NIL) goto at_end; } else { struct hashmap_base_entry *e; assert(i->idx > 0); e = bucket_at(h, i->idx); /* * We allow removing the current entry while iterating, but removal may cause * a backward shift. The next entry may thus move one bucket to the left. * To detect when it happens, we remember the key pointer of the entry we were * going to iterate next. If it does not match, there was a backward shift. */ if (e->key != i->next_key) e = bucket_at(h, --i->idx); assert(e->key == i->next_key); } idx = i->idx; #ifdef ENABLE_DEBUG_HASHMAP i->prev_idx = idx; #endif i->idx = skip_free_buckets(h, i->idx + 1); if (i->idx != IDX_NIL) i->next_key = bucket_at(h, i->idx)->key; else i->idx = IDX_NIL; return idx; at_end: i->idx = IDX_NIL; return IDX_NIL; } static unsigned hashmap_iterate_entry(HashmapBase *h, Iterator *i) { if (!h) { i->idx = IDX_NIL; return IDX_NIL; } #ifdef ENABLE_DEBUG_HASHMAP if (i->idx == IDX_FIRST) { i->put_count = h->debug.put_count; i->rem_count = h->debug.rem_count; } else { /* While iterating, must not add any new entries */ assert(i->put_count == h->debug.put_count); /* ... or remove entries other than the current one */ assert(i->rem_count == h->debug.rem_count || (i->rem_count == h->debug.rem_count - 1 && i->prev_idx == h->debug.last_rem_idx)); /* Reset our removals counter */ i->rem_count = h->debug.rem_count; } #endif return h->type == HASHMAP_TYPE_ORDERED ? hashmap_iterate_in_insertion_order((OrderedHashmap*) h, i) : hashmap_iterate_in_internal_order(h, i); } bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key) { struct hashmap_base_entry *e; void *data; unsigned idx; idx = hashmap_iterate_entry(h, i); if (idx == IDX_NIL) { if (value) *value = NULL; if (key) *key = NULL; return false; } e = bucket_at(h, idx); data = entry_value(h, e); if (value) *value = data; if (key) *key = e->key; return true; } bool set_iterate(Set *s, Iterator *i, void **value) { return internal_hashmap_iterate(HASHMAP_BASE(s), i, value, NULL); } #define HASHMAP_FOREACH_IDX(idx, h, i) \ for ((i) = ITERATOR_FIRST, (idx) = hashmap_iterate_entry((h), &(i)); \ (idx != IDX_NIL); \ (idx) = hashmap_iterate_entry((h), &(i))) static void reset_direct_storage(HashmapBase *h) { const struct hashmap_type_info *hi = &hashmap_type_info[h->type]; void *p; assert(!h->has_indirect); p = mempset(h->direct.storage, 0, hi->entry_size * hi->n_direct_buckets); memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets); } static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) { HashmapBase *h; const struct hashmap_type_info *hi = &hashmap_type_info[type]; bool use_pool; use_pool = is_main_thread(); h = use_pool ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size); if (!h) return NULL; h->type = type; h->from_pool = use_pool; h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops; if (type == HASHMAP_TYPE_ORDERED) { OrderedHashmap *lh = (OrderedHashmap*)h; lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL; } reset_direct_storage(h); if (!shared_hash_key_initialized) { random_bytes(shared_hash_key, sizeof(shared_hash_key)); shared_hash_key_initialized= true; } #ifdef ENABLE_DEBUG_HASHMAP h->debug.func = func; h->debug.file = file; h->debug.line = line; assert_se(pthread_mutex_lock(&hashmap_debug_list_mutex) == 0); LIST_PREPEND(debug_list, hashmap_debug_list, &h->debug); assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0); #endif return h; } Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) { return (Hashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS); } OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) { return (OrderedHashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS); } Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) { return (Set*) hashmap_base_new(hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS); } static int hashmap_base_ensure_allocated(HashmapBase **h, const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) { HashmapBase *q; assert(h); if (*h) return 0; q = hashmap_base_new(hash_ops, type HASHMAP_DEBUG_PASS_ARGS); if (!q) return -ENOMEM; *h = q; return 0; } int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) { return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS); } int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) { return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS); } int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) { return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS); } static void hashmap_free_no_clear(HashmapBase *h) { assert(!h->has_indirect); assert(!h->n_direct_entries); #ifdef ENABLE_DEBUG_HASHMAP assert_se(pthread_mutex_lock(&hashmap_debug_list_mutex) == 0); LIST_REMOVE(debug_list, hashmap_debug_list, &h->debug); assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0); #endif if (h->from_pool) mempool_free_tile(hashmap_type_info[h->type].mempool, h); else free(h); } HashmapBase *internal_hashmap_free(HashmapBase *h) { /* Free the hashmap, but nothing in it */ if (h) { internal_hashmap_clear(h); hashmap_free_no_clear(h); } return NULL; } HashmapBase *internal_hashmap_free_free(HashmapBase *h) { /* Free the hashmap and all data objects in it, but not the * keys */ if (h) { internal_hashmap_clear_free(h); hashmap_free_no_clear(h); } return NULL; } Hashmap *hashmap_free_free_free(Hashmap *h) { /* Free the hashmap and all data and key objects in it */ if (h) { hashmap_clear_free_free(h); hashmap_free_no_clear(HASHMAP_BASE(h)); } return NULL; } void internal_hashmap_clear(HashmapBase *h) { if (!h) return; if (h->has_indirect) { free(h->indirect.storage); h->has_indirect = false; } h->n_direct_entries = 0; reset_direct_storage(h); if (h->type == HASHMAP_TYPE_ORDERED) { OrderedHashmap *lh = (OrderedHashmap*) h; lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL; } } void internal_hashmap_clear_free(HashmapBase *h) { unsigned idx; if (!h) return; for (idx = skip_free_buckets(h, 0); idx != IDX_NIL; idx = skip_free_buckets(h, idx + 1)) free(entry_value(h, bucket_at(h, idx))); internal_hashmap_clear(h); } void hashmap_clear_free_free(Hashmap *h) { unsigned idx; if (!h) return; for (idx = skip_free_buckets(HASHMAP_BASE(h), 0); idx != IDX_NIL; idx = skip_free_buckets(HASHMAP_BASE(h), idx + 1)) { struct plain_hashmap_entry *e = plain_bucket_at(h, idx); free((void*)e->b.key); free(e->value); } internal_hashmap_clear(HASHMAP_BASE(h)); } static int resize_buckets(HashmapBase *h, unsigned entries_add); /* * Finds an empty bucket to put an entry into, starting the scan at 'idx'. * Performs Robin Hood swaps as it goes. The entry to put must be placed * by the caller into swap slot IDX_PUT. * If used for in-place resizing, may leave a displaced entry in swap slot * IDX_PUT. Caller must rehash it next. * Returns: true if it left a displaced entry to rehash next in IDX_PUT, * false otherwise. */ static bool hashmap_put_robin_hood(HashmapBase *h, unsigned idx, struct swap_entries *swap) { dib_raw_t raw_dib, *dibs; unsigned dib, distance; #ifdef ENABLE_DEBUG_HASHMAP h->debug.put_count++; #endif dibs = dib_raw_ptr(h); for (distance = 0; ; distance++) { raw_dib = dibs[idx]; if (raw_dib == DIB_RAW_FREE || raw_dib == DIB_RAW_REHASH) { if (raw_dib == DIB_RAW_REHASH) bucket_move_entry(h, swap, idx, IDX_TMP); if (h->has_indirect && h->indirect.idx_lowest_entry > idx) h->indirect.idx_lowest_entry = idx; bucket_set_dib(h, idx, distance); bucket_move_entry(h, swap, IDX_PUT, idx); if (raw_dib == DIB_RAW_REHASH) { bucket_move_entry(h, swap, IDX_TMP, IDX_PUT); return true; } return false; } dib = bucket_calculate_dib(h, idx, raw_dib); if (dib < distance) { /* Found a wealthier entry. Go Robin Hood! */ bucket_set_dib(h, idx, distance); /* swap the entries */ bucket_move_entry(h, swap, idx, IDX_TMP); bucket_move_entry(h, swap, IDX_PUT, idx); bucket_move_entry(h, swap, IDX_TMP, IDX_PUT); distance = dib; } idx = next_idx(h, idx); } } /* * Puts an entry into a hashmap, boldly - no check whether key already exists. * The caller must place the entry (only its key and value, not link indexes) * in swap slot IDX_PUT. * Caller must ensure: the key does not exist yet in the hashmap. * that resize is not needed if !may_resize. * Returns: 1 if entry was put successfully. * -ENOMEM if may_resize==true and resize failed with -ENOMEM. * Cannot return -ENOMEM if !may_resize. */ static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx, struct swap_entries *swap, bool may_resize) { struct ordered_hashmap_entry *new_entry; int r; assert(idx < n_buckets(h)); new_entry = bucket_at_swap(swap, IDX_PUT); if (may_resize) { r = resize_buckets(h, 1); if (r < 0) return r; if (r > 0) idx = bucket_hash(h, new_entry->p.b.key); } assert(n_entries(h) < n_buckets(h)); if (h->type == HASHMAP_TYPE_ORDERED) { OrderedHashmap *lh = (OrderedHashmap*) h; new_entry->iterate_next = IDX_NIL; new_entry->iterate_previous = lh->iterate_list_tail; if (lh->iterate_list_tail != IDX_NIL) { struct ordered_hashmap_entry *old_tail; old_tail = ordered_bucket_at(lh, lh->iterate_list_tail); assert(old_tail->iterate_next == IDX_NIL); old_tail->iterate_next = IDX_PUT; } lh->iterate_list_tail = IDX_PUT; if (lh->iterate_list_head == IDX_NIL) lh->iterate_list_head = IDX_PUT; } assert_se(hashmap_put_robin_hood(h, idx, swap) == false); n_entries_inc(h); #ifdef ENABLE_DEBUG_HASHMAP h->debug.max_entries = MAX(h->debug.max_entries, n_entries(h)); #endif return 1; } #define hashmap_put_boldly(h, idx, swap, may_resize) \ hashmap_base_put_boldly(HASHMAP_BASE(h), idx, swap, may_resize) /* * Returns 0 if resize is not needed. * 1 if successfully resized. * -ENOMEM on allocation failure. */ static int resize_buckets(HashmapBase *h, unsigned entries_add) { struct swap_entries swap; char *new_storage; dib_raw_t *old_dibs, *new_dibs; const struct hashmap_type_info *hi; unsigned idx, optimal_idx; unsigned old_n_buckets, new_n_buckets, n_rehashed, new_n_entries; uint8_t new_shift; bool rehash_next; assert(h); hi = &hashmap_type_info[h->type]; new_n_entries = n_entries(h) + entries_add; /* overflow? */ if (_unlikely_(new_n_entries < entries_add)) return -ENOMEM; /* For direct storage we allow 100% load, because it's tiny. */ if (!h->has_indirect && new_n_entries <= hi->n_direct_buckets) return 0; /* * Load factor = n/m = 1 - (1/INV_KEEP_FREE). * From it follows: m = n + n/(INV_KEEP_FREE - 1) */ new_n_buckets = new_n_entries + new_n_entries / (INV_KEEP_FREE - 1); /* overflow? */ if (_unlikely_(new_n_buckets < new_n_entries)) return -ENOMEM; if (_unlikely_(new_n_buckets > UINT_MAX / (hi->entry_size + sizeof(dib_raw_t)))) return -ENOMEM; old_n_buckets = n_buckets(h); if (_likely_(new_n_buckets <= old_n_buckets)) return 0; new_shift = log2u_round_up(MAX( new_n_buckets * (hi->entry_size + sizeof(dib_raw_t)), 2 * sizeof(struct direct_storage))); /* Realloc storage (buckets and DIB array). */ new_storage = realloc(h->has_indirect ? h->indirect.storage : NULL, 1U << new_shift); if (!new_storage) return -ENOMEM; /* Must upgrade direct to indirect storage. */ if (!h->has_indirect) { memcpy(new_storage, h->direct.storage, old_n_buckets * (hi->entry_size + sizeof(dib_raw_t))); h->indirect.n_entries = h->n_direct_entries; h->indirect.idx_lowest_entry = 0; h->n_direct_entries = 0; } /* Get a new hash key. If we've just upgraded to indirect storage, * allow reusing a previously generated key. It's still a different key * from the shared one that we used for direct storage. */ get_hash_key(h->indirect.hash_key, !h->has_indirect); h->has_indirect = true; h->indirect.storage = new_storage; h->indirect.n_buckets = (1U << new_shift) / (hi->entry_size + sizeof(dib_raw_t)); old_dibs = (dib_raw_t*)(new_storage + hi->entry_size * old_n_buckets); new_dibs = dib_raw_ptr(h); /* * Move the DIB array to the new place, replacing valid DIB values with * DIB_RAW_REHASH to indicate all of the used buckets need rehashing. * Note: Overlap is not possible, because we have at least doubled the * number of buckets and dib_raw_t is smaller than any entry type. */ for (idx = 0; idx < old_n_buckets; idx++) { assert(old_dibs[idx] != DIB_RAW_REHASH); new_dibs[idx] = old_dibs[idx] == DIB_RAW_FREE ? DIB_RAW_FREE : DIB_RAW_REHASH; } /* Zero the area of newly added entries (including the old DIB area) */ memzero(bucket_at(h, old_n_buckets), (n_buckets(h) - old_n_buckets) * hi->entry_size); /* The upper half of the new DIB array needs initialization */ memset(&new_dibs[old_n_buckets], DIB_RAW_INIT, (n_buckets(h) - old_n_buckets) * sizeof(dib_raw_t)); /* Rehash entries that need it */ n_rehashed = 0; for (idx = 0; idx < old_n_buckets; idx++) { if (new_dibs[idx] != DIB_RAW_REHASH) continue; optimal_idx = bucket_hash(h, bucket_at(h, idx)->key); /* * Not much to do if by luck the entry hashes to its current * location. Just set its DIB. */ if (optimal_idx == idx) { new_dibs[idx] = 0; n_rehashed++; continue; } new_dibs[idx] = DIB_RAW_FREE; bucket_move_entry(h, &swap, idx, IDX_PUT); /* bucket_move_entry does not clear the source */ memzero(bucket_at(h, idx), hi->entry_size); do { /* * Find the new bucket for the current entry. This may make * another entry homeless and load it into IDX_PUT. */ rehash_next = hashmap_put_robin_hood(h, optimal_idx, &swap); n_rehashed++; /* Did the current entry displace another one? */ if (rehash_next) optimal_idx = bucket_hash(h, bucket_at_swap(&swap, IDX_PUT)->p.b.key); } while (rehash_next); } assert(n_rehashed == n_entries(h)); return 1; } /* * Finds an entry with a matching key * Returns: index of the found entry, or IDX_NIL if not found. */ static unsigned base_bucket_scan(HashmapBase *h, unsigned idx, const void *key) { struct hashmap_base_entry *e; unsigned dib, distance; dib_raw_t *dibs = dib_raw_ptr(h); assert(idx < n_buckets(h)); for (distance = 0; ; distance++) { if (dibs[idx] == DIB_RAW_FREE) return IDX_NIL; dib = bucket_calculate_dib(h, idx, dibs[idx]); if (dib < distance) return IDX_NIL; if (dib == distance) { e = bucket_at(h, idx); if (h->hash_ops->compare(e->key, key) == 0) return idx; } idx = next_idx(h, idx); } } #define bucket_scan(h, idx, key) base_bucket_scan(HASHMAP_BASE(h), idx, key) int hashmap_put(Hashmap *h, const void *key, void *value) { struct swap_entries swap; struct plain_hashmap_entry *e; unsigned hash, idx; assert(h); hash = bucket_hash(h, key); idx = bucket_scan(h, hash, key); if (idx != IDX_NIL) { e = plain_bucket_at(h, idx); if (e->value == value) return 0; return -EEXIST; } e = &bucket_at_swap(&swap, IDX_PUT)->p; e->b.key = key; e->value = value; return hashmap_put_boldly(h, hash, &swap, true); } int set_put(Set *s, const void *key) { struct swap_entries swap; struct hashmap_base_entry *e; unsigned hash, idx; assert(s); hash = bucket_hash(s, key); idx = bucket_scan(s, hash, key); if (idx != IDX_NIL) return 0; e = &bucket_at_swap(&swap, IDX_PUT)->p.b; e->key = key; return hashmap_put_boldly(s, hash, &swap, true); } int hashmap_replace(Hashmap *h, const void *key, void *value) { struct swap_entries swap; struct plain_hashmap_entry *e; unsigned hash, idx; assert(h); hash = bucket_hash(h, key); idx = bucket_scan(h, hash, key); if (idx != IDX_NIL) { e = plain_bucket_at(h, idx); #ifdef ENABLE_DEBUG_HASHMAP /* Although the key is equal, the key pointer may have changed, * and this would break our assumption for iterating. So count * this operation as incompatible with iteration. */ if (e->b.key != key) { h->b.debug.put_count++; h->b.debug.rem_count++; h->b.debug.last_rem_idx = idx; } #endif e->b.key = key; e->value = value; return 0; } e = &bucket_at_swap(&swap, IDX_PUT)->p; e->b.key = key; e->value = value; return hashmap_put_boldly(h, hash, &swap, true); } int hashmap_update(Hashmap *h, const void *key, void *value) { struct plain_hashmap_entry *e; unsigned hash, idx; assert(h); hash = bucket_hash(h, key); idx = bucket_scan(h, hash, key); if (idx == IDX_NIL) return -ENOENT; e = plain_bucket_at(h, idx); e->value = value; return 0; } void *internal_hashmap_get(HashmapBase *h, const void *key) { struct hashmap_base_entry *e; unsigned hash, idx; if (!h) return NULL; hash = bucket_hash(h, key); idx = bucket_scan(h, hash, key); if (idx == IDX_NIL) return NULL; e = bucket_at(h, idx); return entry_value(h, e); } void *hashmap_get2(Hashmap *h, const void *key, void **key2) { struct plain_hashmap_entry *e; unsigned hash, idx; if (!h) return NULL; hash = bucket_hash(h, key); idx = bucket_scan(h, hash, key); if (idx == IDX_NIL) return NULL; e = plain_bucket_at(h, idx); if (key2) *key2 = (void*) e->b.key; return e->value; } bool internal_hashmap_contains(HashmapBase *h, const void *key) { unsigned hash; if (!h) return false; hash = bucket_hash(h, key); return bucket_scan(h, hash, key) != IDX_NIL; } void *internal_hashmap_remove(HashmapBase *h, const void *key) { struct hashmap_base_entry *e; unsigned hash, idx; void *data; if (!h) return NULL; hash = bucket_hash(h, key); idx = bucket_scan(h, hash, key); if (idx == IDX_NIL) return NULL; e = bucket_at(h, idx); data = entry_value(h, e); remove_entry(h, idx); return data; } void *hashmap_remove2(Hashmap *h, const void *key, void **rkey) { struct plain_hashmap_entry *e; unsigned hash, idx; void *data; if (!h) { if (rkey) *rkey = NULL; return NULL; } hash = bucket_hash(h, key); idx = bucket_scan(h, hash, key); if (idx == IDX_NIL) { if (rkey) *rkey = NULL; return NULL; } e = plain_bucket_at(h, idx); data = e->value; if (rkey) *rkey = (void*) e->b.key; remove_entry(h, idx); return data; } int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value) { struct swap_entries swap; struct plain_hashmap_entry *e; unsigned old_hash, new_hash, idx; if (!h) return -ENOENT; old_hash = bucket_hash(h, old_key); idx = bucket_scan(h, old_hash, old_key); if (idx == IDX_NIL) return -ENOENT; new_hash = bucket_hash(h, new_key); if (bucket_scan(h, new_hash, new_key) != IDX_NIL) return -EEXIST; remove_entry(h, idx); e = &bucket_at_swap(&swap, IDX_PUT)->p; e->b.key = new_key; e->value = value; assert_se(hashmap_put_boldly(h, new_hash, &swap, false) == 1); return 0; } int set_remove_and_put(Set *s, const void *old_key, const void *new_key) { struct swap_entries swap; struct hashmap_base_entry *e; unsigned old_hash, new_hash, idx; if (!s) return -ENOENT; old_hash = bucket_hash(s, old_key); idx = bucket_scan(s, old_hash, old_key); if (idx == IDX_NIL) return -ENOENT; new_hash = bucket_hash(s, new_key); if (bucket_scan(s, new_hash, new_key) != IDX_NIL) return -EEXIST; remove_entry(s, idx); e = &bucket_at_swap(&swap, IDX_PUT)->p.b; e->key = new_key; assert_se(hashmap_put_boldly(s, new_hash, &swap, false) == 1); return 0; } int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value) { struct swap_entries swap; struct plain_hashmap_entry *e; unsigned old_hash, new_hash, idx_old, idx_new; if (!h) return -ENOENT; old_hash = bucket_hash(h, old_key); idx_old = bucket_scan(h, old_hash, old_key); if (idx_old == IDX_NIL) return -ENOENT; old_key = bucket_at(HASHMAP_BASE(h), idx_old)->key; new_hash = bucket_hash(h, new_key); idx_new = bucket_scan(h, new_hash, new_key); if (idx_new != IDX_NIL) if (idx_old != idx_new) { remove_entry(h, idx_new); /* Compensate for a possible backward shift. */ if (old_key != bucket_at(HASHMAP_BASE(h), idx_old)->key) idx_old = prev_idx(HASHMAP_BASE(h), idx_old); assert(old_key == bucket_at(HASHMAP_BASE(h), idx_old)->key); } remove_entry(h, idx_old); e = &bucket_at_swap(&swap, IDX_PUT)->p; e->b.key = new_key; e->value = value; assert_se(hashmap_put_boldly(h, new_hash, &swap, false) == 1); return 0; } void *hashmap_remove_value(Hashmap *h, const void *key, void *value) { struct plain_hashmap_entry *e; unsigned hash, idx; if (!h) return NULL; hash = bucket_hash(h, key); idx = bucket_scan(h, hash, key); if (idx == IDX_NIL) return NULL; e = plain_bucket_at(h, idx); if (e->value != value) return NULL; remove_entry(h, idx); return value; } static unsigned find_first_entry(HashmapBase *h) { Iterator i = ITERATOR_FIRST; if (!h || !n_entries(h)) return IDX_NIL; return hashmap_iterate_entry(h, &i); } void *internal_hashmap_first(HashmapBase *h) { unsigned idx; idx = find_first_entry(h); if (idx == IDX_NIL) return NULL; return entry_value(h, bucket_at(h, idx)); } void *internal_hashmap_first_key(HashmapBase *h) { struct hashmap_base_entry *e; unsigned idx; idx = find_first_entry(h); if (idx == IDX_NIL) return NULL; e = bucket_at(h, idx); return (void*) e->key; } void *internal_hashmap_steal_first(HashmapBase *h) { struct hashmap_base_entry *e; void *data; unsigned idx; idx = find_first_entry(h); if (idx == IDX_NIL) return NULL; e = bucket_at(h, idx); data = entry_value(h, e); remove_entry(h, idx); return data; } void *internal_hashmap_steal_first_key(HashmapBase *h) { struct hashmap_base_entry *e; void *key; unsigned idx; idx = find_first_entry(h); if (idx == IDX_NIL) return NULL; e = bucket_at(h, idx); key = (void*) e->key; remove_entry(h, idx); return key; } unsigned internal_hashmap_size(HashmapBase *h) { if (!h) return 0; return n_entries(h); } unsigned internal_hashmap_buckets(HashmapBase *h) { if (!h) return 0; return n_buckets(h); } int internal_hashmap_merge(Hashmap *h, Hashmap *other) { Iterator i; unsigned idx; assert(h); HASHMAP_FOREACH_IDX(idx, HASHMAP_BASE(other), i) { struct plain_hashmap_entry *pe = plain_bucket_at(other, idx); int r; r = hashmap_put(h, pe->b.key, pe->value); if (r < 0 && r != -EEXIST) return r; } return 0; } int set_merge(Set *s, Set *other) { Iterator i; unsigned idx; assert(s); HASHMAP_FOREACH_IDX(idx, HASHMAP_BASE(other), i) { struct set_entry *se = set_bucket_at(other, idx); int r; r = set_put(s, se->b.key); if (r < 0) return r; } return 0; } int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add) { int r; assert(h); r = resize_buckets(h, entries_add); if (r < 0) return r; return 0; } /* * The same as hashmap_merge(), but every new item from other is moved to h. * Keys already in h are skipped and stay in other. * Returns: 0 on success. * -ENOMEM on alloc failure, in which case no move has been done. */ int internal_hashmap_move(HashmapBase *h, HashmapBase *other) { struct swap_entries swap; struct hashmap_base_entry *e, *n; Iterator i; unsigned idx; int r; assert(h); if (!other) return 0; assert(other->type == h->type); /* * This reserves buckets for the worst case, where none of other's * entries are yet present in h. This is preferable to risking * an allocation failure in the middle of the moving and having to * rollback or return a partial result. */ r = resize_buckets(h, n_entries(other)); if (r < 0) return r; HASHMAP_FOREACH_IDX(idx, other, i) { unsigned h_hash; e = bucket_at(other, idx); h_hash = bucket_hash(h, e->key); if (bucket_scan(h, h_hash, e->key) != IDX_NIL) continue; n = &bucket_at_swap(&swap, IDX_PUT)->p.b; n->key = e->key; if (h->type != HASHMAP_TYPE_SET) ((struct plain_hashmap_entry*) n)->value = ((struct plain_hashmap_entry*) e)->value; assert_se(hashmap_put_boldly(h, h_hash, &swap, false) == 1); remove_entry(other, idx); } return 0; } int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key) { struct swap_entries swap; unsigned h_hash, other_hash, idx; struct hashmap_base_entry *e, *n; int r; assert(h); h_hash = bucket_hash(h, key); if (bucket_scan(h, h_hash, key) != IDX_NIL) return -EEXIST; if (!other) return -ENOENT; assert(other->type == h->type); other_hash = bucket_hash(other, key); idx = bucket_scan(other, other_hash, key); if (idx == IDX_NIL) return -ENOENT; e = bucket_at(other, idx); n = &bucket_at_swap(&swap, IDX_PUT)->p.b; n->key = e->key; if (h->type != HASHMAP_TYPE_SET) ((struct plain_hashmap_entry*) n)->value = ((struct plain_hashmap_entry*) e)->value; r = hashmap_put_boldly(h, h_hash, &swap, true); if (r < 0) return r; remove_entry(other, idx); return 0; } HashmapBase *internal_hashmap_copy(HashmapBase *h) { HashmapBase *copy; int r; assert(h); copy = hashmap_base_new(h->hash_ops, h->type HASHMAP_DEBUG_SRC_ARGS); if (!copy) return NULL; switch (h->type) { case HASHMAP_TYPE_PLAIN: case HASHMAP_TYPE_ORDERED: r = hashmap_merge((Hashmap*)copy, (Hashmap*)h); break; case HASHMAP_TYPE_SET: r = set_merge((Set*)copy, (Set*)h); break; default: assert_not_reached("Unknown hashmap type"); } if (r < 0) { internal_hashmap_free(copy); return NULL; } return copy; } char **internal_hashmap_get_strv(HashmapBase *h) { char **sv; Iterator i; unsigned idx, n; sv = new(char*, n_entries(h)+1); if (!sv) return NULL; n = 0; HASHMAP_FOREACH_IDX(idx, h, i) sv[n++] = entry_value(h, bucket_at(h, idx)); sv[n] = NULL; return sv; } void *ordered_hashmap_next(OrderedHashmap *h, const void *key) { struct ordered_hashmap_entry *e; unsigned hash, idx; if (!h) return NULL; hash = bucket_hash(h, key); idx = bucket_scan(h, hash, key); if (idx == IDX_NIL) return NULL; e = ordered_bucket_at(h, idx); if (e->iterate_next == IDX_NIL) return NULL; return ordered_bucket_at(h, e->iterate_next)->p.value; } int set_consume(Set *s, void *value) { int r; r = set_put(s, value); if (r <= 0) free(value); return r; } int set_put_strdup(Set *s, const char *p) { char *c; int r; assert(s); assert(p); c = strdup(p); if (!c) return -ENOMEM; r = set_consume(s, c); if (r == -EEXIST) return 0; return r; } int set_put_strdupv(Set *s, char **l) { int n = 0, r; char **i; STRV_FOREACH(i, l) { r = set_put_strdup(s, *i); if (r < 0) return r; n += r; } return n; } systemd-229/src/basic/hashmap.h000066400000000000000000000367361265713322000165420ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2014 Michal Schmidt systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "hash-funcs.h" #include "macro.h" #include "util.h" /* * A hash table implementation. As a minor optimization a NULL hashmap object * will be treated as empty hashmap for all read operations. That way it is not * necessary to instantiate an object for each Hashmap use. * * If ENABLE_DEBUG_HASHMAP is defined (by configuring with --enable-debug=hashmap), * the implemention will: * - store extra data for debugging and statistics (see tools/gdb-sd_dump_hashmaps.py) * - perform extra checks for invalid use of iterators */ #define HASH_KEY_SIZE 16 /* The base type for all hashmap and set types. Many functions in the * implementation take (HashmapBase*) parameters and are run-time polymorphic, * though the API is not meant to be polymorphic (do not call functions * internal_*() directly). */ typedef struct HashmapBase HashmapBase; /* Specific hashmap/set types */ typedef struct Hashmap Hashmap; /* Maps keys to values */ typedef struct OrderedHashmap OrderedHashmap; /* Like Hashmap, but also remembers entry insertion order */ typedef struct Set Set; /* Stores just keys */ /* Ideally the Iterator would be an opaque struct, but it is instantiated * by hashmap users, so the definition has to be here. Do not use its fields * directly. */ typedef struct { unsigned idx; /* index of an entry to be iterated next */ const void *next_key; /* expected value of that entry's key pointer */ #ifdef ENABLE_DEBUG_HASHMAP unsigned put_count; /* hashmap's put_count recorded at start of iteration */ unsigned rem_count; /* hashmap's rem_count in previous iteration */ unsigned prev_idx; /* idx in previous iteration */ #endif } Iterator; #define _IDX_ITERATOR_FIRST (UINT_MAX - 1) #define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL }) /* Macros for type checking */ #define PTR_COMPATIBLE_WITH_HASHMAP_BASE(h) \ (__builtin_types_compatible_p(typeof(h), HashmapBase*) || \ __builtin_types_compatible_p(typeof(h), Hashmap*) || \ __builtin_types_compatible_p(typeof(h), OrderedHashmap*) || \ __builtin_types_compatible_p(typeof(h), Set*)) #define PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h) \ (__builtin_types_compatible_p(typeof(h), Hashmap*) || \ __builtin_types_compatible_p(typeof(h), OrderedHashmap*)) \ #define HASHMAP_BASE(h) \ __builtin_choose_expr(PTR_COMPATIBLE_WITH_HASHMAP_BASE(h), \ (HashmapBase*)(h), \ (void)0) #define PLAIN_HASHMAP(h) \ __builtin_choose_expr(PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h), \ (Hashmap*)(h), \ (void)0) #ifdef ENABLE_DEBUG_HASHMAP # define HASHMAP_DEBUG_PARAMS , const char *func, const char *file, int line # define HASHMAP_DEBUG_SRC_ARGS , __func__, __FILE__, __LINE__ # define HASHMAP_DEBUG_PASS_ARGS , func, file, line #else # define HASHMAP_DEBUG_PARAMS # define HASHMAP_DEBUG_SRC_ARGS # define HASHMAP_DEBUG_PASS_ARGS #endif Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); #define hashmap_new(ops) internal_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) #define ordered_hashmap_new(ops) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) HashmapBase *internal_hashmap_free(HashmapBase *h); static inline Hashmap *hashmap_free(Hashmap *h) { return (void*)internal_hashmap_free(HASHMAP_BASE(h)); } static inline OrderedHashmap *ordered_hashmap_free(OrderedHashmap *h) { return (void*)internal_hashmap_free(HASHMAP_BASE(h)); } HashmapBase *internal_hashmap_free_free(HashmapBase *h); static inline Hashmap *hashmap_free_free(Hashmap *h) { return (void*)internal_hashmap_free_free(HASHMAP_BASE(h)); } static inline OrderedHashmap *ordered_hashmap_free_free(OrderedHashmap *h) { return (void*)internal_hashmap_free_free(HASHMAP_BASE(h)); } Hashmap *hashmap_free_free_free(Hashmap *h); static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h) { return (void*)hashmap_free_free_free(PLAIN_HASHMAP(h)); } HashmapBase *internal_hashmap_copy(HashmapBase *h); static inline Hashmap *hashmap_copy(Hashmap *h) { return (Hashmap*) internal_hashmap_copy(HASHMAP_BASE(h)); } static inline OrderedHashmap *ordered_hashmap_copy(OrderedHashmap *h) { return (OrderedHashmap*) internal_hashmap_copy(HASHMAP_BASE(h)); } int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); #define hashmap_ensure_allocated(h, ops) internal_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) #define ordered_hashmap_ensure_allocated(h, ops) internal_ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) int hashmap_put(Hashmap *h, const void *key, void *value); static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *value) { return hashmap_put(PLAIN_HASHMAP(h), key, value); } int hashmap_update(Hashmap *h, const void *key, void *value); static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) { return hashmap_update(PLAIN_HASHMAP(h), key, value); } int hashmap_replace(Hashmap *h, const void *key, void *value); static inline int ordered_hashmap_replace(OrderedHashmap *h, const void *key, void *value) { return hashmap_replace(PLAIN_HASHMAP(h), key, value); } void *internal_hashmap_get(HashmapBase *h, const void *key); static inline void *hashmap_get(Hashmap *h, const void *key) { return internal_hashmap_get(HASHMAP_BASE(h), key); } static inline void *ordered_hashmap_get(OrderedHashmap *h, const void *key) { return internal_hashmap_get(HASHMAP_BASE(h), key); } void *hashmap_get2(Hashmap *h, const void *key, void **rkey); static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, void **rkey) { return hashmap_get2(PLAIN_HASHMAP(h), key, rkey); } bool internal_hashmap_contains(HashmapBase *h, const void *key); static inline bool hashmap_contains(Hashmap *h, const void *key) { return internal_hashmap_contains(HASHMAP_BASE(h), key); } static inline bool ordered_hashmap_contains(OrderedHashmap *h, const void *key) { return internal_hashmap_contains(HASHMAP_BASE(h), key); } void *internal_hashmap_remove(HashmapBase *h, const void *key); static inline void *hashmap_remove(Hashmap *h, const void *key) { return internal_hashmap_remove(HASHMAP_BASE(h), key); } static inline void *ordered_hashmap_remove(OrderedHashmap *h, const void *key) { return internal_hashmap_remove(HASHMAP_BASE(h), key); } void *hashmap_remove2(Hashmap *h, const void *key, void **rkey); static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key, void **rkey) { return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey); } void *hashmap_remove_value(Hashmap *h, const void *key, void *value); static inline void *ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) { return hashmap_remove_value(PLAIN_HASHMAP(h), key, value); } int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value); static inline int ordered_hashmap_remove_and_put(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) { return hashmap_remove_and_put(PLAIN_HASHMAP(h), old_key, new_key, value); } int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value); static inline int ordered_hashmap_remove_and_replace(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) { return hashmap_remove_and_replace(PLAIN_HASHMAP(h), old_key, new_key, value); } /* Since merging data from a OrderedHashmap into a Hashmap or vice-versa * should just work, allow this by having looser type-checking here. */ int internal_hashmap_merge(Hashmap *h, Hashmap *other); #define hashmap_merge(h, other) internal_hashmap_merge(PLAIN_HASHMAP(h), PLAIN_HASHMAP(other)) #define ordered_hashmap_merge(h, other) hashmap_merge(h, other) int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add); static inline int hashmap_reserve(Hashmap *h, unsigned entries_add) { return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add); } static inline int ordered_hashmap_reserve(OrderedHashmap *h, unsigned entries_add) { return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add); } int internal_hashmap_move(HashmapBase *h, HashmapBase *other); /* Unlike hashmap_merge, hashmap_move does not allow mixing the types. */ static inline int hashmap_move(Hashmap *h, Hashmap *other) { return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other)); } static inline int ordered_hashmap_move(OrderedHashmap *h, OrderedHashmap *other) { return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other)); } int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key); static inline int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) { return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key); } static inline int ordered_hashmap_move_one(OrderedHashmap *h, OrderedHashmap *other, const void *key) { return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key); } unsigned internal_hashmap_size(HashmapBase *h) _pure_; static inline unsigned hashmap_size(Hashmap *h) { return internal_hashmap_size(HASHMAP_BASE(h)); } static inline unsigned ordered_hashmap_size(OrderedHashmap *h) { return internal_hashmap_size(HASHMAP_BASE(h)); } static inline bool hashmap_isempty(Hashmap *h) { return hashmap_size(h) == 0; } static inline bool ordered_hashmap_isempty(OrderedHashmap *h) { return ordered_hashmap_size(h) == 0; } unsigned internal_hashmap_buckets(HashmapBase *h) _pure_; static inline unsigned hashmap_buckets(Hashmap *h) { return internal_hashmap_buckets(HASHMAP_BASE(h)); } static inline unsigned ordered_hashmap_buckets(OrderedHashmap *h) { return internal_hashmap_buckets(HASHMAP_BASE(h)); } bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key); static inline bool hashmap_iterate(Hashmap *h, Iterator *i, void **value, const void **key) { return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key); } static inline bool ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, void **value, const void **key) { return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key); } void internal_hashmap_clear(HashmapBase *h); static inline void hashmap_clear(Hashmap *h) { internal_hashmap_clear(HASHMAP_BASE(h)); } static inline void ordered_hashmap_clear(OrderedHashmap *h) { internal_hashmap_clear(HASHMAP_BASE(h)); } void internal_hashmap_clear_free(HashmapBase *h); static inline void hashmap_clear_free(Hashmap *h) { internal_hashmap_clear_free(HASHMAP_BASE(h)); } static inline void ordered_hashmap_clear_free(OrderedHashmap *h) { internal_hashmap_clear_free(HASHMAP_BASE(h)); } void hashmap_clear_free_free(Hashmap *h); static inline void ordered_hashmap_clear_free_free(OrderedHashmap *h) { hashmap_clear_free_free(PLAIN_HASHMAP(h)); } /* * Note about all *_first*() functions * * For plain Hashmaps and Sets the order of entries is undefined. * The functions find whatever entry is first in the implementation * internal order. * * Only for OrderedHashmaps the order is well defined and finding * the first entry is O(1). */ void *internal_hashmap_steal_first(HashmapBase *h); static inline void *hashmap_steal_first(Hashmap *h) { return internal_hashmap_steal_first(HASHMAP_BASE(h)); } static inline void *ordered_hashmap_steal_first(OrderedHashmap *h) { return internal_hashmap_steal_first(HASHMAP_BASE(h)); } void *internal_hashmap_steal_first_key(HashmapBase *h); static inline void *hashmap_steal_first_key(Hashmap *h) { return internal_hashmap_steal_first_key(HASHMAP_BASE(h)); } static inline void *ordered_hashmap_steal_first_key(OrderedHashmap *h) { return internal_hashmap_steal_first_key(HASHMAP_BASE(h)); } void *internal_hashmap_first_key(HashmapBase *h) _pure_; static inline void *hashmap_first_key(Hashmap *h) { return internal_hashmap_first_key(HASHMAP_BASE(h)); } static inline void *ordered_hashmap_first_key(OrderedHashmap *h) { return internal_hashmap_first_key(HASHMAP_BASE(h)); } void *internal_hashmap_first(HashmapBase *h) _pure_; static inline void *hashmap_first(Hashmap *h) { return internal_hashmap_first(HASHMAP_BASE(h)); } static inline void *ordered_hashmap_first(OrderedHashmap *h) { return internal_hashmap_first(HASHMAP_BASE(h)); } /* no hashmap_next */ void *ordered_hashmap_next(OrderedHashmap *h, const void *key); char **internal_hashmap_get_strv(HashmapBase *h); static inline char **hashmap_get_strv(Hashmap *h) { return internal_hashmap_get_strv(HASHMAP_BASE(h)); } static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) { return internal_hashmap_get_strv(HASHMAP_BASE(h)); } /* * Hashmaps are iterated in unpredictable order. * OrderedHashmaps are an exception to this. They are iterated in the order * the entries were inserted. * It is safe to remove the current entry. */ #define HASHMAP_FOREACH(e, h, i) \ for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), NULL); ) #define ORDERED_HASHMAP_FOREACH(e, h, i) \ for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), NULL); ) #define HASHMAP_FOREACH_KEY(e, k, h, i) \ for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) #define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \ for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free_free); DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free); DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free); DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_free); #define _cleanup_hashmap_free_ _cleanup_(hashmap_freep) #define _cleanup_hashmap_free_free_ _cleanup_(hashmap_free_freep) #define _cleanup_hashmap_free_free_free_ _cleanup_(hashmap_free_free_freep) #define _cleanup_ordered_hashmap_free_ _cleanup_(ordered_hashmap_freep) #define _cleanup_ordered_hashmap_free_free_ _cleanup_(ordered_hashmap_free_freep) #define _cleanup_ordered_hashmap_free_free_free_ _cleanup_(ordered_hashmap_free_free_freep) systemd-229/src/basic/hexdecoct.c000066400000000000000000000534121265713322000170500ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "hexdecoct.h" #include "macro.h" char octchar(int x) { return '0' + (x & 7); } int unoctchar(char c) { if (c >= '0' && c <= '7') return c - '0'; return -EINVAL; } char decchar(int x) { return '0' + (x % 10); } int undecchar(char c) { if (c >= '0' && c <= '9') return c - '0'; return -EINVAL; } char hexchar(int x) { static const char table[16] = "0123456789abcdef"; return table[x & 15]; } int unhexchar(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -EINVAL; } char *hexmem(const void *p, size_t l) { char *r, *z; const uint8_t *x; z = r = malloc(l * 2 + 1); if (!r) return NULL; for (x = p; x < (const uint8_t*) p + l; x++) { *(z++) = hexchar(*x >> 4); *(z++) = hexchar(*x & 15); } *z = 0; return r; } int unhexmem(const char *p, size_t l, void **mem, size_t *len) { _cleanup_free_ uint8_t *r = NULL; uint8_t *z; const char *x; assert(mem); assert(len); assert(p); z = r = malloc((l + 1) / 2 + 1); if (!r) return -ENOMEM; for (x = p; x < p + l; x += 2) { int a, b; a = unhexchar(x[0]); if (a < 0) return a; else if (x+1 < p + l) { b = unhexchar(x[1]); if (b < 0) return b; } else b = 0; *(z++) = (uint8_t) a << 4 | (uint8_t) b; } *z = 0; *mem = r; r = NULL; *len = (l + 1) / 2; return 0; } /* https://tools.ietf.org/html/rfc4648#section-6 * Notice that base32hex differs from base32 in the alphabet it uses. * The distinction is that the base32hex representation preserves the * order of the underlying data when compared as bytestrings, this is * useful when representing NSEC3 hashes, as one can then verify the * order of hashes directly from their representation. */ char base32hexchar(int x) { static const char table[32] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUV"; return table[x & 31]; } int unbase32hexchar(char c) { unsigned offset; if (c >= '0' && c <= '9') return c - '0'; offset = '9' - '0' + 1; if (c >= 'A' && c <= 'V') return c - 'A' + offset; return -EINVAL; } char *base32hexmem(const void *p, size_t l, bool padding) { char *r, *z; const uint8_t *x; size_t len; if (padding) /* five input bytes makes eight output bytes, padding is added so we must round up */ len = 8 * (l + 4) / 5; else { /* same, but round down as there is no padding */ len = 8 * l / 5; switch (l % 5) { case 4: len += 7; break; case 3: len += 5; break; case 2: len += 4; break; case 1: len += 2; break; } } z = r = malloc(len + 1); if (!r) return NULL; for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) { /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ x[3] == QQQQQQQQ; x[4] == WWWWWWWW */ *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */ *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */ *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */ *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */ *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */ } switch (l % 5) { case 4: *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */ *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */ *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */ *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */ if (padding) *(z++) = '='; break; case 3: *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */ *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */ if (padding) { *(z++) = '='; *(z++) = '='; *(z++) = '='; } break; case 2: *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */ if (padding) { *(z++) = '='; *(z++) = '='; *(z++) = '='; *(z++) = '='; } break; case 1: *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */ if (padding) { *(z++) = '='; *(z++) = '='; *(z++) = '='; *(z++) = '='; *(z++) = '='; *(z++) = '='; } break; } *z = 0; return r; } int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) { _cleanup_free_ uint8_t *r = NULL; int a, b, c, d, e, f, g, h; uint8_t *z; const char *x; size_t len; unsigned pad = 0; assert(p); /* padding ensures any base32hex input has input divisible by 8 */ if (padding && l % 8 != 0) return -EINVAL; if (padding) { /* strip the padding */ while (l > 0 && p[l - 1] == '=' && pad < 7) { pad ++; l --; } } /* a group of eight input bytes needs five output bytes, in case of padding we need to add some extra bytes */ len = (l / 8) * 5; switch (l % 8) { case 7: len += 4; break; case 5: len += 3; break; case 4: len += 2; break; case 2: len += 1; break; case 0: break; default: return -EINVAL; } z = r = malloc(len + 1); if (!r) return -ENOMEM; for (x = p; x < p + (l / 8) * 8; x += 8) { /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */ a = unbase32hexchar(x[0]); if (a < 0) return -EINVAL; b = unbase32hexchar(x[1]); if (b < 0) return -EINVAL; c = unbase32hexchar(x[2]); if (c < 0) return -EINVAL; d = unbase32hexchar(x[3]); if (d < 0) return -EINVAL; e = unbase32hexchar(x[4]); if (e < 0) return -EINVAL; f = unbase32hexchar(x[5]); if (f < 0) return -EINVAL; g = unbase32hexchar(x[6]); if (g < 0) return -EINVAL; h = unbase32hexchar(x[7]); if (h < 0) return -EINVAL; *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */ *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */ *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */ } switch (l % 8) { case 7: a = unbase32hexchar(x[0]); if (a < 0) return -EINVAL; b = unbase32hexchar(x[1]); if (b < 0) return -EINVAL; c = unbase32hexchar(x[2]); if (c < 0) return -EINVAL; d = unbase32hexchar(x[3]); if (d < 0) return -EINVAL; e = unbase32hexchar(x[4]); if (e < 0) return -EINVAL; f = unbase32hexchar(x[5]); if (f < 0) return -EINVAL; g = unbase32hexchar(x[6]); if (g < 0) return -EINVAL; /* g == 000VV000 */ if (g & 7) return -EINVAL; *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */ *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */ break; case 5: a = unbase32hexchar(x[0]); if (a < 0) return -EINVAL; b = unbase32hexchar(x[1]); if (b < 0) return -EINVAL; c = unbase32hexchar(x[2]); if (c < 0) return -EINVAL; d = unbase32hexchar(x[3]); if (d < 0) return -EINVAL; e = unbase32hexchar(x[4]); if (e < 0) return -EINVAL; /* e == 000SSSS0 */ if (e & 1) return -EINVAL; *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */ break; case 4: a = unbase32hexchar(x[0]); if (a < 0) return -EINVAL; b = unbase32hexchar(x[1]); if (b < 0) return -EINVAL; c = unbase32hexchar(x[2]); if (c < 0) return -EINVAL; d = unbase32hexchar(x[3]); if (d < 0) return -EINVAL; /* d == 000W0000 */ if (d & 15) return -EINVAL; *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ break; case 2: a = unbase32hexchar(x[0]); if (a < 0) return -EINVAL; b = unbase32hexchar(x[1]); if (b < 0) return -EINVAL; /* b == 000YYY00 */ if (b & 3) return -EINVAL; *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ break; case 0: break; default: return -EINVAL; } *z = 0; *mem = r; r = NULL; *_len = len; return 0; } /* https://tools.ietf.org/html/rfc4648#section-4 */ char base64char(int x) { static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; return table[x & 63]; } int unbase64char(char c) { unsigned offset; if (c >= 'A' && c <= 'Z') return c - 'A'; offset = 'Z' - 'A' + 1; if (c >= 'a' && c <= 'z') return c - 'a' + offset; offset += 'z' - 'a' + 1; if (c >= '0' && c <= '9') return c - '0' + offset; offset += '9' - '0' + 1; if (c == '+') return offset; offset ++; if (c == '/') return offset; return -EINVAL; } ssize_t base64mem(const void *p, size_t l, char **out) { char *r, *z; const uint8_t *x; /* three input bytes makes four output bytes, padding is added so we must round up */ z = r = malloc(4 * (l + 2) / 3 + 1); if (!r) return -ENOMEM; for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) { /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */ *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */ *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */ *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */ *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */ } switch (l % 3) { case 2: *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */ *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */ *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */ *(z++) = '='; break; case 1: *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */ *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */ *(z++) = '='; *(z++) = '='; break; } *z = 0; *out = r; return z - r; } static int base64_append_width(char **prefix, int plen, const char *sep, int indent, const void *p, size_t l, int width) { _cleanup_free_ char *x = NULL; char *t, *s; ssize_t slen, len, avail; int line, lines; len = base64mem(p, l, &x); if (len <= 0) return len; lines = (len + width - 1) / width; slen = sep ? strlen(sep) : 0; t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines); if (!t) return -ENOMEM; memcpy(t + plen, sep, slen); for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) { int act = MIN(width, avail); if (line > 0 || sep) { memset(s, ' ', indent); s += indent; } memcpy(s, x + width * line, act); s += act; *(s++) = line < lines - 1 ? '\n' : '\0'; avail -= act; } assert(avail == 0); *prefix = t; return 0; } int base64_append(char **prefix, int plen, const void *p, size_t l, int indent, int width) { if (plen > width / 2 || plen + indent > width) /* leave indent on the left, keep last column free */ return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1); else /* leave plen on the left, keep last column free */ return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1); }; int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) { _cleanup_free_ uint8_t *r = NULL; int a, b, c, d; uint8_t *z; const char *x; size_t len; assert(p); /* padding ensures any base63 input has input divisible by 4 */ if (l % 4 != 0) return -EINVAL; /* strip the padding */ if (l > 0 && p[l - 1] == '=') l --; if (l > 0 && p[l - 1] == '=') l --; /* a group of four input bytes needs three output bytes, in case of padding we need to add two or three extra bytes */ len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0); z = r = malloc(len + 1); if (!r) return -ENOMEM; for (x = p; x < p + (l / 4) * 4; x += 4) { /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */ a = unbase64char(x[0]); if (a < 0) return -EINVAL; b = unbase64char(x[1]); if (b < 0) return -EINVAL; c = unbase64char(x[2]); if (c < 0) return -EINVAL; d = unbase64char(x[3]); if (d < 0) return -EINVAL; *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */ } switch (l % 4) { case 3: a = unbase64char(x[0]); if (a < 0) return -EINVAL; b = unbase64char(x[1]); if (b < 0) return -EINVAL; c = unbase64char(x[2]); if (c < 0) return -EINVAL; /* c == 00ZZZZ00 */ if (c & 3) return -EINVAL; *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ break; case 2: a = unbase64char(x[0]); if (a < 0) return -EINVAL; b = unbase64char(x[1]); if (b < 0) return -EINVAL; /* b == 00YY0000 */ if (b & 15) return -EINVAL; *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */ break; case 0: break; default: return -EINVAL; } *z = 0; *mem = r; r = NULL; *_len = len; return 0; } void hexdump(FILE *f, const void *p, size_t s) { const uint8_t *b = p; unsigned n = 0; assert(s == 0 || b); while (s > 0) { size_t i; fprintf(f, "%04x ", n); for (i = 0; i < 16; i++) { if (i >= s) fputs(" ", f); else fprintf(f, "%02x ", b[i]); if (i == 7) fputc(' ', f); } fputc(' ', f); for (i = 0; i < 16; i++) { if (i >= s) fputc(' ', f); else fputc(isprint(b[i]) ? (char) b[i] : '.', f); } fputc('\n', f); if (s < 16) break; n += 16; b += 16; s -= 16; } } systemd-229/src/basic/hexdecoct.h000066400000000000000000000032541265713322000170540ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "macro.h" char octchar(int x) _const_; int unoctchar(char c) _const_; char decchar(int x) _const_; int undecchar(char c) _const_; char hexchar(int x) _const_; int unhexchar(char c) _const_; char *hexmem(const void *p, size_t l); int unhexmem(const char *p, size_t l, void **mem, size_t *len); char base32hexchar(int x) _const_; int unbase32hexchar(char c) _const_; char base64char(int x) _const_; int unbase64char(char c) _const_; char *base32hexmem(const void *p, size_t l, bool padding); int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *len); ssize_t base64mem(const void *p, size_t l, char **out); int base64_append(char **prefix, int plen, const void *p, size_t l, int margin, int width); int unbase64mem(const char *p, size_t l, void **mem, size_t *len); void hexdump(FILE *f, const void *p, size_t s); systemd-229/src/basic/hostname-util.c000066400000000000000000000142141265713322000176700ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "fd-util.h" #include "fileio.h" #include "hostname-util.h" #include "macro.h" #include "string-util.h" bool hostname_is_set(void) { struct utsname u; assert_se(uname(&u) >= 0); if (isempty(u.nodename)) return false; /* This is the built-in kernel default host name */ if (streq(u.nodename, "(none)")) return false; return true; } char* gethostname_malloc(void) { struct utsname u; assert_se(uname(&u) >= 0); if (isempty(u.nodename) || streq(u.nodename, "(none)")) return strdup(u.sysname); return strdup(u.nodename); } static bool hostname_valid_char(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.'; } /** * Check if s looks like a valid host name or FQDN. This does not do * full DNS validation, but only checks if the name is composed of * allowed characters and the length is not above the maximum allowed * by Linux (c.f. dns_name_is_valid()). Trailing dot is allowed if * allow_trailing_dot is true and at least two components are present * in the name. Note that due to the restricted charset and length * this call is substantially more conservative than * dns_name_is_valid(). */ bool hostname_is_valid(const char *s, bool allow_trailing_dot) { unsigned n_dots = 0; const char *p; bool dot; if (isempty(s)) return false; /* Doesn't accept empty hostnames, hostnames with * leading dots, and hostnames with multiple dots in a * sequence. Also ensures that the length stays below * HOST_NAME_MAX. */ for (p = s, dot = true; *p; p++) { if (*p == '.') { if (dot) return false; dot = true; n_dots ++; } else { if (!hostname_valid_char(*p)) return false; dot = false; } } if (dot && (n_dots < 2 || !allow_trailing_dot)) return false; if (p-s > HOST_NAME_MAX) /* Note that HOST_NAME_MAX is 64 on * Linux, but DNS allows domain names * up to 255 characters */ return false; return true; } char* hostname_cleanup(char *s) { char *p, *d; bool dot; assert(s); for (p = s, d = s, dot = true; *p; p++) { if (*p == '.') { if (dot) continue; *(d++) = '.'; dot = true; } else if (hostname_valid_char(*p)) { *(d++) = *p; dot = false; } } if (dot && d > s) d[-1] = 0; else *d = 0; strshorten(s, HOST_NAME_MAX); return s; } bool is_localhost(const char *hostname) { assert(hostname); /* This tries to identify local host and domain names * described in RFC6761 plus the redhatism of .localdomain */ return strcaseeq(hostname, "localhost") || strcaseeq(hostname, "localhost.") || strcaseeq(hostname, "localdomain.") || strcaseeq(hostname, "localdomain") || endswith_no_case(hostname, ".localhost") || endswith_no_case(hostname, ".localhost.") || endswith_no_case(hostname, ".localdomain") || endswith_no_case(hostname, ".localdomain."); } bool is_gateway_hostname(const char *hostname) { assert(hostname); /* This tries to identify the valid syntaxes for the our * synthetic "gateway" host. */ return strcaseeq(hostname, "gateway") || strcaseeq(hostname, "gateway."); } int sethostname_idempotent(const char *s) { char buf[HOST_NAME_MAX + 1] = {}; assert(s); if (gethostname(buf, sizeof(buf)) < 0) return -errno; if (streq(buf, s)) return 0; if (sethostname(s, strlen(s)) < 0) return -errno; return 1; } int read_hostname_config(const char *path, char **hostname) { _cleanup_fclose_ FILE *f = NULL; char l[LINE_MAX]; char *name = NULL; assert(path); assert(hostname); f = fopen(path, "re"); if (!f) return -errno; /* may have comments, ignore them */ FOREACH_LINE(l, f, return -errno) { truncate_nl(l); if (l[0] != '\0' && l[0] != '#') { /* found line with value */ name = hostname_cleanup(l); name = strdup(name); if (!name) return -ENOMEM; break; } } if (!name) /* no non-empty line found */ return -ENOENT; *hostname = name; return 0; } systemd-229/src/basic/hostname-util.h000066400000000000000000000022641265713322000176770ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010-2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" bool hostname_is_set(void); char* gethostname_malloc(void); bool hostname_is_valid(const char *s, bool allow_trailing_dot) _pure_; char* hostname_cleanup(char *s); #define machine_name_is_valid(s) hostname_is_valid(s, false) bool is_localhost(const char *hostname); bool is_gateway_hostname(const char *hostname); int sethostname_idempotent(const char *s); int read_hostname_config(const char *path, char **hostname); systemd-229/src/basic/in-addr-util.c000066400000000000000000000227401265713322000173730ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "in-addr-util.h" #include "macro.h" #include "util.h" int in_addr_is_null(int family, const union in_addr_union *u) { assert(u); if (family == AF_INET) return u->in.s_addr == 0; if (family == AF_INET6) return u->in6.s6_addr32[0] == 0 && u->in6.s6_addr32[1] == 0 && u->in6.s6_addr32[2] == 0 && u->in6.s6_addr32[3] == 0; return -EAFNOSUPPORT; } int in_addr_is_link_local(int family, const union in_addr_union *u) { assert(u); if (family == AF_INET) return (be32toh(u->in.s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16); if (family == AF_INET6) return IN6_IS_ADDR_LINKLOCAL(&u->in6); return -EAFNOSUPPORT; } int in_addr_is_localhost(int family, const union in_addr_union *u) { assert(u); if (family == AF_INET) /* All of 127.x.x.x is localhost. */ return (be32toh(u->in.s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24; if (family == AF_INET6) return IN6_IS_ADDR_LOOPBACK(&u->in6); return -EAFNOSUPPORT; } int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b) { assert(a); assert(b); if (family == AF_INET) return a->in.s_addr == b->in.s_addr; if (family == AF_INET6) return a->in6.s6_addr32[0] == b->in6.s6_addr32[0] && a->in6.s6_addr32[1] == b->in6.s6_addr32[1] && a->in6.s6_addr32[2] == b->in6.s6_addr32[2] && a->in6.s6_addr32[3] == b->in6.s6_addr32[3]; return -EAFNOSUPPORT; } int in_addr_prefix_intersect( int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen) { unsigned m; assert(a); assert(b); /* Checks whether there are any addresses that are in both * networks */ m = MIN(aprefixlen, bprefixlen); if (family == AF_INET) { uint32_t x, nm; x = be32toh(a->in.s_addr ^ b->in.s_addr); nm = (m == 0) ? 0 : 0xFFFFFFFFUL << (32 - m); return (x & nm) == 0; } if (family == AF_INET6) { unsigned i; if (m > 128) m = 128; for (i = 0; i < 16; i++) { uint8_t x, nm; x = a->in6.s6_addr[i] ^ b->in6.s6_addr[i]; if (m < 8) nm = 0xFF << (8 - m); else nm = 0xFF; if ((x & nm) != 0) return 0; if (m > 8) m -= 8; else m = 0; } return 1; } return -EAFNOSUPPORT; } int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen) { assert(u); /* Increases the network part of an address by one. Returns * positive it that succeeds, or 0 if this overflows. */ if (prefixlen <= 0) return 0; if (family == AF_INET) { uint32_t c, n; if (prefixlen > 32) prefixlen = 32; c = be32toh(u->in.s_addr); n = c + (1UL << (32 - prefixlen)); if (n < c) return 0; n &= 0xFFFFFFFFUL << (32 - prefixlen); u->in.s_addr = htobe32(n); return 1; } if (family == AF_INET6) { struct in6_addr add = {}, result; uint8_t overflow = 0; unsigned i; if (prefixlen > 128) prefixlen = 128; /* First calculate what we have to add */ add.s6_addr[(prefixlen-1) / 8] = 1 << (7 - (prefixlen-1) % 8); for (i = 16; i > 0; i--) { unsigned j = i - 1; result.s6_addr[j] = u->in6.s6_addr[j] + add.s6_addr[j] + overflow; overflow = (result.s6_addr[j] < u->in6.s6_addr[j]); } if (overflow) return 0; u->in6 = result; return 1; } return -EAFNOSUPPORT; } int in_addr_to_string(int family, const union in_addr_union *u, char **ret) { char *x; size_t l; assert(u); assert(ret); if (family == AF_INET) l = INET_ADDRSTRLEN; else if (family == AF_INET6) l = INET6_ADDRSTRLEN; else return -EAFNOSUPPORT; x = new(char, l); if (!x) return -ENOMEM; errno = 0; if (!inet_ntop(family, u, x, l)) { free(x); return errno > 0 ? -errno : -EINVAL; } *ret = x; return 0; } int in_addr_from_string(int family, const char *s, union in_addr_union *ret) { assert(s); assert(ret); if (!IN_SET(family, AF_INET, AF_INET6)) return -EAFNOSUPPORT; errno = 0; if (inet_pton(family, s, ret) <= 0) return errno > 0 ? -errno : -EINVAL; return 0; } int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *ret) { int r; assert(s); assert(family); assert(ret); r = in_addr_from_string(AF_INET, s, ret); if (r >= 0) { *family = AF_INET; return 0; } r = in_addr_from_string(AF_INET6, s, ret); if (r >= 0) { *family = AF_INET6; return 0; } return -EINVAL; } unsigned char in_addr_netmask_to_prefixlen(const struct in_addr *addr) { assert(addr); return 32 - u32ctz(be32toh(addr->s_addr)); } struct in_addr* in_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen) { assert(addr); assert(prefixlen <= 32); /* Shifting beyond 32 is not defined, handle this specially. */ if (prefixlen == 0) addr->s_addr = 0; else addr->s_addr = htobe32((0xffffffff << (32 - prefixlen)) & 0xffffffff); return addr; } int in_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen) { uint8_t msb_octet = *(uint8_t*) addr; /* addr may not be aligned, so make sure we only access it byte-wise */ assert(addr); assert(prefixlen); if (msb_octet < 128) /* class A, leading bits: 0 */ *prefixlen = 8; else if (msb_octet < 192) /* class B, leading bits 10 */ *prefixlen = 16; else if (msb_octet < 224) /* class C, leading bits 110 */ *prefixlen = 24; else /* class D or E, no default prefixlen */ return -ERANGE; return 0; } int in_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask) { unsigned char prefixlen; int r; assert(addr); assert(mask); r = in_addr_default_prefixlen(addr, &prefixlen); if (r < 0) return r; in_addr_prefixlen_to_netmask(mask, prefixlen); return 0; } int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen) { assert(addr); if (family == AF_INET) { struct in_addr mask; if (!in_addr_prefixlen_to_netmask(&mask, prefixlen)) return -EINVAL; addr->in.s_addr &= mask.s_addr; return 0; } if (family == AF_INET6) { unsigned i; for (i = 0; i < 16; i++) { uint8_t mask; if (prefixlen >= 8) { mask = 0xFF; prefixlen -= 8; } else { mask = 0xFF << (8 - prefixlen); prefixlen = 0; } addr->in6.s6_addr[i] &= mask; } return 0; } return -EAFNOSUPPORT; } systemd-229/src/basic/in-addr-util.h000066400000000000000000000045171265713322000174020ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "macro.h" #include "util.h" union in_addr_union { struct in_addr in; struct in6_addr in6; }; struct in_addr_data { int family; union in_addr_union address; }; int in_addr_is_null(int family, const union in_addr_union *u); int in_addr_is_link_local(int family, const union in_addr_union *u); int in_addr_is_localhost(int family, const union in_addr_union *u); int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b); int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen); int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen); int in_addr_to_string(int family, const union in_addr_union *u, char **ret); int in_addr_from_string(int family, const char *s, union in_addr_union *ret); int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *ret); unsigned char in_addr_netmask_to_prefixlen(const struct in_addr *addr); struct in_addr* in_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen); int in_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen); int in_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask); int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen); static inline size_t FAMILY_ADDRESS_SIZE(int family) { assert(family == AF_INET || family == AF_INET6); return family == AF_INET6 ? 16 : 4; } #define IN_ADDR_NULL ((union in_addr_union) {}) systemd-229/src/basic/io-util.c000066400000000000000000000154511265713322000164650ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "io-util.h" #include "time-util.h" int flush_fd(int fd) { struct pollfd pollfd = { .fd = fd, .events = POLLIN, }; for (;;) { char buf[LINE_MAX]; ssize_t l; int r; r = poll(&pollfd, 1, 0); if (r < 0) { if (errno == EINTR) continue; return -errno; } else if (r == 0) return 0; l = read(fd, buf, sizeof(buf)); if (l < 0) { if (errno == EINTR) continue; if (errno == EAGAIN) return 0; return -errno; } else if (l == 0) return 0; } } ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) { uint8_t *p = buf; ssize_t n = 0; assert(fd >= 0); assert(buf); /* If called with nbytes == 0, let's call read() at least * once, to validate the operation */ if (nbytes > (size_t) SSIZE_MAX) return -EINVAL; do { ssize_t k; k = read(fd, p, nbytes); if (k < 0) { if (errno == EINTR) continue; if (errno == EAGAIN && do_poll) { /* We knowingly ignore any return value here, * and expect that any error/EOF is reported * via read() */ (void) fd_wait_for_event(fd, POLLIN, USEC_INFINITY); continue; } return n > 0 ? n : -errno; } if (k == 0) return n; assert((size_t) k <= nbytes); p += k; nbytes -= k; n += k; } while (nbytes > 0); return n; } int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) { ssize_t n; n = loop_read(fd, buf, nbytes, do_poll); if (n < 0) return (int) n; if ((size_t) n != nbytes) return -EIO; return 0; } int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) { const uint8_t *p = buf; assert(fd >= 0); assert(buf); if (nbytes > (size_t) SSIZE_MAX) return -EINVAL; do { ssize_t k; k = write(fd, p, nbytes); if (k < 0) { if (errno == EINTR) continue; if (errno == EAGAIN && do_poll) { /* We knowingly ignore any return value here, * and expect that any error/EOF is reported * via write() */ (void) fd_wait_for_event(fd, POLLOUT, USEC_INFINITY); continue; } return -errno; } if (_unlikely_(nbytes > 0 && k == 0)) /* Can't really happen */ return -EIO; assert((size_t) k <= nbytes); p += k; nbytes -= k; } while (nbytes > 0); return 0; } int pipe_eof(int fd) { struct pollfd pollfd = { .fd = fd, .events = POLLIN|POLLHUP, }; int r; r = poll(&pollfd, 1, 0); if (r < 0) return -errno; if (r == 0) return 0; return pollfd.revents & POLLHUP; } int fd_wait_for_event(int fd, int event, usec_t t) { struct pollfd pollfd = { .fd = fd, .events = event, }; struct timespec ts; int r; r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL); if (r < 0) return -errno; if (r == 0) return 0; return pollfd.revents; } static size_t nul_length(const uint8_t *p, size_t sz) { size_t n = 0; while (sz > 0) { if (*p != 0) break; n++; p++; sz--; } return n; } ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) { const uint8_t *q, *w, *e; ssize_t l; q = w = p; e = q + sz; while (q < e) { size_t n; n = nul_length(q, e - q); /* If there are more than the specified run length of * NUL bytes, or if this is the beginning or the end * of the buffer, then seek instead of write */ if ((n > run_length) || (n > 0 && q == p) || (n > 0 && q + n >= e)) { if (q > w) { l = write(fd, w, q - w); if (l < 0) return -errno; if (l != q -w) return -EIO; } if (lseek(fd, n, SEEK_CUR) == (off_t) -1) return -errno; q += n; w = q; } else if (n > 0) q += n; else q ++; } if (q > w) { l = write(fd, w, q - w); if (l < 0) return -errno; if (l != q - w) return -EIO; } return q - (const uint8_t*) p; } systemd-229/src/basic/io-util.h000066400000000000000000000053661265713322000164760ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "macro.h" #include "time-util.h" int flush_fd(int fd); ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll); int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll); int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll); int pipe_eof(int fd); int fd_wait_for_event(int fd, int event, usec_t timeout); ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length); #define IOVEC_SET_STRING(i, s) \ do { \ struct iovec *_i = &(i); \ char *_s = (char *)(s); \ _i->iov_base = _s; \ _i->iov_len = strlen(_s); \ } while(false) static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) { unsigned j; size_t r = 0; for (j = 0; j < n; j++) r += i[j].iov_len; return r; } static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) { unsigned j; for (j = 0; j < n; j++) { size_t sub; if (_unlikely_(k <= 0)) break; sub = MIN(i[j].iov_len, k); i[j].iov_len -= sub; i[j].iov_base = (uint8_t*) i[j].iov_base + sub; k -= sub; } return k; } static inline bool FILE_SIZE_VALID(uint64_t l) { /* ftruncate() and friends take an unsigned file size, but actually cannot deal with file sizes larger than * 2^63 since the kernel internally handles it as signed value. This call allows checking for this early. */ return (l >> 63) == 0; } static inline bool FILE_SIZE_VALID_OR_INFINITY(uint64_t l) { /* Same as above, but allows one extra value: -1 as indication for infinity. */ if (l == (uint64_t) -1) return true; return FILE_SIZE_VALID(l); } systemd-229/src/basic/ioprio.h000066400000000000000000000027311265713322000164060ustar00rootroot00000000000000#ifndef IOPRIO_H #define IOPRIO_H /* This is minimal version of Linux' linux/ioprio.h header file, which * is licensed GPL2 */ #include #include /* * Gives us 8 prio classes with 13-bits of data for each class */ #define IOPRIO_BITS (16) #define IOPRIO_CLASS_SHIFT (13) #define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1) #define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT) #define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK) #define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data) #define ioprio_valid(mask) (IOPRIO_PRIO_CLASS((mask)) != IOPRIO_CLASS_NONE) /* * These are the io priority groups as implemented by CFQ. RT is the realtime * class, it always gets premium service. BE is the best-effort scheduling * class, the default for any process. IDLE is the idle scheduling class, it * is only served when no one else is using the disk. */ enum { IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE, }; /* * 8 best effort priority levels are supported */ #define IOPRIO_BE_NR (8) enum { IOPRIO_WHO_PROCESS = 1, IOPRIO_WHO_PGRP, IOPRIO_WHO_USER, }; static inline int ioprio_set(int which, int who, int ioprio) { return syscall(__NR_ioprio_set, which, who, ioprio); } static inline int ioprio_get(int which, int who) { return syscall(__NR_ioprio_get, which, who); } #endif systemd-229/src/basic/json.c000066400000000000000000000651741265713322000160630ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "hexdecoct.h" #include "json.h" #include "macro.h" #include "string-util.h" #include "utf8.h" int json_variant_new(JsonVariant **ret, JsonVariantType type) { JsonVariant *v; v = new0(JsonVariant, 1); if (!v) return -ENOMEM; v->type = type; *ret = v; return 0; } static int json_variant_deep_copy(JsonVariant *ret, JsonVariant *variant) { int r; assert(ret); assert(variant); ret->type = variant->type; ret->size = variant->size; if (variant->type == JSON_VARIANT_STRING) { ret->string = memdup(variant->string, variant->size+1); if (!ret->string) return -ENOMEM; } else if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT) { size_t i; ret->objects = new0(JsonVariant, variant->size); if (!ret->objects) return -ENOMEM; for (i = 0; i < variant->size; ++i) { r = json_variant_deep_copy(&ret->objects[i], &variant->objects[i]); if (r < 0) return r; } } else ret->value = variant->value; return 0; } static JsonVariant *json_object_unref(JsonVariant *variant); static JsonVariant *json_variant_unref_inner(JsonVariant *variant) { if (!variant) return NULL; if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT) return json_object_unref(variant); else if (variant->type == JSON_VARIANT_STRING) free(variant->string); return NULL; } static JsonVariant *json_raw_unref(JsonVariant *variant, size_t size) { if (!variant) return NULL; for (size_t i = 0; i < size; ++i) json_variant_unref_inner(&variant[i]); free(variant); return NULL; } static JsonVariant *json_object_unref(JsonVariant *variant) { size_t i; assert(variant); if (!variant->objects) return NULL; for (i = 0; i < variant->size; ++i) json_variant_unref_inner(&variant->objects[i]); free(variant->objects); return NULL; } static JsonVariant **json_variant_array_unref(JsonVariant **variant) { size_t i = 0; JsonVariant *p = NULL; if (!variant) return NULL; while((p = (variant[i++])) != NULL) { if (p->type == JSON_VARIANT_STRING) free(p->string); free(p); } free(variant); return NULL; } DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant **, json_variant_array_unref); JsonVariant *json_variant_unref(JsonVariant *variant) { if (!variant) return NULL; if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT) json_object_unref(variant); else if (variant->type == JSON_VARIANT_STRING) free(variant->string); free(variant); return NULL; } char *json_variant_string(JsonVariant *variant){ assert(variant); assert(variant->type == JSON_VARIANT_STRING); return variant->string; } bool json_variant_bool(JsonVariant *variant) { assert(variant); assert(variant->type == JSON_VARIANT_BOOLEAN); return variant->value.boolean; } intmax_t json_variant_integer(JsonVariant *variant) { assert(variant); assert(variant->type == JSON_VARIANT_INTEGER); return variant->value.integer; } double json_variant_real(JsonVariant *variant) { assert(variant); assert(variant->type == JSON_VARIANT_REAL); return variant->value.real; } JsonVariant *json_variant_element(JsonVariant *variant, unsigned index) { assert(variant); assert(variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT); assert(index < variant->size); assert(variant->objects); return &variant->objects[index]; } JsonVariant *json_variant_value(JsonVariant *variant, const char *key) { size_t i; assert(variant); assert(variant->type == JSON_VARIANT_OBJECT); assert(variant->objects); for (i = 0; i < variant->size; i += 2) { JsonVariant *p = &variant->objects[i]; if (p->type == JSON_VARIANT_STRING && streq(key, p->string)) return &variant->objects[i + 1]; } return NULL; } static void inc_lines(unsigned *line, const char *s, size_t n) { const char *p = s; if (!line) return; for (;;) { const char *f; f = memchr(p, '\n', n); if (!f) return; n -= (f - p) + 1; p = f + 1; (*line)++; } } static int unhex_ucs2(const char *c, uint16_t *ret) { int aa, bb, cc, dd; uint16_t x; assert(c); assert(ret); aa = unhexchar(c[0]); if (aa < 0) return -EINVAL; bb = unhexchar(c[1]); if (bb < 0) return -EINVAL; cc = unhexchar(c[2]); if (cc < 0) return -EINVAL; dd = unhexchar(c[3]); if (dd < 0) return -EINVAL; x = ((uint16_t) aa << 12) | ((uint16_t) bb << 8) | ((uint16_t) cc << 4) | ((uint16_t) dd); if (x <= 0) return -EINVAL; *ret = x; return 0; } static int json_parse_string(const char **p, char **ret) { _cleanup_free_ char *s = NULL; size_t n = 0, allocated = 0; const char *c; assert(p); assert(*p); assert(ret); c = *p; if (*c != '"') return -EINVAL; c++; for (;;) { int len; /* Check for EOF */ if (*c == 0) return -EINVAL; /* Check for control characters 0x00..0x1f */ if (*c > 0 && *c < ' ') return -EINVAL; /* Check for control character 0x7f */ if (*c == 0x7f) return -EINVAL; if (*c == '"') { if (!s) { s = strdup(""); if (!s) return -ENOMEM; } else s[n] = 0; *p = c + 1; *ret = s; s = NULL; return JSON_STRING; } if (*c == '\\') { char ch = 0; c++; if (*c == 0) return -EINVAL; if (IN_SET(*c, '"', '\\', '/')) ch = *c; else if (*c == 'b') ch = '\b'; else if (*c == 'f') ch = '\f'; else if (*c == 'n') ch = '\n'; else if (*c == 'r') ch = '\r'; else if (*c == 't') ch = '\t'; else if (*c == 'u') { char16_t x; int r; r = unhex_ucs2(c + 1, &x); if (r < 0) return r; c += 5; if (!GREEDY_REALLOC(s, allocated, n + 4)) return -ENOMEM; if (!utf16_is_surrogate(x)) n += utf8_encode_unichar(s + n, (char32_t) x); else if (utf16_is_trailing_surrogate(x)) return -EINVAL; else { char16_t y; if (c[0] != '\\' || c[1] != 'u') return -EINVAL; r = unhex_ucs2(c + 2, &y); if (r < 0) return r; c += 6; if (!utf16_is_trailing_surrogate(y)) return -EINVAL; n += utf8_encode_unichar(s + n, utf16_surrogate_pair_to_unichar(x, y)); } continue; } else return -EINVAL; if (!GREEDY_REALLOC(s, allocated, n + 2)) return -ENOMEM; s[n++] = ch; c ++; continue; } len = utf8_encoded_valid_unichar(c); if (len < 0) return len; if (!GREEDY_REALLOC(s, allocated, n + len + 1)) return -ENOMEM; memcpy(s + n, c, len); n += len; c += len; } } static int json_parse_number(const char **p, union json_value *ret) { bool negative = false, exponent_negative = false, is_double = false; double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0; intmax_t i = 0; const char *c; assert(p); assert(*p); assert(ret); c = *p; if (*c == '-') { negative = true; c++; } if (*c == '0') c++; else { if (!strchr("123456789", *c) || *c == 0) return -EINVAL; do { if (!is_double) { int64_t t; t = 10 * i + (*c - '0'); if (t < i) /* overflow */ is_double = false; else i = t; } x = 10.0 * x + (*c - '0'); c++; } while (strchr("0123456789", *c) && *c != 0); } if (*c == '.') { is_double = true; c++; if (!strchr("0123456789", *c) || *c == 0) return -EINVAL; do { y = 10.0 * y + (*c - '0'); shift = 10.0 * shift; c++; } while (strchr("0123456789", *c) && *c != 0); } if (*c == 'e' || *c == 'E') { is_double = true; c++; if (*c == '-') { exponent_negative = true; c++; } else if (*c == '+') c++; if (!strchr("0123456789", *c) || *c == 0) return -EINVAL; do { exponent = 10.0 * exponent + (*c - '0'); c++; } while (strchr("0123456789", *c) && *c != 0); } *p = c; if (is_double) { ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10((exponent_negative ? -1.0 : 1.0) * exponent); return JSON_REAL; } else { ret->integer = negative ? -i : i; return JSON_INTEGER; } } int json_tokenize( const char **p, char **ret_string, union json_value *ret_value, void **state, unsigned *line) { const char *c; int t; int r; enum { STATE_NULL, STATE_VALUE, STATE_VALUE_POST, }; assert(p); assert(*p); assert(ret_string); assert(ret_value); assert(state); t = PTR_TO_INT(*state); c = *p; if (t == STATE_NULL) { if (line) *line = 1; t = STATE_VALUE; } for (;;) { const char *b; b = c + strspn(c, WHITESPACE); if (*b == 0) return JSON_END; inc_lines(line, c, b - c); c = b; switch (t) { case STATE_VALUE: if (*c == '{') { *ret_string = NULL; *ret_value = JSON_VALUE_NULL; *p = c + 1; *state = INT_TO_PTR(STATE_VALUE); return JSON_OBJECT_OPEN; } else if (*c == '}') { *ret_string = NULL; *ret_value = JSON_VALUE_NULL; *p = c + 1; *state = INT_TO_PTR(STATE_VALUE_POST); return JSON_OBJECT_CLOSE; } else if (*c == '[') { *ret_string = NULL; *ret_value = JSON_VALUE_NULL; *p = c + 1; *state = INT_TO_PTR(STATE_VALUE); return JSON_ARRAY_OPEN; } else if (*c == ']') { *ret_string = NULL; *ret_value = JSON_VALUE_NULL; *p = c + 1; *state = INT_TO_PTR(STATE_VALUE_POST); return JSON_ARRAY_CLOSE; } else if (*c == '"') { r = json_parse_string(&c, ret_string); if (r < 0) return r; *ret_value = JSON_VALUE_NULL; *p = c; *state = INT_TO_PTR(STATE_VALUE_POST); return r; } else if (strchr("-0123456789", *c)) { r = json_parse_number(&c, ret_value); if (r < 0) return r; *ret_string = NULL; *p = c; *state = INT_TO_PTR(STATE_VALUE_POST); return r; } else if (startswith(c, "true")) { *ret_string = NULL; ret_value->boolean = true; *p = c + 4; *state = INT_TO_PTR(STATE_VALUE_POST); return JSON_BOOLEAN; } else if (startswith(c, "false")) { *ret_string = NULL; ret_value->boolean = false; *p = c + 5; *state = INT_TO_PTR(STATE_VALUE_POST); return JSON_BOOLEAN; } else if (startswith(c, "null")) { *ret_string = NULL; *ret_value = JSON_VALUE_NULL; *p = c + 4; *state = INT_TO_PTR(STATE_VALUE_POST); return JSON_NULL; } else return -EINVAL; case STATE_VALUE_POST: if (*c == ':') { *ret_string = NULL; *ret_value = JSON_VALUE_NULL; *p = c + 1; *state = INT_TO_PTR(STATE_VALUE); return JSON_COLON; } else if (*c == ',') { *ret_string = NULL; *ret_value = JSON_VALUE_NULL; *p = c + 1; *state = INT_TO_PTR(STATE_VALUE); return JSON_COMMA; } else if (*c == '}') { *ret_string = NULL; *ret_value = JSON_VALUE_NULL; *p = c + 1; *state = INT_TO_PTR(STATE_VALUE_POST); return JSON_OBJECT_CLOSE; } else if (*c == ']') { *ret_string = NULL; *ret_value = JSON_VALUE_NULL; *p = c + 1; *state = INT_TO_PTR(STATE_VALUE_POST); return JSON_ARRAY_CLOSE; } else return -EINVAL; } } } static bool json_is_value(JsonVariant *var) { assert(var); return var->type != JSON_VARIANT_CONTROL; } static int json_scoped_parse(JsonVariant **tokens, size_t *i, size_t n, JsonVariant *scope) { bool arr = scope->type == JSON_VARIANT_ARRAY; int terminator = arr ? JSON_ARRAY_CLOSE : JSON_OBJECT_CLOSE; size_t allocated = 0, size = 0; JsonVariant *key = NULL, *value = NULL, *var = NULL, *items = NULL; enum { STATE_KEY, STATE_COLON, STATE_COMMA, STATE_VALUE } state = arr ? STATE_VALUE : STATE_KEY; assert(tokens); assert(i); assert(scope); while((var = *i < n ? tokens[(*i)++] : NULL) != NULL) { bool stopper; int r; stopper = !json_is_value(var) && var->value.integer == terminator; if (stopper) { if (state != STATE_COMMA && size > 0) goto error; goto out; } if (state == STATE_KEY) { if (var->type != JSON_VARIANT_STRING) goto error; else { key = var; state = STATE_COLON; } } else if (state == STATE_COLON) { if (key == NULL) goto error; if (json_is_value(var)) goto error; if (var->value.integer != JSON_COLON) goto error; state = STATE_VALUE; } else if (state == STATE_VALUE) { _cleanup_json_variant_unref_ JsonVariant *v = NULL; size_t toadd = arr ? 1 : 2; if (!json_is_value(var)) { int type = (var->value.integer == JSON_ARRAY_OPEN) ? JSON_VARIANT_ARRAY : JSON_VARIANT_OBJECT; r = json_variant_new(&v, type); if (r < 0) goto error; r = json_scoped_parse(tokens, i, n, v); if (r < 0) goto error; value = v; } else value = var; if(!GREEDY_REALLOC(items, allocated, size + toadd)) goto error; if (arr) { r = json_variant_deep_copy(&items[size], value); if (r < 0) goto error; } else { r = json_variant_deep_copy(&items[size], key); if (r < 0) goto error; r = json_variant_deep_copy(&items[size+1], value); if (r < 0) goto error; } size += toadd; state = STATE_COMMA; } else if (state == STATE_COMMA) { if (json_is_value(var)) goto error; if (var->value.integer != JSON_COMMA) goto error; key = NULL; value = NULL; state = arr ? STATE_VALUE : STATE_KEY; } } error: json_raw_unref(items, size); return -EBADMSG; out: scope->size = size; scope->objects = items; return scope->type; } static int json_parse_tokens(JsonVariant **tokens, size_t ntokens, JsonVariant **rv) { size_t it = 0; int r; JsonVariant *e; _cleanup_json_variant_unref_ JsonVariant *p = NULL; assert(tokens); assert(ntokens); e = tokens[it++]; r = json_variant_new(&p, JSON_VARIANT_OBJECT); if (r < 0) return r; if (e->type != JSON_VARIANT_CONTROL && e->value.integer != JSON_OBJECT_OPEN) return -EBADMSG; r = json_scoped_parse(tokens, &it, ntokens, p); if (r < 0) return r; *rv = p; p = NULL; return 0; } static int json_tokens(const char *string, size_t size, JsonVariant ***tokens, size_t *n) { _cleanup_free_ char *buf = NULL; _cleanup_(json_variant_array_unrefp) JsonVariant **items = NULL; union json_value v = {}; void *json_state = NULL; const char *p; int t, r; size_t allocated = 0, s = 0; assert(string); assert(n); if (size <= 0) return -EBADMSG; buf = strndup(string, size); if (!buf) return -ENOMEM; p = buf; for (;;) { _cleanup_json_variant_unref_ JsonVariant *var = NULL; _cleanup_free_ char *rstr = NULL; t = json_tokenize(&p, &rstr, &v, &json_state, NULL); if (t < 0) return t; else if (t == JSON_END) break; if (t <= JSON_ARRAY_CLOSE) { r = json_variant_new(&var, JSON_VARIANT_CONTROL); if (r < 0) return r; var->value.integer = t; } else { switch (t) { case JSON_STRING: r = json_variant_new(&var, JSON_VARIANT_STRING); if (r < 0) return r; var->size = strlen(rstr); var->string = strdup(rstr); if (!var->string) { return -ENOMEM; } break; case JSON_INTEGER: r = json_variant_new(&var, JSON_VARIANT_INTEGER); if (r < 0) return r; var->value = v; break; case JSON_REAL: r = json_variant_new(&var, JSON_VARIANT_REAL); if (r < 0) return r; var->value = v; break; case JSON_BOOLEAN: r = json_variant_new(&var, JSON_VARIANT_BOOLEAN); if (r < 0) return r; var->value = v; break; case JSON_NULL: r = json_variant_new(&var, JSON_VARIANT_NULL); if (r < 0) return r; break; } } if (!GREEDY_REALLOC(items, allocated, s+2)) return -ENOMEM; items[s++] = var; items[s] = NULL; var = NULL; } *n = s; *tokens = items; items = NULL; return 0; } int json_parse(const char *string, JsonVariant **rv) { _cleanup_(json_variant_array_unrefp) JsonVariant **s = NULL; JsonVariant *v = NULL; size_t n = 0; int r; assert(string); assert(rv); r = json_tokens(string, strlen(string), &s, &n); if (r < 0) return r; r = json_parse_tokens(s, n, &v); if (r < 0) return r; *rv = v; return 0; } systemd-229/src/basic/json.h000066400000000000000000000047431265713322000160630ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "macro.h" #include "util.h" enum { JSON_END, JSON_COLON, JSON_COMMA, JSON_OBJECT_OPEN, JSON_OBJECT_CLOSE, JSON_ARRAY_OPEN, JSON_ARRAY_CLOSE, JSON_STRING, JSON_REAL, JSON_INTEGER, JSON_BOOLEAN, JSON_NULL, }; typedef enum { JSON_VARIANT_CONTROL, JSON_VARIANT_STRING, JSON_VARIANT_INTEGER, JSON_VARIANT_BOOLEAN, JSON_VARIANT_REAL, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT, JSON_VARIANT_NULL } JsonVariantType; union json_value { bool boolean; double real; intmax_t integer; }; typedef struct JsonVariant { JsonVariantType type; size_t size; union { char *string; struct JsonVariant *objects; union json_value value; }; } JsonVariant; int json_variant_new(JsonVariant **ret, JsonVariantType type); JsonVariant *json_variant_unref(JsonVariant *v); DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref); #define _cleanup_json_variant_unref_ _cleanup_(json_variant_unrefp) char *json_variant_string(JsonVariant *v); bool json_variant_bool(JsonVariant *v); intmax_t json_variant_integer(JsonVariant *v); double json_variant_real(JsonVariant *v); JsonVariant *json_variant_element(JsonVariant *v, unsigned index); JsonVariant *json_variant_value(JsonVariant *v, const char *key); #define JSON_VALUE_NULL ((union json_value) {}) int json_tokenize(const char **p, char **ret_string, union json_value *ret_value, void **state, unsigned *line); int json_parse(const char *string, JsonVariant **rv); int json_parse_measure(const char *string, size_t *size); systemd-229/src/basic/label.c000066400000000000000000000040151265713322000161540ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "label.h" #include "macro.h" #include "selinux-util.h" #include "smack-util.h" int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) { int r, q; r = mac_selinux_fix(path, ignore_enoent, ignore_erofs); q = mac_smack_fix(path, ignore_enoent, ignore_erofs); if (r < 0) return r; if (q < 0) return q; return 0; } int mkdir_label(const char *path, mode_t mode) { int r; assert(path); r = mac_selinux_create_file_prepare(path, S_IFDIR); if (r < 0) return r; if (mkdir(path, mode) < 0) r = -errno; mac_selinux_create_file_clear(); if (r < 0) return r; return mac_smack_fix(path, false, false); } int symlink_label(const char *old_path, const char *new_path) { int r; assert(old_path); assert(new_path); r = mac_selinux_create_file_prepare(new_path, S_IFLNK); if (r < 0) return r; if (symlink(old_path, new_path) < 0) r = -errno; mac_selinux_create_file_clear(); if (r < 0) return r; return mac_smack_fix(new_path, false, false); } systemd-229/src/basic/label.h000066400000000000000000000017021265713322000161610ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs); int mkdir_label(const char *path, mode_t mode); int symlink_label(const char *old_path, const char *new_path); systemd-229/src/basic/linux/000077500000000000000000000000001265713322000160705ustar00rootroot00000000000000systemd-229/src/basic/linux/Makefile000077700000000000000000000000001265713322000213762../Makefileustar00rootroot00000000000000systemd-229/src/basic/list.h000066400000000000000000000242731265713322000160650ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* The head of the linked list. Use this in the structure that shall * contain the head of the linked list */ #define LIST_HEAD(t,name) \ t *name /* The pointers in the linked list's items. Use this in the item structure */ #define LIST_FIELDS(t,name) \ t *name##_next, *name##_prev /* Initialize the list's head */ #define LIST_HEAD_INIT(head) \ do { \ (head) = NULL; } \ while(false) /* Initialize a list item */ #define LIST_INIT(name,item) \ do { \ typeof(*(item)) *_item = (item); \ assert(_item); \ _item->name##_prev = _item->name##_next = NULL; \ } while(false) /* Prepend an item to the list */ #define LIST_PREPEND(name,head,item) \ do { \ typeof(*(head)) **_head = &(head), *_item = (item); \ assert(_item); \ if ((_item->name##_next = *_head)) \ _item->name##_next->name##_prev = _item; \ _item->name##_prev = NULL; \ *_head = _item; \ } while(false) /* Append an item to the list */ #define LIST_APPEND(name,head,item) \ do { \ typeof(*(head)) *_tail; \ LIST_FIND_TAIL(name,head,_tail); \ LIST_INSERT_AFTER(name,head,_tail,item); \ } while(false) /* Remove an item from the list */ #define LIST_REMOVE(name,head,item) \ do { \ typeof(*(head)) **_head = &(head), *_item = (item); \ assert(_item); \ if (_item->name##_next) \ _item->name##_next->name##_prev = _item->name##_prev; \ if (_item->name##_prev) \ _item->name##_prev->name##_next = _item->name##_next; \ else { \ assert(*_head == _item); \ *_head = _item->name##_next; \ } \ _item->name##_next = _item->name##_prev = NULL; \ } while(false) /* Find the head of the list */ #define LIST_FIND_HEAD(name,item,head) \ do { \ typeof(*(item)) *_item = (item); \ if (!_item) \ (head) = NULL; \ else { \ while (_item->name##_prev) \ _item = _item->name##_prev; \ (head) = _item; \ } \ } while (false) /* Find the tail of the list */ #define LIST_FIND_TAIL(name,item,tail) \ do { \ typeof(*(item)) *_item = (item); \ if (!_item) \ (tail) = NULL; \ else { \ while (_item->name##_next) \ _item = _item->name##_next; \ (tail) = _item; \ } \ } while (false) /* Insert an item after another one (a = where, b = what) */ #define LIST_INSERT_AFTER(name,head,a,b) \ do { \ typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \ assert(_b); \ if (!_a) { \ if ((_b->name##_next = *_head)) \ _b->name##_next->name##_prev = _b; \ _b->name##_prev = NULL; \ *_head = _b; \ } else { \ if ((_b->name##_next = _a->name##_next)) \ _b->name##_next->name##_prev = _b; \ _b->name##_prev = _a; \ _a->name##_next = _b; \ } \ } while(false) /* Insert an item before another one (a = where, b = what) */ #define LIST_INSERT_BEFORE(name,head,a,b) \ do { \ typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \ assert(_b); \ if (!_a) { \ if (!*_head) { \ _b->name##_next = NULL; \ _b->name##_prev = NULL; \ *_head = _b; \ } else { \ typeof(*(head)) *_tail = (head); \ while (_tail->name##_next) \ _tail = _tail->name##_next; \ _b->name##_next = NULL; \ _b->name##_prev = _tail; \ _tail->name##_next = _b; \ } \ } else { \ if ((_b->name##_prev = _a->name##_prev)) \ _b->name##_prev->name##_next = _b; \ _b->name##_next = _a; \ _a->name##_prev = _b; \ } \ } while(false) #define LIST_JUST_US(name,item) \ (!(item)->name##_prev && !(item)->name##_next) \ #define LIST_FOREACH(name,i,head) \ for ((i) = (head); (i); (i) = (i)->name##_next) #define LIST_FOREACH_SAFE(name,i,n,head) \ for ((i) = (head); (i) && (((n) = (i)->name##_next), 1); (i) = (n)) #define LIST_FOREACH_BEFORE(name,i,p) \ for ((i) = (p)->name##_prev; (i); (i) = (i)->name##_prev) #define LIST_FOREACH_AFTER(name,i,p) \ for ((i) = (p)->name##_next; (i); (i) = (i)->name##_next) /* Iterate through all the members of the list p is included in, but skip over p */ #define LIST_FOREACH_OTHERS(name,i,p) \ for (({ \ (i) = (p); \ while ((i) && (i)->name##_prev) \ (i) = (i)->name##_prev; \ if ((i) == (p)) \ (i) = (p)->name##_next; \ }); \ (i); \ (i) = (i)->name##_next == (p) ? (p)->name##_next : (i)->name##_next) /* Loop starting from p->next until p->prev. p can be adjusted meanwhile. */ #define LIST_LOOP_BUT_ONE(name,i,head,p) \ for ((i) = (p)->name##_next ? (p)->name##_next : (head); \ (i) != (p); \ (i) = (i)->name##_next ? (i)->name##_next : (head)) systemd-229/src/basic/locale-util.c000066400000000000000000000224371265713322000173170ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include "dirent-util.h" #include "fd-util.h" #include "hashmap.h" #include "locale-util.h" #include "path-util.h" #include "set.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "utf8.h" static int add_locales_from_archive(Set *locales) { /* Stolen from glibc... */ struct locarhead { uint32_t magic; /* Serial number. */ uint32_t serial; /* Name hash table. */ uint32_t namehash_offset; uint32_t namehash_used; uint32_t namehash_size; /* String table. */ uint32_t string_offset; uint32_t string_used; uint32_t string_size; /* Table with locale records. */ uint32_t locrectab_offset; uint32_t locrectab_used; uint32_t locrectab_size; /* MD5 sum hash table. */ uint32_t sumhash_offset; uint32_t sumhash_used; uint32_t sumhash_size; }; struct namehashent { /* Hash value of the name. */ uint32_t hashval; /* Offset of the name in the string table. */ uint32_t name_offset; /* Offset of the locale record. */ uint32_t locrec_offset; }; const struct locarhead *h; const struct namehashent *e; const void *p = MAP_FAILED; _cleanup_close_ int fd = -1; size_t sz = 0; struct stat st; unsigned i; int r; fd = open("/usr/lib/locale/locale-archive", O_RDONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) return errno == ENOENT ? 0 : -errno; if (fstat(fd, &st) < 0) return -errno; if (!S_ISREG(st.st_mode)) return -EBADMSG; if (st.st_size < (off_t) sizeof(struct locarhead)) return -EBADMSG; p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (p == MAP_FAILED) return -errno; h = (const struct locarhead *) p; if (h->magic != 0xde020109 || h->namehash_offset + h->namehash_size > st.st_size || h->string_offset + h->string_size > st.st_size || h->locrectab_offset + h->locrectab_size > st.st_size || h->sumhash_offset + h->sumhash_size > st.st_size) { r = -EBADMSG; goto finish; } e = (const struct namehashent*) ((const uint8_t*) p + h->namehash_offset); for (i = 0; i < h->namehash_size; i++) { char *z; if (e[i].locrec_offset == 0) continue; if (!utf8_is_valid((char*) p + e[i].name_offset)) continue; z = strdup((char*) p + e[i].name_offset); if (!z) { r = -ENOMEM; goto finish; } r = set_consume(locales, z); if (r < 0) goto finish; } r = 0; finish: if (p != MAP_FAILED) munmap((void*) p, sz); return r; } static int add_locales_from_libdir (Set *locales) { _cleanup_closedir_ DIR *dir = NULL; struct dirent *entry; int r; dir = opendir("/usr/lib/locale"); if (!dir) return errno == ENOENT ? 0 : -errno; FOREACH_DIRENT(entry, dir, return -errno) { char *z; if (entry->d_type != DT_DIR) continue; z = strdup(entry->d_name); if (!z) return -ENOMEM; r = set_consume(locales, z); if (r < 0 && r != -EEXIST) return r; } return 0; } int get_locales(char ***ret) { _cleanup_set_free_ Set *locales = NULL; _cleanup_strv_free_ char **l = NULL; int r; locales = set_new(&string_hash_ops); if (!locales) return -ENOMEM; r = add_locales_from_archive(locales); if (r < 0 && r != -ENOENT) return r; r = add_locales_from_libdir(locales); if (r < 0) return r; l = set_get_strv(locales); if (!l) return -ENOMEM; strv_sort(l); *ret = l; l = NULL; return 0; } bool locale_is_valid(const char *name) { if (isempty(name)) return false; if (strlen(name) >= 128) return false; if (!utf8_is_valid(name)) return false; if (!filename_is_valid(name)) return false; if (!string_is_safe(name)) return false; return true; } void init_gettext(void) { setlocale(LC_ALL, ""); textdomain(GETTEXT_PACKAGE); } bool is_locale_utf8(void) { const char *set; static int cached_answer = -1; /* Note that we default to 'true' here, since today UTF8 is * pretty much supported everywhere. */ if (cached_answer >= 0) goto out; if (!setlocale(LC_ALL, "")) { cached_answer = true; goto out; } set = nl_langinfo(CODESET); if (!set) { cached_answer = true; goto out; } if (streq(set, "UTF-8")) { cached_answer = true; goto out; } /* For LC_CTYPE=="C" return true, because CTYPE is effectly * unset and everything can do to UTF-8 nowadays. */ set = setlocale(LC_CTYPE, NULL); if (!set) { cached_answer = true; goto out; } /* Check result, but ignore the result if C was set * explicitly. */ cached_answer = STR_IN_SET(set, "C", "POSIX") && !getenv("LC_ALL") && !getenv("LC_CTYPE") && !getenv("LANG"); out: return (bool) cached_answer; } const char *draw_special_char(DrawSpecialChar ch) { static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = { /* UTF-8 */ { [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */ [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */ [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */ [DRAW_TREE_SPACE] = " ", /* */ [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */ [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */ [DRAW_ARROW] = "\342\206\222", /* → */ [DRAW_DASH] = "\342\200\223", /* – */ }, /* ASCII fallback */ { [DRAW_TREE_VERTICAL] = "| ", [DRAW_TREE_BRANCH] = "|-", [DRAW_TREE_RIGHT] = "`-", [DRAW_TREE_SPACE] = " ", [DRAW_TRIANGULAR_BULLET] = ">", [DRAW_BLACK_CIRCLE] = "*", [DRAW_ARROW] = "->", [DRAW_DASH] = "-", } }; return draw_table[!is_locale_utf8()][ch]; } static const char * const locale_variable_table[_VARIABLE_LC_MAX] = { [VARIABLE_LANG] = "LANG", [VARIABLE_LANGUAGE] = "LANGUAGE", [VARIABLE_LC_CTYPE] = "LC_CTYPE", [VARIABLE_LC_NUMERIC] = "LC_NUMERIC", [VARIABLE_LC_TIME] = "LC_TIME", [VARIABLE_LC_COLLATE] = "LC_COLLATE", [VARIABLE_LC_MONETARY] = "LC_MONETARY", [VARIABLE_LC_MESSAGES] = "LC_MESSAGES", [VARIABLE_LC_PAPER] = "LC_PAPER", [VARIABLE_LC_NAME] = "LC_NAME", [VARIABLE_LC_ADDRESS] = "LC_ADDRESS", [VARIABLE_LC_TELEPHONE] = "LC_TELEPHONE", [VARIABLE_LC_MEASUREMENT] = "LC_MEASUREMENT", [VARIABLE_LC_IDENTIFICATION] = "LC_IDENTIFICATION" }; DEFINE_STRING_TABLE_LOOKUP(locale_variable, LocaleVariable); systemd-229/src/basic/locale-util.h000066400000000000000000000040131265713322000173120ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "macro.h" typedef enum LocaleVariable { /* We don't list LC_ALL here on purpose. People should be * using LANG instead. */ VARIABLE_LANG, VARIABLE_LANGUAGE, VARIABLE_LC_CTYPE, VARIABLE_LC_NUMERIC, VARIABLE_LC_TIME, VARIABLE_LC_COLLATE, VARIABLE_LC_MONETARY, VARIABLE_LC_MESSAGES, VARIABLE_LC_PAPER, VARIABLE_LC_NAME, VARIABLE_LC_ADDRESS, VARIABLE_LC_TELEPHONE, VARIABLE_LC_MEASUREMENT, VARIABLE_LC_IDENTIFICATION, _VARIABLE_LC_MAX, _VARIABLE_LC_INVALID = -1 } LocaleVariable; int get_locales(char ***l); bool locale_is_valid(const char *name); #define _(String) gettext(String) #define N_(String) String void init_gettext(void); bool is_locale_utf8(void); typedef enum DrawSpecialChar { DRAW_TREE_VERTICAL, DRAW_TREE_BRANCH, DRAW_TREE_RIGHT, DRAW_TREE_SPACE, DRAW_TRIANGULAR_BULLET, DRAW_BLACK_CIRCLE, DRAW_ARROW, DRAW_DASH, _DRAW_SPECIAL_CHAR_MAX } DrawSpecialChar; const char *draw_special_char(DrawSpecialChar ch); const char* locale_variable_to_string(LocaleVariable i) _const_; LocaleVariable locale_variable_from_string(const char *s) _pure_; systemd-229/src/basic/lockfile-util.c000066400000000000000000000112411265713322000176370ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "fs-util.h" #include "lockfile-util.h" #include "macro.h" #include "path-util.h" int make_lock_file(const char *p, int operation, LockFile *ret) { _cleanup_close_ int fd = -1; _cleanup_free_ char *t = NULL; int r; /* * We use UNPOSIX locks if they are available. They have nice * semantics, and are mostly compatible with NFS. However, * they are only available on new kernels. When we detect we * are running on an older kernel, then we fall back to good * old BSD locks. They also have nice semantics, but are * slightly problematic on NFS, where they are upgraded to * POSIX locks, even though locally they are orthogonal to * POSIX locks. */ t = strdup(p); if (!t) return -ENOMEM; for (;;) { struct flock fl = { .l_type = (operation & ~LOCK_NB) == LOCK_EX ? F_WRLCK : F_RDLCK, .l_whence = SEEK_SET, }; struct stat st; fd = open(p, O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY, 0600); if (fd < 0) return -errno; r = fcntl(fd, (operation & LOCK_NB) ? F_OFD_SETLK : F_OFD_SETLKW, &fl); if (r < 0) { /* If the kernel is too old, use good old BSD locks */ if (errno == EINVAL) r = flock(fd, operation); if (r < 0) return errno == EAGAIN ? -EBUSY : -errno; } /* If we acquired the lock, let's check if the file * still exists in the file system. If not, then the * previous exclusive owner removed it and then closed * it. In such a case our acquired lock is worthless, * hence try again. */ r = fstat(fd, &st); if (r < 0) return -errno; if (st.st_nlink > 0) break; fd = safe_close(fd); } ret->path = t; ret->fd = fd; ret->operation = operation; fd = -1; t = NULL; return r; } int make_lock_file_for(const char *p, int operation, LockFile *ret) { const char *fn; char *t; assert(p); assert(ret); fn = basename(p); if (!filename_is_valid(fn)) return -EINVAL; t = newa(char, strlen(p) + 2 + 4 + 1); stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), fn), ".lck"); return make_lock_file(t, operation, ret); } void release_lock_file(LockFile *f) { int r; if (!f) return; if (f->path) { /* If we are the exclusive owner we can safely delete * the lock file itself. If we are not the exclusive * owner, we can try becoming it. */ if (f->fd >= 0 && (f->operation & ~LOCK_NB) == LOCK_SH) { static const struct flock fl = { .l_type = F_WRLCK, .l_whence = SEEK_SET, }; r = fcntl(f->fd, F_OFD_SETLK, &fl); if (r < 0 && errno == EINVAL) r = flock(f->fd, LOCK_EX|LOCK_NB); if (r >= 0) f->operation = LOCK_EX|LOCK_NB; } if ((f->operation & ~LOCK_NB) == LOCK_EX) unlink_noerrno(f->path); f->path = mfree(f->path); } f->fd = safe_close(f->fd); f->operation = 0; } systemd-229/src/basic/lockfile-util.h000066400000000000000000000022351265713322000176470ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" #include "missing.h" typedef struct LockFile { char *path; int fd; int operation; } LockFile; int make_lock_file(const char *p, int operation, LockFile *ret); int make_lock_file_for(const char *p, int operation, LockFile *ret); void release_lock_file(LockFile *f); #define _cleanup_release_lock_file_ _cleanup_(release_lock_file) #define LOCK_FILE_INIT { .fd = -1, .path = NULL } systemd-229/src/basic/log.c000066400000000000000000001024101265713322000156540ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sd-messages.h" #include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "io-util.h" #include "log.h" #include "macro.h" #include "missing.h" #include "parse-util.h" #include "proc-cmdline.h" #include "process-util.h" #include "signal-util.h" #include "socket-util.h" #include "stdio-util.h" #include "string-table.h" #include "string-util.h" #include "syslog-util.h" #include "terminal-util.h" #include "time-util.h" #include "util.h" #define SNDBUF_SIZE (8*1024*1024) static LogTarget log_target = LOG_TARGET_CONSOLE; static int log_max_level = LOG_INFO; static int log_facility = LOG_DAEMON; static int console_fd = STDERR_FILENO; static int syslog_fd = -1; static int kmsg_fd = -1; static int journal_fd = -1; static bool syslog_is_stream = false; static bool show_color = false; static bool show_location = false; static bool upgrade_syslog_to_journal = false; /* Akin to glibc's __abort_msg; which is private and we hence cannot * use here. */ static char *log_abort_msg = NULL; void log_close_console(void) { if (console_fd < 0) return; if (getpid() == 1) { if (console_fd >= 3) safe_close(console_fd); console_fd = -1; } } static int log_open_console(void) { if (console_fd >= 0) return 0; if (getpid() == 1) { console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); if (console_fd < 0) return console_fd; } else console_fd = STDERR_FILENO; return 0; } void log_close_kmsg(void) { kmsg_fd = safe_close(kmsg_fd); } static int log_open_kmsg(void) { if (kmsg_fd >= 0) return 0; kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC); if (kmsg_fd < 0) return -errno; return 0; } void log_close_syslog(void) { syslog_fd = safe_close(syslog_fd); } static int create_log_socket(int type) { struct timeval tv; int fd; fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0); if (fd < 0) return -errno; fd_inc_sndbuf(fd, SNDBUF_SIZE); /* We need a blocking fd here since we'd otherwise lose messages way too early. However, let's not hang forever in the unlikely case of a deadlock. */ if (getpid() == 1) timeval_store(&tv, 10 * USEC_PER_MSEC); else timeval_store(&tv, 10 * USEC_PER_SEC); (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); return fd; } static int log_open_syslog(void) { static const union sockaddr_union sa = { .un.sun_family = AF_UNIX, .un.sun_path = "/dev/log", }; int r; if (syslog_fd >= 0) return 0; syslog_fd = create_log_socket(SOCK_DGRAM); if (syslog_fd < 0) { r = syslog_fd; goto fail; } if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) { safe_close(syslog_fd); /* Some legacy syslog systems still use stream * sockets. They really shouldn't. But what can we * do... */ syslog_fd = create_log_socket(SOCK_STREAM); if (syslog_fd < 0) { r = syslog_fd; goto fail; } if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) { r = -errno; goto fail; } syslog_is_stream = true; } else syslog_is_stream = false; return 0; fail: log_close_syslog(); return r; } void log_close_journal(void) { journal_fd = safe_close(journal_fd); } static int log_open_journal(void) { static const union sockaddr_union sa = { .un.sun_family = AF_UNIX, .un.sun_path = "/run/systemd/journal/socket", }; int r; if (journal_fd >= 0) return 0; journal_fd = create_log_socket(SOCK_DGRAM); if (journal_fd < 0) { r = journal_fd; goto fail; } if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) { r = -errno; goto fail; } return 0; fail: log_close_journal(); return r; } int log_open(void) { int r; /* If we don't use the console we close it here, to not get * killed by SAK. If we don't use syslog we close it here so * that we are not confused by somebody deleting the socket in * the fs. If we don't use /dev/kmsg we still keep it open, * because there is no reason to close it. */ if (log_target == LOG_TARGET_NULL) { log_close_journal(); log_close_syslog(); log_close_console(); return 0; } if ((log_target != LOG_TARGET_AUTO && log_target != LOG_TARGET_SAFE) || getpid() == 1 || isatty(STDERR_FILENO) <= 0) { if (log_target == LOG_TARGET_AUTO || log_target == LOG_TARGET_JOURNAL_OR_KMSG || log_target == LOG_TARGET_JOURNAL) { r = log_open_journal(); if (r >= 0) { log_close_syslog(); log_close_console(); return r; } } if (log_target == LOG_TARGET_SYSLOG_OR_KMSG || log_target == LOG_TARGET_SYSLOG) { r = log_open_syslog(); if (r >= 0) { log_close_journal(); log_close_console(); return r; } } if (log_target == LOG_TARGET_AUTO || log_target == LOG_TARGET_SAFE || log_target == LOG_TARGET_JOURNAL_OR_KMSG || log_target == LOG_TARGET_SYSLOG_OR_KMSG || log_target == LOG_TARGET_KMSG) { r = log_open_kmsg(); if (r >= 0) { log_close_journal(); log_close_syslog(); log_close_console(); return r; } } } log_close_journal(); log_close_syslog(); return log_open_console(); } void log_set_target(LogTarget target) { assert(target >= 0); assert(target < _LOG_TARGET_MAX); if (upgrade_syslog_to_journal) { if (target == LOG_TARGET_SYSLOG) target = LOG_TARGET_JOURNAL; else if (target == LOG_TARGET_SYSLOG_OR_KMSG) target = LOG_TARGET_JOURNAL_OR_KMSG; } log_target = target; } void log_close(void) { log_close_journal(); log_close_syslog(); log_close_kmsg(); log_close_console(); } void log_forget_fds(void) { console_fd = kmsg_fd = syslog_fd = journal_fd = -1; } void log_set_max_level(int level) { assert((level & LOG_PRIMASK) == level); log_max_level = level; } void log_set_facility(int facility) { log_facility = facility; } static int write_to_console( int level, int error, const char *file, int line, const char *func, const char *object_field, const char *object, const char *buffer) { char location[64], prefix[1 + DECIMAL_STR_MAX(int) + 2]; struct iovec iovec[6] = {}; unsigned n = 0; bool highlight; if (console_fd < 0) return 0; if (log_target == LOG_TARGET_CONSOLE_PREFIXED) { sprintf(prefix, "<%i>", level); IOVEC_SET_STRING(iovec[n++], prefix); } highlight = LOG_PRI(level) <= LOG_ERR && show_color; if (show_location) { xsprintf(location, "(%s:%i) ", file, line); IOVEC_SET_STRING(iovec[n++], location); } if (highlight) IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED); IOVEC_SET_STRING(iovec[n++], buffer); if (highlight) IOVEC_SET_STRING(iovec[n++], ANSI_NORMAL); IOVEC_SET_STRING(iovec[n++], "\n"); if (writev(console_fd, iovec, n) < 0) { if (errno == EIO && getpid() == 1) { /* If somebody tried to kick us from our * console tty (via vhangup() or suchlike), * try to reconnect */ log_close_console(); log_open_console(); if (console_fd < 0) return 0; if (writev(console_fd, iovec, n) < 0) return -errno; } else return -errno; } return 1; } static int write_to_syslog( int level, int error, const char *file, int line, const char *func, const char *object_field, const char *object, const char *buffer) { char header_priority[2 + DECIMAL_STR_MAX(int) + 1], header_time[64], header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1]; struct iovec iovec[5] = {}; struct msghdr msghdr = { .msg_iov = iovec, .msg_iovlen = ELEMENTSOF(iovec), }; time_t t; struct tm *tm; if (syslog_fd < 0) return 0; xsprintf(header_priority, "<%i>", level); t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC); tm = localtime(&t); if (!tm) return -EINVAL; if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0) return -EINVAL; xsprintf(header_pid, "["PID_FMT"]: ", getpid()); IOVEC_SET_STRING(iovec[0], header_priority); IOVEC_SET_STRING(iovec[1], header_time); IOVEC_SET_STRING(iovec[2], program_invocation_short_name); IOVEC_SET_STRING(iovec[3], header_pid); IOVEC_SET_STRING(iovec[4], buffer); /* When using syslog via SOCK_STREAM separate the messages by NUL chars */ if (syslog_is_stream) iovec[4].iov_len++; for (;;) { ssize_t n; n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL); if (n < 0) return -errno; if (!syslog_is_stream || (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec))) break; IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n); } return 1; } static int write_to_kmsg( int level, int error, const char *file, int line, const char *func, const char *object_field, const char *object, const char *buffer) { char header_priority[2 + DECIMAL_STR_MAX(int) + 1], header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1]; struct iovec iovec[5] = {}; if (kmsg_fd < 0) return 0; xsprintf(header_priority, "<%i>", level); xsprintf(header_pid, "["PID_FMT"]: ", getpid()); IOVEC_SET_STRING(iovec[0], header_priority); IOVEC_SET_STRING(iovec[1], program_invocation_short_name); IOVEC_SET_STRING(iovec[2], header_pid); IOVEC_SET_STRING(iovec[3], buffer); IOVEC_SET_STRING(iovec[4], "\n"); if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0) return -errno; return 1; } static int log_do_header( char *header, size_t size, int level, int error, const char *file, int line, const char *func, const char *object_field, const char *object) { snprintf(header, size, "PRIORITY=%i\n" "SYSLOG_FACILITY=%i\n" "%s%s%s" "%s%.*i%s" "%s%s%s" "%s%.*i%s" "%s%s%s" "SYSLOG_IDENTIFIER=%s\n", LOG_PRI(level), LOG_FAC(level), isempty(file) ? "" : "CODE_FILE=", isempty(file) ? "" : file, isempty(file) ? "" : "\n", line ? "CODE_LINE=" : "", line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */ line ? "\n" : "", isempty(func) ? "" : "CODE_FUNCTION=", isempty(func) ? "" : func, isempty(func) ? "" : "\n", error ? "ERRNO=" : "", error ? 1 : 0, error, error ? "\n" : "", isempty(object) ? "" : object_field, isempty(object) ? "" : object, isempty(object) ? "" : "\n", program_invocation_short_name); return 0; } static int write_to_journal( int level, int error, const char *file, int line, const char *func, const char *object_field, const char *object, const char *buffer) { char header[LINE_MAX]; struct iovec iovec[4] = {}; struct msghdr mh = {}; if (journal_fd < 0) return 0; log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object); IOVEC_SET_STRING(iovec[0], header); IOVEC_SET_STRING(iovec[1], "MESSAGE="); IOVEC_SET_STRING(iovec[2], buffer); IOVEC_SET_STRING(iovec[3], "\n"); mh.msg_iov = iovec; mh.msg_iovlen = ELEMENTSOF(iovec); if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0) return -errno; return 1; } static int log_dispatch( int level, int error, const char *file, int line, const char *func, const char *object_field, const char *object, char *buffer) { assert(buffer); if (log_target == LOG_TARGET_NULL) return -error; /* Patch in LOG_DAEMON facility if necessary */ if ((level & LOG_FACMASK) == 0) level = log_facility | LOG_PRI(level); if (error < 0) error = -error; do { char *e; int k = 0; buffer += strspn(buffer, NEWLINE); if (buffer[0] == 0) break; if ((e = strpbrk(buffer, NEWLINE))) *(e++) = 0; if (log_target == LOG_TARGET_AUTO || log_target == LOG_TARGET_JOURNAL_OR_KMSG || log_target == LOG_TARGET_JOURNAL) { k = write_to_journal(level, error, file, line, func, object_field, object, buffer); if (k < 0) { if (k != -EAGAIN) log_close_journal(); log_open_kmsg(); } } if (log_target == LOG_TARGET_SYSLOG_OR_KMSG || log_target == LOG_TARGET_SYSLOG) { k = write_to_syslog(level, error, file, line, func, object_field, object, buffer); if (k < 0) { if (k != -EAGAIN) log_close_syslog(); log_open_kmsg(); } } if (k <= 0 && (log_target == LOG_TARGET_AUTO || log_target == LOG_TARGET_SAFE || log_target == LOG_TARGET_SYSLOG_OR_KMSG || log_target == LOG_TARGET_JOURNAL_OR_KMSG || log_target == LOG_TARGET_KMSG)) { k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer); if (k < 0) { log_close_kmsg(); log_open_console(); } } if (k <= 0) (void) write_to_console(level, error, file, line, func, object_field, object, buffer); buffer = e; } while (buffer); return -error; } int log_dump_internal( int level, int error, const char *file, int line, const char *func, char *buffer) { PROTECT_ERRNO; /* This modifies the buffer... */ if (error < 0) error = -error; if (_likely_(LOG_PRI(level) > log_max_level)) return -error; return log_dispatch(level, error, file, line, func, NULL, NULL, buffer); } int log_internalv( int level, int error, const char *file, int line, const char *func, const char *format, va_list ap) { PROTECT_ERRNO; char buffer[LINE_MAX]; if (error < 0) error = -error; if (_likely_(LOG_PRI(level) > log_max_level)) return -error; /* Make sure that %m maps to the specified error */ if (error != 0) errno = error; vsnprintf(buffer, sizeof(buffer), format, ap); return log_dispatch(level, error, file, line, func, NULL, NULL, buffer); } int log_internal( int level, int error, const char *file, int line, const char *func, const char *format, ...) { va_list ap; int r; va_start(ap, format); r = log_internalv(level, error, file, line, func, format, ap); va_end(ap); return r; } int log_object_internalv( int level, int error, const char *file, int line, const char *func, const char *object_field, const char *object, const char *format, va_list ap) { PROTECT_ERRNO; char *buffer, *b; size_t l; if (error < 0) error = -error; if (_likely_(LOG_PRI(level) > log_max_level)) return -error; /* Make sure that %m maps to the specified error */ if (error != 0) errno = error; /* Prepend the object name before the message */ if (object) { size_t n; n = strlen(object); l = n + 2 + LINE_MAX; buffer = newa(char, l); b = stpcpy(stpcpy(buffer, object), ": "); } else { l = LINE_MAX; b = buffer = newa(char, l); } vsnprintf(b, l, format, ap); return log_dispatch(level, error, file, line, func, object_field, object, buffer); } int log_object_internal( int level, int error, const char *file, int line, const char *func, const char *object_field, const char *object, const char *format, ...) { va_list ap; int r; va_start(ap, format); r = log_object_internalv(level, error, file, line, func, object_field, object, format, ap); va_end(ap); return r; } static void log_assert( int level, const char *text, const char *file, int line, const char *func, const char *format) { static char buffer[LINE_MAX]; if (_likely_(LOG_PRI(level) > log_max_level)) return; DISABLE_WARNING_FORMAT_NONLITERAL; xsprintf(buffer, format, text, file, line, func); REENABLE_WARNING; log_abort_msg = buffer; log_dispatch(level, 0, file, line, func, NULL, NULL, buffer); } noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) { log_assert(LOG_CRIT, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting."); abort(); } noreturn void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) { log_assert(LOG_CRIT, text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting."); abort(); } void log_assert_failed_return(const char *text, const char *file, int line, const char *func) { PROTECT_ERRNO; log_assert(LOG_DEBUG, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring."); } int log_oom_internal(const char *file, int line, const char *func) { log_internal(LOG_ERR, ENOMEM, file, line, func, "Out of memory."); return -ENOMEM; } int log_format_iovec( struct iovec *iovec, unsigned iovec_len, unsigned *n, bool newline_separator, int error, const char *format, va_list ap) { static const char nl = '\n'; while (format && *n + 1 < iovec_len) { va_list aq; char *m; int r; /* We need to copy the va_list structure, * since vasprintf() leaves it afterwards at * an undefined location */ if (error != 0) errno = error; va_copy(aq, ap); r = vasprintf(&m, format, aq); va_end(aq); if (r < 0) return -EINVAL; /* Now, jump enough ahead, so that we point to * the next format string */ VA_FORMAT_ADVANCE(format, ap); IOVEC_SET_STRING(iovec[(*n)++], m); if (newline_separator) { iovec[*n].iov_base = (char*) &nl; iovec[*n].iov_len = 1; (*n)++; } format = va_arg(ap, char *); } return 0; } int log_struct_internal( int level, int error, const char *file, int line, const char *func, const char *format, ...) { char buf[LINE_MAX]; bool found = false; PROTECT_ERRNO; va_list ap; if (error < 0) error = -error; if (_likely_(LOG_PRI(level) > log_max_level)) return -error; if (log_target == LOG_TARGET_NULL) return -error; if ((level & LOG_FACMASK) == 0) level = log_facility | LOG_PRI(level); if ((log_target == LOG_TARGET_AUTO || log_target == LOG_TARGET_JOURNAL_OR_KMSG || log_target == LOG_TARGET_JOURNAL) && journal_fd >= 0) { char header[LINE_MAX]; struct iovec iovec[17] = {}; unsigned n = 0, i; int r; struct msghdr mh = { .msg_iov = iovec, }; bool fallback = false; /* If the journal is available do structured logging */ log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL); IOVEC_SET_STRING(iovec[n++], header); va_start(ap, format); r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap); if (r < 0) fallback = true; else { mh.msg_iovlen = n; (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL); } va_end(ap); for (i = 1; i < n; i += 2) free(iovec[i].iov_base); if (!fallback) return -error; } /* Fallback if journal logging is not available or didn't work. */ va_start(ap, format); while (format) { va_list aq; if (error != 0) errno = error; va_copy(aq, ap); vsnprintf(buf, sizeof(buf), format, aq); va_end(aq); if (startswith(buf, "MESSAGE=")) { found = true; break; } VA_FORMAT_ADVANCE(format, ap); format = va_arg(ap, char *); } va_end(ap); if (!found) return -error; return log_dispatch(level, error, file, line, func, NULL, NULL, buf + 8); } int log_set_target_from_string(const char *e) { LogTarget t; t = log_target_from_string(e); if (t < 0) return -EINVAL; log_set_target(t); return 0; } int log_set_max_level_from_string(const char *e) { int t; t = log_level_from_string(e); if (t < 0) return -EINVAL; log_set_max_level(t); return 0; } static int parse_proc_cmdline_item(const char *key, const char *value) { /* * The systemd.log_xyz= settings are parsed by all tools, and * so is "debug". * * However, "quiet" is only parsed by PID 1, and only turns of * status output to /dev/console, but does not alter the log * level. */ if (streq(key, "debug") && !value) log_set_max_level(LOG_DEBUG); else if (streq(key, "systemd.log_target") && value) { if (log_set_target_from_string(value) < 0) log_warning("Failed to parse log target '%s'. Ignoring.", value); } else if (streq(key, "systemd.log_level") && value) { if (log_set_max_level_from_string(value) < 0) log_warning("Failed to parse log level '%s'. Ignoring.", value); } else if (streq(key, "systemd.log_color") && value) { if (log_show_color_from_string(value) < 0) log_warning("Failed to parse log color setting '%s'. Ignoring.", value); } else if (streq(key, "systemd.log_location") && value) { if (log_show_location_from_string(value) < 0) log_warning("Failed to parse log location setting '%s'. Ignoring.", value); } return 0; } void log_parse_environment(void) { const char *e; if (get_ctty_devnr(0, NULL) < 0) /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is user stuff. */ (void) parse_proc_cmdline(parse_proc_cmdline_item); e = secure_getenv("SYSTEMD_LOG_TARGET"); if (e && log_set_target_from_string(e) < 0) log_warning("Failed to parse log target '%s'. Ignoring.", e); e = secure_getenv("SYSTEMD_LOG_LEVEL"); if (e && log_set_max_level_from_string(e) < 0) log_warning("Failed to parse log level '%s'. Ignoring.", e); e = secure_getenv("SYSTEMD_LOG_COLOR"); if (e && log_show_color_from_string(e) < 0) log_warning("Failed to parse bool '%s'. Ignoring.", e); e = secure_getenv("SYSTEMD_LOG_LOCATION"); if (e && log_show_location_from_string(e) < 0) log_warning("Failed to parse bool '%s'. Ignoring.", e); } LogTarget log_get_target(void) { return log_target; } int log_get_max_level(void) { return log_max_level; } void log_show_color(bool b) { show_color = b; } bool log_get_show_color(void) { return show_color; } void log_show_location(bool b) { show_location = b; } bool log_get_show_location(void) { return show_location; } int log_show_color_from_string(const char *e) { int t; t = parse_boolean(e); if (t < 0) return t; log_show_color(t); return 0; } int log_show_location_from_string(const char *e) { int t; t = parse_boolean(e); if (t < 0) return t; log_show_location(t); return 0; } bool log_on_console(void) { if (log_target == LOG_TARGET_CONSOLE || log_target == LOG_TARGET_CONSOLE_PREFIXED) return true; return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0; } static const char *const log_target_table[_LOG_TARGET_MAX] = { [LOG_TARGET_CONSOLE] = "console", [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed", [LOG_TARGET_KMSG] = "kmsg", [LOG_TARGET_JOURNAL] = "journal", [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg", [LOG_TARGET_SYSLOG] = "syslog", [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg", [LOG_TARGET_AUTO] = "auto", [LOG_TARGET_SAFE] = "safe", [LOG_TARGET_NULL] = "null" }; DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget); void log_received_signal(int level, const struct signalfd_siginfo *si) { if (si->ssi_pid > 0) { _cleanup_free_ char *p = NULL; get_process_comm(si->ssi_pid, &p); log_full(level, "Received SIG%s from PID %"PRIu32" (%s).", signal_to_string(si->ssi_signo), si->ssi_pid, strna(p)); } else log_full(level, "Received SIG%s.", signal_to_string(si->ssi_signo)); } void log_set_upgrade_syslog_to_journal(bool b) { upgrade_syslog_to_journal = b; } int log_syntax_internal( const char *unit, int level, const char *config_file, unsigned config_line, int error, const char *file, int line, const char *func, const char *format, ...) { PROTECT_ERRNO; char buffer[LINE_MAX]; int r; va_list ap; if (error < 0) error = -error; if (_likely_(LOG_PRI(level) > log_max_level)) return -error; if (log_target == LOG_TARGET_NULL) return -error; if (error != 0) errno = error; va_start(ap, format); vsnprintf(buffer, sizeof(buffer), format, ap); va_end(ap); if (unit) r = log_struct_internal( level, error, file, line, func, getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit, LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION), "CONFIG_FILE=%s", config_file, "CONFIG_LINE=%u", config_line, LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer), NULL); else r = log_struct_internal( level, error, file, line, func, LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION), "CONFIG_FILE=%s", config_file, "CONFIG_LINE=%u", config_line, LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer), NULL); return r; } systemd-229/src/basic/log.h000066400000000000000000000214721265713322000156710ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "sd-id128.h" #include "macro.h" typedef enum LogTarget{ LOG_TARGET_CONSOLE, LOG_TARGET_CONSOLE_PREFIXED, LOG_TARGET_KMSG, LOG_TARGET_JOURNAL, LOG_TARGET_JOURNAL_OR_KMSG, LOG_TARGET_SYSLOG, LOG_TARGET_SYSLOG_OR_KMSG, LOG_TARGET_AUTO, /* console if stderr is tty, JOURNAL_OR_KMSG otherwise */ LOG_TARGET_SAFE, /* console if stderr is tty, KMSG otherwise */ LOG_TARGET_NULL, _LOG_TARGET_MAX, _LOG_TARGET_INVALID = -1 } LogTarget; void log_set_target(LogTarget target); void log_set_max_level(int level); void log_set_facility(int facility); int log_set_target_from_string(const char *e); int log_set_max_level_from_string(const char *e); void log_show_color(bool b); bool log_get_show_color(void) _pure_; void log_show_location(bool b); bool log_get_show_location(void) _pure_; int log_show_color_from_string(const char *e); int log_show_location_from_string(const char *e); LogTarget log_get_target(void) _pure_; int log_get_max_level(void) _pure_; int log_open(void); void log_close(void); void log_forget_fds(void); void log_close_syslog(void); void log_close_journal(void); void log_close_kmsg(void); void log_close_console(void); void log_parse_environment(void); int log_internal( int level, int error, const char *file, int line, const char *func, const char *format, ...) _printf_(6,7); int log_internalv( int level, int error, const char *file, int line, const char *func, const char *format, va_list ap) _printf_(6,0); int log_object_internal( int level, int error, const char *file, int line, const char *func, const char *object_field, const char *object, const char *format, ...) _printf_(8,9); int log_object_internalv( int level, int error, const char*file, int line, const char *func, const char *object_field, const char *object, const char *format, va_list ap) _printf_(8,0); int log_struct_internal( int level, int error, const char *file, int line, const char *func, const char *format, ...) _printf_(6,0) _sentinel_; int log_oom_internal( const char *file, int line, const char *func); int log_format_iovec( struct iovec *iovec, unsigned iovec_len, unsigned *n, bool newline_separator, int error, const char *format, va_list ap); /* This modifies the buffer passed! */ int log_dump_internal( int level, int error, const char *file, int line, const char *func, char *buffer); /* Logging for various assertions */ noreturn void log_assert_failed( const char *text, const char *file, int line, const char *func); noreturn void log_assert_failed_unreachable( const char *text, const char *file, int line, const char *func); void log_assert_failed_return( const char *text, const char *file, int line, const char *func); /* Logging with level */ #define log_full_errno(level, error, ...) \ ({ \ int _level = (level), _e = (error); \ (log_get_max_level() >= LOG_PRI(_level)) \ ? log_internal(_level, _e, __FILE__, __LINE__, __func__, __VA_ARGS__) \ : -abs(_e); \ }) #define log_full(level, ...) log_full_errno(level, 0, __VA_ARGS__) /* Normal logging */ #define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__) #define log_info(...) log_full(LOG_INFO, __VA_ARGS__) #define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__) #define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__) #define log_error(...) log_full(LOG_ERR, __VA_ARGS__) #define log_emergency(...) log_full(getpid() == 1 ? LOG_EMERG : LOG_ERR, __VA_ARGS__) /* Logging triggered by an errno-like error */ #define log_debug_errno(error, ...) log_full_errno(LOG_DEBUG, error, __VA_ARGS__) #define log_info_errno(error, ...) log_full_errno(LOG_INFO, error, __VA_ARGS__) #define log_notice_errno(error, ...) log_full_errno(LOG_NOTICE, error, __VA_ARGS__) #define log_warning_errno(error, ...) log_full_errno(LOG_WARNING, error, __VA_ARGS__) #define log_error_errno(error, ...) log_full_errno(LOG_ERR, error, __VA_ARGS__) #define log_emergency_errno(error, ...) log_full_errno(getpid() == 1 ? LOG_EMERG : LOG_ERR, error, __VA_ARGS__) #ifdef LOG_TRACE # define log_trace(...) log_debug(__VA_ARGS__) #else # define log_trace(...) do {} while(0) #endif /* Structured logging */ #define log_struct(level, ...) log_struct_internal(level, 0, __FILE__, __LINE__, __func__, __VA_ARGS__) #define log_struct_errno(level, error, ...) log_struct_internal(level, error, __FILE__, __LINE__, __func__, __VA_ARGS__) /* This modifies the buffer passed! */ #define log_dump(level, buffer) log_dump_internal(level, 0, __FILE__, __LINE__, __func__, buffer) #define log_oom() log_oom_internal(__FILE__, __LINE__, __func__) bool log_on_console(void) _pure_; const char *log_target_to_string(LogTarget target) _const_; LogTarget log_target_from_string(const char *s) _pure_; /* Helpers to prepare various fields for structured logging */ #define LOG_MESSAGE(fmt, ...) "MESSAGE=" fmt, ##__VA_ARGS__ #define LOG_MESSAGE_ID(x) "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(x) void log_received_signal(int level, const struct signalfd_siginfo *si); void log_set_upgrade_syslog_to_journal(bool b); int log_syntax_internal( const char *unit, int level, const char *config_file, unsigned config_line, int error, const char *file, int line, const char *func, const char *format, ...) _printf_(9, 10); #define log_syntax(unit, level, config_file, config_line, error, ...) \ ({ \ int _level = (level), _e = (error); \ (log_get_max_level() >= LOG_PRI(_level)) \ ? log_syntax_internal(unit, _level, config_file, config_line, _e, __FILE__, __LINE__, __func__, __VA_ARGS__) \ : -abs(_e); \ }) #define log_syntax_invalid_utf8(unit, level, config_file, config_line, rvalue) \ ({ \ int _level = (level); \ if (log_get_max_level() >= LOG_PRI(_level)) { \ _cleanup_free_ char *_p = NULL; \ _p = utf8_escape_invalid(rvalue); \ log_syntax_internal(unit, _level, config_file, config_line, 0, __FILE__, __LINE__, __func__, \ "String is not UTF-8 clean, ignoring assignment: %s", strna(_p)); \ } \ -EINVAL; \ }) systemd-229/src/basic/login-util.c000066400000000000000000000016721265713322000171660ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "login-util.h" #include "string-util.h" bool session_id_valid(const char *id) { if (isempty(id)) return false; return id[strspn(id, LETTERS DIGITS)] == '\0'; } systemd-229/src/basic/login-util.h000066400000000000000000000016361265713322000171730ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include #include bool session_id_valid(const char *id); static inline bool logind_running(void) { return access("/run/systemd/seats/", F_OK) >= 0; } systemd-229/src/basic/macro.h000066400000000000000000000426311265713322000162110ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #define _printf_(a,b) __attribute__ ((format (printf, a, b))) #define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__))) #define _sentinel_ __attribute__ ((sentinel)) #define _unused_ __attribute__ ((unused)) #define _destructor_ __attribute__ ((destructor)) #define _pure_ __attribute__ ((pure)) #define _const_ __attribute__ ((const)) #define _deprecated_ __attribute__ ((deprecated)) #define _packed_ __attribute__ ((packed)) #define _malloc_ __attribute__ ((malloc)) #define _weak_ __attribute__ ((weak)) #define _likely_(x) (__builtin_expect(!!(x),1)) #define _unlikely_(x) (__builtin_expect(!!(x),0)) #define _public_ __attribute__ ((visibility("default"))) #define _hidden_ __attribute__ ((visibility("hidden"))) #define _weakref_(x) __attribute__((weakref(#x))) #define _alignas_(x) __attribute__((aligned(__alignof(x)))) #define _cleanup_(x) __attribute__((cleanup(x))) /* Temporarily disable some warnings */ #define DISABLE_WARNING_DECLARATION_AFTER_STATEMENT \ _Pragma("GCC diagnostic push"); \ _Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"") #define DISABLE_WARNING_FORMAT_NONLITERAL \ _Pragma("GCC diagnostic push"); \ _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"") #define DISABLE_WARNING_MISSING_PROTOTYPES \ _Pragma("GCC diagnostic push"); \ _Pragma("GCC diagnostic ignored \"-Wmissing-prototypes\"") #define DISABLE_WARNING_NONNULL \ _Pragma("GCC diagnostic push"); \ _Pragma("GCC diagnostic ignored \"-Wnonnull\"") #define DISABLE_WARNING_SHADOW \ _Pragma("GCC diagnostic push"); \ _Pragma("GCC diagnostic ignored \"-Wshadow\"") #define DISABLE_WARNING_INCOMPATIBLE_POINTER_TYPES \ _Pragma("GCC diagnostic push"); \ _Pragma("GCC diagnostic ignored \"-Wincompatible-pointer-types\"") #define REENABLE_WARNING \ _Pragma("GCC diagnostic pop") /* automake test harness */ #define EXIT_TEST_SKIP 77 #define XSTRINGIFY(x) #x #define STRINGIFY(x) XSTRINGIFY(x) #define XCONCATENATE(x, y) x ## y #define CONCATENATE(x, y) XCONCATENATE(x, y) #define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq)) #define UNIQ __COUNTER__ /* Rounds up */ #define ALIGN4(l) (((l) + 3) & ~3) #define ALIGN8(l) (((l) + 7) & ~7) #if __SIZEOF_POINTER__ == 8 #define ALIGN(l) ALIGN8(l) #elif __SIZEOF_POINTER__ == 4 #define ALIGN(l) ALIGN4(l) #else #error "Wut? Pointers are neither 4 nor 8 bytes long?" #endif #define ALIGN_PTR(p) ((void*) ALIGN((unsigned long) (p))) #define ALIGN4_PTR(p) ((void*) ALIGN4((unsigned long) (p))) #define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) (p))) static inline size_t ALIGN_TO(size_t l, size_t ali) { return ((l + ali - 1) & ~(ali - 1)); } #define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) (p), (ali))) /* align to next higher power-of-2 (except for: 0 => 0, overflow => 0) */ static inline unsigned long ALIGN_POWER2(unsigned long u) { /* clz(0) is undefined */ if (u == 1) return 1; /* left-shift overflow is undefined */ if (__builtin_clzl(u - 1UL) < 1) return 0; return 1UL << (sizeof(u) * 8 - __builtin_clzl(u - 1UL)); } #define ELEMENTSOF(x) \ __extension__ (__builtin_choose_expr( \ !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \ sizeof(x)/sizeof((x)[0]), \ (void)0)) /* * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. */ #define container_of(ptr, type, member) __container_of(UNIQ, (ptr), type, member) #define __container_of(uniq, ptr, type, member) \ __extension__ ({ \ const typeof( ((type*)0)->member ) *UNIQ_T(A, uniq) = (ptr); \ (type*)( (char *)UNIQ_T(A, uniq) - offsetof(type,member) ); \ }) #undef MAX #define MAX(a, b) __MAX(UNIQ, (a), UNIQ, (b)) #define __MAX(aq, a, bq, b) \ __extension__ ({ \ const typeof(a) UNIQ_T(A, aq) = (a); \ const typeof(b) UNIQ_T(B, bq) = (b); \ UNIQ_T(A,aq) > UNIQ_T(B,bq) ? UNIQ_T(A,aq) : UNIQ_T(B,bq); \ }) /* evaluates to (void) if _A or _B are not constant or of different types */ #define CONST_MAX(_A, _B) \ __extension__ (__builtin_choose_expr( \ __builtin_constant_p(_A) && \ __builtin_constant_p(_B) && \ __builtin_types_compatible_p(typeof(_A), typeof(_B)), \ ((_A) > (_B)) ? (_A) : (_B), \ (void)0)) /* takes two types and returns the size of the larger one */ #define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; })) #define MAX3(x,y,z) \ __extension__ ({ \ const typeof(x) _c = MAX(x,y); \ MAX(_c, z); \ }) #undef MIN #define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b)) #define __MIN(aq, a, bq, b) \ __extension__ ({ \ const typeof(a) UNIQ_T(A, aq) = (a); \ const typeof(b) UNIQ_T(B, bq) = (b); \ UNIQ_T(A,aq) < UNIQ_T(B,bq) ? UNIQ_T(A,aq) : UNIQ_T(B,bq); \ }) #define MIN3(x,y,z) \ __extension__ ({ \ const typeof(x) _c = MIN(x,y); \ MIN(_c, z); \ }) #define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b)) #define __LESS_BY(aq, a, bq, b) \ __extension__ ({ \ const typeof(a) UNIQ_T(A, aq) = (a); \ const typeof(b) UNIQ_T(B, bq) = (b); \ UNIQ_T(A,aq) > UNIQ_T(B,bq) ? UNIQ_T(A,aq) - UNIQ_T(B,bq) : 0; \ }) #undef CLAMP #define CLAMP(x, low, high) __CLAMP(UNIQ, (x), UNIQ, (low), UNIQ, (high)) #define __CLAMP(xq, x, lowq, low, highq, high) \ __extension__ ({ \ const typeof(x) UNIQ_T(X,xq) = (x); \ const typeof(low) UNIQ_T(LOW,lowq) = (low); \ const typeof(high) UNIQ_T(HIGH,highq) = (high); \ UNIQ_T(X,xq) > UNIQ_T(HIGH,highq) ? \ UNIQ_T(HIGH,highq) : \ UNIQ_T(X,xq) < UNIQ_T(LOW,lowq) ? \ UNIQ_T(LOW,lowq) : \ UNIQ_T(X,xq); \ }) /* [(x + y - 1) / y] suffers from an integer overflow, even though the * computation should be possible in the given type. Therefore, we use * [x / y + !!(x % y)]. Note that on "Real CPUs" a division returns both the * quotient and the remainder, so both should be equally fast. */ #define DIV_ROUND_UP(_x, _y) \ __extension__ ({ \ const typeof(_x) __x = (_x); \ const typeof(_y) __y = (_y); \ (__x / __y + !!(__x % __y)); \ }) #define assert_message_se(expr, message) \ do { \ if (_unlikely_(!(expr))) \ log_assert_failed(message, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ } while (false) #define assert_se(expr) assert_message_se(expr, #expr) /* We override the glibc assert() here. */ #undef assert #ifdef NDEBUG #define assert(expr) do {} while(false) #else #define assert(expr) assert_message_se(expr, #expr) #endif #define assert_not_reached(t) \ do { \ log_assert_failed_unreachable(t, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ } while (false) #if defined(static_assert) /* static_assert() is sometimes defined in a way that trips up * -Wdeclaration-after-statement, hence let's temporarily turn off * this warning around it. */ #define assert_cc(expr) \ DISABLE_WARNING_DECLARATION_AFTER_STATEMENT; \ static_assert(expr, #expr); \ REENABLE_WARNING #else #define assert_cc(expr) \ DISABLE_WARNING_DECLARATION_AFTER_STATEMENT; \ struct CONCATENATE(_assert_struct_, __COUNTER__) { \ char x[(expr) ? 0 : -1]; \ }; \ REENABLE_WARNING #endif #define assert_log(expr, message) ((_likely_(expr)) \ ? (true) \ : (log_assert_failed_return(message, __FILE__, __LINE__, __PRETTY_FUNCTION__), false)) #define assert_return(expr, r) \ do { \ if (!assert_log(expr, #expr)) \ return (r); \ } while (false) #define assert_return_errno(expr, r, err) \ do { \ if (!assert_log(expr, #expr)) { \ errno = err; \ return (r); \ } \ } while (false) #define PTR_TO_INT(p) ((int) ((intptr_t) (p))) #define INT_TO_PTR(u) ((void *) ((intptr_t) (u))) #define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p))) #define UINT_TO_PTR(u) ((void *) ((uintptr_t) (u))) #define PTR_TO_LONG(p) ((long) ((intptr_t) (p))) #define LONG_TO_PTR(u) ((void *) ((intptr_t) (u))) #define PTR_TO_ULONG(p) ((unsigned long) ((uintptr_t) (p))) #define ULONG_TO_PTR(u) ((void *) ((uintptr_t) (u))) #define PTR_TO_INT32(p) ((int32_t) ((intptr_t) (p))) #define INT32_TO_PTR(u) ((void *) ((intptr_t) (u))) #define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p))) #define UINT32_TO_PTR(u) ((void *) ((uintptr_t) (u))) #define PTR_TO_INT64(p) ((int64_t) ((intptr_t) (p))) #define INT64_TO_PTR(u) ((void *) ((intptr_t) (u))) #define PTR_TO_UINT64(p) ((uint64_t) ((uintptr_t) (p))) #define UINT64_TO_PTR(u) ((void *) ((uintptr_t) (u))) #define PTR_TO_SIZE(p) ((size_t) ((uintptr_t) (p))) #define SIZE_TO_PTR(u) ((void *) ((uintptr_t) (u))) #define CHAR_TO_STR(x) ((char[2]) { x, 0 }) #define char_array_0(x) x[sizeof(x)-1] = 0; /* Returns the number of chars needed to format variables of the * specified type as a decimal string. Adds in extra space for a * negative '-' prefix (hence works correctly on signed * types). Includes space for the trailing NUL. */ #define DECIMAL_STR_MAX(type) \ (2+(sizeof(type) <= 1 ? 3 : \ sizeof(type) <= 2 ? 5 : \ sizeof(type) <= 4 ? 10 : \ sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)]))) #define DECIMAL_STR_WIDTH(x) \ ({ \ typeof(x) _x_ = (x); \ unsigned ans = 1; \ while (_x_ /= 10) \ ans++; \ ans; \ }) #define SET_FLAG(v, flag, b) \ (v) = (b) ? ((v) | (flag)) : ((v) & ~(flag)) #define CASE_F(X) case X: #define CASE_F_1(CASE, X) CASE_F(X) #define CASE_F_2(CASE, X, ...) CASE(X) CASE_F_1(CASE, __VA_ARGS__) #define CASE_F_3(CASE, X, ...) CASE(X) CASE_F_2(CASE, __VA_ARGS__) #define CASE_F_4(CASE, X, ...) CASE(X) CASE_F_3(CASE, __VA_ARGS__) #define CASE_F_5(CASE, X, ...) CASE(X) CASE_F_4(CASE, __VA_ARGS__) #define CASE_F_6(CASE, X, ...) CASE(X) CASE_F_5(CASE, __VA_ARGS__) #define CASE_F_7(CASE, X, ...) CASE(X) CASE_F_6(CASE, __VA_ARGS__) #define CASE_F_8(CASE, X, ...) CASE(X) CASE_F_7(CASE, __VA_ARGS__) #define CASE_F_9(CASE, X, ...) CASE(X) CASE_F_8(CASE, __VA_ARGS__) #define CASE_F_10(CASE, X, ...) CASE(X) CASE_F_9(CASE, __VA_ARGS__) #define CASE_F_11(CASE, X, ...) CASE(X) CASE_F_10(CASE, __VA_ARGS__) #define CASE_F_12(CASE, X, ...) CASE(X) CASE_F_11(CASE, __VA_ARGS__) #define CASE_F_13(CASE, X, ...) CASE(X) CASE_F_12(CASE, __VA_ARGS__) #define CASE_F_14(CASE, X, ...) CASE(X) CASE_F_13(CASE, __VA_ARGS__) #define CASE_F_15(CASE, X, ...) CASE(X) CASE_F_14(CASE, __VA_ARGS__) #define CASE_F_16(CASE, X, ...) CASE(X) CASE_F_15(CASE, __VA_ARGS__) #define CASE_F_17(CASE, X, ...) CASE(X) CASE_F_16(CASE, __VA_ARGS__) #define CASE_F_18(CASE, X, ...) CASE(X) CASE_F_17(CASE, __VA_ARGS__) #define CASE_F_19(CASE, X, ...) CASE(X) CASE_F_18(CASE, __VA_ARGS__) #define CASE_F_20(CASE, X, ...) CASE(X) CASE_F_19(CASE, __VA_ARGS__) #define GET_CASE_F(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME #define FOR_EACH_MAKE_CASE(...) \ GET_CASE_F(__VA_ARGS__,CASE_F_20,CASE_F_19,CASE_F_18,CASE_F_17,CASE_F_16,CASE_F_15,CASE_F_14,CASE_F_13,CASE_F_12,CASE_F_11, \ CASE_F_10,CASE_F_9,CASE_F_8,CASE_F_7,CASE_F_6,CASE_F_5,CASE_F_4,CASE_F_3,CASE_F_2,CASE_F_1) \ (CASE_F,__VA_ARGS__) #define IN_SET(x, ...) \ ({ \ bool _found = false; \ /* If the build breaks in the line below, you need to extend the case macros */ \ static _unused_ char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){__VA_ARGS__})/sizeof(int)]; \ switch(x) { \ FOR_EACH_MAKE_CASE(__VA_ARGS__) \ _found = true; \ break; \ default: \ break; \ } \ _found; \ }) /* Define C11 thread_local attribute even on older gcc compiler * version */ #ifndef thread_local /* * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__ * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769 */ #if __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16)) #define thread_local _Thread_local #else #define thread_local __thread #endif #endif /* Define C11 noreturn without and even on older gcc * compiler versions */ #ifndef noreturn #if __STDC_VERSION__ >= 201112L #define noreturn _Noreturn #else #define noreturn __attribute__((noreturn)) #endif #endif #define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \ static inline void func##p(type *p) { \ if (*p) \ func(*p); \ } \ struct __useless_struct_to_allow_trailing_semicolon__ #include "log.h" systemd-229/src/basic/memfd-util.c000066400000000000000000000077161265713322000171530ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #ifdef HAVE_LINUX_MEMFD_H #include #endif #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "macro.h" #include "memfd-util.h" #include "missing.h" #include "string-util.h" #include "utf8.h" int memfd_new(const char *name) { _cleanup_free_ char *g = NULL; int fd; if (!name) { char pr[17] = {}; /* If no name is specified we generate one. We include * a hint indicating our library implementation, and * add the thread name to it */ assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0); if (isempty(pr)) name = "sd"; else { _cleanup_free_ char *e = NULL; e = utf8_escape_invalid(pr); if (!e) return -ENOMEM; g = strappend("sd-", e); if (!g) return -ENOMEM; name = g; } } fd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC); if (fd < 0) return -errno; return fd; } int memfd_map(int fd, uint64_t offset, size_t size, void **p) { void *q; int sealed; assert(fd >= 0); assert(size > 0); assert(p); sealed = memfd_get_sealed(fd); if (sealed < 0) return sealed; if (sealed) q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset); else q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset); if (q == MAP_FAILED) return -errno; *p = q; return 0; } int memfd_set_sealed(int fd) { int r; assert(fd >= 0); r = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL); if (r < 0) return -errno; return 0; } int memfd_get_sealed(int fd) { int r; assert(fd >= 0); r = fcntl(fd, F_GET_SEALS); if (r < 0) return -errno; return r == (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL); } int memfd_get_size(int fd, uint64_t *sz) { struct stat stat; int r; assert(fd >= 0); assert(sz); r = fstat(fd, &stat); if (r < 0) return -errno; *sz = stat.st_size; return 0; } int memfd_set_size(int fd, uint64_t sz) { int r; assert(fd >= 0); r = ftruncate(fd, sz); if (r < 0) return -errno; return 0; } int memfd_new_and_map(const char *name, size_t sz, void **p) { _cleanup_close_ int fd = -1; int r; assert(sz > 0); assert(p); fd = memfd_new(name); if (fd < 0) return fd; r = memfd_set_size(fd, sz); if (r < 0) return r; r = memfd_map(fd, 0, sz, p); if (r < 0) return r; r = fd; fd = -1; return r; } systemd-229/src/basic/memfd-util.h000066400000000000000000000021431265713322000171450ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include int memfd_new(const char *name); int memfd_new_and_map(const char *name, size_t sz, void **p); int memfd_map(int fd, uint64_t offset, size_t size, void **p); int memfd_set_sealed(int fd); int memfd_get_sealed(int fd); int memfd_get_size(int fd, uint64_t *sz); int memfd_set_size(int fd, uint64_t sz); systemd-229/src/basic/mempool.c000066400000000000000000000053761265713322000165600ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010-2014 Lennart Poettering Copyright 2014 Michal Schmidt systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "macro.h" #include "mempool.h" #include "util.h" struct pool { struct pool *next; unsigned n_tiles; unsigned n_used; }; void* mempool_alloc_tile(struct mempool *mp) { unsigned i; /* When a tile is released we add it to the list and simply * place the next pointer at its offset 0. */ assert(mp->tile_size >= sizeof(void*)); assert(mp->at_least > 0); if (mp->freelist) { void *r; r = mp->freelist; mp->freelist = * (void**) mp->freelist; return r; } if (_unlikely_(!mp->first_pool) || _unlikely_(mp->first_pool->n_used >= mp->first_pool->n_tiles)) { unsigned n; size_t size; struct pool *p; n = mp->first_pool ? mp->first_pool->n_tiles : 0; n = MAX(mp->at_least, n * 2); size = PAGE_ALIGN(ALIGN(sizeof(struct pool)) + n*mp->tile_size); n = (size - ALIGN(sizeof(struct pool))) / mp->tile_size; p = malloc(size); if (!p) return NULL; p->next = mp->first_pool; p->n_tiles = n; p->n_used = 0; mp->first_pool = p; } i = mp->first_pool->n_used++; return ((uint8_t*) mp->first_pool) + ALIGN(sizeof(struct pool)) + i*mp->tile_size; } void* mempool_alloc0_tile(struct mempool *mp) { void *p; p = mempool_alloc_tile(mp); if (p) memzero(p, mp->tile_size); return p; } void mempool_free_tile(struct mempool *mp, void *p) { * (void**) p = mp->freelist; mp->freelist = p; } #ifdef VALGRIND void mempool_drop(struct mempool *mp) { struct pool *p = mp->first_pool; while (p) { struct pool *n; n = p->next; free(p); p = n; } } #endif systemd-229/src/basic/mempool.h000066400000000000000000000024531265713322000165560ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011-2014 Lennart Poettering Copyright 2014 Michal Schmidt systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include struct pool; struct mempool { struct pool *first_pool; void *freelist; size_t tile_size; unsigned at_least; }; void* mempool_alloc_tile(struct mempool *mp); void* mempool_alloc0_tile(struct mempool *mp); void mempool_free_tile(struct mempool *mp, void *p); #define DEFINE_MEMPOOL(pool_name, tile_type, alloc_at_least) \ struct mempool pool_name = { \ .tile_size = sizeof(tile_type), \ .at_least = alloc_at_least, \ } #ifdef VALGRIND void mempool_drop(struct mempool *mp); #endif systemd-229/src/basic/missing.h000066400000000000000000000653351265713322000165670ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* Missing glibc definitions to access certain kernel APIs */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_AUDIT #include #endif #ifdef ARCH_MIPS #include #endif #ifdef HAVE_LINUX_BTRFS_H #include #endif #include "macro.h" #ifndef RLIMIT_RTTIME #define RLIMIT_RTTIME 15 #endif /* If RLIMIT_RTTIME is not defined, then we cannot use RLIMIT_NLIMITS as is */ #define _RLIMIT_MAX (RLIMIT_RTTIME+1 > RLIMIT_NLIMITS ? RLIMIT_RTTIME+1 : RLIMIT_NLIMITS) #ifndef F_LINUX_SPECIFIC_BASE #define F_LINUX_SPECIFIC_BASE 1024 #endif #ifndef F_SETPIPE_SZ #define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7) #endif #ifndef F_GETPIPE_SZ #define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8) #endif #ifndef F_ADD_SEALS #define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) #define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) #define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */ #define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */ #define F_SEAL_GROW 0x0004 /* prevent file from growing */ #define F_SEAL_WRITE 0x0008 /* prevent writes */ #endif #ifndef F_OFD_GETLK #define F_OFD_GETLK 36 #define F_OFD_SETLK 37 #define F_OFD_SETLKW 38 #endif #ifndef MFD_ALLOW_SEALING #define MFD_ALLOW_SEALING 0x0002U #endif #ifndef MFD_CLOEXEC #define MFD_CLOEXEC 0x0001U #endif #ifndef IP_FREEBIND #define IP_FREEBIND 15 #endif #ifndef OOM_SCORE_ADJ_MIN #define OOM_SCORE_ADJ_MIN (-1000) #endif #ifndef OOM_SCORE_ADJ_MAX #define OOM_SCORE_ADJ_MAX 1000 #endif #ifndef AUDIT_SERVICE_START #define AUDIT_SERVICE_START 1130 /* Service (daemon) start */ #endif #ifndef AUDIT_SERVICE_STOP #define AUDIT_SERVICE_STOP 1131 /* Service (daemon) stop */ #endif #ifndef TIOCVHANGUP #define TIOCVHANGUP 0x5437 #endif #ifndef IP_TRANSPARENT #define IP_TRANSPARENT 19 #endif #ifndef SOL_NETLINK #define SOL_NETLINK 270 #endif #ifndef NETLINK_LIST_MEMBERSHIPS #define NETLINK_LIST_MEMBERSHIPS 9 #endif #ifndef SOL_SCTP #define SOL_SCTP 132 #endif #if !HAVE_DECL_PIVOT_ROOT static inline int pivot_root(const char *new_root, const char *put_old) { return syscall(SYS_pivot_root, new_root, put_old); } #endif #ifndef __NR_memfd_create # if defined __x86_64__ # define __NR_memfd_create 319 # elif defined __arm__ # define __NR_memfd_create 385 # elif defined __aarch64__ # define __NR_memfd_create 279 # elif defined __s390__ # define __NR_memfd_create 350 # elif defined _MIPS_SIM # if _MIPS_SIM == _MIPS_SIM_ABI32 # define __NR_memfd_create 4354 # endif # if _MIPS_SIM == _MIPS_SIM_NABI32 # define __NR_memfd_create 6318 # endif # if _MIPS_SIM == _MIPS_SIM_ABI64 # define __NR_memfd_create 5314 # endif # elif defined __i386__ # define __NR_memfd_create 356 # else # warning "__NR_memfd_create unknown for your architecture" # define __NR_memfd_create 0xffffffff # endif #endif #ifndef HAVE_MEMFD_CREATE static inline int memfd_create(const char *name, unsigned int flags) { return syscall(__NR_memfd_create, name, flags); } #endif #ifndef __NR_getrandom # if defined __x86_64__ # define __NR_getrandom 318 # elif defined(__i386__) # define __NR_getrandom 355 # elif defined(__arm__) # define __NR_getrandom 384 # elif defined(__aarch64__) # define __NR_getrandom 278 # elif defined(__ia64__) # define __NR_getrandom 1339 # elif defined(__m68k__) # define __NR_getrandom 352 # elif defined(__s390x__) # define __NR_getrandom 349 # elif defined(__powerpc__) # define __NR_getrandom 359 # elif defined _MIPS_SIM # if _MIPS_SIM == _MIPS_SIM_ABI32 # define __NR_getrandom 4353 # endif # if _MIPS_SIM == _MIPS_SIM_NABI32 # define __NR_getrandom 6317 # endif # if _MIPS_SIM == _MIPS_SIM_ABI64 # define __NR_getrandom 5313 # endif # else # warning "__NR_getrandom unknown for your architecture" # define __NR_getrandom 0xffffffff # endif #endif #if !HAVE_DECL_GETRANDOM static inline int getrandom(void *buffer, size_t count, unsigned flags) { return syscall(__NR_getrandom, buffer, count, flags); } #endif #ifndef GRND_NONBLOCK #define GRND_NONBLOCK 0x0001 #endif #ifndef GRND_RANDOM #define GRND_RANDOM 0x0002 #endif #ifndef BTRFS_IOCTL_MAGIC #define BTRFS_IOCTL_MAGIC 0x94 #endif #ifndef BTRFS_PATH_NAME_MAX #define BTRFS_PATH_NAME_MAX 4087 #endif #ifndef BTRFS_DEVICE_PATH_NAME_MAX #define BTRFS_DEVICE_PATH_NAME_MAX 1024 #endif #ifndef BTRFS_FSID_SIZE #define BTRFS_FSID_SIZE 16 #endif #ifndef BTRFS_UUID_SIZE #define BTRFS_UUID_SIZE 16 #endif #ifndef BTRFS_SUBVOL_RDONLY #define BTRFS_SUBVOL_RDONLY (1ULL << 1) #endif #ifndef BTRFS_SUBVOL_NAME_MAX #define BTRFS_SUBVOL_NAME_MAX 4039 #endif #ifndef BTRFS_INO_LOOKUP_PATH_MAX #define BTRFS_INO_LOOKUP_PATH_MAX 4080 #endif #ifndef BTRFS_SEARCH_ARGS_BUFSIZE #define BTRFS_SEARCH_ARGS_BUFSIZE (4096 - sizeof(struct btrfs_ioctl_search_key)) #endif #ifndef BTRFS_QGROUP_LEVEL_SHIFT #define BTRFS_QGROUP_LEVEL_SHIFT 48 #endif #ifndef HAVE_LINUX_BTRFS_H struct btrfs_ioctl_vol_args { int64_t fd; char name[BTRFS_PATH_NAME_MAX + 1]; }; struct btrfs_qgroup_limit { __u64 flags; __u64 max_rfer; __u64 max_excl; __u64 rsv_rfer; __u64 rsv_excl; }; struct btrfs_qgroup_inherit { __u64 flags; __u64 num_qgroups; __u64 num_ref_copies; __u64 num_excl_copies; struct btrfs_qgroup_limit lim; __u64 qgroups[0]; }; struct btrfs_ioctl_qgroup_limit_args { __u64 qgroupid; struct btrfs_qgroup_limit lim; }; struct btrfs_ioctl_vol_args_v2 { __s64 fd; __u64 transid; __u64 flags; union { struct { __u64 size; struct btrfs_qgroup_inherit *qgroup_inherit; }; __u64 unused[4]; }; char name[BTRFS_SUBVOL_NAME_MAX + 1]; }; struct btrfs_ioctl_dev_info_args { uint64_t devid; /* in/out */ uint8_t uuid[BTRFS_UUID_SIZE]; /* in/out */ uint64_t bytes_used; /* out */ uint64_t total_bytes; /* out */ uint64_t unused[379]; /* pad to 4k */ char path[BTRFS_DEVICE_PATH_NAME_MAX]; /* out */ }; struct btrfs_ioctl_fs_info_args { uint64_t max_id; /* out */ uint64_t num_devices; /* out */ uint8_t fsid[BTRFS_FSID_SIZE]; /* out */ uint64_t reserved[124]; /* pad to 1k */ }; struct btrfs_ioctl_ino_lookup_args { __u64 treeid; __u64 objectid; char name[BTRFS_INO_LOOKUP_PATH_MAX]; }; struct btrfs_ioctl_search_key { /* which root are we searching. 0 is the tree of tree roots */ __u64 tree_id; /* keys returned will be >= min and <= max */ __u64 min_objectid; __u64 max_objectid; /* keys returned will be >= min and <= max */ __u64 min_offset; __u64 max_offset; /* max and min transids to search for */ __u64 min_transid; __u64 max_transid; /* keys returned will be >= min and <= max */ __u32 min_type; __u32 max_type; /* * how many items did userland ask for, and how many are we * returning */ __u32 nr_items; /* align to 64 bits */ __u32 unused; /* some extra for later */ __u64 unused1; __u64 unused2; __u64 unused3; __u64 unused4; }; struct btrfs_ioctl_search_header { __u64 transid; __u64 objectid; __u64 offset; __u32 type; __u32 len; }; struct btrfs_ioctl_search_args { struct btrfs_ioctl_search_key key; char buf[BTRFS_SEARCH_ARGS_BUFSIZE]; }; struct btrfs_ioctl_clone_range_args { __s64 src_fd; __u64 src_offset, src_length; __u64 dest_offset; }; #define BTRFS_QUOTA_CTL_ENABLE 1 #define BTRFS_QUOTA_CTL_DISABLE 2 #define BTRFS_QUOTA_CTL_RESCAN__NOTUSED 3 struct btrfs_ioctl_quota_ctl_args { __u64 cmd; __u64 status; }; #endif #ifndef BTRFS_IOC_DEFRAG #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ struct btrfs_ioctl_vol_args) #endif #ifndef BTRFS_IOC_RESIZE #define BTRFS_IOC_RESIZE _IOW(BTRFS_IOCTL_MAGIC, 3, \ struct btrfs_ioctl_vol_args) #endif #ifndef BTRFS_IOC_CLONE #define BTRFS_IOC_CLONE _IOW(BTRFS_IOCTL_MAGIC, 9, int) #endif #ifndef BTRFS_IOC_CLONE_RANGE #define BTRFS_IOC_CLONE_RANGE _IOW(BTRFS_IOCTL_MAGIC, 13, \ struct btrfs_ioctl_clone_range_args) #endif #ifndef BTRFS_IOC_SUBVOL_CREATE #define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \ struct btrfs_ioctl_vol_args) #endif #ifndef BTRFS_IOC_SNAP_DESTROY #define BTRFS_IOC_SNAP_DESTROY _IOW(BTRFS_IOCTL_MAGIC, 15, \ struct btrfs_ioctl_vol_args) #endif #ifndef BTRFS_IOC_TREE_SEARCH #define BTRFS_IOC_TREE_SEARCH _IOWR(BTRFS_IOCTL_MAGIC, 17, \ struct btrfs_ioctl_search_args) #endif #ifndef BTRFS_IOC_INO_LOOKUP #define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \ struct btrfs_ioctl_ino_lookup_args) #endif #ifndef BTRFS_IOC_SNAP_CREATE_V2 #define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \ struct btrfs_ioctl_vol_args_v2) #endif #ifndef BTRFS_IOC_SUBVOL_GETFLAGS #define BTRFS_IOC_SUBVOL_GETFLAGS _IOR(BTRFS_IOCTL_MAGIC, 25, __u64) #endif #ifndef BTRFS_IOC_SUBVOL_SETFLAGS #define BTRFS_IOC_SUBVOL_SETFLAGS _IOW(BTRFS_IOCTL_MAGIC, 26, __u64) #endif #ifndef BTRFS_IOC_DEV_INFO #define BTRFS_IOC_DEV_INFO _IOWR(BTRFS_IOCTL_MAGIC, 30, \ struct btrfs_ioctl_dev_info_args) #endif #ifndef BTRFS_IOC_FS_INFO #define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \ struct btrfs_ioctl_fs_info_args) #endif #ifndef BTRFS_IOC_DEVICES_READY #define BTRFS_IOC_DEVICES_READY _IOR(BTRFS_IOCTL_MAGIC, 39, \ struct btrfs_ioctl_vol_args) #endif #ifndef BTRFS_IOC_QUOTA_CTL #define BTRFS_IOC_QUOTA_CTL _IOWR(BTRFS_IOCTL_MAGIC, 40, \ struct btrfs_ioctl_quota_ctl_args) #endif #ifndef BTRFS_IOC_QGROUP_LIMIT #define BTRFS_IOC_QGROUP_LIMIT _IOR(BTRFS_IOCTL_MAGIC, 43, \ struct btrfs_ioctl_qgroup_limit_args) #endif #ifndef BTRFS_FIRST_FREE_OBJECTID #define BTRFS_FIRST_FREE_OBJECTID 256 #endif #ifndef BTRFS_LAST_FREE_OBJECTID #define BTRFS_LAST_FREE_OBJECTID -256ULL #endif #ifndef BTRFS_ROOT_TREE_OBJECTID #define BTRFS_ROOT_TREE_OBJECTID 1 #endif #ifndef BTRFS_QUOTA_TREE_OBJECTID #define BTRFS_QUOTA_TREE_OBJECTID 8ULL #endif #ifndef BTRFS_ROOT_ITEM_KEY #define BTRFS_ROOT_ITEM_KEY 132 #endif #ifndef BTRFS_QGROUP_STATUS_KEY #define BTRFS_QGROUP_STATUS_KEY 240 #endif #ifndef BTRFS_QGROUP_INFO_KEY #define BTRFS_QGROUP_INFO_KEY 242 #endif #ifndef BTRFS_QGROUP_LIMIT_KEY #define BTRFS_QGROUP_LIMIT_KEY 244 #endif #ifndef BTRFS_QGROUP_RELATION_KEY #define BTRFS_QGROUP_RELATION_KEY 246 #endif #ifndef BTRFS_ROOT_BACKREF_KEY #define BTRFS_ROOT_BACKREF_KEY 144 #endif #ifndef BTRFS_SUPER_MAGIC #define BTRFS_SUPER_MAGIC 0x9123683E #endif #ifndef CGROUP_SUPER_MAGIC #define CGROUP_SUPER_MAGIC 0x27e0eb #endif #ifndef TMPFS_MAGIC #define TMPFS_MAGIC 0x01021994 #endif #ifndef MS_MOVE #define MS_MOVE 8192 #endif #ifndef MS_PRIVATE #define MS_PRIVATE (1 << 18) #endif #if !HAVE_DECL_GETTID static inline pid_t gettid(void) { return (pid_t) syscall(SYS_gettid); } #endif #ifndef SCM_SECURITY #define SCM_SECURITY 0x03 #endif #ifndef MS_STRICTATIME #define MS_STRICTATIME (1<<24) #endif #ifndef MS_REC #define MS_REC 16384 #endif #ifndef MS_SHARED #define MS_SHARED (1<<20) #endif #ifndef PR_SET_NO_NEW_PRIVS #define PR_SET_NO_NEW_PRIVS 38 #endif #ifndef PR_SET_CHILD_SUBREAPER #define PR_SET_CHILD_SUBREAPER 36 #endif #ifndef MAX_HANDLE_SZ #define MAX_HANDLE_SZ 128 #endif #ifndef __NR_name_to_handle_at # if defined(__x86_64__) # define __NR_name_to_handle_at 303 # elif defined(__i386__) # define __NR_name_to_handle_at 341 # elif defined(__arm__) # define __NR_name_to_handle_at 370 # elif defined(__powerpc__) # define __NR_name_to_handle_at 345 # else # error "__NR_name_to_handle_at is not defined" # endif #endif #if !HAVE_DECL_NAME_TO_HANDLE_AT struct file_handle { unsigned int handle_bytes; int handle_type; unsigned char f_handle[0]; }; static inline int name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) { return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags); } #endif #ifndef HAVE_SECURE_GETENV # ifdef HAVE___SECURE_GETENV # define secure_getenv __secure_getenv # else # error "neither secure_getenv nor __secure_getenv are available" # endif #endif #ifndef CIFS_MAGIC_NUMBER # define CIFS_MAGIC_NUMBER 0xFF534D42 #endif #ifndef TFD_TIMER_CANCEL_ON_SET # define TFD_TIMER_CANCEL_ON_SET (1 << 1) #endif #ifndef SO_REUSEPORT # define SO_REUSEPORT 15 #endif #ifndef EVIOCREVOKE # define EVIOCREVOKE _IOW('E', 0x91, int) #endif #ifndef DRM_IOCTL_SET_MASTER # define DRM_IOCTL_SET_MASTER _IO('d', 0x1e) #endif #ifndef DRM_IOCTL_DROP_MASTER # define DRM_IOCTL_DROP_MASTER _IO('d', 0x1f) #endif #if defined(__i386__) || defined(__x86_64__) /* The precise definition of __O_TMPFILE is arch specific, so let's * just define this on x86 where we know the value. */ #ifndef __O_TMPFILE #define __O_TMPFILE 020000000 #endif /* a horrid kludge trying to make sure that this will fail on old kernels */ #ifndef O_TMPFILE #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) #endif #endif #ifndef __NR_setns # if defined(__x86_64__) # define __NR_setns 308 # elif defined(__i386__) # define __NR_setns 346 # else # error "__NR_setns is not defined" # endif #endif #if !HAVE_DECL_SETNS static inline int setns(int fd, int nstype) { return syscall(__NR_setns, fd, nstype); } #endif #if !HAVE_DECL_LO_FLAGS_PARTSCAN #define LO_FLAGS_PARTSCAN 8 #endif #ifndef LOOP_CTL_REMOVE #define LOOP_CTL_REMOVE 0x4C81 #endif #ifndef LOOP_CTL_GET_FREE #define LOOP_CTL_GET_FREE 0x4C82 #endif #if !HAVE_DECL_IFLA_INET6_ADDR_GEN_MODE #define IFLA_INET6_UNSPEC 0 #define IFLA_INET6_FLAGS 1 #define IFLA_INET6_CONF 2 #define IFLA_INET6_STATS 3 #define IFLA_INET6_MCAST 4 #define IFLA_INET6_CACHEINFO 5 #define IFLA_INET6_ICMP6STATS 6 #define IFLA_INET6_TOKEN 7 #define IFLA_INET6_ADDR_GEN_MODE 8 #define __IFLA_INET6_MAX 9 #define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) #define IN6_ADDR_GEN_MODE_EUI64 0 #define IN6_ADDR_GEN_MODE_NONE 1 #endif #if !HAVE_DECL_IFLA_MACVLAN_FLAGS #define IFLA_MACVLAN_UNSPEC 0 #define IFLA_MACVLAN_MODE 1 #define IFLA_MACVLAN_FLAGS 2 #define __IFLA_MACVLAN_MAX 3 #define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1) #endif #if !HAVE_DECL_IFLA_IPVLAN_MODE #define IFLA_IPVLAN_UNSPEC 0 #define IFLA_IPVLAN_MODE 1 #define __IFLA_IPVLAN_MAX 2 #define IFLA_IPVLAN_MAX (__IFLA_IPVLAN_MAX - 1) #define IPVLAN_MODE_L2 0 #define IPVLAN_MODE_L3 1 #define IPVLAN_MAX 2 #endif #if !HAVE_DECL_IFLA_VTI_REMOTE #define IFLA_VTI_UNSPEC 0 #define IFLA_VTI_LINK 1 #define IFLA_VTI_IKEY 2 #define IFLA_VTI_OKEY 3 #define IFLA_VTI_LOCAL 4 #define IFLA_VTI_REMOTE 5 #define __IFLA_VTI_MAX 6 #define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1) #endif #if !HAVE_DECL_IFLA_PHYS_PORT_ID #undef IFLA_PROMISCUITY #define IFLA_PROMISCUITY 30 #define IFLA_NUM_TX_QUEUES 31 #define IFLA_NUM_RX_QUEUES 32 #define IFLA_CARRIER 33 #define IFLA_PHYS_PORT_ID 34 #define __IFLA_MAX 35 #define IFLA_MAX (__IFLA_MAX - 1) #endif #if !HAVE_DECL_IFLA_BOND_AD_INFO #define IFLA_BOND_UNSPEC 0 #define IFLA_BOND_MODE 1 #define IFLA_BOND_ACTIVE_SLAVE 2 #define IFLA_BOND_MIIMON 3 #define IFLA_BOND_UPDELAY 4 #define IFLA_BOND_DOWNDELAY 5 #define IFLA_BOND_USE_CARRIER 6 #define IFLA_BOND_ARP_INTERVAL 7 #define IFLA_BOND_ARP_IP_TARGET 8 #define IFLA_BOND_ARP_VALIDATE 9 #define IFLA_BOND_ARP_ALL_TARGETS 10 #define IFLA_BOND_PRIMARY 11 #define IFLA_BOND_PRIMARY_RESELECT 12 #define IFLA_BOND_FAIL_OVER_MAC 13 #define IFLA_BOND_XMIT_HASH_POLICY 14 #define IFLA_BOND_RESEND_IGMP 15 #define IFLA_BOND_NUM_PEER_NOTIF 16 #define IFLA_BOND_ALL_SLAVES_ACTIVE 17 #define IFLA_BOND_MIN_LINKS 18 #define IFLA_BOND_LP_INTERVAL 19 #define IFLA_BOND_PACKETS_PER_SLAVE 20 #define IFLA_BOND_AD_LACP_RATE 21 #define IFLA_BOND_AD_SELECT 22 #define IFLA_BOND_AD_INFO 23 #define __IFLA_BOND_MAX 24 #define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1) #endif #if !HAVE_DECL_IFLA_VLAN_PROTOCOL #define IFLA_VLAN_UNSPEC 0 #define IFLA_VLAN_ID 1 #define IFLA_VLAN_FLAGS 2 #define IFLA_VLAN_EGRESS_QOS 3 #define IFLA_VLAN_INGRESS_QOS 4 #define IFLA_VLAN_PROTOCOL 5 #define __IFLA_VLAN_MAX 6 #define IFLA_VLAN_MAX (__IFLA_VLAN_MAX - 1) #endif #if !HAVE_DECL_IFLA_VXLAN_REMCSUM_NOPARTIAL #define IFLA_VXLAN_UNSPEC 0 #define IFLA_VXLAN_ID 1 #define IFLA_VXLAN_GROUP 2 #define IFLA_VXLAN_LINK 3 #define IFLA_VXLAN_LOCAL 4 #define IFLA_VXLAN_TTL 5 #define IFLA_VXLAN_TOS 6 #define IFLA_VXLAN_LEARNING 7 #define IFLA_VXLAN_AGEING 8 #define IFLA_VXLAN_LIMIT 9 #define IFLA_VXLAN_PORT_RANGE 10 #define IFLA_VXLAN_PROXY 11 #define IFLA_VXLAN_RSC 12 #define IFLA_VXLAN_L2MISS 13 #define IFLA_VXLAN_L3MISS 14 #define IFLA_VXLAN_PORT 15 #define IFLA_VXLAN_GROUP6 16 #define IFLA_VXLAN_LOCAL6 17 #define IFLA_VXLAN_UDP_CSUM 18 #define IFLA_VXLAN_UDP_ZERO_CSUM6_TX 19 #define IFLA_VXLAN_UDP_ZERO_CSUM6_RX 20 #define IFLA_VXLAN_REMCSUM_TX 21 #define IFLA_VXLAN_REMCSUM_RX 22 #define IFLA_VXLAN_GBP 23 #define IFLA_VXLAN_REMCSUM_NOPARTIAL 24 #define __IFLA_VXLAN_MAX 25 #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) #endif #if !HAVE_DECL_IFLA_IPTUN_ENCAP_DPORT #define IFLA_IPTUN_UNSPEC 0 #define IFLA_IPTUN_LINK 1 #define IFLA_IPTUN_LOCAL 2 #define IFLA_IPTUN_REMOTE 3 #define IFLA_IPTUN_TTL 4 #define IFLA_IPTUN_TOS 5 #define IFLA_IPTUN_ENCAP_LIMIT 6 #define IFLA_IPTUN_FLOWINFO 7 #define IFLA_IPTUN_FLAGS 8 #define IFLA_IPTUN_PROTO 9 #define IFLA_IPTUN_PMTUDISC 10 #define IFLA_IPTUN_6RD_PREFIX 11 #define IFLA_IPTUN_6RD_RELAY_PREFIX 12 #define IFLA_IPTUN_6RD_PREFIXLEN 13 #define IFLA_IPTUN_6RD_RELAY_PREFIXLEN 14 #define IFLA_IPTUN_ENCAP_TYPE 15 #define IFLA_IPTUN_ENCAP_FLAGS 16 #define IFLA_IPTUN_ENCAP_SPORT 17 #define IFLA_IPTUN_ENCAP_DPORT 18 #define __IFLA_IPTUN_MAX 19 #define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) #endif #if !HAVE_DECL_IFLA_GRE_ENCAP_DPORT #define IFLA_GRE_UNSPEC 0 #define IFLA_GRE_LINK 1 #define IFLA_GRE_IFLAGS 2 #define IFLA_GRE_OFLAGS 3 #define IFLA_GRE_IKEY 4 #define IFLA_GRE_OKEY 5 #define IFLA_GRE_LOCAL 6 #define IFLA_GRE_REMOTE 7 #define IFLA_GRE_TTL 8 #define IFLA_GRE_TOS 9 #define IFLA_GRE_PMTUDISC 10 #define IFLA_GRE_ENCAP_LIMIT 11 #define IFLA_GRE_FLOWINFO 12 #define IFLA_GRE_FLAGS 13 #define IFLA_GRE_ENCAP_TYPE 14 #define IFLA_GRE_ENCAP_FLAGS 15 #define IFLA_GRE_ENCAP_SPORT 16 #define IFLA_GRE_ENCAP_DPORT 17 #define __IFLA_GRE_MAX 18 #define IFLA_GRE_MAX (__IFLA_GRE_MAX - 1) #endif #if !HAVE_DECL_IFLA_BRIDGE_VLAN_INFO #define IFLA_BRIDGE_FLAGS 0 #define IFLA_BRIDGE_MODE 1 #define IFLA_BRIDGE_VLAN_INFO 2 #define __IFLA_BRIDGE_MAX 3 #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) #endif #if !HAVE_DECL_IFLA_BR_PRIORITY #define IFLA_BR_UNSPEC 0 #define IFLA_BR_FORWARD_DELAY 1 #define IFLA_BR_HELLO_TIME 2 #define IFLA_BR_MAX_AGE 3 #define IFLA_BR_AGEING_TIME 4 #define IFLA_BR_STP_STATE 5 #define IFLA_BR_PRIORITY 6 #define __IFLA_BR_MAX 7 #define IFLA_BR_MAX (__IFLA_BR_MAX - 1) #endif #if !HAVE_DECL_IFLA_BRPORT_LEARNING_SYNC #define IFLA_BRPORT_UNSPEC 0 #define IFLA_BRPORT_STATE 1 #define IFLA_BRPORT_PRIORITY 2 #define IFLA_BRPORT_COST 3 #define IFLA_BRPORT_MODE 4 #define IFLA_BRPORT_GUARD 5 #define IFLA_BRPORT_PROTECT 6 #define IFLA_BRPORT_FAST_LEAVE 7 #define IFLA_BRPORT_LEARNING 8 #define IFLA_BRPORT_UNICAST_FLOOD 9 #define IFLA_BRPORT_PROXYARP 10 #define IFLA_BRPORT_LEARNING_SYNC 11 #define __IFLA_BRPORT_MAX 12 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) #endif #if !HAVE_DECL_NDA_IFINDEX #define NDA_UNSPEC 0 #define NDA_DST 1 #define NDA_LLADDR 2 #define NDA_CACHEINFO 3 #define NDA_PROBES 4 #define NDA_VLAN 5 #define NDA_PORT 6 #define NDA_VNI 7 #define NDA_IFINDEX 8 #define __NDA_MAX 9 #define NDA_MAX (__NDA_MAX - 1) #endif #ifndef RTA_PREF #define RTA_PREF 20 #endif #ifndef IPV6_UNICAST_IF #define IPV6_UNICAST_IF 76 #endif #ifndef IFF_MULTI_QUEUE #define IFF_MULTI_QUEUE 0x100 #endif #ifndef IFF_LOWER_UP #define IFF_LOWER_UP 0x10000 #endif #ifndef IFF_DORMANT #define IFF_DORMANT 0x20000 #endif #ifndef BOND_XMIT_POLICY_ENCAP23 #define BOND_XMIT_POLICY_ENCAP23 3 #endif #ifndef BOND_XMIT_POLICY_ENCAP34 #define BOND_XMIT_POLICY_ENCAP34 4 #endif #ifndef NET_ADDR_RANDOM # define NET_ADDR_RANDOM 1 #endif #ifndef NET_NAME_UNKNOWN # define NET_NAME_UNKNOWN 0 #endif #ifndef NET_NAME_ENUM # define NET_NAME_ENUM 1 #endif #ifndef NET_NAME_PREDICTABLE # define NET_NAME_PREDICTABLE 2 #endif #ifndef NET_NAME_USER # define NET_NAME_USER 3 #endif #ifndef NET_NAME_RENAMED # define NET_NAME_RENAMED 4 #endif #ifndef BPF_XOR # define BPF_XOR 0xa0 #endif /* Note that LOOPBACK_IFINDEX is currently not exported by the * kernel/glibc, but hardcoded internally by the kernel. However, as * it is exported to userspace indirectly via rtnetlink and the * ioctls, and made use of widely we define it here too, in a way that * is compatible with the kernel's internal definition. */ #ifndef LOOPBACK_IFINDEX #define LOOPBACK_IFINDEX 1 #endif #if !HAVE_DECL_IFA_FLAGS #define IFA_FLAGS 8 #endif #ifndef IFA_F_MANAGETEMPADDR #define IFA_F_MANAGETEMPADDR 0x100 #endif #ifndef IFA_F_NOPREFIXROUTE #define IFA_F_NOPREFIXROUTE 0x200 #endif #ifndef MAX_AUDIT_MESSAGE_LENGTH #define MAX_AUDIT_MESSAGE_LENGTH 8970 #endif #ifndef AUDIT_NLGRP_MAX #define AUDIT_NLGRP_READLOG 1 #endif #ifndef CAP_MAC_OVERRIDE #define CAP_MAC_OVERRIDE 32 #endif #ifndef CAP_MAC_ADMIN #define CAP_MAC_ADMIN 33 #endif #ifndef CAP_SYSLOG #define CAP_SYSLOG 34 #endif #ifndef CAP_WAKE_ALARM #define CAP_WAKE_ALARM 35 #endif #ifndef CAP_BLOCK_SUSPEND #define CAP_BLOCK_SUSPEND 36 #endif #ifndef CAP_AUDIT_READ #define CAP_AUDIT_READ 37 #endif static inline int raw_clone(unsigned long flags, void *child_stack) { #if defined(__s390__) || defined(__CRIS__) /* On s390 and cris the order of the first and second arguments * of the raw clone() system call is reversed. */ return (int) syscall(__NR_clone, child_stack, flags); #else return (int) syscall(__NR_clone, flags, child_stack); #endif } static inline pid_t raw_getpid(void) { #if defined(__alpha__) return (pid_t) syscall(__NR_getxpid); #else return (pid_t) syscall(__NR_getpid); #endif } #if !HAVE_DECL_RENAMEAT2 #ifndef __NR_renameat2 # if defined __x86_64__ # define __NR_renameat2 316 # elif defined __arm__ # define __NR_renameat2 382 # elif defined _MIPS_SIM # if _MIPS_SIM == _MIPS_SIM_ABI32 # define __NR_renameat2 4351 # endif # if _MIPS_SIM == _MIPS_SIM_NABI32 # define __NR_renameat2 6315 # endif # if _MIPS_SIM == _MIPS_SIM_ABI64 # define __NR_renameat2 5311 # endif # elif defined __i386__ # define __NR_renameat2 353 # else # warning "__NR_renameat2 unknown for your architecture" # define __NR_renameat2 0xffffffff # endif #endif static inline int renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) { return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags); } #endif #ifndef RENAME_NOREPLACE #define RENAME_NOREPLACE (1 << 0) #endif #if !HAVE_DECL_KCMP static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) { #if defined(__NR_kcmp) return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); #else errno = ENOSYS; return -1; #endif } #endif #ifndef KCMP_FILE #define KCMP_FILE 0 #endif #ifndef INPUT_PROP_POINTING_STICK #define INPUT_PROP_POINTING_STICK 0x05 #endif #ifndef INPUT_PROP_ACCELEROMETER #define INPUT_PROP_ACCELEROMETER 0x06 #endif #if !HAVE_DECL_KEY_SERIAL_T typedef int32_t key_serial_t; #endif #if !HAVE_DECL_KEYCTL static inline long keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) { #if defined(__NR_keyctl) return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5); #else errno = ENOSYS; return -1; #endif } static inline key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) { #if defined (__NR_add_key) return syscall(__NR_add_key, type, description, payload, plen, ringid); #else errno = ENOSYS; return -1; #endif } static inline key_serial_t request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) { #if defined (__NR_request_key) return syscall(__NR_request_key, type, description, callout_info, destringid); #else errno = ENOSYS; return -1; #endif } #endif #ifndef KEYCTL_READ #define KEYCTL_READ 11 #endif #ifndef KEYCTL_SET_TIMEOUT #define KEYCTL_SET_TIMEOUT 15 #endif #ifndef KEY_SPEC_USER_KEYRING #define KEY_SPEC_USER_KEYRING -4 #endif #ifndef PR_CAP_AMBIENT #define PR_CAP_AMBIENT 47 #endif #ifndef PR_CAP_AMBIENT_IS_SET #define PR_CAP_AMBIENT_IS_SET 1 #endif #ifndef PR_CAP_AMBIENT_RAISE #define PR_CAP_AMBIENT_RAISE 2 #endif #ifndef PR_CAP_AMBIENT_CLEAR_ALL #define PR_CAP_AMBIENT_CLEAR_ALL 4 #endif /* The following two defines are actually available in the kernel headers for longer, but we define them here anyway, * since that makes it easier to use them in conjunction with the glibc net/if.h header which conflicts with * linux/if.h. */ #ifndef IF_OPER_UNKNOWN #define IF_OPER_UNKNOWN 0 #endif #ifndef IF_OPER_UP #define IF_OPER_UP 6 #ifndef HAVE_DECL_CHAR32_T #define char32_t uint32_t #endif #ifndef HAVE_DECL_CHAR16_T #define char16_t uint16_t #endif #endif systemd-229/src/basic/mkdir-label.c000066400000000000000000000023371265713322000172650ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "label.h" #include "mkdir.h" int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid) { return mkdir_safe_internal(path, mode, uid, gid, mkdir_label); } int mkdir_parents_label(const char *path, mode_t mode) { return mkdir_parents_internal(NULL, path, mode, mkdir_label); } int mkdir_p_label(const char *path, mode_t mode) { return mkdir_p_internal(NULL, path, mode, mkdir_label); } systemd-229/src/basic/mkdir.c000066400000000000000000000071731265713322000162130ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "fs-util.h" #include "macro.h" #include "mkdir.h" #include "path-util.h" #include "stat-util.h" #include "user-util.h" int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir) { struct stat st; if (_mkdir(path, mode) >= 0) if (chmod_and_chown(path, mode, uid, gid) < 0) return -errno; if (lstat(path, &st) < 0) return -errno; if ((st.st_mode & 0007) > (mode & 0007) || (st.st_mode & 0070) > (mode & 0070) || (st.st_mode & 0700) > (mode & 0700) || (uid != UID_INVALID && st.st_uid != uid) || (gid != GID_INVALID && st.st_gid != gid) || !S_ISDIR(st.st_mode)) return -EEXIST; return 0; } int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid) { return mkdir_safe_internal(path, mode, uid, gid, mkdir); } int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) { const char *p, *e; int r; assert(path); if (prefix && !path_startswith(path, prefix)) return -ENOTDIR; /* return immediately if directory exists */ e = strrchr(path, '/'); if (!e) return -EINVAL; if (e == path) return 0; p = strndupa(path, e - path); r = is_dir(p, true); if (r > 0) return 0; if (r == 0) return -ENOTDIR; /* create every parent directory in the path, except the last component */ p = path + strspn(path, "/"); for (;;) { char t[strlen(path) + 1]; e = p + strcspn(p, "/"); p = e + strspn(e, "/"); /* Is this the last component? If so, then we're * done */ if (*p == 0) return 0; memcpy(t, path, e - path); t[e-path] = 0; if (prefix && path_startswith(prefix, t)) continue; r = _mkdir(t, mode); if (r < 0 && errno != EEXIST) return -errno; } } int mkdir_parents(const char *path, mode_t mode) { return mkdir_parents_internal(NULL, path, mode, mkdir); } int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) { int r; /* Like mkdir -p */ r = mkdir_parents_internal(prefix, path, mode, _mkdir); if (r < 0) return r; r = _mkdir(path, mode); if (r < 0 && (errno != EEXIST || is_dir(path, true) <= 0)) return -errno; return 0; } int mkdir_p(const char *path, mode_t mode) { return mkdir_p_internal(NULL, path, mode, mkdir); } systemd-229/src/basic/mkdir.h000066400000000000000000000030241265713322000162070ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid); int mkdir_parents(const char *path, mode_t mode); int mkdir_p(const char *path, mode_t mode); /* mandatory access control(MAC) versions */ int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid); int mkdir_parents_label(const char *path, mode_t mode); int mkdir_p_label(const char *path, mode_t mode); /* internally used */ typedef int (*mkdir_func_t)(const char *pathname, mode_t mode); int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir); int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir); int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir); systemd-229/src/basic/mount-util.c000066400000000000000000000455671265713322000172330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "alloc-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "hashmap.h" #include "mount-util.h" #include "parse-util.h" #include "path-util.h" #include "set.h" #include "stdio-util.h" #include "string-util.h" static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) { char path[strlen("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)]; _cleanup_free_ char *fdinfo = NULL; _cleanup_close_ int subfd = -1; char *p; int r; if ((flags & AT_EMPTY_PATH) && isempty(filename)) xsprintf(path, "/proc/self/fdinfo/%i", fd); else { subfd = openat(fd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH); if (subfd < 0) return -errno; xsprintf(path, "/proc/self/fdinfo/%i", subfd); } r = read_full_file(path, &fdinfo, NULL); if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */ return -EOPNOTSUPP; if (r < 0) return -errno; p = startswith(fdinfo, "mnt_id:"); if (!p) { p = strstr(fdinfo, "\nmnt_id:"); if (!p) /* The mnt_id field is a relatively new addition */ return -EOPNOTSUPP; p += 8; } p += strspn(p, WHITESPACE); p[strcspn(p, WHITESPACE)] = 0; return safe_atoi(p, mnt_id); } int fd_is_mount_point(int fd, const char *filename, int flags) { union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT; int mount_id = -1, mount_id_parent = -1; bool nosupp = false, check_st_dev = true; struct stat a, b; int r; assert(fd >= 0); assert(filename); /* First we will try the name_to_handle_at() syscall, which * tells us the mount id and an opaque file "handle". It is * not supported everywhere though (kernel compile-time * option, not all file systems are hooked up). If it works * the mount id is usually good enough to tell us whether * something is a mount point. * * If that didn't work we will try to read the mount id from * /proc/self/fdinfo/. This is almost as good as * name_to_handle_at(), however, does not return the * opaque file handle. The opaque file handle is pretty useful * to detect the root directory, which we should always * consider a mount point. Hence we use this only as * fallback. Exporting the mnt_id in fdinfo is a pretty recent * kernel addition. * * As last fallback we do traditional fstat() based st_dev * comparisons. This is how things were traditionally done, * but unionfs breaks breaks this since it exposes file * systems with a variety of st_dev reported. Also, btrfs * subvolumes have different st_dev, even though they aren't * real mounts of their own. */ r = name_to_handle_at(fd, filename, &h.handle, &mount_id, flags); if (r < 0) { if (errno == ENOSYS) /* This kernel does not support name_to_handle_at() * fall back to simpler logic. */ goto fallback_fdinfo; else if (errno == EOPNOTSUPP) /* This kernel or file system does not support * name_to_handle_at(), hence let's see if the * upper fs supports it (in which case it is a * mount point), otherwise fallback to the * traditional stat() logic */ nosupp = true; else return -errno; } r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH); if (r < 0) { if (errno == EOPNOTSUPP) { if (nosupp) /* Neither parent nor child do name_to_handle_at()? We have no choice but to fall back. */ goto fallback_fdinfo; else /* The parent can't do name_to_handle_at() but the * directory we are interested in can? * If so, it must be a mount point. */ return 1; } else return -errno; } /* The parent can do name_to_handle_at() but the * directory we are interested in can't? If so, it * must be a mount point. */ if (nosupp) return 1; /* If the file handle for the directory we are * interested in and its parent are identical, we * assume this is the root directory, which is a mount * point. */ if (h.handle.handle_bytes == h_parent.handle.handle_bytes && h.handle.handle_type == h_parent.handle.handle_type && memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0) return 1; return mount_id != mount_id_parent; fallback_fdinfo: r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id); if (r == -EOPNOTSUPP) goto fallback_fstat; if (r < 0) return r; r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent); if (r < 0) return r; if (mount_id != mount_id_parent) return 1; /* Hmm, so, the mount ids are the same. This leaves one * special case though for the root file system. For that, * let's see if the parent directory has the same inode as we * are interested in. Hence, let's also do fstat() checks now, * too, but avoid the st_dev comparisons, since they aren't * that useful on unionfs mounts. */ check_st_dev = false; fallback_fstat: /* yay for fstatat() taking a different set of flags than the other * _at() above */ if (flags & AT_SYMLINK_FOLLOW) flags &= ~AT_SYMLINK_FOLLOW; else flags |= AT_SYMLINK_NOFOLLOW; if (fstatat(fd, filename, &a, flags) < 0) return -errno; if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0) return -errno; /* A directory with same device and inode as its parent? Must * be the root directory */ if (a.st_dev == b.st_dev && a.st_ino == b.st_ino) return 1; return check_st_dev && (a.st_dev != b.st_dev); } /* flags can be AT_SYMLINK_FOLLOW or 0 */ int path_is_mount_point(const char *t, int flags) { _cleanup_close_ int fd = -1; _cleanup_free_ char *canonical = NULL, *parent = NULL; assert(t); if (path_equal(t, "/")) return 1; /* we need to resolve symlinks manually, we can't just rely on * fd_is_mount_point() to do that for us; if we have a structure like * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we * look at needs to be /usr, not /. */ if (flags & AT_SYMLINK_FOLLOW) { canonical = canonicalize_file_name(t); if (!canonical) return -errno; t = canonical; } parent = dirname_malloc(t); if (!parent) return -ENOMEM; fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH); if (fd < 0) return -errno; return fd_is_mount_point(fd, basename(t), flags); } int umount_recursive(const char *prefix, int flags) { bool again; int n = 0, r; /* Try to umount everything recursively below a * directory. Also, take care of stacked mounts, and keep * unmounting them until they are gone. */ do { _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; again = false; r = 0; proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); if (!proc_self_mountinfo) return -errno; for (;;) { _cleanup_free_ char *path = NULL, *p = NULL; int k; k = fscanf(proc_self_mountinfo, "%*s " /* (1) mount id */ "%*s " /* (2) parent id */ "%*s " /* (3) major:minor */ "%*s " /* (4) root */ "%ms " /* (5) mount point */ "%*s" /* (6) mount options */ "%*[^-]" /* (7) optional fields */ "- " /* (8) separator */ "%*s " /* (9) file system type */ "%*s" /* (10) mount source */ "%*s" /* (11) mount options 2 */ "%*[^\n]", /* some rubbish at the end */ &path); if (k != 1) { if (k == EOF) break; continue; } r = cunescape(path, UNESCAPE_RELAX, &p); if (r < 0) return r; if (!path_startswith(p, prefix)) continue; if (umount2(p, flags) < 0) { r = -errno; continue; } again = true; n++; break; } } while (again); return r ? r : n; } static int get_mount_flags(const char *path, unsigned long *flags) { struct statvfs buf; if (statvfs(path, &buf) < 0) return -errno; *flags = buf.f_flag; return 0; } int bind_remount_recursive(const char *prefix, bool ro) { _cleanup_set_free_free_ Set *done = NULL; _cleanup_free_ char *cleaned = NULL; int r; /* Recursively remount a directory (and all its submounts) * read-only or read-write. If the directory is already * mounted, we reuse the mount and simply mark it * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write * operation). If it isn't we first make it one. Afterwards we * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all * submounts we can access, too. When mounts are stacked on * the same mount point we only care for each individual * "top-level" mount on each point, as we cannot * influence/access the underlying mounts anyway. We do not * have any effect on future submounts that might get * propagated, they migt be writable. This includes future * submounts that have been triggered via autofs. */ cleaned = strdup(prefix); if (!cleaned) return -ENOMEM; path_kill_slashes(cleaned); done = set_new(&string_hash_ops); if (!done) return -ENOMEM; for (;;) { _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; _cleanup_set_free_free_ Set *todo = NULL; bool top_autofs = false; char *x; unsigned long orig_flags; todo = set_new(&string_hash_ops); if (!todo) return -ENOMEM; proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); if (!proc_self_mountinfo) return -errno; for (;;) { _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL; int k; k = fscanf(proc_self_mountinfo, "%*s " /* (1) mount id */ "%*s " /* (2) parent id */ "%*s " /* (3) major:minor */ "%*s " /* (4) root */ "%ms " /* (5) mount point */ "%*s" /* (6) mount options (superblock) */ "%*[^-]" /* (7) optional fields */ "- " /* (8) separator */ "%ms " /* (9) file system type */ "%*s" /* (10) mount source */ "%*s" /* (11) mount options (bind mount) */ "%*[^\n]", /* some rubbish at the end */ &path, &type); if (k != 2) { if (k == EOF) break; continue; } r = cunescape(path, UNESCAPE_RELAX, &p); if (r < 0) return r; /* Let's ignore autofs mounts. If they aren't * triggered yet, we want to avoid triggering * them, as we don't make any guarantees for * future submounts anyway. If they are * already triggered, then we will find * another entry for this. */ if (streq(type, "autofs")) { top_autofs = top_autofs || path_equal(cleaned, p); continue; } if (path_startswith(p, cleaned) && !set_contains(done, p)) { r = set_consume(todo, p); p = NULL; if (r == -EEXIST) continue; if (r < 0) return r; } } /* If we have no submounts to process anymore and if * the root is either already done, or an autofs, we * are done */ if (set_isempty(todo) && (top_autofs || set_contains(done, cleaned))) return 0; if (!set_contains(done, cleaned) && !set_contains(todo, cleaned)) { /* The prefix directory itself is not yet a * mount, make it one. */ if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0) return -errno; orig_flags = 0; (void) get_mount_flags(cleaned, &orig_flags); orig_flags &= ~MS_RDONLY; if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) return -errno; x = strdup(cleaned); if (!x) return -ENOMEM; r = set_consume(done, x); if (r < 0) return r; } while ((x = set_steal_first(todo))) { r = set_consume(done, x); if (r == -EEXIST || r == 0) continue; if (r < 0) return r; /* Try to reuse the original flag set, but * don't care for errors, in case of * obstructed mounts */ orig_flags = 0; (void) get_mount_flags(x, &orig_flags); orig_flags &= ~MS_RDONLY; if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) { /* Deal with mount points that are * obstructed by a later mount */ if (errno != ENOENT) return -errno; } } } } int mount_move_root(const char *path) { assert(path); if (chdir(path) < 0) return -errno; if (mount(path, "/", NULL, MS_MOVE, NULL) < 0) return -errno; if (chroot(".") < 0) return -errno; if (chdir("/") < 0) return -errno; return 0; } bool fstype_is_network(const char *fstype) { static const char table[] = "afs\0" "cifs\0" "smbfs\0" "sshfs\0" "ncpfs\0" "ncp\0" "nfs\0" "nfs4\0" "gfs\0" "gfs2\0" "glusterfs\0"; const char *x; x = startswith(fstype, "fuse."); if (x) fstype = x; return nulstr_contains(table, fstype); } int repeat_unmount(const char *path, int flags) { bool done = false; assert(path); /* If there are multiple mounts on a mount point, this * removes them all */ for (;;) { if (umount2(path, flags) < 0) { if (errno == EINVAL) return done; return -errno; } done = true; } } systemd-229/src/basic/mount-util.h000066400000000000000000000030271265713322000172210ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "macro.h" #include "missing.h" int fd_is_mount_point(int fd, const char *filename, int flags); int path_is_mount_point(const char *path, int flags); int repeat_unmount(const char *path, int flags); int umount_recursive(const char *target, int flags); int bind_remount_recursive(const char *prefix, bool ro); int mount_move_root(const char *path); DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent); #define _cleanup_endmntent_ _cleanup_(endmntentp) bool fstype_is_network(const char *fstype); union file_handle_union { struct file_handle handle; char padding[sizeof(struct file_handle) + MAX_HANDLE_SZ]; }; #define FILE_HANDLE_INIT { .handle.handle_bytes = MAX_HANDLE_SZ } systemd-229/src/basic/nss-util.h000066400000000000000000000174411265713322000166670ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #define NSS_SIGNALS_BLOCK SIGALRM,SIGVTALRM,SIGPIPE,SIGCHLD,SIGTSTP,SIGIO,SIGHUP,SIGUSR1,SIGUSR2,SIGPROF,SIGURG,SIGWINCH #define NSS_GETHOSTBYNAME_PROTOTYPES(module) \ enum nss_status _nss_##module##_gethostbyname4_r( \ const char *name, \ struct gaih_addrtuple **pat, \ char *buffer, size_t buflen, \ int *errnop, int *h_errnop, \ int32_t *ttlp) _public_; \ enum nss_status _nss_##module##_gethostbyname3_r( \ const char *name, \ int af, \ struct hostent *host, \ char *buffer, size_t buflen, \ int *errnop, int *h_errnop, \ int32_t *ttlp, \ char **canonp) _public_; \ enum nss_status _nss_##module##_gethostbyname2_r( \ const char *name, \ int af, \ struct hostent *host, \ char *buffer, size_t buflen, \ int *errnop, int *h_errnop) _public_; \ enum nss_status _nss_##module##_gethostbyname_r( \ const char *name, \ struct hostent *host, \ char *buffer, size_t buflen, \ int *errnop, int *h_errnop) _public_ #define NSS_GETHOSTBYADDR_PROTOTYPES(module) \ enum nss_status _nss_##module##_gethostbyaddr2_r( \ const void* addr, socklen_t len, \ int af, \ struct hostent *host, \ char *buffer, size_t buflen, \ int *errnop, int *h_errnop, \ int32_t *ttlp) _public_; \ enum nss_status _nss_##module##_gethostbyaddr_r( \ const void* addr, socklen_t len, \ int af, \ struct hostent *host, \ char *buffer, size_t buflen, \ int *errnop, int *h_errnop) _public_ #define NSS_GETHOSTBYNAME_FALLBACKS(module) \ enum nss_status _nss_##module##_gethostbyname2_r( \ const char *name, \ int af, \ struct hostent *host, \ char *buffer, size_t buflen, \ int *errnop, int *h_errnop) { \ return _nss_##module##_gethostbyname3_r( \ name, \ af, \ host, \ buffer, buflen, \ errnop, h_errnop, \ NULL, \ NULL); \ } \ enum nss_status _nss_##module##_gethostbyname_r( \ const char *name, \ struct hostent *host, \ char *buffer, size_t buflen, \ int *errnop, int *h_errnop) { \ enum nss_status ret = NSS_STATUS_NOTFOUND; \ \ if (_res.options & RES_USE_INET6) \ ret = _nss_##module##_gethostbyname3_r( \ name, \ AF_INET6, \ host, \ buffer, buflen, \ errnop, h_errnop, \ NULL, \ NULL); \ if (ret == NSS_STATUS_NOTFOUND) \ ret = _nss_##module##_gethostbyname3_r( \ name, \ AF_INET, \ host, \ buffer, buflen, \ errnop, h_errnop, \ NULL, \ NULL); \ return ret; \ } \ struct __useless_struct_to_allow_trailing_semicolon__ #define NSS_GETHOSTBYADDR_FALLBACKS(module) \ enum nss_status _nss_##module##_gethostbyaddr_r( \ const void* addr, socklen_t len, \ int af, \ struct hostent *host, \ char *buffer, size_t buflen, \ int *errnop, int *h_errnop) { \ return _nss_##module##_gethostbyaddr2_r( \ addr, len, \ af, \ host, \ buffer, buflen, \ errnop, h_errnop, \ NULL); \ } \ struct __useless_struct_to_allow_trailing_semicolon__ #define NSS_GETPW_PROTOTYPES(module) \ enum nss_status _nss_##module##_getpwnam_r( \ const char *name, \ struct passwd *pwd, \ char *buffer, size_t buflen, \ int *errnop) _public_; \ enum nss_status _nss_mymachines_getpwuid_r( \ uid_t uid, \ struct passwd *pwd, \ char *buffer, size_t buflen, \ int *errnop) _public_ #define NSS_GETGR_PROTOTYPES(module) \ enum nss_status _nss_##module##_getgrnam_r( \ const char *name, \ struct group *gr, \ char *buffer, size_t buflen, \ int *errnop) _public_; \ enum nss_status _nss_##module##_getgrgid_r( \ gid_t gid, \ struct group *gr, \ char *buffer, size_t buflen, \ int *errnop) _public_ systemd-229/src/basic/ordered-set.c000066400000000000000000000030041265713322000173070ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2016 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "ordered-set.h" #include "strv.h" int ordered_set_consume(OrderedSet *s, void *p) { int r; r = ordered_set_put(s, p); if (r <= 0) free(p); return r; } int ordered_set_put_strdup(OrderedSet *s, const char *p) { char *c; int r; assert(s); assert(p); c = strdup(p); if (!c) return -ENOMEM; r = ordered_set_consume(s, c); if (r == -EEXIST) return 0; return r; } int ordered_set_put_strdupv(OrderedSet *s, char **l) { int n = 0, r; char **i; STRV_FOREACH(i, l) { r = ordered_set_put_strdup(s, *i); if (r < 0) return r; n += r; } return n; } systemd-229/src/basic/ordered-set.h000066400000000000000000000046071265713322000173260ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "hashmap.h" typedef struct OrderedSet OrderedSet; static inline OrderedSet* ordered_set_new(const struct hash_ops *ops) { return (OrderedSet*) ordered_hashmap_new(ops); } static inline int ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops) { if (*s) return 0; *s = ordered_set_new(ops); if (!*s) return -ENOMEM; return 0; } static inline OrderedSet* ordered_set_free(OrderedSet *s) { ordered_hashmap_free((OrderedHashmap*) s); return NULL; } static inline OrderedSet* ordered_set_free_free(OrderedSet *s) { ordered_hashmap_free_free((OrderedHashmap*) s); return NULL; } static inline int ordered_set_put(OrderedSet *s, void *p) { return ordered_hashmap_put((OrderedHashmap*) s, p, p); } static inline bool ordered_set_isempty(OrderedSet *s) { return ordered_hashmap_isempty((OrderedHashmap*) s); } static inline bool ordered_set_iterate(OrderedSet *s, Iterator *i, void **value) { return ordered_hashmap_iterate((OrderedHashmap*) s, i, value, NULL); } int ordered_set_consume(OrderedSet *s, void *p); int ordered_set_put_strdup(OrderedSet *s, const char *p); int ordered_set_put_strdupv(OrderedSet *s, char **l); #define ORDERED_SET_FOREACH(e, s, i) \ for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); ) DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free); DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free); #define _cleanup_ordered_set_free_ _cleanup_(ordered_set_freep) #define _cleanup_ordered_set_free_free_ _cleanup_(ordered_set_free_freep) systemd-229/src/basic/parse-util.c000066400000000000000000000336661265713322000172000ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "alloc-util.h" #include "extract-word.h" #include "macro.h" #include "parse-util.h" #include "string-util.h" int parse_boolean(const char *v) { assert(v); if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on")) return 1; else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off")) return 0; return -EINVAL; } int parse_pid(const char *s, pid_t* ret_pid) { unsigned long ul = 0; pid_t pid; int r; assert(s); assert(ret_pid); r = safe_atolu(s, &ul); if (r < 0) return r; pid = (pid_t) ul; if ((unsigned long) pid != ul) return -ERANGE; if (pid <= 0) return -ERANGE; *ret_pid = pid; return 0; } int parse_mode(const char *s, mode_t *ret) { char *x; long l; assert(s); assert(ret); s += strspn(s, WHITESPACE); if (s[0] == '-') return -ERANGE; errno = 0; l = strtol(s, &x, 8); if (errno > 0) return -errno; if (!x || x == s || *x) return -EINVAL; if (l < 0 || l > 07777) return -ERANGE; *ret = (mode_t) l; return 0; } int parse_ifindex(const char *s, int *ret) { int ifi, r; r = safe_atoi(s, &ifi); if (r < 0) return r; if (ifi <= 0) return -EINVAL; *ret = ifi; return 0; } int parse_size(const char *t, uint64_t base, uint64_t *size) { /* Soo, sometimes we want to parse IEC binary suffixes, and * sometimes SI decimal suffixes. This function can parse * both. Which one is the right way depends on the * context. Wikipedia suggests that SI is customary for * hardware metrics and network speeds, while IEC is * customary for most data sizes used by software and volatile * (RAM) memory. Hence be careful which one you pick! * * In either case we use just K, M, G as suffix, and not Ki, * Mi, Gi or so (as IEC would suggest). That's because that's * frickin' ugly. But this means you really need to make sure * to document which base you are parsing when you use this * call. */ struct table { const char *suffix; unsigned long long factor; }; static const struct table iec[] = { { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL }, { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL }, { "T", 1024ULL*1024ULL*1024ULL*1024ULL }, { "G", 1024ULL*1024ULL*1024ULL }, { "M", 1024ULL*1024ULL }, { "K", 1024ULL }, { "B", 1ULL }, { "", 1ULL }, }; static const struct table si[] = { { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL }, { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL }, { "T", 1000ULL*1000ULL*1000ULL*1000ULL }, { "G", 1000ULL*1000ULL*1000ULL }, { "M", 1000ULL*1000ULL }, { "K", 1000ULL }, { "B", 1ULL }, { "", 1ULL }, }; const struct table *table; const char *p; unsigned long long r = 0; unsigned n_entries, start_pos = 0; assert(t); assert(base == 1000 || base == 1024); assert(size); if (base == 1000) { table = si; n_entries = ELEMENTSOF(si); } else { table = iec; n_entries = ELEMENTSOF(iec); } p = t; do { unsigned long long l, tmp; double frac = 0; char *e; unsigned i; p += strspn(p, WHITESPACE); errno = 0; l = strtoull(p, &e, 10); if (errno > 0) return -errno; if (e == p) return -EINVAL; if (*p == '-') return -ERANGE; if (*e == '.') { e++; /* strtoull() itself would accept space/+/- */ if (*e >= '0' && *e <= '9') { unsigned long long l2; char *e2; l2 = strtoull(e, &e2, 10); if (errno > 0) return -errno; /* Ignore failure. E.g. 10.M is valid */ frac = l2; for (; e < e2; e++) frac /= 10; } } e += strspn(e, WHITESPACE); for (i = start_pos; i < n_entries; i++) if (startswith(e, table[i].suffix)) break; if (i >= n_entries) return -EINVAL; if (l + (frac > 0) > ULLONG_MAX / table[i].factor) return -ERANGE; tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor); if (tmp > ULLONG_MAX - r) return -ERANGE; r += tmp; if ((unsigned long long) (uint64_t) r != r) return -ERANGE; p = e + strlen(table[i].suffix); start_pos = i + 1; } while (*p); *size = r; return 0; } int parse_range(const char *t, unsigned *lower, unsigned *upper) { _cleanup_free_ char *word = NULL; unsigned l, u; int r; assert(lower); assert(upper); /* Extract the lower bound. */ r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS); if (r < 0) return r; if (r == 0) return -EINVAL; r = safe_atou(word, &l); if (r < 0) return r; /* Check for the upper bound and extract it if needed */ if (!t) /* Single number with no dashes. */ u = l; else if (!*t) /* Trailing dash is an error. */ return -EINVAL; else { r = safe_atou(t, &u); if (r < 0) return r; } *lower = l; *upper = u; return 0; } char *format_bytes(char *buf, size_t l, uint64_t t) { unsigned i; /* This only does IEC units so far */ static const struct { const char *suffix; uint64_t factor; } table[] = { { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, { "M", UINT64_C(1024)*UINT64_C(1024) }, { "K", UINT64_C(1024) }, }; if (t == (uint64_t) -1) return NULL; for (i = 0; i < ELEMENTSOF(table); i++) { if (t >= table[i].factor) { snprintf(buf, l, "%" PRIu64 ".%" PRIu64 "%s", t / table[i].factor, ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10), table[i].suffix); goto finish; } } snprintf(buf, l, "%" PRIu64 "B", t); finish: buf[l-1] = 0; return buf; } int safe_atou(const char *s, unsigned *ret_u) { char *x = NULL; unsigned long l; assert(s); assert(ret_u); /* strtoul() is happy to parse negative values, and silently * converts them to unsigned values without generating an * error. We want a clean error, hence let's look for the "-" * prefix on our own, and generate an error. But let's do so * only after strtoul() validated that the string is clean * otherwise, so that we return EINVAL preferably over * ERANGE. */ s += strspn(s, WHITESPACE); errno = 0; l = strtoul(s, &x, 0); if (errno > 0) return -errno; if (!x || x == s || *x) return -EINVAL; if (s[0] == '-') return -ERANGE; if ((unsigned long) (unsigned) l != l) return -ERANGE; *ret_u = (unsigned) l; return 0; } int safe_atoi(const char *s, int *ret_i) { char *x = NULL; long l; assert(s); assert(ret_i); errno = 0; l = strtol(s, &x, 0); if (errno > 0) return -errno; if (!x || x == s || *x) return -EINVAL; if ((long) (int) l != l) return -ERANGE; *ret_i = (int) l; return 0; } int safe_atollu(const char *s, long long unsigned *ret_llu) { char *x = NULL; unsigned long long l; assert(s); assert(ret_llu); s += strspn(s, WHITESPACE); errno = 0; l = strtoull(s, &x, 0); if (errno > 0) return -errno; if (!x || x == s || *x) return -EINVAL; if (*s == '-') return -ERANGE; *ret_llu = l; return 0; } int safe_atolli(const char *s, long long int *ret_lli) { char *x = NULL; long long l; assert(s); assert(ret_lli); errno = 0; l = strtoll(s, &x, 0); if (errno > 0) return -errno; if (!x || x == s || *x) return -EINVAL; *ret_lli = l; return 0; } int safe_atou8(const char *s, uint8_t *ret) { char *x = NULL; unsigned long l; assert(s); assert(ret); s += strspn(s, WHITESPACE); errno = 0; l = strtoul(s, &x, 0); if (errno > 0) return -errno; if (!x || x == s || *x) return -EINVAL; if (s[0] == '-') return -ERANGE; if ((unsigned long) (uint8_t) l != l) return -ERANGE; *ret = (uint8_t) l; return 0; } int safe_atou16(const char *s, uint16_t *ret) { char *x = NULL; unsigned long l; assert(s); assert(ret); s += strspn(s, WHITESPACE); errno = 0; l = strtoul(s, &x, 0); if (errno > 0) return -errno; if (!x || x == s || *x) return -EINVAL; if (s[0] == '-') return -ERANGE; if ((unsigned long) (uint16_t) l != l) return -ERANGE; *ret = (uint16_t) l; return 0; } int safe_atoi16(const char *s, int16_t *ret) { char *x = NULL; long l; assert(s); assert(ret); errno = 0; l = strtol(s, &x, 0); if (errno > 0) return -errno; if (!x || x == s || *x) return -EINVAL; if ((long) (int16_t) l != l) return -ERANGE; *ret = (int16_t) l; return 0; } int safe_atod(const char *s, double *ret_d) { char *x = NULL; double d = 0; locale_t loc; assert(s); assert(ret_d); loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0); if (loc == (locale_t) 0) return -errno; errno = 0; d = strtod_l(s, &x, loc); if (errno > 0) { freelocale(loc); return -errno; } if (!x || x == s || *x) { freelocale(loc); return -EINVAL; } freelocale(loc); *ret_d = (double) d; return 0; } int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) { size_t i; unsigned val = 0; const char *s; s = *p; /* accept any number of digits, strtoull is limted to 19 */ for(i=0; i < digits; i++,s++) { if (*s < '0' || *s > '9') { if (i == 0) return -EINVAL; /* too few digits, pad with 0 */ for (; i < digits; i++) val *= 10; break; } val *= 10; val += *s - '0'; } /* maybe round up */ if (*s >= '5' && *s <= '9') val++; s += strspn(s, DIGITS); *p = s; *res = val; return 0; } systemd-229/src/basic/parse-util.h000066400000000000000000000062171265713322000171750ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "macro.h" #define MODE_INVALID ((mode_t) -1) int parse_boolean(const char *v) _pure_; int parse_pid(const char *s, pid_t* ret_pid); int parse_mode(const char *s, mode_t *ret); int parse_ifindex(const char *s, int *ret); int parse_size(const char *t, uint64_t base, uint64_t *size); int parse_range(const char *t, unsigned *lower, unsigned *upper); #define FORMAT_BYTES_MAX 8 char *format_bytes(char *buf, size_t l, uint64_t t); int safe_atou(const char *s, unsigned *ret_u); int safe_atoi(const char *s, int *ret_i); int safe_atollu(const char *s, unsigned long long *ret_u); int safe_atolli(const char *s, long long int *ret_i); int safe_atou8(const char *s, uint8_t *ret); int safe_atou16(const char *s, uint16_t *ret); int safe_atoi16(const char *s, int16_t *ret); static inline int safe_atou32(const char *s, uint32_t *ret_u) { assert_cc(sizeof(uint32_t) == sizeof(unsigned)); return safe_atou(s, (unsigned*) ret_u); } static inline int safe_atoi32(const char *s, int32_t *ret_i) { assert_cc(sizeof(int32_t) == sizeof(int)); return safe_atoi(s, (int*) ret_i); } static inline int safe_atou64(const char *s, uint64_t *ret_u) { assert_cc(sizeof(uint64_t) == sizeof(unsigned long long)); return safe_atollu(s, (unsigned long long*) ret_u); } static inline int safe_atoi64(const char *s, int64_t *ret_i) { assert_cc(sizeof(int64_t) == sizeof(long long int)); return safe_atolli(s, (long long int*) ret_i); } #if LONG_MAX == INT_MAX static inline int safe_atolu(const char *s, unsigned long *ret_u) { assert_cc(sizeof(unsigned long) == sizeof(unsigned)); return safe_atou(s, (unsigned*) ret_u); } static inline int safe_atoli(const char *s, long int *ret_u) { assert_cc(sizeof(long int) == sizeof(int)); return safe_atoi(s, (int*) ret_u); } #else static inline int safe_atolu(const char *s, unsigned long *ret_u) { assert_cc(sizeof(unsigned long) == sizeof(unsigned long long)); return safe_atollu(s, (unsigned long long*) ret_u); } static inline int safe_atoli(const char *s, long int *ret_u) { assert_cc(sizeof(long int) == sizeof(long long int)); return safe_atolli(s, (long long int*) ret_u); } #endif int safe_atod(const char *s, double *ret_d); int parse_fractional_part_u(const char **s, size_t digits, unsigned *res); systemd-229/src/basic/path-util.c000066400000000000000000000512421265713322000170100ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010-2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include /* When we include libgen.h because we need dirname() we immediately * undefine basename() since libgen.h defines it as a macro to the * POSIX version which is really broken. We prefer GNU basename(). */ #include #undef basename #include "alloc-util.h" #include "extract-word.h" #include "fs-util.h" #include "log.h" #include "macro.h" #include "missing.h" #include "path-util.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" bool path_is_absolute(const char *p) { return p[0] == '/'; } bool is_path(const char *p) { return !!strchr(p, '/'); } int path_split_and_make_absolute(const char *p, char ***ret) { char **l; int r; assert(p); assert(ret); l = strv_split(p, ":"); if (!l) return -ENOMEM; r = path_strv_make_absolute_cwd(l); if (r < 0) { strv_free(l); return r; } *ret = l; return r; } char *path_make_absolute(const char *p, const char *prefix) { assert(p); /* Makes every item in the list an absolute path by prepending * the prefix, if specified and necessary */ if (path_is_absolute(p) || !prefix) return strdup(p); return strjoin(prefix, "/", p, NULL); } int path_make_absolute_cwd(const char *p, char **ret) { char *c; assert(p); assert(ret); /* Similar to path_make_absolute(), but prefixes with the * current working directory. */ if (path_is_absolute(p)) c = strdup(p); else { _cleanup_free_ char *cwd = NULL; cwd = get_current_dir_name(); if (!cwd) return negative_errno(); c = strjoin(cwd, "/", p, NULL); } if (!c) return -ENOMEM; *ret = c; return 0; } int path_make_relative(const char *from_dir, const char *to_path, char **_r) { char *r, *p; unsigned n_parents; assert(from_dir); assert(to_path); assert(_r); /* Strips the common part, and adds ".." elements as necessary. */ if (!path_is_absolute(from_dir)) return -EINVAL; if (!path_is_absolute(to_path)) return -EINVAL; /* Skip the common part. */ for (;;) { size_t a; size_t b; from_dir += strspn(from_dir, "/"); to_path += strspn(to_path, "/"); if (!*from_dir) { if (!*to_path) /* from_dir equals to_path. */ r = strdup("."); else /* from_dir is a parent directory of to_path. */ r = strdup(to_path); if (!r) return -ENOMEM; path_kill_slashes(r); *_r = r; return 0; } if (!*to_path) break; a = strcspn(from_dir, "/"); b = strcspn(to_path, "/"); if (a != b) break; if (memcmp(from_dir, to_path, a) != 0) break; from_dir += a; to_path += b; } /* If we're here, then "from_dir" has one or more elements that need to * be replaced with "..". */ /* Count the number of necessary ".." elements. */ for (n_parents = 0;;) { from_dir += strspn(from_dir, "/"); if (!*from_dir) break; from_dir += strcspn(from_dir, "/"); n_parents++; } r = malloc(n_parents * 3 + strlen(to_path) + 1); if (!r) return -ENOMEM; for (p = r; n_parents > 0; n_parents--, p += 3) memcpy(p, "../", 3); strcpy(p, to_path); path_kill_slashes(r); *_r = r; return 0; } int path_strv_make_absolute_cwd(char **l) { char **s; int r; /* Goes through every item in the string list and makes it * absolute. This works in place and won't rollback any * changes on failure. */ STRV_FOREACH(s, l) { char *t; r = path_make_absolute_cwd(*s, &t); if (r < 0) return r; free(*s); *s = t; } return 0; } char **path_strv_resolve(char **l, const char *prefix) { char **s; unsigned k = 0; bool enomem = false; if (strv_isempty(l)) return l; /* Goes through every item in the string list and canonicalize * the path. This works in place and won't rollback any * changes on failure. */ STRV_FOREACH(s, l) { char *t, *u; _cleanup_free_ char *orig = NULL; if (!path_is_absolute(*s)) { free(*s); continue; } if (prefix) { orig = *s; t = strappend(prefix, orig); if (!t) { enomem = true; continue; } } else t = *s; errno = 0; u = canonicalize_file_name(t); if (!u) { if (errno == ENOENT) { if (prefix) { u = orig; orig = NULL; free(t); } else u = t; } else { free(t); if (errno == ENOMEM || errno == 0) enomem = true; continue; } } else if (prefix) { char *x; free(t); x = path_startswith(u, prefix); if (x) { /* restore the slash if it was lost */ if (!startswith(x, "/")) *(--x) = '/'; t = strdup(x); free(u); if (!t) { enomem = true; continue; } u = t; } else { /* canonicalized path goes outside of * prefix, keep the original path instead */ free(u); u = orig; orig = NULL; } } else free(t); l[k++] = u; } l[k] = NULL; if (enomem) return NULL; return l; } char **path_strv_resolve_uniq(char **l, const char *prefix) { if (strv_isempty(l)) return l; if (!path_strv_resolve(l, prefix)) return NULL; return strv_uniq(l); } char *path_kill_slashes(char *path) { char *f, *t; bool slash = false; /* Removes redundant inner and trailing slashes. Modifies the * passed string in-place. * * ///foo///bar/ becomes /foo/bar */ for (f = path, t = path; *f; f++) { if (*f == '/') { slash = true; continue; } if (slash) { slash = false; *(t++) = '/'; } *(t++) = *f; } /* Special rule, if we are talking of the root directory, a trailing slash is good */ if (t == path && slash) *(t++) = '/'; *t = 0; return path; } char* path_startswith(const char *path, const char *prefix) { assert(path); assert(prefix); if ((path[0] == '/') != (prefix[0] == '/')) return NULL; for (;;) { size_t a, b; path += strspn(path, "/"); prefix += strspn(prefix, "/"); if (*prefix == 0) return (char*) path; if (*path == 0) return NULL; a = strcspn(path, "/"); b = strcspn(prefix, "/"); if (a != b) return NULL; if (memcmp(path, prefix, a) != 0) return NULL; path += a; prefix += b; } } int path_compare(const char *a, const char *b) { int d; assert(a); assert(b); /* A relative path and an abolute path must not compare as equal. * Which one is sorted before the other does not really matter. * Here a relative path is ordered before an absolute path. */ d = (a[0] == '/') - (b[0] == '/'); if (d != 0) return d; for (;;) { size_t j, k; a += strspn(a, "/"); b += strspn(b, "/"); if (*a == 0 && *b == 0) return 0; /* Order prefixes first: "/foo" before "/foo/bar" */ if (*a == 0) return -1; if (*b == 0) return 1; j = strcspn(a, "/"); k = strcspn(b, "/"); /* Alphabetical sort: "/foo/aaa" before "/foo/b" */ d = memcmp(a, b, MIN(j, k)); if (d != 0) return (d > 0) - (d < 0); /* sign of d */ /* Sort "/foo/a" before "/foo/aaa" */ d = (j > k) - (j < k); /* sign of (j - k) */ if (d != 0) return d; a += j; b += k; } } bool path_equal(const char *a, const char *b) { return path_compare(a, b) == 0; } bool path_equal_or_files_same(const char *a, const char *b) { return path_equal(a, b) || files_same(a, b) > 0; } char* path_join(const char *root, const char *path, const char *rest) { assert(path); if (!isempty(root)) return strjoin(root, endswith(root, "/") ? "" : "/", path[0] == '/' ? path+1 : path, rest ? (endswith(path, "/") ? "" : "/") : NULL, rest && rest[0] == '/' ? rest+1 : rest, NULL); else return strjoin(path, rest ? (endswith(path, "/") ? "" : "/") : NULL, rest && rest[0] == '/' ? rest+1 : rest, NULL); } int find_binary(const char *name, char **ret) { int last_error, r; const char *p; assert(name); if (is_path(name)) { if (access(name, X_OK) < 0) return -errno; if (ret) { r = path_make_absolute_cwd(name, ret); if (r < 0) return r; } return 0; } /** * Plain getenv, not secure_getenv, because we want * to actually allow the user to pick the binary. */ p = getenv("PATH"); if (!p) p = DEFAULT_PATH; last_error = -ENOENT; for (;;) { _cleanup_free_ char *j = NULL, *element = NULL; r = extract_first_word(&p, &element, ":", EXTRACT_RELAX|EXTRACT_DONT_COALESCE_SEPARATORS); if (r < 0) return r; if (r == 0) break; if (!path_is_absolute(element)) continue; j = strjoin(element, "/", name, NULL); if (!j) return -ENOMEM; if (access(j, X_OK) >= 0) { /* Found it! */ if (ret) { *ret = path_kill_slashes(j); j = NULL; } return 0; } last_error = -errno; } return last_error; } bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool update) { bool changed = false; const char* const* i; assert(timestamp); if (paths == NULL) return false; STRV_FOREACH(i, paths) { struct stat stats; usec_t u; if (stat(*i, &stats) < 0) continue; u = timespec_load(&stats.st_mtim); /* first check */ if (*timestamp >= u) continue; log_debug("timestamp of '%s' changed", *i); /* update timestamp */ if (update) { *timestamp = u; changed = true; } else return true; } return changed; } static int binary_is_good(const char *binary) { _cleanup_free_ char *p = NULL, *d = NULL; int r; r = find_binary(binary, &p); if (r == -ENOENT) return 0; if (r < 0) return r; /* An fsck that is linked to /bin/true is a non-existent * fsck */ r = readlink_malloc(p, &d); if (r == -EINVAL) /* not a symlink */ return 1; if (r < 0) return r; return !path_equal(d, "true") && !path_equal(d, "/bin/true") && !path_equal(d, "/usr/bin/true") && !path_equal(d, "/dev/null"); } int fsck_exists(const char *fstype) { const char *checker; assert(fstype); if (streq(fstype, "auto")) return -EINVAL; checker = strjoina("fsck.", fstype); return binary_is_good(checker); } int mkfs_exists(const char *fstype) { const char *mkfs; assert(fstype); if (streq(fstype, "auto")) return -EINVAL; mkfs = strjoina("mkfs.", fstype); return binary_is_good(mkfs); } char *prefix_root(const char *root, const char *path) { char *n, *p; size_t l; /* If root is passed, prefixes path with it. Otherwise returns * it as is. */ assert(path); /* First, drop duplicate prefixing slashes from the path */ while (path[0] == '/' && path[1] == '/') path++; if (isempty(root) || path_equal(root, "/")) return strdup(path); l = strlen(root) + 1 + strlen(path) + 1; n = new(char, l); if (!n) return NULL; p = stpcpy(n, root); while (p > n && p[-1] == '/') p--; if (path[0] != '/') *(p++) = '/'; strcpy(p, path); return n; } int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg) { char *p; int r; /* * This function is intended to be used in command line * parsers, to handle paths that are passed in. It makes the * path absolute, and reduces it to NULL if omitted or * root (the latter optionally). * * NOTE THAT THIS WILL FREE THE PREVIOUS ARGUMENT POINTER ON * SUCCESS! Hence, do not pass in uninitialized pointers. */ if (isempty(path)) { *arg = mfree(*arg); return 0; } r = path_make_absolute_cwd(path, &p); if (r < 0) return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path); path_kill_slashes(p); if (suppress_root && path_equal(p, "/")) p = mfree(p); free(*arg); *arg = p; return 0; } char* dirname_malloc(const char *path) { char *d, *dir, *dir2; assert(path); d = strdup(path); if (!d) return NULL; dir = dirname(d); assert(dir); if (dir == d) return d; dir2 = strdup(dir); free(d); return dir2; } bool filename_is_valid(const char *p) { const char *e; if (isempty(p)) return false; if (streq(p, ".")) return false; if (streq(p, "..")) return false; e = strchrnul(p, '/'); if (*e != 0) return false; if (e - p > FILENAME_MAX) return false; return true; } bool path_is_safe(const char *p) { if (isempty(p)) return false; if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../")) return false; if (strlen(p)+1 > PATH_MAX) return false; /* The following two checks are not really dangerous, but hey, they still are confusing */ if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./")) return false; if (strstr(p, "//")) return false; return true; } char *file_in_same_dir(const char *path, const char *filename) { char *e, *ret; size_t k; assert(path); assert(filename); /* This removes the last component of path and appends * filename, unless the latter is absolute anyway or the * former isn't */ if (path_is_absolute(filename)) return strdup(filename); e = strrchr(path, '/'); if (!e) return strdup(filename); k = strlen(filename); ret = new(char, (e + 1 - path) + k + 1); if (!ret) return NULL; memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1); return ret; } bool hidden_file_allow_backup(const char *filename) { assert(filename); return filename[0] == '.' || streq(filename, "lost+found") || streq(filename, "aquota.user") || streq(filename, "aquota.group") || endswith(filename, ".rpmnew") || endswith(filename, ".rpmsave") || endswith(filename, ".rpmorig") || endswith(filename, ".dpkg-old") || endswith(filename, ".dpkg-new") || endswith(filename, ".dpkg-tmp") || endswith(filename, ".dpkg-dist") || endswith(filename, ".dpkg-bak") || endswith(filename, ".dpkg-backup") || endswith(filename, ".dpkg-remove") || endswith(filename, ".swp"); } bool hidden_file(const char *filename) { assert(filename); if (endswith(filename, "~")) return true; return hidden_file_allow_backup(filename); } bool is_device_path(const char *path) { /* Returns true on paths that refer to a device, either in * sysfs or in /dev */ return path_startswith(path, "/dev/") || path_startswith(path, "/sys/"); } systemd-229/src/basic/path-util.h000066400000000000000000000117511265713322000170160ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010-2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "macro.h" #include "time-util.h" #define DEFAULT_PATH_NORMAL "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin" #define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":/sbin:/bin" #ifdef HAVE_SPLIT_USR # define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR #else # define DEFAULT_PATH DEFAULT_PATH_NORMAL #endif bool is_path(const char *p) _pure_; int path_split_and_make_absolute(const char *p, char ***ret); bool path_is_absolute(const char *p) _pure_; char* path_make_absolute(const char *p, const char *prefix); int path_make_absolute_cwd(const char *p, char **ret); int path_make_relative(const char *from_dir, const char *to_path, char **_r); char* path_kill_slashes(char *path); char* path_startswith(const char *path, const char *prefix) _pure_; int path_compare(const char *a, const char *b) _pure_; bool path_equal(const char *a, const char *b) _pure_; bool path_equal_or_files_same(const char *a, const char *b); char* path_join(const char *root, const char *path, const char *rest); int path_strv_make_absolute_cwd(char **l); char** path_strv_resolve(char **l, const char *prefix); char** path_strv_resolve_uniq(char **l, const char *prefix); int find_binary(const char *name, char **filename); bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update); int fsck_exists(const char *fstype); int mkfs_exists(const char *fstype); /* Iterates through the path prefixes of the specified path, going up * the tree, to root. Also returns "" (and not "/"!) for the root * directory. Excludes the specified directory itself */ #define PATH_FOREACH_PREFIX(prefix, path) \ for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); streq(prefix, "/") ? NULL : strrchr(prefix, '/'); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/')) /* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */ #define PATH_FOREACH_PREFIX_MORE(prefix, path) \ for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/')) char *prefix_root(const char *root, const char *path); /* Similar to prefix_root(), but returns an alloca() buffer, or * possibly a const pointer into the path parameter */ #define prefix_roota(root, path) \ ({ \ const char* _path = (path), *_root = (root), *_ret; \ char *_p, *_n; \ size_t _l; \ while (_path[0] == '/' && _path[1] == '/') \ _path ++; \ if (isempty(_root) || path_equal(_root, "/")) \ _ret = _path; \ else { \ _l = strlen(_root) + 1 + strlen(_path) + 1; \ _n = alloca(_l); \ _p = stpcpy(_n, _root); \ while (_p > _n && _p[-1] == '/') \ _p--; \ if (_path[0] != '/') \ *(_p++) = '/'; \ strcpy(_p, _path); \ _ret = _n; \ } \ _ret; \ }) int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg); char* dirname_malloc(const char *path); bool filename_is_valid(const char *p) _pure_; bool path_is_safe(const char *p) _pure_; char *file_in_same_dir(const char *path, const char *filename); bool hidden_file_allow_backup(const char *filename); bool hidden_file(const char *filename) _pure_; bool is_device_path(const char *path); systemd-229/src/basic/prioq.c000066400000000000000000000164271265713322000162410ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* * Priority Queue * The prioq object implements a priority queue. That is, it orders objects by * their priority and allows O(1) access to the object with the highest * priority. Insertion and removal are Θ(log n). Optionally, the caller can * provide a pointer to an index which will be kept up-to-date by the prioq. * * The underlying algorithm used in this implementation is a Heap. */ #include #include #include "alloc-util.h" #include "hashmap.h" #include "prioq.h" struct prioq_item { void *data; unsigned *idx; }; struct Prioq { compare_func_t compare_func; unsigned n_items, n_allocated; struct prioq_item *items; }; Prioq *prioq_new(compare_func_t compare_func) { Prioq *q; q = new0(Prioq, 1); if (!q) return q; q->compare_func = compare_func; return q; } Prioq* prioq_free(Prioq *q) { if (!q) return NULL; free(q->items); free(q); return NULL; } int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func) { assert(q); if (*q) return 0; *q = prioq_new(compare_func); if (!*q) return -ENOMEM; return 0; } static void swap(Prioq *q, unsigned j, unsigned k) { void *saved_data; unsigned *saved_idx; assert(q); assert(j < q->n_items); assert(k < q->n_items); assert(!q->items[j].idx || *(q->items[j].idx) == j); assert(!q->items[k].idx || *(q->items[k].idx) == k); saved_data = q->items[j].data; saved_idx = q->items[j].idx; q->items[j].data = q->items[k].data; q->items[j].idx = q->items[k].idx; q->items[k].data = saved_data; q->items[k].idx = saved_idx; if (q->items[j].idx) *q->items[j].idx = j; if (q->items[k].idx) *q->items[k].idx = k; } static unsigned shuffle_up(Prioq *q, unsigned idx) { assert(q); while (idx > 0) { unsigned k; k = (idx-1)/2; if (q->compare_func(q->items[k].data, q->items[idx].data) <= 0) break; swap(q, idx, k); idx = k; } return idx; } static unsigned shuffle_down(Prioq *q, unsigned idx) { assert(q); for (;;) { unsigned j, k, s; k = (idx+1)*2; /* right child */ j = k-1; /* left child */ if (j >= q->n_items) break; if (q->compare_func(q->items[j].data, q->items[idx].data) < 0) /* So our left child is smaller than we are, let's * remember this fact */ s = j; else s = idx; if (k < q->n_items && q->compare_func(q->items[k].data, q->items[s].data) < 0) /* So our right child is smaller than we are, let's * remember this fact */ s = k; /* s now points to the smallest of the three items */ if (s == idx) /* No swap necessary, we're done */ break; swap(q, idx, s); idx = s; } return idx; } int prioq_put(Prioq *q, void *data, unsigned *idx) { struct prioq_item *i; unsigned k; assert(q); if (q->n_items >= q->n_allocated) { unsigned n; struct prioq_item *j; n = MAX((q->n_items+1) * 2, 16u); j = realloc(q->items, sizeof(struct prioq_item) * n); if (!j) return -ENOMEM; q->items = j; q->n_allocated = n; } k = q->n_items++; i = q->items + k; i->data = data; i->idx = idx; if (idx) *idx = k; shuffle_up(q, k); return 0; } static void remove_item(Prioq *q, struct prioq_item *i) { struct prioq_item *l; assert(q); assert(i); l = q->items + q->n_items - 1; if (i == l) /* Last entry, let's just remove it */ q->n_items--; else { unsigned k; /* Not last entry, let's replace the last entry with * this one, and reshuffle */ k = i - q->items; i->data = l->data; i->idx = l->idx; if (i->idx) *i->idx = k; q->n_items--; k = shuffle_down(q, k); shuffle_up(q, k); } } _pure_ static struct prioq_item* find_item(Prioq *q, void *data, unsigned *idx) { struct prioq_item *i; assert(q); if (idx) { if (*idx == PRIOQ_IDX_NULL || *idx > q->n_items) return NULL; i = q->items + *idx; if (i->data != data) return NULL; return i; } else { for (i = q->items; i < q->items + q->n_items; i++) if (i->data == data) return i; return NULL; } } int prioq_remove(Prioq *q, void *data, unsigned *idx) { struct prioq_item *i; if (!q) return 0; i = find_item(q, data, idx); if (!i) return 0; remove_item(q, i); return 1; } int prioq_reshuffle(Prioq *q, void *data, unsigned *idx) { struct prioq_item *i; unsigned k; assert(q); i = find_item(q, data, idx); if (!i) return 0; k = i - q->items; k = shuffle_down(q, k); shuffle_up(q, k); return 1; } void *prioq_peek(Prioq *q) { if (!q) return NULL; if (q->n_items <= 0) return NULL; return q->items[0].data; } void *prioq_pop(Prioq *q) { void *data; if (!q) return NULL; if (q->n_items <= 0) return NULL; data = q->items[0].data; remove_item(q, q->items); return data; } unsigned prioq_size(Prioq *q) { if (!q) return 0; return q->n_items; } bool prioq_isempty(Prioq *q) { if (!q) return true; return q->n_items <= 0; } systemd-229/src/basic/prioq.h000066400000000000000000000024351265713322000162400ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "hashmap.h" #include "macro.h" typedef struct Prioq Prioq; #define PRIOQ_IDX_NULL ((unsigned) -1) Prioq *prioq_new(compare_func_t compare); Prioq *prioq_free(Prioq *q); int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func); int prioq_put(Prioq *q, void *data, unsigned *idx); int prioq_remove(Prioq *q, void *data, unsigned *idx); int prioq_reshuffle(Prioq *q, void *data, unsigned *idx); void *prioq_peek(Prioq *q) _pure_; void *prioq_pop(Prioq *q); unsigned prioq_size(Prioq *q) _pure_; bool prioq_isempty(Prioq *q) _pure_; systemd-229/src/basic/proc-cmdline.c000066400000000000000000000113771265713322000174620ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "extract-word.h" #include "fileio.h" #include "macro.h" #include "parse-util.h" #include "proc-cmdline.h" #include "process-util.h" #include "special.h" #include "string-util.h" #include "util.h" #include "virt.h" int proc_cmdline(char **ret) { assert(ret); if (detect_container() > 0) return get_process_cmdline(1, 0, false, ret); else return read_one_line_file("/proc/cmdline", ret); } int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) { _cleanup_free_ char *line = NULL; const char *p; int r; assert(parse_item); r = proc_cmdline(&line); if (r < 0) return r; p = line; for (;;) { _cleanup_free_ char *word = NULL; char *value = NULL; r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); if (r < 0) return r; if (r == 0) break; /* Filter out arguments that are intended only for the * initrd */ if (!in_initrd() && startswith(word, "rd.")) continue; value = strchr(word, '='); if (value) *(value++) = 0; r = parse_item(word, value); if (r < 0) return r; } return 0; } int get_proc_cmdline_key(const char *key, char **value) { _cleanup_free_ char *line = NULL, *ret = NULL; bool found = false; const char *p; int r; assert(key); r = proc_cmdline(&line); if (r < 0) return r; p = line; for (;;) { _cleanup_free_ char *word = NULL; const char *e; r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); if (r < 0) return r; if (r == 0) break; /* Filter out arguments that are intended only for the * initrd */ if (!in_initrd() && startswith(word, "rd.")) continue; if (value) { e = startswith(word, key); if (!e) continue; r = free_and_strdup(&ret, e); if (r < 0) return r; found = true; } else { if (streq(word, key)) found = true; } } if (value) { *value = ret; ret = NULL; } return found; } int shall_restore_state(void) { _cleanup_free_ char *value = NULL; int r; r = get_proc_cmdline_key("systemd.restore_state=", &value); if (r < 0) return r; if (r == 0) return true; return parse_boolean(value); } static const char * const rlmap[] = { "emergency", SPECIAL_EMERGENCY_TARGET, "-b", SPECIAL_EMERGENCY_TARGET, "rescue", SPECIAL_RESCUE_TARGET, "single", SPECIAL_RESCUE_TARGET, "-s", SPECIAL_RESCUE_TARGET, "s", SPECIAL_RESCUE_TARGET, "S", SPECIAL_RESCUE_TARGET, "1", SPECIAL_RESCUE_TARGET, "2", SPECIAL_MULTI_USER_TARGET, "3", SPECIAL_MULTI_USER_TARGET, "4", SPECIAL_MULTI_USER_TARGET, "5", SPECIAL_GRAPHICAL_TARGET, }; const char* runlevel_to_target(const char *word) { size_t i; if (!word) return NULL; for (i = 0; i < ELEMENTSOF(rlmap); i += 2) if (streq(word, rlmap[i])) return rlmap[i+1]; return NULL; } systemd-229/src/basic/proc-cmdline.h000066400000000000000000000017311265713322000174600ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int proc_cmdline(char **ret); int parse_proc_cmdline(int (*parse_word)(const char *key, const char *value)); int get_proc_cmdline_key(const char *parameter, char **value); int shall_restore_state(void); const char* runlevel_to_target(const char *rl); systemd-229/src/basic/process-util.c000066400000000000000000000464441265713322000175420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_VALGRIND_VALGRIND_H #include #endif #include "alloc-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "ioprio.h" #include "log.h" #include "macro.h" #include "missing.h" #include "process-util.h" #include "signal-util.h" #include "stat-util.h" #include "string-table.h" #include "string-util.h" #include "user-util.h" #include "util.h" int get_process_state(pid_t pid) { const char *p; char state; int r; _cleanup_free_ char *line = NULL; assert(pid >= 0); p = procfs_file_alloca(pid, "stat"); r = read_one_line_file(p, &line); if (r == -ENOENT) return -ESRCH; if (r < 0) return r; p = strrchr(line, ')'); if (!p) return -EIO; p++; if (sscanf(p, " %c", &state) != 1) return -EIO; return (unsigned char) state; } int get_process_comm(pid_t pid, char **name) { const char *p; int r; assert(name); assert(pid >= 0); p = procfs_file_alloca(pid, "comm"); r = read_one_line_file(p, name); if (r == -ENOENT) return -ESRCH; return r; } int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) { _cleanup_fclose_ FILE *f = NULL; char *r = NULL, *k; const char *p; int c; assert(line); assert(pid >= 0); p = procfs_file_alloca(pid, "cmdline"); f = fopen(p, "re"); if (!f) { if (errno == ENOENT) return -ESRCH; return -errno; } if (max_length == 0) { size_t len = 0, allocated = 0; while ((c = getc(f)) != EOF) { if (!GREEDY_REALLOC(r, allocated, len+2)) { free(r); return -ENOMEM; } r[len++] = isprint(c) ? c : ' '; } if (len > 0) r[len-1] = 0; } else { bool space = false; size_t left; r = new(char, max_length); if (!r) return -ENOMEM; k = r; left = max_length; while ((c = getc(f)) != EOF) { if (isprint(c)) { if (space) { if (left <= 4) break; *(k++) = ' '; left--; space = false; } if (left <= 4) break; *(k++) = (char) c; left--; } else space = true; } if (left <= 4) { size_t n = MIN(left-1, 3U); memcpy(k, "...", n); k[n] = 0; } else *k = 0; } /* Kernel threads have no argv[] */ if (isempty(r)) { _cleanup_free_ char *t = NULL; int h; free(r); if (!comm_fallback) return -ENOENT; h = get_process_comm(pid, &t); if (h < 0) return h; r = strjoin("[", t, "]", NULL); if (!r) return -ENOMEM; } *line = r; return 0; } void rename_process(const char name[8]) { assert(name); /* This is a like a poor man's setproctitle(). It changes the * comm field, argv[0], and also the glibc's internally used * name of the process. For the first one a limit of 16 chars * applies, to the second one usually one of 10 (i.e. length * of "/sbin/init"), to the third one one of 7 (i.e. length of * "systemd"). If you pass a longer string it will be * truncated */ prctl(PR_SET_NAME, name); if (program_invocation_name) strncpy(program_invocation_name, name, strlen(program_invocation_name)); if (saved_argc > 0) { int i; if (saved_argv[0]) strncpy(saved_argv[0], name, strlen(saved_argv[0])); for (i = 1; i < saved_argc; i++) { if (!saved_argv[i]) break; memzero(saved_argv[i], strlen(saved_argv[i])); } } } int is_kernel_thread(pid_t pid) { const char *p; size_t count; char c; bool eof; FILE *f; if (pid == 0 || pid == 1) /* pid 1, and we ourselves certainly aren't a kernel thread */ return 0; assert(pid > 1); p = procfs_file_alloca(pid, "cmdline"); f = fopen(p, "re"); if (!f) { if (errno == ENOENT) return -ESRCH; return -errno; } count = fread(&c, 1, 1, f); eof = feof(f); fclose(f); /* Kernel threads have an empty cmdline */ if (count <= 0) return eof ? 1 : -errno; return 0; } int get_process_capeff(pid_t pid, char **capeff) { const char *p; int r; assert(capeff); assert(pid >= 0); p = procfs_file_alloca(pid, "status"); r = get_proc_field(p, "CapEff", WHITESPACE, capeff); if (r == -ENOENT) return -ESRCH; return r; } static int get_process_link_contents(const char *proc_file, char **name) { int r; assert(proc_file); assert(name); r = readlink_malloc(proc_file, name); if (r == -ENOENT) return -ESRCH; if (r < 0) return r; return 0; } int get_process_exe(pid_t pid, char **name) { const char *p; char *d; int r; assert(pid >= 0); p = procfs_file_alloca(pid, "exe"); r = get_process_link_contents(p, name); if (r < 0) return r; d = endswith(*name, " (deleted)"); if (d) *d = '\0'; return 0; } static int get_process_id(pid_t pid, const char *field, uid_t *uid) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; const char *p; assert(field); assert(uid); if (pid == 0) return getuid(); p = procfs_file_alloca(pid, "status"); f = fopen(p, "re"); if (!f) { if (errno == ENOENT) return -ESRCH; return -errno; } FOREACH_LINE(line, f, return -errno) { char *l; l = strstrip(line); if (startswith(l, field)) { l += strlen(field); l += strspn(l, WHITESPACE); l[strcspn(l, WHITESPACE)] = 0; return parse_uid(l, uid); } } return -EIO; } int get_process_uid(pid_t pid, uid_t *uid) { return get_process_id(pid, "Uid:", uid); } int get_process_gid(pid_t pid, gid_t *gid) { assert_cc(sizeof(uid_t) == sizeof(gid_t)); return get_process_id(pid, "Gid:", gid); } int get_process_cwd(pid_t pid, char **cwd) { const char *p; assert(pid >= 0); p = procfs_file_alloca(pid, "cwd"); return get_process_link_contents(p, cwd); } int get_process_root(pid_t pid, char **root) { const char *p; assert(pid >= 0); p = procfs_file_alloca(pid, "root"); return get_process_link_contents(p, root); } int get_process_environ(pid_t pid, char **env) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *outcome = NULL; int c; const char *p; size_t allocated = 0, sz = 0; assert(pid >= 0); assert(env); p = procfs_file_alloca(pid, "environ"); f = fopen(p, "re"); if (!f) { if (errno == ENOENT) return -ESRCH; return -errno; } while ((c = fgetc(f)) != EOF) { if (!GREEDY_REALLOC(outcome, allocated, sz + 5)) return -ENOMEM; if (c == '\0') outcome[sz++] = '\n'; else sz += cescape_char(c, outcome + sz); } if (!outcome) { outcome = strdup(""); if (!outcome) return -ENOMEM; } else outcome[sz] = '\0'; *env = outcome; outcome = NULL; return 0; } int get_process_ppid(pid_t pid, pid_t *_ppid) { int r; _cleanup_free_ char *line = NULL; long unsigned ppid; const char *p; assert(pid >= 0); assert(_ppid); if (pid == 0) { *_ppid = getppid(); return 0; } p = procfs_file_alloca(pid, "stat"); r = read_one_line_file(p, &line); if (r == -ENOENT) return -ESRCH; if (r < 0) return r; /* Let's skip the pid and comm fields. The latter is enclosed * in () but does not escape any () in its value, so let's * skip over it manually */ p = strrchr(line, ')'); if (!p) return -EIO; p++; if (sscanf(p, " " "%*c " /* state */ "%lu ", /* ppid */ &ppid) != 1) return -EIO; if ((long unsigned) (pid_t) ppid != ppid) return -ERANGE; *_ppid = (pid_t) ppid; return 0; } int wait_for_terminate(pid_t pid, siginfo_t *status) { siginfo_t dummy; assert(pid >= 1); if (!status) status = &dummy; for (;;) { zero(*status); if (waitid(P_PID, pid, status, WEXITED) < 0) { if (errno == EINTR) continue; return -errno; } return 0; } } /* * Return values: * < 0 : wait_for_terminate() failed to get the state of the * process, the process was terminated by a signal, or * failed for an unknown reason. * >=0 : The process terminated normally, and its exit code is * returned. * * That is, success is indicated by a return value of zero, and an * error is indicated by a non-zero value. * * A warning is emitted if the process terminates abnormally, * and also if it returns non-zero unless check_exit_code is true. */ int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code) { int r; siginfo_t status; assert(name); assert(pid > 1); r = wait_for_terminate(pid, &status); if (r < 0) return log_warning_errno(r, "Failed to wait for %s: %m", name); if (status.si_code == CLD_EXITED) { if (status.si_status != 0) log_full(check_exit_code ? LOG_WARNING : LOG_DEBUG, "%s failed with error code %i.", name, status.si_status); else log_debug("%s succeeded.", name); return status.si_status; } else if (status.si_code == CLD_KILLED || status.si_code == CLD_DUMPED) { log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status)); return -EPROTO; } log_warning("%s failed due to unknown reason.", name); return -EPROTO; } void sigkill_wait(pid_t *pid) { if (!pid) return; if (*pid <= 1) return; if (kill(*pid, SIGKILL) > 0) (void) wait_for_terminate(*pid, NULL); } int kill_and_sigcont(pid_t pid, int sig) { int r; r = kill(pid, sig) < 0 ? -errno : 0; if (r >= 0) kill(pid, SIGCONT); return r; } int getenv_for_pid(pid_t pid, const char *field, char **_value) { _cleanup_fclose_ FILE *f = NULL; char *value = NULL; int r; bool done = false; size_t l; const char *path; assert(pid >= 0); assert(field); assert(_value); path = procfs_file_alloca(pid, "environ"); f = fopen(path, "re"); if (!f) { if (errno == ENOENT) return -ESRCH; return -errno; } l = strlen(field); r = 0; do { char line[LINE_MAX]; unsigned i; for (i = 0; i < sizeof(line)-1; i++) { int c; c = getc(f); if (_unlikely_(c == EOF)) { done = true; break; } else if (c == 0) break; line[i] = c; } line[i] = 0; if (memcmp(line, field, l) == 0 && line[l] == '=') { value = strdup(line + l + 1); if (!value) return -ENOMEM; r = 1; break; } } while (!done); *_value = value; return r; } bool pid_is_unwaited(pid_t pid) { /* Checks whether a PID is still valid at all, including a zombie */ if (pid < 0) return false; if (pid <= 1) /* If we or PID 1 would be dead and have been waited for, this code would not be running */ return true; if (kill(pid, 0) >= 0) return true; return errno != ESRCH; } bool pid_is_alive(pid_t pid) { int r; /* Checks whether a PID is still valid and not a zombie */ if (pid < 0) return false; if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */ return true; r = get_process_state(pid); if (r == -ESRCH || r == 'Z') return false; return true; } int pid_from_same_root_fs(pid_t pid) { const char *root; if (pid < 0) return 0; root = procfs_file_alloca(pid, "root"); return files_same(root, "/proc/1/root"); } bool is_main_thread(void) { static thread_local int cached = 0; if (_unlikely_(cached == 0)) cached = getpid() == gettid() ? 1 : -1; return cached > 0; } noreturn void freeze(void) { /* Make sure nobody waits for us on a socket anymore */ close_all_fds(NULL, 0); sync(); for (;;) pause(); } bool oom_score_adjust_is_valid(int oa) { return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX; } unsigned long personality_from_string(const char *p) { /* Parse a personality specifier. We introduce our own * identifiers that indicate specific ABIs, rather than just * hints regarding the register size, since we want to keep * things open for multiple locally supported ABIs for the * same register size. We try to reuse the ABI identifiers * used by libseccomp. */ #if defined(__x86_64__) if (streq(p, "x86")) return PER_LINUX32; if (streq(p, "x86-64")) return PER_LINUX; #elif defined(__i386__) if (streq(p, "x86")) return PER_LINUX; #elif defined(__s390x__) if (streq(p, "s390")) return PER_LINUX32; if (streq(p, "s390x")) return PER_LINUX; #elif defined(__s390__) if (streq(p, "s390")) return PER_LINUX; #endif return PERSONALITY_INVALID; } const char* personality_to_string(unsigned long p) { #if defined(__x86_64__) if (p == PER_LINUX32) return "x86"; if (p == PER_LINUX) return "x86-64"; #elif defined(__i386__) if (p == PER_LINUX) return "x86"; #elif defined(__s390x__) if (p == PER_LINUX) return "s390x"; if (p == PER_LINUX32) return "s390"; #elif defined(__s390__) if (p == PER_LINUX) return "s390"; #endif return NULL; } void valgrind_summary_hack(void) { #ifdef HAVE_VALGRIND_VALGRIND_H if (getpid() == 1 && RUNNING_ON_VALGRIND) { pid_t pid; pid = raw_clone(SIGCHLD, NULL); if (pid < 0) log_emergency_errno(errno, "Failed to fork off valgrind helper: %m"); else if (pid == 0) exit(EXIT_SUCCESS); else { log_info("Spawned valgrind helper as PID "PID_FMT".", pid); (void) wait_for_terminate(pid, NULL); } } #endif } static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_RT] = "realtime", [IOPRIO_CLASS_BE] = "best-effort", [IOPRIO_CLASS_IDLE] = "idle" }; DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX); static const char *const sigchld_code_table[] = { [CLD_EXITED] = "exited", [CLD_KILLED] = "killed", [CLD_DUMPED] = "dumped", [CLD_TRAPPED] = "trapped", [CLD_STOPPED] = "stopped", [CLD_CONTINUED] = "continued", }; DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int); static const char* const sched_policy_table[] = { [SCHED_OTHER] = "other", [SCHED_BATCH] = "batch", [SCHED_IDLE] = "idle", [SCHED_FIFO] = "fifo", [SCHED_RR] = "rr" }; DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX); systemd-229/src/basic/process-util.h000066400000000000000000000072031265713322000175350ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "formats-util.h" #include "macro.h" #define procfs_file_alloca(pid, field) \ ({ \ pid_t _pid_ = (pid); \ const char *_r_; \ if (_pid_ == 0) { \ _r_ = ("/proc/self/" field); \ } else { \ _r_ = alloca(strlen("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \ sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \ } \ _r_; \ }) int get_process_state(pid_t pid); int get_process_comm(pid_t pid, char **name); int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line); int get_process_exe(pid_t pid, char **name); int get_process_uid(pid_t pid, uid_t *uid); int get_process_gid(pid_t pid, gid_t *gid); int get_process_capeff(pid_t pid, char **capeff); int get_process_cwd(pid_t pid, char **cwd); int get_process_root(pid_t pid, char **root); int get_process_environ(pid_t pid, char **environ); int get_process_ppid(pid_t pid, pid_t *ppid); int wait_for_terminate(pid_t pid, siginfo_t *status); int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code); void sigkill_wait(pid_t *pid); #define _cleanup_sigkill_wait_ _cleanup_(sigkill_wait) int kill_and_sigcont(pid_t pid, int sig); void rename_process(const char name[8]); int is_kernel_thread(pid_t pid); int getenv_for_pid(pid_t pid, const char *field, char **_value); bool pid_is_alive(pid_t pid); bool pid_is_unwaited(pid_t pid); int pid_from_same_root_fs(pid_t pid); bool is_main_thread(void); noreturn void freeze(void); bool oom_score_adjust_is_valid(int oa); #ifndef PERSONALITY_INVALID /* personality(7) documents that 0xffffffffUL is used for querying the * current personality, hence let's use that here as error * indicator. */ #define PERSONALITY_INVALID 0xffffffffLU #endif unsigned long personality_from_string(const char *p); const char *personality_to_string(unsigned long); int ioprio_class_to_string_alloc(int i, char **s); int ioprio_class_from_string(const char *s); const char *sigchld_code_to_string(int i) _const_; int sigchld_code_from_string(const char *s) _pure_; int sched_policy_to_string_alloc(int i, char **s); int sched_policy_from_string(const char *s); #define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p)) #define PID_TO_PTR(p) ((void*) ((uintptr_t) p)) void valgrind_summary_hack(void); systemd-229/src/basic/random-util.c000066400000000000000000000101471265713322000173330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_AUXV_H #include #endif #include "fd-util.h" #include "io-util.h" #include "missing.h" #include "random-util.h" #include "time-util.h" int dev_urandom(void *p, size_t n) { static int have_syscall = -1; _cleanup_close_ int fd = -1; int r; /* Gathers some randomness from the kernel. This call will * never block, and will always return some data from the * kernel, regardless if the random pool is fully initialized * or not. It thus makes no guarantee for the quality of the * returned entropy, but is good enough for or usual usecases * of seeding the hash functions for hashtable */ /* Use the getrandom() syscall unless we know we don't have * it, or when the requested size is too large for it. */ if (have_syscall != 0 || (size_t) (int) n != n) { r = getrandom(p, n, GRND_NONBLOCK); if (r == (int) n) { have_syscall = true; return 0; } if (r < 0) { if (errno == ENOSYS) /* we lack the syscall, continue with * reading from /dev/urandom */ have_syscall = false; else if (errno == EAGAIN) /* not enough entropy for now. Let's * remember to use the syscall the * next time, again, but also read * from /dev/urandom for now, which * doesn't care about the current * amount of entropy. */ have_syscall = true; else return -errno; } else /* too short read? */ return -ENODATA; } fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return errno == ENOENT ? -ENOSYS : -errno; return loop_read_exact(fd, p, n, true); } void initialize_srand(void) { static bool srand_called = false; unsigned x; #ifdef HAVE_SYS_AUXV_H void *auxv; #endif if (srand_called) return; #ifdef HAVE_SYS_AUXV_H /* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed the * pseudo-random generator. It's better than nothing... */ auxv = (void*) getauxval(AT_RANDOM); if (auxv) { assert_cc(sizeof(x) < 16); memcpy(&x, auxv, sizeof(x)); } else #endif x = 0; x ^= (unsigned) now(CLOCK_REALTIME); x ^= (unsigned) gettid(); srand(x); srand_called = true; } void random_bytes(void *p, size_t n) { uint8_t *q; int r; r = dev_urandom(p, n); if (r >= 0) return; /* If some idiot made /dev/urandom unavailable to us, he'll * get a PRNG instead. */ initialize_srand(); for (q = p; q < (uint8_t*) p + n; q ++) *q = rand(); } systemd-229/src/basic/random-util.h000066400000000000000000000021351265713322000173360ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include int dev_urandom(void *p, size_t n); void random_bytes(void *p, size_t n); void initialize_srand(void); static inline uint64_t random_u64(void) { uint64_t u; random_bytes(&u, sizeof(u)); return u; } static inline uint32_t random_u32(void) { uint32_t u; random_bytes(&u, sizeof(u)); return u; } systemd-229/src/basic/ratelimit.c000066400000000000000000000026221265713322000170710ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" #include "ratelimit.h" /* Modelled after Linux' lib/ratelimit.c by Dave Young * , which is licensed GPLv2. */ bool ratelimit_test(RateLimit *r) { usec_t ts; assert(r); if (r->interval <= 0 || r->burst <= 0) return true; ts = now(CLOCK_MONOTONIC); if (r->begin <= 0 || r->begin + r->interval < ts) { r->begin = ts; /* Reset counter */ r->num = 0; goto good; } if (r->num < r->burst) goto good; return false; good: r->num++; return true; } systemd-229/src/basic/ratelimit.h000066400000000000000000000040511265713322000170740ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "time-util.h" #include "util.h" typedef struct RateLimit { usec_t interval; usec_t begin; unsigned burst; unsigned num; } RateLimit; #define RATELIMIT_DEFINE(_name, _interval, _burst) \ RateLimit _name = { \ .interval = (_interval), \ .burst = (_burst), \ .num = 0, \ .begin = 0 \ } #define RATELIMIT_INIT(v, _interval, _burst) \ do { \ RateLimit *_r = &(v); \ _r->interval = (_interval); \ _r->burst = (_burst); \ _r->num = 0; \ _r->begin = 0; \ } while (false) #define RATELIMIT_RESET(v) \ do { \ RateLimit *_r = &(v); \ _r->num = 0; \ _r->begin = 0; \ } while (false) bool ratelimit_test(RateLimit *r); systemd-229/src/basic/refcnt.h000066400000000000000000000021261265713322000163640ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* A type-safe atomic refcounter. * * DO NOT USE THIS UNLESS YOU ACTUALLY CARE ABOUT THREAD SAFETY! */ typedef struct { volatile unsigned _value; } RefCount; #define REFCNT_GET(r) ((r)._value) #define REFCNT_INC(r) (__sync_add_and_fetch(&(r)._value, 1)) #define REFCNT_DEC(r) (__sync_sub_and_fetch(&(r)._value, 1)) #define REFCNT_INIT ((RefCount) { ._value = 1 }) systemd-229/src/basic/replace-var.c000066400000000000000000000052201265713322000172750ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "macro.h" #include "replace-var.h" #include "string-util.h" /* * Generic infrastructure for replacing @FOO@ style variables in * strings. Will call a callback for each replacement. */ static int get_variable(const char *b, char **r) { size_t k; char *t; assert(b); assert(r); if (*b != '@') return 0; k = strspn(b + 1, UPPERCASE_LETTERS "_"); if (k <= 0 || b[k+1] != '@') return 0; t = strndup(b + 1, k); if (!t) return -ENOMEM; *r = t; return 1; } char *replace_var(const char *text, char *(*lookup)(const char *variable, void*userdata), void *userdata) { char *r, *t; const char *f; size_t l; assert(text); assert(lookup); l = strlen(text); r = new(char, l+1); if (!r) return NULL; f = text; t = r; while (*f) { _cleanup_free_ char *v = NULL, *n = NULL; char *a; int k; size_t skip, d, nl; k = get_variable(f, &v); if (k < 0) goto oom; if (k == 0) { *(t++) = *(f++); continue; } n = lookup(v, userdata); if (!n) goto oom; skip = strlen(v) + 2; d = t - r; nl = l - skip + strlen(n); a = realloc(r, nl + 1); if (!a) goto oom; l = nl; r = a; t = r + d; t = stpcpy(t, n); f += skip; } *t = 0; return r; oom: free(r); return NULL; } systemd-229/src/basic/replace-var.h000066400000000000000000000015101265713322000173000ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ char *replace_var(const char *text, char *(*lookup)(const char *variable, void*userdata), void *userdata); systemd-229/src/basic/rlimit-util.c000066400000000000000000000164061265713322000173570ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "extract-word.h" #include "formats-util.h" #include "macro.h" #include "missing.h" #include "rlimit-util.h" #include "string-table.h" #include "time-util.h" int setrlimit_closest(int resource, const struct rlimit *rlim) { struct rlimit highest, fixed; assert(rlim); if (setrlimit(resource, rlim) >= 0) return 0; if (errno != EPERM) return -errno; /* So we failed to set the desired setrlimit, then let's try * to get as close as we can */ assert_se(getrlimit(resource, &highest) == 0); fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max); fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max); if (setrlimit(resource, &fixed) < 0) return -errno; return 0; } static int rlimit_parse_u64(const char *val, rlim_t *ret) { uint64_t u; int r; assert(val); assert(ret); if (streq(val, "infinity")) { *ret = RLIM_INFINITY; return 0; } /* setrlimit(2) suggests rlim_t is always 64bit on Linux. */ assert_cc(sizeof(rlim_t) == sizeof(uint64_t)); r = safe_atou64(val, &u); if (r < 0) return r; if (u >= (uint64_t) RLIM_INFINITY) return -ERANGE; *ret = (rlim_t) u; return 0; } static int rlimit_parse_size(const char *val, rlim_t *ret) { uint64_t u; int r; assert(val); assert(ret); if (streq(val, "infinity")) { *ret = RLIM_INFINITY; return 0; } r = parse_size(val, 1024, &u); if (r < 0) return r; if (u >= (uint64_t) RLIM_INFINITY) return -ERANGE; *ret = (rlim_t) u; return 0; } static int rlimit_parse_sec(const char *val, rlim_t *ret) { uint64_t u; usec_t t; int r; assert(val); assert(ret); if (streq(val, "infinity")) { *ret = RLIM_INFINITY; return 0; } r = parse_sec(val, &t); if (r < 0) return r; if (t == USEC_INFINITY) { *ret = RLIM_INFINITY; return 0; } u = (uint64_t) DIV_ROUND_UP(t, USEC_PER_SEC); if (u >= (uint64_t) RLIM_INFINITY) return -ERANGE; *ret = (rlim_t) u; return 0; } static int rlimit_parse_usec(const char *val, rlim_t *ret) { usec_t t; int r; assert(val); assert(ret); if (streq(val, "infinity")) { *ret = RLIM_INFINITY; return 0; } r = parse_time(val, &t, 1); if (r < 0) return r; if (t == USEC_INFINITY) { *ret = RLIM_INFINITY; return 0; } *ret = (rlim_t) t; return 0; } static int (*const rlimit_parse_table[_RLIMIT_MAX])(const char *val, rlim_t *ret) = { [RLIMIT_CPU] = rlimit_parse_sec, [RLIMIT_FSIZE] = rlimit_parse_size, [RLIMIT_DATA] = rlimit_parse_size, [RLIMIT_STACK] = rlimit_parse_size, [RLIMIT_CORE] = rlimit_parse_size, [RLIMIT_RSS] = rlimit_parse_size, [RLIMIT_NOFILE] = rlimit_parse_u64, [RLIMIT_AS] = rlimit_parse_size, [RLIMIT_NPROC] = rlimit_parse_u64, [RLIMIT_MEMLOCK] = rlimit_parse_size, [RLIMIT_LOCKS] = rlimit_parse_u64, [RLIMIT_SIGPENDING] = rlimit_parse_u64, [RLIMIT_MSGQUEUE] = rlimit_parse_size, [RLIMIT_NICE] = rlimit_parse_u64, [RLIMIT_RTPRIO] = rlimit_parse_u64, [RLIMIT_RTTIME] = rlimit_parse_usec, }; int rlimit_parse_one(int resource, const char *val, rlim_t *ret) { assert(val); assert(ret); if (resource < 0) return -EINVAL; if (resource >= _RLIMIT_MAX) return -EINVAL; return rlimit_parse_table[resource](val, ret); } int rlimit_parse(int resource, const char *val, struct rlimit *ret) { _cleanup_free_ char *hard = NULL, *soft = NULL; rlim_t hl, sl; int r; assert(val); assert(ret); r = extract_first_word(&val, &soft, ":", EXTRACT_DONT_COALESCE_SEPARATORS); if (r < 0) return r; if (r == 0) return -EINVAL; r = rlimit_parse_one(resource, soft, &sl); if (r < 0) return r; r = extract_first_word(&val, &hard, ":", EXTRACT_DONT_COALESCE_SEPARATORS); if (r < 0) return r; if (!isempty(val)) return -EINVAL; if (r == 0) hl = sl; else { r = rlimit_parse_one(resource, hard, &hl); if (r < 0) return r; if (sl > hl) return -EILSEQ; } *ret = (struct rlimit) { .rlim_cur = sl, .rlim_max = hl, }; return 0; } int rlimit_format(const struct rlimit *rl, char **ret) { char *s = NULL; assert(rl); assert(ret); if (rl->rlim_cur >= RLIM_INFINITY && rl->rlim_max >= RLIM_INFINITY) s = strdup("infinity"); else if (rl->rlim_cur >= RLIM_INFINITY) (void) asprintf(&s, "infinity:" RLIM_FMT, rl->rlim_max); else if (rl->rlim_max >= RLIM_INFINITY) (void) asprintf(&s, RLIM_FMT ":infinity", rl->rlim_cur); else if (rl->rlim_cur == rl->rlim_max) (void) asprintf(&s, RLIM_FMT, rl->rlim_cur); else (void) asprintf(&s, RLIM_FMT ":" RLIM_FMT, rl->rlim_cur, rl->rlim_max); if (!s) return -ENOMEM; *ret = s; return 0; } static const char* const rlimit_table[_RLIMIT_MAX] = { [RLIMIT_CPU] = "LimitCPU", [RLIMIT_FSIZE] = "LimitFSIZE", [RLIMIT_DATA] = "LimitDATA", [RLIMIT_STACK] = "LimitSTACK", [RLIMIT_CORE] = "LimitCORE", [RLIMIT_RSS] = "LimitRSS", [RLIMIT_NOFILE] = "LimitNOFILE", [RLIMIT_AS] = "LimitAS", [RLIMIT_NPROC] = "LimitNPROC", [RLIMIT_MEMLOCK] = "LimitMEMLOCK", [RLIMIT_LOCKS] = "LimitLOCKS", [RLIMIT_SIGPENDING] = "LimitSIGPENDING", [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE", [RLIMIT_NICE] = "LimitNICE", [RLIMIT_RTPRIO] = "LimitRTPRIO", [RLIMIT_RTTIME] = "LimitRTTIME" }; DEFINE_STRING_TABLE_LOOKUP(rlimit, int); systemd-229/src/basic/rlimit-util.h000066400000000000000000000022501265713322000173540ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" const char *rlimit_to_string(int i) _const_; int rlimit_from_string(const char *s) _pure_; int setrlimit_closest(int resource, const struct rlimit *rlim); int rlimit_parse_one(int resource, const char *val, rlim_t *ret); int rlimit_parse(int resource, const char *val, struct rlimit *ret); int rlimit_format(const struct rlimit *rl, char **ret); #define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim }) systemd-229/src/basic/rm-rf.c000066400000000000000000000206201265713322000161200ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "btrfs-util.h" #include "fd-util.h" #include "log.h" #include "macro.h" #include "mount-util.h" #include "path-util.h" #include "rm-rf.h" #include "stat-util.h" #include "string-util.h" int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { _cleanup_closedir_ DIR *d = NULL; int ret = 0, r; assert(fd >= 0); /* This returns the first error we run into, but nevertheless * tries to go on. This closes the passed fd. */ if (!(flags & REMOVE_PHYSICAL)) { r = fd_is_temporary_fs(fd); if (r < 0) { safe_close(fd); return r; } if (!r) { /* We refuse to clean physical file systems * with this call, unless explicitly * requested. This is extra paranoia just to * be sure we never ever remove non-state * data */ log_error("Attempted to remove disk file system, and we can't allow that."); safe_close(fd); return -EPERM; } } d = fdopendir(fd); if (!d) { safe_close(fd); return errno == ENOENT ? 0 : -errno; } for (;;) { struct dirent *de; bool is_dir; struct stat st; errno = 0; de = readdir(d); if (!de) { if (errno > 0 && ret == 0) ret = -errno; return ret; } if (streq(de->d_name, ".") || streq(de->d_name, "..")) continue; if (de->d_type == DT_UNKNOWN || (de->d_type == DT_DIR && (root_dev || (flags & REMOVE_SUBVOLUME)))) { if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { if (ret == 0 && errno != ENOENT) ret = -errno; continue; } is_dir = S_ISDIR(st.st_mode); } else is_dir = de->d_type == DT_DIR; if (is_dir) { int subdir_fd; /* if root_dev is set, remove subdirectories only if device is same */ if (root_dev && st.st_dev != root_dev->st_dev) continue; subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); if (subdir_fd < 0) { if (ret == 0 && errno != ENOENT) ret = -errno; continue; } /* Stop at mount points */ r = fd_is_mount_point(fd, de->d_name, 0); if (r < 0) { if (ret == 0 && r != -ENOENT) ret = r; safe_close(subdir_fd); continue; } if (r) { safe_close(subdir_fd); continue; } if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) { /* This could be a subvolume, try to remove it */ r = btrfs_subvol_remove_fd(fd, de->d_name, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); if (r < 0) { if (r != -ENOTTY && r != -EINVAL) { if (ret == 0) ret = r; safe_close(subdir_fd); continue; } /* ENOTTY, then it wasn't a * btrfs subvolume, continue * below. */ } else { /* It was a subvolume, continue. */ safe_close(subdir_fd); continue; } } /* We pass REMOVE_PHYSICAL here, to avoid * doing the fstatfs() to check the file * system type again for each directory */ r = rm_rf_children(subdir_fd, flags | REMOVE_PHYSICAL, root_dev); if (r < 0 && ret == 0) ret = r; if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) { if (ret == 0 && errno != ENOENT) ret = -errno; } } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) { if (unlinkat(fd, de->d_name, 0) < 0) { if (ret == 0 && errno != ENOENT) ret = -errno; } } } } int rm_rf(const char *path, RemoveFlags flags) { int fd, r; struct statfs s; assert(path); /* We refuse to clean the root file system with this * call. This is extra paranoia to never cause a really * seriously broken system. */ if (path_equal(path, "/")) { log_error("Attempted to remove entire root file system, and we can't allow that."); return -EPERM; } if ((flags & (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) == (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) { /* Try to remove as subvolume first */ r = btrfs_subvol_remove(path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); if (r >= 0) return r; if (r != -ENOTTY && r != -EINVAL && r != -ENOTDIR) return r; /* Not btrfs or not a subvolume */ } fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); if (fd < 0) { if (errno != ENOTDIR && errno != ELOOP) return -errno; if (!(flags & REMOVE_PHYSICAL)) { if (statfs(path, &s) < 0) return -errno; if (!is_temporary_fs(&s)) { log_error("Attempted to remove disk file system, and we can't allow that."); return -EPERM; } } if ((flags & REMOVE_ROOT) && !(flags & REMOVE_ONLY_DIRECTORIES)) if (unlink(path) < 0 && errno != ENOENT) return -errno; return 0; } r = rm_rf_children(fd, flags, NULL); if (flags & REMOVE_ROOT) { if (rmdir(path) < 0) { if (r == 0 && errno != ENOENT) r = -errno; } } return r; } systemd-229/src/basic/rm-rf.h000066400000000000000000000021311265713322000161220ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include typedef enum RemoveFlags { REMOVE_ONLY_DIRECTORIES = 1, REMOVE_ROOT = 2, REMOVE_PHYSICAL = 4, /* if not set, only removes files on tmpfs, never physical file systems */ REMOVE_SUBVOLUME = 8, } RemoveFlags; int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev); int rm_rf(const char *path, RemoveFlags flags); systemd-229/src/basic/securebits.h000066400000000000000000000037571265713322000172660ustar00rootroot00000000000000#ifndef _LINUX_SECUREBITS_H #define _LINUX_SECUREBITS_H 1 /* This is minimal version of Linux' linux/securebits.h header file, * which is licensed GPL2 */ #define SECUREBITS_DEFAULT 0x00000000 /* When set UID 0 has no special privileges. When unset, we support inheritance of root-permissions and suid-root executable under compatibility mode. We raise the effective and inheritable bitmasks *of the executable file* if the effective uid of the new process is 0. If the real uid is 0, we raise the effective (legacy) bit of the executable file. */ #define SECURE_NOROOT 0 #define SECURE_NOROOT_LOCKED 1 /* make bit-0 immutable */ /* When set, setuid to/from uid 0 does not trigger capability-"fixup". When unset, to provide compatibility with old programs relying on set*uid to gain/lose privilege, transitions to/from uid 0 cause capabilities to be gained/lost. */ #define SECURE_NO_SETUID_FIXUP 2 #define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */ /* When set, a process can retain its capabilities even after transitioning to a non-root user (the set-uid fixup suppressed by bit 2). Bit-4 is cleared when a process calls exec(); setting both bit 4 and 5 will create a barrier through exec that no exec()'d child can use this feature again. */ #define SECURE_KEEP_CAPS 4 #define SECURE_KEEP_CAPS_LOCKED 5 /* make bit-4 immutable */ /* Each securesetting is implemented using two bits. One bit specifies whether the setting is on or off. The other bit specify whether the setting is locked or not. A setting which is locked cannot be changed from user-level. */ #define issecure_mask(X) (1 << (X)) #define issecure(X) (issecure_mask(X) & current_cred_xxx(securebits)) #define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \ issecure_mask(SECURE_NO_SETUID_FIXUP) | \ issecure_mask(SECURE_KEEP_CAPS)) #define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1) #endif /* !_LINUX_SECUREBITS_H */ systemd-229/src/basic/selinux-util.c000066400000000000000000000314751265713322000175510ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #ifdef HAVE_SELINUX #include #include #include #endif #include "alloc-util.h" #include "log.h" #include "macro.h" #include "path-util.h" #include "selinux-util.h" #include "time-util.h" #include "util.h" #ifdef HAVE_SELINUX DEFINE_TRIVIAL_CLEANUP_FUNC(security_context_t, freecon); DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free); #define _cleanup_security_context_free_ _cleanup_(freeconp) #define _cleanup_context_free_ _cleanup_(context_freep) static int cached_use = -1; static struct selabel_handle *label_hnd = NULL; #define log_enforcing(...) log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, __VA_ARGS__) #endif bool mac_selinux_have(void) { #ifdef HAVE_SELINUX if (cached_use < 0) cached_use = is_selinux_enabled() > 0; return cached_use; #else return false; #endif } bool mac_selinux_use(void) { if (!mac_selinux_have()) return false; /* Never try to configure SELinux features if we aren't * root */ return getuid() == 0; } void mac_selinux_retest(void) { #ifdef HAVE_SELINUX cached_use = -1; #endif } int mac_selinux_init(const char *prefix) { int r = 0; #ifdef HAVE_SELINUX usec_t before_timestamp, after_timestamp; struct mallinfo before_mallinfo, after_mallinfo; if (!mac_selinux_use()) return 0; if (label_hnd) return 0; before_mallinfo = mallinfo(); before_timestamp = now(CLOCK_MONOTONIC); if (prefix) { struct selinux_opt options[] = { { .type = SELABEL_OPT_SUBSET, .value = prefix }, }; label_hnd = selabel_open(SELABEL_CTX_FILE, options, ELEMENTSOF(options)); } else label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0); if (!label_hnd) { log_enforcing("Failed to initialize SELinux context: %m"); r = security_getenforce() == 1 ? -errno : 0; } else { char timespan[FORMAT_TIMESPAN_MAX]; int l; after_timestamp = now(CLOCK_MONOTONIC); after_mallinfo = mallinfo(); l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0; log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.", format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0), (l+1023)/1024); } #endif return r; } void mac_selinux_finish(void) { #ifdef HAVE_SELINUX if (!label_hnd) return; selabel_close(label_hnd); label_hnd = NULL; #endif } int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) { #ifdef HAVE_SELINUX struct stat st; int r; assert(path); /* if mac_selinux_init() wasn't called before we are a NOOP */ if (!label_hnd) return 0; r = lstat(path, &st); if (r >= 0) { _cleanup_security_context_free_ security_context_t fcon = NULL; r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode); /* If there's no label to set, then exit without warning */ if (r < 0 && errno == ENOENT) return 0; if (r >= 0) { r = lsetfilecon(path, fcon); /* If the FS doesn't support labels, then exit without warning */ if (r < 0 && errno == EOPNOTSUPP) return 0; } } if (r < 0) { /* Ignore ENOENT in some cases */ if (ignore_enoent && errno == ENOENT) return 0; if (ignore_erofs && errno == EROFS) return 0; log_enforcing("Unable to fix SELinux security context of %s: %m", path); if (security_getenforce() == 1) return -errno; } #endif return 0; } int mac_selinux_apply(const char *path, const char *label) { #ifdef HAVE_SELINUX if (!mac_selinux_use()) return 0; assert(path); assert(label); if (setfilecon(path, (security_context_t) label) < 0) { log_enforcing("Failed to set SELinux security context %s on path %s: %m", label, path); if (security_getenforce() > 0) return -errno; } #endif return 0; } int mac_selinux_get_create_label_from_exe(const char *exe, char **label) { int r = -EOPNOTSUPP; #ifdef HAVE_SELINUX _cleanup_security_context_free_ security_context_t mycon = NULL, fcon = NULL; security_class_t sclass; assert(exe); assert(label); if (!mac_selinux_have()) return -EOPNOTSUPP; r = getcon_raw(&mycon); if (r < 0) return -errno; r = getfilecon_raw(exe, &fcon); if (r < 0) return -errno; sclass = string_to_security_class("process"); r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label); if (r < 0) return -errno; #endif return r; } int mac_selinux_get_our_label(char **label) { int r = -EOPNOTSUPP; assert(label); #ifdef HAVE_SELINUX if (!mac_selinux_have()) return -EOPNOTSUPP; r = getcon_raw(label); if (r < 0) return -errno; #endif return r; } int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) { int r = -EOPNOTSUPP; #ifdef HAVE_SELINUX _cleanup_security_context_free_ security_context_t mycon = NULL, peercon = NULL, fcon = NULL; _cleanup_context_free_ context_t pcon = NULL, bcon = NULL; security_class_t sclass; const char *range = NULL; assert(socket_fd >= 0); assert(exe); assert(label); if (!mac_selinux_have()) return -EOPNOTSUPP; r = getcon_raw(&mycon); if (r < 0) return -errno; r = getpeercon(socket_fd, &peercon); if (r < 0) return -errno; if (!exec_label) { /* If there is no context set for next exec let's use context of target executable */ r = getfilecon_raw(exe, &fcon); if (r < 0) return -errno; } bcon = context_new(mycon); if (!bcon) return -ENOMEM; pcon = context_new(peercon); if (!pcon) return -ENOMEM; range = context_range_get(pcon); if (!range) return -errno; r = context_range_set(bcon, range); if (r) return -errno; freecon(mycon); mycon = strdup(context_str(bcon)); if (!mycon) return -ENOMEM; sclass = string_to_security_class("process"); r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label); if (r < 0) return -errno; #endif return r; } char* mac_selinux_free(char *label) { #ifdef HAVE_SELINUX if (!label) return NULL; if (!mac_selinux_have()) return NULL; freecon((security_context_t) label); #endif return NULL; } int mac_selinux_create_file_prepare(const char *path, mode_t mode) { #ifdef HAVE_SELINUX _cleanup_security_context_free_ security_context_t filecon = NULL; int r; assert(path); if (!label_hnd) return 0; if (path_is_absolute(path)) r = selabel_lookup_raw(label_hnd, &filecon, path, mode); else { _cleanup_free_ char *newpath = NULL; r = path_make_absolute_cwd(path, &newpath); if (r < 0) return r; r = selabel_lookup_raw(label_hnd, &filecon, newpath, mode); } if (r < 0) { /* No context specified by the policy? Proceed without setting it. */ if (errno == ENOENT) return 0; log_enforcing("Failed to determine SELinux security context for %s: %m", path); } else { if (setfscreatecon(filecon) >= 0) return 0; /* Success! */ log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path); } if (security_getenforce() > 0) return -errno; #endif return 0; } void mac_selinux_create_file_clear(void) { #ifdef HAVE_SELINUX PROTECT_ERRNO; if (!mac_selinux_use()) return; setfscreatecon(NULL); #endif } int mac_selinux_create_socket_prepare(const char *label) { #ifdef HAVE_SELINUX if (!mac_selinux_use()) return 0; assert(label); if (setsockcreatecon((security_context_t) label) < 0) { log_enforcing("Failed to set SELinux security context %s for sockets: %m", label); if (security_getenforce() == 1) return -errno; } #endif return 0; } void mac_selinux_create_socket_clear(void) { #ifdef HAVE_SELINUX PROTECT_ERRNO; if (!mac_selinux_use()) return; setsockcreatecon(NULL); #endif } int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { /* Binds a socket and label its file system object according to the SELinux policy */ #ifdef HAVE_SELINUX _cleanup_security_context_free_ security_context_t fcon = NULL; const struct sockaddr_un *un; bool context_changed = false; char *path; int r; assert(fd >= 0); assert(addr); assert(addrlen >= sizeof(sa_family_t)); if (!label_hnd) goto skipped; /* Filter out non-local sockets */ if (addr->sa_family != AF_UNIX) goto skipped; /* Filter out anonymous sockets */ if (addrlen < offsetof(struct sockaddr_un, sun_path) + 1) goto skipped; /* Filter out abstract namespace sockets */ un = (const struct sockaddr_un*) addr; if (un->sun_path[0] == 0) goto skipped; path = strndupa(un->sun_path, addrlen - offsetof(struct sockaddr_un, sun_path)); if (path_is_absolute(path)) r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK); else { _cleanup_free_ char *newpath = NULL; r = path_make_absolute_cwd(path, &newpath); if (r < 0) return r; r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK); } if (r < 0) { /* No context specified by the policy? Proceed without setting it */ if (errno == ENOENT) goto skipped; log_enforcing("Failed to determine SELinux security context for %s: %m", path); if (security_getenforce() > 0) return -errno; } else { if (setfscreatecon(fcon) < 0) { log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path); if (security_getenforce() > 0) return -errno; } else context_changed = true; } r = bind(fd, addr, addrlen) < 0 ? -errno : 0; if (context_changed) setfscreatecon(NULL); return r; skipped: #endif if (bind(fd, addr, addrlen) < 0) return -errno; return 0; } systemd-229/src/basic/selinux-util.h000066400000000000000000000033071265713322000175470ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "macro.h" bool mac_selinux_use(void); bool mac_selinux_have(void); void mac_selinux_retest(void); int mac_selinux_init(const char *prefix); void mac_selinux_finish(void); int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs); int mac_selinux_apply(const char *path, const char *label); int mac_selinux_get_create_label_from_exe(const char *exe, char **label); int mac_selinux_get_our_label(char **label); int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label); char* mac_selinux_free(char *label); int mac_selinux_create_file_prepare(const char *path, mode_t mode); void mac_selinux_create_file_clear(void); int mac_selinux_create_socket_prepare(const char *label); void mac_selinux_create_socket_clear(void); int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen); DEFINE_TRIVIAL_CLEANUP_FUNC(char*, mac_selinux_free); systemd-229/src/basic/set.h000066400000000000000000000075261265713322000157070ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "hashmap.h" #include "macro.h" Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); #define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS) static inline Set *set_free(Set *s) { internal_hashmap_free(HASHMAP_BASE(s)); return NULL; } static inline Set *set_free_free(Set *s) { internal_hashmap_free_free(HASHMAP_BASE(s)); return NULL; } /* no set_free_free_free */ static inline Set *set_copy(Set *s) { return (Set*) internal_hashmap_copy(HASHMAP_BASE(s)); } int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); #define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) int set_put(Set *s, const void *key); /* no set_update */ /* no set_replace */ static inline void *set_get(Set *s, void *key) { return internal_hashmap_get(HASHMAP_BASE(s), key); } /* no set_get2 */ static inline bool set_contains(Set *s, const void *key) { return internal_hashmap_contains(HASHMAP_BASE(s), key); } static inline void *set_remove(Set *s, const void *key) { return internal_hashmap_remove(HASHMAP_BASE(s), key); } /* no set_remove2 */ /* no set_remove_value */ int set_remove_and_put(Set *s, const void *old_key, const void *new_key); /* no set_remove_and_replace */ int set_merge(Set *s, Set *other); static inline int set_reserve(Set *h, unsigned entries_add) { return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add); } static inline int set_move(Set *s, Set *other) { return internal_hashmap_move(HASHMAP_BASE(s), HASHMAP_BASE(other)); } static inline int set_move_one(Set *s, Set *other, const void *key) { return internal_hashmap_move_one(HASHMAP_BASE(s), HASHMAP_BASE(other), key); } static inline unsigned set_size(Set *s) { return internal_hashmap_size(HASHMAP_BASE(s)); } static inline bool set_isempty(Set *s) { return set_size(s) == 0; } static inline unsigned set_buckets(Set *s) { return internal_hashmap_buckets(HASHMAP_BASE(s)); } bool set_iterate(Set *s, Iterator *i, void **value); static inline void set_clear(Set *s) { internal_hashmap_clear(HASHMAP_BASE(s)); } static inline void set_clear_free(Set *s) { internal_hashmap_clear_free(HASHMAP_BASE(s)); } /* no set_clear_free_free */ static inline void *set_steal_first(Set *s) { return internal_hashmap_steal_first(HASHMAP_BASE(s)); } /* no set_steal_first_key */ /* no set_first_key */ static inline void *set_first(Set *s) { return internal_hashmap_first(HASHMAP_BASE(s)); } /* no set_next */ static inline char **set_get_strv(Set *s) { return internal_hashmap_get_strv(HASHMAP_BASE(s)); } int set_consume(Set *s, void *value); int set_put_strdup(Set *s, const char *p); int set_put_strdupv(Set *s, char **l); #define SET_FOREACH(e, s, i) \ for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); ) DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free); #define _cleanup_set_free_ _cleanup_(set_freep) #define _cleanup_set_free_free_ _cleanup_(set_free_freep) systemd-229/src/basic/sigbus.c000066400000000000000000000105201265713322000163670ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "macro.h" #include "sigbus.h" #include "util.h" #define SIGBUS_QUEUE_MAX 64 static struct sigaction old_sigaction; static unsigned n_installed = 0; /* We maintain a fixed size list of page addresses that triggered a SIGBUS. We access with list with atomic operations, so that we don't have to deal with locks between signal handler and main programs in possibly multiple threads. */ static void* volatile sigbus_queue[SIGBUS_QUEUE_MAX]; static volatile sig_atomic_t n_sigbus_queue = 0; static void sigbus_push(void *addr) { unsigned u; assert(addr); /* Find a free place, increase the number of entries and leave, if we can */ for (u = 0; u < SIGBUS_QUEUE_MAX; u++) if (__sync_bool_compare_and_swap(&sigbus_queue[u], NULL, addr)) { __sync_fetch_and_add(&n_sigbus_queue, 1); return; } /* If we can't, make sure the queue size is out of bounds, to * mark it as overflow */ for (;;) { unsigned c; __sync_synchronize(); c = n_sigbus_queue; if (c > SIGBUS_QUEUE_MAX) /* already overflow */ return; if (__sync_bool_compare_and_swap(&n_sigbus_queue, c, c + SIGBUS_QUEUE_MAX)) return; } } int sigbus_pop(void **ret) { assert(ret); for (;;) { unsigned u, c; __sync_synchronize(); c = n_sigbus_queue; if (_likely_(c == 0)) return 0; if (_unlikely_(c >= SIGBUS_QUEUE_MAX)) return -EOVERFLOW; for (u = 0; u < SIGBUS_QUEUE_MAX; u++) { void *addr; addr = sigbus_queue[u]; if (!addr) continue; if (__sync_bool_compare_and_swap(&sigbus_queue[u], addr, NULL)) { __sync_fetch_and_sub(&n_sigbus_queue, 1); *ret = addr; return 1; } } } } static void sigbus_handler(int sn, siginfo_t *si, void *data) { unsigned long ul; void *aligned; assert(sn == SIGBUS); assert(si); if (si->si_code != BUS_ADRERR || !si->si_addr) { assert_se(sigaction(SIGBUS, &old_sigaction, NULL) == 0); raise(SIGBUS); return; } ul = (unsigned long) si->si_addr; ul = ul / page_size(); ul = ul * page_size(); aligned = (void*) ul; /* Let's remember which address failed */ sigbus_push(aligned); /* Replace mapping with an anonymous page, so that the * execution can continue, however with a zeroed out page */ assert_se(mmap(aligned, page_size(), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) == aligned); } void sigbus_install(void) { struct sigaction sa = { .sa_sigaction = sigbus_handler, .sa_flags = SA_SIGINFO, }; n_installed++; if (n_installed == 1) assert_se(sigaction(SIGBUS, &sa, &old_sigaction) == 0); return; } void sigbus_reset(void) { if (n_installed <= 0) return; n_installed--; if (n_installed == 0) assert_se(sigaction(SIGBUS, &old_sigaction, NULL) == 0); return; } systemd-229/src/basic/sigbus.h000066400000000000000000000014561265713322000164040ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once void sigbus_install(void); void sigbus_reset(void); int sigbus_pop(void **ret); systemd-229/src/basic/signal-util.c000066400000000000000000000147511265713322000173350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "macro.h" #include "parse-util.h" #include "signal-util.h" #include "stdio-util.h" #include "string-table.h" #include "string-util.h" int reset_all_signal_handlers(void) { static const struct sigaction sa = { .sa_handler = SIG_DFL, .sa_flags = SA_RESTART, }; int sig, r = 0; for (sig = 1; sig < _NSIG; sig++) { /* These two cannot be caught... */ if (sig == SIGKILL || sig == SIGSTOP) continue; /* On Linux the first two RT signals are reserved by * glibc, and sigaction() will return EINVAL for them. */ if ((sigaction(sig, &sa, NULL) < 0)) if (errno != EINVAL && r >= 0) r = -errno; } return r; } int reset_signal_mask(void) { sigset_t ss; if (sigemptyset(&ss) < 0) return -errno; if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0) return -errno; return 0; } static int sigaction_many_ap(const struct sigaction *sa, int sig, va_list ap) { int r = 0; /* negative signal ends the list. 0 signal is skipped. */ if (sig < 0) return 0; if (sig > 0) { if (sigaction(sig, sa, NULL) < 0) r = -errno; } while ((sig = va_arg(ap, int)) >= 0) { if (sig == 0) continue; if (sigaction(sig, sa, NULL) < 0) { if (r >= 0) r = -errno; } } return r; } int sigaction_many(const struct sigaction *sa, ...) { va_list ap; int r; va_start(ap, sa); r = sigaction_many_ap(sa, 0, ap); va_end(ap); return r; } int ignore_signals(int sig, ...) { static const struct sigaction sa = { .sa_handler = SIG_IGN, .sa_flags = SA_RESTART, }; va_list ap; int r; va_start(ap, sig); r = sigaction_many_ap(&sa, sig, ap); va_end(ap); return r; } int default_signals(int sig, ...) { static const struct sigaction sa = { .sa_handler = SIG_DFL, .sa_flags = SA_RESTART, }; va_list ap; int r; va_start(ap, sig); r = sigaction_many_ap(&sa, sig, ap); va_end(ap); return r; } static int sigset_add_many_ap(sigset_t *ss, va_list ap) { int sig, r = 0; assert(ss); while ((sig = va_arg(ap, int)) >= 0) { if (sig == 0) continue; if (sigaddset(ss, sig) < 0) { if (r >= 0) r = -errno; } } return r; } int sigset_add_many(sigset_t *ss, ...) { va_list ap; int r; va_start(ap, ss); r = sigset_add_many_ap(ss, ap); va_end(ap); return r; } int sigprocmask_many(int how, sigset_t *old, ...) { va_list ap; sigset_t ss; int r; if (sigemptyset(&ss) < 0) return -errno; va_start(ap, old); r = sigset_add_many_ap(&ss, ap); va_end(ap); if (r < 0) return r; if (sigprocmask(how, &ss, old) < 0) return -errno; return 0; } static const char *const __signal_table[] = { [SIGHUP] = "HUP", [SIGINT] = "INT", [SIGQUIT] = "QUIT", [SIGILL] = "ILL", [SIGTRAP] = "TRAP", [SIGABRT] = "ABRT", [SIGBUS] = "BUS", [SIGFPE] = "FPE", [SIGKILL] = "KILL", [SIGUSR1] = "USR1", [SIGSEGV] = "SEGV", [SIGUSR2] = "USR2", [SIGPIPE] = "PIPE", [SIGALRM] = "ALRM", [SIGTERM] = "TERM", #ifdef SIGSTKFLT [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */ #endif [SIGCHLD] = "CHLD", [SIGCONT] = "CONT", [SIGSTOP] = "STOP", [SIGTSTP] = "TSTP", [SIGTTIN] = "TTIN", [SIGTTOU] = "TTOU", [SIGURG] = "URG", [SIGXCPU] = "XCPU", [SIGXFSZ] = "XFSZ", [SIGVTALRM] = "VTALRM", [SIGPROF] = "PROF", [SIGWINCH] = "WINCH", [SIGIO] = "IO", [SIGPWR] = "PWR", [SIGSYS] = "SYS" }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int); const char *signal_to_string(int signo) { static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1]; const char *name; name = __signal_to_string(signo); if (name) return name; if (signo >= SIGRTMIN && signo <= SIGRTMAX) xsprintf(buf, "RTMIN+%d", signo - SIGRTMIN); else xsprintf(buf, "%d", signo); return buf; } int signal_from_string(const char *s) { int signo; int offset = 0; unsigned u; signo = __signal_from_string(s); if (signo > 0) return signo; if (startswith(s, "RTMIN+")) { s += 6; offset = SIGRTMIN; } if (safe_atou(s, &u) >= 0) { signo = (int) u + offset; if (signo > 0 && signo < _NSIG) return signo; } return -EINVAL; } int signal_from_string_try_harder(const char *s) { int signo; assert(s); signo = signal_from_string(s); if (signo <= 0) if (startswith(s, "SIG")) return signal_from_string(s+3); return signo; } void nop_signal_handler(int sig) { /* nothing here */ } systemd-229/src/basic/signal-util.h000066400000000000000000000033241265713322000173340ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010-2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" int reset_all_signal_handlers(void); int reset_signal_mask(void); int ignore_signals(int sig, ...); int default_signals(int sig, ...); int sigaction_many(const struct sigaction *sa, ...); int sigset_add_many(sigset_t *ss, ...); int sigprocmask_many(int how, sigset_t *old, ...); const char *signal_to_string(int i) _const_; int signal_from_string(const char *s) _pure_; int signal_from_string_try_harder(const char *s); void nop_signal_handler(int sig); static inline void block_signals_reset(sigset_t *ss) { assert_se(sigprocmask(SIG_SETMASK, ss, NULL) >= 0); } #define BLOCK_SIGNALS(...) \ _cleanup_(block_signals_reset) sigset_t _saved_sigset = ({ \ sigset_t t; \ assert_se(sigprocmask_many(SIG_BLOCK, &t, __VA_ARGS__, -1) >= 0); \ t; \ }) systemd-229/src/basic/siphash24.c000066400000000000000000000156011265713322000167050ustar00rootroot00000000000000/* SipHash reference C implementation Written in 2012 by Jean-Philippe Aumasson Daniel J. Bernstein To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see . (Minimal changes made by Lennart Poettering, to make clean for inclusion in systemd) (Refactored by Tom Gundersen to split up in several functions and follow systemd coding style) */ #include "macro.h" #include "siphash24.h" #include "unaligned.h" static inline uint64_t rotate_left(uint64_t x, uint8_t b) { assert(b < 64); return (x << b) | (x >> (64 - b)); } static inline void sipround(struct siphash *state) { assert(state); state->v0 += state->v1; state->v1 = rotate_left(state->v1, 13); state->v1 ^= state->v0; state->v0 = rotate_left(state->v0, 32); state->v2 += state->v3; state->v3 = rotate_left(state->v3, 16); state->v3 ^= state->v2; state->v0 += state->v3; state->v3 = rotate_left(state->v3, 21); state->v3 ^= state->v0; state->v2 += state->v1; state->v1 = rotate_left(state->v1, 17); state->v1 ^= state->v2; state->v2 = rotate_left(state->v2, 32); } void siphash24_init(struct siphash *state, const uint8_t k[16]) { uint64_t k0, k1; assert(state); assert(k); k0 = unaligned_read_le64(k); k1 = unaligned_read_le64(k + 8); *state = (struct siphash) { /* "somepseudorandomlygeneratedbytes" */ .v0 = 0x736f6d6570736575ULL ^ k0, .v1 = 0x646f72616e646f6dULL ^ k1, .v2 = 0x6c7967656e657261ULL ^ k0, .v3 = 0x7465646279746573ULL ^ k1, .padding = 0, .inlen = 0, }; } void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) { const uint8_t *in = _in; const uint8_t *end = in + inlen; size_t left = state->inlen & 7; uint64_t m; assert(in); assert(state); /* Update total length */ state->inlen += inlen; /* If padding exists, fill it out */ if (left > 0) { for ( ; in < end && left < 8; in ++, left ++) state->padding |= ((uint64_t) *in) << (left * 8); if (in == end && left < 8) /* We did not have enough input to fill out the padding completely */ return; #ifdef DEBUG printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding); #endif state->v3 ^= state->padding; sipround(state); sipround(state); state->v0 ^= state->padding; state->padding = 0; } end -= (state->inlen % sizeof(uint64_t)); for ( ; in < end; in += 8) { m = unaligned_read_le64(in); #ifdef DEBUG printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m); #endif state->v3 ^= m; sipround(state); sipround(state); state->v0 ^= m; } left = state->inlen & 7; switch (left) { case 7: state->padding |= ((uint64_t) in[6]) << 48; case 6: state->padding |= ((uint64_t) in[5]) << 40; case 5: state->padding |= ((uint64_t) in[4]) << 32; case 4: state->padding |= ((uint64_t) in[3]) << 24; case 3: state->padding |= ((uint64_t) in[2]) << 16; case 2: state->padding |= ((uint64_t) in[1]) << 8; case 1: state->padding |= ((uint64_t) in[0]); case 0: break; } } uint64_t siphash24_finalize(struct siphash *state) { uint64_t b; assert(state); b = state->padding | (((uint64_t) state->inlen) << 56); #ifdef DEBUG printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding); #endif state->v3 ^= b; sipround(state); sipround(state); state->v0 ^= b; #ifdef DEBUG printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); #endif state->v2 ^= 0xff; sipround(state); sipround(state); sipround(state); sipround(state); return state->v0 ^ state->v1 ^ state->v2 ^ state->v3; } uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) { struct siphash state; assert(in); assert(k); siphash24_init(&state, k); siphash24_compress(in, inlen, &state); return siphash24_finalize(&state); } systemd-229/src/basic/siphash24.h000066400000000000000000000011631265713322000167100ustar00rootroot00000000000000#pragma once #include #include #include #include struct siphash { uint64_t v0; uint64_t v1; uint64_t v2; uint64_t v3; uint64_t padding; size_t inlen; }; void siphash24_init(struct siphash *state, const uint8_t k[16]); void siphash24_compress(const void *in, size_t inlen, struct siphash *state); #define siphash24_compress_byte(byte, state) siphash24_compress((const uint8_t[]) { (byte) }, 1, (state)) uint64_t siphash24_finalize(struct siphash *state); uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]); systemd-229/src/basic/smack-util.c000066400000000000000000000143061265713322000171520ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Intel Corporation Author: Auke Kok systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "fileio.h" #include "log.h" #include "macro.h" #include "path-util.h" #include "process-util.h" #include "smack-util.h" #include "string-table.h" #include "xattr-util.h" #ifdef HAVE_SMACK bool mac_smack_use(void) { static int cached_use = -1; if (cached_use < 0) cached_use = access("/sys/fs/smackfs/", F_OK) >= 0; return cached_use; } static const char* const smack_attr_table[_SMACK_ATTR_MAX] = { [SMACK_ATTR_ACCESS] = "security.SMACK64", [SMACK_ATTR_EXEC] = "security.SMACK64EXEC", [SMACK_ATTR_MMAP] = "security.SMACK64MMAP", [SMACK_ATTR_TRANSMUTE] = "security.SMACK64TRANSMUTE", [SMACK_ATTR_IPIN] = "security.SMACK64IPIN", [SMACK_ATTR_IPOUT] = "security.SMACK64IPOUT", }; DEFINE_STRING_TABLE_LOOKUP(smack_attr, SmackAttr); int mac_smack_read(const char *path, SmackAttr attr, char **label) { assert(path); assert(attr >= 0 && attr < _SMACK_ATTR_MAX); assert(label); if (!mac_smack_use()) return 0; return getxattr_malloc(path, smack_attr_to_string(attr), label, true); } int mac_smack_read_fd(int fd, SmackAttr attr, char **label) { assert(fd >= 0); assert(attr >= 0 && attr < _SMACK_ATTR_MAX); assert(label); if (!mac_smack_use()) return 0; return fgetxattr_malloc(fd, smack_attr_to_string(attr), label); } int mac_smack_apply(const char *path, SmackAttr attr, const char *label) { int r; assert(path); assert(attr >= 0 && attr < _SMACK_ATTR_MAX); if (!mac_smack_use()) return 0; if (label) r = lsetxattr(path, smack_attr_to_string(attr), label, strlen(label), 0); else r = lremovexattr(path, smack_attr_to_string(attr)); if (r < 0) return -errno; return 0; } int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) { int r; assert(fd >= 0); assert(attr >= 0 && attr < _SMACK_ATTR_MAX); if (!mac_smack_use()) return 0; if (label) r = fsetxattr(fd, smack_attr_to_string(attr), label, strlen(label), 0); else r = fremovexattr(fd, smack_attr_to_string(attr)); if (r < 0) return -errno; return 0; } int mac_smack_apply_pid(pid_t pid, const char *label) { const char *p; int r = 0; assert(label); if (!mac_smack_use()) return 0; p = procfs_file_alloca(pid, "attr/current"); r = write_string_file(p, label, 0); if (r < 0) return r; return r; } int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) { struct stat st; int r = 0; assert(path); if (!mac_smack_use()) return 0; /* * Path must be in /dev and must exist */ if (!path_startswith(path, "/dev")) return 0; r = lstat(path, &st); if (r >= 0) { const char *label; /* * Label directories and character devices "*". * Label symlinks "_". * Don't change anything else. */ if (S_ISDIR(st.st_mode)) label = SMACK_STAR_LABEL; else if (S_ISLNK(st.st_mode)) label = SMACK_FLOOR_LABEL; else if (S_ISCHR(st.st_mode)) label = SMACK_STAR_LABEL; else return 0; r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0); /* If the FS doesn't support labels, then exit without warning */ if (r < 0 && errno == EOPNOTSUPP) return 0; } if (r < 0) { /* Ignore ENOENT in some cases */ if (ignore_enoent && errno == ENOENT) return 0; if (ignore_erofs && errno == EROFS) return 0; r = log_debug_errno(errno, "Unable to fix SMACK label of %s: %m", path); } return r; } int mac_smack_copy(const char *dest, const char *src) { int r = 0; _cleanup_free_ char *label = NULL; assert(dest); assert(src); r = mac_smack_read(src, SMACK_ATTR_ACCESS, &label); if (r < 0) return r; r = mac_smack_apply(dest, SMACK_ATTR_ACCESS, label); if (r < 0) return r; return r; } #else bool mac_smack_use(void) { return false; } int mac_smack_read(const char *path, SmackAttr attr, char **label) { return -EOPNOTSUPP; } int mac_smack_read_fd(int fd, SmackAttr attr, char **label) { return -EOPNOTSUPP; } int mac_smack_apply(const char *path, SmackAttr attr, const char *label) { return 0; } int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) { return 0; } int mac_smack_apply_pid(pid_t pid, const char *label) { return 0; } int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) { return 0; } int mac_smack_copy(const char *dest, const char *src) { return 0; } #endif systemd-229/src/basic/smack-util.h000066400000000000000000000033641265713322000171610ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Intel Corporation Author: Auke Kok systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "macro.h" #define SMACK_FLOOR_LABEL "_" #define SMACK_STAR_LABEL "*" typedef enum SmackAttr { SMACK_ATTR_ACCESS = 0, SMACK_ATTR_EXEC = 1, SMACK_ATTR_MMAP = 2, SMACK_ATTR_TRANSMUTE = 3, SMACK_ATTR_IPIN = 4, SMACK_ATTR_IPOUT = 5, _SMACK_ATTR_MAX, _SMACK_ATTR_INVALID = -1, } SmackAttr; bool mac_smack_use(void); int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs); const char* smack_attr_to_string(SmackAttr i) _const_; SmackAttr smack_attr_from_string(const char *s) _pure_; int mac_smack_read(const char *path, SmackAttr attr, char **label); int mac_smack_read_fd(int fd, SmackAttr attr, char **label); int mac_smack_apply(const char *path, SmackAttr attr, const char *label); int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label); int mac_smack_apply_pid(pid_t pid, const char *label); int mac_smack_copy(const char *dest, const char *src); systemd-229/src/basic/socket-label.c000066400000000000000000000130331265713322000174420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "log.h" #include "macro.h" #include "missing.h" #include "mkdir.h" #include "selinux-util.h" #include "socket-util.h" int socket_address_listen( const SocketAddress *a, int flags, int backlog, SocketAddressBindIPv6Only only, const char *bind_to_device, bool reuse_port, bool free_bind, bool transparent, mode_t directory_mode, mode_t socket_mode, const char *label) { _cleanup_close_ int fd = -1; int r, one; assert(a); r = socket_address_verify(a); if (r < 0) return r; if (socket_address_family(a) == AF_INET6 && !socket_ipv6_is_supported()) return -EAFNOSUPPORT; if (label) { r = mac_selinux_create_socket_prepare(label); if (r < 0) return r; } fd = socket(socket_address_family(a), a->type | flags, a->protocol); r = fd < 0 ? -errno : 0; if (label) mac_selinux_create_socket_clear(); if (r < 0) return r; if (socket_address_family(a) == AF_INET6 && only != SOCKET_ADDRESS_DEFAULT) { int flag = only == SOCKET_ADDRESS_IPV6_ONLY; if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)) < 0) return -errno; } if (socket_address_family(a) == AF_INET || socket_address_family(a) == AF_INET6) { if (bind_to_device) if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, bind_to_device, strlen(bind_to_device)+1) < 0) return -errno; if (reuse_port) { one = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0) log_warning_errno(errno, "SO_REUSEPORT failed: %m"); } if (free_bind) { one = 1; if (setsockopt(fd, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0) log_warning_errno(errno, "IP_FREEBIND failed: %m"); } if (transparent) { one = 1; if (setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &one, sizeof(one)) < 0) log_warning_errno(errno, "IP_TRANSPARENT failed: %m"); } } one = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) return -errno; if (socket_address_family(a) == AF_UNIX && a->sockaddr.un.sun_path[0] != 0) { mode_t old_mask; /* Create parents */ mkdir_parents_label(a->sockaddr.un.sun_path, directory_mode); /* Enforce the right access mode for the socket */ old_mask = umask(~ socket_mode); r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size); if (r < 0 && errno == EADDRINUSE) { /* Unlink and try again */ unlink(a->sockaddr.un.sun_path); r = bind(fd, &a->sockaddr.sa, a->size); } umask(old_mask); } else r = bind(fd, &a->sockaddr.sa, a->size); if (r < 0) return -errno; if (socket_address_can_accept(a)) if (listen(fd, backlog) < 0) return -errno; r = fd; fd = -1; return r; } int make_socket_fd(int log_level, const char* address, int type, int flags) { SocketAddress a; int fd, r; r = socket_address_parse(&a, address); if (r < 0) return log_error_errno(r, "Failed to parse socket address \"%s\": %m", address); a.type = type; fd = socket_address_listen(&a, type | flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT, NULL, false, false, false, 0755, 0644, NULL); if (fd < 0 || log_get_max_level() >= log_level) { _cleanup_free_ char *p = NULL; r = socket_address_print(&a, &p); if (r < 0) return log_error_errno(r, "socket_address_print(): %m"); if (fd < 0) log_error_errno(fd, "Failed to listen on %s: %m", p); else log_full(log_level, "Listening on %s", p); } return fd; } systemd-229/src/basic/socket-util.c000066400000000000000000000677341265713322000173610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "log.h" #include "macro.h" #include "missing.h" #include "parse-util.h" #include "path-util.h" #include "socket-util.h" #include "string-table.h" #include "string-util.h" #include "user-util.h" #include "util.h" int socket_address_parse(SocketAddress *a, const char *s) { char *e, *n; unsigned u; int r; assert(a); assert(s); zero(*a); a->type = SOCK_STREAM; if (*s == '[') { /* IPv6 in [x:.....:z]:p notation */ e = strchr(s+1, ']'); if (!e) return -EINVAL; n = strndupa(s+1, e-s-1); errno = 0; if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0) return errno > 0 ? -errno : -EINVAL; e++; if (*e != ':') return -EINVAL; e++; r = safe_atou(e, &u); if (r < 0) return r; if (u <= 0 || u > 0xFFFF) return -EINVAL; a->sockaddr.in6.sin6_family = AF_INET6; a->sockaddr.in6.sin6_port = htons((uint16_t) u); a->size = sizeof(struct sockaddr_in6); } else if (*s == '/') { /* AF_UNIX socket */ size_t l; l = strlen(s); if (l >= sizeof(a->sockaddr.un.sun_path)) return -EINVAL; a->sockaddr.un.sun_family = AF_UNIX; memcpy(a->sockaddr.un.sun_path, s, l); a->size = offsetof(struct sockaddr_un, sun_path) + l + 1; } else if (*s == '@') { /* Abstract AF_UNIX socket */ size_t l; l = strlen(s+1); if (l >= sizeof(a->sockaddr.un.sun_path) - 1) return -EINVAL; a->sockaddr.un.sun_family = AF_UNIX; memcpy(a->sockaddr.un.sun_path+1, s+1, l); a->size = offsetof(struct sockaddr_un, sun_path) + 1 + l; } else { e = strchr(s, ':'); if (e) { r = safe_atou(e+1, &u); if (r < 0) return r; if (u <= 0 || u > 0xFFFF) return -EINVAL; n = strndupa(s, e-s); /* IPv4 in w.x.y.z:p notation? */ r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr); if (r < 0) return -errno; if (r > 0) { /* Gotcha, it's a traditional IPv4 address */ a->sockaddr.in.sin_family = AF_INET; a->sockaddr.in.sin_port = htons((uint16_t) u); a->size = sizeof(struct sockaddr_in); } else { unsigned idx; if (strlen(n) > IF_NAMESIZE-1) return -EINVAL; /* Uh, our last resort, an interface name */ idx = if_nametoindex(n); if (idx == 0) return -EINVAL; a->sockaddr.in6.sin6_family = AF_INET6; a->sockaddr.in6.sin6_port = htons((uint16_t) u); a->sockaddr.in6.sin6_scope_id = idx; a->sockaddr.in6.sin6_addr = in6addr_any; a->size = sizeof(struct sockaddr_in6); } } else { /* Just a port */ r = safe_atou(s, &u); if (r < 0) return r; if (u <= 0 || u > 0xFFFF) return -EINVAL; if (socket_ipv6_is_supported()) { a->sockaddr.in6.sin6_family = AF_INET6; a->sockaddr.in6.sin6_port = htons((uint16_t) u); a->sockaddr.in6.sin6_addr = in6addr_any; a->size = sizeof(struct sockaddr_in6); } else { a->sockaddr.in.sin_family = AF_INET; a->sockaddr.in.sin_port = htons((uint16_t) u); a->sockaddr.in.sin_addr.s_addr = INADDR_ANY; a->size = sizeof(struct sockaddr_in); } } } return 0; } int socket_address_parse_and_warn(SocketAddress *a, const char *s) { SocketAddress b; int r; /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */ r = socket_address_parse(&b, s); if (r < 0) return r; if (!socket_ipv6_is_supported() && b.sockaddr.sa.sa_family == AF_INET6) { log_warning("Binding to IPv6 address not available since kernel does not support IPv6."); return -EAFNOSUPPORT; } *a = b; return 0; } int socket_address_parse_netlink(SocketAddress *a, const char *s) { int family; unsigned group = 0; _cleanup_free_ char *sfamily = NULL; assert(a); assert(s); zero(*a); a->type = SOCK_RAW; errno = 0; if (sscanf(s, "%ms %u", &sfamily, &group) < 1) return errno > 0 ? -errno : -EINVAL; family = netlink_family_from_string(sfamily); if (family < 0) return -EINVAL; a->sockaddr.nl.nl_family = AF_NETLINK; a->sockaddr.nl.nl_groups = group; a->type = SOCK_RAW; a->size = sizeof(struct sockaddr_nl); a->protocol = family; return 0; } int socket_address_verify(const SocketAddress *a) { assert(a); switch (socket_address_family(a)) { case AF_INET: if (a->size != sizeof(struct sockaddr_in)) return -EINVAL; if (a->sockaddr.in.sin_port == 0) return -EINVAL; if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM) return -EINVAL; return 0; case AF_INET6: if (a->size != sizeof(struct sockaddr_in6)) return -EINVAL; if (a->sockaddr.in6.sin6_port == 0) return -EINVAL; if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM) return -EINVAL; return 0; case AF_UNIX: if (a->size < offsetof(struct sockaddr_un, sun_path)) return -EINVAL; if (a->size > offsetof(struct sockaddr_un, sun_path)) { if (a->sockaddr.un.sun_path[0] != 0) { char *e; /* path */ e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path)); if (!e) return -EINVAL; if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1) return -EINVAL; } } if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM && a->type != SOCK_SEQPACKET) return -EINVAL; return 0; case AF_NETLINK: if (a->size != sizeof(struct sockaddr_nl)) return -EINVAL; if (a->type != SOCK_RAW && a->type != SOCK_DGRAM) return -EINVAL; return 0; default: return -EAFNOSUPPORT; } } int socket_address_print(const SocketAddress *a, char **ret) { int r; assert(a); assert(ret); r = socket_address_verify(a); if (r < 0) return r; if (socket_address_family(a) == AF_NETLINK) { _cleanup_free_ char *sfamily = NULL; r = netlink_family_to_string_alloc(a->protocol, &sfamily); if (r < 0) return r; r = asprintf(ret, "%s %u", sfamily, a->sockaddr.nl.nl_groups); if (r < 0) return -ENOMEM; return 0; } return sockaddr_pretty(&a->sockaddr.sa, a->size, false, true, ret); } bool socket_address_can_accept(const SocketAddress *a) { assert(a); return a->type == SOCK_STREAM || a->type == SOCK_SEQPACKET; } bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) { assert(a); assert(b); /* Invalid addresses are unequal to all */ if (socket_address_verify(a) < 0 || socket_address_verify(b) < 0) return false; if (a->type != b->type) return false; if (socket_address_family(a) != socket_address_family(b)) return false; switch (socket_address_family(a)) { case AF_INET: if (a->sockaddr.in.sin_addr.s_addr != b->sockaddr.in.sin_addr.s_addr) return false; if (a->sockaddr.in.sin_port != b->sockaddr.in.sin_port) return false; break; case AF_INET6: if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0) return false; if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port) return false; break; case AF_UNIX: if (a->size <= offsetof(struct sockaddr_un, sun_path) || b->size <= offsetof(struct sockaddr_un, sun_path)) return false; if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0)) return false; if (a->sockaddr.un.sun_path[0]) { if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path)) return false; } else { if (a->size != b->size) return false; if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0) return false; } break; case AF_NETLINK: if (a->protocol != b->protocol) return false; if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups) return false; break; default: /* Cannot compare, so we assume the addresses are different */ return false; } return true; } bool socket_address_is(const SocketAddress *a, const char *s, int type) { struct SocketAddress b; assert(a); assert(s); if (socket_address_parse(&b, s) < 0) return false; b.type = type; return socket_address_equal(a, &b); } bool socket_address_is_netlink(const SocketAddress *a, const char *s) { struct SocketAddress b; assert(a); assert(s); if (socket_address_parse_netlink(&b, s) < 0) return false; return socket_address_equal(a, &b); } const char* socket_address_get_path(const SocketAddress *a) { assert(a); if (socket_address_family(a) != AF_UNIX) return NULL; if (a->sockaddr.un.sun_path[0] == 0) return NULL; return a->sockaddr.un.sun_path; } bool socket_ipv6_is_supported(void) { if (access("/proc/net/sockstat6", F_OK) != 0) return false; return true; } bool socket_address_matches_fd(const SocketAddress *a, int fd) { SocketAddress b; socklen_t solen; assert(a); assert(fd >= 0); b.size = sizeof(b.sockaddr); if (getsockname(fd, &b.sockaddr.sa, &b.size) < 0) return false; if (b.sockaddr.sa.sa_family != a->sockaddr.sa.sa_family) return false; solen = sizeof(b.type); if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &b.type, &solen) < 0) return false; if (b.type != a->type) return false; if (a->protocol != 0) { solen = sizeof(b.protocol); if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &b.protocol, &solen) < 0) return false; if (b.protocol != a->protocol) return false; } return socket_address_equal(a, &b); } int sockaddr_port(const struct sockaddr *_sa) { union sockaddr_union *sa = (union sockaddr_union*) _sa; assert(sa); if (!IN_SET(sa->sa.sa_family, AF_INET, AF_INET6)) return -EAFNOSUPPORT; return ntohs(sa->sa.sa_family == AF_INET6 ? sa->in6.sin6_port : sa->in.sin_port); } int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) { union sockaddr_union *sa = (union sockaddr_union*) _sa; char *p; int r; assert(sa); assert(salen >= sizeof(sa->sa.sa_family)); switch (sa->sa.sa_family) { case AF_INET: { uint32_t a; a = ntohl(sa->in.sin_addr.s_addr); if (include_port) r = asprintf(&p, "%u.%u.%u.%u:%u", a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF, ntohs(sa->in.sin_port)); else r = asprintf(&p, "%u.%u.%u.%u", a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF); if (r < 0) return -ENOMEM; break; } case AF_INET6: { static const unsigned char ipv4_prefix[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF }; if (translate_ipv6 && memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) { const uint8_t *a = sa->in6.sin6_addr.s6_addr+12; if (include_port) r = asprintf(&p, "%u.%u.%u.%u:%u", a[0], a[1], a[2], a[3], ntohs(sa->in6.sin6_port)); else r = asprintf(&p, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]); if (r < 0) return -ENOMEM; } else { char a[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a)); if (include_port) { r = asprintf(&p, "[%s]:%u", a, ntohs(sa->in6.sin6_port)); if (r < 0) return -ENOMEM; } else { p = strdup(a); if (!p) return -ENOMEM; } } break; } case AF_UNIX: if (salen <= offsetof(struct sockaddr_un, sun_path)) { p = strdup(""); if (!p) return -ENOMEM; } else if (sa->un.sun_path[0] == 0) { /* abstract */ /* FIXME: We assume we can print the * socket path here and that it hasn't * more than one NUL byte. That is * actually an invalid assumption */ p = new(char, sizeof(sa->un.sun_path)+1); if (!p) return -ENOMEM; p[0] = '@'; memcpy(p+1, sa->un.sun_path+1, sizeof(sa->un.sun_path)-1); p[sizeof(sa->un.sun_path)] = 0; } else { p = strndup(sa->un.sun_path, sizeof(sa->un.sun_path)); if (!p) return -ENOMEM; } break; default: return -EOPNOTSUPP; } *ret = p; return 0; } int getpeername_pretty(int fd, bool include_port, char **ret) { union sockaddr_union sa; socklen_t salen = sizeof(sa); int r; assert(fd >= 0); assert(ret); if (getpeername(fd, &sa.sa, &salen) < 0) return -errno; if (sa.sa.sa_family == AF_UNIX) { struct ucred ucred = {}; /* UNIX connection sockets are anonymous, so let's use * PID/UID as pretty credentials instead */ r = getpeercred(fd, &ucred); if (r < 0) return r; if (asprintf(ret, "PID "PID_FMT"/UID "UID_FMT, ucred.pid, ucred.uid) < 0) return -ENOMEM; return 0; } /* For remote sockets we translate IPv6 addresses back to IPv4 * if applicable, since that's nicer. */ return sockaddr_pretty(&sa.sa, salen, true, include_port, ret); } int getsockname_pretty(int fd, char **ret) { union sockaddr_union sa; socklen_t salen = sizeof(sa); assert(fd >= 0); assert(ret); if (getsockname(fd, &sa.sa, &salen) < 0) return -errno; /* For local sockets we do not translate IPv6 addresses back * to IPv6 if applicable, since this is usually used for * listening sockets where the difference between IPv4 and * IPv6 matters. */ return sockaddr_pretty(&sa.sa, salen, false, true, ret); } int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) { int r; char host[NI_MAXHOST], *ret; assert(_ret); r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0, NI_IDN|NI_IDN_USE_STD3_ASCII_RULES); if (r != 0) { int saved_errno = errno; r = sockaddr_pretty(&sa->sa, salen, true, true, &ret); if (r < 0) return r; log_debug_errno(saved_errno, "getnameinfo(%s) failed: %m", ret); } else { ret = strdup(host); if (!ret) return -ENOMEM; } *_ret = ret; return 0; } int getnameinfo_pretty(int fd, char **ret) { union sockaddr_union sa; socklen_t salen = sizeof(sa); assert(fd >= 0); assert(ret); if (getsockname(fd, &sa.sa, &salen) < 0) return -errno; return socknameinfo_pretty(&sa, salen, ret); } int socket_address_unlink(SocketAddress *a) { assert(a); if (socket_address_family(a) != AF_UNIX) return 0; if (a->sockaddr.un.sun_path[0] == 0) return 0; if (unlink(a->sockaddr.un.sun_path) < 0) return -errno; return 1; } static const char* const netlink_family_table[] = { [NETLINK_ROUTE] = "route", [NETLINK_FIREWALL] = "firewall", [NETLINK_INET_DIAG] = "inet-diag", [NETLINK_NFLOG] = "nflog", [NETLINK_XFRM] = "xfrm", [NETLINK_SELINUX] = "selinux", [NETLINK_ISCSI] = "iscsi", [NETLINK_AUDIT] = "audit", [NETLINK_FIB_LOOKUP] = "fib-lookup", [NETLINK_CONNECTOR] = "connector", [NETLINK_NETFILTER] = "netfilter", [NETLINK_IP6_FW] = "ip6-fw", [NETLINK_DNRTMSG] = "dnrtmsg", [NETLINK_KOBJECT_UEVENT] = "kobject-uevent", [NETLINK_GENERIC] = "generic", [NETLINK_SCSITRANSPORT] = "scsitransport", [NETLINK_ECRYPTFS] = "ecryptfs" }; DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX); static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = { [SOCKET_ADDRESS_DEFAULT] = "default", [SOCKET_ADDRESS_BOTH] = "both", [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only" }; DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only); bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) { assert(a); assert(b); if (a->sa.sa_family != b->sa.sa_family) return false; if (a->sa.sa_family == AF_INET) return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr; if (a->sa.sa_family == AF_INET6) return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0; return false; } int fd_inc_sndbuf(int fd, size_t n) { int r, value; socklen_t l = sizeof(value); r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) return 0; /* If we have the privileges we will ignore the kernel limit. */ value = (int) n; if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0) if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0) return -errno; return 1; } int fd_inc_rcvbuf(int fd, size_t n) { int r, value; socklen_t l = sizeof(value); r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) return 0; /* If we have the privileges we will ignore the kernel limit. */ value = (int) n; if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0) if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0) return -errno; return 1; } static const char* const ip_tos_table[] = { [IPTOS_LOWDELAY] = "low-delay", [IPTOS_THROUGHPUT] = "throughput", [IPTOS_RELIABILITY] = "reliability", [IPTOS_LOWCOST] = "low-cost", }; DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff); int getpeercred(int fd, struct ucred *ucred) { socklen_t n = sizeof(struct ucred); struct ucred u; int r; assert(fd >= 0); assert(ucred); r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n); if (r < 0) return -errno; if (n != sizeof(struct ucred)) return -EIO; /* Check if the data is actually useful and not suppressed due * to namespacing issues */ if (u.pid <= 0) return -ENODATA; if (u.uid == UID_INVALID) return -ENODATA; if (u.gid == GID_INVALID) return -ENODATA; *ucred = u; return 0; } int getpeersec(int fd, char **ret) { socklen_t n = 64; char *s; int r; assert(fd >= 0); assert(ret); s = new0(char, n); if (!s) return -ENOMEM; r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n); if (r < 0) { free(s); if (errno != ERANGE) return -errno; s = new0(char, n); if (!s) return -ENOMEM; r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n); if (r < 0) { free(s); return -errno; } } if (isempty(s)) { free(s); return -EOPNOTSUPP; } *ret = s; return 0; } int send_one_fd_sa( int transport_fd, int fd, const struct sockaddr *sa, socklen_t len, int flags) { union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(int))]; } control = {}; struct msghdr mh = { .msg_name = (struct sockaddr*) sa, .msg_namelen = len, .msg_control = &control, .msg_controllen = sizeof(control), }; struct cmsghdr *cmsg; assert(transport_fd >= 0); assert(fd >= 0); cmsg = CMSG_FIRSTHDR(&mh); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int)); memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); mh.msg_controllen = CMSG_SPACE(sizeof(int)); if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0) return -errno; return 0; } int receive_one_fd(int transport_fd, int flags) { union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(int))]; } control = {}; struct msghdr mh = { .msg_control = &control, .msg_controllen = sizeof(control), }; struct cmsghdr *cmsg, *found = NULL; assert(transport_fd >= 0); /* * Receive a single FD via @transport_fd. We don't care for * the transport-type. We retrieve a single FD at most, so for * packet-based transports, the caller must ensure to send * only a single FD per packet. This is best used in * combination with send_one_fd(). */ if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0) return -errno; CMSG_FOREACH(cmsg, &mh) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { assert(!found); found = cmsg; break; } } if (!found) { cmsg_close_all(&mh); return -EIO; } return *(int*) CMSG_DATA(found); } systemd-229/src/basic/socket-util.h000066400000000000000000000112471265713322000173520ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include "macro.h" #include "util.h" union sockaddr_union { struct sockaddr sa; struct sockaddr_in in; struct sockaddr_in6 in6; struct sockaddr_un un; struct sockaddr_nl nl; struct sockaddr_storage storage; struct sockaddr_ll ll; }; typedef struct SocketAddress { union sockaddr_union sockaddr; /* We store the size here explicitly due to the weird * sockaddr_un semantics for abstract sockets */ socklen_t size; /* Socket type, i.e. SOCK_STREAM, SOCK_DGRAM, ... */ int type; /* Socket protocol, IPPROTO_xxx, usually 0, except for netlink */ int protocol; } SocketAddress; typedef enum SocketAddressBindIPv6Only { SOCKET_ADDRESS_DEFAULT, SOCKET_ADDRESS_BOTH, SOCKET_ADDRESS_IPV6_ONLY, _SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX, _SOCKET_ADDRESS_BIND_IPV6_ONLY_INVALID = -1 } SocketAddressBindIPv6Only; #define socket_address_family(a) ((a)->sockaddr.sa.sa_family) int socket_address_parse(SocketAddress *a, const char *s); int socket_address_parse_and_warn(SocketAddress *a, const char *s); int socket_address_parse_netlink(SocketAddress *a, const char *s); int socket_address_print(const SocketAddress *a, char **p); int socket_address_verify(const SocketAddress *a) _pure_; int socket_address_unlink(SocketAddress *a); bool socket_address_can_accept(const SocketAddress *a) _pure_; int socket_address_listen( const SocketAddress *a, int flags, int backlog, SocketAddressBindIPv6Only only, const char *bind_to_device, bool reuse_port, bool free_bind, bool transparent, mode_t directory_mode, mode_t socket_mode, const char *label); int make_socket_fd(int log_level, const char* address, int type, int flags); bool socket_address_is(const SocketAddress *a, const char *s, int type); bool socket_address_is_netlink(const SocketAddress *a, const char *s); bool socket_address_matches_fd(const SocketAddress *a, int fd); bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) _pure_; const char* socket_address_get_path(const SocketAddress *a); bool socket_ipv6_is_supported(void); int sockaddr_port(const struct sockaddr *_sa) _pure_; int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret); int getpeername_pretty(int fd, bool include_port, char **ret); int getsockname_pretty(int fd, char **ret); int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret); int getnameinfo_pretty(int fd, char **ret); const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_; SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_; int netlink_family_to_string_alloc(int b, char **s); int netlink_family_from_string(const char *s) _pure_; bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b); int fd_inc_sndbuf(int fd, size_t n); int fd_inc_rcvbuf(int fd, size_t n); int ip_tos_to_string_alloc(int i, char **s); int ip_tos_from_string(const char *s); int getpeercred(int fd, struct ucred *ucred); int getpeersec(int fd, char **ret); int send_one_fd_sa(int transport_fd, int fd, const struct sockaddr *sa, socklen_t len, int flags); #define send_one_fd(transport_fd, fd, flags) send_one_fd_sa(transport_fd, fd, NULL, 0, flags) int receive_one_fd(int transport_fd, int flags); #define CMSG_FOREACH(cmsg, mh) \ for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg))) systemd-229/src/basic/sparse-endian.h000066400000000000000000000066321265713322000176420ustar00rootroot00000000000000/* Copyright (c) 2012 Josh Triplett * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #ifndef SPARSE_ENDIAN_H #define SPARSE_ENDIAN_H #include #include #include #ifdef __CHECKER__ #define __bitwise __attribute__((bitwise)) #define __force __attribute__((force)) #else #define __bitwise #define __force #endif typedef uint16_t __bitwise le16_t; typedef uint16_t __bitwise be16_t; typedef uint32_t __bitwise le32_t; typedef uint32_t __bitwise be32_t; typedef uint64_t __bitwise le64_t; typedef uint64_t __bitwise be64_t; #undef htobe16 #undef htole16 #undef be16toh #undef le16toh #undef htobe32 #undef htole32 #undef be32toh #undef le32toh #undef htobe64 #undef htole64 #undef be64toh #undef le64toh #if __BYTE_ORDER == __LITTLE_ENDIAN #define bswap_16_on_le(x) __bswap_16(x) #define bswap_32_on_le(x) __bswap_32(x) #define bswap_64_on_le(x) __bswap_64(x) #define bswap_16_on_be(x) (x) #define bswap_32_on_be(x) (x) #define bswap_64_on_be(x) (x) #elif __BYTE_ORDER == __BIG_ENDIAN #define bswap_16_on_le(x) (x) #define bswap_32_on_le(x) (x) #define bswap_64_on_le(x) (x) #define bswap_16_on_be(x) __bswap_16(x) #define bswap_32_on_be(x) __bswap_32(x) #define bswap_64_on_be(x) __bswap_64(x) #endif static inline le16_t htole16(uint16_t value) { return (le16_t __force) bswap_16_on_be(value); } static inline le32_t htole32(uint32_t value) { return (le32_t __force) bswap_32_on_be(value); } static inline le64_t htole64(uint64_t value) { return (le64_t __force) bswap_64_on_be(value); } static inline be16_t htobe16(uint16_t value) { return (be16_t __force) bswap_16_on_le(value); } static inline be32_t htobe32(uint32_t value) { return (be32_t __force) bswap_32_on_le(value); } static inline be64_t htobe64(uint64_t value) { return (be64_t __force) bswap_64_on_le(value); } static inline uint16_t le16toh(le16_t value) { return bswap_16_on_be((uint16_t __force)value); } static inline uint32_t le32toh(le32_t value) { return bswap_32_on_be((uint32_t __force)value); } static inline uint64_t le64toh(le64_t value) { return bswap_64_on_be((uint64_t __force)value); } static inline uint16_t be16toh(be16_t value) { return bswap_16_on_le((uint16_t __force)value); } static inline uint32_t be32toh(be32_t value) { return bswap_32_on_le((uint32_t __force)value); } static inline uint64_t be64toh(be64_t value) { return bswap_64_on_le((uint64_t __force)value); } #endif /* SPARSE_ENDIAN_H */ systemd-229/src/basic/special.h000066400000000000000000000113771265713322000165330ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #define SPECIAL_DEFAULT_TARGET "default.target" /* Shutdown targets */ #define SPECIAL_UMOUNT_TARGET "umount.target" /* This is not really intended to be started by directly. This is * mostly so that other targets (reboot/halt/poweroff) can depend on * it to bring all services down that want to be brought down on * system shutdown. */ #define SPECIAL_SHUTDOWN_TARGET "shutdown.target" #define SPECIAL_HALT_TARGET "halt.target" #define SPECIAL_POWEROFF_TARGET "poweroff.target" #define SPECIAL_REBOOT_TARGET "reboot.target" #define SPECIAL_KEXEC_TARGET "kexec.target" #define SPECIAL_EXIT_TARGET "exit.target" #define SPECIAL_SUSPEND_TARGET "suspend.target" #define SPECIAL_HIBERNATE_TARGET "hibernate.target" #define SPECIAL_HYBRID_SLEEP_TARGET "hybrid-sleep.target" /* Special boot targets */ #define SPECIAL_RESCUE_TARGET "rescue.target" #define SPECIAL_EMERGENCY_TARGET "emergency.target" #define SPECIAL_MULTI_USER_TARGET "multi-user.target" #define SPECIAL_GRAPHICAL_TARGET "graphical.target" /* Early boot targets */ #define SPECIAL_SYSINIT_TARGET "sysinit.target" #define SPECIAL_SOCKETS_TARGET "sockets.target" #define SPECIAL_BUSNAMES_TARGET "busnames.target" #define SPECIAL_TIMERS_TARGET "timers.target" #define SPECIAL_PATHS_TARGET "paths.target" #define SPECIAL_LOCAL_FS_TARGET "local-fs.target" #define SPECIAL_LOCAL_FS_PRE_TARGET "local-fs-pre.target" #define SPECIAL_INITRD_FS_TARGET "initrd-fs.target" #define SPECIAL_INITRD_ROOT_FS_TARGET "initrd-root-fs.target" #define SPECIAL_REMOTE_FS_TARGET "remote-fs.target" /* LSB's $remote_fs */ #define SPECIAL_REMOTE_FS_PRE_TARGET "remote-fs-pre.target" #define SPECIAL_SWAP_TARGET "swap.target" #define SPECIAL_NETWORK_ONLINE_TARGET "network-online.target" #define SPECIAL_TIME_SYNC_TARGET "time-sync.target" /* LSB's $time */ #define SPECIAL_BASIC_TARGET "basic.target" /* LSB compatibility */ #define SPECIAL_NETWORK_TARGET "network.target" /* LSB's $network */ #define SPECIAL_NSS_LOOKUP_TARGET "nss-lookup.target" /* LSB's $named */ #define SPECIAL_RPCBIND_TARGET "rpcbind.target" /* LSB's $portmap */ /* * Rules regarding adding further high level targets like the above: * * - Be conservative, only add more of these when we really need * them. We need strong usecases for further additions. * * - When there can be multiple implementations running side-by-side, * it needs to be a .target unit which can pull in all * implementations. * * - If something can be implemented with socket activation, and * without, it needs to be a .target unit, so that it can pull in * the appropriate unit. * * - Otherwise, it should be a .service unit. * * - In some cases it is OK to have both a .service and a .target * unit, i.e. if there can be multiple parallel implementations, but * only one is the "system" one. Example: syslog. * * Or to put this in other words: .service symlinks can be used to * arbitrate between multiple implementations if there can be only one * of a kind. .target units can be used to support multiple * implementations that can run side-by-side. */ /* Magic early boot services */ #define SPECIAL_FSCK_SERVICE "systemd-fsck@.service" #define SPECIAL_QUOTACHECK_SERVICE "systemd-quotacheck.service" #define SPECIAL_QUOTAON_SERVICE "quotaon.service" #define SPECIAL_REMOUNT_FS_SERVICE "systemd-remount-fs.service" /* Services systemd relies on */ #define SPECIAL_DBUS_SERVICE "dbus.service" #define SPECIAL_DBUS_SOCKET "dbus.socket" #define SPECIAL_JOURNALD_SOCKET "systemd-journald.socket" #define SPECIAL_JOURNALD_SERVICE "systemd-journald.service" /* Magic init signals */ #define SPECIAL_KBREQUEST_TARGET "kbrequest.target" #define SPECIAL_SIGPWR_TARGET "sigpwr.target" #define SPECIAL_CTRL_ALT_DEL_TARGET "ctrl-alt-del.target" /* Where we add all our system units, users and machines by default */ #define SPECIAL_SYSTEM_SLICE "system.slice" #define SPECIAL_USER_SLICE "user.slice" #define SPECIAL_MACHINE_SLICE "machine.slice" #define SPECIAL_ROOT_SLICE "-.slice" /* The scope unit systemd itself lives in. */ #define SPECIAL_INIT_SCOPE "init.scope" systemd-229/src/basic/stat-util.c000066400000000000000000000117441265713322000170320ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010-2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "dirent-util.h" #include "fd-util.h" #include "macro.h" #include "missing.h" #include "stat-util.h" #include "string-util.h" int is_symlink(const char *path) { struct stat info; assert(path); if (lstat(path, &info) < 0) return -errno; return !!S_ISLNK(info.st_mode); } int is_dir(const char* path, bool follow) { struct stat st; int r; assert(path); if (follow) r = stat(path, &st); else r = lstat(path, &st); if (r < 0) return -errno; return !!S_ISDIR(st.st_mode); } int is_device_node(const char *path) { struct stat info; assert(path); if (lstat(path, &info) < 0) return -errno; return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode)); } int dir_is_empty(const char *path) { _cleanup_closedir_ DIR *d; struct dirent *de; d = opendir(path); if (!d) return -errno; FOREACH_DIRENT(de, d, return -errno) return 0; return 1; } bool null_or_empty(struct stat *st) { assert(st); if (S_ISREG(st->st_mode) && st->st_size <= 0) return true; /* We don't want to hardcode the major/minor of /dev/null, * hence we do a simpler "is this a device node?" check. */ if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) return true; return false; } int null_or_empty_path(const char *fn) { struct stat st; assert(fn); if (stat(fn, &st) < 0) return -errno; return null_or_empty(&st); } int null_or_empty_fd(int fd) { struct stat st; assert(fd >= 0); if (fstat(fd, &st) < 0) return -errno; return null_or_empty(&st); } int path_is_read_only_fs(const char *path) { struct statvfs st; assert(path); if (statvfs(path, &st) < 0) return -errno; if (st.f_flag & ST_RDONLY) return true; /* On NFS, statvfs() might not reflect whether we can actually * write to the remote share. Let's try again with * access(W_OK) which is more reliable, at least sometimes. */ if (access(path, W_OK) < 0 && errno == EROFS) return true; return false; } int path_is_os_tree(const char *path) { char *p; int r; assert(path); /* We use /usr/lib/os-release as flag file if something is an OS */ p = strjoina(path, "/usr/lib/os-release"); r = access(p, F_OK); if (r >= 0) return 1; /* Also check for the old location in /etc, just in case. */ p = strjoina(path, "/etc/os-release"); r = access(p, F_OK); return r >= 0; } int files_same(const char *filea, const char *fileb) { struct stat a, b; assert(filea); assert(fileb); if (stat(filea, &a) < 0) return -errno; if (stat(fileb, &b) < 0) return -errno; return a.st_dev == b.st_dev && a.st_ino == b.st_ino; } bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) { assert(s); assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type)); return F_TYPE_EQUAL(s->f_type, magic_value); } int fd_check_fstype(int fd, statfs_f_type_t magic_value) { struct statfs s; if (fstatfs(fd, &s) < 0) return -errno; return is_fs_type(&s, magic_value); } int path_check_fstype(const char *path, statfs_f_type_t magic_value) { _cleanup_close_ int fd = -1; fd = open(path, O_RDONLY); if (fd < 0) return -errno; return fd_check_fstype(fd, magic_value); } bool is_temporary_fs(const struct statfs *s) { return is_fs_type(s, TMPFS_MAGIC) || is_fs_type(s, RAMFS_MAGIC); } int fd_is_temporary_fs(int fd) { struct statfs s; if (fstatfs(fd, &s) < 0) return -errno; return is_temporary_fs(&s); } systemd-229/src/basic/stat-util.h000066400000000000000000000042361265713322000170350ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010-2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "macro.h" int is_symlink(const char *path); int is_dir(const char *path, bool follow); int is_device_node(const char *path); int dir_is_empty(const char *path); static inline int dir_is_populated(const char *path) { int r; r = dir_is_empty(path); if (r < 0) return r; return !r; } bool null_or_empty(struct stat *st) _pure_; int null_or_empty_path(const char *fn); int null_or_empty_fd(int fd); int path_is_read_only_fs(const char *path); int path_is_os_tree(const char *path); int files_same(const char *filea, const char *fileb); /* The .f_type field of struct statfs is really weird defined on * different archs. Let's give its type a name. */ typedef typeof(((struct statfs*)NULL)->f_type) statfs_f_type_t; bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_; int fd_check_fstype(int fd, statfs_f_type_t magic_value); int path_check_fstype(const char *path, statfs_f_type_t magic_value); bool is_temporary_fs(const struct statfs *s) _pure_; int fd_is_temporary_fs(int fd); /* Because statfs.t_type can be int on some architectures, we have to cast * the const magic to the type, otherwise the compiler warns about * signed/unsigned comparison, because the magic can be 32 bit unsigned. */ #define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b) systemd-229/src/basic/stdio-util.h000066400000000000000000000102041265713322000171740ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "macro.h" #define xsprintf(buf, fmt, ...) \ assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), "xsprintf: " #buf "[] must be big enough") #define VA_FORMAT_ADVANCE(format, ap) \ do { \ int _argtypes[128]; \ size_t _i, _k; \ _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \ assert(_k < ELEMENTSOF(_argtypes)); \ for (_i = 0; _i < _k; _i++) { \ if (_argtypes[_i] & PA_FLAG_PTR) { \ (void) va_arg(ap, void*); \ continue; \ } \ \ switch (_argtypes[_i]) { \ case PA_INT: \ case PA_INT|PA_FLAG_SHORT: \ case PA_CHAR: \ (void) va_arg(ap, int); \ break; \ case PA_INT|PA_FLAG_LONG: \ (void) va_arg(ap, long int); \ break; \ case PA_INT|PA_FLAG_LONG_LONG: \ (void) va_arg(ap, long long int); \ break; \ case PA_WCHAR: \ (void) va_arg(ap, wchar_t); \ break; \ case PA_WSTRING: \ case PA_STRING: \ case PA_POINTER: \ (void) va_arg(ap, void*); \ break; \ case PA_FLOAT: \ case PA_DOUBLE: \ (void) va_arg(ap, double); \ break; \ case PA_DOUBLE|PA_FLAG_LONG_DOUBLE: \ (void) va_arg(ap, long double); \ break; \ default: \ assert_not_reached("Unknown format string argument."); \ } \ } \ } while(false) systemd-229/src/basic/strbuf.c000066400000000000000000000137461265713322000164150ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "strbuf.h" /* * Strbuf stores given strings in a single continuous allocated memory * area. Identical strings are de-duplicated and return the same offset * as the first string stored. If the tail of a string already exists * in the buffer, the tail is returned. * * A trie (http://en.wikipedia.org/wiki/Trie) is used to maintain the * information about the stored strings. * * Example of udev rules: * $ ./udevadm test . * ... * read rules file: /usr/lib/udev/rules.d/99-systemd.rules * rules contain 196608 bytes tokens (16384 * 12 bytes), 39742 bytes strings * 23939 strings (207859 bytes), 20404 de-duplicated (171653 bytes), 3536 trie nodes used * ... */ struct strbuf *strbuf_new(void) { struct strbuf *str; str = new0(struct strbuf, 1); if (!str) return NULL; str->buf = new0(char, 1); if (!str->buf) goto err; str->len = 1; str->root = new0(struct strbuf_node, 1); if (!str->root) goto err; str->nodes_count = 1; return str; err: free(str->buf); free(str->root); free(str); return NULL; } static void strbuf_node_cleanup(struct strbuf_node *node) { size_t i; for (i = 0; i < node->children_count; i++) strbuf_node_cleanup(node->children[i].child); free(node->children); free(node); } /* clean up trie data, leave only the string buffer */ void strbuf_complete(struct strbuf *str) { if (!str) return; if (str->root) strbuf_node_cleanup(str->root); str->root = NULL; } /* clean up everything */ void strbuf_cleanup(struct strbuf *str) { if (!str) return; if (str->root) strbuf_node_cleanup(str->root); free(str->buf); free(str); } static int strbuf_children_cmp(const struct strbuf_child_entry *n1, const struct strbuf_child_entry *n2) { return n1->c - n2->c; } static void bubbleinsert(struct strbuf_node *node, uint8_t c, struct strbuf_node *node_child) { struct strbuf_child_entry new = { .c = c, .child = node_child, }; int left = 0, right = node->children_count; while (right > left) { int middle = (right + left) / 2 ; if (strbuf_children_cmp(&node->children[middle], &new) <= 0) left = middle + 1; else right = middle; } memmove(node->children + left + 1, node->children + left, sizeof(struct strbuf_child_entry) * (node->children_count - left)); node->children[left] = new; node->children_count ++; } /* add string, return the index/offset into the buffer */ ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) { uint8_t c; struct strbuf_node *node; size_t depth; char *buf_new; struct strbuf_child_entry *child; struct strbuf_node *node_child; ssize_t off; if (!str->root) return -EINVAL; /* search string; start from last character to find possibly matching tails */ if (len == 0) return 0; str->in_count++; str->in_len += len; node = str->root; c = s[len-1]; for (depth = 0; depth <= len; depth++) { struct strbuf_child_entry search; /* match against current node */ off = node->value_off + node->value_len - len; if (depth == len || (node->value_len >= len && memcmp(str->buf + off, s, len) == 0)) { str->dedup_len += len; str->dedup_count++; return off; } /* lookup child node */ c = s[len - 1 - depth]; search.c = c; child = bsearch(&search, node->children, node->children_count, sizeof(struct strbuf_child_entry), (__compar_fn_t) strbuf_children_cmp); if (!child) break; node = child->child; } /* add new string */ buf_new = realloc(str->buf, str->len + len+1); if (!buf_new) return -ENOMEM; str->buf = buf_new; off = str->len; memcpy(str->buf + off, s, len); str->len += len; str->buf[str->len++] = '\0'; /* new node */ node_child = new0(struct strbuf_node, 1); if (!node_child) return -ENOMEM; node_child->value_off = off; node_child->value_len = len; /* extend array, add new entry, sort for bisection */ child = realloc(node->children, (node->children_count + 1) * sizeof(struct strbuf_child_entry)); if (!child) { free(node_child); return -ENOMEM; } str->nodes_count++; node->children = child; bubbleinsert(node, c, node_child); return off; } systemd-229/src/basic/strbuf.h000066400000000000000000000026641265713322000164170ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include struct strbuf { char *buf; size_t len; struct strbuf_node *root; size_t nodes_count; size_t in_count; size_t in_len; size_t dedup_len; size_t dedup_count; }; struct strbuf_node { size_t value_off; size_t value_len; struct strbuf_child_entry *children; uint8_t children_count; }; struct strbuf_child_entry { uint8_t c; struct strbuf_node *child; }; struct strbuf *strbuf_new(void); ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len); void strbuf_complete(struct strbuf *str); void strbuf_cleanup(struct strbuf *str); systemd-229/src/basic/string-table.c000066400000000000000000000020541265713322000174710ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "string-table.h" #include "string-util.h" ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) { size_t i; if (!key) return -1; for (i = 0; i < len; ++i) if (streq_ptr(table[i], key)) return (ssize_t) i; return -1; } systemd-229/src/basic/string-table.h000066400000000000000000000131401265713322000174740ustar00rootroot00000000000000 #pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "macro.h" #include "parse-util.h" #include "string-util.h" ssize_t string_table_lookup(const char * const *table, size_t len, const char *key); /* For basic lookup tables with strictly enumerated entries */ #define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ scope const char *name##_to_string(type i) { \ if (i < 0 || i >= (type) ELEMENTSOF(name##_table)) \ return NULL; \ return name##_table[i]; \ } #define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ scope type name##_from_string(const char *s) { \ return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \ } #define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \ scope type name##_from_string(const char *s) { \ int b; \ b = parse_boolean(s); \ if (b == 0) \ return (type) 0; \ else if (b > 0) \ return yes; \ return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \ } #define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \ _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ struct __useless_struct_to_allow_trailing_semicolon__ #define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \ _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \ struct __useless_struct_to_allow_trailing_semicolon__ #define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,) #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static) #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static) #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static) #define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,) /* For string conversions where numbers are also acceptable */ #define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \ int name##_to_string_alloc(type i, char **str) { \ char *s; \ if (i < 0 || i > max) \ return -ERANGE; \ if (i < (type) ELEMENTSOF(name##_table)) { \ s = strdup(name##_table[i]); \ if (!s) \ return -ENOMEM; \ } else { \ if (asprintf(&s, "%i", i) < 0) \ return -ENOMEM; \ } \ *str = s; \ return 0; \ } \ type name##_from_string(const char *s) { \ type i; \ unsigned u = 0; \ if (!s) \ return (type) -1; \ for (i = 0; i < (type) ELEMENTSOF(name##_table); i++) \ if (streq_ptr(name##_table[i], s)) \ return i; \ if (safe_atou(s, &u) >= 0 && u <= max) \ return (type) u; \ return (type) -1; \ } \ struct __useless_struct_to_allow_trailing_semicolon__ systemd-229/src/basic/string-util.c000066400000000000000000000467751265713322000174010ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "gunicode.h" #include "macro.h" #include "string-util.h" #include "utf8.h" #include "util.h" int strcmp_ptr(const char *a, const char *b) { /* Like strcmp(), but tries to make sense of NULL pointers */ if (a && b) return strcmp(a, b); if (!a && b) return -1; if (a && !b) return 1; return 0; } char* endswith(const char *s, const char *postfix) { size_t sl, pl; assert(s); assert(postfix); sl = strlen(s); pl = strlen(postfix); if (pl == 0) return (char*) s + sl; if (sl < pl) return NULL; if (memcmp(s + sl - pl, postfix, pl) != 0) return NULL; return (char*) s + sl - pl; } char* endswith_no_case(const char *s, const char *postfix) { size_t sl, pl; assert(s); assert(postfix); sl = strlen(s); pl = strlen(postfix); if (pl == 0) return (char*) s + sl; if (sl < pl) return NULL; if (strcasecmp(s + sl - pl, postfix) != 0) return NULL; return (char*) s + sl - pl; } char* first_word(const char *s, const char *word) { size_t sl, wl; const char *p; assert(s); assert(word); /* Checks if the string starts with the specified word, either * followed by NUL or by whitespace. Returns a pointer to the * NUL or the first character after the whitespace. */ sl = strlen(s); wl = strlen(word); if (sl < wl) return NULL; if (wl == 0) return (char*) s; if (memcmp(s, word, wl) != 0) return NULL; p = s + wl; if (*p == 0) return (char*) p; if (!strchr(WHITESPACE, *p)) return NULL; p += strspn(p, WHITESPACE); return (char*) p; } static size_t strcspn_escaped(const char *s, const char *reject) { bool escaped = false; int n; for (n=0; s[n]; n++) { if (escaped) escaped = false; else if (s[n] == '\\') escaped = true; else if (strchr(reject, s[n])) break; } /* if s ends in \, return index of previous char */ return n - escaped; } /* Split a string into words. */ const char* split(const char **state, size_t *l, const char *separator, bool quoted) { const char *current; current = *state; if (!*current) { assert(**state == '\0'); return NULL; } current += strspn(current, separator); if (!*current) { *state = current; return NULL; } if (quoted && strchr("\'\"", *current)) { char quotechars[2] = {*current, '\0'}; *l = strcspn_escaped(current + 1, quotechars); if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] || (current[*l + 2] && !strchr(separator, current[*l + 2]))) { /* right quote missing or garbage at the end */ *state = current; return NULL; } *state = current++ + *l + 2; } else if (quoted) { *l = strcspn_escaped(current, separator); if (current[*l] && !strchr(separator, current[*l])) { /* unfinished escape */ *state = current; return NULL; } *state = current + *l; } else { *l = strcspn(current, separator); *state = current + *l; } return current; } char *strnappend(const char *s, const char *suffix, size_t b) { size_t a; char *r; if (!s && !suffix) return strdup(""); if (!s) return strndup(suffix, b); if (!suffix) return strdup(s); assert(s); assert(suffix); a = strlen(s); if (b > ((size_t) -1) - a) return NULL; r = new(char, a+b+1); if (!r) return NULL; memcpy(r, s, a); memcpy(r+a, suffix, b); r[a+b] = 0; return r; } char *strappend(const char *s, const char *suffix) { return strnappend(s, suffix, suffix ? strlen(suffix) : 0); } char *strjoin(const char *x, ...) { va_list ap; size_t l; char *r, *p; va_start(ap, x); if (x) { l = strlen(x); for (;;) { const char *t; size_t n; t = va_arg(ap, const char *); if (!t) break; n = strlen(t); if (n > ((size_t) -1) - l) { va_end(ap); return NULL; } l += n; } } else l = 0; va_end(ap); r = new(char, l+1); if (!r) return NULL; if (x) { p = stpcpy(r, x); va_start(ap, x); for (;;) { const char *t; t = va_arg(ap, const char *); if (!t) break; p = stpcpy(p, t); } va_end(ap); } else r[0] = 0; return r; } char *strstrip(char *s) { char *e; /* Drops trailing whitespace. Modifies the string in * place. Returns pointer to first non-space character */ s += strspn(s, WHITESPACE); for (e = strchr(s, 0); e > s; e --) if (!strchr(WHITESPACE, e[-1])) break; *e = 0; return s; } char *delete_chars(char *s, const char *bad) { char *f, *t; /* Drops all whitespace, regardless where in the string */ for (f = s, t = s; *f; f++) { if (strchr(bad, *f)) continue; *(t++) = *f; } *t = 0; return s; } char *truncate_nl(char *s) { assert(s); s[strcspn(s, NEWLINE)] = 0; return s; } char ascii_tolower(char x) { if (x >= 'A' && x <= 'Z') return x - 'A' + 'a'; return x; } char *ascii_strlower(char *t) { char *p; assert(t); for (p = t; *p; p++) *p = ascii_tolower(*p); return t; } char *ascii_strlower_n(char *t, size_t n) { size_t i; if (n <= 0) return t; for (i = 0; i < n; i++) t[i] = ascii_tolower(t[i]); return t; } int ascii_strcasecmp_n(const char *a, const char *b, size_t n) { for (; n > 0; a++, b++, n--) { int x, y; x = (int) (uint8_t) ascii_tolower(*a); y = (int) (uint8_t) ascii_tolower(*b); if (x != y) return x - y; } return 0; } int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m) { int r; r = ascii_strcasecmp_n(a, b, MIN(n, m)); if (r != 0) return r; if (n < m) return -1; else if (n > m) return 1; else return 0; } bool chars_intersect(const char *a, const char *b) { const char *p; /* Returns true if any of the chars in a are in b. */ for (p = a; *p; p++) if (strchr(b, *p)) return true; return false; } bool string_has_cc(const char *p, const char *ok) { const char *t; assert(p); /* * Check if a string contains control characters. If 'ok' is * non-NULL it may be a string containing additional CCs to be * considered OK. */ for (t = p; *t; t++) { if (ok && strchr(ok, *t)) continue; if (*t > 0 && *t < ' ') return true; if (*t == 127) return true; } return false; } static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) { size_t x; char *r; assert(s); assert(percent <= 100); assert(new_length >= 3); if (old_length <= 3 || old_length <= new_length) return strndup(s, old_length); r = new0(char, new_length+1); if (!r) return NULL; x = (new_length * percent) / 100; if (x > new_length - 3) x = new_length - 3; memcpy(r, s, x); r[x] = '.'; r[x+1] = '.'; r[x+2] = '.'; memcpy(r + x + 3, s + old_length - (new_length - x - 3), new_length - x - 3); return r; } char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) { size_t x; char *e; const char *i, *j; unsigned k, len, len2; int r; assert(s); assert(percent <= 100); assert(new_length >= 3); /* if no multibyte characters use ascii_ellipsize_mem for speed */ if (ascii_is_valid(s)) return ascii_ellipsize_mem(s, old_length, new_length, percent); if (old_length <= 3 || old_length <= new_length) return strndup(s, old_length); x = (new_length * percent) / 100; if (x > new_length - 3) x = new_length - 3; k = 0; for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) { char32_t c; r = utf8_encoded_to_unichar(i, &c); if (r < 0) return NULL; k += unichar_iswide(c) ? 2 : 1; } if (k > x) /* last character was wide and went over quota */ x ++; for (j = s + old_length; k < new_length && j > i; ) { char32_t c; j = utf8_prev_char(j); r = utf8_encoded_to_unichar(j, &c); if (r < 0) return NULL; k += unichar_iswide(c) ? 2 : 1; } assert(i <= j); /* we don't actually need to ellipsize */ if (i == j) return memdup(s, old_length + 1); /* make space for ellipsis */ j = utf8_next_char(j); len = i - s; len2 = s + old_length - j; e = new(char, len + 3 + len2 + 1); if (!e) return NULL; /* printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n", old_length, new_length, x, len, len2, k); */ memcpy(e, s, len); e[len] = 0xe2; /* tri-dot ellipsis: … */ e[len + 1] = 0x80; e[len + 2] = 0xa6; memcpy(e + len + 3, j, len2 + 1); return e; } char *ellipsize(const char *s, size_t length, unsigned percent) { return ellipsize_mem(s, strlen(s), length, percent); } bool nulstr_contains(const char*nulstr, const char *needle) { const char *i; if (!nulstr) return false; NULSTR_FOREACH(i, nulstr) if (streq(i, needle)) return true; return false; } char* strshorten(char *s, size_t l) { assert(s); if (l < strlen(s)) s[l] = 0; return s; } char *strreplace(const char *text, const char *old_string, const char *new_string) { const char *f; char *t, *r; size_t l, old_len, new_len; assert(text); assert(old_string); assert(new_string); old_len = strlen(old_string); new_len = strlen(new_string); l = strlen(text); r = new(char, l+1); if (!r) return NULL; f = text; t = r; while (*f) { char *a; size_t d, nl; if (!startswith(f, old_string)) { *(t++) = *(f++); continue; } d = t - r; nl = l - old_len + new_len; a = realloc(r, nl + 1); if (!a) goto oom; l = nl; r = a; t = r + d; t = stpcpy(t, new_string); f += old_len; } *t = 0; return r; oom: free(r); return NULL; } char *strip_tab_ansi(char **ibuf, size_t *_isz) { const char *i, *begin = NULL; enum { STATE_OTHER, STATE_ESCAPE, STATE_BRACKET } state = STATE_OTHER; char *obuf = NULL; size_t osz = 0, isz; FILE *f; assert(ibuf); assert(*ibuf); /* Strips ANSI color and replaces TABs by 8 spaces */ isz = _isz ? *_isz : strlen(*ibuf); f = open_memstream(&obuf, &osz); if (!f) return NULL; for (i = *ibuf; i < *ibuf + isz + 1; i++) { switch (state) { case STATE_OTHER: if (i >= *ibuf + isz) /* EOT */ break; else if (*i == '\x1B') state = STATE_ESCAPE; else if (*i == '\t') fputs(" ", f); else fputc(*i, f); break; case STATE_ESCAPE: if (i >= *ibuf + isz) { /* EOT */ fputc('\x1B', f); break; } else if (*i == '[') { state = STATE_BRACKET; begin = i + 1; } else { fputc('\x1B', f); fputc(*i, f); state = STATE_OTHER; } break; case STATE_BRACKET: if (i >= *ibuf + isz || /* EOT */ (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) { fputc('\x1B', f); fputc('[', f); state = STATE_OTHER; i = begin-1; } else if (*i == 'm') state = STATE_OTHER; break; } } if (ferror(f)) { fclose(f); free(obuf); return NULL; } fclose(f); free(*ibuf); *ibuf = obuf; if (_isz) *_isz = osz; return obuf; } char *strextend(char **x, ...) { va_list ap; size_t f, l; char *r, *p; assert(x); l = f = *x ? strlen(*x) : 0; va_start(ap, x); for (;;) { const char *t; size_t n; t = va_arg(ap, const char *); if (!t) break; n = strlen(t); if (n > ((size_t) -1) - l) { va_end(ap); return NULL; } l += n; } va_end(ap); r = realloc(*x, l+1); if (!r) return NULL; p = r + f; va_start(ap, x); for (;;) { const char *t; t = va_arg(ap, const char *); if (!t) break; p = stpcpy(p, t); } va_end(ap); *p = 0; *x = r; return r + l; } char *strrep(const char *s, unsigned n) { size_t l; char *r, *p; unsigned i; assert(s); l = strlen(s); p = r = malloc(l * n + 1); if (!r) return NULL; for (i = 0; i < n; i++) p = stpcpy(p, s); *p = 0; return r; } int split_pair(const char *s, const char *sep, char **l, char **r) { char *x, *a, *b; assert(s); assert(sep); assert(l); assert(r); if (isempty(sep)) return -EINVAL; x = strstr(s, sep); if (!x) return -EINVAL; a = strndup(s, x - s); if (!a) return -ENOMEM; b = strdup(x + strlen(sep)); if (!b) { free(a); return -ENOMEM; } *l = a; *r = b; return 0; } int free_and_strdup(char **p, const char *s) { char *t; assert(p); /* Replaces a string pointer with an strdup()ed new string, * possibly freeing the old one. */ if (streq_ptr(*p, s)) return 0; if (s) { t = strdup(s); if (!t) return -ENOMEM; } else t = NULL; free(*p); *p = t; return 1; } #pragma GCC push_options #pragma GCC optimize("O0") void* memory_erase(void *p, size_t l) { volatile uint8_t* x = (volatile uint8_t*) p; /* This basically does what memset() does, but hopefully isn't * optimized away by the compiler. One of those days, when * glibc learns memset_s() we should replace this call by * memset_s(), but until then this has to do. */ for (; l > 0; l--) *(x++) = 'x'; return p; } #pragma GCC pop_options char* string_erase(char *x) { if (!x) return NULL; /* A delicious drop of snake-oil! To be called on memory where * we stored passphrases or so, after we used them. */ return memory_erase(x, strlen(x)); } char *string_free_erase(char *s) { return mfree(string_erase(s)); } bool string_is_safe(const char *p) { const char *t; if (!p) return false; for (t = p; *t; t++) { if (*t > 0 && *t < ' ') /* no control characters */ return false; if (strchr(QUOTES "\\\x7f", *t)) return false; } return true; } systemd-229/src/basic/string-util.h000066400000000000000000000145431265713322000173720ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "macro.h" /* What is interpreted as whitespace? */ #define WHITESPACE " \t\n\r" #define NEWLINE "\n\r" #define QUOTES "\"\'" #define COMMENTS "#;" #define GLOB_CHARS "*?[" #define DIGITS "0123456789" #define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz" #define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS #define ALPHANUMERICAL LETTERS DIGITS #define streq(a,b) (strcmp((a),(b)) == 0) #define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) #define strcaseeq(a,b) (strcasecmp((a),(b)) == 0) #define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0) int strcmp_ptr(const char *a, const char *b) _pure_; static inline bool streq_ptr(const char *a, const char *b) { return strcmp_ptr(a, b) == 0; } static inline const char* strempty(const char *s) { return s ? s : ""; } static inline const char* strnull(const char *s) { return s ? s : "(null)"; } static inline const char *strna(const char *s) { return s ? s : "n/a"; } static inline bool isempty(const char *p) { return !p || !p[0]; } static inline char *startswith(const char *s, const char *prefix) { size_t l; l = strlen(prefix); if (strncmp(s, prefix, l) == 0) return (char*) s + l; return NULL; } static inline char *startswith_no_case(const char *s, const char *prefix) { size_t l; l = strlen(prefix); if (strncasecmp(s, prefix, l) == 0) return (char*) s + l; return NULL; } char *endswith(const char *s, const char *postfix) _pure_; char *endswith_no_case(const char *s, const char *postfix) _pure_; char *first_word(const char *s, const char *word) _pure_; const char* split(const char **state, size_t *l, const char *separator, bool quoted); #define FOREACH_WORD(word, length, s, state) \ _FOREACH_WORD(word, length, s, WHITESPACE, false, state) #define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \ _FOREACH_WORD(word, length, s, separator, false, state) #define FOREACH_WORD_QUOTED(word, length, s, state) \ _FOREACH_WORD(word, length, s, WHITESPACE, true, state) #define _FOREACH_WORD(word, length, s, separator, quoted, state) \ for ((state) = (s), (word) = split(&(state), &(length), (separator), (quoted)); (word); (word) = split(&(state), &(length), (separator), (quoted))) char *strappend(const char *s, const char *suffix); char *strnappend(const char *s, const char *suffix, size_t length); char *strjoin(const char *x, ...) _sentinel_; #define strjoina(a, ...) \ ({ \ const char *_appendees_[] = { a, __VA_ARGS__ }; \ char *_d_, *_p_; \ int _len_ = 0; \ unsigned _i_; \ for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ _len_ += strlen(_appendees_[_i_]); \ _p_ = _d_ = alloca(_len_ + 1); \ for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ _p_ = stpcpy(_p_, _appendees_[_i_]); \ *_p_ = 0; \ _d_; \ }) char *strstrip(char *s); char *delete_chars(char *s, const char *bad); char *truncate_nl(char *s); char ascii_tolower(char x); char *ascii_strlower(char *s); char *ascii_strlower_n(char *s, size_t n); int ascii_strcasecmp_n(const char *a, const char *b, size_t n); int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m); bool chars_intersect(const char *a, const char *b) _pure_; static inline bool _pure_ in_charset(const char *s, const char* charset) { assert(s); assert(charset); return s[strspn(s, charset)] == '\0'; } bool string_has_cc(const char *p, const char *ok) _pure_; char *ellipsize_mem(const char *s, size_t old_length_bytes, size_t new_length_columns, unsigned percent); char *ellipsize(const char *s, size_t length, unsigned percent); bool nulstr_contains(const char*nulstr, const char *needle); char* strshorten(char *s, size_t l); char *strreplace(const char *text, const char *old_string, const char *new_string); char *strip_tab_ansi(char **p, size_t *l); char *strextend(char **x, ...) _sentinel_; char *strrep(const char *s, unsigned n); int split_pair(const char *s, const char *sep, char **l, char **r); int free_and_strdup(char **p, const char *s); /* Normal memmem() requires haystack to be nonnull, which is annoying for zero-length buffers */ static inline void *memmem_safe(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { if (needlelen <= 0) return (void*) haystack; if (haystacklen < needlelen) return NULL; assert(haystack); assert(needle); return memmem(haystack, haystacklen, needle, needlelen); } void* memory_erase(void *p, size_t l); char *string_erase(char *x); char *string_free_erase(char *s); DEFINE_TRIVIAL_CLEANUP_FUNC(char *, string_free_erase); #define _cleanup_string_free_erase_ _cleanup_(string_free_erasep) bool string_is_safe(const char *p) _pure_; systemd-229/src/basic/strv.c000066400000000000000000000436531265713322000161060ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "alloc-util.h" #include "escape.h" #include "extract-word.h" #include "fileio.h" #include "string-util.h" #include "strv.h" #include "util.h" char *strv_find(char **l, const char *name) { char **i; assert(name); STRV_FOREACH(i, l) if (streq(*i, name)) return *i; return NULL; } char *strv_find_prefix(char **l, const char *name) { char **i; assert(name); STRV_FOREACH(i, l) if (startswith(*i, name)) return *i; return NULL; } char *strv_find_startswith(char **l, const char *name) { char **i, *e; assert(name); /* Like strv_find_prefix, but actually returns only the * suffix, not the whole item */ STRV_FOREACH(i, l) { e = startswith(*i, name); if (e) return e; } return NULL; } void strv_clear(char **l) { char **k; if (!l) return; for (k = l; *k; k++) free(*k); *l = NULL; } char **strv_free(char **l) { strv_clear(l); free(l); return NULL; } char **strv_free_erase(char **l) { char **i; STRV_FOREACH(i, l) string_erase(*i); return strv_free(l); } char **strv_copy(char * const *l) { char **r, **k; k = r = new(char*, strv_length(l) + 1); if (!r) return NULL; if (l) for (; *l; k++, l++) { *k = strdup(*l); if (!*k) { strv_free(r); return NULL; } } *k = NULL; return r; } unsigned strv_length(char * const *l) { unsigned n = 0; if (!l) return 0; for (; *l; l++) n++; return n; } char **strv_new_ap(const char *x, va_list ap) { const char *s; char **a; unsigned n = 0, i = 0; va_list aq; /* As a special trick we ignore all listed strings that equal * (const char*) -1. This is supposed to be used with the * STRV_IFNOTNULL() macro to include possibly NULL strings in * the string list. */ if (x) { n = x == (const char*) -1 ? 0 : 1; va_copy(aq, ap); while ((s = va_arg(aq, const char*))) { if (s == (const char*) -1) continue; n++; } va_end(aq); } a = new(char*, n+1); if (!a) return NULL; if (x) { if (x != (const char*) -1) { a[i] = strdup(x); if (!a[i]) goto fail; i++; } while ((s = va_arg(ap, const char*))) { if (s == (const char*) -1) continue; a[i] = strdup(s); if (!a[i]) goto fail; i++; } } a[i] = NULL; return a; fail: strv_free(a); return NULL; } char **strv_new(const char *x, ...) { char **r; va_list ap; va_start(ap, x); r = strv_new_ap(x, ap); va_end(ap); return r; } int strv_extend_strv(char ***a, char **b, bool filter_duplicates) { char **s, **t; size_t p, q, i = 0, j; assert(a); if (strv_isempty(b)) return 0; p = strv_length(*a); q = strv_length(b); t = realloc(*a, sizeof(char*) * (p + q + 1)); if (!t) return -ENOMEM; t[p] = NULL; *a = t; STRV_FOREACH(s, b) { if (filter_duplicates && strv_contains(t, *s)) continue; t[p+i] = strdup(*s); if (!t[p+i]) goto rollback; i++; t[p+i] = NULL; } assert(i <= q); return (int) i; rollback: for (j = 0; j < i; j++) free(t[p + j]); t[p] = NULL; return -ENOMEM; } int strv_extend_strv_concat(char ***a, char **b, const char *suffix) { int r; char **s; STRV_FOREACH(s, b) { char *v; v = strappend(*s, suffix); if (!v) return -ENOMEM; r = strv_push(a, v); if (r < 0) { free(v); return r; } } return 0; } char **strv_split(const char *s, const char *separator) { const char *word, *state; size_t l; unsigned n, i; char **r; assert(s); n = 0; FOREACH_WORD_SEPARATOR(word, l, s, separator, state) n++; r = new(char*, n+1); if (!r) return NULL; i = 0; FOREACH_WORD_SEPARATOR(word, l, s, separator, state) { r[i] = strndup(word, l); if (!r[i]) { strv_free(r); return NULL; } i++; } r[i] = NULL; return r; } char **strv_split_newlines(const char *s) { char **l; unsigned n; assert(s); /* Special version of strv_split() that splits on newlines and * suppresses an empty string at the end */ l = strv_split(s, NEWLINE); if (!l) return NULL; n = strv_length(l); if (n <= 0) return l; if (isempty(l[n - 1])) l[n - 1] = mfree(l[n - 1]); return l; } int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) { _cleanup_strv_free_ char **l = NULL; size_t n = 0, allocated = 0; int r; assert(t); assert(s); for (;;) { _cleanup_free_ char *word = NULL; r = extract_first_word(&s, &word, separators, flags); if (r < 0) return r; if (r == 0) break; if (!GREEDY_REALLOC(l, allocated, n + 2)) return -ENOMEM; l[n++] = word; word = NULL; l[n] = NULL; } if (!l) { l = new0(char*, 1); if (!l) return -ENOMEM; } *t = l; l = NULL; return (int) n; } char *strv_join(char **l, const char *separator) { char *r, *e; char **s; size_t n, k; if (!separator) separator = " "; k = strlen(separator); n = 0; STRV_FOREACH(s, l) { if (n != 0) n += k; n += strlen(*s); } r = new(char, n+1); if (!r) return NULL; e = r; STRV_FOREACH(s, l) { if (e != r) e = stpcpy(e, separator); e = stpcpy(e, *s); } *e = 0; return r; } char *strv_join_quoted(char **l) { char *buf = NULL; char **s; size_t allocated = 0, len = 0; STRV_FOREACH(s, l) { /* assuming here that escaped string cannot be more * than twice as long, and reserving space for the * separator and quotes. */ _cleanup_free_ char *esc = NULL; size_t needed; if (!GREEDY_REALLOC(buf, allocated, len + strlen(*s) * 2 + 3)) goto oom; esc = cescape(*s); if (!esc) goto oom; needed = snprintf(buf + len, allocated - len, "%s\"%s\"", len > 0 ? " " : "", esc); assert(needed < allocated - len); len += needed; } if (!buf) buf = malloc0(1); return buf; oom: free(buf); return NULL; } int strv_push(char ***l, char *value) { char **c; unsigned n, m; if (!value) return 0; n = strv_length(*l); /* Increase and check for overflow */ m = n + 2; if (m < n) return -ENOMEM; c = realloc_multiply(*l, sizeof(char*), m); if (!c) return -ENOMEM; c[n] = value; c[n+1] = NULL; *l = c; return 0; } int strv_push_pair(char ***l, char *a, char *b) { char **c; unsigned n, m; if (!a && !b) return 0; n = strv_length(*l); /* increase and check for overflow */ m = n + !!a + !!b + 1; if (m < n) return -ENOMEM; c = realloc_multiply(*l, sizeof(char*), m); if (!c) return -ENOMEM; if (a) c[n++] = a; if (b) c[n++] = b; c[n] = NULL; *l = c; return 0; } int strv_push_prepend(char ***l, char *value) { char **c; unsigned n, m, i; if (!value) return 0; n = strv_length(*l); /* increase and check for overflow */ m = n + 2; if (m < n) return -ENOMEM; c = new(char*, m); if (!c) return -ENOMEM; for (i = 0; i < n; i++) c[i+1] = (*l)[i]; c[0] = value; c[n+1] = NULL; free(*l); *l = c; return 0; } int strv_consume(char ***l, char *value) { int r; r = strv_push(l, value); if (r < 0) free(value); return r; } int strv_consume_pair(char ***l, char *a, char *b) { int r; r = strv_push_pair(l, a, b); if (r < 0) { free(a); free(b); } return r; } int strv_consume_prepend(char ***l, char *value) { int r; r = strv_push_prepend(l, value); if (r < 0) free(value); return r; } int strv_extend(char ***l, const char *value) { char *v; if (!value) return 0; v = strdup(value); if (!v) return -ENOMEM; return strv_consume(l, v); } char **strv_uniq(char **l) { char **i; /* Drops duplicate entries. The first identical string will be * kept, the others dropped */ STRV_FOREACH(i, l) strv_remove(i+1, *i); return l; } bool strv_is_uniq(char **l) { char **i; STRV_FOREACH(i, l) if (strv_find(i+1, *i)) return false; return true; } char **strv_remove(char **l, const char *s) { char **f, **t; if (!l) return NULL; assert(s); /* Drops every occurrence of s in the string list, edits * in-place. */ for (f = t = l; *f; f++) if (streq(*f, s)) free(*f); else *(t++) = *f; *t = NULL; return l; } char **strv_parse_nulstr(const char *s, size_t l) { const char *p; unsigned c = 0, i = 0; char **v; assert(s || l <= 0); if (l <= 0) return new0(char*, 1); for (p = s; p < s + l; p++) if (*p == 0) c++; if (s[l-1] != 0) c++; v = new0(char*, c+1); if (!v) return NULL; p = s; while (p < s + l) { const char *e; e = memchr(p, 0, s + l - p); v[i] = strndup(p, e ? e - p : s + l - p); if (!v[i]) { strv_free(v); return NULL; } i++; if (!e) break; p = e + 1; } assert(i == c); return v; } char **strv_split_nulstr(const char *s) { const char *i; char **r = NULL; NULSTR_FOREACH(i, s) if (strv_extend(&r, i) < 0) { strv_free(r); return NULL; } if (!r) return strv_new(NULL, NULL); return r; } int strv_make_nulstr(char **l, char **p, size_t *q) { size_t n_allocated = 0, n = 0; _cleanup_free_ char *m = NULL; char **i; assert(p); assert(q); STRV_FOREACH(i, l) { size_t z; z = strlen(*i); if (!GREEDY_REALLOC(m, n_allocated, n + z + 1)) return -ENOMEM; memcpy(m + n, *i, z + 1); n += z + 1; } if (!m) { m = new0(char, 1); if (!m) return -ENOMEM; n = 0; } *p = m; *q = n; m = NULL; return 0; } bool strv_overlap(char **a, char **b) { char **i; STRV_FOREACH(i, a) if (strv_contains(b, *i)) return true; return false; } static int str_compare(const void *_a, const void *_b) { const char **a = (const char**) _a, **b = (const char**) _b; return strcmp(*a, *b); } char **strv_sort(char **l) { if (strv_isempty(l)) return l; qsort(l, strv_length(l), sizeof(char*), str_compare); return l; } bool strv_equal(char **a, char **b) { if (strv_isempty(a)) return strv_isempty(b); if (strv_isempty(b)) return false; for ( ; *a || *b; ++a, ++b) if (!streq_ptr(*a, *b)) return false; return true; } void strv_print(char **l) { char **s; STRV_FOREACH(s, l) puts(*s); } int strv_extendf(char ***l, const char *format, ...) { va_list ap; char *x; int r; va_start(ap, format); r = vasprintf(&x, format, ap); va_end(ap); if (r < 0) return -ENOMEM; return strv_consume(l, x); } char **strv_reverse(char **l) { unsigned n, i; n = strv_length(l); if (n <= 1) return l; for (i = 0; i < n / 2; i++) { char *t; t = l[i]; l[i] = l[n-1-i]; l[n-1-i] = t; } return l; } char **strv_shell_escape(char **l, const char *bad) { char **s; /* Escapes every character in every string in l that is in bad, * edits in-place, does not roll-back on error. */ STRV_FOREACH(s, l) { char *v; v = shell_escape(*s, bad); if (!v) return NULL; free(*s); *s = v; } return l; } bool strv_fnmatch(char* const* patterns, const char *s, int flags) { char* const* p; STRV_FOREACH(p, patterns) if (fnmatch(*p, s, 0) == 0) return true; return false; } char ***strv_free_free(char ***l) { char ***i; if (!l) return NULL; for (i = l; *i; i++) strv_free(*i); free(l); return NULL; } char **strv_skip(char **l, size_t n) { while (n > 0) { if (strv_isempty(l)) return l; l++, n--; } return l; } int strv_extend_n(char ***l, const char *value, size_t n) { size_t i, j, k; char **nl; assert(l); if (!value) return 0; if (n == 0) return 0; /* Adds the value value n times to l */ k = strv_length(*l); nl = realloc(*l, sizeof(char*) * (k + n + 1)); if (!nl) return -ENOMEM; *l = nl; for (i = k; i < k + n; i++) { nl[i] = strdup(value); if (!nl[i]) goto rollback; } nl[i] = NULL; return 0; rollback: for (j = k; j < i; j++) free(nl[j]); nl[k] = NULL; return -ENOMEM; } int fputstrv(FILE *f, char **l, const char *separator, bool *space) { bool b = false; char **s; int r; /* Like fputs(), but for strv, and with a less stupid argument order */ if (!space) space = &b; STRV_FOREACH(s, l) { r = fputs_with_space(f, *s, separator, space); if (r < 0) return r; } return 0; } systemd-229/src/basic/strv.h000066400000000000000000000147351265713322000161120ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "extract-word.h" #include "macro.h" #include "util.h" char *strv_find(char **l, const char *name) _pure_; char *strv_find_prefix(char **l, const char *name) _pure_; char *strv_find_startswith(char **l, const char *name) _pure_; char **strv_free(char **l); DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free); #define _cleanup_strv_free_ _cleanup_(strv_freep) char **strv_free_erase(char **l); DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free_erase); #define _cleanup_strv_free_erase_ _cleanup_(strv_free_erasep) void strv_clear(char **l); char **strv_copy(char * const *l); unsigned strv_length(char * const *l) _pure_; int strv_extend_strv(char ***a, char **b, bool filter_duplicates); int strv_extend_strv_concat(char ***a, char **b, const char *suffix); int strv_extend(char ***l, const char *value); int strv_extendf(char ***l, const char *format, ...) _printf_(2,0); int strv_push(char ***l, char *value); int strv_push_pair(char ***l, char *a, char *b); int strv_push_prepend(char ***l, char *value); int strv_consume(char ***l, char *value); int strv_consume_pair(char ***l, char *a, char *b); int strv_consume_prepend(char ***l, char *value); char **strv_remove(char **l, const char *s); char **strv_uniq(char **l); bool strv_is_uniq(char **l); bool strv_equal(char **a, char **b); #define strv_contains(l, s) (!!strv_find((l), (s))) char **strv_new(const char *x, ...) _sentinel_; char **strv_new_ap(const char *x, va_list ap); static inline const char* STRV_IFNOTNULL(const char *x) { return x ? x : (const char *) -1; } static inline bool strv_isempty(char * const *l) { return !l || !*l; } char **strv_split(const char *s, const char *separator); char **strv_split_newlines(const char *s); int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags); char *strv_join(char **l, const char *separator); char *strv_join_quoted(char **l); char **strv_parse_nulstr(const char *s, size_t l); char **strv_split_nulstr(const char *s); int strv_make_nulstr(char **l, char **p, size_t *n); bool strv_overlap(char **a, char **b) _pure_; #define STRV_FOREACH(s, l) \ for ((s) = (l); (s) && *(s); (s)++) #define STRV_FOREACH_BACKWARDS(s, l) \ STRV_FOREACH(s, l) \ ; \ for ((s)--; (l) && ((s) >= (l)); (s)--) #define STRV_FOREACH_PAIR(x, y, l) \ for ((x) = (l), (y) = (x+1); (x) && *(x) && *(y); (x) += 2, (y) = (x + 1)) char **strv_sort(char **l); void strv_print(char **l); #define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL })) #define STRV_MAKE_EMPTY ((char*[1]) { NULL }) #define strv_from_stdarg_alloca(first) \ ({ \ char **_l; \ \ if (!first) \ _l = (char**) &first; \ else { \ unsigned _n; \ va_list _ap; \ \ _n = 1; \ va_start(_ap, first); \ while (va_arg(_ap, char*)) \ _n++; \ va_end(_ap); \ \ _l = newa(char*, _n+1); \ _l[_n = 0] = (char*) first; \ va_start(_ap, first); \ for (;;) { \ _l[++_n] = va_arg(_ap, char*); \ if (!_l[_n]) \ break; \ } \ va_end(_ap); \ } \ _l; \ }) #define STR_IN_SET(x, ...) strv_contains(STRV_MAKE(__VA_ARGS__), x) #define FOREACH_STRING(x, ...) \ for (char **_l = ({ \ char **_ll = STRV_MAKE(__VA_ARGS__); \ x = _ll ? _ll[0] : NULL; \ _ll; \ }); \ _l && *_l; \ x = ({ \ _l ++; \ _l[0]; \ })) char **strv_reverse(char **l); char **strv_shell_escape(char **l, const char *bad); bool strv_fnmatch(char* const* patterns, const char *s, int flags); static inline bool strv_fnmatch_or_empty(char* const* patterns, const char *s, int flags) { assert(s); return strv_isempty(patterns) || strv_fnmatch(patterns, s, flags); } char ***strv_free_free(char ***l); char **strv_skip(char **l, size_t n); int strv_extend_n(char ***l, const char *value, size_t n); int fputstrv(FILE *f, char **l, const char *separator, bool *space); systemd-229/src/basic/strxcpyx.c000066400000000000000000000051301265713322000170000ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* * Concatenates/copies strings. In any case, terminates in all cases * with '\0' * and moves the @dest pointer forward to the added '\0'. * Returns the * remaining size, and 0 if the string was truncated. */ #include #include #include #include "strxcpyx.h" size_t strpcpy(char **dest, size_t size, const char *src) { size_t len; len = strlen(src); if (len >= size) { if (size > 1) *dest = mempcpy(*dest, src, size-1); size = 0; } else { if (len > 0) { *dest = mempcpy(*dest, src, len); size -= len; } } *dest[0] = '\0'; return size; } size_t strpcpyf(char **dest, size_t size, const char *src, ...) { va_list va; int i; va_start(va, src); i = vsnprintf(*dest, size, src, va); if (i < (int)size) { *dest += i; size -= i; } else { *dest += size; size = 0; } va_end(va); *dest[0] = '\0'; return size; } size_t strpcpyl(char **dest, size_t size, const char *src, ...) { va_list va; va_start(va, src); do { size = strpcpy(dest, size, src); src = va_arg(va, char *); } while (src != NULL); va_end(va); return size; } size_t strscpy(char *dest, size_t size, const char *src) { char *s; s = dest; return strpcpy(&s, size, src); } size_t strscpyl(char *dest, size_t size, const char *src, ...) { va_list va; char *s; va_start(va, src); s = dest; do { size = strpcpy(&s, size, src); src = va_arg(va, char *); } while (src != NULL); va_end(va); return size; } systemd-229/src/basic/strxcpyx.h000066400000000000000000000021341265713322000170060ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" size_t strpcpy(char **dest, size_t size, const char *src); size_t strpcpyf(char **dest, size_t size, const char *src, ...) _printf_(3, 4); size_t strpcpyl(char **dest, size_t size, const char *src, ...) _sentinel_; size_t strscpy(char *dest, size_t size, const char *src); size_t strscpyl(char *dest, size_t size, const char *src, ...) _sentinel_; systemd-229/src/basic/syslog-util.c000066400000000000000000000065721265713322000174020ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "hexdecoct.h" #include "macro.h" #include "string-table.h" #include "syslog-util.h" int syslog_parse_priority(const char **p, int *priority, bool with_facility) { int a = 0, b = 0, c = 0; int k; assert(p); assert(*p); assert(priority); if ((*p)[0] != '<') return 0; if (!strchr(*p, '>')) return 0; if ((*p)[2] == '>') { c = undecchar((*p)[1]); k = 3; } else if ((*p)[3] == '>') { b = undecchar((*p)[1]); c = undecchar((*p)[2]); k = 4; } else if ((*p)[4] == '>') { a = undecchar((*p)[1]); b = undecchar((*p)[2]); c = undecchar((*p)[3]); k = 5; } else return 0; if (a < 0 || b < 0 || c < 0 || (!with_facility && (a || b || c > 7))) return 0; if (with_facility) *priority = a*100 + b*10 + c; else *priority = (*priority & LOG_FACMASK) | c; *p += k; return 1; } static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = { [LOG_FAC(LOG_KERN)] = "kern", [LOG_FAC(LOG_USER)] = "user", [LOG_FAC(LOG_MAIL)] = "mail", [LOG_FAC(LOG_DAEMON)] = "daemon", [LOG_FAC(LOG_AUTH)] = "auth", [LOG_FAC(LOG_SYSLOG)] = "syslog", [LOG_FAC(LOG_LPR)] = "lpr", [LOG_FAC(LOG_NEWS)] = "news", [LOG_FAC(LOG_UUCP)] = "uucp", [LOG_FAC(LOG_CRON)] = "cron", [LOG_FAC(LOG_AUTHPRIV)] = "authpriv", [LOG_FAC(LOG_FTP)] = "ftp", [LOG_FAC(LOG_LOCAL0)] = "local0", [LOG_FAC(LOG_LOCAL1)] = "local1", [LOG_FAC(LOG_LOCAL2)] = "local2", [LOG_FAC(LOG_LOCAL3)] = "local3", [LOG_FAC(LOG_LOCAL4)] = "local4", [LOG_FAC(LOG_LOCAL5)] = "local5", [LOG_FAC(LOG_LOCAL6)] = "local6", [LOG_FAC(LOG_LOCAL7)] = "local7" }; DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0)); bool log_facility_unshifted_is_valid(int facility) { return facility >= 0 && facility <= LOG_FAC(~0); } static const char *const log_level_table[] = { [LOG_EMERG] = "emerg", [LOG_ALERT] = "alert", [LOG_CRIT] = "crit", [LOG_ERR] = "err", [LOG_WARNING] = "warning", [LOG_NOTICE] = "notice", [LOG_INFO] = "info", [LOG_DEBUG] = "debug" }; DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG); bool log_level_is_valid(int level) { return level >= 0 && level <= LOG_DEBUG; } systemd-229/src/basic/syslog-util.h000066400000000000000000000021501265713322000173730ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include int log_facility_unshifted_to_string_alloc(int i, char **s); int log_facility_unshifted_from_string(const char *s); bool log_facility_unshifted_is_valid(int faciliy); int log_level_to_string_alloc(int i, char **s); int log_level_from_string(const char *s); bool log_level_is_valid(int level); int syslog_parse_priority(const char **p, int *priority, bool with_facility); systemd-229/src/basic/terminal-util.c000066400000000000000000000744451265713322000177010ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "io-util.h" #include "log.h" #include "macro.h" #include "parse-util.h" #include "process-util.h" #include "socket-util.h" #include "stat-util.h" #include "string-util.h" #include "terminal-util.h" #include "time-util.h" #include "util.h" static volatile unsigned cached_columns = 0; static volatile unsigned cached_lines = 0; int chvt(int vt) { _cleanup_close_ int fd; fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return -errno; if (vt <= 0) { int tiocl[2] = { TIOCL_GETKMSGREDIRECT, 0 }; if (ioctl(fd, TIOCLINUX, tiocl) < 0) return -errno; vt = tiocl[0] <= 0 ? 1 : tiocl[0]; } if (ioctl(fd, VT_ACTIVATE, vt) < 0) return -errno; return 0; } int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) { struct termios old_termios, new_termios; char c, line[LINE_MAX]; assert(f); assert(ret); if (tcgetattr(fileno(f), &old_termios) >= 0) { new_termios = old_termios; new_termios.c_lflag &= ~ICANON; new_termios.c_cc[VMIN] = 1; new_termios.c_cc[VTIME] = 0; if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) { size_t k; if (t != USEC_INFINITY) { if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) { tcsetattr(fileno(f), TCSADRAIN, &old_termios); return -ETIMEDOUT; } } k = fread(&c, 1, 1, f); tcsetattr(fileno(f), TCSADRAIN, &old_termios); if (k <= 0) return -EIO; if (need_nl) *need_nl = c != '\n'; *ret = c; return 0; } } if (t != USEC_INFINITY) { if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) return -ETIMEDOUT; } errno = 0; if (!fgets(line, sizeof(line), f)) return errno > 0 ? -errno : -EIO; truncate_nl(line); if (strlen(line) != 1) return -EBADMSG; if (need_nl) *need_nl = false; *ret = line[0]; return 0; } int ask_char(char *ret, const char *replies, const char *text, ...) { int r; assert(ret); assert(replies); assert(text); for (;;) { va_list ap; char c; bool need_nl = true; if (on_tty()) fputs(ANSI_HIGHLIGHT, stdout); va_start(ap, text); vprintf(text, ap); va_end(ap); if (on_tty()) fputs(ANSI_NORMAL, stdout); fflush(stdout); r = read_one_char(stdin, &c, USEC_INFINITY, &need_nl); if (r < 0) { if (r == -EBADMSG) { puts("Bad input, please try again."); continue; } putchar('\n'); return r; } if (need_nl) putchar('\n'); if (strchr(replies, c)) { *ret = c; return 0; } puts("Read unexpected character, please try again."); } } int ask_string(char **ret, const char *text, ...) { assert(ret); assert(text); for (;;) { char line[LINE_MAX]; va_list ap; if (on_tty()) fputs(ANSI_HIGHLIGHT, stdout); va_start(ap, text); vprintf(text, ap); va_end(ap); if (on_tty()) fputs(ANSI_NORMAL, stdout); fflush(stdout); errno = 0; if (!fgets(line, sizeof(line), stdin)) return errno > 0 ? -errno : -EIO; if (!endswith(line, "\n")) putchar('\n'); else { char *s; if (isempty(line)) continue; truncate_nl(line); s = strdup(line); if (!s) return -ENOMEM; *ret = s; return 0; } } } int reset_terminal_fd(int fd, bool switch_to_text) { struct termios termios; int r = 0; /* Set terminal to some sane defaults */ assert(fd >= 0); /* We leave locked terminal attributes untouched, so that * Plymouth may set whatever it wants to set, and we don't * interfere with that. */ /* Disable exclusive mode, just in case */ (void) ioctl(fd, TIOCNXCL); /* Switch to text mode */ if (switch_to_text) (void) ioctl(fd, KDSETMODE, KD_TEXT); /* Enable console unicode mode */ (void) ioctl(fd, KDSKBMODE, K_UNICODE); if (tcgetattr(fd, &termios) < 0) { r = -errno; goto finish; } /* We only reset the stuff that matters to the software. How * hardware is set up we don't touch assuming that somebody * else will do that for us */ termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC); termios.c_iflag |= ICRNL | IMAXBEL | IUTF8; termios.c_oflag |= ONLCR; termios.c_cflag |= CREAD; termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE; termios.c_cc[VINTR] = 03; /* ^C */ termios.c_cc[VQUIT] = 034; /* ^\ */ termios.c_cc[VERASE] = 0177; termios.c_cc[VKILL] = 025; /* ^X */ termios.c_cc[VEOF] = 04; /* ^D */ termios.c_cc[VSTART] = 021; /* ^Q */ termios.c_cc[VSTOP] = 023; /* ^S */ termios.c_cc[VSUSP] = 032; /* ^Z */ termios.c_cc[VLNEXT] = 026; /* ^V */ termios.c_cc[VWERASE] = 027; /* ^W */ termios.c_cc[VREPRINT] = 022; /* ^R */ termios.c_cc[VEOL] = 0; termios.c_cc[VEOL2] = 0; termios.c_cc[VTIME] = 0; termios.c_cc[VMIN] = 1; if (tcsetattr(fd, TCSANOW, &termios) < 0) r = -errno; finish: /* Just in case, flush all crap out */ (void) tcflush(fd, TCIOFLUSH); return r; } int reset_terminal(const char *name) { _cleanup_close_ int fd = -1; /* We open the terminal with O_NONBLOCK here, to ensure we * don't block on carrier if this is a terminal with carrier * configured. */ fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return fd; return reset_terminal_fd(fd, true); } int open_terminal(const char *name, int mode) { int fd, r; unsigned c = 0; /* * If a TTY is in the process of being closed opening it might * cause EIO. This is horribly awful, but unlikely to be * changed in the kernel. Hence we work around this problem by * retrying a couple of times. * * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245 */ if (mode & O_CREAT) return -EINVAL; for (;;) { fd = open(name, mode, 0); if (fd >= 0) break; if (errno != EIO) return -errno; /* Max 1s in total */ if (c >= 20) return -errno; usleep(50 * USEC_PER_MSEC); c++; } r = isatty(fd); if (r < 0) { safe_close(fd); return -errno; } if (!r) { safe_close(fd); return -ENOTTY; } return fd; } int acquire_terminal( const char *name, bool fail, bool force, bool ignore_tiocstty_eperm, usec_t timeout) { int fd = -1, notify = -1, r = 0, wd = -1; usec_t ts = 0; assert(name); /* We use inotify to be notified when the tty is closed. We * create the watch before checking if we can actually acquire * it, so that we don't lose any event. * * Note: strictly speaking this actually watches for the * device being closed, it does *not* really watch whether a * tty loses its controlling process. However, unless some * rogue process uses TIOCNOTTY on /dev/tty *after* closing * its tty otherwise this will not become a problem. As long * as the administrator makes sure not configure any service * on the same tty as an untrusted user this should not be a * problem. (Which he probably should not do anyway.) */ if (timeout != USEC_INFINITY) ts = now(CLOCK_MONOTONIC); if (!fail && !force) { notify = inotify_init1(IN_CLOEXEC | (timeout != USEC_INFINITY ? IN_NONBLOCK : 0)); if (notify < 0) { r = -errno; goto fail; } wd = inotify_add_watch(notify, name, IN_CLOSE); if (wd < 0) { r = -errno; goto fail; } } for (;;) { struct sigaction sa_old, sa_new = { .sa_handler = SIG_IGN, .sa_flags = SA_RESTART, }; if (notify >= 0) { r = flush_fd(notify); if (r < 0) goto fail; } /* We pass here O_NOCTTY only so that we can check the return * value TIOCSCTTY and have a reliable way to figure out if we * successfully became the controlling process of the tty */ fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) return fd; /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed * if we already own the tty. */ assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0); /* First, try to get the tty */ if (ioctl(fd, TIOCSCTTY, force) < 0) r = -errno; assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0); /* Sometimes, it makes sense to ignore TIOCSCTTY * returning EPERM, i.e. when very likely we already * are have this controlling terminal. */ if (r < 0 && r == -EPERM && ignore_tiocstty_eperm) r = 0; if (r < 0 && (force || fail || r != -EPERM)) goto fail; if (r >= 0) break; assert(!fail); assert(!force); assert(notify >= 0); for (;;) { union inotify_event_buffer buffer; struct inotify_event *e; ssize_t l; if (timeout != USEC_INFINITY) { usec_t n; n = now(CLOCK_MONOTONIC); if (ts + timeout < n) { r = -ETIMEDOUT; goto fail; } r = fd_wait_for_event(fd, POLLIN, ts + timeout - n); if (r < 0) goto fail; if (r == 0) { r = -ETIMEDOUT; goto fail; } } l = read(notify, &buffer, sizeof(buffer)); if (l < 0) { if (errno == EINTR || errno == EAGAIN) continue; r = -errno; goto fail; } FOREACH_INOTIFY_EVENT(e, buffer, l) { if (e->wd != wd || !(e->mask & IN_CLOSE)) { r = -EIO; goto fail; } } break; } /* We close the tty fd here since if the old session * ended our handle will be dead. It's important that * we do this after sleeping, so that we don't enter * an endless loop. */ fd = safe_close(fd); } safe_close(notify); return fd; fail: safe_close(fd); safe_close(notify); return r; } int release_terminal(void) { static const struct sigaction sa_new = { .sa_handler = SIG_IGN, .sa_flags = SA_RESTART, }; _cleanup_close_ int fd = -1; struct sigaction sa_old; int r = 0; fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return -errno; /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed * by our own TIOCNOTTY */ assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0); if (ioctl(fd, TIOCNOTTY) < 0) r = -errno; assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0); return r; } int terminal_vhangup_fd(int fd) { assert(fd >= 0); if (ioctl(fd, TIOCVHANGUP) < 0) return -errno; return 0; } int terminal_vhangup(const char *name) { _cleanup_close_ int fd; fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return fd; return terminal_vhangup_fd(fd); } int vt_disallocate(const char *name) { _cleanup_close_ int fd = -1; unsigned u; int r; /* Deallocate the VT if possible. If not possible * (i.e. because it is the active one), at least clear it * entirely (including the scrollback buffer) */ if (!startswith(name, "/dev/")) return -EINVAL; if (!tty_is_vc(name)) { /* So this is not a VT. I guess we cannot deallocate * it then. But let's at least clear the screen */ fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) return fd; loop_write(fd, "\033[r" /* clear scrolling region */ "\033[H" /* move home */ "\033[2J", /* clear screen */ 10, false); return 0; } if (!startswith(name, "/dev/tty")) return -EINVAL; r = safe_atou(name+8, &u); if (r < 0) return r; if (u <= 0) return -EINVAL; /* Try to deallocate */ fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return fd; r = ioctl(fd, VT_DISALLOCATE, u); fd = safe_close(fd); if (r >= 0) return 0; if (errno != EBUSY) return -errno; /* Couldn't deallocate, so let's clear it fully with * scrollback */ fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) return fd; loop_write(fd, "\033[r" /* clear scrolling region */ "\033[H" /* move home */ "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */ 10, false); return 0; } int make_console_stdio(void) { int fd, r; /* Make /dev/console the controlling terminal and stdin/stdout/stderr */ fd = acquire_terminal("/dev/console", false, true, true, USEC_INFINITY); if (fd < 0) return log_error_errno(fd, "Failed to acquire terminal: %m"); r = reset_terminal_fd(fd, true); if (r < 0) log_warning_errno(r, "Failed to reset terminal, ignoring: %m"); r = make_stdio(fd); if (r < 0) return log_error_errno(r, "Failed to duplicate terminal fd: %m"); return 0; } bool tty_is_vc(const char *tty) { assert(tty); return vtnr_from_tty(tty) >= 0; } bool tty_is_console(const char *tty) { assert(tty); if (startswith(tty, "/dev/")) tty += 5; return streq(tty, "console"); } int vtnr_from_tty(const char *tty) { int i, r; assert(tty); if (startswith(tty, "/dev/")) tty += 5; if (!startswith(tty, "tty") ) return -EINVAL; if (tty[3] < '0' || tty[3] > '9') return -EINVAL; r = safe_atoi(tty+3, &i); if (r < 0) return r; if (i < 0 || i > 63) return -EINVAL; return i; } char *resolve_dev_console(char **active) { char *tty; /* Resolve where /dev/console is pointing to, if /sys is actually ours * (i.e. not read-only-mounted which is a sign for container setups) */ if (path_is_read_only_fs("/sys") > 0) return NULL; if (read_one_line_file("/sys/class/tty/console/active", active) < 0) return NULL; /* If multiple log outputs are configured the last one is what * /dev/console points to */ tty = strrchr(*active, ' '); if (tty) tty++; else tty = *active; if (streq(tty, "tty0")) { char *tmp; /* Get the active VC (e.g. tty1) */ if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) { free(*active); tty = *active = tmp; } } return tty; } bool tty_is_vc_resolve(const char *tty) { _cleanup_free_ char *active = NULL; assert(tty); if (startswith(tty, "/dev/")) tty += 5; if (streq(tty, "console")) { tty = resolve_dev_console(&active); if (!tty) return false; } return tty_is_vc(tty); } const char *default_term_for_tty(const char *tty) { return tty && tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt220"; } int fd_columns(int fd) { struct winsize ws = {}; if (ioctl(fd, TIOCGWINSZ, &ws) < 0) return -errno; if (ws.ws_col <= 0) return -EIO; return ws.ws_col; } unsigned columns(void) { const char *e; int c; if (_likely_(cached_columns > 0)) return cached_columns; c = 0; e = getenv("COLUMNS"); if (e) (void) safe_atoi(e, &c); if (c <= 0) c = fd_columns(STDOUT_FILENO); if (c <= 0) c = 80; cached_columns = c; return cached_columns; } int fd_lines(int fd) { struct winsize ws = {}; if (ioctl(fd, TIOCGWINSZ, &ws) < 0) return -errno; if (ws.ws_row <= 0) return -EIO; return ws.ws_row; } unsigned lines(void) { const char *e; int l; if (_likely_(cached_lines > 0)) return cached_lines; l = 0; e = getenv("LINES"); if (e) (void) safe_atoi(e, &l); if (l <= 0) l = fd_lines(STDOUT_FILENO); if (l <= 0) l = 24; cached_lines = l; return cached_lines; } /* intended to be used as a SIGWINCH sighandler */ void columns_lines_cache_reset(int signum) { cached_columns = 0; cached_lines = 0; } bool on_tty(void) { static int cached_on_tty = -1; if (_unlikely_(cached_on_tty < 0)) cached_on_tty = isatty(STDOUT_FILENO) > 0; return cached_on_tty; } int make_stdio(int fd) { int r, s, t; assert(fd >= 0); r = dup2(fd, STDIN_FILENO); s = dup2(fd, STDOUT_FILENO); t = dup2(fd, STDERR_FILENO); if (fd >= 3) safe_close(fd); if (r < 0 || s < 0 || t < 0) return -errno; /* Explicitly unset O_CLOEXEC, since if fd was < 3, then * dup2() was a NOP and the bit hence possibly set. */ fd_cloexec(STDIN_FILENO, false); fd_cloexec(STDOUT_FILENO, false); fd_cloexec(STDERR_FILENO, false); return 0; } int make_null_stdio(void) { int null_fd; null_fd = open("/dev/null", O_RDWR|O_NOCTTY); if (null_fd < 0) return -errno; return make_stdio(null_fd); } int getttyname_malloc(int fd, char **ret) { size_t l = 100; int r; assert(fd >= 0); assert(ret); for (;;) { char path[l]; r = ttyname_r(fd, path, sizeof(path)); if (r == 0) { const char *p; char *c; p = startswith(path, "/dev/"); c = strdup(p ?: path); if (!c) return -ENOMEM; *ret = c; return 0; } if (r != ERANGE) return -r; l *= 2; } return 0; } int getttyname_harder(int fd, char **r) { int k; char *s = NULL; k = getttyname_malloc(fd, &s); if (k < 0) return k; if (streq(s, "tty")) { free(s); return get_ctty(0, NULL, r); } *r = s; return 0; } int get_ctty_devnr(pid_t pid, dev_t *d) { int r; _cleanup_free_ char *line = NULL; const char *p; unsigned long ttynr; assert(pid >= 0); p = procfs_file_alloca(pid, "stat"); r = read_one_line_file(p, &line); if (r < 0) return r; p = strrchr(line, ')'); if (!p) return -EIO; p++; if (sscanf(p, " " "%*c " /* state */ "%*d " /* ppid */ "%*d " /* pgrp */ "%*d " /* session */ "%lu ", /* ttynr */ &ttynr) != 1) return -EIO; if (major(ttynr) == 0 && minor(ttynr) == 0) return -ENXIO; if (d) *d = (dev_t) ttynr; return 0; } int get_ctty(pid_t pid, dev_t *_devnr, char **r) { char fn[sizeof("/dev/char/")-1 + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *b = NULL; _cleanup_free_ char *s = NULL; const char *p; dev_t devnr; int k; assert(r); k = get_ctty_devnr(pid, &devnr); if (k < 0) return k; sprintf(fn, "/dev/char/%u:%u", major(devnr), minor(devnr)); k = readlink_malloc(fn, &s); if (k < 0) { if (k != -ENOENT) return k; /* This is an ugly hack */ if (major(devnr) == 136) { if (asprintf(&b, "pts/%u", minor(devnr)) < 0) return -ENOMEM; } else { /* Probably something like the ptys which have no * symlink in /dev/char. Let's return something * vaguely useful. */ b = strdup(fn + 5); if (!b) return -ENOMEM; } } else { if (startswith(s, "/dev/")) p = s + 5; else if (startswith(s, "../")) p = s + 3; else p = s; b = strdup(p); if (!b) return -ENOMEM; } *r = b; if (_devnr) *_devnr = devnr; return 0; } int ptsname_malloc(int fd, char **ret) { size_t l = 100; assert(fd >= 0); assert(ret); for (;;) { char *c; c = new(char, l); if (!c) return -ENOMEM; if (ptsname_r(fd, c, l) == 0) { *ret = c; return 0; } if (errno != ERANGE) { free(c); return -errno; } free(c); l *= 2; } } int ptsname_namespace(int pty, char **ret) { int no = -1, r; /* Like ptsname(), but doesn't assume that the path is * accessible in the local namespace. */ r = ioctl(pty, TIOCGPTN, &no); if (r < 0) return -errno; if (no < 0) return -EIO; if (asprintf(ret, "/dev/pts/%i", no) < 0) return -ENOMEM; return 0; } int openpt_in_namespace(pid_t pid, int flags) { _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1; _cleanup_close_pair_ int pair[2] = { -1, -1 }; siginfo_t si; pid_t child; int r; assert(pid > 0); r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd); if (r < 0) return r; if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0) return -errno; child = fork(); if (child < 0) return -errno; if (child == 0) { int master; pair[0] = safe_close(pair[0]); r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd); if (r < 0) _exit(EXIT_FAILURE); master = posix_openpt(flags|O_NOCTTY|O_CLOEXEC); if (master < 0) _exit(EXIT_FAILURE); if (unlockpt(master) < 0) _exit(EXIT_FAILURE); if (send_one_fd(pair[1], master, 0) < 0) _exit(EXIT_FAILURE); _exit(EXIT_SUCCESS); } pair[1] = safe_close(pair[1]); r = wait_for_terminate(child, &si); if (r < 0) return r; if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS) return -EIO; return receive_one_fd(pair[0], 0); } int open_terminal_in_namespace(pid_t pid, const char *name, int mode) { _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1; _cleanup_close_pair_ int pair[2] = { -1, -1 }; siginfo_t si; pid_t child; int r; r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd); if (r < 0) return r; if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0) return -errno; child = fork(); if (child < 0) return -errno; if (child == 0) { int master; pair[0] = safe_close(pair[0]); r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd); if (r < 0) _exit(EXIT_FAILURE); master = open_terminal(name, mode|O_NOCTTY|O_CLOEXEC); if (master < 0) _exit(EXIT_FAILURE); if (send_one_fd(pair[1], master, 0) < 0) _exit(EXIT_FAILURE); _exit(EXIT_SUCCESS); } pair[1] = safe_close(pair[1]); r = wait_for_terminate(child, &si); if (r < 0) return r; if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS) return -EIO; return receive_one_fd(pair[0], 0); } bool colors_enabled(void) { const char *colors; colors = getenv("SYSTEMD_COLORS"); if (!colors) { if (streq_ptr(getenv("TERM"), "dumb")) return false; return on_tty(); } return parse_boolean(colors) != 0; } systemd-229/src/basic/terminal-util.h000066400000000000000000000073601265713322000176760ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "macro.h" #include "time-util.h" #define ANSI_RED "\x1B[0;31m" #define ANSI_GREEN "\x1B[0;32m" #define ANSI_UNDERLINE "\x1B[0;4m" #define ANSI_HIGHLIGHT "\x1B[0;1;39m" #define ANSI_HIGHLIGHT_RED "\x1B[0;1;31m" #define ANSI_HIGHLIGHT_GREEN "\x1B[0;1;32m" #define ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;33m" #define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m" #define ANSI_HIGHLIGHT_UNDERLINE "\x1B[0;1;4m" #define ANSI_NORMAL "\x1B[0m" #define ANSI_ERASE_TO_END_OF_LINE "\x1B[K" /* Set cursor to top left corner and clear screen */ #define ANSI_HOME_CLEAR "\x1B[H\x1B[2J" int reset_terminal_fd(int fd, bool switch_to_text); int reset_terminal(const char *name); int open_terminal(const char *name, int mode); int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm, usec_t timeout); int release_terminal(void); int terminal_vhangup_fd(int fd); int terminal_vhangup(const char *name); int chvt(int vt); int read_one_char(FILE *f, char *ret, usec_t timeout, bool *need_nl); int ask_char(char *ret, const char *replies, const char *text, ...) _printf_(3, 4); int ask_string(char **ret, const char *text, ...) _printf_(2, 3); int vt_disallocate(const char *name); char *resolve_dev_console(char **active); bool tty_is_vc(const char *tty); bool tty_is_vc_resolve(const char *tty); bool tty_is_console(const char *tty) _pure_; int vtnr_from_tty(const char *tty); const char *default_term_for_tty(const char *tty); int make_stdio(int fd); int make_null_stdio(void); int make_console_stdio(void); int fd_columns(int fd); unsigned columns(void); int fd_lines(int fd); unsigned lines(void); void columns_lines_cache_reset(int _unused_ signum); bool on_tty(void); bool colors_enabled(void); static inline const char *ansi_underline(void) { return colors_enabled() ? ANSI_UNDERLINE : ""; } static inline const char *ansi_highlight(void) { return colors_enabled() ? ANSI_HIGHLIGHT : ""; } static inline const char *ansi_highlight_underline(void) { return colors_enabled() ? ANSI_HIGHLIGHT_UNDERLINE : ""; } static inline const char *ansi_highlight_red(void) { return colors_enabled() ? ANSI_HIGHLIGHT_RED : ""; } static inline const char *ansi_highlight_green(void) { return colors_enabled() ? ANSI_HIGHLIGHT_GREEN : ""; } static inline const char *ansi_highlight_yellow(void) { return colors_enabled() ? ANSI_HIGHLIGHT_YELLOW : ""; } static inline const char *ansi_highlight_blue(void) { return colors_enabled() ? ANSI_HIGHLIGHT_BLUE : ""; } static inline const char *ansi_normal(void) { return colors_enabled() ? ANSI_NORMAL : ""; } int get_ctty_devnr(pid_t pid, dev_t *d); int get_ctty(pid_t, dev_t *_devnr, char **r); int getttyname_malloc(int fd, char **r); int getttyname_harder(int fd, char **r); int ptsname_malloc(int fd, char **ret); int ptsname_namespace(int pty, char **ret); int openpt_in_namespace(pid_t pid, int flags); int open_terminal_in_namespace(pid_t pid, const char *name, int mode); systemd-229/src/basic/time-util.c000066400000000000000000000745601265713322000170220ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "log.h" #include "macro.h" #include "parse-util.h" #include "path-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" static nsec_t timespec_load_nsec(const struct timespec *ts); usec_t now(clockid_t clock_id) { struct timespec ts; assert_se(clock_gettime(clock_id, &ts) == 0); return timespec_load(&ts); } nsec_t now_nsec(clockid_t clock_id) { struct timespec ts; assert_se(clock_gettime(clock_id, &ts) == 0); return timespec_load_nsec(&ts); } dual_timestamp* dual_timestamp_get(dual_timestamp *ts) { assert(ts); ts->realtime = now(CLOCK_REALTIME); ts->monotonic = now(CLOCK_MONOTONIC); return ts; } dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) { int64_t delta; assert(ts); if (u == USEC_INFINITY || u <= 0) { ts->realtime = ts->monotonic = u; return ts; } ts->realtime = u; delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u; ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta); return ts; } dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) { int64_t delta; assert(ts); if (u == USEC_INFINITY) { ts->realtime = ts->monotonic = USEC_INFINITY; return ts; } ts->monotonic = u; delta = (int64_t) now(CLOCK_MONOTONIC) - (int64_t) u; ts->realtime = usec_sub(now(CLOCK_REALTIME), delta); return ts; } dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u) { int64_t delta; if (u == USEC_INFINITY) { ts->realtime = ts->monotonic = USEC_INFINITY; return ts; } dual_timestamp_get(ts); delta = (int64_t) now(clock_boottime_or_monotonic()) - (int64_t) u; ts->realtime = usec_sub(ts->realtime, delta); ts->monotonic = usec_sub(ts->monotonic, delta); return ts; } usec_t timespec_load(const struct timespec *ts) { assert(ts); if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1) return USEC_INFINITY; if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC) return USEC_INFINITY; return (usec_t) ts->tv_sec * USEC_PER_SEC + (usec_t) ts->tv_nsec / NSEC_PER_USEC; } static nsec_t timespec_load_nsec(const struct timespec *ts) { assert(ts); if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1) return NSEC_INFINITY; return (nsec_t) ts->tv_sec * NSEC_PER_SEC + (nsec_t) ts->tv_nsec; } struct timespec *timespec_store(struct timespec *ts, usec_t u) { assert(ts); if (u == USEC_INFINITY) { ts->tv_sec = (time_t) -1; ts->tv_nsec = (long) -1; return ts; } ts->tv_sec = (time_t) (u / USEC_PER_SEC); ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC); return ts; } usec_t timeval_load(const struct timeval *tv) { assert(tv); if (tv->tv_sec == (time_t) -1 && tv->tv_usec == (suseconds_t) -1) return USEC_INFINITY; if ((usec_t) tv->tv_sec > (UINT64_MAX - tv->tv_usec) / USEC_PER_SEC) return USEC_INFINITY; return (usec_t) tv->tv_sec * USEC_PER_SEC + (usec_t) tv->tv_usec; } struct timeval *timeval_store(struct timeval *tv, usec_t u) { assert(tv); if (u == USEC_INFINITY) { tv->tv_sec = (time_t) -1; tv->tv_usec = (suseconds_t) -1; } else { tv->tv_sec = (time_t) (u / USEC_PER_SEC); tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC); } return tv; } static char *format_timestamp_internal(char *buf, size_t l, usec_t t, bool utc, bool us) { struct tm tm; time_t sec; int k; assert(buf); assert(l > 0); if (t <= 0 || t == USEC_INFINITY) return NULL; sec = (time_t) (t / USEC_PER_SEC); localtime_or_gmtime_r(&sec, &tm, utc); if (us) k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S", &tm); else k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S %Z", &tm); if (k <= 0) return NULL; if (us) { snprintf(buf + strlen(buf), l - strlen(buf), ".%06llu", (unsigned long long) (t % USEC_PER_SEC)); if (strftime(buf + strlen(buf), l - strlen(buf), " %Z", &tm) <= 0) return NULL; } return buf; } char *format_timestamp(char *buf, size_t l, usec_t t) { return format_timestamp_internal(buf, l, t, false, false); } char *format_timestamp_utc(char *buf, size_t l, usec_t t) { return format_timestamp_internal(buf, l, t, true, false); } char *format_timestamp_us(char *buf, size_t l, usec_t t) { return format_timestamp_internal(buf, l, t, false, true); } char *format_timestamp_us_utc(char *buf, size_t l, usec_t t) { return format_timestamp_internal(buf, l, t, true, true); } char *format_timestamp_relative(char *buf, size_t l, usec_t t) { const char *s; usec_t n, d; if (t <= 0 || t == USEC_INFINITY) return NULL; n = now(CLOCK_REALTIME); if (n > t) { d = n - t; s = "ago"; } else { d = t - n; s = "left"; } if (d >= USEC_PER_YEAR) snprintf(buf, l, USEC_FMT " years " USEC_FMT " months %s", d / USEC_PER_YEAR, (d % USEC_PER_YEAR) / USEC_PER_MONTH, s); else if (d >= USEC_PER_MONTH) snprintf(buf, l, USEC_FMT " months " USEC_FMT " days %s", d / USEC_PER_MONTH, (d % USEC_PER_MONTH) / USEC_PER_DAY, s); else if (d >= USEC_PER_WEEK) snprintf(buf, l, USEC_FMT " weeks " USEC_FMT " days %s", d / USEC_PER_WEEK, (d % USEC_PER_WEEK) / USEC_PER_DAY, s); else if (d >= 2*USEC_PER_DAY) snprintf(buf, l, USEC_FMT " days %s", d / USEC_PER_DAY, s); else if (d >= 25*USEC_PER_HOUR) snprintf(buf, l, "1 day " USEC_FMT "h %s", (d - USEC_PER_DAY) / USEC_PER_HOUR, s); else if (d >= 6*USEC_PER_HOUR) snprintf(buf, l, USEC_FMT "h %s", d / USEC_PER_HOUR, s); else if (d >= USEC_PER_HOUR) snprintf(buf, l, USEC_FMT "h " USEC_FMT "min %s", d / USEC_PER_HOUR, (d % USEC_PER_HOUR) / USEC_PER_MINUTE, s); else if (d >= 5*USEC_PER_MINUTE) snprintf(buf, l, USEC_FMT "min %s", d / USEC_PER_MINUTE, s); else if (d >= USEC_PER_MINUTE) snprintf(buf, l, USEC_FMT "min " USEC_FMT "s %s", d / USEC_PER_MINUTE, (d % USEC_PER_MINUTE) / USEC_PER_SEC, s); else if (d >= USEC_PER_SEC) snprintf(buf, l, USEC_FMT "s %s", d / USEC_PER_SEC, s); else if (d >= USEC_PER_MSEC) snprintf(buf, l, USEC_FMT "ms %s", d / USEC_PER_MSEC, s); else if (d > 0) snprintf(buf, l, USEC_FMT"us %s", d, s); else snprintf(buf, l, "now"); buf[l-1] = 0; return buf; } char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) { static const struct { const char *suffix; usec_t usec; } table[] = { { "y", USEC_PER_YEAR }, { "month", USEC_PER_MONTH }, { "w", USEC_PER_WEEK }, { "d", USEC_PER_DAY }, { "h", USEC_PER_HOUR }, { "min", USEC_PER_MINUTE }, { "s", USEC_PER_SEC }, { "ms", USEC_PER_MSEC }, { "us", 1 }, }; unsigned i; char *p = buf; bool something = false; assert(buf); assert(l > 0); if (t == USEC_INFINITY) { strncpy(p, "infinity", l-1); p[l-1] = 0; return p; } if (t <= 0) { strncpy(p, "0", l-1); p[l-1] = 0; return p; } /* The result of this function can be parsed with parse_sec */ for (i = 0; i < ELEMENTSOF(table); i++) { int k = 0; size_t n; bool done = false; usec_t a, b; if (t <= 0) break; if (t < accuracy && something) break; if (t < table[i].usec) continue; if (l <= 1) break; a = t / table[i].usec; b = t % table[i].usec; /* Let's see if we should shows this in dot notation */ if (t < USEC_PER_MINUTE && b > 0) { usec_t cc; int j; j = 0; for (cc = table[i].usec; cc > 1; cc /= 10) j++; for (cc = accuracy; cc > 1; cc /= 10) { b /= 10; j--; } if (j > 0) { k = snprintf(p, l, "%s"USEC_FMT".%0*llu%s", p > buf ? " " : "", a, j, (unsigned long long) b, table[i].suffix); t = 0; done = true; } } /* No? Then let's show it normally */ if (!done) { k = snprintf(p, l, "%s"USEC_FMT"%s", p > buf ? " " : "", a, table[i].suffix); t = b; } n = MIN((size_t) k, l); l -= n; p += n; something = true; } *p = 0; return buf; } void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) { assert(f); assert(name); assert(t); if (!dual_timestamp_is_set(t)) return; fprintf(f, "%s="USEC_FMT" "USEC_FMT"\n", name, t->realtime, t->monotonic); } int dual_timestamp_deserialize(const char *value, dual_timestamp *t) { unsigned long long a, b; assert(value); assert(t); if (sscanf(value, "%llu %llu", &a, &b) != 2) { log_debug("Failed to parse finish timestamp value %s.", value); return -EINVAL; } t->realtime = a; t->monotonic = b; return 0; } int parse_timestamp(const char *t, usec_t *usec) { static const struct { const char *name; const int nr; } day_nr[] = { { "Sunday", 0 }, { "Sun", 0 }, { "Monday", 1 }, { "Mon", 1 }, { "Tuesday", 2 }, { "Tue", 2 }, { "Wednesday", 3 }, { "Wed", 3 }, { "Thursday", 4 }, { "Thu", 4 }, { "Friday", 5 }, { "Fri", 5 }, { "Saturday", 6 }, { "Sat", 6 }, }; const char *k; const char *utc; struct tm tm, copy; time_t x; usec_t x_usec, plus = 0, minus = 0, ret; int r, weekday = -1; unsigned i; /* * Allowed syntaxes: * * 2012-09-22 16:34:22 * 2012-09-22 16:34 (seconds will be set to 0) * 2012-09-22 (time will be set to 00:00:00) * 16:34:22 (date will be set to today) * 16:34 (date will be set to today, seconds to 0) * now * yesterday (time is set to 00:00:00) * today (time is set to 00:00:00) * tomorrow (time is set to 00:00:00) * +5min * -5days * @2147483647 (seconds since epoch) * */ assert(t); assert(usec); if (t[0] == '@') return parse_sec(t + 1, usec); ret = now(CLOCK_REALTIME); if (streq(t, "now")) goto finish; else if (t[0] == '+') { r = parse_sec(t+1, &plus); if (r < 0) return r; goto finish; } else if (t[0] == '-') { r = parse_sec(t+1, &minus); if (r < 0) return r; goto finish; } else if ((k = endswith(t, " ago"))) { t = strndupa(t, k - t); r = parse_sec(t, &minus); if (r < 0) return r; goto finish; } else if ((k = endswith(t, " left"))) { t = strndupa(t, k - t); r = parse_sec(t, &plus); if (r < 0) return r; goto finish; } utc = endswith_no_case(t, " UTC"); if (utc) t = strndupa(t, utc - t); x = ret / USEC_PER_SEC; x_usec = 0; assert_se(localtime_or_gmtime_r(&x, &tm, utc)); tm.tm_isdst = -1; if (streq(t, "today")) { tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } else if (streq(t, "yesterday")) { tm.tm_mday --; tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } else if (streq(t, "tomorrow")) { tm.tm_mday ++; tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } for (i = 0; i < ELEMENTSOF(day_nr); i++) { size_t skip; if (!startswith_no_case(t, day_nr[i].name)) continue; skip = strlen(day_nr[i].name); if (t[skip] != ' ') continue; weekday = day_nr[i].nr; t += skip + 1; break; } copy = tm; k = strptime(t, "%y-%m-%d %H:%M:%S", &tm); if (k) { if (*k == '.') goto parse_usec; else if (*k == 0) goto from_tm; } tm = copy; k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm); if (k) { if (*k == '.') goto parse_usec; else if (*k == 0) goto from_tm; } tm = copy; k = strptime(t, "%y-%m-%d %H:%M", &tm); if (k && *k == 0) { tm.tm_sec = 0; goto from_tm; } tm = copy; k = strptime(t, "%Y-%m-%d %H:%M", &tm); if (k && *k == 0) { tm.tm_sec = 0; goto from_tm; } tm = copy; k = strptime(t, "%y-%m-%d", &tm); if (k && *k == 0) { tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } tm = copy; k = strptime(t, "%Y-%m-%d", &tm); if (k && *k == 0) { tm.tm_sec = tm.tm_min = tm.tm_hour = 0; goto from_tm; } tm = copy; k = strptime(t, "%H:%M:%S", &tm); if (k) { if (*k == '.') goto parse_usec; else if (*k == 0) goto from_tm; } tm = copy; k = strptime(t, "%H:%M", &tm); if (k && *k == 0) { tm.tm_sec = 0; goto from_tm; } return -EINVAL; parse_usec: { unsigned add; k++; r = parse_fractional_part_u(&k, 6, &add); if (r < 0) return -EINVAL; if (*k) return -EINVAL; x_usec = add; } from_tm: x = mktime_or_timegm(&tm, utc); if (x == (time_t) -1) return -EINVAL; if (weekday >= 0 && tm.tm_wday != weekday) return -EINVAL; ret = (usec_t) x * USEC_PER_SEC + x_usec; finish: ret += plus; if (ret > minus) ret -= minus; else ret = 0; *usec = ret; return 0; } int parse_time(const char *t, usec_t *usec, usec_t default_unit) { static const struct { const char *suffix; usec_t usec; } table[] = { { "seconds", USEC_PER_SEC }, { "second", USEC_PER_SEC }, { "sec", USEC_PER_SEC }, { "s", USEC_PER_SEC }, { "minutes", USEC_PER_MINUTE }, { "minute", USEC_PER_MINUTE }, { "min", USEC_PER_MINUTE }, { "months", USEC_PER_MONTH }, { "month", USEC_PER_MONTH }, { "M", USEC_PER_MONTH }, { "msec", USEC_PER_MSEC }, { "ms", USEC_PER_MSEC }, { "m", USEC_PER_MINUTE }, { "hours", USEC_PER_HOUR }, { "hour", USEC_PER_HOUR }, { "hr", USEC_PER_HOUR }, { "h", USEC_PER_HOUR }, { "days", USEC_PER_DAY }, { "day", USEC_PER_DAY }, { "d", USEC_PER_DAY }, { "weeks", USEC_PER_WEEK }, { "week", USEC_PER_WEEK }, { "w", USEC_PER_WEEK }, { "years", USEC_PER_YEAR }, { "year", USEC_PER_YEAR }, { "y", USEC_PER_YEAR }, { "usec", 1ULL }, { "us", 1ULL }, }; const char *p, *s; usec_t r = 0; bool something = false; assert(t); assert(usec); assert(default_unit > 0); p = t; p += strspn(p, WHITESPACE); s = startswith(p, "infinity"); if (s) { s += strspn(s, WHITESPACE); if (*s != 0) return -EINVAL; *usec = USEC_INFINITY; return 0; } for (;;) { long long l, z = 0; char *e; unsigned i, n = 0; usec_t multiplier, k; p += strspn(p, WHITESPACE); if (*p == 0) { if (!something) return -EINVAL; break; } errno = 0; l = strtoll(p, &e, 10); if (errno > 0) return -errno; if (l < 0) return -ERANGE; if (*e == '.') { char *b = e + 1; errno = 0; z = strtoll(b, &e, 10); if (errno > 0) return -errno; if (z < 0) return -ERANGE; if (e == b) return -EINVAL; n = e - b; } else if (e == p) return -EINVAL; e += strspn(e, WHITESPACE); for (i = 0; i < ELEMENTSOF(table); i++) if (startswith(e, table[i].suffix)) { multiplier = table[i].usec; p = e + strlen(table[i].suffix); break; } if (i >= ELEMENTSOF(table)) { multiplier = default_unit; p = e; } something = true; k = (usec_t) z * multiplier; for (; n > 0; n--) k /= 10; r += (usec_t) l * multiplier + k; } *usec = r; return 0; } int parse_sec(const char *t, usec_t *usec) { return parse_time(t, usec, USEC_PER_SEC); } int parse_nsec(const char *t, nsec_t *nsec) { static const struct { const char *suffix; nsec_t nsec; } table[] = { { "seconds", NSEC_PER_SEC }, { "second", NSEC_PER_SEC }, { "sec", NSEC_PER_SEC }, { "s", NSEC_PER_SEC }, { "minutes", NSEC_PER_MINUTE }, { "minute", NSEC_PER_MINUTE }, { "min", NSEC_PER_MINUTE }, { "months", NSEC_PER_MONTH }, { "month", NSEC_PER_MONTH }, { "msec", NSEC_PER_MSEC }, { "ms", NSEC_PER_MSEC }, { "m", NSEC_PER_MINUTE }, { "hours", NSEC_PER_HOUR }, { "hour", NSEC_PER_HOUR }, { "hr", NSEC_PER_HOUR }, { "h", NSEC_PER_HOUR }, { "days", NSEC_PER_DAY }, { "day", NSEC_PER_DAY }, { "d", NSEC_PER_DAY }, { "weeks", NSEC_PER_WEEK }, { "week", NSEC_PER_WEEK }, { "w", NSEC_PER_WEEK }, { "years", NSEC_PER_YEAR }, { "year", NSEC_PER_YEAR }, { "y", NSEC_PER_YEAR }, { "usec", NSEC_PER_USEC }, { "us", NSEC_PER_USEC }, { "nsec", 1ULL }, { "ns", 1ULL }, { "", 1ULL }, /* default is nsec */ }; const char *p, *s; nsec_t r = 0; bool something = false; assert(t); assert(nsec); p = t; p += strspn(p, WHITESPACE); s = startswith(p, "infinity"); if (s) { s += strspn(s, WHITESPACE); if (*s != 0) return -EINVAL; *nsec = NSEC_INFINITY; return 0; } for (;;) { long long l, z = 0; char *e; unsigned i, n = 0; p += strspn(p, WHITESPACE); if (*p == 0) { if (!something) return -EINVAL; break; } errno = 0; l = strtoll(p, &e, 10); if (errno > 0) return -errno; if (l < 0) return -ERANGE; if (*e == '.') { char *b = e + 1; errno = 0; z = strtoll(b, &e, 10); if (errno > 0) return -errno; if (z < 0) return -ERANGE; if (e == b) return -EINVAL; n = e - b; } else if (e == p) return -EINVAL; e += strspn(e, WHITESPACE); for (i = 0; i < ELEMENTSOF(table); i++) if (startswith(e, table[i].suffix)) { nsec_t k = (nsec_t) z * table[i].nsec; for (; n > 0; n--) k /= 10; r += (nsec_t) l * table[i].nsec + k; p = e + strlen(table[i].suffix); something = true; break; } if (i >= ELEMENTSOF(table)) return -EINVAL; } *nsec = r; return 0; } bool ntp_synced(void) { struct timex txc = {}; if (adjtimex(&txc) < 0) return false; if (txc.status & STA_UNSYNC) return false; return true; } int get_timezones(char ***ret) { _cleanup_fclose_ FILE *f = NULL; _cleanup_strv_free_ char **zones = NULL; size_t n_zones = 0, n_allocated = 0; assert(ret); zones = strv_new("UTC", NULL); if (!zones) return -ENOMEM; n_allocated = 2; n_zones = 1; f = fopen("/usr/share/zoneinfo/zone.tab", "re"); if (f) { char l[LINE_MAX]; FOREACH_LINE(l, f, return -errno) { char *p, *w; size_t k; p = strstrip(l); if (isempty(p) || *p == '#') continue; /* Skip over country code */ p += strcspn(p, WHITESPACE); p += strspn(p, WHITESPACE); /* Skip over coordinates */ p += strcspn(p, WHITESPACE); p += strspn(p, WHITESPACE); /* Found timezone name */ k = strcspn(p, WHITESPACE); if (k <= 0) continue; w = strndup(p, k); if (!w) return -ENOMEM; if (!GREEDY_REALLOC(zones, n_allocated, n_zones + 2)) { free(w); return -ENOMEM; } zones[n_zones++] = w; zones[n_zones] = NULL; } strv_sort(zones); } else if (errno != ENOENT) return -errno; *ret = zones; zones = NULL; return 0; } bool timezone_is_valid(const char *name) { bool slash = false; const char *p, *t; struct stat st; if (isempty(name)) return false; if (name[0] == '/') return false; for (p = name; *p; p++) { if (!(*p >= '0' && *p <= '9') && !(*p >= 'a' && *p <= 'z') && !(*p >= 'A' && *p <= 'Z') && !(*p == '-' || *p == '_' || *p == '+' || *p == '/')) return false; if (*p == '/') { if (slash) return false; slash = true; } else slash = false; } if (slash) return false; t = strjoina("/usr/share/zoneinfo/", name); if (stat(t, &st) < 0) return false; if (!S_ISREG(st.st_mode)) return false; return true; } clockid_t clock_boottime_or_monotonic(void) { static clockid_t clock = -1; int fd; if (clock != -1) return clock; fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC); if (fd < 0) clock = CLOCK_MONOTONIC; else { safe_close(fd); clock = CLOCK_BOOTTIME; } return clock; } int get_timezone(char **tz) { _cleanup_free_ char *t = NULL; const char *e; char *z; int r; r = readlink_malloc("/etc/localtime", &t); if (r < 0) return r; /* returns EINVAL if not a symlink */ e = path_startswith(t, "/usr/share/zoneinfo/"); if (!e) e = path_startswith(t, "../usr/share/zoneinfo/"); if (!e) return -EINVAL; if (!timezone_is_valid(e)) return -EINVAL; z = strdup(e); if (!z) return -ENOMEM; *tz = z; return 0; } time_t mktime_or_timegm(struct tm *tm, bool utc) { return utc ? timegm(tm) : mktime(tm); } struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc) { return utc ? gmtime_r(t, tm) : localtime_r(t, tm); } unsigned long usec_to_jiffies(usec_t u) { static thread_local unsigned long hz = 0; long r; if (hz == 0) { r = sysconf(_SC_CLK_TCK); assert(r > 0); hz = (unsigned long) r; } return DIV_ROUND_UP(u , USEC_PER_SEC / hz); } systemd-229/src/basic/time-util.h000066400000000000000000000121741265713322000170200ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include typedef uint64_t usec_t; typedef uint64_t nsec_t; #define NSEC_FMT "%" PRIu64 #define USEC_FMT "%" PRIu64 #include "macro.h" typedef struct dual_timestamp { usec_t realtime; usec_t monotonic; } dual_timestamp; #define USEC_INFINITY ((usec_t) -1) #define NSEC_INFINITY ((nsec_t) -1) #define MSEC_PER_SEC 1000ULL #define USEC_PER_SEC ((usec_t) 1000000ULL) #define USEC_PER_MSEC ((usec_t) 1000ULL) #define NSEC_PER_SEC ((nsec_t) 1000000000ULL) #define NSEC_PER_MSEC ((nsec_t) 1000000ULL) #define NSEC_PER_USEC ((nsec_t) 1000ULL) #define USEC_PER_MINUTE ((usec_t) (60ULL*USEC_PER_SEC)) #define NSEC_PER_MINUTE ((nsec_t) (60ULL*NSEC_PER_SEC)) #define USEC_PER_HOUR ((usec_t) (60ULL*USEC_PER_MINUTE)) #define NSEC_PER_HOUR ((nsec_t) (60ULL*NSEC_PER_MINUTE)) #define USEC_PER_DAY ((usec_t) (24ULL*USEC_PER_HOUR)) #define NSEC_PER_DAY ((nsec_t) (24ULL*NSEC_PER_HOUR)) #define USEC_PER_WEEK ((usec_t) (7ULL*USEC_PER_DAY)) #define NSEC_PER_WEEK ((nsec_t) (7ULL*NSEC_PER_DAY)) #define USEC_PER_MONTH ((usec_t) (2629800ULL*USEC_PER_SEC)) #define NSEC_PER_MONTH ((nsec_t) (2629800ULL*NSEC_PER_SEC)) #define USEC_PER_YEAR ((usec_t) (31557600ULL*USEC_PER_SEC)) #define NSEC_PER_YEAR ((nsec_t) (31557600ULL*NSEC_PER_SEC)) #define FORMAT_TIMESTAMP_MAX ((4*4+1)+11+9+4+1) /* weekdays can be unicode */ #define FORMAT_TIMESTAMP_WIDTH 28 /* when outputting, assume this width */ #define FORMAT_TIMESTAMP_RELATIVE_MAX 256 #define FORMAT_TIMESPAN_MAX 64 #define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1) #define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) { 0ULL, 0ULL }) usec_t now(clockid_t clock); nsec_t now_nsec(clockid_t clock); dual_timestamp* dual_timestamp_get(dual_timestamp *ts); dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u); dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u); dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u); static inline bool dual_timestamp_is_set(dual_timestamp *ts) { return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) || (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY)); } usec_t timespec_load(const struct timespec *ts) _pure_; struct timespec *timespec_store(struct timespec *ts, usec_t u); usec_t timeval_load(const struct timeval *tv) _pure_; struct timeval *timeval_store(struct timeval *tv, usec_t u); char *format_timestamp(char *buf, size_t l, usec_t t); char *format_timestamp_utc(char *buf, size_t l, usec_t t); char *format_timestamp_us(char *buf, size_t l, usec_t t); char *format_timestamp_us_utc(char *buf, size_t l, usec_t t); char *format_timestamp_relative(char *buf, size_t l, usec_t t); char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy); void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t); int dual_timestamp_deserialize(const char *value, dual_timestamp *t); int parse_timestamp(const char *t, usec_t *usec); int parse_sec(const char *t, usec_t *usec); int parse_time(const char *t, usec_t *usec, usec_t default_unit); int parse_nsec(const char *t, nsec_t *nsec); bool ntp_synced(void); int get_timezones(char ***l); bool timezone_is_valid(const char *name); clockid_t clock_boottime_or_monotonic(void); #define xstrftime(buf, fmt, tm) \ assert_message_se(strftime(buf, ELEMENTSOF(buf), fmt, tm) > 0, \ "xstrftime: " #buf "[] must be big enough") int get_timezone(char **timezone); time_t mktime_or_timegm(struct tm *tm, bool utc); struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc); unsigned long usec_to_jiffies(usec_t usec); static inline usec_t usec_add(usec_t a, usec_t b) { usec_t c; /* Adds two time values, and makes sure USEC_INFINITY as input results as USEC_INFINITY in output, and doesn't * overflow. */ c = a + b; if (c < a || c < b) /* overflow check */ return USEC_INFINITY; return c; } static inline usec_t usec_sub(usec_t timestamp, int64_t delta) { if (delta < 0) return usec_add(timestamp, (usec_t) (-delta)); if (timestamp == USEC_INFINITY) /* Make sure infinity doesn't degrade */ return USEC_INFINITY; if (timestamp < (usec_t) delta) return 0; return timestamp - delta; } systemd-229/src/basic/umask-util.h000066400000000000000000000025331265713322000172000ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "macro.h" static inline void umaskp(mode_t *u) { umask(*u); } #define _cleanup_umask_ _cleanup_(umaskp) struct _umask_struct_ { mode_t mask; bool quit; }; static inline void _reset_umask_(struct _umask_struct_ *s) { umask(s->mask); }; #define RUN_WITH_UMASK(mask) \ for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \ !_saved_umask_.quit ; \ _saved_umask_.quit = true) systemd-229/src/basic/unaligned.h000066400000000000000000000060321265713322000170510ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include /* BE */ static inline uint16_t unaligned_read_be16(const void *_u) { const uint8_t *u = _u; return (((uint16_t) u[0]) << 8) | ((uint16_t) u[1]); } static inline uint32_t unaligned_read_be32(const void *_u) { const uint8_t *u = _u; return (((uint32_t) unaligned_read_be16(u)) << 16) | ((uint32_t) unaligned_read_be16(u + 2)); } static inline uint64_t unaligned_read_be64(const void *_u) { const uint8_t *u = _u; return (((uint64_t) unaligned_read_be32(u)) << 32) | ((uint64_t) unaligned_read_be32(u + 4)); } static inline void unaligned_write_be16(void *_u, uint16_t a) { uint8_t *u = _u; u[0] = (uint8_t) (a >> 8); u[1] = (uint8_t) a; } static inline void unaligned_write_be32(void *_u, uint32_t a) { uint8_t *u = _u; unaligned_write_be16(u, (uint16_t) (a >> 16)); unaligned_write_be16(u + 2, (uint16_t) a); } static inline void unaligned_write_be64(void *_u, uint64_t a) { uint8_t *u = _u; unaligned_write_be32(u, (uint32_t) (a >> 32)); unaligned_write_be32(u + 4, (uint32_t) a); } /* LE */ static inline uint16_t unaligned_read_le16(const void *_u) { const uint8_t *u = _u; return (((uint16_t) u[1]) << 8) | ((uint16_t) u[0]); } static inline uint32_t unaligned_read_le32(const void *_u) { const uint8_t *u = _u; return (((uint32_t) unaligned_read_le16(u + 2)) << 16) | ((uint32_t) unaligned_read_le16(u)); } static inline uint64_t unaligned_read_le64(const void *_u) { const uint8_t *u = _u; return (((uint64_t) unaligned_read_le32(u + 4)) << 32) | ((uint64_t) unaligned_read_le32(u)); } static inline void unaligned_write_le16(void *_u, uint16_t a) { uint8_t *u = _u; u[0] = (uint8_t) a; u[1] = (uint8_t) (a >> 8); } static inline void unaligned_write_le32(void *_u, uint32_t a) { uint8_t *u = _u; unaligned_write_le16(u, (uint16_t) a); unaligned_write_le16(u + 2, (uint16_t) (a >> 16)); } static inline void unaligned_write_le64(void *_u, uint64_t a) { uint8_t *u = _u; unaligned_write_le32(u, (uint32_t) a); unaligned_write_le32(u + 4, (uint32_t) (a >> 32)); } systemd-229/src/basic/unit-name.c000066400000000000000000000664611265713322000170070ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "bus-label.h" #include "glob-util.h" #include "hexdecoct.h" #include "macro.h" #include "path-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" /* Characters valid in a unit name. */ #define VALID_CHARS \ DIGITS \ LETTERS \ ":-_.\\" /* The same, but also permits the single @ character that may appear */ #define VALID_CHARS_WITH_AT \ "@" \ VALID_CHARS /* All chars valid in a unit name glob */ #define VALID_CHARS_GLOB \ VALID_CHARS_WITH_AT \ "[]!-*?" bool unit_name_is_valid(const char *n, UnitNameFlags flags) { const char *e, *i, *at; assert((flags & ~(UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) == 0); if (_unlikely_(flags == 0)) return false; if (isempty(n)) return false; if (strlen(n) >= UNIT_NAME_MAX) return false; e = strrchr(n, '.'); if (!e || e == n) return false; if (unit_type_from_string(e + 1) < 0) return false; for (i = n, at = NULL; i < e; i++) { if (*i == '@' && !at) at = i; if (!strchr("@" VALID_CHARS, *i)) return false; } if (at == n) return false; if (flags & UNIT_NAME_PLAIN) if (!at) return true; if (flags & UNIT_NAME_INSTANCE) if (at && e > at + 1) return true; if (flags & UNIT_NAME_TEMPLATE) if (at && e == at + 1) return true; return false; } bool unit_prefix_is_valid(const char *p) { /* We don't allow additional @ in the prefix string */ if (isempty(p)) return false; return in_charset(p, VALID_CHARS); } bool unit_instance_is_valid(const char *i) { /* The max length depends on the length of the string, so we * don't really check this here. */ if (isempty(i)) return false; /* We allow additional @ in the instance string, we do not * allow them in the prefix! */ return in_charset(i, "@" VALID_CHARS); } bool unit_suffix_is_valid(const char *s) { if (isempty(s)) return false; if (s[0] != '.') return false; if (unit_type_from_string(s + 1) < 0) return false; return true; } int unit_name_to_prefix(const char *n, char **ret) { const char *p; char *s; assert(n); assert(ret); if (!unit_name_is_valid(n, UNIT_NAME_ANY)) return -EINVAL; p = strchr(n, '@'); if (!p) p = strrchr(n, '.'); assert_se(p); s = strndup(n, p - n); if (!s) return -ENOMEM; *ret = s; return 0; } int unit_name_to_instance(const char *n, char **instance) { const char *p, *d; char *i; assert(n); assert(instance); if (!unit_name_is_valid(n, UNIT_NAME_ANY)) return -EINVAL; /* Everything past the first @ and before the last . is the instance */ p = strchr(n, '@'); if (!p) { *instance = NULL; return 0; } p++; d = strrchr(p, '.'); if (!d) return -EINVAL; i = strndup(p, d-p); if (!i) return -ENOMEM; *instance = i; return 1; } int unit_name_to_prefix_and_instance(const char *n, char **ret) { const char *d; char *s; assert(n); assert(ret); if (!unit_name_is_valid(n, UNIT_NAME_ANY)) return -EINVAL; d = strrchr(n, '.'); if (!d) return -EINVAL; s = strndup(n, d - n); if (!s) return -ENOMEM; *ret = s; return 0; } UnitType unit_name_to_type(const char *n) { const char *e; assert(n); if (!unit_name_is_valid(n, UNIT_NAME_ANY)) return _UNIT_TYPE_INVALID; assert_se(e = strrchr(n, '.')); return unit_type_from_string(e + 1); } int unit_name_change_suffix(const char *n, const char *suffix, char **ret) { char *e, *s; size_t a, b; assert(n); assert(suffix); assert(ret); if (!unit_name_is_valid(n, UNIT_NAME_ANY)) return -EINVAL; if (!unit_suffix_is_valid(suffix)) return -EINVAL; assert_se(e = strrchr(n, '.')); a = e - n; b = strlen(suffix); s = new(char, a + b + 1); if (!s) return -ENOMEM; strcpy(mempcpy(s, n, a), suffix); *ret = s; return 0; } int unit_name_build(const char *prefix, const char *instance, const char *suffix, char **ret) { char *s; assert(prefix); assert(suffix); assert(ret); if (!unit_prefix_is_valid(prefix)) return -EINVAL; if (instance && !unit_instance_is_valid(instance)) return -EINVAL; if (!unit_suffix_is_valid(suffix)) return -EINVAL; if (!instance) s = strappend(prefix, suffix); else s = strjoin(prefix, "@", instance, suffix, NULL); if (!s) return -ENOMEM; *ret = s; return 0; } static char *do_escape_char(char c, char *t) { assert(t); *(t++) = '\\'; *(t++) = 'x'; *(t++) = hexchar(c >> 4); *(t++) = hexchar(c); return t; } static char *do_escape(const char *f, char *t) { assert(f); assert(t); /* do not create units with a leading '.', like for "/.dotdir" mount points */ if (*f == '.') { t = do_escape_char(*f, t); f++; } for (; *f; f++) { if (*f == '/') *(t++) = '-'; else if (*f == '-' || *f == '\\' || !strchr(VALID_CHARS, *f)) t = do_escape_char(*f, t); else *(t++) = *f; } return t; } char *unit_name_escape(const char *f) { char *r, *t; assert(f); r = new(char, strlen(f)*4+1); if (!r) return NULL; t = do_escape(f, r); *t = 0; return r; } int unit_name_unescape(const char *f, char **ret) { _cleanup_free_ char *r = NULL; char *t; assert(f); r = strdup(f); if (!r) return -ENOMEM; for (t = r; *f; f++) { if (*f == '-') *(t++) = '/'; else if (*f == '\\') { int a, b; if (f[1] != 'x') return -EINVAL; a = unhexchar(f[2]); if (a < 0) return -EINVAL; b = unhexchar(f[3]); if (b < 0) return -EINVAL; *(t++) = (char) (((uint8_t) a << 4U) | (uint8_t) b); f += 3; } else *(t++) = *f; } *t = 0; *ret = r; r = NULL; return 0; } int unit_name_path_escape(const char *f, char **ret) { char *p, *s; assert(f); assert(ret); p = strdupa(f); if (!p) return -ENOMEM; path_kill_slashes(p); if (STR_IN_SET(p, "/", "")) s = strdup("-"); else { char *e; if (!path_is_safe(p)) return -EINVAL; /* Truncate trailing slashes */ e = endswith(p, "/"); if (e) *e = 0; /* Truncate leading slashes */ if (p[0] == '/') p++; s = unit_name_escape(p); } if (!s) return -ENOMEM; *ret = s; return 0; } int unit_name_path_unescape(const char *f, char **ret) { char *s; int r; assert(f); if (isempty(f)) return -EINVAL; if (streq(f, "-")) { s = strdup("/"); if (!s) return -ENOMEM; } else { char *w; r = unit_name_unescape(f, &w); if (r < 0) return r; /* Don't accept trailing or leading slashes */ if (startswith(w, "/") || endswith(w, "/")) { free(w); return -EINVAL; } /* Prefix a slash again */ s = strappend("/", w); free(w); if (!s) return -ENOMEM; if (!path_is_safe(s)) { free(s); return -EINVAL; } } if (ret) *ret = s; else free(s); return 0; } int unit_name_replace_instance(const char *f, const char *i, char **ret) { const char *p, *e; char *s; size_t a, b; assert(f); assert(i); assert(ret); if (!unit_name_is_valid(f, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) return -EINVAL; if (!unit_instance_is_valid(i)) return -EINVAL; assert_se(p = strchr(f, '@')); assert_se(e = strrchr(f, '.')); a = p - f; b = strlen(i); s = new(char, a + 1 + b + strlen(e) + 1); if (!s) return -ENOMEM; strcpy(mempcpy(mempcpy(s, f, a + 1), i, b), e); *ret = s; return 0; } int unit_name_template(const char *f, char **ret) { const char *p, *e; char *s; size_t a; assert(f); assert(ret); if (!unit_name_is_valid(f, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) return -EINVAL; assert_se(p = strchr(f, '@')); assert_se(e = strrchr(f, '.')); a = p - f; s = new(char, a + 1 + strlen(e) + 1); if (!s) return -ENOMEM; strcpy(mempcpy(s, f, a + 1), e); *ret = s; return 0; } int unit_name_from_path(const char *path, const char *suffix, char **ret) { _cleanup_free_ char *p = NULL; char *s = NULL; int r; assert(path); assert(suffix); assert(ret); if (!unit_suffix_is_valid(suffix)) return -EINVAL; r = unit_name_path_escape(path, &p); if (r < 0) return r; s = strappend(p, suffix); if (!s) return -ENOMEM; *ret = s; return 0; } int unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix, char **ret) { _cleanup_free_ char *p = NULL; char *s; int r; assert(prefix); assert(path); assert(suffix); assert(ret); if (!unit_prefix_is_valid(prefix)) return -EINVAL; if (!unit_suffix_is_valid(suffix)) return -EINVAL; r = unit_name_path_escape(path, &p); if (r < 0) return r; s = strjoin(prefix, "@", p, suffix, NULL); if (!s) return -ENOMEM; *ret = s; return 0; } int unit_name_to_path(const char *name, char **ret) { _cleanup_free_ char *prefix = NULL; int r; assert(name); r = unit_name_to_prefix(name, &prefix); if (r < 0) return r; return unit_name_path_unescape(prefix, ret); } char *unit_dbus_path_from_name(const char *name) { _cleanup_free_ char *e = NULL; assert(name); e = bus_label_escape(name); if (!e) return NULL; return strappend("/org/freedesktop/systemd1/unit/", e); } int unit_name_from_dbus_path(const char *path, char **name) { const char *e; char *n; e = startswith(path, "/org/freedesktop/systemd1/unit/"); if (!e) return -EINVAL; n = bus_label_unescape(e); if (!n) return -ENOMEM; *name = n; return 0; } const char* unit_dbus_interface_from_type(UnitType t) { static const char *const table[_UNIT_TYPE_MAX] = { [UNIT_SERVICE] = "org.freedesktop.systemd1.Service", [UNIT_SOCKET] = "org.freedesktop.systemd1.Socket", [UNIT_BUSNAME] = "org.freedesktop.systemd1.BusName", [UNIT_TARGET] = "org.freedesktop.systemd1.Target", [UNIT_DEVICE] = "org.freedesktop.systemd1.Device", [UNIT_MOUNT] = "org.freedesktop.systemd1.Mount", [UNIT_AUTOMOUNT] = "org.freedesktop.systemd1.Automount", [UNIT_SWAP] = "org.freedesktop.systemd1.Swap", [UNIT_TIMER] = "org.freedesktop.systemd1.Timer", [UNIT_PATH] = "org.freedesktop.systemd1.Path", [UNIT_SLICE] = "org.freedesktop.systemd1.Slice", [UNIT_SCOPE] = "org.freedesktop.systemd1.Scope", }; if (t < 0) return NULL; if (t >= _UNIT_TYPE_MAX) return NULL; return table[t]; } const char *unit_dbus_interface_from_name(const char *name) { UnitType t; t = unit_name_to_type(name); if (t < 0) return NULL; return unit_dbus_interface_from_type(t); } static char *do_escape_mangle(const char *f, UnitNameMangle allow_globs, char *t) { const char *valid_chars; assert(f); assert(IN_SET(allow_globs, UNIT_NAME_GLOB, UNIT_NAME_NOGLOB)); assert(t); /* We'll only escape the obvious characters here, to play * safe. */ valid_chars = allow_globs == UNIT_NAME_GLOB ? VALID_CHARS_GLOB : VALID_CHARS_WITH_AT; for (; *f; f++) { if (*f == '/') *(t++) = '-'; else if (!strchr(valid_chars, *f)) t = do_escape_char(*f, t); else *(t++) = *f; } return t; } /** * Convert a string to a unit name. /dev/blah is converted to dev-blah.device, * /blah/blah is converted to blah-blah.mount, anything else is left alone, * except that @suffix is appended if a valid unit suffix is not present. * * If @allow_globs, globs characters are preserved. Otherwise, they are escaped. */ int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, const char *suffix, char **ret) { char *s, *t; int r; assert(name); assert(suffix); assert(ret); if (isempty(name)) /* We cannot mangle empty unit names to become valid, sorry. */ return -EINVAL; if (!unit_suffix_is_valid(suffix)) return -EINVAL; /* Already a fully valid unit name? If so, no mangling is necessary... */ if (unit_name_is_valid(name, UNIT_NAME_ANY)) goto good; /* Already a fully valid globbing expression? If so, no mangling is necessary either... */ if (allow_globs == UNIT_NAME_GLOB && string_is_glob(name) && in_charset(name, VALID_CHARS_GLOB)) goto good; if (is_device_path(name)) { r = unit_name_from_path(name, ".device", ret); if (r >= 0) return 1; if (r != -EINVAL) return r; } if (path_is_absolute(name)) { r = unit_name_from_path(name, ".mount", ret); if (r >= 0) return 1; if (r != -EINVAL) return r; } s = new(char, strlen(name) * 4 + strlen(suffix) + 1); if (!s) return -ENOMEM; t = do_escape_mangle(name, allow_globs, s); *t = 0; /* Append a suffix if it doesn't have any, but only if this is not a glob, so that we can allow "foo.*" as a * valid glob. */ if ((allow_globs != UNIT_NAME_GLOB || !string_is_glob(s)) && unit_name_to_type(s) < 0) strcpy(t, suffix); *ret = s; return 1; good: s = strdup(name); if (!s) return -ENOMEM; *ret = s; return 0; } int slice_build_parent_slice(const char *slice, char **ret) { char *s, *dash; int r; assert(slice); assert(ret); if (!slice_name_is_valid(slice)) return -EINVAL; if (streq(slice, "-.slice")) { *ret = NULL; return 0; } s = strdup(slice); if (!s) return -ENOMEM; dash = strrchr(s, '-'); if (dash) strcpy(dash, ".slice"); else { r = free_and_strdup(&s, "-.slice"); if (r < 0) { free(s); return r; } } *ret = s; return 1; } int slice_build_subslice(const char *slice, const char*name, char **ret) { char *subslice; assert(slice); assert(name); assert(ret); if (!slice_name_is_valid(slice)) return -EINVAL; if (!unit_prefix_is_valid(name)) return -EINVAL; if (streq(slice, "-.slice")) subslice = strappend(name, ".slice"); else { char *e; assert_se(e = endswith(slice, ".slice")); subslice = new(char, (e - slice) + 1 + strlen(name) + 6 + 1); if (!subslice) return -ENOMEM; stpcpy(stpcpy(stpcpy(mempcpy(subslice, slice, e - slice), "-"), name), ".slice"); } *ret = subslice; return 0; } bool slice_name_is_valid(const char *name) { const char *p, *e; bool dash = false; if (!unit_name_is_valid(name, UNIT_NAME_PLAIN)) return false; if (streq(name, "-.slice")) return true; e = endswith(name, ".slice"); if (!e) return false; for (p = name; p < e; p++) { if (*p == '-') { /* Don't allow initial dash */ if (p == name) return false; /* Don't allow multiple dashes */ if (dash) return false; dash = true; } else dash = false; } /* Don't allow trailing hash */ if (dash) return false; return true; } static const char* const unit_type_table[_UNIT_TYPE_MAX] = { [UNIT_SERVICE] = "service", [UNIT_SOCKET] = "socket", [UNIT_BUSNAME] = "busname", [UNIT_TARGET] = "target", [UNIT_DEVICE] = "device", [UNIT_MOUNT] = "mount", [UNIT_AUTOMOUNT] = "automount", [UNIT_SWAP] = "swap", [UNIT_TIMER] = "timer", [UNIT_PATH] = "path", [UNIT_SLICE] = "slice", [UNIT_SCOPE] = "scope", }; DEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType); static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = { [UNIT_STUB] = "stub", [UNIT_LOADED] = "loaded", [UNIT_NOT_FOUND] = "not-found", [UNIT_ERROR] = "error", [UNIT_MERGED] = "merged", [UNIT_MASKED] = "masked" }; DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState); static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = { [UNIT_ACTIVE] = "active", [UNIT_RELOADING] = "reloading", [UNIT_INACTIVE] = "inactive", [UNIT_FAILED] = "failed", [UNIT_ACTIVATING] = "activating", [UNIT_DEACTIVATING] = "deactivating" }; DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState); static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = { [AUTOMOUNT_DEAD] = "dead", [AUTOMOUNT_WAITING] = "waiting", [AUTOMOUNT_RUNNING] = "running", [AUTOMOUNT_FAILED] = "failed" }; DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState); static const char* const busname_state_table[_BUSNAME_STATE_MAX] = { [BUSNAME_DEAD] = "dead", [BUSNAME_MAKING] = "making", [BUSNAME_REGISTERED] = "registered", [BUSNAME_LISTENING] = "listening", [BUSNAME_RUNNING] = "running", [BUSNAME_SIGTERM] = "sigterm", [BUSNAME_SIGKILL] = "sigkill", [BUSNAME_FAILED] = "failed", }; DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState); static const char* const device_state_table[_DEVICE_STATE_MAX] = { [DEVICE_DEAD] = "dead", [DEVICE_TENTATIVE] = "tentative", [DEVICE_PLUGGED] = "plugged", }; DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState); static const char* const mount_state_table[_MOUNT_STATE_MAX] = { [MOUNT_DEAD] = "dead", [MOUNT_MOUNTING] = "mounting", [MOUNT_MOUNTING_DONE] = "mounting-done", [MOUNT_MOUNTED] = "mounted", [MOUNT_REMOUNTING] = "remounting", [MOUNT_UNMOUNTING] = "unmounting", [MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm", [MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill", [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm", [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill", [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm", [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill", [MOUNT_FAILED] = "failed" }; DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState); static const char* const path_state_table[_PATH_STATE_MAX] = { [PATH_DEAD] = "dead", [PATH_WAITING] = "waiting", [PATH_RUNNING] = "running", [PATH_FAILED] = "failed" }; DEFINE_STRING_TABLE_LOOKUP(path_state, PathState); static const char* const scope_state_table[_SCOPE_STATE_MAX] = { [SCOPE_DEAD] = "dead", [SCOPE_RUNNING] = "running", [SCOPE_ABANDONED] = "abandoned", [SCOPE_STOP_SIGTERM] = "stop-sigterm", [SCOPE_STOP_SIGKILL] = "stop-sigkill", [SCOPE_FAILED] = "failed", }; DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState); static const char* const service_state_table[_SERVICE_STATE_MAX] = { [SERVICE_DEAD] = "dead", [SERVICE_START_PRE] = "start-pre", [SERVICE_START] = "start", [SERVICE_START_POST] = "start-post", [SERVICE_RUNNING] = "running", [SERVICE_EXITED] = "exited", [SERVICE_RELOAD] = "reload", [SERVICE_STOP] = "stop", [SERVICE_STOP_SIGABRT] = "stop-sigabrt", [SERVICE_STOP_SIGTERM] = "stop-sigterm", [SERVICE_STOP_SIGKILL] = "stop-sigkill", [SERVICE_STOP_POST] = "stop-post", [SERVICE_FINAL_SIGTERM] = "final-sigterm", [SERVICE_FINAL_SIGKILL] = "final-sigkill", [SERVICE_FAILED] = "failed", [SERVICE_AUTO_RESTART] = "auto-restart", }; DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState); static const char* const slice_state_table[_SLICE_STATE_MAX] = { [SLICE_DEAD] = "dead", [SLICE_ACTIVE] = "active" }; DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState); static const char* const socket_state_table[_SOCKET_STATE_MAX] = { [SOCKET_DEAD] = "dead", [SOCKET_START_PRE] = "start-pre", [SOCKET_START_CHOWN] = "start-chown", [SOCKET_START_POST] = "start-post", [SOCKET_LISTENING] = "listening", [SOCKET_RUNNING] = "running", [SOCKET_STOP_PRE] = "stop-pre", [SOCKET_STOP_PRE_SIGTERM] = "stop-pre-sigterm", [SOCKET_STOP_PRE_SIGKILL] = "stop-pre-sigkill", [SOCKET_STOP_POST] = "stop-post", [SOCKET_FINAL_SIGTERM] = "final-sigterm", [SOCKET_FINAL_SIGKILL] = "final-sigkill", [SOCKET_FAILED] = "failed" }; DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState); static const char* const swap_state_table[_SWAP_STATE_MAX] = { [SWAP_DEAD] = "dead", [SWAP_ACTIVATING] = "activating", [SWAP_ACTIVATING_DONE] = "activating-done", [SWAP_ACTIVE] = "active", [SWAP_DEACTIVATING] = "deactivating", [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm", [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill", [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm", [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill", [SWAP_FAILED] = "failed" }; DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState); static const char* const target_state_table[_TARGET_STATE_MAX] = { [TARGET_DEAD] = "dead", [TARGET_ACTIVE] = "active" }; DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState); static const char* const timer_state_table[_TIMER_STATE_MAX] = { [TIMER_DEAD] = "dead", [TIMER_WAITING] = "waiting", [TIMER_RUNNING] = "running", [TIMER_ELAPSED] = "elapsed", [TIMER_FAILED] = "failed" }; DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState); static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = { [UNIT_REQUIRES] = "Requires", [UNIT_REQUISITE] = "Requisite", [UNIT_WANTS] = "Wants", [UNIT_BINDS_TO] = "BindsTo", [UNIT_PART_OF] = "PartOf", [UNIT_REQUIRED_BY] = "RequiredBy", [UNIT_REQUISITE_OF] = "RequisiteOf", [UNIT_WANTED_BY] = "WantedBy", [UNIT_BOUND_BY] = "BoundBy", [UNIT_CONSISTS_OF] = "ConsistsOf", [UNIT_CONFLICTS] = "Conflicts", [UNIT_CONFLICTED_BY] = "ConflictedBy", [UNIT_BEFORE] = "Before", [UNIT_AFTER] = "After", [UNIT_ON_FAILURE] = "OnFailure", [UNIT_TRIGGERS] = "Triggers", [UNIT_TRIGGERED_BY] = "TriggeredBy", [UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo", [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom", [UNIT_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf", [UNIT_REFERENCES] = "References", [UNIT_REFERENCED_BY] = "ReferencedBy", }; DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency); systemd-229/src/basic/unit-name.h000066400000000000000000000267271265713322000170150ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" #define UNIT_NAME_MAX 256 typedef enum UnitType { UNIT_SERVICE = 0, UNIT_SOCKET, UNIT_BUSNAME, UNIT_TARGET, UNIT_DEVICE, UNIT_MOUNT, UNIT_AUTOMOUNT, UNIT_SWAP, UNIT_TIMER, UNIT_PATH, UNIT_SLICE, UNIT_SCOPE, _UNIT_TYPE_MAX, _UNIT_TYPE_INVALID = -1 } UnitType; typedef enum UnitLoadState { UNIT_STUB = 0, UNIT_LOADED, UNIT_NOT_FOUND, UNIT_ERROR, UNIT_MERGED, UNIT_MASKED, _UNIT_LOAD_STATE_MAX, _UNIT_LOAD_STATE_INVALID = -1 } UnitLoadState; typedef enum UnitActiveState { UNIT_ACTIVE, UNIT_RELOADING, UNIT_INACTIVE, UNIT_FAILED, UNIT_ACTIVATING, UNIT_DEACTIVATING, _UNIT_ACTIVE_STATE_MAX, _UNIT_ACTIVE_STATE_INVALID = -1 } UnitActiveState; typedef enum AutomountState { AUTOMOUNT_DEAD, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING, AUTOMOUNT_FAILED, _AUTOMOUNT_STATE_MAX, _AUTOMOUNT_STATE_INVALID = -1 } AutomountState; typedef enum BusNameState { BUSNAME_DEAD, BUSNAME_MAKING, BUSNAME_REGISTERED, BUSNAME_LISTENING, BUSNAME_RUNNING, BUSNAME_SIGTERM, BUSNAME_SIGKILL, BUSNAME_FAILED, _BUSNAME_STATE_MAX, _BUSNAME_STATE_INVALID = -1 } BusNameState; /* We simply watch devices, we cannot plug/unplug them. That * simplifies the state engine greatly */ typedef enum DeviceState { DEVICE_DEAD, DEVICE_TENTATIVE, /* mounted or swapped, but not (yet) announced by udev */ DEVICE_PLUGGED, /* announced by udev */ _DEVICE_STATE_MAX, _DEVICE_STATE_INVALID = -1 } DeviceState; typedef enum MountState { MOUNT_DEAD, MOUNT_MOUNTING, /* /usr/bin/mount is running, but the mount is not done yet. */ MOUNT_MOUNTING_DONE, /* /usr/bin/mount is running, and the mount is done. */ MOUNT_MOUNTED, MOUNT_REMOUNTING, MOUNT_UNMOUNTING, MOUNT_MOUNTING_SIGTERM, MOUNT_MOUNTING_SIGKILL, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL, MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILED, _MOUNT_STATE_MAX, _MOUNT_STATE_INVALID = -1 } MountState; typedef enum PathState { PATH_DEAD, PATH_WAITING, PATH_RUNNING, PATH_FAILED, _PATH_STATE_MAX, _PATH_STATE_INVALID = -1 } PathState; typedef enum ScopeState { SCOPE_DEAD, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL, SCOPE_FAILED, _SCOPE_STATE_MAX, _SCOPE_STATE_INVALID = -1 } ScopeState; typedef enum ServiceState { SERVICE_DEAD, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_EXITED, /* Nothing is running anymore, but RemainAfterExit is true hence this is OK */ SERVICE_RELOAD, SERVICE_STOP, /* No STOP_PRE state, instead just register multiple STOP executables */ SERVICE_STOP_SIGABRT, /* Watchdog timeout */ SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, /* In case the STOP_POST executable hangs, we shoot that down, too */ SERVICE_FINAL_SIGKILL, SERVICE_FAILED, SERVICE_AUTO_RESTART, _SERVICE_STATE_MAX, _SERVICE_STATE_INVALID = -1 } ServiceState; typedef enum SliceState { SLICE_DEAD, SLICE_ACTIVE, _SLICE_STATE_MAX, _SLICE_STATE_INVALID = -1 } SliceState; typedef enum SocketState { SOCKET_DEAD, SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING, SOCKET_RUNNING, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM, SOCKET_FINAL_SIGKILL, SOCKET_FAILED, _SOCKET_STATE_MAX, _SOCKET_STATE_INVALID = -1 } SocketState; typedef enum SwapState { SWAP_DEAD, SWAP_ACTIVATING, /* /sbin/swapon is running, but the swap not yet enabled. */ SWAP_ACTIVATING_DONE, /* /sbin/swapon is running, and the swap is done. */ SWAP_ACTIVE, SWAP_DEACTIVATING, SWAP_ACTIVATING_SIGTERM, SWAP_ACTIVATING_SIGKILL, SWAP_DEACTIVATING_SIGTERM, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILED, _SWAP_STATE_MAX, _SWAP_STATE_INVALID = -1 } SwapState; typedef enum TargetState { TARGET_DEAD, TARGET_ACTIVE, _TARGET_STATE_MAX, _TARGET_STATE_INVALID = -1 } TargetState; typedef enum TimerState { TIMER_DEAD, TIMER_WAITING, TIMER_RUNNING, TIMER_ELAPSED, TIMER_FAILED, _TIMER_STATE_MAX, _TIMER_STATE_INVALID = -1 } TimerState; typedef enum UnitDependency { /* Positive dependencies */ UNIT_REQUIRES, UNIT_REQUISITE, UNIT_WANTS, UNIT_BINDS_TO, UNIT_PART_OF, /* Inverse of the above */ UNIT_REQUIRED_BY, /* inverse of 'requires' is 'required_by' */ UNIT_REQUISITE_OF, /* inverse of 'requisite' is 'requisite_of' */ UNIT_WANTED_BY, /* inverse of 'wants' */ UNIT_BOUND_BY, /* inverse of 'binds_to' */ UNIT_CONSISTS_OF, /* inverse of 'part_of' */ /* Negative dependencies */ UNIT_CONFLICTS, /* inverse of 'conflicts' is 'conflicted_by' */ UNIT_CONFLICTED_BY, /* Order */ UNIT_BEFORE, /* inverse of 'before' is 'after' and vice versa */ UNIT_AFTER, /* On Failure */ UNIT_ON_FAILURE, /* Triggers (i.e. a socket triggers a service) */ UNIT_TRIGGERS, UNIT_TRIGGERED_BY, /* Propagate reloads */ UNIT_PROPAGATES_RELOAD_TO, UNIT_RELOAD_PROPAGATED_FROM, /* Joins namespace of */ UNIT_JOINS_NAMESPACE_OF, /* Reference information for GC logic */ UNIT_REFERENCES, /* Inverse of 'references' is 'referenced_by' */ UNIT_REFERENCED_BY, _UNIT_DEPENDENCY_MAX, _UNIT_DEPENDENCY_INVALID = -1 } UnitDependency; typedef enum UnitNameFlags { UNIT_NAME_PLAIN = 1, /* Allow foo.service */ UNIT_NAME_INSTANCE = 2, /* Allow foo@bar.service */ UNIT_NAME_TEMPLATE = 4, /* Allow foo@.service */ UNIT_NAME_ANY = UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE, } UnitNameFlags; bool unit_name_is_valid(const char *n, UnitNameFlags flags) _pure_; bool unit_prefix_is_valid(const char *p) _pure_; bool unit_instance_is_valid(const char *i) _pure_; bool unit_suffix_is_valid(const char *s) _pure_; static inline int unit_prefix_and_instance_is_valid(const char *p) { /* For prefix+instance and instance the same rules apply */ return unit_instance_is_valid(p); } int unit_name_to_prefix(const char *n, char **prefix); int unit_name_to_instance(const char *n, char **instance); int unit_name_to_prefix_and_instance(const char *n, char **ret); UnitType unit_name_to_type(const char *n) _pure_; int unit_name_change_suffix(const char *n, const char *suffix, char **ret); int unit_name_build(const char *prefix, const char *instance, const char *suffix, char **ret); char *unit_name_escape(const char *f); int unit_name_unescape(const char *f, char **ret); int unit_name_path_escape(const char *f, char **ret); int unit_name_path_unescape(const char *f, char **ret); int unit_name_replace_instance(const char *f, const char *i, char **ret); int unit_name_template(const char *f, char **ret); int unit_name_from_path(const char *path, const char *suffix, char **ret); int unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix, char **ret); int unit_name_to_path(const char *name, char **ret); char *unit_dbus_path_from_name(const char *name); int unit_name_from_dbus_path(const char *path, char **name); const char* unit_dbus_interface_from_type(UnitType t); const char *unit_dbus_interface_from_name(const char *name); typedef enum UnitNameMangle { UNIT_NAME_NOGLOB, UNIT_NAME_GLOB, } UnitNameMangle; int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, const char *suffix, char **ret); static inline int unit_name_mangle(const char *name, UnitNameMangle allow_globs, char **ret) { return unit_name_mangle_with_suffix(name, allow_globs, ".service", ret); } int slice_build_parent_slice(const char *slice, char **ret); int slice_build_subslice(const char *slice, const char*name, char **subslice); bool slice_name_is_valid(const char *name); const char *unit_type_to_string(UnitType i) _const_; UnitType unit_type_from_string(const char *s) _pure_; const char *unit_load_state_to_string(UnitLoadState i) _const_; UnitLoadState unit_load_state_from_string(const char *s) _pure_; const char *unit_active_state_to_string(UnitActiveState i) _const_; UnitActiveState unit_active_state_from_string(const char *s) _pure_; const char* automount_state_to_string(AutomountState i) _const_; AutomountState automount_state_from_string(const char *s) _pure_; const char* busname_state_to_string(BusNameState i) _const_; BusNameState busname_state_from_string(const char *s) _pure_; const char* device_state_to_string(DeviceState i) _const_; DeviceState device_state_from_string(const char *s) _pure_; const char* mount_state_to_string(MountState i) _const_; MountState mount_state_from_string(const char *s) _pure_; const char* path_state_to_string(PathState i) _const_; PathState path_state_from_string(const char *s) _pure_; const char* scope_state_to_string(ScopeState i) _const_; ScopeState scope_state_from_string(const char *s) _pure_; const char* service_state_to_string(ServiceState i) _const_; ServiceState service_state_from_string(const char *s) _pure_; const char* slice_state_to_string(SliceState i) _const_; SliceState slice_state_from_string(const char *s) _pure_; const char* socket_state_to_string(SocketState i) _const_; SocketState socket_state_from_string(const char *s) _pure_; const char* swap_state_to_string(SwapState i) _const_; SwapState swap_state_from_string(const char *s) _pure_; const char* target_state_to_string(TargetState i) _const_; TargetState target_state_from_string(const char *s) _pure_; const char *timer_state_to_string(TimerState i) _const_; TimerState timer_state_from_string(const char *s) _pure_; const char *unit_dependency_to_string(UnitDependency i) _const_; UnitDependency unit_dependency_from_string(const char *s) _pure_; systemd-229/src/basic/user-util.c000066400000000000000000000270411265713322000170320ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "macro.h" #include "parse-util.h" #include "path-util.h" #include "string-util.h" #include "user-util.h" bool uid_is_valid(uid_t uid) { /* Some libc APIs use UID_INVALID as special placeholder */ if (uid == (uid_t) UINT32_C(0xFFFFFFFF)) return false; /* A long time ago UIDs where 16bit, hence explicitly avoid the 16bit -1 too */ if (uid == (uid_t) UINT32_C(0xFFFF)) return false; return true; } int parse_uid(const char *s, uid_t *ret) { uint32_t uid = 0; int r; assert(s); assert_cc(sizeof(uid_t) == sizeof(uint32_t)); r = safe_atou32(s, &uid); if (r < 0) return r; if (!uid_is_valid(uid)) return -ENXIO; /* we return ENXIO instead of EINVAL * here, to make it easy to distuingish * invalid numeric uids from invalid * strings. */ if (ret) *ret = uid; return 0; } char* getlogname_malloc(void) { uid_t uid; struct stat st; if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0) uid = st.st_uid; else uid = getuid(); return uid_to_name(uid); } char *getusername_malloc(void) { const char *e; e = getenv("USER"); if (e) return strdup(e); return uid_to_name(getuid()); } int get_user_creds( const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell) { struct passwd *p; uid_t u; assert(username); assert(*username); /* We enforce some special rules for uid=0: in order to avoid * NSS lookups for root we hardcode its data. */ if (streq(*username, "root") || streq(*username, "0")) { *username = "root"; if (uid) *uid = 0; if (gid) *gid = 0; if (home) *home = "/root"; if (shell) *shell = "/bin/sh"; return 0; } if (parse_uid(*username, &u) >= 0) { errno = 0; p = getpwuid(u); /* If there are multiple users with the same id, make * sure to leave $USER to the configured value instead * of the first occurrence in the database. However if * the uid was configured by a numeric uid, then let's * pick the real username from /etc/passwd. */ if (p) *username = p->pw_name; } else { errno = 0; p = getpwnam(*username); } if (!p) return errno > 0 ? -errno : -ESRCH; if (uid) { if (!uid_is_valid(p->pw_uid)) return -EBADMSG; *uid = p->pw_uid; } if (gid) { if (!gid_is_valid(p->pw_gid)) return -EBADMSG; *gid = p->pw_gid; } if (home) *home = p->pw_dir; if (shell) *shell = p->pw_shell; return 0; } int get_group_creds(const char **groupname, gid_t *gid) { struct group *g; gid_t id; assert(groupname); /* We enforce some special rules for gid=0: in order to avoid * NSS lookups for root we hardcode its data. */ if (streq(*groupname, "root") || streq(*groupname, "0")) { *groupname = "root"; if (gid) *gid = 0; return 0; } if (parse_gid(*groupname, &id) >= 0) { errno = 0; g = getgrgid(id); if (g) *groupname = g->gr_name; } else { errno = 0; g = getgrnam(*groupname); } if (!g) return errno > 0 ? -errno : -ESRCH; if (gid) { if (!gid_is_valid(g->gr_gid)) return -EBADMSG; *gid = g->gr_gid; } return 0; } char* uid_to_name(uid_t uid) { char *ret; int r; /* Shortcut things to avoid NSS lookups */ if (uid == 0) return strdup("root"); if (uid_is_valid(uid)) { long bufsize; bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); if (bufsize <= 0) bufsize = 4096; for (;;) { struct passwd pwbuf, *pw = NULL; _cleanup_free_ char *buf = NULL; buf = malloc(bufsize); if (!buf) return NULL; r = getpwuid_r(uid, &pwbuf, buf, (size_t) bufsize, &pw); if (r == 0 && pw) return strdup(pw->pw_name); if (r != ERANGE) break; bufsize *= 2; } } if (asprintf(&ret, UID_FMT, uid) < 0) return NULL; return ret; } char* gid_to_name(gid_t gid) { char *ret; int r; if (gid == 0) return strdup("root"); if (gid_is_valid(gid)) { long bufsize; bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); if (bufsize <= 0) bufsize = 4096; for (;;) { struct group grbuf, *gr = NULL; _cleanup_free_ char *buf = NULL; buf = malloc(bufsize); if (!buf) return NULL; r = getgrgid_r(gid, &grbuf, buf, (size_t) bufsize, &gr); if (r == 0 && gr) return strdup(gr->gr_name); if (r != ERANGE) break; bufsize *= 2; } } if (asprintf(&ret, GID_FMT, gid) < 0) return NULL; return ret; } int in_gid(gid_t gid) { gid_t *gids; int ngroups_max, r, i; if (getgid() == gid) return 1; if (getegid() == gid) return 1; if (!gid_is_valid(gid)) return -EINVAL; ngroups_max = sysconf(_SC_NGROUPS_MAX); assert(ngroups_max > 0); gids = alloca(sizeof(gid_t) * ngroups_max); r = getgroups(ngroups_max, gids); if (r < 0) return -errno; for (i = 0; i < r; i++) if (gids[i] == gid) return 1; return 0; } int in_group(const char *name) { int r; gid_t gid; r = get_group_creds(&name, &gid); if (r < 0) return r; return in_gid(gid); } int get_home_dir(char **_h) { struct passwd *p; const char *e; char *h; uid_t u; assert(_h); /* Take the user specified one */ e = secure_getenv("HOME"); if (e && path_is_absolute(e)) { h = strdup(e); if (!h) return -ENOMEM; *_h = h; return 0; } /* Hardcode home directory for root to avoid NSS */ u = getuid(); if (u == 0) { h = strdup("/root"); if (!h) return -ENOMEM; *_h = h; return 0; } /* Check the database... */ errno = 0; p = getpwuid(u); if (!p) return errno > 0 ? -errno : -ESRCH; if (!path_is_absolute(p->pw_dir)) return -EINVAL; h = strdup(p->pw_dir); if (!h) return -ENOMEM; *_h = h; return 0; } int get_shell(char **_s) { struct passwd *p; const char *e; char *s; uid_t u; assert(_s); /* Take the user specified one */ e = getenv("SHELL"); if (e) { s = strdup(e); if (!s) return -ENOMEM; *_s = s; return 0; } /* Hardcode home directory for root to avoid NSS */ u = getuid(); if (u == 0) { s = strdup("/bin/sh"); if (!s) return -ENOMEM; *_s = s; return 0; } /* Check the database... */ errno = 0; p = getpwuid(u); if (!p) return errno > 0 ? -errno : -ESRCH; if (!path_is_absolute(p->pw_shell)) return -EINVAL; s = strdup(p->pw_shell); if (!s) return -ENOMEM; *_s = s; return 0; } int reset_uid_gid(void) { if (setgroups(0, NULL) < 0) return -errno; if (setresgid(0, 0, 0) < 0) return -errno; if (setresuid(0, 0, 0) < 0) return -errno; return 0; } int take_etc_passwd_lock(const char *root) { struct flock flock = { .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0, }; const char *path; int fd, r; /* This is roughly the same as lckpwdf(), but not as awful. We * don't want to use alarm() and signals, hence we implement * our own trivial version of this. * * Note that shadow-utils also takes per-database locks in * addition to lckpwdf(). However, we don't given that they * are redundant as they they invoke lckpwdf() first and keep * it during everything they do. The per-database locks are * awfully racy, and thus we just won't do them. */ if (root) path = prefix_roota(root, "/etc/.pwd.lock"); else path = "/etc/.pwd.lock"; fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600); if (fd < 0) return -errno; r = fcntl(fd, F_SETLKW, &flock); if (r < 0) { safe_close(fd); return -errno; } return fd; } systemd-229/src/basic/user-util.h000066400000000000000000000036221265713322000170360ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include bool uid_is_valid(uid_t uid); static inline bool gid_is_valid(gid_t gid) { return uid_is_valid((uid_t) gid); } int parse_uid(const char *s, uid_t* ret_uid); static inline int parse_gid(const char *s, gid_t *ret_gid) { return parse_uid(s, (uid_t*) ret_gid); } char* getlogname_malloc(void); char* getusername_malloc(void); int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell); int get_group_creds(const char **groupname, gid_t *gid); char* uid_to_name(uid_t uid); char* gid_to_name(gid_t gid); int in_gid(gid_t gid); int in_group(const char *name); int get_home_dir(char **ret); int get_shell(char **_ret); int reset_uid_gid(void); int take_etc_passwd_lock(const char *root); #define UID_INVALID ((uid_t) -1) #define GID_INVALID ((gid_t) -1) /* The following macros add 1 when converting things, since UID 0 is a * valid UID, while the pointer NULL is special */ #define PTR_TO_UID(p) ((uid_t) (((uintptr_t) (p))-1)) #define UID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1)) #define PTR_TO_GID(p) ((gid_t) (((uintptr_t) (p))-1)) #define GID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1)) systemd-229/src/basic/utf8.c000066400000000000000000000263311265713322000157700ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2011 Kay Sievers Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* Parts of this file are based on the GLIB utf8 validation functions. The * original license text follows. */ /* gutf8.c - Operations on UTF-8 strings. * * Copyright (C) 1999 Tom Tromey * Copyright (C) 2000 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include "alloc-util.h" #include "hexdecoct.h" #include "macro.h" #include "utf8.h" bool unichar_is_valid(char32_t ch) { if (ch >= 0x110000) /* End of unicode space */ return false; if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */ return false; if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */ return false; if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */ return false; return true; } static bool unichar_is_control(char32_t ch) { /* 0 to ' '-1 is the C0 range. DEL=0x7F, and DEL+1 to 0x9F is C1 range. '\t' is in C0 range, but more or less harmless and commonly used. */ return (ch < ' ' && ch != '\t' && ch != '\n') || (0x7F <= ch && ch <= 0x9F); } /* count of characters used to encode one unicode char */ static int utf8_encoded_expected_len(const char *str) { unsigned char c; assert(str); c = (unsigned char) str[0]; if (c < 0x80) return 1; if ((c & 0xe0) == 0xc0) return 2; if ((c & 0xf0) == 0xe0) return 3; if ((c & 0xf8) == 0xf0) return 4; if ((c & 0xfc) == 0xf8) return 5; if ((c & 0xfe) == 0xfc) return 6; return 0; } /* decode one unicode char */ int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) { char32_t unichar; int len, i; assert(str); len = utf8_encoded_expected_len(str); switch (len) { case 1: *ret_unichar = (char32_t)str[0]; return 0; case 2: unichar = str[0] & 0x1f; break; case 3: unichar = (char32_t)str[0] & 0x0f; break; case 4: unichar = (char32_t)str[0] & 0x07; break; case 5: unichar = (char32_t)str[0] & 0x03; break; case 6: unichar = (char32_t)str[0] & 0x01; break; default: return -EINVAL; } for (i = 1; i < len; i++) { if (((char32_t)str[i] & 0xc0) != 0x80) return -EINVAL; unichar <<= 6; unichar |= (char32_t)str[i] & 0x3f; } *ret_unichar = unichar; return 0; } bool utf8_is_printable_newline(const char* str, size_t length, bool newline) { const char *p; assert(str); for (p = str; length;) { int encoded_len, r; char32_t val; encoded_len = utf8_encoded_valid_unichar(p); if (encoded_len < 0 || (size_t) encoded_len > length) return false; r = utf8_encoded_to_unichar(p, &val); if (r < 0 || unichar_is_control(val) || (!newline && val == '\n')) return false; length -= encoded_len; p += encoded_len; } return true; } const char *utf8_is_valid(const char *str) { const uint8_t *p; assert(str); for (p = (const uint8_t*) str; *p; ) { int len; len = utf8_encoded_valid_unichar((const char *)p); if (len < 0) return NULL; p += len; } return str; } char *utf8_escape_invalid(const char *str) { char *p, *s; assert(str); p = s = malloc(strlen(str) * 4 + 1); if (!p) return NULL; while (*str) { int len; len = utf8_encoded_valid_unichar(str); if (len > 0) { s = mempcpy(s, str, len); str += len; } else { s = stpcpy(s, UTF8_REPLACEMENT_CHARACTER); str += 1; } } *s = '\0'; return p; } char *utf8_escape_non_printable(const char *str) { char *p, *s; assert(str); p = s = malloc(strlen(str) * 4 + 1); if (!p) return NULL; while (*str) { int len; len = utf8_encoded_valid_unichar(str); if (len > 0) { if (utf8_is_printable(str, len)) { s = mempcpy(s, str, len); str += len; } else { while (len > 0) { *(s++) = '\\'; *(s++) = 'x'; *(s++) = hexchar((int) *str >> 4); *(s++) = hexchar((int) *str); str += 1; len --; } } } else { s = stpcpy(s, UTF8_REPLACEMENT_CHARACTER); str += 1; } } *s = '\0'; return p; } char *ascii_is_valid(const char *str) { const char *p; assert(str); for (p = str; *p; p++) if ((unsigned char) *p >= 128) return NULL; return (char*) str; } /** * utf8_encode_unichar() - Encode single UCS-4 character as UTF-8 * @out_utf8: output buffer of at least 4 bytes or NULL * @g: UCS-4 character to encode * * This encodes a single UCS-4 character as UTF-8 and writes it into @out_utf8. * The length of the character is returned. It is not zero-terminated! If the * output buffer is NULL, only the length is returned. * * Returns: The length in bytes that the UTF-8 representation does or would * occupy. */ size_t utf8_encode_unichar(char *out_utf8, char32_t g) { if (g < (1 << 7)) { if (out_utf8) out_utf8[0] = g & 0x7f; return 1; } else if (g < (1 << 11)) { if (out_utf8) { out_utf8[0] = 0xc0 | ((g >> 6) & 0x1f); out_utf8[1] = 0x80 | (g & 0x3f); } return 2; } else if (g < (1 << 16)) { if (out_utf8) { out_utf8[0] = 0xe0 | ((g >> 12) & 0x0f); out_utf8[1] = 0x80 | ((g >> 6) & 0x3f); out_utf8[2] = 0x80 | (g & 0x3f); } return 3; } else if (g < (1 << 21)) { if (out_utf8) { out_utf8[0] = 0xf0 | ((g >> 18) & 0x07); out_utf8[1] = 0x80 | ((g >> 12) & 0x3f); out_utf8[2] = 0x80 | ((g >> 6) & 0x3f); out_utf8[3] = 0x80 | (g & 0x3f); } return 4; } return 0; } char *utf16_to_utf8(const void *s, size_t length) { const uint8_t *f; char *r, *t; r = new(char, (length * 4 + 1) / 2 + 1); if (!r) return NULL; f = s; t = r; while (f < (const uint8_t*) s + length) { char16_t w1, w2; /* see RFC 2781 section 2.2 */ w1 = f[1] << 8 | f[0]; f += 2; if (!utf16_is_surrogate(w1)) { t += utf8_encode_unichar(t, w1); continue; } if (utf16_is_trailing_surrogate(w1)) continue; else if (f >= (const uint8_t*) s + length) break; w2 = f[1] << 8 | f[0]; f += 2; if (!utf16_is_trailing_surrogate(w2)) { f -= 2; continue; } t += utf8_encode_unichar(t, utf16_surrogate_pair_to_unichar(w1, w2)); } *t = 0; return r; } /* expected size used to encode one unicode char */ static int utf8_unichar_to_encoded_len(char32_t unichar) { if (unichar < 0x80) return 1; if (unichar < 0x800) return 2; if (unichar < 0x10000) return 3; if (unichar < 0x200000) return 4; if (unichar < 0x4000000) return 5; return 6; } /* validate one encoded unicode char and return its length */ int utf8_encoded_valid_unichar(const char *str) { int len, i, r; char32_t unichar; assert(str); len = utf8_encoded_expected_len(str); if (len == 0) return -EINVAL; /* ascii is valid */ if (len == 1) return 1; /* check if expected encoded chars are available */ for (i = 0; i < len; i++) if ((str[i] & 0x80) != 0x80) return -EINVAL; r = utf8_encoded_to_unichar(str, &unichar); if (r < 0) return r; /* check if encoded length matches encoded value */ if (utf8_unichar_to_encoded_len(unichar) != len) return -EINVAL; /* check if value has valid range */ if (!unichar_is_valid(unichar)) return -EINVAL; return len; } systemd-229/src/basic/utf8.h000066400000000000000000000035561265713322000160010ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "macro.h" #include "missing.h" #define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd" bool unichar_is_valid(char32_t c); const char *utf8_is_valid(const char *s) _pure_; char *ascii_is_valid(const char *s) _pure_; bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pure_; #define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true) char *utf8_escape_invalid(const char *s); char *utf8_escape_non_printable(const char *str); size_t utf8_encode_unichar(char *out_utf8, char32_t g); char *utf16_to_utf8(const void *s, size_t length); int utf8_encoded_valid_unichar(const char *str); int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar); static inline bool utf16_is_surrogate(char16_t c) { return (0xd800 <= c && c <= 0xdfff); } static inline bool utf16_is_trailing_surrogate(char16_t c) { return (0xdc00 <= c && c <= 0xdfff); } static inline char32_t utf16_surrogate_pair_to_unichar(char16_t lead, char16_t trail) { return ((lead - 0xd800) << 10) + (trail - 0xdc00) + 0x10000; } systemd-229/src/basic/util.c000066400000000000000000000546771265713322000160750ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "build.h" #include "def.h" #include "dirent-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "hashmap.h" #include "hostname-util.h" #include "log.h" #include "macro.h" #include "missing.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "set.h" #include "signal-util.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" #include "user-util.h" #include "util.h" /* Put this test here for a lack of better place */ assert_cc(EAGAIN == EWOULDBLOCK); int saved_argc = 0; char **saved_argv = NULL; size_t page_size(void) { static thread_local size_t pgsz = 0; long r; if (_likely_(pgsz > 0)) return pgsz; r = sysconf(_SC_PAGESIZE); assert(r > 0); pgsz = (size_t) r; return pgsz; } static int do_execute(char **directories, usec_t timeout, char *argv[]) { _cleanup_hashmap_free_free_ Hashmap *pids = NULL; _cleanup_set_free_free_ Set *seen = NULL; char **directory; /* We fork this all off from a child process so that we can * somewhat cleanly make use of SIGALRM to set a time limit */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); pids = hashmap_new(NULL); if (!pids) return log_oom(); seen = set_new(&string_hash_ops); if (!seen) return log_oom(); STRV_FOREACH(directory, directories) { _cleanup_closedir_ DIR *d; struct dirent *de; d = opendir(*directory); if (!d) { if (errno == ENOENT) continue; return log_error_errno(errno, "Failed to open directory %s: %m", *directory); } FOREACH_DIRENT(de, d, break) { _cleanup_free_ char *path = NULL; pid_t pid; int r; if (!dirent_is_file(de)) continue; if (set_contains(seen, de->d_name)) { log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name); continue; } r = set_put_strdup(seen, de->d_name); if (r < 0) return log_oom(); path = strjoin(*directory, "/", de->d_name, NULL); if (!path) return log_oom(); if (null_or_empty_path(path)) { log_debug("%s is empty (a mask).", path); continue; } pid = fork(); if (pid < 0) { log_error_errno(errno, "Failed to fork: %m"); continue; } else if (pid == 0) { char *_argv[2]; assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); if (!argv) { _argv[0] = path; _argv[1] = NULL; argv = _argv; } else argv[0] = path; execv(path, argv); return log_error_errno(errno, "Failed to execute %s: %m", path); } log_debug("Spawned %s as " PID_FMT ".", path, pid); r = hashmap_put(pids, PID_TO_PTR(pid), path); if (r < 0) return log_oom(); path = NULL; } } /* Abort execution of this process after the timout. We simply * rely on SIGALRM as default action terminating the process, * and turn on alarm(). */ if (timeout != USEC_INFINITY) alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC); while (!hashmap_isempty(pids)) { _cleanup_free_ char *path = NULL; pid_t pid; pid = PTR_TO_PID(hashmap_first_key(pids)); assert(pid > 0); path = hashmap_remove(pids, PID_TO_PTR(pid)); assert(path); wait_for_terminate_and_warn(path, pid, true); } return 0; } void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) { pid_t executor_pid; int r; char *name; char **dirs = (char**) directories; assert(!strv_isempty(dirs)); name = basename(dirs[0]); assert(!isempty(name)); /* Executes all binaries in the directories in parallel and waits * for them to finish. Optionally a timeout is applied. If a file * with the same name exists in more than one directory, the * earliest one wins. */ executor_pid = fork(); if (executor_pid < 0) { log_error_errno(errno, "Failed to fork: %m"); return; } else if (executor_pid == 0) { r = do_execute(dirs, timeout, argv); _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); } wait_for_terminate_and_warn(name, executor_pid, true); } bool plymouth_running(void) { return access("/run/plymouth/pid", F_OK) >= 0; } bool display_is_local(const char *display) { assert(display); return display[0] == ':' && display[1] >= '0' && display[1] <= '9'; } int socket_from_display(const char *display, char **path) { size_t k; char *f, *c; assert(display); assert(path); if (!display_is_local(display)) return -EINVAL; k = strspn(display+1, "0123456789"); f = new(char, strlen("/tmp/.X11-unix/X") + k + 1); if (!f) return -ENOMEM; c = stpcpy(f, "/tmp/.X11-unix/X"); memcpy(c, display+1, k); c[k] = 0; *path = f; return 0; } int block_get_whole_disk(dev_t d, dev_t *ret) { char *p, *s; int r; unsigned n, m; assert(ret); /* If it has a queue this is good enough for us */ if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0) return -ENOMEM; r = access(p, F_OK); free(p); if (r >= 0) { *ret = d; return 0; } /* If it is a partition find the originating device */ if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0) return -ENOMEM; r = access(p, F_OK); free(p); if (r < 0) return -ENOENT; /* Get parent dev_t */ if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0) return -ENOMEM; r = read_one_line_file(p, &s); free(p); if (r < 0) return r; r = sscanf(s, "%u:%u", &m, &n); free(s); if (r != 2) return -EINVAL; /* Only return this if it is really good enough for us. */ if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0) return -ENOMEM; r = access(p, F_OK); free(p); if (r >= 0) { *ret = makedev(m, n); return 0; } return -ENOENT; } bool kexec_loaded(void) { bool loaded = false; char *s; if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) { if (s[0] == '1') loaded = true; free(s); } return loaded; } int prot_from_flags(int flags) { switch (flags & O_ACCMODE) { case O_RDONLY: return PROT_READ; case O_WRONLY: return PROT_WRITE; case O_RDWR: return PROT_READ|PROT_WRITE; default: return -EINVAL; } } int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) { bool stdout_is_tty, stderr_is_tty; pid_t parent_pid, agent_pid; sigset_t ss, saved_ss; unsigned n, i; va_list ap; char **l; assert(pid); assert(path); /* Spawns a temporary TTY agent, making sure it goes away when * we go away */ parent_pid = getpid(); /* First we temporarily block all signals, so that the new * child has them blocked initially. This way, we can be sure * that SIGTERMs are not lost we might send to the agent. */ assert_se(sigfillset(&ss) >= 0); assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0); agent_pid = fork(); if (agent_pid < 0) { assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0); return -errno; } if (agent_pid != 0) { assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0); *pid = agent_pid; return 0; } /* In the child: * * Make sure the agent goes away when the parent dies */ if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) _exit(EXIT_FAILURE); /* Make sure we actually can kill the agent, if we need to, in * case somebody invoked us from a shell script that trapped * SIGTERM or so... */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); /* Check whether our parent died before we were able * to set the death signal and unblock the signals */ if (getppid() != parent_pid) _exit(EXIT_SUCCESS); /* Don't leak fds to the agent */ close_all_fds(except, n_except); stdout_is_tty = isatty(STDOUT_FILENO); stderr_is_tty = isatty(STDERR_FILENO); if (!stdout_is_tty || !stderr_is_tty) { int fd; /* Detach from stdout/stderr. and reopen * /dev/tty for them. This is important to * ensure that when systemctl is started via * popen() or a similar call that expects to * read EOF we actually do generate EOF and * not delay this indefinitely by because we * keep an unused copy of stdin around. */ fd = open("/dev/tty", O_WRONLY); if (fd < 0) { log_error_errno(errno, "Failed to open /dev/tty: %m"); _exit(EXIT_FAILURE); } if (!stdout_is_tty) dup2(fd, STDOUT_FILENO); if (!stderr_is_tty) dup2(fd, STDERR_FILENO); if (fd > 2) close(fd); } /* Count arguments */ va_start(ap, path); for (n = 0; va_arg(ap, char*); n++) ; va_end(ap); /* Allocate strv */ l = alloca(sizeof(char *) * (n + 1)); /* Fill in arguments */ va_start(ap, path); for (i = 0; i <= n; i++) l[i] = va_arg(ap, char*); va_end(ap); execv(path, l); _exit(EXIT_FAILURE); } bool in_initrd(void) { static int saved = -1; struct statfs s; if (saved >= 0) return saved; /* We make two checks here: * * 1. the flag file /etc/initrd-release must exist * 2. the root file system must be a memory file system * * The second check is extra paranoia, since misdetecting an * initrd can have bad bad consequences due the initrd * emptying when transititioning to the main systemd. */ saved = access("/etc/initrd-release", F_OK) >= 0 && statfs("/", &s) >= 0 && is_temporary_fs(&s); return saved; } /* hey glibc, APIs with callbacks without a user pointer are so useless */ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, int (*compar) (const void *, const void *, void *), void *arg) { size_t l, u, idx; const void *p; int comparison; l = 0; u = nmemb; while (l < u) { idx = (l + u) / 2; p = (void *)(((const char *) base) + (idx * size)); comparison = compar(key, p, arg); if (comparison < 0) u = idx; else if (comparison > 0) l = idx + 1; else return (void *)p; } return NULL; } int on_ac_power(void) { bool found_offline = false, found_online = false; _cleanup_closedir_ DIR *d = NULL; d = opendir("/sys/class/power_supply"); if (!d) return errno == ENOENT ? true : -errno; for (;;) { struct dirent *de; _cleanup_close_ int fd = -1, device = -1; char contents[6]; ssize_t n; errno = 0; de = readdir(d); if (!de && errno > 0) return -errno; if (!de) break; if (hidden_file(de->d_name)) continue; device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY); if (device < 0) { if (errno == ENOENT || errno == ENOTDIR) continue; return -errno; } fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) { if (errno == ENOENT) continue; return -errno; } n = read(fd, contents, sizeof(contents)); if (n < 0) return -errno; if (n != 6 || memcmp(contents, "Mains\n", 6)) continue; safe_close(fd); fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) { if (errno == ENOENT) continue; return -errno; } n = read(fd, contents, sizeof(contents)); if (n < 0) return -errno; if (n != 2 || contents[1] != '\n') return -EIO; if (contents[0] == '1') { found_online = true; break; } else if (contents[0] == '0') found_offline = true; else return -EIO; } return found_online || !found_offline; } bool id128_is_valid(const char *s) { size_t i, l; l = strlen(s); if (l == 32) { /* Simple formatted 128bit hex string */ for (i = 0; i < l; i++) { char c = s[i]; if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z')) return false; } } else if (l == 36) { /* Formatted UUID */ for (i = 0; i < l; i++) { char c = s[i]; if ((i == 8 || i == 13 || i == 18 || i == 23)) { if (c != '-') return false; } else { if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z')) return false; } } } else return false; return true; } int container_get_leader(const char *machine, pid_t *pid) { _cleanup_free_ char *s = NULL, *class = NULL; const char *p; pid_t leader; int r; assert(machine); assert(pid); if (!machine_name_is_valid(machine)) return -EINVAL; p = strjoina("/run/systemd/machines/", machine); r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL); if (r == -ENOENT) return -EHOSTDOWN; if (r < 0) return r; if (!s) return -EIO; if (!streq_ptr(class, "container")) return -EIO; r = parse_pid(s, &leader); if (r < 0) return r; if (leader <= 1) return -EIO; *pid = leader; return 0; } int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) { _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1; int rfd = -1; assert(pid >= 0); if (mntns_fd) { const char *mntns; mntns = procfs_file_alloca(pid, "ns/mnt"); mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC); if (mntnsfd < 0) return -errno; } if (pidns_fd) { const char *pidns; pidns = procfs_file_alloca(pid, "ns/pid"); pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC); if (pidnsfd < 0) return -errno; } if (netns_fd) { const char *netns; netns = procfs_file_alloca(pid, "ns/net"); netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC); if (netnsfd < 0) return -errno; } if (userns_fd) { const char *userns; userns = procfs_file_alloca(pid, "ns/user"); usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC); if (usernsfd < 0 && errno != ENOENT) return -errno; } if (root_fd) { const char *root; root = procfs_file_alloca(pid, "root"); rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); if (rfd < 0) return -errno; } if (pidns_fd) *pidns_fd = pidnsfd; if (mntns_fd) *mntns_fd = mntnsfd; if (netns_fd) *netns_fd = netnsfd; if (userns_fd) *userns_fd = usernsfd; if (root_fd) *root_fd = rfd; pidnsfd = mntnsfd = netnsfd = usernsfd = -1; return 0; } int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) { if (userns_fd >= 0) { /* Can't setns to your own userns, since then you could * escalate from non-root to root in your own namespace, so * check if namespaces equal before attempting to enter. */ _cleanup_free_ char *userns_fd_path = NULL; int r; if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0) return -ENOMEM; r = files_same(userns_fd_path, "/proc/self/ns/user"); if (r < 0) return r; if (r) userns_fd = -1; } if (pidns_fd >= 0) if (setns(pidns_fd, CLONE_NEWPID) < 0) return -errno; if (mntns_fd >= 0) if (setns(mntns_fd, CLONE_NEWNS) < 0) return -errno; if (netns_fd >= 0) if (setns(netns_fd, CLONE_NEWNET) < 0) return -errno; if (userns_fd >= 0) if (setns(userns_fd, CLONE_NEWUSER) < 0) return -errno; if (root_fd >= 0) { if (fchdir(root_fd) < 0) return -errno; if (chroot(".") < 0) return -errno; } return reset_uid_gid(); } uint64_t physical_memory(void) { long mem; /* We return this as uint64_t in case we are running as 32bit * process on a 64bit kernel with huge amounts of memory */ mem = sysconf(_SC_PHYS_PAGES); assert(mem > 0); return (uint64_t) mem * (uint64_t) page_size(); } int update_reboot_param_file(const char *param) { int r = 0; if (param) { r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE); if (r < 0) return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m"); } else (void) unlink(REBOOT_PARAM_FILE); return 0; } int version(void) { puts(PACKAGE_STRING "\n" SYSTEMD_FEATURES); return 0; } systemd-229/src/basic/util.h000066400000000000000000000113431265713322000160610ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "formats-util.h" #include "macro.h" #include "missing.h" #include "time-util.h" size_t page_size(void) _pure_; #define PAGE_ALIGN(l) ALIGN_TO((l), page_size()) static inline const char* yes_no(bool b) { return b ? "yes" : "no"; } static inline const char* true_false(bool b) { return b ? "true" : "false"; } static inline const char* one_zero(bool b) { return b ? "1" : "0"; } void execute_directories(const char* const* directories, usec_t timeout, char *argv[]); bool plymouth_running(void); bool display_is_local(const char *display) _pure_; int socket_from_display(const char *display, char **path); int block_get_whole_disk(dev_t d, dev_t *ret); #define NULSTR_FOREACH(i, l) \ for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1) #define NULSTR_FOREACH_PAIR(i, j, l) \ for ((i) = (l), (j) = strchr((i), 0)+1; (i) && *(i); (i) = strchr((j), 0)+1, (j) = *(i) ? strchr((i), 0)+1 : (i)) extern int saved_argc; extern char **saved_argv; bool kexec_loaded(void); int prot_from_flags(int flags) _const_; int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...); bool in_initrd(void); void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, int (*compar) (const void *, const void *, void *), void *arg); /** * Normal qsort requires base to be nonnull. Here were require * that only if nmemb > 0. */ static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_fn_t compar) { if (nmemb <= 1) return; assert(base); qsort(base, nmemb, size, compar); } int on_ac_power(void); #define memzero(x,l) (memset((x), 0, (l))) #define zero(x) (memzero(&(x), sizeof(x))) static inline void *mempset(void *s, int c, size_t n) { memset(s, c, n); return (uint8_t*)s + n; } static inline void _reset_errno_(int *saved_errno) { errno = *saved_errno; } #define PROTECT_ERRNO _cleanup_(_reset_errno_) __attribute__((unused)) int _saved_errno_ = errno static inline int negative_errno(void) { /* This helper should be used to shut up gcc if you know 'errno' is * negative. Instead of "return -errno;", use "return negative_errno();" * It will suppress bogus gcc warnings in case it assumes 'errno' might * be 0 and thus the caller's error-handling might not be triggered. */ assert_return(errno > 0, -EINVAL); return -errno; } static inline unsigned u64log2(uint64_t n) { #if __SIZEOF_LONG_LONG__ == 8 return (n > 1) ? (unsigned) __builtin_clzll(n) ^ 63U : 0; #else #error "Wut?" #endif } static inline unsigned u32ctz(uint32_t n) { #if __SIZEOF_INT__ == 4 return __builtin_ctz(n); #else #error "Wut?" #endif } static inline unsigned log2i(int x) { assert(x > 0); return __SIZEOF_INT__ * 8 - __builtin_clz(x) - 1; } static inline unsigned log2u(unsigned x) { assert(x > 0); return sizeof(unsigned) * 8 - __builtin_clz(x) - 1; } static inline unsigned log2u_round_up(unsigned x) { assert(x > 0); if (x == 1) return 0; return log2u(x - 1) + 1; } bool id128_is_valid(const char *s) _pure_; int container_get_leader(const char *machine, pid_t *pid); int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd); int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd); uint64_t physical_memory(void); int update_reboot_param_file(const char *param); int version(void); systemd-229/src/basic/verbs.c000066400000000000000000000055261265713322000162260ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "log.h" #include "macro.h" #include "string-util.h" #include "verbs.h" #include "virt.h" int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) { const Verb *verb; const char *name; unsigned i; int left; assert(verbs); assert(verbs[0].dispatch); assert(argc >= 0); assert(argv); assert(argc >= optind); left = argc - optind; name = argv[optind]; for (i = 0;; i++) { bool found; /* At the end of the list? */ if (!verbs[i].dispatch) { if (name) log_error("Unknown operation %s.", name); else log_error("Requires operation parameter."); return -EINVAL; } if (name) found = streq(name, verbs[i].verb); else found = !!(verbs[i].flags & VERB_DEFAULT); if (found) { verb = &verbs[i]; break; } } assert(verb); if (!name) left = 1; if (verb->min_args != VERB_ANY && (unsigned) left < verb->min_args) { log_error("Too few arguments."); return -EINVAL; } if (verb->max_args != VERB_ANY && (unsigned) left > verb->max_args) { log_error("Too many arguments."); return -EINVAL; } if ((verb->flags & VERB_NOCHROOT) && running_in_chroot() > 0) { log_info("Running in chroot, ignoring request."); return 0; } if (name) return verb->dispatch(left, argv + optind, userdata); else { char* fake[2] = { (char*) verb->verb, NULL }; return verb->dispatch(1, fake, userdata); } } systemd-229/src/basic/verbs.h000066400000000000000000000020701265713322000162220ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #define VERB_ANY ((unsigned) -1) #define VERB_DEFAULT 1U #define VERB_NOCHROOT 2U typedef struct { const char *verb; unsigned min_args, max_args; unsigned flags; int (* const dispatch)(int argc, char *argv[], void *userdata); } Verb; int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata); systemd-229/src/basic/virt.c000066400000000000000000000345571265713322000160770ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "dirent-util.h" #include "fd-util.h" #include "fileio.h" #include "macro.h" #include "process-util.h" #include "stat-util.h" #include "string-table.h" #include "string-util.h" #include "virt.h" static int detect_vm_cpuid(void) { /* CPUID is an x86 specific interface. */ #if defined(__i386__) || defined(__x86_64__) static const struct { const char *cpuid; int id; } cpuid_vendor_table[] = { { "XenVMMXenVMM", VIRTUALIZATION_XEN }, { "KVMKVMKVM", VIRTUALIZATION_KVM }, /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */ { "VMwareVMware", VIRTUALIZATION_VMWARE }, /* http://msdn.microsoft.com/en-us/library/ff542428.aspx */ { "Microsoft Hv", VIRTUALIZATION_MICROSOFT }, }; uint32_t eax, ecx; bool hypervisor; /* http://lwn.net/Articles/301888/ */ #if defined (__i386__) #define REG_a "eax" #define REG_b "ebx" #elif defined (__amd64__) #define REG_a "rax" #define REG_b "rbx" #endif /* First detect whether there is a hypervisor */ eax = 1; __asm__ __volatile__ ( /* ebx/rbx is being used for PIC! */ " push %%"REG_b" \n\t" " cpuid \n\t" " pop %%"REG_b" \n\t" : "=a" (eax), "=c" (ecx) : "0" (eax) ); hypervisor = !!(ecx & 0x80000000U); if (hypervisor) { union { uint32_t sig32[3]; char text[13]; } sig = {}; unsigned j; /* There is a hypervisor, see what it is */ eax = 0x40000000U; __asm__ __volatile__ ( /* ebx/rbx is being used for PIC! */ " push %%"REG_b" \n\t" " cpuid \n\t" " mov %%ebx, %1 \n\t" " pop %%"REG_b" \n\t" : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2]) : "0" (eax) ); for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++) if (streq(sig.text, cpuid_vendor_table[j].cpuid)) return cpuid_vendor_table[j].id; return VIRTUALIZATION_VM_OTHER; } #endif return VIRTUALIZATION_NONE; } static int detect_vm_device_tree(void) { #if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__) || defined(__powerpc64__) _cleanup_free_ char *hvtype = NULL; int r; r = read_one_line_file("/proc/device-tree/hypervisor/compatible", &hvtype); if (r == -ENOENT) { _cleanup_closedir_ DIR *dir = NULL; struct dirent *dent; dir = opendir("/proc/device-tree"); if (!dir) { if (errno == ENOENT) return VIRTUALIZATION_NONE; return -errno; } FOREACH_DIRENT(dent, dir, return -errno) if (strstr(dent->d_name, "fw-cfg")) return VIRTUALIZATION_QEMU; return VIRTUALIZATION_NONE; } else if (r < 0) return r; if (streq(hvtype, "linux,kvm")) return VIRTUALIZATION_KVM; else if (strstr(hvtype, "xen")) return VIRTUALIZATION_XEN; else return VIRTUALIZATION_VM_OTHER; #else return VIRTUALIZATION_NONE; #endif } static int detect_vm_dmi(void) { #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) static const char *const dmi_vendors[] = { "/sys/class/dmi/id/product_name", /* Test this before sys_vendor to detect KVM over QEMU */ "/sys/class/dmi/id/sys_vendor", "/sys/class/dmi/id/board_vendor", "/sys/class/dmi/id/bios_vendor" }; static const struct { const char *vendor; int id; } dmi_vendor_table[] = { { "KVM", VIRTUALIZATION_KVM }, { "QEMU", VIRTUALIZATION_QEMU }, /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */ { "VMware", VIRTUALIZATION_VMWARE }, { "VMW", VIRTUALIZATION_VMWARE }, { "innotek GmbH", VIRTUALIZATION_ORACLE }, { "Xen", VIRTUALIZATION_XEN }, { "Bochs", VIRTUALIZATION_BOCHS }, { "Parallels", VIRTUALIZATION_PARALLELS }, }; unsigned i; int r; for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) { _cleanup_free_ char *s = NULL; unsigned j; r = read_one_line_file(dmi_vendors[i], &s); if (r < 0) { if (r == -ENOENT) continue; return r; } for (j = 0; j < ELEMENTSOF(dmi_vendor_table); j++) if (startswith(s, dmi_vendor_table[j].vendor)) return dmi_vendor_table[j].id; } #endif return VIRTUALIZATION_NONE; } static int detect_vm_xen(void) { _cleanup_free_ char *domcap = NULL; char *cap, *i; int r; r = read_one_line_file("/proc/xen/capabilities", &domcap); if (r == -ENOENT) return VIRTUALIZATION_NONE; i = domcap; while ((cap = strsep(&i, ","))) if (streq(cap, "control_d")) break; return cap ? VIRTUALIZATION_NONE : VIRTUALIZATION_XEN; } static int detect_vm_hypervisor(void) { _cleanup_free_ char *hvtype = NULL; int r; r = read_one_line_file("/sys/hypervisor/type", &hvtype); if (r == -ENOENT) return VIRTUALIZATION_NONE; if (r < 0) return r; if (streq(hvtype, "xen")) return VIRTUALIZATION_XEN; else return VIRTUALIZATION_VM_OTHER; } static int detect_vm_uml(void) { _cleanup_free_ char *cpuinfo_contents = NULL; int r; /* Detect User-Mode Linux by reading /proc/cpuinfo */ r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL); if (r < 0) return r; if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) return VIRTUALIZATION_UML; return VIRTUALIZATION_NONE; } static int detect_vm_zvm(void) { #if defined(__s390__) _cleanup_free_ char *t = NULL; int r; r = get_proc_field("/proc/sysinfo", "VM00 Control Program", WHITESPACE, &t); if (r == -ENOENT) return VIRTUALIZATION_NONE; if (r < 0) return r; if (streq(t, "z/VM")) return VIRTUALIZATION_ZVM; else return VIRTUALIZATION_KVM; #else return VIRTUALIZATION_NONE; #endif } /* Returns a short identifier for the various VM implementations */ int detect_vm(void) { static thread_local int cached_found = _VIRTUALIZATION_INVALID; int r; if (cached_found >= 0) return cached_found; /* We have to use the correct order here: * Some virtualization technologies do use KVM hypervisor but are * expected to be detected as something else. So detect DMI first. * * An example is Virtualbox since version 5.0, which uses KVM backend. * Detection via DMI works corretly, the CPU ID would find KVM * only. */ r = detect_vm_dmi(); if (r < 0) return r; if (r != VIRTUALIZATION_NONE) goto finish; r = detect_vm_cpuid(); if (r < 0) return r; if (r != VIRTUALIZATION_NONE) goto finish; /* x86 xen will most likely be detected by cpuid. If not (most likely * because we're not an x86 guest), then we should try the xen capabilities * file next. If that's not found, then we check for the high-level * hypervisor sysfs file: * * https://bugs.freedesktop.org/show_bug.cgi?id=77271 */ r = detect_vm_xen(); if (r < 0) return r; if (r != VIRTUALIZATION_NONE) goto finish; r = detect_vm_hypervisor(); if (r < 0) return r; if (r != VIRTUALIZATION_NONE) goto finish; r = detect_vm_device_tree(); if (r < 0) return r; if (r != VIRTUALIZATION_NONE) goto finish; r = detect_vm_uml(); if (r < 0) return r; if (r != VIRTUALIZATION_NONE) goto finish; r = detect_vm_zvm(); if (r < 0) return r; finish: cached_found = r; return r; } int detect_container(void) { static const struct { const char *value; int id; } value_table[] = { { "lxc", VIRTUALIZATION_LXC }, { "lxc-libvirt", VIRTUALIZATION_LXC_LIBVIRT }, { "systemd-nspawn", VIRTUALIZATION_SYSTEMD_NSPAWN }, { "docker", VIRTUALIZATION_DOCKER }, { "rkt", VIRTUALIZATION_RKT }, }; static thread_local int cached_found = _VIRTUALIZATION_INVALID; _cleanup_free_ char *m = NULL; const char *e = NULL; unsigned j; int r; if (cached_found >= 0) return cached_found; /* /proc/vz exists in container and outside of the container, * /proc/bc only outside of the container. */ if (access("/proc/vz", F_OK) >= 0 && access("/proc/bc", F_OK) < 0) { r = VIRTUALIZATION_OPENVZ; goto finish; } if (getpid() == 1) { /* If we are PID 1 we can just check our own * environment variable */ e = getenv("container"); if (isempty(e)) { r = VIRTUALIZATION_NONE; goto finish; } } else { /* Otherwise, PID 1 dropped this information into a * file in /run. This is better than accessing * /proc/1/environ, since we don't need CAP_SYS_PTRACE * for that. */ r = read_one_line_file("/run/systemd/container", &m); if (r == -ENOENT) { /* Fallback for cases where PID 1 was not * systemd (for example, cases where * init=/bin/sh is used. */ r = getenv_for_pid(1, "container", &m); if (r <= 0) { /* If that didn't work, give up, * assume no container manager. * * Note: This means we still cannot * detect containers if init=/bin/sh * is passed but privileges dropped, * as /proc/1/environ is only readable * with privileges. */ r = VIRTUALIZATION_NONE; goto finish; } } if (r < 0) return r; e = m; } for (j = 0; j < ELEMENTSOF(value_table); j++) if (streq(e, value_table[j].value)) { r = value_table[j].id; goto finish; } r = VIRTUALIZATION_CONTAINER_OTHER; finish: cached_found = r; return r; } int detect_virtualization(void) { int r; r = detect_container(); if (r != 0) return r; return detect_vm(); } int running_in_chroot(void) { int ret; ret = files_same("/proc/1/root", "/"); if (ret < 0) return ret; return ret == 0; } static const char *const virtualization_table[_VIRTUALIZATION_MAX] = { [VIRTUALIZATION_NONE] = "none", [VIRTUALIZATION_KVM] = "kvm", [VIRTUALIZATION_QEMU] = "qemu", [VIRTUALIZATION_BOCHS] = "bochs", [VIRTUALIZATION_XEN] = "xen", [VIRTUALIZATION_UML] = "uml", [VIRTUALIZATION_VMWARE] = "vmware", [VIRTUALIZATION_ORACLE] = "oracle", [VIRTUALIZATION_MICROSOFT] = "microsoft", [VIRTUALIZATION_ZVM] = "zvm", [VIRTUALIZATION_PARALLELS] = "parallels", [VIRTUALIZATION_VM_OTHER] = "vm-other", [VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn", [VIRTUALIZATION_LXC_LIBVIRT] = "lxc-libvirt", [VIRTUALIZATION_LXC] = "lxc", [VIRTUALIZATION_OPENVZ] = "openvz", [VIRTUALIZATION_DOCKER] = "docker", [VIRTUALIZATION_RKT] = "rkt", [VIRTUALIZATION_CONTAINER_OTHER] = "container-other", }; DEFINE_STRING_TABLE_LOOKUP(virtualization, int); systemd-229/src/basic/virt.h000066400000000000000000000042461265713322000160740ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" enum { VIRTUALIZATION_NONE = 0, VIRTUALIZATION_VM_FIRST, VIRTUALIZATION_KVM = VIRTUALIZATION_VM_FIRST, VIRTUALIZATION_QEMU, VIRTUALIZATION_BOCHS, VIRTUALIZATION_XEN, VIRTUALIZATION_UML, VIRTUALIZATION_VMWARE, VIRTUALIZATION_ORACLE, VIRTUALIZATION_MICROSOFT, VIRTUALIZATION_ZVM, VIRTUALIZATION_PARALLELS, VIRTUALIZATION_VM_OTHER, VIRTUALIZATION_VM_LAST = VIRTUALIZATION_VM_OTHER, VIRTUALIZATION_CONTAINER_FIRST, VIRTUALIZATION_SYSTEMD_NSPAWN = VIRTUALIZATION_CONTAINER_FIRST, VIRTUALIZATION_LXC_LIBVIRT, VIRTUALIZATION_LXC, VIRTUALIZATION_OPENVZ, VIRTUALIZATION_DOCKER, VIRTUALIZATION_RKT, VIRTUALIZATION_CONTAINER_OTHER, VIRTUALIZATION_CONTAINER_LAST = VIRTUALIZATION_CONTAINER_OTHER, _VIRTUALIZATION_MAX, _VIRTUALIZATION_INVALID = -1 }; static inline bool VIRTUALIZATION_IS_VM(int x) { return x >= VIRTUALIZATION_VM_FIRST && x <= VIRTUALIZATION_VM_LAST; } static inline bool VIRTUALIZATION_IS_CONTAINER(int x) { return x >= VIRTUALIZATION_CONTAINER_FIRST && x <= VIRTUALIZATION_CONTAINER_LAST; } int detect_vm(void); int detect_container(void); int detect_virtualization(void); int running_in_chroot(void); const char *virtualization_to_string(int v) _const_; int virtualization_from_string(const char *s) _pure_; systemd-229/src/basic/web-util.c000066400000000000000000000035731265713322000166350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "string-util.h" #include "utf8.h" #include "web-util.h" bool http_etag_is_valid(const char *etag) { if (isempty(etag)) return false; if (!endswith(etag, "\"")) return false; if (!startswith(etag, "\"") && !startswith(etag, "W/\"")) return false; return true; } bool http_url_is_valid(const char *url) { const char *p; if (isempty(url)) return false; p = startswith(url, "http://"); if (!p) p = startswith(url, "https://"); if (!p) return false; if (isempty(p)) return false; return ascii_is_valid(p); } bool documentation_url_is_valid(const char *url) { const char *p; if (isempty(url)) return false; if (http_url_is_valid(url)) return true; p = startswith(url, "file:/"); if (!p) p = startswith(url, "info:"); if (!p) p = startswith(url, "man:"); if (isempty(p)) return false; return ascii_is_valid(p); } systemd-229/src/basic/web-util.h000066400000000000000000000016351265713322000166370ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" bool http_url_is_valid(const char *url) _pure_; bool documentation_url_is_valid(const char *url) _pure_; bool http_etag_is_valid(const char *etag); systemd-229/src/basic/xattr-util.c000066400000000000000000000121301265713322000172070ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "macro.h" #include "sparse-endian.h" #include "stdio-util.h" #include "time-util.h" #include "xattr-util.h" int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) { char *v; size_t l; ssize_t n; assert(path); assert(name); assert(value); for (l = 100; ; l = (size_t) n + 1) { v = new0(char, l); if (!v) return -ENOMEM; if (allow_symlink) n = lgetxattr(path, name, v, l); else n = getxattr(path, name, v, l); if (n >= 0 && (size_t) n < l) { *value = v; return n; } free(v); if (n < 0 && errno != ERANGE) return -errno; if (allow_symlink) n = lgetxattr(path, name, NULL, 0); else n = getxattr(path, name, NULL, 0); if (n < 0) return -errno; } } int fgetxattr_malloc(int fd, const char *name, char **value) { char *v; size_t l; ssize_t n; assert(fd >= 0); assert(name); assert(value); for (l = 100; ; l = (size_t) n + 1) { v = new0(char, l); if (!v) return -ENOMEM; n = fgetxattr(fd, name, v, l); if (n >= 0 && (size_t) n < l) { *value = v; return n; } free(v); if (n < 0 && errno != ERANGE) return -errno; n = fgetxattr(fd, name, NULL, 0); if (n < 0) return -errno; } } ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) { char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; _cleanup_close_ int fd = -1; ssize_t l; /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */ fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0)); if (fd < 0) return -errno; xsprintf(fn, "/proc/self/fd/%i", fd); l = getxattr(fn, attribute, value, size); if (l < 0) return -errno; return l; } static int parse_crtime(le64_t le, usec_t *usec) { uint64_t u; assert(usec); u = le64toh(le); if (u == 0 || u == (uint64_t) -1) return -EIO; *usec = (usec_t) u; return 0; } int fd_getcrtime(int fd, usec_t *usec) { le64_t le; ssize_t n; assert(fd >= 0); assert(usec); /* Until Linux gets a real concept of birthtime/creation time, * let's fake one with xattrs */ n = fgetxattr(fd, "user.crtime_usec", &le, sizeof(le)); if (n < 0) return -errno; if (n != sizeof(le)) return -EIO; return parse_crtime(le, usec); } int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags) { le64_t le; ssize_t n; n = fgetxattrat_fake(dirfd, name, "user.crtime_usec", &le, sizeof(le), flags); if (n < 0) return -errno; if (n != sizeof(le)) return -EIO; return parse_crtime(le, usec); } int path_getcrtime(const char *p, usec_t *usec) { le64_t le; ssize_t n; assert(p); assert(usec); n = getxattr(p, "user.crtime_usec", &le, sizeof(le)); if (n < 0) return -errno; if (n != sizeof(le)) return -EIO; return parse_crtime(le, usec); } int fd_setcrtime(int fd, usec_t usec) { le64_t le; assert(fd >= 0); if (usec <= 0) usec = now(CLOCK_REALTIME); le = htole64((uint64_t) usec); if (fsetxattr(fd, "user.crtime_usec", &le, sizeof(le), 0) < 0) return -errno; return 0; } systemd-229/src/basic/xattr-util.h000066400000000000000000000024241265713322000172210ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "time-util.h" int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink); int fgetxattr_malloc(int fd, const char *name, char **value); ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags); int fd_setcrtime(int fd, usec_t usec); int fd_getcrtime(int fd, usec_t *usec); int path_getcrtime(const char *p, usec_t *usec); int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags); systemd-229/src/basic/xml.c000066400000000000000000000174021265713322000157010ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "macro.h" #include "string-util.h" #include "xml.h" enum { STATE_NULL, STATE_TEXT, STATE_TAG, STATE_ATTRIBUTE, }; static void inc_lines(unsigned *line, const char *s, size_t n) { const char *p = s; if (!line) return; for (;;) { const char *f; f = memchr(p, '\n', n); if (!f) return; n -= (f - p) + 1; p = f + 1; (*line)++; } } /* We don't actually do real XML here. We only read a simplistic * subset, that is a bit less strict that XML and lacks all the more * complex features, like entities, or namespaces. However, we do * support some HTML5-like simplifications */ int xml_tokenize(const char **p, char **name, void **state, unsigned *line) { const char *c, *e, *b; char *ret; int t; assert(p); assert(*p); assert(name); assert(state); t = PTR_TO_INT(*state); c = *p; if (t == STATE_NULL) { if (line) *line = 1; t = STATE_TEXT; } for (;;) { if (*c == 0) return XML_END; switch (t) { case STATE_TEXT: { int x; e = strchrnul(c, '<'); if (e > c) { /* More text... */ ret = strndup(c, e - c); if (!ret) return -ENOMEM; inc_lines(line, c, e - c); *name = ret; *p = e; *state = INT_TO_PTR(STATE_TEXT); return XML_TEXT; } assert(*e == '<'); b = c + 1; if (startswith(b, "!--")) { /* A comment */ e = strstr(b + 3, "-->"); if (!e) return -EINVAL; inc_lines(line, b, e + 3 - b); c = e + 3; continue; } if (*b == '?') { /* Processing instruction */ e = strstr(b + 1, "?>"); if (!e) return -EINVAL; inc_lines(line, b, e + 2 - b); c = e + 2; continue; } if (*b == '!') { /* DTD */ e = strchr(b + 1, '>'); if (!e) return -EINVAL; inc_lines(line, b, e + 1 - b); c = e + 1; continue; } if (*b == '/') { /* A closing tag */ x = XML_TAG_CLOSE; b++; } else x = XML_TAG_OPEN; e = strpbrk(b, WHITESPACE "/>"); if (!e) return -EINVAL; ret = strndup(b, e - b); if (!ret) return -ENOMEM; *name = ret; *p = e; *state = INT_TO_PTR(STATE_TAG); return x; } case STATE_TAG: b = c + strspn(c, WHITESPACE); if (*b == 0) return -EINVAL; inc_lines(line, c, b - c); e = b + strcspn(b, WHITESPACE "=/>"); if (e > b) { /* An attribute */ ret = strndup(b, e - b); if (!ret) return -ENOMEM; *name = ret; *p = e; *state = INT_TO_PTR(STATE_ATTRIBUTE); return XML_ATTRIBUTE_NAME; } if (startswith(b, "/>")) { /* An empty tag */ *name = NULL; /* For empty tags we return a NULL name, the caller must be prepared for that */ *p = b + 2; *state = INT_TO_PTR(STATE_TEXT); return XML_TAG_CLOSE_EMPTY; } if (*b != '>') return -EINVAL; c = b + 1; t = STATE_TEXT; continue; case STATE_ATTRIBUTE: if (*c == '=') { c++; if (*c == '\'' || *c == '\"') { /* Tag with a quoted value */ e = strchr(c+1, *c); if (!e) return -EINVAL; inc_lines(line, c, e - c); ret = strndup(c+1, e - c - 1); if (!ret) return -ENOMEM; *name = ret; *p = e + 1; *state = INT_TO_PTR(STATE_TAG); return XML_ATTRIBUTE_VALUE; } /* Tag with a value without quotes */ b = strpbrk(c, WHITESPACE ">"); if (!b) b = c; ret = strndup(c, b - c); if (!ret) return -ENOMEM; *name = ret; *p = b; *state = INT_TO_PTR(STATE_TAG); return XML_ATTRIBUTE_VALUE; } t = STATE_TAG; continue; } } assert_not_reached("Bad state"); } systemd-229/src/basic/xml.h000066400000000000000000000017331265713322000157060ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ enum { XML_END, XML_TEXT, XML_TAG_OPEN, XML_TAG_CLOSE, XML_TAG_CLOSE_EMPTY, XML_ATTRIBUTE_NAME, XML_ATTRIBUTE_VALUE, }; int xml_tokenize(const char **p, char **name, void **state, unsigned *line); systemd-229/src/binfmt/000077500000000000000000000000001265713322000151275ustar00rootroot00000000000000systemd-229/src/binfmt/Makefile000077700000000000000000000000001265713322000204352../Makefileustar00rootroot00000000000000systemd-229/src/binfmt/binfmt.c000066400000000000000000000124411265713322000165540ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "alloc-util.h" #include "conf-files.h" #include "def.h" #include "fd-util.h" #include "fileio.h" #include "log.h" #include "string-util.h" #include "strv.h" #include "util.h" static const char conf_file_dirs[] = CONF_PATHS_NULSTR("binfmt.d"); static int delete_rule(const char *rule) { _cleanup_free_ char *x = NULL, *fn = NULL; char *e; assert(rule[0]); x = strdup(rule); if (!x) return log_oom(); e = strchrnul(x+1, x[0]); *e = 0; fn = strappend("/proc/sys/fs/binfmt_misc/", x+1); if (!fn) return log_oom(); return write_string_file(fn, "-1", 0); } static int apply_rule(const char *rule) { int r; delete_rule(rule); r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, 0); if (r < 0) return log_error_errno(r, "Failed to add binary format: %m"); return 0; } static int apply_file(const char *path, bool ignore_enoent) { _cleanup_fclose_ FILE *f = NULL; int r; assert(path); r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f); if (r < 0) { if (ignore_enoent && r == -ENOENT) return 0; return log_error_errno(r, "Failed to open file '%s', ignoring: %m", path); } log_debug("apply: %s", path); for (;;) { char l[LINE_MAX], *p; int k; if (!fgets(l, sizeof(l), f)) { if (feof(f)) break; return log_error_errno(errno, "Failed to read file '%s', ignoring: %m", path); } p = strstrip(l); if (!*p) continue; if (strchr(COMMENTS "\n", *p)) continue; k = apply_rule(p); if (k < 0 && r == 0) r = k; } return r; } static void help(void) { printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n" "Registers binary formats.\n\n" " -h --help Show this help\n" " --version Show package version\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } int main(int argc, char *argv[]) { int r, k; r = parse_argv(argc, argv); if (r <= 0) return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); r = 0; if (argc > optind) { int i; for (i = optind; i < argc; i++) { k = apply_file(argv[i], false); if (k < 0 && r == 0) r = k; } } else { _cleanup_strv_free_ char **files = NULL; char **f; r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs); if (r < 0) { log_error_errno(r, "Failed to enumerate binfmt.d files: %m"); goto finish; } /* Flush out all rules */ write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", 0); STRV_FOREACH(f, files) { k = apply_file(*f, true); if (k < 0 && r == 0) r = k; } } finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/boot/000077500000000000000000000000001265713322000146135ustar00rootroot00000000000000systemd-229/src/boot/Makefile000077700000000000000000000000001265713322000201212../Makefileustar00rootroot00000000000000systemd-229/src/boot/bootctl.c000066400000000000000000001062541265713322000164350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013-2015 Kay Sievers Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "blkid-util.h" #include "dirent-util.h" #include "efivars.h" #include "fd-util.h" #include "fileio.h" #include "locale-util.h" #include "rm-rf.h" #include "string-util.h" #include "util.h" static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) { struct statfs sfs; struct stat st, st2; _cleanup_free_ char *t = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; int r; const char *v, *t2; if (statfs(p, &sfs) < 0) return log_error_errno(errno, "Failed to check file system type of \"%s\": %m", p); if (sfs.f_type != 0x4d44) { log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p); return -ENODEV; } if (stat(p, &st) < 0) return log_error_errno(errno, "Failed to determine block device node of \"%s\": %m", p); if (major(st.st_dev) == 0) { log_error("Block device node of %p is invalid.", p); return -ENODEV; } t2 = strjoina(p, "/.."); r = stat(t2, &st2); if (r < 0) return log_error_errno(errno, "Failed to determine block device node of parent of \"%s\": %m", p); if (st.st_dev == st2.st_dev) { log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p); return -ENODEV; } r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev)); if (r < 0) return log_oom(); errno = 0; b = blkid_new_probe_from_filename(t); if (!b) { if (errno == 0) return log_oom(); return log_error_errno(errno, "Failed to open file system \"%s\": %m", p); } blkid_probe_enable_superblocks(b, 1); blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE); blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == -2) { log_error("File system \"%s\" is ambigious.", p); return -ENODEV; } else if (r == 1) { log_error("File system \"%s\" does not contain a label.", p); return -ENODEV; } else if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe file system \"%s\": %m", p); } errno = 0; r = blkid_probe_lookup_value(b, "TYPE", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe file system type \"%s\": %m", p); } if (!streq(v, "vfat")) { log_error("File system \"%s\" is not FAT.", p); return -ENODEV; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition scheme \"%s\": %m", p); } if (!streq(v, "gpt")) { log_error("File system \"%s\" is not on a GPT partition table.", p); return -ENODEV; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition type UUID \"%s\": %m", p); } if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) { log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p); return -ENODEV; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition entry UUID \"%s\": %m", p); } r = sd_id128_from_string(v, uuid); if (r < 0) { log_error("Partition \"%s\" has invalid UUID \"%s\".", p, v); return -EIO; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition number \"%s\": m", p); } *part = strtoul(v, NULL, 10); errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition offset \"%s\": %m", p); } *pstart = strtoul(v, NULL, 10); errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL); if (r != 0) { r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition size \"%s\": %m", p); } *psize = strtoul(v, NULL, 10); return 0; } /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */ static int get_file_version(int fd, char **v) { struct stat st; char *buf; const char *s, *e; char *x = NULL; int r = 0; assert(fd >= 0); assert(v); if (fstat(fd, &st) < 0) return -errno; if (st.st_size < 27) return 0; buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (buf == MAP_FAILED) return -errno; s = memmem(buf, st.st_size - 8, "#### LoaderInfo: ", 17); if (!s) goto finish; s += 17; e = memmem(s, st.st_size - (s - buf), " ####", 5); if (!e || e - s < 3) { log_error("Malformed version string."); r = -EINVAL; goto finish; } x = strndup(s, e - s); if (!x) { r = log_oom(); goto finish; } r = 1; finish: munmap(buf, st.st_size); *v = x; return r; } static int enumerate_binaries(const char *esp_path, const char *path, const char *prefix) { char *p; _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0, c = 0; p = strjoina(esp_path, "/", path); d = opendir(p); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to read \"%s\": %m", p); } FOREACH_DIRENT(de, d, break) { _cleanup_close_ int fd = -1; _cleanup_free_ char *v = NULL; if (!endswith_no_case(de->d_name, ".efi")) continue; if (prefix && !startswith_no_case(de->d_name, prefix)) continue; fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC); if (fd < 0) return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name); r = get_file_version(fd, &v); if (r < 0) return r; if (r > 0) printf(" File: %s/%s/%s (%s)\n", draw_special_char(DRAW_TREE_RIGHT), path, de->d_name, v); else printf(" File: %s/%s/%s\n", draw_special_char(DRAW_TREE_RIGHT), path, de->d_name); c++; } return c; } static int status_binaries(const char *esp_path, sd_id128_t partition) { int r; printf("Boot Loader Binaries:\n"); printf(" ESP: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", SD_ID128_FORMAT_VAL(partition)); r = enumerate_binaries(esp_path, "EFI/systemd", NULL); if (r == 0) log_error("systemd-boot not installed in ESP."); else if (r < 0) return r; r = enumerate_binaries(esp_path, "EFI/Boot", "boot"); if (r == 0) log_error("No default/fallback boot loader installed in ESP."); else if (r < 0) return r; printf("\n"); return 0; } static int print_efi_option(uint16_t id, bool in_order) { _cleanup_free_ char *title = NULL; _cleanup_free_ char *path = NULL; sd_id128_t partition; bool active; int r = 0; r = efi_get_boot_option(id, &title, &partition, &path, &active); if (r < 0) return r; /* print only configured entries with partition information */ if (!path || sd_id128_equal(partition, SD_ID128_NULL)) return 0; efi_tilt_backslashes(path); printf(" Title: %s\n", strna(title)); printf(" ID: 0x%04X\n", id); printf(" Status: %sactive%s\n", active ? "" : "in", in_order ? ", boot-order" : ""); printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", SD_ID128_FORMAT_VAL(partition)); printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), path); printf("\n"); return 0; } static int status_variables(void) { int n_options, n_order; _cleanup_free_ uint16_t *options = NULL, *order = NULL; int i; if (!is_efi_boot()) { log_notice("Not booted with EFI, not showing EFI variables."); return 0; } n_options = efi_get_boot_options(&options); if (n_options == -ENOENT) return log_error_errno(ENOENT, "Failed to access EFI variables, efivarfs" " needs to be available at /sys/firmware/efi/efivars/."); else if (n_options < 0) return log_error_errno(n_options, "Failed to read EFI boot entries: %m"); n_order = efi_get_boot_order(&order); if (n_order == -ENOENT) n_order = 0; else if (n_order < 0) return log_error_errno(n_order, "Failed to read EFI boot order."); /* print entries in BootOrder first */ printf("Boot Loader Entries in EFI Variables:\n"); for (i = 0; i < n_order; i++) print_efi_option(order[i], true); /* print remaining entries */ for (i = 0; i < n_options; i++) { int j; for (j = 0; j < n_order; j++) if (options[i] == order[j]) goto next; print_efi_option(options[i], false); next: continue; } return 0; } static int compare_product(const char *a, const char *b) { size_t x, y; assert(a); assert(b); x = strcspn(a, " "); y = strcspn(b, " "); if (x != y) return x < y ? -1 : x > y ? 1 : 0; return strncmp(a, b, x); } static int compare_version(const char *a, const char *b) { assert(a); assert(b); a += strcspn(a, " "); a += strspn(a, " "); b += strcspn(b, " "); b += strspn(b, " "); return strverscmp(a, b); } static int version_check(int fd, const char *from, const char *to) { _cleanup_free_ char *a = NULL, *b = NULL; _cleanup_close_ int fd2 = -1; int r; assert(fd >= 0); assert(from); assert(to); r = get_file_version(fd, &a); if (r < 0) return r; if (r == 0) { log_error("Source file \"%s\" does not carry version information!", from); return -EINVAL; } fd2 = open(to, O_RDONLY|O_CLOEXEC); if (fd2 < 0) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open \"%s\" for reading: %m", to); } r = get_file_version(fd2, &b); if (r < 0) return r; if (r == 0 || compare_product(a, b) != 0) { log_notice("Skipping \"%s\", since it's owned by another boot loader.", to); return -EEXIST; } if (compare_version(a, b) < 0) { log_warning("Skipping \"%s\", since a newer boot loader version exists already.", to); return -ESTALE; } return 0; } static int copy_file(const char *from, const char *to, bool force) { _cleanup_fclose_ FILE *f = NULL, *g = NULL; char *p; int r; struct timespec t[2]; struct stat st; assert(from); assert(to); f = fopen(from, "re"); if (!f) return log_error_errno(errno, "Failed to open \"%s\" for reading: %m", from); if (!force) { /* If this is an update, then let's compare versions first */ r = version_check(fileno(f), from, to); if (r < 0) return r; } p = strjoina(to, "~"); g = fopen(p, "wxe"); if (!g) { /* Directory doesn't exist yet? Then let's skip this... */ if (!force && errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open \"%s\" for writing: %m", to); } rewind(f); do { size_t k; uint8_t buf[32*1024]; k = fread(buf, 1, sizeof(buf), f); if (ferror(f)) { r = log_error_errno(EIO, "Failed to read \"%s\": %m", from); goto error; } if (k == 0) break; fwrite(buf, 1, k, g); if (ferror(g)) { r = log_error_errno(EIO, "Failed to write \"%s\": %m", to); goto error; } } while (!feof(f)); r = fflush_and_check(g); if (r < 0) { log_error_errno(r, "Failed to write \"%s\": %m", to); goto error; } r = fstat(fileno(f), &st); if (r < 0) { r = log_error_errno(errno, "Failed to get file timestamps of \"%s\": %m", from); goto error; } t[0] = st.st_atim; t[1] = st.st_mtim; r = futimens(fileno(g), t); if (r < 0) { r = log_error_errno(errno, "Failed to set file timestamps on \"%s\": %m", p); goto error; } if (rename(p, to) < 0) { r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", p, to); goto error; } log_info("Copied \"%s\" to \"%s\".", from, to); return 0; error: (void) unlink(p); return r; } static char* strupper(char *s) { char *p; for (p = s; *p; p++) *p = toupper(*p); return s; } static int mkdir_one(const char *prefix, const char *suffix) { char *p; p = strjoina(prefix, "/", suffix); if (mkdir(p, 0700) < 0) { if (errno != EEXIST) return log_error_errno(errno, "Failed to create \"%s\": %m", p); } else log_info("Created \"%s\".", p); return 0; } static const char *efi_subdirs[] = { "EFI", "EFI/systemd", "EFI/Boot", "loader", "loader/entries" }; static int create_dirs(const char *esp_path) { int r; unsigned i; for (i = 0; i < ELEMENTSOF(efi_subdirs); i++) { r = mkdir_one(esp_path, efi_subdirs[i]); if (r < 0) return r; } return 0; } static int copy_one_file(const char *esp_path, const char *name, bool force) { char *p, *q; int r; p = strjoina(BOOTLIBDIR "/", name); q = strjoina(esp_path, "/EFI/systemd/", name); r = copy_file(p, q, force); if (startswith(name, "systemd-boot")) { int k; char *v; /* Create the EFI default boot loader name (specified for removable devices) */ v = strjoina(esp_path, "/EFI/Boot/BOOT", name + strlen("systemd-boot")); strupper(strrchr(v, '/') + 1); k = copy_file(p, v, force); if (k < 0 && r == 0) r = k; } return r; } static int install_binaries(const char *esp_path, bool force) { struct dirent *de; _cleanup_closedir_ DIR *d = NULL; int r = 0; if (force) { /* Don't create any of these directories when we are * just updating. When we update we'll drop-in our * files (unless there are newer ones already), but we * won't create the directories for them in the first * place. */ r = create_dirs(esp_path); if (r < 0) return r; } d = opendir(BOOTLIBDIR); if (!d) return log_error_errno(errno, "Failed to open \""BOOTLIBDIR"\": %m"); FOREACH_DIRENT(de, d, break) { int k; if (!endswith_no_case(de->d_name, ".efi")) continue; k = copy_one_file(esp_path, de->d_name, force); if (k < 0 && r == 0) r = k; } return r; } static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) { _cleanup_free_ char *opath = NULL; sd_id128_t ouuid; int r; r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL); if (r < 0) return false; if (!sd_id128_equal(uuid, ouuid)) return false; if (!streq_ptr(path, opath)) return false; return true; } static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) { _cleanup_free_ uint16_t *options = NULL; int n, i; n = efi_get_boot_options(&options); if (n < 0) return n; /* find already existing systemd-boot entry */ for (i = 0; i < n; i++) if (same_entry(options[i], uuid, path)) { *id = options[i]; return 1; } /* find free slot in the sorted BootXXXX variable list */ for (i = 0; i < n; i++) if (i != options[i]) { *id = i; return 1; } /* use the next one */ if (i == 0xffff) return -ENOSPC; *id = i; return 0; } static int insert_into_order(uint16_t slot, bool first) { _cleanup_free_ uint16_t *order = NULL; uint16_t *t; int n, i; n = efi_get_boot_order(&order); if (n <= 0) /* no entry, add us */ return efi_set_boot_order(&slot, 1); /* are we the first and only one? */ if (n == 1 && order[0] == slot) return 0; /* are we already in the boot order? */ for (i = 0; i < n; i++) { if (order[i] != slot) continue; /* we do not require to be the first one, all is fine */ if (!first) return 0; /* move us to the first slot */ memmove(order + 1, order, i * sizeof(uint16_t)); order[0] = slot; return efi_set_boot_order(order, n); } /* extend array */ t = realloc(order, (n + 1) * sizeof(uint16_t)); if (!t) return -ENOMEM; order = t; /* add us to the top or end of the list */ if (first) { memmove(order + 1, order, n * sizeof(uint16_t)); order[0] = slot; } else order[n] = slot; return efi_set_boot_order(order, n + 1); } static int remove_from_order(uint16_t slot) { _cleanup_free_ uint16_t *order = NULL; int n, i; n = efi_get_boot_order(&order); if (n <= 0) return n; for (i = 0; i < n; i++) { if (order[i] != slot) continue; if (i + 1 < n) memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t)); return efi_set_boot_order(order, n - 1); } return 0; } static int install_variables(const char *esp_path, uint32_t part, uint64_t pstart, uint64_t psize, sd_id128_t uuid, const char *path, bool first) { char *p; uint16_t slot; int r; if (!is_efi_boot()) { log_warning("Not booted with EFI, skipping EFI variable setup."); return 0; } p = strjoina(esp_path, path); if (access(p, F_OK) < 0) { if (errno == ENOENT) return 0; else return log_error_errno(errno, "Cannot access \"%s\": %m", p); } r = find_slot(uuid, path, &slot); if (r < 0) return log_error_errno(r, r == -ENOENT ? "Failed to access EFI variables. Is the \"efivarfs\" filesystem mounted?" : "Failed to determine current boot order: %m"); if (first || r == false) { r = efi_add_boot_option(slot, "Linux Boot Manager", part, pstart, psize, uuid, path); if (r < 0) return log_error_errno(r, "Failed to create EFI Boot variable entry: %m"); log_info("Created EFI boot entry \"Linux Boot Manager\"."); } return insert_into_order(slot, first); } static int remove_boot_efi(const char *esp_path) { char *p; _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r, c = 0; p = strjoina(esp_path, "/EFI/Boot"); d = opendir(p); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open directory \"%s\": %m", p); } FOREACH_DIRENT(de, d, break) { _cleanup_close_ int fd = -1; _cleanup_free_ char *v = NULL; if (!endswith_no_case(de->d_name, ".efi")) continue; if (!startswith_no_case(de->d_name, "Boot")) continue; fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC); if (fd < 0) return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name); r = get_file_version(fd, &v); if (r < 0) return r; if (r > 0 && startswith(v, "systemd-boot ")) { r = unlinkat(dirfd(d), de->d_name, 0); if (r < 0) return log_error_errno(errno, "Failed to remove \"%s/%s\": %m", p, de->d_name); log_info("Removed \"%s/%s\".", p, de->d_name); } c++; } return c; } static int rmdir_one(const char *prefix, const char *suffix) { char *p; p = strjoina(prefix, "/", suffix); if (rmdir(p) < 0) { if (!IN_SET(errno, ENOENT, ENOTEMPTY)) return log_error_errno(errno, "Failed to remove \"%s\": %m", p); } else log_info("Removed \"%s\".", p); return 0; } static int remove_binaries(const char *esp_path) { char *p; int r, q; unsigned i; p = strjoina(esp_path, "/EFI/systemd"); r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL); q = remove_boot_efi(esp_path); if (q < 0 && r == 0) r = q; for (i = ELEMENTSOF(efi_subdirs); i > 0; i--) { q = rmdir_one(esp_path, efi_subdirs[i-1]); if (q < 0 && r == 0) r = q; } return r; } static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) { uint16_t slot; int r; if (!is_efi_boot()) return 0; r = find_slot(uuid, path, &slot); if (r != 1) return 0; r = efi_remove_boot_option(slot); if (r < 0) return r; if (in_order) return remove_from_order(slot); else return 0; } static int install_loader_config(const char *esp_path) { char *p; char line[64]; char *machine = NULL; _cleanup_fclose_ FILE *f = NULL, *g = NULL; f = fopen("/etc/machine-id", "re"); if (!f) return errno == ENOENT ? 0 : -errno; if (fgets(line, sizeof(line), f) != NULL) { char *s; s = strchr(line, '\n'); if (s) s[0] = '\0'; if (strlen(line) == 32) machine = line; } if (!machine) return -ESRCH; p = strjoina(esp_path, "/loader/loader.conf"); g = fopen(p, "wxe"); if (g) { fprintf(g, "#timeout 3\n"); fprintf(g, "default %s-*\n", machine); if (ferror(g)) return log_error_errno(EIO, "Failed to write \"%s\": %m", p); } return 0; } static int help(void) { printf("%s [COMMAND] [OPTIONS...]\n" "\n" "Install, update or remove the systemd-boot EFI boot manager.\n\n" " -h --help Show this help\n" " --version Print version\n" " --path=PATH Path to the EFI System Partition (ESP)\n" " --no-variables Don't touch EFI variables\n" "\n" "Commands:\n" " status Show status of installed systemd-boot and EFI variables\n" " install Install systemd-boot to the ESP and EFI variables\n" " update Update systemd-boot in the ESP and EFI variables\n" " remove Remove systemd-boot from the ESP and EFI variables\n", program_invocation_short_name); return 0; } static const char *arg_path = "/boot"; static bool arg_touch_variables = true; static int parse_argv(int argc, char *argv[]) { enum { ARG_PATH = 0x100, ARG_VERSION, ARG_NO_VARIABLES, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "path", required_argument, NULL, ARG_PATH }, { "no-variables", no_argument, NULL, ARG_NO_VARIABLES }, { NULL, 0, NULL, 0 } }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_PATH: arg_path = optarg; break; case ARG_NO_VARIABLES: arg_touch_variables = false; break; case '?': return -EINVAL; default: assert_not_reached("Unknown option"); } return 1; } static void read_loader_efi_var(const char *name, char **var) { int r; r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var); if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to read EFI variable %s: %m", name); } static int bootctl_main(int argc, char*argv[]) { enum action { ACTION_STATUS, ACTION_INSTALL, ACTION_UPDATE, ACTION_REMOVE } arg_action = ACTION_STATUS; static const struct { const char* verb; enum action action; } verbs[] = { { "status", ACTION_STATUS }, { "install", ACTION_INSTALL }, { "update", ACTION_UPDATE }, { "remove", ACTION_REMOVE }, }; sd_id128_t uuid = {}; uint32_t part = 0; uint64_t pstart = 0, psize = 0; int r, q; if (argv[optind]) { unsigned i; for (i = 0; i < ELEMENTSOF(verbs); i++) { if (!streq(argv[optind], verbs[i].verb)) continue; arg_action = verbs[i].action; break; } if (i >= ELEMENTSOF(verbs)) { log_error("Unknown operation \"%s\"", argv[optind]); return -EINVAL; } } if (geteuid() != 0) return log_error_errno(EPERM, "Need to be root."); r = verify_esp(arg_path, &part, &pstart, &psize, &uuid); if (r == -ENODEV && !arg_path) log_notice("You might want to use --path= to indicate the path to your ESP, in case it is not mounted on /boot."); if (r < 0) return r; switch (arg_action) { case ACTION_STATUS: { _cleanup_free_ char *fw_type = NULL; _cleanup_free_ char *fw_info = NULL; _cleanup_free_ char *loader = NULL; _cleanup_free_ char *loader_path = NULL; sd_id128_t loader_part_uuid = {}; if (is_efi_boot()) { read_loader_efi_var("LoaderFirmwareType", &fw_type); read_loader_efi_var("LoaderFirmwareInfo", &fw_info); read_loader_efi_var("LoaderInfo", &loader); read_loader_efi_var("LoaderImageIdentifier", &loader_path); if (loader_path) efi_tilt_backslashes(loader_path); r = efi_loader_get_device_part_uuid(&loader_part_uuid); if (r < 0 && r == -ENOENT) log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m"); printf("System:\n"); printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info)); r = is_efi_secure_boot(); if (r < 0) log_warning_errno(r, "Failed to query secure boot status: %m"); else printf(" Secure Boot: %s\n", r ? "enabled" : "disabled"); r = is_efi_secure_boot_setup_mode(); if (r < 0) log_warning_errno(r, "Failed to query secure boot mode: %m"); else printf(" Setup Mode: %s\n", r ? "setup" : "user"); printf("\n"); printf("Loader:\n"); printf(" Product: %s\n", strna(loader)); if (!sd_id128_equal(loader_part_uuid, SD_ID128_NULL)) printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", SD_ID128_FORMAT_VAL(loader_part_uuid)); else printf(" Partition: n/a\n"); printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), strna(loader_path)); printf("\n"); } else printf("System:\n Not booted with EFI\n"); r = status_binaries(arg_path, uuid); if (r < 0) return r; if (arg_touch_variables) r = status_variables(); break; } case ACTION_INSTALL: case ACTION_UPDATE: umask(0002); r = install_binaries(arg_path, arg_action == ACTION_INSTALL); if (r < 0) return r; if (arg_action == ACTION_INSTALL) { r = install_loader_config(arg_path); if (r < 0) return r; } if (arg_touch_variables) r = install_variables(arg_path, part, pstart, psize, uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", arg_action == ACTION_INSTALL); break; case ACTION_REMOVE: r = remove_binaries(arg_path); if (arg_touch_variables) { q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true); if (q < 0 && r == 0) r = q; } break; } return r; } int main(int argc, char *argv[]) { int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = bootctl_main(argc, argv); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/boot/efi/000077500000000000000000000000001265713322000153565ustar00rootroot00000000000000systemd-229/src/boot/efi/.gitignore000066400000000000000000000000321265713322000173410ustar00rootroot00000000000000/systemd_boot.so /stub.so systemd-229/src/boot/efi/boot.c000066400000000000000000002204621265713322000164730ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2012-2015 Kay Sievers * Copyright (C) 2012-2015 Harald Hoyer */ #include #include #include "console.h" #include "disk.h" #include "graphics.h" #include "linux.h" #include "pefile.h" #include "util.h" #ifndef EFI_OS_INDICATIONS_BOOT_TO_FW_UI #define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001ULL #endif /* magic string to find in the binary image */ static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot " VERSION " ####"; static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE; enum loader_type { LOADER_UNDEFINED, LOADER_EFI, LOADER_LINUX }; typedef struct { CHAR16 *file; CHAR16 *title_show; CHAR16 *title; CHAR16 *version; CHAR16 *machine_id; EFI_HANDLE *device; enum loader_type type; CHAR16 *loader; CHAR16 *options; CHAR16 key; EFI_STATUS (*call)(VOID); BOOLEAN no_autoselect; BOOLEAN non_unique; } ConfigEntry; typedef struct { ConfigEntry **entries; UINTN entry_count; INTN idx_default; INTN idx_default_efivar; UINTN timeout_sec; UINTN timeout_sec_config; INTN timeout_sec_efivar; CHAR16 *entry_default_pattern; CHAR16 *entry_oneshot; CHAR16 *options_edit; BOOLEAN no_editor; } Config; static VOID cursor_left(UINTN *cursor, UINTN *first) { if ((*cursor) > 0) (*cursor)--; else if ((*first) > 0) (*first)--; } static VOID cursor_right(UINTN *cursor, UINTN *first, UINTN x_max, UINTN len) { if ((*cursor)+1 < x_max) (*cursor)++; else if ((*first) + (*cursor) < len) (*first)++; } static BOOLEAN line_edit(CHAR16 *line_in, CHAR16 **line_out, UINTN x_max, UINTN y_pos) { CHAR16 *line; UINTN size; UINTN len; UINTN first; CHAR16 *print; UINTN cursor; UINTN clear; BOOLEAN exit; BOOLEAN enter; if (!line_in) line_in = L""; size = StrLen(line_in) + 1024; line = AllocatePool(size * sizeof(CHAR16)); StrCpy(line, line_in); len = StrLen(line); print = AllocatePool((x_max+1) * sizeof(CHAR16)); uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, TRUE); first = 0; cursor = 0; clear = 0; enter = FALSE; exit = FALSE; while (!exit) { EFI_STATUS err; UINT64 key; UINTN i; i = len - first; if (i >= x_max-1) i = x_max-1; CopyMem(print, line + first, i * sizeof(CHAR16)); while (clear > 0 && i < x_max-1) { clear--; print[i++] = ' '; } print[i] = '\0'; uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_pos); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, print); uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); err = console_key_read(&key, TRUE); if (EFI_ERROR(err)) continue; switch (key) { case KEYPRESS(0, SCAN_ESC, 0): case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'c'): case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'g'): case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('c')): case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('g')): exit = TRUE; break; case KEYPRESS(0, SCAN_HOME, 0): case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'a'): case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('a')): /* beginning-of-line */ cursor = 0; first = 0; continue; case KEYPRESS(0, SCAN_END, 0): case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'e'): case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('e')): /* end-of-line */ cursor = len - first; if (cursor+1 >= x_max) { cursor = x_max-1; first = len - (x_max-1); } continue; case KEYPRESS(0, SCAN_DOWN, 0): case KEYPRESS(EFI_ALT_PRESSED, 0, 'f'): case KEYPRESS(EFI_CONTROL_PRESSED, SCAN_RIGHT, 0): /* forward-word */ while (line[first + cursor] && line[first + cursor] == ' ') cursor_right(&cursor, &first, x_max, len); while (line[first + cursor] && line[first + cursor] != ' ') cursor_right(&cursor, &first, x_max, len); uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); continue; case KEYPRESS(0, SCAN_UP, 0): case KEYPRESS(EFI_ALT_PRESSED, 0, 'b'): case KEYPRESS(EFI_CONTROL_PRESSED, SCAN_LEFT, 0): /* backward-word */ if ((first + cursor) > 0 && line[first + cursor-1] == ' ') { cursor_left(&cursor, &first); while ((first + cursor) > 0 && line[first + cursor] == ' ') cursor_left(&cursor, &first); } while ((first + cursor) > 0 && line[first + cursor-1] != ' ') cursor_left(&cursor, &first); uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); continue; case KEYPRESS(0, SCAN_RIGHT, 0): case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'f'): case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('f')): /* forward-char */ if (first + cursor == len) continue; cursor_right(&cursor, &first, x_max, len); uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); continue; case KEYPRESS(0, SCAN_LEFT, 0): case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'b'): case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('b')): /* backward-char */ cursor_left(&cursor, &first); uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); continue; case KEYPRESS(EFI_ALT_PRESSED, 0, 'd'): /* kill-word */ clear = 0; for (i = first + cursor; i < len && line[i] == ' '; i++) clear++; for (; i < len && line[i] != ' '; i++) clear++; for (i = first + cursor; i + clear < len; i++) line[i] = line[i + clear]; len -= clear; line[len] = '\0'; continue; case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'w'): case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('w')): case KEYPRESS(EFI_ALT_PRESSED, 0, CHAR_BACKSPACE): /* backward-kill-word */ clear = 0; if ((first + cursor) > 0 && line[first + cursor-1] == ' ') { cursor_left(&cursor, &first); clear++; while ((first + cursor) > 0 && line[first + cursor] == ' ') { cursor_left(&cursor, &first); clear++; } } while ((first + cursor) > 0 && line[first + cursor-1] != ' ') { cursor_left(&cursor, &first); clear++; } uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); for (i = first + cursor; i + clear < len; i++) line[i] = line[i + clear]; len -= clear; line[len] = '\0'; continue; case KEYPRESS(0, SCAN_DELETE, 0): case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'd'): case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('d')): if (len == 0) continue; if (first + cursor == len) continue; for (i = first + cursor; i < len; i++) line[i] = line[i+1]; clear = 1; len--; continue; case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'k'): case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('k')): /* kill-line */ line[first + cursor] = '\0'; clear = len - (first + cursor); len = first + cursor; continue; case KEYPRESS(0, 0, CHAR_LINEFEED): case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN): if (StrCmp(line, line_in) != 0) { *line_out = line; line = NULL; } enter = TRUE; exit = TRUE; break; case KEYPRESS(0, 0, CHAR_BACKSPACE): if (len == 0) continue; if (first == 0 && cursor == 0) continue; for (i = first + cursor-1; i < len; i++) line[i] = line[i+1]; clear = 1; len--; if (cursor > 0) cursor--; if (cursor > 0 || first == 0) continue; /* show full line if it fits */ if (len < x_max) { cursor = first; first = 0; continue; } /* jump left to see what we delete */ if (first > 10) { first -= 10; cursor = 10; } else { cursor = first; first = 0; } continue; case KEYPRESS(0, 0, ' ') ... KEYPRESS(0, 0, '~'): case KEYPRESS(0, 0, 0x80) ... KEYPRESS(0, 0, 0xffff): if (len+1 == size) continue; for (i = len; i > first + cursor; i--) line[i] = line[i-1]; line[first + cursor] = KEYCHAR(key); len++; line[len] = '\0'; if (cursor+1 < x_max) cursor++; else if (first + cursor < len) first++; continue; } } uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE); FreePool(print); FreePool(line); return enter; } static UINTN entry_lookup_key(Config *config, UINTN start, CHAR16 key) { UINTN i; if (key == 0) return -1; /* select entry by number key */ if (key >= '1' && key <= '9') { i = key - '0'; if (i > config->entry_count) i = config->entry_count; return i-1; } /* find matching key in config entries */ for (i = start; i < config->entry_count; i++) if (config->entries[i]->key == key) return i; for (i = 0; i < start; i++) if (config->entries[i]->key == key) return i; return -1; } static VOID print_status(Config *config, CHAR16 *loaded_image_path) { UINT64 key; UINTN i; CHAR16 *s; CHAR8 *b; UINTN x; UINTN y; UINTN size; uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); Print(L"systemd-boot version: " VERSION "\n"); Print(L"architecture: " EFI_MACHINE_TYPE_NAME "\n"); Print(L"loaded image: %s\n", loaded_image_path); Print(L"UEFI specification: %d.%02d\n", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); Print(L"firmware vendor: %s\n", ST->FirmwareVendor); Print(L"firmware version: %d.%02d\n", ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); if (uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x, &y) == EFI_SUCCESS) Print(L"console size: %d x %d\n", x, y); if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) { Print(L"SecureBoot: %s\n", yes_no(*b > 0)); FreePool(b); } if (efivar_get_raw(&global_guid, L"SetupMode", &b, &size) == EFI_SUCCESS) { Print(L"SetupMode: %s\n", *b > 0 ? L"setup" : L"user"); FreePool(b); } if (efivar_get_raw(&global_guid, L"OsIndicationsSupported", &b, &size) == EFI_SUCCESS) { Print(L"OsIndicationsSupported: %d\n", (UINT64)*b); FreePool(b); } Print(L"\n"); Print(L"timeout: %d\n", config->timeout_sec); if (config->timeout_sec_efivar >= 0) Print(L"timeout (EFI var): %d\n", config->timeout_sec_efivar); Print(L"timeout (config): %d\n", config->timeout_sec_config); if (config->entry_default_pattern) Print(L"default pattern: '%s'\n", config->entry_default_pattern); Print(L"editor: %s\n", yes_no(!config->no_editor)); Print(L"\n"); Print(L"config entry count: %d\n", config->entry_count); Print(L"entry selected idx: %d\n", config->idx_default); if (config->idx_default_efivar >= 0) Print(L"entry EFI var idx: %d\n", config->idx_default_efivar); Print(L"\n"); if (efivar_get_int(L"LoaderConfigTimeout", &i) == EFI_SUCCESS) Print(L"LoaderConfigTimeout: %d\n", i); if (config->entry_oneshot) Print(L"LoaderEntryOneShot: %s\n", config->entry_oneshot); if (efivar_get(L"LoaderDevicePartUUID", &s) == EFI_SUCCESS) { Print(L"LoaderDevicePartUUID: %s\n", s); FreePool(s); } if (efivar_get(L"LoaderEntryDefault", &s) == EFI_SUCCESS) { Print(L"LoaderEntryDefault: %s\n", s); FreePool(s); } Print(L"\n--- press key ---\n\n"); console_key_read(&key, TRUE); for (i = 0; i < config->entry_count; i++) { ConfigEntry *entry; if (key == KEYPRESS(0, SCAN_ESC, 0) || key == KEYPRESS(0, 0, 'q')) break; entry = config->entries[i]; Print(L"config entry: %d/%d\n", i+1, config->entry_count); if (entry->file) Print(L"file '%s'\n", entry->file); Print(L"title show '%s'\n", entry->title_show); if (entry->title) Print(L"title '%s'\n", entry->title); if (entry->version) Print(L"version '%s'\n", entry->version); if (entry->machine_id) Print(L"machine-id '%s'\n", entry->machine_id); if (entry->device) { EFI_DEVICE_PATH *device_path; CHAR16 *str; device_path = DevicePathFromHandle(entry->device); if (device_path) { str = DevicePathToStr(device_path); Print(L"device handle '%s'\n", str); FreePool(str); } } if (entry->loader) Print(L"loader '%s'\n", entry->loader); if (entry->options) Print(L"options '%s'\n", entry->options); Print(L"auto-select %s\n", yes_no(!entry->no_autoselect)); if (entry->call) Print(L"internal call yes\n"); Print(L"\n--- press key ---\n\n"); console_key_read(&key, TRUE); } uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); } static BOOLEAN menu_run(Config *config, ConfigEntry **chosen_entry, CHAR16 *loaded_image_path) { EFI_STATUS err; UINTN visible_max; UINTN idx_highlight; UINTN idx_highlight_prev; UINTN idx_first; UINTN idx_last; BOOLEAN refresh; BOOLEAN highlight; UINTN i; UINTN line_width; CHAR16 **lines; UINTN x_start; UINTN y_start; UINTN x_max; UINTN y_max; CHAR16 *status; CHAR16 *clearline; INTN timeout_remain; INT16 idx; BOOLEAN exit = FALSE; BOOLEAN run = TRUE; BOOLEAN wait = FALSE; graphics_mode(FALSE); uefi_call_wrapper(ST->ConIn->Reset, 2, ST->ConIn, FALSE); uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE); uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); /* draw a single character to make ClearScreen work on some firmware */ uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L" "); uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); err = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x_max, &y_max); if (EFI_ERROR(err)) { x_max = 80; y_max = 25; } /* we check 10 times per second for a keystroke */ if (config->timeout_sec > 0) timeout_remain = config->timeout_sec * 10; else timeout_remain = -1; idx_highlight = config->idx_default; idx_highlight_prev = 0; visible_max = y_max - 2; if ((UINTN)config->idx_default >= visible_max) idx_first = config->idx_default-1; else idx_first = 0; idx_last = idx_first + visible_max-1; refresh = TRUE; highlight = FALSE; /* length of the longest entry */ line_width = 5; for (i = 0; i < config->entry_count; i++) { UINTN entry_len; entry_len = StrLen(config->entries[i]->title_show); if (line_width < entry_len) line_width = entry_len; } if (line_width > x_max-6) line_width = x_max-6; /* offsets to center the entries on the screen */ x_start = (x_max - (line_width)) / 2; if (config->entry_count < visible_max) y_start = ((visible_max - config->entry_count) / 2) + 1; else y_start = 0; /* menu entries title lines */ lines = AllocatePool(sizeof(CHAR16 *) * config->entry_count); for (i = 0; i < config->entry_count; i++) { UINTN j, k; lines[i] = AllocatePool(((x_max+1) * sizeof(CHAR16))); for (j = 0; j < x_start; j++) lines[i][j] = ' '; for (k = 0; config->entries[i]->title_show[k] != '\0' && j < x_max; j++, k++) lines[i][j] = config->entries[i]->title_show[k]; for (; j < x_max; j++) lines[i][j] = ' '; lines[i][x_max] = '\0'; } status = NULL; clearline = AllocatePool((x_max+1) * sizeof(CHAR16)); for (i = 0; i < x_max; i++) clearline[i] = ' '; clearline[i] = 0; while (!exit) { UINT64 key; if (refresh) { for (i = 0; i < config->entry_count; i++) { if (i < idx_first || i > idx_last) continue; uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_start + i - idx_first); if (i == idx_highlight) uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_BLACK|EFI_BACKGROUND_LIGHTGRAY); else uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, lines[i]); if ((INTN)i == config->idx_default_efivar) { uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, x_start-3, y_start + i - idx_first); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L"=>"); } } refresh = FALSE; } else if (highlight) { uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_start + idx_highlight_prev - idx_first); uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, lines[idx_highlight_prev]); if ((INTN)idx_highlight_prev == config->idx_default_efivar) { uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, x_start-3, y_start + idx_highlight_prev - idx_first); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L"=>"); } uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_start + idx_highlight - idx_first); uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_BLACK|EFI_BACKGROUND_LIGHTGRAY); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, lines[idx_highlight]); if ((INTN)idx_highlight == config->idx_default_efivar) { uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, x_start-3, y_start + idx_highlight - idx_first); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L"=>"); } highlight = FALSE; } if (timeout_remain > 0) { FreePool(status); status = PoolPrint(L"Boot in %d sec.", (timeout_remain + 5) / 10); } /* print status at last line of screen */ if (status) { UINTN len; UINTN x; /* center line */ len = StrLen(status); if (len < x_max) x = (x_max - len) / 2; else x = 0; uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_max-1); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline + (x_max - x)); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, status); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1 + x + len); } err = console_key_read(&key, wait); if (EFI_ERROR(err)) { /* timeout reached */ if (timeout_remain == 0) { exit = TRUE; break; } /* sleep and update status */ if (timeout_remain > 0) { uefi_call_wrapper(BS->Stall, 1, 100 * 1000); timeout_remain--; continue; } /* timeout disabled, wait for next key */ wait = TRUE; continue; } timeout_remain = -1; /* clear status after keystroke */ if (status) { FreePool(status); status = NULL; uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_max-1); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1); } idx_highlight_prev = idx_highlight; switch (key) { case KEYPRESS(0, SCAN_UP, 0): case KEYPRESS(0, 0, 'k'): if (idx_highlight > 0) idx_highlight--; break; case KEYPRESS(0, SCAN_DOWN, 0): case KEYPRESS(0, 0, 'j'): if (idx_highlight < config->entry_count-1) idx_highlight++; break; case KEYPRESS(0, SCAN_HOME, 0): case KEYPRESS(EFI_ALT_PRESSED, 0, '<'): if (idx_highlight > 0) { refresh = TRUE; idx_highlight = 0; } break; case KEYPRESS(0, SCAN_END, 0): case KEYPRESS(EFI_ALT_PRESSED, 0, '>'): if (idx_highlight < config->entry_count-1) { refresh = TRUE; idx_highlight = config->entry_count-1; } break; case KEYPRESS(0, SCAN_PAGE_UP, 0): if (idx_highlight > visible_max) idx_highlight -= visible_max; else idx_highlight = 0; break; case KEYPRESS(0, SCAN_PAGE_DOWN, 0): idx_highlight += visible_max; if (idx_highlight > config->entry_count-1) idx_highlight = config->entry_count-1; break; case KEYPRESS(0, 0, CHAR_LINEFEED): case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN): exit = TRUE; break; case KEYPRESS(0, SCAN_F1, 0): case KEYPRESS(0, 0, 'h'): case KEYPRESS(0, 0, '?'): status = StrDuplicate(L"(d)efault, (t/T)timeout, (e)dit, (v)ersion (Q)uit (P)rint (h)elp"); break; case KEYPRESS(0, 0, 'Q'): exit = TRUE; run = FALSE; break; case KEYPRESS(0, 0, 'd'): if (config->idx_default_efivar != (INTN)idx_highlight) { /* store the selected entry in a persistent EFI variable */ efivar_set(L"LoaderEntryDefault", config->entries[idx_highlight]->file, TRUE); config->idx_default_efivar = idx_highlight; status = StrDuplicate(L"Default boot entry selected."); } else { /* clear the default entry EFI variable */ efivar_set(L"LoaderEntryDefault", NULL, TRUE); config->idx_default_efivar = -1; status = StrDuplicate(L"Default boot entry cleared."); } refresh = TRUE; break; case KEYPRESS(0, 0, '-'): case KEYPRESS(0, 0, 'T'): if (config->timeout_sec_efivar > 0) { config->timeout_sec_efivar--; efivar_set_int(L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE); if (config->timeout_sec_efivar > 0) status = PoolPrint(L"Menu timeout set to %d sec.", config->timeout_sec_efivar); else status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu."); } else if (config->timeout_sec_efivar <= 0){ config->timeout_sec_efivar = -1; efivar_set(L"LoaderConfigTimeout", NULL, TRUE); if (config->timeout_sec_config > 0) status = PoolPrint(L"Menu timeout of %d sec is defined by configuration file.", config->timeout_sec_config); else status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu."); } break; case KEYPRESS(0, 0, '+'): case KEYPRESS(0, 0, 't'): if (config->timeout_sec_efivar == -1 && config->timeout_sec_config == 0) config->timeout_sec_efivar++; config->timeout_sec_efivar++; efivar_set_int(L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE); if (config->timeout_sec_efivar > 0) status = PoolPrint(L"Menu timeout set to %d sec.", config->timeout_sec_efivar); else status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu."); break; case KEYPRESS(0, 0, 'e'): /* only the options of configured entries can be edited */ if (config->no_editor || config->entries[idx_highlight]->type == LOADER_UNDEFINED) break; uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_max-1); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1); if (line_edit(config->entries[idx_highlight]->options, &config->options_edit, x_max-1, y_max-1)) exit = TRUE; uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_max-1); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1); break; case KEYPRESS(0, 0, 'v'): status = PoolPrint(L"systemd-boot " VERSION " (" EFI_MACHINE_TYPE_NAME "), UEFI Specification %d.%02d, Vendor %s %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff, ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); break; case KEYPRESS(0, 0, 'P'): print_status(config, loaded_image_path); refresh = TRUE; break; case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'l'): case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('l')): refresh = TRUE; break; default: /* jump with a hotkey directly to a matching entry */ idx = entry_lookup_key(config, idx_highlight+1, KEYCHAR(key)); if (idx < 0) break; idx_highlight = idx; refresh = TRUE; } if (idx_highlight > idx_last) { idx_last = idx_highlight; idx_first = 1 + idx_highlight - visible_max; refresh = TRUE; } else if (idx_highlight < idx_first) { idx_first = idx_highlight; idx_last = idx_highlight + visible_max-1; refresh = TRUE; } if (!refresh && idx_highlight != idx_highlight_prev) highlight = TRUE; } *chosen_entry = config->entries[idx_highlight]; for (i = 0; i < config->entry_count; i++) FreePool(lines[i]); FreePool(lines); FreePool(clearline); uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_WHITE|EFI_BACKGROUND_BLACK); uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); return run; } static VOID config_add_entry(Config *config, ConfigEntry *entry) { if ((config->entry_count & 15) == 0) { UINTN i; i = config->entry_count + 16; if (config->entry_count == 0) config->entries = AllocatePool(sizeof(VOID *) * i); else config->entries = ReallocatePool(config->entries, sizeof(VOID *) * config->entry_count, sizeof(VOID *) * i); } config->entries[config->entry_count++] = entry; } static VOID config_entry_free(ConfigEntry *entry) { FreePool(entry->title_show); FreePool(entry->title); FreePool(entry->machine_id); FreePool(entry->loader); FreePool(entry->options); } static BOOLEAN is_digit(CHAR16 c) { return (c >= '0') && (c <= '9'); } static UINTN c_order(CHAR16 c) { if (c == '\0') return 0; if (is_digit(c)) return 0; else if ((c >= 'a') && (c <= 'z')) return c; else return c + 0x10000; } static INTN str_verscmp(CHAR16 *s1, CHAR16 *s2) { CHAR16 *os1 = s1; CHAR16 *os2 = s2; while (*s1 || *s2) { INTN first; while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) { INTN order; order = c_order(*s1) - c_order(*s2); if (order) return order; s1++; s2++; } while (*s1 == '0') s1++; while (*s2 == '0') s2++; first = 0; while (is_digit(*s1) && is_digit(*s2)) { if (first == 0) first = *s1 - *s2; s1++; s2++; } if (is_digit(*s1)) return 1; if (is_digit(*s2)) return -1; if (first) return first; } return StrCmp(os1, os2); } static CHAR8 *line_get_key_value(CHAR8 *content, CHAR8 *sep, UINTN *pos, CHAR8 **key_ret, CHAR8 **value_ret) { CHAR8 *line; UINTN linelen; CHAR8 *value; skip: line = content + *pos; if (*line == '\0') return NULL; linelen = 0; while (line[linelen] && !strchra((CHAR8 *)"\n\r", line[linelen])) linelen++; /* move pos to next line */ *pos += linelen; if (content[*pos]) (*pos)++; /* empty line */ if (linelen == 0) goto skip; /* terminate line */ line[linelen] = '\0'; /* remove leading whitespace */ while (strchra((CHAR8 *)" \t", *line)) { line++; linelen--; } /* remove trailing whitespace */ while (linelen > 0 && strchra(sep, line[linelen-1])) linelen--; line[linelen] = '\0'; if (*line == '#') goto skip; /* split key/value */ value = line; while (*value && !strchra(sep, *value)) value++; if (*value == '\0') goto skip; *value = '\0'; value++; while (*value && strchra(sep, *value)) value++; /* unquote */ if (value[0] == '\"' && line[linelen-1] == '\"') { value++; line[linelen-1] = '\0'; } *key_ret = line; *value_ret = value; return line; } static VOID config_defaults_load_from_file(Config *config, CHAR8 *content) { CHAR8 *line; UINTN pos = 0; CHAR8 *key, *value; line = content; while ((line = line_get_key_value(content, (CHAR8 *)" \t", &pos, &key, &value))) { if (strcmpa((CHAR8 *)"timeout", key) == 0) { CHAR16 *s; s = stra_to_str(value); config->timeout_sec_config = Atoi(s); config->timeout_sec = config->timeout_sec_config; FreePool(s); continue; } if (strcmpa((CHAR8 *)"default", key) == 0) { FreePool(config->entry_default_pattern); config->entry_default_pattern = stra_to_str(value); StrLwr(config->entry_default_pattern); continue; } if (strcmpa((CHAR8 *)"editor", key) == 0) { BOOLEAN on; if (EFI_ERROR(parse_boolean(value, &on))) continue; config->no_editor = !on; } } } static VOID config_entry_add_from_file(Config *config, EFI_HANDLE *device, CHAR16 *file, CHAR8 *content, CHAR16 *loaded_image_path) { ConfigEntry *entry; CHAR8 *line; UINTN pos = 0; CHAR8 *key, *value; UINTN len; CHAR16 *initrd = NULL; entry = AllocateZeroPool(sizeof(ConfigEntry)); line = content; while ((line = line_get_key_value(content, (CHAR8 *)" \t", &pos, &key, &value))) { if (strcmpa((CHAR8 *)"title", key) == 0) { FreePool(entry->title); entry->title = stra_to_str(value); continue; } if (strcmpa((CHAR8 *)"version", key) == 0) { FreePool(entry->version); entry->version = stra_to_str(value); continue; } if (strcmpa((CHAR8 *)"machine-id", key) == 0) { FreePool(entry->machine_id); entry->machine_id = stra_to_str(value); continue; } if (strcmpa((CHAR8 *)"linux", key) == 0) { FreePool(entry->loader); entry->type = LOADER_LINUX; entry->loader = stra_to_path(value); entry->key = 'l'; continue; } if (strcmpa((CHAR8 *)"efi", key) == 0) { entry->type = LOADER_EFI; FreePool(entry->loader); entry->loader = stra_to_path(value); /* do not add an entry for ourselves */ if (StriCmp(entry->loader, loaded_image_path) == 0) { entry->type = LOADER_UNDEFINED; break; } continue; } if (strcmpa((CHAR8 *)"architecture", key) == 0) { /* do not add an entry for an EFI image of architecture not matching with that of the image */ if (strcmpa((CHAR8 *)EFI_MACHINE_TYPE_NAME, value) != 0) { entry->type = LOADER_UNDEFINED; break; } continue; } if (strcmpa((CHAR8 *)"initrd", key) == 0) { CHAR16 *new; new = stra_to_path(value); if (initrd) { CHAR16 *s; s = PoolPrint(L"%s initrd=%s", initrd, new); FreePool(initrd); initrd = s; } else initrd = PoolPrint(L"initrd=%s", new); FreePool(new); continue; } if (strcmpa((CHAR8 *)"options", key) == 0) { CHAR16 *new; new = stra_to_str(value); if (entry->options) { CHAR16 *s; s = PoolPrint(L"%s %s", entry->options, new); FreePool(entry->options); entry->options = s; } else { entry->options = new; new = NULL; } FreePool(new); continue; } } if (entry->type == LOADER_UNDEFINED) { config_entry_free(entry); FreePool(initrd); FreePool(entry); return; } /* add initrd= to options */ if (entry->type == LOADER_LINUX && initrd) { if (entry->options) { CHAR16 *s; s = PoolPrint(L"%s %s", initrd, entry->options); FreePool(entry->options); entry->options = s; } else { entry->options = initrd; initrd = NULL; } } FreePool(initrd); entry->device = device; entry->file = StrDuplicate(file); len = StrLen(entry->file); /* remove ".conf" */ if (len > 5) entry->file[len - 5] = '\0'; StrLwr(entry->file); config_add_entry(config, entry); } static VOID config_load_defaults(Config *config, EFI_FILE *root_dir) { CHAR8 *content = NULL; UINTN sec; UINTN len; EFI_STATUS err; len = file_read(root_dir, L"\\loader\\loader.conf", 0, 0, &content); if (len > 0) config_defaults_load_from_file(config, content); FreePool(content); err = efivar_get_int(L"LoaderConfigTimeout", &sec); if (!EFI_ERROR(err)) { config->timeout_sec_efivar = sec; config->timeout_sec = sec; } else config->timeout_sec_efivar = -1; } static VOID config_load_entries(Config *config, EFI_HANDLE *device, EFI_FILE *root_dir, CHAR16 *loaded_image_path) { EFI_FILE_HANDLE entries_dir; EFI_STATUS err; err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &entries_dir, L"\\loader\\entries", EFI_FILE_MODE_READ, 0ULL); if (!EFI_ERROR(err)) { for (;;) { CHAR16 buf[256]; UINTN bufsize; EFI_FILE_INFO *f; CHAR8 *content = NULL; UINTN len; bufsize = sizeof(buf); err = uefi_call_wrapper(entries_dir->Read, 3, entries_dir, &bufsize, buf); if (bufsize == 0 || EFI_ERROR(err)) break; f = (EFI_FILE_INFO *) buf; if (f->FileName[0] == '.') continue; if (f->Attribute & EFI_FILE_DIRECTORY) continue; len = StrLen(f->FileName); if (len < 6) continue; if (StriCmp(f->FileName + len - 5, L".conf") != 0) continue; if (StrnCmp(f->FileName, L"auto-", 5) == 0) continue; len = file_read(entries_dir, f->FileName, 0, 0, &content); if (len > 0) config_entry_add_from_file(config, device, f->FileName, content, loaded_image_path); FreePool(content); } uefi_call_wrapper(entries_dir->Close, 1, entries_dir); } } static VOID config_sort_entries(Config *config) { UINTN i; for (i = 1; i < config->entry_count; i++) { BOOLEAN more; UINTN k; more = FALSE; for (k = 0; k < config->entry_count - i; k++) { ConfigEntry *entry; if (str_verscmp(config->entries[k]->file, config->entries[k+1]->file) <= 0) continue; entry = config->entries[k]; config->entries[k] = config->entries[k+1]; config->entries[k+1] = entry; more = TRUE; } if (!more) break; } } static VOID config_default_entry_select(Config *config) { CHAR16 *var; EFI_STATUS err; UINTN i; /* * The EFI variable to specify a boot entry for the next, and only the * next reboot. The variable is always cleared directly after it is read. */ err = efivar_get(L"LoaderEntryOneShot", &var); if (!EFI_ERROR(err)) { BOOLEAN found = FALSE; for (i = 0; i < config->entry_count; i++) { if (StrCmp(config->entries[i]->file, var) == 0) { config->idx_default = i; found = TRUE; break; } } config->entry_oneshot = StrDuplicate(var); efivar_set(L"LoaderEntryOneShot", NULL, TRUE); FreePool(var); if (found) return; } /* * The EFI variable to select the default boot entry overrides the * configured pattern. The variable can be set and cleared by pressing * the 'd' key in the loader selection menu, the entry is marked with * an '*'. */ err = efivar_get(L"LoaderEntryDefault", &var); if (!EFI_ERROR(err)) { BOOLEAN found = FALSE; for (i = 0; i < config->entry_count; i++) { if (StrCmp(config->entries[i]->file, var) == 0) { config->idx_default = i; config->idx_default_efivar = i; found = TRUE; break; } } FreePool(var); if (found) return; } config->idx_default_efivar = -1; if (config->entry_count == 0) return; /* * Match the pattern from the end of the list to the start, find last * entry (largest number) matching the given pattern. */ if (config->entry_default_pattern) { i = config->entry_count; while (i--) { if (config->entries[i]->no_autoselect) continue; if (MetaiMatch(config->entries[i]->file, config->entry_default_pattern)) { config->idx_default = i; return; } } } /* select the last suitable entry */ i = config->entry_count; while (i--) { if (config->entries[i]->no_autoselect) continue; config->idx_default = i; return; } /* no entry found */ config->idx_default = -1; } /* generate a unique title, avoiding non-distinguishable menu entries */ static VOID config_title_generate(Config *config) { UINTN i, k; BOOLEAN unique; /* set title */ for (i = 0; i < config->entry_count; i++) { CHAR16 *title; FreePool(config->entries[i]->title_show); title = config->entries[i]->title; if (!title) title = config->entries[i]->file; config->entries[i]->title_show = StrDuplicate(title); } unique = TRUE; for (i = 0; i < config->entry_count; i++) { for (k = 0; k < config->entry_count; k++) { if (i == k) continue; if (StrCmp(config->entries[i]->title_show, config->entries[k]->title_show) != 0) continue; unique = FALSE; config->entries[i]->non_unique = TRUE; config->entries[k]->non_unique = TRUE; } } if (unique) return; /* add version to non-unique titles */ for (i = 0; i < config->entry_count; i++) { CHAR16 *s; if (!config->entries[i]->non_unique) continue; if (!config->entries[i]->version) continue; s = PoolPrint(L"%s (%s)", config->entries[i]->title_show, config->entries[i]->version); FreePool(config->entries[i]->title_show); config->entries[i]->title_show = s; config->entries[i]->non_unique = FALSE; } unique = TRUE; for (i = 0; i < config->entry_count; i++) { for (k = 0; k < config->entry_count; k++) { if (i == k) continue; if (StrCmp(config->entries[i]->title_show, config->entries[k]->title_show) != 0) continue; unique = FALSE; config->entries[i]->non_unique = TRUE; config->entries[k]->non_unique = TRUE; } } if (unique) return; /* add machine-id to non-unique titles */ for (i = 0; i < config->entry_count; i++) { CHAR16 *s; CHAR16 *m; if (!config->entries[i]->non_unique) continue; if (!config->entries[i]->machine_id) continue; m = StrDuplicate(config->entries[i]->machine_id); m[8] = '\0'; s = PoolPrint(L"%s (%s)", config->entries[i]->title_show, m); FreePool(config->entries[i]->title_show); config->entries[i]->title_show = s; config->entries[i]->non_unique = FALSE; FreePool(m); } unique = TRUE; for (i = 0; i < config->entry_count; i++) { for (k = 0; k < config->entry_count; k++) { if (i == k) continue; if (StrCmp(config->entries[i]->title_show, config->entries[k]->title_show) != 0) continue; unique = FALSE; config->entries[i]->non_unique = TRUE; config->entries[k]->non_unique = TRUE; } } if (unique) return; /* add file name to non-unique titles */ for (i = 0; i < config->entry_count; i++) { CHAR16 *s; if (!config->entries[i]->non_unique) continue; s = PoolPrint(L"%s (%s)", config->entries[i]->title_show, config->entries[i]->file); FreePool(config->entries[i]->title_show); config->entries[i]->title_show = s; config->entries[i]->non_unique = FALSE; } } static BOOLEAN config_entry_add_call(Config *config, CHAR16 *title, EFI_STATUS (*call)(VOID)) { ConfigEntry *entry; entry = AllocateZeroPool(sizeof(ConfigEntry)); entry->title = StrDuplicate(title); entry->call = call; entry->no_autoselect = TRUE; config_add_entry(config, entry); return TRUE; } static ConfigEntry *config_entry_add_loader(Config *config, EFI_HANDLE *device, enum loader_type type,CHAR16 *file, CHAR16 key, CHAR16 *title, CHAR16 *loader) { ConfigEntry *entry; entry = AllocateZeroPool(sizeof(ConfigEntry)); entry->type = type; entry->title = StrDuplicate(title); entry->device = device; entry->loader = StrDuplicate(loader); entry->file = StrDuplicate(file); StrLwr(entry->file); entry->key = key; config_add_entry(config, entry); return entry; } static BOOLEAN config_entry_add_loader_auto(Config *config, EFI_HANDLE *device, EFI_FILE *root_dir, CHAR16 *loaded_image_path, CHAR16 *file, CHAR16 key, CHAR16 *title, CHAR16 *loader) { EFI_FILE_HANDLE handle; ConfigEntry *entry; EFI_STATUS err; /* do not add an entry for ourselves */ if (loaded_image_path && StriCmp(loader, loaded_image_path) == 0) return FALSE; /* check existence */ err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, loader, EFI_FILE_MODE_READ, 0ULL); if (EFI_ERROR(err)) return FALSE; uefi_call_wrapper(handle->Close, 1, handle); entry = config_entry_add_loader(config, device, LOADER_UNDEFINED, file, key, title, loader); if (!entry) return FALSE; /* do not boot right away into auto-detected entries */ entry->no_autoselect = TRUE; return TRUE; } static VOID config_entry_add_osx(Config *config) { EFI_STATUS err; UINTN handle_count = 0; EFI_HANDLE *handles = NULL; err = LibLocateHandle(ByProtocol, &FileSystemProtocol, NULL, &handle_count, &handles); if (!EFI_ERROR(err)) { UINTN i; for (i = 0; i < handle_count; i++) { EFI_FILE *root; BOOLEAN found; root = LibOpenRoot(handles[i]); if (!root) continue; found = config_entry_add_loader_auto(config, handles[i], root, NULL, L"auto-osx", 'a', L"OS X", L"\\System\\Library\\CoreServices\\boot.efi"); uefi_call_wrapper(root->Close, 1, root); if (found) break; } FreePool(handles); } } static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_image, EFI_FILE *root_dir) { EFI_FILE_HANDLE linux_dir; EFI_STATUS err; ConfigEntry *entry; err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &linux_dir, L"\\EFI\\Linux", EFI_FILE_MODE_READ, 0ULL); if (!EFI_ERROR(err)) { for (;;) { CHAR16 buf[256]; UINTN bufsize; EFI_FILE_INFO *f; CHAR8 *sections[] = { (UINT8 *)".osrel", (UINT8 *)".cmdline", NULL }; UINTN offs[ELEMENTSOF(sections)-1] = {}; UINTN szs[ELEMENTSOF(sections)-1] = {}; UINTN addrs[ELEMENTSOF(sections)-1] = {}; CHAR8 *content = NULL; UINTN len; CHAR8 *line; UINTN pos = 0; CHAR8 *key, *value; CHAR16 *os_name = NULL; CHAR16 *os_id = NULL; CHAR16 *os_version = NULL; CHAR16 *os_build = NULL; bufsize = sizeof(buf); err = uefi_call_wrapper(linux_dir->Read, 3, linux_dir, &bufsize, buf); if (bufsize == 0 || EFI_ERROR(err)) break; f = (EFI_FILE_INFO *) buf; if (f->FileName[0] == '.') continue; if (f->Attribute & EFI_FILE_DIRECTORY) continue; len = StrLen(f->FileName); if (len < 5) continue; if (StriCmp(f->FileName + len - 4, L".efi") != 0) continue; /* look for .osrel and .cmdline sections in the .efi binary */ err = pefile_locate_sections(linux_dir, f->FileName, sections, addrs, offs, szs); if (EFI_ERROR(err)) continue; len = file_read(linux_dir, f->FileName, offs[0], szs[0], &content); if (len <= 0) continue; /* read properties from the embedded os-release file */ line = content; while ((line = line_get_key_value(content, (CHAR8 *)"=", &pos, &key, &value))) { if (strcmpa((CHAR8 *)"PRETTY_NAME", key) == 0) { FreePool(os_name); os_name = stra_to_str(value); continue; } if (strcmpa((CHAR8 *)"ID", key) == 0) { FreePool(os_id); os_id = stra_to_str(value); continue; } if (strcmpa((CHAR8 *)"VERSION_ID", key) == 0) { FreePool(os_version); os_version = stra_to_str(value); continue; } if (strcmpa((CHAR8 *)"BUILD_ID", key) == 0) { FreePool(os_build); os_build = stra_to_str(value); continue; } } if (os_name && os_id && (os_version || os_build)) { CHAR16 *conf; CHAR16 *path; CHAR16 *cmdline; conf = PoolPrint(L"%s-%s", os_id, os_version ? : os_build); path = PoolPrint(L"\\EFI\\Linux\\%s", f->FileName); entry = config_entry_add_loader(config, loaded_image->DeviceHandle, LOADER_LINUX, conf, 'l', os_name, path); FreePool(content); /* read the embedded cmdline file */ len = file_read(linux_dir, f->FileName, offs[1], szs[1] - 1 , &content); if (len > 0) { cmdline = stra_to_str(content); entry->options = cmdline; cmdline = NULL; } FreePool(cmdline); FreePool(conf); FreePool(path); } FreePool(os_name); FreePool(os_id); FreePool(os_version); FreePool(os_build); FreePool(content); } uefi_call_wrapper(linux_dir->Close, 1, linux_dir); } } static EFI_STATUS image_start(EFI_HANDLE parent_image, const Config *config, const ConfigEntry *entry) { EFI_HANDLE image; EFI_DEVICE_PATH *path; CHAR16 *options; EFI_STATUS err; path = FileDevicePath(entry->device, entry->loader); if (!path) { Print(L"Error getting device path."); uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); return EFI_INVALID_PARAMETER; } err = uefi_call_wrapper(BS->LoadImage, 6, FALSE, parent_image, path, NULL, 0, &image); if (EFI_ERROR(err)) { Print(L"Error loading %s: %r", entry->loader, err); uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); goto out; } if (config->options_edit) options = config->options_edit; else if (entry->options) options = entry->options; else options = NULL; if (options) { EFI_LOADED_IMAGE *loaded_image; err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image, parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR(err)) { Print(L"Error getting LoadedImageProtocol handle: %r", err); uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); goto out_unload; } loaded_image->LoadOptions = options; loaded_image->LoadOptionsSize = (StrLen(loaded_image->LoadOptions)+1) * sizeof(CHAR16); } efivar_set_time_usec(L"LoaderTimeExecUSec", 0); err = uefi_call_wrapper(BS->StartImage, 3, image, NULL, NULL); out_unload: uefi_call_wrapper(BS->UnloadImage, 1, image); out: FreePool(path); return err; } static EFI_STATUS reboot_into_firmware(VOID) { CHAR8 *b; UINTN size; UINT64 osind; EFI_STATUS err; osind = EFI_OS_INDICATIONS_BOOT_TO_FW_UI; err = efivar_get_raw(&global_guid, L"OsIndications", &b, &size); if (!EFI_ERROR(err)) osind |= (UINT64)*b; FreePool(b); err = efivar_set_raw(&global_guid, L"OsIndications", (CHAR8 *)&osind, sizeof(UINT64), TRUE); if (EFI_ERROR(err)) return err; err = uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold, EFI_SUCCESS, 0, NULL); Print(L"Error calling ResetSystem: %r", err); uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); return err; } static VOID config_free(Config *config) { UINTN i; for (i = 0; i < config->entry_count; i++) config_entry_free(config->entries[i]); FreePool(config->entries); FreePool(config->entry_default_pattern); FreePool(config->options_edit); FreePool(config->entry_oneshot); } EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { CHAR16 *s; CHAR8 *b; UINTN size; EFI_LOADED_IMAGE *loaded_image; EFI_FILE *root_dir; CHAR16 *loaded_image_path; EFI_STATUS err; Config config; UINT64 init_usec; BOOLEAN menu = FALSE; CHAR16 uuid[37]; InitializeLib(image, sys_table); init_usec = time_usec(); efivar_set_time_usec(L"LoaderTimeInitUSec", init_usec); efivar_set(L"LoaderInfo", L"systemd-boot " VERSION, FALSE); s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); efivar_set(L"LoaderFirmwareInfo", s, FALSE); FreePool(s); s = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); efivar_set(L"LoaderFirmwareType", s, FALSE); FreePool(s); err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image, image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR(err)) { Print(L"Error getting a LoadedImageProtocol handle: %r ", err); uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); return err; } /* export the device path this image is started from */ if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) efivar_set(L"LoaderDevicePartUUID", uuid, FALSE); root_dir = LibOpenRoot(loaded_image->DeviceHandle); if (!root_dir) { Print(L"Unable to open root directory: %r ", err); uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); return EFI_LOAD_ERROR; } /* the filesystem path to this image, to prevent adding ourselves to the menu */ loaded_image_path = DevicePathToStr(loaded_image->FilePath); efivar_set(L"LoaderImageIdentifier", loaded_image_path, FALSE); ZeroMem(&config, sizeof(Config)); config_load_defaults(&config, root_dir); /* scan /EFI/Linux/ directory */ config_entry_add_linux(&config, loaded_image, root_dir); /* scan /loader/entries/\*.conf files */ config_load_entries(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path); /* sort entries after version number */ config_sort_entries(&config); /* if we find some well-known loaders, add them to the end of the list */ config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path, L"auto-windows", 'w', L"Windows Boot Manager", L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi"); config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path, L"auto-efi-shell", 's', L"EFI Shell", L"\\shell" EFI_MACHINE_TYPE_NAME ".efi"); config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path, L"auto-efi-default", '\0', L"EFI Default Loader", L"\\EFI\\Boot\\boot" EFI_MACHINE_TYPE_NAME ".efi"); config_entry_add_osx(&config); if (efivar_get_raw(&global_guid, L"OsIndicationsSupported", &b, &size) == EFI_SUCCESS) { UINT64 osind = (UINT64)*b; if (osind & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) config_entry_add_call(&config, L"Reboot Into Firmware Interface", reboot_into_firmware); FreePool(b); } if (config.entry_count == 0) { Print(L"No loader found. Configuration files in \\loader\\entries\\*.conf are needed."); uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); goto out; } config_title_generate(&config); /* select entry by configured pattern or EFI LoaderDefaultEntry= variable*/ config_default_entry_select(&config); /* if no configured entry to select from was found, enable the menu */ if (config.idx_default == -1) { config.idx_default = 0; if (config.timeout_sec == 0) config.timeout_sec = 10; } /* select entry or show menu when key is pressed or timeout is set */ if (config.timeout_sec == 0) { UINT64 key; err = console_key_read(&key, FALSE); if (!EFI_ERROR(err)) { INT16 idx; /* find matching key in config entries */ idx = entry_lookup_key(&config, config.idx_default, KEYCHAR(key)); if (idx >= 0) config.idx_default = idx; else menu = TRUE; } } else menu = TRUE; for (;;) { ConfigEntry *entry; entry = config.entries[config.idx_default]; if (menu) { efivar_set_time_usec(L"LoaderTimeMenuUSec", 0); uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x10000, 0, NULL); if (!menu_run(&config, &entry, loaded_image_path)) break; /* run special entry like "reboot" */ if (entry->call) { entry->call(); continue; } } /* export the selected boot entry to the system */ efivar_set(L"LoaderEntrySelected", entry->file, FALSE); uefi_call_wrapper(BS->SetWatchdogTimer, 4, 5 * 60, 0x10000, 0, NULL); err = image_start(image, &config, entry); if (EFI_ERROR(err)) { graphics_mode(FALSE); Print(L"\nFailed to execute %s (%s): %r\n", entry->title, entry->loader, err); uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); goto out; } menu = TRUE; config.timeout_sec = 0; } err = EFI_SUCCESS; out: FreePool(loaded_image_path); config_free(&config); uefi_call_wrapper(root_dir->Close, 1, root_dir); uefi_call_wrapper(BS->CloseProtocol, 4, image, &LoadedImageProtocol, image, NULL); return err; } systemd-229/src/boot/efi/console.c000066400000000000000000000116361265713322000171730ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2012-2013 Kay Sievers * Copyright (C) 2012 Harald Hoyer */ #include #include #include "console.h" #include "util.h" #define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \ { 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } } struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL; typedef EFI_STATUS (EFIAPI *EFI_INPUT_RESET_EX)( struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, BOOLEAN ExtendedVerification ); typedef UINT8 EFI_KEY_TOGGLE_STATE; typedef struct { UINT32 KeyShiftState; EFI_KEY_TOGGLE_STATE KeyToggleState; } EFI_KEY_STATE; typedef struct { EFI_INPUT_KEY Key; EFI_KEY_STATE KeyState; } EFI_KEY_DATA; typedef EFI_STATUS (EFIAPI *EFI_INPUT_READ_KEY_EX)( struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, EFI_KEY_DATA *KeyData ); typedef EFI_STATUS (EFIAPI *EFI_SET_STATE)( struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, EFI_KEY_TOGGLE_STATE *KeyToggleState ); typedef EFI_STATUS (EFIAPI *EFI_KEY_NOTIFY_FUNCTION)( EFI_KEY_DATA *KeyData ); typedef EFI_STATUS (EFIAPI *EFI_REGISTER_KEYSTROKE_NOTIFY)( struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, EFI_KEY_DATA KeyData, EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, VOID **NotifyHandle ); typedef EFI_STATUS (EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY)( struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, VOID *NotificationHandle ); typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL { EFI_INPUT_RESET_EX Reset; EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx; EFI_EVENT WaitForKeyEx; EFI_SET_STATE SetState; EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify; EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify; } EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL; EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) { EFI_GUID EfiSimpleTextInputExProtocolGuid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID; static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx; static BOOLEAN checked; UINTN index; EFI_INPUT_KEY k; EFI_STATUS err; if (!checked) { err = LibLocateProtocol(&EfiSimpleTextInputExProtocolGuid, (VOID **)&TextInputEx); if (EFI_ERROR(err)) TextInputEx = NULL; checked = TRUE; } /* wait until key is pressed */ if (wait) { if (TextInputEx) uefi_call_wrapper(BS->WaitForEvent, 3, 1, &TextInputEx->WaitForKeyEx, &index); else uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index); } if (TextInputEx) { EFI_KEY_DATA keydata; UINT64 keypress; err = uefi_call_wrapper(TextInputEx->ReadKeyStrokeEx, 2, TextInputEx, &keydata); if (!EFI_ERROR(err)) { UINT32 shift = 0; /* do not distinguish between left and right keys */ if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) { if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED)) shift |= EFI_CONTROL_PRESSED; if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED)) shift |= EFI_ALT_PRESSED; }; /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */ keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar); if (keypress > 0) { *key = keypress; return 0; } } } /* fallback for firmware which does not support SimpleTextInputExProtocol * * This is also called in case ReadKeyStrokeEx did not return a key, because * some broken firmwares offer SimpleTextInputExProtocol, but never acually * handle any key. */ err = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &k); if (EFI_ERROR(err)) return err; *key = KEYPRESS(0, k.ScanCode, k.UnicodeChar); return 0; } systemd-229/src/boot/efi/console.h000066400000000000000000000025001265713322000171660ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2012-2013 Kay Sievers * Copyright (C) 2012 Harald Hoyer */ #ifndef __SDBOOT_CONSOLE_H #define __SDBOOT_CONSOLE_H #define EFI_SHIFT_STATE_VALID 0x80000000 #define EFI_RIGHT_CONTROL_PRESSED 0x00000004 #define EFI_LEFT_CONTROL_PRESSED 0x00000008 #define EFI_RIGHT_ALT_PRESSED 0x00000010 #define EFI_LEFT_ALT_PRESSED 0x00000020 #define EFI_CONTROL_PRESSED (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED) #define EFI_ALT_PRESSED (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED) #define KEYPRESS(keys, scan, uni) ((((UINT64)keys) << 32) | ((scan) << 16) | (uni)) #define KEYCHAR(k) ((k) & 0xffff) #define CHAR_CTRL(c) ((c) - 'a' + 1) EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait); #endif systemd-229/src/boot/efi/disk.c000066400000000000000000000034241265713322000164570ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2015 Kay Sievers */ #include #include #include "util.h" EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[37]) { EFI_DEVICE_PATH *device_path; EFI_STATUS r = EFI_NOT_FOUND; /* export the device path this image is started from */ device_path = DevicePathFromHandle(handle); if (device_path) { EFI_DEVICE_PATH *path, *paths; paths = UnpackDevicePath(device_path); for (path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) { HARDDRIVE_DEVICE_PATH *drive; if (DevicePathType(path) != MEDIA_DEVICE_PATH) continue; if (DevicePathSubType(path) != MEDIA_HARDDRIVE_DP) continue; drive = (HARDDRIVE_DEVICE_PATH *)path; if (drive->SignatureType != SIGNATURE_TYPE_GUID) continue; GuidToString(uuid, (EFI_GUID *)&drive->Signature); r = EFI_SUCCESS; break; } FreePool(paths); } return r; } systemd-229/src/boot/efi/disk.h000066400000000000000000000012741265713322000164650ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2015 Kay Sievers */ #ifndef __SDBOOT_DISK_H #define __SDBOOT_DISK_H EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[37]); #endif systemd-229/src/boot/efi/graphics.c000066400000000000000000000065621265713322000173330ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2012-2013 Kay Sievers * Copyright (C) 2012 Harald Hoyer * Copyright (C) 2013 Intel Corporation * Authored by Joonas Lahtinen */ #include #include #include "graphics.h" #include "util.h" EFI_STATUS graphics_mode(BOOLEAN on) { #define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \ { 0xf42f7782, 0x12e, 0x4c12, { 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } }; struct _EFI_CONSOLE_CONTROL_PROTOCOL; typedef enum { EfiConsoleControlScreenText, EfiConsoleControlScreenGraphics, EfiConsoleControlScreenMaxValue, } EFI_CONSOLE_CONTROL_SCREEN_MODE; typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE)( struct _EFI_CONSOLE_CONTROL_PROTOCOL *This, EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, BOOLEAN *UgaExists, BOOLEAN *StdInLocked ); typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE)( struct _EFI_CONSOLE_CONTROL_PROTOCOL *This, EFI_CONSOLE_CONTROL_SCREEN_MODE Mode ); typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN)( struct _EFI_CONSOLE_CONTROL_PROTOCOL *This, CHAR16 *Password ); typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL { EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode; EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode; EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn; } EFI_CONSOLE_CONTROL_PROTOCOL; EFI_GUID ConsoleControlProtocolGuid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; EFI_CONSOLE_CONTROL_SCREEN_MODE new; EFI_CONSOLE_CONTROL_SCREEN_MODE current; BOOLEAN uga_exists; BOOLEAN stdin_locked; EFI_STATUS err; err = LibLocateProtocol(&ConsoleControlProtocolGuid, (VOID **)&ConsoleControl); if (EFI_ERROR(err)) /* console control protocol is nonstandard and might not exist. */ return err == EFI_NOT_FOUND ? EFI_SUCCESS : err; /* check current mode */ err = uefi_call_wrapper(ConsoleControl->GetMode, 4, ConsoleControl, ¤t, &uga_exists, &stdin_locked); if (EFI_ERROR(err)) return err; /* do not touch the mode */ new = on ? EfiConsoleControlScreenGraphics : EfiConsoleControlScreenText; if (new == current) return EFI_SUCCESS; err = uefi_call_wrapper(ConsoleControl->SetMode, 2, ConsoleControl, new); /* some firmware enables the cursor when switching modes */ uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE); return err; } systemd-229/src/boot/efi/graphics.h000066400000000000000000000015151265713322000173310ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2012-2013 Kay Sievers * Copyright (C) 2012 Harald Hoyer * Copyright (C) 2013 Intel Corporation * Authored by Joonas Lahtinen */ #ifndef __SDBOOT_GRAPHICS_H #define __SDBOOT_GRAPHICS_H EFI_STATUS graphics_mode(BOOLEAN on); #endif systemd-229/src/boot/efi/linux.c000066400000000000000000000106331265713322000166640ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2015 Kay Sievers */ #include #include #include "linux.h" #include "util.h" #define SETUP_MAGIC 0x53726448 /* "HdrS" */ struct SetupHeader { UINT8 boot_sector[0x01f1]; UINT8 setup_secs; UINT16 root_flags; UINT32 sys_size; UINT16 ram_size; UINT16 video_mode; UINT16 root_dev; UINT16 signature; UINT16 jump; UINT32 header; UINT16 version; UINT16 su_switch; UINT16 setup_seg; UINT16 start_sys; UINT16 kernel_ver; UINT8 loader_id; UINT8 load_flags; UINT16 movesize; UINT32 code32_start; UINT32 ramdisk_start; UINT32 ramdisk_len; UINT32 bootsect_kludge; UINT16 heap_end; UINT8 ext_loader_ver; UINT8 ext_loader_type; UINT32 cmd_line_ptr; UINT32 ramdisk_max; UINT32 kernel_alignment; UINT8 relocatable_kernel; UINT8 min_alignment; UINT16 xloadflags; UINT32 cmdline_size; UINT32 hardware_subarch; UINT64 hardware_subarch_data; UINT32 payload_offset; UINT32 payload_length; UINT64 setup_data; UINT64 pref_address; UINT32 init_size; UINT32 handover_offset; } __attribute__((packed)); #ifdef __x86_64__ typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct SetupHeader *setup); static inline VOID linux_efi_handover(EFI_HANDLE image, struct SetupHeader *setup) { handover_f handover; asm volatile ("cli"); handover = (handover_f)((UINTN)setup->code32_start + 512 + setup->handover_offset); handover(image, ST, setup); } #else typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct SetupHeader *setup) __attribute__((regparm(0))); static inline VOID linux_efi_handover(EFI_HANDLE image, struct SetupHeader *setup) { handover_f handover; handover = (handover_f)((UINTN)setup->code32_start + setup->handover_offset); handover(image, ST, setup); } #endif EFI_STATUS linux_exec(EFI_HANDLE *image, CHAR8 *cmdline, UINTN cmdline_len, UINTN linux_addr, UINTN initrd_addr, UINTN initrd_size) { struct SetupHeader *image_setup; struct SetupHeader *boot_setup; EFI_PHYSICAL_ADDRESS addr; EFI_STATUS err; image_setup = (struct SetupHeader *)(linux_addr); if (image_setup->signature != 0xAA55 || image_setup->header != SETUP_MAGIC) return EFI_LOAD_ERROR; if (image_setup->version < 0x20b || !image_setup->relocatable_kernel) return EFI_LOAD_ERROR; addr = 0x3fffffff; err = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress, EfiLoaderData, EFI_SIZE_TO_PAGES(0x4000), &addr); if (EFI_ERROR(err)) return err; boot_setup = (struct SetupHeader *)(UINTN)addr; ZeroMem(boot_setup, 0x4000); CopyMem(boot_setup, image_setup, sizeof(struct SetupHeader)); boot_setup->loader_id = 0xff; boot_setup->code32_start = (UINT32)linux_addr + (image_setup->setup_secs+1) * 512; if (cmdline) { addr = 0xA0000; err = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress, EfiLoaderData, EFI_SIZE_TO_PAGES(cmdline_len + 1), &addr); if (EFI_ERROR(err)) return err; CopyMem((VOID *)(UINTN)addr, cmdline, cmdline_len); ((CHAR8 *)addr)[cmdline_len] = 0; boot_setup->cmd_line_ptr = (UINT32)addr; } boot_setup->ramdisk_start = (UINT32)initrd_addr; boot_setup->ramdisk_len = (UINT32)initrd_size; linux_efi_handover(image, boot_setup); return EFI_LOAD_ERROR; } systemd-229/src/boot/efi/linux.h000066400000000000000000000015041265713322000166660ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2015 Kay Sievers */ #ifndef __SDBOOT_kernel_H #define __SDBOOT_kernel_H EFI_STATUS linux_exec(EFI_HANDLE *image, CHAR8 *cmdline, UINTN cmdline_size, UINTN linux_addr, UINTN initrd_addr, UINTN initrd_size); #endif systemd-229/src/boot/efi/pefile.c000066400000000000000000000122141265713322000167660ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2015 Kay Sievers */ #include #include #include "pefile.h" #include "util.h" struct DosFileHeader { UINT8 Magic[2]; UINT16 LastSize; UINT16 nBlocks; UINT16 nReloc; UINT16 HdrSize; UINT16 MinAlloc; UINT16 MaxAlloc; UINT16 ss; UINT16 sp; UINT16 Checksum; UINT16 ip; UINT16 cs; UINT16 RelocPos; UINT16 nOverlay; UINT16 reserved[4]; UINT16 OEMId; UINT16 OEMInfo; UINT16 reserved2[10]; UINT32 ExeHeader; } __attribute__((packed)); #define PE_HEADER_MACHINE_I386 0x014c #define PE_HEADER_MACHINE_X64 0x8664 struct PeFileHeader { UINT16 Machine; UINT16 NumberOfSections; UINT32 TimeDateStamp; UINT32 PointerToSymbolTable; UINT32 NumberOfSymbols; UINT16 SizeOfOptionalHeader; UINT16 Characteristics; } __attribute__((packed)); struct PeSectionHeader { UINT8 Name[8]; UINT32 VirtualSize; UINT32 VirtualAddress; UINT32 SizeOfRawData; UINT32 PointerToRawData; UINT32 PointerToRelocations; UINT32 PointerToLinenumbers; UINT16 NumberOfRelocations; UINT16 NumberOfLinenumbers; UINT32 Characteristics; } __attribute__((packed)); EFI_STATUS pefile_locate_sections(EFI_FILE *dir, CHAR16 *path, CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes) { EFI_FILE_HANDLE handle; struct DosFileHeader dos; uint8_t magic[4]; struct PeFileHeader pe; UINTN len; UINTN i; EFI_STATUS err; err = uefi_call_wrapper(dir->Open, 5, dir, &handle, path, EFI_FILE_MODE_READ, 0ULL); if (EFI_ERROR(err)) return err; /* MS-DOS stub */ len = sizeof(dos); err = uefi_call_wrapper(handle->Read, 3, handle, &len, &dos); if (EFI_ERROR(err)) goto out; if (len != sizeof(dos)) { err = EFI_LOAD_ERROR; goto out; } if (CompareMem(dos.Magic, "MZ", 2) != 0) { err = EFI_LOAD_ERROR; goto out; } err = uefi_call_wrapper(handle->SetPosition, 2, handle, dos.ExeHeader); if (EFI_ERROR(err)) goto out; /* PE header */ len = sizeof(magic); err = uefi_call_wrapper(handle->Read, 3, handle, &len, &magic); if (EFI_ERROR(err)) goto out; if (len != sizeof(magic)) { err = EFI_LOAD_ERROR; goto out; } if (CompareMem(magic, "PE\0\0", 2) != 0) { err = EFI_LOAD_ERROR; goto out; } len = sizeof(pe); err = uefi_call_wrapper(handle->Read, 3, handle, &len, &pe); if (EFI_ERROR(err)) goto out; if (len != sizeof(pe)) { err = EFI_LOAD_ERROR; goto out; } /* PE32+ Subsystem type */ if (pe.Machine != PE_HEADER_MACHINE_X64 && pe.Machine != PE_HEADER_MACHINE_I386) { err = EFI_LOAD_ERROR; goto out; } if (pe.NumberOfSections > 96) { err = EFI_LOAD_ERROR; goto out; } /* the sections start directly after the headers */ err = uefi_call_wrapper(handle->SetPosition, 2, handle, dos.ExeHeader + sizeof(magic) + sizeof(pe) + pe.SizeOfOptionalHeader); if (EFI_ERROR(err)) goto out; for (i = 0; i < pe.NumberOfSections; i++) { struct PeSectionHeader sect; UINTN j; len = sizeof(sect); err = uefi_call_wrapper(handle->Read, 3, handle, &len, §); if (EFI_ERROR(err)) goto out; if (len != sizeof(sect)) { err = EFI_LOAD_ERROR; goto out; } for (j = 0; sections[j]; j++) { if (CompareMem(sect.Name, sections[j], strlena(sections[j])) != 0) continue; if (addrs) addrs[j] = (UINTN)sect.VirtualAddress; if (offsets) offsets[j] = (UINTN)sect.PointerToRawData; if (sizes) sizes[j] = (UINTN)sect.VirtualSize; } } out: uefi_call_wrapper(handle->Close, 1, handle); return err; } systemd-229/src/boot/efi/pefile.h000066400000000000000000000014341265713322000167750ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2015 Kay Sievers */ #ifndef __SDBOOT_PEFILE_H #define __SDBOOT_PEFILE_H EFI_STATUS pefile_locate_sections(EFI_FILE *dir, CHAR16 *path, CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes); #endif systemd-229/src/boot/efi/splash.c000066400000000000000000000254321265713322000170220ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2012-2013 Kay Sievers * Copyright (C) 2012 Harald Hoyer */ #include #include #include "graphics.h" #include "splash.h" #include "util.h" struct bmp_file { CHAR8 signature[2]; UINT32 size; UINT16 reserved[2]; UINT32 offset; } __attribute__((packed)); /* we require at least BITMAPINFOHEADER, later versions are accepted, but their features ignored */ struct bmp_dib { UINT32 size; UINT32 x; UINT32 y; UINT16 planes; UINT16 depth; UINT32 compression; UINT32 image_size; INT32 x_pixel_meter; INT32 y_pixel_meter; UINT32 colors_used; UINT32 colors_important; } __attribute__((packed)); struct bmp_map { UINT8 blue; UINT8 green; UINT8 red; UINT8 reserved; } __attribute__((packed)); EFI_STATUS bmp_parse_header(UINT8 *bmp, UINTN size, struct bmp_dib **ret_dib, struct bmp_map **ret_map, UINT8 **pixmap) { struct bmp_file *file; struct bmp_dib *dib; struct bmp_map *map; UINTN row_size; if (size < sizeof(struct bmp_file) + sizeof(struct bmp_dib)) return EFI_INVALID_PARAMETER; /* check file header */ file = (struct bmp_file *)bmp; if (file->signature[0] != 'B' || file->signature[1] != 'M') return EFI_INVALID_PARAMETER; if (file->size != size) return EFI_INVALID_PARAMETER; if (file->size < file->offset) return EFI_INVALID_PARAMETER; /* check device-independent bitmap */ dib = (struct bmp_dib *)(bmp + sizeof(struct bmp_file)); if (dib->size < sizeof(struct bmp_dib)) return EFI_UNSUPPORTED; switch (dib->depth) { case 1: case 4: case 8: case 24: if (dib->compression != 0) return EFI_UNSUPPORTED; break; case 16: case 32: if (dib->compression != 0 && dib->compression != 3) return EFI_UNSUPPORTED; break; default: return EFI_UNSUPPORTED; } row_size = ((UINTN) dib->depth * dib->x + 31) / 32 * 4; if (file->size - file->offset < dib->y * row_size) return EFI_INVALID_PARAMETER; if (row_size * dib->y > 64 * 1024 * 1024) return EFI_INVALID_PARAMETER; /* check color table */ map = (struct bmp_map *)(bmp + sizeof(struct bmp_file) + dib->size); if (file->offset < sizeof(struct bmp_file) + dib->size) return EFI_INVALID_PARAMETER; if (file->offset > sizeof(struct bmp_file) + dib->size) { UINT32 map_count; UINTN map_size; if (dib->colors_used) map_count = dib->colors_used; else { switch (dib->depth) { case 1: case 4: case 8: map_count = 1 << dib->depth; break; default: map_count = 0; break; } } map_size = file->offset - (sizeof(struct bmp_file) + dib->size); if (map_size != sizeof(struct bmp_map) * map_count) return EFI_INVALID_PARAMETER; } *ret_map = map; *ret_dib = dib; *pixmap = bmp + file->offset; return EFI_SUCCESS; } static VOID pixel_blend(UINT32 *dst, const UINT32 source) { UINT32 alpha, src, src_rb, src_g, dst_rb, dst_g, rb, g; alpha = (source & 0xff); /* convert src from RGBA to XRGB */ src = source >> 8; /* decompose into RB and G components */ src_rb = (src & 0xff00ff); src_g = (src & 0x00ff00); dst_rb = (*dst & 0xff00ff); dst_g = (*dst & 0x00ff00); /* blend */ rb = ((((src_rb - dst_rb) * alpha + 0x800080) >> 8) + dst_rb) & 0xff00ff; g = ((((src_g - dst_g) * alpha + 0x008000) >> 8) + dst_g) & 0x00ff00; *dst = (rb | g); } EFI_STATUS bmp_to_blt(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *buf, struct bmp_dib *dib, struct bmp_map *map, UINT8 *pixmap) { UINT8 *in; UINTN y; /* transform and copy pixels */ in = pixmap; for (y = 0; y < dib->y; y++) { EFI_GRAPHICS_OUTPUT_BLT_PIXEL *out; UINTN row_size; UINTN x; out = &buf[(dib->y - y - 1) * dib->x]; for (x = 0; x < dib->x; x++, in++, out++) { switch (dib->depth) { case 1: { UINTN i; for (i = 0; i < 8 && x < dib->x; i++) { out->Red = map[((*in) >> (7 - i)) & 1].red; out->Green = map[((*in) >> (7 - i)) & 1].green; out->Blue = map[((*in) >> (7 - i)) & 1].blue; out++; x++; } out--; x--; break; } case 4: { UINTN i; i = (*in) >> 4; out->Red = map[i].red; out->Green = map[i].green; out->Blue = map[i].blue; if (x < (dib->x - 1)) { out++; x++; i = (*in) & 0x0f; out->Red = map[i].red; out->Green = map[i].green; out->Blue = map[i].blue; } break; } case 8: out->Red = map[*in].red; out->Green = map[*in].green; out->Blue = map[*in].blue; break; case 16: { UINT16 i = *(UINT16 *) in; out->Red = (i & 0x7c00) >> 7; out->Green = (i & 0x3e0) >> 2; out->Blue = (i & 0x1f) << 3; in += 1; break; } case 24: out->Red = in[2]; out->Green = in[1]; out->Blue = in[0]; in += 2; break; case 32: { UINT32 i = *(UINT32 *) in; pixel_blend((UINT32 *)out, i); in += 3; break; } } } /* add row padding; new lines always start at 32 bit boundary */ row_size = in - pixmap; in += ((row_size + 3) & ~3) - row_size; } return EFI_SUCCESS; } EFI_STATUS graphics_splash(UINT8 *content, UINTN len, const EFI_GRAPHICS_OUTPUT_BLT_PIXEL *background) { EFI_GRAPHICS_OUTPUT_BLT_PIXEL pixel = {}; EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput = NULL; struct bmp_dib *dib; struct bmp_map *map; UINT8 *pixmap; UINT64 blt_size; VOID *blt = NULL; UINTN x_pos = 0; UINTN y_pos = 0; EFI_STATUS err; if (!background) { if (StriCmp(L"Apple", ST->FirmwareVendor) == 0) { pixel.Red = 0xc0; pixel.Green = 0xc0; pixel.Blue = 0xc0; } background = &pixel; } err = LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput); if (EFI_ERROR(err)) return err; err = bmp_parse_header(content, len, &dib, &map, &pixmap); if (EFI_ERROR(err)) goto err; if(dib->x < GraphicsOutput->Mode->Info->HorizontalResolution) x_pos = (GraphicsOutput->Mode->Info->HorizontalResolution - dib->x) / 2; if(dib->y < GraphicsOutput->Mode->Info->VerticalResolution) y_pos = (GraphicsOutput->Mode->Info->VerticalResolution - dib->y) / 2; uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput, (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)background, EfiBltVideoFill, 0, 0, 0, 0, GraphicsOutput->Mode->Info->HorizontalResolution, GraphicsOutput->Mode->Info->VerticalResolution, 0); /* EFI buffer */ blt_size = dib->x * dib->y * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL); blt = AllocatePool(blt_size); if (!blt) return EFI_OUT_OF_RESOURCES; err = uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput, blt, EfiBltVideoToBltBuffer, x_pos, y_pos, 0, 0, dib->x, dib->y, 0); if (EFI_ERROR(err)) goto err; err = bmp_to_blt(blt, dib, map, pixmap); if (EFI_ERROR(err)) goto err; err = graphics_mode(TRUE); if (EFI_ERROR(err)) goto err; err = uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput, blt, EfiBltBufferToVideo, 0, 0, x_pos, y_pos, dib->x, dib->y, 0); err: FreePool(blt); return err; } systemd-229/src/boot/efi/splash.h000066400000000000000000000014401265713322000170200ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2012-2013 Kay Sievers * Copyright (C) 2012 Harald Hoyer */ #ifndef __SDBOOT_SPLASH_H #define __SDBOOT_SPLASH_H EFI_STATUS graphics_splash(UINT8 *content, UINTN len, const EFI_GRAPHICS_OUTPUT_BLT_PIXEL *background); #endif systemd-229/src/boot/efi/stub.c000066400000000000000000000104201265713322000164740ustar00rootroot00000000000000/* This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2015 Kay Sievers */ #include #include #include "disk.h" #include "graphics.h" #include "linux.h" #include "pefile.h" #include "splash.h" #include "util.h" /* magic string to find in the binary image */ static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " VERSION " ####"; static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE; EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { EFI_LOADED_IMAGE *loaded_image; EFI_FILE *root_dir; CHAR16 *loaded_image_path; CHAR8 *b; UINTN size; BOOLEAN secure = FALSE; CHAR8 *sections[] = { (UINT8 *)".cmdline", (UINT8 *)".linux", (UINT8 *)".initrd", (UINT8 *)".splash", NULL }; UINTN addrs[ELEMENTSOF(sections)-1] = {}; UINTN offs[ELEMENTSOF(sections)-1] = {}; UINTN szs[ELEMENTSOF(sections)-1] = {}; CHAR8 *cmdline = NULL; UINTN cmdline_len; CHAR16 uuid[37]; EFI_STATUS err; InitializeLib(image, sys_table); err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image, image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR(err)) { Print(L"Error getting a LoadedImageProtocol handle: %r ", err); uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); return err; } root_dir = LibOpenRoot(loaded_image->DeviceHandle); if (!root_dir) { Print(L"Unable to open root directory: %r ", err); uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); return EFI_LOAD_ERROR; } loaded_image_path = DevicePathToStr(loaded_image->FilePath); if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) { if (*b > 0) secure = TRUE; FreePool(b); } err = pefile_locate_sections(root_dir, loaded_image_path, sections, addrs, offs, szs); if (EFI_ERROR(err)) { Print(L"Unable to locate embedded .linux section: %r ", err); uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); return err; } if (szs[0] > 0) cmdline = (CHAR8 *)(loaded_image->ImageBase + addrs[0]); cmdline_len = szs[0]; /* if we are not in secure boot mode, accept a custom command line and replace the built-in one */ if (!secure && loaded_image->LoadOptionsSize > 0) { CHAR16 *options; CHAR8 *line; UINTN i; options = (CHAR16 *)loaded_image->LoadOptions; cmdline_len = (loaded_image->LoadOptionsSize / sizeof(CHAR16)) * sizeof(CHAR8); line = AllocatePool(cmdline_len); for (i = 0; i < cmdline_len; i++) line[i] = options[i]; cmdline = line; } /* export the device path this image is started from */ if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) efivar_set(L"LoaderDevicePartUUID", uuid, FALSE); if (szs[3] > 0) graphics_splash((UINT8 *)((UINTN)loaded_image->ImageBase + addrs[3]), szs[3], NULL); err = linux_exec(image, cmdline, cmdline_len, (UINTN)loaded_image->ImageBase + addrs[1], (UINTN)loaded_image->ImageBase + addrs[2], szs[2]); graphics_mode(FALSE); Print(L"Execution of embedded linux image failed: %r\n", err); uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); return err; } systemd-229/src/boot/efi/util.c000066400000000000000000000220411265713322000164760ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2012-2013 Kay Sievers * Copyright (C) 2012 Harald Hoyer */ #include #include #include "util.h" /* * Allocated random UUID, intended to be shared across tools that implement * the (ESP)\loader\entries\-.conf convention and the * associated EFI variables. */ static const EFI_GUID loader_guid = { 0x4a67b082, 0x0a4c, 0x41cf, {0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f} }; #ifdef __x86_64__ UINT64 ticks_read(VOID) { UINT64 a, d; __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d)); return (d << 32) | a; } #elif defined(__i386__) UINT64 ticks_read(VOID) { UINT64 val; __asm__ volatile ("rdtsc" : "=A" (val)); return val; } #else UINT64 ticks_read(VOID) { UINT64 val = 1; return val; } #endif /* count TSC ticks during a millisecond delay */ UINT64 ticks_freq(VOID) { UINT64 ticks_start, ticks_end; ticks_start = ticks_read(); uefi_call_wrapper(BS->Stall, 1, 1000); ticks_end = ticks_read(); return (ticks_end - ticks_start) * 1000; } UINT64 time_usec(VOID) { UINT64 ticks; static UINT64 freq; ticks = ticks_read(); if (ticks == 0) return 0; if (freq == 0) { freq = ticks_freq(); if (freq == 0) return 0; } return 1000 * 1000 * ticks / freq; } EFI_STATUS parse_boolean(CHAR8 *v, BOOLEAN *b) { if (strcmpa(v, (CHAR8 *)"1") == 0 || strcmpa(v, (CHAR8 *)"yes") == 0 || strcmpa(v, (CHAR8 *)"y") == 0 || strcmpa(v, (CHAR8 *)"true") == 0) { *b = TRUE; return EFI_SUCCESS; } if (strcmpa(v, (CHAR8 *)"0") == 0 || strcmpa(v, (CHAR8 *)"no") == 0 || strcmpa(v, (CHAR8 *)"n") == 0 || strcmpa(v, (CHAR8 *)"false") == 0) { *b = FALSE; return EFI_SUCCESS; } return EFI_INVALID_PARAMETER; } EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 *buf, UINTN size, BOOLEAN persistent) { UINT32 flags; flags = EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS; if (persistent) flags |= EFI_VARIABLE_NON_VOLATILE; return uefi_call_wrapper(RT->SetVariable, 5, name, (EFI_GUID *)vendor, flags, size, buf); } EFI_STATUS efivar_set(CHAR16 *name, CHAR16 *value, BOOLEAN persistent) { return efivar_set_raw(&loader_guid, name, (CHAR8 *)value, value ? (StrLen(value)+1) * sizeof(CHAR16) : 0, persistent); } EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent) { CHAR16 str[32]; SPrint(str, 32, L"%d", i); return efivar_set(name, str, persistent); } EFI_STATUS efivar_get(CHAR16 *name, CHAR16 **value) { CHAR8 *buf; CHAR16 *val; UINTN size; EFI_STATUS err; err = efivar_get_raw(&loader_guid, name, &buf, &size); if (EFI_ERROR(err)) return err; val = StrDuplicate((CHAR16 *)buf); if (!val) { FreePool(buf); return EFI_OUT_OF_RESOURCES; } *value = val; return EFI_SUCCESS; } EFI_STATUS efivar_get_int(CHAR16 *name, UINTN *i) { CHAR16 *val; EFI_STATUS err; err = efivar_get(name, &val); if (!EFI_ERROR(err)) { *i = Atoi(val); FreePool(val); } return err; } EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 **buffer, UINTN *size) { CHAR8 *buf; UINTN l; EFI_STATUS err; l = sizeof(CHAR16 *) * EFI_MAXIMUM_VARIABLE_SIZE; buf = AllocatePool(l); if (!buf) return EFI_OUT_OF_RESOURCES; err = uefi_call_wrapper(RT->GetVariable, 5, name, (EFI_GUID *)vendor, NULL, &l, buf); if (!EFI_ERROR(err)) { *buffer = buf; if (size) *size = l; } else FreePool(buf); return err; } VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec) { CHAR16 str[32]; if (usec == 0) usec = time_usec(); if (usec == 0) return; SPrint(str, 32, L"%ld", usec); efivar_set(name, str, FALSE); } static INTN utf8_to_16(CHAR8 *stra, CHAR16 *c) { CHAR16 unichar; UINTN len; UINTN i; if (stra[0] < 0x80) len = 1; else if ((stra[0] & 0xe0) == 0xc0) len = 2; else if ((stra[0] & 0xf0) == 0xe0) len = 3; else if ((stra[0] & 0xf8) == 0xf0) len = 4; else if ((stra[0] & 0xfc) == 0xf8) len = 5; else if ((stra[0] & 0xfe) == 0xfc) len = 6; else return -1; switch (len) { case 1: unichar = stra[0]; break; case 2: unichar = stra[0] & 0x1f; break; case 3: unichar = stra[0] & 0x0f; break; case 4: unichar = stra[0] & 0x07; break; case 5: unichar = stra[0] & 0x03; break; case 6: unichar = stra[0] & 0x01; break; } for (i = 1; i < len; i++) { if ((stra[i] & 0xc0) != 0x80) return -1; unichar <<= 6; unichar |= stra[i] & 0x3f; } *c = unichar; return len; } CHAR16 *stra_to_str(CHAR8 *stra) { UINTN strlen; UINTN len; UINTN i; CHAR16 *str; len = strlena(stra); str = AllocatePool((len + 1) * sizeof(CHAR16)); strlen = 0; i = 0; while (i < len) { INTN utf8len; utf8len = utf8_to_16(stra + i, str + strlen); if (utf8len <= 0) { /* invalid utf8 sequence, skip the garbage */ i++; continue; } strlen++; i += utf8len; } str[strlen] = '\0'; return str; } CHAR16 *stra_to_path(CHAR8 *stra) { CHAR16 *str; UINTN strlen; UINTN len; UINTN i; len = strlena(stra); str = AllocatePool((len + 2) * sizeof(CHAR16)); str[0] = '\\'; strlen = 1; i = 0; while (i < len) { INTN utf8len; utf8len = utf8_to_16(stra + i, str + strlen); if (utf8len <= 0) { /* invalid utf8 sequence, skip the garbage */ i++; continue; } if (str[strlen] == '/') str[strlen] = '\\'; if (str[strlen] == '\\' && str[strlen-1] == '\\') { /* skip double slashes */ i += utf8len; continue; } strlen++; i += utf8len; } str[strlen] = '\0'; return str; } CHAR8 *strchra(CHAR8 *s, CHAR8 c) { do { if (*s == c) return s; } while (*s++); return NULL; } INTN file_read(EFI_FILE_HANDLE dir, CHAR16 *name, UINTN off, UINTN size, CHAR8 **content) { EFI_FILE_HANDLE handle; CHAR8 *buf; UINTN buflen; EFI_STATUS err; UINTN len; err = uefi_call_wrapper(dir->Open, 5, dir, &handle, name, EFI_FILE_MODE_READ, 0ULL); if (EFI_ERROR(err)) return err; if (size == 0) { EFI_FILE_INFO *info; info = LibFileInfo(handle); buflen = info->FileSize+1; FreePool(info); } else buflen = size; if (off > 0) { err = uefi_call_wrapper(handle->SetPosition, 2, handle, off); if (EFI_ERROR(err)) return err; } buf = AllocatePool(buflen); err = uefi_call_wrapper(handle->Read, 3, handle, &buflen, buf); if (!EFI_ERROR(err)) { buf[buflen] = '\0'; *content = buf; len = buflen; } else { len = err; FreePool(buf); } uefi_call_wrapper(handle->Close, 1, handle); return len; } systemd-229/src/boot/efi/util.h000066400000000000000000000032331265713322000165050ustar00rootroot00000000000000/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Copyright (C) 2012-2013 Kay Sievers * Copyright (C) 2012 Harald Hoyer */ #ifndef __SDBOOT_UTIL_H #define __SDBOOT_UTIL_H #include #include #define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0])) static inline const CHAR16 *yes_no(BOOLEAN b) { return b ? L"yes" : L"no"; } EFI_STATUS parse_boolean(CHAR8 *v, BOOLEAN *b); UINT64 ticks_read(void); UINT64 ticks_freq(void); UINT64 time_usec(void); EFI_STATUS efivar_set(CHAR16 *name, CHAR16 *value, BOOLEAN persistent); EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 *buf, UINTN size, BOOLEAN persistent); EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent); VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec); EFI_STATUS efivar_get(CHAR16 *name, CHAR16 **value); EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 **buffer, UINTN *size); EFI_STATUS efivar_get_int(CHAR16 *name, UINTN *i); CHAR8 *strchra(CHAR8 *s, CHAR8 c); CHAR16 *stra_to_path(CHAR8 *stra); CHAR16 *stra_to_str(CHAR8 *stra); INTN file_read(EFI_FILE_HANDLE dir, CHAR16 *name, UINTN off, UINTN size, CHAR8 **content); #endif systemd-229/src/bootchart/000077500000000000000000000000001265713322000156355ustar00rootroot00000000000000systemd-229/src/bootchart/Makefile000077700000000000000000000000001265713322000211432../Makefileustar00rootroot00000000000000systemd-229/src/bootchart/bootchart.c000066400000000000000000000454771265713322000200070ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2009-2013 Intel Corporation Authors: Auke Kok systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /*** Many thanks to those who contributed ideas and code: - Ziga Mahkovec - Original bootchart author - Anders Norgaard - PyBootchartgui - Michael Meeks - bootchart2 - Scott James Remnant - Ubuntu C-based logger - Arjan van der Ven - for the idea to merge bootgraph.pl functionality ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include "sd-journal.h" #include "alloc-util.h" #include "bootchart.h" #include "conf-parser.h" #include "def.h" #include "fd-util.h" #include "fileio.h" #include "io-util.h" #include "list.h" #include "macro.h" #include "parse-util.h" #include "path-util.h" #include "store.h" #include "string-util.h" #include "strxcpyx.h" #include "svg.h" #include "util.h" static int exiting = 0; #define DEFAULT_SAMPLES_LEN 500 #define DEFAULT_HZ 25.0 #define DEFAULT_SCALE_X 100.0 /* 100px = 1sec */ #define DEFAULT_SCALE_Y 20.0 /* 16px = 1 process bar */ #define DEFAULT_INIT ROOTLIBEXECDIR "/systemd" #define DEFAULT_OUTPUT "/run/log" /* graph defaults */ bool arg_entropy = false; bool arg_initcall = true; bool arg_relative = false; bool arg_filter = true; bool arg_show_cmdline = false; bool arg_show_cgroup = false; bool arg_pss = false; bool arg_percpu = false; int arg_samples_len = DEFAULT_SAMPLES_LEN; /* we record len+1 (1 start sample) */ double arg_hz = DEFAULT_HZ; double arg_scale_x = DEFAULT_SCALE_X; double arg_scale_y = DEFAULT_SCALE_Y; char arg_init_path[PATH_MAX] = DEFAULT_INIT; char arg_output_path[PATH_MAX] = DEFAULT_OUTPUT; static void signal_handler(int sig) { exiting = 1; } #define BOOTCHART_MAX (16*1024*1024) static void parse_conf(void) { char *init = NULL, *output = NULL; const ConfigTableItem items[] = { { "Bootchart", "Samples", config_parse_int, 0, &arg_samples_len }, { "Bootchart", "Frequency", config_parse_double, 0, &arg_hz }, { "Bootchart", "Relative", config_parse_bool, 0, &arg_relative }, { "Bootchart", "Filter", config_parse_bool, 0, &arg_filter }, { "Bootchart", "Output", config_parse_path, 0, &output }, { "Bootchart", "Init", config_parse_path, 0, &init }, { "Bootchart", "PlotMemoryUsage", config_parse_bool, 0, &arg_pss }, { "Bootchart", "PlotEntropyGraph", config_parse_bool, 0, &arg_entropy }, { "Bootchart", "ScaleX", config_parse_double, 0, &arg_scale_x }, { "Bootchart", "ScaleY", config_parse_double, 0, &arg_scale_y }, { "Bootchart", "ControlGroup", config_parse_bool, 0, &arg_show_cgroup }, { "Bootchart", "PerCPU", config_parse_bool, 0, &arg_percpu }, { NULL, NULL, NULL, 0, NULL } }; config_parse_many(PKGSYSCONFDIR "/bootchart.conf", CONF_PATHS_NULSTR("systemd/bootchart.conf.d"), NULL, config_item_table_lookup, items, true, NULL); if (init != NULL) strscpy(arg_init_path, sizeof(arg_init_path), init); if (output != NULL) strscpy(arg_output_path, sizeof(arg_output_path), output); } static void help(void) { printf("Usage: %s [OPTIONS]\n\n" "Options:\n" " -r --rel Record time relative to recording\n" " -f --freq=FREQ Sample frequency [%g]\n" " -n --samples=N Stop sampling at [%d] samples\n" " -x --scale-x=N Scale the graph horizontally [%g] \n" " -y --scale-y=N Scale the graph vertically [%g] \n" " -p --pss Enable PSS graph (CPU intensive)\n" " -e --entropy Enable the entropy_avail graph\n" " -o --output=PATH Path to output files [%s]\n" " -i --init=PATH Path to init executable [%s]\n" " -F --no-filter Disable filtering of unimportant or ephemeral processes\n" " -C --cmdline Display full command lines with arguments\n" " -c --control-group Display process control group\n" " --per-cpu Draw each CPU utilization and wait bar also\n" " -h --help Display this message\n\n" "See bootchart.conf for more information.\n", program_invocation_short_name, DEFAULT_HZ, DEFAULT_SAMPLES_LEN, DEFAULT_SCALE_X, DEFAULT_SCALE_Y, DEFAULT_OUTPUT, DEFAULT_INIT); } static int parse_argv(int argc, char *argv[]) { enum { ARG_PERCPU = 0x100, }; static const struct option options[] = { {"rel", no_argument, NULL, 'r' }, {"freq", required_argument, NULL, 'f' }, {"samples", required_argument, NULL, 'n' }, {"pss", no_argument, NULL, 'p' }, {"output", required_argument, NULL, 'o' }, {"init", required_argument, NULL, 'i' }, {"no-filter", no_argument, NULL, 'F' }, {"cmdline", no_argument, NULL, 'C' }, {"control-group", no_argument, NULL, 'c' }, {"help", no_argument, NULL, 'h' }, {"scale-x", required_argument, NULL, 'x' }, {"scale-y", required_argument, NULL, 'y' }, {"entropy", no_argument, NULL, 'e' }, {"per-cpu", no_argument, NULL, ARG_PERCPU}, {} }; int c, r; if (getpid() == 1) opterr = 0; while ((c = getopt_long(argc, argv, "erpf:n:o:i:FCchx:y:", options, NULL)) >= 0) switch (c) { case 'r': arg_relative = true; break; case 'f': r = safe_atod(optarg, &arg_hz); if (r < 0) log_warning_errno(r, "failed to parse --freq/-f argument '%s': %m", optarg); break; case 'F': arg_filter = false; break; case 'C': arg_show_cmdline = true; break; case 'c': arg_show_cgroup = true; break; case 'n': r = safe_atoi(optarg, &arg_samples_len); if (r < 0) log_warning_errno(r, "failed to parse --samples/-n argument '%s': %m", optarg); break; case 'o': path_kill_slashes(optarg); strscpy(arg_output_path, sizeof(arg_output_path), optarg); break; case 'i': path_kill_slashes(optarg); strscpy(arg_init_path, sizeof(arg_init_path), optarg); break; case 'p': arg_pss = true; break; case 'x': r = safe_atod(optarg, &arg_scale_x); if (r < 0) log_warning_errno(r, "failed to parse --scale-x/-x argument '%s': %m", optarg); break; case 'y': r = safe_atod(optarg, &arg_scale_y); if (r < 0) log_warning_errno(r, "failed to parse --scale-y/-y argument '%s': %m", optarg); break; case 'e': arg_entropy = true; break; case ARG_PERCPU: arg_percpu = true; break; case 'h': help(); return 0; case '?': if (getpid() != 1) return -EINVAL; else return 0; default: assert_not_reached("Unhandled option code."); } if (arg_hz <= 0) { log_error("Frequency needs to be > 0"); return -EINVAL; } return 1; } static int do_journal_append(char *file) { _cleanup_free_ char *bootchart_message = NULL; _cleanup_free_ char *bootchart_file = NULL; _cleanup_free_ char *p = NULL; _cleanup_close_ int fd = -1; struct iovec iovec[5]; int r, j = 0; ssize_t n; bootchart_file = strappend("BOOTCHART_FILE=", file); if (!bootchart_file) return log_oom(); IOVEC_SET_STRING(iovec[j++], bootchart_file); IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=9f26aa562cf440c2b16c773d0479b518"); IOVEC_SET_STRING(iovec[j++], "PRIORITY=7"); bootchart_message = strjoin("MESSAGE=Bootchart created: ", file, NULL); if (!bootchart_message) return log_oom(); IOVEC_SET_STRING(iovec[j++], bootchart_message); p = malloc(10 + BOOTCHART_MAX); if (!p) return log_oom(); memcpy(p, "BOOTCHART=", 10); fd = open(file, O_RDONLY|O_CLOEXEC); if (fd < 0) return log_error_errno(errno, "Failed to open bootchart data \"%s\": %m", file); n = loop_read(fd, p + 10, BOOTCHART_MAX, false); if (n < 0) return log_error_errno(n, "Failed to read bootchart data: %m"); iovec[j].iov_base = p; iovec[j].iov_len = 10 + n; j++; r = sd_journal_sendv(iovec, j); if (r < 0) log_error_errno(r, "Failed to send bootchart: %m"); return 0; } int main(int argc, char *argv[]) { static struct list_sample_data *sampledata; _cleanup_closedir_ DIR *proc = NULL; _cleanup_free_ char *build = NULL; _cleanup_fclose_ FILE *of = NULL; _cleanup_close_ int sysfd = -1; struct ps_struct *ps_first; double graph_start; double log_start; double interval; char output_file[PATH_MAX]; char datestr[200]; int pscount = 0; int n_cpus = 0; int overrun = 0; time_t t = 0; int r, samples; struct ps_struct *ps; struct rlimit rlim; struct list_sample_data *head; struct sigaction sig = { .sa_handler = signal_handler, }; parse_conf(); r = parse_argv(argc, argv); if (r < 0) return EXIT_FAILURE; if (r == 0) return EXIT_SUCCESS; /* * If the kernel executed us through init=/usr/lib/systemd/systemd-bootchart, then * fork: * - parent execs executable specified via init_path[] (/usr/lib/systemd/systemd by default) as pid=1 * - child logs data */ if (getpid() == 1) { if (fork()) /* parent */ execl(arg_init_path, arg_init_path, NULL); } argv[0][0] = '@'; rlim.rlim_cur = 4096; rlim.rlim_max = 4096; (void) setrlimit(RLIMIT_NOFILE, &rlim); /* start with empty ps LL */ ps_first = new0(struct ps_struct, 1); if (!ps_first) { log_oom(); return EXIT_FAILURE; } /* handle TERM/INT nicely */ sigaction(SIGHUP, &sig, NULL); interval = (1.0 / arg_hz) * 1000000000.0; if (arg_relative) graph_start = log_start = gettime_ns(); else { struct timespec n; double uptime; clock_gettime(clock_boottime_or_monotonic(), &n); uptime = (n.tv_sec + (n.tv_nsec / (double) NSEC_PER_SEC)); log_start = gettime_ns(); graph_start = log_start - uptime; } if (graph_start < 0.0) { log_error("Failed to setup graph start time.\n\n" "The system uptime probably includes time that the system was suspended. " "Use --rel to bypass this issue."); return EXIT_FAILURE; } LIST_HEAD_INIT(head); /* main program loop */ for (samples = 0; !exiting && samples < arg_samples_len; samples++) { int res; double sample_stop; double elapsed; double timeleft; sampledata = new0(struct list_sample_data, 1); if (sampledata == NULL) { log_oom(); return EXIT_FAILURE; } sampledata->sampletime = gettime_ns(); sampledata->counter = samples; if (sysfd < 0) sysfd = open("/sys", O_RDONLY|O_CLOEXEC); if (!build) { if (parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &build, NULL) == -ENOENT) parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &build, NULL); } if (proc) rewinddir(proc); else proc = opendir("/proc"); /* wait for /proc to become available, discarding samples */ if (proc) { r = log_sample(proc, samples, ps_first, &sampledata, &pscount, &n_cpus); if (r < 0) return EXIT_FAILURE; } sample_stop = gettime_ns(); elapsed = (sample_stop - sampledata->sampletime) * 1000000000.0; timeleft = interval - elapsed; /* * check if we have not consumed our entire timeslice. If we * do, don't sleep and take a new sample right away. * we'll lose all the missed samples and overrun our total * time */ if (timeleft > 0) { struct timespec req; req.tv_sec = (time_t)(timeleft / 1000000000.0); req.tv_nsec = (long)(timeleft - (req.tv_sec * 1000000000.0)); res = nanosleep(&req, NULL); if (res) { if (errno == EINTR) /* caught signal, probably HUP! */ break; log_error_errno(errno, "nanosleep() failed: %m"); return EXIT_FAILURE; } } else { overrun++; /* calculate how many samples we lost and scrap them */ arg_samples_len -= (int)(-timeleft / interval); } LIST_PREPEND(link, head, sampledata); } /* do some cleanup, close fd's */ ps = ps_first; while (ps->next_ps) { ps = ps->next_ps; ps->schedstat = safe_close(ps->schedstat); ps->sched = safe_close(ps->sched); ps->smaps = safe_fclose(ps->smaps); } if (!of) { t = time(NULL); r = strftime(datestr, sizeof(datestr), "%Y%m%d-%H%M", localtime(&t)); assert_se(r > 0); snprintf(output_file, PATH_MAX, "%s/bootchart-%s.svg", arg_output_path, datestr); of = fopen(output_file, "we"); } if (!of) { log_error("Error opening output file '%s': %m\n", output_file); return EXIT_FAILURE; } r = svg_do(of, strna(build), head, ps_first, samples, pscount, n_cpus, graph_start, log_start, interval, overrun); if (r < 0) { log_error_errno(r, "Error generating svg file: %m"); return EXIT_FAILURE; } log_info("systemd-bootchart wrote %s\n", output_file); r = do_journal_append(output_file); if (r < 0) return EXIT_FAILURE; /* nitpic cleanups */ ps = ps_first->next_ps; while (ps->next_ps) { struct ps_struct *old; old = ps; old->sample = ps->first; ps = ps->next_ps; while (old->sample->next) { struct ps_sched_struct *oldsample = old->sample; old->sample = old->sample->next; free(oldsample); } free(old->cgroup); free(old->sample); free(old); } free(ps->cgroup); free(ps->sample); free(ps); sampledata = head; while (sampledata->link_prev) { struct list_sample_data *old_sampledata = sampledata; sampledata = sampledata->link_prev; free(old_sampledata); } free(sampledata); /* don't complain when overrun once, happens most commonly on 1st sample */ if (overrun > 1) log_warning("systemd-bootchart: sample time overrun %i times\n", overrun); return 0; } systemd-229/src/bootchart/bootchart.conf000066400000000000000000000013201265713322000204650ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # Entries in this file show the compile time defaults. # You can change settings by editing this file. # Defaults can be restored by simply deleting this file. # # See bootchart.conf(5) for details. [Bootchart] #Samples=500 #Frequency=25 #Relative=no #Filter=yes #Output= #Init=/path/to/init-binary #PlotMemoryUsage=no #PlotEntropyGraph=no #ScaleX=100 #ScaleY=20 #ControlGroup=no #PerCPU=no systemd-229/src/bootchart/bootchart.h000066400000000000000000000062031265713322000177740ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2009-2013 Intel Corporation Authors: Auke Kok systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "list.h" #define MAXCPUS 16 #define MAXPIDS 65535 struct block_stat_struct { /* /proc/vmstat pgpgin & pgpgout */ int bi; int bo; }; struct cpu_stat_sample_struct { /* /proc/schedstat fields 10 & 11 (after name) */ double runtime; double waittime; }; /* per process, per sample data we will log */ struct ps_sched_struct { /* /proc//schedstat fields 1 & 2 */ double runtime; double waittime; int pss; struct list_sample_data *sampledata; struct ps_sched_struct *next; struct ps_sched_struct *prev; struct ps_sched_struct *cross; /* cross pointer */ struct ps_struct *ps_new; }; struct list_sample_data { double runtime[MAXCPUS]; double waittime[MAXCPUS]; double sampletime; int entropy_avail; struct block_stat_struct blockstat; LIST_FIELDS(struct list_sample_data, link); /* DLL */ int counter; }; /* process info */ struct ps_struct { struct ps_struct *next_ps; /* SLL pointer */ struct ps_struct *parent; /* ppid ref */ struct ps_struct *children; /* children */ struct ps_struct *next; /* siblings */ /* must match - otherwise it's a new process with same PID */ char name[256]; int pid; int ppid; char *cgroup; /* cache fd's */ int sched; int schedstat; FILE *smaps; /* pointers to first/last seen timestamps */ struct ps_sched_struct *first; struct ps_sched_struct *last; /* records actual start time, may be way before bootchart runs */ double starttime; /* record human readable total cpu time */ double total; /* largest PSS size found */ int pss_max; /* for drawing connection lines later */ double pos_x; double pos_y; struct ps_sched_struct *sample; }; extern bool arg_relative; extern bool arg_filter; extern bool arg_show_cmdline; extern bool arg_show_cgroup; extern bool arg_pss; extern bool arg_entropy; extern bool arg_percpu; extern bool arg_initcall; extern int arg_samples_len; extern double arg_hz; extern double arg_scale_x; extern double arg_scale_y; extern char arg_output_path[PATH_MAX]; extern char arg_init_path[PATH_MAX]; systemd-229/src/bootchart/store.c000066400000000000000000000467271265713322000171550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2009-2013 Intel Corporation Authors: Auke Kok systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "bootchart.h" #include "cgroup-util.h" #include "dirent-util.h" #include "fd-util.h" #include "fileio.h" #include "parse-util.h" #include "store.h" #include "string-util.h" #include "strxcpyx.h" #include "time-util.h" #include "util.h" /* * Alloc a static 4k buffer for stdio - primarily used to increase * PSS buffering from the default 1k stdin buffer to reduce * read() overhead. */ static char smaps_buf[4096]; static int skip = 0; double gettime_ns(void) { struct timespec n; clock_gettime(CLOCK_MONOTONIC, &n); return (n.tv_sec + (n.tv_nsec / (double) NSEC_PER_SEC)); } static char *bufgetline(char *buf) { char *c; if (!buf) return NULL; c = strchr(buf, '\n'); if (c) c++; return c; } static int pid_cmdline_strscpy(int procfd, char *buffer, size_t buf_len, int pid) { char filename[PATH_MAX]; _cleanup_close_ int fd = -1; ssize_t n; sprintf(filename, "%d/cmdline", pid); fd = openat(procfd, filename, O_RDONLY|O_CLOEXEC); if (fd < 0) return -errno; n = read(fd, buffer, buf_len-1); if (n > 0) { int i; for (i = 0; i < n; i++) if (buffer[i] == '\0') buffer[i] = ' '; buffer[n] = '\0'; } return 0; } int log_sample(DIR *proc, int sample, struct ps_struct *ps_first, struct list_sample_data **ptr, int *pscount, int *cpus) { static int vmstat = -1; _cleanup_free_ char *buf_schedstat = NULL; char buf[4096]; char key[256]; char val[256]; char rt[256]; char wt[256]; char *m; int r; int c; int p; int mod; static int e_fd = -1; ssize_t s; ssize_t n; struct dirent *ent; int fd; struct list_sample_data *sampledata; struct ps_sched_struct *ps_prev = NULL; int procfd; int taskfd = -1; sampledata = *ptr; procfd = dirfd(proc); if (procfd < 0) return -errno; if (vmstat < 0) { /* block stuff */ vmstat = openat(procfd, "vmstat", O_RDONLY|O_CLOEXEC); if (vmstat < 0) return log_error_errno(errno, "Failed to open /proc/vmstat: %m"); } n = pread(vmstat, buf, sizeof(buf) - 1, 0); if (n <= 0) { vmstat = safe_close(vmstat); if (n < 0) return -errno; return -ENODATA; } buf[n] = '\0'; m = buf; while (m) { if (sscanf(m, "%s %s", key, val) < 2) goto vmstat_next; if (streq(key, "pgpgin")) sampledata->blockstat.bi = atoi(val); if (streq(key, "pgpgout")) { sampledata->blockstat.bo = atoi(val); break; } vmstat_next: m = bufgetline(m); if (!m) break; } /* Parse "/proc/schedstat" for overall CPU utilization */ r = read_full_file("/proc/schedstat", &buf_schedstat, NULL); if (r < 0) return log_error_errno(r, "Unable to read schedstat: %m"); m = buf_schedstat; while (m) { if (sscanf(m, "%s %*s %*s %*s %*s %*s %*s %s %s", key, rt, wt) < 3) goto schedstat_next; if (strstr(key, "cpu")) { r = safe_atoi((const char*)(key+3), &c); if (r < 0 || c > MAXCPUS -1) /* Oops, we only have room for MAXCPUS data */ break; sampledata->runtime[c] = atoll(rt); sampledata->waittime[c] = atoll(wt); if (c == *cpus) *cpus = c + 1; } schedstat_next: m = bufgetline(m); if (!m) break; } if (arg_entropy) { if (e_fd < 0) { e_fd = openat(procfd, "sys/kernel/random/entropy_avail", O_RDONLY|O_CLOEXEC); if (e_fd < 0) return log_error_errno(errno, "Failed to open /proc/sys/kernel/random/entropy_avail: %m"); } n = pread(e_fd, buf, sizeof(buf) - 1, 0); if (n <= 0) { e_fd = safe_close(e_fd); } else { buf[n] = '\0'; sampledata->entropy_avail = atoi(buf); } } while ((ent = readdir(proc)) != NULL) { char filename[PATH_MAX]; int pid; struct ps_struct *ps; if ((ent->d_name[0] < '0') || (ent->d_name[0] > '9')) continue; pid = atoi(ent->d_name); if (pid >= MAXPIDS) continue; ps = ps_first; while (ps->next_ps) { ps = ps->next_ps; if (ps->pid == pid) break; } /* end of our LL? then append a new record */ if (ps->pid != pid) { _cleanup_fclose_ FILE *st = NULL; char t[32]; struct ps_struct *parent; ps->next_ps = new0(struct ps_struct, 1); if (!ps->next_ps) return log_oom(); ps = ps->next_ps; ps->pid = pid; ps->sched = -1; ps->schedstat = -1; ps->sample = new0(struct ps_sched_struct, 1); if (!ps->sample) return log_oom(); ps->sample->sampledata = sampledata; (*pscount)++; /* mark our first sample */ ps->first = ps->last = ps->sample; ps->sample->runtime = atoll(rt); ps->sample->waittime = atoll(wt); /* get name, start time */ if (ps->sched < 0) { sprintf(filename, "%d/sched", pid); ps->sched = openat(procfd, filename, O_RDONLY|O_CLOEXEC); if (ps->sched < 0) continue; } s = pread(ps->sched, buf, sizeof(buf) - 1, 0); if (s <= 0) { ps->sched = safe_close(ps->sched); continue; } buf[s] = '\0'; if (!sscanf(buf, "%s %*s %*s", key)) continue; strscpy(ps->name, sizeof(ps->name), key); /* cmdline */ if (arg_show_cmdline) pid_cmdline_strscpy(procfd, ps->name, sizeof(ps->name), pid); /* discard line 2 */ m = bufgetline(buf); if (!m) continue; m = bufgetline(m); if (!m) continue; if (!sscanf(m, "%*s %*s %s", t)) continue; r = safe_atod(t, &ps->starttime); if (r < 0) continue; ps->starttime /= 1000.0; if (arg_show_cgroup) /* if this fails, that's OK */ cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, ps->pid, &ps->cgroup); /* ppid */ sprintf(filename, "%d/stat", pid); fd = openat(procfd, filename, O_RDONLY|O_CLOEXEC); if (fd < 0) continue; st = fdopen(fd, "re"); if (!st) { close(fd); continue; } if (!fscanf(st, "%*s %*s %*s %i", &p)) continue; ps->ppid = p; /* * setup child pointers * * these are used to paint the tree coherently later * each parent has a LL of children, and a LL of siblings */ if (pid == 1) continue; /* nothing to do for init atm */ /* kthreadd has ppid=0, which breaks our tree ordering */ if (ps->ppid == 0) ps->ppid = 1; parent = ps_first; while ((parent->next_ps && parent->pid != ps->ppid)) parent = parent->next_ps; if (parent->pid != ps->ppid) { /* orphan */ ps->ppid = 1; parent = ps_first->next_ps; } ps->parent = parent; if (!parent->children) { /* it's the first child */ parent->children = ps; } else { /* walk all children and append */ struct ps_struct *children; children = parent->children; while (children->next) children = children->next; children->next = ps; } } /* else -> found pid, append data in ps */ /* below here is all continuous logging parts - we get here on every * iteration */ /* rt, wt */ if (ps->schedstat < 0) { sprintf(filename, "%d/schedstat", pid); ps->schedstat = openat(procfd, filename, O_RDONLY|O_CLOEXEC); if (ps->schedstat < 0) continue; } s = pread(ps->schedstat, buf, sizeof(buf) - 1, 0); if (s <= 0) { /* clean up our file descriptors - assume that the process exited */ close(ps->schedstat); ps->schedstat = -1; ps->sched = safe_close(ps->sched); continue; } buf[s] = '\0'; if (!sscanf(buf, "%s %s %*s", rt, wt)) continue; ps->sample->next = new0(struct ps_sched_struct, 1); if (!ps->sample->next) return log_oom(); ps->sample->next->prev = ps->sample; ps->sample = ps->sample->next; ps->last = ps->sample; ps->sample->runtime = atoll(rt); ps->sample->waittime = atoll(wt); ps->sample->sampledata = sampledata; ps->sample->ps_new = ps; if (ps_prev) ps_prev->cross = ps->sample; ps_prev = ps->sample; ps->total = (ps->last->runtime - ps->first->runtime) / 1000000000.0; /* Take into account CPU runtime/waittime spent in non-main threads of the process * by parsing "/proc/[pid]/task/[tid]/schedstat" for all [tid] != [pid] * See https://github.com/systemd/systemd/issues/139 */ /* Browse directory "/proc/[pid]/task" to know the thread ids of process [pid] */ snprintf(filename, sizeof(filename), PID_FMT "/task", pid); taskfd = openat(procfd, filename, O_RDONLY|O_DIRECTORY|O_CLOEXEC); if (taskfd >= 0) { _cleanup_closedir_ DIR *taskdir = NULL; taskdir = fdopendir(taskfd); if (!taskdir) { safe_close(taskfd); return -errno; } FOREACH_DIRENT(ent, taskdir, break) { int tid = -1; _cleanup_close_ int tid_schedstat = -1; long long delta_rt; long long delta_wt; if ((ent->d_name[0] < '0') || (ent->d_name[0] > '9')) continue; /* Skip main thread as it was already accounted */ r = safe_atoi(ent->d_name, &tid); if (r < 0 || tid == pid) continue; /* Parse "/proc/[pid]/task/[tid]/schedstat" */ snprintf(filename, sizeof(filename), PID_FMT "/schedstat", tid); tid_schedstat = openat(taskfd, filename, O_RDONLY|O_CLOEXEC); if (tid_schedstat == -1) continue; s = pread(tid_schedstat, buf, sizeof(buf) - 1, 0); if (s <= 0) continue; buf[s] = '\0'; if (!sscanf(buf, "%s %s %*s", rt, wt)) continue; r = safe_atolli(rt, &delta_rt); if (r < 0) continue; r = safe_atolli(rt, &delta_wt); if (r < 0) continue; ps->sample->runtime += delta_rt; ps->sample->waittime += delta_wt; } } if (!arg_pss) goto catch_rename; /* Pss */ if (!ps->smaps) { sprintf(filename, "%d/smaps", pid); fd = openat(procfd, filename, O_RDONLY|O_CLOEXEC); if (fd < 0) continue; ps->smaps = fdopen(fd, "re"); if (!ps->smaps) { close(fd); continue; } setvbuf(ps->smaps, smaps_buf, _IOFBF, sizeof(smaps_buf)); } else { rewind(ps->smaps); } /* test to see if we need to skip another field */ if (skip == 0) { if (fgets(buf, sizeof(buf), ps->smaps) == NULL) { continue; } if (fread(buf, 1, 28 * 15, ps->smaps) != (28 * 15)) { continue; } if (buf[392] == 'V') { skip = 2; } else { skip = 1; } rewind(ps->smaps); } while (1) { int pss_kb; /* skip one line, this contains the object mapped. */ if (fgets(buf, sizeof(buf), ps->smaps) == NULL) { break; } /* then there's a 28 char 14 line block */ if (fread(buf, 1, 28 * 14, ps->smaps) != 28 * 14) { break; } pss_kb = atoi(&buf[61]); ps->sample->pss += pss_kb; /* skip one more line if this is a newer kernel */ if (skip == 2) { if (fgets(buf, sizeof(buf), ps->smaps) == NULL) break; } } if (ps->sample->pss > ps->pss_max) ps->pss_max = ps->sample->pss; catch_rename: /* catch process rename, try to randomize time */ mod = (arg_hz < 4.0) ? 4.0 : (arg_hz / 4.0); if (((sample - ps->pid) + pid) % (int)(mod) == 0) { /* re-fetch name */ /* get name, start time */ if (ps->sched < 0) { sprintf(filename, "%d/sched", pid); ps->sched = openat(procfd, filename, O_RDONLY|O_CLOEXEC); if (ps->sched < 0) continue; } s = pread(ps->sched, buf, sizeof(buf) - 1, 0); if (s <= 0) { /* clean up file descriptors */ ps->sched = safe_close(ps->sched); ps->schedstat = safe_close(ps->schedstat); continue; } buf[s] = '\0'; if (!sscanf(buf, "%s %*s %*s", key)) continue; strscpy(ps->name, sizeof(ps->name), key); /* cmdline */ if (arg_show_cmdline) pid_cmdline_strscpy(procfd, ps->name, sizeof(ps->name), pid); } } return 0; } systemd-229/src/bootchart/store.h000066400000000000000000000020741265713322000171450ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2009-2013 Intel Corporation Authors: Auke Kok systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "bootchart.h" double gettime_ns(void); void log_uptime(void); int log_sample(DIR *proc, int sample, struct ps_struct *ps_first, struct list_sample_data **ptr, int *pscount, int *cpus); systemd-229/src/bootchart/svg.c000066400000000000000000001555551265713322000166200ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2009-2013 Intel Corporation Authors: Auke Kok systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "alloc-util.h" #include "architecture.h" #include "bootchart.h" #include "fd-util.h" #include "fileio.h" #include "list.h" #include "macro.h" #include "stdio-util.h" #include "store.h" #include "svg.h" #include "utf8.h" #include "util.h" #define time_to_graph(t) ((t) * arg_scale_x) #define ps_to_graph(n) ((n) * arg_scale_y) #define kb_to_graph(m) ((m) * arg_scale_y * 0.0001) #define to_color(n) (192.0 - ((n) * 192.0)) static const char * const colorwheel[12] = { "rgb(255,32,32)", // red "rgb(32,192,192)", // cyan "rgb(255,128,32)", // orange "rgb(128,32,192)", // blue-violet "rgb(255,255,32)", // yellow "rgb(192,32,128)", // red-violet "rgb(32,255,32)", // green "rgb(255,64,32)", // red-orange "rgb(32,32,255)", // blue "rgb(255,192,32)", // yellow-orange "rgb(192,32,192)", // violet "rgb(32,192,32)" // yellow-green }; static double idletime = -1.0; static int pfiltered = 0; static int pcount = 0; static int kcount = 0; static double psize = 0; static double ksize = 0; static double esize = 0; static struct list_sample_data *sampledata; static struct list_sample_data *prev_sampledata; static void svg_header(FILE *of, struct list_sample_data *head, double graph_start, int n_cpus) { double w; double h; struct list_sample_data *sampledata_last; assert(head); sampledata_last = head; LIST_FOREACH_BEFORE(link, sampledata, head) { sampledata_last = sampledata; } /* min width is about 1600px due to the label */ w = 150.0 + 10.0 + time_to_graph(sampledata_last->sampletime - graph_start); w = ((w < 1600.0) ? 1600.0 : w); /* height is variable based on pss, psize, ksize */ h = 400.0 + (arg_scale_y * 30.0) /* base graphs and title */ + (arg_pss ? (100.0 * arg_scale_y) + (arg_scale_y * 7.0) : 0.0) /* pss estimate */ + psize + ksize + esize + (n_cpus * 15 * arg_scale_y); fprintf(of, "\n"); fprintf(of, "\n"); //fprintf(of, "\n", 1000 + 150 + (pcount * 20)); fprintf(of, "\n\n"); /* write some basic info as a comment, including some help */ fprintf(of, "\n"); fprintf(of, "\n"); fprintf(of, "\n"); fprintf(of, "\n"); fprintf(of, "\n\n"); fprintf(of, "\n", VERSION); fprintf(of, "\n", arg_hz, arg_samples_len); fprintf(of, "\n", arg_scale_x, arg_scale_y); fprintf(of, "\n", arg_relative, arg_filter); fprintf(of, "\n", arg_pss, arg_entropy); fprintf(of, "\n\n", arg_output_path, arg_init_path); /* style sheet */ fprintf(of, "\n \n\n\n"); } static int svg_title(FILE *of, const char *build, int pscount, double log_start, int overrun) { _cleanup_free_ char *cmdline = NULL; _cleanup_free_ char *model = NULL; _cleanup_free_ char *buf = NULL; char date[256] = "Unknown"; const char *cpu; char *c; time_t t; int r; struct utsname uts; r = read_one_line_file("/proc/cmdline", &cmdline); if (r < 0) { log_error_errno(r, "Unable to read cmdline: %m"); return r; } /* extract root fs so we can find disk model name in sysfs */ /* FIXME: this works only in the simple case */ c = strstr(cmdline, "root=/dev/"); if (c) { char rootbdev[4]; char filename[32]; strncpy(rootbdev, &c[10], sizeof(rootbdev) - 1); rootbdev[3] = '\0'; xsprintf(filename, "/sys/block/%s/device/model", rootbdev); r = read_one_line_file(filename, &model); if (r < 0) log_info("Error reading disk model for %s: %m\n", rootbdev); } /* various utsname parameters */ r = uname(&uts); if (r < 0) { log_error("Error getting uname info\n"); return -errno; } /* date */ t = time(NULL); r = strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", localtime(&t)); assert_se(r > 0); /* CPU type */ r = get_proc_field("/proc/cpuinfo", PROC_CPUINFO_MODEL, "\n", &buf); if (r < 0) cpu = "Unknown"; else cpu = buf; fprintf(of, "Bootchart for %s - %s\n", uts.nodename, date); fprintf(of, "System: %s %s %s %s\n", uts.sysname, uts.release, uts.version, uts.machine); fprintf(of, "CPU: %s\n", cpu); if (model) fprintf(of, "Disk: %s\n", model); fprintf(of, "Boot options: %s\n", cmdline); fprintf(of, "Build: %s\n", build); fprintf(of, "Log start time: %.03fs\n", log_start); fprintf(of, "Idle time: "); if (idletime >= 0.0) fprintf(of, "%.03fs", idletime); else fprintf(of, "Not detected"); fprintf(of, "\n"); fprintf(of, "Graph data: %.03f samples/sec, recorded %i total, dropped %i samples, %i processes, %i filtered\n", arg_hz, arg_samples_len, overrun, pscount, pfiltered); return 0; } static void svg_graph_box(FILE *of, struct list_sample_data *head, int height, double graph_start) { double d = 0.0; int i = 0; double finalsample = 0.0; struct list_sample_data *sampledata_last; sampledata_last = head; LIST_FOREACH_BEFORE(link, sampledata, head) { sampledata_last = sampledata; } finalsample = sampledata_last->sampletime; /* outside box, fill */ fprintf(of, "\n", time_to_graph(0.0), time_to_graph(finalsample - graph_start), ps_to_graph(height)); for (d = graph_start; d <= finalsample; d += (arg_scale_x < 2.0 ? 60.0 : arg_scale_x < 10.0 ? 1.0 : 0.1)) { /* lines for each second */ if (i % 50 == 0) fprintf(of, " \n", time_to_graph(d - graph_start), time_to_graph(d - graph_start), ps_to_graph(height)); else if (i % 10 == 0) fprintf(of, " \n", time_to_graph(d - graph_start), time_to_graph(d - graph_start), ps_to_graph(height)); else fprintf(of, " \n", time_to_graph(d - graph_start), time_to_graph(d - graph_start), ps_to_graph(height)); /* time label */ if (i % 10 == 0) fprintf(of, " %.01fs\n", time_to_graph(d - graph_start), -5.0, d - graph_start); i++; } } /* xml comments must not contain "--" */ static char* xml_comment_encode(const char* name) { char *enc_name, *p; enc_name = strdup(name); if (!enc_name) return NULL; for (p = enc_name; *p; p++) if (p[0] == '-' && p[1] == '-') p[1] = '_'; return enc_name; } static void svg_pss_graph(FILE *of, struct list_sample_data *head, struct ps_struct *ps_first, double graph_start) { struct ps_struct *ps; int i; struct list_sample_data *sampledata_last; sampledata_last = head; LIST_FOREACH_BEFORE(link, sampledata, head) { sampledata_last = sampledata; } fprintf(of, "\n\n\n"); fprintf(of, "\n Memory allocation - Pss\n"); /* vsize 1000 == 1000mb */ svg_graph_box(of, head, 100, graph_start); /* draw some hlines for usable memory sizes */ for (i = 100000; i < 1000000; i += 100000) { fprintf(of, " \n", time_to_graph(.0), kb_to_graph(i), time_to_graph(sampledata_last->sampletime - graph_start), kb_to_graph(i)); fprintf(of, " %dM\n", time_to_graph(sampledata_last->sampletime - graph_start) + 5, kb_to_graph(i), (1000000 - i) / 1000); } fprintf(of, "\n"); /* now plot the graph itself */ i = 1; prev_sampledata = head; LIST_FOREACH_BEFORE(link, sampledata, head) { int bottom; int top; struct ps_sched_struct *cross_place; bottom = 0; top = 0; /* put all the small pss blocks into the bottom */ ps = ps_first; while (ps->next_ps) { ps = ps->next_ps; if (!ps) continue; ps->sample = ps->first; while (ps->sample->next) { ps->sample = ps->sample->next; if (ps->sample->sampledata == sampledata) break; } if (ps->sample->sampledata == sampledata) { if (ps->sample->pss <= (100 * arg_scale_y)) top += ps->sample->pss; break; } } while (ps->sample->cross) { cross_place = ps->sample->cross; ps = ps->sample->cross->ps_new; ps->sample = cross_place; if (ps->sample->pss <= (100 * arg_scale_y)) top += ps->sample->pss; } fprintf(of, " \n", "rgb(64,64,64)", time_to_graph(prev_sampledata->sampletime - graph_start), kb_to_graph(1000000.0 - top), time_to_graph(sampledata->sampletime - prev_sampledata->sampletime), kb_to_graph(top - bottom)); bottom = top; /* now plot the ones that are of significant size */ ps = ps_first; while (ps->next_ps) { ps = ps->next_ps; if (!ps) continue; ps->sample = ps->first; while (ps->sample->next) { ps->sample = ps->sample->next; if (ps->sample->sampledata == sampledata) break; } /* don't draw anything smaller than 2mb */ if (ps->sample->sampledata != sampledata) continue; if (ps->sample->pss > (100 * arg_scale_y)) { top = bottom + ps->sample->pss; fprintf(of, " \n", colorwheel[ps->pid % 12], time_to_graph(prev_sampledata->sampletime - graph_start), kb_to_graph(1000000.0 - top), time_to_graph(sampledata->sampletime - prev_sampledata->sampletime), kb_to_graph(top - bottom)); bottom = top; } break; } while ((cross_place = ps->sample->cross)) { ps = ps->sample->cross->ps_new; ps->sample = cross_place; if (ps->sample->pss > (100 * arg_scale_y)) { top = bottom + ps->sample->pss; fprintf(of, " \n", colorwheel[ps->pid % 12], time_to_graph(prev_sampledata->sampletime - graph_start), kb_to_graph(1000000.0 - top), time_to_graph(sampledata->sampletime - prev_sampledata->sampletime), kb_to_graph(top - bottom)); bottom = top; } } prev_sampledata = sampledata; i++; } /* overlay all the text labels */ i = 1; LIST_FOREACH_BEFORE(link, sampledata, head) { int bottom; int top = 0; struct ps_sched_struct *prev_sample; struct ps_sched_struct *cross_place; /* put all the small pss blocks into the bottom */ ps = ps_first->next_ps; while (ps->next_ps) { ps = ps->next_ps; if (!ps) continue; ps->sample = ps->first; while (ps->sample->next) { ps->sample = ps->sample->next; if (ps->sample->sampledata == sampledata) break; } if (ps->sample->sampledata == sampledata) { if (ps->sample->pss <= (100 * arg_scale_y)) top += ps->sample->pss; break; } } while ((cross_place = ps->sample->cross)) { ps = ps->sample->cross->ps_new; ps->sample = cross_place; if (ps->sample->pss <= (100 * arg_scale_y)) top += ps->sample->pss; } bottom = top; /* now plot the ones that are of significant size */ ps = ps_first; while (ps->next_ps) { prev_sample = ps->sample; ps = ps->next_ps; if (!ps) continue; ps->sample = ps->first; while (ps->sample->next) { prev_sample = ps->sample; ps->sample = ps->sample->next; if (ps->sample->sampledata == sampledata) break; } /* don't draw anything smaller than 2mb */ if (ps->sample->sampledata == sampledata) { if (ps->sample->pss > (100 * arg_scale_y)) { top = bottom + ps->sample->pss; /* draw a label with the process / PID */ if ((i == 1) || (prev_sample->pss <= (100 * arg_scale_y))) fprintf(of, " %s [%i]\n", time_to_graph(sampledata->sampletime - graph_start), kb_to_graph(1000000.0 - bottom - ((top - bottom) / 2)), ps->name, ps->pid); bottom = top; } break; } } while ((cross_place = ps->sample->cross)) { ps = ps->sample->cross->ps_new; ps->sample = cross_place; prev_sample = ps->sample->prev; if (ps->sample->pss > (100 * arg_scale_y)) { top = bottom + ps->sample->pss; /* draw a label with the process / PID */ if ((i == 1) || (prev_sample->pss <= (100 * arg_scale_y))) fprintf(of, " %s [%i]\n", time_to_graph(sampledata->sampletime - graph_start), kb_to_graph(1000000.0 - bottom - ((top - bottom) / 2)), ps->name, ps->pid); bottom = top; } } i++; } /* debug output - full data dump */ fprintf(of, "\n\n\n"); ps = ps_first; while (ps->next_ps) { _cleanup_free_ char *enc_name = NULL; ps = ps->next_ps; if (!ps) continue; enc_name = xml_comment_encode(ps->name); if (!enc_name) continue; fprintf(of, "\n"); } } static void svg_io_bi_bar(FILE *of, struct list_sample_data *head, int n_samples, double graph_start, double interval) { double max = 0.0; double range; int max_here = 0; int i; int k; struct list_sample_data *start_sampledata; struct list_sample_data *stop_sampledata; fprintf(of, "\n"); fprintf(of, "IO utilization - read\n"); /* * calculate rounding range * * We need to round IO data since IO block data is not updated on * each poll. Applying a smoothing function loses some burst data, * so keep the smoothing range short. */ range = 0.25 / (1.0 / arg_hz); if (range < 2.0) range = 2.0; /* no smoothing */ /* surrounding box */ svg_graph_box(of, head, 5, graph_start); /* find the max IO first */ i = 1; LIST_FOREACH_BEFORE(link, sampledata, head) { int start; int stop; int diff; double tot; start = MAX(i - ((range / 2) - 1), 0); stop = MIN(i + (range / 2), n_samples - 1); diff = (stop - start); start_sampledata = sampledata; stop_sampledata = sampledata; for (k = 0; k < ((range/2) - 1) && start_sampledata->link_next; k++) start_sampledata = start_sampledata->link_next; for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++) stop_sampledata = stop_sampledata->link_prev; tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff; if (tot > max) { max = tot; max_here = i; } tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo) / diff; if (tot > max) max = tot; i++; } /* plot bi */ i = 1; prev_sampledata = head; LIST_FOREACH_BEFORE(link, sampledata, head) { int start; int stop; int diff; double tot; double pbi = 0; start = MAX(i - ((range / 2) - 1), 0); stop = MIN(i + (range / 2), n_samples); diff = (stop - start); start_sampledata = sampledata; stop_sampledata = sampledata; for (k = 0; k < ((range/2)-1) && start_sampledata->link_next; k++) start_sampledata = start_sampledata->link_next; for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++) stop_sampledata = stop_sampledata->link_prev; tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff; if (max > 0) pbi = tot / max; if (pbi > 0.001) fprintf(of, "\n", time_to_graph(prev_sampledata->sampletime - graph_start), (arg_scale_y * 5) - (pbi * (arg_scale_y * 5)), time_to_graph(sampledata->sampletime - prev_sampledata->sampletime), pbi * (arg_scale_y * 5)); /* labels around highest value */ if (i == max_here) fprintf(of, " %0.2fmb/sec\n", time_to_graph(sampledata->sampletime - graph_start) + 5, ((arg_scale_y * 5) - (pbi * (arg_scale_y * 5))) + 15, max / 1024.0 / (interval / 1000000000.0)); i++; prev_sampledata = sampledata; } } static void svg_io_bo_bar(FILE *of, struct list_sample_data *head, int n_samples, double graph_start, double interval) { double max = 0.0; double range; int max_here = 0; int i; int k; struct list_sample_data *start_sampledata; struct list_sample_data *stop_sampledata; fprintf(of, "\n"); fprintf(of, "IO utilization - write\n"); /* * calculate rounding range * * We need to round IO data since IO block data is not updated on * each poll. Applying a smoothing function loses some burst data, * so keep the smoothing range short. */ range = 0.25 / (1.0 / arg_hz); if (range < 2.0) range = 2.0; /* no smoothing */ /* surrounding box */ svg_graph_box(of, head, 5, graph_start); /* find the max IO first */ i = 0; LIST_FOREACH_BEFORE(link, sampledata, head) { int start; int stop; int diff; double tot; start = MAX(i - ((range / 2) - 1), 0); stop = MIN(i + (range / 2), n_samples - 1); diff = (stop - start); start_sampledata = sampledata; stop_sampledata = sampledata; for (k = 0; k < (range/2) - 1 && start_sampledata->link_next; k++) start_sampledata = start_sampledata->link_next; for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++) stop_sampledata = stop_sampledata->link_prev; tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff; if (tot > max) max = tot; tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo) / diff; if (tot > max) { max = tot; max_here = i; } i++; } /* plot bo */ prev_sampledata = head; i = 1; LIST_FOREACH_BEFORE(link, sampledata, head) { int start, stop, diff; double tot, pbo; pbo = 0; start = MAX(i - ((range / 2) - 1), 0); stop = MIN(i + (range / 2), n_samples); diff = (stop - start); start_sampledata = sampledata; stop_sampledata = sampledata; for (k = 0; k < ((range/2)-1) && start_sampledata->link_next; k++) start_sampledata = start_sampledata->link_next; for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++) stop_sampledata = stop_sampledata->link_prev; tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo) / diff; if (max > 0) pbo = tot / max; if (pbo > 0.001) fprintf(of, "\n", time_to_graph(prev_sampledata->sampletime - graph_start), (arg_scale_y * 5) - (pbo * (arg_scale_y * 5)), time_to_graph(sampledata->sampletime - prev_sampledata->sampletime), pbo * (arg_scale_y * 5)); /* labels around highest bo value */ if (i == max_here) fprintf(of, " %0.2fmb/sec\n", time_to_graph(sampledata->sampletime - graph_start) + 5, ((arg_scale_y * 5) - (pbo * (arg_scale_y * 5))), max / 1024.0 / (interval / 1000000000.0)); i++; prev_sampledata = sampledata; } } static void svg_cpu_bar(FILE *of, struct list_sample_data *head, int n_cpus, int cpu_num, double graph_start) { fprintf(of, "\n"); if (cpu_num < 0) fprintf(of, "CPU[overall] utilization\n"); else fprintf(of, "CPU[%d] utilization\n", cpu_num); /* surrounding box */ svg_graph_box(of, head, 5, graph_start); /* bars for each sample, proportional to the CPU util. */ prev_sampledata = head; LIST_FOREACH_BEFORE(link, sampledata, head) { int c; double trt; double ptrt; ptrt = trt = 0.0; if (cpu_num < 0) for (c = 0; c < n_cpus; c++) trt += sampledata->runtime[c] - prev_sampledata->runtime[c]; else trt = sampledata->runtime[cpu_num] - prev_sampledata->runtime[cpu_num]; trt = trt / 1000000000.0; if (cpu_num < 0) trt = trt / (double)n_cpus; if (trt > 0.0) ptrt = trt / (sampledata->sampletime - prev_sampledata->sampletime); if (ptrt > 1.0) ptrt = 1.0; if (ptrt > 0.001) fprintf(of, "\n", time_to_graph(prev_sampledata->sampletime - graph_start), (arg_scale_y * 5) - (ptrt * (arg_scale_y * 5)), time_to_graph(sampledata->sampletime - prev_sampledata->sampletime), ptrt * (arg_scale_y * 5)); prev_sampledata = sampledata; } } static void svg_wait_bar(FILE *of, struct list_sample_data *head, int n_cpus, int cpu_num, double graph_start) { fprintf(of, "\n"); if (cpu_num < 0) fprintf(of, "CPU[overall] wait\n"); else fprintf(of, "CPU[%d] wait\n", cpu_num); /* surrounding box */ svg_graph_box(of, head, 5, graph_start); /* bars for each sample, proportional to the CPU util. */ prev_sampledata = head; LIST_FOREACH_BEFORE(link, sampledata, head) { int c; double twt; double ptwt; ptwt = twt = 0.0; if (cpu_num < 0) for (c = 0; c < n_cpus; c++) twt += sampledata->waittime[c] - prev_sampledata->waittime[c]; else twt = sampledata->waittime[cpu_num] - prev_sampledata->waittime[cpu_num]; twt = twt / 1000000000.0; if (cpu_num < 0) twt = twt / (double)n_cpus; if (twt > 0.0) ptwt = twt / (sampledata->sampletime - prev_sampledata->sampletime); if (ptwt > 1.0) ptwt = 1.0; if (ptwt > 0.001) fprintf(of, "\n", time_to_graph(prev_sampledata->sampletime - graph_start), ((arg_scale_y * 5) - (ptwt * (arg_scale_y * 5))), time_to_graph(sampledata->sampletime - prev_sampledata->sampletime), ptwt * (arg_scale_y * 5)); prev_sampledata = sampledata; } } static void svg_entropy_bar(FILE *of, struct list_sample_data *head, double graph_start) { fprintf(of, "\n"); fprintf(of, "Entropy pool size\n"); /* surrounding box */ svg_graph_box(of, head, 5, graph_start); /* bars for each sample, scale 0-4096 */ prev_sampledata = head; LIST_FOREACH_BEFORE(link, sampledata, head) { fprintf(of, "\n", time_to_graph(prev_sampledata->sampletime - graph_start), ((arg_scale_y * 5) - ((sampledata->entropy_avail / 4096.) * (arg_scale_y * 5))), time_to_graph(sampledata->sampletime - prev_sampledata->sampletime), (sampledata->entropy_avail / 4096.) * (arg_scale_y * 5)); prev_sampledata = sampledata; } } static struct ps_struct *get_next_ps(struct ps_struct *ps, struct ps_struct *ps_first) { /* * walk the list of processes and return the next one to be * painted */ if (ps == ps_first) return ps->next_ps; /* go deep */ if (ps->children) return ps->children; /* find siblings */ if (ps->next) return ps->next; /* go back for parent siblings */ for (;;) { if (ps->parent && ps->parent->next) return ps->parent->next; ps = ps->parent; if (!ps) return ps; } return NULL; } static bool ps_filter(struct ps_struct *ps) { if (!arg_filter) return false; /* can't draw data when there is only 1 sample (need start + stop) */ if (ps->first == ps->last) return true; /* don't filter kthreadd */ if (ps->pid == 2) return false; /* drop stuff that doesn't use any real CPU time */ if (ps->total <= 0.001) return true; return 0; } static void svg_do_initcall(FILE *of, struct list_sample_data *head, int count_only, double graph_start) { _cleanup_pclose_ FILE *f = NULL; double t; char func[256]; int ret; int usecs; /* can't plot initcall when disabled or in relative mode */ if (!arg_initcall || arg_relative) { kcount = 0; return; } if (!count_only) { fprintf(of, "\n"); fprintf(of, "Kernel init threads\n"); /* surrounding box */ svg_graph_box(of, head, kcount, graph_start); } kcount = 0; /* * Initcall graphing - parses dmesg buffer and displays kernel threads * This somewhat uses the same methods and scaling to show processes * but looks a lot simpler. It's overlaid entirely onto the PS graph * when appropriate. */ f = popen("dmesg", "r"); if (!f) return; while (!feof(f)) { int c; int z = 0; char l[256]; if (fgets(l, sizeof(l) - 1, f) == NULL) continue; c = sscanf(l, "[%lf] initcall %s %*s %d %*s %d %*s", &t, func, &ret, &usecs); if (c != 4) { /* also parse initcalls done by module loading */ c = sscanf(l, "[%lf] initcall %s %*s %*s %d %*s %d %*s", &t, func, &ret, &usecs); if (c != 4) continue; } /* chop the +0xXX/0xXX stuff */ while(func[z] != '+') z++; func[z] = 0; if (count_only) { /* filter out irrelevant stuff */ if (usecs >= 1000) kcount++; continue; } fprintf(of, "\n", func, t, usecs, ret); if (usecs < 1000) continue; /* rect */ fprintf(of, " \n", time_to_graph(t - (usecs / 1000000.0)), ps_to_graph(kcount), time_to_graph(usecs / 1000000.0), ps_to_graph(1)); /* label */ fprintf(of, " %s %.03fs\n", time_to_graph(t - (usecs / 1000000.0)) + 5, ps_to_graph(kcount) + 15, func, usecs / 1000000.0); kcount++; } } static void svg_ps_bars(FILE *of, struct list_sample_data *head, int n_samples, int n_cpus, struct ps_struct *ps_first, double graph_start, double interval) { struct ps_struct *ps; int i = 0; int j = 0; int pid; double w = 0.0; fprintf(of, "\n"); fprintf(of, "Processes\n"); /* surrounding box */ svg_graph_box(of, head, pcount, graph_start); /* pass 2 - ps boxes */ ps = ps_first; while ((ps = get_next_ps(ps, ps_first))) { _cleanup_free_ char *enc_name = NULL, *escaped = NULL; double endtime; double starttime; int t; if (!utf8_is_printable(ps->name, strlen(ps->name))) escaped = utf8_escape_non_printable(ps->name); enc_name = xml_comment_encode(escaped ? escaped : ps->name); if (!enc_name) continue; /* leave some trace of what we actually filtered etc. */ fprintf(of, "\n", enc_name, ps->pid, ps->ppid, ps->total); starttime = ps->first->sampledata->sampletime; if (!ps_filter(ps)) { /* remember where _to_ our children need to draw a line */ ps->pos_x = time_to_graph(starttime - graph_start); ps->pos_y = ps_to_graph(j+1); /* bottom left corner */ } else if (ps->parent){ /* hook children to our parent coords instead */ ps->pos_x = ps->parent->pos_x; ps->pos_y = ps->parent->pos_y; /* if this is the last child, we might still need to draw a connecting line */ if ((!ps->next) && (ps->parent)) fprintf(of, " \n", ps->parent->pos_x, ps_to_graph(j-1) + 10.0, /* whee, use the last value here */ ps->parent->pos_x, ps->parent->pos_y); continue; } endtime = ps->last->sampledata->sampletime; fprintf(of, " \n", time_to_graph(starttime - graph_start), ps_to_graph(j), time_to_graph(ps->last->sampledata->sampletime - starttime), ps_to_graph(1)); /* paint cpu load over these */ ps->sample = ps->first; t = 1; while (ps->sample->next) { double rt, prt; double wt, wrt; struct ps_sched_struct *prev; prev = ps->sample; ps->sample = ps->sample->next; /* calculate over interval */ rt = ps->sample->runtime - prev->runtime; wt = ps->sample->waittime - prev->waittime; prt = (rt / 1000000000) / (ps->sample->sampledata->sampletime - prev->sampledata->sampletime); wrt = (wt / 1000000000) / (ps->sample->sampledata->sampletime - prev->sampledata->sampletime); /* this can happen if timekeeping isn't accurate enough */ if (prt > 1.0) prt = 1.0; if (wrt > 1.0) wrt = 1.0; if ((prt < 0.1) && (wrt < 0.1)) /* =~ 26 (color threshold) */ continue; fprintf(of, " \n", time_to_graph(prev->sampledata->sampletime - graph_start), ps_to_graph(j), time_to_graph(ps->sample->sampledata->sampletime - prev->sampledata->sampletime), ps_to_graph(wrt)); /* draw cpu over wait - TODO figure out how/why run + wait > interval */ fprintf(of, " \n", time_to_graph(prev->sampledata->sampletime - graph_start), ps_to_graph(j + (1.0 - prt)), time_to_graph(ps->sample->sampledata->sampletime - prev->sampledata->sampletime), ps_to_graph(prt)); t++; } /* determine where to display the process name */ if ((endtime - starttime) < 1.5) /* too small to fit label inside the box */ w = endtime; else w = starttime; /* text label of process name */ fprintf(of, " %s [%i]%.03fs %s\n", time_to_graph(w - graph_start) + 5.0, ps_to_graph(j) + 14.0, escaped ? escaped : ps->name, ps->pid, (ps->last->runtime - ps->first->runtime) / 1000000000.0, arg_show_cgroup ? ps->cgroup : ""); /* paint lines to the parent process */ if (ps->parent) { /* horizontal part */ fprintf(of, " \n", time_to_graph(starttime - graph_start), ps_to_graph(j) + 10.0, ps->parent->pos_x, ps_to_graph(j) + 10.0); /* one vertical line connecting all the horizontal ones up */ if (!ps->next) fprintf(of, " \n", ps->parent->pos_x, ps_to_graph(j) + 10.0, ps->parent->pos_x, ps->parent->pos_y); } j++; /* count boxes */ fprintf(of, "\n"); } /* last pass - determine when idle */ pid = getpid(); /* make sure we start counting from the point where we actually have * data: assume that bootchart's first sample is when data started */ ps = ps_first; while (ps->next_ps) { ps = ps->next_ps; if (ps->pid == pid) break; } /* need to know last node first */ ps->sample = ps->first; i = ps->sample->next->sampledata->counter; while (ps->sample->next && i<(n_samples-(arg_hz/2))) { double crt; double brt; int c; int ii; struct ps_sched_struct *sample_hz; ps->sample = ps->sample->next; sample_hz = ps->sample; for (ii = 0; (ii < (int)arg_hz/2) && sample_hz->next; ii++) sample_hz = sample_hz->next; /* subtract bootchart cpu utilization from total */ crt = 0.0; for (c = 0; c < n_cpus; c++) crt += sample_hz->sampledata->runtime[c] - ps->sample->sampledata->runtime[c]; brt = sample_hz->runtime - ps->sample->runtime; /* * our definition of "idle": * * if for (hz / 2) we've used less CPU than (interval / 2) ... * defaults to 4.0%, which experimentally, is where atom idles */ if ((crt - brt) < (interval / 2.0)) { idletime = ps->sample->sampledata->sampletime - graph_start; fprintf(of, "\n\n", idletime); fprintf(of, "\n", time_to_graph(idletime), -arg_scale_y, time_to_graph(idletime), ps_to_graph(pcount) + arg_scale_y); fprintf(of, "%.01fs\n", time_to_graph(idletime) + 5.0, ps_to_graph(pcount) + arg_scale_y, idletime); break; } i++; } } static void svg_top_ten_cpu(FILE *of, struct ps_struct *ps_first) { struct ps_struct *top[10]; struct ps_struct emptyps = {}; struct ps_struct *ps; int n, m; for (n = 0; n < (int) ELEMENTSOF(top); n++) top[n] = &emptyps; /* walk all ps's and setup ptrs */ ps = ps_first; while ((ps = get_next_ps(ps, ps_first))) { for (n = 0; n < 10; n++) { if (ps->total <= top[n]->total) continue; /* cascade insert */ for (m = 9; m > n; m--) top[m] = top[m-1]; top[n] = ps; break; } } fprintf(of, "Top CPU consumers:\n"); for (n = 0; n < 10; n++) fprintf(of, "%3.03fs - %s [%d]\n", 20 + (n * 13), top[n]->total, top[n]->name, top[n]->pid); } static void svg_top_ten_pss(FILE *of, struct ps_struct *ps_first) { struct ps_struct *top[10]; struct ps_struct emptyps = {}; struct ps_struct *ps; int n, m; for (n = 0; n < (int) ELEMENTSOF(top); n++) top[n] = &emptyps; /* walk all ps's and setup ptrs */ ps = ps_first; while ((ps = get_next_ps(ps, ps_first))) { for (n = 0; n < 10; n++) { if (ps->pss_max <= top[n]->pss_max) continue; /* cascade insert */ for (m = 9; m > n; m--) top[m] = top[m-1]; top[n] = ps; break; } } fprintf(of, "Top PSS consumers:\n"); for (n = 0; n < 10; n++) fprintf(of, "%dK - %s [%d]\n", 20 + (n * 13), top[n]->pss_max, top[n]->name, top[n]->pid); } int svg_do(FILE *of, const char *build, struct list_sample_data *head, struct ps_struct *ps_first, int n_samples, int pscount, int n_cpus, double graph_start, double log_start, double interval, int overrun) { struct ps_struct *ps; double offset = 7; int r, c; sampledata = head; LIST_FIND_TAIL(link, sampledata, head); ps = ps_first; /* count initcall thread count first */ svg_do_initcall(of, head, 1, graph_start); ksize = kcount ? ps_to_graph(kcount) + (arg_scale_y * 2) : 0; /* then count processes */ while ((ps = get_next_ps(ps, ps_first))) { if (!ps_filter(ps)) pcount++; else pfiltered++; } psize = ps_to_graph(pcount) + (arg_scale_y * 2); esize = (arg_entropy ? arg_scale_y * 7 : 0); /* after this, we can draw the header with proper sizing */ svg_header(of, head, graph_start, arg_percpu ? n_cpus : 0); fprintf(of, "\n\n"); fprintf(of, "\n"); svg_io_bi_bar(of, head, n_samples, graph_start, interval); fprintf(of, "\n\n"); fprintf(of, "\n", 400.0 + (arg_scale_y * offset)); svg_io_bo_bar(of, head, n_samples, graph_start, interval); fprintf(of, "\n\n"); for (c = -1; c < (arg_percpu ? n_cpus : 0); c++) { offset += 7; fprintf(of, "\n", 400.0 + (arg_scale_y * offset)); svg_cpu_bar(of, head, n_cpus, c, graph_start); fprintf(of, "\n\n"); offset += 7; fprintf(of, "\n", 400.0 + (arg_scale_y * offset)); svg_wait_bar(of, head, n_cpus, c, graph_start); fprintf(of, "\n\n"); } if (kcount) { offset += 7; fprintf(of, "\n", 400.0 + (arg_scale_y * offset)); svg_do_initcall(of, head, 0, graph_start); fprintf(of, "\n\n"); } offset += 7; fprintf(of, "\n", 400.0 + (arg_scale_y * offset) + ksize); svg_ps_bars(of, head, n_samples, n_cpus, ps_first, graph_start, interval); fprintf(of, "\n\n"); fprintf(of, "\n"); r = svg_title(of, build, pscount, log_start, overrun); fprintf(of, "\n\n"); if (r < 0) return r; fprintf(of, "\n"); svg_top_ten_cpu(of, ps_first); fprintf(of, "\n\n"); if (arg_entropy) { fprintf(of, "\n", 400.0 + (arg_scale_y * offset) + ksize + psize); svg_entropy_bar(of, head, graph_start); fprintf(of, "\n\n"); } if (arg_pss) { fprintf(of, "\n", 400.0 + (arg_scale_y * offset) + ksize + psize + esize); svg_pss_graph(of, head, ps_first, graph_start); fprintf(of, "\n\n"); fprintf(of, "\n"); svg_top_ten_pss(of, ps_first); fprintf(of, "\n\n"); } /* fprintf footer */ fprintf(of, "\n\n"); return 0; } systemd-229/src/bootchart/svg.h000066400000000000000000000021271265713322000166070ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2009-2013 Intel Corporation Authors: Auke Kok systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int svg_do(FILE *of, const char *build, struct list_sample_data *head, struct ps_struct *ps_first, int n_samples, int pscount, int n_cpus, double graph_start, double log_start, double interval, int overrun); systemd-229/src/bus-proxyd/000077500000000000000000000000001265713322000157645ustar00rootroot00000000000000systemd-229/src/bus-proxyd/Makefile000077700000000000000000000000001265713322000212722../Makefileustar00rootroot00000000000000systemd-229/src/bus-proxyd/bus-proxyd.c000066400000000000000000000222421265713322000202460ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Daniel Mack Copyright 2014 Kay Sievers Copyright 2015 David Herrmann systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "sd-daemon.h" #include "alloc-util.h" #include "bus-internal.h" #include "bus-xml-policy.h" #include "capability-util.h" #include "def.h" #include "fd-util.h" #include "formats-util.h" #include "log.h" #include "proxy.h" #include "string-util.h" #include "strv.h" #include "user-util.h" #include "util.h" static char *arg_address = NULL; static char **arg_configuration = NULL; typedef struct { int fd; SharedPolicy *policy; uid_t bus_uid; } ClientContext; static ClientContext *client_context_free(ClientContext *c) { if (!c) return NULL; safe_close(c->fd); free(c); return NULL; } DEFINE_TRIVIAL_CLEANUP_FUNC(ClientContext*, client_context_free); static int client_context_new(ClientContext **out) { _cleanup_(client_context_freep) ClientContext *c = NULL; c = new0(ClientContext, 1); if (!c) return -ENOMEM; c->fd = -1; *out = c; c = NULL; return 0; } static void *run_client(void *userdata) { _cleanup_(client_context_freep) ClientContext *c = userdata; _cleanup_(proxy_freep) Proxy *p = NULL; char comm[16]; int r; r = proxy_new(&p, c->fd, c->fd, arg_address); c->fd = -1; if (r < 0) goto exit; /* set comm to "p$PIDu$UID" and suffix with '*' if truncated */ r = snprintf(comm, sizeof(comm), "p" PID_FMT "u" UID_FMT, p->local_creds.pid, p->local_creds.uid); if (r >= (ssize_t)sizeof(comm)) comm[sizeof(comm) - 2] = '*'; (void) prctl(PR_SET_NAME, comm); r = proxy_set_policy(p, c->policy, arg_configuration); if (r < 0) goto exit; r = proxy_hello_policy(p, c->bus_uid); if (r < 0) goto exit; r = proxy_run(p); exit: return NULL; } static int loop_clients(int accept_fd, uid_t bus_uid) { _cleanup_(shared_policy_freep) SharedPolicy *sp = NULL; pthread_attr_t attr; int r; r = pthread_attr_init(&attr); if (r != 0) return log_error_errno(r, "Cannot initialize pthread attributes: %m"); r = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (r != 0) { r = log_error_errno(r, "Cannot mark pthread attributes as detached: %m"); goto finish; } r = shared_policy_new(&sp); if (r < 0) goto finish; for (;;) { ClientContext *c; pthread_t tid; int fd; fd = accept4(accept_fd, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC); if (fd < 0) { if (errno == EAGAIN || errno == EINTR) continue; r = log_error_errno(errno, "accept4() failed: %m"); goto finish; } r = client_context_new(&c); if (r < 0) { log_oom(); close(fd); continue; } c->fd = fd; c->policy = sp; c->bus_uid = bus_uid; r = pthread_create(&tid, &attr, run_client, c); if (r != 0) { log_warning_errno(r, "Cannot spawn thread, ignoring: %m"); client_context_free(c); continue; } } finish: pthread_attr_destroy(&attr); return r; } static int help(void) { printf("%s [OPTIONS...]\n\n" "DBus proxy server.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --configuration=PATH Configuration file or directory\n" " --machine=MACHINE Connect to specified machine\n" " --address=ADDRESS Connect to the bus specified by ADDRESS\n" " (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n", program_invocation_short_name); return 0; } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_ADDRESS, ARG_CONFIGURATION, ARG_MACHINE, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "address", required_argument, NULL, ARG_ADDRESS }, { "configuration", required_argument, NULL, ARG_CONFIGURATION }, { "machine", required_argument, NULL, ARG_MACHINE }, {}, }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_ADDRESS: r = free_and_strdup(&arg_address, optarg); if (r < 0) return log_oom(); break; case ARG_CONFIGURATION: r = strv_extend(&arg_configuration, optarg); if (r < 0) return log_oom(); break; case ARG_MACHINE: { _cleanup_free_ char *e = NULL; char *a; e = bus_address_escape(optarg); if (!e) return log_oom(); a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL); if (!a) return log_oom(); free(arg_address); arg_address = a; break; } case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (argc > optind) { log_error("Too many arguments"); return -EINVAL; } if (!arg_address) { arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS); if (!arg_address) return log_oom(); } return 1; } int main(int argc, char *argv[]) { int r, accept_fd; uid_t uid, bus_uid; gid_t gid; log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); log_parse_environment(); log_open(); bus_uid = getuid(); if (geteuid() == 0) { const char *user = "systemd-bus-proxy"; r = get_user_creds(&user, &uid, &gid, NULL, NULL); if (r < 0) { log_error_errno(r, "Cannot resolve user name %s: %m", user); goto finish; } r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER); if (r < 0) { log_error_errno(r, "Cannot drop privileges: %m"); goto finish; } } r = parse_argv(argc, argv); if (r <= 0) goto finish; r = sd_listen_fds(0); if (r != 1) { log_error("Illegal number of file descriptors passed"); goto finish; } accept_fd = SD_LISTEN_FDS_START; r = fd_nonblock(accept_fd, false); if (r < 0) { log_error_errno(r, "Cannot mark accept-fd non-blocking: %m"); goto finish; } r = loop_clients(accept_fd, bus_uid); finish: sd_notify(false, "STOPPING=1\n" "STATUS=Shutting down."); strv_free(arg_configuration); free(arg_address); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/bus-proxyd/bus-xml-policy.c000066400000000000000000001401641265713322000210220ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-login.h" #include "alloc-util.h" #include "bus-internal.h" #include "bus-xml-policy.h" #include "conf-files.h" #include "fileio.h" #include "formats-util.h" #include "locale-util.h" #include "set.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "user-util.h" #include "xml.h" static void policy_item_free(PolicyItem *i) { assert(i); free(i->interface); free(i->member); free(i->error); free(i->name); free(i->path); free(i); } DEFINE_TRIVIAL_CLEANUP_FUNC(PolicyItem*, policy_item_free); static void item_append(PolicyItem *i, PolicyItem **list) { PolicyItem *tail; LIST_FIND_TAIL(items, *list, tail); LIST_INSERT_AFTER(items, *list, tail, i); } static int file_load(Policy *p, const char *path) { _cleanup_free_ char *c = NULL, *policy_user = NULL, *policy_group = NULL; _cleanup_(policy_item_freep) PolicyItem *i = NULL; void *xml_state = NULL; unsigned n_other = 0; const char *q; int r; enum { STATE_OUTSIDE, STATE_BUSCONFIG, STATE_POLICY, STATE_POLICY_CONTEXT, STATE_POLICY_CONSOLE, STATE_POLICY_USER, STATE_POLICY_GROUP, STATE_POLICY_OTHER_ATTRIBUTE, STATE_ALLOW_DENY, STATE_ALLOW_DENY_INTERFACE, STATE_ALLOW_DENY_MEMBER, STATE_ALLOW_DENY_ERROR, STATE_ALLOW_DENY_PATH, STATE_ALLOW_DENY_MESSAGE_TYPE, STATE_ALLOW_DENY_NAME, STATE_ALLOW_DENY_OTHER_ATTRIBUTE, STATE_OTHER, } state = STATE_OUTSIDE; enum { POLICY_CATEGORY_NONE, POLICY_CATEGORY_DEFAULT, POLICY_CATEGORY_MANDATORY, POLICY_CATEGORY_ON_CONSOLE, POLICY_CATEGORY_NO_CONSOLE, POLICY_CATEGORY_USER, POLICY_CATEGORY_GROUP } policy_category = POLICY_CATEGORY_NONE; unsigned line = 0; assert(p); r = read_full_file(path, &c, NULL); if (r < 0) { if (r == -ENOENT) return 0; if (r == -EISDIR) return r; return log_error_errno(r, "Failed to load %s: %m", path); } q = c; for (;;) { _cleanup_free_ char *name = NULL; int t; t = xml_tokenize(&q, &name, &xml_state, &line); if (t < 0) return log_error_errno(t, "XML parse failure in %s: %m", path); switch (state) { case STATE_OUTSIDE: if (t == XML_TAG_OPEN) { if (streq(name, "busconfig")) state = STATE_BUSCONFIG; else { log_error("Unexpected tag %s at %s:%u.", name, path, line); return -EINVAL; } } else if (t == XML_END) return 0; else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { log_error("Unexpected token (1) at %s:%u.", path, line); return -EINVAL; } break; case STATE_BUSCONFIG: if (t == XML_TAG_OPEN) { if (streq(name, "policy")) { state = STATE_POLICY; policy_category = POLICY_CATEGORY_NONE; free(policy_user); free(policy_group); policy_user = policy_group = NULL; } else { state = STATE_OTHER; n_other = 0; } } else if (t == XML_TAG_CLOSE_EMPTY || (t == XML_TAG_CLOSE && streq(name, "busconfig"))) state = STATE_OUTSIDE; else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { log_error("Unexpected token (2) at %s:%u.", path, line); return -EINVAL; } break; case STATE_POLICY: if (t == XML_ATTRIBUTE_NAME) { if (streq(name, "context")) state = STATE_POLICY_CONTEXT; else if (streq(name, "at_console")) state = STATE_POLICY_CONSOLE; else if (streq(name, "user")) state = STATE_POLICY_USER; else if (streq(name, "group")) state = STATE_POLICY_GROUP; else { log_warning("Attribute %s of tag unknown at %s:%u, ignoring.", name, path, line); state = STATE_POLICY_OTHER_ATTRIBUTE; } } else if (t == XML_TAG_CLOSE_EMPTY || (t == XML_TAG_CLOSE && streq(name, "policy"))) state = STATE_BUSCONFIG; else if (t == XML_TAG_OPEN) { PolicyItemType it; if (streq(name, "allow")) it = POLICY_ITEM_ALLOW; else if (streq(name, "deny")) it = POLICY_ITEM_DENY; else { log_warning("Unknown tag %s in %s:%u.", name, path, line); return -EINVAL; } assert(!i); i = new0(PolicyItem, 1); if (!i) return log_oom(); i->type = it; state = STATE_ALLOW_DENY; } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { log_error("Unexpected token (3) at %s:%u.", path, line); return -EINVAL; } break; case STATE_POLICY_CONTEXT: if (t == XML_ATTRIBUTE_VALUE) { if (streq(name, "default")) { policy_category = POLICY_CATEGORY_DEFAULT; state = STATE_POLICY; } else if (streq(name, "mandatory")) { policy_category = POLICY_CATEGORY_MANDATORY; state = STATE_POLICY; } else { log_error("context= parameter %s unknown for at %s:%u.", name, path, line); return -EINVAL; } } else { log_error("Unexpected token (4) at %s:%u.", path, line); return -EINVAL; } break; case STATE_POLICY_CONSOLE: if (t == XML_ATTRIBUTE_VALUE) { if (streq(name, "true")) { policy_category = POLICY_CATEGORY_ON_CONSOLE; state = STATE_POLICY; } else if (streq(name, "false")) { policy_category = POLICY_CATEGORY_NO_CONSOLE; state = STATE_POLICY; } else { log_error("at_console= parameter %s unknown for at %s:%u.", name, path, line); return -EINVAL; } } else { log_error("Unexpected token (4.1) at %s:%u.", path, line); return -EINVAL; } break; case STATE_POLICY_USER: if (t == XML_ATTRIBUTE_VALUE) { free(policy_user); policy_user = name; name = NULL; policy_category = POLICY_CATEGORY_USER; state = STATE_POLICY; } else { log_error("Unexpected token (5) in %s:%u.", path, line); return -EINVAL; } break; case STATE_POLICY_GROUP: if (t == XML_ATTRIBUTE_VALUE) { free(policy_group); policy_group = name; name = NULL; policy_category = POLICY_CATEGORY_GROUP; state = STATE_POLICY; } else { log_error("Unexpected token (6) at %s:%u.", path, line); return -EINVAL; } break; case STATE_POLICY_OTHER_ATTRIBUTE: if (t == XML_ATTRIBUTE_VALUE) state = STATE_POLICY; else { log_error("Unexpected token (7) in %s:%u.", path, line); return -EINVAL; } break; case STATE_ALLOW_DENY: assert(i); if (t == XML_ATTRIBUTE_NAME) { PolicyItemClass ic; if (startswith(name, "send_")) ic = POLICY_ITEM_SEND; else if (startswith(name, "receive_")) ic = POLICY_ITEM_RECV; else if (streq(name, "own")) ic = POLICY_ITEM_OWN; else if (streq(name, "own_prefix")) ic = POLICY_ITEM_OWN_PREFIX; else if (streq(name, "user")) ic = POLICY_ITEM_USER; else if (streq(name, "group")) ic = POLICY_ITEM_GROUP; else if (STR_IN_SET(name, "eavesdrop", "log")) { log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name, path, line); state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE; break; } else { log_error("Unknown attribute %s= at %s:%u, ignoring.", name, path, line); state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE; break; } if (i->class != _POLICY_ITEM_CLASS_UNSET && ic != i->class) { log_error("send_, receive_/eavesdrop fields mixed on same tag at %s:%u.", path, line); return -EINVAL; } i->class = ic; if (ic == POLICY_ITEM_SEND || ic == POLICY_ITEM_RECV) { const char *u; u = strchr(name, '_'); assert(u); u++; if (streq(u, "interface")) state = STATE_ALLOW_DENY_INTERFACE; else if (streq(u, "member")) state = STATE_ALLOW_DENY_MEMBER; else if (streq(u, "error")) state = STATE_ALLOW_DENY_ERROR; else if (streq(u, "path")) state = STATE_ALLOW_DENY_PATH; else if (streq(u, "type")) state = STATE_ALLOW_DENY_MESSAGE_TYPE; else if ((streq(u, "destination") && ic == POLICY_ITEM_SEND) || (streq(u, "sender") && ic == POLICY_ITEM_RECV)) state = STATE_ALLOW_DENY_NAME; else { if (streq(u, "requested_reply")) log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name, path, line); else log_error("Unknown attribute %s= at %s:%u, ignoring.", name, path, line); state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE; break; } } else state = STATE_ALLOW_DENY_NAME; } else if (t == XML_TAG_CLOSE_EMPTY || (t == XML_TAG_CLOSE && streq(name, i->type == POLICY_ITEM_ALLOW ? "allow" : "deny"))) { /* If the tag is fully empty so far, we consider it a recv */ if (i->class == _POLICY_ITEM_CLASS_UNSET) i->class = POLICY_ITEM_RECV; if (policy_category == POLICY_CATEGORY_DEFAULT) item_append(i, &p->default_items); else if (policy_category == POLICY_CATEGORY_MANDATORY) item_append(i, &p->mandatory_items); else if (policy_category == POLICY_CATEGORY_ON_CONSOLE) item_append(i, &p->on_console_items); else if (policy_category == POLICY_CATEGORY_NO_CONSOLE) item_append(i, &p->no_console_items); else if (policy_category == POLICY_CATEGORY_USER) { const char *u = policy_user; assert_cc(sizeof(uid_t) == sizeof(uint32_t)); r = hashmap_ensure_allocated(&p->user_items, NULL); if (r < 0) return log_oom(); if (!u) { log_error("User policy without name"); return -EINVAL; } r = get_user_creds(&u, &i->uid, NULL, NULL, NULL); if (r < 0) { log_error_errno(r, "Failed to resolve user %s, ignoring policy: %m", u); free(i); } else { PolicyItem *first; first = hashmap_get(p->user_items, UID_TO_PTR(i->uid)); item_append(i, &first); i->uid_valid = true; r = hashmap_replace(p->user_items, UID_TO_PTR(i->uid), first); if (r < 0) { LIST_REMOVE(items, first, i); return log_oom(); } } } else if (policy_category == POLICY_CATEGORY_GROUP) { const char *g = policy_group; assert_cc(sizeof(gid_t) == sizeof(uint32_t)); r = hashmap_ensure_allocated(&p->group_items, NULL); if (r < 0) return log_oom(); if (!g) { log_error("Group policy without name"); return -EINVAL; } r = get_group_creds(&g, &i->gid); if (r < 0) { log_error_errno(r, "Failed to resolve group %s, ignoring policy: %m", g); free(i); } else { PolicyItem *first; first = hashmap_get(p->group_items, GID_TO_PTR(i->gid)); item_append(i, &first); i->gid_valid = true; r = hashmap_replace(p->group_items, GID_TO_PTR(i->gid), first); if (r < 0) { LIST_REMOVE(items, first, i); return log_oom(); } } } state = STATE_POLICY; i = NULL; } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { log_error("Unexpected token (8) at %s:%u.", path, line); return -EINVAL; } break; case STATE_ALLOW_DENY_INTERFACE: if (t == XML_ATTRIBUTE_VALUE) { assert(i); if (i->interface) { log_error("Duplicate interface at %s:%u.", path, line); return -EINVAL; } if (!streq(name, "*")) { i->interface = name; name = NULL; } state = STATE_ALLOW_DENY; } else { log_error("Unexpected token (9) at %s:%u.", path, line); return -EINVAL; } break; case STATE_ALLOW_DENY_MEMBER: if (t == XML_ATTRIBUTE_VALUE) { assert(i); if (i->member) { log_error("Duplicate member in %s:%u.", path, line); return -EINVAL; } if (!streq(name, "*")) { i->member = name; name = NULL; } state = STATE_ALLOW_DENY; } else { log_error("Unexpected token (10) in %s:%u.", path, line); return -EINVAL; } break; case STATE_ALLOW_DENY_ERROR: if (t == XML_ATTRIBUTE_VALUE) { assert(i); if (i->error) { log_error("Duplicate error in %s:%u.", path, line); return -EINVAL; } if (!streq(name, "*")) { i->error = name; name = NULL; } state = STATE_ALLOW_DENY; } else { log_error("Unexpected token (11) in %s:%u.", path, line); return -EINVAL; } break; case STATE_ALLOW_DENY_PATH: if (t == XML_ATTRIBUTE_VALUE) { assert(i); if (i->path) { log_error("Duplicate path in %s:%u.", path, line); return -EINVAL; } if (!streq(name, "*")) { i->path = name; name = NULL; } state = STATE_ALLOW_DENY; } else { log_error("Unexpected token (12) in %s:%u.", path, line); return -EINVAL; } break; case STATE_ALLOW_DENY_MESSAGE_TYPE: if (t == XML_ATTRIBUTE_VALUE) { assert(i); if (i->message_type != 0) { log_error("Duplicate message type in %s:%u.", path, line); return -EINVAL; } if (!streq(name, "*")) { r = bus_message_type_from_string(name, &i->message_type); if (r < 0) { log_error("Invalid message type in %s:%u.", path, line); return -EINVAL; } } state = STATE_ALLOW_DENY; } else { log_error("Unexpected token (13) in %s:%u.", path, line); return -EINVAL; } break; case STATE_ALLOW_DENY_NAME: if (t == XML_ATTRIBUTE_VALUE) { assert(i); if (i->name) { log_error("Duplicate name in %s:%u.", path, line); return -EINVAL; } switch (i->class) { case POLICY_ITEM_USER: if (!streq(name, "*")) { const char *u = name; r = get_user_creds(&u, &i->uid, NULL, NULL, NULL); if (r < 0) log_error_errno(r, "Failed to resolve user %s: %m", name); else i->uid_valid = true; } break; case POLICY_ITEM_GROUP: if (!streq(name, "*")) { const char *g = name; r = get_group_creds(&g, &i->gid); if (r < 0) log_error_errno(r, "Failed to resolve group %s: %m", name); else i->gid_valid = true; } break; case POLICY_ITEM_SEND: case POLICY_ITEM_RECV: if (streq(name, "*")) name = mfree(name); break; default: break; } i->name = name; name = NULL; state = STATE_ALLOW_DENY; } else { log_error("Unexpected token (14) in %s:%u.", path, line); return -EINVAL; } break; case STATE_ALLOW_DENY_OTHER_ATTRIBUTE: if (t == XML_ATTRIBUTE_VALUE) state = STATE_ALLOW_DENY; else { log_error("Unexpected token (15) in %s:%u.", path, line); return -EINVAL; } break; case STATE_OTHER: if (t == XML_TAG_OPEN) n_other++; else if (t == XML_TAG_CLOSE || t == XML_TAG_CLOSE_EMPTY) { if (n_other == 0) state = STATE_BUSCONFIG; else n_other--; } break; } } } enum { DENY, ALLOW, DUNNO, }; static const char *verdict_to_string(int v) { switch (v) { case DENY: return "DENY"; case ALLOW: return "ALLOW"; case DUNNO: return "DUNNO"; } return NULL; } struct policy_check_filter { PolicyItemClass class; uid_t uid; gid_t gid; int message_type; const char *name; const char *interface; const char *path; const char *member; }; static int is_permissive(PolicyItem *i) { assert(i); return (i->type == POLICY_ITEM_ALLOW) ? ALLOW : DENY; } static int check_policy_item(PolicyItem *i, const struct policy_check_filter *filter) { assert(i); assert(filter); switch (i->class) { case POLICY_ITEM_SEND: case POLICY_ITEM_RECV: if (i->name && !streq_ptr(i->name, filter->name)) break; if ((i->message_type != 0) && (i->message_type != filter->message_type)) break; if (i->path && !streq_ptr(i->path, filter->path)) break; if (i->member && !streq_ptr(i->member, filter->member)) break; if (i->interface && !streq_ptr(i->interface, filter->interface)) break; return is_permissive(i); case POLICY_ITEM_OWN: assert(filter->name); if (streq(i->name, "*") || streq(i->name, filter->name)) return is_permissive(i); break; case POLICY_ITEM_OWN_PREFIX: assert(filter->name); if (streq(i->name, "*") || service_name_startswith(filter->name, i->name)) return is_permissive(i); break; case POLICY_ITEM_USER: if (filter->uid != UID_INVALID) if ((streq_ptr(i->name, "*") || (i->uid_valid && i->uid == filter->uid))) return is_permissive(i); break; case POLICY_ITEM_GROUP: if (filter->gid != GID_INVALID) if ((streq_ptr(i->name, "*") || (i->gid_valid && i->gid == filter->gid))) return is_permissive(i); break; case POLICY_ITEM_IGNORE: default: break; } return DUNNO; } static int check_policy_items(PolicyItem *items, const struct policy_check_filter *filter) { PolicyItem *i; int verdict = DUNNO; assert(filter); /* Check all policies in a set - a broader one might be followed by a more specific one, * and the order of rules in policy definitions matters */ LIST_FOREACH(items, i, items) { int v; if (i->class != filter->class && !(i->class == POLICY_ITEM_OWN_PREFIX && filter->class == POLICY_ITEM_OWN)) continue; v = check_policy_item(i, filter); if (v != DUNNO) verdict = v; } return verdict; } static int policy_check(Policy *p, const struct policy_check_filter *filter) { PolicyItem *items; int verdict, v; assert(p); assert(filter); assert(IN_SET(filter->class, POLICY_ITEM_SEND, POLICY_ITEM_RECV, POLICY_ITEM_OWN, POLICY_ITEM_USER, POLICY_ITEM_GROUP)); /* * The policy check is implemented by the following logic: * * 1. Check default items * 2. Check group items * 3. Check user items * 4. Check on/no_console items * 5. Check mandatory items * * Later rules override earlier rules. */ verdict = check_policy_items(p->default_items, filter); if (filter->gid != GID_INVALID) { items = hashmap_get(p->group_items, GID_TO_PTR(filter->gid)); if (items) { v = check_policy_items(items, filter); if (v != DUNNO) verdict = v; } } if (filter->uid != UID_INVALID) { items = hashmap_get(p->user_items, UID_TO_PTR(filter->uid)); if (items) { v = check_policy_items(items, filter); if (v != DUNNO) verdict = v; } } if (filter->uid != UID_INVALID && sd_uid_get_seats(filter->uid, -1, NULL) > 0) v = check_policy_items(p->on_console_items, filter); else v = check_policy_items(p->no_console_items, filter); if (v != DUNNO) verdict = v; v = check_policy_items(p->mandatory_items, filter); if (v != DUNNO) verdict = v; return verdict; } bool policy_check_own(Policy *p, uid_t uid, gid_t gid, const char *name) { struct policy_check_filter filter = { .class = POLICY_ITEM_OWN, .uid = uid, .gid = gid, .name = name, }; int verdict; assert(p); assert(name); verdict = policy_check(p, &filter); log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG), "Ownership permission check for uid=" UID_FMT " gid=" GID_FMT" name=%s: %s", uid, gid, strna(name), strna(verdict_to_string(verdict))); return verdict == ALLOW; } bool policy_check_hello(Policy *p, uid_t uid, gid_t gid) { struct policy_check_filter filter = { .uid = uid, .gid = gid, }; int verdict; assert(p); filter.class = POLICY_ITEM_USER; verdict = policy_check(p, &filter); if (verdict != DENY) { int v; filter.class = POLICY_ITEM_GROUP; v = policy_check(p, &filter); if (v != DUNNO) verdict = v; } log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG), "Hello permission check for uid=" UID_FMT " gid=" GID_FMT": %s", uid, gid, strna(verdict_to_string(verdict))); return verdict == ALLOW; } bool policy_check_one_recv(Policy *p, uid_t uid, gid_t gid, int message_type, const char *name, const char *path, const char *interface, const char *member) { struct policy_check_filter filter = { .class = POLICY_ITEM_RECV, .uid = uid, .gid = gid, .message_type = message_type, .name = name, .interface = interface, .path = path, .member = member, }; assert(p); return policy_check(p, &filter) == ALLOW; } bool policy_check_recv(Policy *p, uid_t uid, gid_t gid, int message_type, Set *names, char **namesv, const char *path, const char *interface, const char *member, bool dbus_to_kernel) { char *n, **nv, *last = NULL; bool allow = false; Iterator i; assert(p); if (set_isempty(names) && strv_isempty(namesv)) { allow = policy_check_one_recv(p, uid, gid, message_type, NULL, path, interface, member); } else { SET_FOREACH(n, names, i) { last = n; allow = policy_check_one_recv(p, uid, gid, message_type, n, path, interface, member); if (allow) break; } if (!allow) { STRV_FOREACH(nv, namesv) { last = *nv; allow = policy_check_one_recv(p, uid, gid, message_type, *nv, path, interface, member); if (allow) break; } } } log_full(LOG_AUTH | (!allow ? LOG_WARNING : LOG_DEBUG), "Receive permission check %s for uid=" UID_FMT " gid=" GID_FMT" message=%s name=%s path=%s interface=%s member=%s: %s", dbus_to_kernel ? "dbus-1 to kernel" : "kernel to dbus-1", uid, gid, bus_message_type_to_string(message_type), strna(last), strna(path), strna(interface), strna(member), allow ? "ALLOW" : "DENY"); return allow; } bool policy_check_one_send(Policy *p, uid_t uid, gid_t gid, int message_type, const char *name, const char *path, const char *interface, const char *member) { struct policy_check_filter filter = { .class = POLICY_ITEM_SEND, .uid = uid, .gid = gid, .message_type = message_type, .name = name, .interface = interface, .path = path, .member = member, }; assert(p); return policy_check(p, &filter) == ALLOW; } bool policy_check_send(Policy *p, uid_t uid, gid_t gid, int message_type, Set *names, char **namesv, const char *path, const char *interface, const char *member, bool dbus_to_kernel, char **out_used_name) { char *n, **nv, *last = NULL; bool allow = false; Iterator i; assert(p); if (set_isempty(names) && strv_isempty(namesv)) { allow = policy_check_one_send(p, uid, gid, message_type, NULL, path, interface, member); } else { SET_FOREACH(n, names, i) { last = n; allow = policy_check_one_send(p, uid, gid, message_type, n, path, interface, member); if (allow) break; } if (!allow) { STRV_FOREACH(nv, namesv) { last = *nv; allow = policy_check_one_send(p, uid, gid, message_type, *nv, path, interface, member); if (allow) break; } } } if (out_used_name) *out_used_name = last; log_full(LOG_AUTH | (!allow ? LOG_WARNING : LOG_DEBUG), "Send permission check %s for uid=" UID_FMT " gid=" GID_FMT" message=%s name=%s path=%s interface=%s member=%s: %s", dbus_to_kernel ? "dbus-1 to kernel" : "kernel to dbus-1", uid, gid, bus_message_type_to_string(message_type), strna(last), strna(path), strna(interface), strna(member), allow ? "ALLOW" : "DENY"); return allow; } int policy_load(Policy *p, char **files) { char **i; int r; assert(p); STRV_FOREACH(i, files) { r = file_load(p, *i); if (r == -EISDIR) { _cleanup_strv_free_ char **l = NULL; char **j; r = conf_files_list(&l, ".conf", NULL, *i, NULL); if (r < 0) return log_error_errno(r, "Failed to get configuration file list: %m"); STRV_FOREACH(j, l) file_load(p, *j); } /* We ignore all errors but EISDIR, and just proceed. */ } return 0; } void policy_free(Policy *p) { PolicyItem *i, *first; if (!p) return; while ((i = p->default_items)) { LIST_REMOVE(items, p->default_items, i); policy_item_free(i); } while ((i = p->mandatory_items)) { LIST_REMOVE(items, p->mandatory_items, i); policy_item_free(i); } while ((i = p->on_console_items)) { LIST_REMOVE(items, p->on_console_items, i); policy_item_free(i); } while ((i = p->no_console_items)) { LIST_REMOVE(items, p->no_console_items, i); policy_item_free(i); } while ((first = hashmap_steal_first(p->user_items))) { while ((i = first)) { LIST_REMOVE(items, first, i); policy_item_free(i); } } while ((first = hashmap_steal_first(p->group_items))) { while ((i = first)) { LIST_REMOVE(items, first, i); policy_item_free(i); } } hashmap_free(p->user_items); hashmap_free(p->group_items); p->user_items = p->group_items = NULL; } static void dump_items(PolicyItem *items, const char *prefix) { PolicyItem *i; if (!items) return; if (!prefix) prefix = ""; LIST_FOREACH(items, i, items) { printf("%sType: %s\n" "%sClass: %s\n", prefix, policy_item_type_to_string(i->type), prefix, policy_item_class_to_string(i->class)); if (i->interface) printf("%sInterface: %s\n", prefix, i->interface); if (i->member) printf("%sMember: %s\n", prefix, i->member); if (i->error) printf("%sError: %s\n", prefix, i->error); if (i->path) printf("%sPath: %s\n", prefix, i->path); if (i->name) printf("%sName: %s\n", prefix, i->name); if (i->message_type != 0) printf("%sMessage Type: %s\n", prefix, bus_message_type_to_string(i->message_type)); if (i->uid_valid) { _cleanup_free_ char *user; user = uid_to_name(i->uid); printf("%sUser: %s ("UID_FMT")\n", prefix, strna(user), i->uid); } if (i->gid_valid) { _cleanup_free_ char *group; group = gid_to_name(i->gid); printf("%sGroup: %s ("GID_FMT")\n", prefix, strna(group), i->gid); } printf("%s-\n", prefix); } } static void dump_hashmap_items(Hashmap *h) { PolicyItem *i; Iterator j; void *k; HASHMAP_FOREACH_KEY(i, k, h, j) { printf("\t%s Item for " UID_FMT ":\n", draw_special_char(DRAW_ARROW), PTR_TO_UID(k)); dump_items(i, "\t\t"); } } void policy_dump(Policy *p) { printf("%s Default Items:\n", draw_special_char(DRAW_ARROW)); dump_items(p->default_items, "\t"); printf("%s Group Items:\n", draw_special_char(DRAW_ARROW)); dump_hashmap_items(p->group_items); printf("%s User Items:\n", draw_special_char(DRAW_ARROW)); dump_hashmap_items(p->user_items); printf("%s On-Console Items:\n", draw_special_char(DRAW_ARROW)); dump_items(p->on_console_items, "\t"); printf("%s No-Console Items:\n", draw_special_char(DRAW_ARROW)); dump_items(p->no_console_items, "\t"); printf("%s Mandatory Items:\n", draw_special_char(DRAW_ARROW)); dump_items(p->mandatory_items, "\t"); fflush(stdout); } int shared_policy_new(SharedPolicy **out) { SharedPolicy *sp; int r; sp = new0(SharedPolicy, 1); if (!sp) return log_oom(); r = pthread_mutex_init(&sp->lock, NULL); if (r != 0) { r = log_error_errno(r, "Cannot initialize shared policy mutex: %m"); goto exit_free; } r = pthread_rwlock_init(&sp->rwlock, NULL); if (r != 0) { r = log_error_errno(r, "Cannot initialize shared policy rwlock: %m"); goto exit_mutex; } *out = sp; sp = NULL; return 0; /* pthread lock destruction is not fail-safe... meh! */ exit_mutex: pthread_mutex_destroy(&sp->lock); exit_free: free(sp); return r; } SharedPolicy *shared_policy_free(SharedPolicy *sp) { if (!sp) return NULL; policy_free(sp->policy); pthread_rwlock_destroy(&sp->rwlock); pthread_mutex_destroy(&sp->lock); strv_free(sp->configuration); free(sp); return NULL; } static int shared_policy_reload_unlocked(SharedPolicy *sp, char **configuration) { Policy old, buffer = {}; bool free_old; int r; assert(sp); r = policy_load(&buffer, configuration); if (r < 0) return log_error_errno(r, "Failed to load policy: %m"); log_debug("Reloading configuration"); /* policy_dump(&buffer); */ pthread_rwlock_wrlock(&sp->rwlock); memcpy(&old, &sp->buffer, sizeof(old)); memcpy(&sp->buffer, &buffer, sizeof(buffer)); free_old = !!sp->policy; sp->policy = &sp->buffer; pthread_rwlock_unlock(&sp->rwlock); if (free_old) policy_free(&old); return 0; } int shared_policy_reload(SharedPolicy *sp) { int r; assert(sp); pthread_mutex_lock(&sp->lock); r = shared_policy_reload_unlocked(sp, sp->configuration); pthread_mutex_unlock(&sp->lock); return r; } int shared_policy_preload(SharedPolicy *sp, char **configuration) { _cleanup_strv_free_ char **conf = NULL; int r = 0; assert(sp); conf = strv_copy(configuration); if (!conf) return log_oom(); pthread_mutex_lock(&sp->lock); if (!sp->policy) { r = shared_policy_reload_unlocked(sp, conf); if (r >= 0) { sp->configuration = conf; conf = NULL; } } pthread_mutex_unlock(&sp->lock); return r; } Policy *shared_policy_acquire(SharedPolicy *sp) { assert(sp); pthread_rwlock_rdlock(&sp->rwlock); if (sp->policy) return sp->policy; pthread_rwlock_unlock(&sp->rwlock); return NULL; } void shared_policy_release(SharedPolicy *sp, Policy *p) { assert(sp); assert(!p || sp->policy == p); if (p) pthread_rwlock_unlock(&sp->rwlock); } static const char* const policy_item_type_table[_POLICY_ITEM_TYPE_MAX] = { [_POLICY_ITEM_TYPE_UNSET] = "unset", [POLICY_ITEM_ALLOW] = "allow", [POLICY_ITEM_DENY] = "deny", }; DEFINE_STRING_TABLE_LOOKUP(policy_item_type, PolicyItemType); static const char* const policy_item_class_table[_POLICY_ITEM_CLASS_MAX] = { [_POLICY_ITEM_CLASS_UNSET] = "unset", [POLICY_ITEM_SEND] = "send", [POLICY_ITEM_RECV] = "recv", [POLICY_ITEM_OWN] = "own", [POLICY_ITEM_OWN_PREFIX] = "own-prefix", [POLICY_ITEM_USER] = "user", [POLICY_ITEM_GROUP] = "group", [POLICY_ITEM_IGNORE] = "ignore", }; DEFINE_STRING_TABLE_LOOKUP(policy_item_class, PolicyItemClass); systemd-229/src/bus-proxyd/bus-xml-policy.h000066400000000000000000000110471265713322000210240ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "hashmap.h" #include "list.h" typedef enum PolicyItemType { _POLICY_ITEM_TYPE_UNSET = 0, POLICY_ITEM_ALLOW, POLICY_ITEM_DENY, _POLICY_ITEM_TYPE_MAX, _POLICY_ITEM_TYPE_INVALID = -1, } PolicyItemType; typedef enum PolicyItemClass { _POLICY_ITEM_CLASS_UNSET = 0, POLICY_ITEM_SEND, POLICY_ITEM_RECV, POLICY_ITEM_OWN, POLICY_ITEM_OWN_PREFIX, POLICY_ITEM_USER, POLICY_ITEM_GROUP, POLICY_ITEM_IGNORE, _POLICY_ITEM_CLASS_MAX, _POLICY_ITEM_CLASS_INVALID = -1, } PolicyItemClass; typedef struct PolicyItem PolicyItem; struct PolicyItem { PolicyItemType type; PolicyItemClass class; char *interface; char *member; char *error; char *path; char *name; uint8_t message_type; uid_t uid; gid_t gid; bool uid_valid, gid_valid; LIST_FIELDS(PolicyItem, items); }; typedef struct Policy { LIST_HEAD(PolicyItem, default_items); LIST_HEAD(PolicyItem, mandatory_items); LIST_HEAD(PolicyItem, on_console_items); LIST_HEAD(PolicyItem, no_console_items); Hashmap *user_items; Hashmap *group_items; } Policy; typedef struct SharedPolicy { char **configuration; pthread_mutex_t lock; pthread_rwlock_t rwlock; Policy buffer; Policy *policy; } SharedPolicy; /* policy */ int policy_load(Policy *p, char **files); void policy_free(Policy *p); bool policy_check_own(Policy *p, uid_t uid, gid_t gid, const char *name); bool policy_check_hello(Policy *p, uid_t uid, gid_t gid); bool policy_check_one_recv(Policy *p, uid_t uid, gid_t gid, int message_type, const char *name, const char *path, const char *interface, const char *member); bool policy_check_recv(Policy *p, uid_t uid, gid_t gid, int message_type, Set *names, char **namesv, const char *path, const char *interface, const char *member, bool dbus_to_kernel); bool policy_check_one_send(Policy *p, uid_t uid, gid_t gid, int message_type, const char *name, const char *path, const char *interface, const char *member); bool policy_check_send(Policy *p, uid_t uid, gid_t gid, int message_type, Set *names, char **namesv, const char *path, const char *interface, const char *member, bool dbus_to_kernel, char **out_used_name); void policy_dump(Policy *p); const char* policy_item_type_to_string(PolicyItemType t) _const_; PolicyItemType policy_item_type_from_string(const char *s) _pure_; const char* policy_item_class_to_string(PolicyItemClass t) _const_; PolicyItemClass policy_item_class_from_string(const char *s) _pure_; /* shared policy */ int shared_policy_new(SharedPolicy **out); SharedPolicy *shared_policy_free(SharedPolicy *sp); int shared_policy_reload(SharedPolicy *sp); int shared_policy_preload(SharedPolicy *sp, char **configuration); Policy *shared_policy_acquire(SharedPolicy *sp); void shared_policy_release(SharedPolicy *sp, Policy *p); DEFINE_TRIVIAL_CLEANUP_FUNC(SharedPolicy*, shared_policy_free); systemd-229/src/bus-proxyd/driver.c000066400000000000000000001032531265713322000174270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Daniel Mack Copyright 2014 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-util.h" #include "driver.h" #include "env-util.h" #include "proxy.h" #include "set.h" #include "strv.h" #include "synthesize.h" #include "util.h" static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; int r; assert(bus); assert(name); assert(_creds); r = sd_bus_get_name_creds(bus, name, mask, &c); if (r == -ESRCH || r == -ENXIO) return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name); if (r < 0) return r; *_creds = c; c = NULL; return 0; } static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) { const char *name; int r; assert(bus); assert(m); assert(_creds); r = sd_bus_message_read(m, "s", &name); if (r < 0) return r; return get_creds_by_name(bus, name, mask, _creds, error); } static int driver_activation(sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; ProxyActivation *activation = userdata; /* * The org.freedesktop.DBus.Peer.Ping() call returned. We don't care * whether this succeeded, failed, was not implemented or timed out. We * cannot assume that the target reacts to this properly. Hence, just * send the reply to the activation request and be done. */ m = activation->request; /* claim reference */ --activation->proxy->n_activations; LIST_REMOVE(activations_by_proxy, activation->proxy->activations, activation); sd_bus_slot_unref(activation->slot); free(activation); return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS); } int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names) { int r; assert(a); assert(b); assert(m); if (!a->is_kernel) return 0; if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus")) return 0; /* The "Hello()" call is is handled in process_hello() */ if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) { if (!sd_bus_message_has_signature(m, "")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); return synthetic_reply_method_return(m, "s", "\n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n"); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) { const char *match; if (!sd_bus_message_has_signature(m, "s")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = sd_bus_message_read(m, "s", &match); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_add_match(a, NULL, match, proxy_match, p); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); return synthetic_reply_method_return(m, NULL); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) { const char *match; if (!sd_bus_message_has_signature(m, "s")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = sd_bus_message_read(m, "s", &match); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = bus_remove_match_by_string(a, match, NULL, NULL); if (r == 0) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found")); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); return synthetic_reply_method_return(m, NULL); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionCredentials")) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; if (!sd_bus_message_has_signature(m, "s")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = get_creds_by_message(a, m, SD_BUS_CREDS_PID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error); if (r < 0) return synthetic_reply_method_errno(m, r, &error); r = sd_bus_message_new_method_return(m, &reply); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_message_open_container(reply, 'a', "{sv}"); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); /* Due to i.e. namespace translations some data might be missing */ if (creds->mask & SD_BUS_CREDS_PID) { r = sd_bus_message_append(reply, "{sv}", "ProcessID", "u", (uint32_t) creds->pid); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); } if (creds->mask & SD_BUS_CREDS_EUID) { r = sd_bus_message_append(reply, "{sv}", "UnixUserID", "u", (uint32_t) creds->euid); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); } if (creds->mask & SD_BUS_CREDS_SELINUX_CONTEXT) { r = sd_bus_message_open_container(reply, 'e', "sv"); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_message_append(reply, "s", "LinuxSecurityLabel"); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_message_open_container(reply, 'v', "ay"); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_message_append_array(reply, 'y', creds->label, strlen(creds->label)); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_message_close_container(reply); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_message_close_container(reply); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); } r = sd_bus_message_close_container(reply); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); return synthetic_driver_send(m->bus, reply); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; if (!sd_bus_message_has_signature(m, "s")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error); if (r < 0) return synthetic_reply_method_errno(m, r, &error); if (!(creds->mask & SD_BUS_CREDS_SELINUX_CONTEXT)) return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL); r = sd_bus_message_new_method_return(m, &reply); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_message_append_array(reply, 'y', creds->label, strlen(creds->label)); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); return synthetic_driver_send(m->bus, reply); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; if (!sd_bus_message_has_signature(m, "s")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error); if (r < 0) return synthetic_reply_method_errno(m, r, &error); if (!(creds->mask & SD_BUS_CREDS_PID)) return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL); return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; if (!sd_bus_message_has_signature(m, "s")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = get_creds_by_message(a, m, SD_BUS_CREDS_EUID, &creds, &error); if (r < 0) return synthetic_reply_method_errno(m, r, &error); if (!(creds->mask & SD_BUS_CREDS_EUID)) return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL); return synthetic_reply_method_return(m, "u", (uint32_t) creds->euid); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) { sd_id128_t server_id; char buf[SD_ID128_STRING_MAX]; if (!sd_bus_message_has_signature(m, "")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = sd_bus_get_bus_id(a, &server_id); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf)); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) { const char *name; _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; if (!sd_bus_message_has_signature(m, "s")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = sd_bus_message_read(m, "s", &name); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); if (streq(name, "org.freedesktop.DBus")) return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus"); r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error); if (r < 0) return synthetic_reply_method_errno(m, r, &error); if (!(creds->mask & SD_BUS_CREDS_UNIQUE_NAME)) return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL); return synthetic_reply_method_return(m, "s", creds->unique_name); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) { _cleanup_strv_free_ char **names = NULL; if (!sd_bus_message_has_signature(m, "")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = sd_bus_list_names(a, NULL, &names); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); /* Let's sort the names list to make it stable */ strv_sort(names); return synthetic_reply_method_return_strv(m, names); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) { _cleanup_strv_free_ char **names = NULL; if (!sd_bus_message_has_signature(m, "")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = sd_bus_list_names(a, &names, NULL); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = strv_extend(&names, "org.freedesktop.DBus"); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); /* Let's sort the names list to make it stable */ strv_sort(names); return synthetic_reply_method_return_strv(m, names); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) { struct kdbus_cmd_list cmd = { .flags = KDBUS_LIST_QUEUED, .size = sizeof(cmd), }; struct kdbus_info *name_list, *name; _cleanup_strv_free_ char **owners = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *arg0; int err = 0; if (!sd_bus_message_has_signature(m, "s")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = sd_bus_message_read(m, "s", &arg0); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_get_name_creds(a, arg0, 0, NULL); if (r == -ESRCH || r == -ENXIO) { sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0); return synthetic_reply_method_errno(m, r, &error); } if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = ioctl(a->input_fd, KDBUS_CMD_LIST, &cmd); if (r < 0) return synthetic_reply_method_errno(m, -errno, NULL); name_list = (struct kdbus_info *) ((uint8_t *) a->kdbus_buffer + cmd.offset); KDBUS_FOREACH(name, name_list, cmd.list_size) { struct kdbus_item *item; char *n; KDBUS_ITEM_FOREACH(item, name, items) { if (item->type == KDBUS_ITEM_OWNED_NAME) { if (!streq_ptr(item->name.name, arg0)) continue; if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) { err = -ENOMEM; break; } r = strv_consume(&owners, n); if (r < 0) { err = r; break; } } } if (err < 0) break; } r = bus_kernel_cmd_free(a, cmd.offset); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); if (err < 0) return synthetic_reply_method_errno(m, err, NULL); return synthetic_reply_method_return_strv(m, owners); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) { const char *name; if (!sd_bus_message_has_signature(m, "s")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = sd_bus_message_read(m, "s", &name); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); if (streq(name, "org.freedesktop.DBus")) return synthetic_reply_method_return(m, "b", true); r = sd_bus_get_name_creds(a, name, 0, NULL); if (r < 0 && r != -ESRCH && r != -ENXIO) return synthetic_reply_method_errno(m, r, NULL); return synthetic_reply_method_return(m, "b", r >= 0); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) { const char *name; if (!sd_bus_message_has_signature(m, "s")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = sd_bus_message_read(m, "s", &name); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_release_name(a, name); if (r < 0) { if (r == -ESRCH) return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT); if (r == -EADDRINUSE) return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER); return synthetic_reply_method_errno(m, r, NULL); } set_remove(owned_names, (char*) name); return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) { if (!sd_bus_message_has_signature(m, "")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = shared_policy_reload(sp); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); return synthetic_reply_method_return(m, NULL); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) { const char *name; uint32_t flags, param; bool in_queue; if (!sd_bus_message_has_signature(m, "su")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = sd_bus_message_read(m, "su", &name, &flags); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); if (sp) { Policy *policy; bool denied; policy = shared_policy_acquire(sp); denied = !policy_check_own(policy, ucred->uid, ucred->gid, name); shared_policy_release(sp, policy); if (denied) return synthetic_reply_method_errno(m, -EPERM, NULL); } if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0) return synthetic_reply_method_errno(m, -EINVAL, NULL); param = 0; if (flags & BUS_NAME_ALLOW_REPLACEMENT) param |= SD_BUS_NAME_ALLOW_REPLACEMENT; if (flags & BUS_NAME_REPLACE_EXISTING) param |= SD_BUS_NAME_REPLACE_EXISTING; if (!(flags & BUS_NAME_DO_NOT_QUEUE)) param |= SD_BUS_NAME_QUEUE; r = set_put_strdup(owned_names, name); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_request_name(a, name, param); if (r < 0) { if (r == -EALREADY) return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER); set_remove(owned_names, (char*) name); if (r == -EEXIST) return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS); return synthetic_reply_method_errno(m, r, NULL); } in_queue = (r == 0); if (in_queue) return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE); return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *msg = NULL; ProxyActivation *activation; const char *name; uint64_t cookie; uint32_t flags; if (!sd_bus_message_has_signature(m, "su")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = sd_bus_message_read(m, "su", &name, &flags); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); if (flags != 0) return synthetic_reply_method_errno(m, -EINVAL, NULL); r = sd_bus_get_name_creds(a, name, 0, NULL); if (r >= 0 || streq(name, "org.freedesktop.DBus")) return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING); if (r != -ESRCH) return synthetic_reply_method_errno(m, r, NULL); if (p->n_activations >= PROXY_ACTIVATIONS_MAX) return synthetic_reply_method_errno(m, -EMFILE, NULL); r = sd_bus_message_get_cookie(m, &cookie); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_message_new_method_call(a, &msg, name, "/", "org.freedesktop.DBus.Peer", "Ping"); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = bus_message_seal(msg, cookie, BUS_DEFAULT_TIMEOUT); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); activation = new0(ProxyActivation, 1); if (!activation) return synthetic_reply_method_errno(m, -ENOMEM, NULL); r = sd_bus_call_async(a, &activation->slot, msg, driver_activation, activation, 0); if (r < 0) { free(activation); return synthetic_reply_method_errno(m, r, NULL); } activation->proxy = p; activation->request = sd_bus_message_ref(m); LIST_PREPEND(activations_by_proxy, p->activations, activation); ++p->n_activations; return 1; } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *msg = NULL; _cleanup_strv_free_ char **args = NULL; if (!sd_bus_message_has_signature(m, "a{ss}")) return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters")); r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}"); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) { _cleanup_free_ char *s = NULL; const char *key; const char *value; r = sd_bus_message_read(m, "ss", &key, &value); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); s = strjoin(key, "=", value, NULL); if (!s) return synthetic_reply_method_errno(m, -ENOMEM, NULL); if (!env_assignment_is_valid(s)) { log_warning("UpdateActivationEnvironment() called with invalid assignment, discarding: %s", s); } else { r = strv_extend(&args, s); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); } r = sd_bus_message_exit_container(m); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); } r = sd_bus_message_exit_container(m); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); if (strv_isempty(args)) /* nothing to do? */ return synthetic_reply_method_return(m, NULL); r = sd_bus_message_new_method_call( a, &msg, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "SetEnvironment"); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_message_append_strv(msg, args); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); r = sd_bus_call(a, msg, 0, NULL, NULL); if (r < 0) return synthetic_reply_method_errno(m, r, NULL); return synthetic_reply_method_return(m, NULL); } else { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member); return synthetic_reply_method_errno(m, r, &error); } } systemd-229/src/bus-proxyd/driver.h000066400000000000000000000016621265713322000174350ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "bus-xml-policy.h" #include "proxy.h" int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names); systemd-229/src/bus-proxyd/proxy.c000066400000000000000000001070761265713322000173240ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Daniel Mack Copyright 2014 Kay Sievers Copyright 2014 David Herrmann systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-bus.h" #include "sd-daemon.h" #include "alloc-util.h" #include "bus-control.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-util.h" #include "bus-xml-policy.h" #include "driver.h" #include "fd-util.h" #include "formats-util.h" #include "log.h" #include "proxy.h" #include "set.h" #include "strv.h" #include "synthesize.h" #include "user-util.h" #include "util.h" static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *b = NULL; int r; r = sd_bus_new(&b); if (r < 0) return log_error_errno(r, "Failed to allocate bus: %m"); r = sd_bus_set_description(b, "sd-proxy"); if (r < 0) return log_error_errno(r, "Failed to set bus name: %m"); r = sd_bus_set_address(b, destination); if (r < 0) return log_error_errno(r, "Failed to set address to connect to: %m"); r = sd_bus_negotiate_fds(b, negotiate_fds); if (r < 0) return log_error_errno(r, "Failed to set FD negotiation: %m"); r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT); if (r < 0) return log_error_errno(r, "Failed to set credential negotiation: %m"); if (p->local_creds.pid > 0) { b->fake_pids.pid = p->local_creds.pid; b->fake_pids_valid = true; b->fake_creds.uid = UID_INVALID; b->fake_creds.euid = p->local_creds.uid; b->fake_creds.suid = UID_INVALID; b->fake_creds.fsuid = UID_INVALID; b->fake_creds.gid = GID_INVALID; b->fake_creds.egid = p->local_creds.gid; b->fake_creds.sgid = GID_INVALID; b->fake_creds.fsgid = GID_INVALID; b->fake_creds_valid = true; } if (local_sec) { b->fake_label = strdup(local_sec); if (!b->fake_label) return log_oom(); } b->manual_peer_interface = true; r = sd_bus_start(b); if (r < 0) return log_error_errno(r, "Failed to start bus client: %m"); p->destination_bus = b; b = NULL; return 0; } static int proxy_create_local(Proxy *p, bool negotiate_fds) { sd_id128_t server_id; sd_bus *b; int r; r = sd_bus_new(&b); if (r < 0) return log_error_errno(r, "Failed to allocate bus: %m"); r = sd_bus_set_fd(b, p->local_in, p->local_out); if (r < 0) { sd_bus_unref(b); return log_error_errno(r, "Failed to set fds: %m"); } /* The fds are now owned by the bus, and we indicate that by * storing the bus object in the proxy object. */ p->local_bus = b; r = sd_bus_get_bus_id(p->destination_bus, &server_id); if (r < 0) return log_error_errno(r, "Failed to get server ID: %m"); r = sd_bus_set_server(b, 1, server_id); if (r < 0) return log_error_errno(r, "Failed to set server mode: %m"); r = sd_bus_negotiate_fds(b, negotiate_fds); if (r < 0) return log_error_errno(r, "Failed to set FD negotiation: %m"); r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT); if (r < 0) return log_error_errno(r, "Failed to set credential negotiation: %m"); r = sd_bus_set_anonymous(b, true); if (r < 0) return log_error_errno(r, "Failed to set anonymous authentication: %m"); b->manual_peer_interface = true; r = sd_bus_start(b); if (r < 0) return log_error_errno(r, "Failed to start bus client: %m"); return 0; } static int proxy_match_synthetic(sd_bus_message *m, void *userdata, sd_bus_error *error) { Proxy *p = userdata; p->synthetic_matched = true; return 0; /* make sure to continue processing it in further handlers */ } /* * We always need NameOwnerChanged so we can synthesize NameLost and * NameAcquired. Furthermore, dbus-1 always passes unicast-signals through, so * subscribe unconditionally. */ static int proxy_prepare_matches(Proxy *p) { _cleanup_free_ char *match = NULL; const char *unique; int r; if (!p->destination_bus->is_kernel) return 0; r = sd_bus_get_unique_name(p->destination_bus, &unique); if (r < 0) return log_error_errno(r, "Failed to get unique name: %m"); match = strjoin("type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'," "arg1='", unique, "'", NULL); if (!match) return log_oom(); r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p); if (r < 0) return log_error_errno(r, "Failed to add match for NameLost: %m"); free(match); match = strjoin("type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'," "arg2='", unique, "'", NULL); if (!match) return log_oom(); r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p); if (r < 0) return log_error_errno(r, "Failed to add match for NameAcquired: %m"); free(match); match = strjoin("type='signal'," "destination='", unique, "'", NULL); if (!match) return log_oom(); r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p); if (r < 0) log_error_errno(r, "Failed to add match for directed signals: %m"); /* FIXME: temporarily ignore error to support older kdbus versions */ return 0; } int proxy_new(Proxy **out, int in_fd, int out_fd, const char *destination) { _cleanup_(proxy_freep) Proxy *p = NULL; _cleanup_free_ char *local_sec = NULL; bool is_unix; int r; /* This takes possession/destroys the file descriptors passed * in even on failure. The caller should hence forget about * the fds in all cases after calling this function and not * close them. */ p = new0(Proxy, 1); if (!p) { safe_close(in_fd); safe_close(out_fd); return log_oom(); } p->local_in = in_fd; p->local_out = out_fd; p->owned_names = set_new(&string_hash_ops); if (!p->owned_names) return log_oom(); is_unix = sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 && sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0; if (is_unix) { (void) getpeercred(in_fd, &p->local_creds); (void) getpeersec(in_fd, &local_sec); } r = proxy_create_destination(p, destination, local_sec, is_unix); if (r < 0) return r; r = proxy_create_local(p, is_unix); if (r < 0) return r; r = proxy_prepare_matches(p); if (r < 0) return r; *out = p; p = NULL; return 0; } Proxy *proxy_free(Proxy *p) { ProxyActivation *activation; if (!p) return NULL; while ((activation = p->activations)) { LIST_REMOVE(activations_by_proxy, p->activations, activation); sd_bus_message_unref(activation->request); sd_bus_slot_unref(activation->slot); free(activation); } if (p->local_bus) sd_bus_flush_close_unref(p->local_bus); else { safe_close(p->local_in); if (p->local_out != p->local_in) safe_close(p->local_out); } sd_bus_flush_close_unref(p->destination_bus); set_free_free(p->owned_names); free(p); return NULL; } int proxy_set_policy(Proxy *p, SharedPolicy *sp, char **configuration) { _cleanup_strv_free_ char **strv = NULL; Policy *policy; int r; assert(p); assert(sp); /* no need to load legacy policy if destination is not kdbus */ if (!p->destination_bus->is_kernel) return 0; p->policy = sp; policy = shared_policy_acquire(sp); if (policy) { /* policy already pre-loaded */ shared_policy_release(sp, policy); return 0; } if (!configuration) { const char *scope; r = sd_bus_get_scope(p->destination_bus, &scope); if (r < 0) return log_error_errno(r, "Couldn't determine bus scope: %m"); if (streq(scope, "system")) strv = strv_new("/usr/share/dbus-1/system.conf", "/etc/dbus-1/system.conf", "/usr/share/dbus-1/system.d/", "/etc/dbus-1/system.d/", "/etc/dbus-1/system-local.conf", NULL); else if (streq(scope, "user")) strv = strv_new("/usr/share/dbus-1/session.conf", "/etc/dbus-1/session.conf", "/usr/share/dbus-1/session.d/", "/etc/dbus-1/session.d/", "/etc/dbus-1/session-local.conf", NULL); else return log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope); if (!strv) return log_oom(); configuration = strv; } return shared_policy_preload(sp, configuration); } int proxy_hello_policy(Proxy *p, uid_t original_uid) { Policy *policy; int r = 0; assert(p); if (!p->policy) return 0; policy = shared_policy_acquire(p->policy); if (p->local_creds.uid == original_uid) log_debug("Permitting access, since bus owner matches bus client."); else if (policy_check_hello(policy, p->local_creds.uid, p->local_creds.gid)) log_debug("Permitting access due to XML policy."); else r = log_error_errno(EPERM, "Policy denied connection."); shared_policy_release(p->policy, policy); return r; } static int proxy_wait(Proxy *p) { uint64_t timeout_destination, timeout_local, t; int events_destination, events_local, fd; struct timespec _ts, *ts; struct pollfd *pollfd; int r; assert(p); fd = sd_bus_get_fd(p->destination_bus); if (fd < 0) return log_error_errno(fd, "Failed to get fd: %m"); events_destination = sd_bus_get_events(p->destination_bus); if (events_destination < 0) return log_error_errno(events_destination, "Failed to get events mask: %m"); r = sd_bus_get_timeout(p->destination_bus, &timeout_destination); if (r < 0) return log_error_errno(r, "Failed to get timeout: %m"); events_local = sd_bus_get_events(p->local_bus); if (events_local < 0) return log_error_errno(events_local, "Failed to get events mask: %m"); r = sd_bus_get_timeout(p->local_bus, &timeout_local); if (r < 0) return log_error_errno(r, "Failed to get timeout: %m"); t = timeout_destination; if (t == (uint64_t) -1 || (timeout_local != (uint64_t) -1 && timeout_local < timeout_destination)) t = timeout_local; if (t == (uint64_t) -1) ts = NULL; else { usec_t nw; nw = now(CLOCK_MONOTONIC); if (t > nw) t -= nw; else t = 0; ts = timespec_store(&_ts, t); } pollfd = (struct pollfd[3]) { { .fd = fd, .events = events_destination, }, { .fd = p->local_in, .events = events_local & POLLIN, }, { .fd = p->local_out, .events = events_local & POLLOUT, }, }; r = ppoll(pollfd, 3, ts, NULL); if (r < 0) return log_error_errno(errno, "ppoll() failed: %m"); return 0; } static int handle_policy_error(sd_bus_message *m, int r) { if (r == -ESRCH || r == -ENXIO) return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination); return r; } static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) { int r; assert(from); assert(to); assert(m); if (!policy) return 0; /* * dbus-1 distinguishes expected and non-expected replies by tracking * method-calls and timeouts. By default, DENY rules are *NEVER* applied * on expected replies, unless explicitly specified. But we dont track * method-calls, thus, we cannot know whether a reply is expected. * Fortunately, the kdbus forbids non-expected replies, so we can safely * ignore any policy on those and let the kernel deal with it. * * TODO: To be correct, we should only ignore policy-tags that are * applied on non-expected replies. However, so far we don't parse those * tags so we let everything pass. I haven't seen a DENY policy tag on * expected-replies, ever, so don't bother.. */ if (m->reply_cookie > 0) return 0; if (from->is_kernel) { uid_t sender_uid = UID_INVALID; gid_t sender_gid = GID_INVALID; char **sender_names = NULL; /* Driver messages are always OK */ if (streq_ptr(m->sender, "org.freedesktop.DBus")) return 0; /* The message came from the kernel, and is sent to our legacy client. */ (void) sd_bus_creds_get_well_known_names(&m->creds, &sender_names); (void) sd_bus_creds_get_euid(&m->creds, &sender_uid); (void) sd_bus_creds_get_egid(&m->creds, &sender_gid); if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *sender_creds = NULL; /* If the message came from another legacy * client, then the message creds will be * missing, simply because on legacy clients * per-message creds were unknown. In this * case, query the creds of the peer * instead. */ r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID, true, &sender_creds); if (r < 0) return handle_policy_error(m, r); (void) sd_bus_creds_get_euid(sender_creds, &sender_uid); (void) sd_bus_creds_get_egid(sender_creds, &sender_gid); } /* First check whether the sender can send the message to our name */ if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, false, NULL) && policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, sender_names, m->path, m->interface, m->member, false)) return 0; /* Return an error back to the caller */ if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy."); /* Return 1, indicating that the message shall not be processed any further */ return 1; } if (to->is_kernel) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *destination_creds = NULL; uid_t destination_uid = UID_INVALID; gid_t destination_gid = GID_INVALID; const char *destination_unique = NULL; char **destination_names = NULL; char *n; /* Driver messages are always OK */ if (streq_ptr(m->destination, "org.freedesktop.DBus")) return 0; /* The message came from the legacy client, and is sent to kdbus. */ if (m->destination) { r = bus_get_name_creds_kdbus(to, m->destination, SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME| SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID, true, &destination_creds); if (r < 0) return handle_policy_error(m, r); r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique); if (r < 0) return handle_policy_error(m, r); (void) sd_bus_creds_get_well_known_names(destination_creds, &destination_names); (void) sd_bus_creds_get_euid(destination_creds, &destination_uid); (void) sd_bus_creds_get_egid(destination_creds, &destination_gid); } /* First check if we (the sender) can send to this name */ if (sd_bus_message_is_signal(m, NULL, NULL)) { /* If we forward a signal from dbus-1 to kdbus, we have * no idea who the recipient is. Therefore, we cannot * apply any dbus-1 policies that match on receiver * credentials. We know sd-bus always sets * KDBUS_MSG_SIGNAL, so the kernel applies policies to * the message. Therefore, skip policy checks in this * case. */ return 0; } else if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, destination_names, m->path, m->interface, m->member, true, &n)) { if (n) { /* If we made a receiver decision, then remember which * name's policy we used, and to which unique ID it * mapped when we made the decision. Then, let's pass * this to the kernel when sending the message, so that * it refuses the operation should the name and unique * ID not map to each other anymore. */ r = free_and_strdup(&m->destination_ptr, n); if (r < 0) return r; r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id); if (r < 0) return r; } if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true)) return 0; } /* Return an error back to the caller */ if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy."); /* Return 1, indicating that the message shall not be processed any further */ return 1; } return 0; } static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, SharedPolicy *sp, const struct ucred *our_ucred, Set *owned_names) { Policy *policy; int r; assert(sp); policy = shared_policy_acquire(sp); r = process_policy_unlocked(from, to, m, policy, our_ucred, owned_names); shared_policy_release(sp, policy); return r; } static int process_hello(Proxy *p, sd_bus_message *m) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL; bool is_hello; int r; assert(p); assert(m); /* As reaction to hello we need to respond with two messages: * the callback reply and the NameAcquired for the unique * name, since hello is otherwise obsolete on kdbus. */ is_hello = sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") && streq_ptr(m->destination, "org.freedesktop.DBus"); if (!is_hello) { if (p->got_hello) return 0; return log_error_errno(EIO, "First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member); } if (p->got_hello) return log_error_errno(EIO, "Got duplicate hello, aborting."); p->got_hello = true; if (!p->destination_bus->is_kernel) return 0; r = sd_bus_message_new_method_return(m, &n); if (r < 0) return log_error_errno(r, "Failed to generate HELLO reply: %m"); r = sd_bus_message_append(n, "s", p->destination_bus->unique_name); if (r < 0) return log_error_errno(r, "Failed to append unique name to HELLO reply: %m"); r = bus_message_append_sender(n, "org.freedesktop.DBus"); if (r < 0) return log_error_errno(r, "Failed to append sender to HELLO reply: %m"); r = bus_seal_synthetic_message(p->local_bus, n); if (r < 0) return log_error_errno(r, "Failed to seal HELLO reply: %m"); r = sd_bus_send(p->local_bus, n, NULL); if (r < 0) return log_error_errno(r, "Failed to send HELLO reply: %m"); n = sd_bus_message_unref(n); r = sd_bus_message_new_signal( p->local_bus, &n, "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameAcquired"); if (r < 0) return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m"); r = sd_bus_message_append(n, "s", p->destination_bus->unique_name); if (r < 0) return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m"); r = bus_message_append_sender(n, "org.freedesktop.DBus"); if (r < 0) return log_error_errno(r, "Failed to append sender to NameAcquired message: %m"); r = sd_bus_message_set_destination(n, p->destination_bus->unique_name); if (r < 0) return log_error_errno(r, "Failed to set destination for NameAcquired message: %m"); r = bus_seal_synthetic_message(p->local_bus, n); if (r < 0) return log_error_errno(r, "Failed to seal NameAcquired message: %m"); r = sd_bus_send(p->local_bus, n, NULL); if (r < 0) return log_error_errno(r, "Failed to send NameAcquired message: %m"); return 1; } static int patch_sender(sd_bus *a, sd_bus_message *m) { char **well_known = NULL; sd_bus_creds *c; int r; assert(a); assert(m); if (!a->is_kernel) return 0; /* We will change the sender of messages from the bus driver * so that they originate from the bus driver. This is a * speciality originating from dbus1, where the bus driver did * not have a unique id, but only the well-known name. */ c = sd_bus_message_get_creds(m); if (!c) return 0; r = sd_bus_creds_get_well_known_names(c, &well_known); if (r < 0) return r; if (strv_contains(well_known, "org.freedesktop.DBus")) m->sender = "org.freedesktop.DBus"; return 0; } static int proxy_process_destination_to_local(Proxy *p) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; bool matched, matched_synthetic; int r; assert(p); /* * Usually, we would just take any message that the bus passes to us * and forward it to the local connection. However, there are actually * applications that fail if they receive broadcasts that they didn't * subscribe to. Therefore, we actually emulate a real broadcast * matching here, and discard any broadcasts that weren't matched. Our * match-handlers remembers whether a message was matched by any rule, * by marking it in @p->message_matched. */ r = sd_bus_process(p->destination_bus, &m); matched = p->message_matched; matched_synthetic = p->synthetic_matched; p->message_matched = false; p->synthetic_matched = false; if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */ return r; if (r < 0) { log_error_errno(r, "Failed to process destination bus: %m"); return r; } if (r == 0) return 0; if (!m) return 1; /* We officially got EOF, let's quit */ if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) return -ECONNRESET; r = synthesize_name_acquired(p, p->destination_bus, p->local_bus, m); if (r == -ECONNRESET || r == -ENOTCONN) return r; if (r < 0) return log_error_errno(r, "Failed to synthesize message: %m"); /* discard broadcasts that were not matched by any MATCH rule */ if (!matched && !sd_bus_message_get_destination(m)) { if (!matched_synthetic) log_debug("Dropped unmatched broadcast: uid=" UID_FMT " gid=" GID_FMT " pid=" PID_FMT " message=%s path=%s interface=%s member=%s sender=%s destination=%s", p->local_creds.uid, p->local_creds.gid, p->local_creds.pid, bus_message_type_to_string(m->header->type), strna(m->path), strna(m->interface), strna(m->member), strna(m->sender), strna(m->destination)); return 1; } patch_sender(p->destination_bus, m); if (p->policy) { r = process_policy(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names); if (r == -ECONNRESET || r == -ENOTCONN) return r; if (r < 0) return log_error_errno(r, "Failed to process policy: %m"); if (r > 0) return 1; } r = sd_bus_send(p->local_bus, m, NULL); if (r < 0) { if (r == -ECONNRESET || r == -ENOTCONN) return r; /* If the peer tries to send a reply and it is * rejected with EBADSLT by the kernel, we ignore the * error. This catches cases where the original * method-call didn't had EXPECT_REPLY set, but the * proxy-peer still sends a reply. This is allowed in * dbus1, but not in kdbus. We don't want to track * reply-windows in the proxy, so we simply ignore * EBADSLT for all replies. The only downside is, that * callers are no longer notified if their replies are * dropped. However, this is equivalent to the * caller's timeout to expire, so this should be * acceptable. Nobody sane sends replies without a * matching method-call, so nobody should care. */ /* FIXME: remove -EPERM when kdbus is updated */ if ((r == -EPERM || r == -EBADSLT) && m->reply_cookie > 0) return 1; /* Return the error to the client, if we can */ synthetic_reply_method_errnof(m, r, "Failed to forward message we got from destination: %m"); if (r == -ENOBUFS) { /* if local dbus1 peer does not dispatch its queue, warn only once */ if (!p->queue_overflow) log_error("Dropped messages due to queue overflow of local peer (pid: "PID_FMT" uid: "UID_FMT")", p->local_creds.pid, p->local_creds.uid); p->queue_overflow = true; } else log_error_errno(r, "Failed to forward message we got from destination: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m", p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type), strna(m->destination), strna(m->path), strna(m->interface), strna(m->member)); return 1; } p->queue_overflow = false; return 1; } static int proxy_process_local_to_destination(Proxy *p) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; int r; assert(p); r = sd_bus_process(p->local_bus, &m); if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */ return r; if (r < 0) { log_error_errno(r, "Failed to process local bus: %m"); return r; } if (r == 0) return 0; if (!m) return 1; /* We officially got EOF, let's quit */ if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) return -ECONNRESET; r = process_hello(p, m); if (r == -ECONNRESET || r == -ENOTCONN) return r; if (r < 0) return log_error_errno(r, "Failed to process HELLO: %m"); if (r > 0) return 1; r = bus_proxy_process_driver(p, p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names); if (r == -ECONNRESET || r == -ENOTCONN) return r; if (r < 0) return log_error_errno(r, "Failed to process driver calls: %m"); if (r > 0) return 1; for (;;) { if (p->policy) { r = process_policy(p->local_bus, p->destination_bus, m, p->policy, &p->local_creds, p->owned_names); if (r == -ECONNRESET || r == -ENOTCONN) return r; if (r < 0) return log_error_errno(r, "Failed to process policy: %m"); if (r > 0) return 1; } r = sd_bus_send(p->destination_bus, m, NULL); if (r < 0) { if (r == -ECONNRESET || r == -ENOTCONN) return r; /* The name database changed since the policy check, hence let's check again */ if (r == -EREMCHG) continue; /* see above why EBADSLT is ignored for replies */ if ((r == -EPERM || r == -EBADSLT) && m->reply_cookie > 0) return 1; synthetic_reply_method_errnof(m, r, "Failed to forward message we got from local: %m"); log_error_errno(r, "Failed to forward message we got from local: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m", p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type), strna(m->destination), strna(m->path), strna(m->interface), strna(m->member)); return 1; } break; } return 1; } int proxy_match(sd_bus_message *m, void *userdata, sd_bus_error *error) { Proxy *p = userdata; p->message_matched = true; return 0; /* make sure to continue processing it in further handlers */ } int proxy_run(Proxy *p) { int r; assert(p); for (;;) { bool busy = false; if (p->got_hello) { /* Read messages from bus, to pass them on to our client */ r = proxy_process_destination_to_local(p); if (r == -ECONNRESET || r == -ENOTCONN) return 0; if (r < 0) return r; if (r > 0) busy = true; } /* Read messages from our client, to pass them on to the bus */ r = proxy_process_local_to_destination(p); if (r == -ECONNRESET || r == -ENOTCONN) return 0; if (r < 0) return r; if (r > 0) busy = true; if (!busy) { r = proxy_wait(p); if (r == -ECONNRESET || r == -ENOTCONN) return 0; if (r < 0) return r; } } return 0; } systemd-229/src/bus-proxyd/proxy.h000066400000000000000000000035631265713322000173250ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 David Herrmann systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "bus-xml-policy.h" typedef struct Proxy Proxy; typedef struct ProxyActivation ProxyActivation; #define PROXY_ACTIVATIONS_MAX (16) /* max parallel activation requests */ struct Proxy { sd_bus *local_bus; struct ucred local_creds; int local_in; int local_out; sd_bus *destination_bus; Set *owned_names; SharedPolicy *policy; LIST_HEAD(ProxyActivation, activations); size_t n_activations; bool got_hello : 1; bool queue_overflow : 1; bool message_matched : 1; bool synthetic_matched : 1; }; struct ProxyActivation { LIST_FIELDS(ProxyActivation, activations_by_proxy); Proxy *proxy; sd_bus_message *request; sd_bus_slot *slot; }; int proxy_new(Proxy **out, int in_fd, int out_fd, const char *dest); Proxy *proxy_free(Proxy *p); int proxy_set_policy(Proxy *p, SharedPolicy *policy, char **configuration); int proxy_hello_policy(Proxy *p, uid_t original_uid); int proxy_match(sd_bus_message *m, void *userdata, sd_bus_error *error); int proxy_run(Proxy *p); DEFINE_TRIVIAL_CLEANUP_FUNC(Proxy*, proxy_free); systemd-229/src/bus-proxyd/stdio-bridge.c000066400000000000000000000160211265713322000205040ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Daniel Mack Copyright 2014 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-bus.h" #include "sd-daemon.h" #include "alloc-util.h" #include "bus-internal.h" #include "bus-util.h" #include "def.h" #include "formats-util.h" #include "log.h" #include "proxy.h" #include "strv.h" #include "user-util.h" #include "util.h" static char *arg_address = NULL; static char *arg_command_line_buffer = NULL; static int help(void) { printf("%s [OPTIONS...]\n\n" "Connect STDIO to a given bus address.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --machine=MACHINE Connect to specified machine\n" " --address=ADDRESS Connect to the bus specified by ADDRESS\n" " (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n", program_invocation_short_name); return 0; } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_ADDRESS, ARG_MACHINE, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "address", required_argument, NULL, ARG_ADDRESS }, { "machine", required_argument, NULL, ARG_MACHINE }, {}, }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_ADDRESS: { char *a; a = strdup(optarg); if (!a) return log_oom(); free(arg_address); arg_address = a; break; } case ARG_MACHINE: { _cleanup_free_ char *e = NULL; char *a; e = bus_address_escape(optarg); if (!e) return log_oom(); a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL); if (!a) return log_oom(); free(arg_address); arg_address = a; break; } case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } /* If the first command line argument is only "x" characters * we'll write who we are talking to into it, so that "ps" is * explanatory */ arg_command_line_buffer = argv[optind]; if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) { log_error("Too many arguments"); return -EINVAL; } if (!arg_address) { arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS); if (!arg_address) return log_oom(); } return 1; } static int rename_service(sd_bus *a, sd_bus *b) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_free_ char *p = NULL, *name = NULL; const char *comm; char **cmdline; uid_t uid; pid_t pid; int r; assert(a); assert(b); r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds); if (r < 0) return r; r = sd_bus_creds_get_euid(creds, &uid); if (r < 0) return r; r = sd_bus_creds_get_pid(creds, &pid); if (r < 0) return r; r = sd_bus_creds_get_cmdline(creds, &cmdline); if (r < 0) return r; r = sd_bus_creds_get_comm(creds, &comm); if (r < 0) return r; name = uid_to_name(uid); if (!name) return -ENOMEM; p = strv_join(cmdline, " "); if (!p) return -ENOMEM; /* The status string gets the full command line ... */ sd_notifyf(false, "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)", pid, p, uid, name); /* ... and the argv line only the short comm */ if (arg_command_line_buffer) { size_t m, w; m = strlen(arg_command_line_buffer); w = snprintf(arg_command_line_buffer, m, "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]", pid, comm, uid, name); if (m > w) memzero(arg_command_line_buffer + w, m - w); } log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s", pid, p, uid, name, a->unique_name); return 0; } int main(int argc, char *argv[]) { _cleanup_(proxy_freep) Proxy *p = NULL; int r; log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = proxy_new(&p, STDIN_FILENO, STDOUT_FILENO, arg_address); if (r < 0) goto finish; r = rename_service(p->destination_bus, p->local_bus); if (r < 0) log_debug_errno(r, "Failed to rename process: %m"); r = proxy_run(p); finish: sd_notify(false, "STOPPING=1\n" "STATUS=Shutting down."); free(arg_address); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/bus-proxyd/synthesize.c000066400000000000000000000146631265713322000203470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Daniel Mack Copyright 2014 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "bus-internal.h" #include "bus-match.h" #include "bus-message.h" #include "bus-util.h" #include "synthesize.h" #include "util.h" int synthetic_driver_send(sd_bus *b, sd_bus_message *m) { int r; assert(b); assert(m); r = bus_message_append_sender(m, "org.freedesktop.DBus"); if (r < 0) return r; r = bus_seal_synthetic_message(b, m); if (r < 0) return r; return sd_bus_send(b, m, NULL); } int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; int r; assert(call); if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; r = sd_bus_message_new_method_error(call, &m, e); if (r < 0) return r; return synthetic_driver_send(call->bus, m); } int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; va_list ap; va_start(ap, format); bus_error_setfv(&error, name, format, ap); va_end(ap); return synthetic_reply_method_error(call, &error); } int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) { _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL; assert(call); if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; if (sd_bus_error_is_set(p)) return synthetic_reply_method_error(call, p); sd_bus_error_set_errno(&berror, error); return synthetic_reply_method_error(call, &berror); } int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) { _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL; va_list ap; assert(call); if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; va_start(ap, format); sd_bus_error_set_errnofv(&berror, error, format, ap); va_end(ap); return synthetic_reply_method_error(call, &berror); } int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; int r; assert(call); if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; r = sd_bus_message_new_method_return(call, &m); if (r < 0) return r; if (!isempty(types)) { va_list ap; va_start(ap, types); r = bus_message_append_ap(m, types, ap); va_end(ap); if (r < 0) return r; } return synthetic_driver_send(call->bus, m); } int synthetic_reply_method_return_strv(sd_bus_message *call, char **l) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; int r; assert(call); if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; r = sd_bus_message_new_method_return(call, &m); if (r < 0) return synthetic_reply_method_errno(call, r, NULL); r = sd_bus_message_append_strv(m, l); if (r < 0) return synthetic_reply_method_errno(call, r, NULL); return synthetic_driver_send(call->bus, m); } int synthesize_name_acquired(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL; const char *name, *old_owner, *new_owner; int r; assert(p); assert(a); assert(b); assert(m); /* If we get NameOwnerChanged for our own name, we need to * synthesize NameLost/NameAcquired, since socket clients need * that, even though it is obsoleted on kdbus */ if (!a->is_kernel) return 0; if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") || !streq_ptr(m->path, "/org/freedesktop/DBus") || !streq_ptr(m->sender, "org.freedesktop.DBus")) return 0; r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner); if (r < 0) return r; r = sd_bus_message_rewind(m, true); if (r < 0) return r; if (streq(old_owner, a->unique_name)) { r = sd_bus_message_new_signal( b, &n, "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameLost"); } else if (streq(new_owner, a->unique_name)) { r = sd_bus_message_new_signal( b, &n, "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameAcquired"); } else return 0; if (r < 0) return r; r = sd_bus_message_append(n, "s", name); if (r < 0) return r; r = bus_message_append_sender(n, "org.freedesktop.DBus"); if (r < 0) return r; r = sd_bus_message_set_destination(n, a->unique_name); if (r < 0) return r; r = bus_seal_synthetic_message(b, n); if (r < 0) return r; return sd_bus_send(b, n, NULL); } systemd-229/src/bus-proxyd/synthesize.h000066400000000000000000000026721265713322000203510ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "proxy.h" int synthetic_driver_send(sd_bus *b, sd_bus_message *m); int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...); int synthetic_reply_method_return_strv(sd_bus_message *call, char **l); int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e); int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) _sd_printf_(3, 4); int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p); int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) _sd_printf_(3, 4); int synthesize_name_acquired(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m); systemd-229/src/bus-proxyd/test-bus-xml-policy.c000066400000000000000000000165301265713322000217760ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Daniel Mack systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-xml-policy.h" #include "log.h" #include "string-util.h" #include "strv.h" #include "util.h" static int test_policy_load(Policy *p, const char *name) { _cleanup_free_ char *path = NULL; int r = 0; path = strjoin(TEST_DIR, "/bus-policy/", name, NULL); assert_se(path); if (access(path, R_OK) == 0) r = policy_load(p, STRV_MAKE(path)); else r = -ENOENT; return r; } static int show_policy(const char *fn) { Policy p = {}; int r; r = policy_load(&p, STRV_MAKE(fn)); if (r < 0) { log_error_errno(r, "Failed to load policy %s: %m", fn); return r; } policy_dump(&p); policy_free(&p); return 0; } int main(int argc, char *argv[]) { Policy p = {}; printf("Showing session policy BEGIN\n"); show_policy("/etc/dbus-1/session.conf"); printf("Showing session policy END\n"); printf("Showing system policy BEGIN\n"); show_policy("/etc/dbus-1/system.conf"); printf("Showing system policy END\n"); /* Ownership tests */ assert_se(test_policy_load(&p, "ownerships.conf") == 0); assert_se(policy_check_own(&p, 0, 0, "org.test.test1") == true); assert_se(policy_check_own(&p, 1, 0, "org.test.test1") == true); assert_se(policy_check_own(&p, 0, 0, "org.test.test2") == true); assert_se(policy_check_own(&p, 1, 0, "org.test.test2") == false); assert_se(policy_check_own(&p, 0, 0, "org.test.test3") == false); assert_se(policy_check_own(&p, 1, 0, "org.test.test3") == false); assert_se(policy_check_own(&p, 0, 0, "org.test.test4") == false); assert_se(policy_check_own(&p, 1, 0, "org.test.test4") == true); policy_free(&p); /* Signaltest */ assert_se(test_policy_load(&p, "signals.conf") == 0); assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_SIGNAL, "bli.bla.blubb", NULL, "/an/object/path", NULL) == true); assert_se(policy_check_one_send(&p, 1, 0, SD_BUS_MESSAGE_SIGNAL, "bli.bla.blubb", NULL, "/an/object/path", NULL) == false); policy_free(&p); /* Method calls */ assert_se(test_policy_load(&p, "methods.conf") == 0); policy_dump(&p); assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "bli.bla.blubb", "Member") == false); assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "bli.bla.blubb", "Member") == false); assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int1", "Member") == true); assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == true); assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test3", "/an/object/path", "org.test.int3", "Member111") == true); policy_free(&p); /* User and groups */ assert_se(test_policy_load(&p, "hello.conf") == 0); policy_dump(&p); assert_se(policy_check_hello(&p, 0, 0) == true); assert_se(policy_check_hello(&p, 1, 0) == false); assert_se(policy_check_hello(&p, 0, 1) == false); policy_free(&p); /* dbus1 test file: ownership */ assert_se(test_policy_load(&p, "check-own-rules.conf") >= 0); policy_dump(&p); assert_se(policy_check_own(&p, 0, 0, "org.freedesktop") == false); assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystem") == false); assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems") == true); assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems.foo") == true); assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems.foo.bar") == true); assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2") == false); assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2.foo") == false); assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2.foo.bar") == false); policy_free(&p); /* dbus1 test file: many rules */ assert_se(test_policy_load(&p, "many-rules.conf") >= 0); policy_dump(&p); policy_free(&p); /* dbus1 test file: generic test */ assert_se(test_policy_load(&p, "test.conf") >= 0); policy_dump(&p); assert_se(policy_check_own(&p, 0, 0, "org.foo.FooService") == true); assert_se(policy_check_own(&p, 0, 0, "org.foo.FooService2") == false); assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == false); assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true); assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true); assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface2", "Member") == false); assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService2", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false); assert_se(policy_check_own(&p, 100, 0, "org.foo.FooService") == false); assert_se(policy_check_own(&p, 100, 0, "org.foo.FooService2") == false); assert_se(policy_check_one_send(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == false); assert_se(policy_check_one_send(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false); assert_se(policy_check_one_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true); assert_se(policy_check_one_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface2", "Member") == false); assert_se(policy_check_one_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService2", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false); policy_free(&p); return EXIT_SUCCESS; } systemd-229/src/cgls/000077500000000000000000000000001265713322000146005ustar00rootroot00000000000000systemd-229/src/cgls/Makefile000077700000000000000000000000001265713322000201062../Makefileustar00rootroot00000000000000systemd-229/src/cgls/cgls.c000066400000000000000000000225331265713322000157010ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "cgroup-show.h" #include "cgroup-util.h" #include "fileio.h" #include "log.h" #include "output-mode.h" #include "pager.h" #include "path-util.h" #include "unit-name.h" #include "util.h" static bool arg_no_pager = false; static bool arg_kernel_threads = false; static bool arg_all = false; static int arg_full = -1; static char* arg_machine = NULL; static void help(void) { printf("%s [OPTIONS...] [CGROUP...]\n\n" "Recursively show control group contents.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " -a --all Show all groups, including empty\n" " -l --full Do not ellipsize output\n" " -k Include kernel threads in output\n" " -M --machine= Show container\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_NO_PAGER = 0x100, ARG_VERSION, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "all", no_argument, NULL, 'a' }, { "full", no_argument, NULL, 'l' }, { "machine", required_argument, NULL, 'M' }, {} }; int c; assert(argc >= 1); assert(argv); while ((c = getopt_long(argc, argv, "hkalM:", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_NO_PAGER: arg_no_pager = true; break; case 'a': arg_all = true; break; case 'l': arg_full = true; break; case 'k': arg_kernel_threads = true; break; case 'M': arg_machine = optarg; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } static int get_cgroup_root(char **ret) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_free_ char *unit = NULL, *path = NULL; const char *m; int r; if (!arg_machine) { r = cg_get_root_path(ret); if (r == -ENOMEDIUM) return log_error_errno(r, "Failed to get root control group path: No cgroup filesystem mounted on /sys/fs/cgroup"); else if (r < 0) return log_error_errno(r, "Failed to get root control group path: %m"); return 0; } m = strjoina("/run/systemd/machines/", arg_machine); r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); if (r < 0) return log_error_errno(r, "Failed to load machine data: %m"); path = unit_dbus_path_from_name(unit); if (!path) return log_oom(); r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); if (r < 0) return log_error_errno(r, "Failed to create bus connection: %m"); r = sd_bus_get_property_string( bus, "org.freedesktop.systemd1", path, unit_dbus_interface_from_name(unit), "ControlGroup", &error, ret); if (r < 0) return log_error_errno(r, "Failed to query unit control group path: %s", bus_error_message(&error, r)); return 0; } static void show_cg_info(const char *controller, const char *path) { if (cg_unified() <= 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER)) printf("Controller %s; ", controller); printf("Control group %s:\n", isempty(path) ? "/" : path); fflush(stdout); } int main(int argc, char *argv[]) { int r, output_flags; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; if (!arg_no_pager) { r = pager_open(false); if (r > 0 && arg_full < 0) arg_full = true; } output_flags = arg_all * OUTPUT_SHOW_ALL | (arg_full > 0) * OUTPUT_FULL_WIDTH; if (optind < argc) { _cleanup_free_ char *root = NULL; int i; r = get_cgroup_root(&root); if (r < 0) goto finish; for (i = optind; i < argc; i++) { int q; if (path_startswith(argv[i], "/sys/fs/cgroup")) { printf("Directory %s:\n", argv[i]); fflush(stdout); q = show_cgroup_by_path(argv[i], NULL, 0, arg_kernel_threads, output_flags); } else { _cleanup_free_ char *c = NULL, *p = NULL, *j = NULL; const char *controller, *path; r = cg_split_spec(argv[i], &c, &p); if (r < 0) { log_error_errno(r, "Failed to split argument %s: %m", argv[i]); goto finish; } controller = c ?: SYSTEMD_CGROUP_CONTROLLER; if (p) { j = strjoin(root, "/", p, NULL); if (!j) { r = log_oom(); goto finish; } path_kill_slashes(j); path = j; } else path = root; show_cg_info(controller, path); q = show_cgroup(controller, path, NULL, 0, arg_kernel_threads, output_flags); } if (q < 0) r = q; } } else { bool done = false; if (!arg_machine) { _cleanup_free_ char *cwd = NULL; cwd = get_current_dir_name(); if (!cwd) { r = log_error_errno(errno, "Cannot determine current working directory: %m"); goto finish; } if (path_startswith(cwd, "/sys/fs/cgroup")) { printf("Working directory %s:\n", cwd); fflush(stdout); r = show_cgroup_by_path(cwd, NULL, 0, arg_kernel_threads, output_flags); done = true; } } if (!done) { _cleanup_free_ char *root = NULL; r = get_cgroup_root(&root); if (r < 0) goto finish; show_cg_info(SYSTEMD_CGROUP_CONTROLLER, root); printf("-.slice\n"); r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0, arg_kernel_threads, output_flags); } } if (r < 0) log_error_errno(r, "Failed to list cgroup tree: %m"); finish: pager_close(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/cgroups-agent/000077500000000000000000000000001265713322000164265ustar00rootroot00000000000000systemd-229/src/cgroups-agent/Makefile000077700000000000000000000000001265713322000217342../Makefileustar00rootroot00000000000000systemd-229/src/cgroups-agent/cgroups-agent.c000066400000000000000000000043251265713322000213540ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "bus-util.h" #include "log.h" int main(int argc, char *argv[]) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; if (argc != 2) { log_error("Incorrect number of arguments."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); /* We send this event to the private D-Bus socket and then the * system instance will forward this to the system bus. We do * this to avoid an activation loop when we start dbus when we * are called when the dbus service is shut down. */ r = bus_connect_system_systemd(&bus); if (r < 0) { /* If we couldn't connect we assume this was triggered * while systemd got restarted/transitioned from * initrd to the system, so let's ignore this */ log_debug_errno(r, "Failed to get D-Bus connection: %m"); return EXIT_FAILURE; } r = sd_bus_emit_signal(bus, "/org/freedesktop/systemd1/agent", "org.freedesktop.systemd1.Agent", "Released", "s", argv[1]); if (r < 0) { log_debug_errno(r, "Failed to send signal message on private connection: %m"); return EXIT_FAILURE; } return EXIT_SUCCESS; } systemd-229/src/cgtop/000077500000000000000000000000001265713322000147645ustar00rootroot00000000000000systemd-229/src/cgtop/Makefile000077700000000000000000000000001265713322000202722../Makefileustar00rootroot00000000000000systemd-229/src/cgtop/cgtop.c000066400000000000000000001102671265713322000162530ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "cgroup-util.h" #include "fd-util.h" #include "fileio.h" #include "hashmap.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "stdio-util.h" #include "terminal-util.h" #include "unit-name.h" #include "util.h" typedef struct Group { char *path; bool n_tasks_valid:1; bool cpu_valid:1; bool memory_valid:1; bool io_valid:1; uint64_t n_tasks; unsigned cpu_iteration; nsec_t cpu_usage; nsec_t cpu_timestamp; double cpu_fraction; uint64_t memory; unsigned io_iteration; uint64_t io_input, io_output; nsec_t io_timestamp; uint64_t io_input_bps, io_output_bps; } Group; static unsigned arg_depth = 3; static unsigned arg_iterations = (unsigned) -1; static bool arg_batch = false; static bool arg_raw = false; static usec_t arg_delay = 1*USEC_PER_SEC; static char* arg_machine = NULL; enum { COUNT_PIDS, COUNT_USERSPACE_PROCESSES, COUNT_ALL_PROCESSES, } arg_count = COUNT_PIDS; static bool arg_recursive = true; static enum { ORDER_PATH, ORDER_TASKS, ORDER_CPU, ORDER_MEMORY, ORDER_IO, } arg_order = ORDER_CPU; static enum { CPU_PERCENT, CPU_TIME, } arg_cpu_type = CPU_PERCENT; static void group_free(Group *g) { assert(g); free(g->path); free(g); } static void group_hashmap_clear(Hashmap *h) { Group *g; while ((g = hashmap_steal_first(h))) group_free(g); } static void group_hashmap_free(Hashmap *h) { group_hashmap_clear(h); hashmap_free(h); } static const char *maybe_format_bytes(char *buf, size_t l, bool is_valid, uint64_t t) { if (!is_valid) return "-"; if (arg_raw) { snprintf(buf, l, "%jd", t); return buf; } return format_bytes(buf, l, t); } static int process( const char *controller, const char *path, Hashmap *a, Hashmap *b, unsigned iteration, Group **ret) { Group *g; int r; assert(controller); assert(path); assert(a); g = hashmap_get(a, path); if (!g) { g = hashmap_get(b, path); if (!g) { g = new0(Group, 1); if (!g) return -ENOMEM; g->path = strdup(path); if (!g->path) { group_free(g); return -ENOMEM; } r = hashmap_put(a, g->path, g); if (r < 0) { group_free(g); return r; } } else { r = hashmap_move_one(a, b, path); if (r < 0) return r; g->cpu_valid = g->memory_valid = g->io_valid = g->n_tasks_valid = false; } } if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) && IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES)) { _cleanup_fclose_ FILE *f = NULL; pid_t pid; r = cg_enumerate_processes(controller, path, &f); if (r == -ENOENT) return 0; if (r < 0) return r; g->n_tasks = 0; while (cg_read_pid(f, &pid) > 0) { if (arg_count == COUNT_USERSPACE_PROCESSES && is_kernel_thread(pid) > 0) continue; g->n_tasks++; } if (g->n_tasks > 0) g->n_tasks_valid = true; } else if (streq(controller, "pids") && arg_count == COUNT_PIDS) { _cleanup_free_ char *p = NULL, *v = NULL; r = cg_get_path(controller, path, "pids.current", &p); if (r < 0) return r; r = read_one_line_file(p, &v); if (r == -ENOENT) return 0; if (r < 0) return r; r = safe_atou64(v, &g->n_tasks); if (r < 0) return r; if (g->n_tasks > 0) g->n_tasks_valid = true; } else if (streq(controller, "cpuacct") && cg_unified() <= 0) { _cleanup_free_ char *p = NULL, *v = NULL; uint64_t new_usage; nsec_t timestamp; r = cg_get_path(controller, path, "cpuacct.usage", &p); if (r < 0) return r; r = read_one_line_file(p, &v); if (r == -ENOENT) return 0; if (r < 0) return r; r = safe_atou64(v, &new_usage); if (r < 0) return r; timestamp = now_nsec(CLOCK_MONOTONIC); if (g->cpu_iteration == iteration - 1 && (nsec_t) new_usage > g->cpu_usage) { nsec_t x, y; x = timestamp - g->cpu_timestamp; if (x < 1) x = 1; y = (nsec_t) new_usage - g->cpu_usage; g->cpu_fraction = (double) y / (double) x; g->cpu_valid = true; } g->cpu_usage = (nsec_t) new_usage; g->cpu_timestamp = timestamp; g->cpu_iteration = iteration; } else if (streq(controller, "memory")) { _cleanup_free_ char *p = NULL, *v = NULL; if (cg_unified() <= 0) r = cg_get_path(controller, path, "memory.usage_in_bytes", &p); else r = cg_get_path(controller, path, "memory.current", &p); if (r < 0) return r; r = read_one_line_file(p, &v); if (r == -ENOENT) return 0; if (r < 0) return r; r = safe_atou64(v, &g->memory); if (r < 0) return r; if (g->memory > 0) g->memory_valid = true; } else if (streq(controller, "blkio") && cg_unified() <= 0) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; uint64_t wr = 0, rd = 0; nsec_t timestamp; r = cg_get_path(controller, path, "blkio.io_service_bytes", &p); if (r < 0) return r; f = fopen(p, "re"); if (!f) { if (errno == ENOENT) return 0; return -errno; } for (;;) { char line[LINE_MAX], *l; uint64_t k, *q; if (!fgets(line, sizeof(line), f)) break; l = strstrip(line); l += strcspn(l, WHITESPACE); l += strspn(l, WHITESPACE); if (first_word(l, "Read")) { l += 4; q = &rd; } else if (first_word(l, "Write")) { l += 5; q = ≀ } else continue; l += strspn(l, WHITESPACE); r = safe_atou64(l, &k); if (r < 0) continue; *q += k; } timestamp = now_nsec(CLOCK_MONOTONIC); if (g->io_iteration == iteration - 1) { uint64_t x, yr, yw; x = (uint64_t) (timestamp - g->io_timestamp); if (x < 1) x = 1; if (rd > g->io_input) yr = rd - g->io_input; else yr = 0; if (wr > g->io_output) yw = wr - g->io_output; else yw = 0; if (yr > 0 || yw > 0) { g->io_input_bps = (yr * 1000000000ULL) / x; g->io_output_bps = (yw * 1000000000ULL) / x; g->io_valid = true; } } g->io_input = rd; g->io_output = wr; g->io_timestamp = timestamp; g->io_iteration = iteration; } if (ret) *ret = g; return 0; } static int refresh_one( const char *controller, const char *path, Hashmap *a, Hashmap *b, unsigned iteration, unsigned depth, Group **ret) { _cleanup_closedir_ DIR *d = NULL; Group *ours; int r; assert(controller); assert(path); assert(a); if (depth > arg_depth) return 0; r = process(controller, path, a, b, iteration, &ours); if (r < 0) return r; r = cg_enumerate_subgroups(controller, path, &d); if (r == -ENOENT) return 0; if (r < 0) return r; for (;;) { _cleanup_free_ char *fn = NULL, *p = NULL; Group *child = NULL; r = cg_read_subgroup(d, &fn); if (r < 0) return r; if (r == 0) break; p = strjoin(path, "/", fn, NULL); if (!p) return -ENOMEM; path_kill_slashes(p); r = refresh_one(controller, p, a, b, iteration, depth + 1, &child); if (r < 0) return r; if (arg_recursive && IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES) && child && child->n_tasks_valid && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { /* Recursively sum up processes */ if (ours->n_tasks_valid) ours->n_tasks += child->n_tasks; else { ours->n_tasks = child->n_tasks; ours->n_tasks_valid = true; } } } if (ret) *ret = ours; return 1; } static int refresh(const char *root, Hashmap *a, Hashmap *b, unsigned iteration) { int r; assert(a); r = refresh_one(SYSTEMD_CGROUP_CONTROLLER, root, a, b, iteration, 0, NULL); if (r < 0) return r; r = refresh_one("cpuacct", root, a, b, iteration, 0, NULL); if (r < 0) return r; r = refresh_one("memory", root, a, b, iteration, 0, NULL); if (r < 0) return r; r = refresh_one("blkio", root, a, b, iteration, 0, NULL); if (r < 0) return r; r = refresh_one("pids", root, a, b, iteration, 0, NULL); if (r < 0) return r; return 0; } static int group_compare(const void*a, const void *b) { const Group *x = *(Group**)a, *y = *(Group**)b; if (arg_order != ORDER_TASKS || arg_recursive) { /* Let's make sure that the parent is always before * the child. Except when ordering by tasks and * recursive summing is off, since that is actually * not accumulative for all children. */ if (path_startswith(y->path, x->path)) return -1; if (path_startswith(x->path, y->path)) return 1; } switch (arg_order) { case ORDER_PATH: break; case ORDER_CPU: if (arg_cpu_type == CPU_PERCENT) { if (x->cpu_valid && y->cpu_valid) { if (x->cpu_fraction > y->cpu_fraction) return -1; else if (x->cpu_fraction < y->cpu_fraction) return 1; } else if (x->cpu_valid) return -1; else if (y->cpu_valid) return 1; } else { if (x->cpu_usage > y->cpu_usage) return -1; else if (x->cpu_usage < y->cpu_usage) return 1; } break; case ORDER_TASKS: if (x->n_tasks_valid && y->n_tasks_valid) { if (x->n_tasks > y->n_tasks) return -1; else if (x->n_tasks < y->n_tasks) return 1; } else if (x->n_tasks_valid) return -1; else if (y->n_tasks_valid) return 1; break; case ORDER_MEMORY: if (x->memory_valid && y->memory_valid) { if (x->memory > y->memory) return -1; else if (x->memory < y->memory) return 1; } else if (x->memory_valid) return -1; else if (y->memory_valid) return 1; break; case ORDER_IO: if (x->io_valid && y->io_valid) { if (x->io_input_bps + x->io_output_bps > y->io_input_bps + y->io_output_bps) return -1; else if (x->io_input_bps + x->io_output_bps < y->io_input_bps + y->io_output_bps) return 1; } else if (x->io_valid) return -1; else if (y->io_valid) return 1; } return path_compare(x->path, y->path); } static void display(Hashmap *a) { Iterator i; Group *g; Group **array; signed path_columns; unsigned rows, n = 0, j, maxtcpu = 0, maxtpath = 3; /* 3 for ellipsize() to work properly */ char buffer[MAX3(21, FORMAT_BYTES_MAX, FORMAT_TIMESPAN_MAX)]; assert(a); if (on_tty()) fputs(ANSI_HOME_CLEAR, stdout); array = alloca(sizeof(Group*) * hashmap_size(a)); HASHMAP_FOREACH(g, a, i) if (g->n_tasks_valid || g->cpu_valid || g->memory_valid || g->io_valid) array[n++] = g; qsort_safe(array, n, sizeof(Group*), group_compare); /* Find the longest names in one run */ for (j = 0; j < n; j++) { unsigned cputlen, pathtlen; format_timespan(buffer, sizeof(buffer), (usec_t) (array[j]->cpu_usage / NSEC_PER_USEC), 0); cputlen = strlen(buffer); maxtcpu = MAX(maxtcpu, cputlen); pathtlen = strlen(array[j]->path); maxtpath = MAX(maxtpath, pathtlen); } if (arg_cpu_type == CPU_PERCENT) xsprintf(buffer, "%6s", "%CPU"); else xsprintf(buffer, "%*s", maxtcpu, "CPU Time"); rows = lines(); if (rows <= 10) rows = 10; if (on_tty()) { const char *on, *off; path_columns = columns() - 36 - strlen(buffer); if (path_columns < 10) path_columns = 10; on = ansi_highlight_underline(); off = ansi_underline(); printf("%s%s%-*s%s %s%7s%s %s%s%s %s%8s%s %s%8s%s %s%8s%s%s\n", ansi_underline(), arg_order == ORDER_PATH ? on : "", path_columns, "Control Group", arg_order == ORDER_PATH ? off : "", arg_order == ORDER_TASKS ? on : "", arg_count == COUNT_PIDS ? "Tasks" : arg_count == COUNT_USERSPACE_PROCESSES ? "Procs" : "Proc+", arg_order == ORDER_TASKS ? off : "", arg_order == ORDER_CPU ? on : "", buffer, arg_order == ORDER_CPU ? off : "", arg_order == ORDER_MEMORY ? on : "", "Memory", arg_order == ORDER_MEMORY ? off : "", arg_order == ORDER_IO ? on : "", "Input/s", arg_order == ORDER_IO ? off : "", arg_order == ORDER_IO ? on : "", "Output/s", arg_order == ORDER_IO ? off : "", ansi_normal()); } else path_columns = maxtpath; for (j = 0; j < n; j++) { _cleanup_free_ char *ellipsized = NULL; const char *path; if (on_tty() && j + 6 > rows) break; g = array[j]; path = isempty(g->path) ? "/" : g->path; ellipsized = ellipsize(path, path_columns, 33); printf("%-*s", path_columns, ellipsized ?: path); if (g->n_tasks_valid) printf(" %7" PRIu64, g->n_tasks); else fputs(" -", stdout); if (arg_cpu_type == CPU_PERCENT) { if (g->cpu_valid) printf(" %6.1f", g->cpu_fraction*100); else fputs(" -", stdout); } else printf(" %*s", maxtcpu, format_timespan(buffer, sizeof(buffer), (usec_t) (g->cpu_usage / NSEC_PER_USEC), 0)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->memory_valid, g->memory)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->io_valid, g->io_input_bps)); printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->io_valid, g->io_output_bps)); putchar('\n'); } } static void help(void) { printf("%s [OPTIONS...]\n\n" "Show top control groups by their resource usage.\n\n" " -h --help Show this help\n" " --version Show package version\n" " -p --order=path Order by path\n" " -t --order=tasks Order by number of tasks/processes\n" " -c --order=cpu Order by CPU load (default)\n" " -m --order=memory Order by memory load\n" " -i --order=io Order by IO load\n" " -r --raw Provide raw (not human-readable) numbers\n" " --cpu=percentage Show CPU usage as percentage (default)\n" " --cpu=time Show CPU usage as time\n" " -P Count userspace processes instead of tasks (excl. kernel)\n" " -k Count all processes instead of tasks (incl. kernel)\n" " --recursive=BOOL Sum up process count recursively\n" " -d --delay=DELAY Delay between updates\n" " -n --iterations=N Run for N iterations before exiting\n" " -b --batch Run in batch mode, accepting no input\n" " --depth=DEPTH Maximum traversal depth (default: %u)\n" " -M --machine= Show container\n" , program_invocation_short_name, arg_depth); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_DEPTH, ARG_CPU_TYPE, ARG_ORDER, ARG_RECURSIVE, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "delay", required_argument, NULL, 'd' }, { "iterations", required_argument, NULL, 'n' }, { "batch", no_argument, NULL, 'b' }, { "raw", no_argument, NULL, 'r' }, { "depth", required_argument, NULL, ARG_DEPTH }, { "cpu", optional_argument, NULL, ARG_CPU_TYPE }, { "order", required_argument, NULL, ARG_ORDER }, { "recursive", required_argument, NULL, ARG_RECURSIVE }, { "machine", required_argument, NULL, 'M' }, {} }; bool recursive_unset = false; int c, r; assert(argc >= 1); assert(argv); while ((c = getopt_long(argc, argv, "hptcmin:brd:kPM:", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_CPU_TYPE: if (optarg) { if (streq(optarg, "time")) arg_cpu_type = CPU_TIME; else if (streq(optarg, "percentage")) arg_cpu_type = CPU_PERCENT; else { log_error("Unknown argument to --cpu=: %s", optarg); return -EINVAL; } } else arg_cpu_type = CPU_TIME; break; case ARG_DEPTH: r = safe_atou(optarg, &arg_depth); if (r < 0) { log_error("Failed to parse depth parameter."); return -EINVAL; } break; case 'd': r = parse_sec(optarg, &arg_delay); if (r < 0 || arg_delay <= 0) { log_error("Failed to parse delay parameter."); return -EINVAL; } break; case 'n': r = safe_atou(optarg, &arg_iterations); if (r < 0) { log_error("Failed to parse iterations parameter."); return -EINVAL; } break; case 'b': arg_batch = true; break; case 'r': arg_raw = true; break; case 'p': arg_order = ORDER_PATH; break; case 't': arg_order = ORDER_TASKS; break; case 'c': arg_order = ORDER_CPU; break; case 'm': arg_order = ORDER_MEMORY; break; case 'i': arg_order = ORDER_IO; break; case ARG_ORDER: if (streq(optarg, "path")) arg_order = ORDER_PATH; else if (streq(optarg, "tasks")) arg_order = ORDER_TASKS; else if (streq(optarg, "cpu")) arg_order = ORDER_CPU; else if (streq(optarg, "memory")) arg_order = ORDER_MEMORY; else if (streq(optarg, "io")) arg_order = ORDER_IO; else { log_error("Invalid argument to --order=: %s", optarg); return -EINVAL; } break; case 'k': arg_count = COUNT_ALL_PROCESSES; break; case 'P': arg_count = COUNT_USERSPACE_PROCESSES; break; case ARG_RECURSIVE: r = parse_boolean(optarg); if (r < 0) { log_error("Failed to parse --recursive= argument: %s", optarg); return r; } arg_recursive = r; recursive_unset = r == 0; break; case 'M': arg_machine = optarg; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (optind < argc) { log_error("Too many arguments."); return -EINVAL; } if (recursive_unset && arg_count == COUNT_PIDS) { log_error("Non-recursive counting is only supported when counting processes, not tasks. Use -P or -k."); return -EINVAL; } return 1; } static const char* counting_what(void) { if (arg_count == COUNT_PIDS) return "tasks"; else if (arg_count == COUNT_ALL_PROCESSES) return "all processes (incl. kernel)"; else return "userspace processes (excl. kernel)"; } static int get_cgroup_root(char **ret) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_free_ char *unit = NULL, *path = NULL; const char *m; int r; if (!arg_machine) { r = cg_get_root_path(ret); if (r < 0) return log_error_errno(r, "Failed to get root control group path: %m"); return 0; } m = strjoina("/run/systemd/machines/", arg_machine); r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); if (r < 0) return log_error_errno(r, "Failed to load machine data: %m"); path = unit_dbus_path_from_name(unit); if (!path) return log_oom(); r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); if (r < 0) return log_error_errno(r, "Failed to create bus connection: %m"); r = sd_bus_get_property_string( bus, "org.freedesktop.systemd1", path, unit_dbus_interface_from_name(unit), "ControlGroup", &error, ret); if (r < 0) return log_error_errno(r, "Failed to query unit control group path: %s", bus_error_message(&error, r)); return 0; } int main(int argc, char *argv[]) { int r; Hashmap *a = NULL, *b = NULL; unsigned iteration = 0; usec_t last_refresh = 0; bool quit = false, immediate_refresh = false; _cleanup_free_ char *root = NULL; CGroupMask mask; log_parse_environment(); log_open(); r = cg_mask_supported(&mask); if (r < 0) { log_error_errno(r, "Failed to determine supported controllers: %m"); goto finish; } arg_count = (mask & CGROUP_MASK_PIDS) ? COUNT_PIDS : COUNT_USERSPACE_PROCESSES; r = parse_argv(argc, argv); if (r <= 0) goto finish; r = get_cgroup_root(&root); if (r < 0) { log_error_errno(r, "Failed to get root control group path: %m"); goto finish; } a = hashmap_new(&string_hash_ops); b = hashmap_new(&string_hash_ops); if (!a || !b) { r = log_oom(); goto finish; } signal(SIGWINCH, columns_lines_cache_reset); if (arg_iterations == (unsigned) -1) arg_iterations = on_tty() ? 0 : 1; while (!quit) { Hashmap *c; usec_t t; char key; char h[FORMAT_TIMESPAN_MAX]; t = now(CLOCK_MONOTONIC); if (t >= last_refresh + arg_delay || immediate_refresh) { r = refresh(root, a, b, iteration++); if (r < 0) { log_error_errno(r, "Failed to refresh: %m"); goto finish; } group_hashmap_clear(b); c = a; a = b; b = c; last_refresh = t; immediate_refresh = false; } display(b); if (arg_iterations && iteration >= arg_iterations) break; if (!on_tty()) /* non-TTY: Empty newline as delimiter between polls */ fputs("\n", stdout); fflush(stdout); if (arg_batch) (void) usleep(last_refresh + arg_delay - t); else { r = read_one_char(stdin, &key, last_refresh + arg_delay - t, NULL); if (r == -ETIMEDOUT) continue; if (r < 0) { log_error_errno(r, "Couldn't read key: %m"); goto finish; } } if (on_tty()) { /* TTY: Clear any user keystroke */ fputs("\r \r", stdout); fflush(stdout); } if (arg_batch) continue; switch (key) { case ' ': immediate_refresh = true; break; case 'q': quit = true; break; case 'p': arg_order = ORDER_PATH; break; case 't': arg_order = ORDER_TASKS; break; case 'c': arg_order = ORDER_CPU; break; case 'm': arg_order = ORDER_MEMORY; break; case 'i': arg_order = ORDER_IO; break; case '%': arg_cpu_type = arg_cpu_type == CPU_TIME ? CPU_PERCENT : CPU_TIME; break; case 'k': arg_count = arg_count != COUNT_ALL_PROCESSES ? COUNT_ALL_PROCESSES : COUNT_PIDS; fprintf(stdout, "\nCounting: %s.", counting_what()); fflush(stdout); sleep(1); break; case 'P': arg_count = arg_count != COUNT_USERSPACE_PROCESSES ? COUNT_USERSPACE_PROCESSES : COUNT_PIDS; fprintf(stdout, "\nCounting: %s.", counting_what()); fflush(stdout); sleep(1); break; case 'r': if (arg_count == COUNT_PIDS) fprintf(stdout, "\n\aCannot toggle recursive counting, not available in task counting mode."); else { arg_recursive = !arg_recursive; fprintf(stdout, "\nRecursive process counting: %s", yes_no(arg_recursive)); } fflush(stdout); sleep(1); break; case '+': if (arg_delay < USEC_PER_SEC) arg_delay += USEC_PER_MSEC*250; else arg_delay += USEC_PER_SEC; fprintf(stdout, "\nIncreased delay to %s.", format_timespan(h, sizeof(h), arg_delay, 0)); fflush(stdout); sleep(1); break; case '-': if (arg_delay <= USEC_PER_MSEC*500) arg_delay = USEC_PER_MSEC*250; else if (arg_delay < USEC_PER_MSEC*1250) arg_delay -= USEC_PER_MSEC*250; else arg_delay -= USEC_PER_SEC; fprintf(stdout, "\nDecreased delay to %s.", format_timespan(h, sizeof(h), arg_delay, 0)); fflush(stdout); sleep(1); break; case '?': case 'h': #define ON ANSI_HIGHLIGHT #define OFF ANSI_NORMAL fprintf(stdout, "\t<" ON "p" OFF "> By path; <" ON "t" OFF "> By tasks/procs; <" ON "c" OFF "> By CPU; <" ON "m" OFF "> By memory; <" ON "i" OFF "> By I/O\n" "\t<" ON "+" OFF "> Inc. delay; <" ON "-" OFF "> Dec. delay; <" ON "%%" OFF "> Toggle time; <" ON "SPACE" OFF "> Refresh\n" "\t<" ON "P" OFF "> Toggle count userspace processes; <" ON "k" OFF "> Toggle count all processes\n" "\t<" ON "r" OFF "> Count processes recursively; <" ON "q" OFF "> Quit"); fflush(stdout); sleep(3); break; default: if (key < ' ') fprintf(stdout, "\nUnknown key '\\x%x'. Ignoring.", key); else fprintf(stdout, "\nUnknown key '%c'. Ignoring.", key); fflush(stdout); sleep(1); break; } } r = 0; finish: group_hashmap_free(a); group_hashmap_free(b); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/compat-libs/000077500000000000000000000000001265713322000160625ustar00rootroot00000000000000systemd-229/src/compat-libs/.gitignore000066400000000000000000000000211265713322000200430ustar00rootroot00000000000000/libsystemd-*.pc systemd-229/src/compat-libs/libsystemd-daemon.pc.in000066400000000000000000000013031265713322000224300ustar00rootroot00000000000000# Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: systemd Description: systemd Daemon Utility Library - deprecated URL: @PACKAGE_URL@ Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lsystemd Cflags: -I${includedir} systemd-229/src/compat-libs/libsystemd-daemon.sym000066400000000000000000000014011265713322000222300ustar00rootroot00000000000000/*** Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: ***/ /* Original symbols from systemd v31 */ LIBSYSTEMD_DAEMON_31 { global: sd_booted; sd_is_fifo; sd_is_mq; sd_is_socket; sd_is_socket_inet; sd_is_socket_unix; sd_is_special; sd_listen_fds; sd_notify; sd_notifyf; local: *; }; systemd-229/src/compat-libs/libsystemd-id128.pc.in000066400000000000000000000010441265713322000220160ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: systemd Description: systemd 128 Bit ID Utility Library - deprecated URL: @PACKAGE_URL@ Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lsystemd Cflags: -I${includedir} systemd-229/src/compat-libs/libsystemd-id128.sym000066400000000000000000000010231265713322000216140ustar00rootroot00000000000000/*** This file is part of systemd. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. ***/ /* Original symbols from systemd v38 */ LIBSYSTEMD_ID128_38 { global: sd_id128_to_string; sd_id128_from_string; sd_id128_randomize; sd_id128_get_machine; sd_id128_get_boot; local: *; }; systemd-229/src/compat-libs/libsystemd-journal.pc.in000066400000000000000000000011121265713322000226350ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: systemd Description: systemd Journal Utility Library - deprecated URL: @PACKAGE_URL@ Version: @PACKAGE_VERSION@ Requires: libsystemd = @PACKAGE_VERSION@ Libs: -L${libdir} -lsystemd Cflags: -I${includedir} systemd-229/src/compat-libs/libsystemd-journal.sym000066400000000000000000000052741265713322000224530ustar00rootroot00000000000000/*** This file is part of systemd. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. ***/ /* Original symbols from systemd v38 */ LIBSYSTEMD_JOURNAL_38 { global: sd_journal_print; sd_journal_printv; sd_journal_send; sd_journal_sendv; sd_journal_stream_fd; sd_journal_open; sd_journal_close; sd_journal_previous; sd_journal_next; sd_journal_previous_skip; sd_journal_next_skip; sd_journal_get_realtime_usec; sd_journal_get_monotonic_usec; sd_journal_get_data; sd_journal_enumerate_data; sd_journal_restart_data; sd_journal_add_match; sd_journal_flush_matches; sd_journal_seek_head; sd_journal_seek_tail; sd_journal_seek_monotonic_usec; sd_journal_seek_realtime_usec; sd_journal_seek_cursor; sd_journal_get_cursor; sd_journal_get_fd; sd_journal_process; local: *; }; LIBSYSTEMD_JOURNAL_183 { global: sd_journal_print_with_location; sd_journal_printv_with_location; sd_journal_send_with_location; sd_journal_sendv_with_location; } LIBSYSTEMD_JOURNAL_38; LIBSYSTEMD_JOURNAL_184 { global: sd_journal_get_cutoff_realtime_usec; sd_journal_get_cutoff_monotonic_usec; } LIBSYSTEMD_JOURNAL_183; LIBSYSTEMD_JOURNAL_187 { global: sd_journal_wait; sd_journal_open_directory; sd_journal_add_disjunction; } LIBSYSTEMD_JOURNAL_184; LIBSYSTEMD_JOURNAL_188 { global: sd_journal_perror; sd_journal_perror_with_location; } LIBSYSTEMD_JOURNAL_187; LIBSYSTEMD_JOURNAL_190 { global: sd_journal_get_usage; } LIBSYSTEMD_JOURNAL_188; LIBSYSTEMD_JOURNAL_195 { global: sd_journal_test_cursor; sd_journal_query_unique; sd_journal_enumerate_unique; sd_journal_restart_unique; } LIBSYSTEMD_JOURNAL_190; LIBSYSTEMD_JOURNAL_196 { global: sd_journal_get_catalog; sd_journal_get_catalog_for_message_id; sd_journal_set_data_threshold; sd_journal_get_data_threshold; } LIBSYSTEMD_JOURNAL_195; LIBSYSTEMD_JOURNAL_198 { global: sd_journal_reliable_fd; } LIBSYSTEMD_JOURNAL_196; LIBSYSTEMD_JOURNAL_201 { global: sd_journal_get_events; sd_journal_get_timeout; } LIBSYSTEMD_JOURNAL_198; LIBSYSTEMD_JOURNAL_202 { global: sd_journal_add_conjunction; } LIBSYSTEMD_JOURNAL_201; LIBSYSTEMD_JOURNAL_205 { global: sd_journal_open_files; } LIBSYSTEMD_JOURNAL_202; systemd-229/src/compat-libs/libsystemd-login.pc.in000066400000000000000000000010371265713322000223010ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: systemd Description: systemd Login Utility Library - deprecated URL: @PACKAGE_URL@ Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lsystemd Cflags: -I${includedir} systemd-229/src/compat-libs/libsystemd-login.sym000066400000000000000000000035671265713322000221140ustar00rootroot00000000000000/*** This file is part of systemd. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. ***/ /* Original symbols from systemd v31 */ LIBSYSTEMD_LOGIN_31 { global: sd_get_seats; sd_get_sessions; sd_get_uids; sd_login_monitor_flush; sd_login_monitor_get_fd; sd_login_monitor_new; sd_login_monitor_unref; sd_pid_get_owner_uid; sd_pid_get_session; sd_seat_can_multi_session; sd_seat_get_active; sd_seat_get_sessions; sd_session_get_seat; sd_session_get_uid; sd_session_is_active; sd_uid_get_seats; sd_uid_get_sessions; sd_uid_get_state; sd_uid_is_on_seat; local: *; }; LIBSYSTEMD_LOGIN_38 { global: sd_pid_get_unit; sd_session_get_service; } LIBSYSTEMD_LOGIN_31; LIBSYSTEMD_LOGIN_43 { global: sd_session_get_type; sd_session_get_class; sd_session_get_display; } LIBSYSTEMD_LOGIN_38; LIBSYSTEMD_LOGIN_186 { global: sd_session_get_state; sd_seat_can_tty; sd_seat_can_graphical; } LIBSYSTEMD_LOGIN_43; LIBSYSTEMD_LOGIN_198 { global: sd_session_get_tty; } LIBSYSTEMD_LOGIN_186; LIBSYSTEMD_LOGIN_201 { global: sd_login_monitor_get_events; sd_login_monitor_get_timeout; } LIBSYSTEMD_LOGIN_198; LIBSYSTEMD_LOGIN_202 { global: sd_pid_get_user_unit; sd_pid_get_machine_name; } LIBSYSTEMD_LOGIN_201; LIBSYSTEMD_LOGIN_203 { global: sd_get_machine_names; } LIBSYSTEMD_LOGIN_202; LIBSYSTEMD_LOGIN_205 { global: sd_pid_get_slice; } LIBSYSTEMD_LOGIN_203; LIBSYSTEMD_LOGIN_207 { global: sd_session_get_vt; } LIBSYSTEMD_LOGIN_205; systemd-229/src/compat-libs/linkwarning.h000066400000000000000000000025031265713322000205560ustar00rootroot00000000000000/*** This file is part of systemd, but is heavily based on glibc's libc-symbols.h. Copyright (C) 1995-1998,2000-2006,2008,2009 Free Software Foundation, Inc systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #define __make_section_unallocated(section_string) \ asm (".section " section_string "\n\t.previous"); #define __sec_comment "\n#APP\n\t#" #define link_warning(symbol, msg) \ __make_section_unallocated (".gnu.warning." #symbol) \ static const char __evoke_link_warning_##symbol[] \ __attribute__ ((used, section (".gnu.warning." #symbol __sec_comment))) \ = msg #define obsolete_lib(name, lib) \ link_warning(name, #name " was moved to libsystemd. Do not use " #lib ".") systemd-229/src/core/000077500000000000000000000000001265713322000146005ustar00rootroot00000000000000systemd-229/src/core/.gitignore000066400000000000000000000000561265713322000165710ustar00rootroot00000000000000/macros.systemd /triggers.systemd /systemd.pc systemd-229/src/core/Makefile000077700000000000000000000000001265713322000201062../Makefileustar00rootroot00000000000000systemd-229/src/core/audit-fd.c000066400000000000000000000032131265713322000164400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "audit-fd.h" #ifdef HAVE_AUDIT #include #include #include "fd-util.h" #include "log.h" #include "util.h" static bool initialized = false; static int audit_fd; int get_audit_fd(void) { if (!initialized) { audit_fd = audit_open(); if (audit_fd < 0) { if (errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT) log_error_errno(errno, "Failed to connect to audit log: %m"); audit_fd = errno ? -errno : -EINVAL; } initialized = true; } return audit_fd; } void close_audit_fd(void) { if (initialized && audit_fd >= 0) safe_close(audit_fd); initialized = true; audit_fd = -ECONNRESET; } #else int get_audit_fd(void) { return -EAFNOSUPPORT; } void close_audit_fd(void) { } #endif systemd-229/src/core/audit-fd.h000066400000000000000000000014201265713322000164430ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int get_audit_fd(void); void close_audit_fd(void); systemd-229/src/core/automount.c000066400000000000000000001015211265713322000167770ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "async.h" #include "automount.h" #include "bus-error.h" #include "bus-util.h" #include "dbus-automount.h" #include "fd-util.h" #include "formats-util.h" #include "io-util.h" #include "label.h" #include "mkdir.h" #include "mount-util.h" #include "mount.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "special.h" #include "stdio-util.h" #include "string-table.h" #include "string-util.h" #include "unit-name.h" #include "unit.h" static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = { [AUTOMOUNT_DEAD] = UNIT_INACTIVE, [AUTOMOUNT_WAITING] = UNIT_ACTIVE, [AUTOMOUNT_RUNNING] = UNIT_ACTIVE, [AUTOMOUNT_FAILED] = UNIT_FAILED }; struct expire_data { int dev_autofs_fd; int ioctl_fd; }; static inline void expire_data_free(struct expire_data *data) { if (!data) return; safe_close(data->dev_autofs_fd); safe_close(data->ioctl_fd); free(data); } DEFINE_TRIVIAL_CLEANUP_FUNC(struct expire_data*, expire_data_free); static int open_dev_autofs(Manager *m); static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata); static void automount_init(Unit *u) { Automount *a = AUTOMOUNT(u); assert(u); assert(u->load_state == UNIT_STUB); a->pipe_fd = -1; a->directory_mode = 0755; UNIT(a)->ignore_on_isolate = true; } static int automount_send_ready(Automount *a, Set *tokens, int status); static void unmount_autofs(Automount *a) { int r; assert(a); if (a->pipe_fd < 0) return; automount_send_ready(a, a->tokens, -EHOSTDOWN); automount_send_ready(a, a->expire_tokens, -EHOSTDOWN); a->pipe_event_source = sd_event_source_unref(a->pipe_event_source); a->pipe_fd = safe_close(a->pipe_fd); /* If we reload/reexecute things we keep the mount point * around */ if (a->where && (UNIT(a)->manager->exit_code != MANAGER_RELOAD && UNIT(a)->manager->exit_code != MANAGER_REEXECUTE)) { r = repeat_unmount(a->where, MNT_DETACH); if (r < 0) log_error_errno(r, "Failed to unmount: %m"); } } static void automount_done(Unit *u) { Automount *a = AUTOMOUNT(u); assert(a); unmount_autofs(a); a->where = mfree(a->where); a->tokens = set_free(a->tokens); a->expire_tokens = set_free(a->expire_tokens); a->expire_event_source = sd_event_source_unref(a->expire_event_source); } static int automount_add_mount_links(Automount *a) { _cleanup_free_ char *parent = NULL; assert(a); parent = dirname_malloc(a->where); if (!parent) return -ENOMEM; return unit_require_mounts_for(UNIT(a), parent); } static int automount_add_default_dependencies(Automount *a) { int r; assert(a); if (!UNIT(a)->default_dependencies) return 0; if (UNIT(a)->manager->running_as != MANAGER_SYSTEM) return 0; r = unit_add_two_dependencies_by_name(UNIT(a), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true); if (r < 0) return r; return 0; } static int automount_verify(Automount *a) { _cleanup_free_ char *e = NULL; int r; assert(a); if (UNIT(a)->load_state != UNIT_LOADED) return 0; if (path_equal(a->where, "/")) { log_unit_error(UNIT(a), "Cannot have an automount unit for the root directory. Refusing."); return -EINVAL; } r = unit_name_from_path(a->where, ".automount", &e); if (r < 0) return log_unit_error(UNIT(a), "Failed to generate unit name from path: %m"); if (!unit_has_name(UNIT(a), e)) { log_unit_error(UNIT(a), "Where= setting doesn't match unit name. Refusing."); return -EINVAL; } return 0; } static int automount_load(Unit *u) { Automount *a = AUTOMOUNT(u); int r; assert(u); assert(u->load_state == UNIT_STUB); /* Load a .automount file */ r = unit_load_fragment_and_dropin_optional(u); if (r < 0) return r; if (u->load_state == UNIT_LOADED) { Unit *x; if (!a->where) { r = unit_name_to_path(u->id, &a->where); if (r < 0) return r; } path_kill_slashes(a->where); r = unit_load_related_unit(u, ".mount", &x); if (r < 0) return r; r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, x, true); if (r < 0) return r; r = automount_add_mount_links(a); if (r < 0) return r; r = automount_add_default_dependencies(a); if (r < 0) return r; } return automount_verify(a); } static void automount_set_state(Automount *a, AutomountState state) { AutomountState old_state; assert(a); old_state = a->state; a->state = state; if (state != AUTOMOUNT_WAITING && state != AUTOMOUNT_RUNNING) unmount_autofs(a); if (state != old_state) log_unit_debug(UNIT(a), "Changed %s -> %s", automount_state_to_string(old_state), automount_state_to_string(state)); unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], true); } static int automount_coldplug(Unit *u) { Automount *a = AUTOMOUNT(u); int r; assert(a); assert(a->state == AUTOMOUNT_DEAD); if (a->deserialized_state != a->state) { r = open_dev_autofs(u->manager); if (r < 0) return r; if (a->deserialized_state == AUTOMOUNT_WAITING || a->deserialized_state == AUTOMOUNT_RUNNING) { assert(a->pipe_fd >= 0); r = sd_event_add_io(u->manager->event, &a->pipe_event_source, a->pipe_fd, EPOLLIN, automount_dispatch_io, u); if (r < 0) return r; (void) sd_event_source_set_description(a->pipe_event_source, "automount-io"); } automount_set_state(a, a->deserialized_state); } return 0; } static void automount_dump(Unit *u, FILE *f, const char *prefix) { char time_string[FORMAT_TIMESPAN_MAX]; Automount *a = AUTOMOUNT(u); assert(a); fprintf(f, "%sAutomount State: %s\n" "%sResult: %s\n" "%sWhere: %s\n" "%sDirectoryMode: %04o\n" "%sTimeoutIdleUSec: %s\n", prefix, automount_state_to_string(a->state), prefix, automount_result_to_string(a->result), prefix, a->where, prefix, a->directory_mode, prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, a->timeout_idle_usec, USEC_PER_SEC)); } static void automount_enter_dead(Automount *a, AutomountResult f) { assert(a); if (f != AUTOMOUNT_SUCCESS) a->result = f; automount_set_state(a, a->result != AUTOMOUNT_SUCCESS ? AUTOMOUNT_FAILED : AUTOMOUNT_DEAD); } static int open_dev_autofs(Manager *m) { struct autofs_dev_ioctl param; assert(m); if (m->dev_autofs_fd >= 0) return m->dev_autofs_fd; label_fix("/dev/autofs", false, false); m->dev_autofs_fd = open("/dev/autofs", O_CLOEXEC|O_RDONLY); if (m->dev_autofs_fd < 0) return log_error_errno(errno, "Failed to open /dev/autofs: %m"); init_autofs_dev_ioctl(¶m); if (ioctl(m->dev_autofs_fd, AUTOFS_DEV_IOCTL_VERSION, ¶m) < 0) { m->dev_autofs_fd = safe_close(m->dev_autofs_fd); return -errno; } log_debug("Autofs kernel version %i.%i", param.ver_major, param.ver_minor); return m->dev_autofs_fd; } static int open_ioctl_fd(int dev_autofs_fd, const char *where, dev_t devid) { struct autofs_dev_ioctl *param; size_t l; assert(dev_autofs_fd >= 0); assert(where); l = sizeof(struct autofs_dev_ioctl) + strlen(where) + 1; param = alloca(l); init_autofs_dev_ioctl(param); param->size = l; param->ioctlfd = -1; param->openmount.devid = devid; strcpy(param->path, where); if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_OPENMOUNT, param) < 0) return -errno; if (param->ioctlfd < 0) return -EIO; (void) fd_cloexec(param->ioctlfd, true); return param->ioctlfd; } static int autofs_protocol(int dev_autofs_fd, int ioctl_fd) { uint32_t major, minor; struct autofs_dev_ioctl param; assert(dev_autofs_fd >= 0); assert(ioctl_fd >= 0); init_autofs_dev_ioctl(¶m); param.ioctlfd = ioctl_fd; if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOVER, ¶m) < 0) return -errno; major = param.protover.version; init_autofs_dev_ioctl(¶m); param.ioctlfd = ioctl_fd; if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOSUBVER, ¶m) < 0) return -errno; minor = param.protosubver.sub_version; log_debug("Autofs protocol version %i.%i", major, minor); return 0; } static int autofs_set_timeout(int dev_autofs_fd, int ioctl_fd, usec_t usec) { struct autofs_dev_ioctl param; assert(dev_autofs_fd >= 0); assert(ioctl_fd >= 0); init_autofs_dev_ioctl(¶m); param.ioctlfd = ioctl_fd; /* Convert to seconds, rounding up. */ param.timeout.timeout = (usec + USEC_PER_SEC - 1) / USEC_PER_SEC; if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_TIMEOUT, ¶m) < 0) return -errno; return 0; } static int autofs_send_ready(int dev_autofs_fd, int ioctl_fd, uint32_t token, int status) { struct autofs_dev_ioctl param; assert(dev_autofs_fd >= 0); assert(ioctl_fd >= 0); init_autofs_dev_ioctl(¶m); param.ioctlfd = ioctl_fd; if (status) { param.fail.token = token; param.fail.status = status; } else param.ready.token = token; if (ioctl(dev_autofs_fd, status ? AUTOFS_DEV_IOCTL_FAIL : AUTOFS_DEV_IOCTL_READY, ¶m) < 0) return -errno; return 0; } static int automount_send_ready(Automount *a, Set *tokens, int status) { _cleanup_close_ int ioctl_fd = -1; unsigned token; int r; assert(a); assert(status <= 0); if (set_isempty(tokens)) return 0; ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id); if (ioctl_fd < 0) return ioctl_fd; if (status) log_unit_debug_errno(UNIT(a), status, "Sending failure: %m"); else log_unit_debug(UNIT(a), "Sending success."); r = 0; /* Autofs thankfully does not hand out 0 as a token */ while ((token = PTR_TO_UINT(set_steal_first(tokens)))) { int k; /* Autofs fun fact II: * * if you pass a positive status code here, the kernel will * freeze! Yay! */ k = autofs_send_ready(UNIT(a)->manager->dev_autofs_fd, ioctl_fd, token, status); if (k < 0) r = k; } return r; } static int automount_start_expire(Automount *a); int automount_update_mount(Automount *a, MountState old_state, MountState state) { int r; assert(a); switch (state) { case MOUNT_MOUNTED: case MOUNT_REMOUNTING: automount_send_ready(a, a->tokens, 0); r = automount_start_expire(a); if (r < 0) log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m"); break; case MOUNT_DEAD: case MOUNT_UNMOUNTING: case MOUNT_MOUNTING_SIGTERM: case MOUNT_MOUNTING_SIGKILL: case MOUNT_REMOUNTING_SIGTERM: case MOUNT_REMOUNTING_SIGKILL: case MOUNT_UNMOUNTING_SIGTERM: case MOUNT_UNMOUNTING_SIGKILL: case MOUNT_FAILED: if (old_state != state) automount_send_ready(a, a->tokens, -ENODEV); (void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF); break; default: break; } switch (state) { case MOUNT_DEAD: automount_send_ready(a, a->expire_tokens, 0); break; case MOUNT_MOUNTING: case MOUNT_MOUNTING_DONE: case MOUNT_MOUNTING_SIGTERM: case MOUNT_MOUNTING_SIGKILL: case MOUNT_REMOUNTING_SIGTERM: case MOUNT_REMOUNTING_SIGKILL: case MOUNT_UNMOUNTING_SIGTERM: case MOUNT_UNMOUNTING_SIGKILL: case MOUNT_FAILED: if (old_state != state) automount_send_ready(a, a->expire_tokens, -ENODEV); break; default: break; } return 0; } static void automount_enter_waiting(Automount *a) { _cleanup_close_ int ioctl_fd = -1; int p[2] = { -1, -1 }; char name[sizeof("systemd-")-1 + DECIMAL_STR_MAX(pid_t) + 1]; char options[sizeof("fd=,pgrp=,minproto=5,maxproto=5,direct")-1 + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t) + 1]; bool mounted = false; int r, dev_autofs_fd; struct stat st; assert(a); assert(a->pipe_fd < 0); assert(a->where); set_clear(a->tokens); r = unit_fail_if_symlink(UNIT(a), a->where); if (r < 0) goto fail; (void) mkdir_p_label(a->where, 0555); unit_warn_if_dir_nonempty(UNIT(a), a->where); dev_autofs_fd = open_dev_autofs(UNIT(a)->manager); if (dev_autofs_fd < 0) { r = dev_autofs_fd; goto fail; } if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) { r = -errno; goto fail; } xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp()); xsprintf(name, "systemd-"PID_FMT, getpid()); if (mount(name, a->where, "autofs", 0, options) < 0) { r = -errno; goto fail; } mounted = true; p[1] = safe_close(p[1]); if (stat(a->where, &st) < 0) { r = -errno; goto fail; } ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev); if (ioctl_fd < 0) { r = ioctl_fd; goto fail; } r = autofs_protocol(dev_autofs_fd, ioctl_fd); if (r < 0) goto fail; r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, a->timeout_idle_usec); if (r < 0) goto fail; /* Autofs fun fact: * * Unless we close the ioctl fd here, for some weird reason * the direct mount will not receive events from the * kernel. */ r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a); if (r < 0) goto fail; (void) sd_event_source_set_description(a->pipe_event_source, "automount-io"); a->pipe_fd = p[0]; a->dev_id = st.st_dev; automount_set_state(a, AUTOMOUNT_WAITING); return; fail: log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m"); safe_close_pair(p); if (mounted) { r = repeat_unmount(a->where, MNT_DETACH); if (r < 0) log_error_errno(r, "Failed to unmount, ignoring: %m"); } automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES); } static void *expire_thread(void *p) { struct autofs_dev_ioctl param; _cleanup_(expire_data_freep) struct expire_data *data = (struct expire_data*)p; int r; assert(data->dev_autofs_fd >= 0); assert(data->ioctl_fd >= 0); init_autofs_dev_ioctl(¶m); param.ioctlfd = data->ioctl_fd; do { r = ioctl(data->dev_autofs_fd, AUTOFS_DEV_IOCTL_EXPIRE, ¶m); } while (r >= 0); if (errno != EAGAIN) log_warning_errno(errno, "Failed to expire automount, ignoring: %m"); return NULL; } static int automount_dispatch_expire(sd_event_source *source, usec_t usec, void *userdata) { Automount *a = AUTOMOUNT(userdata); _cleanup_(expire_data_freep) struct expire_data *data = NULL; int r; assert(a); assert(source == a->expire_event_source); data = new0(struct expire_data, 1); if (!data) return log_oom(); data->ioctl_fd = -1; data->dev_autofs_fd = fcntl(UNIT(a)->manager->dev_autofs_fd, F_DUPFD_CLOEXEC, 3); if (data->dev_autofs_fd < 0) return log_unit_error_errno(UNIT(a), errno, "Failed to duplicate autofs fd: %m"); data->ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id); if (data->ioctl_fd < 0) return log_unit_error_errno(UNIT(a), data->ioctl_fd, "Couldn't open autofs ioctl fd: %m"); r = asynchronous_job(expire_thread, data); if (r < 0) return log_unit_error_errno(UNIT(a), r, "Failed to start expire job: %m"); data = NULL; return automount_start_expire(a); } static int automount_start_expire(Automount *a) { int r; usec_t timeout; assert(a); if (a->timeout_idle_usec == 0) return 0; timeout = now(CLOCK_MONOTONIC) + MAX(a->timeout_idle_usec/3, USEC_PER_SEC); if (a->expire_event_source) { r = sd_event_source_set_time(a->expire_event_source, timeout); if (r < 0) return r; return sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_ONESHOT); } r = sd_event_add_time( UNIT(a)->manager->event, &a->expire_event_source, CLOCK_MONOTONIC, timeout, 0, automount_dispatch_expire, a); if (r < 0) return r; (void) sd_event_source_set_description(a->expire_event_source, "automount-expire"); return 0; } static void automount_enter_runnning(Automount *a) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; struct stat st; int r; assert(a); /* We don't take mount requests anymore if we are supposed to * shut down anyway */ if (unit_stop_pending(UNIT(a))) { log_unit_debug(UNIT(a), "Suppressing automount request since unit stop is scheduled."); automount_send_ready(a, a->tokens, -EHOSTDOWN); automount_send_ready(a, a->expire_tokens, -EHOSTDOWN); return; } mkdir_p_label(a->where, a->directory_mode); /* Before we do anything, let's see if somebody is playing games with us? */ if (lstat(a->where, &st) < 0) { log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m"); goto fail; } if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id) log_unit_info(UNIT(a), "Automount point already active?"); else { Unit *trigger; trigger = UNIT_TRIGGER(UNIT(a)); if (!trigger) { log_unit_error(UNIT(a), "Unit to trigger vanished."); goto fail; } r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL); if (r < 0) { log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r)); goto fail; } } automount_set_state(a, AUTOMOUNT_RUNNING); return; fail: automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES); } static int automount_start(Unit *u) { Automount *a = AUTOMOUNT(u); Unit *trigger; assert(a); assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED); if (path_is_mount_point(a->where, 0) > 0) { log_unit_error(u, "Path %s is already a mount point, refusing start.", a->where); return -EEXIST; } trigger = UNIT_TRIGGER(u); if (!trigger || trigger->load_state != UNIT_LOADED) { log_unit_error(u, "Refusing to start, unit to trigger not loaded."); return -ENOENT; } a->result = AUTOMOUNT_SUCCESS; automount_enter_waiting(a); return 1; } static int automount_stop(Unit *u) { Automount *a = AUTOMOUNT(u); assert(a); assert(a->state == AUTOMOUNT_WAITING || a->state == AUTOMOUNT_RUNNING); automount_enter_dead(a, AUTOMOUNT_SUCCESS); return 1; } static int automount_serialize(Unit *u, FILE *f, FDSet *fds) { Automount *a = AUTOMOUNT(u); Iterator i; void *p; int r; assert(a); assert(f); assert(fds); unit_serialize_item(u, f, "state", automount_state_to_string(a->state)); unit_serialize_item(u, f, "result", automount_result_to_string(a->result)); unit_serialize_item_format(u, f, "dev-id", "%u", (unsigned) a->dev_id); SET_FOREACH(p, a->tokens, i) unit_serialize_item_format(u, f, "token", "%u", PTR_TO_UINT(p)); SET_FOREACH(p, a->expire_tokens, i) unit_serialize_item_format(u, f, "expire-token", "%u", PTR_TO_UINT(p)); r = unit_serialize_item_fd(u, f, fds, "pipe-fd", a->pipe_fd); if (r < 0) return r; return 0; } static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Automount *a = AUTOMOUNT(u); int r; assert(a); assert(fds); if (streq(key, "state")) { AutomountState state; state = automount_state_from_string(value); if (state < 0) log_unit_debug(u, "Failed to parse state value: %s", value); else a->deserialized_state = state; } else if (streq(key, "result")) { AutomountResult f; f = automount_result_from_string(value); if (f < 0) log_unit_debug(u, "Failed to parse result value: %s", value); else if (f != AUTOMOUNT_SUCCESS) a->result = f; } else if (streq(key, "dev-id")) { unsigned d; if (safe_atou(value, &d) < 0) log_unit_debug(u, "Failed to parse dev-id value: %s", value); else a->dev_id = (unsigned) d; } else if (streq(key, "token")) { unsigned token; if (safe_atou(value, &token) < 0) log_unit_debug(u, "Failed to parse token value: %s", value); else { r = set_ensure_allocated(&a->tokens, NULL); if (r < 0) { log_oom(); return 0; } r = set_put(a->tokens, UINT_TO_PTR(token)); if (r < 0) log_unit_error_errno(u, r, "Failed to add token to set: %m"); } } else if (streq(key, "expire-token")) { unsigned token; if (safe_atou(value, &token) < 0) log_unit_debug(u, "Failed to parse token value: %s", value); else { r = set_ensure_allocated(&a->expire_tokens, NULL); if (r < 0) { log_oom(); return 0; } r = set_put(a->expire_tokens, UINT_TO_PTR(token)); if (r < 0) log_unit_error_errno(u, r, "Failed to add expire token to set: %m"); } } else if (streq(key, "pipe-fd")) { int fd; if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse pipe-fd value: %s", value); else { safe_close(a->pipe_fd); a->pipe_fd = fdset_remove(fds, fd); } } else log_unit_debug(u, "Unknown serialization key: %s", key); return 0; } static UnitActiveState automount_active_state(Unit *u) { assert(u); return state_translation_table[AUTOMOUNT(u)->state]; } static const char *automount_sub_state_to_string(Unit *u) { assert(u); return automount_state_to_string(AUTOMOUNT(u)->state); } static bool automount_check_gc(Unit *u) { assert(u); if (!UNIT_TRIGGER(u)) return false; return UNIT_VTABLE(UNIT_TRIGGER(u))->check_gc(UNIT_TRIGGER(u)); } static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; union autofs_v5_packet_union packet; Automount *a = AUTOMOUNT(userdata); struct stat st; Unit *trigger; int r; assert(a); assert(fd == a->pipe_fd); if (events != EPOLLIN) { log_unit_error(UNIT(a), "Got invalid poll event %"PRIu32" on pipe (fd=%d)", events, fd); goto fail; } r = loop_read_exact(a->pipe_fd, &packet, sizeof(packet), true); if (r < 0) { log_unit_error_errno(UNIT(a), r, "Invalid read from pipe: %m"); goto fail; } switch (packet.hdr.type) { case autofs_ptype_missing_direct: if (packet.v5_packet.pid > 0) { _cleanup_free_ char *p = NULL; get_process_comm(packet.v5_packet.pid, &p); log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p)); } else log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where); r = set_ensure_allocated(&a->tokens, NULL); if (r < 0) { log_unit_error(UNIT(a), "Failed to allocate token set."); goto fail; } r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token)); if (r < 0) { log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m"); goto fail; } automount_enter_runnning(a); break; case autofs_ptype_expire_direct: log_unit_debug(UNIT(a), "Got direct umount request on %s", a->where); (void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF); r = set_ensure_allocated(&a->expire_tokens, NULL); if (r < 0) { log_unit_error(UNIT(a), "Failed to allocate token set."); goto fail; } r = set_put(a->expire_tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token)); if (r < 0) { log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m"); goto fail; } /* Before we do anything, let's see if somebody is playing games with us? */ if (lstat(a->where, &st) < 0) { log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m"); goto fail; } if (!S_ISDIR(st.st_mode) || st.st_dev == a->dev_id) { log_unit_info(UNIT(a), "Automount point already unmounted?"); automount_send_ready(a, a->expire_tokens, 0); break; } trigger = UNIT_TRIGGER(UNIT(a)); if (!trigger) { log_unit_error(UNIT(a), "Unit to trigger vanished."); goto fail; } r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, &error, NULL); if (r < 0) { log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r)); goto fail; } break; default: log_unit_error(UNIT(a), "Received unknown automount request %i", packet.hdr.type); break; } return 0; fail: automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES); return 0; } static void automount_shutdown(Manager *m) { assert(m); m->dev_autofs_fd = safe_close(m->dev_autofs_fd); } static void automount_reset_failed(Unit *u) { Automount *a = AUTOMOUNT(u); assert(a); if (a->state == AUTOMOUNT_FAILED) automount_set_state(a, AUTOMOUNT_DEAD); a->result = AUTOMOUNT_SUCCESS; } static bool automount_supported(void) { static int supported = -1; if (supported < 0) supported = access("/dev/autofs", F_OK) >= 0; return supported; } static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = { [AUTOMOUNT_SUCCESS] = "success", [AUTOMOUNT_FAILURE_RESOURCES] = "resources" }; DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult); const UnitVTable automount_vtable = { .object_size = sizeof(Automount), .sections = "Unit\0" "Automount\0" "Install\0", .no_alias = true, .no_instances = true, .init = automount_init, .load = automount_load, .done = automount_done, .coldplug = automount_coldplug, .dump = automount_dump, .start = automount_start, .stop = automount_stop, .serialize = automount_serialize, .deserialize_item = automount_deserialize_item, .active_state = automount_active_state, .sub_state_to_string = automount_sub_state_to_string, .check_gc = automount_check_gc, .reset_failed = automount_reset_failed, .bus_vtable = bus_automount_vtable, .shutdown = automount_shutdown, .supported = automount_supported, .status_message_formats = { .finished_start_job = { [JOB_DONE] = "Set up automount %s.", [JOB_FAILED] = "Failed to set up automount %s.", }, .finished_stop_job = { [JOB_DONE] = "Unset automount %s.", [JOB_FAILED] = "Failed to unset automount %s.", }, }, }; systemd-229/src/core/automount.h000066400000000000000000000031411265713322000170030ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Automount Automount; #include "unit.h" typedef enum AutomountResult { AUTOMOUNT_SUCCESS, AUTOMOUNT_FAILURE_RESOURCES, _AUTOMOUNT_RESULT_MAX, _AUTOMOUNT_RESULT_INVALID = -1 } AutomountResult; struct Automount { Unit meta; AutomountState state, deserialized_state; char *where; usec_t timeout_idle_usec; int pipe_fd; sd_event_source *pipe_event_source; mode_t directory_mode; dev_t dev_id; Set *tokens; Set *expire_tokens; sd_event_source *expire_event_source; AutomountResult result; }; extern const UnitVTable automount_vtable; int automount_update_mount(Automount *a, MountState old_state, MountState state); const char* automount_result_to_string(AutomountResult i) _const_; AutomountResult automount_result_from_string(const char *s) _pure_; systemd-229/src/core/bus-endpoint.c000066400000000000000000000076501265713322000173630ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Daniel Mack systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "bus-endpoint.h" #include "bus-kernel.h" #include "bus-policy.h" #include "kdbus.h" int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep) { struct kdbus_cmd *update; struct kdbus_item *n; BusEndpointPolicy *po; Iterator i; size_t size; int r; size = ALIGN8(offsetof(struct kdbus_cmd, items)); HASHMAP_FOREACH(po, ep->policy_hash, i) { size += ALIGN8(offsetof(struct kdbus_item, str) + strlen(po->name) + 1); size += ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access)); } update = alloca0_align(size, 8); update->size = size; n = update->items; HASHMAP_FOREACH(po, ep->policy_hash, i) { n->type = KDBUS_ITEM_NAME; n->size = offsetof(struct kdbus_item, str) + strlen(po->name) + 1; strcpy(n->str, po->name); n = KDBUS_ITEM_NEXT(n); n->type = KDBUS_ITEM_POLICY_ACCESS; n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access); n->policy_access.type = KDBUS_POLICY_ACCESS_USER; n->policy_access.access = bus_kernel_translate_access(po->access); n->policy_access.id = uid; n = KDBUS_ITEM_NEXT(n); } r = ioctl(fd, KDBUS_CMD_ENDPOINT_UPDATE, update); if (r < 0) return -errno; return 0; } int bus_endpoint_new(BusEndpoint **ep) { assert(ep); *ep = new0(BusEndpoint, 1); if (!*ep) return -ENOMEM; return 0; } int bus_endpoint_add_policy(BusEndpoint *ep, const char *name, BusPolicyAccess access) { _cleanup_free_ BusEndpointPolicy *po = NULL; _cleanup_free_ char *key = NULL; int r; assert(ep); assert(name); assert(access > _BUS_POLICY_ACCESS_INVALID && access < _BUS_POLICY_ACCESS_MAX); /* check if we already have this name in the policy list. If we do, see if the new access level * is higher than the exising one, and upgrade the entry in that case. Otherwise, do nothing. */ if (ep->policy_hash) { po = hashmap_get(ep->policy_hash, name); if (po) { if (po->access < access) po->access = access; return 0; } } else { ep->policy_hash = hashmap_new(&string_hash_ops); if (!ep->policy_hash) return -ENOMEM; } po = new0(BusEndpointPolicy, 1); if (!po) return -ENOMEM; key = strdup(name); if (!key) return -ENOMEM; po->name = key; po->access = access; r = hashmap_put(ep->policy_hash, key, po); if (r < 0) return r; po = NULL; key = NULL; return 0; } void bus_endpoint_free(BusEndpoint *endpoint) { if (!endpoint) return; hashmap_free_free_free(endpoint->policy_hash); free(endpoint); } systemd-229/src/core/bus-endpoint.h000066400000000000000000000023441265713322000173630ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Daniel Mack systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct BusEndpoint BusEndpoint; typedef struct BusEndpointPolicy BusEndpointPolicy; #include "bus-policy.h" #include "hashmap.h" struct BusEndpointPolicy { char *name; BusPolicyAccess access; }; struct BusEndpoint { Hashmap *policy_hash; }; int bus_endpoint_new(BusEndpoint **ep); void bus_endpoint_free(BusEndpoint *endpoint); int bus_endpoint_add_policy(BusEndpoint *ep, const char *name, BusPolicyAccess access); int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep); systemd-229/src/core/bus-policy.c000066400000000000000000000127541265713322000170430ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Daniel Mack systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "bus-kernel.h" #include "bus-policy.h" #include "kdbus.h" #include "string-table.h" #include "user-util.h" #include "util.h" int bus_kernel_translate_access(BusPolicyAccess access) { assert(access >= 0); assert(access < _BUS_POLICY_ACCESS_MAX); switch (access) { case BUS_POLICY_ACCESS_SEE: return KDBUS_POLICY_SEE; case BUS_POLICY_ACCESS_TALK: return KDBUS_POLICY_TALK; case BUS_POLICY_ACCESS_OWN: return KDBUS_POLICY_OWN; default: assert_not_reached("Unknown policy access"); } } int bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) { int r; assert(policy); assert(item); switch (policy->type) { case BUSNAME_POLICY_TYPE_USER: { const char *user = policy->name; uid_t uid; r = get_user_creds(&user, &uid, NULL, NULL, NULL); if (r < 0) return r; item->policy_access.type = KDBUS_POLICY_ACCESS_USER; item->policy_access.id = uid; break; } case BUSNAME_POLICY_TYPE_GROUP: { const char *group = policy->name; gid_t gid; r = get_group_creds(&group, &gid); if (r < 0) return r; item->policy_access.type = KDBUS_POLICY_ACCESS_GROUP; item->policy_access.id = gid; break; } default: assert_not_reached("Unknown policy type"); } item->policy_access.access = bus_kernel_translate_access(policy->access); return 0; } int bus_kernel_make_starter( int fd, const char *name, bool activating, bool accept_fd, BusNamePolicy *policy, BusPolicyAccess world_policy) { struct kdbus_cmd_free cmd_free = { .size = sizeof(cmd_free) }; struct kdbus_cmd_hello *hello; struct kdbus_item *n; size_t policy_cnt = 0; BusNamePolicy *po; size_t size; int r; assert(fd >= 0); assert(name); LIST_FOREACH(policy, po, policy) policy_cnt++; if (world_policy >= 0) policy_cnt++; size = offsetof(struct kdbus_cmd_hello, items) + ALIGN8(offsetof(struct kdbus_item, str) + strlen(name) + 1) + policy_cnt * ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access)); hello = alloca0_align(size, 8); n = hello->items; strcpy(n->str, name); n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1; n->type = KDBUS_ITEM_NAME; n = KDBUS_ITEM_NEXT(n); LIST_FOREACH(policy, po, policy) { n->type = KDBUS_ITEM_POLICY_ACCESS; n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access); r = bus_kernel_translate_policy(po, n); if (r < 0) return r; n = KDBUS_ITEM_NEXT(n); } if (world_policy >= 0) { n->type = KDBUS_ITEM_POLICY_ACCESS; n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access); n->policy_access.type = KDBUS_POLICY_ACCESS_WORLD; n->policy_access.access = bus_kernel_translate_access(world_policy); } hello->size = size; hello->flags = (activating ? KDBUS_HELLO_ACTIVATOR : KDBUS_HELLO_POLICY_HOLDER) | (accept_fd ? KDBUS_HELLO_ACCEPT_FD : 0); hello->pool_size = KDBUS_POOL_SIZE; hello->attach_flags_send = _KDBUS_ATTACH_ANY; hello->attach_flags_recv = _KDBUS_ATTACH_ANY; if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) { if (errno == ENOTTY) /* Major API change */ return -ESOCKTNOSUPPORT; return -errno; } /* not interested in any output values */ cmd_free.offset = hello->offset; (void) ioctl(fd, KDBUS_CMD_FREE, &cmd_free); /* The higher 32bit of the bus_flags fields are considered * 'incompatible flags'. Refuse them all for now. */ if (hello->bus_flags > 0xFFFFFFFFULL) return -ESOCKTNOSUPPORT; return fd; } static const char* const bus_policy_access_table[_BUS_POLICY_ACCESS_MAX] = { [BUS_POLICY_ACCESS_SEE] = "see", [BUS_POLICY_ACCESS_TALK] = "talk", [BUS_POLICY_ACCESS_OWN] = "own", }; DEFINE_STRING_TABLE_LOOKUP(bus_policy_access, BusPolicyAccess); systemd-229/src/core/bus-policy.h000066400000000000000000000036031265713322000170410ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Daniel Mack systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "kdbus.h" #include "list.h" #include "macro.h" typedef struct BusNamePolicy BusNamePolicy; typedef enum BusPolicyAccess { BUS_POLICY_ACCESS_SEE, BUS_POLICY_ACCESS_TALK, BUS_POLICY_ACCESS_OWN, _BUS_POLICY_ACCESS_MAX, _BUS_POLICY_ACCESS_INVALID = -1 } BusPolicyAccess; typedef enum BusNamePolicyType { BUSNAME_POLICY_TYPE_USER, BUSNAME_POLICY_TYPE_GROUP, _BUSNAME_POLICY_TYPE_MAX, _BUSNAME_POLICY_TYPE_INVALID = -1 } BusNamePolicyType; struct BusNamePolicy { BusNamePolicyType type; BusPolicyAccess access; char *name; LIST_FIELDS(BusNamePolicy, policy); }; int bus_kernel_translate_access(BusPolicyAccess access); int bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item); const char* bus_policy_access_to_string(BusPolicyAccess i) _const_; BusPolicyAccess bus_policy_access_from_string(const char *s) _pure_; int bus_kernel_make_starter( int fd, const char *name, bool activating, bool accept_fd, BusNamePolicy *policy, BusPolicyAccess world_policy); systemd-229/src/core/busname.c000066400000000000000000000752701265713322000164110ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "bus-internal.h" #include "bus-kernel.h" #include "bus-policy.h" #include "bus-util.h" #include "busname.h" #include "dbus-busname.h" #include "fd-util.h" #include "formats-util.h" #include "kdbus.h" #include "parse-util.h" #include "process-util.h" #include "service.h" #include "signal-util.h" #include "special.h" #include "string-table.h" #include "string-util.h" static const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = { [BUSNAME_DEAD] = UNIT_INACTIVE, [BUSNAME_MAKING] = UNIT_ACTIVATING, [BUSNAME_REGISTERED] = UNIT_ACTIVE, [BUSNAME_LISTENING] = UNIT_ACTIVE, [BUSNAME_RUNNING] = UNIT_ACTIVE, [BUSNAME_SIGTERM] = UNIT_DEACTIVATING, [BUSNAME_SIGKILL] = UNIT_DEACTIVATING, [BUSNAME_FAILED] = UNIT_FAILED }; static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); static int busname_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); static void busname_init(Unit *u) { BusName *n = BUSNAME(u); assert(u); assert(u->load_state == UNIT_STUB); n->starter_fd = -1; n->accept_fd = true; n->activating = true; n->timeout_usec = u->manager->default_timeout_start_usec; } static void busname_unwatch_control_pid(BusName *n) { assert(n); if (n->control_pid <= 0) return; unit_unwatch_pid(UNIT(n), n->control_pid); n->control_pid = 0; } static void busname_free_policy(BusName *n) { BusNamePolicy *p; assert(n); while ((p = n->policy)) { LIST_REMOVE(policy, n->policy, p); free(p->name); free(p); } } static void busname_close_fd(BusName *n) { assert(n); n->starter_event_source = sd_event_source_unref(n->starter_event_source); n->starter_fd = safe_close(n->starter_fd); } static void busname_done(Unit *u) { BusName *n = BUSNAME(u); assert(n); n->name = mfree(n->name); busname_free_policy(n); busname_unwatch_control_pid(n); busname_close_fd(n); unit_ref_unset(&n->service); n->timer_event_source = sd_event_source_unref(n->timer_event_source); } static int busname_arm_timer(BusName *n, usec_t usec) { int r; assert(n); if (n->timer_event_source) { r = sd_event_source_set_time(n->timer_event_source, usec); if (r < 0) return r; return sd_event_source_set_enabled(n->timer_event_source, SD_EVENT_ONESHOT); } if (usec == USEC_INFINITY) return 0; r = sd_event_add_time( UNIT(n)->manager->event, &n->timer_event_source, CLOCK_MONOTONIC, usec, 0, busname_dispatch_timer, n); if (r < 0) return r; (void) sd_event_source_set_description(n->timer_event_source, "busname-timer"); return 0; } static int busname_add_default_default_dependencies(BusName *n) { int r; assert(n); r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true); if (r < 0) return r; if (UNIT(n)->manager->running_as == MANAGER_SYSTEM) { r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true); if (r < 0) return r; } return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true); } static int busname_add_extras(BusName *n) { Unit *u = UNIT(n); int r; assert(n); if (!n->name) { r = unit_name_to_prefix(u->id, &n->name); if (r < 0) return r; } if (!u->description) { r = unit_set_description(u, n->name); if (r < 0) return r; } if (n->activating) { if (!UNIT_DEREF(n->service)) { Unit *x; r = unit_load_related_unit(u, ".service", &x); if (r < 0) return r; unit_ref_set(&n->service, x); } r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true); if (r < 0) return r; } if (u->default_dependencies) { r = busname_add_default_default_dependencies(n); if (r < 0) return r; } return 0; } static int busname_verify(BusName *n) { char *e; assert(n); if (UNIT(n)->load_state != UNIT_LOADED) return 0; if (!service_name_is_valid(n->name)) { log_unit_error(UNIT(n), "Name= setting is not a valid service name Refusing."); return -EINVAL; } e = strjoina(n->name, ".busname"); if (!unit_has_name(UNIT(n), e)) { log_unit_error(UNIT(n), "Name= setting doesn't match unit name. Refusing."); return -EINVAL; } return 0; } static int busname_load(Unit *u) { BusName *n = BUSNAME(u); int r; assert(u); assert(u->load_state == UNIT_STUB); r = unit_load_fragment_and_dropin(u); if (r < 0) return r; if (u->load_state == UNIT_LOADED) { /* This is a new unit? Then let's add in some extras */ r = busname_add_extras(n); if (r < 0) return r; } return busname_verify(n); } static void busname_dump(Unit *u, FILE *f, const char *prefix) { BusName *n = BUSNAME(u); assert(n); assert(f); fprintf(f, "%sBus Name State: %s\n" "%sResult: %s\n" "%sName: %s\n" "%sActivating: %s\n" "%sAccept FD: %s\n", prefix, busname_state_to_string(n->state), prefix, busname_result_to_string(n->result), prefix, n->name, prefix, yes_no(n->activating), prefix, yes_no(n->accept_fd)); if (n->control_pid > 0) fprintf(f, "%sControl PID: "PID_FMT"\n", prefix, n->control_pid); } static void busname_unwatch_fd(BusName *n) { int r; assert(n); if (!n->starter_event_source) return; r = sd_event_source_set_enabled(n->starter_event_source, SD_EVENT_OFF); if (r < 0) log_unit_debug_errno(UNIT(n), r, "Failed to disable event source: %m"); } static int busname_watch_fd(BusName *n) { int r; assert(n); if (n->starter_fd < 0) return 0; if (n->starter_event_source) { r = sd_event_source_set_enabled(n->starter_event_source, SD_EVENT_ON); if (r < 0) goto fail; } else { r = sd_event_add_io(UNIT(n)->manager->event, &n->starter_event_source, n->starter_fd, EPOLLIN, busname_dispatch_io, n); if (r < 0) goto fail; (void) sd_event_source_set_description(n->starter_event_source, "busname-starter"); } return 0; fail: log_unit_warning_errno(UNIT(n), r, "Failed to watch starter fd: %m"); busname_unwatch_fd(n); return r; } static int busname_open_fd(BusName *n) { _cleanup_free_ char *path = NULL; const char *mode; assert(n); if (n->starter_fd >= 0) return 0; mode = UNIT(n)->manager->running_as == MANAGER_SYSTEM ? "system" : "user"; n->starter_fd = bus_kernel_open_bus_fd(mode, &path); if (n->starter_fd < 0) return log_unit_warning_errno(UNIT(n), n->starter_fd, "Failed to open %s: %m", path ?: "kdbus"); return 0; } static void busname_set_state(BusName *n, BusNameState state) { BusNameState old_state; assert(n); old_state = n->state; n->state = state; if (!IN_SET(state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) { n->timer_event_source = sd_event_source_unref(n->timer_event_source); busname_unwatch_control_pid(n); } if (state != BUSNAME_LISTENING) busname_unwatch_fd(n); if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_MAKING, BUSNAME_REGISTERED, BUSNAME_RUNNING)) busname_close_fd(n); if (state != old_state) log_unit_debug(UNIT(n), "Changed %s -> %s", busname_state_to_string(old_state), busname_state_to_string(state)); unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true); } static int busname_coldplug(Unit *u) { BusName *n = BUSNAME(u); int r; assert(n); assert(n->state == BUSNAME_DEAD); if (n->deserialized_state == n->state) return 0; if (n->control_pid > 0 && pid_is_unwaited(n->control_pid) && IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) { r = unit_watch_pid(UNIT(n), n->control_pid); if (r < 0) return r; r = busname_arm_timer(n, usec_add(u->state_change_timestamp.monotonic, n->timeout_usec)); if (r < 0) return r; } if (IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_LISTENING, BUSNAME_REGISTERED, BUSNAME_RUNNING)) { r = busname_open_fd(n); if (r < 0) return r; } if (n->deserialized_state == BUSNAME_LISTENING) { r = busname_watch_fd(n); if (r < 0) return r; } busname_set_state(n, n->deserialized_state); return 0; } static int busname_make_starter(BusName *n, pid_t *_pid) { pid_t pid; int r; r = busname_arm_timer(n, usec_add(now(CLOCK_MONOTONIC), n->timeout_usec)); if (r < 0) goto fail; /* We have to resolve the user/group names out-of-process, * hence let's fork here. It's messy, but well, what can we * do? */ pid = fork(); if (pid < 0) return -errno; if (pid == 0) { int ret; (void) default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE, -1); (void) ignore_signals(SIGPIPE, -1); log_forget_fds(); r = bus_kernel_make_starter(n->starter_fd, n->name, n->activating, n->accept_fd, n->policy, n->policy_world); if (r < 0) { ret = EXIT_MAKE_STARTER; goto fail_child; } _exit(0); fail_child: log_open(); log_error_errno(r, "Failed to create starter connection at step %s: %m", exit_status_to_string(ret, EXIT_STATUS_SYSTEMD)); _exit(ret); } r = unit_watch_pid(UNIT(n), pid); if (r < 0) goto fail; *_pid = pid; return 0; fail: n->timer_event_source = sd_event_source_unref(n->timer_event_source); return r; } static void busname_enter_dead(BusName *n, BusNameResult f) { assert(n); if (f != BUSNAME_SUCCESS) n->result = f; busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD); } static void busname_enter_signal(BusName *n, BusNameState state, BusNameResult f) { KillContext kill_context = {}; int r; assert(n); if (f != BUSNAME_SUCCESS) n->result = f; kill_context_init(&kill_context); r = unit_kill_context(UNIT(n), &kill_context, state != BUSNAME_SIGTERM ? KILL_KILL : KILL_TERMINATE, -1, n->control_pid, false); if (r < 0) { log_unit_warning_errno(UNIT(n), r, "Failed to kill control process: %m"); goto fail; } if (r > 0) { r = busname_arm_timer(n, usec_add(now(CLOCK_MONOTONIC), n->timeout_usec)); if (r < 0) { log_unit_warning_errno(UNIT(n), r, "Failed to arm timer: %m"); goto fail; } busname_set_state(n, state); } else if (state == BUSNAME_SIGTERM) busname_enter_signal(n, BUSNAME_SIGKILL, BUSNAME_SUCCESS); else busname_enter_dead(n, BUSNAME_SUCCESS); return; fail: busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES); } static void busname_enter_listening(BusName *n) { int r; assert(n); if (n->activating) { r = busname_watch_fd(n); if (r < 0) { log_unit_warning_errno(UNIT(n), r, "Failed to watch names: %m"); goto fail; } busname_set_state(n, BUSNAME_LISTENING); } else busname_set_state(n, BUSNAME_REGISTERED); return; fail: busname_enter_signal(n, BUSNAME_SIGTERM, BUSNAME_FAILURE_RESOURCES); } static void busname_enter_making(BusName *n) { int r; assert(n); r = busname_open_fd(n); if (r < 0) goto fail; if (n->policy) { /* If there is a policy, we need to resolve user/group * names, which we can't do from PID1, hence let's * fork. */ busname_unwatch_control_pid(n); r = busname_make_starter(n, &n->control_pid); if (r < 0) { log_unit_warning_errno(UNIT(n), r, "Failed to fork 'making' task: %m"); goto fail; } busname_set_state(n, BUSNAME_MAKING); } else { /* If there is no policy, we can do everything * directly from PID 1, hence do so. */ r = bus_kernel_make_starter(n->starter_fd, n->name, n->activating, n->accept_fd, NULL, n->policy_world); if (r < 0) { log_unit_warning_errno(UNIT(n), r, "Failed to make starter: %m"); goto fail; } busname_enter_listening(n); } return; fail: busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES); } static void busname_enter_running(BusName *n) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; bool pending = false; Unit *other; Iterator i; int r; assert(n); if (!n->activating) return; /* We don't take connections anymore if we are supposed to * shut down anyway */ if (unit_stop_pending(UNIT(n))) { log_unit_debug(UNIT(n), "Suppressing activation request since unit stop is scheduled."); /* Flush all queued activation reqeuest by closing and reopening the connection */ bus_kernel_drop_one(n->starter_fd); busname_enter_listening(n); return; } /* If there's already a start pending don't bother to do * anything */ SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i) if (unit_active_or_pending(other)) { pending = true; break; } if (!pending) { if (!UNIT_ISSET(n->service)) { log_unit_error(UNIT(n), "Service to activate vanished, refusing activation."); r = -ENOENT; goto fail; } r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, &error, NULL); if (r < 0) goto fail; } busname_set_state(n, BUSNAME_RUNNING); return; fail: log_unit_warning(UNIT(n), "Failed to queue service startup job: %s", bus_error_message(&error, r)); busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES); } static int busname_start(Unit *u) { BusName *n = BUSNAME(u); assert(n); /* We cannot fulfill this request right now, try again later * please! */ if (IN_SET(n->state, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) return -EAGAIN; /* Already on it! */ if (n->state == BUSNAME_MAKING) return 0; if (n->activating && UNIT_ISSET(n->service)) { Service *service; service = SERVICE(UNIT_DEREF(n->service)); if (UNIT(service)->load_state != UNIT_LOADED) { log_unit_error(u, "Bus service %s not loaded, refusing.", UNIT(service)->id); return -ENOENT; } } assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED)); n->result = BUSNAME_SUCCESS; busname_enter_making(n); return 1; } static int busname_stop(Unit *u) { BusName *n = BUSNAME(u); assert(n); /* Already on it */ if (IN_SET(n->state, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) return 0; /* If there's already something running, we go directly into * kill mode. */ if (n->state == BUSNAME_MAKING) { busname_enter_signal(n, BUSNAME_SIGTERM, BUSNAME_SUCCESS); return -EAGAIN; } assert(IN_SET(n->state, BUSNAME_REGISTERED, BUSNAME_LISTENING, BUSNAME_RUNNING)); busname_enter_dead(n, BUSNAME_SUCCESS); return 1; } static int busname_serialize(Unit *u, FILE *f, FDSet *fds) { BusName *n = BUSNAME(u); int r; assert(n); assert(f); assert(fds); unit_serialize_item(u, f, "state", busname_state_to_string(n->state)); unit_serialize_item(u, f, "result", busname_result_to_string(n->result)); if (n->control_pid > 0) unit_serialize_item_format(u, f, "control-pid", PID_FMT, n->control_pid); r = unit_serialize_item_fd(u, f, fds, "starter-fd", n->starter_fd); if (r < 0) return r; return 0; } static int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { BusName *n = BUSNAME(u); assert(n); assert(key); assert(value); if (streq(key, "state")) { BusNameState state; state = busname_state_from_string(value); if (state < 0) log_unit_debug(u, "Failed to parse state value: %s", value); else n->deserialized_state = state; } else if (streq(key, "result")) { BusNameResult f; f = busname_result_from_string(value); if (f < 0) log_unit_debug(u, "Failed to parse result value: %s", value); else if (f != BUSNAME_SUCCESS) n->result = f; } else if (streq(key, "control-pid")) { pid_t pid; if (parse_pid(value, &pid) < 0) log_unit_debug(u, "Failed to parse control-pid value: %s", value); else n->control_pid = pid; } else if (streq(key, "starter-fd")) { int fd; if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse starter fd value: %s", value); else { safe_close(n->starter_fd); n->starter_fd = fdset_remove(fds, fd); } } else log_unit_debug(u, "Unknown serialization key: %s", key); return 0; } _pure_ static UnitActiveState busname_active_state(Unit *u) { assert(u); return state_translation_table[BUSNAME(u)->state]; } _pure_ static const char *busname_sub_state_to_string(Unit *u) { assert(u); return busname_state_to_string(BUSNAME(u)->state); } static int busname_peek_message(BusName *n) { struct kdbus_cmd_recv cmd_recv = { .size = sizeof(cmd_recv), .flags = KDBUS_RECV_PEEK, }; struct kdbus_cmd_free cmd_free = { .size = sizeof(cmd_free), }; const char *comm = NULL; struct kdbus_item *d; struct kdbus_msg *k; size_t start, ps, sz, delta; void *p = NULL; pid_t pid = 0; int r; /* Generate a friendly debug log message about which process * caused triggering of this bus name. This simply peeks the * metadata of the first queued message and logs it. */ assert(n); /* Let's shortcut things a bit, if debug logging is turned off * anyway. */ if (log_get_max_level() < LOG_DEBUG) return 0; r = ioctl(n->starter_fd, KDBUS_CMD_RECV, &cmd_recv); if (r < 0) { if (errno == EINTR || errno == EAGAIN) return 0; return log_unit_error_errno(UNIT(n), errno, "Failed to query activation message: %m"); } /* We map as late as possible, and unmap imemdiately after * use. On 32bit address space is scarce and we want to be * able to handle a lot of activator connections at the same * time, and hence shouldn't keep the mmap()s around for * longer than necessary. */ ps = page_size(); start = (cmd_recv.msg.offset / ps) * ps; delta = cmd_recv.msg.offset - start; sz = PAGE_ALIGN(delta + cmd_recv.msg.msg_size); p = mmap(NULL, sz, PROT_READ, MAP_SHARED, n->starter_fd, start); if (p == MAP_FAILED) { r = log_unit_error_errno(UNIT(n), errno, "Failed to map activation message: %m"); goto finish; } k = (struct kdbus_msg *) ((uint8_t *) p + delta); KDBUS_ITEM_FOREACH(d, k, items) { switch (d->type) { case KDBUS_ITEM_PIDS: pid = d->pids.pid; break; case KDBUS_ITEM_PID_COMM: comm = d->str; break; } } if (pid > 0) log_unit_debug(UNIT(n), "Activation triggered by process " PID_FMT " (%s)", pid, strna(comm)); r = 0; finish: if (p) (void) munmap(p, sz); cmd_free.offset = cmd_recv.msg.offset; if (ioctl(n->starter_fd, KDBUS_CMD_FREE, &cmd_free) < 0) log_unit_warning(UNIT(n), "Failed to free peeked message, ignoring: %m"); return r; } static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { BusName *n = userdata; assert(n); assert(fd >= 0); if (n->state != BUSNAME_LISTENING) return 0; log_unit_debug(UNIT(n), "Activation request"); if (revents != EPOLLIN) { log_unit_error(UNIT(n), "Got unexpected poll event (0x%x) on starter fd.", revents); goto fail; } busname_peek_message(n); busname_enter_running(n); return 0; fail: busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES); return 0; } static void busname_sigchld_event(Unit *u, pid_t pid, int code, int status) { BusName *n = BUSNAME(u); BusNameResult f; assert(n); assert(pid >= 0); if (pid != n->control_pid) return; n->control_pid = 0; if (is_clean_exit(code, status, NULL)) f = BUSNAME_SUCCESS; else if (code == CLD_EXITED) f = BUSNAME_FAILURE_EXIT_CODE; else if (code == CLD_KILLED) f = BUSNAME_FAILURE_SIGNAL; else if (code == CLD_DUMPED) f = BUSNAME_FAILURE_CORE_DUMP; else assert_not_reached("Unknown sigchld code"); log_unit_full(u, f == BUSNAME_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0, "Control process exited, code=%s status=%i", sigchld_code_to_string(code), status); if (f != BUSNAME_SUCCESS) n->result = f; switch (n->state) { case BUSNAME_MAKING: if (f == BUSNAME_SUCCESS) busname_enter_listening(n); else busname_enter_signal(n, BUSNAME_SIGTERM, f); break; case BUSNAME_SIGTERM: case BUSNAME_SIGKILL: busname_enter_dead(n, f); break; default: assert_not_reached("Uh, control process died at wrong time."); } /* Notify clients about changed exit status */ unit_add_to_dbus_queue(u); } static int busname_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { BusName *n = BUSNAME(userdata); assert(n); assert(n->timer_event_source == source); switch (n->state) { case BUSNAME_MAKING: log_unit_warning(UNIT(n), "Making timed out. Terminating."); busname_enter_signal(n, BUSNAME_SIGTERM, BUSNAME_FAILURE_TIMEOUT); break; case BUSNAME_SIGTERM: log_unit_warning(UNIT(n), "Stopping timed out. Killing."); busname_enter_signal(n, BUSNAME_SIGKILL, BUSNAME_FAILURE_TIMEOUT); break; case BUSNAME_SIGKILL: log_unit_warning(UNIT(n), "Processes still around after SIGKILL. Ignoring."); busname_enter_dead(n, BUSNAME_FAILURE_TIMEOUT); break; default: assert_not_reached("Timeout at wrong time."); } return 0; } static void busname_reset_failed(Unit *u) { BusName *n = BUSNAME(u); assert(n); if (n->state == BUSNAME_FAILED) busname_set_state(n, BUSNAME_DEAD); n->result = BUSNAME_SUCCESS; } static void busname_trigger_notify(Unit *u, Unit *other) { BusName *n = BUSNAME(u); assert(n); assert(other); if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING)) return; if (other->start_limit_hit) { busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT); return; } if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE) return; if (IN_SET(SERVICE(other)->state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, SERVICE_AUTO_RESTART)) busname_enter_listening(n); if (SERVICE(other)->state == SERVICE_RUNNING) busname_set_state(n, BUSNAME_RUNNING); } static int busname_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { return unit_kill_common(u, who, signo, -1, BUSNAME(u)->control_pid, error); } static int busname_get_timeout(Unit *u, usec_t *timeout) { BusName *n = BUSNAME(u); usec_t t; int r; if (!n->timer_event_source) return 0; r = sd_event_source_get_time(n->timer_event_source, &t); if (r < 0) return r; if (t == USEC_INFINITY) return 0; *timeout = t; return 1; } static bool busname_supported(void) { static int supported = -1; if (supported < 0) supported = is_kdbus_available(); return supported; } static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = { [BUSNAME_SUCCESS] = "success", [BUSNAME_FAILURE_RESOURCES] = "resources", [BUSNAME_FAILURE_TIMEOUT] = "timeout", [BUSNAME_FAILURE_EXIT_CODE] = "exit-code", [BUSNAME_FAILURE_SIGNAL] = "signal", [BUSNAME_FAILURE_CORE_DUMP] = "core-dump", [BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit", }; DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult); const UnitVTable busname_vtable = { .object_size = sizeof(BusName), .sections = "Unit\0" "BusName\0" "Install\0", .private_section = "BusName", .no_alias = true, .no_instances = true, .init = busname_init, .done = busname_done, .load = busname_load, .coldplug = busname_coldplug, .dump = busname_dump, .start = busname_start, .stop = busname_stop, .kill = busname_kill, .get_timeout = busname_get_timeout, .serialize = busname_serialize, .deserialize_item = busname_deserialize_item, .active_state = busname_active_state, .sub_state_to_string = busname_sub_state_to_string, .sigchld_event = busname_sigchld_event, .trigger_notify = busname_trigger_notify, .reset_failed = busname_reset_failed, .supported = busname_supported, .bus_vtable = bus_busname_vtable, .status_message_formats = { .finished_start_job = { [JOB_DONE] = "Listening on %s.", [JOB_FAILED] = "Failed to listen on %s.", }, .finished_stop_job = { [JOB_DONE] = "Closed %s.", [JOB_FAILED] = "Failed stopping %s.", }, }, }; systemd-229/src/core/busname.h000066400000000000000000000034421265713322000164060ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct BusName BusName; typedef struct BusNamePolicy BusNamePolicy; #include "unit.h" typedef enum BusNameResult { BUSNAME_SUCCESS, BUSNAME_FAILURE_RESOURCES, BUSNAME_FAILURE_TIMEOUT, BUSNAME_FAILURE_EXIT_CODE, BUSNAME_FAILURE_SIGNAL, BUSNAME_FAILURE_CORE_DUMP, BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT, _BUSNAME_RESULT_MAX, _BUSNAME_RESULT_INVALID = -1 } BusNameResult; struct BusName { Unit meta; char *name; int starter_fd; bool activating; bool accept_fd; UnitRef service; BusNameState state, deserialized_state; BusNameResult result; usec_t timeout_usec; sd_event_source *starter_event_source; sd_event_source *timer_event_source; pid_t control_pid; LIST_HEAD(BusNamePolicy, policy); BusPolicyAccess policy_world; }; extern const UnitVTable busname_vtable; const char* busname_result_to_string(BusNameResult i) _const_; BusNameResult busname_result_from_string(const char *s) _pure_; systemd-229/src/core/cgroup.c000066400000000000000000001523341265713322000162530ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "cgroup-util.h" #include "cgroup.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "special.h" #include "string-table.h" #include "string-util.h" #define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC) void cgroup_context_init(CGroupContext *c) { assert(c); /* Initialize everything to the kernel defaults, assuming the * structure is preinitialized to 0 */ c->cpu_shares = CGROUP_CPU_SHARES_INVALID; c->startup_cpu_shares = CGROUP_CPU_SHARES_INVALID; c->cpu_quota_per_sec_usec = USEC_INFINITY; c->memory_limit = (uint64_t) -1; c->blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID; c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID; c->tasks_max = (uint64_t) -1; } void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) { assert(c); assert(a); LIST_REMOVE(device_allow, c->device_allow, a); free(a->path); free(a); } void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) { assert(c); assert(w); LIST_REMOVE(device_weights, c->blockio_device_weights, w); free(w->path); free(w); } void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b) { assert(c); assert(b); LIST_REMOVE(device_bandwidths, c->blockio_device_bandwidths, b); free(b->path); free(b); } void cgroup_context_done(CGroupContext *c) { assert(c); while (c->blockio_device_weights) cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights); while (c->blockio_device_bandwidths) cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths); while (c->device_allow) cgroup_context_free_device_allow(c, c->device_allow); } void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { CGroupBlockIODeviceBandwidth *b; CGroupBlockIODeviceWeight *w; CGroupDeviceAllow *a; char u[FORMAT_TIMESPAN_MAX]; assert(c); assert(f); prefix = strempty(prefix); fprintf(f, "%sCPUAccounting=%s\n" "%sBlockIOAccounting=%s\n" "%sMemoryAccounting=%s\n" "%sTasksAccounting=%s\n" "%sCPUShares=%" PRIu64 "\n" "%sStartupCPUShares=%" PRIu64 "\n" "%sCPUQuotaPerSecSec=%s\n" "%sBlockIOWeight=%" PRIu64 "\n" "%sStartupBlockIOWeight=%" PRIu64 "\n" "%sMemoryLimit=%" PRIu64 "\n" "%sTasksMax=%" PRIu64 "\n" "%sDevicePolicy=%s\n" "%sDelegate=%s\n", prefix, yes_no(c->cpu_accounting), prefix, yes_no(c->blockio_accounting), prefix, yes_no(c->memory_accounting), prefix, yes_no(c->tasks_accounting), prefix, c->cpu_shares, prefix, c->startup_cpu_shares, prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1), prefix, c->blockio_weight, prefix, c->startup_blockio_weight, prefix, c->memory_limit, prefix, c->tasks_max, prefix, cgroup_device_policy_to_string(c->device_policy), prefix, yes_no(c->delegate)); LIST_FOREACH(device_allow, a, c->device_allow) fprintf(f, "%sDeviceAllow=%s %s%s%s\n", prefix, a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : ""); LIST_FOREACH(device_weights, w, c->blockio_device_weights) fprintf(f, "%sBlockIODeviceWeight=%s %" PRIu64, prefix, w->path, w->weight); LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) { char buf[FORMAT_BYTES_MAX]; fprintf(f, "%s%s=%s %s\n", prefix, b->read ? "BlockIOReadBandwidth" : "BlockIOWriteBandwidth", b->path, format_bytes(buf, sizeof(buf), b->bandwidth)); } } static int lookup_blkio_device(const char *p, dev_t *dev) { struct stat st; int r; assert(p); assert(dev); r = stat(p, &st); if (r < 0) return log_warning_errno(errno, "Couldn't stat device %s: %m", p); if (S_ISBLK(st.st_mode)) *dev = st.st_rdev; else if (major(st.st_dev) != 0) { /* If this is not a device node then find the block * device this file is stored on */ *dev = st.st_dev; /* If this is a partition, try to get the originating * block device */ block_get_whole_disk(*dev, dev); } else { log_warning("%s is not a block device and file system block device cannot be determined or is not local.", p); return -ENODEV; } return 0; } static int whitelist_device(const char *path, const char *node, const char *acc) { char buf[2+DECIMAL_STR_MAX(dev_t)*2+2+4]; struct stat st; int r; assert(path); assert(acc); if (stat(node, &st) < 0) { log_warning("Couldn't stat device %s", node); return -errno; } if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) { log_warning("%s is not a device.", node); return -ENODEV; } sprintf(buf, "%c %u:%u %s", S_ISCHR(st.st_mode) ? 'c' : 'b', major(st.st_rdev), minor(st.st_rdev), acc); r = cg_set_attribute("devices", path, "devices.allow", buf); if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set devices.allow on %s: %m", path); return r; } static int whitelist_major(const char *path, const char *name, char type, const char *acc) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; bool good = false; int r; assert(path); assert(acc); assert(type == 'b' || type == 'c'); f = fopen("/proc/devices", "re"); if (!f) return log_warning_errno(errno, "Cannot open /proc/devices to resolve %s (%c): %m", name, type); FOREACH_LINE(line, f, goto fail) { char buf[2+DECIMAL_STR_MAX(unsigned)+3+4], *p, *w; unsigned maj; truncate_nl(line); if (type == 'c' && streq(line, "Character devices:")) { good = true; continue; } if (type == 'b' && streq(line, "Block devices:")) { good = true; continue; } if (isempty(line)) { good = false; continue; } if (!good) continue; p = strstrip(line); w = strpbrk(p, WHITESPACE); if (!w) continue; *w = 0; r = safe_atou(p, &maj); if (r < 0) continue; if (maj <= 0) continue; w++; w += strspn(w, WHITESPACE); if (fnmatch(name, w, 0) != 0) continue; sprintf(buf, "%c %u:* %s", type, maj, acc); r = cg_set_attribute("devices", path, "devices.allow", buf); if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set devices.allow on %s: %m", path); } return 0; fail: log_warning_errno(errno, "Failed to read /proc/devices: %m"); return -errno; } void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, ManagerState state) { bool is_root; int r; assert(c); assert(path); if (mask == 0) return; /* Some cgroup attributes are not supported on the root cgroup, * hence silently ignore */ is_root = isempty(path) || path_equal(path, "/"); if (is_root) /* Make sure we don't try to display messages with an empty path. */ path = "/"; /* We generally ignore errors caused by read-only mounted * cgroup trees (assuming we are running in a container then), * and missing cgroups, i.e. EROFS and ENOENT. */ if ((mask & CGROUP_MASK_CPU) && !is_root) { char buf[MAX(DECIMAL_STR_MAX(uint64_t), DECIMAL_STR_MAX(usec_t)) + 1]; sprintf(buf, "%" PRIu64 "\n", IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->startup_cpu_shares : c->cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->cpu_shares : CGROUP_CPU_SHARES_DEFAULT); r = cg_set_attribute("cpu", path, "cpu.shares", buf); if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set cpu.shares on %s: %m", path); sprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC); r = cg_set_attribute("cpu", path, "cpu.cfs_period_us", buf); if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set cpu.cfs_period_us on %s: %m", path); if (c->cpu_quota_per_sec_usec != USEC_INFINITY) { sprintf(buf, USEC_FMT "\n", c->cpu_quota_per_sec_usec * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC); r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", buf); } else r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", "-1"); if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set cpu.cfs_quota_us on %s: %m", path); } if (mask & CGROUP_MASK_BLKIO) { char buf[MAX(DECIMAL_STR_MAX(uint64_t)+1, DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)]; CGroupBlockIODeviceWeight *w; CGroupBlockIODeviceBandwidth *b; if (!is_root) { sprintf(buf, "%" PRIu64 "\n", IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->startup_blockio_weight : c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->blockio_weight : CGROUP_BLKIO_WEIGHT_DEFAULT); r = cg_set_attribute("blkio", path, "blkio.weight", buf); if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set blkio.weight on %s: %m", path); /* FIXME: no way to reset this list */ LIST_FOREACH(device_weights, w, c->blockio_device_weights) { dev_t dev; r = lookup_blkio_device(w->path, &dev); if (r < 0) continue; sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), w->weight); r = cg_set_attribute("blkio", path, "blkio.weight_device", buf); if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set blkio.weight_device on %s: %m", path); } } /* FIXME: no way to reset this list */ LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) { const char *a; dev_t dev; r = lookup_blkio_device(b->path, &dev); if (r < 0) continue; a = b->read ? "blkio.throttle.read_bps_device" : "blkio.throttle.write_bps_device"; sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), b->bandwidth); r = cg_set_attribute("blkio", path, a, buf); if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set %s on %s: %m", a, path); } } if ((mask & CGROUP_MASK_MEMORY) && !is_root) { if (c->memory_limit != (uint64_t) -1) { char buf[DECIMAL_STR_MAX(uint64_t) + 1]; sprintf(buf, "%" PRIu64 "\n", c->memory_limit); if (cg_unified() <= 0) r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf); else r = cg_set_attribute("memory", path, "memory.max", buf); } else { if (cg_unified() <= 0) r = cg_set_attribute("memory", path, "memory.limit_in_bytes", "-1"); else r = cg_set_attribute("memory", path, "memory.max", "max"); } if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set memory.limit_in_bytes/memory.max on %s: %m", path); } if ((mask & CGROUP_MASK_DEVICES) && !is_root) { CGroupDeviceAllow *a; /* Changing the devices list of a populated cgroup * might result in EINVAL, hence ignore EINVAL * here. */ if (c->device_allow || c->device_policy != CGROUP_AUTO) r = cg_set_attribute("devices", path, "devices.deny", "a"); else r = cg_set_attribute("devices", path, "devices.allow", "a"); if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to reset devices.list on %s: %m", path); if (c->device_policy == CGROUP_CLOSED || (c->device_policy == CGROUP_AUTO && c->device_allow)) { static const char auto_devices[] = "/dev/null\0" "rwm\0" "/dev/zero\0" "rwm\0" "/dev/full\0" "rwm\0" "/dev/random\0" "rwm\0" "/dev/urandom\0" "rwm\0" "/dev/tty\0" "rwm\0" "/dev/pts/ptmx\0" "rw\0"; /* /dev/pts/ptmx may not be duplicated, but accessed */ const char *x, *y; NULSTR_FOREACH_PAIR(x, y, auto_devices) whitelist_device(path, x, y); whitelist_major(path, "pts", 'c', "rw"); whitelist_major(path, "kdbus", 'c', "rw"); whitelist_major(path, "kdbus/*", 'c', "rw"); } LIST_FOREACH(device_allow, a, c->device_allow) { char acc[4]; unsigned k = 0; if (a->r) acc[k++] = 'r'; if (a->w) acc[k++] = 'w'; if (a->m) acc[k++] = 'm'; if (k == 0) continue; acc[k++] = 0; if (startswith(a->path, "/dev/")) whitelist_device(path, a->path, acc); else if (startswith(a->path, "block-")) whitelist_major(path, a->path + 6, 'b', acc); else if (startswith(a->path, "char-")) whitelist_major(path, a->path + 5, 'c', acc); else log_debug("Ignoring device %s while writing cgroup attribute.", a->path); } } if ((mask & CGROUP_MASK_PIDS) && !is_root) { if (c->tasks_max != (uint64_t) -1) { char buf[DECIMAL_STR_MAX(uint64_t) + 2]; sprintf(buf, "%" PRIu64 "\n", c->tasks_max); r = cg_set_attribute("pids", path, "pids.max", buf); } else r = cg_set_attribute("pids", path, "pids.max", "max"); if (r < 0) log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set pids.max on %s: %m", path); } } CGroupMask cgroup_context_get_mask(CGroupContext *c) { CGroupMask mask = 0; /* Figure out which controllers we need */ if (c->cpu_accounting || c->cpu_shares != CGROUP_CPU_SHARES_INVALID || c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID || c->cpu_quota_per_sec_usec != USEC_INFINITY) mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU; if (c->blockio_accounting || c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID || c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID || c->blockio_device_weights || c->blockio_device_bandwidths) mask |= CGROUP_MASK_BLKIO; if (c->memory_accounting || c->memory_limit != (uint64_t) -1) mask |= CGROUP_MASK_MEMORY; if (c->device_allow || c->device_policy != CGROUP_AUTO) mask |= CGROUP_MASK_DEVICES; if (c->tasks_accounting || c->tasks_max != (uint64_t) -1) mask |= CGROUP_MASK_PIDS; return mask; } CGroupMask unit_get_own_mask(Unit *u) { CGroupContext *c; /* Returns the mask of controllers the unit needs for itself */ c = unit_get_cgroup_context(u); if (!c) return 0; /* If delegation is turned on, then turn on all cgroups, * unless we are on the legacy hierarchy and the process we * fork into it is known to drop privileges, and hence * shouldn't get access to the controllers. * * Note that on the unified hierarchy it is safe to delegate * controllers to unprivileged services. */ if (c->delegate) { ExecContext *e; e = unit_get_exec_context(u); if (!e || exec_context_maintains_privileges(e) || cg_unified() > 0) return _CGROUP_MASK_ALL; } return cgroup_context_get_mask(c); } CGroupMask unit_get_members_mask(Unit *u) { assert(u); /* Returns the mask of controllers all of the unit's children * require, merged */ if (u->cgroup_members_mask_valid) return u->cgroup_members_mask; u->cgroup_members_mask = 0; if (u->type == UNIT_SLICE) { Unit *member; Iterator i; SET_FOREACH(member, u->dependencies[UNIT_BEFORE], i) { if (member == u) continue; if (UNIT_DEREF(member->slice) != u) continue; u->cgroup_members_mask |= unit_get_own_mask(member) | unit_get_members_mask(member); } } u->cgroup_members_mask_valid = true; return u->cgroup_members_mask; } CGroupMask unit_get_siblings_mask(Unit *u) { assert(u); /* Returns the mask of controllers all of the unit's siblings * require, i.e. the members mask of the unit's parent slice * if there is one. */ if (UNIT_ISSET(u->slice)) return unit_get_members_mask(UNIT_DEREF(u->slice)); return unit_get_own_mask(u) | unit_get_members_mask(u); } CGroupMask unit_get_subtree_mask(Unit *u) { /* Returns the mask of this subtree, meaning of the group * itself and its children. */ return unit_get_own_mask(u) | unit_get_members_mask(u); } CGroupMask unit_get_target_mask(Unit *u) { CGroupMask mask; /* This returns the cgroup mask of all controllers to enable * for a specific cgroup, i.e. everything it needs itself, * plus all that its children need, plus all that its siblings * need. This is primarily useful on the legacy cgroup * hierarchy, where we need to duplicate each cgroup in each * hierarchy that shall be enabled for it. */ mask = unit_get_own_mask(u) | unit_get_members_mask(u) | unit_get_siblings_mask(u); mask &= u->manager->cgroup_supported; return mask; } CGroupMask unit_get_enable_mask(Unit *u) { CGroupMask mask; /* This returns the cgroup mask of all controllers to enable * for the children of a specific cgroup. This is primarily * useful for the unified cgroup hierarchy, where each cgroup * controls which controllers are enabled for its children. */ mask = unit_get_members_mask(u); mask &= u->manager->cgroup_supported; return mask; } /* Recurse from a unit up through its containing slices, propagating * mask bits upward. A unit is also member of itself. */ void unit_update_cgroup_members_masks(Unit *u) { CGroupMask m; bool more; assert(u); /* Calculate subtree mask */ m = unit_get_subtree_mask(u); /* See if anything changed from the previous invocation. If * not, we're done. */ if (u->cgroup_subtree_mask_valid && m == u->cgroup_subtree_mask) return; more = u->cgroup_subtree_mask_valid && ((m & ~u->cgroup_subtree_mask) != 0) && ((~m & u->cgroup_subtree_mask) == 0); u->cgroup_subtree_mask = m; u->cgroup_subtree_mask_valid = true; if (UNIT_ISSET(u->slice)) { Unit *s = UNIT_DEREF(u->slice); if (more) /* There's more set now than before. We * propagate the new mask to the parent's mask * (not caring if it actually was valid or * not). */ s->cgroup_members_mask |= m; else /* There's less set now than before (or we * don't know), we need to recalculate * everything, so let's invalidate the * parent's members mask */ s->cgroup_members_mask_valid = false; /* And now make sure that this change also hits our * grandparents */ unit_update_cgroup_members_masks(s); } } static const char *migrate_callback(CGroupMask mask, void *userdata) { Unit *u = userdata; assert(mask != 0); assert(u); while (u) { if (u->cgroup_path && u->cgroup_realized && (u->cgroup_realized_mask & mask) == mask) return u->cgroup_path; u = UNIT_DEREF(u->slice); } return NULL; } char *unit_default_cgroup_path(Unit *u) { _cleanup_free_ char *escaped = NULL, *slice = NULL; int r; assert(u); if (unit_has_name(u, SPECIAL_ROOT_SLICE)) return strdup(u->manager->cgroup_root); if (UNIT_ISSET(u->slice) && !unit_has_name(UNIT_DEREF(u->slice), SPECIAL_ROOT_SLICE)) { r = cg_slice_to_path(UNIT_DEREF(u->slice)->id, &slice); if (r < 0) return NULL; } escaped = cg_escape(u->id); if (!escaped) return NULL; if (slice) return strjoin(u->manager->cgroup_root, "/", slice, "/", escaped, NULL); else return strjoin(u->manager->cgroup_root, "/", escaped, NULL); } int unit_set_cgroup_path(Unit *u, const char *path) { _cleanup_free_ char *p = NULL; int r; assert(u); if (path) { p = strdup(path); if (!p) return -ENOMEM; } else p = NULL; if (streq_ptr(u->cgroup_path, p)) return 0; if (p) { r = hashmap_put(u->manager->cgroup_unit, p, u); if (r < 0) return r; } unit_release_cgroup(u); u->cgroup_path = p; p = NULL; return 1; } int unit_watch_cgroup(Unit *u) { _cleanup_free_ char *populated = NULL; int r; assert(u); if (!u->cgroup_path) return 0; if (u->cgroup_inotify_wd >= 0) return 0; /* Only applies to the unified hierarchy */ r = cg_unified(); if (r < 0) return log_unit_error_errno(u, r, "Failed detect wether the unified hierarchy is used: %m"); if (r == 0) return 0; /* Don't watch the root slice, it's pointless. */ if (unit_has_name(u, SPECIAL_ROOT_SLICE)) return 0; r = hashmap_ensure_allocated(&u->manager->cgroup_inotify_wd_unit, &trivial_hash_ops); if (r < 0) return log_oom(); r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.populated", &populated); if (r < 0) return log_oom(); u->cgroup_inotify_wd = inotify_add_watch(u->manager->cgroup_inotify_fd, populated, IN_MODIFY); if (u->cgroup_inotify_wd < 0) { if (errno == ENOENT) /* If the directory is already * gone we don't need to track * it, so this is not an error */ return 0; return log_unit_error_errno(u, errno, "Failed to add inotify watch descriptor for control group %s: %m", u->cgroup_path); } r = hashmap_put(u->manager->cgroup_inotify_wd_unit, INT_TO_PTR(u->cgroup_inotify_wd), u); if (r < 0) return log_unit_error_errno(u, r, "Failed to add inotify watch descriptor to hash map: %m"); return 0; } static int unit_create_cgroup( Unit *u, CGroupMask target_mask, CGroupMask enable_mask) { CGroupContext *c; int r; assert(u); c = unit_get_cgroup_context(u); if (!c) return 0; if (!u->cgroup_path) { _cleanup_free_ char *path = NULL; path = unit_default_cgroup_path(u); if (!path) return log_oom(); r = unit_set_cgroup_path(u, path); if (r == -EEXIST) return log_unit_error_errno(u, r, "Control group %s exists already.", path); if (r < 0) return log_unit_error_errno(u, r, "Failed to set unit's control group path to %s: %m", path); } /* First, create our own group */ r = cg_create_everywhere(u->manager->cgroup_supported, target_mask, u->cgroup_path); if (r < 0) return log_unit_error_errno(u, r, "Failed to create cgroup %s: %m", u->cgroup_path); /* Start watching it */ (void) unit_watch_cgroup(u); /* Enable all controllers we need */ r = cg_enable_everywhere(u->manager->cgroup_supported, enable_mask, u->cgroup_path); if (r < 0) log_unit_warning_errno(u, r, "Failed to enable controllers on cgroup %s, ignoring: %m", u->cgroup_path); /* Keep track that this is now realized */ u->cgroup_realized = true; u->cgroup_realized_mask = target_mask; if (u->type != UNIT_SLICE && !c->delegate) { /* Then, possibly move things over, but not if * subgroups may contain processes, which is the case * for slice and delegation units. */ r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->cgroup_path, migrate_callback, u); if (r < 0) log_unit_warning_errno(u, r, "Failed to migrate cgroup from to %s, ignoring: %m", u->cgroup_path); } return 0; } int unit_attach_pids_to_cgroup(Unit *u) { int r; assert(u); r = unit_realize_cgroup(u); if (r < 0) return r; r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->pids, migrate_callback, u); if (r < 0) return r; return 0; } static bool unit_has_mask_realized(Unit *u, CGroupMask target_mask) { assert(u); return u->cgroup_realized && u->cgroup_realized_mask == target_mask; } /* Check if necessary controllers and attributes for a unit are in place. * * If so, do nothing. * If not, create paths, move processes over, and set attributes. * * Returns 0 on success and < 0 on failure. */ static int unit_realize_cgroup_now(Unit *u, ManagerState state) { CGroupMask target_mask, enable_mask; int r; assert(u); if (u->in_cgroup_queue) { LIST_REMOVE(cgroup_queue, u->manager->cgroup_queue, u); u->in_cgroup_queue = false; } target_mask = unit_get_target_mask(u); if (unit_has_mask_realized(u, target_mask)) return 0; /* First, realize parents */ if (UNIT_ISSET(u->slice)) { r = unit_realize_cgroup_now(UNIT_DEREF(u->slice), state); if (r < 0) return r; } /* And then do the real work */ enable_mask = unit_get_enable_mask(u); r = unit_create_cgroup(u, target_mask, enable_mask); if (r < 0) return r; /* Finally, apply the necessary attributes. */ cgroup_context_apply(unit_get_cgroup_context(u), target_mask, u->cgroup_path, state); return 0; } static void unit_add_to_cgroup_queue(Unit *u) { if (u->in_cgroup_queue) return; LIST_PREPEND(cgroup_queue, u->manager->cgroup_queue, u); u->in_cgroup_queue = true; } unsigned manager_dispatch_cgroup_queue(Manager *m) { ManagerState state; unsigned n = 0; Unit *i; int r; state = manager_state(m); while ((i = m->cgroup_queue)) { assert(i->in_cgroup_queue); r = unit_realize_cgroup_now(i, state); if (r < 0) log_warning_errno(r, "Failed to realize cgroups for queued unit %s, ignoring: %m", i->id); n++; } return n; } static void unit_queue_siblings(Unit *u) { Unit *slice; /* This adds the siblings of the specified unit and the * siblings of all parent units to the cgroup queue. (But * neither the specified unit itself nor the parents.) */ while ((slice = UNIT_DEREF(u->slice))) { Iterator i; Unit *m; SET_FOREACH(m, slice->dependencies[UNIT_BEFORE], i) { if (m == u) continue; /* Skip units that have a dependency on the slice * but aren't actually in it. */ if (UNIT_DEREF(m->slice) != slice) continue; /* No point in doing cgroup application for units * without active processes. */ if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(m))) continue; /* If the unit doesn't need any new controllers * and has current ones realized, it doesn't need * any changes. */ if (unit_has_mask_realized(m, unit_get_target_mask(m))) continue; unit_add_to_cgroup_queue(m); } u = slice; } } int unit_realize_cgroup(Unit *u) { assert(u); if (!UNIT_HAS_CGROUP_CONTEXT(u)) return 0; /* So, here's the deal: when realizing the cgroups for this * unit, we need to first create all parents, but there's more * actually: for the weight-based controllers we also need to * make sure that all our siblings (i.e. units that are in the * same slice as we are) have cgroups, too. Otherwise, things * would become very uneven as each of their processes would * get as much resources as all our group together. This call * will synchronously create the parent cgroups, but will * defer work on the siblings to the next event loop * iteration. */ /* Add all sibling slices to the cgroup queue. */ unit_queue_siblings(u); /* And realize this one now (and apply the values) */ return unit_realize_cgroup_now(u, manager_state(u->manager)); } void unit_release_cgroup(Unit *u) { assert(u); /* Forgets all cgroup details for this cgroup */ if (u->cgroup_path) { (void) hashmap_remove(u->manager->cgroup_unit, u->cgroup_path); u->cgroup_path = mfree(u->cgroup_path); } if (u->cgroup_inotify_wd >= 0) { if (inotify_rm_watch(u->manager->cgroup_inotify_fd, u->cgroup_inotify_wd) < 0) log_unit_debug_errno(u, errno, "Failed to remove cgroup inotify watch %i for %s, ignoring", u->cgroup_inotify_wd, u->id); (void) hashmap_remove(u->manager->cgroup_inotify_wd_unit, INT_TO_PTR(u->cgroup_inotify_wd)); u->cgroup_inotify_wd = -1; } } void unit_prune_cgroup(Unit *u) { int r; bool is_root_slice; assert(u); /* Removes the cgroup, if empty and possible, and stops watching it. */ if (!u->cgroup_path) return; is_root_slice = unit_has_name(u, SPECIAL_ROOT_SLICE); r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !is_root_slice); if (r < 0) { log_debug_errno(r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path); return; } if (is_root_slice) return; unit_release_cgroup(u); u->cgroup_realized = false; u->cgroup_realized_mask = 0; } int unit_search_main_pid(Unit *u, pid_t *ret) { _cleanup_fclose_ FILE *f = NULL; pid_t pid = 0, npid, mypid; int r; assert(u); assert(ret); if (!u->cgroup_path) return -ENXIO; r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &f); if (r < 0) return r; mypid = getpid(); while (cg_read_pid(f, &npid) > 0) { pid_t ppid; if (npid == pid) continue; /* Ignore processes that aren't our kids */ if (get_process_ppid(npid, &ppid) >= 0 && ppid != mypid) continue; if (pid != 0) /* Dang, there's more than one daemonized PID in this group, so we don't know what process is the main process. */ return -ENODATA; pid = npid; } *ret = pid; return 0; } static int unit_watch_pids_in_path(Unit *u, const char *path) { _cleanup_closedir_ DIR *d = NULL; _cleanup_fclose_ FILE *f = NULL; int ret = 0, r; assert(u); assert(path); r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, path, &f); if (r < 0) ret = r; else { pid_t pid; while ((r = cg_read_pid(f, &pid)) > 0) { r = unit_watch_pid(u, pid); if (r < 0 && ret >= 0) ret = r; } if (r < 0 && ret >= 0) ret = r; } r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, path, &d); if (r < 0) { if (ret >= 0) ret = r; } else { char *fn; while ((r = cg_read_subgroup(d, &fn)) > 0) { _cleanup_free_ char *p = NULL; p = strjoin(path, "/", fn, NULL); free(fn); if (!p) return -ENOMEM; r = unit_watch_pids_in_path(u, p); if (r < 0 && ret >= 0) ret = r; } if (r < 0 && ret >= 0) ret = r; } return ret; } int unit_watch_all_pids(Unit *u) { assert(u); /* Adds all PIDs from our cgroup to the set of PIDs we * watch. This is a fallback logic for cases where we do not * get reliable cgroup empty notifications: we try to use * SIGCHLD as replacement. */ if (!u->cgroup_path) return -ENOENT; if (cg_unified() > 0) /* On unified we can use proper notifications */ return 0; return unit_watch_pids_in_path(u, u->cgroup_path); } int unit_notify_cgroup_empty(Unit *u) { int r; assert(u); if (!u->cgroup_path) return 0; r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path); if (r <= 0) return r; unit_add_to_gc_queue(u); if (UNIT_VTABLE(u)->notify_cgroup_empty) UNIT_VTABLE(u)->notify_cgroup_empty(u); return 0; } static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; assert(s); assert(fd >= 0); assert(m); for (;;) { union inotify_event_buffer buffer; struct inotify_event *e; ssize_t l; l = read(fd, &buffer, sizeof(buffer)); if (l < 0) { if (errno == EINTR || errno == EAGAIN) return 0; return log_error_errno(errno, "Failed to read control group inotify events: %m"); } FOREACH_INOTIFY_EVENT(e, buffer, l) { Unit *u; if (e->wd < 0) /* Queue overflow has no watch descriptor */ continue; if (e->mask & IN_IGNORED) /* The watch was just removed */ continue; u = hashmap_get(m->cgroup_inotify_wd_unit, INT_TO_PTR(e->wd)); if (!u) /* Not that inotify might deliver * events for a watch even after it * was removed, because it was queued * before the removal. Let's ignore * this here safely. */ continue; (void) unit_notify_cgroup_empty(u); } } } int manager_setup_cgroup(Manager *m) { _cleanup_free_ char *path = NULL; CGroupController c; int r, unified; char *e; assert(m); /* 1. Determine hierarchy */ m->cgroup_root = mfree(m->cgroup_root); r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root); if (r < 0) return log_error_errno(r, "Cannot determine cgroup we are running in: %m"); /* Chop off the init scope, if we are already located in it */ e = endswith(m->cgroup_root, "/" SPECIAL_INIT_SCOPE); /* LEGACY: Also chop off the system slice if we are in * it. This is to support live upgrades from older systemd * versions where PID 1 was moved there. Also see * cg_get_root_path(). */ if (!e && m->running_as == MANAGER_SYSTEM) { e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE); if (!e) e = endswith(m->cgroup_root, "/system"); /* even more legacy */ } if (e) *e = 0; /* And make sure to store away the root value without trailing * slash, even for the root dir, so that we can easily prepend * it everywhere. */ while ((e = endswith(m->cgroup_root, "/"))) *e = 0; /* 2. Show data */ r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path); if (r < 0) return log_error_errno(r, "Cannot find cgroup mount point: %m"); unified = cg_unified(); if (unified < 0) return log_error_errno(r, "Couldn't determine if we are running in the unified hierarchy: %m"); if (unified > 0) log_debug("Unified cgroup hierarchy is located at %s.", path); else log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path); if (!m->test_run) { const char *scope_path; /* 3. Install agent */ if (unified) { /* In the unified hierarchy we can can get * cgroup empty notifications via inotify. */ m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source); safe_close(m->cgroup_inotify_fd); m->cgroup_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (m->cgroup_inotify_fd < 0) return log_error_errno(errno, "Failed to create control group inotify object: %m"); r = sd_event_add_io(m->event, &m->cgroup_inotify_event_source, m->cgroup_inotify_fd, EPOLLIN, on_cgroup_inotify_event, m); if (r < 0) return log_error_errno(r, "Failed to watch control group inotify object: %m"); r = sd_event_source_set_priority(m->cgroup_inotify_event_source, SD_EVENT_PRIORITY_IDLE - 5); if (r < 0) return log_error_errno(r, "Failed to set priority of inotify event source: %m"); (void) sd_event_source_set_description(m->cgroup_inotify_event_source, "cgroup-inotify"); } else if (m->running_as == MANAGER_SYSTEM) { /* On the legacy hierarchy we only get * notifications via cgroup agents. (Which * isn't really reliable, since it does not * generate events when control groups with * children run empty. */ r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH); if (r < 0) log_warning_errno(r, "Failed to install release agent, ignoring: %m"); else if (r > 0) log_debug("Installed release agent."); else if (r == 0) log_debug("Release agent already installed."); } /* 4. Make sure we are in the special "init.scope" unit in the root slice. */ scope_path = strjoina(m->cgroup_root, "/" SPECIAL_INIT_SCOPE); r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0); if (r < 0) return log_error_errno(r, "Failed to create %s control group: %m", scope_path); /* also, move all other userspace processes remaining * in the root cgroup into that scope. */ r = cg_migrate(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, SYSTEMD_CGROUP_CONTROLLER, scope_path, false); if (r < 0) log_warning_errno(r, "Couldn't move remaining userspace processes, ignoring: %m"); /* 5. And pin it, so that it cannot be unmounted */ safe_close(m->pin_cgroupfs_fd); m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK); if (m->pin_cgroupfs_fd < 0) return log_error_errno(errno, "Failed to open pin file: %m"); /* 6. Always enable hierarchical support if it exists... */ if (!unified) (void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1"); } /* 7. Figure out which controllers are supported */ r = cg_mask_supported(&m->cgroup_supported); if (r < 0) return log_error_errno(r, "Failed to determine supported controllers: %m"); for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) log_debug("Controller '%s' supported: %s", cgroup_controller_to_string(c), yes_no(m->cgroup_supported & c)); return 0; } void manager_shutdown_cgroup(Manager *m, bool delete) { assert(m); /* We can't really delete the group, since we are in it. But * let's trim it. */ if (delete && m->cgroup_root) (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, false); m->cgroup_inotify_wd_unit = hashmap_free(m->cgroup_inotify_wd_unit); m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source); m->cgroup_inotify_fd = safe_close(m->cgroup_inotify_fd); m->pin_cgroupfs_fd = safe_close(m->pin_cgroupfs_fd); m->cgroup_root = mfree(m->cgroup_root); } Unit* manager_get_unit_by_cgroup(Manager *m, const char *cgroup) { char *p; Unit *u; assert(m); assert(cgroup); u = hashmap_get(m->cgroup_unit, cgroup); if (u) return u; p = strdupa(cgroup); for (;;) { char *e; e = strrchr(p, '/'); if (!e || e == p) return hashmap_get(m->cgroup_unit, SPECIAL_ROOT_SLICE); *e = 0; u = hashmap_get(m->cgroup_unit, p); if (u) return u; } } Unit *manager_get_unit_by_pid_cgroup(Manager *m, pid_t pid) { _cleanup_free_ char *cgroup = NULL; int r; assert(m); if (pid <= 0) return NULL; r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup); if (r < 0) return NULL; return manager_get_unit_by_cgroup(m, cgroup); } Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) { Unit *u; assert(m); if (pid <= 0) return NULL; if (pid == 1) return hashmap_get(m->units, SPECIAL_INIT_SCOPE); u = hashmap_get(m->watch_pids1, PID_TO_PTR(pid)); if (u) return u; u = hashmap_get(m->watch_pids2, PID_TO_PTR(pid)); if (u) return u; return manager_get_unit_by_pid_cgroup(m, pid); } int manager_notify_cgroup_empty(Manager *m, const char *cgroup) { Unit *u; assert(m); assert(cgroup); u = manager_get_unit_by_cgroup(m, cgroup); if (!u) return 0; return unit_notify_cgroup_empty(u); } int unit_get_memory_current(Unit *u, uint64_t *ret) { _cleanup_free_ char *v = NULL; int r; assert(u); assert(ret); if (!u->cgroup_path) return -ENODATA; if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0) return -ENODATA; if (cg_unified() <= 0) r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v); else r = cg_get_attribute("memory", u->cgroup_path, "memory.current", &v); if (r == -ENOENT) return -ENODATA; if (r < 0) return r; return safe_atou64(v, ret); } int unit_get_tasks_current(Unit *u, uint64_t *ret) { _cleanup_free_ char *v = NULL; int r; assert(u); assert(ret); if (!u->cgroup_path) return -ENODATA; if ((u->cgroup_realized_mask & CGROUP_MASK_PIDS) == 0) return -ENODATA; r = cg_get_attribute("pids", u->cgroup_path, "pids.current", &v); if (r == -ENOENT) return -ENODATA; if (r < 0) return r; return safe_atou64(v, ret); } static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) { _cleanup_free_ char *v = NULL; uint64_t ns; int r; assert(u); assert(ret); if (!u->cgroup_path) return -ENODATA; if ((u->cgroup_realized_mask & CGROUP_MASK_CPUACCT) == 0) return -ENODATA; r = cg_get_attribute("cpuacct", u->cgroup_path, "cpuacct.usage", &v); if (r == -ENOENT) return -ENODATA; if (r < 0) return r; r = safe_atou64(v, &ns); if (r < 0) return r; *ret = ns; return 0; } int unit_get_cpu_usage(Unit *u, nsec_t *ret) { nsec_t ns; int r; r = unit_get_cpu_usage_raw(u, &ns); if (r < 0) return r; if (ns > u->cpuacct_usage_base) ns -= u->cpuacct_usage_base; else ns = 0; *ret = ns; return 0; } int unit_reset_cpu_usage(Unit *u) { nsec_t ns; int r; assert(u); r = unit_get_cpu_usage_raw(u, &ns); if (r < 0) { u->cpuacct_usage_base = 0; return r; } u->cpuacct_usage_base = ns; return 0; } bool unit_cgroup_delegate(Unit *u) { CGroupContext *c; assert(u); c = unit_get_cgroup_context(u); if (!c) return false; return c->delegate; } void unit_invalidate_cgroup(Unit *u, CGroupMask m) { assert(u); if (!UNIT_HAS_CGROUP_CONTEXT(u)) return; if (m == 0) return; if ((u->cgroup_realized_mask & m) == 0) return; u->cgroup_realized_mask &= ~m; unit_add_to_cgroup_queue(u); } void manager_invalidate_startup_units(Manager *m) { Iterator i; Unit *u; assert(m); SET_FOREACH(u, m->startup_units, i) unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_BLKIO); } static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = { [CGROUP_AUTO] = "auto", [CGROUP_CLOSED] = "closed", [CGROUP_STRICT] = "strict", }; DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy); systemd-229/src/core/cgroup.h000066400000000000000000000113731265713322000162550ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "list.h" #include "time-util.h" typedef struct CGroupContext CGroupContext; typedef struct CGroupDeviceAllow CGroupDeviceAllow; typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight; typedef struct CGroupBlockIODeviceBandwidth CGroupBlockIODeviceBandwidth; typedef enum CGroupDevicePolicy { /* When devices listed, will allow those, plus built-in ones, if none are listed will allow everything. */ CGROUP_AUTO, /* Everything forbidden, except built-in ones and listed ones. */ CGROUP_CLOSED, /* Everythings forbidden, except for the listed devices */ CGROUP_STRICT, _CGROUP_DEVICE_POLICY_MAX, _CGROUP_DEVICE_POLICY_INVALID = -1 } CGroupDevicePolicy; struct CGroupDeviceAllow { LIST_FIELDS(CGroupDeviceAllow, device_allow); char *path; bool r:1; bool w:1; bool m:1; }; struct CGroupBlockIODeviceWeight { LIST_FIELDS(CGroupBlockIODeviceWeight, device_weights); char *path; uint64_t weight; }; struct CGroupBlockIODeviceBandwidth { LIST_FIELDS(CGroupBlockIODeviceBandwidth, device_bandwidths); char *path; uint64_t bandwidth; bool read; }; struct CGroupContext { bool cpu_accounting; bool blockio_accounting; bool memory_accounting; bool tasks_accounting; uint64_t cpu_shares; uint64_t startup_cpu_shares; usec_t cpu_quota_per_sec_usec; uint64_t blockio_weight; uint64_t startup_blockio_weight; LIST_HEAD(CGroupBlockIODeviceWeight, blockio_device_weights); LIST_HEAD(CGroupBlockIODeviceBandwidth, blockio_device_bandwidths); uint64_t memory_limit; CGroupDevicePolicy device_policy; LIST_HEAD(CGroupDeviceAllow, device_allow); uint64_t tasks_max; bool delegate; }; #include "cgroup-util.h" #include "unit.h" void cgroup_context_init(CGroupContext *c); void cgroup_context_done(CGroupContext *c); void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix); void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, ManagerState state); CGroupMask cgroup_context_get_mask(CGroupContext *c); void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a); void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w); void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b); CGroupMask unit_get_own_mask(Unit *u); CGroupMask unit_get_siblings_mask(Unit *u); CGroupMask unit_get_members_mask(Unit *u); CGroupMask unit_get_subtree_mask(Unit *u); CGroupMask unit_get_target_mask(Unit *u); CGroupMask unit_get_enable_mask(Unit *u); void unit_update_cgroup_members_masks(Unit *u); char *unit_default_cgroup_path(Unit *u); int unit_set_cgroup_path(Unit *u, const char *path); int unit_realize_cgroup(Unit *u); void unit_release_cgroup(Unit *u); void unit_prune_cgroup(Unit *u); int unit_watch_cgroup(Unit *u); int unit_attach_pids_to_cgroup(Unit *u); int manager_setup_cgroup(Manager *m); void manager_shutdown_cgroup(Manager *m, bool delete); unsigned manager_dispatch_cgroup_queue(Manager *m); Unit *manager_get_unit_by_cgroup(Manager *m, const char *cgroup); Unit *manager_get_unit_by_pid_cgroup(Manager *m, pid_t pid); Unit* manager_get_unit_by_pid(Manager *m, pid_t pid); int unit_search_main_pid(Unit *u, pid_t *ret); int unit_watch_all_pids(Unit *u); int unit_get_memory_current(Unit *u, uint64_t *ret); int unit_get_tasks_current(Unit *u, uint64_t *ret); int unit_get_cpu_usage(Unit *u, nsec_t *ret); int unit_reset_cpu_usage(Unit *u); bool unit_cgroup_delegate(Unit *u); int unit_notify_cgroup_empty(Unit *u); int manager_notify_cgroup_empty(Manager *m, const char *group); void unit_invalidate_cgroup(Unit *u, CGroupMask m); void manager_invalidate_startup_units(Manager *m); const char* cgroup_device_policy_to_string(CGroupDevicePolicy i) _const_; CGroupDevicePolicy cgroup_device_policy_from_string(const char *s) _pure_; systemd-229/src/core/dbus-automount.c000066400000000000000000000027711265713322000177410ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "automount.h" #include "bus-util.h" #include "dbus-automount.h" #include "string-util.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, automount_result, AutomountResult); const sd_bus_vtable bus_automount_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Where", "s", NULL, offsetof(Automount, where), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Automount, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Automount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("TimeoutIdleUSec", "t", bus_property_get_usec, offsetof(Automount, timeout_idle_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_VTABLE_END }; systemd-229/src/core/dbus-automount.h000066400000000000000000000014211265713322000177350ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ extern const sd_bus_vtable bus_automount_vtable[]; systemd-229/src/core/dbus-busname.c000066400000000000000000000033701265713322000173340ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-util.h" #include "busname.h" #include "dbus-busname.h" #include "string-util.h" #include "unit.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, busname_result, BusNameResult); const sd_bus_vtable bus_busname_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Name", "s", NULL, offsetof(BusName, name), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(BusName, timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(BusName, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(BusName, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Activating", "b", bus_property_get_bool, offsetof(BusName, activating), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("AcceptFileDescriptors", "b", bus_property_get_bool, offsetof(BusName, accept_fd), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_VTABLE_END }; systemd-229/src/core/dbus-busname.h000066400000000000000000000014171265713322000173410ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ extern const sd_bus_vtable bus_busname_vtable[]; systemd-229/src/core/dbus-cgroup.c000066400000000000000000000636571265713322000172170ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-util.h" #include "cgroup-util.h" #include "cgroup.h" #include "dbus-cgroup.h" #include "fd-util.h" #include "fileio.h" #include "path-util.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy); static int property_get_blockio_device_weight( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { CGroupContext *c = userdata; CGroupBlockIODeviceWeight *w; int r; assert(bus); assert(reply); assert(c); r = sd_bus_message_open_container(reply, 'a', "(st)"); if (r < 0) return r; LIST_FOREACH(device_weights, w, c->blockio_device_weights) { r = sd_bus_message_append(reply, "(st)", w->path, w->weight); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_blockio_device_bandwidths( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { CGroupContext *c = userdata; CGroupBlockIODeviceBandwidth *b; int r; assert(bus); assert(reply); assert(c); r = sd_bus_message_open_container(reply, 'a', "(st)"); if (r < 0) return r; LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) { if (streq(property, "BlockIOReadBandwidth") != b->read) continue; r = sd_bus_message_append(reply, "(st)", b->path, b->bandwidth); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_device_allow( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { CGroupContext *c = userdata; CGroupDeviceAllow *a; int r; assert(bus); assert(reply); assert(c); r = sd_bus_message_open_container(reply, 'a', "(ss)"); if (r < 0) return r; LIST_FOREACH(device_allow, a, c->device_allow) { unsigned k = 0; char rwm[4]; if (a->r) rwm[k++] = 'r'; if (a->w) rwm[k++] = 'w'; if (a->m) rwm[k++] = 'm'; rwm[k] = 0; r = sd_bus_message_append(reply, "(ss)", a->path, rwm); if (r < 0) return r; } return sd_bus_message_close_container(reply); } const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0), SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0), SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0), SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0), SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0), SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0), SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0), SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0), SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0), SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0), SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0), SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0), SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0), SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0), SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0), SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0), SD_BUS_PROPERTY("TasksMax", "t", NULL, offsetof(CGroupContext, tasks_max), 0), SD_BUS_VTABLE_END }; static int bus_cgroup_set_transient_property( Unit *u, CGroupContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { int r; assert(u); assert(c); assert(name); assert(message); if (streq(name, "Delegate")) { int b; r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; if (mode != UNIT_CHECK) { c->delegate = b; unit_write_drop_in_private(u, mode, name, b ? "Delegate=yes" : "Delegate=no"); } return 1; } return 0; } int bus_cgroup_set_property( Unit *u, CGroupContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { int r; assert(u); assert(c); assert(name); assert(message); if (streq(name, "CPUAccounting")) { int b; r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; if (mode != UNIT_CHECK) { c->cpu_accounting = b; unit_invalidate_cgroup(u, CGROUP_MASK_CPUACCT|CGROUP_MASK_CPU); unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no"); } return 1; } else if (streq(name, "CPUShares")) { uint64_t shares; r = sd_bus_message_read(message, "t", &shares); if (r < 0) return r; if (!CGROUP_CPU_SHARES_IS_OK(shares)) return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range"); if (mode != UNIT_CHECK) { c->cpu_shares = shares; unit_invalidate_cgroup(u, CGROUP_MASK_CPU); if (shares == CGROUP_CPU_SHARES_INVALID) unit_write_drop_in_private(u, mode, name, "CPUShares="); else unit_write_drop_in_private_format(u, mode, name, "CPUShares=%" PRIu64, shares); } return 1; } else if (streq(name, "StartupCPUShares")) { uint64_t shares; r = sd_bus_message_read(message, "t", &shares); if (r < 0) return r; if (!CGROUP_CPU_SHARES_IS_OK(shares)) return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range"); if (mode != UNIT_CHECK) { c->startup_cpu_shares = shares; unit_invalidate_cgroup(u, CGROUP_MASK_CPU); if (shares == CGROUP_CPU_SHARES_INVALID) unit_write_drop_in_private(u, mode, name, "StartupCPUShares="); else unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%" PRIu64, shares); } return 1; } else if (streq(name, "CPUQuotaPerSecUSec")) { uint64_t u64; r = sd_bus_message_read(message, "t", &u64); if (r < 0) return r; if (u64 <= 0) return sd_bus_error_set_errnof(error, EINVAL, "CPUQuotaPerSecUSec value out of range"); if (mode != UNIT_CHECK) { c->cpu_quota_per_sec_usec = u64; unit_invalidate_cgroup(u, CGROUP_MASK_CPU); unit_write_drop_in_private_format(u, mode, "CPUQuota", "CPUQuota=%0.f%%", (double) (c->cpu_quota_per_sec_usec / 10000)); } return 1; } else if (streq(name, "BlockIOAccounting")) { int b; r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; if (mode != UNIT_CHECK) { c->blockio_accounting = b; unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no"); } return 1; } else if (streq(name, "BlockIOWeight")) { uint64_t weight; r = sd_bus_message_read(message, "t", &weight); if (r < 0) return r; if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight)) return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range"); if (mode != UNIT_CHECK) { c->blockio_weight = weight; unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); if (weight == CGROUP_BLKIO_WEIGHT_INVALID) unit_write_drop_in_private(u, mode, name, "BlockIOWeight="); else unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%" PRIu64, weight); } return 1; } else if (streq(name, "StartupBlockIOWeight")) { uint64_t weight; r = sd_bus_message_read(message, "t", &weight); if (r < 0) return r; if (CGROUP_BLKIO_WEIGHT_IS_OK(weight)) return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range"); if (mode != UNIT_CHECK) { c->startup_blockio_weight = weight; unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); if (weight == CGROUP_BLKIO_WEIGHT_INVALID) unit_write_drop_in_private(u, mode, name, "StartupBlockIOWeight="); else unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%" PRIu64, weight); } return 1; } else if (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth")) { const char *path; bool read = true; unsigned n = 0; uint64_t u64; if (streq(name, "BlockIOWriteBandwidth")) read = false; r = sd_bus_message_enter_container(message, 'a', "(st)"); if (r < 0) return r; while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) { if (mode != UNIT_CHECK) { CGroupBlockIODeviceBandwidth *a = NULL, *b; LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) { if (path_equal(path, b->path) && read == b->read) { a = b; break; } } if (!a) { a = new0(CGroupBlockIODeviceBandwidth, 1); if (!a) return -ENOMEM; a->read = read; a->path = strdup(path); if (!a->path) { free(a); return -ENOMEM; } LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a); } a->bandwidth = u64; } n++; } if (r < 0) return r; r = sd_bus_message_exit_container(message); if (r < 0) return r; if (mode != UNIT_CHECK) { CGroupBlockIODeviceBandwidth *a, *next; _cleanup_free_ char *buf = NULL; _cleanup_fclose_ FILE *f = NULL; size_t size = 0; if (n == 0) { LIST_FOREACH_SAFE(device_bandwidths, a, next, c->blockio_device_bandwidths) if (a->read == read) cgroup_context_free_blockio_device_bandwidth(c, a); } unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); f = open_memstream(&buf, &size); if (!f) return -ENOMEM; if (read) { fputs("BlockIOReadBandwidth=\n", f); LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) if (a->read) fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth); } else { fputs("BlockIOWriteBandwidth=\n", f); LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) if (!a->read) fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth); } r = fflush_and_check(f); if (r < 0) return r; unit_write_drop_in_private(u, mode, name, buf); } return 1; } else if (streq(name, "BlockIODeviceWeight")) { const char *path; uint64_t weight; unsigned n = 0; r = sd_bus_message_enter_container(message, 'a', "(st)"); if (r < 0) return r; while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) { if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID) return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range"); if (mode != UNIT_CHECK) { CGroupBlockIODeviceWeight *a = NULL, *b; LIST_FOREACH(device_weights, b, c->blockio_device_weights) { if (path_equal(b->path, path)) { a = b; break; } } if (!a) { a = new0(CGroupBlockIODeviceWeight, 1); if (!a) return -ENOMEM; a->path = strdup(path); if (!a->path) { free(a); return -ENOMEM; } LIST_PREPEND(device_weights,c->blockio_device_weights, a); } a->weight = weight; } n++; } r = sd_bus_message_exit_container(message); if (r < 0) return r; if (mode != UNIT_CHECK) { _cleanup_free_ char *buf = NULL; _cleanup_fclose_ FILE *f = NULL; CGroupBlockIODeviceWeight *a; size_t size = 0; if (n == 0) { while (c->blockio_device_weights) cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights); } unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); f = open_memstream(&buf, &size); if (!f) return -ENOMEM; fputs("BlockIODeviceWeight=\n", f); LIST_FOREACH(device_weights, a, c->blockio_device_weights) fprintf(f, "BlockIODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight); r = fflush_and_check(f); if (r < 0) return r; unit_write_drop_in_private(u, mode, name, buf); } return 1; } else if (streq(name, "MemoryAccounting")) { int b; r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; if (mode != UNIT_CHECK) { c->memory_accounting = b; unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY); unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no"); } return 1; } else if (streq(name, "MemoryLimit")) { uint64_t limit; r = sd_bus_message_read(message, "t", &limit); if (r < 0) return r; if (mode != UNIT_CHECK) { c->memory_limit = limit; unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY); if (limit == (uint64_t) -1) unit_write_drop_in_private(u, mode, name, "MemoryLimit=infinity"); else unit_write_drop_in_private_format(u, mode, name, "MemoryLimit=%" PRIu64, limit); } return 1; } else if (streq(name, "DevicePolicy")) { const char *policy; CGroupDevicePolicy p; r = sd_bus_message_read(message, "s", &policy); if (r < 0) return r; p = cgroup_device_policy_from_string(policy); if (p < 0) return -EINVAL; if (mode != UNIT_CHECK) { char *buf; c->device_policy = p; unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES); buf = strjoina("DevicePolicy=", policy); unit_write_drop_in_private(u, mode, name, buf); } return 1; } else if (streq(name, "DeviceAllow")) { const char *path, *rwm; unsigned n = 0; r = sd_bus_message_enter_container(message, 'a', "(ss)"); if (r < 0) return r; while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) { if ((!startswith(path, "/dev/") && !startswith(path, "block-") && !startswith(path, "char-")) || strpbrk(path, WHITESPACE)) return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node"); if (isempty(rwm)) rwm = "rwm"; if (!in_charset(rwm, "rwm")) return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires combination of rwm flags"); if (mode != UNIT_CHECK) { CGroupDeviceAllow *a = NULL, *b; LIST_FOREACH(device_allow, b, c->device_allow) { if (path_equal(b->path, path)) { a = b; break; } } if (!a) { a = new0(CGroupDeviceAllow, 1); if (!a) return -ENOMEM; a->path = strdup(path); if (!a->path) { free(a); return -ENOMEM; } LIST_PREPEND(device_allow, c->device_allow, a); } a->r = !!strchr(rwm, 'r'); a->w = !!strchr(rwm, 'w'); a->m = !!strchr(rwm, 'm'); } n++; } if (r < 0) return r; r = sd_bus_message_exit_container(message); if (r < 0) return r; if (mode != UNIT_CHECK) { _cleanup_free_ char *buf = NULL; _cleanup_fclose_ FILE *f = NULL; CGroupDeviceAllow *a; size_t size = 0; if (n == 0) { while (c->device_allow) cgroup_context_free_device_allow(c, c->device_allow); } unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES); f = open_memstream(&buf, &size); if (!f) return -ENOMEM; fputs("DeviceAllow=\n", f); LIST_FOREACH(device_allow, a, c->device_allow) fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : ""); r = fflush_and_check(f); if (r < 0) return r; unit_write_drop_in_private(u, mode, name, buf); } return 1; } else if (streq(name, "TasksAccounting")) { int b; r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; if (mode != UNIT_CHECK) { c->tasks_accounting = b; unit_invalidate_cgroup(u, CGROUP_MASK_PIDS); unit_write_drop_in_private(u, mode, name, b ? "TasksAccounting=yes" : "TasksAccounting=no"); } return 1; } else if (streq(name, "TasksMax")) { uint64_t limit; r = sd_bus_message_read(message, "t", &limit); if (r < 0) return r; if (mode != UNIT_CHECK) { c->tasks_max = limit; unit_invalidate_cgroup(u, CGROUP_MASK_PIDS); if (limit == (uint64_t) -1) unit_write_drop_in_private(u, mode, name, "TasksMax=infinity"); else unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu64, limit); } return 1; } if (u->transient && u->load_state == UNIT_STUB) { r = bus_cgroup_set_transient_property(u, c, name, message, mode, error); if (r != 0) return r; } return 0; } systemd-229/src/core/dbus-cgroup.h000066400000000000000000000017141265713322000172060ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "cgroup.h" extern const sd_bus_vtable bus_cgroup_vtable[]; int bus_cgroup_set_property(Unit *u, CGroupContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error); systemd-229/src/core/dbus-device.c000066400000000000000000000017471265713322000171470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "dbus-device.h" #include "device.h" #include "unit.h" const sd_bus_vtable bus_device_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("SysFSPath", "s", NULL, offsetof(Device, sysfs), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_VTABLE_END }; systemd-229/src/core/dbus-device.h000066400000000000000000000014401265713322000171420ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "unit.h" extern const sd_bus_vtable bus_device_vtable[]; systemd-229/src/core/dbus-execute.c000066400000000000000000001617641265713322000173600ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #ifdef HAVE_SECCOMP #include #endif #include "af-list.h" #include "alloc-util.h" #include "bus-util.h" #include "capability-util.h" #include "dbus-execute.h" #include "env-util.h" #include "execute.h" #include "fd-util.h" #include "fileio.h" #include "ioprio.h" #include "missing.h" #include "namespace.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "rlimit-util.h" #ifdef HAVE_SECCOMP #include "seccomp-util.h" #endif #include "strv.h" #include "syslog-util.h" #include "utf8.h" BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode); static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home, protect_home, ProtectHome); static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system, protect_system, ProtectSystem); static int property_get_environment_files( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; char **j; int r; assert(bus); assert(reply); assert(c); r = sd_bus_message_open_container(reply, 'a', "(sb)"); if (r < 0) return r; STRV_FOREACH(j, c->environment_files) { const char *fn = *j; r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-'); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_oom_score_adjust( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; int32_t n; assert(bus); assert(reply); assert(c); if (c->oom_score_adjust_set) n = c->oom_score_adjust; else { _cleanup_free_ char *t = NULL; n = 0; if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) safe_atoi32(t, &n); } return sd_bus_message_append(reply, "i", n); } static int property_get_nice( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; int32_t n; assert(bus); assert(reply); assert(c); if (c->nice_set) n = c->nice; else { errno = 0; n = getpriority(PRIO_PROCESS, 0); if (errno > 0) n = 0; } return sd_bus_message_append(reply, "i", n); } static int property_get_ioprio( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; int32_t n; assert(bus); assert(reply); assert(c); if (c->ioprio_set) n = c->ioprio; else { n = ioprio_get(IOPRIO_WHO_PROCESS, 0); if (n < 0) n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4); } return sd_bus_message_append(reply, "i", n); } static int property_get_cpu_sched_policy( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; int32_t n; assert(bus); assert(reply); assert(c); if (c->cpu_sched_set) n = c->cpu_sched_policy; else { n = sched_getscheduler(0); if (n < 0) n = SCHED_OTHER; } return sd_bus_message_append(reply, "i", n); } static int property_get_cpu_sched_priority( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; int32_t n; assert(bus); assert(reply); assert(c); if (c->cpu_sched_set) n = c->cpu_sched_priority; else { struct sched_param p = {}; if (sched_getparam(0, &p) >= 0) n = p.sched_priority; else n = 0; } return sd_bus_message_append(reply, "i", n); } static int property_get_cpu_affinity( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; assert(bus); assert(reply); assert(c); if (c->cpuset) return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus)); else return sd_bus_message_append_array(reply, 'y', NULL, 0); } static int property_get_timer_slack_nsec( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; uint64_t u; assert(bus); assert(reply); assert(c); if (c->timer_slack_nsec != NSEC_INFINITY) u = (uint64_t) c->timer_slack_nsec; else u = (uint64_t) prctl(PR_GET_TIMERSLACK); return sd_bus_message_append(reply, "t", u); } static int property_get_capability_bounding_set( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; assert(bus); assert(reply); assert(c); return sd_bus_message_append(reply, "t", c->capability_bounding_set); } static int property_get_ambient_capabilities( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; assert(bus); assert(reply); assert(c); return sd_bus_message_append(reply, "t", c->capability_ambient_set); } static int property_get_capabilities( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; _cleanup_cap_free_charp_ char *t = NULL; const char *s; assert(bus); assert(reply); assert(c); if (c->capabilities) s = t = cap_to_text(c->capabilities, NULL); else s = ""; if (!s) return -ENOMEM; return sd_bus_message_append(reply, "s", s); } static int property_get_syscall_filter( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; _cleanup_strv_free_ char **l = NULL; int r; #ifdef HAVE_SECCOMP Iterator i; void *id; #endif assert(bus); assert(reply); assert(c); r = sd_bus_message_open_container(reply, 'r', "bas"); if (r < 0) return r; r = sd_bus_message_append(reply, "b", c->syscall_whitelist); if (r < 0) return r; #ifdef HAVE_SECCOMP SET_FOREACH(id, c->syscall_filter, i) { char *name; name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1); if (!name) continue; r = strv_consume(&l, name); if (r < 0) return r; } #endif strv_sort(l); r = sd_bus_message_append_strv(reply, l); if (r < 0) return r; return sd_bus_message_close_container(reply); } static int property_get_syscall_archs( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; _cleanup_strv_free_ char **l = NULL; int r; #ifdef HAVE_SECCOMP Iterator i; void *id; #endif assert(bus); assert(reply); assert(c); #ifdef HAVE_SECCOMP SET_FOREACH(id, c->syscall_archs, i) { const char *name; name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1); if (!name) continue; r = strv_extend(&l, name); if (r < 0) return -ENOMEM; } #endif strv_sort(l); r = sd_bus_message_append_strv(reply, l); if (r < 0) return r; return 0; } static int property_get_syscall_errno( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; assert(bus); assert(reply); assert(c); return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno); } static int property_get_selinux_context( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; assert(bus); assert(reply); assert(c); return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context); } static int property_get_apparmor_profile( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; assert(bus); assert(reply); assert(c); return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile); } static int property_get_smack_process_label( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; assert(bus); assert(reply); assert(c); return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label); } static int property_get_personality( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; assert(bus); assert(reply); assert(c); return sd_bus_message_append(reply, "s", personality_to_string(c->personality)); } static int property_get_address_families( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; _cleanup_strv_free_ char **l = NULL; Iterator i; void *af; int r; assert(bus); assert(reply); assert(c); r = sd_bus_message_open_container(reply, 'r', "bas"); if (r < 0) return r; r = sd_bus_message_append(reply, "b", c->address_families_whitelist); if (r < 0) return r; SET_FOREACH(af, c->address_families, i) { const char *name; name = af_to_name(PTR_TO_INT(af)); if (!name) continue; r = strv_extend(&l, name); if (r < 0) return -ENOMEM; } strv_sort(l); r = sd_bus_message_append_strv(reply, l); if (r < 0) return r; return sd_bus_message_close_container(reply); } static int property_get_working_directory( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; const char *wd; assert(bus); assert(reply); assert(c); if (c->working_directory_home) wd = "~"; else wd = c->working_directory; if (c->working_directory_missing_ok) wd = strjoina("!", wd); return sd_bus_message_append(reply, "s", wd); } static int property_get_syslog_level( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; assert(bus); assert(reply); assert(c); return sd_bus_message_append(reply, "i", LOG_PRI(c->syslog_priority)); } static int property_get_syslog_facility( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { ExecContext *c = userdata; assert(bus); assert(reply); assert(c); return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority)); } const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PassEnvironment", "as", NULL, offsetof(ExecContext, pass_environment), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, runtime_directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, runtime_directory), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_VTABLE_END }; static int append_exec_command(sd_bus_message *reply, ExecCommand *c) { int r; assert(reply); assert(c); if (!c->path) return 0; r = sd_bus_message_open_container(reply, 'r', "sasbttttuii"); if (r < 0) return r; r = sd_bus_message_append(reply, "s", c->path); if (r < 0) return r; r = sd_bus_message_append_strv(reply, c->argv); if (r < 0) return r; r = sd_bus_message_append(reply, "bttttuii", c->ignore, c->exec_status.start_timestamp.realtime, c->exec_status.start_timestamp.monotonic, c->exec_status.exit_timestamp.realtime, c->exec_status.exit_timestamp.monotonic, (uint32_t) c->exec_status.pid, (int32_t) c->exec_status.code, (int32_t) c->exec_status.status); if (r < 0) return r; return sd_bus_message_close_container(reply); } int bus_property_get_exec_command( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error) { ExecCommand *c = (ExecCommand*) userdata; int r; assert(bus); assert(reply); r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)"); if (r < 0) return r; r = append_exec_command(reply, c); if (r < 0) return r; return sd_bus_message_close_container(reply); } int bus_property_get_exec_command_list( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error) { ExecCommand *c = *(ExecCommand**) userdata; int r; assert(bus); assert(reply); r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)"); if (r < 0) return r; LIST_FOREACH(command, c, c) { r = append_exec_command(reply, c); if (r < 0) return r; } return sd_bus_message_close_container(reply); } int bus_exec_context_set_transient_property( Unit *u, ExecContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { const char *soft = NULL; int r, ri; assert(u); assert(c); assert(name); assert(message); if (streq(name, "User")) { const char *uu; r = sd_bus_message_read(message, "s", &uu); if (r < 0) return r; if (mode != UNIT_CHECK) { if (isempty(uu)) { c->user = mfree(c->user); } else { char *t; t = strdup(uu); if (!t) return -ENOMEM; free(c->user); c->user = t; } unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu); } return 1; } else if (streq(name, "Group")) { const char *gg; r = sd_bus_message_read(message, "s", &gg); if (r < 0) return r; if (mode != UNIT_CHECK) { if (isempty(gg)) { c->group = mfree(c->group); } else { char *t; t = strdup(gg); if (!t) return -ENOMEM; free(c->group); c->group = t; } unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg); } return 1; } else if (streq(name, "SyslogIdentifier")) { const char *id; r = sd_bus_message_read(message, "s", &id); if (r < 0) return r; if (mode != UNIT_CHECK) { if (isempty(id)) { c->syslog_identifier = mfree(c->syslog_identifier); } else { char *t; t = strdup(id); if (!t) return -ENOMEM; free(c->syslog_identifier); c->syslog_identifier = t; } unit_write_drop_in_private_format(u, mode, name, "SyslogIdentifier=%s\n", id); } return 1; } else if (streq(name, "SyslogLevel")) { int level; r = sd_bus_message_read(message, "i", &level); if (r < 0) return r; if (!log_level_is_valid(level)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range"); if (mode != UNIT_CHECK) { c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level; unit_write_drop_in_private_format(u, mode, name, "SyslogLevel=%i\n", level); } return 1; } else if (streq(name, "SyslogFacility")) { int facility; r = sd_bus_message_read(message, "i", &facility); if (r < 0) return r; if (!log_facility_unshifted_is_valid(facility)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range"); if (mode != UNIT_CHECK) { c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority); unit_write_drop_in_private_format(u, mode, name, "SyslogFacility=%i\n", facility); } return 1; } else if (streq(name, "Nice")) { int n; r = sd_bus_message_read(message, "i", &n); if (r < 0) return r; if (n < PRIO_MIN || n >= PRIO_MAX) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range"); if (mode != UNIT_CHECK) { c->nice = n; unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n); } return 1; } else if (STR_IN_SET(name, "TTYPath", "RootDirectory")) { const char *s; r = sd_bus_message_read(message, "s", &s); if (r < 0) return r; if (!path_is_absolute(s)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name); if (mode != UNIT_CHECK) { if (streq(name, "TTYPath")) r = free_and_strdup(&c->tty_path, s); else { assert(streq(name, "RootDirectory")); r = free_and_strdup(&c->root_directory, s); } if (r < 0) return r; unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s); } return 1; } else if (streq(name, "WorkingDirectory")) { const char *s; bool missing_ok; r = sd_bus_message_read(message, "s", &s); if (r < 0) return r; if (s[0] == '-') { missing_ok = true; s++; } else missing_ok = false; if (!streq(s, "~") && !path_is_absolute(s)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'"); if (mode != UNIT_CHECK) { if (streq(s, "~")) { c->working_directory = mfree(c->working_directory); c->working_directory_home = true; } else { r = free_and_strdup(&c->working_directory, s); if (r < 0) return r; c->working_directory_home = false; } c->working_directory_missing_ok = missing_ok; unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s); } return 1; } else if (streq(name, "StandardInput")) { const char *s; ExecInput p; r = sd_bus_message_read(message, "s", &s); if (r < 0) return r; p = exec_input_from_string(s); if (p < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard input name"); if (mode != UNIT_CHECK) { c->std_input = p; unit_write_drop_in_private_format(u, mode, name, "StandardInput=%s\n", exec_input_to_string(p)); } return 1; } else if (streq(name, "StandardOutput")) { const char *s; ExecOutput p; r = sd_bus_message_read(message, "s", &s); if (r < 0) return r; p = exec_output_from_string(s); if (p < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard output name"); if (mode != UNIT_CHECK) { c->std_output = p; unit_write_drop_in_private_format(u, mode, name, "StandardOutput=%s\n", exec_output_to_string(p)); } return 1; } else if (streq(name, "StandardError")) { const char *s; ExecOutput p; r = sd_bus_message_read(message, "s", &s); if (r < 0) return r; p = exec_output_from_string(s); if (p < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard error name"); if (mode != UNIT_CHECK) { c->std_error = p; unit_write_drop_in_private_format(u, mode, name, "StandardError=%s\n", exec_output_to_string(p)); } return 1; } else if (STR_IN_SET(name, "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges", "SyslogLevelPrefix")) { int b; r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; if (mode != UNIT_CHECK) { if (streq(name, "IgnoreSIGPIPE")) c->ignore_sigpipe = b; else if (streq(name, "TTYVHangup")) c->tty_vhangup = b; else if (streq(name, "TTYReset")) c->tty_reset = b; else if (streq(name, "PrivateTmp")) c->private_tmp = b; else if (streq(name, "PrivateDevices")) c->private_devices = b; else if (streq(name, "PrivateNetwork")) c->private_network = b; else if (streq(name, "NoNewPrivileges")) c->no_new_privileges = b; else if (streq(name, "SyslogLevelPrefix")) c->syslog_level_prefix = b; unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, yes_no(b)); } return 1; } else if (streq(name, "UtmpIdentifier")) { const char *id; r = sd_bus_message_read(message, "s", &id); if (r < 0) return r; if (mode != UNIT_CHECK) { if (isempty(id)) c->utmp_id = mfree(c->utmp_id); else if (free_and_strdup(&c->utmp_id, id) < 0) return -ENOMEM; unit_write_drop_in_private_format(u, mode, name, "UtmpIdentifier=%s\n", strempty(id)); } return 1; } else if (streq(name, "UtmpMode")) { const char *s; ExecUtmpMode m; r = sd_bus_message_read(message, "s", &s); if (r < 0) return r; m = exec_utmp_mode_from_string(s); if (m < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid utmp mode"); if (mode != UNIT_CHECK) { c->utmp_mode = m; unit_write_drop_in_private_format(u, mode, name, "UtmpMode=%s\n", exec_utmp_mode_to_string(m)); } return 1; } else if (streq(name, "PAMName")) { const char *n; r = sd_bus_message_read(message, "s", &n); if (r < 0) return r; if (mode != UNIT_CHECK) { if (isempty(n)) c->pam_name = mfree(c->pam_name); else if (free_and_strdup(&c->pam_name, n) < 0) return -ENOMEM; unit_write_drop_in_private_format(u, mode, name, "PAMName=%s\n", strempty(n)); } return 1; } else if (streq(name, "Environment")) { _cleanup_strv_free_ char **l = NULL; r = sd_bus_message_read_strv(message, &l); if (r < 0) return r; if (!strv_env_is_valid(l)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block."); if (mode != UNIT_CHECK) { _cleanup_free_ char *joined = NULL; char **e; if (strv_length(l) == 0) { c->environment = strv_free(c->environment); unit_write_drop_in_private_format(u, mode, name, "Environment=\n"); } else { e = strv_env_merge(2, c->environment, l); if (!e) return -ENOMEM; strv_free(c->environment); c->environment = e; joined = strv_join_quoted(c->environment); if (!joined) return -ENOMEM; unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined); } } return 1; } else if (streq(name, "TimerSlackNSec")) { nsec_t n; r = sd_bus_message_read(message, "t", &n); if (r < 0) return r; if (mode != UNIT_CHECK) { c->timer_slack_nsec = n; unit_write_drop_in_private_format(u, mode, name, "TimerSlackNSec=" NSEC_FMT "\n", n); } return 1; } else if (streq(name, "OOMScoreAdjust")) { int oa; r = sd_bus_message_read(message, "i", &oa); if (r < 0) return r; if (!oom_score_adjust_is_valid(oa)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range"); if (mode != UNIT_CHECK) { c->oom_score_adjust = oa; c->oom_score_adjust_set = true; unit_write_drop_in_private_format(u, mode, name, "OOMScoreAdjust=%i\n", oa); } return 1; } else if (streq(name, "EnvironmentFiles")) { _cleanup_free_ char *joined = NULL; _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char **l = NULL; size_t size = 0; char **i; r = sd_bus_message_enter_container(message, 'a', "(sb)"); if (r < 0) return r; f = open_memstream(&joined, &size); if (!f) return -ENOMEM; STRV_FOREACH(i, c->environment_files) fprintf(f, "EnvironmentFile=%s\n", *i); while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) { const char *path; int b; r = sd_bus_message_read(message, "sb", &path, &b); if (r < 0) return r; r = sd_bus_message_exit_container(message); if (r < 0) return r; if (!isempty(path) && !path_is_absolute(path)) return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path); if (mode != UNIT_CHECK) { char *buf = NULL; buf = strjoin(b ? "-" : "", path, NULL); if (!buf) return -ENOMEM; fprintf(f, "EnvironmentFile=%s\n", buf); r = strv_consume(&l, buf); if (r < 0) return r; } } if (r < 0) return r; r = sd_bus_message_exit_container(message); if (r < 0) return r; r = fflush_and_check(f); if (r < 0) return r; if (mode != UNIT_CHECK) { if (strv_isempty(l)) { c->environment_files = strv_free(c->environment_files); unit_write_drop_in_private(u, mode, name, "EnvironmentFile=\n"); } else { r = strv_extend_strv(&c->environment_files, l, true); if (r < 0) return r; unit_write_drop_in_private(u, mode, name, joined); } } return 1; } else if (streq(name, "PassEnvironment")) { _cleanup_strv_free_ char **l = NULL; r = sd_bus_message_read_strv(message, &l); if (r < 0) return r; if (!strv_env_name_is_valid(l)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment block."); if (mode != UNIT_CHECK) { if (strv_isempty(l)) { c->pass_environment = strv_free(c->pass_environment); unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=\n"); } else { _cleanup_free_ char *joined = NULL; r = strv_extend_strv(&c->pass_environment, l, true); if (r < 0) return r; joined = strv_join_quoted(c->pass_environment); if (!joined) return -ENOMEM; unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=%s\n", joined); } } return 1; } else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) { _cleanup_strv_free_ char **l = NULL; char ***dirs; char **p; r = sd_bus_message_read_strv(message, &l); if (r < 0) return r; STRV_FOREACH(p, l) { int offset; if (!utf8_is_valid(*p)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name); offset = **p == '-'; if (!path_is_absolute(*p + offset)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name); } if (mode != UNIT_CHECK) { _cleanup_free_ char *joined = NULL; if (streq(name, "ReadWriteDirectories")) dirs = &c->read_write_dirs; else if (streq(name, "ReadOnlyDirectories")) dirs = &c->read_only_dirs; else /* "InaccessibleDirectories" */ dirs = &c->inaccessible_dirs; if (strv_length(l) == 0) { *dirs = strv_free(*dirs); unit_write_drop_in_private_format(u, mode, name, "%s=\n", name); } else { r = strv_extend_strv(dirs, l, true); if (r < 0) return -ENOMEM; joined = strv_join_quoted(*dirs); if (!joined) return -ENOMEM; unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, joined); } } return 1; } else if (streq(name, "ProtectSystem")) { const char *s; ProtectSystem ps; r = sd_bus_message_read(message, "s", &s); if (r < 0) return r; r = parse_boolean(s); if (r > 0) ps = PROTECT_SYSTEM_YES; else if (r == 0) ps = PROTECT_SYSTEM_NO; else { ps = protect_system_from_string(s); if (ps < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect system value"); } if (mode != UNIT_CHECK) { c->protect_system = ps; unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s); } return 1; } else if (streq(name, "ProtectHome")) { const char *s; ProtectHome ph; r = sd_bus_message_read(message, "s", &s); if (r < 0) return r; r = parse_boolean(s); if (r > 0) ph = PROTECT_HOME_YES; else if (r == 0) ph = PROTECT_HOME_NO; else { ph = protect_home_from_string(s); if (ph < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect home value"); } if (mode != UNIT_CHECK) { c->protect_home = ph; unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s); } return 1; } else if (streq(name, "RuntimeDirectory")) { _cleanup_strv_free_ char **l = NULL; char **p; r = sd_bus_message_read_strv(message, &l); if (r < 0) return r; STRV_FOREACH(p, l) { if (!filename_is_valid(*p)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Runtime directory is not valid %s", *p); } if (mode != UNIT_CHECK) { _cleanup_free_ char *joined = NULL; if (strv_isempty(l)) { c->runtime_directory = strv_free(c->runtime_directory); unit_write_drop_in_private_format(u, mode, name, "%s=\n", name); } else { r = strv_extend_strv(&c->runtime_directory, l, true); if (r < 0) return -ENOMEM; joined = strv_join_quoted(c->runtime_directory); if (!joined) return -ENOMEM; unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, joined); } } return 1; } ri = rlimit_from_string(name); if (ri < 0) { soft = endswith(name, "Soft"); if (soft) { const char *n; n = strndupa(name, soft - name); ri = rlimit_from_string(n); if (ri >= 0) name = n; } } if (ri >= 0) { uint64_t rl; rlim_t x; r = sd_bus_message_read(message, "t", &rl); if (r < 0) return r; if (rl == (uint64_t) -1) x = RLIM_INFINITY; else { x = (rlim_t) rl; if ((uint64_t) x != rl) return -ERANGE; } if (mode != UNIT_CHECK) { _cleanup_free_ char *f = NULL; struct rlimit nl; if (c->rlimit[ri]) { nl = *c->rlimit[ri]; if (soft) nl.rlim_cur = x; else nl.rlim_max = x; } else /* When the resource limit is not initialized yet, then assign the value to both fields */ nl = (struct rlimit) { .rlim_cur = x, .rlim_max = x, }; r = rlimit_format(&nl, &f); if (r < 0) return r; if (c->rlimit[ri]) *c->rlimit[ri] = nl; else { c->rlimit[ri] = newdup(struct rlimit, &nl, 1); if (!c->rlimit[ri]) return -ENOMEM; } unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, f); } return 1; } return 0; } systemd-229/src/core/dbus-execute.h000066400000000000000000000047321265713322000173540ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "execute.h" #define BUS_EXEC_STATUS_VTABLE(prefix, offset, flags) \ BUS_PROPERTY_DUAL_TIMESTAMP(prefix "StartTimestamp", (offset) + offsetof(ExecStatus, start_timestamp), flags), \ BUS_PROPERTY_DUAL_TIMESTAMP(prefix "ExitTimestamp", (offset) + offsetof(ExecStatus, exit_timestamp), flags), \ SD_BUS_PROPERTY(prefix "PID", "u", bus_property_get_pid, (offset) + offsetof(ExecStatus, pid), flags), \ SD_BUS_PROPERTY(prefix "Code", "i", bus_property_get_int, (offset) + offsetof(ExecStatus, code), flags), \ SD_BUS_PROPERTY(prefix "Status", "i", bus_property_get_int, (offset) + offsetof(ExecStatus, status), flags) #define BUS_EXEC_COMMAND_VTABLE(name, offset, flags) \ SD_BUS_PROPERTY(name, "a(sasbttttuii)", bus_property_get_exec_command, offset, flags) #define BUS_EXEC_COMMAND_LIST_VTABLE(name, offset, flags) \ SD_BUS_PROPERTY(name, "a(sasbttttuii)", bus_property_get_exec_command_list, offset, flags) extern const sd_bus_vtable bus_exec_vtable[]; int bus_property_get_exec_output(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error); int bus_property_get_exec_command(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error); int bus_property_get_exec_command_list(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error); int bus_exec_context_set_transient_property(Unit *u, ExecContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error); systemd-229/src/core/dbus-job.c000066400000000000000000000135211265713322000164530ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "alloc-util.h" #include "dbus-job.h" #include "dbus.h" #include "job.h" #include "log.h" #include "selinux-access.h" #include "string-util.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState); static int property_get_unit( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Job *j = userdata; assert(bus); assert(reply); assert(j); p = unit_dbus_path(j->unit); if (!p) return -ENOMEM; return sd_bus_message_append(reply, "(so)", j->unit->id, p); } int bus_job_method_cancel(sd_bus_message *message, void *userdata, sd_bus_error *error) { Job *j = userdata; int r; assert(message); assert(j); r = mac_selinux_unit_access_check(j->unit, message, "stop", error); if (r < 0) return r; /* Access is granted to the job owner */ if (!sd_bus_track_contains(j->clients, sd_bus_message_get_sender(message))) { /* And for everybody else consult PolicyKit */ r = bus_verify_manage_units_async(j->unit->manager, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ } job_finish_and_invalidate(j, JOB_CANCELED, true); return sd_bus_reply_method_return(message, NULL); } const sd_bus_vtable bus_job_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_METHOD("Cancel", NULL, NULL, bus_job_method_cancel, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Job, id), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Unit", "(so)", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("JobType", "s", property_get_type, offsetof(Job, type), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("State", "s", property_get_state, offsetof(Job, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_VTABLE_END }; static int send_new_signal(sd_bus *bus, void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_free_ char *p = NULL; Job *j = userdata; int r; assert(bus); assert(j); p = job_dbus_path(j); if (!p) return -ENOMEM; r = sd_bus_message_new_signal( bus, &m, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "JobNew"); if (r < 0) return r; r = sd_bus_message_append(m, "uos", j->id, p, j->unit->id); if (r < 0) return r; return sd_bus_send(bus, m, NULL); } static int send_changed_signal(sd_bus *bus, void *userdata) { _cleanup_free_ char *p = NULL; Job *j = userdata; assert(bus); assert(j); p = job_dbus_path(j); if (!p) return -ENOMEM; return sd_bus_emit_properties_changed(bus, p, "org.freedesktop.systemd1.Job", "State", NULL); } void bus_job_send_change_signal(Job *j) { int r; assert(j); if (j->in_dbus_queue) { LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j); j->in_dbus_queue = false; } r = bus_foreach_bus(j->manager, j->clients, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal, j); if (r < 0) log_debug_errno(r, "Failed to send job change signal for %u: %m", j->id); j->sent_dbus_new_signal = true; } static int send_removed_signal(sd_bus *bus, void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_free_ char *p = NULL; Job *j = userdata; int r; assert(bus); assert(j); p = job_dbus_path(j); if (!p) return -ENOMEM; r = sd_bus_message_new_signal( bus, &m, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "JobRemoved"); if (r < 0) return r; r = sd_bus_message_append(m, "uoss", j->id, p, j->unit->id, job_result_to_string(j->result)); if (r < 0) return r; return sd_bus_send(bus, m, NULL); } void bus_job_send_removed_signal(Job *j) { int r; assert(j); if (!j->sent_dbus_new_signal) bus_job_send_change_signal(j); r = bus_foreach_bus(j->manager, j->clients, send_removed_signal, j); if (r < 0) log_debug_errno(r, "Failed to send job remove signal for %u: %m", j->id); } systemd-229/src/core/dbus-job.h000066400000000000000000000017321265713322000164610ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "job.h" extern const sd_bus_vtable bus_job_vtable[]; int bus_job_method_cancel(sd_bus_message *message, void *job, sd_bus_error *error); void bus_job_send_change_signal(Job *j); void bus_job_send_removed_signal(Job *j); systemd-229/src/core/dbus-kill.c000066400000000000000000000076051265713322000166420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-util.h" #include "dbus-kill.h" #include "kill.h" #include "signal-util.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_kill_mode, kill_mode, KillMode); const sd_bus_vtable bus_kill_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("KillMode", "s", property_get_kill_mode, offsetof(KillContext, kill_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("KillSignal", "i", bus_property_get_int, offsetof(KillContext, kill_signal), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SendSIGKILL", "b", bus_property_get_bool, offsetof(KillContext, send_sigkill), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SendSIGHUP", "b", bus_property_get_bool, offsetof(KillContext, send_sighup), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_VTABLE_END }; int bus_kill_context_set_transient_property( Unit *u, KillContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { int r; assert(u); assert(c); assert(name); assert(message); if (streq(name, "KillMode")) { const char *m; KillMode k; r = sd_bus_message_read(message, "s", &m); if (r < 0) return r; k = kill_mode_from_string(m); if (k < 0) return -EINVAL; if (mode != UNIT_CHECK) { c->kill_mode = k; unit_write_drop_in_private_format(u, mode, name, "KillMode=%s\n", kill_mode_to_string(k)); } return 1; } else if (streq(name, "KillSignal")) { int sig; r = sd_bus_message_read(message, "i", &sig); if (r < 0) return r; if (sig <= 0 || sig >= _NSIG) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal %i out of range", sig); if (mode != UNIT_CHECK) { c->kill_signal = sig; unit_write_drop_in_private_format(u, mode, name, "KillSignal=%s\n", signal_to_string(sig)); } return 1; } else if (streq(name, "SendSIGHUP")) { int b; r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; if (mode != UNIT_CHECK) { c->send_sighup = b; unit_write_drop_in_private_format(u, mode, name, "SendSIGHUP=%s\n", yes_no(b)); } return 1; } else if (streq(name, "SendSIGKILL")) { int b; r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; if (mode != UNIT_CHECK) { c->send_sigkill = b; unit_write_drop_in_private_format(u, mode, name, "SendSIGKILL=%s\n", yes_no(b)); } return 1; } return 0; } systemd-229/src/core/dbus-kill.h000066400000000000000000000017501265713322000166420ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "kill.h" #include "unit.h" extern const sd_bus_vtable bus_kill_vtable[]; int bus_kill_context_set_transient_property(Unit *u, KillContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error); systemd-229/src/core/dbus-manager.c000066400000000000000000002300121265713322000173070ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "architecture.h" #include "build.h" #include "bus-common-errors.h" #include "clock-util.h" #include "dbus-execute.h" #include "dbus-job.h" #include "dbus-manager.h" #include "dbus-unit.h" #include "dbus.h" #include "env-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "install.h" #include "log.h" #include "path-util.h" #include "selinux-access.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" #include "syslog-util.h" #include "virt.h" #include "watchdog.h" static int property_get_version( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { assert(bus); assert(reply); return sd_bus_message_append(reply, "s", PACKAGE_VERSION); } static int property_get_features( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { assert(bus); assert(reply); return sd_bus_message_append(reply, "s", SYSTEMD_FEATURES); } static int property_get_virtualization( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { int v; assert(bus); assert(reply); v = detect_virtualization(); /* Make sure to return the empty string when we detect no virtualization, as that is the API. * * https://github.com/systemd/systemd/issues/1423 */ return sd_bus_message_append( reply, "s", v == VIRTUALIZATION_NONE ? "" : virtualization_to_string(v)); } static int property_get_architecture( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { assert(bus); assert(reply); return sd_bus_message_append(reply, "s", architecture_to_string(uname_architecture())); } static int property_get_tainted( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { char buf[sizeof("split-usr:cgroups-missing:local-hwclock:")] = "", *e = buf; Manager *m = userdata; assert(bus); assert(reply); assert(m); if (m->taint_usr) e = stpcpy(e, "split-usr:"); if (access("/proc/cgroups", F_OK) < 0) e = stpcpy(e, "cgroups-missing:"); if (clock_is_localtime() > 0) e = stpcpy(e, "local-hwclock:"); /* remove the last ':' */ if (e != buf) e[-1] = 0; return sd_bus_message_append(reply, "s", buf); } static int property_get_log_target( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { assert(bus); assert(reply); return sd_bus_message_append(reply, "s", log_target_to_string(log_get_target())); } static int property_set_log_target( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) { const char *t; int r; assert(bus); assert(value); r = sd_bus_message_read(value, "s", &t); if (r < 0) return r; return log_set_target_from_string(t); } static int property_get_log_level( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_free_ char *t = NULL; int r; assert(bus); assert(reply); r = log_level_to_string_alloc(log_get_max_level(), &t); if (r < 0) return r; return sd_bus_message_append(reply, "s", t); } static int property_set_log_level( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) { const char *t; int r; assert(bus); assert(value); r = sd_bus_message_read(value, "s", &t); if (r < 0) return r; r = log_set_max_level_from_string(t); if (r == 0) log_info("Setting log level to %s.", t); return r; } static int property_get_n_names( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; assert(bus); assert(reply); assert(m); return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->units)); } static int property_get_n_failed_units( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; assert(bus); assert(reply); assert(m); return sd_bus_message_append(reply, "u", (uint32_t) set_size(m->failed_units)); } static int property_get_n_jobs( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; assert(bus); assert(reply); assert(m); return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->jobs)); } static int property_get_progress( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; double d; assert(bus); assert(reply); assert(m); if (dual_timestamp_is_set(&m->finish_timestamp)) d = 1.0; else d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs); return sd_bus_message_append(reply, "d", d); } static int property_get_system_state( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; assert(bus); assert(reply); assert(m); return sd_bus_message_append(reply, "s", manager_state_to_string(manager_state(m))); } static int property_set_runtime_watchdog( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) { usec_t *t = userdata; int r; assert(bus); assert(value); assert_cc(sizeof(usec_t) == sizeof(uint64_t)); r = sd_bus_message_read(value, "t", t); if (r < 0) return r; return watchdog_set_timeout(t); } static int property_get_timer_slack_nsec( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { assert(bus); assert(reply); return sd_bus_message_append(reply, "t", (uint64_t) prctl(PR_GET_TIMERSLACK)); } static int method_get_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *path = NULL; Manager *m = userdata; const char *name; Unit *u; int r; assert(message); assert(m); /* Anyone can call this method */ r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; if (isempty(name)) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; pid_t pid; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); if (r < 0) return r; r = sd_bus_creds_get_pid(creds, &pid); if (r < 0) return r; u = manager_get_unit_by_pid(m, pid); if (!u) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client not member of any unit."); } else { u = manager_get_unit(m, name); if (!u) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name); } r = mac_selinux_unit_access_check(u, message, "status", error); if (r < 0) return r; path = unit_dbus_path(u); if (!path) return -ENOMEM; return sd_bus_reply_method_return(message, "o", path); } static int method_get_unit_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *path = NULL; Manager *m = userdata; pid_t pid; Unit *u; int r; assert(message); assert(m); assert_cc(sizeof(pid_t) == sizeof(uint32_t)); /* Anyone can call this method */ r = sd_bus_message_read(message, "u", &pid); if (r < 0) return r; if (pid < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PID " PID_FMT, pid); if (pid == 0) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); if (r < 0) return r; r = sd_bus_creds_get_pid(creds, &pid); if (r < 0) return r; } u = manager_get_unit_by_pid(m, pid); if (!u) return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID "PID_FMT" does not belong to any loaded unit.", pid); r = mac_selinux_unit_access_check(u, message, "status", error); if (r < 0) return r; path = unit_dbus_path(u); if (!path) return -ENOMEM; return sd_bus_reply_method_return(message, "o", path); } static int method_load_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *path = NULL; Manager *m = userdata; const char *name; Unit *u; int r; assert(message); assert(m); /* Anyone can call this method */ r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; if (isempty(name)) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; pid_t pid; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); if (r < 0) return r; r = sd_bus_creds_get_pid(creds, &pid); if (r < 0) return r; u = manager_get_unit_by_pid(m, pid); if (!u) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client not member of any unit."); } else { r = manager_load_unit(m, name, NULL, error, &u); if (r < 0) return r; } r = mac_selinux_unit_access_check(u, message, "status", error); if (r < 0) return r; path = unit_dbus_path(u); if (!path) return -ENOMEM; return sd_bus_reply_method_return(message, "o", path); } static int method_start_unit_generic(sd_bus_message *message, Manager *m, JobType job_type, bool reload_if_possible, sd_bus_error *error) { const char *name; Unit *u; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = manager_load_unit(m, name, NULL, error, &u); if (r < 0) return r; return bus_unit_method_start_generic(message, u, job_type, reload_if_possible, error); } static int method_start_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_start_unit_generic(message, userdata, JOB_START, false, error); } static int method_stop_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_start_unit_generic(message, userdata, JOB_STOP, false, error); } static int method_reload_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_start_unit_generic(message, userdata, JOB_RELOAD, false, error); } static int method_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_start_unit_generic(message, userdata, JOB_RESTART, false, error); } static int method_try_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, false, error); } static int method_reload_or_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_start_unit_generic(message, userdata, JOB_RESTART, true, error); } static int method_reload_or_try_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, true, error); } static int method_start_unit_replace(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; const char *old_name; Unit *u; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &old_name); if (r < 0) return r; u = manager_get_unit(m, old_name); if (!u || !u->job || u->job->type != JOB_START) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name); return method_start_unit_generic(message, m, JOB_START, false, error); } static int method_kill_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; const char *name; Unit *u; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; u = manager_get_unit(m, name); if (!u) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name); return bus_unit_method_kill(message, u, error); } static int method_reset_failed_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; const char *name; Unit *u; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; u = manager_get_unit(m, name); if (!u) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name); return bus_unit_method_reset_failed(message, u, error); } static int method_set_unit_properties(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; const char *name; Unit *u; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = manager_load_unit(m, name, NULL, error, &u); if (r < 0) return r; r = bus_unit_check_load_state(u, error); if (r < 0) return r; return bus_unit_method_set_properties(message, u, error); } static int transient_unit_from_message( Manager *m, sd_bus_message *message, const char *name, Unit **unit, sd_bus_error *error) { UnitType t; Unit *u; int r; assert(m); assert(message); assert(name); t = unit_name_to_type(name); if (t < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name or type."); if (!unit_vtable[t]->can_transient) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t)); r = manager_load_unit(m, name, NULL, error, &u); if (r < 0) return r; if (!unit_is_pristine(u)) return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name); /* OK, the unit failed to load and is unreferenced, now let's * fill in the transient data instead */ r = unit_make_transient(u); if (r < 0) return r; /* Set our properties */ r = bus_unit_set_properties(u, message, UNIT_RUNTIME, false, error); if (r < 0) return r; /* Now load the missing bits of the unit we just created */ manager_dispatch_load_queue(m); *unit = u; return 0; } static int transient_aux_units_from_message( Manager *m, sd_bus_message *message, sd_bus_error *error) { int r; assert(m); assert(message); r = sd_bus_message_enter_container(message, 'a', "(sa(sv))"); if (r < 0) return r; while ((r = sd_bus_message_enter_container(message, 'r', "sa(sv)")) > 0) { const char *name = NULL; Unit *u; r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = transient_unit_from_message(m, message, name, &u, error); if (r < 0) return r; r = sd_bus_message_exit_container(message); if (r < 0) return r; } if (r < 0) return r; r = sd_bus_message_exit_container(message); if (r < 0) return r; return 0; } static int method_start_transient_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *name, *smode; Manager *m = userdata; JobMode mode; Unit *u; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "start", error); if (r < 0) return r; r = sd_bus_message_read(message, "ss", &name, &smode); if (r < 0) return r; mode = job_mode_from_string(smode); if (mode < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode); r = bus_verify_manage_units_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = transient_unit_from_message(m, message, name, &u, error); if (r < 0) return r; r = transient_aux_units_from_message(m, message, error); if (r < 0) return r; /* Finally, start it */ return bus_unit_queue_job(message, u, JOB_START, mode, false, error); } static int method_get_job(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *path = NULL; Manager *m = userdata; uint32_t id; Job *j; int r; assert(message); assert(m); /* Anyone can call this method */ r = sd_bus_message_read(message, "u", &id); if (r < 0) return r; j = manager_get_job(m, id); if (!j) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id); r = mac_selinux_unit_access_check(j->unit, message, "status", error); if (r < 0) return r; path = job_dbus_path(j); if (!path) return -ENOMEM; return sd_bus_reply_method_return(message, "o", path); } static int method_cancel_job(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; uint32_t id; Job *j; int r; assert(message); assert(m); r = sd_bus_message_read(message, "u", &id); if (r < 0) return r; j = manager_get_job(m, id); if (!j) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id); return bus_job_method_cancel(message, j, error); } static int method_clear_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "reload", error); if (r < 0) return r; r = bus_verify_manage_units_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ manager_clear_jobs(m); return sd_bus_reply_method_return(message, NULL); } static int method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "reload", error); if (r < 0) return r; r = bus_verify_manage_units_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ manager_reset_failed(m); return sd_bus_reply_method_return(message, NULL); } static int list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; const char *k; Iterator i; Unit *u; int r; assert(message); assert(m); /* Anyone can call this method */ r = mac_selinux_access_check(message, "status", error); if (r < 0) return r; r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)"); if (r < 0) return r; HASHMAP_FOREACH_KEY(u, k, m->units, i) { _cleanup_free_ char *unit_path = NULL, *job_path = NULL; Unit *following; if (k != u->id) continue; following = unit_following(u); if (!strv_isempty(states) && !strv_contains(states, unit_load_state_to_string(u->load_state)) && !strv_contains(states, unit_active_state_to_string(unit_active_state(u))) && !strv_contains(states, unit_sub_state_to_string(u))) continue; unit_path = unit_dbus_path(u); if (!unit_path) return -ENOMEM; if (u->job) { job_path = job_dbus_path(u->job); if (!job_path) return -ENOMEM; } r = sd_bus_message_append( reply, "(ssssssouso)", u->id, unit_description(u), unit_load_state_to_string(u->load_state), unit_active_state_to_string(unit_active_state(u)), unit_sub_state_to_string(u), following ? following->id : "", unit_path, u->job ? u->job->id : 0, u->job ? job_type_to_string(u->job->type) : "", job_path ? job_path : "/"); if (r < 0) return r; } r = sd_bus_message_close_container(reply); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); } static int method_list_units(sd_bus_message *message, void *userdata, sd_bus_error *error) { return list_units_filtered(message, userdata, error, NULL); } static int method_list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_strv_free_ char **states = NULL; int r; r = sd_bus_message_read_strv(message, &states); if (r < 0) return r; return list_units_filtered(message, userdata, error, states); } static int method_list_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; Iterator i; Job *j; int r; assert(message); assert(m); /* Anyone can call this method */ r = mac_selinux_access_check(message, "status", error); if (r < 0) return r; r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "(usssoo)"); if (r < 0) return r; HASHMAP_FOREACH(j, m->jobs, i) { _cleanup_free_ char *unit_path = NULL, *job_path = NULL; job_path = job_dbus_path(j); if (!job_path) return -ENOMEM; unit_path = unit_dbus_path(j->unit); if (!unit_path) return -ENOMEM; r = sd_bus_message_append( reply, "(usssoo)", j->id, j->unit->id, job_type_to_string(j->type), job_state_to_string(j->state), job_path, unit_path); if (r < 0) return r; } r = sd_bus_message_close_container(reply); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); } static int method_subscribe(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; int r; assert(message); assert(m); /* Anyone can call this method */ r = mac_selinux_access_check(message, "status", error); if (r < 0) return r; if (sd_bus_message_get_bus(message) == m->api_bus) { /* Note that direct bus connection subscribe by * default, we only track peers on the API bus here */ if (!m->subscribed) { r = sd_bus_track_new(sd_bus_message_get_bus(message), &m->subscribed, NULL, NULL); if (r < 0) return r; } r = sd_bus_track_add_sender(m->subscribed, message); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed."); } return sd_bus_reply_method_return(message, NULL); } static int method_unsubscribe(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; int r; assert(message); assert(m); /* Anyone can call this method */ r = mac_selinux_access_check(message, "status", error); if (r < 0) return r; if (sd_bus_message_get_bus(message) == m->api_bus) { r = sd_bus_track_remove_sender(m->subscribed, message); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed."); } return sd_bus_reply_method_return(message, NULL); } static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *dump = NULL; _cleanup_fclose_ FILE *f = NULL; Manager *m = userdata; size_t size; int r; assert(message); assert(m); /* Anyone can call this method */ r = mac_selinux_access_check(message, "status", error); if (r < 0) return r; f = open_memstream(&dump, &size); if (!f) return -ENOMEM; manager_dump_units(m, f, NULL); manager_dump_jobs(m, f, NULL); r = fflush_and_check(f); if (r < 0) return r; return sd_bus_reply_method_return(message, "s", dump); } static int method_refuse_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) { return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for snapshots has been removed."); } static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "reload", error); if (r < 0) return r; r = bus_verify_reload_daemon_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ /* Instead of sending the reply back right away, we just * remember that we need to and then send it after the reload * is finished. That way the caller knows when the reload * finished. */ assert(!m->queued_message); r = sd_bus_message_new_method_return(message, &m->queued_message); if (r < 0) return r; m->exit_code = MANAGER_RELOAD; return 1; } static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "reload", error); if (r < 0) return r; r = bus_verify_reload_daemon_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ /* We don't send a reply back here, the client should * just wait for us disconnecting. */ m->exit_code = MANAGER_REEXECUTE; return 1; } static int method_exit(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "halt", error); if (r < 0) return r; /* Exit() (in contrast to SetExitCode()) is actually allowed even if * we are running on the host. It will fall back on reboot() in * systemd-shutdown if it cannot do the exit() because it isn't a * container. */ m->exit_code = MANAGER_EXIT; return sd_bus_reply_method_return(message, NULL); } static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "reboot", error); if (r < 0) return r; if (m->running_as != MANAGER_SYSTEM) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers."); m->exit_code = MANAGER_REBOOT; return sd_bus_reply_method_return(message, NULL); } static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "halt", error); if (r < 0) return r; if (m->running_as != MANAGER_SYSTEM) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers."); m->exit_code = MANAGER_POWEROFF; return sd_bus_reply_method_return(message, NULL); } static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "halt", error); if (r < 0) return r; if (m->running_as != MANAGER_SYSTEM) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers."); m->exit_code = MANAGER_HALT; return sd_bus_reply_method_return(message, NULL); } static int method_kexec(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "reboot", error); if (r < 0) return r; if (m->running_as != MANAGER_SYSTEM) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers."); m->exit_code = MANAGER_KEXEC; return sd_bus_reply_method_return(message, NULL); } static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_error *error) { char *ri = NULL, *rt = NULL; const char *root, *init; Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "reboot", error); if (r < 0) return r; if (m->running_as != MANAGER_SYSTEM) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Root switching is only supported by system manager."); r = sd_bus_message_read(message, "ss", &root, &init); if (r < 0) return r; if (path_equal(root, "/") || !path_is_absolute(root)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid switch root path %s", root); /* Safety check */ if (isempty(init)) { if (!path_is_os_tree(root)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path %s does not seem to be an OS tree. os-release file is missing.", root); } else { _cleanup_free_ char *p = NULL; if (!path_is_absolute(init)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init); p = strappend(root, init); if (!p) return -ENOMEM; if (access(p, X_OK) < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p); } rt = strdup(root); if (!rt) return -ENOMEM; if (!isempty(init)) { ri = strdup(init); if (!ri) { free(rt); return -ENOMEM; } } free(m->switch_root); m->switch_root = rt; free(m->switch_root_init); m->switch_root_init = ri; m->exit_code = MANAGER_SWITCH_ROOT; return sd_bus_reply_method_return(message, NULL); } static int method_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_strv_free_ char **plus = NULL; Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "reload", error); if (r < 0) return r; r = sd_bus_message_read_strv(message, &plus); if (r < 0) return r; if (!strv_env_is_valid(plus)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments"); r = bus_verify_set_environment_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = manager_environment_add(m, NULL, plus); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_unset_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_strv_free_ char **minus = NULL; Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "reload", error); if (r < 0) return r; r = sd_bus_message_read_strv(message, &minus); if (r < 0) return r; if (!strv_env_name_or_assignment_is_valid(minus)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments"); r = bus_verify_set_environment_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = manager_environment_add(m, minus, NULL); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_unset_and_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_strv_free_ char **minus = NULL, **plus = NULL; Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "reload", error); if (r < 0) return r; r = sd_bus_message_read_strv(message, &minus); if (r < 0) return r; r = sd_bus_message_read_strv(message, &plus); if (r < 0) return r; if (!strv_env_name_or_assignment_is_valid(minus)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments"); if (!strv_env_is_valid(plus)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments"); r = bus_verify_set_environment_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = manager_environment_add(m, minus, plus); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_set_exit_code(sd_bus_message *message, void *userdata, sd_bus_error *error) { uint8_t code; Manager *m = userdata; int r; assert(message); assert(m); r = mac_selinux_access_check(message, "exit", error); if (r < 0) return r; r = sd_bus_message_read_basic(message, 'y', &code); if (r < 0) return r; if (m->running_as == MANAGER_SYSTEM && detect_container() <= 0) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "ExitCode can only be set for user service managers or in containers."); m->return_value = code; return sd_bus_reply_method_return(message, NULL); } static int method_list_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; UnitFileList *item; Hashmap *h; Iterator i; int r; assert(message); assert(m); /* Anyone can call this method */ r = mac_selinux_access_check(message, "status", error); if (r < 0) return r; r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; h = hashmap_new(&string_hash_ops); if (!h) return -ENOMEM; r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h); if (r < 0) goto fail; r = sd_bus_message_open_container(reply, 'a', "(ss)"); if (r < 0) goto fail; HASHMAP_FOREACH(item, h, i) { r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state)); if (r < 0) goto fail; } unit_file_list_free(h); r = sd_bus_message_close_container(reply); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); fail: unit_file_list_free(h); return r; } static int method_get_unit_file_state(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; const char *name; UnitFileState state; UnitFileScope scope; int r; assert(message); assert(m); /* Anyone can call this method */ r = mac_selinux_access_check(message, "status", error); if (r < 0) return r; r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; r = unit_file_get_state(scope, NULL, name, &state); if (r < 0) return r; return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state)); } static int method_get_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *default_target = NULL; Manager *m = userdata; UnitFileScope scope; int r; assert(message); assert(m); /* Anyone can call this method */ r = mac_selinux_access_check(message, "status", error); if (r < 0) return r; scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; r = unit_file_get_default(scope, NULL, &default_target); if (r < 0) return r; return sd_bus_reply_method_return(message, "s", default_target); } static int send_unit_files_changed(sd_bus *bus, void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL; int r; assert(bus); r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged"); if (r < 0) return r; return sd_bus_send(bus, message, NULL); } static int reply_unit_file_changes_and_free( Manager *m, sd_bus_message *message, int carries_install_info, UnitFileChange *changes, unsigned n_changes) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; unsigned i; int r; if (n_changes > 0) { r = bus_foreach_bus(m, NULL, send_unit_files_changed, NULL); if (r < 0) log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m"); } r = sd_bus_message_new_method_return(message, &reply); if (r < 0) goto fail; if (carries_install_info >= 0) { r = sd_bus_message_append(reply, "b", carries_install_info); if (r < 0) goto fail; } r = sd_bus_message_open_container(reply, 'a', "(sss)"); if (r < 0) goto fail; for (i = 0; i < n_changes; i++) { r = sd_bus_message_append( reply, "(sss)", unit_file_change_type_to_string(changes[i].type), changes[i].path, changes[i].source); if (r < 0) goto fail; } r = sd_bus_message_close_container(reply); if (r < 0) goto fail; unit_file_changes_free(changes, n_changes); return sd_bus_send(NULL, reply, NULL); fail: unit_file_changes_free(changes, n_changes); return r; } static int method_enable_unit_files_generic( sd_bus_message *message, Manager *m, const char *verb, int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes), bool carries_install_info, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; UnitFileChange *changes = NULL; unsigned n_changes = 0; UnitFileScope scope; int runtime, force, r; assert(message); assert(m); r = sd_bus_message_read_strv(message, &l); if (r < 0) return r; r = sd_bus_message_read(message, "bb", &runtime, &force); if (r < 0) return r; r = bus_verify_manage_unit_files_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; r = call(scope, runtime, NULL, l, force, &changes, &n_changes); if (r == -ESHUTDOWN) return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked"); if (r < 0) return r; return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes); } static int method_enable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_enable_unit_files_generic(message, userdata, "enable", unit_file_enable, true, error); } static int method_reenable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_enable_unit_files_generic(message, userdata, "enable", unit_file_reenable, true, error); } static int method_link_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_enable_unit_files_generic(message, userdata, "enable", unit_file_link, false, error); } static int unit_file_preset_without_mode(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes) { return unit_file_preset(scope, runtime, root_dir, files, UNIT_FILE_PRESET_FULL, force, changes, n_changes); } static int method_preset_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_enable_unit_files_generic(message, userdata, "enable", unit_file_preset_without_mode, true, error); } static int method_mask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_enable_unit_files_generic(message, userdata, "disable", unit_file_mask, false, error); } static int method_preset_unit_files_with_mode(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; UnitFileChange *changes = NULL; unsigned n_changes = 0; Manager *m = userdata; UnitFilePresetMode mm; UnitFileScope scope; int runtime, force, r; const char *mode; assert(message); assert(m); r = sd_bus_message_read_strv(message, &l); if (r < 0) return r; r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force); if (r < 0) return r; if (isempty(mode)) mm = UNIT_FILE_PRESET_FULL; else { mm = unit_file_preset_mode_from_string(mode); if (mm < 0) return -EINVAL; } r = bus_verify_manage_unit_files_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; r = unit_file_preset(scope, runtime, NULL, l, mm, force, &changes, &n_changes); if (r < 0) return r; return reply_unit_file_changes_and_free(m, message, r, changes, n_changes); } static int method_disable_unit_files_generic( sd_bus_message *message, Manager *m, const char *verb, int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes), sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; UnitFileChange *changes = NULL; unsigned n_changes = 0; UnitFileScope scope; int r, runtime; assert(message); assert(m); r = sd_bus_message_read_strv(message, &l); if (r < 0) return r; r = sd_bus_message_read(message, "b", &runtime); if (r < 0) return r; scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; r = bus_verify_manage_unit_files_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = call(scope, runtime, NULL, l, &changes, &n_changes); if (r < 0) return r; return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } static int method_disable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_disable_unit_files_generic(message, userdata, "disable", unit_file_disable, error); } static int method_unmask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_disable_unit_files_generic(message, userdata, "enable", unit_file_unmask, error); } static int method_set_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) { UnitFileChange *changes = NULL; unsigned n_changes = 0; Manager *m = userdata; UnitFileScope scope; const char *name; int force, r; assert(message); assert(m); r = mac_selinux_access_check(message, "enable", error); if (r < 0) return r; r = sd_bus_message_read(message, "sb", &name, &force); if (r < 0) return r; r = bus_verify_manage_unit_files_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes); if (r < 0) return r; return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { UnitFileChange *changes = NULL; unsigned n_changes = 0; Manager *m = userdata; UnitFilePresetMode mm; UnitFileScope scope; const char *mode; int force, runtime, r; assert(message); assert(m); r = mac_selinux_access_check(message, "enable", error); if (r < 0) return r; r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force); if (r < 0) return r; if (isempty(mode)) mm = UNIT_FILE_PRESET_FULL; else { mm = unit_file_preset_mode_from_string(mode); if (mm < 0) return -EINVAL; } r = bus_verify_manage_unit_files_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; r = unit_file_preset_all(scope, runtime, NULL, mm, force, &changes, &n_changes); if (r < 0) { unit_file_changes_free(changes, n_changes); return r; } return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } static int method_add_dependency_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; Manager *m = userdata; UnitFileChange *changes = NULL; unsigned n_changes = 0; UnitFileScope scope; int runtime, force, r; char *target; char *type; UnitDependency dep; assert(message); assert(m); r = bus_verify_manage_unit_files_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = sd_bus_message_read_strv(message, &l); if (r < 0) return r; r = sd_bus_message_read(message, "ssbb", &target, &type, &runtime, &force); if (r < 0) return r; dep = unit_dependency_from_string(type); if (dep < 0) return -EINVAL; scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER; r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, force, &changes, &n_changes); if (r == -ESHUTDOWN) return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked"); if (r < 0) return r; return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Version", "s", property_get_version, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Features", "s", property_get_features, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Architecture", "s", property_get_architecture, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, firmware_timestamp), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, loader_timestamp), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, kernel_timestamp), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, initrd_timestamp), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, userspace_timestamp), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, security_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, security_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, generators_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, generators_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, units_load_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, units_load_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0), SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0), SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0), SD_BUS_PROPERTY("NFailedUnits", "u", property_get_n_failed_units, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0), SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0), SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0), SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0), SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0), SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.unit_path), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0), SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0), SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0), SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0), SD_BUS_PROPERTY("ExitCode", "y", bus_property_get_unsigned, offsetof(Manager, return_value), 0), SD_BUS_PROPERTY("DefaultTimerAccuracyUSec", "t", bus_property_get_usec, offsetof(Manager, default_timer_accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultTimeoutStartUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultTimeoutStopUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultRestartUSec", "t", bus_property_get_usec, offsetof(Manager, default_restart_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultStartLimitInterval", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultStartLimitBurst", "u", bus_property_get_unsigned, offsetof(Manager, default_start_limit_burst), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultCPUAccounting", "b", bus_property_get_bool, offsetof(Manager, default_cpu_accounting), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultBlockIOAccounting", "b", bus_property_get_bool, offsetof(Manager, default_blockio_accounting), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultMemoryAccounting", "b", bus_property_get_bool, offsetof(Manager, default_memory_accounting), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultTasksAccounting", "b", bus_property_get_bool, offsetof(Manager, default_tasks_accounting), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitCPU", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitCPUSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitFSIZE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitDATA", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitDATASoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitSTACK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitCORE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitCORESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitRSS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitRSSSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitNOFILE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitAS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitASSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitNPROC", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitLOCKS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitNICE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitNICESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitRTPRIO", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitRTTIME", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultLimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultTasksMax", "t", NULL, offsetof(Manager, default_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ListUnitsFiltered", "as", "a(ssssssouso)", method_list_units_filtered, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0), SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), SD_BUS_METHOD("Halt", NULL, NULL, method_halt, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("PresetUnitFilesWithMode", "assbb", "ba(sss)", method_preset_unit_files_with_mode, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("AddDependencyUnitFiles", "asssbb", "a(sss)", method_add_dependency_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetExitCode", "y", NULL, method_set_exit_code, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("UnitNew", "so", 0), SD_BUS_SIGNAL("UnitRemoved", "so", 0), SD_BUS_SIGNAL("JobNew", "uos", 0), SD_BUS_SIGNAL("JobRemoved", "uoss", 0), SD_BUS_SIGNAL("StartupFinished", "tttttt", 0), SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0), SD_BUS_SIGNAL("Reloading", "b", 0), SD_BUS_VTABLE_END }; static int send_finished(sd_bus *bus, void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL; usec_t *times = userdata; int r; assert(bus); assert(times); r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished"); if (r < 0) return r; r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]); if (r < 0) return r; return sd_bus_send(bus, message, NULL); } void bus_manager_send_finished( Manager *m, usec_t firmware_usec, usec_t loader_usec, usec_t kernel_usec, usec_t initrd_usec, usec_t userspace_usec, usec_t total_usec) { int r; assert(m); r = bus_foreach_bus( m, NULL, send_finished, (usec_t[6]) { firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec }); if (r < 0) log_debug_errno(r, "Failed to send finished signal: %m"); } static int send_reloading(sd_bus *bus, void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL; int r; assert(bus); r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading"); if (r < 0) return r; r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata)); if (r < 0) return r; return sd_bus_send(bus, message, NULL); } void bus_manager_send_reloading(Manager *m, bool active) { int r; assert(m); r = bus_foreach_bus(m, NULL, send_reloading, INT_TO_PTR(active)); if (r < 0) log_debug_errno(r, "Failed to send reloading signal: %m"); } static int send_changed_signal(sd_bus *bus, void *userdata) { assert(bus); return sd_bus_emit_properties_changed_strv(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", NULL); } void bus_manager_send_change_signal(Manager *m) { int r; assert(m); r = bus_foreach_bus(m, NULL, send_changed_signal, NULL); if (r < 0) log_debug_errno(r, "Failed to send manager change signal: %m"); } systemd-229/src/core/dbus-manager.h000066400000000000000000000020701265713322000173150ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "manager.h" extern const sd_bus_vtable bus_manager_vtable[]; void bus_manager_send_finished(Manager *m, usec_t firmware_usec, usec_t loader_usec, usec_t kernel_usec, usec_t initrd_usec, usec_t userspace_usec, usec_t total_usec); void bus_manager_send_reloading(Manager *m, bool active); void bus_manager_send_change_signal(Manager *m); systemd-229/src/core/dbus-mount.c000066400000000000000000000160051265713322000170430ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-util.h" #include "dbus-cgroup.h" #include "dbus-execute.h" #include "dbus-kill.h" #include "dbus-mount.h" #include "mount.h" #include "string-util.h" #include "unit.h" static int property_get_what( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Mount *m = userdata; const char *d; assert(bus); assert(reply); assert(m); if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.what) d = m->parameters_proc_self_mountinfo.what; else if (m->from_fragment && m->parameters_fragment.what) d = m->parameters_fragment.what; else d = ""; return sd_bus_message_append(reply, "s", d); } static int property_get_options( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Mount *m = userdata; const char *d; assert(bus); assert(reply); assert(m); if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.options) d = m->parameters_proc_self_mountinfo.options; else if (m->from_fragment && m->parameters_fragment.options) d = m->parameters_fragment.options; else d = ""; return sd_bus_message_append(reply, "s", d); } static int property_get_type( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Mount *m = userdata; const char *d; assert(bus); assert(reply); assert(m); if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.fstype) d = m->parameters_proc_self_mountinfo.fstype; else if (m->from_fragment && m->parameters_fragment.fstype) d = m->parameters_fragment.fstype; else d = ""; return sd_bus_message_append(reply, "s", d); } static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, mount_result, MountResult); const sd_bus_vtable bus_mount_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Where", "s", NULL, offsetof(Mount, where), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("What", "s", property_get_what, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Options","s", property_get_options, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Type", "s", property_get_type, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Mount, timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Mount, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Mount, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SloppyOptions", "b", bus_property_get_bool, offsetof(Mount, sloppy_options), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_EXEC_COMMAND_VTABLE("ExecMount", offsetof(Mount, exec_command[MOUNT_EXEC_MOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_VTABLE("ExecUnmount", offsetof(Mount, exec_command[MOUNT_EXEC_UNMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_VTABLE("ExecRemount", offsetof(Mount, exec_command[MOUNT_EXEC_REMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), SD_BUS_VTABLE_END }; static int bus_mount_set_transient_property( Mount *m, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { const char *new_property; char **property; char *p; int r; assert(m); assert(name); assert(message); if (streq(name, "What")) property = &m->parameters_fragment.what; else if (streq(name, "Options")) property = &m->parameters_fragment.options; else if (streq(name, "Type")) property = &m->parameters_fragment.fstype; else return 0; r = sd_bus_message_read(message, "s", &new_property); if (r < 0) return r; if (mode != UNIT_CHECK) { p = strdup(new_property); if (!p) return -ENOMEM; free(*property); *property = p; } return 1; } int bus_mount_set_property( Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { Mount *m = MOUNT(u); int r; assert(m); assert(name); assert(message); r = bus_cgroup_set_property(u, &m->cgroup_context, name, message, mode, error); if (r != 0) return r; if (u->transient && u->load_state == UNIT_STUB) { /* This is a transient unit, let's load a little more */ r = bus_mount_set_transient_property(m, name, message, mode, error); if (r != 0) return r; r = bus_exec_context_set_transient_property(u, &m->exec_context, name, message, mode, error); if (r != 0) return r; r = bus_kill_context_set_transient_property(u, &m->kill_context, name, message, mode, error); if (r != 0) return r; } return 0; } int bus_mount_commit_properties(Unit *u) { assert(u); unit_update_cgroup_members_masks(u); unit_realize_cgroup(u); return 0; } systemd-229/src/core/dbus-mount.h000066400000000000000000000017401265713322000170500ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "unit.h" extern const sd_bus_vtable bus_mount_vtable[]; int bus_mount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error); int bus_mount_commit_properties(Unit *u); systemd-229/src/core/dbus-path.c000066400000000000000000000054721265713322000166430ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-util.h" #include "dbus-path.h" #include "path.h" #include "string-util.h" #include "unit.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, path_result, PathResult); static int property_get_paths( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Path *p = userdata; PathSpec *k; int r; assert(bus); assert(reply); assert(p); r = sd_bus_message_open_container(reply, 'a', "(ss)"); if (r < 0) return r; LIST_FOREACH(spec, k, p->specs) { r = sd_bus_message_append(reply, "(ss)", path_type_to_string(k->type), k->path); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_unit( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *p = userdata, *trigger; assert(bus); assert(reply); assert(p); trigger = UNIT_TRIGGER(p); return sd_bus_message_append(reply, "s", trigger ? trigger->id : ""); } const sd_bus_vtable bus_path_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Unit", "s", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Paths", "a(ss)", property_get_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MakeDirectory", "b", bus_property_get_bool, offsetof(Path, make_directory), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Path, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Path, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_VTABLE_END }; systemd-229/src/core/dbus-path.h000066400000000000000000000014151265713322000166410ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ extern const sd_bus_vtable bus_path_vtable[]; systemd-229/src/core/dbus-scope.c000066400000000000000000000160711265713322000170150ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-internal.h" #include "bus-util.h" #include "dbus-cgroup.h" #include "dbus-kill.h" #include "dbus-scope.h" #include "dbus-unit.h" #include "dbus.h" #include "scope.h" #include "selinux-access.h" #include "unit.h" static int bus_scope_abandon(sd_bus_message *message, void *userdata, sd_bus_error *error) { Scope *s = userdata; int r; assert(message); assert(s); r = mac_selinux_unit_access_check(UNIT(s), message, "stop", error); if (r < 0) return r; r = bus_verify_manage_units_async(UNIT(s)->manager, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = scope_abandon(s); if (r == -ESTALE) return sd_bus_error_setf(error, BUS_ERROR_SCOPE_NOT_RUNNING, "Scope %s is not running, cannot abandon.", UNIT(s)->id); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, scope_result, ScopeResult); const sd_bus_vtable bus_scope_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Controller", "s", NULL, offsetof(Scope, controller), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Scope, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Scope, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_SIGNAL("RequestStop", NULL, 0), SD_BUS_METHOD("Abandon", NULL, NULL, bus_scope_abandon, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; static int bus_scope_set_transient_property( Scope *s, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { int r; assert(s); assert(name); assert(message); if (streq(name, "PIDs")) { unsigned n = 0; uint32_t pid; r = sd_bus_message_enter_container(message, 'a', "u"); if (r < 0) return r; while ((r = sd_bus_message_read(message, "u", &pid)) > 0) { if (pid <= 1) return -EINVAL; if (mode != UNIT_CHECK) { r = unit_watch_pid(UNIT(s), pid); if (r < 0 && r != -EEXIST) return r; } n++; } if (r < 0) return r; r = sd_bus_message_exit_container(message); if (r < 0) return r; if (n <= 0) return -EINVAL; return 1; } else if (streq(name, "Controller")) { const char *controller; char *c; r = sd_bus_message_read(message, "s", &controller); if (r < 0) return r; if (!isempty(controller) && !service_name_is_valid(controller)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller); if (mode != UNIT_CHECK) { if (isempty(controller)) c = NULL; else { c = strdup(controller); if (!c) return -ENOMEM; } free(s->controller); s->controller = c; } return 1; } else if (streq(name, "TimeoutStopUSec")) { if (mode != UNIT_CHECK) { r = sd_bus_message_read(message, "t", &s->timeout_stop_usec); if (r < 0) return r; unit_write_drop_in_format(UNIT(s), mode, name, "[Scope]\nTimeoutStopSec="USEC_FMT"us\n", s->timeout_stop_usec); } else { r = sd_bus_message_skip(message, "t"); if (r < 0) return r; } return 1; } return 0; } int bus_scope_set_property( Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { Scope *s = SCOPE(u); int r; assert(s); assert(name); assert(message); r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error); if (r != 0) return r; if (u->load_state == UNIT_STUB) { /* While we are created we still accept PIDs */ r = bus_scope_set_transient_property(s, name, message, mode, error); if (r != 0) return r; r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error); if (r != 0) return r; } return 0; } int bus_scope_commit_properties(Unit *u) { assert(u); unit_update_cgroup_members_masks(u); unit_realize_cgroup(u); return 0; } int bus_scope_send_request_stop(Scope *s) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_free_ char *p = NULL; int r; assert(s); if (!s->controller) return 0; p = unit_dbus_path(UNIT(s)); if (!p) return -ENOMEM; r = sd_bus_message_new_signal( UNIT(s)->manager->api_bus, &m, p, "org.freedesktop.systemd1.Scope", "RequestStop"); if (r < 0) return r; return sd_bus_send_to(UNIT(s)->manager->api_bus, m, /* s->controller */ NULL, NULL); } systemd-229/src/core/dbus-scope.h000066400000000000000000000020061265713322000170130ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "unit.h" extern const sd_bus_vtable bus_scope_vtable[]; int bus_scope_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error); int bus_scope_commit_properties(Unit *u); int bus_scope_send_request_stop(Scope *s); systemd-229/src/core/dbus-service.c000066400000000000000000000346251265713322000173510ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "async.h" #include "bus-util.h" #include "dbus-cgroup.h" #include "dbus-execute.h" #include "dbus-kill.h" #include "dbus-service.h" #include "fd-util.h" #include "fileio.h" #include "path-util.h" #include "service.h" #include "string-util.h" #include "strv.h" #include "unit.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_failure_action, failure_action, FailureAction); const sd_bus_vtable bus_service_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0), /* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */ SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("FailureAction", "s", property_get_failure_action, offsetof(Service, failure_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool, offsetof(Service, guess_main_pid), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store_max), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NFileDescriptorStore", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store), 0), SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("StatusErrno", "i", NULL, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("USBFunctionDescriptors", "s", NULL, offsetof(Service, usb_function_descriptors), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("USBFunctionStrings", "s", NULL, offsetof(Service, usb_function_strings), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), SD_BUS_VTABLE_END }; static int bus_service_set_transient_property( Service *s, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { int r; assert(s); assert(name); assert(message); if (streq(name, "RemainAfterExit")) { int b; r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; if (mode != UNIT_CHECK) { s->remain_after_exit = b; unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b)); } return 1; } else if (streq(name, "Type")) { const char *t; ServiceType k; r = sd_bus_message_read(message, "s", &t); if (r < 0) return r; k = service_type_from_string(t); if (k < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service type %s", t); if (mode != UNIT_CHECK) { s->type = k; unit_write_drop_in_private_format(UNIT(s), mode, name, "Type=%s\n", service_type_to_string(s->type)); } return 1; } else if (streq(name, "RuntimeMaxUSec")) { usec_t u; r = sd_bus_message_read(message, "t", &u); if (r < 0) return r; if (mode != UNIT_CHECK) { s->runtime_max_usec = u; unit_write_drop_in_private_format(UNIT(s), mode, name, "RuntimeMaxSec=" USEC_FMT "us\n", u); } return 1; } else if (STR_IN_SET(name, "StandardInputFileDescriptor", "StandardOutputFileDescriptor", "StandardErrorFileDescriptor")) { int fd; r = sd_bus_message_read(message, "h", &fd); if (r < 0) return r; if (mode != UNIT_CHECK) { int copy; copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (copy < 0) return -errno; if (streq(name, "StandardInputFileDescriptor")) { asynchronous_close(s->stdin_fd); s->stdin_fd = copy; } else if (streq(name, "StandardOutputFileDescriptor")) { asynchronous_close(s->stdout_fd); s->stdout_fd = copy; } else { asynchronous_close(s->stderr_fd); s->stderr_fd = copy; } s->exec_context.stdio_as_fds = true; } return 1; } else if (streq(name, "ExecStart")) { unsigned n = 0; r = sd_bus_message_enter_container(message, 'a', "(sasb)"); if (r < 0) return r; while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) { _cleanup_strv_free_ char **argv = NULL; const char *path; int b; r = sd_bus_message_read(message, "s", &path); if (r < 0) return r; if (!path_is_absolute(path)) return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path); r = sd_bus_message_read_strv(message, &argv); if (r < 0) return r; r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; r = sd_bus_message_exit_container(message); if (r < 0) return r; if (mode != UNIT_CHECK) { ExecCommand *c; c = new0(ExecCommand, 1); if (!c) return -ENOMEM; c->path = strdup(path); if (!c->path) { free(c); return -ENOMEM; } c->argv = argv; argv = NULL; c->ignore = b; path_kill_slashes(c->path); exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c); } n++; } if (r < 0) return r; r = sd_bus_message_exit_container(message); if (r < 0) return r; if (mode != UNIT_CHECK) { _cleanup_free_ char *buf = NULL; _cleanup_fclose_ FILE *f = NULL; ExecCommand *c; size_t size = 0; if (n == 0) s->exec_command[SERVICE_EXEC_START] = exec_command_free_list(s->exec_command[SERVICE_EXEC_START]); f = open_memstream(&buf, &size); if (!f) return -ENOMEM; fputs("ExecStart=\n", f); LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) { _cleanup_free_ char *a; a = strv_join_quoted(c->argv); if (!a) return -ENOMEM; fprintf(f, "ExecStart=%s@%s %s\n", c->ignore ? "-" : "", c->path, a); } r = fflush_and_check(f); if (r < 0) return r; unit_write_drop_in_private(UNIT(s), mode, name, buf); } return 1; } return 0; } int bus_service_set_property( Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { Service *s = SERVICE(u); int r; assert(s); assert(name); assert(message); r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error); if (r != 0) return r; if (u->transient && u->load_state == UNIT_STUB) { /* This is a transient unit, let's load a little more */ r = bus_service_set_transient_property(s, name, message, mode, error); if (r != 0) return r; r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, mode, error); if (r != 0) return r; r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error); if (r != 0) return r; } return 0; } int bus_service_commit_properties(Unit *u) { assert(u); unit_update_cgroup_members_masks(u); unit_realize_cgroup(u); return 0; } systemd-229/src/core/dbus-service.h000066400000000000000000000017401265713322000173460ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "unit.h" extern const sd_bus_vtable bus_service_vtable[]; int bus_service_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error); int bus_service_commit_properties(Unit *u); systemd-229/src/core/dbus-slice.c000066400000000000000000000026521265713322000170030ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "dbus-cgroup.h" #include "dbus-slice.h" #include "slice.h" #include "unit.h" const sd_bus_vtable bus_slice_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_VTABLE_END }; int bus_slice_set_property( Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { Slice *s = SLICE(u); assert(name); assert(u); return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error); } int bus_slice_commit_properties(Unit *u) { assert(u); unit_update_cgroup_members_masks(u); unit_realize_cgroup(u); return 0; } systemd-229/src/core/dbus-slice.h000066400000000000000000000017401265713322000170050ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "unit.h" extern const sd_bus_vtable bus_slice_vtable[]; int bus_slice_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error); int bus_slice_commit_properties(Unit *u); systemd-229/src/core/dbus-socket.c000066400000000000000000000233051265713322000171720ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-util.h" #include "dbus-cgroup.h" #include "dbus-execute.h" #include "dbus-socket.h" #include "socket.h" #include "string-util.h" #include "unit.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, socket_result, SocketResult); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only); static int property_get_listen( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Socket *s = SOCKET(userdata); SocketPort *p; int r; assert(bus); assert(reply); assert(s); r = sd_bus_message_open_container(reply, 'a', "(ss)"); if (r < 0) return r; LIST_FOREACH(port, p, s->ports) { _cleanup_free_ char *address = NULL; const char *a; switch (p->type) { case SOCKET_SOCKET: { r = socket_address_print(&p->address, &address); if (r) return r; a = address; break; } case SOCKET_SPECIAL: case SOCKET_MQUEUE: case SOCKET_FIFO: case SOCKET_USB_FUNCTION: a = p->path; break; default: assert_not_reached("Unknown socket type"); } r = sd_bus_message_append(reply, "(ss)", socket_port_type_to_string(p), a); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_fdname( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Socket *s = SOCKET(userdata); assert(bus); assert(reply); assert(s); return sd_bus_message_append(reply, "s", socket_fdname(s)); } const sd_bus_vtable bus_socket_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("BindIPv6Only", "s", property_get_bind_ipv6_only, offsetof(Socket, bind_ipv6_only), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Backlog", "u", bus_property_get_unsigned, offsetof(Socket, backlog), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Socket, timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("BindToDevice", "s", NULL, offsetof(Socket, bind_to_device), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SocketUser", "s", NULL, offsetof(Socket, user), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SocketGroup", "s", NULL, offsetof(Socket, group), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SocketMode", "u", bus_property_get_mode, offsetof(Socket, socket_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Socket, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Accept", "b", bus_property_get_bool, offsetof(Socket, accept), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Writable", "b", bus_property_get_bool, offsetof(Socket, writable), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("KeepAlive", "b", bus_property_get_bool, offsetof(Socket, keep_alive), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("KeepAliveTimeUSec", "t", bus_property_get_usec, offsetof(Socket, keep_alive_time), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("KeepAliveIntervalUSec", "t", bus_property_get_usec, offsetof(Socket, keep_alive_interval), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("KeepAliveProbes", "u", bus_property_get_unsigned, offsetof(Socket, keep_alive_cnt), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DeferAcceptUSec" , "t", bus_property_get_usec, offsetof(Socket, defer_accept), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NoDelay", "b", bus_property_get_bool, offsetof(Socket, no_delay), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Priority", "i", bus_property_get_int, offsetof(Socket, priority), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ReceiveBuffer", "t", bus_property_get_size, offsetof(Socket, receive_buffer), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SendBuffer", "t", bus_property_get_size, offsetof(Socket, send_buffer), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IPTOS", "i", bus_property_get_int, offsetof(Socket, ip_tos), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IPTTL", "i", bus_property_get_int, offsetof(Socket, ip_ttl), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PipeSize", "t", bus_property_get_size, offsetof(Socket, pipe_size), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("FreeBind", "b", bus_property_get_bool, offsetof(Socket, free_bind), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Transparent", "b", bus_property_get_bool, offsetof(Socket, transparent), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Broadcast", "b", bus_property_get_bool, offsetof(Socket, broadcast), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PassCredentials", "b", bus_property_get_bool, offsetof(Socket, pass_cred), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PassSecurity", "b", bus_property_get_bool, offsetof(Socket, pass_sec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RemoveOnStop", "b", bus_property_get_bool, offsetof(Socket, remove_on_stop), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Listen", "a(ss)", property_get_listen, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Symlinks", "as", NULL, offsetof(Socket, symlinks), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Mark", "i", bus_property_get_int, offsetof(Socket, mark), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MaxConnections", "u", bus_property_get_unsigned, offsetof(Socket, max_connections), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MessageQueueMaxMessages", "x", bus_property_get_long, offsetof(Socket, mq_maxmsg), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MessageQueueMessageSize", "x", bus_property_get_long, offsetof(Socket, mq_msgsize), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ReusePort", "b", bus_property_get_bool, offsetof(Socket, reuse_port), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SmackLabel", "s", NULL, offsetof(Socket, smack), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SmackLabelIPIn", "s", NULL, offsetof(Socket, smack_ip_in), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SmackLabelIPOut", "s", NULL, offsetof(Socket, smack_ip_out), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Socket, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Socket, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("NConnections", "u", bus_property_get_unsigned, offsetof(Socket, n_connections), 0), SD_BUS_PROPERTY("NAccepted", "u", bus_property_get_unsigned, offsetof(Socket, n_accepted), 0), SD_BUS_PROPERTY("FileDescriptorName", "s", property_get_fdname, 0, 0), SD_BUS_PROPERTY("SocketProtocol", "i", bus_property_get_int, offsetof(Socket, socket_protocol), SD_BUS_VTABLE_PROPERTY_CONST), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPre", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), SD_BUS_VTABLE_END }; int bus_socket_set_property( Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { Socket *s = SOCKET(u); assert(s); assert(name); assert(message); return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error); } int bus_socket_commit_properties(Unit *u) { assert(u); unit_update_cgroup_members_masks(u); unit_realize_cgroup(u); return 0; } systemd-229/src/core/dbus-socket.h000066400000000000000000000017431265713322000172010ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "unit.h" extern const sd_bus_vtable bus_socket_vtable[]; int bus_socket_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error); int bus_socket_commit_properties(Unit *u); systemd-229/src/core/dbus-swap.c000066400000000000000000000074471265713322000166650ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2010 Maarten Lankhorst systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-util.h" #include "dbus-cgroup.h" #include "dbus-execute.h" #include "dbus-swap.h" #include "string-util.h" #include "swap.h" #include "unit.h" static int property_get_priority( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Swap *s = SWAP(userdata); int p; assert(bus); assert(reply); assert(s); if (s->from_proc_swaps) p = s->parameters_proc_swaps.priority; else if (s->from_fragment) p = s->parameters_fragment.priority; else p = -1; return sd_bus_message_append(reply, "i", p); } static int property_get_options( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Swap *s = SWAP(userdata); const char *options = NULL; assert(bus); assert(reply); assert(s); if (s->from_fragment) options = s->parameters_fragment.options; return sd_bus_message_append(reply, "s", options); } static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, swap_result, SwapResult); const sd_bus_vtable bus_swap_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("What", "s", NULL, offsetof(Swap, what), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Priority", "i", property_get_priority, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Options", "s", property_get_options, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Swap, timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Swap, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Swap, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_EXEC_COMMAND_VTABLE("ExecActivate", offsetof(Swap, exec_command[SWAP_EXEC_ACTIVATE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_VTABLE("ExecDeactivate", offsetof(Swap, exec_command[SWAP_EXEC_DEACTIVATE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), SD_BUS_VTABLE_END }; int bus_swap_set_property( Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { Swap *s = SWAP(u); assert(s); assert(name); assert(message); return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error); } int bus_swap_commit_properties(Unit *u) { assert(u); unit_update_cgroup_members_masks(u); unit_realize_cgroup(u); return 0; } systemd-229/src/core/dbus-swap.h000066400000000000000000000020001265713322000166460ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2010 Maarten Lankhorst systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "unit.h" extern const sd_bus_vtable bus_swap_vtable[]; int bus_swap_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error); int bus_swap_commit_properties(Unit *u); systemd-229/src/core/dbus-target.c000066400000000000000000000015441265713322000171710ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "dbus-target.h" #include "unit.h" const sd_bus_vtable bus_target_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_VTABLE_END }; systemd-229/src/core/dbus-target.h000066400000000000000000000014421265713322000171730ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" extern const sd_bus_vtable bus_target_vtable[]; systemd-229/src/core/dbus-timer.c000066400000000000000000000263341265713322000170270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-util.h" #include "dbus-timer.h" #include "strv.h" #include "timer.h" #include "unit.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, timer_result, TimerResult); static int property_get_monotonic_timers( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Timer *t = userdata; TimerValue *v; int r; assert(bus); assert(reply); assert(t); r = sd_bus_message_open_container(reply, 'a', "(stt)"); if (r < 0) return r; LIST_FOREACH(value, v, t->values) { _cleanup_free_ char *buf = NULL; const char *s; size_t l; if (v->base == TIMER_CALENDAR) continue; s = timer_base_to_string(v->base); assert(endswith(s, "Sec")); /* s/Sec/USec/ */ l = strlen(s); buf = new(char, l+2); if (!buf) return -ENOMEM; memcpy(buf, s, l-3); memcpy(buf+l-3, "USec", 5); r = sd_bus_message_append(reply, "(stt)", buf, v->value, v->next_elapse); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_calendar_timers( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Timer *t = userdata; TimerValue *v; int r; assert(bus); assert(reply); assert(t); r = sd_bus_message_open_container(reply, 'a', "(sst)"); if (r < 0) return r; LIST_FOREACH(value, v, t->values) { _cleanup_free_ char *buf = NULL; if (v->base != TIMER_CALENDAR) continue; r = calendar_spec_to_string(v->calendar_spec, &buf); if (r < 0) return r; r = sd_bus_message_append(reply, "(sst)", timer_base_to_string(v->base), buf, v->next_elapse); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_unit( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata, *trigger; assert(bus); assert(reply); assert(u); trigger = UNIT_TRIGGER(u); return sd_bus_message_append(reply, "s", trigger ? trigger->id : ""); } static int property_get_next_elapse_monotonic( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Timer *t = userdata; usec_t x; assert(bus); assert(reply); assert(t); if (t->next_elapse_monotonic_or_boottime <= 0) x = 0; else if (t->wake_system) { usec_t a, b; a = now(CLOCK_MONOTONIC); b = now(CLOCK_BOOTTIME); if (t->next_elapse_monotonic_or_boottime + a > b) x = t->next_elapse_monotonic_or_boottime + a - b; else x = 0; } else x = t->next_elapse_monotonic_or_boottime; return sd_bus_message_append(reply, "t", x); } const sd_bus_vtable bus_timer_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Unit", "s", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TimersMonotonic", "a(stt)", property_get_monotonic_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), SD_BUS_PROPERTY("TimersCalendar", "a(sst)", property_get_calendar_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), SD_BUS_PROPERTY("NextElapseUSecRealtime", "t", bus_property_get_usec, offsetof(Timer, next_elapse_realtime), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("NextElapseUSecMonotonic", "t", property_get_next_elapse_monotonic, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_VTABLE_END }; static int bus_timer_set_transient_property( Timer *t, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { int r; assert(t); assert(name); assert(message); if (STR_IN_SET(name, "OnActiveSec", "OnBootSec", "OnStartupSec", "OnUnitActiveSec", "OnUnitInactiveSec")) { TimerValue *v; TimerBase b = _TIMER_BASE_INVALID; usec_t u = 0; b = timer_base_from_string(name); if (b < 0) return -EINVAL; r = sd_bus_message_read(message, "t", &u); if (r < 0) return r; if (mode != UNIT_CHECK) { char time[FORMAT_TIMESPAN_MAX]; unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, format_timespan(time, sizeof(time), u, USEC_PER_MSEC)); v = new0(TimerValue, 1); if (!v) return -ENOMEM; v->base = b; v->value = u; LIST_PREPEND(value, t->values, v); } return 1; } else if (streq(name, "OnCalendar")) { TimerValue *v; CalendarSpec *c = NULL; const char *str; r = sd_bus_message_read(message, "s", &str); if (r < 0) return r; if (mode != UNIT_CHECK) { r = calendar_spec_from_string(str, &c); if (r < 0) return r; unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, str); v = new0(TimerValue, 1); if (!v) { calendar_spec_free(c); return -ENOMEM; } v->base = TIMER_CALENDAR; v->calendar_spec = c; LIST_PREPEND(value, t->values, v); } return 1; } else if (STR_IN_SET(name, "AccuracyUSec", "AccuracySec")) { usec_t u = 0; if (streq(name, "AccuracySec")) log_notice("Client is using obsolete AccuracySec= transient property, please use AccuracyUSec= instead."); r = sd_bus_message_read(message, "t", &u); if (r < 0) return r; if (mode != UNIT_CHECK) { t->accuracy_usec = u; unit_write_drop_in_private_format(UNIT(t), mode, name, "AccuracySec=" USEC_FMT "us\n", u); } return 1; } else if (streq(name, "RandomizedDelayUSec")) { usec_t u = 0; r = sd_bus_message_read(message, "t", &u); if (r < 0) return r; if (mode != UNIT_CHECK) { t->random_usec = u; unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomizedDelaySec=" USEC_FMT "us\n", u); } return 1; } else if (streq(name, "WakeSystem")) { int b; r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; if (mode != UNIT_CHECK) { t->wake_system = b; unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, yes_no(b)); } return 1; } else if (streq(name, "RemainAfterElapse")) { int b; r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; if (mode != UNIT_CHECK) { t->remain_after_elapse = b; unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, yes_no(b)); } return 1; } return 0; } int bus_timer_set_property( Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { Timer *t = TIMER(u); int r; assert(t); assert(name); assert(message); if (u->transient && u->load_state == UNIT_STUB) { r = bus_timer_set_transient_property(t, name, message, mode, error); if (r != 0) return r; } return 0; } systemd-229/src/core/dbus-timer.h000066400000000000000000000016601265713322000170270ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "unit.h" extern const sd_bus_vtable bus_timer_vtable[]; int bus_timer_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error); systemd-229/src/core/dbus-unit.c000066400000000000000000001353231265713322000166650ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "alloc-util.h" #include "bus-common-errors.h" #include "cgroup-util.h" #include "dbus-unit.h" #include "dbus.h" #include "locale-util.h" #include "log.h" #include "selinux-access.h" #include "special.h" #include "string-util.h" #include "strv.h" #include "user-util.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_failure_action, failure_action, FailureAction); static int property_get_names( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata; Iterator i; const char *t; int r; assert(bus); assert(reply); assert(u); r = sd_bus_message_open_container(reply, 'a', "s"); if (r < 0) return r; SET_FOREACH(t, u->names, i) { r = sd_bus_message_append(reply, "s", t); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_following( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata, *f; assert(bus); assert(reply); assert(u); f = unit_following(u); return sd_bus_message_append(reply, "s", f ? f->id : ""); } static int property_get_dependencies( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Set *s = *(Set**) userdata; Iterator j; Unit *u; int r; assert(bus); assert(reply); r = sd_bus_message_open_container(reply, 'a', "s"); if (r < 0) return r; SET_FOREACH(u, s, j) { r = sd_bus_message_append(reply, "s", u->id); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_obsolete_dependencies( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { assert(bus); assert(reply); /* For dependency types we don't support anymore always return an empty array */ return sd_bus_message_append(reply, "as", 0); } static int property_get_description( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata; assert(bus); assert(reply); assert(u); return sd_bus_message_append(reply, "s", unit_description(u)); } static int property_get_active_state( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata; assert(bus); assert(reply); assert(u); return sd_bus_message_append(reply, "s", unit_active_state_to_string(unit_active_state(u))); } static int property_get_sub_state( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata; assert(bus); assert(reply); assert(u); return sd_bus_message_append(reply, "s", unit_sub_state_to_string(u)); } static int property_get_unit_file_preset( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata; int r; assert(bus); assert(reply); assert(u); r = unit_get_unit_file_preset(u); return sd_bus_message_append(reply, "s", r < 0 ? "": r > 0 ? "enabled" : "disabled"); } static int property_get_unit_file_state( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata; assert(bus); assert(reply); assert(u); return sd_bus_message_append(reply, "s", unit_file_state_to_string(unit_get_unit_file_state(u))); } static int property_get_can_start( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata; assert(bus); assert(reply); assert(u); return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_start); } static int property_get_can_stop( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata; assert(bus); assert(reply); assert(u); /* On the lower levels we assume that every unit we can start * we can also stop */ return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_stop); } static int property_get_can_reload( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata; assert(bus); assert(reply); assert(u); return sd_bus_message_append(reply, "b", unit_can_reload(u)); } static int property_get_can_isolate( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata; assert(bus); assert(reply); assert(u); return sd_bus_message_append(reply, "b", unit_can_isolate(u) && !u->refuse_manual_start); } static int property_get_job( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Unit *u = userdata; assert(bus); assert(reply); assert(u); if (!u->job) return sd_bus_message_append(reply, "(uo)", 0, "/"); p = job_dbus_path(u->job); if (!p) return -ENOMEM; return sd_bus_message_append(reply, "(uo)", u->job->id, p); } static int property_get_need_daemon_reload( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata; assert(bus); assert(reply); assert(u); return sd_bus_message_append(reply, "b", unit_need_daemon_reload(u)); } static int property_get_conditions( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { const char *(*to_string)(ConditionType type) = NULL; Condition **list = userdata, *c; int r; assert(bus); assert(reply); assert(list); to_string = streq(property, "Asserts") ? assert_type_to_string : condition_type_to_string; r = sd_bus_message_open_container(reply, 'a', "(sbbsi)"); if (r < 0) return r; LIST_FOREACH(conditions, c, *list) { int tristate; tristate = c->result == CONDITION_UNTESTED ? 0 : c->result == CONDITION_SUCCEEDED ? 1 : -1; r = sd_bus_message_append(reply, "(sbbsi)", to_string(c->type), c->trigger, c->negate, c->parameter, tristate); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_load_error( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL; Unit *u = userdata; assert(bus); assert(reply); assert(u); if (u->load_error != 0) sd_bus_error_set_errno(&e, u->load_error); return sd_bus_message_append(reply, "(ss)", e.name, e.message); } static int bus_verify_manage_units_async_full( Unit *u, const char *verb, int capability, const char *polkit_message, sd_bus_message *call, sd_bus_error *error) { const char *details[9] = { "unit", u->id, "verb", verb, }; if (polkit_message) { details[4] = "polkit.message"; details[5] = polkit_message; details[6] = "polkit.gettext_domain"; details[7] = GETTEXT_PACKAGE; } return bus_verify_polkit_async(call, capability, "org.freedesktop.systemd1.manage-units", details, false, UID_INVALID, &u->manager->polkit_registry, error); } int bus_unit_method_start_generic( sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error) { const char *smode; JobMode mode; _cleanup_free_ char *verb = NULL; static const char *const polkit_message_for_job[_JOB_TYPE_MAX] = { [JOB_START] = N_("Authentication is required to start '$(unit)'."), [JOB_STOP] = N_("Authentication is required to stop '$(unit)'."), [JOB_RELOAD] = N_("Authentication is required to reload '$(unit)'."), [JOB_RESTART] = N_("Authentication is required to restart '$(unit)'."), [JOB_TRY_RESTART] = N_("Authentication is required to restart '$(unit)'."), }; int r; assert(message); assert(u); assert(job_type >= 0 && job_type < _JOB_TYPE_MAX); r = mac_selinux_unit_access_check( u, message, job_type_to_access_method(job_type), error); if (r < 0) return r; r = sd_bus_message_read(message, "s", &smode); if (r < 0) return r; mode = job_mode_from_string(smode); if (mode < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode); if (reload_if_possible) verb = strjoin("reload-or-", job_type_to_string(job_type), NULL); else verb = strdup(job_type_to_string(job_type)); if (!verb) return -ENOMEM; r = bus_verify_manage_units_async_full( u, verb, CAP_SYS_ADMIN, job_type < _JOB_TYPE_MAX ? polkit_message_for_job[job_type] : NULL, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ return bus_unit_queue_job(message, u, job_type, mode, reload_if_possible, error); } static int method_start(sd_bus_message *message, void *userdata, sd_bus_error *error) { return bus_unit_method_start_generic(message, userdata, JOB_START, false, error); } static int method_stop(sd_bus_message *message, void *userdata, sd_bus_error *error) { return bus_unit_method_start_generic(message, userdata, JOB_STOP, false, error); } static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) { return bus_unit_method_start_generic(message, userdata, JOB_RELOAD, false, error); } static int method_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) { return bus_unit_method_start_generic(message, userdata, JOB_RESTART, false, error); } static int method_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) { return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, false, error); } static int method_reload_or_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) { return bus_unit_method_start_generic(message, userdata, JOB_RESTART, true, error); } static int method_reload_or_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) { return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, true, error); } int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) { Unit *u = userdata; const char *swho; int32_t signo; KillWho who; int r; assert(message); assert(u); r = mac_selinux_unit_access_check(u, message, "stop", error); if (r < 0) return r; r = sd_bus_message_read(message, "si", &swho, &signo); if (r < 0) return r; if (isempty(swho)) who = KILL_ALL; else { who = kill_who_from_string(swho); if (who < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho); } if (signo <= 0 || signo >= _NSIG) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range."); r = bus_verify_manage_units_async_full( u, "kill", CAP_KILL, N_("Authentication is required to kill '$(unit)'."), message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = unit_kill(u, who, signo, error); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error) { Unit *u = userdata; int r; assert(message); assert(u); r = mac_selinux_unit_access_check(u, message, "reload", error); if (r < 0) return r; r = bus_verify_manage_units_async_full( u, "reset-failed", CAP_SYS_ADMIN, N_("Authentication is required to reset the \"failed\" state of '$(unit)'."), message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ unit_reset_failed(u); return sd_bus_reply_method_return(message, NULL); } int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error) { Unit *u = userdata; int runtime, r; assert(message); assert(u); r = mac_selinux_unit_access_check(u, message, "start", error); if (r < 0) return r; r = sd_bus_message_read(message, "b", &runtime); if (r < 0) return r; r = bus_verify_manage_units_async_full( u, "set-property", CAP_SYS_ADMIN, N_("Authentication is required to set properties on '$(unit)'."), message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, error); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Names", "as", property_get_names, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0), SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RequisiteOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OF]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Before", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BEFORE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("After", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_AFTER]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_ON_FAILURE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_JOINS_NAMESPACE_OF]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("RequiresMountsFor", "as", NULL, offsetof(Unit, requires_mounts_for), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0), SD_BUS_PROPERTY("UnitFilePreset", "s", property_get_unit_file_preset, 0, 0), BUS_PROPERTY_DUAL_TIMESTAMP("StateChangeTimestamp", offsetof(Unit, state_change_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Job", "(uo)", property_get_job, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_failure_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), 0), SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0), SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Stop", "s", "o", method_stop, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Reload", "s", "o", method_reload, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Restart", "s", "o", method_restart, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; static int property_get_slice( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata; assert(bus); assert(reply); assert(u); return sd_bus_message_append(reply, "s", unit_slice_name(u)); } static int property_get_current_memory( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { uint64_t sz = (uint64_t) -1; Unit *u = userdata; int r; assert(bus); assert(reply); assert(u); r = unit_get_memory_current(u, &sz); if (r < 0 && r != -ENODATA) log_unit_warning_errno(u, r, "Failed to get memory.usage_in_bytes attribute: %m"); return sd_bus_message_append(reply, "t", sz); } static int property_get_current_tasks( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { uint64_t cn = (uint64_t) -1; Unit *u = userdata; int r; assert(bus); assert(reply); assert(u); r = unit_get_tasks_current(u, &cn); if (r < 0 && r != -ENODATA) log_unit_warning_errno(u, r, "Failed to get pids.current attribute: %m"); return sd_bus_message_append(reply, "t", cn); } static int property_get_cpu_usage( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { nsec_t ns = (nsec_t) -1; Unit *u = userdata; int r; assert(bus); assert(reply); assert(u); r = unit_get_cpu_usage(u, &ns); if (r < 0 && r != -ENODATA) log_unit_warning_errno(u, r, "Failed to get cpuacct.usage attribute: %m"); return sd_bus_message_append(reply, "t", ns); } static int property_get_cgroup( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Unit *u = userdata; const char *t; assert(bus); assert(reply); assert(u); /* Three cases: a) u->cgroup_path is NULL, in which case the * unit has no control group, which we report as the empty * string. b) u->cgroup_path is the empty string, which * indicates the root cgroup, which we report as "/". c) all * other cases we report as-is. */ if (u->cgroup_path) t = isempty(u->cgroup_path) ? "/" : u->cgroup_path; else t = ""; return sd_bus_message_append(reply, "s", t); } const sd_bus_vtable bus_unit_cgroup_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0), SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup, 0, 0), SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0), SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0), SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0), SD_BUS_VTABLE_END }; static int send_new_signal(sd_bus *bus, void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_free_ char *p = NULL; Unit *u = userdata; int r; assert(bus); assert(u); p = unit_dbus_path(u); if (!p) return -ENOMEM; r = sd_bus_message_new_signal( bus, &m, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitNew"); if (r < 0) return r; r = sd_bus_message_append(m, "so", u->id, p); if (r < 0) return r; return sd_bus_send(bus, m, NULL); } static int send_changed_signal(sd_bus *bus, void *userdata) { _cleanup_free_ char *p = NULL; Unit *u = userdata; int r; assert(bus); assert(u); p = unit_dbus_path(u); if (!p) return -ENOMEM; /* Send a properties changed signal. First for the specific * type, then for the generic unit. The clients may rely on * this order to get atomic behavior if needed. */ r = sd_bus_emit_properties_changed_strv( bus, p, unit_dbus_interface_from_type(u->type), NULL); if (r < 0) return r; return sd_bus_emit_properties_changed_strv( bus, p, "org.freedesktop.systemd1.Unit", NULL); } void bus_unit_send_change_signal(Unit *u) { int r; assert(u); if (u->in_dbus_queue) { LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u); u->in_dbus_queue = false; } if (!u->id) return; r = bus_foreach_bus(u->manager, NULL, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u); if (r < 0) log_unit_debug_errno(u, r, "Failed to send unit change signal for %s: %m", u->id); u->sent_dbus_new_signal = true; } static int send_removed_signal(sd_bus *bus, void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_free_ char *p = NULL; Unit *u = userdata; int r; assert(bus); assert(u); p = unit_dbus_path(u); if (!p) return -ENOMEM; r = sd_bus_message_new_signal( bus, &m, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitRemoved"); if (r < 0) return r; r = sd_bus_message_append(m, "so", u->id, p); if (r < 0) return r; return sd_bus_send(bus, m, NULL); } void bus_unit_send_removed_signal(Unit *u) { int r; assert(u); if (!u->sent_dbus_new_signal) bus_unit_send_change_signal(u); if (!u->id) return; r = bus_foreach_bus(u->manager, NULL, send_removed_signal, u); if (r < 0) log_unit_debug_errno(u, r, "Failed to send unit remove signal for %s: %m", u->id); } int bus_unit_queue_job( sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error) { _cleanup_free_ char *path = NULL; Job *j; int r; assert(message); assert(u); assert(type >= 0 && type < _JOB_TYPE_MAX); assert(mode >= 0 && mode < _JOB_MODE_MAX); r = mac_selinux_unit_access_check( u, message, job_type_to_access_method(type), error); if (r < 0) return r; if (reload_if_possible && unit_can_reload(u)) { if (type == JOB_RESTART) type = JOB_RELOAD_OR_START; else if (type == JOB_TRY_RESTART) type = JOB_TRY_RELOAD; } if (type == JOB_STOP && (u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) && unit_active_state(u) == UNIT_INACTIVE) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id); if ((type == JOB_START && u->refuse_manual_start) || (type == JOB_STOP && u->refuse_manual_stop) || ((type == JOB_RESTART || type == JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) || (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start)) return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only.", u->id); r = manager_add_job(u->manager, type, u, mode, error, &j); if (r < 0) return r; if (sd_bus_message_get_bus(message) == u->manager->api_bus) { if (!j->clients) { r = sd_bus_track_new(sd_bus_message_get_bus(message), &j->clients, NULL, NULL); if (r < 0) return r; } r = sd_bus_track_add_sender(j->clients, message); if (r < 0) return r; } path = job_dbus_path(j); if (!path) return -ENOMEM; return sd_bus_reply_method_return(message, "o", path); } static int bus_unit_set_transient_property( Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { int r; assert(u); assert(name); assert(message); if (streq(name, "Description")) { const char *d; r = sd_bus_message_read(message, "s", &d); if (r < 0) return r; if (mode != UNIT_CHECK) { r = unit_set_description(u, d); if (r < 0) return r; unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s\n", d); } return 1; } else if (streq(name, "DefaultDependencies")) { int b; r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; if (mode != UNIT_CHECK) { u->default_dependencies = b; unit_write_drop_in_format(u, mode, name, "[Unit]\nDefaultDependencies=%s\n", yes_no(b)); } return 1; } else if (streq(name, "Slice")) { Unit *slice; const char *s; if (!UNIT_HAS_CGROUP_CONTEXT(u)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "The slice property is only available for units with control groups."); if (u->type == UNIT_SLICE) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Slice may not be set for slice units."); if (unit_has_name(u, SPECIAL_INIT_SCOPE)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set slice for init.scope"); r = sd_bus_message_read(message, "s", &s); if (r < 0) return r; if (!unit_name_is_valid(s, UNIT_NAME_PLAIN)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name '%s'", s); r = manager_load_unit(u->manager, s, NULL, error, &slice); if (r < 0) return r; if (slice->type != UNIT_SLICE) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit name '%s' is not a slice", s); if (mode != UNIT_CHECK) { r = unit_set_slice(u, slice); if (r < 0) return r; unit_write_drop_in_private_format(u, mode, name, "Slice=%s\n", s); } return 1; } else if (STR_IN_SET(name, "Requires", "RequiresOverridable", "Requisite", "RequisiteOverridable", "Wants", "BindsTo", "Conflicts", "Before", "After", "OnFailure", "PropagatesReloadTo", "ReloadPropagatedFrom", "PartOf")) { UnitDependency d; const char *other; if (streq(name, "RequiresOverridable")) d = UNIT_REQUIRES; /* redirect for obsolete unit dependency type */ else if (streq(name, "RequisiteOverridable")) d = UNIT_REQUISITE; /* same here */ else { d = unit_dependency_from_string(name); if (d < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit dependency: %s", name); } r = sd_bus_message_enter_container(message, 'a', "s"); if (r < 0) return r; while ((r = sd_bus_message_read(message, "s", &other)) > 0) { if (!unit_name_is_valid(other, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other); if (mode != UNIT_CHECK) { _cleanup_free_ char *label = NULL; r = unit_add_dependency_by_name(u, d, other, NULL, true); if (r < 0) return r; label = strjoin(name, "-", other, NULL); if (!label) return -ENOMEM; unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s\n", name, other); } } if (r < 0) return r; r = sd_bus_message_exit_container(message); if (r < 0) return r; return 1; } return 0; } int bus_unit_set_properties( Unit *u, sd_bus_message *message, UnitSetPropertiesMode mode, bool commit, sd_bus_error *error) { bool for_real = false; unsigned n = 0; int r; assert(u); assert(message); /* We iterate through the array twice. First run we just check * if all passed data is valid, second run actually applies * it. This is to implement transaction-like behaviour without * actually providing full transactions. */ r = sd_bus_message_enter_container(message, 'a', "(sv)"); if (r < 0) return r; for (;;) { const char *name; r = sd_bus_message_enter_container(message, 'r', "sv"); if (r < 0) return r; if (r == 0) { if (for_real || mode == UNIT_CHECK) break; /* Reached EOF. Let's try again, and this time for realz... */ r = sd_bus_message_rewind(message, false); if (r < 0) return r; for_real = true; continue; } r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; if (!UNIT_VTABLE(u)->bus_set_property) return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties."); r = sd_bus_message_enter_container(message, 'v', NULL); if (r < 0) return r; r = UNIT_VTABLE(u)->bus_set_property(u, name, message, for_real ? mode : UNIT_CHECK, error); if (r == 0 && u->transient && u->load_state == UNIT_STUB) r = bus_unit_set_transient_property(u, name, message, for_real ? mode : UNIT_CHECK, error); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name); r = sd_bus_message_exit_container(message); if (r < 0) return r; r = sd_bus_message_exit_container(message); if (r < 0) return r; n += for_real; } r = sd_bus_message_exit_container(message); if (r < 0) return r; if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties) UNIT_VTABLE(u)->bus_commit_properties(u); return n; } int bus_unit_check_load_state(Unit *u, sd_bus_error *error) { if (u->load_state == UNIT_LOADED) return 0; /* Give a better description of the unit error when * possible. Note that in the case of UNIT_MASKED, load_error * is not set. */ if (u->load_state == UNIT_MASKED) return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id); if (u->load_state == UNIT_NOT_FOUND) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not found.", u->id); return sd_bus_error_set_errnof(error, u->load_error, "Unit %s is not loaded properly: %m.", u->id); } systemd-229/src/core/dbus-unit.h000066400000000000000000000032401265713322000166620ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "unit.h" extern const sd_bus_vtable bus_unit_vtable[]; extern const sd_bus_vtable bus_unit_cgroup_vtable[]; void bus_unit_send_change_signal(Unit *u); void bus_unit_send_removed_signal(Unit *u); int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error); int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error); int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitSetPropertiesMode mode, bool commit, sd_bus_error *error); int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_check_load_state(Unit *u, sd_bus_error *error); systemd-229/src/core/dbus.c000066400000000000000000001170401265713322000157040ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-internal.h" #include "bus-util.h" #include "dbus-cgroup.h" #include "dbus-execute.h" #include "dbus-job.h" #include "dbus-kill.h" #include "dbus-manager.h" #include "dbus-unit.h" #include "dbus.h" #include "fd-util.h" #include "log.h" #include "missing.h" #include "mkdir.h" #include "selinux-access.h" #include "special.h" #include "string-util.h" #include "strv.h" #include "strxcpyx.h" #include "user-util.h" #define CONNECTIONS_MAX 4096 static void destroy_bus(Manager *m, sd_bus **bus); int bus_send_queued_message(Manager *m) { int r; assert(m); if (!m->queued_message) return 0; /* If we cannot get rid of this message we won't dispatch any * D-Bus messages, so that we won't end up wanting to queue * another message. */ r = sd_bus_send(NULL, m->queued_message, NULL); if (r < 0) log_warning_errno(r, "Failed to send queued message: %m"); m->queued_message = sd_bus_message_unref(m->queued_message); return 0; } static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *cgroup, *me; Manager *m = userdata; uid_t sender_uid; sd_bus *bus; int r; assert(message); assert(m); /* ignore recursive events sent by us on the system/user bus */ bus = sd_bus_message_get_bus(message); if (!sd_bus_is_server(bus)) { r = sd_bus_get_unique_name(bus, &me); if (r < 0) return r; if (streq_ptr(sd_bus_message_get_sender(message), me)) return 0; } /* only accept org.freedesktop.systemd1.Agent from UID=0 */ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); if (r < 0) return r; r = sd_bus_creds_get_euid(creds, &sender_uid); if (r < 0 || sender_uid != 0) return 0; /* parse 'cgroup-empty' notification */ r = sd_bus_message_read(message, "s", &cgroup); if (r < 0) { bus_log_parse_error(r); return 0; } manager_notify_cgroup_empty(m, cgroup); /* if running as system-instance, forward under our name */ if (m->running_as == MANAGER_SYSTEM && m->system_bus) { r = sd_bus_message_rewind(message, 1); if (r >= 0) r = sd_bus_send(m->system_bus, message, NULL); if (r < 0) log_warning_errno(r, "Failed to forward Released message: %m"); } return 0; } static int signal_disconnected(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; sd_bus *bus; assert(message); assert(m); assert_se(bus = sd_bus_message_get_bus(message)); if (bus == m->api_bus) destroy_bus(m, &m->api_bus); if (bus == m->system_bus) destroy_bus(m, &m->system_bus); if (set_remove(m->private_buses, bus)) { log_debug("Got disconnect on private connection."); destroy_bus(m, &bus); } return 0; } static int signal_activation_request(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; const char *name; Unit *u; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) { bus_log_parse_error(r); return 0; } if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) || manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) { r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down."); goto failed; } r = manager_load_unit(m, name, NULL, &error, &u); if (r < 0) goto failed; if (u->refuse_manual_start) { r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only.", u->id); goto failed; } r = manager_add_job(m, JOB_START, u, JOB_REPLACE, &error, NULL); if (r < 0) goto failed; /* Successfully queued, that's it for us */ return 0; failed: if (!sd_bus_error_is_set(&error)) sd_bus_error_set_errno(&error, r); log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r)); r = sd_bus_message_new_signal(sd_bus_message_get_bus(message), &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure"); if (r < 0) { bus_log_create_error(r); return 0; } r = sd_bus_message_append(reply, "sss", name, error.name, error.message); if (r < 0) { bus_log_create_error(r); return 0; } r = sd_bus_send_to(NULL, reply, "org.freedesktop.DBus", NULL); if (r < 0) return log_error_errno(r, "Failed to respond with to bus activation request: %m"); return 0; } #ifdef HAVE_SELINUX static int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; const char *verb, *path; Unit *u = NULL; Job *j; int r; assert(message); /* Our own method calls are all protected individually with * selinux checks, but the built-in interfaces need to be * protected too. */ if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set")) verb = "reload"; else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) || sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) || sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) || sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL)) verb = "status"; else return 0; path = sd_bus_message_get_path(message); if (object_path_startswith("/org/freedesktop/systemd1", path)) { r = mac_selinux_access_check(message, verb, error); if (r < 0) return r; return 0; } if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; pid_t pid; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); if (r < 0) return 0; r = sd_bus_creds_get_pid(creds, &pid); if (r < 0) return 0; u = manager_get_unit_by_pid(m, pid); } else { r = manager_get_job_from_dbus_path(m, path, &j); if (r >= 0) u = j->unit; else manager_load_unit_from_dbus_path(m, path, NULL, &u); } if (!u) return 0; r = mac_selinux_unit_access_check(u, message, verb, error); if (r < 0) return r; return 0; } #endif static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; Job *j; int r; assert(bus); assert(path); assert(interface); assert(found); assert(m); r = manager_get_job_from_dbus_path(m, path, &j); if (r < 0) return 0; *found = j; return 1; } static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) { Unit *u; int r; assert(m); assert(bus); assert(path); if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; sd_bus_message *message; pid_t pid; message = sd_bus_get_current_message(bus); if (!message) return 0; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); if (r < 0) return r; r = sd_bus_creds_get_pid(creds, &pid); if (r < 0) return r; u = manager_get_unit_by_pid(m, pid); } else { r = manager_load_unit_from_dbus_path(m, path, error, &u); if (r < 0) return 0; } if (!u) return 0; *unit = u; return 1; } static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; assert(bus); assert(path); assert(interface); assert(found); assert(m); return find_unit(m, bus, path, (Unit**) found, error); } static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; Unit *u; int r; assert(bus); assert(path); assert(interface); assert(found); assert(m); r = find_unit(m, bus, path, &u, error); if (r <= 0) return r; if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type))) return 0; *found = u; return 1; } static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; Unit *u; int r; assert(bus); assert(path); assert(interface); assert(found); assert(m); r = find_unit(m, bus, path, &u, error); if (r <= 0) return r; if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type))) return 0; if (!UNIT_HAS_CGROUP_CONTEXT(u)) return 0; *found = u; return 1; } static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; CGroupContext *c; Unit *u; int r; assert(bus); assert(path); assert(interface); assert(found); assert(m); r = find_unit(m, bus, path, &u, error); if (r <= 0) return r; if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type))) return 0; c = unit_get_cgroup_context(u); if (!c) return 0; *found = c; return 1; } static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; ExecContext *c; Unit *u; int r; assert(bus); assert(path); assert(interface); assert(found); assert(m); r = find_unit(m, bus, path, &u, error); if (r <= 0) return r; if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type))) return 0; c = unit_get_exec_context(u); if (!c) return 0; *found = c; return 1; } static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; KillContext *c; Unit *u; int r; assert(bus); assert(path); assert(interface); assert(found); assert(m); r = find_unit(m, bus, path, &u, error); if (r <= 0) return r; if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type))) return 0; c = unit_get_kill_context(u); if (!c) return 0; *found = c; return 1; } static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_free_ char **l = NULL; Manager *m = userdata; unsigned k = 0; Iterator i; Job *j; l = new0(char*, hashmap_size(m->jobs)+1); if (!l) return -ENOMEM; HASHMAP_FOREACH(j, m->jobs, i) { l[k] = job_dbus_path(j); if (!l[k]) return -ENOMEM; k++; } assert(hashmap_size(m->jobs) == k); *nodes = l; l = NULL; return k; } static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_free_ char **l = NULL; Manager *m = userdata; unsigned k = 0; Iterator i; Unit *u; l = new0(char*, hashmap_size(m->units)+1); if (!l) return -ENOMEM; HASHMAP_FOREACH(u, m->units, i) { l[k] = unit_dbus_path(u); if (!l[k]) return -ENOMEM; k++; } *nodes = l; l = NULL; return k; } static int bus_setup_api_vtables(Manager *m, sd_bus *bus) { UnitType t; int r; assert(m); assert(bus); #ifdef HAVE_SELINUX r = sd_bus_add_filter(bus, NULL, mac_selinux_filter, m); if (r < 0) return log_error_errno(r, "Failed to add SELinux access filter: %m"); #endif r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m); if (r < 0) return log_error_errno(r, "Failed to register Manager vtable: %m"); r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m); if (r < 0) return log_error_errno(r, "Failed to register Job vtable: %m"); r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m); if (r < 0) return log_error_errno(r, "Failed to add job enumerator: %m"); r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m); if (r < 0) return log_error_errno(r, "Failed to register Unit vtable: %m"); r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m); if (r < 0) return log_error_errno(r, "Failed to add job enumerator: %m"); for (t = 0; t < _UNIT_TYPE_MAX; t++) { const char *interface; assert_se(interface = unit_dbus_interface_from_type(t)); r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m); if (r < 0) return log_error_errno(r, "Failed to register type specific vtable for %s: %m", interface); if (unit_vtable[t]->cgroup_context_offset > 0) { r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m); if (r < 0) return log_error_errno(r, "Failed to register control group unit vtable for %s: %m", interface); r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_cgroup_vtable, bus_cgroup_context_find, m); if (r < 0) return log_error_errno(r, "Failed to register control group vtable for %s: %m", interface); } if (unit_vtable[t]->exec_context_offset > 0) { r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_exec_vtable, bus_exec_context_find, m); if (r < 0) return log_error_errno(r, "Failed to register execute vtable for %s: %m", interface); } if (unit_vtable[t]->kill_context_offset > 0) { r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_kill_vtable, bus_kill_context_find, m); if (r < 0) return log_error_errno(r, "Failed to register kill vtable for %s: %m", interface); } } return 0; } static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) { int r; assert(m); assert(bus); r = sd_bus_add_match( bus, NULL, "sender='org.freedesktop.DBus.Local'," "type='signal'," "path='/org/freedesktop/DBus/Local'," "interface='org.freedesktop.DBus.Local'," "member='Disconnected'", signal_disconnected, m); if (r < 0) return log_error_errno(r, "Failed to register match for Disconnected message: %m"); return 0; } static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; _cleanup_close_ int nfd = -1; Manager *m = userdata; sd_id128_t id; int r; assert(s); assert(m); nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); if (nfd < 0) { log_warning_errno(errno, "Failed to accept private connection, ignoring: %m"); return 0; } if (set_size(m->private_buses) >= CONNECTIONS_MAX) { log_warning("Too many concurrent connections, refusing"); return 0; } r = set_ensure_allocated(&m->private_buses, NULL); if (r < 0) { log_oom(); return 0; } r = sd_bus_new(&bus); if (r < 0) { log_warning_errno(r, "Failed to allocate new private connection bus: %m"); return 0; } r = sd_bus_set_fd(bus, nfd, nfd); if (r < 0) { log_warning_errno(r, "Failed to set fd on new connection bus: %m"); return 0; } nfd = -1; r = bus_check_peercred(bus); if (r < 0) { log_warning_errno(r, "Incoming private connection from unprivileged client, refusing: %m"); return 0; } assert_se(sd_id128_randomize(&id) >= 0); r = sd_bus_set_server(bus, 1, id); if (r < 0) { log_warning_errno(r, "Failed to enable server support for new connection bus: %m"); return 0; } r = sd_bus_negotiate_creds(bus, 1, SD_BUS_CREDS_PID|SD_BUS_CREDS_UID| SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS| SD_BUS_CREDS_SELINUX_CONTEXT); if (r < 0) { log_warning_errno(r, "Failed to enable credentials for new connection: %m"); return 0; } r = sd_bus_start(bus); if (r < 0) { log_warning_errno(r, "Failed to start new connection bus: %m"); return 0; } r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL); if (r < 0) { log_warning_errno(r, "Failed to attach new connection bus to event loop: %m"); return 0; } if (m->running_as == MANAGER_SYSTEM) { /* When we run as system instance we get the Released * signal via a direct connection */ r = sd_bus_add_match( bus, NULL, "type='signal'," "interface='org.freedesktop.systemd1.Agent'," "member='Released'," "path='/org/freedesktop/systemd1/agent'", signal_agent_released, m); if (r < 0) { log_warning_errno(r, "Failed to register Released match on new connection bus: %m"); return 0; } } r = bus_setup_disconnected_match(m, bus); if (r < 0) return 0; r = bus_setup_api_vtables(m, bus); if (r < 0) { log_warning_errno(r, "Failed to set up API vtables on new connection bus: %m"); return 0; } r = set_put(m->private_buses, bus); if (r < 0) { log_warning_errno(r, "Failed to add new connection bus to set: %m"); return 0; } bus = NULL; log_debug("Accepted new private connection."); return 0; } int manager_sync_bus_names(Manager *m, sd_bus *bus) { _cleanup_strv_free_ char **names = NULL; const char *name; Iterator i; Unit *u; int r; assert(m); assert(bus); r = sd_bus_list_names(bus, &names, NULL); if (r < 0) return log_error_errno(r, "Failed to get initial list of names: %m"); /* We have to synchronize the current bus names with the * list of active services. To do this, walk the list of * all units with bus names. */ HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) { Service *s = SERVICE(u); assert(s); if (!streq_ptr(s->bus_name, name)) { log_unit_warning(u, "Bus name has changed from %s → %s, ignoring.", s->bus_name, name); continue; } /* Check if a service's bus name is in the list of currently * active names */ if (strv_contains(names, name)) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *unique; /* If it is, determine its current owner */ r = sd_bus_get_name_creds(bus, name, SD_BUS_CREDS_UNIQUE_NAME, &creds); if (r < 0) { log_error_errno(r, "Failed to get bus name owner %s: %m", name); continue; } r = sd_bus_creds_get_unique_name(creds, &unique); if (r < 0) { log_error_errno(r, "Failed to get unique name for %s: %m", name); continue; } /* Now, let's compare that to the previous bus owner, and * if it's still the same, all is fine, so just don't * bother the service. Otherwise, the name has apparently * changed, so synthesize a name owner changed signal. */ if (!streq_ptr(unique, s->bus_name_owner)) UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, unique); } else { /* So, the name we're watching is not on the bus. * This either means it simply hasn't appeared yet, * or it was lost during the daemon reload. * Check if the service has a stored name owner, * and synthesize a name loss signal in this case. */ if (s->bus_name_owner) UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, NULL); } } return 0; } static int bus_setup_api(Manager *m, sd_bus *bus) { Iterator i; char *name; Unit *u; int r; assert(m); assert(bus); /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */ r = sd_bus_negotiate_creds(bus, 1, SD_BUS_CREDS_PID|SD_BUS_CREDS_UID| SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS| SD_BUS_CREDS_SELINUX_CONTEXT); if (r < 0) log_warning_errno(r, "Failed to enable credential passing, ignoring: %m"); r = bus_setup_api_vtables(m, bus); if (r < 0) return r; HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) { r = unit_install_bus_match(u, bus, name); if (r < 0) log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name); } r = sd_bus_add_match( bus, NULL, "type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," "interface='org.freedesktop.systemd1.Activator'," "member='ActivationRequest'", signal_activation_request, m); if (r < 0) log_warning_errno(r, "Failed to subscribe to activation signal: %m"); /* Allow replacing of our name, to ease implementation of * reexecution, where we keep the old connection open until * after the new connection is set up and the name installed * to allow clients to synchronously wait for reexecution to * finish */ r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT); if (r < 0) return log_error_errno(r, "Failed to register name: %m"); r = manager_sync_bus_names(m, bus); if (r < 0) return r; log_debug("Successfully connected to API bus."); return 0; } static int bus_init_api(Manager *m) { _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; int r; if (m->api_bus) return 0; /* The API and system bus is the same if we are running in system mode */ if (m->running_as == MANAGER_SYSTEM && m->system_bus) bus = sd_bus_ref(m->system_bus); else { if (m->running_as == MANAGER_SYSTEM) r = sd_bus_open_system(&bus); else r = sd_bus_open_user(&bus); if (r < 0) { log_debug("Failed to connect to API bus, retrying later..."); return 0; } r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL); if (r < 0) { log_error_errno(r, "Failed to attach API bus to event loop: %m"); return 0; } r = bus_setup_disconnected_match(m, bus); if (r < 0) return 0; } r = bus_setup_api(m, bus); if (r < 0) { log_error_errno(r, "Failed to set up API bus: %m"); return 0; } m->api_bus = bus; bus = NULL; return 0; } static int bus_setup_system(Manager *m, sd_bus *bus) { int r; assert(m); assert(bus); /* On kdbus or if we are a user instance we get the Released message via the system bus */ if (m->running_as == MANAGER_USER || m->kdbus_fd >= 0) { r = sd_bus_add_match( bus, NULL, "type='signal'," "interface='org.freedesktop.systemd1.Agent'," "member='Released'," "path='/org/freedesktop/systemd1/agent'", signal_agent_released, m); if (r < 0) log_warning_errno(r, "Failed to register Released match on system bus: %m"); } log_debug("Successfully connected to system bus."); return 0; } static int bus_init_system(Manager *m) { _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; int r; if (m->system_bus) return 0; /* The API and system bus is the same if we are running in system mode */ if (m->running_as == MANAGER_SYSTEM && m->api_bus) { m->system_bus = sd_bus_ref(m->api_bus); return 0; } r = sd_bus_open_system(&bus); if (r < 0) { log_debug("Failed to connect to system bus, retrying later..."); return 0; } r = bus_setup_disconnected_match(m, bus); if (r < 0) return 0; r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL); if (r < 0) { log_error_errno(r, "Failed to attach system bus to event loop: %m"); return 0; } r = bus_setup_system(m, bus); if (r < 0) { log_error_errno(r, "Failed to set up system bus: %m"); return 0; } m->system_bus = bus; bus = NULL; return 0; } static int bus_init_private(Manager *m) { _cleanup_close_ int fd = -1; union sockaddr_union sa = { .un.sun_family = AF_UNIX }; sd_event_source *s; socklen_t salen; int r; assert(m); if (m->private_listen_fd >= 0) return 0; /* We don't need the private socket if we have kdbus */ if (m->kdbus_fd >= 0) return 0; if (m->running_as == MANAGER_SYSTEM) { /* We want the private bus only when running as init */ if (getpid() != 1) return 0; strcpy(sa.un.sun_path, "/run/systemd/private"); salen = offsetof(union sockaddr_union, un.sun_path) + strlen("/run/systemd/private"); } else { size_t left = sizeof(sa.un.sun_path); char *p = sa.un.sun_path; const char *e; e = secure_getenv("XDG_RUNTIME_DIR"); if (!e) { log_error("Failed to determine XDG_RUNTIME_DIR"); return -EHOSTDOWN; } left = strpcpy(&p, left, e); left = strpcpy(&p, left, "/systemd/private"); salen = sizeof(sa.un) - left; } (void) mkdir_parents_label(sa.un.sun_path, 0755); (void) unlink(sa.un.sun_path); fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (fd < 0) return log_error_errno(errno, "Failed to allocate private socket: %m"); r = bind(fd, &sa.sa, salen); if (r < 0) return log_error_errno(errno, "Failed to bind private socket: %m"); r = listen(fd, SOMAXCONN); if (r < 0) return log_error_errno(errno, "Failed to make private socket listening: %m"); r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m); if (r < 0) return log_error_errno(r, "Failed to allocate event source: %m"); (void) sd_event_source_set_description(s, "bus-connection"); m->private_listen_fd = fd; m->private_listen_event_source = s; fd = -1; log_debug("Successfully created private D-Bus server."); return 0; } int bus_init(Manager *m, bool try_bus_connect) { int r; if (try_bus_connect) { r = bus_init_system(m); if (r < 0) return r; r = bus_init_api(m); if (r < 0) return r; } r = bus_init_private(m); if (r < 0) return r; return 0; } static void destroy_bus(Manager *m, sd_bus **bus) { Iterator i; Job *j; assert(m); assert(bus); if (!*bus) return; /* Get rid of tracked clients on this bus */ if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus) m->subscribed = sd_bus_track_unref(m->subscribed); HASHMAP_FOREACH(j, m->jobs, i) if (j->clients && sd_bus_track_get_bus(j->clients) == *bus) j->clients = sd_bus_track_unref(j->clients); /* Get rid of queued message on this bus */ if (m->queued_message && sd_bus_message_get_bus(m->queued_message) == *bus) m->queued_message = sd_bus_message_unref(m->queued_message); /* Possibly flush unwritten data, but only if we are * unprivileged, since we don't want to sync here */ if (m->running_as != MANAGER_SYSTEM) sd_bus_flush(*bus); /* And destroy the object */ sd_bus_close(*bus); *bus = sd_bus_unref(*bus); } void bus_done(Manager *m) { sd_bus *b; assert(m); if (m->api_bus) destroy_bus(m, &m->api_bus); if (m->system_bus) destroy_bus(m, &m->system_bus); while ((b = set_steal_first(m->private_buses))) destroy_bus(m, &b); m->private_buses = set_free(m->private_buses); m->subscribed = sd_bus_track_unref(m->subscribed); m->deserialized_subscribed = strv_free(m->deserialized_subscribed); if (m->private_listen_event_source) m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source); m->private_listen_fd = safe_close(m->private_listen_fd); bus_verify_polkit_async_registry_free(m->polkit_registry); } int bus_fdset_add_all(Manager *m, FDSet *fds) { Iterator i; sd_bus *b; int fd; assert(m); assert(fds); /* When we are about to reexecute we add all D-Bus fds to the * set to pass over to the newly executed systemd. They won't * be used there however, except thatt they are closed at the * very end of deserialization, those making it possible for * clients to synchronously wait for systemd to reexec by * simply waiting for disconnection */ if (m->api_bus) { fd = sd_bus_get_fd(m->api_bus); if (fd >= 0) { fd = fdset_put_dup(fds, fd); if (fd < 0) return fd; } } SET_FOREACH(b, m->private_buses, i) { fd = sd_bus_get_fd(b); if (fd >= 0) { fd = fdset_put_dup(fds, fd); if (fd < 0) return fd; } } /* We don't offer any APIs on the system bus (well, unless it * is the same as the API bus) hence we don't bother with it * here */ return 0; } int bus_foreach_bus( Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata) { Iterator i; sd_bus *b; int r, ret = 0; /* Send to all direct buses, unconditionally */ SET_FOREACH(b, m->private_buses, i) { r = send_message(b, userdata); if (r < 0) ret = r; } /* Send to API bus, but only if somebody is subscribed */ if (sd_bus_track_count(m->subscribed) > 0 || sd_bus_track_count(subscribed2) > 0) { r = send_message(m->api_bus, userdata); if (r < 0) ret = r; } return ret; } void bus_track_serialize(sd_bus_track *t, FILE *f) { const char *n; assert(f); for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) fprintf(f, "subscribed=%s\n", n); } int bus_track_deserialize_item(char ***l, const char *line) { const char *e; int r; assert(l); assert(line); e = startswith(line, "subscribed="); if (!e) return 0; r = strv_extend(l, e); if (r < 0) return r; return 1; } int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) { int r = 0; assert(m); assert(t); assert(l); if (!strv_isempty(*l) && m->api_bus) { char **i; if (!*t) { r = sd_bus_track_new(m->api_bus, t, NULL, NULL); if (r < 0) return r; } r = 0; STRV_FOREACH(i, *l) { int k; k = sd_bus_track_add_name(*t, *i); if (k < 0) r = k; } } *l = strv_free(*l); return r; } int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error) { return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", NULL, false, UID_INVALID, &m->polkit_registry, error); } int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) { return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", NULL, false, UID_INVALID, &m->polkit_registry, error); } int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) { return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", NULL, false, UID_INVALID, &m->polkit_registry, error); } int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error) { return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", NULL, false, UID_INVALID, &m->polkit_registry, error); } systemd-229/src/core/dbus.h000066400000000000000000000031621265713322000157100ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "manager.h" int bus_send_queued_message(Manager *m); int bus_init(Manager *m, bool try_bus_connect); void bus_done(Manager *m); int bus_fdset_add_all(Manager *m, FDSet *fds); void bus_track_serialize(sd_bus_track *t, FILE *f); int bus_track_deserialize_item(char ***l, const char *line); int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l); int manager_sync_bus_names(Manager *m, sd_bus *bus); int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata); int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error); int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error); int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error); int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error); systemd-229/src/core/device.c000066400000000000000000000665561265713322000162250ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "libudev.h" #include "alloc-util.h" #include "dbus-device.h" #include "device.h" #include "log.h" #include "parse-util.h" #include "path-util.h" #include "stat-util.h" #include "string-util.h" #include "swap.h" #include "udev-util.h" #include "unit-name.h" #include "unit.h" static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = { [DEVICE_DEAD] = UNIT_INACTIVE, [DEVICE_TENTATIVE] = UNIT_ACTIVATING, [DEVICE_PLUGGED] = UNIT_ACTIVE, }; static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); static void device_unset_sysfs(Device *d) { Hashmap *devices; Device *first; assert(d); if (!d->sysfs) return; /* Remove this unit from the chain of devices which share the * same sysfs path. */ devices = UNIT(d)->manager->devices_by_sysfs; first = hashmap_get(devices, d->sysfs); LIST_REMOVE(same_sysfs, first, d); if (first) hashmap_remove_and_replace(devices, d->sysfs, first->sysfs, first); else hashmap_remove(devices, d->sysfs); d->sysfs = mfree(d->sysfs); } static int device_set_sysfs(Device *d, const char *sysfs) { Device *first; char *copy; int r; assert(d); if (streq_ptr(d->sysfs, sysfs)) return 0; r = hashmap_ensure_allocated(&UNIT(d)->manager->devices_by_sysfs, &string_hash_ops); if (r < 0) return r; copy = strdup(sysfs); if (!copy) return -ENOMEM; device_unset_sysfs(d); first = hashmap_get(UNIT(d)->manager->devices_by_sysfs, sysfs); LIST_PREPEND(same_sysfs, first, d); r = hashmap_replace(UNIT(d)->manager->devices_by_sysfs, copy, first); if (r < 0) { LIST_REMOVE(same_sysfs, first, d); free(copy); return r; } d->sysfs = copy; return 0; } static void device_init(Unit *u) { Device *d = DEVICE(u); assert(d); assert(UNIT(d)->load_state == UNIT_STUB); /* In contrast to all other unit types we timeout jobs waiting * for devices by default. This is because they otherwise wait * indefinitely for plugged in devices, something which cannot * happen for the other units since their operations time out * anyway. */ u->job_timeout = u->manager->default_timeout_start_usec; u->ignore_on_isolate = true; } static void device_done(Unit *u) { Device *d = DEVICE(u); assert(d); device_unset_sysfs(d); } static void device_set_state(Device *d, DeviceState state) { DeviceState old_state; assert(d); old_state = d->state; d->state = state; if (state != old_state) log_unit_debug(UNIT(d), "Changed %s -> %s", device_state_to_string(old_state), device_state_to_string(state)); unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], true); } static int device_coldplug(Unit *u) { Device *d = DEVICE(u); assert(d); assert(d->state == DEVICE_DEAD); if (d->found & DEVICE_FOUND_UDEV) /* If udev says the device is around, it's around */ device_set_state(d, DEVICE_PLUGGED); else if (d->found != DEVICE_NOT_FOUND && d->deserialized_state != DEVICE_PLUGGED) /* If a device is found in /proc/self/mountinfo or * /proc/swaps, and was not yet announced via udev, * it's "tentatively" around. */ device_set_state(d, DEVICE_TENTATIVE); return 0; } static int device_serialize(Unit *u, FILE *f, FDSet *fds) { Device *d = DEVICE(u); assert(u); assert(f); assert(fds); unit_serialize_item(u, f, "state", device_state_to_string(d->state)); return 0; } static int device_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Device *d = DEVICE(u); assert(u); assert(key); assert(value); assert(fds); if (streq(key, "state")) { DeviceState state; state = device_state_from_string(value); if (state < 0) log_unit_debug(u, "Failed to parse state value: %s", value); else d->deserialized_state = state; } else log_unit_debug(u, "Unknown serialization key: %s", key); return 0; } static void device_dump(Unit *u, FILE *f, const char *prefix) { Device *d = DEVICE(u); assert(d); fprintf(f, "%sDevice State: %s\n" "%sSysfs Path: %s\n", prefix, device_state_to_string(d->state), prefix, strna(d->sysfs)); } _pure_ static UnitActiveState device_active_state(Unit *u) { assert(u); return state_translation_table[DEVICE(u)->state]; } _pure_ static const char *device_sub_state_to_string(Unit *u) { assert(u); return device_state_to_string(DEVICE(u)->state); } static int device_update_description(Unit *u, struct udev_device *dev, const char *path) { const char *model; int r; assert(u); assert(dev); assert(path); model = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE"); if (!model) model = udev_device_get_property_value(dev, "ID_MODEL"); if (model) { const char *label; /* Try to concatenate the device model string with a label, if there is one */ label = udev_device_get_property_value(dev, "ID_FS_LABEL"); if (!label) label = udev_device_get_property_value(dev, "ID_PART_ENTRY_NAME"); if (!label) label = udev_device_get_property_value(dev, "ID_PART_ENTRY_NUMBER"); if (label) { _cleanup_free_ char *j; j = strjoin(model, " ", label, NULL); if (j) r = unit_set_description(u, j); else r = -ENOMEM; } else r = unit_set_description(u, model); } else r = unit_set_description(u, path); if (r < 0) log_unit_error_errno(u, r, "Failed to set device description: %m"); return r; } static int device_add_udev_wants(Unit *u, struct udev_device *dev) { const char *wants; const char *word, *state; size_t l; int r; const char *property; assert(u); assert(dev); property = u->manager->running_as == MANAGER_USER ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS"; wants = udev_device_get_property_value(dev, property); if (!wants) return 0; FOREACH_WORD_QUOTED(word, l, wants, state) { _cleanup_free_ char *n = NULL; char e[l+1]; memcpy(e, word, l); e[l] = 0; r = unit_name_mangle(e, UNIT_NAME_NOGLOB, &n); if (r < 0) return log_unit_error_errno(u, r, "Failed to mangle unit name: %m"); r = unit_add_dependency_by_name(u, UNIT_WANTS, n, NULL, true); if (r < 0) return log_unit_error_errno(u, r, "Failed to add wants dependency: %m"); } if (!isempty(state)) log_unit_warning(u, "Property %s on %s has trailing garbage, ignoring.", property, strna(udev_device_get_syspath(dev))); return 0; } static int device_setup_unit(Manager *m, struct udev_device *dev, const char *path, bool main) { _cleanup_free_ char *e = NULL; const char *sysfs = NULL; Unit *u = NULL; bool delete; int r; assert(m); assert(path); if (dev) { sysfs = udev_device_get_syspath(dev); if (!sysfs) return 0; } r = unit_name_from_path(path, ".device", &e); if (r < 0) return log_error_errno(r, "Failed to generate unit name from device path: %m"); u = manager_get_unit(m, e); /* The device unit can still be present even if the device was * unplugged: a mount unit can reference it hence preventing * the GC to have garbaged it. That's desired since the device * unit may have a dependency on the mount unit which was * added during the loading of the later. */ if (u && DEVICE(u)->state == DEVICE_PLUGGED) { /* This unit is in plugged state: we're sure it's * attached to a device. */ if (!path_equal(DEVICE(u)->sysfs, sysfs)) { log_unit_error(u, "Dev %s appeared twice with different sysfs paths %s and %s", e, DEVICE(u)->sysfs, sysfs); return -EEXIST; } } if (!u) { delete = true; u = unit_new(m, sizeof(Device)); if (!u) return log_oom(); r = unit_add_name(u, e); if (r < 0) goto fail; unit_add_to_load_queue(u); } else delete = false; /* If this was created via some dependency and has not * actually been seen yet ->sysfs will not be * initialized. Hence initialize it if necessary. */ if (sysfs) { r = device_set_sysfs(DEVICE(u), sysfs); if (r < 0) goto fail; (void) device_update_description(u, dev, path); /* The additional systemd udev properties we only interpret * for the main object */ if (main) (void) device_add_udev_wants(u, dev); } /* Note that this won't dispatch the load queue, the caller * has to do that if needed and appropriate */ unit_add_to_dbus_queue(u); return 0; fail: log_unit_warning_errno(u, r, "Failed to set up device unit: %m"); if (delete) unit_free(u); return r; } static int device_process_new(Manager *m, struct udev_device *dev) { const char *sysfs, *dn, *alias; struct udev_list_entry *item = NULL, *first = NULL; int r; assert(m); sysfs = udev_device_get_syspath(dev); if (!sysfs) return 0; /* Add the main unit named after the sysfs path */ r = device_setup_unit(m, dev, sysfs, true); if (r < 0) return r; /* Add an additional unit for the device node */ dn = udev_device_get_devnode(dev); if (dn) (void) device_setup_unit(m, dev, dn, false); /* Add additional units for all symlinks */ first = udev_device_get_devlinks_list_entry(dev); udev_list_entry_foreach(item, first) { const char *p; struct stat st; /* Don't bother with the /dev/block links */ p = udev_list_entry_get_name(item); if (path_startswith(p, "/dev/block/") || path_startswith(p, "/dev/char/")) continue; /* Verify that the symlink in the FS actually belongs * to this device. This is useful to deal with * conflicting devices, e.g. when two disks want the * same /dev/disk/by-label/xxx link because they have * the same label. We want to make sure that the same * device that won the symlink wins in systemd, so we * check the device node major/minor */ if (stat(p, &st) >= 0) if ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) || st.st_rdev != udev_device_get_devnum(dev)) continue; (void) device_setup_unit(m, dev, p, false); } /* Add additional units for all explicitly configured * aliases */ alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS"); if (alias) { const char *word, *state; size_t l; FOREACH_WORD_QUOTED(word, l, alias, state) { char e[l+1]; memcpy(e, word, l); e[l] = 0; if (path_is_absolute(e)) (void) device_setup_unit(m, dev, e, false); else log_warning("SYSTEMD_ALIAS for %s is not an absolute path, ignoring: %s", sysfs, e); } if (!isempty(state)) log_warning("SYSTEMD_ALIAS for %s has trailing garbage, ignoring.", sysfs); } return 0; } static void device_update_found_one(Device *d, bool add, DeviceFound found, bool now) { DeviceFound n, previous; assert(d); n = add ? (d->found | found) : (d->found & ~found); if (n == d->found) return; previous = d->found; d->found = n; if (!now) return; if (d->found & DEVICE_FOUND_UDEV) /* When the device is known to udev we consider it * plugged. */ device_set_state(d, DEVICE_PLUGGED); else if (d->found != DEVICE_NOT_FOUND && (previous & DEVICE_FOUND_UDEV) == 0) /* If the device has not been seen by udev yet, but is * now referenced by the kernel, then we assume the * kernel knows it now, and udev might soon too. */ device_set_state(d, DEVICE_TENTATIVE); else /* If nobody sees the device, or if the device was * previously seen by udev and now is only referenced * from the kernel, then we consider the device is * gone, the kernel just hasn't noticed it yet. */ device_set_state(d, DEVICE_DEAD); } static int device_update_found_by_sysfs(Manager *m, const char *sysfs, bool add, DeviceFound found, bool now) { Device *d, *l; assert(m); assert(sysfs); if (found == DEVICE_NOT_FOUND) return 0; l = hashmap_get(m->devices_by_sysfs, sysfs); LIST_FOREACH(same_sysfs, d, l) device_update_found_one(d, add, found, now); return 0; } static int device_update_found_by_name(Manager *m, const char *path, bool add, DeviceFound found, bool now) { _cleanup_free_ char *e = NULL; Unit *u; int r; assert(m); assert(path); if (found == DEVICE_NOT_FOUND) return 0; r = unit_name_from_path(path, ".device", &e); if (r < 0) return log_error_errno(r, "Failed to generate unit name from device path: %m"); u = manager_get_unit(m, e); if (!u) return 0; device_update_found_one(DEVICE(u), add, found, now); return 0; } static bool device_is_ready(struct udev_device *dev) { const char *ready; assert(dev); ready = udev_device_get_property_value(dev, "SYSTEMD_READY"); if (!ready) return true; return parse_boolean(ready) != 0; } static Unit *device_following(Unit *u) { Device *d = DEVICE(u); Device *other, *first = NULL; assert(d); if (startswith(u->id, "sys-")) return NULL; /* Make everybody follow the unit that's named after the sysfs path */ for (other = d->same_sysfs_next; other; other = other->same_sysfs_next) if (startswith(UNIT(other)->id, "sys-")) return UNIT(other); for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev) { if (startswith(UNIT(other)->id, "sys-")) return UNIT(other); first = other; } return UNIT(first); } static int device_following_set(Unit *u, Set **_set) { Device *d = DEVICE(u), *other; Set *set; int r; assert(d); assert(_set); if (LIST_JUST_US(same_sysfs, d)) { *_set = NULL; return 0; } set = set_new(NULL); if (!set) return -ENOMEM; LIST_FOREACH_AFTER(same_sysfs, other, d) { r = set_put(set, other); if (r < 0) goto fail; } LIST_FOREACH_BEFORE(same_sysfs, other, d) { r = set_put(set, other); if (r < 0) goto fail; } *_set = set; return 1; fail: set_free(set); return r; } static void device_shutdown(Manager *m) { assert(m); m->udev_event_source = sd_event_source_unref(m->udev_event_source); if (m->udev_monitor) { udev_monitor_unref(m->udev_monitor); m->udev_monitor = NULL; } m->devices_by_sysfs = hashmap_free(m->devices_by_sysfs); } static void device_enumerate(Manager *m) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; struct udev_list_entry *item = NULL, *first = NULL; int r; assert(m); if (!m->udev_monitor) { m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"); if (!m->udev_monitor) { log_oom(); goto fail; } /* This will fail if we are unprivileged, but that * should not matter much, as user instances won't run * during boot. */ (void) udev_monitor_set_receive_buffer_size(m->udev_monitor, 128*1024*1024); r = udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd"); if (r < 0) { log_error_errno(r, "Failed to add udev tag match: %m"); goto fail; } r = udev_monitor_enable_receiving(m->udev_monitor); if (r < 0) { log_error_errno(r, "Failed to enable udev event reception: %m"); goto fail; } r = sd_event_add_io(m->event, &m->udev_event_source, udev_monitor_get_fd(m->udev_monitor), EPOLLIN, device_dispatch_io, m); if (r < 0) { log_error_errno(r, "Failed to watch udev file descriptor: %m"); goto fail; } (void) sd_event_source_set_description(m->udev_event_source, "device"); } e = udev_enumerate_new(m->udev); if (!e) { log_oom(); goto fail; } r = udev_enumerate_add_match_tag(e, "systemd"); if (r < 0) { log_error_errno(r, "Failed to create udev tag enumeration: %m"); goto fail; } r = udev_enumerate_add_match_is_initialized(e); if (r < 0) { log_error_errno(r, "Failed to install initialization match into enumeration: %m"); goto fail; } r = udev_enumerate_scan_devices(e); if (r < 0) { log_error_errno(r, "Failed to enumerate devices: %m"); goto fail; } first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *dev = NULL; const char *sysfs; sysfs = udev_list_entry_get_name(item); dev = udev_device_new_from_syspath(m->udev, sysfs); if (!dev) { log_oom(); continue; } if (!device_is_ready(dev)) continue; (void) device_process_new(m, dev); device_update_found_by_sysfs(m, sysfs, true, DEVICE_FOUND_UDEV, false); } return; fail: device_shutdown(m); } static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { _cleanup_udev_device_unref_ struct udev_device *dev = NULL; Manager *m = userdata; const char *action, *sysfs; int r; assert(m); if (revents != EPOLLIN) { static RATELIMIT_DEFINE(limit, 10*USEC_PER_SEC, 5); if (!ratelimit_test(&limit)) log_error_errno(errno, "Failed to get udev event: %m"); if (!(revents & EPOLLIN)) return 0; } /* * libudev might filter-out devices which pass the bloom * filter, so getting NULL here is not necessarily an error. */ dev = udev_monitor_receive_device(m->udev_monitor); if (!dev) return 0; sysfs = udev_device_get_syspath(dev); if (!sysfs) { log_error("Failed to get udev sys path."); return 0; } action = udev_device_get_action(dev); if (!action) { log_error("Failed to get udev action string."); return 0; } if (streq(action, "remove")) { r = swap_process_device_remove(m, dev); if (r < 0) log_error_errno(r, "Failed to process swap device remove event: %m"); /* If we get notified that a device was removed by * udev, then it's completely gone, hence unset all * found bits */ device_update_found_by_sysfs(m, sysfs, false, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP, true); } else if (device_is_ready(dev)) { (void) device_process_new(m, dev); r = swap_process_device_new(m, dev); if (r < 0) log_error_errno(r, "Failed to process swap device new event: %m"); manager_dispatch_load_queue(m); /* The device is found now, set the udev found bit */ device_update_found_by_sysfs(m, sysfs, true, DEVICE_FOUND_UDEV, true); } else { /* The device is nominally around, but not ready for * us. Hence unset the udev bit, but leave the rest * around. */ device_update_found_by_sysfs(m, sysfs, false, DEVICE_FOUND_UDEV, true); } return 0; } static bool device_supported(void) { static int read_only = -1; /* If /sys is read-only we don't support device units, and any * attempts to start one should fail immediately. */ if (read_only < 0) read_only = path_is_read_only_fs("/sys"); return read_only <= 0; } int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, bool now) { _cleanup_udev_device_unref_ struct udev_device *dev = NULL; struct stat st; assert(m); assert(node); if (!device_supported()) return 0; /* This is called whenever we find a device referenced in * /proc/swaps or /proc/self/mounts. Such a device might be * mounted/enabled at a time where udev has not finished * probing it yet, and we thus haven't learned about it * yet. In this case we will set the device unit to * "tentative" state. */ if (add) { if (!path_startswith(node, "/dev")) return 0; /* We make an extra check here, if the device node * actually exists. If it's missing, then this is an * indication that device was unplugged but is still * referenced in /proc/swaps or * /proc/self/mountinfo. Note that this check doesn't * really cover all cases where a device might be gone * away, since drives that can have a medium inserted * will still have a device node even when the medium * is not there... */ if (stat(node, &st) >= 0) { if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) return 0; dev = udev_device_new_from_devnum(m->udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev); if (!dev && errno != ENOENT) return log_error_errno(errno, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev)); } else if (errno != ENOENT) return log_error_errno(errno, "Failed to stat device node file %s: %m", node); /* If the device is known in the kernel and newly * appeared, then we'll create a device unit for it, * under the name referenced in /proc/swaps or * /proc/self/mountinfo. */ (void) device_setup_unit(m, dev, node, false); } /* Update the device unit's state, should it exist */ return device_update_found_by_name(m, node, add, found, now); } const UnitVTable device_vtable = { .object_size = sizeof(Device), .sections = "Unit\0" "Device\0" "Install\0", .no_instances = true, .init = device_init, .done = device_done, .load = unit_load_fragment_and_dropin_optional, .coldplug = device_coldplug, .serialize = device_serialize, .deserialize_item = device_deserialize_item, .dump = device_dump, .active_state = device_active_state, .sub_state_to_string = device_sub_state_to_string, .bus_vtable = bus_device_vtable, .following = device_following, .following_set = device_following_set, .enumerate = device_enumerate, .shutdown = device_shutdown, .supported = device_supported, .status_message_formats = { .starting_stopping = { [0] = "Expecting device %s...", }, .finished_start_job = { [JOB_DONE] = "Found device %s.", [JOB_TIMEOUT] = "Timed out waiting for device %s.", }, }, }; systemd-229/src/core/device.h000066400000000000000000000026421265713322000162140ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Device Device; typedef enum DeviceFound { DEVICE_NOT_FOUND = 0, DEVICE_FOUND_UDEV = 1, DEVICE_FOUND_MOUNT = 2, DEVICE_FOUND_SWAP = 4, } DeviceFound; struct Device { Unit meta; char *sysfs; DeviceFound found; /* In order to be able to distinguish dependencies on different device nodes we might end up creating multiple devices for the same sysfs path. We chain them up here. */ LIST_FIELDS(struct Device, same_sysfs); DeviceState state, deserialized_state; }; extern const UnitVTable device_vtable; int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, bool now); systemd-229/src/core/execute.c000066400000000000000000003074021265713322000164140ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_PAM #include #endif #ifdef HAVE_SELINUX #include #endif #ifdef HAVE_SECCOMP #include #endif #ifdef HAVE_APPARMOR #include #endif #include "sd-messages.h" #include "af-list.h" #include "alloc-util.h" #ifdef HAVE_APPARMOR #include "apparmor-util.h" #endif #include "async.h" #include "barrier.h" #include "bus-endpoint.h" #include "cap-list.h" #include "capability-util.h" #include "def.h" #include "env-util.h" #include "errno-list.h" #include "execute.h" #include "exit-status.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "glob-util.h" #include "io-util.h" #include "ioprio.h" #include "log.h" #include "macro.h" #include "missing.h" #include "mkdir.h" #include "namespace.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "rlimit-util.h" #include "rm-rf.h" #ifdef HAVE_SECCOMP #include "seccomp-util.h" #endif #include "securebits.h" #include "selinux-util.h" #include "signal-util.h" #include "smack-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "syslog-util.h" #include "terminal-util.h" #include "unit.h" #include "user-util.h" #include "util.h" #include "utmp-wtmp.h" #define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC) #define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC) /* This assumes there is a 'tty' group */ #define TTY_MODE 0620 #define SNDBUF_SIZE (8*1024*1024) static int shift_fds(int fds[], unsigned n_fds) { int start, restart_from; if (n_fds <= 0) return 0; /* Modifies the fds array! (sorts it) */ assert(fds); start = 0; for (;;) { int i; restart_from = -1; for (i = start; i < (int) n_fds; i++) { int nfd; /* Already at right index? */ if (fds[i] == i+3) continue; nfd = fcntl(fds[i], F_DUPFD, i + 3); if (nfd < 0) return -errno; safe_close(fds[i]); fds[i] = nfd; /* Hmm, the fd we wanted isn't free? Then * let's remember that and try again from here */ if (nfd != i+3 && restart_from < 0) restart_from = i; } if (restart_from < 0) break; start = restart_from; } return 0; } static int flags_fds(const int fds[], unsigned n_fds, bool nonblock) { unsigned i; int r; if (n_fds <= 0) return 0; assert(fds); /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */ for (i = 0; i < n_fds; i++) { r = fd_nonblock(fds[i], nonblock); if (r < 0) return r; /* We unconditionally drop FD_CLOEXEC from the fds, * since after all we want to pass these fds to our * children */ r = fd_cloexec(fds[i], false); if (r < 0) return r; } return 0; } static const char *exec_context_tty_path(const ExecContext *context) { assert(context); if (context->stdio_as_fds) return NULL; if (context->tty_path) return context->tty_path; return "/dev/console"; } static void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p) { const char *path; assert(context); path = exec_context_tty_path(context); if (context->tty_vhangup) { if (p && p->stdin_fd >= 0) (void) terminal_vhangup_fd(p->stdin_fd); else if (path) (void) terminal_vhangup(path); } if (context->tty_reset) { if (p && p->stdin_fd >= 0) (void) reset_terminal_fd(p->stdin_fd, true); else if (path) (void) reset_terminal(path); } if (context->tty_vt_disallocate && path) (void) vt_disallocate(path); } static bool is_terminal_output(ExecOutput o) { return o == EXEC_OUTPUT_TTY || o == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || o == EXEC_OUTPUT_KMSG_AND_CONSOLE || o == EXEC_OUTPUT_JOURNAL_AND_CONSOLE; } static int open_null_as(int flags, int nfd) { int fd, r; assert(nfd >= 0); fd = open("/dev/null", flags|O_NOCTTY); if (fd < 0) return -errno; if (fd != nfd) { r = dup2(fd, nfd) < 0 ? -errno : nfd; safe_close(fd); } else r = nfd; return r; } static int connect_journal_socket(int fd, uid_t uid, gid_t gid) { union sockaddr_union sa = { .un.sun_family = AF_UNIX, .un.sun_path = "/run/systemd/journal/stdout", }; uid_t olduid = UID_INVALID; gid_t oldgid = GID_INVALID; int r; if (gid != GID_INVALID) { oldgid = getgid(); r = setegid(gid); if (r < 0) return -errno; } if (uid != UID_INVALID) { olduid = getuid(); r = seteuid(uid); if (r < 0) { r = -errno; goto restore_gid; } } r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)); if (r < 0) r = -errno; /* If we fail to restore the uid or gid, things will likely fail later on. This should only happen if an LSM interferes. */ if (uid != UID_INVALID) (void) seteuid(olduid); restore_gid: if (gid != GID_INVALID) (void) setegid(oldgid); return r; } static int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, const char *unit_id, int nfd, uid_t uid, gid_t gid) { int fd, r; assert(context); assert(output < _EXEC_OUTPUT_MAX); assert(ident); assert(nfd >= 0); fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) return -errno; r = connect_journal_socket(fd, uid, gid); if (r < 0) return r; if (shutdown(fd, SHUT_RD) < 0) { safe_close(fd); return -errno; } fd_inc_sndbuf(fd, SNDBUF_SIZE); dprintf(fd, "%s\n" "%s\n" "%i\n" "%i\n" "%i\n" "%i\n" "%i\n", context->syslog_identifier ? context->syslog_identifier : ident, unit_id, context->syslog_priority, !!context->syslog_level_prefix, output == EXEC_OUTPUT_SYSLOG || output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE, output == EXEC_OUTPUT_KMSG || output == EXEC_OUTPUT_KMSG_AND_CONSOLE, is_terminal_output(output)); if (fd != nfd) { r = dup2(fd, nfd) < 0 ? -errno : nfd; safe_close(fd); } else r = nfd; return r; } static int open_terminal_as(const char *path, mode_t mode, int nfd) { int fd, r; assert(path); assert(nfd >= 0); fd = open_terminal(path, mode | O_NOCTTY); if (fd < 0) return fd; if (fd != nfd) { r = dup2(fd, nfd) < 0 ? -errno : nfd; safe_close(fd); } else r = nfd; return r; } static bool is_terminal_input(ExecInput i) { return i == EXEC_INPUT_TTY || i == EXEC_INPUT_TTY_FORCE || i == EXEC_INPUT_TTY_FAIL; } static int fixup_input(ExecInput std_input, int socket_fd, bool apply_tty_stdin) { if (is_terminal_input(std_input) && !apply_tty_stdin) return EXEC_INPUT_NULL; if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0) return EXEC_INPUT_NULL; return std_input; } static int fixup_output(ExecOutput std_output, int socket_fd) { if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0) return EXEC_OUTPUT_INHERIT; return std_output; } static int setup_input( const ExecContext *context, const ExecParameters *params, int socket_fd) { ExecInput i; assert(context); assert(params); if (params->stdin_fd >= 0) { if (dup2(params->stdin_fd, STDIN_FILENO) < 0) return -errno; /* Try to make this the controlling tty, if it is a tty, and reset it */ (void) ioctl(STDIN_FILENO, TIOCSCTTY, context->std_input == EXEC_INPUT_TTY_FORCE); (void) reset_terminal_fd(STDIN_FILENO, true); return STDIN_FILENO; } i = fixup_input(context->std_input, socket_fd, params->apply_tty_stdin); switch (i) { case EXEC_INPUT_NULL: return open_null_as(O_RDONLY, STDIN_FILENO); case EXEC_INPUT_TTY: case EXEC_INPUT_TTY_FORCE: case EXEC_INPUT_TTY_FAIL: { int fd, r; fd = acquire_terminal(exec_context_tty_path(context), i == EXEC_INPUT_TTY_FAIL, i == EXEC_INPUT_TTY_FORCE, false, USEC_INFINITY); if (fd < 0) return fd; if (fd != STDIN_FILENO) { r = dup2(fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO; safe_close(fd); } else r = STDIN_FILENO; return r; } case EXEC_INPUT_SOCKET: return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO; default: assert_not_reached("Unknown input type"); } } static int setup_output( Unit *unit, const ExecContext *context, const ExecParameters *params, int fileno, int socket_fd, const char *ident, uid_t uid, gid_t gid) { ExecOutput o; ExecInput i; int r; assert(unit); assert(context); assert(params); assert(ident); if (fileno == STDOUT_FILENO && params->stdout_fd >= 0) { if (dup2(params->stdout_fd, STDOUT_FILENO) < 0) return -errno; return STDOUT_FILENO; } if (fileno == STDERR_FILENO && params->stderr_fd >= 0) { if (dup2(params->stderr_fd, STDERR_FILENO) < 0) return -errno; return STDERR_FILENO; } i = fixup_input(context->std_input, socket_fd, params->apply_tty_stdin); o = fixup_output(context->std_output, socket_fd); if (fileno == STDERR_FILENO) { ExecOutput e; e = fixup_output(context->std_error, socket_fd); /* This expects the input and output are already set up */ /* Don't change the stderr file descriptor if we inherit all * the way and are not on a tty */ if (e == EXEC_OUTPUT_INHERIT && o == EXEC_OUTPUT_INHERIT && i == EXEC_INPUT_NULL && !is_terminal_input(context->std_input) && getppid () != 1) return fileno; /* Duplicate from stdout if possible */ if (e == o || e == EXEC_OUTPUT_INHERIT) return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno; o = e; } else if (o == EXEC_OUTPUT_INHERIT) { /* If input got downgraded, inherit the original value */ if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input)) return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno); /* If the input is connected to anything that's not a /dev/null, inherit that... */ if (i != EXEC_INPUT_NULL) return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno; /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */ if (getppid() != 1) return fileno; /* We need to open /dev/null here anew, to get the right access mode. */ return open_null_as(O_WRONLY, fileno); } switch (o) { case EXEC_OUTPUT_NULL: return open_null_as(O_WRONLY, fileno); case EXEC_OUTPUT_TTY: if (is_terminal_input(i)) return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno; /* We don't reset the terminal if this is just about output */ return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno); case EXEC_OUTPUT_SYSLOG: case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: case EXEC_OUTPUT_KMSG: case EXEC_OUTPUT_KMSG_AND_CONSOLE: case EXEC_OUTPUT_JOURNAL: case EXEC_OUTPUT_JOURNAL_AND_CONSOLE: r = connect_logger_as(context, o, ident, unit->id, fileno, uid, gid); if (r < 0) { log_unit_error_errno(unit, r, "Failed to connect %s to the journal socket, ignoring: %m", fileno == STDOUT_FILENO ? "stdout" : "stderr"); r = open_null_as(O_WRONLY, fileno); } return r; case EXEC_OUTPUT_SOCKET: assert(socket_fd >= 0); return dup2(socket_fd, fileno) < 0 ? -errno : fileno; default: assert_not_reached("Unknown error type"); } } static int chown_terminal(int fd, uid_t uid) { struct stat st; assert(fd >= 0); /* This might fail. What matters are the results. */ (void) fchown(fd, uid, -1); (void) fchmod(fd, TTY_MODE); if (fstat(fd, &st) < 0) return -errno; if (st.st_uid != uid || (st.st_mode & 0777) != TTY_MODE) return -EPERM; return 0; } static int setup_confirm_stdio(int *_saved_stdin, int *_saved_stdout) { _cleanup_close_ int fd = -1, saved_stdin = -1, saved_stdout = -1; int r; assert(_saved_stdin); assert(_saved_stdout); saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3); if (saved_stdin < 0) return -errno; saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3); if (saved_stdout < 0) return -errno; fd = acquire_terminal( "/dev/console", false, false, false, DEFAULT_CONFIRM_USEC); if (fd < 0) return fd; r = chown_terminal(fd, getuid()); if (r < 0) return r; r = reset_terminal_fd(fd, true); if (r < 0) return r; if (dup2(fd, STDIN_FILENO) < 0) return -errno; if (dup2(fd, STDOUT_FILENO) < 0) return -errno; if (fd >= 2) safe_close(fd); fd = -1; *_saved_stdin = saved_stdin; *_saved_stdout = saved_stdout; saved_stdin = saved_stdout = -1; return 0; } _printf_(1, 2) static int write_confirm_message(const char *format, ...) { _cleanup_close_ int fd = -1; va_list ap; assert(format); fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) return fd; va_start(ap, format); vdprintf(fd, format, ap); va_end(ap); return 0; } static int restore_confirm_stdio(int *saved_stdin, int *saved_stdout) { int r = 0; assert(saved_stdin); assert(saved_stdout); release_terminal(); if (*saved_stdin >= 0) if (dup2(*saved_stdin, STDIN_FILENO) < 0) r = -errno; if (*saved_stdout >= 0) if (dup2(*saved_stdout, STDOUT_FILENO) < 0) r = -errno; *saved_stdin = safe_close(*saved_stdin); *saved_stdout = safe_close(*saved_stdout); return r; } static int ask_for_confirmation(char *response, char **argv) { int saved_stdout = -1, saved_stdin = -1, r; _cleanup_free_ char *line = NULL; r = setup_confirm_stdio(&saved_stdin, &saved_stdout); if (r < 0) return r; line = exec_command_line(argv); if (!line) return -ENOMEM; r = ask_char(response, "yns", "Execute %s? [Yes, No, Skip] ", line); restore_confirm_stdio(&saved_stdin, &saved_stdout); return r; } static int enforce_groups(const ExecContext *context, const char *username, gid_t gid) { bool keep_groups = false; int r; assert(context); /* Lookup and set GID and supplementary group list. Here too * we avoid NSS lookups for gid=0. */ if (context->group || username) { /* First step, initialize groups from /etc/groups */ if (username && gid != 0) { if (initgroups(username, gid) < 0) return -errno; keep_groups = true; } /* Second step, set our gids */ if (setresgid(gid, gid, gid) < 0) return -errno; } if (context->supplementary_groups) { int ngroups_max, k; gid_t *gids; char **i; /* Final step, initialize any manually set supplementary groups */ assert_se((ngroups_max = (int) sysconf(_SC_NGROUPS_MAX)) > 0); if (!(gids = new(gid_t, ngroups_max))) return -ENOMEM; if (keep_groups) { k = getgroups(ngroups_max, gids); if (k < 0) { free(gids); return -errno; } } else k = 0; STRV_FOREACH(i, context->supplementary_groups) { const char *g; if (k >= ngroups_max) { free(gids); return -E2BIG; } g = *i; r = get_group_creds(&g, gids+k); if (r < 0) { free(gids); return r; } k++; } if (setgroups(k, gids) < 0) { free(gids); return -errno; } free(gids); } return 0; } static int enforce_user(const ExecContext *context, uid_t uid) { assert(context); /* Sets (but doesn't lookup) the uid and make sure we keep the * capabilities while doing so. */ if (context->capabilities || context->capability_ambient_set != 0) { /* First step: If we need to keep capabilities but * drop privileges we need to make sure we keep our * caps, while we drop privileges. */ if (uid != 0) { int sb = context->secure_bits | 1<capabilities) { _cleanup_cap_free_ cap_t d = NULL; static const cap_value_t bits[] = { CAP_SETUID, /* Necessary so that we can run setresuid() below */ CAP_SETPCAP /* Necessary so that we can set PR_SET_SECUREBITS later on */ }; d = cap_dup(context->capabilities); if (!d) return -errno; if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 || cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0) return -errno; if (cap_set_proc(d) < 0) return -errno; } } /* Third step: actually set the uids */ if (setresuid(uid, uid, uid) < 0) return -errno; /* At this point we should have all necessary capabilities but are otherwise a normal user. However, the caps might got corrupted due to the setresuid() so we need clean them up later. This is done outside of this call. */ return 0; } #ifdef HAVE_PAM static int null_conv( int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { /* We don't support conversations */ return PAM_CONV_ERR; } static int setup_pam( const char *name, const char *user, uid_t uid, const char *tty, char ***pam_env, int fds[], unsigned n_fds) { static const struct pam_conv conv = { .conv = null_conv, .appdata_ptr = NULL }; _cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL; pam_handle_t *handle = NULL; sigset_t old_ss; int pam_code = PAM_SUCCESS, r; char **e = NULL; bool close_session = false; pid_t pam_pid = 0, parent_pid; int flags = 0; assert(name); assert(user); assert(pam_env); /* We set up PAM in the parent process, then fork. The child * will then stay around until killed via PR_GET_PDEATHSIG or * systemd via the cgroup logic. It will then remove the PAM * session again. The parent process will exec() the actual * daemon. We do things this way to ensure that the main PID * of the daemon is the one we initially fork()ed. */ r = barrier_create(&barrier); if (r < 0) goto fail; if (log_get_max_level() < LOG_DEBUG) flags |= PAM_SILENT; pam_code = pam_start(name, user, &conv, &handle); if (pam_code != PAM_SUCCESS) { handle = NULL; goto fail; } if (tty) { pam_code = pam_set_item(handle, PAM_TTY, tty); if (pam_code != PAM_SUCCESS) goto fail; } pam_code = pam_acct_mgmt(handle, flags); if (pam_code != PAM_SUCCESS) goto fail; pam_code = pam_open_session(handle, flags); if (pam_code != PAM_SUCCESS) goto fail; close_session = true; e = pam_getenvlist(handle); if (!e) { pam_code = PAM_BUF_ERR; goto fail; } /* Block SIGTERM, so that we know that it won't get lost in * the child */ assert_se(sigprocmask_many(SIG_BLOCK, &old_ss, SIGTERM, -1) >= 0); parent_pid = getpid(); pam_pid = fork(); if (pam_pid < 0) { r = -errno; goto fail; } if (pam_pid == 0) { int sig, ret = EXIT_PAM; /* The child's job is to reset the PAM session on * termination */ barrier_set_role(&barrier, BARRIER_CHILD); /* This string must fit in 10 chars (i.e. the length * of "/sbin/init"), to look pretty in /bin/ps */ rename_process("(sd-pam)"); /* Make sure we don't keep open the passed fds in this child. We assume that otherwise only those fds are open here that have been opened by PAM. */ close_many(fds, n_fds); /* Drop privileges - we don't need any to pam_close_session * and this will make PR_SET_PDEATHSIG work in most cases. * If this fails, ignore the error - but expect sd-pam threads * to fail to exit normally */ if (setresuid(uid, uid, uid) < 0) log_error_errno(r, "Error: Failed to setresuid() in sd-pam: %m"); (void) ignore_signals(SIGPIPE, -1); /* Wait until our parent died. This will only work if * the above setresuid() succeeds, otherwise the kernel * will not allow unprivileged parents kill their privileged * children this way. We rely on the control groups kill logic * to do the rest for us. */ if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) goto child_finish; /* Tell the parent that our setup is done. This is especially * important regarding dropping privileges. Otherwise, unit * setup might race against our setresuid(2) call. */ barrier_place(&barrier); /* Check if our parent process might already have * died? */ if (getppid() == parent_pid) { sigset_t ss; assert_se(sigemptyset(&ss) >= 0); assert_se(sigaddset(&ss, SIGTERM) >= 0); for (;;) { if (sigwait(&ss, &sig) < 0) { if (errno == EINTR) continue; goto child_finish; } assert(sig == SIGTERM); break; } } /* If our parent died we'll end the session */ if (getppid() != parent_pid) { pam_code = pam_close_session(handle, flags); if (pam_code != PAM_SUCCESS) goto child_finish; } ret = 0; child_finish: pam_end(handle, pam_code | flags); _exit(ret); } barrier_set_role(&barrier, BARRIER_PARENT); /* If the child was forked off successfully it will do all the * cleanups, so forget about the handle here. */ handle = NULL; /* Unblock SIGTERM again in the parent */ assert_se(sigprocmask(SIG_SETMASK, &old_ss, NULL) >= 0); /* We close the log explicitly here, since the PAM modules * might have opened it, but we don't want this fd around. */ closelog(); /* Synchronously wait for the child to initialize. We don't care for * errors as we cannot recover. However, warn loudly if it happens. */ if (!barrier_place_and_sync(&barrier)) log_error("PAM initialization failed"); *pam_env = e; e = NULL; return 0; fail: if (pam_code != PAM_SUCCESS) { log_error("PAM failed: %s", pam_strerror(handle, pam_code)); r = -EPERM; /* PAM errors do not map to errno */ } else log_error_errno(r, "PAM failed: %m"); if (handle) { if (close_session) pam_code = pam_close_session(handle, flags); pam_end(handle, pam_code | flags); } strv_free(e); closelog(); return r; } #endif static void rename_process_from_path(const char *path) { char process_name[11]; const char *p; size_t l; /* This resulting string must fit in 10 chars (i.e. the length * of "/sbin/init") to look pretty in /bin/ps */ p = basename(path); if (isempty(p)) { rename_process("(...)"); return; } l = strlen(p); if (l > 8) { /* The end of the process name is usually more * interesting, since the first bit might just be * "systemd-" */ p = p + l - 8; l = 8; } process_name[0] = '('; memcpy(process_name+1, p, l); process_name[1+l] = ')'; process_name[1+l+1] = 0; rename_process(process_name); } #ifdef HAVE_SECCOMP static int apply_seccomp(const ExecContext *c) { uint32_t negative_action, action; scmp_filter_ctx *seccomp; Iterator i; void *id; int r; assert(c); negative_action = c->syscall_errno == 0 ? SCMP_ACT_KILL : SCMP_ACT_ERRNO(c->syscall_errno); seccomp = seccomp_init(c->syscall_whitelist ? negative_action : SCMP_ACT_ALLOW); if (!seccomp) return -ENOMEM; if (c->syscall_archs) { SET_FOREACH(id, c->syscall_archs, i) { r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1); if (r == -EEXIST) continue; if (r < 0) goto finish; } } else { r = seccomp_add_secondary_archs(seccomp); if (r < 0) goto finish; } action = c->syscall_whitelist ? SCMP_ACT_ALLOW : negative_action; SET_FOREACH(id, c->syscall_filter, i) { r = seccomp_rule_add(seccomp, action, PTR_TO_INT(id) - 1, 0); if (r < 0) goto finish; } r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); if (r < 0) goto finish; r = seccomp_load(seccomp); finish: seccomp_release(seccomp); return r; } static int apply_address_families(const ExecContext *c) { scmp_filter_ctx *seccomp; Iterator i; int r; assert(c); seccomp = seccomp_init(SCMP_ACT_ALLOW); if (!seccomp) return -ENOMEM; r = seccomp_add_secondary_archs(seccomp); if (r < 0) goto finish; if (c->address_families_whitelist) { int af, first = 0, last = 0; void *afp; /* If this is a whitelist, we first block the address * families that are out of range and then everything * that is not in the set. First, we find the lowest * and highest address family in the set. */ SET_FOREACH(afp, c->address_families, i) { af = PTR_TO_INT(afp); if (af <= 0 || af >= af_max()) continue; if (first == 0 || af < first) first = af; if (last == 0 || af > last) last = af; } assert((first == 0) == (last == 0)); if (first == 0) { /* No entries in the valid range, block everything */ r = seccomp_rule_add( seccomp, SCMP_ACT_ERRNO(EPROTONOSUPPORT), SCMP_SYS(socket), 0); if (r < 0) goto finish; } else { /* Block everything below the first entry */ r = seccomp_rule_add( seccomp, SCMP_ACT_ERRNO(EPROTONOSUPPORT), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_LT, first)); if (r < 0) goto finish; /* Block everything above the last entry */ r = seccomp_rule_add( seccomp, SCMP_ACT_ERRNO(EPROTONOSUPPORT), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_GT, last)); if (r < 0) goto finish; /* Block everything between the first and last * entry */ for (af = 1; af < af_max(); af++) { if (set_contains(c->address_families, INT_TO_PTR(af))) continue; r = seccomp_rule_add( seccomp, SCMP_ACT_ERRNO(EPROTONOSUPPORT), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_EQ, af)); if (r < 0) goto finish; } } } else { void *af; /* If this is a blacklist, then generate one rule for * each address family that are then combined in OR * checks. */ SET_FOREACH(af, c->address_families, i) { r = seccomp_rule_add( seccomp, SCMP_ACT_ERRNO(EPROTONOSUPPORT), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_EQ, PTR_TO_INT(af))); if (r < 0) goto finish; } } r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); if (r < 0) goto finish; r = seccomp_load(seccomp); finish: seccomp_release(seccomp); return r; } #endif static void do_idle_pipe_dance(int idle_pipe[4]) { assert(idle_pipe); idle_pipe[1] = safe_close(idle_pipe[1]); idle_pipe[2] = safe_close(idle_pipe[2]); if (idle_pipe[0] >= 0) { int r; r = fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC); if (idle_pipe[3] >= 0 && r == 0 /* timeout */) { ssize_t n; /* Signal systemd that we are bored and want to continue. */ n = write(idle_pipe[3], "x", 1); if (n > 0) /* Wait for systemd to react to the signal above. */ fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC); } idle_pipe[0] = safe_close(idle_pipe[0]); } idle_pipe[3] = safe_close(idle_pipe[3]); } static int build_environment( const ExecContext *c, const ExecParameters *p, unsigned n_fds, const char *home, const char *username, const char *shell, char ***ret) { _cleanup_strv_free_ char **our_env = NULL; unsigned n_env = 0; char *x; assert(c); assert(ret); our_env = new0(char*, 11); if (!our_env) return -ENOMEM; if (n_fds > 0) { _cleanup_free_ char *joined = NULL; if (asprintf(&x, "LISTEN_PID="PID_FMT, getpid()) < 0) return -ENOMEM; our_env[n_env++] = x; if (asprintf(&x, "LISTEN_FDS=%u", n_fds) < 0) return -ENOMEM; our_env[n_env++] = x; joined = strv_join(p->fd_names, ":"); if (!joined) return -ENOMEM; x = strjoin("LISTEN_FDNAMES=", joined, NULL); if (!x) return -ENOMEM; our_env[n_env++] = x; } if (p->watchdog_usec > 0) { if (asprintf(&x, "WATCHDOG_PID="PID_FMT, getpid()) < 0) return -ENOMEM; our_env[n_env++] = x; if (asprintf(&x, "WATCHDOG_USEC="USEC_FMT, p->watchdog_usec) < 0) return -ENOMEM; our_env[n_env++] = x; } if (home) { x = strappend("HOME=", home); if (!x) return -ENOMEM; our_env[n_env++] = x; } if (username) { x = strappend("LOGNAME=", username); if (!x) return -ENOMEM; our_env[n_env++] = x; x = strappend("USER=", username); if (!x) return -ENOMEM; our_env[n_env++] = x; } if (shell) { x = strappend("SHELL=", shell); if (!x) return -ENOMEM; our_env[n_env++] = x; } if (is_terminal_input(c->std_input) || c->std_output == EXEC_OUTPUT_TTY || c->std_error == EXEC_OUTPUT_TTY || c->tty_path) { x = strdup(default_term_for_tty(exec_context_tty_path(c))); if (!x) return -ENOMEM; our_env[n_env++] = x; } our_env[n_env++] = NULL; assert(n_env <= 11); *ret = our_env; our_env = NULL; return 0; } static int build_pass_environment(const ExecContext *c, char ***ret) { _cleanup_strv_free_ char **pass_env = NULL; size_t n_env = 0, n_bufsize = 0; char **i; STRV_FOREACH(i, c->pass_environment) { _cleanup_free_ char *x = NULL; char *v; v = getenv(*i); if (!v) continue; x = strjoin(*i, "=", v, NULL); if (!x) return -ENOMEM; if (!GREEDY_REALLOC(pass_env, n_bufsize, n_env + 2)) return -ENOMEM; pass_env[n_env++] = x; pass_env[n_env] = NULL; x = NULL; } *ret = pass_env; pass_env = NULL; return 0; } static bool exec_needs_mount_namespace( const ExecContext *context, const ExecParameters *params, ExecRuntime *runtime) { assert(context); assert(params); if (!strv_isempty(context->read_write_dirs) || !strv_isempty(context->read_only_dirs) || !strv_isempty(context->inaccessible_dirs)) return true; if (context->mount_flags != 0) return true; if (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir)) return true; if (params->bus_endpoint_path) return true; if (context->private_devices || context->protect_system != PROTECT_SYSTEM_NO || context->protect_home != PROTECT_HOME_NO) return true; return false; } static int close_remaining_fds( const ExecParameters *params, ExecRuntime *runtime, int socket_fd, int *fds, unsigned n_fds) { unsigned n_dont_close = 0; int dont_close[n_fds + 7]; assert(params); if (params->stdin_fd >= 0) dont_close[n_dont_close++] = params->stdin_fd; if (params->stdout_fd >= 0) dont_close[n_dont_close++] = params->stdout_fd; if (params->stderr_fd >= 0) dont_close[n_dont_close++] = params->stderr_fd; if (socket_fd >= 0) dont_close[n_dont_close++] = socket_fd; if (n_fds > 0) { memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds); n_dont_close += n_fds; } if (params->bus_endpoint_fd >= 0) dont_close[n_dont_close++] = params->bus_endpoint_fd; if (runtime) { if (runtime->netns_storage_socket[0] >= 0) dont_close[n_dont_close++] = runtime->netns_storage_socket[0]; if (runtime->netns_storage_socket[1] >= 0) dont_close[n_dont_close++] = runtime->netns_storage_socket[1]; } return close_all_fds(dont_close, n_dont_close); } static int exec_child( Unit *unit, ExecCommand *command, const ExecContext *context, const ExecParameters *params, ExecRuntime *runtime, char **argv, int socket_fd, int *fds, unsigned n_fds, char **files_env, int *exit_status) { _cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL; _cleanup_free_ char *mac_selinux_context_net = NULL; const char *username = NULL, *home = NULL, *shell = NULL, *wd; uid_t uid = UID_INVALID; gid_t gid = GID_INVALID; int i, r; bool needs_mount_namespace; assert(unit); assert(command); assert(context); assert(params); assert(exit_status); rename_process_from_path(command->path); /* We reset exactly these signals, since they are the * only ones we set to SIG_IGN in the main daemon. All * others we leave untouched because we set them to * SIG_DFL or a valid handler initially, both of which * will be demoted to SIG_DFL. */ (void) default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE, -1); if (context->ignore_sigpipe) (void) ignore_signals(SIGPIPE, -1); r = reset_signal_mask(); if (r < 0) { *exit_status = EXIT_SIGNAL_MASK; return r; } if (params->idle_pipe) do_idle_pipe_dance(params->idle_pipe); /* Close sockets very early to make sure we don't * block init reexecution because it cannot bind its * sockets */ log_forget_fds(); r = close_remaining_fds(params, runtime, socket_fd, fds, n_fds); if (r < 0) { *exit_status = EXIT_FDS; return r; } if (!context->same_pgrp) if (setsid() < 0) { *exit_status = EXIT_SETSID; return -errno; } exec_context_tty_reset(context, params); if (params->confirm_spawn) { char response; r = ask_for_confirmation(&response, argv); if (r == -ETIMEDOUT) write_confirm_message("Confirmation question timed out, assuming positive response.\n"); else if (r < 0) write_confirm_message("Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-r)); else if (response == 's') { write_confirm_message("Skipping execution.\n"); *exit_status = EXIT_CONFIRM; return -ECANCELED; } else if (response == 'n') { write_confirm_message("Failing execution.\n"); *exit_status = 0; return 0; } } if (context->user) { username = context->user; r = get_user_creds(&username, &uid, &gid, &home, &shell); if (r < 0) { *exit_status = EXIT_USER; return r; } } if (context->group) { const char *g = context->group; r = get_group_creds(&g, &gid); if (r < 0) { *exit_status = EXIT_GROUP; return r; } } /* If a socket is connected to STDIN/STDOUT/STDERR, we * must sure to drop O_NONBLOCK */ if (socket_fd >= 0) (void) fd_nonblock(socket_fd, false); r = setup_input(context, params, socket_fd); if (r < 0) { *exit_status = EXIT_STDIN; return r; } r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, basename(command->path), uid, gid); if (r < 0) { *exit_status = EXIT_STDOUT; return r; } r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, basename(command->path), uid, gid); if (r < 0) { *exit_status = EXIT_STDERR; return r; } if (params->cgroup_path) { r = cg_attach_everywhere(params->cgroup_supported, params->cgroup_path, 0, NULL, NULL); if (r < 0) { *exit_status = EXIT_CGROUP; return r; } } if (context->oom_score_adjust_set) { char t[DECIMAL_STR_MAX(context->oom_score_adjust)]; /* When we can't make this change due to EPERM, then * let's silently skip over it. User namespaces * prohibit write access to this file, and we * shouldn't trip up over that. */ sprintf(t, "%i", context->oom_score_adjust); r = write_string_file("/proc/self/oom_score_adj", t, 0); if (r == -EPERM || r == -EACCES) { log_open(); log_unit_debug_errno(unit, r, "Failed to adjust OOM setting, assuming containerized execution, ignoring: %m"); log_close(); } else if (r < 0) { *exit_status = EXIT_OOM_ADJUST; return -errno; } } if (context->nice_set) if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) { *exit_status = EXIT_NICE; return -errno; } if (context->cpu_sched_set) { struct sched_param param = { .sched_priority = context->cpu_sched_priority, }; r = sched_setscheduler(0, context->cpu_sched_policy | (context->cpu_sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0), ¶m); if (r < 0) { *exit_status = EXIT_SETSCHEDULER; return -errno; } } if (context->cpuset) if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) { *exit_status = EXIT_CPUAFFINITY; return -errno; } if (context->ioprio_set) if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) { *exit_status = EXIT_IOPRIO; return -errno; } if (context->timer_slack_nsec != NSEC_INFINITY) if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) { *exit_status = EXIT_TIMERSLACK; return -errno; } if (context->personality != PERSONALITY_INVALID) if (personality(context->personality) < 0) { *exit_status = EXIT_PERSONALITY; return -errno; } if (context->utmp_id) utmp_put_init_process(context->utmp_id, getpid(), getsid(0), context->tty_path, context->utmp_mode == EXEC_UTMP_INIT ? INIT_PROCESS : context->utmp_mode == EXEC_UTMP_LOGIN ? LOGIN_PROCESS : USER_PROCESS, username ? "root" : context->user); if (context->user && is_terminal_input(context->std_input)) { r = chown_terminal(STDIN_FILENO, uid); if (r < 0) { *exit_status = EXIT_STDIN; return r; } } if (params->bus_endpoint_fd >= 0 && context->bus_endpoint) { uid_t ep_uid = (uid == UID_INVALID) ? 0 : uid; r = bus_kernel_set_endpoint_policy(params->bus_endpoint_fd, ep_uid, context->bus_endpoint); if (r < 0) { *exit_status = EXIT_BUS_ENDPOINT; return r; } } /* If delegation is enabled we'll pass ownership of the cgroup * (but only in systemd's own controller hierarchy!) to the * user of the new process. */ if (params->cgroup_path && context->user && params->cgroup_delegate) { r = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0644, uid, gid); if (r < 0) { *exit_status = EXIT_CGROUP; return r; } r = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0755, uid, gid); if (r < 0) { *exit_status = EXIT_CGROUP; return r; } } if (!strv_isempty(context->runtime_directory) && params->runtime_prefix) { char **rt; STRV_FOREACH(rt, context->runtime_directory) { _cleanup_free_ char *p; p = strjoin(params->runtime_prefix, "/", *rt, NULL); if (!p) { *exit_status = EXIT_RUNTIME_DIRECTORY; return -ENOMEM; } r = mkdir_p_label(p, context->runtime_directory_mode); if (r < 0) { *exit_status = EXIT_RUNTIME_DIRECTORY; return r; } r = chmod_and_chown(p, context->runtime_directory_mode, uid, gid); if (r < 0) { *exit_status = EXIT_RUNTIME_DIRECTORY; return r; } } } umask(context->umask); if (params->apply_permissions) { r = enforce_groups(context, username, gid); if (r < 0) { *exit_status = EXIT_GROUP; return r; } #ifdef HAVE_SMACK if (context->smack_process_label) { r = mac_smack_apply_pid(0, context->smack_process_label); if (r < 0) { *exit_status = EXIT_SMACK_PROCESS_LABEL; return r; } } #ifdef SMACK_DEFAULT_PROCESS_LABEL else { _cleanup_free_ char *exec_label = NULL; r = mac_smack_read(command->path, SMACK_ATTR_EXEC, &exec_label); if (r < 0 && r != -ENODATA && r != -EOPNOTSUPP) { *exit_status = EXIT_SMACK_PROCESS_LABEL; return r; } r = mac_smack_apply_pid(0, exec_label ? : SMACK_DEFAULT_PROCESS_LABEL); if (r < 0) { *exit_status = EXIT_SMACK_PROCESS_LABEL; return r; } } #endif #endif #ifdef HAVE_PAM if (context->pam_name && username) { r = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds); if (r < 0) { *exit_status = EXIT_PAM; return r; } } #endif } if (context->private_network && runtime && runtime->netns_storage_socket[0] >= 0) { r = setup_netns(runtime->netns_storage_socket); if (r < 0) { *exit_status = EXIT_NETWORK; return r; } } needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime); if (needs_mount_namespace) { char *tmp = NULL, *var = NULL; /* The runtime struct only contains the parent * of the private /tmp, which is * non-accessible to world users. Inside of it * there's a /tmp that is sticky, and that's * the one we want to use here. */ if (context->private_tmp && runtime) { if (runtime->tmp_dir) tmp = strjoina(runtime->tmp_dir, "/tmp"); if (runtime->var_tmp_dir) var = strjoina(runtime->var_tmp_dir, "/tmp"); } r = setup_namespace( params->apply_chroot ? context->root_directory : NULL, context->read_write_dirs, context->read_only_dirs, context->inaccessible_dirs, tmp, var, params->bus_endpoint_path, context->private_devices, context->protect_home, context->protect_system, context->mount_flags); /* If we couldn't set up the namespace this is * probably due to a missing capability. In this case, * silently proceeed. */ if (r == -EPERM || r == -EACCES) { log_open(); log_unit_debug_errno(unit, r, "Failed to set up namespace, assuming containerized execution, ignoring: %m"); log_close(); } else if (r < 0) { *exit_status = EXIT_NAMESPACE; return r; } } if (context->working_directory_home) wd = home; else if (context->working_directory) wd = context->working_directory; else wd = "/"; if (params->apply_chroot) { if (!needs_mount_namespace && context->root_directory) if (chroot(context->root_directory) < 0) { *exit_status = EXIT_CHROOT; return -errno; } if (chdir(wd) < 0 && !context->working_directory_missing_ok) { *exit_status = EXIT_CHDIR; return -errno; } } else { const char *d; d = strjoina(strempty(context->root_directory), "/", strempty(wd)); if (chdir(d) < 0 && !context->working_directory_missing_ok) { *exit_status = EXIT_CHDIR; return -errno; } } #ifdef HAVE_SELINUX if (params->apply_permissions && mac_selinux_use() && params->selinux_context_net && socket_fd >= 0) { r = mac_selinux_get_child_mls_label(socket_fd, command->path, context->selinux_context, &mac_selinux_context_net); if (r < 0) { *exit_status = EXIT_SELINUX_CONTEXT; return r; } } #endif /* We repeat the fd closing here, to make sure that * nothing is leaked from the PAM modules. Note that * we are more aggressive this time since socket_fd * and the netns fds we don't need anymore. The custom * endpoint fd was needed to upload the policy and can * now be closed as well. */ r = close_all_fds(fds, n_fds); if (r >= 0) r = shift_fds(fds, n_fds); if (r >= 0) r = flags_fds(fds, n_fds, context->non_blocking); if (r < 0) { *exit_status = EXIT_FDS; return r; } if (params->apply_permissions) { int secure_bits = context->secure_bits; for (i = 0; i < _RLIMIT_MAX; i++) { if (!context->rlimit[i]) continue; if (setrlimit_closest(i, context->rlimit[i]) < 0) { *exit_status = EXIT_LIMITS; return -errno; } } if (!cap_test_all(context->capability_bounding_set)) { r = capability_bounding_set_drop(context->capability_bounding_set, false); if (r < 0) { *exit_status = EXIT_CAPABILITIES; return r; } } /* This is done before enforce_user, but ambient set * does not survive over setresuid() if keep_caps is not set. */ if (context->capability_ambient_set != 0) { r = capability_ambient_set_apply(context->capability_ambient_set, true); if (r < 0) { *exit_status = EXIT_CAPABILITIES; return r; } if (context->capabilities) { /* The capabilities in ambient set need to be also in the inherited * set. If they aren't, trying to get them will fail. Add the ambient * set inherited capabilities to the capability set in the context. * This is needed because if capabilities are set (using "Capabilities=" * keyword), they will override whatever we set now. */ r = capability_update_inherited_set(context->capabilities, context->capability_ambient_set); if (r < 0) { *exit_status = EXIT_CAPABILITIES; return r; } } } if (context->user) { r = enforce_user(context, uid); if (r < 0) { *exit_status = EXIT_USER; return r; } if (context->capability_ambient_set != 0) { /* Fix the ambient capabilities after user change. */ r = capability_ambient_set_apply(context->capability_ambient_set, false); if (r < 0) { *exit_status = EXIT_CAPABILITIES; return r; } /* If we were asked to change user and ambient capabilities * were requested, we had to add keep-caps to the securebits * so that we would maintain the inherited capability set * through the setresuid(). Make sure that the bit is added * also to the context secure_bits so that we don't try to * drop the bit away next. */ secure_bits |= 1<capabilities) if (cap_set_proc(context->capabilities) < 0) { *exit_status = EXIT_CAPABILITIES; return -errno; } if (context->no_new_privileges) if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { *exit_status = EXIT_NO_NEW_PRIVILEGES; return -errno; } #ifdef HAVE_SECCOMP if (context->address_families_whitelist || !set_isempty(context->address_families)) { r = apply_address_families(context); if (r < 0) { *exit_status = EXIT_ADDRESS_FAMILIES; return r; } } if (context->syscall_whitelist || !set_isempty(context->syscall_filter) || !set_isempty(context->syscall_archs)) { r = apply_seccomp(context); if (r < 0) { *exit_status = EXIT_SECCOMP; return r; } } #endif #ifdef HAVE_SELINUX if (mac_selinux_use()) { char *exec_context = mac_selinux_context_net ?: context->selinux_context; if (exec_context) { r = setexeccon(exec_context); if (r < 0) { *exit_status = EXIT_SELINUX_CONTEXT; return r; } } } #endif #ifdef HAVE_APPARMOR if (context->apparmor_profile && mac_apparmor_use()) { r = aa_change_onexec(context->apparmor_profile); if (r < 0 && !context->apparmor_profile_ignore) { *exit_status = EXIT_APPARMOR_PROFILE; return -errno; } } #endif } r = build_environment(context, params, n_fds, home, username, shell, &our_env); if (r < 0) { *exit_status = EXIT_MEMORY; return r; } r = build_pass_environment(context, &pass_env); if (r < 0) { *exit_status = EXIT_MEMORY; return r; } final_env = strv_env_merge(6, params->environment, our_env, pass_env, context->environment, files_env, pam_env, NULL); if (!final_env) { *exit_status = EXIT_MEMORY; return -ENOMEM; } final_argv = replace_env_argv(argv, final_env); if (!final_argv) { *exit_status = EXIT_MEMORY; return -ENOMEM; } final_env = strv_env_clean(final_env); if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) { _cleanup_free_ char *line; line = exec_command_line(final_argv); if (line) { log_open(); log_struct(LOG_DEBUG, LOG_UNIT_ID(unit), "EXECUTABLE=%s", command->path, LOG_UNIT_MESSAGE(unit, "Executing: %s", line), NULL); log_close(); } } execve(command->path, final_argv, final_env); *exit_status = EXIT_EXEC; return -errno; } int exec_spawn(Unit *unit, ExecCommand *command, const ExecContext *context, const ExecParameters *params, ExecRuntime *runtime, pid_t *ret) { _cleanup_strv_free_ char **files_env = NULL; int *fds = NULL; unsigned n_fds = 0; _cleanup_free_ char *line = NULL; int socket_fd, r; char **argv; pid_t pid; assert(unit); assert(command); assert(context); assert(ret); assert(params); assert(params->fds || params->n_fds <= 0); if (context->std_input == EXEC_INPUT_SOCKET || context->std_output == EXEC_OUTPUT_SOCKET || context->std_error == EXEC_OUTPUT_SOCKET) { if (params->n_fds != 1) { log_unit_error(unit, "Got more than one socket."); return -EINVAL; } socket_fd = params->fds[0]; } else { socket_fd = -1; fds = params->fds; n_fds = params->n_fds; } r = exec_context_load_environment(unit, context, &files_env); if (r < 0) return log_unit_error_errno(unit, r, "Failed to load environment files: %m"); argv = params->argv ?: command->argv; line = exec_command_line(argv); if (!line) return log_oom(); log_struct(LOG_DEBUG, LOG_UNIT_ID(unit), LOG_UNIT_MESSAGE(unit, "About to execute: %s", line), "EXECUTABLE=%s", command->path, NULL); pid = fork(); if (pid < 0) return log_unit_error_errno(unit, errno, "Failed to fork: %m"); if (pid == 0) { int exit_status; r = exec_child(unit, command, context, params, runtime, argv, socket_fd, fds, n_fds, files_env, &exit_status); if (r < 0) { log_open(); log_struct_errno(LOG_ERR, r, LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED), LOG_UNIT_ID(unit), LOG_UNIT_MESSAGE(unit, "Failed at step %s spawning %s: %m", exit_status_to_string(exit_status, EXIT_STATUS_SYSTEMD), command->path), "EXECUTABLE=%s", command->path, NULL); } _exit(exit_status); } log_unit_debug(unit, "Forked %s as "PID_FMT, command->path, pid); /* We add the new process to the cgroup both in the child (so * that we can be sure that no user code is ever executed * outside of the cgroup) and in the parent (so that we can be * sure that when we kill the cgroup the process will be * killed too). */ if (params->cgroup_path) (void) cg_attach(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, pid); exec_status_start(&command->exec_status, pid); *ret = pid; return 0; } void exec_context_init(ExecContext *c) { assert(c); c->umask = 0022; c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0); c->cpu_sched_policy = SCHED_OTHER; c->syslog_priority = LOG_DAEMON|LOG_INFO; c->syslog_level_prefix = true; c->ignore_sigpipe = true; c->timer_slack_nsec = NSEC_INFINITY; c->personality = PERSONALITY_INVALID; c->runtime_directory_mode = 0755; c->capability_bounding_set = CAP_ALL; } void exec_context_done(ExecContext *c) { unsigned l; assert(c); c->environment = strv_free(c->environment); c->environment_files = strv_free(c->environment_files); c->pass_environment = strv_free(c->pass_environment); for (l = 0; l < ELEMENTSOF(c->rlimit); l++) c->rlimit[l] = mfree(c->rlimit[l]); c->working_directory = mfree(c->working_directory); c->root_directory = mfree(c->root_directory); c->tty_path = mfree(c->tty_path); c->syslog_identifier = mfree(c->syslog_identifier); c->user = mfree(c->user); c->group = mfree(c->group); c->supplementary_groups = strv_free(c->supplementary_groups); c->pam_name = mfree(c->pam_name); if (c->capabilities) { cap_free(c->capabilities); c->capabilities = NULL; } c->read_only_dirs = strv_free(c->read_only_dirs); c->read_write_dirs = strv_free(c->read_write_dirs); c->inaccessible_dirs = strv_free(c->inaccessible_dirs); if (c->cpuset) CPU_FREE(c->cpuset); c->utmp_id = mfree(c->utmp_id); c->selinux_context = mfree(c->selinux_context); c->apparmor_profile = mfree(c->apparmor_profile); c->syscall_filter = set_free(c->syscall_filter); c->syscall_archs = set_free(c->syscall_archs); c->address_families = set_free(c->address_families); c->runtime_directory = strv_free(c->runtime_directory); bus_endpoint_free(c->bus_endpoint); c->bus_endpoint = NULL; } int exec_context_destroy_runtime_directory(ExecContext *c, const char *runtime_prefix) { char **i; assert(c); if (!runtime_prefix) return 0; STRV_FOREACH(i, c->runtime_directory) { _cleanup_free_ char *p; p = strjoin(runtime_prefix, "/", *i, NULL); if (!p) return -ENOMEM; /* We execute this synchronously, since we need to be * sure this is gone when we start the service * next. */ (void) rm_rf(p, REMOVE_ROOT); } return 0; } void exec_command_done(ExecCommand *c) { assert(c); c->path = mfree(c->path); c->argv = strv_free(c->argv); } void exec_command_done_array(ExecCommand *c, unsigned n) { unsigned i; for (i = 0; i < n; i++) exec_command_done(c+i); } ExecCommand* exec_command_free_list(ExecCommand *c) { ExecCommand *i; while ((i = c)) { LIST_REMOVE(command, c, i); exec_command_done(i); free(i); } return NULL; } void exec_command_free_array(ExecCommand **c, unsigned n) { unsigned i; for (i = 0; i < n; i++) c[i] = exec_command_free_list(c[i]); } typedef struct InvalidEnvInfo { Unit *unit; const char *path; } InvalidEnvInfo; static void invalid_env(const char *p, void *userdata) { InvalidEnvInfo *info = userdata; log_unit_error(info->unit, "Ignoring invalid environment assignment '%s': %s", p, info->path); } int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) { char **i, **r = NULL; assert(c); assert(l); STRV_FOREACH(i, c->environment_files) { char *fn; int k; bool ignore = false; char **p; _cleanup_globfree_ glob_t pglob = {}; int count, n; fn = *i; if (fn[0] == '-') { ignore = true; fn ++; } if (!path_is_absolute(fn)) { if (ignore) continue; strv_free(r); return -EINVAL; } /* Filename supports globbing, take all matching files */ errno = 0; if (glob(fn, 0, NULL, &pglob) != 0) { if (ignore) continue; strv_free(r); return errno > 0 ? -errno : -EINVAL; } count = pglob.gl_pathc; if (count == 0) { if (ignore) continue; strv_free(r); return -EINVAL; } for (n = 0; n < count; n++) { k = load_env_file(NULL, pglob.gl_pathv[n], NULL, &p); if (k < 0) { if (ignore) continue; strv_free(r); return k; } /* Log invalid environment variables with filename */ if (p) { InvalidEnvInfo info = { .unit = unit, .path = pglob.gl_pathv[n] }; p = strv_env_clean_with_callback(p, invalid_env, &info); } if (r == NULL) r = p; else { char **m; m = strv_env_merge(2, r, p); strv_free(r); strv_free(p); if (!m) return -ENOMEM; r = m; } } } *l = r; return 0; } static bool tty_may_match_dev_console(const char *tty) { _cleanup_free_ char *active = NULL; char *console; if (!tty) return true; if (startswith(tty, "/dev/")) tty += 5; /* trivial identity? */ if (streq(tty, "console")) return true; console = resolve_dev_console(&active); /* if we could not resolve, assume it may */ if (!console) return true; /* "tty0" means the active VC, so it may be the same sometimes */ return streq(console, tty) || (streq(console, "tty0") && tty_is_vc(tty)); } bool exec_context_may_touch_console(ExecContext *ec) { return (ec->tty_reset || ec->tty_vhangup || ec->tty_vt_disallocate || is_terminal_input(ec->std_input) || is_terminal_output(ec->std_output) || is_terminal_output(ec->std_error)) && tty_may_match_dev_console(exec_context_tty_path(ec)); } static void strv_fprintf(FILE *f, char **l) { char **g; assert(f); STRV_FOREACH(g, l) fprintf(f, " %s", *g); } void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { char **e, **d; unsigned i; assert(c); assert(f); prefix = strempty(prefix); fprintf(f, "%sUMask: %04o\n" "%sWorkingDirectory: %s\n" "%sRootDirectory: %s\n" "%sNonBlocking: %s\n" "%sPrivateTmp: %s\n" "%sPrivateNetwork: %s\n" "%sPrivateDevices: %s\n" "%sProtectHome: %s\n" "%sProtectSystem: %s\n" "%sIgnoreSIGPIPE: %s\n", prefix, c->umask, prefix, c->working_directory ? c->working_directory : "/", prefix, c->root_directory ? c->root_directory : "/", prefix, yes_no(c->non_blocking), prefix, yes_no(c->private_tmp), prefix, yes_no(c->private_network), prefix, yes_no(c->private_devices), prefix, protect_home_to_string(c->protect_home), prefix, protect_system_to_string(c->protect_system), prefix, yes_no(c->ignore_sigpipe)); STRV_FOREACH(e, c->environment) fprintf(f, "%sEnvironment: %s\n", prefix, *e); STRV_FOREACH(e, c->environment_files) fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e); STRV_FOREACH(e, c->pass_environment) fprintf(f, "%sPassEnvironment: %s\n", prefix, *e); fprintf(f, "%sRuntimeDirectoryMode: %04o\n", prefix, c->runtime_directory_mode); STRV_FOREACH(d, c->runtime_directory) fprintf(f, "%sRuntimeDirectory: %s\n", prefix, *d); if (c->nice_set) fprintf(f, "%sNice: %i\n", prefix, c->nice); if (c->oom_score_adjust_set) fprintf(f, "%sOOMScoreAdjust: %i\n", prefix, c->oom_score_adjust); for (i = 0; i < RLIM_NLIMITS; i++) if (c->rlimit[i]) { fprintf(f, "%s%s: " RLIM_FMT "\n", prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max); fprintf(f, "%s%sSoft: " RLIM_FMT "\n", prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur); } if (c->ioprio_set) { _cleanup_free_ char *class_str = NULL; ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c->ioprio), &class_str); fprintf(f, "%sIOSchedulingClass: %s\n" "%sIOPriority: %i\n", prefix, strna(class_str), prefix, (int) IOPRIO_PRIO_DATA(c->ioprio)); } if (c->cpu_sched_set) { _cleanup_free_ char *policy_str = NULL; sched_policy_to_string_alloc(c->cpu_sched_policy, &policy_str); fprintf(f, "%sCPUSchedulingPolicy: %s\n" "%sCPUSchedulingPriority: %i\n" "%sCPUSchedulingResetOnFork: %s\n", prefix, strna(policy_str), prefix, c->cpu_sched_priority, prefix, yes_no(c->cpu_sched_reset_on_fork)); } if (c->cpuset) { fprintf(f, "%sCPUAffinity:", prefix); for (i = 0; i < c->cpuset_ncpus; i++) if (CPU_ISSET_S(i, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset)) fprintf(f, " %u", i); fputs("\n", f); } if (c->timer_slack_nsec != NSEC_INFINITY) fprintf(f, "%sTimerSlackNSec: "NSEC_FMT "\n", prefix, c->timer_slack_nsec); fprintf(f, "%sStandardInput: %s\n" "%sStandardOutput: %s\n" "%sStandardError: %s\n", prefix, exec_input_to_string(c->std_input), prefix, exec_output_to_string(c->std_output), prefix, exec_output_to_string(c->std_error)); if (c->tty_path) fprintf(f, "%sTTYPath: %s\n" "%sTTYReset: %s\n" "%sTTYVHangup: %s\n" "%sTTYVTDisallocate: %s\n", prefix, c->tty_path, prefix, yes_no(c->tty_reset), prefix, yes_no(c->tty_vhangup), prefix, yes_no(c->tty_vt_disallocate)); if (c->std_output == EXEC_OUTPUT_SYSLOG || c->std_output == EXEC_OUTPUT_KMSG || c->std_output == EXEC_OUTPUT_JOURNAL || c->std_output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_KMSG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_JOURNAL_AND_CONSOLE || c->std_error == EXEC_OUTPUT_SYSLOG || c->std_error == EXEC_OUTPUT_KMSG || c->std_error == EXEC_OUTPUT_JOURNAL || c->std_error == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_KMSG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_JOURNAL_AND_CONSOLE) { _cleanup_free_ char *fac_str = NULL, *lvl_str = NULL; log_facility_unshifted_to_string_alloc(c->syslog_priority >> 3, &fac_str); log_level_to_string_alloc(LOG_PRI(c->syslog_priority), &lvl_str); fprintf(f, "%sSyslogFacility: %s\n" "%sSyslogLevel: %s\n", prefix, strna(fac_str), prefix, strna(lvl_str)); } if (c->capabilities) { _cleanup_cap_free_charp_ char *t; t = cap_to_text(c->capabilities, NULL); if (t) fprintf(f, "%sCapabilities: %s\n", prefix, t); } if (c->secure_bits) fprintf(f, "%sSecure Bits:%s%s%s%s%s%s\n", prefix, (c->secure_bits & 1<secure_bits & 1<secure_bits & 1<secure_bits & 1<secure_bits & 1<secure_bits & 1<capability_bounding_set != CAP_ALL) { unsigned long l; fprintf(f, "%sCapabilityBoundingSet:", prefix); for (l = 0; l <= cap_last_cap(); l++) if (c->capability_bounding_set & (UINT64_C(1) << l)) fprintf(f, " %s", strna(capability_to_name(l))); fputs("\n", f); } if (c->capability_ambient_set != 0) { unsigned long l; fprintf(f, "%sAmbientCapabilities:", prefix); for (l = 0; l <= cap_last_cap(); l++) if (c->capability_ambient_set & (UINT64_C(1) << l)) fprintf(f, " %s", strna(capability_to_name(l))); fputs("\n", f); } if (c->user) fprintf(f, "%sUser: %s\n", prefix, c->user); if (c->group) fprintf(f, "%sGroup: %s\n", prefix, c->group); if (strv_length(c->supplementary_groups) > 0) { fprintf(f, "%sSupplementaryGroups:", prefix); strv_fprintf(f, c->supplementary_groups); fputs("\n", f); } if (c->pam_name) fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name); if (strv_length(c->read_write_dirs) > 0) { fprintf(f, "%sReadWriteDirs:", prefix); strv_fprintf(f, c->read_write_dirs); fputs("\n", f); } if (strv_length(c->read_only_dirs) > 0) { fprintf(f, "%sReadOnlyDirs:", prefix); strv_fprintf(f, c->read_only_dirs); fputs("\n", f); } if (strv_length(c->inaccessible_dirs) > 0) { fprintf(f, "%sInaccessibleDirs:", prefix); strv_fprintf(f, c->inaccessible_dirs); fputs("\n", f); } if (c->utmp_id) fprintf(f, "%sUtmpIdentifier: %s\n", prefix, c->utmp_id); if (c->selinux_context) fprintf(f, "%sSELinuxContext: %s%s\n", prefix, c->selinux_context_ignore ? "-" : "", c->selinux_context); if (c->personality != PERSONALITY_INVALID) fprintf(f, "%sPersonality: %s\n", prefix, strna(personality_to_string(c->personality))); if (c->syscall_filter) { #ifdef HAVE_SECCOMP Iterator j; void *id; bool first = true; #endif fprintf(f, "%sSystemCallFilter: ", prefix); if (!c->syscall_whitelist) fputc('~', f); #ifdef HAVE_SECCOMP SET_FOREACH(id, c->syscall_filter, j) { _cleanup_free_ char *name = NULL; if (first) first = false; else fputc(' ', f); name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1); fputs(strna(name), f); } #endif fputc('\n', f); } if (c->syscall_archs) { #ifdef HAVE_SECCOMP Iterator j; void *id; #endif fprintf(f, "%sSystemCallArchitectures:", prefix); #ifdef HAVE_SECCOMP SET_FOREACH(id, c->syscall_archs, j) fprintf(f, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id) - 1))); #endif fputc('\n', f); } if (c->syscall_errno > 0) fprintf(f, "%sSystemCallErrorNumber: %s\n", prefix, strna(errno_to_name(c->syscall_errno))); if (c->apparmor_profile) fprintf(f, "%sAppArmorProfile: %s%s\n", prefix, c->apparmor_profile_ignore ? "-" : "", c->apparmor_profile); } bool exec_context_maintains_privileges(ExecContext *c) { assert(c); /* Returns true if the process forked off would run run under * an unchanged UID or as root. */ if (!c->user) return true; if (streq(c->user, "root") || streq(c->user, "0")) return true; return false; } void exec_status_start(ExecStatus *s, pid_t pid) { assert(s); zero(*s); s->pid = pid; dual_timestamp_get(&s->start_timestamp); } void exec_status_exit(ExecStatus *s, ExecContext *context, pid_t pid, int code, int status) { assert(s); if (s->pid && s->pid != pid) zero(*s); s->pid = pid; dual_timestamp_get(&s->exit_timestamp); s->code = code; s->status = status; if (context) { if (context->utmp_id) utmp_put_dead_process(context->utmp_id, pid, code, status); exec_context_tty_reset(context, NULL); } } void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) { char buf[FORMAT_TIMESTAMP_MAX]; assert(s); assert(f); if (s->pid <= 0) return; prefix = strempty(prefix); fprintf(f, "%sPID: "PID_FMT"\n", prefix, s->pid); if (s->start_timestamp.realtime > 0) fprintf(f, "%sStart Timestamp: %s\n", prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp.realtime)); if (s->exit_timestamp.realtime > 0) fprintf(f, "%sExit Timestamp: %s\n" "%sExit Code: %s\n" "%sExit Status: %i\n", prefix, format_timestamp(buf, sizeof(buf), s->exit_timestamp.realtime), prefix, sigchld_code_to_string(s->code), prefix, s->status); } char *exec_command_line(char **argv) { size_t k; char *n, *p, **a; bool first = true; assert(argv); k = 1; STRV_FOREACH(a, argv) k += strlen(*a)+3; if (!(n = new(char, k))) return NULL; p = n; STRV_FOREACH(a, argv) { if (!first) *(p++) = ' '; else first = false; if (strpbrk(*a, WHITESPACE)) { *(p++) = '\''; p = stpcpy(p, *a); *(p++) = '\''; } else p = stpcpy(p, *a); } *p = 0; /* FIXME: this doesn't really handle arguments that have * spaces and ticks in them */ return n; } void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) { _cleanup_free_ char *cmd = NULL; const char *prefix2; assert(c); assert(f); prefix = strempty(prefix); prefix2 = strjoina(prefix, "\t"); cmd = exec_command_line(c->argv); fprintf(f, "%sCommand Line: %s\n", prefix, cmd ? cmd : strerror(ENOMEM)); exec_status_dump(&c->exec_status, f, prefix2); } void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) { assert(f); prefix = strempty(prefix); LIST_FOREACH(command, c, c) exec_command_dump(c, f, prefix); } void exec_command_append_list(ExecCommand **l, ExecCommand *e) { ExecCommand *end; assert(l); assert(e); if (*l) { /* It's kind of important, that we keep the order here */ LIST_FIND_TAIL(command, *l, end); LIST_INSERT_AFTER(command, *l, end, e); } else *l = e; } int exec_command_set(ExecCommand *c, const char *path, ...) { va_list ap; char **l, *p; assert(c); assert(path); va_start(ap, path); l = strv_new_ap(path, ap); va_end(ap); if (!l) return -ENOMEM; p = strdup(path); if (!p) { strv_free(l); return -ENOMEM; } free(c->path); c->path = p; strv_free(c->argv); c->argv = l; return 0; } int exec_command_append(ExecCommand *c, const char *path, ...) { _cleanup_strv_free_ char **l = NULL; va_list ap; int r; assert(c); assert(path); va_start(ap, path); l = strv_new_ap(path, ap); va_end(ap); if (!l) return -ENOMEM; r = strv_extend_strv(&c->argv, l, false); if (r < 0) return r; return 0; } static int exec_runtime_allocate(ExecRuntime **rt) { if (*rt) return 0; *rt = new0(ExecRuntime, 1); if (!*rt) return -ENOMEM; (*rt)->n_ref = 1; (*rt)->netns_storage_socket[0] = (*rt)->netns_storage_socket[1] = -1; return 0; } int exec_runtime_make(ExecRuntime **rt, ExecContext *c, const char *id) { int r; assert(rt); assert(c); assert(id); if (*rt) return 1; if (!c->private_network && !c->private_tmp) return 0; r = exec_runtime_allocate(rt); if (r < 0) return r; if (c->private_network && (*rt)->netns_storage_socket[0] < 0) { if (socketpair(AF_UNIX, SOCK_DGRAM, 0, (*rt)->netns_storage_socket) < 0) return -errno; } if (c->private_tmp && !(*rt)->tmp_dir) { r = setup_tmp_dirs(id, &(*rt)->tmp_dir, &(*rt)->var_tmp_dir); if (r < 0) return r; } return 1; } ExecRuntime *exec_runtime_ref(ExecRuntime *r) { assert(r); assert(r->n_ref > 0); r->n_ref++; return r; } ExecRuntime *exec_runtime_unref(ExecRuntime *r) { if (!r) return NULL; assert(r->n_ref > 0); r->n_ref--; if (r->n_ref > 0) return NULL; free(r->tmp_dir); free(r->var_tmp_dir); safe_close_pair(r->netns_storage_socket); free(r); return NULL; } int exec_runtime_serialize(Unit *u, ExecRuntime *rt, FILE *f, FDSet *fds) { assert(u); assert(f); assert(fds); if (!rt) return 0; if (rt->tmp_dir) unit_serialize_item(u, f, "tmp-dir", rt->tmp_dir); if (rt->var_tmp_dir) unit_serialize_item(u, f, "var-tmp-dir", rt->var_tmp_dir); if (rt->netns_storage_socket[0] >= 0) { int copy; copy = fdset_put_dup(fds, rt->netns_storage_socket[0]); if (copy < 0) return copy; unit_serialize_item_format(u, f, "netns-socket-0", "%i", copy); } if (rt->netns_storage_socket[1] >= 0) { int copy; copy = fdset_put_dup(fds, rt->netns_storage_socket[1]); if (copy < 0) return copy; unit_serialize_item_format(u, f, "netns-socket-1", "%i", copy); } return 0; } int exec_runtime_deserialize_item(Unit *u, ExecRuntime **rt, const char *key, const char *value, FDSet *fds) { int r; assert(rt); assert(key); assert(value); if (streq(key, "tmp-dir")) { char *copy; r = exec_runtime_allocate(rt); if (r < 0) return log_oom(); copy = strdup(value); if (!copy) return log_oom(); free((*rt)->tmp_dir); (*rt)->tmp_dir = copy; } else if (streq(key, "var-tmp-dir")) { char *copy; r = exec_runtime_allocate(rt); if (r < 0) return log_oom(); copy = strdup(value); if (!copy) return log_oom(); free((*rt)->var_tmp_dir); (*rt)->var_tmp_dir = copy; } else if (streq(key, "netns-socket-0")) { int fd; r = exec_runtime_allocate(rt); if (r < 0) return log_oom(); if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse netns socket value: %s", value); else { safe_close((*rt)->netns_storage_socket[0]); (*rt)->netns_storage_socket[0] = fdset_remove(fds, fd); } } else if (streq(key, "netns-socket-1")) { int fd; r = exec_runtime_allocate(rt); if (r < 0) return log_oom(); if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse netns socket value: %s", value); else { safe_close((*rt)->netns_storage_socket[1]); (*rt)->netns_storage_socket[1] = fdset_remove(fds, fd); } } else return 0; return 1; } static void *remove_tmpdir_thread(void *p) { _cleanup_free_ char *path = p; (void) rm_rf(path, REMOVE_ROOT|REMOVE_PHYSICAL); return NULL; } void exec_runtime_destroy(ExecRuntime *rt) { int r; if (!rt) return; /* If there are multiple users of this, let's leave the stuff around */ if (rt->n_ref > 1) return; if (rt->tmp_dir) { log_debug("Spawning thread to nuke %s", rt->tmp_dir); r = asynchronous_job(remove_tmpdir_thread, rt->tmp_dir); if (r < 0) { log_warning_errno(r, "Failed to nuke %s: %m", rt->tmp_dir); free(rt->tmp_dir); } rt->tmp_dir = NULL; } if (rt->var_tmp_dir) { log_debug("Spawning thread to nuke %s", rt->var_tmp_dir); r = asynchronous_job(remove_tmpdir_thread, rt->var_tmp_dir); if (r < 0) { log_warning_errno(r, "Failed to nuke %s: %m", rt->var_tmp_dir); free(rt->var_tmp_dir); } rt->var_tmp_dir = NULL; } safe_close_pair(rt->netns_storage_socket); } static const char* const exec_input_table[_EXEC_INPUT_MAX] = { [EXEC_INPUT_NULL] = "null", [EXEC_INPUT_TTY] = "tty", [EXEC_INPUT_TTY_FORCE] = "tty-force", [EXEC_INPUT_TTY_FAIL] = "tty-fail", [EXEC_INPUT_SOCKET] = "socket" }; DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput); static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = { [EXEC_OUTPUT_INHERIT] = "inherit", [EXEC_OUTPUT_NULL] = "null", [EXEC_OUTPUT_TTY] = "tty", [EXEC_OUTPUT_SYSLOG] = "syslog", [EXEC_OUTPUT_SYSLOG_AND_CONSOLE] = "syslog+console", [EXEC_OUTPUT_KMSG] = "kmsg", [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console", [EXEC_OUTPUT_JOURNAL] = "journal", [EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console", [EXEC_OUTPUT_SOCKET] = "socket" }; DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput); static const char* const exec_utmp_mode_table[_EXEC_UTMP_MODE_MAX] = { [EXEC_UTMP_INIT] = "init", [EXEC_UTMP_LOGIN] = "login", [EXEC_UTMP_USER] = "user", }; DEFINE_STRING_TABLE_LOOKUP(exec_utmp_mode, ExecUtmpMode); systemd-229/src/core/execute.h000066400000000000000000000201231265713322000164110ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct ExecStatus ExecStatus; typedef struct ExecCommand ExecCommand; typedef struct ExecContext ExecContext; typedef struct ExecRuntime ExecRuntime; typedef struct ExecParameters ExecParameters; #include #include #include #include #include "bus-endpoint.h" #include "fdset.h" #include "list.h" #include "missing.h" #include "namespace.h" typedef enum ExecUtmpMode { EXEC_UTMP_INIT, EXEC_UTMP_LOGIN, EXEC_UTMP_USER, _EXEC_UTMP_MODE_MAX, _EXEC_UTMP_MODE_INVALID = -1 } ExecUtmpMode; typedef enum ExecInput { EXEC_INPUT_NULL, EXEC_INPUT_TTY, EXEC_INPUT_TTY_FORCE, EXEC_INPUT_TTY_FAIL, EXEC_INPUT_SOCKET, _EXEC_INPUT_MAX, _EXEC_INPUT_INVALID = -1 } ExecInput; typedef enum ExecOutput { EXEC_OUTPUT_INHERIT, EXEC_OUTPUT_NULL, EXEC_OUTPUT_TTY, EXEC_OUTPUT_SYSLOG, EXEC_OUTPUT_SYSLOG_AND_CONSOLE, EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE, EXEC_OUTPUT_SOCKET, _EXEC_OUTPUT_MAX, _EXEC_OUTPUT_INVALID = -1 } ExecOutput; struct ExecStatus { dual_timestamp start_timestamp; dual_timestamp exit_timestamp; pid_t pid; int code; /* as in siginfo_t::si_code */ int status; /* as in sigingo_t::si_status */ }; struct ExecCommand { char *path; char **argv; ExecStatus exec_status; LIST_FIELDS(ExecCommand, command); /* useful for chaining commands */ bool ignore; }; struct ExecRuntime { int n_ref; char *tmp_dir; char *var_tmp_dir; int netns_storage_socket[2]; }; struct ExecContext { char **environment; char **environment_files; char **pass_environment; struct rlimit *rlimit[_RLIMIT_MAX]; char *working_directory, *root_directory; bool working_directory_missing_ok; bool working_directory_home; mode_t umask; int oom_score_adjust; int nice; int ioprio; int cpu_sched_policy; int cpu_sched_priority; cpu_set_t *cpuset; unsigned cpuset_ncpus; ExecInput std_input; ExecOutput std_output; ExecOutput std_error; nsec_t timer_slack_nsec; bool stdio_as_fds; char *tty_path; bool tty_reset; bool tty_vhangup; bool tty_vt_disallocate; bool ignore_sigpipe; /* Since resolving these names might might involve socket * connections and we don't want to deadlock ourselves these * names are resolved on execution only and in the child * process. */ char *user; char *group; char **supplementary_groups; char *pam_name; char *utmp_id; ExecUtmpMode utmp_mode; bool selinux_context_ignore; char *selinux_context; bool apparmor_profile_ignore; char *apparmor_profile; bool smack_process_label_ignore; char *smack_process_label; char **read_write_dirs, **read_only_dirs, **inaccessible_dirs; unsigned long mount_flags; uint64_t capability_bounding_set; uint64_t capability_ambient_set; cap_t capabilities; int secure_bits; int syslog_priority; char *syslog_identifier; bool syslog_level_prefix; bool cpu_sched_reset_on_fork; bool non_blocking; bool private_tmp; bool private_network; bool private_devices; ProtectSystem protect_system; ProtectHome protect_home; bool no_new_privileges; /* This is not exposed to the user but available * internally. We need it to make sure that whenever we spawn * /usr/bin/mount it is run in the same process group as us so * that the autofs logic detects that it belongs to us and we * don't enter a trigger loop. */ bool same_pgrp; unsigned long personality; Set *syscall_filter; Set *syscall_archs; int syscall_errno; bool syscall_whitelist:1; Set *address_families; bool address_families_whitelist:1; char **runtime_directory; mode_t runtime_directory_mode; bool oom_score_adjust_set:1; bool nice_set:1; bool ioprio_set:1; bool cpu_sched_set:1; bool no_new_privileges_set:1; /* custom dbus enpoint */ BusEndpoint *bus_endpoint; }; #include "cgroup-util.h" #include "cgroup.h" struct ExecParameters { char **argv; char **environment; int *fds; char **fd_names; unsigned n_fds; bool apply_permissions:1; bool apply_chroot:1; bool apply_tty_stdin:1; bool confirm_spawn:1; bool selinux_context_net:1; bool cgroup_delegate:1; CGroupMask cgroup_supported; const char *cgroup_path; const char *runtime_prefix; usec_t watchdog_usec; int *idle_pipe; char *bus_endpoint_path; int bus_endpoint_fd; int stdin_fd; int stdout_fd; int stderr_fd; }; int exec_spawn(Unit *unit, ExecCommand *command, const ExecContext *context, const ExecParameters *exec_params, ExecRuntime *runtime, pid_t *ret); void exec_command_done(ExecCommand *c); void exec_command_done_array(ExecCommand *c, unsigned n); ExecCommand* exec_command_free_list(ExecCommand *c); void exec_command_free_array(ExecCommand **c, unsigned n); char *exec_command_line(char **argv); void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix); void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix); void exec_command_append_list(ExecCommand **l, ExecCommand *e); int exec_command_set(ExecCommand *c, const char *path, ...); int exec_command_append(ExecCommand *c, const char *path, ...); void exec_context_init(ExecContext *c); void exec_context_done(ExecContext *c); void exec_context_dump(ExecContext *c, FILE* f, const char *prefix); int exec_context_destroy_runtime_directory(ExecContext *c, const char *runtime_root); int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l); bool exec_context_may_touch_console(ExecContext *c); bool exec_context_maintains_privileges(ExecContext *c); void exec_status_start(ExecStatus *s, pid_t pid); void exec_status_exit(ExecStatus *s, ExecContext *context, pid_t pid, int code, int status); void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix); int exec_runtime_make(ExecRuntime **rt, ExecContext *c, const char *id); ExecRuntime *exec_runtime_ref(ExecRuntime *r); ExecRuntime *exec_runtime_unref(ExecRuntime *r); int exec_runtime_serialize(Unit *unit, ExecRuntime *rt, FILE *f, FDSet *fds); int exec_runtime_deserialize_item(Unit *unit, ExecRuntime **rt, const char *key, const char *value, FDSet *fds); void exec_runtime_destroy(ExecRuntime *rt); const char* exec_output_to_string(ExecOutput i) _const_; ExecOutput exec_output_from_string(const char *s) _pure_; const char* exec_input_to_string(ExecInput i) _const_; ExecInput exec_input_from_string(const char *s) _pure_; const char* exec_utmp_mode_to_string(ExecUtmpMode i) _const_; ExecUtmpMode exec_utmp_mode_from_string(const char *s) _pure_; systemd-229/src/core/failure-action.c000066400000000000000000000102451265713322000176500ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering Copyright 2012 Michael Olbrich systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "bus-error.h" #include "bus-util.h" #include "failure-action.h" #include "special.h" #include "string-table.h" #include "terminal-util.h" static void log_and_status(Manager *m, const char *message) { log_warning("%s", message); manager_status_printf(m, STATUS_TYPE_EMERGENCY, ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL, "%s", message); } int failure_action( Manager *m, FailureAction action, const char *reboot_arg) { assert(m); assert(action >= 0); assert(action < _FAILURE_ACTION_MAX); if (action == FAILURE_ACTION_NONE) return -ECANCELED; if (m->running_as == MANAGER_USER) { /* Downgrade all options to simply exiting if we run * in user mode */ log_warning("Exiting as result of failure."); m->exit_code = MANAGER_EXIT; return -ECANCELED; } switch (action) { case FAILURE_ACTION_REBOOT: log_and_status(m, "Rebooting as result of failure."); update_reboot_param_file(reboot_arg); (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE, NULL); break; case FAILURE_ACTION_REBOOT_FORCE: log_and_status(m, "Forcibly rebooting as result of failure."); update_reboot_param_file(reboot_arg); m->exit_code = MANAGER_REBOOT; break; case FAILURE_ACTION_REBOOT_IMMEDIATE: log_and_status(m, "Rebooting immediately as result of failure."); sync(); if (reboot_arg) { log_info("Rebooting with argument '%s'.", reboot_arg); syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, reboot_arg); } log_info("Rebooting."); reboot(RB_AUTOBOOT); break; case FAILURE_ACTION_POWEROFF: log_and_status(m, "Powering off as result of failure."); (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE, NULL); break; case FAILURE_ACTION_POWEROFF_FORCE: log_and_status(m, "Forcibly powering off as result of failure."); m->exit_code = MANAGER_POWEROFF; break; case FAILURE_ACTION_POWEROFF_IMMEDIATE: log_and_status(m, "Powering off immediately as result of failure."); sync(); log_info("Powering off."); reboot(RB_POWER_OFF); break; default: assert_not_reached("Unknown failure action"); } return -ECANCELED; } static const char* const failure_action_table[_FAILURE_ACTION_MAX] = { [FAILURE_ACTION_NONE] = "none", [FAILURE_ACTION_REBOOT] = "reboot", [FAILURE_ACTION_REBOOT_FORCE] = "reboot-force", [FAILURE_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate", [FAILURE_ACTION_POWEROFF] = "poweroff", [FAILURE_ACTION_POWEROFF_FORCE] = "poweroff-force", [FAILURE_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate" }; DEFINE_STRING_TABLE_LOOKUP(failure_action, FailureAction); systemd-229/src/core/failure-action.h000066400000000000000000000025431265713322000176570ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering Copyright 2012 Michael Olbrich systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef enum FailureAction { FAILURE_ACTION_NONE, FAILURE_ACTION_REBOOT, FAILURE_ACTION_REBOOT_FORCE, FAILURE_ACTION_REBOOT_IMMEDIATE, FAILURE_ACTION_POWEROFF, FAILURE_ACTION_POWEROFF_FORCE, FAILURE_ACTION_POWEROFF_IMMEDIATE, _FAILURE_ACTION_MAX, _FAILURE_ACTION_INVALID = -1 } FailureAction; #include "macro.h" #include "manager.h" int failure_action(Manager *m, FailureAction action, const char *reboot_arg); const char* failure_action_to_string(FailureAction i) _const_; FailureAction failure_action_from_string(const char *s) _pure_; systemd-229/src/core/hostname-setup.c000066400000000000000000000037041265713322000177240ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "fileio.h" #include "hostname-setup.h" #include "hostname-util.h" #include "log.h" #include "macro.h" #include "string-util.h" #include "util.h" int hostname_setup(void) { int r; _cleanup_free_ char *b = NULL; const char *hn; bool enoent = false; r = read_hostname_config("/etc/hostname", &b); if (r < 0) { if (r == -ENOENT) enoent = true; else log_warning_errno(r, "Failed to read configured hostname: %m"); hn = NULL; } else hn = b; if (isempty(hn)) { /* Don't override the hostname if it is already set * and not explicitly configured */ if (hostname_is_set()) return 0; if (enoent) log_info("No hostname configured."); hn = "localhost"; } r = sethostname_idempotent(hn); if (r < 0) return log_warning_errno(r, "Failed to set hostname to <%s>: %m", hn); log_info("Set hostname to <%s>.", hn); return 0; } systemd-229/src/core/hostname-setup.h000066400000000000000000000013671265713322000177340ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int hostname_setup(void); systemd-229/src/core/ima-setup.c000066400000000000000000000054171265713322000166570ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright (C) 2012 Roberto Sassu - Politecnico di Torino, Italy TORSEC group -- http://security.polito.it systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "fd-util.h" #include "fileio.h" #include "ima-setup.h" #include "log.h" #include "util.h" #define IMA_SECFS_DIR "/sys/kernel/security/ima" #define IMA_SECFS_POLICY IMA_SECFS_DIR "/policy" #define IMA_POLICY_PATH "/etc/ima/ima-policy" int ima_setup(void) { #ifdef HAVE_IMA _cleanup_fclose_ FILE *input = NULL; _cleanup_close_ int imafd = -1; unsigned lineno = 0; char line[page_size()]; if (access(IMA_SECFS_DIR, F_OK) < 0) { log_debug("IMA support is disabled in the kernel, ignoring."); return 0; } input = fopen(IMA_POLICY_PATH, "re"); if (!input) { log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, "Failed to open the IMA custom policy file "IMA_POLICY_PATH", ignoring: %m"); return 0; } if (access(IMA_SECFS_POLICY, F_OK) < 0) { log_warning("Another IMA custom policy has already been loaded, ignoring."); return 0; } imafd = open(IMA_SECFS_POLICY, O_WRONLY|O_CLOEXEC); if (imafd < 0) { log_error_errno(errno, "Failed to open the IMA kernel interface "IMA_SECFS_POLICY", ignoring: %m"); return 0; } FOREACH_LINE(line, input, return log_error_errno(errno, "Failed to read the IMA custom policy file "IMA_POLICY_PATH": %m")) { size_t len; len = strlen(line); lineno++; if (len > 0 && write(imafd, line, len) < 0) return log_error_errno(errno, "Failed to load the IMA custom policy file "IMA_POLICY_PATH"%u: %m", lineno); } log_info("Successfully loaded the IMA custom policy "IMA_POLICY_PATH"."); #endif /* HAVE_IMA */ return 0; } systemd-229/src/core/ima-setup.h000066400000000000000000000016031265713322000166550ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright (C) 2012 Roberto Sassu - Politecnico di Torino, Italy TORSEC group -- http://security.polito.it systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int ima_setup(void); systemd-229/src/core/job.c000066400000000000000000001164731265713322000155320ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-id128.h" #include "sd-messages.h" #include "alloc-util.h" #include "async.h" #include "dbus-job.h" #include "dbus.h" #include "escape.h" #include "job.h" #include "log.h" #include "macro.h" #include "parse-util.h" #include "set.h" #include "special.h" #include "stdio-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "unit.h" #include "virt.h" Job* job_new_raw(Unit *unit) { Job *j; /* used for deserialization */ assert(unit); j = new0(Job, 1); if (!j) return NULL; j->manager = unit->manager; j->unit = unit; j->type = _JOB_TYPE_INVALID; return j; } Job* job_new(Unit *unit, JobType type) { Job *j; assert(type < _JOB_TYPE_MAX); j = job_new_raw(unit); if (!j) return NULL; j->id = j->manager->current_job_id++; j->type = type; /* We don't link it here, that's what job_dependency() is for */ return j; } void job_free(Job *j) { assert(j); assert(!j->installed); assert(!j->transaction_prev); assert(!j->transaction_next); assert(!j->subject_list); assert(!j->object_list); if (j->in_run_queue) LIST_REMOVE(run_queue, j->manager->run_queue, j); if (j->in_dbus_queue) LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j); sd_event_source_unref(j->timer_event_source); sd_bus_track_unref(j->clients); strv_free(j->deserialized_clients); free(j); } static void job_set_state(Job *j, JobState state) { assert(j); assert(state >= 0); assert(state < _JOB_STATE_MAX); if (j->state == state) return; j->state = state; if (!j->installed) return; if (j->state == JOB_RUNNING) j->unit->manager->n_running_jobs++; else { assert(j->state == JOB_WAITING); assert(j->unit->manager->n_running_jobs > 0); j->unit->manager->n_running_jobs--; if (j->unit->manager->n_running_jobs <= 0) j->unit->manager->jobs_in_progress_event_source = sd_event_source_unref(j->unit->manager->jobs_in_progress_event_source); } } void job_uninstall(Job *j) { Job **pj; assert(j->installed); job_set_state(j, JOB_WAITING); pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job; assert(*pj == j); /* Detach from next 'bigger' objects */ /* daemon-reload should be transparent to job observers */ if (j->manager->n_reloading <= 0) bus_job_send_removed_signal(j); *pj = NULL; unit_add_to_gc_queue(j->unit); hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id)); j->installed = false; } static bool job_type_allows_late_merge(JobType t) { /* Tells whether it is OK to merge a job of type 't' with an already * running job. * Reloads cannot be merged this way. Think of the sequence: * 1. Reload of a daemon is in progress; the daemon has already loaded * its config file, but hasn't completed the reload operation yet. * 2. Edit foo's config file. * 3. Trigger another reload to have the daemon use the new config. * Should the second reload job be merged into the first one, the daemon * would not know about the new config. * JOB_RESTART jobs on the other hand can be merged, because they get * patched into JOB_START after stopping the unit. So if we see a * JOB_RESTART running, it means the unit hasn't stopped yet and at * this time the merge is still allowed. */ return t != JOB_RELOAD; } static void job_merge_into_installed(Job *j, Job *other) { assert(j->installed); assert(j->unit == other->unit); if (j->type != JOB_NOP) job_type_merge_and_collapse(&j->type, other->type, j->unit); else assert(other->type == JOB_NOP); j->irreversible = j->irreversible || other->irreversible; j->ignore_order = j->ignore_order || other->ignore_order; } Job* job_install(Job *j) { Job **pj; Job *uj; assert(!j->installed); assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION); assert(j->state == JOB_WAITING); pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job; uj = *pj; if (uj) { if (job_type_is_conflicting(uj->type, j->type)) job_finish_and_invalidate(uj, JOB_CANCELED, false); else { /* not conflicting, i.e. mergeable */ if (uj->state == JOB_WAITING || (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) { job_merge_into_installed(uj, j); log_unit_debug(uj->unit, "Merged into installed job %s/%s as %u", uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id); return uj; } else { /* already running and not safe to merge into */ /* Patch uj to become a merged job and re-run it. */ /* XXX It should be safer to queue j to run after uj finishes, but it is * not currently possible to have more than one installed job per unit. */ job_merge_into_installed(uj, j); log_unit_debug(uj->unit, "Merged into running job, re-running: %s/%s as %u", uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id); job_set_state(uj, JOB_WAITING); return uj; } } } /* Install the job */ *pj = j; j->installed = true; j->manager->n_installed_jobs ++; log_unit_debug(j->unit, "Installed new job %s/%s as %u", j->unit->id, job_type_to_string(j->type), (unsigned) j->id); return j; } int job_install_deserialized(Job *j) { Job **pj; assert(!j->installed); if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION) { log_debug("Invalid job type %s in deserialization.", strna(job_type_to_string(j->type))); return -EINVAL; } pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job; if (*pj) { log_unit_debug(j->unit, "Unit already has a job installed. Not installing deserialized job."); return -EEXIST; } *pj = j; j->installed = true; if (j->state == JOB_RUNNING) j->unit->manager->n_running_jobs++; log_unit_debug(j->unit, "Reinstalled deserialized job %s/%s as %u", j->unit->id, job_type_to_string(j->type), (unsigned) j->id); return 0; } JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) { JobDependency *l; assert(object); /* Adds a new job link, which encodes that the 'subject' job * needs the 'object' job in some way. If 'subject' is NULL * this means the 'anchor' job (i.e. the one the user * explicitly asked for) is the requester. */ if (!(l = new0(JobDependency, 1))) return NULL; l->subject = subject; l->object = object; l->matters = matters; l->conflicts = conflicts; if (subject) LIST_PREPEND(subject, subject->subject_list, l); LIST_PREPEND(object, object->object_list, l); return l; } void job_dependency_free(JobDependency *l) { assert(l); if (l->subject) LIST_REMOVE(subject, l->subject->subject_list, l); LIST_REMOVE(object, l->object->object_list, l); free(l); } void job_dump(Job *j, FILE*f, const char *prefix) { assert(j); assert(f); if (!prefix) prefix = ""; fprintf(f, "%s-> Job %u:\n" "%s\tAction: %s -> %s\n" "%s\tState: %s\n" "%s\tIrreversible: %s\n", prefix, j->id, prefix, j->unit->id, job_type_to_string(j->type), prefix, job_state_to_string(j->state), prefix, yes_no(j->irreversible)); } /* * Merging is commutative, so imagine the matrix as symmetric. We store only * its lower triangle to avoid duplication. We don't store the main diagonal, * because A merged with A is simply A. * * If the resulting type is collapsed immediately afterwards (to get rid of * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain), * the following properties hold: * * Merging is associative! A merged with B, and then merged with C is the same * as A merged with the result of B merged with C. * * Mergeability is transitive! If A can be merged with B and B with C then * A also with C. * * Also, if A merged with B cannot be merged with C, then either A or B cannot * be merged with C either. */ static const JobType job_merging_table[] = { /* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */ /*********************************************************************************/ /*JOB_START */ /*JOB_VERIFY_ACTIVE */ JOB_START, /*JOB_STOP */ -1, -1, /*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1, /*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART, }; JobType job_type_lookup_merge(JobType a, JobType b) { assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1) / 2); assert(a >= 0 && a < _JOB_TYPE_MAX_MERGING); assert(b >= 0 && b < _JOB_TYPE_MAX_MERGING); if (a == b) return a; if (a < b) { JobType tmp = a; a = b; b = tmp; } return job_merging_table[(a - 1) * a / 2 + b]; } bool job_type_is_redundant(JobType a, UnitActiveState b) { switch (a) { case JOB_START: return b == UNIT_ACTIVE || b == UNIT_RELOADING; case JOB_STOP: return b == UNIT_INACTIVE || b == UNIT_FAILED; case JOB_VERIFY_ACTIVE: return b == UNIT_ACTIVE || b == UNIT_RELOADING; case JOB_RELOAD: return b == UNIT_RELOADING; case JOB_RESTART: return b == UNIT_ACTIVATING; case JOB_NOP: return true; default: assert_not_reached("Invalid job type"); } } JobType job_type_collapse(JobType t, Unit *u) { UnitActiveState s; switch (t) { case JOB_TRY_RESTART: s = unit_active_state(u); if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) return JOB_NOP; return JOB_RESTART; case JOB_TRY_RELOAD: s = unit_active_state(u); if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) return JOB_NOP; return JOB_RELOAD; case JOB_RELOAD_OR_START: s = unit_active_state(u); if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) return JOB_START; return JOB_RELOAD; default: return t; } } int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) { JobType t; t = job_type_lookup_merge(*a, b); if (t < 0) return -EEXIST; *a = job_type_collapse(t, u); return 0; } static bool job_is_runnable(Job *j) { Iterator i; Unit *other; assert(j); assert(j->installed); /* Checks whether there is any job running for the units this * job needs to be running after (in the case of a 'positive' * job type) or before (in the case of a 'negative' job * type. */ /* Note that unit types have a say in what is runnable, * too. For example, if they return -EAGAIN from * unit_start() they can indicate they are not * runnable yet. */ /* First check if there is an override */ if (j->ignore_order) return true; if (j->type == JOB_NOP) return true; if (j->type == JOB_START || j->type == JOB_VERIFY_ACTIVE || j->type == JOB_RELOAD) { /* Immediate result is that the job is or might be * started. In this case let's wait for the * dependencies, regardless whether they are * starting or stopping something. */ SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i) if (other->job) return false; } /* Also, if something else is being stopped and we should * change state after it, then let's wait. */ SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i) if (other->job && (other->job->type == JOB_STOP || other->job->type == JOB_RESTART)) return false; /* This means that for a service a and a service b where b * shall be started after a: * * start a + start b → 1st step start a, 2nd step start b * start a + stop b → 1st step stop b, 2nd step start a * stop a + start b → 1st step stop a, 2nd step start b * stop a + stop b → 1st step stop b, 2nd step stop a * * This has the side effect that restarts are properly * synchronized too. */ return true; } static void job_change_type(Job *j, JobType newtype) { assert(j); log_unit_debug(j->unit, "Converting job %s/%s -> %s/%s", j->unit->id, job_type_to_string(j->type), j->unit->id, job_type_to_string(newtype)); j->type = newtype; } static int job_perform_on_unit(Job **j) { uint32_t id; Manager *m; JobType t; Unit *u; int r; /* While we execute this operation the job might go away (for * example: because it finishes immediately or is replaced by * a new, conflicting job.) To make sure we don't access a * freed job later on we store the id here, so that we can * verify the job is still valid. */ assert(j); assert(*j); m = (*j)->manager; u = (*j)->unit; t = (*j)->type; id = (*j)->id; switch (t) { case JOB_START: r = unit_start(u); break; case JOB_RESTART: t = JOB_STOP; /* fall through */ case JOB_STOP: r = unit_stop(u); break; case JOB_RELOAD: r = unit_reload(u); break; default: assert_not_reached("Invalid job type"); } /* Log if the job still exists and the start/stop/reload function * actually did something. */ *j = manager_get_job(m, id); if (*j && r > 0) unit_status_emit_starting_stopping_reloading(u, t); return r; } int job_run_and_invalidate(Job *j) { int r; assert(j); assert(j->installed); assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION); assert(j->in_run_queue); LIST_REMOVE(run_queue, j->manager->run_queue, j); j->in_run_queue = false; if (j->state != JOB_WAITING) return 0; if (!job_is_runnable(j)) return -EAGAIN; job_set_state(j, JOB_RUNNING); job_add_to_dbus_queue(j); switch (j->type) { case JOB_VERIFY_ACTIVE: { UnitActiveState t = unit_active_state(j->unit); if (UNIT_IS_ACTIVE_OR_RELOADING(t)) r = -EALREADY; else if (t == UNIT_ACTIVATING) r = -EAGAIN; else r = -EBADR; break; } case JOB_START: case JOB_STOP: case JOB_RESTART: r = job_perform_on_unit(&j); /* If the unit type does not support starting/stopping, * then simply wait. */ if (r == -EBADR) r = 0; break; case JOB_RELOAD: r = job_perform_on_unit(&j); break; case JOB_NOP: r = -EALREADY; break; default: assert_not_reached("Unknown job type"); } if (j) { if (r == -EALREADY) r = job_finish_and_invalidate(j, JOB_DONE, true); else if (r == -EBADR) r = job_finish_and_invalidate(j, JOB_SKIPPED, true); else if (r == -ENOEXEC) r = job_finish_and_invalidate(j, JOB_INVALID, true); else if (r == -EPROTO) r = job_finish_and_invalidate(j, JOB_ASSERT, true); else if (r == -EOPNOTSUPP) r = job_finish_and_invalidate(j, JOB_UNSUPPORTED, true); else if (r == -EAGAIN) job_set_state(j, JOB_WAITING); else if (r < 0) r = job_finish_and_invalidate(j, JOB_FAILED, true); } return r; } _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) { static const char *const generic_finished_start_job[_JOB_RESULT_MAX] = { [JOB_DONE] = "Started %s.", [JOB_TIMEOUT] = "Timed out starting %s.", [JOB_FAILED] = "Failed to start %s.", [JOB_DEPENDENCY] = "Dependency failed for %s.", [JOB_ASSERT] = "Assertion failed for %s.", [JOB_UNSUPPORTED] = "Starting of %s not supported.", }; static const char *const generic_finished_stop_job[_JOB_RESULT_MAX] = { [JOB_DONE] = "Stopped %s.", [JOB_FAILED] = "Stopped (with error) %s.", [JOB_TIMEOUT] = "Timed out stoppping %s.", }; static const char *const generic_finished_reload_job[_JOB_RESULT_MAX] = { [JOB_DONE] = "Reloaded %s.", [JOB_FAILED] = "Reload failed for %s.", [JOB_TIMEOUT] = "Timed out reloading %s.", }; /* When verify-active detects the unit is inactive, report it. * Most likely a DEPEND warning from a requisiting unit will * occur next and it's nice to see what was requisited. */ static const char *const generic_finished_verify_active_job[_JOB_RESULT_MAX] = { [JOB_SKIPPED] = "%s is not active.", }; const UnitStatusMessageFormats *format_table; const char *format; assert(u); assert(t >= 0); assert(t < _JOB_TYPE_MAX); if (IN_SET(t, JOB_START, JOB_STOP, JOB_RESTART)) { format_table = &UNIT_VTABLE(u)->status_message_formats; if (format_table) { format = t == JOB_START ? format_table->finished_start_job[result] : format_table->finished_stop_job[result]; if (format) return format; } } /* Return generic strings */ if (t == JOB_START) return generic_finished_start_job[result]; else if (t == JOB_STOP || t == JOB_RESTART) return generic_finished_stop_job[result]; else if (t == JOB_RELOAD) return generic_finished_reload_job[result]; else if (t == JOB_VERIFY_ACTIVE) return generic_finished_verify_active_job[result]; return NULL; } static void job_print_status_message(Unit *u, JobType t, JobResult result) { static const char* const job_result_status_table[_JOB_RESULT_MAX] = { [JOB_DONE] = ANSI_GREEN " OK " ANSI_NORMAL, [JOB_TIMEOUT] = ANSI_HIGHLIGHT_RED " TIME " ANSI_NORMAL, [JOB_FAILED] = ANSI_HIGHLIGHT_RED "FAILED" ANSI_NORMAL, [JOB_DEPENDENCY] = ANSI_HIGHLIGHT_YELLOW "DEPEND" ANSI_NORMAL, [JOB_SKIPPED] = ANSI_HIGHLIGHT " INFO " ANSI_NORMAL, [JOB_ASSERT] = ANSI_HIGHLIGHT_YELLOW "ASSERT" ANSI_NORMAL, [JOB_UNSUPPORTED] = ANSI_HIGHLIGHT_YELLOW "UNSUPP" ANSI_NORMAL, }; const char *format; assert(u); assert(t >= 0); assert(t < _JOB_TYPE_MAX); /* Reload status messages have traditionally not been printed to console. */ if (t == JOB_RELOAD) return; format = job_get_status_message_format(u, t, result); if (!format) return; if (result != JOB_DONE) manager_flip_auto_status(u->manager, true); DISABLE_WARNING_FORMAT_NONLITERAL; unit_status_printf(u, job_result_status_table[result], format); REENABLE_WARNING; if (t == JOB_START && result == JOB_FAILED) { _cleanup_free_ char *quoted; quoted = shell_maybe_quote(u->id); manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, "See 'systemctl status %s' for details.", strna(quoted)); } } static void job_log_status_message(Unit *u, JobType t, JobResult result) { const char *format; char buf[LINE_MAX]; sd_id128_t mid; static const int job_result_log_level[_JOB_RESULT_MAX] = { [JOB_DONE] = LOG_INFO, [JOB_CANCELED] = LOG_INFO, [JOB_TIMEOUT] = LOG_ERR, [JOB_FAILED] = LOG_ERR, [JOB_DEPENDENCY] = LOG_WARNING, [JOB_SKIPPED] = LOG_NOTICE, [JOB_INVALID] = LOG_INFO, [JOB_ASSERT] = LOG_WARNING, [JOB_UNSUPPORTED] = LOG_WARNING, }; assert(u); assert(t >= 0); assert(t < _JOB_TYPE_MAX); /* Skip this if it goes to the console. since we already print * to the console anyway... */ if (log_on_console()) return; format = job_get_status_message_format(u, t, result); if (!format) return; DISABLE_WARNING_FORMAT_NONLITERAL; xsprintf(buf, format, unit_description(u)); REENABLE_WARNING; switch (t) { case JOB_START: mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED; break; case JOB_RELOAD: mid = SD_MESSAGE_UNIT_RELOADED; break; case JOB_STOP: case JOB_RESTART: mid = SD_MESSAGE_UNIT_STOPPED; break; default: log_struct(job_result_log_level[result], LOG_UNIT_ID(u), LOG_MESSAGE("%s", buf), "RESULT=%s", job_result_to_string(result), NULL); return; } log_struct(job_result_log_level[result], LOG_MESSAGE_ID(mid), LOG_UNIT_ID(u), LOG_MESSAGE("%s", buf), "RESULT=%s", job_result_to_string(result), NULL); } static void job_emit_status_message(Unit *u, JobType t, JobResult result) { /* No message if the job did not actually do anything due to failed condition. */ if (t == JOB_START && result == JOB_DONE && !u->condition_result) return; job_log_status_message(u, t, result); job_print_status_message(u, t, result); } static void job_fail_dependencies(Unit *u, UnitDependency d) { Unit *other; Iterator i; assert(u); SET_FOREACH(other, u->dependencies[d], i) { Job *j = other->job; if (!j) continue; if (!IN_SET(j->type, JOB_START, JOB_VERIFY_ACTIVE)) continue; job_finish_and_invalidate(j, JOB_DEPENDENCY, true); } } int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) { Unit *u; Unit *other; JobType t; Iterator i; assert(j); assert(j->installed); assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION); u = j->unit; t = j->type; j->result = result; log_unit_debug(u, "Job %s/%s finished, result=%s", u->id, job_type_to_string(t), job_result_to_string(result)); job_emit_status_message(u, t, result); job_add_to_dbus_queue(j); /* Patch restart jobs so that they become normal start jobs */ if (result == JOB_DONE && t == JOB_RESTART) { job_change_type(j, JOB_START); job_set_state(j, JOB_WAITING); job_add_to_run_queue(j); goto finish; } if (result == JOB_FAILED || result == JOB_INVALID) j->manager->n_failed_jobs ++; job_uninstall(j); job_free(j); /* Fail depending jobs on failure */ if (result != JOB_DONE && recursive) { if (IN_SET(t, JOB_START, JOB_VERIFY_ACTIVE)) { job_fail_dependencies(u, UNIT_REQUIRED_BY); job_fail_dependencies(u, UNIT_REQUISITE_OF); job_fail_dependencies(u, UNIT_BOUND_BY); } else if (t == JOB_STOP) job_fail_dependencies(u, UNIT_CONFLICTED_BY); } /* Trigger OnFailure dependencies that are not generated by * the unit itself. We don't treat JOB_CANCELED as failure in * this context. And JOB_FAILURE is already handled by the * unit itself. */ if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) { log_struct(LOG_NOTICE, "JOB_TYPE=%s", job_type_to_string(t), "JOB_RESULT=%s", job_result_to_string(result), LOG_UNIT_ID(u), LOG_UNIT_MESSAGE(u, "Job %s/%s failed with result '%s'.", u->id, job_type_to_string(t), job_result_to_string(result)), NULL); unit_start_on_failure(u); } unit_trigger_notify(u); finish: /* Try to start the next jobs that can be started */ SET_FOREACH(other, u->dependencies[UNIT_AFTER], i) if (other->job) job_add_to_run_queue(other->job); SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i) if (other->job) job_add_to_run_queue(other->job); manager_check_finished(u->manager); return 0; } static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *userdata) { Job *j = userdata; Unit *u; assert(j); assert(s == j->timer_event_source); log_unit_warning(j->unit, "Job %s/%s timed out.", j->unit->id, job_type_to_string(j->type)); u = j->unit; job_finish_and_invalidate(j, JOB_TIMEOUT, true); failure_action(u->manager, u->job_timeout_action, u->job_timeout_reboot_arg); return 0; } int job_start_timer(Job *j) { int r; if (j->timer_event_source) return 0; j->begin_usec = now(CLOCK_MONOTONIC); if (j->unit->job_timeout == USEC_INFINITY) return 0; r = sd_event_add_time( j->manager->event, &j->timer_event_source, CLOCK_MONOTONIC, usec_add(j->begin_usec, j->unit->job_timeout), 0, job_dispatch_timer, j); if (r < 0) return r; (void) sd_event_source_set_description(j->timer_event_source, "job-start"); return 0; } void job_add_to_run_queue(Job *j) { assert(j); assert(j->installed); if (j->in_run_queue) return; if (!j->manager->run_queue) sd_event_source_set_enabled(j->manager->run_queue_event_source, SD_EVENT_ONESHOT); LIST_PREPEND(run_queue, j->manager->run_queue, j); j->in_run_queue = true; } void job_add_to_dbus_queue(Job *j) { assert(j); assert(j->installed); if (j->in_dbus_queue) return; /* We don't check if anybody is subscribed here, since this * job might just have been created and not yet assigned to a * connection/client. */ LIST_PREPEND(dbus_queue, j->manager->dbus_job_queue, j); j->in_dbus_queue = true; } char *job_dbus_path(Job *j) { char *p; assert(j); if (asprintf(&p, "/org/freedesktop/systemd1/job/%"PRIu32, j->id) < 0) return NULL; return p; } int job_serialize(Job *j, FILE *f, FDSet *fds) { fprintf(f, "job-id=%u\n", j->id); fprintf(f, "job-type=%s\n", job_type_to_string(j->type)); fprintf(f, "job-state=%s\n", job_state_to_string(j->state)); fprintf(f, "job-irreversible=%s\n", yes_no(j->irreversible)); fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal)); fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order)); if (j->begin_usec > 0) fprintf(f, "job-begin="USEC_FMT"\n", j->begin_usec); bus_track_serialize(j->clients, f); /* End marker */ fputc('\n', f); return 0; } int job_deserialize(Job *j, FILE *f, FDSet *fds) { assert(j); for (;;) { char line[LINE_MAX], *l, *v; size_t k; if (!fgets(line, sizeof(line), f)) { if (feof(f)) return 0; return -errno; } char_array_0(line); l = strstrip(line); /* End marker */ if (l[0] == 0) return 0; k = strcspn(l, "="); if (l[k] == '=') { l[k] = 0; v = l+k+1; } else v = l+k; if (streq(l, "job-id")) { if (safe_atou32(v, &j->id) < 0) log_debug("Failed to parse job id value %s", v); } else if (streq(l, "job-type")) { JobType t; t = job_type_from_string(v); if (t < 0) log_debug("Failed to parse job type %s", v); else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION) log_debug("Cannot deserialize job of type %s", v); else j->type = t; } else if (streq(l, "job-state")) { JobState s; s = job_state_from_string(v); if (s < 0) log_debug("Failed to parse job state %s", v); else job_set_state(j, s); } else if (streq(l, "job-irreversible")) { int b; b = parse_boolean(v); if (b < 0) log_debug("Failed to parse job irreversible flag %s", v); else j->irreversible = j->irreversible || b; } else if (streq(l, "job-sent-dbus-new-signal")) { int b; b = parse_boolean(v); if (b < 0) log_debug("Failed to parse job sent_dbus_new_signal flag %s", v); else j->sent_dbus_new_signal = j->sent_dbus_new_signal || b; } else if (streq(l, "job-ignore-order")) { int b; b = parse_boolean(v); if (b < 0) log_debug("Failed to parse job ignore_order flag %s", v); else j->ignore_order = j->ignore_order || b; } else if (streq(l, "job-begin")) { unsigned long long ull; if (sscanf(v, "%llu", &ull) != 1) log_debug("Failed to parse job-begin value %s", v); else j->begin_usec = ull; } else if (streq(l, "subscribed")) { if (strv_extend(&j->deserialized_clients, v) < 0) return log_oom(); } } } int job_coldplug(Job *j) { int r; assert(j); /* After deserialization is complete and the bus connection * set up again, let's start watching our subscribers again */ r = bus_track_coldplug(j->manager, &j->clients, &j->deserialized_clients); if (r < 0) return r; if (j->state == JOB_WAITING) job_add_to_run_queue(j); if (j->begin_usec == 0 || j->unit->job_timeout == USEC_INFINITY) return 0; j->timer_event_source = sd_event_source_unref(j->timer_event_source); r = sd_event_add_time( j->manager->event, &j->timer_event_source, CLOCK_MONOTONIC, usec_add(j->begin_usec, j->unit->job_timeout), 0, job_dispatch_timer, j); if (r < 0) log_debug_errno(r, "Failed to restart timeout for job: %m"); (void) sd_event_source_set_description(j->timer_event_source, "job-timeout"); return r; } void job_shutdown_magic(Job *j) { assert(j); /* The shutdown target gets some special treatment here: we * tell the kernel to begin with flushing its disk caches, to * optimize shutdown time a bit. Ideally we wouldn't hardcode * this magic into PID 1. However all other processes aren't * options either since they'd exit much sooner than PID 1 and * asynchronous sync() would cause their exit to be * delayed. */ if (j->type != JOB_START) return; if (j->unit->manager->running_as != MANAGER_SYSTEM) return; if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET)) return; /* In case messages on console has been disabled on boot */ j->unit->manager->no_console_output = false; if (detect_container() > 0) return; asynchronous_sync(); } int job_get_timeout(Job *j, usec_t *timeout) { usec_t x = USEC_INFINITY, y = USEC_INFINITY; Unit *u = j->unit; int r; assert(u); if (j->timer_event_source) { r = sd_event_source_get_time(j->timer_event_source, &x); if (r < 0) return r; } if (UNIT_VTABLE(u)->get_timeout) { r = UNIT_VTABLE(u)->get_timeout(u, &y); if (r < 0) return r; } if (x == USEC_INFINITY && y == USEC_INFINITY) return 0; *timeout = MIN(x, y); return 1; } static const char* const job_state_table[_JOB_STATE_MAX] = { [JOB_WAITING] = "waiting", [JOB_RUNNING] = "running" }; DEFINE_STRING_TABLE_LOOKUP(job_state, JobState); static const char* const job_type_table[_JOB_TYPE_MAX] = { [JOB_START] = "start", [JOB_VERIFY_ACTIVE] = "verify-active", [JOB_STOP] = "stop", [JOB_RELOAD] = "reload", [JOB_RELOAD_OR_START] = "reload-or-start", [JOB_RESTART] = "restart", [JOB_TRY_RESTART] = "try-restart", [JOB_TRY_RELOAD] = "try-reload", [JOB_NOP] = "nop", }; DEFINE_STRING_TABLE_LOOKUP(job_type, JobType); static const char* const job_mode_table[_JOB_MODE_MAX] = { [JOB_FAIL] = "fail", [JOB_REPLACE] = "replace", [JOB_REPLACE_IRREVERSIBLY] = "replace-irreversibly", [JOB_ISOLATE] = "isolate", [JOB_FLUSH] = "flush", [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies", [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements", }; DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode); static const char* const job_result_table[_JOB_RESULT_MAX] = { [JOB_DONE] = "done", [JOB_CANCELED] = "canceled", [JOB_TIMEOUT] = "timeout", [JOB_FAILED] = "failed", [JOB_DEPENDENCY] = "dependency", [JOB_SKIPPED] = "skipped", [JOB_INVALID] = "invalid", [JOB_ASSERT] = "assert", [JOB_UNSUPPORTED] = "unsupported", }; DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult); const char* job_type_to_access_method(JobType t) { assert(t >= 0); assert(t < _JOB_TYPE_MAX); if (IN_SET(t, JOB_START, JOB_RESTART, JOB_TRY_RESTART)) return "start"; else if (t == JOB_STOP) return "stop"; else return "reload"; } systemd-229/src/core/job.h000066400000000000000000000202521265713322000155240ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-event.h" #include "list.h" #include "unit-name.h" typedef struct Job Job; typedef struct JobDependency JobDependency; typedef enum JobType JobType; typedef enum JobState JobState; typedef enum JobMode JobMode; typedef enum JobResult JobResult; /* Be careful when changing the job types! Adjust job_merging_table[] accordingly! */ enum JobType { JOB_START, /* if a unit does not support being started, we'll just wait until it becomes active */ JOB_VERIFY_ACTIVE, JOB_STOP, JOB_RELOAD, /* if running, reload */ /* Note that restarts are first treated like JOB_STOP, but * then instead of finishing are patched to become * JOB_START. */ JOB_RESTART, /* If running, stop. Then start unconditionally. */ _JOB_TYPE_MAX_MERGING, /* JOB_NOP can enter into a transaction, but as it won't pull in * any dependencies and it uses the special 'nop_job' slot in Unit, * it won't have to merge with anything (except possibly into another * JOB_NOP, previously installed). JOB_NOP is special-cased in * job_type_is_*() functions so that the transaction can be * activated. */ JOB_NOP = _JOB_TYPE_MAX_MERGING, /* do nothing */ _JOB_TYPE_MAX_IN_TRANSACTION, /* JOB_TRY_RESTART can never appear in a transaction, because * it always collapses into JOB_RESTART or JOB_NOP before entering. * Thus we never need to merge it with anything. */ JOB_TRY_RESTART = _JOB_TYPE_MAX_IN_TRANSACTION, /* if running, stop and then start */ /* Similar to JOB_TRY_RESTART but collapses to JOB_RELOAD or JOB_NOP */ JOB_TRY_RELOAD, /* JOB_RELOAD_OR_START won't enter into a transaction and cannot result * from transaction merging (there's no way for JOB_RELOAD and * JOB_START to meet in one transaction). It can result from a merge * during job installation, but then it will immediately collapse into * one of the two simpler types. */ JOB_RELOAD_OR_START, /* if running, reload, otherwise start */ _JOB_TYPE_MAX, _JOB_TYPE_INVALID = -1 }; enum JobState { JOB_WAITING, JOB_RUNNING, _JOB_STATE_MAX, _JOB_STATE_INVALID = -1 }; enum JobMode { JOB_FAIL, /* Fail if a conflicting job is already queued */ JOB_REPLACE, /* Replace an existing conflicting job */ JOB_REPLACE_IRREVERSIBLY,/* Like JOB_REPLACE + produce irreversible jobs */ JOB_ISOLATE, /* Start a unit, and stop all others */ JOB_FLUSH, /* Flush out all other queued jobs when queing this one */ JOB_IGNORE_DEPENDENCIES, /* Ignore both requirement and ordering dependencies */ JOB_IGNORE_REQUIREMENTS, /* Ignore requirement dependencies */ _JOB_MODE_MAX, _JOB_MODE_INVALID = -1 }; enum JobResult { JOB_DONE, /* Job completed successfully */ JOB_CANCELED, /* Job canceled by a conflicting job installation or by explicit cancel request */ JOB_TIMEOUT, /* Job timeout elapsed */ JOB_FAILED, /* Job failed */ JOB_DEPENDENCY, /* A required dependency job did not result in JOB_DONE */ JOB_SKIPPED, /* Negative result of JOB_VERIFY_ACTIVE */ JOB_INVALID, /* JOB_RELOAD of inactive unit */ JOB_ASSERT, /* Couldn't start a unit, because an assert didn't hold */ JOB_UNSUPPORTED, /* Couldn't start a unit, because the unit type is not supported on the system */ _JOB_RESULT_MAX, _JOB_RESULT_INVALID = -1 }; #include "unit.h" struct JobDependency { /* Encodes that the 'subject' job needs the 'object' job in * some way. This structure is used only while building a transaction. */ Job *subject; Job *object; LIST_FIELDS(JobDependency, subject); LIST_FIELDS(JobDependency, object); bool matters; bool conflicts; }; struct Job { Manager *manager; Unit *unit; LIST_FIELDS(Job, transaction); LIST_FIELDS(Job, run_queue); LIST_FIELDS(Job, dbus_queue); LIST_HEAD(JobDependency, subject_list); LIST_HEAD(JobDependency, object_list); /* Used for graph algs as a "I have been here" marker */ Job* marker; unsigned generation; uint32_t id; JobType type; JobState state; sd_event_source *timer_event_source; usec_t begin_usec; /* * This tracks where to send signals, and also which clients * are allowed to call DBus methods on the job (other than * root). * * There can be more than one client, because of job merging. */ sd_bus_track *clients; char **deserialized_clients; JobResult result; bool installed:1; bool in_run_queue:1; bool matters_to_anchor:1; bool in_dbus_queue:1; bool sent_dbus_new_signal:1; bool ignore_order:1; bool irreversible:1; }; Job* job_new(Unit *unit, JobType type); Job* job_new_raw(Unit *unit); void job_free(Job *job); Job* job_install(Job *j); int job_install_deserialized(Job *j); void job_uninstall(Job *j); void job_dump(Job *j, FILE*f, const char *prefix); int job_serialize(Job *j, FILE *f, FDSet *fds); int job_deserialize(Job *j, FILE *f, FDSet *fds); int job_coldplug(Job *j); JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts); void job_dependency_free(JobDependency *l); int job_merge(Job *j, Job *other); JobType job_type_lookup_merge(JobType a, JobType b) _pure_; _pure_ static inline bool job_type_is_mergeable(JobType a, JobType b) { return job_type_lookup_merge(a, b) >= 0; } _pure_ static inline bool job_type_is_conflicting(JobType a, JobType b) { return a != JOB_NOP && b != JOB_NOP && !job_type_is_mergeable(a, b); } _pure_ static inline bool job_type_is_superset(JobType a, JobType b) { /* Checks whether operation a is a "superset" of b in its actions */ if (b == JOB_NOP) return true; if (a == JOB_NOP) return false; return a == job_type_lookup_merge(a, b); } bool job_type_is_redundant(JobType a, UnitActiveState b) _pure_; /* Collapses a state-dependent job type into a simpler type by observing * the state of the unit which it is going to be applied to. */ JobType job_type_collapse(JobType t, Unit *u); int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u); void job_add_to_run_queue(Job *j); void job_add_to_dbus_queue(Job *j); int job_start_timer(Job *j); int job_run_and_invalidate(Job *j); int job_finish_and_invalidate(Job *j, JobResult result, bool recursive); char *job_dbus_path(Job *j); void job_shutdown_magic(Job *j); int job_get_timeout(Job *j, usec_t *timeout) _pure_; const char* job_type_to_string(JobType t) _const_; JobType job_type_from_string(const char *s) _pure_; const char* job_state_to_string(JobState t) _const_; JobState job_state_from_string(const char *s) _pure_; const char* job_mode_to_string(JobMode t) _const_; JobMode job_mode_from_string(const char *s) _pure_; const char* job_result_to_string(JobResult t) _const_; JobResult job_result_from_string(const char *s) _pure_; const char* job_type_to_access_method(JobType t); systemd-229/src/core/kill.c000066400000000000000000000040461265713322000157030ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "kill.h" #include "signal-util.h" #include "string-table.h" #include "util.h" void kill_context_init(KillContext *c) { assert(c); c->kill_signal = SIGTERM; c->send_sigkill = true; c->send_sighup = false; } void kill_context_dump(KillContext *c, FILE *f, const char *prefix) { assert(c); if (!prefix) prefix = ""; fprintf(f, "%sKillMode: %s\n" "%sKillSignal: SIG%s\n" "%sSendSIGKILL: %s\n" "%sSendSIGHUP: %s\n", prefix, kill_mode_to_string(c->kill_mode), prefix, signal_to_string(c->kill_signal), prefix, yes_no(c->send_sigkill), prefix, yes_no(c->send_sighup)); } static const char* const kill_mode_table[_KILL_MODE_MAX] = { [KILL_CONTROL_GROUP] = "control-group", [KILL_PROCESS] = "process", [KILL_MIXED] = "mixed", [KILL_NONE] = "none" }; DEFINE_STRING_TABLE_LOOKUP(kill_mode, KillMode); static const char* const kill_who_table[_KILL_WHO_MAX] = { [KILL_MAIN] = "main", [KILL_CONTROL] = "control", [KILL_ALL] = "all", [KILL_MAIN_FAIL] = "main-fail", [KILL_CONTROL_FAIL] = "control-fail", [KILL_ALL_FAIL] = "all-fail" }; DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho); systemd-229/src/core/kill.h000066400000000000000000000034111265713322000157030ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct KillContext KillContext; #include #include #include "macro.h" typedef enum KillMode { /* The kill mode is a property of a unit. */ KILL_CONTROL_GROUP = 0, KILL_PROCESS, KILL_MIXED, KILL_NONE, _KILL_MODE_MAX, _KILL_MODE_INVALID = -1 } KillMode; struct KillContext { KillMode kill_mode; int kill_signal; bool send_sigkill; bool send_sighup; }; typedef enum KillWho { /* Kill who is a property of an operation */ KILL_MAIN, KILL_CONTROL, KILL_ALL, KILL_MAIN_FAIL, KILL_CONTROL_FAIL, KILL_ALL_FAIL, _KILL_WHO_MAX, _KILL_WHO_INVALID = -1 } KillWho; void kill_context_init(KillContext *c); void kill_context_dump(KillContext *c, FILE *f, const char *prefix); const char *kill_mode_to_string(KillMode k) _const_; KillMode kill_mode_from_string(const char *s) _pure_; const char *kill_who_to_string(KillWho k) _const_; KillWho kill_who_from_string(const char *s) _pure_; systemd-229/src/core/killall.c000066400000000000000000000200471265713322000163730ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 ProFUSION embedded systems systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "killall.h" #include "parse-util.h" #include "process-util.h" #include "set.h" #include "string-util.h" #include "terminal-util.h" #include "util.h" #define TIMEOUT_USEC (10 * USEC_PER_SEC) static bool ignore_proc(pid_t pid, bool warn_rootfs) { _cleanup_fclose_ FILE *f = NULL; char c; const char *p; size_t count; uid_t uid; int r; /* We are PID 1, let's not commit suicide */ if (pid == 1) return true; r = get_process_uid(pid, &uid); if (r < 0) return true; /* not really, but better safe than sorry */ /* Non-root processes otherwise are always subject to be killed */ if (uid != 0) return false; p = procfs_file_alloca(pid, "cmdline"); f = fopen(p, "re"); if (!f) return true; /* not really, but has the desired effect */ count = fread(&c, 1, 1, f); /* Kernel threads have an empty cmdline */ if (count <= 0) return true; /* Processes with argv[0][0] = '@' we ignore from the killing * spree. * * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */ if (c == '@' && warn_rootfs) { _cleanup_free_ char *comm = NULL; r = pid_from_same_root_fs(pid); if (r < 0) return true; get_process_comm(pid, &comm); if (r) log_notice("Process " PID_FMT " (%s) has been been marked to be excluded from killing. It is " "running from the root file system, and thus likely to block re-mounting of the " "root file system to read-only. Please consider moving it into an initrd file " "system instead.", pid, strna(comm)); return true; } else if (c == '@') return true; return false; } static void wait_for_children(Set *pids, sigset_t *mask) { usec_t until; assert(mask); if (set_isempty(pids)) return; until = now(CLOCK_MONOTONIC) + TIMEOUT_USEC; for (;;) { struct timespec ts; int k; usec_t n; void *p; Iterator i; /* First, let the kernel inform us about killed * children. Most processes will probably be our * children, but some are not (might be our * grandchildren instead...). */ for (;;) { pid_t pid; pid = waitpid(-1, NULL, WNOHANG); if (pid == 0) break; if (pid < 0) { if (errno == ECHILD) break; log_error_errno(errno, "waitpid() failed: %m"); return; } (void) set_remove(pids, PID_TO_PTR(pid)); } /* Now explicitly check who might be remaining, who * might not be our child. */ SET_FOREACH(p, pids, i) { /* We misuse getpgid as a check whether a * process still exists. */ if (getpgid(PTR_TO_PID(p)) >= 0) continue; if (errno != ESRCH) continue; set_remove(pids, p); } if (set_isempty(pids)) return; n = now(CLOCK_MONOTONIC); if (n >= until) return; timespec_store(&ts, until - n); k = sigtimedwait(mask, NULL, &ts); if (k != SIGCHLD) { if (k < 0 && errno != EAGAIN) { log_error_errno(errno, "sigtimedwait() failed: %m"); return; } if (k >= 0) log_warning("sigtimedwait() returned unexpected signal."); } } } static int killall(int sig, Set *pids, bool send_sighup) { _cleanup_closedir_ DIR *dir = NULL; struct dirent *d; dir = opendir("/proc"); if (!dir) return -errno; while ((d = readdir(dir))) { pid_t pid; int r; if (d->d_type != DT_DIR && d->d_type != DT_UNKNOWN) continue; if (parse_pid(d->d_name, &pid) < 0) continue; if (ignore_proc(pid, sig == SIGKILL && !in_initrd())) continue; if (sig == SIGKILL) { _cleanup_free_ char *s = NULL; get_process_comm(pid, &s); log_notice("Sending SIGKILL to PID "PID_FMT" (%s).", pid, strna(s)); } if (kill(pid, sig) >= 0) { if (pids) { r = set_put(pids, PID_TO_PTR(pid)); if (r < 0) log_oom(); } } else if (errno != ENOENT) log_warning_errno(errno, "Could not kill %d: %m", pid); if (send_sighup) { /* Optionally, also send a SIGHUP signal, but only if the process has a controlling tty. This is useful to allow handling of shells which ignore SIGTERM but react to SIGHUP. We do not send this to processes that have no controlling TTY since we don't want to trigger reloads of daemon processes. Also we make sure to only send this after SIGTERM so that SIGTERM is always first in the queue. */ if (get_ctty_devnr(pid, NULL) >= 0) kill(pid, SIGHUP); } } return set_size(pids); } void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup) { sigset_t mask, oldmask; _cleanup_set_free_ Set *pids = NULL; if (wait_for_exit) pids = set_new(NULL); assert_se(sigemptyset(&mask) == 0); assert_se(sigaddset(&mask, SIGCHLD) == 0); assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0); if (kill(-1, SIGSTOP) < 0 && errno != ESRCH) log_warning_errno(errno, "kill(-1, SIGSTOP) failed: %m"); killall(sig, pids, send_sighup); if (kill(-1, SIGCONT) < 0 && errno != ESRCH) log_warning_errno(errno, "kill(-1, SIGCONT) failed: %m"); if (wait_for_exit) wait_for_children(pids, &mask); assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0); } systemd-229/src/core/killall.h000066400000000000000000000014431265713322000163770ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup); systemd-229/src/core/kmod-setup.c000066400000000000000000000111651265713322000170400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #ifdef HAVE_KMOD #include #endif #include "bus-util.h" #include "capability-util.h" #include "kmod-setup.h" #include "macro.h" #ifdef HAVE_KMOD static void systemd_kmod_log( void *data, int priority, const char *file, int line, const char *fn, const char *format, va_list args) { /* library logging is enabled at debug only */ DISABLE_WARNING_FORMAT_NONLITERAL; log_internalv(LOG_DEBUG, 0, file, line, fn, format, args); REENABLE_WARNING; } #endif int kmod_setup(void) { #ifdef HAVE_KMOD static const struct { const char *module; const char *path; bool warn_if_unavailable:1; bool warn_if_module:1; bool (*condition_fn)(void); } kmod_table[] = { /* auto-loading on use doesn't work before udev is up */ { "autofs4", "/sys/class/misc/autofs", true, false, NULL }, /* early configure of ::1 on the loopback device */ { "ipv6", "/sys/module/ipv6", false, true, NULL }, /* this should never be a module */ { "unix", "/proc/net/unix", true, true, NULL }, /* IPC is needed before we bring up any other services */ { "kdbus", "/sys/fs/kdbus", false, false, is_kdbus_wanted }, #ifdef HAVE_LIBIPTC /* netfilter is needed by networkd, nspawn among others, and cannot be autoloaded */ { "ip_tables", "/proc/net/ip_tables_names", false, false, NULL }, #endif }; struct kmod_ctx *ctx = NULL; unsigned int i; int r; if (have_effective_cap(CAP_SYS_MODULE) == 0) return 0; for (i = 0; i < ELEMENTSOF(kmod_table); i++) { struct kmod_module *mod; if (kmod_table[i].path && access(kmod_table[i].path, F_OK) >= 0) continue; if (kmod_table[i].condition_fn && !kmod_table[i].condition_fn()) continue; if (kmod_table[i].warn_if_module) log_debug("Your kernel apparently lacks built-in %s support. Might be " "a good idea to compile it in. We'll now try to work around " "this by loading the module...", kmod_table[i].module); if (!ctx) { ctx = kmod_new(NULL, NULL); if (!ctx) return log_oom(); kmod_set_log_fn(ctx, systemd_kmod_log, NULL); kmod_load_resources(ctx); } r = kmod_module_new_from_name(ctx, kmod_table[i].module, &mod); if (r < 0) { log_error("Failed to lookup module '%s'", kmod_table[i].module); continue; } r = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, NULL); if (r == 0) log_debug("Inserted module '%s'", kmod_module_get_name(mod)); else if (r == KMOD_PROBE_APPLY_BLACKLIST) log_info("Module '%s' is blacklisted", kmod_module_get_name(mod)); else { bool print_warning = kmod_table[i].warn_if_unavailable || (r < 0 && r != -ENOENT); log_full_errno(print_warning ? LOG_WARNING : LOG_DEBUG, r, "Failed to insert module '%s': %m", kmod_module_get_name(mod)); } kmod_module_unref(mod); } if (ctx) kmod_unref(ctx); #endif return 0; } systemd-229/src/core/kmod-setup.h000066400000000000000000000013631265713322000170440ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int kmod_setup(void); systemd-229/src/core/load-dropin.c000066400000000000000000000050131265713322000171530ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "conf-parser.h" #include "load-dropin.h" #include "load-fragment.h" #include "log.h" #include "strv.h" #include "unit-name.h" #include "unit.h" static int add_dependency_consumer( UnitDependency dependency, const char *entry, const char* filepath, void *arg) { Unit *u = arg; int r; assert(u); r = unit_add_dependency_by_name(u, dependency, entry, filepath, true); if (r < 0) log_error_errno(r, "Cannot add dependency %s to %s, ignoring: %m", entry, u->id); return 0; } int unit_load_dropin(Unit *u) { Iterator i; char *t, **f; int r; assert(u); /* Load dependencies from supplementary drop-in directories */ SET_FOREACH(t, u->names, i) { char **p; STRV_FOREACH(p, u->manager->lookup_paths.unit_path) { unit_file_process_dir(u->manager->unit_path_cache, *p, t, ".wants", UNIT_WANTS, add_dependency_consumer, u, NULL); unit_file_process_dir(u->manager->unit_path_cache, *p, t, ".requires", UNIT_REQUIRES, add_dependency_consumer, u, NULL); } } u->dropin_paths = strv_free(u->dropin_paths); r = unit_find_dropin_paths(u, &u->dropin_paths); if (r <= 0) return 0; STRV_FOREACH(f, u->dropin_paths) { config_parse(u->id, *f, NULL, UNIT_VTABLE(u)->sections, config_item_perf_lookup, load_fragment_gperf_lookup, false, false, false, u); } u->dropin_mtime = now(CLOCK_REALTIME); return 0; } systemd-229/src/core/load-dropin.h000066400000000000000000000022431265713322000171620ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "dropin.h" #include "unit.h" /* Read service data supplementary drop-in directories */ static inline int unit_find_dropin_paths(Unit *u, char ***paths) { return unit_file_find_dropin_paths(u->manager->lookup_paths.unit_path, u->manager->unit_path_cache, u->names, paths); } int unit_load_dropin(Unit *u); systemd-229/src/core/load-fragment-gperf.gperf.m4000066400000000000000000001216101265713322000217660ustar00rootroot00000000000000%{ #include #include "conf-parser.h" #include "load-fragment.h" #include "missing.h" %} struct ConfigPerfItem; %null_strings %language=ANSI-C %define slot-name section_and_lvalue %define hash-function-name load_fragment_gperf_hash %define lookup-function-name load_fragment_gperf_lookup %readonly-tables %omit-struct-type %struct-type %includes %% m4_dnl Define the context options only once m4_define(`EXEC_CONTEXT_CONFIG_ITEMS', `$1.WorkingDirectory, config_parse_working_directory, 0, offsetof($1, exec_context) $1.RootDirectory, config_parse_unit_path_printf, 0, offsetof($1, exec_context.root_directory) $1.User, config_parse_unit_string_printf, 0, offsetof($1, exec_context.user) $1.Group, config_parse_unit_string_printf, 0, offsetof($1, exec_context.group) $1.SupplementaryGroups, config_parse_strv, 0, offsetof($1, exec_context.supplementary_groups) $1.Nice, config_parse_exec_nice, 0, offsetof($1, exec_context) $1.OOMScoreAdjust, config_parse_exec_oom_score_adjust, 0, offsetof($1, exec_context) $1.IOSchedulingClass, config_parse_exec_io_class, 0, offsetof($1, exec_context) $1.IOSchedulingPriority, config_parse_exec_io_priority, 0, offsetof($1, exec_context) $1.CPUSchedulingPolicy, config_parse_exec_cpu_sched_policy, 0, offsetof($1, exec_context) $1.CPUSchedulingPriority, config_parse_exec_cpu_sched_prio, 0, offsetof($1, exec_context) $1.CPUSchedulingResetOnFork, config_parse_bool, 0, offsetof($1, exec_context.cpu_sched_reset_on_fork) $1.CPUAffinity, config_parse_exec_cpu_affinity, 0, offsetof($1, exec_context) $1.UMask, config_parse_mode, 0, offsetof($1, exec_context.umask) $1.Environment, config_parse_environ, 0, offsetof($1, exec_context.environment) $1.EnvironmentFile, config_parse_unit_env_file, 0, offsetof($1, exec_context.environment_files) $1.PassEnvironment, config_parse_pass_environ, 0, offsetof($1, exec_context.pass_environment) $1.StandardInput, config_parse_input, 0, offsetof($1, exec_context.std_input) $1.StandardOutput, config_parse_output, 0, offsetof($1, exec_context.std_output) $1.StandardError, config_parse_output, 0, offsetof($1, exec_context.std_error) $1.TTYPath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.tty_path) $1.TTYReset, config_parse_bool, 0, offsetof($1, exec_context.tty_reset) $1.TTYVHangup, config_parse_bool, 0, offsetof($1, exec_context.tty_vhangup) $1.TTYVTDisallocate, config_parse_bool, 0, offsetof($1, exec_context.tty_vt_disallocate) $1.SyslogIdentifier, config_parse_unit_string_printf, 0, offsetof($1, exec_context.syslog_identifier) $1.SyslogFacility, config_parse_log_facility, 0, offsetof($1, exec_context.syslog_priority) $1.SyslogLevel, config_parse_log_level, 0, offsetof($1, exec_context.syslog_priority) $1.SyslogLevelPrefix, config_parse_bool, 0, offsetof($1, exec_context.syslog_level_prefix) $1.Capabilities, config_parse_exec_capabilities, 0, offsetof($1, exec_context) $1.SecureBits, config_parse_exec_secure_bits, 0, offsetof($1, exec_context) $1.CapabilityBoundingSet, config_parse_capability_set, 0, offsetof($1, exec_context.capability_bounding_set) $1.AmbientCapabilities, config_parse_capability_set, 0, offsetof($1, exec_context.capability_ambient_set) $1.TimerSlackNSec, config_parse_nsec, 0, offsetof($1, exec_context.timer_slack_nsec) $1.NoNewPrivileges, config_parse_no_new_privileges, 0, offsetof($1, exec_context) m4_ifdef(`HAVE_SECCOMP', `$1.SystemCallFilter, config_parse_syscall_filter, 0, offsetof($1, exec_context) $1.SystemCallArchitectures, config_parse_syscall_archs, 0, offsetof($1, exec_context.syscall_archs) $1.SystemCallErrorNumber, config_parse_syscall_errno, 0, offsetof($1, exec_context) $1.RestrictAddressFamilies, config_parse_address_families, 0, offsetof($1, exec_context)', `$1.SystemCallFilter, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 $1.SystemCallArchitectures, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 $1.SystemCallErrorNumber, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 $1.RestrictAddressFamilies, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') $1.LimitCPU, config_parse_limit, RLIMIT_CPU, offsetof($1, exec_context.rlimit) $1.LimitFSIZE, config_parse_limit, RLIMIT_FSIZE, offsetof($1, exec_context.rlimit) $1.LimitDATA, config_parse_limit, RLIMIT_DATA, offsetof($1, exec_context.rlimit) $1.LimitSTACK, config_parse_limit, RLIMIT_STACK, offsetof($1, exec_context.rlimit) $1.LimitCORE, config_parse_limit, RLIMIT_CORE, offsetof($1, exec_context.rlimit) $1.LimitRSS, config_parse_limit, RLIMIT_RSS, offsetof($1, exec_context.rlimit) $1.LimitNOFILE, config_parse_limit, RLIMIT_NOFILE, offsetof($1, exec_context.rlimit) $1.LimitAS, config_parse_limit, RLIMIT_AS, offsetof($1, exec_context.rlimit) $1.LimitNPROC, config_parse_limit, RLIMIT_NPROC, offsetof($1, exec_context.rlimit) $1.LimitMEMLOCK, config_parse_limit, RLIMIT_MEMLOCK, offsetof($1, exec_context.rlimit) $1.LimitLOCKS, config_parse_limit, RLIMIT_LOCKS, offsetof($1, exec_context.rlimit) $1.LimitSIGPENDING, config_parse_limit, RLIMIT_SIGPENDING, offsetof($1, exec_context.rlimit) $1.LimitMSGQUEUE, config_parse_limit, RLIMIT_MSGQUEUE, offsetof($1, exec_context.rlimit) $1.LimitNICE, config_parse_limit, RLIMIT_NICE, offsetof($1, exec_context.rlimit) $1.LimitRTPRIO, config_parse_limit, RLIMIT_RTPRIO, offsetof($1, exec_context.rlimit) $1.LimitRTTIME, config_parse_limit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit) $1.ReadWriteDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_write_dirs) $1.ReadOnlyDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_only_dirs) $1.InaccessibleDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.inaccessible_dirs) $1.PrivateTmp, config_parse_bool, 0, offsetof($1, exec_context.private_tmp) $1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network) $1.PrivateDevices, config_parse_bool, 0, offsetof($1, exec_context.private_devices) $1.ProtectSystem, config_parse_protect_system, 0, offsetof($1, exec_context) $1.ProtectHome, config_parse_protect_home, 0, offsetof($1, exec_context) $1.MountFlags, config_parse_exec_mount_flags, 0, offsetof($1, exec_context) $1.Personality, config_parse_personality, 0, offsetof($1, exec_context.personality) $1.RuntimeDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.runtime_directory_mode) $1.RuntimeDirectory, config_parse_runtime_directory, 0, offsetof($1, exec_context.runtime_directory) m4_ifdef(`HAVE_PAM', `$1.PAMName, config_parse_unit_string_printf, 0, offsetof($1, exec_context.pam_name)', `$1.PAMName, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') $1.IgnoreSIGPIPE, config_parse_bool, 0, offsetof($1, exec_context.ignore_sigpipe) $1.UtmpIdentifier, config_parse_unit_string_printf, 0, offsetof($1, exec_context.utmp_id) $1.UtmpMode, config_parse_exec_utmp_mode, 0, offsetof($1, exec_context.utmp_mode) m4_ifdef(`HAVE_SELINUX', `$1.SELinuxContext, config_parse_exec_selinux_context, 0, offsetof($1, exec_context)', `$1.SELinuxContext, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') m4_ifdef(`HAVE_APPARMOR', `$1.AppArmorProfile, config_parse_exec_apparmor_profile, 0, offsetof($1, exec_context)', `$1.AppArmorProfile, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') m4_ifdef(`HAVE_SMACK', `$1.SmackProcessLabel, config_parse_exec_smack_process_label, 0, offsetof($1, exec_context)', `$1.SmackProcessLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')' )m4_dnl m4_define(`KILL_CONTEXT_CONFIG_ITEMS', `$1.SendSIGKILL, config_parse_bool, 0, offsetof($1, kill_context.send_sigkill) $1.SendSIGHUP, config_parse_bool, 0, offsetof($1, kill_context.send_sighup) $1.KillMode, config_parse_kill_mode, 0, offsetof($1, kill_context.kill_mode) $1.KillSignal, config_parse_signal, 0, offsetof($1, kill_context.kill_signal)' )m4_dnl m4_define(`CGROUP_CONTEXT_CONFIG_ITEMS', `$1.Slice, config_parse_unit_slice, 0, 0 $1.CPUAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.cpu_accounting) $1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.cpu_shares) $1.StartupCPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.startup_cpu_shares) $1.CPUQuota, config_parse_cpu_quota, 0, offsetof($1, cgroup_context) $1.MemoryAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.memory_accounting) $1.MemoryLimit, config_parse_memory_limit, 0, offsetof($1, cgroup_context) $1.DeviceAllow, config_parse_device_allow, 0, offsetof($1, cgroup_context) $1.DevicePolicy, config_parse_device_policy, 0, offsetof($1, cgroup_context.device_policy) $1.BlockIOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.blockio_accounting) $1.BlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.blockio_weight) $1.StartupBlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.startup_blockio_weight) $1.BlockIODeviceWeight, config_parse_blockio_device_weight, 0, offsetof($1, cgroup_context) $1.BlockIOReadBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context) $1.BlockIOWriteBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context) $1.TasksAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.tasks_accounting) $1.TasksMax, config_parse_tasks_max, 0, offsetof($1, cgroup_context.tasks_max) $1.Delegate, config_parse_bool, 0, offsetof($1, cgroup_context.delegate) $1.NetClass, config_parse_warn_compat, DISABLED_LEGACY, 0' )m4_dnl Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description) Unit.Documentation, config_parse_documentation, 0, offsetof(Unit, documentation) Unit.SourcePath, config_parse_path, 0, offsetof(Unit, source_path) Unit.Requires, config_parse_unit_deps, UNIT_REQUIRES, 0 Unit.Requisite, config_parse_unit_deps, UNIT_REQUISITE, 0 Unit.Wants, config_parse_unit_deps, UNIT_WANTS, 0 Unit.BindsTo, config_parse_unit_deps, UNIT_BINDS_TO, 0 Unit.BindTo, config_parse_unit_deps, UNIT_BINDS_TO, 0 Unit.Conflicts, config_parse_unit_deps, UNIT_CONFLICTS, 0 Unit.Before, config_parse_unit_deps, UNIT_BEFORE, 0 Unit.After, config_parse_unit_deps, UNIT_AFTER, 0 Unit.OnFailure, config_parse_unit_deps, UNIT_ON_FAILURE, 0 Unit.PropagatesReloadTo, config_parse_unit_deps, UNIT_PROPAGATES_RELOAD_TO, 0 Unit.PropagateReloadTo, config_parse_unit_deps, UNIT_PROPAGATES_RELOAD_TO, 0 Unit.ReloadPropagatedFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0 Unit.PropagateReloadFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0 Unit.PartOf, config_parse_unit_deps, UNIT_PART_OF, 0 Unit.JoinsNamespaceOf, config_parse_unit_deps, UNIT_JOINS_NAMESPACE_OF, 0 Unit.RequiresOverridable, config_parse_obsolete_unit_deps, UNIT_REQUIRES, 0 Unit.RequisiteOverridable, config_parse_obsolete_unit_deps, UNIT_REQUISITE, 0 Unit.RequiresMountsFor, config_parse_unit_requires_mounts_for, 0, 0 Unit.StopWhenUnneeded, config_parse_bool, 0, offsetof(Unit, stop_when_unneeded) Unit.RefuseManualStart, config_parse_bool, 0, offsetof(Unit, refuse_manual_start) Unit.RefuseManualStop, config_parse_bool, 0, offsetof(Unit, refuse_manual_stop) Unit.AllowIsolate, config_parse_bool, 0, offsetof(Unit, allow_isolate) Unit.DefaultDependencies, config_parse_bool, 0, offsetof(Unit, default_dependencies) Unit.OnFailureJobMode, config_parse_job_mode, 0, offsetof(Unit, on_failure_job_mode) Unit.OnFailureIsolate, config_parse_job_mode_isolate, 0, offsetof(Unit, on_failure_job_mode) Unit.IgnoreOnIsolate, config_parse_bool, 0, offsetof(Unit, ignore_on_isolate) Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LEGACY, 0 Unit.JobTimeoutSec, config_parse_sec_fix_0, 0, offsetof(Unit, job_timeout) Unit.JobTimeoutAction, config_parse_failure_action, 0, offsetof(Unit, job_timeout_action) Unit.JobTimeoutRebootArgument, config_parse_string, 0, offsetof(Unit, job_timeout_reboot_arg) Unit.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval) Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst) Unit.StartLimitAction, config_parse_failure_action, 0, offsetof(Unit, start_limit_action) Unit.RebootArgument, config_parse_string, 0, offsetof(Unit, reboot_arg) Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, conditions) Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, conditions) Unit.ConditionPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, conditions) Unit.ConditionPathIsSymbolicLink,config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, conditions) Unit.ConditionPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, conditions) Unit.ConditionPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, conditions) Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, conditions) Unit.ConditionFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, conditions) Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, conditions) Unit.ConditionNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, conditions) Unit.ConditionFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, conditions) Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions) Unit.ConditionArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, conditions) Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, conditions) Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, conditions) Unit.ConditionCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, conditions) Unit.ConditionHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, conditions) Unit.ConditionACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, conditions) Unit.ConditionNull, config_parse_unit_condition_null, 0, offsetof(Unit, conditions) Unit.AssertPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, asserts) Unit.AssertPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, asserts) Unit.AssertPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, asserts) Unit.AssertPathIsSymbolicLink, config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, asserts) Unit.AssertPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, asserts) Unit.AssertPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, asserts) Unit.AssertDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, asserts) Unit.AssertFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, asserts) Unit.AssertFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, asserts) Unit.AssertNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, asserts) Unit.AssertFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, asserts) Unit.AssertKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts) Unit.AssertArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, asserts) Unit.AssertVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, asserts) Unit.AssertSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, asserts) Unit.AssertCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, asserts) Unit.AssertHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, asserts) Unit.AssertACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, asserts) Unit.AssertNull, config_parse_unit_condition_null, 0, offsetof(Unit, asserts) m4_dnl Service.PIDFile, config_parse_unit_path_printf, 0, offsetof(Service, pid_file) Service.ExecStartPre, config_parse_exec, SERVICE_EXEC_START_PRE, offsetof(Service, exec_command) Service.ExecStart, config_parse_exec, SERVICE_EXEC_START, offsetof(Service, exec_command) Service.ExecStartPost, config_parse_exec, SERVICE_EXEC_START_POST, offsetof(Service, exec_command) Service.ExecReload, config_parse_exec, SERVICE_EXEC_RELOAD, offsetof(Service, exec_command) Service.ExecStop, config_parse_exec, SERVICE_EXEC_STOP, offsetof(Service, exec_command) Service.ExecStopPost, config_parse_exec, SERVICE_EXEC_STOP_POST, offsetof(Service, exec_command) Service.RestartSec, config_parse_sec, 0, offsetof(Service, restart_usec) Service.TimeoutSec, config_parse_service_timeout, 0, 0 Service.TimeoutStartSec, config_parse_service_timeout, 0, 0 Service.TimeoutStopSec, config_parse_service_timeout, 0, 0 Service.RuntimeMaxSec, config_parse_sec, 0, offsetof(Service, runtime_max_usec) Service.WatchdogSec, config_parse_sec, 0, offsetof(Service, watchdog_usec) Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval) Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst) Service.StartLimitAction, config_parse_failure_action, 0, offsetof(Unit, start_limit_action) Service.RebootArgument, config_parse_string, 0, offsetof(Unit, reboot_arg) Service.FailureAction, config_parse_failure_action, 0, offsetof(Service, failure_action) Service.Type, config_parse_service_type, 0, offsetof(Service, type) Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart) Service.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only) Service.RootDirectoryStartOnly, config_parse_bool, 0, offsetof(Service, root_directory_start_only) Service.RemainAfterExit, config_parse_bool, 0, offsetof(Service, remain_after_exit) Service.GuessMainPID, config_parse_bool, 0, offsetof(Service, guess_main_pid) Service.RestartPreventExitStatus, config_parse_set_status, 0, offsetof(Service, restart_prevent_status) Service.RestartForceExitStatus, config_parse_set_status, 0, offsetof(Service, restart_force_status) Service.SuccessExitStatus, config_parse_set_status, 0, offsetof(Service, success_status) Service.SysVStartPriority, config_parse_warn_compat, DISABLED_LEGACY, 0 Service.NonBlocking, config_parse_bool, 0, offsetof(Service, exec_context.non_blocking) Service.BusName, config_parse_bus_name, 0, offsetof(Service, bus_name) Service.FileDescriptorStoreMax, config_parse_unsigned, 0, offsetof(Service, n_fd_store_max) Service.NotifyAccess, config_parse_notify_access, 0, offsetof(Service, notify_access) Service.Sockets, config_parse_service_sockets, 0, 0 Service.BusPolicy, config_parse_bus_endpoint_policy, 0, offsetof(Service, exec_context) Service.USBFunctionDescriptors, config_parse_path, 0, offsetof(Service, usb_function_descriptors) Service.USBFunctionStrings, config_parse_path, 0, offsetof(Service, usb_function_strings) EXEC_CONTEXT_CONFIG_ITEMS(Service)m4_dnl CGROUP_CONTEXT_CONFIG_ITEMS(Service)m4_dnl KILL_CONTEXT_CONFIG_ITEMS(Service)m4_dnl m4_dnl Socket.ListenStream, config_parse_socket_listen, SOCKET_SOCKET, 0 Socket.ListenDatagram, config_parse_socket_listen, SOCKET_SOCKET, 0 Socket.ListenSequentialPacket, config_parse_socket_listen, SOCKET_SOCKET, 0 Socket.ListenFIFO, config_parse_socket_listen, SOCKET_FIFO, 0 Socket.ListenNetlink, config_parse_socket_listen, SOCKET_SOCKET, 0 Socket.ListenSpecial, config_parse_socket_listen, SOCKET_SPECIAL, 0 Socket.ListenMessageQueue, config_parse_socket_listen, SOCKET_MQUEUE, 0 Socket.ListenUSBFunction, config_parse_socket_listen, SOCKET_USB_FUNCTION, 0 Socket.SocketProtocol, config_parse_socket_protocol, 0, 0 Socket.BindIPv6Only, config_parse_socket_bind, 0, 0, Socket.Backlog, config_parse_unsigned, 0, offsetof(Socket, backlog) Socket.BindToDevice, config_parse_socket_bindtodevice, 0, 0 Socket.ExecStartPre, config_parse_exec, SOCKET_EXEC_START_PRE, offsetof(Socket, exec_command) Socket.ExecStartPost, config_parse_exec, SOCKET_EXEC_START_POST, offsetof(Socket, exec_command) Socket.ExecStopPre, config_parse_exec, SOCKET_EXEC_STOP_PRE, offsetof(Socket, exec_command) Socket.ExecStopPost, config_parse_exec, SOCKET_EXEC_STOP_POST, offsetof(Socket, exec_command) Socket.TimeoutSec, config_parse_sec, 0, offsetof(Socket, timeout_usec) Socket.SocketUser, config_parse_unit_string_printf, 0, offsetof(Socket, user) Socket.SocketGroup, config_parse_unit_string_printf, 0, offsetof(Socket, group) Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode) Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode) Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept) Socket.Writable, config_parse_bool, 0, offsetof(Socket, writable) Socket.MaxConnections, config_parse_unsigned, 0, offsetof(Socket, max_connections) Socket.KeepAlive, config_parse_bool, 0, offsetof(Socket, keep_alive) Socket.KeepAliveTimeSec, config_parse_sec, 0, offsetof(Socket, keep_alive_time) Socket.KeepAliveIntervalSec, config_parse_sec, 0, offsetof(Socket, keep_alive_interval) Socket.KeepAliveProbes, config_parse_unsigned, 0, offsetof(Socket, keep_alive_cnt) Socket.DeferAcceptSec, config_parse_sec, 0, offsetof(Socket, defer_accept) Socket.NoDelay, config_parse_bool, 0, offsetof(Socket, no_delay) Socket.Priority, config_parse_int, 0, offsetof(Socket, priority) Socket.ReceiveBuffer, config_parse_iec_size, 0, offsetof(Socket, receive_buffer) Socket.SendBuffer, config_parse_iec_size, 0, offsetof(Socket, send_buffer) Socket.IPTOS, config_parse_ip_tos, 0, offsetof(Socket, ip_tos) Socket.IPTTL, config_parse_int, 0, offsetof(Socket, ip_ttl) Socket.Mark, config_parse_int, 0, offsetof(Socket, mark) Socket.PipeSize, config_parse_iec_size, 0, offsetof(Socket, pipe_size) Socket.FreeBind, config_parse_bool, 0, offsetof(Socket, free_bind) Socket.Transparent, config_parse_bool, 0, offsetof(Socket, transparent) Socket.Broadcast, config_parse_bool, 0, offsetof(Socket, broadcast) Socket.PassCredentials, config_parse_bool, 0, offsetof(Socket, pass_cred) Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec) Socket.TCPCongestion, config_parse_string, 0, offsetof(Socket, tcp_congestion) Socket.ReusePort, config_parse_bool, 0, offsetof(Socket, reuse_port) Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg) Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize) Socket.RemoveOnStop, config_parse_bool, 0, offsetof(Socket, remove_on_stop) Socket.Symlinks, config_parse_unit_path_strv_printf, 0, offsetof(Socket, symlinks) Socket.FileDescriptorName, config_parse_fdname, 0, 0 Socket.Service, config_parse_socket_service, 0, 0 m4_ifdef(`HAVE_SMACK', `Socket.SmackLabel, config_parse_string, 0, offsetof(Socket, smack) Socket.SmackLabelIPIn, config_parse_string, 0, offsetof(Socket, smack_ip_in) Socket.SmackLabelIPOut, config_parse_string, 0, offsetof(Socket, smack_ip_out)', `Socket.SmackLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 Socket.SmackLabelIPIn, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 Socket.SmackLabelIPOut, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') m4_ifdef(`HAVE_SELINUX', `Socket.SELinuxContextFromNet, config_parse_bool, 0, offsetof(Socket, selinux_context_from_net)', `Socket.SELinuxContextFromNet, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') EXEC_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl CGROUP_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl KILL_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl m4_dnl BusName.Name, config_parse_string, 0, offsetof(BusName, name) BusName.Activating, config_parse_bool, 0, offsetof(BusName, activating) BusName.Service, config_parse_busname_service, 0, 0 BusName.AllowUser, config_parse_bus_policy, 0, 0 BusName.AllowGroup, config_parse_bus_policy, 0, 0 BusName.AllowWorld, config_parse_bus_policy_world, 0, offsetof(BusName, policy_world) BusName.SELinuxContext, config_parse_exec_selinux_context, 0, 0 BusName.AcceptFileDescriptors, config_parse_bool, 0, offsetof(BusName, accept_fd) m4_dnl Mount.What, config_parse_string, 0, offsetof(Mount, parameters_fragment.what) Mount.Where, config_parse_path, 0, offsetof(Mount, where) Mount.Options, config_parse_string, 0, offsetof(Mount, parameters_fragment.options) Mount.Type, config_parse_string, 0, offsetof(Mount, parameters_fragment.fstype) Mount.TimeoutSec, config_parse_sec, 0, offsetof(Mount, timeout_usec) Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode) Mount.SloppyOptions, config_parse_bool, 0, offsetof(Mount, sloppy_options) EXEC_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl CGROUP_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl m4_dnl Automount.Where, config_parse_path, 0, offsetof(Automount, where) Automount.DirectoryMode, config_parse_mode, 0, offsetof(Automount, directory_mode) Automount.TimeoutIdleSec, config_parse_sec, 0, offsetof(Automount, timeout_idle_usec) m4_dnl Swap.What, config_parse_path, 0, offsetof(Swap, parameters_fragment.what) Swap.Priority, config_parse_int, 0, offsetof(Swap, parameters_fragment.priority) Swap.Options, config_parse_string, 0, offsetof(Swap, parameters_fragment.options) Swap.TimeoutSec, config_parse_sec, 0, offsetof(Swap, timeout_usec) EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl CGROUP_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl KILL_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl m4_dnl Timer.OnCalendar, config_parse_timer, 0, 0 Timer.OnActiveSec, config_parse_timer, 0, 0 Timer.OnBootSec, config_parse_timer, 0, 0 Timer.OnStartupSec, config_parse_timer, 0, 0 Timer.OnUnitActiveSec, config_parse_timer, 0, 0 Timer.OnUnitInactiveSec, config_parse_timer, 0, 0 Timer.Persistent, config_parse_bool, 0, offsetof(Timer, persistent) Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system) Timer.RemainAfterElapse, config_parse_bool, 0, offsetof(Timer, remain_after_elapse) Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec) Timer.RandomizedDelaySec, config_parse_sec, 0, offsetof(Timer, random_usec) Timer.Unit, config_parse_trigger_unit, 0, 0 m4_dnl Path.PathExists, config_parse_path_spec, 0, 0 Path.PathExistsGlob, config_parse_path_spec, 0, 0 Path.PathChanged, config_parse_path_spec, 0, 0 Path.PathModified, config_parse_path_spec, 0, 0 Path.DirectoryNotEmpty, config_parse_path_spec, 0, 0 Path.Unit, config_parse_trigger_unit, 0, 0 Path.MakeDirectory, config_parse_bool, 0, offsetof(Path, make_directory) Path.DirectoryMode, config_parse_mode, 0, offsetof(Path, directory_mode) m4_dnl CGROUP_CONTEXT_CONFIG_ITEMS(Slice)m4_dnl m4_dnl CGROUP_CONTEXT_CONFIG_ITEMS(Scope)m4_dnl KILL_CONTEXT_CONFIG_ITEMS(Scope)m4_dnl Scope.TimeoutStopSec, config_parse_sec, 0, offsetof(Scope, timeout_stop_usec) m4_dnl The [Install] section is ignored here. Install.Alias, NULL, 0, 0 Install.WantedBy, NULL, 0, 0 Install.RequiredBy, NULL, 0, 0 Install.Also, NULL, 0, 0 Install.DefaultInstance, NULL, 0, 0 systemd-229/src/core/load-fragment.c000066400000000000000000003645371265713322000175060ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2012 Holger Hans Peter Freyther systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #ifdef HAVE_SECCOMP #include #endif #include #include #include #include #include "af-list.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-internal.h" #include "bus-util.h" #include "cap-list.h" #include "capability-util.h" #include "cgroup.h" #include "conf-parser.h" #include "cpu-set-util.h" #include "env-util.h" #include "errno-list.h" #include "escape.h" #include "fd-util.h" #include "fs-util.h" #include "ioprio.h" #include "load-fragment.h" #include "log.h" #include "missing.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "rlimit-util.h" #ifdef HAVE_SECCOMP #include "seccomp-util.h" #endif #include "securebits.h" #include "signal-util.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "unit-printf.h" #include "unit.h" #include "utf8.h" #include "web-util.h" int config_parse_warn_compat( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Disabled reason = ltype; switch(reason) { case DISABLED_CONFIGURATION: log_syntax(unit, LOG_DEBUG, filename, line, 0, "Support for option %s= has been disabled at compile time and it is ignored", lvalue); break; case DISABLED_LEGACY: log_syntax(unit, LOG_INFO, filename, line, 0, "Support for option %s= has been removed and it is ignored", lvalue); break; case DISABLED_EXPERIMENTAL: log_syntax(unit, LOG_INFO, filename, line, 0, "Support for option %s= has not yet been enabled and it is ignored", lvalue); break; }; return 0; } int config_parse_unit_deps( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { UnitDependency d = ltype; Unit *u = userdata; const char *p; assert(filename); assert(lvalue); assert(rvalue); p = rvalue; for(;;) { _cleanup_free_ char *word = NULL, *k = NULL; int r; r = extract_first_word(&p, &word, NULL, EXTRACT_RETAIN_ESCAPE); if (r == 0) break; if (r == -ENOMEM) return log_oom(); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); break; } r = unit_name_printf(u, word, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m"); continue; } r = unit_add_dependency_by_name(u, d, k, NULL, true); if (r < 0) log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k); } return 0; } int config_parse_obsolete_unit_deps( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { log_syntax(unit, LOG_WARNING, filename, line, 0, "Unit dependency type %s= is obsolete, replacing by %s=, please update your unit file", lvalue, unit_dependency_to_string(ltype)); return config_parse_unit_deps(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata); } int config_parse_unit_string_printf( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *k = NULL; Unit *u = userdata; int r; assert(filename); assert(lvalue); assert(rvalue); assert(u); r = unit_full_printf(u, rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue); return 0; } return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata); } int config_parse_unit_strv_printf( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Unit *u = userdata; _cleanup_free_ char *k = NULL; int r; assert(filename); assert(lvalue); assert(rvalue); assert(u); r = unit_full_printf(u, rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue); return 0; } return config_parse_strv(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata); } int config_parse_unit_path_printf( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *k = NULL; Unit *u = userdata; int r; assert(filename); assert(lvalue); assert(rvalue); assert(u); r = unit_full_printf(u, rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue); return 0; } return config_parse_path(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata); } int config_parse_unit_path_strv_printf( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { char ***x = data; const char *word, *state; Unit *u = userdata; size_t l; int r; assert(filename); assert(lvalue); assert(rvalue); assert(u); FOREACH_WORD_QUOTED(word, l, rvalue, state) { _cleanup_free_ char *k = NULL; char t[l+1]; memcpy(t, word, l); t[l] = 0; r = unit_full_printf(u, t, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", t); return 0; } if (!utf8_is_valid(k)) { log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); return 0; } if (!path_is_absolute(k)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Symlink path %s is not absolute, ignoring: %m", k); return 0; } path_kill_slashes(k); r = strv_push(x, k); if (r < 0) return log_oom(); k = NULL; } if (!isempty(state)) log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid syntax, ignoring."); return 0; } int config_parse_socket_listen(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ SocketPort *p = NULL; SocketPort *tail; Socket *s; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); s = SOCKET(data); if (isempty(rvalue)) { /* An empty assignment removes all ports */ socket_free_ports(s); return 0; } p = new0(SocketPort, 1); if (!p) return log_oom(); if (ltype != SOCKET_SOCKET) { p->type = ltype; r = unit_full_printf(UNIT(s), rvalue, &p->path); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue); return 0; } path_kill_slashes(p->path); } else if (streq(lvalue, "ListenNetlink")) { _cleanup_free_ char *k = NULL; p->type = SOCKET_SOCKET; r = unit_full_printf(UNIT(s), rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue); return 0; } r = socket_address_parse_netlink(&p->address, k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value, ignoring: %s", rvalue); return 0; } } else { _cleanup_free_ char *k = NULL; p->type = SOCKET_SOCKET; r = unit_full_printf(UNIT(s), rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r,"Failed to resolve unit specifiers on %s, ignoring: %m", rvalue); return 0; } r = socket_address_parse_and_warn(&p->address, k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value, ignoring: %s", rvalue); return 0; } if (streq(lvalue, "ListenStream")) p->address.type = SOCK_STREAM; else if (streq(lvalue, "ListenDatagram")) p->address.type = SOCK_DGRAM; else { assert(streq(lvalue, "ListenSequentialPacket")); p->address.type = SOCK_SEQPACKET; } if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) { log_syntax(unit, LOG_ERR, filename, line, 0, "Address family not supported, ignoring: %s", rvalue); return 0; } } p->fd = -1; p->auxiliary_fds = NULL; p->n_auxiliary_fds = 0; p->socket = s; if (s->ports) { LIST_FIND_TAIL(port, s->ports, tail); LIST_INSERT_AFTER(port, s->ports, tail, p); } else LIST_PREPEND(port, s->ports, p); p = NULL; return 0; } int config_parse_socket_protocol(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Socket *s; assert(filename); assert(lvalue); assert(rvalue); assert(data); s = SOCKET(data); if (streq(rvalue, "udplite")) s->socket_protocol = IPPROTO_UDPLITE; else if (streq(rvalue, "sctp")) s->socket_protocol = IPPROTO_SCTP; else { log_syntax(unit, LOG_ERR, filename, line, 0, "Socket protocol not supported, ignoring: %s", rvalue); return 0; } return 0; } int config_parse_socket_bind(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Socket *s; SocketAddressBindIPv6Only b; assert(filename); assert(lvalue); assert(rvalue); assert(data); s = SOCKET(data); b = socket_address_bind_ipv6_only_from_string(rvalue); if (b < 0) { int r; r = parse_boolean(rvalue); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse bind IPv6 only value, ignoring: %s", rvalue); return 0; } s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH; } else s->bind_ipv6_only = b; return 0; } int config_parse_exec_nice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; int priority, r; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = safe_atoi(rvalue, &priority); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse nice priority, ignoring: %s", rvalue); return 0; } if (priority < PRIO_MIN || priority >= PRIO_MAX) { log_syntax(unit, LOG_ERR, filename, line, 0, "Nice priority out of range, ignoring: %s", rvalue); return 0; } c->nice = priority; c->nice_set = true; return 0; } int config_parse_exec_oom_score_adjust(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; int oa, r; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = safe_atoi(rvalue, &oa); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value, ignoring: %s", rvalue); return 0; } if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) { log_syntax(unit, LOG_ERR, filename, line, 0, "OOM score adjust value out of range, ignoring: %s", rvalue); return 0; } c->oom_score_adjust = oa; c->oom_score_adjust_set = true; return 0; } int config_parse_exec( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *cmd = NULL; ExecCommand **e = data; Unit *u = userdata; const char *p; bool semicolon; int r; assert(filename); assert(lvalue); assert(rvalue); assert(e); assert(u); e += ltype; rvalue += strspn(rvalue, WHITESPACE); if (isempty(rvalue)) { /* An empty assignment resets the list */ *e = exec_command_free_list(*e); return 0; } r = unit_full_printf(u, rvalue, &cmd); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue); return 0; } p = cmd; do { _cleanup_free_ char *path = NULL, *firstword = NULL; bool separate_argv0 = false, ignore = false; _cleanup_free_ ExecCommand *nce = NULL; _cleanup_strv_free_ char **n = NULL; size_t nlen = 0, nbufsize = 0; char *f; int i; semicolon = false; r = extract_first_word_and_warn(&p, &firstword, WHITESPACE, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, unit, filename, line, rvalue); if (r <= 0) return 0; f = firstword; for (i = 0; i < 2; i++) { /* We accept an absolute path as first argument, or * alternatively an absolute prefixed with @ to allow * overriding of argv[0]. */ if (*f == '-' && !ignore) ignore = true; else if (*f == '@' && !separate_argv0) separate_argv0 = true; else break; f ++; } if (isempty(f)) { /* First word is either "-" or "@" with no command. */ log_syntax(unit, LOG_ERR, filename, line, 0, "Empty path in command line, ignoring: \"%s\"", rvalue); return 0; } if (!string_is_safe(f)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path contains special characters, ignoring: %s", rvalue); return 0; } if (!path_is_absolute(f)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path is not absolute, ignoring: %s", rvalue); return 0; } if (endswith(f, "/")) { log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path specifies a directory, ignoring: %s", rvalue); return 0; } if (f == firstword) { path = firstword; firstword = NULL; } else { path = strdup(f); if (!path) return log_oom(); } if (!separate_argv0) { if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) return log_oom(); f = strdup(path); if (!f) return log_oom(); n[nlen++] = f; n[nlen] = NULL; } path_kill_slashes(path); while (!isempty(p)) { _cleanup_free_ char *word = NULL; /* Check explicitly for an unquoted semicolon as * command separator token. */ if (p[0] == ';' && (!p[1] || strchr(WHITESPACE, p[1]))) { p ++; p += strspn(p, WHITESPACE); semicolon = true; break; } /* Check for \; explicitly, to not confuse it with \\; * or "\;" or "\\;" etc. extract_first_word would * return the same for all of those. */ if (p[0] == '\\' && p[1] == ';' && (!p[2] || strchr(WHITESPACE, p[2]))) { p += 2; p += strspn(p, WHITESPACE); if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) return log_oom(); f = strdup(";"); if (!f) return log_oom(); n[nlen++] = f; n[nlen] = NULL; continue; } r = extract_first_word_and_warn(&p, &word, WHITESPACE, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, unit, filename, line, rvalue); if (r == 0) break; else if (r < 0) return 0; if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) return log_oom(); n[nlen++] = word; n[nlen] = NULL; word = NULL; } if (!n || !n[0]) { log_syntax(unit, LOG_ERR, filename, line, 0, "Empty executable name or zeroeth argument, ignoring: %s", rvalue); return 0; } nce = new0(ExecCommand, 1); if (!nce) return log_oom(); nce->argv = n; nce->path = path; nce->ignore = ignore; exec_command_append_list(e, nce); /* Do not _cleanup_free_ these. */ n = NULL; path = NULL; nce = NULL; rvalue = p; } while (semicolon); return 0; } DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type"); DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier"); int config_parse_socket_bindtodevice(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Socket *s = data; char *n; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (rvalue[0] && !streq(rvalue, "*")) { n = strdup(rvalue); if (!n) return log_oom(); } else n = NULL; free(s->bind_to_device); s->bind_to_device = n; return 0; } DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier"); DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier"); int config_parse_exec_io_class(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; int x; assert(filename); assert(lvalue); assert(rvalue); assert(data); x = ioprio_class_from_string(rvalue); if (x < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IO scheduling class, ignoring: %s", rvalue); return 0; } c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio)); c->ioprio_set = true; return 0; } int config_parse_exec_io_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; int i, r; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = safe_atoi(rvalue, &i); if (r < 0 || i < 0 || i >= IOPRIO_BE_NR) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IO priority, ignoring: %s", rvalue); return 0; } c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i); c->ioprio_set = true; return 0; } int config_parse_exec_cpu_sched_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; int x; assert(filename); assert(lvalue); assert(rvalue); assert(data); x = sched_policy_from_string(rvalue); if (x < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue); return 0; } c->cpu_sched_policy = x; /* Moving to or from real-time policy? We need to adjust the priority */ c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(x), sched_get_priority_max(x)); c->cpu_sched_set = true; return 0; } int config_parse_exec_cpu_sched_prio(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; int i, min, max, r; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = safe_atoi(rvalue, &i); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue); return 0; } /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0 */ min = sched_get_priority_min(c->cpu_sched_policy); max = sched_get_priority_max(c->cpu_sched_policy); if (i < min || i > max) { log_syntax(unit, LOG_ERR, filename, line, 0, "CPU scheduling priority is out of range, ignoring: %s", rvalue); return 0; } c->cpu_sched_priority = i; c->cpu_sched_set = true; return 0; } int config_parse_exec_cpu_affinity(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; _cleanup_cpu_free_ cpu_set_t *cpuset = NULL; int ncpus; assert(filename); assert(lvalue); assert(rvalue); assert(data); ncpus = parse_cpu_set_and_warn(rvalue, &cpuset, unit, filename, line, lvalue); if (ncpus < 0) return ncpus; if (c->cpuset) CPU_FREE(c->cpuset); if (ncpus == 0) /* An empty assignment resets the CPU list */ c->cpuset = NULL; else { c->cpuset = cpuset; cpuset = NULL; } c->cpuset_ncpus = ncpus; return 0; } int config_parse_exec_capabilities(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; cap_t cap; assert(filename); assert(lvalue); assert(rvalue); assert(data); cap = cap_from_text(rvalue); if (!cap) { log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse capabilities, ignoring: %s", rvalue); return 0; } if (c->capabilities) cap_free(c->capabilities); c->capabilities = cap; return 0; } int config_parse_exec_secure_bits(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; size_t l; const char *word, *state; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { /* An empty assignment resets the field */ c->secure_bits = 0; return 0; } FOREACH_WORD_QUOTED(word, l, rvalue, state) { if (first_word(word, "keep-caps")) c->secure_bits |= 1<secure_bits |= 1<secure_bits |= 1<secure_bits |= 1<secure_bits |= 1<secure_bits |= 1< replace */ *capability_set = sum; else /* previous data -> merge */ *capability_set |= sum; return 0; } int config_parse_limit( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { struct rlimit **rl = data, d = {}; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = rlimit_parse(ltype, rvalue, &d); if (r == -EILSEQ) { log_syntax(unit, LOG_WARNING, filename, line, r, "Soft resource limit chosen higher than hard limit, ignoring: %s", rvalue); return 0; } if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue); return 0; } if (rl[ltype]) *rl[ltype] = d; else { rl[ltype] = newdup(struct rlimit, &d, 1); if (!rl[ltype]) return log_oom(); } return 0; } #ifdef HAVE_SYSV_COMPAT int config_parse_sysv_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { int *priority = data; int i, r; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = safe_atoi(rvalue, &i); if (r < 0 || i < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse SysV start priority, ignoring: %s", rvalue); return 0; } *priority = (int) i; return 0; } #endif DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode, "Failed to parse utmp mode"); DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode"); int config_parse_exec_mount_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { unsigned long flags = 0; ExecContext *c = data; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (streq(rvalue, "shared")) flags = MS_SHARED; else if (streq(rvalue, "slave")) flags = MS_SLAVE; else if (streq(rvalue, "private")) flags = MS_PRIVATE; else { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring.", rvalue); return 0; } c->mount_flags = flags; return 0; } int config_parse_exec_selinux_context( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; Unit *u = userdata; bool ignore; char *k; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { c->selinux_context = mfree(c->selinux_context); c->selinux_context_ignore = false; return 0; } if (rvalue[0] == '-') { ignore = true; rvalue++; } else ignore = false; r = unit_name_printf(u, rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m"); return 0; } free(c->selinux_context); c->selinux_context = k; c->selinux_context_ignore = ignore; return 0; } int config_parse_exec_apparmor_profile( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; Unit *u = userdata; bool ignore; char *k; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { c->apparmor_profile = mfree(c->apparmor_profile); c->apparmor_profile_ignore = false; return 0; } if (rvalue[0] == '-') { ignore = true; rvalue++; } else ignore = false; r = unit_name_printf(u, rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m"); return 0; } free(c->apparmor_profile); c->apparmor_profile = k; c->apparmor_profile_ignore = ignore; return 0; } int config_parse_exec_smack_process_label( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; Unit *u = userdata; bool ignore; char *k; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { c->smack_process_label = mfree(c->smack_process_label); c->smack_process_label_ignore = false; return 0; } if (rvalue[0] == '-') { ignore = true; rvalue++; } else ignore = false; r = unit_name_printf(u, rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m"); return 0; } free(c->smack_process_label); c->smack_process_label = k; c->smack_process_label_ignore = ignore; return 0; } int config_parse_timer(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Timer *t = data; usec_t u = 0; TimerValue *v; TimerBase b; CalendarSpec *c = NULL; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { /* Empty assignment resets list */ timer_free_values(t); return 0; } b = timer_base_from_string(lvalue); if (b < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse timer base, ignoring: %s", lvalue); return 0; } if (b == TIMER_CALENDAR) { if (calendar_spec_from_string(rvalue, &c) < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse calendar specification, ignoring: %s", rvalue); return 0; } } else { if (parse_sec(rvalue, &u) < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse timer value, ignoring: %s", rvalue); return 0; } } v = new0(TimerValue, 1); if (!v) { calendar_spec_free(c); return log_oom(); } v->base = b; v->value = u; v->calendar_spec = c; LIST_PREPEND(value, t->values, v); return 0; } int config_parse_trigger_unit( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *p = NULL; Unit *u = data; UnitType type; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (!set_isempty(u->dependencies[UNIT_TRIGGERS])) { log_syntax(unit, LOG_ERR, filename, line, 0, "Multiple units to trigger specified, ignoring: %s", rvalue); return 0; } r = unit_name_printf(u, rvalue, &p); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m"); return 0; } type = unit_name_to_type(p); if (type < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Unit type not valid, ignoring: %s", rvalue); return 0; } if (type == u->type) { log_syntax(unit, LOG_ERR, filename, line, 0, "Trigger cannot be of same type, ignoring: %s", rvalue); return 0; } r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p, NULL, true); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add trigger on %s, ignoring: %m", p); return 0; } return 0; } int config_parse_path_spec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Path *p = data; PathSpec *s; PathType b; _cleanup_free_ char *k = NULL; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { /* Empty assignment clears list */ path_free_specs(p); return 0; } b = path_type_from_string(lvalue); if (b < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse path type, ignoring: %s", lvalue); return 0; } r = unit_full_printf(UNIT(p), rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s. Ignoring.", rvalue); return 0; } if (!path_is_absolute(k)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Path is not absolute, ignoring: %s", k); return 0; } s = new0(PathSpec, 1); if (!s) return log_oom(); s->unit = UNIT(p); s->path = path_kill_slashes(k); k = NULL; s->type = b; s->inotify_fd = -1; LIST_PREPEND(spec, p->specs, s); return 0; } int config_parse_socket_service( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *p = NULL; Socket *s = data; Unit *x; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = unit_name_printf(UNIT(s), rvalue, &p); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue); return 0; } if (!endswith(p, ".service")) { log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type service, ignoring: %s", rvalue); return 0; } r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r)); return 0; } unit_ref_set(&s->service, x); return 0; } int config_parse_fdname( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *p = NULL; Socket *s = data; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { s->fdname = mfree(s->fdname); return 0; } r = unit_name_printf(UNIT(s), rvalue, &p); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue); return 0; } if (!fdname_is_valid(p)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name, ignoring: %s", p); return 0; } free(s->fdname); s->fdname = p; p = NULL; return 0; } int config_parse_service_sockets( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Service *s = data; const char *p; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); p = rvalue; for(;;) { _cleanup_free_ char *word = NULL, *k = NULL; r = extract_first_word(&p, &word, NULL, 0); if (r == 0) break; if (r == -ENOMEM) return log_oom(); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Trailing garbage in sockets, ignoring: %s", rvalue); break; } r = unit_name_printf(UNIT(s), word, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m"); continue; } if (!endswith(k, ".socket")) { log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type socket, ignoring: %s", k); continue; } r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, NULL, true); if (r < 0) log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k); r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, NULL, true); if (r < 0) log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k); } return 0; } int config_parse_bus_name( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *k = NULL; Unit *u = userdata; int r; assert(filename); assert(lvalue); assert(rvalue); assert(u); r = unit_full_printf(u, rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue); return 0; } if (!service_name_is_valid(k)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid bus name %s, ignoring.", k); return 0; } return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata); } int config_parse_service_timeout( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Service *s = userdata; usec_t usec; int r; assert(filename); assert(lvalue); assert(rvalue); assert(s); /* This is called for three cases: TimeoutSec=, TimeoutStopSec= and TimeoutStartSec=. */ r = parse_sec(rvalue, &usec); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue); return 0; } /* Traditionally, these options accepted 0 to disable the timeouts. However, a timeout of 0 suggests it happens * immediately, hence fix this to become USEC_INFINITY instead. This is in-line with how we internally handle * all other timeouts. */ if (usec <= 0) usec = USEC_INFINITY; if (!streq(lvalue, "TimeoutStopSec")) { s->start_timeout_defined = true; s->timeout_start_usec = usec; } if (!streq(lvalue, "TimeoutStartSec")) s->timeout_stop_usec = usec; return 0; } int config_parse_sec_fix_0( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { usec_t *usec = data; int r; assert(filename); assert(lvalue); assert(rvalue); assert(usec); /* This is pretty much like config_parse_sec(), except that this treats a time of 0 as infinity, for * compatibility with older versions of systemd where 0 instead of infinity was used as indicator to turn off a * timeout. */ r = parse_sec(rvalue, usec); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue); return 0; } if (*usec <= 0) *usec = USEC_INFINITY; return 0; } int config_parse_busname_service( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; BusName *n = data; int r; Unit *x; _cleanup_free_ char *p = NULL; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = unit_name_printf(UNIT(n), rvalue, &p); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue); return 0; } if (!endswith(p, ".service")) { log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type service, ignoring: %s", rvalue); return 0; } r = manager_load_unit(UNIT(n)->manager, p, NULL, &error, &x); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r)); return 0; } unit_ref_set(&n->service, x); return 0; } DEFINE_CONFIG_PARSE_ENUM(config_parse_bus_policy_world, bus_policy_access, BusPolicyAccess, "Failed to parse bus name policy access"); int config_parse_bus_policy( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ BusNamePolicy *p = NULL; _cleanup_free_ char *id_str = NULL; BusName *busname = data; char *access_str; assert(filename); assert(lvalue); assert(rvalue); assert(data); p = new0(BusNamePolicy, 1); if (!p) return log_oom(); if (streq(lvalue, "AllowUser")) p->type = BUSNAME_POLICY_TYPE_USER; else if (streq(lvalue, "AllowGroup")) p->type = BUSNAME_POLICY_TYPE_GROUP; else assert_not_reached("Unknown lvalue"); id_str = strdup(rvalue); if (!id_str) return log_oom(); access_str = strpbrk(id_str, WHITESPACE); if (!access_str) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid busname policy value '%s'", rvalue); return 0; } *access_str = '\0'; access_str++; access_str += strspn(access_str, WHITESPACE); p->access = bus_policy_access_from_string(access_str); if (p->access < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid busname policy access type '%s'", access_str); return 0; } p->name = id_str; id_str = NULL; LIST_PREPEND(policy, busname->policy, p); p = NULL; return 0; } int config_parse_bus_endpoint_policy( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *name = NULL; BusPolicyAccess access; ExecContext *c = data; char *access_str; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); name = strdup(rvalue); if (!name) return log_oom(); access_str = strpbrk(name, WHITESPACE); if (!access_str) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid endpoint policy value '%s'", rvalue); return 0; } *access_str = '\0'; access_str++; access_str += strspn(access_str, WHITESPACE); access = bus_policy_access_from_string(access_str); if (access <= _BUS_POLICY_ACCESS_INVALID || access >= _BUS_POLICY_ACCESS_MAX) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid endpoint policy access type '%s'", access_str); return 0; } if (!c->bus_endpoint) { r = bus_endpoint_new(&c->bus_endpoint); if (r < 0) return log_error_errno(r, "Failed to create bus endpoint object: %m"); } return bus_endpoint_add_policy(c->bus_endpoint, name, access); } int config_parse_working_directory( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; Unit *u = userdata; bool missing_ok; int r; assert(filename); assert(lvalue); assert(rvalue); assert(c); assert(u); if (rvalue[0] == '-') { missing_ok = true; rvalue++; } else missing_ok = false; if (streq(rvalue, "~")) { c->working_directory_home = true; c->working_directory = mfree(c->working_directory); } else { _cleanup_free_ char *k = NULL; r = unit_full_printf(u, rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in working directory path '%s', ignoring: %m", rvalue); return 0; } path_kill_slashes(k); if (!utf8_is_valid(k)) { log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); return 0; } if (!path_is_absolute(k)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Working directory path '%s' is not absolute, ignoring.", rvalue); return 0; } free(c->working_directory); c->working_directory = k; k = NULL; c->working_directory_home = false; } c->working_directory_missing_ok = missing_ok; return 0; } int config_parse_unit_env_file(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { char ***env = data; Unit *u = userdata; _cleanup_free_ char *n = NULL; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { /* Empty assignment frees the list */ *env = strv_free(*env); return 0; } r = unit_full_printf(u, rvalue, &n); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue); return 0; } if (!path_is_absolute(n[0] == '-' ? n + 1 : n)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Path '%s' is not absolute, ignoring.", n); return 0; } r = strv_extend(env, n); if (r < 0) return log_oom(); return 0; } int config_parse_environ(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Unit *u = userdata; char*** env = data; const char *word, *state; size_t l; _cleanup_free_ char *k = NULL; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { /* Empty assignment resets the list */ *env = strv_free(*env); return 0; } if (u) { r = unit_full_printf(u, rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue); return 0; } } if (!k) { k = strdup(rvalue); if (!k) return log_oom(); } FOREACH_WORD_QUOTED(word, l, k, state) { _cleanup_free_ char *n = NULL; char **x; r = cunescape_length(word, l, 0, &n); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Couldn't unescape assignment, ignoring: %s", rvalue); continue; } if (!env_assignment_is_valid(n)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid environment assignment, ignoring: %s", rvalue); continue; } x = strv_env_set(*env, n); if (!x) return log_oom(); strv_free(*env); *env = x; } if (!isempty(state)) log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); return 0; } int config_parse_pass_environ(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { const char *whole_rvalue = rvalue; char*** passenv = data; _cleanup_strv_free_ char **n = NULL; size_t nlen = 0, nbufsize = 0; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { /* Empty assignment resets the list */ *passenv = strv_free(*passenv); return 0; } for (;;) { _cleanup_free_ char *word = NULL; r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES); if (r == 0) break; if (r == -ENOMEM) return log_oom(); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Trailing garbage in %s, ignoring: %s", lvalue, whole_rvalue); break; } if (!env_name_is_valid(word)) { log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid environment name for %s, ignoring: %s", lvalue, word); continue; } if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) return log_oom(); n[nlen++] = word; n[nlen] = NULL; word = NULL; } if (n) { r = strv_extend_strv(passenv, n, true); if (r < 0) return r; } return 0; } int config_parse_ip_tos(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { int *ip_tos = data, x; assert(filename); assert(lvalue); assert(rvalue); assert(data); x = ip_tos_from_string(rvalue); if (x < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IP TOS value, ignoring: %s", rvalue); return 0; } *ip_tos = x; return 0; } int config_parse_unit_condition_path( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *p = NULL; Condition **list = data, *c; ConditionType t = ltype; bool trigger, negate; Unit *u = userdata; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { /* Empty assignment resets the list */ *list = condition_free_list(*list); return 0; } trigger = rvalue[0] == '|'; if (trigger) rvalue++; negate = rvalue[0] == '!'; if (negate) rvalue++; r = unit_full_printf(u, rvalue, &p); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue); return 0; } if (!path_is_absolute(p)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Path in condition not absolute, ignoring: %s", p); return 0; } c = condition_new(t, p, trigger, negate); if (!c) return log_oom(); LIST_PREPEND(conditions, *list, c); return 0; } int config_parse_unit_condition_string( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *s = NULL; Condition **list = data, *c; ConditionType t = ltype; bool trigger, negate; Unit *u = userdata; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { /* Empty assignment resets the list */ *list = condition_free_list(*list); return 0; } trigger = rvalue[0] == '|'; if (trigger) rvalue++; negate = rvalue[0] == '!'; if (negate) rvalue++; r = unit_full_printf(u, rvalue, &s); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue); return 0; } c = condition_new(t, s, trigger, negate); if (!c) return log_oom(); LIST_PREPEND(conditions, *list, c); return 0; } int config_parse_unit_condition_null( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Condition **list = data, *c; bool trigger, negate; int b; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { /* Empty assignment resets the list */ *list = condition_free_list(*list); return 0; } trigger = rvalue[0] == '|'; if (trigger) rvalue++; negate = rvalue[0] == '!'; if (negate) rvalue++; b = parse_boolean(rvalue); if (b < 0) { log_syntax(unit, LOG_ERR, filename, line, b, "Failed to parse boolean value in condition, ignoring: %s", rvalue); return 0; } if (!b) negate = !negate; c = condition_new(CONDITION_NULL, NULL, trigger, negate); if (!c) return log_oom(); LIST_PREPEND(conditions, *list, c); return 0; } DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier"); DEFINE_CONFIG_PARSE_ENUM(config_parse_failure_action, failure_action, FailureAction, "Failed to parse failure action specifier"); int config_parse_unit_requires_mounts_for( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Unit *u = userdata; const char *word, *state; size_t l; assert(filename); assert(lvalue); assert(rvalue); assert(data); FOREACH_WORD_QUOTED(word, l, rvalue, state) { int r; _cleanup_free_ char *n; n = strndup(word, l); if (!n) return log_oom(); if (!utf8_is_valid(n)) { log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); continue; } r = unit_require_mounts_for(u, n); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount for, ignoring: %s", rvalue); continue; } } if (!isempty(state)) log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); return 0; } int config_parse_documentation(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Unit *u = userdata; int r; char **a, **b; assert(filename); assert(lvalue); assert(rvalue); assert(u); if (isempty(rvalue)) { /* Empty assignment resets the list */ u->documentation = strv_free(u->documentation); return 0; } r = config_parse_unit_strv_printf(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata); if (r < 0) return r; for (a = b = u->documentation; a && *a; a++) { if (documentation_url_is_valid(*a)) *(b++) = *a; else { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid URL, ignoring: %s", *a); free(*a); } } if (b) *b = NULL; return r; } #ifdef HAVE_SECCOMP int config_parse_syscall_filter( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { static const char default_syscalls[] = "execve\0" "exit\0" "exit_group\0" "rt_sigreturn\0" "sigreturn\0"; ExecContext *c = data; Unit *u = userdata; bool invert = false; const char *word, *state; size_t l; int r; assert(filename); assert(lvalue); assert(rvalue); assert(u); if (isempty(rvalue)) { /* Empty assignment resets the list */ c->syscall_filter = set_free(c->syscall_filter); c->syscall_whitelist = false; return 0; } if (rvalue[0] == '~') { invert = true; rvalue++; } if (!c->syscall_filter) { c->syscall_filter = set_new(NULL); if (!c->syscall_filter) return log_oom(); if (invert) /* Allow everything but the ones listed */ c->syscall_whitelist = false; else { const char *i; /* Allow nothing but the ones listed */ c->syscall_whitelist = true; /* Accept default syscalls if we are on a whitelist */ NULSTR_FOREACH(i, default_syscalls) { int id; id = seccomp_syscall_resolve_name(i); if (id < 0) continue; r = set_put(c->syscall_filter, INT_TO_PTR(id + 1)); if (r == 0) continue; if (r < 0) return log_oom(); } } } FOREACH_WORD_QUOTED(word, l, rvalue, state) { _cleanup_free_ char *t = NULL; int id; t = strndup(word, l); if (!t) return log_oom(); id = seccomp_syscall_resolve_name(t); if (id < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse system call, ignoring: %s", t); continue; } /* If we previously wanted to forbid a syscall and now * we want to allow it, then remove it from the list */ if (!invert == c->syscall_whitelist) { r = set_put(c->syscall_filter, INT_TO_PTR(id + 1)); if (r == 0) continue; if (r < 0) return log_oom(); } else set_remove(c->syscall_filter, INT_TO_PTR(id + 1)); } if (!isempty(state)) log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); /* Turn on NNP, but only if it wasn't configured explicitly * before, and only if we are in user mode. */ if (!c->no_new_privileges_set && u->manager->running_as == MANAGER_USER) c->no_new_privileges = true; return 0; } int config_parse_syscall_archs( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Set **archs = data; const char *word, *state; size_t l; int r; if (isempty(rvalue)) { *archs = set_free(*archs); return 0; } r = set_ensure_allocated(archs, NULL); if (r < 0) return log_oom(); FOREACH_WORD_QUOTED(word, l, rvalue, state) { _cleanup_free_ char *t = NULL; uint32_t a; t = strndup(word, l); if (!t) return log_oom(); r = seccomp_arch_from_string(t, &a); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse system call architecture, ignoring: %s", t); continue; } r = set_put(*archs, UINT32_TO_PTR(a + 1)); if (r == 0) continue; if (r < 0) return log_oom(); } if (!isempty(state)) log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); return 0; } int config_parse_syscall_errno( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; int e; assert(filename); assert(lvalue); assert(rvalue); if (isempty(rvalue)) { /* Empty assignment resets to KILL */ c->syscall_errno = 0; return 0; } e = errno_from_name(rvalue); if (e < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse error number, ignoring: %s", rvalue); return 0; } c->syscall_errno = e; return 0; } int config_parse_address_families( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; bool invert = false; const char *word, *state; size_t l; int r; assert(filename); assert(lvalue); assert(rvalue); if (isempty(rvalue)) { /* Empty assignment resets the list */ c->address_families = set_free(c->address_families); c->address_families_whitelist = false; return 0; } if (rvalue[0] == '~') { invert = true; rvalue++; } if (!c->address_families) { c->address_families = set_new(NULL); if (!c->address_families) return log_oom(); c->address_families_whitelist = !invert; } FOREACH_WORD_QUOTED(word, l, rvalue, state) { _cleanup_free_ char *t = NULL; int af; t = strndup(word, l); if (!t) return log_oom(); af = af_from_name(t); if (af <= 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse address family, ignoring: %s", t); continue; } /* If we previously wanted to forbid an address family and now * we want to allow it, then remove it from the list */ if (!invert == c->address_families_whitelist) { r = set_put(c->address_families, INT_TO_PTR(af)); if (r == 0) continue; if (r < 0) return log_oom(); } else set_remove(c->address_families, INT_TO_PTR(af)); } if (!isempty(state)) log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); return 0; } #endif int config_parse_unit_slice( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *k = NULL; Unit *u = userdata, *slice = NULL; int r; assert(filename); assert(lvalue); assert(rvalue); assert(u); r = unit_name_printf(u, rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s. Ignoring.", rvalue); return 0; } r = manager_load_unit(u->manager, k, NULL, NULL, &slice); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load slice unit %s. Ignoring.", k); return 0; } r = unit_set_slice(u, slice); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to assign slice %s to unit %s. Ignoring.", slice->id, u->id); return 0; } return 0; } DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy"); int config_parse_cpu_shares( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { uint64_t *shares = data; int r; assert(filename); assert(lvalue); assert(rvalue); r = cg_cpu_shares_parse(rvalue, shares); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "CPU shares '%s' invalid. Ignoring.", rvalue); return 0; } return 0; } int config_parse_cpu_quota( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { CGroupContext *c = data; double percent; assert(filename); assert(lvalue); assert(rvalue); if (isempty(rvalue)) { c->cpu_quota_per_sec_usec = USEC_INFINITY; return 0; } if (!endswith(rvalue, "%")) { log_syntax(unit, LOG_ERR, filename, line, 0, "CPU quota '%s' not ending in '%%'. Ignoring.", rvalue); return 0; } if (sscanf(rvalue, "%lf%%", &percent) != 1 || percent <= 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "CPU quota '%s' invalid. Ignoring.", rvalue); return 0; } c->cpu_quota_per_sec_usec = (usec_t) (percent * USEC_PER_SEC / 100); return 0; } int config_parse_memory_limit( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { CGroupContext *c = data; uint64_t bytes; int r; if (isempty(rvalue) || streq(rvalue, "infinity")) { c->memory_limit = (uint64_t) -1; return 0; } r = parse_size(rvalue, 1024, &bytes); if (r < 0 || bytes < 1) { log_syntax(unit, LOG_ERR, filename, line, r, "Memory limit '%s' invalid. Ignoring.", rvalue); return 0; } c->memory_limit = bytes; return 0; } int config_parse_tasks_max( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { uint64_t *tasks_max = data, u; int r; if (isempty(rvalue) || streq(rvalue, "infinity")) { *tasks_max = (uint64_t) -1; return 0; } r = safe_atou64(rvalue, &u); if (r < 0 || u < 1) { log_syntax(unit, LOG_ERR, filename, line, r, "Maximum tasks value '%s' invalid. Ignoring.", rvalue); return 0; } *tasks_max = u; return 0; } int config_parse_device_allow( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *path = NULL; CGroupContext *c = data; CGroupDeviceAllow *a; const char *m; size_t n; if (isempty(rvalue)) { while (c->device_allow) cgroup_context_free_device_allow(c, c->device_allow); return 0; } n = strcspn(rvalue, WHITESPACE); path = strndup(rvalue, n); if (!path) return log_oom(); if (!startswith(path, "/dev/") && !startswith(path, "block-") && !startswith(path, "char-")) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path); return 0; } m = rvalue + n + strspn(rvalue + n, WHITESPACE); if (isempty(m)) m = "rwm"; if (!in_charset(m, "rwm")) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device rights '%s'. Ignoring.", m); return 0; } a = new0(CGroupDeviceAllow, 1); if (!a) return log_oom(); a->path = path; path = NULL; a->r = !!strchr(m, 'r'); a->w = !!strchr(m, 'w'); a->m = !!strchr(m, 'm'); LIST_PREPEND(device_allow, c->device_allow, a); return 0; } int config_parse_blockio_weight( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { uint64_t *weight = data; int r; assert(filename); assert(lvalue); assert(rvalue); r = cg_blkio_weight_parse(rvalue, weight); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Block IO weight '%s' invalid. Ignoring.", rvalue); return 0; } return 0; } int config_parse_blockio_device_weight( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *path = NULL; CGroupBlockIODeviceWeight *w; CGroupContext *c = data; const char *weight; uint64_t u; size_t n; int r; assert(filename); assert(lvalue); assert(rvalue); if (isempty(rvalue)) { while (c->blockio_device_weights) cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights); return 0; } n = strcspn(rvalue, WHITESPACE); weight = rvalue + n; weight += strspn(weight, WHITESPACE); if (isempty(weight)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Expected block device and device weight. Ignoring."); return 0; } path = strndup(rvalue, n); if (!path) return log_oom(); if (!path_startswith(path, "/dev")) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path); return 0; } r = cg_blkio_weight_parse(weight, &u); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Block IO weight '%s' invalid. Ignoring.", weight); return 0; } assert(u != CGROUP_BLKIO_WEIGHT_INVALID); w = new0(CGroupBlockIODeviceWeight, 1); if (!w) return log_oom(); w->path = path; path = NULL; w->weight = u; LIST_PREPEND(device_weights, c->blockio_device_weights, w); return 0; } int config_parse_blockio_bandwidth( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *path = NULL; CGroupBlockIODeviceBandwidth *b; CGroupContext *c = data; const char *bandwidth; uint64_t bytes; bool read; size_t n; int r; assert(filename); assert(lvalue); assert(rvalue); read = streq("BlockIOReadBandwidth", lvalue); if (isempty(rvalue)) { CGroupBlockIODeviceBandwidth *next; LIST_FOREACH_SAFE (device_bandwidths, b, next, c->blockio_device_bandwidths) if (b->read == read) cgroup_context_free_blockio_device_bandwidth(c, b); return 0; } n = strcspn(rvalue, WHITESPACE); bandwidth = rvalue + n; bandwidth += strspn(bandwidth, WHITESPACE); if (!*bandwidth) { log_syntax(unit, LOG_ERR, filename, line, 0, "Expected space separated pair of device node and bandwidth. Ignoring."); return 0; } path = strndup(rvalue, n); if (!path) return log_oom(); if (!path_startswith(path, "/dev")) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path); return 0; } r = parse_size(bandwidth, 1000, &bytes); if (r < 0 || bytes <= 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue); return 0; } b = new0(CGroupBlockIODeviceBandwidth, 1); if (!b) return log_oom(); b->path = path; path = NULL; b->bandwidth = bytes; b->read = read; LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, b); return 0; } DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode"); int config_parse_job_mode_isolate( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { JobMode *m = data; int r; assert(filename); assert(lvalue); assert(rvalue); r = parse_boolean(rvalue); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse boolean, ignoring: %s", rvalue); return 0; } *m = r ? JOB_ISOLATE : JOB_REPLACE; return 0; } int config_parse_runtime_directory( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { char***rt = data; Unit *u = userdata; const char *word, *state; size_t l; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { /* Empty assignment resets the list */ *rt = strv_free(*rt); return 0; } FOREACH_WORD_QUOTED(word, l, rvalue, state) { _cleanup_free_ char *t = NULL, *n = NULL; t = strndup(word, l); if (!t) return log_oom(); r = unit_name_printf(u, t, &n); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m"); continue; } if (!filename_is_valid(n)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Runtime directory is not valid, ignoring assignment: %s", rvalue); continue; } r = strv_push(rt, n); if (r < 0) return log_oom(); n = NULL; } if (!isempty(state)) log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); return 0; } int config_parse_set_status( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { size_t l; const char *word, *state; int r; ExitStatusSet *status_set = data; assert(filename); assert(lvalue); assert(rvalue); assert(data); /* Empty assignment resets the list */ if (isempty(rvalue)) { exit_status_set_free(status_set); return 0; } FOREACH_WORD(word, l, rvalue, state) { _cleanup_free_ char *temp; int val; Set **set; temp = strndup(word, l); if (!temp) return log_oom(); r = safe_atoi(temp, &val); if (r < 0) { val = signal_from_string_try_harder(temp); if (val <= 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse value, ignoring: %s", word); continue; } set = &status_set->signal; } else { if (val < 0 || val > 255) { log_syntax(unit, LOG_ERR, filename, line, 0, "Value %d is outside range 0-255, ignoring", val); continue; } set = &status_set->status; } r = set_ensure_allocated(set, NULL); if (r < 0) return log_oom(); r = set_put(*set, INT_TO_PTR(val)); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Unable to store: %s", word); return r; } } if (!isempty(state)) log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); return 0; } int config_parse_namespace_path_strv( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { char*** sv = data; const char *prev; const char *cur; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { /* Empty assignment resets the list */ *sv = strv_free(*sv); return 0; } prev = cur = rvalue; for (;;) { _cleanup_free_ char *word = NULL; int offset; r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES); if (r == 0) break; if (r == -ENOMEM) return log_oom(); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Trailing garbage, ignoring: %s", prev); return 0; } if (!utf8_is_valid(word)) { log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, word); prev = cur; continue; } offset = word[0] == '-'; if (!path_is_absolute(word + offset)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", word); prev = cur; continue; } path_kill_slashes(word + offset); r = strv_push(sv, word); if (r < 0) return log_oom(); prev = cur; word = NULL; } return 0; } int config_parse_no_new_privileges( const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; int k; assert(filename); assert(lvalue); assert(rvalue); assert(data); k = parse_boolean(rvalue); if (k < 0) { log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue); return 0; } c->no_new_privileges = !!k; c->no_new_privileges_set = true; return 0; } int config_parse_protect_home( const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; int k; assert(filename); assert(lvalue); assert(rvalue); assert(data); /* Our enum shall be a superset of booleans, hence first try * to parse as as boolean, and then as enum */ k = parse_boolean(rvalue); if (k > 0) c->protect_home = PROTECT_HOME_YES; else if (k == 0) c->protect_home = PROTECT_HOME_NO; else { ProtectHome h; h = protect_home_from_string(rvalue); if (h < 0){ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect home value, ignoring: %s", rvalue); return 0; } c->protect_home = h; } return 0; } int config_parse_protect_system( const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ExecContext *c = data; int k; assert(filename); assert(lvalue); assert(rvalue); assert(data); /* Our enum shall be a superset of booleans, hence first try * to parse as as boolean, and then as enum */ k = parse_boolean(rvalue); if (k > 0) c->protect_system = PROTECT_SYSTEM_YES; else if (k == 0) c->protect_system = PROTECT_SYSTEM_NO; else { ProtectSystem s; s = protect_system_from_string(rvalue); if (s < 0){ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect system value, ignoring: %s", rvalue); return 0; } c->protect_system = s; } return 0; } #define FOLLOW_MAX 8 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) { unsigned c = 0; int fd, r; FILE *f; char *id = NULL; assert(filename); assert(*filename); assert(_f); assert(names); /* This will update the filename pointer if the loaded file is * reached by a symlink. The old string will be freed. */ for (;;) { char *target, *name; if (c++ >= FOLLOW_MAX) return -ELOOP; path_kill_slashes(*filename); /* Add the file name we are currently looking at to * the names of this unit, but only if it is a valid * unit name. */ name = basename(*filename); if (unit_name_is_valid(name, UNIT_NAME_ANY)) { id = set_get(names, name); if (!id) { id = strdup(name); if (!id) return -ENOMEM; r = set_consume(names, id); if (r < 0) return r; } } /* Try to open the file name, but don't if its a symlink */ fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd >= 0) break; if (errno != ELOOP) return -errno; /* Hmm, so this is a symlink. Let's read the name, and follow it manually */ r = readlink_and_make_absolute(*filename, &target); if (r < 0) return r; free(*filename); *filename = target; } f = fdopen(fd, "re"); if (!f) { safe_close(fd); return -errno; } *_f = f; *_final = id; return 0; } static int merge_by_names(Unit **u, Set *names, const char *id) { char *k; int r; assert(u); assert(*u); assert(names); /* Let's try to add in all symlink names we found */ while ((k = set_steal_first(names))) { /* First try to merge in the other name into our * unit */ r = unit_merge_by_name(*u, k); if (r < 0) { Unit *other; /* Hmm, we couldn't merge the other unit into * ours? Then let's try it the other way * round */ other = manager_get_unit((*u)->manager, k); free(k); if (other) { r = unit_merge(other, *u); if (r >= 0) { *u = other; return merge_by_names(u, names, NULL); } } return r; } if (id == k) unit_choose_id(*u, id); free(k); } return 0; } static int load_from_path(Unit *u, const char *path) { int r; _cleanup_set_free_free_ Set *symlink_names = NULL; _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *filename = NULL; char *id = NULL; Unit *merged; struct stat st; assert(u); assert(path); symlink_names = set_new(&string_hash_ops); if (!symlink_names) return -ENOMEM; if (path_is_absolute(path)) { filename = strdup(path); if (!filename) return -ENOMEM; r = open_follow(&filename, &f, symlink_names, &id); if (r < 0) { filename = mfree(filename); if (r != -ENOENT) return r; } } else { char **p; STRV_FOREACH(p, u->manager->lookup_paths.unit_path) { /* Instead of opening the path right away, we manually * follow all symlinks and add their name to our unit * name set while doing so */ filename = path_make_absolute(path, *p); if (!filename) return -ENOMEM; if (u->manager->unit_path_cache && !set_get(u->manager->unit_path_cache, filename)) r = -ENOENT; else r = open_follow(&filename, &f, symlink_names, &id); if (r < 0) { filename = mfree(filename); if (r != -ENOENT) return r; /* Empty the symlink names for the next run */ set_clear_free(symlink_names); continue; } break; } } if (!filename) /* Hmm, no suitable file found? */ return 0; merged = u; r = merge_by_names(&merged, symlink_names, id); if (r < 0) return r; if (merged != u) { u->load_state = UNIT_MERGED; return 0; } if (fstat(fileno(f), &st) < 0) return -errno; if (null_or_empty(&st)) u->load_state = UNIT_MASKED; else { u->load_state = UNIT_LOADED; /* Now, parse the file contents */ r = config_parse(u->id, filename, f, UNIT_VTABLE(u)->sections, config_item_perf_lookup, load_fragment_gperf_lookup, false, true, false, u); if (r < 0) return r; } free(u->fragment_path); u->fragment_path = filename; filename = NULL; u->fragment_mtime = timespec_load(&st.st_mtim); if (u->source_path) { if (stat(u->source_path, &st) >= 0) u->source_mtime = timespec_load(&st.st_mtim); else u->source_mtime = 0; } return 0; } int unit_load_fragment(Unit *u) { int r; Iterator i; const char *t; assert(u); assert(u->load_state == UNIT_STUB); assert(u->id); if (u->transient) { u->load_state = UNIT_LOADED; return 0; } /* First, try to find the unit under its id. We always look * for unit files in the default directories, to make it easy * to override things by placing things in /etc/systemd/system */ r = load_from_path(u, u->id); if (r < 0) return r; /* Try to find an alias we can load this with */ if (u->load_state == UNIT_STUB) { SET_FOREACH(t, u->names, i) { if (t == u->id) continue; r = load_from_path(u, t); if (r < 0) return r; if (u->load_state != UNIT_STUB) break; } } /* And now, try looking for it under the suggested (originally linked) path */ if (u->load_state == UNIT_STUB && u->fragment_path) { r = load_from_path(u, u->fragment_path); if (r < 0) return r; if (u->load_state == UNIT_STUB) /* Hmm, this didn't work? Then let's get rid * of the fragment path stored for us, so that * we don't point to an invalid location. */ u->fragment_path = mfree(u->fragment_path); } /* Look for a template */ if (u->load_state == UNIT_STUB && u->instance) { _cleanup_free_ char *k = NULL; r = unit_name_template(u->id, &k); if (r < 0) return r; r = load_from_path(u, k); if (r < 0) return r; if (u->load_state == UNIT_STUB) { SET_FOREACH(t, u->names, i) { _cleanup_free_ char *z = NULL; if (t == u->id) continue; r = unit_name_template(t, &z); if (r < 0) return r; r = load_from_path(u, z); if (r < 0) return r; if (u->load_state != UNIT_STUB) break; } } } return 0; } void unit_dump_config_items(FILE *f) { static const struct { const ConfigParserCallback callback; const char *rvalue; } table[] = { #if !defined(HAVE_SYSV_COMPAT) || !defined(HAVE_SECCOMP) || !defined(HAVE_PAM) || !defined(HAVE_SELINUX) || !defined(HAVE_SMACK) || !defined(HAVE_APPARMOR) { config_parse_warn_compat, "NOTSUPPORTED" }, #endif { config_parse_int, "INTEGER" }, { config_parse_unsigned, "UNSIGNED" }, { config_parse_iec_size, "SIZE" }, { config_parse_iec_uint64, "SIZE" }, { config_parse_si_size, "SIZE" }, { config_parse_bool, "BOOLEAN" }, { config_parse_string, "STRING" }, { config_parse_path, "PATH" }, { config_parse_unit_path_printf, "PATH" }, { config_parse_strv, "STRING [...]" }, { config_parse_exec_nice, "NICE" }, { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" }, { config_parse_exec_io_class, "IOCLASS" }, { config_parse_exec_io_priority, "IOPRIORITY" }, { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" }, { config_parse_exec_cpu_sched_prio, "CPUSCHEDPRIO" }, { config_parse_exec_cpu_affinity, "CPUAFFINITY" }, { config_parse_mode, "MODE" }, { config_parse_unit_env_file, "FILE" }, { config_parse_output, "OUTPUT" }, { config_parse_input, "INPUT" }, { config_parse_log_facility, "FACILITY" }, { config_parse_log_level, "LEVEL" }, { config_parse_exec_capabilities, "CAPABILITIES" }, { config_parse_exec_secure_bits, "SECUREBITS" }, { config_parse_capability_set, "BOUNDINGSET" }, { config_parse_limit, "LIMIT" }, { config_parse_unit_deps, "UNIT [...]" }, { config_parse_exec, "PATH [ARGUMENT [...]]" }, { config_parse_service_type, "SERVICETYPE" }, { config_parse_service_restart, "SERVICERESTART" }, #ifdef HAVE_SYSV_COMPAT { config_parse_sysv_priority, "SYSVPRIORITY" }, #endif { config_parse_kill_mode, "KILLMODE" }, { config_parse_signal, "SIGNAL" }, { config_parse_socket_listen, "SOCKET [...]" }, { config_parse_socket_bind, "SOCKETBIND" }, { config_parse_socket_bindtodevice, "NETWORKINTERFACE" }, { config_parse_sec, "SECONDS" }, { config_parse_nsec, "NANOSECONDS" }, { config_parse_namespace_path_strv, "PATH [...]" }, { config_parse_unit_requires_mounts_for, "PATH [...]" }, { config_parse_exec_mount_flags, "MOUNTFLAG [...]" }, { config_parse_unit_string_printf, "STRING" }, { config_parse_trigger_unit, "UNIT" }, { config_parse_timer, "TIMER" }, { config_parse_path_spec, "PATH" }, { config_parse_notify_access, "ACCESS" }, { config_parse_ip_tos, "TOS" }, { config_parse_unit_condition_path, "CONDITION" }, { config_parse_unit_condition_string, "CONDITION" }, { config_parse_unit_condition_null, "CONDITION" }, { config_parse_unit_slice, "SLICE" }, { config_parse_documentation, "URL" }, { config_parse_service_timeout, "SECONDS" }, { config_parse_failure_action, "ACTION" }, { config_parse_set_status, "STATUS" }, { config_parse_service_sockets, "SOCKETS" }, { config_parse_environ, "ENVIRON" }, #ifdef HAVE_SECCOMP { config_parse_syscall_filter, "SYSCALLS" }, { config_parse_syscall_archs, "ARCHS" }, { config_parse_syscall_errno, "ERRNO" }, { config_parse_address_families, "FAMILIES" }, #endif { config_parse_cpu_shares, "SHARES" }, { config_parse_memory_limit, "LIMIT" }, { config_parse_device_allow, "DEVICE" }, { config_parse_device_policy, "POLICY" }, { config_parse_blockio_bandwidth, "BANDWIDTH" }, { config_parse_blockio_weight, "WEIGHT" }, { config_parse_blockio_device_weight, "DEVICEWEIGHT" }, { config_parse_long, "LONG" }, { config_parse_socket_service, "SERVICE" }, #ifdef HAVE_SELINUX { config_parse_exec_selinux_context, "LABEL" }, #endif { config_parse_job_mode, "MODE" }, { config_parse_job_mode_isolate, "BOOLEAN" }, { config_parse_personality, "PERSONALITY" }, }; const char *prev = NULL; const char *i; assert(f); NULSTR_FOREACH(i, load_fragment_gperf_nulstr) { const char *rvalue = "OTHER", *lvalue; unsigned j; size_t prefix_len; const char *dot; const ConfigPerfItem *p; assert_se(p = load_fragment_gperf_lookup(i, strlen(i))); dot = strchr(i, '.'); lvalue = dot ? dot + 1 : i; prefix_len = dot-i; if (dot) if (!prev || !strneq(prev, i, prefix_len+1)) { if (prev) fputc('\n', f); fprintf(f, "[%.*s]\n", (int) prefix_len, i); } for (j = 0; j < ELEMENTSOF(table); j++) if (p->parse == table[j].callback) { rvalue = table[j].rvalue; break; } fprintf(f, "%s=%s\n", lvalue, rvalue); prev = i; } } systemd-229/src/core/load-fragment.h000066400000000000000000000443661265713322000175060ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "unit.h" /* Read service data from .desktop file style configuration fragments */ int unit_load_fragment(Unit *u); void unit_dump_config_items(FILE *f); int config_parse_warn_compat(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_unit_deps(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_obsolete_unit_deps(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_unit_string_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_unit_strv_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_unit_path_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_unit_path_strv_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_documentation(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_socket_listen(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_socket_protocol(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_socket_bind(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_nice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_oom_score_adjust(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_service_timeout(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_service_type(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_service_restart(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_socket_bindtodevice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_output(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_input(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_io_class(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_io_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_cpu_sched_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_cpu_sched_prio(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_cpu_affinity(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_capabilities(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_secure_bits(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_capability_set(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_sysv_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_kill_signal(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_mount_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_timer(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_trigger_unit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_path_spec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_socket_service(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_service_sockets(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_busname_service(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bus_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bus_policy_world(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bus_endpoint_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_unit_env_file(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_ip_tos(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_unit_condition_path(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_unit_condition_string(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_unit_condition_null(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_kill_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_notify_access(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_failure_action(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_unit_requires_mounts_for(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_syscall_filter(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_syscall_archs(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_syscall_errno(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_environ(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_pass_environ(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_unit_slice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_cpu_shares(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_memory_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_tasks_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_device_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_device_allow(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_blockio_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_blockio_device_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_blockio_bandwidth(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_netclass(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_job_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_job_mode_isolate(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_selinux_context(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_apparmor_profile(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_smack_process_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_address_families(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_runtime_directory(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_set_status(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_namespace_path_strv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_no_new_privileges(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_cpu_quota(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_protect_home(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_protect_system(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bus_name(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_exec_utmp_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_working_directory(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_fdname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_sec_fix_0(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); /* gperf prototypes */ const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, unsigned length); extern const char load_fragment_gperf_nulstr[]; typedef enum Disabled { DISABLED_CONFIGURATION, DISABLED_LEGACY, DISABLED_EXPERIMENTAL, } Disabled; systemd-229/src/core/locale-setup.c000066400000000000000000000122541265713322000173450ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "env-util.h" #include "fileio.h" #include "locale-setup.h" #include "locale-util.h" #include "string-util.h" #include "strv.h" #include "util.h" #include "virt.h" int locale_setup(char ***environment) { char **add; char *variables[_VARIABLE_LC_MAX] = {}; int r = 0, i; if (detect_container() <= 0) { r = parse_env_file("/proc/cmdline", WHITESPACE, "locale.LANG", &variables[VARIABLE_LANG], "locale.LANGUAGE", &variables[VARIABLE_LANGUAGE], "locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE], "locale.LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC], "locale.LC_TIME", &variables[VARIABLE_LC_TIME], "locale.LC_COLLATE", &variables[VARIABLE_LC_COLLATE], "locale.LC_MONETARY", &variables[VARIABLE_LC_MONETARY], "locale.LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES], "locale.LC_PAPER", &variables[VARIABLE_LC_PAPER], "locale.LC_NAME", &variables[VARIABLE_LC_NAME], "locale.LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS], "locale.LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE], "locale.LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT], "locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION], NULL); if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to read /proc/cmdline: %m"); } /* Hmm, nothing set on the kernel cmd line? Then let's * try /etc/locale.conf */ if (r <= 0) { r = parse_env_file("/etc/locale.conf", NEWLINE, "LANG", &variables[VARIABLE_LANG], "LANGUAGE", &variables[VARIABLE_LANGUAGE], "LC_CTYPE", &variables[VARIABLE_LC_CTYPE], "LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC], "LC_TIME", &variables[VARIABLE_LC_TIME], "LC_COLLATE", &variables[VARIABLE_LC_COLLATE], "LC_MONETARY", &variables[VARIABLE_LC_MONETARY], "LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES], "LC_PAPER", &variables[VARIABLE_LC_PAPER], "LC_NAME", &variables[VARIABLE_LC_NAME], "LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS], "LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE], "LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT], "LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION], NULL); if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to read /etc/locale.conf: %m"); } add = NULL; for (i = 0; i < _VARIABLE_LC_MAX; i++) { char *s; if (!variables[i]) continue; s = strjoin(locale_variable_to_string(i), "=", variables[i], NULL); if (!s) { r = -ENOMEM; goto finish; } if (strv_consume(&add, s) < 0) { r = -ENOMEM; goto finish; } } if (!strv_isempty(add)) { char **e; e = strv_env_merge(2, *environment, add); if (!e) { r = -ENOMEM; goto finish; } strv_free(*environment); *environment = e; } r = 0; finish: strv_free(add); for (i = 0; i < _VARIABLE_LC_MAX; i++) free(variables[i]); return r; } systemd-229/src/core/locale-setup.h000066400000000000000000000014041265713322000173450ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int locale_setup(char ***environment); systemd-229/src/core/loopback-setup.c000066400000000000000000000050621265713322000176770ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-netlink.h" #include "loopback-setup.h" #include "missing.h" #include "netlink-util.h" static int start_loopback(sd_netlink *rtnl) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; r = sd_rtnl_message_new_link(rtnl, &req, RTM_SETLINK, LOOPBACK_IFINDEX); if (r < 0) return r; r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP); if (r < 0) return r; r = sd_netlink_call(rtnl, req, 0, NULL); if (r < 0) return r; return 0; } static bool check_loopback(sd_netlink *rtnl) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; unsigned flags; int r; r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, LOOPBACK_IFINDEX); if (r < 0) return false; r = sd_netlink_call(rtnl, req, 0, &reply); if (r < 0) return false; r = sd_rtnl_message_link_get_flags(reply, &flags); if (r < 0) return false; return flags & IFF_UP; } int loopback_setup(void) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; int r; r = sd_netlink_open(&rtnl); if (r < 0) return r; r = start_loopback(rtnl); if (r < 0) { /* If we lack the permissions to configure the * loopback device, but we find it to be already * configured, let's exit cleanly, in order to * supported unprivileged containers. */ if (r == -EPERM && check_loopback(rtnl)) return 0; return log_warning_errno(r, "Failed to configure loopback device: %m"); } return 0; } systemd-229/src/core/loopback-setup.h000066400000000000000000000013671265713322000177100ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int loopback_setup(void); systemd-229/src/core/machine-id-setup.c000066400000000000000000000316051265713322000201050ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "sd-id128.h" #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "hexdecoct.h" #include "io-util.h" #include "log.h" #include "machine-id-setup.h" #include "macro.h" #include "mkdir.h" #include "mount-util.h" #include "path-util.h" #include "process-util.h" #include "stat-util.h" #include "string-util.h" #include "umask-util.h" #include "util.h" #include "virt.h" static int shorten_uuid(char destination[34], const char source[36]) { unsigned i, j; assert(destination); assert(source); /* Converts a UUID into a machine ID, by lowercasing it and * removing dashes. Validates everything. */ for (i = 0, j = 0; i < 36 && j < 32; i++) { int t; t = unhexchar(source[i]); if (t < 0) continue; destination[j++] = hexchar(t); } if (i != 36 || j != 32) return -EINVAL; destination[32] = '\n'; destination[33] = 0; return 0; } static int read_machine_id(int fd, char id[34]) { char id_to_validate[34]; int r; assert(fd >= 0); assert(id); /* Reads a machine ID from a file, validates it, and returns * it. The returned ID ends in a newline. */ r = loop_read_exact(fd, id_to_validate, 33, false); if (r < 0) return r; if (id_to_validate[32] != '\n') return -EINVAL; id_to_validate[32] = 0; if (!id128_is_valid(id_to_validate)) return -EINVAL; memcpy(id, id_to_validate, 32); id[32] = '\n'; id[33] = 0; return 0; } static int write_machine_id(int fd, char id[34]) { assert(fd >= 0); assert(id); if (lseek(fd, 0, SEEK_SET) < 0) return -errno; return loop_write(fd, id, 33, false); } static int generate_machine_id(char id[34], const char *root) { int fd, r; unsigned char *p; sd_id128_t buf; char *q; const char *dbus_machine_id; assert(id); if (isempty(root)) dbus_machine_id = "/var/lib/dbus/machine-id"; else dbus_machine_id = strjoina(root, "/var/lib/dbus/machine-id"); /* First, try reading the D-Bus machine id, unless it is a symlink */ fd = open(dbus_machine_id, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd >= 0) { r = read_machine_id(fd, id); safe_close(fd); if (r >= 0) { log_info("Initializing machine ID from D-Bus machine ID."); return 0; } } if (isempty(root)) { /* If that didn't work, see if we are running in a container, * and a machine ID was passed in via $container_uuid the way * libvirt/LXC does it */ if (detect_container() > 0) { _cleanup_free_ char *e = NULL; r = getenv_for_pid(1, "container_uuid", &e); if (r > 0) { r = shorten_uuid(id, e); if (r >= 0) { log_info("Initializing machine ID from container UUID."); return 0; } } } else if (detect_vm() == VIRTUALIZATION_KVM) { /* If we are not running in a container, see if we are * running in qemu/kvm and a machine ID was passed in * via -uuid on the qemu/kvm command line */ char uuid[36]; fd = open("/sys/class/dmi/id/product_uuid", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd >= 0) { r = loop_read_exact(fd, uuid, 36, false); safe_close(fd); if (r >= 0) { r = shorten_uuid(id, uuid); if (r >= 0) { log_info("Initializing machine ID from KVM UUID."); return 0; } } } } } /* If that didn't work, generate a random machine id */ r = sd_id128_randomize(&buf); if (r < 0) return log_error_errno(r, "Failed to open /dev/urandom: %m"); for (p = buf.bytes, q = id; p < buf.bytes + sizeof(buf); p++, q += 2) { q[0] = hexchar(*p >> 4); q[1] = hexchar(*p & 15); } id[32] = '\n'; id[33] = 0; log_info("Initializing machine ID from random generator."); return 0; } int machine_id_setup(const char *root, sd_id128_t machine_id) { const char *etc_machine_id, *run_machine_id; _cleanup_close_ int fd = -1; bool writable = true; char id[34]; /* 32 + \n + \0 */ int r; if (isempty(root)) { etc_machine_id = "/etc/machine-id"; run_machine_id = "/run/machine-id"; } else { char *x; x = strjoina(root, "/etc/machine-id"); etc_machine_id = path_kill_slashes(x); x = strjoina(root, "/run/machine-id"); run_machine_id = path_kill_slashes(x); } RUN_WITH_UMASK(0000) { /* We create this 0444, to indicate that this isn't really * something you should ever modify. Of course, since the file * will be owned by root it doesn't matter much, but maybe * people look. */ mkdir_parents(etc_machine_id, 0755); fd = open(etc_machine_id, O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY, 0444); if (fd < 0) { int old_errno = errno; fd = open(etc_machine_id, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) { if (old_errno == EROFS && errno == ENOENT) log_error_errno(errno, "System cannot boot: Missing /etc/machine-id and /etc is mounted read-only.\n" "Booting up is supported only when:\n" "1) /etc/machine-id exists and is populated.\n" "2) /etc/machine-id exists and is empty.\n" "3) /etc/machine-id is missing and /etc is writable.\n"); else log_error_errno(errno, "Cannot open %s: %m", etc_machine_id); return -errno; } writable = false; } } /* A machine id argument overrides all other machined-ids */ if (!sd_id128_is_null(machine_id)) { sd_id128_to_string(machine_id, id); id[32] = '\n'; id[33] = 0; } else { if (read_machine_id(fd, id) >= 0) return 0; /* Hmm, so, the id currently stored is not useful, then let's * generate one */ r = generate_machine_id(id, root); if (r < 0) return r; } if (writable) if (write_machine_id(fd, id) >= 0) return 0; fd = safe_close(fd); /* Hmm, we couldn't write it? So let's write it to * /run/machine-id as a replacement */ RUN_WITH_UMASK(0022) { r = write_string_file(run_machine_id, id, WRITE_STRING_FILE_CREATE); } if (r < 0) { (void) unlink(run_machine_id); return log_error_errno(r, "Cannot write %s: %m", run_machine_id); } /* And now, let's mount it over */ if (mount(run_machine_id, etc_machine_id, NULL, MS_BIND, NULL) < 0) { (void) unlink_noerrno(run_machine_id); return log_error_errno(errno, "Failed to mount %s: %m", etc_machine_id); } log_info("Installed transient %s file.", etc_machine_id); /* Mark the mount read-only */ if (mount(NULL, etc_machine_id, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL) < 0) log_warning_errno(errno, "Failed to make transient %s read-only: %m", etc_machine_id); return 0; } int machine_id_commit(const char *root) { _cleanup_close_ int fd = -1, initial_mntns_fd = -1; const char *etc_machine_id; char id[34]; /* 32 + \n + \0 */ int r; if (isempty(root)) etc_machine_id = "/etc/machine-id"; else { char *x; x = strjoina(root, "/etc/machine-id"); etc_machine_id = path_kill_slashes(x); } r = path_is_mount_point(etc_machine_id, 0); if (r < 0) return log_error_errno(r, "Failed to determine whether %s is a mount point: %m", etc_machine_id); if (r == 0) { log_debug("%s is is not a mount point. Nothing to do.", etc_machine_id); return 0; } /* Read existing machine-id */ fd = open(etc_machine_id, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return log_error_errno(errno, "Cannot open %s: %m", etc_machine_id); r = read_machine_id(fd, id); if (r < 0) return log_error_errno(r, "We didn't find a valid machine ID in %s.", etc_machine_id); r = fd_is_temporary_fs(fd); if (r < 0) return log_error_errno(r, "Failed to determine whether %s is on a temporary file system: %m", etc_machine_id); if (r == 0) { log_error("%s is not on a temporary file system.", etc_machine_id); return -EROFS; } fd = safe_close(fd); /* Store current mount namespace */ r = namespace_open(0, NULL, &initial_mntns_fd, NULL, NULL, NULL); if (r < 0) return log_error_errno(r, "Can't fetch current mount namespace: %m"); /* Switch to a new mount namespace, isolate ourself and unmount etc_machine_id in our new namespace */ if (unshare(CLONE_NEWNS) < 0) return log_error_errno(errno, "Failed to enter new namespace: %m"); if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) return log_error_errno(errno, "Couldn't make-rslave / mountpoint in our private namespace: %m"); if (umount(etc_machine_id) < 0) return log_error_errno(errno, "Failed to unmount transient %s file in our private namespace: %m", etc_machine_id); /* Update a persistent version of etc_machine_id */ fd = open(etc_machine_id, O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY, 0444); if (fd < 0) return log_error_errno(errno, "Cannot open for writing %s. This is mandatory to get a persistent machine-id: %m", etc_machine_id); r = write_machine_id(fd, id); if (r < 0) return log_error_errno(r, "Cannot write %s: %m", etc_machine_id); fd = safe_close(fd); /* Return to initial namespace and proceed a lazy tmpfs unmount */ r = namespace_enter(-1, initial_mntns_fd, -1, -1, -1); if (r < 0) return log_warning_errno(r, "Failed to switch back to initial mount namespace: %m.\nWe'll keep transient %s file until next reboot.", etc_machine_id); if (umount2(etc_machine_id, MNT_DETACH) < 0) return log_warning_errno(errno, "Failed to unmount transient %s file: %m.\nWe keep that mount until next reboot.", etc_machine_id); return 0; } systemd-229/src/core/machine-id-setup.h000066400000000000000000000015051265713322000201060ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int machine_id_commit(const char *root); int machine_id_setup(const char *root, sd_id128_t machine_id); systemd-229/src/core/macros.systemd.in000066400000000000000000000052761265713322000201150ustar00rootroot00000000000000# -*- Mode: rpm-spec; indent-tabs-mode: nil -*- */ # # This file is part of systemd. # # Copyright 2012 Lennart Poettering # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # RPM macros for packages installing systemd unit files %_unitdir @systemunitdir@ %_userunitdir @userunitdir@ %_presetdir @systempresetdir@ %_udevhwdbdir @udevhwdbdir@ %_udevrulesdir @udevrulesdir@ %_journalcatalogdir @catalogdir@ %_tmpfilesdir @tmpfilesdir@ %_sysusersdir @sysusersdir@ %_sysctldir @sysctldir@ %_binfmtdir @binfmtdir@ %systemd_requires \ Requires(post): systemd \ Requires(preun): systemd \ Requires(postun): systemd \ %{nil} %systemd_post() \ if [ $1 -eq 1 ] ; then \ # Initial installation \ systemctl --no-reload preset %{?*} >/dev/null 2>&1 || : \ fi \ %{nil} %systemd_user_post() %{expand:%systemd_post \\--user \\--global %%{?*}} %systemd_preun() \ if [ $1 -eq 0 ] ; then \ # Package removal, not upgrade \ systemctl --no-reload disable --now %{?*} > /dev/null 2>&1 || : \ fi \ %{nil} %systemd_user_preun() \ if [ $1 -eq 0 ] ; then \ # Package removal, not upgrade \ systemctl --no-reload --user --global disable %{?*} > /dev/null 2>&1 || : \ fi \ %{nil} %systemd_postun() %{nil} %systemd_user_postun() %{nil} %systemd_postun_with_restart() \ if [ $1 -ge 1 ] ; then \ # Package upgrade, not uninstall \ systemctl try-restart %{?*} >/dev/null 2>&1 || : \ fi \ %{nil} %systemd_user_postun_with_restart() %{nil} %udev_hwdb_update() \ udevadm hwdb --update >/dev/null 2>&1 || : \ %{nil} %udev_rules_update() \ udevadm control --reload >/dev/null 2>&1 || : \ %{nil} %journal_catalog_update() \ journalctl --update-catalog >/dev/null 2>&1 || : \ %{nil} %tmpfiles_create() \ systemd-tmpfiles --create %{?*} >/dev/null 2>&1 || : \ %{nil} %sysusers_create() \ systemd-sysusers %{?*} >/dev/null 2>&1 || : \ %{nil} %sysusers_create_inline() \ echo %{?*} | systemd-sysusers - >/dev/null 2>&1 || : \ %{nil} %sysctl_apply() \ @rootlibexecdir@/systemd-sysctl %{?*} >/dev/null 2>&1 || : \ %{nil} %binfmt_apply() \ @rootlibexecdir@/systemd-binfmt %{?*} >/dev/null 2>&1 || : \ %{nil} systemd-229/src/core/main.c000066400000000000000000002556231265713322000157050ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SECCOMP #include #endif #ifdef HAVE_VALGRIND_VALGRIND_H #include #endif #include "sd-bus.h" #include "sd-daemon.h" #include "alloc-util.h" #include "architecture.h" #include "build.h" #include "bus-error.h" #include "bus-util.h" #include "capability-util.h" #include "clock-util.h" #include "conf-parser.h" #include "cpu-set-util.h" #include "dbus-manager.h" #include "def.h" #include "env-util.h" #include "fd-util.h" #include "fdset.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "hostname-setup.h" #include "ima-setup.h" #include "killall.h" #include "kmod-setup.h" #include "load-fragment.h" #include "log.h" #include "loopback-setup.h" #include "machine-id-setup.h" #include "manager.h" #include "missing.h" #include "mount-setup.h" #include "pager.h" #include "parse-util.h" #include "proc-cmdline.h" #include "process-util.h" #include "rlimit-util.h" #include "selinux-setup.h" #include "selinux-util.h" #include "signal-util.h" #include "smack-setup.h" #include "special.h" #include "stat-util.h" #include "stdio-util.h" #include "strv.h" #include "switch-root.h" #include "terminal-util.h" #include "user-util.h" #include "virt.h" #include "watchdog.h" static enum { ACTION_RUN, ACTION_HELP, ACTION_VERSION, ACTION_TEST, ACTION_DUMP_CONFIGURATION_ITEMS, ACTION_DONE } arg_action = ACTION_RUN; static char *arg_default_unit = NULL; static ManagerRunningAs arg_running_as = _MANAGER_RUNNING_AS_INVALID; static bool arg_dump_core = true; static int arg_crash_chvt = -1; static bool arg_crash_shell = false; static bool arg_crash_reboot = false; static bool arg_confirm_spawn = false; static ShowStatus arg_show_status = _SHOW_STATUS_UNSET; static bool arg_switched_root = false; static int arg_no_pager = -1; static char ***arg_join_controllers = NULL; static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL; static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT; static usec_t arg_default_restart_usec = DEFAULT_RESTART_USEC; static usec_t arg_default_timeout_start_usec = DEFAULT_TIMEOUT_USEC; static usec_t arg_default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC; static usec_t arg_default_start_limit_interval = DEFAULT_START_LIMIT_INTERVAL; static unsigned arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST; static usec_t arg_runtime_watchdog = 0; static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE; static char **arg_default_environment = NULL; static struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {}; static uint64_t arg_capability_bounding_set = CAP_ALL; static nsec_t arg_timer_slack_nsec = NSEC_INFINITY; static usec_t arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE; static Set* arg_syscall_archs = NULL; static FILE* arg_serialization = NULL; static bool arg_default_cpu_accounting = false; static bool arg_default_blockio_accounting = false; static bool arg_default_memory_accounting = false; static bool arg_default_tasks_accounting = true; static uint64_t arg_default_tasks_max = UINT64_C(512); static sd_id128_t arg_machine_id = {}; static void pager_open_if_enabled(void) { if (arg_no_pager <= 0) return; pager_open(false); } noreturn static void freeze_or_reboot(void) { if (arg_crash_reboot) { log_notice("Rebooting in 10s..."); (void) sleep(10); log_notice("Rebooting now..."); (void) reboot(RB_AUTOBOOT); log_emergency_errno(errno, "Failed to reboot: %m"); } log_emergency("Freezing execution."); freeze(); } noreturn static void crash(int sig) { struct sigaction sa; pid_t pid; if (getpid() != 1) /* Pass this on immediately, if this is not PID 1 */ (void) raise(sig); else if (!arg_dump_core) log_emergency("Caught <%s>, not dumping core.", signal_to_string(sig)); else { sa = (struct sigaction) { .sa_handler = nop_signal_handler, .sa_flags = SA_NOCLDSTOP|SA_RESTART, }; /* We want to wait for the core process, hence let's enable SIGCHLD */ (void) sigaction(SIGCHLD, &sa, NULL); pid = raw_clone(SIGCHLD, NULL); if (pid < 0) log_emergency_errno(errno, "Caught <%s>, cannot fork for core dump: %m", signal_to_string(sig)); else if (pid == 0) { /* Enable default signal handler for core dump */ sa = (struct sigaction) { .sa_handler = SIG_DFL, }; (void) sigaction(sig, &sa, NULL); /* Don't limit the coredump size */ (void) setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY)); /* Just to be sure... */ (void) chdir("/"); /* Raise the signal again */ pid = raw_getpid(); (void) kill(pid, sig); /* raise() would kill the parent */ assert_not_reached("We shouldn't be here..."); _exit(EXIT_FAILURE); } else { siginfo_t status; int r; /* Order things nicely. */ r = wait_for_terminate(pid, &status); if (r < 0) log_emergency_errno(r, "Caught <%s>, waitpid() failed: %m", signal_to_string(sig)); else if (status.si_code != CLD_DUMPED) log_emergency("Caught <%s>, core dump failed (child "PID_FMT", code=%s, status=%i/%s).", signal_to_string(sig), pid, sigchld_code_to_string(status.si_code), status.si_status, strna(status.si_code == CLD_EXITED ? exit_status_to_string(status.si_status, EXIT_STATUS_FULL) : signal_to_string(status.si_status))); else log_emergency("Caught <%s>, dumped core as pid "PID_FMT".", signal_to_string(sig), pid); } } if (arg_crash_chvt >= 0) (void) chvt(arg_crash_chvt); sa = (struct sigaction) { .sa_handler = SIG_IGN, .sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART, }; /* Let the kernel reap children for us */ (void) sigaction(SIGCHLD, &sa, NULL); if (arg_crash_shell) { log_notice("Executing crash shell in 10s..."); (void) sleep(10); pid = raw_clone(SIGCHLD, NULL); if (pid < 0) log_emergency_errno(errno, "Failed to fork off crash shell: %m"); else if (pid == 0) { (void) setsid(); (void) make_console_stdio(); (void) execle("/bin/sh", "/bin/sh", NULL, environ); log_emergency_errno(errno, "execle() failed: %m"); _exit(EXIT_FAILURE); } else { log_info("Spawned crash shell as PID "PID_FMT".", pid); (void) wait_for_terminate(pid, NULL); } } freeze_or_reboot(); } static void install_crash_handler(void) { static const struct sigaction sa = { .sa_handler = crash, .sa_flags = SA_NODEFER, /* So that we can raise the signal again from the signal handler */ }; int r; /* We ignore the return value here, since, we don't mind if we * cannot set up a crash handler */ r = sigaction_many(&sa, SIGNALS_CRASH_HANDLER, -1); if (r < 0) log_debug_errno(r, "I had trouble setting up the crash handler, ignoring: %m"); } static int console_setup(void) { _cleanup_close_ int tty_fd = -1; int r; tty_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); if (tty_fd < 0) return log_error_errno(tty_fd, "Failed to open /dev/console: %m"); /* We don't want to force text mode. plymouth may be showing * pictures already from initrd. */ r = reset_terminal_fd(tty_fd, false); if (r < 0) return log_error_errno(r, "Failed to reset /dev/console: %m"); return 0; } static int parse_crash_chvt(const char *value) { int b; if (safe_atoi(value, &arg_crash_chvt) >= 0) return 0; b = parse_boolean(value); if (b < 0) return b; if (b > 0) arg_crash_chvt = 0; /* switch to where kmsg goes */ else arg_crash_chvt = -1; /* turn off switching */ return 0; } static int set_machine_id(const char *m) { if (sd_id128_from_string(m, &arg_machine_id) < 0) return -EINVAL; if (sd_id128_is_null(arg_machine_id)) return -EINVAL; return 0; } static int parse_proc_cmdline_item(const char *key, const char *value) { int r; assert(key); if (streq(key, "systemd.unit") && value) { if (!in_initrd()) return free_and_strdup(&arg_default_unit, value); } else if (streq(key, "rd.systemd.unit") && value) { if (in_initrd()) return free_and_strdup(&arg_default_unit, value); } else if (streq(key, "systemd.dump_core") && value) { r = parse_boolean(value); if (r < 0) log_warning("Failed to parse dump core switch %s. Ignoring.", value); else arg_dump_core = r; } else if (streq(key, "systemd.crash_chvt") && value) { if (parse_crash_chvt(value) < 0) log_warning("Failed to parse crash chvt switch %s. Ignoring.", value); } else if (streq(key, "systemd.crash_shell") && value) { r = parse_boolean(value); if (r < 0) log_warning("Failed to parse crash shell switch %s. Ignoring.", value); else arg_crash_shell = r; } else if (streq(key, "systemd.crash_reboot") && value) { r = parse_boolean(value); if (r < 0) log_warning("Failed to parse crash reboot switch %s. Ignoring.", value); else arg_crash_reboot = r; } else if (streq(key, "systemd.confirm_spawn") && value) { r = parse_boolean(value); if (r < 0) log_warning("Failed to parse confirm spawn switch %s. Ignoring.", value); else arg_confirm_spawn = r; } else if (streq(key, "systemd.show_status") && value) { r = parse_show_status(value, &arg_show_status); if (r < 0) log_warning("Failed to parse show status switch %s. Ignoring.", value); } else if (streq(key, "systemd.default_standard_output") && value) { r = exec_output_from_string(value); if (r < 0) log_warning("Failed to parse default standard output switch %s. Ignoring.", value); else arg_default_std_output = r; } else if (streq(key, "systemd.default_standard_error") && value) { r = exec_output_from_string(value); if (r < 0) log_warning("Failed to parse default standard error switch %s. Ignoring.", value); else arg_default_std_error = r; } else if (streq(key, "systemd.setenv") && value) { if (env_assignment_is_valid(value)) { char **env; env = strv_env_set(arg_default_environment, value); if (env) arg_default_environment = env; else log_warning_errno(ENOMEM, "Setting environment variable '%s' failed, ignoring: %m", value); } else log_warning("Environment variable name '%s' is not valid. Ignoring.", value); } else if (streq(key, "systemd.machine_id") && value) { r = set_machine_id(value); if (r < 0) log_warning("MachineID '%s' is not valid. Ignoring.", value); } else if (streq(key, "quiet") && !value) { if (arg_show_status == _SHOW_STATUS_UNSET) arg_show_status = SHOW_STATUS_AUTO; } else if (streq(key, "debug") && !value) { /* Note that log_parse_environment() handles 'debug' * too, and sets the log level to LOG_DEBUG. */ if (detect_container() > 0) log_set_target(LOG_TARGET_CONSOLE); } else if (!in_initrd() && !value) { const char *target; /* SysV compatibility */ target = runlevel_to_target(key); if (target) return free_and_strdup(&arg_default_unit, target); } return 0; } #define DEFINE_SETTER(name, func, descr) \ static int name(const char *unit, \ const char *filename, \ unsigned line, \ const char *section, \ unsigned section_line, \ const char *lvalue, \ int ltype, \ const char *rvalue, \ void *data, \ void *userdata) { \ \ int r; \ \ assert(filename); \ assert(lvalue); \ assert(rvalue); \ \ r = func(rvalue); \ if (r < 0) \ log_syntax(unit, LOG_ERR, filename, line, r, \ "Invalid " descr "'%s': %m", \ rvalue); \ \ return 0; \ } DEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level") DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target") DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" ) DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location") static int config_parse_cpu_affinity2( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_cpu_free_ cpu_set_t *c = NULL; int ncpus; ncpus = parse_cpu_set_and_warn(rvalue, &c, unit, filename, line, lvalue); if (ncpus < 0) return ncpus; if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0) log_warning("Failed to set CPU affinity: %m"); return 0; } static int config_parse_show_status( const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { int k; ShowStatus *b = data; assert(filename); assert(lvalue); assert(rvalue); assert(data); k = parse_show_status(rvalue, b); if (k < 0) { log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse show status setting, ignoring: %s", rvalue); return 0; } return 0; } static int config_parse_crash_chvt( const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { int r; assert(filename); assert(lvalue); assert(rvalue); r = parse_crash_chvt(rvalue); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CrashChangeVT= setting, ignoring: %s", rvalue); return 0; } return 0; } static int config_parse_join_controllers(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { const char *whole_rvalue = rvalue; unsigned n = 0; assert(filename); assert(lvalue); assert(rvalue); arg_join_controllers = strv_free_free(arg_join_controllers); for (;;) { _cleanup_free_ char *word = NULL; char **l; int r; r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue); return r; } if (r == 0) break; l = strv_split(word, ","); if (!l) return log_oom(); strv_uniq(l); if (strv_length(l) <= 1) { strv_free(l); continue; } if (!arg_join_controllers) { arg_join_controllers = new(char**, 2); if (!arg_join_controllers) { strv_free(l); return log_oom(); } arg_join_controllers[0] = l; arg_join_controllers[1] = NULL; n = 1; } else { char ***a; char ***t; t = new0(char**, n+2); if (!t) { strv_free(l); return log_oom(); } n = 0; for (a = arg_join_controllers; *a; a++) { if (strv_overlap(*a, l)) { if (strv_extend_strv(&l, *a, false) < 0) { strv_free(l); strv_free_free(t); return log_oom(); } } else { char **c; c = strv_copy(*a); if (!c) { strv_free(l); strv_free_free(t); return log_oom(); } t[n++] = c; } } t[n++] = strv_uniq(l); strv_free_free(arg_join_controllers); arg_join_controllers = t; } } if (!isempty(rvalue)) log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); return 0; } static int parse_config_file(void) { const ConfigTableItem items[] = { { "Manager", "LogLevel", config_parse_level2, 0, NULL }, { "Manager", "LogTarget", config_parse_target, 0, NULL }, { "Manager", "LogColor", config_parse_color, 0, NULL }, { "Manager", "LogLocation", config_parse_location, 0, NULL }, { "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core }, { "Manager", "CrashChVT", /* legacy */ config_parse_crash_chvt, 0, NULL }, { "Manager", "CrashChangeVT", config_parse_crash_chvt, 0, NULL }, { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell }, { "Manager", "CrashReboot", config_parse_bool, 0, &arg_crash_reboot }, { "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status }, { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL }, { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers }, { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog }, { "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog }, { "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set }, #ifdef HAVE_SECCOMP { "Manager", "SystemCallArchitectures", config_parse_syscall_archs, 0, &arg_syscall_archs }, #endif { "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec }, { "Manager", "DefaultTimerAccuracySec", config_parse_sec, 0, &arg_default_timer_accuracy_usec }, { "Manager", "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output }, { "Manager", "DefaultStandardError", config_parse_output, 0, &arg_default_std_error }, { "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec }, { "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec }, { "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec }, { "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval }, { "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst }, { "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment }, { "Manager", "DefaultLimitCPU", config_parse_limit, RLIMIT_CPU, arg_default_rlimit }, { "Manager", "DefaultLimitFSIZE", config_parse_limit, RLIMIT_FSIZE, arg_default_rlimit }, { "Manager", "DefaultLimitDATA", config_parse_limit, RLIMIT_DATA, arg_default_rlimit }, { "Manager", "DefaultLimitSTACK", config_parse_limit, RLIMIT_STACK, arg_default_rlimit }, { "Manager", "DefaultLimitCORE", config_parse_limit, RLIMIT_CORE, arg_default_rlimit }, { "Manager", "DefaultLimitRSS", config_parse_limit, RLIMIT_RSS, arg_default_rlimit }, { "Manager", "DefaultLimitNOFILE", config_parse_limit, RLIMIT_NOFILE, arg_default_rlimit }, { "Manager", "DefaultLimitAS", config_parse_limit, RLIMIT_AS, arg_default_rlimit }, { "Manager", "DefaultLimitNPROC", config_parse_limit, RLIMIT_NPROC, arg_default_rlimit }, { "Manager", "DefaultLimitMEMLOCK", config_parse_limit, RLIMIT_MEMLOCK, arg_default_rlimit }, { "Manager", "DefaultLimitLOCKS", config_parse_limit, RLIMIT_LOCKS, arg_default_rlimit }, { "Manager", "DefaultLimitSIGPENDING", config_parse_limit, RLIMIT_SIGPENDING, arg_default_rlimit }, { "Manager", "DefaultLimitMSGQUEUE", config_parse_limit, RLIMIT_MSGQUEUE, arg_default_rlimit }, { "Manager", "DefaultLimitNICE", config_parse_limit, RLIMIT_NICE, arg_default_rlimit }, { "Manager", "DefaultLimitRTPRIO", config_parse_limit, RLIMIT_RTPRIO, arg_default_rlimit }, { "Manager", "DefaultLimitRTTIME", config_parse_limit, RLIMIT_RTTIME, arg_default_rlimit }, { "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting }, { "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting }, { "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting }, { "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting }, { "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max }, {} }; const char *fn, *conf_dirs_nulstr; fn = arg_running_as == MANAGER_SYSTEM ? PKGSYSCONFDIR "/system.conf" : PKGSYSCONFDIR "/user.conf"; conf_dirs_nulstr = arg_running_as == MANAGER_SYSTEM ? CONF_PATHS_NULSTR("systemd/system.conf.d") : CONF_PATHS_NULSTR("systemd/user.conf.d"); config_parse_many(fn, conf_dirs_nulstr, "Manager\0", config_item_table_lookup, items, false, NULL); /* Traditionally "0" was used to turn off the default unit timeouts. Fix this up so that we used USEC_INFINITY * like everywhere else. */ if (arg_default_timeout_start_usec <= 0) arg_default_timeout_start_usec = USEC_INFINITY; if (arg_default_timeout_stop_usec <= 0) arg_default_timeout_stop_usec = USEC_INFINITY; return 0; } static void manager_set_defaults(Manager *m) { assert(m); m->default_timer_accuracy_usec = arg_default_timer_accuracy_usec; m->default_std_output = arg_default_std_output; m->default_std_error = arg_default_std_error; m->default_timeout_start_usec = arg_default_timeout_start_usec; m->default_timeout_stop_usec = arg_default_timeout_stop_usec; m->default_restart_usec = arg_default_restart_usec; m->default_start_limit_interval = arg_default_start_limit_interval; m->default_start_limit_burst = arg_default_start_limit_burst; m->default_cpu_accounting = arg_default_cpu_accounting; m->default_blockio_accounting = arg_default_blockio_accounting; m->default_memory_accounting = arg_default_memory_accounting; m->default_tasks_accounting = arg_default_tasks_accounting; m->default_tasks_max = arg_default_tasks_max; manager_set_default_rlimits(m, arg_default_rlimit); manager_environment_add(m, NULL, arg_default_environment); } static int parse_argv(int argc, char *argv[]) { enum { ARG_LOG_LEVEL = 0x100, ARG_LOG_TARGET, ARG_LOG_COLOR, ARG_LOG_LOCATION, ARG_UNIT, ARG_SYSTEM, ARG_USER, ARG_TEST, ARG_NO_PAGER, ARG_VERSION, ARG_DUMP_CONFIGURATION_ITEMS, ARG_DUMP_CORE, ARG_CRASH_CHVT, ARG_CRASH_SHELL, ARG_CRASH_REBOOT, ARG_CONFIRM_SPAWN, ARG_SHOW_STATUS, ARG_DESERIALIZE, ARG_SWITCHED_ROOT, ARG_DEFAULT_STD_OUTPUT, ARG_DEFAULT_STD_ERROR, ARG_MACHINE_ID }; static const struct option options[] = { { "log-level", required_argument, NULL, ARG_LOG_LEVEL }, { "log-target", required_argument, NULL, ARG_LOG_TARGET }, { "log-color", optional_argument, NULL, ARG_LOG_COLOR }, { "log-location", optional_argument, NULL, ARG_LOG_LOCATION }, { "unit", required_argument, NULL, ARG_UNIT }, { "system", no_argument, NULL, ARG_SYSTEM }, { "user", no_argument, NULL, ARG_USER }, { "test", no_argument, NULL, ARG_TEST }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS }, { "dump-core", optional_argument, NULL, ARG_DUMP_CORE }, { "crash-chvt", required_argument, NULL, ARG_CRASH_CHVT }, { "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL }, { "crash-reboot", optional_argument, NULL, ARG_CRASH_REBOOT }, { "confirm-spawn", optional_argument, NULL, ARG_CONFIRM_SPAWN }, { "show-status", optional_argument, NULL, ARG_SHOW_STATUS }, { "deserialize", required_argument, NULL, ARG_DESERIALIZE }, { "switched-root", no_argument, NULL, ARG_SWITCHED_ROOT }, { "default-standard-output", required_argument, NULL, ARG_DEFAULT_STD_OUTPUT, }, { "default-standard-error", required_argument, NULL, ARG_DEFAULT_STD_ERROR, }, { "machine-id", required_argument, NULL, ARG_MACHINE_ID }, {} }; int c, r; assert(argc >= 1); assert(argv); if (getpid() == 1) opterr = 0; while ((c = getopt_long(argc, argv, "hDbsz:", options, NULL)) >= 0) switch (c) { case ARG_LOG_LEVEL: r = log_set_max_level_from_string(optarg); if (r < 0) { log_error("Failed to parse log level %s.", optarg); return r; } break; case ARG_LOG_TARGET: r = log_set_target_from_string(optarg); if (r < 0) { log_error("Failed to parse log target %s.", optarg); return r; } break; case ARG_LOG_COLOR: if (optarg) { r = log_show_color_from_string(optarg); if (r < 0) { log_error("Failed to parse log color setting %s.", optarg); return r; } } else log_show_color(true); break; case ARG_LOG_LOCATION: if (optarg) { r = log_show_location_from_string(optarg); if (r < 0) { log_error("Failed to parse log location setting %s.", optarg); return r; } } else log_show_location(true); break; case ARG_DEFAULT_STD_OUTPUT: r = exec_output_from_string(optarg); if (r < 0) { log_error("Failed to parse default standard output setting %s.", optarg); return r; } else arg_default_std_output = r; break; case ARG_DEFAULT_STD_ERROR: r = exec_output_from_string(optarg); if (r < 0) { log_error("Failed to parse default standard error output setting %s.", optarg); return r; } else arg_default_std_error = r; break; case ARG_UNIT: r = free_and_strdup(&arg_default_unit, optarg); if (r < 0) return log_error_errno(r, "Failed to set default unit %s: %m", optarg); break; case ARG_SYSTEM: arg_running_as = MANAGER_SYSTEM; break; case ARG_USER: arg_running_as = MANAGER_USER; break; case ARG_TEST: arg_action = ACTION_TEST; if (arg_no_pager < 0) arg_no_pager = true; break; case ARG_NO_PAGER: arg_no_pager = true; break; case ARG_VERSION: arg_action = ACTION_VERSION; break; case ARG_DUMP_CONFIGURATION_ITEMS: arg_action = ACTION_DUMP_CONFIGURATION_ITEMS; break; case ARG_DUMP_CORE: if (!optarg) arg_dump_core = true; else { r = parse_boolean(optarg); if (r < 0) return log_error_errno(r, "Failed to parse dump core boolean: %s", optarg); arg_dump_core = r; } break; case ARG_CRASH_CHVT: r = parse_crash_chvt(optarg); if (r < 0) return log_error_errno(r, "Failed to parse crash virtual terminal index: %s", optarg); break; case ARG_CRASH_SHELL: if (!optarg) arg_crash_shell = true; else { r = parse_boolean(optarg); if (r < 0) return log_error_errno(r, "Failed to parse crash shell boolean: %s", optarg); arg_crash_shell = r; } break; case ARG_CRASH_REBOOT: if (!optarg) arg_crash_reboot = true; else { r = parse_boolean(optarg); if (r < 0) return log_error_errno(r, "Failed to parse crash shell boolean: %s", optarg); arg_crash_reboot = r; } break; case ARG_CONFIRM_SPAWN: r = optarg ? parse_boolean(optarg) : 1; if (r < 0) { log_error("Failed to parse confirm spawn boolean %s.", optarg); return r; } arg_confirm_spawn = r; break; case ARG_SHOW_STATUS: if (optarg) { r = parse_show_status(optarg, &arg_show_status); if (r < 0) { log_error("Failed to parse show status boolean %s.", optarg); return r; } } else arg_show_status = SHOW_STATUS_YES; break; case ARG_DESERIALIZE: { int fd; FILE *f; r = safe_atoi(optarg, &fd); if (r < 0 || fd < 0) { log_error("Failed to parse deserialize option %s.", optarg); return -EINVAL; } (void) fd_cloexec(fd, true); f = fdopen(fd, "r"); if (!f) return log_error_errno(errno, "Failed to open serialization fd: %m"); safe_fclose(arg_serialization); arg_serialization = f; break; } case ARG_SWITCHED_ROOT: arg_switched_root = true; break; case ARG_MACHINE_ID: r = set_machine_id(optarg); if (r < 0) { log_error("MachineID '%s' is not valid.", optarg); return r; } break; case 'h': arg_action = ACTION_HELP; if (arg_no_pager < 0) arg_no_pager = true; break; case 'D': log_set_max_level(LOG_DEBUG); break; case 'b': case 's': case 'z': /* Just to eat away the sysvinit kernel * cmdline args without getopt() error * messages that we'll parse in * parse_proc_cmdline_word() or ignore. */ case '?': if (getpid() != 1) return -EINVAL; else return 0; default: assert_not_reached("Unhandled option code."); } if (optind < argc && getpid() != 1) { /* Hmm, when we aren't run as init system * let's complain about excess arguments */ log_error("Excess arguments."); return -EINVAL; } return 0; } static int help(void) { printf("%s [OPTIONS...]\n\n" "Starts up and maintains the system or user services.\n\n" " -h --help Show this help\n" " --test Determine startup sequence, dump it and exit\n" " --no-pager Do not pipe output into a pager\n" " --dump-configuration-items Dump understood unit configuration items\n" " --unit=UNIT Set default unit\n" " --system Run a system instance, even if PID != 1\n" " --user Run a user instance\n" " --dump-core[=BOOL] Dump core on crash\n" " --crash-vt=NR Change to specified VT on crash\n" " --crash-reboot[=BOOL] Reboot on crash\n" " --crash-shell[=BOOL] Run shell on crash\n" " --confirm-spawn[=BOOL] Ask for confirmation when spawning processes\n" " --show-status[=BOOL] Show status updates on the console during bootup\n" " --log-target=TARGET Set log target (console, journal, kmsg, journal-or-kmsg, null)\n" " --log-level=LEVEL Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n" " --log-color[=BOOL] Highlight important log messages\n" " --log-location[=BOOL] Include code location in log messages\n" " --default-standard-output= Set default standard output for services\n" " --default-standard-error= Set default standard error output for services\n", program_invocation_short_name); return 0; } static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching_root) { _cleanup_fdset_free_ FDSet *fds = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(m); assert(_f); assert(_fds); r = manager_open_serialization(m, &f); if (r < 0) return log_error_errno(r, "Failed to create serialization file: %m"); /* Make sure nothing is really destructed when we shut down */ m->n_reloading ++; bus_manager_send_reloading(m, true); fds = fdset_new(); if (!fds) return log_oom(); r = manager_serialize(m, f, fds, switching_root); if (r < 0) return log_error_errno(r, "Failed to serialize state: %m"); if (fseeko(f, 0, SEEK_SET) == (off_t) -1) return log_error_errno(errno, "Failed to rewind serialization fd: %m"); r = fd_cloexec(fileno(f), false); if (r < 0) return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization: %m"); r = fdset_cloexec(fds, false); if (r < 0) return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m"); *_f = f; *_fds = fds; f = NULL; fds = NULL; return 0; } static int bump_rlimit_nofile(struct rlimit *saved_rlimit) { struct rlimit nl; int r; assert(saved_rlimit); /* Save the original RLIMIT_NOFILE so that we can reset it * later when transitioning from the initrd to the main * systemd or suchlike. */ if (getrlimit(RLIMIT_NOFILE, saved_rlimit) < 0) return log_error_errno(errno, "Reading RLIMIT_NOFILE failed: %m"); /* Make sure forked processes get the default kernel setting */ if (!arg_default_rlimit[RLIMIT_NOFILE]) { struct rlimit *rl; rl = newdup(struct rlimit, saved_rlimit, 1); if (!rl) return log_oom(); arg_default_rlimit[RLIMIT_NOFILE] = rl; } /* Bump up the resource limit for ourselves substantially */ nl.rlim_cur = nl.rlim_max = 64*1024; r = setrlimit_closest(RLIMIT_NOFILE, &nl); if (r < 0) return log_error_errno(r, "Setting RLIMIT_NOFILE failed: %m"); return 0; } static void test_usr(void) { /* Check that /usr is not a separate fs */ if (dir_is_empty("/usr") <= 0) return; log_warning("/usr appears to be on its own filesystem and is not already mounted. This is not a supported setup. " "Some things will probably break (sometimes even silently) in mysterious ways. " "Consult http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken for more information."); } static int initialize_join_controllers(void) { /* By default, mount "cpu" + "cpuacct" together, and "net_cls" * + "net_prio". We'd like to add "cpuset" to the mix, but * "cpuset" doesn't really work for groups with no initialized * attributes. */ arg_join_controllers = new(char**, 3); if (!arg_join_controllers) return -ENOMEM; arg_join_controllers[0] = strv_new("cpu", "cpuacct", NULL); if (!arg_join_controllers[0]) goto oom; arg_join_controllers[1] = strv_new("net_cls", "net_prio", NULL); if (!arg_join_controllers[1]) goto oom; arg_join_controllers[2] = NULL; return 0; oom: arg_join_controllers = strv_free_free(arg_join_controllers); return -ENOMEM; } static int enforce_syscall_archs(Set *archs) { #ifdef HAVE_SECCOMP scmp_filter_ctx *seccomp; Iterator i; void *id; int r; seccomp = seccomp_init(SCMP_ACT_ALLOW); if (!seccomp) return log_oom(); SET_FOREACH(id, arg_syscall_archs, i) { r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1); if (r == -EEXIST) continue; if (r < 0) { log_error_errno(r, "Failed to add architecture to seccomp: %m"); goto finish; } } r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); if (r < 0) { log_error_errno(r, "Failed to unset NO_NEW_PRIVS: %m"); goto finish; } r = seccomp_load(seccomp); if (r < 0) log_error_errno(r, "Failed to add install architecture seccomp: %m"); finish: seccomp_release(seccomp); return r; #else return 0; #endif } static int status_welcome(void) { _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL; int r; r = parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &pretty_name, "ANSI_COLOR", &ansi_color, NULL); if (r == -ENOENT) r = parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &pretty_name, "ANSI_COLOR", &ansi_color, NULL); if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to read os-release file: %m"); return status_printf(NULL, false, false, "\nWelcome to \x1B[%sm%s\x1B[0m!\n", isempty(ansi_color) ? "1" : ansi_color, isempty(pretty_name) ? "Linux" : pretty_name); } static int write_container_id(void) { const char *c; int r; c = getenv("container"); if (isempty(c)) return 0; r = write_string_file("/run/systemd/container", c, WRITE_STRING_FILE_CREATE); if (r < 0) return log_warning_errno(r, "Failed to write /run/systemd/container, ignoring: %m"); return 1; } static int bump_unix_max_dgram_qlen(void) { _cleanup_free_ char *qlen = NULL; unsigned long v; int r; /* Let's bump the net.unix.max_dgram_qlen sysctl. The kernel * default of 16 is simply too low. We set the value really * really early during boot, so that it is actually applied to * all our sockets, including the $NOTIFY_SOCKET one. */ r = read_one_line_file("/proc/sys/net/unix/max_dgram_qlen", &qlen); if (r < 0) return log_warning_errno(r, "Failed to read AF_UNIX datagram queue length, ignoring: %m"); r = safe_atolu(qlen, &v); if (r < 0) return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length, ignoring: %m"); if (v >= DEFAULT_UNIX_MAX_DGRAM_QLEN) return 0; qlen = mfree(qlen); if (asprintf(&qlen, "%lu\n", DEFAULT_UNIX_MAX_DGRAM_QLEN) < 0) return log_oom(); r = write_string_file("/proc/sys/net/unix/max_dgram_qlen", qlen, 0); if (r < 0) return log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to bump AF_UNIX datagram queue length, ignoring: %m"); return 1; } int main(int argc, char *argv[]) { Manager *m = NULL; int r, retval = EXIT_FAILURE; usec_t before_startup, after_startup; char timespan[FORMAT_TIMESPAN_MAX]; FDSet *fds = NULL; bool reexecute = false; const char *shutdown_verb = NULL; dual_timestamp initrd_timestamp = DUAL_TIMESTAMP_NULL; dual_timestamp userspace_timestamp = DUAL_TIMESTAMP_NULL; dual_timestamp kernel_timestamp = DUAL_TIMESTAMP_NULL; dual_timestamp security_start_timestamp = DUAL_TIMESTAMP_NULL; dual_timestamp security_finish_timestamp = DUAL_TIMESTAMP_NULL; static char systemd[] = "systemd"; bool skip_setup = false; unsigned j; bool loaded_policy = false; bool arm_reboot_watchdog = false; bool queue_default_job = false; bool empty_etc = false; char *switch_root_dir = NULL, *switch_root_init = NULL; struct rlimit saved_rlimit_nofile = RLIMIT_MAKE_CONST(0); const char *error_message = NULL; #ifdef HAVE_SYSV_COMPAT if (getpid() != 1 && strstr(program_invocation_short_name, "init")) { /* This is compatibility support for SysV, where * calling init as a user is identical to telinit. */ errno = -ENOENT; execv(SYSTEMCTL_BINARY_PATH, argv); log_error_errno(errno, "Failed to exec " SYSTEMCTL_BINARY_PATH ": %m"); return 1; } #endif dual_timestamp_from_monotonic(&kernel_timestamp, 0); dual_timestamp_get(&userspace_timestamp); /* Determine if this is a reexecution or normal bootup. We do * the full command line parsing much later, so let's just * have a quick peek here. */ if (strv_find(argv+1, "--deserialize")) skip_setup = true; /* If we have switched root, do all the special setup * things */ if (strv_find(argv+1, "--switched-root")) skip_setup = false; /* If we get started via the /sbin/init symlink then we are called 'init'. After a subsequent reexecution we are then called 'systemd'. That is confusing, hence let's call us systemd right-away. */ program_invocation_short_name = systemd; prctl(PR_SET_NAME, systemd); saved_argv = argv; saved_argc = argc; log_show_color(isatty(STDERR_FILENO) > 0); log_set_upgrade_syslog_to_journal(true); /* Disable the umask logic */ if (getpid() == 1) umask(0); if (getpid() == 1 && detect_container() <= 0) { /* Running outside of a container as PID 1 */ arg_running_as = MANAGER_SYSTEM; make_null_stdio(); log_set_target(LOG_TARGET_KMSG); log_open(); if (in_initrd()) initrd_timestamp = userspace_timestamp; if (!skip_setup) { r = mount_setup_early(); if (r < 0) { error_message = "Failed to early mount API filesystems"; goto finish; } dual_timestamp_get(&security_start_timestamp); if (mac_selinux_setup(&loaded_policy) < 0) { error_message = "Failed to load SELinux policy"; goto finish; } else if (ima_setup() < 0) { error_message = "Failed to load IMA policy"; goto finish; } else if (mac_smack_setup(&loaded_policy) < 0) { error_message = "Failed to load SMACK policy"; goto finish; } dual_timestamp_get(&security_finish_timestamp); } if (mac_selinux_init(NULL) < 0) { error_message = "Failed to initialize SELinux policy"; goto finish; } if (!skip_setup) { if (clock_is_localtime() > 0) { int min; /* * The very first call of settimeofday() also does a time warp in the kernel. * * In the rtc-in-local time mode, we set the kernel's timezone, and rely on * external tools to take care of maintaining the RTC and do all adjustments. * This matches the behavior of Windows, which leaves the RTC alone if the * registry tells that the RTC runs in UTC. */ r = clock_set_timezone(&min); if (r < 0) log_error_errno(r, "Failed to apply local time delta, ignoring: %m"); else log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min); } else if (!in_initrd()) { /* * Do a dummy very first call to seal the kernel's time warp magic. * * Do not call this this from inside the initrd. The initrd might not * carry /etc/adjtime with LOCAL, but the real system could be set up * that way. In such case, we need to delay the time-warp or the sealing * until we reach the real system. * * Do no set the kernel's timezone. The concept of local time cannot * be supported reliably, the time will jump or be incorrect at every daylight * saving time change. All kernel local time concepts will be treated * as UTC that way. */ (void) clock_reset_timewarp(); } r = clock_apply_epoch(); if (r < 0) log_error_errno(r, "Current system time is before build time, but cannot correct: %m"); else if (r > 0) log_info("System time before build time, advancing clock."); } /* Set the default for later on, but don't actually * open the logs like this for now. Note that if we * are transitioning from the initrd there might still * be journal fd open, and we shouldn't attempt * opening that before we parsed /proc/cmdline which * might redirect output elsewhere. */ log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); } else if (getpid() == 1) { /* Running inside a container, as PID 1 */ arg_running_as = MANAGER_SYSTEM; log_set_target(LOG_TARGET_CONSOLE); log_close_console(); /* force reopen of /dev/console */ log_open(); /* For the later on, see above... */ log_set_target(LOG_TARGET_JOURNAL); /* clear the kernel timestamp, * because we are in a container */ kernel_timestamp.monotonic = 0ULL; kernel_timestamp.realtime = 0ULL; } else { /* Running as user instance */ arg_running_as = MANAGER_USER; log_set_target(LOG_TARGET_AUTO); log_open(); /* clear the kernel timestamp, * because we are not PID 1 */ kernel_timestamp = DUAL_TIMESTAMP_NULL; } if (getpid() == 1) { /* Don't limit the core dump size, so that coredump handlers such as systemd-coredump (which honour the limit) * will process core dumps for system services by default. */ (void) setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY)); /* But at the same time, turn off the core_pattern logic by default, so that no coredumps are stored * until the systemd-coredump tool is enabled via sysctl. */ if (!skip_setup) (void) write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", 0); } /* Initialize default unit */ r = free_and_strdup(&arg_default_unit, SPECIAL_DEFAULT_TARGET); if (r < 0) { log_emergency_errno(r, "Failed to set default unit %s: %m", SPECIAL_DEFAULT_TARGET); error_message = "Failed to set default unit"; goto finish; } r = initialize_join_controllers(); if (r < 0) { error_message = "Failed to initialize cgroup controllers"; goto finish; } /* Mount /proc, /sys and friends, so that /proc/cmdline and * /proc/$PID/fd is available. */ if (getpid() == 1) { /* Load the kernel modules early, so that we kdbus.ko is loaded before kdbusfs shall be mounted */ if (!skip_setup) kmod_setup(); r = mount_setup(loaded_policy); if (r < 0) { error_message = "Failed to mount API filesystems"; goto finish; } } /* Reset all signal handlers. */ (void) reset_all_signal_handlers(); (void) ignore_signals(SIGNALS_IGNORE, -1); if (parse_config_file() < 0) { error_message = "Failed to parse config file"; goto finish; } if (arg_running_as == MANAGER_SYSTEM) { r = parse_proc_cmdline(parse_proc_cmdline_item); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); } /* Note that this also parses bits from the kernel command * line, including "debug". */ log_parse_environment(); if (parse_argv(argc, argv) < 0) { error_message = "Failed to parse commandline arguments"; goto finish; } if (arg_action == ACTION_TEST && geteuid() == 0) { log_error("Don't run test mode as root."); goto finish; } if (arg_running_as == MANAGER_USER && arg_action == ACTION_RUN && sd_booted() <= 0) { log_error("Trying to run as user instance, but the system has not been booted with systemd."); goto finish; } if (arg_running_as == MANAGER_SYSTEM && arg_action == ACTION_RUN && running_in_chroot() > 0) { log_error("Cannot be run in a chroot() environment."); goto finish; } if (arg_action == ACTION_TEST) skip_setup = true; pager_open_if_enabled(); if (arg_action == ACTION_HELP) { retval = help(); goto finish; } else if (arg_action == ACTION_VERSION) { retval = version(); goto finish; } else if (arg_action == ACTION_DUMP_CONFIGURATION_ITEMS) { unit_dump_config_items(stdout); retval = EXIT_SUCCESS; goto finish; } else if (arg_action == ACTION_DONE) { retval = EXIT_SUCCESS; goto finish; } if (arg_running_as == MANAGER_USER && !getenv("XDG_RUNTIME_DIR")) { log_error("Trying to run as user instance, but $XDG_RUNTIME_DIR is not set."); goto finish; } assert_se(arg_action == ACTION_RUN || arg_action == ACTION_TEST); /* Close logging fds, in order not to confuse fdset below */ log_close(); /* Remember open file descriptors for later deserialization */ r = fdset_new_fill(&fds); if (r < 0) { log_emergency_errno(r, "Failed to allocate fd set: %m"); error_message = "Failed to allocate fd set"; goto finish; } else fdset_cloexec(fds, true); if (arg_serialization) assert_se(fdset_remove(fds, fileno(arg_serialization)) >= 0); if (arg_running_as == MANAGER_SYSTEM) /* Become a session leader if we aren't one yet. */ setsid(); /* Move out of the way, so that we won't block unmounts */ assert_se(chdir("/") == 0); /* Reset the console, but only if this is really init and we * are freshly booted */ if (arg_running_as == MANAGER_SYSTEM && arg_action == ACTION_RUN) { /* If we are init, we connect stdin/stdout/stderr to * /dev/null and make sure we don't have a controlling * tty. */ release_terminal(); if (getpid() == 1 && !skip_setup) console_setup(); } /* Open the logging devices, if possible and necessary */ log_open(); if (arg_show_status == _SHOW_STATUS_UNSET) arg_show_status = SHOW_STATUS_YES; /* Make sure we leave a core dump without panicing the * kernel. */ if (getpid() == 1) { install_crash_handler(); r = mount_cgroup_controllers(arg_join_controllers); if (r < 0) goto finish; } if (arg_running_as == MANAGER_SYSTEM) { int v; log_info(PACKAGE_STRING " running in %ssystem mode. (" SYSTEMD_FEATURES ")", arg_action == ACTION_TEST ? "test " : "" ); v = detect_virtualization(); if (v > 0) log_info("Detected virtualization %s.", virtualization_to_string(v)); write_container_id(); log_info("Detected architecture %s.", architecture_to_string(uname_architecture())); if (in_initrd()) log_info("Running in initial RAM disk."); /* Let's check whether /etc is already populated. We * don't actually really check for that, but use * /etc/machine-id as flag file. This allows container * managers and installers to provision a couple of * files already. If the container manager wants to * provision the machine ID itself it should pass * $container_uuid to PID 1. */ empty_etc = access("/etc/machine-id", F_OK) < 0; if (empty_etc) log_info("Running with unpopulated /etc."); } else { _cleanup_free_ char *t; t = uid_to_name(getuid()); log_debug(PACKAGE_STRING " running in %suser mode for user "UID_FMT"/%s. (" SYSTEMD_FEATURES ")", arg_action == ACTION_TEST ? " test" : "", getuid(), t); } if (arg_running_as == MANAGER_SYSTEM && !skip_setup) { if (arg_show_status > 0) status_welcome(); hostname_setup(); machine_id_setup(NULL, arg_machine_id); loopback_setup(); bump_unix_max_dgram_qlen(); test_usr(); } if (arg_running_as == MANAGER_SYSTEM && arg_runtime_watchdog > 0) watchdog_set_timeout(&arg_runtime_watchdog); if (arg_timer_slack_nsec != NSEC_INFINITY) if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0) log_error_errno(errno, "Failed to adjust timer slack: %m"); if (!cap_test_all(arg_capability_bounding_set)) { r = capability_bounding_set_drop_usermode(arg_capability_bounding_set); if (r < 0) { log_emergency_errno(r, "Failed to drop capability bounding set of usermode helpers: %m"); error_message = "Failed to drop capability bounding set of usermode helpers"; goto finish; } r = capability_bounding_set_drop(arg_capability_bounding_set, true); if (r < 0) { log_emergency_errno(r, "Failed to drop capability bounding set: %m"); error_message = "Failed to drop capability bounding set"; goto finish; } } if (arg_syscall_archs) { r = enforce_syscall_archs(arg_syscall_archs); if (r < 0) { error_message = "Failed to set syscall architectures"; goto finish; } } if (arg_running_as == MANAGER_USER) /* Become reaper of our children */ if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) log_warning_errno(errno, "Failed to make us a subreaper: %m"); if (arg_running_as == MANAGER_SYSTEM) { bump_rlimit_nofile(&saved_rlimit_nofile); if (empty_etc) { r = unit_file_preset_all(UNIT_FILE_SYSTEM, false, NULL, UNIT_FILE_PRESET_ENABLE_ONLY, false, NULL, 0); if (r < 0) log_full_errno(r == -EEXIST ? LOG_NOTICE : LOG_WARNING, r, "Failed to populate /etc with preset unit settings, ignoring: %m"); else log_info("Populated /etc with preset unit settings."); } } r = manager_new(arg_running_as, arg_action == ACTION_TEST, &m); if (r < 0) { log_emergency_errno(r, "Failed to allocate manager object: %m"); error_message = "Failed to allocate manager object"; goto finish; } m->confirm_spawn = arg_confirm_spawn; m->runtime_watchdog = arg_runtime_watchdog; m->shutdown_watchdog = arg_shutdown_watchdog; m->userspace_timestamp = userspace_timestamp; m->kernel_timestamp = kernel_timestamp; m->initrd_timestamp = initrd_timestamp; m->security_start_timestamp = security_start_timestamp; m->security_finish_timestamp = security_finish_timestamp; manager_set_defaults(m); manager_set_show_status(m, arg_show_status); manager_set_first_boot(m, empty_etc); /* Remember whether we should queue the default job */ queue_default_job = !arg_serialization || arg_switched_root; before_startup = now(CLOCK_MONOTONIC); r = manager_startup(m, arg_serialization, fds); if (r < 0) log_error_errno(r, "Failed to fully start up daemon: %m"); /* This will close all file descriptors that were opened, but * not claimed by any unit. */ fds = fdset_free(fds); arg_serialization = safe_fclose(arg_serialization); if (queue_default_job) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; Unit *target = NULL; Job *default_unit_job; log_debug("Activating default unit: %s", arg_default_unit); r = manager_load_unit(m, arg_default_unit, NULL, &error, &target); if (r < 0) log_error("Failed to load default target: %s", bus_error_message(&error, r)); else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND) log_error_errno(target->load_error, "Failed to load default target: %m"); else if (target->load_state == UNIT_MASKED) log_error("Default target masked."); if (!target || target->load_state != UNIT_LOADED) { log_info("Trying to load rescue target..."); r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target); if (r < 0) { log_emergency("Failed to load rescue target: %s", bus_error_message(&error, r)); error_message = "Failed to load rescue target"; goto finish; } else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND) { log_emergency_errno(target->load_error, "Failed to load rescue target: %m"); error_message = "Failed to load rescue target"; goto finish; } else if (target->load_state == UNIT_MASKED) { log_emergency("Rescue target masked."); error_message = "Rescue target masked"; goto finish; } } assert(target->load_state == UNIT_LOADED); if (arg_action == ACTION_TEST) { printf("-> By units:\n"); manager_dump_units(m, stdout, "\t"); } r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, &error, &default_unit_job); if (r == -EPERM) { log_debug("Default target could not be isolated, starting instead: %s", bus_error_message(&error, r)); sd_bus_error_free(&error); r = manager_add_job(m, JOB_START, target, JOB_REPLACE, &error, &default_unit_job); if (r < 0) { log_emergency("Failed to start default target: %s", bus_error_message(&error, r)); error_message = "Failed to start default target"; goto finish; } } else if (r < 0) { log_emergency("Failed to isolate default target: %s", bus_error_message(&error, r)); error_message = "Failed to isolate default target"; goto finish; } m->default_unit_job_id = default_unit_job->id; after_startup = now(CLOCK_MONOTONIC); log_full(arg_action == ACTION_TEST ? LOG_INFO : LOG_DEBUG, "Loaded units and determined initial transaction in %s.", format_timespan(timespan, sizeof(timespan), after_startup - before_startup, 100 * USEC_PER_MSEC)); if (arg_action == ACTION_TEST) { printf("-> By jobs:\n"); manager_dump_jobs(m, stdout, "\t"); retval = EXIT_SUCCESS; goto finish; } } for (;;) { r = manager_loop(m); if (r < 0) { log_emergency_errno(r, "Failed to run main loop: %m"); error_message = "Failed to run main loop"; goto finish; } switch (m->exit_code) { case MANAGER_RELOAD: log_info("Reloading."); r = parse_config_file(); if (r < 0) log_error("Failed to parse config file."); manager_set_defaults(m); r = manager_reload(m); if (r < 0) log_error_errno(r, "Failed to reload: %m"); break; case MANAGER_REEXECUTE: if (prepare_reexecute(m, &arg_serialization, &fds, false) < 0) { error_message = "Failed to prepare for reexecution"; goto finish; } reexecute = true; log_notice("Reexecuting."); goto finish; case MANAGER_SWITCH_ROOT: /* Steal the switch root parameters */ switch_root_dir = m->switch_root; switch_root_init = m->switch_root_init; m->switch_root = m->switch_root_init = NULL; if (!switch_root_init) if (prepare_reexecute(m, &arg_serialization, &fds, true) < 0) { error_message = "Failed to prepare for reexecution"; goto finish; } reexecute = true; log_notice("Switching root."); goto finish; case MANAGER_EXIT: retval = m->return_value; if (m->running_as == MANAGER_USER) { log_debug("Exit."); goto finish; } /* fallthrough */ case MANAGER_REBOOT: case MANAGER_POWEROFF: case MANAGER_HALT: case MANAGER_KEXEC: { static const char * const table[_MANAGER_EXIT_CODE_MAX] = { [MANAGER_EXIT] = "exit", [MANAGER_REBOOT] = "reboot", [MANAGER_POWEROFF] = "poweroff", [MANAGER_HALT] = "halt", [MANAGER_KEXEC] = "kexec" }; assert_se(shutdown_verb = table[m->exit_code]); arm_reboot_watchdog = m->exit_code == MANAGER_REBOOT; log_notice("Shutting down."); goto finish; } default: assert_not_reached("Unknown exit code."); } } finish: pager_close(); if (m) arg_shutdown_watchdog = m->shutdown_watchdog; m = manager_free(m); for (j = 0; j < ELEMENTSOF(arg_default_rlimit); j++) arg_default_rlimit[j] = mfree(arg_default_rlimit[j]); arg_default_unit = mfree(arg_default_unit); arg_join_controllers = strv_free_free(arg_join_controllers); arg_default_environment = strv_free(arg_default_environment); arg_syscall_archs = set_free(arg_syscall_archs); mac_selinux_finish(); if (reexecute) { const char **args; unsigned i, args_size; /* Close and disarm the watchdog, so that the new * instance can reinitialize it, but doesn't get * rebooted while we do that */ watchdog_close(true); /* Reset the RLIMIT_NOFILE to the kernel default, so * that the new systemd can pass the kernel default to * its child processes */ if (saved_rlimit_nofile.rlim_cur > 0) (void) setrlimit(RLIMIT_NOFILE, &saved_rlimit_nofile); if (switch_root_dir) { /* Kill all remaining processes from the * initrd, but don't wait for them, so that we * can handle the SIGCHLD for them after * deserializing. */ broadcast_signal(SIGTERM, false, true); /* And switch root with MS_MOVE, because we remove the old directory afterwards and detach it. */ r = switch_root(switch_root_dir, "/mnt", true, MS_MOVE); if (r < 0) log_error_errno(r, "Failed to switch root, trying to continue: %m"); } args_size = MAX(6, argc+1); args = newa(const char*, args_size); if (!switch_root_init) { char sfd[DECIMAL_STR_MAX(int) + 1]; /* First try to spawn ourselves with the right * path, and with full serialization. We do * this only if the user didn't specify an * explicit init to spawn. */ assert(arg_serialization); assert(fds); xsprintf(sfd, "%i", fileno(arg_serialization)); i = 0; args[i++] = SYSTEMD_BINARY_PATH; if (switch_root_dir) args[i++] = "--switched-root"; args[i++] = arg_running_as == MANAGER_SYSTEM ? "--system" : "--user"; args[i++] = "--deserialize"; args[i++] = sfd; args[i++] = NULL; /* do not pass along the environment we inherit from the kernel or initrd */ if (switch_root_dir) (void) clearenv(); assert(i <= args_size); /* * We want valgrind to print its memory usage summary before reexecution. * Valgrind won't do this is on its own on exec(), but it will do it on exit(). * Hence, to ensure we get a summary here, fork() off a child, let it exit() cleanly, * so that it prints the summary, and wait() for it in the parent, before proceeding into the exec(). */ valgrind_summary_hack(); (void) execv(args[0], (char* const*) args); } /* Try the fallback, if there is any, without any * serialization. We pass the original argv[] and * envp[]. (Well, modulo the ordering changes due to * getopt() in argv[], and some cleanups in envp[], * but let's hope that doesn't matter.) */ arg_serialization = safe_fclose(arg_serialization); fds = fdset_free(fds); /* Reopen the console */ (void) make_console_stdio(); for (j = 1, i = 1; j < (unsigned) argc; j++) args[i++] = argv[j]; args[i++] = NULL; assert(i <= args_size); /* Reenable any blocked signals, especially important * if we switch from initial ramdisk to init=... */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); if (switch_root_init) { args[0] = switch_root_init; (void) execv(args[0], (char* const*) args); log_warning_errno(errno, "Failed to execute configured init, trying fallback: %m"); } args[0] = "/sbin/init"; (void) execv(args[0], (char* const*) args); if (errno == ENOENT) { log_warning("No /sbin/init, trying fallback"); args[0] = "/bin/sh"; args[1] = NULL; (void) execv(args[0], (char* const*) args); log_error_errno(errno, "Failed to execute /bin/sh, giving up: %m"); } else log_warning_errno(errno, "Failed to execute /sbin/init, giving up: %m"); } arg_serialization = safe_fclose(arg_serialization); fds = fdset_free(fds); #ifdef HAVE_VALGRIND_VALGRIND_H /* If we are PID 1 and running under valgrind, then let's exit * here explicitly. valgrind will only generate nice output on * exit(), not on exec(), hence let's do the former not the * latter here. */ if (getpid() == 1 && RUNNING_ON_VALGRIND) return 0; #endif if (shutdown_verb) { char log_level[DECIMAL_STR_MAX(int) + 1]; char exit_code[DECIMAL_STR_MAX(uint8_t) + 1]; const char* command_line[11] = { SYSTEMD_SHUTDOWN_BINARY_PATH, shutdown_verb, "--log-level", log_level, "--log-target", }; unsigned pos = 5; _cleanup_strv_free_ char **env_block = NULL; assert(command_line[pos] == NULL); env_block = strv_copy(environ); xsprintf(log_level, "%d", log_get_max_level()); switch (log_get_target()) { case LOG_TARGET_KMSG: case LOG_TARGET_JOURNAL_OR_KMSG: case LOG_TARGET_SYSLOG_OR_KMSG: command_line[pos++] = "kmsg"; break; case LOG_TARGET_NULL: command_line[pos++] = "null"; break; case LOG_TARGET_CONSOLE: default: command_line[pos++] = "console"; break; }; if (log_get_show_color()) command_line[pos++] = "--log-color"; if (log_get_show_location()) command_line[pos++] = "--log-location"; if (streq(shutdown_verb, "exit")) { command_line[pos++] = "--exit-code"; command_line[pos++] = exit_code; xsprintf(exit_code, "%d", retval); } assert(pos < ELEMENTSOF(command_line)); if (arm_reboot_watchdog && arg_shutdown_watchdog > 0) { char *e; /* If we reboot let's set the shutdown * watchdog and tell the shutdown binary to * repeatedly ping it */ r = watchdog_set_timeout(&arg_shutdown_watchdog); watchdog_close(r < 0); /* Tell the binary how often to ping, ignore failure */ if (asprintf(&e, "WATCHDOG_USEC="USEC_FMT, arg_shutdown_watchdog) > 0) (void) strv_push(&env_block, e); } else watchdog_close(true); /* Avoid the creation of new processes forked by the * kernel; at this point, we will not listen to the * signals anyway */ if (detect_container() <= 0) (void) cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER); execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block); log_error_errno(errno, "Failed to execute shutdown binary, %s: %m", getpid() == 1 ? "freezing" : "quitting"); } if (getpid() == 1) { if (error_message) manager_status_printf(NULL, STATUS_TYPE_EMERGENCY, ANSI_HIGHLIGHT_RED "!!!!!!" ANSI_NORMAL, "%s, freezing.", error_message); freeze_or_reboot(); } return retval; } systemd-229/src/core/manager.c000066400000000000000000003074251265713322000163710ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_AUDIT #include #endif #include "sd-daemon.h" #include "sd-messages.h" #include "alloc-util.h" #include "audit-fd.h" #include "boot-timestamps.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-kernel.h" #include "bus-util.h" #include "dbus-job.h" #include "dbus-manager.h" #include "dbus-unit.h" #include "dbus.h" #include "env-util.h" #include "escape.h" #include "exit-status.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "hashmap.h" #include "io-util.h" #include "locale-setup.h" #include "log.h" #include "macro.h" #include "manager.h" #include "missing.h" #include "mkdir.h" #include "parse-util.h" #include "path-lookup.h" #include "path-util.h" #include "process-util.h" #include "ratelimit.h" #include "rm-rf.h" #include "signal-util.h" #include "special.h" #include "stat-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "time-util.h" #include "transaction.h" #include "umask-util.h" #include "unit-name.h" #include "util.h" #include "virt.h" #include "watchdog.h" #define NOTIFY_RCVBUF_SIZE (8*1024*1024) /* Initial delay and the interval for printing status messages about running jobs */ #define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC) #define JOBS_IN_PROGRESS_PERIOD_USEC (USEC_PER_SEC / 3) #define JOBS_IN_PROGRESS_PERIOD_DIVISOR 3 static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata); static int manager_dispatch_run_queue(sd_event_source *source, void *userdata); static int manager_run_generators(Manager *m); static void manager_undo_generators(Manager *m); static void manager_watch_jobs_in_progress(Manager *m) { usec_t next; int r; assert(m); if (m->jobs_in_progress_event_source) return; next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC; r = sd_event_add_time( m->event, &m->jobs_in_progress_event_source, CLOCK_MONOTONIC, next, 0, manager_dispatch_jobs_in_progress, m); if (r < 0) return; (void) sd_event_source_set_description(m->jobs_in_progress_event_source, "manager-jobs-in-progress"); } #define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED)-1) + sizeof(ANSI_HIGHLIGHT_RED)-1 + 2*(sizeof(ANSI_NORMAL)-1)) static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned pos) { char *p = buffer; assert(buflen >= CYLON_BUFFER_EXTRA + width + 1); assert(pos <= width+1); /* 0 or width+1 mean that the center light is behind the corner */ if (pos > 1) { if (pos > 2) p = mempset(p, ' ', pos-2); p = stpcpy(p, ANSI_RED); *p++ = '*'; } if (pos > 0 && pos <= width) { p = stpcpy(p, ANSI_HIGHLIGHT_RED); *p++ = '*'; } p = stpcpy(p, ANSI_NORMAL); if (pos < width) { p = stpcpy(p, ANSI_RED); *p++ = '*'; if (pos < width-1) p = mempset(p, ' ', width-1-pos); strcpy(p, ANSI_NORMAL); } } void manager_flip_auto_status(Manager *m, bool enable) { assert(m); if (enable) { if (m->show_status == SHOW_STATUS_AUTO) manager_set_show_status(m, SHOW_STATUS_TEMPORARY); } else { if (m->show_status == SHOW_STATUS_TEMPORARY) manager_set_show_status(m, SHOW_STATUS_AUTO); } } static void manager_print_jobs_in_progress(Manager *m) { _cleanup_free_ char *job_of_n = NULL; Iterator i; Job *j; unsigned counter = 0, print_nr; char cylon[6 + CYLON_BUFFER_EXTRA + 1]; unsigned cylon_pos; char time[FORMAT_TIMESPAN_MAX], limit[FORMAT_TIMESPAN_MAX] = "no limit"; uint64_t x; assert(m); assert(m->n_running_jobs > 0); manager_flip_auto_status(m, true); print_nr = (m->jobs_in_progress_iteration / JOBS_IN_PROGRESS_PERIOD_DIVISOR) % m->n_running_jobs; HASHMAP_FOREACH(j, m->jobs, i) if (j->state == JOB_RUNNING && counter++ == print_nr) break; /* m->n_running_jobs must be consistent with the contents of m->jobs, * so the above loop must have succeeded in finding j. */ assert(counter == print_nr + 1); assert(j); cylon_pos = m->jobs_in_progress_iteration % 14; if (cylon_pos >= 8) cylon_pos = 14 - cylon_pos; draw_cylon(cylon, sizeof(cylon), 6, cylon_pos); m->jobs_in_progress_iteration++; if (m->n_running_jobs > 1) { if (asprintf(&job_of_n, "(%u of %u) ", counter, m->n_running_jobs) < 0) job_of_n = NULL; } format_timespan(time, sizeof(time), now(CLOCK_MONOTONIC) - j->begin_usec, 1*USEC_PER_SEC); if (job_get_timeout(j, &x) > 0) format_timespan(limit, sizeof(limit), x - j->begin_usec, 1*USEC_PER_SEC); manager_status_printf(m, STATUS_TYPE_EPHEMERAL, cylon, "%sA %s job is running for %s (%s / %s)", strempty(job_of_n), job_type_to_string(j->type), unit_description(j->unit), time, limit); } static int have_ask_password(void) { _cleanup_closedir_ DIR *dir; dir = opendir("/run/systemd/ask-password"); if (!dir) { if (errno == ENOENT) return false; else return -errno; } for (;;) { struct dirent *de; errno = 0; de = readdir(dir); if (!de && errno > 0) return -errno; if (!de) return false; if (startswith(de->d_name, "ask.")) return true; } } static int manager_dispatch_ask_password_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; assert(m); flush_fd(fd); m->have_ask_password = have_ask_password(); if (m->have_ask_password < 0) /* Log error but continue. Negative have_ask_password * is treated as unknown status. */ log_error_errno(m->have_ask_password, "Failed to list /run/systemd/ask-password: %m"); return 0; } static void manager_close_ask_password(Manager *m) { assert(m); m->ask_password_event_source = sd_event_source_unref(m->ask_password_event_source); m->ask_password_inotify_fd = safe_close(m->ask_password_inotify_fd); m->have_ask_password = -EINVAL; } static int manager_check_ask_password(Manager *m) { int r; assert(m); if (!m->ask_password_event_source) { assert(m->ask_password_inotify_fd < 0); mkdir_p_label("/run/systemd/ask-password", 0755); m->ask_password_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (m->ask_password_inotify_fd < 0) return log_error_errno(errno, "inotify_init1() failed: %m"); if (inotify_add_watch(m->ask_password_inotify_fd, "/run/systemd/ask-password", IN_CREATE|IN_DELETE|IN_MOVE) < 0) { log_error_errno(errno, "Failed to add watch on /run/systemd/ask-password: %m"); manager_close_ask_password(m); return -errno; } r = sd_event_add_io(m->event, &m->ask_password_event_source, m->ask_password_inotify_fd, EPOLLIN, manager_dispatch_ask_password_fd, m); if (r < 0) { log_error_errno(errno, "Failed to add event source for /run/systemd/ask-password: %m"); manager_close_ask_password(m); return -errno; } (void) sd_event_source_set_description(m->ask_password_event_source, "manager-ask-password"); /* Queries might have been added meanwhile... */ manager_dispatch_ask_password_fd(m->ask_password_event_source, m->ask_password_inotify_fd, EPOLLIN, m); } return m->have_ask_password; } static int manager_watch_idle_pipe(Manager *m) { int r; assert(m); if (m->idle_pipe_event_source) return 0; if (m->idle_pipe[2] < 0) return 0; r = sd_event_add_io(m->event, &m->idle_pipe_event_source, m->idle_pipe[2], EPOLLIN, manager_dispatch_idle_pipe_fd, m); if (r < 0) return log_error_errno(r, "Failed to watch idle pipe: %m"); (void) sd_event_source_set_description(m->idle_pipe_event_source, "manager-idle-pipe"); return 0; } static void manager_close_idle_pipe(Manager *m) { assert(m); m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source); safe_close_pair(m->idle_pipe); safe_close_pair(m->idle_pipe + 2); } static int manager_setup_time_change(Manager *m) { int r; /* We only care for the cancellation event, hence we set the * timeout to the latest possible value. */ struct itimerspec its = { .it_value.tv_sec = TIME_T_MAX, }; assert(m); assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX)); if (m->test_run) return 0; /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever * CLOCK_REALTIME makes a jump relative to CLOCK_MONOTONIC */ m->time_change_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC); if (m->time_change_fd < 0) return log_error_errno(errno, "Failed to create timerfd: %m"); if (timerfd_settime(m->time_change_fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) { log_debug_errno(errno, "Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m"); m->time_change_fd = safe_close(m->time_change_fd); return 0; } r = sd_event_add_io(m->event, &m->time_change_event_source, m->time_change_fd, EPOLLIN, manager_dispatch_time_change_fd, m); if (r < 0) return log_error_errno(r, "Failed to create time change event source: %m"); (void) sd_event_source_set_description(m->time_change_event_source, "manager-time-change"); log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd."); return 0; } static int enable_special_signals(Manager *m) { _cleanup_close_ int fd = -1; assert(m); if (m->test_run) return 0; /* Enable that we get SIGINT on control-alt-del. In containers * this will fail with EPERM (older) or EINVAL (newer), so * ignore that. */ if (reboot(RB_DISABLE_CAD) < 0 && errno != EPERM && errno != EINVAL) log_warning_errno(errno, "Failed to enable ctrl-alt-del handling: %m"); fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) { /* Support systems without virtual console */ if (fd != -ENOENT) log_warning_errno(errno, "Failed to open /dev/tty0: %m"); } else { /* Enable that we get SIGWINCH on kbrequest */ if (ioctl(fd, KDSIGACCEPT, SIGWINCH) < 0) log_warning_errno(errno, "Failed to enable kbrequest handling: %m"); } return 0; } static int manager_setup_signals(Manager *m) { struct sigaction sa = { .sa_handler = SIG_DFL, .sa_flags = SA_NOCLDSTOP|SA_RESTART, }; sigset_t mask; int r; assert(m); assert_se(sigaction(SIGCHLD, &sa, NULL) == 0); /* We make liberal use of realtime signals here. On * Linux/glibc we have 30 of them (with the exception of Linux * on hppa, see below), between SIGRTMIN+0 ... SIGRTMIN+30 * (aka SIGRTMAX). */ assert_se(sigemptyset(&mask) == 0); sigset_add_many(&mask, SIGCHLD, /* Child died */ SIGTERM, /* Reexecute daemon */ SIGHUP, /* Reload configuration */ SIGUSR1, /* systemd/upstart: reconnect to D-Bus */ SIGUSR2, /* systemd: dump status */ SIGINT, /* Kernel sends us this on control-alt-del */ SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */ SIGPWR, /* Some kernel drivers and upsd send us this on power failure */ SIGRTMIN+0, /* systemd: start default.target */ SIGRTMIN+1, /* systemd: isolate rescue.target */ SIGRTMIN+2, /* systemd: isolate emergency.target */ SIGRTMIN+3, /* systemd: start halt.target */ SIGRTMIN+4, /* systemd: start poweroff.target */ SIGRTMIN+5, /* systemd: start reboot.target */ SIGRTMIN+6, /* systemd: start kexec.target */ /* ... space for more special targets ... */ SIGRTMIN+13, /* systemd: Immediate halt */ SIGRTMIN+14, /* systemd: Immediate poweroff */ SIGRTMIN+15, /* systemd: Immediate reboot */ SIGRTMIN+16, /* systemd: Immediate kexec */ /* ... space for more immediate system state changes ... */ SIGRTMIN+20, /* systemd: enable status messages */ SIGRTMIN+21, /* systemd: disable status messages */ SIGRTMIN+22, /* systemd: set log level to LOG_DEBUG */ SIGRTMIN+23, /* systemd: set log level to LOG_INFO */ SIGRTMIN+24, /* systemd: Immediate exit (--user only) */ /* .. one free signal here ... */ #if !defined(__hppa64__) && !defined(__hppa__) /* Apparently Linux on hppa has fewer RT * signals (SIGRTMAX is SIGRTMIN+25 there), * hence let's not try to make use of them * here. Since these commands are accessible * by different means and only really a safety * net, the missing functionality on hppa * shouldn't matter. */ SIGRTMIN+26, /* systemd: set log target to journal-or-kmsg */ SIGRTMIN+27, /* systemd: set log target to console */ SIGRTMIN+28, /* systemd: set log target to kmsg */ SIGRTMIN+29, /* systemd: set log target to syslog-or-kmsg (obsolete) */ /* ... one free signal here SIGRTMIN+30 ... */ #endif -1); assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); m->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); if (m->signal_fd < 0) return -errno; r = sd_event_add_io(m->event, &m->signal_event_source, m->signal_fd, EPOLLIN, manager_dispatch_signal_fd, m); if (r < 0) return r; (void) sd_event_source_set_description(m->signal_event_source, "manager-signal"); /* Process signals a bit earlier than the rest of things, but * later than notify_fd processing, so that the notify * processing can still figure out to which process/service a * message belongs, before we reap the process. */ r = sd_event_source_set_priority(m->signal_event_source, SD_EVENT_PRIORITY_NORMAL-5); if (r < 0) return r; if (m->running_as == MANAGER_SYSTEM) return enable_special_signals(m); return 0; } static void manager_clean_environment(Manager *m) { assert(m); /* Let's remove some environment variables that we * need ourselves to communicate with our clients */ strv_env_unset_many( m->environment, "NOTIFY_SOCKET", "MAINPID", "MANAGERPID", "LISTEN_PID", "LISTEN_FDS", "LISTEN_FDNAMES", "WATCHDOG_PID", "WATCHDOG_USEC", NULL); } static int manager_default_environment(Manager *m) { assert(m); if (m->running_as == MANAGER_SYSTEM) { /* The system manager always starts with a clean * environment for its children. It does not import * the kernel or the parents exported variables. * * The initial passed environ is untouched to keep * /proc/self/environ valid; it is used for tagging * the init process inside containers. */ m->environment = strv_new("PATH=" DEFAULT_PATH, NULL); /* Import locale variables LC_*= from configuration */ locale_setup(&m->environment); } else { /* The user manager passes its own environment * along to its children. */ m->environment = strv_copy(environ); } if (!m->environment) return -ENOMEM; manager_clean_environment(m); strv_sort(m->environment); return 0; } int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) { static const char * const unit_log_fields[_MANAGER_RUNNING_AS_MAX] = { [MANAGER_SYSTEM] = "UNIT=", [MANAGER_USER] = "USER_UNIT=", }; static const char * const unit_log_format_strings[_MANAGER_RUNNING_AS_MAX] = { [MANAGER_SYSTEM] = "UNIT=%s", [MANAGER_USER] = "USER_UNIT=%s", }; Manager *m; int r; assert(_m); assert(running_as >= 0); assert(running_as < _MANAGER_RUNNING_AS_MAX); m = new0(Manager, 1); if (!m) return -ENOMEM; #ifdef ENABLE_EFI if (running_as == MANAGER_SYSTEM && detect_container() <= 0) boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp); #endif m->running_as = running_as; m->exit_code = _MANAGER_EXIT_CODE_INVALID; m->default_timer_accuracy_usec = USEC_PER_MINUTE; m->default_tasks_accounting = true; m->default_tasks_max = UINT64_C(512); /* Prepare log fields we can use for structured logging */ m->unit_log_field = unit_log_fields[running_as]; m->unit_log_format_string = unit_log_format_strings[running_as]; m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1; m->pin_cgroupfs_fd = m->notify_fd = m->signal_fd = m->time_change_fd = m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->cgroup_inotify_fd = -1; m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */ m->ask_password_inotify_fd = -1; m->have_ask_password = -EINVAL; /* we don't know */ m->first_boot = -1; m->test_run = test_run; /* Reboot immediately if the user hits C-A-D more often than 7x per 2s */ RATELIMIT_INIT(m->ctrl_alt_del_ratelimit, 2 * USEC_PER_SEC, 7); r = manager_default_environment(m); if (r < 0) goto fail; r = hashmap_ensure_allocated(&m->units, &string_hash_ops); if (r < 0) goto fail; r = hashmap_ensure_allocated(&m->jobs, NULL); if (r < 0) goto fail; r = hashmap_ensure_allocated(&m->cgroup_unit, &string_hash_ops); if (r < 0) goto fail; r = hashmap_ensure_allocated(&m->watch_bus, &string_hash_ops); if (r < 0) goto fail; r = sd_event_default(&m->event); if (r < 0) goto fail; r = sd_event_add_defer(m->event, &m->run_queue_event_source, manager_dispatch_run_queue, m); if (r < 0) goto fail; r = sd_event_source_set_priority(m->run_queue_event_source, SD_EVENT_PRIORITY_IDLE); if (r < 0) goto fail; r = sd_event_source_set_enabled(m->run_queue_event_source, SD_EVENT_OFF); if (r < 0) goto fail; (void) sd_event_source_set_description(m->run_queue_event_source, "manager-run-queue"); r = manager_setup_signals(m); if (r < 0) goto fail; r = manager_setup_cgroup(m); if (r < 0) goto fail; r = manager_setup_time_change(m); if (r < 0) goto fail; m->udev = udev_new(); if (!m->udev) { r = -ENOMEM; goto fail; } /* Note that we set up neither kdbus, nor the notify fd * here. We do that after deserialization, since they might * have gotten serialized across the reexec. */ m->taint_usr = dir_is_empty("/usr") > 0; *_m = m; return 0; fail: manager_free(m); return r; } static int manager_setup_notify(Manager *m) { int r; if (m->test_run) return 0; if (m->notify_fd < 0) { _cleanup_close_ int fd = -1; union sockaddr_union sa = { .sa.sa_family = AF_UNIX, }; static const int one = 1; /* First free all secondary fields */ m->notify_socket = mfree(m->notify_socket); m->notify_event_source = sd_event_source_unref(m->notify_event_source); fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (fd < 0) return log_error_errno(errno, "Failed to allocate notification socket: %m"); fd_inc_rcvbuf(fd, NOTIFY_RCVBUF_SIZE); if (m->running_as == MANAGER_SYSTEM) m->notify_socket = strdup("/run/systemd/notify"); else { const char *e; e = getenv("XDG_RUNTIME_DIR"); if (!e) { log_error_errno(errno, "XDG_RUNTIME_DIR is not set: %m"); return -EINVAL; } m->notify_socket = strappend(e, "/systemd/notify"); } if (!m->notify_socket) return log_oom(); (void) mkdir_parents_label(m->notify_socket, 0755); (void) unlink(m->notify_socket); strncpy(sa.un.sun_path, m->notify_socket, sizeof(sa.un.sun_path)-1); r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)); if (r < 0) return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); r = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); if (r < 0) return log_error_errno(errno, "SO_PASSCRED failed: %m"); m->notify_fd = fd; fd = -1; log_debug("Using notification socket %s", m->notify_socket); } if (!m->notify_event_source) { r = sd_event_add_io(m->event, &m->notify_event_source, m->notify_fd, EPOLLIN, manager_dispatch_notify_fd, m); if (r < 0) return log_error_errno(r, "Failed to allocate notify event source: %m"); /* Process signals a bit earlier than SIGCHLD, so that we can * still identify to which service an exit message belongs */ r = sd_event_source_set_priority(m->notify_event_source, SD_EVENT_PRIORITY_NORMAL-7); if (r < 0) return log_error_errno(r, "Failed to set priority of notify event source: %m"); (void) sd_event_source_set_description(m->notify_event_source, "manager-notify"); } return 0; } static int manager_setup_kdbus(Manager *m) { _cleanup_free_ char *p = NULL; assert(m); if (m->test_run || m->kdbus_fd >= 0) return 0; if (!is_kdbus_available()) return -ESOCKTNOSUPPORT; m->kdbus_fd = bus_kernel_create_bus( m->running_as == MANAGER_SYSTEM ? "system" : "user", m->running_as == MANAGER_SYSTEM, &p); if (m->kdbus_fd < 0) return log_debug_errno(m->kdbus_fd, "Failed to set up kdbus: %m"); log_debug("Successfully set up kdbus on %s", p); return 0; } static int manager_connect_bus(Manager *m, bool reexecuting) { bool try_bus_connect; assert(m); if (m->test_run) return 0; try_bus_connect = m->kdbus_fd >= 0 || reexecuting || (m->running_as == MANAGER_USER && getenv("DBUS_SESSION_BUS_ADDRESS")); /* Try to connect to the buses, if possible. */ return bus_init(m, try_bus_connect); } static unsigned manager_dispatch_cleanup_queue(Manager *m) { Unit *u; unsigned n = 0; assert(m); while ((u = m->cleanup_queue)) { assert(u->in_cleanup_queue); unit_free(u); n++; } return n; } enum { GC_OFFSET_IN_PATH, /* This one is on the path we were traveling */ GC_OFFSET_UNSURE, /* No clue */ GC_OFFSET_GOOD, /* We still need this unit */ GC_OFFSET_BAD, /* We don't need this unit anymore */ _GC_OFFSET_MAX }; static void unit_gc_sweep(Unit *u, unsigned gc_marker) { Iterator i; Unit *other; bool is_bad; assert(u); if (u->gc_marker == gc_marker + GC_OFFSET_GOOD || u->gc_marker == gc_marker + GC_OFFSET_BAD || u->gc_marker == gc_marker + GC_OFFSET_IN_PATH) return; if (u->in_cleanup_queue) goto bad; if (unit_check_gc(u)) goto good; u->gc_marker = gc_marker + GC_OFFSET_IN_PATH; is_bad = true; SET_FOREACH(other, u->dependencies[UNIT_REFERENCED_BY], i) { unit_gc_sweep(other, gc_marker); if (other->gc_marker == gc_marker + GC_OFFSET_GOOD) goto good; if (other->gc_marker != gc_marker + GC_OFFSET_BAD) is_bad = false; } if (is_bad) goto bad; /* We were unable to find anything out about this entry, so * let's investigate it later */ u->gc_marker = gc_marker + GC_OFFSET_UNSURE; unit_add_to_gc_queue(u); return; bad: /* We definitely know that this one is not useful anymore, so * let's mark it for deletion */ u->gc_marker = gc_marker + GC_OFFSET_BAD; unit_add_to_cleanup_queue(u); return; good: u->gc_marker = gc_marker + GC_OFFSET_GOOD; } static unsigned manager_dispatch_gc_queue(Manager *m) { Unit *u; unsigned n = 0; unsigned gc_marker; assert(m); /* log_debug("Running GC..."); */ m->gc_marker += _GC_OFFSET_MAX; if (m->gc_marker + _GC_OFFSET_MAX <= _GC_OFFSET_MAX) m->gc_marker = 1; gc_marker = m->gc_marker; while ((u = m->gc_queue)) { assert(u->in_gc_queue); unit_gc_sweep(u, gc_marker); LIST_REMOVE(gc_queue, m->gc_queue, u); u->in_gc_queue = false; n++; if (u->gc_marker == gc_marker + GC_OFFSET_BAD || u->gc_marker == gc_marker + GC_OFFSET_UNSURE) { if (u->id) log_unit_debug(u, "Collecting."); u->gc_marker = gc_marker + GC_OFFSET_BAD; unit_add_to_cleanup_queue(u); } } m->n_in_gc_queue = 0; return n; } static void manager_clear_jobs_and_units(Manager *m) { Unit *u; assert(m); while ((u = hashmap_first(m->units))) unit_free(u); manager_dispatch_cleanup_queue(m); assert(!m->load_queue); assert(!m->run_queue); assert(!m->dbus_unit_queue); assert(!m->dbus_job_queue); assert(!m->cleanup_queue); assert(!m->gc_queue); assert(hashmap_isempty(m->jobs)); assert(hashmap_isempty(m->units)); m->n_on_console = 0; m->n_running_jobs = 0; } Manager* manager_free(Manager *m) { UnitType c; int i; if (!m) return NULL; manager_clear_jobs_and_units(m); for (c = 0; c < _UNIT_TYPE_MAX; c++) if (unit_vtable[c]->shutdown) unit_vtable[c]->shutdown(m); /* If we reexecute ourselves, we keep the root cgroup * around */ manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE); manager_undo_generators(m); bus_done(m); hashmap_free(m->units); hashmap_free(m->jobs); hashmap_free(m->watch_pids1); hashmap_free(m->watch_pids2); hashmap_free(m->watch_bus); set_free(m->startup_units); set_free(m->failed_units); sd_event_source_unref(m->signal_event_source); sd_event_source_unref(m->notify_event_source); sd_event_source_unref(m->time_change_event_source); sd_event_source_unref(m->jobs_in_progress_event_source); sd_event_source_unref(m->run_queue_event_source); safe_close(m->signal_fd); safe_close(m->notify_fd); safe_close(m->time_change_fd); safe_close(m->kdbus_fd); manager_close_ask_password(m); manager_close_idle_pipe(m); udev_unref(m->udev); sd_event_unref(m->event); free(m->notify_socket); lookup_paths_free(&m->lookup_paths); strv_free(m->environment); hashmap_free(m->cgroup_unit); set_free_free(m->unit_path_cache); free(m->switch_root); free(m->switch_root_init); for (i = 0; i < _RLIMIT_MAX; i++) m->rlimit[i] = mfree(m->rlimit[i]); assert(hashmap_isempty(m->units_requiring_mounts_for)); hashmap_free(m->units_requiring_mounts_for); free(m); return NULL; } void manager_enumerate(Manager *m) { UnitType c; assert(m); /* Let's ask every type to load all units from disk/kernel * that it might know */ for (c = 0; c < _UNIT_TYPE_MAX; c++) { if (!unit_type_supported(c)) { log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c)); continue; } if (!unit_vtable[c]->enumerate) continue; unit_vtable[c]->enumerate(m); } manager_dispatch_load_queue(m); } static void manager_coldplug(Manager *m) { Iterator i; Unit *u; char *k; int r; assert(m); /* Then, let's set up their initial state. */ HASHMAP_FOREACH_KEY(u, k, m->units, i) { /* ignore aliases */ if (u->id != k) continue; r = unit_coldplug(u); if (r < 0) log_warning_errno(r, "We couldn't coldplug %s, proceeding anyway: %m", u->id); } } static void manager_build_unit_path_cache(Manager *m) { char **i; _cleanup_closedir_ DIR *d = NULL; int r; assert(m); set_free_free(m->unit_path_cache); m->unit_path_cache = set_new(&string_hash_ops); if (!m->unit_path_cache) { log_error("Failed to allocate unit path cache."); return; } /* This simply builds a list of files we know exist, so that * we don't always have to go to disk */ STRV_FOREACH(i, m->lookup_paths.unit_path) { struct dirent *de; d = opendir(*i); if (!d) { if (errno != ENOENT) log_error_errno(errno, "Failed to open directory %s: %m", *i); continue; } while ((de = readdir(d))) { char *p; if (hidden_file(de->d_name)) continue; p = strjoin(streq(*i, "/") ? "" : *i, "/", de->d_name, NULL); if (!p) { r = -ENOMEM; goto fail; } r = set_consume(m->unit_path_cache, p); if (r < 0) goto fail; } d = safe_closedir(d); } return; fail: log_error_errno(r, "Failed to build unit path cache: %m"); set_free_free(m->unit_path_cache); m->unit_path_cache = NULL; } static void manager_distribute_fds(Manager *m, FDSet *fds) { Iterator i; Unit *u; assert(m); HASHMAP_FOREACH(u, m->units, i) { if (fdset_size(fds) <= 0) break; if (!UNIT_VTABLE(u)->distribute_fds) continue; UNIT_VTABLE(u)->distribute_fds(u, fds); } } int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { int r, q; assert(m); dual_timestamp_get(&m->generators_start_timestamp); r = manager_run_generators(m); dual_timestamp_get(&m->generators_finish_timestamp); if (r < 0) return r; r = lookup_paths_init( &m->lookup_paths, m->running_as, true, NULL, m->generator_unit_path, m->generator_unit_path_early, m->generator_unit_path_late); if (r < 0) return r; manager_build_unit_path_cache(m); /* If we will deserialize make sure that during enumeration * this is already known, so we increase the counter here * already */ if (serialization) m->n_reloading ++; /* First, enumerate what we can from all config files */ dual_timestamp_get(&m->units_load_start_timestamp); manager_enumerate(m); dual_timestamp_get(&m->units_load_finish_timestamp); /* Second, deserialize if there is something to deserialize */ if (serialization) r = manager_deserialize(m, serialization, fds); /* Any fds left? Find some unit which wants them. This is * useful to allow container managers to pass some file * descriptors to us pre-initialized. This enables * socket-based activation of entire containers. */ manager_distribute_fds(m, fds); /* We might have deserialized the notify fd, but if we didn't * then let's create the bus now */ q = manager_setup_notify(m); if (q < 0 && r == 0) r = q; /* We might have deserialized the kdbus control fd, but if we * didn't, then let's create the bus now. */ manager_setup_kdbus(m); manager_connect_bus(m, !!serialization); bus_track_coldplug(m, &m->subscribed, &m->deserialized_subscribed); /* Third, fire things up! */ manager_coldplug(m); if (serialization) { assert(m->n_reloading > 0); m->n_reloading --; /* Let's wait for the UnitNew/JobNew messages being * sent, before we notify that the reload is * finished */ m->send_reloading_done = true; } return r; } int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret) { int r; Transaction *tr; assert(m); assert(type < _JOB_TYPE_MAX); assert(unit); assert(mode < _JOB_MODE_MAX); if (mode == JOB_ISOLATE && type != JOB_START) return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start."); if (mode == JOB_ISOLATE && !unit->allow_isolate) return sd_bus_error_setf(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated."); log_unit_debug(unit, "Trying to enqueue job %s/%s/%s", unit->id, job_type_to_string(type), job_mode_to_string(mode)); type = job_type_collapse(type, unit); tr = transaction_new(mode == JOB_REPLACE_IRREVERSIBLY); if (!tr) return -ENOMEM; r = transaction_add_job_and_dependencies(tr, type, unit, NULL, true, false, mode == JOB_IGNORE_DEPENDENCIES || mode == JOB_IGNORE_REQUIREMENTS, mode == JOB_IGNORE_DEPENDENCIES, e); if (r < 0) goto tr_abort; if (mode == JOB_ISOLATE) { r = transaction_add_isolate_jobs(tr, m); if (r < 0) goto tr_abort; } r = transaction_activate(tr, m, mode, e); if (r < 0) goto tr_abort; log_unit_debug(unit, "Enqueued job %s/%s as %u", unit->id, job_type_to_string(type), (unsigned) tr->anchor_job->id); if (_ret) *_ret = tr->anchor_job; transaction_free(tr); return 0; tr_abort: transaction_abort(tr); transaction_free(tr); return r; } int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, sd_bus_error *e, Job **ret) { Unit *unit; int r; assert(m); assert(type < _JOB_TYPE_MAX); assert(name); assert(mode < _JOB_MODE_MAX); r = manager_load_unit(m, name, NULL, NULL, &unit); if (r < 0) return r; return manager_add_job(m, type, unit, mode, e, ret); } int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Job **ret) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(m); assert(type < _JOB_TYPE_MAX); assert(name); assert(mode < _JOB_MODE_MAX); r = manager_add_job_by_name(m, type, name, mode, &error, ret); if (r < 0) return log_warning_errno(r, "Failed to enqueue %s job for %s: %s", job_mode_to_string(mode), name, bus_error_message(&error, r)); return r; } Job *manager_get_job(Manager *m, uint32_t id) { assert(m); return hashmap_get(m->jobs, UINT32_TO_PTR(id)); } Unit *manager_get_unit(Manager *m, const char *name) { assert(m); assert(name); return hashmap_get(m->units, name); } unsigned manager_dispatch_load_queue(Manager *m) { Unit *u; unsigned n = 0; assert(m); /* Make sure we are not run recursively */ if (m->dispatching_load_queue) return 0; m->dispatching_load_queue = true; /* Dispatches the load queue. Takes a unit from the queue and * tries to load its data until the queue is empty */ while ((u = m->load_queue)) { assert(u->in_load_queue); unit_load(u); n++; } m->dispatching_load_queue = false; return n; } int manager_load_unit_prepare( Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret) { Unit *ret; UnitType t; int r; assert(m); assert(name || path); /* This will prepare the unit for loading, but not actually * load anything from disk. */ if (path && !is_path(path)) return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path); if (!name) name = basename(path); t = unit_name_to_type(name); if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name); ret = manager_get_unit(m, name); if (ret) { *_ret = ret; return 1; } ret = unit_new(m, unit_vtable[t]->object_size); if (!ret) return -ENOMEM; if (path) { ret->fragment_path = strdup(path); if (!ret->fragment_path) { unit_free(ret); return -ENOMEM; } } r = unit_add_name(ret, name); if (r < 0) { unit_free(ret); return r; } unit_add_to_load_queue(ret); unit_add_to_dbus_queue(ret); unit_add_to_gc_queue(ret); if (_ret) *_ret = ret; return 0; } int manager_load_unit( Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret) { int r; assert(m); /* This will load the service information files, but not actually * start any services or anything. */ r = manager_load_unit_prepare(m, name, path, e, _ret); if (r != 0) return r; manager_dispatch_load_queue(m); if (_ret) *_ret = unit_follow_merge(*_ret); return 0; } void manager_dump_jobs(Manager *s, FILE *f, const char *prefix) { Iterator i; Job *j; assert(s); assert(f); HASHMAP_FOREACH(j, s->jobs, i) job_dump(j, f, prefix); } void manager_dump_units(Manager *s, FILE *f, const char *prefix) { Iterator i; Unit *u; const char *t; assert(s); assert(f); HASHMAP_FOREACH_KEY(u, t, s->units, i) if (u->id == t) unit_dump(u, f, prefix); } void manager_clear_jobs(Manager *m) { Job *j; assert(m); while ((j = hashmap_first(m->jobs))) /* No need to recurse. We're cancelling all jobs. */ job_finish_and_invalidate(j, JOB_CANCELED, false); } static int manager_dispatch_run_queue(sd_event_source *source, void *userdata) { Manager *m = userdata; Job *j; assert(source); assert(m); while ((j = m->run_queue)) { assert(j->installed); assert(j->in_run_queue); job_run_and_invalidate(j); } if (m->n_running_jobs > 0) manager_watch_jobs_in_progress(m); if (m->n_on_console > 0) manager_watch_idle_pipe(m); return 1; } static unsigned manager_dispatch_dbus_queue(Manager *m) { Job *j; Unit *u; unsigned n = 0; assert(m); if (m->dispatching_dbus_queue) return 0; m->dispatching_dbus_queue = true; while ((u = m->dbus_unit_queue)) { assert(u->in_dbus_queue); bus_unit_send_change_signal(u); n++; } while ((j = m->dbus_job_queue)) { assert(j->in_dbus_queue); bus_job_send_change_signal(j); n++; } m->dispatching_dbus_queue = false; if (m->send_reloading_done) { m->send_reloading_done = false; bus_manager_send_reloading(m, false); } if (m->queued_message) bus_send_queued_message(m); return n; } static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, const char *buf, size_t n, FDSet *fds) { _cleanup_strv_free_ char **tags = NULL; assert(m); assert(u); assert(buf); assert(n > 0); tags = strv_split(buf, "\n\r"); if (!tags) { log_oom(); return; } if (UNIT_VTABLE(u)->notify_message) UNIT_VTABLE(u)->notify_message(u, pid, tags, fds); else log_unit_debug(u, "Got notification message for unit. Ignoring."); } static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { _cleanup_fdset_free_ FDSet *fds = NULL; Manager *m = userdata; char buf[NOTIFY_BUFFER_MAX+1]; struct iovec iovec = { .iov_base = buf, .iov_len = sizeof(buf)-1, }; union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)]; } control = {}; struct msghdr msghdr = { .msg_iov = &iovec, .msg_iovlen = 1, .msg_control = &control, .msg_controllen = sizeof(control), }; struct cmsghdr *cmsg; struct ucred *ucred = NULL; bool found = false; Unit *u1, *u2, *u3; int r, *fd_array = NULL; unsigned n_fds = 0; ssize_t n; assert(m); assert(m->notify_fd == fd); if (revents != EPOLLIN) { log_warning("Got unexpected poll event for notify fd."); return 0; } n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); if (n < 0) { if (errno == EAGAIN || errno == EINTR) return 0; return -errno; } CMSG_FOREACH(cmsg, &msghdr) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { fd_array = (int*) CMSG_DATA(cmsg); n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); } else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { ucred = (struct ucred*) CMSG_DATA(cmsg); } } if (n_fds > 0) { assert(fd_array); r = fdset_new_array(&fds, fd_array, n_fds); if (r < 0) { close_many(fd_array, n_fds); return log_oom(); } } if (!ucred || ucred->pid <= 0) { log_warning("Received notify message without valid credentials. Ignoring."); return 0; } if ((size_t) n >= sizeof(buf)) { log_warning("Received notify message exceeded maximum size. Ignoring."); return 0; } buf[n] = 0; /* Notify every unit that might be interested, but try * to avoid notifying the same one multiple times. */ u1 = manager_get_unit_by_pid_cgroup(m, ucred->pid); if (u1) { manager_invoke_notify_message(m, u1, ucred->pid, buf, n, fds); found = true; } u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(ucred->pid)); if (u2 && u2 != u1) { manager_invoke_notify_message(m, u2, ucred->pid, buf, n, fds); found = true; } u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(ucred->pid)); if (u3 && u3 != u2 && u3 != u1) { manager_invoke_notify_message(m, u3, ucred->pid, buf, n, fds); found = true; } if (!found) log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid); if (fdset_size(fds) > 0) log_warning("Got auxiliary fds with notification message, closing all."); return 0; } static void invoke_sigchld_event(Manager *m, Unit *u, const siginfo_t *si) { assert(m); assert(u); assert(si); log_unit_debug(u, "Child "PID_FMT" belongs to %s", si->si_pid, u->id); unit_unwatch_pid(u, si->si_pid); UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status); } static int manager_dispatch_sigchld(Manager *m) { assert(m); for (;;) { siginfo_t si = {}; /* First we call waitd() for a PID and do not reap the * zombie. That way we can still access /proc/$PID for * it while it is a zombie. */ if (waitid(P_ALL, 0, &si, WEXITED|WNOHANG|WNOWAIT) < 0) { if (errno == ECHILD) break; if (errno == EINTR) continue; return -errno; } if (si.si_pid <= 0) break; if (si.si_code == CLD_EXITED || si.si_code == CLD_KILLED || si.si_code == CLD_DUMPED) { _cleanup_free_ char *name = NULL; Unit *u1, *u2, *u3; get_process_comm(si.si_pid, &name); log_debug("Child "PID_FMT" (%s) died (code=%s, status=%i/%s)", si.si_pid, strna(name), sigchld_code_to_string(si.si_code), si.si_status, strna(si.si_code == CLD_EXITED ? exit_status_to_string(si.si_status, EXIT_STATUS_FULL) : signal_to_string(si.si_status))); /* And now figure out the unit this belongs * to, it might be multiple... */ u1 = manager_get_unit_by_pid_cgroup(m, si.si_pid); if (u1) invoke_sigchld_event(m, u1, &si); u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(si.si_pid)); if (u2 && u2 != u1) invoke_sigchld_event(m, u2, &si); u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(si.si_pid)); if (u3 && u3 != u2 && u3 != u1) invoke_sigchld_event(m, u3, &si); } /* And now, we actually reap the zombie. */ if (waitid(P_PID, si.si_pid, &si, WEXITED) < 0) { if (errno == EINTR) continue; return -errno; } } return 0; } static int manager_start_target(Manager *m, const char *name, JobMode mode) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; log_debug("Activating special unit %s", name); r = manager_add_job_by_name(m, JOB_START, name, mode, &error, NULL); if (r < 0) log_error("Failed to enqueue %s job: %s", name, bus_error_message(&error, r)); return r; } static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; ssize_t n; struct signalfd_siginfo sfsi; bool sigchld = false; int r; assert(m); assert(m->signal_fd == fd); if (revents != EPOLLIN) { log_warning("Got unexpected events from signal file descriptor."); return 0; } for (;;) { n = read(m->signal_fd, &sfsi, sizeof(sfsi)); if (n != sizeof(sfsi)) { if (n >= 0) return -EIO; if (errno == EINTR || errno == EAGAIN) break; return -errno; } log_received_signal(sfsi.ssi_signo == SIGCHLD || (sfsi.ssi_signo == SIGTERM && m->running_as == MANAGER_USER) ? LOG_DEBUG : LOG_INFO, &sfsi); switch (sfsi.ssi_signo) { case SIGCHLD: sigchld = true; break; case SIGTERM: if (m->running_as == MANAGER_SYSTEM) { /* This is for compatibility with the * original sysvinit */ m->exit_code = MANAGER_REEXECUTE; break; } /* Fall through */ case SIGINT: if (m->running_as == MANAGER_SYSTEM) { /* If the user presses C-A-D more than * 7 times within 2s, we reboot * immediately. */ if (ratelimit_test(&m->ctrl_alt_del_ratelimit)) manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY); else { log_notice("Ctrl-Alt-Del was pressed more than 7 times within 2s, rebooting immediately."); status_printf(NULL, true, false, "Ctrl-Alt-Del was pressed more than 7 times within 2s, rebooting immediately."); m->exit_code = MANAGER_REBOOT; } break; } /* Run the exit target if there is one, if not, just exit. */ if (manager_start_target(m, SPECIAL_EXIT_TARGET, JOB_REPLACE) < 0) { m->exit_code = MANAGER_EXIT; return 0; } break; case SIGWINCH: if (m->running_as == MANAGER_SYSTEM) manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE); /* This is a nop on non-init */ break; case SIGPWR: if (m->running_as == MANAGER_SYSTEM) manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE); /* This is a nop on non-init */ break; case SIGUSR1: { Unit *u; u = manager_get_unit(m, SPECIAL_DBUS_SERVICE); if (!u || UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) { log_info("Trying to reconnect to bus..."); bus_init(m, true); } if (!u || !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) { log_info("Loading D-Bus service..."); manager_start_target(m, SPECIAL_DBUS_SERVICE, JOB_REPLACE); } break; } case SIGUSR2: { _cleanup_free_ char *dump = NULL; _cleanup_fclose_ FILE *f = NULL; size_t size; f = open_memstream(&dump, &size); if (!f) { log_warning_errno(errno, "Failed to allocate memory stream: %m"); break; } manager_dump_units(m, f, "\t"); manager_dump_jobs(m, f, "\t"); r = fflush_and_check(f); if (r < 0) { log_warning_errno(r, "Failed to write status stream: %m"); break; } log_dump(LOG_INFO, dump); break; } case SIGHUP: m->exit_code = MANAGER_RELOAD; break; default: { /* Starting SIGRTMIN+0 */ static const char * const target_table[] = { [0] = SPECIAL_DEFAULT_TARGET, [1] = SPECIAL_RESCUE_TARGET, [2] = SPECIAL_EMERGENCY_TARGET, [3] = SPECIAL_HALT_TARGET, [4] = SPECIAL_POWEROFF_TARGET, [5] = SPECIAL_REBOOT_TARGET, [6] = SPECIAL_KEXEC_TARGET }; /* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */ static const ManagerExitCode code_table[] = { [0] = MANAGER_HALT, [1] = MANAGER_POWEROFF, [2] = MANAGER_REBOOT, [3] = MANAGER_KEXEC }; if ((int) sfsi.ssi_signo >= SIGRTMIN+0 && (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) { int idx = (int) sfsi.ssi_signo - SIGRTMIN; manager_start_target(m, target_table[idx], (idx == 1 || idx == 2) ? JOB_ISOLATE : JOB_REPLACE); break; } if ((int) sfsi.ssi_signo >= SIGRTMIN+13 && (int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(code_table)) { m->exit_code = code_table[sfsi.ssi_signo - SIGRTMIN - 13]; break; } switch (sfsi.ssi_signo - SIGRTMIN) { case 20: manager_set_show_status(m, SHOW_STATUS_YES); break; case 21: manager_set_show_status(m, SHOW_STATUS_NO); break; case 22: log_set_max_level(LOG_DEBUG); log_info("Setting log level to debug."); break; case 23: log_set_max_level(LOG_INFO); log_info("Setting log level to info."); break; case 24: if (m->running_as == MANAGER_USER) { m->exit_code = MANAGER_EXIT; return 0; } /* This is a nop on init */ break; case 26: case 29: /* compatibility: used to be mapped to LOG_TARGET_SYSLOG_OR_KMSG */ log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); log_notice("Setting log target to journal-or-kmsg."); break; case 27: log_set_target(LOG_TARGET_CONSOLE); log_notice("Setting log target to console."); break; case 28: log_set_target(LOG_TARGET_KMSG); log_notice("Setting log target to kmsg."); break; default: log_warning("Got unhandled signal <%s>.", signal_to_string(sfsi.ssi_signo)); } } } } if (sigchld) manager_dispatch_sigchld(m); return 0; } static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; Iterator i; Unit *u; assert(m); assert(m->time_change_fd == fd); log_struct(LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_TIME_CHANGE), LOG_MESSAGE("Time has been changed"), NULL); /* Restart the watch */ m->time_change_event_source = sd_event_source_unref(m->time_change_event_source); m->time_change_fd = safe_close(m->time_change_fd); manager_setup_time_change(m); HASHMAP_FOREACH(u, m->units, i) if (UNIT_VTABLE(u)->time_change) UNIT_VTABLE(u)->time_change(u); return 0; } static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; assert(m); assert(m->idle_pipe[2] == fd); m->no_console_output = m->n_on_console > 0; manager_close_idle_pipe(m); return 0; } static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata) { Manager *m = userdata; int r; uint64_t next; assert(m); assert(source); manager_print_jobs_in_progress(m); next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_PERIOD_USEC; r = sd_event_source_set_time(source, next); if (r < 0) return r; return sd_event_source_set_enabled(source, SD_EVENT_ONESHOT); } int manager_loop(Manager *m) { int r; RATELIMIT_DEFINE(rl, 1*USEC_PER_SEC, 50000); assert(m); m->exit_code = MANAGER_OK; /* Release the path cache */ m->unit_path_cache = set_free_free(m->unit_path_cache); manager_check_finished(m); /* There might still be some zombies hanging around from * before we were exec()'ed. Let's reap them. */ r = manager_dispatch_sigchld(m); if (r < 0) return r; while (m->exit_code == MANAGER_OK) { usec_t wait_usec; if (m->runtime_watchdog > 0 && m->running_as == MANAGER_SYSTEM) watchdog_ping(); if (!ratelimit_test(&rl)) { /* Yay, something is going seriously wrong, pause a little */ log_warning("Looping too fast. Throttling execution a little."); sleep(1); } if (manager_dispatch_load_queue(m) > 0) continue; if (manager_dispatch_gc_queue(m) > 0) continue; if (manager_dispatch_cleanup_queue(m) > 0) continue; if (manager_dispatch_cgroup_queue(m) > 0) continue; if (manager_dispatch_dbus_queue(m) > 0) continue; /* Sleep for half the watchdog time */ if (m->runtime_watchdog > 0 && m->running_as == MANAGER_SYSTEM) { wait_usec = m->runtime_watchdog / 2; if (wait_usec <= 0) wait_usec = 1; } else wait_usec = USEC_INFINITY; r = sd_event_run(m->event, wait_usec); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); } return m->exit_code; } int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u) { _cleanup_free_ char *n = NULL; Unit *u; int r; assert(m); assert(s); assert(_u); r = unit_name_from_dbus_path(s, &n); if (r < 0) return r; r = manager_load_unit(m, n, NULL, e, &u); if (r < 0) return r; *_u = u; return 0; } int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j) { const char *p; unsigned id; Job *j; int r; assert(m); assert(s); assert(_j); p = startswith(s, "/org/freedesktop/systemd1/job/"); if (!p) return -EINVAL; r = safe_atou(p, &id); if (r < 0) return r; j = manager_get_job(m, id); if (!j) return -ENOENT; *_j = j; return 0; } void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) { #ifdef HAVE_AUDIT _cleanup_free_ char *p = NULL; const char *msg; int audit_fd, r; if (m->running_as != MANAGER_SYSTEM) return; audit_fd = get_audit_fd(); if (audit_fd < 0) return; /* Don't generate audit events if the service was already * started and we're just deserializing */ if (m->n_reloading > 0) return; if (u->type != UNIT_SERVICE) return; r = unit_name_to_prefix_and_instance(u->id, &p); if (r < 0) { log_error_errno(r, "Failed to extract prefix and instance of unit name: %m"); return; } msg = strjoina("unit=", p); if (audit_log_user_comm_message(audit_fd, type, msg, "systemd", NULL, NULL, NULL, success) < 0) { if (errno == EPERM) /* We aren't allowed to send audit messages? * Then let's not retry again. */ close_audit_fd(); else log_warning_errno(errno, "Failed to send audit message: %m"); } #endif } void manager_send_unit_plymouth(Manager *m, Unit *u) { union sockaddr_union sa = PLYMOUTH_SOCKET; int n = 0; _cleanup_free_ char *message = NULL; _cleanup_close_ int fd = -1; /* Don't generate plymouth events if the service was already * started and we're just deserializing */ if (m->n_reloading > 0) return; if (m->running_as != MANAGER_SYSTEM) return; if (detect_container() > 0) return; if (u->type != UNIT_SERVICE && u->type != UNIT_MOUNT && u->type != UNIT_SWAP) return; /* We set SOCK_NONBLOCK here so that we rather drop the * message then wait for plymouth */ fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (fd < 0) { log_error_errno(errno, "socket() failed: %m"); return; } if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) { if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED)) log_error_errno(errno, "connect() failed: %m"); return; } if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->id) + 1), u->id, &n) < 0) { log_oom(); return; } errno = 0; if (write(fd, message, n + 1) != n + 1) if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED)) log_error_errno(errno, "Failed to write Plymouth message: %m"); } int manager_open_serialization(Manager *m, FILE **_f) { const char *path; int fd = -1; FILE *f; assert(_f); path = m->running_as == MANAGER_SYSTEM ? "/run/systemd" : "/tmp"; fd = open_tmpfile(path, O_RDWR|O_CLOEXEC); if (fd < 0) return -errno; log_debug("Serializing state to %s", path); f = fdopen(fd, "w+"); if (!f) { safe_close(fd); return -errno; } *_f = f; return 0; } int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { Iterator i; Unit *u; const char *t; char **e; int r; assert(m); assert(f); assert(fds); m->n_reloading ++; fprintf(f, "current-job-id=%"PRIu32"\n", m->current_job_id); fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr)); fprintf(f, "n-installed-jobs=%u\n", m->n_installed_jobs); fprintf(f, "n-failed-jobs=%u\n", m->n_failed_jobs); dual_timestamp_serialize(f, "firmware-timestamp", &m->firmware_timestamp); dual_timestamp_serialize(f, "loader-timestamp", &m->loader_timestamp); dual_timestamp_serialize(f, "kernel-timestamp", &m->kernel_timestamp); dual_timestamp_serialize(f, "initrd-timestamp", &m->initrd_timestamp); if (!in_initrd()) { dual_timestamp_serialize(f, "userspace-timestamp", &m->userspace_timestamp); dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp); dual_timestamp_serialize(f, "security-start-timestamp", &m->security_start_timestamp); dual_timestamp_serialize(f, "security-finish-timestamp", &m->security_finish_timestamp); dual_timestamp_serialize(f, "generators-start-timestamp", &m->generators_start_timestamp); dual_timestamp_serialize(f, "generators-finish-timestamp", &m->generators_finish_timestamp); dual_timestamp_serialize(f, "units-load-start-timestamp", &m->units_load_start_timestamp); dual_timestamp_serialize(f, "units-load-finish-timestamp", &m->units_load_finish_timestamp); } if (!switching_root) { STRV_FOREACH(e, m->environment) { _cleanup_free_ char *ce; ce = cescape(*e); if (!ce) return -ENOMEM; fprintf(f, "env=%s\n", *e); } } if (m->notify_fd >= 0) { int copy; copy = fdset_put_dup(fds, m->notify_fd); if (copy < 0) return copy; fprintf(f, "notify-fd=%i\n", copy); fprintf(f, "notify-socket=%s\n", m->notify_socket); } if (m->kdbus_fd >= 0) { int copy; copy = fdset_put_dup(fds, m->kdbus_fd); if (copy < 0) return copy; fprintf(f, "kdbus-fd=%i\n", copy); } bus_track_serialize(m->subscribed, f); fputc('\n', f); HASHMAP_FOREACH_KEY(u, t, m->units, i) { if (u->id != t) continue; /* Start marker */ fputs(u->id, f); fputc('\n', f); r = unit_serialize(u, f, fds, !switching_root); if (r < 0) { m->n_reloading --; return r; } } assert(m->n_reloading > 0); m->n_reloading --; if (ferror(f)) return -EIO; r = bus_fdset_add_all(m, fds); if (r < 0) return r; return 0; } int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { int r = 0; assert(m); assert(f); log_debug("Deserializing state..."); m->n_reloading ++; for (;;) { char line[LINE_MAX], *l; if (!fgets(line, sizeof(line), f)) { if (feof(f)) r = 0; else r = -errno; goto finish; } char_array_0(line); l = strstrip(line); if (l[0] == 0) break; if (startswith(l, "current-job-id=")) { uint32_t id; if (safe_atou32(l+15, &id) < 0) log_debug("Failed to parse current job id value %s", l+15); else m->current_job_id = MAX(m->current_job_id, id); } else if (startswith(l, "n-installed-jobs=")) { uint32_t n; if (safe_atou32(l+17, &n) < 0) log_debug("Failed to parse installed jobs counter %s", l+17); else m->n_installed_jobs += n; } else if (startswith(l, "n-failed-jobs=")) { uint32_t n; if (safe_atou32(l+14, &n) < 0) log_debug("Failed to parse failed jobs counter %s", l+14); else m->n_failed_jobs += n; } else if (startswith(l, "taint-usr=")) { int b; b = parse_boolean(l+10); if (b < 0) log_debug("Failed to parse taint /usr flag %s", l+10); else m->taint_usr = m->taint_usr || b; } else if (startswith(l, "firmware-timestamp=")) dual_timestamp_deserialize(l+19, &m->firmware_timestamp); else if (startswith(l, "loader-timestamp=")) dual_timestamp_deserialize(l+17, &m->loader_timestamp); else if (startswith(l, "kernel-timestamp=")) dual_timestamp_deserialize(l+17, &m->kernel_timestamp); else if (startswith(l, "initrd-timestamp=")) dual_timestamp_deserialize(l+17, &m->initrd_timestamp); else if (startswith(l, "userspace-timestamp=")) dual_timestamp_deserialize(l+20, &m->userspace_timestamp); else if (startswith(l, "finish-timestamp=")) dual_timestamp_deserialize(l+17, &m->finish_timestamp); else if (startswith(l, "security-start-timestamp=")) dual_timestamp_deserialize(l+25, &m->security_start_timestamp); else if (startswith(l, "security-finish-timestamp=")) dual_timestamp_deserialize(l+26, &m->security_finish_timestamp); else if (startswith(l, "generators-start-timestamp=")) dual_timestamp_deserialize(l+27, &m->generators_start_timestamp); else if (startswith(l, "generators-finish-timestamp=")) dual_timestamp_deserialize(l+28, &m->generators_finish_timestamp); else if (startswith(l, "units-load-start-timestamp=")) dual_timestamp_deserialize(l+27, &m->units_load_start_timestamp); else if (startswith(l, "units-load-finish-timestamp=")) dual_timestamp_deserialize(l+28, &m->units_load_finish_timestamp); else if (startswith(l, "env=")) { _cleanup_free_ char *uce = NULL; char **e; r = cunescape(l + 4, UNESCAPE_RELAX, &uce); if (r < 0) goto finish; e = strv_env_set(m->environment, uce); if (!e) { r = -ENOMEM; goto finish; } strv_free(m->environment); m->environment = e; } else if (startswith(l, "notify-fd=")) { int fd; if (safe_atoi(l + 10, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) log_debug("Failed to parse notify fd: %s", l + 10); else { m->notify_event_source = sd_event_source_unref(m->notify_event_source); safe_close(m->notify_fd); m->notify_fd = fdset_remove(fds, fd); } } else if (startswith(l, "notify-socket=")) { char *n; n = strdup(l+14); if (!n) { r = -ENOMEM; goto finish; } free(m->notify_socket); m->notify_socket = n; } else if (startswith(l, "kdbus-fd=")) { int fd; if (safe_atoi(l + 9, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) log_debug("Failed to parse kdbus fd: %s", l + 9); else { safe_close(m->kdbus_fd); m->kdbus_fd = fdset_remove(fds, fd); } } else { int k; k = bus_track_deserialize_item(&m->deserialized_subscribed, l); if (k < 0) log_debug_errno(k, "Failed to deserialize bus tracker object: %m"); else if (k == 0) log_debug("Unknown serialization item '%s'", l); } } for (;;) { Unit *u; char name[UNIT_NAME_MAX+2]; /* Start marker */ if (!fgets(name, sizeof(name), f)) { if (feof(f)) r = 0; else r = -errno; goto finish; } char_array_0(name); r = manager_load_unit(m, strstrip(name), NULL, NULL, &u); if (r < 0) goto finish; r = unit_deserialize(u, f, fds); if (r < 0) goto finish; } finish: if (ferror(f)) r = -EIO; assert(m->n_reloading > 0); m->n_reloading --; return r; } int manager_reload(Manager *m) { int r, q; _cleanup_fclose_ FILE *f = NULL; _cleanup_fdset_free_ FDSet *fds = NULL; assert(m); r = manager_open_serialization(m, &f); if (r < 0) return r; m->n_reloading ++; bus_manager_send_reloading(m, true); fds = fdset_new(); if (!fds) { m->n_reloading --; return -ENOMEM; } r = manager_serialize(m, f, fds, false); if (r < 0) { m->n_reloading --; return r; } if (fseeko(f, 0, SEEK_SET) < 0) { m->n_reloading --; return -errno; } /* From here on there is no way back. */ manager_clear_jobs_and_units(m); manager_undo_generators(m); lookup_paths_free(&m->lookup_paths); /* Find new unit paths */ q = manager_run_generators(m); if (q < 0 && r >= 0) r = q; q = lookup_paths_init( &m->lookup_paths, m->running_as, true, NULL, m->generator_unit_path, m->generator_unit_path_early, m->generator_unit_path_late); if (q < 0 && r >= 0) r = q; manager_build_unit_path_cache(m); /* First, enumerate what we can from all config files */ manager_enumerate(m); /* Second, deserialize our stored data */ q = manager_deserialize(m, f, fds); if (q < 0 && r >= 0) r = q; fclose(f); f = NULL; /* Re-register notify_fd as event source */ q = manager_setup_notify(m); if (q < 0 && r >= 0) r = q; /* Third, fire things up! */ manager_coldplug(m); /* Sync current state of bus names with our set of listening units */ if (m->api_bus) manager_sync_bus_names(m, m->api_bus); assert(m->n_reloading > 0); m->n_reloading--; m->send_reloading_done = true; return r; } bool manager_is_reloading_or_reexecuting(Manager *m) { assert(m); return m->n_reloading != 0; } void manager_reset_failed(Manager *m) { Unit *u; Iterator i; assert(m); HASHMAP_FOREACH(u, m->units, i) unit_reset_failed(u); } bool manager_unit_inactive_or_pending(Manager *m, const char *name) { Unit *u; assert(m); assert(name); /* Returns true if the unit is inactive or going down */ u = manager_get_unit(m, name); if (!u) return true; return unit_inactive_or_pending(u); } static void manager_notify_finished(Manager *m) { char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX]; usec_t firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec; if (m->test_run) return; if (m->running_as == MANAGER_SYSTEM && detect_container() <= 0) { /* Note that m->kernel_usec.monotonic is always at 0, * and m->firmware_usec.monotonic and * m->loader_usec.monotonic should be considered * negative values. */ firmware_usec = m->firmware_timestamp.monotonic - m->loader_timestamp.monotonic; loader_usec = m->loader_timestamp.monotonic - m->kernel_timestamp.monotonic; userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic; total_usec = m->firmware_timestamp.monotonic + m->finish_timestamp.monotonic; if (dual_timestamp_is_set(&m->initrd_timestamp)) { kernel_usec = m->initrd_timestamp.monotonic - m->kernel_timestamp.monotonic; initrd_usec = m->userspace_timestamp.monotonic - m->initrd_timestamp.monotonic; log_struct(LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED), "KERNEL_USEC="USEC_FMT, kernel_usec, "INITRD_USEC="USEC_FMT, initrd_usec, "USERSPACE_USEC="USEC_FMT, userspace_usec, LOG_MESSAGE("Startup finished in %s (kernel) + %s (initrd) + %s (userspace) = %s.", format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC), format_timespan(initrd, sizeof(initrd), initrd_usec, USEC_PER_MSEC), format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC), format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)), NULL); } else { kernel_usec = m->userspace_timestamp.monotonic - m->kernel_timestamp.monotonic; initrd_usec = 0; log_struct(LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED), "KERNEL_USEC="USEC_FMT, kernel_usec, "USERSPACE_USEC="USEC_FMT, userspace_usec, LOG_MESSAGE("Startup finished in %s (kernel) + %s (userspace) = %s.", format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC), format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC), format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)), NULL); } } else { firmware_usec = loader_usec = initrd_usec = kernel_usec = 0; total_usec = userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic; log_struct(LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED), "USERSPACE_USEC="USEC_FMT, userspace_usec, LOG_MESSAGE("Startup finished in %s.", format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)), NULL); } bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec); sd_notifyf(false, "READY=1\n" "STATUS=Startup finished in %s.", format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)); } void manager_check_finished(Manager *m) { assert(m); if (m->n_reloading > 0) return; /* Verify that we are actually running currently. Initially * the exit code is set to invalid, and during operation it is * then set to MANAGER_OK */ if (m->exit_code != MANAGER_OK) return; if (hashmap_size(m->jobs) > 0) { if (m->jobs_in_progress_event_source) /* Ignore any failure, this is only for feedback */ (void) sd_event_source_set_time(m->jobs_in_progress_event_source, now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC); return; } manager_flip_auto_status(m, false); /* Notify Type=idle units that we are done now */ manager_close_idle_pipe(m); /* Turn off confirm spawn now */ m->confirm_spawn = false; /* No need to update ask password status when we're going non-interactive */ manager_close_ask_password(m); /* This is no longer the first boot */ manager_set_first_boot(m, false); if (dual_timestamp_is_set(&m->finish_timestamp)) return; dual_timestamp_get(&m->finish_timestamp); manager_notify_finished(m); manager_invalidate_startup_units(m); } static int create_generator_dir(Manager *m, char **generator, const char *name) { char *p; int r; assert(m); assert(generator); assert(name); if (*generator) return 0; if (m->running_as == MANAGER_SYSTEM && getpid() == 1) { /* systemd --system, not running --test */ p = strappend("/run/systemd/", name); if (!p) return log_oom(); r = mkdir_p_label(p, 0755); if (r < 0) { log_error_errno(r, "Failed to create generator directory %s: %m", p); free(p); return r; } } else if (m->running_as == MANAGER_USER) { const char *s = NULL; s = getenv("XDG_RUNTIME_DIR"); if (!s) return -EINVAL; p = strjoin(s, "/systemd/", name, NULL); if (!p) return log_oom(); r = mkdir_p_label(p, 0755); if (r < 0) { log_error_errno(r, "Failed to create generator directory %s: %m", p); free(p); return r; } } else { /* systemd --system --test */ p = strjoin("/tmp/systemd-", name, ".XXXXXX", NULL); if (!p) return log_oom(); if (!mkdtemp(p)) { log_error_errno(errno, "Failed to create generator directory %s: %m", p); free(p); return -errno; } } *generator = p; return 0; } static void trim_generator_dir(Manager *m, char **generator) { assert(m); assert(generator); if (!*generator) return; if (rmdir(*generator) >= 0) *generator = mfree(*generator); return; } static int manager_run_generators(Manager *m) { _cleanup_strv_free_ char **paths = NULL; const char *argv[5]; char **path; int r; assert(m); if (m->test_run) return 0; paths = generator_paths(m->running_as); if (!paths) return log_oom(); /* Optimize by skipping the whole process by not creating output directories * if no generators are found. */ STRV_FOREACH(path, paths) { r = access(*path, F_OK); if (r == 0) goto found; if (errno != ENOENT) log_warning_errno(errno, "Failed to open generator directory %s: %m", *path); } return 0; found: r = create_generator_dir(m, &m->generator_unit_path, "generator"); if (r < 0) goto finish; r = create_generator_dir(m, &m->generator_unit_path_early, "generator.early"); if (r < 0) goto finish; r = create_generator_dir(m, &m->generator_unit_path_late, "generator.late"); if (r < 0) goto finish; argv[0] = NULL; /* Leave this empty, execute_directory() will fill something in */ argv[1] = m->generator_unit_path; argv[2] = m->generator_unit_path_early; argv[3] = m->generator_unit_path_late; argv[4] = NULL; RUN_WITH_UMASK(0022) execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC, (char**) argv); finish: trim_generator_dir(m, &m->generator_unit_path); trim_generator_dir(m, &m->generator_unit_path_early); trim_generator_dir(m, &m->generator_unit_path_late); return r; } static void remove_generator_dir(Manager *m, char **generator) { assert(m); assert(generator); if (!*generator) return; strv_remove(m->lookup_paths.unit_path, *generator); (void) rm_rf(*generator, REMOVE_ROOT); *generator = mfree(*generator); } static void manager_undo_generators(Manager *m) { assert(m); remove_generator_dir(m, &m->generator_unit_path); remove_generator_dir(m, &m->generator_unit_path_early); remove_generator_dir(m, &m->generator_unit_path_late); } int manager_environment_add(Manager *m, char **minus, char **plus) { char **a = NULL, **b = NULL, **l; assert(m); l = m->environment; if (!strv_isempty(minus)) { a = strv_env_delete(l, 1, minus); if (!a) return -ENOMEM; l = a; } if (!strv_isempty(plus)) { b = strv_env_merge(2, l, plus); if (!b) { strv_free(a); return -ENOMEM; } l = b; } if (m->environment != l) strv_free(m->environment); if (a != l) strv_free(a); if (b != l) strv_free(b); m->environment = l; manager_clean_environment(m); strv_sort(m->environment); return 0; } int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) { int i; assert(m); for (i = 0; i < _RLIMIT_MAX; i++) { m->rlimit[i] = mfree(m->rlimit[i]); if (!default_rlimit[i]) continue; m->rlimit[i] = newdup(struct rlimit, default_rlimit[i], 1); if (!m->rlimit[i]) return -ENOMEM; } return 0; } void manager_recheck_journal(Manager *m) { Unit *u; assert(m); if (m->running_as != MANAGER_SYSTEM) return; u = manager_get_unit(m, SPECIAL_JOURNALD_SOCKET); if (u && SOCKET(u)->state != SOCKET_RUNNING) { log_close_journal(); return; } u = manager_get_unit(m, SPECIAL_JOURNALD_SERVICE); if (u && SERVICE(u)->state != SERVICE_RUNNING) { log_close_journal(); return; } /* Hmm, OK, so the socket is fully up and the service is up * too, then let's make use of the thing. */ log_open(); } void manager_set_show_status(Manager *m, ShowStatus mode) { assert(m); assert(IN_SET(mode, SHOW_STATUS_AUTO, SHOW_STATUS_NO, SHOW_STATUS_YES, SHOW_STATUS_TEMPORARY)); if (m->running_as != MANAGER_SYSTEM) return; if (m->show_status != mode) log_debug("%s showing of status.", mode == SHOW_STATUS_NO ? "Disabling" : "Enabling"); m->show_status = mode; if (mode > 0) (void) touch("/run/systemd/show-status"); else (void) unlink("/run/systemd/show-status"); } static bool manager_get_show_status(Manager *m, StatusType type) { assert(m); if (m->running_as != MANAGER_SYSTEM) return false; if (m->no_console_output) return false; if (!IN_SET(manager_state(m), MANAGER_INITIALIZING, MANAGER_STARTING, MANAGER_STOPPING)) return false; /* If we cannot find out the status properly, just proceed. */ if (type != STATUS_TYPE_EMERGENCY && manager_check_ask_password(m) > 0) return false; if (m->show_status > 0) return true; return false; } void manager_set_first_boot(Manager *m, bool b) { assert(m); if (m->running_as != MANAGER_SYSTEM) return; if (m->first_boot != (int) b) { if (b) (void) touch("/run/systemd/first-boot"); else (void) unlink("/run/systemd/first-boot"); } m->first_boot = b; } void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) { va_list ap; /* If m is NULL, assume we're after shutdown and let the messages through. */ if (m && !manager_get_show_status(m, type)) return; /* XXX We should totally drop the check for ephemeral here * and thus effectively make 'Type=idle' pointless. */ if (type == STATUS_TYPE_EPHEMERAL && m && m->n_on_console > 0) return; va_start(ap, format); status_vprintf(status, true, type == STATUS_TYPE_EPHEMERAL, format, ap); va_end(ap); } Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) { char p[strlen(path)+1]; assert(m); assert(path); strcpy(p, path); path_kill_slashes(p); return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p); } const char *manager_get_runtime_prefix(Manager *m) { assert(m); return m->running_as == MANAGER_SYSTEM ? "/run" : getenv("XDG_RUNTIME_DIR"); } int manager_update_failed_units(Manager *m, Unit *u, bool failed) { unsigned size; int r; assert(m); assert(u->manager == m); size = set_size(m->failed_units); if (failed) { r = set_ensure_allocated(&m->failed_units, NULL); if (r < 0) return log_oom(); if (set_put(m->failed_units, u) < 0) return log_oom(); } else (void) set_remove(m->failed_units, u); if (set_size(m->failed_units) != size) bus_manager_send_change_signal(m); return 0; } ManagerState manager_state(Manager *m) { Unit *u; assert(m); /* Did we ever finish booting? If not then we are still starting up */ if (!dual_timestamp_is_set(&m->finish_timestamp)) { u = manager_get_unit(m, SPECIAL_BASIC_TARGET); if (!u || !UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) return MANAGER_INITIALIZING; return MANAGER_STARTING; } /* Is the special shutdown target queued? If so, we are in shutdown state */ u = manager_get_unit(m, SPECIAL_SHUTDOWN_TARGET); if (u && u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_RELOAD_OR_START)) return MANAGER_STOPPING; /* Are the rescue or emergency targets active or queued? If so we are in maintenance state */ u = manager_get_unit(m, SPECIAL_RESCUE_TARGET); if (u && (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)) || (u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_RELOAD_OR_START)))) return MANAGER_MAINTENANCE; u = manager_get_unit(m, SPECIAL_EMERGENCY_TARGET); if (u && (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)) || (u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_RELOAD_OR_START)))) return MANAGER_MAINTENANCE; /* Are there any failed units? If so, we are in degraded mode */ if (set_size(m->failed_units) > 0) return MANAGER_DEGRADED; return MANAGER_RUNNING; } static const char *const manager_state_table[_MANAGER_STATE_MAX] = { [MANAGER_INITIALIZING] = "initializing", [MANAGER_STARTING] = "starting", [MANAGER_RUNNING] = "running", [MANAGER_DEGRADED] = "degraded", [MANAGER_MAINTENANCE] = "maintenance", [MANAGER_STOPPING] = "stopping", }; DEFINE_STRING_TABLE_LOOKUP(manager_state, ManagerState); systemd-229/src/core/manager.h000066400000000000000000000277141265713322000163760ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-bus.h" #include "sd-event.h" #include "cgroup-util.h" #include "fdset.h" #include "hashmap.h" #include "list.h" #include "ratelimit.h" /* Enforce upper limit how many names we allow */ #define MANAGER_MAX_NAMES 131072 /* 128K */ typedef struct Manager Manager; typedef enum ManagerState { MANAGER_INITIALIZING, MANAGER_STARTING, MANAGER_RUNNING, MANAGER_DEGRADED, MANAGER_MAINTENANCE, MANAGER_STOPPING, _MANAGER_STATE_MAX, _MANAGER_STATE_INVALID = -1 } ManagerState; typedef enum ManagerExitCode { MANAGER_OK, MANAGER_EXIT, MANAGER_RELOAD, MANAGER_REEXECUTE, MANAGER_REBOOT, MANAGER_POWEROFF, MANAGER_HALT, MANAGER_KEXEC, MANAGER_SWITCH_ROOT, _MANAGER_EXIT_CODE_MAX, _MANAGER_EXIT_CODE_INVALID = -1 } ManagerExitCode; typedef enum StatusType { STATUS_TYPE_EPHEMERAL, STATUS_TYPE_NORMAL, STATUS_TYPE_EMERGENCY, } StatusType; #include "execute.h" #include "job.h" #include "path-lookup.h" #include "show-status.h" #include "unit-name.h" struct Manager { /* Note that the set of units we know of is allowed to be * inconsistent. However the subset of it that is loaded may * not, and the list of jobs may neither. */ /* Active jobs and units */ Hashmap *units; /* name string => Unit object n:1 */ Hashmap *jobs; /* job id => Job object 1:1 */ /* To make it easy to iterate through the units of a specific * type we maintain a per type linked list */ LIST_HEAD(Unit, units_by_type[_UNIT_TYPE_MAX]); /* Units that need to be loaded */ LIST_HEAD(Unit, load_queue); /* this is actually more a stack than a queue, but uh. */ /* Jobs that need to be run */ LIST_HEAD(Job, run_queue); /* more a stack than a queue, too */ /* Units and jobs that have not yet been announced via * D-Bus. When something about a job changes it is added here * if it is not in there yet. This allows easy coalescing of * D-Bus change signals. */ LIST_HEAD(Unit, dbus_unit_queue); LIST_HEAD(Job, dbus_job_queue); /* Units to remove */ LIST_HEAD(Unit, cleanup_queue); /* Units to check when doing GC */ LIST_HEAD(Unit, gc_queue); /* Units that should be realized */ LIST_HEAD(Unit, cgroup_queue); sd_event *event; /* We use two hash tables here, since the same PID might be * watched by two different units: once the unit that forked * it off, and possibly a different unit to which it was * joined as cgroup member. Since we know that it is either * one or two units for each PID we just use to hashmaps * here. */ Hashmap *watch_pids1; /* pid => Unit object n:1 */ Hashmap *watch_pids2; /* pid => Unit object n:1 */ /* A set contains all units which cgroup should be refreshed after startup */ Set *startup_units; /* A set which contains all currently failed units */ Set *failed_units; sd_event_source *run_queue_event_source; char *notify_socket; int notify_fd; sd_event_source *notify_event_source; int signal_fd; sd_event_source *signal_event_source; int time_change_fd; sd_event_source *time_change_event_source; sd_event_source *jobs_in_progress_event_source; LookupPaths lookup_paths; Set *unit_path_cache; char **environment; usec_t runtime_watchdog; usec_t shutdown_watchdog; dual_timestamp firmware_timestamp; dual_timestamp loader_timestamp; dual_timestamp kernel_timestamp; dual_timestamp initrd_timestamp; dual_timestamp userspace_timestamp; dual_timestamp finish_timestamp; dual_timestamp security_start_timestamp; dual_timestamp security_finish_timestamp; dual_timestamp generators_start_timestamp; dual_timestamp generators_finish_timestamp; dual_timestamp units_load_start_timestamp; dual_timestamp units_load_finish_timestamp; char *generator_unit_path; char *generator_unit_path_early; char *generator_unit_path_late; struct udev* udev; /* Data specific to the device subsystem */ struct udev_monitor* udev_monitor; sd_event_source *udev_event_source; Hashmap *devices_by_sysfs; /* Data specific to the mount subsystem */ struct libmnt_monitor *mount_monitor; sd_event_source *mount_event_source; /* Data specific to the swap filesystem */ FILE *proc_swaps; sd_event_source *swap_event_source; Hashmap *swaps_by_devnode; /* Data specific to the D-Bus subsystem */ sd_bus *api_bus, *system_bus; Set *private_buses; int private_listen_fd; sd_event_source *private_listen_event_source; /* Contains all the clients that are subscribed to signals via the API bus. Note that private bus connections are always considered subscribes, since they last for very short only, and it is much simpler that way. */ sd_bus_track *subscribed; char **deserialized_subscribed; /* This is used during reloading: before the reload we queue * the reply message here, and afterwards we send it */ sd_bus_message *queued_message; Hashmap *watch_bus; /* D-Bus names => Unit object n:1 */ bool send_reloading_done; uint32_t current_job_id; uint32_t default_unit_job_id; /* Data specific to the Automount subsystem */ int dev_autofs_fd; /* Data specific to the cgroup subsystem */ Hashmap *cgroup_unit; CGroupMask cgroup_supported; char *cgroup_root; /* Notifications from cgroups, when the unified hierarchy is * used is done via inotify. */ int cgroup_inotify_fd; sd_event_source *cgroup_inotify_event_source; Hashmap *cgroup_inotify_wd_unit; /* Make sure the user cannot accidentally unmount our cgroup * file system */ int pin_cgroupfs_fd; int gc_marker; unsigned n_in_gc_queue; /* Flags */ ManagerRunningAs running_as; ManagerExitCode exit_code:5; bool dispatching_load_queue:1; bool dispatching_dbus_queue:1; bool taint_usr:1; bool test_run:1; /* If non-zero, exit with the following value when the systemd * process terminate. Useful for containers: systemd-nspawn could get * the return value. */ uint8_t return_value; ShowStatus show_status; bool confirm_spawn; bool no_console_output; ExecOutput default_std_output, default_std_error; usec_t default_restart_usec, default_timeout_start_usec, default_timeout_stop_usec; usec_t default_start_limit_interval; unsigned default_start_limit_burst; bool default_cpu_accounting; bool default_memory_accounting; bool default_blockio_accounting; bool default_tasks_accounting; uint64_t default_tasks_max; usec_t default_timer_accuracy_usec; struct rlimit *rlimit[_RLIMIT_MAX]; /* non-zero if we are reloading or reexecuting, */ int n_reloading; unsigned n_installed_jobs; unsigned n_failed_jobs; /* Jobs in progress watching */ unsigned n_running_jobs; unsigned n_on_console; unsigned jobs_in_progress_iteration; /* Do we have any outstanding password prompts? */ int have_ask_password; int ask_password_inotify_fd; sd_event_source *ask_password_event_source; /* Type=idle pipes */ int idle_pipe[4]; sd_event_source *idle_pipe_event_source; char *switch_root; char *switch_root_init; /* This maps all possible path prefixes to the units needing * them. It's a hashmap with a path string as key and a Set as * value where Unit objects are contained. */ Hashmap *units_requiring_mounts_for; /* Reference to the kdbus bus control fd */ int kdbus_fd; /* Used for processing polkit authorization responses */ Hashmap *polkit_registry; /* When the user hits C-A-D more than 7 times per 2s, reboot immediately... */ RateLimit ctrl_alt_del_ratelimit; const char *unit_log_field; const char *unit_log_format_string; int first_boot; }; int manager_new(ManagerRunningAs running_as, bool test_run, Manager **m); Manager* manager_free(Manager *m); void manager_enumerate(Manager *m); int manager_startup(Manager *m, FILE *serialization, FDSet *fds); Job *manager_get_job(Manager *m, uint32_t id); Unit *manager_get_unit(Manager *m, const char *name); int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j); int manager_load_unit_prepare(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret); int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret); int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u); int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret); int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, sd_bus_error *e, Job **_ret); int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Job **ret); void manager_dump_units(Manager *s, FILE *f, const char *prefix); void manager_dump_jobs(Manager *s, FILE *f, const char *prefix); void manager_clear_jobs(Manager *m); unsigned manager_dispatch_load_queue(Manager *m); int manager_environment_add(Manager *m, char **minus, char **plus); int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit); int manager_loop(Manager *m); int manager_open_serialization(Manager *m, FILE **_f); int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root); int manager_deserialize(Manager *m, FILE *f, FDSet *fds); int manager_reload(Manager *m); bool manager_is_reloading_or_reexecuting(Manager *m) _pure_; void manager_reset_failed(Manager *m); void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success); void manager_send_unit_plymouth(Manager *m, Unit *u); bool manager_unit_inactive_or_pending(Manager *m, const char *name); void manager_check_finished(Manager *m); void manager_recheck_journal(Manager *m); void manager_set_show_status(Manager *m, ShowStatus mode); void manager_set_first_boot(Manager *m, bool b); void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) _printf_(4,5); void manager_flip_auto_status(Manager *m, bool enable); Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path); const char *manager_get_runtime_prefix(Manager *m); ManagerState manager_state(Manager *m); int manager_update_failed_units(Manager *m, Unit *u, bool failed); const char *manager_state_to_string(ManagerState m) _const_; ManagerState manager_state_from_string(const char *s) _pure_; systemd-229/src/core/mount-setup.c000066400000000000000000000364331265713322000172550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "bus-util.h" #include "cgroup-util.h" #include "dev-setup.h" #include "efivars.h" #include "label.h" #include "log.h" #include "macro.h" #include "missing.h" #include "mkdir.h" #include "mount-setup.h" #include "mount-util.h" #include "path-util.h" #include "set.h" #include "smack-util.h" #include "strv.h" #include "user-util.h" #include "util.h" #include "virt.h" typedef enum MountMode { MNT_NONE = 0, MNT_FATAL = 1 << 0, MNT_IN_CONTAINER = 1 << 1, } MountMode; typedef struct MountPoint { const char *what; const char *where; const char *type; const char *options; unsigned long flags; bool (*condition_fn)(void); MountMode mode; } MountPoint; /* The first three entries we might need before SELinux is up. The * fourth (securityfs) is needed by IMA to load a custom policy. The * other ones we can delay until SELinux and IMA are loaded. When * SMACK is enabled we need smackfs, too, so it's a fifth one. */ #ifdef HAVE_SMACK #define N_EARLY_MOUNT 5 #else #define N_EARLY_MOUNT 4 #endif static const MountPoint mount_table[] = { { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL, MNT_FATAL|MNT_IN_CONTAINER }, { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL, MNT_FATAL|MNT_IN_CONTAINER }, { "devtmpfs", "/dev", "devtmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, NULL, MNT_FATAL|MNT_IN_CONTAINER }, { "securityfs", "/sys/kernel/security", "securityfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL, MNT_NONE }, #ifdef HAVE_SMACK { "smackfs", "/sys/fs/smackfs", "smackfs", "smackfsdef=*", MS_NOSUID|MS_NOEXEC|MS_NODEV, mac_smack_use, MNT_FATAL }, { "tmpfs", "/dev/shm", "tmpfs", "mode=1777,smackfsroot=*", MS_NOSUID|MS_NODEV|MS_STRICTATIME, mac_smack_use, MNT_FATAL }, #endif { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, NULL, MNT_FATAL|MNT_IN_CONTAINER }, { "devpts", "/dev/pts", "devpts", "mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC, NULL, MNT_IN_CONTAINER }, #ifdef HAVE_SMACK { "tmpfs", "/run", "tmpfs", "mode=755,smackfsroot=*", MS_NOSUID|MS_NODEV|MS_STRICTATIME, mac_smack_use, MNT_FATAL }, #endif { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, NULL, MNT_FATAL|MNT_IN_CONTAINER }, { "cgroup", "/sys/fs/cgroup", "cgroup", "__DEVEL__sane_behavior", MS_NOSUID|MS_NOEXEC|MS_NODEV, cg_is_unified_wanted, MNT_FATAL|MNT_IN_CONTAINER }, { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER }, { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd,xattr", MS_NOSUID|MS_NOEXEC|MS_NODEV, cg_is_legacy_wanted, MNT_IN_CONTAINER }, { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV, cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER }, { "pstore", "/sys/fs/pstore", "pstore", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL, MNT_NONE }, #ifdef ENABLE_EFI { "efivarfs", "/sys/firmware/efi/efivars", "efivarfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, is_efi_boot, MNT_NONE }, #endif { "kdbusfs", "/sys/fs/kdbus", "kdbusfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, is_kdbus_wanted, MNT_IN_CONTAINER }, }; /* These are API file systems that might be mounted by other software, * we just list them here so that we know that we should ignore them */ static const char ignore_paths[] = /* SELinux file systems */ "/sys/fs/selinux\0" /* Container bind mounts */ "/proc/sys\0" "/dev/console\0" "/proc/kmsg\0"; bool mount_point_is_api(const char *path) { unsigned i; /* Checks if this mount point is considered "API", and hence * should be ignored */ for (i = 0; i < ELEMENTSOF(mount_table); i ++) if (path_equal(path, mount_table[i].where)) return true; return path_startswith(path, "/sys/fs/cgroup/"); } bool mount_point_ignore(const char *path) { const char *i; NULSTR_FOREACH(i, ignore_paths) if (path_equal(path, i)) return true; return false; } static int mount_one(const MountPoint *p, bool relabel) { int r; assert(p); if (p->condition_fn && !p->condition_fn()) return 0; /* Relabel first, just in case */ if (relabel) (void) label_fix(p->where, true, true); r = path_is_mount_point(p->where, AT_SYMLINK_FOLLOW); if (r < 0 && r != -ENOENT) { log_full_errno((p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG, r, "Failed to determine whether %s is a mount point: %m", p->where); return (p->mode & MNT_FATAL) ? r : 0; } if (r > 0) return 0; /* Skip securityfs in a container */ if (!(p->mode & MNT_IN_CONTAINER) && detect_container() > 0) return 0; /* The access mode here doesn't really matter too much, since * the mounted file system will take precedence anyway. */ if (relabel) (void) mkdir_p_label(p->where, 0755); else (void) mkdir_p(p->where, 0755); log_debug("Mounting %s to %s of type %s with options %s.", p->what, p->where, p->type, strna(p->options)); if (mount(p->what, p->where, p->type, p->flags, p->options) < 0) { log_full_errno((p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG, errno, "Failed to mount %s at %s: %m", p->type, p->where); return (p->mode & MNT_FATAL) ? -errno : 0; } /* Relabel again, since we now mounted something fresh here */ if (relabel) (void) label_fix(p->where, false, false); return 1; } static int mount_points_setup(unsigned n, bool loaded_policy) { unsigned i; int r = 0; for (i = 0; i < n; i ++) { int j; j = mount_one(mount_table + i, loaded_policy); if (j != 0 && r >= 0) r = j; } return r; } int mount_setup_early(void) { assert_cc(N_EARLY_MOUNT <= ELEMENTSOF(mount_table)); /* Do a minimal mount of /proc and friends to enable the most * basic stuff, such as SELinux */ return mount_points_setup(N_EARLY_MOUNT, false); } int mount_cgroup_controllers(char ***join_controllers) { _cleanup_set_free_free_ Set *controllers = NULL; int r; if (!cg_is_legacy_wanted()) return 0; /* Mount all available cgroup controllers that are built into the kernel. */ controllers = set_new(&string_hash_ops); if (!controllers) return log_oom(); r = cg_kernel_controllers(controllers); if (r < 0) return log_error_errno(r, "Failed to enumerate cgroup controllers: %m"); for (;;) { _cleanup_free_ char *options = NULL, *controller = NULL, *where = NULL; MountPoint p = { .what = "cgroup", .type = "cgroup", .flags = MS_NOSUID|MS_NOEXEC|MS_NODEV, .mode = MNT_IN_CONTAINER, }; char ***k = NULL; controller = set_steal_first(controllers); if (!controller) break; if (join_controllers) for (k = join_controllers; *k; k++) if (strv_find(*k, controller)) break; if (k && *k) { char **i, **j; for (i = *k, j = *k; *i; i++) { if (!streq(*i, controller)) { _cleanup_free_ char *t; t = set_remove(controllers, *i); if (!t) { free(*i); continue; } } *(j++) = *i; } *j = NULL; options = strv_join(*k, ","); if (!options) return log_oom(); } else { options = controller; controller = NULL; } where = strappend("/sys/fs/cgroup/", options); if (!where) return log_oom(); p.where = where; p.options = options; r = mount_one(&p, true); if (r < 0) return r; if (r > 0 && k && *k) { char **i; for (i = *k; *i; i++) { _cleanup_free_ char *t = NULL; t = strappend("/sys/fs/cgroup/", *i); if (!t) return log_oom(); r = symlink(options, t); if (r >= 0) { #ifdef SMACK_RUN_LABEL _cleanup_free_ char *src; src = strappend("/sys/fs/cgroup/", options); if (!src) return log_oom(); r = mac_smack_copy(t, src); if (r < 0 && r != -EOPNOTSUPP) return log_error_errno(r, "Failed to copy smack label from %s to %s: %m", src, t); #endif } else if (errno != EEXIST) return log_error_errno(errno, "Failed to create symlink %s: %m", t); } } } /* Now that we mounted everything, let's make the tmpfs the * cgroup file systems are mounted into read-only. */ (void) mount("tmpfs", "/sys/fs/cgroup", "tmpfs", MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755"); return 0; } #if defined(HAVE_SELINUX) || defined(HAVE_SMACK) static int nftw_cb( const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf) { /* No need to label /dev twice in a row... */ if (_unlikely_(ftwbuf->level == 0)) return FTW_CONTINUE; label_fix(fpath, false, false); /* /run/initramfs is static data and big, no need to * dynamically relabel its contents at boot... */ if (_unlikely_(ftwbuf->level == 1 && tflag == FTW_D && streq(fpath, "/run/initramfs"))) return FTW_SKIP_SUBTREE; return FTW_CONTINUE; }; #endif int mount_setup(bool loaded_policy) { int r = 0; r = mount_points_setup(ELEMENTSOF(mount_table), loaded_policy); if (r < 0) return r; #if defined(HAVE_SELINUX) || defined(HAVE_SMACK) /* Nodes in devtmpfs and /run need to be manually updated for * the appropriate labels, after mounting. The other virtual * API file systems like /sys and /proc do not need that, they * use the same label for all their files. */ if (loaded_policy) { usec_t before_relabel, after_relabel; char timespan[FORMAT_TIMESPAN_MAX]; before_relabel = now(CLOCK_MONOTONIC); nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); after_relabel = now(CLOCK_MONOTONIC); log_info("Relabelled /dev and /run in %s.", format_timespan(timespan, sizeof(timespan), after_relabel - before_relabel, 0)); } #endif /* Create a few default symlinks, which are normally created * by udevd, but some scripts might need them before we start * udevd. */ dev_setup(NULL, UID_INVALID, GID_INVALID); /* Mark the root directory as shared in regards to mount * propagation. The kernel defaults to "private", but we think * it makes more sense to have a default of "shared" so that * nspawn and the container tools work out of the box. If * specific setups need other settings they can reset the * propagation mode to private if needed. */ if (detect_container() <= 0) if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0) log_warning_errno(errno, "Failed to set up the root directory for shared mount propagation: %m"); /* Create a few directories we always want around, Note that * sd_booted() checks for /run/systemd/system, so this mkdir * really needs to stay for good, otherwise software that * copied sd-daemon.c into their sources will misdetect * systemd. */ mkdir_label("/run/systemd", 0755); mkdir_label("/run/systemd/system", 0755); mkdir_label("/run/systemd/inaccessible", 0000); return 0; } systemd-229/src/core/mount-setup.h000066400000000000000000000017051265713322000172540ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include int mount_setup_early(void); int mount_setup(bool loaded_policy); int mount_cgroup_controllers(char ***join_controllers); bool mount_point_is_api(const char *path); bool mount_point_ignore(const char *path); systemd-229/src/core/mount.c000066400000000000000000001656241265713322000161240ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-messages.h" #include "alloc-util.h" #include "dbus-mount.h" #include "escape.h" #include "exit-status.h" #include "formats-util.h" #include "fstab-util.h" #include "log.h" #include "manager.h" #include "mkdir.h" #include "mount-setup.h" #include "mount-util.h" #include "mount.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "special.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "unit.h" #define RETRY_UMOUNT_MAX 32 DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table); DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter); static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = { [MOUNT_DEAD] = UNIT_INACTIVE, [MOUNT_MOUNTING] = UNIT_ACTIVATING, [MOUNT_MOUNTING_DONE] = UNIT_ACTIVE, [MOUNT_MOUNTED] = UNIT_ACTIVE, [MOUNT_REMOUNTING] = UNIT_RELOADING, [MOUNT_UNMOUNTING] = UNIT_DEACTIVATING, [MOUNT_MOUNTING_SIGTERM] = UNIT_DEACTIVATING, [MOUNT_MOUNTING_SIGKILL] = UNIT_DEACTIVATING, [MOUNT_REMOUNTING_SIGTERM] = UNIT_RELOADING, [MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING, [MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING, [MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING, [MOUNT_FAILED] = UNIT_FAILED }; static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); static bool mount_needs_network(const char *options, const char *fstype) { if (fstab_test_option(options, "_netdev\0")) return true; if (fstype && fstype_is_network(fstype)) return true; return false; } static bool mount_is_network(const MountParameters *p) { assert(p); return mount_needs_network(p->options, p->fstype); } static bool mount_is_bind(const MountParameters *p) { assert(p); if (fstab_test_option(p->options, "bind\0" "rbind\0")) return true; if (p->fstype && STR_IN_SET(p->fstype, "bind", "rbind")) return true; return false; } static bool mount_is_auto(const MountParameters *p) { assert(p); return !fstab_test_option(p->options, "noauto\0"); } static bool needs_quota(const MountParameters *p) { assert(p); /* Quotas are not enabled on network filesystems, * but we want them, for example, on storage connected via iscsi */ if (p->fstype && fstype_is_network(p->fstype)) return false; if (mount_is_bind(p)) return false; return fstab_test_option(p->options, "usrquota\0" "grpquota\0" "quota\0" "usrjquota\0" "grpjquota\0"); } static void mount_init(Unit *u) { Mount *m = MOUNT(u); assert(u); assert(u->load_state == UNIT_STUB); m->timeout_usec = u->manager->default_timeout_start_usec; m->directory_mode = 0755; if (unit_has_name(u, "-.mount")) { /* Don't allow start/stop for root directory */ u->refuse_manual_start = true; u->refuse_manual_stop = true; } else { /* The stdio/kmsg bridge socket is on /, in order to avoid a * dep loop, don't use kmsg logging for -.mount */ m->exec_context.std_output = u->manager->default_std_output; m->exec_context.std_error = u->manager->default_std_error; } /* We need to make sure that /usr/bin/mount is always called * in the same process group as us, so that the autofs kernel * side doesn't send us another mount request while we are * already trying to comply its last one. */ m->exec_context.same_pgrp = true; m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID; u->ignore_on_isolate = true; } static int mount_arm_timer(Mount *m, usec_t usec) { int r; assert(m); if (m->timer_event_source) { r = sd_event_source_set_time(m->timer_event_source, usec); if (r < 0) return r; return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_ONESHOT); } if (usec == USEC_INFINITY) return 0; r = sd_event_add_time( UNIT(m)->manager->event, &m->timer_event_source, CLOCK_MONOTONIC, usec, 0, mount_dispatch_timer, m); if (r < 0) return r; (void) sd_event_source_set_description(m->timer_event_source, "mount-timer"); return 0; } static void mount_unwatch_control_pid(Mount *m) { assert(m); if (m->control_pid <= 0) return; unit_unwatch_pid(UNIT(m), m->control_pid); m->control_pid = 0; } static void mount_parameters_done(MountParameters *p) { assert(p); free(p->what); free(p->options); free(p->fstype); p->what = p->options = p->fstype = NULL; } static void mount_done(Unit *u) { Mount *m = MOUNT(u); assert(m); m->where = mfree(m->where); mount_parameters_done(&m->parameters_proc_self_mountinfo); mount_parameters_done(&m->parameters_fragment); m->exec_runtime = exec_runtime_unref(m->exec_runtime); exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX); m->control_command = NULL; mount_unwatch_control_pid(m); m->timer_event_source = sd_event_source_unref(m->timer_event_source); } _pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) { assert(m); if (m->from_fragment) return &m->parameters_fragment; return NULL; } _pure_ static MountParameters* get_mount_parameters(Mount *m) { assert(m); if (m->from_proc_self_mountinfo) return &m->parameters_proc_self_mountinfo; return get_mount_parameters_fragment(m); } static int mount_add_mount_links(Mount *m) { _cleanup_free_ char *parent = NULL; MountParameters *pm; Unit *other; Iterator i; Set *s; int r; assert(m); if (!path_equal(m->where, "/")) { /* Adds in links to other mount points that might lie further * up in the hierarchy */ parent = dirname_malloc(m->where); if (!parent) return -ENOMEM; r = unit_require_mounts_for(UNIT(m), parent); if (r < 0) return r; } /* Adds in links to other mount points that might be needed * for the source path (if this is a bind mount) to be * available. */ pm = get_mount_parameters_fragment(m); if (pm && pm->what && path_is_absolute(pm->what) && !mount_is_network(pm)) { r = unit_require_mounts_for(UNIT(m), pm->what); if (r < 0) return r; } /* Adds in links to other units that use this path or paths * further down in the hierarchy */ s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where); SET_FOREACH(other, s, i) { if (other->load_state != UNIT_LOADED) continue; if (other == UNIT(m)) continue; r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true); if (r < 0) return r; if (UNIT(m)->fragment_path) { /* If we have fragment configuration, then make this dependency required */ r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true); if (r < 0) return r; } } return 0; } static int mount_add_device_links(Mount *m) { MountParameters *p; bool device_wants_mount = false; int r; assert(m); p = get_mount_parameters(m); if (!p) return 0; if (!p->what) return 0; if (mount_is_bind(p)) return 0; if (!is_device_path(p->what)) return 0; /* /dev/root is a really weird thing, it's not a real device, * but just a path the kernel exports for the root file system * specified on the kernel command line. Ignore it here. */ if (path_equal(p->what, "/dev/root")) return 0; if (path_equal(m->where, "/")) return 0; if (mount_is_auto(p) && UNIT(m)->manager->running_as == MANAGER_SYSTEM) device_wants_mount = true; r = unit_add_node_link(UNIT(m), p->what, device_wants_mount, m->from_fragment ? UNIT_BINDS_TO : UNIT_REQUIRES); if (r < 0) return r; return 0; } static int mount_add_quota_links(Mount *m) { int r; MountParameters *p; assert(m); if (UNIT(m)->manager->running_as != MANAGER_SYSTEM) return 0; p = get_mount_parameters_fragment(m); if (!p) return 0; if (!needs_quota(p)) return 0; r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true); if (r < 0) return r; r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true); if (r < 0) return r; return 0; } static bool should_umount(Mount *m) { MountParameters *p; if (path_equal(m->where, "/") || path_equal(m->where, "/usr")) return false; p = get_mount_parameters(m); if (p && fstab_test_option(p->options, "x-initrd.mount\0") && !in_initrd()) return false; return true; } static int mount_add_default_dependencies(Mount *m) { MountParameters *p; const char *after; int r; assert(m); if (!UNIT(m)->default_dependencies) return 0; if (UNIT(m)->manager->running_as != MANAGER_SYSTEM) return 0; /* We do not add any default dependencies to / and /usr, since * they are guaranteed to stay mounted the whole time, since * our system is on it. Also, don't bother with anything * mounted below virtual file systems, it's also going to be * virtual, and hence not worth the effort. */ if (path_equal(m->where, "/") || path_equal(m->where, "/usr") || path_startswith(m->where, "/proc") || path_startswith(m->where, "/sys") || path_startswith(m->where, "/dev")) return 0; p = get_mount_parameters(m); if (!p) return 0; if (mount_is_network(p)) { /* We order ourselves after network.target. This is * primarily useful at shutdown: services that take * down the network should order themselves before * network.target, so that they are shut down only * after this mount unit is stopped. */ r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_NETWORK_TARGET, NULL, true); if (r < 0) return r; /* We pull in network-online.target, and order * ourselves after it. This is useful at start-up to * actively pull in tools that want to be started * before we start mounting network file systems, and * whose purpose it is to delay this until the network * is "up". */ r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, SPECIAL_NETWORK_ONLINE_TARGET, NULL, true); if (r < 0) return r; after = SPECIAL_REMOTE_FS_PRE_TARGET; } else after = SPECIAL_LOCAL_FS_PRE_TARGET; r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true); if (r < 0) return r; if (should_umount(m)) { r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true); if (r < 0) return r; } return 0; } static int mount_verify(Mount *m) { _cleanup_free_ char *e = NULL; int r; assert(m); if (UNIT(m)->load_state != UNIT_LOADED) return 0; if (!m->from_fragment && !m->from_proc_self_mountinfo) return -ENOENT; r = unit_name_from_path(m->where, ".mount", &e); if (r < 0) return log_unit_error_errno(UNIT(m), r, "Failed to generate unit name from mount path: %m"); if (!unit_has_name(UNIT(m), e)) { log_unit_error(UNIT(m), "Where= setting doesn't match unit name. Refusing."); return -EINVAL; } if (mount_point_is_api(m->where) || mount_point_ignore(m->where)) { log_unit_error(UNIT(m), "Cannot create mount unit for API file system %s. Refusing.", m->where); return -EINVAL; } if (UNIT(m)->fragment_path && !m->parameters_fragment.what) { log_unit_error(UNIT(m), "What= setting is missing. Refusing."); return -EBADMSG; } if (m->exec_context.pam_name && m->kill_context.kill_mode != KILL_CONTROL_GROUP) { log_unit_error(UNIT(m), "Unit has PAM enabled. Kill mode must be set to control-group'. Refusing."); return -EINVAL; } return 0; } static int mount_add_extras(Mount *m) { Unit *u = UNIT(m); int r; assert(m); if (u->fragment_path) m->from_fragment = true; if (!m->where) { r = unit_name_to_path(u->id, &m->where); if (r < 0) return r; } path_kill_slashes(m->where); if (!u->description) { r = unit_set_description(u, m->where); if (r < 0) return r; } r = mount_add_device_links(m); if (r < 0) return r; r = mount_add_mount_links(m); if (r < 0) return r; r = mount_add_quota_links(m); if (r < 0) return r; r = unit_patch_contexts(u); if (r < 0) return r; r = unit_add_exec_dependencies(u, &m->exec_context); if (r < 0) return r; r = unit_set_default_slice(u); if (r < 0) return r; r = mount_add_default_dependencies(m); if (r < 0) return r; return 0; } static int mount_load(Unit *u) { Mount *m = MOUNT(u); int r; assert(u); assert(u->load_state == UNIT_STUB); if (m->from_proc_self_mountinfo) r = unit_load_fragment_and_dropin_optional(u); else r = unit_load_fragment_and_dropin(u); if (r < 0) return r; /* This is a new unit? Then let's add in some extras */ if (u->load_state == UNIT_LOADED) { r = mount_add_extras(m); if (r < 0) return r; } return mount_verify(m); } static int mount_notify_automount(Mount *m, MountState old_state, MountState state) { Unit *p; int r; Iterator i; assert(m); SET_FOREACH(p, UNIT(m)->dependencies[UNIT_TRIGGERED_BY], i) if (p->type == UNIT_AUTOMOUNT) { r = automount_update_mount(AUTOMOUNT(p), old_state, state); if (r < 0) return r; } return 0; } static void mount_set_state(Mount *m, MountState state) { MountState old_state; assert(m); old_state = m->state; m->state = state; if (state != MOUNT_MOUNTING && state != MOUNT_MOUNTING_DONE && state != MOUNT_REMOUNTING && state != MOUNT_UNMOUNTING && state != MOUNT_MOUNTING_SIGTERM && state != MOUNT_MOUNTING_SIGKILL && state != MOUNT_UNMOUNTING_SIGTERM && state != MOUNT_UNMOUNTING_SIGKILL && state != MOUNT_REMOUNTING_SIGTERM && state != MOUNT_REMOUNTING_SIGKILL) { m->timer_event_source = sd_event_source_unref(m->timer_event_source); mount_unwatch_control_pid(m); m->control_command = NULL; m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID; } mount_notify_automount(m, old_state, state); if (state != old_state) log_unit_debug(UNIT(m), "Changed %s -> %s", mount_state_to_string(old_state), mount_state_to_string(state)); unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], m->reload_result == MOUNT_SUCCESS); m->reload_result = MOUNT_SUCCESS; } static int mount_coldplug(Unit *u) { Mount *m = MOUNT(u); MountState new_state = MOUNT_DEAD; int r; assert(m); assert(m->state == MOUNT_DEAD); if (m->deserialized_state != m->state) new_state = m->deserialized_state; else if (m->from_proc_self_mountinfo) new_state = MOUNT_MOUNTED; if (new_state == m->state) return 0; if (m->control_pid > 0 && pid_is_unwaited(m->control_pid) && IN_SET(new_state, MOUNT_MOUNTING, MOUNT_MOUNTING_DONE, MOUNT_REMOUNTING, MOUNT_UNMOUNTING, MOUNT_MOUNTING_SIGTERM, MOUNT_MOUNTING_SIGKILL, MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL)) { r = unit_watch_pid(UNIT(m), m->control_pid); if (r < 0) return r; r = mount_arm_timer(m, usec_add(u->state_change_timestamp.monotonic, m->timeout_usec)); if (r < 0) return r; } mount_set_state(m, new_state); return 0; } static void mount_dump(Unit *u, FILE *f, const char *prefix) { Mount *m = MOUNT(u); MountParameters *p; assert(m); assert(f); p = get_mount_parameters(m); fprintf(f, "%sMount State: %s\n" "%sResult: %s\n" "%sWhere: %s\n" "%sWhat: %s\n" "%sFile System Type: %s\n" "%sOptions: %s\n" "%sFrom /proc/self/mountinfo: %s\n" "%sFrom fragment: %s\n" "%sDirectoryMode: %04o\n", prefix, mount_state_to_string(m->state), prefix, mount_result_to_string(m->result), prefix, m->where, prefix, p ? strna(p->what) : "n/a", prefix, p ? strna(p->fstype) : "n/a", prefix, p ? strna(p->options) : "n/a", prefix, yes_no(m->from_proc_self_mountinfo), prefix, yes_no(m->from_fragment), prefix, m->directory_mode); if (m->control_pid > 0) fprintf(f, "%sControl PID: "PID_FMT"\n", prefix, m->control_pid); exec_context_dump(&m->exec_context, f, prefix); kill_context_dump(&m->kill_context, f, prefix); } static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { pid_t pid; int r; ExecParameters exec_params = { .apply_permissions = true, .apply_chroot = true, .apply_tty_stdin = true, .bus_endpoint_fd = -1, .stdin_fd = -1, .stdout_fd = -1, .stderr_fd = -1, }; assert(m); assert(c); assert(_pid); (void) unit_realize_cgroup(UNIT(m)); if (m->reset_cpu_usage) { (void) unit_reset_cpu_usage(UNIT(m)); m->reset_cpu_usage = false; } r = unit_setup_exec_runtime(UNIT(m)); if (r < 0) return r; r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->timeout_usec)); if (r < 0) return r; exec_params.environment = UNIT(m)->manager->environment; exec_params.confirm_spawn = UNIT(m)->manager->confirm_spawn; exec_params.cgroup_supported = UNIT(m)->manager->cgroup_supported; exec_params.cgroup_path = UNIT(m)->cgroup_path; exec_params.cgroup_delegate = m->cgroup_context.delegate; exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(m)->manager); r = exec_spawn(UNIT(m), c, &m->exec_context, &exec_params, m->exec_runtime, &pid); if (r < 0) return r; r = unit_watch_pid(UNIT(m), pid); if (r < 0) /* FIXME: we need to do something here */ return r; *_pid = pid; return 0; } static void mount_enter_dead(Mount *m, MountResult f) { assert(m); if (f != MOUNT_SUCCESS) m->result = f; exec_runtime_destroy(m->exec_runtime); m->exec_runtime = exec_runtime_unref(m->exec_runtime); exec_context_destroy_runtime_directory(&m->exec_context, manager_get_runtime_prefix(UNIT(m)->manager)); mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD); } static void mount_enter_mounted(Mount *m, MountResult f) { assert(m); if (f != MOUNT_SUCCESS) m->result = f; mount_set_state(m, MOUNT_MOUNTED); } static void mount_enter_signal(Mount *m, MountState state, MountResult f) { int r; assert(m); if (f != MOUNT_SUCCESS) m->result = f; r = unit_kill_context( UNIT(m), &m->kill_context, (state != MOUNT_MOUNTING_SIGTERM && state != MOUNT_UNMOUNTING_SIGTERM && state != MOUNT_REMOUNTING_SIGTERM) ? KILL_KILL : KILL_TERMINATE, -1, m->control_pid, false); if (r < 0) goto fail; if (r > 0) { r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->timeout_usec)); if (r < 0) goto fail; mount_set_state(m, state); } else if (state == MOUNT_REMOUNTING_SIGTERM) mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS); else if (state == MOUNT_REMOUNTING_SIGKILL) mount_enter_mounted(m, MOUNT_SUCCESS); else if (state == MOUNT_MOUNTING_SIGTERM) mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_SUCCESS); else if (state == MOUNT_UNMOUNTING_SIGTERM) mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS); else mount_enter_dead(m, MOUNT_SUCCESS); return; fail: log_unit_warning_errno(UNIT(m), r, "Failed to kill processes: %m"); if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL) mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES); else mount_enter_dead(m, MOUNT_FAILURE_RESOURCES); } static void mount_enter_unmounting(Mount *m) { int r; assert(m); /* Start counting our attempts */ if (!IN_SET(m->state, MOUNT_UNMOUNTING, MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL)) m->n_retry_umount = 0; m->control_command_id = MOUNT_EXEC_UNMOUNT; m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT; r = exec_command_set(m->control_command, UMOUNT_PATH, m->where, NULL); if (r < 0) goto fail; mount_unwatch_control_pid(m); r = mount_spawn(m, m->control_command, &m->control_pid); if (r < 0) goto fail; mount_set_state(m, MOUNT_UNMOUNTING); return; fail: log_unit_warning_errno(UNIT(m), r, "Failed to run 'umount' task: %m"); mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES); } static int mount_get_opts(Mount *m, char **ret) { return fstab_filter_options(m->parameters_fragment.options, "nofail\0" "noauto\0" "auto\0", NULL, NULL, ret); } static void mount_enter_mounting(Mount *m) { int r; MountParameters *p; assert(m); m->control_command_id = MOUNT_EXEC_MOUNT; m->control_command = m->exec_command + MOUNT_EXEC_MOUNT; r = unit_fail_if_symlink(UNIT(m), m->where); if (r < 0) goto fail; (void) mkdir_p_label(m->where, m->directory_mode); unit_warn_if_dir_nonempty(UNIT(m), m->where); /* Create the source directory for bind-mounts if needed */ p = get_mount_parameters_fragment(m); if (p && mount_is_bind(p)) (void) mkdir_p_label(p->what, m->directory_mode); if (m->from_fragment) { _cleanup_free_ char *opts = NULL; r = mount_get_opts(m, &opts); if (r < 0) goto fail; r = exec_command_set(m->control_command, MOUNT_PATH, m->parameters_fragment.what, m->where, NULL); if (r >= 0 && m->sloppy_options) r = exec_command_append(m->control_command, "-s", NULL); if (r >= 0 && m->parameters_fragment.fstype) r = exec_command_append(m->control_command, "-t", m->parameters_fragment.fstype, NULL); if (r >= 0 && !isempty(opts)) r = exec_command_append(m->control_command, "-o", opts, NULL); } else r = -ENOENT; if (r < 0) goto fail; mount_unwatch_control_pid(m); r = mount_spawn(m, m->control_command, &m->control_pid); if (r < 0) goto fail; mount_set_state(m, MOUNT_MOUNTING); return; fail: log_unit_warning_errno(UNIT(m), r, "Failed to run 'mount' task: %m"); mount_enter_dead(m, MOUNT_FAILURE_RESOURCES); } static void mount_enter_remounting(Mount *m) { int r; assert(m); m->control_command_id = MOUNT_EXEC_REMOUNT; m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT; if (m->from_fragment) { const char *o; if (m->parameters_fragment.options) o = strjoina("remount,", m->parameters_fragment.options); else o = "remount"; r = exec_command_set(m->control_command, MOUNT_PATH, m->parameters_fragment.what, m->where, "-o", o, NULL); if (r >= 0 && m->sloppy_options) r = exec_command_append(m->control_command, "-s", NULL); if (r >= 0 && m->parameters_fragment.fstype) r = exec_command_append(m->control_command, "-t", m->parameters_fragment.fstype, NULL); } else r = -ENOENT; if (r < 0) goto fail; mount_unwatch_control_pid(m); r = mount_spawn(m, m->control_command, &m->control_pid); if (r < 0) goto fail; mount_set_state(m, MOUNT_REMOUNTING); return; fail: log_unit_warning_errno(UNIT(m), r, "Failed to run 'remount' task: %m"); m->reload_result = MOUNT_FAILURE_RESOURCES; mount_enter_mounted(m, MOUNT_SUCCESS); } static int mount_start(Unit *u) { Mount *m = MOUNT(u); assert(m); /* We cannot fulfill this request right now, try again later * please! */ if (m->state == MOUNT_UNMOUNTING || m->state == MOUNT_UNMOUNTING_SIGTERM || m->state == MOUNT_UNMOUNTING_SIGKILL || m->state == MOUNT_MOUNTING_SIGTERM || m->state == MOUNT_MOUNTING_SIGKILL) return -EAGAIN; /* Already on it! */ if (m->state == MOUNT_MOUNTING) return 0; assert(m->state == MOUNT_DEAD || m->state == MOUNT_FAILED); m->result = MOUNT_SUCCESS; m->reload_result = MOUNT_SUCCESS; m->reset_cpu_usage = true; mount_enter_mounting(m); return 1; } static int mount_stop(Unit *u) { Mount *m = MOUNT(u); assert(m); /* Already on it */ if (m->state == MOUNT_UNMOUNTING || m->state == MOUNT_UNMOUNTING_SIGKILL || m->state == MOUNT_UNMOUNTING_SIGTERM || m->state == MOUNT_MOUNTING_SIGTERM || m->state == MOUNT_MOUNTING_SIGKILL) return 0; assert(m->state == MOUNT_MOUNTING || m->state == MOUNT_MOUNTING_DONE || m->state == MOUNT_MOUNTED || m->state == MOUNT_REMOUNTING || m->state == MOUNT_REMOUNTING_SIGTERM || m->state == MOUNT_REMOUNTING_SIGKILL); mount_enter_unmounting(m); return 1; } static int mount_reload(Unit *u) { Mount *m = MOUNT(u); assert(m); if (m->state == MOUNT_MOUNTING_DONE) return -EAGAIN; assert(m->state == MOUNT_MOUNTED); mount_enter_remounting(m); return 1; } static int mount_serialize(Unit *u, FILE *f, FDSet *fds) { Mount *m = MOUNT(u); assert(m); assert(f); assert(fds); unit_serialize_item(u, f, "state", mount_state_to_string(m->state)); unit_serialize_item(u, f, "result", mount_result_to_string(m->result)); unit_serialize_item(u, f, "reload-result", mount_result_to_string(m->reload_result)); if (m->control_pid > 0) unit_serialize_item_format(u, f, "control-pid", PID_FMT, m->control_pid); if (m->control_command_id >= 0) unit_serialize_item(u, f, "control-command", mount_exec_command_to_string(m->control_command_id)); return 0; } static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Mount *m = MOUNT(u); assert(u); assert(key); assert(value); assert(fds); if (streq(key, "state")) { MountState state; if ((state = mount_state_from_string(value)) < 0) log_unit_debug(u, "Failed to parse state value: %s", value); else m->deserialized_state = state; } else if (streq(key, "result")) { MountResult f; f = mount_result_from_string(value); if (f < 0) log_unit_debug(u, "Failed to parse result value: %s", value); else if (f != MOUNT_SUCCESS) m->result = f; } else if (streq(key, "reload-result")) { MountResult f; f = mount_result_from_string(value); if (f < 0) log_unit_debug(u, "Failed to parse reload result value: %s", value); else if (f != MOUNT_SUCCESS) m->reload_result = f; } else if (streq(key, "control-pid")) { pid_t pid; if (parse_pid(value, &pid) < 0) log_unit_debug(u, "Failed to parse control-pid value: %s", value); else m->control_pid = pid; } else if (streq(key, "control-command")) { MountExecCommand id; id = mount_exec_command_from_string(value); if (id < 0) log_unit_debug(u, "Failed to parse exec-command value: %s", value); else { m->control_command_id = id; m->control_command = m->exec_command + id; } } else log_unit_debug(u, "Unknown serialization key: %s", key); return 0; } _pure_ static UnitActiveState mount_active_state(Unit *u) { assert(u); return state_translation_table[MOUNT(u)->state]; } _pure_ static const char *mount_sub_state_to_string(Unit *u) { assert(u); return mount_state_to_string(MOUNT(u)->state); } _pure_ static bool mount_check_gc(Unit *u) { Mount *m = MOUNT(u); assert(m); return m->from_proc_self_mountinfo; } static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { Mount *m = MOUNT(u); MountResult f; assert(m); assert(pid >= 0); if (pid != m->control_pid) return; m->control_pid = 0; if (is_clean_exit(code, status, NULL)) f = MOUNT_SUCCESS; else if (code == CLD_EXITED) f = MOUNT_FAILURE_EXIT_CODE; else if (code == CLD_KILLED) f = MOUNT_FAILURE_SIGNAL; else if (code == CLD_DUMPED) f = MOUNT_FAILURE_CORE_DUMP; else assert_not_reached("Unknown code"); if (f != MOUNT_SUCCESS) m->result = f; if (m->control_command) { exec_status_exit(&m->control_command->exec_status, &m->exec_context, pid, code, status); m->control_command = NULL; m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID; } log_unit_full(u, f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0, "Mount process exited, code=%s status=%i", sigchld_code_to_string(code), status); /* Note that mount(8) returning and the kernel sending us a * mount table change event might happen out-of-order. If an * operation succeed we assume the kernel will follow soon too * and already change into the resulting state. If it fails * we check if the kernel still knows about the mount. and * change state accordingly. */ switch (m->state) { case MOUNT_MOUNTING: case MOUNT_MOUNTING_DONE: case MOUNT_MOUNTING_SIGKILL: case MOUNT_MOUNTING_SIGTERM: if (f == MOUNT_SUCCESS) mount_enter_mounted(m, f); else if (m->from_proc_self_mountinfo) mount_enter_mounted(m, f); else mount_enter_dead(m, f); break; case MOUNT_REMOUNTING: case MOUNT_REMOUNTING_SIGKILL: case MOUNT_REMOUNTING_SIGTERM: m->reload_result = f; if (m->from_proc_self_mountinfo) mount_enter_mounted(m, MOUNT_SUCCESS); else mount_enter_dead(m, MOUNT_SUCCESS); break; case MOUNT_UNMOUNTING: case MOUNT_UNMOUNTING_SIGKILL: case MOUNT_UNMOUNTING_SIGTERM: if (f == MOUNT_SUCCESS) { if (m->from_proc_self_mountinfo) { /* Still a mount point? If so, let's * try again. Most likely there were * multiple mount points stacked on * top of each other. Note that due to * the io event priority logic we can * be sure the new mountinfo is loaded * before we process the SIGCHLD for * the mount command. */ if (m->n_retry_umount < RETRY_UMOUNT_MAX) { log_unit_debug(u, "Mount still present, trying again."); m->n_retry_umount++; mount_enter_unmounting(m); } else { log_unit_debug(u, "Mount still present after %u attempts to unmount, giving up.", m->n_retry_umount); mount_enter_mounted(m, f); } } else mount_enter_dead(m, f); } else if (m->from_proc_self_mountinfo) mount_enter_mounted(m, f); else mount_enter_dead(m, f); break; default: assert_not_reached("Uh, control process died at wrong time."); } /* Notify clients about changed exit status */ unit_add_to_dbus_queue(u); } static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { Mount *m = MOUNT(userdata); assert(m); assert(m->timer_event_source == source); switch (m->state) { case MOUNT_MOUNTING: case MOUNT_MOUNTING_DONE: log_unit_warning(UNIT(m), "Mounting timed out. Stopping."); mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT); break; case MOUNT_REMOUNTING: log_unit_warning(UNIT(m), "Remounting timed out. Stopping."); m->reload_result = MOUNT_FAILURE_TIMEOUT; mount_enter_mounted(m, MOUNT_SUCCESS); break; case MOUNT_UNMOUNTING: log_unit_warning(UNIT(m), "Unmounting timed out. Stopping."); mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT); break; case MOUNT_MOUNTING_SIGTERM: if (m->kill_context.send_sigkill) { log_unit_warning(UNIT(m), "Mounting timed out. Killing."); mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT); } else { log_unit_warning(UNIT(m), "Mounting timed out. Skipping SIGKILL. Ignoring."); if (m->from_proc_self_mountinfo) mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT); else mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT); } break; case MOUNT_REMOUNTING_SIGTERM: if (m->kill_context.send_sigkill) { log_unit_warning(UNIT(m), "Remounting timed out. Killing."); mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT); } else { log_unit_warning(UNIT(m), "Remounting timed out. Skipping SIGKILL. Ignoring."); if (m->from_proc_self_mountinfo) mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT); else mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT); } break; case MOUNT_UNMOUNTING_SIGTERM: if (m->kill_context.send_sigkill) { log_unit_warning(UNIT(m), "Unmounting timed out. Killing."); mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT); } else { log_unit_warning(UNIT(m), "Unmounting timed out. Skipping SIGKILL. Ignoring."); if (m->from_proc_self_mountinfo) mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT); else mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT); } break; case MOUNT_MOUNTING_SIGKILL: case MOUNT_REMOUNTING_SIGKILL: case MOUNT_UNMOUNTING_SIGKILL: log_unit_warning(UNIT(m),"Mount process still around after SIGKILL. Ignoring."); if (m->from_proc_self_mountinfo) mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT); else mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT); break; default: assert_not_reached("Timeout at wrong time."); } return 0; } static int mount_setup_unit( Manager *m, const char *what, const char *where, const char *options, const char *fstype, bool set_flags) { _cleanup_free_ char *e = NULL, *w = NULL, *o = NULL, *f = NULL; bool load_extras = false; MountParameters *p; bool delete, changed = false; Unit *u; int r; assert(m); assert(what); assert(where); assert(options); assert(fstype); /* Ignore API mount points. They should never be referenced in * dependencies ever. */ if (mount_point_is_api(where) || mount_point_ignore(where)) return 0; if (streq(fstype, "autofs")) return 0; /* probably some kind of swap, ignore */ if (!is_path(where)) return 0; r = unit_name_from_path(where, ".mount", &e); if (r < 0) return r; u = manager_get_unit(m, e); if (!u) { delete = true; u = unit_new(m, sizeof(Mount)); if (!u) return log_oom(); r = unit_add_name(u, e); if (r < 0) goto fail; MOUNT(u)->where = strdup(where); if (!MOUNT(u)->where) { r = -ENOMEM; goto fail; } u->source_path = strdup("/proc/self/mountinfo"); if (!u->source_path) { r = -ENOMEM; goto fail; } if (m->running_as == MANAGER_SYSTEM) { const char* target; target = mount_needs_network(options, fstype) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET; r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, NULL, true); if (r < 0) goto fail; if (should_umount(MOUNT(u))) { r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true); if (r < 0) goto fail; } } unit_add_to_load_queue(u); changed = true; } else { delete = false; if (!MOUNT(u)->where) { MOUNT(u)->where = strdup(where); if (!MOUNT(u)->where) { r = -ENOMEM; goto fail; } } if (m->running_as == MANAGER_SYSTEM && mount_needs_network(options, fstype)) { /* _netdev option may have shown up late, or on a * remount. Add remote-fs dependencies, even though * local-fs ones may already be there. */ unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_REMOTE_FS_TARGET, NULL, true); load_extras = true; } if (u->load_state == UNIT_NOT_FOUND) { u->load_state = UNIT_LOADED; u->load_error = 0; /* Load in the extras later on, after we * finished initialization of the unit */ load_extras = true; changed = true; } } w = strdup(what); o = strdup(options); f = strdup(fstype); if (!w || !o || !f) { r = -ENOMEM; goto fail; } p = &MOUNT(u)->parameters_proc_self_mountinfo; changed = changed || !streq_ptr(p->options, options) || !streq_ptr(p->what, what) || !streq_ptr(p->fstype, fstype); if (set_flags) { MOUNT(u)->is_mounted = true; MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo; MOUNT(u)->just_changed = changed; } MOUNT(u)->from_proc_self_mountinfo = true; free(p->what); p->what = w; w = NULL; free(p->options); p->options = o; o = NULL; free(p->fstype); p->fstype = f; f = NULL; if (load_extras) { r = mount_add_extras(MOUNT(u)); if (r < 0) goto fail; } if (changed) unit_add_to_dbus_queue(u); return 0; fail: log_warning_errno(r, "Failed to set up mount unit: %m"); if (delete && u) unit_free(u); return r; } static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL; _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL; int r = 0; assert(m); t = mnt_new_table(); if (!t) return log_oom(); i = mnt_new_iter(MNT_ITER_FORWARD); if (!i) return log_oom(); r = mnt_table_parse_mtab(t, NULL); if (r < 0) return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); r = 0; for (;;) { const char *device, *path, *options, *fstype; _cleanup_free_ char *d = NULL, *p = NULL; struct libmnt_fs *fs; int k; k = mnt_table_next_fs(t, i, &fs); if (k == 1) break; if (k < 0) return log_error_errno(k, "Failed to get next entry from /proc/self/mountinfo: %m"); device = mnt_fs_get_source(fs); path = mnt_fs_get_target(fs); options = mnt_fs_get_options(fs); fstype = mnt_fs_get_fstype(fs); if (!device || !path) continue; if (cunescape(device, UNESCAPE_RELAX, &d) < 0) return log_oom(); if (cunescape(path, UNESCAPE_RELAX, &p) < 0) return log_oom(); (void) device_found_node(m, d, true, DEVICE_FOUND_MOUNT, set_flags); k = mount_setup_unit(m, d, p, options, fstype, set_flags); if (r == 0 && k < 0) r = k; } return r; } static void mount_shutdown(Manager *m) { assert(m); m->mount_event_source = sd_event_source_unref(m->mount_event_source); mnt_unref_monitor(m->mount_monitor); m->mount_monitor = NULL; } static int mount_get_timeout(Unit *u, usec_t *timeout) { Mount *m = MOUNT(u); usec_t t; int r; if (!m->timer_event_source) return 0; r = sd_event_source_get_time(m->timer_event_source, &t); if (r < 0) return r; if (t == USEC_INFINITY) return 0; *timeout = t; return 1; } static void mount_enumerate(Manager *m) { int r; assert(m); mnt_init_debug(0); if (!m->mount_monitor) { int fd; m->mount_monitor = mnt_new_monitor(); if (!m->mount_monitor) { log_oom(); goto fail; } r = mnt_monitor_enable_kernel(m->mount_monitor, 1); if (r < 0) { log_error_errno(r, "Failed to enable watching of kernel mount events: %m"); goto fail; } r = mnt_monitor_enable_userspace(m->mount_monitor, 1, NULL); if (r < 0) { log_error_errno(r, "Failed to enable watching of userspace mount events: %m"); goto fail; } /* mnt_unref_monitor() will close the fd */ fd = r = mnt_monitor_get_fd(m->mount_monitor); if (r < 0) { log_error_errno(r, "Failed to acquire watch file descriptor: %m"); goto fail; } r = sd_event_add_io(m->event, &m->mount_event_source, fd, EPOLLIN, mount_dispatch_io, m); if (r < 0) { log_error_errno(r, "Failed to watch mount file descriptor: %m"); goto fail; } r = sd_event_source_set_priority(m->mount_event_source, -10); if (r < 0) { log_error_errno(r, "Failed to adjust mount watch priority: %m"); goto fail; } (void) sd_event_source_set_description(m->mount_event_source, "mount-monitor-dispatch"); } r = mount_load_proc_self_mountinfo(m, false); if (r < 0) goto fail; return; fail: mount_shutdown(m); } static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { _cleanup_set_free_ Set *around = NULL, *gone = NULL; Manager *m = userdata; const char *what; Iterator i; Unit *u; int r; assert(m); assert(revents & EPOLLIN); if (fd == mnt_monitor_get_fd(m->mount_monitor)) { bool rescan = false; /* Drain all events and verify that the event is valid. * * Note that libmount also monitors /run/mount mkdir if the * directory does not exist yet. The mkdir may generate event * which is irrelevant for us. * * error: r < 0; valid: r == 0, false positive: rc == 1 */ do { r = mnt_monitor_next_change(m->mount_monitor, NULL, NULL); if (r == 0) rescan = true; else if (r < 0) return log_error_errno(r, "Failed to drain libmount events"); } while (r == 0); log_debug("libmount event [rescan: %s]", yes_no(rescan)); if (!rescan) return 0; } r = mount_load_proc_self_mountinfo(m, true); if (r < 0) { /* Reset flags, just in case, for later calls */ LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) { Mount *mount = MOUNT(u); mount->is_mounted = mount->just_mounted = mount->just_changed = false; } return 0; } manager_dispatch_load_queue(m); LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) { Mount *mount = MOUNT(u); if (!mount->is_mounted) { /* A mount point is not around right now. It * might be gone, or might never have * existed. */ if (mount->from_proc_self_mountinfo && mount->parameters_proc_self_mountinfo.what) { /* Remember that this device might just have disappeared */ if (set_ensure_allocated(&gone, &string_hash_ops) < 0 || set_put(gone, mount->parameters_proc_self_mountinfo.what) < 0) log_oom(); /* we don't care too much about OOM here... */ } mount->from_proc_self_mountinfo = false; switch (mount->state) { case MOUNT_MOUNTED: /* This has just been unmounted by * somebody else, follow the state * change. */ mount_enter_dead(mount, MOUNT_SUCCESS); break; default: break; } } else if (mount->just_mounted || mount->just_changed) { /* A mount point was added or changed */ switch (mount->state) { case MOUNT_DEAD: case MOUNT_FAILED: /* This has just been mounted by * somebody else, follow the state * change. */ mount_enter_mounted(mount, MOUNT_SUCCESS); break; case MOUNT_MOUNTING: mount_set_state(mount, MOUNT_MOUNTING_DONE); break; default: /* Nothing really changed, but let's * issue an notification call * nonetheless, in case somebody is * waiting for this. (e.g. file system * ro/rw remounts.) */ mount_set_state(mount, mount->state); break; } } if (mount->is_mounted && mount->from_proc_self_mountinfo && mount->parameters_proc_self_mountinfo.what) { if (set_ensure_allocated(&around, &string_hash_ops) < 0 || set_put(around, mount->parameters_proc_self_mountinfo.what) < 0) log_oom(); } /* Reset the flags for later calls */ mount->is_mounted = mount->just_mounted = mount->just_changed = false; } SET_FOREACH(what, gone, i) { if (set_contains(around, what)) continue; /* Let the device units know that the device is no longer mounted */ (void) device_found_node(m, what, false, DEVICE_FOUND_MOUNT, true); } return 0; } static void mount_reset_failed(Unit *u) { Mount *m = MOUNT(u); assert(m); if (m->state == MOUNT_FAILED) mount_set_state(m, MOUNT_DEAD); m->result = MOUNT_SUCCESS; m->reload_result = MOUNT_SUCCESS; } static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error); } static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = { [MOUNT_EXEC_MOUNT] = "ExecMount", [MOUNT_EXEC_UNMOUNT] = "ExecUnmount", [MOUNT_EXEC_REMOUNT] = "ExecRemount", }; DEFINE_STRING_TABLE_LOOKUP(mount_exec_command, MountExecCommand); static const char* const mount_result_table[_MOUNT_RESULT_MAX] = { [MOUNT_SUCCESS] = "success", [MOUNT_FAILURE_RESOURCES] = "resources", [MOUNT_FAILURE_TIMEOUT] = "timeout", [MOUNT_FAILURE_EXIT_CODE] = "exit-code", [MOUNT_FAILURE_SIGNAL] = "signal", [MOUNT_FAILURE_CORE_DUMP] = "core-dump" }; DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult); const UnitVTable mount_vtable = { .object_size = sizeof(Mount), .exec_context_offset = offsetof(Mount, exec_context), .cgroup_context_offset = offsetof(Mount, cgroup_context), .kill_context_offset = offsetof(Mount, kill_context), .exec_runtime_offset = offsetof(Mount, exec_runtime), .sections = "Unit\0" "Mount\0" "Install\0", .private_section = "Mount", .no_alias = true, .no_instances = true, .init = mount_init, .load = mount_load, .done = mount_done, .coldplug = mount_coldplug, .dump = mount_dump, .start = mount_start, .stop = mount_stop, .reload = mount_reload, .kill = mount_kill, .serialize = mount_serialize, .deserialize_item = mount_deserialize_item, .active_state = mount_active_state, .sub_state_to_string = mount_sub_state_to_string, .check_gc = mount_check_gc, .sigchld_event = mount_sigchld_event, .reset_failed = mount_reset_failed, .bus_vtable = bus_mount_vtable, .bus_set_property = bus_mount_set_property, .bus_commit_properties = bus_mount_commit_properties, .get_timeout = mount_get_timeout, .can_transient = true, .enumerate = mount_enumerate, .shutdown = mount_shutdown, .status_message_formats = { .starting_stopping = { [0] = "Mounting %s...", [1] = "Unmounting %s...", }, .finished_start_job = { [JOB_DONE] = "Mounted %s.", [JOB_FAILED] = "Failed to mount %s.", [JOB_TIMEOUT] = "Timed out mounting %s.", }, .finished_stop_job = { [JOB_DONE] = "Unmounted %s.", [JOB_FAILED] = "Failed unmounting %s.", [JOB_TIMEOUT] = "Timed out unmounting %s.", }, }, }; systemd-229/src/core/mount.h000066400000000000000000000054161265713322000161210ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Mount Mount; #include "execute.h" #include "kill.h" typedef enum MountExecCommand { MOUNT_EXEC_MOUNT, MOUNT_EXEC_UNMOUNT, MOUNT_EXEC_REMOUNT, _MOUNT_EXEC_COMMAND_MAX, _MOUNT_EXEC_COMMAND_INVALID = -1 } MountExecCommand; typedef enum MountResult { MOUNT_SUCCESS, MOUNT_FAILURE_RESOURCES, MOUNT_FAILURE_TIMEOUT, MOUNT_FAILURE_EXIT_CODE, MOUNT_FAILURE_SIGNAL, MOUNT_FAILURE_CORE_DUMP, _MOUNT_RESULT_MAX, _MOUNT_RESULT_INVALID = -1 } MountResult; typedef struct MountParameters { char *what; char *options; char *fstype; } MountParameters; struct Mount { Unit meta; char *where; MountParameters parameters_proc_self_mountinfo; MountParameters parameters_fragment; bool from_proc_self_mountinfo:1; bool from_fragment:1; /* Used while looking for mount points that vanished or got * added from/to /proc/self/mountinfo */ bool is_mounted:1; bool just_mounted:1; bool just_changed:1; bool reset_cpu_usage:1; bool sloppy_options; MountResult result; MountResult reload_result; mode_t directory_mode; usec_t timeout_usec; ExecCommand exec_command[_MOUNT_EXEC_COMMAND_MAX]; ExecContext exec_context; KillContext kill_context; CGroupContext cgroup_context; ExecRuntime *exec_runtime; MountState state, deserialized_state; ExecCommand* control_command; MountExecCommand control_command_id; pid_t control_pid; sd_event_source *timer_event_source; unsigned n_retry_umount; }; extern const UnitVTable mount_vtable; void mount_fd_event(Manager *m, int events); const char* mount_exec_command_to_string(MountExecCommand i) _const_; MountExecCommand mount_exec_command_from_string(const char *s) _pure_; const char* mount_result_to_string(MountResult i) _const_; MountResult mount_result_from_string(const char *s) _pure_; systemd-229/src/core/namespace.c000066400000000000000000000511651265713322000167100ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "dev-setup.h" #include "fd-util.h" #include "loopback-setup.h" #include "missing.h" #include "mkdir.h" #include "mount-util.h" #include "namespace.h" #include "path-util.h" #include "selinux-util.h" #include "socket-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "umask-util.h" #include "user-util.h" #include "util.h" typedef enum MountMode { /* This is ordered by priority! */ INACCESSIBLE, READONLY, PRIVATE_TMP, PRIVATE_VAR_TMP, PRIVATE_DEV, PRIVATE_BUS_ENDPOINT, READWRITE } MountMode; typedef struct BindMount { const char *path; MountMode mode; bool done; bool ignore; } BindMount; static int append_mounts(BindMount **p, char **strv, MountMode mode) { char **i; assert(p); STRV_FOREACH(i, strv) { (*p)->ignore = false; (*p)->done = false; if ((mode == INACCESSIBLE || mode == READONLY || mode == READWRITE) && (*i)[0] == '-') { (*p)->ignore = true; (*i)++; } if (!path_is_absolute(*i)) return -EINVAL; (*p)->path = *i; (*p)->mode = mode; (*p)++; } return 0; } static int mount_path_compare(const void *a, const void *b) { const BindMount *p = a, *q = b; int d; d = path_compare(p->path, q->path); if (d == 0) { /* If the paths are equal, check the mode */ if (p->mode < q->mode) return -1; if (p->mode > q->mode) return 1; return 0; } /* If the paths are not equal, then order prefixes first */ return d; } static void drop_duplicates(BindMount *m, unsigned *n) { BindMount *f, *t, *previous; assert(m); assert(n); for (f = m, t = m, previous = NULL; f < m+*n; f++) { /* The first one wins */ if (previous && path_equal(f->path, previous->path)) continue; *t = *f; previous = t; t++; } *n = t - m; } static int mount_dev(BindMount *m) { static const char devnodes[] = "/dev/null\0" "/dev/zero\0" "/dev/full\0" "/dev/random\0" "/dev/urandom\0" "/dev/tty\0"; char temporary_mount[] = "/tmp/namespace-dev-XXXXXX"; const char *d, *dev = NULL, *devpts = NULL, *devshm = NULL, *devhugepages = NULL, *devmqueue = NULL, *devlog = NULL, *devptmx = NULL; _cleanup_umask_ mode_t u; int r; assert(m); u = umask(0000); if (!mkdtemp(temporary_mount)) return -errno; dev = strjoina(temporary_mount, "/dev"); (void) mkdir(dev, 0755); if (mount("tmpfs", dev, "tmpfs", MS_NOSUID|MS_STRICTATIME, "mode=755") < 0) { r = -errno; goto fail; } devpts = strjoina(temporary_mount, "/dev/pts"); (void) mkdir(devpts, 0755); if (mount("/dev/pts", devpts, NULL, MS_BIND, NULL) < 0) { r = -errno; goto fail; } devptmx = strjoina(temporary_mount, "/dev/ptmx"); if (symlink("pts/ptmx", devptmx) < 0) { r = -errno; goto fail; } devshm = strjoina(temporary_mount, "/dev/shm"); (void) mkdir(devshm, 01777); r = mount("/dev/shm", devshm, NULL, MS_BIND, NULL); if (r < 0) { r = -errno; goto fail; } devmqueue = strjoina(temporary_mount, "/dev/mqueue"); (void) mkdir(devmqueue, 0755); (void) mount("/dev/mqueue", devmqueue, NULL, MS_BIND, NULL); devhugepages = strjoina(temporary_mount, "/dev/hugepages"); (void) mkdir(devhugepages, 0755); (void) mount("/dev/hugepages", devhugepages, NULL, MS_BIND, NULL); devlog = strjoina(temporary_mount, "/dev/log"); (void) symlink("/run/systemd/journal/dev-log", devlog); NULSTR_FOREACH(d, devnodes) { _cleanup_free_ char *dn = NULL; struct stat st; r = stat(d, &st); if (r < 0) { if (errno == ENOENT) continue; r = -errno; goto fail; } if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) { r = -EINVAL; goto fail; } if (st.st_rdev == 0) continue; dn = strappend(temporary_mount, d); if (!dn) { r = -ENOMEM; goto fail; } mac_selinux_create_file_prepare(d, st.st_mode); r = mknod(dn, st.st_mode, st.st_rdev); mac_selinux_create_file_clear(); if (r < 0) { r = -errno; goto fail; } } dev_setup(temporary_mount, UID_INVALID, GID_INVALID); /* Create the /dev directory if missing. It is more likely to be * missing when the service is started with RootDirectory. This is * consistent with mount units creating the mount points when missing. */ (void) mkdir_p_label(m->path, 0755); if (mount(dev, m->path, NULL, MS_MOVE, NULL) < 0) { r = -errno; goto fail; } rmdir(dev); rmdir(temporary_mount); return 0; fail: if (devpts) umount(devpts); if (devshm) umount(devshm); if (devhugepages) umount(devhugepages); if (devmqueue) umount(devmqueue); umount(dev); rmdir(dev); rmdir(temporary_mount); return r; } static int mount_kdbus(BindMount *m) { char temporary_mount[] = "/tmp/kdbus-dev-XXXXXX"; _cleanup_free_ char *basepath = NULL; _cleanup_umask_ mode_t u; char *busnode = NULL, *root; struct stat st; int r; assert(m); u = umask(0000); if (!mkdtemp(temporary_mount)) return log_error_errno(errno, "Failed create temp dir: %m"); root = strjoina(temporary_mount, "/kdbus"); (void) mkdir(root, 0755); if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_STRICTATIME, "mode=777") < 0) { r = -errno; goto fail; } /* create a new /dev/null dev node copy so we have some fodder to * bind-mount the custom endpoint over. */ if (stat("/dev/null", &st) < 0) { r = log_error_errno(errno, "Failed to stat /dev/null: %m"); goto fail; } busnode = strjoina(root, "/bus"); if (mknod(busnode, (st.st_mode & ~07777) | 0600, st.st_rdev) < 0) { r = log_error_errno(errno, "mknod() for %s failed: %m", busnode); goto fail; } r = mount(m->path, busnode, NULL, MS_BIND, NULL); if (r < 0) { r = log_error_errno(errno, "bind mount of %s failed: %m", m->path); goto fail; } basepath = dirname_malloc(m->path); if (!basepath) { r = -ENOMEM; goto fail; } if (mount(root, basepath, NULL, MS_MOVE, NULL) < 0) { r = log_error_errno(errno, "bind mount of %s failed: %m", basepath); goto fail; } rmdir(temporary_mount); return 0; fail: if (busnode) { umount(busnode); unlink(busnode); } umount(root); rmdir(root); rmdir(temporary_mount); return r; } static int apply_mount( BindMount *m, const char *tmp_dir, const char *var_tmp_dir) { const char *what; int r; assert(m); switch (m->mode) { case INACCESSIBLE: /* First, get rid of everything that is below if there * is anything... Then, overmount it with an * inaccessible directory. */ umount_recursive(m->path, 0); what = "/run/systemd/inaccessible"; break; case READONLY: case READWRITE: /* Nothing to mount here, we just later toggle the * MS_RDONLY bit for the mount point */ return 0; case PRIVATE_TMP: what = tmp_dir; break; case PRIVATE_VAR_TMP: what = var_tmp_dir; break; case PRIVATE_DEV: return mount_dev(m); case PRIVATE_BUS_ENDPOINT: return mount_kdbus(m); default: assert_not_reached("Unknown mode"); } assert(what); r = mount(what, m->path, NULL, MS_BIND|MS_REC, NULL); if (r >= 0) log_debug("Successfully mounted %s to %s", what, m->path); else if (m->ignore && errno == ENOENT) return 0; return r; } static int make_read_only(BindMount *m) { int r; assert(m); if (IN_SET(m->mode, INACCESSIBLE, READONLY)) r = bind_remount_recursive(m->path, true); else if (IN_SET(m->mode, READWRITE, PRIVATE_TMP, PRIVATE_VAR_TMP, PRIVATE_DEV)) r = bind_remount_recursive(m->path, false); else r = 0; if (m->ignore && r == -ENOENT) return 0; return r; } int setup_namespace( const char* root_directory, char** read_write_dirs, char** read_only_dirs, char** inaccessible_dirs, const char* tmp_dir, const char* var_tmp_dir, const char* bus_endpoint_path, bool private_dev, ProtectHome protect_home, ProtectSystem protect_system, unsigned long mount_flags) { BindMount *m, *mounts = NULL; unsigned n; int r = 0; if (mount_flags == 0) mount_flags = MS_SHARED; if (unshare(CLONE_NEWNS) < 0) return -errno; n = !!tmp_dir + !!var_tmp_dir + !!bus_endpoint_path + strv_length(read_write_dirs) + strv_length(read_only_dirs) + strv_length(inaccessible_dirs) + private_dev + (protect_home != PROTECT_HOME_NO ? 3 : 0) + (protect_system != PROTECT_SYSTEM_NO ? 2 : 0) + (protect_system == PROTECT_SYSTEM_FULL ? 1 : 0); if (n > 0) { m = mounts = (BindMount *) alloca0(n * sizeof(BindMount)); r = append_mounts(&m, read_write_dirs, READWRITE); if (r < 0) return r; r = append_mounts(&m, read_only_dirs, READONLY); if (r < 0) return r; r = append_mounts(&m, inaccessible_dirs, INACCESSIBLE); if (r < 0) return r; if (tmp_dir) { m->path = prefix_roota(root_directory, "/tmp"); m->mode = PRIVATE_TMP; m++; } if (var_tmp_dir) { m->path = prefix_roota(root_directory, "/var/tmp"); m->mode = PRIVATE_VAR_TMP; m++; } if (private_dev) { m->path = prefix_roota(root_directory, "/dev"); m->mode = PRIVATE_DEV; m++; } if (bus_endpoint_path) { m->path = prefix_roota(root_directory, bus_endpoint_path); m->mode = PRIVATE_BUS_ENDPOINT; m++; } if (protect_home != PROTECT_HOME_NO) { const char *home_dir, *run_user_dir, *root_dir; home_dir = prefix_roota(root_directory, "/home"); home_dir = strjoina("-", home_dir); run_user_dir = prefix_roota(root_directory, "/run/user"); run_user_dir = strjoina("-", run_user_dir); root_dir = prefix_roota(root_directory, "/root"); root_dir = strjoina("-", root_dir); r = append_mounts(&m, STRV_MAKE(home_dir, run_user_dir, root_dir), protect_home == PROTECT_HOME_READ_ONLY ? READONLY : INACCESSIBLE); if (r < 0) return r; } if (protect_system != PROTECT_SYSTEM_NO) { const char *usr_dir, *boot_dir, *etc_dir; usr_dir = prefix_roota(root_directory, "/usr"); boot_dir = prefix_roota(root_directory, "/boot"); boot_dir = strjoina("-", boot_dir); etc_dir = prefix_roota(root_directory, "/etc"); r = append_mounts(&m, protect_system == PROTECT_SYSTEM_FULL ? STRV_MAKE(usr_dir, boot_dir, etc_dir) : STRV_MAKE(usr_dir, boot_dir), READONLY); if (r < 0) return r; } assert(mounts + n == m); qsort(mounts, n, sizeof(BindMount), mount_path_compare); drop_duplicates(mounts, &n); } if (n > 0 || root_directory) { /* Remount / as SLAVE so that nothing now mounted in the namespace shows up in the parent */ if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) return -errno; } if (root_directory) { /* Turn directory into bind mount */ if (mount(root_directory, root_directory, NULL, MS_BIND|MS_REC, NULL) < 0) return -errno; } if (n > 0) { for (m = mounts; m < mounts + n; ++m) { r = apply_mount(m, tmp_dir, var_tmp_dir); if (r < 0) goto fail; } for (m = mounts; m < mounts + n; ++m) { r = make_read_only(m); if (r < 0) goto fail; } } if (root_directory) { /* MS_MOVE does not work on MS_SHARED so the remount MS_SHARED will be done later */ r = mount_move_root(root_directory); /* at this point, we cannot rollback */ if (r < 0) return r; } /* Remount / as the desired mode. Not that this will not * reestablish propagation from our side to the host, since * what's disconnected is disconnected. */ if (mount(NULL, "/", NULL, mount_flags | MS_REC, NULL) < 0) /* at this point, we cannot rollback */ return -errno; return 0; fail: if (n > 0) { for (m = mounts; m < mounts + n; ++m) if (m->done) (void) umount2(m->path, MNT_DETACH); } return r; } static int setup_one_tmp_dir(const char *id, const char *prefix, char **path) { _cleanup_free_ char *x = NULL; char bid[SD_ID128_STRING_MAX]; sd_id128_t boot_id; int r; assert(id); assert(prefix); assert(path); /* We include the boot id in the directory so that after a * reboot we can easily identify obsolete directories. */ r = sd_id128_get_boot(&boot_id); if (r < 0) return r; x = strjoin(prefix, "/systemd-private-", sd_id128_to_string(boot_id, bid), "-", id, "-XXXXXX", NULL); if (!x) return -ENOMEM; RUN_WITH_UMASK(0077) if (!mkdtemp(x)) return -errno; RUN_WITH_UMASK(0000) { char *y; y = strjoina(x, "/tmp"); if (mkdir(y, 0777 | S_ISVTX) < 0) return -errno; } *path = x; x = NULL; return 0; } int setup_tmp_dirs(const char *id, char **tmp_dir, char **var_tmp_dir) { char *a, *b; int r; assert(id); assert(tmp_dir); assert(var_tmp_dir); r = setup_one_tmp_dir(id, "/tmp", &a); if (r < 0) return r; r = setup_one_tmp_dir(id, "/var/tmp", &b); if (r < 0) { char *t; t = strjoina(a, "/tmp"); rmdir(t); rmdir(a); free(a); return r; } *tmp_dir = a; *var_tmp_dir = b; return 0; } int setup_netns(int netns_storage_socket[2]) { _cleanup_close_ int netns = -1; int r, q; assert(netns_storage_socket); assert(netns_storage_socket[0] >= 0); assert(netns_storage_socket[1] >= 0); /* We use the passed socketpair as a storage buffer for our * namespace reference fd. Whatever process runs this first * shall create a new namespace, all others should just join * it. To serialize that we use a file lock on the socket * pair. * * It's a bit crazy, but hey, works great! */ if (lockf(netns_storage_socket[0], F_LOCK, 0) < 0) return -errno; netns = receive_one_fd(netns_storage_socket[0], MSG_DONTWAIT); if (netns == -EAGAIN) { /* Nothing stored yet, so let's create a new namespace */ if (unshare(CLONE_NEWNET) < 0) { r = -errno; goto fail; } loopback_setup(); netns = open("/proc/self/ns/net", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (netns < 0) { r = -errno; goto fail; } r = 1; } else if (netns < 0) { r = netns; goto fail; } else { /* Yay, found something, so let's join the namespace */ if (setns(netns, CLONE_NEWNET) < 0) { r = -errno; goto fail; } r = 0; } q = send_one_fd(netns_storage_socket[1], netns, MSG_DONTWAIT); if (q < 0) { r = q; goto fail; } fail: lockf(netns_storage_socket[0], F_ULOCK, 0); return r; } static const char *const protect_home_table[_PROTECT_HOME_MAX] = { [PROTECT_HOME_NO] = "no", [PROTECT_HOME_YES] = "yes", [PROTECT_HOME_READ_ONLY] = "read-only", }; DEFINE_STRING_TABLE_LOOKUP(protect_home, ProtectHome); static const char *const protect_system_table[_PROTECT_SYSTEM_MAX] = { [PROTECT_SYSTEM_NO] = "no", [PROTECT_SYSTEM_YES] = "yes", [PROTECT_SYSTEM_FULL] = "full", }; DEFINE_STRING_TABLE_LOOKUP(protect_system, ProtectSystem); systemd-229/src/core/namespace.h000066400000000000000000000040041265713322000167030ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" typedef enum ProtectHome { PROTECT_HOME_NO, PROTECT_HOME_YES, PROTECT_HOME_READ_ONLY, _PROTECT_HOME_MAX, _PROTECT_HOME_INVALID = -1 } ProtectHome; typedef enum ProtectSystem { PROTECT_SYSTEM_NO, PROTECT_SYSTEM_YES, PROTECT_SYSTEM_FULL, _PROTECT_SYSTEM_MAX, _PROTECT_SYSTEM_INVALID = -1 } ProtectSystem; int setup_namespace(const char *chroot, char **read_write_dirs, char **read_only_dirs, char **inaccessible_dirs, const char *tmp_dir, const char *var_tmp_dir, const char *endpoint_path, bool private_dev, ProtectHome protect_home, ProtectSystem protect_system, unsigned long mount_flags); int setup_tmp_dirs(const char *id, char **tmp_dir, char **var_tmp_dir); int setup_netns(int netns_storage_socket[2]); const char* protect_home_to_string(ProtectHome p) _const_; ProtectHome protect_home_from_string(const char *s) _pure_; const char* protect_system_to_string(ProtectSystem p) _const_; ProtectSystem protect_system_from_string(const char *s) _pure_; systemd-229/src/core/org.freedesktop.systemd1.conf000066400000000000000000000227701265713322000223300ustar00rootroot00000000000000 systemd-229/src/core/org.freedesktop.systemd1.policy.in.in000066400000000000000000000065131265713322000237110ustar00rootroot00000000000000 The systemd Project http://www.freedesktop.org/wiki/Software/systemd <_description>Send passphrase back to system <_message>Authentication is required to send the entered passphrase back to the system. no no auth_admin_keep @rootlibexecdir@/systemd-reply-password <_description>Manage system services or other units <_message>Authentication is required to manage system services or other units. auth_admin auth_admin auth_admin_keep <_description>Manage system service or unit files <_message>Authentication is required to manage system service or unit files. auth_admin auth_admin auth_admin_keep <_description>Set or unset system and service manager environment variables <_message>Authentication is required to set or unset system and service manager environment variables. auth_admin auth_admin auth_admin_keep <_description>Reload the systemd state <_message>Authentication is required to reload the systemd state. auth_admin auth_admin auth_admin_keep systemd-229/src/core/org.freedesktop.systemd1.service000066400000000000000000000005541265713322000230370ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] Name=org.freedesktop.systemd1 Exec=/bin/false User=root systemd-229/src/core/path.c000066400000000000000000000513621265713322000157070ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "bus-error.h" #include "bus-util.h" #include "dbus-path.h" #include "fd-util.h" #include "fs-util.h" #include "glob-util.h" #include "macro.h" #include "mkdir.h" #include "path.h" #include "special.h" #include "stat-util.h" #include "string-table.h" #include "string-util.h" #include "unit-name.h" #include "unit.h" static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = { [PATH_DEAD] = UNIT_INACTIVE, [PATH_WAITING] = UNIT_ACTIVE, [PATH_RUNNING] = UNIT_ACTIVE, [PATH_FAILED] = UNIT_FAILED }; static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) { static const int flags_table[_PATH_TYPE_MAX] = { [PATH_EXISTS] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, [PATH_EXISTS_GLOB] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, [PATH_CHANGED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO, [PATH_MODIFIED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO|IN_MODIFY, [PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO }; bool exists = false; char *slash, *oldslash = NULL; int r; assert(s); assert(s->unit); assert(handler); path_spec_unwatch(s); s->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (s->inotify_fd < 0) { r = -errno; goto fail; } r = sd_event_add_io(s->unit->manager->event, &s->event_source, s->inotify_fd, EPOLLIN, handler, s); if (r < 0) goto fail; (void) sd_event_source_set_description(s->event_source, "path"); /* This assumes the path was passed through path_kill_slashes()! */ for (slash = strchr(s->path, '/'); ; slash = strchr(slash+1, '/')) { char *cut = NULL; int flags; char tmp; if (slash) { cut = slash + (slash == s->path); tmp = *cut; *cut = '\0'; flags = IN_MOVE_SELF | IN_DELETE_SELF | IN_ATTRIB | IN_CREATE | IN_MOVED_TO; } else flags = flags_table[s->type]; r = inotify_add_watch(s->inotify_fd, s->path, flags); if (r < 0) { if (errno == EACCES || errno == ENOENT) { if (cut) *cut = tmp; break; } r = log_warning_errno(errno, "Failed to add watch on %s: %s", s->path, errno == ENOSPC ? "too many watches" : strerror(-r)); if (cut) *cut = tmp; goto fail; } else { exists = true; /* Path exists, we don't need to watch parent too closely. */ if (oldslash) { char *cut2 = oldslash + (oldslash == s->path); char tmp2 = *cut2; *cut2 = '\0'; inotify_add_watch(s->inotify_fd, s->path, IN_MOVE_SELF); /* Error is ignored, the worst can happen is we get spurious events. */ *cut2 = tmp2; } } if (cut) *cut = tmp; if (slash) oldslash = slash; else { /* whole path has been iterated over */ s->primary_wd = r; break; } } if (!exists) { r = log_error_errno(errno, "Failed to add watch on any of the components of %s: %m", s->path); /* either EACCESS or ENOENT */ goto fail; } return 0; fail: path_spec_unwatch(s); return r; } void path_spec_unwatch(PathSpec *s) { assert(s); s->event_source = sd_event_source_unref(s->event_source); s->inotify_fd = safe_close(s->inotify_fd); } int path_spec_fd_event(PathSpec *s, uint32_t revents) { union inotify_event_buffer buffer; struct inotify_event *e; ssize_t l; int r = 0; if (revents != EPOLLIN) { log_error("Got invalid poll event on inotify."); return -EINVAL; } l = read(s->inotify_fd, &buffer, sizeof(buffer)); if (l < 0) { if (errno == EAGAIN || errno == EINTR) return 0; return log_error_errno(errno, "Failed to read inotify event: %m"); } FOREACH_INOTIFY_EVENT(e, buffer, l) { if ((s->type == PATH_CHANGED || s->type == PATH_MODIFIED) && s->primary_wd == e->wd) r = 1; } return r; } static bool path_spec_check_good(PathSpec *s, bool initial) { bool good = false; switch (s->type) { case PATH_EXISTS: good = access(s->path, F_OK) >= 0; break; case PATH_EXISTS_GLOB: good = glob_exists(s->path) > 0; break; case PATH_DIRECTORY_NOT_EMPTY: { int k; k = dir_is_empty(s->path); good = !(k == -ENOENT || k > 0); break; } case PATH_CHANGED: case PATH_MODIFIED: { bool b; b = access(s->path, F_OK) >= 0; good = !initial && b != s->previous_exists; s->previous_exists = b; break; } default: ; } return good; } static void path_spec_mkdir(PathSpec *s, mode_t mode) { int r; if (s->type == PATH_EXISTS || s->type == PATH_EXISTS_GLOB) return; r = mkdir_p_label(s->path, mode); if (r < 0) log_warning_errno(r, "mkdir(%s) failed: %m", s->path); } static void path_spec_dump(PathSpec *s, FILE *f, const char *prefix) { fprintf(f, "%s%s: %s\n", prefix, path_type_to_string(s->type), s->path); } void path_spec_done(PathSpec *s) { assert(s); assert(s->inotify_fd == -1); free(s->path); } static void path_init(Unit *u) { Path *p = PATH(u); assert(u); assert(u->load_state == UNIT_STUB); p->directory_mode = 0755; } void path_free_specs(Path *p) { PathSpec *s; assert(p); while ((s = p->specs)) { path_spec_unwatch(s); LIST_REMOVE(spec, p->specs, s); path_spec_done(s); free(s); } } static void path_done(Unit *u) { Path *p = PATH(u); assert(p); path_free_specs(p); } static int path_add_mount_links(Path *p) { PathSpec *s; int r; assert(p); LIST_FOREACH(spec, s, p->specs) { r = unit_require_mounts_for(UNIT(p), s->path); if (r < 0) return r; } return 0; } static int path_verify(Path *p) { assert(p); if (UNIT(p)->load_state != UNIT_LOADED) return 0; if (!p->specs) { log_unit_error(UNIT(p), "Path unit lacks path setting. Refusing."); return -EINVAL; } return 0; } static int path_add_default_dependencies(Path *p) { int r; assert(p); if (!UNIT(p)->default_dependencies) return 0; r = unit_add_dependency_by_name(UNIT(p), UNIT_BEFORE, SPECIAL_PATHS_TARGET, NULL, true); if (r < 0) return r; if (UNIT(p)->manager->running_as == MANAGER_SYSTEM) { r = unit_add_two_dependencies_by_name(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true); if (r < 0) return r; } return unit_add_two_dependencies_by_name(UNIT(p), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true); } static int path_load(Unit *u) { Path *p = PATH(u); int r; assert(u); assert(u->load_state == UNIT_STUB); r = unit_load_fragment_and_dropin(u); if (r < 0) return r; if (u->load_state == UNIT_LOADED) { if (set_isempty(u->dependencies[UNIT_TRIGGERS])) { Unit *x; r = unit_load_related_unit(u, ".service", &x); if (r < 0) return r; r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, x, true); if (r < 0) return r; } r = path_add_mount_links(p); if (r < 0) return r; r = path_add_default_dependencies(p); if (r < 0) return r; } return path_verify(p); } static void path_dump(Unit *u, FILE *f, const char *prefix) { Path *p = PATH(u); Unit *trigger; PathSpec *s; assert(p); assert(f); trigger = UNIT_TRIGGER(u); fprintf(f, "%sPath State: %s\n" "%sResult: %s\n" "%sUnit: %s\n" "%sMakeDirectory: %s\n" "%sDirectoryMode: %04o\n", prefix, path_state_to_string(p->state), prefix, path_result_to_string(p->result), prefix, trigger ? trigger->id : "n/a", prefix, yes_no(p->make_directory), prefix, p->directory_mode); LIST_FOREACH(spec, s, p->specs) path_spec_dump(s, f, prefix); } static void path_unwatch(Path *p) { PathSpec *s; assert(p); LIST_FOREACH(spec, s, p->specs) path_spec_unwatch(s); } static int path_watch(Path *p) { int r; PathSpec *s; assert(p); LIST_FOREACH(spec, s, p->specs) { r = path_spec_watch(s, path_dispatch_io); if (r < 0) return r; } return 0; } static void path_set_state(Path *p, PathState state) { PathState old_state; assert(p); old_state = p->state; p->state = state; if (state != PATH_WAITING && (state != PATH_RUNNING || p->inotify_triggered)) path_unwatch(p); if (state != old_state) log_unit_debug(UNIT(p), "Changed %s -> %s", path_state_to_string(old_state), path_state_to_string(state)); unit_notify(UNIT(p), state_translation_table[old_state], state_translation_table[state], true); } static void path_enter_waiting(Path *p, bool initial, bool recheck); static int path_coldplug(Unit *u) { Path *p = PATH(u); assert(p); assert(p->state == PATH_DEAD); if (p->deserialized_state != p->state) { if (p->deserialized_state == PATH_WAITING || p->deserialized_state == PATH_RUNNING) path_enter_waiting(p, true, true); else path_set_state(p, p->deserialized_state); } return 0; } static void path_enter_dead(Path *p, PathResult f) { assert(p); if (f != PATH_SUCCESS) p->result = f; path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD); } static void path_enter_running(Path *p) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; Unit *trigger; int r; assert(p); /* Don't start job if we are supposed to go down */ if (unit_stop_pending(UNIT(p))) return; trigger = UNIT_TRIGGER(UNIT(p)); if (!trigger) { log_unit_error(UNIT(p), "Unit to trigger vanished."); path_enter_dead(p, TIMER_FAILURE_RESOURCES); return; } r = manager_add_job(UNIT(p)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL); if (r < 0) goto fail; p->inotify_triggered = false; r = path_watch(p); if (r < 0) goto fail; path_set_state(p, PATH_RUNNING); return; fail: log_unit_warning(UNIT(p), "Failed to queue unit startup job: %s", bus_error_message(&error, r)); path_enter_dead(p, PATH_FAILURE_RESOURCES); } static bool path_check_good(Path *p, bool initial) { PathSpec *s; bool good = false; assert(p); LIST_FOREACH(spec, s, p->specs) { good = path_spec_check_good(s, initial); if (good) break; } return good; } static void path_enter_waiting(Path *p, bool initial, bool recheck) { int r; if (recheck) if (path_check_good(p, initial)) { log_unit_debug(UNIT(p), "Got triggered."); path_enter_running(p); return; } r = path_watch(p); if (r < 0) goto fail; /* Hmm, so now we have created inotify watches, but the file * might have appeared/been removed by now, so we must * recheck */ if (recheck) if (path_check_good(p, false)) { log_unit_debug(UNIT(p), "Got triggered."); path_enter_running(p); return; } path_set_state(p, PATH_WAITING); return; fail: log_unit_warning_errno(UNIT(p), r, "Failed to enter waiting state: %m"); path_enter_dead(p, PATH_FAILURE_RESOURCES); } static void path_mkdir(Path *p) { PathSpec *s; assert(p); if (!p->make_directory) return; LIST_FOREACH(spec, s, p->specs) path_spec_mkdir(s, p->directory_mode); } static int path_start(Unit *u) { Path *p = PATH(u); Unit *trigger; assert(p); assert(p->state == PATH_DEAD || p->state == PATH_FAILED); trigger = UNIT_TRIGGER(u); if (!trigger || trigger->load_state != UNIT_LOADED) { log_unit_error(u, "Refusing to start, unit to trigger not loaded."); return -ENOENT; } path_mkdir(p); p->result = PATH_SUCCESS; path_enter_waiting(p, true, true); return 1; } static int path_stop(Unit *u) { Path *p = PATH(u); assert(p); assert(p->state == PATH_WAITING || p->state == PATH_RUNNING); path_enter_dead(p, PATH_SUCCESS); return 1; } static int path_serialize(Unit *u, FILE *f, FDSet *fds) { Path *p = PATH(u); assert(u); assert(f); assert(fds); unit_serialize_item(u, f, "state", path_state_to_string(p->state)); unit_serialize_item(u, f, "result", path_result_to_string(p->result)); return 0; } static int path_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Path *p = PATH(u); assert(u); assert(key); assert(value); assert(fds); if (streq(key, "state")) { PathState state; state = path_state_from_string(value); if (state < 0) log_unit_debug(u, "Failed to parse state value: %s", value); else p->deserialized_state = state; } else if (streq(key, "result")) { PathResult f; f = path_result_from_string(value); if (f < 0) log_unit_debug(u, "Failed to parse result value: %s", value); else if (f != PATH_SUCCESS) p->result = f; } else log_unit_debug(u, "Unknown serialization key: %s", key); return 0; } _pure_ static UnitActiveState path_active_state(Unit *u) { assert(u); return state_translation_table[PATH(u)->state]; } _pure_ static const char *path_sub_state_to_string(Unit *u) { assert(u); return path_state_to_string(PATH(u)->state); } static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { PathSpec *s = userdata; Path *p; int changed; assert(s); assert(s->unit); assert(fd >= 0); p = PATH(s->unit); if (p->state != PATH_WAITING && p->state != PATH_RUNNING) return 0; /* log_debug("inotify wakeup on %s.", u->id); */ LIST_FOREACH(spec, s, p->specs) if (path_spec_owns_inotify_fd(s, fd)) break; if (!s) { log_error("Got event on unknown fd."); goto fail; } changed = path_spec_fd_event(s, revents); if (changed < 0) goto fail; /* If we are already running, then remember that one event was * dispatched so that we restart the service only if something * actually changed on disk */ p->inotify_triggered = true; if (changed) path_enter_running(p); else path_enter_waiting(p, false, true); return 0; fail: path_enter_dead(p, PATH_FAILURE_RESOURCES); return 0; } static void path_trigger_notify(Unit *u, Unit *other) { Path *p = PATH(u); assert(u); assert(other); /* Invoked whenever the unit we trigger changes state or gains * or loses a job */ if (other->load_state != UNIT_LOADED) return; if (p->state == PATH_RUNNING && UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) { log_unit_debug(UNIT(p), "Got notified about unit deactivation."); /* Hmm, so inotify was triggered since the * last activation, so I guess we need to * recheck what is going on. */ path_enter_waiting(p, false, p->inotify_triggered); } } static void path_reset_failed(Unit *u) { Path *p = PATH(u); assert(p); if (p->state == PATH_FAILED) path_set_state(p, PATH_DEAD); p->result = PATH_SUCCESS; } static const char* const path_type_table[_PATH_TYPE_MAX] = { [PATH_EXISTS] = "PathExists", [PATH_EXISTS_GLOB] = "PathExistsGlob", [PATH_DIRECTORY_NOT_EMPTY] = "DirectoryNotEmpty", [PATH_CHANGED] = "PathChanged", [PATH_MODIFIED] = "PathModified", }; DEFINE_STRING_TABLE_LOOKUP(path_type, PathType); static const char* const path_result_table[_PATH_RESULT_MAX] = { [PATH_SUCCESS] = "success", [PATH_FAILURE_RESOURCES] = "resources", }; DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult); const UnitVTable path_vtable = { .object_size = sizeof(Path), .sections = "Unit\0" "Path\0" "Install\0", .init = path_init, .done = path_done, .load = path_load, .coldplug = path_coldplug, .dump = path_dump, .start = path_start, .stop = path_stop, .serialize = path_serialize, .deserialize_item = path_deserialize_item, .active_state = path_active_state, .sub_state_to_string = path_sub_state_to_string, .trigger_notify = path_trigger_notify, .reset_failed = path_reset_failed, .bus_vtable = bus_path_vtable }; systemd-229/src/core/path.h000066400000000000000000000043601265713322000157100ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Path Path; typedef struct PathSpec PathSpec; #include "unit.h" typedef enum PathType { PATH_EXISTS, PATH_EXISTS_GLOB, PATH_DIRECTORY_NOT_EMPTY, PATH_CHANGED, PATH_MODIFIED, _PATH_TYPE_MAX, _PATH_TYPE_INVALID = -1 } PathType; typedef struct PathSpec { Unit *unit; char *path; sd_event_source *event_source; LIST_FIELDS(struct PathSpec, spec); PathType type; int inotify_fd; int primary_wd; bool previous_exists; } PathSpec; int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler); void path_spec_unwatch(PathSpec *s); int path_spec_fd_event(PathSpec *s, uint32_t events); void path_spec_done(PathSpec *s); static inline bool path_spec_owns_inotify_fd(PathSpec *s, int fd) { return s->inotify_fd == fd; } typedef enum PathResult { PATH_SUCCESS, PATH_FAILURE_RESOURCES, _PATH_RESULT_MAX, _PATH_RESULT_INVALID = -1 } PathResult; struct Path { Unit meta; LIST_HEAD(PathSpec, specs); PathState state, deserialized_state; bool inotify_triggered; bool make_directory; mode_t directory_mode; PathResult result; }; void path_free_specs(Path *p); extern const UnitVTable path_vtable; const char* path_type_to_string(PathType i) _const_; PathType path_type_from_string(const char *s) _pure_; const char* path_result_to_string(PathResult i) _const_; PathResult path_result_from_string(const char *s) _pure_; systemd-229/src/core/scope.c000066400000000000000000000417021265713322000160610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "dbus-scope.h" #include "load-dropin.h" #include "log.h" #include "scope.h" #include "special.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "unit.h" static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = { [SCOPE_DEAD] = UNIT_INACTIVE, [SCOPE_RUNNING] = UNIT_ACTIVE, [SCOPE_ABANDONED] = UNIT_ACTIVE, [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING, [SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING, [SCOPE_FAILED] = UNIT_FAILED }; static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); static void scope_init(Unit *u) { Scope *s = SCOPE(u); assert(u); assert(u->load_state == UNIT_STUB); s->timeout_stop_usec = u->manager->default_timeout_stop_usec; UNIT(s)->ignore_on_isolate = true; } static void scope_done(Unit *u) { Scope *s = SCOPE(u); assert(u); free(s->controller); s->timer_event_source = sd_event_source_unref(s->timer_event_source); } static int scope_arm_timer(Scope *s, usec_t usec) { int r; assert(s); if (s->timer_event_source) { r = sd_event_source_set_time(s->timer_event_source, usec); if (r < 0) return r; return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); } if (usec == USEC_INFINITY) return 0; r = sd_event_add_time( UNIT(s)->manager->event, &s->timer_event_source, CLOCK_MONOTONIC, usec, 0, scope_dispatch_timer, s); if (r < 0) return r; (void) sd_event_source_set_description(s->timer_event_source, "scope-timer"); return 0; } static void scope_set_state(Scope *s, ScopeState state) { ScopeState old_state; assert(s); old_state = s->state; s->state = state; if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) s->timer_event_source = sd_event_source_unref(s->timer_event_source); if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED)) unit_unwatch_all_pids(UNIT(s)); if (state != old_state) log_debug("%s changed %s -> %s", UNIT(s)->id, scope_state_to_string(old_state), scope_state_to_string(state)); unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true); } static int scope_add_default_dependencies(Scope *s) { int r; assert(s); if (!UNIT(s)->default_dependencies) return 0; /* Make sure scopes are unloaded on shutdown */ r = unit_add_two_dependencies_by_name( UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true); if (r < 0) return r; return 0; } static int scope_verify(Scope *s) { assert(s); if (UNIT(s)->load_state != UNIT_LOADED) return 0; if (set_isempty(UNIT(s)->pids) && !manager_is_reloading_or_reexecuting(UNIT(s)->manager) && !unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE)) { log_unit_error(UNIT(s), "Scope has no PIDs. Refusing."); return -EINVAL; } return 0; } static int scope_load(Unit *u) { Scope *s = SCOPE(u); int r; assert(s); assert(u->load_state == UNIT_STUB); if (!u->transient && !manager_is_reloading_or_reexecuting(u->manager)) return -ENOENT; u->load_state = UNIT_LOADED; r = unit_load_dropin(u); if (r < 0) return r; r = unit_patch_contexts(u); if (r < 0) return r; r = unit_set_default_slice(u); if (r < 0) return r; r = scope_add_default_dependencies(s); if (r < 0) return r; return scope_verify(s); } static int scope_coldplug(Unit *u) { Scope *s = SCOPE(u); int r; assert(s); assert(s->state == SCOPE_DEAD); if (s->deserialized_state == s->state) return 0; if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) { r = scope_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_stop_usec)); if (r < 0) return r; } if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED)) unit_watch_all_pids(UNIT(s)); scope_set_state(s, s->deserialized_state); return 0; } static void scope_dump(Unit *u, FILE *f, const char *prefix) { Scope *s = SCOPE(u); assert(s); assert(f); fprintf(f, "%sScope State: %s\n" "%sResult: %s\n", prefix, scope_state_to_string(s->state), prefix, scope_result_to_string(s->result)); cgroup_context_dump(&s->cgroup_context, f, prefix); kill_context_dump(&s->kill_context, f, prefix); } static void scope_enter_dead(Scope *s, ScopeResult f) { assert(s); if (f != SCOPE_SUCCESS) s->result = f; scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD); } static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) { bool skip_signal = false; int r; assert(s); if (f != SCOPE_SUCCESS) s->result = f; unit_watch_all_pids(UNIT(s)); /* If we have a controller set let's ask the controller nicely * to terminate the scope, instead of us going directly into * SIGTERM beserk mode */ if (state == SCOPE_STOP_SIGTERM) skip_signal = bus_scope_send_request_stop(s) > 0; if (!skip_signal) { r = unit_kill_context( UNIT(s), &s->kill_context, state != SCOPE_STOP_SIGTERM ? KILL_KILL : KILL_TERMINATE, -1, -1, false); if (r < 0) goto fail; } else r = 1; if (r > 0) { r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec)); if (r < 0) goto fail; scope_set_state(s, state); } else if (state == SCOPE_STOP_SIGTERM) scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS); else scope_enter_dead(s, SCOPE_SUCCESS); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m"); scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); } static int scope_start(Unit *u) { Scope *s = SCOPE(u); int r; assert(s); if (unit_has_name(u, SPECIAL_INIT_SCOPE)) return -EPERM; if (s->state == SCOPE_FAILED) return -EPERM; /* We can't fulfill this right now, please try again later */ if (s->state == SCOPE_STOP_SIGTERM || s->state == SCOPE_STOP_SIGKILL) return -EAGAIN; assert(s->state == SCOPE_DEAD); if (!u->transient && !manager_is_reloading_or_reexecuting(u->manager)) return -ENOENT; (void) unit_realize_cgroup(u); (void) unit_reset_cpu_usage(u); r = unit_attach_pids_to_cgroup(u); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to add PIDs to scope's control group: %m"); scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); return r; } s->result = SCOPE_SUCCESS; scope_set_state(s, SCOPE_RUNNING); return 1; } static int scope_stop(Unit *u) { Scope *s = SCOPE(u); assert(s); if (s->state == SCOPE_STOP_SIGTERM || s->state == SCOPE_STOP_SIGKILL) return 0; assert(s->state == SCOPE_RUNNING || s->state == SCOPE_ABANDONED); scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS); return 1; } static void scope_reset_failed(Unit *u) { Scope *s = SCOPE(u); assert(s); if (s->state == SCOPE_FAILED) scope_set_state(s, SCOPE_DEAD); s->result = SCOPE_SUCCESS; } static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { return unit_kill_common(u, who, signo, -1, -1, error); } static int scope_get_timeout(Unit *u, usec_t *timeout) { Scope *s = SCOPE(u); usec_t t; int r; if (!s->timer_event_source) return 0; r = sd_event_source_get_time(s->timer_event_source, &t); if (r < 0) return r; if (t == USEC_INFINITY) return 0; *timeout = t; return 1; } static int scope_serialize(Unit *u, FILE *f, FDSet *fds) { Scope *s = SCOPE(u); assert(s); assert(f); assert(fds); unit_serialize_item(u, f, "state", scope_state_to_string(s->state)); return 0; } static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Scope *s = SCOPE(u); assert(u); assert(key); assert(value); assert(fds); if (streq(key, "state")) { ScopeState state; state = scope_state_from_string(value); if (state < 0) log_unit_debug(u, "Failed to parse state value: %s", value); else s->deserialized_state = state; } else log_unit_debug(u, "Unknown serialization key: %s", key); return 0; } static bool scope_check_gc(Unit *u) { assert(u); /* Never clean up scopes that still have a process around, * even if the scope is formally dead. */ if (!u->cgroup_path) return false; return cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path) <= 0; } static void scope_notify_cgroup_empty_event(Unit *u) { Scope *s = SCOPE(u); assert(u); log_unit_debug(u, "cgroup is empty"); if (IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) scope_enter_dead(s, SCOPE_SUCCESS); } static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) { /* If we get a SIGCHLD event for one of the processes we were interested in, then we look for others to watch, under the assumption that we'll sooner or later get a SIGCHLD for them, as the original process we watched was probably the parent of them, and they are hence now our children. */ unit_tidy_watch_pids(u, 0, 0); unit_watch_all_pids(u); /* If the PID set is empty now, then let's finish this off */ if (set_isempty(u->pids)) scope_notify_cgroup_empty_event(u); } static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { Scope *s = SCOPE(userdata); assert(s); assert(s->timer_event_source == source); switch (s->state) { case SCOPE_STOP_SIGTERM: if (s->kill_context.send_sigkill) { log_unit_warning(UNIT(s), "Stopping timed out. Killing."); scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT); } else { log_unit_warning(UNIT(s), "Stopping timed out. Skipping SIGKILL."); scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT); } break; case SCOPE_STOP_SIGKILL: log_unit_warning(UNIT(s), "Still around after SIGKILL. Ignoring."); scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT); break; default: assert_not_reached("Timeout at wrong time."); } return 0; } int scope_abandon(Scope *s) { assert(s); if (unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE)) return -EPERM; if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED)) return -ESTALE; s->controller = mfree(s->controller); /* The client is no longer watching the remaining processes, * so let's step in here, under the assumption that the * remaining processes will be sooner or later reassigned to * us as parent. */ unit_tidy_watch_pids(UNIT(s), 0, 0); unit_watch_all_pids(UNIT(s)); /* If the PID set is empty now, then let's finish this off */ if (set_isempty(UNIT(s)->pids)) scope_notify_cgroup_empty_event(UNIT(s)); else scope_set_state(s, SCOPE_ABANDONED); return 0; } _pure_ static UnitActiveState scope_active_state(Unit *u) { assert(u); return state_translation_table[SCOPE(u)->state]; } _pure_ static const char *scope_sub_state_to_string(Unit *u) { assert(u); return scope_state_to_string(SCOPE(u)->state); } static void scope_enumerate(Manager *m) { Unit *u; int r; assert(m); /* Let's unconditionally add the "init.scope" special unit * that encapsulates PID 1. Note that PID 1 already is in the * cgroup for this, we hence just need to allocate the object * for it and that's it. */ u = manager_get_unit(m, SPECIAL_INIT_SCOPE); if (!u) { u = unit_new(m, sizeof(Scope)); if (!u) { log_oom(); return; } r = unit_add_name(u, SPECIAL_INIT_SCOPE); if (r < 0) { unit_free(u); log_error_errno(r, "Failed to add init.scope name"); return; } } u->transient = true; u->default_dependencies = false; u->no_gc = true; u->ignore_on_isolate = true; u->refuse_manual_start = true; u->refuse_manual_stop = true; SCOPE(u)->deserialized_state = SCOPE_RUNNING; SCOPE(u)->kill_context.kill_signal = SIGRTMIN+14; /* Prettify things, if we can. */ if (!u->description) u->description = strdup("System and Service Manager"); if (!u->documentation) (void) strv_extend(&u->documentation, "man:systemd(1)"); unit_add_to_load_queue(u); unit_add_to_dbus_queue(u); } static const char* const scope_result_table[_SCOPE_RESULT_MAX] = { [SCOPE_SUCCESS] = "success", [SCOPE_FAILURE_RESOURCES] = "resources", [SCOPE_FAILURE_TIMEOUT] = "timeout", }; DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult); const UnitVTable scope_vtable = { .object_size = sizeof(Scope), .cgroup_context_offset = offsetof(Scope, cgroup_context), .kill_context_offset = offsetof(Scope, kill_context), .sections = "Unit\0" "Scope\0" "Install\0", .private_section = "Scope", .no_alias = true, .no_instances = true, .can_transient = true, .init = scope_init, .load = scope_load, .done = scope_done, .coldplug = scope_coldplug, .dump = scope_dump, .start = scope_start, .stop = scope_stop, .kill = scope_kill, .get_timeout = scope_get_timeout, .serialize = scope_serialize, .deserialize_item = scope_deserialize_item, .active_state = scope_active_state, .sub_state_to_string = scope_sub_state_to_string, .check_gc = scope_check_gc, .sigchld_event = scope_sigchld_event, .reset_failed = scope_reset_failed, .notify_cgroup_empty = scope_notify_cgroup_empty_event, .bus_vtable = bus_scope_vtable, .bus_set_property = bus_scope_set_property, .bus_commit_properties = bus_scope_commit_properties, .enumerate = scope_enumerate, }; systemd-229/src/core/scope.h000066400000000000000000000026571265713322000160740ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Scope Scope; #include "kill.h" typedef enum ScopeResult { SCOPE_SUCCESS, SCOPE_FAILURE_RESOURCES, SCOPE_FAILURE_TIMEOUT, _SCOPE_RESULT_MAX, _SCOPE_RESULT_INVALID = -1 } ScopeResult; struct Scope { Unit meta; CGroupContext cgroup_context; KillContext kill_context; ScopeState state, deserialized_state; ScopeResult result; usec_t timeout_stop_usec; char *controller; sd_event_source *timer_event_source; }; extern const UnitVTable scope_vtable; int scope_abandon(Scope *s); const char* scope_result_to_string(ScopeResult i) _const_; ScopeResult scope_result_from_string(const char *s) _pure_; systemd-229/src/core/selinux-access.c000066400000000000000000000211271265713322000176750ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Dan Walsh systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "selinux-access.h" #ifdef HAVE_SELINUX #include #include #include #include #ifdef HAVE_AUDIT #include #endif #include "sd-bus.h" #include "alloc-util.h" #include "audit-fd.h" #include "bus-util.h" #include "log.h" #include "path-util.h" #include "selinux-util.h" #include "stdio-util.h" #include "strv.h" #include "util.h" static bool initialized = false; struct audit_info { sd_bus_creds *creds; const char *path; const char *cmdline; }; /* Any time an access gets denied this callback will be called with the audit data. We then need to just copy the audit data into the msgbuf. */ static int audit_callback( void *auditdata, security_class_t cls, char *msgbuf, size_t msgbufsize) { const struct audit_info *audit = auditdata; uid_t uid = 0, login_uid = 0; gid_t gid = 0; char login_uid_buf[DECIMAL_STR_MAX(uid_t) + 1] = "n/a"; char uid_buf[DECIMAL_STR_MAX(uid_t) + 1] = "n/a"; char gid_buf[DECIMAL_STR_MAX(gid_t) + 1] = "n/a"; if (sd_bus_creds_get_audit_login_uid(audit->creds, &login_uid) >= 0) xsprintf(login_uid_buf, UID_FMT, login_uid); if (sd_bus_creds_get_euid(audit->creds, &uid) >= 0) xsprintf(uid_buf, UID_FMT, uid); if (sd_bus_creds_get_egid(audit->creds, &gid) >= 0) xsprintf(gid_buf, GID_FMT, gid); snprintf(msgbuf, msgbufsize, "auid=%s uid=%s gid=%s%s%s%s%s%s%s", login_uid_buf, uid_buf, gid_buf, audit->path ? " path=\"" : "", strempty(audit->path), audit->path ? "\"" : "", audit->cmdline ? " cmdline=\"" : "", strempty(audit->cmdline), audit->cmdline ? "\"" : ""); return 0; } static int callback_type_to_priority(int type) { switch(type) { case SELINUX_ERROR: return LOG_ERR; case SELINUX_WARNING: return LOG_WARNING; case SELINUX_INFO: return LOG_INFO; case SELINUX_AVC: default: return LOG_NOTICE; } } /* libselinux uses this callback when access gets denied or other events happen. If audit is turned on, messages will be reported using audit netlink, otherwise they will be logged using the usual channels. Code copied from dbus and modified. */ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) { va_list ap; #ifdef HAVE_AUDIT int fd; fd = get_audit_fd(); if (fd >= 0) { _cleanup_free_ char *buf = NULL; int r; va_start(ap, fmt); r = vasprintf(&buf, fmt, ap); va_end(ap); if (r >= 0) { audit_log_user_avc_message(fd, AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0); return 0; } } #endif va_start(ap, fmt); log_internalv(LOG_AUTH | callback_type_to_priority(type), 0, __FILE__, __LINE__, __FUNCTION__, fmt, ap); va_end(ap); return 0; } static int access_init(sd_bus_error *error) { if (!mac_selinux_use()) return 0; if (initialized) return 1; if (avc_open(NULL, 0) != 0) { int enforce, saved_errno = errno; enforce = security_getenforce(); log_full_errno(enforce != 0 ? LOG_ERR : LOG_WARNING, saved_errno, "Failed to open the SELinux AVC: %m"); /* If enforcement isn't on, then let's suppress this * error, and just don't do any AVC checks. The * warning we printed is hence all the admin will * see. */ if (enforce == 0) return 0; /* Return an access denied error, if we couldn't load * the AVC but enforcing mode was on, or we couldn't * determine whether it is one. */ return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to open the SELinux AVC: %s", strerror(saved_errno)); } selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback); selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback); initialized = true; return 1; } /* This function communicates with the kernel to check whether or not it should allow the access. If the machine is in permissive mode it will return ok. Audit messages will still be generated if the access would be denied in enforcing mode. */ int mac_selinux_generic_access_check( sd_bus_message *message, const char *path, const char *permission, sd_bus_error *error) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *tclass = NULL, *scon = NULL; struct audit_info audit_info = {}; _cleanup_free_ char *cl = NULL; security_context_t fcon = NULL; char **cmdline = NULL; int r = 0; assert(message); assert(permission); assert(error); r = access_init(error); if (r <= 0) return r; r = sd_bus_query_sender_creds( message, SD_BUS_CREDS_PID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID| SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_AUDIT_LOGIN_UID| SD_BUS_CREDS_SELINUX_CONTEXT| SD_BUS_CREDS_AUGMENT /* get more bits from /proc */, &creds); if (r < 0) goto finish; /* The SELinux context is something we really should have * gotten directly from the message or sender, and not be an * augmented field. If it was augmented we cannot use it for * authorization, since this is racy and vulnerable. Let's add * an extra check, just in case, even though this really * shouldn't be possible. */ assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_SELINUX_CONTEXT) == 0, -EPERM); r = sd_bus_creds_get_selinux_context(creds, &scon); if (r < 0) goto finish; if (path) { /* Get the file context of the unit file */ r = getfilecon_raw(path, &fcon); if (r < 0) { r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path); goto finish; } tclass = "service"; } else { r = getcon_raw(&fcon); if (r < 0) { r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context."); goto finish; } tclass = "system"; } sd_bus_creds_get_cmdline(creds, &cmdline); cl = strv_join(cmdline, " "); audit_info.creds = creds; audit_info.path = path; audit_info.cmdline = cl; r = selinux_check_access(scon, fcon, tclass, permission, &audit_info); if (r < 0) r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access."); log_debug("SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %i", scon, fcon, tclass, permission, path, cl, r); finish: freecon(fcon); if (r < 0 && security_getenforce() != 1) { sd_bus_error_free(error); r = 0; } return r; } #else int mac_selinux_generic_access_check( sd_bus_message *message, const char *path, const char *permission, sd_bus_error *error) { return 0; } #endif systemd-229/src/core/selinux-access.h000066400000000000000000000030761265713322000177050ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Dan Walsh systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "bus-util.h" #include "manager.h" int mac_selinux_generic_access_check(sd_bus_message *message, const char *path, const char *permission, sd_bus_error *error); #ifdef HAVE_SELINUX #define mac_selinux_access_check(message, permission, error) \ mac_selinux_generic_access_check((message), NULL, (permission), (error)) #define mac_selinux_unit_access_check(unit, message, permission, error) \ ({ \ Unit *_unit = (unit); \ mac_selinux_generic_access_check((message), _unit->source_path ?: _unit->fragment_path, (permission), (error)); \ }) #else #define mac_selinux_access_check(message, permission, error) 0 #define mac_selinux_unit_access_check(unit, message, permission, error) 0 #endif systemd-229/src/core/selinux-setup.c000066400000000000000000000072711265713322000176000ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #ifdef HAVE_SELINUX #include #endif #include "log.h" #include "macro.h" #include "selinux-setup.h" #include "selinux-util.h" #include "string-util.h" #include "util.h" #ifdef HAVE_SELINUX _printf_(2,3) static int null_log(int type, const char *fmt, ...) { return 0; } #endif int mac_selinux_setup(bool *loaded_policy) { #ifdef HAVE_SELINUX int enforce = 0; usec_t before_load, after_load; security_context_t con; int r; union selinux_callback cb; bool initialized = false; assert(loaded_policy); /* Turn off all of SELinux' own logging, we want to do that */ cb.func_log = null_log; selinux_set_callback(SELINUX_CB_LOG, cb); /* Don't load policy in the initrd if we don't appear to have * it. For the real root, we check below if we've already * loaded policy, and return gracefully. */ if (in_initrd() && access(selinux_path(), F_OK) < 0) return 0; /* Already initialized by somebody else? */ r = getcon_raw(&con); if (r == 0) { initialized = !streq(con, "kernel"); freecon(con); } /* Make sure we have no fds open while loading the policy and * transitioning */ log_close(); /* Now load the policy */ before_load = now(CLOCK_MONOTONIC); r = selinux_init_load_policy(&enforce); if (r == 0) { _cleanup_(mac_selinux_freep) char *label = NULL; char timespan[FORMAT_TIMESPAN_MAX]; mac_selinux_retest(); /* Transition to the new context */ r = mac_selinux_get_create_label_from_exe(SYSTEMD_BINARY_PATH, &label); if (r < 0 || !label) { log_open(); log_error("Failed to compute init label, ignoring."); } else { r = setcon(label); log_open(); if (r < 0) log_error("Failed to transition into init label '%s', ignoring.", label); } after_load = now(CLOCK_MONOTONIC); log_info("Successfully loaded SELinux policy in %s.", format_timespan(timespan, sizeof(timespan), after_load - before_load, 0)); *loaded_policy = true; } else { log_open(); if (enforce > 0) { if (!initialized) { log_emergency("Failed to load SELinux policy."); return -EIO; } log_warning("Failed to load new SELinux policy. Continuing with old policy."); } else log_debug("Unable to load SELinux policy. Ignoring."); } #endif return 0; } systemd-229/src/core/selinux-setup.h000066400000000000000000000014371265713322000176030ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include int mac_selinux_setup(bool *loaded_policy); systemd-229/src/core/service.c000066400000000000000000003504401265713322000164120ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "async.h" #include "bus-error.h" #include "bus-kernel.h" #include "bus-util.h" #include "dbus-service.h" #include "def.h" #include "env-util.h" #include "escape.h" #include "exit-status.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "load-dropin.h" #include "load-fragment.h" #include "log.h" #include "manager.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "service.h" #include "signal-util.h" #include "special.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "unit-printf.h" #include "unit.h" #include "utf8.h" #include "util.h" static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = { [SERVICE_DEAD] = UNIT_INACTIVE, [SERVICE_START_PRE] = UNIT_ACTIVATING, [SERVICE_START] = UNIT_ACTIVATING, [SERVICE_START_POST] = UNIT_ACTIVATING, [SERVICE_RUNNING] = UNIT_ACTIVE, [SERVICE_EXITED] = UNIT_ACTIVE, [SERVICE_RELOAD] = UNIT_RELOADING, [SERVICE_STOP] = UNIT_DEACTIVATING, [SERVICE_STOP_SIGABRT] = UNIT_DEACTIVATING, [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING, [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING, [SERVICE_STOP_POST] = UNIT_DEACTIVATING, [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING, [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING, [SERVICE_FAILED] = UNIT_FAILED, [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING }; /* For Type=idle we never want to delay any other jobs, hence we * consider idle jobs active as soon as we start working on them */ static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] = { [SERVICE_DEAD] = UNIT_INACTIVE, [SERVICE_START_PRE] = UNIT_ACTIVE, [SERVICE_START] = UNIT_ACTIVE, [SERVICE_START_POST] = UNIT_ACTIVE, [SERVICE_RUNNING] = UNIT_ACTIVE, [SERVICE_EXITED] = UNIT_ACTIVE, [SERVICE_RELOAD] = UNIT_RELOADING, [SERVICE_STOP] = UNIT_DEACTIVATING, [SERVICE_STOP_SIGABRT] = UNIT_DEACTIVATING, [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING, [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING, [SERVICE_STOP_POST] = UNIT_DEACTIVATING, [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING, [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING, [SERVICE_FAILED] = UNIT_FAILED, [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING }; static int service_dispatch_io(sd_event_source *source, int fd, uint32_t events, void *userdata); static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata); static void service_enter_signal(Service *s, ServiceState state, ServiceResult f); static void service_enter_reload_by_notify(Service *s); static void service_init(Unit *u) { Service *s = SERVICE(u); assert(u); assert(u->load_state == UNIT_STUB); s->timeout_start_usec = u->manager->default_timeout_start_usec; s->timeout_stop_usec = u->manager->default_timeout_stop_usec; s->restart_usec = u->manager->default_restart_usec; s->runtime_max_usec = USEC_INFINITY; s->type = _SERVICE_TYPE_INVALID; s->socket_fd = -1; s->bus_endpoint_fd = -1; s->stdin_fd = s->stdout_fd = s->stderr_fd = -1; s->guess_main_pid = true; s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; } static void service_unwatch_control_pid(Service *s) { assert(s); if (s->control_pid <= 0) return; unit_unwatch_pid(UNIT(s), s->control_pid); s->control_pid = 0; } static void service_unwatch_main_pid(Service *s) { assert(s); if (s->main_pid <= 0) return; unit_unwatch_pid(UNIT(s), s->main_pid); s->main_pid = 0; } static void service_unwatch_pid_file(Service *s) { if (!s->pid_file_pathspec) return; log_unit_debug(UNIT(s), "Stopping watch for PID file %s", s->pid_file_pathspec->path); path_spec_unwatch(s->pid_file_pathspec); path_spec_done(s->pid_file_pathspec); s->pid_file_pathspec = mfree(s->pid_file_pathspec); } static int service_set_main_pid(Service *s, pid_t pid) { pid_t ppid; assert(s); if (pid <= 1) return -EINVAL; if (pid == getpid()) return -EINVAL; if (s->main_pid == pid && s->main_pid_known) return 0; if (s->main_pid != pid) { service_unwatch_main_pid(s); exec_status_start(&s->main_exec_status, pid); } s->main_pid = pid; s->main_pid_known = true; if (get_process_ppid(pid, &ppid) >= 0 && ppid != getpid()) { log_unit_warning(UNIT(s), "Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.", pid); s->main_pid_alien = true; } else s->main_pid_alien = false; return 0; } static void service_close_socket_fd(Service *s) { assert(s); s->socket_fd = asynchronous_close(s->socket_fd); } static void service_connection_unref(Service *s) { assert(s); if (!UNIT_ISSET(s->accept_socket)) return; socket_connection_unref(SOCKET(UNIT_DEREF(s->accept_socket))); unit_ref_unset(&s->accept_socket); } static void service_stop_watchdog(Service *s) { assert(s); s->watchdog_event_source = sd_event_source_unref(s->watchdog_event_source); s->watchdog_timestamp = DUAL_TIMESTAMP_NULL; } static void service_start_watchdog(Service *s) { int r; assert(s); if (s->watchdog_usec <= 0) return; if (s->watchdog_event_source) { r = sd_event_source_set_time(s->watchdog_event_source, usec_add(s->watchdog_timestamp.monotonic, s->watchdog_usec)); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to reset watchdog timer: %m"); return; } r = sd_event_source_set_enabled(s->watchdog_event_source, SD_EVENT_ONESHOT); } else { r = sd_event_add_time( UNIT(s)->manager->event, &s->watchdog_event_source, CLOCK_MONOTONIC, usec_add(s->watchdog_timestamp.monotonic, s->watchdog_usec), 0, service_dispatch_watchdog, s); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to add watchdog timer: %m"); return; } (void) sd_event_source_set_description(s->watchdog_event_source, "service-watchdog"); /* Let's process everything else which might be a sign * of living before we consider a service died. */ r = sd_event_source_set_priority(s->watchdog_event_source, SD_EVENT_PRIORITY_IDLE); } if (r < 0) log_unit_warning_errno(UNIT(s), r, "Failed to install watchdog timer: %m"); } static void service_reset_watchdog(Service *s) { assert(s); dual_timestamp_get(&s->watchdog_timestamp); service_start_watchdog(s); } static void service_fd_store_unlink(ServiceFDStore *fs) { if (!fs) return; if (fs->service) { assert(fs->service->n_fd_store > 0); LIST_REMOVE(fd_store, fs->service->fd_store, fs); fs->service->n_fd_store--; } if (fs->event_source) { sd_event_source_set_enabled(fs->event_source, SD_EVENT_OFF); sd_event_source_unref(fs->event_source); } free(fs->fdname); safe_close(fs->fd); free(fs); } static void service_release_resources(Unit *u) { Service *s = SERVICE(u); assert(s); if (!s->fd_store && s->stdin_fd < 0 && s->stdout_fd < 0 && s->stderr_fd < 0) return; log_unit_debug(u, "Releasing all resources."); s->stdin_fd = safe_close(s->stdin_fd); s->stdout_fd = safe_close(s->stdout_fd); s->stderr_fd = safe_close(s->stderr_fd); while (s->fd_store) service_fd_store_unlink(s->fd_store); assert(s->n_fd_store == 0); } static void service_done(Unit *u) { Service *s = SERVICE(u); assert(s); s->pid_file = mfree(s->pid_file); s->status_text = mfree(s->status_text); s->exec_runtime = exec_runtime_unref(s->exec_runtime); exec_command_free_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX); s->control_command = NULL; s->main_command = NULL; exit_status_set_free(&s->restart_prevent_status); exit_status_set_free(&s->restart_force_status); exit_status_set_free(&s->success_status); /* This will leak a process, but at least no memory or any of * our resources */ service_unwatch_main_pid(s); service_unwatch_control_pid(s); service_unwatch_pid_file(s); if (s->bus_name) { unit_unwatch_bus_name(u, s->bus_name); s->bus_name = mfree(s->bus_name); } s->bus_name_owner = mfree(s->bus_name_owner); s->bus_endpoint_fd = safe_close(s->bus_endpoint_fd); service_close_socket_fd(s); service_connection_unref(s); unit_ref_unset(&s->accept_socket); service_stop_watchdog(s); s->timer_event_source = sd_event_source_unref(s->timer_event_source); service_release_resources(u); } static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *userdata) { ServiceFDStore *fs = userdata; assert(e); assert(fs); /* If we get either EPOLLHUP or EPOLLERR, it's time to remove this entry from the fd store */ service_fd_store_unlink(fs); return 0; } static int service_add_fd_store(Service *s, int fd, const char *name) { ServiceFDStore *fs; int r; assert(s); assert(fd >= 0); if (s->n_fd_store >= s->n_fd_store_max) return 0; LIST_FOREACH(fd_store, fs, s->fd_store) { r = same_fd(fs->fd, fd); if (r < 0) return r; if (r > 0) { /* Already included */ safe_close(fd); return 1; } } fs = new0(ServiceFDStore, 1); if (!fs) return -ENOMEM; fs->fd = fd; fs->service = s; fs->fdname = strdup(name ?: "stored"); if (!fs->fdname) { free(fs); return -ENOMEM; } r = sd_event_add_io(UNIT(s)->manager->event, &fs->event_source, fd, 0, on_fd_store_io, fs); if (r < 0) { free(fs->fdname); free(fs); return r; } (void) sd_event_source_set_description(fs->event_source, "service-fd-store"); LIST_PREPEND(fd_store, s->fd_store, fs); s->n_fd_store++; return 1; } static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) { int r; assert(s); if (fdset_size(fds) <= 0) return 0; while (s->n_fd_store < s->n_fd_store_max) { _cleanup_close_ int fd = -1; fd = fdset_steal_first(fds); if (fd < 0) break; r = service_add_fd_store(s, fd, name); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Couldn't add fd to fd store: %m"); if (r > 0) { log_unit_debug(UNIT(s), "Added fd to fd store."); fd = -1; } } if (fdset_size(fds) > 0) log_unit_warning(UNIT(s), "Tried to store more fds than FileDescriptorStoreMax=%u allows, closing remaining.", s->n_fd_store_max); return 0; } static int service_arm_timer(Service *s, usec_t usec) { int r; assert(s); if (s->timer_event_source) { r = sd_event_source_set_time(s->timer_event_source, usec); if (r < 0) return r; return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); } if (usec == USEC_INFINITY) return 0; r = sd_event_add_time( UNIT(s)->manager->event, &s->timer_event_source, CLOCK_MONOTONIC, usec, 0, service_dispatch_timer, s); if (r < 0) return r; (void) sd_event_source_set_description(s->timer_event_source, "service-timer"); return 0; } static int service_verify(Service *s) { assert(s); if (UNIT(s)->load_state != UNIT_LOADED) return 0; if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP]) { log_unit_error(UNIT(s), "Service lacks both ExecStart= and ExecStop= setting. Refusing."); return -EINVAL; } if (s->type != SERVICE_ONESHOT && !s->exec_command[SERVICE_EXEC_START]) { log_unit_error(UNIT(s), "Service has no ExecStart= setting, which is only allowed for Type=oneshot services. Refusing."); return -EINVAL; } if (!s->remain_after_exit && !s->exec_command[SERVICE_EXEC_START]) { log_unit_error(UNIT(s), "Service has no ExecStart= setting, which is only allowed for RemainAfterExit=yes services. Refusing."); return -EINVAL; } if (s->type != SERVICE_ONESHOT && s->exec_command[SERVICE_EXEC_START]->command_next) { log_unit_error(UNIT(s), "Service has more than one ExecStart= setting, which is only allowed for Type=oneshot services. Refusing."); return -EINVAL; } if (s->type == SERVICE_ONESHOT && s->restart != SERVICE_RESTART_NO) { log_unit_error(UNIT(s), "Service has Restart= setting other than no, which isn't allowed for Type=oneshot services. Refusing."); return -EINVAL; } if (s->type == SERVICE_ONESHOT && !exit_status_set_is_empty(&s->restart_force_status)) { log_unit_error(UNIT(s), "Service has RestartForceStatus= set, which isn't allowed for Type=oneshot services. Refusing."); return -EINVAL; } if (s->type == SERVICE_DBUS && !s->bus_name) { log_unit_error(UNIT(s), "Service is of type D-Bus but no D-Bus service name has been specified. Refusing."); return -EINVAL; } if (s->bus_name && s->type != SERVICE_DBUS) log_unit_warning(UNIT(s), "Service has a D-Bus service name specified, but is not of type dbus. Ignoring."); if (s->exec_context.pam_name && !(s->kill_context.kill_mode == KILL_CONTROL_GROUP || s->kill_context.kill_mode == KILL_MIXED)) { log_unit_error(UNIT(s), "Service has PAM enabled. Kill mode must be set to 'control-group' or 'mixed'. Refusing."); return -EINVAL; } if (s->usb_function_descriptors && !s->usb_function_strings) log_unit_warning(UNIT(s), "Service has USBFunctionDescriptors= setting, but no USBFunctionStrings=. Ignoring."); if (!s->usb_function_descriptors && s->usb_function_strings) log_unit_warning(UNIT(s), "Service has USBFunctionStrings= setting, but no USBFunctionDescriptors=. Ignoring."); if (s->runtime_max_usec != USEC_INFINITY && s->type == SERVICE_ONESHOT) log_unit_warning(UNIT(s), "MaxRuntimeSec= has no effect in combination with Type=oneshot. Ignoring."); return 0; } static int service_add_default_dependencies(Service *s) { int r; assert(s); if (!UNIT(s)->default_dependencies) return 0; /* Add a number of automatic dependencies useful for the * majority of services. */ if (UNIT(s)->manager->running_as == MANAGER_SYSTEM) { /* First, pull in the really early boot stuff, and * require it, so that we fail if we can't acquire * it. */ r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true); if (r < 0) return r; } else { /* In the --user instance there's no sysinit.target, * in that case require basic.target instead. */ r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_BASIC_TARGET, NULL, true); if (r < 0) return r; } /* Second, if the rest of the base system is in the same * transaction, order us after it, but do not pull it in or * even require it. */ r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_BASIC_TARGET, NULL, true); if (r < 0) return r; /* Third, add us in for normal shutdown. */ return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true); } static void service_fix_output(Service *s) { assert(s); /* If nothing has been explicitly configured, patch default * output in. If input is socket/tty we avoid this however, * since in that case we want output to default to the same * place as we read input from. */ if (s->exec_context.std_error == EXEC_OUTPUT_INHERIT && s->exec_context.std_output == EXEC_OUTPUT_INHERIT && s->exec_context.std_input == EXEC_INPUT_NULL) s->exec_context.std_error = UNIT(s)->manager->default_std_error; if (s->exec_context.std_output == EXEC_OUTPUT_INHERIT && s->exec_context.std_input == EXEC_INPUT_NULL) s->exec_context.std_output = UNIT(s)->manager->default_std_output; } static int service_setup_bus_name(Service *s) { int r; assert(s); if (!s->bus_name) return 0; if (is_kdbus_available()) { const char *n; n = strjoina(s->bus_name, ".busname"); r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, n, NULL, true); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Failed to add dependency to .busname unit: %m"); } else { /* If kdbus is not available, we know the dbus socket is required, hence pull it in, and require it */ r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, NULL, true); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m"); } /* Regardless if kdbus is used or not, we always want to be ordered against dbus.socket if both are in the transaction. */ r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_DBUS_SOCKET, NULL, true); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m"); r = unit_watch_bus_name(UNIT(s), s->bus_name); if (r == -EEXIST) return log_unit_error_errno(UNIT(s), r, "Two services allocated for the same bus name %s, refusing operation.", s->bus_name); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Cannot watch bus name %s: %m", s->bus_name); return 0; } static int service_add_extras(Service *s) { int r; assert(s); if (s->type == _SERVICE_TYPE_INVALID) { /* Figure out a type automatically */ if (s->bus_name) s->type = SERVICE_DBUS; else if (s->exec_command[SERVICE_EXEC_START]) s->type = SERVICE_SIMPLE; else s->type = SERVICE_ONESHOT; } /* Oneshot services have disabled start timeout by default */ if (s->type == SERVICE_ONESHOT && !s->start_timeout_defined) s->timeout_start_usec = USEC_INFINITY; service_fix_output(s); r = unit_patch_contexts(UNIT(s)); if (r < 0) return r; r = unit_add_exec_dependencies(UNIT(s), &s->exec_context); if (r < 0) return r; r = unit_set_default_slice(UNIT(s)); if (r < 0) return r; if (s->type == SERVICE_NOTIFY && s->notify_access == NOTIFY_NONE) s->notify_access = NOTIFY_MAIN; if (s->watchdog_usec > 0 && s->notify_access == NOTIFY_NONE) s->notify_access = NOTIFY_MAIN; r = service_add_default_dependencies(s); if (r < 0) return r; r = service_setup_bus_name(s); if (r < 0) return r; return 0; } static int service_load(Unit *u) { Service *s = SERVICE(u); int r; assert(s); /* Load a .service file */ r = unit_load_fragment(u); if (r < 0) return r; /* Still nothing found? Then let's give up */ if (u->load_state == UNIT_STUB) return -ENOENT; /* This is a new unit? Then let's add in some extras */ if (u->load_state == UNIT_LOADED) { /* We were able to load something, then let's add in * the dropin directories. */ r = unit_load_dropin(u); if (r < 0) return r; /* This is a new unit? Then let's add in some * extras */ r = service_add_extras(s); if (r < 0) return r; } return service_verify(s); } static void service_dump(Unit *u, FILE *f, const char *prefix) { ServiceExecCommand c; Service *s = SERVICE(u); const char *prefix2; assert(s); prefix = strempty(prefix); prefix2 = strjoina(prefix, "\t"); fprintf(f, "%sService State: %s\n" "%sResult: %s\n" "%sReload Result: %s\n" "%sPermissionsStartOnly: %s\n" "%sRootDirectoryStartOnly: %s\n" "%sRemainAfterExit: %s\n" "%sGuessMainPID: %s\n" "%sType: %s\n" "%sRestart: %s\n" "%sNotifyAccess: %s\n" "%sNotifyState: %s\n", prefix, service_state_to_string(s->state), prefix, service_result_to_string(s->result), prefix, service_result_to_string(s->reload_result), prefix, yes_no(s->permissions_start_only), prefix, yes_no(s->root_directory_start_only), prefix, yes_no(s->remain_after_exit), prefix, yes_no(s->guess_main_pid), prefix, service_type_to_string(s->type), prefix, service_restart_to_string(s->restart), prefix, notify_access_to_string(s->notify_access), prefix, notify_state_to_string(s->notify_state)); if (s->control_pid > 0) fprintf(f, "%sControl PID: "PID_FMT"\n", prefix, s->control_pid); if (s->main_pid > 0) fprintf(f, "%sMain PID: "PID_FMT"\n" "%sMain PID Known: %s\n" "%sMain PID Alien: %s\n", prefix, s->main_pid, prefix, yes_no(s->main_pid_known), prefix, yes_no(s->main_pid_alien)); if (s->pid_file) fprintf(f, "%sPIDFile: %s\n", prefix, s->pid_file); if (s->bus_name) fprintf(f, "%sBusName: %s\n" "%sBus Name Good: %s\n", prefix, s->bus_name, prefix, yes_no(s->bus_name_good)); kill_context_dump(&s->kill_context, f, prefix); exec_context_dump(&s->exec_context, f, prefix); for (c = 0; c < _SERVICE_EXEC_COMMAND_MAX; c++) { if (!s->exec_command[c]) continue; fprintf(f, "%s-> %s:\n", prefix, service_exec_command_to_string(c)); exec_command_dump_list(s->exec_command[c], f, prefix2); } if (s->status_text) fprintf(f, "%sStatus Text: %s\n", prefix, s->status_text); if (s->n_fd_store_max > 0) fprintf(f, "%sFile Descriptor Store Max: %u\n" "%sFile Descriptor Store Current: %u\n", prefix, s->n_fd_store_max, prefix, s->n_fd_store); } static int service_load_pid_file(Service *s, bool may_warn) { _cleanup_free_ char *k = NULL; int r; pid_t pid; assert(s); if (!s->pid_file) return -ENOENT; r = read_one_line_file(s->pid_file, &k); if (r < 0) { if (may_warn) log_unit_info_errno(UNIT(s), r, "PID file %s not readable (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); return r; } r = parse_pid(k, &pid); if (r < 0) { if (may_warn) log_unit_info_errno(UNIT(s), r, "Failed to read PID from file %s: %m", s->pid_file); return r; } if (!pid_is_alive(pid)) { if (may_warn) log_unit_info(UNIT(s), "PID "PID_FMT" read from file %s does not exist or is a zombie.", pid, s->pid_file); return -ESRCH; } if (s->main_pid_known) { if (pid == s->main_pid) return 0; log_unit_debug(UNIT(s), "Main PID changing: "PID_FMT" -> "PID_FMT, s->main_pid, pid); service_unwatch_main_pid(s); s->main_pid_known = false; } else log_unit_debug(UNIT(s), "Main PID loaded: "PID_FMT, pid); r = service_set_main_pid(s, pid); if (r < 0) return r; r = unit_watch_pid(UNIT(s), pid); if (r < 0) { /* FIXME: we need to do something here */ log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" for service: %m", pid); return r; } return 0; } static int service_search_main_pid(Service *s) { pid_t pid = 0; int r; assert(s); /* If we know it anyway, don't ever fallback to unreliable * heuristics */ if (s->main_pid_known) return 0; if (!s->guess_main_pid) return 0; assert(s->main_pid <= 0); r = unit_search_main_pid(UNIT(s), &pid); if (r < 0) return r; log_unit_debug(UNIT(s), "Main PID guessed: "PID_FMT, pid); r = service_set_main_pid(s, pid); if (r < 0) return r; r = unit_watch_pid(UNIT(s), pid); if (r < 0) { /* FIXME: we need to do something here */ log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" from: %m", pid); return r; } return 0; } static void service_set_state(Service *s, ServiceState state) { ServiceState old_state; const UnitActiveState *table; assert(s); table = s->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table; old_state = s->state; s->state = state; service_unwatch_pid_file(s); if (!IN_SET(state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, SERVICE_AUTO_RESTART)) s->timer_event_source = sd_event_source_unref(s->timer_event_source); if (!IN_SET(state, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) { service_unwatch_main_pid(s); s->main_command = NULL; } if (!IN_SET(state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) { service_unwatch_control_pid(s); s->control_command = NULL; s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; } if (IN_SET(state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)) unit_unwatch_all_pids(UNIT(s)); if (!IN_SET(state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL) && !(state == SERVICE_DEAD && UNIT(s)->job)) { service_close_socket_fd(s); service_connection_unref(s); } if (!IN_SET(state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) service_stop_watchdog(s); /* For the inactive states unit_notify() will trim the cgroup, * but for exit we have to do that ourselves... */ if (state == SERVICE_EXITED && UNIT(s)->manager->n_reloading <= 0) unit_prune_cgroup(UNIT(s)); /* For remain_after_exit services, let's see if we can "release" the * hold on the console, since unit_notify() only does that in case of * change of state */ if (state == SERVICE_EXITED && s->remain_after_exit && UNIT(s)->manager->n_on_console > 0) { ExecContext *ec; ec = unit_get_exec_context(UNIT(s)); if (ec && exec_context_may_touch_console(ec)) { Manager *m = UNIT(s)->manager; m->n_on_console --; if (m->n_on_console == 0) /* unset no_console_output flag, since the console is free */ m->no_console_output = false; } } if (old_state != state) log_unit_debug(UNIT(s), "Changed %s -> %s", service_state_to_string(old_state), service_state_to_string(state)); unit_notify(UNIT(s), table[old_state], table[state], s->reload_result == SERVICE_SUCCESS); } static usec_t service_coldplug_timeout(Service *s) { assert(s); switch (s->deserialized_state) { case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST: case SERVICE_RELOAD: return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->timeout_start_usec); case SERVICE_RUNNING: return usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec); case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->timeout_stop_usec); case SERVICE_AUTO_RESTART: return usec_add(UNIT(s)->inactive_enter_timestamp.monotonic, s->restart_usec); default: return USEC_INFINITY; } } static int service_coldplug(Unit *u) { Service *s = SERVICE(u); int r; assert(s); assert(s->state == SERVICE_DEAD); if (s->deserialized_state == s->state) return 0; r = service_arm_timer(s, service_coldplug_timeout(s)); if (r < 0) return r; if (s->main_pid > 0 && pid_is_unwaited(s->main_pid) && ((s->deserialized_state == SERVICE_START && IN_SET(s->type, SERVICE_FORKING, SERVICE_DBUS, SERVICE_ONESHOT, SERVICE_NOTIFY)) || IN_SET(s->deserialized_state, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))) { r = unit_watch_pid(UNIT(s), s->main_pid); if (r < 0) return r; } if (s->control_pid > 0 && pid_is_unwaited(s->control_pid) && IN_SET(s->deserialized_state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) { r = unit_watch_pid(UNIT(s), s->control_pid); if (r < 0) return r; } if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)) unit_watch_all_pids(UNIT(s)); if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) service_start_watchdog(s); service_set_state(s, s->deserialized_state); return 0; } static int service_collect_fds(Service *s, int **fds, char ***fd_names) { _cleanup_strv_free_ char **rfd_names = NULL; _cleanup_free_ int *rfds = NULL; int rn_fds = 0, r; assert(s); assert(fds); assert(fd_names); if (s->socket_fd >= 0) { /* Pass the per-connection socket */ rfds = new(int, 1); if (!rfds) return -ENOMEM; rfds[0] = s->socket_fd; rfd_names = strv_new("connection", NULL); if (!rfd_names) return -ENOMEM; rn_fds = 1; } else { Iterator i; Unit *u; /* Pass all our configured sockets for singleton services */ SET_FOREACH(u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY], i) { _cleanup_free_ int *cfds = NULL; Socket *sock; int cn_fds; if (u->type != UNIT_SOCKET) continue; sock = SOCKET(u); cn_fds = socket_collect_fds(sock, &cfds); if (cn_fds < 0) return cn_fds; if (cn_fds <= 0) continue; if (!rfds) { rfds = cfds; rn_fds = cn_fds; cfds = NULL; } else { int *t; t = realloc(rfds, (rn_fds + cn_fds) * sizeof(int)); if (!t) return -ENOMEM; memcpy(t + rn_fds, cfds, cn_fds * sizeof(int)); rfds = t; rn_fds += cn_fds; } r = strv_extend_n(&rfd_names, socket_fdname(sock), cn_fds); if (r < 0) return r; } } if (s->n_fd_store > 0) { ServiceFDStore *fs; char **nl; int *t; t = realloc(rfds, (rn_fds + s->n_fd_store) * sizeof(int)); if (!t) return -ENOMEM; rfds = t; nl = realloc(rfd_names, (rn_fds + s->n_fd_store + 1) * sizeof(char*)); if (!nl) return -ENOMEM; rfd_names = nl; LIST_FOREACH(fd_store, fs, s->fd_store) { rfds[rn_fds] = fs->fd; rfd_names[rn_fds] = strdup(strempty(fs->fdname)); if (!rfd_names[rn_fds]) return -ENOMEM; rn_fds++; } rfd_names[rn_fds] = NULL; } *fds = rfds; *fd_names = rfd_names; rfds = NULL; rfd_names = NULL; return rn_fds; } static int service_spawn( Service *s, ExecCommand *c, usec_t timeout, bool pass_fds, bool apply_permissions, bool apply_chroot, bool apply_tty_stdin, bool is_control, pid_t *_pid) { _cleanup_strv_free_ char **argv = NULL, **final_env = NULL, **our_env = NULL, **fd_names = NULL; _cleanup_free_ char *bus_endpoint_path = NULL; _cleanup_free_ int *fds = NULL; unsigned n_fds = 0, n_env = 0; const char *path; pid_t pid; ExecParameters exec_params = { .apply_permissions = apply_permissions, .apply_chroot = apply_chroot, .apply_tty_stdin = apply_tty_stdin, .bus_endpoint_fd = -1, .stdin_fd = -1, .stdout_fd = -1, .stderr_fd = -1, }; int r; assert(s); assert(c); assert(_pid); (void) unit_realize_cgroup(UNIT(s)); if (s->reset_cpu_usage) { (void) unit_reset_cpu_usage(UNIT(s)); s->reset_cpu_usage = false; } r = unit_setup_exec_runtime(UNIT(s)); if (r < 0) return r; if (pass_fds || s->exec_context.std_input == EXEC_INPUT_SOCKET || s->exec_context.std_output == EXEC_OUTPUT_SOCKET || s->exec_context.std_error == EXEC_OUTPUT_SOCKET) { r = service_collect_fds(s, &fds, &fd_names); if (r < 0) return r; n_fds = r; } r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), timeout)); if (r < 0) return r; r = unit_full_printf_strv(UNIT(s), c->argv, &argv); if (r < 0) return r; our_env = new0(char*, 6); if (!our_env) return -ENOMEM; if (is_control ? s->notify_access == NOTIFY_ALL : s->notify_access != NOTIFY_NONE) if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=%s", UNIT(s)->manager->notify_socket) < 0) return -ENOMEM; if (s->main_pid > 0) if (asprintf(our_env + n_env++, "MAINPID="PID_FMT, s->main_pid) < 0) return -ENOMEM; if (UNIT(s)->manager->running_as != MANAGER_SYSTEM) if (asprintf(our_env + n_env++, "MANAGERPID="PID_FMT, getpid()) < 0) return -ENOMEM; if (s->socket_fd >= 0) { union sockaddr_union sa; socklen_t salen = sizeof(sa); r = getpeername(s->socket_fd, &sa.sa, &salen); if (r < 0) return -errno; if (IN_SET(sa.sa.sa_family, AF_INET, AF_INET6)) { _cleanup_free_ char *addr = NULL; char *t; int port; r = sockaddr_pretty(&sa.sa, salen, true, false, &addr); if (r < 0) return r; t = strappend("REMOTE_ADDR=", addr); if (!t) return -ENOMEM; our_env[n_env++] = t; port = sockaddr_port(&sa.sa); if (port < 0) return port; if (asprintf(&t, "REMOTE_PORT=%u", port) < 0) return -ENOMEM; our_env[n_env++] = t; } } final_env = strv_env_merge(2, UNIT(s)->manager->environment, our_env, NULL); if (!final_env) return -ENOMEM; if (is_control && UNIT(s)->cgroup_path) { path = strjoina(UNIT(s)->cgroup_path, "/control"); (void) cg_create(SYSTEMD_CGROUP_CONTROLLER, path); } else path = UNIT(s)->cgroup_path; if (s->exec_context.bus_endpoint) { r = bus_kernel_create_endpoint(UNIT(s)->manager->running_as == MANAGER_SYSTEM ? "system" : "user", UNIT(s)->id, &bus_endpoint_path); if (r < 0) return r; /* Pass the fd to the exec_params so that the child process can upload the policy. * Keep a reference to the fd in the service, so the endpoint is kept alive as long * as the service is running. */ exec_params.bus_endpoint_fd = s->bus_endpoint_fd = r; } exec_params.argv = argv; exec_params.fds = fds; exec_params.fd_names = fd_names; exec_params.n_fds = n_fds; exec_params.environment = final_env; exec_params.confirm_spawn = UNIT(s)->manager->confirm_spawn; exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported; exec_params.cgroup_path = path; exec_params.cgroup_delegate = s->cgroup_context.delegate; exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager); exec_params.watchdog_usec = s->watchdog_usec; exec_params.bus_endpoint_path = bus_endpoint_path; exec_params.selinux_context_net = s->socket_fd_selinux_context_net; if (s->type == SERVICE_IDLE) exec_params.idle_pipe = UNIT(s)->manager->idle_pipe; exec_params.stdin_fd = s->stdin_fd; exec_params.stdout_fd = s->stdout_fd; exec_params.stderr_fd = s->stderr_fd; r = exec_spawn(UNIT(s), c, &s->exec_context, &exec_params, s->exec_runtime, &pid); if (r < 0) return r; r = unit_watch_pid(UNIT(s), pid); if (r < 0) /* FIXME: we need to do something here */ return r; *_pid = pid; return 0; } static int main_pid_good(Service *s) { assert(s); /* Returns 0 if the pid is dead, 1 if it is good, -1 if we * don't know */ /* If we know the pid file, then let's just check if it is * still valid */ if (s->main_pid_known) { /* If it's an alien child let's check if it is still * alive ... */ if (s->main_pid_alien && s->main_pid > 0) return pid_is_alive(s->main_pid); /* .. otherwise assume we'll get a SIGCHLD for it, * which we really should wait for to collect exit * status and code */ return s->main_pid > 0; } /* We don't know the pid */ return -EAGAIN; } _pure_ static int control_pid_good(Service *s) { assert(s); return s->control_pid > 0; } static int cgroup_good(Service *s) { int r; assert(s); if (!UNIT(s)->cgroup_path) return 0; r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path); if (r < 0) return r; return !r; } static bool service_shall_restart(Service *s) { assert(s); /* Don't restart after manual stops */ if (s->forbid_restart) return false; /* Never restart if this is configured as special exception */ if (exit_status_set_test(&s->restart_prevent_status, s->main_exec_status.code, s->main_exec_status.status)) return false; /* Restart if the exit code/status are configured as restart triggers */ if (exit_status_set_test(&s->restart_force_status, s->main_exec_status.code, s->main_exec_status.status)) return true; switch (s->restart) { case SERVICE_RESTART_NO: return false; case SERVICE_RESTART_ALWAYS: return true; case SERVICE_RESTART_ON_SUCCESS: return s->result == SERVICE_SUCCESS; case SERVICE_RESTART_ON_FAILURE: return s->result != SERVICE_SUCCESS; case SERVICE_RESTART_ON_ABNORMAL: return !IN_SET(s->result, SERVICE_SUCCESS, SERVICE_FAILURE_EXIT_CODE); case SERVICE_RESTART_ON_WATCHDOG: return s->result == SERVICE_FAILURE_WATCHDOG; case SERVICE_RESTART_ON_ABORT: return IN_SET(s->result, SERVICE_FAILURE_SIGNAL, SERVICE_FAILURE_CORE_DUMP); default: assert_not_reached("unknown restart setting"); } } static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) { int r; assert(s); if (f != SERVICE_SUCCESS) s->result = f; service_set_state(s, s->result != SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD); if (s->result != SERVICE_SUCCESS) { log_unit_warning(UNIT(s), "Failed with result '%s'.", service_result_to_string(s->result)); failure_action(UNIT(s)->manager, s->failure_action, UNIT(s)->reboot_arg); } if (allow_restart && service_shall_restart(s)) { r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec)); if (r < 0) goto fail; service_set_state(s, SERVICE_AUTO_RESTART); } /* The next restart might not be a manual stop, hence reset the flag indicating manual stops */ s->forbid_restart = false; /* We want fresh tmpdirs in case service is started again immediately */ exec_runtime_destroy(s->exec_runtime); s->exec_runtime = exec_runtime_unref(s->exec_runtime); /* Also, remove the runtime directory in */ exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager)); /* Try to delete the pid file. At this point it will be * out-of-date, and some software might be confused by it, so * let's remove it. */ if (s->pid_file) (void) unlink(s->pid_file); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run install restart timer: %m"); service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false); } static void service_enter_stop_post(Service *s, ServiceResult f) { int r; assert(s); if (f != SERVICE_SUCCESS) s->result = f; service_unwatch_control_pid(s); unit_watch_all_pids(UNIT(s)); s->control_command = s->exec_command[SERVICE_EXEC_STOP_POST]; if (s->control_command) { s->control_command_id = SERVICE_EXEC_STOP_POST; r = service_spawn(s, s->control_command, s->timeout_stop_usec, false, !s->permissions_start_only, !s->root_directory_start_only, true, true, &s->control_pid); if (r < 0) goto fail; service_set_state(s, SERVICE_STOP_POST); } else service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_SUCCESS); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop-post' task: %m"); service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES); } static int state_to_kill_operation(ServiceState state) { switch (state) { case SERVICE_STOP_SIGABRT: return KILL_ABORT; case SERVICE_STOP_SIGTERM: case SERVICE_FINAL_SIGTERM: return KILL_TERMINATE; case SERVICE_STOP_SIGKILL: case SERVICE_FINAL_SIGKILL: return KILL_KILL; default: return _KILL_OPERATION_INVALID; } } static void service_enter_signal(Service *s, ServiceState state, ServiceResult f) { int r; assert(s); if (f != SERVICE_SUCCESS) s->result = f; unit_watch_all_pids(UNIT(s)); r = unit_kill_context( UNIT(s), &s->kill_context, state_to_kill_operation(state), s->main_pid, s->control_pid, s->main_pid_alien); if (r < 0) goto fail; if (r > 0) { r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec)); if (r < 0) goto fail; service_set_state(s, state); } else if (IN_SET(state, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM) && s->kill_context.send_sigkill) service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_SUCCESS); else if (IN_SET(state, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL)) service_enter_stop_post(s, SERVICE_SUCCESS); else if (state == SERVICE_FINAL_SIGTERM && s->kill_context.send_sigkill) service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_SUCCESS); else service_enter_dead(s, SERVICE_SUCCESS, true); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m"); if (IN_SET(state, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL)) service_enter_stop_post(s, SERVICE_FAILURE_RESOURCES); else service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true); } static void service_enter_stop_by_notify(Service *s) { assert(s); unit_watch_all_pids(UNIT(s)); service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec)); /* The service told us it's stopping, so it's as if we SIGTERM'd it. */ service_set_state(s, SERVICE_STOP_SIGTERM); } static void service_enter_stop(Service *s, ServiceResult f) { int r; assert(s); if (f != SERVICE_SUCCESS) s->result = f; service_unwatch_control_pid(s); unit_watch_all_pids(UNIT(s)); s->control_command = s->exec_command[SERVICE_EXEC_STOP]; if (s->control_command) { s->control_command_id = SERVICE_EXEC_STOP; r = service_spawn(s, s->control_command, s->timeout_stop_usec, false, !s->permissions_start_only, !s->root_directory_start_only, false, true, &s->control_pid); if (r < 0) goto fail; service_set_state(s, SERVICE_STOP); } else service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_SUCCESS); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop' task: %m"); service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES); } static bool service_good(Service *s) { int main_pid_ok; assert(s); if (s->type == SERVICE_DBUS && !s->bus_name_good) return false; main_pid_ok = main_pid_good(s); if (main_pid_ok > 0) /* It's alive */ return true; if (main_pid_ok == 0) /* It's dead */ return false; /* OK, we don't know anything about the main PID, maybe * because there is none. Let's check the control group * instead. */ return cgroup_good(s) != 0; } static void service_enter_running(Service *s, ServiceResult f) { assert(s); if (f != SERVICE_SUCCESS) s->result = f; service_unwatch_control_pid(s); if (service_good(s)) { /* If there are any queued up sd_notify() * notifications, process them now */ if (s->notify_state == NOTIFY_RELOADING) service_enter_reload_by_notify(s); else if (s->notify_state == NOTIFY_STOPPING) service_enter_stop_by_notify(s); else { service_set_state(s, SERVICE_RUNNING); service_arm_timer(s, usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec)); } } else if (s->remain_after_exit) service_set_state(s, SERVICE_EXITED); else service_enter_stop(s, SERVICE_SUCCESS); } static void service_enter_start_post(Service *s) { int r; assert(s); service_unwatch_control_pid(s); service_reset_watchdog(s); s->control_command = s->exec_command[SERVICE_EXEC_START_POST]; if (s->control_command) { s->control_command_id = SERVICE_EXEC_START_POST; r = service_spawn(s, s->control_command, s->timeout_start_usec, false, !s->permissions_start_only, !s->root_directory_start_only, false, true, &s->control_pid); if (r < 0) goto fail; service_set_state(s, SERVICE_START_POST); } else service_enter_running(s, SERVICE_SUCCESS); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-post' task: %m"); service_enter_stop(s, SERVICE_FAILURE_RESOURCES); } static void service_kill_control_processes(Service *s) { char *p; if (!UNIT(s)->cgroup_path) return; p = strjoina(UNIT(s)->cgroup_path, "/control"); cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, p, SIGKILL, true, true, true, NULL); } static void service_enter_start(Service *s) { ExecCommand *c; usec_t timeout; pid_t pid; int r; assert(s); service_unwatch_control_pid(s); service_unwatch_main_pid(s); /* We want to ensure that nobody leaks processes from * START_PRE here, so let's go on a killing spree, People * should not spawn long running processes from START_PRE. */ service_kill_control_processes(s); if (s->type == SERVICE_FORKING) { s->control_command_id = SERVICE_EXEC_START; c = s->control_command = s->exec_command[SERVICE_EXEC_START]; s->main_command = NULL; } else { s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; s->control_command = NULL; c = s->main_command = s->exec_command[SERVICE_EXEC_START]; } if (!c) { assert(s->type == SERVICE_ONESHOT); service_enter_start_post(s); return; } if (IN_SET(s->type, SERVICE_SIMPLE, SERVICE_IDLE)) /* For simple + idle this is the main process. We don't apply any timeout here, but * service_enter_running() will later apply the .runtime_max_usec timeout. */ timeout = USEC_INFINITY; else timeout = s->timeout_start_usec; r = service_spawn(s, c, timeout, true, true, true, true, false, &pid); if (r < 0) goto fail; if (IN_SET(s->type, SERVICE_SIMPLE, SERVICE_IDLE)) { /* For simple services we immediately start * the START_POST binaries. */ service_set_main_pid(s, pid); service_enter_start_post(s); } else if (s->type == SERVICE_FORKING) { /* For forking services we wait until the start * process exited. */ s->control_pid = pid; service_set_state(s, SERVICE_START); } else if (IN_SET(s->type, SERVICE_ONESHOT, SERVICE_DBUS, SERVICE_NOTIFY)) { /* For oneshot services we wait until the start * process exited, too, but it is our main process. */ /* For D-Bus services we know the main pid right away, * but wait for the bus name to appear on the * bus. Notify services are similar. */ service_set_main_pid(s, pid); service_set_state(s, SERVICE_START); } else assert_not_reached("Unknown service type"); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run 'start' task: %m"); service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES); } static void service_enter_start_pre(Service *s) { int r; assert(s); service_unwatch_control_pid(s); s->control_command = s->exec_command[SERVICE_EXEC_START_PRE]; if (s->control_command) { /* Before we start anything, let's clear up what might * be left from previous runs. */ service_kill_control_processes(s); s->control_command_id = SERVICE_EXEC_START_PRE; r = service_spawn(s, s->control_command, s->timeout_start_usec, false, !s->permissions_start_only, !s->root_directory_start_only, true, true, &s->control_pid); if (r < 0) goto fail; service_set_state(s, SERVICE_START_PRE); } else service_enter_start(s); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-pre' task: %m"); service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true); } static void service_enter_restart(Service *s) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(s); if (UNIT(s)->job && UNIT(s)->job->type == JOB_STOP) { /* Don't restart things if we are going down anyway */ log_unit_info(UNIT(s), "Stop job pending for unit, delaying automatic restart."); r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec)); if (r < 0) goto fail; return; } /* Any units that are bound to this service must also be * restarted. We use JOB_RESTART (instead of the more obvious * JOB_START) here so that those dependency jobs will be added * as well. */ r = manager_add_job(UNIT(s)->manager, JOB_RESTART, UNIT(s), JOB_FAIL, &error, NULL); if (r < 0) goto fail; /* Note that we stay in the SERVICE_AUTO_RESTART state here, * it will be canceled as part of the service_stop() call that * is executed as part of JOB_RESTART. */ log_unit_debug(UNIT(s), "Scheduled restart job."); return; fail: log_unit_warning(UNIT(s), "Failed to schedule restart job: %s", bus_error_message(&error, -r)); service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false); } static void service_enter_reload_by_notify(Service *s) { assert(s); service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_start_usec)); service_set_state(s, SERVICE_RELOAD); } static void service_enter_reload(Service *s) { int r; assert(s); service_unwatch_control_pid(s); s->reload_result = SERVICE_SUCCESS; s->control_command = s->exec_command[SERVICE_EXEC_RELOAD]; if (s->control_command) { s->control_command_id = SERVICE_EXEC_RELOAD; r = service_spawn(s, s->control_command, s->timeout_start_usec, false, !s->permissions_start_only, !s->root_directory_start_only, false, true, &s->control_pid); if (r < 0) goto fail; service_set_state(s, SERVICE_RELOAD); } else service_enter_running(s, SERVICE_SUCCESS); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run 'reload' task: %m"); s->reload_result = SERVICE_FAILURE_RESOURCES; service_enter_running(s, SERVICE_SUCCESS); } static void service_run_next_control(Service *s) { usec_t timeout; int r; assert(s); assert(s->control_command); assert(s->control_command->command_next); assert(s->control_command_id != SERVICE_EXEC_START); s->control_command = s->control_command->command_next; service_unwatch_control_pid(s); if (IN_SET(s->state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) timeout = s->timeout_start_usec; else timeout = s->timeout_stop_usec; r = service_spawn(s, s->control_command, timeout, false, !s->permissions_start_only, !s->root_directory_start_only, s->control_command_id == SERVICE_EXEC_START_PRE || s->control_command_id == SERVICE_EXEC_STOP_POST, true, &s->control_pid); if (r < 0) goto fail; return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run next control task: %m"); if (s->state == SERVICE_START_PRE) service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES); else if (s->state == SERVICE_STOP) service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES); else if (s->state == SERVICE_STOP_POST) service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true); else if (s->state == SERVICE_RELOAD) { s->reload_result = SERVICE_FAILURE_RESOURCES; service_enter_running(s, SERVICE_SUCCESS); } else service_enter_stop(s, SERVICE_FAILURE_RESOURCES); } static void service_run_next_main(Service *s) { pid_t pid; int r; assert(s); assert(s->main_command); assert(s->main_command->command_next); assert(s->type == SERVICE_ONESHOT); s->main_command = s->main_command->command_next; service_unwatch_main_pid(s); r = service_spawn(s, s->main_command, s->timeout_start_usec, true, true, true, true, false, &pid); if (r < 0) goto fail; service_set_main_pid(s, pid); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run next main task: %m"); service_enter_stop(s, SERVICE_FAILURE_RESOURCES); } static int service_start(Unit *u) { Service *s = SERVICE(u); assert(s); /* We cannot fulfill this request right now, try again later * please! */ if (IN_SET(s->state, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) return -EAGAIN; /* Already on it! */ if (IN_SET(s->state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST)) return 0; /* A service that will be restarted must be stopped first to * trigger BindsTo and/or OnFailure dependencies. If a user * does not want to wait for the holdoff time to elapse, the * service should be manually restarted, not started. We * simply return EAGAIN here, so that any start jobs stay * queued, and assume that the auto restart timer will * eventually trigger the restart. */ if (s->state == SERVICE_AUTO_RESTART) return -EAGAIN; assert(IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED)); s->result = SERVICE_SUCCESS; s->reload_result = SERVICE_SUCCESS; s->main_pid_known = false; s->main_pid_alien = false; s->forbid_restart = false; s->reset_cpu_usage = true; s->status_text = mfree(s->status_text); s->status_errno = 0; s->notify_state = NOTIFY_UNKNOWN; service_enter_start_pre(s); return 1; } static int service_stop(Unit *u) { Service *s = SERVICE(u); assert(s); /* Don't create restart jobs from manual stops. */ s->forbid_restart = true; /* Already on it */ if (IN_SET(s->state, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) return 0; /* A restart will be scheduled or is in progress. */ if (s->state == SERVICE_AUTO_RESTART) { service_set_state(s, SERVICE_DEAD); return 0; } /* If there's already something running we go directly into * kill mode. */ if (IN_SET(s->state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD)) { service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_SUCCESS); return 0; } assert(IN_SET(s->state, SERVICE_RUNNING, SERVICE_EXITED)); service_enter_stop(s, SERVICE_SUCCESS); return 1; } static int service_reload(Unit *u) { Service *s = SERVICE(u); assert(s); assert(s->state == SERVICE_RUNNING || s->state == SERVICE_EXITED); service_enter_reload(s); return 1; } _pure_ static bool service_can_reload(Unit *u) { Service *s = SERVICE(u); assert(s); return !!s->exec_command[SERVICE_EXEC_RELOAD]; } static int service_serialize(Unit *u, FILE *f, FDSet *fds) { Service *s = SERVICE(u); ServiceFDStore *fs; int r; assert(u); assert(f); assert(fds); unit_serialize_item(u, f, "state", service_state_to_string(s->state)); unit_serialize_item(u, f, "result", service_result_to_string(s->result)); unit_serialize_item(u, f, "reload-result", service_result_to_string(s->reload_result)); if (s->control_pid > 0) unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid); if (s->main_pid_known && s->main_pid > 0) unit_serialize_item_format(u, f, "main-pid", PID_FMT, s->main_pid); unit_serialize_item(u, f, "main-pid-known", yes_no(s->main_pid_known)); unit_serialize_item(u, f, "bus-name-good", yes_no(s->bus_name_good)); unit_serialize_item(u, f, "bus-name-owner", s->bus_name_owner); r = unit_serialize_item_escaped(u, f, "status-text", s->status_text); if (r < 0) return r; /* FIXME: There's a minor uncleanliness here: if there are * multiple commands attached here, we will start from the * first one again */ if (s->control_command_id >= 0) unit_serialize_item(u, f, "control-command", service_exec_command_to_string(s->control_command_id)); r = unit_serialize_item_fd(u, f, fds, "stdin-fd", s->stdin_fd); if (r < 0) return r; r = unit_serialize_item_fd(u, f, fds, "stdout-fd", s->stdout_fd); if (r < 0) return r; r = unit_serialize_item_fd(u, f, fds, "stderr-fd", s->stderr_fd); if (r < 0) return r; r = unit_serialize_item_fd(u, f, fds, "socket-fd", s->socket_fd); if (r < 0) return r; r = unit_serialize_item_fd(u, f, fds, "endpoint-fd", s->bus_endpoint_fd); if (r < 0) return r; LIST_FOREACH(fd_store, fs, s->fd_store) { _cleanup_free_ char *c = NULL; int copy; copy = fdset_put_dup(fds, fs->fd); if (copy < 0) return copy; c = cescape(fs->fdname); unit_serialize_item_format(u, f, "fd-store-fd", "%i %s", copy, strempty(c)); } if (s->main_exec_status.pid > 0) { unit_serialize_item_format(u, f, "main-exec-status-pid", PID_FMT, s->main_exec_status.pid); dual_timestamp_serialize(f, "main-exec-status-start", &s->main_exec_status.start_timestamp); dual_timestamp_serialize(f, "main-exec-status-exit", &s->main_exec_status.exit_timestamp); if (dual_timestamp_is_set(&s->main_exec_status.exit_timestamp)) { unit_serialize_item_format(u, f, "main-exec-status-code", "%i", s->main_exec_status.code); unit_serialize_item_format(u, f, "main-exec-status-status", "%i", s->main_exec_status.status); } } if (dual_timestamp_is_set(&s->watchdog_timestamp)) dual_timestamp_serialize(f, "watchdog-timestamp", &s->watchdog_timestamp); unit_serialize_item(u, f, "forbid-restart", yes_no(s->forbid_restart)); return 0; } static int service_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Service *s = SERVICE(u); int r; assert(u); assert(key); assert(value); assert(fds); if (streq(key, "state")) { ServiceState state; state = service_state_from_string(value); if (state < 0) log_unit_debug(u, "Failed to parse state value: %s", value); else s->deserialized_state = state; } else if (streq(key, "result")) { ServiceResult f; f = service_result_from_string(value); if (f < 0) log_unit_debug(u, "Failed to parse result value: %s", value); else if (f != SERVICE_SUCCESS) s->result = f; } else if (streq(key, "reload-result")) { ServiceResult f; f = service_result_from_string(value); if (f < 0) log_unit_debug(u, "Failed to parse reload result value: %s", value); else if (f != SERVICE_SUCCESS) s->reload_result = f; } else if (streq(key, "control-pid")) { pid_t pid; if (parse_pid(value, &pid) < 0) log_unit_debug(u, "Failed to parse control-pid value: %s", value); else s->control_pid = pid; } else if (streq(key, "main-pid")) { pid_t pid; if (parse_pid(value, &pid) < 0) log_unit_debug(u, "Failed to parse main-pid value: %s", value); else { service_set_main_pid(s, pid); unit_watch_pid(UNIT(s), pid); } } else if (streq(key, "main-pid-known")) { int b; b = parse_boolean(value); if (b < 0) log_unit_debug(u, "Failed to parse main-pid-known value: %s", value); else s->main_pid_known = b; } else if (streq(key, "bus-name-good")) { int b; b = parse_boolean(value); if (b < 0) log_unit_debug(u, "Failed to parse bus-name-good value: %s", value); else s->bus_name_good = b; } else if (streq(key, "bus-name-owner")) { r = free_and_strdup(&s->bus_name_owner, value); if (r < 0) log_unit_error_errno(u, r, "Unable to deserialize current bus owner %s: %m", value); } else if (streq(key, "status-text")) { char *t; r = cunescape(value, 0, &t); if (r < 0) log_unit_debug_errno(u, r, "Failed to unescape status text: %s", value); else { free(s->status_text); s->status_text = t; } } else if (streq(key, "control-command")) { ServiceExecCommand id; id = service_exec_command_from_string(value); if (id < 0) log_unit_debug(u, "Failed to parse exec-command value: %s", value); else { s->control_command_id = id; s->control_command = s->exec_command[id]; } } else if (streq(key, "socket-fd")) { int fd; if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse socket-fd value: %s", value); else { asynchronous_close(s->socket_fd); s->socket_fd = fdset_remove(fds, fd); } } else if (streq(key, "endpoint-fd")) { int fd; if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse endpoint-fd value: %s", value); else { safe_close(s->bus_endpoint_fd); s->bus_endpoint_fd = fdset_remove(fds, fd); } } else if (streq(key, "fd-store-fd")) { const char *fdv; size_t pf; int fd; pf = strcspn(value, WHITESPACE); fdv = strndupa(value, pf); if (safe_atoi(fdv, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse fd-store-fd value: %s", value); else { _cleanup_free_ char *t = NULL; const char *fdn; fdn = value + pf; fdn += strspn(fdn, WHITESPACE); (void) cunescape(fdn, 0, &t); r = service_add_fd_store(s, fd, t); if (r < 0) log_unit_error_errno(u, r, "Failed to add fd to store: %m"); else if (r > 0) fdset_remove(fds, fd); } } else if (streq(key, "main-exec-status-pid")) { pid_t pid; if (parse_pid(value, &pid) < 0) log_unit_debug(u, "Failed to parse main-exec-status-pid value: %s", value); else s->main_exec_status.pid = pid; } else if (streq(key, "main-exec-status-code")) { int i; if (safe_atoi(value, &i) < 0) log_unit_debug(u, "Failed to parse main-exec-status-code value: %s", value); else s->main_exec_status.code = i; } else if (streq(key, "main-exec-status-status")) { int i; if (safe_atoi(value, &i) < 0) log_unit_debug(u, "Failed to parse main-exec-status-status value: %s", value); else s->main_exec_status.status = i; } else if (streq(key, "main-exec-status-start")) dual_timestamp_deserialize(value, &s->main_exec_status.start_timestamp); else if (streq(key, "main-exec-status-exit")) dual_timestamp_deserialize(value, &s->main_exec_status.exit_timestamp); else if (streq(key, "watchdog-timestamp")) dual_timestamp_deserialize(value, &s->watchdog_timestamp); else if (streq(key, "forbid-restart")) { int b; b = parse_boolean(value); if (b < 0) log_unit_debug(u, "Failed to parse forbid-restart value: %s", value); else s->forbid_restart = b; } else if (streq(key, "stdin-fd")) { int fd; if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse stdin-fd value: %s", value); else { asynchronous_close(s->stdin_fd); s->stdin_fd = fdset_remove(fds, fd); s->exec_context.stdio_as_fds = true; } } else if (streq(key, "stdout-fd")) { int fd; if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse stdout-fd value: %s", value); else { asynchronous_close(s->stdout_fd); s->stdout_fd = fdset_remove(fds, fd); s->exec_context.stdio_as_fds = true; } } else if (streq(key, "stderr-fd")) { int fd; if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse stderr-fd value: %s", value); else { asynchronous_close(s->stderr_fd); s->stderr_fd = fdset_remove(fds, fd); s->exec_context.stdio_as_fds = true; } } else log_unit_debug(u, "Unknown serialization key: %s", key); return 0; } _pure_ static UnitActiveState service_active_state(Unit *u) { const UnitActiveState *table; assert(u); table = SERVICE(u)->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table; return table[SERVICE(u)->state]; } static const char *service_sub_state_to_string(Unit *u) { assert(u); return service_state_to_string(SERVICE(u)->state); } static bool service_check_gc(Unit *u) { Service *s = SERVICE(u); assert(s); /* Never clean up services that still have a process around, * even if the service is formally dead. */ if (cgroup_good(s) > 0 || main_pid_good(s) > 0 || control_pid_good(s) > 0) return true; return false; } static int service_retry_pid_file(Service *s) { int r; assert(s->pid_file); assert(s->state == SERVICE_START || s->state == SERVICE_START_POST); r = service_load_pid_file(s, false); if (r < 0) return r; service_unwatch_pid_file(s); service_enter_running(s, SERVICE_SUCCESS); return 0; } static int service_watch_pid_file(Service *s) { int r; log_unit_debug(UNIT(s), "Setting watch for PID file %s", s->pid_file_pathspec->path); r = path_spec_watch(s->pid_file_pathspec, service_dispatch_io); if (r < 0) goto fail; /* the pidfile might have appeared just before we set the watch */ log_unit_debug(UNIT(s), "Trying to read PID file %s in case it changed", s->pid_file_pathspec->path); service_retry_pid_file(s); return 0; fail: log_unit_error_errno(UNIT(s), r, "Failed to set a watch for PID file %s: %m", s->pid_file_pathspec->path); service_unwatch_pid_file(s); return r; } static int service_demand_pid_file(Service *s) { PathSpec *ps; assert(s->pid_file); assert(!s->pid_file_pathspec); ps = new0(PathSpec, 1); if (!ps) return -ENOMEM; ps->unit = UNIT(s); ps->path = strdup(s->pid_file); if (!ps->path) { free(ps); return -ENOMEM; } path_kill_slashes(ps->path); /* PATH_CHANGED would not be enough. There are daemons (sendmail) that * keep their PID file open all the time. */ ps->type = PATH_MODIFIED; ps->inotify_fd = -1; s->pid_file_pathspec = ps; return service_watch_pid_file(s); } static int service_dispatch_io(sd_event_source *source, int fd, uint32_t events, void *userdata) { PathSpec *p = userdata; Service *s; assert(p); s = SERVICE(p->unit); assert(s); assert(fd >= 0); assert(s->state == SERVICE_START || s->state == SERVICE_START_POST); assert(s->pid_file_pathspec); assert(path_spec_owns_inotify_fd(s->pid_file_pathspec, fd)); log_unit_debug(UNIT(s), "inotify event"); if (path_spec_fd_event(p, events) < 0) goto fail; if (service_retry_pid_file(s) == 0) return 0; if (service_watch_pid_file(s) < 0) goto fail; return 0; fail: service_unwatch_pid_file(s); service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES); return 0; } static void service_notify_cgroup_empty_event(Unit *u) { Service *s = SERVICE(u); assert(u); log_unit_debug(u, "cgroup is empty"); switch (s->state) { /* Waiting for SIGCHLD is usually more interesting, * because it includes return codes/signals. Which is * why we ignore the cgroup events for most cases, * except when we don't know pid which to expect the * SIGCHLD for. */ case SERVICE_START: case SERVICE_START_POST: /* If we were hoping for the daemon to write its PID file, * we can give up now. */ if (s->pid_file_pathspec) { log_unit_warning(u, "Daemon never wrote its PID file. Failing."); service_unwatch_pid_file(s); if (s->state == SERVICE_START) service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES); else service_enter_stop(s, SERVICE_FAILURE_RESOURCES); } break; case SERVICE_RUNNING: /* service_enter_running() will figure out what to do */ service_enter_running(s, SERVICE_SUCCESS); break; case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: if (main_pid_good(s) <= 0 && !control_pid_good(s)) service_enter_stop_post(s, SERVICE_SUCCESS); break; case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: if (main_pid_good(s) <= 0 && !control_pid_good(s)) service_enter_dead(s, SERVICE_SUCCESS, true); break; default: ; } } static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { Service *s = SERVICE(u); ServiceResult f; assert(s); assert(pid >= 0); if (UNIT(s)->fragment_path ? is_clean_exit(code, status, &s->success_status) : is_clean_exit_lsb(code, status, &s->success_status)) f = SERVICE_SUCCESS; else if (code == CLD_EXITED) f = SERVICE_FAILURE_EXIT_CODE; else if (code == CLD_KILLED) f = SERVICE_FAILURE_SIGNAL; else if (code == CLD_DUMPED) f = SERVICE_FAILURE_CORE_DUMP; else assert_not_reached("Unknown code"); if (s->main_pid == pid) { /* Forking services may occasionally move to a new PID. * As long as they update the PID file before exiting the old * PID, they're fine. */ if (service_load_pid_file(s, false) == 0) return; s->main_pid = 0; exec_status_exit(&s->main_exec_status, &s->exec_context, pid, code, status); if (s->main_command) { /* If this is not a forking service than the * main process got started and hence we copy * the exit status so that it is recorded both * as main and as control process exit * status */ s->main_command->exec_status = s->main_exec_status; if (s->main_command->ignore) f = SERVICE_SUCCESS; } else if (s->exec_command[SERVICE_EXEC_START]) { /* If this is a forked process, then we should * ignore the return value if this was * configured for the starter process */ if (s->exec_command[SERVICE_EXEC_START]->ignore) f = SERVICE_SUCCESS; } log_struct(f == SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE, LOG_UNIT_ID(u), LOG_UNIT_MESSAGE(u, "Main process exited, code=%s, status=%i/%s", sigchld_code_to_string(code), status, strna(code == CLD_EXITED ? exit_status_to_string(status, EXIT_STATUS_FULL) : signal_to_string(status))), "EXIT_CODE=%s", sigchld_code_to_string(code), "EXIT_STATUS=%i", status, NULL); if (f != SERVICE_SUCCESS) s->result = f; if (s->main_command && s->main_command->command_next && f == SERVICE_SUCCESS) { /* There is another command to * * execute, so let's do that. */ log_unit_debug(u, "Running next main command for state %s.", service_state_to_string(s->state)); service_run_next_main(s); } else { /* The service exited, so the service is officially * gone. */ s->main_command = NULL; switch (s->state) { case SERVICE_START_POST: case SERVICE_RELOAD: case SERVICE_STOP: /* Need to wait until the operation is * done */ break; case SERVICE_START: if (s->type == SERVICE_ONESHOT) { /* This was our main goal, so let's go on */ if (f == SERVICE_SUCCESS) service_enter_start_post(s); else service_enter_signal(s, SERVICE_FINAL_SIGTERM, f); break; } /* Fall through */ case SERVICE_RUNNING: service_enter_running(s, f); break; case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: if (!control_pid_good(s)) service_enter_stop_post(s, f); /* If there is still a control process, wait for that first */ break; case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: if (!control_pid_good(s)) service_enter_dead(s, f, true); break; default: assert_not_reached("Uh, main process died at wrong time."); } } } else if (s->control_pid == pid) { s->control_pid = 0; if (s->control_command) { exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status); if (s->control_command->ignore) f = SERVICE_SUCCESS; } log_unit_full(u, f == SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0, "Control process exited, code=%s status=%i", sigchld_code_to_string(code), status); if (f != SERVICE_SUCCESS) s->result = f; /* Immediately get rid of the cgroup, so that the * kernel doesn't delay the cgroup empty messages for * the service cgroup any longer than necessary */ service_kill_control_processes(s); if (s->control_command && s->control_command->command_next && f == SERVICE_SUCCESS) { /* There is another command to * * execute, so let's do that. */ log_unit_debug(u, "Running next control command for state %s.", service_state_to_string(s->state)); service_run_next_control(s); } else { /* No further commands for this step, so let's * figure out what to do next */ s->control_command = NULL; s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; log_unit_debug(u, "Got final SIGCHLD for state %s.", service_state_to_string(s->state)); switch (s->state) { case SERVICE_START_PRE: if (f == SERVICE_SUCCESS) service_enter_start(s); else service_enter_signal(s, SERVICE_FINAL_SIGTERM, f); break; case SERVICE_START: if (s->type != SERVICE_FORKING) /* Maybe spurious event due to a reload that changed the type? */ break; if (f != SERVICE_SUCCESS) { service_enter_signal(s, SERVICE_FINAL_SIGTERM, f); break; } if (s->pid_file) { bool has_start_post; int r; /* Let's try to load the pid file here if we can. * The PID file might actually be created by a START_POST * script. In that case don't worry if the loading fails. */ has_start_post = !!s->exec_command[SERVICE_EXEC_START_POST]; r = service_load_pid_file(s, !has_start_post); if (!has_start_post && r < 0) { r = service_demand_pid_file(s); if (r < 0 || !cgroup_good(s)) service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES); break; } } else (void) service_search_main_pid(s); service_enter_start_post(s); break; case SERVICE_START_POST: if (f != SERVICE_SUCCESS) { service_enter_signal(s, SERVICE_STOP_SIGTERM, f); break; } if (s->pid_file) { int r; r = service_load_pid_file(s, true); if (r < 0) { r = service_demand_pid_file(s); if (r < 0 || !cgroup_good(s)) service_enter_stop(s, SERVICE_FAILURE_RESOURCES); break; } } else (void) service_search_main_pid(s); service_enter_running(s, SERVICE_SUCCESS); break; case SERVICE_RELOAD: if (f == SERVICE_SUCCESS) { service_load_pid_file(s, true); (void) service_search_main_pid(s); } s->reload_result = f; service_enter_running(s, SERVICE_SUCCESS); break; case SERVICE_STOP: service_enter_signal(s, SERVICE_STOP_SIGTERM, f); break; case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: if (main_pid_good(s) <= 0) service_enter_stop_post(s, f); /* If there is still a service * process around, wait until * that one quit, too */ break; case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: if (main_pid_good(s) <= 0) service_enter_dead(s, f, true); break; default: assert_not_reached("Uh, control process died at wrong time."); } } } /* Notify clients about changed exit status */ unit_add_to_dbus_queue(u); /* We got one SIGCHLD for the service, let's watch all * processes that are now running of the service, and watch * that. Among the PIDs we then watch will be children * reassigned to us, which hopefully allows us to identify * when all children are gone */ unit_tidy_watch_pids(u, s->main_pid, s->control_pid); unit_watch_all_pids(u); /* If the PID set is empty now, then let's finish this off */ if (set_isempty(u->pids)) service_notify_cgroup_empty_event(u); } static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { Service *s = SERVICE(userdata); assert(s); assert(source == s->timer_event_source); switch (s->state) { case SERVICE_START_PRE: case SERVICE_START: log_unit_warning(UNIT(s), "%s operation timed out. Terminating.", s->state == SERVICE_START ? "Start" : "Start-pre"); service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT); break; case SERVICE_START_POST: log_unit_warning(UNIT(s), "Start-post operation timed out. Stopping."); service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT); break; case SERVICE_RUNNING: log_unit_warning(UNIT(s), "Service reached runtime time limit. Stopping."); service_enter_stop(s, SERVICE_FAILURE_TIMEOUT); break; case SERVICE_RELOAD: log_unit_warning(UNIT(s), "Reload operation timed out. Killing reload process."); service_kill_control_processes(s); s->reload_result = SERVICE_FAILURE_TIMEOUT; service_enter_running(s, SERVICE_SUCCESS); break; case SERVICE_STOP: log_unit_warning(UNIT(s), "Stopping timed out. Terminating."); service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT); break; case SERVICE_STOP_SIGABRT: log_unit_warning(UNIT(s), "State 'stop-sigabrt' timed out. Terminating."); service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT); break; case SERVICE_STOP_SIGTERM: if (s->kill_context.send_sigkill) { log_unit_warning(UNIT(s), "State 'stop-sigterm' timed out. Killing."); service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_TIMEOUT); } else { log_unit_warning(UNIT(s), "State 'stop-sigterm' timed out. Skipping SIGKILL."); service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT); } break; case SERVICE_STOP_SIGKILL: /* Uh, we sent a SIGKILL and it is still not gone? * Must be something we cannot kill, so let's just be * weirded out and continue */ log_unit_warning(UNIT(s), "Processes still around after SIGKILL. Ignoring."); service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT); break; case SERVICE_STOP_POST: log_unit_warning(UNIT(s), "State 'stop-post' timed out. Terminating."); service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT); break; case SERVICE_FINAL_SIGTERM: if (s->kill_context.send_sigkill) { log_unit_warning(UNIT(s), "State 'stop-final-sigterm' timed out. Killing."); service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_FAILURE_TIMEOUT); } else { log_unit_warning(UNIT(s), "State 'stop-final-sigterm' timed out. Skipping SIGKILL. Entering failed mode."); service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, false); } break; case SERVICE_FINAL_SIGKILL: log_unit_warning(UNIT(s), "Processes still around after final SIGKILL. Entering failed mode."); service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, true); break; case SERVICE_AUTO_RESTART: log_unit_info(UNIT(s), s->restart_usec > 0 ? "Service hold-off time over, scheduling restart." : "Service has no hold-off time, scheduling restart."); service_enter_restart(s); break; default: assert_not_reached("Timeout at wrong time."); } return 0; } static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata) { Service *s = SERVICE(userdata); char t[FORMAT_TIMESPAN_MAX]; assert(s); assert(source == s->watchdog_event_source); log_unit_error(UNIT(s), "Watchdog timeout (limit %s)!", format_timespan(t, sizeof(t), s->watchdog_usec, 1)); service_enter_signal(s, SERVICE_STOP_SIGABRT, SERVICE_FAILURE_WATCHDOG); return 0; } static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds) { Service *s = SERVICE(u); _cleanup_free_ char *cc = NULL; bool notify_dbus = false; const char *e; assert(u); cc = strv_join(tags, ", "); if (s->notify_access == NOTIFY_NONE) { log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception is disabled.", pid); return; } else if (s->notify_access == NOTIFY_MAIN && pid != s->main_pid) { if (s->main_pid != 0) log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT, pid, s->main_pid); else log_unit_debug(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID which is currently not known", pid); return; } else log_unit_debug(u, "Got notification message from PID "PID_FMT" (%s)", pid, isempty(cc) ? "n/a" : cc); /* Interpret MAINPID= */ e = strv_find_startswith(tags, "MAINPID="); if (e && IN_SET(s->state, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) { if (parse_pid(e, &pid) < 0) log_unit_warning(u, "Failed to parse MAINPID= field in notification message: %s", e); else { service_set_main_pid(s, pid); unit_watch_pid(UNIT(s), pid); notify_dbus = true; } } /* Interpret RELOADING= */ if (strv_find(tags, "RELOADING=1")) { s->notify_state = NOTIFY_RELOADING; if (s->state == SERVICE_RUNNING) service_enter_reload_by_notify(s); notify_dbus = true; } /* Interpret READY= */ if (strv_find(tags, "READY=1")) { s->notify_state = NOTIFY_READY; /* Type=notify services inform us about completed * initialization with READY=1 */ if (s->type == SERVICE_NOTIFY && s->state == SERVICE_START) service_enter_start_post(s); /* Sending READY=1 while we are reloading informs us * that the reloading is complete */ if (s->state == SERVICE_RELOAD && s->control_pid == 0) service_enter_running(s, SERVICE_SUCCESS); notify_dbus = true; } /* Interpret STOPPING= */ if (strv_find(tags, "STOPPING=1")) { s->notify_state = NOTIFY_STOPPING; if (s->state == SERVICE_RUNNING) service_enter_stop_by_notify(s); notify_dbus = true; } /* Interpret STATUS= */ e = strv_find_startswith(tags, "STATUS="); if (e) { _cleanup_free_ char *t = NULL; if (!isempty(e)) { if (!utf8_is_valid(e)) log_unit_warning(u, "Status message in notification message is not UTF-8 clean."); else { t = strdup(e); if (!t) log_oom(); } } if (!streq_ptr(s->status_text, t)) { free(s->status_text); s->status_text = t; t = NULL; notify_dbus = true; } } /* Interpret ERRNO= */ e = strv_find_startswith(tags, "ERRNO="); if (e) { int status_errno; if (safe_atoi(e, &status_errno) < 0 || status_errno < 0) log_unit_warning(u, "Failed to parse ERRNO= field in notification message: %s", e); else { if (s->status_errno != status_errno) { s->status_errno = status_errno; notify_dbus = true; } } } /* Interpret WATCHDOG= */ if (strv_find(tags, "WATCHDOG=1")) service_reset_watchdog(s); if (strv_find(tags, "FDSTORE=1")) { const char *name; name = strv_find_startswith(tags, "FDNAME="); if (name && !fdname_is_valid(name)) { log_unit_warning(u, "Passed FDNAME= name is invalid, ignoring."); name = NULL; } service_add_fd_store_set(s, fds, name); } /* Notify clients about changed status or main pid */ if (notify_dbus) unit_add_to_dbus_queue(u); } static int service_get_timeout(Unit *u, usec_t *timeout) { Service *s = SERVICE(u); uint64_t t; int r; if (!s->timer_event_source) return 0; r = sd_event_source_get_time(s->timer_event_source, &t); if (r < 0) return r; if (t == USEC_INFINITY) return 0; *timeout = t; return 1; } static void service_bus_name_owner_change( Unit *u, const char *name, const char *old_owner, const char *new_owner) { Service *s = SERVICE(u); int r; assert(s); assert(name); assert(streq(s->bus_name, name)); assert(old_owner || new_owner); if (old_owner && new_owner) log_unit_debug(u, "D-Bus name %s changed owner from %s to %s", name, old_owner, new_owner); else if (old_owner) log_unit_debug(u, "D-Bus name %s no longer registered by %s", name, old_owner); else log_unit_debug(u, "D-Bus name %s now registered by %s", name, new_owner); s->bus_name_good = !!new_owner; /* Track the current owner, so we can reconstruct changes after a daemon reload */ r = free_and_strdup(&s->bus_name_owner, new_owner); if (r < 0) { log_unit_error_errno(u, r, "Unable to set new bus name owner %s: %m", new_owner); return; } if (s->type == SERVICE_DBUS) { /* service_enter_running() will figure out what to * do */ if (s->state == SERVICE_RUNNING) service_enter_running(s, SERVICE_SUCCESS); else if (s->state == SERVICE_START && new_owner) service_enter_start_post(s); } else if (new_owner && s->main_pid <= 0 && (s->state == SERVICE_START || s->state == SERVICE_START_POST || s->state == SERVICE_RUNNING || s->state == SERVICE_RELOAD)) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; pid_t pid; /* Try to acquire PID from bus service */ r = sd_bus_get_name_creds(u->manager->api_bus, name, SD_BUS_CREDS_PID, &creds); if (r >= 0) r = sd_bus_creds_get_pid(creds, &pid); if (r >= 0) { log_unit_debug(u, "D-Bus name %s is now owned by process %u", name, (unsigned) pid); service_set_main_pid(s, pid); unit_watch_pid(UNIT(s), pid); } } } int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context_net) { _cleanup_free_ char *peer = NULL; int r; assert(s); assert(fd >= 0); /* This is called by the socket code when instantiating a new * service for a stream socket and the socket needs to be * configured. */ if (UNIT(s)->load_state != UNIT_LOADED) return -EINVAL; if (s->socket_fd >= 0) return -EBUSY; if (s->state != SERVICE_DEAD) return -EAGAIN; if (getpeername_pretty(fd, true, &peer) >= 0) { if (UNIT(s)->description) { _cleanup_free_ char *a; a = strjoin(UNIT(s)->description, " (", peer, ")", NULL); if (!a) return -ENOMEM; r = unit_set_description(UNIT(s), a); } else r = unit_set_description(UNIT(s), peer); if (r < 0) return r; } s->socket_fd = fd; s->socket_fd_selinux_context_net = selinux_context_net; unit_ref_set(&s->accept_socket, UNIT(sock)); return unit_add_two_dependencies(UNIT(sock), UNIT_BEFORE, UNIT_TRIGGERS, UNIT(s), false); } static void service_reset_failed(Unit *u) { Service *s = SERVICE(u); assert(s); if (s->state == SERVICE_FAILED) service_set_state(s, SERVICE_DEAD); s->result = SERVICE_SUCCESS; s->reload_result = SERVICE_SUCCESS; } static int service_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { Service *s = SERVICE(u); return unit_kill_common(u, who, signo, s->main_pid, s->control_pid, error); } static const char* const service_restart_table[_SERVICE_RESTART_MAX] = { [SERVICE_RESTART_NO] = "no", [SERVICE_RESTART_ON_SUCCESS] = "on-success", [SERVICE_RESTART_ON_FAILURE] = "on-failure", [SERVICE_RESTART_ON_ABNORMAL] = "on-abnormal", [SERVICE_RESTART_ON_WATCHDOG] = "on-watchdog", [SERVICE_RESTART_ON_ABORT] = "on-abort", [SERVICE_RESTART_ALWAYS] = "always", }; DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart); static const char* const service_type_table[_SERVICE_TYPE_MAX] = { [SERVICE_SIMPLE] = "simple", [SERVICE_FORKING] = "forking", [SERVICE_ONESHOT] = "oneshot", [SERVICE_DBUS] = "dbus", [SERVICE_NOTIFY] = "notify", [SERVICE_IDLE] = "idle" }; DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType); static const char* const service_exec_command_table[_SERVICE_EXEC_COMMAND_MAX] = { [SERVICE_EXEC_START_PRE] = "ExecStartPre", [SERVICE_EXEC_START] = "ExecStart", [SERVICE_EXEC_START_POST] = "ExecStartPost", [SERVICE_EXEC_RELOAD] = "ExecReload", [SERVICE_EXEC_STOP] = "ExecStop", [SERVICE_EXEC_STOP_POST] = "ExecStopPost", }; DEFINE_STRING_TABLE_LOOKUP(service_exec_command, ServiceExecCommand); static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = { [NOTIFY_NONE] = "none", [NOTIFY_MAIN] = "main", [NOTIFY_ALL] = "all" }; DEFINE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess); static const char* const notify_state_table[_NOTIFY_STATE_MAX] = { [NOTIFY_UNKNOWN] = "unknown", [NOTIFY_READY] = "ready", [NOTIFY_RELOADING] = "reloading", [NOTIFY_STOPPING] = "stopping", }; DEFINE_STRING_TABLE_LOOKUP(notify_state, NotifyState); static const char* const service_result_table[_SERVICE_RESULT_MAX] = { [SERVICE_SUCCESS] = "success", [SERVICE_FAILURE_RESOURCES] = "resources", [SERVICE_FAILURE_TIMEOUT] = "timeout", [SERVICE_FAILURE_EXIT_CODE] = "exit-code", [SERVICE_FAILURE_SIGNAL] = "signal", [SERVICE_FAILURE_CORE_DUMP] = "core-dump", [SERVICE_FAILURE_WATCHDOG] = "watchdog", }; DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult); const UnitVTable service_vtable = { .object_size = sizeof(Service), .exec_context_offset = offsetof(Service, exec_context), .cgroup_context_offset = offsetof(Service, cgroup_context), .kill_context_offset = offsetof(Service, kill_context), .exec_runtime_offset = offsetof(Service, exec_runtime), .sections = "Unit\0" "Service\0" "Install\0", .private_section = "Service", .init = service_init, .done = service_done, .load = service_load, .release_resources = service_release_resources, .coldplug = service_coldplug, .dump = service_dump, .start = service_start, .stop = service_stop, .reload = service_reload, .can_reload = service_can_reload, .kill = service_kill, .serialize = service_serialize, .deserialize_item = service_deserialize_item, .active_state = service_active_state, .sub_state_to_string = service_sub_state_to_string, .check_gc = service_check_gc, .sigchld_event = service_sigchld_event, .reset_failed = service_reset_failed, .notify_cgroup_empty = service_notify_cgroup_empty_event, .notify_message = service_notify_message, .bus_name_owner_change = service_bus_name_owner_change, .bus_vtable = bus_service_vtable, .bus_set_property = bus_service_set_property, .bus_commit_properties = bus_service_commit_properties, .get_timeout = service_get_timeout, .can_transient = true, .status_message_formats = { .starting_stopping = { [0] = "Starting %s...", [1] = "Stopping %s...", }, .finished_start_job = { [JOB_DONE] = "Started %s.", [JOB_FAILED] = "Failed to start %s.", }, .finished_stop_job = { [JOB_DONE] = "Stopped %s.", [JOB_FAILED] = "Stopped (with error) %s.", }, }, }; systemd-229/src/core/service.h000066400000000000000000000150231265713322000164120ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Service Service; typedef struct ServiceFDStore ServiceFDStore; #include "exit-status.h" #include "kill.h" #include "path.h" #include "ratelimit.h" typedef enum ServiceRestart { SERVICE_RESTART_NO, SERVICE_RESTART_ON_SUCCESS, SERVICE_RESTART_ON_FAILURE, SERVICE_RESTART_ON_ABNORMAL, SERVICE_RESTART_ON_WATCHDOG, SERVICE_RESTART_ON_ABORT, SERVICE_RESTART_ALWAYS, _SERVICE_RESTART_MAX, _SERVICE_RESTART_INVALID = -1 } ServiceRestart; typedef enum ServiceType { SERVICE_SIMPLE, /* we fork and go on right-away (i.e. modern socket activated daemons) */ SERVICE_FORKING, /* forks by itself (i.e. traditional daemons) */ SERVICE_ONESHOT, /* we fork and wait until the program finishes (i.e. programs like fsck which run and need to finish before we continue) */ SERVICE_DBUS, /* we fork and wait until a specific D-Bus name appears on the bus */ SERVICE_NOTIFY, /* we fork and wait until a daemon sends us a ready message with sd_notify() */ SERVICE_IDLE, /* much like simple, but delay exec() until all jobs are dispatched. */ _SERVICE_TYPE_MAX, _SERVICE_TYPE_INVALID = -1 } ServiceType; typedef enum ServiceExecCommand { SERVICE_EXEC_START_PRE, SERVICE_EXEC_START, SERVICE_EXEC_START_POST, SERVICE_EXEC_RELOAD, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST, _SERVICE_EXEC_COMMAND_MAX, _SERVICE_EXEC_COMMAND_INVALID = -1 } ServiceExecCommand; typedef enum NotifyAccess { NOTIFY_NONE, NOTIFY_ALL, NOTIFY_MAIN, _NOTIFY_ACCESS_MAX, _NOTIFY_ACCESS_INVALID = -1 } NotifyAccess; typedef enum NotifyState { NOTIFY_UNKNOWN, NOTIFY_READY, NOTIFY_RELOADING, NOTIFY_STOPPING, _NOTIFY_STATE_MAX, _NOTIFY_STATE_INVALID = -1 } NotifyState; typedef enum ServiceResult { SERVICE_SUCCESS, SERVICE_FAILURE_RESOURCES, SERVICE_FAILURE_TIMEOUT, SERVICE_FAILURE_EXIT_CODE, SERVICE_FAILURE_SIGNAL, SERVICE_FAILURE_CORE_DUMP, SERVICE_FAILURE_WATCHDOG, _SERVICE_RESULT_MAX, _SERVICE_RESULT_INVALID = -1 } ServiceResult; struct ServiceFDStore { Service *service; int fd; char *fdname; sd_event_source *event_source; LIST_FIELDS(ServiceFDStore, fd_store); }; struct Service { Unit meta; ServiceType type; ServiceRestart restart; ExitStatusSet restart_prevent_status; ExitStatusSet restart_force_status; ExitStatusSet success_status; /* If set we'll read the main daemon PID from this file */ char *pid_file; usec_t restart_usec; usec_t timeout_start_usec; usec_t timeout_stop_usec; usec_t runtime_max_usec; dual_timestamp watchdog_timestamp; usec_t watchdog_usec; sd_event_source *watchdog_event_source; ExecCommand* exec_command[_SERVICE_EXEC_COMMAND_MAX]; ExecContext exec_context; KillContext kill_context; CGroupContext cgroup_context; ServiceState state, deserialized_state; /* The exit status of the real main process */ ExecStatus main_exec_status; /* The currently executed control process */ ExecCommand *control_command; /* The currently executed main process, which may be NULL if * the main process got started via forking mode and not by * us */ ExecCommand *main_command; /* The ID of the control command currently being executed */ ServiceExecCommand control_command_id; /* Runtime data of the execution context */ ExecRuntime *exec_runtime; pid_t main_pid, control_pid; int socket_fd; bool socket_fd_selinux_context_net; int bus_endpoint_fd; bool permissions_start_only; bool root_directory_start_only; bool remain_after_exit; bool guess_main_pid; /* If we shut down, remember why */ ServiceResult result; ServiceResult reload_result; bool main_pid_known:1; bool main_pid_alien:1; bool bus_name_good:1; bool forbid_restart:1; bool start_timeout_defined:1; bool reset_cpu_usage:1; char *bus_name; char *bus_name_owner; /* unique name of the current owner */ char *status_text; int status_errno; FailureAction failure_action; UnitRef accept_socket; sd_event_source *timer_event_source; PathSpec *pid_file_pathspec; NotifyAccess notify_access; NotifyState notify_state; ServiceFDStore *fd_store; unsigned n_fd_store; unsigned n_fd_store_max; char *usb_function_descriptors; char *usb_function_strings; int stdin_fd; int stdout_fd; int stderr_fd; }; extern const UnitVTable service_vtable; int service_set_socket_fd(Service *s, int fd, struct Socket *socket, bool selinux_context_net); const char* service_restart_to_string(ServiceRestart i) _const_; ServiceRestart service_restart_from_string(const char *s) _pure_; const char* service_type_to_string(ServiceType i) _const_; ServiceType service_type_from_string(const char *s) _pure_; const char* service_exec_command_to_string(ServiceExecCommand i) _const_; ServiceExecCommand service_exec_command_from_string(const char *s) _pure_; const char* notify_access_to_string(NotifyAccess i) _const_; NotifyAccess notify_access_from_string(const char *s) _pure_; const char* notify_state_to_string(NotifyState i) _const_; NotifyState notify_state_from_string(const char *s) _pure_; const char* service_result_to_string(ServiceResult i) _const_; ServiceResult service_result_from_string(const char *s) _pure_; systemd-229/src/core/show-status.c000066400000000000000000000066461265713322000172610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "fd-util.h" #include "io-util.h" #include "parse-util.h" #include "show-status.h" #include "string-util.h" #include "terminal-util.h" #include "util.h" int parse_show_status(const char *v, ShowStatus *ret) { int r; assert(v); assert(ret); if (streq(v, "auto")) { *ret = SHOW_STATUS_AUTO; return 0; } r = parse_boolean(v); if (r < 0) return r; *ret = r ? SHOW_STATUS_YES : SHOW_STATUS_NO; return 0; } int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) { static const char status_indent[] = " "; /* "[" STATUS "] " */ _cleanup_free_ char *s = NULL; _cleanup_close_ int fd = -1; struct iovec iovec[6] = {}; int n = 0; static bool prev_ephemeral; assert(format); /* This is independent of logging, as status messages are * optional and go exclusively to the console. */ if (vasprintf(&s, format, ap) < 0) return log_oom(); fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) return fd; if (ellipse) { char *e; size_t emax, sl; int c; c = fd_columns(fd); if (c <= 0) c = 80; sl = status ? sizeof(status_indent)-1 : 0; emax = c - sl - 1; if (emax < 3) emax = 3; e = ellipsize(s, emax, 50); if (e) { free(s); s = e; } } if (prev_ephemeral) IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE); prev_ephemeral = ephemeral; if (status) { if (!isempty(status)) { IOVEC_SET_STRING(iovec[n++], "["); IOVEC_SET_STRING(iovec[n++], status); IOVEC_SET_STRING(iovec[n++], "] "); } else IOVEC_SET_STRING(iovec[n++], status_indent); } IOVEC_SET_STRING(iovec[n++], s); if (!ephemeral) IOVEC_SET_STRING(iovec[n++], "\n"); if (writev(fd, iovec, n) < 0) return -errno; return 0; } int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) { va_list ap; int r; assert(format); va_start(ap, format); r = status_vprintf(status, ellipse, ephemeral, format, ap); va_end(ap); return r; } systemd-229/src/core/show-status.h000066400000000000000000000023721265713322000172560ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" /* Manager status */ typedef enum ShowStatus { _SHOW_STATUS_UNSET = -2, SHOW_STATUS_AUTO = -1, SHOW_STATUS_NO = 0, SHOW_STATUS_YES = 1, SHOW_STATUS_TEMPORARY = 2, } ShowStatus; int parse_show_status(const char *v, ShowStatus *ret); int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) _printf_(4,0); int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) _printf_(4,5); systemd-229/src/core/shutdown.c000066400000000000000000000372161265713322000166300ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 ProFUSION embedded systems systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "cgroup-util.h" #include "def.h" #include "fileio.h" #include "killall.h" #include "log.h" #include "missing.h" #include "parse-util.h" #include "process-util.h" #include "string-util.h" #include "switch-root.h" #include "terminal-util.h" #include "umount.h" #include "util.h" #include "virt.h" #include "watchdog.h" #define FINALIZE_ATTEMPTS 50 static char* arg_verb; static uint8_t arg_exit_code; static int parse_argv(int argc, char *argv[]) { enum { ARG_LOG_LEVEL = 0x100, ARG_LOG_TARGET, ARG_LOG_COLOR, ARG_LOG_LOCATION, ARG_EXIT_CODE, }; static const struct option options[] = { { "log-level", required_argument, NULL, ARG_LOG_LEVEL }, { "log-target", required_argument, NULL, ARG_LOG_TARGET }, { "log-color", optional_argument, NULL, ARG_LOG_COLOR }, { "log-location", optional_argument, NULL, ARG_LOG_LOCATION }, { "exit-code", required_argument, NULL, ARG_EXIT_CODE }, {} }; int c, r; assert(argc >= 1); assert(argv); /* "-" prevents getopt from permuting argv[] and moving the verb away * from argv[1]. Our interface to initrd promises it'll be there. */ while ((c = getopt_long(argc, argv, "-", options, NULL)) >= 0) switch (c) { case ARG_LOG_LEVEL: r = log_set_max_level_from_string(optarg); if (r < 0) log_error("Failed to parse log level %s, ignoring.", optarg); break; case ARG_LOG_TARGET: r = log_set_target_from_string(optarg); if (r < 0) log_error("Failed to parse log target %s, ignoring", optarg); break; case ARG_LOG_COLOR: if (optarg) { r = log_show_color_from_string(optarg); if (r < 0) log_error("Failed to parse log color setting %s, ignoring", optarg); } else log_show_color(true); break; case ARG_LOG_LOCATION: if (optarg) { r = log_show_location_from_string(optarg); if (r < 0) log_error("Failed to parse log location setting %s, ignoring", optarg); } else log_show_location(true); break; case ARG_EXIT_CODE: r = safe_atou8(optarg, &arg_exit_code); if (r < 0) log_error("Failed to parse exit code %s, ignoring", optarg); break; case '\001': if (!arg_verb) arg_verb = optarg; else log_error("Excess arguments, ignoring"); break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option code."); } if (!arg_verb) { log_error("Verb argument missing."); return -EINVAL; } return 0; } static int switch_root_initramfs(void) { if (mount("/run/initramfs", "/run/initramfs", NULL, MS_BIND, NULL) < 0) return log_error_errno(errno, "Failed to mount bind /run/initramfs on /run/initramfs: %m"); if (mount(NULL, "/run/initramfs", NULL, MS_PRIVATE, NULL) < 0) return log_error_errno(errno, "Failed to make /run/initramfs private mount: %m"); /* switch_root with MS_BIND, because there might still be processes lurking around, which have open file descriptors. * /run/initramfs/shutdown will take care of these. * Also do not detach the old root, because /run/initramfs/shutdown needs to access it. */ return switch_root("/run/initramfs", "/oldroot", false, MS_BIND); } int main(int argc, char *argv[]) { bool need_umount, need_swapoff, need_loop_detach, need_dm_detach; bool in_container, use_watchdog = false; _cleanup_free_ char *cgroup = NULL; char *arguments[3]; unsigned retries; int cmd, r; static const char* const dirs[] = {SYSTEM_SHUTDOWN_PATH, NULL}; log_parse_environment(); r = parse_argv(argc, argv); if (r < 0) goto error; /* journald will die if not gone yet. The log target defaults * to console, but may have been changed by command line options. */ log_close_console(); /* force reopen of /dev/console */ log_open(); umask(0022); if (getpid() != 1) { log_error("Not executed by init (PID 1)."); r = -EPERM; goto error; } if (streq(arg_verb, "reboot")) cmd = RB_AUTOBOOT; else if (streq(arg_verb, "poweroff")) cmd = RB_POWER_OFF; else if (streq(arg_verb, "halt")) cmd = RB_HALT_SYSTEM; else if (streq(arg_verb, "kexec")) cmd = LINUX_REBOOT_CMD_KEXEC; else if (streq(arg_verb, "exit")) cmd = 0; /* ignored, just checking that arg_verb is valid */ else { r = -EINVAL; log_error("Unknown action '%s'.", arg_verb); goto error; } cg_get_root_path(&cgroup); use_watchdog = !!getenv("WATCHDOG_USEC"); /* lock us into memory */ mlockall(MCL_CURRENT|MCL_FUTURE); log_info("Sending SIGTERM to remaining processes..."); broadcast_signal(SIGTERM, true, true); log_info("Sending SIGKILL to remaining processes..."); broadcast_signal(SIGKILL, true, false); in_container = detect_container() > 0; need_umount = !in_container; need_swapoff = !in_container; need_loop_detach = !in_container; need_dm_detach = !in_container; /* Unmount all mountpoints, swaps, and loopback devices */ for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) { bool changed = false; if (use_watchdog) watchdog_ping(); /* Let's trim the cgroup tree on each iteration so that we leave an empty cgroup tree around, so that container managers get a nice notify event when we are down */ if (cgroup) cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false); if (need_umount) { log_info("Unmounting file systems."); r = umount_all(&changed); if (r == 0) { need_umount = false; log_info("All filesystems unmounted."); } else if (r > 0) log_info("Not all file systems unmounted, %d left.", r); else log_error_errno(r, "Failed to unmount file systems: %m"); } if (need_swapoff) { log_info("Deactivating swaps."); r = swapoff_all(&changed); if (r == 0) { need_swapoff = false; log_info("All swaps deactivated."); } else if (r > 0) log_info("Not all swaps deactivated, %d left.", r); else log_error_errno(r, "Failed to deactivate swaps: %m"); } if (need_loop_detach) { log_info("Detaching loop devices."); r = loopback_detach_all(&changed); if (r == 0) { need_loop_detach = false; log_info("All loop devices detached."); } else if (r > 0) log_info("Not all loop devices detached, %d left.", r); else log_error_errno(r, "Failed to detach loop devices: %m"); } if (need_dm_detach) { log_info("Detaching DM devices."); r = dm_detach_all(&changed); if (r == 0) { need_dm_detach = false; log_info("All DM devices detached."); } else if (r > 0) log_info("Not all DM devices detached, %d left.", r); else log_error_errno(r, "Failed to detach DM devices: %m"); } if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) { if (retries > 0) log_info("All filesystems, swaps, loop devices, DM devices detached."); /* Yay, done */ goto initrd_jump; } /* If in this iteration we didn't manage to * unmount/deactivate anything, we simply give up */ if (!changed) { log_info("Cannot finalize remaining%s%s%s%s continuing.", need_umount ? " file systems," : "", need_swapoff ? " swap devices," : "", need_loop_detach ? " loop devices," : "", need_dm_detach ? " DM devices," : ""); goto initrd_jump; } log_debug("After %u retries, couldn't finalize remaining %s%s%s%s trying again.", retries + 1, need_umount ? " file systems," : "", need_swapoff ? " swap devices," : "", need_loop_detach ? " loop devices," : "", need_dm_detach ? " DM devices," : ""); } log_error("Too many iterations, giving up."); initrd_jump: arguments[0] = NULL; arguments[1] = arg_verb; arguments[2] = NULL; execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments); if (!in_container && !in_initrd() && access("/run/initramfs/shutdown", X_OK) == 0) { r = switch_root_initramfs(); if (r >= 0) { argv[0] = (char*) "/shutdown"; setsid(); make_console_stdio(); log_info("Successfully changed into root pivot.\n" "Returning to initrd..."); execv("/shutdown", argv); log_error_errno(errno, "Failed to execute shutdown binary: %m"); } else log_error_errno(r, "Failed to switch root to \"/run/initramfs\": %m"); } if (need_umount || need_swapoff || need_loop_detach || need_dm_detach) log_error("Failed to finalize %s%s%s%s ignoring", need_umount ? " file systems," : "", need_swapoff ? " swap devices," : "", need_loop_detach ? " loop devices," : "", need_dm_detach ? " DM devices," : ""); /* The kernel will automaticall flush ATA disks and suchlike * on reboot(), but the file systems need to be synce'd * explicitly in advance. So let's do this here, but not * needlessly slow down containers. */ if (!in_container) sync(); if (streq(arg_verb, "exit")) { if (in_container) exit(arg_exit_code); else { /* We cannot exit() on the host, fallback on another * method. */ cmd = RB_POWER_OFF; } } switch (cmd) { case LINUX_REBOOT_CMD_KEXEC: if (!in_container) { /* We cheat and exec kexec to avoid doing all its work */ pid_t pid; log_info("Rebooting with kexec."); pid = fork(); if (pid < 0) log_error_errno(errno, "Failed to fork: %m"); else if (pid == 0) { const char * const args[] = { KEXEC, "-e", NULL }; /* Child */ execv(args[0], (char * const *) args); _exit(EXIT_FAILURE); } else wait_for_terminate_and_warn("kexec", pid, true); } cmd = RB_AUTOBOOT; /* Fall through */ case RB_AUTOBOOT: if (!in_container) { _cleanup_free_ char *param = NULL; if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) { log_info("Rebooting with argument '%s'.", param); syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param); } } log_info("Rebooting."); break; case RB_POWER_OFF: log_info("Powering off."); break; case RB_HALT_SYSTEM: log_info("Halting system."); break; default: assert_not_reached("Unknown magic"); } reboot(cmd); if (errno == EPERM && in_container) { /* If we are in a container, and we lacked * CAP_SYS_BOOT just exit, this will kill our * container for good. */ log_info("Exiting container."); exit(0); } r = log_error_errno(errno, "Failed to invoke reboot(): %m"); error: log_emergency_errno(r, "Critical error while doing system shutdown: %m"); freeze(); } systemd-229/src/core/slice.c000066400000000000000000000214111265713322000160420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "dbus-slice.h" #include "log.h" #include "slice.h" #include "special.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "unit.h" static const UnitActiveState state_translation_table[_SLICE_STATE_MAX] = { [SLICE_DEAD] = UNIT_INACTIVE, [SLICE_ACTIVE] = UNIT_ACTIVE }; static void slice_set_state(Slice *t, SliceState state) { SliceState old_state; assert(t); old_state = t->state; t->state = state; if (state != old_state) log_debug("%s changed %s -> %s", UNIT(t)->id, slice_state_to_string(old_state), slice_state_to_string(state)); unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true); } static int slice_add_parent_slice(Slice *s) { char *a, *dash; Unit *parent; int r; assert(s); if (UNIT_ISSET(UNIT(s)->slice)) return 0; if (unit_has_name(UNIT(s), SPECIAL_ROOT_SLICE)) return 0; a = strdupa(UNIT(s)->id); dash = strrchr(a, '-'); if (dash) strcpy(dash, ".slice"); else a = (char*) SPECIAL_ROOT_SLICE; r = manager_load_unit(UNIT(s)->manager, a, NULL, NULL, &parent); if (r < 0) return r; unit_ref_set(&UNIT(s)->slice, parent); return 0; } static int slice_add_default_dependencies(Slice *s) { int r; assert(s); if (!UNIT(s)->default_dependencies) return 0; /* Make sure slices are unloaded on shutdown */ r = unit_add_two_dependencies_by_name( UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true); if (r < 0) return r; return 0; } static int slice_verify(Slice *s) { _cleanup_free_ char *parent = NULL; int r; assert(s); if (UNIT(s)->load_state != UNIT_LOADED) return 0; if (!slice_name_is_valid(UNIT(s)->id)) { log_unit_error(UNIT(s), "Slice name %s is not valid. Refusing.", UNIT(s)->id); return -EINVAL; } r = slice_build_parent_slice(UNIT(s)->id, &parent); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Failed to determine parent slice: %m"); if (parent ? !unit_has_name(UNIT_DEREF(UNIT(s)->slice), parent) : UNIT_ISSET(UNIT(s)->slice)) { log_unit_error(UNIT(s), "Located outside of parent slice. Refusing."); return -EINVAL; } return 0; } static int slice_load(Unit *u) { Slice *s = SLICE(u); int r; assert(s); r = unit_load_fragment_and_dropin_optional(u); if (r < 0) return r; /* This is a new unit? Then let's add in some extras */ if (u->load_state == UNIT_LOADED) { r = unit_patch_contexts(u); if (r < 0) return r; r = slice_add_parent_slice(s); if (r < 0) return r; r = slice_add_default_dependencies(s); if (r < 0) return r; } return slice_verify(s); } static int slice_coldplug(Unit *u) { Slice *t = SLICE(u); assert(t); assert(t->state == SLICE_DEAD); if (t->deserialized_state != t->state) slice_set_state(t, t->deserialized_state); return 0; } static void slice_dump(Unit *u, FILE *f, const char *prefix) { Slice *t = SLICE(u); assert(t); assert(f); fprintf(f, "%sSlice State: %s\n", prefix, slice_state_to_string(t->state)); cgroup_context_dump(&t->cgroup_context, f, prefix); } static int slice_start(Unit *u) { Slice *t = SLICE(u); assert(t); assert(t->state == SLICE_DEAD); (void) unit_realize_cgroup(u); (void) unit_reset_cpu_usage(u); slice_set_state(t, SLICE_ACTIVE); return 1; } static int slice_stop(Unit *u) { Slice *t = SLICE(u); assert(t); assert(t->state == SLICE_ACTIVE); /* We do not need to destroy the cgroup explicitly, * unit_notify() will do that for us anyway. */ slice_set_state(t, SLICE_DEAD); return 1; } static int slice_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { return unit_kill_common(u, who, signo, -1, -1, error); } static int slice_serialize(Unit *u, FILE *f, FDSet *fds) { Slice *s = SLICE(u); assert(s); assert(f); assert(fds); unit_serialize_item(u, f, "state", slice_state_to_string(s->state)); return 0; } static int slice_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Slice *s = SLICE(u); assert(u); assert(key); assert(value); assert(fds); if (streq(key, "state")) { SliceState state; state = slice_state_from_string(value); if (state < 0) log_debug("Failed to parse state value %s", value); else s->deserialized_state = state; } else log_debug("Unknown serialization key '%s'", key); return 0; } _pure_ static UnitActiveState slice_active_state(Unit *u) { assert(u); return state_translation_table[SLICE(u)->state]; } _pure_ static const char *slice_sub_state_to_string(Unit *u) { assert(u); return slice_state_to_string(SLICE(u)->state); } static void slice_enumerate(Manager *m) { Unit *u; int r; assert(m); u = manager_get_unit(m, SPECIAL_ROOT_SLICE); if (!u) { u = unit_new(m, sizeof(Slice)); if (!u) { log_oom(); return; } r = unit_add_name(u, SPECIAL_ROOT_SLICE); if (r < 0) { unit_free(u); log_error_errno(r, "Failed to add -.slice name"); return; } } u->default_dependencies = false; u->no_gc = true; u->ignore_on_isolate = true; u->refuse_manual_start = true; u->refuse_manual_stop = true; SLICE(u)->deserialized_state = SLICE_ACTIVE; if (!u->description) u->description = strdup("Root Slice"); if (!u->documentation) (void) strv_extend(&u->documentation, "man:systemd.special(7)"); unit_add_to_load_queue(u); unit_add_to_dbus_queue(u); } const UnitVTable slice_vtable = { .object_size = sizeof(Slice), .cgroup_context_offset = offsetof(Slice, cgroup_context), .sections = "Unit\0" "Slice\0" "Install\0", .private_section = "Slice", .no_alias = true, .no_instances = true, .can_transient = true, .load = slice_load, .coldplug = slice_coldplug, .dump = slice_dump, .start = slice_start, .stop = slice_stop, .kill = slice_kill, .serialize = slice_serialize, .deserialize_item = slice_deserialize_item, .active_state = slice_active_state, .sub_state_to_string = slice_sub_state_to_string, .bus_vtable = bus_slice_vtable, .bus_set_property = bus_slice_set_property, .bus_commit_properties = bus_slice_commit_properties, .enumerate = slice_enumerate, .status_message_formats = { .finished_start_job = { [JOB_DONE] = "Created slice %s.", }, .finished_stop_job = { [JOB_DONE] = "Removed slice %s.", }, }, }; systemd-229/src/core/slice.h000066400000000000000000000016341265713322000160540ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Slice Slice; struct Slice { Unit meta; SliceState state, deserialized_state; CGroupContext cgroup_context; }; extern const UnitVTable slice_vtable; systemd-229/src/core/smack-setup.c000066400000000000000000000307521265713322000172070ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Intel Corporation Authors: Nathaniel Chen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "alloc-util.h" #include "dirent-util.h" #include "fd-util.h" #include "fileio.h" #include "log.h" #include "macro.h" #include "smack-setup.h" #include "string-util.h" #include "util.h" #ifdef HAVE_SMACK static int write_access2_rules(const char* srcdir) { _cleanup_close_ int load2_fd = -1, change_fd = -1; _cleanup_closedir_ DIR *dir = NULL; struct dirent *entry; char buf[NAME_MAX]; int dfd = -1; int r = 0; load2_fd = open("/sys/fs/smackfs/load2", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); if (load2_fd < 0) { if (errno != ENOENT) log_warning_errno(errno, "Failed to open '/sys/fs/smackfs/load2': %m"); return -errno; /* negative error */ } change_fd = open("/sys/fs/smackfs/change-rule", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); if (change_fd < 0) { if (errno != ENOENT) log_warning_errno(errno, "Failed to open '/sys/fs/smackfs/change-rule': %m"); return -errno; /* negative error */ } /* write rules to load2 or change-rule from every file in the directory */ dir = opendir(srcdir); if (!dir) { if (errno != ENOENT) log_warning_errno(errno, "Failed to opendir '%s': %m", srcdir); return errno; /* positive on purpose */ } dfd = dirfd(dir); assert(dfd >= 0); FOREACH_DIRENT(entry, dir, return 0) { int fd; _cleanup_fclose_ FILE *policy = NULL; if (!dirent_is_file(entry)) continue; fd = openat(dfd, entry->d_name, O_RDONLY|O_CLOEXEC); if (fd < 0) { if (r == 0) r = -errno; log_warning_errno(errno, "Failed to open '%s': %m", entry->d_name); continue; } policy = fdopen(fd, "re"); if (!policy) { if (r == 0) r = -errno; safe_close(fd); log_error_errno(errno, "Failed to open '%s': %m", entry->d_name); continue; } /* load2 write rules in the kernel require a line buffered stream */ FOREACH_LINE(buf, policy, log_error_errno(errno, "Failed to read line from '%s': %m", entry->d_name)) { _cleanup_free_ char *sbj = NULL, *obj = NULL, *acc1 = NULL, *acc2 = NULL; if (isempty(truncate_nl(buf))) continue; /* if 3 args -> load rule : subject object access1 */ /* if 4 args -> change rule : subject object access1 access2 */ if (sscanf(buf, "%ms %ms %ms %ms", &sbj, &obj, &acc1, &acc2) < 3) { log_error_errno(errno, "Failed to parse rule '%s' in '%s', ignoring.", buf, entry->d_name); continue; } if (write(isempty(acc2) ? load2_fd : change_fd, buf, strlen(buf)) < 0) { if (r == 0) r = -errno; log_error_errno(errno, "Failed to write '%s' to '%s' in '%s'", buf, isempty(acc2) ? "/sys/fs/smackfs/load2" : "/sys/fs/smackfs/change-rule", entry->d_name); } } } return r; } static int write_cipso2_rules(const char* srcdir) { _cleanup_close_ int cipso2_fd = -1; _cleanup_closedir_ DIR *dir = NULL; struct dirent *entry; char buf[NAME_MAX]; int dfd = -1; int r = 0; cipso2_fd = open("/sys/fs/smackfs/cipso2", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); if (cipso2_fd < 0) { if (errno != ENOENT) log_warning_errno(errno, "Failed to open '/sys/fs/smackfs/cipso2': %m"); return -errno; /* negative error */ } /* write rules to cipso2 from every file in the directory */ dir = opendir(srcdir); if (!dir) { if (errno != ENOENT) log_warning_errno(errno, "Failed to opendir '%s': %m", srcdir); return errno; /* positive on purpose */ } dfd = dirfd(dir); assert(dfd >= 0); FOREACH_DIRENT(entry, dir, return 0) { int fd; _cleanup_fclose_ FILE *policy = NULL; if (!dirent_is_file(entry)) continue; fd = openat(dfd, entry->d_name, O_RDONLY|O_CLOEXEC); if (fd < 0) { if (r == 0) r = -errno; log_error_errno(errno, "Failed to open '%s': %m", entry->d_name); continue; } policy = fdopen(fd, "re"); if (!policy) { if (r == 0) r = -errno; safe_close(fd); log_error_errno(errno, "Failed to open '%s': %m", entry->d_name); continue; } /* cipso2 write rules in the kernel require a line buffered stream */ FOREACH_LINE(buf, policy, log_error_errno(errno, "Failed to read line from '%s': %m", entry->d_name)) { if (isempty(truncate_nl(buf))) continue; if (write(cipso2_fd, buf, strlen(buf)) < 0) { if (r == 0) r = -errno; log_error_errno(errno, "Failed to write '%s' to '/sys/fs/smackfs/cipso2' in '%s'", buf, entry->d_name); break; } } } return r; } static int write_netlabel_rules(const char* srcdir) { _cleanup_fclose_ FILE *dst = NULL; _cleanup_closedir_ DIR *dir = NULL; struct dirent *entry; char buf[NAME_MAX]; int dfd = -1; int r = 0; dst = fopen("/sys/fs/smackfs/netlabel", "we"); if (!dst) { if (errno != ENOENT) log_warning_errno(errno, "Failed to open /sys/fs/smackfs/netlabel: %m"); return -errno; /* negative error */ } /* write rules to dst from every file in the directory */ dir = opendir(srcdir); if (!dir) { if (errno != ENOENT) log_warning_errno(errno, "Failed to opendir %s: %m", srcdir); return errno; /* positive on purpose */ } dfd = dirfd(dir); assert(dfd >= 0); FOREACH_DIRENT(entry, dir, return 0) { int fd; _cleanup_fclose_ FILE *policy = NULL; fd = openat(dfd, entry->d_name, O_RDONLY|O_CLOEXEC); if (fd < 0) { if (r == 0) r = -errno; log_warning_errno(errno, "Failed to open %s: %m", entry->d_name); continue; } policy = fdopen(fd, "re"); if (!policy) { if (r == 0) r = -errno; safe_close(fd); log_error_errno(errno, "Failed to open %s: %m", entry->d_name); continue; } /* load2 write rules in the kernel require a line buffered stream */ FOREACH_LINE(buf, policy, log_error_errno(errno, "Failed to read line from %s: %m", entry->d_name)) { if (!fputs(buf, dst)) { if (r == 0) r = -EINVAL; log_error_errno(errno, "Failed to write line to /sys/fs/smackfs/netlabel"); break; } if (fflush(dst)) { if (r == 0) r = -errno; log_error_errno(errno, "Failed to flush writes to /sys/fs/smackfs/netlabel: %m"); break; } } } return r; } #endif int mac_smack_setup(bool *loaded_policy) { #ifdef HAVE_SMACK int r; assert(loaded_policy); r = write_access2_rules("/etc/smack/accesses.d/"); switch(r) { case -ENOENT: log_debug("Smack is not enabled in the kernel."); return 0; case ENOENT: log_debug("Smack access rules directory '/etc/smack/accesses.d/' not found"); return 0; case 0: log_info("Successfully loaded Smack policies."); break; default: log_warning_errno(r, "Failed to load Smack access rules, ignoring: %m"); return 0; } #ifdef SMACK_RUN_LABEL r = write_string_file("/proc/self/attr/current", SMACK_RUN_LABEL, 0); if (r < 0) log_warning_errno(r, "Failed to set SMACK label \"" SMACK_RUN_LABEL "\" on self: %m"); r = write_string_file("/sys/fs/smackfs/ambient", SMACK_RUN_LABEL, 0); if (r < 0) log_warning_errno(r, "Failed to set SMACK ambient label \"" SMACK_RUN_LABEL "\": %m"); r = write_string_file("/sys/fs/smackfs/netlabel", "0.0.0.0/0 " SMACK_RUN_LABEL, 0); if (r < 0) log_warning_errno(r, "Failed to set SMACK netlabel rule \"0.0.0.0/0 " SMACK_RUN_LABEL "\": %m"); r = write_string_file("/sys/fs/smackfs/netlabel", "127.0.0.1 -CIPSO", 0); if (r < 0) log_warning_errno(r, "Failed to set SMACK netlabel rule \"127.0.0.1 -CIPSO\": %m"); #endif r = write_cipso2_rules("/etc/smack/cipso.d/"); switch(r) { case -ENOENT: log_debug("Smack/CIPSO is not enabled in the kernel."); return 0; case ENOENT: log_debug("Smack/CIPSO access rules directory '/etc/smack/cipso.d/' not found"); break; case 0: log_info("Successfully loaded Smack/CIPSO policies."); break; default: log_warning_errno(r, "Failed to load Smack/CIPSO access rules, ignoring: %m"); break; } r = write_netlabel_rules("/etc/smack/netlabel.d/"); switch(r) { case -ENOENT: log_debug("Smack/CIPSO is not enabled in the kernel."); return 0; case ENOENT: log_debug("Smack network host rules directory '/etc/smack/netlabel.d/' not found"); break; case 0: log_info("Successfully loaded Smack network host rules."); break; default: log_warning_errno(r, "Failed to load Smack network host rules: %m, ignoring."); break; } *loaded_policy = true; #endif return 0; } systemd-229/src/core/smack-setup.h000066400000000000000000000015111265713322000172030ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2013 Intel Corporation Authors: Nathaniel Chen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int mac_smack_setup(bool *loaded_policy); systemd-229/src/core/socket.c000066400000000000000000002641051265713322000162440ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include "sd-event.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "copy.h" #include "dbus-socket.h" #include "def.h" #include "exit-status.h" #include "fd-util.h" #include "formats-util.h" #include "label.h" #include "log.h" #include "missing.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "selinux-util.h" #include "signal-util.h" #include "smack-util.h" #include "socket.h" #include "special.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "unit-printf.h" #include "unit.h" #include "user-util.h" static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = { [SOCKET_DEAD] = UNIT_INACTIVE, [SOCKET_START_PRE] = UNIT_ACTIVATING, [SOCKET_START_CHOWN] = UNIT_ACTIVATING, [SOCKET_START_POST] = UNIT_ACTIVATING, [SOCKET_LISTENING] = UNIT_ACTIVE, [SOCKET_RUNNING] = UNIT_ACTIVE, [SOCKET_STOP_PRE] = UNIT_DEACTIVATING, [SOCKET_STOP_PRE_SIGTERM] = UNIT_DEACTIVATING, [SOCKET_STOP_PRE_SIGKILL] = UNIT_DEACTIVATING, [SOCKET_STOP_POST] = UNIT_DEACTIVATING, [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING, [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING, [SOCKET_FAILED] = UNIT_FAILED }; static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); static void socket_init(Unit *u) { Socket *s = SOCKET(u); assert(u); assert(u->load_state == UNIT_STUB); s->backlog = SOMAXCONN; s->timeout_usec = u->manager->default_timeout_start_usec; s->directory_mode = 0755; s->socket_mode = 0666; s->max_connections = 64; s->priority = -1; s->ip_tos = -1; s->ip_ttl = -1; s->mark = -1; s->exec_context.std_output = u->manager->default_std_output; s->exec_context.std_error = u->manager->default_std_error; s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID; } static void socket_unwatch_control_pid(Socket *s) { assert(s); if (s->control_pid <= 0) return; unit_unwatch_pid(UNIT(s), s->control_pid); s->control_pid = 0; } static void socket_cleanup_fd_list(SocketPort *p) { assert(p); close_many(p->auxiliary_fds, p->n_auxiliary_fds); p->auxiliary_fds = mfree(p->auxiliary_fds); p->n_auxiliary_fds = 0; } void socket_free_ports(Socket *s) { SocketPort *p; assert(s); while ((p = s->ports)) { LIST_REMOVE(port, s->ports, p); sd_event_source_unref(p->event_source); socket_cleanup_fd_list(p); safe_close(p->fd); free(p->path); free(p); } } static void socket_done(Unit *u) { Socket *s = SOCKET(u); assert(s); socket_free_ports(s); s->exec_runtime = exec_runtime_unref(s->exec_runtime); exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX); s->control_command = NULL; socket_unwatch_control_pid(s); unit_ref_unset(&s->service); s->tcp_congestion = mfree(s->tcp_congestion); s->bind_to_device = mfree(s->bind_to_device); s->smack = mfree(s->smack); s->smack_ip_in = mfree(s->smack_ip_in); s->smack_ip_out = mfree(s->smack_ip_out); strv_free(s->symlinks); s->user = mfree(s->user); s->group = mfree(s->group); s->fdname = mfree(s->fdname); s->timer_event_source = sd_event_source_unref(s->timer_event_source); } static int socket_arm_timer(Socket *s, usec_t usec) { int r; assert(s); if (s->timer_event_source) { r = sd_event_source_set_time(s->timer_event_source, usec); if (r < 0) return r; return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); } if (usec == USEC_INFINITY) return 0; r = sd_event_add_time( UNIT(s)->manager->event, &s->timer_event_source, CLOCK_MONOTONIC, usec, 0, socket_dispatch_timer, s); if (r < 0) return r; (void) sd_event_source_set_description(s->timer_event_source, "socket-timer"); return 0; } int socket_instantiate_service(Socket *s) { _cleanup_free_ char *prefix = NULL, *name = NULL; int r; Unit *u; assert(s); /* This fills in s->service if it isn't filled in yet. For * Accept=yes sockets we create the next connection service * here. For Accept=no this is mostly a NOP since the service * is figured out at load time anyway. */ if (UNIT_DEREF(s->service)) return 0; if (!s->accept) return 0; r = unit_name_to_prefix(UNIT(s)->id, &prefix); if (r < 0) return r; if (asprintf(&name, "%s@%u.service", prefix, s->n_accepted) < 0) return -ENOMEM; r = manager_load_unit(UNIT(s)->manager, name, NULL, NULL, &u); if (r < 0) return r; u->no_gc = true; unit_ref_set(&s->service, u); return unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, u, false); } static bool have_non_accept_socket(Socket *s) { SocketPort *p; assert(s); if (!s->accept) return true; LIST_FOREACH(port, p, s->ports) { if (p->type != SOCKET_SOCKET) return true; if (!socket_address_can_accept(&p->address)) return true; } return false; } static int socket_add_mount_links(Socket *s) { SocketPort *p; int r; assert(s); LIST_FOREACH(port, p, s->ports) { const char *path = NULL; if (p->type == SOCKET_SOCKET) path = socket_address_get_path(&p->address); else if (IN_SET(p->type, SOCKET_FIFO, SOCKET_SPECIAL, SOCKET_USB_FUNCTION)) path = p->path; if (!path) continue; r = unit_require_mounts_for(UNIT(s), path); if (r < 0) return r; } return 0; } static int socket_add_device_link(Socket *s) { char *t; assert(s); if (!s->bind_to_device || streq(s->bind_to_device, "lo")) return 0; t = strjoina("/sys/subsystem/net/devices/", s->bind_to_device); return unit_add_node_link(UNIT(s), t, false, UNIT_BINDS_TO); } static int socket_add_default_dependencies(Socket *s) { int r; assert(s); if (!UNIT(s)->default_dependencies) return 0; r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SOCKETS_TARGET, NULL, true); if (r < 0) return r; if (UNIT(s)->manager->running_as == MANAGER_SYSTEM) { r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true); if (r < 0) return r; } return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true); } _pure_ static bool socket_has_exec(Socket *s) { unsigned i; assert(s); for (i = 0; i < _SOCKET_EXEC_COMMAND_MAX; i++) if (s->exec_command[i]) return true; return false; } static int socket_add_extras(Socket *s) { Unit *u = UNIT(s); int r; assert(s); if (have_non_accept_socket(s)) { if (!UNIT_DEREF(s->service)) { Unit *x; r = unit_load_related_unit(u, ".service", &x); if (r < 0) return r; unit_ref_set(&s->service, x); } r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(s->service), true); if (r < 0) return r; } r = socket_add_mount_links(s); if (r < 0) return r; r = socket_add_device_link(s); if (r < 0) return r; r = unit_patch_contexts(u); if (r < 0) return r; if (socket_has_exec(s)) { r = unit_add_exec_dependencies(u, &s->exec_context); if (r < 0) return r; r = unit_set_default_slice(u); if (r < 0) return r; } r = socket_add_default_dependencies(s); if (r < 0) return r; return 0; } static const char *socket_find_symlink_target(Socket *s) { const char *found = NULL; SocketPort *p; LIST_FOREACH(port, p, s->ports) { const char *f = NULL; switch (p->type) { case SOCKET_FIFO: f = p->path; break; case SOCKET_SOCKET: if (p->address.sockaddr.un.sun_path[0] != 0) f = p->address.sockaddr.un.sun_path; break; default: break; } if (f) { if (found) return NULL; found = f; } } return found; } static int socket_verify(Socket *s) { assert(s); if (UNIT(s)->load_state != UNIT_LOADED) return 0; if (!s->ports) { log_unit_error(UNIT(s), "Unit lacks Listen setting. Refusing."); return -EINVAL; } if (s->accept && have_non_accept_socket(s)) { log_unit_error(UNIT(s), "Unit configured for accepting sockets, but sockets are non-accepting. Refusing."); return -EINVAL; } if (s->accept && s->max_connections <= 0) { log_unit_error(UNIT(s), "MaxConnection= setting too small. Refusing."); return -EINVAL; } if (s->accept && UNIT_DEREF(s->service)) { log_unit_error(UNIT(s), "Explicit service configuration for accepting socket units not supported. Refusing."); return -EINVAL; } if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) { log_unit_error(UNIT(s), "Unit has PAM enabled. Kill mode must be set to 'control-group'. Refusing."); return -EINVAL; } if (!strv_isempty(s->symlinks) && !socket_find_symlink_target(s)) { log_unit_error(UNIT(s), "Unit has symlinks set but none or more than one node in the file system. Refusing."); return -EINVAL; } return 0; } static int socket_load(Unit *u) { Socket *s = SOCKET(u); int r; assert(u); assert(u->load_state == UNIT_STUB); r = unit_load_fragment_and_dropin(u); if (r < 0) return r; if (u->load_state == UNIT_LOADED) { /* This is a new unit? Then let's add in some extras */ r = socket_add_extras(s); if (r < 0) return r; } return socket_verify(s); } _const_ static const char* listen_lookup(int family, int type) { if (family == AF_NETLINK) return "ListenNetlink"; if (type == SOCK_STREAM) return "ListenStream"; else if (type == SOCK_DGRAM) return "ListenDatagram"; else if (type == SOCK_SEQPACKET) return "ListenSequentialPacket"; assert_not_reached("Unknown socket type"); return NULL; } static void socket_dump(Unit *u, FILE *f, const char *prefix) { char time_string[FORMAT_TIMESPAN_MAX]; SocketExecCommand c; Socket *s = SOCKET(u); SocketPort *p; const char *prefix2; assert(s); assert(f); prefix = strempty(prefix); prefix2 = strjoina(prefix, "\t"); fprintf(f, "%sSocket State: %s\n" "%sResult: %s\n" "%sBindIPv6Only: %s\n" "%sBacklog: %u\n" "%sSocketMode: %04o\n" "%sDirectoryMode: %04o\n" "%sKeepAlive: %s\n" "%sNoDelay: %s\n" "%sFreeBind: %s\n" "%sTransparent: %s\n" "%sBroadcast: %s\n" "%sPassCredentials: %s\n" "%sPassSecurity: %s\n" "%sTCPCongestion: %s\n" "%sRemoveOnStop: %s\n" "%sWritable: %s\n" "%sFDName: %s\n" "%sSELinuxContextFromNet: %s\n", prefix, socket_state_to_string(s->state), prefix, socket_result_to_string(s->result), prefix, socket_address_bind_ipv6_only_to_string(s->bind_ipv6_only), prefix, s->backlog, prefix, s->socket_mode, prefix, s->directory_mode, prefix, yes_no(s->keep_alive), prefix, yes_no(s->no_delay), prefix, yes_no(s->free_bind), prefix, yes_no(s->transparent), prefix, yes_no(s->broadcast), prefix, yes_no(s->pass_cred), prefix, yes_no(s->pass_sec), prefix, strna(s->tcp_congestion), prefix, yes_no(s->remove_on_stop), prefix, yes_no(s->writable), prefix, socket_fdname(s), prefix, yes_no(s->selinux_context_from_net)); if (s->control_pid > 0) fprintf(f, "%sControl PID: "PID_FMT"\n", prefix, s->control_pid); if (s->bind_to_device) fprintf(f, "%sBindToDevice: %s\n", prefix, s->bind_to_device); if (s->accept) fprintf(f, "%sAccepted: %u\n" "%sNConnections: %u\n" "%sMaxConnections: %u\n", prefix, s->n_accepted, prefix, s->n_connections, prefix, s->max_connections); if (s->priority >= 0) fprintf(f, "%sPriority: %i\n", prefix, s->priority); if (s->receive_buffer > 0) fprintf(f, "%sReceiveBuffer: %zu\n", prefix, s->receive_buffer); if (s->send_buffer > 0) fprintf(f, "%sSendBuffer: %zu\n", prefix, s->send_buffer); if (s->ip_tos >= 0) fprintf(f, "%sIPTOS: %i\n", prefix, s->ip_tos); if (s->ip_ttl >= 0) fprintf(f, "%sIPTTL: %i\n", prefix, s->ip_ttl); if (s->pipe_size > 0) fprintf(f, "%sPipeSize: %zu\n", prefix, s->pipe_size); if (s->mark >= 0) fprintf(f, "%sMark: %i\n", prefix, s->mark); if (s->mq_maxmsg > 0) fprintf(f, "%sMessageQueueMaxMessages: %li\n", prefix, s->mq_maxmsg); if (s->mq_msgsize > 0) fprintf(f, "%sMessageQueueMessageSize: %li\n", prefix, s->mq_msgsize); if (s->reuse_port) fprintf(f, "%sReusePort: %s\n", prefix, yes_no(s->reuse_port)); if (s->smack) fprintf(f, "%sSmackLabel: %s\n", prefix, s->smack); if (s->smack_ip_in) fprintf(f, "%sSmackLabelIPIn: %s\n", prefix, s->smack_ip_in); if (s->smack_ip_out) fprintf(f, "%sSmackLabelIPOut: %s\n", prefix, s->smack_ip_out); if (!isempty(s->user) || !isempty(s->group)) fprintf(f, "%sOwnerUser: %s\n" "%sOwnerGroup: %s\n", prefix, strna(s->user), prefix, strna(s->group)); if (s->keep_alive_time > 0) fprintf(f, "%sKeepAliveTimeSec: %s\n", prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->keep_alive_time, USEC_PER_SEC)); if (s->keep_alive_interval) fprintf(f, "%sKeepAliveIntervalSec: %s\n", prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->keep_alive_interval, USEC_PER_SEC)); if (s->keep_alive_cnt) fprintf(f, "%sKeepAliveProbes: %u\n", prefix, s->keep_alive_cnt); if (s->defer_accept) fprintf(f, "%sDeferAcceptSec: %s\n", prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->defer_accept, USEC_PER_SEC)); LIST_FOREACH(port, p, s->ports) { if (p->type == SOCKET_SOCKET) { const char *t; int r; char *k = NULL; r = socket_address_print(&p->address, &k); if (r < 0) t = strerror(-r); else t = k; fprintf(f, "%s%s: %s\n", prefix, listen_lookup(socket_address_family(&p->address), p->address.type), t); free(k); } else if (p->type == SOCKET_SPECIAL) fprintf(f, "%sListenSpecial: %s\n", prefix, p->path); else if (p->type == SOCKET_USB_FUNCTION) fprintf(f, "%sListenUSBFunction: %s\n", prefix, p->path); else if (p->type == SOCKET_MQUEUE) fprintf(f, "%sListenMessageQueue: %s\n", prefix, p->path); else fprintf(f, "%sListenFIFO: %s\n", prefix, p->path); } exec_context_dump(&s->exec_context, f, prefix); kill_context_dump(&s->kill_context, f, prefix); for (c = 0; c < _SOCKET_EXEC_COMMAND_MAX; c++) { if (!s->exec_command[c]) continue; fprintf(f, "%s-> %s:\n", prefix, socket_exec_command_to_string(c)); exec_command_dump_list(s->exec_command[c], f, prefix2); } } static int instance_from_socket(int fd, unsigned nr, char **instance) { socklen_t l; char *r; union sockaddr_union local, remote; assert(fd >= 0); assert(instance); l = sizeof(local); if (getsockname(fd, &local.sa, &l) < 0) return -errno; l = sizeof(remote); if (getpeername(fd, &remote.sa, &l) < 0) return -errno; switch (local.sa.sa_family) { case AF_INET: { uint32_t a = ntohl(local.in.sin_addr.s_addr), b = ntohl(remote.in.sin_addr.s_addr); if (asprintf(&r, "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u", nr, a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF, ntohs(local.in.sin_port), b >> 24, (b >> 16) & 0xFF, (b >> 8) & 0xFF, b & 0xFF, ntohs(remote.in.sin_port)) < 0) return -ENOMEM; break; } case AF_INET6: { static const unsigned char ipv4_prefix[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF }; if (memcmp(&local.in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0 && memcmp(&remote.in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) { const uint8_t *a = local.in6.sin6_addr.s6_addr+12, *b = remote.in6.sin6_addr.s6_addr+12; if (asprintf(&r, "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u", nr, a[0], a[1], a[2], a[3], ntohs(local.in6.sin6_port), b[0], b[1], b[2], b[3], ntohs(remote.in6.sin6_port)) < 0) return -ENOMEM; } else { char a[INET6_ADDRSTRLEN], b[INET6_ADDRSTRLEN]; if (asprintf(&r, "%u-%s:%u-%s:%u", nr, inet_ntop(AF_INET6, &local.in6.sin6_addr, a, sizeof(a)), ntohs(local.in6.sin6_port), inet_ntop(AF_INET6, &remote.in6.sin6_addr, b, sizeof(b)), ntohs(remote.in6.sin6_port)) < 0) return -ENOMEM; } break; } case AF_UNIX: { struct ucred ucred; int k; k = getpeercred(fd, &ucred); if (k >= 0) { if (asprintf(&r, "%u-"PID_FMT"-"UID_FMT, nr, ucred.pid, ucred.uid) < 0) return -ENOMEM; } else if (k == -ENODATA) { /* This handles the case where somebody is * connecting from another pid/uid namespace * (e.g. from outside of our container). */ if (asprintf(&r, "%u-unknown", nr) < 0) return -ENOMEM; } else return k; break; } default: assert_not_reached("Unhandled socket type."); } *instance = r; return 0; } static void socket_close_fds(Socket *s) { SocketPort *p; char **i; assert(s); LIST_FOREACH(port, p, s->ports) { p->event_source = sd_event_source_unref(p->event_source); if (p->fd < 0) continue; p->fd = safe_close(p->fd); socket_cleanup_fd_list(p); /* One little note: we should normally not delete any * sockets in the file system here! After all some * other process we spawned might still have a * reference of this fd and wants to continue to use * it. Therefore we delete sockets in the file system * before we create a new one, not after we stopped * using one! */ if (s->remove_on_stop) { switch (p->type) { case SOCKET_FIFO: unlink(p->path); break; case SOCKET_MQUEUE: mq_unlink(p->path); break; case SOCKET_SOCKET: socket_address_unlink(&p->address); break; default: break; } } } if (s->remove_on_stop) STRV_FOREACH(i, s->symlinks) unlink(*i); } static void socket_apply_socket_options(Socket *s, int fd) { int r; assert(s); assert(fd >= 0); if (s->keep_alive) { int b = s->keep_alive; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &b, sizeof(b)) < 0) log_unit_warning_errno(UNIT(s), errno, "SO_KEEPALIVE failed: %m"); } if (s->keep_alive_time) { int value = s->keep_alive_time / USEC_PER_SEC; if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &value, sizeof(value)) < 0) log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPIDLE failed: %m"); } if (s->keep_alive_interval) { int value = s->keep_alive_interval / USEC_PER_SEC; if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &value, sizeof(value)) < 0) log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPINTVL failed: %m"); } if (s->keep_alive_cnt) { int value = s->keep_alive_cnt; if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &value, sizeof(value)) < 0) log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPCNT failed: %m"); } if (s->defer_accept) { int value = s->defer_accept / USEC_PER_SEC; if (setsockopt(fd, SOL_TCP, TCP_DEFER_ACCEPT, &value, sizeof(value)) < 0) log_unit_warning_errno(UNIT(s), errno, "TCP_DEFER_ACCEPT failed: %m"); } if (s->no_delay) { int b = s->no_delay; if (s->socket_protocol == IPPROTO_SCTP) { if (setsockopt(fd, SOL_SCTP, SCTP_NODELAY, &b, sizeof(b)) < 0) log_unit_warning_errno(UNIT(s), errno, "SCTP_NODELAY failed: %m"); } else { if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &b, sizeof(b)) < 0) log_unit_warning_errno(UNIT(s), errno, "TCP_NODELAY failed: %m"); } } if (s->broadcast) { int one = 1; if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) < 0) log_unit_warning_errno(UNIT(s), errno, "SO_BROADCAST failed: %m"); } if (s->pass_cred) { int one = 1; if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) log_unit_warning_errno(UNIT(s), errno, "SO_PASSCRED failed: %m"); } if (s->pass_sec) { int one = 1; if (setsockopt(fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one)) < 0) log_unit_warning_errno(UNIT(s), errno, "SO_PASSSEC failed: %m"); } if (s->priority >= 0) if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &s->priority, sizeof(s->priority)) < 0) log_unit_warning_errno(UNIT(s), errno, "SO_PRIORITY failed: %m"); if (s->receive_buffer > 0) { int value = (int) s->receive_buffer; /* We first try with SO_RCVBUFFORCE, in case we have the perms for that */ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0) if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0) log_unit_warning_errno(UNIT(s), errno, "SO_RCVBUF failed: %m"); } if (s->send_buffer > 0) { int value = (int) s->send_buffer; if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0) if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0) log_unit_warning_errno(UNIT(s), errno, "SO_SNDBUF failed: %m"); } if (s->mark >= 0) if (setsockopt(fd, SOL_SOCKET, SO_MARK, &s->mark, sizeof(s->mark)) < 0) log_unit_warning_errno(UNIT(s), errno, "SO_MARK failed: %m"); if (s->ip_tos >= 0) if (setsockopt(fd, IPPROTO_IP, IP_TOS, &s->ip_tos, sizeof(s->ip_tos)) < 0) log_unit_warning_errno(UNIT(s), errno, "IP_TOS failed: %m"); if (s->ip_ttl >= 0) { int x; r = setsockopt(fd, IPPROTO_IP, IP_TTL, &s->ip_ttl, sizeof(s->ip_ttl)); if (socket_ipv6_is_supported()) x = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &s->ip_ttl, sizeof(s->ip_ttl)); else { x = -1; errno = EAFNOSUPPORT; } if (r < 0 && x < 0) log_unit_warning_errno(UNIT(s), errno, "IP_TTL/IPV6_UNICAST_HOPS failed: %m"); } if (s->tcp_congestion) if (setsockopt(fd, SOL_TCP, TCP_CONGESTION, s->tcp_congestion, strlen(s->tcp_congestion)+1) < 0) log_unit_warning_errno(UNIT(s), errno, "TCP_CONGESTION failed: %m"); if (s->smack_ip_in) { r = mac_smack_apply_fd(fd, SMACK_ATTR_IPIN, s->smack_ip_in); if (r < 0) log_unit_error_errno(UNIT(s), r, "mac_smack_apply_ip_in_fd: %m"); } if (s->smack_ip_out) { r = mac_smack_apply_fd(fd, SMACK_ATTR_IPOUT, s->smack_ip_out); if (r < 0) log_unit_error_errno(UNIT(s), r, "mac_smack_apply_ip_out_fd: %m"); } } static void socket_apply_fifo_options(Socket *s, int fd) { int r; assert(s); assert(fd >= 0); if (s->pipe_size > 0) if (fcntl(fd, F_SETPIPE_SZ, s->pipe_size) < 0) log_unit_warning_errno(UNIT(s), errno, "Setting pipe size failed, ignoring: %m"); if (s->smack) { r = mac_smack_apply_fd(fd, SMACK_ATTR_ACCESS, s->smack); if (r < 0) log_unit_error_errno(UNIT(s), r, "SMACK relabelling failed, ignoring: %m"); } } static int fifo_address_create( const char *path, mode_t directory_mode, mode_t socket_mode) { _cleanup_close_ int fd = -1; mode_t old_mask; struct stat st; int r; assert(path); mkdir_parents_label(path, directory_mode); r = mac_selinux_create_file_prepare(path, S_IFIFO); if (r < 0) return r; /* Enforce the right access mode for the fifo */ old_mask = umask(~ socket_mode); /* Include the original umask in our mask */ (void) umask(~socket_mode | old_mask); r = mkfifo(path, socket_mode); (void) umask(old_mask); if (r < 0 && errno != EEXIST) { r = -errno; goto fail; } fd = open(path, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK | O_NOFOLLOW); if (fd < 0) { r = -errno; goto fail; } mac_selinux_create_file_clear(); if (fstat(fd, &st) < 0) { r = -errno; goto fail; } if (!S_ISFIFO(st.st_mode) || (st.st_mode & 0777) != (socket_mode & ~old_mask) || st.st_uid != getuid() || st.st_gid != getgid()) { r = -EEXIST; goto fail; } r = fd; fd = -1; return r; fail: mac_selinux_create_file_clear(); return r; } static int special_address_create(const char *path, bool writable) { _cleanup_close_ int fd = -1; struct stat st; int r; assert(path); fd = open(path, (writable ? O_RDWR : O_RDONLY)|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW); if (fd < 0) return -errno; if (fstat(fd, &st) < 0) return -errno; /* Check whether this is a /proc, /sys or /dev file or char device */ if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) return -EEXIST; r = fd; fd = -1; return r; } static int usbffs_address_create(const char *path) { _cleanup_close_ int fd = -1; struct stat st; int r; assert(path); fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW); if (fd < 0) return -errno; if (fstat(fd, &st) < 0) return -errno; /* Check whether this is a regular file (ffs endpoint)*/ if (!S_ISREG(st.st_mode)) return -EEXIST; r = fd; fd = -1; return r; } static int mq_address_create( const char *path, mode_t mq_mode, long maxmsg, long msgsize) { _cleanup_close_ int fd = -1; struct stat st; mode_t old_mask; struct mq_attr _attr, *attr = NULL; int r; assert(path); if (maxmsg > 0 && msgsize > 0) { _attr = (struct mq_attr) { .mq_flags = O_NONBLOCK, .mq_maxmsg = maxmsg, .mq_msgsize = msgsize, }; attr = &_attr; } /* Enforce the right access mode for the mq */ old_mask = umask(~ mq_mode); /* Include the original umask in our mask */ (void) umask(~mq_mode | old_mask); fd = mq_open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_CREAT, mq_mode, attr); (void) umask(old_mask); if (fd < 0) return -errno; if (fstat(fd, &st) < 0) return -errno; if ((st.st_mode & 0777) != (mq_mode & ~old_mask) || st.st_uid != getuid() || st.st_gid != getgid()) return -EEXIST; r = fd; fd = -1; return r; } static int socket_symlink(Socket *s) { const char *p; char **i; assert(s); p = socket_find_symlink_target(s); if (!p) return 0; STRV_FOREACH(i, s->symlinks) symlink_label(p, *i); return 0; } static int usbffs_write_descs(int fd, Service *s) { int r; if (!s->usb_function_descriptors || !s->usb_function_strings) return -EINVAL; r = copy_file_fd(s->usb_function_descriptors, fd, false); if (r < 0) return r; return copy_file_fd(s->usb_function_strings, fd, false); } static int usbffs_select_ep(const struct dirent *d) { return d->d_name[0] != '.' && !streq(d->d_name, "ep0"); } static int usbffs_dispatch_eps(SocketPort *p) { _cleanup_free_ struct dirent **ent = NULL; _cleanup_free_ char *path = NULL; int r, i, n, k; path = dirname_malloc(p->path); if (!path) return -ENOMEM; r = scandir(path, &ent, usbffs_select_ep, alphasort); if (r < 0) return -errno; n = r; p->auxiliary_fds = new(int, n); if (!p->auxiliary_fds) return -ENOMEM; p->n_auxiliary_fds = n; k = 0; for (i = 0; i < n; ++i) { _cleanup_free_ char *ep = NULL; ep = path_make_absolute(ent[i]->d_name, path); if (!ep) return -ENOMEM; path_kill_slashes(ep); r = usbffs_address_create(ep); if (r < 0) goto fail; p->auxiliary_fds[k] = r; ++k; free(ent[i]); } return r; fail: close_many(p->auxiliary_fds, k); p->auxiliary_fds = mfree(p->auxiliary_fds); p->n_auxiliary_fds = 0; return r; } static int socket_open_fds(Socket *s) { _cleanup_(mac_selinux_freep) char *label = NULL; bool know_label = false; SocketPort *p; int r; assert(s); LIST_FOREACH(port, p, s->ports) { if (p->fd >= 0) continue; switch (p->type) { case SOCKET_SOCKET: if (!know_label) { /* Figure out label, if we don't it know * yet. We do it once, for the first * socket where we need this and * remember it for the rest. */ if (s->selinux_context_from_net) { /* Get it from the network label */ r = mac_selinux_get_our_label(&label); if (r < 0 && r != -EOPNOTSUPP) goto rollback; } else { /* Get it from the executable we are about to start */ r = socket_instantiate_service(s); if (r < 0) goto rollback; if (UNIT_ISSET(s->service) && SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START]) { r = mac_selinux_get_create_label_from_exe(SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START]->path, &label); if (r < 0 && r != -EPERM && r != -EOPNOTSUPP) goto rollback; } } know_label = true; } /* Apply the socket protocol */ switch(p->address.type) { case SOCK_STREAM: case SOCK_SEQPACKET: if (p->socket->socket_protocol == IPPROTO_SCTP) p->address.protocol = p->socket->socket_protocol; break; case SOCK_DGRAM: if (p->socket->socket_protocol == IPPROTO_UDPLITE) p->address.protocol = p->socket->socket_protocol; break; } r = socket_address_listen( &p->address, SOCK_CLOEXEC|SOCK_NONBLOCK, s->backlog, s->bind_ipv6_only, s->bind_to_device, s->reuse_port, s->free_bind, s->transparent, s->directory_mode, s->socket_mode, label); if (r < 0) goto rollback; p->fd = r; socket_apply_socket_options(s, p->fd); socket_symlink(s); break; case SOCKET_SPECIAL: p->fd = special_address_create(p->path, s->writable); if (p->fd < 0) { r = p->fd; goto rollback; } break; case SOCKET_FIFO: p->fd = fifo_address_create( p->path, s->directory_mode, s->socket_mode); if (p->fd < 0) { r = p->fd; goto rollback; } socket_apply_fifo_options(s, p->fd); socket_symlink(s); break; case SOCKET_MQUEUE: p->fd = mq_address_create( p->path, s->socket_mode, s->mq_maxmsg, s->mq_msgsize); if (p->fd < 0) { r = p->fd; goto rollback; } break; case SOCKET_USB_FUNCTION: p->fd = usbffs_address_create(p->path); if (p->fd < 0) { r = p->fd; goto rollback; } r = usbffs_write_descs(p->fd, SERVICE(UNIT_DEREF(s->service))); if (r < 0) goto rollback; r = usbffs_dispatch_eps(p); if (r < 0) goto rollback; break; default: assert_not_reached("Unknown port type"); } } return 0; rollback: socket_close_fds(s); return r; } static void socket_unwatch_fds(Socket *s) { SocketPort *p; int r; assert(s); LIST_FOREACH(port, p, s->ports) { if (p->fd < 0) continue; if (!p->event_source) continue; r = sd_event_source_set_enabled(p->event_source, SD_EVENT_OFF); if (r < 0) log_unit_debug_errno(UNIT(s), r, "Failed to disable event source: %m"); } } static int socket_watch_fds(Socket *s) { SocketPort *p; int r; assert(s); LIST_FOREACH(port, p, s->ports) { if (p->fd < 0) continue; if (p->event_source) { r = sd_event_source_set_enabled(p->event_source, SD_EVENT_ON); if (r < 0) goto fail; } else { r = sd_event_add_io(UNIT(s)->manager->event, &p->event_source, p->fd, EPOLLIN, socket_dispatch_io, p); if (r < 0) goto fail; (void) sd_event_source_set_description(p->event_source, "socket-port-io"); } } return 0; fail: log_unit_warning_errno(UNIT(s), r, "Failed to watch listening fds: %m"); socket_unwatch_fds(s); return r; } static void socket_set_state(Socket *s, SocketState state) { SocketState old_state; assert(s); old_state = s->state; s->state = state; if (!IN_SET(state, SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM, SOCKET_FINAL_SIGKILL)) { s->timer_event_source = sd_event_source_unref(s->timer_event_source); socket_unwatch_control_pid(s); s->control_command = NULL; s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID; } if (state != SOCKET_LISTENING) socket_unwatch_fds(s); if (!IN_SET(state, SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING, SOCKET_RUNNING, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL)) socket_close_fds(s); if (state != old_state) log_unit_debug(UNIT(s), "Changed %s -> %s", socket_state_to_string(old_state), socket_state_to_string(state)); unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true); } static int socket_coldplug(Unit *u) { Socket *s = SOCKET(u); int r; assert(s); assert(s->state == SOCKET_DEAD); if (s->deserialized_state == s->state) return 0; if (s->control_pid > 0 && pid_is_unwaited(s->control_pid) && IN_SET(s->deserialized_state, SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM, SOCKET_FINAL_SIGKILL)) { r = unit_watch_pid(UNIT(s), s->control_pid); if (r < 0) return r; r = socket_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec)); if (r < 0) return r; } if (IN_SET(s->deserialized_state, SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING, SOCKET_RUNNING, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL)) { r = socket_open_fds(s); if (r < 0) return r; } if (s->deserialized_state == SOCKET_LISTENING) { r = socket_watch_fds(s); if (r < 0) return r; } socket_set_state(s, s->deserialized_state); return 0; } static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) { _cleanup_free_ char **argv = NULL; pid_t pid; int r; ExecParameters exec_params = { .apply_permissions = true, .apply_chroot = true, .apply_tty_stdin = true, .bus_endpoint_fd = -1, .stdin_fd = -1, .stdout_fd = -1, .stderr_fd = -1, }; assert(s); assert(c); assert(_pid); (void) unit_realize_cgroup(UNIT(s)); if (s->reset_cpu_usage) { (void) unit_reset_cpu_usage(UNIT(s)); s->reset_cpu_usage = false; } r = unit_setup_exec_runtime(UNIT(s)); if (r < 0) return r; r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec)); if (r < 0) return r; r = unit_full_printf_strv(UNIT(s), c->argv, &argv); if (r < 0) return r; exec_params.argv = argv; exec_params.environment = UNIT(s)->manager->environment; exec_params.confirm_spawn = UNIT(s)->manager->confirm_spawn; exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported; exec_params.cgroup_path = UNIT(s)->cgroup_path; exec_params.cgroup_delegate = s->cgroup_context.delegate; exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager); r = exec_spawn(UNIT(s), c, &s->exec_context, &exec_params, s->exec_runtime, &pid); if (r < 0) return r; r = unit_watch_pid(UNIT(s), pid); if (r < 0) /* FIXME: we need to do something here */ return r; *_pid = pid; return 0; } static int socket_chown(Socket *s, pid_t *_pid) { pid_t pid; int r; r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec)); if (r < 0) goto fail; /* We have to resolve the user names out-of-process, hence * let's fork here. It's messy, but well, what can we do? */ pid = fork(); if (pid < 0) return -errno; if (pid == 0) { SocketPort *p; uid_t uid = UID_INVALID; gid_t gid = GID_INVALID; int ret; (void) default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE, -1); (void) ignore_signals(SIGPIPE, -1); log_forget_fds(); if (!isempty(s->user)) { const char *user = s->user; r = get_user_creds(&user, &uid, &gid, NULL, NULL); if (r < 0) { ret = EXIT_USER; goto fail_child; } } if (!isempty(s->group)) { const char *group = s->group; r = get_group_creds(&group, &gid); if (r < 0) { ret = EXIT_GROUP; goto fail_child; } } LIST_FOREACH(port, p, s->ports) { const char *path = NULL; if (p->type == SOCKET_SOCKET) path = socket_address_get_path(&p->address); else if (p->type == SOCKET_FIFO) path = p->path; if (!path) continue; if (chown(path, uid, gid) < 0) { r = -errno; ret = EXIT_CHOWN; goto fail_child; } } _exit(0); fail_child: log_open(); log_error_errno(r, "Failed to chown socket at step %s: %m", exit_status_to_string(ret, EXIT_STATUS_SYSTEMD)); _exit(ret); } r = unit_watch_pid(UNIT(s), pid); if (r < 0) goto fail; *_pid = pid; return 0; fail: s->timer_event_source = sd_event_source_unref(s->timer_event_source); return r; } static void socket_enter_dead(Socket *s, SocketResult f) { assert(s); if (f != SOCKET_SUCCESS) s->result = f; exec_runtime_destroy(s->exec_runtime); s->exec_runtime = exec_runtime_unref(s->exec_runtime); exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager)); socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD); } static void socket_enter_signal(Socket *s, SocketState state, SocketResult f); static void socket_enter_stop_post(Socket *s, SocketResult f) { int r; assert(s); if (f != SOCKET_SUCCESS) s->result = f; socket_unwatch_control_pid(s); s->control_command_id = SOCKET_EXEC_STOP_POST; s->control_command = s->exec_command[SOCKET_EXEC_STOP_POST]; if (s->control_command) { r = socket_spawn(s, s->control_command, &s->control_pid); if (r < 0) goto fail; socket_set_state(s, SOCKET_STOP_POST); } else socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_SUCCESS); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop-post' task: %m"); socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES); } static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) { int r; assert(s); if (f != SOCKET_SUCCESS) s->result = f; r = unit_kill_context( UNIT(s), &s->kill_context, (state != SOCKET_STOP_PRE_SIGTERM && state != SOCKET_FINAL_SIGTERM) ? KILL_KILL : KILL_TERMINATE, -1, s->control_pid, false); if (r < 0) goto fail; if (r > 0) { r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec)); if (r < 0) goto fail; socket_set_state(s, state); } else if (state == SOCKET_STOP_PRE_SIGTERM) socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, SOCKET_SUCCESS); else if (state == SOCKET_STOP_PRE_SIGKILL) socket_enter_stop_post(s, SOCKET_SUCCESS); else if (state == SOCKET_FINAL_SIGTERM) socket_enter_signal(s, SOCKET_FINAL_SIGKILL, SOCKET_SUCCESS); else socket_enter_dead(s, SOCKET_SUCCESS); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m"); if (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_STOP_PRE_SIGKILL) socket_enter_stop_post(s, SOCKET_FAILURE_RESOURCES); else socket_enter_dead(s, SOCKET_FAILURE_RESOURCES); } static void socket_enter_stop_pre(Socket *s, SocketResult f) { int r; assert(s); if (f != SOCKET_SUCCESS) s->result = f; socket_unwatch_control_pid(s); s->control_command_id = SOCKET_EXEC_STOP_PRE; s->control_command = s->exec_command[SOCKET_EXEC_STOP_PRE]; if (s->control_command) { r = socket_spawn(s, s->control_command, &s->control_pid); if (r < 0) goto fail; socket_set_state(s, SOCKET_STOP_PRE); } else socket_enter_stop_post(s, SOCKET_SUCCESS); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop-pre' task: %m"); socket_enter_stop_post(s, SOCKET_FAILURE_RESOURCES); } static void socket_enter_listening(Socket *s) { int r; assert(s); r = socket_watch_fds(s); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to watch sockets: %m"); goto fail; } socket_set_state(s, SOCKET_LISTENING); return; fail: socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); } static void socket_enter_start_post(Socket *s) { int r; assert(s); socket_unwatch_control_pid(s); s->control_command_id = SOCKET_EXEC_START_POST; s->control_command = s->exec_command[SOCKET_EXEC_START_POST]; if (s->control_command) { r = socket_spawn(s, s->control_command, &s->control_pid); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-post' task: %m"); goto fail; } socket_set_state(s, SOCKET_START_POST); } else socket_enter_listening(s); return; fail: socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); } static void socket_enter_start_chown(Socket *s) { int r; assert(s); r = socket_open_fds(s); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to listen on sockets: %m"); goto fail; } if (!isempty(s->user) || !isempty(s->group)) { socket_unwatch_control_pid(s); s->control_command_id = SOCKET_EXEC_START_CHOWN; s->control_command = NULL; r = socket_chown(s, &s->control_pid); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to fork 'start-chown' task: %m"); goto fail; } socket_set_state(s, SOCKET_START_CHOWN); } else socket_enter_start_post(s); return; fail: socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); } static void socket_enter_start_pre(Socket *s) { int r; assert(s); socket_unwatch_control_pid(s); s->control_command_id = SOCKET_EXEC_START_PRE; s->control_command = s->exec_command[SOCKET_EXEC_START_PRE]; if (s->control_command) { r = socket_spawn(s, s->control_command, &s->control_pid); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-pre' task: %m"); goto fail; } socket_set_state(s, SOCKET_START_PRE); } else socket_enter_start_chown(s); return; fail: socket_enter_dead(s, SOCKET_FAILURE_RESOURCES); } static void socket_enter_running(Socket *s, int cfd) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(s); /* We don't take connections anymore if we are supposed to * shut down anyway */ if (unit_stop_pending(UNIT(s))) { log_unit_debug(UNIT(s), "Suppressing connection request since unit stop is scheduled."); if (cfd >= 0) safe_close(cfd); else { /* Flush all sockets by closing and reopening them */ socket_close_fds(s); r = socket_open_fds(s); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to listen on sockets: %m"); socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); return; } r = socket_watch_fds(s); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to watch sockets: %m"); socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); } } return; } if (cfd < 0) { Iterator i; Unit *other; bool pending = false; /* If there's already a start pending don't bother to * do anything */ SET_FOREACH(other, UNIT(s)->dependencies[UNIT_TRIGGERS], i) if (unit_active_or_pending(other)) { pending = true; break; } if (!pending) { if (!UNIT_ISSET(s->service)) { log_unit_error(UNIT(s), "Service to activate vanished, refusing activation."); r = -ENOENT; goto fail; } r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, &error, NULL); if (r < 0) goto fail; } socket_set_state(s, SOCKET_RUNNING); } else { _cleanup_free_ char *prefix = NULL, *instance = NULL, *name = NULL; Service *service; if (s->n_connections >= s->max_connections) { log_unit_warning(UNIT(s), "Too many incoming connections (%u)", s->n_connections); safe_close(cfd); return; } r = socket_instantiate_service(s); if (r < 0) goto fail; r = instance_from_socket(cfd, s->n_accepted, &instance); if (r < 0) { if (r != -ENOTCONN) goto fail; /* ENOTCONN is legitimate if TCP RST was received. * This connection is over, but the socket unit lives on. */ safe_close(cfd); return; } r = unit_name_to_prefix(UNIT(s)->id, &prefix); if (r < 0) goto fail; r = unit_name_build(prefix, instance, ".service", &name); if (r < 0) goto fail; r = unit_add_name(UNIT_DEREF(s->service), name); if (r < 0) goto fail; service = SERVICE(UNIT_DEREF(s->service)); unit_ref_unset(&s->service); s->n_accepted ++; UNIT(service)->no_gc = false; unit_choose_id(UNIT(service), name); r = service_set_socket_fd(service, cfd, s, s->selinux_context_from_net); if (r < 0) goto fail; cfd = -1; s->n_connections ++; r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, &error, NULL); if (r < 0) goto fail; /* Notify clients about changed counters */ unit_add_to_dbus_queue(UNIT(s)); } return; fail: log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s", cfd >= 0 ? "template" : "non-template", bus_error_message(&error, r)); socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); safe_close(cfd); } static void socket_run_next(Socket *s) { int r; assert(s); assert(s->control_command); assert(s->control_command->command_next); socket_unwatch_control_pid(s); s->control_command = s->control_command->command_next; r = socket_spawn(s, s->control_command, &s->control_pid); if (r < 0) goto fail; return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run next task: %m"); if (s->state == SOCKET_START_POST) socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); else if (s->state == SOCKET_STOP_POST) socket_enter_dead(s, SOCKET_FAILURE_RESOURCES); else socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES); } static int socket_start(Unit *u) { Socket *s = SOCKET(u); assert(s); /* We cannot fulfill this request right now, try again later * please! */ if (IN_SET(s->state, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGKILL, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM, SOCKET_FINAL_SIGKILL)) return -EAGAIN; /* Already on it! */ if (IN_SET(s->state, SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST)) return 0; /* Cannot run this without the service being around */ if (UNIT_ISSET(s->service)) { Service *service; service = SERVICE(UNIT_DEREF(s->service)); if (UNIT(service)->load_state != UNIT_LOADED) { log_unit_error(u, "Socket service %s not loaded, refusing.", UNIT(service)->id); return -ENOENT; } /* If the service is already active we cannot start the * socket */ if (service->state != SERVICE_DEAD && service->state != SERVICE_FAILED && service->state != SERVICE_AUTO_RESTART) { log_unit_error(u, "Socket service %s already active, refusing.", UNIT(service)->id); return -EBUSY; } } assert(s->state == SOCKET_DEAD || s->state == SOCKET_FAILED); s->result = SOCKET_SUCCESS; s->reset_cpu_usage = true; socket_enter_start_pre(s); return 1; } static int socket_stop(Unit *u) { Socket *s = SOCKET(u); assert(s); /* Already on it */ if (IN_SET(s->state, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM, SOCKET_FINAL_SIGKILL)) return 0; /* If there's already something running we go directly into * kill mode. */ if (IN_SET(s->state, SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST)) { socket_enter_signal(s, SOCKET_STOP_PRE_SIGTERM, SOCKET_SUCCESS); return -EAGAIN; } assert(s->state == SOCKET_LISTENING || s->state == SOCKET_RUNNING); socket_enter_stop_pre(s, SOCKET_SUCCESS); return 1; } static int socket_serialize(Unit *u, FILE *f, FDSet *fds) { Socket *s = SOCKET(u); SocketPort *p; int r; assert(u); assert(f); assert(fds); unit_serialize_item(u, f, "state", socket_state_to_string(s->state)); unit_serialize_item(u, f, "result", socket_result_to_string(s->result)); unit_serialize_item_format(u, f, "n-accepted", "%u", s->n_accepted); if (s->control_pid > 0) unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid); if (s->control_command_id >= 0) unit_serialize_item(u, f, "control-command", socket_exec_command_to_string(s->control_command_id)); LIST_FOREACH(port, p, s->ports) { int copy; if (p->fd < 0) continue; copy = fdset_put_dup(fds, p->fd); if (copy < 0) return copy; if (p->type == SOCKET_SOCKET) { _cleanup_free_ char *t = NULL; r = socket_address_print(&p->address, &t); if (r < 0) return r; if (socket_address_family(&p->address) == AF_NETLINK) unit_serialize_item_format(u, f, "netlink", "%i %s", copy, t); else unit_serialize_item_format(u, f, "socket", "%i %i %s", copy, p->address.type, t); } else if (p->type == SOCKET_SPECIAL) unit_serialize_item_format(u, f, "special", "%i %s", copy, p->path); else if (p->type == SOCKET_MQUEUE) unit_serialize_item_format(u, f, "mqueue", "%i %s", copy, p->path); else if (p->type == SOCKET_USB_FUNCTION) unit_serialize_item_format(u, f, "ffs", "%i %s", copy, p->path); else { assert(p->type == SOCKET_FIFO); unit_serialize_item_format(u, f, "fifo", "%i %s", copy, p->path); } } return 0; } static int socket_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Socket *s = SOCKET(u); assert(u); assert(key); assert(value); if (streq(key, "state")) { SocketState state; state = socket_state_from_string(value); if (state < 0) log_unit_debug(u, "Failed to parse state value: %s", value); else s->deserialized_state = state; } else if (streq(key, "result")) { SocketResult f; f = socket_result_from_string(value); if (f < 0) log_unit_debug(u, "Failed to parse result value: %s", value); else if (f != SOCKET_SUCCESS) s->result = f; } else if (streq(key, "n-accepted")) { unsigned k; if (safe_atou(value, &k) < 0) log_unit_debug(u, "Failed to parse n-accepted value: %s", value); else s->n_accepted += k; } else if (streq(key, "control-pid")) { pid_t pid; if (parse_pid(value, &pid) < 0) log_unit_debug(u, "Failed to parse control-pid value: %s", value); else s->control_pid = pid; } else if (streq(key, "control-command")) { SocketExecCommand id; id = socket_exec_command_from_string(value); if (id < 0) log_unit_debug(u, "Failed to parse exec-command value: %s", value); else { s->control_command_id = id; s->control_command = s->exec_command[id]; } } else if (streq(key, "fifo")) { int fd, skip = 0; SocketPort *p; if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse fifo value: %s", value); else { LIST_FOREACH(port, p, s->ports) if (p->type == SOCKET_FIFO && path_equal_or_files_same(p->path, value+skip)) break; if (p) { safe_close(p->fd); p->fd = fdset_remove(fds, fd); } } } else if (streq(key, "special")) { int fd, skip = 0; SocketPort *p; if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse special value: %s", value); else { LIST_FOREACH(port, p, s->ports) if (p->type == SOCKET_SPECIAL && path_equal_or_files_same(p->path, value+skip)) break; if (p) { safe_close(p->fd); p->fd = fdset_remove(fds, fd); } } } else if (streq(key, "mqueue")) { int fd, skip = 0; SocketPort *p; if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse mqueue value: %s", value); else { LIST_FOREACH(port, p, s->ports) if (p->type == SOCKET_MQUEUE && streq(p->path, value+skip)) break; if (p) { safe_close(p->fd); p->fd = fdset_remove(fds, fd); } } } else if (streq(key, "socket")) { int fd, type, skip = 0; SocketPort *p; if (sscanf(value, "%i %i %n", &fd, &type, &skip) < 2 || fd < 0 || type < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse socket value: %s", value); else { LIST_FOREACH(port, p, s->ports) if (socket_address_is(&p->address, value+skip, type)) break; if (p) { safe_close(p->fd); p->fd = fdset_remove(fds, fd); } } } else if (streq(key, "netlink")) { int fd, skip = 0; SocketPort *p; if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse socket value: %s", value); else { LIST_FOREACH(port, p, s->ports) if (socket_address_is_netlink(&p->address, value+skip)) break; if (p) { safe_close(p->fd); p->fd = fdset_remove(fds, fd); } } } else if (streq(key, "ffs")) { int fd, skip = 0; SocketPort *p; if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse ffs value: %s", value); else { LIST_FOREACH(port, p, s->ports) if (p->type == SOCKET_USB_FUNCTION && path_equal_or_files_same(p->path, value+skip)) break; if (p) { safe_close(p->fd); p->fd = fdset_remove(fds, fd); } } } else log_unit_debug(UNIT(s), "Unknown serialization key: %s", key); return 0; } static void socket_distribute_fds(Unit *u, FDSet *fds) { Socket *s = SOCKET(u); SocketPort *p; assert(u); LIST_FOREACH(port, p, s->ports) { Iterator i; int fd; if (p->type != SOCKET_SOCKET) continue; if (p->fd >= 0) continue; FDSET_FOREACH(fd, fds, i) { if (socket_address_matches_fd(&p->address, fd)) { p->fd = fdset_remove(fds, fd); s->deserialized_state = SOCKET_LISTENING; break; } } } } _pure_ static UnitActiveState socket_active_state(Unit *u) { assert(u); return state_translation_table[SOCKET(u)->state]; } _pure_ static const char *socket_sub_state_to_string(Unit *u) { assert(u); return socket_state_to_string(SOCKET(u)->state); } const char* socket_port_type_to_string(SocketPort *p) { assert(p); switch (p->type) { case SOCKET_SOCKET: switch (p->address.type) { case SOCK_STREAM: return "Stream"; case SOCK_DGRAM: return "Datagram"; case SOCK_SEQPACKET: return "SequentialPacket"; case SOCK_RAW: if (socket_address_family(&p->address) == AF_NETLINK) return "Netlink"; default: return NULL; } case SOCKET_SPECIAL: return "Special"; case SOCKET_MQUEUE: return "MessageQueue"; case SOCKET_FIFO: return "FIFO"; case SOCKET_USB_FUNCTION: return "USBFunction"; default: return NULL; } } _pure_ static bool socket_check_gc(Unit *u) { Socket *s = SOCKET(u); assert(u); return s->n_connections > 0; } static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { SocketPort *p = userdata; int cfd = -1; assert(p); assert(fd >= 0); if (p->socket->state != SOCKET_LISTENING) return 0; log_unit_debug(UNIT(p->socket), "Incoming traffic"); if (revents != EPOLLIN) { if (revents & EPOLLHUP) log_unit_error(UNIT(p->socket), "Got POLLHUP on a listening socket. The service probably invoked shutdown() on it, and should better not do that."); else log_unit_error(UNIT(p->socket), "Got unexpected poll event (0x%x) on socket.", revents); goto fail; } if (p->socket->accept && p->type == SOCKET_SOCKET && socket_address_can_accept(&p->address)) { for (;;) { cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK); if (cfd < 0) { if (errno == EINTR) continue; log_unit_error_errno(UNIT(p->socket), errno, "Failed to accept socket: %m"); goto fail; } break; } socket_apply_socket_options(p->socket, cfd); } socket_enter_running(p->socket, cfd); return 0; fail: socket_enter_stop_pre(p->socket, SOCKET_FAILURE_RESOURCES); return 0; } static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) { Socket *s = SOCKET(u); SocketResult f; assert(s); assert(pid >= 0); if (pid != s->control_pid) return; s->control_pid = 0; if (is_clean_exit(code, status, NULL)) f = SOCKET_SUCCESS; else if (code == CLD_EXITED) f = SOCKET_FAILURE_EXIT_CODE; else if (code == CLD_KILLED) f = SOCKET_FAILURE_SIGNAL; else if (code == CLD_DUMPED) f = SOCKET_FAILURE_CORE_DUMP; else assert_not_reached("Unknown sigchld code"); if (s->control_command) { exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status); if (s->control_command->ignore) f = SOCKET_SUCCESS; } log_unit_full(u, f == SOCKET_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0, "Control process exited, code=%s status=%i", sigchld_code_to_string(code), status); if (f != SOCKET_SUCCESS) s->result = f; if (s->control_command && s->control_command->command_next && f == SOCKET_SUCCESS) { log_unit_debug(u, "Running next command for state %s", socket_state_to_string(s->state)); socket_run_next(s); } else { s->control_command = NULL; s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID; /* No further commands for this step, so let's figure * out what to do next */ log_unit_debug(u, "Got final SIGCHLD for state %s", socket_state_to_string(s->state)); switch (s->state) { case SOCKET_START_PRE: if (f == SOCKET_SUCCESS) socket_enter_start_chown(s); else socket_enter_signal(s, SOCKET_FINAL_SIGTERM, f); break; case SOCKET_START_CHOWN: if (f == SOCKET_SUCCESS) socket_enter_start_post(s); else socket_enter_stop_pre(s, f); break; case SOCKET_START_POST: if (f == SOCKET_SUCCESS) socket_enter_listening(s); else socket_enter_stop_pre(s, f); break; case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL: socket_enter_stop_post(s, f); break; case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL: socket_enter_dead(s, f); break; default: assert_not_reached("Uh, control process died at wrong time."); } } /* Notify clients about changed exit status */ unit_add_to_dbus_queue(u); } static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { Socket *s = SOCKET(userdata); assert(s); assert(s->timer_event_source == source); switch (s->state) { case SOCKET_START_PRE: log_unit_warning(UNIT(s), "Starting timed out. Terminating."); socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_TIMEOUT); break; case SOCKET_START_CHOWN: case SOCKET_START_POST: log_unit_warning(UNIT(s), "Starting timed out. Stopping."); socket_enter_stop_pre(s, SOCKET_FAILURE_TIMEOUT); break; case SOCKET_STOP_PRE: log_unit_warning(UNIT(s), "Stopping timed out. Terminating."); socket_enter_signal(s, SOCKET_STOP_PRE_SIGTERM, SOCKET_FAILURE_TIMEOUT); break; case SOCKET_STOP_PRE_SIGTERM: if (s->kill_context.send_sigkill) { log_unit_warning(UNIT(s), "Stopping timed out. Killing."); socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, SOCKET_FAILURE_TIMEOUT); } else { log_unit_warning(UNIT(s), "Stopping timed out. Skipping SIGKILL. Ignoring."); socket_enter_stop_post(s, SOCKET_FAILURE_TIMEOUT); } break; case SOCKET_STOP_PRE_SIGKILL: log_unit_warning(UNIT(s), "Processes still around after SIGKILL. Ignoring."); socket_enter_stop_post(s, SOCKET_FAILURE_TIMEOUT); break; case SOCKET_STOP_POST: log_unit_warning(UNIT(s), "Stopping timed out (2). Terminating."); socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_TIMEOUT); break; case SOCKET_FINAL_SIGTERM: if (s->kill_context.send_sigkill) { log_unit_warning(UNIT(s), "Stopping timed out (2). Killing."); socket_enter_signal(s, SOCKET_FINAL_SIGKILL, SOCKET_FAILURE_TIMEOUT); } else { log_unit_warning(UNIT(s), "Stopping timed out (2). Skipping SIGKILL. Ignoring."); socket_enter_dead(s, SOCKET_FAILURE_TIMEOUT); } break; case SOCKET_FINAL_SIGKILL: log_unit_warning(UNIT(s), "Still around after SIGKILL (2). Entering failed mode."); socket_enter_dead(s, SOCKET_FAILURE_TIMEOUT); break; default: assert_not_reached("Timeout at wrong time."); } return 0; } int socket_collect_fds(Socket *s, int **fds) { int *rfds, k = 0, n = 0; SocketPort *p; assert(s); assert(fds); /* Called from the service code for requesting our fds */ LIST_FOREACH(port, p, s->ports) { if (p->fd >= 0) n++; n += p->n_auxiliary_fds; } if (n <= 0) { *fds = NULL; return 0; } rfds = new(int, n); if (!rfds) return -ENOMEM; LIST_FOREACH(port, p, s->ports) { int i; if (p->fd >= 0) rfds[k++] = p->fd; for (i = 0; i < p->n_auxiliary_fds; ++i) rfds[k++] = p->auxiliary_fds[i]; } assert(k == n); *fds = rfds; return n; } static void socket_reset_failed(Unit *u) { Socket *s = SOCKET(u); assert(s); if (s->state == SOCKET_FAILED) socket_set_state(s, SOCKET_DEAD); s->result = SOCKET_SUCCESS; } void socket_connection_unref(Socket *s) { assert(s); /* The service is dead. Yay! * * This is strictly for one-instance-per-connection * services. */ assert(s->n_connections > 0); s->n_connections--; log_unit_debug(UNIT(s), "One connection closed, %u left.", s->n_connections); } static void socket_trigger_notify(Unit *u, Unit *other) { Socket *s = SOCKET(u); assert(u); assert(other); /* Don't propagate state changes from the service if we are already down or accepting connections */ if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING) || s->accept) return; if (other->start_limit_hit) { socket_enter_stop_pre(s, SOCKET_FAILURE_SERVICE_START_LIMIT_HIT); return; } if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE) return; if (IN_SET(SERVICE(other)->state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, SERVICE_AUTO_RESTART)) socket_enter_listening(s); if (SERVICE(other)->state == SERVICE_RUNNING) socket_set_state(s, SOCKET_RUNNING); } static int socket_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { return unit_kill_common(u, who, signo, -1, SOCKET(u)->control_pid, error); } static int socket_get_timeout(Unit *u, usec_t *timeout) { Socket *s = SOCKET(u); usec_t t; int r; if (!s->timer_event_source) return 0; r = sd_event_source_get_time(s->timer_event_source, &t); if (r < 0) return r; if (t == USEC_INFINITY) return 0; *timeout = t; return 1; } char *socket_fdname(Socket *s) { assert(s); /* Returns the name to use for $LISTEN_NAMES. If the user * didn't specify anything specifically, use the socket unit's * name as fallback. */ if (s->fdname) return s->fdname; return UNIT(s)->id; } static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = { [SOCKET_EXEC_START_PRE] = "StartPre", [SOCKET_EXEC_START_CHOWN] = "StartChown", [SOCKET_EXEC_START_POST] = "StartPost", [SOCKET_EXEC_STOP_PRE] = "StopPre", [SOCKET_EXEC_STOP_POST] = "StopPost" }; DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand); static const char* const socket_result_table[_SOCKET_RESULT_MAX] = { [SOCKET_SUCCESS] = "success", [SOCKET_FAILURE_RESOURCES] = "resources", [SOCKET_FAILURE_TIMEOUT] = "timeout", [SOCKET_FAILURE_EXIT_CODE] = "exit-code", [SOCKET_FAILURE_SIGNAL] = "signal", [SOCKET_FAILURE_CORE_DUMP] = "core-dump", [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit" }; DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult); const UnitVTable socket_vtable = { .object_size = sizeof(Socket), .exec_context_offset = offsetof(Socket, exec_context), .cgroup_context_offset = offsetof(Socket, cgroup_context), .kill_context_offset = offsetof(Socket, kill_context), .exec_runtime_offset = offsetof(Socket, exec_runtime), .sections = "Unit\0" "Socket\0" "Install\0", .private_section = "Socket", .init = socket_init, .done = socket_done, .load = socket_load, .coldplug = socket_coldplug, .dump = socket_dump, .start = socket_start, .stop = socket_stop, .kill = socket_kill, .get_timeout = socket_get_timeout, .serialize = socket_serialize, .deserialize_item = socket_deserialize_item, .distribute_fds = socket_distribute_fds, .active_state = socket_active_state, .sub_state_to_string = socket_sub_state_to_string, .check_gc = socket_check_gc, .sigchld_event = socket_sigchld_event, .trigger_notify = socket_trigger_notify, .reset_failed = socket_reset_failed, .bus_vtable = bus_socket_vtable, .bus_set_property = bus_socket_set_property, .bus_commit_properties = bus_socket_commit_properties, .status_message_formats = { /*.starting_stopping = { [0] = "Starting socket %s...", [1] = "Stopping socket %s...", },*/ .finished_start_job = { [JOB_DONE] = "Listening on %s.", [JOB_FAILED] = "Failed to listen on %s.", [JOB_TIMEOUT] = "Timed out starting %s.", }, .finished_stop_job = { [JOB_DONE] = "Closed %s.", [JOB_FAILED] = "Failed stopping %s.", [JOB_TIMEOUT] = "Timed out stopping %s.", }, }, }; systemd-229/src/core/socket.h000066400000000000000000000111271265713322000162430ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Socket Socket; #include "mount.h" #include "service.h" #include "socket-util.h" typedef enum SocketExecCommand { SOCKET_EXEC_START_PRE, SOCKET_EXEC_START_CHOWN, SOCKET_EXEC_START_POST, SOCKET_EXEC_STOP_PRE, SOCKET_EXEC_STOP_POST, _SOCKET_EXEC_COMMAND_MAX, _SOCKET_EXEC_COMMAND_INVALID = -1 } SocketExecCommand; typedef enum SocketType { SOCKET_SOCKET, SOCKET_FIFO, SOCKET_SPECIAL, SOCKET_MQUEUE, SOCKET_USB_FUNCTION, _SOCKET_FIFO_MAX, _SOCKET_FIFO_INVALID = -1 } SocketType; typedef enum SocketResult { SOCKET_SUCCESS, SOCKET_FAILURE_RESOURCES, SOCKET_FAILURE_TIMEOUT, SOCKET_FAILURE_EXIT_CODE, SOCKET_FAILURE_SIGNAL, SOCKET_FAILURE_CORE_DUMP, SOCKET_FAILURE_SERVICE_START_LIMIT_HIT, _SOCKET_RESULT_MAX, _SOCKET_RESULT_INVALID = -1 } SocketResult; typedef struct SocketPort { Socket *socket; SocketType type; int fd; int *auxiliary_fds; int n_auxiliary_fds; SocketAddress address; char *path; sd_event_source *event_source; LIST_FIELDS(struct SocketPort, port); } SocketPort; struct Socket { Unit meta; LIST_HEAD(SocketPort, ports); unsigned n_accepted; unsigned n_connections; unsigned max_connections; unsigned backlog; unsigned keep_alive_cnt; usec_t timeout_usec; usec_t keep_alive_time; usec_t keep_alive_interval; usec_t defer_accept; ExecCommand* exec_command[_SOCKET_EXEC_COMMAND_MAX]; ExecContext exec_context; KillContext kill_context; CGroupContext cgroup_context; ExecRuntime *exec_runtime; /* For Accept=no sockets refers to the one service we'll activate. For Accept=yes sockets is either NULL, or filled when the next service we spawn. */ UnitRef service; SocketState state, deserialized_state; sd_event_source *timer_event_source; ExecCommand* control_command; SocketExecCommand control_command_id; pid_t control_pid; mode_t directory_mode; mode_t socket_mode; SocketResult result; char **symlinks; bool accept; bool remove_on_stop; bool writable; int socket_protocol; /* Socket options */ bool keep_alive; bool no_delay; bool free_bind; bool transparent; bool broadcast; bool pass_cred; bool pass_sec; /* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */ SocketAddressBindIPv6Only bind_ipv6_only; int priority; int mark; size_t receive_buffer; size_t send_buffer; int ip_tos; int ip_ttl; size_t pipe_size; char *bind_to_device; char *tcp_congestion; bool reuse_port; long mq_maxmsg; long mq_msgsize; char *smack; char *smack_ip_in; char *smack_ip_out; bool selinux_context_from_net; char *user, *group; bool reset_cpu_usage:1; char *fdname; }; /* Called from the service code when collecting fds */ int socket_collect_fds(Socket *s, int **fds); /* Called from the service code when a per-connection service ended */ void socket_connection_unref(Socket *s); void socket_free_ports(Socket *s); int socket_instantiate_service(Socket *s); char *socket_fdname(Socket *s); extern const UnitVTable socket_vtable; const char* socket_exec_command_to_string(SocketExecCommand i) _const_; SocketExecCommand socket_exec_command_from_string(const char *s) _pure_; const char* socket_result_to_string(SocketResult i) _const_; SocketResult socket_result_from_string(const char *s) _pure_; const char* socket_port_type_to_string(SocketPort *p) _pure_; systemd-229/src/core/swap.c000066400000000000000000001320071265713322000157210ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "libudev.h" #include "alloc-util.h" #include "dbus-swap.h" #include "escape.h" #include "exit-status.h" #include "fd-util.h" #include "formats-util.h" #include "fstab-util.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "special.h" #include "string-table.h" #include "string-util.h" #include "swap.h" #include "udev-util.h" #include "unit-name.h" #include "unit.h" #include "virt.h" static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = { [SWAP_DEAD] = UNIT_INACTIVE, [SWAP_ACTIVATING] = UNIT_ACTIVATING, [SWAP_ACTIVATING_DONE] = UNIT_ACTIVE, [SWAP_ACTIVE] = UNIT_ACTIVE, [SWAP_DEACTIVATING] = UNIT_DEACTIVATING, [SWAP_ACTIVATING_SIGTERM] = UNIT_DEACTIVATING, [SWAP_ACTIVATING_SIGKILL] = UNIT_DEACTIVATING, [SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING, [SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING, [SWAP_FAILED] = UNIT_FAILED }; static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); static void swap_unset_proc_swaps(Swap *s) { assert(s); if (!s->from_proc_swaps) return; s->parameters_proc_swaps.what = mfree(s->parameters_proc_swaps.what); s->from_proc_swaps = false; } static int swap_set_devnode(Swap *s, const char *devnode) { Hashmap *swaps; Swap *first; int r; assert(s); r = hashmap_ensure_allocated(&UNIT(s)->manager->swaps_by_devnode, &string_hash_ops); if (r < 0) return r; swaps = UNIT(s)->manager->swaps_by_devnode; if (s->devnode) { first = hashmap_get(swaps, s->devnode); LIST_REMOVE(same_devnode, first, s); if (first) hashmap_replace(swaps, first->devnode, first); else hashmap_remove(swaps, s->devnode); s->devnode = mfree(s->devnode); } if (devnode) { s->devnode = strdup(devnode); if (!s->devnode) return -ENOMEM; first = hashmap_get(swaps, s->devnode); LIST_PREPEND(same_devnode, first, s); return hashmap_replace(swaps, first->devnode, first); } return 0; } static void swap_init(Unit *u) { Swap *s = SWAP(u); assert(s); assert(UNIT(s)->load_state == UNIT_STUB); s->timeout_usec = u->manager->default_timeout_start_usec; s->exec_context.std_output = u->manager->default_std_output; s->exec_context.std_error = u->manager->default_std_error; s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1; s->control_command_id = _SWAP_EXEC_COMMAND_INVALID; u->ignore_on_isolate = true; } static void swap_unwatch_control_pid(Swap *s) { assert(s); if (s->control_pid <= 0) return; unit_unwatch_pid(UNIT(s), s->control_pid); s->control_pid = 0; } static void swap_done(Unit *u) { Swap *s = SWAP(u); assert(s); swap_unset_proc_swaps(s); swap_set_devnode(s, NULL); s->what = mfree(s->what); s->parameters_fragment.what = mfree(s->parameters_fragment.what); s->parameters_fragment.options = mfree(s->parameters_fragment.options); s->exec_runtime = exec_runtime_unref(s->exec_runtime); exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX); s->control_command = NULL; swap_unwatch_control_pid(s); s->timer_event_source = sd_event_source_unref(s->timer_event_source); } static int swap_arm_timer(Swap *s, usec_t usec) { int r; assert(s); if (s->timer_event_source) { r = sd_event_source_set_time(s->timer_event_source, usec); if (r < 0) return r; return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); } if (usec == USEC_INFINITY) return 0; r = sd_event_add_time( UNIT(s)->manager->event, &s->timer_event_source, CLOCK_MONOTONIC, usec, 0, swap_dispatch_timer, s); if (r < 0) return r; (void) sd_event_source_set_description(s->timer_event_source, "swap-timer"); return 0; } static int swap_add_device_links(Swap *s) { assert(s); if (!s->what) return 0; if (!s->from_fragment) return 0; if (is_device_path(s->what)) return unit_add_node_link(UNIT(s), s->what, UNIT(s)->manager->running_as == MANAGER_SYSTEM, UNIT_BINDS_TO); else /* File based swap devices need to be ordered after * systemd-remount-fs.service, since they might need a * writable file system. */ return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, NULL, true); } static int swap_add_default_dependencies(Swap *s) { int r; assert(s); if (!UNIT(s)->default_dependencies) return 0; if (UNIT(s)->manager->running_as != MANAGER_SYSTEM) return 0; if (detect_container() > 0) return 0; /* swap units generated for the swap dev links are missing the * ordering dep against the swap target. */ r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SWAP_TARGET, NULL, true); if (r < 0) return r; return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true); } static int swap_verify(Swap *s) { _cleanup_free_ char *e = NULL; int r; if (UNIT(s)->load_state != UNIT_LOADED) return 0; r = unit_name_from_path(s->what, ".swap", &e); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Failed to generate unit name from path: %m"); if (!unit_has_name(UNIT(s), e)) { log_unit_error(UNIT(s), "Value of What= and unit name do not match, not loading."); return -EINVAL; } if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) { log_unit_error(UNIT(s), "Unit has PAM enabled. Kill mode must be set to 'control-group'. Refusing to load."); return -EINVAL; } return 0; } static int swap_load_devnode(Swap *s) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; struct stat st; const char *p; assert(s); if (stat(s->what, &st) < 0 || !S_ISBLK(st.st_mode)) return 0; d = udev_device_new_from_devnum(UNIT(s)->manager->udev, 'b', st.st_rdev); if (!d) return 0; p = udev_device_get_devnode(d); if (!p) return 0; return swap_set_devnode(s, p); } static int swap_load(Unit *u) { int r; Swap *s = SWAP(u); assert(s); assert(u->load_state == UNIT_STUB); /* Load a .swap file */ r = unit_load_fragment_and_dropin_optional(u); if (r < 0) return r; if (u->load_state == UNIT_LOADED) { if (UNIT(s)->fragment_path) s->from_fragment = true; if (!s->what) { if (s->parameters_fragment.what) s->what = strdup(s->parameters_fragment.what); else if (s->parameters_proc_swaps.what) s->what = strdup(s->parameters_proc_swaps.what); else { r = unit_name_to_path(u->id, &s->what); if (r < 0) return r; } if (!s->what) return -ENOMEM; } path_kill_slashes(s->what); if (!UNIT(s)->description) { r = unit_set_description(u, s->what); if (r < 0) return r; } r = unit_require_mounts_for(UNIT(s), s->what); if (r < 0) return r; r = swap_add_device_links(s); if (r < 0) return r; r = swap_load_devnode(s); if (r < 0) return r; r = unit_patch_contexts(u); if (r < 0) return r; r = unit_add_exec_dependencies(u, &s->exec_context); if (r < 0) return r; r = unit_set_default_slice(u); if (r < 0) return r; r = swap_add_default_dependencies(s); if (r < 0) return r; } return swap_verify(s); } static int swap_setup_unit( Manager *m, const char *what, const char *what_proc_swaps, int priority, bool set_flags) { _cleanup_free_ char *e = NULL; bool delete = false; Unit *u = NULL; int r; SwapParameters *p; assert(m); assert(what); assert(what_proc_swaps); r = unit_name_from_path(what, ".swap", &e); if (r < 0) return log_unit_error_errno(u, r, "Failed to generate unit name from path: %m"); u = manager_get_unit(m, e); if (u && SWAP(u)->from_proc_swaps && !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps)) { log_error("Swap %s appeared twice with different device paths %s and %s", e, SWAP(u)->parameters_proc_swaps.what, what_proc_swaps); return -EEXIST; } if (!u) { delete = true; u = unit_new(m, sizeof(Swap)); if (!u) return log_oom(); r = unit_add_name(u, e); if (r < 0) goto fail; SWAP(u)->what = strdup(what); if (!SWAP(u)->what) { r = -ENOMEM; goto fail; } unit_add_to_load_queue(u); } else delete = false; p = &SWAP(u)->parameters_proc_swaps; if (!p->what) { p->what = strdup(what_proc_swaps); if (!p->what) { r = -ENOMEM; goto fail; } } if (set_flags) { SWAP(u)->is_active = true; SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps; } SWAP(u)->from_proc_swaps = true; p->priority = priority; unit_add_to_dbus_queue(u); return 0; fail: log_unit_warning_errno(u, r, "Failed to load swap unit: %m"); if (delete && u) unit_free(u); return r; } static int swap_process_new(Manager *m, const char *device, int prio, bool set_flags) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; struct udev_list_entry *item = NULL, *first = NULL; const char *dn; struct stat st; int r; assert(m); r = swap_setup_unit(m, device, device, prio, set_flags); if (r < 0) return r; /* If this is a block device, then let's add duplicates for * all other names of this block device */ if (stat(device, &st) < 0 || !S_ISBLK(st.st_mode)) return 0; d = udev_device_new_from_devnum(m->udev, 'b', st.st_rdev); if (!d) return 0; /* Add the main device node */ dn = udev_device_get_devnode(d); if (dn && !streq(dn, device)) swap_setup_unit(m, dn, device, prio, set_flags); /* Add additional units for all symlinks */ first = udev_device_get_devlinks_list_entry(d); udev_list_entry_foreach(item, first) { const char *p; /* Don't bother with the /dev/block links */ p = udev_list_entry_get_name(item); if (streq(p, device)) continue; if (path_startswith(p, "/dev/block/")) continue; if (stat(p, &st) >= 0) if (!S_ISBLK(st.st_mode) || st.st_rdev != udev_device_get_devnum(d)) continue; swap_setup_unit(m, p, device, prio, set_flags); } return r; } static void swap_set_state(Swap *s, SwapState state) { SwapState old_state; Swap *other; assert(s); old_state = s->state; s->state = state; if (state != SWAP_ACTIVATING && state != SWAP_ACTIVATING_SIGTERM && state != SWAP_ACTIVATING_SIGKILL && state != SWAP_ACTIVATING_DONE && state != SWAP_DEACTIVATING && state != SWAP_DEACTIVATING_SIGTERM && state != SWAP_DEACTIVATING_SIGKILL) { s->timer_event_source = sd_event_source_unref(s->timer_event_source); swap_unwatch_control_pid(s); s->control_command = NULL; s->control_command_id = _SWAP_EXEC_COMMAND_INVALID; } if (state != old_state) log_unit_debug(UNIT(s), "Changed %s -> %s", swap_state_to_string(old_state), swap_state_to_string(state)); unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true); /* If there other units for the same device node have a job queued it might be worth checking again if it is runnable now. This is necessary, since swap_start() refuses operation with EAGAIN if there's already another job for the same device node queued. */ LIST_FOREACH_OTHERS(same_devnode, other, s) if (UNIT(other)->job) job_add_to_run_queue(UNIT(other)->job); } static int swap_coldplug(Unit *u) { Swap *s = SWAP(u); SwapState new_state = SWAP_DEAD; int r; assert(s); assert(s->state == SWAP_DEAD); if (s->deserialized_state != s->state) new_state = s->deserialized_state; else if (s->from_proc_swaps) new_state = SWAP_ACTIVE; if (new_state == s->state) return 0; if (s->control_pid > 0 && pid_is_unwaited(s->control_pid) && IN_SET(new_state, SWAP_ACTIVATING, SWAP_ACTIVATING_SIGTERM, SWAP_ACTIVATING_SIGKILL, SWAP_ACTIVATING_DONE, SWAP_DEACTIVATING, SWAP_DEACTIVATING_SIGTERM, SWAP_DEACTIVATING_SIGKILL)) { r = unit_watch_pid(UNIT(s), s->control_pid); if (r < 0) return r; r = swap_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec)); if (r < 0) return r; } swap_set_state(s, new_state); return 0; } static void swap_dump(Unit *u, FILE *f, const char *prefix) { Swap *s = SWAP(u); SwapParameters *p; assert(s); assert(f); if (s->from_proc_swaps) p = &s->parameters_proc_swaps; else if (s->from_fragment) p = &s->parameters_fragment; else p = NULL; fprintf(f, "%sSwap State: %s\n" "%sResult: %s\n" "%sWhat: %s\n" "%sFrom /proc/swaps: %s\n" "%sFrom fragment: %s\n", prefix, swap_state_to_string(s->state), prefix, swap_result_to_string(s->result), prefix, s->what, prefix, yes_no(s->from_proc_swaps), prefix, yes_no(s->from_fragment)); if (s->devnode) fprintf(f, "%sDevice Node: %s\n", prefix, s->devnode); if (p) fprintf(f, "%sPriority: %i\n" "%sOptions: %s\n", prefix, p->priority, prefix, strempty(p->options)); if (s->control_pid > 0) fprintf(f, "%sControl PID: "PID_FMT"\n", prefix, s->control_pid); exec_context_dump(&s->exec_context, f, prefix); kill_context_dump(&s->kill_context, f, prefix); } static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { pid_t pid; int r; ExecParameters exec_params = { .apply_permissions = true, .apply_chroot = true, .apply_tty_stdin = true, .bus_endpoint_fd = -1, .stdin_fd = -1, .stdout_fd = -1, .stderr_fd = -1, }; assert(s); assert(c); assert(_pid); (void) unit_realize_cgroup(UNIT(s)); if (s->reset_cpu_usage) { (void) unit_reset_cpu_usage(UNIT(s)); s->reset_cpu_usage = false; } r = unit_setup_exec_runtime(UNIT(s)); if (r < 0) goto fail; r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec)); if (r < 0) goto fail; exec_params.environment = UNIT(s)->manager->environment; exec_params.confirm_spawn = UNIT(s)->manager->confirm_spawn; exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported; exec_params.cgroup_path = UNIT(s)->cgroup_path; exec_params.cgroup_delegate = s->cgroup_context.delegate; exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager); r = exec_spawn(UNIT(s), c, &s->exec_context, &exec_params, s->exec_runtime, &pid); if (r < 0) goto fail; r = unit_watch_pid(UNIT(s), pid); if (r < 0) /* FIXME: we need to do something here */ goto fail; *_pid = pid; return 0; fail: s->timer_event_source = sd_event_source_unref(s->timer_event_source); return r; } static void swap_enter_dead(Swap *s, SwapResult f) { assert(s); if (f != SWAP_SUCCESS) s->result = f; exec_runtime_destroy(s->exec_runtime); s->exec_runtime = exec_runtime_unref(s->exec_runtime); exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager)); swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD); } static void swap_enter_active(Swap *s, SwapResult f) { assert(s); if (f != SWAP_SUCCESS) s->result = f; swap_set_state(s, SWAP_ACTIVE); } static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) { int r; assert(s); if (f != SWAP_SUCCESS) s->result = f; r = unit_kill_context( UNIT(s), &s->kill_context, (state != SWAP_ACTIVATING_SIGTERM && state != SWAP_DEACTIVATING_SIGTERM) ? KILL_KILL : KILL_TERMINATE, -1, s->control_pid, false); if (r < 0) goto fail; if (r > 0) { r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec)); if (r < 0) goto fail; swap_set_state(s, state); } else if (state == SWAP_ACTIVATING_SIGTERM) swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_SUCCESS); else if (state == SWAP_DEACTIVATING_SIGTERM) swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS); else swap_enter_dead(s, SWAP_SUCCESS); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m"); swap_enter_dead(s, SWAP_FAILURE_RESOURCES); } static void swap_enter_activating(Swap *s) { _cleanup_free_ char *opts = NULL; int r; assert(s); s->control_command_id = SWAP_EXEC_ACTIVATE; s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE; if (s->from_fragment) { int priority = -1; r = fstab_find_pri(s->parameters_fragment.options, &priority); if (r < 0) log_warning_errno(r, "Failed to parse swap priority \"%s\", ignoring: %m", s->parameters_fragment.options); else if (r == 1 && s->parameters_fragment.priority >= 0) log_warning("Duplicate swap priority configuration by Priority and Options fields."); if (r <= 0 && s->parameters_fragment.priority >= 0) { if (s->parameters_fragment.options) r = asprintf(&opts, "%s,pri=%i", s->parameters_fragment.options, s->parameters_fragment.priority); else r = asprintf(&opts, "pri=%i", s->parameters_fragment.priority); if (r < 0) goto fail; } } r = exec_command_set(s->control_command, "/sbin/swapon", NULL); if (r < 0) goto fail; if (s->parameters_fragment.options || opts) { r = exec_command_append(s->control_command, "-o", opts ? : s->parameters_fragment.options, NULL); if (r < 0) goto fail; } r = exec_command_append(s->control_command, s->what, NULL); if (r < 0) goto fail; swap_unwatch_control_pid(s); r = swap_spawn(s, s->control_command, &s->control_pid); if (r < 0) goto fail; swap_set_state(s, SWAP_ACTIVATING); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapon' task: %m"); swap_enter_dead(s, SWAP_FAILURE_RESOURCES); } static void swap_enter_deactivating(Swap *s) { int r; assert(s); s->control_command_id = SWAP_EXEC_DEACTIVATE; s->control_command = s->exec_command + SWAP_EXEC_DEACTIVATE; r = exec_command_set(s->control_command, "/sbin/swapoff", s->what, NULL); if (r < 0) goto fail; swap_unwatch_control_pid(s); r = swap_spawn(s, s->control_command, &s->control_pid); if (r < 0) goto fail; swap_set_state(s, SWAP_DEACTIVATING); return; fail: log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapoff' task: %m"); swap_enter_active(s, SWAP_FAILURE_RESOURCES); } static int swap_start(Unit *u) { Swap *s = SWAP(u), *other; assert(s); /* We cannot fulfill this request right now, try again later * please! */ if (s->state == SWAP_DEACTIVATING || s->state == SWAP_DEACTIVATING_SIGTERM || s->state == SWAP_DEACTIVATING_SIGKILL || s->state == SWAP_ACTIVATING_SIGTERM || s->state == SWAP_ACTIVATING_SIGKILL) return -EAGAIN; if (s->state == SWAP_ACTIVATING) return 0; assert(s->state == SWAP_DEAD || s->state == SWAP_FAILED); if (detect_container() > 0) return -EPERM; /* If there's a job for another swap unit for the same node * running, then let's not dispatch this one for now, and wait * until that other job has finished. */ LIST_FOREACH_OTHERS(same_devnode, other, s) if (UNIT(other)->job && UNIT(other)->job->state == JOB_RUNNING) return -EAGAIN; s->result = SWAP_SUCCESS; s->reset_cpu_usage = true; swap_enter_activating(s); return 1; } static int swap_stop(Unit *u) { Swap *s = SWAP(u); assert(s); if (s->state == SWAP_DEACTIVATING || s->state == SWAP_DEACTIVATING_SIGTERM || s->state == SWAP_DEACTIVATING_SIGKILL || s->state == SWAP_ACTIVATING_SIGTERM || s->state == SWAP_ACTIVATING_SIGKILL) return 0; assert(s->state == SWAP_ACTIVATING || s->state == SWAP_ACTIVATING_DONE || s->state == SWAP_ACTIVE); if (detect_container() > 0) return -EPERM; swap_enter_deactivating(s); return 1; } static int swap_serialize(Unit *u, FILE *f, FDSet *fds) { Swap *s = SWAP(u); assert(s); assert(f); assert(fds); unit_serialize_item(u, f, "state", swap_state_to_string(s->state)); unit_serialize_item(u, f, "result", swap_result_to_string(s->result)); if (s->control_pid > 0) unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid); if (s->control_command_id >= 0) unit_serialize_item(u, f, "control-command", swap_exec_command_to_string(s->control_command_id)); return 0; } static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Swap *s = SWAP(u); assert(s); assert(fds); if (streq(key, "state")) { SwapState state; state = swap_state_from_string(value); if (state < 0) log_unit_debug(u, "Failed to parse state value: %s", value); else s->deserialized_state = state; } else if (streq(key, "result")) { SwapResult f; f = swap_result_from_string(value); if (f < 0) log_unit_debug(u, "Failed to parse result value: %s", value); else if (f != SWAP_SUCCESS) s->result = f; } else if (streq(key, "control-pid")) { pid_t pid; if (parse_pid(value, &pid) < 0) log_unit_debug(u, "Failed to parse control-pid value: %s", value); else s->control_pid = pid; } else if (streq(key, "control-command")) { SwapExecCommand id; id = swap_exec_command_from_string(value); if (id < 0) log_unit_debug(u, "Failed to parse exec-command value: %s", value); else { s->control_command_id = id; s->control_command = s->exec_command + id; } } else log_unit_debug(u, "Unknown serialization key: %s", key); return 0; } _pure_ static UnitActiveState swap_active_state(Unit *u) { assert(u); return state_translation_table[SWAP(u)->state]; } _pure_ static const char *swap_sub_state_to_string(Unit *u) { assert(u); return swap_state_to_string(SWAP(u)->state); } _pure_ static bool swap_check_gc(Unit *u) { Swap *s = SWAP(u); assert(s); return s->from_proc_swaps; } static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) { Swap *s = SWAP(u); SwapResult f; assert(s); assert(pid >= 0); if (pid != s->control_pid) return; s->control_pid = 0; if (is_clean_exit(code, status, NULL)) f = SWAP_SUCCESS; else if (code == CLD_EXITED) f = SWAP_FAILURE_EXIT_CODE; else if (code == CLD_KILLED) f = SWAP_FAILURE_SIGNAL; else if (code == CLD_DUMPED) f = SWAP_FAILURE_CORE_DUMP; else assert_not_reached("Unknown code"); if (f != SWAP_SUCCESS) s->result = f; if (s->control_command) { exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status); s->control_command = NULL; s->control_command_id = _SWAP_EXEC_COMMAND_INVALID; } log_unit_full(u, f == SWAP_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0, "Swap process exited, code=%s status=%i", sigchld_code_to_string(code), status); switch (s->state) { case SWAP_ACTIVATING: case SWAP_ACTIVATING_DONE: case SWAP_ACTIVATING_SIGTERM: case SWAP_ACTIVATING_SIGKILL: if (f == SWAP_SUCCESS) swap_enter_active(s, f); else swap_enter_dead(s, f); break; case SWAP_DEACTIVATING: case SWAP_DEACTIVATING_SIGKILL: case SWAP_DEACTIVATING_SIGTERM: swap_enter_dead(s, f); break; default: assert_not_reached("Uh, control process died at wrong time."); } /* Notify clients about changed exit status */ unit_add_to_dbus_queue(u); } static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { Swap *s = SWAP(userdata); assert(s); assert(s->timer_event_source == source); switch (s->state) { case SWAP_ACTIVATING: case SWAP_ACTIVATING_DONE: log_unit_warning(UNIT(s), "Activation timed out. Stopping."); swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT); break; case SWAP_DEACTIVATING: log_unit_warning(UNIT(s), "Deactivation timed out. Stopping."); swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT); break; case SWAP_ACTIVATING_SIGTERM: if (s->kill_context.send_sigkill) { log_unit_warning(UNIT(s), "Activation timed out. Killing."); swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT); } else { log_unit_warning(UNIT(s), "Activation timed out. Skipping SIGKILL. Ignoring."); swap_enter_dead(s, SWAP_FAILURE_TIMEOUT); } break; case SWAP_DEACTIVATING_SIGTERM: if (s->kill_context.send_sigkill) { log_unit_warning(UNIT(s), "Deactivation timed out. Killing."); swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT); } else { log_unit_warning(UNIT(s), "Deactivation timed out. Skipping SIGKILL. Ignoring."); swap_enter_dead(s, SWAP_FAILURE_TIMEOUT); } break; case SWAP_ACTIVATING_SIGKILL: case SWAP_DEACTIVATING_SIGKILL: log_unit_warning(UNIT(s), "Swap process still around after SIGKILL. Ignoring."); swap_enter_dead(s, SWAP_FAILURE_TIMEOUT); break; default: assert_not_reached("Timeout at wrong time."); } return 0; } static int swap_load_proc_swaps(Manager *m, bool set_flags) { unsigned i; int r = 0; assert(m); rewind(m->proc_swaps); (void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n"); for (i = 1;; i++) { _cleanup_free_ char *dev = NULL, *d = NULL; int prio = 0, k; k = fscanf(m->proc_swaps, "%ms " /* device/file */ "%*s " /* type of swap */ "%*s " /* swap size */ "%*s " /* used */ "%i\n", /* priority */ &dev, &prio); if (k != 2) { if (k == EOF) break; log_warning("Failed to parse /proc/swaps:%u.", i); continue; } if (cunescape(dev, UNESCAPE_RELAX, &d) < 0) return log_oom(); device_found_node(m, d, true, DEVICE_FOUND_SWAP, set_flags); k = swap_process_new(m, d, prio, set_flags); if (k < 0) r = k; } return r; } static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; Unit *u; int r; assert(m); assert(revents & EPOLLPRI); r = swap_load_proc_swaps(m, true); if (r < 0) { log_error_errno(r, "Failed to reread /proc/swaps: %m"); /* Reset flags, just in case, for late calls */ LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) { Swap *swap = SWAP(u); swap->is_active = swap->just_activated = false; } return 0; } manager_dispatch_load_queue(m); LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) { Swap *swap = SWAP(u); if (!swap->is_active) { /* This has just been deactivated */ swap_unset_proc_swaps(swap); switch (swap->state) { case SWAP_ACTIVE: swap_enter_dead(swap, SWAP_SUCCESS); break; default: /* Fire again */ swap_set_state(swap, swap->state); break; } if (swap->what) device_found_node(m, swap->what, false, DEVICE_FOUND_SWAP, true); } else if (swap->just_activated) { /* New swap entry */ switch (swap->state) { case SWAP_DEAD: case SWAP_FAILED: swap_enter_active(swap, SWAP_SUCCESS); break; case SWAP_ACTIVATING: swap_set_state(swap, SWAP_ACTIVATING_DONE); break; default: /* Nothing really changed, but let's * issue an notification call * nonetheless, in case somebody is * waiting for this. */ swap_set_state(swap, swap->state); break; } } /* Reset the flags for later calls */ swap->is_active = swap->just_activated = false; } return 1; } static Unit *swap_following(Unit *u) { Swap *s = SWAP(u); Swap *other, *first = NULL; assert(s); /* If the user configured the swap through /etc/fstab or * a device unit, follow that. */ if (s->from_fragment) return NULL; LIST_FOREACH_OTHERS(same_devnode, other, s) if (other->from_fragment) return UNIT(other); /* Otherwise, make everybody follow the unit that's named after * the swap device in the kernel */ if (streq_ptr(s->what, s->devnode)) return NULL; LIST_FOREACH_AFTER(same_devnode, other, s) if (streq_ptr(other->what, other->devnode)) return UNIT(other); LIST_FOREACH_BEFORE(same_devnode, other, s) { if (streq_ptr(other->what, other->devnode)) return UNIT(other); first = other; } /* Fall back to the first on the list */ return UNIT(first); } static int swap_following_set(Unit *u, Set **_set) { Swap *s = SWAP(u), *other; Set *set; int r; assert(s); assert(_set); if (LIST_JUST_US(same_devnode, s)) { *_set = NULL; return 0; } set = set_new(NULL); if (!set) return -ENOMEM; LIST_FOREACH_OTHERS(same_devnode, other, s) { r = set_put(set, other); if (r < 0) goto fail; } *_set = set; return 1; fail: set_free(set); return r; } static void swap_shutdown(Manager *m) { assert(m); m->swap_event_source = sd_event_source_unref(m->swap_event_source); m->proc_swaps = safe_fclose(m->proc_swaps); m->swaps_by_devnode = hashmap_free(m->swaps_by_devnode); } static void swap_enumerate(Manager *m) { int r; assert(m); if (!m->proc_swaps) { m->proc_swaps = fopen("/proc/swaps", "re"); if (!m->proc_swaps) { if (errno == ENOENT) log_debug("Not swap enabled, skipping enumeration"); else log_error_errno(errno, "Failed to open /proc/swaps: %m"); return; } r = sd_event_add_io(m->event, &m->swap_event_source, fileno(m->proc_swaps), EPOLLPRI, swap_dispatch_io, m); if (r < 0) { log_error_errno(r, "Failed to watch /proc/swaps: %m"); goto fail; } /* Dispatch this before we dispatch SIGCHLD, so that * we always get the events from /proc/swaps before * the SIGCHLD of /sbin/swapon. */ r = sd_event_source_set_priority(m->swap_event_source, -10); if (r < 0) { log_error_errno(r, "Failed to change /proc/swaps priority: %m"); goto fail; } (void) sd_event_source_set_description(m->swap_event_source, "swap-proc"); } r = swap_load_proc_swaps(m, false); if (r < 0) goto fail; return; fail: swap_shutdown(m); } int swap_process_device_new(Manager *m, struct udev_device *dev) { struct udev_list_entry *item = NULL, *first = NULL; _cleanup_free_ char *e = NULL; const char *dn; Swap *s; int r = 0; assert(m); assert(dev); dn = udev_device_get_devnode(dev); if (!dn) return 0; r = unit_name_from_path(dn, ".swap", &e); if (r < 0) return r; s = hashmap_get(m->units, e); if (s) r = swap_set_devnode(s, dn); first = udev_device_get_devlinks_list_entry(dev); udev_list_entry_foreach(item, first) { _cleanup_free_ char *n = NULL; int q; q = unit_name_from_path(udev_list_entry_get_name(item), ".swap", &n); if (q < 0) return q; s = hashmap_get(m->units, n); if (s) { q = swap_set_devnode(s, dn); if (q < 0) r = q; } } return r; } int swap_process_device_remove(Manager *m, struct udev_device *dev) { const char *dn; int r = 0; Swap *s; dn = udev_device_get_devnode(dev); if (!dn) return 0; while ((s = hashmap_get(m->swaps_by_devnode, dn))) { int q; q = swap_set_devnode(s, NULL); if (q < 0) r = q; } return r; } static void swap_reset_failed(Unit *u) { Swap *s = SWAP(u); assert(s); if (s->state == SWAP_FAILED) swap_set_state(s, SWAP_DEAD); s->result = SWAP_SUCCESS; } static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error); } static int swap_get_timeout(Unit *u, usec_t *timeout) { Swap *s = SWAP(u); usec_t t; int r; if (!s->timer_event_source) return 0; r = sd_event_source_get_time(s->timer_event_source, &t); if (r < 0) return r; if (t == USEC_INFINITY) return 0; *timeout = t; return 1; } static bool swap_supported(void) { static int supported = -1; /* If swap support is not available in the kernel, or we are * running in a container we don't support swap units, and any * attempts to starting one should fail immediately. */ if (supported < 0) supported = access("/proc/swaps", F_OK) >= 0 && detect_container() <= 0; return supported; } static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = { [SWAP_EXEC_ACTIVATE] = "ExecActivate", [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate", }; DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand); static const char* const swap_result_table[_SWAP_RESULT_MAX] = { [SWAP_SUCCESS] = "success", [SWAP_FAILURE_RESOURCES] = "resources", [SWAP_FAILURE_TIMEOUT] = "timeout", [SWAP_FAILURE_EXIT_CODE] = "exit-code", [SWAP_FAILURE_SIGNAL] = "signal", [SWAP_FAILURE_CORE_DUMP] = "core-dump" }; DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult); const UnitVTable swap_vtable = { .object_size = sizeof(Swap), .exec_context_offset = offsetof(Swap, exec_context), .cgroup_context_offset = offsetof(Swap, cgroup_context), .kill_context_offset = offsetof(Swap, kill_context), .exec_runtime_offset = offsetof(Swap, exec_runtime), .sections = "Unit\0" "Swap\0" "Install\0", .private_section = "Swap", .no_alias = true, .no_instances = true, .init = swap_init, .load = swap_load, .done = swap_done, .coldplug = swap_coldplug, .dump = swap_dump, .start = swap_start, .stop = swap_stop, .kill = swap_kill, .get_timeout = swap_get_timeout, .serialize = swap_serialize, .deserialize_item = swap_deserialize_item, .active_state = swap_active_state, .sub_state_to_string = swap_sub_state_to_string, .check_gc = swap_check_gc, .sigchld_event = swap_sigchld_event, .reset_failed = swap_reset_failed, .bus_vtable = bus_swap_vtable, .bus_set_property = bus_swap_set_property, .bus_commit_properties = bus_swap_commit_properties, .following = swap_following, .following_set = swap_following_set, .enumerate = swap_enumerate, .shutdown = swap_shutdown, .supported = swap_supported, .status_message_formats = { .starting_stopping = { [0] = "Activating swap %s...", [1] = "Deactivating swap %s...", }, .finished_start_job = { [JOB_DONE] = "Activated swap %s.", [JOB_FAILED] = "Failed to activate swap %s.", [JOB_TIMEOUT] = "Timed out activating swap %s.", }, .finished_stop_job = { [JOB_DONE] = "Deactivated swap %s.", [JOB_FAILED] = "Failed deactivating swap %s.", [JOB_TIMEOUT] = "Timed out deactivating swap %s.", }, }, }; systemd-229/src/core/swap.h000066400000000000000000000060271265713322000157300ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2010 Maarten Lankhorst systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "libudev.h" typedef struct Swap Swap; typedef enum SwapExecCommand { SWAP_EXEC_ACTIVATE, SWAP_EXEC_DEACTIVATE, _SWAP_EXEC_COMMAND_MAX, _SWAP_EXEC_COMMAND_INVALID = -1 } SwapExecCommand; typedef enum SwapResult { SWAP_SUCCESS, SWAP_FAILURE_RESOURCES, SWAP_FAILURE_TIMEOUT, SWAP_FAILURE_EXIT_CODE, SWAP_FAILURE_SIGNAL, SWAP_FAILURE_CORE_DUMP, _SWAP_RESULT_MAX, _SWAP_RESULT_INVALID = -1 } SwapResult; typedef struct SwapParameters { char *what; char *options; int priority; } SwapParameters; struct Swap { Unit meta; char *what; /* If the device has already shown up, this is the device * node, which might be different from what, due to * symlinks */ char *devnode; SwapParameters parameters_proc_swaps; SwapParameters parameters_fragment; bool from_proc_swaps:1; bool from_fragment:1; /* Used while looking for swaps that vanished or got added * from/to /proc/swaps */ bool is_active:1; bool just_activated:1; bool reset_cpu_usage:1; SwapResult result; usec_t timeout_usec; ExecCommand exec_command[_SWAP_EXEC_COMMAND_MAX]; ExecContext exec_context; KillContext kill_context; CGroupContext cgroup_context; ExecRuntime *exec_runtime; SwapState state, deserialized_state; ExecCommand* control_command; SwapExecCommand control_command_id; pid_t control_pid; sd_event_source *timer_event_source; /* In order to be able to distinguish dependencies on different device nodes we might end up creating multiple devices for the same swap. We chain them up here. */ LIST_FIELDS(struct Swap, same_devnode); }; extern const UnitVTable swap_vtable; int swap_process_device_new(Manager *m, struct udev_device *dev); int swap_process_device_remove(Manager *m, struct udev_device *dev); const char* swap_exec_command_to_string(SwapExecCommand i) _const_; SwapExecCommand swap_exec_command_from_string(const char *s) _pure_; const char* swap_result_to_string(SwapResult i) _const_; SwapResult swap_result_from_string(const char *s) _pure_; systemd-229/src/core/system.conf000066400000000000000000000030051265713322000167710ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # Entries in this file show the compile time defaults. # You can change settings by editing this file. # Defaults can be restored by simply deleting this file. # # See systemd-system.conf(5) for details. [Manager] #LogLevel=info #LogTarget=journal-or-kmsg #LogColor=yes #LogLocation=no #DumpCore=yes #ShowStatus=yes #CrashChangeVT=no #CrashShell=no #CrashReboot=no #CPUAffinity=1 2 #JoinControllers=cpu,cpuacct net_cls,net_prio #RuntimeWatchdogSec=0 #ShutdownWatchdogSec=10min #CapabilityBoundingSet= #SystemCallArchitectures= #TimerSlackNSec= #DefaultTimerAccuracySec=1min #DefaultStandardOutput=journal #DefaultStandardError=inherit #DefaultTimeoutStartSec=90s #DefaultTimeoutStopSec=90s #DefaultRestartSec=100ms #DefaultStartLimitInterval=10s #DefaultStartLimitBurst=5 #DefaultEnvironment= #DefaultCPUAccounting=no #DefaultBlockIOAccounting=no #DefaultMemoryAccounting=no #DefaultTasksAccounting=yes #DefaultTasksMax=512 #DefaultLimitCPU= #DefaultLimitFSIZE= #DefaultLimitDATA= #DefaultLimitSTACK= #DefaultLimitCORE= #DefaultLimitRSS= #DefaultLimitNOFILE= #DefaultLimitAS= #DefaultLimitNPROC= #DefaultLimitMEMLOCK= #DefaultLimitLOCKS= #DefaultLimitSIGPENDING= #DefaultLimitMSGQUEUE= #DefaultLimitNICE= #DefaultLimitRTPRIO= #DefaultLimitRTTIME= systemd-229/src/core/systemd.pc.in000066400000000000000000000026371265713322000172310ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. prefix=@prefix@ systemdutildir=@rootlibexecdir@ systemdsystemunitdir=@systemunitdir@ systemdsystempresetdir=@systempresetdir@ systemduserunitdir=@userunitdir@ systemduserpresetdir=@userpresetdir@ systemdsystemconfdir=@pkgsysconfdir@/system systemduserconfdir=@pkgsysconfdir@/user systemdsystemunitpath=${systemdsystemconfdir}:/etc/systemd/system:/run/systemd/system:/usr/local/lib/systemd/system:${systemdsystemunitdir}:/usr/lib/systemd/system:/lib/systemd/system systemduserunitpath=${systemduserconfdir}:/etc/systemd/user:/run/systemd/user:/usr/local/lib/systemd/user:/usr/local/share/systemd/user:${systemduserunitdir}:/usr/lib/systemd/user:/usr/share/systemd/user systemdsystemgeneratordir=@systemgeneratordir@ systemdusergeneratordir=@usergeneratordir@ systemdsleepdir=@systemsleepdir@ systemdshutdowndir=@systemshutdowndir@ tmpfilesdir=@tmpfilesdir@ sysusersdir=@sysusersdir@ sysctldir=@sysctldir@ binfmtdir=@binfmtdir@ modulesloaddir=@modulesloaddir@ catalogdir=@catalogdir@ systemuidmax=@systemuidmax@ systemgidmax=@systemgidmax@ Name: systemd Description: systemd System and Service Manager URL: @PACKAGE_URL@ Version: @PACKAGE_VERSION@ systemd-229/src/core/target.c000066400000000000000000000136061265713322000162400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "dbus-target.h" #include "log.h" #include "special.h" #include "string-util.h" #include "unit-name.h" #include "unit.h" #include "target.h" static const UnitActiveState state_translation_table[_TARGET_STATE_MAX] = { [TARGET_DEAD] = UNIT_INACTIVE, [TARGET_ACTIVE] = UNIT_ACTIVE }; static void target_set_state(Target *t, TargetState state) { TargetState old_state; assert(t); old_state = t->state; t->state = state; if (state != old_state) log_debug("%s changed %s -> %s", UNIT(t)->id, target_state_to_string(old_state), target_state_to_string(state)); unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true); } static int target_add_default_dependencies(Target *t) { static const UnitDependency deps[] = { UNIT_REQUIRES, UNIT_REQUISITE, UNIT_WANTS, UNIT_BINDS_TO, UNIT_PART_OF }; Iterator i; Unit *other; int r; unsigned k; assert(t); /* Imply ordering for requirement dependencies on target * units. Note that when the user created a contradicting * ordering manually we won't add anything in here to make * sure we don't create a loop. */ for (k = 0; k < ELEMENTSOF(deps); k++) SET_FOREACH(other, UNIT(t)->dependencies[deps[k]], i) { r = unit_add_default_target_dependency(other, UNIT(t)); if (r < 0) return r; } /* Make sure targets are unloaded on shutdown */ return unit_add_dependency_by_name(UNIT(t), UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true); } static int target_load(Unit *u) { Target *t = TARGET(u); int r; assert(t); r = unit_load_fragment_and_dropin(u); if (r < 0) return r; /* This is a new unit? Then let's add in some extras */ if (u->load_state == UNIT_LOADED && u->default_dependencies) { r = target_add_default_dependencies(t); if (r < 0) return r; } return 0; } static int target_coldplug(Unit *u) { Target *t = TARGET(u); assert(t); assert(t->state == TARGET_DEAD); if (t->deserialized_state != t->state) target_set_state(t, t->deserialized_state); return 0; } static void target_dump(Unit *u, FILE *f, const char *prefix) { Target *t = TARGET(u); assert(t); assert(f); fprintf(f, "%sTarget State: %s\n", prefix, target_state_to_string(t->state)); } static int target_start(Unit *u) { Target *t = TARGET(u); assert(t); assert(t->state == TARGET_DEAD); target_set_state(t, TARGET_ACTIVE); return 1; } static int target_stop(Unit *u) { Target *t = TARGET(u); assert(t); assert(t->state == TARGET_ACTIVE); target_set_state(t, TARGET_DEAD); return 1; } static int target_serialize(Unit *u, FILE *f, FDSet *fds) { Target *s = TARGET(u); assert(s); assert(f); assert(fds); unit_serialize_item(u, f, "state", target_state_to_string(s->state)); return 0; } static int target_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Target *s = TARGET(u); assert(u); assert(key); assert(value); assert(fds); if (streq(key, "state")) { TargetState state; state = target_state_from_string(value); if (state < 0) log_debug("Failed to parse state value %s", value); else s->deserialized_state = state; } else log_debug("Unknown serialization key '%s'", key); return 0; } _pure_ static UnitActiveState target_active_state(Unit *u) { assert(u); return state_translation_table[TARGET(u)->state]; } _pure_ static const char *target_sub_state_to_string(Unit *u) { assert(u); return target_state_to_string(TARGET(u)->state); } const UnitVTable target_vtable = { .object_size = sizeof(Target), .sections = "Unit\0" "Target\0" "Install\0", .load = target_load, .coldplug = target_coldplug, .dump = target_dump, .start = target_start, .stop = target_stop, .serialize = target_serialize, .deserialize_item = target_deserialize_item, .active_state = target_active_state, .sub_state_to_string = target_sub_state_to_string, .bus_vtable = bus_target_vtable, .status_message_formats = { .finished_start_job = { [JOB_DONE] = "Reached target %s.", }, .finished_stop_job = { [JOB_DONE] = "Stopped target %s.", }, }, }; systemd-229/src/core/target.h000066400000000000000000000015721265713322000162440ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Target Target; struct Target { Unit meta; TargetState state, deserialized_state; }; extern const UnitVTable target_vtable; systemd-229/src/core/timer.c000066400000000000000000000656641265713322000161050ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "dbus-timer.h" #include "fs-util.h" #include "parse-util.h" #include "random-util.h" #include "special.h" #include "string-table.h" #include "string-util.h" #include "timer.h" #include "unit-name.h" #include "unit.h" #include "user-util.h" #include "virt.h" static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = { [TIMER_DEAD] = UNIT_INACTIVE, [TIMER_WAITING] = UNIT_ACTIVE, [TIMER_RUNNING] = UNIT_ACTIVE, [TIMER_ELAPSED] = UNIT_ACTIVE, [TIMER_FAILED] = UNIT_FAILED }; static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata); static void timer_init(Unit *u) { Timer *t = TIMER(u); assert(u); assert(u->load_state == UNIT_STUB); t->next_elapse_monotonic_or_boottime = USEC_INFINITY; t->next_elapse_realtime = USEC_INFINITY; t->accuracy_usec = u->manager->default_timer_accuracy_usec; t->remain_after_elapse = true; } void timer_free_values(Timer *t) { TimerValue *v; assert(t); while ((v = t->values)) { LIST_REMOVE(value, t->values, v); calendar_spec_free(v->calendar_spec); free(v); } } static void timer_done(Unit *u) { Timer *t = TIMER(u); assert(t); timer_free_values(t); t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source); t->realtime_event_source = sd_event_source_unref(t->realtime_event_source); free(t->stamp_path); } static int timer_verify(Timer *t) { assert(t); if (UNIT(t)->load_state != UNIT_LOADED) return 0; if (!t->values) { log_unit_error(UNIT(t), "Timer unit lacks value setting. Refusing."); return -EINVAL; } return 0; } static int timer_add_default_dependencies(Timer *t) { int r; TimerValue *v; assert(t); if (!UNIT(t)->default_dependencies) return 0; r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_TIMERS_TARGET, NULL, true); if (r < 0) return r; if (UNIT(t)->manager->running_as == MANAGER_SYSTEM) { r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true); if (r < 0) return r; LIST_FOREACH(value, v, t->values) { if (v->base == TIMER_CALENDAR) { r = unit_add_dependency_by_name(UNIT(t), UNIT_AFTER, SPECIAL_TIME_SYNC_TARGET, NULL, true); if (r < 0) return r; break; } } } return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true); } static int timer_setup_persistent(Timer *t) { int r; assert(t); if (!t->persistent) return 0; if (UNIT(t)->manager->running_as == MANAGER_SYSTEM) { r = unit_require_mounts_for(UNIT(t), "/var/lib/systemd/timers"); if (r < 0) return r; t->stamp_path = strappend("/var/lib/systemd/timers/stamp-", UNIT(t)->id); } else { const char *e; e = getenv("XDG_DATA_HOME"); if (e) t->stamp_path = strjoin(e, "/systemd/timers/stamp-", UNIT(t)->id, NULL); else { _cleanup_free_ char *h = NULL; r = get_home_dir(&h); if (r < 0) return log_unit_error_errno(UNIT(t), r, "Failed to determine home directory: %m"); t->stamp_path = strjoin(h, "/.local/share/systemd/timers/stamp-", UNIT(t)->id, NULL); } } if (!t->stamp_path) return log_oom(); return 0; } static int timer_load(Unit *u) { Timer *t = TIMER(u); int r; assert(u); assert(u->load_state == UNIT_STUB); r = unit_load_fragment_and_dropin(u); if (r < 0) return r; if (u->load_state == UNIT_LOADED) { if (set_isempty(u->dependencies[UNIT_TRIGGERS])) { Unit *x; r = unit_load_related_unit(u, ".service", &x); if (r < 0) return r; r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, x, true); if (r < 0) return r; } r = timer_setup_persistent(t); if (r < 0) return r; r = timer_add_default_dependencies(t); if (r < 0) return r; } return timer_verify(t); } static void timer_dump(Unit *u, FILE *f, const char *prefix) { char buf[FORMAT_TIMESPAN_MAX]; Timer *t = TIMER(u); Unit *trigger; TimerValue *v; trigger = UNIT_TRIGGER(u); fprintf(f, "%sTimer State: %s\n" "%sResult: %s\n" "%sUnit: %s\n" "%sPersistent: %s\n" "%sWakeSystem: %s\n" "%sAccuracy: %s\n" "%sRemainAfterElapse: %s\n", prefix, timer_state_to_string(t->state), prefix, timer_result_to_string(t->result), prefix, trigger ? trigger->id : "n/a", prefix, yes_no(t->persistent), prefix, yes_no(t->wake_system), prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1), prefix, yes_no(t->remain_after_elapse)); LIST_FOREACH(value, v, t->values) { if (v->base == TIMER_CALENDAR) { _cleanup_free_ char *p = NULL; calendar_spec_to_string(v->calendar_spec, &p); fprintf(f, "%s%s: %s\n", prefix, timer_base_to_string(v->base), strna(p)); } else { char timespan1[FORMAT_TIMESPAN_MAX]; fprintf(f, "%s%s: %s\n", prefix, timer_base_to_string(v->base), format_timespan(timespan1, sizeof(timespan1), v->value, 0)); } } } static void timer_set_state(Timer *t, TimerState state) { TimerState old_state; assert(t); old_state = t->state; t->state = state; if (state != TIMER_WAITING) { t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source); t->realtime_event_source = sd_event_source_unref(t->realtime_event_source); } if (state != old_state) log_unit_debug(UNIT(t), "Changed %s -> %s", timer_state_to_string(old_state), timer_state_to_string(state)); unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true); } static void timer_enter_waiting(Timer *t, bool initial); static int timer_coldplug(Unit *u) { Timer *t = TIMER(u); assert(t); assert(t->state == TIMER_DEAD); if (t->deserialized_state == t->state) return 0; if (t->deserialized_state == TIMER_WAITING) timer_enter_waiting(t, false); else timer_set_state(t, t->deserialized_state); return 0; } static void timer_enter_dead(Timer *t, TimerResult f) { assert(t); if (f != TIMER_SUCCESS) t->result = f; timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD); } static void timer_enter_elapsed(Timer *t, bool leave_around) { assert(t); /* If a unit is marked with RemainAfterElapse=yes we leave it * around even after it elapsed once, so that starting it * later again does not necessarily mean immediate * retriggering. We unconditionally leave units with * TIMER_UNIT_ACTIVE or TIMER_UNIT_INACTIVE triggers around, * since they might be restarted automatically at any time * later on. */ if (t->remain_after_elapse || leave_around) timer_set_state(t, TIMER_ELAPSED); else timer_enter_dead(t, TIMER_SUCCESS); } static usec_t monotonic_to_boottime(usec_t t) { usec_t a, b; if (t <= 0) return 0; a = now(CLOCK_BOOTTIME); b = now(CLOCK_MONOTONIC); if (t + a > b) return t + a - b; else return 0; } static void add_random(Timer *t, usec_t *v) { char s[FORMAT_TIMESPAN_MAX]; usec_t add; assert(t); assert(*v); if (t->random_usec == 0) return; if (*v == USEC_INFINITY) return; add = random_u64() % t->random_usec; if (*v + add < *v) /* overflow */ *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */ else *v += add; log_unit_info(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0)); } static void timer_enter_waiting(Timer *t, bool initial) { bool found_monotonic = false, found_realtime = false; usec_t ts_realtime, ts_monotonic; usec_t base = 0; bool leave_around = false; TimerValue *v; Unit *trigger; int r; assert(t); trigger = UNIT_TRIGGER(UNIT(t)); if (!trigger) { log_unit_error(UNIT(t), "Unit to trigger vanished."); timer_enter_dead(t, TIMER_FAILURE_RESOURCES); return; } /* If we shall wake the system we use the boottime clock * rather than the monotonic clock. */ ts_realtime = now(CLOCK_REALTIME); ts_monotonic = now(t->wake_system ? CLOCK_BOOTTIME : CLOCK_MONOTONIC); t->next_elapse_monotonic_or_boottime = t->next_elapse_realtime = 0; LIST_FOREACH(value, v, t->values) { if (v->disabled) continue; if (v->base == TIMER_CALENDAR) { usec_t b; /* If we know the last time this was * triggered, schedule the job based relative * to that. If we don't just start from * now. */ b = t->last_trigger.realtime > 0 ? t->last_trigger.realtime : ts_realtime; r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse); if (r < 0) continue; if (!found_realtime) t->next_elapse_realtime = v->next_elapse; else t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse); found_realtime = true; } else { switch (v->base) { case TIMER_ACTIVE: if (state_translation_table[t->state] == UNIT_ACTIVE) base = UNIT(t)->inactive_exit_timestamp.monotonic; else base = ts_monotonic; break; case TIMER_BOOT: if (detect_container() <= 0) { /* CLOCK_MONOTONIC equals the uptime on Linux */ base = 0; break; } /* In a container we don't want to include the time the host * was already up when the container started, so count from * our own startup. Fall through. */ case TIMER_STARTUP: base = UNIT(t)->manager->userspace_timestamp.monotonic; break; case TIMER_UNIT_ACTIVE: leave_around = true; base = trigger->inactive_exit_timestamp.monotonic; if (base <= 0) base = t->last_trigger.monotonic; if (base <= 0) continue; break; case TIMER_UNIT_INACTIVE: leave_around = true; base = trigger->inactive_enter_timestamp.monotonic; if (base <= 0) base = t->last_trigger.monotonic; if (base <= 0) continue; break; default: assert_not_reached("Unknown timer base"); } if (t->wake_system) base = monotonic_to_boottime(base); v->next_elapse = base + v->value; if (!initial && v->next_elapse < ts_monotonic && IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) { /* This is a one time trigger, disable it now */ v->disabled = true; continue; } if (!found_monotonic) t->next_elapse_monotonic_or_boottime = v->next_elapse; else t->next_elapse_monotonic_or_boottime = MIN(t->next_elapse_monotonic_or_boottime, v->next_elapse); found_monotonic = true; } } if (!found_monotonic && !found_realtime) { log_unit_debug(UNIT(t), "Timer is elapsed."); timer_enter_elapsed(t, leave_around); return; } if (found_monotonic) { char buf[FORMAT_TIMESPAN_MAX]; usec_t left; add_random(t, &t->next_elapse_monotonic_or_boottime); left = t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0; log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), left, 0)); if (t->monotonic_event_source) { r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic_or_boottime); if (r < 0) goto fail; r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT); if (r < 0) goto fail; } else { r = sd_event_add_time( UNIT(t)->manager->event, &t->monotonic_event_source, t->wake_system ? CLOCK_BOOTTIME_ALARM : CLOCK_MONOTONIC, t->next_elapse_monotonic_or_boottime, t->accuracy_usec, timer_dispatch, t); if (r < 0) goto fail; (void) sd_event_source_set_description(t->monotonic_event_source, "timer-monotonic"); } } else if (t->monotonic_event_source) { r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF); if (r < 0) goto fail; } if (found_realtime) { char buf[FORMAT_TIMESTAMP_MAX]; add_random(t, &t->next_elapse_realtime); log_unit_debug(UNIT(t), "Realtime timer elapses at %s.", format_timestamp(buf, sizeof(buf), t->next_elapse_realtime)); if (t->realtime_event_source) { r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime); if (r < 0) goto fail; r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT); if (r < 0) goto fail; } else { r = sd_event_add_time( UNIT(t)->manager->event, &t->realtime_event_source, t->wake_system ? CLOCK_REALTIME_ALARM : CLOCK_REALTIME, t->next_elapse_realtime, t->accuracy_usec, timer_dispatch, t); if (r < 0) goto fail; (void) sd_event_source_set_description(t->realtime_event_source, "timer-realtime"); } } else if (t->realtime_event_source) { r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF); if (r < 0) goto fail; } timer_set_state(t, TIMER_WAITING); return; fail: log_unit_warning_errno(UNIT(t), r, "Failed to enter waiting state: %m"); timer_enter_dead(t, TIMER_FAILURE_RESOURCES); } static void timer_enter_running(Timer *t) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; Unit *trigger; int r; assert(t); /* Don't start job if we are supposed to go down */ if (unit_stop_pending(UNIT(t))) return; trigger = UNIT_TRIGGER(UNIT(t)); if (!trigger) { log_unit_error(UNIT(t), "Unit to trigger vanished."); timer_enter_dead(t, TIMER_FAILURE_RESOURCES); return; } r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL); if (r < 0) goto fail; dual_timestamp_get(&t->last_trigger); if (t->stamp_path) touch_file(t->stamp_path, true, t->last_trigger.realtime, UID_INVALID, GID_INVALID, MODE_INVALID); timer_set_state(t, TIMER_RUNNING); return; fail: log_unit_warning(UNIT(t), "Failed to queue unit startup job: %s", bus_error_message(&error, r)); timer_enter_dead(t, TIMER_FAILURE_RESOURCES); } static int timer_start(Unit *u) { Timer *t = TIMER(u); TimerValue *v; Unit *trigger; assert(t); assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED); trigger = UNIT_TRIGGER(u); if (!trigger || trigger->load_state != UNIT_LOADED) { log_unit_error(u, "Refusing to start, unit to trigger not loaded."); return -ENOENT; } t->last_trigger = DUAL_TIMESTAMP_NULL; /* Reenable all timers that depend on unit activation time */ LIST_FOREACH(value, v, t->values) if (v->base == TIMER_ACTIVE) v->disabled = false; if (t->stamp_path) { struct stat st; if (stat(t->stamp_path, &st) >= 0) t->last_trigger.realtime = timespec_load(&st.st_atim); else if (errno == ENOENT) /* The timer has never run before, * make sure a stamp file exists. */ touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID); } t->result = TIMER_SUCCESS; timer_enter_waiting(t, true); return 1; } static int timer_stop(Unit *u) { Timer *t = TIMER(u); assert(t); assert(t->state == TIMER_WAITING || t->state == TIMER_RUNNING || t->state == TIMER_ELAPSED); timer_enter_dead(t, TIMER_SUCCESS); return 1; } static int timer_serialize(Unit *u, FILE *f, FDSet *fds) { Timer *t = TIMER(u); assert(u); assert(f); assert(fds); unit_serialize_item(u, f, "state", timer_state_to_string(t->state)); unit_serialize_item(u, f, "result", timer_result_to_string(t->result)); if (t->last_trigger.realtime > 0) unit_serialize_item_format(u, f, "last-trigger-realtime", "%" PRIu64, t->last_trigger.realtime); if (t->last_trigger.monotonic > 0) unit_serialize_item_format(u, f, "last-trigger-monotonic", "%" PRIu64, t->last_trigger.monotonic); return 0; } static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Timer *t = TIMER(u); int r; assert(u); assert(key); assert(value); assert(fds); if (streq(key, "state")) { TimerState state; state = timer_state_from_string(value); if (state < 0) log_unit_debug(u, "Failed to parse state value: %s", value); else t->deserialized_state = state; } else if (streq(key, "result")) { TimerResult f; f = timer_result_from_string(value); if (f < 0) log_unit_debug(u, "Failed to parse result value: %s", value); else if (f != TIMER_SUCCESS) t->result = f; } else if (streq(key, "last-trigger-realtime")) { r = safe_atou64(value, &t->last_trigger.realtime); if (r < 0) log_unit_debug(u, "Failed to parse last-trigger-realtime value: %s", value); } else if (streq(key, "last-trigger-monotonic")) { r = safe_atou64(value, &t->last_trigger.monotonic); if (r < 0) log_unit_debug(u, "Failed to parse last-trigger-monotonic value: %s", value); } else log_unit_debug(u, "Unknown serialization key: %s", key); return 0; } _pure_ static UnitActiveState timer_active_state(Unit *u) { assert(u); return state_translation_table[TIMER(u)->state]; } _pure_ static const char *timer_sub_state_to_string(Unit *u) { assert(u); return timer_state_to_string(TIMER(u)->state); } static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) { Timer *t = TIMER(userdata); assert(t); if (t->state != TIMER_WAITING) return 0; log_unit_debug(UNIT(t), "Timer elapsed."); timer_enter_running(t); return 0; } static void timer_trigger_notify(Unit *u, Unit *other) { Timer *t = TIMER(u); TimerValue *v; assert(u); assert(other); if (other->load_state != UNIT_LOADED) return; /* Reenable all timers that depend on unit state */ LIST_FOREACH(value, v, t->values) if (v->base == TIMER_UNIT_ACTIVE || v->base == TIMER_UNIT_INACTIVE) v->disabled = false; switch (t->state) { case TIMER_WAITING: case TIMER_ELAPSED: /* Recalculate sleep time */ timer_enter_waiting(t, false); break; case TIMER_RUNNING: if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) { log_unit_debug(UNIT(t), "Got notified about unit deactivation."); timer_enter_waiting(t, false); } break; case TIMER_DEAD: case TIMER_FAILED: break; default: assert_not_reached("Unknown timer state"); } } static void timer_reset_failed(Unit *u) { Timer *t = TIMER(u); assert(t); if (t->state == TIMER_FAILED) timer_set_state(t, TIMER_DEAD); t->result = TIMER_SUCCESS; } static void timer_time_change(Unit *u) { Timer *t = TIMER(u); assert(u); if (t->state != TIMER_WAITING) return; log_unit_debug(u, "Time change, recalculating next elapse."); timer_enter_waiting(t, false); } static const char* const timer_base_table[_TIMER_BASE_MAX] = { [TIMER_ACTIVE] = "OnActiveSec", [TIMER_BOOT] = "OnBootSec", [TIMER_STARTUP] = "OnStartupSec", [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec", [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec", [TIMER_CALENDAR] = "OnCalendar" }; DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase); static const char* const timer_result_table[_TIMER_RESULT_MAX] = { [TIMER_SUCCESS] = "success", [TIMER_FAILURE_RESOURCES] = "resources" }; DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult); const UnitVTable timer_vtable = { .object_size = sizeof(Timer), .sections = "Unit\0" "Timer\0" "Install\0", .private_section = "Timer", .init = timer_init, .done = timer_done, .load = timer_load, .coldplug = timer_coldplug, .dump = timer_dump, .start = timer_start, .stop = timer_stop, .serialize = timer_serialize, .deserialize_item = timer_deserialize_item, .active_state = timer_active_state, .sub_state_to_string = timer_sub_state_to_string, .trigger_notify = timer_trigger_notify, .reset_failed = timer_reset_failed, .time_change = timer_time_change, .bus_vtable = bus_timer_vtable, .bus_set_property = bus_timer_set_property, .can_transient = true, }; systemd-229/src/core/timer.h000066400000000000000000000044361265713322000161000ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Timer Timer; #include "calendarspec.h" typedef enum TimerBase { TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP, TIMER_UNIT_ACTIVE, TIMER_UNIT_INACTIVE, TIMER_CALENDAR, _TIMER_BASE_MAX, _TIMER_BASE_INVALID = -1 } TimerBase; typedef struct TimerValue { TimerBase base; bool disabled; usec_t value; /* only for monotonic events */ CalendarSpec *calendar_spec; /* only for calendar events */ usec_t next_elapse; LIST_FIELDS(struct TimerValue, value); } TimerValue; typedef enum TimerResult { TIMER_SUCCESS, TIMER_FAILURE_RESOURCES, _TIMER_RESULT_MAX, _TIMER_RESULT_INVALID = -1 } TimerResult; struct Timer { Unit meta; usec_t accuracy_usec; usec_t random_usec; LIST_HEAD(TimerValue, values); usec_t next_elapse_realtime; usec_t next_elapse_monotonic_or_boottime; dual_timestamp last_trigger; TimerState state, deserialized_state; sd_event_source *monotonic_event_source; sd_event_source *realtime_event_source; TimerResult result; bool persistent; bool wake_system; bool remain_after_elapse; char *stamp_path; }; void timer_free_values(Timer *t); extern const UnitVTable timer_vtable; const char *timer_base_to_string(TimerBase i) _const_; TimerBase timer_base_from_string(const char *s) _pure_; const char* timer_result_to_string(TimerResult i) _const_; TimerResult timer_result_from_string(const char *s) _pure_; systemd-229/src/core/transaction.c000066400000000000000000001212741265713322000173000ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "terminal-util.h" #include "transaction.h" #include "dbus-unit.h" static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies); static void transaction_delete_job(Transaction *tr, Job *j, bool delete_dependencies) { assert(tr); assert(j); /* Deletes one job from the transaction */ transaction_unlink_job(tr, j, delete_dependencies); job_free(j); } static void transaction_delete_unit(Transaction *tr, Unit *u) { Job *j; /* Deletes all jobs associated with a certain unit from the * transaction */ while ((j = hashmap_get(tr->jobs, u))) transaction_delete_job(tr, j, true); } void transaction_abort(Transaction *tr) { Job *j; assert(tr); while ((j = hashmap_first(tr->jobs))) transaction_delete_job(tr, j, false); assert(hashmap_isempty(tr->jobs)); } static void transaction_find_jobs_that_matter_to_anchor(Job *j, unsigned generation) { JobDependency *l; /* A recursive sweep through the graph that marks all units * that matter to the anchor job, i.e. are directly or * indirectly a dependency of the anchor job via paths that * are fully marked as mattering. */ j->matters_to_anchor = true; j->generation = generation; LIST_FOREACH(subject, l, j->subject_list) { /* This link does not matter */ if (!l->matters) continue; /* This unit has already been marked */ if (l->object->generation == generation) continue; transaction_find_jobs_that_matter_to_anchor(l->object, generation); } } static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other, JobType t) { JobDependency *l, *last; assert(j); assert(other); assert(j->unit == other->unit); assert(!j->installed); /* Merges 'other' into 'j' and then deletes 'other'. */ j->type = t; j->state = JOB_WAITING; j->irreversible = j->irreversible || other->irreversible; j->matters_to_anchor = j->matters_to_anchor || other->matters_to_anchor; /* Patch us in as new owner of the JobDependency objects */ last = NULL; LIST_FOREACH(subject, l, other->subject_list) { assert(l->subject == other); l->subject = j; last = l; } /* Merge both lists */ if (last) { last->subject_next = j->subject_list; if (j->subject_list) j->subject_list->subject_prev = last; j->subject_list = other->subject_list; } /* Patch us in as new owner of the JobDependency objects */ last = NULL; LIST_FOREACH(object, l, other->object_list) { assert(l->object == other); l->object = j; last = l; } /* Merge both lists */ if (last) { last->object_next = j->object_list; if (j->object_list) j->object_list->object_prev = last; j->object_list = other->object_list; } /* Kill the other job */ other->subject_list = NULL; other->object_list = NULL; transaction_delete_job(tr, other, true); } _pure_ static bool job_is_conflicted_by(Job *j) { JobDependency *l; assert(j); /* Returns true if this job is pulled in by a least one * ConflictedBy dependency. */ LIST_FOREACH(object, l, j->object_list) if (l->conflicts) return true; return false; } static int delete_one_unmergeable_job(Transaction *tr, Job *j) { Job *k; assert(j); /* Tries to delete one item in the linked list * j->transaction_next->transaction_next->... that conflicts * with another one, in an attempt to make an inconsistent * transaction work. */ /* We rely here on the fact that if a merged with b does not * merge with c, either a or b merge with c neither */ LIST_FOREACH(transaction, j, j) LIST_FOREACH(transaction, k, j->transaction_next) { Job *d; /* Is this one mergeable? Then skip it */ if (job_type_is_mergeable(j->type, k->type)) continue; /* Ok, we found two that conflict, let's see if we can * drop one of them */ if (!j->matters_to_anchor && !k->matters_to_anchor) { /* Both jobs don't matter, so let's * find the one that is smarter to * remove. Let's think positive and * rather remove stops then starts -- * except if something is being * stopped because it is conflicted by * another unit in which case we * rather remove the start. */ log_unit_debug(j->unit, "Looking at job %s/%s conflicted_by=%s", j->unit->id, job_type_to_string(j->type), yes_no(j->type == JOB_STOP && job_is_conflicted_by(j))); log_unit_debug(k->unit, "Looking at job %s/%s conflicted_by=%s", k->unit->id, job_type_to_string(k->type), yes_no(k->type == JOB_STOP && job_is_conflicted_by(k))); if (j->type == JOB_STOP) { if (job_is_conflicted_by(j)) d = k; else d = j; } else if (k->type == JOB_STOP) { if (job_is_conflicted_by(k)) d = j; else d = k; } else d = j; } else if (!j->matters_to_anchor) d = j; else if (!k->matters_to_anchor) d = k; else return -ENOEXEC; /* Ok, we can drop one, so let's do so. */ log_unit_debug(d->unit, "Fixing conflicting jobs %s/%s,%s/%s by deleting job %s/%s", j->unit->id, job_type_to_string(j->type), k->unit->id, job_type_to_string(k->type), d->unit->id, job_type_to_string(d->type)); transaction_delete_job(tr, d, true); return 0; } return -EINVAL; } static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) { Job *j; Iterator i; int r; assert(tr); /* First step, check whether any of the jobs for one specific * task conflict. If so, try to drop one of them. */ HASHMAP_FOREACH(j, tr->jobs, i) { JobType t; Job *k; t = j->type; LIST_FOREACH(transaction, k, j->transaction_next) { if (job_type_merge_and_collapse(&t, k->type, j->unit) >= 0) continue; /* OK, we could not merge all jobs for this * action. Let's see if we can get rid of one * of them */ r = delete_one_unmergeable_job(tr, j); if (r >= 0) /* Ok, we managed to drop one, now * let's ask our callers to call us * again after garbage collecting */ return -EAGAIN; /* We couldn't merge anything. Failure */ return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, "Transaction contains conflicting jobs '%s' and '%s' for %s. " "Probably contradicting requirement dependencies configured.", job_type_to_string(t), job_type_to_string(k->type), k->unit->id); } } /* Second step, merge the jobs. */ HASHMAP_FOREACH(j, tr->jobs, i) { JobType t = j->type; Job *k; /* Merge all transaction jobs for j->unit */ LIST_FOREACH(transaction, k, j->transaction_next) assert_se(job_type_merge_and_collapse(&t, k->type, j->unit) == 0); while ((k = j->transaction_next)) { if (tr->anchor_job == k) { transaction_merge_and_delete_job(tr, k, j, t); j = k; } else transaction_merge_and_delete_job(tr, j, k, t); } assert(!j->transaction_next); assert(!j->transaction_prev); } return 0; } static void transaction_drop_redundant(Transaction *tr) { Job *j; Iterator i; /* Goes through the transaction and removes all jobs of the units * whose jobs are all noops. If not all of a unit's jobs are * redundant, they are kept. */ assert(tr); rescan: HASHMAP_FOREACH(j, tr->jobs, i) { Job *k; LIST_FOREACH(transaction, k, j) { if (tr->anchor_job == k || !job_type_is_redundant(k->type, unit_active_state(k->unit)) || (k->unit->job && job_type_is_conflicting(k->type, k->unit->job->type))) goto next_unit; } /* log_debug("Found redundant job %s/%s, dropping.", j->unit->id, job_type_to_string(j->type)); */ transaction_delete_job(tr, j, false); goto rescan; next_unit:; } } _pure_ static bool unit_matters_to_anchor(Unit *u, Job *j) { assert(u); assert(!j->transaction_prev); /* Checks whether at least one of the jobs for this unit * matters to the anchor. */ LIST_FOREACH(transaction, j, j) if (j->matters_to_anchor) return true; return false; } static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsigned generation, sd_bus_error *e) { Iterator i; Unit *u; int r; assert(tr); assert(j); assert(!j->transaction_prev); /* Does a recursive sweep through the ordering graph, looking * for a cycle. If we find a cycle we try to break it. */ /* Have we seen this before? */ if (j->generation == generation) { Job *k, *delete; /* If the marker is NULL we have been here already and * decided the job was loop-free from here. Hence * shortcut things and return right-away. */ if (!j->marker) return 0; /* So, the marker is not NULL and we already have been * here. We have a cycle. Let's try to break it. We go * backwards in our path and try to find a suitable * job to remove. We use the marker to find our way * back, since smart how we are we stored our way back * in there. */ log_unit_warning(j->unit, "Found ordering cycle on %s/%s", j->unit->id, job_type_to_string(j->type)); delete = NULL; for (k = from; k; k = ((k->generation == generation && k->marker != k) ? k->marker : NULL)) { /* logging for j not k here here to provide consistent narrative */ log_unit_warning(j->unit, "Found dependency on %s/%s", k->unit->id, job_type_to_string(k->type)); if (!delete && hashmap_get(tr->jobs, k->unit) && !unit_matters_to_anchor(k->unit, k)) /* Ok, we can drop this one, so let's * do so. */ delete = k; /* Check if this in fact was the beginning of * the cycle */ if (k == j) break; } if (delete) { /* logging for j not k here here to provide consistent narrative */ log_unit_warning(j->unit, "Breaking ordering cycle by deleting job %s/%s", delete->unit->id, job_type_to_string(delete->type)); log_unit_error(delete->unit, "Job %s/%s deleted to break ordering cycle starting with %s/%s", delete->unit->id, job_type_to_string(delete->type), j->unit->id, job_type_to_string(j->type)); unit_status_printf(delete->unit, ANSI_HIGHLIGHT_RED " SKIP " ANSI_NORMAL, "Ordering cycle found, skipping %s"); transaction_delete_unit(tr, delete->unit); return -EAGAIN; } log_error("Unable to break cycle"); return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC, "Transaction order is cyclic. See system logs for details."); } /* Make the marker point to where we come from, so that we can * find our way backwards if we want to break a cycle. We use * a special marker for the beginning: we point to * ourselves. */ j->marker = from ? from : j; j->generation = generation; /* We assume that the dependencies are bidirectional, and * hence can ignore UNIT_AFTER */ SET_FOREACH(u, j->unit->dependencies[UNIT_BEFORE], i) { Job *o; /* Is there a job for this unit? */ o = hashmap_get(tr->jobs, u); if (!o) { /* Ok, there is no job for this in the * transaction, but maybe there is already one * running? */ o = u->job; if (!o) continue; } r = transaction_verify_order_one(tr, o, j, generation, e); if (r < 0) return r; } /* Ok, let's backtrack, and remember that this entry is not on * our path anymore. */ j->marker = NULL; return 0; } static int transaction_verify_order(Transaction *tr, unsigned *generation, sd_bus_error *e) { Job *j; int r; Iterator i; unsigned g; assert(tr); assert(generation); /* Check if the ordering graph is cyclic. If it is, try to fix * that up by dropping one of the jobs. */ g = (*generation)++; HASHMAP_FOREACH(j, tr->jobs, i) { r = transaction_verify_order_one(tr, j, NULL, g, e); if (r < 0) return r; } return 0; } static void transaction_collect_garbage(Transaction *tr) { Iterator i; Job *j; assert(tr); /* Drop jobs that are not required by any other job */ rescan: HASHMAP_FOREACH(j, tr->jobs, i) { if (tr->anchor_job == j || j->object_list) { /* log_debug("Keeping job %s/%s because of %s/%s", */ /* j->unit->id, job_type_to_string(j->type), */ /* j->object_list->subject ? j->object_list->subject->unit->id : "root", */ /* j->object_list->subject ? job_type_to_string(j->object_list->subject->type) : "root"); */ continue; } /* log_debug("Garbage collecting job %s/%s", j->unit->id, job_type_to_string(j->type)); */ transaction_delete_job(tr, j, true); goto rescan; } } static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_error *e) { Iterator i; Job *j; assert(tr); /* Checks whether applying this transaction means that * existing jobs would be replaced */ HASHMAP_FOREACH(j, tr->jobs, i) { /* Assume merged */ assert(!j->transaction_prev); assert(!j->transaction_next); if (j->unit->job && (mode == JOB_FAIL || j->unit->job->irreversible) && job_type_is_conflicting(j->unit->job->type, j->type)) return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, "Transaction is destructive."); } return 0; } static void transaction_minimize_impact(Transaction *tr) { Job *j; Iterator i; assert(tr); /* Drops all unnecessary jobs that reverse already active jobs * or that stop a running service. */ rescan: HASHMAP_FOREACH(j, tr->jobs, i) { LIST_FOREACH(transaction, j, j) { bool stops_running_service, changes_existing_job; /* If it matters, we shouldn't drop it */ if (j->matters_to_anchor) continue; /* Would this stop a running service? * Would this change an existing job? * If so, let's drop this entry */ stops_running_service = j->type == JOB_STOP && UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(j->unit)); changes_existing_job = j->unit->job && job_type_is_conflicting(j->type, j->unit->job->type); if (!stops_running_service && !changes_existing_job) continue; if (stops_running_service) log_unit_debug(j->unit, "%s/%s would stop a running service.", j->unit->id, job_type_to_string(j->type)); if (changes_existing_job) log_unit_debug(j->unit, "%s/%s would change existing job.", j->unit->id, job_type_to_string(j->type)); /* Ok, let's get rid of this */ log_unit_debug(j->unit, "Deleting %s/%s to minimize impact.", j->unit->id, job_type_to_string(j->type)); transaction_delete_job(tr, j, true); goto rescan; } } } static int transaction_apply(Transaction *tr, Manager *m, JobMode mode) { Iterator i; Job *j; int r; /* Moves the transaction jobs to the set of active jobs */ if (mode == JOB_ISOLATE || mode == JOB_FLUSH) { /* When isolating first kill all installed jobs which * aren't part of the new transaction */ HASHMAP_FOREACH(j, m->jobs, i) { assert(j->installed); if (hashmap_get(tr->jobs, j->unit)) continue; /* Not invalidating recursively. Avoids triggering * OnFailure= actions of dependent jobs. Also avoids * invalidating our iterator. */ job_finish_and_invalidate(j, JOB_CANCELED, false); } } HASHMAP_FOREACH(j, tr->jobs, i) { /* Assume merged */ assert(!j->transaction_prev); assert(!j->transaction_next); r = hashmap_put(m->jobs, UINT32_TO_PTR(j->id), j); if (r < 0) goto rollback; } while ((j = hashmap_steal_first(tr->jobs))) { Job *installed_job; /* Clean the job dependencies */ transaction_unlink_job(tr, j, false); installed_job = job_install(j); if (installed_job != j) { /* j has been merged into a previously installed job */ if (tr->anchor_job == j) tr->anchor_job = installed_job; hashmap_remove(m->jobs, UINT32_TO_PTR(j->id)); job_free(j); j = installed_job; } job_add_to_run_queue(j); job_add_to_dbus_queue(j); job_start_timer(j); job_shutdown_magic(j); } return 0; rollback: HASHMAP_FOREACH(j, tr->jobs, i) hashmap_remove(m->jobs, UINT32_TO_PTR(j->id)); return r; } int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error *e) { Iterator i; Job *j; int r; unsigned generation = 1; assert(tr); /* This applies the changes recorded in tr->jobs to * the actual list of jobs, if possible. */ /* Reset the generation counter of all installed jobs. The detection of cycles * looks at installed jobs. If they had a non-zero generation from some previous * walk of the graph, the algorithm would break. */ HASHMAP_FOREACH(j, m->jobs, i) j->generation = 0; /* First step: figure out which jobs matter */ transaction_find_jobs_that_matter_to_anchor(tr->anchor_job, generation++); /* Second step: Try not to stop any running services if * we don't have to. Don't try to reverse running * jobs if we don't have to. */ if (mode == JOB_FAIL) transaction_minimize_impact(tr); /* Third step: Drop redundant jobs */ transaction_drop_redundant(tr); for (;;) { /* Fourth step: Let's remove unneeded jobs that might * be lurking. */ if (mode != JOB_ISOLATE) transaction_collect_garbage(tr); /* Fifth step: verify order makes sense and correct * cycles if necessary and possible */ r = transaction_verify_order(tr, &generation, e); if (r >= 0) break; if (r != -EAGAIN) { log_warning("Requested transaction contains an unfixable cyclic ordering dependency: %s", bus_error_message(e, r)); return r; } /* Let's see if the resulting transaction ordering * graph is still cyclic... */ } for (;;) { /* Sixth step: let's drop unmergeable entries if * necessary and possible, merge entries we can * merge */ r = transaction_merge_jobs(tr, e); if (r >= 0) break; if (r != -EAGAIN) { log_warning("Requested transaction contains unmergeable jobs: %s", bus_error_message(e, r)); return r; } /* Seventh step: an entry got dropped, let's garbage * collect its dependencies. */ if (mode != JOB_ISOLATE) transaction_collect_garbage(tr); /* Let's see if the resulting transaction still has * unmergeable entries ... */ } /* Eights step: Drop redundant jobs again, if the merging now allows us to drop more. */ transaction_drop_redundant(tr); /* Ninth step: check whether we can actually apply this */ r = transaction_is_destructive(tr, mode, e); if (r < 0) { log_notice("Requested transaction contradicts existing jobs: %s", bus_error_message(e, r)); return r; } /* Tenth step: apply changes */ r = transaction_apply(tr, m, mode); if (r < 0) return log_warning_errno(r, "Failed to apply transaction: %m"); assert(hashmap_isempty(tr->jobs)); if (!hashmap_isempty(m->jobs)) { /* Are there any jobs now? Then make sure we have the * idle pipe around. We don't really care too much * whether this works or not, as the idle pipe is a * feature for cosmetics, not actually useful for * anything beyond that. */ if (m->idle_pipe[0] < 0 && m->idle_pipe[1] < 0 && m->idle_pipe[2] < 0 && m->idle_pipe[3] < 0) { (void) pipe2(m->idle_pipe, O_NONBLOCK|O_CLOEXEC); (void) pipe2(m->idle_pipe + 2, O_NONBLOCK|O_CLOEXEC); } } return 0; } static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, bool *is_new) { Job *j, *f; assert(tr); assert(unit); /* Looks for an existing prospective job and returns that. If * it doesn't exist it is created and added to the prospective * jobs list. */ f = hashmap_get(tr->jobs, unit); LIST_FOREACH(transaction, j, f) { assert(j->unit == unit); if (j->type == type) { if (is_new) *is_new = false; return j; } } j = job_new(unit, type); if (!j) return NULL; j->generation = 0; j->marker = NULL; j->matters_to_anchor = false; j->irreversible = tr->irreversible; LIST_PREPEND(transaction, f, j); if (hashmap_replace(tr->jobs, unit, f) < 0) { LIST_REMOVE(transaction, f, j); job_free(j); return NULL; } if (is_new) *is_new = true; /* log_debug("Added job %s/%s to transaction.", unit->id, job_type_to_string(type)); */ return j; } static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies) { assert(tr); assert(j); if (j->transaction_prev) j->transaction_prev->transaction_next = j->transaction_next; else if (j->transaction_next) hashmap_replace(tr->jobs, j->unit, j->transaction_next); else hashmap_remove_value(tr->jobs, j->unit, j); if (j->transaction_next) j->transaction_next->transaction_prev = j->transaction_prev; j->transaction_prev = j->transaction_next = NULL; while (j->subject_list) job_dependency_free(j->subject_list); while (j->object_list) { Job *other = j->object_list->matters ? j->object_list->subject : NULL; job_dependency_free(j->object_list); if (other && delete_dependencies) { log_unit_debug(other->unit, "Deleting job %s/%s as dependency of job %s/%s", other->unit->id, job_type_to_string(other->type), j->unit->id, job_type_to_string(j->type)); transaction_delete_job(tr, other, delete_dependencies); } } } int transaction_add_job_and_dependencies( Transaction *tr, JobType type, Unit *unit, Job *by, bool matters, bool conflicts, bool ignore_requirements, bool ignore_order, sd_bus_error *e) { Job *ret; Iterator i; Unit *dep; int r; bool is_new; assert(tr); assert(type < _JOB_TYPE_MAX); assert(type < _JOB_TYPE_MAX_IN_TRANSACTION); assert(unit); /* Before adding jobs for this unit, let's ensure that its state has been loaded * This matters when jobs are spawned as part of coldplugging itself (see e. g. path_coldplug()). * This way, we "recursively" coldplug units, ensuring that we do not look at state of * not-yet-coldplugged units. */ if (unit->manager->n_reloading > 0) unit_coldplug(unit); /* log_debug("Pulling in %s/%s from %s/%s", */ /* unit->id, job_type_to_string(type), */ /* by ? by->unit->id : "NA", */ /* by ? job_type_to_string(by->type) : "NA"); */ if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_MASKED)) return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id); if (type != JOB_STOP) { r = bus_unit_check_load_state(unit, e); if (r < 0) return r; } if (!unit_job_is_applicable(unit, type)) return sd_bus_error_setf(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, "Job type %s is not applicable for unit %s.", job_type_to_string(type), unit->id); /* First add the job. */ ret = transaction_add_one_job(tr, type, unit, &is_new); if (!ret) return -ENOMEM; ret->ignore_order = ret->ignore_order || ignore_order; /* Then, add a link to the job. */ if (by) { if (!job_dependency_new(by, ret, matters, conflicts)) return -ENOMEM; } else { /* If the job has no parent job, it is the anchor job. */ assert(!tr->anchor_job); tr->anchor_job = ret; } if (is_new && !ignore_requirements && type != JOB_NOP) { Set *following; /* If we are following some other unit, make sure we * add all dependencies of everybody following. */ if (unit_following_set(ret->unit, &following) > 0) { SET_FOREACH(dep, following, i) { r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, false, false, ignore_order, e); if (r < 0) { log_unit_warning(dep, "Cannot add dependency job for, ignoring: %s", bus_error_message(e, r)); sd_bus_error_free(e); } } set_free(following); } /* Finally, recursively add in all dependencies. */ if (type == JOB_START || type == JOB_RESTART) { SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES], i) { r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, false, false, ignore_order, e); if (r < 0) { if (r != -EBADR) /* job type not applicable */ goto fail; sd_bus_error_free(e); } } SET_FOREACH(dep, ret->unit->dependencies[UNIT_BINDS_TO], i) { r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, false, false, ignore_order, e); if (r < 0) { if (r != -EBADR) /* job type not applicable */ goto fail; sd_bus_error_free(e); } } SET_FOREACH(dep, ret->unit->dependencies[UNIT_WANTS], i) { r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, ignore_order, e); if (r < 0) { /* unit masked, job type not applicable and unit not found are not considered as errors. */ log_unit_full(dep, IN_SET(r, -ESHUTDOWN, -EBADR, -ENOENT) ? LOG_DEBUG : LOG_WARNING, r, "Cannot add dependency job, ignoring: %s", bus_error_message(e, r)); sd_bus_error_free(e); } } SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE], i) { r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, true, false, false, ignore_order, e); if (r < 0) { if (r != -EBADR) /* job type not applicable */ goto fail; sd_bus_error_free(e); } } SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTS], i) { r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, true, true, false, ignore_order, e); if (r < 0) { if (r != -EBADR) /* job type not applicable */ goto fail; sd_bus_error_free(e); } } SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTED_BY], i) { r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, false, false, false, ignore_order, e); if (r < 0) { log_unit_warning(dep, "Cannot add dependency job, ignoring: %s", bus_error_message(e, r)); sd_bus_error_free(e); } } } if (type == JOB_STOP || type == JOB_RESTART) { static const UnitDependency propagate_deps[] = { UNIT_REQUIRED_BY, UNIT_REQUISITE_OF, UNIT_BOUND_BY, UNIT_CONSISTS_OF, }; JobType ptype; unsigned j; /* We propagate STOP as STOP, but RESTART only * as TRY_RESTART, in order not to start * dependencies that are not around. */ ptype = type == JOB_RESTART ? JOB_TRY_RESTART : type; for (j = 0; j < ELEMENTSOF(propagate_deps); j++) SET_FOREACH(dep, ret->unit->dependencies[propagate_deps[j]], i) { JobType nt; nt = job_type_collapse(ptype, dep); if (nt == JOB_NOP) continue; r = transaction_add_job_and_dependencies(tr, nt, dep, ret, true, false, false, ignore_order, e); if (r < 0) { if (r != -EBADR) /* job type not applicable */ goto fail; sd_bus_error_free(e); } } } if (type == JOB_RELOAD) { SET_FOREACH(dep, ret->unit->dependencies[UNIT_PROPAGATES_RELOAD_TO], i) { JobType nt; nt = job_type_collapse(JOB_TRY_RELOAD, dep); if (nt == JOB_NOP) continue; r = transaction_add_job_and_dependencies(tr, nt, dep, ret, false, false, false, ignore_order, e); if (r < 0) { log_unit_warning(dep, "Cannot add dependency reload job, ignoring: %s", bus_error_message(e, r)); sd_bus_error_free(e); } } } /* JOB_VERIFY_STARTED require no dependency handling */ } return 0; fail: return r; } int transaction_add_isolate_jobs(Transaction *tr, Manager *m) { Iterator i; Unit *u; char *k; int r; assert(tr); assert(m); HASHMAP_FOREACH_KEY(u, k, m->units, i) { /* ignore aliases */ if (u->id != k) continue; if (u->ignore_on_isolate) continue; /* No need to stop inactive jobs */ if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)) && !u->job) continue; /* Is there already something listed for this? */ if (hashmap_get(tr->jobs, u)) continue; r = transaction_add_job_and_dependencies(tr, JOB_STOP, u, tr->anchor_job, true, false, false, false, NULL); if (r < 0) log_unit_warning_errno(u, r, "Cannot add isolate job, ignoring: %m"); } return 0; } Transaction *transaction_new(bool irreversible) { Transaction *tr; tr = new0(Transaction, 1); if (!tr) return NULL; tr->jobs = hashmap_new(NULL); if (!tr->jobs) { free(tr); return NULL; } tr->irreversible = irreversible; return tr; } void transaction_free(Transaction *tr) { assert(hashmap_isempty(tr->jobs)); hashmap_free(tr->jobs); free(tr); } systemd-229/src/core/transaction.h000066400000000000000000000032161265713322000173000ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Transaction Transaction; #include "hashmap.h" #include "job.h" #include "manager.h" #include "unit.h" struct Transaction { /* Jobs to be added */ Hashmap *jobs; /* Unit object => Job object list 1:1 */ Job *anchor_job; /* the job the user asked for */ bool irreversible; }; Transaction *transaction_new(bool irreversible); void transaction_free(Transaction *tr); int transaction_add_job_and_dependencies( Transaction *tr, JobType type, Unit *unit, Job *by, bool matters, bool conflicts, bool ignore_requirements, bool ignore_order, sd_bus_error *e); int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error *e); int transaction_add_isolate_jobs(Transaction *tr, Manager *m); void transaction_abort(Transaction *tr); systemd-229/src/core/triggers.systemd.in000066400000000000000000000052561265713322000204550ustar00rootroot00000000000000# -*- Mode: rpm-spec; indent-tabs-mode: nil -*- */ # # This file is part of systemd. # # Copyright 2015 Zbigniew Jędrzejewski-Szmek # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # The contents of this are an example to be copied into systemd.spec. %transfiletriggerin -P 900900 -p -- @systemunitdir@ /etc/systemd/system -- This script will run after any package is initially installed or -- upgraded. We care about the case where a package is initially -- installed, because other cases are covered by the *un scriptlets, -- so sometimes we will reload needlessly. pid = posix.fork() if pid == 0 then assert(posix.exec("%{_bindir}/systemctl", "daemon-reload")) elseif pid > 0 then posix.wait(pid) end %transfiletriggerun -p -- @systemunitdir@ /etc/systemd/system -- On removal, we need to run daemon-reload after any units have been -- removed. %transfiletriggerpostun would be ideal, but it does not get -- executed for some reason. -- On upgrade, we need to run daemon-reload after any new unit files -- have been installed, but before %postun scripts in packages get -- executed. %transfiletriggerun gets the right list of files -- but it is invoked too early (before changes happen). -- %filetriggerpostun happens at the right time, but it fires for -- every package. -- To execute the reload at the right time, we create a state -- file in %transfiletriggerun and execute the daemon-reload in -- the first %filetriggerpostun. posix.mkdir("%{_localstatedir}/lib") posix.mkdir("%{_localstatedir}/lib/rpm-state") posix.mkdir("%{_localstatedir}/lib/rpm-state/systemd") io.open("%{_localstatedir}/lib/rpm-state/systemd/needs-reload", "w") %filetriggerpostun -P 1000100 -p -- @systemunitdir@ /etc/systemd/system if posix.access("%{_localstatedir}/lib/rpm-state/systemd/needs-reload") then posix.unlink("%{_localstatedir}/lib/rpm-state/systemd/needs-reload") posix.rmdir("%{_localstatedir}/lib/rpm-state/systemd") pid = posix.fork() if pid == 0 then assert(posix.exec("%{_bindir}/systemctl", "daemon-reload")) elseif pid > 0 then posix.wait(pid) end end systemd-229/src/core/umount.c000066400000000000000000000444551265713322000163070ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 ProFUSION embedded systems systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "libudev.h" #include "alloc-util.h" #include "escape.h" #include "fd-util.h" #include "fstab-util.h" #include "list.h" #include "mount-setup.h" #include "path-util.h" #include "string-util.h" #include "udev-util.h" #include "umount.h" #include "util.h" #include "virt.h" typedef struct MountPoint { char *path; char *options; dev_t devnum; LIST_FIELDS(struct MountPoint, mount_point); } MountPoint; static void mount_point_free(MountPoint **head, MountPoint *m) { assert(head); assert(m); LIST_REMOVE(mount_point, *head, m); free(m->path); free(m); } static void mount_points_list_free(MountPoint **head) { assert(head); while (*head) mount_point_free(head, *head); } static int mount_points_list_get(MountPoint **head) { _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; unsigned int i; int r; assert(head); proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); if (!proc_self_mountinfo) return -errno; for (i = 1;; i++) { _cleanup_free_ char *path = NULL, *options = NULL; char *p = NULL; MountPoint *m; int k; k = fscanf(proc_self_mountinfo, "%*s " /* (1) mount id */ "%*s " /* (2) parent id */ "%*s " /* (3) major:minor */ "%*s " /* (4) root */ "%ms " /* (5) mount point */ "%*s" /* (6) mount flags */ "%*[^-]" /* (7) optional fields */ "- " /* (8) separator */ "%*s " /* (9) file system type */ "%*s" /* (10) mount source */ "%ms" /* (11) mount options */ "%*[^\n]", /* some rubbish at the end */ &path, &options); if (k != 2) { if (k == EOF) break; log_warning("Failed to parse /proc/self/mountinfo:%u.", i); continue; } r = cunescape(path, UNESCAPE_RELAX, &p); if (r < 0) return r; /* Ignore mount points we can't unmount because they * are API or because we are keeping them open (like * /dev/console). Also, ignore all mounts below API * file systems, since they are likely virtual too, * and hence not worth spending time on. Also, in * unprivileged containers we might lack the rights to * unmount these things, hence don't bother. */ if (mount_point_is_api(p) || mount_point_ignore(p) || path_startswith(p, "/dev") || path_startswith(p, "/sys") || path_startswith(p, "/proc")) { free(p); continue; } m = new0(MountPoint, 1); if (!m) { free(p); return -ENOMEM; } m->path = p; m->options = options; options = NULL; LIST_PREPEND(mount_point, *head, m); } return 0; } static int swap_list_get(MountPoint **head) { _cleanup_fclose_ FILE *proc_swaps = NULL; unsigned int i; int r; assert(head); proc_swaps = fopen("/proc/swaps", "re"); if (!proc_swaps) return (errno == ENOENT) ? 0 : -errno; (void) fscanf(proc_swaps, "%*s %*s %*s %*s %*s\n"); for (i = 2;; i++) { MountPoint *swap; char *dev = NULL, *d; int k; k = fscanf(proc_swaps, "%ms " /* device/file */ "%*s " /* type of swap */ "%*s " /* swap size */ "%*s " /* used */ "%*s\n", /* priority */ &dev); if (k != 1) { if (k == EOF) break; log_warning("Failed to parse /proc/swaps:%u.", i); free(dev); continue; } if (endswith(dev, " (deleted)")) { free(dev); continue; } r = cunescape(dev, UNESCAPE_RELAX, &d); free(dev); if (r < 0) return r; swap = new0(MountPoint, 1); if (!swap) { free(d); return -ENOMEM; } swap->path = d; LIST_PREPEND(mount_point, *head, swap); } return 0; } static int loopback_list_get(MountPoint **head) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; struct udev_list_entry *item = NULL, *first = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; int r; assert(head); udev = udev_new(); if (!udev) return -ENOMEM; e = udev_enumerate_new(udev); if (!e) return -ENOMEM; r = udev_enumerate_add_match_subsystem(e, "block"); if (r < 0) return r; r = udev_enumerate_add_match_sysname(e, "loop*"); if (r < 0) return r; r = udev_enumerate_add_match_sysattr(e, "loop/backing_file", NULL); if (r < 0) return r; r = udev_enumerate_scan_devices(e); if (r < 0) return r; first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { MountPoint *lb; _cleanup_udev_device_unref_ struct udev_device *d; char *loop; const char *dn; d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!d) return -ENOMEM; dn = udev_device_get_devnode(d); if (!dn) continue; loop = strdup(dn); if (!loop) return -ENOMEM; lb = new0(MountPoint, 1); if (!lb) { free(loop); return -ENOMEM; } lb->path = loop; LIST_PREPEND(mount_point, *head, lb); } return 0; } static int dm_list_get(MountPoint **head) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; struct udev_list_entry *item = NULL, *first = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; int r; assert(head); udev = udev_new(); if (!udev) return -ENOMEM; e = udev_enumerate_new(udev); if (!e) return -ENOMEM; r = udev_enumerate_add_match_subsystem(e, "block"); if (r < 0) return r; r = udev_enumerate_add_match_sysname(e, "dm-*"); if (r < 0) return r; r = udev_enumerate_scan_devices(e); if (r < 0) return r; first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { MountPoint *m; _cleanup_udev_device_unref_ struct udev_device *d; dev_t devnum; char *node; const char *dn; d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!d) return -ENOMEM; devnum = udev_device_get_devnum(d); dn = udev_device_get_devnode(d); if (major(devnum) == 0 || !dn) continue; node = strdup(dn); if (!node) return -ENOMEM; m = new(MountPoint, 1); if (!m) { free(node); return -ENOMEM; } m->path = node; m->devnum = devnum; LIST_PREPEND(mount_point, *head, m); } return 0; } static int delete_loopback(const char *device) { _cleanup_close_ int fd = -1; int r; fd = open(device, O_RDONLY|O_CLOEXEC); if (fd < 0) return errno == ENOENT ? 0 : -errno; r = ioctl(fd, LOOP_CLR_FD, 0); if (r >= 0) return 1; /* ENXIO: not bound, so no error */ if (errno == ENXIO) return 0; return -errno; } static int delete_dm(dev_t devnum) { _cleanup_close_ int fd = -1; int r; struct dm_ioctl dm = { .version = {DM_VERSION_MAJOR, DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL}, .data_size = sizeof(dm), .dev = devnum, }; assert(major(devnum) != 0); fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC); if (fd < 0) return -errno; r = ioctl(fd, DM_DEV_REMOVE, &dm); return r >= 0 ? 0 : -errno; } static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_error) { MountPoint *m, *n; int n_failed = 0; assert(head); LIST_FOREACH_SAFE(mount_point, m, n, *head) { /* If we are in a container, don't attempt to read-only mount anything as that brings no real benefits, but might confuse the host, as we remount the superblock here, not the bind mound. */ if (detect_container() <= 0) { _cleanup_free_ char *options = NULL; /* MS_REMOUNT requires that the data parameter * should be the same from the original mount * except for the desired changes. Since we want * to remount read-only, we should filter out * rw (and ro too, because it confuses the kernel) */ (void) fstab_filter_options(m->options, "rw\0ro\0", NULL, NULL, &options); /* We always try to remount directories * read-only first, before we go on and umount * them. * * Mount points can be stacked. If a mount * point is stacked below / or /usr, we * cannot umount or remount it directly, * since there is no way to refer to the * underlying mount. There's nothing we can do * about it for the general case, but we can * do something about it if it is aliased * somehwere else via a bind mount. If we * explicitly remount the super block of that * alias read-only we hence should be * relatively safe regarding keeping the fs we * can otherwise not see dirty. */ log_info("Remounting '%s' read-only with options '%s'.", m->path, options); (void) mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options); } /* Skip / and /usr since we cannot unmount that * anyway, since we are running from it. They have * already been remounted ro. */ if (path_equal(m->path, "/") #ifndef HAVE_SPLIT_USR || path_equal(m->path, "/usr") #endif ) continue; /* Trying to umount. We don't force here since we rely * on busy NFS and FUSE file systems to return EBUSY * until we closed everything on top of them. */ log_info("Unmounting %s.", m->path); if (umount2(m->path, 0) == 0) { if (changed) *changed = true; mount_point_free(head, m); } else if (log_error) { log_warning_errno(errno, "Could not unmount %s: %m", m->path); n_failed++; } } return n_failed; } static int swap_points_list_off(MountPoint **head, bool *changed) { MountPoint *m, *n; int n_failed = 0; assert(head); LIST_FOREACH_SAFE(mount_point, m, n, *head) { log_info("Deactivating swap %s.", m->path); if (swapoff(m->path) == 0) { if (changed) *changed = true; mount_point_free(head, m); } else { log_warning_errno(errno, "Could not deactivate swap %s: %m", m->path); n_failed++; } } return n_failed; } static int loopback_points_list_detach(MountPoint **head, bool *changed) { MountPoint *m, *n; int n_failed = 0, k; struct stat root_st; assert(head); k = lstat("/", &root_st); LIST_FOREACH_SAFE(mount_point, m, n, *head) { int r; struct stat loopback_st; if (k >= 0 && major(root_st.st_dev) != 0 && lstat(m->path, &loopback_st) >= 0 && root_st.st_dev == loopback_st.st_rdev) { n_failed ++; continue; } log_info("Detaching loopback %s.", m->path); r = delete_loopback(m->path); if (r >= 0) { if (r > 0 && changed) *changed = true; mount_point_free(head, m); } else { log_warning_errno(errno, "Could not detach loopback %s: %m", m->path); n_failed++; } } return n_failed; } static int dm_points_list_detach(MountPoint **head, bool *changed) { MountPoint *m, *n; int n_failed = 0, k; struct stat root_st; assert(head); k = lstat("/", &root_st); LIST_FOREACH_SAFE(mount_point, m, n, *head) { int r; if (k >= 0 && major(root_st.st_dev) != 0 && root_st.st_dev == m->devnum) { n_failed ++; continue; } log_info("Detaching DM %u:%u.", major(m->devnum), minor(m->devnum)); r = delete_dm(m->devnum); if (r >= 0) { if (changed) *changed = true; mount_point_free(head, m); } else { log_warning_errno(errno, "Could not detach DM %s: %m", m->path); n_failed++; } } return n_failed; } int umount_all(bool *changed) { int r; bool umount_changed; LIST_HEAD(MountPoint, mp_list_head); LIST_HEAD_INIT(mp_list_head); r = mount_points_list_get(&mp_list_head); if (r < 0) goto end; /* retry umount, until nothing can be umounted anymore */ do { umount_changed = false; mount_points_list_umount(&mp_list_head, &umount_changed, false); if (umount_changed) *changed = true; } while (umount_changed); /* umount one more time with logging enabled */ r = mount_points_list_umount(&mp_list_head, &umount_changed, true); if (r <= 0) goto end; end: mount_points_list_free(&mp_list_head); return r; } int swapoff_all(bool *changed) { int r; LIST_HEAD(MountPoint, swap_list_head); LIST_HEAD_INIT(swap_list_head); r = swap_list_get(&swap_list_head); if (r < 0) goto end; r = swap_points_list_off(&swap_list_head, changed); end: mount_points_list_free(&swap_list_head); return r; } int loopback_detach_all(bool *changed) { int r; LIST_HEAD(MountPoint, loopback_list_head); LIST_HEAD_INIT(loopback_list_head); r = loopback_list_get(&loopback_list_head); if (r < 0) goto end; r = loopback_points_list_detach(&loopback_list_head, changed); end: mount_points_list_free(&loopback_list_head); return r; } int dm_detach_all(bool *changed) { int r; LIST_HEAD(MountPoint, dm_list_head); LIST_HEAD_INIT(dm_list_head); r = dm_list_get(&dm_list_head); if (r < 0) goto end; r = dm_points_list_detach(&dm_list_head, changed); end: mount_points_list_free(&dm_list_head); return r; } systemd-229/src/core/umount.h000066400000000000000000000015611265713322000163030ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 ProFUSION embedded systems systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int umount_all(bool *changed); int swapoff_all(bool *changed); int loopback_detach_all(bool *changed); int dm_detach_all(bool *changed); systemd-229/src/core/unit-printf.c000066400000000000000000000214101265713322000172210ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "cgroup-util.h" #include "formats-util.h" #include "macro.h" #include "specifier.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "unit-printf.h" #include "unit.h" #include "user-util.h" static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) { Unit *u = userdata; assert(u); return unit_name_to_prefix_and_instance(u->id, ret); } static int specifier_prefix(char specifier, void *data, void *userdata, char **ret) { Unit *u = userdata; assert(u); return unit_name_to_prefix(u->id, ret); } static int specifier_prefix_unescaped(char specifier, void *data, void *userdata, char **ret) { _cleanup_free_ char *p = NULL; Unit *u = userdata; int r; assert(u); r = unit_name_to_prefix(u->id, &p); if (r < 0) return r; return unit_name_unescape(p, ret); } static int specifier_instance_unescaped(char specifier, void *data, void *userdata, char **ret) { Unit *u = userdata; assert(u); return unit_name_unescape(strempty(u->instance), ret); } static int specifier_filename(char specifier, void *data, void *userdata, char **ret) { Unit *u = userdata; assert(u); if (u->instance) return unit_name_path_unescape(u->instance, ret); else return unit_name_to_path(u->id, ret); } static int specifier_cgroup(char specifier, void *data, void *userdata, char **ret) { Unit *u = userdata; char *n; assert(u); if (u->cgroup_path) n = strdup(u->cgroup_path); else n = unit_default_cgroup_path(u); if (!n) return -ENOMEM; *ret = n; return 0; } static int specifier_cgroup_root(char specifier, void *data, void *userdata, char **ret) { Unit *u = userdata; char *n; assert(u); n = strdup(u->manager->cgroup_root); if (!n) return -ENOMEM; *ret = n; return 0; } static int specifier_cgroup_slice(char specifier, void *data, void *userdata, char **ret) { Unit *u = userdata; char *n; assert(u); if (UNIT_ISSET(u->slice)) { Unit *slice; slice = UNIT_DEREF(u->slice); if (slice->cgroup_path) n = strdup(slice->cgroup_path); else n = unit_default_cgroup_path(slice); } else n = strdup(u->manager->cgroup_root); if (!n) return -ENOMEM; *ret = n; return 0; } static int specifier_runtime(char specifier, void *data, void *userdata, char **ret) { Unit *u = userdata; const char *e; char *n = NULL; assert(u); if (u->manager->running_as == MANAGER_SYSTEM) e = "/run"; else { e = getenv("XDG_RUNTIME_DIR"); if (!e) return -EOPNOTSUPP; } n = strdup(e); if (!n) return -ENOMEM; *ret = n; return 0; } static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) { char *t; /* If we are UID 0 (root), this will not result in NSS, * otherwise it might. This is good, as we want to be able to * run this in PID 1, where our user ID is 0, but where NSS * lookups are not allowed. */ t = getusername_malloc(); if (!t) return -ENOMEM; *ret = t; return 0; } static int specifier_user_id(char specifier, void *data, void *userdata, char **ret) { if (asprintf(ret, UID_FMT, getuid()) < 0) return -ENOMEM; return 0; } static int specifier_user_home(char specifier, void *data, void *userdata, char **ret) { /* On PID 1 (which runs as root) this will not result in NSS, * which is good. See above */ return get_home_dir(ret); } static int specifier_user_shell(char specifier, void *data, void *userdata, char **ret) { /* On PID 1 (which runs as root) this will not result in NSS, * which is good. See above */ return get_shell(ret); } int unit_name_printf(Unit *u, const char* format, char **ret) { /* * This will use the passed string as format string and * replace the following specifiers: * * %n: the full id of the unit (foo@bar.waldo) * %N: the id of the unit without the suffix (foo@bar) * %p: the prefix (foo) * %i: the instance (bar) */ const Specifier table[] = { { 'n', specifier_string, u->id }, { 'N', specifier_prefix_and_instance, NULL }, { 'p', specifier_prefix, NULL }, { 'i', specifier_string, u->instance }, { 0, NULL, NULL } }; assert(u); assert(format); assert(ret); return specifier_printf(format, table, u, ret); } int unit_full_printf(Unit *u, const char *format, char **ret) { /* This is similar to unit_name_printf() but also supports * unescaping. Also, adds a couple of additional codes: * * %f the instance if set, otherwise the id * %c cgroup path of unit * %r where units in this slice are placed in the cgroup tree * %R the root of this systemd's instance tree * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR) * %U the UID of the running user * %u the username of the running user * %h the homedir of the running user * %s the shell of the running user * %m the machine ID of the running system * %H the host name of the running system * %b the boot ID of the running system * %v `uname -r` of the running system */ const Specifier table[] = { { 'n', specifier_string, u->id }, { 'N', specifier_prefix_and_instance, NULL }, { 'p', specifier_prefix, NULL }, { 'P', specifier_prefix_unescaped, NULL }, { 'i', specifier_string, u->instance }, { 'I', specifier_instance_unescaped, NULL }, { 'f', specifier_filename, NULL }, { 'c', specifier_cgroup, NULL }, { 'r', specifier_cgroup_slice, NULL }, { 'R', specifier_cgroup_root, NULL }, { 't', specifier_runtime, NULL }, { 'U', specifier_user_id, NULL }, { 'u', specifier_user_name, NULL }, { 'h', specifier_user_home, NULL }, { 's', specifier_user_shell, NULL }, { 'm', specifier_machine_id, NULL }, { 'H', specifier_host_name, NULL }, { 'b', specifier_boot_id, NULL }, { 'v', specifier_kernel_release, NULL }, {} }; assert(u); assert(format); assert(ret); return specifier_printf(format, table, u, ret); } int unit_full_printf_strv(Unit *u, char **l, char ***ret) { size_t n; char **r, **i, **j; int q; /* Applies unit_full_printf to every entry in l */ assert(u); n = strv_length(l); r = new(char*, n+1); if (!r) return -ENOMEM; for (i = l, j = r; *i; i++, j++) { q = unit_full_printf(u, *i, j); if (q < 0) goto fail; } *j = NULL; *ret = r; return 0; fail: for (j--; j >= r; j--) free(*j); free(r); return q; } systemd-229/src/core/unit-printf.h000066400000000000000000000016451265713322000172360ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "unit.h" int unit_name_printf(Unit *u, const char* text, char **ret); int unit_full_printf(Unit *u, const char *text, char **ret); int unit_full_printf_strv(Unit *u, char **l, char ***ret); systemd-229/src/core/unit.c000066400000000000000000003461761265713322000157440ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-id128.h" #include "sd-messages.h" #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-util.h" #include "cgroup-util.h" #include "dbus-unit.h" #include "dbus.h" #include "dropin.h" #include "escape.h" #include "execute.h" #include "fileio-label.h" #include "formats-util.h" #include "load-dropin.h" #include "load-fragment.h" #include "log.h" #include "macro.h" #include "missing.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "set.h" #include "special.h" #include "stat-util.h" #include "stdio-util.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "unit.h" #include "user-util.h" #include "virt.h" const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = { [UNIT_SERVICE] = &service_vtable, [UNIT_SOCKET] = &socket_vtable, [UNIT_BUSNAME] = &busname_vtable, [UNIT_TARGET] = &target_vtable, [UNIT_DEVICE] = &device_vtable, [UNIT_MOUNT] = &mount_vtable, [UNIT_AUTOMOUNT] = &automount_vtable, [UNIT_SWAP] = &swap_vtable, [UNIT_TIMER] = &timer_vtable, [UNIT_PATH] = &path_vtable, [UNIT_SLICE] = &slice_vtable, [UNIT_SCOPE] = &scope_vtable }; static void maybe_warn_about_dependency(Unit *u, const char *other, UnitDependency dependency); Unit *unit_new(Manager *m, size_t size) { Unit *u; assert(m); assert(size >= sizeof(Unit)); u = malloc0(size); if (!u) return NULL; u->names = set_new(&string_hash_ops); if (!u->names) { free(u); return NULL; } u->manager = m; u->type = _UNIT_TYPE_INVALID; u->default_dependencies = true; u->unit_file_state = _UNIT_FILE_STATE_INVALID; u->unit_file_preset = -1; u->on_failure_job_mode = JOB_REPLACE; u->cgroup_inotify_wd = -1; u->job_timeout = USEC_INFINITY; RATELIMIT_INIT(u->start_limit, m->default_start_limit_interval, m->default_start_limit_burst); RATELIMIT_INIT(u->auto_stop_ratelimit, 10 * USEC_PER_SEC, 16); return u; } bool unit_has_name(Unit *u, const char *name) { assert(u); assert(name); return !!set_get(u->names, (char*) name); } static void unit_init(Unit *u) { CGroupContext *cc; ExecContext *ec; KillContext *kc; assert(u); assert(u->manager); assert(u->type >= 0); cc = unit_get_cgroup_context(u); if (cc) { cgroup_context_init(cc); /* Copy in the manager defaults into the cgroup * context, _before_ the rest of the settings have * been initialized */ cc->cpu_accounting = u->manager->default_cpu_accounting; cc->blockio_accounting = u->manager->default_blockio_accounting; cc->memory_accounting = u->manager->default_memory_accounting; cc->tasks_accounting = u->manager->default_tasks_accounting; if (u->type != UNIT_SLICE) cc->tasks_max = u->manager->default_tasks_max; } ec = unit_get_exec_context(u); if (ec) exec_context_init(ec); kc = unit_get_kill_context(u); if (kc) kill_context_init(kc); if (UNIT_VTABLE(u)->init) UNIT_VTABLE(u)->init(u); } int unit_add_name(Unit *u, const char *text) { _cleanup_free_ char *s = NULL, *i = NULL; UnitType t; int r; assert(u); assert(text); if (unit_name_is_valid(text, UNIT_NAME_TEMPLATE)) { if (!u->instance) return -EINVAL; r = unit_name_replace_instance(text, u->instance, &s); if (r < 0) return r; } else { s = strdup(text); if (!s) return -ENOMEM; } if (set_contains(u->names, s)) return 0; if (hashmap_contains(u->manager->units, s)) return -EEXIST; if (!unit_name_is_valid(s, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) return -EINVAL; t = unit_name_to_type(s); if (t < 0) return -EINVAL; if (u->type != _UNIT_TYPE_INVALID && t != u->type) return -EINVAL; r = unit_name_to_instance(s, &i); if (r < 0) return r; if (i && unit_vtable[t]->no_instances) return -EINVAL; /* Ensure that this unit is either instanced or not instanced, * but not both. Note that we do allow names with different * instance names however! */ if (u->type != _UNIT_TYPE_INVALID && !u->instance != !i) return -EINVAL; if (unit_vtable[t]->no_alias && !set_isempty(u->names)) return -EEXIST; if (hashmap_size(u->manager->units) >= MANAGER_MAX_NAMES) return -E2BIG; r = set_put(u->names, s); if (r < 0) return r; assert(r > 0); r = hashmap_put(u->manager->units, s, u); if (r < 0) { (void) set_remove(u->names, s); return r; } if (u->type == _UNIT_TYPE_INVALID) { u->type = t; u->id = s; u->instance = i; LIST_PREPEND(units_by_type, u->manager->units_by_type[t], u); unit_init(u); i = NULL; } s = NULL; unit_add_to_dbus_queue(u); return 0; } int unit_choose_id(Unit *u, const char *name) { _cleanup_free_ char *t = NULL; char *s, *i; int r; assert(u); assert(name); if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) { if (!u->instance) return -EINVAL; r = unit_name_replace_instance(name, u->instance, &t); if (r < 0) return r; name = t; } /* Selects one of the names of this unit as the id */ s = set_get(u->names, (char*) name); if (!s) return -ENOENT; /* Determine the new instance from the new id */ r = unit_name_to_instance(s, &i); if (r < 0) return r; u->id = s; free(u->instance); u->instance = i; unit_add_to_dbus_queue(u); return 0; } int unit_set_description(Unit *u, const char *description) { char *s; assert(u); if (isempty(description)) s = NULL; else { s = strdup(description); if (!s) return -ENOMEM; } free(u->description); u->description = s; unit_add_to_dbus_queue(u); return 0; } bool unit_check_gc(Unit *u) { UnitActiveState state; assert(u); if (u->job) return true; if (u->nop_job) return true; state = unit_active_state(u); /* If the unit is inactive and failed and no job is queued for * it, then release its runtime resources */ if (UNIT_IS_INACTIVE_OR_FAILED(state) && UNIT_VTABLE(u)->release_resources) UNIT_VTABLE(u)->release_resources(u); /* But we keep the unit object around for longer when it is * referenced or configured to not be gc'ed */ if (state != UNIT_INACTIVE) return true; if (u->no_gc) return true; if (u->refs) return true; if (UNIT_VTABLE(u)->check_gc) if (UNIT_VTABLE(u)->check_gc(u)) return true; return false; } void unit_add_to_load_queue(Unit *u) { assert(u); assert(u->type != _UNIT_TYPE_INVALID); if (u->load_state != UNIT_STUB || u->in_load_queue) return; LIST_PREPEND(load_queue, u->manager->load_queue, u); u->in_load_queue = true; } void unit_add_to_cleanup_queue(Unit *u) { assert(u); if (u->in_cleanup_queue) return; LIST_PREPEND(cleanup_queue, u->manager->cleanup_queue, u); u->in_cleanup_queue = true; } void unit_add_to_gc_queue(Unit *u) { assert(u); if (u->in_gc_queue || u->in_cleanup_queue) return; if (unit_check_gc(u)) return; LIST_PREPEND(gc_queue, u->manager->gc_queue, u); u->in_gc_queue = true; u->manager->n_in_gc_queue ++; } void unit_add_to_dbus_queue(Unit *u) { assert(u); assert(u->type != _UNIT_TYPE_INVALID); if (u->load_state == UNIT_STUB || u->in_dbus_queue) return; /* Shortcut things if nobody cares */ if (sd_bus_track_count(u->manager->subscribed) <= 0 && set_isempty(u->manager->private_buses)) { u->sent_dbus_new_signal = true; return; } LIST_PREPEND(dbus_queue, u->manager->dbus_unit_queue, u); u->in_dbus_queue = true; } static void bidi_set_free(Unit *u, Set *s) { Iterator i; Unit *other; assert(u); /* Frees the set and makes sure we are dropped from the * inverse pointers */ SET_FOREACH(other, s, i) { UnitDependency d; for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) set_remove(other->dependencies[d], u); unit_add_to_gc_queue(other); } set_free(s); } static void unit_remove_transient(Unit *u) { char **i; assert(u); if (!u->transient) return; if (u->fragment_path) (void) unlink(u->fragment_path); STRV_FOREACH(i, u->dropin_paths) { _cleanup_free_ char *p = NULL; (void) unlink(*i); p = dirname_malloc(*i); if (p) (void) rmdir(p); } } static void unit_free_requires_mounts_for(Unit *u) { char **j; STRV_FOREACH(j, u->requires_mounts_for) { char s[strlen(*j) + 1]; PATH_FOREACH_PREFIX_MORE(s, *j) { char *y; Set *x; x = hashmap_get2(u->manager->units_requiring_mounts_for, s, (void**) &y); if (!x) continue; set_remove(x, u); if (set_isempty(x)) { hashmap_remove(u->manager->units_requiring_mounts_for, y); free(y); set_free(x); } } } u->requires_mounts_for = strv_free(u->requires_mounts_for); } static void unit_done(Unit *u) { ExecContext *ec; CGroupContext *cc; assert(u); if (u->type < 0) return; if (UNIT_VTABLE(u)->done) UNIT_VTABLE(u)->done(u); ec = unit_get_exec_context(u); if (ec) exec_context_done(ec); cc = unit_get_cgroup_context(u); if (cc) cgroup_context_done(cc); } void unit_free(Unit *u) { UnitDependency d; Iterator i; char *t; assert(u); if (u->manager->n_reloading <= 0) unit_remove_transient(u); bus_unit_send_removed_signal(u); unit_done(u); sd_bus_slot_unref(u->match_bus_slot); unit_free_requires_mounts_for(u); SET_FOREACH(t, u->names, i) hashmap_remove_value(u->manager->units, t, u); if (u->job) { Job *j = u->job; job_uninstall(j); job_free(j); } if (u->nop_job) { Job *j = u->nop_job; job_uninstall(j); job_free(j); } for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) bidi_set_free(u, u->dependencies[d]); if (u->type != _UNIT_TYPE_INVALID) LIST_REMOVE(units_by_type, u->manager->units_by_type[u->type], u); if (u->in_load_queue) LIST_REMOVE(load_queue, u->manager->load_queue, u); if (u->in_dbus_queue) LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u); if (u->in_cleanup_queue) LIST_REMOVE(cleanup_queue, u->manager->cleanup_queue, u); if (u->in_gc_queue) { LIST_REMOVE(gc_queue, u->manager->gc_queue, u); u->manager->n_in_gc_queue--; } if (u->in_cgroup_queue) LIST_REMOVE(cgroup_queue, u->manager->cgroup_queue, u); unit_release_cgroup(u); (void) manager_update_failed_units(u->manager, u, false); set_remove(u->manager->startup_units, u); free(u->description); strv_free(u->documentation); free(u->fragment_path); free(u->source_path); strv_free(u->dropin_paths); free(u->instance); free(u->job_timeout_reboot_arg); set_free_free(u->names); unit_unwatch_all_pids(u); condition_free_list(u->conditions); condition_free_list(u->asserts); free(u->reboot_arg); unit_ref_unset(&u->slice); while (u->refs) unit_ref_unset(u->refs); free(u); } UnitActiveState unit_active_state(Unit *u) { assert(u); if (u->load_state == UNIT_MERGED) return unit_active_state(unit_follow_merge(u)); /* After a reload it might happen that a unit is not correctly * loaded but still has a process around. That's why we won't * shortcut failed loading to UNIT_INACTIVE_FAILED. */ return UNIT_VTABLE(u)->active_state(u); } const char* unit_sub_state_to_string(Unit *u) { assert(u); return UNIT_VTABLE(u)->sub_state_to_string(u); } static int complete_move(Set **s, Set **other) { int r; assert(s); assert(other); if (!*other) return 0; if (*s) { r = set_move(*s, *other); if (r < 0) return r; } else { *s = *other; *other = NULL; } return 0; } static int merge_names(Unit *u, Unit *other) { char *t; Iterator i; int r; assert(u); assert(other); r = complete_move(&u->names, &other->names); if (r < 0) return r; set_free_free(other->names); other->names = NULL; other->id = NULL; SET_FOREACH(t, u->names, i) assert_se(hashmap_replace(u->manager->units, t, u) == 0); return 0; } static int reserve_dependencies(Unit *u, Unit *other, UnitDependency d) { unsigned n_reserve; assert(u); assert(other); assert(d < _UNIT_DEPENDENCY_MAX); /* * If u does not have this dependency set allocated, there is no need * to reserve anything. In that case other's set will be transferred * as a whole to u by complete_move(). */ if (!u->dependencies[d]) return 0; /* merge_dependencies() will skip a u-on-u dependency */ n_reserve = set_size(other->dependencies[d]) - !!set_get(other->dependencies[d], u); return set_reserve(u->dependencies[d], n_reserve); } static void merge_dependencies(Unit *u, Unit *other, const char *other_id, UnitDependency d) { Iterator i; Unit *back; int r; assert(u); assert(other); assert(d < _UNIT_DEPENDENCY_MAX); /* Fix backwards pointers */ SET_FOREACH(back, other->dependencies[d], i) { UnitDependency k; for (k = 0; k < _UNIT_DEPENDENCY_MAX; k++) { /* Do not add dependencies between u and itself */ if (back == u) { if (set_remove(back->dependencies[k], other)) maybe_warn_about_dependency(u, other_id, k); } else { r = set_remove_and_put(back->dependencies[k], other, u); if (r == -EEXIST) set_remove(back->dependencies[k], other); else assert(r >= 0 || r == -ENOENT); } } } /* Also do not move dependencies on u to itself */ back = set_remove(other->dependencies[d], u); if (back) maybe_warn_about_dependency(u, other_id, d); /* The move cannot fail. The caller must have performed a reservation. */ assert_se(complete_move(&u->dependencies[d], &other->dependencies[d]) == 0); other->dependencies[d] = set_free(other->dependencies[d]); } int unit_merge(Unit *u, Unit *other) { UnitDependency d; const char *other_id = NULL; int r; assert(u); assert(other); assert(u->manager == other->manager); assert(u->type != _UNIT_TYPE_INVALID); other = unit_follow_merge(other); if (other == u) return 0; if (u->type != other->type) return -EINVAL; if (!u->instance != !other->instance) return -EINVAL; if (other->load_state != UNIT_STUB && other->load_state != UNIT_NOT_FOUND) return -EEXIST; if (other->job) return -EEXIST; if (other->nop_job) return -EEXIST; if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) return -EEXIST; if (other->id) other_id = strdupa(other->id); /* Make reservations to ensure merge_dependencies() won't fail */ for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) { r = reserve_dependencies(u, other, d); /* * We don't rollback reservations if we fail. We don't have * a way to undo reservations. A reservation is not a leak. */ if (r < 0) return r; } /* Merge names */ r = merge_names(u, other); if (r < 0) return r; /* Redirect all references */ while (other->refs) unit_ref_set(other->refs, u); /* Merge dependencies */ for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) merge_dependencies(u, other, other_id, d); other->load_state = UNIT_MERGED; other->merged_into = u; /* If there is still some data attached to the other node, we * don't need it anymore, and can free it. */ if (other->load_state != UNIT_STUB) if (UNIT_VTABLE(other)->done) UNIT_VTABLE(other)->done(other); unit_add_to_dbus_queue(u); unit_add_to_cleanup_queue(other); return 0; } int unit_merge_by_name(Unit *u, const char *name) { Unit *other; int r; _cleanup_free_ char *s = NULL; assert(u); assert(name); if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) { if (!u->instance) return -EINVAL; r = unit_name_replace_instance(name, u->instance, &s); if (r < 0) return r; name = s; } other = manager_get_unit(u->manager, name); if (other) return unit_merge(u, other); return unit_add_name(u, name); } Unit* unit_follow_merge(Unit *u) { assert(u); while (u->load_state == UNIT_MERGED) assert_se(u = u->merged_into); return u; } int unit_add_exec_dependencies(Unit *u, ExecContext *c) { int r; assert(u); assert(c); if (c->working_directory) { r = unit_require_mounts_for(u, c->working_directory); if (r < 0) return r; } if (c->root_directory) { r = unit_require_mounts_for(u, c->root_directory); if (r < 0) return r; } if (u->manager->running_as != MANAGER_SYSTEM) return 0; if (c->private_tmp) { r = unit_require_mounts_for(u, "/tmp"); if (r < 0) return r; r = unit_require_mounts_for(u, "/var/tmp"); if (r < 0) return r; } if (c->std_output != EXEC_OUTPUT_KMSG && c->std_output != EXEC_OUTPUT_SYSLOG && c->std_output != EXEC_OUTPUT_JOURNAL && c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE && c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE && c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE && c->std_error != EXEC_OUTPUT_KMSG && c->std_error != EXEC_OUTPUT_SYSLOG && c->std_error != EXEC_OUTPUT_JOURNAL && c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE && c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE && c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE) return 0; /* If syslog or kernel logging is requested, make sure our own * logging daemon is run first. */ r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, NULL, true); if (r < 0) return r; return 0; } const char *unit_description(Unit *u) { assert(u); if (u->description) return u->description; return strna(u->id); } void unit_dump(Unit *u, FILE *f, const char *prefix) { char *t, **j; UnitDependency d; Iterator i; const char *prefix2; char timestamp0[FORMAT_TIMESTAMP_MAX], timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX], timestamp3[FORMAT_TIMESTAMP_MAX], timestamp4[FORMAT_TIMESTAMP_MAX], timespan[FORMAT_TIMESPAN_MAX]; Unit *following; _cleanup_set_free_ Set *following_set = NULL; int r; assert(u); assert(u->type >= 0); prefix = strempty(prefix); prefix2 = strjoina(prefix, "\t"); fprintf(f, "%s-> Unit %s:\n" "%s\tDescription: %s\n" "%s\tInstance: %s\n" "%s\tUnit Load State: %s\n" "%s\tUnit Active State: %s\n" "%s\nState Change Timestamp: %s\n" "%s\tInactive Exit Timestamp: %s\n" "%s\tActive Enter Timestamp: %s\n" "%s\tActive Exit Timestamp: %s\n" "%s\tInactive Enter Timestamp: %s\n" "%s\tGC Check Good: %s\n" "%s\tNeed Daemon Reload: %s\n" "%s\tTransient: %s\n" "%s\tSlice: %s\n" "%s\tCGroup: %s\n" "%s\tCGroup realized: %s\n" "%s\tCGroup mask: 0x%x\n" "%s\tCGroup members mask: 0x%x\n", prefix, u->id, prefix, unit_description(u), prefix, strna(u->instance), prefix, unit_load_state_to_string(u->load_state), prefix, unit_active_state_to_string(unit_active_state(u)), prefix, strna(format_timestamp(timestamp0, sizeof(timestamp0), u->state_change_timestamp.realtime)), prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->inactive_exit_timestamp.realtime)), prefix, strna(format_timestamp(timestamp2, sizeof(timestamp2), u->active_enter_timestamp.realtime)), prefix, strna(format_timestamp(timestamp3, sizeof(timestamp3), u->active_exit_timestamp.realtime)), prefix, strna(format_timestamp(timestamp4, sizeof(timestamp4), u->inactive_enter_timestamp.realtime)), prefix, yes_no(unit_check_gc(u)), prefix, yes_no(unit_need_daemon_reload(u)), prefix, yes_no(u->transient), prefix, strna(unit_slice_name(u)), prefix, strna(u->cgroup_path), prefix, yes_no(u->cgroup_realized), prefix, u->cgroup_realized_mask, prefix, u->cgroup_members_mask); SET_FOREACH(t, u->names, i) fprintf(f, "%s\tName: %s\n", prefix, t); STRV_FOREACH(j, u->documentation) fprintf(f, "%s\tDocumentation: %s\n", prefix, *j); following = unit_following(u); if (following) fprintf(f, "%s\tFollowing: %s\n", prefix, following->id); r = unit_following_set(u, &following_set); if (r >= 0) { Unit *other; SET_FOREACH(other, following_set, i) fprintf(f, "%s\tFollowing Set Member: %s\n", prefix, other->id); } if (u->fragment_path) fprintf(f, "%s\tFragment Path: %s\n", prefix, u->fragment_path); if (u->source_path) fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path); STRV_FOREACH(j, u->dropin_paths) fprintf(f, "%s\tDropIn Path: %s\n", prefix, *j); if (u->job_timeout != USEC_INFINITY) fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0)); if (u->job_timeout_action != FAILURE_ACTION_NONE) fprintf(f, "%s\tJob Timeout Action: %s\n", prefix, failure_action_to_string(u->job_timeout_action)); if (u->job_timeout_reboot_arg) fprintf(f, "%s\tJob Timeout Reboot Argument: %s\n", prefix, u->job_timeout_reboot_arg); condition_dump_list(u->conditions, f, prefix, condition_type_to_string); condition_dump_list(u->asserts, f, prefix, assert_type_to_string); if (dual_timestamp_is_set(&u->condition_timestamp)) fprintf(f, "%s\tCondition Timestamp: %s\n" "%s\tCondition Result: %s\n", prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)), prefix, yes_no(u->condition_result)); if (dual_timestamp_is_set(&u->assert_timestamp)) fprintf(f, "%s\tAssert Timestamp: %s\n" "%s\tAssert Result: %s\n", prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->assert_timestamp.realtime)), prefix, yes_no(u->assert_result)); for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) { Unit *other; SET_FOREACH(other, u->dependencies[d], i) fprintf(f, "%s\t%s: %s\n", prefix, unit_dependency_to_string(d), other->id); } if (!strv_isempty(u->requires_mounts_for)) { fprintf(f, "%s\tRequiresMountsFor:", prefix); STRV_FOREACH(j, u->requires_mounts_for) fprintf(f, " %s", *j); fputs("\n", f); } if (u->load_state == UNIT_LOADED) { fprintf(f, "%s\tStopWhenUnneeded: %s\n" "%s\tRefuseManualStart: %s\n" "%s\tRefuseManualStop: %s\n" "%s\tDefaultDependencies: %s\n" "%s\tOnFailureJobMode: %s\n" "%s\tIgnoreOnIsolate: %s\n", prefix, yes_no(u->stop_when_unneeded), prefix, yes_no(u->refuse_manual_start), prefix, yes_no(u->refuse_manual_stop), prefix, yes_no(u->default_dependencies), prefix, job_mode_to_string(u->on_failure_job_mode), prefix, yes_no(u->ignore_on_isolate)); if (UNIT_VTABLE(u)->dump) UNIT_VTABLE(u)->dump(u, f, prefix2); } else if (u->load_state == UNIT_MERGED) fprintf(f, "%s\tMerged into: %s\n", prefix, u->merged_into->id); else if (u->load_state == UNIT_ERROR) fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror(-u->load_error)); if (u->job) job_dump(u->job, f, prefix2); if (u->nop_job) job_dump(u->nop_job, f, prefix2); } /* Common implementation for multiple backends */ int unit_load_fragment_and_dropin(Unit *u) { int r; assert(u); /* Load a .{service,socket,...} file */ r = unit_load_fragment(u); if (r < 0) return r; if (u->load_state == UNIT_STUB) return -ENOENT; /* Load drop-in directory data */ r = unit_load_dropin(unit_follow_merge(u)); if (r < 0) return r; return 0; } /* Common implementation for multiple backends */ int unit_load_fragment_and_dropin_optional(Unit *u) { int r; assert(u); /* Same as unit_load_fragment_and_dropin(), but whether * something can be loaded or not doesn't matter. */ /* Load a .service file */ r = unit_load_fragment(u); if (r < 0) return r; if (u->load_state == UNIT_STUB) u->load_state = UNIT_LOADED; /* Load drop-in directory data */ r = unit_load_dropin(unit_follow_merge(u)); if (r < 0) return r; return 0; } int unit_add_default_target_dependency(Unit *u, Unit *target) { assert(u); assert(target); if (target->type != UNIT_TARGET) return 0; /* Only add the dependency if both units are loaded, so that * that loop check below is reliable */ if (u->load_state != UNIT_LOADED || target->load_state != UNIT_LOADED) return 0; /* If either side wants no automatic dependencies, then let's * skip this */ if (!u->default_dependencies || !target->default_dependencies) return 0; /* Don't create loops */ if (set_get(target->dependencies[UNIT_BEFORE], u)) return 0; return unit_add_dependency(target, UNIT_AFTER, u, true); } static int unit_add_target_dependencies(Unit *u) { static const UnitDependency deps[] = { UNIT_REQUIRED_BY, UNIT_REQUISITE_OF, UNIT_WANTED_BY, UNIT_BOUND_BY }; Unit *target; Iterator i; unsigned k; int r = 0; assert(u); for (k = 0; k < ELEMENTSOF(deps); k++) SET_FOREACH(target, u->dependencies[deps[k]], i) { r = unit_add_default_target_dependency(u, target); if (r < 0) return r; } return r; } static int unit_add_slice_dependencies(Unit *u) { assert(u); if (!UNIT_HAS_CGROUP_CONTEXT(u)) return 0; if (UNIT_ISSET(u->slice)) return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT_DEREF(u->slice), true); if (unit_has_name(u, SPECIAL_ROOT_SLICE)) return 0; return unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, SPECIAL_ROOT_SLICE, NULL, true); } static int unit_add_mount_dependencies(Unit *u) { char **i; int r; assert(u); STRV_FOREACH(i, u->requires_mounts_for) { char prefix[strlen(*i) + 1]; PATH_FOREACH_PREFIX_MORE(prefix, *i) { _cleanup_free_ char *p = NULL; Unit *m; r = unit_name_from_path(prefix, ".mount", &p); if (r < 0) return r; m = manager_get_unit(u->manager, p); if (!m) { /* Make sure to load the mount unit if * it exists. If so the dependencies * on this unit will be added later * during the loading of the mount * unit. */ (void) manager_load_unit_prepare(u->manager, p, NULL, NULL, &m); continue; } if (m == u) continue; if (m->load_state != UNIT_LOADED) continue; r = unit_add_dependency(u, UNIT_AFTER, m, true); if (r < 0) return r; if (m->fragment_path) { r = unit_add_dependency(u, UNIT_REQUIRES, m, true); if (r < 0) return r; } } } return 0; } static int unit_add_startup_units(Unit *u) { CGroupContext *c; int r; c = unit_get_cgroup_context(u); if (!c) return 0; if (c->startup_cpu_shares == CGROUP_CPU_SHARES_INVALID && c->startup_blockio_weight == CGROUP_BLKIO_WEIGHT_INVALID) return 0; r = set_ensure_allocated(&u->manager->startup_units, NULL); if (r < 0) return r; return set_put(u->manager->startup_units, u); } int unit_load(Unit *u) { int r; assert(u); if (u->in_load_queue) { LIST_REMOVE(load_queue, u->manager->load_queue, u); u->in_load_queue = false; } if (u->type == _UNIT_TYPE_INVALID) return -EINVAL; if (u->load_state != UNIT_STUB) return 0; if (UNIT_VTABLE(u)->load) { r = UNIT_VTABLE(u)->load(u); if (r < 0) goto fail; } if (u->load_state == UNIT_STUB) { r = -ENOENT; goto fail; } if (u->load_state == UNIT_LOADED) { r = unit_add_target_dependencies(u); if (r < 0) goto fail; r = unit_add_slice_dependencies(u); if (r < 0) goto fail; r = unit_add_mount_dependencies(u); if (r < 0) goto fail; r = unit_add_startup_units(u); if (r < 0) goto fail; if (u->on_failure_job_mode == JOB_ISOLATE && set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) { log_unit_error(u, "More than one OnFailure= dependencies specified but OnFailureJobMode=isolate set. Refusing."); r = -EINVAL; goto fail; } unit_update_cgroup_members_masks(u); } assert((u->load_state != UNIT_MERGED) == !u->merged_into); unit_add_to_dbus_queue(unit_follow_merge(u)); unit_add_to_gc_queue(u); return 0; fail: u->load_state = u->load_state == UNIT_STUB ? UNIT_NOT_FOUND : UNIT_ERROR; u->load_error = r; unit_add_to_dbus_queue(u); unit_add_to_gc_queue(u); log_unit_debug_errno(u, r, "Failed to load configuration: %m"); return r; } static bool unit_condition_test_list(Unit *u, Condition *first, const char *(*to_string)(ConditionType t)) { Condition *c; int triggered = -1; assert(u); assert(to_string); /* If the condition list is empty, then it is true */ if (!first) return true; /* Otherwise, if all of the non-trigger conditions apply and * if any of the trigger conditions apply (unless there are * none) we return true */ LIST_FOREACH(conditions, c, first) { int r; r = condition_test(c); if (r < 0) log_unit_warning(u, "Couldn't determine result for %s=%s%s%s, assuming failed: %m", to_string(c->type), c->trigger ? "|" : "", c->negate ? "!" : "", c->parameter); else log_unit_debug(u, "%s=%s%s%s %s.", to_string(c->type), c->trigger ? "|" : "", c->negate ? "!" : "", c->parameter, condition_result_to_string(c->result)); if (!c->trigger && r <= 0) return false; if (c->trigger && triggered <= 0) triggered = r > 0; } return triggered != 0; } static bool unit_condition_test(Unit *u) { assert(u); dual_timestamp_get(&u->condition_timestamp); u->condition_result = unit_condition_test_list(u, u->conditions, condition_type_to_string); return u->condition_result; } static bool unit_assert_test(Unit *u) { assert(u); dual_timestamp_get(&u->assert_timestamp); u->assert_result = unit_condition_test_list(u, u->asserts, assert_type_to_string); return u->assert_result; } void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) { DISABLE_WARNING_FORMAT_NONLITERAL; manager_status_printf(u->manager, STATUS_TYPE_NORMAL, status, unit_status_msg_format, unit_description(u)); REENABLE_WARNING; } _pure_ static const char* unit_get_status_message_format(Unit *u, JobType t) { const char *format; const UnitStatusMessageFormats *format_table; assert(u); assert(IN_SET(t, JOB_START, JOB_STOP, JOB_RELOAD)); if (t != JOB_RELOAD) { format_table = &UNIT_VTABLE(u)->status_message_formats; if (format_table) { format = format_table->starting_stopping[t == JOB_STOP]; if (format) return format; } } /* Return generic strings */ if (t == JOB_START) return "Starting %s."; else if (t == JOB_STOP) return "Stopping %s."; else return "Reloading %s."; } static void unit_status_print_starting_stopping(Unit *u, JobType t) { const char *format; assert(u); /* Reload status messages have traditionally not been printed to console. */ if (!IN_SET(t, JOB_START, JOB_STOP)) return; format = unit_get_status_message_format(u, t); DISABLE_WARNING_FORMAT_NONLITERAL; unit_status_printf(u, "", format); REENABLE_WARNING; } static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { const char *format; char buf[LINE_MAX]; sd_id128_t mid; assert(u); if (!IN_SET(t, JOB_START, JOB_STOP, JOB_RELOAD)) return; if (log_on_console()) return; /* We log status messages for all units and all operations. */ format = unit_get_status_message_format(u, t); DISABLE_WARNING_FORMAT_NONLITERAL; xsprintf(buf, format, unit_description(u)); REENABLE_WARNING; mid = t == JOB_START ? SD_MESSAGE_UNIT_STARTING : t == JOB_STOP ? SD_MESSAGE_UNIT_STOPPING : SD_MESSAGE_UNIT_RELOADING; /* Note that we deliberately use LOG_MESSAGE() instead of * LOG_UNIT_MESSAGE() here, since this is supposed to mimic * closely what is written to screen using the status output, * which is supposed the highest level, friendliest output * possible, which means we should avoid the low-level unit * name. */ log_struct(LOG_INFO, LOG_MESSAGE_ID(mid), LOG_UNIT_ID(u), LOG_MESSAGE("%s", buf), NULL); } void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t) { assert(u); assert(t >= 0); assert(t < _JOB_TYPE_MAX); unit_status_log_starting_stopping_reloading(u, t); unit_status_print_starting_stopping(u, t); } static int unit_start_limit_test(Unit *u) { assert(u); if (ratelimit_test(&u->start_limit)) { u->start_limit_hit = false; return 0; } log_unit_warning(u, "Start request repeated too quickly."); u->start_limit_hit = true; return failure_action(u->manager, u->start_limit_action, u->reboot_arg); } /* Errors: * -EBADR: This unit type does not support starting. * -EALREADY: Unit is already started. * -EAGAIN: An operation is already in progress. Retry later. * -ECANCELED: Too many requests for now. * -EPROTO: Assert failed * -EINVAL: Unit not loaded * -EOPNOTSUPP: Unit type not supported */ int unit_start(Unit *u) { UnitActiveState state; Unit *following; int r; assert(u); /* If this is already started, then this will succeed. Note * that this will even succeed if this unit is not startable * by the user. This is relied on to detect when we need to * wait for units and when waiting is finished. */ state = unit_active_state(u); if (UNIT_IS_ACTIVE_OR_RELOADING(state)) return -EALREADY; /* Make sure we don't enter a busy loop of some kind. */ r = unit_start_limit_test(u); if (r < 0) return r; /* Units that aren't loaded cannot be started */ if (u->load_state != UNIT_LOADED) return -EINVAL; /* If the conditions failed, don't do anything at all. If we * already are activating this call might still be useful to * speed up activation in case there is some hold-off time, * but we don't want to recheck the condition in that case. */ if (state != UNIT_ACTIVATING && !unit_condition_test(u)) { log_unit_debug(u, "Starting requested but condition failed. Not starting unit."); return -EALREADY; } /* If the asserts failed, fail the entire job */ if (state != UNIT_ACTIVATING && !unit_assert_test(u)) { log_unit_notice(u, "Starting requested but asserts failed."); return -EPROTO; } /* Units of types that aren't supported cannot be * started. Note that we do this test only after the condition * checks, so that we rather return condition check errors * (which are usually not considered a true failure) than "not * supported" errors (which are considered a failure). */ if (!unit_supported(u)) return -EOPNOTSUPP; /* Forward to the main object, if we aren't it. */ following = unit_following(u); if (following) { log_unit_debug(u, "Redirecting start request from %s to %s.", u->id, following->id); return unit_start(following); } /* If it is stopped, but we cannot start it, then fail */ if (!UNIT_VTABLE(u)->start) return -EBADR; /* We don't suppress calls to ->start() here when we are * already starting, to allow this request to be used as a * "hurry up" call, for example when the unit is in some "auto * restart" state where it waits for a holdoff timer to elapse * before it will start again. */ unit_add_to_dbus_queue(u); return UNIT_VTABLE(u)->start(u); } bool unit_can_start(Unit *u) { assert(u); if (u->load_state != UNIT_LOADED) return false; if (!unit_supported(u)) return false; return !!UNIT_VTABLE(u)->start; } bool unit_can_isolate(Unit *u) { assert(u); return unit_can_start(u) && u->allow_isolate; } /* Errors: * -EBADR: This unit type does not support stopping. * -EALREADY: Unit is already stopped. * -EAGAIN: An operation is already in progress. Retry later. */ int unit_stop(Unit *u) { UnitActiveState state; Unit *following; assert(u); state = unit_active_state(u); if (UNIT_IS_INACTIVE_OR_FAILED(state)) return -EALREADY; following = unit_following(u); if (following) { log_unit_debug(u, "Redirecting stop request from %s to %s.", u->id, following->id); return unit_stop(following); } if (!UNIT_VTABLE(u)->stop) return -EBADR; unit_add_to_dbus_queue(u); return UNIT_VTABLE(u)->stop(u); } /* Errors: * -EBADR: This unit type does not support reloading. * -ENOEXEC: Unit is not started. * -EAGAIN: An operation is already in progress. Retry later. */ int unit_reload(Unit *u) { UnitActiveState state; Unit *following; assert(u); if (u->load_state != UNIT_LOADED) return -EINVAL; if (!unit_can_reload(u)) return -EBADR; state = unit_active_state(u); if (state == UNIT_RELOADING) return -EALREADY; if (state != UNIT_ACTIVE) { log_unit_warning(u, "Unit cannot be reloaded because it is inactive."); return -ENOEXEC; } following = unit_following(u); if (following) { log_unit_debug(u, "Redirecting reload request from %s to %s.", u->id, following->id); return unit_reload(following); } unit_add_to_dbus_queue(u); return UNIT_VTABLE(u)->reload(u); } bool unit_can_reload(Unit *u) { assert(u); if (!UNIT_VTABLE(u)->reload) return false; if (!UNIT_VTABLE(u)->can_reload) return true; return UNIT_VTABLE(u)->can_reload(u); } static void unit_check_unneeded(Unit *u) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; static const UnitDependency needed_dependencies[] = { UNIT_REQUIRED_BY, UNIT_REQUISITE_OF, UNIT_WANTED_BY, UNIT_BOUND_BY, }; Unit *other; Iterator i; unsigned j; int r; assert(u); /* If this service shall be shut down when unneeded then do * so. */ if (!u->stop_when_unneeded) return; if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) return; for (j = 0; j < ELEMENTSOF(needed_dependencies); j++) SET_FOREACH(other, u->dependencies[needed_dependencies[j]], i) if (unit_active_or_pending(other)) return; /* If stopping a unit fails continously we might enter a stop * loop here, hence stop acting on the service being * unnecessary after a while. */ if (!ratelimit_test(&u->auto_stop_ratelimit)) { log_unit_warning(u, "Unit not needed anymore, but not stopping since we tried this too often recently."); return; } log_unit_info(u, "Unit not needed anymore. Stopping."); /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */ r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, &error, NULL); if (r < 0) log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r)); } static void unit_check_binds_to(Unit *u) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; bool stop = false; Unit *other; Iterator i; int r; assert(u); if (u->job) return; if (unit_active_state(u) != UNIT_ACTIVE) return; SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i) { if (other->job) continue; if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) continue; stop = true; break; } if (!stop) return; /* If stopping a unit fails continously we might enter a stop * loop here, hence stop acting on the service being * unnecessary after a while. */ if (!ratelimit_test(&u->auto_stop_ratelimit)) { log_unit_warning(u, "Unit is bound to inactive unit %s, but not stopping since we tried this too often recently.", other->id); return; } assert(other); log_unit_info(u, "Unit is bound to inactive unit %s. Stopping, too.", other->id); /* A unit we need to run is gone. Sniff. Let's stop this. */ r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, &error, NULL); if (r < 0) log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r)); } static void retroactively_start_dependencies(Unit *u) { Iterator i; Unit *other; assert(u); assert(UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))); SET_FOREACH(other, u->dependencies[UNIT_REQUIRES], i) if (!set_get(u->dependencies[UNIT_AFTER], other) && !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other))) manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL, NULL); SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i) if (!set_get(u->dependencies[UNIT_AFTER], other) && !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other))) manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL, NULL); SET_FOREACH(other, u->dependencies[UNIT_WANTS], i) if (!set_get(u->dependencies[UNIT_AFTER], other) && !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other))) manager_add_job(u->manager, JOB_START, other, JOB_FAIL, NULL, NULL); SET_FOREACH(other, u->dependencies[UNIT_CONFLICTS], i) if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL); SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i) if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL); } static void retroactively_stop_dependencies(Unit *u) { Iterator i; Unit *other; assert(u); assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u))); /* Pull down units which are bound to us recursively if enabled */ SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i) if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL); } static void check_unneeded_dependencies(Unit *u) { Iterator i; Unit *other; assert(u); assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u))); /* Garbage collect services that might not be needed anymore, if enabled */ SET_FOREACH(other, u->dependencies[UNIT_REQUIRES], i) if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) unit_check_unneeded(other); SET_FOREACH(other, u->dependencies[UNIT_WANTS], i) if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) unit_check_unneeded(other); SET_FOREACH(other, u->dependencies[UNIT_REQUISITE], i) if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) unit_check_unneeded(other); SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i) if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) unit_check_unneeded(other); } void unit_start_on_failure(Unit *u) { Unit *other; Iterator i; assert(u); if (set_size(u->dependencies[UNIT_ON_FAILURE]) <= 0) return; log_unit_info(u, "Triggering OnFailure= dependencies."); SET_FOREACH(other, u->dependencies[UNIT_ON_FAILURE], i) { int r; r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, NULL, NULL); if (r < 0) log_unit_error_errno(u, r, "Failed to enqueue OnFailure= job: %m"); } } void unit_trigger_notify(Unit *u) { Unit *other; Iterator i; assert(u); SET_FOREACH(other, u->dependencies[UNIT_TRIGGERED_BY], i) if (UNIT_VTABLE(other)->trigger_notify) UNIT_VTABLE(other)->trigger_notify(other, u); } void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success) { Manager *m; bool unexpected; assert(u); assert(os < _UNIT_ACTIVE_STATE_MAX); assert(ns < _UNIT_ACTIVE_STATE_MAX); /* Note that this is called for all low-level state changes, * even if they might map to the same high-level * UnitActiveState! That means that ns == os is an expected * behavior here. For example: if a mount point is remounted * this function will be called too! */ m = u->manager; /* Update timestamps for state changes */ if (m->n_reloading <= 0) { dual_timestamp_get(&u->state_change_timestamp); if (UNIT_IS_INACTIVE_OR_FAILED(os) && !UNIT_IS_INACTIVE_OR_FAILED(ns)) u->inactive_exit_timestamp = u->state_change_timestamp; else if (!UNIT_IS_INACTIVE_OR_FAILED(os) && UNIT_IS_INACTIVE_OR_FAILED(ns)) u->inactive_enter_timestamp = u->state_change_timestamp; if (!UNIT_IS_ACTIVE_OR_RELOADING(os) && UNIT_IS_ACTIVE_OR_RELOADING(ns)) u->active_enter_timestamp = u->state_change_timestamp; else if (UNIT_IS_ACTIVE_OR_RELOADING(os) && !UNIT_IS_ACTIVE_OR_RELOADING(ns)) u->active_exit_timestamp = u->state_change_timestamp; } /* Keep track of failed units */ (void) manager_update_failed_units(u->manager, u, ns == UNIT_FAILED); /* Make sure the cgroup is always removed when we become inactive */ if (UNIT_IS_INACTIVE_OR_FAILED(ns)) unit_prune_cgroup(u); /* Note that this doesn't apply to RemainAfterExit services exiting * successfully, since there's no change of state in that case. Which is * why it is handled in service_set_state() */ if (UNIT_IS_INACTIVE_OR_FAILED(os) != UNIT_IS_INACTIVE_OR_FAILED(ns)) { ExecContext *ec; ec = unit_get_exec_context(u); if (ec && exec_context_may_touch_console(ec)) { if (UNIT_IS_INACTIVE_OR_FAILED(ns)) { m->n_on_console --; if (m->n_on_console == 0) /* unset no_console_output flag, since the console is free */ m->no_console_output = false; } else m->n_on_console ++; } } if (u->job) { unexpected = false; if (u->job->state == JOB_WAITING) /* So we reached a different state for this * job. Let's see if we can run it now if it * failed previously due to EAGAIN. */ job_add_to_run_queue(u->job); /* Let's check whether this state change constitutes a * finished job, or maybe contradicts a running job and * hence needs to invalidate jobs. */ switch (u->job->type) { case JOB_START: case JOB_VERIFY_ACTIVE: if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) job_finish_and_invalidate(u->job, JOB_DONE, true); else if (u->job->state == JOB_RUNNING && ns != UNIT_ACTIVATING) { unexpected = true; if (UNIT_IS_INACTIVE_OR_FAILED(ns)) job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true); } break; case JOB_RELOAD: case JOB_RELOAD_OR_START: case JOB_TRY_RELOAD: if (u->job->state == JOB_RUNNING) { if (ns == UNIT_ACTIVE) job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED, true); else if (ns != UNIT_ACTIVATING && ns != UNIT_RELOADING) { unexpected = true; if (UNIT_IS_INACTIVE_OR_FAILED(ns)) job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true); } } break; case JOB_STOP: case JOB_RESTART: case JOB_TRY_RESTART: if (UNIT_IS_INACTIVE_OR_FAILED(ns)) job_finish_and_invalidate(u->job, JOB_DONE, true); else if (u->job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) { unexpected = true; job_finish_and_invalidate(u->job, JOB_FAILED, true); } break; default: assert_not_reached("Job type unknown"); } } else unexpected = true; if (m->n_reloading <= 0) { /* If this state change happened without being * requested by a job, then let's retroactively start * or stop dependencies. We skip that step when * deserializing, since we don't want to create any * additional jobs just because something is already * activated. */ if (unexpected) { if (UNIT_IS_INACTIVE_OR_FAILED(os) && UNIT_IS_ACTIVE_OR_ACTIVATING(ns)) retroactively_start_dependencies(u); else if (UNIT_IS_ACTIVE_OR_ACTIVATING(os) && UNIT_IS_INACTIVE_OR_DEACTIVATING(ns)) retroactively_stop_dependencies(u); } /* stop unneeded units regardless if going down was expected or not */ if (UNIT_IS_INACTIVE_OR_DEACTIVATING(ns)) check_unneeded_dependencies(u); if (ns != os && ns == UNIT_FAILED) { log_unit_notice(u, "Unit entered failed state."); unit_start_on_failure(u); } } /* Some names are special */ if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) { if (unit_has_name(u, SPECIAL_DBUS_SERVICE)) /* The bus might have just become available, * hence try to connect to it, if we aren't * yet connected. */ bus_init(m, true); if (u->type == UNIT_SERVICE && !UNIT_IS_ACTIVE_OR_RELOADING(os) && m->n_reloading <= 0) { /* Write audit record if we have just finished starting up */ manager_send_unit_audit(m, u, AUDIT_SERVICE_START, true); u->in_audit = true; } if (!UNIT_IS_ACTIVE_OR_RELOADING(os)) manager_send_unit_plymouth(m, u); } else { /* We don't care about D-Bus here, since we'll get an * asynchronous notification for it anyway. */ if (u->type == UNIT_SERVICE && UNIT_IS_INACTIVE_OR_FAILED(ns) && !UNIT_IS_INACTIVE_OR_FAILED(os) && m->n_reloading <= 0) { /* Hmm, if there was no start record written * write it now, so that we always have a nice * pair */ if (!u->in_audit) { manager_send_unit_audit(m, u, AUDIT_SERVICE_START, ns == UNIT_INACTIVE); if (ns == UNIT_INACTIVE) manager_send_unit_audit(m, u, AUDIT_SERVICE_STOP, true); } else /* Write audit record if we have just finished shutting down */ manager_send_unit_audit(m, u, AUDIT_SERVICE_STOP, ns == UNIT_INACTIVE); u->in_audit = false; } } manager_recheck_journal(m); unit_trigger_notify(u); if (u->manager->n_reloading <= 0) { /* Maybe we finished startup and are now ready for * being stopped because unneeded? */ unit_check_unneeded(u); /* Maybe we finished startup, but something we needed * has vanished? Let's die then. (This happens when * something BindsTo= to a Type=oneshot unit, as these * units go directly from starting to inactive, * without ever entering started.) */ unit_check_binds_to(u); } unit_add_to_dbus_queue(u); unit_add_to_gc_queue(u); } int unit_watch_pid(Unit *u, pid_t pid) { int q, r; assert(u); assert(pid >= 1); /* Watch a specific PID. We only support one or two units * watching each PID for now, not more. */ r = set_ensure_allocated(&u->pids, NULL); if (r < 0) return r; r = hashmap_ensure_allocated(&u->manager->watch_pids1, NULL); if (r < 0) return r; r = hashmap_put(u->manager->watch_pids1, PID_TO_PTR(pid), u); if (r == -EEXIST) { r = hashmap_ensure_allocated(&u->manager->watch_pids2, NULL); if (r < 0) return r; r = hashmap_put(u->manager->watch_pids2, PID_TO_PTR(pid), u); } q = set_put(u->pids, PID_TO_PTR(pid)); if (q < 0) return q; return r; } void unit_unwatch_pid(Unit *u, pid_t pid) { assert(u); assert(pid >= 1); (void) hashmap_remove_value(u->manager->watch_pids1, PID_TO_PTR(pid), u); (void) hashmap_remove_value(u->manager->watch_pids2, PID_TO_PTR(pid), u); (void) set_remove(u->pids, PID_TO_PTR(pid)); } void unit_unwatch_all_pids(Unit *u) { assert(u); while (!set_isempty(u->pids)) unit_unwatch_pid(u, PTR_TO_PID(set_first(u->pids))); u->pids = set_free(u->pids); } void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2) { Iterator i; void *e; assert(u); /* Cleans dead PIDs from our list */ SET_FOREACH(e, u->pids, i) { pid_t pid = PTR_TO_PID(e); if (pid == except1 || pid == except2) continue; if (!pid_is_unwaited(pid)) unit_unwatch_pid(u, pid); } } bool unit_job_is_applicable(Unit *u, JobType j) { assert(u); assert(j >= 0 && j < _JOB_TYPE_MAX); switch (j) { case JOB_VERIFY_ACTIVE: case JOB_START: case JOB_STOP: case JOB_NOP: return true; case JOB_RESTART: case JOB_TRY_RESTART: return unit_can_start(u); case JOB_RELOAD: case JOB_TRY_RELOAD: return unit_can_reload(u); case JOB_RELOAD_OR_START: return unit_can_reload(u) && unit_can_start(u); default: assert_not_reached("Invalid job type"); } } static void maybe_warn_about_dependency(Unit *u, const char *other, UnitDependency dependency) { assert(u); /* Only warn about some unit types */ if (!IN_SET(dependency, UNIT_CONFLICTS, UNIT_CONFLICTED_BY, UNIT_BEFORE, UNIT_AFTER, UNIT_ON_FAILURE, UNIT_TRIGGERS, UNIT_TRIGGERED_BY)) return; if (streq_ptr(u->id, other)) log_unit_warning(u, "Dependency %s=%s dropped", unit_dependency_to_string(dependency), u->id); else log_unit_warning(u, "Dependency %s=%s dropped, merged into %s", unit_dependency_to_string(dependency), strna(other), u->id); } int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_reference) { static const UnitDependency inverse_table[_UNIT_DEPENDENCY_MAX] = { [UNIT_REQUIRES] = UNIT_REQUIRED_BY, [UNIT_WANTS] = UNIT_WANTED_BY, [UNIT_REQUISITE] = UNIT_REQUISITE_OF, [UNIT_BINDS_TO] = UNIT_BOUND_BY, [UNIT_PART_OF] = UNIT_CONSISTS_OF, [UNIT_REQUIRED_BY] = UNIT_REQUIRES, [UNIT_REQUISITE_OF] = UNIT_REQUISITE, [UNIT_WANTED_BY] = UNIT_WANTS, [UNIT_BOUND_BY] = UNIT_BINDS_TO, [UNIT_CONSISTS_OF] = UNIT_PART_OF, [UNIT_CONFLICTS] = UNIT_CONFLICTED_BY, [UNIT_CONFLICTED_BY] = UNIT_CONFLICTS, [UNIT_BEFORE] = UNIT_AFTER, [UNIT_AFTER] = UNIT_BEFORE, [UNIT_ON_FAILURE] = _UNIT_DEPENDENCY_INVALID, [UNIT_REFERENCES] = UNIT_REFERENCED_BY, [UNIT_REFERENCED_BY] = UNIT_REFERENCES, [UNIT_TRIGGERS] = UNIT_TRIGGERED_BY, [UNIT_TRIGGERED_BY] = UNIT_TRIGGERS, [UNIT_PROPAGATES_RELOAD_TO] = UNIT_RELOAD_PROPAGATED_FROM, [UNIT_RELOAD_PROPAGATED_FROM] = UNIT_PROPAGATES_RELOAD_TO, [UNIT_JOINS_NAMESPACE_OF] = UNIT_JOINS_NAMESPACE_OF, }; int r, q = 0, v = 0, w = 0; Unit *orig_u = u, *orig_other = other; assert(u); assert(d >= 0 && d < _UNIT_DEPENDENCY_MAX); assert(other); u = unit_follow_merge(u); other = unit_follow_merge(other); /* We won't allow dependencies on ourselves. We will not * consider them an error however. */ if (u == other) { maybe_warn_about_dependency(orig_u, orig_other->id, d); return 0; } r = set_ensure_allocated(&u->dependencies[d], NULL); if (r < 0) return r; if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID) { r = set_ensure_allocated(&other->dependencies[inverse_table[d]], NULL); if (r < 0) return r; } if (add_reference) { r = set_ensure_allocated(&u->dependencies[UNIT_REFERENCES], NULL); if (r < 0) return r; r = set_ensure_allocated(&other->dependencies[UNIT_REFERENCED_BY], NULL); if (r < 0) return r; } q = set_put(u->dependencies[d], other); if (q < 0) return q; if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID && inverse_table[d] != d) { v = set_put(other->dependencies[inverse_table[d]], u); if (v < 0) { r = v; goto fail; } } if (add_reference) { w = set_put(u->dependencies[UNIT_REFERENCES], other); if (w < 0) { r = w; goto fail; } r = set_put(other->dependencies[UNIT_REFERENCED_BY], u); if (r < 0) goto fail; } unit_add_to_dbus_queue(u); return 0; fail: if (q > 0) set_remove(u->dependencies[d], other); if (v > 0) set_remove(other->dependencies[inverse_table[d]], u); if (w > 0) set_remove(u->dependencies[UNIT_REFERENCES], other); return r; } int unit_add_two_dependencies(Unit *u, UnitDependency d, UnitDependency e, Unit *other, bool add_reference) { int r; assert(u); r = unit_add_dependency(u, d, other, add_reference); if (r < 0) return r; return unit_add_dependency(u, e, other, add_reference); } static int resolve_template(Unit *u, const char *name, const char*path, char **buf, const char **ret) { int r; assert(u); assert(name || path); assert(buf); assert(ret); if (!name) name = basename(path); if (!unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) { *buf = NULL; *ret = name; return 0; } if (u->instance) r = unit_name_replace_instance(name, u->instance, buf); else { _cleanup_free_ char *i = NULL; r = unit_name_to_prefix(u->id, &i); if (r < 0) return r; r = unit_name_replace_instance(name, i, buf); } if (r < 0) return r; *ret = *buf; return 0; } int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, const char *path, bool add_reference) { _cleanup_free_ char *buf = NULL; Unit *other; int r; assert(u); assert(name || path); r = resolve_template(u, name, path, &buf, &name); if (r < 0) return r; r = manager_load_unit(u->manager, name, path, NULL, &other); if (r < 0) return r; return unit_add_dependency(u, d, other, add_reference); } int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference) { _cleanup_free_ char *buf = NULL; Unit *other; int r; assert(u); assert(name || path); r = resolve_template(u, name, path, &buf, &name); if (r < 0) return r; r = manager_load_unit(u->manager, name, path, NULL, &other); if (r < 0) return r; return unit_add_two_dependencies(u, d, e, other, add_reference); } int set_unit_path(const char *p) { /* This is mostly for debug purposes */ if (setenv("SYSTEMD_UNIT_PATH", p, 1) < 0) return -errno; return 0; } char *unit_dbus_path(Unit *u) { assert(u); if (!u->id) return NULL; return unit_dbus_path_from_name(u->id); } int unit_set_slice(Unit *u, Unit *slice) { assert(u); assert(slice); /* Sets the unit slice if it has not been set before. Is extra * careful, to only allow this for units that actually have a * cgroup context. Also, we don't allow to set this for slices * (since the parent slice is derived from the name). Make * sure the unit we set is actually a slice. */ if (!UNIT_HAS_CGROUP_CONTEXT(u)) return -EOPNOTSUPP; if (u->type == UNIT_SLICE) return -EINVAL; if (unit_active_state(u) != UNIT_INACTIVE) return -EBUSY; if (slice->type != UNIT_SLICE) return -EINVAL; if (unit_has_name(u, SPECIAL_INIT_SCOPE) && !unit_has_name(slice, SPECIAL_ROOT_SLICE)) return -EPERM; if (UNIT_DEREF(u->slice) == slice) return 0; if (UNIT_ISSET(u->slice)) return -EBUSY; unit_ref_set(&u->slice, slice); return 1; } int unit_set_default_slice(Unit *u) { _cleanup_free_ char *b = NULL; const char *slice_name; Unit *slice; int r; assert(u); if (UNIT_ISSET(u->slice)) return 0; if (u->instance) { _cleanup_free_ char *prefix = NULL, *escaped = NULL; /* Implicitly place all instantiated units in their * own per-template slice */ r = unit_name_to_prefix(u->id, &prefix); if (r < 0) return r; /* The prefix is already escaped, but it might include * "-" which has a special meaning for slice units, * hence escape it here extra. */ escaped = unit_name_escape(prefix); if (!escaped) return -ENOMEM; if (u->manager->running_as == MANAGER_SYSTEM) b = strjoin("system-", escaped, ".slice", NULL); else b = strappend(escaped, ".slice"); if (!b) return -ENOMEM; slice_name = b; } else slice_name = u->manager->running_as == MANAGER_SYSTEM && !unit_has_name(u, SPECIAL_INIT_SCOPE) ? SPECIAL_SYSTEM_SLICE : SPECIAL_ROOT_SLICE; r = manager_load_unit(u->manager, slice_name, NULL, NULL, &slice); if (r < 0) return r; return unit_set_slice(u, slice); } const char *unit_slice_name(Unit *u) { assert(u); if (!UNIT_ISSET(u->slice)) return NULL; return UNIT_DEREF(u->slice)->id; } int unit_load_related_unit(Unit *u, const char *type, Unit **_found) { _cleanup_free_ char *t = NULL; int r; assert(u); assert(type); assert(_found); r = unit_name_change_suffix(u->id, type, &t); if (r < 0) return r; if (unit_has_name(u, t)) return -EINVAL; r = manager_load_unit(u->manager, t, NULL, NULL, _found); assert(r < 0 || *_found != u); return r; } static int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *name, *old_owner, *new_owner; Unit *u = userdata; int r; assert(message); assert(u); r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner); if (r < 0) { bus_log_parse_error(r); return 0; } if (UNIT_VTABLE(u)->bus_name_owner_change) UNIT_VTABLE(u)->bus_name_owner_change(u, name, old_owner, new_owner); return 0; } int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) { const char *match; assert(u); assert(bus); assert(name); if (u->match_bus_slot) return -EBUSY; match = strjoina("type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'," "arg0='", name, "'", NULL); return sd_bus_add_match(bus, &u->match_bus_slot, match, signal_name_owner_changed, u); } int unit_watch_bus_name(Unit *u, const char *name) { int r; assert(u); assert(name); /* Watch a specific name on the bus. We only support one unit * watching each name for now. */ if (u->manager->api_bus) { /* If the bus is already available, install the match directly. * Otherwise, just put the name in the list. bus_setup_api() will take care later. */ r = unit_install_bus_match(u, u->manager->api_bus, name); if (r < 0) return log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name); } r = hashmap_put(u->manager->watch_bus, name, u); if (r < 0) { u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot); return log_warning_errno(r, "Failed to put bus name to hashmap: %m"); } return 0; } void unit_unwatch_bus_name(Unit *u, const char *name) { assert(u); assert(name); hashmap_remove_value(u->manager->watch_bus, name, u); u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot); } bool unit_can_serialize(Unit *u) { assert(u); return UNIT_VTABLE(u)->serialize && UNIT_VTABLE(u)->deserialize_item; } int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { int r; assert(u); assert(f); assert(fds); if (unit_can_serialize(u)) { ExecRuntime *rt; r = UNIT_VTABLE(u)->serialize(u, f, fds); if (r < 0) return r; rt = unit_get_exec_runtime(u); if (rt) { r = exec_runtime_serialize(u, rt, f, fds); if (r < 0) return r; } } dual_timestamp_serialize(f, "state-change-timestamp", &u->state_change_timestamp); dual_timestamp_serialize(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp); dual_timestamp_serialize(f, "active-enter-timestamp", &u->active_enter_timestamp); dual_timestamp_serialize(f, "active-exit-timestamp", &u->active_exit_timestamp); dual_timestamp_serialize(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp); dual_timestamp_serialize(f, "condition-timestamp", &u->condition_timestamp); dual_timestamp_serialize(f, "assert-timestamp", &u->assert_timestamp); if (dual_timestamp_is_set(&u->condition_timestamp)) unit_serialize_item(u, f, "condition-result", yes_no(u->condition_result)); if (dual_timestamp_is_set(&u->assert_timestamp)) unit_serialize_item(u, f, "assert-result", yes_no(u->assert_result)); unit_serialize_item(u, f, "transient", yes_no(u->transient)); unit_serialize_item_format(u, f, "cpuacct-usage-base", "%" PRIu64, u->cpuacct_usage_base); if (u->cgroup_path) unit_serialize_item(u, f, "cgroup", u->cgroup_path); unit_serialize_item(u, f, "cgroup-realized", yes_no(u->cgroup_realized)); if (serialize_jobs) { if (u->job) { fprintf(f, "job\n"); job_serialize(u->job, f, fds); } if (u->nop_job) { fprintf(f, "job\n"); job_serialize(u->nop_job, f, fds); } } /* End marker */ fputc('\n', f); return 0; } int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) { assert(u); assert(f); assert(key); if (!value) return 0; fputs(key, f); fputc('=', f); fputs(value, f); fputc('\n', f); return 1; } int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value) { _cleanup_free_ char *c = NULL; assert(u); assert(f); assert(key); if (!value) return 0; c = cescape(value); if (!c) return -ENOMEM; fputs(key, f); fputc('=', f); fputs(c, f); fputc('\n', f); return 1; } int unit_serialize_item_fd(Unit *u, FILE *f, FDSet *fds, const char *key, int fd) { int copy; assert(u); assert(f); assert(key); if (fd < 0) return 0; copy = fdset_put_dup(fds, fd); if (copy < 0) return copy; fprintf(f, "%s=%i\n", key, copy); return 1; } void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *format, ...) { va_list ap; assert(u); assert(f); assert(key); assert(format); fputs(key, f); fputc('=', f); va_start(ap, format); vfprintf(f, format, ap); va_end(ap); fputc('\n', f); } int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { ExecRuntime **rt = NULL; size_t offset; int r; assert(u); assert(f); assert(fds); offset = UNIT_VTABLE(u)->exec_runtime_offset; if (offset > 0) rt = (ExecRuntime**) ((uint8_t*) u + offset); for (;;) { char line[LINE_MAX], *l, *v; size_t k; if (!fgets(line, sizeof(line), f)) { if (feof(f)) return 0; return -errno; } char_array_0(line); l = strstrip(line); /* End marker */ if (isempty(l)) break; k = strcspn(l, "="); if (l[k] == '=') { l[k] = 0; v = l+k+1; } else v = l+k; if (streq(l, "job")) { if (v[0] == '\0') { /* new-style serialized job */ Job *j; j = job_new_raw(u); if (!j) return log_oom(); r = job_deserialize(j, f, fds); if (r < 0) { job_free(j); return r; } r = hashmap_put(u->manager->jobs, UINT32_TO_PTR(j->id), j); if (r < 0) { job_free(j); return r; } r = job_install_deserialized(j); if (r < 0) { hashmap_remove(u->manager->jobs, UINT32_TO_PTR(j->id)); job_free(j); return r; } } else /* legacy for pre-44 */ log_unit_warning(u, "Update from too old systemd versions are unsupported, cannot deserialize job: %s", v); continue; } else if (streq(l, "state-change-timestamp")) { dual_timestamp_deserialize(v, &u->state_change_timestamp); continue; } else if (streq(l, "inactive-exit-timestamp")) { dual_timestamp_deserialize(v, &u->inactive_exit_timestamp); continue; } else if (streq(l, "active-enter-timestamp")) { dual_timestamp_deserialize(v, &u->active_enter_timestamp); continue; } else if (streq(l, "active-exit-timestamp")) { dual_timestamp_deserialize(v, &u->active_exit_timestamp); continue; } else if (streq(l, "inactive-enter-timestamp")) { dual_timestamp_deserialize(v, &u->inactive_enter_timestamp); continue; } else if (streq(l, "condition-timestamp")) { dual_timestamp_deserialize(v, &u->condition_timestamp); continue; } else if (streq(l, "assert-timestamp")) { dual_timestamp_deserialize(v, &u->assert_timestamp); continue; } else if (streq(l, "condition-result")) { r = parse_boolean(v); if (r < 0) log_unit_debug(u, "Failed to parse condition result value %s, ignoring.", v); else u->condition_result = r; continue; } else if (streq(l, "assert-result")) { r = parse_boolean(v); if (r < 0) log_unit_debug(u, "Failed to parse assert result value %s, ignoring.", v); else u->assert_result = r; continue; } else if (streq(l, "transient")) { r = parse_boolean(v); if (r < 0) log_unit_debug(u, "Failed to parse transient bool %s, ignoring.", v); else u->transient = r; continue; } else if (streq(l, "cpuacct-usage-base")) { r = safe_atou64(v, &u->cpuacct_usage_base); if (r < 0) log_unit_debug(u, "Failed to parse CPU usage %s, ignoring.", v); continue; } else if (streq(l, "cgroup")) { r = unit_set_cgroup_path(u, v); if (r < 0) log_unit_debug_errno(u, r, "Failed to set cgroup path %s, ignoring: %m", v); (void) unit_watch_cgroup(u); continue; } else if (streq(l, "cgroup-realized")) { int b; b = parse_boolean(v); if (b < 0) log_unit_debug(u, "Failed to parse cgroup-realized bool %s, ignoring.", v); else u->cgroup_realized = b; continue; } if (unit_can_serialize(u)) { if (rt) { r = exec_runtime_deserialize_item(u, rt, l, v, fds); if (r < 0) { log_unit_warning(u, "Failed to deserialize runtime parameter '%s', ignoring.", l); continue; } /* Returns positive if key was handled by the call */ if (r > 0) continue; } r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds); if (r < 0) log_unit_warning(u, "Failed to deserialize unit parameter '%s', ignoring.", l); } } /* Versions before 228 did not carry a state change timestamp. In this case, take the current time. This is * useful, so that timeouts based on this timestamp don't trigger too early, and is in-line with the logic from * before 228 where the base for timeouts was not persistent across reboots. */ if (!dual_timestamp_is_set(&u->state_change_timestamp)) dual_timestamp_get(&u->state_change_timestamp); return 0; } int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency dep) { Unit *device; _cleanup_free_ char *e = NULL; int r; assert(u); /* Adds in links to the device node that this unit is based on */ if (isempty(what)) return 0; if (!is_device_path(what)) return 0; /* When device units aren't supported (such as in a * container), don't create dependencies on them. */ if (!unit_type_supported(UNIT_DEVICE)) return 0; r = unit_name_from_path(what, ".device", &e); if (r < 0) return r; r = manager_load_unit(u->manager, e, NULL, NULL, &device); if (r < 0) return r; r = unit_add_two_dependencies(u, UNIT_AFTER, u->manager->running_as == MANAGER_SYSTEM ? dep : UNIT_WANTS, device, true); if (r < 0) return r; if (wants) { r = unit_add_dependency(device, UNIT_WANTS, u, false); if (r < 0) return r; } return 0; } int unit_coldplug(Unit *u) { int r = 0, q = 0; assert(u); /* Make sure we don't enter a loop, when coldplugging * recursively. */ if (u->coldplugged) return 0; u->coldplugged = true; if (UNIT_VTABLE(u)->coldplug) r = UNIT_VTABLE(u)->coldplug(u); if (u->job) q = job_coldplug(u->job); if (r < 0) return r; if (q < 0) return q; return 0; } bool unit_need_daemon_reload(Unit *u) { _cleanup_strv_free_ char **t = NULL; char **path; struct stat st; unsigned loaded_cnt, current_cnt; assert(u); if (u->fragment_path) { zero(st); if (stat(u->fragment_path, &st) < 0) /* What, cannot access this anymore? */ return true; if (u->fragment_mtime > 0 && timespec_load(&st.st_mtim) != u->fragment_mtime) return true; } if (u->source_path) { zero(st); if (stat(u->source_path, &st) < 0) return true; if (u->source_mtime > 0 && timespec_load(&st.st_mtim) != u->source_mtime) return true; } (void) unit_find_dropin_paths(u, &t); loaded_cnt = strv_length(t); current_cnt = strv_length(u->dropin_paths); if (loaded_cnt == current_cnt) { if (loaded_cnt == 0) return false; if (strv_overlap(u->dropin_paths, t)) { STRV_FOREACH(path, u->dropin_paths) { zero(st); if (stat(*path, &st) < 0) return true; if (u->dropin_mtime > 0 && timespec_load(&st.st_mtim) > u->dropin_mtime) return true; } return false; } else return true; } else return true; } void unit_reset_failed(Unit *u) { assert(u); if (UNIT_VTABLE(u)->reset_failed) UNIT_VTABLE(u)->reset_failed(u); RATELIMIT_RESET(u->start_limit); u->start_limit_hit = false; } Unit *unit_following(Unit *u) { assert(u); if (UNIT_VTABLE(u)->following) return UNIT_VTABLE(u)->following(u); return NULL; } bool unit_stop_pending(Unit *u) { assert(u); /* This call does check the current state of the unit. It's * hence useful to be called from state change calls of the * unit itself, where the state isn't updated yet. This is * different from unit_inactive_or_pending() which checks both * the current state and for a queued job. */ return u->job && u->job->type == JOB_STOP; } bool unit_inactive_or_pending(Unit *u) { assert(u); /* Returns true if the unit is inactive or going down */ if (UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u))) return true; if (unit_stop_pending(u)) return true; return false; } bool unit_active_or_pending(Unit *u) { assert(u); /* Returns true if the unit is active or going up */ if (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) return true; if (u->job && (u->job->type == JOB_START || u->job->type == JOB_RELOAD_OR_START || u->job->type == JOB_RESTART)) return true; return false; } int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) { assert(u); assert(w >= 0 && w < _KILL_WHO_MAX); assert(signo > 0); assert(signo < _NSIG); if (!UNIT_VTABLE(u)->kill) return -EOPNOTSUPP; return UNIT_VTABLE(u)->kill(u, w, signo, error); } static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) { Set *pid_set; int r; pid_set = set_new(NULL); if (!pid_set) return NULL; /* Exclude the main/control pids from being killed via the cgroup */ if (main_pid > 0) { r = set_put(pid_set, PID_TO_PTR(main_pid)); if (r < 0) goto fail; } if (control_pid > 0) { r = set_put(pid_set, PID_TO_PTR(control_pid)); if (r < 0) goto fail; } return pid_set; fail: set_free(pid_set); return NULL; } int unit_kill_common( Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, sd_bus_error *error) { int r = 0; bool killed = false; if (IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL)) { if (main_pid < 0) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type)); else if (main_pid == 0) return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill"); } if (IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL)) { if (control_pid < 0) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type)); else if (control_pid == 0) return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill"); } if (IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL, KILL_ALL, KILL_ALL_FAIL)) if (control_pid > 0) { if (kill(control_pid, signo) < 0) r = -errno; else killed = true; } if (IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL, KILL_ALL, KILL_ALL_FAIL)) if (main_pid > 0) { if (kill(main_pid, signo) < 0) r = -errno; else killed = true; } if (IN_SET(who, KILL_ALL, KILL_ALL_FAIL) && u->cgroup_path) { _cleanup_set_free_ Set *pid_set = NULL; int q; /* Exclude the main/control pids from being killed via the cgroup */ pid_set = unit_pid_set(main_pid, control_pid); if (!pid_set) return -ENOMEM; q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, false, false, pid_set); if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT) r = q; else killed = true; } if (r == 0 && !killed && IN_SET(who, KILL_ALL_FAIL, KILL_CONTROL_FAIL)) return -ESRCH; return r; } int unit_following_set(Unit *u, Set **s) { assert(u); assert(s); if (UNIT_VTABLE(u)->following_set) return UNIT_VTABLE(u)->following_set(u, s); *s = NULL; return 0; } UnitFileState unit_get_unit_file_state(Unit *u) { int r; assert(u); if (u->unit_file_state < 0 && u->fragment_path) { r = unit_file_get_state( u->manager->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, basename(u->fragment_path), &u->unit_file_state); if (r < 0) u->unit_file_state = UNIT_FILE_BAD; } return u->unit_file_state; } int unit_get_unit_file_preset(Unit *u) { assert(u); if (u->unit_file_preset < 0 && u->fragment_path) u->unit_file_preset = unit_file_query_preset( u->manager->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, basename(u->fragment_path)); return u->unit_file_preset; } Unit* unit_ref_set(UnitRef *ref, Unit *u) { assert(ref); assert(u); if (ref->unit) unit_ref_unset(ref); ref->unit = u; LIST_PREPEND(refs, u->refs, ref); return u; } void unit_ref_unset(UnitRef *ref) { assert(ref); if (!ref->unit) return; LIST_REMOVE(refs, ref->unit->refs, ref); ref->unit = NULL; } int unit_patch_contexts(Unit *u) { CGroupContext *cc; ExecContext *ec; unsigned i; int r; assert(u); /* Patch in the manager defaults into the exec and cgroup * contexts, _after_ the rest of the settings have been * initialized */ ec = unit_get_exec_context(u); if (ec) { /* This only copies in the ones that need memory */ for (i = 0; i < _RLIMIT_MAX; i++) if (u->manager->rlimit[i] && !ec->rlimit[i]) { ec->rlimit[i] = newdup(struct rlimit, u->manager->rlimit[i], 1); if (!ec->rlimit[i]) return -ENOMEM; } if (u->manager->running_as == MANAGER_USER && !ec->working_directory) { r = get_home_dir(&ec->working_directory); if (r < 0) return r; /* Allow user services to run, even if the * home directory is missing */ ec->working_directory_missing_ok = true; } if (u->manager->running_as == MANAGER_USER && (ec->syscall_whitelist || !set_isempty(ec->syscall_filter) || !set_isempty(ec->syscall_archs) || ec->address_families_whitelist || !set_isempty(ec->address_families))) ec->no_new_privileges = true; if (ec->private_devices) ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_MKNOD); } cc = unit_get_cgroup_context(u); if (cc) { if (ec && ec->private_devices && cc->device_policy == CGROUP_AUTO) cc->device_policy = CGROUP_CLOSED; } return 0; } ExecContext *unit_get_exec_context(Unit *u) { size_t offset; assert(u); if (u->type < 0) return NULL; offset = UNIT_VTABLE(u)->exec_context_offset; if (offset <= 0) return NULL; return (ExecContext*) ((uint8_t*) u + offset); } KillContext *unit_get_kill_context(Unit *u) { size_t offset; assert(u); if (u->type < 0) return NULL; offset = UNIT_VTABLE(u)->kill_context_offset; if (offset <= 0) return NULL; return (KillContext*) ((uint8_t*) u + offset); } CGroupContext *unit_get_cgroup_context(Unit *u) { size_t offset; if (u->type < 0) return NULL; offset = UNIT_VTABLE(u)->cgroup_context_offset; if (offset <= 0) return NULL; return (CGroupContext*) ((uint8_t*) u + offset); } ExecRuntime *unit_get_exec_runtime(Unit *u) { size_t offset; if (u->type < 0) return NULL; offset = UNIT_VTABLE(u)->exec_runtime_offset; if (offset <= 0) return NULL; return *(ExecRuntime**) ((uint8_t*) u + offset); } static int unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode, bool transient, char **dir) { assert(u); if (u->manager->running_as == MANAGER_USER) { int r; if (mode == UNIT_PERSISTENT && !transient) r = user_config_home(dir); else r = user_runtime_dir(dir); if (r == 0) return -ENOENT; return r; } if (mode == UNIT_PERSISTENT && !transient) *dir = strdup("/etc/systemd/system"); else *dir = strdup("/run/systemd/system"); if (!*dir) return -ENOMEM; return 0; } int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) { _cleanup_free_ char *dir = NULL, *p = NULL, *q = NULL; int r; assert(u); if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME)) return 0; r = unit_drop_in_dir(u, mode, u->transient, &dir); if (r < 0) return r; r = write_drop_in(dir, u->id, 50, name, data); if (r < 0) return r; r = drop_in_file(dir, u->id, 50, name, &p, &q); if (r < 0) return r; r = strv_extend(&u->dropin_paths, q); if (r < 0) return r; strv_sort(u->dropin_paths); strv_uniq(u->dropin_paths); u->dropin_mtime = now(CLOCK_REALTIME); return 0; } int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) { _cleanup_free_ char *p = NULL; va_list ap; int r; assert(u); assert(name); assert(format); if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME)) return 0; va_start(ap, format); r = vasprintf(&p, format, ap); va_end(ap); if (r < 0) return -ENOMEM; return unit_write_drop_in(u, mode, name, p); } int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) { _cleanup_free_ char *ndata = NULL; assert(u); assert(name); assert(data); if (!UNIT_VTABLE(u)->private_section) return -EINVAL; if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME)) return 0; ndata = strjoin("[", UNIT_VTABLE(u)->private_section, "]\n", data, NULL); if (!ndata) return -ENOMEM; return unit_write_drop_in(u, mode, name, ndata); } int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) { _cleanup_free_ char *p = NULL; va_list ap; int r; assert(u); assert(name); assert(format); if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME)) return 0; va_start(ap, format); r = vasprintf(&p, format, ap); va_end(ap); if (r < 0) return -ENOMEM; return unit_write_drop_in_private(u, mode, name, p); } int unit_make_transient(Unit *u) { assert(u); if (!UNIT_VTABLE(u)->can_transient) return -EOPNOTSUPP; u->load_state = UNIT_STUB; u->load_error = 0; u->transient = true; u->fragment_path = mfree(u->fragment_path); u->source_path = mfree(u->source_path); u->dropin_paths = strv_free(u->dropin_paths); u->fragment_mtime = u->source_mtime = u->dropin_mtime = 0; unit_add_to_dbus_queue(u); unit_add_to_gc_queue(u); unit_add_to_load_queue(u); return 0; } int unit_kill_context( Unit *u, KillContext *c, KillOperation k, pid_t main_pid, pid_t control_pid, bool main_pid_alien) { bool wait_for_exit = false; int sig, r; assert(u); assert(c); if (c->kill_mode == KILL_NONE) return 0; switch (k) { case KILL_KILL: sig = SIGKILL; break; case KILL_ABORT: sig = SIGABRT; break; case KILL_TERMINATE: sig = c->kill_signal; break; default: assert_not_reached("KillOperation unknown"); } if (main_pid > 0) { r = kill_and_sigcont(main_pid, sig); if (r < 0 && r != -ESRCH) { _cleanup_free_ char *comm = NULL; get_process_comm(main_pid, &comm); log_unit_warning_errno(u, r, "Failed to kill main process " PID_FMT " (%s), ignoring: %m", main_pid, strna(comm)); } else { if (!main_pid_alien) wait_for_exit = true; if (c->send_sighup && k == KILL_TERMINATE) (void) kill(main_pid, SIGHUP); } } if (control_pid > 0) { r = kill_and_sigcont(control_pid, sig); if (r < 0 && r != -ESRCH) { _cleanup_free_ char *comm = NULL; get_process_comm(control_pid, &comm); log_unit_warning_errno(u, r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m", control_pid, strna(comm)); } else { wait_for_exit = true; if (c->send_sighup && k == KILL_TERMINATE) (void) kill(control_pid, SIGHUP); } } if (u->cgroup_path && (c->kill_mode == KILL_CONTROL_GROUP || (c->kill_mode == KILL_MIXED && k == KILL_KILL))) { _cleanup_set_free_ Set *pid_set = NULL; /* Exclude the main/control pids from being killed via the cgroup */ pid_set = unit_pid_set(main_pid, control_pid); if (!pid_set) return -ENOMEM; r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, sig, true, k != KILL_TERMINATE, false, pid_set); if (r < 0) { if (r != -EAGAIN && r != -ESRCH && r != -ENOENT) log_unit_warning_errno(u, r, "Failed to kill control group %s, ignoring: %m", u->cgroup_path); } else if (r > 0) { /* FIXME: For now, on the legacy hierarchy, we * will not wait for the cgroup members to die * if we are running in a container or if this * is a delegation unit, simply because cgroup * notification is unreliable in these * cases. It doesn't work at all in * containers, and outside of containers it * can be confused easily by left-over * directories in the cgroup -- which however * should not exist in non-delegated units. On * the unified hierarchy that's different, * there we get proper events. Hence rely on * them.*/ if (cg_unified() > 0 || (detect_container() == 0 && !unit_cgroup_delegate(u))) wait_for_exit = true; if (c->send_sighup && k != KILL_KILL) { set_free(pid_set); pid_set = unit_pid_set(main_pid, control_pid); if (!pid_set) return -ENOMEM; cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, SIGHUP, false, true, false, pid_set); } } } return wait_for_exit; } int unit_require_mounts_for(Unit *u, const char *path) { char prefix[strlen(path) + 1], *p; int r; assert(u); assert(path); /* Registers a unit for requiring a certain path and all its * prefixes. We keep a simple array of these paths in the * unit, since its usually short. However, we build a prefix * table for all possible prefixes so that new appearing mount * units can easily determine which units to make themselves a * dependency of. */ if (!path_is_absolute(path)) return -EINVAL; p = strdup(path); if (!p) return -ENOMEM; path_kill_slashes(p); if (!path_is_safe(p)) { free(p); return -EPERM; } if (strv_contains(u->requires_mounts_for, p)) { free(p); return 0; } r = strv_consume(&u->requires_mounts_for, p); if (r < 0) return r; PATH_FOREACH_PREFIX_MORE(prefix, p) { Set *x; x = hashmap_get(u->manager->units_requiring_mounts_for, prefix); if (!x) { char *q; r = hashmap_ensure_allocated(&u->manager->units_requiring_mounts_for, &string_hash_ops); if (r < 0) return r; q = strdup(prefix); if (!q) return -ENOMEM; x = set_new(NULL); if (!x) { free(q); return -ENOMEM; } r = hashmap_put(u->manager->units_requiring_mounts_for, q, x); if (r < 0) { free(q); set_free(x); return r; } } r = set_put(x, u); if (r < 0) return r; } return 0; } int unit_setup_exec_runtime(Unit *u) { ExecRuntime **rt; size_t offset; Iterator i; Unit *other; offset = UNIT_VTABLE(u)->exec_runtime_offset; assert(offset > 0); /* Check if there already is an ExecRuntime for this unit? */ rt = (ExecRuntime**) ((uint8_t*) u + offset); if (*rt) return 0; /* Try to get it from somebody else */ SET_FOREACH(other, u->dependencies[UNIT_JOINS_NAMESPACE_OF], i) { *rt = unit_get_exec_runtime(other); if (*rt) { exec_runtime_ref(*rt); return 0; } } return exec_runtime_make(rt, unit_get_exec_context(u), u->id); } bool unit_type_supported(UnitType t) { if (_unlikely_(t < 0)) return false; if (_unlikely_(t >= _UNIT_TYPE_MAX)) return false; if (!unit_vtable[t]->supported) return true; return unit_vtable[t]->supported(); } void unit_warn_if_dir_nonempty(Unit *u, const char* where) { int r; assert(u); assert(where); r = dir_is_empty(where); if (r > 0) return; if (r < 0) { log_unit_warning_errno(u, r, "Failed to check directory %s: %m", where); return; } log_struct(LOG_NOTICE, LOG_MESSAGE_ID(SD_MESSAGE_OVERMOUNTING), LOG_UNIT_ID(u), LOG_UNIT_MESSAGE(u, "Directory %s to mount over is not empty, mounting anyway.", where), "WHERE=%s", where, NULL); } int unit_fail_if_symlink(Unit *u, const char* where) { int r; assert(u); assert(where); r = is_symlink(where); if (r < 0) { log_unit_debug_errno(u, r, "Failed to check symlink %s, ignoring: %m", where); return 0; } if (r == 0) return 0; log_struct(LOG_ERR, LOG_MESSAGE_ID(SD_MESSAGE_OVERMOUNTING), LOG_UNIT_ID(u), LOG_UNIT_MESSAGE(u, "Mount on symlink %s not allowed.", where), "WHERE=%s", where, NULL); return -ELOOP; } bool unit_is_pristine(Unit *u) { assert(u); /* Check if the unit already exists or is already around, * in a number of different ways. Note that to cater for unit * types such as slice, we are generally fine with units that * are marked UNIT_LOADED even even though nothing was * actually loaded, as those unit types don't require a file * on disk to validly load. */ return !(!IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_LOADED) || u->fragment_path || u->source_path || !strv_isempty(u->dropin_paths) || u->job || u->merged_into); } systemd-229/src/core/unit.h000066400000000000000000000526251265713322000157420ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include typedef struct Unit Unit; typedef struct UnitVTable UnitVTable; typedef struct UnitRef UnitRef; typedef struct UnitStatusMessageFormats UnitStatusMessageFormats; #include "condition.h" #include "failure-action.h" #include "install.h" #include "list.h" #include "unit-name.h" typedef enum KillOperation { KILL_TERMINATE, KILL_KILL, KILL_ABORT, _KILL_OPERATION_MAX, _KILL_OPERATION_INVALID = -1 } KillOperation; static inline bool UNIT_IS_ACTIVE_OR_RELOADING(UnitActiveState t) { return t == UNIT_ACTIVE || t == UNIT_RELOADING; } static inline bool UNIT_IS_ACTIVE_OR_ACTIVATING(UnitActiveState t) { return t == UNIT_ACTIVE || t == UNIT_ACTIVATING || t == UNIT_RELOADING; } static inline bool UNIT_IS_INACTIVE_OR_DEACTIVATING(UnitActiveState t) { return t == UNIT_INACTIVE || t == UNIT_FAILED || t == UNIT_DEACTIVATING; } static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) { return t == UNIT_INACTIVE || t == UNIT_FAILED; } #include "job.h" struct UnitRef { /* Keeps tracks of references to a unit. This is useful so * that we can merge two units if necessary and correct all * references to them */ Unit* unit; LIST_FIELDS(UnitRef, refs); }; struct Unit { Manager *manager; UnitType type; UnitLoadState load_state; Unit *merged_into; char *id; /* One name is special because we use it for identification. Points to an entry in the names set */ char *instance; Set *names; Set *dependencies[_UNIT_DEPENDENCY_MAX]; char **requires_mounts_for; char *description; char **documentation; char *fragment_path; /* if loaded from a config file this is the primary path to it */ char *source_path; /* if converted, the source file */ char **dropin_paths; usec_t fragment_mtime; usec_t source_mtime; usec_t dropin_mtime; /* If there is something to do with this unit, then this is the installed job for it */ Job *job; /* JOB_NOP jobs are special and can be installed without disturbing the real job. */ Job *nop_job; /* The slot used for watching NameOwnerChanged signals */ sd_bus_slot *match_bus_slot; /* Job timeout and action to take */ usec_t job_timeout; FailureAction job_timeout_action; char *job_timeout_reboot_arg; /* References to this */ LIST_HEAD(UnitRef, refs); /* Conditions to check */ LIST_HEAD(Condition, conditions); LIST_HEAD(Condition, asserts); dual_timestamp condition_timestamp; dual_timestamp assert_timestamp; /* Updated whenever the low-level state changes */ dual_timestamp state_change_timestamp; /* Updated whenever the (high-level) active state enters or leaves the active or inactive states */ dual_timestamp inactive_exit_timestamp; dual_timestamp active_enter_timestamp; dual_timestamp active_exit_timestamp; dual_timestamp inactive_enter_timestamp; UnitRef slice; /* Per type list */ LIST_FIELDS(Unit, units_by_type); /* All units which have requires_mounts_for set */ LIST_FIELDS(Unit, has_requires_mounts_for); /* Load queue */ LIST_FIELDS(Unit, load_queue); /* D-Bus queue */ LIST_FIELDS(Unit, dbus_queue); /* Cleanup queue */ LIST_FIELDS(Unit, cleanup_queue); /* GC queue */ LIST_FIELDS(Unit, gc_queue); /* CGroup realize members queue */ LIST_FIELDS(Unit, cgroup_queue); /* Units with the same CGroup netclass */ LIST_FIELDS(Unit, cgroup_netclass); /* PIDs we keep an eye on. Note that a unit might have many * more, but these are the ones we care enough about to * process SIGCHLD for */ Set *pids; /* Used during GC sweeps */ unsigned gc_marker; /* Error code when we didn't manage to load the unit (negative) */ int load_error; /* Put a ratelimit on unit starting */ RateLimit start_limit; FailureAction start_limit_action; char *reboot_arg; /* Make sure we never enter endless loops with the check unneeded logic, or the BindsTo= logic */ RateLimit auto_stop_ratelimit; /* Cached unit file state and preset */ UnitFileState unit_file_state; int unit_file_preset; /* Where the cpuacct.usage cgroup counter was at the time the unit was started */ nsec_t cpuacct_usage_base; /* Counterparts in the cgroup filesystem */ char *cgroup_path; CGroupMask cgroup_realized_mask; CGroupMask cgroup_subtree_mask; CGroupMask cgroup_members_mask; int cgroup_inotify_wd; uint32_t cgroup_netclass_id; /* How to start OnFailure units */ JobMode on_failure_job_mode; /* Garbage collect us we nobody wants or requires us anymore */ bool stop_when_unneeded; /* Create default dependencies */ bool default_dependencies; /* Refuse manual starting, allow starting only indirectly via dependency. */ bool refuse_manual_start; /* Don't allow the user to stop this unit manually, allow stopping only indirectly via dependency. */ bool refuse_manual_stop; /* Allow isolation requests */ bool allow_isolate; /* Ignore this unit when isolating */ bool ignore_on_isolate; /* Did the last condition check succeed? */ bool condition_result; bool assert_result; /* Is this a transient unit? */ bool transient; bool in_load_queue:1; bool in_dbus_queue:1; bool in_cleanup_queue:1; bool in_gc_queue:1; bool in_cgroup_queue:1; bool sent_dbus_new_signal:1; bool no_gc:1; bool in_audit:1; bool cgroup_realized:1; bool cgroup_members_mask_valid:1; bool cgroup_subtree_mask_valid:1; bool start_limit_hit:1; /* Did we already invoke unit_coldplug() for this unit? */ bool coldplugged:1; }; struct UnitStatusMessageFormats { const char *starting_stopping[2]; const char *finished_start_job[_JOB_RESULT_MAX]; const char *finished_stop_job[_JOB_RESULT_MAX]; }; typedef enum UnitSetPropertiesMode { UNIT_CHECK = 0, UNIT_RUNTIME = 1, UNIT_PERSISTENT = 2, } UnitSetPropertiesMode; #include "automount.h" #include "busname.h" #include "device.h" #include "path.h" #include "scope.h" #include "slice.h" #include "socket.h" #include "swap.h" #include "target.h" #include "timer.h" struct UnitVTable { /* How much memory does an object of this unit type need */ size_t object_size; /* If greater than 0, the offset into the object where * ExecContext is found, if the unit type has that */ size_t exec_context_offset; /* If greater than 0, the offset into the object where * CGroupContext is found, if the unit type has that */ size_t cgroup_context_offset; /* If greater than 0, the offset into the object where * KillContext is found, if the unit type has that */ size_t kill_context_offset; /* If greater than 0, the offset into the object where the * pointer to ExecRuntime is found, if the unit type has * that */ size_t exec_runtime_offset; /* The name of the configuration file section with the private settings of this unit */ const char *private_section; /* Config file sections this unit type understands, separated * by NUL chars */ const char *sections; /* This should reset all type-specific variables. This should * not allocate memory, and is called with zero-initialized * data. It should hence only initialize variables that need * to be set != 0. */ void (*init)(Unit *u); /* This should free all type-specific variables. It should be * idempotent. */ void (*done)(Unit *u); /* Actually load data from disk. This may fail, and should set * load_state to UNIT_LOADED, UNIT_MERGED or leave it at * UNIT_STUB if no configuration could be found. */ int (*load)(Unit *u); /* If a lot of units got created via enumerate(), this is * where to actually set the state and call unit_notify(). */ int (*coldplug)(Unit *u); void (*dump)(Unit *u, FILE *f, const char *prefix); int (*start)(Unit *u); int (*stop)(Unit *u); int (*reload)(Unit *u); int (*kill)(Unit *u, KillWho w, int signo, sd_bus_error *error); bool (*can_reload)(Unit *u); /* Write all data that cannot be restored from other sources * away using unit_serialize_item() */ int (*serialize)(Unit *u, FILE *f, FDSet *fds); /* Restore one item from the serialization */ int (*deserialize_item)(Unit *u, const char *key, const char *data, FDSet *fds); /* Try to match up fds with what we need for this unit */ void (*distribute_fds)(Unit *u, FDSet *fds); /* Boils down the more complex internal state of this unit to * a simpler one that the engine can understand */ UnitActiveState (*active_state)(Unit *u); /* Returns the substate specific to this unit type as * string. This is purely information so that we can give the * user a more fine grained explanation in which actual state a * unit is in. */ const char* (*sub_state_to_string)(Unit *u); /* Return true when there is reason to keep this entry around * even nothing references it and it isn't active in any * way */ bool (*check_gc)(Unit *u); /* When the unit is not running and no job for it queued we * shall release its runtime resources */ void (*release_resources)(Unit *u); /* Invoked on every child that died */ void (*sigchld_event)(Unit *u, pid_t pid, int code, int status); /* Reset failed state if we are in failed state */ void (*reset_failed)(Unit *u); /* Called whenever any of the cgroups this unit watches for * ran empty */ void (*notify_cgroup_empty)(Unit *u); /* Called whenever a process of this unit sends us a message */ void (*notify_message)(Unit *u, pid_t pid, char **tags, FDSet *fds); /* Called whenever a name this Unit registered for comes or * goes away. */ void (*bus_name_owner_change)(Unit *u, const char *name, const char *old_owner, const char *new_owner); /* Called for each property that is being set */ int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error); /* Called after at least one property got changed to apply the necessary change */ int (*bus_commit_properties)(Unit *u); /* Return the unit this unit is following */ Unit *(*following)(Unit *u); /* Return the set of units that are following each other */ int (*following_set)(Unit *u, Set **s); /* Invoked each time a unit this unit is triggering changes * state or gains/loses a job */ void (*trigger_notify)(Unit *u, Unit *trigger); /* Called whenever CLOCK_REALTIME made a jump */ void (*time_change)(Unit *u); /* Returns the next timeout of a unit */ int (*get_timeout)(Unit *u, usec_t *timeout); /* This is called for each unit type and should be used to * enumerate existing devices and load them. However, * everything that is loaded here should still stay in * inactive state. It is the job of the coldplug() call above * to put the units into the initial state. */ void (*enumerate)(Manager *m); /* Type specific cleanups. */ void (*shutdown)(Manager *m); /* If this function is set and return false all jobs for units * of this type will immediately fail. */ bool (*supported)(void); /* The bus vtable */ const sd_bus_vtable *bus_vtable; /* The strings to print in status messages */ UnitStatusMessageFormats status_message_formats; /* Can units of this type have multiple names? */ bool no_alias:1; /* Instances make no sense for this type */ bool no_instances:1; /* True if transient units of this type are OK */ bool can_transient:1; }; extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX]; #define UNIT_VTABLE(u) unit_vtable[(u)->type] /* For casting a unit into the various unit types */ #define DEFINE_CAST(UPPERCASE, MixedCase) \ static inline MixedCase* UPPERCASE(Unit *u) { \ if (_unlikely_(!u || u->type != UNIT_##UPPERCASE)) \ return NULL; \ \ return (MixedCase*) u; \ } /* For casting the various unit types into a unit */ #define UNIT(u) (&(u)->meta) #define UNIT_HAS_EXEC_CONTEXT(u) (UNIT_VTABLE(u)->exec_context_offset > 0) #define UNIT_HAS_CGROUP_CONTEXT(u) (UNIT_VTABLE(u)->cgroup_context_offset > 0) #define UNIT_HAS_KILL_CONTEXT(u) (UNIT_VTABLE(u)->kill_context_offset > 0) #define UNIT_TRIGGER(u) ((Unit*) set_first((u)->dependencies[UNIT_TRIGGERS])) DEFINE_CAST(SERVICE, Service); DEFINE_CAST(SOCKET, Socket); DEFINE_CAST(BUSNAME, BusName); DEFINE_CAST(TARGET, Target); DEFINE_CAST(DEVICE, Device); DEFINE_CAST(MOUNT, Mount); DEFINE_CAST(AUTOMOUNT, Automount); DEFINE_CAST(SWAP, Swap); DEFINE_CAST(TIMER, Timer); DEFINE_CAST(PATH, Path); DEFINE_CAST(SLICE, Slice); DEFINE_CAST(SCOPE, Scope); Unit *unit_new(Manager *m, size_t size); void unit_free(Unit *u); int unit_add_name(Unit *u, const char *name); int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_reference); int unit_add_two_dependencies(Unit *u, UnitDependency d, UnitDependency e, Unit *other, bool add_reference); int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, const char *filename, bool add_reference); int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference); int unit_add_exec_dependencies(Unit *u, ExecContext *c); int unit_choose_id(Unit *u, const char *name); int unit_set_description(Unit *u, const char *description); bool unit_check_gc(Unit *u); void unit_add_to_load_queue(Unit *u); void unit_add_to_dbus_queue(Unit *u); void unit_add_to_cleanup_queue(Unit *u); void unit_add_to_gc_queue(Unit *u); int unit_merge(Unit *u, Unit *other); int unit_merge_by_name(Unit *u, const char *other); Unit *unit_follow_merge(Unit *u) _pure_; int unit_load_fragment_and_dropin(Unit *u); int unit_load_fragment_and_dropin_optional(Unit *u); int unit_load(Unit *unit); int unit_set_slice(Unit *u, Unit *slice); int unit_set_default_slice(Unit *u); const char *unit_description(Unit *u) _pure_; bool unit_has_name(Unit *u, const char *name); UnitActiveState unit_active_state(Unit *u); const char* unit_sub_state_to_string(Unit *u); void unit_dump(Unit *u, FILE *f, const char *prefix); bool unit_can_reload(Unit *u) _pure_; bool unit_can_start(Unit *u) _pure_; bool unit_can_isolate(Unit *u) _pure_; int unit_start(Unit *u); int unit_stop(Unit *u); int unit_reload(Unit *u); int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error); int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, sd_bus_error *error); void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success); int unit_watch_pid(Unit *u, pid_t pid); void unit_unwatch_pid(Unit *u, pid_t pid); void unit_unwatch_all_pids(Unit *u); void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2); int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name); int unit_watch_bus_name(Unit *u, const char *name); void unit_unwatch_bus_name(Unit *u, const char *name); bool unit_job_is_applicable(Unit *u, JobType j); int set_unit_path(const char *p); char *unit_dbus_path(Unit *u); int unit_load_related_unit(Unit *u, const char *type, Unit **_found); bool unit_can_serialize(Unit *u) _pure_; int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs); int unit_deserialize(Unit *u, FILE *f, FDSet *fds); int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value); int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value); int unit_serialize_item_fd(Unit *u, FILE *f, FDSet *fds, const char *key, int fd); void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *value, ...) _printf_(4,5); int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency d); int unit_coldplug(Unit *u); void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) _printf_(3, 0); void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t); bool unit_need_daemon_reload(Unit *u); void unit_reset_failed(Unit *u); Unit *unit_following(Unit *u); int unit_following_set(Unit *u, Set **s); const char *unit_slice_name(Unit *u); bool unit_stop_pending(Unit *u) _pure_; bool unit_inactive_or_pending(Unit *u) _pure_; bool unit_active_or_pending(Unit *u); int unit_add_default_target_dependency(Unit *u, Unit *target); void unit_start_on_failure(Unit *u); void unit_trigger_notify(Unit *u); UnitFileState unit_get_unit_file_state(Unit *u); int unit_get_unit_file_preset(Unit *u); Unit* unit_ref_set(UnitRef *ref, Unit *u); void unit_ref_unset(UnitRef *ref); #define UNIT_DEREF(ref) ((ref).unit) #define UNIT_ISSET(ref) (!!(ref).unit) int unit_patch_contexts(Unit *u); ExecContext *unit_get_exec_context(Unit *u) _pure_; KillContext *unit_get_kill_context(Unit *u) _pure_; CGroupContext *unit_get_cgroup_context(Unit *u) _pure_; ExecRuntime *unit_get_exec_runtime(Unit *u) _pure_; int unit_setup_exec_runtime(Unit *u); int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data); int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) _printf_(4,5); int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data); int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) _printf_(4,5); int unit_kill_context(Unit *u, KillContext *c, KillOperation k, pid_t main_pid, pid_t control_pid, bool main_pid_alien); int unit_make_transient(Unit *u); int unit_require_mounts_for(Unit *u, const char *path); bool unit_type_supported(UnitType t); bool unit_is_pristine(Unit *u); static inline bool unit_supported(Unit *u) { return unit_type_supported(u->type); } void unit_warn_if_dir_nonempty(Unit *u, const char* where); int unit_fail_if_symlink(Unit *u, const char* where); /* Macros which append UNIT= or USER_UNIT= to the message */ #define log_unit_full(unit, level, error, ...) \ ({ \ Unit *_u = (unit); \ _u ? log_object_internal(level, error, __FILE__, __LINE__, __func__, _u->manager->unit_log_field, _u->id, ##__VA_ARGS__) : \ log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ }) #define log_unit_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__) #define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, 0, ##__VA_ARGS__) #define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, 0, ##__VA_ARGS__) #define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, 0, ##__VA_ARGS__) #define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, 0, ##__VA_ARGS__) #define log_unit_debug_errno(unit, error, ...) log_unit_full(unit, LOG_DEBUG, error, ##__VA_ARGS__) #define log_unit_info_errno(unit, error, ...) log_unit_full(unit, LOG_INFO, error, ##__VA_ARGS__) #define log_unit_notice_errno(unit, error, ...) log_unit_full(unit, LOG_NOTICE, error, ##__VA_ARGS__) #define log_unit_warning_errno(unit, error, ...) log_unit_full(unit, LOG_WARNING, error, ##__VA_ARGS__) #define log_unit_error_errno(unit, error, ...) log_unit_full(unit, LOG_ERR, error, ##__VA_ARGS__) #define LOG_UNIT_MESSAGE(unit, fmt, ...) "MESSAGE=%s: " fmt, (unit)->id, ##__VA_ARGS__ #define LOG_UNIT_ID(unit) (unit)->manager->unit_log_format_string, (unit)->id systemd-229/src/core/user.conf000066400000000000000000000021471265713322000164310ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # You can override the directives in this file by creating files in # /etc/systemd/user.conf.d/*.conf. # # See systemd-user.conf(5) for details [Manager] #LogLevel=info #LogTarget=console #LogColor=yes #LogLocation=no #SystemCallArchitectures= #TimerSlackNSec= #DefaultTimerAccuracySec=1min #DefaultStandardOutput=inherit #DefaultStandardError=inherit #DefaultTimeoutStartSec=90s #DefaultTimeoutStopSec=90s #DefaultRestartSec=100ms #DefaultStartLimitInterval=10s #DefaultStartLimitBurst=5 #DefaultEnvironment= #DefaultLimitCPU= #DefaultLimitFSIZE= #DefaultLimitDATA= #DefaultLimitSTACK= #DefaultLimitCORE= #DefaultLimitRSS= #DefaultLimitNOFILE= #DefaultLimitAS= #DefaultLimitNPROC= #DefaultLimitMEMLOCK= #DefaultLimitLOCKS= #DefaultLimitSIGPENDING= #DefaultLimitMSGQUEUE= #DefaultLimitNICE= #DefaultLimitRTPRIO= #DefaultLimitRTTIME= systemd-229/src/coredump/000077500000000000000000000000001265713322000154665ustar00rootroot00000000000000systemd-229/src/coredump/Makefile000077700000000000000000000000001265713322000207742../Makefileustar00rootroot00000000000000systemd-229/src/coredump/coredump-vacuum.c000066400000000000000000000212521265713322000207500ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "coredump-vacuum.h" #include "dirent-util.h" #include "fd-util.h" #include "hashmap.h" #include "macro.h" #include "string-util.h" #include "time-util.h" #include "user-util.h" #include "util.h" #define DEFAULT_MAX_USE_LOWER (uint64_t) (1ULL*1024ULL*1024ULL) /* 1 MiB */ #define DEFAULT_MAX_USE_UPPER (uint64_t) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */ #define DEFAULT_KEEP_FREE_UPPER (uint64_t) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */ #define DEFAULT_KEEP_FREE (uint64_t) (1024ULL*1024ULL) /* 1 MB */ struct vacuum_candidate { unsigned n_files; char *oldest_file; usec_t oldest_mtime; }; static void vacuum_candidate_free(struct vacuum_candidate *c) { if (!c) return; free(c->oldest_file); free(c); } DEFINE_TRIVIAL_CLEANUP_FUNC(struct vacuum_candidate*, vacuum_candidate_free); static void vacuum_candidate_hasmap_free(Hashmap *h) { struct vacuum_candidate *c; while ((c = hashmap_steal_first(h))) vacuum_candidate_free(c); hashmap_free(h); } DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, vacuum_candidate_hasmap_free); static int uid_from_file_name(const char *filename, uid_t *uid) { const char *p, *e, *u; p = startswith(filename, "core."); if (!p) return -EINVAL; /* Skip the comm field */ p = strchr(p, '.'); if (!p) return -EINVAL; p++; /* Find end up UID */ e = strchr(p, '.'); if (!e) return -EINVAL; u = strndupa(p, e-p); return parse_uid(u, uid); } static bool vacuum_necessary(int fd, uint64_t sum, uint64_t keep_free, uint64_t max_use) { uint64_t fs_size = 0, fs_free = (uint64_t) -1; struct statvfs sv; assert(fd >= 0); if (fstatvfs(fd, &sv) >= 0) { fs_size = sv.f_frsize * sv.f_blocks; fs_free = sv.f_frsize * sv.f_bfree; } if (max_use == (uint64_t) -1) { if (fs_size > 0) { max_use = PAGE_ALIGN(fs_size / 10); /* 10% */ if (max_use > DEFAULT_MAX_USE_UPPER) max_use = DEFAULT_MAX_USE_UPPER; if (max_use < DEFAULT_MAX_USE_LOWER) max_use = DEFAULT_MAX_USE_LOWER; } else max_use = DEFAULT_MAX_USE_LOWER; } else max_use = PAGE_ALIGN(max_use); if (max_use > 0 && sum > max_use) return true; if (keep_free == (uint64_t) -1) { if (fs_size > 0) { keep_free = PAGE_ALIGN((fs_size * 3) / 20); /* 15% */ if (keep_free > DEFAULT_KEEP_FREE_UPPER) keep_free = DEFAULT_KEEP_FREE_UPPER; } else keep_free = DEFAULT_KEEP_FREE; } else keep_free = PAGE_ALIGN(keep_free); if (keep_free > 0 && fs_free < keep_free) return true; return false; } int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) { _cleanup_closedir_ DIR *d = NULL; struct stat exclude_st; int r; if (keep_free == 0 && max_use == 0) return 0; if (exclude_fd >= 0) { if (fstat(exclude_fd, &exclude_st) < 0) return log_error_errno(errno, "Failed to fstat(): %m"); } /* This algorithm will keep deleting the oldest file of the * user with the most coredumps until we are back in the size * limits. Note that vacuuming for journal files is different, * because we rely on rate-limiting of the messages there, * to avoid being flooded. */ d = opendir("/var/lib/systemd/coredump"); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Can't open coredump directory: %m"); } for (;;) { _cleanup_(vacuum_candidate_hasmap_freep) Hashmap *h = NULL; struct vacuum_candidate *worst = NULL; struct dirent *de; uint64_t sum = 0; rewinddir(d); FOREACH_DIRENT(de, d, goto fail) { struct vacuum_candidate *c; struct stat st; uid_t uid; usec_t t; r = uid_from_file_name(de->d_name, &uid); if (r < 0) continue; if (fstatat(dirfd(d), de->d_name, &st, AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW) < 0) { if (errno == ENOENT) continue; log_warning_errno(errno, "Failed to stat /var/lib/systemd/coredump/%s: %m", de->d_name); continue; } if (!S_ISREG(st.st_mode)) continue; if (exclude_fd >= 0 && exclude_st.st_dev == st.st_dev && exclude_st.st_ino == st.st_ino) continue; r = hashmap_ensure_allocated(&h, NULL); if (r < 0) return log_oom(); t = timespec_load(&st.st_mtim); c = hashmap_get(h, UID_TO_PTR(uid)); if (c) { if (t < c->oldest_mtime) { char *n; n = strdup(de->d_name); if (!n) return log_oom(); free(c->oldest_file); c->oldest_file = n; c->oldest_mtime = t; } } else { _cleanup_(vacuum_candidate_freep) struct vacuum_candidate *n = NULL; n = new0(struct vacuum_candidate, 1); if (!n) return log_oom(); n->oldest_file = strdup(de->d_name); if (!n->oldest_file) return log_oom(); n->oldest_mtime = t; r = hashmap_put(h, UID_TO_PTR(uid), n); if (r < 0) return log_oom(); c = n; n = NULL; } c->n_files++; if (!worst || worst->n_files < c->n_files || (worst->n_files == c->n_files && c->oldest_mtime < worst->oldest_mtime)) worst = c; sum += st.st_blocks * 512; } if (!worst) break; r = vacuum_necessary(dirfd(d), sum, keep_free, max_use); if (r <= 0) return r; if (unlinkat(dirfd(d), worst->oldest_file, 0) < 0) { if (errno == ENOENT) continue; return log_error_errno(errno, "Failed to remove file %s: %m", worst->oldest_file); } else log_info("Removed old coredump %s.", worst->oldest_file); } return 0; fail: return log_error_errno(errno, "Failed to read directory: %m"); } systemd-229/src/coredump/coredump-vacuum.h000066400000000000000000000015261265713322000207570ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use); systemd-229/src/coredump/coredump.c000066400000000000000000001147121265713322000174560ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #ifdef HAVE_ELFUTILS #include #include #endif #include "sd-journal.h" #include "sd-login.h" #include "sd-daemon.h" #include "acl-util.h" #include "alloc-util.h" #include "capability-util.h" #include "cgroup-util.h" #include "compress.h" #include "conf-parser.h" #include "copy.h" #include "coredump-vacuum.h" #include "dirent-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "io-util.h" #include "journald-native.h" #include "log.h" #include "macro.h" #include "mkdir.h" #include "parse-util.h" #include "process-util.h" #include "socket-util.h" #include "special.h" #include "stacktrace.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "user-util.h" #include "util.h" /* The maximum size up to which we process coredumps */ #define PROCESS_SIZE_MAX ((uint64_t) (2LLU*1024LLU*1024LLU*1024LLU)) /* The maximum size up to which we leave the coredump around on disk */ #define EXTERNAL_SIZE_MAX PROCESS_SIZE_MAX /* The maximum size up to which we store the coredump in the journal */ #define JOURNAL_SIZE_MAX ((size_t) (767LU*1024LU*1024LU)) /* Make sure to not make this larger than the maximum journal entry * size. See DATA_SIZE_MAX in journald-native.c. */ assert_cc(JOURNAL_SIZE_MAX <= DATA_SIZE_MAX); enum { /* We use this as array indexes for a couple of special fields we use for naming coredumping files, and * attaching xattrs */ CONTEXT_PID, CONTEXT_UID, CONTEXT_GID, CONTEXT_SIGNAL, CONTEXT_TIMESTAMP, CONTEXT_RLIMIT, CONTEXT_COMM, CONTEXT_EXE, _CONTEXT_MAX }; typedef enum CoredumpStorage { COREDUMP_STORAGE_NONE, COREDUMP_STORAGE_EXTERNAL, COREDUMP_STORAGE_JOURNAL, COREDUMP_STORAGE_BOTH, _COREDUMP_STORAGE_MAX, _COREDUMP_STORAGE_INVALID = -1 } CoredumpStorage; static const char* const coredump_storage_table[_COREDUMP_STORAGE_MAX] = { [COREDUMP_STORAGE_NONE] = "none", [COREDUMP_STORAGE_EXTERNAL] = "external", [COREDUMP_STORAGE_JOURNAL] = "journal", [COREDUMP_STORAGE_BOTH] = "both", }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP(coredump_storage, CoredumpStorage); static DEFINE_CONFIG_PARSE_ENUM(config_parse_coredump_storage, coredump_storage, CoredumpStorage, "Failed to parse storage setting"); static CoredumpStorage arg_storage = COREDUMP_STORAGE_EXTERNAL; static bool arg_compress = true; static uint64_t arg_process_size_max = PROCESS_SIZE_MAX; static uint64_t arg_external_size_max = EXTERNAL_SIZE_MAX; static size_t arg_journal_size_max = JOURNAL_SIZE_MAX; static uint64_t arg_keep_free = (uint64_t) -1; static uint64_t arg_max_use = (uint64_t) -1; static int parse_config(void) { static const ConfigTableItem items[] = { { "Coredump", "Storage", config_parse_coredump_storage, 0, &arg_storage }, { "Coredump", "Compress", config_parse_bool, 0, &arg_compress }, { "Coredump", "ProcessSizeMax", config_parse_iec_uint64, 0, &arg_process_size_max }, { "Coredump", "ExternalSizeMax", config_parse_iec_uint64, 0, &arg_external_size_max }, { "Coredump", "JournalSizeMax", config_parse_iec_size, 0, &arg_journal_size_max }, { "Coredump", "KeepFree", config_parse_iec_uint64, 0, &arg_keep_free }, { "Coredump", "MaxUse", config_parse_iec_uint64, 0, &arg_max_use }, {} }; return config_parse_many(PKGSYSCONFDIR "/coredump.conf", CONF_PATHS_NULSTR("systemd/coredump.conf.d"), "Coredump\0", config_item_table_lookup, items, false, NULL); } static int fix_acl(int fd, uid_t uid) { #ifdef HAVE_ACL _cleanup_(acl_freep) acl_t acl = NULL; acl_entry_t entry; acl_permset_t permset; int r; assert(fd >= 0); if (uid <= SYSTEM_UID_MAX) return 0; /* Make sure normal users can read (but not write or delete) * their own coredumps */ acl = acl_get_fd(fd); if (!acl) return log_error_errno(errno, "Failed to get ACL: %m"); if (acl_create_entry(&acl, &entry) < 0 || acl_set_tag_type(entry, ACL_USER) < 0 || acl_set_qualifier(entry, &uid) < 0) { log_error_errno(errno, "Failed to patch ACL: %m"); return -errno; } if (acl_get_permset(entry, &permset) < 0 || acl_add_perm(permset, ACL_READ) < 0) return log_warning_errno(errno, "Failed to patch ACL: %m"); r = calc_acl_mask_if_needed(&acl); if (r < 0) return log_warning_errno(r, "Failed to patch ACL: %m"); if (acl_set_fd(fd, acl) < 0) return log_error_errno(errno, "Failed to apply ACL: %m"); #endif return 0; } static int fix_xattr(int fd, const char *context[_CONTEXT_MAX]) { static const char * const xattrs[_CONTEXT_MAX] = { [CONTEXT_PID] = "user.coredump.pid", [CONTEXT_UID] = "user.coredump.uid", [CONTEXT_GID] = "user.coredump.gid", [CONTEXT_SIGNAL] = "user.coredump.signal", [CONTEXT_TIMESTAMP] = "user.coredump.timestamp", [CONTEXT_COMM] = "user.coredump.comm", [CONTEXT_EXE] = "user.coredump.exe", }; int r = 0; unsigned i; assert(fd >= 0); /* Attach some metadata to coredumps via extended * attributes. Just because we can. */ for (i = 0; i < _CONTEXT_MAX; i++) { int k; if (isempty(context[i]) || !xattrs[i]) continue; k = fsetxattr(fd, xattrs[i], context[i], strlen(context[i]), XATTR_CREATE); if (k < 0 && r == 0) r = -errno; } return r; } #define filename_escape(s) xescape((s), "./ ") static int fix_permissions( int fd, const char *filename, const char *target, const char *context[_CONTEXT_MAX], uid_t uid) { assert(fd >= 0); assert(filename); assert(target); assert(context); /* Ignore errors on these */ (void) fchmod(fd, 0640); (void) fix_acl(fd, uid); (void) fix_xattr(fd, context); if (fsync(fd) < 0) return log_error_errno(errno, "Failed to sync coredump %s: %m", filename); if (rename(filename, target) < 0) return log_error_errno(errno, "Failed to rename coredump %s -> %s: %m", filename, target); return 0; } static int maybe_remove_external_coredump(const char *filename, uint64_t size) { /* Returns 1 if might remove, 0 if will not remove, < 0 on error. */ if (IN_SET(arg_storage, COREDUMP_STORAGE_EXTERNAL, COREDUMP_STORAGE_BOTH) && size <= arg_external_size_max) return 0; if (!filename) return 1; if (unlink(filename) < 0 && errno != ENOENT) return log_error_errno(errno, "Failed to unlink %s: %m", filename); return 1; } static int make_filename(const char *context[_CONTEXT_MAX], char **ret) { _cleanup_free_ char *c = NULL, *u = NULL, *p = NULL, *t = NULL; sd_id128_t boot = {}; int r; assert(context); c = filename_escape(context[CONTEXT_COMM]); if (!c) return -ENOMEM; u = filename_escape(context[CONTEXT_UID]); if (!u) return -ENOMEM; r = sd_id128_get_boot(&boot); if (r < 0) return r; p = filename_escape(context[CONTEXT_PID]); if (!p) return -ENOMEM; t = filename_escape(context[CONTEXT_TIMESTAMP]); if (!t) return -ENOMEM; if (asprintf(ret, "/var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR ".%s.%s000000", c, u, SD_ID128_FORMAT_VAL(boot), p, t) < 0) return -ENOMEM; return 0; } static int save_external_coredump( const char *context[_CONTEXT_MAX], int input_fd, char **ret_filename, int *ret_node_fd, int *ret_data_fd, uint64_t *ret_size) { _cleanup_free_ char *fn = NULL, *tmp = NULL; _cleanup_close_ int fd = -1; uint64_t rlimit, max_size; struct stat st; uid_t uid; int r; assert(context); assert(ret_filename); assert(ret_node_fd); assert(ret_data_fd); assert(ret_size); r = parse_uid(context[CONTEXT_UID], &uid); if (r < 0) return log_error_errno(r, "Failed to parse UID: %m"); r = safe_atou64(context[CONTEXT_RLIMIT], &rlimit); if (r < 0) return log_error_errno(r, "Failed to parse resource limit: %s", context[CONTEXT_RLIMIT]); if (rlimit <= 0) { /* Is coredumping disabled? Then don't bother saving/processing the coredump */ log_info("Core Dumping has been disabled for process %s (%s).", context[CONTEXT_PID], context[CONTEXT_COMM]); return -EBADSLT; } /* Never store more than the process configured, or than we actually shall keep or process */ max_size = MIN(rlimit, MAX(arg_process_size_max, arg_external_size_max)); r = make_filename(context, &fn); if (r < 0) return log_error_errno(r, "Failed to determine coredump file name: %m"); r = tempfn_random(fn, NULL, &tmp); if (r < 0) return log_error_errno(r, "Failed to determine temporary file name: %m"); mkdir_p_label("/var/lib/systemd/coredump", 0755); fd = open(tmp, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0640); if (fd < 0) return log_error_errno(errno, "Failed to create coredump file %s: %m", tmp); r = copy_bytes(input_fd, fd, max_size, false); if (r == -EFBIG) { log_error("Coredump of %s (%s) is larger than configured processing limit, refusing.", context[CONTEXT_PID], context[CONTEXT_COMM]); goto fail; } else if (IN_SET(r, -EDQUOT, -ENOSPC)) { log_error("Not enough disk space for coredump of %s (%s), refusing.", context[CONTEXT_PID], context[CONTEXT_COMM]); goto fail; } else if (r < 0) { log_error_errno(r, "Failed to dump coredump to file: %m"); goto fail; } if (fstat(fd, &st) < 0) { log_error_errno(errno, "Failed to fstat coredump %s: %m", tmp); goto fail; } if (lseek(fd, 0, SEEK_SET) == (off_t) -1) { log_error_errno(errno, "Failed to seek on %s: %m", tmp); goto fail; } #if defined(HAVE_XZ) || defined(HAVE_LZ4) /* If we will remove the coredump anyway, do not compress. */ if (maybe_remove_external_coredump(NULL, st.st_size) == 0 && arg_compress) { _cleanup_free_ char *fn_compressed = NULL, *tmp_compressed = NULL; _cleanup_close_ int fd_compressed = -1; fn_compressed = strappend(fn, COMPRESSED_EXT); if (!fn_compressed) { log_oom(); goto uncompressed; } r = tempfn_random(fn_compressed, NULL, &tmp_compressed); if (r < 0) { log_error_errno(r, "Failed to determine temporary file name for %s: %m", fn_compressed); goto uncompressed; } fd_compressed = open(tmp_compressed, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0640); if (fd_compressed < 0) { log_error_errno(errno, "Failed to create file %s: %m", tmp_compressed); goto uncompressed; } r = compress_stream(fd, fd_compressed, -1); if (r < 0) { log_error_errno(r, "Failed to compress %s: %m", tmp_compressed); goto fail_compressed; } r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid); if (r < 0) goto fail_compressed; /* OK, this worked, we can get rid of the uncompressed version now */ unlink_noerrno(tmp); *ret_filename = fn_compressed; /* compressed */ *ret_node_fd = fd_compressed; /* compressed */ *ret_data_fd = fd; /* uncompressed */ *ret_size = (uint64_t) st.st_size; /* uncompressed */ fn_compressed = NULL; fd = fd_compressed = -1; return 0; fail_compressed: (void) unlink(tmp_compressed); } uncompressed: #endif r = fix_permissions(fd, tmp, fn, context, uid); if (r < 0) goto fail; *ret_filename = fn; *ret_data_fd = fd; *ret_node_fd = -1; *ret_size = (uint64_t) st.st_size; fn = NULL; fd = -1; return 0; fail: (void) unlink(tmp); return r; } static int allocate_journal_field(int fd, size_t size, char **ret, size_t *ret_size) { _cleanup_free_ char *field = NULL; ssize_t n; assert(fd >= 0); assert(ret); assert(ret_size); if (lseek(fd, 0, SEEK_SET) == (off_t) -1) return log_warning_errno(errno, "Failed to seek: %m"); field = malloc(9 + size); if (!field) { log_warning("Failed to allocate memory for coredump, coredump will not be stored."); return -ENOMEM; } memcpy(field, "COREDUMP=", 9); n = read(fd, field + 9, size); if (n < 0) return log_error_errno((int) n, "Failed to read core data: %m"); if ((size_t) n < size) { log_error("Core data too short."); return -EIO; } *ret = field; *ret_size = size + 9; field = NULL; return 0; } /* Joins /proc/[pid]/fd/ and /proc/[pid]/fdinfo/ into the following lines: * 0:/dev/pts/23 * pos: 0 * flags: 0100002 * * 1:/dev/pts/23 * pos: 0 * flags: 0100002 * * 2:/dev/pts/23 * pos: 0 * flags: 0100002 * EOF */ static int compose_open_fds(pid_t pid, char **open_fds) { _cleanup_closedir_ DIR *proc_fd_dir = NULL; _cleanup_close_ int proc_fdinfo_fd = -1; _cleanup_free_ char *buffer = NULL; _cleanup_fclose_ FILE *stream = NULL; const char *fddelim = "", *path; struct dirent *dent = NULL; size_t size = 0; int r = 0; assert(pid >= 0); assert(open_fds != NULL); path = procfs_file_alloca(pid, "fd"); proc_fd_dir = opendir(path); if (!proc_fd_dir) return -errno; proc_fdinfo_fd = openat(dirfd(proc_fd_dir), "../fdinfo", O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC|O_PATH); if (proc_fdinfo_fd < 0) return -errno; stream = open_memstream(&buffer, &size); if (!stream) return -ENOMEM; FOREACH_DIRENT(dent, proc_fd_dir, return -errno) { _cleanup_fclose_ FILE *fdinfo = NULL; _cleanup_free_ char *fdname = NULL; char line[LINE_MAX]; int fd; r = readlinkat_malloc(dirfd(proc_fd_dir), dent->d_name, &fdname); if (r < 0) return r; fprintf(stream, "%s%s:%s\n", fddelim, dent->d_name, fdname); fddelim = "\n"; /* Use the directory entry from /proc/[pid]/fd with /proc/[pid]/fdinfo */ fd = openat(proc_fdinfo_fd, dent->d_name, O_NOFOLLOW|O_CLOEXEC|O_RDONLY); if (fd < 0) continue; fdinfo = fdopen(fd, "re"); if (fdinfo == NULL) { close(fd); continue; } FOREACH_LINE(line, fdinfo, break) { fputs(line, stream); if (!endswith(line, "\n")) fputc('\n', stream); } } errno = 0; stream = safe_fclose(stream); if (errno > 0) return -errno; *open_fds = buffer; buffer = NULL; return 0; } static int change_uid_gid(const char *context[]) { uid_t uid; gid_t gid; int r; r = parse_uid(context[CONTEXT_UID], &uid); if (r < 0) return r; if (uid <= SYSTEM_UID_MAX) { const char *user = "systemd-coredump"; r = get_user_creds(&user, &uid, &gid, NULL, NULL); if (r < 0) { log_warning_errno(r, "Cannot resolve %s user. Proceeding to dump core as root: %m", user); uid = gid = 0; } } else { r = parse_gid(context[CONTEXT_GID], &gid); if (r < 0) return r; } return drop_privileges(uid, gid, 0); } static int submit_coredump( const char *context[_CONTEXT_MAX], struct iovec *iovec, size_t n_iovec_allocated, size_t n_iovec, int input_fd) { _cleanup_close_ int coredump_fd = -1, coredump_node_fd = -1; _cleanup_free_ char *core_message = NULL, *filename = NULL, *coredump_data = NULL; uint64_t coredump_size; int r; assert(context); assert(iovec); assert(n_iovec_allocated >= n_iovec + 3); assert(input_fd >= 0); /* Vacuum before we write anything again */ (void) coredump_vacuum(-1, arg_keep_free, arg_max_use); /* Always stream the coredump to disk, if that's possible */ r = save_external_coredump(context, input_fd, &filename, &coredump_node_fd, &coredump_fd, &coredump_size); if (r < 0) /* Skip whole core dumping part */ goto log; /* If we don't want to keep the coredump on disk, remove it now, as later on we will lack the privileges for * it. However, we keep the fd to it, so that we can still process it and log it. */ r = maybe_remove_external_coredump(filename, coredump_size); if (r < 0) return r; if (r == 0) { const char *coredump_filename; coredump_filename = strjoina("COREDUMP_FILENAME=", filename); IOVEC_SET_STRING(iovec[n_iovec++], coredump_filename); } /* Vacuum again, but exclude the coredump we just created */ (void) coredump_vacuum(coredump_node_fd >= 0 ? coredump_node_fd : coredump_fd, arg_keep_free, arg_max_use); /* Now, let's drop privileges to become the user who owns the segfaulted process and allocate the coredump * memory under the user's uid. This also ensures that the credentials journald will see are the ones of the * coredumping user, thus making sure the user gets access to the core dump. Let's also get rid of all * capabilities, if we run as root, we won't need them anymore. */ r = change_uid_gid(context); if (r < 0) return log_error_errno(r, "Failed to drop privileges: %m"); #ifdef HAVE_ELFUTILS /* Try to get a strack trace if we can */ if (coredump_size <= arg_process_size_max) { _cleanup_free_ char *stacktrace = NULL; r = coredump_make_stack_trace(coredump_fd, context[CONTEXT_EXE], &stacktrace); if (r >= 0) core_message = strjoin("MESSAGE=Process ", context[CONTEXT_PID], " (", context[CONTEXT_COMM], ") of user ", context[CONTEXT_UID], " dumped core.\n\n", stacktrace, NULL); else if (r == -EINVAL) log_warning("Failed to generate stack trace: %s", dwfl_errmsg(dwfl_errno())); else log_warning_errno(r, "Failed to generate stack trace: %m"); } if (!core_message) #endif log: core_message = strjoin("MESSAGE=Process ", context[CONTEXT_PID], " (", context[CONTEXT_COMM], ") of user ", context[CONTEXT_UID], " dumped core.", NULL); if (core_message) IOVEC_SET_STRING(iovec[n_iovec++], core_message); /* Optionally store the entire coredump in the journal */ if (IN_SET(arg_storage, COREDUMP_STORAGE_JOURNAL, COREDUMP_STORAGE_BOTH) && coredump_size <= arg_journal_size_max) { size_t sz = 0; /* Store the coredump itself in the journal */ r = allocate_journal_field(coredump_fd, (size_t) coredump_size, &coredump_data, &sz); if (r >= 0) { iovec[n_iovec].iov_base = coredump_data; iovec[n_iovec].iov_len = sz; n_iovec++; } } assert(n_iovec <= n_iovec_allocated); r = sd_journal_sendv(iovec, n_iovec); if (r < 0) return log_error_errno(r, "Failed to log coredump: %m"); return 0; } static void map_context_fields(const struct iovec *iovec, const char *context[]) { static const char * const context_field_names[_CONTEXT_MAX] = { [CONTEXT_PID] = "COREDUMP_PID=", [CONTEXT_UID] = "COREDUMP_UID=", [CONTEXT_GID] = "COREDUMP_GID=", [CONTEXT_SIGNAL] = "COREDUMP_SIGNAL=", [CONTEXT_TIMESTAMP] = "COREDUMP_TIMESTAMP=", [CONTEXT_COMM] = "COREDUMP_COMM=", [CONTEXT_EXE] = "COREDUMP_EXE=", [CONTEXT_RLIMIT] = "COREDUMP_RLIMIT=", }; unsigned i; assert(iovec); assert(context); for (i = 0; i < _CONTEXT_MAX; i++) { size_t l; l = strlen(context_field_names[i]); if (iovec->iov_len < l) continue; if (memcmp(iovec->iov_base, context_field_names[i], l) != 0) continue; /* Note that these strings are NUL terminated, because we made sure that a trailing NUL byte is in the * buffer, though not included in the iov_len count. (see below) */ context[i] = (char*) iovec->iov_base + l; break; } } static int process_socket(int fd) { _cleanup_close_ int coredump_fd = -1; struct iovec *iovec = NULL; size_t n_iovec = 0, n_iovec_allocated = 0, i; const char *context[_CONTEXT_MAX] = {}; int r; assert(fd >= 0); log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); for (;;) { union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(int))]; } control = {}; struct msghdr mh = { .msg_control = &control, .msg_controllen = sizeof(control), .msg_iovlen = 1, }; ssize_t n; int l; if (!GREEDY_REALLOC(iovec, n_iovec_allocated, n_iovec + 3)) { r = log_oom(); goto finish; } if (ioctl(fd, FIONREAD, &l) < 0) { r = log_error_errno(errno, "FIONREAD failed: %m"); goto finish; } assert(l >= 0); iovec[n_iovec].iov_len = l; iovec[n_iovec].iov_base = malloc(l + 1); if (!iovec[n_iovec].iov_base) { r = log_oom(); goto finish; } mh.msg_iov = iovec + n_iovec; n = recvmsg(fd, &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC); if (n < 0) { free(iovec[n_iovec].iov_base); r = log_error_errno(errno, "Failed to receive datagram: %m"); goto finish; } if (n == 0) { struct cmsghdr *cmsg, *found = NULL; /* The final zero-length datagram carries the file descriptor and tells us that we're done. */ free(iovec[n_iovec].iov_base); CMSG_FOREACH(cmsg, &mh) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { assert(!found); found = cmsg; } } if (!found) { log_error("Coredump file descriptor missing."); r = -EBADMSG; goto finish; } assert(coredump_fd < 0); coredump_fd = *(int*) CMSG_DATA(found); break; } /* Add trailing NUL byte, in case these are strings */ ((char*) iovec[n_iovec].iov_base)[n] = 0; iovec[n_iovec].iov_len = (size_t) n; cmsg_close_all(&mh); map_context_fields(iovec + n_iovec, context); n_iovec++; } if (!GREEDY_REALLOC(iovec, n_iovec_allocated, n_iovec + 3)) { r = log_oom(); goto finish; } /* Make sure we we got all data we really need */ assert(context[CONTEXT_PID]); assert(context[CONTEXT_UID]); assert(context[CONTEXT_GID]); assert(context[CONTEXT_SIGNAL]); assert(context[CONTEXT_TIMESTAMP]); assert(context[CONTEXT_RLIMIT]); assert(context[CONTEXT_COMM]); assert(coredump_fd >= 0); r = submit_coredump(context, iovec, n_iovec_allocated, n_iovec, coredump_fd); finish: for (i = 0; i < n_iovec; i++) free(iovec[i].iov_base); free(iovec); return r; } static int send_iovec(const struct iovec iovec[], size_t n_iovec, int input_fd) { static const union sockaddr_union sa = { .un.sun_family = AF_UNIX, .un.sun_path = "/run/systemd/coredump", }; _cleanup_close_ int fd = -1; size_t i; int r; assert(iovec || n_iovec <= 0); assert(input_fd >= 0); fd = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0); if (fd < 0) return log_error_errno(errno, "Failed to create coredump socket: %m"); if (connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)) < 0) return log_error_errno(errno, "Failed to connect to coredump service: %m"); for (i = 0; i < n_iovec; i++) { ssize_t n; assert(iovec[i].iov_len > 0); n = send(fd, iovec[i].iov_base, iovec[i].iov_len, MSG_NOSIGNAL); if (n < 0) return log_error_errno(errno, "Failed to send coredump datagram: %m"); } r = send_one_fd(fd, input_fd, 0); if (r < 0) return log_error_errno(r, "Failed to send coredump fd: %m"); return 0; } static int process_journald_crash(const char *context[], int input_fd) { _cleanup_close_ int coredump_fd = -1, coredump_node_fd = -1; _cleanup_free_ char *filename = NULL; uint64_t coredump_size; int r; assert(context); assert(input_fd >= 0); /* If we are journald, we cut things short, don't write to the journal, but still create a coredump. */ if (arg_storage != COREDUMP_STORAGE_NONE) arg_storage = COREDUMP_STORAGE_EXTERNAL; r = save_external_coredump(context, input_fd, &filename, &coredump_node_fd, &coredump_fd, &coredump_size); if (r < 0) return r; r = maybe_remove_external_coredump(filename, coredump_size); if (r < 0) return r; log_info("Detected coredump of the journal daemon itself, diverted to %s.", filename); return 0; } static int process_kernel(int argc, char* argv[]) { /* The small core field we allocate on the stack, to keep things simple */ char *core_pid = NULL, *core_uid = NULL, *core_gid = NULL, *core_signal = NULL, *core_session = NULL, *core_exe = NULL, *core_comm = NULL, *core_cmdline = NULL, *core_cgroup = NULL, *core_cwd = NULL, *core_root = NULL, *core_unit = NULL, *core_user_unit = NULL, *core_slice = NULL, *core_timestamp = NULL, *core_rlimit = NULL; /* The larger ones we allocate on the heap */ _cleanup_free_ char *core_owner_uid = NULL, *core_open_fds = NULL, *core_proc_status = NULL, *core_proc_maps = NULL, *core_proc_limits = NULL, *core_proc_cgroup = NULL, *core_environ = NULL; _cleanup_free_ char *exe = NULL, *comm = NULL; const char *context[_CONTEXT_MAX]; struct iovec iovec[25]; size_t n_iovec = 0; uid_t owner_uid; const char *p; pid_t pid; char *t; int r; if (argc < CONTEXT_COMM + 1) { log_error("Not enough arguments passed from kernel (%i, expected %i).", argc - 1, CONTEXT_COMM + 1 - 1); return -EINVAL; } r = parse_pid(argv[CONTEXT_PID + 1], &pid); if (r < 0) return log_error_errno(r, "Failed to parse PID."); r = get_process_comm(pid, &comm); if (r < 0) { log_warning_errno(r, "Failed to get COMM, falling back to the command line: %m"); comm = strv_join(argv + CONTEXT_COMM + 1, " "); if (!comm) return log_oom(); } r = get_process_exe(pid, &exe); if (r < 0) log_warning_errno(r, "Failed to get EXE, ignoring: %m"); context[CONTEXT_PID] = argv[CONTEXT_PID + 1]; context[CONTEXT_UID] = argv[CONTEXT_UID + 1]; context[CONTEXT_GID] = argv[CONTEXT_GID + 1]; context[CONTEXT_SIGNAL] = argv[CONTEXT_SIGNAL + 1]; context[CONTEXT_TIMESTAMP] = argv[CONTEXT_TIMESTAMP + 1]; context[CONTEXT_RLIMIT] = argv[CONTEXT_RLIMIT + 1]; context[CONTEXT_COMM] = comm; context[CONTEXT_EXE] = exe; if (cg_pid_get_unit(pid, &t) >= 0) { if (streq(t, SPECIAL_JOURNALD_SERVICE)) { free(t); return process_journald_crash(context, STDIN_FILENO); } core_unit = strjoina("COREDUMP_UNIT=", t); free(t); IOVEC_SET_STRING(iovec[n_iovec++], core_unit); } /* OK, now we know it's not the journal, hence we can make use of it now. */ log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); log_open(); if (cg_pid_get_user_unit(pid, &t) >= 0) { core_user_unit = strjoina("COREDUMP_USER_UNIT=", t); free(t); IOVEC_SET_STRING(iovec[n_iovec++], core_user_unit); } core_pid = strjoina("COREDUMP_PID=", context[CONTEXT_PID]); IOVEC_SET_STRING(iovec[n_iovec++], core_pid); core_uid = strjoina("COREDUMP_UID=", context[CONTEXT_UID]); IOVEC_SET_STRING(iovec[n_iovec++], core_uid); core_gid = strjoina("COREDUMP_GID=", context[CONTEXT_GID]); IOVEC_SET_STRING(iovec[n_iovec++], core_gid); core_signal = strjoina("COREDUMP_SIGNAL=", context[CONTEXT_SIGNAL]); IOVEC_SET_STRING(iovec[n_iovec++], core_signal); core_rlimit = strjoina("COREDUMP_RLIMIT=", context[CONTEXT_RLIMIT]); IOVEC_SET_STRING(iovec[n_iovec++], core_rlimit); if (sd_pid_get_session(pid, &t) >= 0) { core_session = strjoina("COREDUMP_SESSION=", t); free(t); IOVEC_SET_STRING(iovec[n_iovec++], core_session); } if (sd_pid_get_owner_uid(pid, &owner_uid) >= 0) { r = asprintf(&core_owner_uid, "COREDUMP_OWNER_UID=" UID_FMT, owner_uid); if (r > 0) IOVEC_SET_STRING(iovec[n_iovec++], core_owner_uid); } if (sd_pid_get_slice(pid, &t) >= 0) { core_slice = strjoina("COREDUMP_SLICE=", t); free(t); IOVEC_SET_STRING(iovec[n_iovec++], core_slice); } if (comm) { core_comm = strjoina("COREDUMP_COMM=", comm); IOVEC_SET_STRING(iovec[n_iovec++], core_comm); } if (exe) { core_exe = strjoina("COREDUMP_EXE=", exe); IOVEC_SET_STRING(iovec[n_iovec++], core_exe); } if (get_process_cmdline(pid, 0, false, &t) >= 0) { core_cmdline = strjoina("COREDUMP_CMDLINE=", t); free(t); IOVEC_SET_STRING(iovec[n_iovec++], core_cmdline); } if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0) { core_cgroup = strjoina("COREDUMP_CGROUP=", t); free(t); IOVEC_SET_STRING(iovec[n_iovec++], core_cgroup); } if (compose_open_fds(pid, &t) >= 0) { core_open_fds = strappend("COREDUMP_OPEN_FDS=", t); free(t); if (core_open_fds) IOVEC_SET_STRING(iovec[n_iovec++], core_open_fds); } p = procfs_file_alloca(pid, "status"); if (read_full_file(p, &t, NULL) >= 0) { core_proc_status = strappend("COREDUMP_PROC_STATUS=", t); free(t); if (core_proc_status) IOVEC_SET_STRING(iovec[n_iovec++], core_proc_status); } p = procfs_file_alloca(pid, "maps"); if (read_full_file(p, &t, NULL) >= 0) { core_proc_maps = strappend("COREDUMP_PROC_MAPS=", t); free(t); if (core_proc_maps) IOVEC_SET_STRING(iovec[n_iovec++], core_proc_maps); } p = procfs_file_alloca(pid, "limits"); if (read_full_file(p, &t, NULL) >= 0) { core_proc_limits = strappend("COREDUMP_PROC_LIMITS=", t); free(t); if (core_proc_limits) IOVEC_SET_STRING(iovec[n_iovec++], core_proc_limits); } p = procfs_file_alloca(pid, "cgroup"); if (read_full_file(p, &t, NULL) >=0) { core_proc_cgroup = strappend("COREDUMP_PROC_CGROUP=", t); free(t); if (core_proc_cgroup) IOVEC_SET_STRING(iovec[n_iovec++], core_proc_cgroup); } if (get_process_cwd(pid, &t) >= 0) { core_cwd = strjoina("COREDUMP_CWD=", t); free(t); IOVEC_SET_STRING(iovec[n_iovec++], core_cwd); } if (get_process_root(pid, &t) >= 0) { core_root = strjoina("COREDUMP_ROOT=", t); free(t); IOVEC_SET_STRING(iovec[n_iovec++], core_root); } if (get_process_environ(pid, &t) >= 0) { core_environ = strappend("COREDUMP_ENVIRON=", t); free(t); if (core_environ) IOVEC_SET_STRING(iovec[n_iovec++], core_environ); } core_timestamp = strjoina("COREDUMP_TIMESTAMP=", context[CONTEXT_TIMESTAMP], "000000", NULL); IOVEC_SET_STRING(iovec[n_iovec++], core_timestamp); IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); assert_cc(2 == LOG_CRIT); IOVEC_SET_STRING(iovec[n_iovec++], "PRIORITY=2"); assert(n_iovec <= ELEMENTSOF(iovec)); return send_iovec(iovec, n_iovec, STDIN_FILENO); } int main(int argc, char *argv[]) { int r; /* First, log to a safe place, since we don't know what crashed and it might be journald which we'd rather not * log to then. */ log_set_target(LOG_TARGET_KMSG); log_open(); /* Make sure we never enter a loop */ (void) prctl(PR_SET_DUMPABLE, 0); /* Ignore all parse errors */ (void) parse_config(); log_debug("Selected storage '%s'.", coredump_storage_to_string(arg_storage)); log_debug("Selected compression %s.", yes_no(arg_compress)); r = sd_listen_fds(false); if (r < 0) { log_error_errno(r, "Failed to determine number of file descriptor: %m"); goto finish; } /* If we got an fd passed, we are running in coredumpd mode. Otherwise we are invoked from the kernel as * coredump handler */ if (r == 0) r = process_kernel(argc, argv); else if (r == 1) r = process_socket(SD_LISTEN_FDS_START); else { log_error("Received unexpected number of file descriptors."); r = -EINVAL; } finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/coredump/coredump.conf000066400000000000000000000011471265713322000201560ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # Entries in this file show the compile time defaults. # You can change settings by editing this file. # Defaults can be restored by simply deleting this file. # # See coredump.conf(5) for details. [Coredump] #Storage=external #Compress=yes #ProcessSizeMax=2G #ExternalSizeMax=2G #JournalSizeMax=767M #MaxUse= #KeepFree= systemd-229/src/coredump/coredumpctl.c000066400000000000000000000661211265713322000201610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "sd-journal.h" #include "alloc-util.h" #include "compress.h" #include "fd-util.h" #include "fileio.h" #include "journal-internal.h" #include "log.h" #include "macro.h" #include "pager.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "set.h" #include "sigbus.h" #include "signal-util.h" #include "string-util.h" #include "terminal-util.h" #include "user-util.h" #include "util.h" static enum { ACTION_NONE, ACTION_INFO, ACTION_LIST, ACTION_DUMP, ACTION_GDB, } arg_action = ACTION_LIST; static const char* arg_field = NULL; static const char *arg_directory = NULL; static int arg_no_pager = false; static int arg_no_legend = false; static int arg_one = false; static FILE* arg_output = NULL; static Set *new_matches(void) { Set *set; char *tmp; int r; set = set_new(NULL); if (!set) { log_oom(); return NULL; } tmp = strdup("MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); if (!tmp) { log_oom(); set_free(set); return NULL; } r = set_consume(set, tmp); if (r < 0) { log_error_errno(r, "failed to add to set: %m"); set_free(set); return NULL; } return set; } static int add_match(Set *set, const char *match) { _cleanup_free_ char *p = NULL; char *pattern = NULL; const char* prefix; pid_t pid; int r; if (strchr(match, '=')) prefix = ""; else if (strchr(match, '/')) { r = path_make_absolute_cwd(match, &p); if (r < 0) goto fail; match = p; prefix = "COREDUMP_EXE="; } else if (parse_pid(match, &pid) >= 0) prefix = "COREDUMP_PID="; else prefix = "COREDUMP_COMM="; pattern = strjoin(prefix, match, NULL); if (!pattern) { r = -ENOMEM; goto fail; } log_debug("Adding pattern: %s", pattern); r = set_consume(set, pattern); if (r < 0) goto fail; return 0; fail: return log_error_errno(r, "Failed to add match: %m"); } static void help(void) { printf("%s [OPTIONS...]\n\n" "List or retrieve coredumps from the journal.\n\n" "Flags:\n" " -h --help Show this help\n" " --version Print version string\n" " --no-pager Do not pipe output into a pager\n" " --no-legend Do not print the column headers.\n" " -1 Show information about most recent entry only\n" " -F --field=FIELD List all values a certain field takes\n" " -o --output=FILE Write output to FILE\n\n" " -D --directory=DIR Use journal files from directory\n\n" "Commands:\n" " list [MATCHES...] List available coredumps (default)\n" " info [MATCHES...] Show detailed information about one or more coredumps\n" " dump [MATCHES...] Print first matching coredump to stdout\n" " gdb [MATCHES...] Start gdb for the first matching coredump\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[], Set *matches) { enum { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_LEGEND, }; int r, c; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version" , no_argument, NULL, ARG_VERSION }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, { "output", required_argument, NULL, 'o' }, { "field", required_argument, NULL, 'F' }, { "directory", required_argument, NULL, 'D' }, {} }; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "ho:F:1D:", options, NULL)) >= 0) switch(c) { case 'h': arg_action = ACTION_NONE; help(); return 0; case ARG_VERSION: arg_action = ACTION_NONE; return version(); case ARG_NO_PAGER: arg_no_pager = true; break; case ARG_NO_LEGEND: arg_no_legend = true; break; case 'o': if (arg_output) { log_error("cannot set output more than once"); return -EINVAL; } arg_output = fopen(optarg, "we"); if (!arg_output) return log_error_errno(errno, "writing to '%s': %m", optarg); break; case 'F': if (arg_field) { log_error("cannot use --field/-F more than once"); return -EINVAL; } arg_field = optarg; break; case '1': arg_one = true; break; case 'D': arg_directory = optarg; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (optind < argc) { const char *cmd = argv[optind++]; if (streq(cmd, "list")) arg_action = ACTION_LIST; else if (streq(cmd, "dump")) arg_action = ACTION_DUMP; else if (streq(cmd, "gdb")) arg_action = ACTION_GDB; else if (streq(cmd, "info")) arg_action = ACTION_INFO; else { log_error("Unknown action '%s'", cmd); return -EINVAL; } } if (arg_field && arg_action != ACTION_LIST) { log_error("Option --field/-F only makes sense with list"); return -EINVAL; } while (optind < argc) { r = add_match(matches, argv[optind]); if (r != 0) return r; optind++; } return 0; } static int retrieve(const void *data, size_t len, const char *name, char **var) { size_t ident; char *v; ident = strlen(name) + 1; /* name + "=" */ if (len < ident) return 0; if (memcmp(data, name, ident - 1) != 0) return 0; if (((const char*) data)[ident - 1] != '=') return 0; v = strndup((const char*)data + ident, len - ident); if (!v) return log_oom(); free(*var); *var = v; return 0; } static void print_field(FILE* file, sd_journal *j) { _cleanup_free_ char *value = NULL; const void *d; size_t l; assert(file); assert(j); assert(arg_field); SD_JOURNAL_FOREACH_DATA(j, d, l) retrieve(d, l, arg_field, &value); if (value) fprintf(file, "%s\n", value); } static int print_list(FILE* file, sd_journal *j, int had_legend) { _cleanup_free_ char *pid = NULL, *uid = NULL, *gid = NULL, *sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL, *filename = NULL; const void *d; size_t l; usec_t t; char buf[FORMAT_TIMESTAMP_MAX]; int r; bool present; assert(file); assert(j); SD_JOURNAL_FOREACH_DATA(j, d, l) { retrieve(d, l, "COREDUMP_PID", &pid); retrieve(d, l, "COREDUMP_UID", &uid); retrieve(d, l, "COREDUMP_GID", &gid); retrieve(d, l, "COREDUMP_SIGNAL", &sgnl); retrieve(d, l, "COREDUMP_EXE", &exe); retrieve(d, l, "COREDUMP_COMM", &comm); retrieve(d, l, "COREDUMP_CMDLINE", &cmdline); retrieve(d, l, "COREDUMP_FILENAME", &filename); } if (!pid && !uid && !gid && !sgnl && !exe && !comm && !cmdline && !filename) { log_warning("Empty coredump log entry"); return -EINVAL; } r = sd_journal_get_realtime_usec(j, &t); if (r < 0) return log_error_errno(r, "Failed to get realtime timestamp: %m"); format_timestamp(buf, sizeof(buf), t); present = filename && access(filename, F_OK) == 0; if (!had_legend && !arg_no_legend) fprintf(file, "%-*s %*s %*s %*s %*s %*s %s\n", FORMAT_TIMESTAMP_WIDTH, "TIME", 6, "PID", 5, "UID", 5, "GID", 3, "SIG", 1, "PRESENT", "EXE"); fprintf(file, "%-*s %*s %*s %*s %*s %*s %s\n", FORMAT_TIMESTAMP_WIDTH, buf, 6, strna(pid), 5, strna(uid), 5, strna(gid), 3, strna(sgnl), 1, present ? "*" : "", strna(exe ?: (comm ?: cmdline))); return 0; } static int print_info(FILE *file, sd_journal *j, bool need_space) { _cleanup_free_ char *pid = NULL, *uid = NULL, *gid = NULL, *sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL, *unit = NULL, *user_unit = NULL, *session = NULL, *boot_id = NULL, *machine_id = NULL, *hostname = NULL, *slice = NULL, *cgroup = NULL, *owner_uid = NULL, *message = NULL, *timestamp = NULL, *filename = NULL; const void *d; size_t l; int r; assert(file); assert(j); SD_JOURNAL_FOREACH_DATA(j, d, l) { retrieve(d, l, "COREDUMP_PID", &pid); retrieve(d, l, "COREDUMP_UID", &uid); retrieve(d, l, "COREDUMP_GID", &gid); retrieve(d, l, "COREDUMP_SIGNAL", &sgnl); retrieve(d, l, "COREDUMP_EXE", &exe); retrieve(d, l, "COREDUMP_COMM", &comm); retrieve(d, l, "COREDUMP_CMDLINE", &cmdline); retrieve(d, l, "COREDUMP_UNIT", &unit); retrieve(d, l, "COREDUMP_USER_UNIT", &user_unit); retrieve(d, l, "COREDUMP_SESSION", &session); retrieve(d, l, "COREDUMP_OWNER_UID", &owner_uid); retrieve(d, l, "COREDUMP_SLICE", &slice); retrieve(d, l, "COREDUMP_CGROUP", &cgroup); retrieve(d, l, "COREDUMP_TIMESTAMP", ×tamp); retrieve(d, l, "COREDUMP_FILENAME", &filename); retrieve(d, l, "_BOOT_ID", &boot_id); retrieve(d, l, "_MACHINE_ID", &machine_id); retrieve(d, l, "_HOSTNAME", &hostname); retrieve(d, l, "MESSAGE", &message); } if (need_space) fputs("\n", file); if (comm) fprintf(file, " PID: %s%s%s (%s)\n", ansi_highlight(), strna(pid), ansi_normal(), comm); else fprintf(file, " PID: %s%s%s\n", ansi_highlight(), strna(pid), ansi_normal()); if (uid) { uid_t n; if (parse_uid(uid, &n) >= 0) { _cleanup_free_ char *u = NULL; u = uid_to_name(n); fprintf(file, " UID: %s (%s)\n", uid, u); } else { fprintf(file, " UID: %s\n", uid); } } if (gid) { gid_t n; if (parse_gid(gid, &n) >= 0) { _cleanup_free_ char *g = NULL; g = gid_to_name(n); fprintf(file, " GID: %s (%s)\n", gid, g); } else { fprintf(file, " GID: %s\n", gid); } } if (sgnl) { int sig; if (safe_atoi(sgnl, &sig) >= 0) fprintf(file, " Signal: %s (%s)\n", sgnl, signal_to_string(sig)); else fprintf(file, " Signal: %s\n", sgnl); } if (timestamp) { usec_t u; r = safe_atou64(timestamp, &u); if (r >= 0) { char absolute[FORMAT_TIMESTAMP_MAX], relative[FORMAT_TIMESPAN_MAX]; fprintf(file, " Timestamp: %s (%s)\n", format_timestamp(absolute, sizeof(absolute), u), format_timestamp_relative(relative, sizeof(relative), u)); } else fprintf(file, " Timestamp: %s\n", timestamp); } if (cmdline) fprintf(file, " Command Line: %s\n", cmdline); if (exe) fprintf(file, " Executable: %s%s%s\n", ansi_highlight(), exe, ansi_normal()); if (cgroup) fprintf(file, " Control Group: %s\n", cgroup); if (unit) fprintf(file, " Unit: %s\n", unit); if (user_unit) fprintf(file, " User Unit: %s\n", unit); if (slice) fprintf(file, " Slice: %s\n", slice); if (session) fprintf(file, " Session: %s\n", session); if (owner_uid) { uid_t n; if (parse_uid(owner_uid, &n) >= 0) { _cleanup_free_ char *u = NULL; u = uid_to_name(n); fprintf(file, " Owner UID: %s (%s)\n", owner_uid, u); } else { fprintf(file, " Owner UID: %s\n", owner_uid); } } if (boot_id) fprintf(file, " Boot ID: %s\n", boot_id); if (machine_id) fprintf(file, " Machine ID: %s\n", machine_id); if (hostname) fprintf(file, " Hostname: %s\n", hostname); if (filename && access(filename, F_OK) == 0) fprintf(file, " Coredump: %s\n", filename); if (message) { _cleanup_free_ char *m = NULL; m = strreplace(message, "\n", "\n "); fprintf(file, " Message: %s\n", strstrip(m ?: message)); } return 0; } static int focus(sd_journal *j) { int r; r = sd_journal_seek_tail(j); if (r == 0) r = sd_journal_previous(j); if (r < 0) return log_error_errno(r, "Failed to search journal: %m"); if (r == 0) { log_error("No match found."); return -ESRCH; } return r; } static void print_entry(sd_journal *j, unsigned n_found) { assert(j); if (arg_action == ACTION_INFO) print_info(stdout, j, n_found); else if (arg_field) print_field(stdout, j); else print_list(stdout, j, n_found); } static int dump_list(sd_journal *j) { unsigned n_found = 0; int r; assert(j); /* The coredumps are likely to compressed, and for just * listing them we don't need to decompress them, so let's * pick a fairly low data threshold here */ sd_journal_set_data_threshold(j, 4096); if (arg_one) { r = focus(j); if (r < 0) return r; print_entry(j, 0); } else { SD_JOURNAL_FOREACH(j) print_entry(j, n_found++); if (!arg_field && n_found <= 0) { log_notice("No coredumps found."); return -ESRCH; } } return 0; } static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { const char *data; _cleanup_free_ char *filename = NULL; size_t len; int r; assert((fd >= 0) != !!path); assert(!!path == !!unlink_temp); /* Prefer uncompressed file to journal (probably cached) to * compressed file (probably uncached). */ r = sd_journal_get_data(j, "COREDUMP_FILENAME", (const void**) &data, &len); if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to retrieve COREDUMP_FILENAME: %m"); else if (r == 0) retrieve(data, len, "COREDUMP_FILENAME", &filename); if (filename && access(filename, R_OK) < 0) { log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, "File %s is not readable: %m", filename); filename = mfree(filename); } if (filename && !endswith(filename, ".xz") && !endswith(filename, ".lz4")) { if (path) { *path = filename; filename = NULL; } return 0; } else { _cleanup_close_ int fdt = -1; char *temp = NULL; if (fd < 0) { temp = strdup("/var/tmp/coredump-XXXXXX"); if (!temp) return log_oom(); fdt = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC); if (fdt < 0) return log_error_errno(fdt, "Failed to create temporary file: %m"); log_debug("Created temporary file %s", temp); fd = fdt; } r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len); if (r == 0) { ssize_t sz; assert(len >= 9); data += 9; len -= 9; sz = write(fdt, data, len); if (sz < 0) { r = log_error_errno(errno, "Failed to write temporary file: %m"); goto error; } if (sz != (ssize_t) len) { log_error("Short write to temporary file."); r = -EIO; goto error; } } else if (filename) { #if defined(HAVE_XZ) || defined(HAVE_LZ4) _cleanup_close_ int fdf; fdf = open(filename, O_RDONLY | O_CLOEXEC); if (fdf < 0) { r = log_error_errno(errno, "Failed to open %s: %m", filename); goto error; } r = decompress_stream(filename, fdf, fd, -1); if (r < 0) { log_error_errno(r, "Failed to decompress %s: %m", filename); goto error; } #else log_error("Cannot decompress file. Compiled without compression support."); r = -EOPNOTSUPP; goto error; #endif } else { if (r == -ENOENT) log_error("Cannot retrieve coredump from journal nor disk."); else log_error_errno(r, "Failed to retrieve COREDUMP field: %m"); goto error; } if (temp) { *path = temp; *unlink_temp = true; } return 0; error: if (temp) { unlink(temp); log_debug("Removed temporary file %s", temp); } return r; } } static int dump_core(sd_journal* j) { int r; assert(j); r = focus(j); if (r < 0) return r; print_info(arg_output ? stdout : stderr, j, false); if (on_tty() && !arg_output) { log_error("Refusing to dump core to tty."); return -ENOTTY; } r = save_core(j, arg_output ? fileno(arg_output) : STDOUT_FILENO, NULL, NULL); if (r < 0) return log_error_errno(r, "Coredump retrieval failed: %m"); r = sd_journal_previous(j); if (r >= 0) log_warning("More than one entry matches, ignoring rest."); return 0; } static int run_gdb(sd_journal *j) { _cleanup_free_ char *exe = NULL, *path = NULL; bool unlink_path = false; const char *data; siginfo_t st; size_t len; pid_t pid; int r; assert(j); r = focus(j); if (r < 0) return r; print_info(stdout, j, false); fputs("\n", stdout); r = sd_journal_get_data(j, "COREDUMP_EXE", (const void**) &data, &len); if (r < 0) return log_error_errno(r, "Failed to retrieve COREDUMP_EXE field: %m"); assert(len > strlen("COREDUMP_EXE=")); data += strlen("COREDUMP_EXE="); len -= strlen("COREDUMP_EXE="); exe = strndup(data, len); if (!exe) return log_oom(); if (endswith(exe, " (deleted)")) { log_error("Binary already deleted."); return -ENOENT; } if (!path_is_absolute(exe)) { log_error("Binary is not an absolute path."); return -ENOENT; } r = save_core(j, -1, &path, &unlink_path); if (r < 0) return log_error_errno(r, "Failed to retrieve core: %m"); pid = fork(); if (pid < 0) { r = log_error_errno(errno, "Failed to fork(): %m"); goto finish; } if (pid == 0) { (void) reset_all_signal_handlers(); (void) reset_signal_mask(); execlp("gdb", "gdb", exe, path, NULL); log_error_errno(errno, "Failed to invoke gdb: %m"); _exit(1); } r = wait_for_terminate(pid, &st); if (r < 0) { log_error_errno(r, "Failed to wait for gdb: %m"); goto finish; } r = st.si_code == CLD_EXITED ? st.si_status : 255; finish: if (unlink_path) { log_debug("Removed temporary file %s", path); unlink(path); } return r; } int main(int argc, char *argv[]) { _cleanup_(sd_journal_closep) sd_journal*j = NULL; const char* match; Iterator it; int r = 0; _cleanup_set_free_free_ Set *matches = NULL; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); matches = new_matches(); if (!matches) { r = -ENOMEM; goto end; } r = parse_argv(argc, argv, matches); if (r < 0) goto end; if (arg_action == ACTION_NONE) goto end; sigbus_install(); if (arg_directory) { r = sd_journal_open_directory(&j, arg_directory, 0); if (r < 0) { log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory); goto end; } } else { r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); if (r < 0) { log_error_errno(r, "Failed to open journal: %m"); goto end; } } /* We want full data, nothing truncated. */ sd_journal_set_data_threshold(j, 0); SET_FOREACH(match, matches, it) { r = sd_journal_add_match(j, match, strlen(match)); if (r != 0) { log_error_errno(r, "Failed to add match '%s': %m", match); goto end; } } if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) { _cleanup_free_ char *filter; filter = journal_make_match_string(j); log_debug("Journal filter: %s", filter); } switch(arg_action) { case ACTION_LIST: case ACTION_INFO: if (!arg_no_pager) pager_open(false); r = dump_list(j); break; case ACTION_DUMP: r = dump_core(j); break; case ACTION_GDB: r = run_gdb(j); break; default: assert_not_reached("Shouldn't be here"); } end: pager_close(); if (arg_output) fclose(arg_output); return r >= 0 ? r : EXIT_FAILURE; } systemd-229/src/coredump/stacktrace.c000066400000000000000000000130101265713322000177510ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "macro.h" #include "stacktrace.h" #include "string-util.h" #include "util.h" #define FRAMES_MAX 64 #define THREADS_MAX 64 struct stack_context { FILE *f; Dwfl *dwfl; Elf *elf; unsigned n_thread; unsigned n_frame; }; static int frame_callback(Dwfl_Frame *frame, void *userdata) { struct stack_context *c = userdata; Dwarf_Addr pc, pc_adjusted, bias = 0; _cleanup_free_ Dwarf_Die *scopes = NULL; const char *fname = NULL, *symbol = NULL; Dwfl_Module *module; bool is_activation; assert(frame); assert(c); if (c->n_frame >= FRAMES_MAX) return DWARF_CB_ABORT; if (!dwfl_frame_pc(frame, &pc, &is_activation)) return DWARF_CB_ABORT; pc_adjusted = pc - (is_activation ? 0 : 1); module = dwfl_addrmodule(c->dwfl, pc_adjusted); if (module) { Dwarf_Die *s, *cudie; int n; cudie = dwfl_module_addrdie(module, pc_adjusted, &bias); if (cudie) { n = dwarf_getscopes(cudie, pc_adjusted - bias, &scopes); for (s = scopes; s < scopes + n; s++) { if (IN_SET(dwarf_tag(s), DW_TAG_subprogram, DW_TAG_inlined_subroutine, DW_TAG_entry_point)) { Dwarf_Attribute *a, space; a = dwarf_attr_integrate(s, DW_AT_MIPS_linkage_name, &space); if (!a) a = dwarf_attr_integrate(s, DW_AT_linkage_name, &space); if (a) symbol = dwarf_formstring(a); if (!symbol) symbol = dwarf_diename(s); if (symbol) break; } } } if (!symbol) symbol = dwfl_module_addrname(module, pc_adjusted); fname = dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } fprintf(c->f, "#%-2u 0x%016" PRIx64 " %s (%s)\n", c->n_frame, (uint64_t) pc, strna(symbol), strna(fname)); c->n_frame ++; return DWARF_CB_OK; } static int thread_callback(Dwfl_Thread *thread, void *userdata) { struct stack_context *c = userdata; pid_t tid; assert(thread); assert(c); if (c->n_thread >= THREADS_MAX) return DWARF_CB_ABORT; if (c->n_thread != 0) fputc('\n', c->f); c->n_frame = 0; tid = dwfl_thread_tid(thread); fprintf(c->f, "Stack trace of thread " PID_FMT ":\n", tid); if (dwfl_thread_getframes(thread, frame_callback, c) < 0) return DWARF_CB_ABORT; c->n_thread ++; return DWARF_CB_OK; } int coredump_make_stack_trace(int fd, const char *executable, char **ret) { static const Dwfl_Callbacks callbacks = { .find_elf = dwfl_build_id_find_elf, .find_debuginfo = dwfl_standard_find_debuginfo, }; struct stack_context c = {}; char *buf = NULL; size_t sz = 0; int r; assert(fd >= 0); assert(ret); if (lseek(fd, 0, SEEK_SET) == (off_t) -1) return -errno; c.f = open_memstream(&buf, &sz); if (!c.f) return -ENOMEM; elf_version(EV_CURRENT); c.elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); if (!c.elf) { r = -EINVAL; goto finish; } c.dwfl = dwfl_begin(&callbacks); if (!c.dwfl) { r = -EINVAL; goto finish; } if (dwfl_core_file_report(c.dwfl, c.elf, executable) < 0) { r = -EINVAL; goto finish; } if (dwfl_report_end(c.dwfl, NULL, NULL) != 0) { r = -EINVAL; goto finish; } if (dwfl_core_file_attach(c.dwfl, c.elf) < 0) { r = -EINVAL; goto finish; } if (dwfl_getthreads(c.dwfl, thread_callback, &c) < 0) { r = -EINVAL; goto finish; } c.f = safe_fclose(c.f); *ret = buf; buf = NULL; r = 0; finish: if (c.dwfl) dwfl_end(c.dwfl); if (c.elf) elf_end(c.elf); safe_fclose(c.f); free(buf); return r; } systemd-229/src/coredump/stacktrace.h000066400000000000000000000014501265713322000177630ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int coredump_make_stack_trace(int fd, const char *executable, char **ret); systemd-229/src/coredump/test-coredump-vacuum.c000066400000000000000000000016641265713322000217320ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "coredump-vacuum.h" int main(int argc, char *argv[]) { if (coredump_vacuum(-1, (uint64_t) -1, 70 * 1024) < 0) return EXIT_FAILURE; return EXIT_SUCCESS; } systemd-229/src/cryptsetup/000077500000000000000000000000001265713322000160725ustar00rootroot00000000000000systemd-229/src/cryptsetup/Makefile000077700000000000000000000000001265713322000214002../Makefileustar00rootroot00000000000000systemd-229/src/cryptsetup/cryptsetup-generator.c000066400000000000000000000400371265713322000224500ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "dropin.h" #include "fd-util.h" #include "fileio.h" #include "fstab-util.h" #include "generator.h" #include "hashmap.h" #include "log.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "util.h" typedef struct crypto_device { char *uuid; char *keyfile; char *name; char *options; bool create; } crypto_device; static const char *arg_dest = "/tmp"; static bool arg_enabled = true; static bool arg_read_crypttab = true; static bool arg_whitelist = false; static Hashmap *arg_disks = NULL; static char *arg_default_options = NULL; static char *arg_default_keyfile = NULL; static int create_disk( const char *name, const char *device, const char *password, const char *options) { _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *to = NULL, *e = NULL, *filtered = NULL; _cleanup_fclose_ FILE *f = NULL; bool noauto, nofail, tmp, swap; char *from; int r; assert(name); assert(device); noauto = fstab_test_yes_no_option(options, "noauto\0" "auto\0"); nofail = fstab_test_yes_no_option(options, "nofail\0" "fail\0"); tmp = fstab_test_option(options, "tmp\0"); swap = fstab_test_option(options, "swap\0"); if (tmp && swap) { log_error("Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", name); return -EINVAL; } e = unit_name_escape(name); if (!e) return log_oom(); r = unit_name_build("systemd-cryptsetup", e, ".service", &n); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); p = strjoin(arg_dest, "/", n, NULL); if (!p) return log_oom(); u = fstab_node_to_udev_node(device); if (!u) return log_oom(); r = unit_name_from_path(u, ".device", &d); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); f = fopen(p, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", p); fputs( "# Automatically generated by systemd-cryptsetup-generator\n\n" "[Unit]\n" "Description=Cryptography Setup for %I\n" "Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n" "SourcePath=/etc/crypttab\n" "DefaultDependencies=no\n" "Conflicts=umount.target\n" "BindsTo=dev-mapper-%i.device\n" "IgnoreOnIsolate=true\n" "After=cryptsetup-pre.target\n", f); if (!nofail) fprintf(f, "Before=cryptsetup.target\n"); if (password) { if (STR_IN_SET(password, "/dev/urandom", "/dev/random", "/dev/hw_random")) fputs("After=systemd-random-seed.service\n", f); else if (!streq(password, "-") && !streq(password, "none")) { _cleanup_free_ char *uu; uu = fstab_node_to_udev_node(password); if (!uu) return log_oom(); if (!path_equal(uu, "/dev/null")) { if (is_device_path(uu)) { _cleanup_free_ char *dd = NULL; r = unit_name_from_path(uu, ".device", &dd); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); fprintf(f, "After=%1$s\nRequires=%1$s\n", dd); } else fprintf(f, "RequiresMountsFor=%s\n", password); } } } if (is_device_path(u)) fprintf(f, "BindsTo=%s\n" "After=%s\n" "Before=umount.target\n", d, d); else fprintf(f, "RequiresMountsFor=%s\n", u); r = generator_write_timeouts(arg_dest, device, name, options, &filtered); if (r < 0) return r; fprintf(f, "\n[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" "TimeoutSec=0\n" /* the binary handles timeouts anyway */ "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n" "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n", name, u, strempty(password), strempty(filtered), name); if (tmp) fprintf(f, "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n", name); if (swap) fprintf(f, "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n", name); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write file %s: %m", p); from = strjoina("../", n); if (!noauto) { to = strjoin(arg_dest, "/", d, ".wants/", n, NULL); if (!to) return log_oom(); mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); free(to); if (!nofail) to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL); else to = strjoin(arg_dest, "/cryptsetup.target.wants/", n, NULL); if (!to) return log_oom(); mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); } free(to); to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL); if (!to) return log_oom(); mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); if (!noauto && !nofail) { _cleanup_free_ char *dmname; dmname = strjoin("dev-mapper-", e, ".device", NULL); if (!dmname) return log_oom(); r = write_drop_in(arg_dest, dmname, 90, "device-timeout", "# Automatically generated by systemd-cryptsetup-generator \n\n" "[Unit]\nJobTimeoutSec=0"); if (r < 0) return log_error_errno(r, "Failed to write device drop-in: %m"); } return 0; } static void free_arg_disks(void) { crypto_device *d; while ((d = hashmap_steal_first(arg_disks))) { free(d->uuid); free(d->keyfile); free(d->name); free(d->options); free(d); } hashmap_free(arg_disks); } static crypto_device *get_crypto_device(const char *uuid) { int r; crypto_device *d; assert(uuid); d = hashmap_get(arg_disks, uuid); if (!d) { d = new0(struct crypto_device, 1); if (!d) return NULL; d->create = false; d->keyfile = d->options = d->name = NULL; d->uuid = strdup(uuid); if (!d->uuid) { free(d); return NULL; } r = hashmap_put(arg_disks, d->uuid, d); if (r < 0) { free(d->uuid); free(d); return NULL; } } return d; } static int parse_proc_cmdline_item(const char *key, const char *value) { int r; crypto_device *d; _cleanup_free_ char *uuid = NULL, *uuid_value = NULL; if (STR_IN_SET(key, "luks", "rd.luks") && value) { r = parse_boolean(value); if (r < 0) log_warning("Failed to parse luks switch %s. Ignoring.", value); else arg_enabled = r; } else if (STR_IN_SET(key, "luks.crypttab", "rd.luks.crypttab") && value) { r = parse_boolean(value); if (r < 0) log_warning("Failed to parse luks crypttab switch %s. Ignoring.", value); else arg_read_crypttab = r; } else if (STR_IN_SET(key, "luks.uuid", "rd.luks.uuid") && value) { d = get_crypto_device(startswith(value, "luks-") ? value+5 : value); if (!d) return log_oom(); d->create = arg_whitelist = true; } else if (STR_IN_SET(key, "luks.options", "rd.luks.options") && value) { r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); if (r == 2) { d = get_crypto_device(uuid); if (!d) return log_oom(); free(d->options); d->options = uuid_value; uuid_value = NULL; } else if (free_and_strdup(&arg_default_options, value) < 0) return log_oom(); } else if (STR_IN_SET(key, "luks.key", "rd.luks.key") && value) { r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); if (r == 2) { d = get_crypto_device(uuid); if (!d) return log_oom(); free(d->keyfile); d->keyfile = uuid_value; uuid_value = NULL; } else if (free_and_strdup(&arg_default_keyfile, value) < 0) return log_oom(); } else if (STR_IN_SET(key, "luks.name", "rd.luks.name") && value) { r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); if (r == 2) { d = get_crypto_device(uuid); if (!d) return log_oom(); d->create = arg_whitelist = true; free(d->name); d->name = uuid_value; uuid_value = NULL; } else log_warning("Failed to parse luks name switch %s. Ignoring.", value); } return 0; } static int add_crypttab_devices(void) { struct stat st; unsigned crypttab_line = 0; _cleanup_fclose_ FILE *f = NULL; if (!arg_read_crypttab) return 0; f = fopen("/etc/crypttab", "re"); if (!f) { if (errno != ENOENT) log_error_errno(errno, "Failed to open /etc/crypttab: %m"); return 0; } if (fstat(fileno(f), &st) < 0) { log_error_errno(errno, "Failed to stat /etc/crypttab: %m"); return 0; } for (;;) { int r, k; char line[LINE_MAX], *l, *uuid; crypto_device *d = NULL; _cleanup_free_ char *name = NULL, *device = NULL, *keyfile = NULL, *options = NULL; if (!fgets(line, sizeof(line), f)) break; crypttab_line++; l = strstrip(line); if (*l == '#' || *l == 0) continue; k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &keyfile, &options); if (k < 2 || k > 4) { log_error("Failed to parse /etc/crypttab:%u, ignoring.", crypttab_line); continue; } uuid = startswith(device, "UUID="); if (!uuid) uuid = path_startswith(device, "/dev/disk/by-uuid/"); if (!uuid) uuid = startswith(name, "luks-"); if (uuid) d = hashmap_get(arg_disks, uuid); if (arg_whitelist && !d) { log_info("Not creating device '%s' because it was not specified on the kernel command line.", name); continue; } r = create_disk(name, device, keyfile, (d && d->options) ? d->options : options); if (r < 0) return r; if (d) d->create = false; } return 0; } static int add_proc_cmdline_devices(void) { int r; Iterator i; crypto_device *d; HASHMAP_FOREACH(d, arg_disks, i) { const char *options; _cleanup_free_ char *device = NULL; if (!d->create) continue; if (!d->name) { d->name = strappend("luks-", d->uuid); if (!d->name) return log_oom(); } device = strappend("UUID=", d->uuid); if (!device) return log_oom(); if (d->options) options = d->options; else if (arg_default_options) options = arg_default_options; else options = "timeout=0"; r = create_disk(d->name, device, d->keyfile ?: arg_default_keyfile, options); if (r < 0) return r; } return 0; } int main(int argc, char *argv[]) { int r = EXIT_FAILURE; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); return EXIT_FAILURE; } if (argc > 1) arg_dest = argv[1]; log_set_target(LOG_TARGET_SAFE); log_parse_environment(); log_open(); umask(0022); arg_disks = hashmap_new(&string_hash_ops); if (!arg_disks) goto cleanup; r = parse_proc_cmdline(parse_proc_cmdline_item); if (r < 0) { log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); r = EXIT_FAILURE; } if (!arg_enabled) { r = EXIT_SUCCESS; goto cleanup; } if (add_crypttab_devices() < 0) goto cleanup; if (add_proc_cmdline_devices() < 0) goto cleanup; r = EXIT_SUCCESS; cleanup: free_arg_disks(); free(arg_default_options); free(arg_default_keyfile); return r; } systemd-229/src/cryptsetup/cryptsetup.c000066400000000000000000000610611265713322000204640ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-device.h" #include "alloc-util.h" #include "ask-password-api.h" #include "device-util.h" #include "escape.h" #include "fileio.h" #include "log.h" #include "mount-util.h" #include "parse-util.h" #include "path-util.h" #include "string-util.h" #include "strv.h" #include "util.h" static const char *arg_type = NULL; /* CRYPT_LUKS1, CRYPT_TCRYPT or CRYPT_PLAIN */ static char *arg_cipher = NULL; static unsigned arg_key_size = 0; static int arg_key_slot = CRYPT_ANY_SLOT; static unsigned arg_keyfile_size = 0; static unsigned arg_keyfile_offset = 0; static char *arg_hash = NULL; static char *arg_header = NULL; static unsigned arg_tries = 3; static bool arg_readonly = false; static bool arg_verify = false; static bool arg_discards = false; static bool arg_tcrypt_hidden = false; static bool arg_tcrypt_system = false; static char **arg_tcrypt_keyfiles = NULL; static uint64_t arg_offset = 0; static uint64_t arg_skip = 0; static usec_t arg_timeout = 0; /* Options Debian's crypttab knows we don't: precheck= check= checkargs= noearly= loud= keyscript= */ static int parse_one_option(const char *option) { assert(option); /* Handled outside of this tool */ if (STR_IN_SET(option, "noauto", "auto", "nofail", "fail")) return 0; if (startswith(option, "cipher=")) { char *t; t = strdup(option+7); if (!t) return log_oom(); free(arg_cipher); arg_cipher = t; } else if (startswith(option, "size=")) { if (safe_atou(option+5, &arg_key_size) < 0) { log_error("size= parse failure, ignoring."); return 0; } if (arg_key_size % 8) { log_error("size= not a multiple of 8, ignoring."); return 0; } arg_key_size /= 8; } else if (startswith(option, "key-slot=")) { arg_type = CRYPT_LUKS1; if (safe_atoi(option+9, &arg_key_slot) < 0) { log_error("key-slot= parse failure, ignoring."); return 0; } } else if (startswith(option, "tcrypt-keyfile=")) { arg_type = CRYPT_TCRYPT; if (path_is_absolute(option+15)) { if (strv_extend(&arg_tcrypt_keyfiles, option + 15) < 0) return log_oom(); } else log_error("Key file path '%s' is not absolute. Ignoring.", option+15); } else if (startswith(option, "keyfile-size=")) { if (safe_atou(option+13, &arg_keyfile_size) < 0) { log_error("keyfile-size= parse failure, ignoring."); return 0; } } else if (startswith(option, "keyfile-offset=")) { if (safe_atou(option+15, &arg_keyfile_offset) < 0) { log_error("keyfile-offset= parse failure, ignoring."); return 0; } } else if (startswith(option, "hash=")) { char *t; t = strdup(option+5); if (!t) return log_oom(); free(arg_hash); arg_hash = t; } else if (startswith(option, "header=")) { arg_type = CRYPT_LUKS1; if (!path_is_absolute(option+7)) { log_error("Header path '%s' is not absolute, refusing.", option+7); return -EINVAL; } if (arg_header) { log_error("Duplicate header= options, refusing."); return -EINVAL; } arg_header = strdup(option+7); if (!arg_header) return log_oom(); } else if (startswith(option, "tries=")) { if (safe_atou(option+6, &arg_tries) < 0) { log_error("tries= parse failure, ignoring."); return 0; } } else if (STR_IN_SET(option, "readonly", "read-only")) arg_readonly = true; else if (streq(option, "verify")) arg_verify = true; else if (STR_IN_SET(option, "allow-discards", "discard")) arg_discards = true; else if (streq(option, "luks")) arg_type = CRYPT_LUKS1; else if (streq(option, "tcrypt")) arg_type = CRYPT_TCRYPT; else if (streq(option, "tcrypt-hidden")) { arg_type = CRYPT_TCRYPT; arg_tcrypt_hidden = true; } else if (streq(option, "tcrypt-system")) { arg_type = CRYPT_TCRYPT; arg_tcrypt_system = true; } else if (STR_IN_SET(option, "plain", "swap", "tmp")) arg_type = CRYPT_PLAIN; else if (startswith(option, "timeout=")) { if (parse_sec(option+8, &arg_timeout) < 0) { log_error("timeout= parse failure, ignoring."); return 0; } } else if (startswith(option, "offset=")) { if (safe_atou64(option+7, &arg_offset) < 0) { log_error("offset= parse failure, refusing."); return -EINVAL; } } else if (startswith(option, "skip=")) { if (safe_atou64(option+5, &arg_skip) < 0) { log_error("skip= parse failure, refusing."); return -EINVAL; } } else if (!streq(option, "none")) log_error("Encountered unknown /etc/crypttab option '%s', ignoring.", option); return 0; } static int parse_options(const char *options) { const char *word, *state; size_t l; int r; assert(options); FOREACH_WORD_SEPARATOR(word, l, options, ",", state) { _cleanup_free_ char *o; o = strndup(word, l); if (!o) return -ENOMEM; r = parse_one_option(o); if (r < 0) return r; } /* sanity-check options */ if (arg_type != NULL && !streq(arg_type, CRYPT_PLAIN)) { if (arg_offset) log_warning("offset= ignored with type %s", arg_type); if (arg_skip) log_warning("skip= ignored with type %s", arg_type); } return 0; } static void log_glue(int level, const char *msg, void *usrptr) { log_debug("%s", msg); } static int disk_major_minor(const char *path, char **ret) { struct stat st; assert(path); if (stat(path, &st) < 0) return -errno; if (!S_ISBLK(st.st_mode)) return -EINVAL; if (asprintf(ret, "/dev/block/%d:%d", major(st.st_rdev), minor(st.st_rdev)) < 0) return -errno; return 0; } static char* disk_description(const char *path) { static const char name_fields[] = "ID_PART_ENTRY_NAME\0" "DM_NAME\0" "ID_MODEL_FROM_DATABASE\0" "ID_MODEL\0"; _cleanup_(sd_device_unrefp) sd_device *device = NULL; struct stat st; const char *i; int r; assert(path); if (stat(path, &st) < 0) return NULL; if (!S_ISBLK(st.st_mode)) return NULL; r = sd_device_new_from_devnum(&device, 'b', st.st_rdev); if (r < 0) return NULL; NULSTR_FOREACH(i, name_fields) { const char *name; r = sd_device_get_property_value(device, i, &name); if (r >= 0 && !isempty(name)) return strdup(name); } return NULL; } static char *disk_mount_point(const char *label) { _cleanup_free_ char *device = NULL; _cleanup_endmntent_ FILE *f = NULL; struct mntent *m; /* Yeah, we don't support native systemd unit files here for now */ if (asprintf(&device, "/dev/mapper/%s", label) < 0) return NULL; f = setmntent("/etc/fstab", "r"); if (!f) return NULL; while ((m = getmntent(f))) if (path_equal(m->mnt_fsname, device)) return strdup(m->mnt_dir); return NULL; } static int get_password(const char *vol, const char *src, usec_t until, bool accept_cached, char ***ret) { _cleanup_free_ char *description = NULL, *name_buffer = NULL, *mount_point = NULL, *maj_min = NULL, *text = NULL, *escaped_name = NULL; _cleanup_strv_free_erase_ char **passwords = NULL; const char *name = NULL; char **p, *id; int r = 0; assert(vol); assert(src); assert(ret); description = disk_description(src); mount_point = disk_mount_point(vol); if (description && streq(vol, description)) /* If the description string is simply the * volume name, then let's not show this * twice */ description = mfree(description); if (mount_point && description) r = asprintf(&name_buffer, "%s (%s) on %s", description, vol, mount_point); else if (mount_point) r = asprintf(&name_buffer, "%s on %s", vol, mount_point); else if (description) r = asprintf(&name_buffer, "%s (%s)", description, vol); if (r < 0) return log_oom(); name = name_buffer ? name_buffer : vol; if (asprintf(&text, "Please enter passphrase for disk %s!", name) < 0) return log_oom(); if (src) (void) disk_major_minor(src, &maj_min); if (maj_min) { escaped_name = maj_min; maj_min = NULL; } else escaped_name = cescape(name); if (!escaped_name) return log_oom(); id = strjoina("cryptsetup:", escaped_name); r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", until, ASK_PASSWORD_PUSH_CACHE | (accept_cached*ASK_PASSWORD_ACCEPT_CACHED), &passwords); if (r < 0) return log_error_errno(r, "Failed to query password: %m"); if (arg_verify) { _cleanup_strv_free_erase_ char **passwords2 = NULL; assert(strv_length(passwords) == 1); if (asprintf(&text, "Please enter passphrase for disk %s! (verification)", name) < 0) return log_oom(); id = strjoina("cryptsetup-verification:", escaped_name); r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", until, ASK_PASSWORD_PUSH_CACHE, &passwords2); if (r < 0) return log_error_errno(r, "Failed to query verification password: %m"); assert(strv_length(passwords2) == 1); if (!streq(passwords[0], passwords2[0])) { log_warning("Passwords did not match, retrying."); return -EAGAIN; } } strv_uniq(passwords); STRV_FOREACH(p, passwords) { char *c; if (strlen(*p)+1 >= arg_key_size) continue; /* Pad password if necessary */ c = new(char, arg_key_size); if (!c) return log_oom(); strncpy(c, *p, arg_key_size); free(*p); *p = c; } *ret = passwords; passwords = NULL; return 0; } static int attach_tcrypt( struct crypt_device *cd, const char *name, const char *key_file, char **passwords, uint32_t flags) { int r = 0; _cleanup_free_ char *passphrase = NULL; struct crypt_params_tcrypt params = { .flags = CRYPT_TCRYPT_LEGACY_MODES, .keyfiles = (const char **)arg_tcrypt_keyfiles, .keyfiles_count = strv_length(arg_tcrypt_keyfiles) }; assert(cd); assert(name); assert(key_file || (passwords && passwords[0])); if (arg_tcrypt_hidden) params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER; if (arg_tcrypt_system) params.flags |= CRYPT_TCRYPT_SYSTEM_HEADER; if (key_file) { r = read_one_line_file(key_file, &passphrase); if (r < 0) { log_error_errno(r, "Failed to read password file '%s': %m", key_file); return -EAGAIN; } params.passphrase = passphrase; } else params.passphrase = passwords[0]; params.passphrase_size = strlen(params.passphrase); r = crypt_load(cd, CRYPT_TCRYPT, ¶ms); if (r < 0) { if (key_file && r == -EPERM) { log_error("Failed to activate using password file '%s'.", key_file); return -EAGAIN; } return r; } return crypt_activate_by_volume_key(cd, name, NULL, 0, flags); } static int attach_luks_or_plain(struct crypt_device *cd, const char *name, const char *key_file, const char *data_device, char **passwords, uint32_t flags) { int r = 0; bool pass_volume_key = false; assert(cd); assert(name); assert(key_file || passwords); if (!arg_type || streq(arg_type, CRYPT_LUKS1)) { r = crypt_load(cd, CRYPT_LUKS1, NULL); if (r < 0) { log_error("crypt_load() failed on device %s.\n", crypt_get_device_name(cd)); return r; } if (data_device) r = crypt_set_data_device(cd, data_device); } if ((!arg_type && r < 0) || streq_ptr(arg_type, CRYPT_PLAIN)) { struct crypt_params_plain params = { .offset = arg_offset, .skip = arg_skip, }; const char *cipher, *cipher_mode; _cleanup_free_ char *truncated_cipher = NULL; if (arg_hash) { /* plain isn't a real hash type. it just means "use no hash" */ if (!streq(arg_hash, "plain")) params.hash = arg_hash; } else if (!key_file) /* for CRYPT_PLAIN, the behaviour of cryptsetup * package is to not hash when a key file is provided */ params.hash = "ripemd160"; if (arg_cipher) { size_t l; l = strcspn(arg_cipher, "-"); truncated_cipher = strndup(arg_cipher, l); if (!truncated_cipher) return log_oom(); cipher = truncated_cipher; cipher_mode = arg_cipher[l] ? arg_cipher+l+1 : "plain"; } else { cipher = "aes"; cipher_mode = "cbc-essiv:sha256"; } /* for CRYPT_PLAIN limit reads * from keyfile to key length, and * ignore keyfile-size */ arg_keyfile_size = arg_key_size; /* In contrast to what the name * crypt_setup() might suggest this * doesn't actually format anything, * it just configures encryption * parameters when used for plain * mode. */ r = crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, arg_keyfile_size, ¶ms); /* hash == NULL implies the user passed "plain" */ pass_volume_key = (params.hash == NULL); } if (r < 0) return log_error_errno(r, "Loading of cryptographic parameters failed: %m"); log_info("Set cipher %s, mode %s, key size %i bits for device %s.", crypt_get_cipher(cd), crypt_get_cipher_mode(cd), crypt_get_volume_key_size(cd)*8, crypt_get_device_name(cd)); if (key_file) { r = crypt_activate_by_keyfile_offset(cd, name, arg_key_slot, key_file, arg_keyfile_size, arg_keyfile_offset, flags); if (r < 0) { log_error_errno(r, "Failed to activate with key file '%s': %m", key_file); return -EAGAIN; } } else { char **p; STRV_FOREACH(p, passwords) { if (pass_volume_key) r = crypt_activate_by_volume_key(cd, name, *p, arg_key_size, flags); else r = crypt_activate_by_passphrase(cd, name, arg_key_slot, *p, strlen(*p), flags); if (r >= 0) break; } } return r; } static int help(void) { printf("%s attach VOLUME SOURCEDEVICE [PASSWORD] [OPTIONS]\n" "%s detach VOLUME\n\n" "Attaches or detaches an encrypted block device.\n", program_invocation_short_name, program_invocation_short_name); return 0; } int main(int argc, char *argv[]) { int r = EXIT_FAILURE; struct crypt_device *cd = NULL; if (argc <= 1) { help(); return EXIT_SUCCESS; } if (argc < 3) { log_error("This program requires at least two arguments."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); if (streq(argv[1], "attach")) { uint32_t flags = 0; int k; unsigned tries; usec_t until; crypt_status_info status; const char *key_file = NULL; /* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */ if (argc < 4) { log_error("attach requires at least two arguments."); goto finish; } if (argc >= 5 && argv[4][0] && !streq(argv[4], "-") && !streq(argv[4], "none")) { if (!path_is_absolute(argv[4])) log_error("Password file path '%s' is not absolute. Ignoring.", argv[4]); else key_file = argv[4]; } if (argc >= 6 && argv[5][0] && !streq(argv[5], "-")) { if (parse_options(argv[5]) < 0) goto finish; } /* A delicious drop of snake oil */ mlockall(MCL_FUTURE); if (arg_header) { log_debug("LUKS header: %s", arg_header); k = crypt_init(&cd, arg_header); } else k = crypt_init(&cd, argv[3]); if (k) { log_error_errno(k, "crypt_init() failed: %m"); goto finish; } crypt_set_log_callback(cd, log_glue, NULL); status = crypt_status(cd, argv[2]); if (status == CRYPT_ACTIVE || status == CRYPT_BUSY) { log_info("Volume %s already active.", argv[2]); r = EXIT_SUCCESS; goto finish; } if (arg_readonly) flags |= CRYPT_ACTIVATE_READONLY; if (arg_discards) flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; if (arg_timeout > 0) until = now(CLOCK_MONOTONIC) + arg_timeout; else until = 0; arg_key_size = (arg_key_size > 0 ? arg_key_size : (256 / 8)); if (key_file) { struct stat st; /* Ideally we'd do this on the open fd, but since this is just a * warning it's OK to do this in two steps. */ if (stat(key_file, &st) >= 0 && S_ISREG(st.st_mode) && (st.st_mode & 0005)) log_warning("Key file %s is world-readable. This is not a good idea!", key_file); } for (tries = 0; arg_tries == 0 || tries < arg_tries; tries++) { _cleanup_strv_free_erase_ char **passwords = NULL; if (!key_file) { k = get_password(argv[2], argv[3], until, tries == 0 && !arg_verify, &passwords); if (k == -EAGAIN) continue; else if (k < 0) goto finish; } if (streq_ptr(arg_type, CRYPT_TCRYPT)) k = attach_tcrypt(cd, argv[2], key_file, passwords, flags); else k = attach_luks_or_plain(cd, argv[2], key_file, arg_header ? argv[3] : NULL, passwords, flags); if (k >= 0) break; else if (k == -EAGAIN) { key_file = NULL; continue; } else if (k != -EPERM) { log_error_errno(k, "Failed to activate: %m"); goto finish; } log_warning("Invalid passphrase."); } if (arg_tries != 0 && tries >= arg_tries) { log_error("Too many attempts; giving up."); r = EXIT_FAILURE; goto finish; } } else if (streq(argv[1], "detach")) { int k; k = crypt_init_by_name(&cd, argv[2]); if (k) { log_error_errno(k, "crypt_init() failed: %m"); goto finish; } crypt_set_log_callback(cd, log_glue, NULL); k = crypt_deactivate(cd, argv[2]); if (k < 0) { log_error_errno(k, "Failed to deactivate: %m"); goto finish; } } else { log_error("Unknown verb %s.", argv[1]); goto finish; } r = EXIT_SUCCESS; finish: if (cd) crypt_free(cd); free(arg_cipher); free(arg_hash); free(arg_header); strv_free(arg_tcrypt_keyfiles); return r; } systemd-229/src/dbus1-generator/000077500000000000000000000000001265713322000166525ustar00rootroot00000000000000systemd-229/src/dbus1-generator/Makefile000077700000000000000000000000001265713322000221602../Makefileustar00rootroot00000000000000systemd-229/src/dbus1-generator/dbus1-generator.c000066400000000000000000000250451265713322000220260ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-internal.h" #include "bus-util.h" #include "cgroup-util.h" #include "conf-parser.h" #include "dirent-util.h" #include "fd-util.h" #include "fileio.h" #include "mkdir.h" #include "special.h" #include "unit-name.h" #include "util.h" static const char *arg_dest_late = "/tmp", *arg_dest = "/tmp"; static int create_dbus_files( const char *path, const char *name, const char *service, const char *exec, const char *user, const char *type) { _cleanup_free_ char *b = NULL, *s = NULL, *lnk = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(path); assert(name); assert(service || exec); if (!service) { _cleanup_free_ char *a = NULL; s = strjoin("dbus-", name, ".service", NULL); if (!s) return log_oom(); a = strjoin(arg_dest_late, "/", s, NULL); if (!a) return log_oom(); f = fopen(a, "wxe"); if (!f) return log_error_errno(errno, "Failed to create %s: %m", a); fprintf(f, "# Automatically generated by systemd-dbus1-generator\n\n" "[Unit]\n" "SourcePath=%s\n" "Description=DBUS1: %s\n" "Documentation=man:systemd-dbus1-generator(8)\n\n" "[Service]\n" "ExecStart=%s\n" "Type=dbus\n" "BusName=%s\n", path, name, exec, name); if (user) fprintf(f, "User=%s\n", user); if (type) { fprintf(f, "Environment=DBUS_STARTER_BUS_TYPE=%s\n", type); if (streq(type, "system")) fprintf(f, "Environment=DBUS_STARTER_ADDRESS=" DEFAULT_SYSTEM_BUS_ADDRESS "\n"); else if (streq(type, "session")) { char *run; run = getenv("XDG_RUNTIME_DIR"); if (!run) { log_error("XDG_RUNTIME_DIR not set."); return -EINVAL; } fprintf(f, "Environment=DBUS_STARTER_ADDRESS="KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT "\n", getuid(), run); } } r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write %s: %m", a); f = safe_fclose(f); service = s; } b = strjoin(arg_dest_late, "/", name, ".busname", NULL); if (!b) return log_oom(); f = fopen(b, "wxe"); if (!f) return log_error_errno(errno, "Failed to create %s: %m", b); fprintf(f, "# Automatically generated by systemd-dbus1-generator\n\n" "[Unit]\n" "SourcePath=%s\n" "Description=DBUS1: %s\n" "Documentation=man:systemd-dbus1-generator(8)\n\n" "[BusName]\n" "Name=%s\n" "Service=%s\n" "AllowWorld=talk\n", path, name, name, service); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write %s: %m", b); lnk = strjoin(arg_dest_late, "/" SPECIAL_BUSNAMES_TARGET ".wants/", name, ".busname", NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(b, lnk)) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); return 0; } static int add_dbus(const char *path, const char *fname, const char *type) { _cleanup_free_ char *name = NULL, *exec = NULL, *user = NULL, *service = NULL; const ConfigTableItem table[] = { { "D-BUS Service", "Name", config_parse_string, 0, &name }, { "D-BUS Service", "Exec", config_parse_string, 0, &exec }, { "D-BUS Service", "User", config_parse_string, 0, &user }, { "D-BUS Service", "SystemdService", config_parse_string, 0, &service }, { }, }; char *p; int r; assert(path); assert(fname); p = strjoina(path, "/", fname); r = config_parse(NULL, p, NULL, "D-BUS Service\0", config_item_table_lookup, table, true, false, true, NULL); if (r < 0) return r; if (!name) { log_warning("Activation file %s lacks name setting, ignoring.", p); return 0; } if (!service_name_is_valid(name)) { log_warning("Bus service name %s is not valid, ignoring.", name); return 0; } if (streq(name, "org.freedesktop.systemd1")) { log_debug("Skipping %s, identified as systemd.", p); return 0; } if (service) { if (!unit_name_is_valid(service, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) { log_warning("Unit name %s is not valid, ignoring.", service); return 0; } if (!endswith(service, ".service")) { log_warning("Bus names can only activate services, ignoring %s.", p); return 0; } } else { if (streq(exec, "/bin/false") || !exec) { log_warning("Neither service name nor binary path specified, ignoring %s.", p); return 0; } if (exec[0] != '/') { log_warning("Exec= in %s does not start with an absolute path, ignoring.", p); return 0; } } return create_dbus_files(p, name, service, exec, user, type); } static int parse_dbus_fragments(const char *path, const char *type) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r; assert(path); assert(type); d = opendir(path); if (!d) { if (errno == -ENOENT) return 0; return log_error_errno(errno, "Failed to enumerate D-Bus activated services: %m"); } r = 0; FOREACH_DIRENT(de, d, goto fail) { int q; if (!endswith(de->d_name, ".service")) continue; q = add_dbus(path, de->d_name, type); if (q < 0) r = q; } return r; fail: return log_error_errno(errno, "Failed to read D-Bus services directory: %m"); } static int link_busnames_target(const char *units) { const char *f, *t; f = strjoina(units, "/" SPECIAL_BUSNAMES_TARGET); t = strjoina(arg_dest, "/" SPECIAL_BASIC_TARGET ".wants/" SPECIAL_BUSNAMES_TARGET); mkdir_parents_label(t, 0755); if (symlink(f, t) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", t); return 0; } static int link_compatibility(const char *units) { const char *f, *t; f = strjoina(units, "/systemd-bus-proxyd.socket"); t = strjoina(arg_dest, "/" SPECIAL_DBUS_SOCKET); mkdir_parents_label(t, 0755); if (symlink(f, t) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", t); f = strjoina(units, "/systemd-bus-proxyd.socket"); t = strjoina(arg_dest, "/" SPECIAL_SOCKETS_TARGET ".wants/systemd-bus-proxyd.socket"); mkdir_parents_label(t, 0755); if (symlink(f, t) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", t); t = strjoina(arg_dest, "/" SPECIAL_DBUS_SERVICE); if (symlink("/dev/null", t) < 0) return log_error_errno(errno, "Failed to mask %s: %m", t); return 0; } int main(int argc, char *argv[]) { const char *path, *type, *units; int r, q; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); return EXIT_FAILURE; } if (argc > 1) { arg_dest = argv[1]; arg_dest_late = argv[3]; } log_set_target(LOG_TARGET_SAFE); log_parse_environment(); log_open(); umask(0022); if (!is_kdbus_available()) return 0; r = cg_pid_get_owner_uid(0, NULL); if (r >= 0) { path = "/usr/share/dbus-1/services"; type = "session"; units = USER_DATA_UNIT_PATH; } else if (r == -ENXIO) { path = "/usr/share/dbus-1/system-services"; type = "system"; units = SYSTEM_DATA_UNIT_PATH; } else return log_error_errno(r, "Failed to determine whether we are running as user or system instance: %m"); r = parse_dbus_fragments(path, type); /* FIXME: One day this should just be pulled in statically from basic.target */ q = link_busnames_target(units); if (q < 0) r = q; q = link_compatibility(units); if (q < 0) r = q; return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/debug-generator/000077500000000000000000000000001265713322000167225ustar00rootroot00000000000000systemd-229/src/debug-generator/Makefile000077700000000000000000000000001265713322000222302../Makefileustar00rootroot00000000000000systemd-229/src/debug-generator/debug-generator.c000066400000000000000000000142551265713322000221470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "mkdir.h" #include "parse-util.h" #include "proc-cmdline.h" #include "special.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "util.h" static char *arg_default_unit = NULL; static const char *arg_dest = "/tmp"; static char **arg_mask = NULL; static char **arg_wants = NULL; static bool arg_debug_shell = false; static int parse_proc_cmdline_item(const char *key, const char *value) { int r; assert(key); if (streq(key, "systemd.mask")) { if (!value) log_error("Missing argument for systemd.mask= kernel command line parameter."); else { char *n; r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n); if (r < 0) return log_error_errno(r, "Failed to glob unit name: %m"); r = strv_consume(&arg_mask, n); if (r < 0) return log_oom(); } } else if (streq(key, "systemd.wants")) { if (!value) log_error("Missing argument for systemd.want= kernel command line parameter."); else { char *n; r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n); if (r < 0) return log_error_errno(r, "Failed to glob unit name: %m"); r = strv_consume(&arg_wants, n); if (r < 0) return log_oom(); } } else if (streq(key, "systemd.debug-shell")) { if (value) { r = parse_boolean(value); if (r < 0) log_error("Failed to parse systemd.debug-shell= argument '%s', ignoring.", value); else arg_debug_shell = r; } else arg_debug_shell = true; } else if (streq(key, "systemd.unit")) { if (!value) log_error("Missing argument for systemd.unit= kernel command line parameter."); else { r = free_and_strdup(&arg_default_unit, value); if (r < 0) return log_error_errno(r, "Failed to set default unit %s: %m", value); } } else if (!value) { const char *target; target = runlevel_to_target(key); if (target) { r = free_and_strdup(&arg_default_unit, target); if (r < 0) return log_error_errno(r, "Failed to set default unit %s: %m", target); } } return 0; } static int generate_mask_symlinks(void) { char **u; int r = 0; if (strv_isempty(arg_mask)) return 0; STRV_FOREACH(u, arg_mask) { _cleanup_free_ char *p = NULL; p = strjoin(arg_dest, "/", *u, NULL); if (!p) return log_oom(); if (symlink("/dev/null", p) < 0) r = log_error_errno(errno, "Failed to create mask symlink %s: %m", p); } return r; } static int generate_wants_symlinks(void) { char **u; int r = 0; if (strv_isempty(arg_wants)) return 0; STRV_FOREACH(u, arg_wants) { _cleanup_free_ char *p = NULL, *f = NULL; p = strjoin(arg_dest, "/", arg_default_unit, ".wants/", *u, NULL); if (!p) return log_oom(); f = strappend(SYSTEM_DATA_UNIT_PATH "/", *u); if (!f) return log_oom(); mkdir_parents_label(p, 0755); if (symlink(f, p) < 0) r = log_error_errno(errno, "Failed to create wants symlink %s: %m", p); } return r; } int main(int argc, char *argv[]) { int r, q; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); return EXIT_FAILURE; } if (argc > 1) arg_dest = argv[2]; log_set_target(LOG_TARGET_SAFE); log_parse_environment(); log_open(); umask(0022); r = free_and_strdup(&arg_default_unit, SPECIAL_DEFAULT_TARGET); if (r < 0) { log_error_errno(r, "Failed to set default unit %s: %m", SPECIAL_DEFAULT_TARGET); goto finish; } r = parse_proc_cmdline(parse_proc_cmdline_item); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); if (arg_debug_shell) { r = strv_extend(&arg_wants, "debug-shell.service"); if (r < 0) { r = log_oom(); goto finish; } } r = generate_mask_symlinks(); q = generate_wants_symlinks(); if (q < 0) r = q; finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/delta/000077500000000000000000000000001265713322000147415ustar00rootroot00000000000000systemd-229/src/delta/Makefile000077700000000000000000000000001265713322000202472../Makefileustar00rootroot00000000000000systemd-229/src/delta/delta.c000066400000000000000000000452031265713322000162020ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "dirent-util.h" #include "fd-util.h" #include "fs-util.h" #include "hashmap.h" #include "locale-util.h" #include "log.h" #include "pager.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "signal-util.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "util.h" static const char prefixes[] = "/etc\0" "/run\0" "/usr/local/lib\0" "/usr/local/share\0" "/usr/lib\0" "/usr/share\0" #ifdef HAVE_SPLIT_USR "/lib\0" #endif ; static const char suffixes[] = "sysctl.d\0" "tmpfiles.d\0" "modules-load.d\0" "binfmt.d\0" "systemd/system\0" "systemd/user\0" "systemd/system-preset\0" "systemd/user-preset\0" "udev/rules.d\0" "modprobe.d\0"; static const char have_dropins[] = "systemd/system\0" "systemd/user\0"; static bool arg_no_pager = false; static int arg_diff = -1; static enum { SHOW_MASKED = 1 << 0, SHOW_EQUIVALENT = 1 << 1, SHOW_REDIRECTED = 1 << 2, SHOW_OVERRIDDEN = 1 << 3, SHOW_UNCHANGED = 1 << 4, SHOW_EXTENDED = 1 << 5, SHOW_DEFAULTS = (SHOW_MASKED | SHOW_EQUIVALENT | SHOW_REDIRECTED | SHOW_OVERRIDDEN | SHOW_EXTENDED) } arg_flags = 0; static void pager_open_if_enabled(void) { if (arg_no_pager) return; pager_open(false); } static int equivalent(const char *a, const char *b) { _cleanup_free_ char *x = NULL, *y = NULL; x = canonicalize_file_name(a); if (!x) return -errno; y = canonicalize_file_name(b); if (!y) return -errno; return path_equal(x, y); } static int notify_override_masked(const char *top, const char *bottom) { if (!(arg_flags & SHOW_MASKED)) return 0; printf("%s%s%s %s %s %s\n", ansi_highlight_red(), "[MASKED]", ansi_normal(), top, draw_special_char(DRAW_ARROW), bottom); return 1; } static int notify_override_equivalent(const char *top, const char *bottom) { if (!(arg_flags & SHOW_EQUIVALENT)) return 0; printf("%s%s%s %s %s %s\n", ansi_highlight_green(), "[EQUIVALENT]", ansi_normal(), top, draw_special_char(DRAW_ARROW), bottom); return 1; } static int notify_override_redirected(const char *top, const char *bottom) { if (!(arg_flags & SHOW_REDIRECTED)) return 0; printf("%s%s%s %s %s %s\n", ansi_highlight(), "[REDIRECTED]", ansi_normal(), top, draw_special_char(DRAW_ARROW), bottom); return 1; } static int notify_override_overridden(const char *top, const char *bottom) { if (!(arg_flags & SHOW_OVERRIDDEN)) return 0; printf("%s%s%s %s %s %s\n", ansi_highlight(), "[OVERRIDDEN]", ansi_normal(), top, draw_special_char(DRAW_ARROW), bottom); return 1; } static int notify_override_extended(const char *top, const char *bottom) { if (!(arg_flags & SHOW_EXTENDED)) return 0; printf("%s%s%s %s %s %s\n", ansi_highlight(), "[EXTENDED]", ansi_normal(), top, draw_special_char(DRAW_ARROW), bottom); return 1; } static int notify_override_unchanged(const char *f) { if (!(arg_flags & SHOW_UNCHANGED)) return 0; printf("[UNCHANGED] %s\n", f); return 1; } static int found_override(const char *top, const char *bottom) { _cleanup_free_ char *dest = NULL; int k; pid_t pid; assert(top); assert(bottom); if (null_or_empty_path(top) > 0) return notify_override_masked(top, bottom); k = readlink_malloc(top, &dest); if (k >= 0) { if (equivalent(dest, bottom) > 0) return notify_override_equivalent(top, bottom); else return notify_override_redirected(top, bottom); } k = notify_override_overridden(top, bottom); if (!arg_diff) return k; putchar('\n'); fflush(stdout); pid = fork(); if (pid < 0) return log_error_errno(errno, "Failed to fork off diff: %m"); else if (pid == 0) { (void) reset_all_signal_handlers(); (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); execlp("diff", "diff", "-us", "--", bottom, top, NULL); log_error_errno(errno, "Failed to execute diff: %m"); _exit(EXIT_FAILURE); } wait_for_terminate_and_warn("diff", pid, false); putchar('\n'); return k; } static int enumerate_dir_d(Hashmap *top, Hashmap *bottom, Hashmap *drops, const char *toppath, const char *drop) { _cleanup_free_ char *unit = NULL; _cleanup_free_ char *path = NULL; _cleanup_strv_free_ char **list = NULL; char **file; char *c; int r; assert(!endswith(drop, "/")); path = strjoin(toppath, "/", drop, NULL); if (!path) return -ENOMEM; log_debug("Looking at %s", path); unit = strdup(drop); if (!unit) return -ENOMEM; c = strrchr(unit, '.'); if (!c) return -EINVAL; *c = 0; r = get_files_in_directory(path, &list); if (r < 0) return log_error_errno(r, "Failed to enumerate %s: %m", path); STRV_FOREACH(file, list) { Hashmap *h; int k; char *p; char *d; if (!endswith(*file, ".conf")) continue; p = strjoin(path, "/", *file, NULL); if (!p) return -ENOMEM; d = p + strlen(toppath) + 1; log_debug("Adding at top: %s %s %s", d, draw_special_char(DRAW_ARROW), p); k = hashmap_put(top, d, p); if (k >= 0) { p = strdup(p); if (!p) return -ENOMEM; d = p + strlen(toppath) + 1; } else if (k != -EEXIST) { free(p); return k; } log_debug("Adding at bottom: %s %s %s", d, draw_special_char(DRAW_ARROW), p); free(hashmap_remove(bottom, d)); k = hashmap_put(bottom, d, p); if (k < 0) { free(p); return k; } h = hashmap_get(drops, unit); if (!h) { h = hashmap_new(&string_hash_ops); if (!h) return -ENOMEM; hashmap_put(drops, unit, h); unit = strdup(unit); if (!unit) return -ENOMEM; } p = strdup(p); if (!p) return -ENOMEM; log_debug("Adding to drops: %s %s %s %s %s", unit, draw_special_char(DRAW_ARROW), basename(p), draw_special_char(DRAW_ARROW), p); k = hashmap_put(h, basename(p), p); if (k < 0) { free(p); if (k != -EEXIST) return k; } } return 0; } static int enumerate_dir(Hashmap *top, Hashmap *bottom, Hashmap *drops, const char *path, bool dropins) { _cleanup_closedir_ DIR *d; assert(top); assert(bottom); assert(drops); assert(path); log_debug("Looking at %s", path); d = opendir(path); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open %s: %m", path); } for (;;) { struct dirent *de; int k; char *p; errno = 0; de = readdir(d); if (!de) return -errno; dirent_ensure_type(d, de); if (dropins && de->d_type == DT_DIR && endswith(de->d_name, ".d")) enumerate_dir_d(top, bottom, drops, path, de->d_name); if (!dirent_is_file(de)) continue; p = strjoin(path, "/", de->d_name, NULL); if (!p) return -ENOMEM; log_debug("Adding at top: %s %s %s", basename(p), draw_special_char(DRAW_ARROW), p); k = hashmap_put(top, basename(p), p); if (k >= 0) { p = strdup(p); if (!p) return -ENOMEM; } else if (k != -EEXIST) { free(p); return k; } log_debug("Adding at bottom: %s %s %s", basename(p), draw_special_char(DRAW_ARROW), p); free(hashmap_remove(bottom, basename(p))); k = hashmap_put(bottom, basename(p), p); if (k < 0) { free(p); return k; } } } static int process_suffix(const char *suffix, const char *onlyprefix) { const char *p; char *f; Hashmap *top, *bottom, *drops; Hashmap *h; char *key; int r = 0, k; Iterator i, j; int n_found = 0; bool dropins; assert(suffix); assert(!startswith(suffix, "/")); assert(!strstr(suffix, "//")); dropins = nulstr_contains(have_dropins, suffix); top = hashmap_new(&string_hash_ops); bottom = hashmap_new(&string_hash_ops); drops = hashmap_new(&string_hash_ops); if (!top || !bottom || !drops) { r = -ENOMEM; goto finish; } NULSTR_FOREACH(p, prefixes) { _cleanup_free_ char *t = NULL; t = strjoin(p, "/", suffix, NULL); if (!t) { r = -ENOMEM; goto finish; } k = enumerate_dir(top, bottom, drops, t, dropins); if (r == 0) r = k; } HASHMAP_FOREACH_KEY(f, key, top, i) { char *o; o = hashmap_get(bottom, key); assert(o); if (!onlyprefix || startswith(o, onlyprefix)) { if (path_equal(o, f)) { notify_override_unchanged(f); } else { k = found_override(f, o); if (k < 0) r = k; else n_found += k; } } h = hashmap_get(drops, key); if (h) HASHMAP_FOREACH(o, h, j) if (!onlyprefix || startswith(o, onlyprefix)) n_found += notify_override_extended(f, o); } finish: hashmap_free_free(top); hashmap_free_free(bottom); HASHMAP_FOREACH_KEY(h, key, drops, i){ hashmap_free_free(hashmap_remove(drops, key)); hashmap_remove(drops, key); free(key); } hashmap_free(drops); return r < 0 ? r : n_found; } static int process_suffixes(const char *onlyprefix) { const char *n; int n_found = 0, r; NULSTR_FOREACH(n, suffixes) { r = process_suffix(n, onlyprefix); if (r < 0) return r; n_found += r; } return n_found; } static int process_suffix_chop(const char *arg) { const char *p; assert(arg); if (!path_is_absolute(arg)) return process_suffix(arg, NULL); /* Strip prefix from the suffix */ NULSTR_FOREACH(p, prefixes) { const char *suffix; suffix = startswith(arg, p); if (suffix) { suffix += strspn(suffix, "/"); if (*suffix) return process_suffix(suffix, NULL); else return process_suffixes(arg); } } log_error("Invalid suffix specification %s.", arg); return -EINVAL; } static void help(void) { printf("%s [OPTIONS...] [SUFFIX...]\n\n" "Find overridden configuration files.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " --diff[=1|0] Show a diff when overridden files differ\n" " -t --type=LIST... Only display a selected set of override types\n" , program_invocation_short_name); } static int parse_flags(const char *flag_str, int flags) { const char *word, *state; size_t l; FOREACH_WORD_SEPARATOR(word, l, flag_str, ",", state) { if (strneq("masked", word, l)) flags |= SHOW_MASKED; else if (strneq ("equivalent", word, l)) flags |= SHOW_EQUIVALENT; else if (strneq("redirected", word, l)) flags |= SHOW_REDIRECTED; else if (strneq("overridden", word, l)) flags |= SHOW_OVERRIDDEN; else if (strneq("unchanged", word, l)) flags |= SHOW_UNCHANGED; else if (strneq("extended", word, l)) flags |= SHOW_EXTENDED; else if (strneq("default", word, l)) flags |= SHOW_DEFAULTS; else return -EINVAL; } return flags; } static int parse_argv(int argc, char *argv[]) { enum { ARG_NO_PAGER = 0x100, ARG_DIFF, ARG_VERSION }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "diff", optional_argument, NULL, ARG_DIFF }, { "type", required_argument, NULL, 't' }, {} }; int c; assert(argc >= 1); assert(argv); while ((c = getopt_long(argc, argv, "ht:", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_NO_PAGER: arg_no_pager = true; break; case 't': { int f; f = parse_flags(optarg, arg_flags); if (f < 0) { log_error("Failed to parse flags field."); return -EINVAL; } arg_flags = f; break; } case ARG_DIFF: if (!optarg) arg_diff = 1; else { int b; b = parse_boolean(optarg); if (b < 0) { log_error("Failed to parse diff boolean."); return -EINVAL; } arg_diff = b; } break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } int main(int argc, char *argv[]) { int r, k, n_found = 0; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; if (arg_flags == 0) arg_flags = SHOW_DEFAULTS; if (arg_diff < 0) arg_diff = !!(arg_flags & SHOW_OVERRIDDEN); else if (arg_diff) arg_flags |= SHOW_OVERRIDDEN; pager_open_if_enabled(); if (optind < argc) { int i; for (i = optind; i < argc; i++) { path_kill_slashes(argv[i]); k = process_suffix_chop(argv[i]); if (k < 0) r = k; else n_found += k; } } else { k = process_suffixes(NULL); if (k < 0) r = k; else n_found += k; } if (r >= 0) printf("%s%i overridden configuration files found.\n", n_found ? "\n" : "", n_found); finish: pager_close(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/detect-virt/000077500000000000000000000000001265713322000161025ustar00rootroot00000000000000systemd-229/src/detect-virt/Makefile000077700000000000000000000000001265713322000214102../Makefileustar00rootroot00000000000000systemd-229/src/detect-virt/detect-virt.c000066400000000000000000000117551265713322000205110ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "util.h" #include "virt.h" static bool arg_quiet = false; static enum { ANY_VIRTUALIZATION, ONLY_VM, ONLY_CONTAINER, ONLY_CHROOT, } arg_mode = ANY_VIRTUALIZATION; static void help(void) { printf("%s [OPTIONS...]\n\n" "Detect execution in a virtualized environment.\n\n" " -h --help Show this help\n" " --version Show package version\n" " -c --container Only detect whether we are run in a container\n" " -v --vm Only detect whether we are run in a VM\n" " -r --chroot Detect whether we are run in a chroot() environment\n" " -q --quiet Don't output anything, just set return value\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100 }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "container", no_argument, NULL, 'c' }, { "vm", no_argument, NULL, 'v' }, { "chroot", no_argument, NULL, 'r' }, { "quiet", no_argument, NULL, 'q' }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "hqcvr", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case 'q': arg_quiet = true; break; case 'c': arg_mode = ONLY_CONTAINER; break; case 'v': arg_mode = ONLY_VM; break; case 'r': arg_mode = ONLY_CHROOT; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (optind < argc) { log_error("%s takes no arguments.", program_invocation_short_name); return -EINVAL; } return 1; } int main(int argc, char *argv[]) { int r; /* This is mostly intended to be used for scripts which want * to detect whether we are being run in a virtualized * environment or not */ log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; switch (arg_mode) { case ONLY_VM: r = detect_vm(); if (r < 0) { log_error_errno(r, "Failed to check for VM: %m"); return EXIT_FAILURE; } break; case ONLY_CONTAINER: r = detect_container(); if (r < 0) { log_error_errno(r, "Failed to check for container: %m"); return EXIT_FAILURE; } break; case ONLY_CHROOT: r = running_in_chroot(); if (r < 0) { log_error_errno(r, "Failed to check for chroot() environment: %m"); return EXIT_FAILURE; } return r ? EXIT_SUCCESS : EXIT_FAILURE; case ANY_VIRTUALIZATION: default: r = detect_virtualization(); if (r < 0) { log_error_errno(r, "Failed to check for virtualization: %m"); return EXIT_FAILURE; } break; } if (!arg_quiet) puts(virtualization_to_string(r)); return r != VIRTUALIZATION_NONE ? EXIT_SUCCESS : EXIT_FAILURE; } systemd-229/src/escape/000077500000000000000000000000001265713322000151105ustar00rootroot00000000000000systemd-229/src/escape/Makefile000077700000000000000000000000001265713322000204162../Makefileustar00rootroot00000000000000systemd-229/src/escape/escape.c000066400000000000000000000171761265713322000165300ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Michael Biebl systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "log.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" static enum { ACTION_ESCAPE, ACTION_UNESCAPE, ACTION_MANGLE } arg_action = ACTION_ESCAPE; static const char *arg_suffix = NULL; static const char *arg_template = NULL; static bool arg_path = false; static void help(void) { printf("%s [OPTIONS...] [NAME...]\n\n" "Show system and user paths.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --suffix=SUFFIX Unit suffix to append to escaped strings\n" " --template=TEMPLATE Insert strings as instance into template\n" " -u --unescape Unescape strings\n" " -m --mangle Mangle strings\n" " -p --path When escaping/unescaping assume the string is a path\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_SUFFIX, ARG_TEMPLATE }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "suffix", required_argument, NULL, ARG_SUFFIX }, { "template", required_argument, NULL, ARG_TEMPLATE }, { "unescape", no_argument, NULL, 'u' }, { "mangle", no_argument, NULL, 'm' }, { "path", no_argument, NULL, 'p' }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "hump", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_SUFFIX: if (unit_type_from_string(optarg) < 0) { log_error("Invalid unit suffix type %s.", optarg); return -EINVAL; } arg_suffix = optarg; break; case ARG_TEMPLATE: if (!unit_name_is_valid(optarg, UNIT_NAME_TEMPLATE)) { log_error("Template name %s is not valid.", optarg); return -EINVAL; } arg_template = optarg; break; case 'u': arg_action = ACTION_UNESCAPE; break; case 'm': arg_action = ACTION_MANGLE; break; case 'p': arg_path = true; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (optind >= argc) { log_error("Not enough arguments."); return -EINVAL; } if (arg_template && arg_suffix) { log_error("--suffix= and --template= may not be combined."); return -EINVAL; } if ((arg_template || arg_suffix) && arg_action != ACTION_ESCAPE) { log_error("--suffix= and --template= are not compatible with --unescape or --mangle."); return -EINVAL; } if (arg_path && !IN_SET(arg_action, ACTION_ESCAPE, ACTION_UNESCAPE)) { log_error("--path may not be combined with --mangle."); return -EINVAL; } return 1; } int main(int argc, char *argv[]) { char **i; int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; STRV_FOREACH(i, argv + optind) { _cleanup_free_ char *e = NULL; switch (arg_action) { case ACTION_ESCAPE: if (arg_path) { r = unit_name_path_escape(*i, &e); if (r < 0) { log_error_errno(r, "Failed to escape string: %m"); goto finish; } } else { e = unit_name_escape(*i); if (!e) { r = log_oom(); goto finish; } } if (arg_template) { char *x; r = unit_name_replace_instance(arg_template, e, &x); if (r < 0) { log_error_errno(r, "Failed to replace instance: %m"); goto finish; } free(e); e = x; } else if (arg_suffix) { char *x; x = strjoin(e, ".", arg_suffix, NULL); if (!x) { r = log_oom(); goto finish; } free(e); e = x; } break; case ACTION_UNESCAPE: if (arg_path) r = unit_name_path_unescape(*i, &e); else r = unit_name_unescape(*i, &e); if (r < 0) { log_error_errno(r, "Failed to unescape string: %m"); goto finish; } break; case ACTION_MANGLE: r = unit_name_mangle(*i, UNIT_NAME_NOGLOB, &e); if (r < 0) { log_error_errno(r, "Failed to mangle name: %m"); goto finish; } break; } if (i != argv+optind) fputc(' ', stdout); fputs(e, stdout); } fputc('\n', stdout); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/firstboot/000077500000000000000000000000001265713322000156635ustar00rootroot00000000000000systemd-229/src/firstboot/Makefile000077700000000000000000000000001265713322000211712../Makefileustar00rootroot00000000000000systemd-229/src/firstboot/firstboot.c000066400000000000000000000672631265713322000200600ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "ask-password-api.h" #include "copy.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "hostname-util.h" #include "locale-util.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" #include "random-util.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "time-util.h" #include "umask-util.h" #include "user-util.h" static char *arg_root = NULL; static char *arg_locale = NULL; /* $LANG */ static char *arg_locale_messages = NULL; /* $LC_MESSAGES */ static char *arg_timezone = NULL; static char *arg_hostname = NULL; static sd_id128_t arg_machine_id = {}; static char *arg_root_password = NULL; static bool arg_prompt_locale = false; static bool arg_prompt_timezone = false; static bool arg_prompt_hostname = false; static bool arg_prompt_root_password = false; static bool arg_copy_locale = false; static bool arg_copy_timezone = false; static bool arg_copy_root_password = false; static bool press_any_key(void) { char k = 0; bool need_nl = true; printf("-- Press any key to proceed --"); fflush(stdout); (void) read_one_char(stdin, &k, USEC_INFINITY, &need_nl); if (need_nl) putchar('\n'); return k != 'q'; } static void print_welcome(void) { _cleanup_free_ char *pretty_name = NULL; const char *os_release = NULL; static bool done = false; int r; if (done) return; os_release = prefix_roota(arg_root, "/etc/os-release"); r = parse_env_file(os_release, NEWLINE, "PRETTY_NAME", &pretty_name, NULL); if (r == -ENOENT) { os_release = prefix_roota(arg_root, "/usr/lib/os-release"); r = parse_env_file(os_release, NEWLINE, "PRETTY_NAME", &pretty_name, NULL); } if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to read os-release file: %m"); printf("\nWelcome to your new installation of %s!\nPlease configure a few basic system settings:\n\n", isempty(pretty_name) ? "Linux" : pretty_name); press_any_key(); done = true; } static int show_menu(char **x, unsigned n_columns, unsigned width, unsigned percentage) { unsigned n, per_column, i, j; unsigned break_lines, break_modulo; assert(n_columns > 0); n = strv_length(x); per_column = (n + n_columns - 1) / n_columns; break_lines = lines(); if (break_lines > 2) break_lines--; /* The first page gets two extra lines, since we want to show * a title */ break_modulo = break_lines; if (break_modulo > 3) break_modulo -= 3; for (i = 0; i < per_column; i++) { for (j = 0; j < n_columns; j ++) { _cleanup_free_ char *e = NULL; if (j * per_column + i >= n) break; e = ellipsize(x[j * per_column + i], width, percentage); if (!e) return log_oom(); printf("%4u) %-*s", j * per_column + i + 1, width, e); } putchar('\n'); /* on the first screen we reserve 2 extra lines for the title */ if (i % break_lines == break_modulo) { if (!press_any_key()) return 0; } } return 0; } static int prompt_loop(const char *text, char **l, bool (*is_valid)(const char *name), char **ret) { int r; assert(text); assert(is_valid); assert(ret); for (;;) { _cleanup_free_ char *p = NULL; unsigned u; r = ask_string(&p, "%s %s (empty to skip): ", draw_special_char(DRAW_TRIANGULAR_BULLET), text); if (r < 0) return log_error_errno(r, "Failed to query user: %m"); if (isempty(p)) { log_warning("No data entered, skipping."); return 0; } r = safe_atou(p, &u); if (r >= 0) { char *c; if (u <= 0 || u > strv_length(l)) { log_error("Specified entry number out of range."); continue; } log_info("Selected '%s'.", l[u-1]); c = strdup(l[u-1]); if (!c) return log_oom(); free(*ret); *ret = c; return 0; } if (!is_valid(p)) { log_error("Entered data invalid."); continue; } free(*ret); *ret = p; p = 0; return 0; } } static int prompt_locale(void) { _cleanup_strv_free_ char **locales = NULL; int r; if (arg_locale || arg_locale_messages) return 0; if (!arg_prompt_locale) return 0; r = get_locales(&locales); if (r < 0) return log_error_errno(r, "Cannot query locales list: %m"); print_welcome(); printf("\nAvailable Locales:\n\n"); r = show_menu(locales, 3, 22, 60); if (r < 0) return r; putchar('\n'); r = prompt_loop("Please enter system locale name or number", locales, locale_is_valid, &arg_locale); if (r < 0) return r; if (isempty(arg_locale)) return 0; r = prompt_loop("Please enter system message locale name or number", locales, locale_is_valid, &arg_locale_messages); if (r < 0) return r; return 0; } static int process_locale(void) { const char *etc_localeconf; char* locales[3]; unsigned i = 0; int r; etc_localeconf = prefix_roota(arg_root, "/etc/locale.conf"); if (faccessat(AT_FDCWD, etc_localeconf, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) return 0; if (arg_copy_locale && arg_root) { mkdir_parents(etc_localeconf, 0755); r = copy_file("/etc/locale.conf", etc_localeconf, 0, 0644, 0); if (r != -ENOENT) { if (r < 0) return log_error_errno(r, "Failed to copy %s: %m", etc_localeconf); log_info("%s copied.", etc_localeconf); return 0; } } r = prompt_locale(); if (r < 0) return r; if (!isempty(arg_locale)) locales[i++] = strjoina("LANG=", arg_locale); if (!isempty(arg_locale_messages) && !streq(arg_locale_messages, arg_locale)) locales[i++] = strjoina("LC_MESSAGES=", arg_locale_messages); if (i == 0) return 0; locales[i] = NULL; mkdir_parents(etc_localeconf, 0755); r = write_env_file(etc_localeconf, locales); if (r < 0) return log_error_errno(r, "Failed to write %s: %m", etc_localeconf); log_info("%s written.", etc_localeconf); return 0; } static int prompt_timezone(void) { _cleanup_strv_free_ char **zones = NULL; int r; if (arg_timezone) return 0; if (!arg_prompt_timezone) return 0; r = get_timezones(&zones); if (r < 0) return log_error_errno(r, "Cannot query timezone list: %m"); print_welcome(); printf("\nAvailable Time Zones:\n\n"); r = show_menu(zones, 3, 22, 30); if (r < 0) return r; putchar('\n'); r = prompt_loop("Please enter timezone name or number", zones, timezone_is_valid, &arg_timezone); if (r < 0) return r; return 0; } static int process_timezone(void) { const char *etc_localtime, *e; int r; etc_localtime = prefix_roota(arg_root, "/etc/localtime"); if (faccessat(AT_FDCWD, etc_localtime, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) return 0; if (arg_copy_timezone && arg_root) { _cleanup_free_ char *p = NULL; r = readlink_malloc("/etc/localtime", &p); if (r != -ENOENT) { if (r < 0) return log_error_errno(r, "Failed to read host timezone: %m"); mkdir_parents(etc_localtime, 0755); if (symlink(p, etc_localtime) < 0) return log_error_errno(errno, "Failed to create %s symlink: %m", etc_localtime); log_info("%s copied.", etc_localtime); return 0; } } r = prompt_timezone(); if (r < 0) return r; if (isempty(arg_timezone)) return 0; e = strjoina("../usr/share/zoneinfo/", arg_timezone); mkdir_parents(etc_localtime, 0755); if (symlink(e, etc_localtime) < 0) return log_error_errno(errno, "Failed to create %s symlink: %m", etc_localtime); log_info("%s written", etc_localtime); return 0; } static int prompt_hostname(void) { int r; if (arg_hostname) return 0; if (!arg_prompt_hostname) return 0; print_welcome(); putchar('\n'); for (;;) { _cleanup_free_ char *h = NULL; r = ask_string(&h, "%s Please enter hostname for new system (empty to skip): ", draw_special_char(DRAW_TRIANGULAR_BULLET)); if (r < 0) return log_error_errno(r, "Failed to query hostname: %m"); if (isempty(h)) { log_warning("No hostname entered, skipping."); break; } if (!hostname_is_valid(h, true)) { log_error("Specified hostname invalid."); continue; } /* Get rid of the trailing dot that we allow, but don't want to see */ arg_hostname = hostname_cleanup(h); h = NULL; break; } return 0; } static int process_hostname(void) { const char *etc_hostname; int r; etc_hostname = prefix_roota(arg_root, "/etc/hostname"); if (faccessat(AT_FDCWD, etc_hostname, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) return 0; r = prompt_hostname(); if (r < 0) return r; if (isempty(arg_hostname)) return 0; mkdir_parents(etc_hostname, 0755); r = write_string_file(etc_hostname, arg_hostname, WRITE_STRING_FILE_CREATE); if (r < 0) return log_error_errno(r, "Failed to write %s: %m", etc_hostname); log_info("%s written.", etc_hostname); return 0; } static int process_machine_id(void) { const char *etc_machine_id; char id[SD_ID128_STRING_MAX]; int r; etc_machine_id = prefix_roota(arg_root, "/etc/machine-id"); if (faccessat(AT_FDCWD, etc_machine_id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) return 0; if (sd_id128_equal(arg_machine_id, SD_ID128_NULL)) return 0; mkdir_parents(etc_machine_id, 0755); r = write_string_file(etc_machine_id, sd_id128_to_string(arg_machine_id, id), WRITE_STRING_FILE_CREATE); if (r < 0) return log_error_errno(r, "Failed to write machine id: %m"); log_info("%s written.", etc_machine_id); return 0; } static int prompt_root_password(void) { const char *msg1, *msg2, *etc_shadow; int r; if (arg_root_password) return 0; if (!arg_prompt_root_password) return 0; etc_shadow = prefix_roota(arg_root, "/etc/shadow"); if (faccessat(AT_FDCWD, etc_shadow, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) return 0; print_welcome(); putchar('\n'); msg1 = strjoina(draw_special_char(DRAW_TRIANGULAR_BULLET), " Please enter a new root password (empty to skip): "); msg2 = strjoina(draw_special_char(DRAW_TRIANGULAR_BULLET), " Please enter new root password again: "); for (;;) { _cleanup_string_free_erase_ char *a = NULL, *b = NULL; r = ask_password_tty(msg1, NULL, 0, 0, NULL, &a); if (r < 0) return log_error_errno(r, "Failed to query root password: %m"); if (isempty(a)) { log_warning("No password entered, skipping."); break; } r = ask_password_tty(msg2, NULL, 0, 0, NULL, &b); if (r < 0) return log_error_errno(r, "Failed to query root password: %m"); if (!streq(a, b)) { log_error("Entered passwords did not match, please try again."); continue; } arg_root_password = a; a = NULL; break; } return 0; } static int write_root_shadow(const char *path, const struct spwd *p) { _cleanup_fclose_ FILE *f = NULL; assert(path); assert(p); RUN_WITH_UMASK(0777) f = fopen(path, "wex"); if (!f) return -errno; errno = 0; if (putspent(p, f) != 0) return errno > 0 ? -errno : -EIO; return fflush_and_check(f); } static int process_root_password(void) { static const char table[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "./"; struct spwd item = { .sp_namp = (char*) "root", .sp_min = -1, .sp_max = -1, .sp_warn = -1, .sp_inact = -1, .sp_expire = -1, .sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */ }; _cleanup_close_ int lock = -1; char salt[3+16+1+1]; uint8_t raw[16]; unsigned i; char *j; const char *etc_shadow; int r; etc_shadow = prefix_roota(arg_root, "/etc/shadow"); if (faccessat(AT_FDCWD, etc_shadow, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) return 0; mkdir_parents(etc_shadow, 0755); lock = take_etc_passwd_lock(arg_root); if (lock < 0) return log_error_errno(lock, "Failed to take a lock: %m"); if (arg_copy_root_password && arg_root) { struct spwd *p; errno = 0; p = getspnam("root"); if (p || errno != ENOENT) { if (!p) { if (!errno) errno = EIO; return log_error_errno(errno, "Failed to find shadow entry for root: %m"); } r = write_root_shadow(etc_shadow, p); if (r < 0) return log_error_errno(r, "Failed to write %s: %m", etc_shadow); log_info("%s copied.", etc_shadow); return 0; } } r = prompt_root_password(); if (r < 0) return r; if (!arg_root_password) return 0; r = dev_urandom(raw, 16); if (r < 0) return log_error_errno(r, "Failed to get salt: %m"); /* We only bother with SHA512 hashed passwords, the rest is legacy, and we don't do legacy. */ assert_cc(sizeof(table) == 64 + 1); j = stpcpy(salt, "$6$"); for (i = 0; i < 16; i++) j[i] = table[raw[i] & 63]; j[i++] = '$'; j[i] = 0; errno = 0; item.sp_pwdp = crypt(arg_root_password, salt); if (!item.sp_pwdp) { if (!errno) errno = EINVAL; return log_error_errno(errno, "Failed to encrypt password: %m"); } item.sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY); r = write_root_shadow(etc_shadow, &item); if (r < 0) return log_error_errno(r, "Failed to write %s: %m", etc_shadow); log_info("%s written.", etc_shadow); return 0; } static void help(void) { printf("%s [OPTIONS...]\n\n" "Configures basic settings of the system.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --root=PATH Operate on an alternate filesystem root\n" " --locale=LOCALE Set primary locale (LANG=)\n" " --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n" " --timezone=TIMEZONE Set timezone\n" " --hostname=NAME Set host name\n" " --machine-ID=ID Set machine ID\n" " --root-password=PASSWORD Set root password\n" " --root-password-file=FILE Set root password from file\n" " --prompt-locale Prompt the user for locale settings\n" " --prompt-timezone Prompt the user for timezone\n" " --prompt-hostname Prompt the user for hostname\n" " --prompt-root-password Prompt the user for root password\n" " --prompt Prompt for all of the above\n" " --copy-locale Copy locale from host\n" " --copy-timezone Copy timezone from host\n" " --copy-root-password Copy root password from host\n" " --copy Copy locale, timezone, root password\n" " --setup-machine-id Generate a new random machine ID\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_ROOT, ARG_LOCALE, ARG_LOCALE_MESSAGES, ARG_TIMEZONE, ARG_HOSTNAME, ARG_MACHINE_ID, ARG_ROOT_PASSWORD, ARG_ROOT_PASSWORD_FILE, ARG_PROMPT, ARG_PROMPT_LOCALE, ARG_PROMPT_TIMEZONE, ARG_PROMPT_HOSTNAME, ARG_PROMPT_ROOT_PASSWORD, ARG_COPY, ARG_COPY_LOCALE, ARG_COPY_TIMEZONE, ARG_COPY_ROOT_PASSWORD, ARG_SETUP_MACHINE_ID, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "root", required_argument, NULL, ARG_ROOT }, { "locale", required_argument, NULL, ARG_LOCALE }, { "locale-messages", required_argument, NULL, ARG_LOCALE_MESSAGES }, { "timezone", required_argument, NULL, ARG_TIMEZONE }, { "hostname", required_argument, NULL, ARG_HOSTNAME }, { "machine-id", required_argument, NULL, ARG_MACHINE_ID }, { "root-password", required_argument, NULL, ARG_ROOT_PASSWORD }, { "root-password-file", required_argument, NULL, ARG_ROOT_PASSWORD_FILE }, { "prompt", no_argument, NULL, ARG_PROMPT }, { "prompt-locale", no_argument, NULL, ARG_PROMPT_LOCALE }, { "prompt-timezone", no_argument, NULL, ARG_PROMPT_TIMEZONE }, { "prompt-hostname", no_argument, NULL, ARG_PROMPT_HOSTNAME }, { "prompt-root-password", no_argument, NULL, ARG_PROMPT_ROOT_PASSWORD }, { "copy", no_argument, NULL, ARG_COPY }, { "copy-locale", no_argument, NULL, ARG_COPY_LOCALE }, { "copy-timezone", no_argument, NULL, ARG_COPY_TIMEZONE }, { "copy-root-password", no_argument, NULL, ARG_COPY_ROOT_PASSWORD }, { "setup-machine-id", no_argument, NULL, ARG_SETUP_MACHINE_ID }, {} }; int r, c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_ROOT: r = parse_path_argument_and_warn(optarg, true, &arg_root); if (r < 0) return r; break; case ARG_LOCALE: if (!locale_is_valid(optarg)) { log_error("Locale %s is not valid.", optarg); return -EINVAL; } r = free_and_strdup(&arg_locale, optarg); if (r < 0) return log_oom(); break; case ARG_LOCALE_MESSAGES: if (!locale_is_valid(optarg)) { log_error("Locale %s is not valid.", optarg); return -EINVAL; } r = free_and_strdup(&arg_locale_messages, optarg); if (r < 0) return log_oom(); break; case ARG_TIMEZONE: if (!timezone_is_valid(optarg)) { log_error("Timezone %s is not valid.", optarg); return -EINVAL; } r = free_and_strdup(&arg_timezone, optarg); if (r < 0) return log_oom(); break; case ARG_ROOT_PASSWORD: r = free_and_strdup(&arg_root_password, optarg); if (r < 0) return log_oom(); break; case ARG_ROOT_PASSWORD_FILE: arg_root_password = mfree(arg_root_password); r = read_one_line_file(optarg, &arg_root_password); if (r < 0) return log_error_errno(r, "Failed to read %s: %m", optarg); break; case ARG_HOSTNAME: if (!hostname_is_valid(optarg, true)) { log_error("Host name %s is not valid.", optarg); return -EINVAL; } hostname_cleanup(optarg); r = free_and_strdup(&arg_hostname, optarg); if (r < 0) return log_oom(); break; case ARG_MACHINE_ID: if (sd_id128_from_string(optarg, &arg_machine_id) < 0) { log_error("Failed to parse machine id %s.", optarg); return -EINVAL; } break; case ARG_PROMPT: arg_prompt_locale = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = true; break; case ARG_PROMPT_LOCALE: arg_prompt_locale = true; break; case ARG_PROMPT_TIMEZONE: arg_prompt_timezone = true; break; case ARG_PROMPT_HOSTNAME: arg_prompt_hostname = true; break; case ARG_PROMPT_ROOT_PASSWORD: arg_prompt_root_password = true; break; case ARG_COPY: arg_copy_locale = arg_copy_timezone = arg_copy_root_password = true; break; case ARG_COPY_LOCALE: arg_copy_locale = true; break; case ARG_COPY_TIMEZONE: arg_copy_timezone = true; break; case ARG_COPY_ROOT_PASSWORD: arg_copy_root_password = true; break; case ARG_SETUP_MACHINE_ID: r = sd_id128_randomize(&arg_machine_id); if (r < 0) return log_error_errno(r, "Failed to generate randomized machine ID: %m"); break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } int main(int argc, char *argv[]) { int r; r = parse_argv(argc, argv); if (r <= 0) goto finish; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); r = process_locale(); if (r < 0) goto finish; r = process_timezone(); if (r < 0) goto finish; r = process_hostname(); if (r < 0) goto finish; r = process_machine_id(); if (r < 0) goto finish; r = process_root_password(); if (r < 0) goto finish; finish: free(arg_root); free(arg_locale); free(arg_locale_messages); free(arg_timezone); free(arg_hostname); string_erase(arg_root_password); free(arg_root_password); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/fsck/000077500000000000000000000000001265713322000145765ustar00rootroot00000000000000systemd-229/src/fsck/Makefile000077700000000000000000000000001265713322000201042../Makefileustar00rootroot00000000000000systemd-229/src/fsck/fsck.c000066400000000000000000000402331265713322000156720ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2014 Holger Hans Peter Freyther systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "sd-bus.h" #include "sd-device.h" #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" #include "device-util.h" #include "fd-util.h" #include "fs-util.h" #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" #include "process-util.h" #include "signal-util.h" #include "socket-util.h" #include "special.h" #include "stdio-util.h" #include "util.h" /* exit codes as defined in fsck(8) */ enum { FSCK_SUCCESS = 0, FSCK_ERROR_CORRECTED = 1, FSCK_SYSTEM_SHOULD_REBOOT = 2, FSCK_ERRORS_LEFT_UNCORRECTED = 4, FSCK_OPERATIONAL_ERROR = 8, FSCK_USAGE_OR_SYNTAX_ERROR = 16, FSCK_USER_CANCELLED = 32, FSCK_SHARED_LIB_ERROR = 128, }; static bool arg_skip = false; static bool arg_force = false; static bool arg_show_progress = false; static const char *arg_repair = "-a"; static void start_target(const char *target, const char *mode) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; assert(target); r = bus_connect_system_systemd(&bus); if (r < 0) { log_error_errno(r, "Failed to get D-Bus connection: %m"); return; } log_info("Running request %s/start/replace", target); /* Start these units only if we can replace base.target with it */ r = sd_bus_call_method(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnitReplace", &error, NULL, "sss", "basic.target", target, mode); /* Don't print a warning if we aren't called during startup */ if (r < 0 && !sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_JOB)) log_error("Failed to start unit: %s", bus_error_message(&error, r)); } static int parse_proc_cmdline_item(const char *key, const char *value) { int r; assert(key); if (streq(key, "fsck.mode") && value) { if (streq(value, "auto")) arg_force = arg_skip = false; else if (streq(value, "force")) arg_force = true; else if (streq(value, "skip")) arg_skip = true; else log_warning("Invalid fsck.mode= parameter '%s'. Ignoring.", value); } else if (streq(key, "fsck.repair") && value) { if (streq(value, "preen")) arg_repair = "-a"; else { r = parse_boolean(value); if (r > 0) arg_repair = "-y"; else if (r == 0) arg_repair = "-n"; else log_warning("Invalid fsck.repair= parameter '%s'. Ignoring.", value); } } #ifdef HAVE_SYSV_COMPAT else if (streq(key, "fastboot") && !value) { log_warning("Please pass 'fsck.mode=skip' rather than 'fastboot' on the kernel command line."); arg_skip = true; } else if (streq(key, "forcefsck") && !value) { log_warning("Please pass 'fsck.mode=force' rather than 'forcefsck' on the kernel command line."); arg_force = true; } #endif return 0; } static void test_files(void) { #ifdef HAVE_SYSV_COMPAT if (access("/fastboot", F_OK) >= 0) { log_error("Please pass 'fsck.mode=skip' on the kernel command line rather than creating /fastboot on the root file system."); arg_skip = true; } if (access("/forcefsck", F_OK) >= 0) { log_error("Please pass 'fsck.mode=force' on the kernel command line rather than creating /forcefsck on the root file system."); arg_force = true; } #endif arg_show_progress = access("/run/systemd/show-status", F_OK) >= 0; } static double percent(int pass, unsigned long cur, unsigned long max) { /* Values stolen from e2fsck */ static const int pass_table[] = { 0, 70, 90, 92, 95, 100 }; if (pass <= 0) return 0.0; if ((unsigned) pass >= ELEMENTSOF(pass_table) || max == 0) return 100.0; return (double) pass_table[pass-1] + ((double) pass_table[pass] - (double) pass_table[pass-1]) * (double) cur / (double) max; } static int process_progress(int fd) { _cleanup_fclose_ FILE *console = NULL, *f = NULL; usec_t last = 0; bool locked = false; int clear = 0, r; /* No progress pipe to process? Then we are a NOP. */ if (fd < 0) return 0; f = fdopen(fd, "re"); if (!f) { safe_close(fd); return -errno; } console = fopen("/dev/console", "we"); if (!console) return -ENOMEM; for (;;) { int pass, m; unsigned long cur, max; _cleanup_free_ char *device = NULL; double p; usec_t t; if (fscanf(f, "%i %lu %lu %ms", &pass, &cur, &max, &device) != 4) { if (ferror(f)) r = log_warning_errno(errno, "Failed to read from progress pipe: %m"); else if (feof(f)) r = 0; else { log_warning("Failed to parse progress pipe data"); r = -EBADMSG; } break; } /* Only show one progress counter at max */ if (!locked) { if (flock(fileno(console), LOCK_EX|LOCK_NB) < 0) continue; locked = true; } /* Only update once every 50ms */ t = now(CLOCK_MONOTONIC); if (last + 50 * USEC_PER_MSEC > t) continue; last = t; p = percent(pass, cur, max); fprintf(console, "\r%s: fsck %3.1f%% complete...\r%n", device, p, &m); fflush(console); if (m > clear) clear = m; } if (clear > 0) { unsigned j; fputc('\r', console); for (j = 0; j < (unsigned) clear; j++) fputc(' ', console); fputc('\r', console); fflush(console); } return r; } static int fsck_progress_socket(void) { static const union sockaddr_union sa = { .un.sun_family = AF_UNIX, .un.sun_path = "/run/systemd/fsck.progress", }; int fd, r; fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) return log_warning_errno(errno, "socket(): %m"); if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) { r = log_full_errno(errno == ECONNREFUSED || errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, "Failed to connect to progress socket %s, ignoring: %m", sa.un.sun_path); safe_close(fd); return r; } return fd; } int main(int argc, char *argv[]) { _cleanup_close_pair_ int progress_pipe[2] = { -1, -1 }; _cleanup_(sd_device_unrefp) sd_device *dev = NULL; const char *device, *type; bool root_directory; siginfo_t status; struct stat st; int r; pid_t pid; if (argc > 2) { log_error("This program expects one or no arguments."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); r = parse_proc_cmdline(parse_proc_cmdline_item); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); test_files(); if (!arg_force && arg_skip) { r = 0; goto finish; } if (argc > 1) { device = argv[1]; if (stat(device, &st) < 0) { r = log_error_errno(errno, "Failed to stat %s: %m", device); goto finish; } if (!S_ISBLK(st.st_mode)) { log_error("%s is not a block device.", device); r = -EINVAL; goto finish; } r = sd_device_new_from_devnum(&dev, 'b', st.st_rdev); if (r < 0) { log_error_errno(r, "Failed to detect device %s: %m", device); goto finish; } root_directory = false; } else { struct timespec times[2]; /* Find root device */ if (stat("/", &st) < 0) { r = log_error_errno(errno, "Failed to stat() the root directory: %m"); goto finish; } /* Virtual root devices don't need an fsck */ if (major(st.st_dev) == 0) { log_debug("Root directory is virtual or btrfs, skipping check."); r = 0; goto finish; } /* check if we are already writable */ times[0] = st.st_atim; times[1] = st.st_mtim; if (utimensat(AT_FDCWD, "/", times, 0) == 0) { log_info("Root directory is writable, skipping check."); r = 0; goto finish; } r = sd_device_new_from_devnum(&dev, 'b', st.st_dev); if (r < 0) { log_error_errno(r, "Failed to detect root device: %m"); goto finish; } r = sd_device_get_devname(dev, &device); if (r < 0) { log_error_errno(r, "Failed to detect device node of root directory: %m"); goto finish; } root_directory = true; } r = sd_device_get_property_value(dev, "ID_FS_TYPE", &type); if (r >= 0) { r = fsck_exists(type); if (r < 0) log_warning_errno(r, "Couldn't detect if fsck.%s may be used for %s, proceeding: %m", type, device); else if (r == 0) { log_info("fsck.%s doesn't exist, not checking file system on %s.", type, device); goto finish; } } if (arg_show_progress) { if (pipe(progress_pipe) < 0) { r = log_error_errno(errno, "pipe(): %m"); goto finish; } } pid = fork(); if (pid < 0) { r = log_error_errno(errno, "fork(): %m"); goto finish; } if (pid == 0) { char dash_c[sizeof("-C")-1 + DECIMAL_STR_MAX(int) + 1]; int progress_socket = -1; const char *cmdline[9]; int i = 0; /* Child */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); /* Close the reading side of the progress pipe */ progress_pipe[0] = safe_close(progress_pipe[0]); /* Try to connect to a progress management daemon, if there is one */ progress_socket = fsck_progress_socket(); if (progress_socket >= 0) { /* If this worked we close the progress pipe early, and just use the socket */ progress_pipe[1] = safe_close(progress_pipe[1]); xsprintf(dash_c, "-C%i", progress_socket); } else if (progress_pipe[1] >= 0) { /* Otherwise if we have the progress pipe to our own local handle, we use it */ xsprintf(dash_c, "-C%i", progress_pipe[1]); } else dash_c[0] = 0; cmdline[i++] = "/sbin/fsck"; cmdline[i++] = arg_repair; cmdline[i++] = "-T"; /* * Since util-linux v2.25 fsck uses /run/fsck/.lock files. * The previous versions use flock for the device and conflict with * udevd, see https://bugs.freedesktop.org/show_bug.cgi?id=79576#c5 */ cmdline[i++] = "-l"; if (!root_directory) cmdline[i++] = "-M"; if (arg_force) cmdline[i++] = "-f"; if (!isempty(dash_c)) cmdline[i++] = dash_c; cmdline[i++] = device; cmdline[i++] = NULL; execv(cmdline[0], (char**) cmdline); _exit(FSCK_OPERATIONAL_ERROR); } progress_pipe[1] = safe_close(progress_pipe[1]); (void) process_progress(progress_pipe[0]); progress_pipe[0] = -1; r = wait_for_terminate(pid, &status); if (r < 0) { log_error_errno(r, "waitid(): %m"); goto finish; } if (status.si_code != CLD_EXITED || (status.si_status & ~1)) { if (status.si_code == CLD_KILLED || status.si_code == CLD_DUMPED) log_error("fsck terminated by signal %s.", signal_to_string(status.si_status)); else if (status.si_code == CLD_EXITED) log_error("fsck failed with error code %i.", status.si_status); else log_error("fsck failed due to unknown reason."); r = -EINVAL; if (status.si_code == CLD_EXITED && (status.si_status & FSCK_SYSTEM_SHOULD_REBOOT) && root_directory) /* System should be rebooted. */ start_target(SPECIAL_REBOOT_TARGET, "replace-irreversibly"); else if (status.si_code == CLD_EXITED && (status.si_status & (FSCK_SYSTEM_SHOULD_REBOOT | FSCK_ERRORS_LEFT_UNCORRECTED))) /* Some other problem */ start_target(SPECIAL_EMERGENCY_TARGET, "replace"); else { log_warning("Ignoring error."); r = 0; } } else r = 0; if (status.si_code == CLD_EXITED && (status.si_status & FSCK_ERROR_CORRECTED)) (void) touch("/run/systemd/quotacheck"); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/fstab-generator/000077500000000000000000000000001265713322000167335ustar00rootroot00000000000000systemd-229/src/fstab-generator/Makefile000077700000000000000000000000001265713322000222412../Makefileustar00rootroot00000000000000systemd-229/src/fstab-generator/fstab-generator.c000066400000000000000000000547461265713322000222020ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "fstab-util.h" #include "generator.h" #include "log.h" #include "mkdir.h" #include "mount-setup.h" #include "mount-util.h" #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" #include "special.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "util.h" #include "virt.h" static const char *arg_dest = "/tmp"; static bool arg_fstab_enabled = true; static char *arg_root_what = NULL; static char *arg_root_fstype = NULL; static char *arg_root_options = NULL; static int arg_root_rw = -1; static char *arg_usr_what = NULL; static char *arg_usr_fstype = NULL; static char *arg_usr_options = NULL; static int add_swap( const char *what, struct mntent *me, bool noauto, bool nofail) { _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(what); assert(me); if (access("/proc/swaps", F_OK) < 0) { log_info("Swap not supported, ignoring fstab swap entry for %s.", what); return 0; } if (detect_container() > 0) { log_info("Running in a container, ignoring fstab swap entry for %s.", what); return 0; } r = unit_name_from_path(what, ".swap", &name); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); unit = strjoin(arg_dest, "/", name, NULL); if (!unit) return log_oom(); f = fopen(unit, "wxe"); if (!f) { if (errno == EEXIST) log_error("Failed to create swap unit file %s, as it already exists. Duplicate entry in /etc/fstab?", unit); else log_error_errno(errno, "Failed to create unit file %s: %m", unit); return -errno; } fprintf(f, "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=/etc/fstab\n" "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n\n" "[Swap]\n" "What=%s\n", what); if (!isempty(me->mnt_opts) && !streq(me->mnt_opts, "defaults")) fprintf(f, "Options=%s\n", me->mnt_opts); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", unit); /* use what as where, to have a nicer error message */ r = generator_write_timeouts(arg_dest, what, what, me->mnt_opts, NULL); if (r < 0) return r; if (!noauto) { lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET, nofail ? ".wants/" : ".requires/", name, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(unit, lnk) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); } return 0; } static bool mount_is_network(struct mntent *me) { assert(me); return fstab_test_option(me->mnt_opts, "_netdev\0") || fstype_is_network(me->mnt_type); } static bool mount_in_initrd(struct mntent *me) { assert(me); return fstab_test_option(me->mnt_opts, "x-initrd.mount\0") || streq(me->mnt_dir, "/usr"); } static int write_idle_timeout(FILE *f, const char *where, const char *opts) { _cleanup_free_ char *timeout = NULL; char timespan[FORMAT_TIMESPAN_MAX]; usec_t u; int r; r = fstab_filter_options(opts, "x-systemd.idle-timeout\0", NULL, &timeout, NULL); if (r < 0) return log_warning_errno(r, "Failed to parse options: %m"); if (r == 0) return 0; r = parse_sec(timeout, &u); if (r < 0) { log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout); return 0; } fprintf(f, "TimeoutIdleSec=%s\n", format_timespan(timespan, sizeof(timespan), u, 0)); return 0; } static int write_requires_after(FILE *f, const char *opts) { _cleanup_strv_free_ char **names = NULL, **units = NULL; _cleanup_free_ char *res = NULL; char **s; int r; assert(f); assert(opts); r = fstab_extract_values(opts, "x-systemd.requires", &names); if (r < 0) return log_warning_errno(r, "Failed to parse options: %m"); if (r == 0) return 0; STRV_FOREACH(s, names) { char *x; r = unit_name_mangle_with_suffix(*s, UNIT_NAME_NOGLOB, ".mount", &x); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); r = strv_consume(&units, x); if (r < 0) return log_oom(); } if (units) { res = strv_join(units, " "); if (!res) return log_oom(); fprintf(f, "After=%1$s\nRequires=%1$s\n", res); } return 0; } static int write_requires_mounts_for(FILE *f, const char *opts) { _cleanup_strv_free_ char **paths = NULL; _cleanup_free_ char *res = NULL; int r; assert(f); assert(opts); r = fstab_extract_values(opts, "x-systemd.requires-mounts-for", &paths); if (r < 0) return log_warning_errno(r, "Failed to parse options: %m"); if (r == 0) return 0; res = strv_join(paths, " "); if (!res) return log_oom(); fprintf(f, "RequiresMountsFor=%s\n", res); return 0; } static int add_mount( const char *what, const char *where, const char *fstype, const char *opts, int passno, bool noauto, bool nofail, bool automount, const char *post, const char *source) { _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL, *automount_name = NULL, *automount_unit = NULL, *filtered = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(what); assert(where); assert(opts); assert(post); assert(source); if (streq_ptr(fstype, "autofs")) return 0; if (!is_path(where)) { log_warning("Mount point %s is not a valid path, ignoring.", where); return 0; } if (mount_point_is_api(where) || mount_point_ignore(where)) return 0; if (path_equal(where, "/")) { if (noauto) log_warning("Ignoring \"noauto\" for root device"); if (nofail) log_warning("Ignoring \"nofail\" for root device"); if (automount) log_warning("Ignoring automount option for root device"); noauto = nofail = automount = false; } r = unit_name_from_path(where, ".mount", &name); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); unit = strjoin(arg_dest, "/", name, NULL); if (!unit) return log_oom(); f = fopen(unit, "wxe"); if (!f) { if (errno == EEXIST) log_error("Failed to create mount unit file %s, as it already exists. Duplicate entry in /etc/fstab?", unit); else log_error_errno(errno, "Failed to create unit file %s: %m", unit); return -errno; } fprintf(f, "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=%s\n" "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n", source); if (!noauto && !nofail && !automount) fprintf(f, "Before=%s\n", post); if (!automount && opts) { r = write_requires_after(f, opts); if (r < 0) return r; r = write_requires_mounts_for(f, opts); if (r < 0) return r; } if (passno != 0) { r = generator_write_fsck_deps(f, arg_dest, what, where, fstype); if (r < 0) return r; } fprintf(f, "\n" "[Mount]\n" "What=%s\n" "Where=%s\n", what, where); if (!isempty(fstype) && !streq(fstype, "auto")) fprintf(f, "Type=%s\n", fstype); r = generator_write_timeouts(arg_dest, what, where, opts, &filtered); if (r < 0) return r; if (!isempty(filtered) && !streq(filtered, "defaults")) fprintf(f, "Options=%s\n", filtered); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", unit); if (!noauto) { lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(unit, lnk) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); } if (automount) { r = unit_name_from_path(where, ".automount", &automount_name); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); automount_unit = strjoin(arg_dest, "/", automount_name, NULL); if (!automount_unit) return log_oom(); fclose(f); f = fopen(automount_unit, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", automount_unit); fprintf(f, "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=%s\n" "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n", source); fprintf(f, "Before=%s\n", post); if (opts) { r = write_requires_after(f, opts); if (r < 0) return r; r = write_requires_mounts_for(f, opts); if (r < 0) return r; } fprintf(f, "[Automount]\n" "Where=%s\n", where); r = write_idle_timeout(f, where, opts); if (r < 0) return r; r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", automount_unit); free(lnk); lnk = strjoin(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", automount_name, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(automount_unit, lnk) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); } return 0; } static int parse_fstab(bool initrd) { _cleanup_endmntent_ FILE *f = NULL; const char *fstab_path; struct mntent *me; int r = 0; fstab_path = initrd ? "/sysroot/etc/fstab" : "/etc/fstab"; f = setmntent(fstab_path, "re"); if (!f) { if (errno == ENOENT) return 0; log_error_errno(errno, "Failed to open %s: %m", fstab_path); return -errno; } while ((me = getmntent(f))) { _cleanup_free_ char *where = NULL, *what = NULL; bool noauto, nofail; int k; if (initrd && !mount_in_initrd(me)) continue; what = fstab_node_to_udev_node(me->mnt_fsname); if (!what) return log_oom(); if (is_device_path(what) && path_is_read_only_fs("sys") > 0) { log_info("Running in a container, ignoring fstab device entry for %s.", what); continue; } where = initrd ? strappend("/sysroot/", me->mnt_dir) : strdup(me->mnt_dir); if (!where) return log_oom(); if (is_path(where)) path_kill_slashes(where); noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0"); nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0"); log_debug("Found entry what=%s where=%s type=%s nofail=%s noauto=%s", what, where, me->mnt_type, yes_no(noauto), yes_no(nofail)); if (streq(me->mnt_type, "swap")) k = add_swap(what, me, noauto, nofail); else { bool automount; const char *post; automount = fstab_test_option(me->mnt_opts, "comment=systemd.automount\0" "x-systemd.automount\0"); if (initrd) post = SPECIAL_INITRD_FS_TARGET; else if (mount_is_network(me)) post = SPECIAL_REMOTE_FS_TARGET; else post = SPECIAL_LOCAL_FS_TARGET; k = add_mount(what, where, me->mnt_type, me->mnt_opts, me->mnt_passno, noauto, nofail, automount, post, fstab_path); } if (k < 0) r = k; } return r; } static int add_sysroot_mount(void) { _cleanup_free_ char *what = NULL; const char *opts; if (isempty(arg_root_what)) { log_debug("Could not find a root= entry on the kernel command line."); return 0; } what = fstab_node_to_udev_node(arg_root_what); if (!what) return log_oom(); if (!arg_root_options) opts = arg_root_rw > 0 ? "rw" : "ro"; else if (arg_root_rw >= 0 || !fstab_test_option(arg_root_options, "ro\0" "rw\0")) opts = strjoina(arg_root_options, ",", arg_root_rw > 0 ? "rw" : "ro"); else opts = arg_root_options; log_debug("Found entry what=%s where=/sysroot type=%s", what, strna(arg_root_fstype)); return add_mount(what, "/sysroot", arg_root_fstype, opts, is_device_path(what) ? 1 : 0, false, false, false, SPECIAL_INITRD_ROOT_FS_TARGET, "/proc/cmdline"); } static int add_sysroot_usr_mount(void) { _cleanup_free_ char *what = NULL; const char *opts; if (!arg_usr_what && !arg_usr_fstype && !arg_usr_options) return 0; if (arg_root_what && !arg_usr_what) { arg_usr_what = strdup(arg_root_what); if (!arg_usr_what) return log_oom(); } if (arg_root_fstype && !arg_usr_fstype) { arg_usr_fstype = strdup(arg_root_fstype); if (!arg_usr_fstype) return log_oom(); } if (arg_root_options && !arg_usr_options) { arg_usr_options = strdup(arg_root_options); if (!arg_usr_options) return log_oom(); } if (!arg_usr_what) return 0; what = fstab_node_to_udev_node(arg_usr_what); if (!path_is_absolute(what)) { log_debug("Skipping entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype)); return -1; } if (!arg_usr_options) opts = arg_root_rw > 0 ? "rw" : "ro"; else if (!fstab_test_option(arg_usr_options, "ro\0" "rw\0")) opts = strjoina(arg_usr_options, ",", arg_root_rw > 0 ? "rw" : "ro"); else opts = arg_usr_options; log_debug("Found entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype)); return add_mount(what, "/sysroot/usr", arg_usr_fstype, opts, 1, false, false, false, SPECIAL_INITRD_FS_TARGET, "/proc/cmdline"); } static int parse_proc_cmdline_item(const char *key, const char *value) { int r; /* root=, usr=, usrfstype= and roofstype= may occur more than once, the last * instance should take precedence. In the case of multiple rootflags= * or usrflags= the arguments should be concatenated */ if (STR_IN_SET(key, "fstab", "rd.fstab") && value) { r = parse_boolean(value); if (r < 0) log_warning("Failed to parse fstab switch %s. Ignoring.", value); else arg_fstab_enabled = r; } else if (streq(key, "root") && value) { if (free_and_strdup(&arg_root_what, value) < 0) return log_oom(); } else if (streq(key, "rootfstype") && value) { if (free_and_strdup(&arg_root_fstype, value) < 0) return log_oom(); } else if (streq(key, "rootflags") && value) { char *o; o = arg_root_options ? strjoin(arg_root_options, ",", value, NULL) : strdup(value); if (!o) return log_oom(); free(arg_root_options); arg_root_options = o; } else if (streq(key, "mount.usr") && value) { if (free_and_strdup(&arg_usr_what, value) < 0) return log_oom(); } else if (streq(key, "mount.usrfstype") && value) { if (free_and_strdup(&arg_usr_fstype, value) < 0) return log_oom(); } else if (streq(key, "mount.usrflags") && value) { char *o; o = arg_usr_options ? strjoin(arg_usr_options, ",", value, NULL) : strdup(value); if (!o) return log_oom(); free(arg_usr_options); arg_usr_options = o; } else if (streq(key, "rw") && !value) arg_root_rw = true; else if (streq(key, "ro") && !value) arg_root_rw = false; return 0; } int main(int argc, char *argv[]) { int r = 0; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); return EXIT_FAILURE; } if (argc > 1) arg_dest = argv[1]; log_set_target(LOG_TARGET_SAFE); log_parse_environment(); log_open(); umask(0022); r = parse_proc_cmdline(parse_proc_cmdline_item); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); /* Always honour root= and usr= in the kernel command line if we are in an initrd */ if (in_initrd()) { r = add_sysroot_mount(); if (r == 0) r = add_sysroot_usr_mount(); } /* Honour /etc/fstab only when that's enabled */ if (arg_fstab_enabled) { int k; log_debug("Parsing /etc/fstab"); /* Parse the local /etc/fstab, possibly from the initrd */ k = parse_fstab(false); if (k < 0) r = k; /* If running in the initrd also parse the /etc/fstab from the host */ if (in_initrd()) { log_debug("Parsing /sysroot/etc/fstab"); k = parse_fstab(true); if (k < 0) r = k; } } free(arg_root_what); free(arg_root_fstype); free(arg_root_options); free(arg_usr_what); free(arg_usr_fstype); free(arg_usr_options); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/getty-generator/000077500000000000000000000000001265713322000167705ustar00rootroot00000000000000systemd-229/src/getty-generator/Makefile000077700000000000000000000000001265713322000222762../Makefileustar00rootroot00000000000000systemd-229/src/getty-generator/getty-generator.c000066400000000000000000000162111265713322000222550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "log.h" #include "mkdir.h" #include "path-util.h" #include "process-util.h" #include "string-util.h" #include "terminal-util.h" #include "unit-name.h" #include "util.h" #include "virt.h" static const char *arg_dest = "/tmp"; static int add_symlink(const char *fservice, const char *tservice) { char *from, *to; int r; assert(fservice); assert(tservice); from = strjoina(SYSTEM_DATA_UNIT_PATH "/", fservice); to = strjoina(arg_dest, "/getty.target.wants/", tservice); mkdir_parents_label(to, 0755); r = symlink(from, to); if (r < 0) { /* In case console=hvc0 is passed this will very likely result in EEXIST */ if (errno == EEXIST) return 0; return log_error_errno(errno, "Failed to create symlink %s: %m", to); } return 0; } static int add_serial_getty(const char *tty) { _cleanup_free_ char *n = NULL; int r; assert(tty); log_debug("Automatically adding serial getty for /dev/%s.", tty); r = unit_name_from_path_instance("serial-getty", tty, ".service", &n); if (r < 0) return log_error_errno(r, "Failed to generate service name: %m"); return add_symlink("serial-getty@.service", n); } static int add_container_getty(const char *tty) { _cleanup_free_ char *n = NULL; int r; assert(tty); log_debug("Automatically adding container getty for /dev/pts/%s.", tty); r = unit_name_from_path_instance("container-getty", tty, ".service", &n); if (r < 0) return log_error_errno(r, "Failed to generate service name: %m"); return add_symlink("container-getty@.service", n); } static int verify_tty(const char *name) { _cleanup_close_ int fd = -1; const char *p; /* Some TTYs are weird and have been enumerated but don't work * when you try to use them, such as classic ttyS0 and * friends. Let's check that and open the device and run * isatty() on it. */ p = strjoina("/dev/", name); /* O_NONBLOCK is essential here, to make sure we don't wait * for DCD */ fd = open(p, O_RDWR|O_NONBLOCK|O_NOCTTY|O_CLOEXEC|O_NOFOLLOW); if (fd < 0) return -errno; errno = 0; if (isatty(fd) <= 0) return errno > 0 ? -errno : -EIO; return 0; } int main(int argc, char *argv[]) { static const char virtualization_consoles[] = "hvc0\0" "xvc0\0" "hvsi0\0" "sclp_line0\0" "ttysclp0\0" "3270!tty1\0"; _cleanup_free_ char *active = NULL; const char *j; int r; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); return EXIT_FAILURE; } if (argc > 1) arg_dest = argv[1]; log_set_target(LOG_TARGET_SAFE); log_parse_environment(); log_open(); umask(0022); if (detect_container() > 0) { _cleanup_free_ char *container_ttys = NULL; log_debug("Automatically adding console shell."); if (add_symlink("console-getty.service", "console-getty.service") < 0) return EXIT_FAILURE; /* When $container_ttys is set for PID 1, spawn * gettys on all ptys named therein. Note that despite * the variable name we only support ptys here. */ r = getenv_for_pid(1, "container_ttys", &container_ttys); if (r > 0) { const char *word, *state; size_t l; FOREACH_WORD(word, l, container_ttys, state) { const char *t; char tty[l + 1]; memcpy(tty, word, l); tty[l] = 0; /* First strip off /dev/ if it is specified */ t = path_startswith(tty, "/dev/"); if (!t) t = tty; /* Then, make sure it's actually a pty */ t = path_startswith(t, "pts/"); if (!t) continue; if (add_container_getty(t) < 0) return EXIT_FAILURE; } } /* Don't add any further magic if we are in a container */ return EXIT_SUCCESS; } if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) { const char *word, *state; size_t l; /* Automatically add in a serial getty on all active * kernel consoles */ FOREACH_WORD(word, l, active, state) { _cleanup_free_ char *tty = NULL; tty = strndup(word, l); if (!tty) { log_oom(); return EXIT_FAILURE; } if (isempty(tty) || tty_is_vc(tty)) continue; if (verify_tty(tty) < 0) continue; /* We assume that gettys on virtual terminals are * started via manual configuration and do this magic * only for non-VC terminals. */ if (add_serial_getty(tty) < 0) return EXIT_FAILURE; } } /* Automatically add in a serial getty on the first * virtualizer console */ NULSTR_FOREACH(j, virtualization_consoles) { char *p; p = strjoina("/sys/class/tty/", j); if (access(p, F_OK) < 0) continue; if (add_serial_getty(j) < 0) return EXIT_FAILURE; } return EXIT_SUCCESS; } systemd-229/src/gpt-auto-generator/000077500000000000000000000000001265713322000173745ustar00rootroot00000000000000systemd-229/src/gpt-auto-generator/Makefile000077700000000000000000000000001265713322000227022../Makefileustar00rootroot00000000000000systemd-229/src/gpt-auto-generator/gpt-auto-generator.c000066400000000000000000000757021265713322000232770ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "libudev.h" #include "sd-id128.h" #include "alloc-util.h" #include "blkid-util.h" #include "btrfs-util.h" #include "dirent-util.h" #include "efivars.h" #include "fd-util.h" #include "fileio.h" #include "fstab-util.h" #include "generator.h" #include "gpt.h" #include "missing.h" #include "mkdir.h" #include "mount-util.h" #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" #include "special.h" #include "stat-util.h" #include "string-util.h" #include "udev-util.h" #include "unit-name.h" #include "util.h" #include "virt.h" static const char *arg_dest = "/tmp"; static bool arg_enabled = true; static bool arg_root_enabled = true; static bool arg_root_rw = false; static int add_cryptsetup(const char *id, const char *what, bool rw, char **device) { _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *to = NULL; _cleanup_fclose_ FILE *f = NULL; char *from, *ret; int r; assert(id); assert(what); assert(device); r = unit_name_from_path(what, ".device", &d); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); e = unit_name_escape(id); if (!e) return log_oom(); r = unit_name_build("systemd-cryptsetup", e, ".service", &n); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); p = strjoin(arg_dest, "/", n, NULL); if (!p) return log_oom(); f = fopen(p, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", p); fprintf(f, "# Automatically generated by systemd-gpt-auto-generator\n\n" "[Unit]\n" "Description=Cryptography Setup for %%I\n" "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n" "DefaultDependencies=no\n" "Conflicts=umount.target\n" "BindsTo=dev-mapper-%%i.device %s\n" "Before=umount.target cryptsetup.target\n" "After=%s\n" "IgnoreOnIsolate=true\n" "[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" "TimeoutSec=0\n" /* the binary handles timeouts anyway */ "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n" "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n", d, d, id, what, rw ? "" : "read-only", id); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write file %s: %m", p); from = strjoina("../", n); to = strjoin(arg_dest, "/", d, ".wants/", n, NULL); if (!to) return log_oom(); mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); free(to); to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL); if (!to) return log_oom(); mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); free(to); to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL); if (!to) return log_oom(); mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); free(p); p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL); if (!p) return log_oom(); mkdir_parents_label(p, 0755); r = write_string_file(p, "# Automatically generated by systemd-gpt-auto-generator\n\n" "[Unit]\n" "JobTimeoutSec=0\n", WRITE_STRING_FILE_CREATE); /* the binary handles timeouts anyway */ if (r < 0) return log_error_errno(r, "Failed to write device drop-in: %m"); ret = strappend("/dev/mapper/", id); if (!ret) return log_oom(); *device = ret; return 0; } static int add_mount( const char *id, const char *what, const char *where, const char *fstype, bool rw, const char *options, const char *description, const char *post) { _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(id); assert(what); assert(where); assert(description); log_debug("Adding %s: %s %s", where, what, strna(fstype)); if (streq_ptr(fstype, "crypto_LUKS")) { r = add_cryptsetup(id, what, rw, &crypto_what); if (r < 0) return r; what = crypto_what; fstype = NULL; } r = unit_name_from_path(where, ".mount", &unit); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); p = strjoin(arg_dest, "/", unit, NULL); if (!p) return log_oom(); f = fopen(p, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", unit); fprintf(f, "# Automatically generated by systemd-gpt-auto-generator\n\n" "[Unit]\n" "Description=%s\n" "Documentation=man:systemd-gpt-auto-generator(8)\n", description); if (post) fprintf(f, "Before=%s\n", post); r = generator_write_fsck_deps(f, arg_dest, what, where, fstype); if (r < 0) return r; fprintf(f, "\n" "[Mount]\n" "What=%s\n" "Where=%s\n", what, where); if (fstype) fprintf(f, "Type=%s\n", fstype); if (options) fprintf(f, "Options=%s,%s\n", options, rw ? "rw" : "ro"); else fprintf(f, "Options=%s\n", rw ? "rw" : "ro"); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", p); if (post) { lnk = strjoin(arg_dest, "/", post, ".requires/", unit, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(p, lnk) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); } return 0; } static bool path_is_busy(const char *where) { int r; /* already a mountpoint; generators run during reload */ r = path_is_mount_point(where, AT_SYMLINK_FOLLOW); if (r > 0) return false; /* the directory might not exist on a stateless system */ if (r == -ENOENT) return false; if (r < 0) return true; /* not a mountpoint but it contains files */ if (dir_is_empty(where) <= 0) return true; return false; } static int probe_and_add_mount( const char *id, const char *what, const char *where, bool rw, const char *description, const char *post) { _cleanup_blkid_free_probe_ blkid_probe b = NULL; const char *fstype = NULL; int r; assert(id); assert(what); assert(where); assert(description); if (path_is_busy(where)) { log_debug("%s already populated, ignoring.", where); return 0; } /* Let's check the partition type here, so that we know * whether to do LUKS magic. */ errno = 0; b = blkid_new_probe_from_filename(what); if (!b) { if (errno == 0) return log_oom(); return log_error_errno(errno, "Failed to allocate prober: %m"); } blkid_probe_enable_superblocks(b, 1); blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE); errno = 0; r = blkid_do_safeprobe(b); if (r == -2 || r == 1) /* no result or uncertain */ return 0; else if (r != 0) return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what); /* add_mount is OK with fstype being NULL. */ (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); return add_mount( id, what, where, fstype, rw, NULL, description, post); } static int add_swap(const char *path) { _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(path); log_debug("Adding swap: %s", path); r = unit_name_from_path(path, ".swap", &name); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); unit = strjoin(arg_dest, "/", name, NULL); if (!unit) return log_oom(); f = fopen(unit, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", unit); fprintf(f, "# Automatically generated by systemd-gpt-auto-generator\n\n" "[Unit]\n" "Description=Swap Partition\n" "Documentation=man:systemd-gpt-auto-generator(8)\n\n" "[Swap]\n" "What=%s\n", path); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", unit); lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(unit, lnk) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); return 0; } #ifdef ENABLE_EFI static int add_automount( const char *id, const char *what, const char *where, const char *fstype, bool rw, const char *options, const char *description, usec_t timeout) { _cleanup_free_ char *unit = NULL, *lnk = NULL; _cleanup_free_ char *opt, *p = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(id); assert(where); assert(description); if (options) opt = strjoin(options, ",noauto", NULL); else opt = strdup("noauto"); if (!opt) return log_oom(); r = add_mount(id, what, where, fstype, rw, opt, description, NULL); if (r < 0) return r; r = unit_name_from_path(where, ".automount", &unit); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); p = strjoin(arg_dest, "/", unit, NULL); if (!p) return log_oom(); f = fopen(p, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", unit); fprintf(f, "# Automatically generated by systemd-gpt-auto-generator\n\n" "[Unit]\n" "Description=%s\n" "Documentation=man:systemd-gpt-auto-generator(8)\n" "[Automount]\n" "Where=%s\n" "TimeoutIdleSec=%lld\n", description, where, (unsigned long long)timeout / USEC_PER_SEC); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", p); lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/", unit, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(p, lnk) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); return 0; } static int add_boot(const char *what) { _cleanup_blkid_free_probe_ blkid_probe b = NULL; const char *fstype = NULL, *uuid = NULL; sd_id128_t id, type_id; int r; assert(what); if (!is_efi_boot()) { log_debug("Not an EFI boot, ignoring /boot."); return 0; } if (in_initrd()) { log_debug("In initrd, ignoring /boot."); return 0; } if (detect_container() > 0) { log_debug("In a container, ignoring /boot."); return 0; } /* We create an .automount which is not overridden by the .mount from the fstab generator. */ if (fstab_is_mount_point("/boot")) { log_debug("/boot specified in fstab, ignoring."); return 0; } if (path_is_busy("/boot")) { log_debug("/boot already populated, ignoring."); return 0; } r = efi_loader_get_device_part_uuid(&id); if (r == -ENOENT) { log_debug("EFI loader partition unknown."); return 0; } if (r < 0) { log_error_errno(r, "Failed to read ESP partition UUID: %m"); return r; } errno = 0; b = blkid_new_probe_from_filename(what); if (!b) { if (errno == 0) return log_oom(); return log_error_errno(errno, "Failed to allocate prober: %m"); } blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == -2 || r == 1) /* no result or uncertain */ return 0; else if (r != 0) return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what); (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); if (!streq_ptr(fstype, "vfat")) { log_debug("Partition for /boot is not a FAT filesystem, ignoring."); return 0; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &uuid, NULL); if (r != 0) { log_debug_errno(errno, "Partition for /boot does not have a UUID, ignoring."); return 0; } if (sd_id128_from_string(uuid, &type_id) < 0) { log_debug("Partition for /boot does not have a valid UUID, ignoring."); return 0; } if (!sd_id128_equal(type_id, id)) { log_debug("Partition for /boot does not appear to be the partition we are booted from."); return 0; } r = add_automount("boot", what, "/boot", "vfat", true, "umask=0077", "EFI System Partition Automount", 120 * USEC_PER_SEC); return r; } #else static int add_boot(const char *what) { return 0; } #endif static int enumerate_partitions(dev_t devnum) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; _cleanup_udev_device_unref_ struct udev_device *d = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_free_ char *boot = NULL, *home = NULL, *srv = NULL; struct udev_list_entry *first, *item; struct udev_device *parent = NULL; const char *name, *node, *pttype, *devtype; int boot_nr = -1, home_nr = -1, srv_nr = -1; bool home_rw = true, srv_rw = true; blkid_partlist pl; int r, k; dev_t pn; udev = udev_new(); if (!udev) return log_oom(); d = udev_device_new_from_devnum(udev, 'b', devnum); if (!d) return log_oom(); name = udev_device_get_devnode(d); if (!name) name = udev_device_get_syspath(d); if (!name) { log_debug("Device %u:%u does not have a name, ignoring.", major(devnum), minor(devnum)); return 0; } parent = udev_device_get_parent(d); if (!parent) { log_debug("%s: not a partitioned device, ignoring.", name); return 0; } /* Does it have a devtype? */ devtype = udev_device_get_devtype(parent); if (!devtype) { log_debug("%s: parent doesn't have a device type, ignoring.", name); return 0; } /* Is this a disk or a partition? We only care for disks... */ if (!streq(devtype, "disk")) { log_debug("%s: parent isn't a raw disk, ignoring.", name); return 0; } /* Does it have a device node? */ node = udev_device_get_devnode(parent); if (!node) { log_debug("%s: parent device does not have device node, ignoring.", name); return 0; } log_debug("%s: root device %s.", name, node); pn = udev_device_get_devnum(parent); if (major(pn) == 0) return 0; errno = 0; b = blkid_new_probe_from_filename(node); if (!b) { if (errno == 0) return log_oom(); return log_error_errno(errno, "%s: failed to allocate prober: %m", node); } blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == 1) return 0; /* no results */ else if (r == -2) { log_warning("%s: probe gave ambiguous results, ignoring.", node); return 0; } else if (r != 0) return log_error_errno(errno ?: EIO, "%s: failed to probe: %m", node); errno = 0; r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL); if (r != 0) { if (errno == 0) return 0; /* No partition table found. */ return log_error_errno(errno, "%s: failed to determine partition table type: %m", node); } /* We only do this all for GPT... */ if (!streq_ptr(pttype, "gpt")) { log_debug("%s: not a GPT partition table, ignoring.", node); return 0; } errno = 0; pl = blkid_probe_get_partitions(b); if (!pl) { if (errno == 0) return log_oom(); return log_error_errno(errno, "%s: failed to list partitions: %m", node); } e = udev_enumerate_new(udev); if (!e) return log_oom(); r = udev_enumerate_add_match_parent(e, parent); if (r < 0) return log_oom(); r = udev_enumerate_add_match_subsystem(e, "block"); if (r < 0) return log_oom(); r = udev_enumerate_scan_devices(e); if (r < 0) return log_error_errno(r, "%s: failed to enumerate partitions: %m", node); first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *q; unsigned long long flags; const char *stype, *subnode; sd_id128_t type_id; blkid_partition pp; dev_t qn; int nr; q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!q) continue; qn = udev_device_get_devnum(q); if (major(qn) == 0) continue; if (qn == devnum) continue; if (qn == pn) continue; subnode = udev_device_get_devnode(q); if (!subnode) continue; pp = blkid_partlist_devno_to_partition(pl, qn); if (!pp) continue; nr = blkid_partition_get_partno(pp); if (nr < 0) continue; stype = blkid_partition_get_type_string(pp); if (!stype) continue; if (sd_id128_from_string(stype, &type_id) < 0) continue; flags = blkid_partition_get_flags(pp); if (sd_id128_equal(type_id, GPT_SWAP)) { if (flags & GPT_FLAG_NO_AUTO) continue; if (flags & GPT_FLAG_READ_ONLY) { log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode); continue; } k = add_swap(subnode); if (k < 0) r = k; } else if (sd_id128_equal(type_id, GPT_ESP)) { /* We only care for the first /boot partition */ if (boot && nr >= boot_nr) continue; /* Note that we do not honour the "no-auto" * flag for the ESP, as it is often unset, to * hide it from Windows. */ boot_nr = nr; r = free_and_strdup(&boot, subnode); if (r < 0) return log_oom(); } else if (sd_id128_equal(type_id, GPT_HOME)) { if (flags & GPT_FLAG_NO_AUTO) continue; /* We only care for the first /home partition */ if (home && nr >= home_nr) continue; home_nr = nr; home_rw = !(flags & GPT_FLAG_READ_ONLY), r = free_and_strdup(&home, subnode); if (r < 0) return log_oom(); } else if (sd_id128_equal(type_id, GPT_SRV)) { if (flags & GPT_FLAG_NO_AUTO) continue; /* We only care for the first /srv partition */ if (srv && nr >= srv_nr) continue; srv_nr = nr; srv_rw = !(flags & GPT_FLAG_READ_ONLY), r = free_and_strdup(&srv, subnode); if (r < 0) return log_oom(); } } if (boot) { k = add_boot(boot); if (k < 0) r = k; } if (home) { k = probe_and_add_mount("home", home, "/home", home_rw, "Home Partition", SPECIAL_LOCAL_FS_TARGET); if (k < 0) r = k; } if (srv) { k = probe_and_add_mount("srv", srv, "/srv", srv_rw, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET); if (k < 0) r = k; } return r; } static int get_block_device(const char *path, dev_t *dev) { struct stat st; struct statfs sfs; assert(path); assert(dev); /* Get's the block device directly backing a file system. If * the block device is encrypted, returns the device mapper * block device. */ if (lstat(path, &st)) return -errno; if (major(st.st_dev) != 0) { *dev = st.st_dev; return 1; } if (statfs(path, &sfs) < 0) return -errno; if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC)) return btrfs_get_block_device(path, dev); return 0; } static int get_block_device_harder(const char *path, dev_t *dev) { _cleanup_closedir_ DIR *d = NULL; _cleanup_free_ char *p = NULL, *t = NULL; struct dirent *de, *found = NULL; const char *q; unsigned maj, min; dev_t dt; int r; assert(path); assert(dev); /* Gets the backing block device for a file system, and * handles LUKS encrypted file systems, looking for its * immediate parent, if there is one. */ r = get_block_device(path, &dt); if (r <= 0) return r; if (asprintf(&p, "/sys/dev/block/%u:%u/slaves", major(dt), minor(dt)) < 0) return -ENOMEM; d = opendir(p); if (!d) { if (errno == ENOENT) goto fallback; return -errno; } FOREACH_DIRENT_ALL(de, d, return -errno) { if (STR_IN_SET(de->d_name, ".", "..")) continue; if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN)) continue; if (found) /* Don't try to support multiple backing block devices */ goto fallback; found = de; } if (!found) goto fallback; q = strjoina(p, "/", found->d_name, "/dev"); r = read_one_line_file(q, &t); if (r == -ENOENT) goto fallback; if (r < 0) return r; if (sscanf(t, "%u:%u", &maj, &min) != 2) return -EINVAL; if (maj == 0) goto fallback; *dev = makedev(maj, min); return 1; fallback: *dev = dt; return 1; } static int parse_proc_cmdline_item(const char *key, const char *value) { int r; assert(key); if (STR_IN_SET(key, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value) { r = parse_boolean(value); if (r < 0) log_warning("Failed to parse gpt-auto switch \"%s\". Ignoring.", value); else arg_enabled = r; } else if (streq(key, "root") && value) { /* Disable root disk logic if there's a root= value * specified (unless it happens to be "gpt-auto") */ arg_root_enabled = streq(value, "gpt-auto"); } else if (streq(key, "rw") && !value) arg_root_rw = true; else if (streq(key, "ro") && !value) arg_root_rw = false; return 0; } static int add_root_mount(void) { #ifdef ENABLE_EFI int r; if (!is_efi_boot()) { log_debug("Not a EFI boot, not creating root mount."); return 0; } r = efi_loader_get_device_part_uuid(NULL); if (r == -ENOENT) { log_debug("EFI loader partition unknown, exiting."); return 0; } else if (r < 0) return log_error_errno(r, "Failed to read ESP partition UUID: %m"); /* OK, we have an ESP partition, this is fantastic, so let's * wait for a root device to show up. A udev rule will create * the link for us under the right name. */ return add_mount( "root", "/dev/gpt-auto-root", in_initrd() ? "/sysroot" : "/", NULL, arg_root_rw, NULL, "Root Partition", in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET); #else return 0; #endif } static int add_mounts(void) { dev_t devno; int r; r = get_block_device_harder("/", &devno); if (r < 0) return log_error_errno(r, "Failed to determine block device of root file system: %m"); else if (r == 0) { r = get_block_device_harder("/usr", &devno); if (r < 0) return log_error_errno(r, "Failed to determine block device of /usr file system: %m"); else if (r == 0) { log_debug("Neither root nor /usr file system are on a (single) block device."); return 0; } } return enumerate_partitions(devno); } int main(int argc, char *argv[]) { int r = 0; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); return EXIT_FAILURE; } if (argc > 1) arg_dest = argv[3]; log_set_target(LOG_TARGET_SAFE); log_parse_environment(); log_open(); umask(0022); if (detect_container() > 0) { log_debug("In a container, exiting."); return EXIT_SUCCESS; } r = parse_proc_cmdline(parse_proc_cmdline_item); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); if (!arg_enabled) { log_debug("Disabled, exiting."); return EXIT_SUCCESS; } if (arg_root_enabled) r = add_root_mount(); if (!in_initrd()) { int k; k = add_mounts(); if (k < 0) r = k; } return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/hibernate-resume/000077500000000000000000000000001265713322000171075ustar00rootroot00000000000000systemd-229/src/hibernate-resume/Makefile000077700000000000000000000000001265713322000224152../Makefileustar00rootroot00000000000000systemd-229/src/hibernate-resume/hibernate-resume-generator.c000066400000000000000000000055251265713322000245050ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Ivan Shapovalov systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "fstab-util.h" #include "log.h" #include "mkdir.h" #include "proc-cmdline.h" #include "special.h" #include "string-util.h" #include "unit-name.h" #include "util.h" static const char *arg_dest = "/tmp"; static char *arg_resume_dev = NULL; static int parse_proc_cmdline_item(const char *key, const char *value) { if (streq(key, "resume") && value) { free(arg_resume_dev); arg_resume_dev = fstab_node_to_udev_node(value); if (!arg_resume_dev) return log_oom(); } return 0; } static int process_resume(void) { _cleanup_free_ char *name = NULL, *lnk = NULL; int r; if (!arg_resume_dev) return 0; r = unit_name_from_path_instance("systemd-hibernate-resume", arg_resume_dev, ".service", &name); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); lnk = strjoin(arg_dest, "/" SPECIAL_SYSINIT_TARGET ".wants/", name, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-hibernate-resume@.service", lnk) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); return 0; } int main(int argc, char *argv[]) { int r = 0; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); return EXIT_FAILURE; } if (argc > 1) arg_dest = argv[1]; log_set_target(LOG_TARGET_SAFE); log_parse_environment(); log_open(); umask(0022); /* Don't even consider resuming outside of initramfs. */ if (!in_initrd()) return EXIT_SUCCESS; r = parse_proc_cmdline(parse_proc_cmdline_item); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); r = process_resume(); free(arg_resume_dev); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/hibernate-resume/hibernate-resume.c000066400000000000000000000046321265713322000225170ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Ivan Shapovalov systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "fileio.h" #include "log.h" #include "util.h" int main(int argc, char *argv[]) { struct stat st; const char *device; _cleanup_free_ char *major_minor = NULL; int r; if (argc != 2) { log_error("This program expects one argument."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); /* Refuse to run unless we are in an initrd() */ if (!in_initrd()) return EXIT_SUCCESS; device = argv[1]; if (stat(device, &st) < 0) { log_error_errno(errno, "Failed to stat '%s': %m", device); return EXIT_FAILURE; } if (!S_ISBLK(st.st_mode)) { log_error("Resume device '%s' is not a block device.", device); return EXIT_FAILURE; } if (asprintf(&major_minor, "%d:%d", major(st.st_rdev), minor(st.st_rdev)) < 0) { log_oom(); return EXIT_FAILURE; } r = write_string_file("/sys/power/resume", major_minor, WRITE_STRING_FILE_CREATE); if (r < 0) { log_error_errno(r, "Failed to write '%s' to /sys/power/resume: %m", major_minor); return EXIT_FAILURE; } /* * The write above shall not return. * * However, failed resume is a normal condition (may mean that there is * no hibernation image). */ log_info("Could not resume from '%s' (%s).", device, major_minor); return EXIT_SUCCESS; } systemd-229/src/hostname/000077500000000000000000000000001265713322000154665ustar00rootroot00000000000000systemd-229/src/hostname/.gitignore000066400000000000000000000000411265713322000174510ustar00rootroot00000000000000org.freedesktop.hostname1.policy systemd-229/src/hostname/Makefile000077700000000000000000000000001265713322000207742../Makefileustar00rootroot00000000000000systemd-229/src/hostname/hostnamectl.c000066400000000000000000000420711265713322000201570ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-bus.h" #include "sd-id128.h" #include "alloc-util.h" #include "architecture.h" #include "bus-error.h" #include "bus-util.h" #include "hostname-util.h" #include "spawn-polkit-agent.h" #include "util.h" static bool arg_ask_password = true; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static char *arg_host = NULL; static bool arg_transient = false; static bool arg_pretty = false; static bool arg_static = false; static void polkit_agent_open_if_enabled(void) { /* Open the polkit agent as a child process if necessary */ if (!arg_ask_password) return; if (arg_transport != BUS_TRANSPORT_LOCAL) return; polkit_agent_open(); } typedef struct StatusInfo { char *hostname; char *static_hostname; char *pretty_hostname; char *icon_name; char *chassis; char *deployment; char *location; char *kernel_name; char *kernel_release; char *os_pretty_name; char *os_cpe_name; char *virtualization; char *architecture; } StatusInfo; static void print_status_info(StatusInfo *i) { sd_id128_t mid = {}, bid = {}; int r; assert(i); printf(" Static hostname: %s\n", strna(i->static_hostname)); if (!isempty(i->pretty_hostname) && !streq_ptr(i->pretty_hostname, i->static_hostname)) printf(" Pretty hostname: %s\n", i->pretty_hostname); if (!isempty(i->hostname) && !streq_ptr(i->hostname, i->static_hostname)) printf("Transient hostname: %s\n", i->hostname); if (!isempty(i->icon_name)) printf(" Icon name: %s\n", strna(i->icon_name)); if (!isempty(i->chassis)) printf(" Chassis: %s\n", strna(i->chassis)); if (!isempty(i->deployment)) printf(" Deployment: %s\n", i->deployment); if (!isempty(i->location)) printf(" Location: %s\n", i->location); r = sd_id128_get_machine(&mid); if (r >= 0) printf(" Machine ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(mid)); r = sd_id128_get_boot(&bid); if (r >= 0) printf(" Boot ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(bid)); if (!isempty(i->virtualization)) printf(" Virtualization: %s\n", i->virtualization); if (!isempty(i->os_pretty_name)) printf(" Operating System: %s\n", i->os_pretty_name); if (!isempty(i->os_cpe_name)) printf(" CPE OS Name: %s\n", i->os_cpe_name); if (!isempty(i->kernel_name) && !isempty(i->kernel_release)) printf(" Kernel: %s %s\n", i->kernel_name, i->kernel_release); if (!isempty(i->architecture)) printf(" Architecture: %s\n", i->architecture); } static int show_one_name(sd_bus *bus, const char* attr) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *s; int r; r = sd_bus_get_property( bus, "org.freedesktop.hostname1", "/org/freedesktop/hostname1", "org.freedesktop.hostname1", attr, &error, &reply, "s"); if (r < 0) { log_error("Could not get property: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_read(reply, "s", &s); if (r < 0) return bus_log_parse_error(r); printf("%s\n", s); return 0; } static int show_all_names(sd_bus *bus) { StatusInfo info = {}; static const struct bus_properties_map hostname_map[] = { { "Hostname", "s", NULL, offsetof(StatusInfo, hostname) }, { "StaticHostname", "s", NULL, offsetof(StatusInfo, static_hostname) }, { "PrettyHostname", "s", NULL, offsetof(StatusInfo, pretty_hostname) }, { "IconName", "s", NULL, offsetof(StatusInfo, icon_name) }, { "Chassis", "s", NULL, offsetof(StatusInfo, chassis) }, { "Deployment", "s", NULL, offsetof(StatusInfo, deployment) }, { "Location", "s", NULL, offsetof(StatusInfo, location) }, { "KernelName", "s", NULL, offsetof(StatusInfo, kernel_name) }, { "KernelRelease", "s", NULL, offsetof(StatusInfo, kernel_release) }, { "OperatingSystemPrettyName", "s", NULL, offsetof(StatusInfo, os_pretty_name) }, { "OperatingSystemCPEName", "s", NULL, offsetof(StatusInfo, os_cpe_name) }, {} }; static const struct bus_properties_map manager_map[] = { { "Virtualization", "s", NULL, offsetof(StatusInfo, virtualization) }, { "Architecture", "s", NULL, offsetof(StatusInfo, architecture) }, {} }; int r; r = bus_map_all_properties(bus, "org.freedesktop.hostname1", "/org/freedesktop/hostname1", hostname_map, &info); if (r < 0) goto fail; bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", manager_map, &info); print_status_info(&info); fail: free(info.hostname); free(info.static_hostname); free(info.pretty_hostname); free(info.icon_name); free(info.chassis); free(info.deployment); free(info.location); free(info.kernel_name); free(info.kernel_release); free(info.os_pretty_name); free(info.os_cpe_name); free(info.virtualization); free(info.architecture); return r; } static int show_status(sd_bus *bus, char **args, unsigned n) { assert(args); if (arg_pretty || arg_static || arg_transient) { const char *attr; if (!!arg_static + !!arg_pretty + !!arg_transient > 1) { log_error("Cannot query more than one name type at a time"); return -EINVAL; } attr = arg_pretty ? "PrettyHostname" : arg_static ? "StaticHostname" : "Hostname"; return show_one_name(bus, attr); } else return show_all_names(bus); } static int set_simple_string(sd_bus *bus, const char *method, const char *value) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r = 0; polkit_agent_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.hostname1", "/org/freedesktop/hostname1", "org.freedesktop.hostname1", method, &error, NULL, "sb", value, arg_ask_password); if (r < 0) log_error("Could not set property: %s", bus_error_message(&error, -r)); return r; } static int set_hostname(sd_bus *bus, char **args, unsigned n) { _cleanup_free_ char *h = NULL; char *hostname = args[1]; int r; assert(args); assert(n == 2); if (!arg_pretty && !arg_static && !arg_transient) arg_pretty = arg_static = arg_transient = true; if (arg_pretty) { const char *p; /* If the passed hostname is already valid, then * assume the user doesn't know anything about pretty * hostnames, so let's unset the pretty hostname, and * just set the passed hostname as static/dynamic * hostname. */ if (arg_static && hostname_is_valid(hostname, true)) { p = ""; /* maybe get rid of trailing dot */ hostname = hostname_cleanup(hostname); } else { p = h = strdup(hostname); if (!p) return log_oom(); hostname_cleanup(hostname); } r = set_simple_string(bus, "SetPrettyHostname", p); if (r < 0) return r; } if (arg_static) { r = set_simple_string(bus, "SetStaticHostname", hostname); if (r < 0) return r; } if (arg_transient) { r = set_simple_string(bus, "SetHostname", hostname); if (r < 0) return r; } return 0; } static int set_icon_name(sd_bus *bus, char **args, unsigned n) { assert(args); assert(n == 2); return set_simple_string(bus, "SetIconName", args[1]); } static int set_chassis(sd_bus *bus, char **args, unsigned n) { assert(args); assert(n == 2); return set_simple_string(bus, "SetChassis", args[1]); } static int set_deployment(sd_bus *bus, char **args, unsigned n) { assert(args); assert(n == 2); return set_simple_string(bus, "SetDeployment", args[1]); } static int set_location(sd_bus *bus, char **args, unsigned n) { assert(args); assert(n == 2); return set_simple_string(bus, "SetLocation", args[1]); } static void help(void) { printf("%s [OPTIONS...] COMMAND ...\n\n" "Query or change system hostname.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --no-ask-password Do not prompt for password\n" " -H --host=[USER@]HOST Operate on remote host\n" " -M --machine=CONTAINER Operate on local container\n" " --transient Only set transient hostname\n" " --static Only set static hostname\n" " --pretty Only set pretty hostname\n\n" "Commands:\n" " status Show current hostname settings\n" " set-hostname NAME Set system hostname\n" " set-icon-name NAME Set icon name for host\n" " set-chassis NAME Set chassis type for host\n" " set-deployment NAME Set deployment environment for host\n" " set-location NAME Set location for host\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_NO_ASK_PASSWORD, ARG_TRANSIENT, ARG_STATIC, ARG_PRETTY }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "transient", no_argument, NULL, ARG_TRANSIENT }, { "static", no_argument, NULL, ARG_STATIC }, { "pretty", no_argument, NULL, ARG_PRETTY }, { "host", required_argument, NULL, 'H' }, { "machine", required_argument, NULL, 'M' }, { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case 'H': arg_transport = BUS_TRANSPORT_REMOTE; arg_host = optarg; break; case 'M': arg_transport = BUS_TRANSPORT_MACHINE; arg_host = optarg; break; case ARG_TRANSIENT: arg_transient = true; break; case ARG_PRETTY: arg_pretty = true; break; case ARG_STATIC: arg_static = true; break; case ARG_NO_ASK_PASSWORD: arg_ask_password = false; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } static int hostnamectl_main(sd_bus *bus, int argc, char *argv[]) { static const struct { const char* verb; const enum { MORE, LESS, EQUAL } argc_cmp; const int argc; int (* const dispatch)(sd_bus *bus, char **args, unsigned n); } verbs[] = { { "status", LESS, 1, show_status }, { "set-hostname", EQUAL, 2, set_hostname }, { "set-icon-name", EQUAL, 2, set_icon_name }, { "set-chassis", EQUAL, 2, set_chassis }, { "set-deployment", EQUAL, 2, set_deployment }, { "set-location", EQUAL, 2, set_location }, }; int left; unsigned i; assert(argc >= 0); assert(argv); left = argc - optind; if (left <= 0) /* Special rule: no arguments means "status" */ i = 0; else { if (streq(argv[optind], "help")) { help(); return 0; } for (i = 0; i < ELEMENTSOF(verbs); i++) if (streq(argv[optind], verbs[i].verb)) break; if (i >= ELEMENTSOF(verbs)) { log_error("Unknown operation %s", argv[optind]); return -EINVAL; } } switch (verbs[i].argc_cmp) { case EQUAL: if (left != verbs[i].argc) { log_error("Invalid number of arguments."); return -EINVAL; } break; case MORE: if (left < verbs[i].argc) { log_error("Too few arguments."); return -EINVAL; } break; case LESS: if (left > verbs[i].argc) { log_error("Too many arguments."); return -EINVAL; } break; default: assert_not_reached("Unknown comparison operator."); } return verbs[i].dispatch(bus, argv + optind, left); } int main(int argc, char *argv[]) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = bus_connect_transport(arg_transport, arg_host, false, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; } r = hostnamectl_main(bus, argc, argv); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/hostname/hostnamed.c000066400000000000000000000604741265713322000176270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "bus-util.h" #include "def.h" #include "env-util.h" #include "fileio-label.h" #include "hostname-util.h" #include "parse-util.h" #include "path-util.h" #include "selinux-util.h" #include "strv.h" #include "user-util.h" #include "util.h" #include "virt.h" #define VALID_DEPLOYMENT_CHARS (DIGITS LETTERS "-.:") enum { PROP_HOSTNAME, PROP_STATIC_HOSTNAME, PROP_PRETTY_HOSTNAME, PROP_ICON_NAME, PROP_CHASSIS, PROP_DEPLOYMENT, PROP_LOCATION, PROP_KERNEL_NAME, PROP_KERNEL_RELEASE, PROP_KERNEL_VERSION, PROP_OS_PRETTY_NAME, PROP_OS_CPE_NAME, _PROP_MAX }; typedef struct Context { char *data[_PROP_MAX]; Hashmap *polkit_registry; } Context; static void context_reset(Context *c) { int p; assert(c); for (p = 0; p < _PROP_MAX; p++) c->data[p] = mfree(c->data[p]); } static void context_free(Context *c) { assert(c); context_reset(c); bus_verify_polkit_async_registry_free(c->polkit_registry); } static int context_read_data(Context *c) { int r; struct utsname u; assert(c); context_reset(c); assert_se(uname(&u) >= 0); c->data[PROP_KERNEL_NAME] = strdup(u.sysname); c->data[PROP_KERNEL_RELEASE] = strdup(u.release); c->data[PROP_KERNEL_VERSION] = strdup(u.version); if (!c->data[PROP_KERNEL_NAME] || !c->data[PROP_KERNEL_RELEASE] || !c->data[PROP_KERNEL_VERSION]) return -ENOMEM; c->data[PROP_HOSTNAME] = gethostname_malloc(); if (!c->data[PROP_HOSTNAME]) return -ENOMEM; r = read_hostname_config("/etc/hostname", &c->data[PROP_STATIC_HOSTNAME]); if (r < 0 && r != -ENOENT) return r; r = parse_env_file("/etc/machine-info", NEWLINE, "PRETTY_HOSTNAME", &c->data[PROP_PRETTY_HOSTNAME], "ICON_NAME", &c->data[PROP_ICON_NAME], "CHASSIS", &c->data[PROP_CHASSIS], "DEPLOYMENT", &c->data[PROP_DEPLOYMENT], "LOCATION", &c->data[PROP_LOCATION], NULL); if (r < 0 && r != -ENOENT) return r; r = parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME], "CPE_NAME", &c->data[PROP_OS_CPE_NAME], NULL); if (r == -ENOENT) r = parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME], "CPE_NAME", &c->data[PROP_OS_CPE_NAME], NULL); if (r < 0 && r != -ENOENT) return r; return 0; } static bool valid_chassis(const char *chassis) { assert(chassis); return nulstr_contains( "vm\0" "container\0" "desktop\0" "laptop\0" "server\0" "tablet\0" "handset\0" "watch\0" "embedded\0", chassis); } static bool valid_deployment(const char *deployment) { assert(deployment); return in_charset(deployment, VALID_DEPLOYMENT_CHARS); } static const char* fallback_chassis(void) { int r; char *type; unsigned t; int v; v = detect_virtualization(); if (VIRTUALIZATION_IS_VM(v)) return "vm"; if (VIRTUALIZATION_IS_CONTAINER(v)) return "container"; r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type); if (r < 0) goto try_dmi; r = safe_atou(type, &t); free(type); if (r < 0) goto try_dmi; /* We only list the really obvious cases here as the ACPI data * is not really super reliable. * * See the ACPI 5.0 Spec Section 5.2.9.1 for details: * * http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf */ switch(t) { case 1: case 3: case 6: return "desktop"; case 2: return "laptop"; case 4: case 5: case 7: return "server"; case 8: return "tablet"; } try_dmi: r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type); if (r < 0) return NULL; r = safe_atou(type, &t); free(type); if (r < 0) return NULL; /* We only list the really obvious cases here. The DMI data is unreliable enough, so let's not do any additional guesswork on top of that. See the SMBIOS Specification 3.0 section 7.4.1 for details about the values listed here: https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf */ switch (t) { case 0x3: case 0x4: case 0x6: case 0x7: return "desktop"; case 0x8: case 0x9: case 0xA: case 0xE: return "laptop"; case 0xB: return "handset"; case 0x11: case 0x1C: case 0x1D: return "server"; case 0x1E: return "tablet"; } return NULL; } static char* context_fallback_icon_name(Context *c) { const char *chassis; assert(c); if (!isempty(c->data[PROP_CHASSIS])) return strappend("computer-", c->data[PROP_CHASSIS]); chassis = fallback_chassis(); if (chassis) return strappend("computer-", chassis); return strdup("computer"); } static bool hostname_is_useful(const char *hn) { return !isempty(hn) && !is_localhost(hn); } static int context_update_kernel_hostname(Context *c) { const char *static_hn; const char *hn; assert(c); static_hn = c->data[PROP_STATIC_HOSTNAME]; /* /etc/hostname with something other than "localhost" * has the highest preference ... */ if (hostname_is_useful(static_hn)) hn = static_hn; /* ... the transient host name, (ie: DHCP) comes next ... */ else if (!isempty(c->data[PROP_HOSTNAME])) hn = c->data[PROP_HOSTNAME]; /* ... fallback to static "localhost.*" ignored above ... */ else if (!isempty(static_hn)) hn = static_hn; /* ... and the ultimate fallback */ else hn = "localhost"; if (sethostname_idempotent(hn) < 0) return -errno; return 0; } static int context_write_data_static_hostname(Context *c) { assert(c); if (isempty(c->data[PROP_STATIC_HOSTNAME])) { if (unlink("/etc/hostname") < 0) return errno == ENOENT ? 0 : -errno; return 0; } return write_string_file_atomic_label("/etc/hostname", c->data[PROP_STATIC_HOSTNAME]); } static int context_write_data_machine_info(Context *c) { static const char * const name[_PROP_MAX] = { [PROP_PRETTY_HOSTNAME] = "PRETTY_HOSTNAME", [PROP_ICON_NAME] = "ICON_NAME", [PROP_CHASSIS] = "CHASSIS", [PROP_DEPLOYMENT] = "DEPLOYMENT", [PROP_LOCATION] = "LOCATION", }; _cleanup_strv_free_ char **l = NULL; int r, p; assert(c); r = load_env_file(NULL, "/etc/machine-info", NULL, &l); if (r < 0 && r != -ENOENT) return r; for (p = PROP_PRETTY_HOSTNAME; p <= PROP_LOCATION; p++) { _cleanup_free_ char *t = NULL; char **u; assert(name[p]); if (isempty(c->data[p])) { strv_env_unset(l, name[p]); continue; } t = strjoin(name[p], "=", c->data[p], NULL); if (!t) return -ENOMEM; u = strv_env_set(l, t); if (!u) return -ENOMEM; strv_free(l); l = u; } if (strv_isempty(l)) { if (unlink("/etc/machine-info") < 0) return errno == ENOENT ? 0 : -errno; return 0; } return write_env_file_label("/etc/machine-info", l); } static int property_get_icon_name( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_free_ char *n = NULL; Context *c = userdata; const char *name; if (isempty(c->data[PROP_ICON_NAME])) name = n = context_fallback_icon_name(c); else name = c->data[PROP_ICON_NAME]; if (!name) return -ENOMEM; return sd_bus_message_append(reply, "s", name); } static int property_get_chassis( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Context *c = userdata; const char *name; if (isempty(c->data[PROP_CHASSIS])) name = fallback_chassis(); else name = c->data[PROP_CHASSIS]; return sd_bus_message_append(reply, "s", name); } static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) { Context *c = userdata; const char *name; int interactive; char *h; int r; assert(m); assert(c); r = sd_bus_message_read(m, "sb", &name, &interactive); if (r < 0) return r; if (isempty(name)) name = c->data[PROP_STATIC_HOSTNAME]; if (isempty(name)) name = "localhost"; if (!hostname_is_valid(name, false)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name); if (streq_ptr(name, c->data[PROP_HOSTNAME])) return sd_bus_reply_method_return(m, NULL); r = bus_verify_polkit_async( m, CAP_SYS_ADMIN, "org.freedesktop.hostname1.set-hostname", NULL, interactive, UID_INVALID, &c->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ h = strdup(name); if (!h) return -ENOMEM; free(c->data[PROP_HOSTNAME]); c->data[PROP_HOSTNAME] = h; r = context_update_kernel_hostname(c); if (r < 0) { log_error_errno(r, "Failed to set host name: %m"); return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %s", strerror(-r)); } log_info("Changed host name to '%s'", strna(c->data[PROP_HOSTNAME])); (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "Hostname", NULL); return sd_bus_reply_method_return(m, NULL); } static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) { Context *c = userdata; const char *name; int interactive; int r; assert(m); assert(c); r = sd_bus_message_read(m, "sb", &name, &interactive); if (r < 0) return r; if (isempty(name)) name = NULL; if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME])) return sd_bus_reply_method_return(m, NULL); r = bus_verify_polkit_async( m, CAP_SYS_ADMIN, "org.freedesktop.hostname1.set-static-hostname", NULL, interactive, UID_INVALID, &c->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ if (isempty(name)) { c->data[PROP_STATIC_HOSTNAME] = mfree(c->data[PROP_STATIC_HOSTNAME]); } else { char *h; if (!hostname_is_valid(name, false)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name); h = strdup(name); if (!h) return -ENOMEM; free(c->data[PROP_STATIC_HOSTNAME]); c->data[PROP_STATIC_HOSTNAME] = h; } r = context_update_kernel_hostname(c); if (r < 0) { log_error_errno(r, "Failed to set host name: %m"); return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %s", strerror(-r)); } r = context_write_data_static_hostname(c); if (r < 0) { log_error_errno(r, "Failed to write static host name: %m"); return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %s", strerror(-r)); } log_info("Changed static host name to '%s'", strna(c->data[PROP_STATIC_HOSTNAME])); (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "StaticHostname", NULL); return sd_bus_reply_method_return(m, NULL); } static int set_machine_info(Context *c, sd_bus_message *m, int prop, sd_bus_message_handler_t cb, sd_bus_error *error) { int interactive; const char *name; int r; assert(c); assert(m); r = sd_bus_message_read(m, "sb", &name, &interactive); if (r < 0) return r; if (isempty(name)) name = NULL; if (streq_ptr(name, c->data[prop])) return sd_bus_reply_method_return(m, NULL); /* Since the pretty hostname should always be changed at the * same time as the static one, use the same policy action for * both... */ r = bus_verify_polkit_async( m, CAP_SYS_ADMIN, prop == PROP_PRETTY_HOSTNAME ? "org.freedesktop.hostname1.set-static-hostname" : "org.freedesktop.hostname1.set-machine-info", NULL, interactive, UID_INVALID, &c->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ if (isempty(name)) { c->data[prop] = mfree(c->data[prop]); } else { char *h; /* The icon name might ultimately be used as file * name, so better be safe than sorry */ if (prop == PROP_ICON_NAME && !filename_is_valid(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid icon name '%s'", name); if (prop == PROP_PRETTY_HOSTNAME && string_has_cc(name, NULL)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid pretty host name '%s'", name); if (prop == PROP_CHASSIS && !valid_chassis(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid chassis '%s'", name); if (prop == PROP_DEPLOYMENT && !valid_deployment(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid deployment '%s'", name); if (prop == PROP_LOCATION && string_has_cc(name, NULL)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid location '%s'", name); h = strdup(name); if (!h) return -ENOMEM; free(c->data[prop]); c->data[prop] = h; } r = context_write_data_machine_info(c); if (r < 0) { log_error_errno(r, "Failed to write machine info: %m"); return sd_bus_error_set_errnof(error, r, "Failed to write machine info: %s", strerror(-r)); } log_info("Changed %s to '%s'", prop == PROP_PRETTY_HOSTNAME ? "pretty host name" : prop == PROP_DEPLOYMENT ? "deployment" : prop == PROP_LOCATION ? "location" : prop == PROP_CHASSIS ? "chassis" : "icon name", strna(c->data[prop])); (void) sd_bus_emit_properties_changed( sd_bus_message_get_bus(m), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", prop == PROP_PRETTY_HOSTNAME ? "PrettyHostname" : prop == PROP_DEPLOYMENT ? "Deployment" : prop == PROP_LOCATION ? "Location" : prop == PROP_CHASSIS ? "Chassis" : "IconName" , NULL); return sd_bus_reply_method_return(m, NULL); } static int method_set_pretty_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) { return set_machine_info(userdata, m, PROP_PRETTY_HOSTNAME, method_set_pretty_hostname, error); } static int method_set_icon_name(sd_bus_message *m, void *userdata, sd_bus_error *error) { return set_machine_info(userdata, m, PROP_ICON_NAME, method_set_icon_name, error); } static int method_set_chassis(sd_bus_message *m, void *userdata, sd_bus_error *error) { return set_machine_info(userdata, m, PROP_CHASSIS, method_set_chassis, error); } static int method_set_deployment(sd_bus_message *m, void *userdata, sd_bus_error *error) { return set_machine_info(userdata, m, PROP_DEPLOYMENT, method_set_deployment, error); } static int method_set_location(sd_bus_message *m, void *userdata, sd_bus_error *error) { return set_machine_info(userdata, m, PROP_LOCATION, method_set_location, error); } static const sd_bus_vtable hostname_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Hostname", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("StaticHostname", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_STATIC_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("PrettyHostname", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_PRETTY_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IconName", "s", property_get_icon_name, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Chassis", "s", property_get_chassis, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Deployment", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_DEPLOYMENT, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Location", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_LOCATION, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("KernelName", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_KERNEL_NAME, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("KernelRelease", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_KERNEL_RELEASE, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("KernelVersion", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_KERNEL_VERSION, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("OperatingSystemPrettyName", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_OS_PRETTY_NAME, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("OperatingSystemCPEName", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_OS_CPE_NAME, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_METHOD("SetHostname", "sb", NULL, method_set_hostname, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetStaticHostname", "sb", NULL, method_set_static_hostname, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetPrettyHostname", "sb", NULL, method_set_pretty_hostname, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetIconName", "sb", NULL, method_set_icon_name, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetChassis", "sb", NULL, method_set_chassis, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetDeployment", "sb", NULL, method_set_deployment, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetLocation", "sb", NULL, method_set_location, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END, }; static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; assert(c); assert(event); assert(_bus); r = sd_bus_default_system(&bus); if (r < 0) return log_error_errno(r, "Failed to get system bus connection: %m"); r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", hostname_vtable, c); if (r < 0) return log_error_errno(r, "Failed to register object: %m"); r = sd_bus_request_name(bus, "org.freedesktop.hostname1", 0); if (r < 0) return log_error_errno(r, "Failed to register name: %m"); r = sd_bus_attach_event(bus, event, 0); if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop: %m"); *_bus = bus; bus = NULL; return 0; } int main(int argc, char *argv[]) { Context context = {}; _cleanup_(sd_event_unrefp) sd_event *event = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); mac_selinux_init("/etc"); if (argc != 1) { log_error("This program takes no arguments."); r = -EINVAL; goto finish; } r = sd_event_default(&event); if (r < 0) { log_error_errno(r, "Failed to allocate event loop: %m"); goto finish; } sd_event_set_watchdog(event, true); r = connect_bus(&context, event, &bus); if (r < 0) goto finish; r = context_read_data(&context); if (r < 0) { log_error_errno(r, "Failed to read hostname and machine information: %m"); goto finish; } r = bus_event_loop_with_idle(event, bus, "org.freedesktop.hostname1", DEFAULT_EXIT_USEC, NULL, NULL); if (r < 0) { log_error_errno(r, "Failed to run event loop: %m"); goto finish; } finish: context_free(&context); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/hostname/org.freedesktop.hostname1.conf000066400000000000000000000016631265713322000233420ustar00rootroot00000000000000 systemd-229/src/hostname/org.freedesktop.hostname1.policy.in000066400000000000000000000045361265713322000243230ustar00rootroot00000000000000 The systemd Project http://www.freedesktop.org/wiki/Software/systemd <_description>Set host name <_message>Authentication is required to set the local host name. auth_admin_keep auth_admin_keep auth_admin_keep <_description>Set static host name <_message>Authentication is required to set the statically configured local host name, as well as the pretty host name. auth_admin_keep auth_admin_keep auth_admin_keep org.freedesktop.hostname1.set-hostname org.freedesktop.hostname1.set-machine-info <_description>Set machine information <_message>Authentication is required to set local machine information. auth_admin_keep auth_admin_keep auth_admin_keep systemd-229/src/hostname/org.freedesktop.hostname1.service000066400000000000000000000006431265713322000240520ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] Name=org.freedesktop.hostname1 Exec=/bin/false User=root SystemdService=dbus-org.freedesktop.hostname1.service systemd-229/src/hwdb/000077500000000000000000000000001265713322000145745ustar00rootroot00000000000000systemd-229/src/hwdb/Makefile000077700000000000000000000000001265713322000201022../Makefileustar00rootroot00000000000000systemd-229/src/hwdb/hwdb.c000066400000000000000000000576631265713322000157050ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "conf-files.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "hwdb-internal.h" #include "hwdb-util.h" #include "mkdir.h" #include "strbuf.h" #include "string-util.h" #include "strv.h" #include "util.h" #include "verbs.h" /* * Generic udev properties, key/value database based on modalias strings. * Uses a Patricia/radix trie to index all matches for efficient lookup. */ static const char *arg_hwdb_bin_dir = "/etc/udev"; static const char *arg_root = ""; static const char * const conf_file_dirs[] = { "/etc/udev/hwdb.d", UDEVLIBEXECDIR "/hwdb.d", NULL }; /* in-memory trie objects */ struct trie { struct trie_node *root; struct strbuf *strings; size_t nodes_count; size_t children_count; size_t values_count; }; struct trie_node { /* prefix, common part for all children of this node */ size_t prefix_off; /* sorted array of pointers to children nodes */ struct trie_child_entry *children; uint8_t children_count; /* sorted array of key/value pairs */ struct trie_value_entry *values; size_t values_count; }; /* children array item with char (0-255) index */ struct trie_child_entry { uint8_t c; struct trie_node *child; }; /* value array item with key/value pairs */ struct trie_value_entry { size_t key_off; size_t value_off; }; static int trie_children_cmp(const void *v1, const void *v2) { const struct trie_child_entry *n1 = v1; const struct trie_child_entry *n2 = v2; return n1->c - n2->c; } static int node_add_child(struct trie *trie, struct trie_node *node, struct trie_node *node_child, uint8_t c) { struct trie_child_entry *child; /* extend array, add new entry, sort for bisection */ child = realloc(node->children, (node->children_count + 1) * sizeof(struct trie_child_entry)); if (!child) return -ENOMEM; node->children = child; trie->children_count++; node->children[node->children_count].c = c; node->children[node->children_count].child = node_child; node->children_count++; qsort(node->children, node->children_count, sizeof(struct trie_child_entry), trie_children_cmp); trie->nodes_count++; return 0; } static struct trie_node *node_lookup(const struct trie_node *node, uint8_t c) { struct trie_child_entry *child; struct trie_child_entry search; search.c = c; child = bsearch(&search, node->children, node->children_count, sizeof(struct trie_child_entry), trie_children_cmp); if (child) return child->child; return NULL; } static void trie_node_cleanup(struct trie_node *node) { size_t i; for (i = 0; i < node->children_count; i++) trie_node_cleanup(node->children[i].child); free(node->children); free(node->values); free(node); } static void trie_free(struct trie *trie) { if (!trie) return; if (trie->root) trie_node_cleanup(trie->root); strbuf_cleanup(trie->strings); free(trie); } DEFINE_TRIVIAL_CLEANUP_FUNC(struct trie*, trie_free); static int trie_values_cmp(const void *v1, const void *v2, void *arg) { const struct trie_value_entry *val1 = v1; const struct trie_value_entry *val2 = v2; struct trie *trie = arg; return strcmp(trie->strings->buf + val1->key_off, trie->strings->buf + val2->key_off); } static int trie_node_add_value(struct trie *trie, struct trie_node *node, const char *key, const char *value) { ssize_t k, v; struct trie_value_entry *val; k = strbuf_add_string(trie->strings, key, strlen(key)); if (k < 0) return k; v = strbuf_add_string(trie->strings, value, strlen(value)); if (v < 0) return v; if (node->values_count) { struct trie_value_entry search = { .key_off = k, .value_off = v, }; val = xbsearch_r(&search, node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie); if (val) { /* replace existing earlier key with new value */ val->value_off = v; return 0; } } /* extend array, add new entry, sort for bisection */ val = realloc(node->values, (node->values_count + 1) * sizeof(struct trie_value_entry)); if (!val) return -ENOMEM; trie->values_count++; node->values = val; node->values[node->values_count].key_off = k; node->values[node->values_count].value_off = v; node->values_count++; qsort_r(node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie); return 0; } static int trie_insert(struct trie *trie, struct trie_node *node, const char *search, const char *key, const char *value) { size_t i = 0; int err = 0; for (;;) { size_t p; uint8_t c; struct trie_node *child; for (p = 0; (c = trie->strings->buf[node->prefix_off + p]); p++) { _cleanup_free_ char *s = NULL; ssize_t off; _cleanup_free_ struct trie_node *new_child = NULL; if (c == search[i + p]) continue; /* split node */ new_child = new0(struct trie_node, 1); if (!new_child) return -ENOMEM; /* move values from parent to child */ new_child->prefix_off = node->prefix_off + p+1; new_child->children = node->children; new_child->children_count = node->children_count; new_child->values = node->values; new_child->values_count = node->values_count; /* update parent; use strdup() because the source gets realloc()d */ s = strndup(trie->strings->buf + node->prefix_off, p); if (!s) return -ENOMEM; off = strbuf_add_string(trie->strings, s, p); if (off < 0) return off; node->prefix_off = off; node->children = NULL; node->children_count = 0; node->values = NULL; node->values_count = 0; err = node_add_child(trie, node, new_child, c); if (err < 0) return err; new_child = NULL; /* avoid cleanup */ break; } i += p; c = search[i]; if (c == '\0') return trie_node_add_value(trie, node, key, value); child = node_lookup(node, c); if (!child) { ssize_t off; /* new child */ child = new0(struct trie_node, 1); if (!child) return -ENOMEM; off = strbuf_add_string(trie->strings, search + i+1, strlen(search + i+1)); if (off < 0) { free(child); return off; } child->prefix_off = off; err = node_add_child(trie, node, child, c); if (err < 0) { free(child); return err; } return trie_node_add_value(trie, child, key, value); } node = child; i++; } } struct trie_f { FILE *f; struct trie *trie; uint64_t strings_off; uint64_t nodes_count; uint64_t children_count; uint64_t values_count; }; /* calculate the storage space for the nodes, children arrays, value arrays */ static void trie_store_nodes_size(struct trie_f *trie, struct trie_node *node) { uint64_t i; for (i = 0; i < node->children_count; i++) trie_store_nodes_size(trie, node->children[i].child); trie->strings_off += sizeof(struct trie_node_f); for (i = 0; i < node->children_count; i++) trie->strings_off += sizeof(struct trie_child_entry_f); for (i = 0; i < node->values_count; i++) trie->strings_off += sizeof(struct trie_value_entry_f); } static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node) { uint64_t i; struct trie_node_f n = { .prefix_off = htole64(trie->strings_off + node->prefix_off), .children_count = node->children_count, .values_count = htole64(node->values_count), }; struct trie_child_entry_f *children = NULL; int64_t node_off; if (node->children_count) { children = new0(struct trie_child_entry_f, node->children_count); if (!children) return -ENOMEM; } /* post-order recursion */ for (i = 0; i < node->children_count; i++) { int64_t child_off; child_off = trie_store_nodes(trie, node->children[i].child); if (child_off < 0) { free(children); return child_off; } children[i].c = node->children[i].c; children[i].child_off = htole64(child_off); } /* write node */ node_off = ftello(trie->f); fwrite(&n, sizeof(struct trie_node_f), 1, trie->f); trie->nodes_count++; /* append children array */ if (node->children_count) { fwrite(children, sizeof(struct trie_child_entry_f), node->children_count, trie->f); trie->children_count += node->children_count; free(children); } /* append values array */ for (i = 0; i < node->values_count; i++) { struct trie_value_entry_f v = { .key_off = htole64(trie->strings_off + node->values[i].key_off), .value_off = htole64(trie->strings_off + node->values[i].value_off), }; fwrite(&v, sizeof(struct trie_value_entry_f), 1, trie->f); trie->values_count++; } return node_off; } static int trie_store(struct trie *trie, const char *filename) { struct trie_f t = { .trie = trie, }; _cleanup_free_ char *filename_tmp = NULL; int64_t pos; int64_t root_off; int64_t size; struct trie_header_f h = { .signature = HWDB_SIG, .tool_version = htole64(atoi(VERSION)), .header_size = htole64(sizeof(struct trie_header_f)), .node_size = htole64(sizeof(struct trie_node_f)), .child_entry_size = htole64(sizeof(struct trie_child_entry_f)), .value_entry_size = htole64(sizeof(struct trie_value_entry_f)), }; int err; /* calculate size of header, nodes, children entries, value entries */ t.strings_off = sizeof(struct trie_header_f); trie_store_nodes_size(&t, trie->root); err = fopen_temporary(filename , &t.f, &filename_tmp); if (err < 0) return err; fchmod(fileno(t.f), 0444); /* write nodes */ err = fseeko(t.f, sizeof(struct trie_header_f), SEEK_SET); if (err < 0) { fclose(t.f); unlink_noerrno(filename_tmp); return -errno; } root_off = trie_store_nodes(&t, trie->root); h.nodes_root_off = htole64(root_off); pos = ftello(t.f); h.nodes_len = htole64(pos - sizeof(struct trie_header_f)); /* write string buffer */ fwrite(trie->strings->buf, trie->strings->len, 1, t.f); h.strings_len = htole64(trie->strings->len); /* write header */ size = ftello(t.f); h.file_size = htole64(size); err = fseeko(t.f, 0, SEEK_SET); if (err < 0) { fclose(t.f); unlink_noerrno(filename_tmp); return -errno; } fwrite(&h, sizeof(struct trie_header_f), 1, t.f); err = ferror(t.f); if (err) err = -errno; fclose(t.f); if (err < 0 || rename(filename_tmp, filename) < 0) { unlink_noerrno(filename_tmp); return err < 0 ? err : -errno; } log_debug("=== trie on-disk ==="); log_debug("size: %8"PRIi64" bytes", size); log_debug("header: %8zu bytes", sizeof(struct trie_header_f)); log_debug("nodes: %8"PRIu64" bytes (%8"PRIu64")", t.nodes_count * sizeof(struct trie_node_f), t.nodes_count); log_debug("child pointers: %8"PRIu64" bytes (%8"PRIu64")", t.children_count * sizeof(struct trie_child_entry_f), t.children_count); log_debug("value pointers: %8"PRIu64" bytes (%8"PRIu64")", t.values_count * sizeof(struct trie_value_entry_f), t.values_count); log_debug("string store: %8zu bytes", trie->strings->len); log_debug("strings start: %8"PRIu64, t.strings_off); return 0; } static int insert_data(struct trie *trie, char **match_list, char *line, const char *filename) { char *value, **entry; value = strchr(line, '='); if (!value) { log_error("Error, key/value pair expected but got '%s' in '%s':", line, filename); return -EINVAL; } value[0] = '\0'; value++; /* libudev requires properties to start with a space */ while (isblank(line[0]) && isblank(line[1])) line++; if (line[0] == '\0' || value[0] == '\0') { log_error("Error, empty key or value '%s' in '%s':", line, filename); return -EINVAL; } STRV_FOREACH(entry, match_list) trie_insert(trie, trie->root, *entry, line, value); return 0; } static int import_file(struct trie *trie, const char *filename) { enum { HW_NONE, HW_MATCH, HW_DATA, } state = HW_NONE; _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; _cleanup_strv_free_ char **match_list = NULL; char *match = NULL; int r; f = fopen(filename, "re"); if (!f) return -errno; while (fgets(line, sizeof(line), f)) { size_t len; char *pos; /* comment line */ if (line[0] == '#') continue; /* strip trailing comment */ pos = strchr(line, '#'); if (pos) pos[0] = '\0'; /* strip trailing whitespace */ len = strlen(line); while (len > 0 && isspace(line[len-1])) len--; line[len] = '\0'; switch (state) { case HW_NONE: if (len == 0) break; if (line[0] == ' ') { log_error("Error, MATCH expected but got '%s' in '%s':", line, filename); break; } /* start of record, first match */ state = HW_MATCH; match = strdup(line); if (!match) return -ENOMEM; r = strv_consume(&match_list, match); if (r < 0) return r; break; case HW_MATCH: if (len == 0) { log_error("Error, DATA expected but got empty line in '%s':", filename); state = HW_NONE; strv_clear(match_list); break; } /* another match */ if (line[0] != ' ') { match = strdup(line); if (!match) return -ENOMEM; r = strv_consume(&match_list, match); if (r < 0) return r; break; } /* first data */ state = HW_DATA; insert_data(trie, match_list, line, filename); break; case HW_DATA: /* end of record */ if (len == 0) { state = HW_NONE; strv_clear(match_list); break; } if (line[0] != ' ') { log_error("Error, DATA expected but got '%s' in '%s':", line, filename); state = HW_NONE; strv_clear(match_list); break; } insert_data(trie, match_list, line, filename); break; }; } return 0; } static int hwdb_query(int argc, char *argv[], void *userdata) { _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; const char *key, *value; const char *modalias; int r; assert(argc >= 2); assert(argv); modalias = argv[1]; r = sd_hwdb_new(&hwdb); if (r < 0) return r; SD_HWDB_FOREACH_PROPERTY(hwdb, modalias, key, value) printf("%s=%s\n", key, value); return 0; } static int hwdb_update(int argc, char *argv[], void *userdata) { _cleanup_free_ char *hwdb_bin = NULL; _cleanup_(trie_freep) struct trie *trie = NULL; char **files, **f; int r; trie = new0(struct trie, 1); if (!trie) return -ENOMEM; /* string store */ trie->strings = strbuf_new(); if (!trie->strings) return -ENOMEM; /* index */ trie->root = new0(struct trie_node, 1); if (!trie->root) return -ENOMEM; trie->nodes_count++; r = conf_files_list_strv(&files, ".hwdb", arg_root, conf_file_dirs); if (r < 0) return log_error_errno(r, "failed to enumerate hwdb files: %m"); STRV_FOREACH(f, files) { log_debug("reading file '%s'", *f); import_file(trie, *f); } strv_free(files); strbuf_complete(trie->strings); log_debug("=== trie in-memory ==="); log_debug("nodes: %8zu bytes (%8zu)", trie->nodes_count * sizeof(struct trie_node), trie->nodes_count); log_debug("children arrays: %8zu bytes (%8zu)", trie->children_count * sizeof(struct trie_child_entry), trie->children_count); log_debug("values arrays: %8zu bytes (%8zu)", trie->values_count * sizeof(struct trie_value_entry), trie->values_count); log_debug("strings: %8zu bytes", trie->strings->len); log_debug("strings incoming: %8zu bytes (%8zu)", trie->strings->in_len, trie->strings->in_count); log_debug("strings dedup'ed: %8zu bytes (%8zu)", trie->strings->dedup_len, trie->strings->dedup_count); hwdb_bin = strjoin(arg_root, "/", arg_hwdb_bin_dir, "/hwdb.bin", NULL); if (!hwdb_bin) return -ENOMEM; mkdir_parents(hwdb_bin, 0755); r = trie_store(trie, hwdb_bin); if (r < 0) return log_error_errno(r, "Failure writing database %s: %m", hwdb_bin); return 0; } static void help(void) { printf("Usage: %s OPTIONS COMMAND\n\n" "Update or query the hardware database.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --usr Generate in " UDEVLIBEXECDIR " instead of /etc/udev\n" " -r --root=PATH Alternative root path in the filesystem\n\n" "Commands:\n" " update Update the hwdb database\n" " query MODALIAS Query database and print result\n", program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_USR, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "usr", no_argument, NULL, ARG_USR }, { "root", required_argument, NULL, 'r' }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "ut:r:h", options, NULL)) >= 0) { switch(c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_USR: arg_hwdb_bin_dir = UDEVLIBEXECDIR; break; case 'r': arg_root = optarg; break; case '?': return -EINVAL; default: assert_not_reached("Unknown option"); } } return 1; } static int hwdb_main(int argc, char *argv[]) { const Verb verbs[] = { { "update", 1, 1, 0, hwdb_update }, { "query", 2, 2, 0, hwdb_query }, {}, }; return dispatch_verb(argc, argv, verbs, NULL); } int main (int argc, char *argv[]) { int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = hwdb_main(argc, argv); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/import/000077500000000000000000000000001265713322000151625ustar00rootroot00000000000000systemd-229/src/import/.gitignore000066400000000000000000000000401265713322000171440ustar00rootroot00000000000000/org.freedesktop.import1.policy systemd-229/src/import/Makefile000077700000000000000000000000001265713322000204702../Makefileustar00rootroot00000000000000systemd-229/src/import/aufs-util.c000066400000000000000000000040241265713322000172370ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "aufs-util.h" #include "rm-rf.h" #include "string-util.h" #include "util.h" static int nftw_cb( const char *fpath, const struct stat *sb, int flag, struct FTW *ftwbuf) { const char *fn, *original; char *p; int r; fn = fpath + ftwbuf->base; /* We remove all whiteout files, and all whiteouts */ original = startswith(fn, ".wh."); if (!original) return FTW_CONTINUE; log_debug("Removing whiteout indicator %s.", fpath); r = rm_rf(fpath, REMOVE_ROOT|REMOVE_PHYSICAL); if (r < 0) return FTW_STOP; if (!startswith(fn, ".wh..wh.")) { p = alloca(ftwbuf->base + strlen(original)); strcpy(mempcpy(p, fpath, ftwbuf->base), original); log_debug("Removing deleted file %s.", p); r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL); if (r < 0) return FTW_STOP; } return FTW_CONTINUE; } int aufs_resolve(const char *path) { int r; errno = 0; r = nftw(path, nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); if (r == FTW_STOP) return errno > 0 ? -errno : -EIO; return 0; } systemd-229/src/import/aufs-util.h000066400000000000000000000014011265713322000172400ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int aufs_resolve(const char *path); systemd-229/src/import/curl-util.c000066400000000000000000000273541265713322000172610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "curl-util.h" #include "fd-util.h" #include "string-util.h" static void curl_glue_check_finished(CurlGlue *g) { CURLMsg *msg; int k = 0; assert(g); msg = curl_multi_info_read(g->curl, &k); if (!msg) return; if (msg->msg != CURLMSG_DONE) return; if (g->on_finished) g->on_finished(g, msg->easy_handle, msg->data.result); } static int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) { CurlGlue *g = userdata; int action, k = 0, translated_fd; assert(s); assert(g); translated_fd = PTR_TO_FD(hashmap_get(g->translate_fds, FD_TO_PTR(fd))); if ((revents & (EPOLLIN|EPOLLOUT)) == (EPOLLIN|EPOLLOUT)) action = CURL_POLL_INOUT; else if (revents & EPOLLIN) action = CURL_POLL_IN; else if (revents & EPOLLOUT) action = CURL_POLL_OUT; else action = 0; if (curl_multi_socket_action(g->curl, translated_fd, action, &k) < 0) { log_debug("Failed to propagate IO event."); return -EINVAL; } curl_glue_check_finished(g); return 0; } static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, void *userdata, void *socketp) { sd_event_source *io; CurlGlue *g = userdata; uint32_t events = 0; int r; assert(curl); assert(g); io = hashmap_get(g->ios, FD_TO_PTR(s)); if (action == CURL_POLL_REMOVE) { if (io) { int fd; fd = sd_event_source_get_io_fd(io); assert(fd >= 0); sd_event_source_set_enabled(io, SD_EVENT_OFF); sd_event_source_unref(io); hashmap_remove(g->ios, FD_TO_PTR(s)); hashmap_remove(g->translate_fds, FD_TO_PTR(fd)); safe_close(fd); } return 0; } r = hashmap_ensure_allocated(&g->ios, &trivial_hash_ops); if (r < 0) { log_oom(); return -1; } r = hashmap_ensure_allocated(&g->translate_fds, &trivial_hash_ops); if (r < 0) { log_oom(); return -1; } if (action == CURL_POLL_IN) events = EPOLLIN; else if (action == CURL_POLL_OUT) events = EPOLLOUT; else if (action == CURL_POLL_INOUT) events = EPOLLIN|EPOLLOUT; if (io) { if (sd_event_source_set_io_events(io, events) < 0) return -1; if (sd_event_source_set_enabled(io, SD_EVENT_ON) < 0) return -1; } else { _cleanup_close_ int fd = -1; /* When curl needs to remove an fd from us it closes * the fd first, and only then calls into us. This is * nasty, since we cannot pass the fd on to epoll() * anymore. Hence, duplicate the fds here, and keep a * copy for epoll which we control after use. */ fd = fcntl(s, F_DUPFD_CLOEXEC, 3); if (fd < 0) return -1; if (sd_event_add_io(g->event, &io, fd, events, curl_glue_on_io, g) < 0) return -1; sd_event_source_set_description(io, "curl-io"); r = hashmap_put(g->ios, FD_TO_PTR(s), io); if (r < 0) { log_oom(); sd_event_source_unref(io); return -1; } r = hashmap_put(g->translate_fds, FD_TO_PTR(fd), FD_TO_PTR(s)); if (r < 0) { log_oom(); hashmap_remove(g->ios, FD_TO_PTR(s)); sd_event_source_unref(io); return -1; } fd = -1; } return 0; } static int curl_glue_on_timer(sd_event_source *s, uint64_t usec, void *userdata) { CurlGlue *g = userdata; int k = 0; assert(s); assert(g); if (curl_multi_socket_action(g->curl, CURL_SOCKET_TIMEOUT, 0, &k) != CURLM_OK) { log_debug("Failed to propagate timeout."); return -EINVAL; } curl_glue_check_finished(g); return 0; } static int curl_glue_timer_callback(CURLM *curl, long timeout_ms, void *userdata) { CurlGlue *g = userdata; usec_t usec; assert(curl); assert(g); if (timeout_ms < 0) { if (g->timer) { if (sd_event_source_set_enabled(g->timer, SD_EVENT_OFF) < 0) return -1; } return 0; } usec = now(clock_boottime_or_monotonic()) + (usec_t) timeout_ms * USEC_PER_MSEC + USEC_PER_MSEC - 1; if (g->timer) { if (sd_event_source_set_time(g->timer, usec) < 0) return -1; if (sd_event_source_set_enabled(g->timer, SD_EVENT_ONESHOT) < 0) return -1; } else { if (sd_event_add_time(g->event, &g->timer, clock_boottime_or_monotonic(), usec, 0, curl_glue_on_timer, g) < 0) return -1; sd_event_source_set_description(g->timer, "curl-timer"); } return 0; } CurlGlue *curl_glue_unref(CurlGlue *g) { sd_event_source *io; if (!g) return NULL; if (g->curl) curl_multi_cleanup(g->curl); while ((io = hashmap_steal_first(g->ios))) { int fd; fd = sd_event_source_get_io_fd(io); assert(fd >= 0); hashmap_remove(g->translate_fds, FD_TO_PTR(fd)); safe_close(fd); sd_event_source_unref(io); } hashmap_free(g->ios); sd_event_source_unref(g->timer); sd_event_unref(g->event); free(g); return NULL; } int curl_glue_new(CurlGlue **glue, sd_event *event) { _cleanup_(curl_glue_unrefp) CurlGlue *g = NULL; int r; g = new0(CurlGlue, 1); if (!g) return -ENOMEM; if (event) g->event = sd_event_ref(event); else { r = sd_event_default(&g->event); if (r < 0) return r; } g->curl = curl_multi_init(); if (!g->curl) return -ENOMEM; if (curl_multi_setopt(g->curl, CURLMOPT_SOCKETDATA, g) != CURLM_OK) return -EINVAL; if (curl_multi_setopt(g->curl, CURLMOPT_SOCKETFUNCTION, curl_glue_socket_callback) != CURLM_OK) return -EINVAL; if (curl_multi_setopt(g->curl, CURLMOPT_TIMERDATA, g) != CURLM_OK) return -EINVAL; if (curl_multi_setopt(g->curl, CURLMOPT_TIMERFUNCTION, curl_glue_timer_callback) != CURLM_OK) return -EINVAL; *glue = g; g = NULL; return 0; } int curl_glue_make(CURL **ret, const char *url, void *userdata) { const char *useragent; CURL *c; int r; assert(ret); assert(url); c = curl_easy_init(); if (!c) return -ENOMEM; /* curl_easy_setopt(c, CURLOPT_VERBOSE, 1L); */ if (curl_easy_setopt(c, CURLOPT_URL, url) != CURLE_OK) { r = -EIO; goto fail; } if (curl_easy_setopt(c, CURLOPT_PRIVATE, userdata) != CURLE_OK) { r = -EIO; goto fail; } useragent = strjoina(program_invocation_short_name, "/" PACKAGE_VERSION); if (curl_easy_setopt(c, CURLOPT_USERAGENT, useragent) != CURLE_OK) { r = -EIO; goto fail; } if (curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK) { r = -EIO; goto fail; } *ret = c; return 0; fail: curl_easy_cleanup(c); return r; } int curl_glue_add(CurlGlue *g, CURL *c) { assert(g); assert(c); if (curl_multi_add_handle(g->curl, c) != CURLM_OK) return -EIO; return 0; } void curl_glue_remove_and_free(CurlGlue *g, CURL *c) { assert(g); if (!c) return; if (g->curl) curl_multi_remove_handle(g->curl, c); curl_easy_cleanup(c); } struct curl_slist *curl_slist_new(const char *first, ...) { struct curl_slist *l; va_list ap; if (!first) return NULL; l = curl_slist_append(NULL, first); if (!l) return NULL; va_start(ap, first); for (;;) { struct curl_slist *n; const char *i; i = va_arg(ap, const char*); if (!i) break; n = curl_slist_append(l, i); if (!n) { va_end(ap); curl_slist_free_all(l); return NULL; } l = n; } va_end(ap); return l; } int curl_header_strdup(const void *contents, size_t sz, const char *field, char **value) { const char *p = contents; size_t l; char *s; l = strlen(field); if (sz < l) return 0; if (memcmp(p, field, l) != 0) return 0; p += l; sz -= l; if (memchr(p, 0, sz)) return 0; /* Skip over preceeding whitespace */ while (sz > 0 && strchr(WHITESPACE, p[0])) { p++; sz--; } /* Truncate trailing whitespace*/ while (sz > 0 && strchr(WHITESPACE, p[sz-1])) sz--; s = strndup(p, sz); if (!s) return -ENOMEM; *value = s; return 1; } int curl_parse_http_time(const char *t, usec_t *ret) { const char *e; locale_t loc; struct tm tm; time_t v; assert(t); assert(ret); loc = newlocale(LC_TIME_MASK, "C", (locale_t) 0); if (loc == (locale_t) 0) return -errno; /* RFC822 */ e = strptime_l(t, "%a, %d %b %Y %H:%M:%S %Z", &tm, loc); if (!e || *e != 0) /* RFC 850 */ e = strptime_l(t, "%A, %d-%b-%y %H:%M:%S %Z", &tm, loc); if (!e || *e != 0) /* ANSI C */ e = strptime_l(t, "%a %b %d %H:%M:%S %Y", &tm, loc); freelocale(loc); if (!e || *e != 0) return -EINVAL; v = timegm(&tm); if (v == (time_t) -1) return -EINVAL; *ret = (usec_t) v * USEC_PER_SEC; return 0; } systemd-229/src/import/curl-util.h000066400000000000000000000033441265713322000172570ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-event.h" #include "hashmap.h" typedef struct CurlGlue CurlGlue; struct CurlGlue { sd_event *event; CURLM *curl; sd_event_source *timer; Hashmap *ios; Hashmap *translate_fds; void (*on_finished)(CurlGlue *g, CURL *curl, CURLcode code); void *userdata; }; int curl_glue_new(CurlGlue **glue, sd_event *event); CurlGlue* curl_glue_unref(CurlGlue *glue); DEFINE_TRIVIAL_CLEANUP_FUNC(CurlGlue*, curl_glue_unref); int curl_glue_make(CURL **ret, const char *url, void *userdata); int curl_glue_add(CurlGlue *g, CURL *c); void curl_glue_remove_and_free(CurlGlue *g, CURL *c); struct curl_slist *curl_slist_new(const char *first, ...) _sentinel_; int curl_header_strdup(const void *contents, size_t sz, const char *field, char **value); int curl_parse_http_time(const char *t, usec_t *ret); DEFINE_TRIVIAL_CLEANUP_FUNC(CURL*, curl_easy_cleanup); DEFINE_TRIVIAL_CLEANUP_FUNC(struct curl_slist*, curl_slist_free_all); systemd-229/src/import/export-raw.c000066400000000000000000000225341265713322000174440ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include /* When we include libgen.h because we need dirname() we immediately * undefine basename() since libgen.h defines it as a macro to the POSIX * version which is really broken. We prefer GNU basename(). */ #include #undef basename #include "sd-daemon.h" #include "alloc-util.h" #include "btrfs-util.h" #include "copy.h" #include "export-raw.h" #include "fd-util.h" #include "fileio.h" #include "import-common.h" #include "ratelimit.h" #include "string-util.h" #include "util.h" #define COPY_BUFFER_SIZE (16*1024) struct RawExport { sd_event *event; RawExportFinished on_finished; void *userdata; char *path; int input_fd; int output_fd; ImportCompress compress; sd_event_source *output_event_source; void *buffer; size_t buffer_size; size_t buffer_allocated; uint64_t written_compressed; uint64_t written_uncompressed; unsigned last_percent; RateLimit progress_rate_limit; struct stat st; bool eof; bool tried_reflink; bool tried_sendfile; }; RawExport *raw_export_unref(RawExport *e) { if (!e) return NULL; sd_event_source_unref(e->output_event_source); import_compress_free(&e->compress); sd_event_unref(e->event); safe_close(e->input_fd); free(e->buffer); free(e->path); free(e); return NULL; } int raw_export_new( RawExport **ret, sd_event *event, RawExportFinished on_finished, void *userdata) { _cleanup_(raw_export_unrefp) RawExport *e = NULL; int r; assert(ret); e = new0(RawExport, 1); if (!e) return -ENOMEM; e->output_fd = e->input_fd = -1; e->on_finished = on_finished; e->userdata = userdata; RATELIMIT_INIT(e->progress_rate_limit, 100 * USEC_PER_MSEC, 1); e->last_percent = (unsigned) -1; if (event) e->event = sd_event_ref(event); else { r = sd_event_default(&e->event); if (r < 0) return r; } *ret = e; e = NULL; return 0; } static void raw_export_report_progress(RawExport *e) { unsigned percent; assert(e); if (e->written_uncompressed >= (uint64_t) e->st.st_size) percent = 100; else percent = (unsigned) ((e->written_uncompressed * UINT64_C(100)) / (uint64_t) e->st.st_size); if (percent == e->last_percent) return; if (!ratelimit_test(&e->progress_rate_limit)) return; sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent); log_info("Exported %u%%.", percent); e->last_percent = percent; } static int raw_export_process(RawExport *e) { ssize_t l; int r; assert(e); if (!e->tried_reflink && e->compress.type == IMPORT_COMPRESS_UNCOMPRESSED) { /* If we shall take an uncompressed snapshot we can * reflink source to destination directly. Let's see * if this works. */ r = btrfs_reflink(e->input_fd, e->output_fd); if (r >= 0) { r = 0; goto finish; } e->tried_reflink = true; } if (!e->tried_sendfile && e->compress.type == IMPORT_COMPRESS_UNCOMPRESSED) { l = sendfile(e->output_fd, e->input_fd, NULL, COPY_BUFFER_SIZE); if (l < 0) { if (errno == EAGAIN) return 0; e->tried_sendfile = true; } else if (l == 0) { r = 0; goto finish; } else { e->written_uncompressed += l; e->written_compressed += l; raw_export_report_progress(e); return 0; } } while (e->buffer_size <= 0) { uint8_t input[COPY_BUFFER_SIZE]; if (e->eof) { r = 0; goto finish; } l = read(e->input_fd, input, sizeof(input)); if (l < 0) { r = log_error_errno(errno, "Failed to read raw file: %m"); goto finish; } if (l == 0) { e->eof = true; r = import_compress_finish(&e->compress, &e->buffer, &e->buffer_size, &e->buffer_allocated); } else { e->written_uncompressed += l; r = import_compress(&e->compress, input, l, &e->buffer, &e->buffer_size, &e->buffer_allocated); } if (r < 0) { r = log_error_errno(r, "Failed to encode: %m"); goto finish; } } l = write(e->output_fd, e->buffer, e->buffer_size); if (l < 0) { if (errno == EAGAIN) return 0; r = log_error_errno(errno, "Failed to write output file: %m"); goto finish; } assert((size_t) l <= e->buffer_size); memmove(e->buffer, (uint8_t*) e->buffer + l, e->buffer_size - l); e->buffer_size -= l; e->written_compressed += l; raw_export_report_progress(e); return 0; finish: if (r >= 0) { (void) copy_times(e->input_fd, e->output_fd); (void) copy_xattr(e->input_fd, e->output_fd); } if (e->on_finished) e->on_finished(e, r, e->userdata); else sd_event_exit(e->event, r); return 0; } static int raw_export_on_output(sd_event_source *s, int fd, uint32_t revents, void *userdata) { RawExport *i = userdata; return raw_export_process(i); } static int raw_export_on_defer(sd_event_source *s, void *userdata) { RawExport *i = userdata; return raw_export_process(i); } static int reflink_snapshot(int fd, const char *path) { char *p, *d; int new_fd, r; p = strdupa(path); d = dirname(p); new_fd = open(d, O_TMPFILE|O_CLOEXEC|O_NOCTTY|O_RDWR, 0600); if (new_fd < 0) { _cleanup_free_ char *t = NULL; r = tempfn_random(path, NULL, &t); if (r < 0) return r; new_fd = open(t, O_CLOEXEC|O_CREAT|O_NOCTTY|O_RDWR, 0600); if (new_fd < 0) return -errno; (void) unlink(t); } r = btrfs_reflink(fd, new_fd); if (r < 0) { safe_close(new_fd); return r; } return new_fd; } int raw_export_start(RawExport *e, const char *path, int fd, ImportCompressType compress) { _cleanup_close_ int sfd = -1, tfd = -1; int r; assert(e); assert(path); assert(fd >= 0); assert(compress < _IMPORT_COMPRESS_TYPE_MAX); assert(compress != IMPORT_COMPRESS_UNKNOWN); if (e->output_fd >= 0) return -EBUSY; r = fd_nonblock(fd, true); if (r < 0) return r; r = free_and_strdup(&e->path, path); if (r < 0) return r; sfd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (sfd < 0) return -errno; if (fstat(sfd, &e->st) < 0) return -errno; if (!S_ISREG(e->st.st_mode)) return -ENOTTY; /* Try to take a reflink snapshot of the file, if we can t make the export atomic */ tfd = reflink_snapshot(sfd, path); if (tfd >= 0) { e->input_fd = tfd; tfd = -1; } else { e->input_fd = sfd; sfd = -1; } r = import_compress_init(&e->compress, compress); if (r < 0) return r; r = sd_event_add_io(e->event, &e->output_event_source, fd, EPOLLOUT, raw_export_on_output, e); if (r == -EPERM) { r = sd_event_add_defer(e->event, &e->output_event_source, raw_export_on_defer, e); if (r < 0) return r; r = sd_event_source_set_enabled(e->output_event_source, SD_EVENT_ON); } if (r < 0) return r; e->output_fd = fd; return r; } systemd-229/src/import/export-raw.h000066400000000000000000000023211265713322000174410ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-event.h" #include "import-compress.h" #include "macro.h" typedef struct RawExport RawExport; typedef void (*RawExportFinished)(RawExport *export, int error, void *userdata); int raw_export_new(RawExport **export, sd_event *event, RawExportFinished on_finished, void *userdata); RawExport* raw_export_unref(RawExport *export); DEFINE_TRIVIAL_CLEANUP_FUNC(RawExport*, raw_export_unref); int raw_export_start(RawExport *export, const char *path, int fd, ImportCompressType compress); systemd-229/src/import/export-tar.c000066400000000000000000000220541265713322000174360ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-daemon.h" #include "alloc-util.h" #include "btrfs-util.h" #include "export-tar.h" #include "fd-util.h" #include "fileio.h" #include "import-common.h" #include "process-util.h" #include "ratelimit.h" #include "string-util.h" #include "util.h" #define COPY_BUFFER_SIZE (16*1024) struct TarExport { sd_event *event; TarExportFinished on_finished; void *userdata; char *path; char *temp_path; int output_fd; int tar_fd; ImportCompress compress; sd_event_source *output_event_source; void *buffer; size_t buffer_size; size_t buffer_allocated; uint64_t written_compressed; uint64_t written_uncompressed; pid_t tar_pid; struct stat st; uint64_t quota_referenced; unsigned last_percent; RateLimit progress_rate_limit; bool eof; bool tried_splice; }; TarExport *tar_export_unref(TarExport *e) { if (!e) return NULL; sd_event_source_unref(e->output_event_source); if (e->tar_pid > 1) { (void) kill_and_sigcont(e->tar_pid, SIGKILL); (void) wait_for_terminate(e->tar_pid, NULL); } if (e->temp_path) { (void) btrfs_subvol_remove(e->temp_path, BTRFS_REMOVE_QUOTA); free(e->temp_path); } import_compress_free(&e->compress); sd_event_unref(e->event); safe_close(e->tar_fd); free(e->buffer); free(e->path); free(e); return NULL; } int tar_export_new( TarExport **ret, sd_event *event, TarExportFinished on_finished, void *userdata) { _cleanup_(tar_export_unrefp) TarExport *e = NULL; int r; assert(ret); e = new0(TarExport, 1); if (!e) return -ENOMEM; e->output_fd = e->tar_fd = -1; e->on_finished = on_finished; e->userdata = userdata; e->quota_referenced = (uint64_t) -1; RATELIMIT_INIT(e->progress_rate_limit, 100 * USEC_PER_MSEC, 1); e->last_percent = (unsigned) -1; if (event) e->event = sd_event_ref(event); else { r = sd_event_default(&e->event); if (r < 0) return r; } *ret = e; e = NULL; return 0; } static void tar_export_report_progress(TarExport *e) { unsigned percent; assert(e); /* Do we have any quota info? If not, we don't know anything about the progress */ if (e->quota_referenced == (uint64_t) -1) return; if (e->written_uncompressed >= e->quota_referenced) percent = 100; else percent = (unsigned) ((e->written_uncompressed * UINT64_C(100)) / e->quota_referenced); if (percent == e->last_percent) return; if (!ratelimit_test(&e->progress_rate_limit)) return; sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent); log_info("Exported %u%%.", percent); e->last_percent = percent; } static int tar_export_process(TarExport *e) { ssize_t l; int r; assert(e); if (!e->tried_splice && e->compress.type == IMPORT_COMPRESS_UNCOMPRESSED) { l = splice(e->tar_fd, NULL, e->output_fd, NULL, COPY_BUFFER_SIZE, 0); if (l < 0) { if (errno == EAGAIN) return 0; e->tried_splice = true; } else if (l == 0) { r = 0; goto finish; } else { e->written_uncompressed += l; e->written_compressed += l; tar_export_report_progress(e); return 0; } } while (e->buffer_size <= 0) { uint8_t input[COPY_BUFFER_SIZE]; if (e->eof) { r = 0; goto finish; } l = read(e->tar_fd, input, sizeof(input)); if (l < 0) { r = log_error_errno(errno, "Failed to read tar file: %m"); goto finish; } if (l == 0) { e->eof = true; r = import_compress_finish(&e->compress, &e->buffer, &e->buffer_size, &e->buffer_allocated); } else { e->written_uncompressed += l; r = import_compress(&e->compress, input, l, &e->buffer, &e->buffer_size, &e->buffer_allocated); } if (r < 0) { r = log_error_errno(r, "Failed to encode: %m"); goto finish; } } l = write(e->output_fd, e->buffer, e->buffer_size); if (l < 0) { if (errno == EAGAIN) return 0; r = log_error_errno(errno, "Failed to write output file: %m"); goto finish; } assert((size_t) l <= e->buffer_size); memmove(e->buffer, (uint8_t*) e->buffer + l, e->buffer_size - l); e->buffer_size -= l; e->written_compressed += l; tar_export_report_progress(e); return 0; finish: if (e->on_finished) e->on_finished(e, r, e->userdata); else sd_event_exit(e->event, r); return 0; } static int tar_export_on_output(sd_event_source *s, int fd, uint32_t revents, void *userdata) { TarExport *i = userdata; return tar_export_process(i); } static int tar_export_on_defer(sd_event_source *s, void *userdata) { TarExport *i = userdata; return tar_export_process(i); } int tar_export_start(TarExport *e, const char *path, int fd, ImportCompressType compress) { _cleanup_close_ int sfd = -1; int r; assert(e); assert(path); assert(fd >= 0); assert(compress < _IMPORT_COMPRESS_TYPE_MAX); assert(compress != IMPORT_COMPRESS_UNKNOWN); if (e->output_fd >= 0) return -EBUSY; sfd = open(path, O_DIRECTORY|O_RDONLY|O_NOCTTY|O_CLOEXEC); if (sfd < 0) return -errno; if (fstat(sfd, &e->st) < 0) return -errno; r = fd_nonblock(fd, true); if (r < 0) return r; r = free_and_strdup(&e->path, path); if (r < 0) return r; e->quota_referenced = (uint64_t) -1; if (e->st.st_ino == 256) { /* might be a btrfs subvolume? */ BtrfsQuotaInfo q; r = btrfs_subvol_get_subtree_quota_fd(sfd, 0, &q); if (r >= 0) e->quota_referenced = q.referenced; e->temp_path = mfree(e->temp_path); r = tempfn_random(path, NULL, &e->temp_path); if (r < 0) return r; /* Let's try to make a snapshot, if we can, so that the export is atomic */ r = btrfs_subvol_snapshot_fd(sfd, e->temp_path, BTRFS_SNAPSHOT_READ_ONLY|BTRFS_SNAPSHOT_RECURSIVE); if (r < 0) { log_debug_errno(r, "Couldn't create snapshot %s of %s, not exporting atomically: %m", e->temp_path, path); e->temp_path = mfree(e->temp_path); } } r = import_compress_init(&e->compress, compress); if (r < 0) return r; r = sd_event_add_io(e->event, &e->output_event_source, fd, EPOLLOUT, tar_export_on_output, e); if (r == -EPERM) { r = sd_event_add_defer(e->event, &e->output_event_source, tar_export_on_defer, e); if (r < 0) return r; r = sd_event_source_set_enabled(e->output_event_source, SD_EVENT_ON); } if (r < 0) return r; e->tar_fd = import_fork_tar_c(e->temp_path ?: e->path, &e->tar_pid); if (e->tar_fd < 0) { e->output_event_source = sd_event_source_unref(e->output_event_source); return e->tar_fd; } e->output_fd = fd; return r; } systemd-229/src/import/export-tar.h000066400000000000000000000023211265713322000174360ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-event.h" #include "import-compress.h" #include "macro.h" typedef struct TarExport TarExport; typedef void (*TarExportFinished)(TarExport *export, int error, void *userdata); int tar_export_new(TarExport **export, sd_event *event, TarExportFinished on_finished, void *userdata); TarExport* tar_export_unref(TarExport *export); DEFINE_TRIVIAL_CLEANUP_FUNC(TarExport*, tar_export_unref); int tar_export_start(TarExport *export, const char *path, int fd, ImportCompressType compress); systemd-229/src/import/export.c000066400000000000000000000251051265713322000166520ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-event.h" #include "alloc-util.h" #include "export-raw.h" #include "export-tar.h" #include "fd-util.h" #include "fs-util.h" #include "hostname-util.h" #include "import-util.h" #include "machine-image.h" #include "signal-util.h" #include "string-util.h" #include "verbs.h" static ImportCompressType arg_compress = IMPORT_COMPRESS_UNKNOWN; static void determine_compression_from_filename(const char *p) { if (arg_compress != IMPORT_COMPRESS_UNKNOWN) return; if (!p) { arg_compress = IMPORT_COMPRESS_UNCOMPRESSED; return; } if (endswith(p, ".xz")) arg_compress = IMPORT_COMPRESS_XZ; else if (endswith(p, ".gz")) arg_compress = IMPORT_COMPRESS_GZIP; else if (endswith(p, ".bz2")) arg_compress = IMPORT_COMPRESS_BZIP2; else arg_compress = IMPORT_COMPRESS_UNCOMPRESSED; } static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { log_notice("Transfer aborted."); sd_event_exit(sd_event_source_get_event(s), EINTR); return 0; } static void on_tar_finished(TarExport *export, int error, void *userdata) { sd_event *event = userdata; assert(export); if (error == 0) log_info("Operation completed successfully."); sd_event_exit(event, abs(error)); } static int export_tar(int argc, char *argv[], void *userdata) { _cleanup_(tar_export_unrefp) TarExport *export = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; _cleanup_(image_unrefp) Image *image = NULL; const char *path = NULL, *local = NULL; _cleanup_close_ int open_fd = -1; int r, fd; if (machine_name_is_valid(argv[1])) { r = image_find(argv[1], &image); if (r < 0) return log_error_errno(r, "Failed to look for machine %s: %m", argv[1]); if (r == 0) { log_error("Machine image %s not found.", argv[1]); return -ENOENT; } local = image->path; } else local = argv[1]; if (argc >= 3) path = argv[2]; if (isempty(path) || streq(path, "-")) path = NULL; determine_compression_from_filename(path); if (path) { open_fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666); if (open_fd < 0) return log_error_errno(errno, "Failed to open tar image for export: %m"); fd = open_fd; log_info("Exporting '%s', saving to '%s' with compression '%s'.", local, path, import_compress_type_to_string(arg_compress)); } else { _cleanup_free_ char *pretty = NULL; fd = STDOUT_FILENO; (void) readlink_malloc("/proc/self/fd/1", &pretty); log_info("Exporting '%s', saving to '%s' with compression '%s'.", local, strna(pretty), import_compress_type_to_string(arg_compress)); } r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to allocate event loop: %m"); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); r = tar_export_new(&export, event, on_tar_finished, event); if (r < 0) return log_error_errno(r, "Failed to allocate exporter: %m"); r = tar_export_start(export, local, fd, arg_compress); if (r < 0) return log_error_errno(r, "Failed to export image: %m"); r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); log_info("Exiting."); return -r; } static void on_raw_finished(RawExport *export, int error, void *userdata) { sd_event *event = userdata; assert(export); if (error == 0) log_info("Operation completed successfully."); sd_event_exit(event, abs(error)); } static int export_raw(int argc, char *argv[], void *userdata) { _cleanup_(raw_export_unrefp) RawExport *export = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; _cleanup_(image_unrefp) Image *image = NULL; const char *path = NULL, *local = NULL; _cleanup_close_ int open_fd = -1; int r, fd; if (machine_name_is_valid(argv[1])) { r = image_find(argv[1], &image); if (r < 0) return log_error_errno(r, "Failed to look for machine %s: %m", argv[1]); if (r == 0) { log_error("Machine image %s not found.", argv[1]); return -ENOENT; } local = image->path; } else local = argv[1]; if (argc >= 3) path = argv[2]; if (isempty(path) || streq(path, "-")) path = NULL; determine_compression_from_filename(path); if (path) { open_fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666); if (open_fd < 0) return log_error_errno(errno, "Failed to open raw image for export: %m"); fd = open_fd; log_info("Exporting '%s', saving to '%s' with compression '%s'.", local, path, import_compress_type_to_string(arg_compress)); } else { _cleanup_free_ char *pretty = NULL; fd = STDOUT_FILENO; (void) readlink_malloc("/proc/self/fd/1", &pretty); log_info("Exporting '%s', saving to '%s' with compression '%s'.", local, strna(pretty), import_compress_type_to_string(arg_compress)); } r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to allocate event loop: %m"); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); r = raw_export_new(&export, event, on_raw_finished, event); if (r < 0) return log_error_errno(r, "Failed to allocate exporter: %m"); r = raw_export_start(export, local, fd, arg_compress); if (r < 0) return log_error_errno(r, "Failed to export image: %m"); r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); log_info("Exiting."); return -r; } static int help(int argc, char *argv[], void *userdata) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" "Export container or virtual machine images.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --format=FORMAT Select format\n\n" "Commands:\n" " tar NAME [FILE] Export a TAR image\n" " raw NAME [FILE] Export a RAW image\n", program_invocation_short_name); return 0; } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_FORMAT, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "format", required_argument, NULL, ARG_FORMAT }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': return help(0, NULL, NULL); case ARG_VERSION: return version(); case ARG_FORMAT: if (streq(optarg, "uncompressed")) arg_compress = IMPORT_COMPRESS_UNCOMPRESSED; else if (streq(optarg, "xz")) arg_compress = IMPORT_COMPRESS_XZ; else if (streq(optarg, "gzip")) arg_compress = IMPORT_COMPRESS_GZIP; else if (streq(optarg, "bzip2")) arg_compress = IMPORT_COMPRESS_BZIP2; else { log_error("Unknown format: %s", optarg); return -EINVAL; } break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } static int export_main(int argc, char *argv[]) { static const Verb verbs[] = { { "help", VERB_ANY, VERB_ANY, 0, help }, { "tar", 2, 3, 0, export_tar }, { "raw", 2, 3, 0, export_raw }, {} }; return dispatch_verb(argc, argv, verbs, NULL); } int main(int argc, char *argv[]) { int r; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; (void) ignore_signals(SIGPIPE, -1); r = export_main(argc, argv); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/import/import-common.c000066400000000000000000000164221265713322000201330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "btrfs-util.h" #include "capability-util.h" #include "fd-util.h" #include "import-common.h" #include "signal-util.h" #include "util.h" int import_make_read_only_fd(int fd) { int r; assert(fd >= 0); /* First, let's make this a read-only subvolume if it refers * to a subvolume */ r = btrfs_subvol_set_read_only_fd(fd, true); if (r == -ENOTTY || r == -ENOTDIR || r == -EINVAL) { struct stat st; /* This doesn't refer to a subvolume, or the file * system isn't even btrfs. In that, case fall back to * chmod()ing */ r = fstat(fd, &st); if (r < 0) return log_error_errno(errno, "Failed to stat temporary image: %m"); /* Drop "w" flag */ if (fchmod(fd, st.st_mode & 07555) < 0) return log_error_errno(errno, "Failed to chmod() final image: %m"); return 0; } else if (r < 0) return log_error_errno(r, "Failed to make subvolume read-only: %m"); return 0; } int import_make_read_only(const char *path) { _cleanup_close_ int fd = 1; fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) return log_error_errno(errno, "Failed to open %s: %m", path); return import_make_read_only_fd(fd); } int import_fork_tar_x(const char *path, pid_t *ret) { _cleanup_close_pair_ int pipefd[2] = { -1, -1 }; pid_t pid; int r; assert(path); assert(ret); if (pipe2(pipefd, O_CLOEXEC) < 0) return log_error_errno(errno, "Failed to create pipe for tar: %m"); pid = fork(); if (pid < 0) return log_error_errno(errno, "Failed to fork off tar: %m"); if (pid == 0) { int null_fd; uint64_t retain = (1ULL << CAP_CHOWN) | (1ULL << CAP_FOWNER) | (1ULL << CAP_FSETID) | (1ULL << CAP_MKNOD) | (1ULL << CAP_SETFCAP) | (1ULL << CAP_DAC_OVERRIDE); /* Child */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); pipefd[1] = safe_close(pipefd[1]); if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) { log_error_errno(errno, "Failed to dup2() fd: %m"); _exit(EXIT_FAILURE); } if (pipefd[0] != STDIN_FILENO) pipefd[0] = safe_close(pipefd[0]); null_fd = open("/dev/null", O_WRONLY|O_NOCTTY); if (null_fd < 0) { log_error_errno(errno, "Failed to open /dev/null: %m"); _exit(EXIT_FAILURE); } if (dup2(null_fd, STDOUT_FILENO) != STDOUT_FILENO) { log_error_errno(errno, "Failed to dup2() fd: %m"); _exit(EXIT_FAILURE); } if (null_fd != STDOUT_FILENO) null_fd = safe_close(null_fd); fd_cloexec(STDIN_FILENO, false); fd_cloexec(STDOUT_FILENO, false); fd_cloexec(STDERR_FILENO, false); if (unshare(CLONE_NEWNET) < 0) log_error_errno(errno, "Failed to lock tar into network namespace, ignoring: %m"); r = capability_bounding_set_drop(retain, true); if (r < 0) log_error_errno(r, "Failed to drop capabilities, ignoring: %m"); execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", NULL); log_error_errno(errno, "Failed to execute tar: %m"); _exit(EXIT_FAILURE); } pipefd[0] = safe_close(pipefd[0]); r = pipefd[1]; pipefd[1] = -1; *ret = pid; return r; } int import_fork_tar_c(const char *path, pid_t *ret) { _cleanup_close_pair_ int pipefd[2] = { -1, -1 }; pid_t pid; int r; assert(path); assert(ret); if (pipe2(pipefd, O_CLOEXEC) < 0) return log_error_errno(errno, "Failed to create pipe for tar: %m"); pid = fork(); if (pid < 0) return log_error_errno(errno, "Failed to fork off tar: %m"); if (pid == 0) { int null_fd; uint64_t retain = (1ULL << CAP_DAC_OVERRIDE); /* Child */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); pipefd[0] = safe_close(pipefd[0]); if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) { log_error_errno(errno, "Failed to dup2() fd: %m"); _exit(EXIT_FAILURE); } if (pipefd[1] != STDOUT_FILENO) pipefd[1] = safe_close(pipefd[1]); null_fd = open("/dev/null", O_RDONLY|O_NOCTTY); if (null_fd < 0) { log_error_errno(errno, "Failed to open /dev/null: %m"); _exit(EXIT_FAILURE); } if (dup2(null_fd, STDIN_FILENO) != STDIN_FILENO) { log_error_errno(errno, "Failed to dup2() fd: %m"); _exit(EXIT_FAILURE); } if (null_fd != STDIN_FILENO) null_fd = safe_close(null_fd); fd_cloexec(STDIN_FILENO, false); fd_cloexec(STDOUT_FILENO, false); fd_cloexec(STDERR_FILENO, false); if (unshare(CLONE_NEWNET) < 0) log_error_errno(errno, "Failed to lock tar into network namespace, ignoring: %m"); r = capability_bounding_set_drop(retain, true); if (r < 0) log_error_errno(r, "Failed to drop capabilities, ignoring: %m"); execlp("tar", "tar", "-C", path, "-c", ".", NULL); log_error_errno(errno, "Failed to execute tar: %m"); _exit(EXIT_FAILURE); } pipefd[1] = safe_close(pipefd[1]); r = pipefd[0]; pipefd[0] = -1; *ret = pid; return r; } systemd-229/src/import/import-common.h000066400000000000000000000016331265713322000201360ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int import_make_read_only_fd(int fd); int import_make_read_only(const char *path); int import_fork_tar_c(const char *path, pid_t *ret); int import_fork_tar_x(const char *path, pid_t *ret); systemd-229/src/import/import-compress.c000066400000000000000000000334301265713322000204740ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "import-compress.h" #include "string-table.h" #include "util.h" void import_compress_free(ImportCompress *c) { assert(c); if (c->type == IMPORT_COMPRESS_XZ) lzma_end(&c->xz); else if (c->type == IMPORT_COMPRESS_GZIP) { if (c->encoding) deflateEnd(&c->gzip); else inflateEnd(&c->gzip); } else if (c->type == IMPORT_COMPRESS_BZIP2) { if (c->encoding) BZ2_bzCompressEnd(&c->bzip2); else BZ2_bzDecompressEnd(&c->bzip2); } c->type = IMPORT_COMPRESS_UNKNOWN; } int import_uncompress_detect(ImportCompress *c, const void *data, size_t size) { static const uint8_t xz_signature[] = { 0xfd, '7', 'z', 'X', 'Z', 0x00 }; static const uint8_t gzip_signature[] = { 0x1f, 0x8b }; static const uint8_t bzip2_signature[] = { 'B', 'Z', 'h' }; int r; assert(c); if (c->type != IMPORT_COMPRESS_UNKNOWN) return 1; if (size < MAX3(sizeof(xz_signature), sizeof(gzip_signature), sizeof(bzip2_signature))) return 0; assert(data); if (memcmp(data, xz_signature, sizeof(xz_signature)) == 0) { lzma_ret xzr; xzr = lzma_stream_decoder(&c->xz, UINT64_MAX, LZMA_TELL_UNSUPPORTED_CHECK); if (xzr != LZMA_OK) return -EIO; c->type = IMPORT_COMPRESS_XZ; } else if (memcmp(data, gzip_signature, sizeof(gzip_signature)) == 0) { r = inflateInit2(&c->gzip, 15+16); if (r != Z_OK) return -EIO; c->type = IMPORT_COMPRESS_GZIP; } else if (memcmp(data, bzip2_signature, sizeof(bzip2_signature)) == 0) { r = BZ2_bzDecompressInit(&c->bzip2, 0, 0); if (r != BZ_OK) return -EIO; c->type = IMPORT_COMPRESS_BZIP2; } else c->type = IMPORT_COMPRESS_UNCOMPRESSED; c->encoding = false; return 1; } int import_uncompress(ImportCompress *c, const void *data, size_t size, ImportCompressCallback callback, void *userdata) { int r; assert(c); assert(callback); r = import_uncompress_detect(c, data, size); if (r <= 0) return r; if (c->encoding) return -EINVAL; if (size <= 0) return 1; assert(data); switch (c->type) { case IMPORT_COMPRESS_UNCOMPRESSED: r = callback(data, size, userdata); if (r < 0) return r; break; case IMPORT_COMPRESS_XZ: c->xz.next_in = data; c->xz.avail_in = size; while (c->xz.avail_in > 0) { uint8_t buffer[16 * 1024]; lzma_ret lzr; c->xz.next_out = buffer; c->xz.avail_out = sizeof(buffer); lzr = lzma_code(&c->xz, LZMA_RUN); if (lzr != LZMA_OK && lzr != LZMA_STREAM_END) return -EIO; r = callback(buffer, sizeof(buffer) - c->xz.avail_out, userdata); if (r < 0) return r; } break; case IMPORT_COMPRESS_GZIP: c->gzip.next_in = (void*) data; c->gzip.avail_in = size; while (c->gzip.avail_in > 0) { uint8_t buffer[16 * 1024]; c->gzip.next_out = buffer; c->gzip.avail_out = sizeof(buffer); r = inflate(&c->gzip, Z_NO_FLUSH); if (r != Z_OK && r != Z_STREAM_END) return -EIO; r = callback(buffer, sizeof(buffer) - c->gzip.avail_out, userdata); if (r < 0) return r; } break; case IMPORT_COMPRESS_BZIP2: c->bzip2.next_in = (void*) data; c->bzip2.avail_in = size; while (c->bzip2.avail_in > 0) { uint8_t buffer[16 * 1024]; c->bzip2.next_out = (char*) buffer; c->bzip2.avail_out = sizeof(buffer); r = BZ2_bzDecompress(&c->bzip2); if (r != BZ_OK && r != BZ_STREAM_END) return -EIO; r = callback(buffer, sizeof(buffer) - c->bzip2.avail_out, userdata); if (r < 0) return r; } break; default: assert_not_reached("Unknown compression"); } return 1; } int import_compress_init(ImportCompress *c, ImportCompressType t) { int r; assert(c); switch (t) { case IMPORT_COMPRESS_XZ: { lzma_ret xzr; xzr = lzma_easy_encoder(&c->xz, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64); if (xzr != LZMA_OK) return -EIO; c->type = IMPORT_COMPRESS_XZ; break; } case IMPORT_COMPRESS_GZIP: r = deflateInit2(&c->gzip, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY); if (r != Z_OK) return -EIO; c->type = IMPORT_COMPRESS_GZIP; break; case IMPORT_COMPRESS_BZIP2: r = BZ2_bzCompressInit(&c->bzip2, 9, 0, 0); if (r != BZ_OK) return -EIO; c->type = IMPORT_COMPRESS_BZIP2; break; case IMPORT_COMPRESS_UNCOMPRESSED: c->type = IMPORT_COMPRESS_UNCOMPRESSED; break; default: return -EOPNOTSUPP; } c->encoding = true; return 0; } static int enlarge_buffer(void **buffer, size_t *buffer_size, size_t *buffer_allocated) { size_t l; void *p; if (*buffer_allocated > *buffer_size) return 0; l = MAX(16*1024U, (*buffer_size * 2)); p = realloc(*buffer, l); if (!p) return -ENOMEM; *buffer = p; *buffer_allocated = l; return 1; } int import_compress(ImportCompress *c, const void *data, size_t size, void **buffer, size_t *buffer_size, size_t *buffer_allocated) { int r; assert(c); assert(buffer); assert(buffer_size); assert(buffer_allocated); if (!c->encoding) return -EINVAL; if (size <= 0) return 0; assert(data); *buffer_size = 0; switch (c->type) { case IMPORT_COMPRESS_XZ: c->xz.next_in = data; c->xz.avail_in = size; while (c->xz.avail_in > 0) { lzma_ret lzr; r = enlarge_buffer(buffer, buffer_size, buffer_allocated); if (r < 0) return r; c->xz.next_out = (uint8_t*) *buffer + *buffer_size; c->xz.avail_out = *buffer_allocated - *buffer_size; lzr = lzma_code(&c->xz, LZMA_RUN); if (lzr != LZMA_OK) return -EIO; *buffer_size += (*buffer_allocated - *buffer_size) - c->xz.avail_out; } break; case IMPORT_COMPRESS_GZIP: c->gzip.next_in = (void*) data; c->gzip.avail_in = size; while (c->gzip.avail_in > 0) { r = enlarge_buffer(buffer, buffer_size, buffer_allocated); if (r < 0) return r; c->gzip.next_out = (uint8_t*) *buffer + *buffer_size; c->gzip.avail_out = *buffer_allocated - *buffer_size; r = deflate(&c->gzip, Z_NO_FLUSH); if (r != Z_OK) return -EIO; *buffer_size += (*buffer_allocated - *buffer_size) - c->gzip.avail_out; } break; case IMPORT_COMPRESS_BZIP2: c->bzip2.next_in = (void*) data; c->bzip2.avail_in = size; while (c->bzip2.avail_in > 0) { r = enlarge_buffer(buffer, buffer_size, buffer_allocated); if (r < 0) return r; c->bzip2.next_out = (void*) ((uint8_t*) *buffer + *buffer_size); c->bzip2.avail_out = *buffer_allocated - *buffer_size; r = BZ2_bzCompress(&c->bzip2, BZ_RUN); if (r != BZ_RUN_OK) return -EIO; *buffer_size += (*buffer_allocated - *buffer_size) - c->bzip2.avail_out; } break; case IMPORT_COMPRESS_UNCOMPRESSED: if (*buffer_allocated < size) { void *p; p = realloc(*buffer, size); if (!p) return -ENOMEM; *buffer = p; *buffer_allocated = size; } memcpy(*buffer, data, size); *buffer_size = size; break; default: return -EOPNOTSUPP; } return 0; } int import_compress_finish(ImportCompress *c, void **buffer, size_t *buffer_size, size_t *buffer_allocated) { int r; assert(c); assert(buffer); assert(buffer_size); assert(buffer_allocated); if (!c->encoding) return -EINVAL; *buffer_size = 0; switch (c->type) { case IMPORT_COMPRESS_XZ: { lzma_ret lzr; c->xz.avail_in = 0; do { r = enlarge_buffer(buffer, buffer_size, buffer_allocated); if (r < 0) return r; c->xz.next_out = (uint8_t*) *buffer + *buffer_size; c->xz.avail_out = *buffer_allocated - *buffer_size; lzr = lzma_code(&c->xz, LZMA_FINISH); if (lzr != LZMA_OK && lzr != LZMA_STREAM_END) return -EIO; *buffer_size += (*buffer_allocated - *buffer_size) - c->xz.avail_out; } while (lzr != LZMA_STREAM_END); break; } case IMPORT_COMPRESS_GZIP: c->gzip.avail_in = 0; do { r = enlarge_buffer(buffer, buffer_size, buffer_allocated); if (r < 0) return r; c->gzip.next_out = (uint8_t*) *buffer + *buffer_size; c->gzip.avail_out = *buffer_allocated - *buffer_size; r = deflate(&c->gzip, Z_FINISH); if (r != Z_OK && r != Z_STREAM_END) return -EIO; *buffer_size += (*buffer_allocated - *buffer_size) - c->gzip.avail_out; } while (r != Z_STREAM_END); break; case IMPORT_COMPRESS_BZIP2: c->bzip2.avail_in = 0; do { r = enlarge_buffer(buffer, buffer_size, buffer_allocated); if (r < 0) return r; c->bzip2.next_out = (void*) ((uint8_t*) *buffer + *buffer_size); c->bzip2.avail_out = *buffer_allocated - *buffer_size; r = BZ2_bzCompress(&c->bzip2, BZ_FINISH); if (r != BZ_FINISH_OK && r != BZ_STREAM_END) return -EIO; *buffer_size += (*buffer_allocated - *buffer_size) - c->bzip2.avail_out; } while (r != BZ_STREAM_END); break; case IMPORT_COMPRESS_UNCOMPRESSED: break; default: return -EOPNOTSUPP; } return 0; } static const char* const import_compress_type_table[_IMPORT_COMPRESS_TYPE_MAX] = { [IMPORT_COMPRESS_UNKNOWN] = "unknown", [IMPORT_COMPRESS_UNCOMPRESSED] = "uncompressed", [IMPORT_COMPRESS_XZ] = "xz", [IMPORT_COMPRESS_GZIP] = "gzip", [IMPORT_COMPRESS_BZIP2] = "bzip2", }; DEFINE_STRING_TABLE_LOOKUP(import_compress_type, ImportCompressType); systemd-229/src/import/import-compress.h000066400000000000000000000041521265713322000205000ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "macro.h" typedef enum ImportCompressType { IMPORT_COMPRESS_UNKNOWN, IMPORT_COMPRESS_UNCOMPRESSED, IMPORT_COMPRESS_XZ, IMPORT_COMPRESS_GZIP, IMPORT_COMPRESS_BZIP2, _IMPORT_COMPRESS_TYPE_MAX, _IMPORT_COMPRESS_TYPE_INVALID = -1, } ImportCompressType; typedef struct ImportCompress { ImportCompressType type; bool encoding; union { lzma_stream xz; z_stream gzip; bz_stream bzip2; }; } ImportCompress; typedef int (*ImportCompressCallback)(const void *data, size_t size, void *userdata); void import_compress_free(ImportCompress *c); int import_uncompress_detect(ImportCompress *c, const void *data, size_t size); int import_uncompress(ImportCompress *c, const void *data, size_t size, ImportCompressCallback callback, void *userdata); int import_compress_init(ImportCompress *c, ImportCompressType t); int import_compress(ImportCompress *c, const void *data, size_t size, void **buffer, size_t *buffer_size, size_t *buffer_allocated); int import_compress_finish(ImportCompress *c, void **buffer, size_t *buffer_size, size_t *buffer_allocated); const char* import_compress_type_to_string(ImportCompressType t) _const_; ImportCompressType import_compress_type_from_string(const char *s) _pure_; systemd-229/src/import/import-pubring.gpg000066400000000000000000000225171265713322000206460ustar00rootroot00000000000000 S _yQiIP̢ Zvx=eQxjry)fթ0ZxrbNOEr&Ryi2Ϩ#r,t݅_NFg[|h Xn|oO"x=D\/ݵ03,g_!쵬A5L|kC~bI@3U[g/wFCC<C;)߲%Sth۬Dɖ'@ s8"S   W_h쮆*}iEr %V|%DCR1v1lVVzfCkJ-~&\3*ݯB5lcKjVz_ɺXL&(lt!01-R X;w_sVfԱp'z9AC\(q>l_.g)j(8IW:Z搁0P([J%U[}vEHD_Xĭ7d 7ޘHϔy+y(B~b5V[jdYlbv-̹:k%2'r8Xft=! S}hvu,˚| >C!h0T2q#$@s̖C=1ذpzYvc44} WQ ~K],D$ |Z!x(E:Yyî :Wn;j{&lc2 IJl q[ek5ʺ#I_L ldۯCi|۟% '`_&fƝM7kHpk\{F-t%,oQ`_UP`:w b(勫xS2ŧ Hi\Z2 B]( ǭ1cDJpCu*]gY$6Eaw"g "PY-lMz**8k*`t(i3>@ Yrx΀#z=ǝ_fqLq4g̏P\[x5jdi^W\5CmVg0IG;Bރو7UR,no?+)G-ȡ|Tz} ad1m-fd~PLOkfҎ䇢sSo'e2Nj}-#0R>WRCmfX@qJy{D֙4YsXrYQ%4CȳjNp%ryzj\r[7̶qOh,KeqXrg%c$Ʋ|g t $h!kd?%™"$KQ@VPoO֓U3b@nZ'4 Ê:LveQD,Tj|2ukV͍eR$օ/ؑ+`3q78Fvlܑ^3%Ghm;Snw̑ 8i#pPGdڒuTlu'gL ~75!:v$8(lpO[72VK9FZstL)lK.ԊwT(:c(BmIsO2;U4~?Eg[^˯ThBƯY/L2p;Ko->O 7q(m;kq[)XߓcsXL*KPu+6Oկ jd#_>8"S   1.UTPe;u2c>{ʶ"^۳ :nH ^ר;e5);;LtEhws5 ɒz . VXK=7^lYvleH"R#oPH&浳D AHIEҾJ& ًlg&X8p#;2m!p,O~)h<3\G-:xꉄIX4\D]04v:oy o67?#pB4`nifb;qCqhO#LP;ަANt?>zBWt_:*" =&r7ЀE RB-RiyC,B`Lp8YAH("؝7_&Ci3=6ÂHxpZu=ztԓj/"gXp:891|-c^Z_Va<7]NxFBs#S9m?Ԭ-^({W)t8&]LId $ m+3|K5}ϭs{+ >Ȫ"uύo[i =v<6Vݻ9h`Vo0H݅ԊI@Dk@Ï9q)6F.Ŧ X3w62E"/@R (į< (7!HG}^lC%_@UQ 9,[ӏ5oZ3%)4:B[.rjxL`9 G䖕t~Ѕ]1lR(;n,z%,8ak}J% G:CƐu/-sX\{u{W$#6E0Fedora Secondary (21) 8"RB   cmz¬T dGTbt5=£UrZE$>:;a/V^Jraԑfl|* 5B^.#{.X!WR}cv WDIRP`p3}G>QFaPpg>;2 {I੏=^̍6HՓK0L)4|faN){Irh=yxP"h)C~x%Eg3&jgsBjxDjvhBwrzT!3^ Lˏsok>[ [ԧ$60&Ze.{V\ǥYsN1 wk~Q"?E IbY\ BfkԎ?9gB2o^s*[/?hlo "ԋ%Gv$!. mX(9=[H!Q\S6x|R RB\ʑl$~dD&m x0Gϸ4V/Ân0ڻmo ع-*aRK>*!d8V/U<,_c%kF["$@EWPs6I~Ŭc*toټ" Xa|NuKC#gL`F n*3˅mpP C(ƅߓӝبU=]1ށZYyCȥ?WUC#Dd;QxSOw|> J"FPVA@=R CɫTGVv(~c5l3P[c-0/#2te,aVm-ܦ^csW #qIHY2Amb_mAfd9N-;"2hPArA}܉1T[Fsncge~/[I}f\@gwC!;pEXW'rk!7E+ (I M2rӇyO; HV)^o7-*q՜$U5̫$ ;uOW m`n+QE:RTտ`ܽ.]Lt>ݬѿ-yk+! K[3.RKpɛ@ըJ^"IirUFO!񳕡=tXdPjlLR ӆYyr\Y}Z(ۉ RB cmەBm .P 'pߐyۄu to2`r_G<*2ď 6>RacʵJOt^[,EB|Zޓ TmsN&3Z%y%2R$ns5{RpR!V)O259w^^ `6!W4JwumF6qDߚ5NDňߕL1y= s({eIC czZdzi/ 2sW#IU>tӪnYUFM;Hf]S C=M.:ҹ %c3 D[^!Y*NȘ>0xmDW`FD"ub|5\갉K x ڇY'fex*-?K1d'T*-rL]s ^uj?~dm,NU-Tɷ4X]-|A)ԴuN$A2[Kc"Ÿ%ܑ OO]MT Fq RAZoيeS!TL1(/轙ybtZ}]FE s<*cݖS\+/ci}?&/L @ASM`wAm~amX:ݍBL2.X8) i2U^?X=#L[|'*?t,OsNIOZM֦r$і,1*RBO K)!.u7!٥ $sn ~bɋ;+ ֆ_h5B#n |Ddzjd#WYa"g+-P˧;;[FX犦(B_ Ʊo>6@B$KΔf)=.y scĎb*Vq?K\YhO8f%2 y*d< &;'{m3:Lξ, fkuA'|JiD暑lv #l#6Exa#U&Fedora (21) 8"RAZ   N?TW>9tR1 E#n&wJ_SD_-V|=C)# ~SaEA^,st&7%O,j*x؇FcʊtfD&jT[ ᮬ(0QTL(43~alr'%6%ҟ=dV`Ph ɱYMJg:F";ŭzY\ \Cr3|Ns_]RUtPCԸyEmJ54GOH`},zĨƤLpIn.-qH;g-Ãd>,?Wh Zۍ4Ywy,{LS0%/OL2=<]z635!U|B*dyUo`S;akʧ#sgyU,8gUj"uGF[qG.]sP$R\Tk J)5WMIUYpvl{[+fQDfp @u+ :C)nЁm',sji賊<~$#0/%ϣl#udT-Wo4T;kCVt%|mee8 !c6a!2utr[3 ]2`WӳDR_^&3kËa hmm 64'Sjf_9 QXCP$xy+>N^.tvɜAiAV8!MXյ+B_ Ѡ'$IL)?Pg~g4>,v &yQmx{ZZ枰oDm0 =ȦVvtk0Kaׁ<?َG9ڷtWfYota`}4]S.ݔda}}lh,( X*%g+Bdhn£d%% 9p ˹uP0+=Yn EZ'EtIMKΣ4UEC Image Automatic Signing Key FJ-3 (ޮ).Zslf=*HŠNJΧ13SE=sRQnvJ-' WYPJd ʵ1E*,@SHٲ,ٴ&^&\CU̵$K#A&XAz}̩%[(43KzI+eM &~CL܊'H1 ê'?a{^;g|N,3`i 1rmcӒ1挹JZ@ QY'ZX^Sf{iᵑ] cIJBzgc(uan > QXiRfA hCd!/~^̞nݴ㵜|*6ZK`tVZf7`I\ˏ0XvO9'gR@PN?BE ~Rx^ZF2PK($h ֵǩcnU\璾iicƢEy*gD..bGD?c%cDy$ xxgo9ӂ,}-DB ܷ-` Zή+L1rKӰ7!J*%    ]lL}|.'5|l۞hO&`IO1w@!OZQ< b\د}7 IUhsVBy9NWbWSfei>34@JiN6ĻԠ-/r"XvW[CZj}^#2g#Ez`ɺ"̭Vȵ4@i9RLj4%-Ϫ[/vgBn'rQDlnz`[:qqO(p'4KƂӊsystemd-229/src/import/import-raw.c000066400000000000000000000310601265713322000174270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-daemon.h" #include "sd-event.h" #include "alloc-util.h" #include "btrfs-util.h" #include "chattr-util.h" #include "copy.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "hostname-util.h" #include "import-common.h" #include "import-compress.h" #include "import-raw.h" #include "io-util.h" #include "machine-pool.h" #include "mkdir.h" #include "path-util.h" #include "qcow2-util.h" #include "ratelimit.h" #include "rm-rf.h" #include "string-util.h" #include "util.h" struct RawImport { sd_event *event; char *image_root; RawImportFinished on_finished; void *userdata; char *local; bool force_local; bool read_only; bool grow_machine_directory; char *temp_path; char *final_path; int input_fd; int output_fd; ImportCompress compress; uint64_t written_since_last_grow; sd_event_source *input_event_source; uint8_t buffer[16*1024]; size_t buffer_size; uint64_t written_compressed; uint64_t written_uncompressed; struct stat st; unsigned last_percent; RateLimit progress_rate_limit; }; RawImport* raw_import_unref(RawImport *i) { if (!i) return NULL; sd_event_unref(i->event); if (i->temp_path) { (void) unlink(i->temp_path); free(i->temp_path); } import_compress_free(&i->compress); sd_event_source_unref(i->input_event_source); safe_close(i->output_fd); free(i->final_path); free(i->image_root); free(i->local); free(i); return NULL; } int raw_import_new( RawImport **ret, sd_event *event, const char *image_root, RawImportFinished on_finished, void *userdata) { _cleanup_(raw_import_unrefp) RawImport *i = NULL; int r; assert(ret); i = new0(RawImport, 1); if (!i) return -ENOMEM; i->input_fd = i->output_fd = -1; i->on_finished = on_finished; i->userdata = userdata; RATELIMIT_INIT(i->progress_rate_limit, 100 * USEC_PER_MSEC, 1); i->last_percent = (unsigned) -1; i->image_root = strdup(image_root ?: "/var/lib/machines"); if (!i->image_root) return -ENOMEM; i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines"); if (event) i->event = sd_event_ref(event); else { r = sd_event_default(&i->event); if (r < 0) return r; } *ret = i; i = NULL; return 0; } static void raw_import_report_progress(RawImport *i) { unsigned percent; assert(i); /* We have no size information, unless the source is a regular file */ if (!S_ISREG(i->st.st_mode)) return; if (i->written_compressed >= (uint64_t) i->st.st_size) percent = 100; else percent = (unsigned) ((i->written_compressed * UINT64_C(100)) / (uint64_t) i->st.st_size); if (percent == i->last_percent) return; if (!ratelimit_test(&i->progress_rate_limit)) return; sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent); log_info("Imported %u%%.", percent); i->last_percent = percent; } static int raw_import_maybe_convert_qcow2(RawImport *i) { _cleanup_close_ int converted_fd = -1; _cleanup_free_ char *t = NULL; int r; assert(i); r = qcow2_detect(i->output_fd); if (r < 0) return log_error_errno(r, "Failed to detect whether this is a QCOW2 image: %m"); if (r == 0) return 0; /* This is a QCOW2 image, let's convert it */ r = tempfn_random(i->final_path, NULL, &t); if (r < 0) return log_oom(); converted_fd = open(t, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); if (converted_fd < 0) return log_error_errno(errno, "Failed to create %s: %m", t); r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL); if (r < 0) log_warning_errno(r, "Failed to set file attributes on %s: %m", t); log_info("Unpacking QCOW2 file."); r = qcow2_convert(i->output_fd, converted_fd); if (r < 0) { unlink(t); return log_error_errno(r, "Failed to convert qcow2 image: %m"); } (void) unlink(i->temp_path); free(i->temp_path); i->temp_path = t; t = NULL; safe_close(i->output_fd); i->output_fd = converted_fd; converted_fd = -1; return 1; } static int raw_import_finish(RawImport *i) { int r; assert(i); assert(i->output_fd >= 0); assert(i->temp_path); assert(i->final_path); /* In case this was a sparse file, make sure the file system is right */ if (i->written_uncompressed > 0) { if (ftruncate(i->output_fd, i->written_uncompressed) < 0) return log_error_errno(errno, "Failed to truncate file: %m"); } r = raw_import_maybe_convert_qcow2(i); if (r < 0) return r; if (S_ISREG(i->st.st_mode)) { (void) copy_times(i->input_fd, i->output_fd); (void) copy_xattr(i->input_fd, i->output_fd); } if (i->read_only) { r = import_make_read_only_fd(i->output_fd); if (r < 0) return r; } if (i->force_local) (void) rm_rf(i->final_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path); if (r < 0) return log_error_errno(r, "Failed to move image into place: %m"); i->temp_path = mfree(i->temp_path); return 0; } static int raw_import_open_disk(RawImport *i) { int r; assert(i); assert(!i->final_path); assert(!i->temp_path); assert(i->output_fd < 0); i->final_path = strjoin(i->image_root, "/", i->local, ".raw", NULL); if (!i->final_path) return log_oom(); r = tempfn_random(i->final_path, NULL, &i->temp_path); if (r < 0) return log_oom(); (void) mkdir_parents_label(i->temp_path, 0700); i->output_fd = open(i->temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); if (i->output_fd < 0) return log_error_errno(errno, "Failed to open destination %s: %m", i->temp_path); r = chattr_fd(i->output_fd, FS_NOCOW_FL, FS_NOCOW_FL); if (r < 0) log_warning_errno(r, "Failed to set file attributes on %s: %m", i->temp_path); return 0; } static int raw_import_try_reflink(RawImport *i) { off_t p; int r; assert(i); assert(i->input_fd >= 0); assert(i->output_fd >= 0); if (i->compress.type != IMPORT_COMPRESS_UNCOMPRESSED) return 0; if (!S_ISREG(i->st.st_mode)) return 0; p = lseek(i->input_fd, 0, SEEK_CUR); if (p == (off_t) -1) return log_error_errno(errno, "Failed to read file offset of input file: %m"); /* Let's only try a btrfs reflink, if we are reading from the beginning of the file */ if ((uint64_t) p != (uint64_t) i->buffer_size) return 0; r = btrfs_reflink(i->input_fd, i->output_fd); if (r >= 0) return 1; return 0; } static int raw_import_write(const void *p, size_t sz, void *userdata) { RawImport *i = userdata; ssize_t n; if (i->grow_machine_directory && i->written_since_last_grow >= GROW_INTERVAL_BYTES) { i->written_since_last_grow = 0; grow_machine_directory(); } n = sparse_write(i->output_fd, p, sz, 64); if (n < 0) return -errno; if ((size_t) n < sz) return -EIO; i->written_uncompressed += sz; i->written_since_last_grow += sz; return 0; } static int raw_import_process(RawImport *i) { ssize_t l; int r; assert(i); assert(i->buffer_size < sizeof(i->buffer)); l = read(i->input_fd, i->buffer + i->buffer_size, sizeof(i->buffer) - i->buffer_size); if (l < 0) { if (errno == EAGAIN) return 0; r = log_error_errno(errno, "Failed to read input file: %m"); goto finish; } if (l == 0) { if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) { log_error("Premature end of file: %m"); r = -EIO; goto finish; } r = raw_import_finish(i); goto finish; } i->buffer_size += l; if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) { r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size); if (r < 0) { log_error("Failed to detect file compression: %m"); goto finish; } if (r == 0) /* Need more data */ return 0; r = raw_import_open_disk(i); if (r < 0) goto finish; r = raw_import_try_reflink(i); if (r < 0) goto finish; if (r > 0) { r = raw_import_finish(i); goto finish; } } r = import_uncompress(&i->compress, i->buffer, i->buffer_size, raw_import_write, i); if (r < 0) { log_error_errno(r, "Failed to decode and write: %m"); goto finish; } i->written_compressed += i->buffer_size; i->buffer_size = 0; raw_import_report_progress(i); return 0; finish: if (i->on_finished) i->on_finished(i, r, i->userdata); else sd_event_exit(i->event, r); return 0; } static int raw_import_on_input(sd_event_source *s, int fd, uint32_t revents, void *userdata) { RawImport *i = userdata; return raw_import_process(i); } static int raw_import_on_defer(sd_event_source *s, void *userdata) { RawImport *i = userdata; return raw_import_process(i); } int raw_import_start(RawImport *i, int fd, const char *local, bool force_local, bool read_only) { int r; assert(i); assert(fd >= 0); assert(local); if (!machine_name_is_valid(local)) return -EINVAL; if (i->input_fd >= 0) return -EBUSY; r = fd_nonblock(fd, true); if (r < 0) return r; r = free_and_strdup(&i->local, local); if (r < 0) return r; i->force_local = force_local; i->read_only = read_only; if (fstat(fd, &i->st) < 0) return -errno; r = sd_event_add_io(i->event, &i->input_event_source, fd, EPOLLIN, raw_import_on_input, i); if (r == -EPERM) { /* This fd does not support epoll, for example because it is a regular file. Busy read in that case */ r = sd_event_add_defer(i->event, &i->input_event_source, raw_import_on_defer, i); if (r < 0) return r; r = sd_event_source_set_enabled(i->input_event_source, SD_EVENT_ON); } if (r < 0) return r; i->input_fd = fd; return r; } systemd-229/src/import/import-raw.h000066400000000000000000000023461265713322000174410ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-event.h" #include "import-util.h" #include "macro.h" typedef struct RawImport RawImport; typedef void (*RawImportFinished)(RawImport *import, int error, void *userdata); int raw_import_new(RawImport **import, sd_event *event, const char *image_root, RawImportFinished on_finished, void *userdata); RawImport* raw_import_unref(RawImport *import); DEFINE_TRIVIAL_CLEANUP_FUNC(RawImport*, raw_import_unref); int raw_import_start(RawImport *i, int fd, const char *local, bool force_local, bool read_only); systemd-229/src/import/import-tar.c000066400000000000000000000243041265713322000174270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-daemon.h" #include "sd-event.h" #include "alloc-util.h" #include "btrfs-util.h" #include "copy.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "hostname-util.h" #include "import-common.h" #include "import-compress.h" #include "import-tar.h" #include "io-util.h" #include "machine-pool.h" #include "mkdir.h" #include "path-util.h" #include "process-util.h" #include "qcow2-util.h" #include "ratelimit.h" #include "rm-rf.h" #include "string-util.h" #include "util.h" struct TarImport { sd_event *event; char *image_root; TarImportFinished on_finished; void *userdata; char *local; bool force_local; bool read_only; bool grow_machine_directory; char *temp_path; char *final_path; int input_fd; int tar_fd; ImportCompress compress; uint64_t written_since_last_grow; sd_event_source *input_event_source; uint8_t buffer[16*1024]; size_t buffer_size; uint64_t written_compressed; uint64_t written_uncompressed; struct stat st; pid_t tar_pid; unsigned last_percent; RateLimit progress_rate_limit; }; TarImport* tar_import_unref(TarImport *i) { if (!i) return NULL; sd_event_source_unref(i->input_event_source); if (i->tar_pid > 1) { (void) kill_and_sigcont(i->tar_pid, SIGKILL); (void) wait_for_terminate(i->tar_pid, NULL); } if (i->temp_path) { (void) rm_rf(i->temp_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); free(i->temp_path); } import_compress_free(&i->compress); sd_event_unref(i->event); safe_close(i->tar_fd); free(i->final_path); free(i->image_root); free(i->local); free(i); return NULL; } int tar_import_new( TarImport **ret, sd_event *event, const char *image_root, TarImportFinished on_finished, void *userdata) { _cleanup_(tar_import_unrefp) TarImport *i = NULL; int r; assert(ret); i = new0(TarImport, 1); if (!i) return -ENOMEM; i->input_fd = i->tar_fd = -1; i->on_finished = on_finished; i->userdata = userdata; RATELIMIT_INIT(i->progress_rate_limit, 100 * USEC_PER_MSEC, 1); i->last_percent = (unsigned) -1; i->image_root = strdup(image_root ?: "/var/lib/machines"); if (!i->image_root) return -ENOMEM; i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines"); if (event) i->event = sd_event_ref(event); else { r = sd_event_default(&i->event); if (r < 0) return r; } *ret = i; i = NULL; return 0; } static void tar_import_report_progress(TarImport *i) { unsigned percent; assert(i); /* We have no size information, unless the source is a regular file */ if (!S_ISREG(i->st.st_mode)) return; if (i->written_compressed >= (uint64_t) i->st.st_size) percent = 100; else percent = (unsigned) ((i->written_compressed * UINT64_C(100)) / (uint64_t) i->st.st_size); if (percent == i->last_percent) return; if (!ratelimit_test(&i->progress_rate_limit)) return; sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent); log_info("Imported %u%%.", percent); i->last_percent = percent; } static int tar_import_finish(TarImport *i) { int r; assert(i); assert(i->tar_fd >= 0); assert(i->temp_path); assert(i->final_path); i->tar_fd = safe_close(i->tar_fd); if (i->tar_pid > 0) { r = wait_for_terminate_and_warn("tar", i->tar_pid, true); i->tar_pid = 0; if (r < 0) return r; } if (i->read_only) { r = import_make_read_only(i->temp_path); if (r < 0) return r; } if (i->force_local) (void) rm_rf(i->final_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path); if (r < 0) return log_error_errno(r, "Failed to move image into place: %m"); i->temp_path = mfree(i->temp_path); return 0; } static int tar_import_fork_tar(TarImport *i) { int r; assert(i); assert(!i->final_path); assert(!i->temp_path); assert(i->tar_fd < 0); i->final_path = strjoin(i->image_root, "/", i->local, NULL); if (!i->final_path) return log_oom(); r = tempfn_random(i->final_path, NULL, &i->temp_path); if (r < 0) return log_oom(); (void) mkdir_parents_label(i->temp_path, 0700); r = btrfs_subvol_make(i->temp_path); if (r == -ENOTTY) { if (mkdir(i->temp_path, 0755) < 0) return log_error_errno(errno, "Failed to create directory %s: %m", i->temp_path); } else if (r < 0) return log_error_errno(r, "Failed to create subvolume %s: %m", i->temp_path); else (void) import_assign_pool_quota_and_warn(i->temp_path); i->tar_fd = import_fork_tar_x(i->temp_path, &i->tar_pid); if (i->tar_fd < 0) return i->tar_fd; return 0; } static int tar_import_write(const void *p, size_t sz, void *userdata) { TarImport *i = userdata; int r; if (i->grow_machine_directory && i->written_since_last_grow >= GROW_INTERVAL_BYTES) { i->written_since_last_grow = 0; grow_machine_directory(); } r = loop_write(i->tar_fd, p, sz, false); if (r < 0) return r; i->written_uncompressed += sz; i->written_since_last_grow += sz; return 0; } static int tar_import_process(TarImport *i) { ssize_t l; int r; assert(i); assert(i->buffer_size < sizeof(i->buffer)); l = read(i->input_fd, i->buffer + i->buffer_size, sizeof(i->buffer) - i->buffer_size); if (l < 0) { if (errno == EAGAIN) return 0; r = log_error_errno(errno, "Failed to read input file: %m"); goto finish; } if (l == 0) { if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) { log_error("Premature end of file: %m"); r = -EIO; goto finish; } r = tar_import_finish(i); goto finish; } i->buffer_size += l; if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) { r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size); if (r < 0) { log_error("Failed to detect file compression: %m"); goto finish; } if (r == 0) /* Need more data */ return 0; r = tar_import_fork_tar(i); if (r < 0) goto finish; } r = import_uncompress(&i->compress, i->buffer, i->buffer_size, tar_import_write, i); if (r < 0) { log_error_errno(r, "Failed to decode and write: %m"); goto finish; } i->written_compressed += i->buffer_size; i->buffer_size = 0; tar_import_report_progress(i); return 0; finish: if (i->on_finished) i->on_finished(i, r, i->userdata); else sd_event_exit(i->event, r); return 0; } static int tar_import_on_input(sd_event_source *s, int fd, uint32_t revents, void *userdata) { TarImport *i = userdata; return tar_import_process(i); } static int tar_import_on_defer(sd_event_source *s, void *userdata) { TarImport *i = userdata; return tar_import_process(i); } int tar_import_start(TarImport *i, int fd, const char *local, bool force_local, bool read_only) { int r; assert(i); assert(fd >= 0); assert(local); if (!machine_name_is_valid(local)) return -EINVAL; if (i->input_fd >= 0) return -EBUSY; r = fd_nonblock(fd, true); if (r < 0) return r; r = free_and_strdup(&i->local, local); if (r < 0) return r; i->force_local = force_local; i->read_only = read_only; if (fstat(fd, &i->st) < 0) return -errno; r = sd_event_add_io(i->event, &i->input_event_source, fd, EPOLLIN, tar_import_on_input, i); if (r == -EPERM) { /* This fd does not support epoll, for example because it is a regular file. Busy read in that case */ r = sd_event_add_defer(i->event, &i->input_event_source, tar_import_on_defer, i); if (r < 0) return r; r = sd_event_source_set_enabled(i->input_event_source, SD_EVENT_ON); } if (r < 0) return r; i->input_fd = fd; return r; } systemd-229/src/import/import-tar.h000066400000000000000000000023531265713322000174340ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-event.h" #include "import-util.h" #include "macro.h" typedef struct TarImport TarImport; typedef void (*TarImportFinished)(TarImport *import, int error, void *userdata); int tar_import_new(TarImport **import, sd_event *event, const char *image_root, TarImportFinished on_finished, void *userdata); TarImport* tar_import_unref(TarImport *import); DEFINE_TRIVIAL_CLEANUP_FUNC(TarImport*, tar_import_unref); int tar_import_start(TarImport *import, int fd, const char *local, bool force_local, bool read_only); systemd-229/src/import/import.c000066400000000000000000000255541265713322000166530ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-event.h" #include "alloc-util.h" #include "fd-util.h" #include "fs-util.h" #include "hostname-util.h" #include "import-raw.h" #include "import-tar.h" #include "import-util.h" #include "machine-image.h" #include "signal-util.h" #include "string-util.h" #include "verbs.h" static bool arg_force = false; static bool arg_read_only = false; static const char *arg_image_root = "/var/lib/machines"; static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { log_notice("Transfer aborted."); sd_event_exit(sd_event_source_get_event(s), EINTR); return 0; } static void on_tar_finished(TarImport *import, int error, void *userdata) { sd_event *event = userdata; assert(import); if (error == 0) log_info("Operation completed successfully."); sd_event_exit(event, abs(error)); } static int import_tar(int argc, char *argv[], void *userdata) { _cleanup_(tar_import_unrefp) TarImport *import = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; const char *path = NULL, *local = NULL; _cleanup_free_ char *ll = NULL; _cleanup_close_ int open_fd = -1; int r, fd; if (argc >= 2) path = argv[1]; if (isempty(path) || streq(path, "-")) path = NULL; if (argc >= 3) local = argv[2]; else if (path) local = basename(path); if (isempty(local) || streq(local, "-")) local = NULL; if (local) { r = tar_strip_suffixes(local, &ll); if (r < 0) return log_oom(); local = ll; if (!machine_name_is_valid(local)) { log_error("Local image name '%s' is not valid.", local); return -EINVAL; } if (!arg_force) { r = image_find(local, NULL); if (r < 0) return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local); else if (r > 0) { log_error_errno(EEXIST, "Image '%s' already exists.", local); return -EEXIST; } } } else local = "imported"; if (path) { open_fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (open_fd < 0) return log_error_errno(errno, "Failed to open tar image to import: %m"); fd = open_fd; log_info("Importing '%s', saving as '%s'.", path, local); } else { _cleanup_free_ char *pretty = NULL; fd = STDIN_FILENO; (void) readlink_malloc("/proc/self/fd/0", &pretty); log_info("Importing '%s', saving as '%s'.", strna(pretty), local); } r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to allocate event loop: %m"); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); r = tar_import_new(&import, event, arg_image_root, on_tar_finished, event); if (r < 0) return log_error_errno(r, "Failed to allocate importer: %m"); r = tar_import_start(import, fd, local, arg_force, arg_read_only); if (r < 0) return log_error_errno(r, "Failed to import image: %m"); r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); log_info("Exiting."); return -r; } static void on_raw_finished(RawImport *import, int error, void *userdata) { sd_event *event = userdata; assert(import); if (error == 0) log_info("Operation completed successfully."); sd_event_exit(event, abs(error)); } static int import_raw(int argc, char *argv[], void *userdata) { _cleanup_(raw_import_unrefp) RawImport *import = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; const char *path = NULL, *local = NULL; _cleanup_free_ char *ll = NULL; _cleanup_close_ int open_fd = -1; int r, fd; if (argc >= 2) path = argv[1]; if (isempty(path) || streq(path, "-")) path = NULL; if (argc >= 3) local = argv[2]; else if (path) local = basename(path); if (isempty(local) || streq(local, "-")) local = NULL; if (local) { r = raw_strip_suffixes(local, &ll); if (r < 0) return log_oom(); local = ll; if (!machine_name_is_valid(local)) { log_error("Local image name '%s' is not valid.", local); return -EINVAL; } if (!arg_force) { r = image_find(local, NULL); if (r < 0) return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local); else if (r > 0) { log_error_errno(EEXIST, "Image '%s' already exists.", local); return -EEXIST; } } } else local = "imported"; if (path) { open_fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (open_fd < 0) return log_error_errno(errno, "Failed to open raw image to import: %m"); fd = open_fd; log_info("Importing '%s', saving as '%s'.", path, local); } else { _cleanup_free_ char *pretty = NULL; fd = STDIN_FILENO; (void) readlink_malloc("/proc/self/fd/0", &pretty); log_info("Importing '%s', saving as '%s'.", pretty, local); } r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to allocate event loop: %m"); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); r = raw_import_new(&import, event, arg_image_root, on_raw_finished, event); if (r < 0) return log_error_errno(r, "Failed to allocate importer: %m"); r = raw_import_start(import, fd, local, arg_force, arg_read_only); if (r < 0) return log_error_errno(r, "Failed to import image: %m"); r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); log_info("Exiting."); return -r; } static int help(int argc, char *argv[], void *userdata) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" "Import container or virtual machine images.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --force Force creation of image\n" " --image-root=PATH Image root directory\n" " --read-only Create a read-only image\n\n" "Commands:\n" " tar FILE [NAME] Import a TAR image\n" " raw FILE [NAME] Import a RAW image\n", program_invocation_short_name); return 0; } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_FORCE, ARG_IMAGE_ROOT, ARG_READ_ONLY, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "force", no_argument, NULL, ARG_FORCE }, { "image-root", required_argument, NULL, ARG_IMAGE_ROOT }, { "read-only", no_argument, NULL, ARG_READ_ONLY }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': return help(0, NULL, NULL); case ARG_VERSION: return version(); case ARG_FORCE: arg_force = true; break; case ARG_IMAGE_ROOT: arg_image_root = optarg; break; case ARG_READ_ONLY: arg_read_only = true; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } static int import_main(int argc, char *argv[]) { static const Verb verbs[] = { { "help", VERB_ANY, VERB_ANY, 0, help }, { "tar", 2, 3, 0, import_tar }, { "raw", 2, 3, 0, import_raw }, {} }; return dispatch_verb(argc, argv, verbs, NULL); } int main(int argc, char *argv[]) { int r; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; (void) ignore_signals(SIGPIPE, -1); r = import_main(argc, argv); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/import/importd.c000066400000000000000000001103001265713322000167770ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-util.h" #include "def.h" #include "fd-util.h" #include "hostname-util.h" #include "import-util.h" #include "machine-pool.h" #include "missing.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "signal-util.h" #include "socket-util.h" #include "string-table.h" #include "strv.h" #include "syslog-util.h" #include "user-util.h" #include "util.h" #include "web-util.h" typedef struct Transfer Transfer; typedef struct Manager Manager; typedef enum TransferType { TRANSFER_IMPORT_TAR, TRANSFER_IMPORT_RAW, TRANSFER_EXPORT_TAR, TRANSFER_EXPORT_RAW, TRANSFER_PULL_TAR, TRANSFER_PULL_RAW, _TRANSFER_TYPE_MAX, _TRANSFER_TYPE_INVALID = -1, } TransferType; struct Transfer { Manager *manager; uint32_t id; char *object_path; TransferType type; ImportVerify verify; char *remote; char *local; bool force_local; bool read_only; char *format; pid_t pid; int log_fd; char log_message[LINE_MAX]; size_t log_message_size; sd_event_source *pid_event_source; sd_event_source *log_event_source; unsigned n_canceled; unsigned progress_percent; int stdin_fd; int stdout_fd; }; struct Manager { sd_event *event; sd_bus *bus; uint32_t current_transfer_id; Hashmap *transfers; Hashmap *polkit_registry; int notify_fd; sd_event_source *notify_event_source; }; #define TRANSFERS_MAX 64 static const char* const transfer_type_table[_TRANSFER_TYPE_MAX] = { [TRANSFER_IMPORT_TAR] = "import-tar", [TRANSFER_IMPORT_RAW] = "import-raw", [TRANSFER_EXPORT_TAR] = "export-tar", [TRANSFER_EXPORT_RAW] = "export-raw", [TRANSFER_PULL_TAR] = "pull-tar", [TRANSFER_PULL_RAW] = "pull-raw", }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(transfer_type, TransferType); static Transfer *transfer_unref(Transfer *t) { if (!t) return NULL; if (t->manager) hashmap_remove(t->manager->transfers, UINT32_TO_PTR(t->id)); sd_event_source_unref(t->pid_event_source); sd_event_source_unref(t->log_event_source); free(t->remote); free(t->local); free(t->format); free(t->object_path); if (t->pid > 0) { (void) kill_and_sigcont(t->pid, SIGKILL); (void) wait_for_terminate(t->pid, NULL); } safe_close(t->log_fd); safe_close(t->stdin_fd); safe_close(t->stdout_fd); free(t); return NULL; } DEFINE_TRIVIAL_CLEANUP_FUNC(Transfer*, transfer_unref); static int transfer_new(Manager *m, Transfer **ret) { _cleanup_(transfer_unrefp) Transfer *t = NULL; uint32_t id; int r; assert(m); assert(ret); if (hashmap_size(m->transfers) >= TRANSFERS_MAX) return -E2BIG; r = hashmap_ensure_allocated(&m->transfers, &trivial_hash_ops); if (r < 0) return r; t = new0(Transfer, 1); if (!t) return -ENOMEM; t->type = _TRANSFER_TYPE_INVALID; t->log_fd = -1; t->stdin_fd = -1; t->stdout_fd = -1; t->verify = _IMPORT_VERIFY_INVALID; id = m->current_transfer_id + 1; if (asprintf(&t->object_path, "/org/freedesktop/import1/transfer/_%" PRIu32, id) < 0) return -ENOMEM; r = hashmap_put(m->transfers, UINT32_TO_PTR(id), t); if (r < 0) return r; m->current_transfer_id = id; t->manager = m; t->id = id; *ret = t; t = NULL; return 0; } static void transfer_send_log_line(Transfer *t, const char *line) { int r, priority = LOG_INFO; assert(t); assert(line); syslog_parse_priority(&line, &priority, true); log_full(priority, "(transfer%" PRIu32 ") %s", t->id, line); r = sd_bus_emit_signal( t->manager->bus, t->object_path, "org.freedesktop.import1.Transfer", "LogMessage", "us", priority, line); if (r < 0) log_error_errno(r, "Cannot emit message: %m"); } static void transfer_send_logs(Transfer *t, bool flush) { assert(t); /* Try to send out all log messages, if we can. But if we * can't we remove the messages from the buffer, but don't * fail */ while (t->log_message_size > 0) { _cleanup_free_ char *n = NULL; char *e; if (t->log_message_size >= sizeof(t->log_message)) e = t->log_message + sizeof(t->log_message); else { char *a, *b; a = memchr(t->log_message, 0, t->log_message_size); b = memchr(t->log_message, '\n', t->log_message_size); if (a && b) e = a < b ? a : b; else if (a) e = a; else e = b; } if (!e) { if (!flush) return; e = t->log_message + t->log_message_size; } n = strndup(t->log_message, e - t->log_message); /* Skip over NUL and newlines */ while ((e < t->log_message + t->log_message_size) && (*e == 0 || *e == '\n')) e++; memmove(t->log_message, e, t->log_message + sizeof(t->log_message) - e); t->log_message_size -= e - t->log_message; if (!n) { log_oom(); continue; } if (isempty(n)) continue; transfer_send_log_line(t, n); } } static int transfer_finalize(Transfer *t, bool success) { int r; assert(t); transfer_send_logs(t, true); r = sd_bus_emit_signal( t->manager->bus, "/org/freedesktop/import1", "org.freedesktop.import1.Manager", "TransferRemoved", "uos", t->id, t->object_path, success ? "done" : t->n_canceled > 0 ? "canceled" : "failed"); if (r < 0) log_error_errno(r, "Cannot emit message: %m"); transfer_unref(t); return 0; } static int transfer_cancel(Transfer *t) { int r; assert(t); r = kill_and_sigcont(t->pid, t->n_canceled < 3 ? SIGTERM : SIGKILL); if (r < 0) return r; t->n_canceled++; return 0; } static int transfer_on_pid(sd_event_source *s, const siginfo_t *si, void *userdata) { Transfer *t = userdata; bool success = false; assert(s); assert(t); if (si->si_code == CLD_EXITED) { if (si->si_status != 0) log_error("Import process failed with exit code %i.", si->si_status); else { log_debug("Import process succeeded."); success = true; } } else if (si->si_code == CLD_KILLED || si->si_code == CLD_DUMPED) log_error("Import process terminated by signal %s.", signal_to_string(si->si_status)); else log_error("Import process failed due to unknown reason."); t->pid = 0; return transfer_finalize(t, success); } static int transfer_on_log(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Transfer *t = userdata; ssize_t l; assert(s); assert(t); l = read(fd, t->log_message + t->log_message_size, sizeof(t->log_message) - t->log_message_size); if (l <= 0) { /* EOF/read error. We just close the pipe here, and * close the watch, waiting for the SIGCHLD to arrive, * before we do anything else. */ if (l < 0) log_error_errno(errno, "Failed to read log message: %m"); t->log_event_source = sd_event_source_unref(t->log_event_source); return 0; } t->log_message_size += l; transfer_send_logs(t, false); return 0; } static int transfer_start(Transfer *t) { _cleanup_close_pair_ int pipefd[2] = { -1, -1 }; int r; assert(t); assert(t->pid <= 0); if (pipe2(pipefd, O_CLOEXEC) < 0) return -errno; t->pid = fork(); if (t->pid < 0) return -errno; if (t->pid == 0) { const char *cmd[] = { NULL, /* systemd-import, systemd-export or systemd-pull */ NULL, /* tar, raw */ NULL, /* --verify= */ NULL, /* verify argument */ NULL, /* maybe --force */ NULL, /* maybe --read-only */ NULL, /* if so: the actual URL */ NULL, /* maybe --format= */ NULL, /* if so: the actual format */ NULL, /* remote */ NULL, /* local */ NULL }; unsigned k = 0; /* Child */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); pipefd[0] = safe_close(pipefd[0]); if (dup2(pipefd[1], STDERR_FILENO) != STDERR_FILENO) { log_error_errno(errno, "Failed to dup2() fd: %m"); _exit(EXIT_FAILURE); } if (t->stdout_fd >= 0) { if (dup2(t->stdout_fd, STDOUT_FILENO) != STDOUT_FILENO) { log_error_errno(errno, "Failed to dup2() fd: %m"); _exit(EXIT_FAILURE); } if (t->stdout_fd != STDOUT_FILENO) safe_close(t->stdout_fd); } else { if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) { log_error_errno(errno, "Failed to dup2() fd: %m"); _exit(EXIT_FAILURE); } } if (pipefd[1] != STDOUT_FILENO && pipefd[1] != STDERR_FILENO) pipefd[1] = safe_close(pipefd[1]); if (t->stdin_fd >= 0) { if (dup2(t->stdin_fd, STDIN_FILENO) != STDIN_FILENO) { log_error_errno(errno, "Failed to dup2() fd: %m"); _exit(EXIT_FAILURE); } if (t->stdin_fd != STDIN_FILENO) safe_close(t->stdin_fd); } else { int null_fd; null_fd = open("/dev/null", O_RDONLY|O_NOCTTY); if (null_fd < 0) { log_error_errno(errno, "Failed to open /dev/null: %m"); _exit(EXIT_FAILURE); } if (dup2(null_fd, STDIN_FILENO) != STDIN_FILENO) { log_error_errno(errno, "Failed to dup2() fd: %m"); _exit(EXIT_FAILURE); } if (null_fd != STDIN_FILENO) safe_close(null_fd); } fd_cloexec(STDIN_FILENO, false); fd_cloexec(STDOUT_FILENO, false); fd_cloexec(STDERR_FILENO, false); setenv("SYSTEMD_LOG_TARGET", "console-prefixed", 1); setenv("NOTIFY_SOCKET", "/run/systemd/import/notify", 1); if (IN_SET(t->type, TRANSFER_IMPORT_TAR, TRANSFER_IMPORT_RAW)) cmd[k++] = SYSTEMD_IMPORT_PATH; else if (IN_SET(t->type, TRANSFER_EXPORT_TAR, TRANSFER_EXPORT_RAW)) cmd[k++] = SYSTEMD_EXPORT_PATH; else cmd[k++] = SYSTEMD_PULL_PATH; if (IN_SET(t->type, TRANSFER_IMPORT_TAR, TRANSFER_EXPORT_TAR, TRANSFER_PULL_TAR)) cmd[k++] = "tar"; else cmd[k++] = "raw"; if (t->verify != _IMPORT_VERIFY_INVALID) { cmd[k++] = "--verify"; cmd[k++] = import_verify_to_string(t->verify); } if (t->force_local) cmd[k++] = "--force"; if (t->read_only) cmd[k++] = "--read-only"; if (t->format) { cmd[k++] = "--format"; cmd[k++] = t->format; } if (!IN_SET(t->type, TRANSFER_EXPORT_TAR, TRANSFER_EXPORT_RAW)) { if (t->remote) cmd[k++] = t->remote; else cmd[k++] = "-"; } if (t->local) cmd[k++] = t->local; cmd[k] = NULL; execv(cmd[0], (char * const *) cmd); log_error_errno(errno, "Failed to execute %s tool: %m", cmd[0]); _exit(EXIT_FAILURE); } pipefd[1] = safe_close(pipefd[1]); t->log_fd = pipefd[0]; pipefd[0] = -1; t->stdin_fd = safe_close(t->stdin_fd); r = sd_event_add_child(t->manager->event, &t->pid_event_source, t->pid, WEXITED, transfer_on_pid, t); if (r < 0) return r; r = sd_event_add_io(t->manager->event, &t->log_event_source, t->log_fd, EPOLLIN, transfer_on_log, t); if (r < 0) return r; /* Make sure always process logging before SIGCHLD */ r = sd_event_source_set_priority(t->log_event_source, SD_EVENT_PRIORITY_NORMAL -5); if (r < 0) return r; r = sd_bus_emit_signal( t->manager->bus, "/org/freedesktop/import1", "org.freedesktop.import1.Manager", "TransferNew", "uo", t->id, t->object_path); if (r < 0) return r; return 0; } static Manager *manager_unref(Manager *m) { Transfer *t; if (!m) return NULL; sd_event_source_unref(m->notify_event_source); safe_close(m->notify_fd); while ((t = hashmap_first(m->transfers))) transfer_unref(t); hashmap_free(m->transfers); bus_verify_polkit_async_registry_free(m->polkit_registry); m->bus = sd_bus_flush_close_unref(m->bus); sd_event_unref(m->event); free(m); return NULL; } DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref); static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void *userdata) { char buf[NOTIFY_BUFFER_MAX+1]; struct iovec iovec = { .iov_base = buf, .iov_len = sizeof(buf)-1, }; union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)]; } control = {}; struct msghdr msghdr = { .msg_iov = &iovec, .msg_iovlen = 1, .msg_control = &control, .msg_controllen = sizeof(control), }; struct ucred *ucred = NULL; Manager *m = userdata; struct cmsghdr *cmsg; unsigned percent; char *p, *e; Transfer *t; Iterator i; ssize_t n; int r; n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); if (n < 0) { if (errno == EAGAIN || errno == EINTR) return 0; return -errno; } cmsg_close_all(&msghdr); CMSG_FOREACH(cmsg, &msghdr) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) ucred = (struct ucred*) CMSG_DATA(cmsg); if (msghdr.msg_flags & MSG_TRUNC) { log_warning("Got overly long notification datagram, ignoring."); return 0; } if (!ucred || ucred->pid <= 0) { log_warning("Got notification datagram lacking credential information, ignoring."); return 0; } HASHMAP_FOREACH(t, m->transfers, i) if (ucred->pid == t->pid) break; if (!t) { log_warning("Got notification datagram from unexpected peer, ignoring."); return 0; } buf[n] = 0; p = startswith(buf, "X_IMPORT_PROGRESS="); if (!p) { p = strstr(buf, "\nX_IMPORT_PROGRESS="); if (!p) return 0; p += 19; } e = strchrnul(p, '\n'); *e = 0; r = safe_atou(p, &percent); if (r < 0 || percent > 100) { log_warning("Got invalid percent value, ignoring."); return 0; } t->progress_percent = percent; log_debug("Got percentage from client: %u%%", percent); return 0; } static int manager_new(Manager **ret) { _cleanup_(manager_unrefp) Manager *m = NULL; static const union sockaddr_union sa = { .un.sun_family = AF_UNIX, .un.sun_path = "/run/systemd/import/notify", }; static const int one = 1; int r; assert(ret); m = new0(Manager, 1); if (!m) return -ENOMEM; r = sd_event_default(&m->event); if (r < 0) return r; sd_event_set_watchdog(m->event, true); r = sd_bus_default_system(&m->bus); if (r < 0) return r; m->notify_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (m->notify_fd < 0) return -errno; (void) mkdir_parents_label(sa.un.sun_path, 0755); (void) unlink(sa.un.sun_path); if (bind(m->notify_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)) < 0) return -errno; if (setsockopt(m->notify_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) return -errno; r = sd_event_add_io(m->event, &m->notify_event_source, m->notify_fd, EPOLLIN, manager_on_notify, m); if (r < 0) return r; *ret = m; m = NULL; return 0; } static Transfer *manager_find(Manager *m, TransferType type, const char *remote) { Transfer *t; Iterator i; assert(m); assert(type >= 0); assert(type < _TRANSFER_TYPE_MAX); HASHMAP_FOREACH(t, m->transfers, i) { if (t->type == type && streq_ptr(t->remote, remote)) return t; } return NULL; } static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) { _cleanup_(transfer_unrefp) Transfer *t = NULL; int fd, force, read_only, r; const char *local, *object; Manager *m = userdata; TransferType type; uint32_t id; assert(msg); assert(m); r = bus_verify_polkit_async( msg, CAP_SYS_ADMIN, "org.freedesktop.import1.import", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = sd_bus_message_read(msg, "hsbb", &fd, &local, &force, &read_only); if (r < 0) return r; if (!machine_name_is_valid(local)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local); r = setup_machine_directory((uint64_t) -1, error); if (r < 0) return r; type = streq_ptr(sd_bus_message_get_member(msg), "ImportTar") ? TRANSFER_IMPORT_TAR : TRANSFER_IMPORT_RAW; r = transfer_new(m, &t); if (r < 0) return r; t->type = type; t->force_local = force; t->read_only = read_only; t->local = strdup(local); if (!t->local) return -ENOMEM; t->stdin_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (t->stdin_fd < 0) return -errno; r = transfer_start(t); if (r < 0) return r; object = t->object_path; id = t->id; t = NULL; return sd_bus_reply_method_return(msg, "uo", id, object); } static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) { _cleanup_(transfer_unrefp) Transfer *t = NULL; int fd, r; const char *local, *object, *format; Manager *m = userdata; TransferType type; uint32_t id; assert(msg); assert(m); r = bus_verify_polkit_async( msg, CAP_SYS_ADMIN, "org.freedesktop.import1.export", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = sd_bus_message_read(msg, "shs", &local, &fd, &format); if (r < 0) return r; if (!machine_name_is_valid(local)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local); type = streq_ptr(sd_bus_message_get_member(msg), "ExportTar") ? TRANSFER_EXPORT_TAR : TRANSFER_EXPORT_RAW; r = transfer_new(m, &t); if (r < 0) return r; t->type = type; if (!isempty(format)) { t->format = strdup(format); if (!t->format) return -ENOMEM; } t->local = strdup(local); if (!t->local) return -ENOMEM; t->stdout_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (t->stdout_fd < 0) return -errno; r = transfer_start(t); if (r < 0) return r; object = t->object_path; id = t->id; t = NULL; return sd_bus_reply_method_return(msg, "uo", id, object); } static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) { _cleanup_(transfer_unrefp) Transfer *t = NULL; const char *remote, *local, *verify, *object; Manager *m = userdata; ImportVerify v; TransferType type; int force, r; uint32_t id; assert(msg); assert(m); r = bus_verify_polkit_async( msg, CAP_SYS_ADMIN, "org.freedesktop.import1.pull", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = sd_bus_message_read(msg, "sssb", &remote, &local, &verify, &force); if (r < 0) return r; if (!http_url_is_valid(remote)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "URL %s is invalid", remote); if (isempty(local)) local = NULL; else if (!machine_name_is_valid(local)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local); if (isempty(verify)) v = IMPORT_VERIFY_SIGNATURE; else v = import_verify_from_string(verify); if (v < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown verification mode %s", verify); r = setup_machine_directory((uint64_t) -1, error); if (r < 0) return r; type = streq_ptr(sd_bus_message_get_member(msg), "PullTar") ? TRANSFER_PULL_TAR : TRANSFER_PULL_RAW; if (manager_find(m, type, remote)) return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS, "Transfer for %s already in progress.", remote); r = transfer_new(m, &t); if (r < 0) return r; t->type = type; t->verify = v; t->force_local = force; t->remote = strdup(remote); if (!t->remote) return -ENOMEM; if (local) { t->local = strdup(local); if (!t->local) return -ENOMEM; } r = transfer_start(t); if (r < 0) return r; object = t->object_path; id = t->id; t = NULL; return sd_bus_reply_method_return(msg, "uo", id, object); } static int method_list_transfers(sd_bus_message *msg, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; Transfer *t; Iterator i; int r; assert(msg); assert(m); r = sd_bus_message_new_method_return(msg, &reply); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "(usssdo)"); if (r < 0) return r; HASHMAP_FOREACH(t, m->transfers, i) { r = sd_bus_message_append( reply, "(usssdo)", t->id, transfer_type_to_string(t->type), t->remote, t->local, (double) t->progress_percent / 100.0, t->object_path); if (r < 0) return r; } r = sd_bus_message_close_container(reply); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); } static int method_cancel(sd_bus_message *msg, void *userdata, sd_bus_error *error) { Transfer *t = userdata; int r; assert(msg); assert(t); r = bus_verify_polkit_async( msg, CAP_SYS_ADMIN, "org.freedesktop.import1.pull", NULL, false, UID_INVALID, &t->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = transfer_cancel(t); if (r < 0) return r; return sd_bus_reply_method_return(msg, NULL); } static int method_cancel_transfer(sd_bus_message *msg, void *userdata, sd_bus_error *error) { Manager *m = userdata; Transfer *t; uint32_t id; int r; assert(msg); assert(m); r = bus_verify_polkit_async( msg, CAP_SYS_ADMIN, "org.freedesktop.import1.pull", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = sd_bus_message_read(msg, "u", &id); if (r < 0) return r; if (id <= 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid transfer id"); t = hashmap_get(m->transfers, UINT32_TO_PTR(id)); if (!t) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_TRANSFER, "No transfer by id %" PRIu32, id); r = transfer_cancel(t); if (r < 0) return r; return sd_bus_reply_method_return(msg, NULL); } static int property_get_progress( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Transfer *t = userdata; assert(bus); assert(reply); assert(t); return sd_bus_message_append(reply, "d", (double) t->progress_percent / 100.0); } static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, transfer_type, TransferType); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_verify, import_verify, ImportVerify); static const sd_bus_vtable transfer_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Transfer, id), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Local", "s", NULL, offsetof(Transfer, local), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Remote", "s", NULL, offsetof(Transfer, remote), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Transfer, type), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Verify", "s", property_get_verify, offsetof(Transfer, verify), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0), SD_BUS_METHOD("Cancel", NULL, NULL, method_cancel, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("LogMessage", "us", 0), SD_BUS_VTABLE_END, }; static const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_METHOD("ImportTar", "hsbb", "uo", method_import_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ImportRaw", "hsbb", "uo", method_import_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ExportTar", "shs", "uo", method_export_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ExportRaw", "shs", "uo", method_export_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("PullTar", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("PullRaw", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ListTransfers", NULL, "a(usssdo)", method_list_transfers, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CancelTransfer", "u", NULL, method_cancel_transfer, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("TransferNew", "uo", 0), SD_BUS_SIGNAL("TransferRemoved", "uos", 0), SD_BUS_VTABLE_END, }; static int transfer_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; Transfer *t; const char *p; uint32_t id; int r; assert(bus); assert(path); assert(interface); assert(found); assert(m); p = startswith(path, "/org/freedesktop/import1/transfer/_"); if (!p) return 0; r = safe_atou32(p, &id); if (r < 0 || id == 0) return 0; t = hashmap_get(m->transfers, UINT32_TO_PTR(id)); if (!t) return 0; *found = t; return 1; } static int transfer_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; Manager *m = userdata; Transfer *t; unsigned k = 0; Iterator i; l = new0(char*, hashmap_size(m->transfers) + 1); if (!l) return -ENOMEM; HASHMAP_FOREACH(t, m->transfers, i) { l[k] = strdup(t->object_path); if (!l[k]) return -ENOMEM; k++; } *nodes = l; l = NULL; return 1; } static int manager_add_bus_objects(Manager *m) { int r; assert(m); r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/import1", "org.freedesktop.import1.Manager", manager_vtable, m); if (r < 0) return log_error_errno(r, "Failed to register object: %m"); r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/import1/transfer", "org.freedesktop.import1.Transfer", transfer_vtable, transfer_object_find, m); if (r < 0) return log_error_errno(r, "Failed to register object: %m"); r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/import1/transfer", transfer_node_enumerator, m); if (r < 0) return log_error_errno(r, "Failed to add transfer enumerator: %m"); r = sd_bus_request_name(m->bus, "org.freedesktop.import1", 0); if (r < 0) return log_error_errno(r, "Failed to register name: %m"); r = sd_bus_attach_event(m->bus, m->event, 0); if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop: %m"); return 0; } static bool manager_check_idle(void *userdata) { Manager *m = userdata; return hashmap_isempty(m->transfers); } static int manager_run(Manager *m) { assert(m); return bus_event_loop_with_idle( m->event, m->bus, "org.freedesktop.import1", DEFAULT_EXIT_USEC, manager_check_idle, m); } int main(int argc, char *argv[]) { _cleanup_(manager_unrefp) Manager *m = NULL; int r; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); if (argc != 1) { log_error("This program takes no arguments."); r = -EINVAL; goto finish; } assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0); r = manager_new(&m); if (r < 0) { log_error_errno(r, "Failed to allocate manager object: %m"); goto finish; } r = manager_add_bus_objects(m); if (r < 0) goto finish; r = manager_run(m); if (r < 0) { log_error_errno(r, "Failed to run event loop: %m"); goto finish; } finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/import/org.freedesktop.import1.conf000066400000000000000000000047371265713322000225370ustar00rootroot00000000000000 systemd-229/src/import/org.freedesktop.import1.policy.in000066400000000000000000000041711265713322000235060ustar00rootroot00000000000000 The systemd Project http://www.freedesktop.org/wiki/Software/systemd <_description>Import a VM or container image <_message>Authentication is required to import a VM or container image auth_admin auth_admin auth_admin_keep <_description>Export a VM or container image <_message>Authentication is required to export a VM or container image auth_admin auth_admin auth_admin_keep <_description>Download a VM or container image <_message>Authentication is required to download a VM or container image auth_admin auth_admin auth_admin_keep systemd-229/src/import/org.freedesktop.import1.service000066400000000000000000000006371265713322000232450ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] Name=org.freedesktop.import1 Exec=/bin/false User=root SystemdService=dbus-org.freedesktop.import1.service systemd-229/src/import/pull-common.c000066400000000000000000000423121265713322000175720ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "btrfs-util.h" #include "capability-util.h" #include "copy.h" #include "dirent-util.h" #include "escape.h" #include "fd-util.h" #include "io-util.h" #include "path-util.h" #include "process-util.h" #include "pull-common.h" #include "pull-job.h" #include "rm-rf.h" #include "signal-util.h" #include "siphash24.h" #include "string-util.h" #include "strv.h" #include "util.h" #include "web-util.h" #define FILENAME_ESCAPE "/.#\"\'" #define HASH_URL_THRESHOLD_LENGTH (_POSIX_PATH_MAX - 16) int pull_find_old_etags( const char *url, const char *image_root, int dt, const char *prefix, const char *suffix, char ***etags) { _cleanup_free_ char *escaped_url = NULL; _cleanup_closedir_ DIR *d = NULL; _cleanup_strv_free_ char **l = NULL; struct dirent *de; int r; assert(url); assert(etags); if (!image_root) image_root = "/var/lib/machines"; escaped_url = xescape(url, FILENAME_ESCAPE); if (!escaped_url) return -ENOMEM; d = opendir(image_root); if (!d) { if (errno == ENOENT) { *etags = NULL; return 0; } return -errno; } FOREACH_DIRENT_ALL(de, d, return -errno) { const char *a, *b; char *u; if (de->d_type != DT_UNKNOWN && de->d_type != dt) continue; if (prefix) { a = startswith(de->d_name, prefix); if (!a) continue; } else a = de->d_name; a = startswith(a, escaped_url); if (!a) continue; a = startswith(a, "."); if (!a) continue; if (suffix) { b = endswith(de->d_name, suffix); if (!b) continue; } else b = strchr(de->d_name, 0); if (a >= b) continue; r = cunescape_length(a, b - a, 0, &u); if (r < 0) return r; if (!http_etag_is_valid(u)) { free(u); continue; } r = strv_consume(&l, u); if (r < 0) return r; } *etags = l; l = NULL; return 0; } int pull_make_local_copy(const char *final, const char *image_root, const char *local, bool force_local) { const char *p; int r; assert(final); assert(local); if (!image_root) image_root = "/var/lib/machines"; p = strjoina(image_root, "/", local); if (force_local) (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); r = btrfs_subvol_snapshot(final, p, BTRFS_SNAPSHOT_QUOTA); if (r == -ENOTTY) { r = copy_tree(final, p, false); if (r < 0) return log_error_errno(r, "Failed to copy image: %m"); } else if (r < 0) return log_error_errno(r, "Failed to create local image: %m"); log_info("Created new local image '%s'.", local); return 0; } static int hash_url(const char *url, char **ret) { uint64_t h; static const sd_id128_t k = SD_ID128_ARRAY(df,89,16,87,01,cc,42,30,98,ab,4a,19,a6,a5,63,4f); assert(url); h = siphash24(url, strlen(url), k.bytes); if (asprintf(ret, "%"PRIx64, h) < 0) return -ENOMEM; return 0; } int pull_make_path(const char *url, const char *etag, const char *image_root, const char *prefix, const char *suffix, char **ret) { _cleanup_free_ char *escaped_url = NULL, *escaped_etag = NULL; char *path; assert(url); assert(ret); if (!image_root) image_root = "/var/lib/machines"; escaped_url = xescape(url, FILENAME_ESCAPE); if (!escaped_url) return -ENOMEM; if (etag) { escaped_etag = xescape(etag, FILENAME_ESCAPE); if (!escaped_etag) return -ENOMEM; } path = strjoin(image_root, "/", strempty(prefix), escaped_url, escaped_etag ? "." : "", strempty(escaped_etag), strempty(suffix), NULL); if (!path) return -ENOMEM; /* URLs might make the path longer than the maximum allowed length for a file name. * When that happens, a URL hash is used instead. Paths returned by this function * can be later used with tempfn_random() which adds 16 bytes to the resulting name. */ if (strlen(path) >= HASH_URL_THRESHOLD_LENGTH) { _cleanup_free_ char *hash = NULL; int r; free(path); r = hash_url(url, &hash); if (r < 0) return r; path = strjoin(image_root, "/", strempty(prefix), hash, escaped_etag ? "." : "", strempty(escaped_etag), strempty(suffix), NULL); if (!path) return -ENOMEM; } *ret = path; return 0; } int pull_make_settings_job( PullJob **ret, const char *url, CurlGlue *glue, PullJobFinished on_finished, void *userdata) { _cleanup_free_ char *last_component = NULL, *ll = NULL, *settings_url = NULL; _cleanup_(pull_job_unrefp) PullJob *job = NULL; const char *q; int r; assert(ret); assert(url); assert(glue); r = import_url_last_component(url, &last_component); if (r < 0) return r; r = tar_strip_suffixes(last_component, &ll); if (r < 0) return r; q = strjoina(ll, ".nspawn"); r = import_url_change_last_component(url, q, &settings_url); if (r < 0) return r; r = pull_job_new(&job, settings_url, glue, userdata); if (r < 0) return r; job->on_finished = on_finished; job->compressed_max = job->uncompressed_max = 1ULL * 1024ULL * 1024ULL; *ret = job; job = NULL; return 0; } int pull_make_verification_jobs( PullJob **ret_checksum_job, PullJob **ret_signature_job, ImportVerify verify, const char *url, CurlGlue *glue, PullJobFinished on_finished, void *userdata) { _cleanup_(pull_job_unrefp) PullJob *checksum_job = NULL, *signature_job = NULL; int r; assert(ret_checksum_job); assert(ret_signature_job); assert(verify >= 0); assert(verify < _IMPORT_VERIFY_MAX); assert(url); assert(glue); if (verify != IMPORT_VERIFY_NO) { _cleanup_free_ char *checksum_url = NULL; /* Queue job for the SHA256SUMS file for the image */ r = import_url_change_last_component(url, "SHA256SUMS", &checksum_url); if (r < 0) return r; r = pull_job_new(&checksum_job, checksum_url, glue, userdata); if (r < 0) return r; checksum_job->on_finished = on_finished; checksum_job->uncompressed_max = checksum_job->compressed_max = 1ULL * 1024ULL * 1024ULL; } if (verify == IMPORT_VERIFY_SIGNATURE) { _cleanup_free_ char *signature_url = NULL; /* Queue job for the SHA256SUMS.gpg file for the image. */ r = import_url_change_last_component(url, "SHA256SUMS.gpg", &signature_url); if (r < 0) return r; r = pull_job_new(&signature_job, signature_url, glue, userdata); if (r < 0) return r; signature_job->on_finished = on_finished; signature_job->uncompressed_max = signature_job->compressed_max = 1ULL * 1024ULL * 1024ULL; } *ret_checksum_job = checksum_job; *ret_signature_job = signature_job; checksum_job = signature_job = NULL; return 0; } int pull_verify(PullJob *main_job, PullJob *settings_job, PullJob *checksum_job, PullJob *signature_job) { _cleanup_close_pair_ int gpg_pipe[2] = { -1, -1 }; _cleanup_free_ char *fn = NULL; _cleanup_close_ int sig_file = -1; const char *p, *line; char sig_file_path[] = "/tmp/sigXXXXXX", gpg_home[] = "/tmp/gpghomeXXXXXX"; _cleanup_sigkill_wait_ pid_t pid = 0; bool gpg_home_created = false; int r; assert(main_job); assert(main_job->state == PULL_JOB_DONE); if (!checksum_job) return 0; assert(main_job->calc_checksum); assert(main_job->checksum); assert(checksum_job->state == PULL_JOB_DONE); if (!checksum_job->payload || checksum_job->payload_size <= 0) { log_error("Checksum is empty, cannot verify."); return -EBADMSG; } r = import_url_last_component(main_job->url, &fn); if (r < 0) return log_oom(); if (!filename_is_valid(fn)) { log_error("Cannot verify checksum, could not determine valid server-side file name."); return -EBADMSG; } line = strjoina(main_job->checksum, " *", fn, "\n"); p = memmem(checksum_job->payload, checksum_job->payload_size, line, strlen(line)); if (!p || (p != (char*) checksum_job->payload && p[-1] != '\n')) { log_error("DOWNLOAD INVALID: Checksum did not check out, payload has been tampered with."); return -EBADMSG; } log_info("SHA256 checksum of %s is valid.", main_job->url); assert(!settings_job || IN_SET(settings_job->state, PULL_JOB_DONE, PULL_JOB_FAILED)); if (settings_job && settings_job->state == PULL_JOB_DONE && settings_job->error == 0 && !settings_job->etag_exists) { _cleanup_free_ char *settings_fn = NULL; assert(settings_job->calc_checksum); assert(settings_job->checksum); r = import_url_last_component(settings_job->url, &settings_fn); if (r < 0) return log_oom(); if (!filename_is_valid(settings_fn)) { log_error("Cannot verify checksum, could not determine server-side settings file name."); return -EBADMSG; } line = strjoina(settings_job->checksum, " *", settings_fn, "\n"); p = memmem(checksum_job->payload, checksum_job->payload_size, line, strlen(line)); if (!p || (p != (char*) checksum_job->payload && p[-1] != '\n')) { log_error("DOWNLOAD INVALID: Checksum of settings file did not checkout, settings file has been tampered with."); return -EBADMSG; } log_info("SHA256 checksum of %s is valid.", settings_job->url); } if (!signature_job) return 0; assert(signature_job->state == PULL_JOB_DONE); if (!signature_job->payload || signature_job->payload_size <= 0) { log_error("Signature is empty, cannot verify."); return -EBADMSG; } r = pipe2(gpg_pipe, O_CLOEXEC); if (r < 0) return log_error_errno(errno, "Failed to create pipe for gpg: %m"); sig_file = mkostemp(sig_file_path, O_RDWR); if (sig_file < 0) return log_error_errno(errno, "Failed to create temporary file: %m"); r = loop_write(sig_file, signature_job->payload, signature_job->payload_size, false); if (r < 0) { log_error_errno(r, "Failed to write to temporary file: %m"); goto finish; } if (!mkdtemp(gpg_home)) { r = log_error_errno(errno, "Failed to create tempory home for gpg: %m"); goto finish; } gpg_home_created = true; pid = fork(); if (pid < 0) return log_error_errno(errno, "Failed to fork off gpg: %m"); if (pid == 0) { const char *cmd[] = { "gpg", "--no-options", "--no-default-keyring", "--no-auto-key-locate", "--no-auto-check-trustdb", "--batch", "--trust-model=always", NULL, /* --homedir= */ NULL, /* --keyring= */ NULL, /* --verify */ NULL, /* signature file */ NULL, /* dash */ NULL /* trailing NULL */ }; unsigned k = ELEMENTSOF(cmd) - 6; int null_fd; /* Child */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); gpg_pipe[1] = safe_close(gpg_pipe[1]); if (dup2(gpg_pipe[0], STDIN_FILENO) != STDIN_FILENO) { log_error_errno(errno, "Failed to dup2() fd: %m"); _exit(EXIT_FAILURE); } if (gpg_pipe[0] != STDIN_FILENO) gpg_pipe[0] = safe_close(gpg_pipe[0]); null_fd = open("/dev/null", O_WRONLY|O_NOCTTY); if (null_fd < 0) { log_error_errno(errno, "Failed to open /dev/null: %m"); _exit(EXIT_FAILURE); } if (dup2(null_fd, STDOUT_FILENO) != STDOUT_FILENO) { log_error_errno(errno, "Failed to dup2() fd: %m"); _exit(EXIT_FAILURE); } if (null_fd != STDOUT_FILENO) null_fd = safe_close(null_fd); cmd[k++] = strjoina("--homedir=", gpg_home); /* We add the user keyring only to the command line * arguments, if it's around since gpg fails * otherwise. */ if (access(USER_KEYRING_PATH, F_OK) >= 0) cmd[k++] = "--keyring=" USER_KEYRING_PATH; else cmd[k++] = "--keyring=" VENDOR_KEYRING_PATH; cmd[k++] = "--verify"; cmd[k++] = sig_file_path; cmd[k++] = "-"; cmd[k++] = NULL; fd_cloexec(STDIN_FILENO, false); fd_cloexec(STDOUT_FILENO, false); fd_cloexec(STDERR_FILENO, false); execvp("gpg2", (char * const *) cmd); execvp("gpg", (char * const *) cmd); log_error_errno(errno, "Failed to execute gpg: %m"); _exit(EXIT_FAILURE); } gpg_pipe[0] = safe_close(gpg_pipe[0]); r = loop_write(gpg_pipe[1], checksum_job->payload, checksum_job->payload_size, false); if (r < 0) { log_error_errno(r, "Failed to write to pipe: %m"); goto finish; } gpg_pipe[1] = safe_close(gpg_pipe[1]); r = wait_for_terminate_and_warn("gpg", pid, true); pid = 0; if (r < 0) goto finish; if (r > 0) { log_error("DOWNLOAD INVALID: Signature verification failed."); r = -EBADMSG; } else { log_info("Signature verification succeeded."); r = 0; } finish: if (sig_file >= 0) (void) unlink(sig_file_path); if (gpg_home_created) (void) rm_rf(gpg_home, REMOVE_ROOT|REMOVE_PHYSICAL); return r; } systemd-229/src/import/pull-common.h000066400000000000000000000030511265713322000175740ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "import-util.h" #include "pull-job.h" int pull_make_local_copy(const char *final, const char *root, const char *local, bool force_local); int pull_find_old_etags(const char *url, const char *root, int dt, const char *prefix, const char *suffix, char ***etags); int pull_make_path(const char *url, const char *etag, const char *image_root, const char *prefix, const char *suffix, char **ret); int pull_make_settings_job(PullJob **ret, const char *url, CurlGlue *glue, PullJobFinished on_finished, void *userdata); int pull_make_verification_jobs(PullJob **ret_checksum_job, PullJob **ret_signature_job, ImportVerify verify, const char *url, CurlGlue *glue, PullJobFinished on_finished, void *userdata); int pull_verify(PullJob *main_job, PullJob *settings_job, PullJob *checksum_job, PullJob *signature_job); systemd-229/src/import/pull-job.c000066400000000000000000000433321265713322000170570ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "fd-util.h" #include "hexdecoct.h" #include "io-util.h" #include "machine-pool.h" #include "parse-util.h" #include "pull-job.h" #include "string-util.h" #include "strv.h" #include "xattr-util.h" PullJob* pull_job_unref(PullJob *j) { if (!j) return NULL; curl_glue_remove_and_free(j->glue, j->curl); curl_slist_free_all(j->request_header); safe_close(j->disk_fd); import_compress_free(&j->compress); if (j->checksum_context) gcry_md_close(j->checksum_context); free(j->url); free(j->etag); strv_free(j->old_etags); free(j->payload); free(j->checksum); free(j); return NULL; } static void pull_job_finish(PullJob *j, int ret) { assert(j); if (j->state == PULL_JOB_DONE || j->state == PULL_JOB_FAILED) return; if (ret == 0) { j->state = PULL_JOB_DONE; j->progress_percent = 100; log_info("Download of %s complete.", j->url); } else { j->state = PULL_JOB_FAILED; j->error = ret; } if (j->on_finished) j->on_finished(j); } void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) { PullJob *j = NULL; CURLcode code; long status; int r; if (curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&j) != CURLE_OK) return; if (!j || j->state == PULL_JOB_DONE || j->state == PULL_JOB_FAILED) return; if (result != CURLE_OK) { log_error("Transfer failed: %s", curl_easy_strerror(result)); r = -EIO; goto finish; } code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status); if (code != CURLE_OK) { log_error("Failed to retrieve response code: %s", curl_easy_strerror(code)); r = -EIO; goto finish; } else if (status == 304) { log_info("Image already downloaded. Skipping download."); j->etag_exists = true; r = 0; goto finish; } else if (status >= 300) { log_error("HTTP request to %s failed with code %li.", j->url, status); r = -EIO; goto finish; } else if (status < 200) { log_error("HTTP request to %s finished with unexpected code %li.", j->url, status); r = -EIO; goto finish; } if (j->state != PULL_JOB_RUNNING) { log_error("Premature connection termination."); r = -EIO; goto finish; } if (j->content_length != (uint64_t) -1 && j->content_length != j->written_compressed) { log_error("Download truncated."); r = -EIO; goto finish; } if (j->checksum_context) { uint8_t *k; k = gcry_md_read(j->checksum_context, GCRY_MD_SHA256); if (!k) { log_error("Failed to get checksum."); r = -EIO; goto finish; } j->checksum = hexmem(k, gcry_md_get_algo_dlen(GCRY_MD_SHA256)); if (!j->checksum) { r = log_oom(); goto finish; } log_debug("SHA256 of %s is %s.", j->url, j->checksum); } if (j->disk_fd >= 0 && j->allow_sparse) { /* Make sure the file size is right, in case the file was * sparse and we just seeked for the last part */ if (ftruncate(j->disk_fd, j->written_uncompressed) < 0) { r = log_error_errno(errno, "Failed to truncate file: %m"); goto finish; } if (j->etag) (void) fsetxattr(j->disk_fd, "user.source_etag", j->etag, strlen(j->etag), 0); if (j->url) (void) fsetxattr(j->disk_fd, "user.source_url", j->url, strlen(j->url), 0); if (j->mtime != 0) { struct timespec ut[2]; timespec_store(&ut[0], j->mtime); ut[1] = ut[0]; (void) futimens(j->disk_fd, ut); (void) fd_setcrtime(j->disk_fd, j->mtime); } } r = 0; finish: pull_job_finish(j, r); } static int pull_job_write_uncompressed(const void *p, size_t sz, void *userdata) { PullJob *j = userdata; ssize_t n; assert(j); assert(p); if (sz <= 0) return 0; if (j->written_uncompressed + sz < j->written_uncompressed) { log_error("File too large, overflow"); return -EOVERFLOW; } if (j->written_uncompressed + sz > j->uncompressed_max) { log_error("File overly large, refusing"); return -EFBIG; } if (j->disk_fd >= 0) { if (j->grow_machine_directory && j->written_since_last_grow >= GROW_INTERVAL_BYTES) { j->written_since_last_grow = 0; grow_machine_directory(); } if (j->allow_sparse) n = sparse_write(j->disk_fd, p, sz, 64); else n = write(j->disk_fd, p, sz); if (n < 0) return log_error_errno(errno, "Failed to write file: %m"); if ((size_t) n < sz) { log_error("Short write"); return -EIO; } } else { if (!GREEDY_REALLOC(j->payload, j->payload_allocated, j->payload_size + sz)) return log_oom(); memcpy(j->payload + j->payload_size, p, sz); j->payload_size += sz; } j->written_uncompressed += sz; j->written_since_last_grow += sz; return 0; } static int pull_job_write_compressed(PullJob *j, void *p, size_t sz) { int r; assert(j); assert(p); if (sz <= 0) return 0; if (j->written_compressed + sz < j->written_compressed) { log_error("File too large, overflow"); return -EOVERFLOW; } if (j->written_compressed + sz > j->compressed_max) { log_error("File overly large, refusing."); return -EFBIG; } if (j->content_length != (uint64_t) -1 && j->written_compressed + sz > j->content_length) { log_error("Content length incorrect."); return -EFBIG; } if (j->checksum_context) gcry_md_write(j->checksum_context, p, sz); r = import_uncompress(&j->compress, p, sz, pull_job_write_uncompressed, j); if (r < 0) return r; j->written_compressed += sz; return 0; } static int pull_job_open_disk(PullJob *j) { int r; assert(j); if (j->on_open_disk) { r = j->on_open_disk(j); if (r < 0) return r; } if (j->disk_fd >= 0) { /* Check if we can do sparse files */ if (lseek(j->disk_fd, SEEK_SET, 0) == 0) j->allow_sparse = true; else { if (errno != ESPIPE) return log_error_errno(errno, "Failed to seek on file descriptor: %m"); j->allow_sparse = false; } } if (j->calc_checksum) { if (gcry_md_open(&j->checksum_context, GCRY_MD_SHA256, 0) != 0) { log_error("Failed to initialize hash context."); return -EIO; } } return 0; } static int pull_job_detect_compression(PullJob *j) { _cleanup_free_ uint8_t *stub = NULL; size_t stub_size; int r; assert(j); r = import_uncompress_detect(&j->compress, j->payload, j->payload_size); if (r < 0) return log_error_errno(r, "Failed to initialize compressor: %m"); if (r == 0) return 0; log_debug("Stream is compressed: %s", import_compress_type_to_string(j->compress.type)); r = pull_job_open_disk(j); if (r < 0) return r; /* Now, take the payload we read so far, and decompress it */ stub = j->payload; stub_size = j->payload_size; j->payload = NULL; j->payload_size = 0; j->payload_allocated = 0; j->state = PULL_JOB_RUNNING; r = pull_job_write_compressed(j, stub, stub_size); if (r < 0) return r; return 0; } static size_t pull_job_write_callback(void *contents, size_t size, size_t nmemb, void *userdata) { PullJob *j = userdata; size_t sz = size * nmemb; int r; assert(contents); assert(j); switch (j->state) { case PULL_JOB_ANALYZING: /* Let's first check what it actually is */ if (!GREEDY_REALLOC(j->payload, j->payload_allocated, j->payload_size + sz)) { r = log_oom(); goto fail; } memcpy(j->payload + j->payload_size, contents, sz); j->payload_size += sz; r = pull_job_detect_compression(j); if (r < 0) goto fail; break; case PULL_JOB_RUNNING: r = pull_job_write_compressed(j, contents, sz); if (r < 0) goto fail; break; case PULL_JOB_DONE: case PULL_JOB_FAILED: r = -ESTALE; goto fail; default: assert_not_reached("Impossible state."); } return sz; fail: pull_job_finish(j, r); return 0; } static size_t pull_job_header_callback(void *contents, size_t size, size_t nmemb, void *userdata) { PullJob *j = userdata; size_t sz = size * nmemb; _cleanup_free_ char *length = NULL, *last_modified = NULL; char *etag; int r; assert(contents); assert(j); if (j->state == PULL_JOB_DONE || j->state == PULL_JOB_FAILED) { r = -ESTALE; goto fail; } assert(j->state == PULL_JOB_ANALYZING); r = curl_header_strdup(contents, sz, "ETag:", &etag); if (r < 0) { log_oom(); goto fail; } if (r > 0) { free(j->etag); j->etag = etag; if (strv_contains(j->old_etags, j->etag)) { log_info("Image already downloaded. Skipping download."); j->etag_exists = true; pull_job_finish(j, 0); return sz; } return sz; } r = curl_header_strdup(contents, sz, "Content-Length:", &length); if (r < 0) { log_oom(); goto fail; } if (r > 0) { (void) safe_atou64(length, &j->content_length); if (j->content_length != (uint64_t) -1) { char bytes[FORMAT_BYTES_MAX]; if (j->content_length > j->compressed_max) { log_error("Content too large."); r = -EFBIG; goto fail; } log_info("Downloading %s for %s.", format_bytes(bytes, sizeof(bytes), j->content_length), j->url); } return sz; } r = curl_header_strdup(contents, sz, "Last-Modified:", &last_modified); if (r < 0) { log_oom(); goto fail; } if (r > 0) { (void) curl_parse_http_time(last_modified, &j->mtime); return sz; } if (j->on_header) { r = j->on_header(j, contents, sz); if (r < 0) goto fail; } return sz; fail: pull_job_finish(j, r); return 0; } static int pull_job_progress_callback(void *userdata, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { PullJob *j = userdata; unsigned percent; usec_t n; assert(j); if (dltotal <= 0) return 0; percent = ((100 * dlnow) / dltotal); n = now(CLOCK_MONOTONIC); if (n > j->last_status_usec + USEC_PER_SEC && percent != j->progress_percent && dlnow < dltotal) { char buf[FORMAT_TIMESPAN_MAX]; if (n - j->start_usec > USEC_PER_SEC && dlnow > 0) { char y[FORMAT_BYTES_MAX]; usec_t left, done; done = n - j->start_usec; left = (usec_t) (((double) done * (double) dltotal) / dlnow) - done; log_info("Got %u%% of %s. %s left at %s/s.", percent, j->url, format_timespan(buf, sizeof(buf), left, USEC_PER_SEC), format_bytes(y, sizeof(y), (uint64_t) ((double) dlnow / ((double) done / (double) USEC_PER_SEC)))); } else log_info("Got %u%% of %s.", percent, j->url); j->progress_percent = percent; j->last_status_usec = n; if (j->on_progress) j->on_progress(j); } return 0; } int pull_job_new(PullJob **ret, const char *url, CurlGlue *glue, void *userdata) { _cleanup_(pull_job_unrefp) PullJob *j = NULL; assert(url); assert(glue); assert(ret); j = new0(PullJob, 1); if (!j) return -ENOMEM; j->state = PULL_JOB_INIT; j->disk_fd = -1; j->userdata = userdata; j->glue = glue; j->content_length = (uint64_t) -1; j->start_usec = now(CLOCK_MONOTONIC); j->compressed_max = j->uncompressed_max = 8LLU * 1024LLU * 1024LLU * 1024LLU; /* 8GB */ j->url = strdup(url); if (!j->url) return -ENOMEM; *ret = j; j = NULL; return 0; } int pull_job_begin(PullJob *j) { int r; assert(j); if (j->state != PULL_JOB_INIT) return -EBUSY; if (j->grow_machine_directory) grow_machine_directory(); r = curl_glue_make(&j->curl, j->url, j); if (r < 0) return r; if (!strv_isempty(j->old_etags)) { _cleanup_free_ char *cc = NULL, *hdr = NULL; cc = strv_join(j->old_etags, ", "); if (!cc) return -ENOMEM; hdr = strappend("If-None-Match: ", cc); if (!hdr) return -ENOMEM; if (!j->request_header) { j->request_header = curl_slist_new(hdr, NULL); if (!j->request_header) return -ENOMEM; } else { struct curl_slist *l; l = curl_slist_append(j->request_header, hdr); if (!l) return -ENOMEM; j->request_header = l; } } if (j->request_header) { if (curl_easy_setopt(j->curl, CURLOPT_HTTPHEADER, j->request_header) != CURLE_OK) return -EIO; } if (curl_easy_setopt(j->curl, CURLOPT_WRITEFUNCTION, pull_job_write_callback) != CURLE_OK) return -EIO; if (curl_easy_setopt(j->curl, CURLOPT_WRITEDATA, j) != CURLE_OK) return -EIO; if (curl_easy_setopt(j->curl, CURLOPT_HEADERFUNCTION, pull_job_header_callback) != CURLE_OK) return -EIO; if (curl_easy_setopt(j->curl, CURLOPT_HEADERDATA, j) != CURLE_OK) return -EIO; if (curl_easy_setopt(j->curl, CURLOPT_XFERINFOFUNCTION, pull_job_progress_callback) != CURLE_OK) return -EIO; if (curl_easy_setopt(j->curl, CURLOPT_XFERINFODATA, j) != CURLE_OK) return -EIO; if (curl_easy_setopt(j->curl, CURLOPT_NOPROGRESS, 0) != CURLE_OK) return -EIO; r = curl_glue_add(j->glue, j->curl); if (r < 0) return r; j->state = PULL_JOB_ANALYZING; return 0; } systemd-229/src/import/pull-job.h000066400000000000000000000060031265713322000170560ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "curl-util.h" #include "import-compress.h" #include "macro.h" typedef struct PullJob PullJob; typedef void (*PullJobFinished)(PullJob *job); typedef int (*PullJobOpenDisk)(PullJob *job); typedef int (*PullJobHeader)(PullJob *job, const char *header, size_t sz); typedef void (*PullJobProgress)(PullJob *job); typedef enum PullJobState { PULL_JOB_INIT, PULL_JOB_ANALYZING, /* Still reading into ->payload, to figure out what we have */ PULL_JOB_RUNNING, /* Writing to destination */ PULL_JOB_DONE, PULL_JOB_FAILED, _PULL_JOB_STATE_MAX, _PULL_JOB_STATE_INVALID = -1, } PullJobState; #define PULL_JOB_IS_COMPLETE(j) (IN_SET((j)->state, PULL_JOB_DONE, PULL_JOB_FAILED)) typedef enum PullJobCompression { PULL_JOB_UNCOMPRESSED, PULL_JOB_XZ, PULL_JOB_GZIP, PULL_JOB_BZIP2, _PULL_JOB_COMPRESSION_MAX, _PULL_JOB_COMPRESSION_INVALID = -1, } PullJobCompression; struct PullJob { PullJobState state; int error; char *url; void *userdata; PullJobFinished on_finished; PullJobOpenDisk on_open_disk; PullJobHeader on_header; PullJobProgress on_progress; CurlGlue *glue; CURL *curl; struct curl_slist *request_header; char *etag; char **old_etags; bool etag_exists; uint64_t content_length; uint64_t written_compressed; uint64_t written_uncompressed; uint64_t uncompressed_max; uint64_t compressed_max; uint8_t *payload; size_t payload_size; size_t payload_allocated; int disk_fd; usec_t mtime; ImportCompress compress; unsigned progress_percent; usec_t start_usec; usec_t last_status_usec; bool allow_sparse; bool calc_checksum; gcry_md_hd_t checksum_context; char *checksum; bool grow_machine_directory; uint64_t written_since_last_grow; }; int pull_job_new(PullJob **job, const char *url, CurlGlue *glue, void *userdata); PullJob* pull_job_unref(PullJob *job); int pull_job_begin(PullJob *j); void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result); DEFINE_TRIVIAL_CLEANUP_FUNC(PullJob*, pull_job_unref); systemd-229/src/import/pull-raw.c000066400000000000000000000457331265713322000171050ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-daemon.h" #include "alloc-util.h" #include "btrfs-util.h" #include "chattr-util.h" #include "copy.h" #include "curl-util.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "hostname-util.h" #include "import-common.h" #include "import-util.h" #include "macro.h" #include "mkdir.h" #include "path-util.h" #include "pull-common.h" #include "pull-job.h" #include "pull-raw.h" #include "qcow2-util.h" #include "rm-rf.h" #include "string-util.h" #include "strv.h" #include "utf8.h" #include "util.h" #include "web-util.h" typedef enum RawProgress { RAW_DOWNLOADING, RAW_VERIFYING, RAW_UNPACKING, RAW_FINALIZING, RAW_COPYING, } RawProgress; struct RawPull { sd_event *event; CurlGlue *glue; char *image_root; PullJob *raw_job; PullJob *settings_job; PullJob *checksum_job; PullJob *signature_job; RawPullFinished on_finished; void *userdata; char *local; bool force_local; bool grow_machine_directory; bool settings; char *final_path; char *temp_path; char *settings_path; char *settings_temp_path; ImportVerify verify; }; RawPull* raw_pull_unref(RawPull *i) { if (!i) return NULL; pull_job_unref(i->raw_job); pull_job_unref(i->settings_job); pull_job_unref(i->checksum_job); pull_job_unref(i->signature_job); curl_glue_unref(i->glue); sd_event_unref(i->event); if (i->temp_path) { (void) unlink(i->temp_path); free(i->temp_path); } if (i->settings_temp_path) { (void) unlink(i->settings_temp_path); free(i->settings_temp_path); } free(i->final_path); free(i->settings_path); free(i->image_root); free(i->local); free(i); return NULL; } int raw_pull_new( RawPull **ret, sd_event *event, const char *image_root, RawPullFinished on_finished, void *userdata) { _cleanup_(raw_pull_unrefp) RawPull *i = NULL; int r; assert(ret); i = new0(RawPull, 1); if (!i) return -ENOMEM; i->on_finished = on_finished; i->userdata = userdata; i->image_root = strdup(image_root ?: "/var/lib/machines"); if (!i->image_root) return -ENOMEM; i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines"); if (event) i->event = sd_event_ref(event); else { r = sd_event_default(&i->event); if (r < 0) return r; } r = curl_glue_new(&i->glue, i->event); if (r < 0) return r; i->glue->on_finished = pull_job_curl_on_finished; i->glue->userdata = i; *ret = i; i = NULL; return 0; } static void raw_pull_report_progress(RawPull *i, RawProgress p) { unsigned percent; assert(i); switch (p) { case RAW_DOWNLOADING: { unsigned remain = 80; percent = 0; if (i->settings_job) { percent += i->settings_job->progress_percent * 5 / 100; remain -= 5; } if (i->checksum_job) { percent += i->checksum_job->progress_percent * 5 / 100; remain -= 5; } if (i->signature_job) { percent += i->signature_job->progress_percent * 5 / 100; remain -= 5; } if (i->raw_job) percent += i->raw_job->progress_percent * remain / 100; break; } case RAW_VERIFYING: percent = 80; break; case RAW_UNPACKING: percent = 85; break; case RAW_FINALIZING: percent = 90; break; case RAW_COPYING: percent = 95; break; default: assert_not_reached("Unknown progress state"); } sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent); log_debug("Combined progress %u%%", percent); } static int raw_pull_maybe_convert_qcow2(RawPull *i) { _cleanup_close_ int converted_fd = -1; _cleanup_free_ char *t = NULL; int r; assert(i); assert(i->raw_job); r = qcow2_detect(i->raw_job->disk_fd); if (r < 0) return log_error_errno(r, "Failed to detect whether this is a QCOW2 image: %m"); if (r == 0) return 0; /* This is a QCOW2 image, let's convert it */ r = tempfn_random(i->final_path, NULL, &t); if (r < 0) return log_oom(); converted_fd = open(t, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); if (converted_fd < 0) return log_error_errno(errno, "Failed to create %s: %m", t); r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL); if (r < 0) log_warning_errno(r, "Failed to set file attributes on %s: %m", t); log_info("Unpacking QCOW2 file."); r = qcow2_convert(i->raw_job->disk_fd, converted_fd); if (r < 0) { unlink(t); return log_error_errno(r, "Failed to convert qcow2 image: %m"); } (void) unlink(i->temp_path); free(i->temp_path); i->temp_path = t; t = NULL; safe_close(i->raw_job->disk_fd); i->raw_job->disk_fd = converted_fd; converted_fd = -1; return 1; } static int raw_pull_make_local_copy(RawPull *i) { _cleanup_free_ char *tp = NULL; _cleanup_close_ int dfd = -1; const char *p; int r; assert(i); assert(i->raw_job); if (!i->local) return 0; if (!i->final_path) { r = pull_make_path(i->raw_job->url, i->raw_job->etag, i->image_root, ".raw-", ".raw", &i->final_path); if (r < 0) return log_oom(); } if (i->raw_job->etag_exists) { /* We have downloaded this one previously, reopen it */ assert(i->raw_job->disk_fd < 0); i->raw_job->disk_fd = open(i->final_path, O_RDONLY|O_NOCTTY|O_CLOEXEC); if (i->raw_job->disk_fd < 0) return log_error_errno(errno, "Failed to open vendor image: %m"); } else { /* We freshly downloaded the image, use it */ assert(i->raw_job->disk_fd >= 0); if (lseek(i->raw_job->disk_fd, SEEK_SET, 0) == (off_t) -1) return log_error_errno(errno, "Failed to seek to beginning of vendor image: %m"); } p = strjoina(i->image_root, "/", i->local, ".raw"); if (i->force_local) (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); r = tempfn_random(p, NULL, &tp); if (r < 0) return log_oom(); dfd = open(tp, O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); if (dfd < 0) return log_error_errno(errno, "Failed to create writable copy of image: %m"); /* Turn off COW writing. This should greatly improve * performance on COW file systems like btrfs, since it * reduces fragmentation caused by not allowing in-place * writes. */ r = chattr_fd(dfd, FS_NOCOW_FL, FS_NOCOW_FL); if (r < 0) log_warning_errno(r, "Failed to set file attributes on %s: %m", tp); r = copy_bytes(i->raw_job->disk_fd, dfd, (uint64_t) -1, true); if (r < 0) { unlink(tp); return log_error_errno(r, "Failed to make writable copy of image: %m"); } (void) copy_times(i->raw_job->disk_fd, dfd); (void) copy_xattr(i->raw_job->disk_fd, dfd); dfd = safe_close(dfd); r = rename(tp, p); if (r < 0) { r = log_error_errno(errno, "Failed to move writable image into place: %m"); unlink(tp); return r; } log_info("Created new local image '%s'.", i->local); if (i->settings) { const char *local_settings; assert(i->settings_job); if (!i->settings_path) { r = pull_make_path(i->settings_job->url, i->settings_job->etag, i->image_root, ".settings-", NULL, &i->settings_path); if (r < 0) return log_oom(); } local_settings = strjoina(i->image_root, "/", i->local, ".nspawn"); r = copy_file_atomic(i->settings_path, local_settings, 0644, i->force_local, 0); if (r == -EEXIST) log_warning_errno(r, "Settings file %s already exists, not replacing.", local_settings); else if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to copy settings files %s, ignoring: %m", local_settings); else log_info("Created new settings file '%s.nspawn'", i->local); } return 0; } static bool raw_pull_is_done(RawPull *i) { assert(i); assert(i->raw_job); if (!PULL_JOB_IS_COMPLETE(i->raw_job)) return false; if (i->settings_job && !PULL_JOB_IS_COMPLETE(i->settings_job)) return false; if (i->checksum_job && !PULL_JOB_IS_COMPLETE(i->checksum_job)) return false; if (i->signature_job && !PULL_JOB_IS_COMPLETE(i->signature_job)) return false; return true; } static void raw_pull_job_on_finished(PullJob *j) { RawPull *i; int r; assert(j); assert(j->userdata); i = j->userdata; if (j == i->settings_job) { if (j->error != 0) log_info_errno(j->error, "Settings file could not be retrieved, proceeding without."); } else if (j->error != 0) { if (j == i->checksum_job) log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)"); else if (j == i->signature_job) log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)"); else log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)"); r = j->error; goto finish; } /* This is invoked if either the download completed * successfully, or the download was skipped because we * already have the etag. In this case ->etag_exists is * true. * * We only do something when we got all three files */ if (!raw_pull_is_done(i)) return; if (i->settings_job) i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd); if (!i->raw_job->etag_exists) { /* This is a new download, verify it, and move it into place */ assert(i->raw_job->disk_fd >= 0); raw_pull_report_progress(i, RAW_VERIFYING); r = pull_verify(i->raw_job, i->settings_job, i->checksum_job, i->signature_job); if (r < 0) goto finish; raw_pull_report_progress(i, RAW_UNPACKING); r = raw_pull_maybe_convert_qcow2(i); if (r < 0) goto finish; raw_pull_report_progress(i, RAW_FINALIZING); r = import_make_read_only_fd(i->raw_job->disk_fd); if (r < 0) goto finish; r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path); if (r < 0) { log_error_errno(r, "Failed to move RAW file into place: %m"); goto finish; } i->temp_path = mfree(i->temp_path); if (i->settings_job && i->settings_job->error == 0 && !i->settings_job->etag_exists) { assert(i->settings_temp_path); assert(i->settings_path); r = import_make_read_only(i->settings_temp_path); if (r < 0) goto finish; r = rename_noreplace(AT_FDCWD, i->settings_temp_path, AT_FDCWD, i->settings_path); if (r < 0) { log_error_errno(r, "Failed to rename settings file: %m"); goto finish; } i->settings_temp_path = mfree(i->settings_temp_path); } } raw_pull_report_progress(i, RAW_COPYING); r = raw_pull_make_local_copy(i); if (r < 0) goto finish; r = 0; finish: if (i->on_finished) i->on_finished(i, r, i->userdata); else sd_event_exit(i->event, r); } static int raw_pull_job_on_open_disk_raw(PullJob *j) { RawPull *i; int r; assert(j); assert(j->userdata); i = j->userdata; assert(i->raw_job == j); assert(!i->final_path); assert(!i->temp_path); r = pull_make_path(j->url, j->etag, i->image_root, ".raw-", ".raw", &i->final_path); if (r < 0) return log_oom(); r = tempfn_random(i->final_path, NULL, &i->temp_path); if (r < 0) return log_oom(); (void) mkdir_parents_label(i->temp_path, 0700); j->disk_fd = open(i->temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); if (j->disk_fd < 0) return log_error_errno(errno, "Failed to create %s: %m", i->temp_path); r = chattr_fd(j->disk_fd, FS_NOCOW_FL, FS_NOCOW_FL); if (r < 0) log_warning_errno(r, "Failed to set file attributes on %s: %m", i->temp_path); return 0; } static int raw_pull_job_on_open_disk_settings(PullJob *j) { RawPull *i; int r; assert(j); assert(j->userdata); i = j->userdata; assert(i->settings_job == j); assert(!i->settings_path); assert(!i->settings_temp_path); r = pull_make_path(j->url, j->etag, i->image_root, ".settings-", NULL, &i->settings_path); if (r < 0) return log_oom(); r = tempfn_random(i->settings_path, NULL, &i->settings_temp_path); if (r < 0) return log_oom(); mkdir_parents_label(i->settings_temp_path, 0700); j->disk_fd = open(i->settings_temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); if (j->disk_fd < 0) return log_error_errno(errno, "Failed to create %s: %m", i->settings_temp_path); return 0; } static void raw_pull_job_on_progress(PullJob *j) { RawPull *i; assert(j); assert(j->userdata); i = j->userdata; raw_pull_report_progress(i, RAW_DOWNLOADING); } int raw_pull_start( RawPull *i, const char *url, const char *local, bool force_local, ImportVerify verify, bool settings) { int r; assert(i); assert(verify < _IMPORT_VERIFY_MAX); assert(verify >= 0); if (!http_url_is_valid(url)) return -EINVAL; if (local && !machine_name_is_valid(local)) return -EINVAL; if (i->raw_job) return -EBUSY; r = free_and_strdup(&i->local, local); if (r < 0) return r; i->force_local = force_local; i->verify = verify; i->settings = settings; /* Queue job for the image itself */ r = pull_job_new(&i->raw_job, url, i->glue, i); if (r < 0) return r; i->raw_job->on_finished = raw_pull_job_on_finished; i->raw_job->on_open_disk = raw_pull_job_on_open_disk_raw; i->raw_job->on_progress = raw_pull_job_on_progress; i->raw_job->calc_checksum = verify != IMPORT_VERIFY_NO; i->raw_job->grow_machine_directory = i->grow_machine_directory; r = pull_find_old_etags(url, i->image_root, DT_REG, ".raw-", ".raw", &i->raw_job->old_etags); if (r < 0) return r; if (settings) { r = pull_make_settings_job(&i->settings_job, url, i->glue, raw_pull_job_on_finished, i); if (r < 0) return r; i->settings_job->on_open_disk = raw_pull_job_on_open_disk_settings; i->settings_job->on_progress = raw_pull_job_on_progress; i->settings_job->calc_checksum = verify != IMPORT_VERIFY_NO; r = pull_find_old_etags(i->settings_job->url, i->image_root, DT_REG, ".settings-", NULL, &i->settings_job->old_etags); if (r < 0) return r; } r = pull_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, raw_pull_job_on_finished, i); if (r < 0) return r; r = pull_job_begin(i->raw_job); if (r < 0) return r; if (i->settings_job) { r = pull_job_begin(i->settings_job); if (r < 0) return r; } if (i->checksum_job) { i->checksum_job->on_progress = raw_pull_job_on_progress; r = pull_job_begin(i->checksum_job); if (r < 0) return r; } if (i->signature_job) { i->signature_job->on_progress = raw_pull_job_on_progress; r = pull_job_begin(i->signature_job); if (r < 0) return r; } return 0; } systemd-229/src/import/pull-raw.h000066400000000000000000000023441265713322000171010ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-event.h" #include "import-util.h" #include "macro.h" typedef struct RawPull RawPull; typedef void (*RawPullFinished)(RawPull *pull, int error, void *userdata); int raw_pull_new(RawPull **pull, sd_event *event, const char *image_root, RawPullFinished on_finished, void *userdata); RawPull* raw_pull_unref(RawPull *pull); DEFINE_TRIVIAL_CLEANUP_FUNC(RawPull*, raw_pull_unref); int raw_pull_start(RawPull *pull, const char *url, const char *local, bool force_local, ImportVerify verify, bool settings); systemd-229/src/import/pull-tar.c000066400000000000000000000403171265713322000170730ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-daemon.h" #include "alloc-util.h" #include "btrfs-util.h" #include "copy.h" #include "curl-util.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "hostname-util.h" #include "import-common.h" #include "import-util.h" #include "macro.h" #include "mkdir.h" #include "path-util.h" #include "process-util.h" #include "pull-common.h" #include "pull-job.h" #include "pull-tar.h" #include "rm-rf.h" #include "string-util.h" #include "strv.h" #include "utf8.h" #include "util.h" #include "web-util.h" typedef enum TarProgress { TAR_DOWNLOADING, TAR_VERIFYING, TAR_FINALIZING, TAR_COPYING, } TarProgress; struct TarPull { sd_event *event; CurlGlue *glue; char *image_root; PullJob *tar_job; PullJob *settings_job; PullJob *checksum_job; PullJob *signature_job; TarPullFinished on_finished; void *userdata; char *local; bool force_local; bool grow_machine_directory; bool settings; pid_t tar_pid; char *final_path; char *temp_path; char *settings_path; char *settings_temp_path; ImportVerify verify; }; TarPull* tar_pull_unref(TarPull *i) { if (!i) return NULL; if (i->tar_pid > 1) { (void) kill_and_sigcont(i->tar_pid, SIGKILL); (void) wait_for_terminate(i->tar_pid, NULL); } pull_job_unref(i->tar_job); pull_job_unref(i->settings_job); pull_job_unref(i->checksum_job); pull_job_unref(i->signature_job); curl_glue_unref(i->glue); sd_event_unref(i->event); if (i->temp_path) { (void) rm_rf(i->temp_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); free(i->temp_path); } if (i->settings_temp_path) { (void) unlink(i->settings_temp_path); free(i->settings_temp_path); } free(i->final_path); free(i->settings_path); free(i->image_root); free(i->local); free(i); return NULL; } int tar_pull_new( TarPull **ret, sd_event *event, const char *image_root, TarPullFinished on_finished, void *userdata) { _cleanup_(tar_pull_unrefp) TarPull *i = NULL; int r; assert(ret); i = new0(TarPull, 1); if (!i) return -ENOMEM; i->on_finished = on_finished; i->userdata = userdata; i->image_root = strdup(image_root ?: "/var/lib/machines"); if (!i->image_root) return -ENOMEM; i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines"); if (event) i->event = sd_event_ref(event); else { r = sd_event_default(&i->event); if (r < 0) return r; } r = curl_glue_new(&i->glue, i->event); if (r < 0) return r; i->glue->on_finished = pull_job_curl_on_finished; i->glue->userdata = i; *ret = i; i = NULL; return 0; } static void tar_pull_report_progress(TarPull *i, TarProgress p) { unsigned percent; assert(i); switch (p) { case TAR_DOWNLOADING: { unsigned remain = 85; percent = 0; if (i->settings_job) { percent += i->settings_job->progress_percent * 5 / 100; remain -= 5; } if (i->checksum_job) { percent += i->checksum_job->progress_percent * 5 / 100; remain -= 5; } if (i->signature_job) { percent += i->signature_job->progress_percent * 5 / 100; remain -= 5; } if (i->tar_job) percent += i->tar_job->progress_percent * remain / 100; break; } case TAR_VERIFYING: percent = 85; break; case TAR_FINALIZING: percent = 90; break; case TAR_COPYING: percent = 95; break; default: assert_not_reached("Unknown progress state"); } sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent); log_debug("Combined progress %u%%", percent); } static int tar_pull_make_local_copy(TarPull *i) { int r; assert(i); assert(i->tar_job); if (!i->local) return 0; if (!i->final_path) { r = pull_make_path(i->tar_job->url, i->tar_job->etag, i->image_root, ".tar-", NULL, &i->final_path); if (r < 0) return log_oom(); } r = pull_make_local_copy(i->final_path, i->image_root, i->local, i->force_local); if (r < 0) return r; if (i->settings) { const char *local_settings; assert(i->settings_job); if (!i->settings_path) { r = pull_make_path(i->settings_job->url, i->settings_job->etag, i->image_root, ".settings-", NULL, &i->settings_path); if (r < 0) return log_oom(); } local_settings = strjoina(i->image_root, "/", i->local, ".nspawn"); r = copy_file_atomic(i->settings_path, local_settings, 0664, i->force_local, 0); if (r == -EEXIST) log_warning_errno(r, "Settings file %s already exists, not replacing.", local_settings); else if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to copy settings files %s, ignoring: %m", local_settings); else log_info("Created new settings file '%s.nspawn'", i->local); } return 0; } static bool tar_pull_is_done(TarPull *i) { assert(i); assert(i->tar_job); if (!PULL_JOB_IS_COMPLETE(i->tar_job)) return false; if (i->settings_job && !PULL_JOB_IS_COMPLETE(i->settings_job)) return false; if (i->checksum_job && !PULL_JOB_IS_COMPLETE(i->checksum_job)) return false; if (i->signature_job && !PULL_JOB_IS_COMPLETE(i->signature_job)) return false; return true; } static void tar_pull_job_on_finished(PullJob *j) { TarPull *i; int r; assert(j); assert(j->userdata); i = j->userdata; if (j == i->settings_job) { if (j->error != 0) log_info_errno(j->error, "Settings file could not be retrieved, proceeding without."); } else if (j->error != 0) { if (j == i->checksum_job) log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)"); else if (j == i->signature_job) log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)"); else log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)"); r = j->error; goto finish; } /* This is invoked if either the download completed * successfully, or the download was skipped because we * already have the etag. */ if (!tar_pull_is_done(i)) return; i->tar_job->disk_fd = safe_close(i->tar_job->disk_fd); if (i->settings_job) i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd); if (i->tar_pid > 0) { r = wait_for_terminate_and_warn("tar", i->tar_pid, true); i->tar_pid = 0; if (r < 0) goto finish; if (r > 0) { r = -EIO; goto finish; } } if (!i->tar_job->etag_exists) { /* This is a new download, verify it, and move it into place */ tar_pull_report_progress(i, TAR_VERIFYING); r = pull_verify(i->tar_job, i->settings_job, i->checksum_job, i->signature_job); if (r < 0) goto finish; tar_pull_report_progress(i, TAR_FINALIZING); r = import_make_read_only(i->temp_path); if (r < 0) goto finish; r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path); if (r < 0) { log_error_errno(r, "Failed to rename to final image name: %m"); goto finish; } i->temp_path = mfree(i->temp_path); if (i->settings_job && i->settings_job->error == 0 && !i->settings_job->etag_exists) { assert(i->settings_temp_path); assert(i->settings_path); /* Also move the settings file into place, if * it exist. Note that we do so only if we * also moved the tar file in place, to keep * things strictly in sync. */ r = import_make_read_only(i->settings_temp_path); if (r < 0) goto finish; r = rename_noreplace(AT_FDCWD, i->settings_temp_path, AT_FDCWD, i->settings_path); if (r < 0) { log_error_errno(r, "Failed to rename settings file: %m"); goto finish; } i->settings_temp_path = mfree(i->settings_temp_path); } } tar_pull_report_progress(i, TAR_COPYING); r = tar_pull_make_local_copy(i); if (r < 0) goto finish; r = 0; finish: if (i->on_finished) i->on_finished(i, r, i->userdata); else sd_event_exit(i->event, r); } static int tar_pull_job_on_open_disk_tar(PullJob *j) { TarPull *i; int r; assert(j); assert(j->userdata); i = j->userdata; assert(i->tar_job == j); assert(!i->final_path); assert(!i->temp_path); assert(i->tar_pid <= 0); r = pull_make_path(j->url, j->etag, i->image_root, ".tar-", NULL, &i->final_path); if (r < 0) return log_oom(); r = tempfn_random(i->final_path, NULL, &i->temp_path); if (r < 0) return log_oom(); mkdir_parents_label(i->temp_path, 0700); r = btrfs_subvol_make(i->temp_path); if (r == -ENOTTY) { if (mkdir(i->temp_path, 0755) < 0) return log_error_errno(errno, "Failed to create directory %s: %m", i->temp_path); } else if (r < 0) return log_error_errno(r, "Failed to create subvolume %s: %m", i->temp_path); else (void) import_assign_pool_quota_and_warn(i->temp_path); j->disk_fd = import_fork_tar_x(i->temp_path, &i->tar_pid); if (j->disk_fd < 0) return j->disk_fd; return 0; } static int tar_pull_job_on_open_disk_settings(PullJob *j) { TarPull *i; int r; assert(j); assert(j->userdata); i = j->userdata; assert(i->settings_job == j); assert(!i->settings_path); assert(!i->settings_temp_path); r = pull_make_path(j->url, j->etag, i->image_root, ".settings-", NULL, &i->settings_path); if (r < 0) return log_oom(); r = tempfn_random(i->settings_path, NULL, &i->settings_temp_path); if (r < 0) return log_oom(); mkdir_parents_label(i->settings_temp_path, 0700); j->disk_fd = open(i->settings_temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); if (j->disk_fd < 0) return log_error_errno(errno, "Failed to create %s: %m", i->settings_temp_path); return 0; } static void tar_pull_job_on_progress(PullJob *j) { TarPull *i; assert(j); assert(j->userdata); i = j->userdata; tar_pull_report_progress(i, TAR_DOWNLOADING); } int tar_pull_start( TarPull *i, const char *url, const char *local, bool force_local, ImportVerify verify, bool settings) { int r; assert(i); assert(verify < _IMPORT_VERIFY_MAX); assert(verify >= 0); if (!http_url_is_valid(url)) return -EINVAL; if (local && !machine_name_is_valid(local)) return -EINVAL; if (i->tar_job) return -EBUSY; r = free_and_strdup(&i->local, local); if (r < 0) return r; i->force_local = force_local; i->verify = verify; i->settings = settings; /* Set up download job for TAR file */ r = pull_job_new(&i->tar_job, url, i->glue, i); if (r < 0) return r; i->tar_job->on_finished = tar_pull_job_on_finished; i->tar_job->on_open_disk = tar_pull_job_on_open_disk_tar; i->tar_job->on_progress = tar_pull_job_on_progress; i->tar_job->calc_checksum = verify != IMPORT_VERIFY_NO; i->tar_job->grow_machine_directory = i->grow_machine_directory; r = pull_find_old_etags(url, i->image_root, DT_DIR, ".tar-", NULL, &i->tar_job->old_etags); if (r < 0) return r; /* Set up download job for the settings file (.nspawn) */ if (settings) { r = pull_make_settings_job(&i->settings_job, url, i->glue, tar_pull_job_on_finished, i); if (r < 0) return r; i->settings_job->on_open_disk = tar_pull_job_on_open_disk_settings; i->settings_job->on_progress = tar_pull_job_on_progress; i->settings_job->calc_checksum = verify != IMPORT_VERIFY_NO; r = pull_find_old_etags(i->settings_job->url, i->image_root, DT_REG, ".settings-", NULL, &i->settings_job->old_etags); if (r < 0) return r; } /* Set up download of checksum/signature files */ r = pull_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, tar_pull_job_on_finished, i); if (r < 0) return r; r = pull_job_begin(i->tar_job); if (r < 0) return r; if (i->settings_job) { r = pull_job_begin(i->settings_job); if (r < 0) return r; } if (i->checksum_job) { i->checksum_job->on_progress = tar_pull_job_on_progress; r = pull_job_begin(i->checksum_job); if (r < 0) return r; } if (i->signature_job) { i->signature_job->on_progress = tar_pull_job_on_progress; r = pull_job_begin(i->signature_job); if (r < 0) return r; } return 0; } systemd-229/src/import/pull-tar.h000066400000000000000000000023441265713322000170760ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-event.h" #include "import-util.h" #include "macro.h" typedef struct TarPull TarPull; typedef void (*TarPullFinished)(TarPull *pull, int error, void *userdata); int tar_pull_new(TarPull **pull, sd_event *event, const char *image_root, TarPullFinished on_finished, void *userdata); TarPull* tar_pull_unref(TarPull *pull); DEFINE_TRIVIAL_CLEANUP_FUNC(TarPull*, tar_pull_unref); int tar_pull_start(TarPull *pull, const char *url, const char *local, bool force_local, ImportVerify verify, bool settings); systemd-229/src/import/pull.c000066400000000000000000000257651265713322000163210ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-event.h" #include "alloc-util.h" #include "hostname-util.h" #include "import-util.h" #include "machine-image.h" #include "parse-util.h" #include "pull-raw.h" #include "pull-tar.h" #include "signal-util.h" #include "string-util.h" #include "verbs.h" #include "web-util.h" static bool arg_force = false; static const char *arg_image_root = "/var/lib/machines"; static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE; static bool arg_settings = true; static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { log_notice("Transfer aborted."); sd_event_exit(sd_event_source_get_event(s), EINTR); return 0; } static void on_tar_finished(TarPull *pull, int error, void *userdata) { sd_event *event = userdata; assert(pull); if (error == 0) log_info("Operation completed successfully."); sd_event_exit(event, abs(error)); } static int pull_tar(int argc, char *argv[], void *userdata) { _cleanup_(tar_pull_unrefp) TarPull *pull = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; const char *url, *local; _cleanup_free_ char *l = NULL, *ll = NULL; int r; url = argv[1]; if (!http_url_is_valid(url)) { log_error("URL '%s' is not valid.", url); return -EINVAL; } if (argc >= 3) local = argv[2]; else { r = import_url_last_component(url, &l); if (r < 0) return log_error_errno(r, "Failed get final component of URL: %m"); local = l; } if (isempty(local) || streq(local, "-")) local = NULL; if (local) { r = tar_strip_suffixes(local, &ll); if (r < 0) return log_oom(); local = ll; if (!machine_name_is_valid(local)) { log_error("Local image name '%s' is not valid.", local); return -EINVAL; } if (!arg_force) { r = image_find(local, NULL); if (r < 0) return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local); else if (r > 0) { log_error_errno(EEXIST, "Image '%s' already exists.", local); return -EEXIST; } } log_info("Pulling '%s', saving as '%s'.", url, local); } else log_info("Pulling '%s'.", url); r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to allocate event loop: %m"); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); r = tar_pull_new(&pull, event, arg_image_root, on_tar_finished, event); if (r < 0) return log_error_errno(r, "Failed to allocate puller: %m"); r = tar_pull_start(pull, url, local, arg_force, arg_verify, arg_settings); if (r < 0) return log_error_errno(r, "Failed to pull image: %m"); r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); log_info("Exiting."); return -r; } static void on_raw_finished(RawPull *pull, int error, void *userdata) { sd_event *event = userdata; assert(pull); if (error == 0) log_info("Operation completed successfully."); sd_event_exit(event, abs(error)); } static int pull_raw(int argc, char *argv[], void *userdata) { _cleanup_(raw_pull_unrefp) RawPull *pull = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; const char *url, *local; _cleanup_free_ char *l = NULL, *ll = NULL; int r; url = argv[1]; if (!http_url_is_valid(url)) { log_error("URL '%s' is not valid.", url); return -EINVAL; } if (argc >= 3) local = argv[2]; else { r = import_url_last_component(url, &l); if (r < 0) return log_error_errno(r, "Failed get final component of URL: %m"); local = l; } if (isempty(local) || streq(local, "-")) local = NULL; if (local) { r = raw_strip_suffixes(local, &ll); if (r < 0) return log_oom(); local = ll; if (!machine_name_is_valid(local)) { log_error("Local image name '%s' is not valid.", local); return -EINVAL; } if (!arg_force) { r = image_find(local, NULL); if (r < 0) return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local); else if (r > 0) { log_error_errno(EEXIST, "Image '%s' already exists.", local); return -EEXIST; } } log_info("Pulling '%s', saving as '%s'.", url, local); } else log_info("Pulling '%s'.", url); r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to allocate event loop: %m"); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); r = raw_pull_new(&pull, event, arg_image_root, on_raw_finished, event); if (r < 0) return log_error_errno(r, "Failed to allocate puller: %m"); r = raw_pull_start(pull, url, local, arg_force, arg_verify, arg_settings); if (r < 0) return log_error_errno(r, "Failed to pull image: %m"); r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); log_info("Exiting."); return -r; } static int help(int argc, char *argv[], void *userdata) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" "Download container or virtual machine images.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --force Force creation of image\n" " --verify=MODE Verify downloaded image, one of: 'no',\n" " 'checksum', 'signature'\n" " --settings=BOOL Download settings file with image\n" " --image-root=PATH Image root directory\n\n" "Commands:\n" " tar URL [NAME] Download a TAR image\n" " raw URL [NAME] Download a RAW image\n", program_invocation_short_name); return 0; } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_FORCE, ARG_IMAGE_ROOT, ARG_VERIFY, ARG_SETTINGS, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "force", no_argument, NULL, ARG_FORCE }, { "image-root", required_argument, NULL, ARG_IMAGE_ROOT }, { "verify", required_argument, NULL, ARG_VERIFY }, { "settings", required_argument, NULL, ARG_SETTINGS }, {} }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': return help(0, NULL, NULL); case ARG_VERSION: return version(); case ARG_FORCE: arg_force = true; break; case ARG_IMAGE_ROOT: arg_image_root = optarg; break; case ARG_VERIFY: arg_verify = import_verify_from_string(optarg); if (arg_verify < 0) { log_error("Invalid verification setting '%s'", optarg); return -EINVAL; } break; case ARG_SETTINGS: r = parse_boolean(optarg); if (r < 0) return log_error_errno(r, "Failed to parse --settings= parameter '%s'", optarg); arg_settings = r; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } static int pull_main(int argc, char *argv[]) { static const Verb verbs[] = { { "help", VERB_ANY, VERB_ANY, 0, help }, { "tar", 2, 3, 0, pull_tar }, { "raw", 2, 3, 0, pull_raw }, {} }; return dispatch_verb(argc, argv, verbs, NULL); } int main(int argc, char *argv[]) { int r; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; (void) ignore_signals(SIGPIPE, -1); r = pull_main(argc, argv); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/import/qcow2-util.c000066400000000000000000000246701265713322000173450ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "btrfs-util.h" #include "qcow2-util.h" #include "sparse-endian.h" #include "util.h" #define QCOW2_MAGIC 0x514649fb #define QCOW2_COPIED (1ULL << 63) #define QCOW2_COMPRESSED (1ULL << 62) #define QCOW2_ZERO (1ULL << 0) typedef struct _packed_ Header { be32_t magic; be32_t version; be64_t backing_file_offset; be32_t backing_file_size; be32_t cluster_bits; be64_t size; be32_t crypt_method; be32_t l1_size; be64_t l1_table_offset; be64_t refcount_table_offset; be32_t refcount_table_clusters; be32_t nb_snapshots; be64_t snapshots_offset; /* The remainder is only present on QCOW3 */ be64_t incompatible_features; be64_t compatible_features; be64_t autoclear_features; be32_t refcount_order; be32_t header_length; } Header; #define HEADER_MAGIC(header) be32toh((header)->magic) #define HEADER_VERSION(header) be32toh((header)->version) #define HEADER_CLUSTER_BITS(header) be32toh((header)->cluster_bits) #define HEADER_CLUSTER_SIZE(header) (1ULL << HEADER_CLUSTER_BITS(header)) #define HEADER_L2_BITS(header) (HEADER_CLUSTER_BITS(header) - 3) #define HEADER_SIZE(header) be64toh((header)->size) #define HEADER_CRYPT_METHOD(header) be32toh((header)->crypt_method) #define HEADER_L1_SIZE(header) be32toh((header)->l1_size) #define HEADER_L2_SIZE(header) (HEADER_CLUSTER_SIZE(header)/sizeof(uint64_t)) #define HEADER_L1_TABLE_OFFSET(header) be64toh((header)->l1_table_offset) static uint32_t HEADER_HEADER_LENGTH(const Header *h) { if (HEADER_VERSION(h) < 3) return offsetof(Header, incompatible_features); return be32toh(h->header_length); } static int copy_cluster( int sfd, uint64_t soffset, int dfd, uint64_t doffset, uint64_t cluster_size, void *buffer) { ssize_t l; int r; r = btrfs_clone_range(sfd, soffset, dfd, doffset, cluster_size); if (r >= 0) return r; l = pread(sfd, buffer, cluster_size, soffset); if (l < 0) return -errno; if ((uint64_t) l != cluster_size) return -EIO; l = pwrite(dfd, buffer, cluster_size, doffset); if (l < 0) return -errno; if ((uint64_t) l != cluster_size) return -EIO; return 0; } static int decompress_cluster( int sfd, uint64_t soffset, int dfd, uint64_t doffset, uint64_t compressed_size, uint64_t cluster_size, void *buffer1, void *buffer2) { _cleanup_free_ void *large_buffer = NULL; z_stream s = {}; uint64_t sz; ssize_t l; int r; if (compressed_size > cluster_size) { /* The usual cluster buffer doesn't suffice, let's * allocate a larger one, temporarily */ large_buffer = malloc(compressed_size); if (!large_buffer) return -ENOMEM; buffer1 = large_buffer; } l = pread(sfd, buffer1, compressed_size, soffset); if (l < 0) return -errno; if ((uint64_t) l != compressed_size) return -EIO; s.next_in = buffer1; s.avail_in = compressed_size; s.next_out = buffer2; s.avail_out = cluster_size; r = inflateInit2(&s, -12); if (r != Z_OK) return -EIO; r = inflate(&s, Z_FINISH); sz = (uint8_t*) s.next_out - (uint8_t*) buffer2; inflateEnd(&s); if (r != Z_STREAM_END || sz != cluster_size) return -EIO; l = pwrite(dfd, buffer2, cluster_size, doffset); if (l < 0) return -errno; if ((uint64_t) l != cluster_size) return -EIO; return 0; } static int normalize_offset( const Header *header, uint64_t p, uint64_t *ret, bool *compressed, uint64_t *compressed_size) { uint64_t q; q = be64toh(p); if (q & QCOW2_COMPRESSED) { uint64_t sz, csize_shift, csize_mask; if (!compressed) return -EOPNOTSUPP; csize_shift = 64 - 2 - (HEADER_CLUSTER_BITS(header) - 8); csize_mask = (1ULL << (HEADER_CLUSTER_BITS(header) - 8)) - 1; sz = (((q >> csize_shift) & csize_mask) + 1) * 512 - (q & 511); q &= ((1ULL << csize_shift) - 1); if (compressed_size) *compressed_size = sz; *compressed = true; } else { if (compressed) { *compressed = false; *compressed_size = 0; } if (q & QCOW2_ZERO) { /* We make no distinction between zero blocks and holes */ *ret = 0; return 0; } q &= ~QCOW2_COPIED; } *ret = q; return q > 0; /* returns positive if not a hole */ } static int verify_header(const Header *header) { assert(header); if (HEADER_MAGIC(header) != QCOW2_MAGIC) return -EBADMSG; if (HEADER_VERSION(header) != 2 && HEADER_VERSION(header) != 3) return -EOPNOTSUPP; if (HEADER_CRYPT_METHOD(header) != 0) return -EOPNOTSUPP; if (HEADER_CLUSTER_BITS(header) < 9) /* 512K */ return -EBADMSG; if (HEADER_CLUSTER_BITS(header) > 21) /* 2MB */ return -EBADMSG; if (HEADER_SIZE(header) % HEADER_CLUSTER_SIZE(header) != 0) return -EBADMSG; if (HEADER_L1_SIZE(header) > 32*1024*1024) /* 32MB */ return -EBADMSG; if (HEADER_VERSION(header) == 3) { if (header->incompatible_features != 0) return -EOPNOTSUPP; if (HEADER_HEADER_LENGTH(header) < sizeof(Header)) return -EBADMSG; } return 0; } int qcow2_convert(int qcow2_fd, int raw_fd) { _cleanup_free_ void *buffer1 = NULL, *buffer2 = NULL; _cleanup_free_ be64_t *l1_table = NULL, *l2_table = NULL; uint64_t sz, i; Header header; ssize_t l; int r; l = pread(qcow2_fd, &header, sizeof(header), 0); if (l < 0) return -errno; if (l != sizeof(header)) return -EIO; r = verify_header(&header); if (r < 0) return r; l1_table = new(be64_t, HEADER_L1_SIZE(&header)); if (!l1_table) return -ENOMEM; l2_table = malloc(HEADER_CLUSTER_SIZE(&header)); if (!l2_table) return -ENOMEM; buffer1 = malloc(HEADER_CLUSTER_SIZE(&header)); if (!buffer1) return -ENOMEM; buffer2 = malloc(HEADER_CLUSTER_SIZE(&header)); if (!buffer2) return -ENOMEM; /* Empty the file if it exists, we rely on zero bits */ if (ftruncate(raw_fd, 0) < 0) return -errno; if (ftruncate(raw_fd, HEADER_SIZE(&header)) < 0) return -errno; sz = sizeof(uint64_t) * HEADER_L1_SIZE(&header); l = pread(qcow2_fd, l1_table, sz, HEADER_L1_TABLE_OFFSET(&header)); if (l < 0) return -errno; if ((uint64_t) l != sz) return -EIO; for (i = 0; i < HEADER_L1_SIZE(&header); i ++) { uint64_t l2_begin, j; r = normalize_offset(&header, l1_table[i], &l2_begin, NULL, NULL); if (r < 0) return r; if (r == 0) continue; l = pread(qcow2_fd, l2_table, HEADER_CLUSTER_SIZE(&header), l2_begin); if (l < 0) return -errno; if ((uint64_t) l != HEADER_CLUSTER_SIZE(&header)) return -EIO; for (j = 0; j < HEADER_L2_SIZE(&header); j++) { uint64_t data_begin, p, compressed_size; bool compressed; p = ((i << HEADER_L2_BITS(&header)) + j) << HEADER_CLUSTER_BITS(&header); r = normalize_offset(&header, l2_table[j], &data_begin, &compressed, &compressed_size); if (r < 0) return r; if (r == 0) continue; if (compressed) r = decompress_cluster( qcow2_fd, data_begin, raw_fd, p, compressed_size, HEADER_CLUSTER_SIZE(&header), buffer1, buffer2); else r = copy_cluster( qcow2_fd, data_begin, raw_fd, p, HEADER_CLUSTER_SIZE(&header), buffer1); if (r < 0) return r; } } return 0; } int qcow2_detect(int fd) { be32_t id; ssize_t l; l = pread(fd, &id, sizeof(id), 0); if (l < 0) return -errno; if (l != sizeof(id)) return -EIO; return htobe32(QCOW2_MAGIC) == id; } systemd-229/src/import/qcow2-util.h000066400000000000000000000014441265713322000173440ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int qcow2_detect(int fd); int qcow2_convert(int qcow2_fd, int raw_fd); systemd-229/src/import/test-qcow2.c000066400000000000000000000031451265713322000173410ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "fd-util.h" #include "log.h" #include "qcow2-util.h" #include "util.h" int main(int argc, char *argv[]) { _cleanup_close_ int sfd = -1, dfd = -1; int r; if (argc != 3) { log_error("Needs two arguments."); return EXIT_FAILURE; } sfd = open(argv[1], O_RDONLY|O_CLOEXEC|O_NOCTTY); if (sfd < 0) { log_error_errno(errno, "Can't open source file: %m"); return EXIT_FAILURE; } dfd = open(argv[2], O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0666); if (dfd < 0) { log_error_errno(errno, "Can't open destination file: %m"); return EXIT_FAILURE; } r = qcow2_convert(sfd, dfd); if (r < 0) { log_error_errno(r, "Failed to unpack: %m"); return EXIT_FAILURE; } return EXIT_SUCCESS; } systemd-229/src/initctl/000077500000000000000000000000001265713322000153165ustar00rootroot00000000000000systemd-229/src/initctl/Makefile000077700000000000000000000000001265713322000206242../Makefileustar00rootroot00000000000000systemd-229/src/initctl/initctl.c000066400000000000000000000275511265713322000171420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-bus.h" #include "sd-daemon.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "def.h" #include "fd-util.h" #include "formats-util.h" #include "initreq.h" #include "list.h" #include "log.h" #include "special.h" #include "util.h" #define SERVER_FD_MAX 16 #define TIMEOUT_MSEC ((int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC)) typedef struct Fifo Fifo; typedef struct Server { int epoll_fd; LIST_HEAD(Fifo, fifos); unsigned n_fifos; sd_bus *bus; bool quit; } Server; struct Fifo { Server *server; int fd; struct init_request buffer; size_t bytes_read; LIST_FIELDS(Fifo, fifo); }; static const char *translate_runlevel(int runlevel, bool *isolate) { static const struct { const int runlevel; const char *special; bool isolate; } table[] = { { '0', SPECIAL_POWEROFF_TARGET, false }, { '1', SPECIAL_RESCUE_TARGET, true }, { 's', SPECIAL_RESCUE_TARGET, true }, { 'S', SPECIAL_RESCUE_TARGET, true }, { '2', SPECIAL_MULTI_USER_TARGET, true }, { '3', SPECIAL_MULTI_USER_TARGET, true }, { '4', SPECIAL_MULTI_USER_TARGET, true }, { '5', SPECIAL_GRAPHICAL_TARGET, true }, { '6', SPECIAL_REBOOT_TARGET, false }, }; unsigned i; assert(isolate); for (i = 0; i < ELEMENTSOF(table); i++) if (table[i].runlevel == runlevel) { *isolate = table[i].isolate; if (runlevel == '6' && kexec_loaded()) return SPECIAL_KEXEC_TARGET; return table[i].special; } return NULL; } static void change_runlevel(Server *s, int runlevel) { const char *target; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *mode; bool isolate = false; int r; assert(s); target = translate_runlevel(runlevel, &isolate); if (!target) { log_warning("Got request for unknown runlevel %c, ignoring.", runlevel); return; } if (isolate) mode = "isolate"; else mode = "replace-irreversibly"; log_debug("Running request %s/start/%s", target, mode); r = sd_bus_call_method( s->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit", &error, NULL, "ss", target, mode); if (r < 0) { log_error("Failed to change runlevel: %s", bus_error_message(&error, -r)); return; } } static void request_process(Server *s, const struct init_request *req) { assert(s); assert(req); if (req->magic != INIT_MAGIC) { log_error("Got initctl request with invalid magic. Ignoring."); return; } switch (req->cmd) { case INIT_CMD_RUNLVL: if (!isprint(req->runlevel)) log_error("Got invalid runlevel. Ignoring."); else switch (req->runlevel) { /* we are async anyway, so just use kill for reexec/reload */ case 'u': case 'U': if (kill(1, SIGTERM) < 0) log_error_errno(errno, "kill() failed: %m"); /* The bus connection will be * terminated if PID 1 is reexecuted, * hence let's just exit here, and * rely on that we'll be restarted on * the next request */ s->quit = true; break; case 'q': case 'Q': if (kill(1, SIGHUP) < 0) log_error_errno(errno, "kill() failed: %m"); break; default: change_runlevel(s, req->runlevel); } return; case INIT_CMD_POWERFAIL: case INIT_CMD_POWERFAILNOW: case INIT_CMD_POWEROK: log_warning("Received UPS/power initctl request. This is not implemented in systemd. Upgrade your UPS daemon!"); return; case INIT_CMD_CHANGECONS: log_warning("Received console change initctl request. This is not implemented in systemd."); return; case INIT_CMD_SETENV: case INIT_CMD_UNSETENV: log_warning("Received environment initctl request. This is not implemented in systemd."); return; default: log_warning("Received unknown initctl request. Ignoring."); return; } } static int fifo_process(Fifo *f) { ssize_t l; assert(f); errno = EIO; l = read(f->fd, ((uint8_t*) &f->buffer) + f->bytes_read, sizeof(f->buffer) - f->bytes_read); if (l <= 0) { if (errno == EAGAIN) return 0; return log_warning_errno(errno, "Failed to read from fifo: %m"); } f->bytes_read += l; assert(f->bytes_read <= sizeof(f->buffer)); if (f->bytes_read == sizeof(f->buffer)) { request_process(f->server, &f->buffer); f->bytes_read = 0; } return 0; } static void fifo_free(Fifo *f) { assert(f); if (f->server) { assert(f->server->n_fifos > 0); f->server->n_fifos--; LIST_REMOVE(fifo, f->server->fifos, f); } if (f->fd >= 0) { if (f->server) epoll_ctl(f->server->epoll_fd, EPOLL_CTL_DEL, f->fd, NULL); safe_close(f->fd); } free(f); } static void server_done(Server *s) { assert(s); while (s->fifos) fifo_free(s->fifos); safe_close(s->epoll_fd); if (s->bus) { sd_bus_flush(s->bus); sd_bus_unref(s->bus); } } static int server_init(Server *s, unsigned n_sockets) { int r; unsigned i; assert(s); assert(n_sockets > 0); zero(*s); s->epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (s->epoll_fd < 0) { r = log_error_errno(errno, "Failed to create epoll object: %m"); goto fail; } for (i = 0; i < n_sockets; i++) { struct epoll_event ev; Fifo *f; int fd; fd = SD_LISTEN_FDS_START+i; r = sd_is_fifo(fd, NULL); if (r < 0) { log_error_errno(r, "Failed to determine file descriptor type: %m"); goto fail; } if (!r) { log_error("Wrong file descriptor type."); r = -EINVAL; goto fail; } f = new0(Fifo, 1); if (!f) { r = -ENOMEM; log_error_errno(errno, "Failed to create fifo object: %m"); goto fail; } f->fd = -1; zero(ev); ev.events = EPOLLIN; ev.data.ptr = f; if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) { r = -errno; fifo_free(f); log_error_errno(errno, "Failed to add fifo fd to epoll object: %m"); goto fail; } f->fd = fd; LIST_PREPEND(fifo, s->fifos, f); f->server = s; s->n_fifos ++; } r = bus_connect_system_systemd(&s->bus); if (r < 0) { log_error_errno(r, "Failed to get D-Bus connection: %m"); r = -EIO; goto fail; } return 0; fail: server_done(s); return r; } static int process_event(Server *s, struct epoll_event *ev) { int r; Fifo *f; assert(s); if (!(ev->events & EPOLLIN)) { log_info("Got invalid event from epoll. (3)"); return -EIO; } f = (Fifo*) ev->data.ptr; r = fifo_process(f); if (r < 0) { log_info_errno(r, "Got error on fifo: %m"); fifo_free(f); return r; } return 0; } int main(int argc, char *argv[]) { Server server; int r = EXIT_FAILURE, n; if (getppid() != 1) { log_error("This program should be invoked by init only."); return EXIT_FAILURE; } if (argc > 1) { log_error("This program does not take arguments."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); n = sd_listen_fds(true); if (n < 0) { log_error_errno(r, "Failed to read listening file descriptors from environment: %m"); return EXIT_FAILURE; } if (n <= 0 || n > SERVER_FD_MAX) { log_error("No or too many file descriptors passed."); return EXIT_FAILURE; } if (server_init(&server, (unsigned) n) < 0) return EXIT_FAILURE; log_debug("systemd-initctl running as pid "PID_FMT, getpid()); sd_notify(false, "READY=1\n" "STATUS=Processing requests..."); while (!server.quit) { struct epoll_event event; int k; k = epoll_wait(server.epoll_fd, &event, 1, TIMEOUT_MSEC); if (k < 0) { if (errno == EINTR) continue; log_error_errno(errno, "epoll_wait() failed: %m"); goto fail; } if (k <= 0) break; if (process_event(&server, &event) < 0) goto fail; } r = EXIT_SUCCESS; log_debug("systemd-initctl stopped as pid "PID_FMT, getpid()); fail: sd_notify(false, "STOPPING=1\n" "STATUS=Shutting down..."); server_done(&server); return r; } systemd-229/src/journal-remote/000077500000000000000000000000001265713322000166135ustar00rootroot00000000000000systemd-229/src/journal-remote/.gitignore000066400000000000000000000000521265713322000206000ustar00rootroot00000000000000/journal-remote.conf /journal-upload.conf systemd-229/src/journal-remote/Makefile000077700000000000000000000000001265713322000221212../Makefileustar00rootroot00000000000000systemd-229/src/journal-remote/browse.html000066400000000000000000000553341265713322000210140ustar00rootroot00000000000000 Journal

     Only current boot
    
g: First Page      ←, k, BACKSPACE: Previous Page      →, j, SPACE: Next Page      G: Last Page      +: More entries      -: Fewer entries
systemd-229/src/journal-remote/journal-gatewayd.c000066400000000000000000001022401265713322000222330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #ifdef HAVE_GNUTLS #include #endif #include #include #include #include #include "sd-bus.h" #include "sd-daemon.h" #include "sd-journal.h" #include "alloc-util.h" #include "bus-util.h" #include "fd-util.h" #include "fileio.h" #include "hostname-util.h" #include "log.h" #include "logs-show.h" #include "microhttpd-util.h" #include "parse-util.h" #include "sigbus.h" #include "util.h" #define JOURNAL_WAIT_TIMEOUT (10*USEC_PER_SEC) static char *arg_key_pem = NULL; static char *arg_cert_pem = NULL; static char *arg_trust_pem = NULL; typedef struct RequestMeta { sd_journal *journal; OutputMode mode; char *cursor; int64_t n_skip; uint64_t n_entries; bool n_entries_set; FILE *tmp; uint64_t delta, size; int argument_parse_error; bool follow; bool discrete; uint64_t n_fields; bool n_fields_set; } RequestMeta; static const char* const mime_types[_OUTPUT_MODE_MAX] = { [OUTPUT_SHORT] = "text/plain", [OUTPUT_JSON] = "application/json", [OUTPUT_JSON_SSE] = "text/event-stream", [OUTPUT_EXPORT] = "application/vnd.fdo.journal", }; static RequestMeta *request_meta(void **connection_cls) { RequestMeta *m; assert(connection_cls); if (*connection_cls) return *connection_cls; m = new0(RequestMeta, 1); if (!m) return NULL; *connection_cls = m; return m; } static void request_meta_free( void *cls, struct MHD_Connection *connection, void **connection_cls, enum MHD_RequestTerminationCode toe) { RequestMeta *m = *connection_cls; if (!m) return; sd_journal_close(m->journal); safe_fclose(m->tmp); free(m->cursor); free(m); } static int open_journal(RequestMeta *m) { assert(m); if (m->journal) return 0; return sd_journal_open(&m->journal, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM); } static int request_meta_ensure_tmp(RequestMeta *m) { if (m->tmp) rewind(m->tmp); else { int fd; fd = open_tmpfile("/tmp", O_RDWR|O_CLOEXEC); if (fd < 0) return fd; m->tmp = fdopen(fd, "w+"); if (!m->tmp) { safe_close(fd); return -errno; } } return 0; } static ssize_t request_reader_entries( void *cls, uint64_t pos, char *buf, size_t max) { RequestMeta *m = cls; int r; size_t n, k; assert(m); assert(buf); assert(max > 0); assert(pos >= m->delta); pos -= m->delta; while (pos >= m->size) { off_t sz; /* End of this entry, so let's serialize the next * one */ if (m->n_entries_set && m->n_entries <= 0) return MHD_CONTENT_READER_END_OF_STREAM; if (m->n_skip < 0) r = sd_journal_previous_skip(m->journal, (uint64_t) -m->n_skip + 1); else if (m->n_skip > 0) r = sd_journal_next_skip(m->journal, (uint64_t) m->n_skip + 1); else r = sd_journal_next(m->journal); if (r < 0) { log_error_errno(r, "Failed to advance journal pointer: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; } else if (r == 0) { if (m->follow) { r = sd_journal_wait(m->journal, (uint64_t) JOURNAL_WAIT_TIMEOUT); if (r < 0) { log_error_errno(r, "Couldn't wait for journal event: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; } if (r == SD_JOURNAL_NOP) break; continue; } return MHD_CONTENT_READER_END_OF_STREAM; } if (m->discrete) { assert(m->cursor); r = sd_journal_test_cursor(m->journal, m->cursor); if (r < 0) { log_error_errno(r, "Failed to test cursor: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; } if (r == 0) return MHD_CONTENT_READER_END_OF_STREAM; } pos -= m->size; m->delta += m->size; if (m->n_entries_set) m->n_entries -= 1; m->n_skip = 0; r = request_meta_ensure_tmp(m); if (r < 0) { log_error_errno(r, "Failed to create temporary file: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; } r = output_journal(m->tmp, m->journal, m->mode, 0, OUTPUT_FULL_WIDTH, NULL); if (r < 0) { log_error_errno(r, "Failed to serialize item: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; } sz = ftello(m->tmp); if (sz == (off_t) -1) { log_error_errno(errno, "Failed to retrieve file position: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; } m->size = (uint64_t) sz; } if (fseeko(m->tmp, pos, SEEK_SET) < 0) { log_error_errno(errno, "Failed to seek to position: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; } n = m->size - pos; if (n < 1) return 0; if (n > max) n = max; errno = 0; k = fread(buf, 1, n, m->tmp); if (k != n) { log_error("Failed to read from file: %s", errno ? strerror(errno) : "Premature EOF"); return MHD_CONTENT_READER_END_WITH_ERROR; } return (ssize_t) k; } static int request_parse_accept( RequestMeta *m, struct MHD_Connection *connection) { const char *header; assert(m); assert(connection); header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Accept"); if (!header) return 0; if (streq(header, mime_types[OUTPUT_JSON])) m->mode = OUTPUT_JSON; else if (streq(header, mime_types[OUTPUT_JSON_SSE])) m->mode = OUTPUT_JSON_SSE; else if (streq(header, mime_types[OUTPUT_EXPORT])) m->mode = OUTPUT_EXPORT; else m->mode = OUTPUT_SHORT; return 0; } static int request_parse_range( RequestMeta *m, struct MHD_Connection *connection) { const char *range, *colon, *colon2; int r; assert(m); assert(connection); range = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Range"); if (!range) return 0; if (!startswith(range, "entries=")) return 0; range += 8; range += strspn(range, WHITESPACE); colon = strchr(range, ':'); if (!colon) m->cursor = strdup(range); else { const char *p; colon2 = strchr(colon + 1, ':'); if (colon2) { _cleanup_free_ char *t; t = strndup(colon + 1, colon2 - colon - 1); if (!t) return -ENOMEM; r = safe_atoi64(t, &m->n_skip); if (r < 0) return r; } p = (colon2 ? colon2 : colon) + 1; if (*p) { r = safe_atou64(p, &m->n_entries); if (r < 0) return r; if (m->n_entries <= 0) return -EINVAL; m->n_entries_set = true; } m->cursor = strndup(range, colon - range); } if (!m->cursor) return -ENOMEM; m->cursor[strcspn(m->cursor, WHITESPACE)] = 0; if (isempty(m->cursor)) m->cursor = mfree(m->cursor); return 0; } static int request_parse_arguments_iterator( void *cls, enum MHD_ValueKind kind, const char *key, const char *value) { RequestMeta *m = cls; _cleanup_free_ char *p = NULL; int r; assert(m); if (isempty(key)) { m->argument_parse_error = -EINVAL; return MHD_NO; } if (streq(key, "follow")) { if (isempty(value)) { m->follow = true; return MHD_YES; } r = parse_boolean(value); if (r < 0) { m->argument_parse_error = r; return MHD_NO; } m->follow = r; return MHD_YES; } if (streq(key, "discrete")) { if (isempty(value)) { m->discrete = true; return MHD_YES; } r = parse_boolean(value); if (r < 0) { m->argument_parse_error = r; return MHD_NO; } m->discrete = r; return MHD_YES; } if (streq(key, "boot")) { if (isempty(value)) r = true; else { r = parse_boolean(value); if (r < 0) { m->argument_parse_error = r; return MHD_NO; } } if (r) { char match[9 + 32 + 1] = "_BOOT_ID="; sd_id128_t bid; r = sd_id128_get_boot(&bid); if (r < 0) { log_error_errno(r, "Failed to get boot ID: %m"); return MHD_NO; } sd_id128_to_string(bid, match + 9); r = sd_journal_add_match(m->journal, match, sizeof(match)-1); if (r < 0) { m->argument_parse_error = r; return MHD_NO; } } return MHD_YES; } p = strjoin(key, "=", strempty(value), NULL); if (!p) { m->argument_parse_error = log_oom(); return MHD_NO; } r = sd_journal_add_match(m->journal, p, 0); if (r < 0) { m->argument_parse_error = r; return MHD_NO; } return MHD_YES; } static int request_parse_arguments( RequestMeta *m, struct MHD_Connection *connection) { assert(m); assert(connection); m->argument_parse_error = 0; MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, request_parse_arguments_iterator, m); return m->argument_parse_error; } static int request_handler_entries( struct MHD_Connection *connection, void *connection_cls) { struct MHD_Response *response; RequestMeta *m = connection_cls; int r; assert(connection); assert(m); r = open_journal(m); if (r < 0) return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r)); if (request_parse_accept(m, connection) < 0) return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header.\n"); if (request_parse_range(m, connection) < 0) return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Range header.\n"); if (request_parse_arguments(m, connection) < 0) return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse URL arguments.\n"); if (m->discrete) { if (!m->cursor) return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Discrete seeks require a cursor specification.\n"); m->n_entries = 1; m->n_entries_set = true; } if (m->cursor) r = sd_journal_seek_cursor(m->journal, m->cursor); else if (m->n_skip >= 0) r = sd_journal_seek_head(m->journal); else if (m->n_skip < 0) r = sd_journal_seek_tail(m->journal); if (r < 0) return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to seek in journal.\n"); response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_entries, m, NULL); if (!response) return respond_oom(connection); MHD_add_response_header(response, "Content-Type", mime_types[m->mode]); r = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); return r; } static int output_field(FILE *f, OutputMode m, const char *d, size_t l) { const char *eq; size_t j; eq = memchr(d, '=', l); if (!eq) return -EINVAL; j = l - (eq - d + 1); if (m == OUTPUT_JSON) { fprintf(f, "{ \"%.*s\" : ", (int) (eq - d), d); json_escape(f, eq+1, j, OUTPUT_FULL_WIDTH); fputs(" }\n", f); } else { fwrite(eq+1, 1, j, f); fputc('\n', f); } return 0; } static ssize_t request_reader_fields( void *cls, uint64_t pos, char *buf, size_t max) { RequestMeta *m = cls; int r; size_t n, k; assert(m); assert(buf); assert(max > 0); assert(pos >= m->delta); pos -= m->delta; while (pos >= m->size) { off_t sz; const void *d; size_t l; /* End of this field, so let's serialize the next * one */ if (m->n_fields_set && m->n_fields <= 0) return MHD_CONTENT_READER_END_OF_STREAM; r = sd_journal_enumerate_unique(m->journal, &d, &l); if (r < 0) { log_error_errno(r, "Failed to advance field index: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; } else if (r == 0) return MHD_CONTENT_READER_END_OF_STREAM; pos -= m->size; m->delta += m->size; if (m->n_fields_set) m->n_fields -= 1; r = request_meta_ensure_tmp(m); if (r < 0) { log_error_errno(r, "Failed to create temporary file: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; } r = output_field(m->tmp, m->mode, d, l); if (r < 0) { log_error_errno(r, "Failed to serialize item: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; } sz = ftello(m->tmp); if (sz == (off_t) -1) { log_error_errno(errno, "Failed to retrieve file position: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; } m->size = (uint64_t) sz; } if (fseeko(m->tmp, pos, SEEK_SET) < 0) { log_error_errno(errno, "Failed to seek to position: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; } n = m->size - pos; if (n > max) n = max; errno = 0; k = fread(buf, 1, n, m->tmp); if (k != n) { log_error("Failed to read from file: %s", errno ? strerror(errno) : "Premature EOF"); return MHD_CONTENT_READER_END_WITH_ERROR; } return (ssize_t) k; } static int request_handler_fields( struct MHD_Connection *connection, const char *field, void *connection_cls) { struct MHD_Response *response; RequestMeta *m = connection_cls; int r; assert(connection); assert(m); r = open_journal(m); if (r < 0) return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r)); if (request_parse_accept(m, connection) < 0) return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header.\n"); r = sd_journal_query_unique(m->journal, field); if (r < 0) return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to query unique fields.\n"); response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_fields, m, NULL); if (!response) return respond_oom(connection); MHD_add_response_header(response, "Content-Type", mime_types[m->mode == OUTPUT_JSON ? OUTPUT_JSON : OUTPUT_SHORT]); r = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); return r; } static int request_handler_redirect( struct MHD_Connection *connection, const char *target) { char *page; struct MHD_Response *response; int ret; assert(connection); assert(target); if (asprintf(&page, "Please continue to the journal browser.", target) < 0) return respond_oom(connection); response = MHD_create_response_from_buffer(strlen(page), page, MHD_RESPMEM_MUST_FREE); if (!response) { free(page); return respond_oom(connection); } MHD_add_response_header(response, "Content-Type", "text/html"); MHD_add_response_header(response, "Location", target); ret = MHD_queue_response(connection, MHD_HTTP_MOVED_PERMANENTLY, response); MHD_destroy_response(response); return ret; } static int request_handler_file( struct MHD_Connection *connection, const char *path, const char *mime_type) { struct MHD_Response *response; int ret; _cleanup_close_ int fd = -1; struct stat st; assert(connection); assert(path); assert(mime_type); fd = open(path, O_RDONLY|O_CLOEXEC); if (fd < 0) return mhd_respondf(connection, MHD_HTTP_NOT_FOUND, "Failed to open file %s: %m\n", path); if (fstat(fd, &st) < 0) return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to stat file: %m\n"); response = MHD_create_response_from_fd_at_offset64(st.st_size, fd, 0); if (!response) return respond_oom(connection); fd = -1; MHD_add_response_header(response, "Content-Type", mime_type); ret = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); return ret; } static int get_virtualization(char **v) { _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; char *b = NULL; int r; r = sd_bus_default_system(&bus); if (r < 0) return r; r = sd_bus_get_property_string( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Virtualization", NULL, &b); if (r < 0) return r; if (isempty(b)) { free(b); *v = NULL; return 0; } *v = b; return 1; } static int request_handler_machine( struct MHD_Connection *connection, void *connection_cls) { struct MHD_Response *response; RequestMeta *m = connection_cls; int r; _cleanup_free_ char* hostname = NULL, *os_name = NULL; uint64_t cutoff_from = 0, cutoff_to = 0, usage = 0; char *json; sd_id128_t mid, bid; _cleanup_free_ char *v = NULL; assert(connection); assert(m); r = open_journal(m); if (r < 0) return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r)); r = sd_id128_get_machine(&mid); if (r < 0) return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine machine ID: %s\n", strerror(-r)); r = sd_id128_get_boot(&bid); if (r < 0) return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine boot ID: %s\n", strerror(-r)); hostname = gethostname_malloc(); if (!hostname) return respond_oom(connection); r = sd_journal_get_usage(m->journal, &usage); if (r < 0) return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n", strerror(-r)); r = sd_journal_get_cutoff_realtime_usec(m->journal, &cutoff_from, &cutoff_to); if (r < 0) return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n", strerror(-r)); if (parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL) == -ENOENT) (void) parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL); get_virtualization(&v); r = asprintf(&json, "{ \"machine_id\" : \"" SD_ID128_FORMAT_STR "\"," "\"boot_id\" : \"" SD_ID128_FORMAT_STR "\"," "\"hostname\" : \"%s\"," "\"os_pretty_name\" : \"%s\"," "\"virtualization\" : \"%s\"," "\"usage\" : \"%"PRIu64"\"," "\"cutoff_from_realtime\" : \"%"PRIu64"\"," "\"cutoff_to_realtime\" : \"%"PRIu64"\" }\n", SD_ID128_FORMAT_VAL(mid), SD_ID128_FORMAT_VAL(bid), hostname_cleanup(hostname), os_name ? os_name : "Linux", v ? v : "bare", usage, cutoff_from, cutoff_to); if (r < 0) return respond_oom(connection); response = MHD_create_response_from_buffer(strlen(json), json, MHD_RESPMEM_MUST_FREE); if (!response) { free(json); return respond_oom(connection); } MHD_add_response_header(response, "Content-Type", "application/json"); r = MHD_queue_response(connection, MHD_HTTP_OK, response); MHD_destroy_response(response); return r; } static int request_handler( void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **connection_cls) { int r, code; assert(connection); assert(connection_cls); assert(url); assert(method); if (!streq(method, "GET")) return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, "Unsupported method.\n"); if (!*connection_cls) { if (!request_meta(connection_cls)) return respond_oom(connection); return MHD_YES; } if (arg_trust_pem) { r = check_permissions(connection, &code, NULL); if (r < 0) return code; } if (streq(url, "/")) return request_handler_redirect(connection, "/browse"); if (streq(url, "/entries")) return request_handler_entries(connection, *connection_cls); if (startswith(url, "/fields/")) return request_handler_fields(connection, url + 8, *connection_cls); if (streq(url, "/browse")) return request_handler_file(connection, DOCUMENT_ROOT "/browse.html", "text/html"); if (streq(url, "/machine")) return request_handler_machine(connection, *connection_cls); return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found.\n"); } static void help(void) { printf("%s [OPTIONS...] ...\n\n" "HTTP server for journal events.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --cert=CERT.PEM Server certificate in PEM format\n" " --key=KEY.PEM Server key in PEM format\n" " --trust=CERT.PEM Certificat authority certificate in PEM format\n", program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_KEY, ARG_CERT, ARG_TRUST, }; int r, c; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "key", required_argument, NULL, ARG_KEY }, { "cert", required_argument, NULL, ARG_CERT }, { "trust", required_argument, NULL, ARG_TRUST }, {} }; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch(c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_KEY: if (arg_key_pem) { log_error("Key file specified twice"); return -EINVAL; } r = read_full_file(optarg, &arg_key_pem, NULL); if (r < 0) return log_error_errno(r, "Failed to read key file: %m"); assert(arg_key_pem); break; case ARG_CERT: if (arg_cert_pem) { log_error("Certificate file specified twice"); return -EINVAL; } r = read_full_file(optarg, &arg_cert_pem, NULL); if (r < 0) return log_error_errno(r, "Failed to read certificate file: %m"); assert(arg_cert_pem); break; case ARG_TRUST: #ifdef HAVE_GNUTLS if (arg_trust_pem) { log_error("CA certificate file specified twice"); return -EINVAL; } r = read_full_file(optarg, &arg_trust_pem, NULL); if (r < 0) return log_error_errno(r, "Failed to read CA certificate file: %m"); assert(arg_trust_pem); break; #else log_error("Option --trust is not available."); #endif case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (optind < argc) { log_error("This program does not take arguments."); return -EINVAL; } if (!!arg_key_pem != !!arg_cert_pem) { log_error("Certificate and key files must be specified together"); return -EINVAL; } if (arg_trust_pem && !arg_key_pem) { log_error("CA certificate can only be used with certificate file"); return -EINVAL; } return 1; } int main(int argc, char *argv[]) { struct MHD_Daemon *d = NULL; int r, n; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r < 0) return EXIT_FAILURE; if (r == 0) return EXIT_SUCCESS; sigbus_install(); r = setup_gnutls_logger(NULL); if (r < 0) return EXIT_FAILURE; n = sd_listen_fds(1); if (n < 0) { log_error_errno(n, "Failed to determine passed sockets: %m"); goto finish; } else if (n > 1) { log_error("Can't listen on more than one socket."); goto finish; } else { struct MHD_OptionItem opts[] = { { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free, NULL }, { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger, NULL }, { MHD_OPTION_END, 0, NULL }, { MHD_OPTION_END, 0, NULL }, { MHD_OPTION_END, 0, NULL }, { MHD_OPTION_END, 0, NULL }, { MHD_OPTION_END, 0, NULL }}; int opts_pos = 2; /* We force MHD_USE_PIPE_FOR_SHUTDOWN here, in order * to make sure libmicrohttpd doesn't use shutdown() * on our listening socket, which would break socket * re-activation. See * * https://lists.gnu.org/archive/html/libmicrohttpd/2015-09/msg00014.html * https://github.com/systemd/systemd/pull/1286 */ int flags = MHD_USE_DEBUG | MHD_USE_DUAL_STACK | MHD_USE_PIPE_FOR_SHUTDOWN | MHD_USE_POLL | MHD_USE_THREAD_PER_CONNECTION; if (n > 0) opts[opts_pos++] = (struct MHD_OptionItem) {MHD_OPTION_LISTEN_SOCKET, SD_LISTEN_FDS_START}; if (arg_key_pem) { assert(arg_cert_pem); opts[opts_pos++] = (struct MHD_OptionItem) {MHD_OPTION_HTTPS_MEM_KEY, 0, arg_key_pem}; opts[opts_pos++] = (struct MHD_OptionItem) {MHD_OPTION_HTTPS_MEM_CERT, 0, arg_cert_pem}; flags |= MHD_USE_SSL; } if (arg_trust_pem) { assert(flags & MHD_USE_SSL); opts[opts_pos++] = (struct MHD_OptionItem) {MHD_OPTION_HTTPS_MEM_TRUST, 0, arg_trust_pem}; } d = MHD_start_daemon(flags, 19531, NULL, NULL, request_handler, NULL, MHD_OPTION_ARRAY, opts, MHD_OPTION_END); } if (!d) { log_error("Failed to start daemon!"); goto finish; } pause(); r = EXIT_SUCCESS; finish: if (d) MHD_stop_daemon(d); return r; } systemd-229/src/journal-remote/journal-remote-parse.c000066400000000000000000000371071265713322000230420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "fd-util.h" #include "journal-remote-parse.h" #include "journald-native.h" #include "parse-util.h" #include "string-util.h" #define LINE_CHUNK 8*1024u void source_free(RemoteSource *source) { if (!source) return; if (source->fd >= 0 && !source->passive_fd) { log_debug("Closing fd:%d (%s)", source->fd, source->name); safe_close(source->fd); } free(source->name); free(source->buf); iovw_free_contents(&source->iovw); log_debug("Writer ref count %i", source->writer->n_ref); writer_unref(source->writer); sd_event_source_unref(source->event); sd_event_source_unref(source->buffer_event); free(source); } /** * Initialize zero-filled source with given values. On success, takes * ownerhship of fd and writer, otherwise does not touch them. */ RemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer) { RemoteSource *source; log_debug("Creating source for %sfd:%d (%s)", passive_fd ? "passive " : "", fd, name); assert(fd >= 0); source = new0(RemoteSource, 1); if (!source) return NULL; source->fd = fd; source->passive_fd = passive_fd; source->name = name; source->writer = writer; return source; } static char* realloc_buffer(RemoteSource *source, size_t size) { char *b, *old = source->buf; b = GREEDY_REALLOC(source->buf, source->size, size); if (!b) return NULL; iovw_rebase(&source->iovw, old, source->buf); return b; } static int get_line(RemoteSource *source, char **line, size_t *size) { ssize_t n; char *c = NULL; assert(source); assert(source->state == STATE_LINE); assert(source->offset <= source->filled); assert(source->filled <= source->size); assert(source->buf == NULL || source->size > 0); assert(source->fd >= 0); for (;;) { if (source->buf) { size_t start = MAX(source->scanned, source->offset); c = memchr(source->buf + start, '\n', source->filled - start); if (c != NULL) break; } source->scanned = source->filled; if (source->scanned >= DATA_SIZE_MAX) { log_error("Entry is bigger than %u bytes.", DATA_SIZE_MAX); return -E2BIG; } if (source->passive_fd) /* we have to wait for some data to come to us */ return -EAGAIN; /* We know that source->filled is at most DATA_SIZE_MAX, so if we reallocate it, we'll increase the size at least a bit. */ assert_cc(DATA_SIZE_MAX < ENTRY_SIZE_MAX); if (source->size - source->filled < LINE_CHUNK && !realloc_buffer(source, MIN(source->filled + LINE_CHUNK, ENTRY_SIZE_MAX))) return log_oom(); assert(source->buf); assert(source->size - source->filled >= LINE_CHUNK || source->size == ENTRY_SIZE_MAX); n = read(source->fd, source->buf + source->filled, source->size - source->filled); if (n < 0) { if (errno != EAGAIN) log_error_errno(errno, "read(%d, ..., %zu): %m", source->fd, source->size - source->filled); return -errno; } else if (n == 0) return 0; source->filled += n; } *line = source->buf + source->offset; *size = c + 1 - source->buf - source->offset; source->offset += *size; return 1; } int push_data(RemoteSource *source, const char *data, size_t size) { assert(source); assert(source->state != STATE_EOF); if (!realloc_buffer(source, source->filled + size)) { log_error("Failed to store received data of size %zu " "(in addition to existing %zu bytes with %zu filled): %s", size, source->size, source->filled, strerror(ENOMEM)); return -ENOMEM; } memcpy(source->buf + source->filled, data, size); source->filled += size; return 0; } static int fill_fixed_size(RemoteSource *source, void **data, size_t size) { assert(source); assert(source->state == STATE_DATA_START || source->state == STATE_DATA || source->state == STATE_DATA_FINISH); assert(size <= DATA_SIZE_MAX); assert(source->offset <= source->filled); assert(source->filled <= source->size); assert(source->buf != NULL || source->size == 0); assert(source->buf == NULL || source->size > 0); assert(source->fd >= 0); assert(data); while (source->filled - source->offset < size) { int n; if (source->passive_fd) /* we have to wait for some data to come to us */ return -EAGAIN; if (!realloc_buffer(source, source->offset + size)) return log_oom(); n = read(source->fd, source->buf + source->filled, source->size - source->filled); if (n < 0) { if (errno != EAGAIN) log_error_errno(errno, "read(%d, ..., %zu): %m", source->fd, source->size - source->filled); return -errno; } else if (n == 0) return 0; source->filled += n; } *data = source->buf + source->offset; source->offset += size; return 1; } static int get_data_size(RemoteSource *source) { int r; void *data; assert(source); assert(source->state == STATE_DATA_START); assert(source->data_size == 0); r = fill_fixed_size(source, &data, sizeof(uint64_t)); if (r <= 0) return r; source->data_size = le64toh( *(uint64_t *) data ); if (source->data_size > DATA_SIZE_MAX) { log_error("Stream declares field with size %zu > DATA_SIZE_MAX = %u", source->data_size, DATA_SIZE_MAX); return -EINVAL; } if (source->data_size == 0) log_warning("Binary field with zero length"); return 1; } static int get_data_data(RemoteSource *source, void **data) { int r; assert(source); assert(data); assert(source->state == STATE_DATA); r = fill_fixed_size(source, data, source->data_size); if (r <= 0) return r; return 1; } static int get_data_newline(RemoteSource *source) { int r; char *data; assert(source); assert(source->state == STATE_DATA_FINISH); r = fill_fixed_size(source, (void**) &data, 1); if (r <= 0) return r; assert(data); if (*data != '\n') { log_error("expected newline, got '%c'", *data); return -EINVAL; } return 1; } static int process_dunder(RemoteSource *source, char *line, size_t n) { const char *timestamp; int r; assert(line); assert(n > 0); assert(line[n-1] == '\n'); /* XXX: is it worth to support timestamps in extended format? * We don't produce them, but who knows... */ timestamp = startswith(line, "__CURSOR="); if (timestamp) /* ignore __CURSOR */ return 1; timestamp = startswith(line, "__REALTIME_TIMESTAMP="); if (timestamp) { long long unsigned x; line[n-1] = '\0'; r = safe_atollu(timestamp, &x); if (r < 0) log_warning("Failed to parse __REALTIME_TIMESTAMP: '%s'", timestamp); else source->ts.realtime = x; return r < 0 ? r : 1; } timestamp = startswith(line, "__MONOTONIC_TIMESTAMP="); if (timestamp) { long long unsigned x; line[n-1] = '\0'; r = safe_atollu(timestamp, &x); if (r < 0) log_warning("Failed to parse __MONOTONIC_TIMESTAMP: '%s'", timestamp); else source->ts.monotonic = x; return r < 0 ? r : 1; } timestamp = startswith(line, "__"); if (timestamp) { log_notice("Unknown dunder line %s", line); return 1; } /* no dunder */ return 0; } static int process_data(RemoteSource *source) { int r; switch(source->state) { case STATE_LINE: { char *line, *sep; size_t n = 0; assert(source->data_size == 0); r = get_line(source, &line, &n); if (r < 0) return r; if (r == 0) { source->state = STATE_EOF; return r; } assert(n > 0); assert(line[n-1] == '\n'); if (n == 1) { log_trace("Received empty line, event is ready"); return 1; } r = process_dunder(source, line, n); if (r != 0) return r < 0 ? r : 0; /* MESSAGE=xxx\n or COREDUMP\n LLLLLLLL0011223344...\n */ sep = memchr(line, '=', n); if (sep) { /* chomp newline */ n--; r = iovw_put(&source->iovw, line, n); if (r < 0) return r; } else { /* replace \n with = */ line[n-1] = '='; source->field_len = n; source->state = STATE_DATA_START; /* we cannot put the field in iovec until we have all data */ } log_trace("Received: %.*s (%s)", (int) n, line, sep ? "text" : "binary"); return 0; /* continue */ } case STATE_DATA_START: assert(source->data_size == 0); r = get_data_size(source); // log_debug("get_data_size() -> %d", r); if (r < 0) return r; if (r == 0) { source->state = STATE_EOF; return 0; } source->state = source->data_size > 0 ? STATE_DATA : STATE_DATA_FINISH; return 0; /* continue */ case STATE_DATA: { void *data; char *field; assert(source->data_size > 0); r = get_data_data(source, &data); // log_debug("get_data_data() -> %d", r); if (r < 0) return r; if (r == 0) { source->state = STATE_EOF; return 0; } assert(data); field = (char*) data - sizeof(uint64_t) - source->field_len; memmove(field + sizeof(uint64_t), field, source->field_len); r = iovw_put(&source->iovw, field + sizeof(uint64_t), source->field_len + source->data_size); if (r < 0) return r; source->state = STATE_DATA_FINISH; return 0; /* continue */ } case STATE_DATA_FINISH: r = get_data_newline(source); // log_debug("get_data_newline() -> %d", r); if (r < 0) return r; if (r == 0) { source->state = STATE_EOF; return 0; } source->data_size = 0; source->state = STATE_LINE; return 0; /* continue */ default: assert_not_reached("wtf?"); } } int process_source(RemoteSource *source, bool compress, bool seal) { size_t remain, target; int r; assert(source); assert(source->writer); r = process_data(source); if (r <= 0) return r; /* We have a full event */ log_trace("Received full event from source@%p fd:%d (%s)", source, source->fd, source->name); if (!source->iovw.count) { log_warning("Entry with no payload, skipping"); goto freeing; } assert(source->iovw.iovec); assert(source->iovw.count); r = writer_write(source->writer, &source->iovw, &source->ts, compress, seal); if (r < 0) log_error_errno(r, "Failed to write entry of %zu bytes: %m", iovw_size(&source->iovw)); else r = 1; freeing: iovw_free_contents(&source->iovw); /* possibly reset buffer position */ remain = source->filled - source->offset; if (remain == 0) /* no brainer */ source->offset = source->scanned = source->filled = 0; else if (source->offset > source->size - source->filled && source->offset > remain) { memcpy(source->buf, source->buf + source->offset, remain); source->offset = source->scanned = 0; source->filled = remain; } target = source->size; while (target > 16 * LINE_CHUNK && remain < target / 2) target /= 2; if (target < source->size) { char *tmp; tmp = realloc(source->buf, target); if (!tmp) log_warning("Failed to reallocate buffer to (smaller) size %zu", target); else { log_debug("Reallocated buffer from %zu to %zu bytes", source->size, target); source->buf = tmp; source->size = target; } } return r; } systemd-229/src/journal-remote/journal-remote-parse.h000066400000000000000000000043341265713322000230430ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "sd-event.h" #include "journal-remote-write.h" typedef enum { STATE_LINE = 0, /* waiting to read, or reading line */ STATE_DATA_START, /* reading binary data header */ STATE_DATA, /* reading binary data */ STATE_DATA_FINISH, /* expecting newline */ STATE_EOF, /* done */ } source_state; typedef struct RemoteSource { char *name; int fd; bool passive_fd; char *buf; size_t size; /* total size of the buffer */ size_t offset; /* offset to the beginning of live data in the buffer */ size_t scanned; /* number of bytes since the beginning of data without a newline */ size_t filled; /* total number of bytes in the buffer */ size_t field_len; /* used for binary fields: the field name length */ size_t data_size; /* and the size of the binary data chunk being processed */ struct iovec_wrapper iovw; source_state state; dual_timestamp ts; Writer *writer; sd_event_source *event; sd_event_source *buffer_event; } RemoteSource; RemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer); static inline size_t source_non_empty(RemoteSource *source) { assert(source); return source->filled; } void source_free(RemoteSource *source); int push_data(RemoteSource *source, const char *data, size_t size); int process_source(RemoteSource *source, bool compress, bool seal); systemd-229/src/journal-remote/journal-remote-write.c000066400000000000000000000112551265713322000230560ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "journal-remote.h" int iovw_put(struct iovec_wrapper *iovw, void* data, size_t len) { if (!GREEDY_REALLOC(iovw->iovec, iovw->size_bytes, iovw->count + 1)) return log_oom(); iovw->iovec[iovw->count++] = (struct iovec) {data, len}; return 0; } void iovw_free_contents(struct iovec_wrapper *iovw) { iovw->iovec = mfree(iovw->iovec); iovw->size_bytes = iovw->count = 0; } size_t iovw_size(struct iovec_wrapper *iovw) { size_t n = 0, i; for (i = 0; i < iovw->count; i++) n += iovw->iovec[i].iov_len; return n; } void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new) { size_t i; for (i = 0; i < iovw->count; i++) iovw->iovec[i].iov_base = (char*) iovw->iovec[i].iov_base - old + new; } /********************************************************************** ********************************************************************** **********************************************************************/ static int do_rotate(JournalFile **f, bool compress, bool seal) { int r = journal_file_rotate(f, compress, seal); if (r < 0) { if (*f) log_error_errno(r, "Failed to rotate %s: %m", (*f)->path); else log_error_errno(r, "Failed to create rotated journal: %m"); } return r; } Writer* writer_new(RemoteServer *server) { Writer *w; w = new0(Writer, 1); if (!w) return NULL; memset(&w->metrics, 0xFF, sizeof(w->metrics)); w->mmap = mmap_cache_new(); if (!w->mmap) { free(w); return NULL; } w->n_ref = 1; w->server = server; return w; } Writer* writer_free(Writer *w) { if (!w) return NULL; if (w->journal) { log_debug("Closing journal file %s.", w->journal->path); journal_file_close(w->journal); } if (w->server && w->hashmap_key) hashmap_remove(w->server->writers, w->hashmap_key); free(w->hashmap_key); if (w->mmap) mmap_cache_unref(w->mmap); free(w); return NULL; } Writer* writer_unref(Writer *w) { if (w && (-- w->n_ref <= 0)) writer_free(w); return NULL; } Writer* writer_ref(Writer *w) { if (w) assert_se(++ w->n_ref >= 2); return w; } int writer_write(Writer *w, struct iovec_wrapper *iovw, dual_timestamp *ts, bool compress, bool seal) { int r; assert(w); assert(iovw); assert(iovw->count > 0); if (journal_file_rotate_suggested(w->journal, 0)) { log_info("%s: Journal header limits reached or header out-of-date, rotating", w->journal->path); r = do_rotate(&w->journal, compress, seal); if (r < 0) return r; } r = journal_file_append_entry(w->journal, ts, iovw->iovec, iovw->count, &w->seqnum, NULL, NULL); if (r >= 0) { if (w->server) w->server->event_count += 1; return 1; } log_debug_errno(r, "%s: Write failed, rotating: %m", w->journal->path); r = do_rotate(&w->journal, compress, seal); if (r < 0) return r; else log_debug("%s: Successfully rotated journal", w->journal->path); log_debug("Retrying write."); r = journal_file_append_entry(w->journal, ts, iovw->iovec, iovw->count, &w->seqnum, NULL, NULL); if (r < 0) return r; if (w->server) w->server->event_count += 1; return 1; } systemd-229/src/journal-remote/journal-remote-write.h000066400000000000000000000037261265713322000230670ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "journal-file.h" typedef struct RemoteServer RemoteServer; struct iovec_wrapper { struct iovec *iovec; size_t size_bytes; size_t count; }; int iovw_put(struct iovec_wrapper *iovw, void* data, size_t len); void iovw_free_contents(struct iovec_wrapper *iovw); size_t iovw_size(struct iovec_wrapper *iovw); void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new); typedef struct Writer { JournalFile *journal; JournalMetrics metrics; MMapCache *mmap; RemoteServer *server; char *hashmap_key; uint64_t seqnum; int n_ref; } Writer; Writer* writer_new(RemoteServer* server); Writer* writer_free(Writer *w); Writer* writer_ref(Writer *w); Writer* writer_unref(Writer *w); DEFINE_TRIVIAL_CLEANUP_FUNC(Writer*, writer_unref); #define _cleanup_writer_unref_ _cleanup_(writer_unrefp) int writer_write(Writer *s, struct iovec_wrapper *iovw, dual_timestamp *ts, bool compress, bool seal); typedef enum JournalWriteSplitMode { JOURNAL_WRITE_SPLIT_NONE, JOURNAL_WRITE_SPLIT_HOST, _JOURNAL_WRITE_SPLIT_MAX, _JOURNAL_WRITE_SPLIT_INVALID = -1 } JournalWriteSplitMode; systemd-229/src/journal-remote/journal-remote.c000066400000000000000000001534721265713322000217360ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #ifdef HAVE_GNUTLS #include #endif #include "sd-daemon.h" #include "alloc-util.h" #include "conf-parser.h" #include "def.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "journal-file.h" #include "journal-remote-write.h" #include "journal-remote.h" #include "journald-native.h" #include "macro.h" #include "parse-util.h" #include "signal-util.h" #include "socket-util.h" #include "stat-util.h" #include "stdio-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #define REMOTE_JOURNAL_PATH "/var/log/journal/remote" #define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-remote.pem" #define CERT_FILE CERTIFICATE_ROOT "/certs/journal-remote.pem" #define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem" static char* arg_url = NULL; static char* arg_getter = NULL; static char* arg_listen_raw = NULL; static char* arg_listen_http = NULL; static char* arg_listen_https = NULL; static char** arg_files = NULL; static int arg_compress = true; static int arg_seal = false; static int http_socket = -1, https_socket = -1; static char** arg_gnutls_log = NULL; static JournalWriteSplitMode arg_split_mode = JOURNAL_WRITE_SPLIT_HOST; static char* arg_output = NULL; static char *arg_key = NULL; static char *arg_cert = NULL; static char *arg_trust = NULL; static bool arg_trust_all = false; /********************************************************************** ********************************************************************** **********************************************************************/ static int spawn_child(const char* child, char** argv) { int fd[2]; pid_t parent_pid, child_pid; int r; if (pipe(fd) < 0) return log_error_errno(errno, "Failed to create pager pipe: %m"); parent_pid = getpid(); child_pid = fork(); if (child_pid < 0) { r = log_error_errno(errno, "Failed to fork: %m"); safe_close_pair(fd); return r; } /* In the child */ if (child_pid == 0) { (void) reset_all_signal_handlers(); (void) reset_signal_mask(); r = dup2(fd[1], STDOUT_FILENO); if (r < 0) { log_error_errno(errno, "Failed to dup pipe to stdout: %m"); _exit(EXIT_FAILURE); } safe_close_pair(fd); /* Make sure the child goes away when the parent dies */ if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) _exit(EXIT_FAILURE); /* Check whether our parent died before we were able * to set the death signal */ if (getppid() != parent_pid) _exit(EXIT_SUCCESS); execvp(child, argv); log_error_errno(errno, "Failed to exec child %s: %m", child); _exit(EXIT_FAILURE); } r = close(fd[1]); if (r < 0) log_warning_errno(errno, "Failed to close write end of pipe: %m"); return fd[0]; } static int spawn_curl(const char* url) { char **argv = STRV_MAKE("curl", "-HAccept: application/vnd.fdo.journal", "--silent", "--show-error", url); int r; r = spawn_child("curl", argv); if (r < 0) log_error_errno(r, "Failed to spawn curl: %m"); return r; } static int spawn_getter(const char *getter) { int r; _cleanup_strv_free_ char **words = NULL; assert(getter); r = strv_split_extract(&words, getter, WHITESPACE, EXTRACT_QUOTES); if (r < 0) return log_error_errno(r, "Failed to split getter option: %m"); r = spawn_child(words[0], words); if (r < 0) log_error_errno(r, "Failed to spawn getter %s: %m", getter); return r; } #define filename_escape(s) xescape((s), "/ ") static int open_output(Writer *w, const char* host) { _cleanup_free_ char *_output = NULL; const char *output; int r; switch (arg_split_mode) { case JOURNAL_WRITE_SPLIT_NONE: output = arg_output ?: REMOTE_JOURNAL_PATH "/remote.journal"; break; case JOURNAL_WRITE_SPLIT_HOST: { _cleanup_free_ char *name; assert(host); name = filename_escape(host); if (!name) return log_oom(); r = asprintf(&_output, "%s/remote-%s.journal", arg_output ?: REMOTE_JOURNAL_PATH, name); if (r < 0) return log_oom(); output = _output; break; } default: assert_not_reached("what?"); } r = journal_file_open_reliably(output, O_RDWR|O_CREAT, 0640, arg_compress, arg_seal, &w->metrics, w->mmap, NULL, &w->journal); if (r < 0) log_error_errno(r, "Failed to open output journal %s: %m", output); else log_debug("Opened output file %s", w->journal->path); return r; } /********************************************************************** ********************************************************************** **********************************************************************/ static int init_writer_hashmap(RemoteServer *s) { static const struct hash_ops *hash_ops[] = { [JOURNAL_WRITE_SPLIT_NONE] = NULL, [JOURNAL_WRITE_SPLIT_HOST] = &string_hash_ops, }; assert(arg_split_mode >= 0 && arg_split_mode < (int) ELEMENTSOF(hash_ops)); s->writers = hashmap_new(hash_ops[arg_split_mode]); if (!s->writers) return log_oom(); return 0; } static int get_writer(RemoteServer *s, const char *host, Writer **writer) { const void *key; _cleanup_writer_unref_ Writer *w = NULL; int r; switch(arg_split_mode) { case JOURNAL_WRITE_SPLIT_NONE: key = "one and only"; break; case JOURNAL_WRITE_SPLIT_HOST: assert(host); key = host; break; default: assert_not_reached("what split mode?"); } w = hashmap_get(s->writers, key); if (w) writer_ref(w); else { w = writer_new(s); if (!w) return log_oom(); if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST) { w->hashmap_key = strdup(key); if (!w->hashmap_key) return log_oom(); } r = open_output(w, host); if (r < 0) return r; r = hashmap_put(s->writers, w->hashmap_key ?: key, w); if (r < 0) return r; } *writer = w; w = NULL; return 0; } /********************************************************************** ********************************************************************** **********************************************************************/ /* This should go away as soon as µhttpd allows state to be passed around. */ static RemoteServer *server; static int dispatch_raw_source_event(sd_event_source *event, int fd, uint32_t revents, void *userdata); static int dispatch_raw_source_until_block(sd_event_source *event, void *userdata); static int dispatch_blocking_source_event(sd_event_source *event, void *userdata); static int dispatch_raw_connection_event(sd_event_source *event, int fd, uint32_t revents, void *userdata); static int dispatch_http_event(sd_event_source *event, int fd, uint32_t revents, void *userdata); static int get_source_for_fd(RemoteServer *s, int fd, char *name, RemoteSource **source) { Writer *writer; int r; /* This takes ownership of name, but only on success. */ assert(fd >= 0); assert(source); if (!GREEDY_REALLOC0(s->sources, s->sources_size, fd + 1)) return log_oom(); r = get_writer(s, name, &writer); if (r < 0) return log_warning_errno(r, "Failed to get writer for source %s: %m", name); if (s->sources[fd] == NULL) { s->sources[fd] = source_new(fd, false, name, writer); if (!s->sources[fd]) { writer_unref(writer); return log_oom(); } s->active++; } *source = s->sources[fd]; return 0; } static int remove_source(RemoteServer *s, int fd) { RemoteSource *source; assert(s); assert(fd >= 0 && fd < (ssize_t) s->sources_size); source = s->sources[fd]; if (source) { /* this closes fd too */ source_free(source); s->sources[fd] = NULL; s->active--; } return 0; } static int add_source(RemoteServer *s, int fd, char* name, bool own_name) { RemoteSource *source = NULL; int r; /* This takes ownership of name, even on failure, if own_name is true. */ assert(s); assert(fd >= 0); assert(name); if (!own_name) { name = strdup(name); if (!name) return log_oom(); } r = get_source_for_fd(s, fd, name, &source); if (r < 0) { log_error_errno(r, "Failed to create source for fd:%d (%s): %m", fd, name); free(name); return r; } r = sd_event_add_io(s->events, &source->event, fd, EPOLLIN|EPOLLRDHUP|EPOLLPRI, dispatch_raw_source_event, source); if (r == 0) { /* Add additional source for buffer processing. It will be * enabled later. */ r = sd_event_add_defer(s->events, &source->buffer_event, dispatch_raw_source_until_block, source); if (r == 0) sd_event_source_set_enabled(source->buffer_event, SD_EVENT_OFF); } else if (r == -EPERM) { log_debug("Falling back to sd_event_add_defer for fd:%d (%s)", fd, name); r = sd_event_add_defer(s->events, &source->event, dispatch_blocking_source_event, source); if (r == 0) sd_event_source_set_enabled(source->event, SD_EVENT_ON); } if (r < 0) { log_error_errno(r, "Failed to register event source for fd:%d: %m", fd); goto error; } r = sd_event_source_set_description(source->event, name); if (r < 0) { log_error_errno(r, "Failed to set source name for fd:%d: %m", fd); goto error; } return 1; /* work to do */ error: remove_source(s, fd); return r; } static int add_raw_socket(RemoteServer *s, int fd) { int r; _cleanup_close_ int fd_ = fd; char name[sizeof("raw-socket-")-1 + DECIMAL_STR_MAX(int) + 1]; assert(fd >= 0); r = sd_event_add_io(s->events, &s->listen_event, fd, EPOLLIN, dispatch_raw_connection_event, s); if (r < 0) return r; xsprintf(name, "raw-socket-%d", fd); r = sd_event_source_set_description(s->listen_event, name); if (r < 0) return r; fd_ = -1; s->active ++; return 0; } static int setup_raw_socket(RemoteServer *s, const char *address) { int fd; fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM, SOCK_CLOEXEC); if (fd < 0) return fd; return add_raw_socket(s, fd); } /********************************************************************** ********************************************************************** **********************************************************************/ static int request_meta(void **connection_cls, int fd, char *hostname) { RemoteSource *source; Writer *writer; int r; assert(connection_cls); if (*connection_cls) return 0; r = get_writer(server, hostname, &writer); if (r < 0) return log_warning_errno(r, "Failed to get writer for source %s: %m", hostname); source = source_new(fd, true, hostname, writer); if (!source) { writer_unref(writer); return log_oom(); } log_debug("Added RemoteSource as connection metadata %p", source); *connection_cls = source; return 0; } static void request_meta_free(void *cls, struct MHD_Connection *connection, void **connection_cls, enum MHD_RequestTerminationCode toe) { RemoteSource *s; assert(connection_cls); s = *connection_cls; if (s) { log_debug("Cleaning up connection metadata %p", s); source_free(s); *connection_cls = NULL; } } static int process_http_upload( struct MHD_Connection *connection, const char *upload_data, size_t *upload_data_size, RemoteSource *source) { bool finished = false; size_t remaining; int r; assert(source); log_trace("%s: connection %p, %zu bytes", __func__, connection, *upload_data_size); if (*upload_data_size) { log_trace("Received %zu bytes", *upload_data_size); r = push_data(source, upload_data, *upload_data_size); if (r < 0) return mhd_respond_oom(connection); *upload_data_size = 0; } else finished = true; for (;;) { r = process_source(source, arg_compress, arg_seal); if (r == -EAGAIN) break; else if (r < 0) { log_warning("Failed to process data for connection %p", connection); if (r == -E2BIG) return mhd_respondf(connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, "Entry is too large, maximum is %u bytes.\n", DATA_SIZE_MAX); else return mhd_respondf(connection, MHD_HTTP_UNPROCESSABLE_ENTITY, "Processing failed: %s.", strerror(-r)); } } if (!finished) return MHD_YES; /* The upload is finished */ remaining = source_non_empty(source); if (remaining > 0) { log_warning("Premature EOFbyte. %zu bytes lost.", remaining); return mhd_respondf(connection, MHD_HTTP_EXPECTATION_FAILED, "Premature EOF. %zu bytes of trailing data not processed.", remaining); } return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK.\n"); }; static int request_handler( void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **connection_cls) { const char *header; int r, code, fd; _cleanup_free_ char *hostname = NULL; assert(connection); assert(connection_cls); assert(url); assert(method); log_trace("Handling a connection %s %s %s", method, url, version); if (*connection_cls) return process_http_upload(connection, upload_data, upload_data_size, *connection_cls); if (!streq(method, "POST")) return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, "Unsupported method.\n"); if (!streq(url, "/upload")) return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found.\n"); header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Type"); if (!header || !streq(header, "application/vnd.fdo.journal")) return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE, "Content-Type: application/vnd.fdo.journal" " is required.\n"); { const union MHD_ConnectionInfo *ci; ci = MHD_get_connection_info(connection, MHD_CONNECTION_INFO_CONNECTION_FD); if (!ci) { log_error("MHD_get_connection_info failed: cannot get remote fd"); return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Cannot check remote address"); } fd = ci->connect_fd; assert(fd >= 0); } if (server->check_trust) { r = check_permissions(connection, &code, &hostname); if (r < 0) return code; } else { r = getpeername_pretty(fd, false, &hostname); if (r < 0) return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Cannot check remote hostname"); } assert(hostname); r = request_meta(connection_cls, fd, hostname); if (r == -ENOMEM) return respond_oom(connection); else if (r < 0) return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, strerror(-r)); hostname = NULL; return MHD_YES; } static int setup_microhttpd_server(RemoteServer *s, int fd, const char *key, const char *cert, const char *trust) { struct MHD_OptionItem opts[] = { { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free}, { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger}, { MHD_OPTION_LISTEN_SOCKET, fd}, { MHD_OPTION_CONNECTION_MEMORY_LIMIT, 128*1024}, { MHD_OPTION_END}, { MHD_OPTION_END}, { MHD_OPTION_END}, { MHD_OPTION_END}}; int opts_pos = 4; int flags = MHD_USE_DEBUG | MHD_USE_DUAL_STACK | MHD_USE_EPOLL_LINUX_ONLY | MHD_USE_PEDANTIC_CHECKS | MHD_USE_PIPE_FOR_SHUTDOWN; const union MHD_DaemonInfo *info; int r, epoll_fd; MHDDaemonWrapper *d; assert(fd >= 0); r = fd_nonblock(fd, true); if (r < 0) return log_error_errno(r, "Failed to make fd:%d nonblocking: %m", fd); if (key) { assert(cert); opts[opts_pos++] = (struct MHD_OptionItem) {MHD_OPTION_HTTPS_MEM_KEY, 0, (char*) key}; opts[opts_pos++] = (struct MHD_OptionItem) {MHD_OPTION_HTTPS_MEM_CERT, 0, (char*) cert}; flags |= MHD_USE_SSL; if (trust) opts[opts_pos++] = (struct MHD_OptionItem) {MHD_OPTION_HTTPS_MEM_TRUST, 0, (char*) trust}; } d = new(MHDDaemonWrapper, 1); if (!d) return log_oom(); d->fd = (uint64_t) fd; d->daemon = MHD_start_daemon(flags, 0, NULL, NULL, request_handler, NULL, MHD_OPTION_ARRAY, opts, MHD_OPTION_END); if (!d->daemon) { log_error("Failed to start µhttp daemon"); r = -EINVAL; goto error; } log_debug("Started MHD %s daemon on fd:%d (wrapper @ %p)", key ? "HTTPS" : "HTTP", fd, d); info = MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY); if (!info) { log_error("µhttp returned NULL daemon info"); r = -EOPNOTSUPP; goto error; } epoll_fd = info->listen_fd; if (epoll_fd < 0) { log_error("µhttp epoll fd is invalid"); r = -EUCLEAN; goto error; } r = sd_event_add_io(s->events, &d->event, epoll_fd, EPOLLIN, dispatch_http_event, d); if (r < 0) { log_error_errno(r, "Failed to add event callback: %m"); goto error; } r = sd_event_source_set_description(d->event, "epoll-fd"); if (r < 0) { log_error_errno(r, "Failed to set source name: %m"); goto error; } r = hashmap_ensure_allocated(&s->daemons, &uint64_hash_ops); if (r < 0) { log_oom(); goto error; } r = hashmap_put(s->daemons, &d->fd, d); if (r < 0) { log_error_errno(r, "Failed to add daemon to hashmap: %m"); goto error; } s->active ++; return 0; error: MHD_stop_daemon(d->daemon); free(d->daemon); free(d); return r; } static int setup_microhttpd_socket(RemoteServer *s, const char *address, const char *key, const char *cert, const char *trust) { int fd; fd = make_socket_fd(LOG_DEBUG, address, SOCK_STREAM, SOCK_CLOEXEC); if (fd < 0) return fd; return setup_microhttpd_server(s, fd, key, cert, trust); } static int dispatch_http_event(sd_event_source *event, int fd, uint32_t revents, void *userdata) { MHDDaemonWrapper *d = userdata; int r; assert(d); r = MHD_run(d->daemon); if (r == MHD_NO) { log_error("MHD_run failed!"); // XXX: unregister daemon return -EINVAL; } return 1; /* work to do */ } /********************************************************************** ********************************************************************** **********************************************************************/ static int setup_signals(RemoteServer *s) { int r; assert(s); assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, -1) >= 0); r = sd_event_add_signal(s->events, &s->sigterm_event, SIGTERM, NULL, s); if (r < 0) return r; r = sd_event_add_signal(s->events, &s->sigint_event, SIGINT, NULL, s); if (r < 0) return r; return 0; } static int negative_fd(const char *spec) { /* Return a non-positive number as its inverse, -EINVAL otherwise. */ int fd, r; r = safe_atoi(spec, &fd); if (r < 0) return r; if (fd > 0) return -EINVAL; else return -fd; } static int remoteserver_init(RemoteServer *s, const char* key, const char* cert, const char* trust) { int r, n, fd; char **file; assert(s); if ((arg_listen_raw || arg_listen_http) && trust) { log_error("Option --trust makes all non-HTTPS connections untrusted."); return -EINVAL; } r = sd_event_default(&s->events); if (r < 0) return log_error_errno(r, "Failed to allocate event loop: %m"); setup_signals(s); assert(server == NULL); server = s; r = init_writer_hashmap(s); if (r < 0) return r; n = sd_listen_fds(true); if (n < 0) return log_error_errno(n, "Failed to read listening file descriptors from environment: %m"); else log_debug("Received %d descriptors", n); if (MAX(http_socket, https_socket) >= SD_LISTEN_FDS_START + n) { log_error("Received fewer sockets than expected"); return -EBADFD; } for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { if (sd_is_socket(fd, AF_UNSPEC, 0, true)) { log_debug("Received a listening socket (fd:%d)", fd); if (fd == http_socket) r = setup_microhttpd_server(s, fd, NULL, NULL, NULL); else if (fd == https_socket) r = setup_microhttpd_server(s, fd, key, cert, trust); else r = add_raw_socket(s, fd); } else if (sd_is_socket(fd, AF_UNSPEC, 0, false)) { char *hostname; r = getpeername_pretty(fd, false, &hostname); if (r < 0) return log_error_errno(r, "Failed to retrieve remote name: %m"); log_debug("Received a connection socket (fd:%d) from %s", fd, hostname); r = add_source(s, fd, hostname, true); } else { log_error("Unknown socket passed on fd:%d", fd); return -EINVAL; } if (r < 0) return log_error_errno(r, "Failed to register socket (fd:%d): %m", fd); } if (arg_getter) { log_info("Spawning getter %s...", arg_getter); fd = spawn_getter(arg_getter); if (fd < 0) return fd; r = add_source(s, fd, (char*) arg_output, false); if (r < 0) return r; } if (arg_url) { const char *url; char *hostname, *p; if (!strstr(arg_url, "/entries")) { if (endswith(arg_url, "/")) url = strjoina(arg_url, "entries"); else url = strjoina(arg_url, "/entries"); } else url = strdupa(arg_url); log_info("Spawning curl %s...", url); fd = spawn_curl(url); if (fd < 0) return fd; hostname = startswith(arg_url, "https://") ?: startswith(arg_url, "http://") ?: arg_url; hostname = strdupa(hostname); if ((p = strchr(hostname, '/'))) *p = '\0'; if ((p = strchr(hostname, ':'))) *p = '\0'; r = add_source(s, fd, hostname, false); if (r < 0) return r; } if (arg_listen_raw) { log_debug("Listening on a socket..."); r = setup_raw_socket(s, arg_listen_raw); if (r < 0) return r; } if (arg_listen_http) { r = setup_microhttpd_socket(s, arg_listen_http, NULL, NULL, NULL); if (r < 0) return r; } if (arg_listen_https) { r = setup_microhttpd_socket(s, arg_listen_https, key, cert, trust); if (r < 0) return r; } STRV_FOREACH(file, arg_files) { const char *output_name; if (streq(*file, "-")) { log_debug("Using standard input as source."); fd = STDIN_FILENO; output_name = "stdin"; } else { log_debug("Reading file %s...", *file); fd = open(*file, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); if (fd < 0) return log_error_errno(errno, "Failed to open %s: %m", *file); output_name = *file; } r = add_source(s, fd, (char*) output_name, false); if (r < 0) return r; } if (s->active == 0) { log_error("Zero sources specified"); return -EINVAL; } if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE) { /* In this case we know what the writer will be called, so we can create it and verify that we can create output as expected. */ r = get_writer(s, NULL, &s->_single_writer); if (r < 0) return r; } return 0; } static void server_destroy(RemoteServer *s) { size_t i; MHDDaemonWrapper *d; while ((d = hashmap_steal_first(s->daemons))) { MHD_stop_daemon(d->daemon); sd_event_source_unref(d->event); free(d); } hashmap_free(s->daemons); assert(s->sources_size == 0 || s->sources); for (i = 0; i < s->sources_size; i++) remove_source(s, i); free(s->sources); writer_unref(s->_single_writer); hashmap_free(s->writers); sd_event_source_unref(s->sigterm_event); sd_event_source_unref(s->sigint_event); sd_event_source_unref(s->listen_event); sd_event_unref(s->events); /* fds that we're listening on remain open... */ } /********************************************************************** ********************************************************************** **********************************************************************/ static int handle_raw_source(sd_event_source *event, int fd, uint32_t revents, RemoteServer *s) { RemoteSource *source; int r; /* Returns 1 if there might be more data pending, * 0 if data is currently exhausted, negative on error. */ assert(fd >= 0 && fd < (ssize_t) s->sources_size); source = s->sources[fd]; assert(source->fd == fd); r = process_source(source, arg_compress, arg_seal); if (source->state == STATE_EOF) { size_t remaining; log_debug("EOF reached with source fd:%d (%s)", source->fd, source->name); remaining = source_non_empty(source); if (remaining > 0) log_notice("Premature EOF. %zu bytes lost.", remaining); remove_source(s, source->fd); log_debug("%zu active sources remaining", s->active); return 0; } else if (r == -E2BIG) { log_notice_errno(E2BIG, "Entry too big, skipped"); return 1; } else if (r == -EAGAIN) { return 0; } else if (r < 0) { log_debug_errno(r, "Closing connection: %m"); remove_source(server, fd); return 0; } else return 1; } static int dispatch_raw_source_until_block(sd_event_source *event, void *userdata) { RemoteSource *source = userdata; int r; /* Make sure event stays around even if source is destroyed */ sd_event_source_ref(event); r = handle_raw_source(event, source->fd, EPOLLIN, server); if (r != 1) /* No more data for now */ sd_event_source_set_enabled(event, SD_EVENT_OFF); sd_event_source_unref(event); return r; } static int dispatch_raw_source_event(sd_event_source *event, int fd, uint32_t revents, void *userdata) { RemoteSource *source = userdata; int r; assert(source->event); assert(source->buffer_event); r = handle_raw_source(event, fd, EPOLLIN, server); if (r == 1) /* Might have more data. We need to rerun the handler * until we are sure the buffer is exhausted. */ sd_event_source_set_enabled(source->buffer_event, SD_EVENT_ON); return r; } static int dispatch_blocking_source_event(sd_event_source *event, void *userdata) { RemoteSource *source = userdata; return handle_raw_source(event, source->fd, EPOLLIN, server); } static int accept_connection(const char* type, int fd, SocketAddress *addr, char **hostname) { int fd2, r; log_debug("Accepting new %s connection on fd:%d", type, fd); fd2 = accept4(fd, &addr->sockaddr.sa, &addr->size, SOCK_NONBLOCK|SOCK_CLOEXEC); if (fd2 < 0) return log_error_errno(errno, "accept() on fd:%d failed: %m", fd); switch(socket_address_family(addr)) { case AF_INET: case AF_INET6: { _cleanup_free_ char *a = NULL; char *b; r = socket_address_print(addr, &a); if (r < 0) { log_error_errno(r, "socket_address_print(): %m"); close(fd2); return r; } r = socknameinfo_pretty(&addr->sockaddr, addr->size, &b); if (r < 0) { log_error_errno(r, "Resolving hostname failed: %m"); close(fd2); return r; } log_debug("Accepted %s %s connection from %s", type, socket_address_family(addr) == AF_INET ? "IP" : "IPv6", a); *hostname = b; return fd2; }; default: log_error("Rejected %s connection with unsupported family %d", type, socket_address_family(addr)); close(fd2); return -EINVAL; } } static int dispatch_raw_connection_event(sd_event_source *event, int fd, uint32_t revents, void *userdata) { RemoteServer *s = userdata; int fd2; SocketAddress addr = { .size = sizeof(union sockaddr_union), .type = SOCK_STREAM, }; char *hostname = NULL; fd2 = accept_connection("raw", fd, &addr, &hostname); if (fd2 < 0) return fd2; return add_source(s, fd2, hostname, true); } /********************************************************************** ********************************************************************** **********************************************************************/ static const char* const journal_write_split_mode_table[_JOURNAL_WRITE_SPLIT_MAX] = { [JOURNAL_WRITE_SPLIT_NONE] = "none", [JOURNAL_WRITE_SPLIT_HOST] = "host", }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP(journal_write_split_mode, JournalWriteSplitMode); static DEFINE_CONFIG_PARSE_ENUM(config_parse_write_split_mode, journal_write_split_mode, JournalWriteSplitMode, "Failed to parse split mode setting"); static int parse_config(void) { const ConfigTableItem items[] = { { "Remote", "Seal", config_parse_bool, 0, &arg_seal }, { "Remote", "SplitMode", config_parse_write_split_mode, 0, &arg_split_mode }, { "Remote", "ServerKeyFile", config_parse_path, 0, &arg_key }, { "Remote", "ServerCertificateFile", config_parse_path, 0, &arg_cert }, { "Remote", "TrustedCertificateFile", config_parse_path, 0, &arg_trust }, {}}; return config_parse_many(PKGSYSCONFDIR "/journal-remote.conf", CONF_PATHS_NULSTR("systemd/journal-remote.conf.d"), "Remote\0", config_item_table_lookup, items, false, NULL); } static void help(void) { printf("%s [OPTIONS...] {FILE|-}...\n\n" "Write external journal events to journal file(s).\n\n" " -h --help Show this help\n" " --version Show package version\n" " --url=URL Read events from systemd-journal-gatewayd at URL\n" " --getter=COMMAND Read events from the output of COMMAND\n" " --listen-raw=ADDR Listen for connections at ADDR\n" " --listen-http=ADDR Listen for HTTP connections at ADDR\n" " --listen-https=ADDR Listen for HTTPS connections at ADDR\n" " -o --output=FILE|DIR Write output to FILE or DIR/external-*.journal\n" " --compress[=BOOL] XZ-compress the output journal (default: yes)\n" " --seal[=BOOL] Use event sealing (default: no)\n" " --key=FILENAME SSL key in PEM format (default:\n" " \"" PRIV_KEY_FILE "\")\n" " --cert=FILENAME SSL certificate in PEM format (default:\n" " \"" CERT_FILE "\")\n" " --trust=FILENAME|all SSL CA certificate or disable checking (default:\n" " \"" TRUST_FILE "\")\n" " --gnutls-log=CATEGORY...\n" " Specify a list of gnutls logging categories\n" " --split-mode=none|host How many output files to create\n" "\n" "Note: file descriptors from sd_listen_fds() will be consumed, too.\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_URL, ARG_LISTEN_RAW, ARG_LISTEN_HTTP, ARG_LISTEN_HTTPS, ARG_GETTER, ARG_SPLIT_MODE, ARG_COMPRESS, ARG_SEAL, ARG_KEY, ARG_CERT, ARG_TRUST, ARG_GNUTLS_LOG, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "url", required_argument, NULL, ARG_URL }, { "getter", required_argument, NULL, ARG_GETTER }, { "listen-raw", required_argument, NULL, ARG_LISTEN_RAW }, { "listen-http", required_argument, NULL, ARG_LISTEN_HTTP }, { "listen-https", required_argument, NULL, ARG_LISTEN_HTTPS }, { "output", required_argument, NULL, 'o' }, { "split-mode", required_argument, NULL, ARG_SPLIT_MODE }, { "compress", optional_argument, NULL, ARG_COMPRESS }, { "seal", optional_argument, NULL, ARG_SEAL }, { "key", required_argument, NULL, ARG_KEY }, { "cert", required_argument, NULL, ARG_CERT }, { "trust", required_argument, NULL, ARG_TRUST }, { "gnutls-log", required_argument, NULL, ARG_GNUTLS_LOG }, {} }; int c, r; bool type_a, type_b; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "ho:", options, NULL)) >= 0) switch(c) { case 'h': help(); return 0 /* done */; case ARG_VERSION: return version(); case ARG_URL: if (arg_url) { log_error("cannot currently set more than one --url"); return -EINVAL; } arg_url = optarg; break; case ARG_GETTER: if (arg_getter) { log_error("cannot currently use --getter more than once"); return -EINVAL; } arg_getter = optarg; break; case ARG_LISTEN_RAW: if (arg_listen_raw) { log_error("cannot currently use --listen-raw more than once"); return -EINVAL; } arg_listen_raw = optarg; break; case ARG_LISTEN_HTTP: if (arg_listen_http || http_socket >= 0) { log_error("cannot currently use --listen-http more than once"); return -EINVAL; } r = negative_fd(optarg); if (r >= 0) http_socket = r; else arg_listen_http = optarg; break; case ARG_LISTEN_HTTPS: if (arg_listen_https || https_socket >= 0) { log_error("cannot currently use --listen-https more than once"); return -EINVAL; } r = negative_fd(optarg); if (r >= 0) https_socket = r; else arg_listen_https = optarg; break; case ARG_KEY: if (arg_key) { log_error("Key file specified twice"); return -EINVAL; } arg_key = strdup(optarg); if (!arg_key) return log_oom(); break; case ARG_CERT: if (arg_cert) { log_error("Certificate file specified twice"); return -EINVAL; } arg_cert = strdup(optarg); if (!arg_cert) return log_oom(); break; case ARG_TRUST: if (arg_trust || arg_trust_all) { log_error("Confusing trusted CA configuration"); return -EINVAL; } if (streq(optarg, "all")) arg_trust_all = true; else { #ifdef HAVE_GNUTLS arg_trust = strdup(optarg); if (!arg_trust) return log_oom(); #else log_error("Option --trust is not available."); return -EINVAL; #endif } break; case 'o': if (arg_output) { log_error("cannot use --output/-o more than once"); return -EINVAL; } arg_output = optarg; break; case ARG_SPLIT_MODE: arg_split_mode = journal_write_split_mode_from_string(optarg); if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID) { log_error("Invalid split mode: %s", optarg); return -EINVAL; } break; case ARG_COMPRESS: if (optarg) { r = parse_boolean(optarg); if (r < 0) { log_error("Failed to parse --compress= parameter."); return -EINVAL; } arg_compress = !!r; } else arg_compress = true; break; case ARG_SEAL: if (optarg) { r = parse_boolean(optarg); if (r < 0) { log_error("Failed to parse --seal= parameter."); return -EINVAL; } arg_seal = !!r; } else arg_seal = true; break; case ARG_GNUTLS_LOG: { #ifdef HAVE_GNUTLS const char* p = optarg; for (;;) { _cleanup_free_ char *word = NULL; r = extract_first_word(&p, &word, ",", 0); if (r < 0) return log_error_errno(r, "Failed to parse --gnutls-log= argument: %m"); if (r == 0) break; if (strv_push(&arg_gnutls_log, word) < 0) return log_oom(); word = NULL; } break; #else log_error("Option --gnutls-log is not available."); return -EINVAL; #endif } case '?': return -EINVAL; default: assert_not_reached("Unknown option code."); } if (optind < argc) arg_files = argv + optind; type_a = arg_getter || !strv_isempty(arg_files); type_b = arg_url || arg_listen_raw || arg_listen_http || arg_listen_https || sd_listen_fds(false) > 0; if (type_a && type_b) { log_error("Cannot use file input or --getter with " "--arg-listen-... or socket activation."); return -EINVAL; } if (type_a) { if (!arg_output) { log_error("Option --output must be specified with file input or --getter."); return -EINVAL; } arg_split_mode = JOURNAL_WRITE_SPLIT_NONE; } if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE && arg_output && is_dir(arg_output, true) > 0) { log_error("For SplitMode=none, output must be a file."); return -EINVAL; } if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST && arg_output && is_dir(arg_output, true) <= 0) { log_error("For SplitMode=host, output must be a directory."); return -EINVAL; } log_debug("Full config: SplitMode=%s Key=%s Cert=%s Trust=%s", journal_write_split_mode_to_string(arg_split_mode), strna(arg_key), strna(arg_cert), strna(arg_trust)); return 1 /* work to do */; } static int load_certificates(char **key, char **cert, char **trust) { int r; r = read_full_file(arg_key ?: PRIV_KEY_FILE, key, NULL); if (r < 0) return log_error_errno(r, "Failed to read key from file '%s': %m", arg_key ?: PRIV_KEY_FILE); r = read_full_file(arg_cert ?: CERT_FILE, cert, NULL); if (r < 0) return log_error_errno(r, "Failed to read certificate from file '%s': %m", arg_cert ?: CERT_FILE); if (arg_trust_all) log_info("Certificate checking disabled."); else { r = read_full_file(arg_trust ?: TRUST_FILE, trust, NULL); if (r < 0) return log_error_errno(r, "Failed to read CA certificate file '%s': %m", arg_trust ?: TRUST_FILE); } return 0; } int main(int argc, char **argv) { RemoteServer s = {}; int r; _cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL; log_show_color(true); log_parse_environment(); r = parse_config(); if (r < 0) return EXIT_FAILURE; r = parse_argv(argc, argv); if (r <= 0) return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; if (arg_listen_http || arg_listen_https) { r = setup_gnutls_logger(arg_gnutls_log); if (r < 0) return EXIT_FAILURE; } if (arg_listen_https || https_socket >= 0) if (load_certificates(&key, &cert, &trust) < 0) return EXIT_FAILURE; if (remoteserver_init(&s, key, cert, trust) < 0) return EXIT_FAILURE; r = sd_event_set_watchdog(s.events, true); if (r < 0) log_error_errno(r, "Failed to enable watchdog: %m"); else log_debug("Watchdog is %s.", r > 0 ? "enabled" : "disabled"); log_debug("%s running as pid "PID_FMT, program_invocation_short_name, getpid()); sd_notify(false, "READY=1\n" "STATUS=Processing requests..."); while (s.active) { r = sd_event_get_state(s.events); if (r < 0) break; if (r == SD_EVENT_FINISHED) break; r = sd_event_run(s.events, -1); if (r < 0) { log_error_errno(r, "Failed to run event loop: %m"); break; } } sd_notifyf(false, "STOPPING=1\n" "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count); log_info("Finishing after writing %" PRIu64 " entries", s.event_count); server_destroy(&s); free(arg_key); free(arg_cert); free(arg_trust); return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; } systemd-229/src/journal-remote/journal-remote.conf.in000066400000000000000000000003411265713322000230300ustar00rootroot00000000000000[Remote] # Seal=false # SplitMode=host # ServerKeyFile=@CERTIFICATEROOT@/private/journal-remote.pem # ServerCertificateFile=@CERTIFICATEROOT@/certs/journal-remote.pem # TrustedCertificateFile=@CERTIFICATEROOT@/ca/trusted.pem systemd-229/src/journal-remote/journal-remote.h000066400000000000000000000025741265713322000217370ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "sd-event.h" #include "hashmap.h" #include "journal-remote-parse.h" #include "journal-remote-write.h" #include "microhttpd-util.h" typedef struct MHDDaemonWrapper MHDDaemonWrapper; struct MHDDaemonWrapper { uint64_t fd; struct MHD_Daemon *daemon; sd_event_source *event; }; struct RemoteServer { RemoteSource **sources; size_t sources_size; size_t active; sd_event *events; sd_event_source *sigterm_event, *sigint_event, *listen_event; Hashmap *writers; Writer *_single_writer; uint64_t event_count; bool check_trust; Hashmap *daemons; }; systemd-229/src/journal-remote/journal-upload-journal.c000066400000000000000000000336321265713322000233720ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "journal-upload.h" #include "log.h" #include "utf8.h" #include "util.h" /** * Write up to size bytes to buf. Return negative on error, and number of * bytes written otherwise. The last case is a kind of an error too. */ static ssize_t write_entry(char *buf, size_t size, Uploader *u) { int r; size_t pos = 0; assert(size <= SSIZE_MAX); for (;;) { switch(u->entry_state) { case ENTRY_CURSOR: { u->current_cursor = mfree(u->current_cursor); r = sd_journal_get_cursor(u->journal, &u->current_cursor); if (r < 0) return log_error_errno(r, "Failed to get cursor: %m"); r = snprintf(buf + pos, size - pos, "__CURSOR=%s\n", u->current_cursor); if (pos + r > size) /* not enough space */ return pos; u->entry_state ++; if (pos + r == size) { /* exactly one character short, but we don't need it */ buf[size - 1] = '\n'; return size; } pos += r; } /* fall through */ case ENTRY_REALTIME: { usec_t realtime; r = sd_journal_get_realtime_usec(u->journal, &realtime); if (r < 0) return log_error_errno(r, "Failed to get realtime timestamp: %m"); r = snprintf(buf + pos, size - pos, "__REALTIME_TIMESTAMP="USEC_FMT"\n", realtime); if (r + pos > size) /* not enough space */ return pos; u->entry_state ++; if (r + pos == size) { /* exactly one character short, but we don't need it */ buf[size - 1] = '\n'; return size; } pos += r; } /* fall through */ case ENTRY_MONOTONIC: { usec_t monotonic; sd_id128_t boot_id; r = sd_journal_get_monotonic_usec(u->journal, &monotonic, &boot_id); if (r < 0) return log_error_errno(r, "Failed to get monotonic timestamp: %m"); r = snprintf(buf + pos, size - pos, "__MONOTONIC_TIMESTAMP="USEC_FMT"\n", monotonic); if (r + pos > size) /* not enough space */ return pos; u->entry_state ++; if (r + pos == size) { /* exactly one character short, but we don't need it */ buf[size - 1] = '\n'; return size; } pos += r; } /* fall through */ case ENTRY_BOOT_ID: { sd_id128_t boot_id; char sid[33]; r = sd_journal_get_monotonic_usec(u->journal, NULL, &boot_id); if (r < 0) return log_error_errno(r, "Failed to get monotonic timestamp: %m"); r = snprintf(buf + pos, size - pos, "_BOOT_ID=%s\n", sd_id128_to_string(boot_id, sid)); if (r + pos > size) /* not enough space */ return pos; u->entry_state ++; if (r + pos == size) { /* exactly one character short, but we don't need it */ buf[size - 1] = '\n'; return size; } pos += r; } /* fall through */ case ENTRY_NEW_FIELD: { u->field_pos = 0; r = sd_journal_enumerate_data(u->journal, &u->field_data, &u->field_length); if (r < 0) return log_error_errno(r, "Failed to move to next field in entry: %m"); else if (r == 0) { u->entry_state = ENTRY_OUTRO; continue; } if (!utf8_is_printable_newline(u->field_data, u->field_length, false)) { u->entry_state = ENTRY_BINARY_FIELD_START; continue; } u->entry_state ++; } /* fall through */ case ENTRY_TEXT_FIELD: case ENTRY_BINARY_FIELD: { bool done; size_t tocopy; done = size - pos > u->field_length - u->field_pos; if (done) tocopy = u->field_length - u->field_pos; else tocopy = size - pos; memcpy(buf + pos, (char*) u->field_data + u->field_pos, tocopy); if (done) { buf[pos + tocopy] = '\n'; pos += tocopy + 1; u->entry_state = ENTRY_NEW_FIELD; continue; } else { u->field_pos += tocopy; return size; } } case ENTRY_BINARY_FIELD_START: { const char *c; size_t len; c = memchr(u->field_data, '=', u->field_length); if (!c || c == u->field_data) { log_error("Invalid field."); return -EINVAL; } len = c - (const char*)u->field_data; /* need space for label + '\n' */ if (size - pos < len + 1) return pos; memcpy(buf + pos, u->field_data, len); buf[pos + len] = '\n'; pos += len + 1; u->field_pos = len + 1; u->entry_state ++; } /* fall through */ case ENTRY_BINARY_FIELD_SIZE: { uint64_t le64; /* need space for uint64_t */ if (size - pos < 8) return pos; le64 = htole64(u->field_length - u->field_pos); memcpy(buf + pos, &le64, 8); pos += 8; u->entry_state ++; continue; } case ENTRY_OUTRO: /* need space for '\n' */ if (size - pos < 1) return pos; buf[pos++] = '\n'; u->entry_state ++; u->entries_sent ++; return pos; default: assert_not_reached("WTF?"); } } assert_not_reached("WTF?"); } static size_t journal_input_callback(void *buf, size_t size, size_t nmemb, void *userp) { Uploader *u = userp; int r; sd_journal *j; size_t filled = 0; ssize_t w; assert(u); assert(nmemb <= SSIZE_MAX / size); j = u->journal; while (j && filled < size * nmemb) { if (u->entry_state == ENTRY_DONE) { r = sd_journal_next(j); if (r < 0) { log_error_errno(r, "Failed to move to next entry in journal: %m"); return CURL_READFUNC_ABORT; } else if (r == 0) { if (u->input_event) log_debug("No more entries, waiting for journal."); else { log_info("No more entries, closing journal."); close_journal_input(u); } u->uploading = false; break; } u->entry_state = ENTRY_CURSOR; } w = write_entry((char*)buf + filled, size * nmemb - filled, u); if (w < 0) return CURL_READFUNC_ABORT; filled += w; if (filled == 0) { log_error("Buffer space is too small to write entry."); return CURL_READFUNC_ABORT; } else if (u->entry_state != ENTRY_DONE) /* This means that all available space was used up */ break; log_debug("Entry %zu (%s) has been uploaded.", u->entries_sent, u->current_cursor); } return filled; } void close_journal_input(Uploader *u) { assert(u); if (u->journal) { log_debug("Closing journal input."); sd_journal_close(u->journal); u->journal = NULL; } u->timeout = 0; } static int process_journal_input(Uploader *u, int skip) { int r; if (u->uploading) return 0; r = sd_journal_next_skip(u->journal, skip); if (r < 0) return log_error_errno(r, "Failed to skip to next entry: %m"); else if (r < skip) return 0; /* have data */ u->entry_state = ENTRY_CURSOR; return start_upload(u, journal_input_callback, u); } int check_journal_input(Uploader *u) { if (u->input_event) { int r; r = sd_journal_process(u->journal); if (r < 0) { log_error_errno(r, "Failed to process journal: %m"); close_journal_input(u); return r; } if (r == SD_JOURNAL_NOP) return 0; } return process_journal_input(u, 1); } static int dispatch_journal_input(sd_event_source *event, int fd, uint32_t revents, void *userp) { Uploader *u = userp; assert(u); if (u->uploading) return 0; log_debug("Detected journal input, checking for new data."); return check_journal_input(u); } int open_journal_for_upload(Uploader *u, sd_journal *j, const char *cursor, bool after_cursor, bool follow) { int fd, r, events; u->journal = j; sd_journal_set_data_threshold(j, 0); if (follow) { fd = sd_journal_get_fd(j); if (fd < 0) return log_error_errno(fd, "sd_journal_get_fd failed: %m"); events = sd_journal_get_events(j); r = sd_journal_reliable_fd(j); assert(r >= 0); if (r > 0) u->timeout = -1; else u->timeout = JOURNAL_UPLOAD_POLL_TIMEOUT; r = sd_event_add_io(u->events, &u->input_event, fd, events, dispatch_journal_input, u); if (r < 0) return log_error_errno(r, "Failed to register input event: %m"); log_debug("Listening for journal events on fd:%d, timeout %d", fd, u->timeout == (uint64_t) -1 ? -1 : (int) u->timeout); } else log_debug("Not listening for journal events."); if (cursor) { r = sd_journal_seek_cursor(j, cursor); if (r < 0) return log_error_errno(r, "Failed to seek to cursor %s: %m", cursor); } return process_journal_input(u, 1 + !!after_cursor); } systemd-229/src/journal-remote/journal-upload.c000066400000000000000000000711571265713322000217260ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-daemon.h" #include "alloc-util.h" #include "conf-parser.h" #include "def.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "glob-util.h" #include "journal-upload.h" #include "log.h" #include "mkdir.h" #include "parse-util.h" #include "sigbus.h" #include "signal-util.h" #include "string-util.h" #include "util.h" #define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-upload.pem" #define CERT_FILE CERTIFICATE_ROOT "/certs/journal-upload.pem" #define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem" #define DEFAULT_PORT 19532 static const char* arg_url = NULL; static const char *arg_key = NULL; static const char *arg_cert = NULL; static const char *arg_trust = NULL; static const char *arg_directory = NULL; static char **arg_file = NULL; static const char *arg_cursor = NULL; static bool arg_after_cursor = false; static int arg_journal_type = 0; static const char *arg_machine = NULL; static bool arg_merge = false; static int arg_follow = -1; static const char *arg_save_state = NULL; static void close_fd_input(Uploader *u); #define SERVER_ANSWER_KEEP 2048 #define STATE_FILE "/var/lib/systemd/journal-upload/state" #define easy_setopt(curl, opt, value, level, cmd) \ do { \ code = curl_easy_setopt(curl, opt, value); \ if (code) { \ log_full(level, \ "curl_easy_setopt " #opt " failed: %s", \ curl_easy_strerror(code)); \ cmd; \ } \ } while(0) static size_t output_callback(char *buf, size_t size, size_t nmemb, void *userp) { Uploader *u = userp; assert(u); log_debug("The server answers (%zu bytes): %.*s", size*nmemb, (int)(size*nmemb), buf); if (nmemb && !u->answer) { u->answer = strndup(buf, size*nmemb); if (!u->answer) log_warning_errno(ENOMEM, "Failed to store server answer (%zu bytes): %m", size*nmemb); } return size * nmemb; } static int check_cursor_updating(Uploader *u) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; int r; if (!u->state_file) return 0; r = mkdir_parents(u->state_file, 0755); if (r < 0) return log_error_errno(r, "Cannot create parent directory of state file %s: %m", u->state_file); r = fopen_temporary(u->state_file, &f, &temp_path); if (r < 0) return log_error_errno(r, "Cannot save state to %s: %m", u->state_file); unlink(temp_path); return 0; } static int update_cursor_state(Uploader *u) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; int r; if (!u->state_file || !u->last_cursor) return 0; r = fopen_temporary(u->state_file, &f, &temp_path); if (r < 0) goto fail; fprintf(f, "# This is private data. Do not parse.\n" "LAST_CURSOR=%s\n", u->last_cursor); r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, u->state_file) < 0) { r = -errno; goto fail; } return 0; fail: if (temp_path) (void) unlink(temp_path); (void) unlink(u->state_file); return log_error_errno(r, "Failed to save state %s: %m", u->state_file); } static int load_cursor_state(Uploader *u) { int r; if (!u->state_file) return 0; r = parse_env_file(u->state_file, NEWLINE, "LAST_CURSOR", &u->last_cursor, NULL); if (r == -ENOENT) log_debug("State file %s is not present.", u->state_file); else if (r < 0) return log_error_errno(r, "Failed to read state file %s: %m", u->state_file); else log_debug("Last cursor was %s", u->last_cursor); return 0; } int start_upload(Uploader *u, size_t (*input_callback)(void *ptr, size_t size, size_t nmemb, void *userdata), void *data) { CURLcode code; assert(u); assert(input_callback); if (!u->header) { struct curl_slist *h; h = curl_slist_append(NULL, "Content-Type: application/vnd.fdo.journal"); if (!h) return log_oom(); h = curl_slist_append(h, "Transfer-Encoding: chunked"); if (!h) { curl_slist_free_all(h); return log_oom(); } h = curl_slist_append(h, "Accept: text/plain"); if (!h) { curl_slist_free_all(h); return log_oom(); } u->header = h; } if (!u->easy) { CURL *curl; curl = curl_easy_init(); if (!curl) { log_error("Call to curl_easy_init failed."); return -ENOSR; } /* tell it to POST to the URL */ easy_setopt(curl, CURLOPT_POST, 1L, LOG_ERR, return -EXFULL); easy_setopt(curl, CURLOPT_ERRORBUFFER, u->error, LOG_ERR, return -EXFULL); /* set where to write to */ easy_setopt(curl, CURLOPT_WRITEFUNCTION, output_callback, LOG_ERR, return -EXFULL); easy_setopt(curl, CURLOPT_WRITEDATA, data, LOG_ERR, return -EXFULL); /* set where to read from */ easy_setopt(curl, CURLOPT_READFUNCTION, input_callback, LOG_ERR, return -EXFULL); easy_setopt(curl, CURLOPT_READDATA, data, LOG_ERR, return -EXFULL); /* use our special own mime type and chunked transfer */ easy_setopt(curl, CURLOPT_HTTPHEADER, u->header, LOG_ERR, return -EXFULL); if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) /* enable verbose for easier tracing */ easy_setopt(curl, CURLOPT_VERBOSE, 1L, LOG_WARNING, ); easy_setopt(curl, CURLOPT_USERAGENT, "systemd-journal-upload " PACKAGE_STRING, LOG_WARNING, ); if (arg_key || startswith(u->url, "https://")) { easy_setopt(curl, CURLOPT_SSLKEY, arg_key ?: PRIV_KEY_FILE, LOG_ERR, return -EXFULL); easy_setopt(curl, CURLOPT_SSLCERT, arg_cert ?: CERT_FILE, LOG_ERR, return -EXFULL); } if (streq_ptr(arg_trust, "all")) easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0, LOG_ERR, return -EUCLEAN); else if (arg_trust || startswith(u->url, "https://")) easy_setopt(curl, CURLOPT_CAINFO, arg_trust ?: TRUST_FILE, LOG_ERR, return -EXFULL); if (arg_key || arg_trust) easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1, LOG_WARNING, ); u->easy = curl; } else { /* truncate the potential old error message */ u->error[0] = '\0'; free(u->answer); u->answer = 0; } /* upload to this place */ code = curl_easy_setopt(u->easy, CURLOPT_URL, u->url); if (code) { log_error("curl_easy_setopt CURLOPT_URL failed: %s", curl_easy_strerror(code)); return -EXFULL; } u->uploading = true; return 0; } static size_t fd_input_callback(void *buf, size_t size, size_t nmemb, void *userp) { Uploader *u = userp; ssize_t r; assert(u); assert(nmemb <= SSIZE_MAX / size); if (u->input < 0) return 0; r = read(u->input, buf, size * nmemb); log_debug("%s: allowed %zu, read %zd", __func__, size*nmemb, r); if (r > 0) return r; u->uploading = false; if (r == 0) { log_debug("Reached EOF"); close_fd_input(u); return 0; } else { log_error_errno(errno, "Aborting transfer after read error on input: %m."); return CURL_READFUNC_ABORT; } } static void close_fd_input(Uploader *u) { assert(u); if (u->input >= 0) close_nointr(u->input); u->input = -1; u->timeout = 0; } static int dispatch_fd_input(sd_event_source *event, int fd, uint32_t revents, void *userp) { Uploader *u = userp; assert(u); assert(fd >= 0); if (revents & EPOLLHUP) { log_debug("Received HUP"); close_fd_input(u); return 0; } if (!(revents & EPOLLIN)) { log_warning("Unexpected poll event %"PRIu32".", revents); return -EINVAL; } if (u->uploading) { log_warning("dispatch_fd_input called when uploading, ignoring."); return 0; } return start_upload(u, fd_input_callback, u); } static int open_file_for_upload(Uploader *u, const char *filename) { int fd, r = 0; if (streq(filename, "-")) fd = STDIN_FILENO; else { fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return log_error_errno(errno, "Failed to open %s: %m", filename); } u->input = fd; if (arg_follow) { r = sd_event_add_io(u->events, &u->input_event, fd, EPOLLIN, dispatch_fd_input, u); if (r < 0) { if (r != -EPERM || arg_follow > 0) return log_error_errno(r, "Failed to register input event: %m"); /* Normal files should just be consumed without polling. */ r = start_upload(u, fd_input_callback, u); } } return r; } static int dispatch_sigterm(sd_event_source *event, const struct signalfd_siginfo *si, void *userdata) { Uploader *u = userdata; assert(u); log_received_signal(LOG_INFO, si); close_fd_input(u); close_journal_input(u); sd_event_exit(u->events, 0); return 0; } static int setup_signals(Uploader *u) { int r; assert(u); assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, -1) >= 0); r = sd_event_add_signal(u->events, &u->sigterm_event, SIGTERM, dispatch_sigterm, u); if (r < 0) return r; r = sd_event_add_signal(u->events, &u->sigint_event, SIGINT, dispatch_sigterm, u); if (r < 0) return r; return 0; } static int setup_uploader(Uploader *u, const char *url, const char *state_file) { int r; const char *host, *proto = ""; assert(u); assert(url); memzero(u, sizeof(Uploader)); u->input = -1; if (!(host = startswith(url, "http://")) && !(host = startswith(url, "https://"))) { host = url; proto = "https://"; } if (strchr(host, ':')) u->url = strjoin(proto, url, "/upload", NULL); else { char *t; size_t x; t = strdupa(url); x = strlen(t); while (x > 0 && t[x - 1] == '/') t[x - 1] = '\0'; u->url = strjoin(proto, t, ":" STRINGIFY(DEFAULT_PORT), "/upload", NULL); } if (!u->url) return log_oom(); u->state_file = state_file; r = sd_event_default(&u->events); if (r < 0) return log_error_errno(r, "sd_event_default failed: %m"); r = setup_signals(u); if (r < 0) return log_error_errno(r, "Failed to set up signals: %m"); return load_cursor_state(u); } static void destroy_uploader(Uploader *u) { assert(u); curl_easy_cleanup(u->easy); curl_slist_free_all(u->header); free(u->answer); free(u->last_cursor); free(u->current_cursor); free(u->url); u->input_event = sd_event_source_unref(u->input_event); close_fd_input(u); close_journal_input(u); sd_event_source_unref(u->sigterm_event); sd_event_source_unref(u->sigint_event); sd_event_unref(u->events); } static int perform_upload(Uploader *u) { CURLcode code; long status; assert(u); code = curl_easy_perform(u->easy); if (code) { if (u->error[0]) log_error("Upload to %s failed: %.*s", u->url, (int) sizeof(u->error), u->error); else log_error("Upload to %s failed: %s", u->url, curl_easy_strerror(code)); return -EIO; } code = curl_easy_getinfo(u->easy, CURLINFO_RESPONSE_CODE, &status); if (code) { log_error("Failed to retrieve response code: %s", curl_easy_strerror(code)); return -EUCLEAN; } if (status >= 300) { log_error("Upload to %s failed with code %ld: %s", u->url, status, strna(u->answer)); return -EIO; } else if (status < 200) { log_error("Upload to %s finished with unexpected code %ld: %s", u->url, status, strna(u->answer)); return -EIO; } else log_debug("Upload finished successfully with code %ld: %s", status, strna(u->answer)); free(u->last_cursor); u->last_cursor = u->current_cursor; u->current_cursor = NULL; return update_cursor_state(u); } static int parse_config(void) { const ConfigTableItem items[] = { { "Upload", "URL", config_parse_string, 0, &arg_url }, { "Upload", "ServerKeyFile", config_parse_path, 0, &arg_key }, { "Upload", "ServerCertificateFile", config_parse_path, 0, &arg_cert }, { "Upload", "TrustedCertificateFile", config_parse_path, 0, &arg_trust }, {}}; return config_parse_many(PKGSYSCONFDIR "/journal-upload.conf", CONF_PATHS_NULSTR("systemd/journal-upload.conf.d"), "Upload\0", config_item_table_lookup, items, false, NULL); } static void help(void) { printf("%s -u URL {FILE|-}...\n\n" "Upload journal events to a remote server.\n\n" " -h --help Show this help\n" " --version Show package version\n" " -u --url=URL Upload to this address (default port " STRINGIFY(DEFAULT_PORT) ")\n" " --key=FILENAME Specify key in PEM format (default:\n" " \"" PRIV_KEY_FILE "\")\n" " --cert=FILENAME Specify certificate in PEM format (default:\n" " \"" CERT_FILE "\")\n" " --trust=FILENAME|all Specify CA certificate or disable checking (default:\n" " \"" TRUST_FILE "\")\n" " --system Use the system journal\n" " --user Use the user journal for the current user\n" " -m --merge Use all available journals\n" " -M --machine=CONTAINER Operate on local container\n" " -D --directory=PATH Use journal files from directory\n" " --file=PATH Use this journal file\n" " --cursor=CURSOR Start at the specified cursor\n" " --after-cursor=CURSOR Start after the specified cursor\n" " --follow[=BOOL] Do [not] wait for input\n" " --save-state[=FILE] Save uploaded cursors (default \n" " " STATE_FILE ")\n" " -h --help Show this help and exit\n" " --version Print version string and exit\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_KEY, ARG_CERT, ARG_TRUST, ARG_USER, ARG_SYSTEM, ARG_FILE, ARG_CURSOR, ARG_AFTER_CURSOR, ARG_FOLLOW, ARG_SAVE_STATE, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "url", required_argument, NULL, 'u' }, { "key", required_argument, NULL, ARG_KEY }, { "cert", required_argument, NULL, ARG_CERT }, { "trust", required_argument, NULL, ARG_TRUST }, { "system", no_argument, NULL, ARG_SYSTEM }, { "user", no_argument, NULL, ARG_USER }, { "merge", no_argument, NULL, 'm' }, { "machine", required_argument, NULL, 'M' }, { "directory", required_argument, NULL, 'D' }, { "file", required_argument, NULL, ARG_FILE }, { "cursor", required_argument, NULL, ARG_CURSOR }, { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR }, { "follow", optional_argument, NULL, ARG_FOLLOW }, { "save-state", optional_argument, NULL, ARG_SAVE_STATE }, {} }; int c, r; assert(argc >= 0); assert(argv); opterr = 0; while ((c = getopt_long(argc, argv, "hu:mM:D:", options, NULL)) >= 0) switch(c) { case 'h': help(); return 0 /* done */; case ARG_VERSION: return version(); case 'u': if (arg_url) { log_error("cannot use more than one --url"); return -EINVAL; } arg_url = optarg; break; case ARG_KEY: if (arg_key) { log_error("cannot use more than one --key"); return -EINVAL; } arg_key = optarg; break; case ARG_CERT: if (arg_cert) { log_error("cannot use more than one --cert"); return -EINVAL; } arg_cert = optarg; break; case ARG_TRUST: if (arg_trust) { log_error("cannot use more than one --trust"); return -EINVAL; } arg_trust = optarg; break; case ARG_SYSTEM: arg_journal_type |= SD_JOURNAL_SYSTEM; break; case ARG_USER: arg_journal_type |= SD_JOURNAL_CURRENT_USER; break; case 'm': arg_merge = true; break; case 'M': if (arg_machine) { log_error("cannot use more than one --machine/-M"); return -EINVAL; } arg_machine = optarg; break; case 'D': if (arg_directory) { log_error("cannot use more than one --directory/-D"); return -EINVAL; } arg_directory = optarg; break; case ARG_FILE: r = glob_extend(&arg_file, optarg); if (r < 0) return log_error_errno(r, "Failed to add paths: %m"); break; case ARG_CURSOR: if (arg_cursor) { log_error("cannot use more than one --cursor/--after-cursor"); return -EINVAL; } arg_cursor = optarg; break; case ARG_AFTER_CURSOR: if (arg_cursor) { log_error("cannot use more than one --cursor/--after-cursor"); return -EINVAL; } arg_cursor = optarg; arg_after_cursor = true; break; case ARG_FOLLOW: if (optarg) { r = parse_boolean(optarg); if (r < 0) { log_error("Failed to parse --follow= parameter."); return -EINVAL; } arg_follow = !!r; } else arg_follow = true; break; case ARG_SAVE_STATE: arg_save_state = optarg ?: STATE_FILE; break; case '?': log_error("Unknown option %s.", argv[optind-1]); return -EINVAL; case ':': log_error("Missing argument to %s.", argv[optind-1]); return -EINVAL; default: assert_not_reached("Unhandled option code."); } if (!arg_url) { log_error("Required --url/-u option missing."); return -EINVAL; } if (!!arg_key != !!arg_cert) { log_error("Options --key and --cert must be used together."); return -EINVAL; } if (optind < argc && (arg_directory || arg_file || arg_machine || arg_journal_type)) { log_error("Input arguments make no sense with journal input."); return -EINVAL; } return 1; } static int open_journal(sd_journal **j) { int r; if (arg_directory) r = sd_journal_open_directory(j, arg_directory, arg_journal_type); else if (arg_file) r = sd_journal_open_files(j, (const char**) arg_file, 0); else if (arg_machine) r = sd_journal_open_container(j, arg_machine, 0); else r = sd_journal_open(j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type); if (r < 0) log_error_errno(r, "Failed to open %s: %m", arg_directory ? arg_directory : arg_file ? "files" : "journal"); return r; } int main(int argc, char **argv) { Uploader u; int r; bool use_journal; log_show_color(true); log_parse_environment(); r = parse_config(); if (r < 0) goto finish; r = parse_argv(argc, argv); if (r <= 0) goto finish; sigbus_install(); r = setup_uploader(&u, arg_url, arg_save_state); if (r < 0) goto cleanup; sd_event_set_watchdog(u.events, true); r = check_cursor_updating(&u); if (r < 0) goto cleanup; log_debug("%s running as pid "PID_FMT, program_invocation_short_name, getpid()); use_journal = optind >= argc; if (use_journal) { sd_journal *j; r = open_journal(&j); if (r < 0) goto finish; r = open_journal_for_upload(&u, j, arg_cursor ?: u.last_cursor, arg_cursor ? arg_after_cursor : true, !!arg_follow); if (r < 0) goto finish; } sd_notify(false, "READY=1\n" "STATUS=Processing input..."); for (;;) { r = sd_event_get_state(u.events); if (r < 0) break; if (r == SD_EVENT_FINISHED) break; if (use_journal) { if (!u.journal) break; r = check_journal_input(&u); } else if (u.input < 0 && !use_journal) { if (optind >= argc) break; log_debug("Using %s as input.", argv[optind]); r = open_file_for_upload(&u, argv[optind++]); } if (r < 0) goto cleanup; if (u.uploading) { r = perform_upload(&u); if (r < 0) break; } r = sd_event_run(u.events, u.timeout); if (r < 0) { log_error_errno(r, "Failed to run event loop: %m"); break; } } cleanup: sd_notify(false, "STOPPING=1\n" "STATUS=Shutting down..."); destroy_uploader(&u); finish: return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; } systemd-229/src/journal-remote/journal-upload.conf.in000066400000000000000000000003121265713322000230170ustar00rootroot00000000000000[Upload] # URL= # ServerKeyFile=@CERTIFICATEROOT@/private/journal-upload.pem # ServerCertificateFile=@CERTIFICATEROOT@/certs/journal-upload.pem # TrustedCertificateFile=@CERTIFICATEROOT@/ca/trusted.pem systemd-229/src/journal-remote/journal-upload.h000066400000000000000000000040341265713322000217210ustar00rootroot00000000000000#pragma once #include #include "sd-event.h" #include "sd-journal.h" typedef enum { ENTRY_CURSOR = 0, /* Nothing actually written yet. */ ENTRY_REALTIME, ENTRY_MONOTONIC, ENTRY_BOOT_ID, ENTRY_NEW_FIELD, /* In between fields. */ ENTRY_TEXT_FIELD, /* In the middle of a text field. */ ENTRY_BINARY_FIELD_START, /* Writing the name of a binary field. */ ENTRY_BINARY_FIELD_SIZE, /* Writing the size of a binary field. */ ENTRY_BINARY_FIELD, /* In the middle of a binary field. */ ENTRY_OUTRO, /* Writing '\n' */ ENTRY_DONE, /* Need to move to a new field. */ } entry_state; typedef struct Uploader { sd_event *events; sd_event_source *sigint_event, *sigterm_event; char *url; CURL *easy; bool uploading; char error[CURL_ERROR_SIZE]; struct curl_slist *header; char *answer; sd_event_source *input_event; uint64_t timeout; /* fd stuff */ int input; /* journal stuff */ sd_journal* journal; entry_state entry_state; const void *field_data; size_t field_pos, field_length; /* general metrics */ const char *state_file; size_t entries_sent; char *last_cursor, *current_cursor; } Uploader; #define JOURNAL_UPLOAD_POLL_TIMEOUT (10 * USEC_PER_SEC) int start_upload(Uploader *u, size_t (*input_callback)(void *ptr, size_t size, size_t nmemb, void *userdata), void *data); int open_journal_for_upload(Uploader *u, sd_journal *j, const char *cursor, bool after_cursor, bool follow); void close_journal_input(Uploader *u); int check_journal_input(Uploader *u); systemd-229/src/journal-remote/log-generator.py000077500000000000000000000040561265713322000217420ustar00rootroot00000000000000#!/usr/bin/python from __future__ import print_function import sys import argparse PARSER = argparse.ArgumentParser() PARSER.add_argument('n', type=int) PARSER.add_argument('--dots', action='store_true') PARSER.add_argument('--data-size', type=int, default=4000) PARSER.add_argument('--data-type', choices={'random', 'simple'}) OPTIONS = PARSER.parse_args() template = """\ __CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m={m:x};t=4fd05c __REALTIME_TIMESTAMP={realtime_ts} __MONOTONIC_TIMESTAMP={monotonic_ts} _BOOT_ID=f446871715504074bf7049ef0718fa93 _TRANSPORT=syslog PRIORITY={priority} SYSLOG_FACILITY={facility} SYSLOG_IDENTIFIER=/USR/SBIN/CRON MESSAGE={message} _UID=0 _GID=0 _MACHINE_ID=69121ca41d12c1b69a7960174c27b618 _HOSTNAME=hostname SYSLOG_PID=25721 _PID=25721 _SOURCE_REALTIME_TIMESTAMP={source_realtime_ts} DATA={data} """ m = 0x198603b12d7 realtime_ts = 1404101101501873 monotonic_ts = 1753961140951 source_realtime_ts = 1404101101483516 priority = 3 facility = 6 src = open('/dev/urandom', 'rb') bytes = 0 counter = 0 for i in range(OPTIONS.n): message = repr(src.read(2000)) if OPTIONS.data_type == 'random': data = repr(src.read(OPTIONS.data_size)) else: # keep the pattern non-repeating so we get a different blob every time data = '{:0{}}'.format(counter, OPTIONS.data_size) counter += 1 entry = template.format(m=m, realtime_ts=realtime_ts, monotonic_ts=monotonic_ts, source_realtime_ts=source_realtime_ts, priority=priority, facility=facility, message=message, data=data) m += 1 realtime_ts += 1 monotonic_ts += 1 source_realtime_ts += 1 bytes += len(entry) print(entry) if OPTIONS.dots: print('.', file=sys.stderr, end='', flush=True) if OPTIONS.dots: print(file=sys.stderr) print('Wrote {} bytes'.format(bytes), file=sys.stderr) systemd-229/src/journal-remote/microhttpd-util.c000066400000000000000000000244131265713322000221130ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering Copyright 2012 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #ifdef HAVE_GNUTLS #include #include #endif #include "alloc-util.h" #include "log.h" #include "macro.h" #include "microhttpd-util.h" #include "string-util.h" #include "strv.h" #include "util.h" void microhttpd_logger(void *arg, const char *fmt, va_list ap) { char *f; f = strjoina("microhttpd: ", fmt); DISABLE_WARNING_FORMAT_NONLITERAL; log_internalv(LOG_INFO, 0, NULL, 0, NULL, f, ap); REENABLE_WARNING; } static int mhd_respond_internal(struct MHD_Connection *connection, enum MHD_RequestTerminationCode code, char *buffer, size_t size, enum MHD_ResponseMemoryMode mode) { struct MHD_Response *response; int r; assert(connection); response = MHD_create_response_from_buffer(size, buffer, mode); if (!response) return MHD_NO; log_debug("Queing response %u: %s", code, buffer); MHD_add_response_header(response, "Content-Type", "text/plain"); r = MHD_queue_response(connection, code, response); MHD_destroy_response(response); return r; } int mhd_respond(struct MHD_Connection *connection, enum MHD_RequestTerminationCode code, const char *message) { return mhd_respond_internal(connection, code, (char*) message, strlen(message), MHD_RESPMEM_PERSISTENT); } int mhd_respond_oom(struct MHD_Connection *connection) { return mhd_respond(connection, MHD_HTTP_SERVICE_UNAVAILABLE, "Out of memory.\n"); } int mhd_respondf(struct MHD_Connection *connection, enum MHD_RequestTerminationCode code, const char *format, ...) { char *m; int r; va_list ap; assert(connection); assert(format); va_start(ap, format); r = vasprintf(&m, format, ap); va_end(ap); if (r < 0) return respond_oom(connection); return mhd_respond_internal(connection, code, m, r, MHD_RESPMEM_MUST_FREE); } #ifdef HAVE_GNUTLS static struct { const char *const names[4]; int level; bool enabled; } gnutls_log_map[] = { { {"0"}, LOG_DEBUG }, { {"1", "audit"}, LOG_WARNING, true}, /* gnutls session audit */ { {"2", "assert"}, LOG_DEBUG }, /* gnutls assert log */ { {"3", "hsk", "ext"}, LOG_DEBUG }, /* gnutls handshake log */ { {"4", "rec"}, LOG_DEBUG }, /* gnutls record log */ { {"5", "dtls"}, LOG_DEBUG }, /* gnutls DTLS log */ { {"6", "buf"}, LOG_DEBUG }, { {"7", "write", "read"}, LOG_DEBUG }, { {"8"}, LOG_DEBUG }, { {"9", "enc", "int"}, LOG_DEBUG }, }; static void log_func_gnutls(int level, const char *message) { assert_se(message); if (0 <= level && level < (int) ELEMENTSOF(gnutls_log_map)) { if (gnutls_log_map[level].enabled) log_internal(gnutls_log_map[level].level, 0, NULL, 0, NULL, "gnutls %d/%s: %s", level, gnutls_log_map[level].names[1], message); } else { log_debug("Received GNUTLS message with unknown level %d.", level); log_internal(LOG_DEBUG, 0, NULL, 0, NULL, "gnutls: %s", message); } } static void log_reset_gnutls_level(void) { int i; for (i = ELEMENTSOF(gnutls_log_map) - 1; i >= 0; i--) if (gnutls_log_map[i].enabled) { log_debug("Setting gnutls log level to %d", i); gnutls_global_set_log_level(i); break; } } static int log_enable_gnutls_category(const char *cat) { unsigned i; if (streq(cat, "all")) { for (i = 0; i < ELEMENTSOF(gnutls_log_map); i++) gnutls_log_map[i].enabled = true; log_reset_gnutls_level(); return 0; } else for (i = 0; i < ELEMENTSOF(gnutls_log_map); i++) if (strv_contains((char**)gnutls_log_map[i].names, cat)) { gnutls_log_map[i].enabled = true; log_reset_gnutls_level(); return 0; } log_error("No such log category: %s", cat); return -EINVAL; } int setup_gnutls_logger(char **categories) { char **cat; int r; gnutls_global_set_log_function(log_func_gnutls); if (categories) { STRV_FOREACH(cat, categories) { r = log_enable_gnutls_category(*cat); if (r < 0) return r; } } else log_reset_gnutls_level(); return 0; } static int verify_cert_authorized(gnutls_session_t session) { unsigned status; gnutls_certificate_type_t type; gnutls_datum_t out; int r; r = gnutls_certificate_verify_peers2(session, &status); if (r < 0) return log_error_errno(r, "gnutls_certificate_verify_peers2 failed: %m"); type = gnutls_certificate_type_get(session); r = gnutls_certificate_verification_status_print(status, type, &out, 0); if (r < 0) return log_error_errno(r, "gnutls_certificate_verification_status_print failed: %m"); log_debug("Certificate status: %s", out.data); gnutls_free(out.data); return status == 0 ? 0 : -EPERM; } static int get_client_cert(gnutls_session_t session, gnutls_x509_crt_t *client_cert) { const gnutls_datum_t *pcert; unsigned listsize; gnutls_x509_crt_t cert; int r; assert(session); assert(client_cert); pcert = gnutls_certificate_get_peers(session, &listsize); if (!pcert || !listsize) { log_error("Failed to retrieve certificate chain"); return -EINVAL; } r = gnutls_x509_crt_init(&cert); if (r < 0) { log_error("Failed to initialize client certificate"); return r; } /* Note that by passing values between 0 and listsize here, you can get access to the CA's certs */ r = gnutls_x509_crt_import(cert, &pcert[0], GNUTLS_X509_FMT_DER); if (r < 0) { log_error("Failed to import client certificate"); gnutls_x509_crt_deinit(cert); return r; } *client_cert = cert; return 0; } static int get_auth_dn(gnutls_x509_crt_t client_cert, char **buf) { size_t len = 0; int r; assert(buf); assert(*buf == NULL); r = gnutls_x509_crt_get_dn(client_cert, NULL, &len); if (r != GNUTLS_E_SHORT_MEMORY_BUFFER) { log_error("gnutls_x509_crt_get_dn failed"); return r; } *buf = malloc(len); if (!*buf) return log_oom(); gnutls_x509_crt_get_dn(client_cert, *buf, &len); return 0; } static inline void gnutls_x509_crt_deinitp(gnutls_x509_crt_t *p) { gnutls_x509_crt_deinit(*p); } int check_permissions(struct MHD_Connection *connection, int *code, char **hostname) { const union MHD_ConnectionInfo *ci; gnutls_session_t session; _cleanup_(gnutls_x509_crt_deinitp) gnutls_x509_crt_t client_cert = NULL; _cleanup_free_ char *buf = NULL; int r; assert(connection); assert(code); *code = 0; ci = MHD_get_connection_info(connection, MHD_CONNECTION_INFO_GNUTLS_SESSION); if (!ci) { log_error("MHD_get_connection_info failed: session is unencrypted"); *code = mhd_respond(connection, MHD_HTTP_FORBIDDEN, "Encrypted connection is required"); return -EPERM; } session = ci->tls_session; assert(session); r = get_client_cert(session, &client_cert); if (r < 0) { *code = mhd_respond(connection, MHD_HTTP_UNAUTHORIZED, "Authorization through certificate is required"); return -EPERM; } r = get_auth_dn(client_cert, &buf); if (r < 0) { *code = mhd_respond(connection, MHD_HTTP_UNAUTHORIZED, "Failed to determine distinguished name from certificate"); return -EPERM; } log_debug("Connection from %s", buf); if (hostname) { *hostname = buf; buf = NULL; } r = verify_cert_authorized(session); if (r < 0) { log_warning("Client is not authorized"); *code = mhd_respond(connection, MHD_HTTP_UNAUTHORIZED, "Client certificate not signed by recognized authority"); } return r; } #else int check_permissions(struct MHD_Connection *connection, int *code, char **hostname) { return -EPERM; } int setup_gnutls_logger(char **categories) { if (categories) log_notice("Ignoring specified gnutls logging categories — gnutls not available."); return 0; } #endif systemd-229/src/journal-remote/microhttpd-util.h000066400000000000000000000037661265713322000221300ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include #include #include "macro.h" /* Compatiblity with libmicrohttpd < 0.9.38 */ #ifndef MHD_HTTP_NOT_ACCEPTABLE #define MHD_HTTP_NOT_ACCEPTABLE MHD_HTTP_METHOD_NOT_ACCEPTABLE #endif #if MHD_VERSION < 0x00094203 #define MHD_create_response_from_fd_at_offset64 MHD_create_response_from_fd_at_offset #endif void microhttpd_logger(void *arg, const char *fmt, va_list ap) _printf_(2, 0); /* respond_oom() must be usable with return, hence this form. */ #define respond_oom(connection) log_oom(), mhd_respond_oom(connection) int mhd_respondf(struct MHD_Connection *connection, unsigned code, const char *format, ...) _printf_(3,4); int mhd_respond(struct MHD_Connection *connection, unsigned code, const char *message); int mhd_respond_oom(struct MHD_Connection *connection); int check_permissions(struct MHD_Connection *connection, int *code, char **hostname); /* Set gnutls internal logging function to a callback which uses our * own logging framework. * * gnutls categories are additionally filtered by our internal log * level, so it should be set fairly high to capture all potentially * interesting events without overwhelming detail. */ int setup_gnutls_logger(char **categories); systemd-229/src/journal/000077500000000000000000000000001265713322000153225ustar00rootroot00000000000000systemd-229/src/journal/.gitignore000066400000000000000000000001231265713322000173060ustar00rootroot00000000000000/journald-gperf.c /libsystemd-journal.pc /audit_type-list.txt /audit_type-*-name.* systemd-229/src/journal/Makefile000077700000000000000000000000001265713322000206302../Makefileustar00rootroot00000000000000systemd-229/src/journal/audit-type.c000066400000000000000000000016271265713322000175610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #ifdef HAVE_AUDIT # include #endif #include "missing.h" #include "audit-type.h" #include "audit_type-to-name.h" #include "macro.h" systemd-229/src/journal/audit-type.h000066400000000000000000000030571265713322000175650ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "macro.h" const char *audit_type_to_string(int type); int audit_type_from_string(const char *s); /* This is inspired by DNS TYPEnnn formatting */ #define audit_type_name_alloca(type) \ ({ \ const char *_s_; \ _s_ = audit_type_to_string(type); \ if (!_s_) { \ _s_ = alloca(strlen("AUDIT") + DECIMAL_STR_MAX(int)); \ sprintf((char*) _s_, "AUDIT%04i", type); \ } \ _s_; \ }) systemd-229/src/journal/cat.c000066400000000000000000000116571265713322000162470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "sd-journal.h" #include "fd-util.h" #include "parse-util.h" #include "string-util.h" #include "syslog-util.h" #include "util.h" static const char *arg_identifier = NULL; static int arg_priority = LOG_INFO; static bool arg_level_prefix = true; static void help(void) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" "Execute process with stdout/stderr connected to the journal.\n\n" " -h --help Show this help\n" " --version Show package version\n" " -t --identifier=STRING Set syslog identifier\n" " -p --priority=PRIORITY Set priority value (0..7)\n" " --level-prefix=BOOL Control whether level prefix shall be parsed\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_LEVEL_PREFIX }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "identifier", required_argument, NULL, 't' }, { "priority", required_argument, NULL, 'p' }, { "level-prefix", required_argument, NULL, ARG_LEVEL_PREFIX }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "+ht:p:", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case 't': if (isempty(optarg)) arg_identifier = NULL; else arg_identifier = optarg; break; case 'p': arg_priority = log_level_from_string(optarg); if (arg_priority < 0) { log_error("Failed to parse priority value."); return -EINVAL; } break; case ARG_LEVEL_PREFIX: { int k; k = parse_boolean(optarg); if (k < 0) return log_error_errno(k, "Failed to parse level prefix value."); arg_level_prefix = k; break; } case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } int main(int argc, char *argv[]) { _cleanup_close_ int fd = -1, saved_stderr = -1; int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; fd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix); if (fd < 0) { r = log_error_errno(fd, "Failed to create stream fd: %m"); goto finish; } saved_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3); if (dup3(fd, STDOUT_FILENO, 0) < 0 || dup3(fd, STDERR_FILENO, 0) < 0) { r = log_error_errno(errno, "Failed to duplicate fd: %m"); goto finish; } if (fd >= 3) safe_close(fd); fd = -1; if (argc <= optind) (void) execl("/bin/cat", "/bin/cat", NULL); else (void) execvp(argv[optind], argv + optind); r = -errno; /* Let's try to restore a working stderr, so we can print the error message */ if (saved_stderr >= 0) (void) dup3(saved_stderr, STDERR_FILENO, 0); log_error_errno(r, "Failed to execute process: %m"); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/journal/catalog.c000066400000000000000000000527531265713322000171140ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "sd-id128.h" #include "alloc-util.h" #include "catalog.h" #include "conf-files.h" #include "fd-util.h" #include "fileio.h" #include "hashmap.h" #include "log.h" #include "mkdir.h" #include "path-util.h" #include "siphash24.h" #include "sparse-endian.h" #include "strbuf.h" #include "string-util.h" #include "strv.h" #include "util.h" const char * const catalog_file_dirs[] = { "/usr/local/lib/systemd/catalog/", "/usr/lib/systemd/catalog/", NULL }; #define CATALOG_SIGNATURE (uint8_t[]) { 'R', 'H', 'H', 'H', 'K', 'S', 'L', 'P' } typedef struct CatalogHeader { uint8_t signature[8]; /* "RHHHKSLP" */ le32_t compatible_flags; le32_t incompatible_flags; le64_t header_size; le64_t n_items; le64_t catalog_item_size; } CatalogHeader; typedef struct CatalogItem { sd_id128_t id; char language[32]; le64_t offset; } CatalogItem; static void catalog_hash_func(const void *p, struct siphash *state) { const CatalogItem *i = p; siphash24_compress(&i->id, sizeof(i->id), state); siphash24_compress(i->language, strlen(i->language), state); } static int catalog_compare_func(const void *a, const void *b) { const CatalogItem *i = a, *j = b; unsigned k; for (k = 0; k < ELEMENTSOF(j->id.bytes); k++) { if (i->id.bytes[k] < j->id.bytes[k]) return -1; if (i->id.bytes[k] > j->id.bytes[k]) return 1; } return strcmp(i->language, j->language); } const struct hash_ops catalog_hash_ops = { .hash = catalog_hash_func, .compare = catalog_compare_func }; static bool next_header(const char **s) { const char *e; e = strchr(*s, '\n'); /* Unexpected end */ if (!e) return false; /* End of headers */ if (e == *s) return false; *s = e + 1; return true; } static const char *skip_header(const char *s) { while (next_header(&s)) ; return s; } static char *combine_entries(const char *one, const char *two) { const char *b1, *b2; size_t l1, l2, n; char *dest, *p; /* Find split point of headers to body */ b1 = skip_header(one); b2 = skip_header(two); l1 = strlen(one); l2 = strlen(two); dest = new(char, l1 + l2 + 1); if (!dest) { log_oom(); return NULL; } p = dest; /* Headers from @one */ n = b1 - one; p = mempcpy(p, one, n); /* Headers from @two, these will only be found if not present above */ n = b2 - two; p = mempcpy(p, two, n); /* Body from @one */ n = l1 - (b1 - one); if (n > 0) { memcpy(p, b1, n); p += n; /* Body from @two */ } else { n = l2 - (b2 - two); memcpy(p, b2, n); p += n; } assert(p - dest <= (ptrdiff_t)(l1 + l2)); p[0] = '\0'; return dest; } static int finish_item( Hashmap *h, sd_id128_t id, const char *language, char *payload) { _cleanup_free_ CatalogItem *i = NULL; _cleanup_free_ char *combined = NULL, *prev = NULL; int r; assert(h); assert(payload); i = new0(CatalogItem, 1); if (!i) return log_oom(); i->id = id; if (language) { assert(strlen(language) > 1 && strlen(language) < 32); strcpy(i->language, language); } prev = hashmap_get(h, i); /* Already have such an item, combine them */ if (prev) { combined = combine_entries(payload, prev); if (!combined) return log_oom(); r = hashmap_update(h, i, combined); if (r < 0) return r; combined = NULL; /* A new item */ } else { r = hashmap_put(h, i, payload); if (r < 0) return r; i = NULL; } return 0; } int catalog_file_lang(const char* filename, char **lang) { char *beg, *end, *_lang; end = endswith(filename, ".catalog"); if (!end) return 0; beg = end - 1; while (beg > filename && *beg != '.' && *beg != '/' && end - beg < 32) beg --; if (*beg != '.' || end <= beg + 1) return 0; _lang = strndup(beg + 1, end - beg - 1); if (!_lang) return -ENOMEM; *lang = _lang; return 1; } static int catalog_entry_lang(const char* filename, int line, const char* t, const char* deflang, char **lang) { size_t c; c = strlen(t); if (c == 0) { log_error("[%s:%u] Language too short.", filename, line); return -EINVAL; } if (c > 31) { log_error("[%s:%u] language too long.", filename, line); return -EINVAL; } if (deflang) { if (streq(t, deflang)) { log_warning("[%s:%u] language specified unnecessarily", filename, line); return 0; } else log_warning("[%s:%u] language differs from default for file", filename, line); } *lang = strdup(t); if (!*lang) return -ENOMEM; return 0; } int catalog_import_file(Hashmap *h, const char *path) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *payload = NULL; unsigned n = 0; sd_id128_t id; _cleanup_free_ char *deflang = NULL, *lang = NULL; bool got_id = false, empty_line = true; int r; assert(h); assert(path); f = fopen(path, "re"); if (!f) return log_error_errno(errno, "Failed to open file %s: %m", path); r = catalog_file_lang(path, &deflang); if (r < 0) log_error_errno(r, "Failed to determine language for file %s: %m", path); if (r == 1) log_debug("File %s has language %s.", path, deflang); for (;;) { char line[LINE_MAX]; size_t a, b, c; char *t; if (!fgets(line, sizeof(line), f)) { if (feof(f)) break; return log_error_errno(errno, "Failed to read file %s: %m", path); } n++; truncate_nl(line); if (line[0] == 0) { empty_line = true; continue; } if (strchr(COMMENTS "\n", line[0])) continue; if (empty_line && strlen(line) >= 2+1+32 && line[0] == '-' && line[1] == '-' && line[2] == ' ' && (line[2+1+32] == ' ' || line[2+1+32] == '\0')) { bool with_language; sd_id128_t jd; /* New entry */ with_language = line[2+1+32] != '\0'; line[2+1+32] = '\0'; if (sd_id128_from_string(line + 2 + 1, &jd) >= 0) { if (got_id) { r = finish_item(h, id, lang ?: deflang, payload); if (r < 0) return r; payload = NULL; lang = mfree(lang); } if (with_language) { t = strstrip(line + 2 + 1 + 32 + 1); r = catalog_entry_lang(path, n, t, deflang, &lang); if (r < 0) return r; } got_id = true; empty_line = false; id = jd; if (payload) payload[0] = '\0'; continue; } } /* Payload */ if (!got_id) { log_error("[%s:%u] Got payload before ID.", path, n); return -EINVAL; } a = payload ? strlen(payload) : 0; b = strlen(line); c = a + (empty_line ? 1 : 0) + b + 1 + 1; t = realloc(payload, c); if (!t) return log_oom(); if (empty_line) { t[a] = '\n'; memcpy(t + a + 1, line, b); t[a+b+1] = '\n'; t[a+b+2] = 0; } else { memcpy(t + a, line, b); t[a+b] = '\n'; t[a+b+1] = 0; } payload = t; empty_line = false; } if (got_id) { r = finish_item(h, id, lang ?: deflang, payload); if (r < 0) return r; payload = NULL; } return 0; } static int64_t write_catalog(const char *database, struct strbuf *sb, CatalogItem *items, size_t n) { CatalogHeader header; _cleanup_fclose_ FILE *w = NULL; int r; _cleanup_free_ char *d, *p = NULL; size_t k; d = dirname_malloc(database); if (!d) return log_oom(); r = mkdir_p(d, 0775); if (r < 0) return log_error_errno(r, "Recursive mkdir %s: %m", d); r = fopen_temporary(database, &w, &p); if (r < 0) return log_error_errno(r, "Failed to open database for writing: %s: %m", database); zero(header); memcpy(header.signature, CATALOG_SIGNATURE, sizeof(header.signature)); header.header_size = htole64(ALIGN_TO(sizeof(CatalogHeader), 8)); header.catalog_item_size = htole64(sizeof(CatalogItem)); header.n_items = htole64(n); r = -EIO; k = fwrite(&header, 1, sizeof(header), w); if (k != sizeof(header)) { log_error("%s: failed to write header.", p); goto error; } k = fwrite(items, 1, n * sizeof(CatalogItem), w); if (k != n * sizeof(CatalogItem)) { log_error("%s: failed to write database.", p); goto error; } k = fwrite(sb->buf, 1, sb->len, w); if (k != sb->len) { log_error("%s: failed to write strings.", p); goto error; } r = fflush_and_check(w); if (r < 0) { log_error_errno(r, "%s: failed to write database: %m", p); goto error; } fchmod(fileno(w), 0644); if (rename(p, database) < 0) { r = log_error_errno(errno, "rename (%s -> %s) failed: %m", p, database); goto error; } return ftello(w); error: (void) unlink(p); return r; } int catalog_update(const char* database, const char* root, const char* const* dirs) { _cleanup_strv_free_ char **files = NULL; char **f; struct strbuf *sb = NULL; _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; _cleanup_free_ CatalogItem *items = NULL; ssize_t offset; char *payload; CatalogItem *i; Iterator j; unsigned n; int r; int64_t sz; h = hashmap_new(&catalog_hash_ops); sb = strbuf_new(); if (!h || !sb) { r = log_oom(); goto finish; } r = conf_files_list_strv(&files, ".catalog", root, dirs); if (r < 0) { log_error_errno(r, "Failed to get catalog files: %m"); goto finish; } STRV_FOREACH(f, files) { log_debug("Reading file '%s'", *f); r = catalog_import_file(h, *f); if (r < 0) { log_error_errno(r, "Failed to import file '%s': %m", *f); goto finish; } } if (hashmap_size(h) <= 0) { log_info("No items in catalog."); goto finish; } else log_debug("Found %u items in catalog.", hashmap_size(h)); items = new(CatalogItem, hashmap_size(h)); if (!items) { r = log_oom(); goto finish; } n = 0; HASHMAP_FOREACH_KEY(payload, i, h, j) { log_debug("Found " SD_ID128_FORMAT_STR ", language %s", SD_ID128_FORMAT_VAL(i->id), isempty(i->language) ? "C" : i->language); offset = strbuf_add_string(sb, payload, strlen(payload)); if (offset < 0) { r = log_oom(); goto finish; } i->offset = htole64((uint64_t) offset); items[n++] = *i; } assert(n == hashmap_size(h)); qsort_safe(items, n, sizeof(CatalogItem), catalog_compare_func); strbuf_complete(sb); sz = write_catalog(database, sb, items, n); if (sz < 0) r = log_error_errno(sz, "Failed to write %s: %m", database); else { r = 0; log_debug("%s: wrote %u items, with %zu bytes of strings, %"PRIi64" total size.", database, n, sb->len, sz); } finish: strbuf_cleanup(sb); return r; } static int open_mmap(const char *database, int *_fd, struct stat *_st, void **_p) { const CatalogHeader *h; int fd; void *p; struct stat st; assert(_fd); assert(_st); assert(_p); fd = open(database, O_RDONLY|O_CLOEXEC); if (fd < 0) return -errno; if (fstat(fd, &st) < 0) { safe_close(fd); return -errno; } if (st.st_size < (off_t) sizeof(CatalogHeader)) { safe_close(fd); return -EINVAL; } p = mmap(NULL, PAGE_ALIGN(st.st_size), PROT_READ, MAP_SHARED, fd, 0); if (p == MAP_FAILED) { safe_close(fd); return -errno; } h = p; if (memcmp(h->signature, CATALOG_SIGNATURE, sizeof(h->signature)) != 0 || le64toh(h->header_size) < sizeof(CatalogHeader) || le64toh(h->catalog_item_size) < sizeof(CatalogItem) || h->incompatible_flags != 0 || le64toh(h->n_items) <= 0 || st.st_size < (off_t) (le64toh(h->header_size) + le64toh(h->catalog_item_size) * le64toh(h->n_items))) { safe_close(fd); munmap(p, st.st_size); return -EBADMSG; } *_fd = fd; *_st = st; *_p = p; return 0; } static const char *find_id(void *p, sd_id128_t id) { CatalogItem key, *f = NULL; const CatalogHeader *h = p; const char *loc; zero(key); key.id = id; loc = setlocale(LC_MESSAGES, NULL); if (loc && loc[0] && !streq(loc, "C") && !streq(loc, "POSIX")) { strncpy(key.language, loc, sizeof(key.language)); key.language[strcspn(key.language, ".@")] = 0; f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), catalog_compare_func); if (!f) { char *e; e = strchr(key.language, '_'); if (e) { *e = 0; f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), catalog_compare_func); } } } if (!f) { zero(key.language); f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), catalog_compare_func); } if (!f) return NULL; return (const char*) p + le64toh(h->header_size) + le64toh(h->n_items) * le64toh(h->catalog_item_size) + le64toh(f->offset); } int catalog_get(const char* database, sd_id128_t id, char **_text) { _cleanup_close_ int fd = -1; void *p = NULL; struct stat st = {}; char *text = NULL; int r; const char *s; assert(_text); r = open_mmap(database, &fd, &st, &p); if (r < 0) return r; s = find_id(p, id); if (!s) { r = -ENOENT; goto finish; } text = strdup(s); if (!text) { r = -ENOMEM; goto finish; } *_text = text; r = 0; finish: if (p) munmap(p, st.st_size); return r; } static char *find_header(const char *s, const char *header) { for (;;) { const char *v; v = startswith(s, header); if (v) { v += strspn(v, WHITESPACE); return strndup(v, strcspn(v, NEWLINE)); } if (!next_header(&s)) return NULL; } } static void dump_catalog_entry(FILE *f, sd_id128_t id, const char *s, bool oneline) { if (oneline) { _cleanup_free_ char *subject = NULL, *defined_by = NULL; subject = find_header(s, "Subject:"); defined_by = find_header(s, "Defined-By:"); fprintf(f, SD_ID128_FORMAT_STR " %s: %s\n", SD_ID128_FORMAT_VAL(id), strna(defined_by), strna(subject)); } else fprintf(f, "-- " SD_ID128_FORMAT_STR "\n%s\n", SD_ID128_FORMAT_VAL(id), s); } int catalog_list(FILE *f, const char *database, bool oneline) { _cleanup_close_ int fd = -1; void *p = NULL; struct stat st; const CatalogHeader *h; const CatalogItem *items; int r; unsigned n; sd_id128_t last_id; bool last_id_set = false; r = open_mmap(database, &fd, &st, &p); if (r < 0) return r; h = p; items = (const CatalogItem*) ((const uint8_t*) p + le64toh(h->header_size)); for (n = 0; n < le64toh(h->n_items); n++) { const char *s; if (last_id_set && sd_id128_equal(last_id, items[n].id)) continue; assert_se(s = find_id(p, items[n].id)); dump_catalog_entry(f, items[n].id, s, oneline); last_id_set = true; last_id = items[n].id; } munmap(p, st.st_size); return 0; } int catalog_list_items(FILE *f, const char *database, bool oneline, char **items) { char **item; int r = 0; STRV_FOREACH(item, items) { sd_id128_t id; int k; _cleanup_free_ char *msg = NULL; k = sd_id128_from_string(*item, &id); if (k < 0) { log_error_errno(k, "Failed to parse id128 '%s': %m", *item); if (r == 0) r = k; continue; } k = catalog_get(database, id, &msg); if (k < 0) { log_full_errno(k == -ENOENT ? LOG_NOTICE : LOG_ERR, k, "Failed to retrieve catalog entry for '%s': %m", *item); if (r == 0) r = k; continue; } dump_catalog_entry(f, id, msg, oneline); } return r; } systemd-229/src/journal/catalog.h000066400000000000000000000024551265713322000171130ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-id128.h" #include "hashmap.h" #include "strbuf.h" int catalog_import_file(Hashmap *h, const char *path); int catalog_update(const char* database, const char* root, const char* const* dirs); int catalog_get(const char* database, sd_id128_t id, char **data); int catalog_list(FILE *f, const char* database, bool oneline); int catalog_list_items(FILE *f, const char* database, bool oneline, char **items); int catalog_file_lang(const char *filename, char **lang); extern const char * const catalog_file_dirs[]; extern const struct hash_ops catalog_hash_ops; systemd-229/src/journal/compress.c000066400000000000000000000526661265713322000173400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #ifdef HAVE_XZ #include #endif #ifdef HAVE_LZ4 #include #include #endif #include "alloc-util.h" #include "compress.h" #include "fd-util.h" #include "io-util.h" #include "journal-def.h" #include "macro.h" #include "sparse-endian.h" #include "string-table.h" #include "string-util.h" #include "util.h" #ifdef HAVE_LZ4 DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_compressionContext_t, LZ4F_freeCompressionContext); DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_decompressionContext_t, LZ4F_freeDecompressionContext); #endif #define ALIGN_8(l) ALIGN_TO(l, sizeof(size_t)) static const char* const object_compressed_table[_OBJECT_COMPRESSED_MAX] = { [OBJECT_COMPRESSED_XZ] = "XZ", [OBJECT_COMPRESSED_LZ4] = "LZ4", }; DEFINE_STRING_TABLE_LOOKUP(object_compressed, int); int compress_blob_xz(const void *src, uint64_t src_size, void *dst, size_t dst_alloc_size, size_t *dst_size) { #ifdef HAVE_XZ static const lzma_options_lzma opt = { 1u << 20u, NULL, 0, LZMA_LC_DEFAULT, LZMA_LP_DEFAULT, LZMA_PB_DEFAULT, LZMA_MODE_FAST, 128, LZMA_MF_HC3, 4 }; static const lzma_filter filters[] = { { LZMA_FILTER_LZMA2, (lzma_options_lzma*) &opt }, { LZMA_VLI_UNKNOWN, NULL } }; lzma_ret ret; size_t out_pos = 0; assert(src); assert(src_size > 0); assert(dst); assert(dst_alloc_size > 0); assert(dst_size); /* Returns < 0 if we couldn't compress the data or the * compressed result is longer than the original */ if (src_size < 80) return -ENOBUFS; ret = lzma_stream_buffer_encode((lzma_filter*) filters, LZMA_CHECK_NONE, NULL, src, src_size, dst, &out_pos, dst_alloc_size); if (ret != LZMA_OK) return -ENOBUFS; *dst_size = out_pos; return 0; #else return -EPROTONOSUPPORT; #endif } int compress_blob_lz4(const void *src, uint64_t src_size, void *dst, size_t dst_alloc_size, size_t *dst_size) { #ifdef HAVE_LZ4 int r; assert(src); assert(src_size > 0); assert(dst); assert(dst_alloc_size > 0); assert(dst_size); /* Returns < 0 if we couldn't compress the data or the * compressed result is longer than the original */ if (src_size < 9) return -ENOBUFS; r = LZ4_compress_limitedOutput(src, dst + 8, src_size, (int) dst_alloc_size - 8); if (r <= 0) return -ENOBUFS; *(le64_t*) dst = htole64(src_size); *dst_size = r + 8; return 0; #else return -EPROTONOSUPPORT; #endif } int decompress_blob_xz(const void *src, uint64_t src_size, void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max) { #ifdef HAVE_XZ _cleanup_(lzma_end) lzma_stream s = LZMA_STREAM_INIT; lzma_ret ret; size_t space; assert(src); assert(src_size > 0); assert(dst); assert(dst_alloc_size); assert(dst_size); assert(*dst_alloc_size == 0 || *dst); ret = lzma_stream_decoder(&s, UINT64_MAX, 0); if (ret != LZMA_OK) return -ENOMEM; space = MIN(src_size * 2, dst_max ?: (size_t) -1); if (!greedy_realloc(dst, dst_alloc_size, space, 1)) return -ENOMEM; s.next_in = src; s.avail_in = src_size; s.next_out = *dst; s.avail_out = space; for (;;) { size_t used; ret = lzma_code(&s, LZMA_FINISH); if (ret == LZMA_STREAM_END) break; else if (ret != LZMA_OK) return -ENOMEM; if (dst_max > 0 && (space - s.avail_out) >= dst_max) break; else if (dst_max > 0 && space == dst_max) return -ENOBUFS; used = space - s.avail_out; space = MIN(2 * space, dst_max ?: (size_t) -1); if (!greedy_realloc(dst, dst_alloc_size, space, 1)) return -ENOMEM; s.avail_out = space - used; s.next_out = *dst + used; } *dst_size = space - s.avail_out; return 0; #else return -EPROTONOSUPPORT; #endif } int decompress_blob_lz4(const void *src, uint64_t src_size, void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max) { #ifdef HAVE_LZ4 char* out; int r, size; /* LZ4 uses int for size */ assert(src); assert(src_size > 0); assert(dst); assert(dst_alloc_size); assert(dst_size); assert(*dst_alloc_size == 0 || *dst); if (src_size <= 8) return -EBADMSG; size = le64toh( *(le64_t*)src ); if (size < 0 || (unsigned) size != le64toh(*(le64_t*)src)) return -EFBIG; if ((size_t) size > *dst_alloc_size) { out = realloc(*dst, size); if (!out) return -ENOMEM; *dst = out; *dst_alloc_size = size; } else out = *dst; r = LZ4_decompress_safe(src + 8, out, src_size - 8, size); if (r < 0 || r != size) return -EBADMSG; *dst_size = size; return 0; #else return -EPROTONOSUPPORT; #endif } int decompress_blob(int compression, const void *src, uint64_t src_size, void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max) { if (compression == OBJECT_COMPRESSED_XZ) return decompress_blob_xz(src, src_size, dst, dst_alloc_size, dst_size, dst_max); else if (compression == OBJECT_COMPRESSED_LZ4) return decompress_blob_lz4(src, src_size, dst, dst_alloc_size, dst_size, dst_max); else return -EBADMSG; } int decompress_startswith_xz(const void *src, uint64_t src_size, void **buffer, size_t *buffer_size, const void *prefix, size_t prefix_len, uint8_t extra) { #ifdef HAVE_XZ _cleanup_(lzma_end) lzma_stream s = LZMA_STREAM_INIT; lzma_ret ret; /* Checks whether the decompressed blob starts with the * mentioned prefix. The byte extra needs to follow the * prefix */ assert(src); assert(src_size > 0); assert(buffer); assert(buffer_size); assert(prefix); assert(*buffer_size == 0 || *buffer); ret = lzma_stream_decoder(&s, UINT64_MAX, 0); if (ret != LZMA_OK) return -EBADMSG; if (!(greedy_realloc(buffer, buffer_size, ALIGN_8(prefix_len + 1), 1))) return -ENOMEM; s.next_in = src; s.avail_in = src_size; s.next_out = *buffer; s.avail_out = *buffer_size; for (;;) { ret = lzma_code(&s, LZMA_FINISH); if (ret != LZMA_STREAM_END && ret != LZMA_OK) return -EBADMSG; if (*buffer_size - s.avail_out >= prefix_len + 1) return memcmp(*buffer, prefix, prefix_len) == 0 && ((const uint8_t*) *buffer)[prefix_len] == extra; if (ret == LZMA_STREAM_END) return 0; s.avail_out += *buffer_size; if (!(greedy_realloc(buffer, buffer_size, *buffer_size * 2, 1))) return -ENOMEM; s.next_out = *buffer + *buffer_size - s.avail_out; } #else return -EPROTONOSUPPORT; #endif } int decompress_startswith_lz4(const void *src, uint64_t src_size, void **buffer, size_t *buffer_size, const void *prefix, size_t prefix_len, uint8_t extra) { #ifdef HAVE_LZ4 /* Checks whether the decompressed blob starts with the * mentioned prefix. The byte extra needs to follow the * prefix */ int r; size_t size; assert(src); assert(src_size > 0); assert(buffer); assert(buffer_size); assert(prefix); assert(*buffer_size == 0 || *buffer); if (src_size <= 8) return -EBADMSG; if (!(greedy_realloc(buffer, buffer_size, ALIGN_8(prefix_len + 1), 1))) return -ENOMEM; r = LZ4_decompress_safe_partial(src + 8, *buffer, src_size - 8, prefix_len + 1, *buffer_size); if (r >= 0) size = (unsigned) r; else { /* lz4 always tries to decode full "sequence", so in * pathological cases might need to decompress the * full field. */ r = decompress_blob_lz4(src, src_size, buffer, buffer_size, &size, 0); if (r < 0) return r; } if (size >= prefix_len + 1) return memcmp(*buffer, prefix, prefix_len) == 0 && ((const uint8_t*) *buffer)[prefix_len] == extra; else return 0; #else return -EPROTONOSUPPORT; #endif } int decompress_startswith(int compression, const void *src, uint64_t src_size, void **buffer, size_t *buffer_size, const void *prefix, size_t prefix_len, uint8_t extra) { if (compression == OBJECT_COMPRESSED_XZ) return decompress_startswith_xz(src, src_size, buffer, buffer_size, prefix, prefix_len, extra); else if (compression == OBJECT_COMPRESSED_LZ4) return decompress_startswith_lz4(src, src_size, buffer, buffer_size, prefix, prefix_len, extra); else return -EBADMSG; } int compress_stream_xz(int fdf, int fdt, uint64_t max_bytes) { #ifdef HAVE_XZ _cleanup_(lzma_end) lzma_stream s = LZMA_STREAM_INIT; lzma_ret ret; uint8_t buf[BUFSIZ], out[BUFSIZ]; lzma_action action = LZMA_RUN; assert(fdf >= 0); assert(fdt >= 0); ret = lzma_easy_encoder(&s, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64); if (ret != LZMA_OK) { log_error("Failed to initialize XZ encoder: code %u", ret); return -EINVAL; } for (;;) { if (s.avail_in == 0 && action == LZMA_RUN) { size_t m = sizeof(buf); ssize_t n; if (max_bytes != (uint64_t) -1 && (uint64_t) m > max_bytes) m = (size_t) max_bytes; n = read(fdf, buf, m); if (n < 0) return -errno; if (n == 0) action = LZMA_FINISH; else { s.next_in = buf; s.avail_in = n; if (max_bytes != (uint64_t) -1) { assert(max_bytes >= (uint64_t) n); max_bytes -= n; } } } if (s.avail_out == 0) { s.next_out = out; s.avail_out = sizeof(out); } ret = lzma_code(&s, action); if (ret != LZMA_OK && ret != LZMA_STREAM_END) { log_error("Compression failed: code %u", ret); return -EBADMSG; } if (s.avail_out == 0 || ret == LZMA_STREAM_END) { ssize_t n, k; n = sizeof(out) - s.avail_out; k = loop_write(fdt, out, n, false); if (k < 0) return k; if (ret == LZMA_STREAM_END) { log_debug("XZ compression finished (%"PRIu64" -> %"PRIu64" bytes, %.1f%%)", s.total_in, s.total_out, (double) s.total_out / s.total_in * 100); return 0; } } } #else return -EPROTONOSUPPORT; #endif } #define LZ4_BUFSIZE (512*1024u) int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) { #ifdef HAVE_LZ4 LZ4F_errorCode_t c; _cleanup_(LZ4F_freeCompressionContextp) LZ4F_compressionContext_t ctx = NULL; _cleanup_free_ char *buf = NULL; char *src = NULL; size_t size, n, total_in = 0, total_out, offset = 0, frame_size; struct stat st; int r; static const LZ4F_compressOptions_t options = { .stableSrc = 1, }; static const LZ4F_preferences_t preferences = { .frameInfo.blockSizeID = 5, }; c = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION); if (LZ4F_isError(c)) return -ENOMEM; if (fstat(fdf, &st) < 0) return log_debug_errno(errno, "fstat() failed: %m"); frame_size = LZ4F_compressBound(LZ4_BUFSIZE, &preferences); size = frame_size + 64*1024; /* add some space for header and trailer */ buf = malloc(size); if (!buf) return -ENOMEM; n = offset = total_out = LZ4F_compressBegin(ctx, buf, size, &preferences); if (LZ4F_isError(n)) return -EINVAL; src = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fdf, 0); if (src == MAP_FAILED) return -errno; log_debug("Buffer size is %zu bytes, header size %zu bytes.", size, n); while (total_in < (size_t) st.st_size) { ssize_t k; k = MIN(LZ4_BUFSIZE, st.st_size - total_in); n = LZ4F_compressUpdate(ctx, buf + offset, size - offset, src + total_in, k, &options); if (LZ4F_isError(n)) { r = -ENOTRECOVERABLE; goto cleanup; } total_in += k; offset += n; total_out += n; if (max_bytes != (uint64_t) -1 && total_out > (size_t) max_bytes) { log_debug("Compressed stream longer than %zd bytes", max_bytes); return -EFBIG; } if (size - offset < frame_size + 4) { k = loop_write(fdt, buf, offset, false); if (k < 0) { r = k; goto cleanup; } offset = 0; } } n = LZ4F_compressEnd(ctx, buf + offset, size - offset, &options); if (LZ4F_isError(n)) { r = -ENOTRECOVERABLE; goto cleanup; } offset += n; total_out += n; r = loop_write(fdt, buf, offset, false); if (r < 0) goto cleanup; log_debug("LZ4 compression finished (%zu -> %zu bytes, %.1f%%)", total_in, total_out, (double) total_out / total_in * 100); cleanup: munmap(src, st.st_size); return r; #else return -EPROTONOSUPPORT; #endif } int decompress_stream_xz(int fdf, int fdt, uint64_t max_bytes) { #ifdef HAVE_XZ _cleanup_(lzma_end) lzma_stream s = LZMA_STREAM_INIT; lzma_ret ret; uint8_t buf[BUFSIZ], out[BUFSIZ]; lzma_action action = LZMA_RUN; assert(fdf >= 0); assert(fdt >= 0); ret = lzma_stream_decoder(&s, UINT64_MAX, 0); if (ret != LZMA_OK) { log_debug("Failed to initialize XZ decoder: code %u", ret); return -ENOMEM; } for (;;) { if (s.avail_in == 0 && action == LZMA_RUN) { ssize_t n; n = read(fdf, buf, sizeof(buf)); if (n < 0) return -errno; if (n == 0) action = LZMA_FINISH; else { s.next_in = buf; s.avail_in = n; } } if (s.avail_out == 0) { s.next_out = out; s.avail_out = sizeof(out); } ret = lzma_code(&s, action); if (ret != LZMA_OK && ret != LZMA_STREAM_END) { log_debug("Decompression failed: code %u", ret); return -EBADMSG; } if (s.avail_out == 0 || ret == LZMA_STREAM_END) { ssize_t n, k; n = sizeof(out) - s.avail_out; if (max_bytes != (uint64_t) -1) { if (max_bytes < (uint64_t) n) return -EFBIG; max_bytes -= n; } k = loop_write(fdt, out, n, false); if (k < 0) return k; if (ret == LZMA_STREAM_END) { log_debug("XZ decompression finished (%"PRIu64" -> %"PRIu64" bytes, %.1f%%)", s.total_in, s.total_out, (double) s.total_out / s.total_in * 100); return 0; } } } #else log_debug("Cannot decompress file. Compiled without XZ support."); return -EPROTONOSUPPORT; #endif } int decompress_stream_lz4(int in, int out, uint64_t max_bytes) { #ifdef HAVE_LZ4 size_t c; _cleanup_(LZ4F_freeDecompressionContextp) LZ4F_decompressionContext_t ctx = NULL; _cleanup_free_ char *buf = NULL; char *src; struct stat st; int r = 0; size_t total_in = 0, total_out = 0; c = LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION); if (LZ4F_isError(c)) return -ENOMEM; if (fstat(in, &st) < 0) return log_debug_errno(errno, "fstat() failed: %m"); buf = malloc(LZ4_BUFSIZE); if (!buf) return -ENOMEM; src = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, in, 0); if (src == MAP_FAILED) return -errno; while (total_in < (size_t) st.st_size) { size_t produced = LZ4_BUFSIZE; size_t used = st.st_size - total_in; c = LZ4F_decompress(ctx, buf, &produced, src + total_in, &used, NULL); if (LZ4F_isError(c)) { r = -EBADMSG; goto cleanup; } total_in += used; total_out += produced; if (max_bytes != (uint64_t) -1 && total_out > (size_t) max_bytes) { log_debug("Decompressed stream longer than %zd bytes", max_bytes); r = -EFBIG; goto cleanup; } r = loop_write(out, buf, produced, false); if (r < 0) goto cleanup; } log_debug("LZ4 decompression finished (%zu -> %zu bytes, %.1f%%)", total_in, total_out, (double) total_out / total_in * 100); cleanup: munmap(src, st.st_size); return r; #else log_debug("Cannot decompress file. Compiled without LZ4 support."); return -EPROTONOSUPPORT; #endif } int decompress_stream(const char *filename, int fdf, int fdt, uint64_t max_bytes) { if (endswith(filename, ".lz4")) return decompress_stream_lz4(fdf, fdt, max_bytes); else if (endswith(filename, ".xz")) return decompress_stream_xz(fdf, fdt, max_bytes); else return -EPROTONOSUPPORT; } systemd-229/src/journal/compress.h000066400000000000000000000065661265713322000173430ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "journal-def.h" const char* object_compressed_to_string(int compression); int object_compressed_from_string(const char *compression); int compress_blob_xz(const void *src, uint64_t src_size, void *dst, size_t dst_alloc_size, size_t *dst_size); int compress_blob_lz4(const void *src, uint64_t src_size, void *dst, size_t dst_alloc_size, size_t *dst_size); static inline int compress_blob(const void *src, uint64_t src_size, void *dst, size_t dst_alloc_size, size_t *dst_size) { int r; #ifdef HAVE_LZ4 r = compress_blob_lz4(src, src_size, dst, dst_alloc_size, dst_size); if (r == 0) return OBJECT_COMPRESSED_LZ4; #else r = compress_blob_xz(src, src_size, dst, dst_alloc_size, dst_size); if (r == 0) return OBJECT_COMPRESSED_XZ; #endif return r; } int decompress_blob_xz(const void *src, uint64_t src_size, void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max); int decompress_blob_lz4(const void *src, uint64_t src_size, void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max); int decompress_blob(int compression, const void *src, uint64_t src_size, void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max); int decompress_startswith_xz(const void *src, uint64_t src_size, void **buffer, size_t *buffer_size, const void *prefix, size_t prefix_len, uint8_t extra); int decompress_startswith_lz4(const void *src, uint64_t src_size, void **buffer, size_t *buffer_size, const void *prefix, size_t prefix_len, uint8_t extra); int decompress_startswith(int compression, const void *src, uint64_t src_size, void **buffer, size_t *buffer_size, const void *prefix, size_t prefix_len, uint8_t extra); int compress_stream_xz(int fdf, int fdt, uint64_t max_bytes); int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes); int decompress_stream_xz(int fdf, int fdt, uint64_t max_size); int decompress_stream_lz4(int fdf, int fdt, uint64_t max_size); #ifdef HAVE_LZ4 # define compress_stream compress_stream_lz4 # define COMPRESSED_EXT ".lz4" #else # define compress_stream compress_stream_xz # define COMPRESSED_EXT ".xz" #endif int decompress_stream(const char *filename, int fdf, int fdt, uint64_t max_bytes); systemd-229/src/journal/fsprg.c000066400000000000000000000315111265713322000166100ustar00rootroot00000000000000/* * fsprg v0.1 - (seekable) forward-secure pseudorandom generator * Copyright (C) 2012 B. Poettering * Contact: fsprg@point-at-infinity.org * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA */ /* * See "Practical Secure Logging: Seekable Sequential Key Generators" * by G. A. Marson, B. Poettering for details: * * http://eprint.iacr.org/2013/397 */ #include #include #include "fsprg.h" #define ISVALID_SECPAR(secpar) (((secpar) % 16 == 0) && ((secpar) >= 16) && ((secpar) <= 16384)) #define VALIDATE_SECPAR(secpar) assert(ISVALID_SECPAR(secpar)); #define RND_HASH GCRY_MD_SHA256 #define RND_GEN_P 0x01 #define RND_GEN_Q 0x02 #define RND_GEN_X 0x03 /******************************************************************************/ static void mpi_export(void *buf, size_t buflen, const gcry_mpi_t x) { unsigned len; size_t nwritten; assert(gcry_mpi_cmp_ui(x, 0) >= 0); len = (gcry_mpi_get_nbits(x) + 7) / 8; assert(len <= buflen); memzero(buf, buflen); gcry_mpi_print(GCRYMPI_FMT_USG, buf + (buflen - len), len, &nwritten, x); assert(nwritten == len); } static gcry_mpi_t mpi_import(const void *buf, size_t buflen) { gcry_mpi_t h; unsigned len; gcry_mpi_scan(&h, GCRYMPI_FMT_USG, buf, buflen, NULL); len = (gcry_mpi_get_nbits(h) + 7) / 8; assert(len <= buflen); assert(gcry_mpi_cmp_ui(h, 0) >= 0); return h; } static void uint64_export(void *buf, size_t buflen, uint64_t x) { assert(buflen == 8); ((uint8_t*) buf)[0] = (x >> 56) & 0xff; ((uint8_t*) buf)[1] = (x >> 48) & 0xff; ((uint8_t*) buf)[2] = (x >> 40) & 0xff; ((uint8_t*) buf)[3] = (x >> 32) & 0xff; ((uint8_t*) buf)[4] = (x >> 24) & 0xff; ((uint8_t*) buf)[5] = (x >> 16) & 0xff; ((uint8_t*) buf)[6] = (x >> 8) & 0xff; ((uint8_t*) buf)[7] = (x >> 0) & 0xff; } _pure_ static uint64_t uint64_import(const void *buf, size_t buflen) { assert(buflen == 8); return (uint64_t)(((uint8_t*) buf)[0]) << 56 | (uint64_t)(((uint8_t*) buf)[1]) << 48 | (uint64_t)(((uint8_t*) buf)[2]) << 40 | (uint64_t)(((uint8_t*) buf)[3]) << 32 | (uint64_t)(((uint8_t*) buf)[4]) << 24 | (uint64_t)(((uint8_t*) buf)[5]) << 16 | (uint64_t)(((uint8_t*) buf)[6]) << 8 | (uint64_t)(((uint8_t*) buf)[7]) << 0; } /* deterministically generate from seed/idx a string of buflen pseudorandom bytes */ static void det_randomize(void *buf, size_t buflen, const void *seed, size_t seedlen, uint32_t idx) { gcry_md_hd_t hd, hd2; size_t olen, cpylen; uint32_t ctr; olen = gcry_md_get_algo_dlen(RND_HASH); gcry_md_open(&hd, RND_HASH, 0); gcry_md_write(hd, seed, seedlen); gcry_md_putc(hd, (idx >> 24) & 0xff); gcry_md_putc(hd, (idx >> 16) & 0xff); gcry_md_putc(hd, (idx >> 8) & 0xff); gcry_md_putc(hd, (idx >> 0) & 0xff); for (ctr = 0; buflen; ctr++) { gcry_md_copy(&hd2, hd); gcry_md_putc(hd2, (ctr >> 24) & 0xff); gcry_md_putc(hd2, (ctr >> 16) & 0xff); gcry_md_putc(hd2, (ctr >> 8) & 0xff); gcry_md_putc(hd2, (ctr >> 0) & 0xff); gcry_md_final(hd2); cpylen = (buflen < olen) ? buflen : olen; memcpy(buf, gcry_md_read(hd2, RND_HASH), cpylen); gcry_md_close(hd2); buf += cpylen; buflen -= cpylen; } gcry_md_close(hd); } /* deterministically generate from seed/idx a prime of length `bits' that is 3 (mod 4) */ static gcry_mpi_t genprime3mod4(int bits, const void *seed, size_t seedlen, uint32_t idx) { size_t buflen = bits / 8; uint8_t buf[buflen]; gcry_mpi_t p; assert(bits % 8 == 0); assert(buflen > 0); det_randomize(buf, buflen, seed, seedlen, idx); buf[0] |= 0xc0; /* set upper two bits, so that n=pq has maximum size */ buf[buflen - 1] |= 0x03; /* set lower two bits, to have result 3 (mod 4) */ p = mpi_import(buf, buflen); while (gcry_prime_check(p, 0)) gcry_mpi_add_ui(p, p, 4); return p; } /* deterministically generate from seed/idx a quadratic residue (mod n) */ static gcry_mpi_t gensquare(const gcry_mpi_t n, const void *seed, size_t seedlen, uint32_t idx, unsigned secpar) { size_t buflen = secpar / 8; uint8_t buf[buflen]; gcry_mpi_t x; det_randomize(buf, buflen, seed, seedlen, idx); buf[0] &= 0x7f; /* clear upper bit, so that we have x < n */ x = mpi_import(buf, buflen); assert(gcry_mpi_cmp(x, n) < 0); gcry_mpi_mulm(x, x, x, n); return x; } /* compute 2^m (mod phi(p)), for a prime p */ static gcry_mpi_t twopowmodphi(uint64_t m, const gcry_mpi_t p) { gcry_mpi_t phi, r; int n; phi = gcry_mpi_new(0); gcry_mpi_sub_ui(phi, p, 1); /* count number of used bits in m */ for (n = 0; (1ULL << n) <= m; n++) ; r = gcry_mpi_new(0); gcry_mpi_set_ui(r, 1); while (n) { /* square and multiply algorithm for fast exponentiation */ n--; gcry_mpi_mulm(r, r, r, phi); if (m & ((uint64_t)1 << n)) { gcry_mpi_add(r, r, r); if (gcry_mpi_cmp(r, phi) >= 0) gcry_mpi_sub(r, r, phi); } } gcry_mpi_release(phi); return r; } /* Decompose $x \in Z_n$ into $(xp,xq) \in Z_p \times Z_q$ using Chinese Remainder Theorem */ static void CRT_decompose(gcry_mpi_t *xp, gcry_mpi_t *xq, const gcry_mpi_t x, const gcry_mpi_t p, const gcry_mpi_t q) { *xp = gcry_mpi_new(0); *xq = gcry_mpi_new(0); gcry_mpi_mod(*xp, x, p); gcry_mpi_mod(*xq, x, q); } /* Compose $(xp,xq) \in Z_p \times Z_q$ into $x \in Z_n$ using Chinese Remainder Theorem */ static void CRT_compose(gcry_mpi_t *x, const gcry_mpi_t xp, const gcry_mpi_t xq, const gcry_mpi_t p, const gcry_mpi_t q) { gcry_mpi_t a, u; a = gcry_mpi_new(0); u = gcry_mpi_new(0); *x = gcry_mpi_new(0); gcry_mpi_subm(a, xq, xp, q); gcry_mpi_invm(u, p, q); gcry_mpi_mulm(a, a, u, q); /* a = (xq - xp) / p (mod q) */ gcry_mpi_mul(*x, p, a); gcry_mpi_add(*x, *x, xp); /* x = p * ((xq - xp) / p mod q) + xp */ gcry_mpi_release(a); gcry_mpi_release(u); } static void initialize_libgcrypt(void) { const char *p; if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P)) return; p = gcry_check_version("1.4.5"); assert(p); /* Turn off "secmem". Clients which whish to make use of this * feature should initialize the library manually */ gcry_control(GCRYCTL_DISABLE_SECMEM); gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); } /******************************************************************************/ size_t FSPRG_mskinbytes(unsigned _secpar) { VALIDATE_SECPAR(_secpar); return 2 + 2 * (_secpar / 2) / 8; /* to store header,p,q */ } size_t FSPRG_mpkinbytes(unsigned _secpar) { VALIDATE_SECPAR(_secpar); return 2 + _secpar / 8; /* to store header,n */ } size_t FSPRG_stateinbytes(unsigned _secpar) { VALIDATE_SECPAR(_secpar); return 2 + 2 * _secpar / 8 + 8; /* to store header,n,x,epoch */ } static void store_secpar(void *buf, uint16_t secpar) { secpar = secpar / 16 - 1; ((uint8_t*) buf)[0] = (secpar >> 8) & 0xff; ((uint8_t*) buf)[1] = (secpar >> 0) & 0xff; } static uint16_t read_secpar(const void *buf) { uint16_t secpar; secpar = (uint16_t)(((uint8_t*) buf)[0]) << 8 | (uint16_t)(((uint8_t*) buf)[1]) << 0; return 16 * (secpar + 1); } void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned _secpar) { uint8_t iseed[FSPRG_RECOMMENDED_SEEDLEN]; gcry_mpi_t n, p, q; uint16_t secpar; VALIDATE_SECPAR(_secpar); secpar = _secpar; initialize_libgcrypt(); if (!seed) { gcry_randomize(iseed, FSPRG_RECOMMENDED_SEEDLEN, GCRY_STRONG_RANDOM); seed = iseed; seedlen = FSPRG_RECOMMENDED_SEEDLEN; } p = genprime3mod4(secpar / 2, seed, seedlen, RND_GEN_P); q = genprime3mod4(secpar / 2, seed, seedlen, RND_GEN_Q); if (msk) { store_secpar(msk + 0, secpar); mpi_export(msk + 2 + 0 * (secpar / 2) / 8, (secpar / 2) / 8, p); mpi_export(msk + 2 + 1 * (secpar / 2) / 8, (secpar / 2) / 8, q); } if (mpk) { n = gcry_mpi_new(0); gcry_mpi_mul(n, p, q); assert(gcry_mpi_get_nbits(n) == secpar); store_secpar(mpk + 0, secpar); mpi_export(mpk + 2, secpar / 8, n); gcry_mpi_release(n); } gcry_mpi_release(p); gcry_mpi_release(q); } void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen) { gcry_mpi_t n, x; uint16_t secpar; initialize_libgcrypt(); secpar = read_secpar(mpk + 0); n = mpi_import(mpk + 2, secpar / 8); x = gensquare(n, seed, seedlen, RND_GEN_X, secpar); memcpy(state, mpk, 2 + secpar / 8); mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x); memzero(state + 2 + 2 * secpar / 8, 8); gcry_mpi_release(n); gcry_mpi_release(x); } void FSPRG_Evolve(void *state) { gcry_mpi_t n, x; uint16_t secpar; uint64_t epoch; initialize_libgcrypt(); secpar = read_secpar(state + 0); n = mpi_import(state + 2 + 0 * secpar / 8, secpar / 8); x = mpi_import(state + 2 + 1 * secpar / 8, secpar / 8); epoch = uint64_import(state + 2 + 2 * secpar / 8, 8); gcry_mpi_mulm(x, x, x, n); epoch++; mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x); uint64_export(state + 2 + 2 * secpar / 8, 8, epoch); gcry_mpi_release(n); gcry_mpi_release(x); } uint64_t FSPRG_GetEpoch(const void *state) { uint16_t secpar; secpar = read_secpar(state + 0); return uint64_import(state + 2 + 2 * secpar / 8, 8); } void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen) { gcry_mpi_t p, q, n, x, xp, xq, kp, kq, xm; uint16_t secpar; initialize_libgcrypt(); secpar = read_secpar(msk + 0); p = mpi_import(msk + 2 + 0 * (secpar / 2) / 8, (secpar / 2) / 8); q = mpi_import(msk + 2 + 1 * (secpar / 2) / 8, (secpar / 2) / 8); n = gcry_mpi_new(0); gcry_mpi_mul(n, p, q); x = gensquare(n, seed, seedlen, RND_GEN_X, secpar); CRT_decompose(&xp, &xq, x, p, q); /* split (mod n) into (mod p) and (mod q) using CRT */ kp = twopowmodphi(epoch, p); /* compute 2^epoch (mod phi(p)) */ kq = twopowmodphi(epoch, q); /* compute 2^epoch (mod phi(q)) */ gcry_mpi_powm(xp, xp, kp, p); /* compute x^(2^epoch) (mod p) */ gcry_mpi_powm(xq, xq, kq, q); /* compute x^(2^epoch) (mod q) */ CRT_compose(&xm, xp, xq, p, q); /* combine (mod p) and (mod q) to (mod n) using CRT */ store_secpar(state + 0, secpar); mpi_export(state + 2 + 0 * secpar / 8, secpar / 8, n); mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, xm); uint64_export(state + 2 + 2 * secpar / 8, 8, epoch); gcry_mpi_release(p); gcry_mpi_release(q); gcry_mpi_release(n); gcry_mpi_release(x); gcry_mpi_release(xp); gcry_mpi_release(xq); gcry_mpi_release(kp); gcry_mpi_release(kq); gcry_mpi_release(xm); } void FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx) { uint16_t secpar; initialize_libgcrypt(); secpar = read_secpar(state + 0); det_randomize(key, keylen, state + 2, 2 * secpar / 8 + 8, idx); } systemd-229/src/journal/fsprg.h000066400000000000000000000041341265713322000166160ustar00rootroot00000000000000#ifndef __fsprgh__ #define __fsprgh__ /* * fsprg v0.1 - (seekable) forward-secure pseudorandom generator * Copyright (C) 2012 B. Poettering * Contact: fsprg@point-at-infinity.org * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include #include #include "macro.h" #include "util.h" #ifdef __cplusplus extern "C" { #endif #define FSPRG_RECOMMENDED_SECPAR 1536 #define FSPRG_RECOMMENDED_SEEDLEN (96/8) size_t FSPRG_mskinbytes(unsigned secpar) _const_; size_t FSPRG_mpkinbytes(unsigned secpar) _const_; size_t FSPRG_stateinbytes(unsigned secpar) _const_; /* Setup msk and mpk. Providing seed != NULL makes this algorithm deterministic. */ void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned secpar); /* Initialize state deterministically in dependence on seed. */ /* Note: in case one wants to run only one GenState0 per GenMK it is safe to use the same seed for both GenMK and GenState0. */ void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen); void FSPRG_Evolve(void *state); uint64_t FSPRG_GetEpoch(const void *state) _pure_; /* Seek to any arbitrary state (by providing msk together with seed from GenState0). */ void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen); void FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx); #ifdef __cplusplus } #endif #endif systemd-229/src/journal/journal-authenticate.c000066400000000000000000000355421265713322000216250ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "fd-util.h" #include "fsprg.h" #include "hexdecoct.h" #include "journal-authenticate.h" #include "journal-def.h" #include "journal-file.h" static uint64_t journal_file_tag_seqnum(JournalFile *f) { uint64_t r; assert(f); r = le64toh(f->header->n_tags) + 1; f->header->n_tags = htole64(r); return r; } int journal_file_append_tag(JournalFile *f) { Object *o; uint64_t p; int r; assert(f); if (!f->seal) return 0; if (!f->hmac_running) return 0; assert(f->hmac); r = journal_file_append_object(f, OBJECT_TAG, sizeof(struct TagObject), &o, &p); if (r < 0) return r; o->tag.seqnum = htole64(journal_file_tag_seqnum(f)); o->tag.epoch = htole64(FSPRG_GetEpoch(f->fsprg_state)); log_debug("Writing tag %"PRIu64" for epoch %"PRIu64"", le64toh(o->tag.seqnum), FSPRG_GetEpoch(f->fsprg_state)); /* Add the tag object itself, so that we can protect its * header. This will exclude the actual hash value in it */ r = journal_file_hmac_put_object(f, OBJECT_TAG, o, p); if (r < 0) return r; /* Get the HMAC tag and store it in the object */ memcpy(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH); f->hmac_running = false; return 0; } int journal_file_hmac_start(JournalFile *f) { uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */ assert(f); if (!f->seal) return 0; if (f->hmac_running) return 0; /* Prepare HMAC for next cycle */ gcry_md_reset(f->hmac); FSPRG_GetKey(f->fsprg_state, key, sizeof(key), 0); gcry_md_setkey(f->hmac, key, sizeof(key)); f->hmac_running = true; return 0; } static int journal_file_get_epoch(JournalFile *f, uint64_t realtime, uint64_t *epoch) { uint64_t t; assert(f); assert(epoch); assert(f->seal); if (f->fss_start_usec == 0 || f->fss_interval_usec == 0) return -EOPNOTSUPP; if (realtime < f->fss_start_usec) return -ESTALE; t = realtime - f->fss_start_usec; t = t / f->fss_interval_usec; *epoch = t; return 0; } static int journal_file_fsprg_need_evolve(JournalFile *f, uint64_t realtime) { uint64_t goal, epoch; int r; assert(f); if (!f->seal) return 0; r = journal_file_get_epoch(f, realtime, &goal); if (r < 0) return r; epoch = FSPRG_GetEpoch(f->fsprg_state); if (epoch > goal) return -ESTALE; return epoch != goal; } int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime) { uint64_t goal, epoch; int r; assert(f); if (!f->seal) return 0; r = journal_file_get_epoch(f, realtime, &goal); if (r < 0) return r; epoch = FSPRG_GetEpoch(f->fsprg_state); if (epoch < goal) log_debug("Evolving FSPRG key from epoch %"PRIu64" to %"PRIu64".", epoch, goal); for (;;) { if (epoch > goal) return -ESTALE; if (epoch == goal) return 0; FSPRG_Evolve(f->fsprg_state); epoch = FSPRG_GetEpoch(f->fsprg_state); } } int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) { void *msk; uint64_t epoch; assert(f); if (!f->seal) return 0; assert(f->fsprg_seed); if (f->fsprg_state) { /* Cheaper... */ epoch = FSPRG_GetEpoch(f->fsprg_state); if (goal == epoch) return 0; if (goal == epoch+1) { FSPRG_Evolve(f->fsprg_state); return 0; } } else { f->fsprg_state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR); f->fsprg_state = malloc(f->fsprg_state_size); if (!f->fsprg_state) return -ENOMEM; } log_debug("Seeking FSPRG key to %"PRIu64".", goal); msk = alloca(FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR)); FSPRG_GenMK(msk, NULL, f->fsprg_seed, f->fsprg_seed_size, FSPRG_RECOMMENDED_SECPAR); FSPRG_Seek(f->fsprg_state, goal, msk, f->fsprg_seed, f->fsprg_seed_size); return 0; } int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) { int r; assert(f); if (!f->seal) return 0; if (realtime <= 0) realtime = now(CLOCK_REALTIME); r = journal_file_fsprg_need_evolve(f, realtime); if (r <= 0) return 0; r = journal_file_append_tag(f); if (r < 0) return r; r = journal_file_fsprg_evolve(f, realtime); if (r < 0) return r; return 0; } int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uint64_t p) { int r; assert(f); if (!f->seal) return 0; r = journal_file_hmac_start(f); if (r < 0) return r; if (!o) { r = journal_file_move_to_object(f, type, p, &o); if (r < 0) return r; } else { if (type > OBJECT_UNUSED && o->object.type != type) return -EBADMSG; } gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload)); switch (o->object.type) { case OBJECT_DATA: /* All but hash and payload are mutable */ gcry_md_write(f->hmac, &o->data.hash, sizeof(o->data.hash)); gcry_md_write(f->hmac, o->data.payload, le64toh(o->object.size) - offsetof(DataObject, payload)); break; case OBJECT_FIELD: /* Same here */ gcry_md_write(f->hmac, &o->field.hash, sizeof(o->field.hash)); gcry_md_write(f->hmac, o->field.payload, le64toh(o->object.size) - offsetof(FieldObject, payload)); break; case OBJECT_ENTRY: /* All */ gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(EntryObject, seqnum)); break; case OBJECT_FIELD_HASH_TABLE: case OBJECT_DATA_HASH_TABLE: case OBJECT_ENTRY_ARRAY: /* Nothing: everything is mutable */ break; case OBJECT_TAG: /* All but the tag itself */ gcry_md_write(f->hmac, &o->tag.seqnum, sizeof(o->tag.seqnum)); gcry_md_write(f->hmac, &o->tag.epoch, sizeof(o->tag.epoch)); break; default: return -EINVAL; } return 0; } int journal_file_hmac_put_header(JournalFile *f) { int r; assert(f); if (!f->seal) return 0; r = journal_file_hmac_start(f); if (r < 0) return r; /* All but state+reserved, boot_id, arena_size, * tail_object_offset, n_objects, n_entries, * tail_entry_seqnum, head_entry_seqnum, entry_array_offset, * head_entry_realtime, tail_entry_realtime, * tail_entry_monotonic, n_data, n_fields, n_tags, * n_entry_arrays. */ gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature)); gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, boot_id) - offsetof(Header, file_id)); gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id)); gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset)); return 0; } int journal_file_fss_load(JournalFile *f) { int r, fd = -1; char *p = NULL; struct stat st; FSSHeader *m = NULL; sd_id128_t machine; assert(f); if (!f->seal) return 0; r = sd_id128_get_machine(&machine); if (r < 0) return r; if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss", SD_ID128_FORMAT_VAL(machine)) < 0) return -ENOMEM; fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY, 0600); if (fd < 0) { if (errno != ENOENT) log_error_errno(errno, "Failed to open %s: %m", p); r = -errno; goto finish; } if (fstat(fd, &st) < 0) { r = -errno; goto finish; } if (st.st_size < (off_t) sizeof(FSSHeader)) { r = -ENODATA; goto finish; } m = mmap(NULL, PAGE_ALIGN(sizeof(FSSHeader)), PROT_READ, MAP_SHARED, fd, 0); if (m == MAP_FAILED) { m = NULL; r = -errno; goto finish; } if (memcmp(m->signature, FSS_HEADER_SIGNATURE, 8) != 0) { r = -EBADMSG; goto finish; } if (m->incompatible_flags != 0) { r = -EPROTONOSUPPORT; goto finish; } if (le64toh(m->header_size) < sizeof(FSSHeader)) { r = -EBADMSG; goto finish; } if (le64toh(m->fsprg_state_size) != FSPRG_stateinbytes(le16toh(m->fsprg_secpar))) { r = -EBADMSG; goto finish; } f->fss_file_size = le64toh(m->header_size) + le64toh(m->fsprg_state_size); if ((uint64_t) st.st_size < f->fss_file_size) { r = -ENODATA; goto finish; } if (!sd_id128_equal(machine, m->machine_id)) { r = -EHOSTDOWN; goto finish; } if (le64toh(m->start_usec) <= 0 || le64toh(m->interval_usec) <= 0) { r = -EBADMSG; goto finish; } f->fss_file = mmap(NULL, PAGE_ALIGN(f->fss_file_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (f->fss_file == MAP_FAILED) { f->fss_file = NULL; r = -errno; goto finish; } f->fss_start_usec = le64toh(f->fss_file->start_usec); f->fss_interval_usec = le64toh(f->fss_file->interval_usec); f->fsprg_state = (uint8_t*) f->fss_file + le64toh(f->fss_file->header_size); f->fsprg_state_size = le64toh(f->fss_file->fsprg_state_size); r = 0; finish: if (m) munmap(m, PAGE_ALIGN(sizeof(FSSHeader))); safe_close(fd); free(p); return r; } static void initialize_libgcrypt(void) { const char *p; if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P)) return; p = gcry_check_version("1.4.5"); assert(p); gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); } int journal_file_hmac_setup(JournalFile *f) { gcry_error_t e; if (!f->seal) return 0; initialize_libgcrypt(); e = gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); if (e != 0) return -EOPNOTSUPP; return 0; } int journal_file_append_first_tag(JournalFile *f) { int r; uint64_t p; if (!f->seal) return 0; log_debug("Calculating first tag..."); r = journal_file_hmac_put_header(f); if (r < 0) return r; p = le64toh(f->header->field_hash_table_offset); if (p < offsetof(Object, hash_table.items)) return -EINVAL; p -= offsetof(Object, hash_table.items); r = journal_file_hmac_put_object(f, OBJECT_FIELD_HASH_TABLE, NULL, p); if (r < 0) return r; p = le64toh(f->header->data_hash_table_offset); if (p < offsetof(Object, hash_table.items)) return -EINVAL; p -= offsetof(Object, hash_table.items); r = journal_file_hmac_put_object(f, OBJECT_DATA_HASH_TABLE, NULL, p); if (r < 0) return r; r = journal_file_append_tag(f); if (r < 0) return r; return 0; } int journal_file_parse_verification_key(JournalFile *f, const char *key) { uint8_t *seed; size_t seed_size, c; const char *k; int r; unsigned long long start, interval; seed_size = FSPRG_RECOMMENDED_SEEDLEN; seed = malloc(seed_size); if (!seed) return -ENOMEM; k = key; for (c = 0; c < seed_size; c++) { int x, y; while (*k == '-') k++; x = unhexchar(*k); if (x < 0) { free(seed); return -EINVAL; } k++; y = unhexchar(*k); if (y < 0) { free(seed); return -EINVAL; } k++; seed[c] = (uint8_t) (x * 16 + y); } if (*k != '/') { free(seed); return -EINVAL; } k++; r = sscanf(k, "%llx-%llx", &start, &interval); if (r != 2) { free(seed); return -EINVAL; } f->fsprg_seed = seed; f->fsprg_seed_size = seed_size; f->fss_start_usec = start * interval; f->fss_interval_usec = interval; return 0; } bool journal_file_next_evolve_usec(JournalFile *f, usec_t *u) { uint64_t epoch; assert(f); assert(u); if (!f->seal) return false; epoch = FSPRG_GetEpoch(f->fsprg_state); *u = (usec_t) (f->fss_start_usec + f->fss_interval_usec * epoch + f->fss_interval_usec); return true; } systemd-229/src/journal/journal-authenticate.h000066400000000000000000000027211265713322000216230ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "journal-file.h" int journal_file_append_tag(JournalFile *f); int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime); int journal_file_append_first_tag(JournalFile *f); int journal_file_hmac_setup(JournalFile *f); int journal_file_hmac_start(JournalFile *f); int journal_file_hmac_put_header(JournalFile *f); int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uint64_t p); int journal_file_fss_load(JournalFile *f); int journal_file_parse_verification_key(JournalFile *f, const char *key); int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime); int journal_file_fsprg_seek(JournalFile *f, uint64_t epoch); bool journal_file_next_evolve_usec(JournalFile *f, usec_t *u); systemd-229/src/journal/journal-def.h000066400000000000000000000140671265713322000177110ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-id128.h" #include "macro.h" #include "sparse-endian.h" /* * If you change this file you probably should also change its documentation: * * http://www.freedesktop.org/wiki/Software/systemd/journal-files * */ typedef struct Header Header; typedef struct ObjectHeader ObjectHeader; typedef union Object Object; typedef struct DataObject DataObject; typedef struct FieldObject FieldObject; typedef struct EntryObject EntryObject; typedef struct HashTableObject HashTableObject; typedef struct EntryArrayObject EntryArrayObject; typedef struct TagObject TagObject; typedef struct EntryItem EntryItem; typedef struct HashItem HashItem; typedef struct FSSHeader FSSHeader; /* Object types */ typedef enum ObjectType { OBJECT_UNUSED, /* also serves as "any type" or "additional context" */ OBJECT_DATA, OBJECT_FIELD, OBJECT_ENTRY, OBJECT_DATA_HASH_TABLE, OBJECT_FIELD_HASH_TABLE, OBJECT_ENTRY_ARRAY, OBJECT_TAG, _OBJECT_TYPE_MAX } ObjectType; /* Object flags */ enum { OBJECT_COMPRESSED_XZ = 1 << 0, OBJECT_COMPRESSED_LZ4 = 1 << 1, _OBJECT_COMPRESSED_MAX }; #define OBJECT_COMPRESSION_MASK (OBJECT_COMPRESSED_XZ | OBJECT_COMPRESSED_LZ4) struct ObjectHeader { uint8_t type; uint8_t flags; uint8_t reserved[6]; le64_t size; uint8_t payload[]; } _packed_; struct DataObject { ObjectHeader object; le64_t hash; le64_t next_hash_offset; le64_t next_field_offset; le64_t entry_offset; /* the first array entry we store inline */ le64_t entry_array_offset; le64_t n_entries; uint8_t payload[]; } _packed_; struct FieldObject { ObjectHeader object; le64_t hash; le64_t next_hash_offset; le64_t head_data_offset; uint8_t payload[]; } _packed_; struct EntryItem { le64_t object_offset; le64_t hash; } _packed_; struct EntryObject { ObjectHeader object; le64_t seqnum; le64_t realtime; le64_t monotonic; sd_id128_t boot_id; le64_t xor_hash; EntryItem items[]; } _packed_; struct HashItem { le64_t head_hash_offset; le64_t tail_hash_offset; } _packed_; struct HashTableObject { ObjectHeader object; HashItem items[]; } _packed_; struct EntryArrayObject { ObjectHeader object; le64_t next_entry_array_offset; le64_t items[]; } _packed_; #define TAG_LENGTH (256/8) struct TagObject { ObjectHeader object; le64_t seqnum; le64_t epoch; uint8_t tag[TAG_LENGTH]; /* SHA-256 HMAC */ } _packed_; union Object { ObjectHeader object; DataObject data; FieldObject field; EntryObject entry; HashTableObject hash_table; EntryArrayObject entry_array; TagObject tag; }; enum { STATE_OFFLINE = 0, STATE_ONLINE = 1, STATE_ARCHIVED = 2, _STATE_MAX }; /* Header flags */ enum { HEADER_INCOMPATIBLE_COMPRESSED_XZ = 1 << 0, HEADER_INCOMPATIBLE_COMPRESSED_LZ4 = 1 << 1, }; #define HEADER_INCOMPATIBLE_ANY (HEADER_INCOMPATIBLE_COMPRESSED_XZ|HEADER_INCOMPATIBLE_COMPRESSED_LZ4) #if defined(HAVE_XZ) && defined(HAVE_LZ4) # define HEADER_INCOMPATIBLE_SUPPORTED HEADER_INCOMPATIBLE_ANY #elif defined(HAVE_XZ) # define HEADER_INCOMPATIBLE_SUPPORTED HEADER_INCOMPATIBLE_COMPRESSED_XZ #elif defined(HAVE_LZ4) # define HEADER_INCOMPATIBLE_SUPPORTED HEADER_INCOMPATIBLE_COMPRESSED_LZ4 #else # define HEADER_INCOMPATIBLE_SUPPORTED 0 #endif enum { HEADER_COMPATIBLE_SEALED = 1 }; #define HEADER_COMPATIBLE_ANY HEADER_COMPATIBLE_SEALED #ifdef HAVE_GCRYPT # define HEADER_COMPATIBLE_SUPPORTED HEADER_COMPATIBLE_SEALED #else # define HEADER_COMPATIBLE_SUPPORTED 0 #endif #define HEADER_SIGNATURE ((char[]) { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }) struct Header { uint8_t signature[8]; /* "LPKSHHRH" */ le32_t compatible_flags; le32_t incompatible_flags; uint8_t state; uint8_t reserved[7]; sd_id128_t file_id; sd_id128_t machine_id; sd_id128_t boot_id; /* last writer */ sd_id128_t seqnum_id; le64_t header_size; le64_t arena_size; le64_t data_hash_table_offset; le64_t data_hash_table_size; le64_t field_hash_table_offset; le64_t field_hash_table_size; le64_t tail_object_offset; le64_t n_objects; le64_t n_entries; le64_t tail_entry_seqnum; le64_t head_entry_seqnum; le64_t entry_array_offset; le64_t head_entry_realtime; le64_t tail_entry_realtime; le64_t tail_entry_monotonic; /* Added in 187 */ le64_t n_data; le64_t n_fields; /* Added in 189 */ le64_t n_tags; le64_t n_entry_arrays; /* Size: 240 */ } _packed_; #define FSS_HEADER_SIGNATURE ((char[]) { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' }) struct FSSHeader { uint8_t signature[8]; /* "KSHHRHLP" */ le32_t compatible_flags; le32_t incompatible_flags; sd_id128_t machine_id; sd_id128_t boot_id; /* last writer */ le64_t header_size; le64_t start_usec; le64_t interval_usec; le16_t fsprg_secpar; le16_t reserved[3]; le64_t fsprg_state_size; } _packed_; systemd-229/src/journal/journal-file.c000066400000000000000000003177601265713322000200730ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "btrfs-util.h" #include "chattr-util.h" #include "compress.h" #include "fd-util.h" #include "journal-authenticate.h" #include "journal-def.h" #include "journal-file.h" #include "lookup3.h" #include "parse-util.h" #include "random-util.h" #include "sd-event.h" #include "string-util.h" #include "xattr-util.h" #define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem)) #define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem)) #define COMPRESSION_SIZE_THRESHOLD (512ULL) /* This is the minimum journal file size */ #define JOURNAL_FILE_SIZE_MIN (512ULL*1024ULL) /* 512 KiB */ /* These are the lower and upper bounds if we deduce the max_use value * from the file system size */ #define DEFAULT_MAX_USE_LOWER (1ULL*1024ULL*1024ULL) /* 1 MiB */ #define DEFAULT_MAX_USE_UPPER (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */ /* This is the default minimal use limit, how much we'll use even if keep_free suggests otherwise. */ #define DEFAULT_MIN_USE (1ULL*1024ULL*1024ULL) /* 1 MiB */ /* This is the upper bound if we deduce max_size from max_use */ #define DEFAULT_MAX_SIZE_UPPER (128ULL*1024ULL*1024ULL) /* 128 MiB */ /* This is the upper bound if we deduce the keep_free value from the * file system size */ #define DEFAULT_KEEP_FREE_UPPER (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */ /* This is the keep_free value when we can't determine the system * size */ #define DEFAULT_KEEP_FREE (1024ULL*1024ULL) /* 1 MB */ /* This is the default maximum number of journal files to keep around. */ #define DEFAULT_N_MAX_FILES (100) /* n_data was the first entry we added after the initial file format design */ #define HEADER_SIZE_MIN ALIGN64(offsetof(Header, n_data)) /* How many entries to keep in the entry array chain cache at max */ #define CHAIN_CACHE_MAX 20 /* How much to increase the journal file size at once each time we allocate something new. */ #define FILE_SIZE_INCREASE (8ULL*1024ULL*1024ULL) /* 8MB */ /* Reread fstat() of the file for detecting deletions at least this often */ #define LAST_STAT_REFRESH_USEC (5*USEC_PER_SEC) /* The mmap context to use for the header we pick as one above the last defined typed */ #define CONTEXT_HEADER _OBJECT_TYPE_MAX static int journal_file_set_online(JournalFile *f) { assert(f); if (!f->writable) return -EPERM; if (!(f->fd >= 0 && f->header)) return -EINVAL; if (mmap_cache_got_sigbus(f->mmap, f->fd)) return -EIO; switch (f->header->state) { case STATE_ONLINE: return 0; case STATE_OFFLINE: f->header->state = STATE_ONLINE; fsync(f->fd); return 0; default: return -EINVAL; } } int journal_file_set_offline(JournalFile *f) { assert(f); if (!f->writable) return -EPERM; if (!(f->fd >= 0 && f->header)) return -EINVAL; if (f->header->state != STATE_ONLINE) return 0; fsync(f->fd); if (mmap_cache_got_sigbus(f->mmap, f->fd)) return -EIO; f->header->state = STATE_OFFLINE; if (mmap_cache_got_sigbus(f->mmap, f->fd)) return -EIO; fsync(f->fd); return 0; } JournalFile* journal_file_close(JournalFile *f) { assert(f); #ifdef HAVE_GCRYPT /* Write the final tag */ if (f->seal && f->writable) journal_file_append_tag(f); #endif if (f->post_change_timer) { int enabled; if (sd_event_source_get_enabled(f->post_change_timer, &enabled) >= 0) if (enabled == SD_EVENT_ONESHOT) journal_file_post_change(f); (void) sd_event_source_set_enabled(f->post_change_timer, SD_EVENT_OFF); sd_event_source_unref(f->post_change_timer); } journal_file_set_offline(f); if (f->mmap && f->fd >= 0) mmap_cache_close_fd(f->mmap, f->fd); if (f->fd >= 0 && f->defrag_on_close) { /* Be friendly to btrfs: turn COW back on again now, * and defragment the file. We won't write to the file * ever again, hence remove all fragmentation, and * reenable all the good bits COW usually provides * (such as data checksumming). */ (void) chattr_fd(f->fd, 0, FS_NOCOW_FL); (void) btrfs_defrag_fd(f->fd); } safe_close(f->fd); free(f->path); mmap_cache_unref(f->mmap); ordered_hashmap_free_free(f->chain_cache); #if defined(HAVE_XZ) || defined(HAVE_LZ4) free(f->compress_buffer); #endif #ifdef HAVE_GCRYPT if (f->fss_file) munmap(f->fss_file, PAGE_ALIGN(f->fss_file_size)); else free(f->fsprg_state); free(f->fsprg_seed); if (f->hmac) gcry_md_close(f->hmac); #endif free(f); return NULL; } static int journal_file_init_header(JournalFile *f, JournalFile *template) { Header h = {}; ssize_t k; int r; assert(f); memcpy(h.signature, HEADER_SIGNATURE, 8); h.header_size = htole64(ALIGN64(sizeof(h))); h.incompatible_flags |= htole32( f->compress_xz * HEADER_INCOMPATIBLE_COMPRESSED_XZ | f->compress_lz4 * HEADER_INCOMPATIBLE_COMPRESSED_LZ4); h.compatible_flags = htole32( f->seal * HEADER_COMPATIBLE_SEALED); r = sd_id128_randomize(&h.file_id); if (r < 0) return r; if (template) { h.seqnum_id = template->header->seqnum_id; h.tail_entry_seqnum = template->header->tail_entry_seqnum; } else h.seqnum_id = h.file_id; k = pwrite(f->fd, &h, sizeof(h), 0); if (k < 0) return -errno; if (k != sizeof(h)) return -EIO; return 0; } static int journal_file_refresh_header(JournalFile *f) { sd_id128_t boot_id; int r; assert(f); assert(f->header); r = sd_id128_get_machine(&f->header->machine_id); if (r < 0) return r; r = sd_id128_get_boot(&boot_id); if (r < 0) return r; if (sd_id128_equal(boot_id, f->header->boot_id)) f->tail_entry_monotonic_valid = true; f->header->boot_id = boot_id; r = journal_file_set_online(f); /* Sync the online state to disk */ fsync(f->fd); return r; } static int journal_file_verify_header(JournalFile *f) { uint32_t flags; assert(f); assert(f->header); if (memcmp(f->header->signature, HEADER_SIGNATURE, 8)) return -EBADMSG; /* In both read and write mode we refuse to open files with * incompatible flags we don't know */ flags = le32toh(f->header->incompatible_flags); if (flags & ~HEADER_INCOMPATIBLE_SUPPORTED) { if (flags & ~HEADER_INCOMPATIBLE_ANY) log_debug("Journal file %s has unknown incompatible flags %"PRIx32, f->path, flags & ~HEADER_INCOMPATIBLE_ANY); flags = (flags & HEADER_INCOMPATIBLE_ANY) & ~HEADER_INCOMPATIBLE_SUPPORTED; if (flags) log_debug("Journal file %s uses incompatible flags %"PRIx32 " disabled at compilation time.", f->path, flags); return -EPROTONOSUPPORT; } /* When open for writing we refuse to open files with * compatible flags, too */ flags = le32toh(f->header->compatible_flags); if (f->writable && (flags & ~HEADER_COMPATIBLE_SUPPORTED)) { if (flags & ~HEADER_COMPATIBLE_ANY) log_debug("Journal file %s has unknown compatible flags %"PRIx32, f->path, flags & ~HEADER_COMPATIBLE_ANY); flags = (flags & HEADER_COMPATIBLE_ANY) & ~HEADER_COMPATIBLE_SUPPORTED; if (flags) log_debug("Journal file %s uses compatible flags %"PRIx32 " disabled at compilation time.", f->path, flags); return -EPROTONOSUPPORT; } if (f->header->state >= _STATE_MAX) return -EBADMSG; /* The first addition was n_data, so check that we are at least this large */ if (le64toh(f->header->header_size) < HEADER_SIZE_MIN) return -EBADMSG; if (JOURNAL_HEADER_SEALED(f->header) && !JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays)) return -EBADMSG; if ((le64toh(f->header->header_size) + le64toh(f->header->arena_size)) > (uint64_t) f->last_stat.st_size) return -ENODATA; if (le64toh(f->header->tail_object_offset) > (le64toh(f->header->header_size) + le64toh(f->header->arena_size))) return -ENODATA; if (!VALID64(le64toh(f->header->data_hash_table_offset)) || !VALID64(le64toh(f->header->field_hash_table_offset)) || !VALID64(le64toh(f->header->tail_object_offset)) || !VALID64(le64toh(f->header->entry_array_offset))) return -ENODATA; if (f->writable) { uint8_t state; sd_id128_t machine_id; int r; r = sd_id128_get_machine(&machine_id); if (r < 0) return r; if (!sd_id128_equal(machine_id, f->header->machine_id)) return -EHOSTDOWN; state = f->header->state; if (state == STATE_ONLINE) { log_debug("Journal file %s is already online. Assuming unclean closing.", f->path); return -EBUSY; } else if (state == STATE_ARCHIVED) return -ESHUTDOWN; else if (state != STATE_OFFLINE) { log_debug("Journal file %s has unknown state %i.", f->path, state); return -EBUSY; } } f->compress_xz = JOURNAL_HEADER_COMPRESSED_XZ(f->header); f->compress_lz4 = JOURNAL_HEADER_COMPRESSED_LZ4(f->header); f->seal = JOURNAL_HEADER_SEALED(f->header); return 0; } static int journal_file_fstat(JournalFile *f) { assert(f); assert(f->fd >= 0); if (fstat(f->fd, &f->last_stat) < 0) return -errno; f->last_stat_usec = now(CLOCK_MONOTONIC); /* Refuse appending to files that are already deleted */ if (f->last_stat.st_nlink <= 0) return -EIDRM; return 0; } static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) { uint64_t old_size, new_size; int r; assert(f); assert(f->header); /* We assume that this file is not sparse, and we know that * for sure, since we always call posix_fallocate() * ourselves */ if (mmap_cache_got_sigbus(f->mmap, f->fd)) return -EIO; old_size = le64toh(f->header->header_size) + le64toh(f->header->arena_size); new_size = PAGE_ALIGN(offset + size); if (new_size < le64toh(f->header->header_size)) new_size = le64toh(f->header->header_size); if (new_size <= old_size) { /* We already pre-allocated enough space, but before * we write to it, let's check with fstat() if the * file got deleted, in order make sure we don't throw * away the data immediately. Don't check fstat() for * all writes though, but only once ever 10s. */ if (f->last_stat_usec + LAST_STAT_REFRESH_USEC > now(CLOCK_MONOTONIC)) return 0; return journal_file_fstat(f); } /* Allocate more space. */ if (f->metrics.max_size > 0 && new_size > f->metrics.max_size) return -E2BIG; if (new_size > f->metrics.min_size && f->metrics.keep_free > 0) { struct statvfs svfs; if (fstatvfs(f->fd, &svfs) >= 0) { uint64_t available; available = LESS_BY((uint64_t) svfs.f_bfree * (uint64_t) svfs.f_bsize, f->metrics.keep_free); if (new_size - old_size > available) return -E2BIG; } } /* Increase by larger blocks at once */ new_size = ((new_size+FILE_SIZE_INCREASE-1) / FILE_SIZE_INCREASE) * FILE_SIZE_INCREASE; if (f->metrics.max_size > 0 && new_size > f->metrics.max_size) new_size = f->metrics.max_size; /* Note that the glibc fallocate() fallback is very inefficient, hence we try to minimize the allocation area as we can. */ r = posix_fallocate(f->fd, old_size, new_size - old_size); if (r != 0) return -r; f->header->arena_size = htole64(new_size - le64toh(f->header->header_size)); return journal_file_fstat(f); } static unsigned type_to_context(ObjectType type) { /* One context for each type, plus one catch-all for the rest */ assert_cc(_OBJECT_TYPE_MAX <= MMAP_CACHE_MAX_CONTEXTS); assert_cc(CONTEXT_HEADER < MMAP_CACHE_MAX_CONTEXTS); return type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX ? type : 0; } static int journal_file_move_to(JournalFile *f, ObjectType type, bool keep_always, uint64_t offset, uint64_t size, void **ret) { int r; assert(f); assert(ret); if (size <= 0) return -EINVAL; /* Avoid SIGBUS on invalid accesses */ if (offset + size > (uint64_t) f->last_stat.st_size) { /* Hmm, out of range? Let's refresh the fstat() data * first, before we trust that check. */ r = journal_file_fstat(f); if (r < 0) return r; if (offset + size > (uint64_t) f->last_stat.st_size) return -EADDRNOTAVAIL; } return mmap_cache_get(f->mmap, f->fd, f->prot, type_to_context(type), keep_always, offset, size, &f->last_stat, ret); } static uint64_t minimum_header_size(Object *o) { static const uint64_t table[] = { [OBJECT_DATA] = sizeof(DataObject), [OBJECT_FIELD] = sizeof(FieldObject), [OBJECT_ENTRY] = sizeof(EntryObject), [OBJECT_DATA_HASH_TABLE] = sizeof(HashTableObject), [OBJECT_FIELD_HASH_TABLE] = sizeof(HashTableObject), [OBJECT_ENTRY_ARRAY] = sizeof(EntryArrayObject), [OBJECT_TAG] = sizeof(TagObject), }; if (o->object.type >= ELEMENTSOF(table) || table[o->object.type] <= 0) return sizeof(ObjectHeader); return table[o->object.type]; } int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret) { int r; void *t; Object *o; uint64_t s; assert(f); assert(ret); /* Objects may only be located at multiple of 64 bit */ if (!VALID64(offset)) return -EFAULT; r = journal_file_move_to(f, type, false, offset, sizeof(ObjectHeader), &t); if (r < 0) return r; o = (Object*) t; s = le64toh(o->object.size); if (s < sizeof(ObjectHeader)) return -EBADMSG; if (o->object.type <= OBJECT_UNUSED) return -EBADMSG; if (s < minimum_header_size(o)) return -EBADMSG; if (type > OBJECT_UNUSED && o->object.type != type) return -EBADMSG; if (s > sizeof(ObjectHeader)) { r = journal_file_move_to(f, type, false, offset, s, &t); if (r < 0) return r; o = (Object*) t; } *ret = o; return 0; } static uint64_t journal_file_entry_seqnum(JournalFile *f, uint64_t *seqnum) { uint64_t r; assert(f); assert(f->header); r = le64toh(f->header->tail_entry_seqnum) + 1; if (seqnum) { /* If an external seqnum counter was passed, we update * both the local and the external one, and set it to * the maximum of both */ if (*seqnum + 1 > r) r = *seqnum + 1; *seqnum = r; } f->header->tail_entry_seqnum = htole64(r); if (f->header->head_entry_seqnum == 0) f->header->head_entry_seqnum = htole64(r); return r; } int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *offset) { int r; uint64_t p; Object *tail, *o; void *t; assert(f); assert(f->header); assert(type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX); assert(size >= sizeof(ObjectHeader)); assert(offset); assert(ret); r = journal_file_set_online(f); if (r < 0) return r; p = le64toh(f->header->tail_object_offset); if (p == 0) p = le64toh(f->header->header_size); else { r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &tail); if (r < 0) return r; p += ALIGN64(le64toh(tail->object.size)); } r = journal_file_allocate(f, p, size); if (r < 0) return r; r = journal_file_move_to(f, type, false, p, size, &t); if (r < 0) return r; o = (Object*) t; zero(o->object); o->object.type = type; o->object.size = htole64(size); f->header->tail_object_offset = htole64(p); f->header->n_objects = htole64(le64toh(f->header->n_objects) + 1); *ret = o; *offset = p; return 0; } static int journal_file_setup_data_hash_table(JournalFile *f) { uint64_t s, p; Object *o; int r; assert(f); assert(f->header); /* We estimate that we need 1 hash table entry per 768 bytes of journal file and we want to make sure we never get beyond 75% fill level. Calculate the hash table size for the maximum file size based on these metrics. */ s = (f->metrics.max_size * 4 / 768 / 3) * sizeof(HashItem); if (s < DEFAULT_DATA_HASH_TABLE_SIZE) s = DEFAULT_DATA_HASH_TABLE_SIZE; log_debug("Reserving %"PRIu64" entries in hash table.", s / sizeof(HashItem)); r = journal_file_append_object(f, OBJECT_DATA_HASH_TABLE, offsetof(Object, hash_table.items) + s, &o, &p); if (r < 0) return r; memzero(o->hash_table.items, s); f->header->data_hash_table_offset = htole64(p + offsetof(Object, hash_table.items)); f->header->data_hash_table_size = htole64(s); return 0; } static int journal_file_setup_field_hash_table(JournalFile *f) { uint64_t s, p; Object *o; int r; assert(f); assert(f->header); /* We use a fixed size hash table for the fields as this * number should grow very slowly only */ s = DEFAULT_FIELD_HASH_TABLE_SIZE; r = journal_file_append_object(f, OBJECT_FIELD_HASH_TABLE, offsetof(Object, hash_table.items) + s, &o, &p); if (r < 0) return r; memzero(o->hash_table.items, s); f->header->field_hash_table_offset = htole64(p + offsetof(Object, hash_table.items)); f->header->field_hash_table_size = htole64(s); return 0; } int journal_file_map_data_hash_table(JournalFile *f) { uint64_t s, p; void *t; int r; assert(f); assert(f->header); if (f->data_hash_table) return 0; p = le64toh(f->header->data_hash_table_offset); s = le64toh(f->header->data_hash_table_size); r = journal_file_move_to(f, OBJECT_DATA_HASH_TABLE, true, p, s, &t); if (r < 0) return r; f->data_hash_table = t; return 0; } int journal_file_map_field_hash_table(JournalFile *f) { uint64_t s, p; void *t; int r; assert(f); assert(f->header); if (f->field_hash_table) return 0; p = le64toh(f->header->field_hash_table_offset); s = le64toh(f->header->field_hash_table_size); r = journal_file_move_to(f, OBJECT_FIELD_HASH_TABLE, true, p, s, &t); if (r < 0) return r; f->field_hash_table = t; return 0; } static int journal_file_link_field( JournalFile *f, Object *o, uint64_t offset, uint64_t hash) { uint64_t p, h, m; int r; assert(f); assert(f->header); assert(f->field_hash_table); assert(o); assert(offset > 0); if (o->object.type != OBJECT_FIELD) return -EINVAL; m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem); if (m <= 0) return -EBADMSG; /* This might alter the window we are looking at */ o->field.next_hash_offset = o->field.head_data_offset = 0; h = hash % m; p = le64toh(f->field_hash_table[h].tail_hash_offset); if (p == 0) f->field_hash_table[h].head_hash_offset = htole64(offset); else { r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o); if (r < 0) return r; o->field.next_hash_offset = htole64(offset); } f->field_hash_table[h].tail_hash_offset = htole64(offset); if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)) f->header->n_fields = htole64(le64toh(f->header->n_fields) + 1); return 0; } static int journal_file_link_data( JournalFile *f, Object *o, uint64_t offset, uint64_t hash) { uint64_t p, h, m; int r; assert(f); assert(f->header); assert(f->data_hash_table); assert(o); assert(offset > 0); if (o->object.type != OBJECT_DATA) return -EINVAL; m = le64toh(f->header->data_hash_table_size) / sizeof(HashItem); if (m <= 0) return -EBADMSG; /* This might alter the window we are looking at */ o->data.next_hash_offset = o->data.next_field_offset = 0; o->data.entry_offset = o->data.entry_array_offset = 0; o->data.n_entries = 0; h = hash % m; p = le64toh(f->data_hash_table[h].tail_hash_offset); if (p == 0) /* Only entry in the hash table is easy */ f->data_hash_table[h].head_hash_offset = htole64(offset); else { /* Move back to the previous data object, to patch in * pointer */ r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; o->data.next_hash_offset = htole64(offset); } f->data_hash_table[h].tail_hash_offset = htole64(offset); if (JOURNAL_HEADER_CONTAINS(f->header, n_data)) f->header->n_data = htole64(le64toh(f->header->n_data) + 1); return 0; } int journal_file_find_field_object_with_hash( JournalFile *f, const void *field, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset) { uint64_t p, osize, h, m; int r; assert(f); assert(f->header); assert(field && size > 0); /* If the field hash table is empty, we can't find anything */ if (le64toh(f->header->field_hash_table_size) <= 0) return 0; /* Map the field hash table, if it isn't mapped yet. */ r = journal_file_map_field_hash_table(f); if (r < 0) return r; osize = offsetof(Object, field.payload) + size; m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem); if (m <= 0) return -EBADMSG; h = hash % m; p = le64toh(f->field_hash_table[h].head_hash_offset); while (p > 0) { Object *o; r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o); if (r < 0) return r; if (le64toh(o->field.hash) == hash && le64toh(o->object.size) == osize && memcmp(o->field.payload, field, size) == 0) { if (ret) *ret = o; if (offset) *offset = p; return 1; } p = le64toh(o->field.next_hash_offset); } return 0; } int journal_file_find_field_object( JournalFile *f, const void *field, uint64_t size, Object **ret, uint64_t *offset) { uint64_t hash; assert(f); assert(field && size > 0); hash = hash64(field, size); return journal_file_find_field_object_with_hash(f, field, size, hash, ret, offset); } int journal_file_find_data_object_with_hash( JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset) { uint64_t p, osize, h, m; int r; assert(f); assert(f->header); assert(data || size == 0); /* If there's no data hash table, then there's no entry. */ if (le64toh(f->header->data_hash_table_size) <= 0) return 0; /* Map the data hash table, if it isn't mapped yet. */ r = journal_file_map_data_hash_table(f); if (r < 0) return r; osize = offsetof(Object, data.payload) + size; m = le64toh(f->header->data_hash_table_size) / sizeof(HashItem); if (m <= 0) return -EBADMSG; h = hash % m; p = le64toh(f->data_hash_table[h].head_hash_offset); while (p > 0) { Object *o; r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; if (le64toh(o->data.hash) != hash) goto next; if (o->object.flags & OBJECT_COMPRESSION_MASK) { #if defined(HAVE_XZ) || defined(HAVE_LZ4) uint64_t l; size_t rsize = 0; l = le64toh(o->object.size); if (l <= offsetof(Object, data.payload)) return -EBADMSG; l -= offsetof(Object, data.payload); r = decompress_blob(o->object.flags & OBJECT_COMPRESSION_MASK, o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize, 0); if (r < 0) return r; if (rsize == size && memcmp(f->compress_buffer, data, size) == 0) { if (ret) *ret = o; if (offset) *offset = p; return 1; } #else return -EPROTONOSUPPORT; #endif } else if (le64toh(o->object.size) == osize && memcmp(o->data.payload, data, size) == 0) { if (ret) *ret = o; if (offset) *offset = p; return 1; } next: p = le64toh(o->data.next_hash_offset); } return 0; } int journal_file_find_data_object( JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) { uint64_t hash; assert(f); assert(data || size == 0); hash = hash64(data, size); return journal_file_find_data_object_with_hash(f, data, size, hash, ret, offset); } static int journal_file_append_field( JournalFile *f, const void *field, uint64_t size, Object **ret, uint64_t *offset) { uint64_t hash, p; uint64_t osize; Object *o; int r; assert(f); assert(field && size > 0); hash = hash64(field, size); r = journal_file_find_field_object_with_hash(f, field, size, hash, &o, &p); if (r < 0) return r; else if (r > 0) { if (ret) *ret = o; if (offset) *offset = p; return 0; } osize = offsetof(Object, field.payload) + size; r = journal_file_append_object(f, OBJECT_FIELD, osize, &o, &p); if (r < 0) return r; o->field.hash = htole64(hash); memcpy(o->field.payload, field, size); r = journal_file_link_field(f, o, p, hash); if (r < 0) return r; /* The linking might have altered the window, so let's * refresh our pointer */ r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o); if (r < 0) return r; #ifdef HAVE_GCRYPT r = journal_file_hmac_put_object(f, OBJECT_FIELD, o, p); if (r < 0) return r; #endif if (ret) *ret = o; if (offset) *offset = p; return 0; } static int journal_file_append_data( JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) { uint64_t hash, p; uint64_t osize; Object *o; int r, compression = 0; const void *eq; assert(f); assert(data || size == 0); hash = hash64(data, size); r = journal_file_find_data_object_with_hash(f, data, size, hash, &o, &p); if (r < 0) return r; if (r > 0) { if (ret) *ret = o; if (offset) *offset = p; return 0; } osize = offsetof(Object, data.payload) + size; r = journal_file_append_object(f, OBJECT_DATA, osize, &o, &p); if (r < 0) return r; o->data.hash = htole64(hash); #if defined(HAVE_XZ) || defined(HAVE_LZ4) if (JOURNAL_FILE_COMPRESS(f) && size >= COMPRESSION_SIZE_THRESHOLD) { size_t rsize = 0; compression = compress_blob(data, size, o->data.payload, size - 1, &rsize); if (compression >= 0) { o->object.size = htole64(offsetof(Object, data.payload) + rsize); o->object.flags |= compression; log_debug("Compressed data object %"PRIu64" -> %zu using %s", size, rsize, object_compressed_to_string(compression)); } else /* Compression didn't work, we don't really care why, let's continue without compression */ compression = 0; } #endif if (compression == 0 && size > 0) memcpy(o->data.payload, data, size); r = journal_file_link_data(f, o, p, hash); if (r < 0) return r; /* The linking might have altered the window, so let's * refresh our pointer */ r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; if (!data) eq = NULL; else eq = memchr(data, '=', size); if (eq && eq > data) { Object *fo = NULL; uint64_t fp; /* Create field object ... */ r = journal_file_append_field(f, data, (uint8_t*) eq - (uint8_t*) data, &fo, &fp); if (r < 0) return r; /* ... and link it in. */ o->data.next_field_offset = fo->field.head_data_offset; fo->field.head_data_offset = le64toh(p); } #ifdef HAVE_GCRYPT r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p); if (r < 0) return r; #endif if (ret) *ret = o; if (offset) *offset = p; return 0; } uint64_t journal_file_entry_n_items(Object *o) { assert(o); if (o->object.type != OBJECT_ENTRY) return 0; return (le64toh(o->object.size) - offsetof(Object, entry.items)) / sizeof(EntryItem); } uint64_t journal_file_entry_array_n_items(Object *o) { assert(o); if (o->object.type != OBJECT_ENTRY_ARRAY) return 0; return (le64toh(o->object.size) - offsetof(Object, entry_array.items)) / sizeof(uint64_t); } uint64_t journal_file_hash_table_n_items(Object *o) { assert(o); if (o->object.type != OBJECT_DATA_HASH_TABLE && o->object.type != OBJECT_FIELD_HASH_TABLE) return 0; return (le64toh(o->object.size) - offsetof(Object, hash_table.items)) / sizeof(HashItem); } static int link_entry_into_array(JournalFile *f, le64_t *first, le64_t *idx, uint64_t p) { int r; uint64_t n = 0, ap = 0, q, i, a, hidx; Object *o; assert(f); assert(f->header); assert(first); assert(idx); assert(p > 0); a = le64toh(*first); i = hidx = le64toh(*idx); while (a > 0) { r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); if (r < 0) return r; n = journal_file_entry_array_n_items(o); if (i < n) { o->entry_array.items[i] = htole64(p); *idx = htole64(hidx + 1); return 0; } i -= n; ap = a; a = le64toh(o->entry_array.next_entry_array_offset); } if (hidx > n) n = (hidx+1) * 2; else n = n * 2; if (n < 4) n = 4; r = journal_file_append_object(f, OBJECT_ENTRY_ARRAY, offsetof(Object, entry_array.items) + n * sizeof(uint64_t), &o, &q); if (r < 0) return r; #ifdef HAVE_GCRYPT r = journal_file_hmac_put_object(f, OBJECT_ENTRY_ARRAY, o, q); if (r < 0) return r; #endif o->entry_array.items[i] = htole64(p); if (ap == 0) *first = htole64(q); else { r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, ap, &o); if (r < 0) return r; o->entry_array.next_entry_array_offset = htole64(q); } if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays)) f->header->n_entry_arrays = htole64(le64toh(f->header->n_entry_arrays) + 1); *idx = htole64(hidx + 1); return 0; } static int link_entry_into_array_plus_one(JournalFile *f, le64_t *extra, le64_t *first, le64_t *idx, uint64_t p) { int r; assert(f); assert(extra); assert(first); assert(idx); assert(p > 0); if (*idx == 0) *extra = htole64(p); else { le64_t i; i = htole64(le64toh(*idx) - 1); r = link_entry_into_array(f, first, &i, p); if (r < 0) return r; } *idx = htole64(le64toh(*idx) + 1); return 0; } static int journal_file_link_entry_item(JournalFile *f, Object *o, uint64_t offset, uint64_t i) { uint64_t p; int r; assert(f); assert(o); assert(offset > 0); p = le64toh(o->entry.items[i].object_offset); if (p == 0) return -EINVAL; r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; return link_entry_into_array_plus_one(f, &o->data.entry_offset, &o->data.entry_array_offset, &o->data.n_entries, offset); } static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) { uint64_t n, i; int r; assert(f); assert(f->header); assert(o); assert(offset > 0); if (o->object.type != OBJECT_ENTRY) return -EINVAL; __sync_synchronize(); /* Link up the entry itself */ r = link_entry_into_array(f, &f->header->entry_array_offset, &f->header->n_entries, offset); if (r < 0) return r; /* log_debug("=> %s seqnr=%"PRIu64" n_entries=%"PRIu64, f->path, o->entry.seqnum, f->header->n_entries); */ if (f->header->head_entry_realtime == 0) f->header->head_entry_realtime = o->entry.realtime; f->header->tail_entry_realtime = o->entry.realtime; f->header->tail_entry_monotonic = o->entry.monotonic; f->tail_entry_monotonic_valid = true; /* Link up the items */ n = journal_file_entry_n_items(o); for (i = 0; i < n; i++) { r = journal_file_link_entry_item(f, o, offset, i); if (r < 0) return r; } return 0; } static int journal_file_append_entry_internal( JournalFile *f, const dual_timestamp *ts, uint64_t xor_hash, const EntryItem items[], unsigned n_items, uint64_t *seqnum, Object **ret, uint64_t *offset) { uint64_t np; uint64_t osize; Object *o; int r; assert(f); assert(f->header); assert(items || n_items == 0); assert(ts); osize = offsetof(Object, entry.items) + (n_items * sizeof(EntryItem)); r = journal_file_append_object(f, OBJECT_ENTRY, osize, &o, &np); if (r < 0) return r; o->entry.seqnum = htole64(journal_file_entry_seqnum(f, seqnum)); memcpy(o->entry.items, items, n_items * sizeof(EntryItem)); o->entry.realtime = htole64(ts->realtime); o->entry.monotonic = htole64(ts->monotonic); o->entry.xor_hash = htole64(xor_hash); o->entry.boot_id = f->header->boot_id; #ifdef HAVE_GCRYPT r = journal_file_hmac_put_object(f, OBJECT_ENTRY, o, np); if (r < 0) return r; #endif r = journal_file_link_entry(f, o, np); if (r < 0) return r; if (ret) *ret = o; if (offset) *offset = np; return 0; } void journal_file_post_change(JournalFile *f) { assert(f); /* inotify() does not receive IN_MODIFY events from file * accesses done via mmap(). After each access we hence * trigger IN_MODIFY by truncating the journal file to its * current size which triggers IN_MODIFY. */ __sync_synchronize(); if (ftruncate(f->fd, f->last_stat.st_size) < 0) log_debug_errno(errno, "Failed to truncate file to its own size: %m"); } static int post_change_thunk(sd_event_source *timer, uint64_t usec, void *userdata) { assert(userdata); journal_file_post_change(userdata); return 1; } static void schedule_post_change(JournalFile *f) { sd_event_source *timer; int enabled, r; uint64_t now; assert(f); assert(f->post_change_timer); timer = f->post_change_timer; r = sd_event_source_get_enabled(timer, &enabled); if (r < 0) { log_debug_errno(r, "Failed to get ftruncate timer state: %m"); goto fail; } if (enabled == SD_EVENT_ONESHOT) return; r = sd_event_now(sd_event_source_get_event(timer), CLOCK_MONOTONIC, &now); if (r < 0) { log_debug_errno(r, "Failed to get clock's now for scheduling ftruncate: %m"); goto fail; } r = sd_event_source_set_time(timer, now+f->post_change_timer_period); if (r < 0) { log_debug_errno(r, "Failed to set time for scheduling ftruncate: %m"); goto fail; } r = sd_event_source_set_enabled(timer, SD_EVENT_ONESHOT); if (r < 0) { log_debug_errno(r, "Failed to enable scheduled ftruncate: %m"); goto fail; } return; fail: /* On failure, let's simply post the change immediately. */ journal_file_post_change(f); } /* Enable coalesced change posting in a timer on the provided sd_event instance */ int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t) { _cleanup_(sd_event_source_unrefp) sd_event_source *timer = NULL; int r; assert(f); assert_return(!f->post_change_timer, -EINVAL); assert(e); assert(t); r = sd_event_add_time(e, &timer, CLOCK_MONOTONIC, 0, 0, post_change_thunk, f); if (r < 0) return r; r = sd_event_source_set_enabled(timer, SD_EVENT_OFF); if (r < 0) return r; f->post_change_timer = timer; timer = NULL; f->post_change_timer_period = t; return r; } static int entry_item_cmp(const void *_a, const void *_b) { const EntryItem *a = _a, *b = _b; if (le64toh(a->object_offset) < le64toh(b->object_offset)) return -1; if (le64toh(a->object_offset) > le64toh(b->object_offset)) return 1; return 0; } int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqnum, Object **ret, uint64_t *offset) { unsigned i; EntryItem *items; int r; uint64_t xor_hash = 0; struct dual_timestamp _ts; assert(f); assert(f->header); assert(iovec || n_iovec == 0); if (!ts) { dual_timestamp_get(&_ts); ts = &_ts; } #ifdef HAVE_GCRYPT r = journal_file_maybe_append_tag(f, ts->realtime); if (r < 0) return r; #endif /* alloca() can't take 0, hence let's allocate at least one */ items = alloca(sizeof(EntryItem) * MAX(1u, n_iovec)); for (i = 0; i < n_iovec; i++) { uint64_t p; Object *o; r = journal_file_append_data(f, iovec[i].iov_base, iovec[i].iov_len, &o, &p); if (r < 0) return r; xor_hash ^= le64toh(o->data.hash); items[i].object_offset = htole64(p); items[i].hash = o->data.hash; } /* Order by the position on disk, in order to improve seek * times for rotating media. */ qsort_safe(items, n_iovec, sizeof(EntryItem), entry_item_cmp); r = journal_file_append_entry_internal(f, ts, xor_hash, items, n_iovec, seqnum, ret, offset); /* If the memory mapping triggered a SIGBUS then we return an * IO error and ignore the error code passed down to us, since * it is very likely just an effect of a nullified replacement * mapping page */ if (mmap_cache_got_sigbus(f->mmap, f->fd)) r = -EIO; if (f->post_change_timer) schedule_post_change(f); else journal_file_post_change(f); return r; } typedef struct ChainCacheItem { uint64_t first; /* the array at the beginning of the chain */ uint64_t array; /* the cached array */ uint64_t begin; /* the first item in the cached array */ uint64_t total; /* the total number of items in all arrays before this one in the chain */ uint64_t last_index; /* the last index we looked at, to optimize locality when bisecting */ } ChainCacheItem; static void chain_cache_put( OrderedHashmap *h, ChainCacheItem *ci, uint64_t first, uint64_t array, uint64_t begin, uint64_t total, uint64_t last_index) { if (!ci) { /* If the chain item to cache for this chain is the * first one it's not worth caching anything */ if (array == first) return; if (ordered_hashmap_size(h) >= CHAIN_CACHE_MAX) { ci = ordered_hashmap_steal_first(h); assert(ci); } else { ci = new(ChainCacheItem, 1); if (!ci) return; } ci->first = first; if (ordered_hashmap_put(h, &ci->first, ci) < 0) { free(ci); return; } } else assert(ci->first == first); ci->array = array; ci->begin = begin; ci->total = total; ci->last_index = last_index; } static int generic_array_get( JournalFile *f, uint64_t first, uint64_t i, Object **ret, uint64_t *offset) { Object *o; uint64_t p = 0, a, t = 0; int r; ChainCacheItem *ci; assert(f); a = first; /* Try the chain cache first */ ci = ordered_hashmap_get(f->chain_cache, &first); if (ci && i > ci->total) { a = ci->array; i -= ci->total; t = ci->total; } while (a > 0) { uint64_t k; r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); if (r < 0) return r; k = journal_file_entry_array_n_items(o); if (i < k) { p = le64toh(o->entry_array.items[i]); goto found; } i -= k; t += k; a = le64toh(o->entry_array.next_entry_array_offset); } return 0; found: /* Let's cache this item for the next invocation */ chain_cache_put(f->chain_cache, ci, first, a, le64toh(o->entry_array.items[0]), t, i); r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); if (r < 0) return r; if (ret) *ret = o; if (offset) *offset = p; return 1; } static int generic_array_get_plus_one( JournalFile *f, uint64_t extra, uint64_t first, uint64_t i, Object **ret, uint64_t *offset) { Object *o; assert(f); if (i == 0) { int r; r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o); if (r < 0) return r; if (ret) *ret = o; if (offset) *offset = extra; return 1; } return generic_array_get(f, first, i-1, ret, offset); } enum { TEST_FOUND, TEST_LEFT, TEST_RIGHT }; static int generic_array_bisect( JournalFile *f, uint64_t first, uint64_t n, uint64_t needle, int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle), direction_t direction, Object **ret, uint64_t *offset, uint64_t *idx) { uint64_t a, p, t = 0, i = 0, last_p = 0, last_index = (uint64_t) -1; bool subtract_one = false; Object *o, *array = NULL; int r; ChainCacheItem *ci; assert(f); assert(test_object); /* Start with the first array in the chain */ a = first; ci = ordered_hashmap_get(f->chain_cache, &first); if (ci && n > ci->total) { /* Ah, we have iterated this bisection array chain * previously! Let's see if we can skip ahead in the * chain, as far as the last time. But we can't jump * backwards in the chain, so let's check that * first. */ r = test_object(f, ci->begin, needle); if (r < 0) return r; if (r == TEST_LEFT) { /* OK, what we are looking for is right of the * begin of this EntryArray, so let's jump * straight to previously cached array in the * chain */ a = ci->array; n -= ci->total; t = ci->total; last_index = ci->last_index; } } while (a > 0) { uint64_t left, right, k, lp; r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array); if (r < 0) return r; k = journal_file_entry_array_n_items(array); right = MIN(k, n); if (right <= 0) return 0; i = right - 1; lp = p = le64toh(array->entry_array.items[i]); if (p <= 0) return -EBADMSG; r = test_object(f, p, needle); if (r < 0) return r; if (r == TEST_FOUND) r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; if (r == TEST_RIGHT) { left = 0; right -= 1; if (last_index != (uint64_t) -1) { assert(last_index <= right); /* If we cached the last index we * looked at, let's try to not to jump * too wildly around and see if we can * limit the range to look at early to * the immediate neighbors of the last * index we looked at. */ if (last_index > 0) { uint64_t x = last_index - 1; p = le64toh(array->entry_array.items[x]); if (p <= 0) return -EBADMSG; r = test_object(f, p, needle); if (r < 0) return r; if (r == TEST_FOUND) r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; if (r == TEST_RIGHT) right = x; else left = x + 1; } if (last_index < right) { uint64_t y = last_index + 1; p = le64toh(array->entry_array.items[y]); if (p <= 0) return -EBADMSG; r = test_object(f, p, needle); if (r < 0) return r; if (r == TEST_FOUND) r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; if (r == TEST_RIGHT) right = y; else left = y + 1; } } for (;;) { if (left == right) { if (direction == DIRECTION_UP) subtract_one = true; i = left; goto found; } assert(left < right); i = (left + right) / 2; p = le64toh(array->entry_array.items[i]); if (p <= 0) return -EBADMSG; r = test_object(f, p, needle); if (r < 0) return r; if (r == TEST_FOUND) r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; if (r == TEST_RIGHT) right = i; else left = i + 1; } } if (k >= n) { if (direction == DIRECTION_UP) { i = n; subtract_one = true; goto found; } return 0; } last_p = lp; n -= k; t += k; last_index = (uint64_t) -1; a = le64toh(array->entry_array.next_entry_array_offset); } return 0; found: if (subtract_one && t == 0 && i == 0) return 0; /* Let's cache this item for the next invocation */ chain_cache_put(f->chain_cache, ci, first, a, le64toh(array->entry_array.items[0]), t, subtract_one ? (i > 0 ? i-1 : (uint64_t) -1) : i); if (subtract_one && i == 0) p = last_p; else if (subtract_one) p = le64toh(array->entry_array.items[i-1]); else p = le64toh(array->entry_array.items[i]); r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); if (r < 0) return r; if (ret) *ret = o; if (offset) *offset = p; if (idx) *idx = t + i + (subtract_one ? -1 : 0); return 1; } static int generic_array_bisect_plus_one( JournalFile *f, uint64_t extra, uint64_t first, uint64_t n, uint64_t needle, int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle), direction_t direction, Object **ret, uint64_t *offset, uint64_t *idx) { int r; bool step_back = false; Object *o; assert(f); assert(test_object); if (n <= 0) return 0; /* This bisects the array in object 'first', but first checks * an extra */ r = test_object(f, extra, needle); if (r < 0) return r; if (r == TEST_FOUND) r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; /* if we are looking with DIRECTION_UP then we need to first see if in the actual array there is a matching entry, and return the last one of that. But if there isn't any we need to return this one. Hence remember this, and return it below. */ if (r == TEST_LEFT) step_back = direction == DIRECTION_UP; if (r == TEST_RIGHT) { if (direction == DIRECTION_DOWN) goto found; else return 0; } r = generic_array_bisect(f, first, n-1, needle, test_object, direction, ret, offset, idx); if (r == 0 && step_back) goto found; if (r > 0 && idx) (*idx) ++; return r; found: r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o); if (r < 0) return r; if (ret) *ret = o; if (offset) *offset = extra; if (idx) *idx = 0; return 1; } _pure_ static int test_object_offset(JournalFile *f, uint64_t p, uint64_t needle) { assert(f); assert(p > 0); if (p == needle) return TEST_FOUND; else if (p < needle) return TEST_LEFT; else return TEST_RIGHT; } static int test_object_seqnum(JournalFile *f, uint64_t p, uint64_t needle) { Object *o; int r; assert(f); assert(p > 0); r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); if (r < 0) return r; if (le64toh(o->entry.seqnum) == needle) return TEST_FOUND; else if (le64toh(o->entry.seqnum) < needle) return TEST_LEFT; else return TEST_RIGHT; } int journal_file_move_to_entry_by_seqnum( JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset) { assert(f); assert(f->header); return generic_array_bisect(f, le64toh(f->header->entry_array_offset), le64toh(f->header->n_entries), seqnum, test_object_seqnum, direction, ret, offset, NULL); } static int test_object_realtime(JournalFile *f, uint64_t p, uint64_t needle) { Object *o; int r; assert(f); assert(p > 0); r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); if (r < 0) return r; if (le64toh(o->entry.realtime) == needle) return TEST_FOUND; else if (le64toh(o->entry.realtime) < needle) return TEST_LEFT; else return TEST_RIGHT; } int journal_file_move_to_entry_by_realtime( JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset) { assert(f); assert(f->header); return generic_array_bisect(f, le64toh(f->header->entry_array_offset), le64toh(f->header->n_entries), realtime, test_object_realtime, direction, ret, offset, NULL); } static int test_object_monotonic(JournalFile *f, uint64_t p, uint64_t needle) { Object *o; int r; assert(f); assert(p > 0); r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); if (r < 0) return r; if (le64toh(o->entry.monotonic) == needle) return TEST_FOUND; else if (le64toh(o->entry.monotonic) < needle) return TEST_LEFT; else return TEST_RIGHT; } static int find_data_object_by_boot_id( JournalFile *f, sd_id128_t boot_id, Object **o, uint64_t *b) { char t[sizeof("_BOOT_ID=")-1 + 32 + 1] = "_BOOT_ID="; sd_id128_to_string(boot_id, t + 9); return journal_file_find_data_object(f, t, sizeof(t) - 1, o, b); } int journal_file_move_to_entry_by_monotonic( JournalFile *f, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset) { Object *o; int r; assert(f); r = find_data_object_by_boot_id(f, boot_id, &o, NULL); if (r < 0) return r; if (r == 0) return -ENOENT; return generic_array_bisect_plus_one(f, le64toh(o->data.entry_offset), le64toh(o->data.entry_array_offset), le64toh(o->data.n_entries), monotonic, test_object_monotonic, direction, ret, offset, NULL); } void journal_file_reset_location(JournalFile *f) { f->location_type = LOCATION_HEAD; f->current_offset = 0; f->current_seqnum = 0; f->current_realtime = 0; f->current_monotonic = 0; zero(f->current_boot_id); f->current_xor_hash = 0; } void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset) { f->location_type = LOCATION_SEEK; f->current_offset = offset; f->current_seqnum = le64toh(o->entry.seqnum); f->current_realtime = le64toh(o->entry.realtime); f->current_monotonic = le64toh(o->entry.monotonic); f->current_boot_id = o->entry.boot_id; f->current_xor_hash = le64toh(o->entry.xor_hash); } int journal_file_compare_locations(JournalFile *af, JournalFile *bf) { assert(af); assert(af->header); assert(bf); assert(bf->header); assert(af->location_type == LOCATION_SEEK); assert(bf->location_type == LOCATION_SEEK); /* If contents and timestamps match, these entries are * identical, even if the seqnum does not match */ if (sd_id128_equal(af->current_boot_id, bf->current_boot_id) && af->current_monotonic == bf->current_monotonic && af->current_realtime == bf->current_realtime && af->current_xor_hash == bf->current_xor_hash) return 0; if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) { /* If this is from the same seqnum source, compare * seqnums */ if (af->current_seqnum < bf->current_seqnum) return -1; if (af->current_seqnum > bf->current_seqnum) return 1; /* Wow! This is weird, different data but the same * seqnums? Something is borked, but let's make the * best of it and compare by time. */ } if (sd_id128_equal(af->current_boot_id, bf->current_boot_id)) { /* If the boot id matches, compare monotonic time */ if (af->current_monotonic < bf->current_monotonic) return -1; if (af->current_monotonic > bf->current_monotonic) return 1; } /* Otherwise, compare UTC time */ if (af->current_realtime < bf->current_realtime) return -1; if (af->current_realtime > bf->current_realtime) return 1; /* Finally, compare by contents */ if (af->current_xor_hash < bf->current_xor_hash) return -1; if (af->current_xor_hash > bf->current_xor_hash) return 1; return 0; } int journal_file_next_entry( JournalFile *f, uint64_t p, direction_t direction, Object **ret, uint64_t *offset) { uint64_t i, n, ofs; int r; assert(f); assert(f->header); n = le64toh(f->header->n_entries); if (n <= 0) return 0; if (p == 0) i = direction == DIRECTION_DOWN ? 0 : n - 1; else { r = generic_array_bisect(f, le64toh(f->header->entry_array_offset), le64toh(f->header->n_entries), p, test_object_offset, DIRECTION_DOWN, NULL, NULL, &i); if (r <= 0) return r; if (direction == DIRECTION_DOWN) { if (i >= n - 1) return 0; i++; } else { if (i <= 0) return 0; i--; } } /* And jump to it */ r = generic_array_get(f, le64toh(f->header->entry_array_offset), i, ret, &ofs); if (r <= 0) return r; if (p > 0 && (direction == DIRECTION_DOWN ? ofs <= p : ofs >= p)) { log_debug("%s: entry array corrupted at entry %"PRIu64, f->path, i); return -EBADMSG; } if (offset) *offset = ofs; return 1; } int journal_file_next_entry_for_data( JournalFile *f, Object *o, uint64_t p, uint64_t data_offset, direction_t direction, Object **ret, uint64_t *offset) { uint64_t n, i; int r; Object *d; assert(f); assert(p > 0 || !o); r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); if (r < 0) return r; n = le64toh(d->data.n_entries); if (n <= 0) return n; if (!o) i = direction == DIRECTION_DOWN ? 0 : n - 1; else { if (o->object.type != OBJECT_ENTRY) return -EINVAL; r = generic_array_bisect_plus_one(f, le64toh(d->data.entry_offset), le64toh(d->data.entry_array_offset), le64toh(d->data.n_entries), p, test_object_offset, DIRECTION_DOWN, NULL, NULL, &i); if (r <= 0) return r; if (direction == DIRECTION_DOWN) { if (i >= n - 1) return 0; i++; } else { if (i <= 0) return 0; i--; } } return generic_array_get_plus_one(f, le64toh(d->data.entry_offset), le64toh(d->data.entry_array_offset), i, ret, offset); } int journal_file_move_to_entry_by_offset_for_data( JournalFile *f, uint64_t data_offset, uint64_t p, direction_t direction, Object **ret, uint64_t *offset) { int r; Object *d; assert(f); r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); if (r < 0) return r; return generic_array_bisect_plus_one(f, le64toh(d->data.entry_offset), le64toh(d->data.entry_array_offset), le64toh(d->data.n_entries), p, test_object_offset, direction, ret, offset, NULL); } int journal_file_move_to_entry_by_monotonic_for_data( JournalFile *f, uint64_t data_offset, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset) { Object *o, *d; int r; uint64_t b, z; assert(f); /* First, seek by time */ r = find_data_object_by_boot_id(f, boot_id, &o, &b); if (r < 0) return r; if (r == 0) return -ENOENT; r = generic_array_bisect_plus_one(f, le64toh(o->data.entry_offset), le64toh(o->data.entry_array_offset), le64toh(o->data.n_entries), monotonic, test_object_monotonic, direction, NULL, &z, NULL); if (r <= 0) return r; /* And now, continue seeking until we find an entry that * exists in both bisection arrays */ for (;;) { Object *qo; uint64_t p, q; r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); if (r < 0) return r; r = generic_array_bisect_plus_one(f, le64toh(d->data.entry_offset), le64toh(d->data.entry_array_offset), le64toh(d->data.n_entries), z, test_object_offset, direction, NULL, &p, NULL); if (r <= 0) return r; r = journal_file_move_to_object(f, OBJECT_DATA, b, &o); if (r < 0) return r; r = generic_array_bisect_plus_one(f, le64toh(o->data.entry_offset), le64toh(o->data.entry_array_offset), le64toh(o->data.n_entries), p, test_object_offset, direction, &qo, &q, NULL); if (r <= 0) return r; if (p == q) { if (ret) *ret = qo; if (offset) *offset = q; return 1; } z = q; } } int journal_file_move_to_entry_by_seqnum_for_data( JournalFile *f, uint64_t data_offset, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset) { Object *d; int r; assert(f); r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); if (r < 0) return r; return generic_array_bisect_plus_one(f, le64toh(d->data.entry_offset), le64toh(d->data.entry_array_offset), le64toh(d->data.n_entries), seqnum, test_object_seqnum, direction, ret, offset, NULL); } int journal_file_move_to_entry_by_realtime_for_data( JournalFile *f, uint64_t data_offset, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset) { Object *d; int r; assert(f); r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); if (r < 0) return r; return generic_array_bisect_plus_one(f, le64toh(d->data.entry_offset), le64toh(d->data.entry_array_offset), le64toh(d->data.n_entries), realtime, test_object_realtime, direction, ret, offset, NULL); } void journal_file_dump(JournalFile *f) { Object *o; int r; uint64_t p; assert(f); assert(f->header); journal_file_print_header(f); p = le64toh(f->header->header_size); while (p != 0) { r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o); if (r < 0) goto fail; switch (o->object.type) { case OBJECT_UNUSED: printf("Type: OBJECT_UNUSED\n"); break; case OBJECT_DATA: printf("Type: OBJECT_DATA\n"); break; case OBJECT_FIELD: printf("Type: OBJECT_FIELD\n"); break; case OBJECT_ENTRY: printf("Type: OBJECT_ENTRY seqnum=%"PRIu64" monotonic=%"PRIu64" realtime=%"PRIu64"\n", le64toh(o->entry.seqnum), le64toh(o->entry.monotonic), le64toh(o->entry.realtime)); break; case OBJECT_FIELD_HASH_TABLE: printf("Type: OBJECT_FIELD_HASH_TABLE\n"); break; case OBJECT_DATA_HASH_TABLE: printf("Type: OBJECT_DATA_HASH_TABLE\n"); break; case OBJECT_ENTRY_ARRAY: printf("Type: OBJECT_ENTRY_ARRAY\n"); break; case OBJECT_TAG: printf("Type: OBJECT_TAG seqnum=%"PRIu64" epoch=%"PRIu64"\n", le64toh(o->tag.seqnum), le64toh(o->tag.epoch)); break; default: printf("Type: unknown (%i)\n", o->object.type); break; } if (o->object.flags & OBJECT_COMPRESSION_MASK) printf("Flags: %s\n", object_compressed_to_string(o->object.flags & OBJECT_COMPRESSION_MASK)); if (p == le64toh(f->header->tail_object_offset)) p = 0; else p = p + ALIGN64(le64toh(o->object.size)); } return; fail: log_error("File corrupt"); } static const char* format_timestamp_safe(char *buf, size_t l, usec_t t) { const char *x; x = format_timestamp(buf, l, t); if (x) return x; return " --- "; } void journal_file_print_header(JournalFile *f) { char a[33], b[33], c[33], d[33]; char x[FORMAT_TIMESTAMP_MAX], y[FORMAT_TIMESTAMP_MAX], z[FORMAT_TIMESTAMP_MAX]; struct stat st; char bytes[FORMAT_BYTES_MAX]; assert(f); assert(f->header); printf("File Path: %s\n" "File ID: %s\n" "Machine ID: %s\n" "Boot ID: %s\n" "Sequential Number ID: %s\n" "State: %s\n" "Compatible Flags:%s%s\n" "Incompatible Flags:%s%s%s\n" "Header size: %"PRIu64"\n" "Arena size: %"PRIu64"\n" "Data Hash Table Size: %"PRIu64"\n" "Field Hash Table Size: %"PRIu64"\n" "Rotate Suggested: %s\n" "Head Sequential Number: %"PRIu64"\n" "Tail Sequential Number: %"PRIu64"\n" "Head Realtime Timestamp: %s\n" "Tail Realtime Timestamp: %s\n" "Tail Monotonic Timestamp: %s\n" "Objects: %"PRIu64"\n" "Entry Objects: %"PRIu64"\n", f->path, sd_id128_to_string(f->header->file_id, a), sd_id128_to_string(f->header->machine_id, b), sd_id128_to_string(f->header->boot_id, c), sd_id128_to_string(f->header->seqnum_id, d), f->header->state == STATE_OFFLINE ? "OFFLINE" : f->header->state == STATE_ONLINE ? "ONLINE" : f->header->state == STATE_ARCHIVED ? "ARCHIVED" : "UNKNOWN", JOURNAL_HEADER_SEALED(f->header) ? " SEALED" : "", (le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_ANY) ? " ???" : "", JOURNAL_HEADER_COMPRESSED_XZ(f->header) ? " COMPRESSED-XZ" : "", JOURNAL_HEADER_COMPRESSED_LZ4(f->header) ? " COMPRESSED-LZ4" : "", (le32toh(f->header->incompatible_flags) & ~HEADER_INCOMPATIBLE_ANY) ? " ???" : "", le64toh(f->header->header_size), le64toh(f->header->arena_size), le64toh(f->header->data_hash_table_size) / sizeof(HashItem), le64toh(f->header->field_hash_table_size) / sizeof(HashItem), yes_no(journal_file_rotate_suggested(f, 0)), le64toh(f->header->head_entry_seqnum), le64toh(f->header->tail_entry_seqnum), format_timestamp_safe(x, sizeof(x), le64toh(f->header->head_entry_realtime)), format_timestamp_safe(y, sizeof(y), le64toh(f->header->tail_entry_realtime)), format_timespan(z, sizeof(z), le64toh(f->header->tail_entry_monotonic), USEC_PER_MSEC), le64toh(f->header->n_objects), le64toh(f->header->n_entries)); if (JOURNAL_HEADER_CONTAINS(f->header, n_data)) printf("Data Objects: %"PRIu64"\n" "Data Hash Table Fill: %.1f%%\n", le64toh(f->header->n_data), 100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)))); if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)) printf("Field Objects: %"PRIu64"\n" "Field Hash Table Fill: %.1f%%\n", le64toh(f->header->n_fields), 100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)))); if (JOURNAL_HEADER_CONTAINS(f->header, n_tags)) printf("Tag Objects: %"PRIu64"\n", le64toh(f->header->n_tags)); if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays)) printf("Entry Array Objects: %"PRIu64"\n", le64toh(f->header->n_entry_arrays)); if (fstat(f->fd, &st) >= 0) printf("Disk usage: %s\n", format_bytes(bytes, sizeof(bytes), (uint64_t) st.st_blocks * 512ULL)); } static int journal_file_warn_btrfs(JournalFile *f) { unsigned attrs; int r; assert(f); /* Before we write anything, check if the COW logic is turned * off on btrfs. Given our write pattern that is quite * unfriendly to COW file systems this should greatly improve * performance on COW file systems, such as btrfs, at the * expense of data integrity features (which shouldn't be too * bad, given that we do our own checksumming). */ r = btrfs_is_filesystem(f->fd); if (r < 0) return log_warning_errno(r, "Failed to determine if journal is on btrfs: %m"); if (!r) return 0; r = read_attr_fd(f->fd, &attrs); if (r < 0) return log_warning_errno(r, "Failed to read file attributes: %m"); if (attrs & FS_NOCOW_FL) { log_debug("Detected btrfs file system with copy-on-write disabled, all is good."); return 0; } log_notice("Creating journal file %s on a btrfs file system, and copy-on-write is enabled. " "This is likely to slow down journal access substantially, please consider turning " "off the copy-on-write file attribute on the journal directory, using chattr +C.", f->path); return 1; } int journal_file_open( const char *fname, int flags, mode_t mode, bool compress, bool seal, JournalMetrics *metrics, MMapCache *mmap_cache, JournalFile *template, JournalFile **ret) { bool newly_created = false; JournalFile *f; void *h; int r; assert(fname); assert(ret); if ((flags & O_ACCMODE) != O_RDONLY && (flags & O_ACCMODE) != O_RDWR) return -EINVAL; if (!endswith(fname, ".journal") && !endswith(fname, ".journal~")) return -EINVAL; f = new0(JournalFile, 1); if (!f) return -ENOMEM; f->fd = -1; f->mode = mode; f->flags = flags; f->prot = prot_from_flags(flags); f->writable = (flags & O_ACCMODE) != O_RDONLY; #if defined(HAVE_LZ4) f->compress_lz4 = compress; #elif defined(HAVE_XZ) f->compress_xz = compress; #endif #ifdef HAVE_GCRYPT f->seal = seal; #endif if (mmap_cache) f->mmap = mmap_cache_ref(mmap_cache); else { f->mmap = mmap_cache_new(); if (!f->mmap) { r = -ENOMEM; goto fail; } } f->path = strdup(fname); if (!f->path) { r = -ENOMEM; goto fail; } f->chain_cache = ordered_hashmap_new(&uint64_hash_ops); if (!f->chain_cache) { r = -ENOMEM; goto fail; } f->fd = open(f->path, f->flags|O_CLOEXEC, f->mode); if (f->fd < 0) { r = -errno; goto fail; } r = journal_file_fstat(f); if (r < 0) goto fail; if (f->last_stat.st_size == 0 && f->writable) { (void) journal_file_warn_btrfs(f); /* Let's attach the creation time to the journal file, * so that the vacuuming code knows the age of this * file even if the file might end up corrupted one * day... Ideally we'd just use the creation time many * file systems maintain for each file, but there is * currently no usable API to query this, hence let's * emulate this via extended attributes. If extended * attributes are not supported we'll just skip this, * and rely solely on mtime/atime/ctime of the file. */ fd_setcrtime(f->fd, 0); #ifdef HAVE_GCRYPT /* Try to load the FSPRG state, and if we can't, then * just don't do sealing */ if (f->seal) { r = journal_file_fss_load(f); if (r < 0) f->seal = false; } #endif r = journal_file_init_header(f, template); if (r < 0) goto fail; r = journal_file_fstat(f); if (r < 0) goto fail; newly_created = true; } if (f->last_stat.st_size < (off_t) HEADER_SIZE_MIN) { r = -ENODATA; goto fail; } r = mmap_cache_get(f->mmap, f->fd, f->prot, CONTEXT_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h); if (r < 0) goto fail; f->header = h; if (!newly_created) { r = journal_file_verify_header(f); if (r < 0) goto fail; } #ifdef HAVE_GCRYPT if (!newly_created && f->writable) { r = journal_file_fss_load(f); if (r < 0) goto fail; } #endif if (f->writable) { if (metrics) { journal_default_metrics(metrics, f->fd); f->metrics = *metrics; } else if (template) f->metrics = template->metrics; r = journal_file_refresh_header(f); if (r < 0) goto fail; } #ifdef HAVE_GCRYPT r = journal_file_hmac_setup(f); if (r < 0) goto fail; #endif if (newly_created) { r = journal_file_setup_field_hash_table(f); if (r < 0) goto fail; r = journal_file_setup_data_hash_table(f); if (r < 0) goto fail; #ifdef HAVE_GCRYPT r = journal_file_append_first_tag(f); if (r < 0) goto fail; #endif } if (mmap_cache_got_sigbus(f->mmap, f->fd)) { r = -EIO; goto fail; } if (template && template->post_change_timer) { r = journal_file_enable_post_change_timer( f, sd_event_source_get_event(template->post_change_timer), template->post_change_timer_period); if (r < 0) goto fail; } *ret = f; return 0; fail: if (f->fd >= 0 && mmap_cache_got_sigbus(f->mmap, f->fd)) r = -EIO; journal_file_close(f); return r; } int journal_file_rotate(JournalFile **f, bool compress, bool seal) { _cleanup_free_ char *p = NULL; size_t l; JournalFile *old_file, *new_file = NULL; int r; assert(f); assert(*f); old_file = *f; if (!old_file->writable) return -EINVAL; if (!endswith(old_file->path, ".journal")) return -EINVAL; l = strlen(old_file->path); r = asprintf(&p, "%.*s@" SD_ID128_FORMAT_STR "-%016"PRIx64"-%016"PRIx64".journal", (int) l - 8, old_file->path, SD_ID128_FORMAT_VAL(old_file->header->seqnum_id), le64toh((*f)->header->head_entry_seqnum), le64toh((*f)->header->head_entry_realtime)); if (r < 0) return -ENOMEM; /* Try to rename the file to the archived version. If the file * already was deleted, we'll get ENOENT, let's ignore that * case. */ r = rename(old_file->path, p); if (r < 0 && errno != ENOENT) return -errno; old_file->header->state = STATE_ARCHIVED; /* Currently, btrfs is not very good with out write patterns * and fragments heavily. Let's defrag our journal files when * we archive them */ old_file->defrag_on_close = true; r = journal_file_open(old_file->path, old_file->flags, old_file->mode, compress, seal, NULL, old_file->mmap, old_file, &new_file); journal_file_close(old_file); *f = new_file; return r; } int journal_file_open_reliably( const char *fname, int flags, mode_t mode, bool compress, bool seal, JournalMetrics *metrics, MMapCache *mmap_cache, JournalFile *template, JournalFile **ret) { int r; size_t l; _cleanup_free_ char *p = NULL; r = journal_file_open(fname, flags, mode, compress, seal, metrics, mmap_cache, template, ret); if (!IN_SET(r, -EBADMSG, /* corrupted */ -ENODATA, /* truncated */ -EHOSTDOWN, /* other machine */ -EPROTONOSUPPORT, /* incompatible feature */ -EBUSY, /* unclean shutdown */ -ESHUTDOWN, /* already archived */ -EIO, /* IO error, including SIGBUS on mmap */ -EIDRM /* File has been deleted */)) return r; if ((flags & O_ACCMODE) == O_RDONLY) return r; if (!(flags & O_CREAT)) return r; if (!endswith(fname, ".journal")) return r; /* The file is corrupted. Rotate it away and try it again (but only once) */ l = strlen(fname); if (asprintf(&p, "%.*s@%016"PRIx64 "-%016"PRIx64 ".journal~", (int) l - 8, fname, now(CLOCK_REALTIME), random_u64()) < 0) return -ENOMEM; if (rename(fname, p) < 0) return -errno; /* btrfs doesn't cope well with our write pattern and * fragments heavily. Let's defrag all files we rotate */ (void) chattr_path(p, false, FS_NOCOW_FL); (void) btrfs_defrag(p); log_warning_errno(r, "File %s corrupted or uncleanly shut down, renaming and replacing.", fname); return journal_file_open(fname, flags, mode, compress, seal, metrics, mmap_cache, template, ret); } int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset) { uint64_t i, n; uint64_t q, xor_hash = 0; int r; EntryItem *items; dual_timestamp ts; assert(from); assert(to); assert(o); assert(p); if (!to->writable) return -EPERM; ts.monotonic = le64toh(o->entry.monotonic); ts.realtime = le64toh(o->entry.realtime); n = journal_file_entry_n_items(o); /* alloca() can't take 0, hence let's allocate at least one */ items = alloca(sizeof(EntryItem) * MAX(1u, n)); for (i = 0; i < n; i++) { uint64_t l, h; le64_t le_hash; size_t t; void *data; Object *u; q = le64toh(o->entry.items[i].object_offset); le_hash = o->entry.items[i].hash; r = journal_file_move_to_object(from, OBJECT_DATA, q, &o); if (r < 0) return r; if (le_hash != o->data.hash) return -EBADMSG; l = le64toh(o->object.size) - offsetof(Object, data.payload); t = (size_t) l; /* We hit the limit on 32bit machines */ if ((uint64_t) t != l) return -E2BIG; if (o->object.flags & OBJECT_COMPRESSION_MASK) { #if defined(HAVE_XZ) || defined(HAVE_LZ4) size_t rsize = 0; r = decompress_blob(o->object.flags & OBJECT_COMPRESSION_MASK, o->data.payload, l, &from->compress_buffer, &from->compress_buffer_size, &rsize, 0); if (r < 0) return r; data = from->compress_buffer; l = rsize; #else return -EPROTONOSUPPORT; #endif } else data = o->data.payload; r = journal_file_append_data(to, data, l, &u, &h); if (r < 0) return r; xor_hash ^= le64toh(u->data.hash); items[i].object_offset = htole64(h); items[i].hash = u->data.hash; r = journal_file_move_to_object(from, OBJECT_ENTRY, p, &o); if (r < 0) return r; } r = journal_file_append_entry_internal(to, &ts, xor_hash, items, n, seqnum, ret, offset); if (mmap_cache_got_sigbus(to->mmap, to->fd)) return -EIO; return r; } void journal_reset_metrics(JournalMetrics *m) { assert(m); /* Set everything to "pick automatic values". */ *m = (JournalMetrics) { .min_use = (uint64_t) -1, .max_use = (uint64_t) -1, .min_size = (uint64_t) -1, .max_size = (uint64_t) -1, .keep_free = (uint64_t) -1, .n_max_files = (uint64_t) -1, }; } void journal_default_metrics(JournalMetrics *m, int fd) { char a[FORMAT_BYTES_MAX], b[FORMAT_BYTES_MAX], c[FORMAT_BYTES_MAX], d[FORMAT_BYTES_MAX], e[FORMAT_BYTES_MAX]; struct statvfs ss; uint64_t fs_size; assert(m); assert(fd >= 0); if (fstatvfs(fd, &ss) >= 0) fs_size = ss.f_frsize * ss.f_blocks; else { log_debug_errno(errno, "Failed to detremine disk size: %m"); fs_size = 0; } if (m->max_use == (uint64_t) -1) { if (fs_size > 0) { m->max_use = PAGE_ALIGN(fs_size / 10); /* 10% of file system size */ if (m->max_use > DEFAULT_MAX_USE_UPPER) m->max_use = DEFAULT_MAX_USE_UPPER; if (m->max_use < DEFAULT_MAX_USE_LOWER) m->max_use = DEFAULT_MAX_USE_LOWER; } else m->max_use = DEFAULT_MAX_USE_LOWER; } else { m->max_use = PAGE_ALIGN(m->max_use); if (m->max_use != 0 && m->max_use < JOURNAL_FILE_SIZE_MIN*2) m->max_use = JOURNAL_FILE_SIZE_MIN*2; } if (m->min_use == (uint64_t) -1) m->min_use = DEFAULT_MIN_USE; if (m->min_use > m->max_use) m->min_use = m->max_use; if (m->max_size == (uint64_t) -1) { m->max_size = PAGE_ALIGN(m->max_use / 8); /* 8 chunks */ if (m->max_size > DEFAULT_MAX_SIZE_UPPER) m->max_size = DEFAULT_MAX_SIZE_UPPER; } else m->max_size = PAGE_ALIGN(m->max_size); if (m->max_size != 0) { if (m->max_size < JOURNAL_FILE_SIZE_MIN) m->max_size = JOURNAL_FILE_SIZE_MIN; if (m->max_use != 0 && m->max_size*2 > m->max_use) m->max_use = m->max_size*2; } if (m->min_size == (uint64_t) -1) m->min_size = JOURNAL_FILE_SIZE_MIN; else { m->min_size = PAGE_ALIGN(m->min_size); if (m->min_size < JOURNAL_FILE_SIZE_MIN) m->min_size = JOURNAL_FILE_SIZE_MIN; if (m->max_size != 0 && m->min_size > m->max_size) m->max_size = m->min_size; } if (m->keep_free == (uint64_t) -1) { if (fs_size > 0) { m->keep_free = PAGE_ALIGN(fs_size * 3 / 20); /* 15% of file system size */ if (m->keep_free > DEFAULT_KEEP_FREE_UPPER) m->keep_free = DEFAULT_KEEP_FREE_UPPER; } else m->keep_free = DEFAULT_KEEP_FREE; } if (m->n_max_files == (uint64_t) -1) m->n_max_files = DEFAULT_N_MAX_FILES; log_debug("Fixed min_use=%s max_use=%s max_size=%s min_size=%s keep_free=%s n_max_files=%" PRIu64, format_bytes(a, sizeof(a), m->min_use), format_bytes(b, sizeof(b), m->max_use), format_bytes(c, sizeof(c), m->max_size), format_bytes(d, sizeof(d), m->min_size), format_bytes(e, sizeof(e), m->keep_free), m->n_max_files); } int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to) { assert(f); assert(f->header); assert(from || to); if (from) { if (f->header->head_entry_realtime == 0) return -ENOENT; *from = le64toh(f->header->head_entry_realtime); } if (to) { if (f->header->tail_entry_realtime == 0) return -ENOENT; *to = le64toh(f->header->tail_entry_realtime); } return 1; } int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, usec_t *from, usec_t *to) { Object *o; uint64_t p; int r; assert(f); assert(from || to); r = find_data_object_by_boot_id(f, boot_id, &o, &p); if (r <= 0) return r; if (le64toh(o->data.n_entries) <= 0) return 0; if (from) { r = journal_file_move_to_object(f, OBJECT_ENTRY, le64toh(o->data.entry_offset), &o); if (r < 0) return r; *from = le64toh(o->entry.monotonic); } if (to) { r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; r = generic_array_get_plus_one(f, le64toh(o->data.entry_offset), le64toh(o->data.entry_array_offset), le64toh(o->data.n_entries)-1, &o, NULL); if (r <= 0) return r; *to = le64toh(o->entry.monotonic); } return 1; } bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec) { assert(f); assert(f->header); /* If we gained new header fields we gained new features, * hence suggest a rotation */ if (le64toh(f->header->header_size) < sizeof(Header)) { log_debug("%s uses an outdated header, suggesting rotation.", f->path); return true; } /* Let's check if the hash tables grew over a certain fill * level (75%, borrowing this value from Java's hash table * implementation), and if so suggest a rotation. To calculate * the fill level we need the n_data field, which only exists * in newer versions. */ if (JOURNAL_HEADER_CONTAINS(f->header, n_data)) if (le64toh(f->header->n_data) * 4ULL > (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)) * 3ULL) { log_debug("Data hash table of %s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items, %llu file size, %"PRIu64" bytes per hash table item), suggesting rotation.", f->path, 100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem))), le64toh(f->header->n_data), le64toh(f->header->data_hash_table_size) / sizeof(HashItem), (unsigned long long) f->last_stat.st_size, f->last_stat.st_size / le64toh(f->header->n_data)); return true; } if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)) if (le64toh(f->header->n_fields) * 4ULL > (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)) * 3ULL) { log_debug("Field hash table of %s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items), suggesting rotation.", f->path, 100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem))), le64toh(f->header->n_fields), le64toh(f->header->field_hash_table_size) / sizeof(HashItem)); return true; } /* Are the data objects properly indexed by field objects? */ if (JOURNAL_HEADER_CONTAINS(f->header, n_data) && JOURNAL_HEADER_CONTAINS(f->header, n_fields) && le64toh(f->header->n_data) > 0 && le64toh(f->header->n_fields) == 0) return true; if (max_file_usec > 0) { usec_t t, h; h = le64toh(f->header->head_entry_realtime); t = now(CLOCK_REALTIME); if (h > 0 && t > h + max_file_usec) return true; } return false; } systemd-229/src/journal/journal-file.h000066400000000000000000000220001265713322000200540ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #ifdef HAVE_GCRYPT #include #endif #include "sd-id128.h" #include "hashmap.h" #include "journal-def.h" #include "macro.h" #include "mmap-cache.h" #include "sd-event.h" #include "sparse-endian.h" typedef struct JournalMetrics { /* For all these: -1 means "pick automatically", and 0 means "no limit enforced" */ uint64_t max_size; /* how large journal files grow at max */ uint64_t min_size; /* how large journal files grow at least */ uint64_t max_use; /* how much disk space to use in total at max, keep_free permitting */ uint64_t min_use; /* how much disk space to use in total at least, even if keep_free says not to */ uint64_t keep_free; /* how much to keep free on disk */ uint64_t n_max_files; /* how many files to keep around at max */ } JournalMetrics; typedef enum direction { DIRECTION_UP, DIRECTION_DOWN } direction_t; typedef enum LocationType { /* The first and last entries, resp. */ LOCATION_HEAD, LOCATION_TAIL, /* We already read the entry we currently point to, and the * next one to read should probably not be this one again. */ LOCATION_DISCRETE, /* We should seek to the precise location specified, and * return it, as we haven't read it yet. */ LOCATION_SEEK } LocationType; typedef struct JournalFile { int fd; mode_t mode; int flags; int prot; bool writable:1; bool compress_xz:1; bool compress_lz4:1; bool seal:1; bool defrag_on_close:1; bool tail_entry_monotonic_valid:1; direction_t last_direction; LocationType location_type; uint64_t last_n_entries; char *path; struct stat last_stat; usec_t last_stat_usec; Header *header; HashItem *data_hash_table; HashItem *field_hash_table; uint64_t current_offset; uint64_t current_seqnum; uint64_t current_realtime; uint64_t current_monotonic; sd_id128_t current_boot_id; uint64_t current_xor_hash; JournalMetrics metrics; MMapCache *mmap; sd_event_source *post_change_timer; usec_t post_change_timer_period; OrderedHashmap *chain_cache; #if defined(HAVE_XZ) || defined(HAVE_LZ4) void *compress_buffer; size_t compress_buffer_size; #endif #ifdef HAVE_GCRYPT gcry_md_hd_t hmac; bool hmac_running; FSSHeader *fss_file; size_t fss_file_size; uint64_t fss_start_usec; uint64_t fss_interval_usec; void *fsprg_state; size_t fsprg_state_size; void *fsprg_seed; size_t fsprg_seed_size; #endif } JournalFile; int journal_file_open( const char *fname, int flags, mode_t mode, bool compress, bool seal, JournalMetrics *metrics, MMapCache *mmap_cache, JournalFile *template, JournalFile **ret); int journal_file_set_offline(JournalFile *f); JournalFile* journal_file_close(JournalFile *j); int journal_file_open_reliably( const char *fname, int flags, mode_t mode, bool compress, bool seal, JournalMetrics *metrics, MMapCache *mmap_cache, JournalFile *template, JournalFile **ret); #define ALIGN64(x) (((x) + 7ULL) & ~7ULL) #define VALID64(x) (((x) & 7ULL) == 0ULL) /* Use six characters to cover the offsets common in smallish journal * files without adding too many zeros. */ #define OFSfmt "%06"PRIx64 static inline bool VALID_REALTIME(uint64_t u) { /* This considers timestamps until the year 3112 valid. That should be plenty room... */ return u > 0 && u < (1ULL << 55); } static inline bool VALID_MONOTONIC(uint64_t u) { /* This considers timestamps until 1142 years of runtime valid. */ return u < (1ULL << 55); } static inline bool VALID_EPOCH(uint64_t u) { /* This allows changing the key for 1142 years, every usec. */ return u < (1ULL << 55); } #define JOURNAL_HEADER_CONTAINS(h, field) \ (le64toh((h)->header_size) >= offsetof(Header, field) + sizeof((h)->field)) #define JOURNAL_HEADER_SEALED(h) \ (!!(le32toh((h)->compatible_flags) & HEADER_COMPATIBLE_SEALED)) #define JOURNAL_HEADER_COMPRESSED_XZ(h) \ (!!(le32toh((h)->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED_XZ)) #define JOURNAL_HEADER_COMPRESSED_LZ4(h) \ (!!(le32toh((h)->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED_LZ4)) int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret); uint64_t journal_file_entry_n_items(Object *o) _pure_; uint64_t journal_file_entry_array_n_items(Object *o) _pure_; uint64_t journal_file_hash_table_n_items(Object *o) _pure_; int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *offset); int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqno, Object **ret, uint64_t *offset); int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset); int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset); int journal_file_find_field_object(JournalFile *f, const void *field, uint64_t size, Object **ret, uint64_t *offset); int journal_file_find_field_object_with_hash(JournalFile *f, const void *field, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset); void journal_file_reset_location(JournalFile *f); void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset); int journal_file_compare_locations(JournalFile *af, JournalFile *bf); int journal_file_next_entry(JournalFile *f, uint64_t p, direction_t direction, Object **ret, uint64_t *offset); int journal_file_next_entry_for_data(JournalFile *f, Object *o, uint64_t p, uint64_t data_offset, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_monotonic(JournalFile *f, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_offset_for_data(JournalFile *f, uint64_t data_offset, uint64_t p, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_seqnum_for_data(JournalFile *f, uint64_t data_offset, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_realtime_for_data(JournalFile *f, uint64_t data_offset, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_monotonic_for_data(JournalFile *f, uint64_t data_offset, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset); int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset); void journal_file_dump(JournalFile *f); void journal_file_print_header(JournalFile *f); int journal_file_rotate(JournalFile **f, bool compress, bool seal); void journal_file_post_change(JournalFile *f); int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t); void journal_reset_metrics(JournalMetrics *m); void journal_default_metrics(JournalMetrics *m, int fd); int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to); int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to); bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec); int journal_file_map_data_hash_table(JournalFile *f); int journal_file_map_field_hash_table(JournalFile *f); static inline bool JOURNAL_FILE_COMPRESS(JournalFile *f) { assert(f); return f->compress_xz || f->compress_lz4; } systemd-229/src/journal/journal-internal.h000066400000000000000000000066701265713322000207700ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-id128.h" #include "sd-journal.h" #include "hashmap.h" #include "journal-def.h" #include "journal-file.h" #include "list.h" #include "set.h" typedef struct Match Match; typedef struct Location Location; typedef struct Directory Directory; typedef enum MatchType { MATCH_DISCRETE, MATCH_OR_TERM, MATCH_AND_TERM } MatchType; struct Match { MatchType type; Match *parent; LIST_FIELDS(Match, matches); /* For concrete matches */ char *data; size_t size; le64_t le_hash; /* For terms */ LIST_HEAD(Match, matches); }; struct Location { LocationType type; bool seqnum_set; bool realtime_set; bool monotonic_set; bool xor_hash_set; uint64_t seqnum; sd_id128_t seqnum_id; uint64_t realtime; uint64_t monotonic; sd_id128_t boot_id; uint64_t xor_hash; }; struct Directory { char *path; int wd; bool is_root; }; struct sd_journal { char *path; char *prefix; OrderedHashmap *files; MMapCache *mmap; Location current_location; JournalFile *current_file; uint64_t current_field; Match *level0, *level1, *level2; pid_t original_pid; int inotify_fd; unsigned current_invalidate_counter, last_invalidate_counter; usec_t last_process_usec; /* Iterating through unique fields and their data values */ char *unique_field; JournalFile *unique_file; uint64_t unique_offset; /* Iterating through known fields */ JournalFile *fields_file; uint64_t fields_offset; uint64_t fields_hash_table_index; char *fields_buffer; size_t fields_buffer_allocated; int flags; bool on_network:1; bool no_new_files:1; bool unique_file_lost:1; /* File we were iterating over got removed, and there were no more files, so sd_j_enumerate_unique will return a value equal to 0. */ bool fields_file_lost:1; bool has_runtime_files:1; bool has_persistent_files:1; size_t data_threshold; Hashmap *directories_by_path; Hashmap *directories_by_wd; Hashmap *errors; }; char *journal_make_match_string(sd_journal *j); void journal_print_header(sd_journal *j); #define JOURNAL_FOREACH_DATA_RETVAL(j, data, l, retval) \ for (sd_journal_restart_data(j); ((retval) = sd_journal_enumerate_data((j), &(data), &(l))) > 0; ) systemd-229/src/journal/journal-qrcode.c000066400000000000000000000073171265713322000204230ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "journal-qrcode.h" #define WHITE_ON_BLACK "\033[40;37;1m" #define NORMAL "\033[0m" static void print_border(FILE *output, unsigned width) { unsigned x, y; /* Four rows of border */ for (y = 0; y < 4; y += 2) { fputs(WHITE_ON_BLACK, output); for (x = 0; x < 4 + width + 4; x++) fputs("\342\226\210", output); fputs(NORMAL "\n", output); } } int print_qr_code( FILE *output, const void *seed, size_t seed_size, uint64_t start, uint64_t interval, const char *hn, sd_id128_t machine) { FILE *f; char *url = NULL; size_t url_size = 0, i; QRcode* qr; unsigned x, y; assert(seed); assert(seed_size > 0); f = open_memstream(&url, &url_size); if (!f) return -ENOMEM; fputs("fss://", f); for (i = 0; i < seed_size; i++) { if (i > 0 && i % 3 == 0) fputc('-', f); fprintf(f, "%02x", ((uint8_t*) seed)[i]); } fprintf(f, "/%"PRIx64"-%"PRIx64"?machine=" SD_ID128_FORMAT_STR, start, interval, SD_ID128_FORMAT_VAL(machine)); if (hn) fprintf(f, ";hostname=%s", hn); if (ferror(f)) { fclose(f); free(url); return -ENOMEM; } fclose(f); qr = QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1); free(url); if (!qr) return -ENOMEM; print_border(output, qr->width); for (y = 0; y < (unsigned) qr->width; y += 2) { const uint8_t *row1, *row2; row1 = qr->data + qr->width * y; row2 = row1 + qr->width; fputs(WHITE_ON_BLACK, output); for (x = 0; x < 4; x++) fputs("\342\226\210", output); for (x = 0; x < (unsigned) qr->width; x ++) { bool a, b; a = row1[x] & 1; b = (y+1) < (unsigned) qr->width ? (row2[x] & 1) : false; if (a && b) fputc(' ', output); else if (a) fputs("\342\226\204", output); else if (b) fputs("\342\226\200", output); else fputs("\342\226\210", output); } for (x = 0; x < 4; x++) fputs("\342\226\210", output); fputs(NORMAL "\n", output); } print_border(output, qr->width); QRcode_free(qr); return 0; } systemd-229/src/journal/journal-qrcode.h000066400000000000000000000016451265713322000204260ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-id128.h" int print_qr_code(FILE *f, const void *seed, size_t seed_size, uint64_t start, uint64_t interval, const char *hn, sd_id128_t machine); systemd-229/src/journal/journal-send.c000066400000000000000000000403361265713322000200750ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #define SD_JOURNAL_SUPPRESS_LOCATION #include "sd-journal.h" #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "io-util.h" #include "memfd-util.h" #include "socket-util.h" #include "stdio-util.h" #include "string-util.h" #include "util.h" #define SNDBUF_SIZE (8*1024*1024) #define ALLOCA_CODE_FUNC(f, func) \ do { \ size_t _fl; \ const char *_func = (func); \ char **_f = &(f); \ _fl = strlen(_func) + 1; \ *_f = alloca(_fl + 10); \ memcpy(*_f, "CODE_FUNC=", 10); \ memcpy(*_f + 10, _func, _fl); \ } while(false) /* We open a single fd, and we'll share it with the current process, * all its threads, and all its subprocesses. This means we need to * initialize it atomically, and need to operate on it atomically * never assuming we are the only user */ static int journal_fd(void) { int fd; static int fd_plus_one = 0; retry: if (fd_plus_one > 0) return fd_plus_one - 1; fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); if (fd < 0) return -errno; fd_inc_sndbuf(fd, SNDBUF_SIZE); if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) { safe_close(fd); goto retry; } return fd; } _public_ int sd_journal_print(int priority, const char *format, ...) { int r; va_list ap; va_start(ap, format); r = sd_journal_printv(priority, format, ap); va_end(ap); return r; } _public_ int sd_journal_printv(int priority, const char *format, va_list ap) { /* FIXME: Instead of limiting things to LINE_MAX we could do a C99 variable-length array on the stack here in a loop. */ char buffer[8 + LINE_MAX], p[sizeof("PRIORITY=")-1 + DECIMAL_STR_MAX(int) + 1]; struct iovec iov[2]; assert_return(priority >= 0, -EINVAL); assert_return(priority <= 7, -EINVAL); assert_return(format, -EINVAL); xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK); memcpy(buffer, "MESSAGE=", 8); vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap); zero(iov); IOVEC_SET_STRING(iov[0], buffer); IOVEC_SET_STRING(iov[1], p); return sd_journal_sendv(iov, 2); } _printf_(1, 0) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) { PROTECT_ERRNO; int r, n = 0, i = 0, j; struct iovec *iov = NULL; assert(_iov); if (extra > 0) { n = MAX(extra * 2, extra + 4); iov = malloc0(n * sizeof(struct iovec)); if (!iov) { r = -ENOMEM; goto fail; } i = extra; } while (format) { struct iovec *c; char *buffer; va_list aq; if (i >= n) { n = MAX(i*2, 4); c = realloc(iov, n * sizeof(struct iovec)); if (!c) { r = -ENOMEM; goto fail; } iov = c; } va_copy(aq, ap); if (vasprintf(&buffer, format, aq) < 0) { va_end(aq); r = -ENOMEM; goto fail; } va_end(aq); VA_FORMAT_ADVANCE(format, ap); IOVEC_SET_STRING(iov[i++], buffer); format = va_arg(ap, char *); } *_iov = iov; return i; fail: for (j = 0; j < i; j++) free(iov[j].iov_base); free(iov); return r; } _public_ int sd_journal_send(const char *format, ...) { int r, i, j; va_list ap; struct iovec *iov = NULL; va_start(ap, format); i = fill_iovec_sprintf(format, ap, 0, &iov); va_end(ap); if (_unlikely_(i < 0)) { r = i; goto finish; } r = sd_journal_sendv(iov, i); finish: for (j = 0; j < i; j++) free(iov[j].iov_base); free(iov); return r; } _public_ int sd_journal_sendv(const struct iovec *iov, int n) { PROTECT_ERRNO; int fd, r; _cleanup_close_ int buffer_fd = -1; struct iovec *w; uint64_t *l; int i, j = 0; struct sockaddr_un sa = { .sun_family = AF_UNIX, .sun_path = "/run/systemd/journal/socket", }; struct msghdr mh = { .msg_name = &sa, .msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path), }; ssize_t k; bool have_syslog_identifier = false; bool seal = true; assert_return(iov, -EINVAL); assert_return(n > 0, -EINVAL); w = newa(struct iovec, n * 5 + 3); l = newa(uint64_t, n); for (i = 0; i < n; i++) { char *c, *nl; if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1)) return -EINVAL; c = memchr(iov[i].iov_base, '=', iov[i].iov_len); if (_unlikely_(!c || c == iov[i].iov_base)) return -EINVAL; have_syslog_identifier = have_syslog_identifier || (c == (char *) iov[i].iov_base + 17 && startswith(iov[i].iov_base, "SYSLOG_IDENTIFIER")); nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len); if (nl) { if (_unlikely_(nl < c)) return -EINVAL; /* Already includes a newline? Bummer, then * let's write the variable name, then a * newline, then the size (64bit LE), followed * by the data and a final newline */ w[j].iov_base = iov[i].iov_base; w[j].iov_len = c - (char*) iov[i].iov_base; j++; IOVEC_SET_STRING(w[j++], "\n"); l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1); w[j].iov_base = &l[i]; w[j].iov_len = sizeof(uint64_t); j++; w[j].iov_base = c + 1; w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1; j++; } else /* Nothing special? Then just add the line and * append a newline */ w[j++] = iov[i]; IOVEC_SET_STRING(w[j++], "\n"); } if (!have_syslog_identifier && string_is_safe(program_invocation_short_name)) { /* Implicitly add program_invocation_short_name, if it * is not set explicitly. We only do this for * program_invocation_short_name, and nothing else * since everything else is much nicer to retrieve * from the outside. */ IOVEC_SET_STRING(w[j++], "SYSLOG_IDENTIFIER="); IOVEC_SET_STRING(w[j++], program_invocation_short_name); IOVEC_SET_STRING(w[j++], "\n"); } fd = journal_fd(); if (_unlikely_(fd < 0)) return fd; mh.msg_iov = w; mh.msg_iovlen = j; k = sendmsg(fd, &mh, MSG_NOSIGNAL); if (k >= 0) return 0; /* Fail silently if the journal is not available */ if (errno == ENOENT) return 0; if (errno != EMSGSIZE && errno != ENOBUFS) return -errno; /* Message doesn't fit... Let's dump the data in a memfd or * temporary file and just pass a file descriptor of it to the * other side. * * For the temporary files we use /dev/shm instead of /tmp * here, since we want this to be a tmpfs, and one that is * available from early boot on and where unprivileged users * can create files. */ buffer_fd = memfd_new(NULL); if (buffer_fd < 0) { if (buffer_fd == -ENOSYS) { buffer_fd = open_tmpfile("/dev/shm", O_RDWR | O_CLOEXEC); if (buffer_fd < 0) return buffer_fd; seal = false; } else return buffer_fd; } n = writev(buffer_fd, w, j); if (n < 0) return -errno; if (seal) { r = memfd_set_sealed(buffer_fd); if (r < 0) return r; } r = send_one_fd_sa(fd, buffer_fd, mh.msg_name, mh.msg_namelen, 0); if (r == -ENOENT) /* Fail silently if the journal is not available */ return 0; return r; } static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) { PROTECT_ERRNO; size_t n, k; k = isempty(message) ? 0 : strlen(message) + 2; n = 8 + k + 256 + 1; for (;;) { char buffer[n]; char* j; errno = 0; j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k); if (errno == 0) { char error[sizeof("ERRNO=")-1 + DECIMAL_STR_MAX(int) + 1]; if (j != buffer + 8 + k) memmove(buffer + 8 + k, j, strlen(j)+1); memcpy(buffer, "MESSAGE=", 8); if (k > 0) { memcpy(buffer + 8, message, k - 2); memcpy(buffer + 8 + k - 2, ": ", 2); } xsprintf(error, "ERRNO=%i", _saved_errno_); assert_cc(3 == LOG_ERR); IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3"); IOVEC_SET_STRING(iov[skip+1], buffer); IOVEC_SET_STRING(iov[skip+2], error); return sd_journal_sendv(iov, skip + 3); } if (errno != ERANGE) return -errno; n *= 2; } } _public_ int sd_journal_perror(const char *message) { struct iovec iovec[3]; return fill_iovec_perror_and_send(message, 0, iovec); } _public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) { union sockaddr_union sa = { .un.sun_family = AF_UNIX, .un.sun_path = "/run/systemd/journal/stdout", }; _cleanup_close_ int fd = -1; char *header; size_t l; int r; assert_return(priority >= 0, -EINVAL); assert_return(priority <= 7, -EINVAL); fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); if (fd < 0) return -errno; r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)); if (r < 0) return -errno; if (shutdown(fd, SHUT_RD) < 0) return -errno; fd_inc_sndbuf(fd, SNDBUF_SIZE); if (!identifier) identifier = ""; l = strlen(identifier); header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2); memcpy(header, identifier, l); header[l++] = '\n'; header[l++] = '\n'; /* unit id */ header[l++] = '0' + priority; header[l++] = '\n'; header[l++] = '0' + !!level_prefix; header[l++] = '\n'; header[l++] = '0'; header[l++] = '\n'; header[l++] = '0'; header[l++] = '\n'; header[l++] = '0'; header[l++] = '\n'; r = loop_write(fd, header, l, false); if (r < 0) return r; r = fd; fd = -1; return r; } _public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) { int r; va_list ap; va_start(ap, format); r = sd_journal_printv_with_location(priority, file, line, func, format, ap); va_end(ap); return r; } _public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) { char buffer[8 + LINE_MAX], p[sizeof("PRIORITY=")-1 + DECIMAL_STR_MAX(int) + 1]; struct iovec iov[5]; char *f; assert_return(priority >= 0, -EINVAL); assert_return(priority <= 7, -EINVAL); assert_return(format, -EINVAL); xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK); memcpy(buffer, "MESSAGE=", 8); vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap); /* func is initialized from __func__ which is not a macro, but * a static const char[], hence cannot easily be prefixed with * CODE_FUNC=, hence let's do it manually here. */ ALLOCA_CODE_FUNC(f, func); zero(iov); IOVEC_SET_STRING(iov[0], buffer); IOVEC_SET_STRING(iov[1], p); IOVEC_SET_STRING(iov[2], file); IOVEC_SET_STRING(iov[3], line); IOVEC_SET_STRING(iov[4], f); return sd_journal_sendv(iov, ELEMENTSOF(iov)); } _public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) { int r, i, j; va_list ap; struct iovec *iov = NULL; char *f; va_start(ap, format); i = fill_iovec_sprintf(format, ap, 3, &iov); va_end(ap); if (_unlikely_(i < 0)) { r = i; goto finish; } ALLOCA_CODE_FUNC(f, func); IOVEC_SET_STRING(iov[0], file); IOVEC_SET_STRING(iov[1], line); IOVEC_SET_STRING(iov[2], f); r = sd_journal_sendv(iov, i); finish: for (j = 3; j < i; j++) free(iov[j].iov_base); free(iov); return r; } _public_ int sd_journal_sendv_with_location( const char *file, const char *line, const char *func, const struct iovec *iov, int n) { struct iovec *niov; char *f; assert_return(iov, -EINVAL); assert_return(n > 0, -EINVAL); niov = alloca(sizeof(struct iovec) * (n + 3)); memcpy(niov, iov, sizeof(struct iovec) * n); ALLOCA_CODE_FUNC(f, func); IOVEC_SET_STRING(niov[n++], file); IOVEC_SET_STRING(niov[n++], line); IOVEC_SET_STRING(niov[n++], f); return sd_journal_sendv(niov, n); } _public_ int sd_journal_perror_with_location( const char *file, const char *line, const char *func, const char *message) { struct iovec iov[6]; char *f; ALLOCA_CODE_FUNC(f, func); IOVEC_SET_STRING(iov[0], file); IOVEC_SET_STRING(iov[1], line); IOVEC_SET_STRING(iov[2], f); return fill_iovec_perror_and_send(message, 3, iov); } systemd-229/src/journal/journal-vacuum.c000066400000000000000000000272351265713322000204470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-id128.h" #include "alloc-util.h" #include "dirent-util.h" #include "fd-util.h" #include "journal-def.h" #include "journal-file.h" #include "journal-vacuum.h" #include "parse-util.h" #include "string-util.h" #include "util.h" #include "xattr-util.h" struct vacuum_info { uint64_t usage; char *filename; uint64_t realtime; sd_id128_t seqnum_id; uint64_t seqnum; bool have_seqnum; }; static int vacuum_compare(const void *_a, const void *_b) { const struct vacuum_info *a, *b; a = _a; b = _b; if (a->have_seqnum && b->have_seqnum && sd_id128_equal(a->seqnum_id, b->seqnum_id)) { if (a->seqnum < b->seqnum) return -1; else if (a->seqnum > b->seqnum) return 1; else return 0; } if (a->realtime < b->realtime) return -1; else if (a->realtime > b->realtime) return 1; else if (a->have_seqnum && b->have_seqnum) return memcmp(&a->seqnum_id, &b->seqnum_id, 16); else return strcmp(a->filename, b->filename); } static void patch_realtime( int fd, const char *fn, const struct stat *st, unsigned long long *realtime) { usec_t x, crtime = 0; /* The timestamp was determined by the file name, but let's * see if the file might actually be older than the file name * suggested... */ assert(fd >= 0); assert(fn); assert(st); assert(realtime); x = timespec_load(&st->st_ctim); if (x > 0 && x != USEC_INFINITY && x < *realtime) *realtime = x; x = timespec_load(&st->st_atim); if (x > 0 && x != USEC_INFINITY && x < *realtime) *realtime = x; x = timespec_load(&st->st_mtim); if (x > 0 && x != USEC_INFINITY && x < *realtime) *realtime = x; /* Let's read the original creation time, if possible. Ideally * we'd just query the creation time the FS might provide, but * unfortunately there's currently no sane API to query * it. Hence let's implement this manually... */ if (fd_getcrtime_at(fd, fn, &crtime, 0) >= 0) { if (crtime < *realtime) *realtime = crtime; } } static int journal_file_empty(int dir_fd, const char *name) { _cleanup_close_ int fd; struct stat st; le64_t n_entries; ssize_t n; fd = openat(dir_fd, name, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK|O_NOATIME); if (fd < 0) { /* Maybe failed due to O_NOATIME and lack of privileges? */ fd = openat(dir_fd, name, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK); if (fd < 0) return -errno; } if (fstat(fd, &st) < 0) return -errno; /* If an offline file doesn't even have a header we consider it empty */ if (st.st_size < (off_t) sizeof(Header)) return 1; /* If the number of entries is empty, we consider it empty, too */ n = pread(fd, &n_entries, sizeof(n_entries), offsetof(Header, n_entries)); if (n < 0) return -errno; if (n != sizeof(n_entries)) return -EIO; return le64toh(n_entries) <= 0; } int journal_directory_vacuum( const char *directory, uint64_t max_use, uint64_t n_max_files, usec_t max_retention_usec, usec_t *oldest_usec, bool verbose) { _cleanup_closedir_ DIR *d = NULL; struct vacuum_info *list = NULL; unsigned n_list = 0, i, n_active_files = 0; size_t n_allocated = 0; uint64_t sum = 0, freed = 0; usec_t retention_limit = 0; char sbytes[FORMAT_BYTES_MAX]; struct dirent *de; int r; assert(directory); if (max_use <= 0 && max_retention_usec <= 0 && n_max_files <= 0) return 0; if (max_retention_usec > 0) { retention_limit = now(CLOCK_REALTIME); if (retention_limit > max_retention_usec) retention_limit -= max_retention_usec; else max_retention_usec = retention_limit = 0; } d = opendir(directory); if (!d) return -errno; FOREACH_DIRENT_ALL(de, d, r = -errno; goto finish) { unsigned long long seqnum = 0, realtime; _cleanup_free_ char *p = NULL; sd_id128_t seqnum_id; bool have_seqnum; uint64_t size; struct stat st; size_t q; if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { log_debug_errno(errno, "Failed to stat file %s while vacuuming, ignoring: %m", de->d_name); continue; } if (!S_ISREG(st.st_mode)) continue; q = strlen(de->d_name); if (endswith(de->d_name, ".journal")) { /* Vacuum archived files. Active files are * left around */ if (q < 1 + 32 + 1 + 16 + 1 + 16 + 8) { n_active_files++; continue; } if (de->d_name[q-8-16-1] != '-' || de->d_name[q-8-16-1-16-1] != '-' || de->d_name[q-8-16-1-16-1-32-1] != '@') { n_active_files++; continue; } p = strdup(de->d_name); if (!p) { r = -ENOMEM; goto finish; } de->d_name[q-8-16-1-16-1] = 0; if (sd_id128_from_string(de->d_name + q-8-16-1-16-1-32, &seqnum_id) < 0) { n_active_files++; continue; } if (sscanf(de->d_name + q-8-16-1-16, "%16llx-%16llx.journal", &seqnum, &realtime) != 2) { n_active_files++; continue; } have_seqnum = true; } else if (endswith(de->d_name, ".journal~")) { unsigned long long tmp; /* Vacuum corrupted files */ if (q < 1 + 16 + 1 + 16 + 8 + 1) { n_active_files ++; continue; } if (de->d_name[q-1-8-16-1] != '-' || de->d_name[q-1-8-16-1-16-1] != '@') { n_active_files ++; continue; } p = strdup(de->d_name); if (!p) { r = -ENOMEM; goto finish; } if (sscanf(de->d_name + q-1-8-16-1-16, "%16llx-%16llx.journal~", &realtime, &tmp) != 2) { n_active_files ++; continue; } have_seqnum = false; } else { /* We do not vacuum unknown files! */ log_debug("Not vacuuming unknown file %s.", de->d_name); continue; } size = 512UL * (uint64_t) st.st_blocks; r = journal_file_empty(dirfd(d), p); if (r < 0) { log_debug_errno(r, "Failed check if %s is empty, ignoring: %m", p); continue; } if (r > 0) { /* Always vacuum empty non-online files. */ if (unlinkat(dirfd(d), p, 0) >= 0) { log_full(verbose ? LOG_INFO : LOG_DEBUG, "Deleted empty archived journal %s/%s (%s).", directory, p, format_bytes(sbytes, sizeof(sbytes), size)); freed += size; } else if (errno != ENOENT) log_warning_errno(errno, "Failed to delete empty archived journal %s/%s: %m", directory, p); continue; } patch_realtime(dirfd(d), p, &st, &realtime); if (!GREEDY_REALLOC(list, n_allocated, n_list + 1)) { r = -ENOMEM; goto finish; } list[n_list].filename = p; list[n_list].usage = size; list[n_list].seqnum = seqnum; list[n_list].realtime = realtime; list[n_list].seqnum_id = seqnum_id; list[n_list].have_seqnum = have_seqnum; n_list ++; p = NULL; sum += size; } qsort_safe(list, n_list, sizeof(struct vacuum_info), vacuum_compare); for (i = 0; i < n_list; i++) { unsigned left; left = n_active_files + n_list - i; if ((max_retention_usec <= 0 || list[i].realtime >= retention_limit) && (max_use <= 0 || sum <= max_use) && (n_max_files <= 0 || left <= n_max_files)) break; if (unlinkat(dirfd(d), list[i].filename, 0) >= 0) { log_full(verbose ? LOG_INFO : LOG_DEBUG, "Deleted archived journal %s/%s (%s).", directory, list[i].filename, format_bytes(sbytes, sizeof(sbytes), list[i].usage)); freed += list[i].usage; if (list[i].usage < sum) sum -= list[i].usage; else sum = 0; } else if (errno != ENOENT) log_warning_errno(errno, "Failed to delete archived journal %s/%s: %m", directory, list[i].filename); } if (oldest_usec && i < n_list && (*oldest_usec == 0 || list[i].realtime < *oldest_usec)) *oldest_usec = list[i].realtime; r = 0; finish: for (i = 0; i < n_list; i++) free(list[i].filename); free(list); log_full(verbose ? LOG_INFO : LOG_DEBUG, "Vacuuming done, freed %s of archived journals on disk.", format_bytes(sbytes, sizeof(sbytes), freed)); return r; } systemd-229/src/journal/journal-vacuum.h000066400000000000000000000016741265713322000204530ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "time-util.h" int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t n_max_files, usec_t max_retention_usec, usec_t *oldest_usec, bool verbose); systemd-229/src/journal/journal-verify.c000066400000000000000000001357561265713322000204630ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "compress.h" #include "fd-util.h" #include "fileio.h" #include "journal-authenticate.h" #include "journal-def.h" #include "journal-file.h" #include "journal-verify.h" #include "lookup3.h" #include "macro.h" #include "terminal-util.h" #include "util.h" static void draw_progress(uint64_t p, usec_t *last_usec) { unsigned n, i, j, k; usec_t z, x; if (!on_tty()) return; z = now(CLOCK_MONOTONIC); x = *last_usec; if (x != 0 && x + 40 * USEC_PER_MSEC > z) return; *last_usec = z; n = (3 * columns()) / 4; j = (n * (unsigned) p) / 65535ULL; k = n - j; fputs("\r\x1B[?25l" ANSI_HIGHLIGHT_GREEN, stdout); for (i = 0; i < j; i++) fputs("\xe2\x96\x88", stdout); fputs(ANSI_NORMAL, stdout); for (i = 0; i < k; i++) fputs("\xe2\x96\x91", stdout); printf(" %3"PRIu64"%%", 100U * p / 65535U); fputs("\r\x1B[?25h", stdout); fflush(stdout); } static uint64_t scale_progress(uint64_t scale, uint64_t p, uint64_t m) { /* Calculates scale * p / m, but handles m == 0 safely, and saturates */ if (p >= m || m == 0) return scale; return scale * p / m; } static void flush_progress(void) { unsigned n, i; if (!on_tty()) return; n = (3 * columns()) / 4; putchar('\r'); for (i = 0; i < n + 5; i++) putchar(' '); putchar('\r'); fflush(stdout); } #define debug(_offset, _fmt, ...) do{ \ flush_progress(); \ log_debug(OFSfmt": " _fmt, _offset, ##__VA_ARGS__); \ } while(0) #define warning(_offset, _fmt, ...) do{ \ flush_progress(); \ log_warning(OFSfmt": " _fmt, _offset, ##__VA_ARGS__); \ } while(0) #define error(_offset, _fmt, ...) do{ \ flush_progress(); \ log_error(OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \ } while(0) static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o) { uint64_t i; assert(f); assert(offset); assert(o); /* This does various superficial tests about the length an * possible field values. It does not follow any references to * other objects. */ if ((o->object.flags & OBJECT_COMPRESSED_XZ) && o->object.type != OBJECT_DATA) { error(offset, "Found compressed object that isn't of type DATA, which is not allowed."); return -EBADMSG; } switch (o->object.type) { case OBJECT_DATA: { uint64_t h1, h2; int compression, r; if (le64toh(o->data.entry_offset) == 0) warning(offset, "Unused data (entry_offset==0)"); if ((le64toh(o->data.entry_offset) == 0) ^ (le64toh(o->data.n_entries) == 0)) { error(offset, "Bad n_entries: %"PRIu64, o->data.n_entries); return -EBADMSG; } if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0) { error(offset, "Bad object size (<= %zu): %"PRIu64, offsetof(DataObject, payload), le64toh(o->object.size)); return -EBADMSG; } h1 = le64toh(o->data.hash); compression = o->object.flags & OBJECT_COMPRESSION_MASK; if (compression) { _cleanup_free_ void *b = NULL; size_t alloc = 0, b_size; r = decompress_blob(compression, o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload), &b, &alloc, &b_size, 0); if (r < 0) { error(offset, "%s decompression failed: %s", object_compressed_to_string(compression), strerror(-r)); return r; } h2 = hash64(b, b_size); } else h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload)); if (h1 != h2) { error(offset, "Invalid hash (%08"PRIx64" vs. %08"PRIx64, h1, h2); return -EBADMSG; } if (!VALID64(o->data.next_hash_offset) || !VALID64(o->data.next_field_offset) || !VALID64(o->data.entry_offset) || !VALID64(o->data.entry_array_offset)) { error(offset, "Invalid offset (next_hash_offset="OFSfmt", next_field_offset="OFSfmt", entry_offset="OFSfmt", entry_array_offset="OFSfmt, o->data.next_hash_offset, o->data.next_field_offset, o->data.entry_offset, o->data.entry_array_offset); return -EBADMSG; } break; } case OBJECT_FIELD: if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0) { error(offset, "Bad field size (<= %zu): %"PRIu64, offsetof(FieldObject, payload), le64toh(o->object.size)); return -EBADMSG; } if (!VALID64(o->field.next_hash_offset) || !VALID64(o->field.head_data_offset)) { error(offset, "Invalid offset (next_hash_offset="OFSfmt", head_data_offset="OFSfmt, o->field.next_hash_offset, o->field.head_data_offset); return -EBADMSG; } break; case OBJECT_ENTRY: if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0) { error(offset, "Bad entry size (<= %zu): %"PRIu64, offsetof(EntryObject, items), le64toh(o->object.size)); return -EBADMSG; } if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0) { error(offset, "Invalid number items in entry: %"PRIu64, (le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem)); return -EBADMSG; } if (le64toh(o->entry.seqnum) <= 0) { error(offset, "Invalid entry seqnum: %"PRIx64, le64toh(o->entry.seqnum)); return -EBADMSG; } if (!VALID_REALTIME(le64toh(o->entry.realtime))) { error(offset, "Invalid entry realtime timestamp: %"PRIu64, le64toh(o->entry.realtime)); return -EBADMSG; } if (!VALID_MONOTONIC(le64toh(o->entry.monotonic))) { error(offset, "Invalid entry monotonic timestamp: %"PRIu64, le64toh(o->entry.monotonic)); return -EBADMSG; } for (i = 0; i < journal_file_entry_n_items(o); i++) { if (o->entry.items[i].object_offset == 0 || !VALID64(o->entry.items[i].object_offset)) { error(offset, "Invalid entry item (%"PRIu64"/%"PRIu64" offset: "OFSfmt, i, journal_file_entry_n_items(o), o->entry.items[i].object_offset); return -EBADMSG; } } break; case OBJECT_DATA_HASH_TABLE: case OBJECT_FIELD_HASH_TABLE: if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0 || (le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0) { error(offset, "Invalid %s hash table size: %"PRIu64, o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field", le64toh(o->object.size)); return -EBADMSG; } for (i = 0; i < journal_file_hash_table_n_items(o); i++) { if (o->hash_table.items[i].head_hash_offset != 0 && !VALID64(le64toh(o->hash_table.items[i].head_hash_offset))) { error(offset, "Invalid %s hash table item (%"PRIu64"/%"PRIu64") head_hash_offset: "OFSfmt, o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field", i, journal_file_hash_table_n_items(o), le64toh(o->hash_table.items[i].head_hash_offset)); return -EBADMSG; } if (o->hash_table.items[i].tail_hash_offset != 0 && !VALID64(le64toh(o->hash_table.items[i].tail_hash_offset))) { error(offset, "Invalid %s hash table item (%"PRIu64"/%"PRIu64") tail_hash_offset: "OFSfmt, o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field", i, journal_file_hash_table_n_items(o), le64toh(o->hash_table.items[i].tail_hash_offset)); return -EBADMSG; } if ((o->hash_table.items[i].head_hash_offset != 0) != (o->hash_table.items[i].tail_hash_offset != 0)) { error(offset, "Invalid %s hash table item (%"PRIu64"/%"PRIu64"): head_hash_offset="OFSfmt" tail_hash_offset="OFSfmt, o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field", i, journal_file_hash_table_n_items(o), le64toh(o->hash_table.items[i].head_hash_offset), le64toh(o->hash_table.items[i].tail_hash_offset)); return -EBADMSG; } } break; case OBJECT_ENTRY_ARRAY: if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0 || (le64toh(o->object.size) - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0) { error(offset, "Invalid object entry array size: %"PRIu64, le64toh(o->object.size)); return -EBADMSG; } if (!VALID64(o->entry_array.next_entry_array_offset)) { error(offset, "Invalid object entry array next_entry_array_offset: "OFSfmt, o->entry_array.next_entry_array_offset); return -EBADMSG; } for (i = 0; i < journal_file_entry_array_n_items(o); i++) if (le64toh(o->entry_array.items[i]) != 0 && !VALID64(le64toh(o->entry_array.items[i]))) { error(offset, "Invalid object entry array item (%"PRIu64"/%"PRIu64"): "OFSfmt, i, journal_file_entry_array_n_items(o), le64toh(o->entry_array.items[i])); return -EBADMSG; } break; case OBJECT_TAG: if (le64toh(o->object.size) != sizeof(TagObject)) { error(offset, "Invalid object tag size: %"PRIu64, le64toh(o->object.size)); return -EBADMSG; } if (!VALID_EPOCH(o->tag.epoch)) { error(offset, "Invalid object tag epoch: %"PRIu64, o->tag.epoch); return -EBADMSG; } break; } return 0; } static int write_uint64(int fd, uint64_t p) { ssize_t k; k = write(fd, &p, sizeof(p)); if (k < 0) return -errno; if (k != sizeof(p)) return -EIO; return 0; } static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) { uint64_t a, b; int r; assert(m); assert(fd >= 0); /* Bisection ... */ a = 0; b = n; while (a < b) { uint64_t c, *z; c = (a + b) / 2; r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z); if (r < 0) return r; if (*z == p) return 1; if (a + 1 >= b) return 0; if (p < *z) b = c; else a = c; } return 0; } static int entry_points_to_data( JournalFile *f, int entry_fd, uint64_t n_entries, uint64_t entry_p, uint64_t data_p) { int r; uint64_t i, n, a; Object *o; bool found = false; assert(f); assert(entry_fd >= 0); if (!contains_uint64(f->mmap, entry_fd, n_entries, entry_p)) { error(data_p, "Data object references invalid entry at "OFSfmt, entry_p); return -EBADMSG; } r = journal_file_move_to_object(f, OBJECT_ENTRY, entry_p, &o); if (r < 0) return r; n = journal_file_entry_n_items(o); for (i = 0; i < n; i++) if (le64toh(o->entry.items[i].object_offset) == data_p) { found = true; break; } if (!found) { error(entry_p, "Data object at "OFSfmt" not referenced by linked entry", data_p); return -EBADMSG; } /* Check if this entry is also in main entry array. Since the * main entry array has already been verified we can rely on * its consistency. */ i = 0; n = le64toh(f->header->n_entries); a = le64toh(f->header->entry_array_offset); while (i < n) { uint64_t m, u; r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); if (r < 0) return r; m = journal_file_entry_array_n_items(o); u = MIN(n - i, m); if (entry_p <= le64toh(o->entry_array.items[u-1])) { uint64_t x, y, z; x = 0; y = u; while (x < y) { z = (x + y) / 2; if (le64toh(o->entry_array.items[z]) == entry_p) return 0; if (x + 1 >= y) break; if (entry_p < le64toh(o->entry_array.items[z])) y = z; else x = z; } error(entry_p, "Entry object doesn't exist in main entry array"); return -EBADMSG; } i += u; a = le64toh(o->entry_array.next_entry_array_offset); } return 0; } static int verify_data( JournalFile *f, Object *o, uint64_t p, int entry_fd, uint64_t n_entries, int entry_array_fd, uint64_t n_entry_arrays) { uint64_t i, n, a, last, q; int r; assert(f); assert(o); assert(entry_fd >= 0); assert(entry_array_fd >= 0); n = le64toh(o->data.n_entries); a = le64toh(o->data.entry_array_offset); /* Entry array means at least two objects */ if (a && n < 2) { error(p, "Entry array present (entry_array_offset="OFSfmt", but n_entries=%"PRIu64")", a, n); return -EBADMSG; } if (n == 0) return 0; /* We already checked that earlier */ assert(o->data.entry_offset); last = q = le64toh(o->data.entry_offset); r = entry_points_to_data(f, entry_fd, n_entries, q, p); if (r < 0) return r; i = 1; while (i < n) { uint64_t next, m, j; if (a == 0) { error(p, "Array chain too short"); return -EBADMSG; } if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) { error(p, "Invalid array offset "OFSfmt, a); return -EBADMSG; } r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); if (r < 0) return r; next = le64toh(o->entry_array.next_entry_array_offset); if (next != 0 && next <= a) { error(p, "Array chain has cycle (jumps back from "OFSfmt" to "OFSfmt")", a, next); return -EBADMSG; } m = journal_file_entry_array_n_items(o); for (j = 0; i < n && j < m; i++, j++) { q = le64toh(o->entry_array.items[j]); if (q <= last) { error(p, "Data object's entry array not sorted"); return -EBADMSG; } last = q; r = entry_points_to_data(f, entry_fd, n_entries, q, p); if (r < 0) return r; /* Pointer might have moved, reposition */ r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); if (r < 0) return r; } a = next; } return 0; } static int verify_hash_table( JournalFile *f, int data_fd, uint64_t n_data, int entry_fd, uint64_t n_entries, int entry_array_fd, uint64_t n_entry_arrays, usec_t *last_usec, bool show_progress) { uint64_t i, n; int r; assert(f); assert(data_fd >= 0); assert(entry_fd >= 0); assert(entry_array_fd >= 0); assert(last_usec); n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem); if (n <= 0) return 0; r = journal_file_map_data_hash_table(f); if (r < 0) return log_error_errno(r, "Failed to map data hash table: %m"); for (i = 0; i < n; i++) { uint64_t last = 0, p; if (show_progress) draw_progress(0xC000 + scale_progress(0x3FFF, i, n), last_usec); p = le64toh(f->data_hash_table[i].head_hash_offset); while (p != 0) { Object *o; uint64_t next; if (!contains_uint64(f->mmap, data_fd, n_data, p)) { error(p, "Invalid data object at hash entry %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; next = le64toh(o->data.next_hash_offset); if (next != 0 && next <= p) { error(p, "Hash chain has a cycle in hash entry %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } if (le64toh(o->data.hash) % n != i) { error(p, "Hash value mismatch in hash entry %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } r = verify_data(f, o, p, entry_fd, n_entries, entry_array_fd, n_entry_arrays); if (r < 0) return r; last = p; p = next; } if (last != le64toh(f->data_hash_table[i].tail_hash_offset)) { error(p, "Tail hash pointer mismatch in hash table"); return -EBADMSG; } } return 0; } static int data_object_in_hash_table(JournalFile *f, uint64_t hash, uint64_t p) { uint64_t n, h, q; int r; assert(f); n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem); if (n <= 0) return 0; r = journal_file_map_data_hash_table(f); if (r < 0) return log_error_errno(r, "Failed to map data hash table: %m"); h = hash % n; q = le64toh(f->data_hash_table[h].head_hash_offset); while (q != 0) { Object *o; if (p == q) return 1; r = journal_file_move_to_object(f, OBJECT_DATA, q, &o); if (r < 0) return r; q = le64toh(o->data.next_hash_offset); } return 0; } static int verify_entry( JournalFile *f, Object *o, uint64_t p, int data_fd, uint64_t n_data) { uint64_t i, n; int r; assert(f); assert(o); assert(data_fd >= 0); n = journal_file_entry_n_items(o); for (i = 0; i < n; i++) { uint64_t q, h; Object *u; q = le64toh(o->entry.items[i].object_offset); h = le64toh(o->entry.items[i].hash); if (!contains_uint64(f->mmap, data_fd, n_data, q)) { error(p, "Invalid data object of entry"); return -EBADMSG; } r = journal_file_move_to_object(f, OBJECT_DATA, q, &u); if (r < 0) return r; if (le64toh(u->data.hash) != h) { error(p, "Hash mismatch for data object of entry"); return -EBADMSG; } r = data_object_in_hash_table(f, h, q); if (r < 0) return r; if (r == 0) { error(p, "Data object missing from hash table"); return -EBADMSG; } } return 0; } static int verify_entry_array( JournalFile *f, int data_fd, uint64_t n_data, int entry_fd, uint64_t n_entries, int entry_array_fd, uint64_t n_entry_arrays, usec_t *last_usec, bool show_progress) { uint64_t i = 0, a, n, last = 0; int r; assert(f); assert(data_fd >= 0); assert(entry_fd >= 0); assert(entry_array_fd >= 0); assert(last_usec); n = le64toh(f->header->n_entries); a = le64toh(f->header->entry_array_offset); while (i < n) { uint64_t next, m, j; Object *o; if (show_progress) draw_progress(0x8000 + scale_progress(0x3FFF, i, n), last_usec); if (a == 0) { error(a, "Array chain too short at %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) { error(a, "Invalid array %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); if (r < 0) return r; next = le64toh(o->entry_array.next_entry_array_offset); if (next != 0 && next <= a) { error(a, "Array chain has cycle at %"PRIu64" of %"PRIu64" (jumps back from to "OFSfmt")", i, n, next); return -EBADMSG; } m = journal_file_entry_array_n_items(o); for (j = 0; i < n && j < m; i++, j++) { uint64_t p; p = le64toh(o->entry_array.items[j]); if (p <= last) { error(a, "Entry array not sorted at %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } last = p; if (!contains_uint64(f->mmap, entry_fd, n_entries, p)) { error(a, "Invalid array entry at %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); if (r < 0) return r; r = verify_entry(f, o, p, data_fd, n_data); if (r < 0) return r; /* Pointer might have moved, reposition */ r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); if (r < 0) return r; } a = next; } return 0; } int journal_file_verify( JournalFile *f, const char *key, usec_t *first_contained, usec_t *last_validated, usec_t *last_contained, bool show_progress) { int r; Object *o; uint64_t p = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0; uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0; sd_id128_t entry_boot_id; bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false; uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0; usec_t last_usec = 0; int data_fd = -1, entry_fd = -1, entry_array_fd = -1; unsigned i; bool found_last = false; #ifdef HAVE_GCRYPT uint64_t last_tag = 0; #endif assert(f); if (key) { #ifdef HAVE_GCRYPT r = journal_file_parse_verification_key(f, key); if (r < 0) { log_error("Failed to parse seed."); return r; } #else return -EOPNOTSUPP; #endif } else if (f->seal) return -ENOKEY; data_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC); if (data_fd < 0) { r = log_error_errno(data_fd, "Failed to create data file: %m"); goto fail; } entry_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC); if (entry_fd < 0) { r = log_error_errno(entry_fd, "Failed to create entry file: %m"); goto fail; } entry_array_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC); if (entry_array_fd < 0) { r = log_error_errno(entry_array_fd, "Failed to create entry array file: %m"); goto fail; } if (le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SUPPORTED) { log_error("Cannot verify file with unknown extensions."); r = -EOPNOTSUPP; goto fail; } for (i = 0; i < sizeof(f->header->reserved); i++) if (f->header->reserved[i] != 0) { error(offsetof(Header, reserved[i]), "Reserved field is non-zero"); r = -EBADMSG; goto fail; } /* First iteration: we go through all objects, verify the * superficial structure, headers, hashes. */ p = le64toh(f->header->header_size); for (;;) { /* Early exit if there are no objects in the file, at all */ if (le64toh(f->header->tail_object_offset) == 0) break; if (show_progress) draw_progress(scale_progress(0x7FFF, p, le64toh(f->header->tail_object_offset)), &last_usec); r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o); if (r < 0) { error(p, "Invalid object"); goto fail; } if (p > le64toh(f->header->tail_object_offset)) { error(offsetof(Header, tail_object_offset), "Invalid tail object pointer"); r = -EBADMSG; goto fail; } n_objects ++; r = journal_file_object_verify(f, p, o); if (r < 0) { error(p, "Invalid object contents: %s", strerror(-r)); goto fail; } if ((o->object.flags & OBJECT_COMPRESSED_XZ) && (o->object.flags & OBJECT_COMPRESSED_LZ4)) { error(p, "Objected with double compression"); r = -EINVAL; goto fail; } if ((o->object.flags & OBJECT_COMPRESSED_XZ) && !JOURNAL_HEADER_COMPRESSED_XZ(f->header)) { error(p, "XZ compressed object in file without XZ compression"); r = -EBADMSG; goto fail; } if ((o->object.flags & OBJECT_COMPRESSED_LZ4) && !JOURNAL_HEADER_COMPRESSED_LZ4(f->header)) { error(p, "LZ4 compressed object in file without LZ4 compression"); r = -EBADMSG; goto fail; } switch (o->object.type) { case OBJECT_DATA: r = write_uint64(data_fd, p); if (r < 0) goto fail; n_data++; break; case OBJECT_FIELD: n_fields++; break; case OBJECT_ENTRY: if (JOURNAL_HEADER_SEALED(f->header) && n_tags <= 0) { error(p, "First entry before first tag"); r = -EBADMSG; goto fail; } r = write_uint64(entry_fd, p); if (r < 0) goto fail; if (le64toh(o->entry.realtime) < last_tag_realtime) { error(p, "Older entry after newer tag"); r = -EBADMSG; goto fail; } if (!entry_seqnum_set && le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) { error(p, "Head entry sequence number incorrect"); r = -EBADMSG; goto fail; } if (entry_seqnum_set && entry_seqnum >= le64toh(o->entry.seqnum)) { error(p, "Entry sequence number out of synchronization"); r = -EBADMSG; goto fail; } entry_seqnum = le64toh(o->entry.seqnum); entry_seqnum_set = true; if (entry_monotonic_set && sd_id128_equal(entry_boot_id, o->entry.boot_id) && entry_monotonic > le64toh(o->entry.monotonic)) { error(p, "Entry timestamp out of synchronization"); r = -EBADMSG; goto fail; } entry_monotonic = le64toh(o->entry.monotonic); entry_boot_id = o->entry.boot_id; entry_monotonic_set = true; if (!entry_realtime_set && le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) { error(p, "Head entry realtime timestamp incorrect"); r = -EBADMSG; goto fail; } entry_realtime = le64toh(o->entry.realtime); entry_realtime_set = true; n_entries ++; break; case OBJECT_DATA_HASH_TABLE: if (n_data_hash_tables > 1) { error(p, "More than one data hash table"); r = -EBADMSG; goto fail; } if (le64toh(f->header->data_hash_table_offset) != p + offsetof(HashTableObject, items) || le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { error(p, "header fields for data hash table invalid"); r = -EBADMSG; goto fail; } n_data_hash_tables++; break; case OBJECT_FIELD_HASH_TABLE: if (n_field_hash_tables > 1) { error(p, "More than one field hash table"); r = -EBADMSG; goto fail; } if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) || le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { error(p, "Header fields for field hash table invalid"); r = -EBADMSG; goto fail; } n_field_hash_tables++; break; case OBJECT_ENTRY_ARRAY: r = write_uint64(entry_array_fd, p); if (r < 0) goto fail; if (p == le64toh(f->header->entry_array_offset)) { if (found_main_entry_array) { error(p, "More than one main entry array"); r = -EBADMSG; goto fail; } found_main_entry_array = true; } n_entry_arrays++; break; case OBJECT_TAG: if (!JOURNAL_HEADER_SEALED(f->header)) { error(p, "Tag object in file without sealing"); r = -EBADMSG; goto fail; } if (le64toh(o->tag.seqnum) != n_tags + 1) { error(p, "Tag sequence number out of synchronization"); r = -EBADMSG; goto fail; } if (le64toh(o->tag.epoch) < last_epoch) { error(p, "Epoch sequence out of synchronization"); r = -EBADMSG; goto fail; } #ifdef HAVE_GCRYPT if (f->seal) { uint64_t q, rt; debug(p, "Checking tag %"PRIu64"...", le64toh(o->tag.seqnum)); rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec; if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) { error(p, "tag/entry realtime timestamp out of synchronization"); r = -EBADMSG; goto fail; } /* OK, now we know the epoch. So let's now set * it, and calculate the HMAC for everything * since the last tag. */ r = journal_file_fsprg_seek(f, le64toh(o->tag.epoch)); if (r < 0) goto fail; r = journal_file_hmac_start(f); if (r < 0) goto fail; if (last_tag == 0) { r = journal_file_hmac_put_header(f); if (r < 0) goto fail; q = le64toh(f->header->header_size); } else q = last_tag; while (q <= p) { r = journal_file_move_to_object(f, OBJECT_UNUSED, q, &o); if (r < 0) goto fail; r = journal_file_hmac_put_object(f, OBJECT_UNUSED, o, q); if (r < 0) goto fail; q = q + ALIGN64(le64toh(o->object.size)); } /* Position might have changed, let's reposition things */ r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o); if (r < 0) goto fail; if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) { error(p, "Tag failed verification"); r = -EBADMSG; goto fail; } f->hmac_running = false; last_tag_realtime = rt; last_sealed_realtime = entry_realtime; } last_tag = p + ALIGN64(le64toh(o->object.size)); #endif last_epoch = le64toh(o->tag.epoch); n_tags ++; break; default: n_weird ++; } if (p == le64toh(f->header->tail_object_offset)) { found_last = true; break; } p = p + ALIGN64(le64toh(o->object.size)); }; if (!found_last && le64toh(f->header->tail_object_offset) != 0) { error(le64toh(f->header->tail_object_offset), "Tail object pointer dead"); r = -EBADMSG; goto fail; } if (n_objects != le64toh(f->header->n_objects)) { error(offsetof(Header, n_objects), "Object number mismatch"); r = -EBADMSG; goto fail; } if (n_entries != le64toh(f->header->n_entries)) { error(offsetof(Header, n_entries), "Entry number mismatch"); r = -EBADMSG; goto fail; } if (JOURNAL_HEADER_CONTAINS(f->header, n_data) && n_data != le64toh(f->header->n_data)) { error(offsetof(Header, n_data), "Data number mismatch"); r = -EBADMSG; goto fail; } if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) && n_fields != le64toh(f->header->n_fields)) { error(offsetof(Header, n_fields), "Field number mismatch"); r = -EBADMSG; goto fail; } if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) && n_tags != le64toh(f->header->n_tags)) { error(offsetof(Header, n_tags), "Tag number mismatch"); r = -EBADMSG; goto fail; } if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays) && n_entry_arrays != le64toh(f->header->n_entry_arrays)) { error(offsetof(Header, n_entry_arrays), "Entry array number mismatch"); r = -EBADMSG; goto fail; } if (!found_main_entry_array && le64toh(f->header->entry_array_offset) != 0) { error(0, "Missing entry array"); r = -EBADMSG; goto fail; } if (entry_seqnum_set && entry_seqnum != le64toh(f->header->tail_entry_seqnum)) { error(offsetof(Header, tail_entry_seqnum), "Invalid tail seqnum"); r = -EBADMSG; goto fail; } if (entry_monotonic_set && (!sd_id128_equal(entry_boot_id, f->header->boot_id) || entry_monotonic != le64toh(f->header->tail_entry_monotonic))) { error(0, "Invalid tail monotonic timestamp"); r = -EBADMSG; goto fail; } if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) { error(0, "Invalid tail realtime timestamp"); r = -EBADMSG; goto fail; } /* Second iteration: we follow all objects referenced from the * two entry points: the object hash table and the entry * array. We also check that everything referenced (directly * or indirectly) in the data hash table also exists in the * entry array, and vice versa. Note that we do not care for * unreferenced objects. We only care that everything that is * referenced is consistent. */ r = verify_entry_array(f, data_fd, n_data, entry_fd, n_entries, entry_array_fd, n_entry_arrays, &last_usec, show_progress); if (r < 0) goto fail; r = verify_hash_table(f, data_fd, n_data, entry_fd, n_entries, entry_array_fd, n_entry_arrays, &last_usec, show_progress); if (r < 0) goto fail; if (show_progress) flush_progress(); mmap_cache_close_fd(f->mmap, data_fd); mmap_cache_close_fd(f->mmap, entry_fd); mmap_cache_close_fd(f->mmap, entry_array_fd); safe_close(data_fd); safe_close(entry_fd); safe_close(entry_array_fd); if (first_contained) *first_contained = le64toh(f->header->head_entry_realtime); if (last_validated) *last_validated = last_sealed_realtime; if (last_contained) *last_contained = le64toh(f->header->tail_entry_realtime); return 0; fail: if (show_progress) flush_progress(); log_error("File corruption detected at %s:"OFSfmt" (of %llu bytes, %"PRIu64"%%).", f->path, p, (unsigned long long) f->last_stat.st_size, 100 * p / f->last_stat.st_size); if (data_fd >= 0) { mmap_cache_close_fd(f->mmap, data_fd); safe_close(data_fd); } if (entry_fd >= 0) { mmap_cache_close_fd(f->mmap, entry_fd); safe_close(entry_fd); } if (entry_array_fd >= 0) { mmap_cache_close_fd(f->mmap, entry_array_fd); safe_close(entry_array_fd); } return r; } systemd-229/src/journal/journal-verify.h000066400000000000000000000016171265713322000204540ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "journal-file.h" int journal_file_verify(JournalFile *f, const char *key, usec_t *first_contained, usec_t *last_validated, usec_t *last_contained, bool show_progress); systemd-229/src/journal/journalctl.c000066400000000000000000002604531265713322000176550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sd-bus.h" #include "sd-journal.h" #include "acl-util.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "catalog.h" #include "chattr-util.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "fsprg.h" #include "glob-util.h" #include "hostname-util.h" #include "io-util.h" #include "journal-def.h" #include "journal-internal.h" #include "journal-qrcode.h" #include "journal-vacuum.h" #include "journal-verify.h" #include "locale-util.h" #include "log.h" #include "logs-show.h" #include "mkdir.h" #include "pager.h" #include "parse-util.h" #include "path-util.h" #include "rlimit-util.h" #include "set.h" #include "sigbus.h" #include "strv.h" #include "syslog-util.h" #include "terminal-util.h" #include "udev.h" #include "udev-util.h" #include "unit-name.h" #include "user-util.h" #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE) enum { /* Special values for arg_lines */ ARG_LINES_DEFAULT = -2, ARG_LINES_ALL = -1, }; static OutputMode arg_output = OUTPUT_SHORT; static bool arg_utc = false; static bool arg_pager_end = false; static bool arg_follow = false; static bool arg_full = true; static bool arg_all = false; static bool arg_no_pager = false; static int arg_lines = ARG_LINES_DEFAULT; static bool arg_no_tail = false; static bool arg_quiet = false; static bool arg_merge = false; static bool arg_boot = false; static sd_id128_t arg_boot_id = {}; static int arg_boot_offset = 0; static bool arg_dmesg = false; static const char *arg_cursor = NULL; static const char *arg_after_cursor = NULL; static bool arg_show_cursor = false; static const char *arg_directory = NULL; static char **arg_file = NULL; static int arg_priorities = 0xFF; static const char *arg_verify_key = NULL; #ifdef HAVE_GCRYPT static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC; static bool arg_force = false; #endif static usec_t arg_since, arg_until; static bool arg_since_set = false, arg_until_set = false; static char **arg_syslog_identifier = NULL; static char **arg_system_units = NULL; static char **arg_user_units = NULL; static const char *arg_field = NULL; static bool arg_catalog = false; static bool arg_reverse = false; static int arg_journal_type = 0; static char *arg_root = NULL; static const char *arg_machine = NULL; static uint64_t arg_vacuum_size = 0; static uint64_t arg_vacuum_n_files = 0; static usec_t arg_vacuum_time = 0; static enum { ACTION_SHOW, ACTION_NEW_ID128, ACTION_PRINT_HEADER, ACTION_SETUP_KEYS, ACTION_VERIFY, ACTION_DISK_USAGE, ACTION_LIST_CATALOG, ACTION_DUMP_CATALOG, ACTION_UPDATE_CATALOG, ACTION_LIST_BOOTS, ACTION_FLUSH, ACTION_SYNC, ACTION_ROTATE, ACTION_VACUUM, ACTION_LIST_FIELDS, ACTION_LIST_FIELD_NAMES, } arg_action = ACTION_SHOW; typedef struct BootId { sd_id128_t id; uint64_t first; uint64_t last; LIST_FIELDS(struct BootId, boot_list); } BootId; static int add_matches_for_device(sd_journal *j, const char *devpath) { int r; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_udev_device_unref_ struct udev_device *device = NULL; struct udev_device *d = NULL; struct stat st; assert(j); assert(devpath); if (!path_startswith(devpath, "/dev/")) { log_error("Devpath does not start with /dev/"); return -EINVAL; } udev = udev_new(); if (!udev) return log_oom(); r = stat(devpath, &st); if (r < 0) log_error_errno(errno, "Couldn't stat file: %m"); d = device = udev_device_new_from_devnum(udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev); if (!device) return log_error_errno(errno, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev)); while (d) { _cleanup_free_ char *match = NULL; const char *subsys, *sysname, *devnode; subsys = udev_device_get_subsystem(d); if (!subsys) { d = udev_device_get_parent(d); continue; } sysname = udev_device_get_sysname(d); if (!sysname) { d = udev_device_get_parent(d); continue; } match = strjoin("_KERNEL_DEVICE=+", subsys, ":", sysname, NULL); if (!match) return log_oom(); r = sd_journal_add_match(j, match, 0); if (r < 0) return log_error_errno(r, "Failed to add match: %m"); devnode = udev_device_get_devnode(d); if (devnode) { _cleanup_free_ char *match1 = NULL; r = stat(devnode, &st); if (r < 0) return log_error_errno(r, "Failed to stat() device node \"%s\": %m", devnode); r = asprintf(&match1, "_KERNEL_DEVICE=%c%u:%u", S_ISBLK(st.st_mode) ? 'b' : 'c', major(st.st_rdev), minor(st.st_rdev)); if (r < 0) return log_oom(); r = sd_journal_add_match(j, match1, 0); if (r < 0) return log_error_errno(r, "Failed to add match: %m"); } d = udev_device_get_parent(d); } r = add_match_this_boot(j, arg_machine); if (r < 0) return log_error_errno(r, "Failed to add match for the current boot: %m"); return 0; } static void pager_open_if_enabled(void) { if (arg_no_pager) return; pager_open(arg_pager_end); } static char *format_timestamp_maybe_utc(char *buf, size_t l, usec_t t) { if (arg_utc) return format_timestamp_utc(buf, l, t); return format_timestamp(buf, l, t); } static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset) { sd_id128_t id = SD_ID128_NULL; int off = 0, r; if (strlen(x) >= 32) { char *t; t = strndupa(x, 32); r = sd_id128_from_string(t, &id); if (r >= 0) x += 32; if (*x != '-' && *x != '+' && *x != 0) return -EINVAL; if (*x != 0) { r = safe_atoi(x, &off); if (r < 0) return r; } } else { r = safe_atoi(x, &off); if (r < 0) return r; } if (boot_id) *boot_id = id; if (offset) *offset = off; return 0; } static void help(void) { pager_open_if_enabled(); printf("%s [OPTIONS...] [MATCHES...]\n\n" "Query the journal.\n\n" "Options:\n" " --system Show the system journal\n" " --user Show the user journal for the current user\n" " -M --machine=CONTAINER Operate on local container\n" " -S --since=DATE Show entries not older than the specified date\n" " -U --until=DATE Show entries not newer than the specified date\n" " -c --cursor=CURSOR Show entries starting at the specified cursor\n" " --after-cursor=CURSOR Show entries after the specified cursor\n" " --show-cursor Print the cursor after all the entries\n" " -b --boot[=ID] Show current boot or the specified boot\n" " --list-boots Show terse information about recorded boots\n" " -k --dmesg Show kernel message log from the current boot\n" " -u --unit=UNIT Show logs from the specified unit\n" " --user-unit=UNIT Show logs from the specified user unit\n" " -t --identifier=STRING Show entries with the specified syslog identifier\n" " -p --priority=RANGE Show entries with the specified priority\n" " -e --pager-end Immediately jump to the end in the pager\n" " -f --follow Follow the journal\n" " -n --lines[=INTEGER] Number of journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" " -r --reverse Show the newest entries first\n" " -o --output=STRING Change journal output mode (short, short-iso,\n" " short-precise, short-monotonic, verbose,\n" " export, json, json-pretty, json-sse, cat)\n" " --utc Express time in Coordinated Universal Time (UTC)\n" " -x --catalog Add message explanations where available\n" " --no-full Ellipsize fields\n" " -a --all Show all fields, including long and unprintable\n" " -q --quiet Do not show info messages and privilege warning\n" " --no-pager Do not pipe output into a pager\n" " -m --merge Show entries from all available journals\n" " -D --directory=PATH Show journal files from directory\n" " --file=PATH Show journal file\n" " --root=ROOT Operate on catalog files below a root directory\n" #ifdef HAVE_GCRYPT " --interval=TIME Time interval for changing the FSS sealing key\n" " --verify-key=KEY Specify FSS verification key\n" " --force Override of the FSS key pair with --setup-keys\n" #endif "\nCommands:\n" " -h --help Show this help text\n" " --version Show package version\n" " -N --fields List all field names currently used\n" " -F --field=FIELD List all values that a specified field takes\n" " --disk-usage Show total disk usage of all journal files\n" " --vacuum-size=BYTES Reduce disk usage below specified size\n" " --vacuum-files=INT Leave only the specified number of journal files\n" " --vacuum-time=TIME Remove journal files older than specified time\n" " --verify Verify journal file consistency\n" " --sync Synchronize unwritten journal messages to disk\n" " --flush Flush all journal data from /run into /var\n" " --rotate Request immediate rotation of the journal files\n" " --header Show journal header information\n" " --list-catalog Show all message IDs in the catalog\n" " --dump-catalog Show entries in the message catalog\n" " --update-catalog Update the message catalog database\n" " --new-id128 Generate a new 128-bit ID\n" #ifdef HAVE_GCRYPT " --setup-keys Generate a new FSS key pair\n" #endif , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_FULL, ARG_NO_TAIL, ARG_NEW_ID128, ARG_LIST_BOOTS, ARG_USER, ARG_SYSTEM, ARG_ROOT, ARG_HEADER, ARG_SETUP_KEYS, ARG_FILE, ARG_INTERVAL, ARG_VERIFY, ARG_VERIFY_KEY, ARG_DISK_USAGE, ARG_AFTER_CURSOR, ARG_SHOW_CURSOR, ARG_USER_UNIT, ARG_LIST_CATALOG, ARG_DUMP_CATALOG, ARG_UPDATE_CATALOG, ARG_FORCE, ARG_UTC, ARG_SYNC, ARG_FLUSH, ARG_ROTATE, ARG_VACUUM_SIZE, ARG_VACUUM_FILES, ARG_VACUUM_TIME, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version" , no_argument, NULL, ARG_VERSION }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "pager-end", no_argument, NULL, 'e' }, { "follow", no_argument, NULL, 'f' }, { "force", no_argument, NULL, ARG_FORCE }, { "output", required_argument, NULL, 'o' }, { "all", no_argument, NULL, 'a' }, { "full", no_argument, NULL, 'l' }, { "no-full", no_argument, NULL, ARG_NO_FULL }, { "lines", optional_argument, NULL, 'n' }, { "no-tail", no_argument, NULL, ARG_NO_TAIL }, { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, { "quiet", no_argument, NULL, 'q' }, { "merge", no_argument, NULL, 'm' }, { "boot", optional_argument, NULL, 'b' }, { "list-boots", no_argument, NULL, ARG_LIST_BOOTS }, { "this-boot", optional_argument, NULL, 'b' }, /* deprecated */ { "dmesg", no_argument, NULL, 'k' }, { "system", no_argument, NULL, ARG_SYSTEM }, { "user", no_argument, NULL, ARG_USER }, { "directory", required_argument, NULL, 'D' }, { "file", required_argument, NULL, ARG_FILE }, { "root", required_argument, NULL, ARG_ROOT }, { "header", no_argument, NULL, ARG_HEADER }, { "identifier", required_argument, NULL, 't' }, { "priority", required_argument, NULL, 'p' }, { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS }, { "interval", required_argument, NULL, ARG_INTERVAL }, { "verify", no_argument, NULL, ARG_VERIFY }, { "verify-key", required_argument, NULL, ARG_VERIFY_KEY }, { "disk-usage", no_argument, NULL, ARG_DISK_USAGE }, { "cursor", required_argument, NULL, 'c' }, { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR }, { "show-cursor", no_argument, NULL, ARG_SHOW_CURSOR }, { "since", required_argument, NULL, 'S' }, { "until", required_argument, NULL, 'U' }, { "unit", required_argument, NULL, 'u' }, { "user-unit", required_argument, NULL, ARG_USER_UNIT }, { "field", required_argument, NULL, 'F' }, { "fields", no_argument, NULL, 'N' }, { "catalog", no_argument, NULL, 'x' }, { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG }, { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG }, { "update-catalog", no_argument, NULL, ARG_UPDATE_CATALOG }, { "reverse", no_argument, NULL, 'r' }, { "machine", required_argument, NULL, 'M' }, { "utc", no_argument, NULL, ARG_UTC }, { "flush", no_argument, NULL, ARG_FLUSH }, { "sync", no_argument, NULL, ARG_SYNC }, { "rotate", no_argument, NULL, ARG_ROTATE }, { "vacuum-size", required_argument, NULL, ARG_VACUUM_SIZE }, { "vacuum-files", required_argument, NULL, ARG_VACUUM_FILES }, { "vacuum-time", required_argument, NULL, ARG_VACUUM_TIME }, {} }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:S:U:t:u:NF:xrM:", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_NO_PAGER: arg_no_pager = true; break; case 'e': arg_pager_end = true; if (arg_lines == ARG_LINES_DEFAULT) arg_lines = 1000; break; case 'f': arg_follow = true; break; case 'o': arg_output = output_mode_from_string(optarg); if (arg_output < 0) { log_error("Unknown output format '%s'.", optarg); return -EINVAL; } if (arg_output == OUTPUT_EXPORT || arg_output == OUTPUT_JSON || arg_output == OUTPUT_JSON_PRETTY || arg_output == OUTPUT_JSON_SSE || arg_output == OUTPUT_CAT) arg_quiet = true; break; case 'l': arg_full = true; break; case ARG_NO_FULL: arg_full = false; break; case 'a': arg_all = true; break; case 'n': if (optarg) { if (streq(optarg, "all")) arg_lines = ARG_LINES_ALL; else { r = safe_atoi(optarg, &arg_lines); if (r < 0 || arg_lines < 0) { log_error("Failed to parse lines '%s'", optarg); return -EINVAL; } } } else { arg_lines = 10; /* Hmm, no argument? Maybe the next * word on the command line is * supposed to be the argument? Let's * see if there is one, and is * parsable. */ if (optind < argc) { int n; if (streq(argv[optind], "all")) { arg_lines = ARG_LINES_ALL; optind++; } else if (safe_atoi(argv[optind], &n) >= 0 && n >= 0) { arg_lines = n; optind++; } } } break; case ARG_NO_TAIL: arg_no_tail = true; break; case ARG_NEW_ID128: arg_action = ACTION_NEW_ID128; break; case 'q': arg_quiet = true; break; case 'm': arg_merge = true; break; case 'b': arg_boot = true; if (optarg) { r = parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset); if (r < 0) { log_error("Failed to parse boot descriptor '%s'", optarg); return -EINVAL; } } else { /* Hmm, no argument? Maybe the next * word on the command line is * supposed to be the argument? Let's * see if there is one and is parsable * as a boot descriptor... */ if (optind < argc && parse_boot_descriptor(argv[optind], &arg_boot_id, &arg_boot_offset) >= 0) optind++; } break; case ARG_LIST_BOOTS: arg_action = ACTION_LIST_BOOTS; break; case 'k': arg_boot = arg_dmesg = true; break; case ARG_SYSTEM: arg_journal_type |= SD_JOURNAL_SYSTEM; break; case ARG_USER: arg_journal_type |= SD_JOURNAL_CURRENT_USER; break; case 'M': arg_machine = optarg; break; case 'D': arg_directory = optarg; break; case ARG_FILE: r = glob_extend(&arg_file, optarg); if (r < 0) return log_error_errno(r, "Failed to add paths: %m"); break; case ARG_ROOT: r = parse_path_argument_and_warn(optarg, true, &arg_root); if (r < 0) return r; break; case 'c': arg_cursor = optarg; break; case ARG_AFTER_CURSOR: arg_after_cursor = optarg; break; case ARG_SHOW_CURSOR: arg_show_cursor = true; break; case ARG_HEADER: arg_action = ACTION_PRINT_HEADER; break; case ARG_VERIFY: arg_action = ACTION_VERIFY; break; case ARG_DISK_USAGE: arg_action = ACTION_DISK_USAGE; break; case ARG_VACUUM_SIZE: r = parse_size(optarg, 1024, &arg_vacuum_size); if (r < 0) { log_error("Failed to parse vacuum size: %s", optarg); return r; } arg_action = ACTION_VACUUM; break; case ARG_VACUUM_FILES: r = safe_atou64(optarg, &arg_vacuum_n_files); if (r < 0) { log_error("Failed to parse vacuum files: %s", optarg); return r; } arg_action = ACTION_VACUUM; break; case ARG_VACUUM_TIME: r = parse_sec(optarg, &arg_vacuum_time); if (r < 0) { log_error("Failed to parse vacuum time: %s", optarg); return r; } arg_action = ACTION_VACUUM; break; #ifdef HAVE_GCRYPT case ARG_FORCE: arg_force = true; break; case ARG_SETUP_KEYS: arg_action = ACTION_SETUP_KEYS; break; case ARG_VERIFY_KEY: arg_action = ACTION_VERIFY; arg_verify_key = optarg; arg_merge = false; break; case ARG_INTERVAL: r = parse_sec(optarg, &arg_interval); if (r < 0 || arg_interval <= 0) { log_error("Failed to parse sealing key change interval: %s", optarg); return -EINVAL; } break; #else case ARG_SETUP_KEYS: case ARG_VERIFY_KEY: case ARG_INTERVAL: case ARG_FORCE: log_error("Forward-secure sealing not available."); return -EOPNOTSUPP; #endif case 'p': { const char *dots; dots = strstr(optarg, ".."); if (dots) { char *a; int from, to, i; /* a range */ a = strndup(optarg, dots - optarg); if (!a) return log_oom(); from = log_level_from_string(a); to = log_level_from_string(dots + 2); free(a); if (from < 0 || to < 0) { log_error("Failed to parse log level range %s", optarg); return -EINVAL; } arg_priorities = 0; if (from < to) { for (i = from; i <= to; i++) arg_priorities |= 1 << i; } else { for (i = to; i <= from; i++) arg_priorities |= 1 << i; } } else { int p, i; p = log_level_from_string(optarg); if (p < 0) { log_error("Unknown log level %s", optarg); return -EINVAL; } arg_priorities = 0; for (i = 0; i <= p; i++) arg_priorities |= 1 << i; } break; } case 'S': r = parse_timestamp(optarg, &arg_since); if (r < 0) { log_error("Failed to parse timestamp: %s", optarg); return -EINVAL; } arg_since_set = true; break; case 'U': r = parse_timestamp(optarg, &arg_until); if (r < 0) { log_error("Failed to parse timestamp: %s", optarg); return -EINVAL; } arg_until_set = true; break; case 't': r = strv_extend(&arg_syslog_identifier, optarg); if (r < 0) return log_oom(); break; case 'u': r = strv_extend(&arg_system_units, optarg); if (r < 0) return log_oom(); break; case ARG_USER_UNIT: r = strv_extend(&arg_user_units, optarg); if (r < 0) return log_oom(); break; case 'F': arg_action = ACTION_LIST_FIELDS; arg_field = optarg; break; case 'N': arg_action = ACTION_LIST_FIELD_NAMES; break; case 'x': arg_catalog = true; break; case ARG_LIST_CATALOG: arg_action = ACTION_LIST_CATALOG; break; case ARG_DUMP_CATALOG: arg_action = ACTION_DUMP_CATALOG; break; case ARG_UPDATE_CATALOG: arg_action = ACTION_UPDATE_CATALOG; break; case 'r': arg_reverse = true; break; case ARG_UTC: arg_utc = true; break; case ARG_FLUSH: arg_action = ACTION_FLUSH; break; case ARG_ROTATE: arg_action = ACTION_ROTATE; break; case ARG_SYNC: arg_action = ACTION_SYNC; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (arg_follow && !arg_no_tail && !arg_since && arg_lines == ARG_LINES_DEFAULT) arg_lines = 10; if (!!arg_directory + !!arg_file + !!arg_machine > 1) { log_error("Please specify either -D/--directory= or --file= or -M/--machine=, not more than one."); return -EINVAL; } if (arg_since_set && arg_until_set && arg_since > arg_until) { log_error("--since= must be before --until=."); return -EINVAL; } if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1) { log_error("Please specify only one of --since=, --cursor=, and --after-cursor."); return -EINVAL; } if (arg_follow && arg_reverse) { log_error("Please specify either --reverse= or --follow=, not both."); return -EINVAL; } if (!IN_SET(arg_action, ACTION_SHOW, ACTION_DUMP_CATALOG, ACTION_LIST_CATALOG) && optind < argc) { log_error("Extraneous arguments starting with '%s'", argv[optind]); return -EINVAL; } if ((arg_boot || arg_action == ACTION_LIST_BOOTS) && (arg_file || arg_directory || arg_merge)) { log_error("Using --boot or --list-boots with --file, --directory or --merge is not supported."); return -EINVAL; } return 1; } static int generate_new_id128(void) { sd_id128_t id; int r; unsigned i; r = sd_id128_randomize(&id); if (r < 0) return log_error_errno(r, "Failed to generate ID: %m"); printf("As string:\n" SD_ID128_FORMAT_STR "\n\n" "As UUID:\n" "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n" "As macro:\n" "#define MESSAGE_XYZ SD_ID128_MAKE(", SD_ID128_FORMAT_VAL(id), SD_ID128_FORMAT_VAL(id)); for (i = 0; i < 16; i++) printf("%02x%s", id.bytes[i], i != 15 ? "," : ""); fputs(")\n\n", stdout); printf("As Python constant:\n" ">>> import uuid\n" ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n", SD_ID128_FORMAT_VAL(id)); return 0; } static int add_matches(sd_journal *j, char **args) { char **i; bool have_term = false; assert(j); STRV_FOREACH(i, args) { int r; if (streq(*i, "+")) { if (!have_term) break; r = sd_journal_add_disjunction(j); have_term = false; } else if (path_is_absolute(*i)) { _cleanup_free_ char *p, *t = NULL, *t2 = NULL, *interpreter = NULL; const char *path; struct stat st; p = canonicalize_file_name(*i); path = p ?: *i; if (lstat(path, &st) < 0) return log_error_errno(errno, "Couldn't stat file: %m"); if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) { if (executable_is_script(path, &interpreter) > 0) { _cleanup_free_ char *comm; comm = strndup(basename(path), 15); if (!comm) return log_oom(); t = strappend("_COMM=", comm); if (!t) return log_oom(); /* Append _EXE only if the interpreter is not a link. Otherwise, it might be outdated often. */ if (lstat(interpreter, &st) == 0 && !S_ISLNK(st.st_mode)) { t2 = strappend("_EXE=", interpreter); if (!t2) return log_oom(); } } else { t = strappend("_EXE=", path); if (!t) return log_oom(); } r = sd_journal_add_match(j, t, 0); if (r >=0 && t2) r = sd_journal_add_match(j, t2, 0); } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { r = add_matches_for_device(j, path); if (r < 0) return r; } else { log_error("File is neither a device node, nor regular file, nor executable: %s", *i); return -EINVAL; } have_term = true; } else { r = sd_journal_add_match(j, *i, 0); have_term = true; } if (r < 0) return log_error_errno(r, "Failed to add match '%s': %m", *i); } if (!strv_isempty(args) && !have_term) { log_error("\"+\" can only be used between terms"); return -EINVAL; } return 0; } static void boot_id_free_all(BootId *l) { while (l) { BootId *i = l; LIST_REMOVE(boot_list, l, i); free(i); } } static int discover_next_boot( sd_journal *j, BootId **boot, bool advance_older, bool read_realtime) { int r; char match[9+32+1] = "_BOOT_ID="; _cleanup_free_ BootId *next_boot = NULL; assert(j); assert(boot); /* We expect the journal to be on the last position of a boot * (in relation to the direction we are going), so that the next * invocation of sd_journal_next/previous will be from a different * boot. We then collect any information we desire and then jump * to the last location of the new boot by using a _BOOT_ID match * coming from the other journal direction. */ /* Make sure we aren't restricted by any _BOOT_ID matches, so that * we can actually advance to a *different* boot. */ sd_journal_flush_matches(j); if (advance_older) r = sd_journal_previous(j); else r = sd_journal_next(j); if (r < 0) return r; else if (r == 0) return 0; /* End of journal, yay. */ next_boot = new0(BootId, 1); if (!next_boot) return -ENOMEM; r = sd_journal_get_monotonic_usec(j, NULL, &next_boot->id); if (r < 0) return r; if (read_realtime) { r = sd_journal_get_realtime_usec(j, &next_boot->first); if (r < 0) return r; } /* Now seek to the last occurrence of this boot ID. */ sd_id128_to_string(next_boot->id, match + 9); r = sd_journal_add_match(j, match, sizeof(match) - 1); if (r < 0) return r; if (advance_older) r = sd_journal_seek_head(j); else r = sd_journal_seek_tail(j); if (r < 0) return r; if (advance_older) r = sd_journal_next(j); else r = sd_journal_previous(j); if (r < 0) return r; else if (r == 0) return -ENODATA; /* This shouldn't happen. We just came from this very boot ID. */ if (read_realtime) { r = sd_journal_get_realtime_usec(j, &next_boot->last); if (r < 0) return r; } *boot = next_boot; next_boot = NULL; return 0; } static int get_boots( sd_journal *j, BootId **boots, BootId *query_ref_boot, int ref_boot_offset) { bool skip_once; int r, count = 0; BootId *head = NULL, *tail = NULL; const bool advance_older = query_ref_boot && ref_boot_offset <= 0; assert(j); /* Adjust for the asymmetry that offset 0 is * the last (and current) boot, while 1 is considered the * (chronological) first boot in the journal. */ skip_once = query_ref_boot && sd_id128_is_null(query_ref_boot->id) && ref_boot_offset < 0; /* Advance to the earliest/latest occurrence of our reference * boot ID (taking our lookup direction into account), so that * discover_next_boot() can do its job. * If no reference is given, the journal head/tail will do, * they're "virtual" boots after all. */ if (query_ref_boot && !sd_id128_is_null(query_ref_boot->id)) { char match[9+32+1] = "_BOOT_ID="; sd_journal_flush_matches(j); sd_id128_to_string(query_ref_boot->id, match + 9); r = sd_journal_add_match(j, match, sizeof(match) - 1); if (r < 0) return r; if (advance_older) r = sd_journal_seek_head(j); else r = sd_journal_seek_tail(j); if (r < 0) return r; if (advance_older) r = sd_journal_next(j); else r = sd_journal_previous(j); if (r < 0) return r; else if (r == 0) goto finish; else if (ref_boot_offset == 0) { count = 1; goto finish; } } else { if (advance_older) r = sd_journal_seek_tail(j); else r = sd_journal_seek_head(j); if (r < 0) return r; /* No sd_journal_next/previous here. */ } for (;;) { _cleanup_free_ BootId *current = NULL; r = discover_next_boot(j, ¤t, advance_older, !query_ref_boot); if (r < 0) { boot_id_free_all(head); return r; } if (!current) break; if (query_ref_boot) { if (!skip_once) ref_boot_offset += advance_older ? 1 : -1; skip_once = false; if (ref_boot_offset == 0) { count = 1; query_ref_boot->id = current->id; break; } } else { LIST_INSERT_AFTER(boot_list, head, tail, current); tail = current; current = NULL; count++; } } finish: if (boots) *boots = head; sd_journal_flush_matches(j); return count; } static int list_boots(sd_journal *j) { int w, i, count; BootId *id, *all_ids; assert(j); count = get_boots(j, &all_ids, NULL, 0); if (count < 0) return log_error_errno(count, "Failed to determine boots: %m"); if (count == 0) return count; pager_open_if_enabled(); /* numbers are one less, but we need an extra char for the sign */ w = DECIMAL_STR_WIDTH(count - 1) + 1; i = 0; LIST_FOREACH(boot_list, id, all_ids) { char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX]; printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n", w, i - count + 1, SD_ID128_FORMAT_VAL(id->id), format_timestamp_maybe_utc(a, sizeof(a), id->first), format_timestamp_maybe_utc(b, sizeof(b), id->last)); i++; } boot_id_free_all(all_ids); return 0; } static int add_boot(sd_journal *j) { char match[9+32+1] = "_BOOT_ID="; int r; BootId ref_boot_id = {}; assert(j); if (!arg_boot) return 0; if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL)) return add_match_this_boot(j, arg_machine); ref_boot_id.id = arg_boot_id; r = get_boots(j, NULL, &ref_boot_id, arg_boot_offset); assert(r <= 1); if (r <= 0) { const char *reason = (r == 0) ? "No such boot ID in journal" : strerror(-r); if (sd_id128_is_null(arg_boot_id)) log_error("Data from the specified boot (%+i) is not available: %s", arg_boot_offset, reason); else log_error("Data from the specified boot ("SD_ID128_FORMAT_STR") is not available: %s", SD_ID128_FORMAT_VAL(arg_boot_id), reason); return r == 0 ? -ENODATA : r; } sd_id128_to_string(ref_boot_id.id, match + 9); r = sd_journal_add_match(j, match, sizeof(match) - 1); if (r < 0) return log_error_errno(r, "Failed to add match: %m"); r = sd_journal_add_conjunction(j); if (r < 0) return log_error_errno(r, "Failed to add conjunction: %m"); return 0; } static int add_dmesg(sd_journal *j) { int r; assert(j); if (!arg_dmesg) return 0; r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel")); if (r < 0) return log_error_errno(r, "Failed to add match: %m"); r = sd_journal_add_conjunction(j); if (r < 0) return log_error_errno(r, "Failed to add conjunction: %m"); return 0; } static int get_possible_units( sd_journal *j, const char *fields, char **patterns, Set **units) { _cleanup_set_free_free_ Set *found; const char *field; int r; found = set_new(&string_hash_ops); if (!found) return -ENOMEM; NULSTR_FOREACH(field, fields) { const void *data; size_t size; r = sd_journal_query_unique(j, field); if (r < 0) return r; SD_JOURNAL_FOREACH_UNIQUE(j, data, size) { char **pattern, *eq; size_t prefix; _cleanup_free_ char *u = NULL; eq = memchr(data, '=', size); if (eq) prefix = eq - (char*) data + 1; else prefix = 0; u = strndup((char*) data + prefix, size - prefix); if (!u) return -ENOMEM; STRV_FOREACH(pattern, patterns) if (fnmatch(*pattern, u, FNM_NOESCAPE) == 0) { log_debug("Matched %s with pattern %s=%s", u, field, *pattern); r = set_consume(found, u); u = NULL; if (r < 0 && r != -EEXIST) return r; break; } } } *units = found; found = NULL; return 0; } /* This list is supposed to return the superset of unit names * possibly matched by rules added with add_matches_for_unit... */ #define SYSTEM_UNITS \ "_SYSTEMD_UNIT\0" \ "COREDUMP_UNIT\0" \ "UNIT\0" \ "OBJECT_SYSTEMD_UNIT\0" \ "_SYSTEMD_SLICE\0" /* ... and add_matches_for_user_unit */ #define USER_UNITS \ "_SYSTEMD_USER_UNIT\0" \ "USER_UNIT\0" \ "COREDUMP_USER_UNIT\0" \ "OBJECT_SYSTEMD_USER_UNIT\0" static int add_units(sd_journal *j) { _cleanup_strv_free_ char **patterns = NULL; int r, count = 0; char **i; assert(j); STRV_FOREACH(i, arg_system_units) { _cleanup_free_ char *u = NULL; r = unit_name_mangle(*i, UNIT_NAME_GLOB, &u); if (r < 0) return r; if (string_is_glob(u)) { r = strv_push(&patterns, u); if (r < 0) return r; u = NULL; } else { r = add_matches_for_unit(j, u); if (r < 0) return r; r = sd_journal_add_disjunction(j); if (r < 0) return r; count ++; } } if (!strv_isempty(patterns)) { _cleanup_set_free_free_ Set *units = NULL; Iterator it; char *u; r = get_possible_units(j, SYSTEM_UNITS, patterns, &units); if (r < 0) return r; SET_FOREACH(u, units, it) { r = add_matches_for_unit(j, u); if (r < 0) return r; r = sd_journal_add_disjunction(j); if (r < 0) return r; count ++; } } patterns = strv_free(patterns); STRV_FOREACH(i, arg_user_units) { _cleanup_free_ char *u = NULL; r = unit_name_mangle(*i, UNIT_NAME_GLOB, &u); if (r < 0) return r; if (string_is_glob(u)) { r = strv_push(&patterns, u); if (r < 0) return r; u = NULL; } else { r = add_matches_for_user_unit(j, u, getuid()); if (r < 0) return r; r = sd_journal_add_disjunction(j); if (r < 0) return r; count ++; } } if (!strv_isempty(patterns)) { _cleanup_set_free_free_ Set *units = NULL; Iterator it; char *u; r = get_possible_units(j, USER_UNITS, patterns, &units); if (r < 0) return r; SET_FOREACH(u, units, it) { r = add_matches_for_user_unit(j, u, getuid()); if (r < 0) return r; r = sd_journal_add_disjunction(j); if (r < 0) return r; count ++; } } /* Complain if the user request matches but nothing whatsoever was * found, since otherwise everything would be matched. */ if (!(strv_isempty(arg_system_units) && strv_isempty(arg_user_units)) && count == 0) return -ENODATA; r = sd_journal_add_conjunction(j); if (r < 0) return r; return 0; } static int add_priorities(sd_journal *j) { char match[] = "PRIORITY=0"; int i, r; assert(j); if (arg_priorities == 0xFF) return 0; for (i = LOG_EMERG; i <= LOG_DEBUG; i++) if (arg_priorities & (1 << i)) { match[sizeof(match)-2] = '0' + i; r = sd_journal_add_match(j, match, strlen(match)); if (r < 0) return log_error_errno(r, "Failed to add match: %m"); } r = sd_journal_add_conjunction(j); if (r < 0) return log_error_errno(r, "Failed to add conjunction: %m"); return 0; } static int add_syslog_identifier(sd_journal *j) { int r; char **i; assert(j); STRV_FOREACH(i, arg_syslog_identifier) { char *u; u = strjoina("SYSLOG_IDENTIFIER=", *i); r = sd_journal_add_match(j, u, 0); if (r < 0) return r; r = sd_journal_add_disjunction(j); if (r < 0) return r; } r = sd_journal_add_conjunction(j); if (r < 0) return r; return 0; } static int setup_keys(void) { #ifdef HAVE_GCRYPT size_t mpk_size, seed_size, state_size, i; uint8_t *mpk, *seed, *state; int fd = -1, r; sd_id128_t machine, boot; char *p = NULL, *k = NULL; struct FSSHeader h; uint64_t n; struct stat st; r = stat("/var/log/journal", &st); if (r < 0 && errno != ENOENT && errno != ENOTDIR) return log_error_errno(errno, "stat(\"%s\") failed: %m", "/var/log/journal"); if (r < 0 || !S_ISDIR(st.st_mode)) { log_error("%s is not a directory, must be using persistent logging for FSS.", "/var/log/journal"); return r < 0 ? -errno : -ENOTDIR; } r = sd_id128_get_machine(&machine); if (r < 0) return log_error_errno(r, "Failed to get machine ID: %m"); r = sd_id128_get_boot(&boot); if (r < 0) return log_error_errno(r, "Failed to get boot ID: %m"); if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss", SD_ID128_FORMAT_VAL(machine)) < 0) return log_oom(); if (arg_force) { r = unlink(p); if (r < 0 && errno != ENOENT) { r = log_error_errno(errno, "unlink(\"%s\") failed: %m", p); goto finish; } } else if (access(p, F_OK) >= 0) { log_error("Sealing key file %s exists already. Use --force to recreate.", p); r = -EEXIST; goto finish; } if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX", SD_ID128_FORMAT_VAL(machine)) < 0) { r = log_oom(); goto finish; } mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR); mpk = alloca(mpk_size); seed_size = FSPRG_RECOMMENDED_SEEDLEN; seed = alloca(seed_size); state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR); state = alloca(state_size); fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) { r = log_error_errno(errno, "Failed to open /dev/random: %m"); goto finish; } log_info("Generating seed..."); r = loop_read_exact(fd, seed, seed_size, true); if (r < 0) { log_error_errno(r, "Failed to read random seed: %m"); goto finish; } log_info("Generating key pair..."); FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR); log_info("Generating sealing key..."); FSPRG_GenState0(state, mpk, seed, seed_size); assert(arg_interval > 0); n = now(CLOCK_REALTIME); n /= arg_interval; safe_close(fd); fd = mkostemp_safe(k, O_WRONLY|O_CLOEXEC); if (fd < 0) { r = log_error_errno(fd, "Failed to open %s: %m", k); goto finish; } /* Enable secure remove, exclusion from dump, synchronous * writing and in-place updating */ r = chattr_fd(fd, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL); if (r < 0) log_warning_errno(r, "Failed to set file attributes: %m"); zero(h); memcpy(h.signature, "KSHHRHLP", 8); h.machine_id = machine; h.boot_id = boot; h.header_size = htole64(sizeof(h)); h.start_usec = htole64(n * arg_interval); h.interval_usec = htole64(arg_interval); h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR); h.fsprg_state_size = htole64(state_size); r = loop_write(fd, &h, sizeof(h), false); if (r < 0) { log_error_errno(r, "Failed to write header: %m"); goto finish; } r = loop_write(fd, state, state_size, false); if (r < 0) { log_error_errno(r, "Failed to write state: %m"); goto finish; } if (link(k, p) < 0) { r = log_error_errno(errno, "Failed to link file: %m"); goto finish; } if (on_tty()) { fprintf(stderr, "\n" "The new key pair has been generated. The " ANSI_HIGHLIGHT "secret sealing key" ANSI_NORMAL " has been written to\n" "the following local file. This key file is automatically updated when the\n" "sealing key is advanced. It should not be used on multiple hosts.\n" "\n" "\t%s\n" "\n" "Please write down the following " ANSI_HIGHLIGHT "secret verification key" ANSI_NORMAL ". It should be stored\n" "at a safe location and should not be saved locally on disk.\n" "\n\t" ANSI_HIGHLIGHT_RED, p); fflush(stderr); } for (i = 0; i < seed_size; i++) { if (i > 0 && i % 3 == 0) putchar('-'); printf("%02x", ((uint8_t*) seed)[i]); } printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval); if (on_tty()) { char tsb[FORMAT_TIMESPAN_MAX], *hn; fprintf(stderr, ANSI_NORMAL "\n" "The sealing key is automatically changed every %s.\n", format_timespan(tsb, sizeof(tsb), arg_interval, 0)); hn = gethostname_malloc(); if (hn) { hostname_cleanup(hn); fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine)); } else fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine)); #ifdef HAVE_QRENCODE /* If this is not an UTF-8 system don't print any QR codes */ if (is_locale_utf8()) { fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr); print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine); } #endif free(hn); } r = 0; finish: safe_close(fd); if (k) { unlink(k); free(k); } free(p); return r; #else log_error("Forward-secure sealing not available."); return -EOPNOTSUPP; #endif } static int verify(sd_journal *j) { int r = 0; Iterator i; JournalFile *f; assert(j); log_show_color(true); ORDERED_HASHMAP_FOREACH(f, j->files, i) { int k; usec_t first = 0, validated = 0, last = 0; #ifdef HAVE_GCRYPT if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path); #endif k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true); if (k == -EINVAL) { /* If the key was invalid give up right-away. */ return k; } else if (k < 0) { log_warning_errno(k, "FAIL: %s (%m)", f->path); r = k; } else { char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX]; log_info("PASS: %s", f->path); if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) { if (validated > 0) { log_info("=> Validated from %s to %s, final %s entries not sealed.", format_timestamp_maybe_utc(a, sizeof(a), first), format_timestamp_maybe_utc(b, sizeof(b), validated), format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0)); } else if (last > 0) log_info("=> No sealing yet, %s of entries not sealed.", format_timespan(c, sizeof(c), last - first, 0)); else log_info("=> No sealing yet, no entries in file."); } } } return r; } static int access_check_var_log_journal(sd_journal *j) { #ifdef HAVE_ACL _cleanup_strv_free_ char **g = NULL; const char* dir; #endif int r; assert(j); if (arg_quiet) return 0; /* If we are root, we should have access, don't warn. */ if (getuid() == 0) return 0; /* If we are in the 'systemd-journal' group, we should have * access too. */ r = in_group("systemd-journal"); if (r < 0) return log_error_errno(r, "Failed to check if we are in the 'systemd-journal' group: %m"); if (r > 0) return 0; #ifdef HAVE_ACL if (laccess("/run/log/journal", F_OK) >= 0) dir = "/run/log/journal"; else dir = "/var/log/journal"; /* If we are in any of the groups listed in the journal ACLs, * then all is good, too. Let's enumerate all groups from the * default ACL of the directory, which generally should allow * access to most journal files too. */ r = acl_search_groups(dir, &g); if (r < 0) return log_error_errno(r, "Failed to search journal ACL: %m"); if (r > 0) return 0; /* Print a pretty list, if there were ACLs set. */ if (!strv_isempty(g)) { _cleanup_free_ char *s = NULL; /* Thre are groups in the ACL, let's list them */ r = strv_extend(&g, "systemd-journal"); if (r < 0) return log_oom(); strv_sort(g); strv_uniq(g); s = strv_join(g, "', '"); if (!s) return log_oom(); log_notice("Hint: You are currently not seeing messages from other users and the system.\n" " Users in groups '%s' can see all messages.\n" " Pass -q to turn off this notice.", s); return 1; } #endif /* If no ACLs were found, print a short version of the message. */ log_notice("Hint: You are currently not seeing messages from other users and the system.\n" " Users in the 'systemd-journal' group can see all messages. Pass -q to\n" " turn off this notice."); return 1; } static int access_check(sd_journal *j) { Iterator it; void *code; char *path; int r = 0; assert(j); if (hashmap_isempty(j->errors)) { if (ordered_hashmap_isempty(j->files)) log_notice("No journal files were found."); return 0; } if (hashmap_contains(j->errors, INT_TO_PTR(-EACCES))) { (void) access_check_var_log_journal(j); if (ordered_hashmap_isempty(j->files)) r = log_error_errno(EACCES, "No journal files were opened due to insufficient permissions."); } HASHMAP_FOREACH_KEY(path, code, j->errors, it) { int err; err = abs(PTR_TO_INT(code)); switch (err) { case EACCES: continue; case ENODATA: log_warning_errno(err, "Journal file %s is truncated, ignoring file.", path); break; case EPROTONOSUPPORT: log_warning_errno(err, "Journal file %s uses an unsupported feature, ignoring file.", path); break; case EBADMSG: log_warning_errno(err, "Journal file %s corrupted, ignoring file.", path); break; default: log_warning_errno(err, "An error was encountered while opening journal file %s, ignoring file.", path); break; } } return r; } static int flush_to_var(void) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_close_ int watch_fd = -1; int r; if (arg_machine) { log_error("--flush is not supported in conjunction with --machine=."); return -EOPNOTSUPP; } /* Quick exit */ if (access("/run/systemd/journal/flushed", F_OK) >= 0) return 0; /* OK, let's actually do the full logic, send SIGUSR1 to the * daemon and set up inotify to wait for the flushed file to appear */ r = bus_connect_system_systemd(&bus); if (r < 0) return log_error_errno(r, "Failed to get D-Bus connection: %m"); r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "KillUnit", &error, NULL, "ssi", "systemd-journald.service", "main", SIGUSR1); if (r < 0) return log_error_errno(r, "Failed to kill journal service: %s", bus_error_message(&error, r)); mkdir_p("/run/systemd/journal", 0755); watch_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (watch_fd < 0) return log_error_errno(errno, "Failed to create inotify watch: %m"); r = inotify_add_watch(watch_fd, "/run/systemd/journal", IN_CREATE|IN_DONT_FOLLOW|IN_ONLYDIR); if (r < 0) return log_error_errno(errno, "Failed to watch journal directory: %m"); for (;;) { if (access("/run/systemd/journal/flushed", F_OK) >= 0) break; if (errno != ENOENT) return log_error_errno(errno, "Failed to check for existence of /run/systemd/journal/flushed: %m"); r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY); if (r < 0) return log_error_errno(r, "Failed to wait for event: %m"); r = flush_fd(watch_fd); if (r < 0) return log_error_errno(r, "Failed to flush inotify events: %m"); } return 0; } static int send_signal_and_wait(int sig, const char *watch_path) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_close_ int watch_fd = -1; usec_t start; int r; if (arg_machine) { log_error("--sync and --rotate are not supported in conjunction with --machine=."); return -EOPNOTSUPP; } start = now(CLOCK_MONOTONIC); /* This call sends the specified signal to journald, and waits * for acknowledgment by watching the mtime of the specified * flag file. This is used to trigger syncing or rotation and * then wait for the operation to complete. */ for (;;) { usec_t tstamp; /* See if a sync happened by now. */ r = read_timestamp_file(watch_path, &tstamp); if (r < 0 && r != -ENOENT) return log_error_errno(errno, "Failed to read %s: %m", watch_path); if (r >= 0 && tstamp >= start) return 0; /* Let's ask for a sync, but only once. */ if (!bus) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; r = bus_connect_system_systemd(&bus); if (r < 0) return log_error_errno(r, "Failed to get D-Bus connection: %m"); r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "KillUnit", &error, NULL, "ssi", "systemd-journald.service", "main", sig); if (r < 0) return log_error_errno(r, "Failed to kill journal service: %s", bus_error_message(&error, r)); continue; } /* Let's install the inotify watch, if we didn't do that yet. */ if (watch_fd < 0) { mkdir_p("/run/systemd/journal", 0755); watch_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (watch_fd < 0) return log_error_errno(errno, "Failed to create inotify watch: %m"); r = inotify_add_watch(watch_fd, "/run/systemd/journal", IN_MOVED_TO|IN_DONT_FOLLOW|IN_ONLYDIR); if (r < 0) return log_error_errno(errno, "Failed to watch journal directory: %m"); /* Recheck the flag file immediately, so that we don't miss any event since the last check. */ continue; } /* OK, all preparatory steps done, let's wait until * inotify reports an event. */ r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY); if (r < 0) return log_error_errno(r, "Failed to wait for event: %m"); r = flush_fd(watch_fd); if (r < 0) return log_error_errno(r, "Failed to flush inotify events: %m"); } return 0; } static int rotate(void) { return send_signal_and_wait(SIGUSR2, "/run/systemd/journal/rotated"); } static int sync_journal(void) { return send_signal_and_wait(SIGRTMIN+1, "/run/systemd/journal/synced"); } int main(int argc, char *argv[]) { int r; _cleanup_(sd_journal_closep) sd_journal *j = NULL; bool need_seek = false; sd_id128_t previous_boot_id; bool previous_boot_id_valid = false, first_line = true; int n_shown = 0; bool ellipsized = false; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; signal(SIGWINCH, columns_lines_cache_reset); sigbus_install(); /* Increase max number of open files to 16K if we can, we * might needs this when browsing journal files, which might * be split up into many files. */ setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384)); switch (arg_action) { case ACTION_NEW_ID128: r = generate_new_id128(); goto finish; case ACTION_SETUP_KEYS: r = setup_keys(); goto finish; case ACTION_LIST_CATALOG: case ACTION_DUMP_CATALOG: case ACTION_UPDATE_CATALOG: { _cleanup_free_ char *database; database = path_join(arg_root, CATALOG_DATABASE, NULL); if (!database) { r = log_oom(); goto finish; } if (arg_action == ACTION_UPDATE_CATALOG) { r = catalog_update(database, arg_root, catalog_file_dirs); if (r < 0) log_error_errno(r, "Failed to list catalog: %m"); } else { bool oneline = arg_action == ACTION_LIST_CATALOG; pager_open_if_enabled(); if (optind < argc) r = catalog_list_items(stdout, database, oneline, argv + optind); else r = catalog_list(stdout, database, oneline); if (r < 0) log_error_errno(r, "Failed to list catalog: %m"); } goto finish; } case ACTION_FLUSH: r = flush_to_var(); goto finish; case ACTION_SYNC: r = sync_journal(); goto finish; case ACTION_ROTATE: r = rotate(); goto finish; case ACTION_SHOW: case ACTION_PRINT_HEADER: case ACTION_VERIFY: case ACTION_DISK_USAGE: case ACTION_LIST_BOOTS: case ACTION_VACUUM: case ACTION_LIST_FIELDS: case ACTION_LIST_FIELD_NAMES: /* These ones require access to the journal files, continue below. */ break; default: assert_not_reached("Unknown action"); } if (arg_directory) r = sd_journal_open_directory(&j, arg_directory, arg_journal_type); else if (arg_file) r = sd_journal_open_files(&j, (const char**) arg_file, 0); else if (arg_machine) r = sd_journal_open_container(&j, arg_machine, 0); else r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type); if (r < 0) { log_error_errno(r, "Failed to open %s: %m", arg_directory ?: arg_file ? "files" : "journal"); goto finish; } r = access_check(j); if (r < 0) goto finish; switch (arg_action) { case ACTION_NEW_ID128: case ACTION_SETUP_KEYS: case ACTION_LIST_CATALOG: case ACTION_DUMP_CATALOG: case ACTION_UPDATE_CATALOG: case ACTION_FLUSH: case ACTION_SYNC: case ACTION_ROTATE: assert_not_reached("Unexpected action."); case ACTION_PRINT_HEADER: journal_print_header(j); r = 0; goto finish; case ACTION_VERIFY: r = verify(j); goto finish; case ACTION_DISK_USAGE: { uint64_t bytes = 0; char sbytes[FORMAT_BYTES_MAX]; r = sd_journal_get_usage(j, &bytes); if (r < 0) goto finish; printf("Archived and active journals take up %s on disk.\n", format_bytes(sbytes, sizeof(sbytes), bytes)); goto finish; } case ACTION_LIST_BOOTS: r = list_boots(j); goto finish; case ACTION_VACUUM: { Directory *d; Iterator i; HASHMAP_FOREACH(d, j->directories_by_path, i) { int q; if (d->is_root) continue; q = journal_directory_vacuum(d->path, arg_vacuum_size, arg_vacuum_n_files, arg_vacuum_time, NULL, true); if (q < 0) { log_error_errno(q, "Failed to vacuum %s: %m", d->path); r = q; } } goto finish; } case ACTION_LIST_FIELD_NAMES: { const char *field; SD_JOURNAL_FOREACH_FIELD(j, field) { printf("%s\n", field); n_shown ++; } r = 0; goto finish; } case ACTION_SHOW: case ACTION_LIST_FIELDS: break; default: assert_not_reached("Unknown action"); } if (arg_boot_offset != 0 && sd_journal_has_runtime_files(j) > 0 && sd_journal_has_persistent_files(j) == 0) { log_info("Specifying boot ID has no effect, no persistent journal was found"); r = 0; goto finish; } /* add_boot() must be called first! * It may need to seek the journal to find parent boot IDs. */ r = add_boot(j); if (r < 0) goto finish; r = add_dmesg(j); if (r < 0) goto finish; r = add_units(j); if (r < 0) { log_error_errno(r, "Failed to add filter for units: %m"); goto finish; } r = add_syslog_identifier(j); if (r < 0) { log_error_errno(r, "Failed to add filter for syslog identifiers: %m"); goto finish; } r = add_priorities(j); if (r < 0) goto finish; r = add_matches(j, argv + optind); if (r < 0) goto finish; if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) { _cleanup_free_ char *filter; filter = journal_make_match_string(j); if (!filter) return log_oom(); log_debug("Journal filter: %s", filter); } if (arg_action == ACTION_LIST_FIELDS) { const void *data; size_t size; assert(arg_field); r = sd_journal_set_data_threshold(j, 0); if (r < 0) { log_error_errno(r, "Failed to unset data size threshold: %m"); goto finish; } r = sd_journal_query_unique(j, arg_field); if (r < 0) { log_error_errno(r, "Failed to query unique data objects: %m"); goto finish; } SD_JOURNAL_FOREACH_UNIQUE(j, data, size) { const void *eq; if (arg_lines >= 0 && n_shown >= arg_lines) break; eq = memchr(data, '=', size); if (eq) printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1); else printf("%.*s\n", (int) size, (const char*) data); n_shown ++; } r = 0; goto finish; } /* Opening the fd now means the first sd_journal_wait() will actually wait */ if (arg_follow) { r = sd_journal_get_fd(j); if (r < 0) { log_error_errno(r, "Failed to get journal fd: %m"); goto finish; } } if (arg_cursor || arg_after_cursor) { r = sd_journal_seek_cursor(j, arg_cursor ?: arg_after_cursor); if (r < 0) { log_error_errno(r, "Failed to seek to cursor: %m"); goto finish; } if (!arg_reverse) r = sd_journal_next_skip(j, 1 + !!arg_after_cursor); else r = sd_journal_previous_skip(j, 1 + !!arg_after_cursor); if (arg_after_cursor && r < 2) { /* We couldn't find the next entry after the cursor. */ if (arg_follow) need_seek = true; else arg_lines = 0; } } else if (arg_since_set && !arg_reverse) { r = sd_journal_seek_realtime_usec(j, arg_since); if (r < 0) { log_error_errno(r, "Failed to seek to date: %m"); goto finish; } r = sd_journal_next(j); } else if (arg_until_set && arg_reverse) { r = sd_journal_seek_realtime_usec(j, arg_until); if (r < 0) { log_error_errno(r, "Failed to seek to date: %m"); goto finish; } r = sd_journal_previous(j); } else if (arg_lines >= 0) { r = sd_journal_seek_tail(j); if (r < 0) { log_error_errno(r, "Failed to seek to tail: %m"); goto finish; } r = sd_journal_previous_skip(j, arg_lines); } else if (arg_reverse) { r = sd_journal_seek_tail(j); if (r < 0) { log_error_errno(r, "Failed to seek to tail: %m"); goto finish; } r = sd_journal_previous(j); } else { r = sd_journal_seek_head(j); if (r < 0) { log_error_errno(r, "Failed to seek to head: %m"); goto finish; } r = sd_journal_next(j); } if (r < 0) { log_error_errno(r, "Failed to iterate through journal: %m"); goto finish; } if (r == 0) { if (arg_follow) need_seek = true; else { if (!arg_quiet) printf("-- No entries --\n"); goto finish; } } if (!arg_follow) pager_open_if_enabled(); if (!arg_quiet) { usec_t start, end; char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX]; r = sd_journal_get_cutoff_realtime_usec(j, &start, &end); if (r < 0) { log_error_errno(r, "Failed to get cutoff: %m"); goto finish; } if (r > 0) { if (arg_follow) printf("-- Logs begin at %s. --\n", format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start)); else printf("-- Logs begin at %s, end at %s. --\n", format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start), format_timestamp_maybe_utc(end_buf, sizeof(end_buf), end)); } } for (;;) { while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) { int flags; if (need_seek) { if (!arg_reverse) r = sd_journal_next(j); else r = sd_journal_previous(j); if (r < 0) { log_error_errno(r, "Failed to iterate through journal: %m"); goto finish; } if (r == 0) break; } if (arg_until_set && !arg_reverse) { usec_t usec; r = sd_journal_get_realtime_usec(j, &usec); if (r < 0) { log_error_errno(r, "Failed to determine timestamp: %m"); goto finish; } if (usec > arg_until) goto finish; } if (arg_since_set && arg_reverse) { usec_t usec; r = sd_journal_get_realtime_usec(j, &usec); if (r < 0) { log_error_errno(r, "Failed to determine timestamp: %m"); goto finish; } if (usec < arg_since) goto finish; } if (!arg_merge && !arg_quiet) { sd_id128_t boot_id; r = sd_journal_get_monotonic_usec(j, NULL, &boot_id); if (r >= 0) { if (previous_boot_id_valid && !sd_id128_equal(boot_id, previous_boot_id)) printf("%s-- Reboot --%s\n", ansi_highlight(), ansi_normal()); previous_boot_id = boot_id; previous_boot_id_valid = true; } } flags = arg_all * OUTPUT_SHOW_ALL | arg_full * OUTPUT_FULL_WIDTH | colors_enabled() * OUTPUT_COLOR | arg_catalog * OUTPUT_CATALOG | arg_utc * OUTPUT_UTC; r = output_journal(stdout, j, arg_output, 0, flags, &ellipsized); need_seek = true; if (r == -EADDRNOTAVAIL) break; else if (r < 0 || ferror(stdout)) goto finish; n_shown++; } if (!arg_follow) { if (arg_show_cursor) { _cleanup_free_ char *cursor = NULL; r = sd_journal_get_cursor(j, &cursor); if (r < 0 && r != -EADDRNOTAVAIL) log_error_errno(r, "Failed to get cursor: %m"); else if (r >= 0) printf("-- cursor: %s\n", cursor); } break; } r = sd_journal_wait(j, (uint64_t) -1); if (r < 0) { log_error_errno(r, "Couldn't wait for journal event: %m"); goto finish; } first_line = false; } finish: pager_close(); strv_free(arg_file); strv_free(arg_syslog_identifier); strv_free(arg_system_units); strv_free(arg_user_units); free(arg_root); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/journal/journald-audit.c000066400000000000000000000454611265713322000204220ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "audit-type.h" #include "fd-util.h" #include "hexdecoct.h" #include "io-util.h" #include "journald-audit.h" #include "missing.h" #include "string-util.h" typedef struct MapField { const char *audit_field; const char *journal_field; int (*map)(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov); } MapField; static int map_simple_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) { _cleanup_free_ char *c = NULL; size_t l = 0, allocated = 0; const char *e; assert(field); assert(p); assert(iov); assert(n_iov); l = strlen(field); allocated = l + 1; c = malloc(allocated); if (!c) return -ENOMEM; memcpy(c, field, l); for (e = *p; *e != ' ' && *e != 0; e++) { if (!GREEDY_REALLOC(c, allocated, l+2)) return -ENOMEM; c[l++] = *e; } c[l] = 0; if (!GREEDY_REALLOC(*iov, *n_iov_allocated, *n_iov + 1)) return -ENOMEM; (*iov)[*n_iov].iov_base = c; (*iov)[*n_iov].iov_len = l; (*n_iov) ++; *p = e; c = NULL; return 1; } static int map_string_field_internal(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov, bool filter_printable) { _cleanup_free_ char *c = NULL; const char *s, *e; size_t l; assert(field); assert(p); assert(iov); assert(n_iov); /* The kernel formats string fields in one of two formats. */ if (**p == '"') { /* Normal quoted syntax */ s = *p + 1; e = strchr(s, '"'); if (!e) return 0; l = strlen(field) + (e - s); c = malloc(l+1); if (!c) return -ENOMEM; *((char*) mempcpy(stpcpy(c, field), s, e - s)) = 0; e += 1; } else if (unhexchar(**p) >= 0) { /* Hexadecimal escaping */ size_t allocated = 0; l = strlen(field); allocated = l + 2; c = malloc(allocated); if (!c) return -ENOMEM; memcpy(c, field, l); for (e = *p; *e != ' ' && *e != 0; e += 2) { int a, b; uint8_t x; a = unhexchar(e[0]); if (a < 0) return 0; b = unhexchar(e[1]); if (b < 0) return 0; x = ((uint8_t) a << 4 | (uint8_t) b); if (filter_printable && x < (uint8_t) ' ') x = (uint8_t) ' '; if (!GREEDY_REALLOC(c, allocated, l+2)) return -ENOMEM; c[l++] = (char) x; } c[l] = 0; } else return 0; if (!GREEDY_REALLOC(*iov, *n_iov_allocated, *n_iov + 1)) return -ENOMEM; (*iov)[*n_iov].iov_base = c; (*iov)[*n_iov].iov_len = l; (*n_iov) ++; *p = e; c = NULL; return 1; } static int map_string_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) { return map_string_field_internal(field, p, iov, n_iov_allocated, n_iov, false); } static int map_string_field_printable(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) { return map_string_field_internal(field, p, iov, n_iov_allocated, n_iov, true); } static int map_generic_field(const char *prefix, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) { const char *e, *f; char *c, *t; int r; /* Implements fallback mappings for all fields we don't know */ for (e = *p; e < *p + 16; e++) { if (*e == 0 || *e == ' ') return 0; if (*e == '=') break; if (!((*e >= 'a' && *e <= 'z') || (*e >= 'A' && *e <= 'Z') || (*e >= '0' && *e <= '9') || *e == '_' || *e == '-')) return 0; } if (e <= *p || e >= *p + 16) return 0; c = alloca(strlen(prefix) + (e - *p) + 2); t = stpcpy(c, prefix); for (f = *p; f < e; f++) { char x; if (*f >= 'a' && *f <= 'z') x = (*f - 'a') + 'A'; /* uppercase */ else if (*f == '-') x = '_'; /* dashes → underscores */ else x = *f; *(t++) = x; } strcpy(t, "="); e ++; r = map_simple_field(c, &e, iov, n_iov_allocated, n_iov); if (r < 0) return r; *p = e; return r; } /* Kernel fields are those occurring in the audit string before * msg='. All of these fields are trusted, hence carry the "_" prefix. * We try to translate the fields we know into our native names. The * other's are generically mapped to _AUDIT_FIELD_XYZ= */ static const MapField map_fields_kernel[] = { /* First, we map certain well-known audit fields into native * well-known fields */ { "pid=", "_PID=", map_simple_field }, { "ppid=", "_PPID=", map_simple_field }, { "uid=", "_UID=", map_simple_field }, { "euid=", "_EUID=", map_simple_field }, { "fsuid=", "_FSUID=", map_simple_field }, { "gid=", "_GID=", map_simple_field }, { "egid=", "_EGID=", map_simple_field }, { "fsgid=", "_FSGID=", map_simple_field }, { "tty=", "_TTY=", map_simple_field }, { "ses=", "_AUDIT_SESSION=", map_simple_field }, { "auid=", "_AUDIT_LOGINUID=", map_simple_field }, { "subj=", "_SELINUX_CONTEXT=", map_simple_field }, { "comm=", "_COMM=", map_string_field }, { "exe=", "_EXE=", map_string_field }, { "proctitle=", "_CMDLINE=", map_string_field_printable }, /* Some fields don't map to native well-known fields. However, * we know that they are string fields, hence let's undo * string field escaping for them, though we stick to the * generic field names. */ { "path=", "_AUDIT_FIELD_PATH=", map_string_field }, { "dev=", "_AUDIT_FIELD_DEV=", map_string_field }, { "name=", "_AUDIT_FIELD_NAME=", map_string_field }, {} }; /* Userspace fields are those occurring in the audit string after * msg='. All of these fields are untrusted, hence carry no "_" * prefix. We map the fields we don't know to AUDIT_FIELD_XYZ= */ static const MapField map_fields_userspace[] = { { "cwd=", "AUDIT_FIELD_CWD=", map_string_field }, { "cmd=", "AUDIT_FIELD_CMD=", map_string_field }, { "acct=", "AUDIT_FIELD_ACCT=", map_string_field }, { "exe=", "AUDIT_FIELD_EXE=", map_string_field }, { "comm=", "AUDIT_FIELD_COMM=", map_string_field }, {} }; static int map_all_fields( const char *p, const MapField map_fields[], const char *prefix, bool handle_msg, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) { int r; assert(p); assert(iov); assert(n_iov_allocated); assert(n_iov); for (;;) { bool mapped = false; const MapField *m; const char *v; p += strspn(p, WHITESPACE); if (*p == 0) return 0; if (handle_msg) { v = startswith(p, "msg='"); if (v) { const char *e; char *c; /* Userspace message. It's enclosed in simple quotation marks, is not escaped, but the last field in the line, hence let's remove the quotation mark, and apply the userspace mapping instead of the kernel mapping. */ e = endswith(v, "'"); if (!e) return 0; /* don't continue splitting up if the final quotation mark is missing */ c = strndupa(v, e - v); return map_all_fields(c, map_fields_userspace, "AUDIT_FIELD_", false, iov, n_iov_allocated, n_iov); } } /* Try to map the kernel fields to our own names */ for (m = map_fields; m->audit_field; m++) { v = startswith(p, m->audit_field); if (!v) continue; r = m->map(m->journal_field, &v, iov, n_iov_allocated, n_iov); if (r < 0) return log_debug_errno(r, "Failed to parse audit array: %m"); if (r > 0) { mapped = true; p = v; break; } } if (!mapped) { r = map_generic_field(prefix, &p, iov, n_iov_allocated, n_iov); if (r < 0) return log_debug_errno(r, "Failed to parse audit array: %m"); if (r == 0) /* Couldn't process as generic field, let's just skip over it */ p += strcspn(p, WHITESPACE); } } } static void process_audit_string(Server *s, int type, const char *data, size_t size) { _cleanup_free_ struct iovec *iov = NULL; size_t n_iov_allocated = 0; unsigned n_iov = 0, k; uint64_t seconds, msec, id; const char *p, *type_name; unsigned z; char id_field[sizeof("_AUDIT_ID=") + DECIMAL_STR_MAX(uint64_t)], type_field[sizeof("_AUDIT_TYPE=") + DECIMAL_STR_MAX(int)], source_time_field[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)]; char *m; assert(s); if (size <= 0) return; if (!data) return; /* Note that the input buffer is NUL terminated, but let's * check whether there is a spurious NUL byte */ if (memchr(data, 0, size)) return; p = startswith(data, "audit"); if (!p) return; if (sscanf(p, "(%" PRIu64 ".%" PRIu64 ":%" PRIu64 "):%n", &seconds, &msec, &id, &k) != 3) return; p += k; p += strspn(p, WHITESPACE); if (isempty(p)) return; n_iov_allocated = N_IOVEC_META_FIELDS + 7; iov = new(struct iovec, n_iov_allocated); if (!iov) { log_oom(); return; } IOVEC_SET_STRING(iov[n_iov++], "_TRANSPORT=audit"); sprintf(source_time_field, "_SOURCE_REALTIME_TIMESTAMP=%" PRIu64, (usec_t) seconds * USEC_PER_SEC + (usec_t) msec * USEC_PER_MSEC); IOVEC_SET_STRING(iov[n_iov++], source_time_field); sprintf(type_field, "_AUDIT_TYPE=%i", type); IOVEC_SET_STRING(iov[n_iov++], type_field); sprintf(id_field, "_AUDIT_ID=%" PRIu64, id); IOVEC_SET_STRING(iov[n_iov++], id_field); assert_cc(4 == LOG_FAC(LOG_AUTH)); IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_FACILITY=4"); IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_IDENTIFIER=audit"); type_name = audit_type_name_alloca(type); m = strjoina("MESSAGE=", type_name, " ", p); IOVEC_SET_STRING(iov[n_iov++], m); z = n_iov; map_all_fields(p, map_fields_kernel, "_AUDIT_FIELD_", true, &iov, &n_iov_allocated, &n_iov); if (!GREEDY_REALLOC(iov, n_iov_allocated, n_iov + N_IOVEC_META_FIELDS)) { log_oom(); goto finish; } server_dispatch_message(s, iov, n_iov, n_iov_allocated, NULL, NULL, NULL, 0, NULL, LOG_NOTICE, 0); finish: /* free() all entries that map_all_fields() added. All others * are allocated on the stack or are constant. */ for (; z < n_iov; z++) free(iov[z].iov_base); } void server_process_audit_message( Server *s, const void *buffer, size_t buffer_size, const struct ucred *ucred, const union sockaddr_union *sa, socklen_t salen) { const struct nlmsghdr *nl = buffer; assert(s); if (buffer_size < ALIGN(sizeof(struct nlmsghdr))) return; assert(buffer); /* Filter out fake data */ if (!sa || salen != sizeof(struct sockaddr_nl) || sa->nl.nl_family != AF_NETLINK || sa->nl.nl_pid != 0) { log_debug("Audit netlink message from invalid sender."); return; } if (!ucred || ucred->pid != 0) { log_debug("Audit netlink message with invalid credentials."); return; } if (!NLMSG_OK(nl, buffer_size)) { log_error("Audit netlink message truncated."); return; } /* Ignore special Netlink messages */ if (IN_SET(nl->nlmsg_type, NLMSG_NOOP, NLMSG_ERROR)) return; /* Below AUDIT_FIRST_USER_MSG theer are only control messages, let's ignore those */ if (nl->nlmsg_type < AUDIT_FIRST_USER_MSG) return; process_audit_string(s, nl->nlmsg_type, NLMSG_DATA(nl), nl->nlmsg_len - ALIGN(sizeof(struct nlmsghdr))); } static int enable_audit(int fd, bool b) { struct { union { struct nlmsghdr header; uint8_t header_space[NLMSG_HDRLEN]; }; struct audit_status body; } _packed_ request = { .header.nlmsg_len = NLMSG_LENGTH(sizeof(struct audit_status)), .header.nlmsg_type = AUDIT_SET, .header.nlmsg_flags = NLM_F_REQUEST, .header.nlmsg_seq = 1, .header.nlmsg_pid = 0, .body.mask = AUDIT_STATUS_ENABLED, .body.enabled = b, }; union sockaddr_union sa = { .nl.nl_family = AF_NETLINK, .nl.nl_pid = 0, }; struct iovec iovec = { .iov_base = &request, .iov_len = NLMSG_LENGTH(sizeof(struct audit_status)), }; struct msghdr mh = { .msg_iov = &iovec, .msg_iovlen = 1, .msg_name = &sa.sa, .msg_namelen = sizeof(sa.nl), }; ssize_t n; n = sendmsg(fd, &mh, MSG_NOSIGNAL); if (n < 0) return -errno; if (n != NLMSG_LENGTH(sizeof(struct audit_status))) return -EIO; /* We don't wait for the result here, we can't do anything * about it anyway */ return 0; } int server_open_audit(Server *s) { static const int one = 1; int r; if (s->audit_fd < 0) { static const union sockaddr_union sa = { .nl.nl_family = AF_NETLINK, .nl.nl_pid = 0, .nl.nl_groups = AUDIT_NLGRP_READLOG, }; s->audit_fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT); if (s->audit_fd < 0) { if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) log_debug("Audit not supported in the kernel."); else log_warning_errno(errno, "Failed to create audit socket, ignoring: %m"); return 0; } if (bind(s->audit_fd, &sa.sa, sizeof(sa.nl)) < 0) { log_warning_errno(errno, "Failed to join audit multicast group. " "The kernel is probably too old or multicast reading is not supported. " "Ignoring: %m"); s->audit_fd = safe_close(s->audit_fd); return 0; } } else fd_nonblock(s->audit_fd, 1); r = setsockopt(s->audit_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); if (r < 0) return log_error_errno(errno, "Failed to set SO_PASSCRED on audit socket: %m"); r = sd_event_add_io(s->event, &s->audit_event_source, s->audit_fd, EPOLLIN, server_process_datagram, s); if (r < 0) return log_error_errno(r, "Failed to add audit fd to event loop: %m"); /* We are listening now, try to enable audit */ r = enable_audit(s->audit_fd, true); if (r < 0) log_warning_errno(r, "Failed to issue audit enable call: %m"); return 0; } systemd-229/src/journal/journald-audit.h000066400000000000000000000017301265713322000204160ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "journald-server.h" #include "socket-util.h" void server_process_audit_message(Server *s, const void *buffer, size_t buffer_size, const struct ucred *ucred, const union sockaddr_union *sa, socklen_t salen); int server_open_audit(Server*s); systemd-229/src/journal/journald-console.c000066400000000000000000000070061265713322000207470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "io-util.h" #include "journald-console.h" #include "journald-server.h" #include "parse-util.h" #include "process-util.h" #include "stdio-util.h" #include "terminal-util.h" static bool prefix_timestamp(void) { static int cached_printk_time = -1; if (_unlikely_(cached_printk_time < 0)) { _cleanup_free_ char *p = NULL; cached_printk_time = read_one_line_file("/sys/module/printk/parameters/time", &p) >= 0 && parse_boolean(p) > 0; } return cached_printk_time; } void server_forward_console( Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred) { struct iovec iovec[5]; struct timespec ts; char tbuf[sizeof("[] ")-1 + DECIMAL_STR_MAX(ts.tv_sec) + DECIMAL_STR_MAX(ts.tv_nsec)-3 + 1]; char header_pid[sizeof("[]: ")-1 + DECIMAL_STR_MAX(pid_t)]; int n = 0, fd; _cleanup_free_ char *ident_buf = NULL; const char *tty; assert(s); assert(message); if (LOG_PRI(priority) > s->max_level_console) return; /* First: timestamp */ if (prefix_timestamp()) { assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0); xsprintf(tbuf, "[%5"PRI_TIME".%06ld] ", ts.tv_sec, ts.tv_nsec / 1000); IOVEC_SET_STRING(iovec[n++], tbuf); } /* Second: identifier and PID */ if (ucred) { if (!identifier) { get_process_comm(ucred->pid, &ident_buf); identifier = ident_buf; } xsprintf(header_pid, "["PID_FMT"]: ", ucred->pid); if (identifier) IOVEC_SET_STRING(iovec[n++], identifier); IOVEC_SET_STRING(iovec[n++], header_pid); } else if (identifier) { IOVEC_SET_STRING(iovec[n++], identifier); IOVEC_SET_STRING(iovec[n++], ": "); } /* Fourth: message */ IOVEC_SET_STRING(iovec[n++], message); IOVEC_SET_STRING(iovec[n++], "\n"); tty = s->tty_path ? s->tty_path : "/dev/console"; fd = open_terminal(tty, O_WRONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) { log_debug_errno(fd, "Failed to open %s for logging: %m", tty); return; } if (writev(fd, iovec, n) < 0) log_debug_errno(errno, "Failed to write to %s for logging: %m", tty); safe_close(fd); } systemd-229/src/journal/journald-console.h000066400000000000000000000015711265713322000207550ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "journald-server.h" void server_forward_console(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred); systemd-229/src/journal/journald-gperf.gperf000066400000000000000000000054231265713322000212720ustar00rootroot00000000000000%{ #include #include #include "conf-parser.h" #include "journald-server.h" %} struct ConfigPerfItem; %null_strings %language=ANSI-C %define slot-name section_and_lvalue %define hash-function-name journald_gperf_hash %define lookup-function-name journald_gperf_lookup %readonly-tables %omit-struct-type %struct-type %includes %% Journal.Storage, config_parse_storage, 0, offsetof(Server, storage) Journal.Compress, config_parse_bool, 0, offsetof(Server, compress) Journal.Seal, config_parse_bool, 0, offsetof(Server, seal) Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_interval_usec) Journal.RateLimitInterval, config_parse_sec, 0, offsetof(Server, rate_limit_interval) Journal.RateLimitBurst, config_parse_unsigned, 0, offsetof(Server, rate_limit_burst) Journal.SystemMaxUse, config_parse_iec_uint64, 0, offsetof(Server, system_metrics.max_use) Journal.SystemMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, system_metrics.max_size) Journal.SystemKeepFree, config_parse_iec_uint64, 0, offsetof(Server, system_metrics.keep_free) Journal.SystemMaxFiles, config_parse_uint64, 0, offsetof(Server, system_metrics.n_max_files) Journal.RuntimeMaxUse, config_parse_iec_uint64, 0, offsetof(Server, runtime_metrics.max_use) Journal.RuntimeMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, runtime_metrics.max_size) Journal.RuntimeKeepFree, config_parse_iec_uint64, 0, offsetof(Server, runtime_metrics.keep_free) Journal.RuntimeMaxFiles, config_parse_uint64, 0, offsetof(Server, runtime_metrics.n_max_files) Journal.MaxRetentionSec, config_parse_sec, 0, offsetof(Server, max_retention_usec) Journal.MaxFileSec, config_parse_sec, 0, offsetof(Server, max_file_usec) Journal.ForwardToSyslog, config_parse_bool, 0, offsetof(Server, forward_to_syslog) Journal.ForwardToKMsg, config_parse_bool, 0, offsetof(Server, forward_to_kmsg) Journal.ForwardToConsole, config_parse_bool, 0, offsetof(Server, forward_to_console) Journal.ForwardToWall, config_parse_bool, 0, offsetof(Server, forward_to_wall) Journal.TTYPath, config_parse_path, 0, offsetof(Server, tty_path) Journal.MaxLevelStore, config_parse_log_level, 0, offsetof(Server, max_level_store) Journal.MaxLevelSyslog, config_parse_log_level, 0, offsetof(Server, max_level_syslog) Journal.MaxLevelKMsg, config_parse_log_level, 0, offsetof(Server, max_level_kmsg) Journal.MaxLevelConsole, config_parse_log_level, 0, offsetof(Server, max_level_console) Journal.MaxLevelWall, config_parse_log_level, 0, offsetof(Server, max_level_wall) Journal.SplitMode, config_parse_split_mode, 0, offsetof(Server, split_mode) systemd-229/src/journal/journald-kmsg.c000066400000000000000000000346331265713322000202540ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "libudev.h" #include "sd-messages.h" #include "escape.h" #include "fd-util.h" #include "formats-util.h" #include "io-util.h" #include "journald-kmsg.h" #include "journald-server.h" #include "journald-syslog.h" #include "parse-util.h" #include "process-util.h" #include "stdio-util.h" #include "string-util.h" void server_forward_kmsg( Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred) { struct iovec iovec[5]; char header_priority[DECIMAL_STR_MAX(priority) + 3], header_pid[sizeof("[]: ")-1 + DECIMAL_STR_MAX(pid_t) + 1]; int n = 0; char *ident_buf = NULL; assert(s); assert(priority >= 0); assert(priority <= 999); assert(message); if (_unlikely_(LOG_PRI(priority) > s->max_level_kmsg)) return; if (_unlikely_(s->dev_kmsg_fd < 0)) return; /* Never allow messages with kernel facility to be written to * kmsg, regardless where the data comes from. */ priority = syslog_fixup_facility(priority); /* First: priority field */ xsprintf(header_priority, "<%i>", priority); IOVEC_SET_STRING(iovec[n++], header_priority); /* Second: identifier and PID */ if (ucred) { if (!identifier) { get_process_comm(ucred->pid, &ident_buf); identifier = ident_buf; } xsprintf(header_pid, "["PID_FMT"]: ", ucred->pid); if (identifier) IOVEC_SET_STRING(iovec[n++], identifier); IOVEC_SET_STRING(iovec[n++], header_pid); } else if (identifier) { IOVEC_SET_STRING(iovec[n++], identifier); IOVEC_SET_STRING(iovec[n++], ": "); } /* Fourth: message */ IOVEC_SET_STRING(iovec[n++], message); IOVEC_SET_STRING(iovec[n++], "\n"); if (writev(s->dev_kmsg_fd, iovec, n) < 0) log_debug_errno(errno, "Failed to write to /dev/kmsg for logging: %m"); free(ident_buf); } static bool is_us(const char *pid) { pid_t t; assert(pid); if (parse_pid(pid, &t) < 0) return false; return t == getpid(); } static void dev_kmsg_record(Server *s, const char *p, size_t l) { struct iovec iovec[N_IOVEC_META_FIELDS + 7 + N_IOVEC_KERNEL_FIELDS + 2 + N_IOVEC_UDEV_FIELDS]; char *message = NULL, *syslog_priority = NULL, *syslog_pid = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *source_time = NULL; int priority, r; unsigned n = 0, z = 0, j; unsigned long long usec; char *identifier = NULL, *pid = NULL, *e, *f, *k; uint64_t serial; size_t pl; char *kernel_device = NULL; assert(s); assert(p); if (l <= 0) return; e = memchr(p, ',', l); if (!e) return; *e = 0; r = safe_atoi(p, &priority); if (r < 0 || priority < 0 || priority > 999) return; if (s->forward_to_kmsg && (priority & LOG_FACMASK) != LOG_KERN) return; l -= (e - p) + 1; p = e + 1; e = memchr(p, ',', l); if (!e) return; *e = 0; r = safe_atou64(p, &serial); if (r < 0) return; if (s->kernel_seqnum) { /* We already read this one? */ if (serial < *s->kernel_seqnum) return; /* Did we lose any? */ if (serial > *s->kernel_seqnum) server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, LOG_MESSAGE("Missed %"PRIu64" kernel messages", serial - *s->kernel_seqnum), NULL); /* Make sure we never read this one again. Note that * we always store the next message serial we expect * here, simply because this makes handling the first * message with serial 0 easy. */ *s->kernel_seqnum = serial + 1; } l -= (e - p) + 1; p = e + 1; f = memchr(p, ';', l); if (!f) return; /* Kernel 3.6 has the flags field, kernel 3.5 lacks that */ e = memchr(p, ',', l); if (!e || f < e) e = f; *e = 0; r = safe_atollu(p, &usec); if (r < 0) return; l -= (f - p) + 1; p = f + 1; e = memchr(p, '\n', l); if (!e) return; *e = 0; pl = e - p; l -= (e - p) + 1; k = e + 1; for (j = 0; l > 0 && j < N_IOVEC_KERNEL_FIELDS; j++) { char *m; /* Metadata fields attached */ if (*k != ' ') break; k ++, l --; e = memchr(k, '\n', l); if (!e) return; *e = 0; if (cunescape_length_with_prefix(k, e - k, "_KERNEL_", UNESCAPE_RELAX, &m) < 0) break; if (startswith(m, "_KERNEL_DEVICE=")) kernel_device = m + 15; IOVEC_SET_STRING(iovec[n++], m); z++; l -= (e - k) + 1; k = e + 1; } if (kernel_device) { struct udev_device *ud; ud = udev_device_new_from_device_id(s->udev, kernel_device); if (ud) { const char *g; struct udev_list_entry *ll; char *b; g = udev_device_get_devnode(ud); if (g) { b = strappend("_UDEV_DEVNODE=", g); if (b) { IOVEC_SET_STRING(iovec[n++], b); z++; } } g = udev_device_get_sysname(ud); if (g) { b = strappend("_UDEV_SYSNAME=", g); if (b) { IOVEC_SET_STRING(iovec[n++], b); z++; } } j = 0; ll = udev_device_get_devlinks_list_entry(ud); udev_list_entry_foreach(ll, ll) { if (j > N_IOVEC_UDEV_FIELDS) break; g = udev_list_entry_get_name(ll); if (g) { b = strappend("_UDEV_DEVLINK=", g); if (b) { IOVEC_SET_STRING(iovec[n++], b); z++; } } j++; } udev_device_unref(ud); } } if (asprintf(&source_time, "_SOURCE_MONOTONIC_TIMESTAMP=%llu", usec) >= 0) IOVEC_SET_STRING(iovec[n++], source_time); IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=kernel"); if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0) IOVEC_SET_STRING(iovec[n++], syslog_priority); if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0) IOVEC_SET_STRING(iovec[n++], syslog_facility); if ((priority & LOG_FACMASK) == LOG_KERN) IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=kernel"); else { pl -= syslog_parse_identifier((const char**) &p, &identifier, &pid); /* Avoid any messages we generated ourselves via * log_info() and friends. */ if (pid && is_us(pid)) goto finish; if (identifier) { syslog_identifier = strappend("SYSLOG_IDENTIFIER=", identifier); if (syslog_identifier) IOVEC_SET_STRING(iovec[n++], syslog_identifier); } if (pid) { syslog_pid = strappend("SYSLOG_PID=", pid); if (syslog_pid) IOVEC_SET_STRING(iovec[n++], syslog_pid); } } if (cunescape_length_with_prefix(p, pl, "MESSAGE=", UNESCAPE_RELAX, &message) >= 0) IOVEC_SET_STRING(iovec[n++], message); server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, NULL, 0, NULL, priority, 0); finish: for (j = 0; j < z; j++) free(iovec[j].iov_base); free(message); free(syslog_priority); free(syslog_identifier); free(syslog_pid); free(syslog_facility); free(source_time); free(identifier); free(pid); } static int server_read_dev_kmsg(Server *s) { char buffer[8192+1]; /* the kernel-side limit per record is 8K currently */ ssize_t l; assert(s); assert(s->dev_kmsg_fd >= 0); l = read(s->dev_kmsg_fd, buffer, sizeof(buffer) - 1); if (l == 0) return 0; if (l < 0) { /* Old kernels who don't allow reading from /dev/kmsg * return EINVAL when we try. So handle this cleanly, * but don' try to ever read from it again. */ if (errno == EINVAL) { s->dev_kmsg_event_source = sd_event_source_unref(s->dev_kmsg_event_source); return 0; } if (errno == EAGAIN || errno == EINTR || errno == EPIPE) return 0; return log_error_errno(errno, "Failed to read from kernel: %m"); } dev_kmsg_record(s, buffer, l); return 1; } int server_flush_dev_kmsg(Server *s) { int r; assert(s); if (s->dev_kmsg_fd < 0) return 0; if (!s->dev_kmsg_readable) return 0; log_debug("Flushing /dev/kmsg..."); for (;;) { r = server_read_dev_kmsg(s); if (r < 0) return r; if (r == 0) break; } return 0; } static int dispatch_dev_kmsg(sd_event_source *es, int fd, uint32_t revents, void *userdata) { Server *s = userdata; assert(es); assert(fd == s->dev_kmsg_fd); assert(s); if (revents & EPOLLERR) log_warning("/dev/kmsg buffer overrun, some messages lost."); if (!(revents & EPOLLIN)) log_error("Got invalid event from epoll for /dev/kmsg: %"PRIx32, revents); return server_read_dev_kmsg(s); } int server_open_dev_kmsg(Server *s) { int r; assert(s); s->dev_kmsg_fd = open("/dev/kmsg", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); if (s->dev_kmsg_fd < 0) { log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to open /dev/kmsg, ignoring: %m"); return 0; } r = sd_event_add_io(s->event, &s->dev_kmsg_event_source, s->dev_kmsg_fd, EPOLLIN, dispatch_dev_kmsg, s); if (r < 0) { /* This will fail with EPERM on older kernels where * /dev/kmsg is not readable. */ if (r == -EPERM) { r = 0; goto fail; } log_error_errno(r, "Failed to add /dev/kmsg fd to event loop: %m"); goto fail; } r = sd_event_source_set_priority(s->dev_kmsg_event_source, SD_EVENT_PRIORITY_IMPORTANT+10); if (r < 0) { log_error_errno(r, "Failed to adjust priority of kmsg event source: %m"); goto fail; } s->dev_kmsg_readable = true; return 0; fail: s->dev_kmsg_event_source = sd_event_source_unref(s->dev_kmsg_event_source); s->dev_kmsg_fd = safe_close(s->dev_kmsg_fd); return r; } int server_open_kernel_seqnum(Server *s) { _cleanup_close_ int fd; uint64_t *p; int r; assert(s); /* We store the seqnum we last read in an mmaped file. That * way we can just use it like a variable, but it is * persistent and automatically flushed at reboot. */ fd = open("/run/systemd/journal/kernel-seqnum", O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); if (fd < 0) { log_error_errno(errno, "Failed to open /run/systemd/journal/kernel-seqnum, ignoring: %m"); return 0; } r = posix_fallocate(fd, 0, sizeof(uint64_t)); if (r != 0) { log_error_errno(r, "Failed to allocate sequential number file, ignoring: %m"); return 0; } p = mmap(NULL, sizeof(uint64_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (p == MAP_FAILED) { log_error_errno(errno, "Failed to map sequential number file, ignoring: %m"); return 0; } s->kernel_seqnum = p; return 0; } systemd-229/src/journal/journald-kmsg.h000066400000000000000000000017551265713322000202600ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "journald-server.h" int server_open_dev_kmsg(Server *s); int server_flush_dev_kmsg(Server *s); void server_forward_kmsg(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred); int server_open_kernel_seqnum(Server *s); systemd-229/src/journal/journald-native.c000066400000000000000000000444641265713322000206040ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "fs-util.h" #include "io-util.h" #include "journald-console.h" #include "journald-kmsg.h" #include "journald-native.h" #include "journald-server.h" #include "journald-syslog.h" #include "journald-wall.h" #include "memfd-util.h" #include "parse-util.h" #include "path-util.h" #include "selinux-util.h" #include "socket-util.h" #include "string-util.h" bool valid_user_field(const char *p, size_t l, bool allow_protected) { const char *a; /* We kinda enforce POSIX syntax recommendations for environment variables here, but make a couple of additional requirements. http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html */ /* No empty field names */ if (l <= 0) return false; /* Don't allow names longer than 64 chars */ if (l > 64) return false; /* Variables starting with an underscore are protected */ if (!allow_protected && p[0] == '_') return false; /* Don't allow digits as first character */ if (p[0] >= '0' && p[0] <= '9') return false; /* Only allow A-Z0-9 and '_' */ for (a = p; a < p + l; a++) if ((*a < 'A' || *a > 'Z') && (*a < '0' || *a > '9') && *a != '_') return false; return true; } static bool allow_object_pid(const struct ucred *ucred) { return ucred && ucred->uid == 0; } void server_process_native_message( Server *s, const void *buffer, size_t buffer_size, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len) { struct iovec *iovec = NULL; unsigned n = 0, j, tn = (unsigned) -1; const char *p; size_t remaining, m = 0, entry_size = 0; int priority = LOG_INFO; char *identifier = NULL, *message = NULL; pid_t object_pid = 0; assert(s); assert(buffer || buffer_size == 0); p = buffer; remaining = buffer_size; while (remaining > 0) { const char *e, *q; e = memchr(p, '\n', remaining); if (!e) { /* Trailing noise, let's ignore it, and flush what we collected */ log_debug("Received message with trailing noise, ignoring."); break; } if (e == p) { /* Entry separator */ if (entry_size + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */ log_debug("Entry is too big with %u properties and %zu bytes, ignoring.", n, entry_size); continue; } server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority, object_pid); n = 0; priority = LOG_INFO; entry_size = 0; p++; remaining--; continue; } if (*p == '.' || *p == '#') { /* Ignore control commands for now, and * comments too. */ remaining -= (e - p) + 1; p = e + 1; continue; } /* A property follows */ /* n existing properties, 1 new, +1 for _TRANSPORT */ if (!GREEDY_REALLOC(iovec, m, n + 2 + N_IOVEC_META_FIELDS + N_IOVEC_OBJECT_FIELDS)) { log_oom(); break; } q = memchr(p, '=', e - p); if (q) { if (valid_user_field(p, q - p, false)) { size_t l; l = e - p; /* If the field name starts with an * underscore, skip the variable, * since that indidates a trusted * field */ iovec[n].iov_base = (char*) p; iovec[n].iov_len = l; entry_size += iovec[n].iov_len; n++; /* We need to determine the priority * of this entry for the rate limiting * logic */ if (l == 10 && startswith(p, "PRIORITY=") && p[9] >= '0' && p[9] <= '9') priority = (priority & LOG_FACMASK) | (p[9] - '0'); else if (l == 17 && startswith(p, "SYSLOG_FACILITY=") && p[16] >= '0' && p[16] <= '9') priority = (priority & LOG_PRIMASK) | ((p[16] - '0') << 3); else if (l == 18 && startswith(p, "SYSLOG_FACILITY=") && p[16] >= '0' && p[16] <= '9' && p[17] >= '0' && p[17] <= '9') priority = (priority & LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) << 3); else if (l >= 19 && startswith(p, "SYSLOG_IDENTIFIER=")) { char *t; t = strndup(p + 18, l - 18); if (t) { free(identifier); identifier = t; } } else if (l >= 8 && startswith(p, "MESSAGE=")) { char *t; t = strndup(p + 8, l - 8); if (t) { free(message); message = t; } } else if (l > strlen("OBJECT_PID=") && l < strlen("OBJECT_PID=") + DECIMAL_STR_MAX(pid_t) && startswith(p, "OBJECT_PID=") && allow_object_pid(ucred)) { char buf[DECIMAL_STR_MAX(pid_t)]; memcpy(buf, p + strlen("OBJECT_PID="), l - strlen("OBJECT_PID=")); char_array_0(buf); /* ignore error */ parse_pid(buf, &object_pid); } } remaining -= (e - p) + 1; p = e + 1; continue; } else { le64_t l_le; uint64_t l; char *k; if (remaining < e - p + 1 + sizeof(uint64_t) + 1) { log_debug("Failed to parse message, ignoring."); break; } memcpy(&l_le, e + 1, sizeof(uint64_t)); l = le64toh(l_le); if (l > DATA_SIZE_MAX) { log_debug("Received binary data block of %"PRIu64" bytes is too large, ignoring.", l); break; } if ((uint64_t) remaining < e - p + 1 + sizeof(uint64_t) + l + 1 || e[1+sizeof(uint64_t)+l] != '\n') { log_debug("Failed to parse message, ignoring."); break; } k = malloc((e - p) + 1 + l); if (!k) { log_oom(); break; } memcpy(k, p, e - p); k[e - p] = '='; memcpy(k + (e - p) + 1, e + 1 + sizeof(uint64_t), l); if (valid_user_field(p, e - p, false)) { iovec[n].iov_base = k; iovec[n].iov_len = (e - p) + 1 + l; entry_size += iovec[n].iov_len; n++; } else free(k); remaining -= (e - p) + 1 + sizeof(uint64_t) + l + 1; p = e + 1 + sizeof(uint64_t) + l + 1; } } if (n <= 0) goto finish; tn = n++; IOVEC_SET_STRING(iovec[tn], "_TRANSPORT=journal"); entry_size += strlen("_TRANSPORT=journal"); if (entry_size + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */ log_debug("Entry is too big with %u properties and %zu bytes, ignoring.", n, entry_size); goto finish; } if (message) { if (s->forward_to_syslog) server_forward_syslog(s, priority, identifier, message, ucred, tv); if (s->forward_to_kmsg) server_forward_kmsg(s, priority, identifier, message, ucred); if (s->forward_to_console) server_forward_console(s, priority, identifier, message, ucred); if (s->forward_to_wall) server_forward_wall(s, priority, identifier, message, ucred); } server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority, object_pid); finish: for (j = 0; j < n; j++) { if (j == tn) continue; if (iovec[j].iov_base < buffer || (const uint8_t*) iovec[j].iov_base >= (const uint8_t*) buffer + buffer_size) free(iovec[j].iov_base); } free(iovec); free(identifier); free(message); } void server_process_native_file( Server *s, int fd, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len) { struct stat st; bool sealed; int r; /* Data is in the passed fd, since it didn't fit in a * datagram. */ assert(s); assert(fd >= 0); /* If it's a memfd, check if it is sealed. If so, we can just * use map it and use it, and do not need to copy the data * out. */ sealed = memfd_get_sealed(fd) > 0; if (!sealed && (!ucred || ucred->uid != 0)) { _cleanup_free_ char *sl = NULL, *k = NULL; const char *e; /* If this is not a sealed memfd, and the peer is unknown or * unprivileged, then verify the path. */ if (asprintf(&sl, "/proc/self/fd/%i", fd) < 0) { log_oom(); return; } r = readlink_malloc(sl, &k); if (r < 0) { log_error_errno(r, "readlink(%s) failed: %m", sl); return; } e = path_startswith(k, "/dev/shm/"); if (!e) e = path_startswith(k, "/tmp/"); if (!e) e = path_startswith(k, "/var/tmp/"); if (!e) { log_error("Received file outside of allowed directories. Refusing."); return; } if (!filename_is_valid(e)) { log_error("Received file in subdirectory of allowed directories. Refusing."); return; } } if (fstat(fd, &st) < 0) { log_error_errno(errno, "Failed to stat passed file, ignoring: %m"); return; } if (!S_ISREG(st.st_mode)) { log_error("File passed is not regular. Ignoring."); return; } if (st.st_size <= 0) return; if (st.st_size > ENTRY_SIZE_MAX) { log_error("File passed too large. Ignoring."); return; } if (sealed) { void *p; size_t ps; /* The file is sealed, we can just map it and use it. */ ps = PAGE_ALIGN(st.st_size); p = mmap(NULL, ps, PROT_READ, MAP_PRIVATE, fd, 0); if (p == MAP_FAILED) { log_error_errno(errno, "Failed to map memfd, ignoring: %m"); return; } server_process_native_message(s, p, st.st_size, ucred, tv, label, label_len); assert_se(munmap(p, ps) >= 0); } else { _cleanup_free_ void *p = NULL; struct statvfs vfs; ssize_t n; if (fstatvfs(fd, &vfs) < 0) { log_error_errno(errno, "Failed to stat file system of passed file, ignoring: %m"); return; } /* Refuse operating on file systems that have * mandatory locking enabled, see: * * https://github.com/systemd/systemd/issues/1822 */ if (vfs.f_flag & ST_MANDLOCK) { log_error("Received file descriptor from file system with mandatory locking enable, refusing."); return; } /* Make the fd non-blocking. On regular files this has * the effect of bypassing mandatory locking. Of * course, this should normally not be necessary given * the check above, but let's better be safe than * sorry, after all NFS is pretty confusing regarding * file system flags, and we better don't trust it, * and so is SMB. */ r = fd_nonblock(fd, true); if (r < 0) { log_error_errno(r, "Failed to make fd non-blocking, ignoring: %m"); return; } /* The file is not sealed, we can't map the file here, since * clients might then truncate it and trigger a SIGBUS for * us. So let's stupidly read it */ p = malloc(st.st_size); if (!p) { log_oom(); return; } n = pread(fd, p, st.st_size, 0); if (n < 0) log_error_errno(errno, "Failed to read file, ignoring: %m"); else if (n > 0) server_process_native_message(s, p, n, ucred, tv, label, label_len); } } int server_open_native_socket(Server*s) { static const int one = 1; int r; assert(s); if (s->native_fd < 0) { union sockaddr_union sa = { .un.sun_family = AF_UNIX, .un.sun_path = "/run/systemd/journal/socket", }; s->native_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (s->native_fd < 0) return log_error_errno(errno, "socket() failed: %m"); unlink(sa.un.sun_path); r = bind(s->native_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)); if (r < 0) return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); (void) chmod(sa.un.sun_path, 0666); } else fd_nonblock(s->native_fd, 1); r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); if (r < 0) return log_error_errno(errno, "SO_PASSCRED failed: %m"); #ifdef HAVE_SELINUX if (mac_selinux_have()) { r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one)); if (r < 0) log_warning_errno(errno, "SO_PASSSEC failed: %m"); } #endif r = setsockopt(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one)); if (r < 0) return log_error_errno(errno, "SO_TIMESTAMP failed: %m"); r = sd_event_add_io(s->event, &s->native_event_source, s->native_fd, EPOLLIN, server_process_datagram, s); if (r < 0) return log_error_errno(r, "Failed to add native server fd to event loop: %m"); r = sd_event_source_set_priority(s->native_event_source, SD_EVENT_PRIORITY_NORMAL+5); if (r < 0) return log_error_errno(r, "Failed to adjust native event source priority: %m"); return 0; } systemd-229/src/journal/journald-native.h000066400000000000000000000025471265713322000206050ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "journald-server.h" /* Make sure not to make this smaller than the maximum coredump * size. See COREDUMP_MAX in coredump.c */ #define ENTRY_SIZE_MAX (1024*1024*770u) #define DATA_SIZE_MAX (1024*1024*768u) bool valid_user_field(const char *p, size_t l, bool allow_protected); void server_process_native_message(Server *s, const void *buffer, size_t buffer_size, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len); void server_process_native_file(Server *s, int fd, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len); int server_open_native_socket(Server*s); systemd-229/src/journal/journald-rate-limit.c000066400000000000000000000150221265713322000213510ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "hashmap.h" #include "journald-rate-limit.h" #include "list.h" #include "random-util.h" #include "string-util.h" #include "util.h" #define POOLS_MAX 5 #define BUCKETS_MAX 127 #define GROUPS_MAX 2047 static const int priority_map[] = { [LOG_EMERG] = 0, [LOG_ALERT] = 0, [LOG_CRIT] = 0, [LOG_ERR] = 1, [LOG_WARNING] = 2, [LOG_NOTICE] = 3, [LOG_INFO] = 3, [LOG_DEBUG] = 4 }; typedef struct JournalRateLimitPool JournalRateLimitPool; typedef struct JournalRateLimitGroup JournalRateLimitGroup; struct JournalRateLimitPool { usec_t begin; unsigned num; unsigned suppressed; }; struct JournalRateLimitGroup { JournalRateLimit *parent; char *id; JournalRateLimitPool pools[POOLS_MAX]; uint64_t hash; LIST_FIELDS(JournalRateLimitGroup, bucket); LIST_FIELDS(JournalRateLimitGroup, lru); }; struct JournalRateLimit { usec_t interval; unsigned burst; JournalRateLimitGroup* buckets[BUCKETS_MAX]; JournalRateLimitGroup *lru, *lru_tail; unsigned n_groups; uint8_t hash_key[16]; }; JournalRateLimit *journal_rate_limit_new(usec_t interval, unsigned burst) { JournalRateLimit *r; assert(interval > 0 || burst == 0); r = new0(JournalRateLimit, 1); if (!r) return NULL; r->interval = interval; r->burst = burst; random_bytes(r->hash_key, sizeof(r->hash_key)); return r; } static void journal_rate_limit_group_free(JournalRateLimitGroup *g) { assert(g); if (g->parent) { assert(g->parent->n_groups > 0); if (g->parent->lru_tail == g) g->parent->lru_tail = g->lru_prev; LIST_REMOVE(lru, g->parent->lru, g); LIST_REMOVE(bucket, g->parent->buckets[g->hash % BUCKETS_MAX], g); g->parent->n_groups --; } free(g->id); free(g); } void journal_rate_limit_free(JournalRateLimit *r) { assert(r); while (r->lru) journal_rate_limit_group_free(r->lru); free(r); } _pure_ static bool journal_rate_limit_group_expired(JournalRateLimitGroup *g, usec_t ts) { unsigned i; assert(g); for (i = 0; i < POOLS_MAX; i++) if (g->pools[i].begin + g->parent->interval >= ts) return false; return true; } static void journal_rate_limit_vacuum(JournalRateLimit *r, usec_t ts) { assert(r); /* Makes room for at least one new item, but drop all * expored items too. */ while (r->n_groups >= GROUPS_MAX || (r->lru_tail && journal_rate_limit_group_expired(r->lru_tail, ts))) journal_rate_limit_group_free(r->lru_tail); } static JournalRateLimitGroup* journal_rate_limit_group_new(JournalRateLimit *r, const char *id, usec_t ts) { JournalRateLimitGroup *g; struct siphash state; assert(r); assert(id); g = new0(JournalRateLimitGroup, 1); if (!g) return NULL; g->id = strdup(id); if (!g->id) goto fail; siphash24_init(&state, r->hash_key); string_hash_func(g->id, &state); g->hash = siphash24_finalize(&state); journal_rate_limit_vacuum(r, ts); LIST_PREPEND(bucket, r->buckets[g->hash % BUCKETS_MAX], g); LIST_PREPEND(lru, r->lru, g); if (!g->lru_next) r->lru_tail = g; r->n_groups ++; g->parent = r; return g; fail: journal_rate_limit_group_free(g); return NULL; } static unsigned burst_modulate(unsigned burst, uint64_t available) { unsigned k; /* Modulates the burst rate a bit with the amount of available * disk space */ k = u64log2(available); /* 1MB */ if (k <= 20) return burst; burst = (burst * (k-20)) / 4; /* * Example: * * <= 1MB = rate * 1 * 16MB = rate * 2 * 256MB = rate * 3 * 4GB = rate * 4 * 64GB = rate * 5 * 1TB = rate * 6 */ return burst; } int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, uint64_t available) { uint64_t h; JournalRateLimitGroup *g; JournalRateLimitPool *p; struct siphash state; unsigned burst; usec_t ts; assert(id); if (!r) return 1; if (r->interval == 0 || r->burst == 0) return 1; burst = burst_modulate(r->burst, available); ts = now(CLOCK_MONOTONIC); siphash24_init(&state, r->hash_key); string_hash_func(id, &state); h = siphash24_finalize(&state); g = r->buckets[h % BUCKETS_MAX]; LIST_FOREACH(bucket, g, g) if (streq(g->id, id)) break; if (!g) { g = journal_rate_limit_group_new(r, id, ts); if (!g) return -ENOMEM; } p = &g->pools[priority_map[priority]]; if (p->begin <= 0) { p->suppressed = 0; p->num = 1; p->begin = ts; return 1; } if (p->begin + r->interval < ts) { unsigned s; s = p->suppressed; p->suppressed = 0; p->num = 1; p->begin = ts; return 1 + s; } if (p->num <= burst) { p->num++; return 1; } p->suppressed++; return 0; } systemd-229/src/journal/journald-rate-limit.h000066400000000000000000000020051265713322000213530ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "util.h" typedef struct JournalRateLimit JournalRateLimit; JournalRateLimit *journal_rate_limit_new(usec_t interval, unsigned burst); void journal_rate_limit_free(JournalRateLimit *r); int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, uint64_t available); systemd-229/src/journal/journald-server.c000066400000000000000000002102171265713322000206130ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #ifdef HAVE_SELINUX #include #endif #include #include #include #include #include #include "libudev.h" #include "sd-daemon.h" #include "sd-journal.h" #include "sd-messages.h" #include "acl-util.h" #include "alloc-util.h" #include "audit-util.h" #include "cgroup-util.h" #include "conf-parser.h" #include "dirent-util.h" #include "extract-word.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "hashmap.h" #include "hostname-util.h" #include "io-util.h" #include "journal-authenticate.h" #include "journal-file.h" #include "journal-internal.h" #include "journal-vacuum.h" #include "journald-audit.h" #include "journald-kmsg.h" #include "journald-native.h" #include "journald-rate-limit.h" #include "journald-server.h" #include "journald-stream.h" #include "journald-syslog.h" #include "missing.h" #include "mkdir.h" #include "parse-util.h" #include "proc-cmdline.h" #include "process-util.h" #include "rm-rf.h" #include "selinux-util.h" #include "signal-util.h" #include "socket-util.h" #include "stdio-util.h" #include "string-table.h" #include "string-util.h" #include "user-util.h" #include "log.h" #define USER_JOURNALS_MAX 1024 #define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE) #define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC) #define DEFAULT_RATE_LIMIT_BURST 1000 #define DEFAULT_MAX_FILE_USEC USEC_PER_MONTH #define RECHECK_SPACE_USEC (30*USEC_PER_SEC) #define NOTIFY_SNDBUF_SIZE (8*1024*1024) /* The period to insert between posting changes for coalescing */ #define POST_CHANGE_TIMER_INTERVAL_USEC (250*USEC_PER_MSEC) static int determine_space_for( Server *s, JournalMetrics *metrics, const char *path, const char *name, bool verbose, bool patch_min_use, uint64_t *available, uint64_t *limit) { uint64_t sum = 0, ss_avail, avail; _cleanup_closedir_ DIR *d = NULL; struct dirent *de; struct statvfs ss; const char *p; usec_t ts; assert(s); assert(metrics); assert(path); assert(name); ts = now(CLOCK_MONOTONIC); if (!verbose && s->cached_space_timestamp + RECHECK_SPACE_USEC > ts) { if (available) *available = s->cached_space_available; if (limit) *limit = s->cached_space_limit; return 0; } p = strjoina(path, SERVER_MACHINE_ID(s)); d = opendir(p); if (!d) return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open %s: %m", p); if (fstatvfs(dirfd(d), &ss) < 0) return log_error_errno(errno, "Failed to fstatvfs(%s): %m", p); FOREACH_DIRENT_ALL(de, d, break) { struct stat st; if (!endswith(de->d_name, ".journal") && !endswith(de->d_name, ".journal~")) continue; if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { log_debug_errno(errno, "Failed to stat %s/%s, ignoring: %m", p, de->d_name); continue; } if (!S_ISREG(st.st_mode)) continue; sum += (uint64_t) st.st_blocks * 512UL; } /* If requested, then let's bump the min_use limit to the * current usage on disk. We do this when starting up and * first opening the journal files. This way sudden spikes in * disk usage will not cause journald to vacuum files without * bounds. Note that this means that only a restart of * journald will make it reset this value. */ if (patch_min_use) metrics->min_use = MAX(metrics->min_use, sum); ss_avail = ss.f_bsize * ss.f_bavail; avail = LESS_BY(ss_avail, metrics->keep_free); s->cached_space_limit = MIN(MAX(sum + avail, metrics->min_use), metrics->max_use); s->cached_space_available = LESS_BY(s->cached_space_limit, sum); s->cached_space_timestamp = ts; if (verbose) { char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX], fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX], fb6[FORMAT_BYTES_MAX]; format_bytes(fb1, sizeof(fb1), sum); format_bytes(fb2, sizeof(fb2), metrics->max_use); format_bytes(fb3, sizeof(fb3), metrics->keep_free); format_bytes(fb4, sizeof(fb4), ss_avail); format_bytes(fb5, sizeof(fb5), s->cached_space_limit); format_bytes(fb6, sizeof(fb6), s->cached_space_available); server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE, LOG_MESSAGE("%s (%s) is %s, max %s, %s free.", name, path, fb1, fb5, fb6), "JOURNAL_NAME=%s", name, "JOURNAL_PATH=%s", path, "CURRENT_USE=%"PRIu64, sum, "CURRENT_USE_PRETTY=%s", fb1, "MAX_USE=%"PRIu64, metrics->max_use, "MAX_USE_PRETTY=%s", fb2, "DISK_KEEP_FREE=%"PRIu64, metrics->keep_free, "DISK_KEEP_FREE_PRETTY=%s", fb3, "DISK_AVAILABLE=%"PRIu64, ss_avail, "DISK_AVAILABLE_PRETTY=%s", fb4, "LIMIT=%"PRIu64, s->cached_space_limit, "LIMIT_PRETTY=%s", fb5, "AVAILABLE=%"PRIu64, s->cached_space_available, "AVAILABLE_PRETTY=%s", fb6, NULL); } if (available) *available = s->cached_space_available; if (limit) *limit = s->cached_space_limit; return 1; } static int determine_space(Server *s, bool verbose, bool patch_min_use, uint64_t *available, uint64_t *limit) { JournalMetrics *metrics; const char *path, *name; assert(s); if (s->system_journal) { path = "/var/log/journal/"; metrics = &s->system_metrics; name = "System journal"; } else { path = "/run/log/journal/"; metrics = &s->runtime_metrics; name = "Runtime journal"; } return determine_space_for(s, metrics, path, name, verbose, patch_min_use, available, limit); } static void server_add_acls(JournalFile *f, uid_t uid) { #ifdef HAVE_ACL int r; #endif assert(f); #ifdef HAVE_ACL if (uid <= SYSTEM_UID_MAX) return; r = add_acls_for_user(f->fd, uid); if (r < 0) log_warning_errno(r, "Failed to set ACL on %s, ignoring: %m", f->path); #endif } static int open_journal( Server *s, bool reliably, const char *fname, int flags, bool seal, JournalMetrics *metrics, JournalFile **ret) { int r; JournalFile *f; assert(s); assert(fname); assert(ret); if (reliably) r = journal_file_open_reliably(fname, flags, 0640, s->compress, seal, metrics, s->mmap, NULL, &f); else r = journal_file_open(fname, flags, 0640, s->compress, seal, metrics, s->mmap, NULL, &f); if (r < 0) return r; r = journal_file_enable_post_change_timer(f, s->event, POST_CHANGE_TIMER_INTERVAL_USEC); if (r < 0) { journal_file_close(f); return r; } *ret = f; return r; } static JournalFile* find_journal(Server *s, uid_t uid) { _cleanup_free_ char *p = NULL; int r; JournalFile *f; sd_id128_t machine; assert(s); /* We split up user logs only on /var, not on /run. If the * runtime file is open, we write to it exclusively, in order * to guarantee proper order as soon as we flush /run to * /var and close the runtime file. */ if (s->runtime_journal) return s->runtime_journal; if (uid <= SYSTEM_UID_MAX) return s->system_journal; r = sd_id128_get_machine(&machine); if (r < 0) return s->system_journal; f = ordered_hashmap_get(s->user_journals, UID_TO_PTR(uid)); if (f) return f; if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/user-"UID_FMT".journal", SD_ID128_FORMAT_VAL(machine), uid) < 0) return s->system_journal; while (ordered_hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) { /* Too many open? Then let's close one */ f = ordered_hashmap_steal_first(s->user_journals); assert(f); journal_file_close(f); } r = open_journal(s, true, p, O_RDWR|O_CREAT, s->seal, &s->system_metrics, &f); if (r < 0) return s->system_journal; server_add_acls(f, uid); r = ordered_hashmap_put(s->user_journals, UID_TO_PTR(uid), f); if (r < 0) { journal_file_close(f); return s->system_journal; } return f; } static int do_rotate( Server *s, JournalFile **f, const char* name, bool seal, uint32_t uid) { int r; assert(s); if (!*f) return -EINVAL; r = journal_file_rotate(f, s->compress, seal); if (r < 0) if (*f) log_error_errno(r, "Failed to rotate %s: %m", (*f)->path); else log_error_errno(r, "Failed to create new %s journal: %m", name); else server_add_acls(*f, uid); return r; } void server_rotate(Server *s) { JournalFile *f; void *k; Iterator i; int r; log_debug("Rotating..."); (void) do_rotate(s, &s->runtime_journal, "runtime", false, 0); (void) do_rotate(s, &s->system_journal, "system", s->seal, 0); ORDERED_HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) { r = do_rotate(s, &f, "user", s->seal, PTR_TO_UID(k)); if (r >= 0) ordered_hashmap_replace(s->user_journals, k, f); else if (!f) /* Old file has been closed and deallocated */ ordered_hashmap_remove(s->user_journals, k); } } void server_sync(Server *s) { JournalFile *f; Iterator i; int r; if (s->system_journal) { r = journal_file_set_offline(s->system_journal); if (r < 0) log_warning_errno(r, "Failed to sync system journal, ignoring: %m"); } ORDERED_HASHMAP_FOREACH(f, s->user_journals, i) { r = journal_file_set_offline(f); if (r < 0) log_warning_errno(r, "Failed to sync user journal, ignoring: %m"); } if (s->sync_event_source) { r = sd_event_source_set_enabled(s->sync_event_source, SD_EVENT_OFF); if (r < 0) log_error_errno(r, "Failed to disable sync timer source: %m"); } s->sync_scheduled = false; } static void do_vacuum( Server *s, JournalFile *f, JournalMetrics *metrics, const char *path, const char *name, bool verbose, bool patch_min_use) { const char *p; uint64_t limit; int r; assert(s); assert(metrics); assert(path); assert(name); if (!f) return; p = strjoina(path, SERVER_MACHINE_ID(s)); limit = metrics->max_use; (void) determine_space_for(s, metrics, path, name, verbose, patch_min_use, NULL, &limit); r = journal_directory_vacuum(p, limit, metrics->n_max_files, s->max_retention_usec, &s->oldest_file_usec, verbose); if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to vacuum %s, ignoring: %m", p); } int server_vacuum(Server *s, bool verbose, bool patch_min_use) { assert(s); log_debug("Vacuuming..."); s->oldest_file_usec = 0; do_vacuum(s, s->system_journal, &s->system_metrics, "/var/log/journal/", "System journal", verbose, patch_min_use); do_vacuum(s, s->runtime_journal, &s->runtime_metrics, "/run/log/journal/", "Runtime journal", verbose, patch_min_use); s->cached_space_limit = 0; s->cached_space_available = 0; s->cached_space_timestamp = 0; return 0; } static void server_cache_machine_id(Server *s) { sd_id128_t id; int r; assert(s); r = sd_id128_get_machine(&id); if (r < 0) return; sd_id128_to_string(id, stpcpy(s->machine_id_field, "_MACHINE_ID=")); } static void server_cache_boot_id(Server *s) { sd_id128_t id; int r; assert(s); r = sd_id128_get_boot(&id); if (r < 0) return; sd_id128_to_string(id, stpcpy(s->boot_id_field, "_BOOT_ID=")); } static void server_cache_hostname(Server *s) { _cleanup_free_ char *t = NULL; char *x; assert(s); t = gethostname_malloc(); if (!t) return; x = strappend("_HOSTNAME=", t); if (!x) return; free(s->hostname_field); s->hostname_field = x; } static bool shall_try_append_again(JournalFile *f, int r) { /* -E2BIG Hit configured limit -EFBIG Hit fs limit -EDQUOT Quota limit hit -ENOSPC Disk full -EIO I/O error of some kind (mmap) -EHOSTDOWN Other machine -EBUSY Unclean shutdown -EPROTONOSUPPORT Unsupported feature -EBADMSG Corrupted -ENODATA Truncated -ESHUTDOWN Already archived -EIDRM Journal file has been deleted */ if (r == -E2BIG || r == -EFBIG || r == -EDQUOT || r == -ENOSPC) log_debug("%s: Allocation limit reached, rotating.", f->path); else if (r == -EHOSTDOWN) log_info("%s: Journal file from other machine, rotating.", f->path); else if (r == -EBUSY) log_info("%s: Unclean shutdown, rotating.", f->path); else if (r == -EPROTONOSUPPORT) log_info("%s: Unsupported feature, rotating.", f->path); else if (r == -EBADMSG || r == -ENODATA || r == ESHUTDOWN) log_warning("%s: Journal file corrupted, rotating.", f->path); else if (r == -EIO) log_warning("%s: IO error, rotating.", f->path); else if (r == -EIDRM) log_warning("%s: Journal file has been deleted, rotating.", f->path); else return false; return true; } static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n, int priority) { JournalFile *f; bool vacuumed = false; int r; assert(s); assert(iovec); assert(n > 0); f = find_journal(s, uid); if (!f) return; if (journal_file_rotate_suggested(f, s->max_file_usec)) { log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path); server_rotate(s); server_vacuum(s, false, false); vacuumed = true; f = find_journal(s, uid); if (!f) return; } r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL); if (r >= 0) { server_schedule_sync(s, priority); return; } if (vacuumed || !shall_try_append_again(f, r)) { log_error_errno(r, "Failed to write entry (%d items, %zu bytes), ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n)); return; } server_rotate(s); server_vacuum(s, false, false); f = find_journal(s, uid); if (!f) return; log_debug("Retrying write."); r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL); if (r < 0) log_error_errno(r, "Failed to write entry (%d items, %zu bytes) despite vacuuming, ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n)); else server_schedule_sync(s, priority); } static void dispatch_message_real( Server *s, struct iovec *iovec, unsigned n, unsigned m, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len, const char *unit_id, int priority, pid_t object_pid) { char pid[sizeof("_PID=") + DECIMAL_STR_MAX(pid_t)], uid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)], gid[sizeof("_GID=") + DECIMAL_STR_MAX(gid_t)], owner_uid[sizeof("_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)], source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)], o_uid[sizeof("OBJECT_UID=") + DECIMAL_STR_MAX(uid_t)], o_gid[sizeof("OBJECT_GID=") + DECIMAL_STR_MAX(gid_t)], o_owner_uid[sizeof("OBJECT_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)]; uid_t object_uid; gid_t object_gid; char *x; int r; char *t, *c; uid_t realuid = 0, owner = 0, journal_uid; bool owner_valid = false; #ifdef HAVE_AUDIT char audit_session[sizeof("_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)], audit_loginuid[sizeof("_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)], o_audit_session[sizeof("OBJECT_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)], o_audit_loginuid[sizeof("OBJECT_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)]; uint32_t audit; uid_t loginuid; #endif assert(s); assert(iovec); assert(n > 0); assert(n + N_IOVEC_META_FIELDS + (object_pid ? N_IOVEC_OBJECT_FIELDS : 0) <= m); if (ucred) { realuid = ucred->uid; sprintf(pid, "_PID="PID_FMT, ucred->pid); IOVEC_SET_STRING(iovec[n++], pid); sprintf(uid, "_UID="UID_FMT, ucred->uid); IOVEC_SET_STRING(iovec[n++], uid); sprintf(gid, "_GID="GID_FMT, ucred->gid); IOVEC_SET_STRING(iovec[n++], gid); r = get_process_comm(ucred->pid, &t); if (r >= 0) { x = strjoina("_COMM=", t); free(t); IOVEC_SET_STRING(iovec[n++], x); } r = get_process_exe(ucred->pid, &t); if (r >= 0) { x = strjoina("_EXE=", t); free(t); IOVEC_SET_STRING(iovec[n++], x); } r = get_process_cmdline(ucred->pid, 0, false, &t); if (r >= 0) { x = strjoina("_CMDLINE=", t); free(t); IOVEC_SET_STRING(iovec[n++], x); } r = get_process_capeff(ucred->pid, &t); if (r >= 0) { x = strjoina("_CAP_EFFECTIVE=", t); free(t); IOVEC_SET_STRING(iovec[n++], x); } #ifdef HAVE_AUDIT r = audit_session_from_pid(ucred->pid, &audit); if (r >= 0) { sprintf(audit_session, "_AUDIT_SESSION=%"PRIu32, audit); IOVEC_SET_STRING(iovec[n++], audit_session); } r = audit_loginuid_from_pid(ucred->pid, &loginuid); if (r >= 0) { sprintf(audit_loginuid, "_AUDIT_LOGINUID="UID_FMT, loginuid); IOVEC_SET_STRING(iovec[n++], audit_loginuid); } #endif r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &c); if (r >= 0) { char *session = NULL; x = strjoina("_SYSTEMD_CGROUP=", c); IOVEC_SET_STRING(iovec[n++], x); r = cg_path_get_session(c, &t); if (r >= 0) { session = strjoina("_SYSTEMD_SESSION=", t); free(t); IOVEC_SET_STRING(iovec[n++], session); } if (cg_path_get_owner_uid(c, &owner) >= 0) { owner_valid = true; sprintf(owner_uid, "_SYSTEMD_OWNER_UID="UID_FMT, owner); IOVEC_SET_STRING(iovec[n++], owner_uid); } if (cg_path_get_unit(c, &t) >= 0) { x = strjoina("_SYSTEMD_UNIT=", t); free(t); IOVEC_SET_STRING(iovec[n++], x); } else if (unit_id && !session) { x = strjoina("_SYSTEMD_UNIT=", unit_id); IOVEC_SET_STRING(iovec[n++], x); } if (cg_path_get_user_unit(c, &t) >= 0) { x = strjoina("_SYSTEMD_USER_UNIT=", t); free(t); IOVEC_SET_STRING(iovec[n++], x); } else if (unit_id && session) { x = strjoina("_SYSTEMD_USER_UNIT=", unit_id); IOVEC_SET_STRING(iovec[n++], x); } if (cg_path_get_slice(c, &t) >= 0) { x = strjoina("_SYSTEMD_SLICE=", t); free(t); IOVEC_SET_STRING(iovec[n++], x); } free(c); } else if (unit_id) { x = strjoina("_SYSTEMD_UNIT=", unit_id); IOVEC_SET_STRING(iovec[n++], x); } #ifdef HAVE_SELINUX if (mac_selinux_have()) { if (label) { x = alloca(strlen("_SELINUX_CONTEXT=") + label_len + 1); *((char*) mempcpy(stpcpy(x, "_SELINUX_CONTEXT="), label, label_len)) = 0; IOVEC_SET_STRING(iovec[n++], x); } else { security_context_t con; if (getpidcon(ucred->pid, &con) >= 0) { x = strjoina("_SELINUX_CONTEXT=", con); freecon(con); IOVEC_SET_STRING(iovec[n++], x); } } } #endif } assert(n <= m); if (object_pid) { r = get_process_uid(object_pid, &object_uid); if (r >= 0) { sprintf(o_uid, "OBJECT_UID="UID_FMT, object_uid); IOVEC_SET_STRING(iovec[n++], o_uid); } r = get_process_gid(object_pid, &object_gid); if (r >= 0) { sprintf(o_gid, "OBJECT_GID="GID_FMT, object_gid); IOVEC_SET_STRING(iovec[n++], o_gid); } r = get_process_comm(object_pid, &t); if (r >= 0) { x = strjoina("OBJECT_COMM=", t); free(t); IOVEC_SET_STRING(iovec[n++], x); } r = get_process_exe(object_pid, &t); if (r >= 0) { x = strjoina("OBJECT_EXE=", t); free(t); IOVEC_SET_STRING(iovec[n++], x); } r = get_process_cmdline(object_pid, 0, false, &t); if (r >= 0) { x = strjoina("OBJECT_CMDLINE=", t); free(t); IOVEC_SET_STRING(iovec[n++], x); } #ifdef HAVE_AUDIT r = audit_session_from_pid(object_pid, &audit); if (r >= 0) { sprintf(o_audit_session, "OBJECT_AUDIT_SESSION=%"PRIu32, audit); IOVEC_SET_STRING(iovec[n++], o_audit_session); } r = audit_loginuid_from_pid(object_pid, &loginuid); if (r >= 0) { sprintf(o_audit_loginuid, "OBJECT_AUDIT_LOGINUID="UID_FMT, loginuid); IOVEC_SET_STRING(iovec[n++], o_audit_loginuid); } #endif r = cg_pid_get_path_shifted(object_pid, s->cgroup_root, &c); if (r >= 0) { x = strjoina("OBJECT_SYSTEMD_CGROUP=", c); IOVEC_SET_STRING(iovec[n++], x); r = cg_path_get_session(c, &t); if (r >= 0) { x = strjoina("OBJECT_SYSTEMD_SESSION=", t); free(t); IOVEC_SET_STRING(iovec[n++], x); } if (cg_path_get_owner_uid(c, &owner) >= 0) { sprintf(o_owner_uid, "OBJECT_SYSTEMD_OWNER_UID="UID_FMT, owner); IOVEC_SET_STRING(iovec[n++], o_owner_uid); } if (cg_path_get_unit(c, &t) >= 0) { x = strjoina("OBJECT_SYSTEMD_UNIT=", t); free(t); IOVEC_SET_STRING(iovec[n++], x); } if (cg_path_get_user_unit(c, &t) >= 0) { x = strjoina("OBJECT_SYSTEMD_USER_UNIT=", t); free(t); IOVEC_SET_STRING(iovec[n++], x); } free(c); } } assert(n <= m); if (tv) { sprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu", (unsigned long long) timeval_load(tv)); IOVEC_SET_STRING(iovec[n++], source_time); } /* Note that strictly speaking storing the boot id here is * redundant since the entry includes this in-line * anyway. However, we need this indexed, too. */ if (!isempty(s->boot_id_field)) IOVEC_SET_STRING(iovec[n++], s->boot_id_field); if (!isempty(s->machine_id_field)) IOVEC_SET_STRING(iovec[n++], s->machine_id_field); if (!isempty(s->hostname_field)) IOVEC_SET_STRING(iovec[n++], s->hostname_field); assert(n <= m); if (s->split_mode == SPLIT_UID && realuid > 0) /* Split up strictly by any UID */ journal_uid = realuid; else if (s->split_mode == SPLIT_LOGIN && realuid > 0 && owner_valid && owner > 0) /* Split up by login UIDs. We do this only if the * realuid is not root, in order not to accidentally * leak privileged information to the user that is * logged by a privileged process that is part of an * unprivileged session. */ journal_uid = owner; else journal_uid = 0; write_to_journal(s, journal_uid, iovec, n, priority); } void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) { char mid[11 + 32 + 1]; struct iovec iovec[N_IOVEC_META_FIELDS + 5 + N_IOVEC_PAYLOAD_FIELDS]; unsigned n = 0, m; int r; va_list ap; struct ucred ucred = {}; assert(s); assert(format); assert_cc(3 == LOG_FAC(LOG_DAEMON)); IOVEC_SET_STRING(iovec[n++], "SYSLOG_FACILITY=3"); IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=systemd-journald"); IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver"); assert_cc(6 == LOG_INFO); IOVEC_SET_STRING(iovec[n++], "PRIORITY=6"); if (!sd_id128_equal(message_id, SD_ID128_NULL)) { snprintf(mid, sizeof(mid), LOG_MESSAGE_ID(message_id)); IOVEC_SET_STRING(iovec[n++], mid); } m = n; va_start(ap, format); r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, false, 0, format, ap); /* Error handling below */ va_end(ap); ucred.pid = getpid(); ucred.uid = getuid(); ucred.gid = getgid(); if (r >= 0) dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0); while (m < n) free(iovec[m++].iov_base); if (r < 0) { /* We failed to format the message. Emit a warning instead. */ char buf[LINE_MAX]; xsprintf(buf, "MESSAGE=Entry printing failed: %s", strerror(-r)); n = 3; IOVEC_SET_STRING(iovec[n++], "PRIORITY=4"); IOVEC_SET_STRING(iovec[n++], buf); dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0); } } void server_dispatch_message( Server *s, struct iovec *iovec, unsigned n, unsigned m, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len, const char *unit_id, int priority, pid_t object_pid) { int rl, r; _cleanup_free_ char *path = NULL; uint64_t available = 0; char *c; assert(s); assert(iovec || n == 0); if (n == 0) return; if (LOG_PRI(priority) > s->max_level_store) return; /* Stop early in case the information will not be stored * in a journal. */ if (s->storage == STORAGE_NONE) return; if (!ucred) goto finish; r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &path); if (r < 0) goto finish; /* example: /user/lennart/3/foobar * /system/dbus.service/foobar * * So let's cut of everything past the third /, since that is * where user directories start */ c = strchr(path, '/'); if (c) { c = strchr(c+1, '/'); if (c) { c = strchr(c+1, '/'); if (c) *c = 0; } } (void) determine_space(s, false, false, &available, NULL); rl = journal_rate_limit_test(s->rate_limit, path, priority & LOG_PRIMASK, available); if (rl == 0) return; /* Write a suppression message if we suppressed something */ if (rl > 1) server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED, LOG_MESSAGE("Suppressed %u messages from %s", rl - 1, path), NULL); finish: dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id, priority, object_pid); } static int system_journal_open(Server *s, bool flush_requested) { const char *fn; int r = 0; if (!s->system_journal && (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) && (flush_requested || access("/run/systemd/journal/flushed", F_OK) >= 0)) { /* If in auto mode: first try to create the machine * path, but not the prefix. * * If in persistent mode: create /var/log/journal and * the machine path */ if (s->storage == STORAGE_PERSISTENT) (void) mkdir_p("/var/log/journal/", 0755); fn = strjoina("/var/log/journal/", SERVER_MACHINE_ID(s)); (void) mkdir(fn, 0755); fn = strjoina(fn, "/system.journal"); r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_metrics, &s->system_journal); if (r >= 0) { server_add_acls(s->system_journal, 0); (void) determine_space_for(s, &s->system_metrics, "/var/log/journal/", "System journal", true, true, NULL, NULL); } else if (r < 0) { if (r != -ENOENT && r != -EROFS) log_warning_errno(r, "Failed to open system journal: %m"); r = 0; } } if (!s->runtime_journal && (s->storage != STORAGE_NONE)) { fn = strjoina("/run/log/journal/", SERVER_MACHINE_ID(s), "/system.journal"); if (s->system_journal) { /* Try to open the runtime journal, but only * if it already exists, so that we can flush * it into the system journal */ r = open_journal(s, false, fn, O_RDWR, false, &s->runtime_metrics, &s->runtime_journal); if (r < 0) { if (r != -ENOENT) log_warning_errno(r, "Failed to open runtime journal: %m"); r = 0; } } else { /* OK, we really need the runtime journal, so create * it if necessary. */ (void) mkdir("/run/log", 0755); (void) mkdir("/run/log/journal", 0755); (void) mkdir_parents(fn, 0750); r = open_journal(s, true, fn, O_RDWR|O_CREAT, false, &s->runtime_metrics, &s->runtime_journal); if (r < 0) return log_error_errno(r, "Failed to open runtime journal: %m"); } if (s->runtime_journal) { server_add_acls(s->runtime_journal, 0); (void) determine_space_for(s, &s->runtime_metrics, "/run/log/journal/", "Runtime journal", true, true, NULL, NULL); } } return r; } int server_flush_to_var(Server *s) { sd_id128_t machine; sd_journal *j = NULL; char ts[FORMAT_TIMESPAN_MAX]; usec_t start; unsigned n = 0; int r; assert(s); if (s->storage != STORAGE_AUTO && s->storage != STORAGE_PERSISTENT) return 0; if (!s->runtime_journal) return 0; (void) system_journal_open(s, true); if (!s->system_journal) return 0; log_debug("Flushing to /var..."); start = now(CLOCK_MONOTONIC); r = sd_id128_get_machine(&machine); if (r < 0) return r; r = sd_journal_open(&j, SD_JOURNAL_RUNTIME_ONLY); if (r < 0) return log_error_errno(r, "Failed to read runtime journal: %m"); sd_journal_set_data_threshold(j, 0); SD_JOURNAL_FOREACH(j) { Object *o = NULL; JournalFile *f; f = j->current_file; assert(f && f->current_offset > 0); n++; r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); if (r < 0) { log_error_errno(r, "Can't read entry: %m"); goto finish; } r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL); if (r >= 0) continue; if (!shall_try_append_again(s->system_journal, r)) { log_error_errno(r, "Can't write entry: %m"); goto finish; } server_rotate(s); server_vacuum(s, false, false); if (!s->system_journal) { log_notice("Didn't flush runtime journal since rotation of system journal wasn't successful."); r = -EIO; goto finish; } log_debug("Retrying write."); r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL); if (r < 0) { log_error_errno(r, "Can't write entry: %m"); goto finish; } } r = 0; finish: journal_file_post_change(s->system_journal); s->runtime_journal = journal_file_close(s->runtime_journal); if (r >= 0) (void) rm_rf("/run/log/journal", REMOVE_ROOT); sd_journal_close(j); server_driver_message(s, SD_ID128_NULL, LOG_MESSAGE("Time spent on flushing to /var is %s for %u entries.", format_timespan(ts, sizeof(ts), now(CLOCK_MONOTONIC) - start, 0), n), NULL); return r; } int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata) { Server *s = userdata; struct ucred *ucred = NULL; struct timeval *tv = NULL; struct cmsghdr *cmsg; char *label = NULL; size_t label_len = 0, m; struct iovec iovec; ssize_t n; int *fds = NULL, v = 0; unsigned n_fds = 0; union { struct cmsghdr cmsghdr; /* We use NAME_MAX space for the SELinux label * here. The kernel currently enforces no * limit, but according to suggestions from * the SELinux people this will change and it * will probably be identical to NAME_MAX. For * now we use that, but this should be updated * one day when the final limit is known. */ uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(int)) + /* fd */ CMSG_SPACE(NAME_MAX)]; /* selinux label */ } control = {}; union sockaddr_union sa = {}; struct msghdr msghdr = { .msg_iov = &iovec, .msg_iovlen = 1, .msg_control = &control, .msg_controllen = sizeof(control), .msg_name = &sa, .msg_namelen = sizeof(sa), }; assert(s); assert(fd == s->native_fd || fd == s->syslog_fd || fd == s->audit_fd); if (revents != EPOLLIN) { log_error("Got invalid event from epoll for datagram fd: %"PRIx32, revents); return -EIO; } /* Try to get the right size, if we can. (Not all * sockets support SIOCINQ, hence we just try, but * don't rely on it. */ (void) ioctl(fd, SIOCINQ, &v); /* Fix it up, if it is too small. We use the same fixed value as auditd here. Awful! */ m = PAGE_ALIGN(MAX3((size_t) v + 1, (size_t) LINE_MAX, ALIGN(sizeof(struct nlmsghdr)) + ALIGN((size_t) MAX_AUDIT_MESSAGE_LENGTH)) + 1); if (!GREEDY_REALLOC(s->buffer, s->buffer_size, m)) return log_oom(); iovec.iov_base = s->buffer; iovec.iov_len = s->buffer_size - 1; /* Leave room for trailing NUL we add later */ n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); if (n < 0) { if (errno == EINTR || errno == EAGAIN) return 0; return log_error_errno(errno, "recvmsg() failed: %m"); } CMSG_FOREACH(cmsg, &msghdr) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) ucred = (struct ucred*) CMSG_DATA(cmsg); else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_SECURITY) { label = (char*) CMSG_DATA(cmsg); label_len = cmsg->cmsg_len - CMSG_LEN(0); } else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP && cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) tv = (struct timeval*) CMSG_DATA(cmsg); else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { fds = (int*) CMSG_DATA(cmsg); n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); } } /* And a trailing NUL, just in case */ s->buffer[n] = 0; if (fd == s->syslog_fd) { if (n > 0 && n_fds == 0) server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len); else if (n_fds > 0) log_warning("Got file descriptors via syslog socket. Ignoring."); } else if (fd == s->native_fd) { if (n > 0 && n_fds == 0) server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len); else if (n == 0 && n_fds == 1) server_process_native_file(s, fds[0], ucred, tv, label, label_len); else if (n_fds > 0) log_warning("Got too many file descriptors via native socket. Ignoring."); } else { assert(fd == s->audit_fd); if (n > 0 && n_fds == 0) server_process_audit_message(s, s->buffer, n, ucred, &sa, msghdr.msg_namelen); else if (n_fds > 0) log_warning("Got file descriptors via audit socket. Ignoring."); } close_many(fds, n_fds); return 0; } static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) { Server *s = userdata; int r; assert(s); log_info("Received request to flush runtime journal from PID " PID_FMT, si->ssi_pid); server_flush_to_var(s); server_sync(s); server_vacuum(s, false, false); r = touch("/run/systemd/journal/flushed"); if (r < 0) log_warning_errno(r, "Failed to touch /run/systemd/journal/flushed, ignoring: %m"); return 0; } static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) { Server *s = userdata; int r; assert(s); log_info("Received request to rotate journal from PID " PID_FMT, si->ssi_pid); server_rotate(s); server_vacuum(s, true, true); /* Let clients know when the most recent rotation happened. */ r = write_timestamp_file_atomic("/run/systemd/journal/rotated", now(CLOCK_MONOTONIC)); if (r < 0) log_warning_errno(r, "Failed to write /run/systemd/journal/rotated, ignoring: %m"); return 0; } static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) { Server *s = userdata; assert(s); log_received_signal(LOG_INFO, si); sd_event_exit(s->event, 0); return 0; } static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) { Server *s = userdata; int r; assert(s); log_debug("Received request to sync from PID " PID_FMT, si->ssi_pid); server_sync(s); /* Let clients know when the most recent sync happened. */ r = write_timestamp_file_atomic("/run/systemd/journal/synced", now(CLOCK_MONOTONIC)); if (r < 0) log_warning_errno(r, "Failed to write /run/systemd/journal/synced, ignoring: %m"); return 0; } static int setup_signals(Server *s) { int r; assert(s); assert(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGRTMIN+1, -1) >= 0); r = sd_event_add_signal(s->event, &s->sigusr1_event_source, SIGUSR1, dispatch_sigusr1, s); if (r < 0) return r; r = sd_event_add_signal(s->event, &s->sigusr2_event_source, SIGUSR2, dispatch_sigusr2, s); if (r < 0) return r; r = sd_event_add_signal(s->event, &s->sigterm_event_source, SIGTERM, dispatch_sigterm, s); if (r < 0) return r; /* Let's process SIGTERM late, so that we flush all queued * messages to disk before we exit */ r = sd_event_source_set_priority(s->sigterm_event_source, SD_EVENT_PRIORITY_NORMAL+20); if (r < 0) return r; /* When journald is invoked on the terminal (when debugging), * it's useful if C-c is handled equivalent to SIGTERM. */ r = sd_event_add_signal(s->event, &s->sigint_event_source, SIGINT, dispatch_sigterm, s); if (r < 0) return r; r = sd_event_source_set_priority(s->sigint_event_source, SD_EVENT_PRIORITY_NORMAL+20); if (r < 0) return r; /* SIGRTMIN+1 causes an immediate sync. We process this very * late, so that everything else queued at this point is * really written to disk. Clients can watch * /run/systemd/journal/synced with inotify until its mtime * changes to see when a sync happened. */ r = sd_event_add_signal(s->event, &s->sigrtmin1_event_source, SIGRTMIN+1, dispatch_sigrtmin1, s); if (r < 0) return r; r = sd_event_source_set_priority(s->sigrtmin1_event_source, SD_EVENT_PRIORITY_NORMAL+15); if (r < 0) return r; return 0; } static int server_parse_proc_cmdline(Server *s) { _cleanup_free_ char *line = NULL; const char *p; int r; r = proc_cmdline(&line); if (r < 0) { log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m"); return 0; } p = line; for(;;) { _cleanup_free_ char *word = NULL; r = extract_first_word(&p, &word, NULL, 0); if (r < 0) return log_error_errno(r, "Failed to parse journald syntax \"%s\": %m", line); if (r == 0) break; if (startswith(word, "systemd.journald.forward_to_syslog=")) { r = parse_boolean(word + 35); if (r < 0) log_warning("Failed to parse forward to syslog switch %s. Ignoring.", word + 35); else s->forward_to_syslog = r; } else if (startswith(word, "systemd.journald.forward_to_kmsg=")) { r = parse_boolean(word + 33); if (r < 0) log_warning("Failed to parse forward to kmsg switch %s. Ignoring.", word + 33); else s->forward_to_kmsg = r; } else if (startswith(word, "systemd.journald.forward_to_console=")) { r = parse_boolean(word + 36); if (r < 0) log_warning("Failed to parse forward to console switch %s. Ignoring.", word + 36); else s->forward_to_console = r; } else if (startswith(word, "systemd.journald.forward_to_wall=")) { r = parse_boolean(word + 33); if (r < 0) log_warning("Failed to parse forward to wall switch %s. Ignoring.", word + 33); else s->forward_to_wall = r; } else if (startswith(word, "systemd.journald")) log_warning("Invalid systemd.journald parameter. Ignoring."); } /* do not warn about state here, since probably systemd already did */ return 0; } static int server_parse_config_file(Server *s) { assert(s); return config_parse_many(PKGSYSCONFDIR "/journald.conf", CONF_PATHS_NULSTR("systemd/journald.conf.d"), "Journal\0", config_item_perf_lookup, journald_gperf_lookup, false, s); } static int server_dispatch_sync(sd_event_source *es, usec_t t, void *userdata) { Server *s = userdata; assert(s); server_sync(s); return 0; } int server_schedule_sync(Server *s, int priority) { int r; assert(s); if (priority <= LOG_CRIT) { /* Immediately sync to disk when this is of priority CRIT, ALERT, EMERG */ server_sync(s); return 0; } if (s->sync_scheduled) return 0; if (s->sync_interval_usec > 0) { usec_t when; r = sd_event_now(s->event, CLOCK_MONOTONIC, &when); if (r < 0) return r; when += s->sync_interval_usec; if (!s->sync_event_source) { r = sd_event_add_time( s->event, &s->sync_event_source, CLOCK_MONOTONIC, when, 0, server_dispatch_sync, s); if (r < 0) return r; r = sd_event_source_set_priority(s->sync_event_source, SD_EVENT_PRIORITY_IMPORTANT); } else { r = sd_event_source_set_time(s->sync_event_source, when); if (r < 0) return r; r = sd_event_source_set_enabled(s->sync_event_source, SD_EVENT_ONESHOT); } if (r < 0) return r; s->sync_scheduled = true; } return 0; } static int dispatch_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) { Server *s = userdata; assert(s); server_cache_hostname(s); return 0; } static int server_open_hostname(Server *s) { int r; assert(s); s->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY); if (s->hostname_fd < 0) return log_error_errno(errno, "Failed to open /proc/sys/kernel/hostname: %m"); r = sd_event_add_io(s->event, &s->hostname_event_source, s->hostname_fd, 0, dispatch_hostname_change, s); if (r < 0) { /* kernels prior to 3.2 don't support polling this file. Ignore * the failure. */ if (r == -EPERM) { log_warning_errno(r, "Failed to register hostname fd in event loop, ignoring: %m"); s->hostname_fd = safe_close(s->hostname_fd); return 0; } return log_error_errno(r, "Failed to register hostname fd in event loop: %m"); } r = sd_event_source_set_priority(s->hostname_event_source, SD_EVENT_PRIORITY_IMPORTANT-10); if (r < 0) return log_error_errno(r, "Failed to adjust priority of host name event source: %m"); return 0; } static int dispatch_notify_event(sd_event_source *es, int fd, uint32_t revents, void *userdata) { Server *s = userdata; int r; assert(s); assert(s->notify_event_source == es); assert(s->notify_fd == fd); /* The $NOTIFY_SOCKET is writable again, now send exactly one * message on it. Either it's the wtachdog event, the initial * READY=1 event or an stdout stream event. If there's nothing * to write anymore, turn our event source off. The next time * there's something to send it will be turned on again. */ if (!s->sent_notify_ready) { static const char p[] = "READY=1\n" "STATUS=Processing requests..."; ssize_t l; l = send(s->notify_fd, p, strlen(p), MSG_DONTWAIT); if (l < 0) { if (errno == EAGAIN) return 0; return log_error_errno(errno, "Failed to send READY=1 notification message: %m"); } s->sent_notify_ready = true; log_debug("Sent READY=1 notification."); } else if (s->send_watchdog) { static const char p[] = "WATCHDOG=1"; ssize_t l; l = send(s->notify_fd, p, strlen(p), MSG_DONTWAIT); if (l < 0) { if (errno == EAGAIN) return 0; return log_error_errno(errno, "Failed to send WATCHDOG=1 notification message: %m"); } s->send_watchdog = false; log_debug("Sent WATCHDOG=1 notification."); } else if (s->stdout_streams_notify_queue) /* Dispatch one stream notification event */ stdout_stream_send_notify(s->stdout_streams_notify_queue); /* Leave us enabled if there's still more to to do. */ if (s->send_watchdog || s->stdout_streams_notify_queue) return 0; /* There was nothing to do anymore, let's turn ourselves off. */ r = sd_event_source_set_enabled(es, SD_EVENT_OFF); if (r < 0) return log_error_errno(r, "Failed to turn off notify event source: %m"); return 0; } static int dispatch_watchdog(sd_event_source *es, uint64_t usec, void *userdata) { Server *s = userdata; int r; assert(s); s->send_watchdog = true; r = sd_event_source_set_enabled(s->notify_event_source, SD_EVENT_ON); if (r < 0) log_warning_errno(r, "Failed to turn on notify event source: %m"); r = sd_event_source_set_time(s->watchdog_event_source, usec + s->watchdog_usec / 2); if (r < 0) return log_error_errno(r, "Failed to restart watchdog event source: %m"); r = sd_event_source_set_enabled(s->watchdog_event_source, SD_EVENT_ON); if (r < 0) return log_error_errno(r, "Failed to enable watchdog event source: %m"); return 0; } static int server_connect_notify(Server *s) { union sockaddr_union sa = { .un.sun_family = AF_UNIX, }; const char *e; int r; assert(s); assert(s->notify_fd < 0); assert(!s->notify_event_source); /* So here's the problem: we'd like to send notification messages to PID 1, but we cannot do that via sd_notify(), since that's synchronous, and we might end up blocking on it. Specifically: given that PID 1 might block on dbus-daemon during IPC, and dbus-daemon is logging to us, and might hence block on us, we might end up in a deadlock if we block on sending PID 1 notification messages -- by generating a full blocking circle. To avoid this, let's create a non-blocking socket, and connect it to the notification socket, and then wait for POLLOUT before we send anything. This should efficiently avoid any deadlocks, as we'll never block on PID 1, hence PID 1 can safely block on dbus-daemon which can safely block on us again. Don't think that this issue is real? It is, see: https://github.com/systemd/systemd/issues/1505 */ e = getenv("NOTIFY_SOCKET"); if (!e) return 0; if ((e[0] != '@' && e[0] != '/') || e[1] == 0) { log_error("NOTIFY_SOCKET set to an invalid value: %s", e); return -EINVAL; } if (strlen(e) > sizeof(sa.un.sun_path)) { log_error("NOTIFY_SOCKET path too long: %s", e); return -EINVAL; } s->notify_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (s->notify_fd < 0) return log_error_errno(errno, "Failed to create notify socket: %m"); (void) fd_inc_sndbuf(s->notify_fd, NOTIFY_SNDBUF_SIZE); strncpy(sa.un.sun_path, e, sizeof(sa.un.sun_path)); if (sa.un.sun_path[0] == '@') sa.un.sun_path[0] = 0; r = connect(s->notify_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(e)); if (r < 0) return log_error_errno(errno, "Failed to connect to notify socket: %m"); r = sd_event_add_io(s->event, &s->notify_event_source, s->notify_fd, EPOLLOUT, dispatch_notify_event, s); if (r < 0) return log_error_errno(r, "Failed to watch notification socket: %m"); if (sd_watchdog_enabled(false, &s->watchdog_usec) > 0) { s->send_watchdog = true; r = sd_event_add_time(s->event, &s->watchdog_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + s->watchdog_usec/2, s->watchdog_usec/4, dispatch_watchdog, s); if (r < 0) return log_error_errno(r, "Failed to add watchdog time event: %m"); } /* This should fire pretty soon, which we'll use to send the * READY=1 event. */ return 0; } int server_init(Server *s) { _cleanup_fdset_free_ FDSet *fds = NULL; int n, r, fd; bool no_sockets; assert(s); zero(*s); s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->audit_fd = s->hostname_fd = s->notify_fd = -1; s->compress = true; s->seal = true; s->watchdog_usec = USEC_INFINITY; s->sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC; s->sync_scheduled = false; s->rate_limit_interval = DEFAULT_RATE_LIMIT_INTERVAL; s->rate_limit_burst = DEFAULT_RATE_LIMIT_BURST; s->forward_to_wall = true; s->max_file_usec = DEFAULT_MAX_FILE_USEC; s->max_level_store = LOG_DEBUG; s->max_level_syslog = LOG_DEBUG; s->max_level_kmsg = LOG_NOTICE; s->max_level_console = LOG_INFO; s->max_level_wall = LOG_EMERG; journal_reset_metrics(&s->system_metrics); journal_reset_metrics(&s->runtime_metrics); server_parse_config_file(s); server_parse_proc_cmdline(s); if (!!s->rate_limit_interval ^ !!s->rate_limit_burst) { log_debug("Setting both rate limit interval and burst from "USEC_FMT",%u to 0,0", s->rate_limit_interval, s->rate_limit_burst); s->rate_limit_interval = s->rate_limit_burst = 0; } (void) mkdir_p("/run/systemd/journal", 0755); s->user_journals = ordered_hashmap_new(NULL); if (!s->user_journals) return log_oom(); s->mmap = mmap_cache_new(); if (!s->mmap) return log_oom(); r = sd_event_default(&s->event); if (r < 0) return log_error_errno(r, "Failed to create event loop: %m"); n = sd_listen_fds(true); if (n < 0) return log_error_errno(n, "Failed to read listening file descriptors from environment: %m"); for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/run/systemd/journal/socket", 0) > 0) { if (s->native_fd >= 0) { log_error("Too many native sockets passed."); return -EINVAL; } s->native_fd = fd; } else if (sd_is_socket_unix(fd, SOCK_STREAM, 1, "/run/systemd/journal/stdout", 0) > 0) { if (s->stdout_fd >= 0) { log_error("Too many stdout sockets passed."); return -EINVAL; } s->stdout_fd = fd; } else if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/dev/log", 0) > 0 || sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/run/systemd/journal/dev-log", 0) > 0) { if (s->syslog_fd >= 0) { log_error("Too many /dev/log sockets passed."); return -EINVAL; } s->syslog_fd = fd; } else if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) { if (s->audit_fd >= 0) { log_error("Too many audit sockets passed."); return -EINVAL; } s->audit_fd = fd; } else { if (!fds) { fds = fdset_new(); if (!fds) return log_oom(); } r = fdset_put(fds, fd); if (r < 0) return log_oom(); } } /* Try to restore streams, but don't bother if this fails */ (void) server_restore_streams(s, fds); if (fdset_size(fds) > 0) { log_warning("%u unknown file descriptors passed, closing.", fdset_size(fds)); fds = fdset_free(fds); } no_sockets = s->native_fd < 0 && s->stdout_fd < 0 && s->syslog_fd < 0 && s->audit_fd < 0; /* always open stdout, syslog, native, and kmsg sockets */ /* systemd-journald.socket: /run/systemd/journal/stdout */ r = server_open_stdout_socket(s); if (r < 0) return r; /* systemd-journald-dev-log.socket: /run/systemd/journal/dev-log */ r = server_open_syslog_socket(s); if (r < 0) return r; /* systemd-journald.socket: /run/systemd/journal/socket */ r = server_open_native_socket(s); if (r < 0) return r; /* /dev/ksmg */ r = server_open_dev_kmsg(s); if (r < 0) return r; /* Unless we got *some* sockets and not audit, open audit socket */ if (s->audit_fd >= 0 || no_sockets) { r = server_open_audit(s); if (r < 0) return r; } r = server_open_kernel_seqnum(s); if (r < 0) return r; r = server_open_hostname(s); if (r < 0) return r; r = setup_signals(s); if (r < 0) return r; s->udev = udev_new(); if (!s->udev) return -ENOMEM; s->rate_limit = journal_rate_limit_new(s->rate_limit_interval, s->rate_limit_burst); if (!s->rate_limit) return -ENOMEM; r = cg_get_root_path(&s->cgroup_root); if (r < 0) return r; server_cache_hostname(s); server_cache_boot_id(s); server_cache_machine_id(s); (void) server_connect_notify(s); return system_journal_open(s, false); } void server_maybe_append_tags(Server *s) { #ifdef HAVE_GCRYPT JournalFile *f; Iterator i; usec_t n; n = now(CLOCK_REALTIME); if (s->system_journal) journal_file_maybe_append_tag(s->system_journal, n); ORDERED_HASHMAP_FOREACH(f, s->user_journals, i) journal_file_maybe_append_tag(f, n); #endif } void server_done(Server *s) { JournalFile *f; assert(s); while (s->stdout_streams) stdout_stream_free(s->stdout_streams); if (s->system_journal) journal_file_close(s->system_journal); if (s->runtime_journal) journal_file_close(s->runtime_journal); while ((f = ordered_hashmap_steal_first(s->user_journals))) journal_file_close(f); ordered_hashmap_free(s->user_journals); sd_event_source_unref(s->syslog_event_source); sd_event_source_unref(s->native_event_source); sd_event_source_unref(s->stdout_event_source); sd_event_source_unref(s->dev_kmsg_event_source); sd_event_source_unref(s->audit_event_source); sd_event_source_unref(s->sync_event_source); sd_event_source_unref(s->sigusr1_event_source); sd_event_source_unref(s->sigusr2_event_source); sd_event_source_unref(s->sigterm_event_source); sd_event_source_unref(s->sigint_event_source); sd_event_source_unref(s->sigrtmin1_event_source); sd_event_source_unref(s->hostname_event_source); sd_event_source_unref(s->notify_event_source); sd_event_source_unref(s->watchdog_event_source); sd_event_unref(s->event); safe_close(s->syslog_fd); safe_close(s->native_fd); safe_close(s->stdout_fd); safe_close(s->dev_kmsg_fd); safe_close(s->audit_fd); safe_close(s->hostname_fd); safe_close(s->notify_fd); if (s->rate_limit) journal_rate_limit_free(s->rate_limit); if (s->kernel_seqnum) munmap(s->kernel_seqnum, sizeof(uint64_t)); free(s->buffer); free(s->tty_path); free(s->cgroup_root); free(s->hostname_field); if (s->mmap) mmap_cache_unref(s->mmap); udev_unref(s->udev); } static const char* const storage_table[_STORAGE_MAX] = { [STORAGE_AUTO] = "auto", [STORAGE_VOLATILE] = "volatile", [STORAGE_PERSISTENT] = "persistent", [STORAGE_NONE] = "none" }; DEFINE_STRING_TABLE_LOOKUP(storage, Storage); DEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting"); static const char* const split_mode_table[_SPLIT_MAX] = { [SPLIT_LOGIN] = "login", [SPLIT_UID] = "uid", [SPLIT_NONE] = "none", }; DEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode); DEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting"); systemd-229/src/journal/journald-server.h000066400000000000000000000131051265713322000206150ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-event.h" typedef struct Server Server; #include "hashmap.h" #include "journal-file.h" #include "journald-rate-limit.h" #include "journald-stream.h" #include "list.h" typedef enum Storage { STORAGE_AUTO, STORAGE_VOLATILE, STORAGE_PERSISTENT, STORAGE_NONE, _STORAGE_MAX, _STORAGE_INVALID = -1 } Storage; typedef enum SplitMode { SPLIT_UID, SPLIT_LOGIN, SPLIT_NONE, _SPLIT_MAX, _SPLIT_INVALID = -1 } SplitMode; struct Server { int syslog_fd; int native_fd; int stdout_fd; int dev_kmsg_fd; int audit_fd; int hostname_fd; int notify_fd; sd_event *event; sd_event_source *syslog_event_source; sd_event_source *native_event_source; sd_event_source *stdout_event_source; sd_event_source *dev_kmsg_event_source; sd_event_source *audit_event_source; sd_event_source *sync_event_source; sd_event_source *sigusr1_event_source; sd_event_source *sigusr2_event_source; sd_event_source *sigterm_event_source; sd_event_source *sigint_event_source; sd_event_source *sigrtmin1_event_source; sd_event_source *hostname_event_source; sd_event_source *notify_event_source; sd_event_source *watchdog_event_source; JournalFile *runtime_journal; JournalFile *system_journal; OrderedHashmap *user_journals; uint64_t seqnum; char *buffer; size_t buffer_size; JournalRateLimit *rate_limit; usec_t sync_interval_usec; usec_t rate_limit_interval; unsigned rate_limit_burst; JournalMetrics runtime_metrics; JournalMetrics system_metrics; bool compress; bool seal; bool forward_to_kmsg; bool forward_to_syslog; bool forward_to_console; bool forward_to_wall; unsigned n_forward_syslog_missed; usec_t last_warn_forward_syslog_missed; uint64_t cached_space_available; uint64_t cached_space_limit; usec_t cached_space_timestamp; uint64_t var_available_timestamp; usec_t max_retention_usec; usec_t max_file_usec; usec_t oldest_file_usec; LIST_HEAD(StdoutStream, stdout_streams); LIST_HEAD(StdoutStream, stdout_streams_notify_queue); unsigned n_stdout_streams; char *tty_path; int max_level_store; int max_level_syslog; int max_level_kmsg; int max_level_console; int max_level_wall; Storage storage; SplitMode split_mode; MMapCache *mmap; struct udev *udev; uint64_t *kernel_seqnum; bool dev_kmsg_readable:1; bool send_watchdog:1; bool sent_notify_ready:1; bool sync_scheduled:1; char machine_id_field[sizeof("_MACHINE_ID=") + 32]; char boot_id_field[sizeof("_BOOT_ID=") + 32]; char *hostname_field; /* Cached cgroup root, so that we don't have to query that all the time */ char *cgroup_root; usec_t watchdog_usec; }; #define SERVER_MACHINE_ID(s) ((s)->machine_id_field + strlen("_MACHINE_ID=")) #define N_IOVEC_META_FIELDS 20 #define N_IOVEC_KERNEL_FIELDS 64 #define N_IOVEC_UDEV_FIELDS 32 #define N_IOVEC_OBJECT_FIELDS 12 #define N_IOVEC_PAYLOAD_FIELDS 15 void server_dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigned m, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len, const char *unit_id, int priority, pid_t object_pid); void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) _printf_(3,0) _sentinel_; /* gperf lookup function */ const struct ConfigPerfItem* journald_gperf_lookup(const char *key, unsigned length); int config_parse_storage(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); const char *storage_to_string(Storage s) _const_; Storage storage_from_string(const char *s) _pure_; int config_parse_split_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); const char *split_mode_to_string(SplitMode s) _const_; SplitMode split_mode_from_string(const char *s) _pure_; int server_init(Server *s); void server_done(Server *s); void server_sync(Server *s); int server_vacuum(Server *s, bool verbose, bool patch_min_use); void server_rotate(Server *s); int server_schedule_sync(Server *s, int priority); int server_flush_to_var(Server *s); void server_maybe_append_tags(Server *s); int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata); systemd-229/src/journal/journald-stream.c000066400000000000000000000566171265713322000206140ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #ifdef HAVE_SELINUX #include #endif #include "sd-daemon.h" #include "sd-event.h" #include "alloc-util.h" #include "dirent-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "io-util.h" #include "journald-console.h" #include "journald-kmsg.h" #include "journald-server.h" #include "journald-stream.h" #include "journald-syslog.h" #include "journald-wall.h" #include "mkdir.h" #include "parse-util.h" #include "selinux-util.h" #include "socket-util.h" #include "stdio-util.h" #include "string-util.h" #include "syslog-util.h" #define STDOUT_STREAMS_MAX 4096 typedef enum StdoutStreamState { STDOUT_STREAM_IDENTIFIER, STDOUT_STREAM_UNIT_ID, STDOUT_STREAM_PRIORITY, STDOUT_STREAM_LEVEL_PREFIX, STDOUT_STREAM_FORWARD_TO_SYSLOG, STDOUT_STREAM_FORWARD_TO_KMSG, STDOUT_STREAM_FORWARD_TO_CONSOLE, STDOUT_STREAM_RUNNING } StdoutStreamState; struct StdoutStream { Server *server; StdoutStreamState state; int fd; struct ucred ucred; char *label; char *identifier; char *unit_id; int priority; bool level_prefix:1; bool forward_to_syslog:1; bool forward_to_kmsg:1; bool forward_to_console:1; bool fdstore:1; bool in_notify_queue:1; char buffer[LINE_MAX+1]; size_t length; sd_event_source *event_source; char *state_file; LIST_FIELDS(StdoutStream, stdout_stream); LIST_FIELDS(StdoutStream, stdout_stream_notify_queue); }; void stdout_stream_free(StdoutStream *s) { if (!s) return; if (s->server) { assert(s->server->n_stdout_streams > 0); s->server->n_stdout_streams --; LIST_REMOVE(stdout_stream, s->server->stdout_streams, s); if (s->in_notify_queue) LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s); } if (s->event_source) { sd_event_source_set_enabled(s->event_source, SD_EVENT_OFF); s->event_source = sd_event_source_unref(s->event_source); } safe_close(s->fd); free(s->label); free(s->identifier); free(s->unit_id); free(s->state_file); free(s); } DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream*, stdout_stream_free); static void stdout_stream_destroy(StdoutStream *s) { if (!s) return; if (s->state_file) (void) unlink(s->state_file); stdout_stream_free(s); } static int stdout_stream_save(StdoutStream *s) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(s); if (s->state != STDOUT_STREAM_RUNNING) return 0; if (!s->state_file) { struct stat st; r = fstat(s->fd, &st); if (r < 0) return log_warning_errno(errno, "Failed to stat connected stream: %m"); /* We use device and inode numbers as identifier for the stream */ if (asprintf(&s->state_file, "/run/systemd/journal/streams/%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino) < 0) return log_oom(); } mkdir_p("/run/systemd/journal/streams", 0755); r = fopen_temporary(s->state_file, &f, &temp_path); if (r < 0) goto fail; fprintf(f, "# This is private data. Do not parse\n" "PRIORITY=%i\n" "LEVEL_PREFIX=%i\n" "FORWARD_TO_SYSLOG=%i\n" "FORWARD_TO_KMSG=%i\n" "FORWARD_TO_CONSOLE=%i\n", s->priority, s->level_prefix, s->forward_to_syslog, s->forward_to_kmsg, s->forward_to_console); if (!isempty(s->identifier)) { _cleanup_free_ char *escaped; escaped = cescape(s->identifier); if (!escaped) { r = -ENOMEM; goto fail; } fprintf(f, "IDENTIFIER=%s\n", escaped); } if (!isempty(s->unit_id)) { _cleanup_free_ char *escaped; escaped = cescape(s->unit_id); if (!escaped) { r = -ENOMEM; goto fail; } fprintf(f, "UNIT=%s\n", escaped); } r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, s->state_file) < 0) { r = -errno; goto fail; } if (!s->fdstore && !s->in_notify_queue) { LIST_PREPEND(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s); s->in_notify_queue = true; if (s->server->notify_event_source) { r = sd_event_source_set_enabled(s->server->notify_event_source, SD_EVENT_ON); if (r < 0) log_warning_errno(r, "Failed to enable notify event source: %m"); } } return 0; fail: (void) unlink(s->state_file); if (temp_path) (void) unlink(temp_path); return log_error_errno(r, "Failed to save stream data %s: %m", s->state_file); } static int stdout_stream_log(StdoutStream *s, const char *p) { struct iovec iovec[N_IOVEC_META_FIELDS + 5]; int priority; char syslog_priority[] = "PRIORITY=\0"; char syslog_facility[sizeof("SYSLOG_FACILITY=")-1 + DECIMAL_STR_MAX(int) + 1]; _cleanup_free_ char *message = NULL, *syslog_identifier = NULL; unsigned n = 0; size_t label_len; assert(s); assert(p); priority = s->priority; if (s->level_prefix) syslog_parse_priority(&p, &priority, false); if (isempty(p)) return 0; if (s->forward_to_syslog || s->server->forward_to_syslog) server_forward_syslog(s->server, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL); if (s->forward_to_kmsg || s->server->forward_to_kmsg) server_forward_kmsg(s->server, priority, s->identifier, p, &s->ucred); if (s->forward_to_console || s->server->forward_to_console) server_forward_console(s->server, priority, s->identifier, p, &s->ucred); if (s->server->forward_to_wall) server_forward_wall(s->server, priority, s->identifier, p, &s->ucred); IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=stdout"); syslog_priority[strlen("PRIORITY=")] = '0' + LOG_PRI(priority); IOVEC_SET_STRING(iovec[n++], syslog_priority); if (priority & LOG_FACMASK) { xsprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)); IOVEC_SET_STRING(iovec[n++], syslog_facility); } if (s->identifier) { syslog_identifier = strappend("SYSLOG_IDENTIFIER=", s->identifier); if (syslog_identifier) IOVEC_SET_STRING(iovec[n++], syslog_identifier); } message = strappend("MESSAGE=", p); if (message) IOVEC_SET_STRING(iovec[n++], message); label_len = s->label ? strlen(s->label) : 0; server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, s->label, label_len, s->unit_id, priority, 0); return 0; } static int stdout_stream_line(StdoutStream *s, char *p) { int r; char *orig; assert(s); assert(p); orig = p; p = strstrip(p); switch (s->state) { case STDOUT_STREAM_IDENTIFIER: if (isempty(p)) s->identifier = NULL; else { s->identifier = strdup(p); if (!s->identifier) return log_oom(); } s->state = STDOUT_STREAM_UNIT_ID; return 0; case STDOUT_STREAM_UNIT_ID: if (s->ucred.uid == 0) { if (isempty(p)) s->unit_id = NULL; else { s->unit_id = strdup(p); if (!s->unit_id) return log_oom(); } } s->state = STDOUT_STREAM_PRIORITY; return 0; case STDOUT_STREAM_PRIORITY: r = safe_atoi(p, &s->priority); if (r < 0 || s->priority < 0 || s->priority > 999) { log_warning("Failed to parse log priority line."); return -EINVAL; } s->state = STDOUT_STREAM_LEVEL_PREFIX; return 0; case STDOUT_STREAM_LEVEL_PREFIX: r = parse_boolean(p); if (r < 0) { log_warning("Failed to parse level prefix line."); return -EINVAL; } s->level_prefix = !!r; s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG; return 0; case STDOUT_STREAM_FORWARD_TO_SYSLOG: r = parse_boolean(p); if (r < 0) { log_warning("Failed to parse forward to syslog line."); return -EINVAL; } s->forward_to_syslog = !!r; s->state = STDOUT_STREAM_FORWARD_TO_KMSG; return 0; case STDOUT_STREAM_FORWARD_TO_KMSG: r = parse_boolean(p); if (r < 0) { log_warning("Failed to parse copy to kmsg line."); return -EINVAL; } s->forward_to_kmsg = !!r; s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE; return 0; case STDOUT_STREAM_FORWARD_TO_CONSOLE: r = parse_boolean(p); if (r < 0) { log_warning("Failed to parse copy to console line."); return -EINVAL; } s->forward_to_console = !!r; s->state = STDOUT_STREAM_RUNNING; /* Try to save the stream, so that journald can be restarted and we can recover */ (void) stdout_stream_save(s); return 0; case STDOUT_STREAM_RUNNING: return stdout_stream_log(s, orig); } assert_not_reached("Unknown stream state"); } static int stdout_stream_scan(StdoutStream *s, bool force_flush) { char *p; size_t remaining; int r; assert(s); p = s->buffer; remaining = s->length; for (;;) { char *end; size_t skip; end = memchr(p, '\n', remaining); if (end) skip = end - p + 1; else if (remaining >= sizeof(s->buffer) - 1) { end = p + sizeof(s->buffer) - 1; skip = remaining; } else break; *end = 0; r = stdout_stream_line(s, p); if (r < 0) return r; remaining -= skip; p += skip; } if (force_flush && remaining > 0) { p[remaining] = 0; r = stdout_stream_line(s, p); if (r < 0) return r; p += remaining; remaining = 0; } if (p > s->buffer) { memmove(s->buffer, p, remaining); s->length = remaining; } return 0; } static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) { StdoutStream *s = userdata; ssize_t l; int r; assert(s); if ((revents|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) { log_error("Got invalid event from epoll for stdout stream: %"PRIx32, revents); goto terminate; } l = read(s->fd, s->buffer+s->length, sizeof(s->buffer)-1-s->length); if (l < 0) { if (errno == EAGAIN) return 0; log_warning_errno(errno, "Failed to read from stream: %m"); goto terminate; } if (l == 0) { stdout_stream_scan(s, true); goto terminate; } s->length += l; r = stdout_stream_scan(s, false); if (r < 0) goto terminate; return 1; terminate: stdout_stream_destroy(s); return 0; } static int stdout_stream_install(Server *s, int fd, StdoutStream **ret) { _cleanup_(stdout_stream_freep) StdoutStream *stream = NULL; int r; assert(s); assert(fd >= 0); stream = new0(StdoutStream, 1); if (!stream) return log_oom(); stream->fd = -1; stream->priority = LOG_INFO; r = getpeercred(fd, &stream->ucred); if (r < 0) return log_error_errno(r, "Failed to determine peer credentials: %m"); if (mac_selinux_have()) { r = getpeersec(fd, &stream->label); if (r < 0 && r != -EOPNOTSUPP) (void) log_warning_errno(r, "Failed to determine peer security context: %m"); } (void) shutdown(fd, SHUT_WR); r = sd_event_add_io(s->event, &stream->event_source, fd, EPOLLIN, stdout_stream_process, stream); if (r < 0) return log_error_errno(r, "Failed to add stream to event loop: %m"); r = sd_event_source_set_priority(stream->event_source, SD_EVENT_PRIORITY_NORMAL+5); if (r < 0) return log_error_errno(r, "Failed to adjust stdout event source priority: %m"); stream->fd = fd; stream->server = s; LIST_PREPEND(stdout_stream, s->stdout_streams, stream); s->n_stdout_streams ++; if (ret) *ret = stream; stream = NULL; return 0; } static int stdout_stream_new(sd_event_source *es, int listen_fd, uint32_t revents, void *userdata) { _cleanup_close_ int fd = -1; Server *s = userdata; int r; assert(s); if (revents != EPOLLIN) { log_error("Got invalid event from epoll for stdout server fd: %"PRIx32, revents); return -EIO; } fd = accept4(s->stdout_fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); if (fd < 0) { if (errno == EAGAIN) return 0; return log_error_errno(errno, "Failed to accept stdout connection: %m"); } if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) { log_warning("Too many stdout streams, refusing connection."); return 0; } r = stdout_stream_install(s, fd, NULL); if (r < 0) return r; fd = -1; return 0; } static int stdout_stream_load(StdoutStream *stream, const char *fname) { _cleanup_free_ char *priority = NULL, *level_prefix = NULL, *forward_to_syslog = NULL, *forward_to_kmsg = NULL, *forward_to_console = NULL; int r; assert(stream); assert(fname); if (!stream->state_file) { stream->state_file = strappend("/run/systemd/journal/streams/", fname); if (!stream->state_file) return log_oom(); } r = parse_env_file(stream->state_file, NEWLINE, "PRIORITY", &priority, "LEVEL_PREFIX", &level_prefix, "FORWARD_TO_SYSLOG", &forward_to_syslog, "FORWARD_TO_KMSG", &forward_to_kmsg, "FORWARD_TO_CONSOLE", &forward_to_console, "IDENTIFIER", &stream->identifier, "UNIT", &stream->unit_id, NULL); if (r < 0) return log_error_errno(r, "Failed to read: %s", stream->state_file); if (priority) { int p; p = log_level_from_string(priority); if (p >= 0) stream->priority = p; } if (level_prefix) { r = parse_boolean(level_prefix); if (r >= 0) stream->level_prefix = r; } if (forward_to_syslog) { r = parse_boolean(forward_to_syslog); if (r >= 0) stream->forward_to_syslog = r; } if (forward_to_kmsg) { r = parse_boolean(forward_to_kmsg); if (r >= 0) stream->forward_to_kmsg = r; } if (forward_to_console) { r = parse_boolean(forward_to_console); if (r >= 0) stream->forward_to_console = r; } return 0; } static int stdout_stream_restore(Server *s, const char *fname, int fd) { StdoutStream *stream; int r; assert(s); assert(fname); assert(fd >= 0); if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) { log_warning("Too many stdout streams, refusing restoring of stream."); return -ENOBUFS; } r = stdout_stream_install(s, fd, &stream); if (r < 0) return r; stream->state = STDOUT_STREAM_RUNNING; stream->fdstore = true; /* Ignore all parsing errors */ (void) stdout_stream_load(stream, fname); return 0; } int server_restore_streams(Server *s, FDSet *fds) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r; d = opendir("/run/systemd/journal/streams"); if (!d) { if (errno == ENOENT) return 0; return log_warning_errno(errno, "Failed to enumerate /run/systemd/journal/streams: %m"); } FOREACH_DIRENT(de, d, goto fail) { unsigned long st_dev, st_ino; bool found = false; Iterator i; int fd; if (sscanf(de->d_name, "%lu:%lu", &st_dev, &st_ino) != 2) continue; FDSET_FOREACH(fd, fds, i) { struct stat st; if (fstat(fd, &st) < 0) return log_error_errno(errno, "Failed to stat %s: %m", de->d_name); if (S_ISSOCK(st.st_mode) && st.st_dev == st_dev && st.st_ino == st_ino) { found = true; break; } } if (!found) { /* No file descriptor? Then let's delete the state file */ log_debug("Cannot restore stream file %s", de->d_name); unlinkat(dirfd(d), de->d_name, 0); continue; } fdset_remove(fds, fd); r = stdout_stream_restore(s, de->d_name, fd); if (r < 0) safe_close(fd); } return 0; fail: return log_error_errno(errno, "Failed to read streams directory: %m"); } int server_open_stdout_socket(Server *s) { int r; assert(s); if (s->stdout_fd < 0) { union sockaddr_union sa = { .un.sun_family = AF_UNIX, .un.sun_path = "/run/systemd/journal/stdout", }; s->stdout_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (s->stdout_fd < 0) return log_error_errno(errno, "socket() failed: %m"); unlink(sa.un.sun_path); r = bind(s->stdout_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)); if (r < 0) return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); (void) chmod(sa.un.sun_path, 0666); if (listen(s->stdout_fd, SOMAXCONN) < 0) return log_error_errno(errno, "listen(%s) failed: %m", sa.un.sun_path); } else fd_nonblock(s->stdout_fd, 1); r = sd_event_add_io(s->event, &s->stdout_event_source, s->stdout_fd, EPOLLIN, stdout_stream_new, s); if (r < 0) return log_error_errno(r, "Failed to add stdout server fd to event source: %m"); r = sd_event_source_set_priority(s->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+5); if (r < 0) return log_error_errno(r, "Failed to adjust priority of stdout server event source: %m"); return 0; } void stdout_stream_send_notify(StdoutStream *s) { struct iovec iovec = { .iov_base = (char*) "FDSTORE=1", .iov_len = strlen("FDSTORE=1"), }; struct msghdr msghdr = { .msg_iov = &iovec, .msg_iovlen = 1, }; struct cmsghdr *cmsg; ssize_t l; assert(s); assert(!s->fdstore); assert(s->in_notify_queue); assert(s->server); assert(s->server->notify_fd >= 0); /* Store the connection fd in PID 1, so that we get it passed * in again on next start */ msghdr.msg_controllen = CMSG_SPACE(sizeof(int)); msghdr.msg_control = alloca0(msghdr.msg_controllen); cmsg = CMSG_FIRSTHDR(&msghdr); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int)); memcpy(CMSG_DATA(cmsg), &s->fd, sizeof(int)); l = sendmsg(s->server->notify_fd, &msghdr, MSG_DONTWAIT|MSG_NOSIGNAL); if (l < 0) { if (errno == EAGAIN) return; log_error_errno(errno, "Failed to send stream file descriptor to service manager: %m"); } else { log_debug("Successfully sent stream file descriptor to service manager."); s->fdstore = 1; } LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s); s->in_notify_queue = false; } systemd-229/src/journal/journald-stream.h000066400000000000000000000017621265713322000206100ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct StdoutStream StdoutStream; #include "fdset.h" #include "journald-server.h" int server_open_stdout_socket(Server *s); int server_restore_streams(Server *s, FDSet *fds); void stdout_stream_free(StdoutStream *s); void stdout_stream_send_notify(StdoutStream *s); systemd-229/src/journal/journald-syslog.c000066400000000000000000000336031265713322000206270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-messages.h" #include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "io-util.h" #include "journald-console.h" #include "journald-kmsg.h" #include "journald-server.h" #include "journald-syslog.h" #include "journald-wall.h" #include "process-util.h" #include "selinux-util.h" #include "socket-util.h" #include "stdio-util.h" #include "string-util.h" #include "syslog-util.h" /* Warn once every 30s if we missed syslog message */ #define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC) static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned n_iovec, const struct ucred *ucred, const struct timeval *tv) { static const union sockaddr_union sa = { .un.sun_family = AF_UNIX, .un.sun_path = "/run/systemd/journal/syslog", }; struct msghdr msghdr = { .msg_iov = (struct iovec *) iovec, .msg_iovlen = n_iovec, .msg_name = (struct sockaddr*) &sa.sa, .msg_namelen = offsetof(union sockaddr_union, un.sun_path) + strlen("/run/systemd/journal/syslog"), }; struct cmsghdr *cmsg; union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; } control; assert(s); assert(iovec); assert(n_iovec > 0); if (ucred) { zero(control); msghdr.msg_control = &control; msghdr.msg_controllen = sizeof(control); cmsg = CMSG_FIRSTHDR(&msghdr); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_CREDENTIALS; cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); memcpy(CMSG_DATA(cmsg), ucred, sizeof(struct ucred)); msghdr.msg_controllen = cmsg->cmsg_len; } /* Forward the syslog message we received via /dev/log to * /run/systemd/syslog. Unfortunately we currently can't set * the SO_TIMESTAMP auxiliary data, and hence we don't. */ if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0) return; /* The socket is full? I guess the syslog implementation is * too slow, and we shouldn't wait for that... */ if (errno == EAGAIN) { s->n_forward_syslog_missed++; return; } if (ucred && (errno == ESRCH || errno == EPERM)) { struct ucred u; /* Hmm, presumably the sender process vanished * by now, or we don't have CAP_SYS_AMDIN, so * let's fix it as good as we can, and retry */ u = *ucred; u.pid = getpid(); memcpy(CMSG_DATA(cmsg), &u, sizeof(struct ucred)); if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0) return; if (errno == EAGAIN) { s->n_forward_syslog_missed++; return; } } if (errno != ENOENT) log_debug_errno(errno, "Failed to forward syslog message: %m"); } static void forward_syslog_raw(Server *s, int priority, const char *buffer, const struct ucred *ucred, const struct timeval *tv) { struct iovec iovec; assert(s); assert(buffer); if (LOG_PRI(priority) > s->max_level_syslog) return; IOVEC_SET_STRING(iovec, buffer); forward_syslog_iovec(s, &iovec, 1, ucred, tv); } void server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred, const struct timeval *tv) { struct iovec iovec[5]; char header_priority[DECIMAL_STR_MAX(priority) + 3], header_time[64], header_pid[sizeof("[]: ")-1 + DECIMAL_STR_MAX(pid_t) + 1]; int n = 0; time_t t; struct tm *tm; char *ident_buf = NULL; assert(s); assert(priority >= 0); assert(priority <= 999); assert(message); if (LOG_PRI(priority) > s->max_level_syslog) return; /* First: priority field */ xsprintf(header_priority, "<%i>", priority); IOVEC_SET_STRING(iovec[n++], header_priority); /* Second: timestamp */ t = tv ? tv->tv_sec : ((time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC)); tm = localtime(&t); if (!tm) return; if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0) return; IOVEC_SET_STRING(iovec[n++], header_time); /* Third: identifier and PID */ if (ucred) { if (!identifier) { get_process_comm(ucred->pid, &ident_buf); identifier = ident_buf; } xsprintf(header_pid, "["PID_FMT"]: ", ucred->pid); if (identifier) IOVEC_SET_STRING(iovec[n++], identifier); IOVEC_SET_STRING(iovec[n++], header_pid); } else if (identifier) { IOVEC_SET_STRING(iovec[n++], identifier); IOVEC_SET_STRING(iovec[n++], ": "); } /* Fourth: message */ IOVEC_SET_STRING(iovec[n++], message); forward_syslog_iovec(s, iovec, n, ucred, tv); free(ident_buf); } int syslog_fixup_facility(int priority) { if ((priority & LOG_FACMASK) == 0) return (priority & LOG_PRIMASK) | LOG_USER; return priority; } size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid) { const char *p; char *t; size_t l, e; assert(buf); assert(identifier); assert(pid); p = *buf; p += strspn(p, WHITESPACE); l = strcspn(p, WHITESPACE); if (l <= 0 || p[l-1] != ':') return 0; e = l; l--; if (p[l-1] == ']') { size_t k = l-1; for (;;) { if (p[k] == '[') { t = strndup(p+k+1, l-k-2); if (t) *pid = t; l = k; break; } if (k == 0) break; k--; } } t = strndup(p, l); if (t) *identifier = t; if (strchr(WHITESPACE, p[e])) e++; *buf = p + e; return e; } static void syslog_skip_date(char **buf) { enum { LETTER, SPACE, NUMBER, SPACE_OR_NUMBER, COLON } sequence[] = { LETTER, LETTER, LETTER, SPACE, SPACE_OR_NUMBER, NUMBER, SPACE, SPACE_OR_NUMBER, NUMBER, COLON, SPACE_OR_NUMBER, NUMBER, COLON, SPACE_OR_NUMBER, NUMBER, SPACE }; char *p; unsigned i; assert(buf); assert(*buf); p = *buf; for (i = 0; i < ELEMENTSOF(sequence); i++, p++) { if (!*p) return; switch (sequence[i]) { case SPACE: if (*p != ' ') return; break; case SPACE_OR_NUMBER: if (*p == ' ') break; /* fall through */ case NUMBER: if (*p < '0' || *p > '9') return; break; case LETTER: if (!(*p >= 'A' && *p <= 'Z') && !(*p >= 'a' && *p <= 'z')) return; break; case COLON: if (*p != ':') return; break; } } *buf = p; } void server_process_syslog_message( Server *s, const char *buf, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len) { char syslog_priority[sizeof("PRIORITY=") + DECIMAL_STR_MAX(int)], syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)]; const char *message = NULL, *syslog_identifier = NULL, *syslog_pid = NULL; struct iovec iovec[N_IOVEC_META_FIELDS + 6]; unsigned n = 0; int priority = LOG_USER | LOG_INFO; _cleanup_free_ char *identifier = NULL, *pid = NULL; const char *orig; assert(s); assert(buf); orig = buf; syslog_parse_priority(&buf, &priority, true); if (s->forward_to_syslog) forward_syslog_raw(s, priority, orig, ucred, tv); syslog_skip_date((char**) &buf); syslog_parse_identifier(&buf, &identifier, &pid); if (s->forward_to_kmsg) server_forward_kmsg(s, priority, identifier, buf, ucred); if (s->forward_to_console) server_forward_console(s, priority, identifier, buf, ucred); if (s->forward_to_wall) server_forward_wall(s, priority, identifier, buf, ucred); IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=syslog"); xsprintf(syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK); IOVEC_SET_STRING(iovec[n++], syslog_priority); if (priority & LOG_FACMASK) { xsprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)); IOVEC_SET_STRING(iovec[n++], syslog_facility); } if (identifier) { syslog_identifier = strjoina("SYSLOG_IDENTIFIER=", identifier); if (syslog_identifier) IOVEC_SET_STRING(iovec[n++], syslog_identifier); } if (pid) { syslog_pid = strjoina("SYSLOG_PID=", pid); if (syslog_pid) IOVEC_SET_STRING(iovec[n++], syslog_pid); } message = strjoina("MESSAGE=", buf); if (message) IOVEC_SET_STRING(iovec[n++], message); server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), ucred, tv, label, label_len, NULL, priority, 0); } int server_open_syslog_socket(Server *s) { static const int one = 1; int r; assert(s); if (s->syslog_fd < 0) { static const union sockaddr_union sa = { .un.sun_family = AF_UNIX, .un.sun_path = "/run/systemd/journal/dev-log", }; s->syslog_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (s->syslog_fd < 0) return log_error_errno(errno, "socket() failed: %m"); unlink(sa.un.sun_path); r = bind(s->syslog_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)); if (r < 0) return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); (void) chmod(sa.un.sun_path, 0666); } else fd_nonblock(s->syslog_fd, 1); r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); if (r < 0) return log_error_errno(errno, "SO_PASSCRED failed: %m"); #ifdef HAVE_SELINUX if (mac_selinux_have()) { r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one)); if (r < 0) log_warning_errno(errno, "SO_PASSSEC failed: %m"); } #endif r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one)); if (r < 0) return log_error_errno(errno, "SO_TIMESTAMP failed: %m"); r = sd_event_add_io(s->event, &s->syslog_event_source, s->syslog_fd, EPOLLIN, server_process_datagram, s); if (r < 0) return log_error_errno(r, "Failed to add syslog server fd to event loop: %m"); r = sd_event_source_set_priority(s->syslog_event_source, SD_EVENT_PRIORITY_NORMAL+5); if (r < 0) return log_error_errno(r, "Failed to adjust syslog event source priority: %m"); return 0; } void server_maybe_warn_forward_syslog_missed(Server *s) { usec_t n; assert(s); if (s->n_forward_syslog_missed <= 0) return; n = now(CLOCK_MONOTONIC); if (s->last_warn_forward_syslog_missed + WARN_FORWARD_SYSLOG_MISSED_USEC > n) return; server_driver_message(s, SD_MESSAGE_FORWARD_SYSLOG_MISSED, LOG_MESSAGE("Forwarding to syslog missed %u messages.", s->n_forward_syslog_missed), NULL); s->n_forward_syslog_missed = 0; s->last_warn_forward_syslog_missed = n; } systemd-229/src/journal/journald-syslog.h000066400000000000000000000024251265713322000206320ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "journald-server.h" int syslog_fixup_facility(int priority) _const_; size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid); void server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred, const struct timeval *tv); void server_process_syslog_message(Server *s, const char *buf, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len); int server_open_syslog_socket(Server *s); void server_maybe_warn_forward_syslog_missed(Server *s); systemd-229/src/journal/journald-wall.c000066400000000000000000000041621265713322000202440ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Sebastian Thorarensen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "formats-util.h" #include "journald-server.h" #include "journald-wall.h" #include "process-util.h" #include "string-util.h" #include "utmp-wtmp.h" void server_forward_wall( Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred) { _cleanup_free_ char *ident_buf = NULL, *l_buf = NULL; const char *l; int r; assert(s); assert(message); if (LOG_PRI(priority) > s->max_level_wall) return; if (ucred) { if (!identifier) { get_process_comm(ucred->pid, &ident_buf); identifier = ident_buf; } if (asprintf(&l_buf, "%s["PID_FMT"]: %s", strempty(identifier), ucred->pid, message) < 0) { log_oom(); return; } l = l_buf; } else if (identifier) { l = l_buf = strjoin(identifier, ": ", message, NULL); if (!l_buf) { log_oom(); return; } } else l = message; r = utmp_wall(l, "systemd-journald", NULL, NULL, NULL); if (r < 0) log_debug_errno(r, "Failed to send wall message: %m"); } systemd-229/src/journal/journald-wall.h000066400000000000000000000015711265713322000202520ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Sebastian Thorarensen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "journald-server.h" void server_forward_wall(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred); systemd-229/src/journal/journald.c000066400000000000000000000074471265713322000173200ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-daemon.h" #include "sd-messages.h" #include "formats-util.h" #include "journal-authenticate.h" #include "journald-kmsg.h" #include "journald-server.h" #include "journald-syslog.h" #include "sigbus.h" int main(int argc, char *argv[]) { Server server; int r; if (argc > 1) { log_error("This program does not take arguments."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_SAFE); log_set_facility(LOG_SYSLOG); log_parse_environment(); log_open(); umask(0022); sigbus_install(); r = server_init(&server); if (r < 0) goto finish; server_vacuum(&server, false, false); server_flush_to_var(&server); server_flush_dev_kmsg(&server); log_debug("systemd-journald running as pid "PID_FMT, getpid()); server_driver_message(&server, SD_MESSAGE_JOURNAL_START, LOG_MESSAGE("Journal started"), NULL); for (;;) { usec_t t = USEC_INFINITY, n; r = sd_event_get_state(server.event); if (r < 0) goto finish; if (r == SD_EVENT_FINISHED) break; n = now(CLOCK_REALTIME); if (server.max_retention_usec > 0 && server.oldest_file_usec > 0) { /* The retention time is reached, so let's vacuum! */ if (server.oldest_file_usec + server.max_retention_usec < n) { log_info("Retention time reached."); server_rotate(&server); server_vacuum(&server, false, false); continue; } /* Calculate when to rotate the next time */ t = server.oldest_file_usec + server.max_retention_usec - n; } #ifdef HAVE_GCRYPT if (server.system_journal) { usec_t u; if (journal_file_next_evolve_usec(server.system_journal, &u)) { if (n >= u) t = 0; else t = MIN(t, u - n); } } #endif r = sd_event_run(server.event, t); if (r < 0) { log_error_errno(r, "Failed to run event loop: %m"); goto finish; } server_maybe_append_tags(&server); server_maybe_warn_forward_syslog_missed(&server); } log_debug("systemd-journald stopped as pid "PID_FMT, getpid()); server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP, LOG_MESSAGE("Journal stopped"), NULL); finish: server_done(&server); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/journal/journald.conf000066400000000000000000000017621265713322000200150ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # Entries in this file show the compile time defaults. # You can change settings by editing this file. # Defaults can be restored by simply deleting this file. # # See journald.conf(5) for details. [Journal] #Storage=auto #Compress=yes #Seal=yes #SplitMode=uid #SyncIntervalSec=5m #RateLimitInterval=30s #RateLimitBurst=1000 #SystemMaxUse= #SystemKeepFree= #SystemMaxFileSize= #SystemMaxFiles=100 #RuntimeMaxUse= #RuntimeKeepFree= #RuntimeMaxFileSize= #RuntimeMaxFiles=100 #MaxRetentionSec= #MaxFileSec=1month #ForwardToSyslog=no #ForwardToKMsg=no #ForwardToConsole=no #ForwardToWall=yes #TTYPath=/dev/console #MaxLevelStore=debug #MaxLevelSyslog=debug #MaxLevelKMsg=notice #MaxLevelConsole=info #MaxLevelWall=emerg systemd-229/src/journal/lookup3.c000066400000000000000000001060661265713322000170730ustar00rootroot00000000000000/* Slightly modified by Lennart Poettering, to avoid name clashes, and * unexport a few functions. */ #include "lookup3.h" /* ------------------------------------------------------------------------------- lookup3.c, by Bob Jenkins, May 2006, Public Domain. These are functions for producing 32-bit hashes for hash table lookup. hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() are externally useful functions. Routines to test the hash are included if SELF_TEST is defined. You can use this free for any purpose. It's in the public domain. It has no warranty. You probably want to use hashlittle(). hashlittle() and hashbig() hash byte arrays. hashlittle() is faster than hashbig() on little-endian machines. Intel and AMD are little-endian machines. On second thought, you probably want hashlittle2(), which is identical to hashlittle() except it returns two 32-bit hashes for the price of one. You could implement hashbig2() if you wanted but I haven't bothered here. If you want to find a hash of, say, exactly 7 integers, do a = i1; b = i2; c = i3; mix(a,b,c); a += i4; b += i5; c += i6; mix(a,b,c); a += i7; final(a,b,c); then use c as the hash value. If you have a variable length array of 4-byte integers to hash, use hashword(). If you have a byte array (like a character string), use hashlittle(). If you have several byte arrays, or a mix of things, see the comments above hashlittle(). Why is this so big? I read 12 bytes at a time into 3 4-byte integers, then mix those integers. This is fast (you can do a lot more thorough mixing with 12*3 instructions on 3 integers than you can with 3 instructions on 1 byte), but shoehorning those bytes into integers efficiently is messy. ------------------------------------------------------------------------------- */ /* #define SELF_TEST 1 */ #include /* defines uint32_t etc */ #include /* defines printf for tests */ #include /* attempt to define endianness */ #include /* defines time_t for timings in the test */ #ifdef linux # include /* attempt to define endianness */ #endif /* * My best guess at if you are big-endian or little-endian. This may * need adjustment. */ #if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ __BYTE_ORDER == __LITTLE_ENDIAN) || \ (defined(i386) || defined(__i386__) || defined(__i486__) || \ defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) # define HASH_LITTLE_ENDIAN 1 # define HASH_BIG_ENDIAN 0 #elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ __BYTE_ORDER == __BIG_ENDIAN) || \ (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) # define HASH_LITTLE_ENDIAN 0 # define HASH_BIG_ENDIAN 1 #else # define HASH_LITTLE_ENDIAN 0 # define HASH_BIG_ENDIAN 0 #endif #define hashsize(n) ((uint32_t)1<<(n)) #define hashmask(n) (hashsize(n)-1) #define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) /* ------------------------------------------------------------------------------- mix -- mix 3 32-bit values reversibly. This is reversible, so any information in (a,b,c) before mix() is still in (a,b,c) after mix(). If four pairs of (a,b,c) inputs are run through mix(), or through mix() in reverse, there are at least 32 bits of the output that are sometimes the same for one pair and different for another pair. This was tested for: * pairs that differed by one bit, by two bits, in any combination of top bits of (a,b,c), or in any combination of bottom bits of (a,b,c). * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed the output delta to a Gray code (a^(a>>1)) so a string of 1's (as is commonly produced by subtraction) look like a single 1-bit difference. * the base values were pseudorandom, all zero but one bit set, or all zero plus a counter that starts at zero. Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that satisfy this are 4 6 8 16 19 4 9 15 3 18 27 15 14 9 3 7 17 3 Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing for "differ" defined as + with a one-bit base and a two-bit delta. I used http://burtleburtle.net/bob/hash/avalanche.html to choose the operations, constants, and arrangements of the variables. This does not achieve avalanche. There are input bits of (a,b,c) that fail to affect some output bits of (a,b,c), especially of a. The most thoroughly mixed value is c, but it doesn't really even achieve avalanche in c. This allows some parallelism. Read-after-writes are good at doubling the number of bits affected, so the goal of mixing pulls in the opposite direction as the goal of parallelism. I did what I could. Rotates seem to cost as much as shifts on every machine I could lay my hands on, and rotates are much kinder to the top and bottom bits, so I used rotates. ------------------------------------------------------------------------------- */ #define mix(a,b,c) \ { \ a -= c; a ^= rot(c, 4); c += b; \ b -= a; b ^= rot(a, 6); a += c; \ c -= b; c ^= rot(b, 8); b += a; \ a -= c; a ^= rot(c,16); c += b; \ b -= a; b ^= rot(a,19); a += c; \ c -= b; c ^= rot(b, 4); b += a; \ } /* ------------------------------------------------------------------------------- final -- final mixing of 3 32-bit values (a,b,c) into c Pairs of (a,b,c) values differing in only a few bits will usually produce values of c that look totally different. This was tested for * pairs that differed by one bit, by two bits, in any combination of top bits of (a,b,c), or in any combination of bottom bits of (a,b,c). * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed the output delta to a Gray code (a^(a>>1)) so a string of 1's (as is commonly produced by subtraction) look like a single 1-bit difference. * the base values were pseudorandom, all zero but one bit set, or all zero plus a counter that starts at zero. These constants passed: 14 11 25 16 4 14 24 12 14 25 16 4 14 24 and these came close: 4 8 15 26 3 22 24 10 8 15 26 3 22 24 11 8 15 26 3 22 24 ------------------------------------------------------------------------------- */ #define final(a,b,c) \ { \ c ^= b; c -= rot(b,14); \ a ^= c; a -= rot(c,11); \ b ^= a; b -= rot(a,25); \ c ^= b; c -= rot(b,16); \ a ^= c; a -= rot(c,4); \ b ^= a; b -= rot(a,14); \ c ^= b; c -= rot(b,24); \ } /* -------------------------------------------------------------------- This works on all machines. To be useful, it requires -- that the key be an array of uint32_t's, and -- that the length be the number of uint32_t's in the key The function hashword() is identical to hashlittle() on little-endian machines, and identical to hashbig() on big-endian machines, except that the length has to be measured in uint32_ts rather than in bytes. hashlittle() is more complicated than hashword() only because hashlittle() has to dance around fitting the key bytes into registers. -------------------------------------------------------------------- */ uint32_t jenkins_hashword( const uint32_t *k, /* the key, an array of uint32_t values */ size_t length, /* the length of the key, in uint32_ts */ uint32_t initval) /* the previous hash, or an arbitrary value */ { uint32_t a,b,c; /* Set up the internal state */ a = b = c = 0xdeadbeef + (((uint32_t)length)<<2) + initval; /*------------------------------------------------- handle most of the key */ while (length > 3) { a += k[0]; b += k[1]; c += k[2]; mix(a,b,c); length -= 3; k += 3; } /*------------------------------------------- handle the last 3 uint32_t's */ switch(length) /* all the case statements fall through */ { case 3 : c+=k[2]; case 2 : b+=k[1]; case 1 : a+=k[0]; final(a,b,c); case 0: /* case 0: nothing left to add */ break; } /*------------------------------------------------------ report the result */ return c; } /* -------------------------------------------------------------------- hashword2() -- same as hashword(), but take two seeds and return two 32-bit values. pc and pb must both be nonnull, and *pc and *pb must both be initialized with seeds. If you pass in (*pb)==0, the output (*pc) will be the same as the return value from hashword(). -------------------------------------------------------------------- */ void jenkins_hashword2 ( const uint32_t *k, /* the key, an array of uint32_t values */ size_t length, /* the length of the key, in uint32_ts */ uint32_t *pc, /* IN: seed OUT: primary hash value */ uint32_t *pb) /* IN: more seed OUT: secondary hash value */ { uint32_t a,b,c; /* Set up the internal state */ a = b = c = 0xdeadbeef + ((uint32_t)(length<<2)) + *pc; c += *pb; /*------------------------------------------------- handle most of the key */ while (length > 3) { a += k[0]; b += k[1]; c += k[2]; mix(a,b,c); length -= 3; k += 3; } /*------------------------------------------- handle the last 3 uint32_t's */ switch(length) /* all the case statements fall through */ { case 3 : c+=k[2]; case 2 : b+=k[1]; case 1 : a+=k[0]; final(a,b,c); case 0: /* case 0: nothing left to add */ break; } /*------------------------------------------------------ report the result */ *pc=c; *pb=b; } /* ------------------------------------------------------------------------------- hashlittle() -- hash a variable-length key into a 32-bit value k : the key (the unaligned variable-length array of bytes) length : the length of the key, counting by bytes initval : can be any 4-byte value Returns a 32-bit value. Every bit of the key affects every bit of the return value. Two keys differing by one or two bits will have totally different hash values. The best hash table sizes are powers of 2. There is no need to do mod a prime (mod is sooo slow!). If you need less than 32 bits, use a bitmask. For example, if you need only 10 bits, do h = (h & hashmask(10)); In which case, the hash table should have hashsize(10) elements. If you are hashing n strings (uint8_t **)k, do it like this: for (i=0, h=0; i 12) { a += k[0]; b += k[1]; c += k[2]; mix(a,b,c); length -= 12; k += 3; } /*----------------------------- handle the last (probably partial) block */ /* * "k[2]&0xffffff" actually reads beyond the end of the string, but * then masks off the part it's not allowed to read. Because the * string is aligned, the masked-off tail is in the same word as the * rest of the string. Every machine with memory protection I've seen * does it on word boundaries, so is OK with this. But VALGRIND will * still catch it and complain. The masking trick does make the hash * noticeably faster for short strings (like English words). */ #ifndef VALGRIND switch(length) { case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; case 8 : b+=k[1]; a+=k[0]; break; case 7 : b+=k[1]&0xffffff; a+=k[0]; break; case 6 : b+=k[1]&0xffff; a+=k[0]; break; case 5 : b+=k[1]&0xff; a+=k[0]; break; case 4 : a+=k[0]; break; case 3 : a+=k[0]&0xffffff; break; case 2 : a+=k[0]&0xffff; break; case 1 : a+=k[0]&0xff; break; case 0 : return c; /* zero length strings require no mixing */ } #else /* make valgrind happy */ { const uint8_t *k8 = (const uint8_t *) k; switch(length) { case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ case 9 : c+=k8[8]; /* fall through */ case 8 : b+=k[1]; a+=k[0]; break; case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ case 5 : b+=k8[4]; /* fall through */ case 4 : a+=k[0]; break; case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ case 1 : a+=k8[0]; break; case 0 : return c; } } #endif /* !valgrind */ } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ const uint8_t *k8; /*--------------- all but last block: aligned reads and different mixing */ while (length > 12) { a += k[0] + (((uint32_t)k[1])<<16); b += k[2] + (((uint32_t)k[3])<<16); c += k[4] + (((uint32_t)k[5])<<16); mix(a,b,c); length -= 12; k += 6; } /*----------------------------- handle the last (probably partial) block */ k8 = (const uint8_t *)k; switch(length) { case 12: c+=k[4]+(((uint32_t)k[5])<<16); b+=k[2]+(((uint32_t)k[3])<<16); a+=k[0]+(((uint32_t)k[1])<<16); break; case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ case 10: c+=k[4]; b+=k[2]+(((uint32_t)k[3])<<16); a+=k[0]+(((uint32_t)k[1])<<16); break; case 9 : c+=k8[8]; /* fall through */ case 8 : b+=k[2]+(((uint32_t)k[3])<<16); a+=k[0]+(((uint32_t)k[1])<<16); break; case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ case 6 : b+=k[2]; a+=k[0]+(((uint32_t)k[1])<<16); break; case 5 : b+=k8[4]; /* fall through */ case 4 : a+=k[0]+(((uint32_t)k[1])<<16); break; case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ case 2 : a+=k[0]; break; case 1 : a+=k8[0]; break; case 0 : return c; /* zero length requires no mixing */ } } else { /* need to read the key one byte at a time */ const uint8_t *k = (const uint8_t *)key; /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ while (length > 12) { a += k[0]; a += ((uint32_t)k[1])<<8; a += ((uint32_t)k[2])<<16; a += ((uint32_t)k[3])<<24; b += k[4]; b += ((uint32_t)k[5])<<8; b += ((uint32_t)k[6])<<16; b += ((uint32_t)k[7])<<24; c += k[8]; c += ((uint32_t)k[9])<<8; c += ((uint32_t)k[10])<<16; c += ((uint32_t)k[11])<<24; mix(a,b,c); length -= 12; k += 12; } /*-------------------------------- last block: affect all 32 bits of (c) */ switch(length) /* all the case statements fall through */ { case 12: c+=((uint32_t)k[11])<<24; case 11: c+=((uint32_t)k[10])<<16; case 10: c+=((uint32_t)k[9])<<8; case 9 : c+=k[8]; case 8 : b+=((uint32_t)k[7])<<24; case 7 : b+=((uint32_t)k[6])<<16; case 6 : b+=((uint32_t)k[5])<<8; case 5 : b+=k[4]; case 4 : a+=((uint32_t)k[3])<<24; case 3 : a+=((uint32_t)k[2])<<16; case 2 : a+=((uint32_t)k[1])<<8; case 1 : a+=k[0]; break; case 0 : return c; } } final(a,b,c); return c; } /* * hashlittle2: return 2 32-bit hash values * * This is identical to hashlittle(), except it returns two 32-bit hash * values instead of just one. This is good enough for hash table * lookup with 2^^64 buckets, or if you want a second hash if you're not * happy with the first, or if you want a probably-unique 64-bit ID for * the key. *pc is better mixed than *pb, so use *pc first. If you want * a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)". */ void jenkins_hashlittle2( const void *key, /* the key to hash */ size_t length, /* length of the key */ uint32_t *pc, /* IN: primary initval, OUT: primary hash */ uint32_t *pb) /* IN: secondary initval, OUT: secondary hash */ { uint32_t a,b,c; /* internal state */ union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ /* Set up the internal state */ a = b = c = 0xdeadbeef + ((uint32_t)length) + *pc; c += *pb; u.ptr = key; if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ while (length > 12) { a += k[0]; b += k[1]; c += k[2]; mix(a,b,c); length -= 12; k += 3; } /*----------------------------- handle the last (probably partial) block */ /* * "k[2]&0xffffff" actually reads beyond the end of the string, but * then masks off the part it's not allowed to read. Because the * string is aligned, the masked-off tail is in the same word as the * rest of the string. Every machine with memory protection I've seen * does it on word boundaries, so is OK with this. But VALGRIND will * still catch it and complain. The masking trick does make the hash * noticeably faster for short strings (like English words). */ #ifndef VALGRIND switch(length) { case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; case 8 : b+=k[1]; a+=k[0]; break; case 7 : b+=k[1]&0xffffff; a+=k[0]; break; case 6 : b+=k[1]&0xffff; a+=k[0]; break; case 5 : b+=k[1]&0xff; a+=k[0]; break; case 4 : a+=k[0]; break; case 3 : a+=k[0]&0xffffff; break; case 2 : a+=k[0]&0xffff; break; case 1 : a+=k[0]&0xff; break; case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ } #else /* make valgrind happy */ { const uint8_t *k8 = (const uint8_t *)k; switch(length) { case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ case 9 : c+=k8[8]; /* fall through */ case 8 : b+=k[1]; a+=k[0]; break; case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ case 5 : b+=k8[4]; /* fall through */ case 4 : a+=k[0]; break; case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ case 1 : a+=k8[0]; break; case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ } } #endif /* !valgrind */ } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ const uint8_t *k8; /*--------------- all but last block: aligned reads and different mixing */ while (length > 12) { a += k[0] + (((uint32_t)k[1])<<16); b += k[2] + (((uint32_t)k[3])<<16); c += k[4] + (((uint32_t)k[5])<<16); mix(a,b,c); length -= 12; k += 6; } /*----------------------------- handle the last (probably partial) block */ k8 = (const uint8_t *)k; switch(length) { case 12: c+=k[4]+(((uint32_t)k[5])<<16); b+=k[2]+(((uint32_t)k[3])<<16); a+=k[0]+(((uint32_t)k[1])<<16); break; case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ case 10: c+=k[4]; b+=k[2]+(((uint32_t)k[3])<<16); a+=k[0]+(((uint32_t)k[1])<<16); break; case 9 : c+=k8[8]; /* fall through */ case 8 : b+=k[2]+(((uint32_t)k[3])<<16); a+=k[0]+(((uint32_t)k[1])<<16); break; case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ case 6 : b+=k[2]; a+=k[0]+(((uint32_t)k[1])<<16); break; case 5 : b+=k8[4]; /* fall through */ case 4 : a+=k[0]+(((uint32_t)k[1])<<16); break; case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ case 2 : a+=k[0]; break; case 1 : a+=k8[0]; break; case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ } } else { /* need to read the key one byte at a time */ const uint8_t *k = (const uint8_t *)key; /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ while (length > 12) { a += k[0]; a += ((uint32_t)k[1])<<8; a += ((uint32_t)k[2])<<16; a += ((uint32_t)k[3])<<24; b += k[4]; b += ((uint32_t)k[5])<<8; b += ((uint32_t)k[6])<<16; b += ((uint32_t)k[7])<<24; c += k[8]; c += ((uint32_t)k[9])<<8; c += ((uint32_t)k[10])<<16; c += ((uint32_t)k[11])<<24; mix(a,b,c); length -= 12; k += 12; } /*-------------------------------- last block: affect all 32 bits of (c) */ switch(length) /* all the case statements fall through */ { case 12: c+=((uint32_t)k[11])<<24; case 11: c+=((uint32_t)k[10])<<16; case 10: c+=((uint32_t)k[9])<<8; case 9 : c+=k[8]; case 8 : b+=((uint32_t)k[7])<<24; case 7 : b+=((uint32_t)k[6])<<16; case 6 : b+=((uint32_t)k[5])<<8; case 5 : b+=k[4]; case 4 : a+=((uint32_t)k[3])<<24; case 3 : a+=((uint32_t)k[2])<<16; case 2 : a+=((uint32_t)k[1])<<8; case 1 : a+=k[0]; break; case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ } } final(a,b,c); *pc=c; *pb=b; } /* * hashbig(): * This is the same as hashword() on big-endian machines. It is different * from hashlittle() on all machines. hashbig() takes advantage of * big-endian byte ordering. */ uint32_t jenkins_hashbig( const void *key, size_t length, uint32_t initval) { uint32_t a,b,c; union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */ /* Set up the internal state */ a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; u.ptr = key; if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) { const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ while (length > 12) { a += k[0]; b += k[1]; c += k[2]; mix(a,b,c); length -= 12; k += 3; } /*----------------------------- handle the last (probably partial) block */ /* * "k[2]<<8" actually reads beyond the end of the string, but * then shifts out the part it's not allowed to read. Because the * string is aligned, the illegal read is in the same word as the * rest of the string. Every machine with memory protection I've seen * does it on word boundaries, so is OK with this. But VALGRIND will * still catch it and complain. The masking trick does make the hash * noticeably faster for short strings (like English words). */ #ifndef VALGRIND switch(length) { case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break; case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break; case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break; case 8 : b+=k[1]; a+=k[0]; break; case 7 : b+=k[1]&0xffffff00; a+=k[0]; break; case 6 : b+=k[1]&0xffff0000; a+=k[0]; break; case 5 : b+=k[1]&0xff000000; a+=k[0]; break; case 4 : a+=k[0]; break; case 3 : a+=k[0]&0xffffff00; break; case 2 : a+=k[0]&0xffff0000; break; case 1 : a+=k[0]&0xff000000; break; case 0 : return c; /* zero length strings require no mixing */ } #else /* make valgrind happy */ { const uint8_t *k8 = (const uint8_t *)k; switch(length) /* all the case statements fall through */ { case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; case 11: c+=((uint32_t)k8[10])<<8; /* fall through */ case 10: c+=((uint32_t)k8[9])<<16; /* fall through */ case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */ case 8 : b+=k[1]; a+=k[0]; break; case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */ case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */ case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */ case 4 : a+=k[0]; break; case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */ case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */ case 1 : a+=((uint32_t)k8[0])<<24; break; case 0 : return c; } } #endif /* !VALGRIND */ } else { /* need to read the key one byte at a time */ const uint8_t *k = (const uint8_t *)key; /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ while (length > 12) { a += ((uint32_t)k[0])<<24; a += ((uint32_t)k[1])<<16; a += ((uint32_t)k[2])<<8; a += ((uint32_t)k[3]); b += ((uint32_t)k[4])<<24; b += ((uint32_t)k[5])<<16; b += ((uint32_t)k[6])<<8; b += ((uint32_t)k[7]); c += ((uint32_t)k[8])<<24; c += ((uint32_t)k[9])<<16; c += ((uint32_t)k[10])<<8; c += ((uint32_t)k[11]); mix(a,b,c); length -= 12; k += 12; } /*-------------------------------- last block: affect all 32 bits of (c) */ switch(length) /* all the case statements fall through */ { case 12: c+=k[11]; case 11: c+=((uint32_t)k[10])<<8; case 10: c+=((uint32_t)k[9])<<16; case 9 : c+=((uint32_t)k[8])<<24; case 8 : b+=k[7]; case 7 : b+=((uint32_t)k[6])<<8; case 6 : b+=((uint32_t)k[5])<<16; case 5 : b+=((uint32_t)k[4])<<24; case 4 : a+=k[3]; case 3 : a+=((uint32_t)k[2])<<8; case 2 : a+=((uint32_t)k[1])<<16; case 1 : a+=((uint32_t)k[0])<<24; break; case 0 : return c; } } final(a,b,c); return c; } #ifdef SELF_TEST /* used for timings */ void driver1() { uint8_t buf[256]; uint32_t i; uint32_t h=0; time_t a,z; time(&a); for (i=0; i<256; ++i) buf[i] = 'x'; for (i=0; i<1; ++i) { h = hashlittle(&buf[0],1,h); } time(&z); if (z-a > 0) printf("time %d %.8x\n", z-a, h); } /* check that every input bit changes every output bit half the time */ #define HASHSTATE 1 #define HASHLEN 1 #define MAXPAIR 60 #define MAXLEN 70 void driver2() { uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1]; uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z; uint32_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE]; uint32_t x[HASHSTATE],y[HASHSTATE]; uint32_t hlen; printf("No more than %d trials should ever be needed \n",MAXPAIR/2); for (hlen=0; hlen < MAXLEN; ++hlen) { z=0; for (i=0; i>(8-j)); c[0] = hashlittle(a, hlen, m); b[i] ^= ((k+1)<>(8-j)); d[0] = hashlittle(b, hlen, m); /* check every bit is 1, 0, set, and not set at least once */ for (l=0; lz) z=k; if (k==MAXPAIR) { printf("Some bit didn't change: "); printf("%.8x %.8x %.8x %.8x %.8x %.8x ", e[0],f[0],g[0],h[0],x[0],y[0]); printf("i %d j %d m %d len %d\n", i, j, m, hlen); } if (z==MAXPAIR) goto done; } } } done: if (z < MAXPAIR) { printf("Mix success %2d bytes %2d initvals ",i,m); printf("required %d trials\n", z/2); } } printf("\n"); } /* Check for reading beyond the end of the buffer and alignment problems */ void driver3() { uint8_t buf[MAXLEN+20], *b; uint32_t len; uint8_t q[] = "This is the time for all good men to come to the aid of their country..."; uint32_t h; uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country..."; uint32_t i; uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country..."; uint32_t j; uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country..."; uint32_t ref,x,y; uint8_t *p; printf("Endianness. These lines should all be the same (for values filled in):\n"); printf("%.8x %.8x %.8x\n", hashword((const uint32_t *)q, (sizeof(q)-1)/4, 13), hashword((const uint32_t *)q, (sizeof(q)-5)/4, 13), hashword((const uint32_t *)q, (sizeof(q)-9)/4, 13)); p = q; printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); p = &qq[1]; printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); p = &qqq[2]; printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); p = &qqqq[3]; printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); printf("\n"); /* check that hashlittle2 and hashlittle produce the same results */ i=47; j=0; hashlittle2(q, sizeof(q), &i, &j); if (hashlittle(q, sizeof(q), 47) != i) printf("hashlittle2 and hashlittle mismatch\n"); /* check that hashword2 and hashword produce the same results */ len = 0xdeadbeef; i=47, j=0; hashword2(&len, 1, &i, &j); if (hashword(&len, 1, 47) != i) printf("hashword2 and hashword mismatch %x %x\n", i, hashword(&len, 1, 47)); /* check hashlittle doesn't read before or after the ends of the string */ for (h=0, b=buf+1; h<8; ++h, ++b) { for (i=0; i #include #include "macro.h" uint32_t jenkins_hashword(const uint32_t *k, size_t length, uint32_t initval) _pure_; void jenkins_hashword2(const uint32_t *k, size_t length, uint32_t *pc, uint32_t *pb); uint32_t jenkins_hashlittle(const void *key, size_t length, uint32_t initval) _pure_; void jenkins_hashlittle2(const void *key, size_t length, uint32_t *pc, uint32_t *pb); uint32_t jenkins_hashbig(const void *key, size_t length, uint32_t initval) _pure_; static inline uint64_t hash64(const void *data, size_t length) { uint32_t a = 0, b = 0; jenkins_hashlittle2(data, length, &a, &b); return ((uint64_t) a << 32ULL) | (uint64_t) b; } systemd-229/src/journal/mmap-cache.c000066400000000000000000000416741265713322000174750ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "hashmap.h" #include "list.h" #include "log.h" #include "macro.h" #include "mmap-cache.h" #include "sigbus.h" #include "util.h" typedef struct Window Window; typedef struct Context Context; typedef struct FileDescriptor FileDescriptor; struct Window { MMapCache *cache; bool invalidated:1; bool keep_always:1; bool in_unused:1; int prot; void *ptr; uint64_t offset; size_t size; FileDescriptor *fd; LIST_FIELDS(Window, by_fd); LIST_FIELDS(Window, unused); LIST_HEAD(Context, contexts); }; struct Context { MMapCache *cache; unsigned id; Window *window; LIST_FIELDS(Context, by_window); }; struct FileDescriptor { MMapCache *cache; int fd; bool sigbus; LIST_HEAD(Window, windows); }; struct MMapCache { int n_ref; unsigned n_windows; unsigned n_hit, n_missed; Hashmap *fds; Context *contexts[MMAP_CACHE_MAX_CONTEXTS]; LIST_HEAD(Window, unused); Window *last_unused; }; #define WINDOWS_MIN 64 #ifdef ENABLE_DEBUG_MMAP_CACHE /* Tiny windows increase mmap activity and the chance of exposing unsafe use. */ # define WINDOW_SIZE (page_size()) #else # define WINDOW_SIZE (8ULL*1024ULL*1024ULL) #endif MMapCache* mmap_cache_new(void) { MMapCache *m; m = new0(MMapCache, 1); if (!m) return NULL; m->n_ref = 1; return m; } MMapCache* mmap_cache_ref(MMapCache *m) { assert(m); assert(m->n_ref > 0); m->n_ref ++; return m; } static void window_unlink(Window *w) { Context *c; assert(w); if (w->ptr) munmap(w->ptr, w->size); if (w->fd) LIST_REMOVE(by_fd, w->fd->windows, w); if (w->in_unused) { if (w->cache->last_unused == w) w->cache->last_unused = w->unused_prev; LIST_REMOVE(unused, w->cache->unused, w); } LIST_FOREACH(by_window, c, w->contexts) { assert(c->window == w); c->window = NULL; } } static void window_invalidate(Window *w) { assert(w); if (w->invalidated) return; /* Replace the window with anonymous pages. This is useful * when we hit a SIGBUS and want to make sure the file cannot * trigger any further SIGBUS, possibly overrunning the sigbus * queue. */ assert_se(mmap(w->ptr, w->size, w->prot, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) == w->ptr); w->invalidated = true; } static void window_free(Window *w) { assert(w); window_unlink(w); w->cache->n_windows--; free(w); } _pure_ static bool window_matches(Window *w, int fd, int prot, uint64_t offset, size_t size) { assert(w); assert(fd >= 0); assert(size > 0); return w->fd && fd == w->fd->fd && prot == w->prot && offset >= w->offset && offset + size <= w->offset + w->size; } static Window *window_add(MMapCache *m, FileDescriptor *fd, int prot, bool keep_always, uint64_t offset, size_t size, void *ptr) { Window *w; assert(m); assert(fd); if (!m->last_unused || m->n_windows <= WINDOWS_MIN) { /* Allocate a new window */ w = new0(Window, 1); if (!w) return NULL; m->n_windows++; } else { /* Reuse an existing one */ w = m->last_unused; window_unlink(w); zero(*w); } w->cache = m; w->fd = fd; w->prot = prot; w->keep_always = keep_always; w->offset = offset; w->size = size; w->ptr = ptr; LIST_PREPEND(by_fd, fd->windows, w); return w; } static void context_detach_window(Context *c) { Window *w; assert(c); if (!c->window) return; w = c->window; c->window = NULL; LIST_REMOVE(by_window, w->contexts, c); if (!w->contexts && !w->keep_always) { /* Not used anymore? */ #ifdef ENABLE_DEBUG_MMAP_CACHE /* Unmap unused windows immediately to expose use-after-unmap * by SIGSEGV. */ window_free(w); #else LIST_PREPEND(unused, c->cache->unused, w); if (!c->cache->last_unused) c->cache->last_unused = w; w->in_unused = true; #endif } } static void context_attach_window(Context *c, Window *w) { assert(c); assert(w); if (c->window == w) return; context_detach_window(c); if (w->in_unused) { /* Used again? */ LIST_REMOVE(unused, c->cache->unused, w); if (c->cache->last_unused == w) c->cache->last_unused = w->unused_prev; w->in_unused = false; } c->window = w; LIST_PREPEND(by_window, w->contexts, c); } static Context *context_add(MMapCache *m, unsigned id) { Context *c; assert(m); c = m->contexts[id]; if (c) return c; c = new0(Context, 1); if (!c) return NULL; c->cache = m; c->id = id; assert(!m->contexts[id]); m->contexts[id] = c; return c; } static void context_free(Context *c) { assert(c); context_detach_window(c); if (c->cache) { assert(c->cache->contexts[c->id] == c); c->cache->contexts[c->id] = NULL; } free(c); } static void fd_free(FileDescriptor *f) { assert(f); while (f->windows) window_free(f->windows); if (f->cache) assert_se(hashmap_remove(f->cache->fds, FD_TO_PTR(f->fd))); free(f); } static FileDescriptor* fd_add(MMapCache *m, int fd) { FileDescriptor *f; int r; assert(m); assert(fd >= 0); f = hashmap_get(m->fds, FD_TO_PTR(fd)); if (f) return f; r = hashmap_ensure_allocated(&m->fds, NULL); if (r < 0) return NULL; f = new0(FileDescriptor, 1); if (!f) return NULL; f->cache = m; f->fd = fd; r = hashmap_put(m->fds, FD_TO_PTR(fd), f); if (r < 0) { free(f); return NULL; } return f; } static void mmap_cache_free(MMapCache *m) { FileDescriptor *f; int i; assert(m); for (i = 0; i < MMAP_CACHE_MAX_CONTEXTS; i++) if (m->contexts[i]) context_free(m->contexts[i]); while ((f = hashmap_first(m->fds))) fd_free(f); hashmap_free(m->fds); while (m->unused) window_free(m->unused); free(m); } MMapCache* mmap_cache_unref(MMapCache *m) { if (!m) return NULL; assert(m->n_ref > 0); m->n_ref --; if (m->n_ref == 0) mmap_cache_free(m); return NULL; } static int make_room(MMapCache *m) { assert(m); if (!m->last_unused) return 0; window_free(m->last_unused); return 1; } static int try_context( MMapCache *m, int fd, int prot, unsigned context, bool keep_always, uint64_t offset, size_t size, void **ret) { Context *c; assert(m); assert(m->n_ref > 0); assert(fd >= 0); assert(size > 0); assert(ret); c = m->contexts[context]; if (!c) return 0; assert(c->id == context); if (!c->window) return 0; if (!window_matches(c->window, fd, prot, offset, size)) { /* Drop the reference to the window, since it's unnecessary now */ context_detach_window(c); return 0; } if (c->window->fd->sigbus) return -EIO; c->window->keep_always = c->window->keep_always || keep_always; *ret = (uint8_t*) c->window->ptr + (offset - c->window->offset); return 1; } static int find_mmap( MMapCache *m, int fd, int prot, unsigned context, bool keep_always, uint64_t offset, size_t size, void **ret) { FileDescriptor *f; Window *w; Context *c; assert(m); assert(m->n_ref > 0); assert(fd >= 0); assert(size > 0); f = hashmap_get(m->fds, FD_TO_PTR(fd)); if (!f) return 0; assert(f->fd == fd); if (f->sigbus) return -EIO; LIST_FOREACH(by_fd, w, f->windows) if (window_matches(w, fd, prot, offset, size)) break; if (!w) return 0; c = context_add(m, context); if (!c) return -ENOMEM; context_attach_window(c, w); w->keep_always = w->keep_always || keep_always; *ret = (uint8_t*) w->ptr + (offset - w->offset); return 1; } static int mmap_try_harder(MMapCache *m, void *addr, int fd, int prot, int flags, uint64_t offset, size_t size, void **res) { void *ptr; assert(m); assert(fd >= 0); assert(res); for (;;) { int r; ptr = mmap(addr, size, prot, flags, fd, offset); if (ptr != MAP_FAILED) break; if (errno != ENOMEM) return -errno; r = make_room(m); if (r < 0) return r; if (r == 0) return -ENOMEM; } *res = ptr; return 0; } static int add_mmap( MMapCache *m, int fd, int prot, unsigned context, bool keep_always, uint64_t offset, size_t size, struct stat *st, void **ret) { uint64_t woffset, wsize; Context *c; FileDescriptor *f; Window *w; void *d; int r; assert(m); assert(m->n_ref > 0); assert(fd >= 0); assert(size > 0); assert(ret); woffset = offset & ~((uint64_t) page_size() - 1ULL); wsize = size + (offset - woffset); wsize = PAGE_ALIGN(wsize); if (wsize < WINDOW_SIZE) { uint64_t delta; delta = PAGE_ALIGN((WINDOW_SIZE - wsize) / 2); if (delta > offset) woffset = 0; else woffset -= delta; wsize = WINDOW_SIZE; } if (st) { /* Memory maps that are larger then the files underneath have undefined behavior. Hence, clamp things to the file size if we know it */ if (woffset >= (uint64_t) st->st_size) return -EADDRNOTAVAIL; if (woffset + wsize > (uint64_t) st->st_size) wsize = PAGE_ALIGN(st->st_size - woffset); } r = mmap_try_harder(m, NULL, fd, prot, MAP_SHARED, woffset, wsize, &d); if (r < 0) return r; c = context_add(m, context); if (!c) goto outofmem; f = fd_add(m, fd); if (!f) goto outofmem; w = window_add(m, f, prot, keep_always, woffset, wsize, d); if (!w) goto outofmem; context_detach_window(c); c->window = w; LIST_PREPEND(by_window, w->contexts, c); *ret = (uint8_t*) w->ptr + (offset - w->offset); return 1; outofmem: munmap(d, wsize); return -ENOMEM; } int mmap_cache_get( MMapCache *m, int fd, int prot, unsigned context, bool keep_always, uint64_t offset, size_t size, struct stat *st, void **ret) { int r; assert(m); assert(m->n_ref > 0); assert(fd >= 0); assert(size > 0); assert(ret); assert(context < MMAP_CACHE_MAX_CONTEXTS); /* Check whether the current context is the right one already */ r = try_context(m, fd, prot, context, keep_always, offset, size, ret); if (r != 0) { m->n_hit ++; return r; } /* Search for a matching mmap */ r = find_mmap(m, fd, prot, context, keep_always, offset, size, ret); if (r != 0) { m->n_hit ++; return r; } m->n_missed++; /* Create a new mmap */ return add_mmap(m, fd, prot, context, keep_always, offset, size, st, ret); } unsigned mmap_cache_get_hit(MMapCache *m) { assert(m); return m->n_hit; } unsigned mmap_cache_get_missed(MMapCache *m) { assert(m); return m->n_missed; } static void mmap_cache_process_sigbus(MMapCache *m) { bool found = false; FileDescriptor *f; Iterator i; int r; assert(m); /* Iterate through all triggered pages and mark their files as * invalidated */ for (;;) { bool ours; void *addr; r = sigbus_pop(&addr); if (_likely_(r == 0)) break; if (r < 0) { log_error_errno(r, "SIGBUS handling failed: %m"); abort(); } ours = false; HASHMAP_FOREACH(f, m->fds, i) { Window *w; LIST_FOREACH(by_fd, w, f->windows) { if ((uint8_t*) addr >= (uint8_t*) w->ptr && (uint8_t*) addr < (uint8_t*) w->ptr + w->size) { found = ours = f->sigbus = true; break; } } if (ours) break; } /* Didn't find a matching window, give up */ if (!ours) { log_error("Unknown SIGBUS page, aborting."); abort(); } } /* The list of triggered pages is now empty. Now, let's remap * all windows of the triggered file to anonymous maps, so * that no page of the file in question is triggered again, so * that we can be sure not to hit the queue size limit. */ if (_likely_(!found)) return; HASHMAP_FOREACH(f, m->fds, i) { Window *w; if (!f->sigbus) continue; LIST_FOREACH(by_fd, w, f->windows) window_invalidate(w); } } bool mmap_cache_got_sigbus(MMapCache *m, int fd) { FileDescriptor *f; assert(m); assert(fd >= 0); mmap_cache_process_sigbus(m); f = hashmap_get(m->fds, FD_TO_PTR(fd)); if (!f) return false; return f->sigbus; } void mmap_cache_close_fd(MMapCache *m, int fd) { FileDescriptor *f; assert(m); assert(fd >= 0); /* Make sure that any queued SIGBUS are first dispatched, so * that we don't end up with a SIGBUS entry we cannot relate * to any existing memory map */ mmap_cache_process_sigbus(m); f = hashmap_get(m->fds, FD_TO_PTR(fd)); if (!f) return; fd_free(f); } systemd-229/src/journal/mmap-cache.h000066400000000000000000000026651265713322000174770ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include /* One context per object type, plus one of the header, plus one "additional" one */ #define MMAP_CACHE_MAX_CONTEXTS 9 typedef struct MMapCache MMapCache; MMapCache* mmap_cache_new(void); MMapCache* mmap_cache_ref(MMapCache *m); MMapCache* mmap_cache_unref(MMapCache *m); int mmap_cache_get( MMapCache *m, int fd, int prot, unsigned context, bool keep_always, uint64_t offset, size_t size, struct stat *st, void **ret); void mmap_cache_close_fd(MMapCache *m, int fd); unsigned mmap_cache_get_hit(MMapCache *m); unsigned mmap_cache_get_missed(MMapCache *m); bool mmap_cache_got_sigbus(MMapCache *m, int fd); systemd-229/src/journal/sd-journal.c000066400000000000000000002427261265713322000175610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "sd-journal.h" #include "alloc-util.h" #include "catalog.h" #include "compress.h" #include "dirent-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "hashmap.h" #include "hostname-util.h" #include "io-util.h" #include "journal-def.h" #include "journal-file.h" #include "journal-internal.h" #include "list.h" #include "lookup3.h" #include "missing.h" #include "path-util.h" #include "replace-var.h" #include "stat-util.h" #include "stdio-util.h" #include "string-util.h" #include "strv.h" #define JOURNAL_FILES_MAX 7168 #define JOURNAL_FILES_RECHECK_USEC (2 * USEC_PER_SEC) #define REPLACE_VAR_MAX 256 #define DEFAULT_DATA_THRESHOLD (64*1024) static void remove_file_real(sd_journal *j, JournalFile *f); static bool journal_pid_changed(sd_journal *j) { assert(j); /* We don't support people creating a journal object and * keeping it around over a fork(). Let's complain. */ return j->original_pid != getpid(); } static int journal_put_error(sd_journal *j, int r, const char *path) { char *copy; int k; /* Memorize an error we encountered, and store which * file/directory it was generated from. Note that we store * only *one* path per error code, as the error code is the * key into the hashmap, and the path is the value. This means * we keep track only of all error kinds, but not of all error * locations. This has the benefit that the hashmap cannot * grow beyond bounds. * * We return an error here only if we didn't manage to * memorize the real error. */ if (r >= 0) return r; k = hashmap_ensure_allocated(&j->errors, NULL); if (k < 0) return k; if (path) { copy = strdup(path); if (!copy) return -ENOMEM; } else copy = NULL; k = hashmap_put(j->errors, INT_TO_PTR(r), copy); if (k < 0) { free(copy); if (k == -EEXIST) return 0; return k; } return 0; } static void detach_location(sd_journal *j) { Iterator i; JournalFile *f; assert(j); j->current_file = NULL; j->current_field = 0; ORDERED_HASHMAP_FOREACH(f, j->files, i) journal_file_reset_location(f); } static void reset_location(sd_journal *j) { assert(j); detach_location(j); zero(j->current_location); } static void init_location(Location *l, LocationType type, JournalFile *f, Object *o) { assert(l); assert(type == LOCATION_DISCRETE || type == LOCATION_SEEK); assert(f); assert(o->object.type == OBJECT_ENTRY); l->type = type; l->seqnum = le64toh(o->entry.seqnum); l->seqnum_id = f->header->seqnum_id; l->realtime = le64toh(o->entry.realtime); l->monotonic = le64toh(o->entry.monotonic); l->boot_id = o->entry.boot_id; l->xor_hash = le64toh(o->entry.xor_hash); l->seqnum_set = l->realtime_set = l->monotonic_set = l->xor_hash_set = true; } static void set_location(sd_journal *j, JournalFile *f, Object *o) { assert(j); assert(f); assert(o); init_location(&j->current_location, LOCATION_DISCRETE, f, o); j->current_file = f; j->current_field = 0; /* Let f know its candidate entry was picked. */ assert(f->location_type == LOCATION_SEEK); f->location_type = LOCATION_DISCRETE; } static int match_is_valid(const void *data, size_t size) { const char *b, *p; assert(data); if (size < 2) return false; if (startswith(data, "__")) return false; b = data; for (p = b; p < b + size; p++) { if (*p == '=') return p > b; if (*p == '_') continue; if (*p >= 'A' && *p <= 'Z') continue; if (*p >= '0' && *p <= '9') continue; return false; } return false; } static bool same_field(const void *_a, size_t s, const void *_b, size_t t) { const uint8_t *a = _a, *b = _b; size_t j; for (j = 0; j < s && j < t; j++) { if (a[j] != b[j]) return false; if (a[j] == '=') return true; } assert_not_reached("\"=\" not found"); } static Match *match_new(Match *p, MatchType t) { Match *m; m = new0(Match, 1); if (!m) return NULL; m->type = t; if (p) { m->parent = p; LIST_PREPEND(matches, p->matches, m); } return m; } static void match_free(Match *m) { assert(m); while (m->matches) match_free(m->matches); if (m->parent) LIST_REMOVE(matches, m->parent->matches, m); free(m->data); free(m); } static void match_free_if_empty(Match *m) { if (!m || m->matches) return; match_free(m); } _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) { Match *l3, *l4, *add_here = NULL, *m; le64_t le_hash; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(data, -EINVAL); if (size == 0) size = strlen(data); assert_return(match_is_valid(data, size), -EINVAL); /* level 0: AND term * level 1: OR terms * level 2: AND terms * level 3: OR terms * level 4: concrete matches */ if (!j->level0) { j->level0 = match_new(NULL, MATCH_AND_TERM); if (!j->level0) return -ENOMEM; } if (!j->level1) { j->level1 = match_new(j->level0, MATCH_OR_TERM); if (!j->level1) return -ENOMEM; } if (!j->level2) { j->level2 = match_new(j->level1, MATCH_AND_TERM); if (!j->level2) return -ENOMEM; } assert(j->level0->type == MATCH_AND_TERM); assert(j->level1->type == MATCH_OR_TERM); assert(j->level2->type == MATCH_AND_TERM); le_hash = htole64(hash64(data, size)); LIST_FOREACH(matches, l3, j->level2->matches) { assert(l3->type == MATCH_OR_TERM); LIST_FOREACH(matches, l4, l3->matches) { assert(l4->type == MATCH_DISCRETE); /* Exactly the same match already? Then ignore * this addition */ if (l4->le_hash == le_hash && l4->size == size && memcmp(l4->data, data, size) == 0) return 0; /* Same field? Then let's add this to this OR term */ if (same_field(data, size, l4->data, l4->size)) { add_here = l3; break; } } if (add_here) break; } if (!add_here) { add_here = match_new(j->level2, MATCH_OR_TERM); if (!add_here) goto fail; } m = match_new(add_here, MATCH_DISCRETE); if (!m) goto fail; m->le_hash = le_hash; m->size = size; m->data = memdup(data, size); if (!m->data) goto fail; detach_location(j); return 0; fail: match_free_if_empty(add_here); match_free_if_empty(j->level2); match_free_if_empty(j->level1); match_free_if_empty(j->level0); return -ENOMEM; } _public_ int sd_journal_add_conjunction(sd_journal *j) { assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); if (!j->level0) return 0; if (!j->level1) return 0; if (!j->level1->matches) return 0; j->level1 = NULL; j->level2 = NULL; return 0; } _public_ int sd_journal_add_disjunction(sd_journal *j) { assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); if (!j->level0) return 0; if (!j->level1) return 0; if (!j->level2) return 0; if (!j->level2->matches) return 0; j->level2 = NULL; return 0; } static char *match_make_string(Match *m) { char *p, *r; Match *i; bool enclose = false; if (!m) return strdup("none"); if (m->type == MATCH_DISCRETE) return strndup(m->data, m->size); p = NULL; LIST_FOREACH(matches, i, m->matches) { char *t, *k; t = match_make_string(i); if (!t) { free(p); return NULL; } if (p) { k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t, NULL); free(p); free(t); if (!k) return NULL; p = k; enclose = true; } else p = t; } if (enclose) { r = strjoin("(", p, ")", NULL); free(p); return r; } return p; } char *journal_make_match_string(sd_journal *j) { assert(j); return match_make_string(j->level0); } _public_ void sd_journal_flush_matches(sd_journal *j) { if (!j) return; if (j->level0) match_free(j->level0); j->level0 = j->level1 = j->level2 = NULL; detach_location(j); } _pure_ static int compare_with_location(JournalFile *f, Location *l) { assert(f); assert(l); assert(f->location_type == LOCATION_SEEK); assert(l->type == LOCATION_DISCRETE || l->type == LOCATION_SEEK); if (l->monotonic_set && sd_id128_equal(f->current_boot_id, l->boot_id) && l->realtime_set && f->current_realtime == l->realtime && l->xor_hash_set && f->current_xor_hash == l->xor_hash) return 0; if (l->seqnum_set && sd_id128_equal(f->header->seqnum_id, l->seqnum_id)) { if (f->current_seqnum < l->seqnum) return -1; if (f->current_seqnum > l->seqnum) return 1; } if (l->monotonic_set && sd_id128_equal(f->current_boot_id, l->boot_id)) { if (f->current_monotonic < l->monotonic) return -1; if (f->current_monotonic > l->monotonic) return 1; } if (l->realtime_set) { if (f->current_realtime < l->realtime) return -1; if (f->current_realtime > l->realtime) return 1; } if (l->xor_hash_set) { if (f->current_xor_hash < l->xor_hash) return -1; if (f->current_xor_hash > l->xor_hash) return 1; } return 0; } static int next_for_match( sd_journal *j, Match *m, JournalFile *f, uint64_t after_offset, direction_t direction, Object **ret, uint64_t *offset) { int r; uint64_t np = 0; Object *n; assert(j); assert(m); assert(f); if (m->type == MATCH_DISCRETE) { uint64_t dp; r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp); if (r <= 0) return r; return journal_file_move_to_entry_by_offset_for_data(f, dp, after_offset, direction, ret, offset); } else if (m->type == MATCH_OR_TERM) { Match *i; /* Find the earliest match beyond after_offset */ LIST_FOREACH(matches, i, m->matches) { uint64_t cp; r = next_for_match(j, i, f, after_offset, direction, NULL, &cp); if (r < 0) return r; else if (r > 0) { if (np == 0 || (direction == DIRECTION_DOWN ? cp < np : cp > np)) np = cp; } } if (np == 0) return 0; } else if (m->type == MATCH_AND_TERM) { Match *i, *last_moved; /* Always jump to the next matching entry and repeat * this until we find an offset that matches for all * matches. */ if (!m->matches) return 0; r = next_for_match(j, m->matches, f, after_offset, direction, NULL, &np); if (r <= 0) return r; assert(direction == DIRECTION_DOWN ? np >= after_offset : np <= after_offset); last_moved = m->matches; LIST_LOOP_BUT_ONE(matches, i, m->matches, last_moved) { uint64_t cp; r = next_for_match(j, i, f, np, direction, NULL, &cp); if (r <= 0) return r; assert(direction == DIRECTION_DOWN ? cp >= np : cp <= np); if (direction == DIRECTION_DOWN ? cp > np : cp < np) { np = cp; last_moved = i; } } } assert(np > 0); r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n); if (r < 0) return r; if (ret) *ret = n; if (offset) *offset = np; return 1; } static int find_location_for_match( sd_journal *j, Match *m, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) { int r; assert(j); assert(m); assert(f); if (m->type == MATCH_DISCRETE) { uint64_t dp; r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp); if (r <= 0) return r; /* FIXME: missing: find by monotonic */ if (j->current_location.type == LOCATION_HEAD) return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_DOWN, ret, offset); if (j->current_location.type == LOCATION_TAIL) return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_UP, ret, offset); if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id)) return journal_file_move_to_entry_by_seqnum_for_data(f, dp, j->current_location.seqnum, direction, ret, offset); if (j->current_location.monotonic_set) { r = journal_file_move_to_entry_by_monotonic_for_data(f, dp, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset); if (r != -ENOENT) return r; } if (j->current_location.realtime_set) return journal_file_move_to_entry_by_realtime_for_data(f, dp, j->current_location.realtime, direction, ret, offset); return journal_file_next_entry_for_data(f, NULL, 0, dp, direction, ret, offset); } else if (m->type == MATCH_OR_TERM) { uint64_t np = 0; Object *n; Match *i; /* Find the earliest match */ LIST_FOREACH(matches, i, m->matches) { uint64_t cp; r = find_location_for_match(j, i, f, direction, NULL, &cp); if (r < 0) return r; else if (r > 0) { if (np == 0 || (direction == DIRECTION_DOWN ? np > cp : np < cp)) np = cp; } } if (np == 0) return 0; r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n); if (r < 0) return r; if (ret) *ret = n; if (offset) *offset = np; return 1; } else { Match *i; uint64_t np = 0; assert(m->type == MATCH_AND_TERM); /* First jump to the last match, and then find the * next one where all matches match */ if (!m->matches) return 0; LIST_FOREACH(matches, i, m->matches) { uint64_t cp; r = find_location_for_match(j, i, f, direction, NULL, &cp); if (r <= 0) return r; if (np == 0 || (direction == DIRECTION_DOWN ? cp > np : cp < np)) np = cp; } return next_for_match(j, m, f, np, direction, ret, offset); } } static int find_location_with_matches( sd_journal *j, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) { int r; assert(j); assert(f); assert(ret); assert(offset); if (!j->level0) { /* No matches is simple */ if (j->current_location.type == LOCATION_HEAD) return journal_file_next_entry(f, 0, DIRECTION_DOWN, ret, offset); if (j->current_location.type == LOCATION_TAIL) return journal_file_next_entry(f, 0, DIRECTION_UP, ret, offset); if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id)) return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, offset); if (j->current_location.monotonic_set) { r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset); if (r != -ENOENT) return r; } if (j->current_location.realtime_set) return journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, ret, offset); return journal_file_next_entry(f, 0, direction, ret, offset); } else return find_location_for_match(j, j->level0, f, direction, ret, offset); } static int next_with_matches( sd_journal *j, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) { assert(j); assert(f); assert(ret); assert(offset); /* No matches is easy. We simple advance the file * pointer by one. */ if (!j->level0) return journal_file_next_entry(f, f->current_offset, direction, ret, offset); /* If we have a match then we look for the next matching entry * with an offset at least one step larger */ return next_for_match(j, j->level0, f, direction == DIRECTION_DOWN ? f->current_offset + 1 : f->current_offset - 1, direction, ret, offset); } static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction) { Object *c; uint64_t cp, n_entries; int r; assert(j); assert(f); n_entries = le64toh(f->header->n_entries); /* If we hit EOF before, we don't need to look into this file again * unless direction changed or new entries appeared. */ if (f->last_direction == direction && f->location_type == LOCATION_TAIL && n_entries == f->last_n_entries) return 0; f->last_n_entries = n_entries; if (f->last_direction == direction && f->current_offset > 0) { /* LOCATION_SEEK here means we did the work in a previous * iteration and the current location already points to a * candidate entry. */ if (f->location_type != LOCATION_SEEK) { r = next_with_matches(j, f, direction, &c, &cp); if (r <= 0) return r; journal_file_save_location(f, c, cp); } } else { f->last_direction = direction; r = find_location_with_matches(j, f, direction, &c, &cp); if (r <= 0) return r; journal_file_save_location(f, c, cp); } /* OK, we found the spot, now let's advance until an entry * that is actually different from what we were previously * looking at. This is necessary to handle entries which exist * in two (or more) journal files, and which shall all be * suppressed but one. */ for (;;) { bool found; if (j->current_location.type == LOCATION_DISCRETE) { int k; k = compare_with_location(f, &j->current_location); found = direction == DIRECTION_DOWN ? k > 0 : k < 0; } else found = true; if (found) return 1; r = next_with_matches(j, f, direction, &c, &cp); if (r <= 0) return r; journal_file_save_location(f, c, cp); } } static int real_journal_next(sd_journal *j, direction_t direction) { JournalFile *f, *new_file = NULL; Iterator i; Object *o; int r; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); ORDERED_HASHMAP_FOREACH(f, j->files, i) { bool found; r = next_beyond_location(j, f, direction); if (r < 0) { log_debug_errno(r, "Can't iterate through %s, ignoring: %m", f->path); remove_file_real(j, f); continue; } else if (r == 0) { f->location_type = LOCATION_TAIL; continue; } if (!new_file) found = true; else { int k; k = journal_file_compare_locations(f, new_file); found = direction == DIRECTION_DOWN ? k < 0 : k > 0; } if (found) new_file = f; } if (!new_file) return 0; r = journal_file_move_to_object(new_file, OBJECT_ENTRY, new_file->current_offset, &o); if (r < 0) return r; set_location(j, new_file, o); return 1; } _public_ int sd_journal_next(sd_journal *j) { return real_journal_next(j, DIRECTION_DOWN); } _public_ int sd_journal_previous(sd_journal *j) { return real_journal_next(j, DIRECTION_UP); } static int real_journal_next_skip(sd_journal *j, direction_t direction, uint64_t skip) { int c = 0, r; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); if (skip == 0) { /* If this is not a discrete skip, then at least * resolve the current location */ if (j->current_location.type != LOCATION_DISCRETE) return real_journal_next(j, direction); return 0; } do { r = real_journal_next(j, direction); if (r < 0) return r; if (r == 0) return c; skip--; c++; } while (skip > 0); return c; } _public_ int sd_journal_next_skip(sd_journal *j, uint64_t skip) { return real_journal_next_skip(j, DIRECTION_DOWN, skip); } _public_ int sd_journal_previous_skip(sd_journal *j, uint64_t skip) { return real_journal_next_skip(j, DIRECTION_UP, skip); } _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) { Object *o; int r; char bid[33], sid[33]; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(cursor, -EINVAL); if (!j->current_file || j->current_file->current_offset <= 0) return -EADDRNOTAVAIL; r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o); if (r < 0) return r; sd_id128_to_string(j->current_file->header->seqnum_id, sid); sd_id128_to_string(o->entry.boot_id, bid); if (asprintf(cursor, "s=%s;i=%"PRIx64";b=%s;m=%"PRIx64";t=%"PRIx64";x=%"PRIx64, sid, le64toh(o->entry.seqnum), bid, le64toh(o->entry.monotonic), le64toh(o->entry.realtime), le64toh(o->entry.xor_hash)) < 0) return -ENOMEM; return 0; } _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) { const char *word, *state; size_t l; unsigned long long seqnum, monotonic, realtime, xor_hash; bool seqnum_id_set = false, seqnum_set = false, boot_id_set = false, monotonic_set = false, realtime_set = false, xor_hash_set = false; sd_id128_t seqnum_id, boot_id; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(!isempty(cursor), -EINVAL); FOREACH_WORD_SEPARATOR(word, l, cursor, ";", state) { char *item; int k = 0; if (l < 2 || word[1] != '=') return -EINVAL; item = strndup(word, l); if (!item) return -ENOMEM; switch (word[0]) { case 's': seqnum_id_set = true; k = sd_id128_from_string(item+2, &seqnum_id); break; case 'i': seqnum_set = true; if (sscanf(item+2, "%llx", &seqnum) != 1) k = -EINVAL; break; case 'b': boot_id_set = true; k = sd_id128_from_string(item+2, &boot_id); break; case 'm': monotonic_set = true; if (sscanf(item+2, "%llx", &monotonic) != 1) k = -EINVAL; break; case 't': realtime_set = true; if (sscanf(item+2, "%llx", &realtime) != 1) k = -EINVAL; break; case 'x': xor_hash_set = true; if (sscanf(item+2, "%llx", &xor_hash) != 1) k = -EINVAL; break; } free(item); if (k < 0) return k; } if ((!seqnum_set || !seqnum_id_set) && (!monotonic_set || !boot_id_set) && !realtime_set) return -EINVAL; reset_location(j); j->current_location.type = LOCATION_SEEK; if (realtime_set) { j->current_location.realtime = (uint64_t) realtime; j->current_location.realtime_set = true; } if (seqnum_set && seqnum_id_set) { j->current_location.seqnum = (uint64_t) seqnum; j->current_location.seqnum_id = seqnum_id; j->current_location.seqnum_set = true; } if (monotonic_set && boot_id_set) { j->current_location.monotonic = (uint64_t) monotonic; j->current_location.boot_id = boot_id; j->current_location.monotonic_set = true; } if (xor_hash_set) { j->current_location.xor_hash = (uint64_t) xor_hash; j->current_location.xor_hash_set = true; } return 0; } _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) { int r; Object *o; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(!isempty(cursor), -EINVAL); if (!j->current_file || j->current_file->current_offset <= 0) return -EADDRNOTAVAIL; r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o); if (r < 0) return r; for(;;) { _cleanup_free_ char *item = NULL; unsigned long long ll; sd_id128_t id; int k = 0; r = extract_first_word(&cursor, &item, ";", EXTRACT_DONT_COALESCE_SEPARATORS); if (r < 0) return r; if (r == 0) break; if (strlen(item) < 2 || item[1] != '=') return -EINVAL; switch (item[0]) { case 's': k = sd_id128_from_string(item+2, &id); if (k < 0) return k; if (!sd_id128_equal(id, j->current_file->header->seqnum_id)) return 0; break; case 'i': if (sscanf(item+2, "%llx", &ll) != 1) return -EINVAL; if (ll != le64toh(o->entry.seqnum)) return 0; break; case 'b': k = sd_id128_from_string(item+2, &id); if (k < 0) return k; if (!sd_id128_equal(id, o->entry.boot_id)) return 0; break; case 'm': if (sscanf(item+2, "%llx", &ll) != 1) return -EINVAL; if (ll != le64toh(o->entry.monotonic)) return 0; break; case 't': if (sscanf(item+2, "%llx", &ll) != 1) return -EINVAL; if (ll != le64toh(o->entry.realtime)) return 0; break; case 'x': if (sscanf(item+2, "%llx", &ll) != 1) return -EINVAL; if (ll != le64toh(o->entry.xor_hash)) return 0; break; } } return 1; } _public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec) { assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); reset_location(j); j->current_location.type = LOCATION_SEEK; j->current_location.boot_id = boot_id; j->current_location.monotonic = usec; j->current_location.monotonic_set = true; return 0; } _public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) { assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); reset_location(j); j->current_location.type = LOCATION_SEEK; j->current_location.realtime = usec; j->current_location.realtime_set = true; return 0; } _public_ int sd_journal_seek_head(sd_journal *j) { assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); reset_location(j); j->current_location.type = LOCATION_HEAD; return 0; } _public_ int sd_journal_seek_tail(sd_journal *j) { assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); reset_location(j); j->current_location.type = LOCATION_TAIL; return 0; } static void check_network(sd_journal *j, int fd) { struct statfs sfs; assert(j); if (j->on_network) return; if (fstatfs(fd, &sfs) < 0) return; j->on_network = F_TYPE_EQUAL(sfs.f_type, CIFS_MAGIC_NUMBER) || F_TYPE_EQUAL(sfs.f_type, CODA_SUPER_MAGIC) || F_TYPE_EQUAL(sfs.f_type, NCP_SUPER_MAGIC) || F_TYPE_EQUAL(sfs.f_type, NFS_SUPER_MAGIC) || F_TYPE_EQUAL(sfs.f_type, SMB_SUPER_MAGIC); } static bool file_has_type_prefix(const char *prefix, const char *filename) { const char *full, *tilded, *atted; full = strjoina(prefix, ".journal"); tilded = strjoina(full, "~"); atted = strjoina(prefix, "@"); return streq(filename, full) || streq(filename, tilded) || startswith(filename, atted); } static bool file_type_wanted(int flags, const char *filename) { assert(filename); if (!endswith(filename, ".journal") && !endswith(filename, ".journal~")) return false; /* no flags set → every type is OK */ if (!(flags & (SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER))) return true; if (flags & SD_JOURNAL_SYSTEM && file_has_type_prefix("system", filename)) return true; if (flags & SD_JOURNAL_CURRENT_USER) { char prefix[5 + DECIMAL_STR_MAX(uid_t) + 1]; xsprintf(prefix, "user-"UID_FMT, getuid()); if (file_has_type_prefix(prefix, filename)) return true; } return false; } static int add_any_file(sd_journal *j, const char *path) { JournalFile *f = NULL; int r, k; assert(j); assert(path); if (ordered_hashmap_get(j->files, path)) return 0; if (ordered_hashmap_size(j->files) >= JOURNAL_FILES_MAX) { log_debug("Too many open journal files, not adding %s.", path); r = -ETOOMANYREFS; goto fail; } r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f); if (r < 0) { log_debug_errno(r, "Failed to open journal file %s: %m", path); goto fail; } /* journal_file_dump(f); */ r = ordered_hashmap_put(j->files, f->path, f); if (r < 0) { journal_file_close(f); goto fail; } log_debug("File %s added.", f->path); check_network(j, f->fd); j->current_invalidate_counter ++; return 0; fail: k = journal_put_error(j, r, path); if (k < 0) return k; return r; } static int add_file(sd_journal *j, const char *prefix, const char *filename) { const char *path; assert(j); assert(prefix); assert(filename); if (j->no_new_files || !file_type_wanted(j->flags, filename)) return 0; path = strjoina(prefix, "/", filename); if (!j->has_runtime_files && path_startswith(path, "/run/log/journal")) j->has_runtime_files = true; else if (!j->has_persistent_files && path_startswith(path, "/var/log/journal")) j->has_persistent_files = true; return add_any_file(j, path); } static void remove_file(sd_journal *j, const char *prefix, const char *filename) { const char *path; JournalFile *f; assert(j); assert(prefix); assert(filename); path = strjoina(prefix, "/", filename); f = ordered_hashmap_get(j->files, path); if (!f) return; remove_file_real(j, f); } static void remove_file_real(sd_journal *j, JournalFile *f) { assert(j); assert(f); ordered_hashmap_remove(j->files, f->path); log_debug("File %s removed.", f->path); if (j->current_file == f) { j->current_file = NULL; j->current_field = 0; } if (j->unique_file == f) { /* Jump to the next unique_file or NULL if that one was last */ j->unique_file = ordered_hashmap_next(j->files, j->unique_file->path); j->unique_offset = 0; if (!j->unique_file) j->unique_file_lost = true; } if (j->fields_file == f) { j->fields_file = ordered_hashmap_next(j->files, j->fields_file->path); j->fields_offset = 0; if (!j->fields_file) j->fields_file_lost = true; } journal_file_close(f); j->current_invalidate_counter ++; } static int dirname_is_machine_id(const char *fn) { sd_id128_t id, machine; int r; r = sd_id128_get_machine(&machine); if (r < 0) return r; r = sd_id128_from_string(fn, &id); if (r < 0) return r; return sd_id128_equal(id, machine); } static int add_directory(sd_journal *j, const char *prefix, const char *dirname) { _cleanup_free_ char *path = NULL; _cleanup_closedir_ DIR *d = NULL; struct dirent *de = NULL; Directory *m; int r, k; assert(j); assert(prefix); assert(dirname); log_debug("Considering %s/%s.", prefix, dirname); if ((j->flags & SD_JOURNAL_LOCAL_ONLY) && !(dirname_is_machine_id(dirname) > 0 || path_startswith(prefix, "/run"))) return 0; path = strjoin(prefix, "/", dirname, NULL); if (!path) { r = -ENOMEM; goto fail; } d = opendir(path); if (!d) { r = log_debug_errno(errno, "Failed to open directory %s: %m", path); goto fail; } m = hashmap_get(j->directories_by_path, path); if (!m) { m = new0(Directory, 1); if (!m) { r = -ENOMEM; goto fail; } m->is_root = false; m->path = path; if (hashmap_put(j->directories_by_path, m->path, m) < 0) { free(m); r = -ENOMEM; goto fail; } path = NULL; /* avoid freeing in cleanup */ j->current_invalidate_counter ++; log_debug("Directory %s added.", m->path); } else if (m->is_root) return 0; if (m->wd <= 0 && j->inotify_fd >= 0) { m->wd = inotify_add_watch(j->inotify_fd, m->path, IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE| IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM| IN_ONLYDIR); if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0) inotify_rm_watch(j->inotify_fd, m->wd); } FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) { if (dirent_is_file_with_suffix(de, ".journal") || dirent_is_file_with_suffix(de, ".journal~")) (void) add_file(j, m->path, de->d_name); } check_network(j, dirfd(d)); return 0; fail: k = journal_put_error(j, r, path ?: dirname); if (k < 0) return k; return r; } static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; Directory *m; int r, k; assert(j); assert(p); if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) && !path_startswith(p, "/run")) return -EINVAL; if (j->prefix) p = strjoina(j->prefix, p); d = opendir(p); if (!d) { if (errno == ENOENT && missing_ok) return 0; r = log_debug_errno(errno, "Failed to open root directory %s: %m", p); goto fail; } m = hashmap_get(j->directories_by_path, p); if (!m) { m = new0(Directory, 1); if (!m) { r = -ENOMEM; goto fail; } m->is_root = true; m->path = strdup(p); if (!m->path) { free(m); r = -ENOMEM; goto fail; } if (hashmap_put(j->directories_by_path, m->path, m) < 0) { free(m->path); free(m); r = -ENOMEM; goto fail; } j->current_invalidate_counter ++; log_debug("Root directory %s added.", m->path); } else if (!m->is_root) return 0; if (m->wd <= 0 && j->inotify_fd >= 0) { m->wd = inotify_add_watch(j->inotify_fd, m->path, IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE| IN_ONLYDIR); if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0) inotify_rm_watch(j->inotify_fd, m->wd); } if (j->no_new_files) return 0; FOREACH_DIRENT_ALL(de, d, return log_debug_errno(errno, "Failed to read directory %s: %m", m->path)) { sd_id128_t id; if (dirent_is_file_with_suffix(de, ".journal") || dirent_is_file_with_suffix(de, ".journal~")) (void) add_file(j, m->path, de->d_name); else if (IN_SET(de->d_type, DT_DIR, DT_LNK, DT_UNKNOWN) && sd_id128_from_string(de->d_name, &id) >= 0) (void) add_directory(j, m->path, de->d_name); } check_network(j, dirfd(d)); return 0; fail: k = journal_put_error(j, r, p); if (k < 0) return k; return r; } static void remove_directory(sd_journal *j, Directory *d) { assert(j); if (d->wd > 0) { hashmap_remove(j->directories_by_wd, INT_TO_PTR(d->wd)); if (j->inotify_fd >= 0) inotify_rm_watch(j->inotify_fd, d->wd); } hashmap_remove(j->directories_by_path, d->path); if (d->is_root) log_debug("Root directory %s removed.", d->path); else log_debug("Directory %s removed.", d->path); free(d->path); free(d); } static int add_search_paths(sd_journal *j) { static const char search_paths[] = "/run/log/journal\0" "/var/log/journal\0"; const char *p; assert(j); /* We ignore most errors here, since the idea is to only open * what's actually accessible, and ignore the rest. */ NULSTR_FOREACH(p, search_paths) (void) add_root_directory(j, p, true); return 0; } static int add_current_paths(sd_journal *j) { Iterator i; JournalFile *f; assert(j); assert(j->no_new_files); /* Simply adds all directories for files we have open as * "root" directories. We don't expect errors here, so we * treat them as fatal. */ ORDERED_HASHMAP_FOREACH(f, j->files, i) { _cleanup_free_ char *dir; int r; dir = dirname_malloc(f->path); if (!dir) return -ENOMEM; r = add_root_directory(j, dir, true); if (r < 0) return r; } return 0; } static int allocate_inotify(sd_journal *j) { assert(j); if (j->inotify_fd < 0) { j->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (j->inotify_fd < 0) return -errno; } if (!j->directories_by_wd) { j->directories_by_wd = hashmap_new(NULL); if (!j->directories_by_wd) return -ENOMEM; } return 0; } static sd_journal *journal_new(int flags, const char *path) { sd_journal *j; j = new0(sd_journal, 1); if (!j) return NULL; j->original_pid = getpid(); j->inotify_fd = -1; j->flags = flags; j->data_threshold = DEFAULT_DATA_THRESHOLD; if (path) { j->path = strdup(path); if (!j->path) goto fail; } j->files = ordered_hashmap_new(&string_hash_ops); j->directories_by_path = hashmap_new(&string_hash_ops); j->mmap = mmap_cache_new(); if (!j->files || !j->directories_by_path || !j->mmap) goto fail; return j; fail: sd_journal_close(j); return NULL; } _public_ int sd_journal_open(sd_journal **ret, int flags) { sd_journal *j; int r; assert_return(ret, -EINVAL); assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_RUNTIME_ONLY|SD_JOURNAL_SYSTEM|SD_JOURNAL_CURRENT_USER)) == 0, -EINVAL); j = journal_new(flags, NULL); if (!j) return -ENOMEM; r = add_search_paths(j); if (r < 0) goto fail; *ret = j; return 0; fail: sd_journal_close(j); return r; } _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) { _cleanup_free_ char *root = NULL, *class = NULL; sd_journal *j; char *p; int r; assert_return(machine, -EINVAL); assert_return(ret, -EINVAL); assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM)) == 0, -EINVAL); assert_return(machine_name_is_valid(machine), -EINVAL); p = strjoina("/run/systemd/machines/", machine); r = parse_env_file(p, NEWLINE, "ROOT", &root, "CLASS", &class, NULL); if (r == -ENOENT) return -EHOSTDOWN; if (r < 0) return r; if (!root) return -ENODATA; if (!streq_ptr(class, "container")) return -EIO; j = journal_new(flags, NULL); if (!j) return -ENOMEM; j->prefix = root; root = NULL; r = add_search_paths(j); if (r < 0) goto fail; *ret = j; return 0; fail: sd_journal_close(j); return r; } _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) { sd_journal *j; int r; assert_return(ret, -EINVAL); assert_return(path, -EINVAL); assert_return(flags == 0, -EINVAL); j = journal_new(flags, path); if (!j) return -ENOMEM; r = add_root_directory(j, path, false); if (r < 0) goto fail; *ret = j; return 0; fail: sd_journal_close(j); return r; } _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int flags) { sd_journal *j; const char **path; int r; assert_return(ret, -EINVAL); assert_return(flags == 0, -EINVAL); j = journal_new(flags, NULL); if (!j) return -ENOMEM; STRV_FOREACH(path, paths) { r = add_any_file(j, *path); if (r < 0) goto fail; } j->no_new_files = true; *ret = j; return 0; fail: sd_journal_close(j); return r; } _public_ void sd_journal_close(sd_journal *j) { Directory *d; JournalFile *f; char *p; if (!j) return; sd_journal_flush_matches(j); while ((f = ordered_hashmap_steal_first(j->files))) journal_file_close(f); ordered_hashmap_free(j->files); while ((d = hashmap_first(j->directories_by_path))) remove_directory(j, d); while ((d = hashmap_first(j->directories_by_wd))) remove_directory(j, d); hashmap_free(j->directories_by_path); hashmap_free(j->directories_by_wd); safe_close(j->inotify_fd); if (j->mmap) { log_debug("mmap cache statistics: %u hit, %u miss", mmap_cache_get_hit(j->mmap), mmap_cache_get_missed(j->mmap)); mmap_cache_unref(j->mmap); } while ((p = hashmap_steal_first(j->errors))) free(p); hashmap_free(j->errors); free(j->path); free(j->prefix); free(j->unique_field); free(j->fields_buffer); free(j); } _public_ int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) { Object *o; JournalFile *f; int r; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(ret, -EINVAL); f = j->current_file; if (!f) return -EADDRNOTAVAIL; if (f->current_offset <= 0) return -EADDRNOTAVAIL; r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); if (r < 0) return r; *ret = le64toh(o->entry.realtime); return 0; } _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id) { Object *o; JournalFile *f; int r; sd_id128_t id; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); f = j->current_file; if (!f) return -EADDRNOTAVAIL; if (f->current_offset <= 0) return -EADDRNOTAVAIL; r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); if (r < 0) return r; if (ret_boot_id) *ret_boot_id = o->entry.boot_id; else { r = sd_id128_get_boot(&id); if (r < 0) return r; if (!sd_id128_equal(id, o->entry.boot_id)) return -ESTALE; } if (ret) *ret = le64toh(o->entry.monotonic); return 0; } static bool field_is_valid(const char *field) { const char *p; assert(field); if (isempty(field)) return false; if (startswith(field, "__")) return false; for (p = field; *p; p++) { if (*p == '_') continue; if (*p >= 'A' && *p <= 'Z') continue; if (*p >= '0' && *p <= '9') continue; return false; } return true; } _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *size) { JournalFile *f; uint64_t i, n; size_t field_length; int r; Object *o; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(field, -EINVAL); assert_return(data, -EINVAL); assert_return(size, -EINVAL); assert_return(field_is_valid(field), -EINVAL); f = j->current_file; if (!f) return -EADDRNOTAVAIL; if (f->current_offset <= 0) return -EADDRNOTAVAIL; r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); if (r < 0) return r; field_length = strlen(field); n = journal_file_entry_n_items(o); for (i = 0; i < n; i++) { uint64_t p, l; le64_t le_hash; size_t t; int compression; p = le64toh(o->entry.items[i].object_offset); le_hash = o->entry.items[i].hash; r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; if (le_hash != o->data.hash) return -EBADMSG; l = le64toh(o->object.size) - offsetof(Object, data.payload); compression = o->object.flags & OBJECT_COMPRESSION_MASK; if (compression) { #if defined(HAVE_XZ) || defined(HAVE_LZ4) r = decompress_startswith(compression, o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, field, field_length, '='); if (r < 0) log_debug_errno(r, "Cannot decompress %s object of length %zu at offset "OFSfmt": %m", object_compressed_to_string(compression), l, p); else if (r > 0) { size_t rsize; r = decompress_blob(compression, o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize, j->data_threshold); if (r < 0) return r; *data = f->compress_buffer; *size = (size_t) rsize; return 0; } #else return -EPROTONOSUPPORT; #endif } else if (l >= field_length+1 && memcmp(o->data.payload, field, field_length) == 0 && o->data.payload[field_length] == '=') { t = (size_t) l; if ((uint64_t) t != l) return -E2BIG; *data = o->data.payload; *size = t; return 0; } r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); if (r < 0) return r; } return -ENOENT; } static int return_data(sd_journal *j, JournalFile *f, Object *o, const void **data, size_t *size) { size_t t; uint64_t l; int compression; l = le64toh(o->object.size) - offsetof(Object, data.payload); t = (size_t) l; /* We can't read objects larger than 4G on a 32bit machine */ if ((uint64_t) t != l) return -E2BIG; compression = o->object.flags & OBJECT_COMPRESSION_MASK; if (compression) { #if defined(HAVE_XZ) || defined(HAVE_LZ4) size_t rsize; int r; r = decompress_blob(compression, o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize, j->data_threshold); if (r < 0) return r; *data = f->compress_buffer; *size = (size_t) rsize; #else return -EPROTONOSUPPORT; #endif } else { *data = o->data.payload; *size = t; } return 0; } _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) { JournalFile *f; uint64_t p, n; le64_t le_hash; int r; Object *o; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(data, -EINVAL); assert_return(size, -EINVAL); f = j->current_file; if (!f) return -EADDRNOTAVAIL; if (f->current_offset <= 0) return -EADDRNOTAVAIL; r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); if (r < 0) return r; n = journal_file_entry_n_items(o); if (j->current_field >= n) return 0; p = le64toh(o->entry.items[j->current_field].object_offset); le_hash = o->entry.items[j->current_field].hash; r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; if (le_hash != o->data.hash) return -EBADMSG; r = return_data(j, f, o, data, size); if (r < 0) return r; j->current_field ++; return 1; } _public_ void sd_journal_restart_data(sd_journal *j) { if (!j) return; j->current_field = 0; } _public_ int sd_journal_get_fd(sd_journal *j) { int r; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); if (j->inotify_fd >= 0) return j->inotify_fd; r = allocate_inotify(j); if (r < 0) return r; /* Iterate through all dirs again, to add them to the * inotify */ if (j->no_new_files) r = add_current_paths(j); else if (j->path) r = add_root_directory(j, j->path, true); else r = add_search_paths(j); if (r < 0) return r; return j->inotify_fd; } _public_ int sd_journal_get_events(sd_journal *j) { int fd; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); fd = sd_journal_get_fd(j); if (fd < 0) return fd; return POLLIN; } _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) { int fd; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(timeout_usec, -EINVAL); fd = sd_journal_get_fd(j); if (fd < 0) return fd; if (!j->on_network) { *timeout_usec = (uint64_t) -1; return 0; } /* If we are on the network we need to regularly check for * changes manually */ *timeout_usec = j->last_process_usec + JOURNAL_FILES_RECHECK_USEC; return 1; } static void process_inotify_event(sd_journal *j, struct inotify_event *e) { Directory *d; assert(j); assert(e); /* Is this a subdirectory we watch? */ d = hashmap_get(j->directories_by_wd, INT_TO_PTR(e->wd)); if (d) { sd_id128_t id; if (!(e->mask & IN_ISDIR) && e->len > 0 && (endswith(e->name, ".journal") || endswith(e->name, ".journal~"))) { /* Event for a journal file */ if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) (void) add_file(j, d->path, e->name); else if (e->mask & (IN_DELETE|IN_MOVED_FROM|IN_UNMOUNT)) remove_file(j, d->path, e->name); } else if (!d->is_root && e->len == 0) { /* Event for a subdirectory */ if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)) remove_directory(j, d); } else if (d->is_root && (e->mask & IN_ISDIR) && e->len > 0 && sd_id128_from_string(e->name, &id) >= 0) { /* Event for root directory */ if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) (void) add_directory(j, d->path, e->name); } return; } if (e->mask & IN_IGNORED) return; log_debug("Unknown inotify event."); } static int determine_change(sd_journal *j) { bool b; assert(j); b = j->current_invalidate_counter != j->last_invalidate_counter; j->last_invalidate_counter = j->current_invalidate_counter; return b ? SD_JOURNAL_INVALIDATE : SD_JOURNAL_APPEND; } _public_ int sd_journal_process(sd_journal *j) { bool got_something = false; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); j->last_process_usec = now(CLOCK_MONOTONIC); for (;;) { union inotify_event_buffer buffer; struct inotify_event *e; ssize_t l; l = read(j->inotify_fd, &buffer, sizeof(buffer)); if (l < 0) { if (errno == EAGAIN || errno == EINTR) return got_something ? determine_change(j) : SD_JOURNAL_NOP; return -errno; } got_something = true; FOREACH_INOTIFY_EVENT(e, buffer, l) process_inotify_event(j, e); } } _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { int r; uint64_t t; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); if (j->inotify_fd < 0) { /* This is the first invocation, hence create the * inotify watch */ r = sd_journal_get_fd(j); if (r < 0) return r; /* The journal might have changed since the context * object was created and we weren't watching before, * hence don't wait for anything, and return * immediately. */ return determine_change(j); } r = sd_journal_get_timeout(j, &t); if (r < 0) return r; if (t != (uint64_t) -1) { usec_t n; n = now(CLOCK_MONOTONIC); t = t > n ? t - n : 0; if (timeout_usec == (uint64_t) -1 || timeout_usec > t) timeout_usec = t; } do { r = fd_wait_for_event(j->inotify_fd, POLLIN, timeout_usec); } while (r == -EINTR); if (r < 0) return r; return sd_journal_process(j); } _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to) { Iterator i; JournalFile *f; bool first = true; uint64_t fmin = 0, tmax = 0; int r; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(from || to, -EINVAL); assert_return(from != to, -EINVAL); ORDERED_HASHMAP_FOREACH(f, j->files, i) { usec_t fr, t; r = journal_file_get_cutoff_realtime_usec(f, &fr, &t); if (r == -ENOENT) continue; if (r < 0) return r; if (r == 0) continue; if (first) { fmin = fr; tmax = t; first = false; } else { fmin = MIN(fr, fmin); tmax = MAX(t, tmax); } } if (from) *from = fmin; if (to) *to = tmax; return first ? 0 : 1; } _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t *from, uint64_t *to) { Iterator i; JournalFile *f; bool found = false; int r; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(from || to, -EINVAL); assert_return(from != to, -EINVAL); ORDERED_HASHMAP_FOREACH(f, j->files, i) { usec_t fr, t; r = journal_file_get_cutoff_monotonic_usec(f, boot_id, &fr, &t); if (r == -ENOENT) continue; if (r < 0) return r; if (r == 0) continue; if (found) { if (from) *from = MIN(fr, *from); if (to) *to = MAX(t, *to); } else { if (from) *from = fr; if (to) *to = t; found = true; } } return found; } void journal_print_header(sd_journal *j) { Iterator i; JournalFile *f; bool newline = false; assert(j); ORDERED_HASHMAP_FOREACH(f, j->files, i) { if (newline) putchar('\n'); else newline = true; journal_file_print_header(f); } } _public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) { Iterator i; JournalFile *f; uint64_t sum = 0; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(bytes, -EINVAL); ORDERED_HASHMAP_FOREACH(f, j->files, i) { struct stat st; if (fstat(f->fd, &st) < 0) return -errno; sum += (uint64_t) st.st_blocks * 512ULL; } *bytes = sum; return 0; } _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { char *f; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(!isempty(field), -EINVAL); assert_return(field_is_valid(field), -EINVAL); f = strdup(field); if (!f) return -ENOMEM; free(j->unique_field); j->unique_field = f; j->unique_file = NULL; j->unique_offset = 0; j->unique_file_lost = false; return 0; } _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l) { size_t k; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(data, -EINVAL); assert_return(l, -EINVAL); assert_return(j->unique_field, -EINVAL); k = strlen(j->unique_field); if (!j->unique_file) { if (j->unique_file_lost) return 0; j->unique_file = ordered_hashmap_first(j->files); if (!j->unique_file) return 0; j->unique_offset = 0; } for (;;) { JournalFile *of; Iterator i; Object *o; const void *odata; size_t ol; bool found; int r; /* Proceed to next data object in the field's linked list */ if (j->unique_offset == 0) { r = journal_file_find_field_object(j->unique_file, j->unique_field, k, &o, NULL); if (r < 0) return r; j->unique_offset = r > 0 ? le64toh(o->field.head_data_offset) : 0; } else { r = journal_file_move_to_object(j->unique_file, OBJECT_DATA, j->unique_offset, &o); if (r < 0) return r; j->unique_offset = le64toh(o->data.next_field_offset); } /* We reached the end of the list? Then start again, with the next file */ if (j->unique_offset == 0) { j->unique_file = ordered_hashmap_next(j->files, j->unique_file->path); if (!j->unique_file) return 0; continue; } /* We do not use OBJECT_DATA context here, but OBJECT_UNUSED * instead, so that we can look at this data object at the same * time as one on another file */ r = journal_file_move_to_object(j->unique_file, OBJECT_UNUSED, j->unique_offset, &o); if (r < 0) return r; /* Let's do the type check by hand, since we used 0 context above. */ if (o->object.type != OBJECT_DATA) { log_debug("%s:offset " OFSfmt ": object has type %d, expected %d", j->unique_file->path, j->unique_offset, o->object.type, OBJECT_DATA); return -EBADMSG; } r = return_data(j, j->unique_file, o, &odata, &ol); if (r < 0) return r; /* Check if we have at least the field name and "=". */ if (ol <= k) { log_debug("%s:offset " OFSfmt ": object has size %zu, expected at least %zu", j->unique_file->path, j->unique_offset, ol, k + 1); return -EBADMSG; } if (memcmp(odata, j->unique_field, k) || ((const char*) odata)[k] != '=') { log_debug("%s:offset " OFSfmt ": object does not start with \"%s=\"", j->unique_file->path, j->unique_offset, j->unique_field); return -EBADMSG; } /* OK, now let's see if we already returned this data * object by checking if it exists in the earlier * traversed files. */ found = false; ORDERED_HASHMAP_FOREACH(of, j->files, i) { if (of == j->unique_file) break; /* Skip this file it didn't have any fields indexed */ if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) && le64toh(of->header->n_fields) <= 0) continue; r = journal_file_find_data_object_with_hash(of, odata, ol, le64toh(o->data.hash), NULL, NULL); if (r < 0) return r; if (r > 0) { found = true; break; } } if (found) continue; r = return_data(j, j->unique_file, o, data, l); if (r < 0) return r; return 1; } } _public_ void sd_journal_restart_unique(sd_journal *j) { if (!j) return; j->unique_file = NULL; j->unique_offset = 0; j->unique_file_lost = false; } _public_ int sd_journal_enumerate_fields(sd_journal *j, const char **field) { int r; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(field, -EINVAL); if (!j->fields_file) { if (j->fields_file_lost) return 0; j->fields_file = ordered_hashmap_first(j->files); if (!j->fields_file) return 0; j->fields_hash_table_index = 0; j->fields_offset = 0; } for (;;) { JournalFile *f, *of; Iterator i; uint64_t m; Object *o; size_t sz; bool found; f = j->fields_file; if (j->fields_offset == 0) { bool eof = false; /* We are not yet positioned at any field. Let's pick the first one */ r = journal_file_map_field_hash_table(f); if (r < 0) return r; m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem); for (;;) { if (j->fields_hash_table_index >= m) { /* Reached the end of the hash table, go to the next file. */ eof = true; break; } j->fields_offset = le64toh(f->field_hash_table[j->fields_hash_table_index].head_hash_offset); if (j->fields_offset != 0) break; /* Empty hash table bucket, go to next one */ j->fields_hash_table_index++; } if (eof) { /* Proceed with next file */ j->fields_file = ordered_hashmap_next(j->files, f->path); if (!j->fields_file) { *field = NULL; return 0; } j->fields_offset = 0; j->fields_hash_table_index = 0; continue; } } else { /* We are already positioned at a field. If so, let's figure out the next field from it */ r = journal_file_move_to_object(f, OBJECT_FIELD, j->fields_offset, &o); if (r < 0) return r; j->fields_offset = le64toh(o->field.next_hash_offset); if (j->fields_offset == 0) { /* Reached the end of the hash table chain */ j->fields_hash_table_index++; continue; } } /* We use OBJECT_UNUSED here, so that the iterator below doesn't remove our mmap window */ r = journal_file_move_to_object(f, OBJECT_UNUSED, j->fields_offset, &o); if (r < 0) return r; /* Because we used OBJECT_UNUSED above, we need to do our type check manually */ if (o->object.type != OBJECT_FIELD) { log_debug("%s:offset " OFSfmt ": object has type %i, expected %i", f->path, j->fields_offset, o->object.type, OBJECT_FIELD); return -EBADMSG; } sz = le64toh(o->object.size) - offsetof(Object, field.payload); /* Let's see if we already returned this field name before. */ found = false; ORDERED_HASHMAP_FOREACH(of, j->files, i) { if (of == f) break; /* Skip this file it didn't have any fields indexed */ if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) && le64toh(of->header->n_fields) <= 0) continue; r = journal_file_find_field_object_with_hash(of, o->field.payload, sz, le64toh(o->field.hash), NULL, NULL); if (r < 0) return r; if (r > 0) { found = true; break; } } if (found) continue; /* Check if this is really a valid string containing no NUL byte */ if (memchr(o->field.payload, 0, sz)) return -EBADMSG; if (sz > j->data_threshold) sz = j->data_threshold; if (!GREEDY_REALLOC(j->fields_buffer, j->fields_buffer_allocated, sz + 1)) return -ENOMEM; memcpy(j->fields_buffer, o->field.payload, sz); j->fields_buffer[sz] = 0; if (!field_is_valid(j->fields_buffer)) return -EBADMSG; *field = j->fields_buffer; return 1; } } _public_ void sd_journal_restart_fields(sd_journal *j) { if (!j) return; j->fields_file = NULL; j->fields_hash_table_index = 0; j->fields_offset = 0; j->fields_file_lost = false; } _public_ int sd_journal_reliable_fd(sd_journal *j) { assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); return !j->on_network; } static char *lookup_field(const char *field, void *userdata) { sd_journal *j = userdata; const void *data; size_t size, d; int r; assert(field); assert(j); r = sd_journal_get_data(j, field, &data, &size); if (r < 0 || size > REPLACE_VAR_MAX) return strdup(field); d = strlen(field) + 1; return strndup((const char*) data + d, size - d); } _public_ int sd_journal_get_catalog(sd_journal *j, char **ret) { const void *data; size_t size; sd_id128_t id; _cleanup_free_ char *text = NULL, *cid = NULL; char *t; int r; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(ret, -EINVAL); r = sd_journal_get_data(j, "MESSAGE_ID", &data, &size); if (r < 0) return r; cid = strndup((const char*) data + 11, size - 11); if (!cid) return -ENOMEM; r = sd_id128_from_string(cid, &id); if (r < 0) return r; r = catalog_get(CATALOG_DATABASE, id, &text); if (r < 0) return r; t = replace_var(text, lookup_field, j); if (!t) return -ENOMEM; *ret = t; return 0; } _public_ int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **ret) { assert_return(ret, -EINVAL); return catalog_get(CATALOG_DATABASE, id, ret); } _public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) { assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); j->data_threshold = sz; return 0; } _public_ int sd_journal_get_data_threshold(sd_journal *j, size_t *sz) { assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); assert_return(sz, -EINVAL); *sz = j->data_threshold; return 0; } _public_ int sd_journal_has_runtime_files(sd_journal *j) { assert_return(j, -EINVAL); return j->has_runtime_files; } _public_ int sd_journal_has_persistent_files(sd_journal *j) { assert_return(j, -EINVAL); return j->has_persistent_files; } systemd-229/src/journal/test-audit-type.c000066400000000000000000000023371265713322000205350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "audit-type.h" static void print_audit_label(int i) { const char *name; name = audit_type_name_alloca(i); /* This is a separate function only because of alloca */ printf("%i → %s → %s\n", i, audit_type_to_string(i), name); } static void test_audit_type(void) { int i; for (i = 0; i <= AUDIT_KERNEL; i++) print_audit_label(i); } int main(int argc, char **argv) { test_audit_type(); } systemd-229/src/journal/test-catalog.c000066400000000000000000000157331265713322000200660ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-messages.h" #include "alloc-util.h" #include "catalog.h" #include "fd-util.h" #include "fileio.h" #include "log.h" #include "macro.h" #include "string-util.h" #include "util.h" static const char *catalog_dirs[] = { CATALOG_DIR, NULL, }; static const char *no_catalog_dirs[] = { "/bin/hopefully/with/no/catalog", NULL }; static Hashmap * test_import(const char* contents, ssize_t size, int code) { int r; char name[] = "/tmp/test-catalog.XXXXXX"; _cleanup_close_ int fd; Hashmap *h; if (size < 0) size = strlen(contents); assert_se(h = hashmap_new(&catalog_hash_ops)); fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(write(fd, contents, size) == size); r = catalog_import_file(h, name); assert_se(r == code); unlink(name); return h; } static void test_catalog_import_invalid(void) { _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; h = test_import("xxx", -1, -EINVAL); assert_se(hashmap_isempty(h)); } static void test_catalog_import_badid(void) { _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; const char *input = "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededede\n" \ "Subject: message\n" \ "\n" \ "payload\n"; h = test_import(input, -1, -EINVAL); } static void test_catalog_import_one(void) { _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; char *payload; Iterator j; const char *input = "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ "Subject: message\n" \ "\n" \ "payload\n"; const char *expect = "Subject: message\n" \ "\n" \ "payload\n"; h = test_import(input, -1, 0); assert_se(hashmap_size(h) == 1); HASHMAP_FOREACH(payload, h, j) { assert_se(streq(expect, payload)); } } static void test_catalog_import_merge(void) { _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; char *payload; Iterator j; const char *input = "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ "Subject: message\n" \ "Defined-By: me\n" \ "\n" \ "payload\n" \ "\n" \ "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ "Subject: override subject\n" \ "X-Header: hello\n" \ "\n" \ "override payload\n"; const char *combined = "Subject: override subject\n" \ "X-Header: hello\n" \ "Subject: message\n" \ "Defined-By: me\n" \ "\n" \ "override payload\n"; h = test_import(input, -1, 0); assert_se(hashmap_size(h) == 1); HASHMAP_FOREACH(payload, h, j) { assert_se(streq(combined, payload)); } } static void test_catalog_import_merge_no_body(void) { _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; char *payload; Iterator j; const char *input = "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ "Subject: message\n" \ "Defined-By: me\n" \ "\n" \ "payload\n" \ "\n" \ "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ "Subject: override subject\n" \ "X-Header: hello\n" \ "\n"; const char *combined = "Subject: override subject\n" \ "X-Header: hello\n" \ "Subject: message\n" \ "Defined-By: me\n" \ "\n" \ "payload\n"; h = test_import(input, -1, 0); assert_se(hashmap_size(h) == 1); HASHMAP_FOREACH(payload, h, j) { assert_se(streq(combined, payload)); } } static const char* database = NULL; static void test_catalog_update(void) { static char name[] = "/tmp/test-catalog.XXXXXX"; int r; r = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(r >= 0); database = name; /* Test what happens if there are no files. */ r = catalog_update(database, NULL, NULL); assert_se(r >= 0); /* Test what happens if there are no files in the directory. */ r = catalog_update(database, NULL, no_catalog_dirs); assert_se(r >= 0); /* Make sure that we at least have some files loaded or the catalog_list below will fail. */ r = catalog_update(database, NULL, catalog_dirs); assert_se(r >= 0); } static void test_catalog_file_lang(void) { _cleanup_free_ char *lang = NULL, *lang2 = NULL, *lang3 = NULL, *lang4 = NULL; assert_se(catalog_file_lang("systemd.de_DE.catalog", &lang) == 1); assert_se(streq(lang, "de_DE")); assert_se(catalog_file_lang("systemd..catalog", &lang2) == 0); assert_se(lang2 == NULL); assert_se(catalog_file_lang("systemd.fr.catalog", &lang2) == 1); assert_se(streq(lang2, "fr")); assert_se(catalog_file_lang("systemd.fr.catalog.gz", &lang3) == 0); assert_se(lang3 == NULL); assert_se(catalog_file_lang("systemd.01234567890123456789012345678901.catalog", &lang3) == 0); assert_se(lang3 == NULL); assert_se(catalog_file_lang("systemd.0123456789012345678901234567890.catalog", &lang3) == 1); assert_se(streq(lang3, "0123456789012345678901234567890")); assert_se(catalog_file_lang("/x/y/systemd.catalog", &lang4) == 0); assert_se(lang4 == NULL); assert_se(catalog_file_lang("/x/y/systemd.ru_RU.catalog", &lang4) == 1); assert_se(streq(lang4, "ru_RU")); } int main(int argc, char *argv[]) { _cleanup_free_ char *text = NULL; int r; setlocale(LC_ALL, "de_DE.UTF-8"); log_parse_environment(); log_open(); test_catalog_file_lang(); test_catalog_import_invalid(); test_catalog_import_badid(); test_catalog_import_one(); test_catalog_import_merge(); test_catalog_import_merge_no_body(); test_catalog_update(); r = catalog_list(stdout, database, true); assert_se(r >= 0); r = catalog_list(stdout, database, false); assert_se(r >= 0); assert_se(catalog_get(database, SD_MESSAGE_COREDUMP, &text) >= 0); printf(">>>%s<<<\n", text); if (database) unlink(database); return 0; } systemd-229/src/journal/test-compress-benchmark.c000066400000000000000000000127771265713322000222440ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "compress.h" #include "macro.h" #include "parse-util.h" #include "random-util.h" #include "string-util.h" #include "util.h" typedef int (compress_t)(const void *src, uint64_t src_size, void *dst, size_t dst_alloc_size, size_t *dst_size); typedef int (decompress_t)(const void *src, uint64_t src_size, void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max); static usec_t arg_duration = 2 * USEC_PER_SEC; static size_t arg_start; #define MAX_SIZE (1024*1024LU) #define PRIME 1048571 /* A prime close enough to one megabyte that mod 4 == 3 */ static size_t _permute(size_t x) { size_t residue; if (x >= PRIME) return x; residue = x*x % PRIME; if (x <= PRIME / 2) return residue; else return PRIME - residue; } static size_t permute(size_t x) { return _permute((_permute(x) + arg_start) % MAX_SIZE ^ 0xFF345); } static char* make_buf(size_t count, const char *type) { char *buf; size_t i; buf = malloc(count); assert_se(buf); if (streq(type, "zeros")) memzero(buf, count); else if (streq(type, "simple")) for (i = 0; i < count; i++) buf[i] = 'a' + i % ('z' - 'a' + 1); else if (streq(type, "random")) { size_t step = count / 10; random_bytes(buf, step); memzero(buf + 1*step, step); random_bytes(buf + 2*step, step); memzero(buf + 3*step, step); random_bytes(buf + 4*step, step); memzero(buf + 5*step, step); random_bytes(buf + 6*step, step); memzero(buf + 7*step, step); random_bytes(buf + 8*step, step); memzero(buf + 9*step, step); } else assert_not_reached("here"); return buf; } static void test_compress_decompress(const char* label, const char* type, compress_t compress, decompress_t decompress) { usec_t n, n2 = 0; float dt; _cleanup_free_ char *text, *buf; _cleanup_free_ void *buf2 = NULL; size_t buf2_allocated = 0; size_t skipped = 0, compressed = 0, total = 0; text = make_buf(MAX_SIZE, type); buf = calloc(MAX_SIZE + 1, 1); assert_se(text && buf); n = now(CLOCK_MONOTONIC); for (size_t i = 0; i <= MAX_SIZE; i++) { size_t j = 0, k = 0, size; int r; size = permute(i); log_debug("%s %zu %zu", type, i, size); memzero(buf, MIN(size + 1000, MAX_SIZE)); r = compress(text, size, buf, size, &j); /* assume compression must be successful except for small or random inputs */ assert_se(r == 0 || (size < 2048 && r == -ENOBUFS) || streq(type, "random")); /* check for overwrites */ assert_se(buf[size] == 0); if (r != 0) { skipped += size; continue; } assert_se(j > 0); if (j >= size) log_error("%s \"compressed\" %zu -> %zu", label, size, j); r = decompress(buf, j, &buf2, &buf2_allocated, &k, 0); assert_se(r == 0); assert_se(buf2_allocated >= k); assert_se(k == size); assert_se(memcmp(text, buf2, size) == 0); total += size; compressed += j; n2 = now(CLOCK_MONOTONIC); if (n2 - n > arg_duration) break; } dt = (n2-n) / 1e6; log_info("%s/%s: compressed & decompressed %zu bytes in %.2fs (%.2fMiB/s), " "mean compresion %.2f%%, skipped %zu bytes", label, type, total, dt, total / 1024. / 1024 / dt, 100 - compressed * 100. / total, skipped); } int main(int argc, char *argv[]) { const char *i; log_set_max_level(LOG_INFO); if (argc >= 2) { unsigned x; assert_se(safe_atou(argv[1], &x) >= 0); arg_duration = x * USEC_PER_SEC; } if (argc == 3) (void) safe_atolu(argv[2], &arg_start); else arg_start = getpid(); NULSTR_FOREACH(i, "zeros\0simple\0random\0") { #ifdef HAVE_XZ test_compress_decompress("XZ", i, compress_blob_xz, decompress_blob_xz); #endif #ifdef HAVE_LZ4 test_compress_decompress("LZ4", i, compress_blob_lz4, decompress_blob_lz4); #endif } return 0; } systemd-229/src/journal/test-compress.c000066400000000000000000000266421265713322000203100ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2014 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #ifdef HAVE_LZ4 #include #endif #include "alloc-util.h" #include "compress.h" #include "fd-util.h" #include "fileio.h" #include "macro.h" #include "random-util.h" #include "util.h" #ifdef HAVE_XZ # define XZ_OK 0 #else # define XZ_OK -EPROTONOSUPPORT #endif #ifdef HAVE_LZ4 # define LZ4_OK 0 #else # define LZ4_OK -EPROTONOSUPPORT #endif typedef int (compress_blob_t)(const void *src, uint64_t src_size, void *dst, size_t dst_alloc_size, size_t *dst_size); typedef int (decompress_blob_t)(const void *src, uint64_t src_size, void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max); typedef int (decompress_sw_t)(const void *src, uint64_t src_size, void **buffer, size_t *buffer_size, const void *prefix, size_t prefix_len, uint8_t extra); typedef int (compress_stream_t)(int fdf, int fdt, uint64_t max_bytes); typedef int (decompress_stream_t)(int fdf, int fdt, uint64_t max_size); static void test_compress_decompress(int compression, compress_blob_t compress, decompress_blob_t decompress, const char *data, size_t data_len, bool may_fail) { char compressed[512]; size_t csize, usize = 0; _cleanup_free_ char *decompressed = NULL; int r; log_info("/* testing %s %s blob compression/decompression */", object_compressed_to_string(compression), data); r = compress(data, data_len, compressed, sizeof(compressed), &csize); if (r == -ENOBUFS) { log_info_errno(r, "compression failed: %m"); assert_se(may_fail); } else { assert_se(r == 0); r = decompress(compressed, csize, (void **) &decompressed, &usize, &csize, 0); assert_se(r == 0); assert_se(decompressed); assert_se(memcmp(decompressed, data, data_len) == 0); } r = decompress("garbage", 7, (void **) &decompressed, &usize, &csize, 0); assert_se(r < 0); /* make sure to have the minimal lz4 compressed size */ r = decompress("00000000\1g", 9, (void **) &decompressed, &usize, &csize, 0); assert_se(r < 0); r = decompress("\100000000g", 9, (void **) &decompressed, &usize, &csize, 0); assert_se(r < 0); memzero(decompressed, usize); } static void test_decompress_startswith(int compression, compress_blob_t compress, decompress_sw_t decompress_sw, const char *data, size_t data_len, bool may_fail) { char *compressed; _cleanup_free_ char *compressed1 = NULL, *compressed2 = NULL, *decompressed = NULL; size_t csize, usize = 0, len; int r; log_info("/* testing decompress_startswith with %s on %.20s text*/", object_compressed_to_string(compression), data); #define BUFSIZE_1 512 #define BUFSIZE_2 20000 compressed = compressed1 = malloc(BUFSIZE_1); assert_se(compressed1); r = compress(data, data_len, compressed, BUFSIZE_1, &csize); if (r == -ENOBUFS) { log_info_errno(r, "compression failed: %m"); assert_se(may_fail); compressed = compressed2 = malloc(BUFSIZE_2); assert_se(compressed2); r = compress(data, data_len, compressed, BUFSIZE_2, &csize); assert(r == 0); } assert_se(r == 0); len = strlen(data); r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len, '\0'); assert_se(r > 0); r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len, 'w'); assert_se(r == 0); r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, "barbarbar", 9, ' '); assert_se(r == 0); r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len - 1, data[len-1]); assert_se(r > 0); r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len - 1, 'w'); assert_se(r == 0); r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len, '\0'); assert_se(r > 0); } static void test_compress_stream(int compression, const char* cat, compress_stream_t compress, decompress_stream_t decompress, const char *srcfile) { _cleanup_close_ int src = -1, dst = -1, dst2 = -1; char pattern[] = "/tmp/systemd-test.compressed.XXXXXX", pattern2[] = "/tmp/systemd-test.compressed.XXXXXX"; int r; _cleanup_free_ char *cmd = NULL, *cmd2; struct stat st = {}; log_debug("/* testing %s compression */", object_compressed_to_string(compression)); log_debug("/* create source from %s */", srcfile); assert_se((src = open(srcfile, O_RDONLY|O_CLOEXEC)) >= 0); log_debug("/* test compression */"); assert_se((dst = mkostemp_safe(pattern, O_RDWR|O_CLOEXEC)) >= 0); assert_se(compress(src, dst, -1) == 0); if (cat) { assert_se(asprintf(&cmd, "%s %s | diff %s -", cat, pattern, srcfile) > 0); assert_se(system(cmd) == 0); } log_debug("/* test decompression */"); assert_se((dst2 = mkostemp_safe(pattern2, O_RDWR|O_CLOEXEC)) >= 0); assert_se(stat(srcfile, &st) == 0); assert_se(lseek(dst, 0, SEEK_SET) == 0); r = decompress(dst, dst2, st.st_size); assert_se(r == 0); assert_se(asprintf(&cmd2, "diff %s %s", srcfile, pattern2) > 0); assert_se(system(cmd2) == 0); log_debug("/* test faulty decompression */"); assert_se(lseek(dst, 1, SEEK_SET) == 1); r = decompress(dst, dst2, st.st_size); assert_se(r == -EBADMSG || r == 0); assert_se(lseek(dst, 0, SEEK_SET) == 0); assert_se(lseek(dst2, 0, SEEK_SET) == 0); r = decompress(dst, dst2, st.st_size - 1); assert_se(r == -EFBIG); assert_se(unlink(pattern) == 0); assert_se(unlink(pattern2) == 0); } #ifdef HAVE_LZ4 static void test_lz4_decompress_partial(void) { char buf[20000]; size_t buf_size = sizeof(buf), compressed; int r; _cleanup_free_ char *huge = NULL; #define HUGE_SIZE (4096*1024) huge = malloc(HUGE_SIZE); memset(huge, 'x', HUGE_SIZE); memcpy(huge, "HUGE=", 5); r = LZ4_compress_limitedOutput(huge, buf, HUGE_SIZE, buf_size); assert_se(r >= 0); compressed = r; log_info("Compressed %i → %zu", HUGE_SIZE, compressed); r = LZ4_decompress_safe(buf, huge, r, HUGE_SIZE); assert_se(r >= 0); log_info("Decompressed → %i", r); r = LZ4_decompress_safe_partial(buf, huge, compressed, 12, HUGE_SIZE); assert_se(r >= 0); log_info("Decompressed partial %i/%i → %i", 12, HUGE_SIZE, r); /* We expect this to fail, because that's how current lz4 works. If this * call succeeds, then lz4 has been fixed, and we need to change our code. */ r = LZ4_decompress_safe_partial(buf, huge, compressed, 12, HUGE_SIZE-1); assert_se(r < 0); log_info("Decompressed partial %i/%i → %i", 12, HUGE_SIZE-1, r); } #endif int main(int argc, char *argv[]) { const char text[] = "text\0foofoofoofoo AAAA aaaaaaaaa ghost busters barbarbar FFF" "foofoofoofoo AAAA aaaaaaaaa ghost busters barbarbar FFF"; char data[512] = "random\0"; char huge[4096*1024]; memset(huge, 'x', sizeof(huge)); memcpy(huge, "HUGE=", 5); char_array_0(huge); log_set_max_level(LOG_DEBUG); random_bytes(data + 7, sizeof(data) - 7); #ifdef HAVE_XZ test_compress_decompress(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_blob_xz, text, sizeof(text), false); test_compress_decompress(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_blob_xz, data, sizeof(data), true); test_decompress_startswith(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_startswith_xz, text, sizeof(text), false); test_decompress_startswith(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_startswith_xz, data, sizeof(data), true); test_decompress_startswith(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_startswith_xz, huge, sizeof(huge), true); test_compress_stream(OBJECT_COMPRESSED_XZ, "xzcat", compress_stream_xz, decompress_stream_xz, argv[0]); #else log_info("/* XZ test skipped */"); #endif #ifdef HAVE_LZ4 test_compress_decompress(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_blob_lz4, text, sizeof(text), false); test_compress_decompress(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_blob_lz4, data, sizeof(data), true); test_decompress_startswith(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_startswith_lz4, text, sizeof(text), false); test_decompress_startswith(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_startswith_lz4, data, sizeof(data), true); test_decompress_startswith(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_startswith_lz4, huge, sizeof(huge), true); test_compress_stream(OBJECT_COMPRESSED_LZ4, "lz4cat", compress_stream_lz4, decompress_stream_lz4, argv[0]); test_lz4_decompress_partial(); #else log_info("/* LZ4 test skipped */"); #endif return 0; } systemd-229/src/journal/test-journal-enum.c000066400000000000000000000030011265713322000210510ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-journal.h" #include "journal-internal.h" #include "log.h" #include "macro.h" int main(int argc, char *argv[]) { unsigned n = 0; _cleanup_(sd_journal_closep) sd_journal*j = NULL; log_set_max_level(LOG_DEBUG); assert_se(sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY) >= 0); assert_se(sd_journal_add_match(j, "_TRANSPORT=syslog", 0) >= 0); assert_se(sd_journal_add_match(j, "_UID=0", 0) >= 0); SD_JOURNAL_FOREACH_BACKWARDS(j) { const void *d; size_t l; assert_se(sd_journal_get_data(j, "MESSAGE", &d, &l) >= 0); printf("%.*s\n", (int) l, (char*) d); n ++; if (n >= 10) break; } return 0; } systemd-229/src/journal/test-journal-flush.c000066400000000000000000000041351265713322000212370ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-journal.h" #include "alloc-util.h" #include "journal-file.h" #include "journal-internal.h" #include "macro.h" #include "string-util.h" int main(int argc, char *argv[]) { _cleanup_free_ char *fn = NULL; char dn[] = "/var/tmp/test-journal-flush.XXXXXX"; JournalFile *new_journal = NULL; sd_journal *j = NULL; unsigned n = 0; int r; assert_se(mkdtemp(dn)); fn = strappend(dn, "/test.journal"); r = journal_file_open(fn, O_CREAT|O_RDWR, 0644, false, false, NULL, NULL, NULL, &new_journal); assert_se(r >= 0); r = sd_journal_open(&j, 0); assert_se(r >= 0); sd_journal_set_data_threshold(j, 0); SD_JOURNAL_FOREACH(j) { Object *o; JournalFile *f; f = j->current_file; assert_se(f && f->current_offset > 0); r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); assert_se(r >= 0); r = journal_file_copy_entry(f, new_journal, o, f->current_offset, NULL, NULL, NULL); assert_se(r >= 0); n++; if (n > 10000) break; } sd_journal_close(j); journal_file_close(new_journal); unlink(fn); assert_se(rmdir(dn) == 0); return 0; } systemd-229/src/journal/test-journal-init.c000066400000000000000000000035011265713322000210550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-journal.h" #include "log.h" #include "parse-util.h" #include "rm-rf.h" #include "util.h" int main(int argc, char *argv[]) { sd_journal *j; int r, i, I = 100; char t[] = "/tmp/journal-stream-XXXXXX"; log_set_max_level(LOG_DEBUG); if (argc >= 2) { r = safe_atoi(argv[1], &I); if (r < 0) log_info("Could not parse loop count argument. Using default."); } log_info("Running %d loops", I); assert_se(mkdtemp(t)); for (i = 0; i < I; i++) { r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); assert_se(r == 0); sd_journal_close(j); r = sd_journal_open_directory(&j, t, 0); assert_se(r == 0); sd_journal_close(j); j = NULL; r = sd_journal_open_directory(&j, t, SD_JOURNAL_LOCAL_ONLY); assert_se(r == -EINVAL); assert_se(j == NULL); } assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); return 0; } systemd-229/src/journal/test-journal-interleaving.c000066400000000000000000000225161265713322000226100ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Marius Vollmer Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-journal.h" #include "alloc-util.h" #include "journal-file.h" #include "journal-vacuum.h" #include "log.h" #include "parse-util.h" #include "rm-rf.h" #include "util.h" /* This program tests skipping around in a multi-file journal. */ static bool arg_keep = false; noreturn static void log_assert_errno(const char *text, int eno, const char *file, int line, const char *func) { log_internal(LOG_CRIT, 0, file, line, func, "'%s' failed at %s:%u (%s): %s.", text, file, line, func, strerror(eno)); abort(); } #define assert_ret(expr) \ do { \ int _r_ = (expr); \ if (_unlikely_(_r_ < 0)) \ log_assert_errno(#expr, -_r_, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ } while (false) static JournalFile *test_open(const char *name) { JournalFile *f; assert_ret(journal_file_open(name, O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, NULL, &f)); return f; } static void test_close(JournalFile *f) { journal_file_close (f); } static void append_number(JournalFile *f, int n, uint64_t *seqnum) { char *p; dual_timestamp ts; static dual_timestamp previous_ts = {}; struct iovec iovec[1]; dual_timestamp_get(&ts); if (ts.monotonic <= previous_ts.monotonic) ts.monotonic = previous_ts.monotonic + 1; if (ts.realtime <= previous_ts.realtime) ts.realtime = previous_ts.realtime + 1; previous_ts = ts; assert_se(asprintf(&p, "NUMBER=%d", n) >= 0); iovec[0].iov_base = p; iovec[0].iov_len = strlen(p); assert_ret(journal_file_append_entry(f, &ts, iovec, 1, seqnum, NULL, NULL)); free(p); } static void test_check_number (sd_journal *j, int n) { const void *d; _cleanup_free_ char *k; size_t l; int x; assert_ret(sd_journal_get_data(j, "NUMBER", &d, &l)); assert_se(k = strndup(d, l)); printf("%s\n", k); assert_se(safe_atoi(k + 7, &x) >= 0); assert_se(n == x); } static void test_check_numbers_down (sd_journal *j, int count) { int i; for (i = 1; i <= count; i++) { int r; test_check_number(j, i); assert_ret(r = sd_journal_next(j)); if (i == count) assert_se(r == 0); else assert_se(r == 1); } } static void test_check_numbers_up (sd_journal *j, int count) { for (int i = count; i >= 1; i--) { int r; test_check_number(j, i); assert_ret(r = sd_journal_previous(j)); if (i == 1) assert_se(r == 0); else assert_se(r == 1); } } static void setup_sequential(void) { JournalFile *one, *two; one = test_open("one.journal"); two = test_open("two.journal"); append_number(one, 1, NULL); append_number(one, 2, NULL); append_number(two, 3, NULL); append_number(two, 4, NULL); test_close(one); test_close(two); } static void setup_interleaved(void) { JournalFile *one, *two; one = test_open("one.journal"); two = test_open("two.journal"); append_number(one, 1, NULL); append_number(two, 2, NULL); append_number(one, 3, NULL); append_number(two, 4, NULL); test_close(one); test_close(two); } static void test_skip(void (*setup)(void)) { char t[] = "/tmp/journal-skip-XXXXXX"; sd_journal *j; int r; assert_se(mkdtemp(t)); assert_se(chdir(t) >= 0); setup(); /* Seek to head, iterate down. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_head(j)); assert_ret(sd_journal_next(j)); test_check_numbers_down(j, 4); sd_journal_close(j); /* Seek to tail, iterate up. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_tail(j)); assert_ret(sd_journal_previous(j)); test_check_numbers_up(j, 4); sd_journal_close(j); /* Seek to tail, skip to head, iterate down. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_tail(j)); assert_ret(r = sd_journal_previous_skip(j, 4)); assert_se(r == 4); test_check_numbers_down(j, 4); sd_journal_close(j); /* Seek to head, skip to tail, iterate up. */ assert_ret(sd_journal_open_directory(&j, t, 0)); assert_ret(sd_journal_seek_head(j)); assert_ret(r = sd_journal_next_skip(j, 4)); assert_se(r == 4); test_check_numbers_up(j, 4); sd_journal_close(j); log_info("Done..."); if (arg_keep) log_info("Not removing %s", t); else { journal_directory_vacuum(".", 3000000, 0, 0, NULL, true); assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); } puts("------------------------------------------------------------"); } static void test_sequence_numbers(void) { char t[] = "/tmp/journal-seq-XXXXXX"; JournalFile *one, *two; uint64_t seqnum = 0; sd_id128_t seqnum_id; assert_se(mkdtemp(t)); assert_se(chdir(t) >= 0); assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, NULL, &one) == 0); append_number(one, 1, &seqnum); printf("seqnum=%"PRIu64"\n", seqnum); assert_se(seqnum == 1); append_number(one, 2, &seqnum); printf("seqnum=%"PRIu64"\n", seqnum); assert_se(seqnum == 2); assert_se(one->header->state == STATE_ONLINE); assert_se(!sd_id128_equal(one->header->file_id, one->header->machine_id)); assert_se(!sd_id128_equal(one->header->file_id, one->header->boot_id)); assert_se(sd_id128_equal(one->header->file_id, one->header->seqnum_id)); memcpy(&seqnum_id, &one->header->seqnum_id, sizeof(sd_id128_t)); assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, one, &two) == 0); assert_se(two->header->state == STATE_ONLINE); assert_se(!sd_id128_equal(two->header->file_id, one->header->file_id)); assert_se(sd_id128_equal(one->header->machine_id, one->header->machine_id)); assert_se(sd_id128_equal(one->header->boot_id, one->header->boot_id)); assert_se(sd_id128_equal(one->header->seqnum_id, one->header->seqnum_id)); append_number(two, 3, &seqnum); printf("seqnum=%"PRIu64"\n", seqnum); assert_se(seqnum == 3); append_number(two, 4, &seqnum); printf("seqnum=%"PRIu64"\n", seqnum); assert_se(seqnum == 4); test_close(two); append_number(one, 5, &seqnum); printf("seqnum=%"PRIu64"\n", seqnum); assert_se(seqnum == 5); append_number(one, 6, &seqnum); printf("seqnum=%"PRIu64"\n", seqnum); assert_se(seqnum == 6); test_close(one); /* restart server */ seqnum = 0; assert_se(journal_file_open("two.journal", O_RDWR, 0, true, false, NULL, NULL, NULL, &two) == 0); assert_se(sd_id128_equal(two->header->seqnum_id, seqnum_id)); append_number(two, 7, &seqnum); printf("seqnum=%"PRIu64"\n", seqnum); assert_se(seqnum == 5); /* So..., here we have the same seqnum in two files with the * same seqnum_id. */ test_close(two); log_info("Done..."); if (arg_keep) log_info("Not removing %s", t); else { journal_directory_vacuum(".", 3000000, 0, 0, NULL, true); assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); } } int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); /* journal_file_open requires a valid machine id */ if (access("/etc/machine-id", F_OK) != 0) return EXIT_TEST_SKIP; arg_keep = argc > 1; test_skip(setup_sequential); test_skip(setup_interleaved); test_sequence_numbers(); return 0; } systemd-229/src/journal/test-journal-match.c000066400000000000000000000056151265713322000212160ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-journal.h" #include "alloc-util.h" #include "journal-internal.h" #include "log.h" #include "string-util.h" #include "util.h" int main(int argc, char *argv[]) { _cleanup_(sd_journal_closep) sd_journal*j = NULL; _cleanup_free_ char *t; log_set_max_level(LOG_DEBUG); assert_se(sd_journal_open(&j, 0) >= 0); assert_se(sd_journal_add_match(j, "foobar", 0) < 0); assert_se(sd_journal_add_match(j, "foobar=waldo", 0) < 0); assert_se(sd_journal_add_match(j, "", 0) < 0); assert_se(sd_journal_add_match(j, "=", 0) < 0); assert_se(sd_journal_add_match(j, "=xxxxx", 0) < 0); assert_se(sd_journal_add_match(j, "HALLO=WALDO", 0) >= 0); assert_se(sd_journal_add_match(j, "QUUX=mmmm", 0) >= 0); assert_se(sd_journal_add_match(j, "QUUX=xxxxx", 0) >= 0); assert_se(sd_journal_add_match(j, "HALLO=", 0) >= 0); assert_se(sd_journal_add_match(j, "QUUX=xxxxx", 0) >= 0); assert_se(sd_journal_add_match(j, "QUUX=yyyyy", 0) >= 0); assert_se(sd_journal_add_match(j, "PIFF=paff", 0) >= 0); assert_se(sd_journal_add_disjunction(j) >= 0); assert_se(sd_journal_add_match(j, "ONE=one", 0) >= 0); assert_se(sd_journal_add_match(j, "ONE=two", 0) >= 0); assert_se(sd_journal_add_match(j, "TWO=two", 0) >= 0); assert_se(sd_journal_add_conjunction(j) >= 0); assert_se(sd_journal_add_match(j, "L4_1=yes", 0) >= 0); assert_se(sd_journal_add_match(j, "L4_1=ok", 0) >= 0); assert_se(sd_journal_add_match(j, "L4_2=yes", 0) >= 0); assert_se(sd_journal_add_match(j, "L4_2=ok", 0) >= 0); assert_se(sd_journal_add_disjunction(j) >= 0); assert_se(sd_journal_add_match(j, "L3=yes", 0) >= 0); assert_se(sd_journal_add_match(j, "L3=ok", 0) >= 0); assert_se(t = journal_make_match_string(j)); printf("resulting match expression is: %s\n", t); assert_se(streq(t, "(((L3=ok OR L3=yes) OR ((L4_2=ok OR L4_2=yes) AND (L4_1=ok OR L4_1=yes))) AND ((TWO=two AND (ONE=two OR ONE=one)) OR (PIFF=paff AND (QUUX=yyyyy OR QUUX=xxxxx OR QUUX=mmmm) AND (HALLO= OR HALLO=WALDO))))")); return 0; } systemd-229/src/journal/test-journal-send.c000066400000000000000000000070601265713322000210470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-journal.h" #include "macro.h" int main(int argc, char *argv[]) { char huge[4096*1024]; /* utf-8 and non-utf-8, message-less and message-ful iovecs */ struct iovec graph1[] = { {(char*) "GRAPH=graph", strlen("GRAPH=graph")} }; struct iovec graph2[] = { {(char*) "GRAPH=graph\n", strlen("GRAPH=graph\n")} }; struct iovec message1[] = { {(char*) "MESSAGE=graph", strlen("MESSAGE=graph")} }; struct iovec message2[] = { {(char*) "MESSAGE=graph\n", strlen("MESSAGE=graph\n")} }; assert_se(sd_journal_print(LOG_INFO, "piepapo") == 0); assert_se(sd_journal_send("MESSAGE=foobar", "VALUE=%i", 7, NULL) == 0); errno = ENOENT; assert_se(sd_journal_perror("Foobar") == 0); assert_se(sd_journal_perror("") == 0); memset(huge, 'x', sizeof(huge)); memcpy(huge, "HUGE=", 5); char_array_0(huge); assert_se(sd_journal_send("MESSAGE=Huge field attached", huge, NULL) == 0); assert_se(sd_journal_send("MESSAGE=uiui", "VALUE=A", "VALUE=B", "VALUE=C", "SINGLETON=1", "OTHERVALUE=X", "OTHERVALUE=Y", "WITH_BINARY=this is a binary value \a", NULL) == 0); syslog(LOG_NOTICE, "Hello World!"); assert_se(sd_journal_print(LOG_NOTICE, "Hello World") == 0); assert_se(sd_journal_send("MESSAGE=Hello World!", "MESSAGE_ID=52fb62f99e2c49d89cfbf9d6de5e3555", "PRIORITY=5", "HOME=%s", getenv("HOME"), "TERM=%s", getenv("TERM"), "PAGE_SIZE=%li", sysconf(_SC_PAGESIZE), "N_CPUS=%li", sysconf(_SC_NPROCESSORS_ONLN), NULL) == 0); assert_se(sd_journal_sendv(graph1, 1) == 0); assert_se(sd_journal_sendv(graph2, 1) == 0); assert_se(sd_journal_sendv(message1, 1) == 0); assert_se(sd_journal_sendv(message2, 1) == 0); /* test without location fields */ #undef sd_journal_sendv assert_se(sd_journal_sendv(graph1, 1) == 0); assert_se(sd_journal_sendv(graph2, 1) == 0); assert_se(sd_journal_sendv(message1, 1) == 0); assert_se(sd_journal_sendv(message2, 1) == 0); sleep(1); return 0; } systemd-229/src/journal/test-journal-stream.c000066400000000000000000000143441265713322000214140ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-journal.h" #include "alloc-util.h" #include "journal-file.h" #include "journal-internal.h" #include "log.h" #include "macro.h" #include "parse-util.h" #include "rm-rf.h" #include "util.h" #define N_ENTRIES 200 static void verify_contents(sd_journal *j, unsigned skip) { unsigned i; assert_se(j); i = 0; SD_JOURNAL_FOREACH(j) { const void *d; char *k, *c; size_t l; unsigned u = 0; assert_se(sd_journal_get_cursor(j, &k) >= 0); printf("cursor: %s\n", k); free(k); assert_se(sd_journal_get_data(j, "MAGIC", &d, &l) >= 0); printf("\t%.*s\n", (int) l, (const char*) d); assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0); assert_se(k = strndup(d, l)); printf("\t%s\n", k); if (skip > 0) { assert_se(safe_atou(k + 7, &u) >= 0); assert_se(i == u); i += skip; } free(k); assert_se(sd_journal_get_cursor(j, &c) >= 0); assert_se(sd_journal_test_cursor(j, c) > 0); free(c); } if (skip > 0) assert_se(i == N_ENTRIES); } int main(int argc, char *argv[]) { JournalFile *one, *two, *three; char t[] = "/tmp/journal-stream-XXXXXX"; unsigned i; _cleanup_(sd_journal_closep) sd_journal *j = NULL; char *z; const void *data; size_t l; dual_timestamp previous_ts = DUAL_TIMESTAMP_NULL; /* journal_file_open requires a valid machine id */ if (access("/etc/machine-id", F_OK) != 0) return EXIT_TEST_SKIP; log_set_max_level(LOG_DEBUG); assert_se(mkdtemp(t)); assert_se(chdir(t) >= 0); assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &one) == 0); assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &two) == 0); assert_se(journal_file_open("three.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &three) == 0); for (i = 0; i < N_ENTRIES; i++) { char *p, *q; dual_timestamp ts; struct iovec iovec[2]; dual_timestamp_get(&ts); if (ts.monotonic <= previous_ts.monotonic) ts.monotonic = previous_ts.monotonic + 1; if (ts.realtime <= previous_ts.realtime) ts.realtime = previous_ts.realtime + 1; previous_ts = ts; assert_se(asprintf(&p, "NUMBER=%u", i) >= 0); iovec[0].iov_base = p; iovec[0].iov_len = strlen(p); assert_se(asprintf(&q, "MAGIC=%s", i % 5 == 0 ? "quux" : "waldo") >= 0); iovec[1].iov_base = q; iovec[1].iov_len = strlen(q); if (i % 10 == 0) assert_se(journal_file_append_entry(three, &ts, iovec, 2, NULL, NULL, NULL) == 0); else { if (i % 3 == 0) assert_se(journal_file_append_entry(two, &ts, iovec, 2, NULL, NULL, NULL) == 0); assert_se(journal_file_append_entry(one, &ts, iovec, 2, NULL, NULL, NULL) == 0); } free(p); free(q); } journal_file_close(one); journal_file_close(two); journal_file_close(three); assert_se(sd_journal_open_directory(&j, t, 0) >= 0); assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0); SD_JOURNAL_FOREACH_BACKWARDS(j) { _cleanup_free_ char *c; assert_se(sd_journal_get_data(j, "NUMBER", &data, &l) >= 0); printf("\t%.*s\n", (int) l, (const char*) data); assert_se(sd_journal_get_cursor(j, &c) >= 0); assert_se(sd_journal_test_cursor(j, c) > 0); } SD_JOURNAL_FOREACH(j) { _cleanup_free_ char *c; assert_se(sd_journal_get_data(j, "NUMBER", &data, &l) >= 0); printf("\t%.*s\n", (int) l, (const char*) data); assert_se(sd_journal_get_cursor(j, &c) >= 0); assert_se(sd_journal_test_cursor(j, c) > 0); } sd_journal_flush_matches(j); verify_contents(j, 1); printf("NEXT TEST\n"); assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0); assert_se(z = journal_make_match_string(j)); printf("resulting match expression is: %s\n", z); free(z); verify_contents(j, 5); printf("NEXT TEST\n"); sd_journal_flush_matches(j); assert_se(sd_journal_add_match(j, "MAGIC=waldo", 0) >= 0); assert_se(sd_journal_add_match(j, "NUMBER=10", 0) >= 0); assert_se(sd_journal_add_match(j, "NUMBER=11", 0) >= 0); assert_se(sd_journal_add_match(j, "NUMBER=12", 0) >= 0); assert_se(z = journal_make_match_string(j)); printf("resulting match expression is: %s\n", z); free(z); verify_contents(j, 0); assert_se(sd_journal_query_unique(j, "NUMBER") >= 0); SD_JOURNAL_FOREACH_UNIQUE(j, data, l) printf("%.*s\n", (int) l, (const char*) data); assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); return 0; } systemd-229/src/journal/test-journal-syslog.c000066400000000000000000000027761265713322000214470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "journald-syslog.h" #include "macro.h" #include "string-util.h" static void test_syslog_parse_identifier(const char* str, const char *ident, const char*pid, int ret) { const char *buf = str; _cleanup_free_ char *ident2 = NULL, *pid2 = NULL; int ret2; ret2 = syslog_parse_identifier(&buf, &ident2, &pid2); assert_se(ret == ret2); assert_se(ident == ident2 || streq_ptr(ident, ident2)); assert_se(pid == pid2 || streq_ptr(pid, pid2)); } int main(void) { test_syslog_parse_identifier("pidu[111]: xxx", "pidu", "111", 11); test_syslog_parse_identifier("pidu: xxx", "pidu", NULL, 6); test_syslog_parse_identifier("pidu xxx", NULL, NULL, 0); return 0; } systemd-229/src/journal/test-journal-verify.c000066400000000000000000000107051265713322000214220ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "fd-util.h" #include "journal-file.h" #include "journal-verify.h" #include "log.h" #include "rm-rf.h" #include "terminal-util.h" #include "util.h" #define N_ENTRIES 6000 #define RANDOM_RANGE 77 static void bit_toggle(const char *fn, uint64_t p) { uint8_t b; ssize_t r; int fd; fd = open(fn, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); r = pread(fd, &b, 1, p/8); assert_se(r == 1); b ^= 1 << (p % 8); r = pwrite(fd, &b, 1, p/8); assert_se(r == 1); safe_close(fd); } static int raw_verify(const char *fn, const char *verification_key) { JournalFile *f; int r; r = journal_file_open(fn, O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f); if (r < 0) return r; r = journal_file_verify(f, verification_key, NULL, NULL, NULL, false); journal_file_close(f); return r; } int main(int argc, char *argv[]) { char t[] = "/tmp/journal-XXXXXX"; unsigned n; JournalFile *f; const char *verification_key = argv[1]; usec_t from = 0, to = 0, total = 0; char a[FORMAT_TIMESTAMP_MAX]; char b[FORMAT_TIMESTAMP_MAX]; char c[FORMAT_TIMESPAN_MAX]; struct stat st; uint64_t p; /* journal_file_open requires a valid machine id */ if (access("/etc/machine-id", F_OK) != 0) return EXIT_TEST_SKIP; log_set_max_level(LOG_DEBUG); assert_se(mkdtemp(t)); assert_se(chdir(t) >= 0); log_info("Generating..."); assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0); for (n = 0; n < N_ENTRIES; n++) { struct iovec iovec; struct dual_timestamp ts; char *test; dual_timestamp_get(&ts); assert_se(asprintf(&test, "RANDOM=%lu", random() % RANDOM_RANGE)); iovec.iov_base = (void*) test; iovec.iov_len = strlen(test); assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0); free(test); } journal_file_close(f); log_info("Verifying..."); assert_se(journal_file_open("test.journal", O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0); /* journal_file_print_header(f); */ journal_file_dump(f); assert_se(journal_file_verify(f, verification_key, &from, &to, &total, true) >= 0); if (verification_key && JOURNAL_HEADER_SEALED(f->header)) log_info("=> Validated from %s to %s, %s missing", format_timestamp(a, sizeof(a), from), format_timestamp(b, sizeof(b), to), format_timespan(c, sizeof(c), total > to ? total - to : 0, 0)); journal_file_close(f); if (verification_key) { log_info("Toggling bits..."); assert_se(stat("test.journal", &st) >= 0); for (p = 38448*8+0; p < ((uint64_t) st.st_size * 8); p ++) { bit_toggle("test.journal", p); log_info("[ %"PRIu64"+%"PRIu64"]", p / 8, p % 8); if (raw_verify("test.journal", verification_key) >= 0) log_notice(ANSI_HIGHLIGHT_RED ">>>> %"PRIu64" (bit %"PRIu64") can be toggled without detection." ANSI_NORMAL, p / 8, p % 8); bit_toggle("test.journal", p); } } log_info("Exiting..."); assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); return 0; } systemd-229/src/journal/test-journal.c000066400000000000000000000137521265713322000201250ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "journal-authenticate.h" #include "journal-file.h" #include "journal-vacuum.h" #include "log.h" #include "rm-rf.h" static bool arg_keep = false; static void test_non_empty(void) { dual_timestamp ts; JournalFile *f; struct iovec iovec; static const char test[] = "TEST1=1", test2[] = "TEST2=2"; Object *o; uint64_t p; char t[] = "/tmp/journal-XXXXXX"; log_set_max_level(LOG_DEBUG); assert_se(mkdtemp(t)); assert_se(chdir(t) >= 0); assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, &f) == 0); dual_timestamp_get(&ts); iovec.iov_base = (void*) test; iovec.iov_len = strlen(test); assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0); iovec.iov_base = (void*) test2; iovec.iov_len = strlen(test2); assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0); iovec.iov_base = (void*) test; iovec.iov_len = strlen(test); assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0); #ifdef HAVE_GCRYPT journal_file_append_tag(f); #endif journal_file_dump(f); assert_se(journal_file_next_entry(f, 0, DIRECTION_DOWN, &o, &p) == 1); assert_se(le64toh(o->entry.seqnum) == 1); assert_se(journal_file_next_entry(f, p, DIRECTION_DOWN, &o, &p) == 1); assert_se(le64toh(o->entry.seqnum) == 2); assert_se(journal_file_next_entry(f, p, DIRECTION_DOWN, &o, &p) == 1); assert_se(le64toh(o->entry.seqnum) == 3); assert_se(journal_file_next_entry(f, p, DIRECTION_DOWN, &o, &p) == 0); assert_se(journal_file_next_entry(f, 0, DIRECTION_DOWN, &o, &p) == 1); assert_se(le64toh(o->entry.seqnum) == 1); assert_se(journal_file_find_data_object(f, test, strlen(test), NULL, &p) == 1); assert_se(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1); assert_se(le64toh(o->entry.seqnum) == 1); assert_se(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1); assert_se(le64toh(o->entry.seqnum) == 3); assert_se(journal_file_find_data_object(f, test2, strlen(test2), NULL, &p) == 1); assert_se(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1); assert_se(le64toh(o->entry.seqnum) == 2); assert_se(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1); assert_se(le64toh(o->entry.seqnum) == 2); assert_se(journal_file_find_data_object(f, "quux", 4, NULL, &p) == 0); assert_se(journal_file_move_to_entry_by_seqnum(f, 1, DIRECTION_DOWN, &o, NULL) == 1); assert_se(le64toh(o->entry.seqnum) == 1); assert_se(journal_file_move_to_entry_by_seqnum(f, 3, DIRECTION_DOWN, &o, NULL) == 1); assert_se(le64toh(o->entry.seqnum) == 3); assert_se(journal_file_move_to_entry_by_seqnum(f, 2, DIRECTION_DOWN, &o, NULL) == 1); assert_se(le64toh(o->entry.seqnum) == 2); assert_se(journal_file_move_to_entry_by_seqnum(f, 10, DIRECTION_DOWN, &o, NULL) == 0); journal_file_rotate(&f, true, true); journal_file_rotate(&f, true, true); journal_file_close(f); log_info("Done..."); if (arg_keep) log_info("Not removing %s", t); else { journal_directory_vacuum(".", 3000000, 0, 0, NULL, true); assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); } puts("------------------------------------------------------------"); } static void test_empty(void) { JournalFile *f1, *f2, *f3, *f4; char t[] = "/tmp/journal-XXXXXX"; log_set_max_level(LOG_DEBUG); assert_se(mkdtemp(t)); assert_se(chdir(t) >= 0); assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, false, false, NULL, NULL, NULL, &f1) == 0); assert_se(journal_file_open("test-compress.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &f2) == 0); assert_se(journal_file_open("test-seal.journal", O_RDWR|O_CREAT, 0666, false, true, NULL, NULL, NULL, &f3) == 0); assert_se(journal_file_open("test-seal-compress.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, &f4) == 0); journal_file_print_header(f1); puts(""); journal_file_print_header(f2); puts(""); journal_file_print_header(f3); puts(""); journal_file_print_header(f4); puts(""); log_info("Done..."); if (arg_keep) log_info("Not removing %s", t); else { journal_directory_vacuum(".", 3000000, 0, 0, NULL, true); assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); } journal_file_close(f1); journal_file_close(f2); journal_file_close(f3); journal_file_close(f4); } int main(int argc, char *argv[]) { arg_keep = argc > 1; /* journal_file_open requires a valid machine id */ if (access("/etc/machine-id", F_OK) != 0) return EXIT_TEST_SKIP; test_non_empty(); test_empty(); return 0; } systemd-229/src/journal/test-mmap-cache.c000066400000000000000000000043311265713322000204370ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "fd-util.h" #include "fileio.h" #include "macro.h" #include "mmap-cache.h" #include "util.h" int main(int argc, char *argv[]) { int x, y, z, r; char px[] = "/tmp/testmmapXXXXXXX", py[] = "/tmp/testmmapYXXXXXX", pz[] = "/tmp/testmmapZXXXXXX"; MMapCache *m; void *p, *q; assert_se(m = mmap_cache_new()); x = mkostemp_safe(px, O_RDWR|O_CLOEXEC); assert_se(x >= 0); unlink(px); y = mkostemp_safe(py, O_RDWR|O_CLOEXEC); assert_se(y >= 0); unlink(py); z = mkostemp_safe(pz, O_RDWR|O_CLOEXEC); assert_se(z >= 0); unlink(pz); r = mmap_cache_get(m, x, PROT_READ, 0, false, 1, 2, NULL, &p); assert_se(r >= 0); r = mmap_cache_get(m, x, PROT_READ, 0, false, 2, 2, NULL, &q); assert_se(r >= 0); assert_se((uint8_t*) p + 1 == (uint8_t*) q); r = mmap_cache_get(m, x, PROT_READ, 1, false, 3, 2, NULL, &q); assert_se(r >= 0); assert_se((uint8_t*) p + 2 == (uint8_t*) q); r = mmap_cache_get(m, x, PROT_READ, 0, false, 16ULL*1024ULL*1024ULL, 2, NULL, &p); assert_se(r >= 0); r = mmap_cache_get(m, x, PROT_READ, 1, false, 16ULL*1024ULL*1024ULL+1, 2, NULL, &q); assert_se(r >= 0); assert_se((uint8_t*) p + 1 == (uint8_t*) q); mmap_cache_unref(m); safe_close(x); safe_close(y); safe_close(z); return 0; } systemd-229/src/kernel-install/000077500000000000000000000000001265713322000165745ustar00rootroot00000000000000systemd-229/src/kernel-install/50-depmod.install000066400000000000000000000002771265713322000216640ustar00rootroot00000000000000#!/bin/bash # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh [[ $1 == "add" ]] || exit 0 [[ $2 ]] || exit 1 exec depmod -a "$2" systemd-229/src/kernel-install/90-loaderentry.install000066400000000000000000000037601265713322000227500ustar00rootroot00000000000000#!/bin/bash # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh COMMAND="$1" KERNEL_VERSION="$2" BOOT_DIR_ABS="$3" KERNEL_IMAGE="$4" if [[ -f /etc/machine-id ]]; then read MACHINE_ID < /etc/machine-id fi if ! [[ $MACHINE_ID ]]; then exit 1 fi BOOT_DIR="/$MACHINE_ID/$KERNEL_VERSION" LOADER_ENTRY="/boot/loader/entries/$MACHINE_ID-$KERNEL_VERSION.conf" if [[ $COMMAND == remove ]]; then exec rm -f "$LOADER_ENTRY" fi if ! [[ $COMMAND == add ]]; then exit 1 fi if ! [[ $KERNEL_IMAGE ]]; then exit 1 fi if [[ -f /etc/os-release ]]; then . /etc/os-release elif [[ -f /usr/lib/os-release ]]; then . /usr/lib/os-release fi if ! [[ $PRETTY_NAME ]]; then PRETTY_NAME="Linux $KERNEL_VERSION" fi declare -a BOOT_OPTIONS if [[ -f /etc/kernel/cmdline ]]; then read -r -d '' -a BOOT_OPTIONS < /etc/kernel/cmdline fi if ! [[ ${BOOT_OPTIONS[*]} ]]; then read -r -d '' -a line < /proc/cmdline for i in "${line[@]}"; do [[ "${i#initrd=*}" != "$i" ]] && continue BOOT_OPTIONS+=("$i") done fi if ! [[ ${BOOT_OPTIONS[*]} ]]; then echo "Could not determine the kernel command line parameters." >&2 echo "Please specify the kernel command line in /etc/kernel/cmdline!" >&2 exit 1 fi cp "$KERNEL_IMAGE" "$BOOT_DIR_ABS/linux" && chown root:root "$BOOT_DIR_ABS/linux" && chmod 0644 "$BOOT_DIR_ABS/linux" || { echo "Could not copy '$KERNEL_IMAGE to '$BOOT_DIR_ABS/linux'." >&2 exit 1 } mkdir -p "${LOADER_ENTRY%/*}" || { echo "Could not create loader entry directory '${LOADER_ENTRY%/*}'." >&2 exit 1 } { echo "title $PRETTY_NAME" echo "version $KERNEL_VERSION" echo "machine-id $MACHINE_ID" echo "options ${BOOT_OPTIONS[*]}" echo "linux $BOOT_DIR/linux" [[ -f $BOOT_DIR_ABS/initrd ]] && \ echo "initrd $BOOT_DIR/initrd" : } > "$LOADER_ENTRY" || { echo "Could not create loader entry '$LOADER_ENTRY'." >&2 exit 1 } exit 0 systemd-229/src/kernel-install/Makefile000077700000000000000000000000001265713322000221022../Makefileustar00rootroot00000000000000systemd-229/src/kernel-install/kernel-install000066400000000000000000000061421265713322000214460ustar00rootroot00000000000000#!/bin/bash # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh # # This file is part of systemd. # # Copyright 2013 Harald Hoyer # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . usage() { echo "Usage:" echo " $0 add KERNEL-VERSION KERNEL-IMAGE" echo " $0 remove KERNEL-VERSION" } dropindirs_sort() { local suffix=$1; shift local -a files local f d i readarray -t files < <( for d in "$@"; do for i in "$d/"*"$suffix"; do if [[ -e "$i" ]]; then echo "${i##*/}" fi done done | sort -Vu ) for f in "${files[@]}"; do for d in "$@"; do if [[ -e "$d/$f" ]]; then echo "$d/$f" continue 2 fi done done } export LC_COLLATE=C for i in "$@"; do if [ "$i" == "--help" -o "$i" == "-h" ]; then usage exit 0 fi done if [[ "${0##*/}" == 'installkernel' ]]; then COMMAND='add' else COMMAND="$1" shift fi KERNEL_VERSION="$1" KERNEL_IMAGE="$2" if [[ -f /etc/machine-id ]]; then read MACHINE_ID < /etc/machine-id fi if ! [[ $MACHINE_ID ]]; then echo "Could not determine your machine ID from /etc/machine-id." >&2 echo "Please run 'systemd-machine-id-setup' as root. See man:machine-id(5)" >&2 exit 1 fi if [[ ! $COMMAND ]] || [[ ! $KERNEL_VERSION ]]; then echo "Not enough arguments" >&2 exit 1 fi BOOT_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION" ret=0 readarray -t PLUGINS < <( dropindirs_sort ".install" \ "/etc/kernel/install.d" \ "/usr/lib/kernel/install.d" ) case $COMMAND in add) if [[ ! "$KERNEL_IMAGE" ]]; then echo "Command 'add' requires an argument" >&2 exit 1 fi mkdir -p "$BOOT_DIR_ABS" || { echo "Could not create boot directory '$BOOT_DIR_ABS'." >&2 exit 1 } for f in "${PLUGINS[@]}"; do if [[ -x $f ]]; then "$f" add "$KERNEL_VERSION" "$BOOT_DIR_ABS" "$KERNEL_IMAGE" ((ret+=$?)) fi done ;; remove) for f in "${PLUGINS[@]}"; do if [[ -x $f ]]; then "$f" remove "$KERNEL_VERSION" "$BOOT_DIR_ABS" ((ret+=$?)) fi done rm -rf "$BOOT_DIR_ABS" ((ret+=$?)) ;; *) echo "Unknown command '$COMMAND'" >&2 exit 1 ;; esac exit $ret systemd-229/src/libsystemd-network/000077500000000000000000000000001265713322000175165ustar00rootroot00000000000000systemd-229/src/libsystemd-network/Makefile000077700000000000000000000000001265713322000230242../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd-network/arp-util.c000066400000000000000000000207671265713322000214330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Axis Communications AB. All rights reserved. Copyright (C) 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "arp-util.h" #include "fd-util.h" #include "util.h" int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_addr *eth_mac) { struct sock_filter filter[] = { BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */ BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct ether_arp), 1, 0), /* packet >= arp packet ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_hrd)), /* A <- header */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPHRD_ETHER, 1, 0), /* header == ethernet ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_pro)), /* A <- protocol */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 1, 0), /* protocol == IP ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_hln)), /* A <- hardware address length */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, sizeof(struct ether_addr), 1, 0), /* length == sizeof(ether_addr)? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_pln)), /* A <- protocol address length */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, sizeof(struct in_addr), 1, 0), /* length == sizeof(in_addr) ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_op)), /* A <- operation */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REQUEST, 2, 0), /* protocol == request ? */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 1, 0), /* protocol == reply ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ /* Sender Hardware Address must be different from our own */ BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((uint32_t *) eth_mac))), /* A <- 4 bytes of client's MAC */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_sha)), /* A <- 4 bytes of SHA */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 6), /* A == 0 ? */ BPF_STMT(BPF_LD + BPF_IMM, htobe16(*((uint16_t *) (((char *) eth_mac) + 4)))), /* A <- remainder of client's MAC */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, arp_sha) + 4), /* A <- remainder of SHA */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ /* Sender Protocol Address or Target Protocol Address must be equal to the one we care about*/ BPF_STMT(BPF_LD + BPF_IMM, htobe32(address)), /* A <- clients IP */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_spa)), /* A <- SPA */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* X xor A */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ BPF_STMT(BPF_LD + BPF_IMM, htobe32(address)), /* A <- clients IP */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_tpa)), /* A <- TPA */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* X xor A */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ }; struct sock_fprog fprog = { .len = ELEMENTSOF(filter), .filter = (struct sock_filter*) filter }; union sockaddr_union link = { .ll.sll_family = AF_PACKET, .ll.sll_protocol = htons(ETH_P_ARP), .ll.sll_ifindex = ifindex, .ll.sll_halen = ETH_ALEN, .ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, }; _cleanup_close_ int s = -1; int r; assert(ifindex > 0); s = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); if (s < 0) return -errno; r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); if (r < 0) return -errno; r = bind(s, &link.sa, sizeof(link.ll)); if (r < 0) return -errno; r = s; s = -1; return r; } static int arp_send_packet(int fd, int ifindex, be32_t pa, const struct ether_addr *ha, bool announce) { union sockaddr_union link = { .ll.sll_family = AF_PACKET, .ll.sll_protocol = htons(ETH_P_ARP), .ll.sll_ifindex = ifindex, .ll.sll_halen = ETH_ALEN, .ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, }; struct ether_arp arp = { .ea_hdr.ar_hrd = htons(ARPHRD_ETHER), /* HTYPE */ .ea_hdr.ar_pro = htons(ETHERTYPE_IP), /* PTYPE */ .ea_hdr.ar_hln = ETH_ALEN, /* HLEN */ .ea_hdr.ar_pln = sizeof(be32_t), /* PLEN */ .ea_hdr.ar_op = htons(ARPOP_REQUEST), /* REQUEST */ }; int r; assert(fd >= 0); assert(pa != 0); assert(ha); memcpy(&arp.arp_sha, ha, ETH_ALEN); memcpy(&arp.arp_tpa, &pa, sizeof(pa)); if (announce) memcpy(&arp.arp_spa, &pa, sizeof(pa)); r = sendto(fd, &arp, sizeof(struct ether_arp), 0, &link.sa, sizeof(link.ll)); if (r < 0) return -errno; return 0; } int arp_send_probe(int fd, int ifindex, be32_t pa, const struct ether_addr *ha) { return arp_send_packet(fd, ifindex, pa, ha, false); } int arp_send_announcement(int fd, int ifindex, be32_t pa, const struct ether_addr *ha) { return arp_send_packet(fd, ifindex, pa, ha, true); } systemd-229/src/libsystemd-network/arp-util.h000066400000000000000000000022041265713322000214220ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2014 Axis Communications AB. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "socket-util.h" #include "sparse-endian.h" int arp_network_bind_raw_socket(int index, be32_t address, const struct ether_addr *eth_mac); int arp_send_probe(int fd, int ifindex, be32_t pa, const struct ether_addr *ha); int arp_send_announcement(int fd, int ifindex, be32_t pa, const struct ether_addr *ha); systemd-229/src/libsystemd-network/dhcp-identifier.c000066400000000000000000000063021265713322000227210ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "libudev.h" #include "sd-id128.h" #include "dhcp-identifier.h" #include "dhcp6-protocol.h" #include "network-internal.h" #include "siphash24.h" #include "sparse-endian.h" #include "udev-util.h" #include "virt.h" #define SYSTEMD_PEN 43793 #define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09) int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) { sd_id128_t machine_id; uint64_t hash; int r; assert(duid); assert(len); r = sd_id128_get_machine(&machine_id); if (r < 0) return r; unaligned_write_be16(&duid->type, DHCP6_DUID_EN); unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN); *len = sizeof(duid->type) + sizeof(duid->en); /* a bit of snake-oil perhaps, but no need to expose the machine-id directly; duid->en.id might not be aligned, so we need to copy */ hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes)); memcpy(duid->en.id, &hash, sizeof(duid->en.id)); return 0; } int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) { /* name is a pointer to memory in the udev_device struct, so must have the same scope */ _cleanup_udev_device_unref_ struct udev_device *device = NULL; const char *name = NULL; uint64_t id; if (detect_container() <= 0) { /* not in a container, udev will be around */ _cleanup_udev_unref_ struct udev *udev; char ifindex_str[2 + DECIMAL_STR_MAX(int)]; udev = udev_new(); if (!udev) return -ENOMEM; sprintf(ifindex_str, "n%d", ifindex); device = udev_device_new_from_device_id(udev, ifindex_str); if (device) { if (udev_device_get_is_initialized(device) <= 0) /* not yet ready */ return -EBUSY; name = net_get_name(device); } } if (name) id = siphash24(name, strlen(name), HASH_KEY.bytes); else /* fall back to MAC address if no predictable name available */ id = siphash24(mac, mac_len, HASH_KEY.bytes); id = htole64(id); /* fold into 32 bits */ unaligned_write_be32(_id, (id & 0xffffffff) ^ (id >> 32)); return 0; } systemd-229/src/libsystemd-network/dhcp-identifier.h000066400000000000000000000037641265713322000227370ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-id128.h" #include "macro.h" #include "sparse-endian.h" #include "unaligned.h" /* RFC 3315 section 9.1: * A DUID can be no more than 128 octets long (not including the type code). */ #define MAX_DUID_LEN 128 struct duid { uint16_t type; union { struct { /* DHCP6_DUID_LLT */ uint16_t htype; uint32_t time; uint8_t haddr[0]; } _packed_ llt; struct { /* DHCP6_DUID_EN */ uint32_t pen; uint8_t id[8]; } _packed_ en; struct { /* DHCP6_DUID_LL */ int16_t htype; uint8_t haddr[0]; } _packed_ ll; struct { /* DHCP6_DUID_UUID */ sd_id128_t uuid; } _packed_ uuid; struct { uint8_t data[MAX_DUID_LEN]; } _packed_ raw; }; } _packed_; int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len); int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id); systemd-229/src/libsystemd-network/dhcp-internal.h000066400000000000000000000056211265713322000224230ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. Copyright (C) 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-dhcp-client.h" #include "dhcp-protocol.h" #include "socket-util.h" int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, uint32_t xid, const uint8_t *mac_addr, size_t mac_addr_len, uint16_t arp_type); int dhcp_network_bind_udp_socket(be32_t address, uint16_t port); int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len); int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, const void *packet, size_t len); int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_t overload, uint8_t code, size_t optlen, const void *optval); typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len, const void *option, void *userdata); int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_cb_t cb, void *userdata, char **error_message); int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, uint8_t type, uint16_t arp_type, size_t optlen, size_t *optoffset); uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len); void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr, uint16_t source, be32_t destination_addr, uint16_t destination, uint16_t len); int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum); /* If we are invoking callbacks of a dhcp-client, ensure unreffing the * client from the callback doesn't destroy the object we are working * on */ #define DHCP_CLIENT_DONT_DESTROY(client) \ _cleanup_(sd_dhcp_client_unrefp) _unused_ sd_dhcp_client *_dont_destroy_##client = sd_dhcp_client_ref(client) #define log_dhcp_client(client, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "DHCP CLIENT (0x%x): " fmt, client->xid, ##__VA_ARGS__) systemd-229/src/libsystemd-network/dhcp-lease-internal.h000066400000000000000000000052141265713322000235100ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. Copyright (C) 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-dhcp-client.h" #include "dhcp-protocol.h" #include "list.h" #include "util.h" struct sd_dhcp_route { struct in_addr dst_addr; struct in_addr gw_addr; unsigned char dst_prefixlen; }; struct sd_dhcp_raw_option { LIST_FIELDS(struct sd_dhcp_raw_option, options); uint8_t tag; uint8_t length; void *data; }; struct sd_dhcp_lease { unsigned n_ref; /* each 0 if unset */ uint32_t t1; uint32_t t2; uint32_t lifetime; /* each 0 if unset */ be32_t address; be32_t server_address; be32_t router; be32_t next_server; bool have_subnet_mask; be32_t subnet_mask; bool have_broadcast; be32_t broadcast; struct in_addr *dns; size_t dns_size; struct in_addr *ntp; size_t ntp_size; struct sd_dhcp_route *static_route; size_t static_route_size, static_route_allocated; uint16_t mtu; /* 0 if unset */ char *domainname; char *hostname; char *root_path; void *client_id; size_t client_id_len; void *vendor_specific; size_t vendor_specific_len; char *timezone; LIST_HEAD(struct sd_dhcp_raw_option, private_options); }; int dhcp_lease_new(sd_dhcp_lease **ret); int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata); int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len); int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease); int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len); int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file); int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file); systemd-229/src/libsystemd-network/dhcp-network.c000066400000000000000000000260451265713322000222760ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include "dhcp-internal.h" #include "fd-util.h" #include "socket-util.h" static int _bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid, const uint8_t *mac_addr, size_t mac_addr_len, const uint8_t *bcast_addr, const struct ether_addr *eth_mac, uint16_t arp_type, uint8_t dhcp_hlen) { struct sock_filter filter[] = { BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */ BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(DHCPPacket), 1, 0), /* packet >= DHCPPacket ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, ip.protocol)), /* A <- IP protocol */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 1, 0), /* IP protocol == UDP ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, ip.frag_off)), /* A <- Flags */ BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x20), /* A <- A & 0x20 (More Fragments bit) */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, ip.frag_off)), /* A <- Flags + Fragment offset */ BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x1fff), /* A <- A & 0x1fff (Fragment offset) */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, udp.dest)), /* A <- UDP destination port */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_PORT_CLIENT, 1, 0), /* UDP destination port == DHCP client port ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.op)), /* A <- DHCP op */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, BOOTREPLY, 1, 0), /* op == BOOTREPLY ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.htype)), /* A <- DHCP header type */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arp_type, 1, 0), /* header type == arp_type ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.hlen)), /* A <- MAC address length */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, dhcp_hlen, 1, 0), /* address length == dhcp_hlen ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.xid)), /* A <- client identifier */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0), /* client identifier == xid ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((unsigned int *) eth_mac))), /* A <- 4 bytes of client's MAC */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr)), /* A <- 4 bytes of MAC from dhcp.chaddr */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_IMM, htobe16(*((unsigned short *) (((char *) eth_mac) + 4)))), /* A <- remainder of client's MAC */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr) + 4), /* A <- remainder of MAC from dhcp.chaddr */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.magic)), /* A <- DHCP magic cookie */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_MAGIC_COOKIE, 1, 0), /* cookie == DHCP magic cookie ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ }; struct sock_fprog fprog = { .len = ELEMENTSOF(filter), .filter = filter }; _cleanup_close_ int s = -1; int r, on = 1; assert(ifindex > 0); assert(link); s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); if (s < 0) return -errno; r = setsockopt(s, SOL_PACKET, PACKET_AUXDATA, &on, sizeof(on)); if (r < 0) return -errno; r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); if (r < 0) return -errno; link->ll.sll_family = AF_PACKET; link->ll.sll_protocol = htons(ETH_P_IP); link->ll.sll_ifindex = ifindex; link->ll.sll_hatype = htons(arp_type); link->ll.sll_halen = mac_addr_len; memcpy(link->ll.sll_addr, bcast_addr, mac_addr_len); r = bind(s, &link->sa, sizeof(link->ll)); if (r < 0) return -errno; r = s; s = -1; return r; } int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid, const uint8_t *mac_addr, size_t mac_addr_len, uint16_t arp_type) { static const uint8_t eth_bcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* Default broadcast address for IPoIB */ static const uint8_t ib_bcast[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff }; struct ether_addr eth_mac = { { 0, 0, 0, 0, 0, 0 } }; const uint8_t *bcast_addr = NULL; uint8_t dhcp_hlen = 0; assert_return(mac_addr_len > 0, -EINVAL); if (arp_type == ARPHRD_ETHER) { assert_return(mac_addr_len == ETH_ALEN, -EINVAL); memcpy(ð_mac, mac_addr, ETH_ALEN); bcast_addr = eth_bcast; dhcp_hlen = ETH_ALEN; } else if (arp_type == ARPHRD_INFINIBAND) { assert_return(mac_addr_len == INFINIBAND_ALEN, -EINVAL); bcast_addr = ib_bcast; } else return -EINVAL; return _bind_raw_socket(ifindex, link, xid, mac_addr, mac_addr_len, bcast_addr, ð_mac, arp_type, dhcp_hlen); } int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) { union sockaddr_union src = { .in.sin_family = AF_INET, .in.sin_port = htobe16(port), .in.sin_addr.s_addr = address, }; _cleanup_close_ int s = -1; int r, on = 1, tos = IPTOS_CLASS_CS6; s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); if (s < 0) return -errno; r = setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); if (r < 0) return -errno; r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (r < 0) return -errno; if (address == INADDR_ANY) { r = setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)); if (r < 0) return -errno; r = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); if (r < 0) return -errno; } else { r = setsockopt(s, IPPROTO_IP, IP_FREEBIND, &on, sizeof(on)); if (r < 0) return -errno; } r = bind(s, &src.sa, sizeof(src.in)); if (r < 0) return -errno; r = s; s = -1; return r; } int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len) { int r; assert(link); assert(packet); assert(len); r = sendto(s, packet, len, 0, &link->sa, sizeof(link->ll)); if (r < 0) return -errno; return 0; } int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, const void *packet, size_t len) { union sockaddr_union dest = { .in.sin_family = AF_INET, .in.sin_port = htobe16(port), .in.sin_addr.s_addr = address, }; int r; assert(s >= 0); assert(packet); assert(len); r = sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in)); if (r < 0) return -errno; return 0; } systemd-229/src/libsystemd-network/dhcp-option.c000066400000000000000000000213741265713322000221150ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "utf8.h" #include "dhcp-internal.h" static int option_append(uint8_t options[], size_t size, size_t *offset, uint8_t code, size_t optlen, const void *optval) { assert(options); assert(offset); if (code != SD_DHCP_OPTION_END) /* always make sure there is space for an END option */ size --; switch (code) { case SD_DHCP_OPTION_PAD: case SD_DHCP_OPTION_END: if (size < *offset + 1) return -ENOBUFS; options[*offset] = code; *offset += 1; break; default: if (size < *offset + optlen + 2) return -ENOBUFS; options[*offset] = code; options[*offset + 1] = optlen; if (optlen) { assert(optval); memcpy(&options[*offset + 2], optval, optlen); } *offset += optlen + 2; break; } return 0; } int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_t overload, uint8_t code, size_t optlen, const void *optval) { size_t file_offset = 0, sname_offset =0; bool file, sname; int r; assert(message); assert(offset); file = overload & DHCP_OVERLOAD_FILE; sname = overload & DHCP_OVERLOAD_SNAME; if (*offset < size) { /* still space in the options array */ r = option_append(message->options, size, offset, code, optlen, optval); if (r >= 0) return 0; else if (r == -ENOBUFS && (file || sname)) { /* did not fit, but we have more buffers to try close the options array and move the offset to its end */ r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL); if (r < 0) return r; *offset = size; } else return r; } if (overload & DHCP_OVERLOAD_FILE) { file_offset = *offset - size; if (file_offset < sizeof(message->file)) { /* still space in the 'file' array */ r = option_append(message->file, sizeof(message->file), &file_offset, code, optlen, optval); if (r >= 0) { *offset = size + file_offset; return 0; } else if (r == -ENOBUFS && sname) { /* did not fit, but we have more buffers to try close the file array and move the offset to its end */ r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL); if (r < 0) return r; *offset = size + sizeof(message->file); } else return r; } } if (overload & DHCP_OVERLOAD_SNAME) { sname_offset = *offset - size - (file ? sizeof(message->file) : 0); if (sname_offset < sizeof(message->sname)) { /* still space in the 'sname' array */ r = option_append(message->sname, sizeof(message->sname), &sname_offset, code, optlen, optval); if (r >= 0) { *offset = size + (file ? sizeof(message->file) : 0) + sname_offset; return 0; } else { /* no space, or other error, give up */ return r; } } } return -ENOBUFS; } static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overload, uint8_t *message_type, char **error_message, dhcp_option_cb_t cb, void *userdata) { uint8_t code, len; const uint8_t *option; size_t offset = 0; while (offset < buflen) { code = options[offset ++]; switch (code) { case SD_DHCP_OPTION_PAD: continue; case SD_DHCP_OPTION_END: return 0; } if (buflen < offset + 1) return -ENOBUFS; len = options[offset ++]; if (buflen < offset + len) return -EINVAL; option = &options[offset]; switch (code) { case SD_DHCP_OPTION_MESSAGE_TYPE: if (len != 1) return -EINVAL; if (message_type) *message_type = *option; break; case SD_DHCP_OPTION_ERROR_MESSAGE: if (len == 0) return -EINVAL; if (error_message) { _cleanup_free_ char *string = NULL; /* Accept a trailing NUL byte */ if (memchr(option, 0, len - 1)) return -EINVAL; string = strndup((const char *) option, len); if (!string) return -ENOMEM; if (!ascii_is_valid(string)) return -EINVAL; free(*error_message); *error_message = string; string = NULL; } break; case SD_DHCP_OPTION_OVERLOAD: if (len != 1) return -EINVAL; if (overload) *overload = *option; break; default: if (cb) cb(code, len, option, userdata); break; } offset += len; } if (offset < buflen) return -EINVAL; return 0; } int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_cb_t cb, void *userdata, char **_error_message) { _cleanup_free_ char *error_message = NULL; uint8_t overload = 0; uint8_t message_type = 0; int r; if (!message) return -EINVAL; if (len < sizeof(DHCPMessage)) return -EINVAL; len -= sizeof(DHCPMessage); r = parse_options(message->options, len, &overload, &message_type, &error_message, cb, userdata); if (r < 0) return r; if (overload & DHCP_OVERLOAD_FILE) { r = parse_options(message->file, sizeof(message->file), NULL, &message_type, &error_message, cb, userdata); if (r < 0) return r; } if (overload & DHCP_OVERLOAD_SNAME) { r = parse_options(message->sname, sizeof(message->sname), NULL, &message_type, &error_message, cb, userdata); if (r < 0) return r; } if (message_type == 0) return -ENOMSG; if (_error_message && IN_SET(message_type, DHCP_NAK, DHCP_DECLINE)) { *_error_message = error_message; error_message = NULL; } return message_type; } systemd-229/src/libsystemd-network/dhcp-packet.c000066400000000000000000000141541265713322000220520ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. Copyright (C) 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "dhcp-internal.h" #include "dhcp-protocol.h" #define DHCP_CLIENT_MIN_OPTIONS_SIZE 312 int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, uint8_t type, uint16_t arp_type, size_t optlen, size_t *optoffset) { size_t offset = 0; int r; assert(op == BOOTREQUEST || op == BOOTREPLY); assert(arp_type == ARPHRD_ETHER || arp_type == ARPHRD_INFINIBAND); message->op = op; message->htype = arp_type; message->hlen = (arp_type == ARPHRD_ETHER) ? ETHER_ADDR_LEN : 0; message->xid = htobe32(xid); message->magic = htobe32(DHCP_MAGIC_COOKIE); r = dhcp_option_append(message, optlen, &offset, 0, SD_DHCP_OPTION_MESSAGE_TYPE, 1, &type); if (r < 0) return r; *optoffset = offset; return 0; } uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len) { uint64_t *buf_64 = (uint64_t*)buf; uint64_t *end_64 = buf_64 + (len / sizeof(uint64_t)); uint64_t sum = 0; /* See RFC1071 */ while (buf_64 < end_64) { sum += *buf_64; if (sum < *buf_64) /* wrap around in one's complement */ sum++; buf_64 ++; } if (len % sizeof(uint64_t)) { /* If the buffer is not aligned to 64-bit, we need to zero-pad the last few bytes and add them in */ uint64_t buf_tail = 0; memcpy(&buf_tail, buf_64, len % sizeof(uint64_t)); sum += buf_tail; if (sum < buf_tail) /* wrap around */ sum++; } while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16); return ~sum; } void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr, uint16_t source_port, be32_t destination_addr, uint16_t destination_port, uint16_t len) { packet->ip.version = IPVERSION; packet->ip.ihl = DHCP_IP_SIZE / 4; packet->ip.tot_len = htobe16(len); packet->ip.tos = IPTOS_CLASS_CS6; packet->ip.protocol = IPPROTO_UDP; packet->ip.saddr = source_addr; packet->ip.daddr = destination_addr; packet->udp.source = htobe16(source_port); packet->udp.dest = htobe16(destination_port); packet->udp.len = htobe16(len - DHCP_IP_SIZE); packet->ip.check = packet->udp.len; packet->udp.check = dhcp_packet_checksum((uint8_t*)&packet->ip.ttl, len - 8); packet->ip.ttl = IPDEFTTL; packet->ip.check = 0; packet->ip.check = dhcp_packet_checksum((uint8_t*)&packet->ip, DHCP_IP_SIZE); } int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum) { size_t hdrlen; assert(packet); /* IP */ if (packet->ip.version != IPVERSION) { log_debug("ignoring packet: not IPv4"); return -EINVAL; } if (packet->ip.ihl < 5) { log_debug("ignoring packet: IPv4 IHL (%u words) invalid", packet->ip.ihl); return -EINVAL; } hdrlen = packet->ip.ihl * 4; if (hdrlen < 20) { log_debug("ignoring packet: IPv4 IHL (%zu bytes) " "smaller than minimum (20 bytes)", hdrlen); return -EINVAL; } if (len < hdrlen) { log_debug("ignoring packet: packet (%zu bytes) " "smaller than expected (%zu) by IP header", len, hdrlen); return -EINVAL; } /* UDP */ if (packet->ip.protocol != IPPROTO_UDP) { log_debug("ignoring packet: not UDP"); return -EINVAL; } if (len < hdrlen + be16toh(packet->udp.len)) { log_debug("ignoring packet: packet (%zu bytes) " "smaller than expected (%zu) by UDP header", len, hdrlen + be16toh(packet->udp.len)); return -EINVAL; } if (be16toh(packet->udp.dest) != DHCP_PORT_CLIENT) { log_debug("ignoring packet: to port %u, which " "is not the DHCP client port (%u)", be16toh(packet->udp.dest), DHCP_PORT_CLIENT); return -EINVAL; } /* checksums - computing these is relatively expensive, so only do it if all the other checks have passed */ if (dhcp_packet_checksum((uint8_t*)&packet->ip, hdrlen)) { log_debug("ignoring packet: invalid IP checksum"); return -EINVAL; } if (checksum && packet->udp.check) { packet->ip.check = packet->udp.len; packet->ip.ttl = 0; if (dhcp_packet_checksum((uint8_t*)&packet->ip.ttl, be16toh(packet->udp.len) + 12)) { log_debug("ignoring packet: invalid UDP checksum"); return -EINVAL; } } return 0; } systemd-229/src/libsystemd-network/dhcp-protocol.h000066400000000000000000000066411265713322000224530ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "macro.h" #include "sparse-endian.h" struct DHCPMessage { uint8_t op; uint8_t htype; uint8_t hlen; uint8_t hops; be32_t xid; be16_t secs; be16_t flags; be32_t ciaddr; be32_t yiaddr; be32_t siaddr; be32_t giaddr; uint8_t chaddr[16]; uint8_t sname[64]; uint8_t file[128]; be32_t magic; uint8_t options[0]; } _packed_; typedef struct DHCPMessage DHCPMessage; struct DHCPPacket { struct iphdr ip; struct udphdr udp; DHCPMessage dhcp; } _packed_; typedef struct DHCPPacket DHCPPacket; #define DHCP_IP_SIZE (int32_t)(sizeof(struct iphdr)) #define DHCP_IP_UDP_SIZE (int32_t)(sizeof(struct udphdr) + DHCP_IP_SIZE) #define DHCP_MESSAGE_SIZE (int32_t)(sizeof(DHCPMessage)) #define DHCP_DEFAULT_MIN_SIZE 576 /* the minimum internet hosts must be able to receive */ #define DHCP_MIN_OPTIONS_SIZE DHCP_DEFAULT_MIN_SIZE - DHCP_IP_UDP_SIZE - DHCP_MESSAGE_SIZE #define DHCP_MAGIC_COOKIE (uint32_t)(0x63825363) enum { DHCP_PORT_SERVER = 67, DHCP_PORT_CLIENT = 68, }; enum DHCPState { DHCP_STATE_INIT = 0, DHCP_STATE_SELECTING = 1, DHCP_STATE_INIT_REBOOT = 2, DHCP_STATE_REBOOTING = 3, DHCP_STATE_REQUESTING = 4, DHCP_STATE_BOUND = 5, DHCP_STATE_RENEWING = 6, DHCP_STATE_REBINDING = 7, DHCP_STATE_STOPPED = 8, }; typedef enum DHCPState DHCPState; enum { BOOTREQUEST = 1, BOOTREPLY = 2, }; enum { DHCP_DISCOVER = 1, DHCP_OFFER = 2, DHCP_REQUEST = 3, DHCP_DECLINE = 4, DHCP_ACK = 5, DHCP_NAK = 6, DHCP_RELEASE = 7, DHCP_INFORM = 8, DHCP_FORCERENEW = 9, }; enum { DHCP_OVERLOAD_FILE = 1, DHCP_OVERLOAD_SNAME = 2, }; #define DHCP_MAX_FQDN_LENGTH 255 enum { DHCP_FQDN_FLAG_S = (1 << 0), DHCP_FQDN_FLAG_O = (1 << 1), DHCP_FQDN_FLAG_E = (1 << 2), DHCP_FQDN_FLAG_N = (1 << 3), }; systemd-229/src/libsystemd-network/dhcp-server-internal.h000066400000000000000000000050641265713322000237300ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. Copyright (C) 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "sd-dhcp-server.h" #include "sd-event.h" #include "dhcp-internal.h" #include "hashmap.h" #include "log.h" #include "util.h" typedef struct DHCPClientId { size_t length; void *data; } DHCPClientId; typedef struct DHCPLease { DHCPClientId client_id; be32_t address; be32_t gateway; uint8_t chaddr[16]; usec_t expiration; } DHCPLease; struct sd_dhcp_server { unsigned n_ref; sd_event *event; int event_priority; sd_event_source *receive_message; int fd; int fd_raw; int ifindex; be32_t address; be32_t netmask; be32_t subnet; uint32_t pool_offset; uint32_t pool_size; char *timezone; struct in_addr *ntp, *dns; unsigned n_ntp, n_dns; Hashmap *leases_by_client_id; DHCPLease **bound_leases; DHCPLease invalid_lease; uint32_t max_lease_time, default_lease_time; }; typedef struct DHCPRequest { /* received message */ DHCPMessage *message; /* options */ DHCPClientId client_id; size_t max_optlen; be32_t server_id; be32_t requested_ip; uint32_t lifetime; } DHCPRequest; #define log_dhcp_server(client, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "DHCP SERVER: " fmt, ##__VA_ARGS__) int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, size_t length); int dhcp_server_send_packet(sd_dhcp_server *server, DHCPRequest *req, DHCPPacket *packet, int type, size_t optoffset); void client_id_hash_func(const void *p, struct siphash *state); int client_id_compare_func(const void *_a, const void *_b); systemd-229/src/libsystemd-network/dhcp6-internal.h000066400000000000000000000054511265713322000225120ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2014-2015 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-event.h" #include "list.h" #include "macro.h" #include "sparse-endian.h" typedef struct DHCP6Address DHCP6Address; struct DHCP6Address { LIST_FIELDS(DHCP6Address, addresses); struct { struct in6_addr address; be32_t lifetime_preferred; be32_t lifetime_valid; } iaaddr _packed_; }; struct DHCP6IA { uint16_t type; struct { be32_t id; be32_t lifetime_t1; be32_t lifetime_t2; } _packed_; sd_event_source *timeout_t1; sd_event_source *timeout_t2; LIST_HEAD(DHCP6Address, addresses); }; typedef struct DHCP6IA DHCP6IA; #define log_dhcp6_client(p, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__) int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, size_t optlen, const void *optval); int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia); int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen, uint8_t **optvalue); int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype, DHCP6IA *ia); int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, struct in6_addr **addrs, size_t count, size_t *allocated); int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char ***str_arr); int dhcp6_network_bind_udp_socket(int index, struct in6_addr *address); int dhcp6_network_send_udp_socket(int s, struct in6_addr *address, const void *packet, size_t len); const char *dhcp6_message_type_to_string(int s) _const_; int dhcp6_message_type_from_string(const char *s) _pure_; const char *dhcp6_message_status_to_string(int s) _const_; int dhcp6_message_status_from_string(const char *s) _pure_; systemd-229/src/libsystemd-network/dhcp6-lease-internal.h000066400000000000000000000047071265713322000236040ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014-2015 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-dhcp6-lease.h" #include "dhcp6-internal.h" struct sd_dhcp6_lease { unsigned n_ref; uint8_t *serverid; size_t serverid_len; uint8_t preference; bool rapid_commit; DHCP6IA ia; DHCP6Address *addr_iter; struct in6_addr *dns; size_t dns_count; size_t dns_allocated; char **domains; size_t domains_count; struct in6_addr *ntp; size_t ntp_count; size_t ntp_allocated; char **ntp_fqdn; size_t ntp_fqdn_count; }; int dhcp6_lease_clear_timers(DHCP6IA *ia); int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire); DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia); int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id, size_t len); int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len); int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, uint8_t preference); int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference); int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease); int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit); int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid); int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) ; int dhcp6_lease_new(sd_dhcp6_lease **ret); systemd-229/src/libsystemd-network/dhcp6-network.c000066400000000000000000000052511265713322000223600ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include "dhcp6-internal.h" #include "dhcp6-protocol.h" #include "fd-util.h" #include "socket-util.h" int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) { union sockaddr_union src = { .in6.sin6_family = AF_INET6, .in6.sin6_port = htobe16(DHCP6_PORT_CLIENT), .in6.sin6_scope_id = index, }; _cleanup_close_ int s = -1; int r, off = 0, on = 1; assert(index > 0); assert(local_address); src.in6.sin6_addr = *local_address; s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_UDP); if (s < 0) return -errno; r = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); if (r < 0) return -errno; r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, sizeof(off)); if (r < 0) return -errno; r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (r < 0) return -errno; r = bind(s, &src.sa, sizeof(src.in6)); if (r < 0) return -errno; r = s; s = -1; return r; } int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address, const void *packet, size_t len) { union sockaddr_union dest = { .in6.sin6_family = AF_INET6, .in6.sin6_port = htobe16(DHCP6_PORT_SERVER), }; int r; assert(server_address); memcpy(&dest.in6.sin6_addr, server_address, sizeof(dest.in6.sin6_addr)); r = sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in6)); if (r < 0) return -errno; return 0; } systemd-229/src/libsystemd-network/dhcp6-option.c000066400000000000000000000274761265713322000222140ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014-2015 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-dhcp6-client.h" #include "alloc-util.h" #include "dhcp6-internal.h" #include "dhcp6-protocol.h" #include "dns-domain.h" #include "sparse-endian.h" #include "strv.h" #include "unaligned.h" #include "util.h" #define DHCP6_OPTION_IA_NA_LEN 12 #define DHCP6_OPTION_IA_TA_LEN 4 typedef struct DHCP6Option { be16_t code; be16_t len; uint8_t data[]; } _packed_ DHCP6Option; static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode, size_t optlen) { DHCP6Option *option = (DHCP6Option*) *buf; assert_return(buf, -EINVAL); assert_return(*buf, -EINVAL); assert_return(buflen, -EINVAL); if (optlen > 0xffff || *buflen < optlen + sizeof(DHCP6Option)) return -ENOBUFS; option->code = htobe16(optcode); option->len = htobe16(optlen); *buf += sizeof(DHCP6Option); *buflen -= sizeof(DHCP6Option); return 0; } int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, size_t optlen, const void *optval) { int r; assert_return(optval || optlen == 0, -EINVAL); r = option_append_hdr(buf, buflen, code, optlen); if (r < 0) return r; if (optval) memcpy(*buf, optval, optlen); *buf += optlen; *buflen -= optlen; return 0; } int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) { uint16_t len; uint8_t *ia_hdr; size_t ia_buflen, ia_addrlen = 0; DHCP6Address *addr; int r; assert_return(buf && *buf && buflen && ia, -EINVAL); switch (ia->type) { case SD_DHCP6_OPTION_IA_NA: len = DHCP6_OPTION_IA_NA_LEN; break; case SD_DHCP6_OPTION_IA_TA: len = DHCP6_OPTION_IA_TA_LEN; break; default: return -EINVAL; } if (*buflen < len) return -ENOBUFS; ia_hdr = *buf; ia_buflen = *buflen; *buf += sizeof(DHCP6Option); *buflen -= sizeof(DHCP6Option); memcpy(*buf, &ia->id, len); *buf += len; *buflen -= len; LIST_FOREACH(addresses, addr, ia->addresses) { r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR, sizeof(addr->iaaddr)); if (r < 0) return r; memcpy(*buf, &addr->iaaddr, sizeof(addr->iaaddr)); *buf += sizeof(addr->iaaddr); *buflen -= sizeof(addr->iaaddr); ia_addrlen += sizeof(DHCP6Option) + sizeof(addr->iaaddr); } r = option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len + ia_addrlen); if (r < 0) return r; return 0; } static int option_parse_hdr(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen) { DHCP6Option *option = (DHCP6Option*) *buf; uint16_t len; assert_return(buf, -EINVAL); assert_return(optcode, -EINVAL); assert_return(optlen, -EINVAL); if (*buflen < sizeof(DHCP6Option)) return -ENOMSG; len = be16toh(option->len); if (len > *buflen) return -ENOMSG; *optcode = be16toh(option->code); *optlen = len; *buf += 4; *buflen -= 4; return 0; } int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen, uint8_t **optvalue) { int r; assert_return(buf && buflen && optcode && optlen && optvalue, -EINVAL); r = option_parse_hdr(buf, buflen, optcode, optlen); if (r < 0) return r; if (*optlen > *buflen) return -ENOBUFS; *optvalue = *buf; *buflen -= *optlen; *buf += *optlen; return 0; } int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype, DHCP6IA *ia) { int r; uint16_t opt, status; size_t optlen; size_t iaaddr_offset; DHCP6Address *addr; uint32_t lt_t1, lt_t2, lt_valid, lt_pref, lt_min = ~0; assert_return(ia, -EINVAL); assert_return(!ia->addresses, -EINVAL); switch (iatype) { case SD_DHCP6_OPTION_IA_NA: if (*buflen < DHCP6_OPTION_IA_NA_LEN + sizeof(DHCP6Option) + sizeof(addr->iaaddr)) { r = -ENOBUFS; goto error; } iaaddr_offset = DHCP6_OPTION_IA_NA_LEN; memcpy(&ia->id, *buf, iaaddr_offset); lt_t1 = be32toh(ia->lifetime_t1); lt_t2 = be32toh(ia->lifetime_t2); if (lt_t1 && lt_t2 && lt_t1 > lt_t2) { log_dhcp6_client(client, "IA T1 %ds > T2 %ds", lt_t1, lt_t2); r = -EINVAL; goto error; } break; case SD_DHCP6_OPTION_IA_TA: if (*buflen < DHCP6_OPTION_IA_TA_LEN + sizeof(DHCP6Option) + sizeof(addr->iaaddr)) { r = -ENOBUFS; goto error; } iaaddr_offset = DHCP6_OPTION_IA_TA_LEN; memcpy(&ia->id, *buf, iaaddr_offset); ia->lifetime_t1 = 0; ia->lifetime_t2 = 0; break; default: r = -ENOMSG; goto error; } ia->type = iatype; *buflen -= iaaddr_offset; *buf += iaaddr_offset; while ((r = option_parse_hdr(buf, buflen, &opt, &optlen)) >= 0) { switch (opt) { case SD_DHCP6_OPTION_IAADDR: addr = new0(DHCP6Address, 1); if (!addr) { r = -ENOMEM; goto error; } LIST_INIT(addresses, addr); memcpy(&addr->iaaddr, *buf, sizeof(addr->iaaddr)); lt_valid = be32toh(addr->iaaddr.lifetime_valid); lt_pref = be32toh(addr->iaaddr.lifetime_valid); if (!lt_valid || lt_pref > lt_valid) { log_dhcp6_client(client, "IA preferred %ds > valid %ds", lt_pref, lt_valid); free(addr); } else { LIST_PREPEND(addresses, ia->addresses, addr); if (lt_valid < lt_min) lt_min = lt_valid; } break; case SD_DHCP6_OPTION_STATUS_CODE: if (optlen < sizeof(status)) break; status = (*buf)[0] << 8 | (*buf)[1]; if (status) { log_dhcp6_client(client, "IA status %d", status); r = -EINVAL; goto error; } break; default: log_dhcp6_client(client, "Unknown IA option %d", opt); break; } *buflen -= optlen; *buf += optlen; } if (r == -ENOMSG) r = 0; if (!ia->lifetime_t1 && !ia->lifetime_t2) { lt_t1 = lt_min / 2; lt_t2 = lt_min / 10 * 8; ia->lifetime_t1 = htobe32(lt_t1); ia->lifetime_t2 = htobe32(lt_t2); log_dhcp6_client(client, "Computed IA T1 %ds and T2 %ds as both were zero", lt_t1, lt_t2); } if (*buflen) r = -ENOMSG; error: *buf += *buflen; *buflen = 0; return r; } int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, struct in6_addr **addrs, size_t count, size_t *allocated) { if (optlen == 0 || optlen % sizeof(struct in6_addr) != 0) return -EINVAL; if (!GREEDY_REALLOC(*addrs, *allocated, count * sizeof(struct in6_addr) + optlen)) return -ENOMEM; memcpy(*addrs + count, optval, optlen); count += optlen / sizeof(struct in6_addr); return count; } int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char ***str_arr) { size_t pos = 0, idx = 0; _cleanup_free_ char **names = NULL; int r; assert_return(optlen > 1, -ENODATA); assert_return(optval[optlen - 1] == '\0', -EINVAL); while (pos < optlen) { _cleanup_free_ char *ret = NULL; size_t n = 0, allocated = 0; bool first = true; for (;;) { uint8_t c; c = optval[pos++]; if (c == 0) /* End of name */ break; else if (c <= 63) { const char *label; /* Literal label */ label = (const char *)&optval[pos]; pos += c; if (pos > optlen) return -EMSGSIZE; if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) { r = -ENOMEM; goto fail; } if (first) first = false; else ret[n++] = '.'; r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX); if (r < 0) goto fail; n += r; continue; } else { r = -EBADMSG; goto fail; } } if (!GREEDY_REALLOC(ret, allocated, n + 1)) { r = -ENOMEM; goto fail; } ret[n] = 0; r = strv_extend(&names, ret); if (r < 0) goto fail; idx++; } *str_arr = names; names = NULL; return idx; fail: return r; } systemd-229/src/libsystemd-network/dhcp6-protocol.h000066400000000000000000000102231265713322000225300ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2014 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "macro.h" #include "sparse-endian.h" struct DHCP6Message { union { struct { uint8_t type; uint8_t _pad[3]; } _packed_; be32_t transaction_id; }; } _packed_; typedef struct DHCP6Message DHCP6Message; #define DHCP6_MIN_OPTIONS_SIZE \ 1280 - sizeof(struct ip6_hdr) - sizeof(struct udphdr) #define IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT \ { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02 } } } enum { DHCP6_PORT_SERVER = 547, DHCP6_PORT_CLIENT = 546, }; #define DHCP6_INF_TIMEOUT 1 * USEC_PER_SEC #define DHCP6_INF_MAX_RT 120 * USEC_PER_SEC #define DHCP6_SOL_MAX_DELAY 1 * USEC_PER_SEC #define DHCP6_SOL_TIMEOUT 1 * USEC_PER_SEC #define DHCP6_SOL_MAX_RT 120 * USEC_PER_SEC #define DHCP6_REQ_TIMEOUT 1 * USEC_PER_SEC #define DHCP6_REQ_MAX_RT 120 * USEC_PER_SEC #define DHCP6_REQ_MAX_RC 10 #define DHCP6_REN_TIMEOUT 10 * USEC_PER_SEC #define DHCP6_REN_MAX_RT 600 * USEC_PER_SEC #define DHCP6_REB_TIMEOUT 10 * USEC_PER_SEC #define DHCP6_REB_MAX_RT 600 * USEC_PER_SEC enum { DHCP6_DUID_LLT = 1, DHCP6_DUID_EN = 2, DHCP6_DUID_LL = 3, DHCP6_DUID_UUID = 4, }; enum DHCP6State { DHCP6_STATE_STOPPED = 0, DHCP6_STATE_INFORMATION_REQUEST = 1, DHCP6_STATE_SOLICITATION = 2, DHCP6_STATE_REQUEST = 3, DHCP6_STATE_BOUND = 4, DHCP6_STATE_RENEW = 5, DHCP6_STATE_REBIND = 6, }; enum { DHCP6_SOLICIT = 1, DHCP6_ADVERTISE = 2, DHCP6_REQUEST = 3, DHCP6_CONFIRM = 4, DHCP6_RENEW = 5, DHCP6_REBIND = 6, DHCP6_REPLY = 7, DHCP6_RELEASE = 8, DHCP6_DECLINE = 9, DHCP6_RECONFIGURE = 10, DHCP6_INFORMATION_REQUEST = 11, DHCP6_RELAY_FORW = 12, DHCP6_RELAY_REPL = 13, _DHCP6_MESSAGE_MAX = 14, }; enum { DHCP6_NTP_SUBOPTION_SRV_ADDR = 1, DHCP6_NTP_SUBOPTION_MC_ADDR = 2, DHCP6_NTP_SUBOPTION_SRV_FQDN = 3, }; enum { DHCP6_STATUS_SUCCESS = 0, DHCP6_STATUS_UNSPEC_FAIL = 1, DHCP6_STATUS_NO_ADDRS_AVAIL = 2, DHCP6_STATUS_NO_BINDING = 3, DHCP6_STATUS_NOT_ON_LINK = 4, DHCP6_STATUS_USE_MULTICAST = 5, _DHCP6_STATUS_MAX = 6, }; systemd-229/src/libsystemd-network/icmp6-util.c000066400000000000000000000101211265713322000216460ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include "fd-util.h" #include "icmp6-util.h" #include "socket-util.h" #define IN6ADDR_ALL_ROUTERS_MULTICAST_INIT \ { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } } } #define IN6ADDR_ALL_NODES_MULTICAST_INIT \ { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } } int icmp6_bind_router_solicitation(int index) { struct icmp6_filter filter = { }; struct ipv6_mreq mreq = { .ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT, .ipv6mr_interface = index, }; _cleanup_close_ int s = -1; int r, zero = 0, one = 1, hops = 255; s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_ICMPV6); if (s < 0) return -errno; ICMP6_FILTER_SETBLOCKALL(&filter); ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter); r = setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)); if (r < 0) return -errno; /* RFC 3315, section 6.7, bullet point 2 may indicate that an IPV6_PKTINFO socket option also applies for ICMPv6 multicast. Empirical experiments indicates otherwise and therefore an IPV6_MULTICAST_IF socket option is used here instead */ r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index)); if (r < 0) return -errno; r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &zero, sizeof(zero)); if (r < 0) return -errno; r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)); if (r < 0) return -errno; r = setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); if (r < 0) return -errno; r = setsockopt(s, SOL_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one)); if (r < 0) return -errno; r = s; s = -1; return r; } int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) { struct sockaddr_in6 dst = { .sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ALL_ROUTERS_MULTICAST_INIT, }; struct { struct nd_router_solicit rs; struct nd_opt_hdr rs_opt; struct ether_addr rs_opt_mac; } _packed_ rs = { .rs.nd_rs_type = ND_ROUTER_SOLICIT, .rs_opt.nd_opt_type = ND_OPT_SOURCE_LINKADDR, .rs_opt.nd_opt_len = 1, }; struct iovec iov = { .iov_base = &rs, .iov_len = sizeof(rs), }; struct msghdr msg = { .msg_name = &dst, .msg_namelen = sizeof(dst), .msg_iov = &iov, .msg_iovlen = 1, }; int r; assert(s >= 0); assert(ether_addr); rs.rs_opt_mac = *ether_addr; r = sendmsg(s, &msg, 0); if (r < 0) return -errno; return 0; } systemd-229/src/libsystemd-network/icmp6-util.h000066400000000000000000000016251265713322000216640ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2014-2015 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include int icmp6_bind_router_solicitation(int index); int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr); systemd-229/src/libsystemd-network/lldp-internal.c000066400000000000000000000234311265713322000224320ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-lldp.h" #include "alloc-util.h" #include "lldp-internal.h" /* We store maximum 1K chassis entries */ #define LLDP_MIB_MAX_CHASSIS 1024 /* Maximum Ports can be attached to any chassis */ #define LLDP_MIB_MAX_PORT_PER_CHASSIS 32 /* 10.5.5.2.2 mibUpdateObjects () * The mibUpdateObjects () procedure updates the MIB objects corresponding to * the TLVs contained in the received LLDPDU for the LLDP remote system * indicated by the LLDP remote systems update process defined in 10.3.5 */ int lldp_mib_update_objects(lldp_chassis *c, tlv_packet *tlv) { lldp_neighbour_port *p; uint16_t length, ttl; uint8_t *data; uint8_t type; int r; assert_return(c, -EINVAL); assert_return(tlv, -EINVAL); r = sd_lldp_packet_read_port_id(tlv, &type, &data, &length); if (r < 0) return r; /* Update the packet if we already have */ LIST_FOREACH(port, p, c->ports) { if ((p->type == type && p->length == length && !memcmp(p->data, data, p->length))) { r = sd_lldp_packet_read_ttl(tlv, &ttl); if (r < 0) return r; p->until = ttl * USEC_PER_SEC + now(clock_boottime_or_monotonic()); sd_lldp_packet_unref(p->packet); p->packet = tlv; prioq_reshuffle(p->c->by_expiry, p, &p->prioq_idx); return 0; } } return -1; } int lldp_mib_remove_objects(lldp_chassis *c, tlv_packet *tlv) { lldp_neighbour_port *p, *q; uint8_t *data; uint16_t length; uint8_t type; int r; assert_return(c, -EINVAL); assert_return(tlv, -EINVAL); r = sd_lldp_packet_read_port_id(tlv, &type, &data, &length); if (r < 0) return r; LIST_FOREACH_SAFE(port, p, q, c->ports) { /* Find the port */ if (p->type == type && p->length == length && !memcmp(p->data, data, p->length)) { lldp_neighbour_port_remove_and_free(p); break; } } return 0; } int lldp_mib_add_objects(Prioq *by_expiry, Hashmap *neighbour_mib, tlv_packet *tlv) { _cleanup_lldp_neighbour_port_free_ lldp_neighbour_port *p = NULL; _cleanup_lldp_chassis_free_ lldp_chassis *c = NULL; lldp_chassis_id chassis_id; bool new_chassis = false; uint8_t subtype, *data; uint16_t ttl, length; int r; assert_return(by_expiry, -EINVAL); assert_return(neighbour_mib, -EINVAL); assert_return(tlv, -EINVAL); r = sd_lldp_packet_read_chassis_id(tlv, &subtype, &data, &length); if (r < 0) goto drop; r = sd_lldp_packet_read_ttl(tlv, &ttl); if (r < 0) goto drop; /* Make hash key */ chassis_id.type = subtype; chassis_id.length = length; chassis_id.data = data; /* Try to find the Chassis */ c = hashmap_get(neighbour_mib, &chassis_id); if (!c) { /* Don't create chassis if ttl 0 is received . Silently drop it */ if (ttl == 0) { log_lldp("TTL value 0 received. Skiping Chassis creation."); goto drop; } /* Admission Control: Can we store this packet ? */ if (hashmap_size(neighbour_mib) >= LLDP_MIB_MAX_CHASSIS) { log_lldp("Exceeding number of chassie: %d. Dropping ...", hashmap_size(neighbour_mib)); goto drop; } r = lldp_chassis_new(tlv, by_expiry, neighbour_mib, &c); if (r < 0) goto drop; new_chassis = true; r = hashmap_put(neighbour_mib, &c->chassis_id, c); if (r < 0) goto drop; } else { /* When the TTL field is set to zero, the receiving LLDP agent is notified all * system information associated with the LLDP agent/port is to be deleted */ if (ttl == 0) { log_lldp("TTL value 0 received . Deleting associated Port ..."); lldp_mib_remove_objects(c, tlv); c = NULL; goto drop; } /* if we already have this port just update it */ r = lldp_mib_update_objects(c, tlv); if (r >= 0) { c = NULL; return r; } /* Admission Control: Can this port attached to the existing chassis ? */ if (c->n_ref >= LLDP_MIB_MAX_PORT_PER_CHASSIS) { log_lldp("Port limit reached. Chassis has: %d ports. Dropping ...", c->n_ref); c = NULL; goto drop; } } /* This is a new port */ r = lldp_neighbour_port_new(c, tlv, &p); if (r < 0) goto drop; r = prioq_put(c->by_expiry, p, &p->prioq_idx); if (r < 0) goto drop; /* Attach new port to chassis */ LIST_PREPEND(port, c->ports, p); c->n_ref ++; p = NULL; c = NULL; return 0; drop: sd_lldp_packet_unref(tlv); if (new_chassis) hashmap_remove(neighbour_mib, &c->chassis_id); return r; } void lldp_neighbour_port_remove_and_free(lldp_neighbour_port *p) { lldp_chassis *c; assert(p); assert(p->c); c = p->c; prioq_remove(c->by_expiry, p, &p->prioq_idx); LIST_REMOVE(port, c->ports, p); lldp_neighbour_port_free(p); /* Drop the Chassis if no port is attached */ c->n_ref --; if (c->n_ref <= 1) { hashmap_remove(c->neighbour_mib, &c->chassis_id); lldp_chassis_free(c); } } void lldp_neighbour_port_free(lldp_neighbour_port *p) { if(!p) return; sd_lldp_packet_unref(p->packet); free(p->data); free(p); } int lldp_neighbour_port_new(lldp_chassis *c, tlv_packet *tlv, lldp_neighbour_port **ret) { _cleanup_lldp_neighbour_port_free_ lldp_neighbour_port *p = NULL; uint16_t length, ttl; uint8_t *data; uint8_t type; int r; assert(tlv); r = sd_lldp_packet_read_port_id(tlv, &type, &data, &length); if (r < 0) return r; r = sd_lldp_packet_read_ttl(tlv, &ttl); if (r < 0) return r; p = new0(lldp_neighbour_port, 1); if (!p) return -ENOMEM; p->c = c; p->type = type; p->length = length; p->packet = tlv; p->prioq_idx = PRIOQ_IDX_NULL; p->until = ttl * USEC_PER_SEC + now(clock_boottime_or_monotonic()); p->data = memdup(data, length); if (!p->data) return -ENOMEM; *ret = p; p = NULL; return 0; } void lldp_chassis_free(lldp_chassis *c) { if (!c) return; if (c->n_ref > 1) return; free(c->chassis_id.data); free(c); } int lldp_chassis_new(tlv_packet *tlv, Prioq *by_expiry, Hashmap *neighbour_mib, lldp_chassis **ret) { _cleanup_lldp_chassis_free_ lldp_chassis *c = NULL; uint16_t length; uint8_t *data; uint8_t type; int r; assert(tlv); r = sd_lldp_packet_read_chassis_id(tlv, &type, &data, &length); if (r < 0) return r; c = new0(lldp_chassis, 1); if (!c) return -ENOMEM; c->n_ref = 1; c->chassis_id.type = type; c->chassis_id.length = length; c->chassis_id.data = memdup(data, length); if (!c->chassis_id.data) return -ENOMEM; LIST_HEAD_INIT(c->ports); c->by_expiry = by_expiry; c->neighbour_mib = neighbour_mib; *ret = c; c = NULL; return 0; } int lldp_receive_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_(sd_lldp_packet_unrefp) tlv_packet *packet = NULL; tlv_packet *p; uint16_t length; int r; assert(fd); assert(userdata); r = tlv_packet_new(&packet); if (r < 0) return r; length = read(fd, &packet->pdu, sizeof(packet->pdu)); /* Silently drop the packet */ if ((size_t) length > ETHER_MAX_LEN) return 0; packet->userdata = userdata; p = packet; packet = NULL; return lldp_handle_packet(p, (uint16_t) length); } systemd-229/src/libsystemd-network/lldp-internal.h000066400000000000000000000053631265713322000224430ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "sd-event.h" #include "list.h" #include "lldp-tlv.h" #include "log.h" #include "prioq.h" typedef struct lldp_neighbour_port lldp_neighbour_port; typedef struct lldp_chassis lldp_chassis; typedef struct lldp_chassis_id lldp_chassis_id; typedef struct lldp_agent_statistics lldp_agent_statistics; struct lldp_neighbour_port { uint8_t type; uint8_t *data; uint16_t length; usec_t until; unsigned prioq_idx; lldp_chassis *c; tlv_packet *packet; LIST_FIELDS(lldp_neighbour_port, port); }; int lldp_neighbour_port_new(lldp_chassis *c, tlv_packet *tlv, lldp_neighbour_port **ret); void lldp_neighbour_port_free(lldp_neighbour_port *p); void lldp_neighbour_port_remove_and_free(lldp_neighbour_port *p); DEFINE_TRIVIAL_CLEANUP_FUNC(lldp_neighbour_port *, lldp_neighbour_port_free); #define _cleanup_lldp_neighbour_port_free_ _cleanup_(lldp_neighbour_port_freep) struct lldp_chassis_id { uint8_t type; uint16_t length; uint8_t *data; }; struct lldp_chassis { unsigned n_ref; lldp_chassis_id chassis_id; Prioq *by_expiry; Hashmap *neighbour_mib; LIST_HEAD(lldp_neighbour_port, ports); }; int lldp_chassis_new(tlv_packet *tlv, Prioq *by_expiry, Hashmap *neighbour_mib, lldp_chassis **ret); void lldp_chassis_free(lldp_chassis *c); DEFINE_TRIVIAL_CLEANUP_FUNC(lldp_chassis *, lldp_chassis_free); #define _cleanup_lldp_chassis_free_ _cleanup_(lldp_chassis_freep) int lldp_mib_update_objects(lldp_chassis *c, tlv_packet *tlv); int lldp_mib_add_objects(Prioq *by_expiry, Hashmap *neighbour_mib, tlv_packet *tlv); int lldp_mib_remove_objects(lldp_chassis *c, tlv_packet *tlv); int lldp_handle_packet(tlv_packet *m, uint16_t length); int lldp_receive_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata); #define log_lldp(fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__) systemd-229/src/libsystemd-network/lldp-network.c000066400000000000000000000062741265713322000223150ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "fd-util.h" #include "lldp-internal.h" #include "lldp-network.h" #include "lldp-tlv.h" #include "socket-util.h" int lldp_network_bind_raw_socket(int ifindex) { typedef struct LLDPFrame { struct ethhdr hdr; uint8_t tlvs[0]; } LLDPFrame; struct sock_filter filter[] = { BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(LLDPFrame, hdr.h_dest)), /* A <- 4 bytes of destination MAC */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0180c200, 1, 0), /* A != 01:80:c2:00 */ BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(LLDPFrame, hdr.h_dest) + 4), /* A <- remaining 2 bytes of destination MAC */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0000, 3, 0), /* A != 00:00 */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0003, 2, 0), /* A != 00:03 */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x000e, 1, 0), /* A != 00:0e */ BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(LLDPFrame, hdr.h_proto)), /* A <- protocol */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_LLDP, 1, 0), /* A != ETHERTYPE_LLDP */ BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ BPF_STMT(BPF_RET + BPF_K, (uint32_t) -1), /* accept packet */ }; struct sock_fprog fprog = { .len = ELEMENTSOF(filter), .filter = filter }; _cleanup_close_ int s = -1; union sockaddr_union saddrll = { .ll.sll_family = AF_PACKET, .ll.sll_ifindex = ifindex, }; int r; assert(ifindex > 0); s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (s < 0) return -errno; r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); if (r < 0) return -errno; r = bind(s, &saddrll.sa, sizeof(saddrll.ll)); if (r < 0) return -errno; r = s; s = -1; return r; } systemd-229/src/libsystemd-network/lldp-network.h000066400000000000000000000015051265713322000223120ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "sd-event.h" int lldp_network_bind_raw_socket(int ifindex); systemd-229/src/libsystemd-network/lldp-port.c000066400000000000000000000055341265713322000216060ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "async.h" #include "lldp-internal.h" #include "lldp-network.h" #include "lldp-port.h" int lldp_port_start(lldp_port *p) { int r; assert_return(p, -EINVAL); r = lldp_network_bind_raw_socket(p->ifindex); if (r < 0) return r; p->rawfd = r; r = sd_event_add_io(p->event, &p->lldp_port_rx, p->rawfd, EPOLLIN, lldp_receive_packet, p); if (r < 0) { log_debug_errno(r, "Failed to allocate event source: %m"); goto fail; } r = sd_event_source_set_priority(p->lldp_port_rx, p->event_priority); if (r < 0) { log_debug_errno(r, "Failed to set event priority: %m"); goto fail; } r = sd_event_source_set_description(p->lldp_port_rx, "lldp-port-rx"); if (r < 0) { log_debug_errno(r, "Failed to set event name: %m"); goto fail; } return 0; fail: lldp_port_stop(p); return r; } int lldp_port_stop(lldp_port *p) { assert_return(p, -EINVAL); p->rawfd = asynchronous_close(p->rawfd); p->lldp_port_rx = sd_event_source_unref(p->lldp_port_rx); return 0; } void lldp_port_free(lldp_port *p) { if (!p) return; lldp_port_stop(p); free(p->ifname); free(p); } int lldp_port_new(int ifindex, const char *ifname, const struct ether_addr *addr, void *userdata, lldp_port **ret) { _cleanup_free_ lldp_port *p = NULL; assert_return(ifindex, -EINVAL); assert_return(ifname, -EINVAL); assert_return(addr, -EINVAL); p = new0(lldp_port, 1); if (!p) return -ENOMEM; p->rawfd = -1; p->ifindex = ifindex; p->ifname = strdup(ifname); if (!p->ifname) return -ENOMEM; memcpy(&p->mac, addr, ETH_ALEN); p->userdata = userdata; *ret = p; p = NULL; return 0; } systemd-229/src/libsystemd-network/lldp-port.h000066400000000000000000000034021265713322000216030ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include #include "sd-event.h" #include "sd-lldp.h" #include "util.h" typedef struct lldp_port lldp_port; typedef enum LLDPPortStatus { LLDP_PORT_STATUS_NONE, LLDP_PORT_STATUS_ENABLED, LLDP_PORT_STATUS_DISABLED, _LLDP_PORT_STATUS_MAX, _LLDP_PORT_STATUS_INVALID = -1, } LLDPPortStatus; struct lldp_port { LLDPPortStatus status; int ifindex; char *ifname; struct ether_addr mac; int rawfd; sd_event *event; sd_event_source *lldp_port_rx; int event_priority; void *userdata; }; int lldp_port_new(int ifindex, const char *ifname, const struct ether_addr *addr, void *userdata, lldp_port **ret); void lldp_port_free(lldp_port *p); DEFINE_TRIVIAL_CLEANUP_FUNC(lldp_port*, lldp_port_free); #define _cleanup_lldp_port_free_ _cleanup_(lldp_port_freep) int lldp_port_start(lldp_port *p); int lldp_port_stop(lldp_port *p); systemd-229/src/libsystemd-network/lldp-tlv.c000066400000000000000000000377171265713322000214370ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "lldp-tlv.h" #include "macro.h" int tlv_section_new(tlv_section **ret) { tlv_section *s; s = new0(tlv_section, 1); if (!s) return -ENOMEM; *ret = s; return 0; } void tlv_section_free(tlv_section *m) { if (!m) return; free(m); } int tlv_packet_new(tlv_packet **ret) { tlv_packet *m; m = new0(tlv_packet, 1); if (!m) return -ENOMEM; LIST_HEAD_INIT(m->sections); m->n_ref = 1; *ret = m; return 0; } tlv_packet *sd_lldp_packet_ref(tlv_packet *m) { if (!m) return NULL; assert(m->n_ref > 0); m->n_ref++; return m; } tlv_packet *sd_lldp_packet_unref(tlv_packet *m) { tlv_section *s, *n; if (!m) return NULL; assert(m->n_ref > 0); m->n_ref--; if (m->n_ref > 0) return m; LIST_FOREACH_SAFE(section, s, n, m->sections) tlv_section_free(s); free(m); return NULL; } int tlv_packet_append_bytes(tlv_packet *m, const void *data, size_t data_length) { uint8_t *p; assert_return(m, -EINVAL); assert_return(data, -EINVAL); assert_return(data_length, -EINVAL); if (m->length + data_length > ETHER_MAX_LEN) return -ENOMEM; p = m->pdu + m->length; memcpy(p, data, data_length); m->length += data_length; return 0; } int tlv_packet_append_u8(tlv_packet *m, uint8_t data) { assert_return(m, -EINVAL); return tlv_packet_append_bytes(m, &data, sizeof(uint8_t)); } int tlv_packet_append_u16(tlv_packet *m, uint16_t data) { uint16_t type; assert_return(m, -EINVAL); type = htons(data); return tlv_packet_append_bytes(m, &type, sizeof(uint16_t)); } int tlv_packet_append_u32(tlv_packet *m, uint32_t data) { uint32_t type; assert_return(m, -EINVAL); type = htonl(data); return tlv_packet_append_bytes(m, &type, sizeof(uint32_t)); } int tlv_packet_append_string(tlv_packet *m, char *data, uint16_t size) { assert_return(m, -EINVAL); return tlv_packet_append_bytes(m, data, size); } int lldp_tlv_packet_open_container(tlv_packet *m, uint16_t type) { assert_return(m, -EINVAL); m->container_pos = m->pdu + m->length; return tlv_packet_append_u16(m, type << 9); } int lldp_tlv_packet_close_container(tlv_packet *m) { uint16_t type; assert_return(m, -EINVAL); assert_return(m->container_pos, -EINVAL); memcpy(&type, m->container_pos, sizeof(uint16_t)); type |= htons(((m->pdu + m->length) - (m->container_pos + 2)) & 0x01ff); memcpy(m->container_pos, &type, sizeof(uint16_t)); return 0; } static inline int tlv_packet_read_internal(tlv_section *m, void **data) { assert_return(m->read_pos, -EINVAL); *data = m->read_pos; return 0; } int tlv_packet_read_u8(tlv_packet *m, uint8_t *data) { void *val = NULL; int r; assert_return(m, -EINVAL); r = tlv_packet_read_internal(m->container, &val); if (r < 0) return r; memcpy(data, val, sizeof(uint8_t)); m->container->read_pos ++; return 0; } int tlv_packet_read_u16(tlv_packet *m, uint16_t *data) { uint16_t t; void *val = NULL; int r; assert_return(m, -EINVAL); r = tlv_packet_read_internal(m->container, &val); if (r < 0) return r; memcpy(&t, val, sizeof(uint16_t)); *data = ntohs(t); m->container->read_pos += 2; return 0; } int tlv_packet_read_u32(tlv_packet *m, uint32_t *data) { uint32_t t; void *val; int r; assert_return(m, -EINVAL); r = tlv_packet_read_internal(m->container, &val); if (r < 0) return r; memcpy(&t, val, sizeof(uint32_t)); *data = ntohl(t); m->container->read_pos += 4; return r; } int tlv_packet_read_string(tlv_packet *m, char **data, uint16_t *data_length) { void *val = NULL; int r; assert_return(m, -EINVAL); r = tlv_packet_read_internal(m->container, &val); if (r < 0) return r; *data = (char *) val; *data_length = m->container->data + m->container->length - m->container->read_pos; m->container->read_pos += *data_length; return 0; } int tlv_packet_read_bytes(tlv_packet *m, uint8_t **data, uint16_t *data_length) { void *val = NULL; int r; assert_return(m, -EINVAL); r = tlv_packet_read_internal(m->container, &val); if (r < 0) return r; *data = (uint8_t *) val; *data_length = m->container->data + m->container->length - m->container->read_pos; m->container->read_pos += *data_length; return 0; } /* parse raw TLV packet */ int tlv_packet_parse_pdu(tlv_packet *m, uint16_t size) { tlv_section *section, *tail; uint16_t t, l; uint8_t *p; int r; assert_return(m, -EINVAL); assert_return(size, -EINVAL); p = m->pdu; /* extract Ethernet header */ memcpy(&m->mac, p, ETH_ALEN); p += sizeof(struct ether_header); for (l = 0; l <= size; ) { r = tlv_section_new(§ion); if (r < 0) return r; memcpy(&t, p, sizeof(uint16_t)); section->type = ntohs(t) >> 9; section->length = ntohs(t) & 0x01ff; if (section->type == LLDP_TYPE_END || section->type >=_LLDP_TYPE_MAX) { tlv_section_free(section); break; } p += 2; if (section->type == LLDP_TYPE_PRIVATE && section->length >= LLDP_OUI_LEN + 1) { section->oui = p; p += LLDP_OUI_LEN; section->subtype = *p++; section->length -= LLDP_OUI_LEN + 1; l += LLDP_OUI_LEN + 1; } section->data = p; LIST_FIND_TAIL(section, m->sections, tail); LIST_INSERT_AFTER(section, m->sections, tail, section); p += section->length; l += (section->length + 2); } return 0; } int lldp_tlv_packet_enter_container(tlv_packet *m, uint16_t type) { tlv_section *s; assert_return(m, -EINVAL); assert_return(type != LLDP_TYPE_PRIVATE, -EINVAL); LIST_FOREACH(section, s, m->sections) if (s->type == type) break; if (!s) return -1; m->container = s; m->container->read_pos = s->data; if (!m->container->read_pos) { m->container = NULL; return -1; } return 0; } int lldp_tlv_packet_enter_container_oui(tlv_packet *m, const uint8_t *oui, uint8_t subtype) { tlv_section *s; assert_return(m, -EINVAL); assert_return(oui, -EINVAL); LIST_FOREACH(section, s, m->sections) { if (s->type == LLDP_TYPE_PRIVATE && s->oui && s->subtype == subtype && !memcmp(s->oui, oui, LLDP_OUI_LEN)) break; } if (!s) return -1; m->container = s; m->container->read_pos = s->data; if (!m->container->read_pos) { m->container = NULL; return -1; } return 0; } int lldp_tlv_packet_exit_container(tlv_packet *m) { assert_return(m, -EINVAL); m->container = 0; return 0; } static int lldp_tlv_packet_read_u16_tlv(tlv_packet *tlv, uint16_t type, uint16_t *value) { int r, r2; assert_return(tlv, -EINVAL); r = lldp_tlv_packet_enter_container(tlv, type); if (r < 0) return r; r = tlv_packet_read_u16(tlv, value); r2 = lldp_tlv_packet_exit_container(tlv); return r < 0 ? r : r2; } static int lldp_tlv_packet_read_string_tlv(tlv_packet *tlv, uint16_t type, char **data, uint16_t *length) { char *s; int r, r2; assert_return(tlv, -EINVAL); r = lldp_tlv_packet_enter_container(tlv, type); if (r < 0) return r; r = tlv_packet_read_string(tlv, &s, length); if (r < 0) goto out; *data = (char *) s; out: r2 = lldp_tlv_packet_exit_container(tlv); return r < 0 ? r : r2; } int sd_lldp_packet_read_chassis_id(tlv_packet *tlv, uint8_t *type, uint8_t **data, uint16_t *length) { uint8_t subtype; int r, r2; assert_return(tlv, -EINVAL); r = lldp_tlv_packet_enter_container(tlv, LLDP_TYPE_CHASSIS_ID); if (r < 0) return r; r = tlv_packet_read_u8(tlv, &subtype); if (r < 0) goto out; switch (subtype) { case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: r = tlv_packet_read_bytes(tlv, data, length); if (r < 0) goto out; break; default: r = -EOPNOTSUPP; break; } *type = subtype; out: r2 = lldp_tlv_packet_exit_container(tlv); return r < 0 ? r : r2; } int sd_lldp_packet_read_port_id(tlv_packet *tlv, uint8_t *type, uint8_t **data, uint16_t *length) { uint8_t subtype; char *s; int r, r2; assert_return(tlv, -EINVAL); r = lldp_tlv_packet_enter_container(tlv, LLDP_TYPE_PORT_ID); if (r < 0) return r; r = tlv_packet_read_u8(tlv, &subtype); if (r < 0) goto out; switch (subtype) { case LLDP_PORT_SUBTYPE_PORT_COMPONENT: case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: case LLDP_PORT_SUBTYPE_INTERFACE_NAME: case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED: r = tlv_packet_read_string(tlv, &s, length); if (r < 0) goto out; *data = (uint8_t *) s; break; case LLDP_PORT_SUBTYPE_MAC_ADDRESS: r = tlv_packet_read_bytes(tlv, data, length); if (r < 0) goto out; break; default: r = -EOPNOTSUPP; break; } *type = subtype; out: r2 = lldp_tlv_packet_exit_container(tlv); return r < 0 ? r : r2; } int sd_lldp_packet_read_ttl(tlv_packet *tlv, uint16_t *ttl) { return lldp_tlv_packet_read_u16_tlv(tlv, LLDP_TYPE_TTL, ttl); } int sd_lldp_packet_read_system_name(tlv_packet *tlv, char **data, uint16_t *length) { return lldp_tlv_packet_read_string_tlv(tlv, LLDP_TYPE_SYSTEM_NAME, data, length); } int sd_lldp_packet_read_system_description(tlv_packet *tlv, char **data, uint16_t *length) { return lldp_tlv_packet_read_string_tlv(tlv, LLDP_TYPE_SYSTEM_DESCRIPTION, data, length); } int sd_lldp_packet_read_port_description(tlv_packet *tlv, char **data, uint16_t *length) { return lldp_tlv_packet_read_string_tlv(tlv, LLDP_TYPE_PORT_DESCRIPTION, data, length); } int sd_lldp_packet_read_system_capability(tlv_packet *tlv, uint16_t *data) { return lldp_tlv_packet_read_u16_tlv(tlv, LLDP_TYPE_SYSTEM_CAPABILITIES, data); } int sd_lldp_packet_read_port_vlan_id(tlv_packet *tlv, uint16_t *id) { int r, r2; assert_return(tlv, -EINVAL); r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_PORT_VLAN_ID); if (r < 0) return r; r = tlv_packet_read_u16(tlv, id); r2 = lldp_tlv_packet_exit_container(tlv); return r < 0 ? r : r2; } int sd_lldp_packet_read_port_protocol_vlan_id(sd_lldp_packet *tlv, uint8_t *flags, uint16_t *id) { int r, r2; assert_return(tlv, -EINVAL); r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_PORT_PROTOCOL_VLAN_ID); if (r < 0) return r; r = tlv_packet_read_u8(tlv, flags); if (r >= 0) r = tlv_packet_read_u16(tlv, id); r2 = lldp_tlv_packet_exit_container(tlv); return r < 0 ? r : r2; } int sd_lldp_packet_read_vlan_name(tlv_packet *tlv, uint16_t *vlan_id, char **name, uint16_t *length) { int r, r2; uint8_t len = 0; assert_return(tlv, -EINVAL); r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_VLAN_NAME); if (r < 0) return r; r = tlv_packet_read_u16(tlv, vlan_id); if (r >= 0) r = tlv_packet_read_u8(tlv, &len); if (r >= 0) r = tlv_packet_read_string(tlv, name, length); if (r >= 0 && len < *length) *length = len; r2 = lldp_tlv_packet_exit_container(tlv); return r < 0 ? r : r2; } int sd_lldp_packet_read_management_vid(tlv_packet *tlv, uint16_t *id) { int r, r2; assert_return(tlv, -EINVAL); r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_MANAGEMENT_VID); if (r < 0) return r; r = tlv_packet_read_u16(tlv, id); r2 = lldp_tlv_packet_exit_container(tlv); return r < 0 ? r : r2; } int sd_lldp_packet_read_link_aggregation(sd_lldp_packet *tlv, uint8_t *status, uint32_t *id) { int r, r2; assert_return(tlv, -EINVAL); r = lldp_tlv_packet_enter_container_oui(tlv, LLDP_OUI_802_1, LLDP_OUI_SUBTYPE_802_1_LINK_AGGREGATION); if (r < 0) return r; r = tlv_packet_read_u8(tlv, status); if (r >= 0) r = tlv_packet_read_u32(tlv, id); r2 = lldp_tlv_packet_exit_container(tlv); return r < 0 ? r : r2; } int sd_lldp_packet_get_destination_type(tlv_packet *tlv, int *dest) { assert_return(tlv, -EINVAL); assert_return(dest, -EINVAL); /* 802.1AB-2009, Table 7-1 */ if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_BRIDGE, ETH_ALEN)) *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE; else if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_NON_TPMR_BRIDGE, ETH_ALEN)) *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE; else if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_CUSTOMER_BRIDGE, ETH_ALEN)) *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_CUSTOMER_BRIDGE; else return -EINVAL; return 0; } systemd-229/src/libsystemd-network/lldp-tlv.h000066400000000000000000000056161265713322000214350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include #include "sd-lldp.h" #include "list.h" #include "lldp.h" #include "util.h" typedef struct sd_lldp_packet tlv_packet; typedef struct sd_lldp_section tlv_section; #define LLDP_OUI_LEN 3 struct sd_lldp_section { uint16_t type; uint16_t length; uint8_t *oui; uint8_t subtype; uint8_t *read_pos; uint8_t *data; LIST_FIELDS(tlv_section, section); }; #define LLDP_MAC_NEAREST_BRIDGE (uint8_t[]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e } #define LLDP_MAC_NEAREST_NON_TPMR_BRIDGE (uint8_t[]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 } #define LLDP_MAC_NEAREST_CUSTOMER_BRIDGE (uint8_t[]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 } int tlv_section_new(tlv_section **ret); void tlv_section_free(tlv_section *ret); struct sd_lldp_packet { unsigned n_ref; uint16_t type; uint16_t length; usec_t ts; uint8_t *container_pos; uint8_t pdu[ETHER_MAX_LEN]; void *userdata; struct ether_addr mac; tlv_section *container; LIST_HEAD(tlv_section, sections); }; int tlv_packet_new(tlv_packet **ret); int lldp_tlv_packet_open_container(tlv_packet *m, uint16_t type); int lldp_tlv_packet_close_container(tlv_packet *m); int tlv_packet_append_bytes(tlv_packet *m, const void *data, size_t data_length); int tlv_packet_append_u8(tlv_packet *m, uint8_t data); int tlv_packet_append_u16(tlv_packet *m, uint16_t data); int tlv_packet_append_u32(tlv_packet *m, uint32_t data); int tlv_packet_append_string(tlv_packet *m, char *data, uint16_t size); int lldp_tlv_packet_enter_container(tlv_packet *m, uint16_t type); int lldp_tlv_packet_enter_container_oui(tlv_packet *m, const uint8_t *oui, uint8_t subtype); int lldp_tlv_packet_exit_container(tlv_packet *m); int tlv_packet_read_bytes(tlv_packet *m, uint8_t **data, uint16_t *data_length); int tlv_packet_read_string(tlv_packet *m, char **data, uint16_t *data_length); int tlv_packet_read_u8(tlv_packet *m, uint8_t *data); int tlv_packet_read_u16(tlv_packet *m, uint16_t *data); int tlv_packet_read_u32(tlv_packet *m, uint32_t *data); int tlv_packet_parse_pdu(tlv_packet *t, uint16_t size); systemd-229/src/libsystemd-network/lldp.h000066400000000000000000000120731265713322000206250ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #define LLDP_MULTICAST_ADDR { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e } #define ETHERTYPE_LLDP 0x88cc /* IEEE 802.3AB Clause 9: TLV Types */ typedef enum LLDPTypes { LLDP_TYPE_END = 0, LLDP_TYPE_CHASSIS_ID = 1, LLDP_TYPE_PORT_ID = 2, LLDP_TYPE_TTL = 3, LLDP_TYPE_PORT_DESCRIPTION = 4, LLDP_TYPE_SYSTEM_NAME = 5, LLDP_TYPE_SYSTEM_DESCRIPTION = 6, LLDP_TYPE_SYSTEM_CAPABILITIES = 7, LLDP_TYPE_MGMT_ADDRESS = 8, LLDP_TYPE_PRIVATE = 127, _LLDP_TYPE_MAX, _LLDP_TYPE_INVALID = -1, } LLDPTypes; /* IEEE 802.3AB Clause 9.5.2: Chassis subtypes */ typedef enum LLDPChassisSubtypes { LLDP_CHASSIS_SUBTYPE_RESERVED = 0, LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT = 1, LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS = 2, LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT = 3, LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS = 4, LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS = 5, LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME = 6, LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED = 7, _LLDP_CHASSIS_SUBTYPE_MAX, _LLDP_CHASSIS_SUBTYPE_INVALID = -1, } LLDPChassisSubtypes; /* IEEE 802.3AB Clause 9.5.3: Port subtype */ typedef enum LLDPPortSubtypes { LLDP_PORT_SUBTYPE_RESERVED = 0, LLDP_PORT_SUBTYPE_INTERFACE_ALIAS = 1, LLDP_PORT_SUBTYPE_PORT_COMPONENT = 2, LLDP_PORT_SUBTYPE_MAC_ADDRESS = 3, LLDP_PORT_SUBTYPE_NETWORK = 4, LLDP_PORT_SUBTYPE_INTERFACE_NAME = 5, LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6, LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7, _LLDP_PORT_SUBTYPE_MAX, _LLDP_PORT_SUBTYPE_INVALID = -1 } LLDPPortSubtypes; typedef enum LLDPSystemCapabilities { LLDP_SYSTEM_CAPABILITIES_OTHER = 1 << 0, LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1, LLDP_SYSTEM_CAPABILITIES_BRIDGE = 1 << 2, LLDP_SYSTEM_CAPABILITIES_WLAN_AP = 1 << 3, LLDP_SYSTEM_CAPABILITIES_ROUTER = 1 << 4, LLDP_SYSTEM_CAPABILITIES_PHONE = 1 << 5, LLDP_SYSTEM_CAPABILITIES_DOCSIS = 1 << 6, LLDP_SYSTEM_CAPABILITIES_STATION = 1 << 7, LLDP_SYSTEM_CAPABILITIES_CVLAN = 1 << 8, LLDP_SYSTEM_CAPABILITIES_SVLAN = 1 << 9, LLDP_SYSTEM_CAPABILITIES_TPMR = 1 << 10, _LLDP_SYSTEM_CAPABILITIES_MAX, _LLDP_SYSTEM_CAPABILITIES_INVALID = -1, } LLDPSystemCapabilities; typedef enum LLDPMedSubtype { LLDP_MED_SUBTYPE_RESERVED = 0, LLDP_MED_SUBTYPE_CAPABILITIES = 1, LLDP_MED_SUBTYPE_NETWORK_POLICY = 2, LLDP_MED_SUBTYPE_LOCATION_ID = 3, LLDP_MED_SUBTYPE_EXTENDED_PVMDI = 4, LLDP_MED_SUBTYPE_INV_HWREV = 5, LLDP_MED_SUBTYPE_INV_FWREV = 6, LLDP_MED_SUBTYPE_INV_SWREV = 7, LLDP_MED_SUBTYPE_INV_SERIAL = 8, LLDP_MED_SUBTYPE_INV_MANUFACTURER = 9, LLDP_MED_SUBTYPE_INV_MODELNAME = 10, LLDP_MED_SUBTYPE_INV_ASSETID = 11, _LLDP_MED_SUBTYPE_MAX, _LLDP_MED_SUBTYPE_INVALID = -1, } LLDPMedSubtype; typedef enum LLDPMedCapability { LLDP_MED_CAPABILITY_CAPAPILITIES = 1 << 0, LLDP_MED_CAPABILITY_NETWORK_POLICY = 1 << 1, LLDP_MED_CAPABILITY_LOCATION_ID = 1 << 2, LLDP_MED_CAPABILITY_EXTENDED_PSE = 1 << 3, LLDP_MED_CAPABILITY_EXTENDED_PD = 1 << 4, LLDP_MED_CAPABILITY_INVENTORY = 1 << 5, LLDP_MED_CAPABILITY_MAX, LLDP_MED_CAPABILITY_INVALID = -1, } LLDPMedCapability; #define LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 } #define LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f } enum { LLDP_OUI_SUBTYPE_802_1_PORT_VLAN_ID = 1, LLDP_OUI_SUBTYPE_802_1_PORT_PROTOCOL_VLAN_ID = 2, LLDP_OUI_SUBTYPE_802_1_VLAN_NAME = 3, LLDP_OUI_SUBTYPE_802_1_PROTOCOL_IDENTITY = 4, LLDP_OUI_SUBTYPE_802_1_VID_USAGE_DIGEST = 5, LLDP_OUI_SUBTYPE_802_1_MANAGEMENT_VID = 6, LLDP_OUI_SUBTYPE_802_1_LINK_AGGREGATION = 7, }; systemd-229/src/libsystemd-network/network-internal.c000066400000000000000000000375531265713322000232020ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-ndisc.h" #include "alloc-util.h" #include "condition.h" #include "conf-parser.h" #include "dhcp-lease-internal.h" #include "hexdecoct.h" #include "log.h" #include "network-internal.h" #include "parse-util.h" #include "siphash24.h" #include "string-util.h" #include "strv.h" #include "utf8.h" #include "util.h" const char *net_get_name(struct udev_device *device) { const char *name, *field; assert(device); /* fetch some persistent data unique (on this machine) to this device */ FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") { name = udev_device_get_property_value(device, field); if (name) return name; } return NULL; } #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a) int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result) { size_t l, sz = 0; const char *name = NULL; int r; uint8_t *v; assert(device); name = net_get_name(device); if (!name) return -ENOENT; l = strlen(name); sz = sizeof(sd_id128_t) + l; v = alloca(sz); /* fetch some persistent data unique to this machine */ r = sd_id128_get_machine((sd_id128_t*) v); if (r < 0) return r; memcpy(v + sizeof(sd_id128_t), name, l); /* Let's hash the machine ID plus the device name. We * use a fixed, but originally randomly created hash * key here. */ *result = htole64(siphash24(v, sz, HASH_KEY.bytes)); return 0; } bool net_match_config(const struct ether_addr *match_mac, char * const *match_paths, char * const *match_drivers, char * const *match_types, char * const *match_names, Condition *match_host, Condition *match_virt, Condition *match_kernel, Condition *match_arch, const struct ether_addr *dev_mac, const char *dev_path, const char *dev_parent_driver, const char *dev_driver, const char *dev_type, const char *dev_name) { if (match_host && !condition_test(match_host)) return false; if (match_virt && !condition_test(match_virt)) return false; if (match_kernel && !condition_test(match_kernel)) return false; if (match_arch && !condition_test(match_arch)) return false; if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN))) return false; if (!strv_isempty(match_paths) && (!dev_path || !strv_fnmatch(match_paths, dev_path, 0))) return false; if (!strv_isempty(match_drivers) && (!dev_driver || !strv_fnmatch(match_drivers, dev_driver, 0))) return false; if (!strv_isempty(match_types) && (!dev_type || !strv_fnmatch_or_empty(match_types, dev_type, 0))) return false; if (!strv_isempty(match_names) && (!dev_name || !strv_fnmatch_or_empty(match_names, dev_name, 0))) return false; return true; } int config_parse_net_condition(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { ConditionType cond = ltype; Condition **ret = data; bool negate; Condition *c; _cleanup_free_ char *s = NULL; assert(filename); assert(lvalue); assert(rvalue); assert(data); negate = rvalue[0] == '!'; if (negate) rvalue++; s = strdup(rvalue); if (!s) return log_oom(); c = condition_new(cond, s, false, negate); if (!c) return log_oom(); if (*ret) condition_free(*ret); *ret = c; return 0; } int config_parse_ifname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { char **s = data; _cleanup_free_ char *n = NULL; assert(filename); assert(lvalue); assert(rvalue); assert(data); n = strdup(rvalue); if (!n) return log_oom(); if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) { log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue); return 0; } free(*s); if (*n) { *s = n; n = NULL; } else *s = NULL; return 0; } int config_parse_ifnames(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { char ***sv = data; const char *word, *state; size_t l; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); FOREACH_WORD(word, l, rvalue, state) { char *n; n = strndup(word, l); if (!n) return log_oom(); if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) { log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue); free(n); return 0; } r = strv_consume(sv, n); if (r < 0) return log_oom(); } return 0; } int config_parse_ifalias(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { char **s = data; _cleanup_free_ char *n = NULL; assert(filename); assert(lvalue); assert(rvalue); assert(data); n = strdup(rvalue); if (!n) return log_oom(); if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) { log_syntax(unit, LOG_ERR, filename, line, 0, "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue); return 0; } free(*s); if (*n) { *s = n; n = NULL; } else *s = NULL; return 0; } int config_parse_hwaddr(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { struct ether_addr **hwaddr = data; struct ether_addr *n; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); n = new0(struct ether_addr, 1); if (!n) return log_oom(); r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &n->ether_addr_octet[0], &n->ether_addr_octet[1], &n->ether_addr_octet[2], &n->ether_addr_octet[3], &n->ether_addr_octet[4], &n->ether_addr_octet[5]); if (r != 6) { log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue); free(n); return 0; } free(*hwaddr); *hwaddr = n; return 0; } void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) { unsigned i; assert(f); assert(addresses); assert(size); for (i = 0; i < size; i++) fprintf(f, "%s%s", inet_ntoa(addresses[i]), (i < (size - 1)) ? " ": ""); } int deserialize_in_addrs(struct in_addr **ret, const char *string) { _cleanup_free_ struct in_addr *addresses = NULL; int size = 0; const char *word, *state; size_t len; assert(ret); assert(string); FOREACH_WORD(word, len, string, state) { _cleanup_free_ char *addr_str = NULL; struct in_addr *new_addresses; int r; new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr)); if (!new_addresses) return -ENOMEM; else addresses = new_addresses; addr_str = strndup(word, len); if (!addr_str) return -ENOMEM; r = inet_pton(AF_INET, addr_str, &(addresses[size])); if (r <= 0) continue; size ++; } *ret = addresses; addresses = NULL; return size; } void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, size_t size) { unsigned i; assert(f); assert(addresses); assert(size); for (i = 0; i < size; i++) fprintf(f, SD_NDISC_ADDRESS_FORMAT_STR"%s", SD_NDISC_ADDRESS_FORMAT_VAL(addresses[i]), (i < (size - 1)) ? " ": ""); } int deserialize_in6_addrs(struct in6_addr **ret, const char *string) { _cleanup_free_ struct in6_addr *addresses = NULL; int size = 0; const char *word, *state; size_t len; assert(ret); assert(string); FOREACH_WORD(word, len, string, state) { _cleanup_free_ char *addr_str = NULL; struct in6_addr *new_addresses; int r; new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr)); if (!new_addresses) return -ENOMEM; else addresses = new_addresses; addr_str = strndup(word, len); if (!addr_str) return -ENOMEM; r = inet_pton(AF_INET6, addr_str, &(addresses[size])); if (r <= 0) continue; size++; } *ret = addresses; addresses = NULL; return size; } void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) { unsigned i; assert(f); assert(key); assert(routes); assert(size); fprintf(f, "%s=", key); for (i = 0; i < size; i++) { struct in_addr dest, gw; uint8_t length; assert_se(sd_dhcp_route_get_destination(routes[i], &dest) >= 0); assert_se(sd_dhcp_route_get_gateway(routes[i], &gw) >= 0); assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &length) >= 0); fprintf(f, "%s/%" PRIu8, inet_ntoa(dest), length); fprintf(f, ",%s%s", inet_ntoa(gw), (i < (size - 1)) ? " ": ""); } fputs("\n", f); } int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) { _cleanup_free_ struct sd_dhcp_route *routes = NULL; size_t size = 0, allocated = 0; const char *word, *state; size_t len; assert(ret); assert(ret_size); assert(ret_allocated); assert(string); FOREACH_WORD(word, len, string, state) { /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */ _cleanup_free_ char* entry = NULL; char *tok, *tok_end; unsigned n; int r; if (!GREEDY_REALLOC(routes, allocated, size + 1)) return -ENOMEM; entry = strndup(word, len); if(!entry) return -ENOMEM; tok = entry; /* get the subnet */ tok_end = strchr(tok, '/'); if (!tok_end) continue; *tok_end = '\0'; r = inet_aton(tok, &routes[size].dst_addr); if (r == 0) continue; tok = tok_end + 1; /* get the prefixlen */ tok_end = strchr(tok, ','); if (!tok_end) continue; *tok_end = '\0'; r = safe_atou(tok, &n); if (r < 0 || n > 32) continue; routes[size].dst_prefixlen = (uint8_t) n; tok = tok_end + 1; /* get the gateway */ r = inet_aton(tok, &routes[size].gw_addr); if (r == 0) continue; size++; } *ret_size = size; *ret_allocated = allocated; *ret = routes; routes = NULL; return 0; } int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size) { _cleanup_free_ char *hex_buf = NULL; assert(f); assert(key); assert(data); hex_buf = hexmem(data, size); if (hex_buf == NULL) return -ENOMEM; fprintf(f, "%s=%s\n", key, hex_buf); return 0; } int deserialize_dhcp_option(void **data, size_t *data_len, const char *string) { assert(data); assert(data_len); assert(string); if (strlen(string) % 2) return -EINVAL; return unhexmem(string, strlen(string), (void **)data, data_len); } systemd-229/src/libsystemd-network/network-internal.h000066400000000000000000000073561265713322000232050ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-dhcp-lease.h" #include "condition.h" #include "udev.h" bool net_match_config(const struct ether_addr *match_mac, char * const *match_path, char * const *match_driver, char * const *match_type, char * const *match_name, Condition *match_host, Condition *match_virt, Condition *match_kernel, Condition *match_arch, const struct ether_addr *dev_mac, const char *dev_path, const char *dev_parent_driver, const char *dev_driver, const char *dev_type, const char *dev_name); int config_parse_net_condition(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_hwaddr(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_ifname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_ifnames(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_ifalias(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result); const char *net_get_name(struct udev_device *device); void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size); int deserialize_in_addrs(struct in_addr **addresses, const char *string); void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, size_t size); int deserialize_in6_addrs(struct in6_addr **addresses, const char *string); /* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */ struct sd_dhcp_route; void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size); int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string); int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size); int deserialize_dhcp_option(void **data, size_t *data_len, const char *string); systemd-229/src/libsystemd-network/sd-dhcp-client.c000066400000000000000000001740631265713322000224730ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "sd-dhcp-client.h" #include "alloc-util.h" #include "async.h" #include "dhcp-identifier.h" #include "dhcp-internal.h" #include "dhcp-lease-internal.h" #include "dhcp-protocol.h" #include "dns-domain.h" #include "hostname-util.h" #include "random-util.h" #include "string-util.h" #include "util.h" #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */ #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN) #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC) #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE) struct sd_dhcp_client { unsigned n_ref; DHCPState state; sd_event *event; int event_priority; sd_event_source *timeout_resend; int index; int fd; union sockaddr_union link; sd_event_source *receive_message; bool request_broadcast; uint8_t *req_opts; size_t req_opts_allocated; size_t req_opts_size; be32_t last_addr; uint8_t mac_addr[MAX_MAC_ADDR_LEN]; size_t mac_addr_len; uint16_t arp_type; struct { uint8_t type; union { struct { /* 0: Generic (non-LL) (RFC 2132) */ uint8_t data[MAX_CLIENT_ID_LEN]; } _packed_ gen; struct { /* 1: Ethernet Link-Layer (RFC 2132) */ uint8_t haddr[ETH_ALEN]; } _packed_ eth; struct { /* 2 - 254: ARP/Link-Layer (RFC 2132) */ uint8_t haddr[0]; } _packed_ ll; struct { /* 255: Node-specific (RFC 4361) */ uint32_t iaid; struct duid duid; } _packed_ ns; struct { uint8_t data[MAX_CLIENT_ID_LEN]; } _packed_ raw; }; } _packed_ client_id; size_t client_id_len; char *hostname; char *vendor_class_identifier; uint32_t mtu; uint32_t xid; usec_t start_time; unsigned int attempt; usec_t request_sent; sd_event_source *timeout_t1; sd_event_source *timeout_t2; sd_event_source *timeout_expire; sd_dhcp_client_cb_t cb; void *userdata; sd_dhcp_lease *lease; usec_t start_delay; }; static const uint8_t default_req_opts[] = { SD_DHCP_OPTION_SUBNET_MASK, SD_DHCP_OPTION_ROUTER, SD_DHCP_OPTION_HOST_NAME, SD_DHCP_OPTION_DOMAIN_NAME, SD_DHCP_OPTION_DOMAIN_NAME_SERVER, }; static int client_receive_message_raw(sd_event_source *s, int fd, uint32_t revents, void *userdata); static int client_receive_message_udp(sd_event_source *s, int fd, uint32_t revents, void *userdata); static void client_stop(sd_dhcp_client *client, int error); int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb, void *userdata) { assert_return(client, -EINVAL); client->cb = cb; client->userdata = userdata; return 0; } int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) { assert_return(client, -EINVAL); client->request_broadcast = !!broadcast; return 0; } int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) { size_t i; assert_return(client, -EINVAL); assert_return (IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY); switch(option) { case SD_DHCP_OPTION_PAD: case SD_DHCP_OPTION_OVERLOAD: case SD_DHCP_OPTION_MESSAGE_TYPE: case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST: case SD_DHCP_OPTION_END: return -EINVAL; default: break; } for (i = 0; i < client->req_opts_size; i++) if (client->req_opts[i] == option) return -EEXIST; if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated, client->req_opts_size + 1)) return -ENOMEM; client->req_opts[client->req_opts_size++] = option; return 0; } int sd_dhcp_client_set_request_address(sd_dhcp_client *client, const struct in_addr *last_addr) { assert_return(client, -EINVAL); assert_return (IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY); if (last_addr) client->last_addr = last_addr->s_addr; else client->last_addr = INADDR_ANY; return 0; } int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) { assert_return(client, -EINVAL); assert_return (IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY); assert_return(interface_index > 0, -EINVAL); client->index = interface_index; return 0; } int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr, size_t addr_len, uint16_t arp_type) { DHCP_CLIENT_DONT_DESTROY(client); bool need_restart = false; assert_return(client, -EINVAL); assert_return(addr, -EINVAL); assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL); assert_return(arp_type > 0, -EINVAL); if (arp_type == ARPHRD_ETHER) assert_return(addr_len == ETH_ALEN, -EINVAL); else if (arp_type == ARPHRD_INFINIBAND) assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); else return -EINVAL; if (client->mac_addr_len == addr_len && memcmp(&client->mac_addr, addr, addr_len) == 0) return 0; if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { log_dhcp_client(client, "Changing MAC address on running DHCP " "client, restarting"); need_restart = true; client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); } memcpy(&client->mac_addr, addr, addr_len); client->mac_addr_len = addr_len; client->arp_type = arp_type; if (need_restart && client->state != DHCP_STATE_STOPPED) sd_dhcp_client_start(client); return 0; } int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type, const uint8_t **data, size_t *data_len) { assert_return(client, -EINVAL); assert_return(type, -EINVAL); assert_return(data, -EINVAL); assert_return(data_len, -EINVAL); *type = 0; *data = NULL; *data_len = 0; if (client->client_id_len) { *type = client->client_id.type; *data = client->client_id.raw.data; *data_len = client->client_id_len - sizeof(client->client_id.type); } return 0; } int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type, const uint8_t *data, size_t data_len) { DHCP_CLIENT_DONT_DESTROY(client); bool need_restart = false; assert_return(client, -EINVAL); assert_return(data, -EINVAL); assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL); switch (type) { case ARPHRD_ETHER: if (data_len != ETH_ALEN) return -EINVAL; break; case ARPHRD_INFINIBAND: if (data_len != INFINIBAND_ALEN) return -EINVAL; break; default: break; } if (client->client_id_len == data_len + sizeof(client->client_id.type) && client->client_id.type == type && memcmp(&client->client_id.raw.data, data, data_len) == 0) return 0; if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { log_dhcp_client(client, "Changing client ID on running DHCP " "client, restarting"); need_restart = true; client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); } client->client_id.type = type; memcpy(&client->client_id.raw.data, data, data_len); client->client_id_len = data_len + sizeof (client->client_id.type); if (need_restart && client->state != DHCP_STATE_STOPPED) sd_dhcp_client_start(client); return 0; } int sd_dhcp_client_set_hostname(sd_dhcp_client *client, const char *hostname) { char *new_hostname = NULL; assert_return(client, -EINVAL); if (!hostname_is_valid(hostname, false) && !dns_name_is_valid(hostname)) return -EINVAL; if (streq_ptr(client->hostname, hostname)) return 0; if (hostname) { new_hostname = strdup(hostname); if (!new_hostname) return -ENOMEM; } free(client->hostname); client->hostname = new_hostname; return 0; } int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client, const char *vci) { char *new_vci = NULL; assert_return(client, -EINVAL); new_vci = strdup(vci); if (!new_vci) return -ENOMEM; free(client->vendor_class_identifier); client->vendor_class_identifier = new_vci; return 0; } int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) { assert_return(client, -EINVAL); assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE); client->mtu = mtu; return 0; } int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) { assert_return(client, -EINVAL); assert_return(ret, -EINVAL); if (client->state != DHCP_STATE_BOUND && client->state != DHCP_STATE_RENEWING && client->state != DHCP_STATE_REBINDING) return -EADDRNOTAVAIL; *ret = client->lease; return 0; } static void client_notify(sd_dhcp_client *client, int event) { if (client->cb) client->cb(client, event, client->userdata); } static int client_initialize(sd_dhcp_client *client) { assert_return(client, -EINVAL); client->receive_message = sd_event_source_unref(client->receive_message); client->fd = asynchronous_close(client->fd); client->timeout_resend = sd_event_source_unref(client->timeout_resend); client->timeout_t1 = sd_event_source_unref(client->timeout_t1); client->timeout_t2 = sd_event_source_unref(client->timeout_t2); client->timeout_expire = sd_event_source_unref(client->timeout_expire); client->attempt = 1; client->state = DHCP_STATE_INIT; client->xid = 0; client->lease = sd_dhcp_lease_unref(client->lease); return 0; } static void client_stop(sd_dhcp_client *client, int error) { assert(client); if (error < 0) log_dhcp_client(client, "STOPPED: %s", strerror(-error)); else if (error == SD_DHCP_CLIENT_EVENT_STOP) log_dhcp_client(client, "STOPPED"); else log_dhcp_client(client, "STOPPED: Unknown event"); client_notify(client, error); client_initialize(client); } static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret, uint8_t type, size_t *_optlen, size_t *_optoffset) { _cleanup_free_ DHCPPacket *packet; size_t optlen, optoffset, size; be16_t max_size; usec_t time_now; uint16_t secs; int r; assert(client); assert(client->start_time); assert(ret); assert(_optlen); assert(_optoffset); assert(type == DHCP_DISCOVER || type == DHCP_REQUEST); optlen = DHCP_MIN_OPTIONS_SIZE; size = sizeof(DHCPPacket) + optlen; packet = malloc0(size); if (!packet) return -ENOMEM; r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type, client->arp_type, optlen, &optoffset); if (r < 0) return r; /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers refuse to issue an DHCP lease if 'secs' is set to zero */ r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); if (r < 0) return r; assert(time_now >= client->start_time); /* seconds between sending first and last DISCOVER * must always be strictly positive to deal with broken servers */ secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1; packet->dhcp.secs = htobe16(secs); /* RFC2132 section 4.1 A client that cannot receive unicast IP datagrams until its protocol software has been configured with an IP address SHOULD set the BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or DHCPREQUEST messages that client sends. The BROADCAST bit will provide a hint to the DHCP server and BOOTP relay agent to broadcast any messages to the client on the client's subnet. Note: some interfaces needs this to be enabled, but some networks needs this to be disabled as broadcasts are filteretd, so this needs to be configurable */ if (client->request_broadcast || client->arp_type != ARPHRD_ETHER) packet->dhcp.flags = htobe16(0x8000); /* RFC2132 section 4.1.1: The client MUST include its hardware address in the ’chaddr’ field, if necessary for delivery of DHCP reply messages. Non-Ethernet interfaces will leave 'chaddr' empty and use the client identifier instead (eg, RFC 4390 section 2.1). */ if (client->arp_type == ARPHRD_ETHER) memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN); /* If no client identifier exists, construct an RFC 4361-compliant one */ if (client->client_id_len == 0) { size_t duid_len; client->client_id.type = 255; r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid); if (r < 0) return r; r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &duid_len); if (r < 0) return r; client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + duid_len; } /* Some DHCP servers will refuse to issue an DHCP lease if the Client Identifier option is not set */ if (client->client_id_len) { r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_CLIENT_IDENTIFIER, client->client_id_len, &client->client_id); if (r < 0) return r; } /* RFC2131 section 3.5: in its initial DHCPDISCOVER or DHCPREQUEST message, a client may provide the server with a list of specific parameters the client is interested in. If the client includes a list of parameters in a DHCPDISCOVER message, it MUST include that list in any subsequent DHCPREQUEST messages. */ r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST, client->req_opts_size, client->req_opts); if (r < 0) return r; /* RFC2131 section 3.5: The client SHOULD include the ’maximum DHCP message size’ option to let the server know how large the server may make its DHCP messages. Note (from ConnMan): Some DHCP servers will send bigger DHCP packets than the defined default size unless the Maximum Messge Size option is explicitly set RFC3442 "Requirements to Avoid Sizing Constraints": Because a full routing table can be quite large, the standard 576 octet maximum size for a DHCP message may be too short to contain some legitimate Classless Static Route options. Because of this, clients implementing the Classless Static Route option SHOULD send a Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP stack is capable of receiving larger IP datagrams. In this case, the client SHOULD set the value of this option to at least the MTU of the interface that the client is configuring. The client MAY set the value of this option higher, up to the size of the largest UDP packet it is prepared to accept. (Note that the value specified in the Maximum DHCP Message Size option is the total maximum packet size, including IP and UDP headers.) */ max_size = htobe16(size); r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0, SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE, 2, &max_size); if (r < 0) return r; *_optlen = optlen; *_optoffset = optoffset; *ret = packet; packet = NULL; return 0; } static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t *optoffset, const char *fqdn) { uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH]; int r; buffer[0] = DHCP_FQDN_FLAG_S | /* Request server to perform A RR DNS updates */ DHCP_FQDN_FLAG_E; /* Canonical wire format */ buffer[1] = 0; /* RCODE1 (deprecated) */ buffer[2] = 0; /* RCODE2 (deprecated) */ r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3, false); if (r > 0) r = dhcp_option_append(message, optlen, optoffset, 0, SD_DHCP_OPTION_FQDN, 3 + r, buffer); return r; } static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet, size_t len) { dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT, INADDR_BROADCAST, DHCP_PORT_SERVER, len); return dhcp_network_send_raw_socket(client->fd, &client->link, packet, len); } static int client_send_discover(sd_dhcp_client *client) { _cleanup_free_ DHCPPacket *discover = NULL; size_t optoffset, optlen; int r; assert(client); assert(client->state == DHCP_STATE_INIT || client->state == DHCP_STATE_SELECTING); r = client_message_init(client, &discover, DHCP_DISCOVER, &optlen, &optoffset); if (r < 0) return r; /* the client may suggest values for the network address and lease time in the DHCPDISCOVER message. The client may include the ’requested IP address’ option to suggest that a particular IP address be assigned, and may include the ’IP address lease time’ option to suggest the lease time it would like. */ if (client->last_addr != INADDR_ANY) { r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, 4, &client->last_addr); if (r < 0) return r; } if (client->hostname) { /* According to RFC 4702 "clients that send the Client FQDN option in their messages MUST NOT also send the Host Name option". Just send one of the two depending on the hostname type. */ if (dns_name_is_single_label(client->hostname)) { /* it is unclear from RFC 2131 if client should send hostname in DHCPDISCOVER but dhclient does and so we do as well */ r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_HOST_NAME, strlen(client->hostname), client->hostname); } else r = client_append_fqdn_option(&discover->dhcp, optlen, &optoffset, client->hostname); if (r < 0) return r; } if (client->vendor_class_identifier) { r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER, strlen(client->vendor_class_identifier), client->vendor_class_identifier); if (r < 0) return r; } r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL); if (r < 0) return r; /* We currently ignore: The client SHOULD wait a random time between one and ten seconds to desynchronize the use of DHCP at startup. */ r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset); if (r < 0) return r; log_dhcp_client(client, "DISCOVER"); return 0; } static int client_send_request(sd_dhcp_client *client) { _cleanup_free_ DHCPPacket *request = NULL; size_t optoffset, optlen; int r; r = client_message_init(client, &request, DHCP_REQUEST, &optlen, &optoffset); if (r < 0) return r; switch (client->state) { /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC, SELECTING should be REQUESTING) */ case DHCP_STATE_REQUESTING: /* Client inserts the address of the selected server in ’server identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be filled in with the yiaddr value from the chosen DHCPOFFER. */ r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_SERVER_IDENTIFIER, 4, &client->lease->server_address); if (r < 0) return r; r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, 4, &client->lease->address); if (r < 0) return r; break; case DHCP_STATE_INIT_REBOOT: /* ’server identifier’ MUST NOT be filled in, ’requested IP address’ option MUST be filled in with client’s notion of its previously assigned address. ’ciaddr’ MUST be zero. */ r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, 4, &client->last_addr); if (r < 0) return r; break; case DHCP_STATE_RENEWING: /* ’server identifier’ MUST NOT be filled in, ’requested IP address’ option MUST NOT be filled in, ’ciaddr’ MUST be filled in with client’s IP address. */ /* fall through */ case DHCP_STATE_REBINDING: /* ’server identifier’ MUST NOT be filled in, ’requested IP address’ option MUST NOT be filled in, ’ciaddr’ MUST be filled in with client’s IP address. This message MUST be broadcast to the 0xffffffff IP broadcast address. */ request->dhcp.ciaddr = client->lease->address; break; case DHCP_STATE_INIT: case DHCP_STATE_SELECTING: case DHCP_STATE_REBOOTING: case DHCP_STATE_BOUND: case DHCP_STATE_STOPPED: return -EINVAL; } if (client->hostname) { if (dns_name_is_single_label(client->hostname)) r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_HOST_NAME, strlen(client->hostname), client->hostname); else r = client_append_fqdn_option(&request->dhcp, optlen, &optoffset, client->hostname); if (r < 0) return r; } r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL); if (r < 0) return r; if (client->state == DHCP_STATE_RENEWING) { r = dhcp_network_send_udp_socket(client->fd, client->lease->server_address, DHCP_PORT_SERVER, &request->dhcp, sizeof(DHCPMessage) + optoffset); } else { r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset); } if (r < 0) return r; switch (client->state) { case DHCP_STATE_REQUESTING: log_dhcp_client(client, "REQUEST (requesting)"); break; case DHCP_STATE_INIT_REBOOT: log_dhcp_client(client, "REQUEST (init-reboot)"); break; case DHCP_STATE_RENEWING: log_dhcp_client(client, "REQUEST (renewing)"); break; case DHCP_STATE_REBINDING: log_dhcp_client(client, "REQUEST (rebinding)"); break; default: log_dhcp_client(client, "REQUEST (invalid)"); break; } return 0; } static int client_start(sd_dhcp_client *client); static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp_client *client = userdata; DHCP_CLIENT_DONT_DESTROY(client); usec_t next_timeout = 0; uint64_t time_now; uint32_t time_left; int r; assert(s); assert(client); assert(client->event); r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); if (r < 0) goto error; switch (client->state) { case DHCP_STATE_RENEWING: time_left = (client->lease->t2 - client->lease->t1) / 2; if (time_left < 60) time_left = 60; next_timeout = time_now + time_left * USEC_PER_SEC; break; case DHCP_STATE_REBINDING: time_left = (client->lease->lifetime - client->lease->t2) / 2; if (time_left < 60) time_left = 60; next_timeout = time_now + time_left * USEC_PER_SEC; break; case DHCP_STATE_REBOOTING: /* start over as we did not receive a timely ack or nak */ r = client_initialize(client); if (r < 0) goto error; r = client_start(client); if (r < 0) goto error; else { log_dhcp_client(client, "REBOOTED"); return 0; } case DHCP_STATE_INIT: case DHCP_STATE_INIT_REBOOT: case DHCP_STATE_SELECTING: case DHCP_STATE_REQUESTING: case DHCP_STATE_BOUND: if (client->attempt < 64) client->attempt *= 2; next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC; break; case DHCP_STATE_STOPPED: r = -EINVAL; goto error; } next_timeout += (random_u32() & 0x1fffff); client->timeout_resend = sd_event_source_unref(client->timeout_resend); r = sd_event_add_time(client->event, &client->timeout_resend, clock_boottime_or_monotonic(), next_timeout, 10 * USEC_PER_MSEC, client_timeout_resend, client); if (r < 0) goto error; r = sd_event_source_set_priority(client->timeout_resend, client->event_priority); if (r < 0) goto error; r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer"); if (r < 0) goto error; switch (client->state) { case DHCP_STATE_INIT: r = client_send_discover(client); if (r >= 0) { client->state = DHCP_STATE_SELECTING; client->attempt = 1; } else { if (client->attempt >= 64) goto error; } break; case DHCP_STATE_SELECTING: r = client_send_discover(client); if (r < 0 && client->attempt >= 64) goto error; break; case DHCP_STATE_INIT_REBOOT: case DHCP_STATE_REQUESTING: case DHCP_STATE_RENEWING: case DHCP_STATE_REBINDING: r = client_send_request(client); if (r < 0 && client->attempt >= 64) goto error; if (client->state == DHCP_STATE_INIT_REBOOT) client->state = DHCP_STATE_REBOOTING; client->request_sent = time_now; break; case DHCP_STATE_REBOOTING: case DHCP_STATE_BOUND: break; case DHCP_STATE_STOPPED: r = -EINVAL; goto error; } return 0; error: client_stop(client, r); /* Errors were dealt with when stopping the client, don't spill errors into the event loop handler */ return 0; } static int client_initialize_io_events(sd_dhcp_client *client, sd_event_io_handler_t io_callback) { int r; assert(client); assert(client->event); r = sd_event_add_io(client->event, &client->receive_message, client->fd, EPOLLIN, io_callback, client); if (r < 0) goto error; r = sd_event_source_set_priority(client->receive_message, client->event_priority); if (r < 0) goto error; r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message"); if (r < 0) goto error; error: if (r < 0) client_stop(client, r); return 0; } static int client_initialize_time_events(sd_dhcp_client *client) { uint64_t usec = 0; int r; assert(client); assert(client->event); client->timeout_resend = sd_event_source_unref(client->timeout_resend); if (client->start_delay) { sd_event_now(client->event, clock_boottime_or_monotonic(), &usec); usec += client->start_delay; } r = sd_event_add_time(client->event, &client->timeout_resend, clock_boottime_or_monotonic(), usec, 0, client_timeout_resend, client); if (r < 0) goto error; r = sd_event_source_set_priority(client->timeout_resend, client->event_priority); if (r < 0) goto error; r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer"); if (r < 0) goto error; error: if (r < 0) client_stop(client, r); return 0; } static int client_initialize_events(sd_dhcp_client *client, sd_event_io_handler_t io_callback) { client_initialize_io_events(client, io_callback); client_initialize_time_events(client); return 0; } static int client_start_delayed(sd_dhcp_client *client) { int r; assert_return(client, -EINVAL); assert_return(client->event, -EINVAL); assert_return(client->index > 0, -EINVAL); assert_return(client->fd < 0, -EBUSY); assert_return(client->xid == 0, -EINVAL); assert_return(client->state == DHCP_STATE_INIT || client->state == DHCP_STATE_INIT_REBOOT, -EBUSY); client->xid = random_u32(); r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid, client->mac_addr, client->mac_addr_len, client->arp_type); if (r < 0) { client_stop(client, r); return r; } client->fd = r; if (client->state == DHCP_STATE_INIT || client->state == DHCP_STATE_INIT_REBOOT) client->start_time = now(clock_boottime_or_monotonic()); return client_initialize_events(client, client_receive_message_raw); } static int client_start(sd_dhcp_client *client) { client->start_delay = 0; return client_start_delayed(client); } static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp_client *client = userdata; DHCP_CLIENT_DONT_DESTROY(client); log_dhcp_client(client, "EXPIRED"); client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED); /* lease was lost, start over if not freed or stopped in callback */ if (client->state != DHCP_STATE_STOPPED) { client_initialize(client); client_start(client); } return 0; } static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp_client *client = userdata; DHCP_CLIENT_DONT_DESTROY(client); int r; client->receive_message = sd_event_source_unref(client->receive_message); client->fd = asynchronous_close(client->fd); client->state = DHCP_STATE_REBINDING; client->attempt = 1; r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid, client->mac_addr, client->mac_addr_len, client->arp_type); if (r < 0) { client_stop(client, r); return 0; } client->fd = r; return client_initialize_events(client, client_receive_message_raw); } static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp_client *client = userdata; DHCP_CLIENT_DONT_DESTROY(client); client->state = DHCP_STATE_RENEWING; client->attempt = 1; return client_initialize_time_events(client); } static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_t len) { _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; int r; r = dhcp_lease_new(&lease); if (r < 0) return r; if (client->client_id_len) { r = dhcp_lease_set_client_id(lease, (uint8_t *) &client->client_id, client->client_id_len); if (r < 0) return r; } r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease, NULL); if (r != DHCP_OFFER) { log_dhcp_client(client, "received message was not an OFFER, ignoring"); return -ENOMSG; } lease->next_server = offer->siaddr; lease->address = offer->yiaddr; if (lease->address == 0 || lease->server_address == 0 || lease->lifetime == 0) { log_dhcp_client(client, "received lease lacks address, server address or lease lifetime, ignoring"); return -ENOMSG; } if (!lease->have_subnet_mask) { r = dhcp_lease_set_default_subnet_mask(lease); if (r < 0) { log_dhcp_client(client, "received lease lacks subnet " "mask, and a fallback one can not be " "generated, ignoring"); return -ENOMSG; } } sd_dhcp_lease_unref(client->lease); client->lease = lease; lease = NULL; log_dhcp_client(client, "OFFER"); return 0; } static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, size_t len) { int r; r = dhcp_option_parse(force, len, NULL, NULL, NULL); if (r != DHCP_FORCERENEW) return -ENOMSG; log_dhcp_client(client, "FORCERENEW"); return 0; } static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t len) { _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; _cleanup_free_ char *error_message = NULL; int r; r = dhcp_lease_new(&lease); if (r < 0) return r; if (client->client_id_len) { r = dhcp_lease_set_client_id(lease, (uint8_t *) &client->client_id, client->client_id_len); if (r < 0) return r; } r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease, &error_message); if (r == DHCP_NAK) { log_dhcp_client(client, "NAK: %s", strna(error_message)); return -EADDRNOTAVAIL; } if (r != DHCP_ACK) { log_dhcp_client(client, "received message was not an ACK, ignoring"); return -ENOMSG; } lease->next_server = ack->siaddr; lease->address = ack->yiaddr; if (lease->address == INADDR_ANY || lease->server_address == INADDR_ANY || lease->lifetime == 0) { log_dhcp_client(client, "received lease lacks address, server " "address or lease lifetime, ignoring"); return -ENOMSG; } if (lease->subnet_mask == INADDR_ANY) { r = dhcp_lease_set_default_subnet_mask(lease); if (r < 0) { log_dhcp_client(client, "received lease lacks subnet " "mask, and a fallback one can not be " "generated, ignoring"); return -ENOMSG; } } r = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE; if (client->lease) { if (client->lease->address != lease->address || client->lease->subnet_mask != lease->subnet_mask || client->lease->router != lease->router) { r = SD_DHCP_CLIENT_EVENT_IP_CHANGE; } else r = SD_DHCP_CLIENT_EVENT_RENEW; client->lease = sd_dhcp_lease_unref(client->lease); } client->lease = lease; lease = NULL; log_dhcp_client(client, "ACK"); return r; } static uint64_t client_compute_timeout(sd_dhcp_client *client, uint32_t lifetime, double factor) { assert(client); assert(client->request_sent); assert(lifetime > 0); if (lifetime > 3) lifetime -= 3; else lifetime = 0; return client->request_sent + (lifetime * USEC_PER_SEC * factor) + + (random_u32() & 0x1fffff); } static int client_set_lease_timeouts(sd_dhcp_client *client) { usec_t time_now; uint64_t lifetime_timeout; uint64_t t2_timeout; uint64_t t1_timeout; char time_string[FORMAT_TIMESPAN_MAX]; int r; assert(client); assert(client->event); assert(client->lease); assert(client->lease->lifetime); client->timeout_t1 = sd_event_source_unref(client->timeout_t1); client->timeout_t2 = sd_event_source_unref(client->timeout_t2); client->timeout_expire = sd_event_source_unref(client->timeout_expire); /* don't set timers for infinite leases */ if (client->lease->lifetime == 0xffffffff) return 0; r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); if (r < 0) return r; assert(client->request_sent <= time_now); /* convert the various timeouts from relative (secs) to absolute (usecs) */ lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1); if (client->lease->t1 > 0 && client->lease->t2 > 0) { /* both T1 and T2 are given */ if (client->lease->t1 < client->lease->t2 && client->lease->t2 < client->lease->lifetime) { /* they are both valid */ t2_timeout = client_compute_timeout(client, client->lease->t2, 1); t1_timeout = client_compute_timeout(client, client->lease->t1, 1); } else { /* discard both */ t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0); client->lease->t2 = (client->lease->lifetime * 7) / 8; t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5); client->lease->t1 = client->lease->lifetime / 2; } } else if (client->lease->t2 > 0 && client->lease->t2 < client->lease->lifetime) { /* only T2 is given, and it is valid */ t2_timeout = client_compute_timeout(client, client->lease->t2, 1); t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5); client->lease->t1 = client->lease->lifetime / 2; if (t2_timeout <= t1_timeout) { /* the computed T1 would be invalid, so discard T2 */ t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0); client->lease->t2 = (client->lease->lifetime * 7) / 8; } } else if (client->lease->t1 > 0 && client->lease->t1 < client->lease->lifetime) { /* only T1 is given, and it is valid */ t1_timeout = client_compute_timeout(client, client->lease->t1, 1); t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0); client->lease->t2 = (client->lease->lifetime * 7) / 8; if (t2_timeout <= t1_timeout) { /* the computed T2 would be invalid, so discard T1 */ t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5); client->lease->t2 = client->lease->lifetime / 2; } } else { /* fall back to the default timeouts */ t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5); client->lease->t1 = client->lease->lifetime / 2; t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0); client->lease->t2 = (client->lease->lifetime * 7) / 8; } /* arm lifetime timeout */ r = sd_event_add_time(client->event, &client->timeout_expire, clock_boottime_or_monotonic(), lifetime_timeout, 10 * USEC_PER_MSEC, client_timeout_expire, client); if (r < 0) return r; r = sd_event_source_set_priority(client->timeout_expire, client->event_priority); if (r < 0) return r; r = sd_event_source_set_description(client->timeout_expire, "dhcp4-lifetime"); if (r < 0) return r; log_dhcp_client(client, "lease expires in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_timeout - time_now, USEC_PER_SEC)); /* don't arm earlier timeouts if this has already expired */ if (lifetime_timeout <= time_now) return 0; /* arm T2 timeout */ r = sd_event_add_time(client->event, &client->timeout_t2, clock_boottime_or_monotonic(), t2_timeout, 10 * USEC_PER_MSEC, client_timeout_t2, client); if (r < 0) return r; r = sd_event_source_set_priority(client->timeout_t2, client->event_priority); if (r < 0) return r; r = sd_event_source_set_description(client->timeout_t2, "dhcp4-t2-timeout"); if (r < 0) return r; log_dhcp_client(client, "T2 expires in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, t2_timeout - time_now, USEC_PER_SEC)); /* don't arm earlier timeout if this has already expired */ if (t2_timeout <= time_now) return 0; /* arm T1 timeout */ r = sd_event_add_time(client->event, &client->timeout_t1, clock_boottime_or_monotonic(), t1_timeout, 10 * USEC_PER_MSEC, client_timeout_t1, client); if (r < 0) return r; r = sd_event_source_set_priority(client->timeout_t1, client->event_priority); if (r < 0) return r; r = sd_event_source_set_description(client->timeout_t1, "dhcp4-t1-timer"); if (r < 0) return r; log_dhcp_client(client, "T1 expires in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, t1_timeout - time_now, USEC_PER_SEC)); return 0; } static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, int len) { DHCP_CLIENT_DONT_DESTROY(client); char time_string[FORMAT_TIMESPAN_MAX]; int r = 0, notify_event = 0; assert(client); assert(client->event); assert(message); switch (client->state) { case DHCP_STATE_SELECTING: r = client_handle_offer(client, message, len); if (r >= 0) { client->timeout_resend = sd_event_source_unref(client->timeout_resend); client->state = DHCP_STATE_REQUESTING; client->attempt = 1; r = sd_event_add_time(client->event, &client->timeout_resend, clock_boottime_or_monotonic(), 0, 0, client_timeout_resend, client); if (r < 0) goto error; r = sd_event_source_set_priority(client->timeout_resend, client->event_priority); if (r < 0) goto error; r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer"); if (r < 0) goto error; } else if (r == -ENOMSG) /* invalid message, let's ignore it */ return 0; break; case DHCP_STATE_REBOOTING: case DHCP_STATE_REQUESTING: case DHCP_STATE_RENEWING: case DHCP_STATE_REBINDING: r = client_handle_ack(client, message, len); if (r >= 0) { client->start_delay = 0; client->timeout_resend = sd_event_source_unref(client->timeout_resend); client->receive_message = sd_event_source_unref(client->receive_message); client->fd = asynchronous_close(client->fd); if (IN_SET(client->state, DHCP_STATE_REQUESTING, DHCP_STATE_REBOOTING)) notify_event = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE; else if (r != SD_DHCP_CLIENT_EVENT_IP_ACQUIRE) notify_event = r; client->state = DHCP_STATE_BOUND; client->attempt = 1; client->last_addr = client->lease->address; r = client_set_lease_timeouts(client); if (r < 0) { log_dhcp_client(client, "could not set lease timeouts"); goto error; } r = dhcp_network_bind_udp_socket(client->lease->address, DHCP_PORT_CLIENT); if (r < 0) { log_dhcp_client(client, "could not bind UDP socket"); goto error; } client->fd = r; client_initialize_io_events(client, client_receive_message_udp); if (notify_event) { client_notify(client, notify_event); if (client->state == DHCP_STATE_STOPPED) return 0; } } else if (r == -EADDRNOTAVAIL) { /* got a NAK, let's restart the client */ client->timeout_resend = sd_event_source_unref(client->timeout_resend); r = client_initialize(client); if (r < 0) goto error; r = client_start_delayed(client); if (r < 0) goto error; log_dhcp_client(client, "REBOOT in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->start_delay, USEC_PER_SEC)); client->start_delay = CLAMP(client->start_delay * 2, RESTART_AFTER_NAK_MIN_USEC, RESTART_AFTER_NAK_MAX_USEC); return 0; } else if (r == -ENOMSG) /* invalid message, let's ignore it */ return 0; break; case DHCP_STATE_BOUND: r = client_handle_forcerenew(client, message, len); if (r >= 0) { r = client_timeout_t1(NULL, 0, client); if (r < 0) goto error; } else if (r == -ENOMSG) /* invalid message, let's ignore it */ return 0; break; case DHCP_STATE_INIT: case DHCP_STATE_INIT_REBOOT: break; case DHCP_STATE_STOPPED: r = -EINVAL; goto error; } error: if (r < 0) client_stop(client, r); return r; } static int client_receive_message_udp(sd_event_source *s, int fd, uint32_t revents, void *userdata) { sd_dhcp_client *client = userdata; _cleanup_free_ DHCPMessage *message = NULL; int buflen = 0, len, r; const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } }; const struct ether_addr *expected_chaddr = NULL; uint8_t expected_hlen = 0; assert(s); assert(client); r = ioctl(fd, FIONREAD, &buflen); if (r < 0) return -errno; else if (buflen < 0) /* this can't be right */ return -EIO; message = malloc0(buflen); if (!message) return -ENOMEM; len = read(fd, message, buflen); if (len < 0) { if (errno == EAGAIN || errno == EINTR) return 0; log_dhcp_client(client, "Could not receive message from UDP socket: %m"); return -errno; } else if ((size_t)len < sizeof(DHCPMessage)) { log_dhcp_client(client, "Too small to be a DHCP message: ignoring"); return 0; } if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) { log_dhcp_client(client, "Not a DHCP message: ignoring"); return 0; } if (message->op != BOOTREPLY) { log_dhcp_client(client, "Not a BOOTREPLY message: ignoring"); return 0; } if (message->htype != client->arp_type) { log_dhcp_client(client, "Packet type does not match client type"); return 0; } if (client->arp_type == ARPHRD_ETHER) { expected_hlen = ETH_ALEN; expected_chaddr = (const struct ether_addr *) &client->mac_addr; } else { /* Non-Ethernet links expect zero chaddr */ expected_hlen = 0; expected_chaddr = &zero_mac; } if (message->hlen != expected_hlen) { log_dhcp_client(client, "Unexpected packet hlen %d", message->hlen); return 0; } if (memcmp(&message->chaddr[0], expected_chaddr, ETH_ALEN)) { log_dhcp_client(client, "Received chaddr does not match expected: ignoring"); return 0; } if (client->state != DHCP_STATE_BOUND && be32toh(message->xid) != client->xid) { /* in BOUND state, we may receive FORCERENEW with xid set by server, so ignore the xid in this case */ log_dhcp_client(client, "Received xid (%u) does not match expected (%u): ignoring", be32toh(message->xid), client->xid); return 0; } return client_handle_message(client, message, len); } static int client_receive_message_raw(sd_event_source *s, int fd, uint32_t revents, void *userdata) { sd_dhcp_client *client = userdata; _cleanup_free_ DHCPPacket *packet = NULL; uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; struct iovec iov = {}; struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, .msg_control = cmsgbuf, .msg_controllen = sizeof(cmsgbuf), }; struct cmsghdr *cmsg; bool checksum = true; int buflen = 0, len, r; assert(s); assert(client); r = ioctl(fd, FIONREAD, &buflen); if (r < 0) return -errno; else if (buflen < 0) /* this can't be right */ return -EIO; packet = malloc0(buflen); if (!packet) return -ENOMEM; iov.iov_base = packet; iov.iov_len = buflen; len = recvmsg(fd, &msg, 0); if (len < 0) { if (errno == EAGAIN || errno == EINTR) return 0; log_dhcp_client(client, "Could not receive message from raw socket: %m"); return -errno; } else if ((size_t)len < sizeof(DHCPPacket)) return 0; CMSG_FOREACH(cmsg, &msg) { if (cmsg->cmsg_level == SOL_PACKET && cmsg->cmsg_type == PACKET_AUXDATA && cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) { struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg); checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY); break; } } r = dhcp_packet_verify_headers(packet, len, checksum); if (r < 0) return 0; len -= DHCP_IP_UDP_SIZE; return client_handle_message(client, &packet->dhcp, len); } int sd_dhcp_client_start(sd_dhcp_client *client) { int r; assert_return(client, -EINVAL); r = client_initialize(client); if (r < 0) return r; if (client->last_addr) client->state = DHCP_STATE_INIT_REBOOT; r = client_start(client); if (r >= 0) log_dhcp_client(client, "STARTED on ifindex %i", client->index); return r; } int sd_dhcp_client_stop(sd_dhcp_client *client) { DHCP_CLIENT_DONT_DESTROY(client); assert_return(client, -EINVAL); client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); client->state = DHCP_STATE_STOPPED; return 0; } int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int priority) { int r; assert_return(client, -EINVAL); assert_return(!client->event, -EBUSY); if (event) client->event = sd_event_ref(event); else { r = sd_event_default(&client->event); if (r < 0) return 0; } client->event_priority = priority; return 0; } int sd_dhcp_client_detach_event(sd_dhcp_client *client) { assert_return(client, -EINVAL); client->event = sd_event_unref(client->event); return 0; } sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) { if (!client) return NULL; return client->event; } sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) { if (!client) return NULL; assert(client->n_ref >= 1); client->n_ref++; return client; } sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) { if (!client) return NULL; assert(client->n_ref >= 1); client->n_ref--; if (client->n_ref > 0) return NULL; log_dhcp_client(client, "FREE"); client_initialize(client); client->receive_message = sd_event_source_unref(client->receive_message); sd_dhcp_client_detach_event(client); sd_dhcp_lease_unref(client->lease); free(client->req_opts); free(client->hostname); free(client->vendor_class_identifier); free(client); return NULL; } int sd_dhcp_client_new(sd_dhcp_client **ret) { _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL; assert_return(ret, -EINVAL); client = new0(sd_dhcp_client, 1); if (!client) return -ENOMEM; client->n_ref = 1; client->state = DHCP_STATE_INIT; client->index = -1; client->fd = -1; client->attempt = 1; client->mtu = DHCP_DEFAULT_MIN_SIZE; client->req_opts_size = ELEMENTSOF(default_req_opts); client->req_opts = memdup(default_req_opts, client->req_opts_size); if (!client->req_opts) return -ENOMEM; *ret = client; client = NULL; return 0; } systemd-229/src/libsystemd-network/sd-dhcp-lease.c000066400000000000000000001072701265713322000223020ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. Copyright (C) 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-dhcp-lease.h" #include "alloc-util.h" #include "dhcp-lease-internal.h" #include "dhcp-protocol.h" #include "dns-domain.h" #include "fd-util.h" #include "fileio.h" #include "hexdecoct.h" #include "hostname-util.h" #include "in-addr-util.h" #include "network-internal.h" #include "parse-util.h" #include "stdio-util.h" #include "string-util.h" #include "unaligned.h" int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) { assert_return(lease, -EINVAL); assert_return(addr, -EINVAL); if (lease->address == 0) return -ENODATA; addr->s_addr = lease->address; return 0; } int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr) { assert_return(lease, -EINVAL); assert_return(addr, -EINVAL); if (!lease->have_broadcast) return -ENODATA; addr->s_addr = lease->broadcast; return 0; } int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) { assert_return(lease, -EINVAL); assert_return(lifetime, -EINVAL); if (lease->lifetime <= 0) return -ENODATA; *lifetime = lease->lifetime; return 0; } int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1) { assert_return(lease, -EINVAL); assert_return(t1, -EINVAL); if (lease->t1 <= 0) return -ENODATA; *t1 = lease->t1; return 0; } int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2) { assert_return(lease, -EINVAL); assert_return(t2, -EINVAL); if (lease->t2 <= 0) return -ENODATA; *t2 = lease->t2; return 0; } int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) { assert_return(lease, -EINVAL); assert_return(mtu, -EINVAL); if (lease->mtu <= 0) return -ENODATA; *mtu = lease->mtu; return 0; } int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) { assert_return(lease, -EINVAL); assert_return(addr, -EINVAL); if (lease->dns_size <= 0) return -ENODATA; *addr = lease->dns; return (int) lease->dns_size; } int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) { assert_return(lease, -EINVAL); assert_return(addr, -EINVAL); if (lease->ntp_size <= 0) return -ENODATA; *addr = lease->ntp; return (int) lease->ntp_size; } int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) { assert_return(lease, -EINVAL); assert_return(domainname, -EINVAL); if (!lease->domainname) return -ENODATA; *domainname = lease->domainname; return 0; } int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) { assert_return(lease, -EINVAL); assert_return(hostname, -EINVAL); if (!lease->hostname) return -ENODATA; *hostname = lease->hostname; return 0; } int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) { assert_return(lease, -EINVAL); assert_return(root_path, -EINVAL); if (!lease->root_path) return -ENODATA; *root_path = lease->root_path; return 0; } int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr) { assert_return(lease, -EINVAL); assert_return(addr, -EINVAL); if (lease->router == 0) return -ENODATA; addr->s_addr = lease->router; return 0; } int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) { assert_return(lease, -EINVAL); assert_return(addr, -EINVAL); if (!lease->have_subnet_mask) return -ENODATA; addr->s_addr = lease->subnet_mask; return 0; } int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr) { assert_return(lease, -EINVAL); assert_return(addr, -EINVAL); if (lease->server_address == 0) return -ENODATA; addr->s_addr = lease->server_address; return 0; } int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) { assert_return(lease, -EINVAL); assert_return(addr, -EINVAL); if (lease->next_server == 0) return -ENODATA; addr->s_addr = lease->next_server; return 0; } /* * The returned routes array must be freed by the caller. * Route objects have the same lifetime of the lease and must not be freed. */ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) { sd_dhcp_route **ret; unsigned i; assert_return(lease, -EINVAL); assert_return(routes, -EINVAL); if (lease->static_route_size <= 0) return -ENODATA; ret = new(sd_dhcp_route *, lease->static_route_size); if (!ret) return -ENOMEM; for (i = 0; i < lease->static_route_size; i++) ret[i] = &lease->static_route[i]; *routes = ret; return (int) lease->static_route_size; } int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len) { assert_return(lease, -EINVAL); assert_return(data, -EINVAL); assert_return(data_len, -EINVAL); if (lease->vendor_specific_len <= 0) return -ENODATA; *data = lease->vendor_specific; *data_len = lease->vendor_specific_len; return 0; } sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) { if (!lease) return NULL; assert(lease->n_ref >= 1); lease->n_ref++; return lease; } sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) { if (!lease) return NULL; assert(lease->n_ref >= 1); lease->n_ref--; if (lease->n_ref > 0) return NULL; while (lease->private_options) { struct sd_dhcp_raw_option *option = lease->private_options; LIST_REMOVE(options, lease->private_options, option); free(option->data); free(option); } free(lease->hostname); free(lease->domainname); free(lease->dns); free(lease->ntp); free(lease->static_route); free(lease->client_id); free(lease->vendor_specific); free(lease); return NULL; } static int lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) { assert(option); assert(ret); if (len != 4) return -EINVAL; *ret = unaligned_read_be32((be32_t*) option); if (*ret < min) *ret = min; return 0; } static int lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) { assert(option); assert(ret); if (len != 2) return -EINVAL; *ret = unaligned_read_be16((be16_t*) option); if (*ret < min) *ret = min; return 0; } static int lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) { assert(option); assert(ret); if (len != 4) return -EINVAL; memcpy(ret, option, 4); return 0; } static int lease_parse_string(const uint8_t *option, size_t len, char **ret) { assert(option); assert(ret); if (len <= 0) *ret = mfree(*ret); else { char *string; /* * One trailing NUL byte is OK, we don't mind. See: * https://github.com/systemd/systemd/issues/1337 */ if (memchr(option, 0, len - 1)) return -EINVAL; string = strndup((const char *) option, len); if (!string) return -ENOMEM; free(*ret); *ret = string; } return 0; } static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) { _cleanup_free_ char *name = NULL, *normalized = NULL; int r; assert(option); assert(ret); r = lease_parse_string(option, len, &name); if (r < 0) return r; if (!name) { *ret = mfree(*ret); return 0; } r = dns_name_normalize(name, &normalized); if (r < 0) return r; if (is_localhost(normalized)) return -EINVAL; if (dns_name_is_root(normalized)) return -EINVAL; free(*ret); *ret = normalized; normalized = NULL; return 0; } static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) { assert(option); assert(ret); assert(n_ret); if (len <= 0) { *ret = mfree(*ret); *n_ret = 0; } else { size_t n_addresses; struct in_addr *addresses; if (len % 4 != 0) return -EINVAL; n_addresses = len / 4; addresses = newdup(struct in_addr, option, n_addresses); if (!addresses) return -ENOMEM; free(*ret); *ret = addresses; *n_ret = n_addresses; } return 0; } static int lease_parse_routes( const uint8_t *option, size_t len, struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) { struct in_addr addr; assert(option || len <= 0); assert(routes); assert(routes_size); assert(routes_allocated); if (len <= 0) return 0; if (len % 8 != 0) return -EINVAL; if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + (len / 8))) return -ENOMEM; while (len >= 8) { struct sd_dhcp_route *route = *routes + *routes_size; int r; r = in_addr_default_prefixlen((struct in_addr*) option, &route->dst_prefixlen); if (r < 0) { log_debug("Failed to determine destination prefix length from class based IP, ignoring"); continue; } assert_se(lease_parse_be32(option, 4, &addr.s_addr) >= 0); route->dst_addr = inet_makeaddr(inet_netof(addr), 0); option += 4; assert_se(lease_parse_be32(option, 4, &route->gw_addr.s_addr) >= 0); option += 4; len -= 8; (*routes_size)++; } return 0; } /* parses RFC3442 Classless Static Route Option */ static int lease_parse_classless_routes( const uint8_t *option, size_t len, struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) { assert(option || len <= 0); assert(routes); assert(routes_size); assert(routes_allocated); if (len <= 0) return 0; /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */ while (len > 0) { uint8_t dst_octets; struct sd_dhcp_route *route; if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + 1)) return -ENOMEM; route = *routes + *routes_size; dst_octets = (*option == 0 ? 0 : ((*option - 1) / 8) + 1); route->dst_prefixlen = *option; option++; len--; /* can't have more than 4 octets in IPv4 */ if (dst_octets > 4 || len < dst_octets) return -EINVAL; route->dst_addr.s_addr = 0; memcpy(&route->dst_addr.s_addr, option, dst_octets); option += dst_octets; len -= dst_octets; if (len < 4) return -EINVAL; assert_se(lease_parse_be32(option, 4, &route->gw_addr.s_addr) >= 0); option += 4; len -= 4; (*routes_size)++; } return 0; } int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata) { sd_dhcp_lease *lease = userdata; int r; assert(lease); switch(code) { case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME: r = lease_parse_u32(option, len, &lease->lifetime, 1); if (r < 0) log_debug_errno(r, "Failed to parse lease time, ignoring: %m"); break; case SD_DHCP_OPTION_SERVER_IDENTIFIER: r = lease_parse_be32(option, len, &lease->server_address); if (r < 0) log_debug_errno(r, "Failed to parse server identifier, ignoring: %m"); break; case SD_DHCP_OPTION_SUBNET_MASK: r = lease_parse_be32(option, len, &lease->subnet_mask); if (r < 0) log_debug_errno(r, "Failed to parse subnet mask, ignoring: %m"); else lease->have_subnet_mask = true; break; case SD_DHCP_OPTION_BROADCAST: r = lease_parse_be32(option, len, &lease->broadcast); if (r < 0) log_debug_errno(r, "Failed to parse broadcast address, ignoring: %m"); else lease->have_broadcast = true; break; case SD_DHCP_OPTION_ROUTER: if (len >= 4) { r = lease_parse_be32(option, 4, &lease->router); if (r < 0) log_debug_errno(r, "Failed to parse router address, ignoring: %m"); } break; case SD_DHCP_OPTION_DOMAIN_NAME_SERVER: r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size); if (r < 0) log_debug_errno(r, "Failed to parse DNS server, ignoring: %m"); break; case SD_DHCP_OPTION_NTP_SERVER: r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size); if (r < 0) log_debug_errno(r, "Failed to parse NTP server, ignoring: %m"); break; case SD_DHCP_OPTION_STATIC_ROUTE: r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated); if (r < 0) log_debug_errno(r, "Failed to parse static routes, ignoring: %m"); break; case SD_DHCP_OPTION_INTERFACE_MTU: r = lease_parse_u16(option, len, &lease->mtu, 68); if (r < 0) log_debug_errno(r, "Failed to parse MTU, ignoring: %m"); break; case SD_DHCP_OPTION_DOMAIN_NAME: r = lease_parse_domain(option, len, &lease->domainname); if (r < 0) { log_debug_errno(r, "Failed to parse domain name, ignoring: %m"); return 0; } break; case SD_DHCP_OPTION_HOST_NAME: r = lease_parse_domain(option, len, &lease->hostname); if (r < 0) { log_debug_errno(r, "Failed to parse host name, ignoring: %m"); return 0; } break; case SD_DHCP_OPTION_ROOT_PATH: r = lease_parse_string(option, len, &lease->root_path); if (r < 0) log_debug_errno(r, "Failed to parse root path, ignoring: %m"); break; case SD_DHCP_OPTION_RENEWAL_T1_TIME: r = lease_parse_u32(option, len, &lease->t1, 1); if (r < 0) log_debug_errno(r, "Failed to parse T1 time, ignoring: %m"); break; case SD_DHCP_OPTION_REBINDING_T2_TIME: r = lease_parse_u32(option, len, &lease->t2, 1); if (r < 0) log_debug_errno(r, "Failed to parse T2 time, ignoring: %m"); break; case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE: r = lease_parse_classless_routes( option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated); if (r < 0) log_debug_errno(r, "Failed to parse classless routes, ignoring: %m"); break; case SD_DHCP_OPTION_NEW_TZDB_TIMEZONE: { _cleanup_free_ char *tz = NULL; r = lease_parse_string(option, len, &tz); if (r < 0) { log_debug_errno(r, "Failed to parse timezone option, ignoring: %m"); return 0; } if (!timezone_is_valid(tz)) { log_debug_errno(r, "Timezone is not valid, ignoring: %m"); return 0; } free(lease->timezone); lease->timezone = tz; tz = NULL; break; } case SD_DHCP_OPTION_VENDOR_SPECIFIC: if (len <= 0) lease->vendor_specific = mfree(lease->vendor_specific); else { void *p; p = memdup(option, len); if (!p) return -ENOMEM; free(lease->vendor_specific); lease->vendor_specific = p; } lease->vendor_specific_len = len; break; case SD_DHCP_OPTION_PRIVATE_BASE ... SD_DHCP_OPTION_PRIVATE_LAST: r = dhcp_lease_insert_private_option(lease, code, option, len); if (r < 0) return r; break; default: log_debug("Ignoring option DHCP option %"PRIu8" while parsing.", code); break; } return 0; } int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len) { struct sd_dhcp_raw_option *cur, *option; assert(lease); LIST_FOREACH(options, cur, lease->private_options) { if (tag < cur->tag) break; if (tag == cur->tag) { log_debug("Ignoring duplicate option, tagged %i.", tag); return 0; } } option = new(struct sd_dhcp_raw_option, 1); if (!option) return -ENOMEM; option->tag = tag; option->length = len; option->data = memdup(data, len); if (!option->data) { free(option); return -ENOMEM; } LIST_INSERT_BEFORE(options, lease->private_options, cur, option); return 0; } int dhcp_lease_new(sd_dhcp_lease **ret) { sd_dhcp_lease *lease; lease = new0(sd_dhcp_lease, 1); if (!lease) return -ENOMEM; lease->router = INADDR_ANY; lease->n_ref = 1; *ret = lease; return 0; } int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; struct sd_dhcp_raw_option *option; struct in_addr address; const struct in_addr *addresses; const void *client_id, *data; size_t client_id_len, data_len; const char *string; uint16_t mtu; _cleanup_free_ sd_dhcp_route **routes = NULL; uint32_t t1, t2, lifetime; int r; assert(lease); assert(lease_file); r = fopen_temporary(lease_file, &f, &temp_path); if (r < 0) goto fail; fchmod(fileno(f), 0644); fprintf(f, "# This is private data. Do not parse.\n"); r = sd_dhcp_lease_get_address(lease, &address); if (r >= 0) fprintf(f, "ADDRESS=%s\n", inet_ntoa(address)); r = sd_dhcp_lease_get_netmask(lease, &address); if (r >= 0) fprintf(f, "NETMASK=%s\n", inet_ntoa(address)); r = sd_dhcp_lease_get_router(lease, &address); if (r >= 0) fprintf(f, "ROUTER=%s\n", inet_ntoa(address)); r = sd_dhcp_lease_get_server_identifier(lease, &address); if (r >= 0) fprintf(f, "SERVER_ADDRESS=%s\n", inet_ntoa(address)); r = sd_dhcp_lease_get_next_server(lease, &address); if (r >= 0) fprintf(f, "NEXT_SERVER=%s\n", inet_ntoa(address)); r = sd_dhcp_lease_get_broadcast(lease, &address); if (r >= 0) fprintf(f, "BROADCAST=%s\n", inet_ntoa(address)); r = sd_dhcp_lease_get_mtu(lease, &mtu); if (r >= 0) fprintf(f, "MTU=%" PRIu16 "\n", mtu); r = sd_dhcp_lease_get_t1(lease, &t1); if (r >= 0) fprintf(f, "T1=%" PRIu32 "\n", t1); r = sd_dhcp_lease_get_t2(lease, &t2); if (r >= 0) fprintf(f, "T2=%" PRIu32 "\n", t2); r = sd_dhcp_lease_get_lifetime(lease, &lifetime); if (r >= 0) fprintf(f, "LIFETIME=%" PRIu32 "\n", lifetime); r = sd_dhcp_lease_get_dns(lease, &addresses); if (r > 0) { fputs("DNS=", f); serialize_in_addrs(f, addresses, r); fputs("\n", f); } r = sd_dhcp_lease_get_ntp(lease, &addresses); if (r > 0) { fputs("NTP=", f); serialize_in_addrs(f, addresses, r); fputs("\n", f); } r = sd_dhcp_lease_get_domainname(lease, &string); if (r >= 0) fprintf(f, "DOMAINNAME=%s\n", string); r = sd_dhcp_lease_get_hostname(lease, &string); if (r >= 0) fprintf(f, "HOSTNAME=%s\n", string); r = sd_dhcp_lease_get_root_path(lease, &string); if (r >= 0) fprintf(f, "ROOT_PATH=%s\n", string); r = sd_dhcp_lease_get_routes(lease, &routes); if (r > 0) serialize_dhcp_routes(f, "ROUTES", routes, r); r = sd_dhcp_lease_get_timezone(lease, &string); if (r >= 0) fprintf(f, "TIMEZONE=%s\n", string); r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len); if (r >= 0) { _cleanup_free_ char *client_id_hex; client_id_hex = hexmem(client_id, client_id_len); if (!client_id_hex) { r = -ENOMEM; goto fail; } fprintf(f, "CLIENTID=%s\n", client_id_hex); } r = sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len); if (r >= 0) { _cleanup_free_ char *option_hex = NULL; option_hex = hexmem(data, data_len); if (!option_hex) { r = -ENOMEM; goto fail; } fprintf(f, "VENDOR_SPECIFIC=%s\n", option_hex); } LIST_FOREACH(options, option, lease->private_options) { char key[strlen("OPTION_000")+1]; xsprintf(key, "OPTION_%" PRIu8, option->tag); r = serialize_dhcp_option(f, key, option->data, option->length); if (r < 0) goto fail; } r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, lease_file) < 0) { r = -errno; goto fail; } return 0; fail: if (temp_path) (void) unlink(temp_path); return log_error_errno(r, "Failed to save lease data %s: %m", lease_file); } int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; _cleanup_free_ char *address = NULL, *router = NULL, *netmask = NULL, *server_address = NULL, *next_server = NULL, *broadcast = NULL, *dns = NULL, *ntp = NULL, *mtu = NULL, *routes = NULL, *client_id_hex = NULL, *vendor_specific_hex = NULL, *lifetime = NULL, *t1 = NULL, *t2 = NULL, *options[SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE + 1] = {}; int r, i; assert(lease_file); assert(ret); r = dhcp_lease_new(&lease); if (r < 0) return r; r = parse_env_file(lease_file, NEWLINE, "ADDRESS", &address, "ROUTER", &router, "NETMASK", &netmask, "SERVER_IDENTIFIER", &server_address, "NEXT_SERVER", &next_server, "BROADCAST", &broadcast, "DNS", &dns, "NTP", &ntp, "MTU", &mtu, "DOMAINNAME", &lease->domainname, "HOSTNAME", &lease->hostname, "ROOT_PATH", &lease->root_path, "ROUTES", &routes, "CLIENTID", &client_id_hex, "TIMEZONE", &lease->timezone, "VENDOR_SPECIFIC", &vendor_specific_hex, "LIFETIME", &lifetime, "T1", &t1, "T2", &t2, "OPTION_224", &options[0], "OPTION_225", &options[1], "OPTION_226", &options[2], "OPTION_227", &options[3], "OPTION_228", &options[4], "OPTION_229", &options[5], "OPTION_230", &options[6], "OPTION_231", &options[7], "OPTION_232", &options[8], "OPTION_233", &options[9], "OPTION_234", &options[10], "OPTION_235", &options[11], "OPTION_236", &options[12], "OPTION_237", &options[13], "OPTION_238", &options[14], "OPTION_239", &options[15], "OPTION_240", &options[16], "OPTION_241", &options[17], "OPTION_242", &options[18], "OPTION_243", &options[19], "OPTION_244", &options[20], "OPTION_245", &options[21], "OPTION_246", &options[22], "OPTION_247", &options[23], "OPTION_248", &options[24], "OPTION_249", &options[25], "OPTION_250", &options[26], "OPTION_251", &options[27], "OPTION_252", &options[28], "OPTION_253", &options[29], "OPTION_254", &options[30], NULL); if (r < 0) return r; if (address) { r = inet_pton(AF_INET, address, &lease->address); if (r <= 0) log_debug("Failed to parse address %s, ignoring.", address); } if (router) { r = inet_pton(AF_INET, router, &lease->router); if (r <= 0) log_debug("Failed to parse router %s, ignoring.", router); } if (netmask) { r = inet_pton(AF_INET, netmask, &lease->subnet_mask); if (r <= 0) log_debug("Failed to parse netmask %s, ignoring.", netmask); else lease->have_subnet_mask = true; } if (server_address) { r = inet_pton(AF_INET, server_address, &lease->server_address); if (r <= 0) log_debug("Failed to parse server address %s, ignoring.", server_address); } if (next_server) { r = inet_pton(AF_INET, next_server, &lease->next_server); if (r <= 0) log_debug("Failed to parse next server %s, ignoring.", next_server); } if (broadcast) { r = inet_pton(AF_INET, broadcast, &lease->broadcast); if (r <= 0) log_debug("Failed to parse broadcast address %s, ignoring.", broadcast); else lease->have_broadcast = true; } if (dns) { r = deserialize_in_addrs(&lease->dns, dns); if (r < 0) log_debug_errno(r, "Failed to deserialize DNS servers %s, ignoring: %m", dns); else lease->dns_size = r; } if (ntp) { r = deserialize_in_addrs(&lease->ntp, ntp); if (r < 0) log_debug_errno(r, "Failed to deserialize NTP servers %s, ignoring: %m", ntp); else lease->ntp_size = r; } if (mtu) { r = safe_atou16(mtu, &lease->mtu); if (r < 0) log_debug_errno(r, "Failed to parse MTU %s, ignoring: %m", mtu); } if (routes) { r = deserialize_dhcp_routes( &lease->static_route, &lease->static_route_size, &lease->static_route_allocated, routes); if (r < 0) log_debug_errno(r, "Failed to parse DHCP routes %s, ignoring: %m", routes); } if (lifetime) { r = safe_atou32(lifetime, &lease->lifetime); if (r < 0) log_debug_errno(r, "Failed to parse lifetime %s, ignoring: %m", lifetime); } if (t1) { r = safe_atou32(t1, &lease->t1); if (r < 0) log_debug_errno(r, "Failed to parse T1 %s, ignoring: %m", t1); } if (t2) { r = safe_atou32(t2, &lease->t2); if (r < 0) log_debug_errno(r, "Failed to parse T2 %s, ignoring: %m", t2); } if (client_id_hex) { r = deserialize_dhcp_option(&lease->client_id, &lease->client_id_len, client_id_hex); if (r < 0) log_debug_errno(r, "Failed to parse client ID %s, ignoring: %m", client_id_hex); } if (vendor_specific_hex) { r = deserialize_dhcp_option(&lease->vendor_specific, &lease->vendor_specific_len, vendor_specific_hex); if (r < 0) log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex); } for (i = 0; i <= SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE; i++) { _cleanup_free_ void *data = NULL; size_t len; if (!options[i]) continue; r = deserialize_dhcp_option(&data, &len, options[i]); if (r < 0) { log_debug_errno(r, "Failed to parse private DHCP option %s, ignoring: %m", options[i]); continue; } r = dhcp_lease_insert_private_option(lease, SD_DHCP_OPTION_PRIVATE_BASE + i, data, len); if (r < 0) return r; } *ret = lease; lease = NULL; return 0; } int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) { struct in_addr address, mask; int r; assert(lease); if (lease->address == 0) return -ENODATA; address.s_addr = lease->address; /* fall back to the default subnet masks based on address class */ r = in_addr_default_subnet_mask(&address, &mask); if (r < 0) return r; lease->subnet_mask = mask.s_addr; lease->have_subnet_mask = true; return 0; } int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len) { assert_return(lease, -EINVAL); assert_return(client_id, -EINVAL); assert_return(client_id_len, -EINVAL); if (!lease->client_id) return -ENODATA; *client_id = lease->client_id; *client_id_len = lease->client_id_len; return 0; } int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len) { assert_return(lease, -EINVAL); assert_return(client_id || client_id_len <= 0, -EINVAL); if (client_id_len <= 0) lease->client_id = mfree(lease->client_id); else { void *p; p = memdup(client_id, client_id_len); if (!p) return -ENOMEM; free(lease->client_id); lease->client_id = p; lease->client_id_len = client_id_len; } return 0; } int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **tz) { assert_return(lease, -EINVAL); assert_return(tz, -EINVAL); if (!lease->timezone) return -ENODATA; *tz = lease->timezone; return 0; } int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination) { assert_return(route, -EINVAL); assert_return(destination, -EINVAL); *destination = route->dst_addr; return 0; } int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length) { assert_return(route, -EINVAL); assert_return(length, -EINVAL); *length = route->dst_prefixlen; return 0; } int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway) { assert_return(route, -EINVAL); assert_return(gateway, -EINVAL); *gateway = route->gw_addr; return 0; } systemd-229/src/libsystemd-network/sd-dhcp-server.c000066400000000000000000001150431265713322000225140ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. Copyright (C) 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-dhcp-server.h" #include "alloc-util.h" #include "dhcp-internal.h" #include "dhcp-server-internal.h" #include "fd-util.h" #include "in-addr-util.h" #include "siphash24.h" #include "string-util.h" #define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR #define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12) /* configures the server's address and subnet, and optionally the pool's size and offset into the subnet * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address * moreover, the server's own address may be in the pool, and is in that case reserved in order not to * accidentally hand it out */ int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *address, unsigned char prefixlen, uint32_t offset, uint32_t size) { struct in_addr netmask_addr; be32_t netmask; uint32_t server_off, broadcast_off, size_max; assert_return(server, -EINVAL); assert_return(address, -EINVAL); assert_return(address->s_addr != INADDR_ANY, -EINVAL); assert_return(prefixlen <= 32, -ERANGE); assert_return(server->address == INADDR_ANY, -EBUSY); assert_se(in_addr_prefixlen_to_netmask(&netmask_addr, prefixlen)); netmask = netmask_addr.s_addr; server_off = be32toh(address->s_addr & ~netmask); broadcast_off = be32toh(~netmask); /* the server address cannot be the subnet address */ assert_return(server_off != 0, -ERANGE); /* nor the broadcast address */ assert_return(server_off != broadcast_off, -ERANGE); /* 0 offset means we should set a default, we skip the first (subnet) address and take the next one */ if (offset == 0) offset = 1; size_max = (broadcast_off + 1) /* the number of addresses in the subnet */ - offset /* exclude the addresses before the offset */ - 1; /* exclude the last (broadcast) address */ /* The pool must contain at least one address */ assert_return(size_max >= 1, -ERANGE); if (size != 0) assert_return(size <= size_max, -ERANGE); else size = size_max; server->bound_leases = new0(DHCPLease*, size); if (!server->bound_leases) return -ENOMEM; server->pool_offset = offset; server->pool_size = size; server->address = address->s_addr; server->netmask = netmask; server->subnet = address->s_addr & netmask; if (server_off >= offset && server_off - offset < size) server->bound_leases[server_off - offset] = &server->invalid_lease; return 0; } int sd_dhcp_server_is_running(sd_dhcp_server *server) { assert_return(server, false); return !!server->receive_message; } sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server) { if (!server) return NULL; assert(server->n_ref >= 1); server->n_ref++; return server; } void client_id_hash_func(const void *p, struct siphash *state) { const DHCPClientId *id = p; assert(id); assert(id->length); assert(id->data); siphash24_compress(&id->length, sizeof(id->length), state); siphash24_compress(id->data, id->length, state); } int client_id_compare_func(const void *_a, const void *_b) { const DHCPClientId *a, *b; a = _a; b = _b; assert(!a->length || a->data); assert(!b->length || b->data); if (a->length != b->length) return a->length < b->length ? -1 : 1; return memcmp(a->data, b->data, a->length); } static const struct hash_ops client_id_hash_ops = { .hash = client_id_hash_func, .compare = client_id_compare_func }; static void dhcp_lease_free(DHCPLease *lease) { if (!lease) return; free(lease->client_id.data); free(lease); } sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) { DHCPLease *lease; if (!server) return NULL; assert(server->n_ref >= 1); server->n_ref--; if (server->n_ref > 0) return NULL; log_dhcp_server(server, "UNREF"); sd_dhcp_server_stop(server); sd_event_unref(server->event); free(server->timezone); free(server->dns); free(server->ntp); while ((lease = hashmap_steal_first(server->leases_by_client_id))) dhcp_lease_free(lease); hashmap_free(server->leases_by_client_id); free(server->bound_leases); free(server); return NULL; } int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) { _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; assert_return(ret, -EINVAL); assert_return(ifindex > 0, -EINVAL); server = new0(sd_dhcp_server, 1); if (!server) return -ENOMEM; server->n_ref = 1; server->fd_raw = -1; server->fd = -1; server->address = htobe32(INADDR_ANY); server->netmask = htobe32(INADDR_ANY); server->ifindex = ifindex; server->leases_by_client_id = hashmap_new(&client_id_hash_ops); server->default_lease_time = DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC, USEC_PER_SEC); server->max_lease_time = DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC, USEC_PER_SEC); *ret = server; server = NULL; return 0; } int sd_dhcp_server_attach_event(sd_dhcp_server *server, sd_event *event, int priority) { int r; assert_return(server, -EINVAL); assert_return(!server->event, -EBUSY); if (event) server->event = sd_event_ref(event); else { r = sd_event_default(&server->event); if (r < 0) return r; } server->event_priority = priority; return 0; } int sd_dhcp_server_detach_event(sd_dhcp_server *server) { assert_return(server, -EINVAL); server->event = sd_event_unref(server->event); return 0; } sd_event *sd_dhcp_server_get_event(sd_dhcp_server *server) { assert_return(server, NULL); return server->event; } int sd_dhcp_server_stop(sd_dhcp_server *server) { assert_return(server, -EINVAL); server->receive_message = sd_event_source_unref(server->receive_message); server->fd_raw = safe_close(server->fd_raw); server->fd = safe_close(server->fd); log_dhcp_server(server, "STOPPED"); return 0; } static int dhcp_server_send_unicast_raw(sd_dhcp_server *server, DHCPPacket *packet, size_t len) { union sockaddr_union link = { .ll.sll_family = AF_PACKET, .ll.sll_protocol = htons(ETH_P_IP), .ll.sll_ifindex = server->ifindex, .ll.sll_halen = ETH_ALEN, }; assert(server); assert(server->ifindex > 0); assert(server->address); assert(packet); assert(len > sizeof(DHCPPacket)); memcpy(&link.ll.sll_addr, &packet->dhcp.chaddr, ETH_ALEN); dhcp_packet_append_ip_headers(packet, server->address, DHCP_PORT_SERVER, packet->dhcp.yiaddr, DHCP_PORT_CLIENT, len); return dhcp_network_send_raw_socket(server->fd_raw, &link, packet, len); } static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination, DHCPMessage *message, size_t len) { union sockaddr_union dest = { .in.sin_family = AF_INET, .in.sin_port = htobe16(DHCP_PORT_CLIENT), .in.sin_addr.s_addr = destination, }; struct iovec iov = { .iov_base = message, .iov_len = len, }; uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))] = {}; struct msghdr msg = { .msg_name = &dest, .msg_namelen = sizeof(dest.in), .msg_iov = &iov, .msg_iovlen = 1, .msg_control = cmsgbuf, .msg_controllen = sizeof(cmsgbuf), }; struct cmsghdr *cmsg; struct in_pktinfo *pktinfo; int r; assert(server); assert(server->fd > 0); assert(message); assert(len > sizeof(DHCPMessage)); cmsg = CMSG_FIRSTHDR(&msg); assert(cmsg); cmsg->cmsg_level = IPPROTO_IP; cmsg->cmsg_type = IP_PKTINFO; cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); /* we attach source interface and address info to the message rather than binding the socket. This will be mostly useful when we gain support for arbitrary number of server addresses */ pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg); assert(pktinfo); pktinfo->ipi_ifindex = server->ifindex; pktinfo->ipi_spec_dst.s_addr = server->address; r = sendmsg(server->fd, &msg, 0); if (r < 0) return -errno; return 0; } static bool requested_broadcast(DHCPRequest *req) { assert(req); return req->message->flags & htobe16(0x8000); } int dhcp_server_send_packet(sd_dhcp_server *server, DHCPRequest *req, DHCPPacket *packet, int type, size_t optoffset) { be32_t destination = INADDR_ANY; int r; assert(server); assert(req); assert(req->max_optlen); assert(optoffset <= req->max_optlen); assert(packet); r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0, SD_DHCP_OPTION_SERVER_IDENTIFIER, 4, &server->address); if (r < 0) return r; r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL); if (r < 0) return r; /* RFC 2131 Section 4.1 If the ’giaddr’ field in a DHCP message from a client is non-zero, the server sends any return messages to the ’DHCP server’ port on the BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’ field is zero and the ’ciaddr’ field is nonzero, then the server unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’. If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is set, then the server broadcasts DHCPOFFER and DHCPACK messages to 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK messages to the client’s hardware address and ’yiaddr’ address. In all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK messages to 0xffffffff. Section 4.3.2 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a different subnet. The server MUST set the broadcast bit in the DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the client, because the client may not have a correct network address or subnet mask, and the client may not be answering ARP requests. */ if (req->message->giaddr) { destination = req->message->giaddr; if (type == DHCP_NAK) packet->dhcp.flags = htobe16(0x8000); } else if (req->message->ciaddr && type != DHCP_NAK) destination = req->message->ciaddr; if (destination != INADDR_ANY) return dhcp_server_send_udp(server, destination, &packet->dhcp, sizeof(DHCPMessage) + optoffset); else if (requested_broadcast(req) || type == DHCP_NAK) return dhcp_server_send_udp(server, INADDR_BROADCAST, &packet->dhcp, sizeof(DHCPMessage) + optoffset); else /* we cannot send UDP packet to specific MAC address when the address is not yet configured, so must fall back to raw packets */ return dhcp_server_send_unicast_raw(server, packet, sizeof(DHCPPacket) + optoffset); } static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret, uint8_t type, size_t *_optoffset, DHCPRequest *req) { _cleanup_free_ DHCPPacket *packet = NULL; size_t optoffset = 0; int r; assert(server); assert(ret); assert(_optoffset); assert(IN_SET(type, DHCP_OFFER, DHCP_ACK, DHCP_NAK)); packet = malloc0(sizeof(DHCPPacket) + req->max_optlen); if (!packet) return -ENOMEM; r = dhcp_message_init(&packet->dhcp, BOOTREPLY, be32toh(req->message->xid), type, ARPHRD_ETHER, req->max_optlen, &optoffset); if (r < 0) return r; packet->dhcp.flags = req->message->flags; packet->dhcp.giaddr = req->message->giaddr; memcpy(&packet->dhcp.chaddr, &req->message->chaddr, ETH_ALEN); *_optoffset = optoffset; *ret = packet; packet = NULL; return 0; } static int server_send_offer(sd_dhcp_server *server, DHCPRequest *req, be32_t address) { _cleanup_free_ DHCPPacket *packet = NULL; size_t offset; be32_t lease_time; int r; r = server_message_init(server, &packet, DHCP_OFFER, &offset, req); if (r < 0) return r; packet->dhcp.yiaddr = address; lease_time = htobe32(req->lifetime); r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4, &lease_time); if (r < 0) return r; r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask); if (r < 0) return r; r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, SD_DHCP_OPTION_ROUTER, 4, &server->address); if (r < 0) return r; r = dhcp_server_send_packet(server, req, packet, DHCP_OFFER, offset); if (r < 0) return r; return 0; } static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req, be32_t address) { _cleanup_free_ DHCPPacket *packet = NULL; size_t offset; be32_t lease_time; int r; r = server_message_init(server, &packet, DHCP_ACK, &offset, req); if (r < 0) return r; packet->dhcp.yiaddr = address; lease_time = htobe32(req->lifetime); r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4, &lease_time); if (r < 0) return r; r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask); if (r < 0) return r; r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, SD_DHCP_OPTION_ROUTER, 4, &server->address); if (r < 0) return r; if (server->n_dns > 0) { r = dhcp_option_append( &packet->dhcp, req->max_optlen, &offset, 0, SD_DHCP_OPTION_DOMAIN_NAME_SERVER, sizeof(struct in_addr) * server->n_dns, server->dns); if (r < 0) return r; } if (server->n_ntp > 0) { r = dhcp_option_append( &packet->dhcp, req->max_optlen, &offset, 0, SD_DHCP_OPTION_NTP_SERVER, sizeof(struct in_addr) * server->n_ntp, server->ntp); if (r < 0) return r; } if (server->timezone) { r = dhcp_option_append( &packet->dhcp, req->max_optlen, &offset, 0, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE, strlen(server->timezone), server->timezone); if (r < 0) return r; } r = dhcp_server_send_packet(server, req, packet, DHCP_ACK, offset); if (r < 0) return r; return 0; } static int server_send_nak(sd_dhcp_server *server, DHCPRequest *req) { _cleanup_free_ DHCPPacket *packet = NULL; size_t offset; int r; r = server_message_init(server, &packet, DHCP_NAK, &offset, req); if (r < 0) return r; return dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset); } static int server_send_forcerenew(sd_dhcp_server *server, be32_t address, be32_t gateway, uint8_t chaddr[]) { _cleanup_free_ DHCPPacket *packet = NULL; size_t optoffset = 0; int r; assert(server); assert(address != INADDR_ANY); assert(chaddr); packet = malloc0(sizeof(DHCPPacket) + DHCP_MIN_OPTIONS_SIZE); if (!packet) return -ENOMEM; r = dhcp_message_init(&packet->dhcp, BOOTREPLY, 0, DHCP_FORCERENEW, ARPHRD_ETHER, DHCP_MIN_OPTIONS_SIZE, &optoffset); if (r < 0) return r; r = dhcp_option_append(&packet->dhcp, DHCP_MIN_OPTIONS_SIZE, &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL); if (r < 0) return r; memcpy(&packet->dhcp.chaddr, chaddr, ETH_ALEN); r = dhcp_server_send_udp(server, address, &packet->dhcp, sizeof(DHCPMessage) + optoffset); if (r < 0) return r; return 0; } static int parse_request(uint8_t code, uint8_t len, const void *option, void *userdata) { DHCPRequest *req = userdata; assert(req); switch(code) { case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME: if (len == 4) req->lifetime = be32toh(*(be32_t*)option); break; case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS: if (len == 4) req->requested_ip = *(be32_t*)option; break; case SD_DHCP_OPTION_SERVER_IDENTIFIER: if (len == 4) req->server_id = *(be32_t*)option; break; case SD_DHCP_OPTION_CLIENT_IDENTIFIER: if (len >= 2) { uint8_t *data; data = memdup(option, len); if (!data) return -ENOMEM; free(req->client_id.data); req->client_id.data = data; req->client_id.length = len; } break; case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE: if (len == 2) req->max_optlen = be16toh(*(be16_t*)option) - - sizeof(DHCPPacket); break; } return 0; } static void dhcp_request_free(DHCPRequest *req) { if (!req) return; free(req->client_id.data); free(req); } DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest*, dhcp_request_free); #define _cleanup_dhcp_request_free_ _cleanup_(dhcp_request_freep) static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMessage *message) { assert(req); assert(message); req->message = message; /* set client id based on MAC address if client did not send an explicit one */ if (!req->client_id.data) { void *data; data = malloc0(ETH_ALEN + 1); if (!data) return -ENOMEM; ((uint8_t*) data)[0] = 0x01; memcpy((uint8_t*) data + 1, &message->chaddr, ETH_ALEN); req->client_id.length = ETH_ALEN + 1; req->client_id.data = data; } if (req->max_optlen < DHCP_MIN_OPTIONS_SIZE) req->max_optlen = DHCP_MIN_OPTIONS_SIZE; if (req->lifetime <= 0) req->lifetime = MAX(1ULL, server->default_lease_time); if (server->max_lease_time > 0 && req->lifetime > server->max_lease_time) req->lifetime = server->max_lease_time; return 0; } static int get_pool_offset(sd_dhcp_server *server, be32_t requested_ip) { assert(server); if (!server->pool_size) return -EINVAL; if (be32toh(requested_ip) < (be32toh(server->subnet) | server->pool_offset) || be32toh(requested_ip) >= (be32toh(server->subnet) | (server->pool_offset + server->pool_size))) return -ERANGE; return be32toh(requested_ip & ~server->netmask) - server->pool_offset; } #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30) int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, size_t length) { _cleanup_dhcp_request_free_ DHCPRequest *req = NULL; _cleanup_free_ char *error_message = NULL; DHCPLease *existing_lease; int type, r; assert(server); assert(message); if (message->op != BOOTREQUEST || message->htype != ARPHRD_ETHER || message->hlen != ETHER_ADDR_LEN) return 0; req = new0(DHCPRequest, 1); if (!req) return -ENOMEM; type = dhcp_option_parse(message, length, parse_request, req, &error_message); if (type < 0) return 0; r = ensure_sane_request(server, req, message); if (r < 0) /* this only fails on critical errors */ return r; existing_lease = hashmap_get(server->leases_by_client_id, &req->client_id); switch(type) { case DHCP_DISCOVER: { be32_t address = INADDR_ANY; unsigned i; log_dhcp_server(server, "DISCOVER (0x%x)", be32toh(req->message->xid)); if (!server->pool_size) /* no pool allocated */ return 0; /* for now pick a random free address from the pool */ if (existing_lease) address = existing_lease->address; else { struct siphash state; uint64_t hash; uint32_t next_offer; /* even with no persistence of leases, we try to offer the same client the same IP address. we do this by using the hash of the client id as the offset into the pool of leases when finding the next free one */ siphash24_init(&state, HASH_KEY.bytes); client_id_hash_func(&req->client_id, &state); hash = htole64(siphash24_finalize(&state)); next_offer = hash % server->pool_size; for (i = 0; i < server->pool_size; i++) { if (!server->bound_leases[next_offer]) { address = server->subnet | htobe32(server->pool_offset + next_offer); break; } else next_offer = (next_offer + 1) % server->pool_size; } } if (address == INADDR_ANY) /* no free addresses left */ return 0; r = server_send_offer(server, req, address); if (r < 0) { /* this only fails on critical errors */ log_dhcp_server(server, "could not send offer: %s", strerror(-r)); return r; } else { log_dhcp_server(server, "OFFER (0x%x)", be32toh(req->message->xid)); return DHCP_OFFER; } break; } case DHCP_DECLINE: log_dhcp_server(server, "DECLINE (0x%x): %s", be32toh(req->message->xid), strna(error_message)); /* TODO: make sure we don't offer this address again */ return 1; case DHCP_REQUEST: { be32_t address; bool init_reboot = false; int pool_offset; /* see RFC 2131, section 4.3.2 */ if (req->server_id) { log_dhcp_server(server, "REQUEST (selecting) (0x%x)", be32toh(req->message->xid)); /* SELECTING */ if (req->server_id != server->address) /* client did not pick us */ return 0; if (req->message->ciaddr) /* this MUST be zero */ return 0; if (!req->requested_ip) /* this must be filled in with the yiaddr from the chosen OFFER */ return 0; address = req->requested_ip; } else if (req->requested_ip) { log_dhcp_server(server, "REQUEST (init-reboot) (0x%x)", be32toh(req->message->xid)); /* INIT-REBOOT */ if (req->message->ciaddr) /* this MUST be zero */ return 0; /* TODO: check more carefully if IP is correct */ address = req->requested_ip; init_reboot = true; } else { log_dhcp_server(server, "REQUEST (rebinding/renewing) (0x%x)", be32toh(req->message->xid)); /* REBINDING / RENEWING */ if (!req->message->ciaddr) /* this MUST be filled in with clients IP address */ return 0; address = req->message->ciaddr; } pool_offset = get_pool_offset(server, address); /* verify that the requested address is from the pool, and either owned by the current client or free */ if (pool_offset >= 0 && server->bound_leases[pool_offset] == existing_lease) { DHCPLease *lease; usec_t time_now = 0; if (!existing_lease) { lease = new0(DHCPLease, 1); lease->address = req->requested_ip; lease->client_id.data = memdup(req->client_id.data, req->client_id.length); if (!lease->client_id.data) { free(lease); return -ENOMEM; } lease->client_id.length = req->client_id.length; memcpy(&lease->chaddr, &req->message->chaddr, ETH_ALEN); lease->gateway = req->message->giaddr; } else lease = existing_lease; r = sd_event_now(server->event, clock_boottime_or_monotonic(), &time_now); if (r < 0) { if (!existing_lease) dhcp_lease_free(lease); return r; } lease->expiration = req->lifetime * USEC_PER_SEC + time_now; r = server_send_ack(server, req, address); if (r < 0) { /* this only fails on critical errors */ log_dhcp_server(server, "could not send ack: %s", strerror(-r)); if (!existing_lease) dhcp_lease_free(lease); return r; } else { log_dhcp_server(server, "ACK (0x%x)", be32toh(req->message->xid)); server->bound_leases[pool_offset] = lease; hashmap_put(server->leases_by_client_id, &lease->client_id, lease); return DHCP_ACK; } } else if (init_reboot) { r = server_send_nak(server, req); if (r < 0) { /* this only fails on critical errors */ log_dhcp_server(server, "could not send nak: %s", strerror(-r)); return r; } else { log_dhcp_server(server, "NAK (0x%x)", be32toh(req->message->xid)); return DHCP_NAK; } } break; } case DHCP_RELEASE: { int pool_offset; log_dhcp_server(server, "RELEASE (0x%x)", be32toh(req->message->xid)); if (!existing_lease) return 0; if (existing_lease->address != req->message->ciaddr) return 0; pool_offset = get_pool_offset(server, req->message->ciaddr); if (pool_offset < 0) return 0; if (server->bound_leases[pool_offset] == existing_lease) { server->bound_leases[pool_offset] = NULL; hashmap_remove(server->leases_by_client_id, existing_lease); dhcp_lease_free(existing_lease); return 1; } else return 0; } } return 0; } static int server_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_free_ DHCPMessage *message = NULL; uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))]; sd_dhcp_server *server = userdata; struct iovec iov = {}; struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, .msg_control = cmsgbuf, .msg_controllen = sizeof(cmsgbuf), }; struct cmsghdr *cmsg; int buflen = 0, len; assert(server); if (ioctl(fd, FIONREAD, &buflen) < 0) return -errno; else if (buflen < 0) return -EIO; message = malloc(buflen); if (!message) return -ENOMEM; iov.iov_base = message; iov.iov_len = buflen; len = recvmsg(fd, &msg, 0); if (len < 0) { if (errno == EAGAIN || errno == EINTR) return 0; return -errno; } else if ((size_t)len < sizeof(DHCPMessage)) return 0; CMSG_FOREACH(cmsg, &msg) { if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO && cmsg->cmsg_len == CMSG_LEN(sizeof(struct in_pktinfo))) { struct in_pktinfo *info = (struct in_pktinfo*)CMSG_DATA(cmsg); /* TODO figure out if this can be done as a filter on * the socket, like for IPv6 */ if (server->ifindex != info->ipi_ifindex) return 0; break; } } return dhcp_server_handle_message(server, message, (size_t)len); } int sd_dhcp_server_start(sd_dhcp_server *server) { int r; assert_return(server, -EINVAL); assert_return(server->event, -EINVAL); assert_return(!server->receive_message, -EBUSY); assert_return(server->fd_raw == -1, -EBUSY); assert_return(server->fd == -1, -EBUSY); assert_return(server->address != htobe32(INADDR_ANY), -EUNATCH); r = socket(AF_PACKET, SOCK_DGRAM | SOCK_NONBLOCK, 0); if (r < 0) { r = -errno; sd_dhcp_server_stop(server); return r; } server->fd_raw = r; r = dhcp_network_bind_udp_socket(INADDR_ANY, DHCP_PORT_SERVER); if (r < 0) { sd_dhcp_server_stop(server); return r; } server->fd = r; r = sd_event_add_io(server->event, &server->receive_message, server->fd, EPOLLIN, server_receive_message, server); if (r < 0) { sd_dhcp_server_stop(server); return r; } r = sd_event_source_set_priority(server->receive_message, server->event_priority); if (r < 0) { sd_dhcp_server_stop(server); return r; } log_dhcp_server(server, "STARTED"); return 0; } int sd_dhcp_server_forcerenew(sd_dhcp_server *server) { unsigned i; int r = 0; assert_return(server, -EINVAL); assert(server->bound_leases); for (i = 0; i < server->pool_size; i++) { DHCPLease *lease = server->bound_leases[i]; if (!lease || lease == &server->invalid_lease) continue; r = server_send_forcerenew(server, lease->address, lease->gateway, lease->chaddr); if (r < 0) return r; else log_dhcp_server(server, "FORCERENEW"); } return r; } int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *tz) { int r; assert_return(server, -EINVAL); assert_return(timezone_is_valid(tz), -EINVAL); if (streq_ptr(tz, server->timezone)) return 0; r = free_and_strdup(&server->timezone, tz); if (r < 0) return r; return 1; } int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t) { assert_return(server, -EINVAL); if (t == server->max_lease_time) return 0; server->max_lease_time = t; return 1; } int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t) { assert_return(server, -EINVAL); if (t == server->default_lease_time) return 0; server->default_lease_time = t; return 1; } int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], unsigned n) { assert_return(server, -EINVAL); assert_return(dns || n <= 0, -EINVAL); if (server->n_dns == n && memcmp(server->dns, dns, sizeof(struct in_addr) * n) == 0) return 0; if (n <= 0) { server->dns = mfree(server->dns); server->n_dns = 0; } else { struct in_addr *c; c = newdup(struct in_addr, dns, n); if (!c) return -ENOMEM; free(server->dns); server->dns = c; server->n_dns = n; } return 1; } int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n) { assert_return(server, -EINVAL); assert_return(ntp || n <= 0, -EINVAL); if (server->n_ntp == n && memcmp(server->ntp, ntp, sizeof(struct in_addr) * n) == 0) return 0; if (n <= 0) { server->ntp = mfree(server->ntp); server->n_ntp = 0; } else { struct in_addr *c; c = newdup(struct in_addr, ntp, n); if (!c) return -ENOMEM; free(server->ntp); server->ntp = c; server->n_ntp = n; } return 1; } systemd-229/src/libsystemd-network/sd-dhcp6-client.c000066400000000000000000001215041265713322000225510ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014-2015 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-dhcp6-client.h" #include "alloc-util.h" #include "dhcp-identifier.h" #include "dhcp6-internal.h" #include "dhcp6-lease-internal.h" #include "dhcp6-protocol.h" #include "fd-util.h" #include "in-addr-util.h" #include "network-internal.h" #include "random-util.h" #include "string-table.h" #include "util.h" #define MAX_MAC_ADDR_LEN INFINIBAND_ALEN struct sd_dhcp6_client { unsigned n_ref; enum DHCP6State state; sd_event *event; int event_priority; int index; struct in6_addr local_address; uint8_t mac_addr[MAX_MAC_ADDR_LEN]; size_t mac_addr_len; uint16_t arp_type; DHCP6IA ia_na; be32_t transaction_id; usec_t transaction_start; struct sd_dhcp6_lease *lease; int fd; bool information_request; be16_t *req_opts; size_t req_opts_allocated; size_t req_opts_len; sd_event_source *receive_message; usec_t retransmit_time; uint8_t retransmit_count; sd_event_source *timeout_resend; sd_event_source *timeout_resend_expire; sd_dhcp6_client_cb_t cb; void *userdata; struct duid duid; size_t duid_len; }; static const uint16_t default_req_opts[] = { SD_DHCP6_OPTION_DNS_SERVERS, SD_DHCP6_OPTION_DOMAIN_LIST, SD_DHCP6_OPTION_NTP_SERVER, SD_DHCP6_OPTION_SNTP_SERVERS, }; const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = { [DHCP6_SOLICIT] = "SOLICIT", [DHCP6_ADVERTISE] = "ADVERTISE", [DHCP6_REQUEST] = "REQUEST", [DHCP6_CONFIRM] = "CONFIRM", [DHCP6_RENEW] = "RENEW", [DHCP6_REBIND] = "REBIND", [DHCP6_REPLY] = "REPLY", [DHCP6_RELEASE] = "RELEASE", [DHCP6_DECLINE] = "DECLINE", [DHCP6_RECONFIGURE] = "RECONFIGURE", [DHCP6_INFORMATION_REQUEST] = "INFORMATION-REQUEST", [DHCP6_RELAY_FORW] = "RELAY-FORW", [DHCP6_RELAY_REPL] = "RELAY-REPL", }; DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_type, int); const char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = { [DHCP6_STATUS_SUCCESS] = "Success", [DHCP6_STATUS_UNSPEC_FAIL] = "Unspecified failure", [DHCP6_STATUS_NO_ADDRS_AVAIL] = "No addresses available", [DHCP6_STATUS_NO_BINDING] = "Binding unavailable", [DHCP6_STATUS_NOT_ON_LINK] = "Not on link", [DHCP6_STATUS_USE_MULTICAST] = "Use multicast", }; DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int); #define DHCP6_CLIENT_DONT_DESTROY(client) \ _cleanup_(sd_dhcp6_client_unrefp) _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client) static int client_start(sd_dhcp6_client *client, enum DHCP6State state); int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_cb_t cb, void *userdata) { assert_return(client, -EINVAL); client->cb = cb; client->userdata = userdata; return 0; } int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) { assert_return(client, -EINVAL); assert_return(interface_index >= -1, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); client->index = interface_index; return 0; } int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address) { assert_return(client, -EINVAL); assert_return(local_address, -EINVAL); assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) local_address) > 0, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); client->local_address = *local_address; return 0; } int sd_dhcp6_client_set_mac( sd_dhcp6_client *client, const uint8_t *addr, size_t addr_len, uint16_t arp_type) { assert_return(client, -EINVAL); assert_return(addr, -EINVAL); assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL); assert_return(arp_type > 0, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); if (arp_type == ARPHRD_ETHER) assert_return(addr_len == ETH_ALEN, -EINVAL); else if (arp_type == ARPHRD_INFINIBAND) assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); else return -EINVAL; if (client->mac_addr_len == addr_len && memcmp(&client->mac_addr, addr, addr_len) == 0) return 0; memcpy(&client->mac_addr, addr, addr_len); client->mac_addr_len = addr_len; client->arp_type = arp_type; return 0; } static int client_ensure_duid(sd_dhcp6_client *client) { if (client->duid_len != 0) return 0; return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len); } int sd_dhcp6_client_set_duid( sd_dhcp6_client *client, uint16_t type, uint8_t *duid, size_t duid_len) { assert_return(client, -EINVAL); assert_return(duid, -EINVAL); assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); switch (type) { case DHCP6_DUID_LLT: if (duid_len <= sizeof(client->duid.llt)) return -EINVAL; break; case DHCP6_DUID_EN: if (duid_len != sizeof(client->duid.en)) return -EINVAL; break; case DHCP6_DUID_LL: if (duid_len <= sizeof(client->duid.ll)) return -EINVAL; break; case DHCP6_DUID_UUID: if (duid_len != sizeof(client->duid.uuid)) return -EINVAL; break; default: /* accept unknown type in order to be forward compatible */ break; } client->duid.type = htobe16(type); memcpy(&client->duid.raw.data, duid, duid_len); client->duid_len = duid_len + sizeof(client->duid.type); return 0; } int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled) { assert_return(client, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); client->information_request = enabled; return 0; } int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled) { assert_return(client, -EINVAL); assert_return(enabled, -EINVAL); *enabled = client->information_request; return 0; } int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) { size_t t; assert_return(client, -EINVAL); assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); switch(option) { case SD_DHCP6_OPTION_DNS_SERVERS: case SD_DHCP6_OPTION_DOMAIN_LIST: case SD_DHCP6_OPTION_SNTP_SERVERS: case SD_DHCP6_OPTION_NTP_SERVER: break; default: return -EINVAL; } for (t = 0; t < client->req_opts_len; t++) if (client->req_opts[t] == htobe16(option)) return -EEXIST; if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated, client->req_opts_len + 1)) return -ENOMEM; client->req_opts[client->req_opts_len++] = htobe16(option); return 0; } int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) { assert_return(client, -EINVAL); if (!client->lease) return -ENOMSG; if (ret) *ret = client->lease; return 0; } static void client_notify(sd_dhcp6_client *client, int event) { if (client->cb) client->cb(client, event, client->userdata); } static void client_set_lease(sd_dhcp6_client *client, sd_dhcp6_lease *lease) { if (client->lease) { dhcp6_lease_clear_timers(&client->lease->ia); sd_dhcp6_lease_unref(client->lease); } client->lease = lease; } static int client_reset(sd_dhcp6_client *client) { assert_return(client, -EINVAL); client_set_lease(client, NULL); client->receive_message = sd_event_source_unref(client->receive_message); client->fd = safe_close(client->fd); client->transaction_id = 0; client->transaction_start = 0; client->ia_na.timeout_t1 = sd_event_source_unref(client->ia_na.timeout_t1); client->ia_na.timeout_t2 = sd_event_source_unref(client->ia_na.timeout_t2); client->retransmit_time = 0; client->retransmit_count = 0; client->timeout_resend = sd_event_source_unref(client->timeout_resend); client->timeout_resend_expire = sd_event_source_unref(client->timeout_resend_expire); client->state = DHCP6_STATE_STOPPED; return 0; } static void client_stop(sd_dhcp6_client *client, int error) { DHCP6_CLIENT_DONT_DESTROY(client); assert(client); client_notify(client, error); client_reset(client); } static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { _cleanup_free_ DHCP6Message *message = NULL; struct in6_addr all_servers = IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT; size_t len, optlen = 512; uint8_t *opt; int r; usec_t elapsed_usec; be16_t elapsed_time; len = sizeof(DHCP6Message) + optlen; message = malloc0(len); if (!message) return -ENOMEM; opt = (uint8_t *)(message + 1); message->transaction_id = client->transaction_id; switch(client->state) { case DHCP6_STATE_INFORMATION_REQUEST: message->type = DHCP6_INFORMATION_REQUEST; break; case DHCP6_STATE_SOLICITATION: message->type = DHCP6_SOLICIT; r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL); if (r < 0) return r; r = dhcp6_option_append_ia(&opt, &optlen, &client->ia_na); if (r < 0) return r; break; case DHCP6_STATE_REQUEST: case DHCP6_STATE_RENEW: if (client->state == DHCP6_STATE_REQUEST) message->type = DHCP6_REQUEST; else message->type = DHCP6_RENEW; r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_SERVERID, client->lease->serverid_len, client->lease->serverid); if (r < 0) return r; r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia); if (r < 0) return r; break; case DHCP6_STATE_REBIND: message->type = DHCP6_REBIND; r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia); if (r < 0) return r; break; case DHCP6_STATE_STOPPED: case DHCP6_STATE_BOUND: return -EINVAL; } r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ORO, client->req_opts_len * sizeof(be16_t), client->req_opts); if (r < 0) return r; assert (client->duid_len); r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_CLIENTID, client->duid_len, &client->duid); if (r < 0) return r; elapsed_usec = time_now - client->transaction_start; if (elapsed_usec < 0xffff * USEC_PER_MSEC * 10) elapsed_time = htobe16(elapsed_usec / USEC_PER_MSEC / 10); else elapsed_time = 0xffff; r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ELAPSED_TIME, sizeof(elapsed_time), &elapsed_time); if (r < 0) return r; r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message, len - optlen); if (r < 0) return r; log_dhcp6_client(client, "Sent %s", dhcp6_message_type_to_string(message->type)); return 0; } static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp6_client *client = userdata; assert_return(s, -EINVAL); assert_return(client, -EINVAL); assert_return(client->lease, -EINVAL); client->lease->ia.timeout_t2 = sd_event_source_unref(client->lease->ia.timeout_t2); log_dhcp6_client(client, "Timeout T2"); client_start(client, DHCP6_STATE_REBIND); return 0; } static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp6_client *client = userdata; assert_return(s, -EINVAL); assert_return(client, -EINVAL); assert_return(client->lease, -EINVAL); client->lease->ia.timeout_t1 = sd_event_source_unref(client->lease->ia.timeout_t1); log_dhcp6_client(client, "Timeout T1"); client_start(client, DHCP6_STATE_RENEW); return 0; } static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp6_client *client = userdata; DHCP6_CLIENT_DONT_DESTROY(client); enum DHCP6State state; assert(s); assert(client); assert(client->event); state = client->state; client_stop(client, SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE); /* RFC 3315, section 18.1.4., says that "...the client may choose to use a Solicit message to locate a new DHCP server..." */ if (state == DHCP6_STATE_REBIND) client_start(client, DHCP6_STATE_SOLICITATION); return 0; } static usec_t client_timeout_compute_random(usec_t val) { return val - val / 10 + (random_u32() % (2 * USEC_PER_SEC)) * val / 10 / USEC_PER_SEC; } static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userdata) { int r = 0; sd_dhcp6_client *client = userdata; usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0; usec_t max_retransmit_duration = 0; uint8_t max_retransmit_count = 0; char time_string[FORMAT_TIMESPAN_MAX]; uint32_t expire = 0; assert(s); assert(client); assert(client->event); client->timeout_resend = sd_event_source_unref(client->timeout_resend); switch (client->state) { case DHCP6_STATE_INFORMATION_REQUEST: init_retransmit_time = DHCP6_INF_TIMEOUT; max_retransmit_time = DHCP6_INF_MAX_RT; break; case DHCP6_STATE_SOLICITATION: if (client->retransmit_count && client->lease) { client_start(client, DHCP6_STATE_REQUEST); return 0; } init_retransmit_time = DHCP6_SOL_TIMEOUT; max_retransmit_time = DHCP6_SOL_MAX_RT; break; case DHCP6_STATE_REQUEST: init_retransmit_time = DHCP6_REQ_TIMEOUT; max_retransmit_time = DHCP6_REQ_MAX_RT; max_retransmit_count = DHCP6_REQ_MAX_RC; break; case DHCP6_STATE_RENEW: init_retransmit_time = DHCP6_REN_TIMEOUT; max_retransmit_time = DHCP6_REN_MAX_RT; /* RFC 3315, section 18.1.3. says max retransmit duration will be the remaining time until T2. Instead of setting MRD, wait for T2 to trigger with the same end result */ break; case DHCP6_STATE_REBIND: init_retransmit_time = DHCP6_REB_TIMEOUT; max_retransmit_time = DHCP6_REB_MAX_RT; if (!client->timeout_resend_expire) { r = dhcp6_lease_ia_rebind_expire(&client->lease->ia, &expire); if (r < 0) { client_stop(client, r); return 0; } max_retransmit_duration = expire * USEC_PER_SEC; } break; case DHCP6_STATE_STOPPED: case DHCP6_STATE_BOUND: return 0; } if (max_retransmit_count && client->retransmit_count >= max_retransmit_count) { client_stop(client, SD_DHCP6_CLIENT_EVENT_RETRANS_MAX); return 0; } r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); if (r < 0) goto error; r = client_send_message(client, time_now); if (r >= 0) client->retransmit_count++; if (!client->retransmit_time) { client->retransmit_time = client_timeout_compute_random(init_retransmit_time); if (client->state == DHCP6_STATE_SOLICITATION) client->retransmit_time += init_retransmit_time / 10; } else { if (max_retransmit_time && client->retransmit_time > max_retransmit_time / 2) client->retransmit_time = client_timeout_compute_random(max_retransmit_time); else client->retransmit_time += client_timeout_compute_random(client->retransmit_time); } log_dhcp6_client(client, "Next retransmission in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->retransmit_time, USEC_PER_SEC)); r = sd_event_add_time(client->event, &client->timeout_resend, clock_boottime_or_monotonic(), time_now + client->retransmit_time, 10 * USEC_PER_MSEC, client_timeout_resend, client); if (r < 0) goto error; r = sd_event_source_set_priority(client->timeout_resend, client->event_priority); if (r < 0) goto error; r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timer"); if (r < 0) goto error; if (max_retransmit_duration && !client->timeout_resend_expire) { log_dhcp6_client(client, "Max retransmission duration %"PRIu64" secs", max_retransmit_duration / USEC_PER_SEC); r = sd_event_add_time(client->event, &client->timeout_resend_expire, clock_boottime_or_monotonic(), time_now + max_retransmit_duration, USEC_PER_SEC, client_timeout_resend_expire, client); if (r < 0) goto error; r = sd_event_source_set_priority(client->timeout_resend_expire, client->event_priority); if (r < 0) goto error; r = sd_event_source_set_description(client->timeout_resend_expire, "dhcp6-resend-expire-timer"); if (r < 0) goto error; } error: if (r < 0) client_stop(client, r); return 0; } static int client_ensure_iaid(sd_dhcp6_client *client) { int r; assert(client); if (client->ia_na.id) return 0; r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->ia_na.id); if (r < 0) return r; return 0; } static int client_parse_message(sd_dhcp6_client *client, DHCP6Message *message, size_t len, sd_dhcp6_lease *lease) { int r; uint8_t *optval, *option, *id = NULL; uint16_t optcode, status; size_t optlen, id_len; bool clientid = false; be32_t iaid_lease; option = (uint8_t *)message + sizeof(DHCP6Message); len -= sizeof(DHCP6Message); while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen, &optval)) >= 0) { switch (optcode) { case SD_DHCP6_OPTION_CLIENTID: if (clientid) { log_dhcp6_client(client, "%s contains multiple clientids", dhcp6_message_type_to_string(message->type)); return -EINVAL; } if (optlen != client->duid_len || memcmp(&client->duid, optval, optlen) != 0) { log_dhcp6_client(client, "%s DUID does not match", dhcp6_message_type_to_string(message->type)); return -EINVAL; } clientid = true; break; case SD_DHCP6_OPTION_SERVERID: r = dhcp6_lease_get_serverid(lease, &id, &id_len); if (r >= 0 && id) { log_dhcp6_client(client, "%s contains multiple serverids", dhcp6_message_type_to_string(message->type)); return -EINVAL; } r = dhcp6_lease_set_serverid(lease, optval, optlen); if (r < 0) return r; break; case SD_DHCP6_OPTION_PREFERENCE: if (optlen != 1) return -EINVAL; r = dhcp6_lease_set_preference(lease, *optval); if (r < 0) return r; break; case SD_DHCP6_OPTION_STATUS_CODE: if (optlen < 2) return -EINVAL; status = optval[0] << 8 | optval[1]; if (status) { log_dhcp6_client(client, "%s Status %s", dhcp6_message_type_to_string(message->type), dhcp6_message_status_to_string(status)); return -EINVAL; } break; case SD_DHCP6_OPTION_IA_NA: if (client->state == DHCP6_STATE_INFORMATION_REQUEST) { log_dhcp6_client(client, "Information request ignoring IA NA option"); break; } r = dhcp6_option_parse_ia(&optval, &optlen, optcode, &lease->ia); if (r < 0 && r != -ENOMSG) return r; r = dhcp6_lease_get_iaid(lease, &iaid_lease); if (r < 0) return r; if (client->ia_na.id != iaid_lease) { log_dhcp6_client(client, "%s has wrong IAID", dhcp6_message_type_to_string(message->type)); return -EINVAL; } break; case SD_DHCP6_OPTION_RAPID_COMMIT: r = dhcp6_lease_set_rapid_commit(lease); if (r < 0) return r; break; case SD_DHCP6_OPTION_DNS_SERVERS: r = dhcp6_lease_set_dns(lease, optval, optlen); if (r < 0) return r; break; case SD_DHCP6_OPTION_DOMAIN_LIST: r = dhcp6_lease_set_domains(lease, optval, optlen); if (r < 0) return r; break; case SD_DHCP6_OPTION_NTP_SERVER: r = dhcp6_lease_set_ntp(lease, optval, optlen); if (r < 0) return r; break; case SD_DHCP6_OPTION_SNTP_SERVERS: r = dhcp6_lease_set_sntp(lease, optval, optlen); if (r < 0) return r; break; } } if (r == -ENOMSG) r = 0; if (r < 0 || !clientid) { log_dhcp6_client(client, "%s has incomplete options", dhcp6_message_type_to_string(message->type)); return -EINVAL; } if (client->state != DHCP6_STATE_INFORMATION_REQUEST) { r = dhcp6_lease_get_serverid(lease, &id, &id_len); if (r < 0) log_dhcp6_client(client, "%s has no server id", dhcp6_message_type_to_string(message->type)); } return r; } static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) { int r; _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; bool rapid_commit; if (reply->type != DHCP6_REPLY) return 0; r = dhcp6_lease_new(&lease); if (r < 0) return -ENOMEM; r = client_parse_message(client, reply, len, lease); if (r < 0) return r; if (client->state == DHCP6_STATE_SOLICITATION) { r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit); if (r < 0) return r; if (!rapid_commit) return 0; } client_set_lease(client, lease); lease = NULL; return DHCP6_STATE_BOUND; } static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) { int r; _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; uint8_t pref_advertise = 0, pref_lease = 0; if (advertise->type != DHCP6_ADVERTISE) return 0; r = dhcp6_lease_new(&lease); if (r < 0) return r; r = client_parse_message(client, advertise, len, lease); if (r < 0) return r; r = dhcp6_lease_get_preference(lease, &pref_advertise); if (r < 0) return r; r = dhcp6_lease_get_preference(client->lease, &pref_lease); if (r < 0 || pref_advertise > pref_lease) { client_set_lease(client, lease); lease = NULL; r = 0; } if (pref_advertise == 255 || client->retransmit_count > 1) r = DHCP6_STATE_REQUEST; return r; } static int client_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) { sd_dhcp6_client *client = userdata; DHCP6_CLIENT_DONT_DESTROY(client); _cleanup_free_ DHCP6Message *message = NULL; int r, buflen, len; assert(s); assert(client); assert(client->event); r = ioctl(fd, FIONREAD, &buflen); if (r < 0) return -errno; else if (buflen < 0) /* This really should not happen */ return -EIO; message = malloc(buflen); if (!message) return -ENOMEM; len = read(fd, message, buflen); if (len < 0) { if (errno == EAGAIN || errno == EINTR) return 0; log_dhcp6_client(client, "Could not receive message from UDP socket: %m"); return -errno; } else if ((size_t)len < sizeof(DHCP6Message)) return 0; switch(message->type) { case DHCP6_SOLICIT: case DHCP6_REQUEST: case DHCP6_CONFIRM: case DHCP6_RENEW: case DHCP6_REBIND: case DHCP6_RELEASE: case DHCP6_DECLINE: case DHCP6_INFORMATION_REQUEST: case DHCP6_RELAY_FORW: case DHCP6_RELAY_REPL: return 0; case DHCP6_ADVERTISE: case DHCP6_REPLY: case DHCP6_RECONFIGURE: break; default: log_dhcp6_client(client, "unknown message type %d", message->type); return 0; } if (client->transaction_id != (message->transaction_id & htobe32(0x00ffffff))) return 0; switch (client->state) { case DHCP6_STATE_INFORMATION_REQUEST: r = client_receive_reply(client, message, len); if (r < 0) return 0; client_notify(client, SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST); client_start(client, DHCP6_STATE_STOPPED); break; case DHCP6_STATE_SOLICITATION: r = client_receive_advertise(client, message, len); if (r == DHCP6_STATE_REQUEST) { client_start(client, r); break; } /* fall through for Soliciation Rapid Commit option check */ case DHCP6_STATE_REQUEST: case DHCP6_STATE_RENEW: case DHCP6_STATE_REBIND: r = client_receive_reply(client, message, len); if (r < 0) return 0; if (r == DHCP6_STATE_BOUND) { r = client_start(client, DHCP6_STATE_BOUND); if (r < 0) { client_stop(client, r); return 0; } client_notify(client, SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE); } break; case DHCP6_STATE_BOUND: break; case DHCP6_STATE_STOPPED: return 0; } if (r >= 0) { log_dhcp6_client(client, "Recv %s", dhcp6_message_type_to_string(message->type)); } return 0; } static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { int r; usec_t timeout, time_now; char time_string[FORMAT_TIMESPAN_MAX]; assert_return(client, -EINVAL); assert_return(client->event, -EINVAL); assert_return(client->index > 0, -EINVAL); assert_return(client->state != state, -EINVAL); client->timeout_resend_expire = sd_event_source_unref(client->timeout_resend_expire); client->timeout_resend = sd_event_source_unref(client->timeout_resend); client->retransmit_time = 0; client->retransmit_count = 0; r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); if (r < 0) return r; switch (state) { case DHCP6_STATE_STOPPED: if (client->state == DHCP6_STATE_INFORMATION_REQUEST) { client->state = DHCP6_STATE_STOPPED; return 0; } /* fall through */ case DHCP6_STATE_SOLICITATION: client->state = DHCP6_STATE_SOLICITATION; break; case DHCP6_STATE_INFORMATION_REQUEST: case DHCP6_STATE_REQUEST: case DHCP6_STATE_RENEW: case DHCP6_STATE_REBIND: client->state = state; break; case DHCP6_STATE_BOUND: if (client->lease->ia.lifetime_t1 == 0xffffffff || client->lease->ia.lifetime_t2 == 0xffffffff) { log_dhcp6_client(client, "infinite T1 0x%08x or T2 0x%08x", be32toh(client->lease->ia.lifetime_t1), be32toh(client->lease->ia.lifetime_t2)); return 0; } timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t1) * USEC_PER_SEC); log_dhcp6_client(client, "T1 expires in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC)); r = sd_event_add_time(client->event, &client->lease->ia.timeout_t1, clock_boottime_or_monotonic(), time_now + timeout, 10 * USEC_PER_SEC, client_timeout_t1, client); if (r < 0) return r; r = sd_event_source_set_priority(client->lease->ia.timeout_t1, client->event_priority); if (r < 0) return r; r = sd_event_source_set_description(client->lease->ia.timeout_t1, "dhcp6-t1-timeout"); if (r < 0) return r; timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t2) * USEC_PER_SEC); log_dhcp6_client(client, "T2 expires in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC)); r = sd_event_add_time(client->event, &client->lease->ia.timeout_t2, clock_boottime_or_monotonic(), time_now + timeout, 10 * USEC_PER_SEC, client_timeout_t2, client); if (r < 0) return r; r = sd_event_source_set_priority(client->lease->ia.timeout_t2, client->event_priority); if (r < 0) return r; r = sd_event_source_set_description(client->lease->ia.timeout_t2, "dhcp6-t2-timeout"); if (r < 0) return r; client->state = state; return 0; } client->transaction_id = random_u32() & htobe32(0x00ffffff); client->transaction_start = time_now; r = sd_event_add_time(client->event, &client->timeout_resend, clock_boottime_or_monotonic(), 0, 0, client_timeout_resend, client); if (r < 0) return r; r = sd_event_source_set_priority(client->timeout_resend, client->event_priority); if (r < 0) return r; r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timeout"); if (r < 0) return r; return 0; } int sd_dhcp6_client_stop(sd_dhcp6_client *client) { assert_return(client, -EINVAL); client_stop(client, SD_DHCP6_CLIENT_EVENT_STOP); return 0; } int sd_dhcp6_client_is_running(sd_dhcp6_client *client) { assert_return(client, -EINVAL); return client->state != DHCP6_STATE_STOPPED; } int sd_dhcp6_client_start(sd_dhcp6_client *client) { int r = 0; enum DHCP6State state = DHCP6_STATE_SOLICITATION; assert_return(client, -EINVAL); assert_return(client->event, -EINVAL); assert_return(client->index > 0, -EINVAL); assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) &client->local_address) > 0, -EINVAL); if (!IN_SET(client->state, DHCP6_STATE_STOPPED)) return -EBUSY; r = client_reset(client); if (r < 0) return r; r = client_ensure_iaid(client); if (r < 0) return r; r = client_ensure_duid(client); if (r < 0) return r; r = dhcp6_network_bind_udp_socket(client->index, &client->local_address); if (r < 0) return r; client->fd = r; r = sd_event_add_io(client->event, &client->receive_message, client->fd, EPOLLIN, client_receive_message, client); if (r < 0) goto error; r = sd_event_source_set_priority(client->receive_message, client->event_priority); if (r < 0) goto error; r = sd_event_source_set_description(client->receive_message, "dhcp6-receive-message"); if (r < 0) goto error; if (client->information_request) state = DHCP6_STATE_INFORMATION_REQUEST; log_dhcp6_client(client, "Started in %s mode", client->information_request? "Information request": "Managed"); return client_start(client, state); error: client_reset(client); return r; } int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int priority) { int r; assert_return(client, -EINVAL); assert_return(!client->event, -EBUSY); if (event) client->event = sd_event_ref(event); else { r = sd_event_default(&client->event); if (r < 0) return 0; } client->event_priority = priority; return 0; } int sd_dhcp6_client_detach_event(sd_dhcp6_client *client) { assert_return(client, -EINVAL); client->event = sd_event_unref(client->event); return 0; } sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) { if (!client) return NULL; return client->event; } sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client) { if (!client) return NULL; assert(client->n_ref >= 1); client->n_ref++; return client; } sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) { if (!client) return NULL; assert(client->n_ref >= 1); client->n_ref--; if (client->n_ref > 0) return NULL; client_reset(client); sd_dhcp6_client_detach_event(client); free(client->req_opts); free(client); return NULL; } int sd_dhcp6_client_new(sd_dhcp6_client **ret) { _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL; size_t t; assert_return(ret, -EINVAL); client = new0(sd_dhcp6_client, 1); if (!client) return -ENOMEM; client->n_ref = 1; client->ia_na.type = SD_DHCP6_OPTION_IA_NA; client->index = -1; client->fd = -1; client->req_opts_len = ELEMENTSOF(default_req_opts); client->req_opts = new0(be16_t, client->req_opts_len); if (!client->req_opts) return -ENOMEM; for (t = 0; t < client->req_opts_len; t++) client->req_opts[t] = htobe16(default_req_opts[t]); *ret = client; client = NULL; return 0; } systemd-229/src/libsystemd-network/sd-dhcp6-lease.c000066400000000000000000000250531265713322000223660ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014-2015 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "dhcp6-lease-internal.h" #include "dhcp6-protocol.h" #include "strv.h" #include "util.h" int dhcp6_lease_clear_timers(DHCP6IA *ia) { assert_return(ia, -EINVAL); ia->timeout_t1 = sd_event_source_unref(ia->timeout_t1); ia->timeout_t2 = sd_event_source_unref(ia->timeout_t2); return 0; } int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) { DHCP6Address *addr; uint32_t valid = 0, t; assert_return(ia, -EINVAL); assert_return(expire, -EINVAL); LIST_FOREACH(addresses, addr, ia->addresses) { t = be32toh(addr->iaaddr.lifetime_valid); if (valid < t) valid = t; } t = be32toh(ia->lifetime_t2); if (t > valid) return -EINVAL; *expire = valid - t; return 0; } DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) { DHCP6Address *address; if (!ia) return NULL; dhcp6_lease_clear_timers(ia); while (ia->addresses) { address = ia->addresses; LIST_REMOVE(addresses, ia->addresses, address); free(address); } return NULL; } int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id, size_t len) { assert_return(lease, -EINVAL); assert_return(id, -EINVAL); free(lease->serverid); lease->serverid = memdup(id, len); if (!lease->serverid) return -EINVAL; lease->serverid_len = len; return 0; } int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len) { assert_return(lease, -EINVAL); assert_return(id, -EINVAL); assert_return(len, -EINVAL); *id = lease->serverid; *len = lease->serverid_len; return 0; } int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, uint8_t preference) { assert_return(lease, -EINVAL); lease->preference = preference; return 0; } int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference) { assert_return(preference, -EINVAL); if (!lease) return -EINVAL; *preference = lease->preference; return 0; } int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease) { assert_return(lease, -EINVAL); lease->rapid_commit = true; return 0; } int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit) { assert_return(lease, -EINVAL); assert_return(rapid_commit, -EINVAL); *rapid_commit = lease->rapid_commit; return 0; } int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) { assert_return(lease, -EINVAL); assert_return(iaid, -EINVAL); *iaid = lease->ia.id; return 0; } int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr, uint32_t *lifetime_preferred, uint32_t *lifetime_valid) { assert_return(lease, -EINVAL); assert_return(addr, -EINVAL); assert_return(lifetime_preferred, -EINVAL); assert_return(lifetime_valid, -EINVAL); if (!lease->addr_iter) return -ENOMSG; memcpy(addr, &lease->addr_iter->iaaddr.address, sizeof(struct in6_addr)); *lifetime_preferred = be32toh(lease->addr_iter->iaaddr.lifetime_preferred); *lifetime_valid = be32toh(lease->addr_iter->iaaddr.lifetime_valid); lease->addr_iter = lease->addr_iter->addresses_next; return 0; } void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease) { if (lease) lease->addr_iter = lease->ia.addresses; } int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) { int r; assert_return(lease, -EINVAL); assert_return(optval, -EINVAL); if (!optlen) return 0; r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->dns, lease->dns_count, &lease->dns_allocated); if (r < 0) { log_dhcp6_client(client, "Invalid DNS server option: %s", strerror(-r)); return r; } lease->dns_count = r; return 0; } int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs) { assert_return(lease, -EINVAL); assert_return(addrs, -EINVAL); if (lease->dns_count) { *addrs = lease->dns; return lease->dns_count; } return -ENOENT; } int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) { int r; char **domains; assert_return(lease, -EINVAL); assert_return(optval, -EINVAL); if (!optlen) return 0; r = dhcp6_option_parse_domainname(optval, optlen, &domains); if (r < 0) return 0; free(lease->domains); lease->domains = domains; lease->domains_count = r; return r; } int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains) { assert_return(lease, -EINVAL); assert_return(domains, -EINVAL); if (lease->domains_count) { *domains = lease->domains; return lease->domains_count; } return -ENOENT; } int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) { int r; uint16_t subopt; size_t sublen; uint8_t *subval; assert_return(lease, -EINVAL); assert_return(optval, -EINVAL); lease->ntp = mfree(lease->ntp); lease->ntp_count = 0; lease->ntp_allocated = 0; while ((r = dhcp6_option_parse(&optval, &optlen, &subopt, &sublen, &subval)) >= 0) { int s; char **servers; switch(subopt) { case DHCP6_NTP_SUBOPTION_SRV_ADDR: case DHCP6_NTP_SUBOPTION_MC_ADDR: if (sublen != 16) return 0; s = dhcp6_option_parse_ip6addrs(subval, sublen, &lease->ntp, lease->ntp_count, &lease->ntp_allocated); if (s < 0) return s; lease->ntp_count = s; break; case DHCP6_NTP_SUBOPTION_SRV_FQDN: r = dhcp6_option_parse_domainname(subval, sublen, &servers); if (r < 0) return 0; lease->ntp_fqdn = strv_free(lease->ntp_fqdn); lease->ntp_fqdn = servers; lease->ntp_fqdn_count = r; break; } } if (r != -ENOMSG) return r; return 0; } int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) { int r; assert_return(lease, -EINVAL); assert_return(optval, -EINVAL); if (!optlen) return 0; if (lease->ntp || lease->ntp_fqdn) { log_dhcp6_client(client, "NTP information already provided"); return 0; } log_dhcp6_client(client, "Using deprecated SNTP information"); r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->ntp, lease->ntp_count, &lease->ntp_allocated); if (r < 0) { log_dhcp6_client(client, "Invalid SNTP server option: %s", strerror(-r)); return r; } lease->ntp_count = r; return 0; } int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, struct in6_addr **addrs) { assert_return(lease, -EINVAL); assert_return(addrs, -EINVAL); if (lease->ntp_count) { *addrs = lease->ntp; return lease->ntp_count; } return -ENOENT; } int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) { assert_return(lease, -EINVAL); assert_return(ntp_fqdn, -EINVAL); if (lease->ntp_fqdn_count) { *ntp_fqdn = lease->ntp_fqdn; return lease->ntp_fqdn_count; } return -ENOENT; } sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) { if (!lease) return NULL; assert(lease->n_ref >= 1); lease->n_ref++; return lease; } sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) { if (!lease) return NULL; assert(lease->n_ref >= 1); lease->n_ref--; if (lease->n_ref > 0) return NULL; free(lease->serverid); dhcp6_lease_free_ia(&lease->ia); free(lease->dns); lease->domains = strv_free(lease->domains); free(lease->ntp); lease->ntp_fqdn = strv_free(lease->ntp_fqdn); free(lease); return NULL; } int dhcp6_lease_new(sd_dhcp6_lease **ret) { sd_dhcp6_lease *lease; lease = new0(sd_dhcp6_lease, 1); if (!lease) return -ENOMEM; lease->n_ref = 1; LIST_HEAD_INIT(lease->ia.addresses); *ret = lease; return 0; } systemd-229/src/libsystemd-network/sd-ipv4acd.c000066400000000000000000000366271265713322000216360ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Axis Communications AB. All rights reserved. Copyright (C) 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-ipv4acd.h" #include "alloc-util.h" #include "arp-util.h" #include "fd-util.h" #include "in-addr-util.h" #include "list.h" #include "random-util.h" #include "refcnt.h" #include "siphash24.h" #include "util.h" /* Constants from the RFC */ #define PROBE_WAIT 1 #define PROBE_NUM 3 #define PROBE_MIN 1 #define PROBE_MAX 2 #define ANNOUNCE_WAIT 2 #define ANNOUNCE_NUM 2 #define ANNOUNCE_INTERVAL 2 #define MAX_CONFLICTS 10 #define RATE_LIMIT_INTERVAL 60 #define DEFEND_INTERVAL 10 #define IPV4ACD_NETWORK 0xA9FE0000L #define IPV4ACD_NETMASK 0xFFFF0000L #define log_ipv4acd_full(ll, level, error, fmt, ...) log_internal(level, error, __FILE__, __LINE__, __func__, "ACD: " fmt, ##__VA_ARGS__) #define log_ipv4acd_debug(ll, ...) log_ipv4acd_full(ll, LOG_DEBUG, 0, ##__VA_ARGS__) #define log_ipv4acd_info(ll, ...) log_ipv4acd_full(ll, LOG_INFO, 0, ##__VA_ARGS__) #define log_ipv4acd_notice(ll, ...) log_ipv4acd_full(ll, LOG_NOTICE, 0, ##__VA_ARGS__) #define log_ipv4acd_warning(ll, ...) log_ipv4acd_full(ll, LOG_WARNING, 0, ##__VA_ARGS__) #define log_ipv4acd_error(ll, ...) log_ipv4acd_full(ll, LOG_ERR, 0, ##__VA_ARGS__) #define log_ipv4acd_debug_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_DEBUG, error, ##__VA_ARGS__) #define log_ipv4acd_info_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_INFO, error, ##__VA_ARGS__) #define log_ipv4acd_notice_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_NOTICE, error, ##__VA_ARGS__) #define log_ipv4acd_warning_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_WARNING, error, ##__VA_ARGS__) #define log_ipv4acd_error_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_ERR, error, ##__VA_ARGS__) typedef enum IPv4ACDState { IPV4ACD_STATE_INIT, IPV4ACD_STATE_WAITING_PROBE, IPV4ACD_STATE_PROBING, IPV4ACD_STATE_WAITING_ANNOUNCE, IPV4ACD_STATE_ANNOUNCING, IPV4ACD_STATE_RUNNING, _IPV4ACD_STATE_MAX, _IPV4ACD_STATE_INVALID = -1 } IPv4ACDState; struct sd_ipv4acd { RefCount n_ref; IPv4ACDState state; int index; int fd; int iteration; int conflict; sd_event_source *receive_message; sd_event_source *timer; usec_t defend_window; be32_t address; /* External */ struct ether_addr mac_addr; sd_event *event; int event_priority; sd_ipv4acd_cb_t cb; void* userdata; }; sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *ll) { if (ll) assert_se(REFCNT_INC(ll->n_ref) >= 2); return ll; } sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *ll) { if (!ll || REFCNT_DEC(ll->n_ref) > 0) return NULL; ll->receive_message = sd_event_source_unref(ll->receive_message); ll->fd = safe_close(ll->fd); ll->timer = sd_event_source_unref(ll->timer); sd_ipv4acd_detach_event(ll); free(ll); return NULL; } int sd_ipv4acd_new(sd_ipv4acd **ret) { _cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *ll = NULL; assert_return(ret, -EINVAL); ll = new0(sd_ipv4acd, 1); if (!ll) return -ENOMEM; ll->n_ref = REFCNT_INIT; ll->state = IPV4ACD_STATE_INIT; ll->index = -1; ll->fd = -1; *ret = ll; ll = NULL; return 0; } static void ipv4acd_set_state(sd_ipv4acd *ll, IPv4ACDState st, bool reset_counter) { assert(ll); assert(st < _IPV4ACD_STATE_MAX); if (st == ll->state && !reset_counter) ll->iteration++; else { ll->state = st; ll->iteration = 0; } } static void ipv4acd_client_notify(sd_ipv4acd *ll, int event) { assert(ll); if (ll->cb) ll->cb(ll, event, ll->userdata); } static void ipv4acd_stop(sd_ipv4acd *ll) { assert(ll); ll->receive_message = sd_event_source_unref(ll->receive_message); ll->fd = safe_close(ll->fd); ll->timer = sd_event_source_unref(ll->timer); log_ipv4acd_debug(ll, "STOPPED"); ipv4acd_set_state (ll, IPV4ACD_STATE_INIT, true); } int sd_ipv4acd_stop(sd_ipv4acd *ll) { assert_return(ll, -EINVAL); ipv4acd_stop(ll); ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_STOP); return 0; } static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata); static int ipv4acd_set_next_wakeup(sd_ipv4acd *ll, int sec, int random_sec) { _cleanup_(sd_event_source_unrefp) sd_event_source *timer = NULL; usec_t next_timeout; usec_t time_now; int r; assert(sec >= 0); assert(random_sec >= 0); assert(ll); next_timeout = sec * USEC_PER_SEC; if (random_sec) next_timeout += random_u32() % (random_sec * USEC_PER_SEC); assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &time_now) >= 0); r = sd_event_add_time(ll->event, &timer, clock_boottime_or_monotonic(), time_now + next_timeout, 0, ipv4acd_on_timeout, ll); if (r < 0) return r; r = sd_event_source_set_priority(timer, ll->event_priority); if (r < 0) return r; r = sd_event_source_set_description(timer, "ipv4acd-timer"); if (r < 0) return r; ll->timer = sd_event_source_unref(ll->timer); ll->timer = timer; timer = NULL; return 0; } static bool ipv4acd_arp_conflict(sd_ipv4acd *ll, struct ether_arp *arp) { assert(ll); assert(arp); /* see the BPF */ if (memcmp(arp->arp_spa, &ll->address, sizeof(ll->address)) == 0) return true; /* the TPA matched instead of the SPA, this is not a conflict */ return false; } static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) { sd_ipv4acd *ll = userdata; int r = 0; assert(ll); switch (ll->state) { case IPV4ACD_STATE_INIT: ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_PROBE, true); if (ll->conflict >= MAX_CONFLICTS) { log_ipv4acd_notice(ll, "Max conflicts reached, delaying by %us", RATE_LIMIT_INTERVAL); r = ipv4acd_set_next_wakeup(ll, RATE_LIMIT_INTERVAL, PROBE_WAIT); if (r < 0) goto out; ll->conflict = 0; } else { r = ipv4acd_set_next_wakeup(ll, 0, PROBE_WAIT); if (r < 0) goto out; } break; case IPV4ACD_STATE_WAITING_PROBE: case IPV4ACD_STATE_PROBING: /* Send a probe */ r = arp_send_probe(ll->fd, ll->index, ll->address, &ll->mac_addr); if (r < 0) { log_ipv4acd_error_errno(ll, r, "Failed to send ARP probe: %m"); goto out; } else { _cleanup_free_ char *address = NULL; union in_addr_union addr = { .in.s_addr = ll->address }; r = in_addr_to_string(AF_INET, &addr, &address); if (r >= 0) log_ipv4acd_debug(ll, "Probing %s", address); } if (ll->iteration < PROBE_NUM - 2) { ipv4acd_set_state(ll, IPV4ACD_STATE_PROBING, false); r = ipv4acd_set_next_wakeup(ll, PROBE_MIN, (PROBE_MAX-PROBE_MIN)); if (r < 0) goto out; } else { ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_ANNOUNCE, true); r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_WAIT, 0); if (r < 0) goto out; } break; case IPV4ACD_STATE_ANNOUNCING: if (ll->iteration >= ANNOUNCE_NUM - 1) { ipv4acd_set_state(ll, IPV4ACD_STATE_RUNNING, false); break; } case IPV4ACD_STATE_WAITING_ANNOUNCE: /* Send announcement packet */ r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr); if (r < 0) { log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m"); goto out; } else log_ipv4acd_debug(ll, "ANNOUNCE"); ipv4acd_set_state(ll, IPV4ACD_STATE_ANNOUNCING, false); r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_INTERVAL, 0); if (r < 0) goto out; if (ll->iteration == 0) { ll->conflict = 0; ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_BIND); } break; default: assert_not_reached("Invalid state."); } out: if (r < 0) sd_ipv4acd_stop(ll); return 1; } static void ipv4acd_on_conflict(sd_ipv4acd *ll) { _cleanup_free_ char *address = NULL; union in_addr_union addr = { .in.s_addr = ll->address }; int r; assert(ll); ll->conflict++; r = in_addr_to_string(AF_INET, &addr, &address); if (r >= 0) log_ipv4acd_debug(ll, "Conflict on %s (%u)", address, ll->conflict); ipv4acd_stop(ll); ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_CONFLICT); } static int ipv4acd_on_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { sd_ipv4acd *ll = userdata; struct ether_arp packet; int r; assert(ll); assert(fd >= 0); r = read(fd, &packet, sizeof(struct ether_arp)); if (r < (int) sizeof(struct ether_arp)) goto out; switch (ll->state) { case IPV4ACD_STATE_ANNOUNCING: case IPV4ACD_STATE_RUNNING: if (ipv4acd_arp_conflict(ll, &packet)) { usec_t ts; assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &ts) >= 0); /* Defend address */ if (ts > ll->defend_window) { ll->defend_window = ts + DEFEND_INTERVAL * USEC_PER_SEC; r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr); if (r < 0) { log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m"); goto out; } else log_ipv4acd_debug(ll, "DEFEND"); } else ipv4acd_on_conflict(ll); } break; case IPV4ACD_STATE_WAITING_PROBE: case IPV4ACD_STATE_PROBING: case IPV4ACD_STATE_WAITING_ANNOUNCE: /* BPF ensures this packet indicates a conflict */ ipv4acd_on_conflict(ll); break; default: assert_not_reached("Invalid state."); } out: if (r < 0) sd_ipv4acd_stop(ll); return 1; } int sd_ipv4acd_set_index(sd_ipv4acd *ll, int interface_index) { assert_return(ll, -EINVAL); assert_return(interface_index > 0, -EINVAL); assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY); ll->index = interface_index; return 0; } int sd_ipv4acd_set_mac(sd_ipv4acd *ll, const struct ether_addr *addr) { assert_return(ll, -EINVAL); assert_return(addr, -EINVAL); assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY); memcpy(&ll->mac_addr, addr, ETH_ALEN); return 0; } int sd_ipv4acd_detach_event(sd_ipv4acd *ll) { assert_return(ll, -EINVAL); ll->event = sd_event_unref(ll->event); return 0; } int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int priority) { int r; assert_return(ll, -EINVAL); assert_return(!ll->event, -EBUSY); if (event) ll->event = sd_event_ref(event); else { r = sd_event_default(&ll->event); if (r < 0) return r; } ll->event_priority = priority; return 0; } int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_cb_t cb, void *userdata) { assert_return(ll, -EINVAL); ll->cb = cb; ll->userdata = userdata; return 0; } int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address){ assert_return(ll, -EINVAL); assert_return(address, -EINVAL); assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY); ll->address = address->s_addr; return 0; } int sd_ipv4acd_is_running(sd_ipv4acd *ll) { assert_return(ll, false); return ll->state != IPV4ACD_STATE_INIT; } static bool ether_addr_is_nul(const struct ether_addr *addr) { const struct ether_addr nul_addr = {}; assert(addr); return memcmp(addr, &nul_addr, sizeof(struct ether_addr)) == 0; } #define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2) int sd_ipv4acd_start(sd_ipv4acd *ll) { int r; assert_return(ll, -EINVAL); assert_return(ll->event, -EINVAL); assert_return(ll->index > 0, -EINVAL); assert_return(ll->address != 0, -EINVAL); assert_return(!ether_addr_is_nul(&ll->mac_addr), -EINVAL); assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY); ll->defend_window = 0; r = arp_network_bind_raw_socket(ll->index, ll->address, &ll->mac_addr); if (r < 0) goto out; ll->fd = safe_close(ll->fd); ll->fd = r; r = sd_event_add_io(ll->event, &ll->receive_message, ll->fd, EPOLLIN, ipv4acd_on_packet, ll); if (r < 0) goto out; r = sd_event_source_set_priority(ll->receive_message, ll->event_priority); if (r < 0) goto out; r = sd_event_source_set_description(ll->receive_message, "ipv4acd-receive-message"); if (r < 0) goto out; r = ipv4acd_set_next_wakeup(ll, 0, 0); if (r < 0) goto out; out: if (r < 0) { ipv4acd_stop(ll); return r; } return 0; } systemd-229/src/libsystemd-network/sd-ipv4ll.c000066400000000000000000000215311265713322000215020ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Axis Communications AB. All rights reserved. Copyright (C) 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-ipv4acd.h" #include "sd-ipv4ll.h" #include "alloc-util.h" #include "in-addr-util.h" #include "list.h" #include "random-util.h" #include "refcnt.h" #include "siphash24.h" #include "sparse-endian.h" #include "util.h" #define IPV4LL_NETWORK 0xA9FE0000L #define IPV4LL_NETMASK 0xFFFF0000L #define IPV4LL_DONT_DESTROY(ll) \ _cleanup_(sd_ipv4ll_unrefp) _unused_ sd_ipv4ll *_dont_destroy_##ll = sd_ipv4ll_ref(ll) struct sd_ipv4ll { unsigned n_ref; sd_ipv4acd *acd; be32_t address; /* the address pushed to ACD */ struct random_data *random_data; char *random_data_state; /* External */ be32_t claimed_address; sd_ipv4ll_cb_t cb; void* userdata; }; sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll) { if (!ll) return NULL; assert(ll->n_ref >= 1); ll->n_ref++; return ll; } sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) { if (!ll) return NULL; assert(ll->n_ref >= 1); ll->n_ref--; if (ll->n_ref > 0) return NULL; sd_ipv4acd_unref(ll->acd); free(ll->random_data); free(ll->random_data_state); free(ll); return NULL; } static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata); int sd_ipv4ll_new(sd_ipv4ll **ret) { _cleanup_(sd_ipv4ll_unrefp) sd_ipv4ll *ll = NULL; int r; assert_return(ret, -EINVAL); ll = new0(sd_ipv4ll, 1); if (!ll) return -ENOMEM; ll->n_ref = 1; r = sd_ipv4acd_new(&ll->acd); if (r < 0) return r; r = sd_ipv4acd_set_callback(ll->acd, ipv4ll_on_acd, ll); if (r < 0) return r; *ret = ll; ll = NULL; return 0; } int sd_ipv4ll_stop(sd_ipv4ll *ll) { int r; assert_return(ll, -EINVAL); r = sd_ipv4acd_stop(ll->acd); if (r < 0) return r; return 0; } int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index) { assert_return(ll, -EINVAL); return sd_ipv4acd_set_index(ll->acd, interface_index); } #define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2) int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr) { int r; assert_return(ll, -EINVAL); if (!ll->random_data) { uint64_t seed; /* If no random data is set, generate some from the MAC */ seed = siphash24(&addr->ether_addr_octet, ETH_ALEN, HASH_KEY.bytes); assert_cc(sizeof(unsigned) <= 8); r = sd_ipv4ll_set_address_seed(ll, (unsigned) htole64(seed)); if (r < 0) return r; } return sd_ipv4acd_set_mac(ll->acd, addr); } int sd_ipv4ll_detach_event(sd_ipv4ll *ll) { assert_return(ll, -EINVAL); return sd_ipv4acd_detach_event(ll->acd); } int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int priority) { int r; assert_return(ll, -EINVAL); r = sd_ipv4acd_attach_event(ll->acd, event, priority); if (r < 0) return r; return 0; } int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_cb_t cb, void *userdata) { assert_return(ll, -EINVAL); ll->cb = cb; ll->userdata = userdata; return 0; } int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address){ assert_return(ll, -EINVAL); assert_return(address, -EINVAL); if (ll->claimed_address == 0) return -ENOENT; address->s_addr = ll->claimed_address; return 0; } int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, unsigned seed) { _cleanup_free_ struct random_data *random_data = NULL; _cleanup_free_ char *random_data_state = NULL; int r; assert_return(ll, -EINVAL); random_data = new0(struct random_data, 1); if (!random_data) return -ENOMEM; random_data_state = new0(char, 128); if (!random_data_state) return -ENOMEM; r = initstate_r(seed, random_data_state, 128, random_data); if (r < 0) return r; free(ll->random_data); ll->random_data = random_data; random_data = NULL; free(ll->random_data_state); ll->random_data_state = random_data_state; random_data_state = NULL; return 0; } int sd_ipv4ll_is_running(sd_ipv4ll *ll) { assert_return(ll, false); return sd_ipv4acd_is_running(ll->acd); } static bool ipv4ll_address_is_valid(const struct in_addr *address) { uint32_t addr; assert(address); if (!in_addr_is_link_local(AF_INET, (const union in_addr_union *) address)) return false; addr = be32toh(address->s_addr); if ((addr & 0x0000FF00) == 0x0000 || (addr & 0x0000FF00) == 0xFF00) return false; return true; } int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address) { int r; assert_return(ll, -EINVAL); assert_return(address, -EINVAL); assert_return(ipv4ll_address_is_valid(address), -EINVAL); r = sd_ipv4acd_set_address(ll->acd, address); if (r < 0) return r; ll->address = address->s_addr; return 0; } static int ipv4ll_pick_address(sd_ipv4ll *ll) { struct in_addr in_addr; be32_t addr; int r; int32_t random; assert(ll); assert(ll->random_data); do { r = random_r(ll->random_data, &random); if (r < 0) return r; addr = htonl((random & 0x0000FFFF) | IPV4LL_NETWORK); } while (addr == ll->address || (ntohl(addr) & 0x0000FF00) == 0x0000 || (ntohl(addr) & 0x0000FF00) == 0xFF00); in_addr.s_addr = addr; r = sd_ipv4ll_set_address(ll, &in_addr); if (r < 0) return r; return 0; } int sd_ipv4ll_start(sd_ipv4ll *ll) { int r; assert_return(ll, -EINVAL); assert_return(ll->random_data, -EINVAL); if (ll->address == 0) { r = ipv4ll_pick_address(ll); if (r < 0) return r; } r = sd_ipv4acd_start(ll->acd); if (r < 0) return r; return 0; } static void ipv4ll_client_notify(sd_ipv4ll *ll, int event) { assert(ll); if (ll->cb) ll->cb(ll, event, ll->userdata); } void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata) { sd_ipv4ll *ll = userdata; IPV4LL_DONT_DESTROY(ll); int r; assert(acd); assert(ll); switch (event) { case SD_IPV4ACD_EVENT_STOP: ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP); ll->claimed_address = 0; break; case SD_IPV4ACD_EVENT_BIND: ll->claimed_address = ll->address; ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_BIND); break; case SD_IPV4ACD_EVENT_CONFLICT: /* if an address was already bound we must call up to the user to handle this, otherwise we just try again */ if (ll->claimed_address != 0) { ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_CONFLICT); ll->claimed_address = 0; } else { r = ipv4ll_pick_address(ll); if (r < 0) goto error; r = sd_ipv4acd_start(ll->acd); if (r < 0) goto error; } break; default: assert_not_reached("Invalid IPv4ACD event."); } return; error: ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP); } systemd-229/src/libsystemd-network/sd-lldp.c000066400000000000000000000532061265713322000212270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-lldp.h" #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "hashmap.h" #include "lldp-internal.h" #include "lldp-port.h" #include "lldp-tlv.h" #include "prioq.h" #include "siphash24.h" #include "string-util.h" typedef enum LLDPAgentRXState { LLDP_AGENT_RX_WAIT_PORT_OPERATIONAL = 4, LLDP_AGENT_RX_DELETE_AGED_INFO, LLDP_AGENT_RX_LLDP_INITIALIZE, LLDP_AGENT_RX_WAIT_FOR_FRAME, LLDP_AGENT_RX_RX_FRAME, LLDP_AGENT_RX_DELETE_INFO, LLDP_AGENT_RX_UPDATE_INFO, _LLDP_AGENT_RX_STATE_MAX, _LLDP_AGENT_RX_INVALID = -1, } LLDPAgentRXState; /* Section 10.5.2.2 Reception counters */ struct lldp_agent_statistics { uint64_t stats_ageouts_total; uint64_t stats_frames_discarded_total; uint64_t stats_frames_in_errors_total; uint64_t stats_frames_in_total; uint64_t stats_tlvs_discarded_total; uint64_t stats_tlvs_unrecognized_total; }; struct sd_lldp { lldp_port *port; Prioq *by_expiry; Hashmap *neighbour_mib; sd_lldp_cb_t cb; void *userdata; LLDPAgentRXState rx_state; lldp_agent_statistics statistics; }; static void chassis_id_hash_func(const void *p, struct siphash *state) { const lldp_chassis_id *id = p; assert(id); assert(id->data); siphash24_compress(&id->length, sizeof(id->length), state); siphash24_compress(id->data, id->length, state); } static int chassis_id_compare_func(const void *_a, const void *_b) { const lldp_chassis_id *a, *b; a = _a; b = _b; assert(!a->length || a->data); assert(!b->length || b->data); if (a->type != b->type) return -1; if (a->length != b->length) return a->length < b->length ? -1 : 1; return memcmp(a->data, b->data, a->length); } static const struct hash_ops chassis_id_hash_ops = { .hash = chassis_id_hash_func, .compare = chassis_id_compare_func }; static void lldp_mib_delete_objects(sd_lldp *lldp); static void lldp_set_state(sd_lldp *lldp, LLDPAgentRXState state); static void lldp_run_state_machine(sd_lldp *ll); static int lldp_receive_frame(sd_lldp *lldp, tlv_packet *tlv) { int r; assert(lldp); assert(tlv); /* Remove expired packets */ if (prioq_size(lldp->by_expiry) > 0) { lldp_set_state(lldp, LLDP_AGENT_RX_DELETE_INFO); lldp_mib_delete_objects(lldp); } r = lldp_mib_add_objects(lldp->by_expiry, lldp->neighbour_mib, tlv); if (r < 0) goto out; lldp_set_state(lldp, LLDP_AGENT_RX_UPDATE_INFO); log_lldp("Packet added. MIB size: %d , PQ size: %d", hashmap_size(lldp->neighbour_mib), prioq_size(lldp->by_expiry)); lldp->statistics.stats_frames_in_total ++; out: if (r < 0) log_lldp("Receive frame failed: %s", strerror(-r)); lldp_set_state(lldp, LLDP_AGENT_RX_WAIT_FOR_FRAME); return 0; } /* 10.3.2 LLDPDU validation: rxProcessFrame() */ int lldp_handle_packet(tlv_packet *tlv, uint16_t length) { bool system_description = false, system_name = false, chassis_id = false; bool malformed = false, port_id = false, ttl = false, end = false; uint16_t type, len, i, l, t; lldp_port *port; uint8_t *p, *q; sd_lldp *lldp; int r; assert(tlv); assert(length > 0); port = (lldp_port *) tlv->userdata; lldp = (sd_lldp *) port->userdata; if (lldp->port->status == LLDP_PORT_STATUS_DISABLED) { log_lldp("Port: %s is disabled. Dropping.", lldp->port->ifname); goto out; } lldp_set_state(lldp, LLDP_AGENT_RX_RX_FRAME); p = tlv->pdu; p += sizeof(struct ether_header); for (i = 1, l = 0; l <= length; i++) { memcpy(&t, p, sizeof(uint16_t)); type = ntohs(t) >> 9; len = ntohs(t) & 0x01ff; if (type == LLDP_TYPE_END) { if (len != 0) { log_lldp("TLV type end must be length 0 (not %d). Dropping.", len); malformed = true; goto out; } end = true; break; } else if (type >=_LLDP_TYPE_MAX) { log_lldp("TLV type: %d not recognized. Dropping.", type); malformed = true; goto out; } /* skip type and length encoding */ p += 2; q = p; p += len; l += (len + 2); if (i <= 3) { if (i != type) { log_lldp("TLV missing or out of order. Dropping."); malformed = true; goto out; } } switch(type) { case LLDP_TYPE_CHASSIS_ID: if (len < 2) { log_lldp("Received malformed Chassis ID TLV length: %d. Dropping.", len); malformed = true; goto out; } if (chassis_id) { log_lldp("Duplicate Chassis ID TLV found. Dropping."); malformed = true; goto out; } /* Look what subtype it has */ if (*q == LLDP_CHASSIS_SUBTYPE_RESERVED || *q > LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED) { log_lldp("Unknown subtype: %d found in Chassis ID TLV. Dropping.", *q); malformed = true; goto out; } chassis_id = true; break; case LLDP_TYPE_PORT_ID: if (len < 2) { log_lldp("Received malformed Port ID TLV length: %d. Dropping.", len); malformed = true; goto out; } if (port_id) { log_lldp("Duplicate Port ID TLV found. Dropping."); malformed = true; goto out; } /* Look what subtype it has */ if (*q == LLDP_PORT_SUBTYPE_RESERVED || *q > LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED) { log_lldp("Unknown subtype: %d found in Port ID TLV. Dropping.", *q); malformed = true; goto out; } port_id = true; break; case LLDP_TYPE_TTL: if(len != 2) { log_lldp("Received invalid TTL TLV lenth: %d. Dropping.", len); malformed = true; goto out; } if (ttl) { log_lldp("Duplicate TTL TLV found. Dropping."); malformed = true; goto out; } ttl = true; break; case LLDP_TYPE_SYSTEM_NAME: /* According to RFC 1035 the length of a FQDN is limited to 255 characters */ if (len > 255) { log_lldp("Received invalid system name length: %d. Dropping.", len); malformed = true; goto out; } if (system_name) { log_lldp("Duplicate system name found. Dropping."); malformed = true; goto out; } system_name = true; break; case LLDP_TYPE_SYSTEM_DESCRIPTION: /* 0 <= n <= 255 octets */ if (len > 255) { log_lldp("Received invalid system description length: %d. Dropping.", len); malformed = true; goto out; } if (system_description) { log_lldp("Duplicate system description found. Dropping."); malformed = true; goto out; } system_description = true; break; default: if (len == 0) { log_lldp("TLV type: %d length 0 received. Dropping.", type); malformed = true; goto out; } break; } } if(!chassis_id || !port_id || !ttl || !end) { log_lldp("One or more mandatory TLV missing. Dropping."); malformed = true; goto out; } r = tlv_packet_parse_pdu(tlv, length); if (r < 0) { log_lldp("Failed to parse the TLV. Dropping."); malformed = true; goto out; } return lldp_receive_frame(lldp, tlv); out: lldp_set_state(lldp, LLDP_AGENT_RX_WAIT_FOR_FRAME); if (malformed) { lldp->statistics.stats_frames_discarded_total ++; lldp->statistics.stats_frames_in_errors_total ++; } sd_lldp_packet_unref(tlv); return 0; } static int ttl_expiry_item_prioq_compare_func(const void *a, const void *b) { const lldp_neighbour_port *p = a, *q = b; if (p->until < q->until) return -1; if (p->until > q->until) return 1; return 0; } static void lldp_set_state(sd_lldp *lldp, LLDPAgentRXState state) { assert(lldp); assert(state < _LLDP_AGENT_RX_STATE_MAX); lldp->rx_state = state; lldp_run_state_machine(lldp); } static void lldp_run_state_machine(sd_lldp *lldp) { if (!lldp->cb) return; switch (lldp->rx_state) { case LLDP_AGENT_RX_UPDATE_INFO: lldp->cb(lldp, SD_LLDP_EVENT_UPDATE_INFO, lldp->userdata); break; default: break; } } /* 10.5.5.2.1 mibDeleteObjects () * The mibDeleteObjects () procedure deletes all information in the LLDP remote * systems MIB associated with the MSAP identifier if an LLDPDU is received with * an rxTTL value of zero (see 10.3.2) or the timing counter rxInfoTTL expires. */ static void lldp_mib_delete_objects(sd_lldp *lldp) { lldp_neighbour_port *p; usec_t t = 0; /* Remove all entries that are past their TTL */ for (;;) { if (prioq_size(lldp->by_expiry) <= 0) break; p = prioq_peek(lldp->by_expiry); if (!p) break; if (t <= 0) t = now(clock_boottime_or_monotonic()); if (p->until > t) break; lldp_neighbour_port_remove_and_free(p); lldp->statistics.stats_ageouts_total ++; } } static void lldp_mib_objects_flush(sd_lldp *lldp) { lldp_neighbour_port *p, *q; lldp_chassis *c; assert(lldp); assert(lldp->neighbour_mib); assert(lldp->by_expiry); /* Drop all packets */ while ((c = hashmap_steal_first(lldp->neighbour_mib))) { LIST_FOREACH_SAFE(port, p, q, c->ports) { lldp_neighbour_port_remove_and_free(p); } } assert(hashmap_size(lldp->neighbour_mib) == 0); assert(prioq_size(lldp->by_expiry) == 0); } int sd_lldp_save(sd_lldp *lldp, const char *lldp_file) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; uint8_t *mac, *port_id, type; lldp_neighbour_port *p; uint16_t data = 0, length = 0; char buf[LINE_MAX]; lldp_chassis *c; usec_t time; Iterator i; int r; assert(lldp); assert(lldp_file); r = fopen_temporary(lldp_file, &f, &temp_path); if (r < 0) goto fail; fchmod(fileno(f), 0644); HASHMAP_FOREACH(c, lldp->neighbour_mib, i) { LIST_FOREACH(port, p, c->ports) { _cleanup_free_ char *s = NULL; char *k, *t; r = sd_lldp_packet_read_chassis_id(p->packet, &type, &mac, &length); if (r < 0) continue; sprintf(buf, "'_Chassis=%02x:%02x:%02x:%02x:%02x:%02x' '_CType=%d' ", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], type); s = strdup(buf); if (!s) { r = -ENOMEM; goto fail; } r = sd_lldp_packet_read_port_id(p->packet, &type, &port_id, &length); if (r < 0) continue; if (type != LLDP_PORT_SUBTYPE_MAC_ADDRESS) { k = strndup((char *) port_id, length -1); if (!k) { r = -ENOMEM; goto fail; } sprintf(buf, "'_Port=%s' '_PType=%d' ", k , type); free(k); } else { mac = port_id; sprintf(buf, "'_Port=%02x:%02x:%02x:%02x:%02x:%02x' '_PType=%d' ", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], type); } k = strappend(s, buf); if (!k) { r = -ENOMEM; goto fail; } free(s); s = k; time = now(clock_boottime_or_monotonic()); /* Don't write expired packets */ if (time - p->until <= 0) continue; sprintf(buf, "'_TTL="USEC_FMT"' ", p->until); k = strappend(s, buf); if (!k) { r = -ENOMEM; goto fail; } free(s); s = k; r = sd_lldp_packet_read_system_name(p->packet, &k, &length); if (r < 0) k = strappend(s, "'_NAME=N/A' "); else { t = strndup(k, length); if (!t) { r = -ENOMEM; goto fail; } k = strjoin(s, "'_NAME=", t, "' ", NULL); free(t); } if (!k) { r = -ENOMEM; goto fail; } free(s); s = k; (void) sd_lldp_packet_read_system_capability(p->packet, &data); sprintf(buf, "'_CAP=%x'", data); k = strappend(s, buf); if (!k) { r = -ENOMEM; goto fail; } free(s); s = k; fprintf(f, "%s\n", s); } } r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, lldp_file) < 0) { r = -errno; goto fail; } return 0; fail: if (temp_path) (void) unlink(temp_path); return log_error_errno(r, "Failed to save lldp data %s: %m", lldp_file); } int sd_lldp_start(sd_lldp *lldp) { int r; assert_return(lldp, -EINVAL); assert_return(lldp->port, -EINVAL); lldp->port->status = LLDP_PORT_STATUS_ENABLED; lldp_set_state(lldp, LLDP_AGENT_RX_LLDP_INITIALIZE); r = lldp_port_start(lldp->port); if (r < 0) { log_lldp("Failed to start Port : %s , %s", lldp->port->ifname, strerror(-r)); lldp_set_state(lldp, LLDP_AGENT_RX_WAIT_PORT_OPERATIONAL); return r; } lldp_set_state(lldp, LLDP_AGENT_RX_WAIT_FOR_FRAME); return 0; } int sd_lldp_stop(sd_lldp *lldp) { int r; assert_return(lldp, -EINVAL); assert_return(lldp->port, -EINVAL); lldp->port->status = LLDP_PORT_STATUS_DISABLED; r = lldp_port_stop(lldp->port); if (r < 0) return r; lldp_mib_objects_flush(lldp); return 0; } int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int priority) { int r; assert_return(lldp, -EINVAL); assert_return(!lldp->port->event, -EBUSY); if (event) lldp->port->event = sd_event_ref(event); else { r = sd_event_default(&lldp->port->event); if (r < 0) return r; } lldp->port->event_priority = priority; return 0; } int sd_lldp_detach_event(sd_lldp *lldp) { assert_return(lldp, -EINVAL); lldp->port->event = sd_event_unref(lldp->port->event); return 0; } int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_cb_t cb, void *userdata) { assert_return(lldp, -EINVAL); lldp->cb = cb; lldp->userdata = userdata; return 0; } sd_lldp* sd_lldp_unref(sd_lldp *lldp) { if (!lldp) return NULL; /* Drop all packets */ lldp_mib_objects_flush(lldp); lldp_port_free(lldp->port); hashmap_free(lldp->neighbour_mib); prioq_free(lldp->by_expiry); free(lldp); return NULL; } int sd_lldp_new(int ifindex, const char *ifname, const struct ether_addr *mac, sd_lldp **ret) { _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL; int r; assert_return(ret, -EINVAL); assert_return(ifindex > 0, -EINVAL); assert_return(ifname, -EINVAL); assert_return(mac, -EINVAL); lldp = new0(sd_lldp, 1); if (!lldp) return -ENOMEM; r = lldp_port_new(ifindex, ifname, mac, lldp, &lldp->port); if (r < 0) return r; lldp->neighbour_mib = hashmap_new(&chassis_id_hash_ops); if (!lldp->neighbour_mib) return -ENOMEM; r = prioq_ensure_allocated(&lldp->by_expiry, ttl_expiry_item_prioq_compare_func); if (r < 0) return r; lldp->rx_state = LLDP_AGENT_RX_WAIT_PORT_OPERATIONAL; *ret = lldp; lldp = NULL; return 0; } int sd_lldp_get_packets(sd_lldp *lldp, sd_lldp_packet ***tlvs) { lldp_neighbour_port *p; lldp_chassis *c; Iterator iter; unsigned count = 0, i; assert_return(lldp, -EINVAL); assert_return(tlvs, -EINVAL); HASHMAP_FOREACH(c, lldp->neighbour_mib, iter) { LIST_FOREACH(port, p, c->ports) count++; } if (!count) { *tlvs = NULL; return 0; } *tlvs = new(sd_lldp_packet *, count); if (!*tlvs) return -ENOMEM; i = 0; HASHMAP_FOREACH(c, lldp->neighbour_mib, iter) { LIST_FOREACH(port, p, c->ports) (*tlvs)[i++] = sd_lldp_packet_ref(p->packet); } return count; } systemd-229/src/libsystemd-network/sd-ndisc.c000066400000000000000000000517131265713322000213750ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "sd-ndisc.h" #include "alloc-util.h" #include "async.h" #include "icmp6-util.h" #include "in-addr-util.h" #include "list.h" #include "socket-util.h" #include "string-util.h" #define NDISC_ROUTER_SOLICITATION_INTERVAL 4 * USEC_PER_SEC #define NDISC_MAX_ROUTER_SOLICITATIONS 3 enum NDiscState { NDISC_STATE_IDLE, NDISC_STATE_SOLICITATION_SENT, NDISC_STATE_ADVERTISMENT_LISTEN, _NDISC_STATE_MAX, _NDISC_STATE_INVALID = -1, }; #define IP6_MIN_MTU (unsigned)1280 #define ICMP6_RECV_SIZE (IP6_MIN_MTU - sizeof(struct ip6_hdr)) #define NDISC_OPT_LEN_UNITS 8 #define ND_RA_FLAG_PREF 0x18 #define ND_RA_FLAG_PREF_LOW 0x03 #define ND_RA_FLAG_PREF_MEDIUM 0x0 #define ND_RA_FLAG_PREF_HIGH 0x1 #define ND_RA_FLAG_PREF_INVALID 0x2 typedef struct NDiscPrefix NDiscPrefix; struct NDiscPrefix { unsigned n_ref; sd_ndisc *nd; LIST_FIELDS(NDiscPrefix, prefixes); uint8_t len; usec_t valid_until; struct in6_addr addr; }; struct sd_ndisc { unsigned n_ref; enum NDiscState state; sd_event *event; int event_priority; int index; struct ether_addr mac_addr; uint32_t mtu; LIST_HEAD(NDiscPrefix, prefixes); int fd; sd_event_source *recv; sd_event_source *timeout; int nd_sent; sd_ndisc_router_callback_t router_callback; sd_ndisc_prefix_autonomous_callback_t prefix_autonomous_callback; sd_ndisc_prefix_onlink_callback_t prefix_onlink_callback; sd_ndisc_callback_t callback; void *userdata; }; #define log_ndisc(p, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "NDisc CLIENT: " fmt, ##__VA_ARGS__) static NDiscPrefix *ndisc_prefix_unref(NDiscPrefix *prefix) { if (!prefix) return NULL; assert(prefix->n_ref > 0); prefix->n_ref--; if (prefix->n_ref > 0) return NULL; if (prefix->nd) LIST_REMOVE(prefixes, prefix->nd->prefixes, prefix); free(prefix); return NULL; } static int ndisc_prefix_new(sd_ndisc *nd, NDiscPrefix **ret) { NDiscPrefix *prefix; assert(ret); prefix = new0(NDiscPrefix, 1); if (!prefix) return -ENOMEM; prefix->n_ref = 1; LIST_INIT(prefixes, prefix); prefix->nd = nd; *ret = prefix; return 0; } int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_router_callback_t router_callback, sd_ndisc_prefix_onlink_callback_t prefix_onlink_callback, sd_ndisc_prefix_autonomous_callback_t prefix_autonomous_callback, sd_ndisc_callback_t callback, void *userdata) { assert(nd); nd->router_callback = router_callback; nd->prefix_onlink_callback = prefix_onlink_callback; nd->prefix_autonomous_callback = prefix_autonomous_callback; nd->callback = callback; nd->userdata = userdata; return 0; } int sd_ndisc_set_index(sd_ndisc *nd, int interface_index) { assert(nd); assert(interface_index >= -1); nd->index = interface_index; return 0; } int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr) { assert(nd); if (mac_addr) memcpy(&nd->mac_addr, mac_addr, sizeof(nd->mac_addr)); else zero(nd->mac_addr); return 0; } int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int priority) { int r; assert_return(nd, -EINVAL); assert_return(!nd->event, -EBUSY); if (event) nd->event = sd_event_ref(event); else { r = sd_event_default(&nd->event); if (r < 0) return 0; } nd->event_priority = priority; return 0; } int sd_ndisc_detach_event(sd_ndisc *nd) { assert_return(nd, -EINVAL); nd->event = sd_event_unref(nd->event); return 0; } sd_event *sd_ndisc_get_event(sd_ndisc *nd) { assert(nd); return nd->event; } sd_ndisc *sd_ndisc_ref(sd_ndisc *nd) { if (!nd) return NULL; assert(nd->n_ref > 0); nd->n_ref++; return nd; } static int ndisc_init(sd_ndisc *nd) { assert(nd); nd->recv = sd_event_source_unref(nd->recv); nd->fd = asynchronous_close(nd->fd); nd->timeout = sd_event_source_unref(nd->timeout); return 0; } sd_ndisc *sd_ndisc_unref(sd_ndisc *nd) { NDiscPrefix *prefix, *p; if (!nd) return NULL; assert(nd->n_ref > 0); nd->n_ref--; if (nd->n_ref > 0) return NULL; ndisc_init(nd); sd_ndisc_detach_event(nd); LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes) prefix = ndisc_prefix_unref(prefix); free(nd); return NULL; } int sd_ndisc_new(sd_ndisc **ret) { _cleanup_(sd_ndisc_unrefp) sd_ndisc *nd = NULL; assert(ret); nd = new0(sd_ndisc, 1); if (!nd) return -ENOMEM; nd->n_ref = 1; nd->index = -1; nd->fd = -1; LIST_HEAD_INIT(nd->prefixes); *ret = nd; nd = NULL; return 0; } int sd_ndisc_get_mtu(sd_ndisc *nd, uint32_t *mtu) { assert_return(nd, -EINVAL); assert_return(mtu, -EINVAL); if (nd->mtu == 0) return -ENOMSG; *mtu = nd->mtu; return 0; } static int prefix_match(const struct in6_addr *prefix, uint8_t prefixlen, const struct in6_addr *addr, uint8_t addr_prefixlen) { uint8_t bytes, mask, len; assert_return(prefix, -EINVAL); assert_return(addr, -EINVAL); len = MIN(prefixlen, addr_prefixlen); bytes = len / 8; mask = 0xff << (8 - len % 8); if (memcmp(prefix, addr, bytes) != 0 || (prefix->s6_addr[bytes] & mask) != (addr->s6_addr[bytes] & mask)) return -EADDRNOTAVAIL; return 0; } static int ndisc_prefix_match(sd_ndisc *nd, const struct in6_addr *addr, uint8_t addr_len, NDiscPrefix **result) { NDiscPrefix *prefix, *p; usec_t time_now; int r; assert(nd); r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now); if (r < 0) return r; LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes) { if (prefix->valid_until < time_now) { prefix = ndisc_prefix_unref(prefix); continue; } if (prefix_match(&prefix->addr, prefix->len, addr, addr_len) >= 0) { *result = prefix; return 0; } } return -EADDRNOTAVAIL; } static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len, const struct nd_opt_prefix_info *prefix_opt) { NDiscPrefix *prefix; uint32_t lifetime_valid, lifetime_preferred; usec_t time_now; char time_string[FORMAT_TIMESPAN_MAX]; int r; assert(nd); assert(prefix_opt); if (len < prefix_opt->nd_opt_pi_len) return -ENOMSG; if (!(prefix_opt->nd_opt_pi_flags_reserved & (ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO))) return 0; if (in_addr_is_link_local(AF_INET6, (const union in_addr_union *) &prefix_opt->nd_opt_pi_prefix) > 0) return 0; lifetime_valid = be32toh(prefix_opt->nd_opt_pi_valid_time); lifetime_preferred = be32toh(prefix_opt->nd_opt_pi_preferred_time); if (lifetime_valid < lifetime_preferred) return 0; r = ndisc_prefix_match(nd, &prefix_opt->nd_opt_pi_prefix, prefix_opt->nd_opt_pi_prefix_len, &prefix); if (r < 0) { if (r != -EADDRNOTAVAIL) return r; /* if router advertisment prefix valid timeout is zero, the timeout callback will be called immediately to clean up the prefix */ r = ndisc_prefix_new(nd, &prefix); if (r < 0) return r; prefix->len = prefix_opt->nd_opt_pi_prefix_len; memcpy(&prefix->addr, &prefix_opt->nd_opt_pi_prefix, sizeof(prefix->addr)); log_ndisc(nd, "New prefix "SD_NDISC_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s", SD_NDISC_ADDRESS_FORMAT_VAL(prefix->addr), prefix->len, lifetime_valid, format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_valid * USEC_PER_SEC, USEC_PER_SEC)); LIST_PREPEND(prefixes, nd->prefixes, prefix); } else { if (prefix->len != prefix_opt->nd_opt_pi_prefix_len) { uint8_t prefixlen; prefixlen = MIN(prefix->len, prefix_opt->nd_opt_pi_prefix_len); log_ndisc(nd, "Prefix length mismatch %d/%d using %d", prefix->len, prefix_opt->nd_opt_pi_prefix_len, prefixlen); prefix->len = prefixlen; } log_ndisc(nd, "Update prefix "SD_NDISC_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s", SD_NDISC_ADDRESS_FORMAT_VAL(prefix->addr), prefix->len, lifetime_valid, format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_valid * USEC_PER_SEC, USEC_PER_SEC)); } r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now); if (r < 0) return r; prefix->valid_until = time_now + lifetime_valid * USEC_PER_SEC; if ((prefix_opt->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) && nd->prefix_onlink_callback) nd->prefix_onlink_callback(nd, &prefix->addr, prefix->len, prefix->valid_until, nd->userdata); if ((prefix_opt->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) && nd->prefix_autonomous_callback) nd->prefix_autonomous_callback(nd, &prefix->addr, prefix->len, lifetime_preferred, lifetime_valid, nd->userdata); return 0; } static int ndisc_ra_parse(sd_ndisc *nd, struct nd_router_advert *ra, ssize_t len) { void *opt; struct nd_opt_hdr *opt_hdr; assert_return(nd, -EINVAL); assert_return(ra, -EINVAL); len -= sizeof(*ra); if (len < NDISC_OPT_LEN_UNITS) { log_ndisc(nd, "Router Advertisement below minimum length"); return -ENOMSG; } opt = ra + 1; opt_hdr = opt; while (len != 0 && len >= opt_hdr->nd_opt_len * NDISC_OPT_LEN_UNITS) { struct nd_opt_mtu *opt_mtu; uint32_t mtu; struct nd_opt_prefix_info *opt_prefix; if (opt_hdr->nd_opt_len == 0) return -ENOMSG; switch (opt_hdr->nd_opt_type) { case ND_OPT_MTU: opt_mtu = opt; mtu = be32toh(opt_mtu->nd_opt_mtu_mtu); if (mtu != nd->mtu) { nd->mtu = MAX(mtu, IP6_MIN_MTU); log_ndisc(nd, "Router Advertisement link MTU %d using %d", mtu, nd->mtu); } break; case ND_OPT_PREFIX_INFORMATION: opt_prefix = opt; ndisc_prefix_update(nd, len, opt_prefix); break; } len -= opt_hdr->nd_opt_len * NDISC_OPT_LEN_UNITS; opt = (void *)((char *)opt + opt_hdr->nd_opt_len * NDISC_OPT_LEN_UNITS); opt_hdr = opt; } if (len > 0) log_ndisc(nd, "Router Advertisement contains %zd bytes of trailing garbage", len); return 0; } static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_free_ struct nd_router_advert *ra = NULL; sd_ndisc *nd = userdata; union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_LEN(sizeof(int))]; } control = {}; struct iovec iov = {}; union sockaddr_union sa = {}; struct msghdr msg = { .msg_name = &sa.sa, .msg_namelen = sizeof(sa), .msg_iov = &iov, .msg_iovlen = 1, .msg_control = &control, .msg_controllen = sizeof(control), }; struct cmsghdr *cmsg; struct in6_addr *gw; unsigned lifetime; ssize_t len; int r, pref, stateful, buflen = 0; assert(s); assert(nd); assert(nd->event); r = ioctl(fd, FIONREAD, &buflen); if (r < 0) return -errno; else if (buflen < 0) /* This really should not happen */ return -EIO; iov.iov_len = buflen; ra = malloc(iov.iov_len); if (!ra) return -ENOMEM; iov.iov_base = ra; len = recvmsg(fd, &msg, 0); if (len < 0) { if (errno == EAGAIN || errno == EINTR) return 0; log_ndisc(nd, "Could not receive message from ICMPv6 socket: %m"); return -errno; } else if ((size_t)len < sizeof(struct nd_router_advert)) { return 0; } else if (msg.msg_namelen == 0) gw = NULL; /* only happens when running the test-suite over a socketpair */ else if (msg.msg_namelen != sizeof(sa.in6)) { log_ndisc(nd, "Received invalid source address size from ICMPv6 socket: %zu bytes", (size_t)msg.msg_namelen); return 0; } else gw = &sa.in6.sin6_addr; assert(!(msg.msg_flags & MSG_CTRUNC)); assert(!(msg.msg_flags & MSG_TRUNC)); CMSG_FOREACH(cmsg, &msg) { if (cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { int hops = *(int*)CMSG_DATA(cmsg); if (hops != 255) { log_ndisc(nd, "Received RA with invalid hop limit %d. Ignoring.", hops); return 0; } break; } } if (gw && !in_addr_is_link_local(AF_INET6, (const union in_addr_union*) gw)) { _cleanup_free_ char *addr = NULL; (void)in_addr_to_string(AF_INET6, (const union in_addr_union*) gw, &addr); log_ndisc(nd, "Received RA from non-link-local address %s. Ignoring.", strna(addr)); return 0; } if (ra->nd_ra_type != ND_ROUTER_ADVERT) return 0; if (ra->nd_ra_code != 0) return 0; nd->timeout = sd_event_source_unref(nd->timeout); nd->state = NDISC_STATE_ADVERTISMENT_LISTEN; stateful = ra->nd_ra_flags_reserved & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER); pref = (ra->nd_ra_flags_reserved & ND_RA_FLAG_PREF) >> 3; switch (pref) { case ND_RA_FLAG_PREF_LOW: case ND_RA_FLAG_PREF_HIGH: break; default: pref = ND_RA_FLAG_PREF_MEDIUM; break; } lifetime = be16toh(ra->nd_ra_router_lifetime); log_ndisc(nd, "Received Router Advertisement: flags %s preference %s lifetime %u sec", stateful & ND_RA_FLAG_MANAGED ? "MANAGED" : stateful & ND_RA_FLAG_OTHER ? "OTHER" : "none", pref == ND_RA_FLAG_PREF_HIGH ? "high" : pref == ND_RA_FLAG_PREF_LOW ? "low" : "medium", lifetime); r = ndisc_ra_parse(nd, ra, len); if (r < 0) { log_ndisc(nd, "Could not parse Router Advertisement: %s", strerror(-r)); return 0; } if (nd->router_callback) nd->router_callback(nd, stateful, gw, lifetime, pref, nd->userdata); return 0; } static int ndisc_router_solicitation_timeout(sd_event_source *s, uint64_t usec, void *userdata) { sd_ndisc *nd = userdata; uint64_t time_now, next_timeout; int r; assert(s); assert(nd); assert(nd->event); nd->timeout = sd_event_source_unref(nd->timeout); if (nd->nd_sent >= NDISC_MAX_ROUTER_SOLICITATIONS) { if (nd->callback) nd->callback(nd, SD_NDISC_EVENT_TIMEOUT, nd->userdata); nd->state = NDISC_STATE_ADVERTISMENT_LISTEN; } else { r = icmp6_send_router_solicitation(nd->fd, &nd->mac_addr); if (r < 0) log_ndisc(nd, "Error sending Router Solicitation"); else { nd->state = NDISC_STATE_SOLICITATION_SENT; log_ndisc(nd, "Sent Router Solicitation"); } nd->nd_sent++; assert_se(sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now) >= 0); next_timeout = time_now + NDISC_ROUTER_SOLICITATION_INTERVAL; r = sd_event_add_time(nd->event, &nd->timeout, clock_boottime_or_monotonic(), next_timeout, 0, ndisc_router_solicitation_timeout, nd); if (r < 0) { /* we cannot continue if we are unable to rearm the timer */ sd_ndisc_stop(nd); return 0; } r = sd_event_source_set_priority(nd->timeout, nd->event_priority); if (r < 0) return 0; r = sd_event_source_set_description(nd->timeout, "ndisc-timeout"); if (r < 0) return 0; } return 0; } int sd_ndisc_stop(sd_ndisc *nd) { assert_return(nd, -EINVAL); assert_return(nd->event, -EINVAL); log_ndisc(client, "Stop NDisc"); ndisc_init(nd); nd->state = NDISC_STATE_IDLE; if (nd->callback) nd->callback(nd, SD_NDISC_EVENT_STOP, nd->userdata); return 0; } int sd_ndisc_router_discovery_start(sd_ndisc *nd) { int r; assert(nd); assert(nd->event); if (nd->state != NDISC_STATE_IDLE) return -EBUSY; if (nd->index < 1) return -EINVAL; r = icmp6_bind_router_solicitation(nd->index); if (r < 0) return r; nd->fd = r; r = sd_event_add_io(nd->event, &nd->recv, nd->fd, EPOLLIN, ndisc_router_advertisment_recv, nd); if (r < 0) goto error; r = sd_event_source_set_priority(nd->recv, nd->event_priority); if (r < 0) goto error; r = sd_event_source_set_description(nd->recv, "ndisc-receive-message"); if (r < 0) goto error; r = sd_event_add_time(nd->event, &nd->timeout, clock_boottime_or_monotonic(), 0, 0, ndisc_router_solicitation_timeout, nd); if (r < 0) goto error; r = sd_event_source_set_priority(nd->timeout, nd->event_priority); if (r < 0) goto error; r = sd_event_source_set_description(nd->timeout, "ndisc-timeout"); error: if (r < 0) ndisc_init(nd); else log_ndisc(client, "Start Router Solicitation"); return r; } systemd-229/src/libsystemd-network/test-acd.c000066400000000000000000000070741265713322000213760ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-event.h" #include "sd-ipv4acd.h" #include "sd-netlink.h" #include "in-addr-util.h" #include "netlink-util.h" #include "util.h" static void acd_handler(sd_ipv4acd *acd, int event, void *userdata) { assert_se(acd); switch (event) { case SD_IPV4ACD_EVENT_BIND: log_info("bound"); break; case SD_IPV4ACD_EVENT_CONFLICT: log_info("conflict"); break; case SD_IPV4ACD_EVENT_STOP: log_error("the client was stopped"); break; default: assert_not_reached("invalid ACD event"); } } static int client_run(int ifindex, const struct in_addr *pa, const struct ether_addr *ha, sd_event *e) { sd_ipv4acd *acd; assert_se(sd_ipv4acd_new(&acd) >= 0); assert_se(sd_ipv4acd_attach_event(acd, e, 0) >= 0); assert_se(sd_ipv4acd_set_index(acd, ifindex) >= 0); assert_se(sd_ipv4acd_set_mac(acd, ha) >= 0); assert_se(sd_ipv4acd_set_address(acd, pa) >= 0); assert_se(sd_ipv4acd_set_callback(acd, acd_handler, NULL) >= 0); log_info("starting IPv4ACD client"); assert_se(sd_ipv4acd_start(acd) >= 0); assert_se(sd_event_loop(e) >= 0); assert_se(!sd_ipv4acd_unref(acd)); return EXIT_SUCCESS; } static int test_acd(const char *ifname, const char *address) { _cleanup_(sd_event_unrefp) sd_event *e = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL; union in_addr_union pa; struct ether_addr ha; int ifindex; assert_se(in_addr_from_string(AF_INET, address, &pa) >= 0); assert_se(sd_event_new(&e) >= 0); assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(sd_netlink_attach_event(rtnl, e, 0) >= 0); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, 0) >= 0); assert_se(sd_netlink_message_append_string(m, IFLA_IFNAME, ifname) >= 0); assert_se(sd_netlink_call(rtnl, m, 0, &reply) >= 0); assert_se(sd_rtnl_message_link_get_ifindex(reply, &ifindex) >= 0); assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &ha) >= 0); client_run(ifindex, &pa.in, &ha, e); return EXIT_SUCCESS; } int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); log_parse_environment(); log_open(); if (argc == 3) return test_acd(argv[1], argv[2]); else { log_error("This program takes two arguments.\n" "\t %s ", program_invocation_short_name); return EXIT_FAILURE; } } systemd-229/src/libsystemd-network/test-dhcp-client.c000066400000000000000000000441141265713322000230350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-dhcp-client.h" #include "sd-event.h" #include "alloc-util.h" #include "dhcp-identifier.h" #include "dhcp-internal.h" #include "dhcp-protocol.h" #include "fd-util.h" #include "util.h" static uint8_t mac_addr[] = {'A', 'B', 'C', '1', '2', '3'}; typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp); static bool verbose = true; static int test_fd[2]; static test_callback_recv_t callback_recv; static be32_t xid; static sd_event_source *test_hangcheck; static int test_dhcp_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) { assert_not_reached("Test case should have completed in 2 seconds"); return 0; } static void test_request_basic(sd_event *e) { int r; sd_dhcp_client *client; if (verbose) printf("* %s\n", __FUNCTION__); r = sd_dhcp_client_new(&client); assert_se(r >= 0); assert_se(client); r = sd_dhcp_client_attach_event(client, e, 0); assert_se(r >= 0); assert_se(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL); assert_se(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL); assert_se(sd_dhcp_client_set_index(NULL, 0) == -EINVAL); assert_se(sd_dhcp_client_set_index(client, 15) == 0); assert_se(sd_dhcp_client_set_index(client, -42) == -EINVAL); assert_se(sd_dhcp_client_set_index(client, -1) == -EINVAL); assert_se(sd_dhcp_client_set_index(client, 0) == -EINVAL); assert_se(sd_dhcp_client_set_index(client, 1) == 0); assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_SUBNET_MASK) == -EEXIST); assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_ROUTER) == -EEXIST); assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_HOST_NAME) == -EEXIST); assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_DOMAIN_NAME) == -EEXIST); assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_DOMAIN_NAME_SERVER) == -EEXIST); assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PAD) == -EINVAL); assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_END) == -EINVAL); assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_MESSAGE_TYPE) == -EINVAL); assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_OVERLOAD) == -EINVAL); assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST) == -EINVAL); assert_se(sd_dhcp_client_set_request_option(client, 33) == 0); assert_se(sd_dhcp_client_set_request_option(client, 33) == -EEXIST); assert_se(sd_dhcp_client_set_request_option(client, 44) == 0); assert_se(sd_dhcp_client_set_request_option(client, 33) == -EEXIST); sd_dhcp_client_unref(client); } static void test_checksum(void) { uint8_t buf[20] = { 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff }; if (verbose) printf("* %s\n", __FUNCTION__); assert_se(dhcp_packet_checksum((uint8_t*)&buf, 20) == be16toh(0x78ae)); } static int check_options(uint8_t code, uint8_t len, const void *option, void *userdata) { switch(code) { case SD_DHCP_OPTION_CLIENT_IDENTIFIER: { uint32_t iaid; struct duid duid; size_t duid_len; assert_se(dhcp_identifier_set_duid_en(&duid, &duid_len) >= 0); assert_se(dhcp_identifier_set_iaid(42, mac_addr, ETH_ALEN, &iaid) >= 0); assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len); assert_se(len == 19); assert_se(((uint8_t*) option)[0] == 0xff); assert_se(memcmp((uint8_t*) option + 1, &iaid, sizeof(iaid)) == 0); assert_se(memcmp((uint8_t*) option + 5, &duid, duid_len) == 0); break; } default: break; } return 0; } int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len) { size_t size; _cleanup_free_ DHCPPacket *discover; uint16_t ip_check, udp_check; assert_se(s >= 0); assert_se(packet); size = sizeof(DHCPPacket); assert_se(len > size); discover = memdup(packet, len); assert_se(discover->ip.ttl == IPDEFTTL); assert_se(discover->ip.protocol == IPPROTO_UDP); assert_se(discover->ip.saddr == INADDR_ANY); assert_se(discover->ip.daddr == INADDR_BROADCAST); assert_se(discover->udp.source == be16toh(DHCP_PORT_CLIENT)); assert_se(discover->udp.dest == be16toh(DHCP_PORT_SERVER)); ip_check = discover->ip.check; discover->ip.ttl = 0; discover->ip.check = discover->udp.len; udp_check = ~dhcp_packet_checksum((uint8_t*)&discover->ip.ttl, len - 8); assert_se(udp_check == 0xffff); discover->ip.ttl = IPDEFTTL; discover->ip.check = ip_check; ip_check = ~dhcp_packet_checksum((uint8_t*)&discover->ip, sizeof(discover->ip)); assert_se(ip_check == 0xffff); assert_se(discover->dhcp.xid); assert_se(memcmp(discover->dhcp.chaddr, &mac_addr, ETH_ALEN) == 0); size = len - sizeof(struct iphdr) - sizeof(struct udphdr); assert_se(callback_recv); callback_recv(size, &discover->dhcp); return 575; } int dhcp_network_bind_raw_socket( int index, union sockaddr_union *link, uint32_t id, const uint8_t *addr, size_t addr_len, uint16_t arp_type) { if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0) return -errno; return test_fd[0]; } int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) { int fd; fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0); if (fd < 0) return -errno; return fd; } int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, const void *packet, size_t len) { return 0; } static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp) { int res; res = dhcp_option_parse(dhcp, size, check_options, NULL, NULL); assert_se(res == DHCP_DISCOVER); if (verbose) printf(" recv DHCP Discover 0x%08x\n", be32toh(dhcp->xid)); return 0; } static void test_discover_message(sd_event *e) { sd_dhcp_client *client; int res, r; if (verbose) printf("* %s\n", __FUNCTION__); r = sd_dhcp_client_new(&client); assert_se(r >= 0); assert_se(client); r = sd_dhcp_client_attach_event(client, e, 0); assert_se(r >= 0); assert_se(sd_dhcp_client_set_index(client, 42) >= 0); assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0); assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0); callback_recv = test_discover_message_verify; res = sd_dhcp_client_start(client); assert_se(res == 0 || res == -EINPROGRESS); sd_event_run(e, (uint64_t) -1); sd_dhcp_client_stop(client); sd_dhcp_client_unref(client); test_fd[1] = safe_close(test_fd[1]); callback_recv = NULL; } static uint8_t test_addr_acq_offer[] = { 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01, 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x6f, 0x95, 0x2f, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf, 0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x02, 0x36, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00, 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f, 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static uint8_t test_addr_acq_ack[] = { 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01, 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf, 0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x05, 0x36, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00, 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f, 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static void test_addr_acq_acquired(sd_dhcp_client *client, int event, void *userdata) { sd_event *e = userdata; sd_dhcp_lease *lease; struct in_addr addr; assert_se(client); assert_se(event == SD_DHCP_CLIENT_EVENT_IP_ACQUIRE); assert_se(sd_dhcp_client_get_lease(client, &lease) >= 0); assert_se(lease); assert_se(sd_dhcp_lease_get_address(lease, &addr) >= 0); assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[44], sizeof(addr.s_addr)) == 0); assert_se(sd_dhcp_lease_get_netmask(lease, &addr) >= 0); assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[285], sizeof(addr.s_addr)) == 0); assert_se(sd_dhcp_lease_get_router(lease, &addr) >= 0); assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[308], sizeof(addr.s_addr)) == 0); if (verbose) printf(" DHCP address acquired\n"); sd_event_exit(e, 0); } static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) { uint16_t udp_check = 0; uint8_t *msg_bytes = (uint8_t *)request; int res; res = dhcp_option_parse(request, size, check_options, NULL, NULL); assert_se(res == DHCP_REQUEST); assert_se(xid == request->xid); assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END); if (verbose) printf(" recv DHCP Request 0x%08x\n", be32toh(xid)); memcpy(&test_addr_acq_ack[26], &udp_check, sizeof(udp_check)); memcpy(&test_addr_acq_ack[32], &xid, sizeof(xid)); memcpy(&test_addr_acq_ack[56], &mac_addr, ETHER_ADDR_LEN); callback_recv = NULL; res = write(test_fd[1], test_addr_acq_ack, sizeof(test_addr_acq_ack)); assert_se(res == sizeof(test_addr_acq_ack)); if (verbose) printf(" send DHCP Ack\n"); return 0; }; static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) { uint16_t udp_check = 0; uint8_t *msg_bytes = (uint8_t *)discover; int res; res = dhcp_option_parse(discover, size, check_options, NULL, NULL); assert_se(res == DHCP_DISCOVER); assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END); xid = discover->xid; if (verbose) printf(" recv DHCP Discover 0x%08x\n", be32toh(xid)); memcpy(&test_addr_acq_offer[26], &udp_check, sizeof(udp_check)); memcpy(&test_addr_acq_offer[32], &xid, sizeof(xid)); memcpy(&test_addr_acq_offer[56], &mac_addr, ETHER_ADDR_LEN); callback_recv = test_addr_acq_recv_request; res = write(test_fd[1], test_addr_acq_offer, sizeof(test_addr_acq_offer)); assert_se(res == sizeof(test_addr_acq_offer)); if (verbose) printf(" sent DHCP Offer\n"); return 0; } static void test_addr_acq(sd_event *e) { usec_t time_now = now(clock_boottime_or_monotonic()); sd_dhcp_client *client; int res, r; if (verbose) printf("* %s\n", __FUNCTION__); r = sd_dhcp_client_new(&client); assert_se(r >= 0); assert_se(client); r = sd_dhcp_client_attach_event(client, e, 0); assert_se(r >= 0); assert_se(sd_dhcp_client_set_index(client, 42) >= 0); assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0); assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e) >= 0); callback_recv = test_addr_acq_recv_discover; assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), time_now + 2 * USEC_PER_SEC, 0, test_dhcp_hangcheck, NULL) >= 0); res = sd_dhcp_client_start(client); assert_se(res == 0 || res == -EINPROGRESS); assert_se(sd_event_loop(e) >= 0); test_hangcheck = sd_event_source_unref(test_hangcheck); assert_se(sd_dhcp_client_set_callback(client, NULL, NULL) >= 0); assert_se(sd_dhcp_client_stop(client) >= 0); sd_dhcp_client_unref(client); test_fd[1] = safe_close(test_fd[1]); callback_recv = NULL; xid = 0; } int main(int argc, char *argv[]) { _cleanup_(sd_event_unrefp) sd_event *e; log_set_max_level(LOG_DEBUG); log_parse_environment(); log_open(); assert_se(sd_event_new(&e) >= 0); test_request_basic(e); test_checksum(); test_discover_message(e); test_addr_acq(e); #ifdef VALGRIND /* Make sure the async_close thread has finished. * valgrind would report some of the phread_* structures * as not cleaned up properly. */ sleep(1); #endif return 0; } systemd-229/src/libsystemd-network/test-dhcp-option.c000066400000000000000000000272301265713322000230670ustar00rootroot00000000000000#include #include #include #include #include "alloc-util.h" #include "dhcp-internal.h" #include "dhcp-protocol.h" #include "macro.h" #include "util.h" struct option_desc { uint8_t sname[64]; int snamelen; uint8_t file[128]; int filelen; uint8_t options[128]; int len; bool success; int filepos; int snamepos; int pos; }; static bool verbose = false; static struct option_desc option_tests[] = { { {}, 0, {}, 0, { 42, 5, 65, 66, 67, 68, 69 }, 7, false, }, { {}, 0, {}, 0, { 42, 5, 65, 66, 67, 68, 69, 0, 0, SD_DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 12, true, }, { {}, 0, {}, 0, { 8, 255, 70, 71, 72 }, 5, false, }, { {}, 0, {}, 0, { 0x35, 0x01, 0x05, 0x36, 0x04, 0x01, 0x00, 0xa8, 0xc0, 0x33, 0x04, 0x00, 0x01, 0x51, 0x80, 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, 0x03, 0x04, 0xc0, 0xa8, 0x00, 0x01, 0x06, 0x04, 0xc0, 0xa8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, 40, true, }, { {}, 0, {}, 0, { SD_DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_OFFER, 42, 3, 0, 0, 0 }, 8, true, }, { {}, 0, {}, 0, { 42, 2, 1, 2, 44 }, 5, false, }, { {}, 0, { 222, 3, 1, 2, 3, SD_DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_NAK }, 8, { SD_DHCP_OPTION_OVERLOAD, 1, DHCP_OVERLOAD_FILE }, 3, true, }, { { 1, 4, 1, 2, 3, 4, SD_DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 9, { 222, 3, 1, 2, 3 }, 5, { SD_DHCP_OPTION_OVERLOAD, 1, DHCP_OVERLOAD_FILE|DHCP_OVERLOAD_SNAME }, 3, true, }, }; static const char *dhcp_type(int type) { switch(type) { case DHCP_DISCOVER: return "DHCPDISCOVER"; case DHCP_OFFER: return "DHCPOFFER"; case DHCP_REQUEST: return "DHCPREQUEST"; case DHCP_DECLINE: return "DHCPDECLINE"; case DHCP_ACK: return "DHCPACK"; case DHCP_NAK: return "DHCPNAK"; case DHCP_RELEASE: return "DHCPRELEASE"; default: return "unknown"; } } static void test_invalid_buffer_length(void) { DHCPMessage message; assert_se(dhcp_option_parse(&message, 0, NULL, NULL, NULL) == -EINVAL); assert_se(dhcp_option_parse(&message, sizeof(DHCPMessage) - 1, NULL, NULL, NULL) == -EINVAL); } static void test_message_init(void) { _cleanup_free_ DHCPMessage *message = NULL; size_t optlen = 4, optoffset; size_t len = sizeof(DHCPMessage) + optlen; uint8_t *magic; message = malloc0(len); assert_se(dhcp_message_init(message, BOOTREQUEST, 0x12345678, DHCP_DISCOVER, ARPHRD_ETHER, optlen, &optoffset) >= 0); assert_se(message->xid == htobe32(0x12345678)); assert_se(message->op == BOOTREQUEST); magic = (uint8_t*)&message->magic; assert_se(magic[0] == 99); assert_se(magic[1] == 130); assert_se(magic[2] == 83); assert_se(magic[3] == 99); assert_se(dhcp_option_parse(message, len, NULL, NULL, NULL) >= 0); } static DHCPMessage *create_message(uint8_t *options, uint16_t optlen, uint8_t *file, uint8_t filelen, uint8_t *sname, uint8_t snamelen) { DHCPMessage *message; size_t len = sizeof(DHCPMessage) + optlen; message = malloc0(len); assert_se(message); if (options && optlen) memcpy(&message->options, options, optlen); if (file && filelen <= 128) memcpy(&message->file, file, filelen); if (sname && snamelen <= 64) memcpy(&message->sname, sname, snamelen); return message; } static void test_ignore_opts(uint8_t *descoption, int *descpos, int *desclen) { assert(*descpos >= 0); while (*descpos < *desclen) { switch(descoption[*descpos]) { case SD_DHCP_OPTION_PAD: *descpos += 1; break; case SD_DHCP_OPTION_MESSAGE_TYPE: case SD_DHCP_OPTION_OVERLOAD: *descpos += 3; break; default: return; } } } static int test_options_cb(uint8_t code, uint8_t len, const void *option, void *userdata) { struct option_desc *desc = userdata; uint8_t *descoption = NULL; int *desclen = NULL, *descpos = NULL; uint8_t optcode = 0; uint8_t optlen = 0; uint8_t i; assert_se((!desc && !code && !len) || desc); if (!desc) return -EINVAL; assert_se(code != SD_DHCP_OPTION_PAD); assert_se(code != SD_DHCP_OPTION_END); assert_se(code != SD_DHCP_OPTION_MESSAGE_TYPE); assert_se(code != SD_DHCP_OPTION_OVERLOAD); while (desc->pos >= 0 || desc->filepos >= 0 || desc->snamepos >= 0) { if (desc->pos >= 0) { descoption = &desc->options[0]; desclen = &desc->len; descpos = &desc->pos; } else if (desc->filepos >= 0) { descoption = &desc->file[0]; desclen = &desc->filelen; descpos = &desc->filepos; } else if (desc->snamepos >= 0) { descoption = &desc->sname[0]; desclen = &desc->snamelen; descpos = &desc->snamepos; } assert_se(descoption && desclen && descpos); if (*desclen) test_ignore_opts(descoption, descpos, desclen); if (*descpos < *desclen) break; if (*descpos == *desclen) *descpos = -1; } assert_se(descpos); assert_se(*descpos != -1); optcode = descoption[*descpos]; optlen = descoption[*descpos + 1]; if (verbose) printf("DHCP code %2d(%2d) len %2d(%2d) ", code, optcode, len, optlen); assert_se(code == optcode); assert_se(len == optlen); for (i = 0; i < len; i++) { if (verbose) printf("0x%02x(0x%02x) ", ((uint8_t*) option)[i], descoption[*descpos + 2 + i]); assert_se(((uint8_t*) option)[i] == descoption[*descpos + 2 + i]); } if (verbose) printf("\n"); *descpos += optlen + 2; test_ignore_opts(descoption, descpos, desclen); if (desc->pos != -1 && desc->pos == desc->len) desc->pos = -1; if (desc->filepos != -1 && desc->filepos == desc->filelen) desc->filepos = -1; if (desc->snamepos != -1 && desc->snamepos == desc->snamelen) desc->snamepos = -1; return 0; } static void test_options(struct option_desc *desc) { uint8_t *options = NULL; uint8_t *file = NULL; uint8_t *sname = NULL; int optlen = 0; int filelen = 0; int snamelen = 0; int buflen = 0; _cleanup_free_ DHCPMessage *message = NULL; int res; if (desc) { file = &desc->file[0]; filelen = desc->filelen; if (!filelen) desc->filepos = -1; sname = &desc->sname[0]; snamelen = desc->snamelen; if (!snamelen) desc->snamepos = -1; options = &desc->options[0]; optlen = desc->len; desc->pos = 0; } message = create_message(options, optlen, file, filelen, sname, snamelen); buflen = sizeof(DHCPMessage) + optlen; if (!desc) { assert_se((res = dhcp_option_parse(message, buflen, test_options_cb, NULL, NULL)) == -ENOMSG); } else if (desc->success) { assert_se((res = dhcp_option_parse(message, buflen, test_options_cb, desc, NULL)) >= 0); assert_se(desc->pos == -1 && desc->filepos == -1 && desc->snamepos == -1); } else assert_se((res = dhcp_option_parse(message, buflen, test_options_cb, desc, NULL)) < 0); if (verbose) printf("DHCP type %s\n", dhcp_type(res)); } static uint8_t options[64] = { 'A', 'B', 'C', 'D', 160, 2, 0x11, 0x12, 0, 31, 8, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0, 55, 3, 0x51, 0x52, 0x53, 17, 7, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 255 }; static void test_option_set(void) { _cleanup_free_ DHCPMessage *result = NULL; size_t offset = 0, len, pos; unsigned i; result = malloc0(sizeof(DHCPMessage) + 11); assert_se(result); result->options[0] = 'A'; result->options[1] = 'B'; result->options[2] = 'C'; result->options[3] = 'D'; assert_se(dhcp_option_append(result, 0, &offset, 0, SD_DHCP_OPTION_PAD, 0, NULL) == -ENOBUFS); assert_se(offset == 0); offset = 4; assert_se(dhcp_option_append(result, 5, &offset, 0, SD_DHCP_OPTION_PAD, 0, NULL) == -ENOBUFS); assert_se(offset == 4); assert_se(dhcp_option_append(result, 6, &offset, 0, SD_DHCP_OPTION_PAD, 0, NULL) >= 0); assert_se(offset == 5); offset = pos = 4; len = 11; while (pos < len && options[pos] != SD_DHCP_OPTION_END) { assert_se(dhcp_option_append(result, len, &offset, DHCP_OVERLOAD_SNAME, options[pos], options[pos + 1], &options[pos + 2]) >= 0); if (options[pos] == SD_DHCP_OPTION_PAD) pos++; else pos += 2 + options[pos + 1]; if (pos < len) assert_se(offset == pos); } for (i = 0; i < 9; i++) { if (verbose) printf("%2u: 0x%02x(0x%02x) (options)\n", i, result->options[i], options[i]); assert_se(result->options[i] == options[i]); } if (verbose) printf("%2d: 0x%02x(0x%02x) (options)\n", 9, result->options[9], SD_DHCP_OPTION_END); assert_se(result->options[9] == SD_DHCP_OPTION_END); if (verbose) printf("%2d: 0x%02x(0x%02x) (options)\n", 10, result->options[10], SD_DHCP_OPTION_PAD); assert_se(result->options[10] == SD_DHCP_OPTION_PAD); for (i = 0; i < pos - 8; i++) { if (verbose) printf("%2u: 0x%02x(0x%02x) (sname)\n", i, result->sname[i], options[i + 9]); assert_se(result->sname[i] == options[i + 9]); } if (verbose) printf ("\n"); } int main(int argc, char *argv[]) { unsigned i; test_invalid_buffer_length(); test_message_init(); test_options(NULL); for (i = 0; i < ELEMENTSOF(option_tests); i++) test_options(&option_tests[i]); test_option_set(); return 0; } systemd-229/src/libsystemd-network/test-dhcp-server.c000066400000000000000000000245101265713322000230630ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. Copyright (C) 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-dhcp-server.h" #include "sd-event.h" #include "dhcp-server-internal.h" static void test_pool(struct in_addr *address, unsigned size, int ret) { _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; assert_se(sd_dhcp_server_new(&server, 1) >= 0); assert_se(sd_dhcp_server_configure_pool(server, address, 8, 0, size) == ret); } static int test_basic(sd_event *event) { _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; struct in_addr address_lo = { .s_addr = htonl(INADDR_LOOPBACK), }; struct in_addr address_any = { .s_addr = htonl(INADDR_ANY), }; int r; /* attach to loopback interface */ assert_se(sd_dhcp_server_new(&server, 1) >= 0); assert_se(server); assert_se(sd_dhcp_server_attach_event(server, event, 0) >= 0); assert_se(sd_dhcp_server_attach_event(server, event, 0) == -EBUSY); assert_se(sd_dhcp_server_get_event(server) == event); assert_se(sd_dhcp_server_detach_event(server) >= 0); assert_se(!sd_dhcp_server_get_event(server)); assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0); assert_se(sd_dhcp_server_attach_event(server, NULL, 0) == -EBUSY); assert_se(sd_dhcp_server_ref(server) == server); assert_se(!sd_dhcp_server_unref(server)); assert_se(sd_dhcp_server_start(server) == -EUNATCH); assert_se(sd_dhcp_server_configure_pool(server, &address_any, 28, 0, 0) == -EINVAL); assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 38, 0, 0) == -ERANGE); assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0); assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) == -EBUSY); test_pool(&address_any, 1, -EINVAL); test_pool(&address_lo, 1, 0); r = sd_dhcp_server_start(server); if (r == -EPERM) return EXIT_TEST_SKIP; assert_se(r >= 0); assert_se(sd_dhcp_server_start(server) == -EBUSY); assert_se(sd_dhcp_server_stop(server) >= 0); assert_se(sd_dhcp_server_stop(server) >= 0); assert_se(sd_dhcp_server_start(server) >= 0); return 0; } static void test_message_handler(void) { _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; struct { DHCPMessage message; struct { uint8_t code; uint8_t length; uint8_t type; } _packed_ option_type; struct { uint8_t code; uint8_t length; be32_t address; } _packed_ option_requested_ip; struct { uint8_t code; uint8_t length; be32_t address; } _packed_ option_server_id; struct { uint8_t code; uint8_t length; uint8_t id[7]; } _packed_ option_client_id; uint8_t end; } _packed_ test = { .message.op = BOOTREQUEST, .message.htype = ARPHRD_ETHER, .message.hlen = ETHER_ADDR_LEN, .message.xid = htobe32(0x12345678), .message.chaddr = { 'A', 'B', 'C', 'D', 'E', 'F' }, .option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE, .option_type.length = 1, .option_type.type = DHCP_DISCOVER, .end = SD_DHCP_OPTION_END, }; struct in_addr address_lo = { .s_addr = htonl(INADDR_LOOPBACK), }; assert_se(sd_dhcp_server_new(&server, 1) >= 0); assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0); assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0); assert_se(sd_dhcp_server_start(server) >= 0); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.end = 0; /* TODO, shouldn't this fail? */ assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.end = SD_DHCP_OPTION_END; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.option_type.code = 0; test.option_type.length = 0; test.option_type.type = 0; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE; test.option_type.length = 1; test.option_type.type = DHCP_DISCOVER; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.message.op = 0; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.message.op = BOOTREQUEST; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.message.htype = 0; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.message.htype = ARPHRD_ETHER; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.message.hlen = 0; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.message.hlen = ETHER_ADDR_LEN; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); test.option_type.type = DHCP_REQUEST; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.option_requested_ip.code = SD_DHCP_OPTION_REQUESTED_IP_ADDRESS; test.option_requested_ip.length = 4; test.option_requested_ip.address = htobe32(0x12345678); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_NAK); test.option_server_id.code = SD_DHCP_OPTION_SERVER_IDENTIFIER; test.option_server_id.length = 4; test.option_server_id.address = htobe32(INADDR_LOOPBACK); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); test.option_server_id.address = htobe32(0x12345678); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.option_server_id.address = htobe32(INADDR_LOOPBACK); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 4); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); test.option_client_id.code = SD_DHCP_OPTION_CLIENT_IDENTIFIER; test.option_client_id.length = 7; test.option_client_id.id[0] = 0x01; test.option_client_id.id[1] = 'A'; test.option_client_id.id[2] = 'B'; test.option_client_id.id[3] = 'C'; test.option_client_id.id[4] = 'D'; test.option_client_id.id[5] = 'E'; test.option_client_id.id[6] = 'F'; assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); } static uint64_t client_id_hash_helper(DHCPClientId *id, uint8_t key[HASH_KEY_SIZE]) { struct siphash state; siphash24_init(&state, key); client_id_hash_func(id, &state); return htole64(siphash24_finalize(&state)); } static void test_client_id_hash(void) { DHCPClientId a = { .length = 4, }, b = { .length = 4, }; uint8_t hash_key[HASH_KEY_SIZE] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', }; a.data = (uint8_t*)strdup("abcd"); b.data = (uint8_t*)strdup("abcd"); assert_se(client_id_compare_func(&a, &b) == 0); assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key)); a.length = 3; assert_se(client_id_compare_func(&a, &b) != 0); a.length = 4; assert_se(client_id_compare_func(&a, &b) == 0); assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key)); b.length = 3; assert_se(client_id_compare_func(&a, &b) != 0); b.length = 4; assert_se(client_id_compare_func(&a, &b) == 0); assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key)); free(b.data); b.data = (uint8_t*)strdup("abce"); assert_se(client_id_compare_func(&a, &b) != 0); free(a.data); free(b.data); } int main(int argc, char *argv[]) { _cleanup_(sd_event_unrefp) sd_event *e; int r; log_set_max_level(LOG_DEBUG); log_parse_environment(); log_open(); assert_se(sd_event_new(&e) >= 0); r = test_basic(e); if (r != 0) return r; test_message_handler(); test_client_id_hash(); return 0; } systemd-229/src/libsystemd-network/test-dhcp6-client.c000066400000000000000000000662051265713322000231300ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "sd-dhcp6-client.h" #include "sd-event.h" #include "dhcp6-internal.h" #include "dhcp6-lease-internal.h" #include "dhcp6-protocol.h" #include "fd-util.h" #include "macro.h" #include "socket-util.h" #include "virt.h" static struct ether_addr mac_addr = { .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'} }; static bool verbose = true; static sd_event_source *hangcheck; static int test_dhcp_fd[2]; static int test_index = 42; static int test_client_message_num; static be32_t test_iaid = 0; static uint8_t test_duid[14] = { }; static int test_client_basic(sd_event *e) { sd_dhcp6_client *client; if (verbose) printf("* %s\n", __FUNCTION__); assert_se(sd_dhcp6_client_new(&client) >= 0); assert_se(client); assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0); assert_se(sd_dhcp6_client_set_index(client, 15) == 0); assert_se(sd_dhcp6_client_set_index(client, -42) == -EINVAL); assert_se(sd_dhcp6_client_set_index(client, -1) == 0); assert_se(sd_dhcp6_client_set_index(client, 42) >= 0); assert_se(sd_dhcp6_client_set_mac(client, (const uint8_t *) &mac_addr, sizeof (mac_addr), ARPHRD_ETHER) >= 0); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_CLIENTID) == -EINVAL); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EEXIST); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) == -EEXIST); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVERS) == -EEXIST); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN_LIST) == -EEXIST); assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL); assert_se(sd_dhcp6_client_set_callback(client, NULL, NULL) >= 0); assert_se(sd_dhcp6_client_detach_event(client) >= 0); assert_se(!sd_dhcp6_client_unref(client)); return 0; } static int test_option(sd_event *e) { uint8_t packet[] = { 'F', 'O', 'O', 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x07, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 0x00, SD_DHCP6_OPTION_VENDOR_CLASS, 0x00, 0x09, '1', '2', '3', '4', '5', '6', '7', '8', '9', 'B', 'A', 'R', }; uint8_t result[] = { 'F', 'O', 'O', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'B', 'A', 'R', }; uint16_t optcode; size_t optlen; uint8_t *optval, *buf, *out; size_t zero = 0, pos = 3; size_t buflen = sizeof(packet), outlen = sizeof(result); if (verbose) printf("* %s\n", __FUNCTION__); assert_se(buflen == outlen); assert_se(dhcp6_option_parse(&buf, &zero, &optcode, &optlen, &optval) == -ENOMSG); buflen -= 3; buf = &packet[3]; outlen -= 3; out = &result[3]; assert_se(dhcp6_option_parse(&buf, &buflen, &optcode, &optlen, &optval) >= 0); pos += 4 + optlen; assert_se(buf == &packet[pos]); assert_se(optcode == SD_DHCP6_OPTION_ORO); assert_se(optlen == 7); assert_se(buflen + pos == sizeof(packet)); assert_se(dhcp6_option_append(&out, &outlen, optcode, optlen, optval) >= 0); assert_se(out == &result[pos]); assert_se(*out == 0x00); assert_se(dhcp6_option_parse(&buf, &buflen, &optcode, &optlen, &optval) >= 0); pos += 4 + optlen; assert_se(buf == &packet[pos]); assert_se(optcode == SD_DHCP6_OPTION_VENDOR_CLASS); assert_se(optlen == 9); assert_se(buflen + pos == sizeof(packet)); assert_se(dhcp6_option_append(&out, &outlen, optcode, optlen, optval) >= 0); assert_se(out == &result[pos]); assert_se(*out == 'B'); assert_se(memcmp(packet, result, sizeof(packet)) == 0); return 0; } static uint8_t msg_advertise[198] = { 0x02, 0x0f, 0xb4, 0xe5, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x1a, 0x6b, 0xf3, 0x30, 0x3c, 0x97, 0x0e, 0xcf, 0xa3, 0x7d, 0x00, 0x03, 0x00, 0x5e, 0x0e, 0xcf, 0xa3, 0x7d, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x78, 0x00, 0x05, 0x00, 0x18, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c, 0x55, 0xad, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x0d, 0x00, 0x32, 0x00, 0x00, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x28, 0x65, 0x73, 0x29, 0x20, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x65, 0x64, 0x2e, 0x20, 0x47, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, 0x00, 0x17, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x0b, 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x00, 0x00, 0x1f, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x19, 0x40, 0x5c, 0x53, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53, 0x00, 0x07, 0x00, 0x01, 0x00 }; static uint8_t msg_reply[173] = { 0x07, 0xf7, 0x4e, 0x57, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x19, 0x40, 0x5c, 0x53, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x1a, 0x6b, 0xf3, 0x30, 0x3c, 0x97, 0x0e, 0xcf, 0xa3, 0x7d, 0x00, 0x03, 0x00, 0x4a, 0x0e, 0xcf, 0xa3, 0x7d, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x78, 0x00, 0x05, 0x00, 0x18, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c, 0x55, 0xad, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x0d, 0x00, 0x1e, 0x00, 0x00, 0x41, 0x6c, 0x6c, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x00, 0x17, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x0b, 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x00, 0x00, 0x1f, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; static int test_advertise_option(sd_event *e) { _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; DHCP6Message *advertise = (DHCP6Message *)msg_advertise; uint8_t *optval, *opt = msg_advertise + sizeof(DHCP6Message); uint16_t optcode; size_t optlen, len = sizeof(msg_advertise) - sizeof(DHCP6Message); be32_t val; uint8_t preference = 255; struct in6_addr addr; uint32_t lt_pref, lt_valid; int r; bool opt_clientid = false; struct in6_addr *addrs; char **domains; if (verbose) printf("* %s\n", __FUNCTION__); assert_se(dhcp6_lease_new(&lease) >= 0); assert_se(advertise->type == DHCP6_ADVERTISE); assert_se((be32toh(advertise->transaction_id) & 0x00ffffff) == 0x0fb4e5); while ((r = dhcp6_option_parse(&opt, &len, &optcode, &optlen, &optval)) >= 0) { switch(optcode) { case SD_DHCP6_OPTION_CLIENTID: assert_se(optlen == 14); opt_clientid = true; break; case SD_DHCP6_OPTION_IA_NA: assert_se(optlen == 94); assert_se(!memcmp(optval, &msg_advertise[26], optlen)); val = htobe32(0x0ecfa37d); assert_se(!memcmp(optval, &val, sizeof(val))); val = htobe32(80); assert_se(!memcmp(optval + 4, &val, sizeof(val))); val = htobe32(120); assert_se(!memcmp(optval + 8, &val, sizeof(val))); assert_se(dhcp6_option_parse_ia(&optval, &optlen, optcode, &lease->ia) >= 0); break; case SD_DHCP6_OPTION_SERVERID: assert_se(optlen == 14); assert_se(!memcmp(optval, &msg_advertise[179], optlen)); assert_se(dhcp6_lease_set_serverid(lease, optval, optlen) >= 0); break; case SD_DHCP6_OPTION_PREFERENCE: assert_se(optlen == 1); assert_se(!*optval); assert_se(dhcp6_lease_set_preference(lease, *optval) >= 0); break; case SD_DHCP6_OPTION_ELAPSED_TIME: assert_se(optlen == 2); break; case SD_DHCP6_OPTION_DNS_SERVERS: assert_se(optlen == 16); assert_se(dhcp6_lease_set_dns(lease, optval, optlen) >= 0); break; case SD_DHCP6_OPTION_DOMAIN_LIST: assert_se(optlen == 11); assert_se(dhcp6_lease_set_domains(lease, optval, optlen) >= 0); break; case SD_DHCP6_OPTION_SNTP_SERVERS: assert_se(optlen == 16); assert_se(dhcp6_lease_set_sntp(lease, optval, optlen) >= 0); break; default: break; } } assert_se(r == -ENOMSG); assert_se(opt_clientid); sd_dhcp6_lease_reset_address_iter(lease); assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, <_valid) >= 0); assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr))); assert_se(lt_pref == 150); assert_se(lt_valid == 180); assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, <_valid) == -ENOMSG); sd_dhcp6_lease_reset_address_iter(lease); assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, <_valid) >= 0); assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr))); assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, <_valid) == -ENOMSG); sd_dhcp6_lease_reset_address_iter(lease); assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, <_valid) >= 0); assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr))); assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, <_valid) == -ENOMSG); assert_se(dhcp6_lease_get_serverid(lease, &opt, &len) >= 0); assert_se(len == 14); assert_se(!memcmp(opt, &msg_advertise[179], len)); assert_se(dhcp6_lease_get_preference(lease, &preference) >= 0); assert_se(preference == 0); r = sd_dhcp6_lease_get_dns(lease, &addrs); assert_se(r == 1); assert_se(!memcmp(addrs, &msg_advertise[124], r * 16)); r = sd_dhcp6_lease_get_domains(lease, &domains); assert_se(r == 1); assert_se(!strcmp("lab.intra", domains[0])); assert_se(domains[1] == NULL); r = sd_dhcp6_lease_get_ntp_addrs(lease, &addrs); assert_se(r == 1); assert_se(!memcmp(addrs, &msg_advertise[159], r * 16)); return 0; } static int test_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) { assert_not_reached("Test case should have completed in 2 seconds"); return 0; } static void test_client_solicit_cb(sd_dhcp6_client *client, int event, void *userdata) { sd_event *e = userdata; sd_dhcp6_lease *lease; struct in6_addr *addrs; char **domains; assert_se(e); assert_se(event == SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE); assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0); assert_se(sd_dhcp6_lease_get_domains(lease, &domains) == 1); assert_se(!strcmp("lab.intra", domains[0])); assert_se(domains[1] == NULL); assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 1); assert_se(!memcmp(addrs, &msg_advertise[124], 16)); assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1); assert_se(!memcmp(addrs, &msg_advertise[159], 16)); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EBUSY); if (verbose) printf(" got DHCPv6 event %d\n", event); sd_event_exit(e, 0); } static int test_client_send_reply(DHCP6Message *request) { DHCP6Message reply; reply.transaction_id = request->transaction_id; reply.type = DHCP6_REPLY; memcpy(msg_reply, &reply.transaction_id, 4); memcpy(&msg_reply[26], test_duid, sizeof(test_duid)); memcpy(&msg_reply[44], &test_iaid, sizeof(test_iaid)); assert_se(write(test_dhcp_fd[1], msg_reply, sizeof(msg_reply)) == sizeof(msg_reply)); return 0; } static int test_client_verify_request(DHCP6Message *request, uint8_t *option, size_t len) { _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; uint8_t *optval; uint16_t optcode; size_t optlen; bool found_clientid = false, found_iana = false, found_serverid = false, found_elapsed_time = false; int r; struct in6_addr addr; be32_t val; uint32_t lt_pref, lt_valid; assert_se(request->type == DHCP6_REQUEST); assert_se(dhcp6_lease_new(&lease) >= 0); while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen, &optval)) >= 0) { switch(optcode) { case SD_DHCP6_OPTION_CLIENTID: assert_se(!found_clientid); found_clientid = true; assert_se(!memcmp(optval, &test_duid, sizeof(test_duid))); break; case SD_DHCP6_OPTION_IA_NA: assert_se(!found_iana); found_iana = true; assert_se(optlen == 40); assert_se(!memcmp(optval, &test_iaid, sizeof(test_iaid))); val = htobe32(80); assert_se(!memcmp(optval + 4, &val, sizeof(val))); val = htobe32(120); assert_se(!memcmp(optval + 8, &val, sizeof(val))); assert_se(!dhcp6_option_parse_ia(&optval, &optlen, optcode, &lease->ia)); break; case SD_DHCP6_OPTION_SERVERID: assert_se(!found_serverid); found_serverid = true; assert_se(optlen == 14); assert_se(!memcmp(&msg_advertise[179], optval, optlen)); break; case SD_DHCP6_OPTION_ELAPSED_TIME: assert_se(!found_elapsed_time); found_elapsed_time = true; assert_se(optlen == 2); break; } } assert_se(r == -ENOMSG); assert_se(found_clientid && found_iana && found_serverid && found_elapsed_time); sd_dhcp6_lease_reset_address_iter(lease); assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, <_valid) >= 0); assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr))); assert_se(lt_pref == 150); assert_se(lt_valid == 180); assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, <_valid) == -ENOMSG); return 0; } static int test_client_send_advertise(DHCP6Message *solicit) { DHCP6Message advertise; advertise.transaction_id = solicit->transaction_id; advertise.type = DHCP6_ADVERTISE; memcpy(msg_advertise, &advertise.transaction_id, 4); memcpy(&msg_advertise[8], test_duid, sizeof(test_duid)); memcpy(&msg_advertise[26], &test_iaid, sizeof(test_iaid)); assert_se(write(test_dhcp_fd[1], msg_advertise, sizeof(msg_advertise)) == sizeof(msg_advertise)); return 0; } static int test_client_verify_solicit(DHCP6Message *solicit, uint8_t *option, size_t len) { uint8_t *optval; uint16_t optcode; size_t optlen; bool found_clientid = false, found_iana = false, found_elapsed_time = false; int r; assert_se(solicit->type == DHCP6_SOLICIT); while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen, &optval)) >= 0) { switch(optcode) { case SD_DHCP6_OPTION_CLIENTID: assert_se(!found_clientid); found_clientid = true; assert_se(optlen == sizeof(test_duid)); memcpy(&test_duid, optval, sizeof(test_duid)); break; case SD_DHCP6_OPTION_IA_NA: assert_se(!found_iana); found_iana = true; assert_se(optlen == 12); memcpy(&test_iaid, optval, sizeof(test_iaid)); break; case SD_DHCP6_OPTION_ELAPSED_TIME: assert_se(!found_elapsed_time); found_elapsed_time = true; assert_se(optlen == 2); break; } } assert_se(r == -ENOMSG); assert_se(found_clientid && found_iana && found_elapsed_time); return 0; } static void test_client_information_cb(sd_dhcp6_client *client, int event, void *userdata) { sd_event *e = userdata; sd_dhcp6_lease *lease; struct in6_addr *addrs; struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; char **domains; assert_se(e); assert_se(event == SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST); assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0); assert_se(sd_dhcp6_lease_get_domains(lease, &domains) == 1); assert_se(!strcmp("lab.intra", domains[0])); assert_se(domains[1] == NULL); assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 1); assert_se(!memcmp(addrs, &msg_advertise[124], 16)); assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1); assert_se(!memcmp(addrs, &msg_advertise[159], 16)); if (verbose) printf(" got DHCPv6 event %d\n", event); assert_se(sd_dhcp6_client_set_information_request(client, false) == -EBUSY); assert_se(sd_dhcp6_client_set_callback(client, NULL, e) >= 0); assert_se(sd_dhcp6_client_stop(client) >= 0); assert_se(sd_dhcp6_client_set_information_request(client, false) >= 0); assert_se(sd_dhcp6_client_set_callback(client, test_client_solicit_cb, e) >= 0); assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0); assert_se(sd_dhcp6_client_start(client) >= 0); } static int test_client_verify_information_request(DHCP6Message *information_request, uint8_t *option, size_t len) { _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; uint8_t *optval; uint16_t optcode; size_t optlen; bool found_clientid = false, found_elapsed_time = false; int r; struct in6_addr addr; uint32_t lt_pref, lt_valid; assert_se(information_request->type == DHCP6_INFORMATION_REQUEST); assert_se(dhcp6_lease_new(&lease) >= 0); while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen, &optval)) >= 0) { switch(optcode) { case SD_DHCP6_OPTION_CLIENTID: assert_se(!found_clientid); found_clientid = true; assert_se(optlen == sizeof(test_duid)); memcpy(&test_duid, optval, sizeof(test_duid)); break; case SD_DHCP6_OPTION_IA_NA: assert_not_reached("IA TA option must not be present"); break; case SD_DHCP6_OPTION_SERVERID: assert_not_reached("Server ID option must not be present"); break; case SD_DHCP6_OPTION_ELAPSED_TIME: assert_se(!found_elapsed_time); found_elapsed_time = true; assert_se(optlen == 2); break; } } assert_se(r == -ENOMSG); assert_se(found_clientid && found_elapsed_time); sd_dhcp6_lease_reset_address_iter(lease); assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, <_valid) == -ENOMSG); return 0; } int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address, const void *packet, size_t len) { struct in6_addr mcast = IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT; DHCP6Message *message; uint8_t *option; assert_se(s == test_dhcp_fd[0]); assert_se(server_address); assert_se(packet); assert_se(len > sizeof(DHCP6Message) + 4); assert_se(IN6_ARE_ADDR_EQUAL(server_address, &mcast)); message = (DHCP6Message *)packet; option = (uint8_t *)(message + 1); len -= sizeof(DHCP6Message); assert_se(message->transaction_id & 0x00ffffff); if (test_client_message_num == 0) { test_client_verify_information_request(message, option, len); test_client_send_reply(message); test_client_message_num++; } else if (test_client_message_num == 1) { test_client_verify_solicit(message, option, len); test_client_send_advertise(message); test_client_message_num++; } else if (test_client_message_num == 2) { test_client_verify_request(message, option, len); test_client_send_reply(message); test_client_message_num++; } return len; } int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) { assert_se(index == test_index); if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_dhcp_fd) < 0) return -errno; return test_dhcp_fd[0]; } static int test_client_solicit(sd_event *e) { sd_dhcp6_client *client; usec_t time_now = now(clock_boottime_or_monotonic()); struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; int val = true; if (verbose) printf("* %s\n", __FUNCTION__); assert_se(sd_dhcp6_client_new(&client) >= 0); assert_se(client); assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0); assert_se(sd_dhcp6_client_set_index(client, test_index) == 0); assert_se(sd_dhcp6_client_set_mac(client, (const uint8_t *) &mac_addr, sizeof (mac_addr), ARPHRD_ETHER) >= 0); assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0); assert_se(val == false); assert_se(sd_dhcp6_client_set_information_request(client, true) >= 0); assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0); assert_se(val == true); assert_se(sd_dhcp6_client_set_callback(client, test_client_information_cb, e) >= 0); assert_se(sd_event_add_time(e, &hangcheck, clock_boottime_or_monotonic(), time_now + 2 * USEC_PER_SEC, 0, test_hangcheck, NULL) >= 0); assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0); assert_se(sd_dhcp6_client_start(client) >= 0); sd_event_loop(e); hangcheck = sd_event_source_unref(hangcheck); assert_se(!sd_dhcp6_client_unref(client)); test_dhcp_fd[1] = safe_close(test_dhcp_fd[1]); return 0; } int main(int argc, char *argv[]) { _cleanup_(sd_event_unrefp) sd_event *e; assert_se(sd_event_new(&e) >= 0); log_set_max_level(LOG_DEBUG); log_parse_environment(); log_open(); test_client_basic(e); test_option(e); test_advertise_option(e); test_client_solicit(e); return 0; } systemd-229/src/libsystemd-network/test-ipv4ll-manual.c000066400000000000000000000100111265713322000233150ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-event.h" #include "sd-ipv4ll.h" #include "sd-netlink.h" #include "alloc-util.h" #include "in-addr-util.h" #include "netlink-util.h" #include "parse-util.h" #include "string-util.h" #include "util.h" static void ll_handler(sd_ipv4ll *ll, int event, void *userdata) { _cleanup_free_ char *address = NULL; struct in_addr addr = {}; assert_se(ll); if (sd_ipv4ll_get_address(ll, &addr) >= 0) assert_se(in_addr_to_string(AF_INET, (const union in_addr_union*) &addr, &address) >= 0); switch (event) { case SD_IPV4LL_EVENT_BIND: log_info("bound %s", strna(address)); break; case SD_IPV4LL_EVENT_CONFLICT: log_info("conflict on %s", strna(address)); break; case SD_IPV4LL_EVENT_STOP: log_error("the client was stopped with address %s", strna(address)); break; default: assert_not_reached("invalid LL event"); } } static int client_run(int ifindex, const char *seed_str, const struct ether_addr *ha, sd_event *e) { sd_ipv4ll *ll; assert_se(sd_ipv4ll_new(&ll) >= 0); assert_se(sd_ipv4ll_attach_event(ll, e, 0) >= 0); assert_se(sd_ipv4ll_set_index(ll, ifindex) >= 0); assert_se(sd_ipv4ll_set_mac(ll, ha) >= 0); assert_se(sd_ipv4ll_set_callback(ll, ll_handler, NULL) >= 0); if (seed_str) { unsigned seed; assert_se(safe_atou(seed_str, &seed) >= 0); assert_se(sd_ipv4ll_set_address_seed(ll, seed) >= 0); } log_info("starting IPv4LL client"); assert_se(sd_ipv4ll_start(ll) >= 0); assert_se(sd_event_loop(e) >= 0); assert_se(!sd_ipv4ll_unref(ll)); return EXIT_SUCCESS; } static int test_ll(const char *ifname, const char *seed) { _cleanup_(sd_event_unrefp) sd_event *e = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL; struct ether_addr ha; int ifindex; assert_se(sd_event_new(&e) >= 0); assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(sd_netlink_attach_event(rtnl, e, 0) >= 0); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, 0) >= 0); assert_se(sd_netlink_message_append_string(m, IFLA_IFNAME, ifname) >= 0); assert_se(sd_netlink_call(rtnl, m, 0, &reply) >= 0); assert_se(sd_rtnl_message_link_get_ifindex(reply, &ifindex) >= 0); assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &ha) >= 0); client_run(ifindex, seed, &ha, e); return EXIT_SUCCESS; } int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); log_parse_environment(); log_open(); if (argc == 2) return test_ll(argv[1], NULL); else if (argc == 3) return test_ll(argv[1], argv[2]); else { log_error("This program takes one or two arguments.\n" "\t %s []", program_invocation_short_name); return EXIT_FAILURE; } } systemd-229/src/libsystemd-network/test-ipv4ll.c000066400000000000000000000157451265713322000220650ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Axis Communications AB. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "sd-ipv4ll.h" #include "arp-util.h" #include "fd-util.h" #include "socket-util.h" #include "util.h" static bool verbose = false; static bool extended = false; static int test_fd[2]; static int basic_request_handler_bind = 0; static int basic_request_handler_stop = 0; static void* basic_request_handler_userdata = (void*)0xCABCAB; static void basic_request_handler(sd_ipv4ll *ll, int event, void *userdata) { assert_se(userdata == basic_request_handler_userdata); switch(event) { case SD_IPV4LL_EVENT_STOP: basic_request_handler_stop = 1; break; case SD_IPV4LL_EVENT_BIND: basic_request_handler_bind = 1; break; default: assert_se(0); break; } } static int arp_network_send_raw_socket(int fd, int ifindex, const struct ether_arp *arp) { assert_se(arp); assert_se(ifindex > 0); assert_se(fd >= 0); if (send(fd, arp, sizeof(struct ether_arp), 0) < 0) return -errno; return 0; } int arp_send_probe(int fd, int ifindex, be32_t pa, const struct ether_addr *ha) { struct ether_arp ea = {}; assert(fd >= 0); assert(ifindex > 0); assert(pa != 0); assert(ha); return arp_network_send_raw_socket(fd, ifindex, &ea); } int arp_send_announcement(int fd, int ifindex, be32_t pa, const struct ether_addr *ha) { struct ether_arp ea = {}; assert(fd >= 0); assert(ifindex > 0); assert(pa != 0); assert(ha); return arp_network_send_raw_socket(fd, ifindex, &ea); } int arp_network_bind_raw_socket(int index, be32_t address, const struct ether_addr *eth_mac) { if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, test_fd) < 0) return -errno; return test_fd[0]; } static void test_public_api_setters(sd_event *e) { struct in_addr address = {}; unsigned seed = 0; sd_ipv4ll *ll; struct ether_addr mac_addr = { .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}}; if (verbose) printf("* %s\n", __FUNCTION__); assert_se(sd_ipv4ll_new(&ll) == 0); assert_se(ll); assert_se(sd_ipv4ll_attach_event(NULL, NULL, 0) == -EINVAL); assert_se(sd_ipv4ll_attach_event(ll, e, 0) == 0); assert_se(sd_ipv4ll_attach_event(ll, e, 0) == -EBUSY); assert_se(sd_ipv4ll_set_callback(NULL, NULL, NULL) == -EINVAL); assert_se(sd_ipv4ll_set_callback(ll, NULL, NULL) == 0); assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL); address.s_addr |= htobe32(169U << 24 | 254U << 16); assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL); address.s_addr |= htobe32(0x00FF); assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL); address.s_addr |= htobe32(0xF000); assert_se(sd_ipv4ll_set_address(ll, &address) == 0); address.s_addr |= htobe32(0x0F00); assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL); assert_se(sd_ipv4ll_set_address_seed(NULL, seed) == -EINVAL); assert_se(sd_ipv4ll_set_address_seed(ll, seed) == 0); assert_se(sd_ipv4ll_set_mac(NULL, NULL) == -EINVAL); assert_se(sd_ipv4ll_set_mac(ll, NULL) == -EINVAL); assert_se(sd_ipv4ll_set_mac(ll, &mac_addr) == 0); assert_se(sd_ipv4ll_set_index(NULL, -1) == -EINVAL); assert_se(sd_ipv4ll_set_index(ll, -1) == -EINVAL); assert_se(sd_ipv4ll_set_index(ll, -99) == -EINVAL); assert_se(sd_ipv4ll_set_index(ll, 1) == 0); assert_se(sd_ipv4ll_set_index(ll, 99) == 0); assert_se(sd_ipv4ll_ref(ll) == ll); assert_se(sd_ipv4ll_unref(ll) == NULL); /* Cleanup */ assert_se(sd_ipv4ll_unref(ll) == NULL); } static void test_basic_request(sd_event *e) { sd_ipv4ll *ll; struct ether_arp arp; struct ether_addr mac_addr = { .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}}; if (verbose) printf("* %s\n", __FUNCTION__); assert_se(sd_ipv4ll_new(&ll) == 0); assert_se(sd_ipv4ll_start(ll) == -EINVAL); assert_se(sd_ipv4ll_attach_event(ll, e, 0) == 0); assert_se(sd_ipv4ll_start(ll) == -EINVAL); assert_se(sd_ipv4ll_set_mac(ll, &mac_addr) == 0); assert_se(sd_ipv4ll_start(ll) == -EINVAL); assert_se(sd_ipv4ll_set_callback(ll, basic_request_handler, basic_request_handler_userdata) == 0); assert_se(sd_ipv4ll_start(ll) == -EINVAL); assert_se(sd_ipv4ll_set_index(ll, 1) == 0); assert_se(sd_ipv4ll_start(ll) == 0); sd_event_run(e, (uint64_t) -1); assert_se(sd_ipv4ll_start(ll) == -EBUSY); assert_se(sd_ipv4ll_is_running(ll)); /* PROBE */ sd_event_run(e, (uint64_t) -1); assert_se(read(test_fd[1], &arp, sizeof(struct ether_arp)) == sizeof(struct ether_arp)); if (extended) { /* PROBE */ sd_event_run(e, (uint64_t) -1); assert_se(read(test_fd[1], &arp, sizeof(struct ether_arp)) == sizeof(struct ether_arp)); /* PROBE */ sd_event_run(e, (uint64_t) -1); assert_se(read(test_fd[1], &arp, sizeof(struct ether_arp)) == sizeof(struct ether_arp)); sd_event_run(e, (uint64_t) -1); assert_se(basic_request_handler_bind == 1); } sd_ipv4ll_stop(ll); assert_se(basic_request_handler_stop == 1); /* Cleanup */ assert_se(sd_ipv4ll_unref(ll) == NULL); safe_close(test_fd[1]); } int main(int argc, char *argv[]) { _cleanup_(sd_event_unrefp) sd_event *e = NULL; log_set_max_level(LOG_DEBUG); log_parse_environment(); log_open(); assert_se(sd_event_new(&e) >= 0); test_public_api_setters(e); test_basic_request(e); return 0; } systemd-229/src/libsystemd-network/test-lldp.c000066400000000000000000000370221265713322000215760ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-event.h" #include "sd-lldp.h" #include "alloc-util.h" #include "fd-util.h" #include "lldp-network.h" #include "lldp-tlv.h" #include "lldp.h" #include "macro.h" #include "string-util.h" #define TEST_LLDP_PORT "em1" #define TEST_LLDP_TYPE_SYSTEM_NAME "systemd-lldp" #define TEST_LLDP_TYPE_SYSTEM_DESC "systemd-lldp-desc" static int test_fd[2]; static struct ether_addr mac_addr = { .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'} }; static int lldp_build_tlv_packet(tlv_packet **ret) { _cleanup_(sd_lldp_packet_unrefp) tlv_packet *m = NULL; const uint8_t lldp_dst[] = LLDP_MULTICAST_ADDR; struct ether_header ether = { .ether_type = htons(ETHERTYPE_LLDP), }; /* Append Ethernet header */ memcpy(ðer.ether_dhost, lldp_dst, ETHER_ADDR_LEN); memcpy(ðer.ether_shost, &mac_addr, ETHER_ADDR_LEN); assert_se(tlv_packet_new(&m) >= 0); assert_se(tlv_packet_append_bytes(m, ðer, sizeof(struct ether_header)) >= 0); assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_CHASSIS_ID) >= 0); assert_se(tlv_packet_append_u8(m, LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS) >= 0); assert_se(tlv_packet_append_bytes(m, &mac_addr, ETHER_ADDR_LEN) >= 0); assert_se(lldp_tlv_packet_close_container(m) >= 0); /* port name */ assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_PORT_ID) >= 0); assert_se(tlv_packet_append_u8(m, LLDP_PORT_SUBTYPE_INTERFACE_NAME) >= 0); assert_se(tlv_packet_append_bytes(m, TEST_LLDP_PORT, strlen(TEST_LLDP_PORT) + 1) >= 0); assert_se(lldp_tlv_packet_close_container(m) >= 0); /* ttl */ assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_TTL) >= 0); assert_se(tlv_packet_append_u16(m, 170) >= 0); assert_se(lldp_tlv_packet_close_container(m) >= 0); /* system name */ assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_SYSTEM_NAME) >= 0); assert_se(tlv_packet_append_bytes(m, TEST_LLDP_TYPE_SYSTEM_NAME, strlen(TEST_LLDP_TYPE_SYSTEM_NAME)) >= 0); assert_se(lldp_tlv_packet_close_container(m) >= 0); /* system descrition */ assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_SYSTEM_DESCRIPTION) >= 0); assert_se(tlv_packet_append_bytes(m, TEST_LLDP_TYPE_SYSTEM_DESC, strlen(TEST_LLDP_TYPE_SYSTEM_DESC)) >= 0); assert_se(lldp_tlv_packet_close_container(m) >= 0); /* Mark end of packet */ assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_END) >= 0); assert_se(lldp_tlv_packet_close_container(m) >= 0); *ret = m; m = NULL; return 0; } static int lldp_parse_chassis_tlv(tlv_packet *m, uint8_t *type) { uint8_t *p, subtype; uint16_t length; assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_CHASSIS_ID) >= 0); assert_se(tlv_packet_read_u8(m, &subtype) >= 0); switch (subtype) { case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: *type = LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS; assert_se(tlv_packet_read_bytes(m, &p, &length) >= 0); assert_se(memcmp(p, &mac_addr.ether_addr_octet, ETHER_ADDR_LEN) == 0); break; default: assert_not_reached("Unhandled option"); } assert_se(lldp_tlv_packet_exit_container(m) >= 0); return 0; } static int lldp_parse_port_id_tlv(tlv_packet *m) { _cleanup_free_ char *p = NULL; char *str = NULL; uint16_t length; uint8_t subtype; assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_PORT_ID) >= 0); assert_se(tlv_packet_read_u8(m, &subtype) >= 0); switch (subtype) { case LLDP_PORT_SUBTYPE_INTERFACE_NAME: assert_se(tlv_packet_read_string(m, &str, &length) >= 0); p = strndup(str, length-1); assert_se(p); assert_se(streq(p, TEST_LLDP_PORT) == 1); break; default: assert_not_reached("Unhandled option"); } assert_se(lldp_tlv_packet_exit_container(m) >= 0); return 0; } static int lldp_parse_system_name_tlv(tlv_packet *m) { _cleanup_free_ char *p = NULL; char *str = NULL; uint16_t length; assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_SYSTEM_NAME) >= 0); assert_se(tlv_packet_read_string(m, &str, &length) >= 0); p = strndup(str, length); assert_se(p); assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_NAME) == 1); assert_se(lldp_tlv_packet_exit_container(m) >= 0); return 1; } static int lldp_parse_system_desc_tlv(tlv_packet *m) { _cleanup_free_ char *p = NULL; char *str = NULL; uint16_t length; assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_SYSTEM_DESCRIPTION) >= 0); assert_se(tlv_packet_read_string(m, &str, &length) >= 0); p = strndup(str, length); assert_se(p); assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_DESC) == 1); assert_se(lldp_tlv_packet_exit_container(m) >= 0); return 0; } static int lldp_parse_ttl_tlv(tlv_packet *m) { uint16_t ttl; assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_TTL) >= 0); assert_se(tlv_packet_read_u16(m, &ttl) >= 0); assert_se(ttl == 170); assert_se(lldp_tlv_packet_exit_container(m) >= 0); return 0; } static int lldp_get_destination_type(tlv_packet *m) { int dest; assert_se(sd_lldp_packet_get_destination_type(m, &dest) >= 0); assert_se(dest == SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE); return 0; } static int lldp_parse_tlv_packet(tlv_packet *m, int len) { uint8_t subtype; assert_se(tlv_packet_parse_pdu(m, len) >= 0); assert_se(lldp_parse_chassis_tlv(m, &subtype) >= 0); assert_se(lldp_parse_port_id_tlv(m) >= 0); assert_se(lldp_parse_system_name_tlv(m) >= 0); assert_se(lldp_parse_ttl_tlv(m) >= 0); assert_se(lldp_parse_system_desc_tlv(m) >= 0); assert_se(lldp_get_destination_type(m) >= 0); return 0; } static void test_parser(void) { _cleanup_(sd_lldp_packet_unrefp) tlv_packet *tlv = NULL; /* form a packet */ lldp_build_tlv_packet(&tlv); /* parse the packet */ tlv_packet_parse_pdu(tlv, tlv->length); /* verify */ lldp_parse_tlv_packet(tlv, tlv->length); } int lldp_network_bind_raw_socket(int ifindex) { if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, test_fd) < 0) return -errno; return test_fd[0]; } static int lldp_handler_calls; static void lldp_handler (sd_lldp *lldp, int event, void *userdata) { lldp_handler_calls++; } static int start_lldp(sd_lldp **lldp, sd_event *e, sd_lldp_cb_t cb, void *cb_data) { int r; r = sd_lldp_new(42, "dummy", &mac_addr, lldp); if (r) return r; r = sd_lldp_attach_event(*lldp, e, 0); if (r) return r; r = sd_lldp_set_callback(*lldp, cb, cb_data); if (r) return r; r = sd_lldp_start(*lldp); if (r) return r; return 0; } static int stop_lldp(sd_lldp *lldp) { int r; r = sd_lldp_stop(lldp); if (r) return r; r = sd_lldp_detach_event(lldp); if (r) return r; sd_lldp_unref(lldp); safe_close(test_fd[1]); return 0; } static void test_receive_basic_packet(sd_event *e) { sd_lldp *lldp; sd_lldp_packet **packets; uint8_t type, *data; uint16_t length, ttl; int dest_type; char *str; uint8_t frame[] = { /* Ethernet header */ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC*/ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ 0x88, 0xcc, /* Ethertype */ /* LLDP mandatory TLVs */ 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ 0x03, 0x04, 0x05, 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds*/ /* LLDP optional TLVs */ 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */ 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */ 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */ 0x00, 0x00 /* End Of LLDPDU */ }; lldp_handler_calls = 0; assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0); assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame)); sd_event_run(e, 0); assert_se(lldp_handler_calls == 1); assert_se(sd_lldp_get_packets(lldp, &packets) == 1); assert_se(sd_lldp_packet_read_chassis_id(packets[0], &type, &data, &length) == 0); assert_se(type == LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS); assert_se(length == ETH_ALEN); assert_se(!memcmp(data, "\x00\x01\x02\x03\x04\x05", ETH_ALEN)); assert_se(sd_lldp_packet_read_port_id(packets[0], &type, &data, &length) == 0); assert_se(type == LLDP_PORT_SUBTYPE_INTERFACE_NAME); assert_se(length == 3); assert_se(strneq((char *) data, "1/3", 3)); assert_se(sd_lldp_packet_read_port_description(packets[0], &str, &length) == 0); assert_se(length == 4); assert_se(strneq(str, "Port", 4)); assert_se(sd_lldp_packet_read_system_name(packets[0], &str, &length) == 0); assert_se(length == 3); assert_se(strneq(str, "SYS", 3)); assert_se(sd_lldp_packet_read_system_description(packets[0], &str, &length) == 0); assert_se(length == 4); /* This is the real length in the TLV packet */ assert_se(strneq(str, "foo", 3)); assert_se(sd_lldp_packet_read_ttl(packets[0], &ttl) == 0); assert_se(ttl == 120); assert_se(sd_lldp_packet_get_destination_type(packets[0], &dest_type) == 0); assert_se(dest_type == SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE); sd_lldp_packet_unref(packets[0]); free(packets); assert_se(stop_lldp(lldp) == 0); } static void test_receive_incomplete_packet(sd_event *e) { sd_lldp *lldp; sd_lldp_packet **packets; uint8_t frame[] = { /* Ethernet header */ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC*/ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ 0x88, 0xcc, /* Ethertype */ /* LLDP mandatory TLVs */ 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ 0x03, 0x04, 0x05, 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ /* Missing TTL */ 0x00, 0x00 /* End Of LLDPDU */ }; lldp_handler_calls = 0; assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0); assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame)); sd_event_run(e, 0); assert_se(lldp_handler_calls == 0); assert_se(sd_lldp_get_packets(lldp, &packets) == 0); assert_se(stop_lldp(lldp) == 0); } static void test_receive_oui_packet(sd_event *e) { sd_lldp *lldp; sd_lldp_packet **packets; uint32_t id32; uint16_t id16, len; uint8_t flags; char *str; uint8_t frame[] = { /* Ethernet header */ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC*/ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ 0x88, 0xcc, /* Ethertype */ /* LLDP mandatory TLVs */ 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ 0x03, 0x04, 0x05, 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port TLV: interface name, "1/3" */ 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds*/ /* LLDP optional TLVs */ 0xfe, 0x06, 0x00, 0x80, 0xc2, 0x01, /* Port VLAN ID: 0x1234 */ 0x12, 0x34, 0xfe, 0x07, 0x00, 0x80, 0xc2, 0x02, /* Port and protocol: flag 1, PPVID 0x7788 */ 0x01, 0x77, 0x88, 0xfe, 0x0d, 0x00, 0x80, 0xc2, 0x03, /* VLAN Name: ID 0x1234, name "Vlan51" */ 0x12, 0x34, 0x06, 0x56, 0x6c, 0x61, 0x6e, 0x35, 0x31, 0xfe, 0x06, 0x00, 0x80, 0xc2, 0x06, /* Management VID: 0x0102 */ 0x01, 0x02, 0xfe, 0x09, 0x00, 0x80, 0xc2, 0x07, /* Link aggregation: status 1, ID 0x00140012 */ 0x01, 0x00, 0x14, 0x00, 0x12, 0x00, 0x00 /* End of LLDPDU */ }; lldp_handler_calls = 0; assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0); assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame)); sd_event_run(e, 0); assert_se(lldp_handler_calls == 1); assert_se(sd_lldp_get_packets(lldp, &packets) == 1); assert_se(sd_lldp_packet_read_port_vlan_id(packets[0], &id16) == 0); assert_se(id16 == 0x1234); assert_se(sd_lldp_packet_read_port_protocol_vlan_id(packets[0], &flags, &id16) == 0); assert_se(flags == 1); assert_se(id16 == 0x7788); assert_se(sd_lldp_packet_read_vlan_name(packets[0], &id16, &str, &len) == 0); assert_se(id16 == 0x1234); assert_se(len == 6); assert_se(strneq(str, "Vlan51", 6)); assert_se(sd_lldp_packet_read_management_vid(packets[0], &id16) == 0); assert_se(id16 == 0x0102); assert_se(sd_lldp_packet_read_link_aggregation(packets[0], &flags, &id32) == 0); assert_se(flags == 1); assert_se(id32 == 0x00140012); sd_lldp_packet_unref(packets[0]); free(packets); assert_se(stop_lldp(lldp) == 0); } int main(int argc, char *argv[]) { _cleanup_(sd_event_unrefp) sd_event *e = NULL; test_parser(); /* LLDP reception tests */ assert_se(sd_event_new(&e) == 0); test_receive_basic_packet(e); test_receive_incomplete_packet(e); test_receive_oui_packet(e); return 0; } systemd-229/src/libsystemd-network/test-ndisc-rs.c000066400000000000000000000115261265713322000223660ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-ndisc.h" #include "icmp6-util.h" #include "socket-util.h" static struct ether_addr mac_addr = { .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'} }; static bool verbose = false; static sd_event_source *test_hangcheck; static int test_fd[2]; typedef int (*send_ra_t)(uint8_t flags); static send_ra_t send_ra_function; static int test_rs_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) { assert_se(false); return 0; } int icmp6_bind_router_solicitation(int index) { assert_se(index == 42); if (socketpair(AF_UNIX, SOCK_DGRAM, 0, test_fd) < 0) return -errno; return test_fd[0]; } static int send_ra(uint8_t flags) { uint8_t advertisement[] = { 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53, }; advertisement[5] = flags; assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) == sizeof(advertisement)); if (verbose) printf(" sent RA with flag 0x%02x\n", flags); return 0; } int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) { return send_ra_function(0); } static void test_rs_done(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata) { sd_event *e = userdata; static unsigned idx = 0; uint8_t flags_array[] = { 0, 0, 0, ND_RA_FLAG_OTHER, ND_RA_FLAG_MANAGED }; uint32_t mtu; assert_se(nd); assert_se(flags == flags_array[idx]); idx++; if (verbose) printf(" got event 0x%02x\n", flags); if (idx < ELEMENTSOF(flags_array)) { send_ra(flags_array[idx]); return; } assert_se(sd_ndisc_get_mtu(nd, &mtu) == -ENOMSG); sd_event_exit(e, 0); } static void test_rs(void) { sd_event *e; sd_ndisc *nd; usec_t time_now = now(clock_boottime_or_monotonic()); if (verbose) printf("* %s\n", __FUNCTION__); send_ra_function = send_ra; assert_se(sd_event_new(&e) >= 0); assert_se(sd_ndisc_new(&nd) >= 0); assert_se(nd); assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0); assert_se(sd_ndisc_set_index(nd, 42) >= 0); assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); assert_se(sd_ndisc_set_callback(nd, test_rs_done, NULL, NULL, NULL, e) >= 0); assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), time_now + 2 *USEC_PER_SEC, 0, test_rs_hangcheck, NULL) >= 0); assert_se(sd_ndisc_stop(nd) >= 0); assert_se(sd_ndisc_router_discovery_start(nd) >= 0); assert_se(sd_ndisc_stop(nd) >= 0); assert_se(sd_ndisc_router_discovery_start(nd) >= 0); sd_event_loop(e); test_hangcheck = sd_event_source_unref(test_hangcheck); nd = sd_ndisc_unref(nd); assert_se(!nd); close(test_fd[1]); sd_event_unref(e); } int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); log_parse_environment(); log_open(); test_rs(); return 0; } systemd-229/src/libsystemd/000077500000000000000000000000001265713322000160275ustar00rootroot00000000000000systemd-229/src/libsystemd/.gitignore000066400000000000000000000000171265713322000200150ustar00rootroot00000000000000/libsystemd.pc systemd-229/src/libsystemd/Makefile000077700000000000000000000000001265713322000213352../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd/libsystemd.pc.in000066400000000000000000000010041265713322000211320ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: systemd Description: systemd Library URL: @PACKAGE_URL@ Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lsystemd Cflags: -I${includedir} systemd-229/src/libsystemd/libsystemd.sym000066400000000000000000000343261265713322000207500ustar00rootroot00000000000000/*** This file is part of systemd. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. ***/ LIBSYSTEMD_209 { global: /* sd-journal */ sd_journal_print; sd_journal_printv; sd_journal_send; sd_journal_sendv; sd_journal_stream_fd; sd_journal_open; sd_journal_close; sd_journal_previous; sd_journal_next; sd_journal_previous_skip; sd_journal_next_skip; sd_journal_get_realtime_usec; sd_journal_get_monotonic_usec; sd_journal_get_data; sd_journal_enumerate_data; sd_journal_restart_data; sd_journal_add_match; sd_journal_flush_matches; sd_journal_seek_head; sd_journal_seek_tail; sd_journal_seek_monotonic_usec; sd_journal_seek_realtime_usec; sd_journal_seek_cursor; sd_journal_get_cursor; sd_journal_get_fd; sd_journal_process; sd_journal_print_with_location; sd_journal_printv_with_location; sd_journal_send_with_location; sd_journal_sendv_with_location; sd_journal_get_cutoff_realtime_usec; sd_journal_get_cutoff_monotonic_usec; sd_journal_wait; sd_journal_open_directory; sd_journal_add_disjunction; sd_journal_perror; sd_journal_perror_with_location; sd_journal_get_usage; sd_journal_test_cursor; sd_journal_query_unique; sd_journal_enumerate_unique; sd_journal_restart_unique; sd_journal_get_catalog; sd_journal_get_catalog_for_message_id; sd_journal_set_data_threshold; sd_journal_get_data_threshold; sd_journal_reliable_fd; sd_journal_get_events; sd_journal_get_timeout; sd_journal_add_conjunction; sd_journal_open_files; sd_journal_open_container; /* sd-daemon */ sd_booted; sd_is_fifo; sd_is_mq; sd_is_socket; sd_is_socket_inet; sd_is_socket_unix; sd_is_special; sd_listen_fds; sd_notify; sd_notifyf; sd_watchdog_enabled; /* sd-id128 */ sd_id128_to_string; sd_id128_from_string; sd_id128_randomize; sd_id128_get_machine; sd_id128_get_boot; /* sd-login */ sd_get_seats; sd_get_sessions; sd_get_uids; sd_login_monitor_flush; sd_login_monitor_get_fd; sd_login_monitor_new; sd_login_monitor_unref; sd_pid_get_owner_uid; sd_pid_get_session; sd_seat_can_multi_session; sd_seat_get_active; sd_seat_get_sessions; sd_session_get_seat; sd_session_get_uid; sd_session_is_active; sd_uid_get_seats; sd_uid_get_sessions; sd_uid_get_state; sd_uid_is_on_seat; sd_pid_get_unit; sd_session_get_service; sd_session_get_type; sd_session_get_class; sd_session_get_display; sd_session_get_state; sd_seat_can_tty; sd_seat_can_graphical; sd_session_get_tty; sd_login_monitor_get_events; sd_login_monitor_get_timeout; sd_pid_get_user_unit; sd_pid_get_machine_name; sd_get_machine_names; sd_pid_get_slice; sd_session_get_vt; sd_session_is_remote; sd_session_get_remote_user; sd_session_get_remote_host; local: *; }; LIBSYSTEMD_211 { global: sd_machine_get_class; sd_peer_get_session; sd_peer_get_owner_uid; sd_peer_get_unit; sd_peer_get_user_unit; sd_peer_get_machine_name; sd_peer_get_slice; } LIBSYSTEMD_209; LIBSYSTEMD_213 { global: sd_uid_get_display; } LIBSYSTEMD_211; LIBSYSTEMD_214 { global: sd_pid_notify; sd_pid_notifyf; } LIBSYSTEMD_213; LIBSYSTEMD_216 { global: sd_machine_get_ifindices; } LIBSYSTEMD_214; LIBSYSTEMD_217 { global: sd_session_get_desktop; } LIBSYSTEMD_216; LIBSYSTEMD_219 { global: sd_pid_notify_with_fds; } LIBSYSTEMD_217; LIBSYSTEMD_220 { global: sd_pid_get_user_slice; sd_peer_get_user_slice; } LIBSYSTEMD_219; LIBSYSTEMD_221 { global: /* sd-bus */ sd_bus_default; sd_bus_default_user; sd_bus_default_system; sd_bus_open; sd_bus_open_user; sd_bus_open_system; sd_bus_open_system_remote; sd_bus_open_system_machine; sd_bus_new; sd_bus_set_address; sd_bus_set_fd; sd_bus_set_exec; sd_bus_get_address; sd_bus_set_bus_client; sd_bus_is_bus_client; sd_bus_set_server; sd_bus_is_server; sd_bus_set_anonymous; sd_bus_is_anonymous; sd_bus_set_trusted; sd_bus_is_trusted; sd_bus_set_monitor; sd_bus_is_monitor; sd_bus_set_description; sd_bus_get_description; sd_bus_negotiate_creds; sd_bus_negotiate_timestamp; sd_bus_negotiate_fds; sd_bus_can_send; sd_bus_get_creds_mask; sd_bus_set_allow_interactive_authorization; sd_bus_get_allow_interactive_authorization; sd_bus_start; sd_bus_close; sd_bus_try_close; sd_bus_ref; sd_bus_unref; sd_bus_is_open; sd_bus_get_bus_id; sd_bus_get_scope; sd_bus_get_tid; sd_bus_get_owner_creds; sd_bus_send; sd_bus_send_to; sd_bus_call; sd_bus_call_async; sd_bus_get_fd; sd_bus_get_events; sd_bus_get_timeout; sd_bus_process; sd_bus_process_priority; sd_bus_wait; sd_bus_flush; sd_bus_get_current_slot; sd_bus_get_current_message; sd_bus_get_current_handler; sd_bus_get_current_userdata; sd_bus_attach_event; sd_bus_detach_event; sd_bus_get_event; sd_bus_add_filter; sd_bus_add_match; sd_bus_add_object; sd_bus_add_fallback; sd_bus_add_object_vtable; sd_bus_add_fallback_vtable; sd_bus_add_node_enumerator; sd_bus_add_object_manager; sd_bus_slot_ref; sd_bus_slot_unref; sd_bus_slot_get_bus; sd_bus_slot_get_userdata; sd_bus_slot_set_userdata; sd_bus_slot_get_description; sd_bus_slot_set_description; sd_bus_slot_get_current_message; sd_bus_slot_get_current_handler; sd_bus_slot_get_current_userdata; sd_bus_message_new_signal; sd_bus_message_new_method_call; sd_bus_message_new_method_return; sd_bus_message_new_method_error; sd_bus_message_new_method_errorf; sd_bus_message_new_method_errno; sd_bus_message_new_method_errnof; sd_bus_message_ref; sd_bus_message_unref; sd_bus_message_get_type; sd_bus_message_get_cookie; sd_bus_message_get_reply_cookie; sd_bus_message_get_priority; sd_bus_message_get_expect_reply; sd_bus_message_get_auto_start; sd_bus_message_get_allow_interactive_authorization; sd_bus_message_get_signature; sd_bus_message_get_path; sd_bus_message_get_interface; sd_bus_message_get_member; sd_bus_message_get_destination; sd_bus_message_get_sender; sd_bus_message_get_error; sd_bus_message_get_errno; sd_bus_message_get_monotonic_usec; sd_bus_message_get_realtime_usec; sd_bus_message_get_seqnum; sd_bus_message_get_bus; sd_bus_message_get_creds; sd_bus_message_is_signal; sd_bus_message_is_method_call; sd_bus_message_is_method_error; sd_bus_message_is_empty; sd_bus_message_has_signature; sd_bus_message_set_expect_reply; sd_bus_message_set_auto_start; sd_bus_message_set_allow_interactive_authorization; sd_bus_message_set_destination; sd_bus_message_set_priority; sd_bus_message_append; sd_bus_message_append_basic; sd_bus_message_append_array; sd_bus_message_append_array_space; sd_bus_message_append_array_iovec; sd_bus_message_append_array_memfd; sd_bus_message_append_string_space; sd_bus_message_append_string_iovec; sd_bus_message_append_string_memfd; sd_bus_message_append_strv; sd_bus_message_open_container; sd_bus_message_close_container; sd_bus_message_copy; sd_bus_message_read; sd_bus_message_read_basic; sd_bus_message_read_array; sd_bus_message_read_strv; sd_bus_message_skip; sd_bus_message_enter_container; sd_bus_message_exit_container; sd_bus_message_peek_type; sd_bus_message_verify_type; sd_bus_message_at_end; sd_bus_message_rewind; sd_bus_get_unique_name; sd_bus_request_name; sd_bus_release_name; sd_bus_list_names; sd_bus_get_name_creds; sd_bus_get_name_machine_id; sd_bus_call_method; sd_bus_call_method_async; sd_bus_get_property; sd_bus_get_property_trivial; sd_bus_get_property_string; sd_bus_get_property_strv; sd_bus_set_property; sd_bus_reply_method_return; sd_bus_reply_method_error; sd_bus_reply_method_errorf; sd_bus_reply_method_errno; sd_bus_reply_method_errnof; sd_bus_emit_signal; sd_bus_emit_properties_changed_strv; sd_bus_emit_properties_changed; sd_bus_emit_interfaces_added_strv; sd_bus_emit_interfaces_added; sd_bus_emit_interfaces_removed_strv; sd_bus_emit_interfaces_removed; sd_bus_query_sender_creds; sd_bus_query_sender_privilege; sd_bus_creds_new_from_pid; sd_bus_creds_ref; sd_bus_creds_unref; sd_bus_creds_get_mask; sd_bus_creds_get_augmented_mask; sd_bus_creds_get_pid; sd_bus_creds_get_ppid; sd_bus_creds_get_tid; sd_bus_creds_get_uid; sd_bus_creds_get_euid; sd_bus_creds_get_suid; sd_bus_creds_get_fsuid; sd_bus_creds_get_gid; sd_bus_creds_get_egid; sd_bus_creds_get_sgid; sd_bus_creds_get_fsgid; sd_bus_creds_get_supplementary_gids; sd_bus_creds_get_comm; sd_bus_creds_get_tid_comm; sd_bus_creds_get_exe; sd_bus_creds_get_cmdline; sd_bus_creds_get_cgroup; sd_bus_creds_get_unit; sd_bus_creds_get_slice; sd_bus_creds_get_user_unit; sd_bus_creds_get_user_slice; sd_bus_creds_get_session; sd_bus_creds_get_owner_uid; sd_bus_creds_has_effective_cap; sd_bus_creds_has_permitted_cap; sd_bus_creds_has_inheritable_cap; sd_bus_creds_has_bounding_cap; sd_bus_creds_get_selinux_context; sd_bus_creds_get_audit_session_id; sd_bus_creds_get_audit_login_uid; sd_bus_creds_get_tty; sd_bus_creds_get_unique_name; sd_bus_creds_get_well_known_names; sd_bus_creds_get_description; sd_bus_error_free; sd_bus_error_set; sd_bus_error_setf; sd_bus_error_set_const; sd_bus_error_set_errno; sd_bus_error_set_errnof; sd_bus_error_set_errnofv; sd_bus_error_get_errno; sd_bus_error_copy; sd_bus_error_is_set; sd_bus_error_has_name; sd_bus_error_add_map; sd_bus_path_encode; sd_bus_path_decode; sd_bus_track_new; sd_bus_track_ref; sd_bus_track_unref; sd_bus_track_get_bus; sd_bus_track_get_userdata; sd_bus_track_set_userdata; sd_bus_track_add_sender; sd_bus_track_remove_sender; sd_bus_track_add_name; sd_bus_track_remove_name; sd_bus_track_count; sd_bus_track_contains; sd_bus_track_first; sd_bus_track_next; /* sd-event */ sd_event_default; sd_event_new; sd_event_ref; sd_event_unref; sd_event_add_io; sd_event_add_time; sd_event_add_signal; sd_event_add_child; sd_event_add_defer; sd_event_add_post; sd_event_add_exit; sd_event_prepare; sd_event_wait; sd_event_dispatch; sd_event_run; sd_event_loop; sd_event_exit; sd_event_now; sd_event_get_fd; sd_event_get_state; sd_event_get_tid; sd_event_get_exit_code; sd_event_set_watchdog; sd_event_get_watchdog; sd_event_source_ref; sd_event_source_unref; sd_event_source_get_event; sd_event_source_get_userdata; sd_event_source_set_userdata; sd_event_source_set_description; sd_event_source_get_description; sd_event_source_set_prepare; sd_event_source_get_pending; sd_event_source_get_priority; sd_event_source_set_priority; sd_event_source_get_enabled; sd_event_source_set_enabled; sd_event_source_get_io_fd; sd_event_source_set_io_fd; sd_event_source_get_io_events; sd_event_source_set_io_events; sd_event_source_get_io_revents; sd_event_source_get_time; sd_event_source_set_time; sd_event_source_set_time_accuracy; sd_event_source_get_time_accuracy; sd_event_source_get_time_clock; sd_event_source_get_signal; sd_event_source_get_child_pid; } LIBSYSTEMD_220; LIBSYSTEMD_222 { global: /* sd-bus */ sd_bus_emit_object_added; sd_bus_emit_object_removed; sd_bus_flush_close_unref; } LIBSYSTEMD_221; LIBSYSTEMD_226 { global: sd_pid_get_cgroup; sd_peer_get_cgroup; } LIBSYSTEMD_222; LIBSYSTEMD_227 { global: sd_bus_default_flush_close; sd_bus_path_decode_many; sd_bus_path_encode_many; sd_listen_fds_with_names; } LIBSYSTEMD_226; LIBSYSTEMD_229 { global: sd_journal_has_runtime_files; sd_journal_has_persistent_files; sd_journal_enumerate_fields; sd_journal_restart_fields; } LIBSYSTEMD_227; systemd-229/src/libsystemd/sd-bus/000077500000000000000000000000001265713322000172245ustar00rootroot00000000000000systemd-229/src/libsystemd/sd-bus/DIFFERENCES000066400000000000000000000022151265713322000206640ustar00rootroot00000000000000Known differences between dbus1 and kdbus: - NameAcquired/NameLost is gone entirely on kdbus backends if libsystemd is used. It is still added in by systemd-bus-proxyd for old dbus1 clients, and it is available if libsystemd is used against the classic dbus1 daemon. If you want to write compatible code with libsystem-bus you need to explicitly subscribe to NameOwnerChanged signals and just ignore NameAcquired/NameLost - Applications have to deal with spurious signals they didn't expect, due to the probabilistic bloom filters. They need to handle this anyway, given that any client can send anything to arbitrary clients anyway, even in dbus1, so not much changes. - clients of the system bus when kdbus is used must roll their own security. Only legacy dbus1 clients get the old XML policy enforced, which is implemented by systemd-bus-proxyd. - Serial numbers of synthesized messages are always (uint32_t) -1. - NameOwnerChanged is a synthetic message, generated locally and not by the driver. On dbus1 only the Disconnected message was synthesized like this. - There's no standard per-session bus anymore. Only a per-user bus. systemd-229/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION000066400000000000000000000104221265713322000223740ustar00rootroot00000000000000How we use GVariant for serializing D-Bus messages -------------------------------------------------- We stay close to the original dbus1 framing as possible, but make certain changes to adapt for GVariant. dbus1 has the following framing: 1. A fixed header of "yyyyuu" 2. Additional header fields of "a(yv)" 3. Padding with NUL bytes to pad up to next 8byte boundary 4. The body Note that the body is not padded at the end, the complete message hence might have a non-aligned size. Reading multiple messages at once will hence result in possibly unaligned messages in memory. The header consists of the following: y Endianness, 'l' or 'B' y Message Type y Flags y Protocol version, '1' u Length of the body, i.e. the length of part 4 above u 32bit Serial number = 12 bytes This header is then followed by the fields array, whose first value is a 32bit array size. When using GVariant we keep the basic structure in place, only slightly alter the header, and define protocol version '2'. The new header: y Endianness, 'l' or 'B' y Message Type y Flags y Protocol version, '2' u Reserved, must be 0 t 64bit Cookie = 16 bytes This is then followed by the GVariant fields array ("a{tv}"), and finally the actual body as variant (v). Putting this altogether a packet on dbus2 hence qualifies as a fully compliant GVariant structure of (yyyyuta{tv}v). For details on gvariant, see: https://people.gnome.org/~desrt/gvariant-serialisation.pdf Regarding the framing of dbus2, also see: https://wiki.gnome.org/Projects/GLib/GDBus/Version2 The first four bytes of the header are defined the same way for dbus1 and dbus2. The first bytes contain the endianess field and the protocol version, so that the remainder of the message can be safely made sense of just by looking at the first 32bit. Note that the length of the body is no longer included in the header on dbus2! In fact, the message size must be known in advance, from the underlying transport in order to parse dbus2 messages, while it is directly included in dbus1 message headers. This change of semantics is an effect of GVariant's basic design. The serial number has been renamed cookie and has been extended from 32bit to 64bit. It is recommended to avoid the higher 32bit of the cookie field though, to simplify compatibility with dbus1 peers. Note that not only the cookie/serial field in the fixed header, but also the reply_cookie/reply_serial additional header field has been increased from 32bit to 64bit, too! The header field identifiers have been extended from 8bit to 64bit. This has been done to simplify things (as kdbus otherwise uses exclusively 64bit types, unless there is a strong reason not to), and has no effect on the serialization size, as due to alignment for each 8bit header field identifier 56 bits of padding had to be added. Note that the header size changed, due to these changes. However, consider that on dbus1 the beginning of the fields array contains the 32bit array size (since that is how arrays are encoded on dbus1), thus, if one considers that size part of the header, instead of the array, the size of the header on dbus1 and dbus2 stays identical, at 16 bytes. 0 4 8 12 16 Common: | E | T | F | V | ... dbus1: | (as above) | Body Length | Serial | Fields Length | Fields array ... gvariant: | (as above) | Reserved | Cookie | Fields array ... And that's already it. Note: to simplify parsing, valid kdbus/dbus2 messages must include the entire fixed header and additional header fields in a single non-memfd message part. Also, the signature string of the body variant all the way to the end of the message must be in a single non-memfd part too. The parts for this extended header and footer can be the same one, and can also continue any amount of additional body bytes. Note: on kdbus only native endian messages marshalled in gvariant may be sent. If a client receives a message in non-native endianness or in dbus1 marshalling it shall ignore the message. Note: The GVariant "MAYBE" type is not supported, so that messages can be fully converted forth and back between dbus1 and gvariant representations. systemd-229/src/libsystemd/sd-bus/Makefile000077700000000000000000000000001265713322000227452../../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd/sd-bus/PORTING-DBUS1000066400000000000000000000614001265713322000211060ustar00rootroot00000000000000A few hints on supporting kdbus as backend in your favorite D-Bus library. ~~~ Before you read this, have a look at the DIFFERENCES and GVARIANT_SERIALIZATION texts you find in the same directory where you found this. We invite you to port your favorite D-Bus protocol implementation over to kdbus. However, there are a couple of complexities involved. On kdbus we only speak GVariant marshaling, kdbus clients ignore traffic in dbus1 marshaling. Thus, you need to add a second, GVariant compatible marshaler to your library first. After you have done that: here's the basic principle how kdbus works: You connect to a bus by opening its bus node in /sys/fs/kdbus/. All buses have a device node there, it starts with a numeric UID of the owner of the bus, followed by a dash and a string identifying the bus. The system bus is thus called /sys/fs/kdbus/0-system, and for user buses the device node is /sys/fs/kdbus/1000-user (if 1000 is your user id). (Before we proceed, please always keep a copy of libsystemd next to you, ultimately that's where the details are, this document simply is a rough overview to help you grok things.) CONNECTING To connect to a bus, simply open() its device node and issue the KDBUS_CMD_HELLO call. That's it. Now you are connected. Do not send Hello messages or so (as you would on dbus1), that does not exist for kdbus. The structure you pass to the ioctl will contain a couple of parameters that you need to know, to operate on the bus. There are two flags fields, one indicating features of the kdbus kernel side ("conn_flags"), the other one ("bus_flags") indicating features of the bus owner (i.e. systemd). Both flags fields are 64bit in width. When calling into the ioctl, you need to place your own supported feature bits into these fields. This tells the kernel about the features you support. When the ioctl returns, it will contain the features the kernel supports. If any of the higher 32bit are set on the two flags fields and your client does not know what they mean, it must disconnect. The upper 32bit are used to indicate "incompatible" feature additions on the bus system, the lower 32bit indicate "compatible" feature additions. A client that does not support a "compatible" feature addition can go on communicating with the bus, however a client that does not support an "incompatible" feature must not proceed with the connection. When a client encountes such an "incompatible" feature it should immediately try the next bus address configured in the bus address string. The hello structure also contains another flags field "attach_flags" which indicates metadata that is optionally attached to all incoming messages. You probably want to set KDBUS_ATTACH_NAMES unconditionally in it. This has the effect that all well-known names of a sender are attached to all incoming messages. You need this information to implement matches that match on a message sender name correctly. Of course, you should only request the attachment of as little metadata fields as you need. The kernel will return in the "id" field your unique id. This is a simple numeric value. For compatibility with classic dbus1 simply format this as string and prefix ":1.". The kernel will also return the bloom filter size and bloom filter hash function number used for the signal broadcast bloom filter (see below). The kernel will also return the bus ID of the bus in a 128bit field. The pool size field specifies the size of the memory mapped buffer. After the calling the hello ioctl, you should memory map the kdbus fd. In this memory mapped region, the kernel will place all your incoming messages. SENDING MESSAGES Use the MSG_SEND ioctl to send a message to another peer. The ioctl takes a structure that contains a variety of fields: The flags field corresponds closely to the old dbus1 message header flags field, though the DONT_EXPECT_REPLY field got inverted into EXPECT_REPLY. The dst_id/src_id field contains the unique id of the destination and the sender. The sender field is overridden by the kernel usually, hence you shouldn't fill it in. The destination field can also take the special value KDBUS_DST_ID_BROADCAST for broadcast messages. For messages intended to a well-known name set the field to KDBUS_DST_ID_NAME, and attach the name in a special "items" entry to the message (see below). The payload field indicates the payload. For all dbus traffic it should carry the value 0x4442757344427573ULL. (Which encodes 'DBusDBus'). The cookie field corresponds with the "serial" field of classic dbus1. We simply renamed it here (and extended it to 64bit) since we didn't want to imply the monotonicity of the assignment the way the word "serial" indicates it. When sending a message that expects a reply, you need to set the EXPECT_REPLY flag in the message flag field. In this case you should also fill out the "timeout_ns" value which indicates the timeout in nsec for this call. If the peer does not respond in this time you will get a notification of a timeout. Note that this is also used for security purposes: a single reply messages is only allowed through the bus as long as the timeout has not ended. With this timeout value you hence "open a time window" in which the peer might respond to your request and the policy allows the response to go through. When sending a message that is a reply, you need to fill in the cookie_reply field, which is similar to the reply_serial field of dbus1. Note that a message cannot have EXPECT_REPLY and a reply_serial at the same time! This pretty much explains the ioctl header. The actual payload of the data is now referenced in additional items that are attached to this ioctl header structure at the end. When sending a message, you attach items of the type PAYLOAD_VEC, PAYLOAD_MEMFD, FDS, BLOOM_FILTER, DST_NAME to it: KDBUS_ITEM_PAYLOAD_VEC: contains a pointer + length pair for referencing arbitrary user memory. This is how you reference most of your data. It's a lot like the good old iovec structure of glibc. KDBUS_ITEM_PAYLOAD_MEMFD: for large data blocks it is preferable to send prepared "memfds" (see below) over. This item contains an fd for a memfd plus a size. KDBUS_ITEM_FDS: for sending over fds attach an item of this type with an array of fds. KDBUS_ITEM_BLOOM_FILTER: the calculated bloom filter of this message, only for undirected (broadcast) message. KDBUS_ITEM_DST_NAME: for messages that are directed to a well-known name (instead of a unique name), this item contains the well-known name field. A single message may consists of no, one or more payload items of type PAYLOAD_VEC or PAYLOAD_MEMFD. D-Bus protocol implementations should treat them as a single block that just happens to be split up into multiple items. Some restrictions apply however: The message header in its entirety must be contained in a single PAYLOAD_VEC item. You may only split your message up right in front of each GVariant contained in the payload, as well is immediately before framing of a Gvariant, as well after as any padding bytes if there are any. The padding bytes must be wholly contained in the preceding PAYLOAD_VEC/PAYLOAD_MEMFD item. You may not split up basic types nor arrays of fixed types. The latter is necessary to allow APIs to return direct pointers to linear arrays of numeric values. Examples: The basic types "u", "s", "t" have to be in the same payload item. The array of fixed types "ay", "ai" have to be fully in contained in the same payload item. For an array "as" or "a(si)" the only restriction however is to keep each string individually in an uninterrupted item, to keep the framing of each element and the array in a single uninterrupted item, however the various strings might end up in different items. Note again, that splitting up messages into separate items is up to the implementation. Also note that the kdbus kernel side might merge separate items if it deems this to be useful. However, the order in which items are contained in the message is left untouched. PAYLOAD_MEMFD items allow zero-copy data transfer (see below regarding the memfd concept). Note however that the overhead of mapping these makes them relatively expensive, and only worth the trouble for memory blocks > 512K (this value appears to be quite universal across architectures, as we tested). Thus we recommend sending PAYLOAD_VEC items over for small messages and restore to PAYLOAD_MEMFD items for messages > 512K. Since while building up the message you might not know yet whether it will grow beyond this boundary a good approach is to simply build the message unconditionally in a memfd object. However, when the message is sealed to be sent away check for the size limit. If the size of the message is < 512K, then simply send the data as PAYLOAD_VEC and reuse the memfd. If it is >= 512K, seal the memfd and send it as PAYLOAD_MEMFD, and allocate a new memfd for the next message. RECEIVING MESSAGES Use the MSG_RECV ioctl to read a message from kdbus. This will return an offset into the pool memory map, relative to its beginning. The received message structure more or less follows the structure of the message originally sent. However, certain changes have been made. In the header the src_id field will be filled in. The payload items might have gotten merged and PAYLOAD_VEC items are not used. Instead, you will only find PAYLOAD_OFF and PAYLOAD_MEMFD items. The former contain an offset and size into your memory mapped pool where you find the payload. If during the HELLO ioctl you asked for getting metadata attached to your message, you will find additional KDBUS_ITEM_CREDS, KDBUS_ITEM_PID_COMM, KDBUS_ITEM_TID_COMM, KDBUS_ITEM_TIMESTAMP, KDBUS_ITEM_EXE, KDBUS_ITEM_CMDLINE, KDBUS_ITEM_CGROUP, KDBUS_ITEM_CAPS, KDBUS_ITEM_SECLABEL, KDBUS_ITEM_AUDIT items that contain this metadata. This metadata will be gathered from the sender at the point in time it sends the message. This information is uncached, and since it is appended by the kernel, trustable. The KDBUS_ITEM_SECLABEL item usually contains the SELinux security label, if it is used. After processing the message you need to call the KDBUS_CMD_FREE ioctl, which releases the message from the pool, and allows the kernel to store another message there. Note that the memory used by the pool is ordinary anonymous, swappable memory that is backed by tmpfs. Hence there is no need to copy the message out of it quickly, instead you can just leave it there as long as you need it and release it via the FREE ioctl only after that's done. BLOOM FILTERS The kernel does not understand dbus marshaling, it will not look into the message payload. To allow clients to subscribe to specific subsets of the broadcast matches we employ bloom filters. When broadcasting messages, a bloom filter needs to be attached to the message in a KDBUS_ITEM_BLOOM item (and only for broadcasting messages!). If you don't know what bloom filters are, read up now on Wikipedia. In short: they are a very efficient way how to probabilistically check whether a certain word is contained in a vocabulary. It knows no false negatives, but it does know false positives. The parameters for the bloom filters that need to be included in broadcast message is communicated to userspace as part of the hello response structure (see above). By default it has the parameters m=512 (bits in the filter), k=8 (nr of hash functions). Note however, that this is subject to change in later versions, and userspace implementations must be capable of handling m values between at least m=8 and m=2^32, and k values between at least k=1 and k=32. The underlying hash function is SipHash-2-4. It is used with a number of constant (yet originally randomly generated) 128bit hash keys, more specifically: b9,66,0b,f0,46,70,47,c1,88,75,c4,9c,54,b9,bd,15, aa,a1,54,a2,e0,71,4b,39,bf,e1,dd,2e,9f,c5,4a,3b, 63,fd,ae,be,cd,82,48,12,a1,6e,41,26,cb,fa,a0,c8, 23,be,45,29,32,d2,46,2d,82,03,52,28,fe,37,17,f5, 56,3b,bf,ee,5a,4f,43,39,af,aa,94,08,df,f0,fc,10, 31,80,c8,73,c7,ea,46,d3,aa,25,75,0f,9e,4c,09,29, 7d,f7,18,4b,7b,a4,44,d5,85,3c,06,e0,65,53,96,6d, f2,77,e9,6f,93,b5,4e,71,9a,0c,34,88,39,25,bf,35 When calculating the first bit index into the bloom filter, the SipHash-2-4 hash value is calculated for the input data and the first 16 bytes of the array above as hash key. Of the resulting 8 bytes of output, as many full bytes are taken for the bit index as necessary, starting from the output's first byte. For the second bit index the same hash value is used, continuing with the next unused output byte, and so on. Each time the bytes returned by the hash function are depleted it is recalculated with the next 16 byte hash key from the array above and the same input data. For each message to send across the bus we populate the bloom filter with all possible matchable strings. If a client then wants to subscribe to messages of this type, it simply tells the kernel to test its own calculated bit mask against the bloom filter of each message. More specifically, the following strings are added to the bloom filter of each message that is broadcasted: The string "interface:" suffixed by the interface name The string "member:" suffixed by the member name The string "path:" suffixed by the path name The string "path-slash-prefix:" suffixed with the path name, and also all prefixes of the path name (cut off at "/"), also prefixed with "path-slash-prefix". The string "message-type:" suffixed with the strings "signal", "method_call", "error" or "method_return" for the respective message type of the message. If the first argument of the message is a string, "arg0:" suffixed with the first argument. If the first argument of the message is a string, "arg0-dot-prefix" suffixed with the first argument, and also all prefixes of the argument (cut off at "."), also prefixed with "arg0-dot-prefix". If the first argument of the message is a string, "arg0-slash-prefix" suffixed with the first argument, and also all prefixes of the argument (cut off at "/"), also prefixed with "arg0-slash-prefix". Similar for all further arguments that are strings up to 63, for the arguments and their "dot" and "slash" prefixes. On the first argument that is not a string, addition to the bloom filter should be stopped however. (Note that the bloom filter does not contain sender nor receiver names!) When a client wants to subscribe to messages matching a certain expression, it should calculate the bloom mask following the same algorithm. The kernel will then simply test the mask against the attached bloom filters. Note that bloom filters are probabilistic, which means that clients might get messages they did not expect. Your bus protocol implementation must be capable of dealing with these unexpected messages (which it needs to anyway, given that transfers are relatively unrestricted on kdbus and people can send you all kinds of non-sense). If a client connects to a bus whose bloom filter metrics (i.e. filter size and number of hash functions) are outside of the range the client supports it must immediately disconnect and continue connection with the next bus address of the bus connection string. INSTALLING MATCHES To install matches for broadcast messages, use the KDBUS_CMD_ADD_MATCH ioctl. It takes a structure that contains an encoded match expression, and that is followed by one or more items, which are combined in an AND way. (Meaning: a message is matched exactly when all items attached to the original ioctl struct match). To match against other user messages add a KDBUS_ITEM_BLOOM item in the match (see above). Note that the bloom filter does not include matches to the sender names. To additionally check against sender names, use the KDBUS_ITEM_ID (for unique id matches) and KDBUS_ITEM_NAME (for well-known name matches) item types. To match against kernel generated messages (see below) you should add items of the same type as the kernel messages include, i.e. KDBUS_ITEM_NAME_ADD, KDBUS_ITEM_NAME_REMOVE, KDBUS_ITEM_NAME_CHANGE, KDBUS_ITEM_ID_ADD, KDBUS_ITEM_ID_REMOVE and fill them out. Note however, that you have some wildcards in this case, for example the .id field of KDBUS_ITEM_ID_ADD/KDBUS_ITEM_ID_REMOVE structures may be set to 0 to match against any id addition/removal. Note that dbus match strings do no map 1:1 to these ioctl() calls. In many cases (where the match string is "underspecified") you might need to issue up to six different ioctl() calls for the same match. For example, the empty match (which matches against all messages), would translate into one KDBUS_ITEM_BLOOM ioctl, one KDBUS_ITEM_NAME_ADD, one KDBUS_ITEM_NAME_CHANGE, one KDBUS_ITEM_NAME_REMOVE, one KDBUS_ITEM_ID_ADD and one KDBUS_ITEM_ID_REMOVE. When creating a match, you may attach a "cookie" value to them, which is used for deleting this match again. The cookie can be selected freely by the client. When issuing KDBUS_CMD_REMOVE_MATCH, simply pass the same cookie as before and all matches matching the same "cookie" value will be removed. This is particularly handy for the case where multiple ioctl()s are added for a single match strings. MEMFDS memfds may be sent across kdbus via KDBUS_ITEM_PAYLOAD_MEMFD items attached to messages. If this is done, the data included in the memfd is considered part of the payload stream of a message, and are treated the same way as KDBUS_ITEM_PAYLOAD_VEC by the receiving side. It is possible to interleave KDBUS_ITEM_PAYLOAD_MEMFD and KDBUS_ITEM_PAYLOAD_VEC items freely, by the reader they will be considered a single stream of bytes in the order these items appear in the message, that just happens to be split up at various places (regarding rules how they may be split up, see above). The kernel will refuse taking KDBUS_ITEM_PAYLOAD_MEMFD items that refer to memfds that are not sealed. Note that sealed memfds may be unsealed again if they are not mapped you have the only fd reference to them. Alternatively to sending memfds as KDBUS_ITEM_PAYLOAD_MEMFD items (where they are just a part of the payload stream of a message) you can also simply attach any memfd to a message using KDBUS_ITEM_PAYLOAD_FDS. In this case, the memfd contents is not considered part of the payload stream of the message, but simply fds like any other, that happen to be attached to the message. MESSAGES FROM THE KERNEL A couple of messages previously generated by the dbus1 bus driver are now generated by the kernel. Since the kernel does not understand the payload marshaling, they are generated by the kernel in a different format. This is indicated with the "payload type" field of the messages set to 0. Library implementations should take these messages and synthesize traditional driver messages for them on reception. More specifically: Instead of the NameOwnerChanged, NameLost, NameAcquired signals there are kernel messages containing KDBUS_ITEM_NAME_ADD, KDBUS_ITEM_NAME_REMOVE, KDBUS_ITEM_NAME_CHANGE, KDBUS_ITEM_ID_ADD, KDBUS_ITEM_ID_REMOVE items are generated (each message will contain exactly one of these items). Note that in libsystemd we have obsoleted NameLost/NameAcquired messages, since they are entirely redundant to NameOwnerChanged. This library will hence only synthesize NameOwnerChanged messages from these kernel messages, and never generate NameLost/NameAcquired. If your library needs to stay compatible to the old dbus1 userspace, you possibly might need to synthesize both a NameOwnerChanged and NameLost/NameAcquired message from the same kernel message. When a method call times out, a KDBUS_ITEM_REPLY_TIMEOUT message is generated. This should be synthesized into a method error reply message to the original call. When a method call fails because the peer terminated the connection before responding, a KDBUS_ITEM_REPLY_DEAD message is generated. Similarly, it should be synthesized into a method error reply message. For synthesized messages we recommend setting the cookie field to (uint32_t) -1 (and not (uint64_t) -1!), so that the cookie is not 0 (which the dbus1 spec does not allow), but clearly recognizable as synthetic. Note that the KDBUS_ITEM_NAME_XYZ messages will actually inform you about all kinds of names, including activatable ones. Classic dbus1 NameOwnerChanged messages OTOH are only generated when a name is really acquired on the bus and not just simply activatable. This means you must explicitly check for the case where an activatable name becomes acquired or an acquired name is lost and returns to be activatable. NAME REGISTRY To acquire names on the bus, use the KDBUS_CMD_NAME_ACQUIRE ioctl(). It takes a flags field similar to dbus1's RequestName() bus driver call, however the NO_QUEUE flag got inverted into a QUEUE flag instead. To release a previously acquired name use the KDBUS_CMD_NAME_RELEASE ioctl(). To list acquired names use the KDBUS_CMD_CONN_INFO ioctl. It may be used to list unique names, well known names as well as activatable names and clients currently queuing for ownership of a well-known name. The ioctl will return an offset into the memory pool. After reading all the data you need, you need to release this via the KDBUS_CMD_FREE ioctl(), similar how you release a received message. CREDENTIALS kdbus can optionally attach various kinds of metadata about the sender at the point of time of sending ("credentials") to messages, on request of the receiver. This is both supported on directed and undirected (broadcast) messages. The metadata to attach is selected at time of the HELLO ioctl of the receiver via a flags field (see above). Note that clients must be able to handle that messages contain more metadata than they asked for themselves, to simplify implementation of broadcasting in the kernel. The receiver should not rely on this data to be around though, even though it will be correct if it happens to be attached. In order to avoid programming errors in applications, we recommend though not passing this data on to clients that did not explicitly ask for it. Credentials may also be queried for a well-known or unique name. Use the KDBUS_CMD_CONN_INFO for this. It will return an offset to the pool area again, which will contain the same credential items as messages have attached. Note that when issuing the ioctl, you can select a different set of credentials to gather, than what was originally requested for being attached to incoming messages. Credentials are always specific to the sender's domain that was current at the time of sending, and of the process that opened the bus connection at the time of opening it. Note that this latter data is cached! POLICY The kernel enforces only very limited policy on names. It will not do access filtering by userspace payload, and thus not by interface or method name. This ultimately means that most fine-grained policy enforcement needs to be done by the receiving process. We recommend using PolicyKit for any more complex checks. However, libraries should make simple static policy decisions regarding privileged/unprivileged method calls easy. We recommend doing this by enabling KDBUS_ATTACH_CAPS and KDBUS_ATTACH_CREDS for incoming messages, and then discerning client access by some capability, or if sender and receiver UIDs match. BUS ADDRESSES When connecting to kdbus use the "kernel:" protocol prefix in DBus address strings. The device node path is encoded in its "path=" parameter. Client libraries should use the following connection string when connecting to the system bus: kernel:path=/sys/fs/kdbus/0-system/bus;unix:path=/var/run/dbus/system_bus_socket This will ensure that kdbus is preferred over the legacy AF_UNIX socket, but compatibility is kept. For the user bus use: kernel:path=/sys/fs/kdbus/$UID-user/bus;unix:path=$XDG_RUNTIME_DIR/bus With $UID replaced by the callers numer user ID, and $XDG_RUNTIME_DIR following the XDG basedir spec. Of course the $DBUS_SYSTEM_BUS_ADDRESS and $DBUS_SESSION_BUS_ADDRESS variables should still take precedence. DBUS SERVICE FILES Activatable services for kdbus may not use classic dbus1 service activation files. Instead, programs should drop in native systemd .service and .busname unit files, so that they are treated uniformly with other types of units and activation of the system. Note that this results in a major difference to classic dbus1: activatable bus names can be established at any time in the boot process. This is unlike dbus1 where activatable names are unconditionally available as long as dbus-daemon is running. Being able to control when activatable names are established is essential to allow usage of kdbus during early boot and in initrds, without the risk of triggering services too early. DISCLAIMER This all is so far just the status quo. We are putting this together, because we are quite confident that further API changes will be smaller, but to make this very clear: this is all subject to change, still! We invite you to port over your favorite dbus library to this new scheme, but please be prepared to make minor changes when we still change these interfaces! systemd-229/src/libsystemd/sd-bus/bus-bloom.c000066400000000000000000000111301265713322000212630ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-bloom.h" #include "siphash24.h" #include "util.h" static inline void set_bit(uint64_t filter[], unsigned long b) { filter[b >> 6] |= 1ULL << (b & 63); } static const sd_id128_t hash_keys[] = { SD_ID128_ARRAY(b9,66,0b,f0,46,70,47,c1,88,75,c4,9c,54,b9,bd,15), SD_ID128_ARRAY(aa,a1,54,a2,e0,71,4b,39,bf,e1,dd,2e,9f,c5,4a,3b), SD_ID128_ARRAY(63,fd,ae,be,cd,82,48,12,a1,6e,41,26,cb,fa,a0,c8), SD_ID128_ARRAY(23,be,45,29,32,d2,46,2d,82,03,52,28,fe,37,17,f5), SD_ID128_ARRAY(56,3b,bf,ee,5a,4f,43,39,af,aa,94,08,df,f0,fc,10), SD_ID128_ARRAY(31,80,c8,73,c7,ea,46,d3,aa,25,75,0f,9e,4c,09,29), SD_ID128_ARRAY(7d,f7,18,4b,7b,a4,44,d5,85,3c,06,e0,65,53,96,6d), SD_ID128_ARRAY(f2,77,e9,6f,93,b5,4e,71,9a,0c,34,88,39,25,bf,35), }; static void bloom_add_data( uint64_t filter[], /* The filter bits */ size_t size, /* Size of the filter in bytes */ unsigned k, /* Number of hash functions */ const void *data, /* Data to hash */ size_t n) { /* Size of data to hash in bytes */ uint64_t h; uint64_t m; unsigned w, i, c = 0; unsigned hash_index; assert(size > 0); assert(k > 0); /* Determine bits in filter */ m = size * 8; /* Determine how many bytes we need to generate a bit index 0..m for this filter */ w = (u64log2(m) + 7) / 8; assert(w <= sizeof(uint64_t)); /* Make sure we have enough hash keys to generate m * k bits * of hash value. Note that SipHash24 generates 64 bits of * hash value for each 128 bits of hash key. */ assert(k * w <= ELEMENTSOF(hash_keys) * 8); for (i = 0, hash_index = 0; i < k; i++) { uint64_t p = 0; unsigned d; for (d = 0; d < w; d++) { if (c <= 0) { h = siphash24(data, n, hash_keys[hash_index++].bytes); c += 8; } p = (p << 8ULL) | (uint64_t) ((uint8_t *)&h)[8 - c]; c--; } p &= m - 1; set_bit(filter, p); } /* log_debug("bloom: adding <%.*s>", (int) n, (char*) data); */ } void bloom_add_pair(uint64_t filter[], size_t size, unsigned k, const char *a, const char *b) { size_t n; char *c; assert(filter); assert(a); assert(b); n = strlen(a) + 1 + strlen(b); c = alloca(n + 1); strcpy(stpcpy(stpcpy(c, a), ":"), b); bloom_add_data(filter, size, k, c, n); } void bloom_add_prefixes(uint64_t filter[], size_t size, unsigned k, const char *a, const char *b, char sep) { size_t n; char *c, *p; assert(filter); assert(a); assert(b); n = strlen(a) + 1 + strlen(b); c = alloca(n + 1); p = stpcpy(stpcpy(c, a), ":"); strcpy(p, b); bloom_add_data(filter, size, k, c, n); for (;;) { char *e; e = strrchr(p, sep); if (!e) break; *(e + 1) = 0; bloom_add_data(filter, size, k, c, e - c + 1); if (e == p) break; *e = 0; bloom_add_data(filter, size, k, c, e - c); } } bool bloom_validate_parameters(size_t size, unsigned k) { uint64_t m; unsigned w; if (size <= 0) return false; if (k <= 0) return false; m = size * 8; w = (u64log2(m) + 7) / 8; if (w > sizeof(uint64_t)) return false; if (k * w > ELEMENTSOF(hash_keys) * 8) return false; return true; } systemd-229/src/libsystemd/sd-bus/bus-bloom.h000066400000000000000000000026331265713322000213000ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include /* * Our default bloom filter has the following parameters: * * m=512 (bits in the filter) * k=8 (hash functions) * * We use SipHash24 as hash function with a number of (originally * randomized) but fixed hash keys. * */ #define DEFAULT_BLOOM_SIZE (512/8) /* m: filter size */ #define DEFAULT_BLOOM_N_HASH 8 /* k: number of hash functions */ void bloom_add_pair(uint64_t filter[], size_t size, unsigned n_hash, const char *a, const char *b); void bloom_add_prefixes(uint64_t filter[], size_t size, unsigned n_hash, const char *a, const char *b, char sep); bool bloom_validate_parameters(size_t size, unsigned n_hash); systemd-229/src/libsystemd/sd-bus/bus-common-errors.c000066400000000000000000000112141265713322000227600ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "bus-common-errors.h" #include "bus-error.h" BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_UNIT, ENOENT), SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_PID, ESRCH), SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_EXISTS, EEXIST), SD_BUS_ERROR_MAP(BUS_ERROR_LOAD_FAILED, EIO), SD_BUS_ERROR_MAP(BUS_ERROR_JOB_FAILED, EREMOTEIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_JOB, ENOENT), SD_BUS_ERROR_MAP(BUS_ERROR_NOT_SUBSCRIBED, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_ALREADY_SUBSCRIBED, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_ONLY_BY_DEPENDENCY, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, EDEADLK), SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC, EDEADLK), SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, EDEADLK), SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_MASKED, ESHUTDOWN), SD_BUS_ERROR_MAP(BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, EBADR), SD_BUS_ERROR_MAP(BUS_ERROR_NO_ISOLATION, EPERM), SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN, ECANCELED), SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING, EHOSTDOWN), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE, ENOENT), SD_BUS_ERROR_MAP(BUS_ERROR_NO_MACHINE_FOR_PID, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_MACHINE_EXISTS, EEXIST), SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRIVATE_NETWORKING, ENOSYS), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SESSION, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SESSION_FOR_PID, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_USER, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_USER_FOR_PID, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SEAT, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_NOT_ON_SEAT, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_NOT_IN_CONTROL, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_IS_TAKEN, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_NOT_TAKEN, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS, EINPROGRESS), SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, EOPNOTSUPP), SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_PROCESS, ESRCH), SD_BUS_ERROR_MAP(BUS_ERROR_NO_NAME_SERVERS, ESRCH), SD_BUS_ERROR_MAP(BUS_ERROR_INVALID_REPLY, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_RR, ENOENT), SD_BUS_ERROR_MAP(BUS_ERROR_NO_RESOURCES, ENOMEM), SD_BUS_ERROR_MAP(BUS_ERROR_CNAME_LOOP, EDEADLK), SD_BUS_ERROR_MAP(BUS_ERROR_ABORTED, ECANCELED), SD_BUS_ERROR_MAP(BUS_ERROR_CONNECTION_FAILURE, ECONNREFUSED), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SERVICE, EUNATCH), SD_BUS_ERROR_MAP(BUS_ERROR_DNSSEC_FAILED, EHOSTUNREACH), SD_BUS_ERROR_MAP(BUS_ERROR_NO_TRUST_ANCHOR, EHOSTUNREACH), SD_BUS_ERROR_MAP(BUS_ERROR_RR_TYPE_UNSUPPORTED, EOPNOTSUPP), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_LINK, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY), SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS, EBUSY), SD_BUS_ERROR_MAP_END }; systemd-229/src/libsystemd/sd-bus/bus-common-errors.h000066400000000000000000000115771265713322000230010ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-error.h" #define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit" #define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID" #define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists" #define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed" #define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed" #define BUS_ERROR_NO_SUCH_JOB "org.freedesktop.systemd1.NoSuchJob" #define BUS_ERROR_NOT_SUBSCRIBED "org.freedesktop.systemd1.NotSubscribed" #define BUS_ERROR_ALREADY_SUBSCRIBED "org.freedesktop.systemd1.AlreadySubscribed" #define BUS_ERROR_ONLY_BY_DEPENDENCY "org.freedesktop.systemd1.OnlyByDependency" #define BUS_ERROR_TRANSACTION_JOBS_CONFLICTING "org.freedesktop.systemd1.TransactionJobsConflicting" #define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic" #define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive" #define BUS_ERROR_UNIT_MASKED "org.freedesktop.systemd1.UnitMasked" #define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable" #define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation" #define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown" #define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning" #define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine" #define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage" #define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID" #define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists" #define BUS_ERROR_NO_PRIVATE_NETWORKING "org.freedesktop.machine1.NoPrivateNetworking" #define BUS_ERROR_NO_SUCH_USER_MAPPING "org.freedesktop.machine1.NoSuchUserMapping" #define BUS_ERROR_NO_SUCH_GROUP_MAPPING "org.freedesktop.machine1.NoSuchGroupMapping" #define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession" #define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID" #define BUS_ERROR_NO_SUCH_USER "org.freedesktop.login1.NoSuchUser" #define BUS_ERROR_NO_USER_FOR_PID "org.freedesktop.login1.NoUserForPID" #define BUS_ERROR_NO_SUCH_SEAT "org.freedesktop.login1.NoSuchSeat" #define BUS_ERROR_SESSION_NOT_ON_SEAT "org.freedesktop.login1.SessionNotOnSeat" #define BUS_ERROR_NOT_IN_CONTROL "org.freedesktop.login1.NotInControl" #define BUS_ERROR_DEVICE_IS_TAKEN "org.freedesktop.login1.DeviceIsTaken" #define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken" #define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress" #define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported" #define BUS_ERROR_SESSION_BUSY "org.freedesktop.login1.SessionBusy" #define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled" #define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess" #define BUS_ERROR_NO_NAME_SERVERS "org.freedesktop.resolve1.NoNameServers" #define BUS_ERROR_INVALID_REPLY "org.freedesktop.resolve1.InvalidReply" #define BUS_ERROR_NO_SUCH_RR "org.freedesktop.resolve1.NoSuchRR" #define BUS_ERROR_NO_RESOURCES "org.freedesktop.resolve1.NoResources" #define BUS_ERROR_CNAME_LOOP "org.freedesktop.resolve1.CNameLoop" #define BUS_ERROR_ABORTED "org.freedesktop.resolve1.Aborted" #define BUS_ERROR_CONNECTION_FAILURE "org.freedesktop.resolve1.ConnectionFailure" #define BUS_ERROR_NO_SUCH_SERVICE "org.freedesktop.resolve1.NoSuchService" #define BUS_ERROR_DNSSEC_FAILED "org.freedesktop.resolve1.DnssecFailed" #define BUS_ERROR_NO_TRUST_ANCHOR "org.freedesktop.resolve1.NoTrustAnchor" #define BUS_ERROR_RR_TYPE_UNSUPPORTED "org.freedesktop.resolve1.ResourceRecordTypeUnsupported" #define BUS_ERROR_NO_SUCH_LINK "org.freedesktop.resolve1.NoSuchLink" #define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy" #define BUS_ERROR_NETWORK_DOWN "org.freedesktop.resolve1.NetworkDown" #define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError." #define BUS_ERROR_NO_SUCH_TRANSFER "org.freedesktop.import1.NoSuchTransfer" #define BUS_ERROR_TRANSFER_IN_PROGRESS "org.freedesktop.import1.TransferInProgress" BUS_ERROR_MAP_ELF_USE(bus_common_errors); systemd-229/src/libsystemd/sd-bus/bus-container.c000066400000000000000000000206441265713322000221470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "bus-container.h" #include "bus-internal.h" #include "bus-socket.h" #include "fd-util.h" #include "process-util.h" #include "util.h" int bus_container_connect_socket(sd_bus *b) { _cleanup_close_pair_ int pair[2] = { -1, -1 }; _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1; pid_t child; siginfo_t si; int r, error_buf = 0; ssize_t n; assert(b); assert(b->input_fd < 0); assert(b->output_fd < 0); assert(b->nspid > 0 || b->machine); if (b->nspid <= 0) { r = container_get_leader(b->machine, &b->nspid); if (r < 0) return r; } r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd); if (r < 0) return r; b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (b->input_fd < 0) return -errno; b->output_fd = b->input_fd; bus_socket_setup(b); if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0) return -errno; child = fork(); if (child < 0) return -errno; if (child == 0) { pid_t grandchild; pair[0] = safe_close(pair[0]); r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd); if (r < 0) _exit(EXIT_FAILURE); /* We just changed PID namespace, however it will only * take effect on the children we now fork. Hence, * let's fork another time, and connect from this * grandchild, so that SO_PEERCRED of our connection * comes from a process from within the container, and * not outside of it */ grandchild = fork(); if (grandchild < 0) _exit(EXIT_FAILURE); if (grandchild == 0) { r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size); if (r < 0) { /* Try to send error up */ error_buf = errno; (void) write(pair[1], &error_buf, sizeof(error_buf)); _exit(EXIT_FAILURE); } _exit(EXIT_SUCCESS); } r = wait_for_terminate(grandchild, &si); if (r < 0) _exit(EXIT_FAILURE); if (si.si_code != CLD_EXITED) _exit(EXIT_FAILURE); _exit(si.si_status); } pair[1] = safe_close(pair[1]); r = wait_for_terminate(child, &si); if (r < 0) return r; n = read(pair[0], &error_buf, sizeof(error_buf)); if (n < 0) return -errno; if (n > 0) { if (n != sizeof(error_buf)) return -EIO; if (error_buf < 0) return -EIO; if (error_buf == EINPROGRESS) return 1; if (error_buf > 0) return -error_buf; } if (si.si_code != CLD_EXITED) return -EIO; if (si.si_status != EXIT_SUCCESS) return -EIO; return bus_socket_start_auth(b); } int bus_container_connect_kernel(sd_bus *b) { _cleanup_close_pair_ int pair[2] = { -1, -1 }; _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1; union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(int))]; } control = {}; int error_buf = 0; struct iovec iov = { .iov_base = &error_buf, .iov_len = sizeof(error_buf), }; struct msghdr mh = { .msg_control = &control, .msg_controllen = sizeof(control), .msg_iov = &iov, .msg_iovlen = 1, }; struct cmsghdr *cmsg; pid_t child; siginfo_t si; int r, fd = -1; ssize_t n; assert(b); assert(b->input_fd < 0); assert(b->output_fd < 0); assert(b->nspid > 0 || b->machine); if (b->nspid <= 0) { r = container_get_leader(b->machine, &b->nspid); if (r < 0) return r; } r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd); if (r < 0) return r; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0) return -errno; child = fork(); if (child < 0) return -errno; if (child == 0) { pid_t grandchild; pair[0] = safe_close(pair[0]); r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd); if (r < 0) _exit(EXIT_FAILURE); /* We just changed PID namespace, however it will only * take effect on the children we now fork. Hence, * let's fork another time, and connect from this * grandchild, so that kdbus only sees the credentials * of this process which comes from within the * container, and not outside of it */ grandchild = fork(); if (grandchild < 0) _exit(EXIT_FAILURE); if (grandchild == 0) { fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) { /* Try to send error up */ error_buf = errno; (void) write(pair[1], &error_buf, sizeof(error_buf)); _exit(EXIT_FAILURE); } r = send_one_fd(pair[1], fd, 0); if (r < 0) _exit(EXIT_FAILURE); _exit(EXIT_SUCCESS); } r = wait_for_terminate(grandchild, &si); if (r < 0) _exit(EXIT_FAILURE); if (si.si_code != CLD_EXITED) _exit(EXIT_FAILURE); _exit(si.si_status); } pair[1] = safe_close(pair[1]); r = wait_for_terminate(child, &si); if (r < 0) return r; n = recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC); if (n < 0) return -errno; CMSG_FOREACH(cmsg, &mh) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { int *fds; unsigned n_fds; assert(fd < 0); fds = (int*) CMSG_DATA(cmsg); n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); if (n_fds != 1) { close_many(fds, n_fds); return -EIO; } fd = fds[0]; } } /* If there's an fd passed, we are good. */ if (fd >= 0) { b->input_fd = b->output_fd = fd; return bus_kernel_take_fd(b); } /* If there's an error passed, use it */ if (n == sizeof(error_buf) && error_buf > 0) return -error_buf; /* Otherwise, we have no clue */ return -EIO; } systemd-229/src/libsystemd/sd-bus/bus-container.h000066400000000000000000000015141265713322000221470ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" int bus_container_connect_socket(sd_bus *b); int bus_container_connect_kernel(sd_bus *b); systemd-229/src/libsystemd/sd-bus/bus-control.c000066400000000000000000001603731265713322000216510ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #ifdef HAVE_VALGRIND_MEMCHECK_H #include #endif #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-bloom.h" #include "bus-control.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-util.h" #include "capability-util.h" #include "stdio-util.h" #include "string-util.h" #include "strv.h" #include "user-util.h" _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) { int r; assert_return(bus, -EINVAL); assert_return(unique, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!bus->bus_client) return -EINVAL; r = bus_ensure_running(bus); if (r < 0) return r; *unique = bus->unique_name; return 0; } static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) { struct kdbus_cmd *n; size_t size, l; int r; assert(bus); assert(name); l = strlen(name) + 1; size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l); n = alloca0_align(size, 8); n->size = size; n->flags = request_name_flags_to_kdbus(flags); n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l; n->items[0].type = KDBUS_ITEM_NAME; memcpy(n->items[0].str, name, l); #ifdef HAVE_VALGRIND_MEMCHECK_H VALGRIND_MAKE_MEM_DEFINED(n, n->size); #endif r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n); if (r < 0) return -errno; if (n->return_flags & KDBUS_NAME_IN_QUEUE) return 0; return 1; } static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; uint32_t ret, param = 0; int r; assert(bus); assert(name); if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT) param |= BUS_NAME_ALLOW_REPLACEMENT; if (flags & SD_BUS_NAME_REPLACE_EXISTING) param |= BUS_NAME_REPLACE_EXISTING; if (!(flags & SD_BUS_NAME_QUEUE)) param |= BUS_NAME_DO_NOT_QUEUE; r = sd_bus_call_method( bus, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "RequestName", NULL, &reply, "su", name, param); if (r < 0) return r; r = sd_bus_message_read(reply, "u", &ret); if (r < 0) return r; if (ret == BUS_NAME_ALREADY_OWNER) return -EALREADY; else if (ret == BUS_NAME_EXISTS) return -EEXIST; else if (ret == BUS_NAME_IN_QUEUE) return 0; else if (ret == BUS_NAME_PRIMARY_OWNER) return 1; return -EIO; } _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) { assert_return(bus, -EINVAL); assert_return(name, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL); assert_return(service_name_is_valid(name), -EINVAL); assert_return(name[0] != ':', -EINVAL); if (!bus->bus_client) return -EINVAL; /* Don't allow requesting the special driver and local names */ if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local")) return -EINVAL; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; if (bus->is_kernel) return bus_request_name_kernel(bus, name, flags); else return bus_request_name_dbus1(bus, name, flags); } static int bus_release_name_kernel(sd_bus *bus, const char *name) { struct kdbus_cmd *n; size_t size, l; int r; assert(bus); assert(name); l = strlen(name) + 1; size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l); n = alloca0_align(size, 8); n->size = size; n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l; n->items[0].type = KDBUS_ITEM_NAME; memcpy(n->items[0].str, name, l); #ifdef HAVE_VALGRIND_MEMCHECK_H VALGRIND_MAKE_MEM_DEFINED(n, n->size); #endif r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n); if (r < 0) return -errno; return 0; } static int bus_release_name_dbus1(sd_bus *bus, const char *name) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; uint32_t ret; int r; assert(bus); assert(name); r = sd_bus_call_method( bus, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ReleaseName", NULL, &reply, "s", name); if (r < 0) return r; r = sd_bus_message_read(reply, "u", &ret); if (r < 0) return r; if (ret == BUS_NAME_NON_EXISTENT) return -ESRCH; if (ret == BUS_NAME_NOT_OWNER) return -EADDRINUSE; if (ret == BUS_NAME_RELEASED) return 0; return -EINVAL; } _public_ int sd_bus_release_name(sd_bus *bus, const char *name) { assert_return(bus, -EINVAL); assert_return(name, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(service_name_is_valid(name), -EINVAL); assert_return(name[0] != ':', -EINVAL); if (!bus->bus_client) return -EINVAL; /* Don't allow releasing the special driver and local names */ if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local")) return -EINVAL; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; if (bus->is_kernel) return bus_release_name_kernel(bus, name); else return bus_release_name_dbus1(bus, name); } static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) { struct kdbus_cmd_list cmd = { .size = sizeof(cmd), .flags = flags, }; struct kdbus_info *name_list, *name; uint64_t previous_id = 0; int r; /* Caller will free half-constructed list on failure... */ r = ioctl(bus->input_fd, KDBUS_CMD_LIST, &cmd); if (r < 0) return -errno; name_list = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset); KDBUS_FOREACH(name, name_list, cmd.list_size) { struct kdbus_item *item; if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id && !(name->flags & KDBUS_HELLO_ACTIVATOR)) { char *n; if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) { r = -ENOMEM; goto fail; } r = strv_consume(x, n); if (r < 0) goto fail; previous_id = name->id; } KDBUS_ITEM_FOREACH(item, name, items) { if (item->type == KDBUS_ITEM_OWNED_NAME) { if (service_name_is_valid(item->name.name)) { r = strv_extend(x, item->name.name); if (r < 0) { r = -ENOMEM; goto fail; } } } } } r = 0; fail: bus_kernel_cmd_free(bus, cmd.offset); return r; } static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) { _cleanup_strv_free_ char **x = NULL, **y = NULL; int r; if (acquired) { r = kernel_get_list(bus, KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES, &x); if (r < 0) return r; } if (activatable) { r = kernel_get_list(bus, KDBUS_LIST_ACTIVATORS, &y); if (r < 0) return r; *activatable = y; y = NULL; } if (acquired) { *acquired = x; x = NULL; } return 0; } static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_strv_free_ char **x = NULL, **y = NULL; int r; if (acquired) { r = sd_bus_call_method( bus, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames", NULL, &reply, NULL); if (r < 0) return r; r = sd_bus_message_read_strv(reply, &x); if (r < 0) return r; reply = sd_bus_message_unref(reply); } if (activatable) { r = sd_bus_call_method( bus, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListActivatableNames", NULL, &reply, NULL); if (r < 0) return r; r = sd_bus_message_read_strv(reply, &y); if (r < 0) return r; *activatable = y; y = NULL; } if (acquired) { *acquired = x; x = NULL; } return 0; } _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) { assert_return(bus, -EINVAL); assert_return(acquired || activatable, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!bus->bus_client) return -EINVAL; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; if (bus->is_kernel) return bus_list_names_kernel(bus, acquired, activatable); else return bus_list_names_dbus1(bus, acquired, activatable); } static int bus_populate_creds_from_items( sd_bus *bus, struct kdbus_info *info, uint64_t mask, sd_bus_creds *c) { struct kdbus_item *item; uint64_t m; int r; assert(bus); assert(info); assert(c); KDBUS_ITEM_FOREACH(item, info, items) { switch (item->type) { case KDBUS_ITEM_PIDS: if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) { c->pid = (pid_t) item->pids.pid; c->mask |= SD_BUS_CREDS_PID; } if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) { c->tid = (pid_t) item->pids.tid; c->mask |= SD_BUS_CREDS_TID; } if (mask & SD_BUS_CREDS_PPID) { if (item->pids.ppid > 0) { c->ppid = (pid_t) item->pids.ppid; c->mask |= SD_BUS_CREDS_PPID; } else if (item->pids.pid == 1) { /* The structure doesn't * really distinguish the case * where a process has no * parent and where we don't * know it because it could * not be translated due to * namespaces. However, we * know that PID 1 has no * parent process, hence let's * patch that in, manually. */ c->ppid = 0; c->mask |= SD_BUS_CREDS_PPID; } } break; case KDBUS_ITEM_CREDS: if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != UID_INVALID) { c->uid = (uid_t) item->creds.uid; c->mask |= SD_BUS_CREDS_UID; } if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != UID_INVALID) { c->euid = (uid_t) item->creds.euid; c->mask |= SD_BUS_CREDS_EUID; } if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != UID_INVALID) { c->suid = (uid_t) item->creds.suid; c->mask |= SD_BUS_CREDS_SUID; } if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != UID_INVALID) { c->fsuid = (uid_t) item->creds.fsuid; c->mask |= SD_BUS_CREDS_FSUID; } if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != GID_INVALID) { c->gid = (gid_t) item->creds.gid; c->mask |= SD_BUS_CREDS_GID; } if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != GID_INVALID) { c->egid = (gid_t) item->creds.egid; c->mask |= SD_BUS_CREDS_EGID; } if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != GID_INVALID) { c->sgid = (gid_t) item->creds.sgid; c->mask |= SD_BUS_CREDS_SGID; } if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != GID_INVALID) { c->fsgid = (gid_t) item->creds.fsgid; c->mask |= SD_BUS_CREDS_FSGID; } break; case KDBUS_ITEM_PID_COMM: if (mask & SD_BUS_CREDS_COMM) { r = free_and_strdup(&c->comm, item->str); if (r < 0) return r; c->mask |= SD_BUS_CREDS_COMM; } break; case KDBUS_ITEM_TID_COMM: if (mask & SD_BUS_CREDS_TID_COMM) { r = free_and_strdup(&c->tid_comm, item->str); if (r < 0) return r; c->mask |= SD_BUS_CREDS_TID_COMM; } break; case KDBUS_ITEM_EXE: if (mask & SD_BUS_CREDS_EXE) { r = free_and_strdup(&c->exe, item->str); if (r < 0) return r; c->mask |= SD_BUS_CREDS_EXE; } break; case KDBUS_ITEM_CMDLINE: if (mask & SD_BUS_CREDS_CMDLINE) { c->cmdline_size = item->size - offsetof(struct kdbus_item, data); c->cmdline = memdup(item->data, c->cmdline_size); if (!c->cmdline) return -ENOMEM; c->mask |= SD_BUS_CREDS_CMDLINE; } break; case KDBUS_ITEM_CGROUP: m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT | SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE | SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask; if (m) { r = free_and_strdup(&c->cgroup, item->str); if (r < 0) return r; r = bus_get_root_path(bus); if (r < 0) return r; r = free_and_strdup(&c->cgroup_root, bus->cgroup_root); if (r < 0) return r; c->mask |= m; } break; case KDBUS_ITEM_CAPS: m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask; if (m) { if (item->caps.last_cap != cap_last_cap() || item->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(item->caps.last_cap, 32U) * 4 * 4) return -EBADMSG; c->capability = memdup(item->caps.caps, item->size - offsetof(struct kdbus_item, caps.caps)); if (!c->capability) return -ENOMEM; c->mask |= m; } break; case KDBUS_ITEM_SECLABEL: if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) { r = free_and_strdup(&c->label, item->str); if (r < 0) return r; c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; } break; case KDBUS_ITEM_AUDIT: if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID) { c->audit_session_id = (uint32_t) item->audit.sessionid; c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID; } if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) { c->audit_login_uid = (uid_t) item->audit.loginuid; c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; } break; case KDBUS_ITEM_OWNED_NAME: if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) { r = strv_extend(&c->well_known_names, item->name.name); if (r < 0) return r; c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES; } break; case KDBUS_ITEM_CONN_DESCRIPTION: if (mask & SD_BUS_CREDS_DESCRIPTION) { r = free_and_strdup(&c->description, item->str); if (r < 0) return r; c->mask |= SD_BUS_CREDS_DESCRIPTION; } break; case KDBUS_ITEM_AUXGROUPS: if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) { size_t i, n; uid_t *g; n = (item->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t); g = new(gid_t, n); if (!g) return -ENOMEM; for (i = 0; i < n; i++) g[i] = item->data64[i]; free(c->supplementary_gids); c->supplementary_gids = g; c->n_supplementary_gids = n; c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS; } break; } } return 0; } int bus_get_name_creds_kdbus( sd_bus *bus, const char *name, uint64_t mask, bool allow_activator, sd_bus_creds **creds) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; struct kdbus_cmd_info *cmd; struct kdbus_info *conn_info; size_t size, l; uint64_t id; int r; if (streq(name, "org.freedesktop.DBus")) return -EOPNOTSUPP; r = bus_kernel_parse_unique_name(name, &id); if (r < 0) return r; if (r > 0) { size = offsetof(struct kdbus_cmd_info, items); cmd = alloca0_align(size, 8); cmd->id = id; } else { l = strlen(name) + 1; size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l); cmd = alloca0_align(size, 8); cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l; cmd->items[0].type = KDBUS_ITEM_NAME; memcpy(cmd->items[0].str, name, l); } /* If augmentation is on, and the bus didn't provide us * the bits we want, then ask for the PID/TID so that we * can read the rest from /proc. */ if ((mask & SD_BUS_CREDS_AUGMENT) && (mask & (SD_BUS_CREDS_PPID| SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID| SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID| SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE| SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID| SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS| SD_BUS_CREDS_SELINUX_CONTEXT| SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))) mask |= SD_BUS_CREDS_PID; cmd->size = size; cmd->attach_flags = attach_flags_to_kdbus(mask); r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd); if (r < 0) return -errno; conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset); /* Non-activated names are considered not available */ if (!allow_activator && (conn_info->flags & KDBUS_HELLO_ACTIVATOR)) { if (name[0] == ':') r = -ENXIO; else r = -ESRCH; goto fail; } c = bus_creds_new(); if (!c) { r = -ENOMEM; goto fail; } if (mask & SD_BUS_CREDS_UNIQUE_NAME) { if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) { r = -ENOMEM; goto fail; } c->mask |= SD_BUS_CREDS_UNIQUE_NAME; } /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of them in case the service has no names. This does not mean however that the list of owned names could not be acquired. Hence, let's explicitly clarify that the data is complete. */ c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES; r = bus_populate_creds_from_items(bus, conn_info, mask, c); if (r < 0) goto fail; r = bus_creds_add_more(c, mask, 0, 0); if (r < 0) goto fail; if (creds) { *creds = c; c = NULL; } r = 0; fail: bus_kernel_cmd_free(bus, cmd->offset); return r; } static int bus_get_name_creds_dbus1( sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **creds) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL; _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; const char *unique = NULL; pid_t pid = 0; int r; /* Only query the owner if the caller wants to know it or if * the caller just wants to check whether a name exists */ if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) { r = sd_bus_call_method( bus, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetNameOwner", NULL, &reply_unique, "s", name); if (r < 0) return r; r = sd_bus_message_read(reply_unique, "s", &unique); if (r < 0) return r; } if (mask != 0) { c = bus_creds_new(); if (!c) return -ENOMEM; if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) { c->unique_name = strdup(unique); if (!c->unique_name) return -ENOMEM; c->mask |= SD_BUS_CREDS_UNIQUE_NAME; } if ((mask & SD_BUS_CREDS_PID) || ((mask & SD_BUS_CREDS_AUGMENT) && (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID| SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID| SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE| SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID| SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS| SD_BUS_CREDS_SELINUX_CONTEXT| SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) { uint32_t u; r = sd_bus_call_method( bus, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetConnectionUnixProcessID", NULL, &reply, "s", unique ? unique : name); if (r < 0) return r; r = sd_bus_message_read(reply, "u", &u); if (r < 0) return r; pid = u; if (mask & SD_BUS_CREDS_PID) { c->pid = u; c->mask |= SD_BUS_CREDS_PID; } reply = sd_bus_message_unref(reply); } if (mask & SD_BUS_CREDS_EUID) { uint32_t u; r = sd_bus_call_method( bus, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetConnectionUnixUser", NULL, &reply, "s", unique ? unique : name); if (r < 0) return r; r = sd_bus_message_read(reply, "u", &u); if (r < 0) return r; c->euid = u; c->mask |= SD_BUS_CREDS_EUID; reply = sd_bus_message_unref(reply); } if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const void *p = NULL; size_t sz = 0; r = sd_bus_call_method( bus, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext", &error, &reply, "s", unique ? unique : name); if (r < 0) { if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown")) return r; } else { r = sd_bus_message_read_array(reply, 'y', &p, &sz); if (r < 0) return r; c->label = strndup(p, sz); if (!c->label) return -ENOMEM; c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; } } r = bus_creds_add_more(c, mask, pid, 0); if (r < 0) return r; } if (creds) { *creds = c; c = NULL; } return 0; } _public_ int sd_bus_get_name_creds( sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **creds) { assert_return(bus, -EINVAL); assert_return(name, -EINVAL); assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP); assert_return(mask == 0 || creds, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(service_name_is_valid(name), -EINVAL); if (!bus->bus_client) return -EINVAL; if (streq(name, "org.freedesktop.DBus.Local")) return -EINVAL; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; if (bus->is_kernel) return bus_get_name_creds_kdbus(bus, name, mask, false, creds); else return bus_get_name_creds_dbus1(bus, name, mask, creds); } static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; struct kdbus_cmd_info cmd = { .size = sizeof(struct kdbus_cmd_info), }; struct kdbus_info *creator_info; pid_t pid = 0; int r; c = bus_creds_new(); if (!c) return -ENOMEM; /* If augmentation is on, and the bus doesn't didn't allow us * to get the bits we want, then ask for the PID/TID so that we * can read the rest from /proc. */ if ((mask & SD_BUS_CREDS_AUGMENT) && (mask & (SD_BUS_CREDS_PPID| SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID| SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID| SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE| SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID| SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS| SD_BUS_CREDS_SELINUX_CONTEXT| SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))) mask |= SD_BUS_CREDS_PID; cmd.attach_flags = attach_flags_to_kdbus(mask); r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd); if (r < 0) return -errno; creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset); r = bus_populate_creds_from_items(bus, creator_info, mask, c); bus_kernel_cmd_free(bus, cmd.offset); if (r < 0) return r; r = bus_creds_add_more(c, mask, pid, 0); if (r < 0) return r; *ret = c; c = NULL; return 0; } static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; pid_t pid = 0; bool do_label; int r; assert(bus); do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT); /* Avoid allocating anything if we have no chance of returning useful data */ if (!bus->ucred_valid && !do_label) return -ENODATA; c = bus_creds_new(); if (!c) return -ENOMEM; if (bus->ucred_valid) { if (bus->ucred.pid > 0) { pid = c->pid = bus->ucred.pid; c->mask |= SD_BUS_CREDS_PID & mask; } if (bus->ucred.uid != UID_INVALID) { c->euid = bus->ucred.uid; c->mask |= SD_BUS_CREDS_EUID & mask; } if (bus->ucred.gid != GID_INVALID) { c->egid = bus->ucred.gid; c->mask |= SD_BUS_CREDS_EGID & mask; } } if (do_label) { c->label = strdup(bus->label); if (!c->label) return -ENOMEM; c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; } r = bus_creds_add_more(c, mask, pid, 0); if (r < 0) return r; *ret = c; c = NULL; return 0; } _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) { assert_return(bus, -EINVAL); assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP); assert_return(ret, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; if (bus->is_kernel) return bus_get_owner_creds_kdbus(bus, mask, ret); else return bus_get_owner_creds_dbus1(bus, mask, ret); } static int add_name_change_match(sd_bus *bus, uint64_t cookie, const char *name, const char *old_owner, const char *new_owner) { uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0; int is_name_id = -1, r; struct kdbus_item *item; assert(bus); /* If we encounter a match that could match against * NameOwnerChanged messages, then we need to create * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly * multiple if the match is underspecified. * * The NameOwnerChanged signals take three parameters with * unique or well-known names, but only some forms actually * exist: * * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE * * For the latter two the two unique names must be identical. * * */ if (name) { is_name_id = bus_kernel_parse_unique_name(name, &name_id); if (is_name_id < 0) return 0; } if (!isempty(old_owner)) { r = bus_kernel_parse_unique_name(old_owner, &old_owner_id); if (r < 0) return 0; if (r == 0) return 0; if (is_name_id > 0 && old_owner_id != name_id) return 0; } else old_owner_id = KDBUS_MATCH_ID_ANY; if (!isempty(new_owner)) { r = bus_kernel_parse_unique_name(new_owner, &new_owner_id); if (r < 0) return r; if (r == 0) return 0; if (is_name_id > 0 && new_owner_id != name_id) return 0; } else new_owner_id = KDBUS_MATCH_ID_ANY; if (is_name_id <= 0) { struct kdbus_cmd_match *m; size_t sz, l; /* If the name argument is missing or is a well-known * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} * matches for it */ l = name ? strlen(name) + 1 : 0; sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) + offsetof(struct kdbus_item, name_change) + offsetof(struct kdbus_notify_name_change, name) + l); m = alloca0_align(sz, 8); m->size = sz; m->cookie = cookie; item = m->items; item->size = offsetof(struct kdbus_item, name_change) + offsetof(struct kdbus_notify_name_change, name) + l; item->name_change.old_id.id = old_owner_id; item->name_change.new_id.id = new_owner_id; if (name) memcpy(item->name_change.name, name, l); /* If the old name is unset or empty, then * this can match against added names */ if (isempty(old_owner)) { item->type = KDBUS_ITEM_NAME_ADD; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); if (r < 0) return -errno; } /* If the new name is unset or empty, then * this can match against removed names */ if (isempty(new_owner)) { item->type = KDBUS_ITEM_NAME_REMOVE; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); if (r < 0) return -errno; } /* The CHANGE match we need in either case, because * what is reported as a name change by the kernel * might just be an owner change between starter and * normal clients. For userspace such a change should * be considered a removal/addition, hence let's * subscribe to this unconditionally. */ item->type = KDBUS_ITEM_NAME_CHANGE; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); if (r < 0) return -errno; } if (is_name_id != 0) { struct kdbus_cmd_match *m; uint64_t sz; /* If the name argument is missing or is a unique * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches * for it */ sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) + offsetof(struct kdbus_item, id_change) + sizeof(struct kdbus_notify_id_change)); m = alloca0_align(sz, 8); m->size = sz; m->cookie = cookie; item = m->items; item->size = offsetof(struct kdbus_item, id_change) + sizeof(struct kdbus_notify_id_change); item->id_change.id = name_id; /* If the old name is unset or empty, then this can * match against added ids */ if (isempty(old_owner)) { item->type = KDBUS_ITEM_ID_ADD; if (!isempty(new_owner)) item->id_change.id = new_owner_id; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); if (r < 0) return -errno; } /* If thew new name is unset or empty, then this can * match against removed ids */ if (isempty(new_owner)) { item->type = KDBUS_ITEM_ID_REMOVE; if (!isempty(old_owner)) item->id_change.id = old_owner_id; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); if (r < 0) return -errno; } } return 0; } int bus_add_match_internal_kernel( sd_bus *bus, struct bus_match_component *components, unsigned n_components, uint64_t cookie) { struct kdbus_cmd_match *m; struct kdbus_item *item; uint64_t *bloom; size_t sz; const char *sender = NULL; size_t sender_length = 0; uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY; bool using_bloom = false; unsigned i; bool matches_name_change = true; const char *name_change_arg[3] = {}; int r; assert(bus); /* Monitor streams don't support matches, make this a NOP */ if (bus->hello_flags & KDBUS_HELLO_MONITOR) return 0; bloom = alloca0(bus->bloom_size); sz = ALIGN8(offsetof(struct kdbus_cmd_match, items)); for (i = 0; i < n_components; i++) { struct bus_match_component *c = &components[i]; switch (c->type) { case BUS_MATCH_SENDER: if (!streq(c->value_str, "org.freedesktop.DBus")) matches_name_change = false; r = bus_kernel_parse_unique_name(c->value_str, &src_id); if (r < 0) return r; else if (r > 0) sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t)); else { sender = c->value_str; sender_length = strlen(sender); sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1); } break; case BUS_MATCH_MESSAGE_TYPE: if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL) matches_name_change = false; bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8)); using_bloom = true; break; case BUS_MATCH_INTERFACE: if (!streq(c->value_str, "org.freedesktop.DBus")) matches_name_change = false; bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str); using_bloom = true; break; case BUS_MATCH_MEMBER: if (!streq(c->value_str, "NameOwnerChanged")) matches_name_change = false; bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str); using_bloom = true; break; case BUS_MATCH_PATH: if (!streq(c->value_str, "/org/freedesktop/DBus")) matches_name_change = false; bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str); using_bloom = true; break; case BUS_MATCH_PATH_NAMESPACE: bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str); using_bloom = true; break; case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: { char buf[sizeof("arg")-1 + 2 + 1]; if (c->type - BUS_MATCH_ARG < 3) name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str; xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG); bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str); using_bloom = true; break; } case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: { char buf[sizeof("arg")-1 + 2 + sizeof("-has")]; xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS); bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str); using_bloom = true; break; } case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: /* * XXX: DBus spec defines arg[0..63]path= matching to be * a two-way glob. That is, if either string is a prefix * of the other, it matches. * This is really hard to realize in bloom-filters, as * we would have to create a bloom-match for each prefix * of @c->value_str. This is excessive, hence we just * ignore all those matches and accept everything from * the kernel. People should really avoid those matches. * If they're used in real-life some day, we will have * to properly support multiple-matches here. */ break; case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: { char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")]; xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE); bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str); using_bloom = true; break; } case BUS_MATCH_DESTINATION: /* * Kernel only supports matching on destination IDs, but * not on destination names. So just skip the * destination name restriction and verify it in * user-space on retrieval. */ r = bus_kernel_parse_unique_name(c->value_str, &dst_id); if (r < 0) return r; else if (r > 0) sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t)); /* if not a broadcast, it cannot be a name-change */ if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST) matches_name_change = false; break; case BUS_MATCH_ROOT: case BUS_MATCH_VALUE: case BUS_MATCH_LEAF: case _BUS_MATCH_NODE_TYPE_MAX: case _BUS_MATCH_NODE_TYPE_INVALID: assert_not_reached("Invalid match type?"); } } if (using_bloom) sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size); m = alloca0_align(sz, 8); m->size = sz; m->cookie = cookie; item = m->items; if (src_id != KDBUS_MATCH_ID_ANY) { item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t); item->type = KDBUS_ITEM_ID; item->id = src_id; item = KDBUS_ITEM_NEXT(item); } if (dst_id != KDBUS_MATCH_ID_ANY) { item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t); item->type = KDBUS_ITEM_DST_ID; item->id = dst_id; item = KDBUS_ITEM_NEXT(item); } if (using_bloom) { item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size; item->type = KDBUS_ITEM_BLOOM_MASK; memcpy(item->data64, bloom, bus->bloom_size); item = KDBUS_ITEM_NEXT(item); } if (sender) { item->size = offsetof(struct kdbus_item, str) + sender_length + 1; item->type = KDBUS_ITEM_NAME; memcpy(item->str, sender, sender_length + 1); } r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); if (r < 0) return -errno; if (matches_name_change) { /* If this match could theoretically match * NameOwnerChanged messages, we need to * install a second non-bloom filter explitly * for it */ r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]); if (r < 0) return r; } return 0; } #define internal_match(bus, m) \ ((bus)->hello_flags & KDBUS_HELLO_MONITOR \ ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \ : (m)) static int bus_add_match_internal_dbus1( sd_bus *bus, const char *match) { const char *e; assert(bus); assert(match); e = internal_match(bus, match); return sd_bus_call_method( bus, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "AddMatch", NULL, NULL, "s", e); } int bus_add_match_internal( sd_bus *bus, const char *match, struct bus_match_component *components, unsigned n_components, uint64_t cookie) { assert(bus); if (!bus->bus_client) return -EINVAL; if (bus->is_kernel) return bus_add_match_internal_kernel(bus, components, n_components, cookie); else return bus_add_match_internal_dbus1(bus, match); } int bus_remove_match_internal_kernel( sd_bus *bus, uint64_t cookie) { struct kdbus_cmd_match m = { .size = offsetof(struct kdbus_cmd_match, items), .cookie = cookie, }; int r; assert(bus); /* Monitor streams don't support matches, make this a NOP */ if (bus->hello_flags & KDBUS_HELLO_MONITOR) return 0; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m); if (r < 0) return -errno; return 0; } static int bus_remove_match_internal_dbus1( sd_bus *bus, const char *match) { const char *e; assert(bus); assert(match); e = internal_match(bus, match); return sd_bus_call_method( bus, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "RemoveMatch", NULL, NULL, "s", e); } int bus_remove_match_internal( sd_bus *bus, const char *match, uint64_t cookie) { assert(bus); if (!bus->bus_client) return -EINVAL; if (bus->is_kernel) return bus_remove_match_internal_kernel(bus, cookie); else return bus_remove_match_internal_dbus1(bus, match); } _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL; const char *mid; int r; assert_return(bus, -EINVAL); assert_return(name, -EINVAL); assert_return(machine, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(service_name_is_valid(name), -EINVAL); if (!bus->bus_client) return -EINVAL; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; if (streq_ptr(name, bus->unique_name)) return sd_id128_get_machine(machine); r = sd_bus_message_new_method_call( bus, &m, name, "/", "org.freedesktop.DBus.Peer", "GetMachineId"); if (r < 0) return r; r = sd_bus_message_set_auto_start(m, false); if (r < 0) return r; r = sd_bus_call(bus, m, 0, NULL, &reply); if (r < 0) return r; r = sd_bus_message_read(reply, "s", &mid); if (r < 0) return r; return sd_id128_from_string(mid, machine); } systemd-229/src/libsystemd/sd-bus/bus-control.h000066400000000000000000000024441265713322000216500ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "bus-match.h" int bus_add_match_internal(sd_bus *bus, const char *match, struct bus_match_component *components, unsigned n_components, uint64_t cookie); int bus_remove_match_internal(sd_bus *bus, const char *match, uint64_t cookie); int bus_add_match_internal_kernel(sd_bus *bus, struct bus_match_component *components, unsigned n_components, uint64_t cookie); int bus_remove_match_internal_kernel(sd_bus *bus, uint64_t cookie); int bus_get_name_creds_kdbus(sd_bus *bus, const char *name, uint64_t mask, bool allow_activator, sd_bus_creds **creds); systemd-229/src/libsystemd/sd-bus/bus-convenience.c000066400000000000000000000477611265713322000224720ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-internal.h" #include "bus-message.h" #include "bus-signature.h" #include "bus-type.h" #include "bus-util.h" #include "string-util.h" _public_ int sd_bus_emit_signal( sd_bus *bus, const char *path, const char *interface, const char *member, const char *types, ...) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; int r; assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; r = sd_bus_message_new_signal(bus, &m, path, interface, member); if (r < 0) return r; if (!isempty(types)) { va_list ap; va_start(ap, types); r = bus_message_append_ap(m, types, ap); va_end(ap); if (r < 0) return r; } return sd_bus_send(bus, m, NULL); } _public_ int sd_bus_call_method_async( sd_bus *bus, sd_bus_slot **slot, const char *destination, const char *path, const char *interface, const char *member, sd_bus_message_handler_t callback, void *userdata, const char *types, ...) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; int r; assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member); if (r < 0) return r; if (!isempty(types)) { va_list ap; va_start(ap, types); r = bus_message_append_ap(m, types, ap); va_end(ap); if (r < 0) return r; } return sd_bus_call_async(bus, slot, m, callback, userdata, 0); } _public_ int sd_bus_call_method( sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *error, sd_bus_message **reply, const char *types, ...) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; int r; bus_assert_return(bus, -EINVAL, error); bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); if (!BUS_IS_OPEN(bus->state)) { r = -ENOTCONN; goto fail; } r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member); if (r < 0) goto fail; if (!isempty(types)) { va_list ap; va_start(ap, types); r = bus_message_append_ap(m, types, ap); va_end(ap); if (r < 0) goto fail; } return sd_bus_call(bus, m, 0, error, reply); fail: return sd_bus_error_set_errno(error, r); } _public_ int sd_bus_reply_method_return( sd_bus_message *call, const char *types, ...) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; int r; assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); if (!BUS_IS_OPEN(call->bus->state)) return -ENOTCONN; if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; r = sd_bus_message_new_method_return(call, &m); if (r < 0) return r; if (!isempty(types)) { va_list ap; va_start(ap, types); r = bus_message_append_ap(m, types, ap); va_end(ap); if (r < 0) return r; } return sd_bus_send(call->bus, m, NULL); } _public_ int sd_bus_reply_method_error( sd_bus_message *call, const sd_bus_error *e) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; int r; assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); assert_return(sd_bus_error_is_set(e), -EINVAL); assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); if (!BUS_IS_OPEN(call->bus->state)) return -ENOTCONN; if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; r = sd_bus_message_new_method_error(call, &m, e); if (r < 0) return r; return sd_bus_send(call->bus, m, NULL); } _public_ int sd_bus_reply_method_errorf( sd_bus_message *call, const char *name, const char *format, ...) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; va_list ap; assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); if (!BUS_IS_OPEN(call->bus->state)) return -ENOTCONN; if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; va_start(ap, format); bus_error_setfv(&error, name, format, ap); va_end(ap); return sd_bus_reply_method_error(call, &error); } _public_ int sd_bus_reply_method_errno( sd_bus_message *call, int error, const sd_bus_error *p) { _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL; assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); if (!BUS_IS_OPEN(call->bus->state)) return -ENOTCONN; if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; if (sd_bus_error_is_set(p)) return sd_bus_reply_method_error(call, p); sd_bus_error_set_errno(&berror, error); return sd_bus_reply_method_error(call, &berror); } _public_ int sd_bus_reply_method_errnof( sd_bus_message *call, int error, const char *format, ...) { _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL; va_list ap; assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); if (!BUS_IS_OPEN(call->bus->state)) return -ENOTCONN; if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; va_start(ap, format); sd_bus_error_set_errnofv(&berror, error, format, ap); va_end(ap); return sd_bus_reply_method_error(call, &berror); } _public_ int sd_bus_get_property( sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *error, sd_bus_message **reply, const char *type) { sd_bus_message *rep = NULL; int r; bus_assert_return(bus, -EINVAL, error); bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); bus_assert_return(member_name_is_valid(member), -EINVAL, error); bus_assert_return(reply, -EINVAL, error); bus_assert_return(signature_is_single(type, false), -EINVAL, error); bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); if (!BUS_IS_OPEN(bus->state)) { r = -ENOTCONN; goto fail; } r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member); if (r < 0) return r; r = sd_bus_message_enter_container(rep, 'v', type); if (r < 0) { sd_bus_message_unref(rep); goto fail; } *reply = rep; return 0; fail: return sd_bus_error_set_errno(error, r); } _public_ int sd_bus_get_property_trivial( sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *error, char type, void *ptr) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; bus_assert_return(bus, -EINVAL, error); bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); bus_assert_return(member_name_is_valid(member), -EINVAL, error); bus_assert_return(bus_type_is_trivial(type), -EINVAL, error); bus_assert_return(ptr, -EINVAL, error); bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); if (!BUS_IS_OPEN(bus->state)) { r = -ENOTCONN; goto fail; } r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member); if (r < 0) return r; r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type)); if (r < 0) goto fail; r = sd_bus_message_read_basic(reply, type, ptr); if (r < 0) goto fail; return 0; fail: return sd_bus_error_set_errno(error, r); } _public_ int sd_bus_get_property_string( sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *error, char **ret) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *s; char *n; int r; bus_assert_return(bus, -EINVAL, error); bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); bus_assert_return(member_name_is_valid(member), -EINVAL, error); bus_assert_return(ret, -EINVAL, error); bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); if (!BUS_IS_OPEN(bus->state)) { r = -ENOTCONN; goto fail; } r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member); if (r < 0) return r; r = sd_bus_message_enter_container(reply, 'v', "s"); if (r < 0) goto fail; r = sd_bus_message_read_basic(reply, 's', &s); if (r < 0) goto fail; n = strdup(s); if (!n) { r = -ENOMEM; goto fail; } *ret = n; return 0; fail: return sd_bus_error_set_errno(error, r); } _public_ int sd_bus_get_property_strv( sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *error, char ***ret) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; bus_assert_return(bus, -EINVAL, error); bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); bus_assert_return(member_name_is_valid(member), -EINVAL, error); bus_assert_return(ret, -EINVAL, error); bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); if (!BUS_IS_OPEN(bus->state)) { r = -ENOTCONN; goto fail; } r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member); if (r < 0) return r; r = sd_bus_message_enter_container(reply, 'v', NULL); if (r < 0) goto fail; r = sd_bus_message_read_strv(reply, ret); if (r < 0) goto fail; return 0; fail: return sd_bus_error_set_errno(error, r); } _public_ int sd_bus_set_property( sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *error, const char *type, ...) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; va_list ap; int r; bus_assert_return(bus, -EINVAL, error); bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); bus_assert_return(member_name_is_valid(member), -EINVAL, error); bus_assert_return(signature_is_single(type, false), -EINVAL, error); bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); if (!BUS_IS_OPEN(bus->state)) { r = -ENOTCONN; goto fail; } r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set"); if (r < 0) goto fail; r = sd_bus_message_append(m, "ss", strempty(interface), member); if (r < 0) goto fail; r = sd_bus_message_open_container(m, 'v', type); if (r < 0) goto fail; va_start(ap, type); r = bus_message_append_ap(m, type, ap); va_end(ap); if (r < 0) goto fail; r = sd_bus_message_close_container(m); if (r < 0) goto fail; return sd_bus_call(bus, m, 0, error, NULL); fail: return sd_bus_error_set_errno(error, r); } _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) { sd_bus_creds *c; assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); if (!BUS_IS_OPEN(call->bus->state)) return -ENOTCONN; c = sd_bus_message_get_creds(call); /* All data we need? */ if (c && (mask & ~c->mask) == 0) { *creds = sd_bus_creds_ref(c); return 0; } /* No data passed? Or not enough data passed to retrieve the missing bits? */ if (!c || !(c->mask & SD_BUS_CREDS_PID)) { /* We couldn't read anything from the call, let's try * to get it from the sender or peer. */ if (call->sender) /* There's a sender, but the creds are * missing. This means we are talking via * dbus1, or are getting a message that was * sent to us via kdbus, but was converted * from a dbus1 message by the bus-proxy and * thus also lacks the creds. */ return sd_bus_get_name_creds(call->bus, call->sender, mask, creds); else /* There's no sender, hence we are on a dbus1 * direct connection. For direct connections * the credentials of the AF_UNIX peer matter, * which may be queried via * sd_bus_get_owner_creds(). */ return sd_bus_get_owner_creds(call->bus, mask, creds); } return bus_creds_extend_by_pid(c, mask, creds); } _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; uid_t our_uid; bool know_caps = false; int r; assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); if (!BUS_IS_OPEN(call->bus->state)) return -ENOTCONN; if (capability >= 0) { r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds); if (r < 0) return r; /* We cannot use augmented caps for authorization, * since then data is acquired raceful from * /proc. This can never actually happen, but let's * better be safe than sorry, and do an extra check * here. */ assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EFFECTIVE_CAPS) == 0, -EPERM); /* Note that not even on kdbus we might have the caps * field, due to faked identities, or namespace * translation issues. */ r = sd_bus_creds_has_effective_cap(creds, capability); if (r > 0) return 1; if (r == 0) know_caps = true; } else { r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID, &creds); if (r < 0) return r; } /* Now, check the UID, but only if the capability check wasn't * sufficient */ our_uid = getuid(); if (our_uid != 0 || !know_caps || capability < 0) { uid_t sender_uid; /* We cannot use augmented uid/euid for authorization, * since then data is acquired raceful from * /proc. This can never actually happen, but let's * better be safe than sorry, and do an extra check * here. */ assert_return((sd_bus_creds_get_augmented_mask(creds) & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID)) == 0, -EPERM); /* Try to use the EUID, if we have it. */ r = sd_bus_creds_get_euid(creds, &sender_uid); if (r < 0) r = sd_bus_creds_get_uid(creds, &sender_uid); if (r >= 0) { /* Sender has same UID as us, then let's grant access */ if (sender_uid == our_uid) return 1; /* Sender is root, we are not root. */ if (our_uid != 0 && sender_uid == 0) return 1; } } return 0; } systemd-229/src/libsystemd/sd-bus/bus-creds.c000066400000000000000000001264151265713322000212700ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "audit-util.h" #include "bus-creds.h" #include "bus-label.h" #include "bus-message.h" #include "bus-util.h" #include "capability-util.h" #include "cgroup-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "hexdecoct.h" #include "parse-util.h" #include "process-util.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "user-util.h" #include "util.h" enum { CAP_OFFSET_INHERITABLE = 0, CAP_OFFSET_PERMITTED = 1, CAP_OFFSET_EFFECTIVE = 2, CAP_OFFSET_BOUNDING = 3 }; void bus_creds_done(sd_bus_creds *c) { assert(c); /* For internal bus cred structures that are allocated by * something else */ free(c->session); free(c->unit); free(c->user_unit); free(c->slice); free(c->user_slice); free(c->unescaped_description); free(c->supplementary_gids); free(c->tty); free(c->well_known_names); /* note that this is an strv, but * we only free the array, not the * strings the array points to. The * full strv we only free if * c->allocated is set, see * below. */ strv_free(c->cmdline_array); } _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) { if (!c) return NULL; if (c->allocated) { assert(c->n_ref > 0); c->n_ref++; } else { sd_bus_message *m; /* If this is an embedded creds structure, then * forward ref counting to the message */ m = container_of(c, sd_bus_message, creds); sd_bus_message_ref(m); } return c; } _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) { if (!c) return NULL; if (c->allocated) { assert(c->n_ref > 0); c->n_ref--; if (c->n_ref == 0) { free(c->comm); free(c->tid_comm); free(c->exe); free(c->cmdline); free(c->cgroup); free(c->capability); free(c->label); free(c->unique_name); free(c->cgroup_root); free(c->description); c->supplementary_gids = mfree(c->supplementary_gids); c->well_known_names = strv_free(c->well_known_names); bus_creds_done(c); free(c); } } else { sd_bus_message *m; m = container_of(c, sd_bus_message, creds); sd_bus_message_unref(m); } return NULL; } _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) { assert_return(c, 0); return c->mask; } _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) { assert_return(c, 0); return c->augmented; } sd_bus_creds* bus_creds_new(void) { sd_bus_creds *c; c = new0(sd_bus_creds, 1); if (!c) return NULL; c->allocated = true; c->n_ref = 1; return c; } _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) { sd_bus_creds *c; int r; assert_return(pid >= 0, -EINVAL); assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP); assert_return(ret, -EINVAL); if (pid == 0) pid = getpid(); c = bus_creds_new(); if (!c) return -ENOMEM; r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0); if (r < 0) { sd_bus_creds_unref(c); return r; } /* Check if the process existed at all, in case we haven't * figured that out already */ if (!pid_is_alive(pid)) { sd_bus_creds_unref(c); return -ESRCH; } *ret = c; return 0; } _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) { assert_return(c, -EINVAL); assert_return(uid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_UID)) return -ENODATA; *uid = c->uid; return 0; } _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) { assert_return(c, -EINVAL); assert_return(euid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_EUID)) return -ENODATA; *euid = c->euid; return 0; } _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) { assert_return(c, -EINVAL); assert_return(suid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_SUID)) return -ENODATA; *suid = c->suid; return 0; } _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) { assert_return(c, -EINVAL); assert_return(fsuid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_FSUID)) return -ENODATA; *fsuid = c->fsuid; return 0; } _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) { assert_return(c, -EINVAL); assert_return(gid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_GID)) return -ENODATA; *gid = c->gid; return 0; } _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) { assert_return(c, -EINVAL); assert_return(egid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_EGID)) return -ENODATA; *egid = c->egid; return 0; } _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) { assert_return(c, -EINVAL); assert_return(sgid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_SGID)) return -ENODATA; *sgid = c->sgid; return 0; } _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) { assert_return(c, -EINVAL); assert_return(fsgid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_FSGID)) return -ENODATA; *fsgid = c->fsgid; return 0; } _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) { assert_return(c, -EINVAL); assert_return(gids, -EINVAL); if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)) return -ENODATA; *gids = c->supplementary_gids; return (int) c->n_supplementary_gids; } _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) { assert_return(c, -EINVAL); assert_return(pid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_PID)) return -ENODATA; assert(c->pid > 0); *pid = c->pid; return 0; } _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) { assert_return(c, -EINVAL); assert_return(ppid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_PPID)) return -ENODATA; /* PID 1 has no parent process. Let's distinguish the case of * not knowing and not having a parent process by the returned * error code. */ if (c->ppid == 0) return -ENXIO; *ppid = c->ppid; return 0; } _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) { assert_return(c, -EINVAL); assert_return(tid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_TID)) return -ENODATA; assert(c->tid > 0); *tid = c->tid; return 0; } _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) { assert_return(c, -EINVAL); if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT)) return -ENODATA; assert(c->label); *ret = c->label; return 0; } _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) { assert_return(c, -EINVAL); assert_return(ret, -EINVAL); if (!(c->mask & SD_BUS_CREDS_COMM)) return -ENODATA; assert(c->comm); *ret = c->comm; return 0; } _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) { assert_return(c, -EINVAL); assert_return(ret, -EINVAL); if (!(c->mask & SD_BUS_CREDS_TID_COMM)) return -ENODATA; assert(c->tid_comm); *ret = c->tid_comm; return 0; } _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) { assert_return(c, -EINVAL); assert_return(ret, -EINVAL); if (!(c->mask & SD_BUS_CREDS_EXE)) return -ENODATA; if (!c->exe) return -ENXIO; *ret = c->exe; return 0; } _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) { assert_return(c, -EINVAL); assert_return(ret, -EINVAL); if (!(c->mask & SD_BUS_CREDS_CGROUP)) return -ENODATA; assert(c->cgroup); *ret = c->cgroup; return 0; } _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) { int r; assert_return(c, -EINVAL); assert_return(ret, -EINVAL); if (!(c->mask & SD_BUS_CREDS_UNIT)) return -ENODATA; assert(c->cgroup); if (!c->unit) { const char *shifted; r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); if (r < 0) return r; r = cg_path_get_unit(shifted, (char**) &c->unit); if (r < 0) return r; } *ret = c->unit; return 0; } _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) { int r; assert_return(c, -EINVAL); assert_return(ret, -EINVAL); if (!(c->mask & SD_BUS_CREDS_USER_UNIT)) return -ENODATA; assert(c->cgroup); if (!c->user_unit) { const char *shifted; r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); if (r < 0) return r; r = cg_path_get_user_unit(shifted, (char**) &c->user_unit); if (r < 0) return r; } *ret = c->user_unit; return 0; } _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) { int r; assert_return(c, -EINVAL); assert_return(ret, -EINVAL); if (!(c->mask & SD_BUS_CREDS_SLICE)) return -ENODATA; assert(c->cgroup); if (!c->slice) { const char *shifted; r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); if (r < 0) return r; r = cg_path_get_slice(shifted, (char**) &c->slice); if (r < 0) return r; } *ret = c->slice; return 0; } _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) { int r; assert_return(c, -EINVAL); assert_return(ret, -EINVAL); if (!(c->mask & SD_BUS_CREDS_USER_SLICE)) return -ENODATA; assert(c->cgroup); if (!c->user_slice) { const char *shifted; r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); if (r < 0) return r; r = cg_path_get_user_slice(shifted, (char**) &c->user_slice); if (r < 0) return r; } *ret = c->user_slice; return 0; } _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) { int r; assert_return(c, -EINVAL); assert_return(ret, -EINVAL); if (!(c->mask & SD_BUS_CREDS_SESSION)) return -ENODATA; assert(c->cgroup); if (!c->session) { const char *shifted; r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); if (r < 0) return r; r = cg_path_get_session(shifted, (char**) &c->session); if (r < 0) return r; } *ret = c->session; return 0; } _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) { const char *shifted; int r; assert_return(c, -EINVAL); assert_return(uid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_OWNER_UID)) return -ENODATA; assert(c->cgroup); r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); if (r < 0) return r; return cg_path_get_owner_uid(shifted, uid); } _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) { assert_return(c, -EINVAL); if (!(c->mask & SD_BUS_CREDS_CMDLINE)) return -ENODATA; if (!c->cmdline) return -ENXIO; if (!c->cmdline_array) { c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size); if (!c->cmdline_array) return -ENOMEM; } *cmdline = c->cmdline_array; return 0; } _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) { assert_return(c, -EINVAL); assert_return(sessionid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID)) return -ENODATA; if (c->audit_session_id == AUDIT_SESSION_INVALID) return -ENXIO; *sessionid = c->audit_session_id; return 0; } _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) { assert_return(c, -EINVAL); assert_return(uid, -EINVAL); if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID)) return -ENODATA; if (c->audit_login_uid == UID_INVALID) return -ENXIO; *uid = c->audit_login_uid; return 0; } _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) { assert_return(c, -EINVAL); assert_return(ret, -EINVAL); if (!(c->mask & SD_BUS_CREDS_TTY)) return -ENODATA; if (!c->tty) return -ENXIO; *ret = c->tty; return 0; } _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) { assert_return(c, -EINVAL); assert_return(unique_name, -EINVAL); if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME)) return -ENODATA; *unique_name = c->unique_name; return 0; } _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) { assert_return(c, -EINVAL); assert_return(well_known_names, -EINVAL); if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)) return -ENODATA; /* As a special hack we return the bus driver as well-known * names list when this is requested. */ if (c->well_known_names_driver) { static const char* const wkn[] = { "org.freedesktop.DBus", NULL }; *well_known_names = (char**) wkn; return 0; } if (c->well_known_names_local) { static const char* const wkn[] = { "org.freedesktop.DBus.Local", NULL }; *well_known_names = (char**) wkn; return 0; } *well_known_names = c->well_known_names; return 0; } _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) { assert_return(c, -EINVAL); assert_return(ret, -EINVAL); if (!(c->mask & SD_BUS_CREDS_DESCRIPTION)) return -ENODATA; assert(c->description); if (!c->unescaped_description) { c->unescaped_description = bus_label_unescape(c->description); if (!c->unescaped_description) return -ENOMEM; } *ret = c->unescaped_description; return 0; } static int has_cap(sd_bus_creds *c, unsigned offset, int capability) { size_t sz; assert(c); assert(capability >= 0); assert(c->capability); if ((unsigned) capability > cap_last_cap()) return 0; sz = DIV_ROUND_UP(cap_last_cap(), 32U); return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability)); } _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) { assert_return(c, -EINVAL); assert_return(capability >= 0, -EINVAL); if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS)) return -ENODATA; return has_cap(c, CAP_OFFSET_EFFECTIVE, capability); } _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) { assert_return(c, -EINVAL); assert_return(capability >= 0, -EINVAL); if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS)) return -ENODATA; return has_cap(c, CAP_OFFSET_PERMITTED, capability); } _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) { assert_return(c, -EINVAL); assert_return(capability >= 0, -EINVAL); if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS)) return -ENODATA; return has_cap(c, CAP_OFFSET_INHERITABLE, capability); } _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) { assert_return(c, -EINVAL); assert_return(capability >= 0, -EINVAL); if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS)) return -ENODATA; return has_cap(c, CAP_OFFSET_BOUNDING, capability); } static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) { size_t sz, max; unsigned i, j; assert(c); assert(p); max = DIV_ROUND_UP(cap_last_cap(), 32U); p += strspn(p, WHITESPACE); sz = strlen(p); if (sz % 8 != 0) return -EINVAL; sz /= 8; if (sz > max) return -EINVAL; if (!c->capability) { c->capability = new0(uint32_t, max * 4); if (!c->capability) return -ENOMEM; } for (i = 0; i < sz; i ++) { uint32_t v = 0; for (j = 0; j < 8; ++j) { int t; t = unhexchar(*p++); if (t < 0) return -EINVAL; v = (v << 4) | t; } c->capability[offset * max + (sz - i - 1)] = v; } return 0; } int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { uint64_t missing; int r; assert(c); assert(c->allocated); if (!(mask & SD_BUS_CREDS_AUGMENT)) return 0; /* Try to retrieve PID from creds if it wasn't passed to us */ if (pid > 0) { c->pid = pid; c->mask |= SD_BUS_CREDS_PID; } else if (c->mask & SD_BUS_CREDS_PID) pid = c->pid; else /* Without pid we cannot do much... */ return 0; /* Try to retrieve TID from creds if it wasn't passed to us */ if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID)) tid = c->tid; /* Calculate what we shall and can add */ missing = mask & ~(c->mask|SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_AUGMENT); if (missing == 0) return 0; if (tid > 0) { c->tid = tid; c->mask |= SD_BUS_CREDS_TID; } if (missing & (SD_BUS_CREDS_PPID | SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID | SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID | SD_BUS_CREDS_SUPPLEMENTARY_GIDS | SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) { _cleanup_fclose_ FILE *f = NULL; const char *p; p = procfs_file_alloca(pid, "status"); f = fopen(p, "re"); if (!f) { if (errno == ENOENT) return -ESRCH; else if (errno != EPERM && errno != EACCES) return -errno; } else { char line[LINE_MAX]; FOREACH_LINE(line, f, return -errno) { truncate_nl(line); if (missing & SD_BUS_CREDS_PPID) { p = startswith(line, "PPid:"); if (p) { p += strspn(p, WHITESPACE); /* Explicitly check for PPID 0 (which is the case for PID 1) */ if (!streq(p, "0")) { r = parse_pid(p, &c->ppid); if (r < 0) return r; } else c->ppid = 0; c->mask |= SD_BUS_CREDS_PPID; continue; } } if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) { p = startswith(line, "Uid:"); if (p) { unsigned long uid, euid, suid, fsuid; p += strspn(p, WHITESPACE); if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4) return -EIO; if (missing & SD_BUS_CREDS_UID) c->uid = (uid_t) uid; if (missing & SD_BUS_CREDS_EUID) c->euid = (uid_t) euid; if (missing & SD_BUS_CREDS_SUID) c->suid = (uid_t) suid; if (missing & SD_BUS_CREDS_FSUID) c->fsuid = (uid_t) fsuid; c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID); continue; } } if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) { p = startswith(line, "Gid:"); if (p) { unsigned long gid, egid, sgid, fsgid; p += strspn(p, WHITESPACE); if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4) return -EIO; if (missing & SD_BUS_CREDS_GID) c->gid = (gid_t) gid; if (missing & SD_BUS_CREDS_EGID) c->egid = (gid_t) egid; if (missing & SD_BUS_CREDS_SGID) c->sgid = (gid_t) sgid; if (missing & SD_BUS_CREDS_FSGID) c->fsgid = (gid_t) fsgid; c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID); continue; } } if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) { p = startswith(line, "Groups:"); if (p) { size_t allocated = 0; for (;;) { unsigned long g; int n = 0; p += strspn(p, WHITESPACE); if (*p == 0) break; if (sscanf(p, "%lu%n", &g, &n) != 1) return -EIO; if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1)) return -ENOMEM; c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g; p += n; } c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS; continue; } } if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) { p = startswith(line, "CapEff:"); if (p) { r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p); if (r < 0) return r; c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS; continue; } } if (missing & SD_BUS_CREDS_PERMITTED_CAPS) { p = startswith(line, "CapPrm:"); if (p) { r = parse_caps(c, CAP_OFFSET_PERMITTED, p); if (r < 0) return r; c->mask |= SD_BUS_CREDS_PERMITTED_CAPS; continue; } } if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) { p = startswith(line, "CapInh:"); if (p) { r = parse_caps(c, CAP_OFFSET_INHERITABLE, p); if (r < 0) return r; c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS; continue; } } if (missing & SD_BUS_CREDS_BOUNDING_CAPS) { p = startswith(line, "CapBnd:"); if (p) { r = parse_caps(c, CAP_OFFSET_BOUNDING, p); if (r < 0) return r; c->mask |= SD_BUS_CREDS_BOUNDING_CAPS; continue; } } } } } if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) { const char *p; p = procfs_file_alloca(pid, "attr/current"); r = read_one_line_file(p, &c->label); if (r < 0) { if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES) return r; } else c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; } if (missing & SD_BUS_CREDS_COMM) { r = get_process_comm(pid, &c->comm); if (r < 0) { if (r != -EPERM && r != -EACCES) return r; } else c->mask |= SD_BUS_CREDS_COMM; } if (missing & SD_BUS_CREDS_EXE) { r = get_process_exe(pid, &c->exe); if (r == -ESRCH) { /* Unfortunately we cannot really distinguish * the case here where the process does not * exist, and /proc/$PID/exe being unreadable * because $PID is a kernel thread. Hence, * assume it is a kernel thread, and rely on * that this case is caught with a later * call. */ c->exe = NULL; c->mask |= SD_BUS_CREDS_EXE; } else if (r < 0) { if (r != -EPERM && r != -EACCES) return r; } else c->mask |= SD_BUS_CREDS_EXE; } if (missing & SD_BUS_CREDS_CMDLINE) { const char *p; p = procfs_file_alloca(pid, "cmdline"); r = read_full_file(p, &c->cmdline, &c->cmdline_size); if (r == -ENOENT) return -ESRCH; if (r < 0) { if (r != -EPERM && r != -EACCES) return r; } else { if (c->cmdline_size == 0) c->cmdline = mfree(c->cmdline); c->mask |= SD_BUS_CREDS_CMDLINE; } } if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) { _cleanup_free_ char *p = NULL; if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0) return -ENOMEM; r = read_one_line_file(p, &c->tid_comm); if (r == -ENOENT) return -ESRCH; if (r < 0) { if (r != -EPERM && r != -EACCES) return r; } else c->mask |= SD_BUS_CREDS_TID_COMM; } if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) { if (!c->cgroup) { r = cg_pid_get_path(NULL, pid, &c->cgroup); if (r < 0) { if (r != -EPERM && r != -EACCES) return r; } } if (!c->cgroup_root) { r = cg_get_root_path(&c->cgroup_root); if (r < 0) return r; } if (c->cgroup) c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID); } if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) { r = audit_session_from_pid(pid, &c->audit_session_id); if (r == -ENODATA) { /* ENODATA means: no audit session id assigned */ c->audit_session_id = AUDIT_SESSION_INVALID; c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID; } else if (r < 0) { if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES) return r; } else c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID; } if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) { r = audit_loginuid_from_pid(pid, &c->audit_login_uid); if (r == -ENODATA) { /* ENODATA means: no audit login uid assigned */ c->audit_login_uid = UID_INVALID; c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; } else if (r < 0) { if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES) return r; } else c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; } if (missing & SD_BUS_CREDS_TTY) { r = get_ctty(pid, NULL, &c->tty); if (r == -ENXIO) { /* ENXIO means: process has no controlling TTY */ c->tty = NULL; c->mask |= SD_BUS_CREDS_TTY; } else if (r < 0) { if (r != -EPERM && r != -EACCES && r != -ENOENT) return r; } else c->mask |= SD_BUS_CREDS_TTY; } /* In case only the exe path was to be read we cannot * distinguish the case where the exe path was unreadable * because the process was a kernel thread, or when the * process didn't exist at all. Hence, let's do a final check, * to be sure. */ if (!pid_is_alive(pid)) return -ESRCH; if (tid > 0 && tid != pid && !pid_is_unwaited(tid)) return -ESRCH; c->augmented = missing & c->mask; return 0; } int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *n = NULL; int r; assert(c); assert(ret); if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) { /* There's already all data we need, or augmentation * wasn't turned on. */ *ret = sd_bus_creds_ref(c); return 0; } n = bus_creds_new(); if (!n) return -ENOMEM; /* Copy the original data over */ if (c->mask & mask & SD_BUS_CREDS_PID) { n->pid = c->pid; n->mask |= SD_BUS_CREDS_PID; } if (c->mask & mask & SD_BUS_CREDS_TID) { n->tid = c->tid; n->mask |= SD_BUS_CREDS_TID; } if (c->mask & mask & SD_BUS_CREDS_PPID) { n->ppid = c->ppid; n->mask |= SD_BUS_CREDS_PPID; } if (c->mask & mask & SD_BUS_CREDS_UID) { n->uid = c->uid; n->mask |= SD_BUS_CREDS_UID; } if (c->mask & mask & SD_BUS_CREDS_EUID) { n->euid = c->euid; n->mask |= SD_BUS_CREDS_EUID; } if (c->mask & mask & SD_BUS_CREDS_SUID) { n->suid = c->suid; n->mask |= SD_BUS_CREDS_SUID; } if (c->mask & mask & SD_BUS_CREDS_FSUID) { n->fsuid = c->fsuid; n->mask |= SD_BUS_CREDS_FSUID; } if (c->mask & mask & SD_BUS_CREDS_GID) { n->gid = c->gid; n->mask |= SD_BUS_CREDS_GID; } if (c->mask & mask & SD_BUS_CREDS_EGID) { n->egid = c->egid; n->mask |= SD_BUS_CREDS_EGID; } if (c->mask & mask & SD_BUS_CREDS_SGID) { n->sgid = c->sgid; n->mask |= SD_BUS_CREDS_SGID; } if (c->mask & mask & SD_BUS_CREDS_FSGID) { n->fsgid = c->fsgid; n->mask |= SD_BUS_CREDS_FSGID; } if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) { if (c->supplementary_gids) { n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids); if (!n->supplementary_gids) return -ENOMEM; n->n_supplementary_gids = c->n_supplementary_gids; } else { n->supplementary_gids = NULL; n->n_supplementary_gids = 0; } n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS; } if (c->mask & mask & SD_BUS_CREDS_COMM) { assert(c->comm); n->comm = strdup(c->comm); if (!n->comm) return -ENOMEM; n->mask |= SD_BUS_CREDS_COMM; } if (c->mask & mask & SD_BUS_CREDS_TID_COMM) { assert(c->tid_comm); n->tid_comm = strdup(c->tid_comm); if (!n->tid_comm) return -ENOMEM; n->mask |= SD_BUS_CREDS_TID_COMM; } if (c->mask & mask & SD_BUS_CREDS_EXE) { if (c->exe) { n->exe = strdup(c->exe); if (!n->exe) return -ENOMEM; } else n->exe = NULL; n->mask |= SD_BUS_CREDS_EXE; } if (c->mask & mask & SD_BUS_CREDS_CMDLINE) { if (c->cmdline) { n->cmdline = memdup(c->cmdline, c->cmdline_size); if (!n->cmdline) return -ENOMEM; n->cmdline_size = c->cmdline_size; } else { n->cmdline = NULL; n->cmdline_size = 0; } n->mask |= SD_BUS_CREDS_CMDLINE; } if (c->mask & mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_OWNER_UID)) { assert(c->cgroup); n->cgroup = strdup(c->cgroup); if (!n->cgroup) return -ENOMEM; n->cgroup_root = strdup(c->cgroup_root); if (!n->cgroup_root) return -ENOMEM; n->mask |= mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_OWNER_UID); } if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) { assert(c->capability); n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4); if (!n->capability) return -ENOMEM; n->mask |= c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS); } if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) { assert(c->label); n->label = strdup(c->label); if (!n->label) return -ENOMEM; n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; } if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) { n->audit_session_id = c->audit_session_id; n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID; } if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) { n->audit_login_uid = c->audit_login_uid; n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; } if (c->mask & mask & SD_BUS_CREDS_TTY) { if (c->tty) { n->tty = strdup(c->tty); if (!n->tty) return -ENOMEM; } else n->tty = NULL; n->mask |= SD_BUS_CREDS_TTY; } if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) { assert(c->unique_name); n->unique_name = strdup(c->unique_name); if (!n->unique_name) return -ENOMEM; n->mask |= SD_BUS_CREDS_UNIQUE_NAME; } if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) { if (strv_isempty(c->well_known_names)) n->well_known_names = NULL; else { n->well_known_names = strv_copy(c->well_known_names); if (!n->well_known_names) return -ENOMEM; } n->well_known_names_driver = c->well_known_names_driver; n->well_known_names_local = c->well_known_names_local; n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES; } if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) { assert(c->description); n->description = strdup(c->description); if (!n->description) return -ENOMEM; n->mask |= SD_BUS_CREDS_DESCRIPTION; } n->augmented = c->augmented & n->mask; /* Get more data */ r = bus_creds_add_more(n, mask, 0, 0); if (r < 0) return r; *ret = n; n = NULL; return 0; } systemd-229/src/libsystemd/sd-bus/bus-creds.h000066400000000000000000000040361265713322000212670ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" struct sd_bus_creds { bool allocated; unsigned n_ref; uint64_t mask; uint64_t augmented; uid_t uid; uid_t euid; uid_t suid; uid_t fsuid; gid_t gid; gid_t egid; gid_t sgid; gid_t fsgid; gid_t *supplementary_gids; unsigned n_supplementary_gids; pid_t ppid; pid_t pid; pid_t tid; char *comm; char *tid_comm; char *exe; char *cmdline; size_t cmdline_size; char **cmdline_array; char *cgroup; char *session; char *unit; char *user_unit; char *slice; char *user_slice; char *tty; uint32_t *capability; uint32_t audit_session_id; uid_t audit_login_uid; char *label; char *unique_name; char **well_known_names; bool well_known_names_driver:1; bool well_known_names_local:1; char *cgroup_root; char *description, *unescaped_description; }; sd_bus_creds* bus_creds_new(void); void bus_creds_done(sd_bus_creds *c); int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid); int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret); systemd-229/src/libsystemd/sd-bus/bus-dump.c000066400000000000000000000533351265713322000211350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-dump.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-type.h" #include "cap-list.h" #include "capability-util.h" #include "fileio.h" #include "formats-util.h" #include "locale-util.h" #include "macro.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "util.h" static char *indent(unsigned level, unsigned flags) { char *p; unsigned n, i = 0; n = 0; if (flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY && level > 0) level -= 1; if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) n += 2; p = new(char, n + level*8 + 1); if (!p) return NULL; if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) { p[i++] = ' '; p[i++] = ' '; } memset(p + i, ' ', level*8); p[i + level*8] = 0; return p; } int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) { unsigned level = 1; int r; assert(m); if (!f) f = stdout; if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) { fprintf(f, "%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u Priority=%"PRIi64, m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() : m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() : m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", draw_special_char(DRAW_TRIANGULAR_BULLET), ansi_normal(), ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_normal(), m->header->endian, m->header->flags, m->header->version, m->priority); /* Display synthetic message serial number in a more readable * format than (uint32_t) -1 */ if (BUS_MESSAGE_COOKIE(m) == 0xFFFFFFFFULL) fprintf(f, " Cookie=-1"); else fprintf(f, " Cookie=%" PRIu64, BUS_MESSAGE_COOKIE(m)); if (m->reply_cookie != 0) fprintf(f, " ReplyCookie=%" PRIu64, m->reply_cookie); fputs("\n", f); if (m->sender) fprintf(f, " Sender=%s%s%s", ansi_highlight(), m->sender, ansi_normal()); if (m->destination) fprintf(f, " Destination=%s%s%s", ansi_highlight(), m->destination, ansi_normal()); if (m->path) fprintf(f, " Path=%s%s%s", ansi_highlight(), m->path, ansi_normal()); if (m->interface) fprintf(f, " Interface=%s%s%s", ansi_highlight(), m->interface, ansi_normal()); if (m->member) fprintf(f, " Member=%s%s%s", ansi_highlight(), m->member, ansi_normal()); if (m->sender || m->destination || m->path || m->interface || m->member) fputs("\n", f); if (sd_bus_error_is_set(&m->error)) fprintf(f, " ErrorName=%s%s%s" " ErrorMessage=%s\"%s\"%s\n", ansi_highlight_red(), strna(m->error.name), ansi_normal(), ansi_highlight_red(), strna(m->error.message), ansi_normal()); if (m->monotonic != 0) fprintf(f, " Monotonic="USEC_FMT, m->monotonic); if (m->realtime != 0) fprintf(f, " Realtime="USEC_FMT, m->realtime); if (m->seqnum != 0) fprintf(f, " SequenceNumber=%"PRIu64, m->seqnum); if (m->monotonic != 0 || m->realtime != 0 || m->seqnum != 0) fputs("\n", f); bus_creds_dump(&m->creds, f, true); } r = sd_bus_message_rewind(m, !(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)); if (r < 0) return log_error_errno(r, "Failed to rewind: %m"); if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)) { _cleanup_free_ char *prefix = NULL; prefix = indent(0, flags); if (!prefix) return log_oom(); fprintf(f, "%sMESSAGE \"%s\" {\n", prefix, strempty(m->root_container.signature)); } for (;;) { _cleanup_free_ char *prefix = NULL; const char *contents = NULL; char type; union { uint8_t u8; uint16_t u16; int16_t s16; uint32_t u32; int32_t s32; uint64_t u64; int64_t s64; double d64; const char *string; int i; } basic; r = sd_bus_message_peek_type(m, &type, &contents); if (r < 0) return log_error_errno(r, "Failed to peek type: %m"); if (r == 0) { if (level <= 1) break; r = sd_bus_message_exit_container(m); if (r < 0) return log_error_errno(r, "Failed to exit container: %m"); level--; prefix = indent(level, flags); if (!prefix) return log_oom(); fprintf(f, "%s};\n", prefix); continue; } prefix = indent(level, flags); if (!prefix) return log_oom(); if (bus_type_is_container(type) > 0) { r = sd_bus_message_enter_container(m, type, contents); if (r < 0) return log_error_errno(r, "Failed to enter container: %m"); if (type == SD_BUS_TYPE_ARRAY) fprintf(f, "%sARRAY \"%s\" {\n", prefix, contents); else if (type == SD_BUS_TYPE_VARIANT) fprintf(f, "%sVARIANT \"%s\" {\n", prefix, contents); else if (type == SD_BUS_TYPE_STRUCT) fprintf(f, "%sSTRUCT \"%s\" {\n", prefix, contents); else if (type == SD_BUS_TYPE_DICT_ENTRY) fprintf(f, "%sDICT_ENTRY \"%s\" {\n", prefix, contents); level ++; continue; } r = sd_bus_message_read_basic(m, type, &basic); if (r < 0) return log_error_errno(r, "Failed to get basic: %m"); assert(r > 0); switch (type) { case SD_BUS_TYPE_BYTE: fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_normal()); break; case SD_BUS_TYPE_BOOLEAN: fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), true_false(basic.i), ansi_normal()); break; case SD_BUS_TYPE_INT16: fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_normal()); break; case SD_BUS_TYPE_UINT16: fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_normal()); break; case SD_BUS_TYPE_INT32: fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_normal()); break; case SD_BUS_TYPE_UINT32: fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_normal()); break; case SD_BUS_TYPE_INT64: fprintf(f, "%sINT64 %s%"PRIi64"%s;\n", prefix, ansi_highlight(), basic.s64, ansi_normal()); break; case SD_BUS_TYPE_UINT64: fprintf(f, "%sUINT64 %s%"PRIu64"%s;\n", prefix, ansi_highlight(), basic.u64, ansi_normal()); break; case SD_BUS_TYPE_DOUBLE: fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_normal()); break; case SD_BUS_TYPE_STRING: fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_normal()); break; case SD_BUS_TYPE_OBJECT_PATH: fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_normal()); break; case SD_BUS_TYPE_SIGNATURE: fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_normal()); break; case SD_BUS_TYPE_UNIX_FD: fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_normal()); break; default: assert_not_reached("Unknown basic type."); } } if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)) { _cleanup_free_ char *prefix = NULL; prefix = indent(0, flags); if (!prefix) return log_oom(); fprintf(f, "%s};\n\n", prefix); } return 0; } static void dump_capabilities( sd_bus_creds *c, FILE *f, const char *name, bool terse, int (*has)(sd_bus_creds *c, int capability)) { unsigned long i, last_cap; unsigned n = 0; int r; assert(c); assert(f); assert(name); assert(has); i = 0; r = has(c, i); if (r < 0) return; fprintf(f, "%s%s=%s", terse ? " " : "", name, terse ? "" : ansi_highlight()); last_cap = cap_last_cap(); for (;;) { if (r > 0) { if (n > 0) fputc(' ', f); if (n % 4 == 3) fprintf(f, terse ? "\n " : "\n "); fprintf(f, "%s", strna(capability_to_name(i))); n++; } i++; if (i > last_cap) break; r = has(c, i); } fputs("\n", f); if (!terse) fputs(ansi_normal(), f); } int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) { uid_t owner, audit_loginuid; uint32_t audit_sessionid; char **cmdline = NULL, **well_known = NULL; const char *prefix, *color, *suffix, *s; int r, q, v, w, z; assert(c); if (!f) f = stdout; if (terse) { prefix = " "; suffix = ""; color = ""; } else { const char *off; prefix = ""; color = ansi_highlight(); off = ansi_normal(); suffix = strjoina(off, "\n"); } if (c->mask & SD_BUS_CREDS_PID) fprintf(f, "%sPID=%s"PID_FMT"%s", prefix, color, c->pid, suffix); if (c->mask & SD_BUS_CREDS_TID) fprintf(f, "%sTID=%s"PID_FMT"%s", prefix, color, c->tid, suffix); if (c->mask & SD_BUS_CREDS_PPID) { if (c->ppid == 0) fprintf(f, "%sPPID=%sn/a%s", prefix, color, suffix); else fprintf(f, "%sPPID=%s"PID_FMT"%s", prefix, color, c->ppid, suffix); } if (c->mask & SD_BUS_CREDS_TTY) fprintf(f, "%sTTY=%s%s%s", prefix, color, strna(c->tty), suffix); if (terse && ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID|SD_BUS_CREDS_TTY)))) fputs("\n", f); if (c->mask & SD_BUS_CREDS_UID) fprintf(f, "%sUID=%s"UID_FMT"%s", prefix, color, c->uid, suffix); if (c->mask & SD_BUS_CREDS_EUID) fprintf(f, "%sEUID=%s"UID_FMT"%s", prefix, color, c->euid, suffix); if (c->mask & SD_BUS_CREDS_SUID) fprintf(f, "%sSUID=%s"UID_FMT"%s", prefix, color, c->suid, suffix); if (c->mask & SD_BUS_CREDS_FSUID) fprintf(f, "%sFSUID=%s"UID_FMT"%s", prefix, color, c->fsuid, suffix); r = sd_bus_creds_get_owner_uid(c, &owner); if (r >= 0) fprintf(f, "%sOwnerUID=%s"UID_FMT"%s", prefix, color, owner, suffix); if (c->mask & SD_BUS_CREDS_GID) fprintf(f, "%sGID=%s"GID_FMT"%s", prefix, color, c->gid, suffix); if (c->mask & SD_BUS_CREDS_EGID) fprintf(f, "%sEGID=%s"GID_FMT"%s", prefix, color, c->egid, suffix); if (c->mask & SD_BUS_CREDS_SGID) fprintf(f, "%sSGID=%s"GID_FMT"%s", prefix, color, c->sgid, suffix); if (c->mask & SD_BUS_CREDS_FSGID) fprintf(f, "%sFSGID=%s"GID_FMT"%s", prefix, color, c->fsgid, suffix); if (c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) { unsigned i; fprintf(f, "%sSupplementaryGIDs=%s", prefix, color); for (i = 0; i < c->n_supplementary_gids; i++) fprintf(f, "%s" GID_FMT, i > 0 ? " " : "", c->supplementary_gids[i]); fprintf(f, "%s", suffix); } if (terse && ((c->mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID| SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID| SD_BUS_CREDS_SUPPLEMENTARY_GIDS)) || r >= 0)) fputs("\n", f); if (c->mask & SD_BUS_CREDS_COMM) fprintf(f, "%sComm=%s%s%s", prefix, color, c->comm, suffix); if (c->mask & SD_BUS_CREDS_TID_COMM) fprintf(f, "%sTIDComm=%s%s%s", prefix, color, c->tid_comm, suffix); if (c->mask & SD_BUS_CREDS_EXE) fprintf(f, "%sExe=%s%s%s", prefix, color, strna(c->exe), suffix); if (terse && (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM))) fputs("\n", f); r = sd_bus_creds_get_cmdline(c, &cmdline); if (r >= 0) { char **i; fprintf(f, "%sCommandLine=%s", prefix, color); STRV_FOREACH(i, cmdline) { if (i != cmdline) fputc(' ', f); fputs(*i, f); } fprintf(f, "%s", suffix); } else if (r != -ENODATA) fprintf(f, "%sCommandLine=%sn/a%s", prefix, color, suffix); if (c->mask & SD_BUS_CREDS_SELINUX_CONTEXT) fprintf(f, "%sLabel=%s%s%s", prefix, color, c->label, suffix); if (c->mask & SD_BUS_CREDS_DESCRIPTION) fprintf(f, "%sDescription=%s%s%s", prefix, color, c->description, suffix); if (terse && (c->mask & (SD_BUS_CREDS_SELINUX_CONTEXT|SD_BUS_CREDS_DESCRIPTION))) fputs("\n", f); if (c->mask & SD_BUS_CREDS_CGROUP) fprintf(f, "%sCGroup=%s%s%s", prefix, color, c->cgroup, suffix); s = NULL; r = sd_bus_creds_get_unit(c, &s); if (r != -ENODATA) fprintf(f, "%sUnit=%s%s%s", prefix, color, strna(s), suffix); s = NULL; v = sd_bus_creds_get_slice(c, &s); if (v != -ENODATA) fprintf(f, "%sSlice=%s%s%s", prefix, color, strna(s), suffix); s = NULL; q = sd_bus_creds_get_user_unit(c, &s); if (q != -ENODATA) fprintf(f, "%sUserUnit=%s%s%s", prefix, color, strna(s), suffix); s = NULL; w = sd_bus_creds_get_user_slice(c, &s); if (w != -ENODATA) fprintf(f, "%sUserSlice=%s%s%s", prefix, color, strna(s), suffix); s = NULL; z = sd_bus_creds_get_session(c, &s); if (z != -ENODATA) fprintf(f, "%sSession=%s%s%s", prefix, color, strna(s), suffix); if (terse && ((c->mask & SD_BUS_CREDS_CGROUP) || r != -ENODATA || q != -ENODATA || v != -ENODATA || w != -ENODATA || z != -ENODATA)) fputs("\n", f); r = sd_bus_creds_get_audit_login_uid(c, &audit_loginuid); if (r >= 0) fprintf(f, "%sAuditLoginUID=%s"UID_FMT"%s", prefix, color, audit_loginuid, suffix); else if (r != -ENODATA) fprintf(f, "%sAuditLoginUID=%sn/a%s", prefix, color, suffix); q = sd_bus_creds_get_audit_session_id(c, &audit_sessionid); if (q >= 0) fprintf(f, "%sAuditSessionID=%s%"PRIu32"%s", prefix, color, audit_sessionid, suffix); else if (q != -ENODATA) fprintf(f, "%sAuditSessionID=%sn/a%s", prefix, color, suffix); if (terse && (r != -ENODATA || q != -ENODATA)) fputs("\n", f); if (c->mask & SD_BUS_CREDS_UNIQUE_NAME) fprintf(f, "%sUniqueName=%s%s%s", prefix, color, c->unique_name, suffix); if (sd_bus_creds_get_well_known_names(c, &well_known) >= 0) { char **i; fprintf(f, "%sWellKnownNames=%s", prefix, color); STRV_FOREACH(i, well_known) { if (i != well_known) fputc(' ', f); fputs(*i, f); } fprintf(f, "%s", suffix); } if (terse && (c->mask & SD_BUS_CREDS_UNIQUE_NAME || well_known)) fputc('\n', f); dump_capabilities(c, f, "EffectiveCapabilities", terse, sd_bus_creds_has_effective_cap); dump_capabilities(c, f, "PermittedCapabilities", terse, sd_bus_creds_has_permitted_cap); dump_capabilities(c, f, "InheritableCapabilities", terse, sd_bus_creds_has_inheritable_cap); dump_capabilities(c, f, "BoundingCapabilities", terse, sd_bus_creds_has_bounding_cap); return 0; } /* * For details about the file format, see: * * http://wiki.wireshark.org/Development/LibpcapFileFormat */ typedef struct _packed_ pcap_hdr_s { uint32_t magic_number; /* magic number */ uint16_t version_major; /* major version number */ uint16_t version_minor; /* minor version number */ int32_t thiszone; /* GMT to local correction */ uint32_t sigfigs; /* accuracy of timestamps */ uint32_t snaplen; /* max length of captured packets, in octets */ uint32_t network; /* data link type */ } pcap_hdr_t ; typedef struct _packed_ pcaprec_hdr_s { uint32_t ts_sec; /* timestamp seconds */ uint32_t ts_usec; /* timestamp microseconds */ uint32_t incl_len; /* number of octets of packet saved in file */ uint32_t orig_len; /* actual length of packet */ } pcaprec_hdr_t; int bus_pcap_header(size_t snaplen, FILE *f) { pcap_hdr_t hdr = { .magic_number = 0xa1b2c3d4U, .version_major = 2, .version_minor = 4, .thiszone = 0, /* UTC */ .sigfigs = 0, .network = 231, /* D-Bus */ }; if (!f) f = stdout; assert(snaplen > 0); assert((size_t) (uint32_t) snaplen == snaplen); hdr.snaplen = (uint32_t) snaplen; fwrite(&hdr, 1, sizeof(hdr), f); return fflush_and_check(f); } int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) { struct bus_body_part *part; pcaprec_hdr_t hdr = {}; struct timeval tv; unsigned i; size_t w; if (!f) f = stdout; assert(m); assert(snaplen > 0); assert((size_t) (uint32_t) snaplen == snaplen); if (m->realtime != 0) timeval_store(&tv, m->realtime); else assert_se(gettimeofday(&tv, NULL) >= 0); hdr.ts_sec = tv.tv_sec; hdr.ts_usec = tv.tv_usec; hdr.orig_len = BUS_MESSAGE_SIZE(m); hdr.incl_len = MIN(hdr.orig_len, snaplen); /* write the pcap header */ fwrite(&hdr, 1, sizeof(hdr), f); /* write the dbus header */ w = MIN(BUS_MESSAGE_BODY_BEGIN(m), snaplen); fwrite(m->header, 1, w, f); snaplen -= w; /* write the dbus body */ MESSAGE_FOREACH_PART(part, i, m) { if (snaplen <= 0) break; w = MIN(part->size, snaplen); fwrite(part->data, 1, w, f); snaplen -= w; } return fflush_and_check(f); } systemd-229/src/libsystemd/sd-bus/bus-dump.h000066400000000000000000000021571265713322000211360ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-bus.h" enum { BUS_MESSAGE_DUMP_WITH_HEADER = 1, BUS_MESSAGE_DUMP_SUBTREE_ONLY = 2, }; int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags); int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse); int bus_pcap_header(size_t snaplen, FILE *f); int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f); systemd-229/src/libsystemd/sd-bus/bus-error.c000066400000000000000000000471171265713322000213220ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-error.h" #include "errno-list.h" #include "string-util.h" #include "util.h" BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = { SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Failed", EACCES), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoMemory", ENOMEM), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.ServiceUnknown", EHOSTUNREACH), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NameHasNoOwner", ENXIO), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoReply", ETIMEDOUT), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.IOError", EIO), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.BadAddress", EADDRNOTAVAIL), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NotSupported", EOPNOTSUPP), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.LimitsExceeded", ENOBUFS), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AccessDenied", EACCES), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AuthFailed", EACCES), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InteractiveAuthorizationRequired", EACCES), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoServer", EHOSTDOWN), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Timeout", ETIMEDOUT), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoNetwork", ENONET), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AddressInUse", EADDRINUSE), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Disconnected", ECONNRESET), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidArgs", EINVAL), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.FileNotFound", ENOENT), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.FileExists", EEXIST), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownMethod", EBADR), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownObject", EBADR), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownInterface", EBADR), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownProperty", EBADR), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.PropertyReadOnly", EROFS), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnixProcessIdUnknown", ESRCH), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidSignature", EINVAL), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InconsistentMessage", EBADMSG), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.TimedOut", ETIMEDOUT), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.MatchRuleInvalid", EINVAL), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidFileContent", EINVAL), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.MatchRuleNotFound", ENOENT), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown", ESRCH), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.ObjectPathInUse", EBUSY), SD_BUS_ERROR_MAP_END }; /* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section. * Hide them; for currently unknown reasons they get exported to the shared libries * even without being listed in the sym file. */ extern const sd_bus_error_map __start_BUS_ERROR_MAP[] _hidden_; extern const sd_bus_error_map __stop_BUS_ERROR_MAP[] _hidden_; /* Additional maps registered with sd_bus_error_add_map() are in this * NULL terminated array */ static const sd_bus_error_map **additional_error_maps = NULL; static int bus_error_name_to_errno(const char *name) { const sd_bus_error_map **map, *m; const char *p; int r; if (!name) return EINVAL; p = startswith(name, "System.Error."); if (p) { r = errno_from_name(p); if (r < 0) return EIO; return r; } if (additional_error_maps) for (map = additional_error_maps; *map; map++) for (m = *map;; m++) { /* For additional error maps the end marker is actually the end marker */ if (m->code == BUS_ERROR_MAP_END_MARKER) break; if (streq(m->name, name)) return m->code; } m = __start_BUS_ERROR_MAP; while (m < __stop_BUS_ERROR_MAP) { /* For magic ELF error maps, the end marker might * appear in the middle of things, since multiple maps * might appear in the same section. Hence, let's skip * over it, but realign the pointer to the next 8 byte * boundary, which is the selected alignment for the * arrays. */ if (m->code == BUS_ERROR_MAP_END_MARKER) { m = ALIGN8_PTR(m+1); continue; } if (streq(m->name, name)) return m->code; m++; } return EIO; } static sd_bus_error errno_to_bus_error_const(int error) { if (error < 0) error = -error; switch (error) { case ENOMEM: return BUS_ERROR_OOM; case EPERM: case EACCES: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_ACCESS_DENIED, "Access denied"); case EINVAL: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid argument"); case ESRCH: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, "No such process"); case ENOENT: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_NOT_FOUND, "File not found"); case EEXIST: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "File exists"); case ETIMEDOUT: case ETIME: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_TIMEOUT, "Timed out"); case EIO: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_IO_ERROR, "Input/output error"); case ENETRESET: case ECONNABORTED: case ECONNRESET: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_DISCONNECTED, "Disconnected"); case EOPNOTSUPP: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NOT_SUPPORTED, "Not supported"); case EADDRNOTAVAIL: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_BAD_ADDRESS, "Address not available"); case ENOBUFS: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_LIMITS_EXCEEDED, "Limits exceeded"); case EADDRINUSE: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_ADDRESS_IN_USE, "Address in use"); case EBADMSG: return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Inconsistent message"); } return SD_BUS_ERROR_NULL; } static int errno_to_bus_error_name_new(int error, char **ret) { const char *name; char *n; if (error < 0) error = -error; name = errno_to_name(error); if (!name) return 0; n = strappend("System.Error.", name); if (!n) return -ENOMEM; *ret = n; return 1; } bool bus_error_is_dirty(sd_bus_error *e) { if (!e) return false; return e->name || e->message || e->_need_free != 0; } _public_ void sd_bus_error_free(sd_bus_error *e) { if (!e) return; if (e->_need_free > 0) { free((void*) e->name); free((void*) e->message); } e->name = e->message = NULL; e->_need_free = 0; } _public_ int sd_bus_error_set(sd_bus_error *e, const char *name, const char *message) { if (!name) return 0; if (!e) goto finish; assert_return(!bus_error_is_dirty(e), -EINVAL); e->name = strdup(name); if (!e->name) { *e = BUS_ERROR_OOM; return -ENOMEM; } if (message) e->message = strdup(message); e->_need_free = 1; finish: return -bus_error_name_to_errno(name); } int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_list ap) { if (!name) return 0; if (e) { assert_return(!bus_error_is_dirty(e), -EINVAL); e->name = strdup(name); if (!e->name) { *e = BUS_ERROR_OOM; return -ENOMEM; } /* If we hit OOM on formatting the pretty message, we ignore * this, since we at least managed to write the error name */ if (format) (void) vasprintf((char**) &e->message, format, ap); e->_need_free = 1; } return -bus_error_name_to_errno(name); } _public_ int sd_bus_error_setf(sd_bus_error *e, const char *name, const char *format, ...) { if (format) { int r; va_list ap; va_start(ap, format); r = bus_error_setfv(e, name, format, ap); va_end(ap); return r; } return sd_bus_error_set(e, name, NULL); } _public_ int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e) { if (!sd_bus_error_is_set(e)) return 0; if (!dest) goto finish; assert_return(!bus_error_is_dirty(dest), -EINVAL); /* * _need_free < 0 indicates that the error is temporarily const, needs deep copying * _need_free == 0 indicates that the error is perpetually const, needs no deep copying * _need_free > 0 indicates that the error is fully dynamic, needs deep copying */ if (e->_need_free == 0) *dest = *e; else { dest->name = strdup(e->name); if (!dest->name) { *dest = BUS_ERROR_OOM; return -ENOMEM; } if (e->message) dest->message = strdup(e->message); dest->_need_free = 1; } finish: return -bus_error_name_to_errno(e->name); } _public_ int sd_bus_error_set_const(sd_bus_error *e, const char *name, const char *message) { if (!name) return 0; if (!e) goto finish; assert_return(!bus_error_is_dirty(e), -EINVAL); *e = SD_BUS_ERROR_MAKE_CONST(name, message); finish: return -bus_error_name_to_errno(name); } _public_ int sd_bus_error_is_set(const sd_bus_error *e) { if (!e) return 0; return !!e->name; } _public_ int sd_bus_error_has_name(const sd_bus_error *e, const char *name) { if (!e) return 0; return streq_ptr(e->name, name); } _public_ int sd_bus_error_get_errno(const sd_bus_error* e) { if (!e) return 0; if (!e->name) return 0; return bus_error_name_to_errno(e->name); } static void bus_error_strerror(sd_bus_error *e, int error) { size_t k = 64; char *m; assert(e); for (;;) { char *x; m = new(char, k); if (!m) return; errno = 0; x = strerror_r(error, m, k); if (errno == ERANGE || strlen(x) >= k - 1) { free(m); k *= 2; continue; } if (errno) { free(m); return; } if (x == m) { if (e->_need_free > 0) { /* Error is already dynamic, let's just update the message */ free((char*) e->message); e->message = x; } else { char *t; /* Error was const so far, let's make it dynamic, if we can */ t = strdup(e->name); if (!t) { free(m); return; } e->_need_free = 1; e->name = t; e->message = x; } } else { free(m); if (e->_need_free > 0) { char *t; /* Error is dynamic, let's hence make the message also dynamic */ t = strdup(x); if (!t) return; free((char*) e->message); e->message = t; } else { /* Error is const, hence we can just override */ e->message = x; } } return; } } _public_ int sd_bus_error_set_errno(sd_bus_error *e, int error) { if (error < 0) error = -error; if (!e) return -error; if (error == 0) return -error; assert_return(!bus_error_is_dirty(e), -EINVAL); /* First, try a const translation */ *e = errno_to_bus_error_const(error); if (!sd_bus_error_is_set(e)) { int k; /* If that didn't work, try a dynamic one. */ k = errno_to_bus_error_name_new(error, (char**) &e->name); if (k > 0) e->_need_free = 1; else if (k < 0) { *e = BUS_ERROR_OOM; return -error; } else *e = BUS_ERROR_FAILED; } /* Now, fill in the message from strerror() if we can */ bus_error_strerror(e, error); return -error; } _public_ int sd_bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) { PROTECT_ERRNO; int r; if (error < 0) error = -error; if (!e) return -error; if (error == 0) return 0; assert_return(!bus_error_is_dirty(e), -EINVAL); /* First, try a const translation */ *e = errno_to_bus_error_const(error); if (!sd_bus_error_is_set(e)) { int k; /* If that didn't work, try a dynamic one */ k = errno_to_bus_error_name_new(error, (char**) &e->name); if (k > 0) e->_need_free = 1; else if (k < 0) { *e = BUS_ERROR_OOM; return -ENOMEM; } else *e = BUS_ERROR_FAILED; } if (format) { char *m; /* Then, let's try to fill in the supplied message */ errno = error; /* Make sure that %m resolves to the specified error */ r = vasprintf(&m, format, ap); if (r >= 0) { if (e->_need_free <= 0) { char *t; t = strdup(e->name); if (t) { e->_need_free = 1; e->name = t; e->message = m; return -error; } free(m); } else { free((char*) e->message); e->message = m; return -error; } } } /* If that didn't work, use strerror() for the message */ bus_error_strerror(e, error); return -error; } _public_ int sd_bus_error_set_errnof(sd_bus_error *e, int error, const char *format, ...) { int r; if (error < 0) error = -error; if (!e) return -error; if (error == 0) return 0; assert_return(!bus_error_is_dirty(e), -EINVAL); if (format) { va_list ap; va_start(ap, format); r = sd_bus_error_set_errnofv(e, error, format, ap); va_end(ap); return r; } return sd_bus_error_set_errno(e, error); } const char *bus_error_message(const sd_bus_error *e, int error) { if (e) { /* Sometimes, the D-Bus server is a little bit too verbose with * its error messages, so let's override them here */ if (sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED)) return "Access denied"; if (e->message) return e->message; } if (error < 0) error = -error; return strerror(error); } static bool map_ok(const sd_bus_error_map *map) { for (; map->code != BUS_ERROR_MAP_END_MARKER; map++) if (!map->name || map->code <=0) return false; return true; } _public_ int sd_bus_error_add_map(const sd_bus_error_map *map) { const sd_bus_error_map **maps = NULL; unsigned n = 0; assert_return(map, -EINVAL); assert_return(map_ok(map), -EINVAL); if (additional_error_maps) for (; additional_error_maps[n] != NULL; n++) if (additional_error_maps[n] == map) return 0; maps = realloc_multiply(additional_error_maps, sizeof(struct sd_bus_error_map*), n + 2); if (!maps) return -ENOMEM; maps[n] = map; maps[n+1] = NULL; additional_error_maps = maps; return 1; } systemd-229/src/libsystemd/sd-bus/bus-error.h000066400000000000000000000050021265713322000213120ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "macro.h" bool bus_error_is_dirty(sd_bus_error *e); const char *bus_error_message(const sd_bus_error *e, int error); int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_list ap) _printf_(3,0); int bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) _printf_(3,0); #define BUS_ERROR_OOM SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_MEMORY, "Out of memory") #define BUS_ERROR_FAILED SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FAILED, "Operation failed") /* * There are two ways to register error maps with the error translation * logic: by using BUS_ERROR_MAP_ELF_REGISTER, which however only * works when linked into the same ELF module, or via * sd_bus_error_add_map() which is the official, external API, that * works from any module. * * Note that BUS_ERROR_MAP_ELF_REGISTER has to be used as decorator in * the bus error table, and BUS_ERROR_MAP_ELF_USE has to be used at * least once per compilation unit (i.e. per library), to ensure that * the error map is really added to the final binary. */ #define BUS_ERROR_MAP_ELF_REGISTER \ __attribute__ ((__section__("BUS_ERROR_MAP"))) \ __attribute__ ((__used__)) \ __attribute__ ((aligned(8))) #define BUS_ERROR_MAP_ELF_USE(errors) \ extern const sd_bus_error_map errors[]; \ __attribute__ ((used)) static const sd_bus_error_map * const CONCATENATE(errors ## _copy_, __COUNTER__) = errors; /* We use something exotic as end marker, to ensure people build the * maps using the macsd-ros. */ #define BUS_ERROR_MAP_END_MARKER -'x' BUS_ERROR_MAP_ELF_USE(bus_standard_errors); systemd-229/src/libsystemd/sd-bus/bus-gvariant.c000066400000000000000000000211011265713322000217650ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-gvariant.h" #include "bus-signature.h" #include "bus-type.h" int bus_gvariant_get_size(const char *signature) { const char *p; int sum = 0, r; /* For fixed size structs. Fails for variable size structs. */ p = signature; while (*p != 0) { size_t n; r = signature_element_length(p, &n); if (r < 0) return r; else { char t[n+1]; memcpy(t, p, n); t[n] = 0; r = bus_gvariant_get_alignment(t); if (r < 0) return r; sum = ALIGN_TO(sum, r); } switch (*p) { case SD_BUS_TYPE_BOOLEAN: case SD_BUS_TYPE_BYTE: sum += 1; break; case SD_BUS_TYPE_INT16: case SD_BUS_TYPE_UINT16: sum += 2; break; case SD_BUS_TYPE_INT32: case SD_BUS_TYPE_UINT32: case SD_BUS_TYPE_UNIX_FD: sum += 4; break; case SD_BUS_TYPE_INT64: case SD_BUS_TYPE_UINT64: case SD_BUS_TYPE_DOUBLE: sum += 8; break; case SD_BUS_TYPE_STRUCT_BEGIN: case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { if (n == 2) { /* unary type () has fixed size of 1 */ r = 1; } else { char t[n-1]; memcpy(t, p + 1, n - 2); t[n - 2] = 0; r = bus_gvariant_get_size(t); if (r < 0) return r; } sum += r; break; } case SD_BUS_TYPE_STRING: case SD_BUS_TYPE_OBJECT_PATH: case SD_BUS_TYPE_SIGNATURE: case SD_BUS_TYPE_ARRAY: case SD_BUS_TYPE_VARIANT: return -EINVAL; default: assert_not_reached("Unknown signature type"); } p += n; } r = bus_gvariant_get_alignment(signature); if (r < 0) return r; return ALIGN_TO(sum, r); } int bus_gvariant_get_alignment(const char *signature) { size_t alignment = 1; const char *p; int r; p = signature; while (*p != 0 && alignment < 8) { size_t n; int a; r = signature_element_length(p, &n); if (r < 0) return r; switch (*p) { case SD_BUS_TYPE_BYTE: case SD_BUS_TYPE_BOOLEAN: case SD_BUS_TYPE_STRING: case SD_BUS_TYPE_OBJECT_PATH: case SD_BUS_TYPE_SIGNATURE: a = 1; break; case SD_BUS_TYPE_INT16: case SD_BUS_TYPE_UINT16: a = 2; break; case SD_BUS_TYPE_INT32: case SD_BUS_TYPE_UINT32: case SD_BUS_TYPE_UNIX_FD: a = 4; break; case SD_BUS_TYPE_INT64: case SD_BUS_TYPE_UINT64: case SD_BUS_TYPE_DOUBLE: case SD_BUS_TYPE_VARIANT: a = 8; break; case SD_BUS_TYPE_ARRAY: { char t[n]; memcpy(t, p + 1, n - 1); t[n - 1] = 0; a = bus_gvariant_get_alignment(t); break; } case SD_BUS_TYPE_STRUCT_BEGIN: case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { char t[n-1]; memcpy(t, p + 1, n - 2); t[n - 2] = 0; a = bus_gvariant_get_alignment(t); break; } default: assert_not_reached("Unknown signature type"); } if (a < 0) return a; assert(a > 0 && a <= 8); if ((size_t) a > alignment) alignment = (size_t) a; p += n; } return alignment; } int bus_gvariant_is_fixed_size(const char *signature) { const char *p; int r; assert(signature); p = signature; while (*p != 0) { size_t n; r = signature_element_length(p, &n); if (r < 0) return r; switch (*p) { case SD_BUS_TYPE_STRING: case SD_BUS_TYPE_OBJECT_PATH: case SD_BUS_TYPE_SIGNATURE: case SD_BUS_TYPE_ARRAY: case SD_BUS_TYPE_VARIANT: return 0; case SD_BUS_TYPE_BYTE: case SD_BUS_TYPE_BOOLEAN: case SD_BUS_TYPE_INT16: case SD_BUS_TYPE_UINT16: case SD_BUS_TYPE_INT32: case SD_BUS_TYPE_UINT32: case SD_BUS_TYPE_UNIX_FD: case SD_BUS_TYPE_INT64: case SD_BUS_TYPE_UINT64: case SD_BUS_TYPE_DOUBLE: break; case SD_BUS_TYPE_STRUCT_BEGIN: case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { char t[n-1]; memcpy(t, p + 1, n - 2); t[n - 2] = 0; r = bus_gvariant_is_fixed_size(t); if (r <= 0) return r; break; } default: assert_not_reached("Unknown signature type"); } p += n; } return true; } size_t bus_gvariant_determine_word_size(size_t sz, size_t extra) { if (sz + extra <= 0xFF) return 1; else if (sz + extra*2 <= 0xFFFF) return 2; else if (sz + extra*4 <= 0xFFFFFFFF) return 4; else return 8; } size_t bus_gvariant_read_word_le(void *p, size_t sz) { union { uint16_t u16; uint32_t u32; uint64_t u64; } x; assert(p); if (sz == 1) return *(uint8_t*) p; memcpy(&x, p, sz); if (sz == 2) return le16toh(x.u16); else if (sz == 4) return le32toh(x.u32); else if (sz == 8) return le64toh(x.u64); assert_not_reached("unknown word width"); } void bus_gvariant_write_word_le(void *p, size_t sz, size_t value) { union { uint16_t u16; uint32_t u32; uint64_t u64; } x; assert(p); assert(sz == 8 || (value < (1ULL << (sz*8)))); if (sz == 1) { *(uint8_t*) p = value; return; } else if (sz == 2) x.u16 = htole16((uint16_t) value); else if (sz == 4) x.u32 = htole32((uint32_t) value); else if (sz == 8) x.u64 = htole64((uint64_t) value); else assert_not_reached("unknown word width"); memcpy(p, &x, sz); } systemd-229/src/libsystemd/sd-bus/bus-gvariant.h000066400000000000000000000021421265713322000217760ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "macro.h" int bus_gvariant_get_size(const char *signature) _pure_; int bus_gvariant_get_alignment(const char *signature) _pure_; int bus_gvariant_is_fixed_size(const char *signature) _pure_; size_t bus_gvariant_determine_word_size(size_t sz, size_t extra); void bus_gvariant_write_word_le(void *p, size_t sz, size_t value); size_t bus_gvariant_read_word_le(void *p, size_t sz); systemd-229/src/libsystemd/sd-bus/bus-internal.c000066400000000000000000000240361265713322000220000ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-internal.h" #include "bus-message.h" #include "hexdecoct.h" #include "string-util.h" bool object_path_is_valid(const char *p) { const char *q; bool slash; if (!p) return false; if (p[0] != '/') return false; if (p[1] == 0) return true; for (slash = true, q = p+1; *q; q++) if (*q == '/') { if (slash) return false; slash = true; } else { bool good; good = (*q >= 'a' && *q <= 'z') || (*q >= 'A' && *q <= 'Z') || (*q >= '0' && *q <= '9') || *q == '_'; if (!good) return false; slash = false; } if (slash) return false; return true; } char* object_path_startswith(const char *a, const char *b) { const char *p; if (!object_path_is_valid(a) || !object_path_is_valid(b)) return NULL; if (streq(b, "/")) return (char*) a + 1; p = startswith(a, b); if (!p) return NULL; if (*p == 0) return (char*) p; if (*p == '/') return (char*) p + 1; return NULL; } bool interface_name_is_valid(const char *p) { const char *q; bool dot, found_dot = false; if (isempty(p)) return false; for (dot = true, q = p; *q; q++) if (*q == '.') { if (dot) return false; found_dot = dot = true; } else { bool good; good = (*q >= 'a' && *q <= 'z') || (*q >= 'A' && *q <= 'Z') || (!dot && *q >= '0' && *q <= '9') || *q == '_'; if (!good) return false; dot = false; } if (q - p > 255) return false; if (dot) return false; if (!found_dot) return false; return true; } bool service_name_is_valid(const char *p) { const char *q; bool dot, found_dot = false, unique; if (isempty(p)) return false; unique = p[0] == ':'; for (dot = true, q = unique ? p+1 : p; *q; q++) if (*q == '.') { if (dot) return false; found_dot = dot = true; } else { bool good; good = (*q >= 'a' && *q <= 'z') || (*q >= 'A' && *q <= 'Z') || ((!dot || unique) && *q >= '0' && *q <= '9') || *q == '_' || *q == '-'; if (!good) return false; dot = false; } if (q - p > 255) return false; if (dot) return false; if (!found_dot) return false; return true; } char* service_name_startswith(const char *a, const char *b) { const char *p; if (!service_name_is_valid(a) || !service_name_is_valid(b)) return NULL; p = startswith(a, b); if (!p) return NULL; if (*p == 0) return (char*) p; if (*p == '.') return (char*) p + 1; return NULL; } bool member_name_is_valid(const char *p) { const char *q; if (isempty(p)) return false; for (q = p; *q; q++) { bool good; good = (*q >= 'a' && *q <= 'z') || (*q >= 'A' && *q <= 'Z') || (*q >= '0' && *q <= '9') || *q == '_'; if (!good) return false; } if (q - p > 255) return false; return true; } /* * Complex pattern match * This checks whether @a is a 'complex-prefix' of @b, or @b is a * 'complex-prefix' of @a, based on strings that consist of labels with @c as * spearator. This function returns true if: * - both strings are equal * - either is a prefix of the other and ends with @c * The second rule makes sure that either string needs to be fully included in * the other, and the string which is considered the prefix needs to end with a * separator. */ static bool complex_pattern_check(char c, const char *a, const char *b) { bool separator = false; if (!a && !b) return true; if (!a || !b) return false; for (;;) { if (*a != *b) return (separator && (*a == 0 || *b == 0)); if (*a == 0) return true; separator = *a == c; a++, b++; } } bool namespace_complex_pattern(const char *pattern, const char *value) { return complex_pattern_check('.', pattern, value); } bool path_complex_pattern(const char *pattern, const char *value) { return complex_pattern_check('/', pattern, value); } /* * Simple pattern match * This checks whether @a is a 'simple-prefix' of @b, based on strings that * consist of labels with @c as separator. This function returns true, if: * - if @a and @b are equal * - if @a is a prefix of @b, and the first following character in @b (or the * last character in @a) is @c * The second rule basically makes sure that if @a is a prefix of @b, then @b * must follow with a new label separated by @c. It cannot extend the label. */ static bool simple_pattern_check(char c, const char *a, const char *b) { bool separator = false; if (!a && !b) return true; if (!a || !b) return false; for (;;) { if (*a != *b) return *a == 0 && (*b == c || separator); if (*a == 0) return true; separator = *a == c; a++, b++; } } bool namespace_simple_pattern(const char *pattern, const char *value) { return simple_pattern_check('.', pattern, value); } bool path_simple_pattern(const char *pattern, const char *value) { return simple_pattern_check('/', pattern, value); } int bus_message_type_from_string(const char *s, uint8_t *u) { if (streq(s, "signal")) *u = SD_BUS_MESSAGE_SIGNAL; else if (streq(s, "method_call")) *u = SD_BUS_MESSAGE_METHOD_CALL; else if (streq(s, "error")) *u = SD_BUS_MESSAGE_METHOD_ERROR; else if (streq(s, "method_return")) *u = SD_BUS_MESSAGE_METHOD_RETURN; else return -EINVAL; return 0; } const char *bus_message_type_to_string(uint8_t u) { if (u == SD_BUS_MESSAGE_SIGNAL) return "signal"; else if (u == SD_BUS_MESSAGE_METHOD_CALL) return "method_call"; else if (u == SD_BUS_MESSAGE_METHOD_ERROR) return "error"; else if (u == SD_BUS_MESSAGE_METHOD_RETURN) return "method_return"; else return NULL; } char *bus_address_escape(const char *v) { const char *a; char *r, *b; r = new(char, strlen(v)*3+1); if (!r) return NULL; for (a = v, b = r; *a; a++) { if ((*a >= '0' && *a <= '9') || (*a >= 'a' && *a <= 'z') || (*a >= 'A' && *a <= 'Z') || strchr("_-/.", *a)) *(b++) = *a; else { *(b++) = '%'; *(b++) = hexchar(*a >> 4); *(b++) = hexchar(*a & 0xF); } } *b = 0; return r; } int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) { assert(m); if (r < 0) { if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) sd_bus_reply_method_errno(m, r, error); } else if (sd_bus_error_is_set(error)) { if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) sd_bus_reply_method_error(m, error); } else return r; log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s", bus_message_type_to_string(m->header->type), strna(m->sender), strna(m->path), strna(m->interface), strna(m->member), strna(m->root_container.signature), bus_error_message(error, r)); return 1; } systemd-229/src/libsystemd/sd-bus/bus-internal.h000066400000000000000000000254111265713322000220030ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-bus.h" #include "bus-error.h" #include "bus-kernel.h" #include "bus-match.h" #include "hashmap.h" #include "kdbus.h" #include "list.h" #include "prioq.h" #include "refcnt.h" #include "socket-util.h" #include "util.h" struct reply_callback { sd_bus_message_handler_t callback; usec_t timeout; uint64_t cookie; unsigned prioq_idx; }; struct filter_callback { sd_bus_message_handler_t callback; unsigned last_iteration; LIST_FIELDS(struct filter_callback, callbacks); }; struct match_callback { sd_bus_message_handler_t callback; uint64_t cookie; unsigned last_iteration; char *match_string; struct bus_match_node *match_node; }; struct node { char *path; struct node *parent; LIST_HEAD(struct node, child); LIST_FIELDS(struct node, siblings); LIST_HEAD(struct node_callback, callbacks); LIST_HEAD(struct node_vtable, vtables); LIST_HEAD(struct node_enumerator, enumerators); LIST_HEAD(struct node_object_manager, object_managers); }; struct node_callback { struct node *node; bool is_fallback; sd_bus_message_handler_t callback; unsigned last_iteration; LIST_FIELDS(struct node_callback, callbacks); }; struct node_enumerator { struct node *node; sd_bus_node_enumerator_t callback; unsigned last_iteration; LIST_FIELDS(struct node_enumerator, enumerators); }; struct node_object_manager { struct node *node; LIST_FIELDS(struct node_object_manager, object_managers); }; struct node_vtable { struct node *node; char *interface; bool is_fallback; const sd_bus_vtable *vtable; sd_bus_object_find_t find; unsigned last_iteration; LIST_FIELDS(struct node_vtable, vtables); }; struct vtable_member { const char *path; const char *interface; const char *member; struct node_vtable *parent; unsigned last_iteration; const sd_bus_vtable *vtable; }; typedef enum BusSlotType { BUS_REPLY_CALLBACK, BUS_FILTER_CALLBACK, BUS_MATCH_CALLBACK, BUS_NODE_CALLBACK, BUS_NODE_ENUMERATOR, BUS_NODE_VTABLE, BUS_NODE_OBJECT_MANAGER, _BUS_SLOT_INVALID = -1, } BusSlotType; struct sd_bus_slot { unsigned n_ref; sd_bus *bus; void *userdata; BusSlotType type:5; bool floating:1; bool match_added:1; char *description; LIST_FIELDS(sd_bus_slot, slots); union { struct reply_callback reply_callback; struct filter_callback filter_callback; struct match_callback match_callback; struct node_callback node_callback; struct node_enumerator node_enumerator; struct node_object_manager node_object_manager; struct node_vtable node_vtable; }; }; enum bus_state { BUS_UNSET, BUS_OPENING, BUS_AUTHENTICATING, BUS_HELLO, BUS_RUNNING, BUS_CLOSING, BUS_CLOSED }; static inline bool BUS_IS_OPEN(enum bus_state state) { return state > BUS_UNSET && state < BUS_CLOSING; } enum bus_auth { _BUS_AUTH_INVALID, BUS_AUTH_EXTERNAL, BUS_AUTH_ANONYMOUS }; struct sd_bus { /* We use atomic ref counting here since sd_bus_message objects retain references to their originating sd_bus but we want to allow them to be processed in a different thread. We won't provide full thread safety, but only the bare minimum that makes it possible to use sd_bus and sd_bus_message objects independently and on different threads as long as each object is used only once at the same time. */ RefCount n_ref; enum bus_state state; int input_fd, output_fd; int message_version; int message_endian; bool is_kernel:1; bool can_fds:1; bool bus_client:1; bool ucred_valid:1; bool is_server:1; bool anonymous_auth:1; bool prefer_readv:1; bool prefer_writev:1; bool match_callbacks_modified:1; bool filter_callbacks_modified:1; bool nodes_modified:1; bool trusted:1; bool fake_creds_valid:1; bool fake_pids_valid:1; bool manual_peer_interface:1; bool is_system:1; bool is_user:1; bool allow_interactive_authorization:1; int use_memfd; void *rbuffer; size_t rbuffer_size; sd_bus_message **rqueue; unsigned rqueue_size; size_t rqueue_allocated; sd_bus_message **wqueue; unsigned wqueue_size; size_t windex; size_t wqueue_allocated; uint64_t cookie; char *unique_name; uint64_t unique_id; struct bus_match_node match_callbacks; Prioq *reply_callbacks_prioq; OrderedHashmap *reply_callbacks; LIST_HEAD(struct filter_callback, filter_callbacks); Hashmap *nodes; Hashmap *vtable_methods; Hashmap *vtable_properties; union sockaddr_union sockaddr; socklen_t sockaddr_size; char *kernel; char *machine; pid_t nspid; sd_id128_t server_id; char *address; unsigned address_index; int last_connect_error; enum bus_auth auth; size_t auth_rbegin; struct iovec auth_iovec[3]; unsigned auth_index; char *auth_buffer; usec_t auth_timeout; struct ucred ucred; char *label; uint64_t creds_mask; int *fds; unsigned n_fds; char *exec_path; char **exec_argv; unsigned iteration_counter; void *kdbus_buffer; /* We do locking around the memfd cache, since we want to * allow people to process a sd_bus_message in a different * thread then it was generated on and free it there. Since * adding something to the memfd cache might happen when a * message is released, we hence need to protect this bit with * a mutex. */ pthread_mutex_t memfd_cache_mutex; struct memfd_cache memfd_cache[MEMFD_CACHE_MAX]; unsigned n_memfd_cache; pid_t original_pid; uint64_t hello_flags; uint64_t attach_flags; uint64_t match_cookie; sd_event_source *input_io_event_source; sd_event_source *output_io_event_source; sd_event_source *time_event_source; sd_event_source *quit_event_source; sd_event *event; int event_priority; sd_bus_message *current_message; sd_bus_slot *current_slot; sd_bus_message_handler_t current_handler; void *current_userdata; sd_bus **default_bus_ptr; pid_t tid; struct kdbus_creds fake_creds; struct kdbus_pids fake_pids; char *fake_label; char *cgroup_root; char *description; size_t bloom_size; unsigned bloom_n_hash; sd_bus_track *track_queue; LIST_HEAD(sd_bus_slot, slots); }; #define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) #define BUS_WQUEUE_MAX 1024 #define BUS_RQUEUE_MAX 64*1024 #define BUS_MESSAGE_SIZE_MAX (64*1024*1024) #define BUS_AUTH_SIZE_MAX (64*1024) #define BUS_CONTAINER_DEPTH 128 /* Defined by the specification as maximum size of an array in * bytes */ #define BUS_ARRAY_MAX_SIZE 67108864 #define BUS_FDS_MAX 1024 #define BUS_EXEC_ARGV_MAX 256 bool interface_name_is_valid(const char *p) _pure_; bool service_name_is_valid(const char *p) _pure_; char* service_name_startswith(const char *a, const char *b); bool member_name_is_valid(const char *p) _pure_; bool object_path_is_valid(const char *p) _pure_; char *object_path_startswith(const char *a, const char *b) _pure_; bool namespace_complex_pattern(const char *pattern, const char *value) _pure_; bool path_complex_pattern(const char *pattern, const char *value) _pure_; bool namespace_simple_pattern(const char *pattern, const char *value) _pure_; bool path_simple_pattern(const char *pattern, const char *value) _pure_; int bus_message_type_from_string(const char *s, uint8_t *u) _pure_; const char *bus_message_type_to_string(uint8_t u) _pure_; #define error_name_is_valid interface_name_is_valid int bus_ensure_running(sd_bus *bus); int bus_start_running(sd_bus *bus); int bus_next_address(sd_bus *bus); int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m); int bus_rqueue_make_room(sd_bus *bus); bool bus_pid_changed(sd_bus *bus); char *bus_address_escape(const char *v); #define OBJECT_PATH_FOREACH_PREFIX(prefix, path) \ for (char *_slash = ({ strcpy((prefix), (path)); streq((prefix), "/") ? NULL : strrchr((prefix), '/'); }) ; \ _slash && !(_slash[(_slash) == (prefix)] = 0); \ _slash = streq((prefix), "/") ? NULL : strrchr((prefix), '/')) /* If we are invoking callbacks of a bus object, ensure unreffing the * bus from the callback doesn't destroy the object we are working * on */ #define BUS_DONT_DESTROY(bus) \ _cleanup_(sd_bus_unrefp) _unused_ sd_bus *_dont_destroy_##bus = sd_bus_ref(bus) int bus_set_address_system(sd_bus *bus); int bus_set_address_user(sd_bus *bus); int bus_set_address_system_remote(sd_bus *b, const char *host); int bus_set_address_system_machine(sd_bus *b, const char *machine); int bus_remove_match_by_string(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata); int bus_get_root_path(sd_bus *bus); int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error); #define bus_assert_return(expr, r, error) \ do { \ if (!assert_log(expr, #expr)) \ return sd_bus_error_set_errno(error, r); \ } while (false) systemd-229/src/libsystemd/sd-bus/bus-introspect.c000066400000000000000000000162371265713322000223620ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-internal.h" #include "bus-introspect.h" #include "bus-protocol.h" #include "bus-signature.h" #include "fd-util.h" #include "fileio.h" #include "string-util.h" #include "util.h" int introspect_begin(struct introspect *i, bool trusted) { assert(i); zero(*i); i->trusted = trusted; i->f = open_memstream(&i->introspection, &i->size); if (!i->f) return -ENOMEM; fputs(BUS_INTROSPECT_DOCTYPE "\n", i->f); return 0; } int introspect_write_default_interfaces(struct introspect *i, bool object_manager) { assert(i); fputs(BUS_INTROSPECT_INTERFACE_PEER BUS_INTROSPECT_INTERFACE_INTROSPECTABLE BUS_INTROSPECT_INTERFACE_PROPERTIES, i->f); if (object_manager) fputs(BUS_INTROSPECT_INTERFACE_OBJECT_MANAGER, i->f); return 0; } int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix) { char *node; assert(i); assert(prefix); while ((node = set_steal_first(s))) { const char *e; e = object_path_startswith(node, prefix); if (e && e[0]) fprintf(i->f, " \n", e); free(node); } return 0; } static void introspect_write_flags(struct introspect *i, int type, int flags) { if (flags & SD_BUS_VTABLE_DEPRECATED) fputs(" \n", i->f); if (type == _SD_BUS_VTABLE_METHOD && (flags & SD_BUS_VTABLE_METHOD_NO_REPLY)) fputs(" \n", i->f); if (type == _SD_BUS_VTABLE_PROPERTY || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) { if (flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT) fputs(" \n", i->f); if (flags & SD_BUS_VTABLE_PROPERTY_CONST) fputs(" \n", i->f); else if (flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) fputs(" \n", i->f); else if (!(flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE)) fputs(" \n", i->f); } if (!i->trusted && (type == _SD_BUS_VTABLE_METHOD || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) && !(flags & SD_BUS_VTABLE_UNPRIVILEGED)) fputs(" \n", i->f); } static int introspect_write_arguments(struct introspect *i, const char *signature, const char *direction) { int r; for (;;) { size_t l; if (!*signature) return 0; r = signature_element_length(signature, &l); if (r < 0) return r; fprintf(i->f, " f, " direction=\"%s\"/>\n", direction); else fputs("/>\n", i->f); signature += l; } } int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) { assert(i); assert(v); for (; v->type != _SD_BUS_VTABLE_END; v++) { /* Ignore methods, signals and properties that are * marked "hidden", but do show the interface * itself */ if (v->type != _SD_BUS_VTABLE_START && (v->flags & SD_BUS_VTABLE_HIDDEN)) continue; switch (v->type) { case _SD_BUS_VTABLE_START: if (v->flags & SD_BUS_VTABLE_DEPRECATED) fputs(" \n", i->f); break; case _SD_BUS_VTABLE_METHOD: fprintf(i->f, " \n", v->x.method.member); introspect_write_arguments(i, strempty(v->x.method.signature), "in"); introspect_write_arguments(i, strempty(v->x.method.result), "out"); introspect_write_flags(i, v->type, v->flags); fputs(" \n", i->f); break; case _SD_BUS_VTABLE_PROPERTY: case _SD_BUS_VTABLE_WRITABLE_PROPERTY: fprintf(i->f, " \n", v->x.property.member, v->x.property.signature, v->type == _SD_BUS_VTABLE_WRITABLE_PROPERTY ? "readwrite" : "read"); introspect_write_flags(i, v->type, v->flags); fputs(" \n", i->f); break; case _SD_BUS_VTABLE_SIGNAL: fprintf(i->f, " \n", v->x.signal.member); introspect_write_arguments(i, strempty(v->x.signal.signature), NULL); introspect_write_flags(i, v->type, v->flags); fputs(" \n", i->f); break; } } return 0; } int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply) { sd_bus_message *q; int r; assert(i); assert(m); assert(reply); fputs("\n", i->f); r = fflush_and_check(i->f); if (r < 0) return r; r = sd_bus_message_new_method_return(m, &q); if (r < 0) return r; r = sd_bus_message_append(q, "s", i->introspection); if (r < 0) { sd_bus_message_unref(q); return r; } *reply = q; return 0; } void introspect_free(struct introspect *i) { assert(i); safe_fclose(i->f); free(i->introspection); zero(*i); } systemd-229/src/libsystemd/sd-bus/bus-introspect.h000066400000000000000000000025121265713322000223560ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "set.h" struct introspect { FILE *f; char *introspection; size_t size; bool trusted; }; int introspect_begin(struct introspect *i, bool trusted); int introspect_write_default_interfaces(struct introspect *i, bool object_manager); int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix); int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v); int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply); void introspect_free(struct introspect *i); systemd-229/src/libsystemd/sd-bus/bus-kernel.c000066400000000000000000001715321265713322000214500ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #ifdef HAVE_VALGRIND_MEMCHECK_H #include #endif #include #include #include #include /* When we include libgen.h because we need dirname() we immediately * undefine basename() since libgen.h defines it as a macro to the POSIX * version which is really broken. We prefer GNU basename(). */ #include #undef basename #include "alloc-util.h" #include "bus-bloom.h" #include "bus-internal.h" #include "bus-kernel.h" #include "bus-label.h" #include "bus-message.h" #include "bus-util.h" #include "capability-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "memfd-util.h" #include "parse-util.h" #include "stdio-util.h" #include "string-util.h" #include "strv.h" #include "user-util.h" #include "util.h" #define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t)) int bus_kernel_parse_unique_name(const char *s, uint64_t *id) { int r; assert(s); assert(id); if (!startswith(s, ":1.")) return 0; r = safe_atou64(s + 3, id); if (r < 0) return r; return 1; } static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) { assert(d); assert(sz > 0); *d = ALIGN8_PTR(*d); /* Note that p can be NULL, which encodes a region full of * zeroes, which is useful to optimize certain padding * conditions */ (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec); (*d)->type = KDBUS_ITEM_PAYLOAD_VEC; (*d)->vec.address = PTR_TO_UINT64(p); (*d)->vec.size = sz; *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size); } static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t start, size_t sz) { assert(d); assert(memfd >= 0); assert(sz > 0); *d = ALIGN8_PTR(*d); (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd); (*d)->type = KDBUS_ITEM_PAYLOAD_MEMFD; (*d)->memfd.fd = memfd; (*d)->memfd.start = start; (*d)->memfd.size = sz; *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size); } static void append_destination(struct kdbus_item **d, const char *s, size_t length) { assert(d); assert(s); *d = ALIGN8_PTR(*d); (*d)->size = offsetof(struct kdbus_item, str) + length + 1; (*d)->type = KDBUS_ITEM_DST_NAME; memcpy((*d)->str, s, length + 1); *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size); } static struct kdbus_bloom_filter *append_bloom(struct kdbus_item **d, size_t length) { struct kdbus_item *i; assert(d); i = ALIGN8_PTR(*d); i->size = offsetof(struct kdbus_item, bloom_filter) + offsetof(struct kdbus_bloom_filter, data) + length; i->type = KDBUS_ITEM_BLOOM_FILTER; *d = (struct kdbus_item *) ((uint8_t*) i + i->size); return &i->bloom_filter; } static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) { assert(d); assert(fds); assert(n_fds > 0); *d = ALIGN8_PTR(*d); (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds; (*d)->type = KDBUS_ITEM_FDS; memcpy((*d)->fds, fds, sizeof(int) * n_fds); *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size); } static void add_bloom_arg(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) { char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")]; char *e; assert(data); assert(size > 0); assert(i < 64); assert(t); e = stpcpy(buf, "arg"); if (i < 10) *(e++) = '0' + (char) i; else { *(e++) = '0' + (char) (i / 10); *(e++) = '0' + (char) (i % 10); } *e = 0; bloom_add_pair(data, size, n_hash, buf, t); strcpy(e, "-dot-prefix"); bloom_add_prefixes(data, size, n_hash, buf, t, '.'); strcpy(e, "-slash-prefix"); bloom_add_prefixes(data, size, n_hash, buf, t, '/'); } static void add_bloom_arg_has(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) { char buf[sizeof("arg")-1 + 2 + sizeof("-has")]; char *e; assert(data); assert(size > 0); assert(i < 64); assert(t); e = stpcpy(buf, "arg"); if (i < 10) *(e++) = '0' + (char) i; else { *(e++) = '0' + (char) (i / 10); *(e++) = '0' + (char) (i % 10); } strcpy(e, "-has"); bloom_add_pair(data, size, n_hash, buf, t); } static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) { void *data; unsigned i; int r; assert(m); assert(bloom); data = bloom->data; memzero(data, m->bus->bloom_size); bloom->generation = 0; bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "message-type", bus_message_type_to_string(m->header->type)); if (m->interface) bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "interface", m->interface); if (m->member) bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "member", m->member); if (m->path) { bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path", m->path); bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path); bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path, '/'); } r = sd_bus_message_rewind(m, true); if (r < 0) return r; for (i = 0; i < 64; i++) { const char *t, *contents; char type; r = sd_bus_message_peek_type(m, &type, &contents); if (r < 0) return r; if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) { /* The bloom filter includes simple strings of any kind */ r = sd_bus_message_read_basic(m, type, &t); if (r < 0) return r; add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t); } if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) { /* As well as array of simple strings of any kinds */ r = sd_bus_message_enter_container(m, type, contents); if (r < 0) return r; while ((r = sd_bus_message_read_basic(m, contents[0], &t)) > 0) add_bloom_arg_has(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t); if (r < 0) return r; r = sd_bus_message_exit_container(m); if (r < 0) return r; } else /* Stop adding to bloom filter as soon as we * run into the first argument we cannot add * to it. */ break; } return 0; } static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { struct bus_body_part *part; struct kdbus_item *d; const char *destination; bool well_known = false; uint64_t dst_id; size_t sz, dl; unsigned i; int r; assert(b); assert(m); assert(m->sealed); /* We put this together only once, if this message is reused * we reuse the earlier-built version */ if (m->kdbus) return 0; destination = m->destination ?: m->destination_ptr; if (destination) { r = bus_kernel_parse_unique_name(destination, &dst_id); if (r < 0) return r; if (r == 0) { well_known = true; /* verify_destination_id will usually be 0, which makes the kernel * driver only look at the provided well-known name. Otherwise, * the kernel will make sure the provided destination id matches * the owner of the provided well-known-name, and fail if they * differ. Currently, this is only needed for bus-proxyd. */ dst_id = m->verify_destination_id; } } else dst_id = KDBUS_DST_ID_BROADCAST; sz = offsetof(struct kdbus_msg, items); /* Add in fixed header, fields header and payload */ sz += (1 + m->n_body_parts) * ALIGN8(offsetof(struct kdbus_item, vec) + MAX(sizeof(struct kdbus_vec), sizeof(struct kdbus_memfd))); /* Add space for bloom filter */ sz += ALIGN8(offsetof(struct kdbus_item, bloom_filter) + offsetof(struct kdbus_bloom_filter, data) + m->bus->bloom_size); /* Add in well-known destination header */ if (well_known) { dl = strlen(destination); sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1); } /* Add space for unix fds */ if (m->n_fds > 0) sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds); m->kdbus = memalign(8, sz); if (!m->kdbus) { r = -ENOMEM; goto fail; } m->free_kdbus = true; memzero(m->kdbus, sz); m->kdbus->flags = ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_EXPECT_REPLY) | ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0) | ((m->header->type == SD_BUS_MESSAGE_SIGNAL) ? KDBUS_MSG_SIGNAL : 0); m->kdbus->dst_id = dst_id; m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS; m->kdbus->cookie = m->header->dbus2.cookie; m->kdbus->priority = m->priority; if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) m->kdbus->cookie_reply = m->reply_cookie; else { struct timespec now; assert_se(clock_gettime(CLOCK_MONOTONIC_COARSE, &now) == 0); m->kdbus->timeout_ns = now.tv_sec * NSEC_PER_SEC + now.tv_nsec + m->timeout * NSEC_PER_USEC; } d = m->kdbus->items; if (well_known) append_destination(&d, destination, dl); append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m)); MESSAGE_FOREACH_PART(part, i, m) { if (part->is_zero) { /* If this is padding then simply send a * vector with a NULL data pointer which the * kernel will just pass through. This is the * most efficient way to encode zeroes */ append_payload_vec(&d, NULL, part->size); continue; } if (part->memfd >= 0 && part->sealed && destination) { /* Try to send a memfd, if the part is * sealed and this is not a broadcast. Since we can only */ append_payload_memfd(&d, part->memfd, part->memfd_offset, part->size); continue; } /* Otherwise, let's send a vector to the actual data. * For that, we need to map it first. */ r = bus_body_part_map(part); if (r < 0) goto fail; append_payload_vec(&d, part->data, part->size); } if (m->header->type == SD_BUS_MESSAGE_SIGNAL) { struct kdbus_bloom_filter *bloom; bloom = append_bloom(&d, m->bus->bloom_size); r = bus_message_setup_bloom(m, bloom); if (r < 0) goto fail; } if (m->n_fds > 0) append_fds(&d, m->fds, m->n_fds); m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus; assert(m->kdbus->size <= sz); return 0; fail: m->poisoned = true; return r; } static void unset_memfds(struct sd_bus_message *m) { struct bus_body_part *part; unsigned i; assert(m); /* Make sure the memfds are not freed twice */ MESSAGE_FOREACH_PART(part, i, m) if (part->memfd >= 0) part->memfd = -1; } static void message_set_timestamp(sd_bus *bus, sd_bus_message *m, const struct kdbus_timestamp *ts) { assert(bus); assert(m); if (!ts) return; if (!(bus->attach_flags & KDBUS_ATTACH_TIMESTAMP)) return; m->realtime = ts->realtime_ns / NSEC_PER_USEC; m->monotonic = ts->monotonic_ns / NSEC_PER_USEC; m->seqnum = ts->seqnum; } static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { sd_bus_message *m = NULL; struct kdbus_item *d; unsigned n_fds = 0; _cleanup_free_ int *fds = NULL; struct bus_header *header = NULL; void *footer = NULL; size_t header_size = 0, footer_size = 0; size_t n_bytes = 0, idx = 0; const char *destination = NULL, *seclabel = NULL; bool last_was_memfd = false; int r; assert(bus); assert(k); assert(k->payload_type == KDBUS_PAYLOAD_DBUS); KDBUS_ITEM_FOREACH(d, k, items) { size_t l; l = d->size - offsetof(struct kdbus_item, data); switch (d->type) { case KDBUS_ITEM_PAYLOAD_OFF: if (!header) { header = (struct bus_header*)((uint8_t*) k + d->vec.offset); header_size = d->vec.size; } footer = (uint8_t*) k + d->vec.offset; footer_size = d->vec.size; n_bytes += d->vec.size; last_was_memfd = false; break; case KDBUS_ITEM_PAYLOAD_MEMFD: if (!header) /* memfd cannot be first part */ return -EBADMSG; n_bytes += d->memfd.size; last_was_memfd = true; break; case KDBUS_ITEM_FDS: { int *f; unsigned j; j = l / sizeof(int); f = realloc(fds, sizeof(int) * (n_fds + j)); if (!f) return -ENOMEM; fds = f; memcpy(fds + n_fds, d->fds, sizeof(int) * j); n_fds += j; break; } case KDBUS_ITEM_SECLABEL: seclabel = d->str; break; } } if (last_was_memfd) /* memfd cannot be last part */ return -EBADMSG; if (!header) return -EBADMSG; if (header_size < sizeof(struct bus_header)) return -EBADMSG; /* on kdbus we only speak native endian gvariant, never dbus1 * marshalling or reverse endian */ if (header->version != 2 || header->endian != BUS_NATIVE_ENDIAN) return -EPROTOTYPE; r = bus_message_from_header( bus, header, header_size, footer, footer_size, n_bytes, fds, n_fds, seclabel, 0, &m); if (r < 0) return r; /* The well-known names list is different from the other credentials. If we asked for it, but nothing is there, this means that the list of well-known names is simply empty, not that we lack any data */ m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask; KDBUS_ITEM_FOREACH(d, k, items) { size_t l; l = d->size - offsetof(struct kdbus_item, data); switch (d->type) { case KDBUS_ITEM_PAYLOAD_OFF: { size_t begin_body; begin_body = BUS_MESSAGE_BODY_BEGIN(m); if (idx + d->vec.size > begin_body) { struct bus_body_part *part; /* Contains body material */ part = message_append_part(m); if (!part) { r = -ENOMEM; goto fail; } /* A -1 offset is NUL padding. */ part->is_zero = d->vec.offset == ~0ULL; if (idx >= begin_body) { if (!part->is_zero) part->data = (uint8_t* )k + d->vec.offset; part->size = d->vec.size; } else { if (!part->is_zero) part->data = (uint8_t*) k + d->vec.offset + (begin_body - idx); part->size = d->vec.size - (begin_body - idx); } part->sealed = true; } idx += d->vec.size; break; } case KDBUS_ITEM_PAYLOAD_MEMFD: { struct bus_body_part *part; if (idx < BUS_MESSAGE_BODY_BEGIN(m)) { r = -EBADMSG; goto fail; } part = message_append_part(m); if (!part) { r = -ENOMEM; goto fail; } part->memfd = d->memfd.fd; part->memfd_offset = d->memfd.start; part->size = d->memfd.size; part->sealed = true; idx += d->memfd.size; break; } case KDBUS_ITEM_PIDS: /* The PID/TID might be missing, when the data * is faked by a bus proxy and it lacks that * information about the real client (since * SO_PEERCRED is used for that). Also kernel * namespacing might make some of this data * unavailable when untranslatable. */ if (d->pids.pid > 0) { m->creds.pid = (pid_t) d->pids.pid; m->creds.mask |= SD_BUS_CREDS_PID & bus->creds_mask; } if (d->pids.tid > 0) { m->creds.tid = (pid_t) d->pids.tid; m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask; } if (d->pids.ppid > 0) { m->creds.ppid = (pid_t) d->pids.ppid; m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask; } else if (d->pids.pid == 1) { m->creds.ppid = 0; m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask; } break; case KDBUS_ITEM_CREDS: /* EUID/SUID/FSUID/EGID/SGID/FSGID might be * missing too (see above). */ if ((uid_t) d->creds.uid != UID_INVALID) { m->creds.uid = (uid_t) d->creds.uid; m->creds.mask |= SD_BUS_CREDS_UID & bus->creds_mask; } if ((uid_t) d->creds.euid != UID_INVALID) { m->creds.euid = (uid_t) d->creds.euid; m->creds.mask |= SD_BUS_CREDS_EUID & bus->creds_mask; } if ((uid_t) d->creds.suid != UID_INVALID) { m->creds.suid = (uid_t) d->creds.suid; m->creds.mask |= SD_BUS_CREDS_SUID & bus->creds_mask; } if ((uid_t) d->creds.fsuid != UID_INVALID) { m->creds.fsuid = (uid_t) d->creds.fsuid; m->creds.mask |= SD_BUS_CREDS_FSUID & bus->creds_mask; } if ((gid_t) d->creds.gid != GID_INVALID) { m->creds.gid = (gid_t) d->creds.gid; m->creds.mask |= SD_BUS_CREDS_GID & bus->creds_mask; } if ((gid_t) d->creds.egid != GID_INVALID) { m->creds.egid = (gid_t) d->creds.egid; m->creds.mask |= SD_BUS_CREDS_EGID & bus->creds_mask; } if ((gid_t) d->creds.sgid != GID_INVALID) { m->creds.sgid = (gid_t) d->creds.sgid; m->creds.mask |= SD_BUS_CREDS_SGID & bus->creds_mask; } if ((gid_t) d->creds.fsgid != GID_INVALID) { m->creds.fsgid = (gid_t) d->creds.fsgid; m->creds.mask |= SD_BUS_CREDS_FSGID & bus->creds_mask; } break; case KDBUS_ITEM_TIMESTAMP: message_set_timestamp(bus, m, &d->timestamp); break; case KDBUS_ITEM_PID_COMM: m->creds.comm = d->str; m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask; break; case KDBUS_ITEM_TID_COMM: m->creds.tid_comm = d->str; m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask; break; case KDBUS_ITEM_EXE: m->creds.exe = d->str; m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask; break; case KDBUS_ITEM_CMDLINE: m->creds.cmdline = d->str; m->creds.cmdline_size = l; m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask; break; case KDBUS_ITEM_CGROUP: m->creds.cgroup = d->str; m->creds.mask |= (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID) & bus->creds_mask; r = bus_get_root_path(bus); if (r < 0) goto fail; m->creds.cgroup_root = bus->cgroup_root; break; case KDBUS_ITEM_AUDIT: m->creds.audit_session_id = (uint32_t) d->audit.sessionid; m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask; m->creds.audit_login_uid = (uid_t) d->audit.loginuid; m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask; break; case KDBUS_ITEM_CAPS: if (d->caps.last_cap != cap_last_cap() || d->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(d->caps.last_cap, 32U) * 4 * 4) { r = -EBADMSG; goto fail; } m->creds.capability = d->caps.caps; m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask; break; case KDBUS_ITEM_DST_NAME: if (!service_name_is_valid(d->str)) { r = -EBADMSG; goto fail; } destination = d->str; break; case KDBUS_ITEM_OWNED_NAME: if (!service_name_is_valid(d->name.name)) { r = -EBADMSG; goto fail; } if (bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) { char **wkn; size_t n; /* We just extend the array here, but * do not allocate the strings inside * of it, instead we just point to our * buffer directly. */ n = strv_length(m->creds.well_known_names); wkn = realloc(m->creds.well_known_names, (n + 2) * sizeof(char*)); if (!wkn) { r = -ENOMEM; goto fail; } wkn[n] = d->name.name; wkn[n+1] = NULL; m->creds.well_known_names = wkn; m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES; } break; case KDBUS_ITEM_CONN_DESCRIPTION: m->creds.description = d->str; m->creds.mask |= SD_BUS_CREDS_DESCRIPTION & bus->creds_mask; break; case KDBUS_ITEM_AUXGROUPS: if (bus->creds_mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) { size_t i, n; gid_t *g; n = (d->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t); g = new(gid_t, n); if (!g) { r = -ENOMEM; goto fail; } for (i = 0; i < n; i++) g[i] = d->data64[i]; m->creds.supplementary_gids = g; m->creds.n_supplementary_gids = n; m->creds.mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS; } break; case KDBUS_ITEM_FDS: case KDBUS_ITEM_SECLABEL: case KDBUS_ITEM_BLOOM_FILTER: break; default: log_debug("Got unknown field from kernel %llu", d->type); } } /* If we requested the list of well-known names to be appended * and the sender had none no item for it will be * attached. However, this does *not* mean that the kernel * didn't want to provide this information to us. Hence, let's * explicitly mark this information as available if it was * requested. */ m->creds.mask |= bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES; r = bus_message_parse_fields(m); if (r < 0) goto fail; /* Refuse messages if kdbus and dbus1 cookie doesn't match up */ if ((uint64_t) m->header->dbus2.cookie != k->cookie) { r = -EBADMSG; goto fail; } /* Refuse messages where the reply flag doesn't match up */ if (!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) != !!(k->flags & KDBUS_MSG_EXPECT_REPLY)) { r = -EBADMSG; goto fail; } /* Refuse reply messages where the reply cookie doesn't match up */ if ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) && m->reply_cookie != k->cookie_reply) { r = -EBADMSG; goto fail; } /* Refuse messages where the autostart flag doesn't match up */ if (!(m->header->flags & BUS_MESSAGE_NO_AUTO_START) != !(k->flags & KDBUS_MSG_NO_AUTO_START)) { r = -EBADMSG; goto fail; } /* Override information from the user header with data from the kernel */ if (k->src_id == KDBUS_SRC_ID_KERNEL) bus_message_set_sender_driver(bus, m); else { xsprintf(m->sender_buffer, ":1.%llu", (unsigned long long)k->src_id); m->sender = m->creds.unique_name = m->sender_buffer; } if (destination) m->destination = destination; else if (k->dst_id == KDBUS_DST_ID_BROADCAST) m->destination = NULL; else if (k->dst_id == KDBUS_DST_ID_NAME) m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */ else { xsprintf(m->destination_buffer, ":1.%llu", (unsigned long long)k->dst_id); m->destination = m->destination_buffer; } /* We take possession of the kmsg struct now */ m->kdbus = k; m->release_kdbus = true; m->free_fds = true; fds = NULL; bus->rqueue[bus->rqueue_size++] = m; return 1; fail: unset_memfds(m); sd_bus_message_unref(m); return r; } int bus_kernel_take_fd(sd_bus *b) { struct kdbus_bloom_parameter *bloom = NULL; struct kdbus_item *items, *item; struct kdbus_cmd_hello *hello; _cleanup_free_ char *g = NULL; const char *name; size_t l = 0, m = 0, sz; int r; assert(b); if (b->is_server) return -EINVAL; b->use_memfd = 1; if (b->description) { g = bus_label_escape(b->description); if (!g) return -ENOMEM; name = g; } else { char pr[17] = {}; /* If no name is explicitly set, we'll include a hint * indicating the library implementation, a hint which * kind of bus this is and the thread name */ assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0); if (isempty(pr)) { name = b->is_system ? "sd-system" : b->is_user ? "sd-user" : "sd"; } else { _cleanup_free_ char *e = NULL; e = bus_label_escape(pr); if (!e) return -ENOMEM; g = strappend(b->is_system ? "sd-system-" : b->is_user ? "sd-user-" : "sd-", e); if (!g) return -ENOMEM; name = g; } b->description = bus_label_unescape(name); if (!b->description) return -ENOMEM; } m = strlen(name); sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) + ALIGN8(offsetof(struct kdbus_item, str) + m + 1); if (b->fake_creds_valid) sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds)); if (b->fake_pids_valid) sz += ALIGN8(offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids)); if (b->fake_label) { l = strlen(b->fake_label); sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1); } hello = alloca0_align(sz, 8); hello->size = sz; hello->flags = b->hello_flags; hello->attach_flags_send = _KDBUS_ATTACH_ANY; hello->attach_flags_recv = b->attach_flags; hello->pool_size = KDBUS_POOL_SIZE; item = hello->items; item->size = offsetof(struct kdbus_item, str) + m + 1; item->type = KDBUS_ITEM_CONN_DESCRIPTION; memcpy(item->str, name, m + 1); item = KDBUS_ITEM_NEXT(item); if (b->fake_creds_valid) { item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds); item->type = KDBUS_ITEM_CREDS; item->creds = b->fake_creds; item = KDBUS_ITEM_NEXT(item); } if (b->fake_pids_valid) { item->size = offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids); item->type = KDBUS_ITEM_PIDS; item->pids = b->fake_pids; item = KDBUS_ITEM_NEXT(item); } if (b->fake_label) { item->size = offsetof(struct kdbus_item, str) + l + 1; item->type = KDBUS_ITEM_SECLABEL; memcpy(item->str, b->fake_label, l+1); } r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello); if (r < 0) { if (errno == ENOTTY) /* If the ioctl is not supported we assume that the * API version changed in a major incompatible way, * let's indicate an API incompatibility in this * case. */ return -ESOCKTNOSUPPORT; return -errno; } if (!b->kdbus_buffer) { b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0); if (b->kdbus_buffer == MAP_FAILED) { b->kdbus_buffer = NULL; r = -errno; goto fail; } } /* The higher 32bit of the bus_flags fields are considered * 'incompatible flags'. Refuse them all for now. */ if (hello->bus_flags > 0xFFFFFFFFULL) { r = -ESOCKTNOSUPPORT; goto fail; } /* extract bloom parameters from items */ items = (void*)((uint8_t*)b->kdbus_buffer + hello->offset); KDBUS_FOREACH(item, items, hello->items_size) { switch (item->type) { case KDBUS_ITEM_BLOOM_PARAMETER: bloom = &item->bloom_parameter; break; } } if (!bloom || !bloom_validate_parameters((size_t) bloom->size, (unsigned) bloom->n_hash)) { r = -EOPNOTSUPP; goto fail; } b->bloom_size = (size_t) bloom->size; b->bloom_n_hash = (unsigned) bloom->n_hash; if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0) { r = -ENOMEM; goto fail; } b->unique_id = hello->id; b->is_kernel = true; b->bus_client = true; b->can_fds = !!(hello->flags & KDBUS_HELLO_ACCEPT_FD); b->message_version = 2; b->message_endian = BUS_NATIVE_ENDIAN; /* the kernel told us the UUID of the underlying bus */ memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes)); /* free returned items */ (void) bus_kernel_cmd_free(b, hello->offset); return bus_start_running(b); fail: (void) bus_kernel_cmd_free(b, hello->offset); return r; } int bus_kernel_connect(sd_bus *b) { assert(b); assert(b->input_fd < 0); assert(b->output_fd < 0); assert(b->kernel); if (b->is_server) return -EINVAL; b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC); if (b->input_fd < 0) return -errno; b->output_fd = b->input_fd; return bus_kernel_take_fd(b); } int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset) { struct kdbus_cmd_free cmd = { .size = sizeof(cmd), .offset = offset, }; int r; assert(bus); assert(bus->is_kernel); r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd); if (r < 0) return -errno; return 0; } static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) { struct kdbus_item *d; assert(bus); assert(k); KDBUS_ITEM_FOREACH(d, k, items) { if (d->type == KDBUS_ITEM_FDS) close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int)); else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD) safe_close(d->memfd.fd); } bus_kernel_cmd_free(bus, (uint8_t*) k - (uint8_t*) bus->kdbus_buffer); } int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) { struct kdbus_cmd_send cmd = { }; int r; assert(bus); assert(m); assert(bus->state == BUS_RUNNING); /* If we can't deliver, we want room for the error message */ r = bus_rqueue_make_room(bus); if (r < 0) return r; r = bus_message_setup_kmsg(bus, m); if (r < 0) return r; cmd.size = sizeof(cmd); cmd.msg_address = (uintptr_t)m->kdbus; /* If this is a synchronous method call, then let's tell the * kernel, so that it can pass CPU time/scheduling to the * destination for the time, if it wants to. If we * synchronously wait for the result anyway, we won't need CPU * anyway. */ if (hint_sync_call) { m->kdbus->flags |= KDBUS_MSG_EXPECT_REPLY; cmd.flags |= KDBUS_SEND_SYNC_REPLY; } r = ioctl(bus->output_fd, KDBUS_CMD_SEND, &cmd); if (r < 0) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus_message *reply; if (errno == EAGAIN || errno == EINTR) return 0; else if (errno == ENXIO || errno == ESRCH) { /* ENXIO: unique name not known * ESRCH: well-known name not known */ if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination); else { log_debug("Could not deliver message to %s as destination is not known. Ignoring.", m->destination); return 0; } } else if (errno == EADDRNOTAVAIL) { /* EADDRNOTAVAIL: activation is possible, but turned off in request flags */ if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination); else { log_debug("Could not deliver message to %s as destination is not activated. Ignoring.", m->destination); return 0; } } else return -errno; r = bus_message_new_synthetic_error( bus, BUS_MESSAGE_COOKIE(m), &error, &reply); if (r < 0) return r; r = bus_seal_synthetic_message(bus, reply); if (r < 0) return r; bus->rqueue[bus->rqueue_size++] = reply; } else if (hint_sync_call) { struct kdbus_msg *k; k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + cmd.reply.offset); assert(k); if (k->payload_type == KDBUS_PAYLOAD_DBUS) { r = bus_kernel_make_message(bus, k); if (r < 0) { close_kdbus_msg(bus, k); /* Anybody can send us invalid messages, let's just drop them. */ if (r == -EBADMSG || r == -EPROTOTYPE) log_debug_errno(r, "Ignoring invalid synchronous reply: %m"); else return r; } } else { log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type); close_kdbus_msg(bus, k); } } return 1; } static int push_name_owner_changed( sd_bus *bus, const char *name, const char *old_owner, const char *new_owner, const struct kdbus_timestamp *ts) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; int r; assert(bus); r = sd_bus_message_new_signal( bus, &m, "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameOwnerChanged"); if (r < 0) return r; r = sd_bus_message_append(m, "sss", name, old_owner, new_owner); if (r < 0) return r; bus_message_set_sender_driver(bus, m); message_set_timestamp(bus, m, ts); r = bus_seal_synthetic_message(bus, m); if (r < 0) return r; bus->rqueue[bus->rqueue_size++] = m; m = NULL; return 1; } static int translate_name_change( sd_bus *bus, const struct kdbus_msg *k, const struct kdbus_item *d, const struct kdbus_timestamp *ts) { char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX]; assert(bus); assert(k); assert(d); if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) old_owner[0] = 0; else sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id.id); if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) { if (isempty(old_owner)) return 0; new_owner[0] = 0; } else sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id.id); return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner, ts); } static int translate_id_change( sd_bus *bus, const struct kdbus_msg *k, const struct kdbus_item *d, const struct kdbus_timestamp *ts) { char owner[UNIQUE_NAME_MAX]; assert(bus); assert(k); assert(d); sprintf(owner, ":1.%llu", d->id_change.id); return push_name_owner_changed( bus, owner, d->type == KDBUS_ITEM_ID_ADD ? NULL : owner, d->type == KDBUS_ITEM_ID_ADD ? owner : NULL, ts); } static int translate_reply( sd_bus *bus, const struct kdbus_msg *k, const struct kdbus_item *d, const struct kdbus_timestamp *ts) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; int r; assert(bus); assert(k); assert(d); r = bus_message_new_synthetic_error( bus, k->cookie_reply, d->type == KDBUS_ITEM_REPLY_TIMEOUT ? &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") : &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"), &m); if (r < 0) return r; message_set_timestamp(bus, m, ts); r = bus_seal_synthetic_message(bus, m); if (r < 0) return r; bus->rqueue[bus->rqueue_size++] = m; m = NULL; return 1; } static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) { static int (* const translate[])(sd_bus *bus, const struct kdbus_msg *k, const struct kdbus_item *d, const struct kdbus_timestamp *ts) = { [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change, [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change, [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change, [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change, [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change, [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply, [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply, }; struct kdbus_item *d, *found = NULL; struct kdbus_timestamp *ts = NULL; assert(bus); assert(k); assert(k->payload_type == KDBUS_PAYLOAD_KERNEL); KDBUS_ITEM_FOREACH(d, k, items) { if (d->type == KDBUS_ITEM_TIMESTAMP) ts = &d->timestamp; else if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) { if (found) return -EBADMSG; found = d; } else log_debug("Got unknown field from kernel %llu", d->type); } if (!found) { log_debug("Didn't find a kernel message to translate."); return 0; } return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found, ts); } int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) { struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; struct kdbus_msg *k; int r; assert(bus); r = bus_rqueue_make_room(bus); if (r < 0) return r; if (hint_priority) { recv.flags |= KDBUS_RECV_USE_PRIORITY; recv.priority = priority; } r = ioctl(bus->input_fd, KDBUS_CMD_RECV, &recv); if (recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS) log_debug("%s: kdbus reports %" PRIu64 " dropped broadcast messages, ignoring.", strna(bus->description), (uint64_t) recv.dropped_msgs); if (r < 0) { if (errno == EAGAIN) return 0; return -errno; } k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.msg.offset); if (k->payload_type == KDBUS_PAYLOAD_DBUS) { r = bus_kernel_make_message(bus, k); /* Anybody can send us invalid messages, let's just drop them. */ if (r == -EBADMSG || r == -EPROTOTYPE) { log_debug_errno(r, "Ignoring invalid message: %m"); r = 0; } if (r <= 0) close_kdbus_msg(bus, k); } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) { r = bus_kernel_translate_message(bus, k); close_kdbus_msg(bus, k); } else { log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type); r = 0; close_kdbus_msg(bus, k); } return r < 0 ? r : 1; } int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated) { struct memfd_cache *c; int fd; assert(address); assert(mapped); assert(allocated); if (!bus || !bus->is_kernel) return -EOPNOTSUPP; assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0); if (bus->n_memfd_cache <= 0) { int r; assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0); r = memfd_new(bus->description); if (r < 0) return r; *address = NULL; *mapped = 0; *allocated = 0; return r; } c = &bus->memfd_cache[--bus->n_memfd_cache]; assert(c->fd >= 0); assert(c->mapped == 0 || c->address); *address = c->address; *mapped = c->mapped; *allocated = c->allocated; fd = c->fd; assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0); return fd; } static void close_and_munmap(int fd, void *address, size_t size) { if (size > 0) assert_se(munmap(address, PAGE_ALIGN(size)) >= 0); safe_close(fd); } void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated) { struct memfd_cache *c; uint64_t max_mapped = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX); assert(fd >= 0); assert(mapped == 0 || address); if (!bus || !bus->is_kernel) { close_and_munmap(fd, address, mapped); return; } assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0); if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) { assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0); close_and_munmap(fd, address, mapped); return; } c = &bus->memfd_cache[bus->n_memfd_cache++]; c->fd = fd; c->address = address; /* If overly long, let's return a bit to the OS */ if (mapped > max_mapped) { assert_se(memfd_set_size(fd, max_mapped) >= 0); assert_se(munmap((uint8_t*) address + max_mapped, PAGE_ALIGN(mapped - max_mapped)) >= 0); c->mapped = c->allocated = max_mapped; } else { c->mapped = mapped; c->allocated = allocated; } assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0); } void bus_kernel_flush_memfd(sd_bus *b) { unsigned i; assert(b); for (i = 0; i < b->n_memfd_cache; i++) close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped); } uint64_t request_name_flags_to_kdbus(uint64_t flags) { uint64_t f = 0; if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT) f |= KDBUS_NAME_ALLOW_REPLACEMENT; if (flags & SD_BUS_NAME_REPLACE_EXISTING) f |= KDBUS_NAME_REPLACE_EXISTING; if (flags & SD_BUS_NAME_QUEUE) f |= KDBUS_NAME_QUEUE; return f; } uint64_t attach_flags_to_kdbus(uint64_t mask) { uint64_t m = 0; if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID| SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) m |= KDBUS_ATTACH_CREDS; if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID)) m |= KDBUS_ATTACH_PIDS; if (mask & SD_BUS_CREDS_COMM) m |= KDBUS_ATTACH_PID_COMM; if (mask & SD_BUS_CREDS_TID_COMM) m |= KDBUS_ATTACH_TID_COMM; if (mask & SD_BUS_CREDS_EXE) m |= KDBUS_ATTACH_EXE; if (mask & SD_BUS_CREDS_CMDLINE) m |= KDBUS_ATTACH_CMDLINE; if (mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) m |= KDBUS_ATTACH_CGROUP; if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) m |= KDBUS_ATTACH_CAPS; if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) m |= KDBUS_ATTACH_SECLABEL; if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) m |= KDBUS_ATTACH_AUDIT; if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) m |= KDBUS_ATTACH_NAMES; if (mask & SD_BUS_CREDS_DESCRIPTION) m |= KDBUS_ATTACH_CONN_DESCRIPTION; if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) m |= KDBUS_ATTACH_AUXGROUPS; return m; } int bus_kernel_create_bus(const char *name, bool world, char **s) { struct kdbus_cmd *make; struct kdbus_item *n; size_t l; int fd; assert(name); assert(s); fd = open("/sys/fs/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) return -errno; l = strlen(name); make = alloca0_align(offsetof(struct kdbus_cmd, items) + ALIGN8(offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter)) + ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) + ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1), 8); make->size = offsetof(struct kdbus_cmd, items); /* Set the bloom parameters */ n = make->items; n->size = offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter); n->type = KDBUS_ITEM_BLOOM_PARAMETER; n->bloom_parameter.size = DEFAULT_BLOOM_SIZE; n->bloom_parameter.n_hash = DEFAULT_BLOOM_N_HASH; assert_cc(DEFAULT_BLOOM_SIZE > 0); assert_cc(DEFAULT_BLOOM_N_HASH > 0); make->size += ALIGN8(n->size); /* Provide all metadata via bus-owner queries */ n = KDBUS_ITEM_NEXT(n); n->type = KDBUS_ITEM_ATTACH_FLAGS_SEND; n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t); n->data64[0] = _KDBUS_ATTACH_ANY; make->size += ALIGN8(n->size); /* Set the a good name */ n = KDBUS_ITEM_NEXT(n); sprintf(n->str, UID_FMT "-%s", getuid(), name); n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1; n->type = KDBUS_ITEM_MAKE_NAME; make->size += ALIGN8(n->size); make->flags = world ? KDBUS_MAKE_ACCESS_WORLD : 0; if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) { safe_close(fd); /* Major API change? then the ioctls got shuffled around. */ if (errno == ENOTTY) return -ESOCKTNOSUPPORT; return -errno; } if (s) { char *p; p = strjoin("/sys/fs/kdbus/", n->str, "/bus", NULL); if (!p) { safe_close(fd); return -ENOMEM; } *s = p; } return fd; } int bus_kernel_open_bus_fd(const char *bus, char **path) { char *p; int fd; size_t len; assert(bus); len = strlen("/sys/fs/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1; if (path) { p = new(char, len); if (!p) return -ENOMEM; } else p = newa(char, len); sprintf(p, "/sys/fs/kdbus/" UID_FMT "-%s/bus", getuid(), bus); fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) { if (path) free(p); return -errno; } if (path) *path = p; return fd; } int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **ep_path) { _cleanup_free_ char *path = NULL; struct kdbus_cmd *make; struct kdbus_item *n; const char *name; int fd; fd = bus_kernel_open_bus_fd(bus_name, &path); if (fd < 0) return fd; make = alloca0_align(ALIGN8(offsetof(struct kdbus_cmd, items)) + ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + strlen(ep_name) + 1), 8); make->size = ALIGN8(offsetof(struct kdbus_cmd, items)); make->flags = KDBUS_MAKE_ACCESS_WORLD; n = make->items; sprintf(n->str, UID_FMT "-%s", getuid(), ep_name); n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1; n->type = KDBUS_ITEM_MAKE_NAME; make->size += ALIGN8(n->size); name = n->str; if (ioctl(fd, KDBUS_CMD_ENDPOINT_MAKE, make) < 0) { safe_close(fd); return -errno; } if (ep_path) { char *p; p = strjoin(dirname(path), "/", name, NULL); if (!p) { safe_close(fd); return -ENOMEM; } *ep_path = p; } return fd; } int bus_kernel_try_close(sd_bus *bus) { struct kdbus_cmd byebye = { .size = sizeof(byebye) }; assert(bus); assert(bus->is_kernel); if (ioctl(bus->input_fd, KDBUS_CMD_BYEBYE, &byebye) < 0) return -errno; return 0; } int bus_kernel_drop_one(int fd) { struct kdbus_cmd_recv recv = { .size = sizeof(recv), .flags = KDBUS_RECV_DROP, }; assert(fd >= 0); if (ioctl(fd, KDBUS_CMD_RECV, &recv) < 0) return -errno; return 0; } int bus_kernel_realize_attach_flags(sd_bus *bus) { struct kdbus_cmd *update; struct kdbus_item *n; assert(bus); assert(bus->is_kernel); update = alloca0_align(offsetof(struct kdbus_cmd, items) + ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)), 8); n = update->items; n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV; n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t); n->data64[0] = bus->attach_flags; update->size = offsetof(struct kdbus_cmd, items) + ALIGN8(n->size); if (ioctl(bus->input_fd, KDBUS_CMD_UPDATE, update) < 0) return -errno; return 0; } int bus_kernel_get_bus_name(sd_bus *bus, char **name) { struct kdbus_cmd_info cmd = { .size = sizeof(struct kdbus_cmd_info), }; struct kdbus_info *info; struct kdbus_item *item; char *n = NULL; int r; assert(bus); assert(name); assert(bus->is_kernel); r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd); if (r < 0) return -errno; info = (struct kdbus_info*) ((uint8_t*) bus->kdbus_buffer + cmd.offset); KDBUS_ITEM_FOREACH(item, info, items) if (item->type == KDBUS_ITEM_MAKE_NAME) { r = free_and_strdup(&n, item->str); break; } bus_kernel_cmd_free(bus, cmd.offset); if (r < 0) return r; if (!n) return -EIO; *name = n; return 0; } systemd-229/src/libsystemd/sd-bus/bus-kernel.h000066400000000000000000000065251265713322000214540ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #define KDBUS_ITEM_NEXT(item) \ (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size)) #define KDBUS_ITEM_FOREACH(part, head, first) \ for (part = (head)->first; \ ((uint8_t *)(part) < (uint8_t *)(head) + (head)->size) && \ ((uint8_t *) part >= (uint8_t *) head); \ part = KDBUS_ITEM_NEXT(part)) #define KDBUS_FOREACH(iter, first, _size) \ for (iter = (first); \ ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \ ((uint8_t *)(iter) >= (uint8_t *)(first)); \ iter = (void*)(((uint8_t *)iter) + ALIGN8((iter)->size))) #define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) #define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE) #define MEMFD_CACHE_MAX 32 /* When we cache a memfd block for reuse, we will truncate blocks * longer than this in order not to keep too much data around. */ #define MEMFD_CACHE_ITEM_SIZE_MAX (128*1024) /* This determines at which minimum size we prefer sending memfds over * sending vectors */ #define MEMFD_MIN_SIZE (512*1024) /* The size of the per-connection memory pool that we set up and where * the kernel places our incoming messages */ #define KDBUS_POOL_SIZE (16*1024*1024) struct memfd_cache { int fd; void *address; size_t mapped; size_t allocated; }; int bus_kernel_connect(sd_bus *b); int bus_kernel_take_fd(sd_bus *b); int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call); int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority); int bus_kernel_open_bus_fd(const char *bus, char **path); int bus_kernel_create_bus(const char *name, bool world, char **s); int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **path); int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated); void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated); void bus_kernel_flush_memfd(sd_bus *bus); int bus_kernel_parse_unique_name(const char *s, uint64_t *id); uint64_t request_name_flags_to_kdbus(uint64_t sd_bus_flags); uint64_t attach_flags_to_kdbus(uint64_t sd_bus_flags); int bus_kernel_try_close(sd_bus *bus); int bus_kernel_drop_one(int fd); int bus_kernel_realize_attach_flags(sd_bus *bus); int bus_kernel_get_bus_name(sd_bus *bus, char **name); int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset); systemd-229/src/libsystemd/sd-bus/bus-match.c000066400000000000000000001123411265713322000212550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-internal.h" #include "bus-match.h" #include "bus-message.h" #include "bus-util.h" #include "fd-util.h" #include "fileio.h" #include "hexdecoct.h" #include "string-util.h" #include "strv.h" /* Example: * * A: type=signal,sender=foo,interface=bar * B: type=signal,sender=quux,interface=fips * C: type=signal,sender=quux,interface=waldo * D: type=signal,member=test * E: sender=miau * F: type=signal * G: type=signal * * results in this tree: * * BUS_MATCH_ROOT * + BUS_MATCH_MESSAGE_TYPE * | ` BUS_MATCH_VALUE: value == signal * | + DBUS_MATCH_SENDER * | | + BUS_MATCH_VALUE: value == foo * | | | ` DBUS_MATCH_INTERFACE * | | | ` BUS_MATCH_VALUE: value == bar * | | | ` BUS_MATCH_LEAF: A * | | ` BUS_MATCH_VALUE: value == quux * | | ` DBUS_MATCH_INTERFACE * | | | BUS_MATCH_VALUE: value == fips * | | | ` BUS_MATCH_LEAF: B * | | ` BUS_MATCH_VALUE: value == waldo * | | ` BUS_MATCH_LEAF: C * | + DBUS_MATCH_MEMBER * | | ` BUS_MATCH_VALUE: value == test * | | ` BUS_MATCH_LEAF: D * | + BUS_MATCH_LEAF: F * | ` BUS_MATCH_LEAF: G * ` BUS_MATCH_SENDER * ` BUS_MATCH_VALUE: value == miau * ` BUS_MATCH_LEAF: E */ static inline bool BUS_MATCH_IS_COMPARE(enum bus_match_node_type t) { return t >= BUS_MATCH_SENDER && t <= BUS_MATCH_ARG_HAS_LAST; } static inline bool BUS_MATCH_CAN_HASH(enum bus_match_node_type t) { return (t >= BUS_MATCH_MESSAGE_TYPE && t <= BUS_MATCH_PATH) || (t >= BUS_MATCH_ARG && t <= BUS_MATCH_ARG_LAST) || (t >= BUS_MATCH_ARG_HAS && t <= BUS_MATCH_ARG_HAS_LAST); } static void bus_match_node_free(struct bus_match_node *node) { assert(node); assert(node->parent); assert(!node->child); assert(node->type != BUS_MATCH_ROOT); assert(node->type < _BUS_MATCH_NODE_TYPE_MAX); if (node->parent->child) { /* We are apparently linked into the parent's child * list. Let's remove us from there. */ if (node->prev) { assert(node->prev->next == node); node->prev->next = node->next; } else { assert(node->parent->child == node); node->parent->child = node->next; } if (node->next) node->next->prev = node->prev; } if (node->type == BUS_MATCH_VALUE) { /* We might be in the parent's hash table, so clean * this up */ if (node->parent->type == BUS_MATCH_MESSAGE_TYPE) hashmap_remove(node->parent->compare.children, UINT_TO_PTR(node->value.u8)); else if (BUS_MATCH_CAN_HASH(node->parent->type) && node->value.str) hashmap_remove(node->parent->compare.children, node->value.str); free(node->value.str); } if (BUS_MATCH_IS_COMPARE(node->type)) { assert(hashmap_isempty(node->compare.children)); hashmap_free(node->compare.children); } free(node); } static bool bus_match_node_maybe_free(struct bus_match_node *node) { assert(node); if (node->type == BUS_MATCH_ROOT) return false; if (node->child) return false; if (BUS_MATCH_IS_COMPARE(node->type) && !hashmap_isempty(node->compare.children)) return true; bus_match_node_free(node); return true; } static bool value_node_test( struct bus_match_node *node, enum bus_match_node_type parent_type, uint8_t value_u8, const char *value_str, char **value_strv, sd_bus_message *m) { assert(node); assert(node->type == BUS_MATCH_VALUE); /* Tests parameters against this value node, doing prefix * magic and stuff. */ switch (parent_type) { case BUS_MATCH_MESSAGE_TYPE: return node->value.u8 == value_u8; case BUS_MATCH_SENDER: if (streq_ptr(node->value.str, value_str)) return true; if (m->creds.mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) { char **i; /* on kdbus we have the well known names list * in the credentials, let's make use of that * for an accurate match */ STRV_FOREACH(i, m->creds.well_known_names) if (streq_ptr(node->value.str, *i)) return true; } else { /* If we don't have kdbus, we don't know the * well-known names of the senders. In that, * let's just hope that dbus-daemon doesn't * send us stuff we didn't want. */ if (node->value.str[0] != ':' && value_str && value_str[0] == ':') return true; } return false; case BUS_MATCH_DESTINATION: case BUS_MATCH_INTERFACE: case BUS_MATCH_MEMBER: case BUS_MATCH_PATH: case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: if (value_str) return streq_ptr(node->value.str, value_str); return false; case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: { char **i; STRV_FOREACH(i, value_strv) if (streq_ptr(node->value.str, *i)) return true; return false; } case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: if (value_str) return namespace_simple_pattern(node->value.str, value_str); return false; case BUS_MATCH_PATH_NAMESPACE: return path_simple_pattern(node->value.str, value_str); case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: if (value_str) return path_complex_pattern(node->value.str, value_str); return false; default: assert_not_reached("Invalid node type"); } } static bool value_node_same( struct bus_match_node *node, enum bus_match_node_type parent_type, uint8_t value_u8, const char *value_str) { /* Tests parameters against this value node, not doing prefix * magic and stuff, i.e. this one actually compares the match * itself. */ assert(node); assert(node->type == BUS_MATCH_VALUE); switch (parent_type) { case BUS_MATCH_MESSAGE_TYPE: return node->value.u8 == value_u8; case BUS_MATCH_SENDER: case BUS_MATCH_DESTINATION: case BUS_MATCH_INTERFACE: case BUS_MATCH_MEMBER: case BUS_MATCH_PATH: case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: case BUS_MATCH_PATH_NAMESPACE: case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: return streq(node->value.str, value_str); default: assert_not_reached("Invalid node type"); } } int bus_match_run( sd_bus *bus, struct bus_match_node *node, sd_bus_message *m) { _cleanup_strv_free_ char **test_strv = NULL; const char *test_str = NULL; uint8_t test_u8 = 0; int r; assert(m); if (!node) return 0; if (bus && bus->match_callbacks_modified) return 0; /* Not these special semantics: when traversing the tree we * usually let bus_match_run() when called for a node * recursively invoke bus_match_run(). There's are two * exceptions here though, which are BUS_NODE_ROOT (which * cannot have a sibling), and BUS_NODE_VALUE (whose siblings * are invoked anyway by its parent. */ switch (node->type) { case BUS_MATCH_ROOT: /* Run all children. Since we cannot have any siblings * we won't call any. The children of the root node * are compares or leaves, they will automatically * call their siblings. */ return bus_match_run(bus, node->child, m); case BUS_MATCH_VALUE: /* Run all children. We don't execute any siblings, we * assume our caller does that. The children of value * nodes are compares or leaves, they will * automatically call their siblings */ assert(node->child); return bus_match_run(bus, node->child, m); case BUS_MATCH_LEAF: if (bus) { if (node->leaf.callback->last_iteration == bus->iteration_counter) return 0; node->leaf.callback->last_iteration = bus->iteration_counter; } r = sd_bus_message_rewind(m, true); if (r < 0) return r; /* Run the callback. And then invoke siblings. */ if (node->leaf.callback->callback) { _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; sd_bus_slot *slot; slot = container_of(node->leaf.callback, sd_bus_slot, match_callback); if (bus) { bus->current_slot = sd_bus_slot_ref(slot); bus->current_handler = node->leaf.callback->callback; bus->current_userdata = slot->userdata; } r = node->leaf.callback->callback(m, slot->userdata, &error_buffer); if (bus) { bus->current_userdata = NULL; bus->current_handler = NULL; bus->current_slot = sd_bus_slot_unref(slot); } r = bus_maybe_reply_error(m, r, &error_buffer); if (r != 0) return r; if (bus && bus->match_callbacks_modified) return 0; } return bus_match_run(bus, node->next, m); case BUS_MATCH_MESSAGE_TYPE: test_u8 = m->header->type; break; case BUS_MATCH_SENDER: test_str = m->sender; /* FIXME: resolve test_str from a well-known to a unique name first */ break; case BUS_MATCH_DESTINATION: test_str = m->destination; break; case BUS_MATCH_INTERFACE: test_str = m->interface; break; case BUS_MATCH_MEMBER: test_str = m->member; break; case BUS_MATCH_PATH: case BUS_MATCH_PATH_NAMESPACE: test_str = m->path; break; case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG, &test_str); break; case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH, &test_str); break; case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE, &test_str); break; case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: (void) bus_message_get_arg_strv(m, node->type - BUS_MATCH_ARG_HAS, &test_strv); break; default: assert_not_reached("Unknown match type."); } if (BUS_MATCH_CAN_HASH(node->type)) { struct bus_match_node *found; /* Lookup via hash table, nice! So let's jump directly. */ if (test_str) found = hashmap_get(node->compare.children, test_str); else if (test_strv) { char **i; STRV_FOREACH(i, test_strv) { found = hashmap_get(node->compare.children, *i); if (found) { r = bus_match_run(bus, found, m); if (r != 0) return r; } } found = NULL; } else if (node->type == BUS_MATCH_MESSAGE_TYPE) found = hashmap_get(node->compare.children, UINT_TO_PTR(test_u8)); else found = NULL; if (found) { r = bus_match_run(bus, found, m); if (r != 0) return r; } } else { struct bus_match_node *c; /* No hash table, so let's iterate manually... */ for (c = node->child; c; c = c->next) { if (!value_node_test(c, node->type, test_u8, test_str, test_strv, m)) continue; r = bus_match_run(bus, c, m); if (r != 0) return r; } } if (bus && bus->match_callbacks_modified) return 0; /* And now, let's invoke our siblings */ return bus_match_run(bus, node->next, m); } static int bus_match_add_compare_value( struct bus_match_node *where, enum bus_match_node_type t, uint8_t value_u8, const char *value_str, struct bus_match_node **ret) { struct bus_match_node *c = NULL, *n = NULL; int r; assert(where); assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE); assert(BUS_MATCH_IS_COMPARE(t)); assert(ret); for (c = where->child; c && c->type != t; c = c->next) ; if (c) { /* Comparison node already exists? Then let's see if * the value node exists too. */ if (t == BUS_MATCH_MESSAGE_TYPE) n = hashmap_get(c->compare.children, UINT_TO_PTR(value_u8)); else if (BUS_MATCH_CAN_HASH(t)) n = hashmap_get(c->compare.children, value_str); else { for (n = c->child; n && !value_node_same(n, t, value_u8, value_str); n = n->next) ; } if (n) { *ret = n; return 0; } } else { /* Comparison node, doesn't exist yet? Then let's * create it. */ c = new0(struct bus_match_node, 1); if (!c) { r = -ENOMEM; goto fail; } c->type = t; c->parent = where; c->next = where->child; if (c->next) c->next->prev = c; where->child = c; if (t == BUS_MATCH_MESSAGE_TYPE) { c->compare.children = hashmap_new(NULL); if (!c->compare.children) { r = -ENOMEM; goto fail; } } else if (BUS_MATCH_CAN_HASH(t)) { c->compare.children = hashmap_new(&string_hash_ops); if (!c->compare.children) { r = -ENOMEM; goto fail; } } } n = new0(struct bus_match_node, 1); if (!n) { r = -ENOMEM; goto fail; } n->type = BUS_MATCH_VALUE; n->value.u8 = value_u8; if (value_str) { n->value.str = strdup(value_str); if (!n->value.str) { r = -ENOMEM; goto fail; } } n->parent = c; if (c->compare.children) { if (t == BUS_MATCH_MESSAGE_TYPE) r = hashmap_put(c->compare.children, UINT_TO_PTR(value_u8), n); else r = hashmap_put(c->compare.children, n->value.str, n); if (r < 0) goto fail; } else { n->next = c->child; if (n->next) n->next->prev = n; c->child = n; } *ret = n; return 1; fail: if (c) bus_match_node_maybe_free(c); if (n) { free(n->value.str); free(n); } return r; } static int bus_match_find_compare_value( struct bus_match_node *where, enum bus_match_node_type t, uint8_t value_u8, const char *value_str, struct bus_match_node **ret) { struct bus_match_node *c, *n; assert(where); assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE); assert(BUS_MATCH_IS_COMPARE(t)); assert(ret); for (c = where->child; c && c->type != t; c = c->next) ; if (!c) return 0; if (t == BUS_MATCH_MESSAGE_TYPE) n = hashmap_get(c->compare.children, UINT_TO_PTR(value_u8)); else if (BUS_MATCH_CAN_HASH(t)) n = hashmap_get(c->compare.children, value_str); else { for (n = c->child; n && !value_node_same(n, t, value_u8, value_str); n = n->next) ; } if (n) { *ret = n; return 1; } return 0; } static int bus_match_add_leaf( struct bus_match_node *where, struct match_callback *callback) { struct bus_match_node *n; assert(where); assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE); assert(callback); n = new0(struct bus_match_node, 1); if (!n) return -ENOMEM; n->type = BUS_MATCH_LEAF; n->parent = where; n->next = where->child; if (n->next) n->next->prev = n; n->leaf.callback = callback; callback->match_node = n; where->child = n; return 1; } static int bus_match_find_leaf( struct bus_match_node *where, sd_bus_message_handler_t callback, void *userdata, struct bus_match_node **ret) { struct bus_match_node *c; assert(where); assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE); assert(ret); for (c = where->child; c; c = c->next) { sd_bus_slot *s; s = container_of(c->leaf.callback, sd_bus_slot, match_callback); if (c->type == BUS_MATCH_LEAF && c->leaf.callback->callback == callback && s->userdata == userdata) { *ret = c; return 1; } } return 0; } enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n) { assert(k); if (n == 4 && startswith(k, "type")) return BUS_MATCH_MESSAGE_TYPE; if (n == 6 && startswith(k, "sender")) return BUS_MATCH_SENDER; if (n == 11 && startswith(k, "destination")) return BUS_MATCH_DESTINATION; if (n == 9 && startswith(k, "interface")) return BUS_MATCH_INTERFACE; if (n == 6 && startswith(k, "member")) return BUS_MATCH_MEMBER; if (n == 4 && startswith(k, "path")) return BUS_MATCH_PATH; if (n == 14 && startswith(k, "path_namespace")) return BUS_MATCH_PATH_NAMESPACE; if (n == 4 && startswith(k, "arg")) { int j; j = undecchar(k[3]); if (j < 0) return -EINVAL; return BUS_MATCH_ARG + j; } if (n == 5 && startswith(k, "arg")) { int a, b; enum bus_match_node_type t; a = undecchar(k[3]); b = undecchar(k[4]); if (a <= 0 || b < 0) return -EINVAL; t = BUS_MATCH_ARG + a * 10 + b; if (t > BUS_MATCH_ARG_LAST) return -EINVAL; return t; } if (n == 8 && startswith(k, "arg") && startswith(k + 4, "path")) { int j; j = undecchar(k[3]); if (j < 0) return -EINVAL; return BUS_MATCH_ARG_PATH + j; } if (n == 9 && startswith(k, "arg") && startswith(k + 5, "path")) { enum bus_match_node_type t; int a, b; a = undecchar(k[3]); b = undecchar(k[4]); if (a <= 0 || b < 0) return -EINVAL; t = BUS_MATCH_ARG_PATH + a * 10 + b; if (t > BUS_MATCH_ARG_PATH_LAST) return -EINVAL; return t; } if (n == 13 && startswith(k, "arg") && startswith(k + 4, "namespace")) { int j; j = undecchar(k[3]); if (j < 0) return -EINVAL; return BUS_MATCH_ARG_NAMESPACE + j; } if (n == 14 && startswith(k, "arg") && startswith(k + 5, "namespace")) { enum bus_match_node_type t; int a, b; a = undecchar(k[3]); b = undecchar(k[4]); if (a <= 0 || b < 0) return -EINVAL; t = BUS_MATCH_ARG_NAMESPACE + a * 10 + b; if (t > BUS_MATCH_ARG_NAMESPACE_LAST) return -EINVAL; return t; } if (n == 7 && startswith(k, "arg") && startswith(k + 4, "has")) { int j; j = undecchar(k[3]); if (j < 0) return -EINVAL; return BUS_MATCH_ARG_HAS + j; } if (n == 8 && startswith(k, "arg") && startswith(k + 5, "has")) { enum bus_match_node_type t; int a, b; a = undecchar(k[3]); b = undecchar(k[4]); if (a <= 0 || b < 0) return -EINVAL; t = BUS_MATCH_ARG_HAS + a * 10 + b; if (t > BUS_MATCH_ARG_HAS_LAST) return -EINVAL; return t; } return -EINVAL; } static int match_component_compare(const void *a, const void *b) { const struct bus_match_component *x = a, *y = b; if (x->type < y->type) return -1; if (x->type > y->type) return 1; return 0; } void bus_match_parse_free(struct bus_match_component *components, unsigned n_components) { unsigned i; for (i = 0; i < n_components; i++) free(components[i].value_str); free(components); } int bus_match_parse( const char *match, struct bus_match_component **_components, unsigned *_n_components) { const char *p = match; struct bus_match_component *components = NULL; size_t components_allocated = 0; unsigned n_components = 0, i; _cleanup_free_ char *value = NULL; int r; assert(match); assert(_components); assert(_n_components); while (*p != 0) { const char *eq, *q; enum bus_match_node_type t; unsigned j = 0; size_t value_allocated = 0; bool escaped = false, quoted; uint8_t u; /* Avahi's match rules appear to include whitespace, skip over it */ p += strspn(p, " "); eq = strchr(p, '='); if (!eq) return -EINVAL; t = bus_match_node_type_from_string(p, eq - p); if (t < 0) return -EINVAL; quoted = eq[1] == '\''; for (q = eq + 1 + quoted;; q++) { if (*q == 0) { if (quoted) { r = -EINVAL; goto fail; } else { if (value) value[j] = 0; break; } } if (!escaped) { if (*q == '\\') { escaped = true; continue; } if (quoted) { if (*q == '\'') { if (value) value[j] = 0; break; } } else { if (*q == ',') { if (value) value[j] = 0; break; } } } if (!GREEDY_REALLOC(value, value_allocated, j + 2)) { r = -ENOMEM; goto fail; } value[j++] = *q; escaped = false; } if (!value) { value = strdup(""); if (!value) { r = -ENOMEM; goto fail; } } if (t == BUS_MATCH_MESSAGE_TYPE) { r = bus_message_type_from_string(value, &u); if (r < 0) goto fail; value = mfree(value); } else u = 0; if (!GREEDY_REALLOC(components, components_allocated, n_components + 1)) { r = -ENOMEM; goto fail; } components[n_components].type = t; components[n_components].value_str = value; components[n_components].value_u8 = u; n_components++; value = NULL; if (q[quoted] == 0) break; if (q[quoted] != ',') { r = -EINVAL; goto fail; } p = q + 1 + quoted; } /* Order the whole thing, so that we always generate the same tree */ qsort_safe(components, n_components, sizeof(struct bus_match_component), match_component_compare); /* Check for duplicates */ for (i = 0; i+1 < n_components; i++) if (components[i].type == components[i+1].type) { r = -EINVAL; goto fail; } *_components = components; *_n_components = n_components; return 0; fail: bus_match_parse_free(components, n_components); return r; } char *bus_match_to_string(struct bus_match_component *components, unsigned n_components) { _cleanup_fclose_ FILE *f = NULL; char *buffer = NULL; size_t size = 0; unsigned i; int r; if (n_components <= 0) return strdup(""); assert(components); f = open_memstream(&buffer, &size); if (!f) return NULL; for (i = 0; i < n_components; i++) { char buf[32]; if (i != 0) fputc(',', f); fputs(bus_match_node_type_to_string(components[i].type, buf, sizeof(buf)), f); fputc('=', f); fputc('\'', f); if (components[i].type == BUS_MATCH_MESSAGE_TYPE) fputs(bus_message_type_to_string(components[i].value_u8), f); else fputs(components[i].value_str, f); fputc('\'', f); } r = fflush_and_check(f); if (r < 0) return NULL; return buffer; } int bus_match_add( struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, struct match_callback *callback) { unsigned i; struct bus_match_node *n; int r; assert(root); assert(callback); n = root; for (i = 0; i < n_components; i++) { r = bus_match_add_compare_value( n, components[i].type, components[i].value_u8, components[i].value_str, &n); if (r < 0) return r; } return bus_match_add_leaf(n, callback); } int bus_match_remove( struct bus_match_node *root, struct match_callback *callback) { struct bus_match_node *node, *pp; assert(root); assert(callback); node = callback->match_node; if (!node) return 0; assert(node->type == BUS_MATCH_LEAF); callback->match_node = NULL; /* Free the leaf */ pp = node->parent; bus_match_node_free(node); /* Prune the tree above */ while (pp) { node = pp; pp = node->parent; if (!bus_match_node_maybe_free(node)) break; } return 1; } int bus_match_find( struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, struct match_callback **ret) { struct bus_match_node *n, **gc; unsigned i; int r; assert(root); assert(ret); gc = newa(struct bus_match_node*, n_components); n = root; for (i = 0; i < n_components; i++) { r = bus_match_find_compare_value( n, components[i].type, components[i].value_u8, components[i].value_str, &n); if (r <= 0) return r; gc[i] = n; } r = bus_match_find_leaf(n, callback, userdata, &n); if (r <= 0) return r; *ret = n->leaf.callback; return 1; } void bus_match_free(struct bus_match_node *node) { struct bus_match_node *c; if (!node) return; if (BUS_MATCH_CAN_HASH(node->type)) { Iterator i; HASHMAP_FOREACH(c, node->compare.children, i) bus_match_free(c); assert(hashmap_isempty(node->compare.children)); } while ((c = node->child)) bus_match_free(c); if (node->type != BUS_MATCH_ROOT) bus_match_node_free(node); } const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[], size_t l) { switch (t) { case BUS_MATCH_ROOT: return "root"; case BUS_MATCH_VALUE: return "value"; case BUS_MATCH_LEAF: return "leaf"; case BUS_MATCH_MESSAGE_TYPE: return "type"; case BUS_MATCH_SENDER: return "sender"; case BUS_MATCH_DESTINATION: return "destination"; case BUS_MATCH_INTERFACE: return "interface"; case BUS_MATCH_MEMBER: return "member"; case BUS_MATCH_PATH: return "path"; case BUS_MATCH_PATH_NAMESPACE: return "path_namespace"; case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: snprintf(buf, l, "arg%i", t - BUS_MATCH_ARG); return buf; case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: snprintf(buf, l, "arg%ipath", t - BUS_MATCH_ARG_PATH); return buf; case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: snprintf(buf, l, "arg%inamespace", t - BUS_MATCH_ARG_NAMESPACE); return buf; case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: snprintf(buf, l, "arg%ihas", t - BUS_MATCH_ARG_HAS); return buf; default: return NULL; } } void bus_match_dump(struct bus_match_node *node, unsigned level) { struct bus_match_node *c; _cleanup_free_ char *pfx = NULL; char buf[32]; if (!node) return; pfx = strrep(" ", level); printf("%s[%s]", strempty(pfx), bus_match_node_type_to_string(node->type, buf, sizeof(buf))); if (node->type == BUS_MATCH_VALUE) { if (node->parent->type == BUS_MATCH_MESSAGE_TYPE) printf(" <%u>\n", node->value.u8); else printf(" <%s>\n", node->value.str); } else if (node->type == BUS_MATCH_ROOT) puts(" root"); else if (node->type == BUS_MATCH_LEAF) printf(" %p/%p\n", node->leaf.callback->callback, container_of(node->leaf.callback, sd_bus_slot, match_callback)->userdata); else putchar('\n'); if (BUS_MATCH_CAN_HASH(node->type)) { Iterator i; HASHMAP_FOREACH(c, node->compare.children, i) bus_match_dump(c, level + 1); } for (c = node->child; c; c = c->next) bus_match_dump(c, level + 1); } enum bus_match_scope bus_match_get_scope(const struct bus_match_component *components, unsigned n_components) { bool found_driver = false; unsigned i; if (n_components <= 0) return BUS_MATCH_GENERIC; assert(components); /* Checks whether the specified match can only match the * pseudo-service for local messages, which we detect by * sender, interface or path. If a match is not restricted to * local messages, then we check if it only matches on the * driver. */ for (i = 0; i < n_components; i++) { const struct bus_match_component *c = components + i; if (c->type == BUS_MATCH_SENDER) { if (streq_ptr(c->value_str, "org.freedesktop.DBus.Local")) return BUS_MATCH_LOCAL; if (streq_ptr(c->value_str, "org.freedesktop.DBus")) found_driver = true; } if (c->type == BUS_MATCH_INTERFACE && streq_ptr(c->value_str, "org.freedesktop.DBus.Local")) return BUS_MATCH_LOCAL; if (c->type == BUS_MATCH_PATH && streq_ptr(c->value_str, "/org/freedesktop/DBus/Local")) return BUS_MATCH_LOCAL; } return found_driver ? BUS_MATCH_DRIVER : BUS_MATCH_GENERIC; } systemd-229/src/libsystemd/sd-bus/bus-match.h000066400000000000000000000067311265713322000212670ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "hashmap.h" enum bus_match_node_type { BUS_MATCH_ROOT, BUS_MATCH_VALUE, BUS_MATCH_LEAF, /* The following are all different kinds of compare nodes */ BUS_MATCH_SENDER, BUS_MATCH_MESSAGE_TYPE, BUS_MATCH_DESTINATION, BUS_MATCH_INTERFACE, BUS_MATCH_MEMBER, BUS_MATCH_PATH, BUS_MATCH_PATH_NAMESPACE, BUS_MATCH_ARG, BUS_MATCH_ARG_LAST = BUS_MATCH_ARG + 63, BUS_MATCH_ARG_PATH, BUS_MATCH_ARG_PATH_LAST = BUS_MATCH_ARG_PATH + 63, BUS_MATCH_ARG_NAMESPACE, BUS_MATCH_ARG_NAMESPACE_LAST = BUS_MATCH_ARG_NAMESPACE + 63, BUS_MATCH_ARG_HAS, BUS_MATCH_ARG_HAS_LAST = BUS_MATCH_ARG_HAS + 63, _BUS_MATCH_NODE_TYPE_MAX, _BUS_MATCH_NODE_TYPE_INVALID = -1 }; struct bus_match_node { enum bus_match_node_type type; struct bus_match_node *parent, *next, *prev, *child; union { struct { char *str; uint8_t u8; } value; struct { struct match_callback *callback; } leaf; struct { /* If this is set, then the child is NULL */ Hashmap *children; } compare; }; }; struct bus_match_component { enum bus_match_node_type type; uint8_t value_u8; char *value_str; }; enum bus_match_scope { BUS_MATCH_GENERIC, BUS_MATCH_LOCAL, BUS_MATCH_DRIVER, }; int bus_match_run(sd_bus *bus, struct bus_match_node *root, sd_bus_message *m); int bus_match_add(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, struct match_callback *callback); int bus_match_remove(struct bus_match_node *root, struct match_callback *callback); int bus_match_find(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, struct match_callback **ret); void bus_match_free(struct bus_match_node *node); void bus_match_dump(struct bus_match_node *node, unsigned level); const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[], size_t l); enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n); int bus_match_parse(const char *match, struct bus_match_component **_components, unsigned *_n_components); void bus_match_parse_free(struct bus_match_component *components, unsigned n_components); char *bus_match_to_string(struct bus_match_component *components, unsigned n_components); enum bus_match_scope bus_match_get_scope(const struct bus_match_component *components, unsigned n_components); systemd-229/src/libsystemd/sd-bus/bus-message.c000066400000000000000000005360641265713322000216210ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-gvariant.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-signature.h" #include "bus-type.h" #include "bus-util.h" #include "fd-util.h" #include "io-util.h" #include "memfd-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" #include "utf8.h" #include "util.h" static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored); static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) { if (p == NULL) return NULL; if (old_base == new_base) return (void*) p; if ((uint8_t*) p < (uint8_t*) old_base) return (void*) p; if ((uint8_t*) p >= (uint8_t*) old_base + sz) return (void*) p; return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base); } static void message_free_part(sd_bus_message *m, struct bus_body_part *part) { assert(m); assert(part); if (part->memfd >= 0) { /* If we can reuse the memfd, try that. For that it * can't be sealed yet. */ if (!part->sealed) { assert(part->memfd_offset == 0); assert(part->data == part->mmap_begin); bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated); } else { if (part->mapped > 0) assert_se(munmap(part->mmap_begin, part->mapped) == 0); safe_close(part->memfd); } } else if (part->munmap_this) munmap(part->mmap_begin, part->mapped); else if (part->free_this) free(part->data); if (part != &m->body) free(part); } static void message_reset_parts(sd_bus_message *m) { struct bus_body_part *part; assert(m); part = &m->body; while (m->n_body_parts > 0) { struct bus_body_part *next = part->next; message_free_part(m, part); part = next; m->n_body_parts--; } m->body_end = NULL; m->cached_rindex_part = NULL; m->cached_rindex_part_begin = 0; } static void message_reset_containers(sd_bus_message *m) { unsigned i; assert(m); for (i = 0; i < m->n_containers; i++) { free(m->containers[i].signature); free(m->containers[i].offsets); } m->containers = mfree(m->containers); m->n_containers = m->containers_allocated = 0; m->root_container.index = 0; } static void message_free(sd_bus_message *m) { assert(m); if (m->free_header) free(m->header); message_reset_parts(m); if (m->release_kdbus) bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer); if (m->free_kdbus) free(m->kdbus); sd_bus_unref(m->bus); if (m->free_fds) { close_many(m->fds, m->n_fds); free(m->fds); } if (m->iovec != m->iovec_fixed) free(m->iovec); m->destination_ptr = mfree(m->destination_ptr); message_reset_containers(m); free(m->root_container.signature); free(m->root_container.offsets); free(m->root_container.peeked_signature); bus_creds_done(&m->creds); free(m); } static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) { void *op, *np; size_t old_size, new_size, start; assert(m); if (m->poisoned) return NULL; old_size = sizeof(struct bus_header) + m->fields_size; start = ALIGN_TO(old_size, align); new_size = start + sz; if (new_size < start || new_size > (size_t) ((uint32_t) -1)) goto poison; if (old_size == new_size) return (uint8_t*) m->header + old_size; if (m->free_header) { np = realloc(m->header, ALIGN8(new_size)); if (!np) goto poison; } else { /* Initially, the header is allocated as part of of * the sd_bus_message itself, let's replace it by * dynamic data */ np = malloc(ALIGN8(new_size)); if (!np) goto poison; memcpy(np, m->header, sizeof(struct bus_header)); } /* Zero out padding */ if (start > old_size) memzero((uint8_t*) np + old_size, start - old_size); op = m->header; m->header = np; m->fields_size = new_size - sizeof(struct bus_header); /* Adjust quick access pointers */ m->path = adjust_pointer(m->path, op, old_size, m->header); m->interface = adjust_pointer(m->interface, op, old_size, m->header); m->member = adjust_pointer(m->member, op, old_size, m->header); m->destination = adjust_pointer(m->destination, op, old_size, m->header); m->sender = adjust_pointer(m->sender, op, old_size, m->header); m->error.name = adjust_pointer(m->error.name, op, old_size, m->header); m->free_header = true; if (add_offset) { if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets)) goto poison; m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header); } return (uint8_t*) np + start; poison: m->poisoned = true; return NULL; } static int message_append_field_string( sd_bus_message *m, uint64_t h, char type, const char *s, const char **ret) { size_t l; uint8_t *p; assert(m); /* dbus1 only allows 8bit header field ids */ if (h > 0xFF) return -EINVAL; /* dbus1 doesn't allow strings over 32bit, let's enforce this * globally, to not risk convertability */ l = strlen(s); if (l > (size_t) (uint32_t) -1) return -EINVAL; /* Signature "(yv)" where the variant contains "s" */ if (BUS_MESSAGE_IS_GVARIANT(m)) { /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */ p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true); if (!p) return -ENOMEM; *((uint64_t*) p) = h; memcpy(p+8, s, l); p[8+l] = 0; p[8+l+1] = 0; p[8+l+2] = type; if (ret) *ret = (char*) p + 8; } else { /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */ p = message_extend_fields(m, 8, 4 + 4 + l + 1, false); if (!p) return -ENOMEM; p[0] = (uint8_t) h; p[1] = 1; p[2] = type; p[3] = 0; ((uint32_t*) p)[1] = l; memcpy(p + 8, s, l + 1); if (ret) *ret = (char*) p + 8; } return 0; } static int message_append_field_signature( sd_bus_message *m, uint64_t h, const char *s, const char **ret) { size_t l; uint8_t *p; assert(m); /* dbus1 only allows 8bit header field ids */ if (h > 0xFF) return -EINVAL; /* dbus1 doesn't allow signatures over 8bit, let's enforce * this globally, to not risk convertability */ l = strlen(s); if (l > 255) return -EINVAL; /* Signature "(yv)" where the variant contains "g" */ if (BUS_MESSAGE_IS_GVARIANT(m)) /* For gvariant the serialization is the same as for normal strings */ return message_append_field_string(m, h, 'g', s, ret); else { /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */ p = message_extend_fields(m, 8, 4 + 1 + l + 1, false); if (!p) return -ENOMEM; p[0] = (uint8_t) h; p[1] = 1; p[2] = SD_BUS_TYPE_SIGNATURE; p[3] = 0; p[4] = l; memcpy(p + 5, s, l + 1); if (ret) *ret = (const char*) p + 5; } return 0; } static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) { uint8_t *p; assert(m); /* dbus1 only allows 8bit header field ids */ if (h > 0xFF) return -EINVAL; if (BUS_MESSAGE_IS_GVARIANT(m)) { /* (field id 64bit + ((value + NUL + signature string 'u') */ p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true); if (!p) return -ENOMEM; *((uint64_t*) p) = h; *((uint32_t*) (p + 8)) = x; p[12] = 0; p[13] = 'u'; } else { /* (field id byte + (signature length + signature 'u' + NUL) + value) */ p = message_extend_fields(m, 8, 4 + 4, false); if (!p) return -ENOMEM; p[0] = (uint8_t) h; p[1] = 1; p[2] = 'u'; p[3] = 0; ((uint32_t*) p)[1] = x; } return 0; } static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) { uint8_t *p; assert(m); /* dbus1 only allows 8bit header field ids */ if (h > 0xFF) return -EINVAL; if (BUS_MESSAGE_IS_GVARIANT(m)) { /* (field id 64bit + ((value + NUL + signature string 't') */ p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true); if (!p) return -ENOMEM; *((uint64_t*) p) = h; *((uint64_t*) (p + 8)) = x; p[16] = 0; p[17] = 't'; } else { /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */ p = message_extend_fields(m, 8, 4 + 4 + 8, false); if (!p) return -ENOMEM; p[0] = (uint8_t) h; p[1] = 1; p[2] = 't'; p[3] = 0; p[4] = 0; p[5] = 0; p[6] = 0; p[7] = 0; ((uint64_t*) p)[1] = x; } return 0; } static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) { assert(m); if (BUS_MESSAGE_IS_GVARIANT(m)) return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie); else { /* 64bit cookies are not supported on dbus1 */ if (cookie > 0xffffffffUL) return -EOPNOTSUPP; return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie); } } int bus_message_from_header( sd_bus *bus, void *header, size_t header_accessible, void *footer, size_t footer_accessible, size_t message_size, int *fds, unsigned n_fds, const char *label, size_t extra, sd_bus_message **ret) { _cleanup_free_ sd_bus_message *m = NULL; struct bus_header *h; size_t a, label_sz; assert(bus); assert(header || header_accessible <= 0); assert(footer || footer_accessible <= 0); assert(fds || n_fds <= 0); assert(ret); if (header_accessible < sizeof(struct bus_header)) return -EBADMSG; if (header_accessible > message_size) return -EBADMSG; if (footer_accessible > message_size) return -EBADMSG; h = header; if (!IN_SET(h->version, 1, 2)) return -EBADMSG; if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID) return -EBADMSG; if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN)) return -EBADMSG; /* Note that we are happy with unknown flags in the flags header! */ a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra); if (label) { label_sz = strlen(label); a += label_sz + 1; } m = malloc0(a); if (!m) return -ENOMEM; m->n_ref = 1; m->sealed = true; m->header = header; m->header_accessible = header_accessible; m->footer = footer; m->footer_accessible = footer_accessible; if (BUS_MESSAGE_IS_GVARIANT(m)) { size_t ws; if (h->dbus2.cookie == 0) return -EBADMSG; /* dbus2 derives the sizes from the message size and the offset table at the end, since it is formatted as gvariant "yyyyuta{tv}v". Since the message itself is a structure with precisely to variable sized entries, there's only one offset in the table, which marks the end of the fields array. */ ws = bus_gvariant_determine_word_size(message_size, 0); if (footer_accessible < ws) return -EBADMSG; m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws); if (ALIGN8(m->fields_size) > message_size - ws) return -EBADMSG; if (m->fields_size < sizeof(struct bus_header)) return -EBADMSG; m->fields_size -= sizeof(struct bus_header); m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size)); } else { if (h->dbus1.serial == 0) return -EBADMSG; /* dbus1 has the sizes in the header */ m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size); m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size); if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size) return -EBADMSG; } m->fds = fds; m->n_fds = n_fds; if (label) { m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra); memcpy(m->creds.label, label, label_sz + 1); m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT; } m->bus = sd_bus_ref(bus); *ret = m; m = NULL; return 0; } int bus_message_from_malloc( sd_bus *bus, void *buffer, size_t length, int *fds, unsigned n_fds, const char *label, sd_bus_message **ret) { sd_bus_message *m; size_t sz; int r; r = bus_message_from_header( bus, buffer, length, /* in this case the initial bytes and the final bytes are the same */ buffer, length, length, fds, n_fds, label, 0, &m); if (r < 0) return r; sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size); if (sz > 0) { m->n_body_parts = 1; m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size); m->body.size = sz; m->body.sealed = true; m->body.memfd = -1; } m->n_iovec = 1; m->iovec = m->iovec_fixed; m->iovec[0].iov_base = buffer; m->iovec[0].iov_len = length; r = bus_message_parse_fields(m); if (r < 0) goto fail; /* We take possession of the memory and fds now */ m->free_header = true; m->free_fds = true; *ret = m; return 0; fail: message_free(m); return r; } static sd_bus_message *message_new(sd_bus *bus, uint8_t type) { sd_bus_message *m; assert(bus); m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header)); if (!m) return NULL; m->n_ref = 1; m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message))); m->header->endian = BUS_NATIVE_ENDIAN; m->header->type = type; m->header->version = bus->message_version; m->allow_fds = bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING); m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m); m->bus = sd_bus_ref(bus); if (bus->allow_interactive_authorization) m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION; return m; } _public_ int sd_bus_message_new_signal( sd_bus *bus, sd_bus_message **m, const char *path, const char *interface, const char *member) { sd_bus_message *t; int r; assert_return(bus, -ENOTCONN); assert_return(bus->state != BUS_UNSET, -ENOTCONN); assert_return(object_path_is_valid(path), -EINVAL); assert_return(interface_name_is_valid(interface), -EINVAL); assert_return(member_name_is_valid(member), -EINVAL); assert_return(m, -EINVAL); t = message_new(bus, SD_BUS_MESSAGE_SIGNAL); if (!t) return -ENOMEM; t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path); if (r < 0) goto fail; r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface); if (r < 0) goto fail; r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member); if (r < 0) goto fail; *m = t; return 0; fail: sd_bus_message_unref(t); return r; } _public_ int sd_bus_message_new_method_call( sd_bus *bus, sd_bus_message **m, const char *destination, const char *path, const char *interface, const char *member) { sd_bus_message *t; int r; assert_return(bus, -ENOTCONN); assert_return(bus->state != BUS_UNSET, -ENOTCONN); assert_return(!destination || service_name_is_valid(destination), -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(!interface || interface_name_is_valid(interface), -EINVAL); assert_return(member_name_is_valid(member), -EINVAL); assert_return(m, -EINVAL); t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL); if (!t) return -ENOMEM; r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path); if (r < 0) goto fail; r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member); if (r < 0) goto fail; if (interface) { r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface); if (r < 0) goto fail; } if (destination) { r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination); if (r < 0) goto fail; } *m = t; return 0; fail: message_free(t); return r; } static int message_new_reply( sd_bus_message *call, uint8_t type, sd_bus_message **m) { sd_bus_message *t; int r; assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); assert_return(call->bus->state != BUS_UNSET, -ENOTCONN); assert_return(m, -EINVAL); t = message_new(call->bus, type); if (!t) return -ENOMEM; t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; t->reply_cookie = BUS_MESSAGE_COOKIE(call); if (t->reply_cookie == 0) return -EOPNOTSUPP; r = message_append_reply_cookie(t, t->reply_cookie); if (r < 0) goto fail; if (call->sender) { r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination); if (r < 0) goto fail; } t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED); t->enforced_reply_signature = call->enforced_reply_signature; *m = t; return 0; fail: message_free(t); return r; } _public_ int sd_bus_message_new_method_return( sd_bus_message *call, sd_bus_message **m) { return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m); } _public_ int sd_bus_message_new_method_error( sd_bus_message *call, sd_bus_message **m, const sd_bus_error *e) { sd_bus_message *t; int r; assert_return(sd_bus_error_is_set(e), -EINVAL); assert_return(m, -EINVAL); r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t); if (r < 0) return r; r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name); if (r < 0) goto fail; if (e->message) { r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message); if (r < 0) goto fail; } t->error._need_free = -1; *m = t; return 0; fail: message_free(t); return r; } _public_ int sd_bus_message_new_method_errorf( sd_bus_message *call, sd_bus_message **m, const char *name, const char *format, ...) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; va_list ap; assert_return(name, -EINVAL); assert_return(m, -EINVAL); va_start(ap, format); bus_error_setfv(&error, name, format, ap); va_end(ap); return sd_bus_message_new_method_error(call, m, &error); } _public_ int sd_bus_message_new_method_errno( sd_bus_message *call, sd_bus_message **m, int error, const sd_bus_error *p) { _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL; if (sd_bus_error_is_set(p)) return sd_bus_message_new_method_error(call, m, p); sd_bus_error_set_errno(&berror, error); return sd_bus_message_new_method_error(call, m, &berror); } _public_ int sd_bus_message_new_method_errnof( sd_bus_message *call, sd_bus_message **m, int error, const char *format, ...) { _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL; va_list ap; va_start(ap, format); sd_bus_error_set_errnofv(&berror, error, format, ap); va_end(ap); return sd_bus_message_new_method_error(call, m, &berror); } void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) { assert(bus); assert(m); m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local"; m->creds.well_known_names_local = true; m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask; } void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) { assert(bus); assert(m); m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus"; m->creds.well_known_names_driver = true; m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask; } int bus_message_new_synthetic_error( sd_bus *bus, uint64_t cookie, const sd_bus_error *e, sd_bus_message **m) { sd_bus_message *t; int r; assert(bus); assert(sd_bus_error_is_set(e)); assert(m); t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR); if (!t) return -ENOMEM; t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; t->reply_cookie = cookie; r = message_append_reply_cookie(t, t->reply_cookie); if (r < 0) goto fail; if (bus && bus->unique_name) { r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination); if (r < 0) goto fail; } r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name); if (r < 0) goto fail; if (e->message) { r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message); if (r < 0) goto fail; } t->error._need_free = -1; bus_message_set_sender_driver(bus, t); *m = t; return 0; fail: message_free(t); return r; } _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) { if (!m) return NULL; assert(m->n_ref > 0); m->n_ref++; return m; } _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) { if (!m) return NULL; assert(m->n_ref > 0); m->n_ref--; if (m->n_ref > 0) return NULL; message_free(m); return NULL; } _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) { assert_return(m, -EINVAL); assert_return(type, -EINVAL); *type = m->header->type; return 0; } _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) { uint64_t c; assert_return(m, -EINVAL); assert_return(cookie, -EINVAL); c = BUS_MESSAGE_COOKIE(m); if (c == 0) return -ENODATA; *cookie = BUS_MESSAGE_COOKIE(m); return 0; } _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) { assert_return(m, -EINVAL); assert_return(cookie, -EINVAL); if (m->reply_cookie == 0) return -ENODATA; *cookie = m->reply_cookie; return 0; } _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) { assert_return(m, -EINVAL); return m->header->type == SD_BUS_MESSAGE_METHOD_CALL && !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED); } _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) { assert_return(m, -EINVAL); return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START); } _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) { assert_return(m, -EINVAL); return m->header->type == SD_BUS_MESSAGE_METHOD_CALL && (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION); } _public_ const char *sd_bus_message_get_path(sd_bus_message *m) { assert_return(m, NULL); return m->path; } _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) { assert_return(m, NULL); return m->interface; } _public_ const char *sd_bus_message_get_member(sd_bus_message *m) { assert_return(m, NULL); return m->member; } _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) { assert_return(m, NULL); return m->destination; } _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) { assert_return(m, NULL); return m->sender; } _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) { assert_return(m, NULL); if (!sd_bus_error_is_set(&m->error)) return NULL; return &m->error; } _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) { assert_return(m, -EINVAL); assert_return(usec, -EINVAL); if (m->monotonic <= 0) return -ENODATA; *usec = m->monotonic; return 0; } _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) { assert_return(m, -EINVAL); assert_return(usec, -EINVAL); if (m->realtime <= 0) return -ENODATA; *usec = m->realtime; return 0; } _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) { assert_return(m, -EINVAL); assert_return(seqnum, -EINVAL); if (m->seqnum <= 0) return -ENODATA; *seqnum = m->seqnum; return 0; } _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) { assert_return(m, NULL); if (m->creds.mask == 0) return NULL; return &m->creds; } _public_ int sd_bus_message_is_signal( sd_bus_message *m, const char *interface, const char *member) { assert_return(m, -EINVAL); if (m->header->type != SD_BUS_MESSAGE_SIGNAL) return 0; if (interface && (!m->interface || !streq(m->interface, interface))) return 0; if (member && (!m->member || !streq(m->member, member))) return 0; return 1; } _public_ int sd_bus_message_is_method_call( sd_bus_message *m, const char *interface, const char *member) { assert_return(m, -EINVAL); if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL) return 0; if (interface && (!m->interface || !streq(m->interface, interface))) return 0; if (member && (!m->member || !streq(m->member, member))) return 0; return 1; } _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) { assert_return(m, -EINVAL); if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR) return 0; if (name && (!m->error.name || !streq(m->error.name, name))) return 0; return 1; } _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) { assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM); if (b) m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED; else m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; return 0; } _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) { assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); if (b) m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START; else m->header->flags |= BUS_MESSAGE_NO_AUTO_START; return 0; } _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) { assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); if (b) m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION; else m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION; return 0; } static struct bus_container *message_get_container(sd_bus_message *m) { assert(m); if (m->n_containers == 0) return &m->root_container; assert(m->containers); return m->containers + m->n_containers - 1; } struct bus_body_part *message_append_part(sd_bus_message *m) { struct bus_body_part *part; assert(m); if (m->poisoned) return NULL; if (m->n_body_parts <= 0) { part = &m->body; zero(*part); } else { assert(m->body_end); part = new0(struct bus_body_part, 1); if (!part) { m->poisoned = true; return NULL; } m->body_end->next = part; } part->memfd = -1; m->body_end = part; m->n_body_parts ++; return part; } static void part_zero(struct bus_body_part *part, size_t sz) { assert(part); assert(sz > 0); assert(sz < 8); /* All other fields can be left in their defaults */ assert(!part->data); assert(part->memfd < 0); part->size = sz; part->is_zero = true; part->sealed = true; } static int part_make_space( struct sd_bus_message *m, struct bus_body_part *part, size_t sz, void **q) { void *n; int r; assert(m); assert(part); assert(!part->sealed); if (m->poisoned) return -ENOMEM; if (!part->data && part->memfd < 0) { part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated); part->mmap_begin = part->data; } if (part->memfd >= 0) { if (part->allocated == 0 || sz > part->allocated) { uint64_t new_allocated; new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1); r = memfd_set_size(part->memfd, new_allocated); if (r < 0) { m->poisoned = true; return r; } part->allocated = new_allocated; } if (!part->data || sz > part->mapped) { size_t psz; psz = PAGE_ALIGN(sz > 0 ? sz : 1); if (part->mapped <= 0) n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0); else n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE); if (n == MAP_FAILED) { m->poisoned = true; return -errno; } part->mmap_begin = part->data = n; part->mapped = psz; part->memfd_offset = 0; } part->munmap_this = true; } else { if (part->allocated == 0 || sz > part->allocated) { size_t new_allocated; new_allocated = sz > 0 ? 2 * sz : 64; n = realloc(part->data, new_allocated); if (!n) { m->poisoned = true; return -ENOMEM; } part->data = n; part->allocated = new_allocated; part->free_this = true; } } if (q) *q = part->data ? (uint8_t*) part->data + part->size : NULL; part->size = sz; return 0; } static int message_add_offset(sd_bus_message *m, size_t offset) { struct bus_container *c; assert(m); assert(BUS_MESSAGE_IS_GVARIANT(m)); /* Add offset to current container, unless this is the first * item in it, which will have the 0 offset, which we can * ignore. */ c = message_get_container(m); if (!c->need_offsets) return 0; if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1)) return -ENOMEM; c->offsets[c->n_offsets++] = offset; return 0; } static void message_extend_containers(sd_bus_message *m, size_t expand) { struct bus_container *c; assert(m); if (expand <= 0) return; /* Update counters */ for (c = m->containers; c < m->containers + m->n_containers; c++) { if (c->array_size) *c->array_size += expand; } } static void *message_extend_body( sd_bus_message *m, size_t align, size_t sz, bool add_offset, bool force_inline) { size_t start_body, end_body, padding, added; void *p; int r; assert(m); assert(align > 0); assert(!m->sealed); if (m->poisoned) return NULL; start_body = ALIGN_TO((size_t) m->body_size, align); end_body = start_body + sz; padding = start_body - m->body_size; added = padding + sz; /* Check for 32bit overflows */ if (end_body > (size_t) ((uint32_t) -1) || end_body < start_body) { m->poisoned = true; return NULL; } if (added > 0) { struct bus_body_part *part = NULL; bool add_new_part; add_new_part = m->n_body_parts <= 0 || m->body_end->sealed || (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) || (force_inline && m->body_end->size > MEMFD_MIN_SIZE); /* if this must be an inlined extension, let's create a new part if the previous part is large enough to be inlined */ if (add_new_part) { if (padding > 0) { part = message_append_part(m); if (!part) return NULL; part_zero(part, padding); } part = message_append_part(m); if (!part) return NULL; r = part_make_space(m, part, sz, &p); if (r < 0) return NULL; } else { struct bus_container *c; void *op; size_t os, start_part, end_part; part = m->body_end; op = part->data; os = part->size; start_part = ALIGN_TO(part->size, align); end_part = start_part + sz; r = part_make_space(m, part, end_part, &p); if (r < 0) return NULL; if (padding > 0) { memzero(p, padding); p = (uint8_t*) p + padding; } /* Readjust pointers */ for (c = m->containers; c < m->containers + m->n_containers; c++) c->array_size = adjust_pointer(c->array_size, op, os, part->data); m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data); } } else /* Return something that is not NULL and is aligned */ p = (uint8_t *) NULL + align; m->body_size = end_body; message_extend_containers(m, added); if (add_offset) { r = message_add_offset(m, end_body); if (r < 0) { m->poisoned = true; return NULL; } } return p; } static int message_push_fd(sd_bus_message *m, int fd) { int *f, copy; assert(m); if (fd < 0) return -EINVAL; if (!m->allow_fds) return -EOPNOTSUPP; copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (copy < 0) return -errno; f = realloc(m->fds, sizeof(int) * (m->n_fds + 1)); if (!f) { m->poisoned = true; safe_close(copy); return -ENOMEM; } m->fds = f; m->fds[m->n_fds] = copy; m->free_fds = true; return copy; } int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) { _cleanup_close_ int fd = -1; struct bus_container *c; ssize_t align, sz; void *a; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(bus_type_is_basic(type), -EINVAL); assert_return(!m->poisoned, -ESTALE); c = message_get_container(m); if (c->signature && c->signature[c->index]) { /* Container signature is already set */ if (c->signature[c->index] != type) return -ENXIO; } else { char *e; /* Maybe we can append to the signature? But only if this is the top-level container */ if (c->enclosing != 0) return -ENXIO; e = strextend(&c->signature, CHAR_TO_STR(type), NULL); if (!e) { m->poisoned = true; return -ENOMEM; } } if (BUS_MESSAGE_IS_GVARIANT(m)) { uint8_t u8; uint32_t u32; switch (type) { case SD_BUS_TYPE_SIGNATURE: case SD_BUS_TYPE_STRING: p = strempty(p); /* Fall through... */ case SD_BUS_TYPE_OBJECT_PATH: if (!p) return -EINVAL; align = 1; sz = strlen(p) + 1; break; case SD_BUS_TYPE_BOOLEAN: u8 = p && *(int*) p; p = &u8; align = sz = 1; break; case SD_BUS_TYPE_UNIX_FD: if (!p) return -EINVAL; fd = message_push_fd(m, *(int*) p); if (fd < 0) return fd; u32 = m->n_fds; p = &u32; align = sz = 4; break; default: align = bus_gvariant_get_alignment(CHAR_TO_STR(type)); sz = bus_gvariant_get_size(CHAR_TO_STR(type)); break; } assert(align > 0); assert(sz > 0); a = message_extend_body(m, align, sz, true, false); if (!a) return -ENOMEM; memcpy(a, p, sz); if (stored) *stored = (const uint8_t*) a; } else { uint32_t u32; switch (type) { case SD_BUS_TYPE_STRING: /* To make things easy we'll serialize a NULL string * into the empty string */ p = strempty(p); /* Fall through... */ case SD_BUS_TYPE_OBJECT_PATH: if (!p) return -EINVAL; align = 4; sz = 4 + strlen(p) + 1; break; case SD_BUS_TYPE_SIGNATURE: p = strempty(p); align = 1; sz = 1 + strlen(p) + 1; break; case SD_BUS_TYPE_BOOLEAN: u32 = p && *(int*) p; p = &u32; align = sz = 4; break; case SD_BUS_TYPE_UNIX_FD: if (!p) return -EINVAL; fd = message_push_fd(m, *(int*) p); if (fd < 0) return fd; u32 = m->n_fds; p = &u32; align = sz = 4; break; default: align = bus_type_get_alignment(type); sz = bus_type_get_size(type); break; } assert(align > 0); assert(sz > 0); a = message_extend_body(m, align, sz, false, false); if (!a) return -ENOMEM; if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) { *(uint32_t*) a = sz - 5; memcpy((uint8_t*) a + 4, p, sz - 4); if (stored) *stored = (const uint8_t*) a + 4; } else if (type == SD_BUS_TYPE_SIGNATURE) { *(uint8_t*) a = sz - 2; memcpy((uint8_t*) a + 1, p, sz - 1); if (stored) *stored = (const uint8_t*) a + 1; } else { memcpy(a, p, sz); if (stored) *stored = a; } } if (type == SD_BUS_TYPE_UNIX_FD) m->n_fds ++; if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index++; fd = -1; return 0; } _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) { return message_append_basic(m, type, p, NULL); } _public_ int sd_bus_message_append_string_space( sd_bus_message *m, size_t size, char **s) { struct bus_container *c; void *a; assert_return(m, -EINVAL); assert_return(s, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(!m->poisoned, -ESTALE); c = message_get_container(m); if (c->signature && c->signature[c->index]) { /* Container signature is already set */ if (c->signature[c->index] != SD_BUS_TYPE_STRING) return -ENXIO; } else { char *e; /* Maybe we can append to the signature? But only if this is the top-level container */ if (c->enclosing != 0) return -ENXIO; e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL); if (!e) { m->poisoned = true; return -ENOMEM; } } if (BUS_MESSAGE_IS_GVARIANT(m)) { a = message_extend_body(m, 1, size + 1, true, false); if (!a) return -ENOMEM; *s = a; } else { a = message_extend_body(m, 4, 4 + size + 1, false, false); if (!a) return -ENOMEM; *(uint32_t*) a = size; *s = (char*) a + 4; } (*s)[size] = 0; if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index++; return 0; } _public_ int sd_bus_message_append_string_iovec( sd_bus_message *m, const struct iovec *iov, unsigned n) { size_t size; unsigned i; char *p; int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(iov || n == 0, -EINVAL); assert_return(!m->poisoned, -ESTALE); size = IOVEC_TOTAL_SIZE(iov, n); r = sd_bus_message_append_string_space(m, size, &p); if (r < 0) return r; for (i = 0; i < n; i++) { if (iov[i].iov_base) memcpy(p, iov[i].iov_base, iov[i].iov_len); else memset(p, ' ', iov[i].iov_len); p += iov[i].iov_len; } return 0; } static int bus_message_open_array( sd_bus_message *m, struct bus_container *c, const char *contents, uint32_t **array_size, size_t *begin, bool *need_offsets) { unsigned nindex; int alignment, r; assert(m); assert(c); assert(contents); assert(array_size); assert(begin); assert(need_offsets); if (!signature_is_single(contents, true)) return -EINVAL; if (c->signature && c->signature[c->index]) { /* Verify the existing signature */ if (c->signature[c->index] != SD_BUS_TYPE_ARRAY) return -ENXIO; if (!startswith(c->signature + c->index + 1, contents)) return -ENXIO; nindex = c->index + 1 + strlen(contents); } else { char *e; if (c->enclosing != 0) return -ENXIO; /* Extend the existing signature */ e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL); if (!e) { m->poisoned = true; return -ENOMEM; } nindex = e - c->signature; } if (BUS_MESSAGE_IS_GVARIANT(m)) { alignment = bus_gvariant_get_alignment(contents); if (alignment < 0) return alignment; /* Add alignment padding and add to offset list */ if (!message_extend_body(m, alignment, 0, false, false)) return -ENOMEM; r = bus_gvariant_is_fixed_size(contents); if (r < 0) return r; *begin = m->body_size; *need_offsets = r == 0; } else { void *a, *op; size_t os; struct bus_body_part *o; alignment = bus_type_get_alignment(contents[0]); if (alignment < 0) return alignment; a = message_extend_body(m, 4, 4, false, false); if (!a) return -ENOMEM; o = m->body_end; op = m->body_end->data; os = m->body_end->size; /* Add alignment between size and first element */ if (!message_extend_body(m, alignment, 0, false, false)) return -ENOMEM; /* location of array size might have changed so let's readjust a */ if (o == m->body_end) a = adjust_pointer(a, op, os, m->body_end->data); *(uint32_t*) a = 0; *array_size = a; } if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index = nindex; return 0; } static int bus_message_open_variant( sd_bus_message *m, struct bus_container *c, const char *contents) { assert(m); assert(c); assert(contents); if (!signature_is_single(contents, false)) return -EINVAL; if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN) return -EINVAL; if (c->signature && c->signature[c->index]) { if (c->signature[c->index] != SD_BUS_TYPE_VARIANT) return -ENXIO; } else { char *e; if (c->enclosing != 0) return -ENXIO; e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL); if (!e) { m->poisoned = true; return -ENOMEM; } } if (BUS_MESSAGE_IS_GVARIANT(m)) { /* Variants are always aligned to 8 */ if (!message_extend_body(m, 8, 0, false, false)) return -ENOMEM; } else { size_t l; void *a; l = strlen(contents); a = message_extend_body(m, 1, 1 + l + 1, false, false); if (!a) return -ENOMEM; *(uint8_t*) a = l; memcpy((uint8_t*) a + 1, contents, l + 1); } if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index++; return 0; } static int bus_message_open_struct( sd_bus_message *m, struct bus_container *c, const char *contents, size_t *begin, bool *need_offsets) { size_t nindex; int r; assert(m); assert(c); assert(contents); assert(begin); assert(need_offsets); if (!signature_is_valid(contents, false)) return -EINVAL; if (c->signature && c->signature[c->index]) { size_t l; l = strlen(contents); if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN || !startswith(c->signature + c->index + 1, contents) || c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END) return -ENXIO; nindex = c->index + 1 + l + 1; } else { char *e; if (c->enclosing != 0) return -ENXIO; e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL); if (!e) { m->poisoned = true; return -ENOMEM; } nindex = e - c->signature; } if (BUS_MESSAGE_IS_GVARIANT(m)) { int alignment; alignment = bus_gvariant_get_alignment(contents); if (alignment < 0) return alignment; if (!message_extend_body(m, alignment, 0, false, false)) return -ENOMEM; r = bus_gvariant_is_fixed_size(contents); if (r < 0) return r; *begin = m->body_size; *need_offsets = r == 0; } else { /* Align contents to 8 byte boundary */ if (!message_extend_body(m, 8, 0, false, false)) return -ENOMEM; } if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index = nindex; return 0; } static int bus_message_open_dict_entry( sd_bus_message *m, struct bus_container *c, const char *contents, size_t *begin, bool *need_offsets) { int r; assert(m); assert(c); assert(contents); assert(begin); assert(need_offsets); if (!signature_is_pair(contents)) return -EINVAL; if (c->enclosing != SD_BUS_TYPE_ARRAY) return -ENXIO; if (c->signature && c->signature[c->index]) { size_t l; l = strlen(contents); if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN || !startswith(c->signature + c->index + 1, contents) || c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END) return -ENXIO; } else return -ENXIO; if (BUS_MESSAGE_IS_GVARIANT(m)) { int alignment; alignment = bus_gvariant_get_alignment(contents); if (alignment < 0) return alignment; if (!message_extend_body(m, alignment, 0, false, false)) return -ENOMEM; r = bus_gvariant_is_fixed_size(contents); if (r < 0) return r; *begin = m->body_size; *need_offsets = r == 0; } else { /* Align contents to 8 byte boundary */ if (!message_extend_body(m, 8, 0, false, false)) return -ENOMEM; } return 0; } _public_ int sd_bus_message_open_container( sd_bus_message *m, char type, const char *contents) { struct bus_container *c, *w; uint32_t *array_size = NULL; char *signature; size_t before, begin = 0; bool need_offsets = false; int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(contents, -EINVAL); assert_return(!m->poisoned, -ESTALE); /* Make sure we have space for one more container */ if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) { m->poisoned = true; return -ENOMEM; } c = message_get_container(m); signature = strdup(contents); if (!signature) { m->poisoned = true; return -ENOMEM; } /* Save old index in the parent container, in case we have to * abort this container */ c->saved_index = c->index; before = m->body_size; if (type == SD_BUS_TYPE_ARRAY) r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets); else if (type == SD_BUS_TYPE_VARIANT) r = bus_message_open_variant(m, c, contents); else if (type == SD_BUS_TYPE_STRUCT) r = bus_message_open_struct(m, c, contents, &begin, &need_offsets); else if (type == SD_BUS_TYPE_DICT_ENTRY) r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets); else r = -EINVAL; if (r < 0) { free(signature); return r; } /* OK, let's fill it in */ w = m->containers + m->n_containers++; w->enclosing = type; w->signature = signature; w->index = 0; w->array_size = array_size; w->before = before; w->begin = begin; w->n_offsets = w->offsets_allocated = 0; w->offsets = NULL; w->need_offsets = need_offsets; return 0; } static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) { assert(m); assert(c); if (!BUS_MESSAGE_IS_GVARIANT(m)) return 0; if (c->need_offsets) { size_t payload, sz, i; uint8_t *a; /* Variable-width arrays */ payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0; sz = bus_gvariant_determine_word_size(payload, c->n_offsets); a = message_extend_body(m, 1, sz * c->n_offsets, true, false); if (!a) return -ENOMEM; for (i = 0; i < c->n_offsets; i++) bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin); } else { void *a; /* Fixed-width or empty arrays */ a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */ if (!a) return -ENOMEM; } return 0; } static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) { uint8_t *a; size_t l; assert(m); assert(c); assert(c->signature); if (!BUS_MESSAGE_IS_GVARIANT(m)) return 0; l = strlen(c->signature); a = message_extend_body(m, 1, 1 + l, true, false); if (!a) return -ENOMEM; a[0] = 0; memcpy(a+1, c->signature, l); return 0; } static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) { bool fixed_size = true; size_t n_variable = 0; unsigned i = 0; const char *p; uint8_t *a; int r; assert(m); assert(c); if (!BUS_MESSAGE_IS_GVARIANT(m)) return 0; p = strempty(c->signature); while (*p != 0) { size_t n; r = signature_element_length(p, &n); if (r < 0) return r; else { char t[n+1]; memcpy(t, p, n); t[n] = 0; r = bus_gvariant_is_fixed_size(t); if (r < 0) return r; } assert(!c->need_offsets || i <= c->n_offsets); /* We need to add an offset for each item that has a * variable size and that is not the last one in the * list */ if (r == 0) fixed_size = false; if (r == 0 && p[n] != 0) n_variable++; i++; p += n; } assert(!c->need_offsets || i == c->n_offsets); assert(c->need_offsets || n_variable == 0); if (isempty(c->signature)) { /* The unary type is encoded as fixed 1 byte padding */ a = message_extend_body(m, 1, 1, add_offset, false); if (!a) return -ENOMEM; *a = 0; } else if (n_variable <= 0) { int alignment = 1; /* Structures with fixed-size members only have to be * fixed-size themselves. But gvariant requires all fixed-size * elements to be sized a multiple of their alignment. Hence, * we must *always* add final padding after the last member so * the overall size of the structure is properly aligned. */ if (fixed_size) alignment = bus_gvariant_get_alignment(strempty(c->signature)); assert(alignment > 0); a = message_extend_body(m, alignment, 0, add_offset, false); if (!a) return -ENOMEM; } else { size_t sz; unsigned j; assert(c->offsets[c->n_offsets-1] == m->body_size); sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable); a = message_extend_body(m, 1, sz * n_variable, add_offset, false); if (!a) return -ENOMEM; p = strempty(c->signature); for (i = 0, j = 0; i < c->n_offsets; i++) { unsigned k; size_t n; r = signature_element_length(p, &n); if (r < 0) return r; else { char t[n+1]; memcpy(t, p, n); t[n] = 0; p += n; r = bus_gvariant_is_fixed_size(t); if (r < 0) return r; if (r > 0 || p[0] == 0) continue; } k = n_variable - 1 - j; bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin); j++; } } return 0; } _public_ int sd_bus_message_close_container(sd_bus_message *m) { struct bus_container *c; int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(m->n_containers > 0, -EINVAL); assert_return(!m->poisoned, -ESTALE); c = message_get_container(m); if (c->enclosing != SD_BUS_TYPE_ARRAY) if (c->signature && c->signature[c->index] != 0) return -EINVAL; m->n_containers--; if (c->enclosing == SD_BUS_TYPE_ARRAY) r = bus_message_close_array(m, c); else if (c->enclosing == SD_BUS_TYPE_VARIANT) r = bus_message_close_variant(m, c); else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY) r = bus_message_close_struct(m, c, true); else assert_not_reached("Unknown container type"); free(c->signature); free(c->offsets); return r; } typedef struct { const char *types; unsigned n_struct; unsigned n_array; } TypeStack; static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) { assert(stack); assert(max > 0); if (*i >= max) return -EINVAL; stack[*i].types = types; stack[*i].n_struct = n_struct; stack[*i].n_array = n_array; (*i)++; return 0; } static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) { assert(stack); assert(max > 0); assert(types); assert(n_struct); assert(n_array); if (*i <= 0) return 0; (*i)--; *types = stack[*i].types; *n_struct = stack[*i].n_struct; *n_array = stack[*i].n_array; return 1; } int bus_message_append_ap( sd_bus_message *m, const char *types, va_list ap) { unsigned n_array, n_struct; TypeStack stack[BUS_CONTAINER_DEPTH]; unsigned stack_ptr = 0; int r; assert(m); if (!types) return 0; n_array = (unsigned) -1; n_struct = strlen(types); for (;;) { const char *t; if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) { r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array); if (r < 0) return r; if (r == 0) break; r = sd_bus_message_close_container(m); if (r < 0) return r; continue; } t = types; if (n_array != (unsigned) -1) n_array --; else { types ++; n_struct--; } switch (*t) { case SD_BUS_TYPE_BYTE: { uint8_t x; x = (uint8_t) va_arg(ap, int); r = sd_bus_message_append_basic(m, *t, &x); break; } case SD_BUS_TYPE_BOOLEAN: case SD_BUS_TYPE_INT32: case SD_BUS_TYPE_UINT32: case SD_BUS_TYPE_UNIX_FD: { uint32_t x; /* We assume a boolean is the same as int32_t */ assert_cc(sizeof(int32_t) == sizeof(int)); x = va_arg(ap, uint32_t); r = sd_bus_message_append_basic(m, *t, &x); break; } case SD_BUS_TYPE_INT16: case SD_BUS_TYPE_UINT16: { uint16_t x; x = (uint16_t) va_arg(ap, int); r = sd_bus_message_append_basic(m, *t, &x); break; } case SD_BUS_TYPE_INT64: case SD_BUS_TYPE_UINT64: { uint64_t x; x = va_arg(ap, uint64_t); r = sd_bus_message_append_basic(m, *t, &x); break; } case SD_BUS_TYPE_DOUBLE: { double x; x = va_arg(ap, double); r = sd_bus_message_append_basic(m, *t, &x); break; } case SD_BUS_TYPE_STRING: case SD_BUS_TYPE_OBJECT_PATH: case SD_BUS_TYPE_SIGNATURE: { const char *x; x = va_arg(ap, const char*); r = sd_bus_message_append_basic(m, *t, x); break; } case SD_BUS_TYPE_ARRAY: { size_t k; r = signature_element_length(t + 1, &k); if (r < 0) return r; { char s[k + 1]; memcpy(s, t + 1, k); s[k] = 0; r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s); if (r < 0) return r; } if (n_array == (unsigned) -1) { types += k; n_struct -= k; } r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array); if (r < 0) return r; types = t + 1; n_struct = k; n_array = va_arg(ap, unsigned); break; } case SD_BUS_TYPE_VARIANT: { const char *s; s = va_arg(ap, const char*); if (!s) return -EINVAL; r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s); if (r < 0) return r; r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array); if (r < 0) return r; types = s; n_struct = strlen(s); n_array = (unsigned) -1; break; } case SD_BUS_TYPE_STRUCT_BEGIN: case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { size_t k; r = signature_element_length(t, &k); if (r < 0) return r; { char s[k - 1]; memcpy(s, t + 1, k - 2); s[k - 2] = 0; r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s); if (r < 0) return r; } if (n_array == (unsigned) -1) { types += k - 1; n_struct -= k - 1; } r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array); if (r < 0) return r; types = t + 1; n_struct = k - 2; n_array = (unsigned) -1; break; } default: r = -EINVAL; } if (r < 0) return r; } return 1; } _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) { va_list ap; int r; assert_return(m, -EINVAL); assert_return(types, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(!m->poisoned, -ESTALE); va_start(ap, types); r = bus_message_append_ap(m, types, ap); va_end(ap); return r; } _public_ int sd_bus_message_append_array_space( sd_bus_message *m, char type, size_t size, void **ptr) { ssize_t align, sz; void *a; int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL); assert_return(ptr || size == 0, -EINVAL); assert_return(!m->poisoned, -ESTALE); /* alignment and size of the trivial types (except bool) is * identical for gvariant and dbus1 marshalling */ align = bus_type_get_alignment(type); sz = bus_type_get_size(type); assert_se(align > 0); assert_se(sz > 0); if (size % sz != 0) return -EINVAL; r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type)); if (r < 0) return r; a = message_extend_body(m, align, size, false, false); if (!a) return -ENOMEM; r = sd_bus_message_close_container(m); if (r < 0) return r; *ptr = a; return 0; } _public_ int sd_bus_message_append_array( sd_bus_message *m, char type, const void *ptr, size_t size) { int r; void *p; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(bus_type_is_trivial(type), -EINVAL); assert_return(ptr || size == 0, -EINVAL); assert_return(!m->poisoned, -ESTALE); r = sd_bus_message_append_array_space(m, type, size, &p); if (r < 0) return r; if (size > 0) memcpy(p, ptr, size); return 0; } _public_ int sd_bus_message_append_array_iovec( sd_bus_message *m, char type, const struct iovec *iov, unsigned n) { size_t size; unsigned i; void *p; int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(bus_type_is_trivial(type), -EINVAL); assert_return(iov || n == 0, -EINVAL); assert_return(!m->poisoned, -ESTALE); size = IOVEC_TOTAL_SIZE(iov, n); r = sd_bus_message_append_array_space(m, type, size, &p); if (r < 0) return r; for (i = 0; i < n; i++) { if (iov[i].iov_base) memcpy(p, iov[i].iov_base, iov[i].iov_len); else memzero(p, iov[i].iov_len); p = (uint8_t*) p + iov[i].iov_len; } return 0; } _public_ int sd_bus_message_append_array_memfd( sd_bus_message *m, char type, int memfd, uint64_t offset, uint64_t size) { _cleanup_close_ int copy_fd = -1; struct bus_body_part *part; ssize_t align, sz; uint64_t real_size; void *a; int r; assert_return(m, -EINVAL); assert_return(memfd >= 0, -EBADF); assert_return(bus_type_is_trivial(type), -EINVAL); assert_return(size > 0, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(!m->poisoned, -ESTALE); r = memfd_set_sealed(memfd); if (r < 0) return r; copy_fd = dup(memfd); if (copy_fd < 0) return copy_fd; r = memfd_get_size(memfd, &real_size); if (r < 0) return r; if (offset == 0 && size == (uint64_t) -1) size = real_size; else if (offset + size > real_size) return -EMSGSIZE; align = bus_type_get_alignment(type); sz = bus_type_get_size(type); assert_se(align > 0); assert_se(sz > 0); if (offset % align != 0) return -EINVAL; if (size % sz != 0) return -EINVAL; if (size > (uint64_t) (uint32_t) -1) return -EINVAL; r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type)); if (r < 0) return r; a = message_extend_body(m, align, 0, false, false); if (!a) return -ENOMEM; part = message_append_part(m); if (!part) return -ENOMEM; part->memfd = copy_fd; part->memfd_offset = offset; part->sealed = true; part->size = size; copy_fd = -1; m->body_size += size; message_extend_containers(m, size); return sd_bus_message_close_container(m); } _public_ int sd_bus_message_append_string_memfd( sd_bus_message *m, int memfd, uint64_t offset, uint64_t size) { _cleanup_close_ int copy_fd = -1; struct bus_body_part *part; struct bus_container *c; uint64_t real_size; void *a; int r; assert_return(m, -EINVAL); assert_return(memfd >= 0, -EBADF); assert_return(size > 0, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(!m->poisoned, -ESTALE); r = memfd_set_sealed(memfd); if (r < 0) return r; copy_fd = dup(memfd); if (copy_fd < 0) return copy_fd; r = memfd_get_size(memfd, &real_size); if (r < 0) return r; if (offset == 0 && size == (uint64_t) -1) size = real_size; else if (offset + size > real_size) return -EMSGSIZE; /* We require this to be NUL terminated */ if (size == 0) return -EINVAL; if (size > (uint64_t) (uint32_t) -1) return -EINVAL; c = message_get_container(m); if (c->signature && c->signature[c->index]) { /* Container signature is already set */ if (c->signature[c->index] != SD_BUS_TYPE_STRING) return -ENXIO; } else { char *e; /* Maybe we can append to the signature? But only if this is the top-level container */ if (c->enclosing != 0) return -ENXIO; e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL); if (!e) { m->poisoned = true; return -ENOMEM; } } if (!BUS_MESSAGE_IS_GVARIANT(m)) { a = message_extend_body(m, 4, 4, false, false); if (!a) return -ENOMEM; *(uint32_t*) a = size - 1; } part = message_append_part(m); if (!part) return -ENOMEM; part->memfd = copy_fd; part->memfd_offset = offset; part->sealed = true; part->size = size; copy_fd = -1; m->body_size += size; message_extend_containers(m, size); if (BUS_MESSAGE_IS_GVARIANT(m)) { r = message_add_offset(m, m->body_size); if (r < 0) { m->poisoned = true; return -ENOMEM; } } if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index++; return 0; } _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) { char **i; int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(!m->poisoned, -ESTALE); r = sd_bus_message_open_container(m, 'a', "s"); if (r < 0) return r; STRV_FOREACH(i, l) { r = sd_bus_message_append_basic(m, 's', *i); if (r < 0) return r; } return sd_bus_message_close_container(m); } static int bus_message_close_header(sd_bus_message *m) { assert(m); /* The actual user data is finished now, we just complete the variant and struct now (at least on gvariant). Remember this position, so that during parsing we know where to to put the outer container end. */ m->user_body_size = m->body_size; if (BUS_MESSAGE_IS_GVARIANT(m)) { const char *signature; size_t sz, l; void *d; /* Add offset table to end of fields array */ if (m->n_header_offsets >= 1) { uint8_t *a; unsigned i; assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]); sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets); a = message_extend_fields(m, 1, sz * m->n_header_offsets, false); if (!a) return -ENOMEM; for (i = 0; i < m->n_header_offsets; i++) bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]); } /* Add gvariant NUL byte plus signature to the end of * the body, followed by the final offset pointing to * the end of the fields array */ signature = strempty(m->root_container.signature); l = strlen(signature); sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1); d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true); if (!d) return -ENOMEM; *(uint8_t*) d = 0; *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN; memcpy((uint8_t*) d + 2, signature, l); *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END; bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size); m->footer = d; m->footer_accessible = 1 + l + 2 + sz; } else { m->header->dbus1.fields_size = m->fields_size; m->header->dbus1.body_size = m->body_size; } return 0; } int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) { struct bus_body_part *part; size_t a; unsigned i; int r; assert(m); if (m->sealed) return -EPERM; if (m->n_containers > 0) return -EBADMSG; if (m->poisoned) return -ESTALE; if (cookie > 0xffffffffULL && !BUS_MESSAGE_IS_GVARIANT(m)) return -EOPNOTSUPP; /* In vtables the return signature of method calls is listed, * let's check if they match if this is a response */ if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN && m->enforced_reply_signature && !streq(strempty(m->root_container.signature), m->enforced_reply_signature)) return -ENOMSG; /* If gvariant marshalling is used we need to close the body structure */ r = bus_message_close_struct(m, &m->root_container, false); if (r < 0) return r; /* If there's a non-trivial signature set, then add it in * here, but only on dbus1 */ if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) { r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL); if (r < 0) return r; } if (m->n_fds > 0) { r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds); if (r < 0) return r; } r = bus_message_close_header(m); if (r < 0) return r; if (BUS_MESSAGE_IS_GVARIANT(m)) m->header->dbus2.cookie = cookie; else m->header->dbus1.serial = (uint32_t) cookie; m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout; /* Add padding at the end of the fields part, since we know * the body needs to start at an 8 byte alignment. We made * sure we allocated enough space for this, so all we need to * do here is to zero it out. */ a = ALIGN8(m->fields_size) - m->fields_size; if (a > 0) memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a); /* If this is something we can send as memfd, then let's seal the memfd now. Note that we can send memfds as payload only for directed messages, and not for broadcasts. */ if (m->destination && m->bus->use_memfd) { MESSAGE_FOREACH_PART(part, i, m) if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) && part != m->body_end) { /* The last part may never be sent as memfd */ uint64_t sz; /* Try to seal it if that makes * sense. First, unmap our own map to * make sure we don't keep it busy. */ bus_body_part_unmap(part); /* Then, sync up real memfd size */ sz = part->size; r = memfd_set_size(part->memfd, sz); if (r < 0) return r; /* Finally, try to seal */ if (memfd_set_sealed(part->memfd) >= 0) part->sealed = true; } } m->root_container.end = m->user_body_size; m->root_container.index = 0; m->root_container.offset_index = 0; m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0; m->sealed = true; return 0; } int bus_body_part_map(struct bus_body_part *part) { void *p; size_t psz, shift; assert_se(part); if (part->data) return 0; if (part->size <= 0) return 0; /* For smaller zero parts (as used for padding) we don't need to map anything... */ if (part->memfd < 0 && part->is_zero && part->size < 8) { static const uint8_t zeroes[7] = { }; part->data = (void*) zeroes; return 0; } shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size()); psz = PAGE_ALIGN(part->size + shift); if (part->memfd >= 0) p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift); else if (part->is_zero) p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); else return -EINVAL; if (p == MAP_FAILED) return -errno; part->mapped = psz; part->mmap_begin = p; part->data = (uint8_t*) p + shift; part->munmap_this = true; return 0; } void bus_body_part_unmap(struct bus_body_part *part) { assert_se(part); if (part->memfd < 0) return; if (!part->mmap_begin) return; if (!part->munmap_this) return; assert_se(munmap(part->mmap_begin, part->mapped) == 0); part->mmap_begin = NULL; part->data = NULL; part->mapped = 0; part->munmap_this = false; return; } static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) { size_t k, start, end; assert(rindex); assert(align > 0); start = ALIGN_TO((size_t) *rindex, align); end = start + nbytes; if (end > sz) return -EBADMSG; /* Verify that padding is 0 */ for (k = *rindex; k < start; k++) if (((const uint8_t*) p)[k] != 0) return -EBADMSG; if (r) *r = (uint8_t*) p + start; *rindex = end; return 1; } static bool message_end_of_signature(sd_bus_message *m) { struct bus_container *c; assert(m); c = message_get_container(m); return !c->signature || c->signature[c->index] == 0; } static bool message_end_of_array(sd_bus_message *m, size_t index) { struct bus_container *c; assert(m); c = message_get_container(m); if (c->enclosing != SD_BUS_TYPE_ARRAY) return false; if (BUS_MESSAGE_IS_GVARIANT(m)) return index >= c->end; else { assert(c->array_size); return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size); } } _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) { assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); if (complete && m->n_containers > 0) return false; if (message_end_of_signature(m)) return true; if (message_end_of_array(m, m->rindex)) return true; return false; } static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) { struct bus_body_part *part; size_t begin; int r; assert(m); if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) { part = m->cached_rindex_part; begin = m->cached_rindex_part_begin; } else { part = &m->body; begin = 0; } while (part) { if (index < begin) return NULL; if (index + sz <= begin + part->size) { r = bus_body_part_map(part); if (r < 0) return NULL; if (p) *p = (uint8_t*) part->data + index - begin; m->cached_rindex_part = part; m->cached_rindex_part_begin = begin; return part; } begin += part->size; part = part->next; } return NULL; } static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) { int r; assert(m); assert(c); assert(rindex); if (!BUS_MESSAGE_IS_GVARIANT(m)) return 0; if (c->enclosing == SD_BUS_TYPE_ARRAY) { int sz; sz = bus_gvariant_get_size(c->signature); if (sz < 0) { int alignment; if (c->offset_index+1 >= c->n_offsets) goto end; /* Variable-size array */ alignment = bus_gvariant_get_alignment(c->signature); assert(alignment > 0); *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment); c->item_size = c->offsets[c->offset_index+1] - *rindex; } else { if (c->offset_index+1 >= (c->end-c->begin)/sz) goto end; /* Fixed-size array */ *rindex = c->begin + (c->offset_index+1) * sz; c->item_size = sz; } c->offset_index++; } else if (c->enclosing == 0 || c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY) { int alignment; size_t n, j; if (c->offset_index+1 >= c->n_offsets) goto end; r = signature_element_length(c->signature + c->index, &n); if (r < 0) return r; r = signature_element_length(c->signature + c->index + n, &j); if (r < 0) return r; else { char t[j+1]; memcpy(t, c->signature + c->index + n, j); t[j] = 0; alignment = bus_gvariant_get_alignment(t); } assert(alignment > 0); *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment); c->item_size = c->offsets[c->offset_index+1] - *rindex; c->offset_index++; } else if (c->enclosing == SD_BUS_TYPE_VARIANT) goto end; else assert_not_reached("Unknown container type"); return 0; end: /* Reached the end */ *rindex = c->end; c->item_size = 0; return 0; } static int message_peek_body( sd_bus_message *m, size_t *rindex, size_t align, size_t nbytes, void **ret) { size_t k, start, end, padding; struct bus_body_part *part; uint8_t *q; assert(m); assert(rindex); assert(align > 0); start = ALIGN_TO((size_t) *rindex, align); padding = start - *rindex; end = start + nbytes; if (end > m->user_body_size) return -EBADMSG; part = find_part(m, *rindex, padding, (void**) &q); if (!part) return -EBADMSG; if (q) { /* Verify padding */ for (k = 0; k < padding; k++) if (q[k] != 0) return -EBADMSG; } part = find_part(m, start, nbytes, (void**) &q); if (!part || (nbytes > 0 && !q)) return -EBADMSG; *rindex = end; if (ret) *ret = q; return 0; } static bool validate_nul(const char *s, size_t l) { /* Check for NUL chars in the string */ if (memchr(s, 0, l)) return false; /* Check for NUL termination */ if (s[l] != 0) return false; return true; } static bool validate_string(const char *s, size_t l) { if (!validate_nul(s, l)) return false; /* Check if valid UTF8 */ if (!utf8_is_valid(s)) return false; return true; } static bool validate_signature(const char *s, size_t l) { if (!validate_nul(s, l)) return false; /* Check if valid signature */ if (!signature_is_valid(s, true)) return false; return true; } static bool validate_object_path(const char *s, size_t l) { if (!validate_nul(s, l)) return false; if (!object_path_is_valid(s)) return false; return true; } _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) { struct bus_container *c; size_t rindex; void *q; int r; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); assert_return(bus_type_is_basic(type), -EINVAL); if (message_end_of_signature(m)) return -ENXIO; if (message_end_of_array(m, m->rindex)) return 0; c = message_get_container(m); if (c->signature[c->index] != type) return -ENXIO; rindex = m->rindex; if (BUS_MESSAGE_IS_GVARIANT(m)) { if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) { bool ok; r = message_peek_body(m, &rindex, 1, c->item_size, &q); if (r < 0) return r; if (type == SD_BUS_TYPE_STRING) ok = validate_string(q, c->item_size-1); else if (type == SD_BUS_TYPE_OBJECT_PATH) ok = validate_object_path(q, c->item_size-1); else ok = validate_signature(q, c->item_size-1); if (!ok) return -EBADMSG; if (p) *(const char**) p = q; } else { int sz, align; sz = bus_gvariant_get_size(CHAR_TO_STR(type)); assert(sz > 0); if ((size_t) sz != c->item_size) return -EBADMSG; align = bus_gvariant_get_alignment(CHAR_TO_STR(type)); assert(align > 0); r = message_peek_body(m, &rindex, align, c->item_size, &q); if (r < 0) return r; switch (type) { case SD_BUS_TYPE_BYTE: if (p) *(uint8_t*) p = *(uint8_t*) q; break; case SD_BUS_TYPE_BOOLEAN: if (p) *(int*) p = !!*(uint8_t*) q; break; case SD_BUS_TYPE_INT16: case SD_BUS_TYPE_UINT16: if (p) *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q); break; case SD_BUS_TYPE_INT32: case SD_BUS_TYPE_UINT32: if (p) *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); break; case SD_BUS_TYPE_INT64: case SD_BUS_TYPE_UINT64: case SD_BUS_TYPE_DOUBLE: if (p) *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q); break; case SD_BUS_TYPE_UNIX_FD: { uint32_t j; j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); if (j >= m->n_fds) return -EBADMSG; if (p) *(int*) p = m->fds[j]; break; } default: assert_not_reached("unexpected type"); } } r = container_next_item(m, c, &rindex); if (r < 0) return r; } else { if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) { uint32_t l; bool ok; r = message_peek_body(m, &rindex, 4, 4, &q); if (r < 0) return r; l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); r = message_peek_body(m, &rindex, 1, l+1, &q); if (r < 0) return r; if (type == SD_BUS_TYPE_OBJECT_PATH) ok = validate_object_path(q, l); else ok = validate_string(q, l); if (!ok) return -EBADMSG; if (p) *(const char**) p = q; } else if (type == SD_BUS_TYPE_SIGNATURE) { uint8_t l; r = message_peek_body(m, &rindex, 1, 1, &q); if (r < 0) return r; l = *(uint8_t*) q; r = message_peek_body(m, &rindex, 1, l+1, &q); if (r < 0) return r; if (!validate_signature(q, l)) return -EBADMSG; if (p) *(const char**) p = q; } else { ssize_t sz, align; align = bus_type_get_alignment(type); assert(align > 0); sz = bus_type_get_size(type); assert(sz > 0); r = message_peek_body(m, &rindex, align, sz, &q); if (r < 0) return r; switch (type) { case SD_BUS_TYPE_BYTE: if (p) *(uint8_t*) p = *(uint8_t*) q; break; case SD_BUS_TYPE_BOOLEAN: if (p) *(int*) p = !!*(uint32_t*) q; break; case SD_BUS_TYPE_INT16: case SD_BUS_TYPE_UINT16: if (p) *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q); break; case SD_BUS_TYPE_INT32: case SD_BUS_TYPE_UINT32: if (p) *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); break; case SD_BUS_TYPE_INT64: case SD_BUS_TYPE_UINT64: case SD_BUS_TYPE_DOUBLE: if (p) *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q); break; case SD_BUS_TYPE_UNIX_FD: { uint32_t j; j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); if (j >= m->n_fds) return -EBADMSG; if (p) *(int*) p = m->fds[j]; break; } default: assert_not_reached("Unknown basic type..."); } } } m->rindex = rindex; if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index++; return 1; } static int bus_message_enter_array( sd_bus_message *m, struct bus_container *c, const char *contents, uint32_t **array_size, size_t *item_size, size_t **offsets, size_t *n_offsets) { size_t rindex; void *q; int r, alignment; assert(m); assert(c); assert(contents); assert(array_size); assert(item_size); assert(offsets); assert(n_offsets); if (!signature_is_single(contents, true)) return -EINVAL; if (!c->signature || c->signature[c->index] == 0) return -ENXIO; if (c->signature[c->index] != SD_BUS_TYPE_ARRAY) return -ENXIO; if (!startswith(c->signature + c->index + 1, contents)) return -ENXIO; rindex = m->rindex; if (!BUS_MESSAGE_IS_GVARIANT(m)) { /* dbus1 */ r = message_peek_body(m, &rindex, 4, 4, &q); if (r < 0) return r; if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE) return -EBADMSG; alignment = bus_type_get_alignment(contents[0]); if (alignment < 0) return alignment; r = message_peek_body(m, &rindex, alignment, 0, NULL); if (r < 0) return r; *array_size = (uint32_t*) q; } else if (c->item_size <= 0) { /* gvariant: empty array */ *item_size = 0; *offsets = NULL; *n_offsets = 0; } else if (bus_gvariant_is_fixed_size(contents)) { /* gvariant: fixed length array */ *item_size = bus_gvariant_get_size(contents); *offsets = NULL; *n_offsets = 0; } else { size_t where, p = 0, framing, sz; unsigned i; /* gvariant: variable length array */ sz = bus_gvariant_determine_word_size(c->item_size, 0); where = rindex + c->item_size - sz; r = message_peek_body(m, &where, 1, sz, &q); if (r < 0) return r; framing = bus_gvariant_read_word_le(q, sz); if (framing > c->item_size - sz) return -EBADMSG; if ((c->item_size - framing) % sz != 0) return -EBADMSG; *n_offsets = (c->item_size - framing) / sz; where = rindex + framing; r = message_peek_body(m, &where, 1, *n_offsets * sz, &q); if (r < 0) return r; *offsets = new(size_t, *n_offsets); if (!*offsets) return -ENOMEM; for (i = 0; i < *n_offsets; i++) { size_t x; x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz); if (x > c->item_size - sz) return -EBADMSG; if (x < p) return -EBADMSG; (*offsets)[i] = rindex + x; p = x; } *item_size = (*offsets)[0] - rindex; } m->rindex = rindex; if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index += 1 + strlen(contents); return 1; } static int bus_message_enter_variant( sd_bus_message *m, struct bus_container *c, const char *contents, size_t *item_size) { size_t rindex; uint8_t l; void *q; int r; assert(m); assert(c); assert(contents); assert(item_size); if (!signature_is_single(contents, false)) return -EINVAL; if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN) return -EINVAL; if (!c->signature || c->signature[c->index] == 0) return -ENXIO; if (c->signature[c->index] != SD_BUS_TYPE_VARIANT) return -ENXIO; rindex = m->rindex; if (BUS_MESSAGE_IS_GVARIANT(m)) { size_t k, where; k = strlen(contents); if (1+k > c->item_size) return -EBADMSG; where = rindex + c->item_size - (1+k); r = message_peek_body(m, &where, 1, 1+k, &q); if (r < 0) return r; if (*(char*) q != 0) return -EBADMSG; if (memcmp((uint8_t*) q+1, contents, k)) return -ENXIO; *item_size = c->item_size - (1+k); } else { r = message_peek_body(m, &rindex, 1, 1, &q); if (r < 0) return r; l = *(uint8_t*) q; r = message_peek_body(m, &rindex, 1, l+1, &q); if (r < 0) return r; if (!validate_signature(q, l)) return -EBADMSG; if (!streq(q, contents)) return -ENXIO; } m->rindex = rindex; if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index++; return 1; } static int build_struct_offsets( sd_bus_message *m, const char *signature, size_t size, size_t *item_size, size_t **offsets, size_t *n_offsets) { unsigned n_variable = 0, n_total = 0, v; size_t previous = 0, where; const char *p; size_t sz; void *q; int r; assert(m); assert(item_size); assert(offsets); assert(n_offsets); if (isempty(signature)) { /* Unary type is encoded as *fixed* 1 byte padding */ r = message_peek_body(m, &m->rindex, 1, 1, &q); if (r < 0) return r; if (*(uint8_t *) q != 0) return -EBADMSG; *item_size = 0; *offsets = NULL; *n_offsets = 0; return 0; } sz = bus_gvariant_determine_word_size(size, 0); if (sz <= 0) return -EBADMSG; /* First, loop over signature and count variable elements and * elements in general. We use this to know how large the * offset array is at the end of the structure. Note that * GVariant only stores offsets for all variable size elements * that are not the last item. */ p = signature; while (*p != 0) { size_t n; r = signature_element_length(p, &n); if (r < 0) return r; else { char t[n+1]; memcpy(t, p, n); t[n] = 0; r = bus_gvariant_is_fixed_size(t); } if (r < 0) return r; if (r == 0 && p[n] != 0) /* except the last item */ n_variable ++; n_total++; p += n; } if (size < n_variable * sz) return -EBADMSG; where = m->rindex + size - (n_variable * sz); r = message_peek_body(m, &where, 1, n_variable * sz, &q); if (r < 0) return r; v = n_variable; *offsets = new(size_t, n_total); if (!*offsets) return -ENOMEM; *n_offsets = 0; /* Second, loop again and build an offset table */ p = signature; while (*p != 0) { size_t n, offset; int k; r = signature_element_length(p, &n); if (r < 0) return r; else { char t[n+1]; memcpy(t, p, n); t[n] = 0; k = bus_gvariant_get_size(t); if (k < 0) { size_t x; /* variable size */ if (v > 0) { v--; x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz); if (x >= size) return -EBADMSG; if (m->rindex + x < previous) return -EBADMSG; } else /* The last item's end * is determined from * the start of the * offset array */ x = size - (n_variable * sz); offset = m->rindex + x; } else { size_t align; /* fixed size */ align = bus_gvariant_get_alignment(t); assert(align > 0); offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k; } } previous = (*offsets)[(*n_offsets)++] = offset; p += n; } assert(v == 0); assert(*n_offsets == n_total); *item_size = (*offsets)[0] - m->rindex; return 0; } static int enter_struct_or_dict_entry( sd_bus_message *m, struct bus_container *c, const char *contents, size_t *item_size, size_t **offsets, size_t *n_offsets) { int r; assert(m); assert(c); assert(contents); assert(item_size); assert(offsets); assert(n_offsets); if (!BUS_MESSAGE_IS_GVARIANT(m)) { /* dbus1 */ r = message_peek_body(m, &m->rindex, 8, 0, NULL); if (r < 0) return r; } else /* gvariant with contents */ return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets); return 0; } static int bus_message_enter_struct( sd_bus_message *m, struct bus_container *c, const char *contents, size_t *item_size, size_t **offsets, size_t *n_offsets) { size_t l; int r; assert(m); assert(c); assert(contents); assert(item_size); assert(offsets); assert(n_offsets); if (!signature_is_valid(contents, false)) return -EINVAL; if (!c->signature || c->signature[c->index] == 0) return -ENXIO; l = strlen(contents); if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN || !startswith(c->signature + c->index + 1, contents) || c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END) return -ENXIO; r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets); if (r < 0) return r; if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index += 1 + l + 1; return 1; } static int bus_message_enter_dict_entry( sd_bus_message *m, struct bus_container *c, const char *contents, size_t *item_size, size_t **offsets, size_t *n_offsets) { size_t l; int r; assert(m); assert(c); assert(contents); if (!signature_is_pair(contents)) return -EINVAL; if (c->enclosing != SD_BUS_TYPE_ARRAY) return -ENXIO; if (!c->signature || c->signature[c->index] == 0) return 0; l = strlen(contents); if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN || !startswith(c->signature + c->index + 1, contents) || c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END) return -ENXIO; r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets); if (r < 0) return r; if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index += 1 + l + 1; return 1; } _public_ int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents) { struct bus_container *c, *w; uint32_t *array_size = NULL; char *signature; size_t before; size_t *offsets = NULL; size_t n_offsets = 0, item_size = 0; int r; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); assert_return(type != 0 || !contents, -EINVAL); if (type == 0 || !contents) { const char *cc; char tt; /* Allow entering into anonymous containers */ r = sd_bus_message_peek_type(m, &tt, &cc); if (r < 0) return r; if (type != 0 && type != tt) return -ENXIO; if (contents && !streq(contents, cc)) return -ENXIO; type = tt; contents = cc; } /* * We enforce a global limit on container depth, that is much * higher than the 32 structs and 32 arrays the specification * mandates. This is simpler to implement for us, and we need * this only to ensure our container array doesn't grow * without bounds. We are happy to return any data from a * message as long as the data itself is valid, even if the * overall message might be not. * * Note that the message signature is validated when * parsing the headers, and that validation does check the * 32/32 limit. * * Note that the specification defines no limits on the depth * of stacked variants, but we do. */ if (m->n_containers >= BUS_CONTAINER_DEPTH) return -EBADMSG; if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) return -ENOMEM; if (message_end_of_signature(m)) return -ENXIO; if (message_end_of_array(m, m->rindex)) return 0; c = message_get_container(m); signature = strdup(contents); if (!signature) return -ENOMEM; c->saved_index = c->index; before = m->rindex; if (type == SD_BUS_TYPE_ARRAY) r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets); else if (type == SD_BUS_TYPE_VARIANT) r = bus_message_enter_variant(m, c, contents, &item_size); else if (type == SD_BUS_TYPE_STRUCT) r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets); else if (type == SD_BUS_TYPE_DICT_ENTRY) r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets); else r = -EINVAL; if (r <= 0) { free(signature); free(offsets); return r; } /* OK, let's fill it in */ w = m->containers + m->n_containers++; w->enclosing = type; w->signature = signature; w->peeked_signature = NULL; w->index = 0; w->before = before; w->begin = m->rindex; /* Unary type has fixed size of 1, but virtual size of 0 */ if (BUS_MESSAGE_IS_GVARIANT(m) && type == SD_BUS_TYPE_STRUCT && isempty(signature)) w->end = m->rindex + 0; else w->end = m->rindex + c->item_size; w->array_size = array_size; w->item_size = item_size; w->offsets = offsets; w->n_offsets = n_offsets; w->offset_index = 0; return 1; } _public_ int sd_bus_message_exit_container(sd_bus_message *m) { struct bus_container *c; unsigned saved; int r; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); assert_return(m->n_containers > 0, -ENXIO); c = message_get_container(m); if (c->enclosing != SD_BUS_TYPE_ARRAY) { if (c->signature && c->signature[c->index] != 0) return -EBUSY; } if (BUS_MESSAGE_IS_GVARIANT(m)) { if (m->rindex < c->end) return -EBUSY; } else if (c->enclosing == SD_BUS_TYPE_ARRAY) { uint32_t l; l = BUS_MESSAGE_BSWAP32(m, *c->array_size); if (c->begin + l != m->rindex) return -EBUSY; } free(c->signature); free(c->peeked_signature); free(c->offsets); m->n_containers--; c = message_get_container(m); saved = c->index; c->index = c->saved_index; r = container_next_item(m, c, &m->rindex); c->index = saved; if (r < 0) return r; return 1; } static void message_quit_container(sd_bus_message *m) { struct bus_container *c; assert(m); assert(m->sealed); assert(m->n_containers > 0); c = message_get_container(m); /* Undo seeks */ assert(m->rindex >= c->before); m->rindex = c->before; /* Free container */ free(c->signature); free(c->offsets); m->n_containers--; /* Correct index of new top-level container */ c = message_get_container(m); c->index = c->saved_index; } _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) { struct bus_container *c; int r; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); if (message_end_of_signature(m)) goto eof; if (message_end_of_array(m, m->rindex)) goto eof; c = message_get_container(m); if (bus_type_is_basic(c->signature[c->index])) { if (contents) *contents = NULL; if (type) *type = c->signature[c->index]; return 1; } if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) { if (contents) { size_t l; char *sig; r = signature_element_length(c->signature+c->index+1, &l); if (r < 0) return r; assert(l >= 1); sig = strndup(c->signature + c->index + 1, l); if (!sig) return -ENOMEM; free(c->peeked_signature); *contents = c->peeked_signature = sig; } if (type) *type = SD_BUS_TYPE_ARRAY; return 1; } if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN || c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) { if (contents) { size_t l; char *sig; r = signature_element_length(c->signature+c->index, &l); if (r < 0) return r; assert(l >= 2); sig = strndup(c->signature + c->index + 1, l - 2); if (!sig) return -ENOMEM; free(c->peeked_signature); *contents = c->peeked_signature = sig; } if (type) *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY; return 1; } if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) { if (contents) { void *q; if (BUS_MESSAGE_IS_GVARIANT(m)) { size_t k; if (c->item_size < 2) return -EBADMSG; /* Look for the NUL delimiter that separates the payload from the signature. Since the body might be in a different part that then the signature we map byte by byte. */ for (k = 2; k <= c->item_size; k++) { size_t where; where = m->rindex + c->item_size - k; r = message_peek_body(m, &where, 1, k, &q); if (r < 0) return r; if (*(char*) q == 0) break; } if (k > c->item_size) return -EBADMSG; free(c->peeked_signature); c->peeked_signature = strndup((char*) q + 1, k - 1); if (!c->peeked_signature) return -ENOMEM; if (!signature_is_valid(c->peeked_signature, true)) return -EBADMSG; *contents = c->peeked_signature; } else { size_t rindex, l; rindex = m->rindex; r = message_peek_body(m, &rindex, 1, 1, &q); if (r < 0) return r; l = *(uint8_t*) q; r = message_peek_body(m, &rindex, 1, l+1, &q); if (r < 0) return r; if (!validate_signature(q, l)) return -EBADMSG; *contents = q; } } if (type) *type = SD_BUS_TYPE_VARIANT; return 1; } return -EINVAL; eof: if (type) *type = 0; if (contents) *contents = NULL; return 0; } _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) { struct bus_container *c; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); if (complete) { message_reset_containers(m); m->rindex = 0; c = message_get_container(m); } else { c = message_get_container(m); c->offset_index = 0; c->index = 0; m->rindex = c->begin; } c->offset_index = 0; c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin; return !isempty(c->signature); } static int message_read_ap( sd_bus_message *m, const char *types, va_list ap) { unsigned n_array, n_struct; TypeStack stack[BUS_CONTAINER_DEPTH]; unsigned stack_ptr = 0; unsigned n_loop = 0; int r; assert(m); if (isempty(types)) return 0; /* Ideally, we'd just call ourselves recursively on every * complex type. However, the state of a va_list that is * passed to a function is undefined after that function * returns. This means we need to docode the va_list linearly * in a single stackframe. We hence implement our own * home-grown stack in an array. */ n_array = (unsigned) -1; /* length of current array entries */ n_struct = strlen(types); /* length of current struct contents signature */ for (;;) { const char *t; n_loop++; if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) { r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array); if (r < 0) return r; if (r == 0) break; r = sd_bus_message_exit_container(m); if (r < 0) return r; continue; } t = types; if (n_array != (unsigned) -1) n_array --; else { types ++; n_struct--; } switch (*t) { case SD_BUS_TYPE_BYTE: case SD_BUS_TYPE_BOOLEAN: case SD_BUS_TYPE_INT16: case SD_BUS_TYPE_UINT16: case SD_BUS_TYPE_INT32: case SD_BUS_TYPE_UINT32: case SD_BUS_TYPE_INT64: case SD_BUS_TYPE_UINT64: case SD_BUS_TYPE_DOUBLE: case SD_BUS_TYPE_STRING: case SD_BUS_TYPE_OBJECT_PATH: case SD_BUS_TYPE_SIGNATURE: case SD_BUS_TYPE_UNIX_FD: { void *p; p = va_arg(ap, void*); r = sd_bus_message_read_basic(m, *t, p); if (r < 0) return r; if (r == 0) { if (n_loop <= 1) return 0; return -ENXIO; } break; } case SD_BUS_TYPE_ARRAY: { size_t k; r = signature_element_length(t + 1, &k); if (r < 0) return r; { char s[k + 1]; memcpy(s, t + 1, k); s[k] = 0; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s); if (r < 0) return r; if (r == 0) { if (n_loop <= 1) return 0; return -ENXIO; } } if (n_array == (unsigned) -1) { types += k; n_struct -= k; } r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array); if (r < 0) return r; types = t + 1; n_struct = k; n_array = va_arg(ap, unsigned); break; } case SD_BUS_TYPE_VARIANT: { const char *s; s = va_arg(ap, const char *); if (!s) return -EINVAL; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s); if (r < 0) return r; if (r == 0) { if (n_loop <= 1) return 0; return -ENXIO; } r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array); if (r < 0) return r; types = s; n_struct = strlen(s); n_array = (unsigned) -1; break; } case SD_BUS_TYPE_STRUCT_BEGIN: case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { size_t k; r = signature_element_length(t, &k); if (r < 0) return r; { char s[k - 1]; memcpy(s, t + 1, k - 2); s[k - 2] = 0; r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s); if (r < 0) return r; if (r == 0) { if (n_loop <= 1) return 0; return -ENXIO; } } if (n_array == (unsigned) -1) { types += k - 1; n_struct -= k - 1; } r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array); if (r < 0) return r; types = t + 1; n_struct = k - 2; n_array = (unsigned) -1; break; } default: return -EINVAL; } } return 1; } _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) { va_list ap; int r; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); assert_return(types, -EINVAL); va_start(ap, types); r = message_read_ap(m, types, ap); va_end(ap); return r; } _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) { int r; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); /* If types is NULL, read exactly one element */ if (!types) { struct bus_container *c; size_t l; if (message_end_of_signature(m)) return -ENXIO; if (message_end_of_array(m, m->rindex)) return 0; c = message_get_container(m); r = signature_element_length(c->signature + c->index, &l); if (r < 0) return r; types = strndupa(c->signature + c->index, l); } switch (*types) { case 0: /* Nothing to drop */ return 0; case SD_BUS_TYPE_BYTE: case SD_BUS_TYPE_BOOLEAN: case SD_BUS_TYPE_INT16: case SD_BUS_TYPE_UINT16: case SD_BUS_TYPE_INT32: case SD_BUS_TYPE_UINT32: case SD_BUS_TYPE_INT64: case SD_BUS_TYPE_UINT64: case SD_BUS_TYPE_DOUBLE: case SD_BUS_TYPE_STRING: case SD_BUS_TYPE_OBJECT_PATH: case SD_BUS_TYPE_SIGNATURE: case SD_BUS_TYPE_UNIX_FD: r = sd_bus_message_read_basic(m, *types, NULL); if (r <= 0) return r; r = sd_bus_message_skip(m, types + 1); if (r < 0) return r; return 1; case SD_BUS_TYPE_ARRAY: { size_t k; r = signature_element_length(types + 1, &k); if (r < 0) return r; { char s[k+1]; memcpy(s, types+1, k); s[k] = 0; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s); if (r <= 0) return r; for (;;) { r = sd_bus_message_skip(m, s); if (r < 0) return r; if (r == 0) break; } r = sd_bus_message_exit_container(m); if (r < 0) return r; } r = sd_bus_message_skip(m, types + 1 + k); if (r < 0) return r; return 1; } case SD_BUS_TYPE_VARIANT: { const char *contents; char x; r = sd_bus_message_peek_type(m, &x, &contents); if (r <= 0) return r; if (x != SD_BUS_TYPE_VARIANT) return -ENXIO; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents); if (r <= 0) return r; r = sd_bus_message_skip(m, contents); if (r < 0) return r; assert(r != 0); r = sd_bus_message_exit_container(m); if (r < 0) return r; r = sd_bus_message_skip(m, types + 1); if (r < 0) return r; return 1; } case SD_BUS_TYPE_STRUCT_BEGIN: case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { size_t k; r = signature_element_length(types, &k); if (r < 0) return r; { char s[k-1]; memcpy(s, types+1, k-2); s[k-2] = 0; r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s); if (r <= 0) return r; r = sd_bus_message_skip(m, s); if (r < 0) return r; r = sd_bus_message_exit_container(m); if (r < 0) return r; } r = sd_bus_message_skip(m, types + k); if (r < 0) return r; return 1; } default: return -EINVAL; } } _public_ int sd_bus_message_read_array( sd_bus_message *m, char type, const void **ptr, size_t *size) { struct bus_container *c; void *p; size_t sz; ssize_t align; int r; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); assert_return(bus_type_is_trivial(type), -EINVAL); assert_return(ptr, -EINVAL); assert_return(size, -EINVAL); assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP); r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type)); if (r <= 0) return r; c = message_get_container(m); if (BUS_MESSAGE_IS_GVARIANT(m)) { align = bus_gvariant_get_alignment(CHAR_TO_STR(type)); if (align < 0) return align; sz = c->end - c->begin; } else { align = bus_type_get_alignment(type); if (align < 0) return align; sz = BUS_MESSAGE_BSWAP32(m, *c->array_size); } if (sz == 0) /* Zero length array, let's return some aligned * pointer that is not NULL */ p = (uint8_t*) NULL + align; else { r = message_peek_body(m, &m->rindex, align, sz, &p); if (r < 0) goto fail; } r = sd_bus_message_exit_container(m); if (r < 0) goto fail; *ptr = (const void*) p; *size = sz; return 1; fail: message_quit_container(m); return r; } static int message_peek_fields( sd_bus_message *m, size_t *rindex, size_t align, size_t nbytes, void **ret) { assert(m); assert(rindex); assert(align > 0); return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret); } static int message_peek_field_uint32( sd_bus_message *m, size_t *ri, size_t item_size, uint32_t *ret) { int r; void *q; assert(m); assert(ri); if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4) return -EBADMSG; /* identical for gvariant and dbus1 */ r = message_peek_fields(m, ri, 4, 4, &q); if (r < 0) return r; if (ret) *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); return 0; } static int message_peek_field_uint64( sd_bus_message *m, size_t *ri, size_t item_size, uint64_t *ret) { int r; void *q; assert(m); assert(ri); if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8) return -EBADMSG; /* identical for gvariant and dbus1 */ r = message_peek_fields(m, ri, 8, 8, &q); if (r < 0) return r; if (ret) *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q); return 0; } static int message_peek_field_string( sd_bus_message *m, bool (*validate)(const char *p), size_t *ri, size_t item_size, const char **ret) { uint32_t l; int r; void *q; assert(m); assert(ri); if (BUS_MESSAGE_IS_GVARIANT(m)) { if (item_size <= 0) return -EBADMSG; r = message_peek_fields(m, ri, 1, item_size, &q); if (r < 0) return r; l = item_size - 1; } else { r = message_peek_field_uint32(m, ri, 4, &l); if (r < 0) return r; r = message_peek_fields(m, ri, 1, l+1, &q); if (r < 0) return r; } if (validate) { if (!validate_nul(q, l)) return -EBADMSG; if (!validate(q)) return -EBADMSG; } else { if (!validate_string(q, l)) return -EBADMSG; } if (ret) *ret = q; return 0; } static int message_peek_field_signature( sd_bus_message *m, size_t *ri, size_t item_size, const char **ret) { size_t l; int r; void *q; assert(m); assert(ri); if (BUS_MESSAGE_IS_GVARIANT(m)) { if (item_size <= 0) return -EBADMSG; r = message_peek_fields(m, ri, 1, item_size, &q); if (r < 0) return r; l = item_size - 1; } else { r = message_peek_fields(m, ri, 1, 1, &q); if (r < 0) return r; l = *(uint8_t*) q; r = message_peek_fields(m, ri, 1, l+1, &q); if (r < 0) return r; } if (!validate_signature(q, l)) return -EBADMSG; if (ret) *ret = q; return 0; } static int message_skip_fields( sd_bus_message *m, size_t *ri, uint32_t array_size, const char **signature) { size_t original_index; int r; assert(m); assert(ri); assert(signature); assert(!BUS_MESSAGE_IS_GVARIANT(m)); original_index = *ri; for (;;) { char t; size_t l; if (array_size != (uint32_t) -1 && array_size <= *ri - original_index) return 0; t = **signature; if (!t) return 0; if (t == SD_BUS_TYPE_STRING) { r = message_peek_field_string(m, NULL, ri, 0, NULL); if (r < 0) return r; (*signature)++; } else if (t == SD_BUS_TYPE_OBJECT_PATH) { r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL); if (r < 0) return r; (*signature)++; } else if (t == SD_BUS_TYPE_SIGNATURE) { r = message_peek_field_signature(m, ri, 0, NULL); if (r < 0) return r; (*signature)++; } else if (bus_type_is_basic(t)) { ssize_t align, k; align = bus_type_get_alignment(t); k = bus_type_get_size(t); assert(align > 0 && k > 0); r = message_peek_fields(m, ri, align, k, NULL); if (r < 0) return r; (*signature)++; } else if (t == SD_BUS_TYPE_ARRAY) { r = signature_element_length(*signature+1, &l); if (r < 0) return r; assert(l >= 1); { char sig[l-1], *s; uint32_t nas; int alignment; strncpy(sig, *signature + 1, l-1); s = sig; alignment = bus_type_get_alignment(sig[0]); if (alignment < 0) return alignment; r = message_peek_field_uint32(m, ri, 0, &nas); if (r < 0) return r; if (nas > BUS_ARRAY_MAX_SIZE) return -EBADMSG; r = message_peek_fields(m, ri, alignment, 0, NULL); if (r < 0) return r; r = message_skip_fields(m, ri, nas, (const char**) &s); if (r < 0) return r; } (*signature) += 1 + l; } else if (t == SD_BUS_TYPE_VARIANT) { const char *s; r = message_peek_field_signature(m, ri, 0, &s); if (r < 0) return r; r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s); if (r < 0) return r; (*signature)++; } else if (t == SD_BUS_TYPE_STRUCT || t == SD_BUS_TYPE_DICT_ENTRY) { r = signature_element_length(*signature, &l); if (r < 0) return r; assert(l >= 2); { char sig[l-1], *s; strncpy(sig, *signature + 1, l-1); s = sig; r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s); if (r < 0) return r; } *signature += l; } else return -EINVAL; } } int bus_message_parse_fields(sd_bus_message *m) { size_t ri; int r; uint32_t unix_fds = 0; bool unix_fds_set = false; void *offsets = NULL; unsigned n_offsets = 0; size_t sz = 0; unsigned i = 0; assert(m); if (BUS_MESSAGE_IS_GVARIANT(m)) { char *p; /* Read the signature from the end of the body variant first */ sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0); if (m->footer_accessible < 1 + sz) return -EBADMSG; p = (char*) m->footer + m->footer_accessible - (1 + sz); for (;;) { if (p < (char*) m->footer) return -EBADMSG; if (*p == 0) { size_t l; char *c; /* We found the beginning of the signature * string, yay! We require the body to be a * structure, so verify it and then strip the * opening/closing brackets. */ l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz); if (l < 2 || p[1] != SD_BUS_TYPE_STRUCT_BEGIN || p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END) return -EBADMSG; c = strndup(p + 1 + 1, l - 2); if (!c) return -ENOMEM; free(m->root_container.signature); m->root_container.signature = c; break; } p--; } /* Calculate the actual user body size, by removing * the trailing variant signature and struct offset * table */ m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p); /* Pull out the offset table for the fields array */ sz = bus_gvariant_determine_word_size(m->fields_size, 0); if (sz > 0) { size_t framing; void *q; ri = m->fields_size - sz; r = message_peek_fields(m, &ri, 1, sz, &q); if (r < 0) return r; framing = bus_gvariant_read_word_le(q, sz); if (framing >= m->fields_size - sz) return -EBADMSG; if ((m->fields_size - framing) % sz != 0) return -EBADMSG; ri = framing; r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets); if (r < 0) return r; n_offsets = (m->fields_size - framing) / sz; } } else m->user_body_size = m->body_size; ri = 0; while (ri < m->fields_size) { _cleanup_free_ char *sig = NULL; const char *signature; uint64_t field_type; size_t item_size = (size_t) -1; if (BUS_MESSAGE_IS_GVARIANT(m)) { uint64_t *u64; if (i >= n_offsets) break; if (i == 0) ri = 0; else ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8); r = message_peek_fields(m, &ri, 8, 8, (void**) &u64); if (r < 0) return r; field_type = BUS_MESSAGE_BSWAP64(m, *u64); } else { uint8_t *u8; r = message_peek_fields(m, &ri, 8, 1, (void**) &u8); if (r < 0) return r; field_type = *u8; } if (BUS_MESSAGE_IS_GVARIANT(m)) { size_t where, end; char *b; void *q; end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz); if (end < ri) return -EBADMSG; where = ri = ALIGN_TO(ri, 8); item_size = end - ri; r = message_peek_fields(m, &where, 1, item_size, &q); if (r < 0) return r; b = memrchr(q, 0, item_size); if (!b) return -EBADMSG; sig = strndup(b+1, item_size - (b+1-(char*) q)); if (!sig) return -ENOMEM; signature = sig; item_size = b - (char*) q; } else { r = message_peek_field_signature(m, &ri, 0, &signature); if (r < 0) return r; } switch (field_type) { case _BUS_MESSAGE_HEADER_INVALID: return -EBADMSG; case BUS_MESSAGE_HEADER_PATH: if (m->path) return -EBADMSG; if (!streq(signature, "o")) return -EBADMSG; r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path); break; case BUS_MESSAGE_HEADER_INTERFACE: if (m->interface) return -EBADMSG; if (!streq(signature, "s")) return -EBADMSG; r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface); break; case BUS_MESSAGE_HEADER_MEMBER: if (m->member) return -EBADMSG; if (!streq(signature, "s")) return -EBADMSG; r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member); break; case BUS_MESSAGE_HEADER_ERROR_NAME: if (m->error.name) return -EBADMSG; if (!streq(signature, "s")) return -EBADMSG; r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name); if (r >= 0) m->error._need_free = -1; break; case BUS_MESSAGE_HEADER_DESTINATION: if (m->destination) return -EBADMSG; if (!streq(signature, "s")) return -EBADMSG; r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination); break; case BUS_MESSAGE_HEADER_SENDER: if (m->sender) return -EBADMSG; if (!streq(signature, "s")) return -EBADMSG; r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender); if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) { m->creds.unique_name = (char*) m->sender; m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask; } break; case BUS_MESSAGE_HEADER_SIGNATURE: { const char *s; char *c; if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */ return -EBADMSG; if (m->root_container.signature) return -EBADMSG; if (!streq(signature, "g")) return -EBADMSG; r = message_peek_field_signature(m, &ri, item_size, &s); if (r < 0) return r; c = strdup(s); if (!c) return -ENOMEM; free(m->root_container.signature); m->root_container.signature = c; break; } case BUS_MESSAGE_HEADER_REPLY_SERIAL: if (m->reply_cookie != 0) return -EBADMSG; if (BUS_MESSAGE_IS_GVARIANT(m)) { /* 64bit on dbus2 */ if (!streq(signature, "t")) return -EBADMSG; r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie); if (r < 0) return r; } else { /* 32bit on dbus1 */ uint32_t serial; if (!streq(signature, "u")) return -EBADMSG; r = message_peek_field_uint32(m, &ri, item_size, &serial); if (r < 0) return r; m->reply_cookie = serial; } if (m->reply_cookie == 0) return -EBADMSG; break; case BUS_MESSAGE_HEADER_UNIX_FDS: if (unix_fds_set) return -EBADMSG; if (!streq(signature, "u")) return -EBADMSG; r = message_peek_field_uint32(m, &ri, item_size, &unix_fds); if (r < 0) return -EBADMSG; unix_fds_set = true; break; default: if (!BUS_MESSAGE_IS_GVARIANT(m)) r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature); } if (r < 0) return r; i++; } if (m->n_fds != unix_fds) return -EBADMSG; switch (m->header->type) { case SD_BUS_MESSAGE_SIGNAL: if (!m->path || !m->interface || !m->member) return -EBADMSG; if (m->reply_cookie != 0) return -EBADMSG; break; case SD_BUS_MESSAGE_METHOD_CALL: if (!m->path || !m->member) return -EBADMSG; if (m->reply_cookie != 0) return -EBADMSG; break; case SD_BUS_MESSAGE_METHOD_RETURN: if (m->reply_cookie == 0) return -EBADMSG; break; case SD_BUS_MESSAGE_METHOD_ERROR: if (m->reply_cookie == 0 || !m->error.name) return -EBADMSG; break; } /* Refuse non-local messages that claim they are local */ if (streq_ptr(m->path, "/org/freedesktop/DBus/Local")) return -EBADMSG; if (streq_ptr(m->interface, "org.freedesktop.DBus.Local")) return -EBADMSG; if (streq_ptr(m->sender, "org.freedesktop.DBus.Local")) return -EBADMSG; m->root_container.end = m->user_body_size; if (BUS_MESSAGE_IS_GVARIANT(m)) { r = build_struct_offsets( m, m->root_container.signature, m->user_body_size, &m->root_container.item_size, &m->root_container.offsets, &m->root_container.n_offsets); if (r < 0) return r; } /* Try to read the error message, but if we can't it's a non-issue */ if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR) (void) sd_bus_message_read(m, "s", &m->error.message); return 0; } _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) { assert_return(m, -EINVAL); assert_return(destination, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(!m->destination, -EEXIST); return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination); } int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) { size_t total; void *p, *e; unsigned i; struct bus_body_part *part; assert(m); assert(buffer); assert(sz); total = BUS_MESSAGE_SIZE(m); p = malloc(total); if (!p) return -ENOMEM; e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m)); MESSAGE_FOREACH_PART(part, i, m) e = mempcpy(e, part->data, part->size); assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p)); *buffer = p; *sz = total; return 0; } int bus_message_read_strv_extend(sd_bus_message *m, char ***l) { const char *s; int r; assert(m); assert(l); r = sd_bus_message_enter_container(m, 'a', "s"); if (r <= 0) return r; while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) { r = strv_extend(l, s); if (r < 0) return r; } if (r < 0) return r; r = sd_bus_message_exit_container(m); if (r < 0) return r; return 1; } _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) { char **strv = NULL; int r; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); assert_return(l, -EINVAL); r = bus_message_read_strv_extend(m, &strv); if (r <= 0) { strv_free(strv); return r; } *l = strv; return 1; } static int bus_message_get_arg_skip( sd_bus_message *m, unsigned i, char *_type, const char **_contents) { unsigned j; int r; r = sd_bus_message_rewind(m, true); if (r < 0) return r; for (j = 0;; j++) { const char *contents; char type; r = sd_bus_message_peek_type(m, &type, &contents); if (r < 0) return r; if (r == 0) return -ENXIO; /* Don't match against arguments after the first one we don't understand */ if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) && !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g"))) return -ENXIO; if (j >= i) { if (_contents) *_contents = contents; if (_type) *_type = type; return 0; } r = sd_bus_message_skip(m, NULL); if (r < 0) return r; } } int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) { char type; int r; assert(m); assert(str); r = bus_message_get_arg_skip(m, i, &type, NULL); if (r < 0) return r; if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) return -ENXIO; return sd_bus_message_read_basic(m, type, str); } int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) { const char *contents; char type; int r; assert(m); assert(strv); r = bus_message_get_arg_skip(m, i, &type, &contents); if (r < 0) return r; if (type != SD_BUS_TYPE_ARRAY) return -ENXIO; if (!STR_IN_SET(contents, "s", "o", "g")) return -ENXIO; return sd_bus_message_read_strv(m, strv); } _public_ int sd_bus_message_get_errno(sd_bus_message *m) { assert_return(m, EINVAL); if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR) return 0; return sd_bus_error_get_errno(&m->error); } _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) { struct bus_container *c; assert_return(m, NULL); c = complete ? &m->root_container : message_get_container(m); return strempty(c->signature); } _public_ int sd_bus_message_is_empty(sd_bus_message *m) { assert_return(m, -EINVAL); return isempty(m->root_container.signature); } _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) { assert_return(m, -EINVAL); return streq(strempty(m->root_container.signature), strempty(signature)); } _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) { bool done_something = false; int r; assert_return(m, -EINVAL); assert_return(source, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(source->sealed, -EPERM); do { const char *contents; char type; union { uint8_t u8; uint16_t u16; int16_t s16; uint32_t u32; int32_t s32; uint64_t u64; int64_t s64; double d64; const char *string; int i; } basic; r = sd_bus_message_peek_type(source, &type, &contents); if (r < 0) return r; if (r == 0) break; done_something = true; if (bus_type_is_container(type) > 0) { r = sd_bus_message_enter_container(source, type, contents); if (r < 0) return r; r = sd_bus_message_open_container(m, type, contents); if (r < 0) return r; r = sd_bus_message_copy(m, source, true); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_exit_container(source); if (r < 0) return r; continue; } r = sd_bus_message_read_basic(source, type, &basic); if (r < 0) return r; assert(r > 0); if (type == SD_BUS_TYPE_OBJECT_PATH || type == SD_BUS_TYPE_SIGNATURE || type == SD_BUS_TYPE_STRING) r = sd_bus_message_append_basic(m, type, basic.string); else r = sd_bus_message_append_basic(m, type, &basic); if (r < 0) return r; } while (all); return done_something; } _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) { const char *c; char t; int r; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); assert_return(!type || bus_type_is_valid(type), -EINVAL); assert_return(!contents || signature_is_valid(contents, true), -EINVAL); assert_return(type || contents, -EINVAL); assert_return(!contents || !type || bus_type_is_container(type), -EINVAL); r = sd_bus_message_peek_type(m, &t, &c); if (r <= 0) return r; if (type != 0 && type != t) return 0; if (contents && !streq_ptr(contents, c)) return 0; return 1; } _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) { assert_return(m, NULL); return m->bus; } int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL; usec_t timeout; int r; assert(bus); assert(m); assert(*m); switch ((*m)->header->type) { case SD_BUS_MESSAGE_SIGNAL: r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member); if (r < 0) return r; break; case SD_BUS_MESSAGE_METHOD_CALL: r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member); if (r < 0) return r; break; case SD_BUS_MESSAGE_METHOD_RETURN: case SD_BUS_MESSAGE_METHOD_ERROR: n = message_new(bus, (*m)->header->type); if (!n) return -ENOMEM; n->reply_cookie = (*m)->reply_cookie; r = message_append_reply_cookie(n, n->reply_cookie); if (r < 0) return r; if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) { r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message); if (r < 0) return r; n->error._need_free = -1; } break; default: return -EINVAL; } if ((*m)->destination && !n->destination) { r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination); if (r < 0) return r; } if ((*m)->sender && !n->sender) { r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender); if (r < 0) return r; } n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START); r = sd_bus_message_copy(n, *m, true); if (r < 0) return r; timeout = (*m)->timeout; if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)) timeout = BUS_DEFAULT_TIMEOUT; r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout); if (r < 0) return r; sd_bus_message_unref(*m); *m = n; n = NULL; return 0; } int bus_message_append_sender(sd_bus_message *m, const char *sender) { assert(m); assert(sender); assert_return(!m->sealed, -EPERM); assert_return(!m->sender, -EPERM); return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender); } _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) { assert_return(m, -EINVAL); assert_return(priority, -EINVAL); *priority = m->priority; return 0; } _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) { assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); m->priority = priority; return 0; } systemd-229/src/libsystemd/sd-bus/bus-message.h000066400000000000000000000156661265713322000216260ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-bus.h" #include "bus-creds.h" #include "bus-protocol.h" #include "macro.h" #include "time-util.h" struct bus_container { char enclosing; bool need_offsets:1; /* Indexes into the signature string */ unsigned index, saved_index; char *signature; size_t before, begin, end; /* dbus1: pointer to the array size value, if this is a value */ uint32_t *array_size; /* gvariant: list of offsets to end of children if this is struct/dict entry/array */ size_t *offsets, n_offsets, offsets_allocated, offset_index; size_t item_size; char *peeked_signature; }; struct bus_body_part { struct bus_body_part *next; void *data; void *mmap_begin; size_t size; size_t mapped; size_t allocated; uint64_t memfd_offset; int memfd; bool free_this:1; bool munmap_this:1; bool sealed:1; bool is_zero:1; }; struct sd_bus_message { unsigned n_ref; sd_bus *bus; uint64_t reply_cookie; const char *path; const char *interface; const char *member; const char *destination; const char *sender; sd_bus_error error; sd_bus_creds creds; usec_t monotonic; usec_t realtime; uint64_t seqnum; int64_t priority; uint64_t verify_destination_id; bool sealed:1; bool dont_send:1; bool allow_fds:1; bool free_header:1; bool free_kdbus:1; bool free_fds:1; bool release_kdbus:1; bool poisoned:1; /* The first and last bytes of the message */ struct bus_header *header; void *footer; /* How many bytes are accessible in the above pointers */ size_t header_accessible; size_t footer_accessible; size_t fields_size; size_t body_size; size_t user_body_size; struct bus_body_part body; struct bus_body_part *body_end; unsigned n_body_parts; size_t rindex; struct bus_body_part *cached_rindex_part; size_t cached_rindex_part_begin; uint32_t n_fds; int *fds; struct bus_container root_container, *containers; size_t n_containers; size_t containers_allocated; struct iovec *iovec; struct iovec iovec_fixed[2]; unsigned n_iovec; struct kdbus_msg *kdbus; char *peeked_signature; /* If set replies to this message must carry the signature * specified here to successfully seal. This is initialized * from the vtable data */ const char *enforced_reply_signature; usec_t timeout; char sender_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1]; char destination_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1]; char *destination_ptr; size_t header_offsets[_BUS_MESSAGE_HEADER_MAX]; unsigned n_header_offsets; }; static inline bool BUS_MESSAGE_NEED_BSWAP(sd_bus_message *m) { return m->header->endian != BUS_NATIVE_ENDIAN; } static inline uint16_t BUS_MESSAGE_BSWAP16(sd_bus_message *m, uint16_t u) { return BUS_MESSAGE_NEED_BSWAP(m) ? bswap_16(u) : u; } static inline uint32_t BUS_MESSAGE_BSWAP32(sd_bus_message *m, uint32_t u) { return BUS_MESSAGE_NEED_BSWAP(m) ? bswap_32(u) : u; } static inline uint64_t BUS_MESSAGE_BSWAP64(sd_bus_message *m, uint64_t u) { return BUS_MESSAGE_NEED_BSWAP(m) ? bswap_64(u) : u; } static inline uint64_t BUS_MESSAGE_COOKIE(sd_bus_message *m) { if (m->header->version == 2) return BUS_MESSAGE_BSWAP64(m, m->header->dbus2.cookie); return BUS_MESSAGE_BSWAP32(m, m->header->dbus1.serial); } static inline size_t BUS_MESSAGE_SIZE(sd_bus_message *m) { return sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size; } static inline size_t BUS_MESSAGE_BODY_BEGIN(sd_bus_message *m) { return sizeof(struct bus_header) + ALIGN8(m->fields_size); } static inline void* BUS_MESSAGE_FIELDS(sd_bus_message *m) { return (uint8_t*) m->header + sizeof(struct bus_header); } static inline bool BUS_MESSAGE_IS_GVARIANT(sd_bus_message *m) { return m->header->version == 2; } int bus_message_seal(sd_bus_message *m, uint64_t serial, usec_t timeout); int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz); int bus_message_read_strv_extend(sd_bus_message *m, char ***l); int bus_message_from_header( sd_bus *bus, void *header, size_t header_accessible, void *footer, size_t footer_accessible, size_t message_size, int *fds, unsigned n_fds, const char *label, size_t extra, sd_bus_message **ret); int bus_message_from_malloc( sd_bus *bus, void *buffer, size_t length, int *fds, unsigned n_fds, const char *label, sd_bus_message **ret); int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str); int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv); int bus_message_append_ap(sd_bus_message *m, const char *types, va_list ap); int bus_message_parse_fields(sd_bus_message *m); struct bus_body_part *message_append_part(sd_bus_message *m); #define MESSAGE_FOREACH_PART(part, i, m) \ for ((i) = 0, (part) = &(m)->body; (i) < (m)->n_body_parts; (i)++, (part) = (part)->next) int bus_body_part_map(struct bus_body_part *part); void bus_body_part_unmap(struct bus_body_part *part); int bus_message_to_errno(sd_bus_message *m); int bus_message_new_synthetic_error(sd_bus *bus, uint64_t serial, const sd_bus_error *e, sd_bus_message **m); int bus_message_remarshal(sd_bus *bus, sd_bus_message **m); int bus_message_append_sender(sd_bus_message *m, const char *sender); void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m); void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m); systemd-229/src/libsystemd/sd-bus/bus-objects.c000066400000000000000000002555011265713322000216200ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-internal.h" #include "bus-introspect.h" #include "bus-message.h" #include "bus-objects.h" #include "bus-signature.h" #include "bus-slot.h" #include "bus-type.h" #include "bus-util.h" #include "set.h" #include "string-util.h" #include "strv.h" static int node_vtable_get_userdata( sd_bus *bus, const char *path, struct node_vtable *c, void **userdata, sd_bus_error *error) { sd_bus_slot *s; void *u; int r; assert(bus); assert(path); assert(c); s = container_of(c, sd_bus_slot, node_vtable); u = s->userdata; if (c->find) { bus->current_slot = sd_bus_slot_ref(s); bus->current_userdata = u; r = c->find(bus, path, c->interface, u, &u, error); bus->current_userdata = NULL; bus->current_slot = sd_bus_slot_unref(s); if (r < 0) return r; if (sd_bus_error_is_set(error)) return -sd_bus_error_get_errno(error); if (r == 0) return r; } if (userdata) *userdata = u; return 1; } static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) { assert(p); return (uint8_t*) u + p->x.method.offset; } static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) { assert(p); return (uint8_t*) u + p->x.property.offset; } static int vtable_property_get_userdata( sd_bus *bus, const char *path, struct vtable_member *p, void **userdata, sd_bus_error *error) { void *u; int r; assert(bus); assert(path); assert(p); assert(userdata); r = node_vtable_get_userdata(bus, path, p->parent, &u, error); if (r <= 0) return r; if (bus->nodes_modified) return 0; *userdata = vtable_property_convert_userdata(p->vtable, u); return 1; } static int add_enumerated_to_set( sd_bus *bus, const char *prefix, struct node_enumerator *first, Set *s, sd_bus_error *error) { struct node_enumerator *c; int r; assert(bus); assert(prefix); assert(s); LIST_FOREACH(enumerators, c, first) { char **children = NULL, **k; sd_bus_slot *slot; if (bus->nodes_modified) return 0; slot = container_of(c, sd_bus_slot, node_enumerator); bus->current_slot = sd_bus_slot_ref(slot); bus->current_userdata = slot->userdata; r = c->callback(bus, prefix, slot->userdata, &children, error); bus->current_userdata = NULL; bus->current_slot = sd_bus_slot_unref(slot); if (r < 0) return r; if (sd_bus_error_is_set(error)) return -sd_bus_error_get_errno(error); STRV_FOREACH(k, children) { if (r < 0) { free(*k); continue; } if (!object_path_is_valid(*k)){ free(*k); r = -EINVAL; continue; } if (!object_path_startswith(*k, prefix)) { free(*k); continue; } r = set_consume(s, *k); if (r == -EEXIST) r = 0; } free(children); if (r < 0) return r; } return 0; } enum { /* if set, add_subtree() works recursively */ CHILDREN_RECURSIVE = (1U << 1), /* if set, add_subtree() scans object-manager hierarchies recursively */ CHILDREN_SUBHIERARCHIES = (1U << 0), }; static int add_subtree_to_set( sd_bus *bus, const char *prefix, struct node *n, unsigned int flags, Set *s, sd_bus_error *error) { struct node *i; int r; assert(bus); assert(prefix); assert(n); assert(s); r = add_enumerated_to_set(bus, prefix, n->enumerators, s, error); if (r < 0) return r; if (bus->nodes_modified) return 0; LIST_FOREACH(siblings, i, n->child) { char *t; if (!object_path_startswith(i->path, prefix)) continue; t = strdup(i->path); if (!t) return -ENOMEM; r = set_consume(s, t); if (r < 0 && r != -EEXIST) return r; if ((flags & CHILDREN_RECURSIVE) && ((flags & CHILDREN_SUBHIERARCHIES) || !i->object_managers)) { r = add_subtree_to_set(bus, prefix, i, flags, s, error); if (r < 0) return r; if (bus->nodes_modified) return 0; } } return 0; } static int get_child_nodes( sd_bus *bus, const char *prefix, struct node *n, unsigned int flags, Set **_s, sd_bus_error *error) { Set *s = NULL; int r; assert(bus); assert(prefix); assert(n); assert(_s); s = set_new(&string_hash_ops); if (!s) return -ENOMEM; r = add_subtree_to_set(bus, prefix, n, flags, s, error); if (r < 0) { set_free_free(s); return r; } *_s = s; return 0; } static int node_callbacks_run( sd_bus *bus, sd_bus_message *m, struct node_callback *first, bool require_fallback, bool *found_object) { struct node_callback *c; int r; assert(bus); assert(m); assert(found_object); LIST_FOREACH(callbacks, c, first) { _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; sd_bus_slot *slot; if (bus->nodes_modified) return 0; if (require_fallback && !c->is_fallback) continue; *found_object = true; if (c->last_iteration == bus->iteration_counter) continue; c->last_iteration = bus->iteration_counter; r = sd_bus_message_rewind(m, true); if (r < 0) return r; slot = container_of(c, sd_bus_slot, node_callback); bus->current_slot = sd_bus_slot_ref(slot); bus->current_handler = c->callback; bus->current_userdata = slot->userdata; r = c->callback(m, slot->userdata, &error_buffer); bus->current_userdata = NULL; bus->current_handler = NULL; bus->current_slot = sd_bus_slot_unref(slot); r = bus_maybe_reply_error(m, r, &error_buffer); if (r != 0) return r; } return 0; } #define CAPABILITY_SHIFT(x) (((x) >> __builtin_ctzll(_SD_BUS_VTABLE_CAPABILITY_MASK)) & 0xFFFF) static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, sd_bus_error *error) { uint64_t cap; int r; assert(bus); assert(m); assert(c); /* If the entire bus is trusted let's grant access */ if (bus->trusted) return 0; /* If the member is marked UNPRIVILEGED let's grant access */ if (c->vtable->flags & SD_BUS_VTABLE_UNPRIVILEGED) return 0; /* Check have the caller has the requested capability * set. Note that the flags value contains the capability * number plus one, which we need to subtract here. We do this * so that we have 0 as special value for "default * capability". */ cap = CAPABILITY_SHIFT(c->vtable->flags); if (cap == 0) cap = CAPABILITY_SHIFT(c->parent->vtable[0].flags); if (cap == 0) cap = CAP_SYS_ADMIN; else cap --; r = sd_bus_query_sender_privilege(m, cap); if (r < 0) return r; if (r > 0) return 0; return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Access to %s.%s() not permitted.", c->interface, c->member); } static int method_callbacks_run( sd_bus *bus, sd_bus_message *m, struct vtable_member *c, bool require_fallback, bool *found_object) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *signature; void *u; int r; assert(bus); assert(m); assert(c); assert(found_object); if (require_fallback && !c->parent->is_fallback) return 0; r = check_access(bus, m, c, &error); if (r < 0) return bus_maybe_reply_error(m, r, &error); r = node_vtable_get_userdata(bus, m->path, c->parent, &u, &error); if (r <= 0) return bus_maybe_reply_error(m, r, &error); if (bus->nodes_modified) return 0; u = vtable_method_convert_userdata(c->vtable, u); *found_object = true; if (c->last_iteration == bus->iteration_counter) return 0; c->last_iteration = bus->iteration_counter; r = sd_bus_message_rewind(m, true); if (r < 0) return r; signature = sd_bus_message_get_signature(m, true); if (!signature) return -EINVAL; if (!streq(strempty(c->vtable->x.method.signature), signature)) return sd_bus_reply_method_errorf( m, SD_BUS_ERROR_INVALID_ARGS, "Invalid arguments '%s' to call %s.%s(), expecting '%s'.", signature, c->interface, c->member, strempty(c->vtable->x.method.signature)); /* Keep track what the signature of the reply to this message * should be, so that this can be enforced when sealing the * reply. */ m->enforced_reply_signature = strempty(c->vtable->x.method.result); if (c->vtable->x.method.handler) { sd_bus_slot *slot; slot = container_of(c->parent, sd_bus_slot, node_vtable); bus->current_slot = sd_bus_slot_ref(slot); bus->current_handler = c->vtable->x.method.handler; bus->current_userdata = u; r = c->vtable->x.method.handler(m, u, &error); bus->current_userdata = NULL; bus->current_handler = NULL; bus->current_slot = sd_bus_slot_unref(slot); return bus_maybe_reply_error(m, r, &error); } /* If the method callback is NULL, make this a successful NOP */ r = sd_bus_reply_method_return(m, NULL); if (r < 0) return r; return 1; } static int invoke_property_get( sd_bus *bus, sd_bus_slot *slot, const sd_bus_vtable *v, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { const void *p; int r; assert(bus); assert(slot); assert(v); assert(path); assert(interface); assert(property); assert(reply); if (v->x.property.get) { bus->current_slot = sd_bus_slot_ref(slot); bus->current_userdata = userdata; r = v->x.property.get(bus, path, interface, property, reply, userdata, error); bus->current_userdata = NULL; bus->current_slot = sd_bus_slot_unref(slot); if (r < 0) return r; if (sd_bus_error_is_set(error)) return -sd_bus_error_get_errno(error); return r; } /* Automatic handling if no callback is defined. */ if (streq(v->x.property.signature, "as")) return sd_bus_message_append_strv(reply, *(char***) userdata); assert(signature_is_single(v->x.property.signature, false)); assert(bus_type_is_basic(v->x.property.signature[0])); switch (v->x.property.signature[0]) { case SD_BUS_TYPE_STRING: case SD_BUS_TYPE_SIGNATURE: p = strempty(*(char**) userdata); break; case SD_BUS_TYPE_OBJECT_PATH: p = *(char**) userdata; assert(p); break; default: p = userdata; break; } return sd_bus_message_append_basic(reply, v->x.property.signature[0], p); } static int invoke_property_set( sd_bus *bus, sd_bus_slot *slot, const sd_bus_vtable *v, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) { int r; assert(bus); assert(slot); assert(v); assert(path); assert(interface); assert(property); assert(value); if (v->x.property.set) { bus->current_slot = sd_bus_slot_ref(slot); bus->current_userdata = userdata; r = v->x.property.set(bus, path, interface, property, value, userdata, error); bus->current_userdata = NULL; bus->current_slot = sd_bus_slot_unref(slot); if (r < 0) return r; if (sd_bus_error_is_set(error)) return -sd_bus_error_get_errno(error); return r; } /* Automatic handling if no callback is defined. */ assert(signature_is_single(v->x.property.signature, false)); assert(bus_type_is_basic(v->x.property.signature[0])); switch (v->x.property.signature[0]) { case SD_BUS_TYPE_STRING: case SD_BUS_TYPE_OBJECT_PATH: case SD_BUS_TYPE_SIGNATURE: { const char *p; char *n; r = sd_bus_message_read_basic(value, v->x.property.signature[0], &p); if (r < 0) return r; n = strdup(p); if (!n) return -ENOMEM; free(*(char**) userdata); *(char**) userdata = n; break; } default: r = sd_bus_message_read_basic(value, v->x.property.signature[0], userdata); if (r < 0) return r; break; } return 1; } static int property_get_set_callbacks_run( sd_bus *bus, sd_bus_message *m, struct vtable_member *c, bool require_fallback, bool is_get, bool *found_object) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; sd_bus_slot *slot; void *u = NULL; int r; assert(bus); assert(m); assert(c); assert(found_object); if (require_fallback && !c->parent->is_fallback) return 0; r = vtable_property_get_userdata(bus, m->path, c, &u, &error); if (r <= 0) return bus_maybe_reply_error(m, r, &error); if (bus->nodes_modified) return 0; slot = container_of(c->parent, sd_bus_slot, node_vtable); *found_object = true; r = sd_bus_message_new_method_return(m, &reply); if (r < 0) return r; if (is_get) { /* Note that we do not protect against reexecution * here (using the last_iteration check, see below), * should the node tree have changed and we got called * again. We assume that property Get() calls are * ultimately without side-effects or if they aren't * then at least idempotent. */ r = sd_bus_message_open_container(reply, 'v', c->vtable->x.property.signature); if (r < 0) return r; /* Note that we do not do an access check here. Read * access to properties is always unrestricted, since * PropertiesChanged signals broadcast contents * anyway. */ r = invoke_property_get(bus, slot, c->vtable, m->path, c->interface, c->member, reply, u, &error); if (r < 0) return bus_maybe_reply_error(m, r, &error); if (bus->nodes_modified) return 0; r = sd_bus_message_close_container(reply); if (r < 0) return r; } else { const char *signature = NULL; char type = 0; if (c->vtable->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY) return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Property '%s' is not writable.", c->member); /* Avoid that we call the set routine more than once * if the processing of this message got restarted * because the node tree changed. */ if (c->last_iteration == bus->iteration_counter) return 0; c->last_iteration = bus->iteration_counter; r = sd_bus_message_peek_type(m, &type, &signature); if (r < 0) return r; if (type != 'v' || !streq(strempty(signature), strempty(c->vtable->x.property.signature))) return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Incorrect parameters for property '%s', expected '%s', got '%s'.", c->member, strempty(c->vtable->x.property.signature), strempty(signature)); r = sd_bus_message_enter_container(m, 'v', c->vtable->x.property.signature); if (r < 0) return r; r = check_access(bus, m, c, &error); if (r < 0) return bus_maybe_reply_error(m, r, &error); r = invoke_property_set(bus, slot, c->vtable, m->path, c->interface, c->member, m, u, &error); if (r < 0) return bus_maybe_reply_error(m, r, &error); if (bus->nodes_modified) return 0; r = sd_bus_message_exit_container(m); if (r < 0) return r; } r = sd_bus_send(bus, reply, NULL); if (r < 0) return r; return 1; } static int vtable_append_one_property( sd_bus *bus, sd_bus_message *reply, const char *path, struct node_vtable *c, const sd_bus_vtable *v, void *userdata, sd_bus_error *error) { sd_bus_slot *slot; int r; assert(bus); assert(reply); assert(path); assert(c); assert(v); r = sd_bus_message_open_container(reply, 'e', "sv"); if (r < 0) return r; r = sd_bus_message_append(reply, "s", v->x.property.member); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'v', v->x.property.signature); if (r < 0) return r; slot = container_of(c, sd_bus_slot, node_vtable); r = invoke_property_get(bus, slot, v, path, c->interface, v->x.property.member, reply, vtable_property_convert_userdata(v, userdata), error); if (r < 0) return r; if (bus->nodes_modified) return 0; r = sd_bus_message_close_container(reply); if (r < 0) return r; r = sd_bus_message_close_container(reply); if (r < 0) return r; return 0; } static int vtable_append_all_properties( sd_bus *bus, sd_bus_message *reply, const char *path, struct node_vtable *c, void *userdata, sd_bus_error *error) { const sd_bus_vtable *v; int r; assert(bus); assert(reply); assert(path); assert(c); if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN) return 1; for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) { if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY) continue; if (v->flags & SD_BUS_VTABLE_HIDDEN) continue; if (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT) continue; r = vtable_append_one_property(bus, reply, path, c, v, userdata, error); if (r < 0) return r; if (bus->nodes_modified) return 0; } return 1; } static int property_get_all_callbacks_run( sd_bus *bus, sd_bus_message *m, struct node_vtable *first, bool require_fallback, const char *iface, bool *found_object) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; struct node_vtable *c; bool found_interface; int r; assert(bus); assert(m); assert(found_object); r = sd_bus_message_new_method_return(m, &reply); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "{sv}"); if (r < 0) return r; found_interface = !iface || streq(iface, "org.freedesktop.DBus.Properties") || streq(iface, "org.freedesktop.DBus.Peer") || streq(iface, "org.freedesktop.DBus.Introspectable"); LIST_FOREACH(vtables, c, first) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; void *u; if (require_fallback && !c->is_fallback) continue; r = node_vtable_get_userdata(bus, m->path, c, &u, &error); if (r < 0) return bus_maybe_reply_error(m, r, &error); if (bus->nodes_modified) return 0; if (r == 0) continue; *found_object = true; if (iface && !streq(c->interface, iface)) continue; found_interface = true; r = vtable_append_all_properties(bus, reply, m->path, c, u, &error); if (r < 0) return bus_maybe_reply_error(m, r, &error); if (bus->nodes_modified) return 0; } if (!found_interface) { r = sd_bus_reply_method_errorf( m, SD_BUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface '%s'.", iface); if (r < 0) return r; return 1; } r = sd_bus_message_close_container(reply); if (r < 0) return r; r = sd_bus_send(bus, reply, NULL); if (r < 0) return r; return 1; } static int bus_node_exists( sd_bus *bus, struct node *n, const char *path, bool require_fallback) { struct node_vtable *c; struct node_callback *k; int r; assert(bus); assert(n); assert(path); /* Tests if there's anything attached directly to this node * for the specified path */ if (!require_fallback && (n->enumerators || n->object_managers)) return true; LIST_FOREACH(callbacks, k, n->callbacks) { if (require_fallback && !k->is_fallback) continue; return 1; } LIST_FOREACH(vtables, c, n->vtables) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; if (require_fallback && !c->is_fallback) continue; r = node_vtable_get_userdata(bus, path, c, NULL, &error); if (r != 0) return r; if (bus->nodes_modified) return 0; } return 0; } static int process_introspect( sd_bus *bus, sd_bus_message *m, struct node *n, bool require_fallback, bool *found_object) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_set_free_free_ Set *s = NULL; const char *previous_interface = NULL; struct introspect intro; struct node_vtable *c; bool empty; int r; assert(bus); assert(m); assert(n); assert(found_object); r = get_child_nodes(bus, m->path, n, 0, &s, &error); if (r < 0) return bus_maybe_reply_error(m, r, &error); if (bus->nodes_modified) return 0; r = introspect_begin(&intro, bus->trusted); if (r < 0) return r; r = introspect_write_default_interfaces(&intro, !require_fallback && n->object_managers); if (r < 0) return r; empty = set_isempty(s); LIST_FOREACH(vtables, c, n->vtables) { if (require_fallback && !c->is_fallback) continue; r = node_vtable_get_userdata(bus, m->path, c, NULL, &error); if (r < 0) { r = bus_maybe_reply_error(m, r, &error); goto finish; } if (bus->nodes_modified) { r = 0; goto finish; } if (r == 0) continue; empty = false; if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN) continue; if (!streq_ptr(previous_interface, c->interface)) { if (previous_interface) fputs(" \n", intro.f); fprintf(intro.f, " \n", c->interface); } r = introspect_write_interface(&intro, c->vtable); if (r < 0) goto finish; previous_interface = c->interface; } if (previous_interface) fputs(" \n", intro.f); if (empty) { /* Nothing?, let's see if we exist at all, and if not * refuse to do anything */ r = bus_node_exists(bus, n, m->path, require_fallback); if (r <= 0) goto finish; if (bus->nodes_modified) { r = 0; goto finish; } } *found_object = true; r = introspect_write_child_nodes(&intro, s, m->path); if (r < 0) goto finish; r = introspect_finish(&intro, bus, m, &reply); if (r < 0) goto finish; r = sd_bus_send(bus, reply, NULL); if (r < 0) goto finish; r = 1; finish: introspect_free(&intro); return r; } static int object_manager_serialize_path( sd_bus *bus, sd_bus_message *reply, const char *prefix, const char *path, bool require_fallback, sd_bus_error *error) { const char *previous_interface = NULL; bool found_something = false; struct node_vtable *i; struct node *n; int r; assert(bus); assert(reply); assert(prefix); assert(path); assert(error); n = hashmap_get(bus->nodes, prefix); if (!n) return 0; LIST_FOREACH(vtables, i, n->vtables) { void *u; if (require_fallback && !i->is_fallback) continue; r = node_vtable_get_userdata(bus, path, i, &u, error); if (r < 0) return r; if (bus->nodes_modified) return 0; if (r == 0) continue; if (!found_something) { /* Open the object part */ r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}"); if (r < 0) return r; r = sd_bus_message_append(reply, "o", path); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "{sa{sv}}"); if (r < 0) return r; found_something = true; } if (!streq_ptr(previous_interface, i->interface)) { /* Maybe close the previous interface part */ if (previous_interface) { r = sd_bus_message_close_container(reply); if (r < 0) return r; r = sd_bus_message_close_container(reply); if (r < 0) return r; } /* Open the new interface part */ r = sd_bus_message_open_container(reply, 'e', "sa{sv}"); if (r < 0) return r; r = sd_bus_message_append(reply, "s", i->interface); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "{sv}"); if (r < 0) return r; } r = vtable_append_all_properties(bus, reply, path, i, u, error); if (r < 0) return r; if (bus->nodes_modified) return 0; previous_interface = i->interface; } if (previous_interface) { r = sd_bus_message_close_container(reply); if (r < 0) return r; r = sd_bus_message_close_container(reply); if (r < 0) return r; } if (found_something) { r = sd_bus_message_close_container(reply); if (r < 0) return r; r = sd_bus_message_close_container(reply); if (r < 0) return r; } return 1; } static int object_manager_serialize_path_and_fallbacks( sd_bus *bus, sd_bus_message *reply, const char *path, sd_bus_error *error) { char *prefix; int r; assert(bus); assert(reply); assert(path); assert(error); /* First, add all vtables registered for this path */ r = object_manager_serialize_path(bus, reply, path, path, false, error); if (r < 0) return r; if (bus->nodes_modified) return 0; /* Second, add fallback vtables registered for any of the prefixes */ prefix = alloca(strlen(path) + 1); OBJECT_PATH_FOREACH_PREFIX(prefix, path) { r = object_manager_serialize_path(bus, reply, prefix, path, true, error); if (r < 0) return r; if (bus->nodes_modified) return 0; } return 0; } static int process_get_managed_objects( sd_bus *bus, sd_bus_message *m, struct node *n, bool require_fallback, bool *found_object) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_set_free_free_ Set *s = NULL; Iterator i; char *path; int r; assert(bus); assert(m); assert(n); assert(found_object); /* Spec says, GetManagedObjects() is only implemented on the root of a * sub-tree. Therefore, we require a registered object-manager on * exactly the queried path, otherwise, we refuse to respond. */ if (require_fallback || !n->object_managers) return 0; r = get_child_nodes(bus, m->path, n, CHILDREN_RECURSIVE, &s, &error); if (r < 0) return r; if (bus->nodes_modified) return 0; r = sd_bus_message_new_method_return(m, &reply); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "{oa{sa{sv}}}"); if (r < 0) return r; SET_FOREACH(path, s, i) { r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error); if (r < 0) return r; if (bus->nodes_modified) return 0; } r = sd_bus_message_close_container(reply); if (r < 0) return r; r = sd_bus_send(bus, reply, NULL); if (r < 0) return r; return 1; } static int object_find_and_run( sd_bus *bus, sd_bus_message *m, const char *p, bool require_fallback, bool *found_object) { struct node *n; struct vtable_member vtable_key, *v; int r; assert(bus); assert(m); assert(p); assert(found_object); n = hashmap_get(bus->nodes, p); if (!n) return 0; /* First, try object callbacks */ r = node_callbacks_run(bus, m, n->callbacks, require_fallback, found_object); if (r != 0) return r; if (bus->nodes_modified) return 0; if (!m->interface || !m->member) return 0; /* Then, look for a known method */ vtable_key.path = (char*) p; vtable_key.interface = m->interface; vtable_key.member = m->member; v = hashmap_get(bus->vtable_methods, &vtable_key); if (v) { r = method_callbacks_run(bus, m, v, require_fallback, found_object); if (r != 0) return r; if (bus->nodes_modified) return 0; } /* Then, look for a known property */ if (streq(m->interface, "org.freedesktop.DBus.Properties")) { bool get = false; get = streq(m->member, "Get"); if (get || streq(m->member, "Set")) { r = sd_bus_message_rewind(m, true); if (r < 0) return r; vtable_key.path = (char*) p; r = sd_bus_message_read(m, "ss", &vtable_key.interface, &vtable_key.member); if (r < 0) return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected interface and member parameters"); v = hashmap_get(bus->vtable_properties, &vtable_key); if (v) { r = property_get_set_callbacks_run(bus, m, v, require_fallback, get, found_object); if (r != 0) return r; } } else if (streq(m->member, "GetAll")) { const char *iface; r = sd_bus_message_rewind(m, true); if (r < 0) return r; r = sd_bus_message_read(m, "s", &iface); if (r < 0) return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected interface parameter"); if (iface[0] == 0) iface = NULL; r = property_get_all_callbacks_run(bus, m, n->vtables, require_fallback, iface, found_object); if (r != 0) return r; } } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) { if (!isempty(sd_bus_message_get_signature(m, true))) return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters"); r = process_introspect(bus, m, n, require_fallback, found_object); if (r != 0) return r; } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.ObjectManager", "GetManagedObjects")) { if (!isempty(sd_bus_message_get_signature(m, true))) return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters"); r = process_get_managed_objects(bus, m, n, require_fallback, found_object); if (r != 0) return r; } if (bus->nodes_modified) return 0; if (!*found_object) { r = bus_node_exists(bus, n, m->path, require_fallback); if (r < 0) return r; if (bus->nodes_modified) return 0; if (r > 0) *found_object = true; } return 0; } int bus_process_object(sd_bus *bus, sd_bus_message *m) { int r; size_t pl; bool found_object = false; assert(bus); assert(m); if (bus->hello_flags & KDBUS_HELLO_MONITOR) return 0; if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL) return 0; if (hashmap_isempty(bus->nodes)) return 0; /* Never respond to broadcast messages */ if (bus->bus_client && !m->destination) return 0; assert(m->path); assert(m->member); pl = strlen(m->path); do { char prefix[pl+1]; bus->nodes_modified = false; r = object_find_and_run(bus, m, m->path, false, &found_object); if (r != 0) return r; /* Look for fallback prefixes */ OBJECT_PATH_FOREACH_PREFIX(prefix, m->path) { if (bus->nodes_modified) break; r = object_find_and_run(bus, m, prefix, true, &found_object); if (r != 0) return r; } } while (bus->nodes_modified); if (!found_object) return 0; if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Get") || sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set")) r = sd_bus_reply_method_errorf( m, SD_BUS_ERROR_UNKNOWN_PROPERTY, "Unknown property or interface."); else r = sd_bus_reply_method_errorf( m, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s' or interface '%s'.", m->member, m->interface); if (r < 0) return r; return 1; } static struct node *bus_node_allocate(sd_bus *bus, const char *path) { struct node *n, *parent; const char *e; _cleanup_free_ char *s = NULL; char *p; int r; assert(bus); assert(path); assert(path[0] == '/'); n = hashmap_get(bus->nodes, path); if (n) return n; r = hashmap_ensure_allocated(&bus->nodes, &string_hash_ops); if (r < 0) return NULL; s = strdup(path); if (!s) return NULL; if (streq(path, "/")) parent = NULL; else { e = strrchr(path, '/'); assert(e); p = strndupa(path, MAX(1, e - path)); parent = bus_node_allocate(bus, p); if (!parent) return NULL; } n = new0(struct node, 1); if (!n) return NULL; n->parent = parent; n->path = s; s = NULL; /* do not free */ r = hashmap_put(bus->nodes, n->path, n); if (r < 0) { free(n->path); free(n); return NULL; } if (parent) LIST_PREPEND(siblings, parent->child, n); return n; } void bus_node_gc(sd_bus *b, struct node *n) { assert(b); if (!n) return; if (n->child || n->callbacks || n->vtables || n->enumerators || n->object_managers) return; assert(hashmap_remove(b->nodes, n->path) == n); if (n->parent) LIST_REMOVE(siblings, n->parent->child, n); free(n->path); bus_node_gc(b, n->parent); free(n); } static int bus_find_parent_object_manager(sd_bus *bus, struct node **out, const char *path) { struct node *n; assert(bus); assert(path); n = hashmap_get(bus->nodes, path); if (!n) { char *prefix; prefix = alloca(strlen(path) + 1); OBJECT_PATH_FOREACH_PREFIX(prefix, path) { n = hashmap_get(bus->nodes, prefix); if (n) break; } } while (n && !n->object_managers) n = n->parent; if (out) *out = n; return !!n; } static int bus_add_object( sd_bus *bus, sd_bus_slot **slot, bool fallback, const char *path, sd_bus_message_handler_t callback, void *userdata) { sd_bus_slot *s; struct node *n; int r; assert_return(bus, -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(callback, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); n = bus_node_allocate(bus, path); if (!n) return -ENOMEM; s = bus_slot_allocate(bus, !slot, BUS_NODE_CALLBACK, sizeof(struct node_callback), userdata); if (!s) { r = -ENOMEM; goto fail; } s->node_callback.callback = callback; s->node_callback.is_fallback = fallback; s->node_callback.node = n; LIST_PREPEND(callbacks, n->callbacks, &s->node_callback); bus->nodes_modified = true; if (slot) *slot = s; return 0; fail: sd_bus_slot_unref(s); bus_node_gc(bus, n); return r; } _public_ int sd_bus_add_object( sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_message_handler_t callback, void *userdata) { return bus_add_object(bus, slot, false, path, callback, userdata); } _public_ int sd_bus_add_fallback( sd_bus *bus, sd_bus_slot **slot, const char *prefix, sd_bus_message_handler_t callback, void *userdata) { return bus_add_object(bus, slot, true, prefix, callback, userdata); } static void vtable_member_hash_func(const void *a, struct siphash *state) { const struct vtable_member *m = a; assert(m); string_hash_func(m->path, state); string_hash_func(m->interface, state); string_hash_func(m->member, state); } static int vtable_member_compare_func(const void *a, const void *b) { const struct vtable_member *x = a, *y = b; int r; assert(x); assert(y); r = strcmp(x->path, y->path); if (r != 0) return r; r = strcmp(x->interface, y->interface); if (r != 0) return r; return strcmp(x->member, y->member); } static const struct hash_ops vtable_member_hash_ops = { .hash = vtable_member_hash_func, .compare = vtable_member_compare_func }; static int add_object_vtable_internal( sd_bus *bus, sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, bool fallback, sd_bus_object_find_t find, void *userdata) { sd_bus_slot *s = NULL; struct node_vtable *i, *existing = NULL; const sd_bus_vtable *v; struct node *n; int r; assert_return(bus, -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(interface_name_is_valid(interface), -EINVAL); assert_return(vtable, -EINVAL); assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL); assert_return(vtable[0].x.start.element_size == sizeof(struct sd_bus_vtable), -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(!streq(interface, "org.freedesktop.DBus.Properties") && !streq(interface, "org.freedesktop.DBus.Introspectable") && !streq(interface, "org.freedesktop.DBus.Peer") && !streq(interface, "org.freedesktop.DBus.ObjectManager"), -EINVAL); r = hashmap_ensure_allocated(&bus->vtable_methods, &vtable_member_hash_ops); if (r < 0) return r; r = hashmap_ensure_allocated(&bus->vtable_properties, &vtable_member_hash_ops); if (r < 0) return r; n = bus_node_allocate(bus, path); if (!n) return -ENOMEM; LIST_FOREACH(vtables, i, n->vtables) { if (i->is_fallback != fallback) { r = -EPROTOTYPE; goto fail; } if (streq(i->interface, interface)) { if (i->vtable == vtable) { r = -EEXIST; goto fail; } existing = i; } } s = bus_slot_allocate(bus, !slot, BUS_NODE_VTABLE, sizeof(struct node_vtable), userdata); if (!s) { r = -ENOMEM; goto fail; } s->node_vtable.is_fallback = fallback; s->node_vtable.vtable = vtable; s->node_vtable.find = find; s->node_vtable.interface = strdup(interface); if (!s->node_vtable.interface) { r = -ENOMEM; goto fail; } for (v = s->node_vtable.vtable+1; v->type != _SD_BUS_VTABLE_END; v++) { switch (v->type) { case _SD_BUS_VTABLE_METHOD: { struct vtable_member *m; if (!member_name_is_valid(v->x.method.member) || !signature_is_valid(strempty(v->x.method.signature), false) || !signature_is_valid(strempty(v->x.method.result), false) || !(v->x.method.handler || (isempty(v->x.method.signature) && isempty(v->x.method.result))) || v->flags & (SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) { r = -EINVAL; goto fail; } m = new0(struct vtable_member, 1); if (!m) { r = -ENOMEM; goto fail; } m->parent = &s->node_vtable; m->path = n->path; m->interface = s->node_vtable.interface; m->member = v->x.method.member; m->vtable = v; r = hashmap_put(bus->vtable_methods, m, m); if (r < 0) { free(m); goto fail; } break; } case _SD_BUS_VTABLE_WRITABLE_PROPERTY: if (!(v->x.property.set || bus_type_is_basic(v->x.property.signature[0]))) { r = -EINVAL; goto fail; } if (v->flags & SD_BUS_VTABLE_PROPERTY_CONST) { r = -EINVAL; goto fail; } /* Fall through */ case _SD_BUS_VTABLE_PROPERTY: { struct vtable_member *m; if (!member_name_is_valid(v->x.property.member) || !signature_is_single(v->x.property.signature, false) || !(v->x.property.get || bus_type_is_basic(v->x.property.signature[0]) || streq(v->x.property.signature, "as")) || (v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) || (!!(v->flags & SD_BUS_VTABLE_PROPERTY_CONST) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) > 1 || ((v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) && (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)) || (v->flags & SD_BUS_VTABLE_UNPRIVILEGED && v->type == _SD_BUS_VTABLE_PROPERTY)) { r = -EINVAL; goto fail; } m = new0(struct vtable_member, 1); if (!m) { r = -ENOMEM; goto fail; } m->parent = &s->node_vtable; m->path = n->path; m->interface = s->node_vtable.interface; m->member = v->x.property.member; m->vtable = v; r = hashmap_put(bus->vtable_properties, m, m); if (r < 0) { free(m); goto fail; } break; } case _SD_BUS_VTABLE_SIGNAL: if (!member_name_is_valid(v->x.signal.member) || !signature_is_valid(strempty(v->x.signal.signature), false) || v->flags & SD_BUS_VTABLE_UNPRIVILEGED) { r = -EINVAL; goto fail; } break; default: r = -EINVAL; goto fail; } } s->node_vtable.node = n; LIST_INSERT_AFTER(vtables, n->vtables, existing, &s->node_vtable); bus->nodes_modified = true; if (slot) *slot = s; return 0; fail: sd_bus_slot_unref(s); bus_node_gc(bus, n); return r; } _public_ int sd_bus_add_object_vtable( sd_bus *bus, sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata) { return add_object_vtable_internal(bus, slot, path, interface, vtable, false, NULL, userdata); } _public_ int sd_bus_add_fallback_vtable( sd_bus *bus, sd_bus_slot **slot, const char *prefix, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata) { return add_object_vtable_internal(bus, slot, prefix, interface, vtable, true, find, userdata); } _public_ int sd_bus_add_node_enumerator( sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_node_enumerator_t callback, void *userdata) { sd_bus_slot *s; struct node *n; int r; assert_return(bus, -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(callback, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); n = bus_node_allocate(bus, path); if (!n) return -ENOMEM; s = bus_slot_allocate(bus, !slot, BUS_NODE_ENUMERATOR, sizeof(struct node_enumerator), userdata); if (!s) { r = -ENOMEM; goto fail; } s->node_enumerator.callback = callback; s->node_enumerator.node = n; LIST_PREPEND(enumerators, n->enumerators, &s->node_enumerator); bus->nodes_modified = true; if (slot) *slot = s; return 0; fail: sd_bus_slot_unref(s); bus_node_gc(bus, n); return r; } static int emit_properties_changed_on_interface( sd_bus *bus, const char *prefix, const char *path, const char *interface, bool require_fallback, bool *found_interface, char **names) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; bool has_invalidating = false, has_changing = false; struct vtable_member key = {}; struct node_vtable *c; struct node *n; char **property; void *u = NULL; int r; assert(bus); assert(prefix); assert(path); assert(interface); assert(found_interface); n = hashmap_get(bus->nodes, prefix); if (!n) return 0; r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.Properties", "PropertiesChanged"); if (r < 0) return r; r = sd_bus_message_append(m, "s", interface); if (r < 0) return r; r = sd_bus_message_open_container(m, 'a', "{sv}"); if (r < 0) return r; key.path = prefix; key.interface = interface; LIST_FOREACH(vtables, c, n->vtables) { if (require_fallback && !c->is_fallback) continue; if (!streq(c->interface, interface)) continue; r = node_vtable_get_userdata(bus, path, c, &u, &error); if (r < 0) return r; if (bus->nodes_modified) return 0; if (r == 0) continue; *found_interface = true; if (names) { /* If the caller specified a list of * properties we include exactly those in the * PropertiesChanged message */ STRV_FOREACH(property, names) { struct vtable_member *v; assert_return(member_name_is_valid(*property), -EINVAL); key.member = *property; v = hashmap_get(bus->vtable_properties, &key); if (!v) return -ENOENT; /* If there are two vtables for the same * interface, let's handle this property when * we come to that vtable. */ if (c != v->parent) continue; assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE || v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION, -EDOM); assert_return(!(v->vtable->flags & SD_BUS_VTABLE_HIDDEN), -EDOM); if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) { has_invalidating = true; continue; } has_changing = true; r = vtable_append_one_property(bus, m, m->path, c, v->vtable, u, &error); if (r < 0) return r; if (bus->nodes_modified) return 0; } } else { const sd_bus_vtable *v; /* If the caller specified no properties list * we include all properties that are marked * as changing in the message. */ for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) { if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY) continue; if (v->flags & SD_BUS_VTABLE_HIDDEN) continue; if (v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) { has_invalidating = true; continue; } if (!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE)) continue; has_changing = true; r = vtable_append_one_property(bus, m, m->path, c, v, u, &error); if (r < 0) return r; if (bus->nodes_modified) return 0; } } } if (!has_invalidating && !has_changing) return 0; r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_open_container(m, 'a', "s"); if (r < 0) return r; if (has_invalidating) { LIST_FOREACH(vtables, c, n->vtables) { if (require_fallback && !c->is_fallback) continue; if (!streq(c->interface, interface)) continue; r = node_vtable_get_userdata(bus, path, c, &u, &error); if (r < 0) return r; if (bus->nodes_modified) return 0; if (r == 0) continue; if (names) { STRV_FOREACH(property, names) { struct vtable_member *v; key.member = *property; assert_se(v = hashmap_get(bus->vtable_properties, &key)); assert(c == v->parent); if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) continue; r = sd_bus_message_append(m, "s", *property); if (r < 0) return r; } } else { const sd_bus_vtable *v; for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) { if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY) continue; if (v->flags & SD_BUS_VTABLE_HIDDEN) continue; if (!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) continue; r = sd_bus_message_append(m, "s", v->x.property.member); if (r < 0) return r; } } } } r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_send(bus, m, NULL); if (r < 0) return r; return 1; } _public_ int sd_bus_emit_properties_changed_strv( sd_bus *bus, const char *path, const char *interface, char **names) { BUS_DONT_DESTROY(bus); bool found_interface = false; char *prefix; int r; assert_return(bus, -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(interface_name_is_valid(interface), -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; /* A non-NULL but empty names list means nothing needs to be generated. A NULL list OTOH indicates that all properties that are set to EMITS_CHANGE or EMITS_INVALIDATION shall be included in the PropertiesChanged message. */ if (names && names[0] == NULL) return 0; do { bus->nodes_modified = false; r = emit_properties_changed_on_interface(bus, path, path, interface, false, &found_interface, names); if (r != 0) return r; if (bus->nodes_modified) continue; prefix = alloca(strlen(path) + 1); OBJECT_PATH_FOREACH_PREFIX(prefix, path) { r = emit_properties_changed_on_interface(bus, prefix, path, interface, true, &found_interface, names); if (r != 0) return r; if (bus->nodes_modified) break; } } while (bus->nodes_modified); return found_interface ? 0 : -ENOENT; } _public_ int sd_bus_emit_properties_changed( sd_bus *bus, const char *path, const char *interface, const char *name, ...) { char **names; assert_return(bus, -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(interface_name_is_valid(interface), -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; if (!name) return 0; names = strv_from_stdarg_alloca(name); return sd_bus_emit_properties_changed_strv(bus, path, interface, names); } static int object_added_append_all_prefix( sd_bus *bus, sd_bus_message *m, Set *s, const char *prefix, const char *path, bool require_fallback) { const char *previous_interface = NULL; struct node_vtable *c; struct node *n; int r; assert(bus); assert(m); assert(s); assert(prefix); assert(path); n = hashmap_get(bus->nodes, prefix); if (!n) return 0; LIST_FOREACH(vtables, c, n->vtables) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; void *u = NULL; if (require_fallback && !c->is_fallback) continue; r = node_vtable_get_userdata(bus, path, c, &u, &error); if (r < 0) return r; if (bus->nodes_modified) return 0; if (r == 0) continue; if (!streq_ptr(c->interface, previous_interface)) { /* If a child-node already handled this interface, we * skip it on any of its parents. The child vtables * always fully override any conflicting vtables of * any parent node. */ if (set_get(s, c->interface)) continue; r = set_put(s, c->interface); if (r < 0) return r; if (previous_interface) { r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; } r = sd_bus_message_open_container(m, 'e', "sa{sv}"); if (r < 0) return r; r = sd_bus_message_append(m, "s", c->interface); if (r < 0) return r; r = sd_bus_message_open_container(m, 'a', "{sv}"); if (r < 0) return r; previous_interface = c->interface; } r = vtable_append_all_properties(bus, m, path, c, u, &error); if (r < 0) return r; if (bus->nodes_modified) return 0; } if (previous_interface) { r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; } return 0; } static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *path) { _cleanup_set_free_ Set *s = NULL; char *prefix; int r; assert(bus); assert(m); assert(path); /* * This appends all interfaces registered on path @path. We first add * the builtin interfaces, which are always available and handled by * sd-bus. Then, we add all interfaces registered on the exact node, * followed by all fallback interfaces registered on any parent prefix. * * If an interface is registered multiple times on the same node with * different vtables, we merge all the properties across all vtables. * However, if a child node has the same interface registered as one of * its parent nodes has as fallback, we make the child overwrite the * parent instead of extending it. Therefore, we keep a "Set" of all * handled interfaces during parent traversal, so we skip interfaces on * a parent that were overwritten by a child. */ s = set_new(&string_hash_ops); if (!s) return -ENOMEM; r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.Peer", 0); if (r < 0) return r; r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.Introspectable", 0); if (r < 0) return r; r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.Properties", 0); if (r < 0) return r; r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.ObjectManager", 0); if (r < 0) return r; r = object_added_append_all_prefix(bus, m, s, path, path, false); if (r < 0) return r; if (bus->nodes_modified) return 0; prefix = alloca(strlen(path) + 1); OBJECT_PATH_FOREACH_PREFIX(prefix, path) { r = object_added_append_all_prefix(bus, m, s, prefix, path, true); if (r < 0) return r; if (bus->nodes_modified) return 0; } return 0; } _public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) { BUS_DONT_DESTROY(bus); _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; struct node *object_manager; int r; /* * This emits an InterfacesAdded signal on the given path, by iterating * all registered vtables and fallback vtables on the path. All * properties are queried and included in the signal. * This call is equivalent to sd_bus_emit_interfaces_added() with an * explicit list of registered interfaces. However, unlike * interfaces_added(), this call can figure out the list of supported * interfaces itself. Furthermore, it properly adds the builtin * org.freedesktop.DBus.* interfaces. */ assert_return(bus, -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; r = bus_find_parent_object_manager(bus, &object_manager, path); if (r < 0) return r; if (r == 0) return -ESRCH; do { bus->nodes_modified = false; m = sd_bus_message_unref(m); r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"); if (r < 0) return r; r = sd_bus_message_append_basic(m, 'o', path); if (r < 0) return r; r = sd_bus_message_open_container(m, 'a', "{sa{sv}}"); if (r < 0) return r; r = object_added_append_all(bus, m, path); if (r < 0) return r; if (bus->nodes_modified) continue; r = sd_bus_message_close_container(m); if (r < 0) return r; } while (bus->nodes_modified); return sd_bus_send(bus, m, NULL); } static int object_removed_append_all_prefix( sd_bus *bus, sd_bus_message *m, Set *s, const char *prefix, const char *path, bool require_fallback) { const char *previous_interface = NULL; struct node_vtable *c; struct node *n; int r; assert(bus); assert(m); assert(s); assert(prefix); assert(path); n = hashmap_get(bus->nodes, prefix); if (!n) return 0; LIST_FOREACH(vtables, c, n->vtables) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; void *u = NULL; if (require_fallback && !c->is_fallback) continue; if (streq_ptr(c->interface, previous_interface)) continue; /* If a child-node already handled this interface, we * skip it on any of its parents. The child vtables * always fully override any conflicting vtables of * any parent node. */ if (set_get(s, c->interface)) continue; r = node_vtable_get_userdata(bus, path, c, &u, &error); if (r < 0) return r; if (bus->nodes_modified) return 0; if (r == 0) continue; r = set_put(s, c->interface); if (r < 0) return r; r = sd_bus_message_append(m, "s", c->interface); if (r < 0) return r; previous_interface = c->interface; } return 0; } static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char *path) { _cleanup_set_free_ Set *s = NULL; char *prefix; int r; assert(bus); assert(m); assert(path); /* see sd_bus_emit_object_added() for details */ s = set_new(&string_hash_ops); if (!s) return -ENOMEM; r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.Peer"); if (r < 0) return r; r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.Introspectable"); if (r < 0) return r; r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.Properties"); if (r < 0) return r; r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.ObjectManager"); if (r < 0) return r; r = object_removed_append_all_prefix(bus, m, s, path, path, false); if (r < 0) return r; if (bus->nodes_modified) return 0; prefix = alloca(strlen(path) + 1); OBJECT_PATH_FOREACH_PREFIX(prefix, path) { r = object_removed_append_all_prefix(bus, m, s, prefix, path, true); if (r < 0) return r; if (bus->nodes_modified) return 0; } return 0; } _public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) { BUS_DONT_DESTROY(bus); _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; struct node *object_manager; int r; /* * This is like sd_bus_emit_object_added(), but emits an * InterfacesRemoved signal on the given path. This only includes any * registered interfaces but skips the properties. Note that this will * call into the find() callbacks of any registered vtable. Therefore, * you must call this function before destroying/unlinking your object. * Otherwise, the list of interfaces will be incomplete. However, note * that this will *NOT* call into any property callback. Therefore, the * object might be in an "destructed" state, as long as we can find it. */ assert_return(bus, -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; r = bus_find_parent_object_manager(bus, &object_manager, path); if (r < 0) return r; if (r == 0) return -ESRCH; do { bus->nodes_modified = false; m = sd_bus_message_unref(m); r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"); if (r < 0) return r; r = sd_bus_message_append_basic(m, 'o', path); if (r < 0) return r; r = sd_bus_message_open_container(m, 'a', "s"); if (r < 0) return r; r = object_removed_append_all(bus, m, path); if (r < 0) return r; if (bus->nodes_modified) continue; r = sd_bus_message_close_container(m); if (r < 0) return r; } while (bus->nodes_modified); return sd_bus_send(bus, m, NULL); } static int interfaces_added_append_one_prefix( sd_bus *bus, sd_bus_message *m, const char *prefix, const char *path, const char *interface, bool require_fallback) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; bool found_interface = false; struct node_vtable *c; struct node *n; void *u = NULL; int r; assert(bus); assert(m); assert(prefix); assert(path); assert(interface); n = hashmap_get(bus->nodes, prefix); if (!n) return 0; LIST_FOREACH(vtables, c, n->vtables) { if (require_fallback && !c->is_fallback) continue; if (!streq(c->interface, interface)) continue; r = node_vtable_get_userdata(bus, path, c, &u, &error); if (r < 0) return r; if (bus->nodes_modified) return 0; if (r == 0) continue; if (!found_interface) { r = sd_bus_message_append_basic(m, 's', interface); if (r < 0) return r; r = sd_bus_message_open_container(m, 'a', "{sv}"); if (r < 0) return r; found_interface = true; } r = vtable_append_all_properties(bus, m, path, c, u, &error); if (r < 0) return r; if (bus->nodes_modified) return 0; } if (found_interface) { r = sd_bus_message_close_container(m); if (r < 0) return r; } return found_interface; } static int interfaces_added_append_one( sd_bus *bus, sd_bus_message *m, const char *path, const char *interface) { char *prefix; int r; assert(bus); assert(m); assert(path); assert(interface); r = interfaces_added_append_one_prefix(bus, m, path, path, interface, false); if (r != 0) return r; if (bus->nodes_modified) return 0; prefix = alloca(strlen(path) + 1); OBJECT_PATH_FOREACH_PREFIX(prefix, path) { r = interfaces_added_append_one_prefix(bus, m, prefix, path, interface, true); if (r != 0) return r; if (bus->nodes_modified) return 0; } return -ENOENT; } _public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) { BUS_DONT_DESTROY(bus); _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; struct node *object_manager; char **i; int r; assert_return(bus, -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; if (strv_isempty(interfaces)) return 0; r = bus_find_parent_object_manager(bus, &object_manager, path); if (r < 0) return r; if (r == 0) return -ESRCH; do { bus->nodes_modified = false; m = sd_bus_message_unref(m); r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"); if (r < 0) return r; r = sd_bus_message_append_basic(m, 'o', path); if (r < 0) return r; r = sd_bus_message_open_container(m, 'a', "{sa{sv}}"); if (r < 0) return r; STRV_FOREACH(i, interfaces) { assert_return(interface_name_is_valid(*i), -EINVAL); r = sd_bus_message_open_container(m, 'e', "sa{sv}"); if (r < 0) return r; r = interfaces_added_append_one(bus, m, path, *i); if (r < 0) return r; if (bus->nodes_modified) break; r = sd_bus_message_close_container(m); if (r < 0) return r; } if (bus->nodes_modified) continue; r = sd_bus_message_close_container(m); if (r < 0) return r; } while (bus->nodes_modified); return sd_bus_send(bus, m, NULL); } _public_ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) { char **interfaces; assert_return(bus, -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; interfaces = strv_from_stdarg_alloca(interface); return sd_bus_emit_interfaces_added_strv(bus, path, interfaces); } _public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; struct node *object_manager; int r; assert_return(bus, -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; if (strv_isempty(interfaces)) return 0; r = bus_find_parent_object_manager(bus, &object_manager, path); if (r < 0) return r; if (r == 0) return -ESRCH; r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"); if (r < 0) return r; r = sd_bus_message_append_basic(m, 'o', path); if (r < 0) return r; r = sd_bus_message_append_strv(m, interfaces); if (r < 0) return r; return sd_bus_send(bus, m, NULL); } _public_ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) { char **interfaces; assert_return(bus, -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; interfaces = strv_from_stdarg_alloca(interface); return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces); } _public_ int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path) { sd_bus_slot *s; struct node *n; int r; assert_return(bus, -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); n = bus_node_allocate(bus, path); if (!n) return -ENOMEM; s = bus_slot_allocate(bus, !slot, BUS_NODE_OBJECT_MANAGER, sizeof(struct node_object_manager), NULL); if (!s) { r = -ENOMEM; goto fail; } s->node_object_manager.node = n; LIST_PREPEND(object_managers, n->object_managers, &s->node_object_manager); bus->nodes_modified = true; if (slot) *slot = s; return 0; fail: sd_bus_slot_unref(s); bus_node_gc(bus, n); return r; } systemd-229/src/libsystemd/sd-bus/bus-objects.h000066400000000000000000000015351265713322000216210ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-internal.h" int bus_process_object(sd_bus *bus, sd_bus_message *m); void bus_node_gc(sd_bus *b, struct node *n); systemd-229/src/libsystemd/sd-bus/bus-protocol.h000066400000000000000000000156421265713322000220350ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" /* Packet header */ struct _packed_ bus_header { /* The first four fields are identical for dbus1, and dbus2 */ uint8_t endian; uint8_t type; uint8_t flags; uint8_t version; union _packed_ { /* dbus1: Used for SOCK_STREAM connections */ struct _packed_ { uint32_t body_size; /* Note that what the bus spec calls "serial" we'll call "cookie" instead, because we don't want to imply that the cookie was in any way monotonically increasing. */ uint32_t serial; uint32_t fields_size; } dbus1; /* dbus2: Used for kdbus connections */ struct _packed_ { uint32_t _reserved; uint64_t cookie; } dbus2; /* Note that both header versions have the same size! */ }; }; /* Endianness */ enum { _BUS_INVALID_ENDIAN = 0, BUS_LITTLE_ENDIAN = 'l', BUS_BIG_ENDIAN = 'B', #if __BYTE_ORDER == __BIG_ENDIAN BUS_NATIVE_ENDIAN = BUS_BIG_ENDIAN, BUS_REVERSE_ENDIAN = BUS_LITTLE_ENDIAN #else BUS_NATIVE_ENDIAN = BUS_LITTLE_ENDIAN, BUS_REVERSE_ENDIAN = BUS_BIG_ENDIAN #endif }; /* Flags */ enum { BUS_MESSAGE_NO_REPLY_EXPECTED = 1, BUS_MESSAGE_NO_AUTO_START = 2, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION = 4, }; /* Header fields */ enum { _BUS_MESSAGE_HEADER_INVALID = 0, BUS_MESSAGE_HEADER_PATH, BUS_MESSAGE_HEADER_INTERFACE, BUS_MESSAGE_HEADER_MEMBER, BUS_MESSAGE_HEADER_ERROR_NAME, BUS_MESSAGE_HEADER_REPLY_SERIAL, BUS_MESSAGE_HEADER_DESTINATION, BUS_MESSAGE_HEADER_SENDER, BUS_MESSAGE_HEADER_SIGNATURE, BUS_MESSAGE_HEADER_UNIX_FDS, _BUS_MESSAGE_HEADER_MAX }; /* RequestName parameters */ enum { BUS_NAME_ALLOW_REPLACEMENT = 1, BUS_NAME_REPLACE_EXISTING = 2, BUS_NAME_DO_NOT_QUEUE = 4 }; /* RequestName returns */ enum { BUS_NAME_PRIMARY_OWNER = 1, BUS_NAME_IN_QUEUE = 2, BUS_NAME_EXISTS = 3, BUS_NAME_ALREADY_OWNER = 4 }; /* ReleaseName returns */ enum { BUS_NAME_RELEASED = 1, BUS_NAME_NON_EXISTENT = 2, BUS_NAME_NOT_OWNER = 3, }; /* StartServiceByName returns */ enum { BUS_START_REPLY_SUCCESS = 1, BUS_START_REPLY_ALREADY_RUNNING = 2, }; #define BUS_INTROSPECT_DOCTYPE \ "\n" #define BUS_INTROSPECT_INTERFACE_PEER \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" #define BUS_INTROSPECT_INTERFACE_INTROSPECTABLE \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" #define BUS_INTROSPECT_INTERFACE_PROPERTIES \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" #define BUS_INTROSPECT_INTERFACE_OBJECT_MANAGER \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" systemd-229/src/libsystemd/sd-bus/bus-signature.c000066400000000000000000000077661265713322000222000ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "bus-signature.h" #include "bus-type.h" static int signature_element_length_internal( const char *s, bool allow_dict_entry, unsigned array_depth, unsigned struct_depth, size_t *l) { int r; if (!s) return -EINVAL; assert(l); if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) { *l = 1; return 0; } if (*s == SD_BUS_TYPE_ARRAY) { size_t t; if (array_depth >= 32) return -EINVAL; r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t); if (r < 0) return r; *l = t + 1; return 0; } if (*s == SD_BUS_TYPE_STRUCT_BEGIN) { const char *p = s + 1; if (struct_depth >= 32) return -EINVAL; while (*p != SD_BUS_TYPE_STRUCT_END) { size_t t; r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t); if (r < 0) return r; p += t; } *l = p - s + 1; return 0; } if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) { const char *p = s + 1; unsigned n = 0; if (struct_depth >= 32) return -EINVAL; while (*p != SD_BUS_TYPE_DICT_ENTRY_END) { size_t t; if (n == 0 && !bus_type_is_basic(*p)) return -EINVAL; r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t); if (r < 0) return r; p += t; n++; } if (n != 2) return -EINVAL; *l = p - s + 1; return 0; } return -EINVAL; } int signature_element_length(const char *s, size_t *l) { return signature_element_length_internal(s, true, 0, 0, l); } bool signature_is_single(const char *s, bool allow_dict_entry) { int r; size_t t; if (!s) return false; r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t); if (r < 0) return false; return s[t] == 0; } bool signature_is_pair(const char *s) { if (!s) return false; if (!bus_type_is_basic(*s)) return false; return signature_is_single(s + 1, false); } bool signature_is_valid(const char *s, bool allow_dict_entry) { const char *p; int r; if (!s) return false; p = s; while (*p) { size_t t; r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t); if (r < 0) return false; p += t; } return p - s <= 255; } systemd-229/src/libsystemd/sd-bus/bus-signature.h000066400000000000000000000017221265713322000221670ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include bool signature_is_single(const char *s, bool allow_dict_entry); bool signature_is_pair(const char *s); bool signature_is_valid(const char *s, bool allow_dict_entry); int signature_element_length(const char *s, size_t *l); systemd-229/src/libsystemd/sd-bus/bus-slot.c000066400000000000000000000205231265713322000211420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "alloc-util.h" #include "bus-control.h" #include "bus-objects.h" #include "bus-slot.h" #include "string-util.h" sd_bus_slot *bus_slot_allocate( sd_bus *bus, bool floating, BusSlotType type, size_t extra, void *userdata) { sd_bus_slot *slot; assert(bus); slot = malloc0(offsetof(sd_bus_slot, reply_callback) + extra); if (!slot) return NULL; slot->n_ref = 1; slot->type = type; slot->bus = bus; slot->floating = floating; slot->userdata = userdata; if (!floating) sd_bus_ref(bus); LIST_PREPEND(slots, bus->slots, slot); return slot; } _public_ sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot) { if (!slot) return NULL; assert(slot->n_ref > 0); slot->n_ref++; return slot; } void bus_slot_disconnect(sd_bus_slot *slot) { sd_bus *bus; assert(slot); if (!slot->bus) return; switch (slot->type) { case BUS_REPLY_CALLBACK: if (slot->reply_callback.cookie != 0) ordered_hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie); if (slot->reply_callback.timeout != 0) prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx); break; case BUS_FILTER_CALLBACK: slot->bus->filter_callbacks_modified = true; LIST_REMOVE(callbacks, slot->bus->filter_callbacks, &slot->filter_callback); break; case BUS_MATCH_CALLBACK: if (slot->match_added) bus_remove_match_internal(slot->bus, slot->match_callback.match_string, slot->match_callback.cookie); slot->bus->match_callbacks_modified = true; bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback); free(slot->match_callback.match_string); break; case BUS_NODE_CALLBACK: if (slot->node_callback.node) { LIST_REMOVE(callbacks, slot->node_callback.node->callbacks, &slot->node_callback); slot->bus->nodes_modified = true; bus_node_gc(slot->bus, slot->node_callback.node); } break; case BUS_NODE_ENUMERATOR: if (slot->node_enumerator.node) { LIST_REMOVE(enumerators, slot->node_enumerator.node->enumerators, &slot->node_enumerator); slot->bus->nodes_modified = true; bus_node_gc(slot->bus, slot->node_enumerator.node); } break; case BUS_NODE_OBJECT_MANAGER: if (slot->node_object_manager.node) { LIST_REMOVE(object_managers, slot->node_object_manager.node->object_managers, &slot->node_object_manager); slot->bus->nodes_modified = true; bus_node_gc(slot->bus, slot->node_object_manager.node); } break; case BUS_NODE_VTABLE: if (slot->node_vtable.node && slot->node_vtable.interface && slot->node_vtable.vtable) { const sd_bus_vtable *v; for (v = slot->node_vtable.vtable; v->type != _SD_BUS_VTABLE_END; v++) { struct vtable_member *x = NULL; switch (v->type) { case _SD_BUS_VTABLE_METHOD: { struct vtable_member key; key.path = slot->node_vtable.node->path; key.interface = slot->node_vtable.interface; key.member = v->x.method.member; x = hashmap_remove(slot->bus->vtable_methods, &key); break; } case _SD_BUS_VTABLE_PROPERTY: case _SD_BUS_VTABLE_WRITABLE_PROPERTY: { struct vtable_member key; key.path = slot->node_vtable.node->path; key.interface = slot->node_vtable.interface; key.member = v->x.method.member; x = hashmap_remove(slot->bus->vtable_properties, &key); break; }} free(x); } } free(slot->node_vtable.interface); if (slot->node_vtable.node) { LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable); slot->bus->nodes_modified = true; bus_node_gc(slot->bus, slot->node_vtable.node); } break; default: assert_not_reached("Wut? Unknown slot type?"); } bus = slot->bus; slot->type = _BUS_SLOT_INVALID; slot->bus = NULL; LIST_REMOVE(slots, bus->slots, slot); if (!slot->floating) sd_bus_unref(bus); } _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) { if (!slot) return NULL; assert(slot->n_ref > 0); if (slot->n_ref > 1) { slot->n_ref --; return NULL; } bus_slot_disconnect(slot); free(slot->description); free(slot); return NULL; } _public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) { assert_return(slot, NULL); return slot->bus; } _public_ void *sd_bus_slot_get_userdata(sd_bus_slot *slot) { assert_return(slot, NULL); return slot->userdata; } _public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) { void *ret; assert_return(slot, NULL); ret = slot->userdata; slot->userdata = userdata; return ret; } _public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) { assert_return(slot, NULL); assert_return(slot->type >= 0, NULL); if (slot->bus->current_slot != slot) return NULL; return slot->bus->current_message; } _public_ sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *slot) { assert_return(slot, NULL); assert_return(slot->type >= 0, NULL); if (slot->bus->current_slot != slot) return NULL; return slot->bus->current_handler; } _public_ void* sd_bus_slot_get_current_userdata(sd_bus_slot *slot) { assert_return(slot, NULL); assert_return(slot->type >= 0, NULL); if (slot->bus->current_slot != slot) return NULL; return slot->bus->current_userdata; } _public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description) { assert_return(slot, -EINVAL); return free_and_strdup(&slot->description, description); } _public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) { assert_return(slot, -EINVAL); assert_return(description, -EINVAL); assert_return(slot->description, -ENXIO); *description = slot->description; return 0; } systemd-229/src/libsystemd/sd-bus/bus-slot.h000066400000000000000000000016471265713322000211550ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "bus-internal.h" sd_bus_slot *bus_slot_allocate(sd_bus *bus, bool floating, BusSlotType type, size_t extra, void *userdata); void bus_slot_disconnect(sd_bus_slot *slot); systemd-229/src/libsystemd/sd-bus/bus-socket.c000066400000000000000000000751321265713322000214570ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-bus.h" #include "sd-daemon.h" #include "alloc-util.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-socket.h" #include "fd-util.h" #include "formats-util.h" #include "hexdecoct.h" #include "macro.h" #include "missing.h" #include "selinux-util.h" #include "signal-util.h" #include "stdio-util.h" #include "string-util.h" #include "user-util.h" #include "utf8.h" #include "util.h" #define SNDBUF_SIZE (8*1024*1024) static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) { while (size > 0) { struct iovec *i = iov + *idx; if (i->iov_len > size) { i->iov_base = (uint8_t*) i->iov_base + size; i->iov_len -= size; return; } size -= i->iov_len; i->iov_base = NULL; i->iov_len = 0; (*idx) ++; } } static int append_iovec(sd_bus_message *m, const void *p, size_t sz) { assert(m); assert(p); assert(sz > 0); m->iovec[m->n_iovec].iov_base = (void*) p; m->iovec[m->n_iovec].iov_len = sz; m->n_iovec++; return 0; } static int bus_message_setup_iovec(sd_bus_message *m) { struct bus_body_part *part; unsigned n, i; int r; assert(m); assert(m->sealed); if (m->n_iovec > 0) return 0; assert(!m->iovec); n = 1 + m->n_body_parts; if (n < ELEMENTSOF(m->iovec_fixed)) m->iovec = m->iovec_fixed; else { m->iovec = new(struct iovec, n); if (!m->iovec) { r = -ENOMEM; goto fail; } } r = append_iovec(m, m->header, BUS_MESSAGE_BODY_BEGIN(m)); if (r < 0) goto fail; MESSAGE_FOREACH_PART(part, i, m) { r = bus_body_part_map(part); if (r < 0) goto fail; r = append_iovec(m, part->data, part->size); if (r < 0) goto fail; } assert(n == m->n_iovec); return 0; fail: m->poisoned = true; return r; } bool bus_socket_auth_needs_write(sd_bus *b) { unsigned i; if (b->auth_index >= ELEMENTSOF(b->auth_iovec)) return false; for (i = b->auth_index; i < ELEMENTSOF(b->auth_iovec); i++) { struct iovec *j = b->auth_iovec + i; if (j->iov_len > 0) return true; } return false; } static int bus_socket_write_auth(sd_bus *b) { ssize_t k; assert(b); assert(b->state == BUS_AUTHENTICATING); if (!bus_socket_auth_needs_write(b)) return 0; if (b->prefer_writev) k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index); else { struct msghdr mh; zero(mh); mh.msg_iov = b->auth_iovec + b->auth_index; mh.msg_iovlen = ELEMENTSOF(b->auth_iovec) - b->auth_index; k = sendmsg(b->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL); if (k < 0 && errno == ENOTSOCK) { b->prefer_writev = true; k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index); } } if (k < 0) return errno == EAGAIN ? 0 : -errno; iovec_advance(b->auth_iovec, &b->auth_index, (size_t) k); return 1; } static int bus_socket_auth_verify_client(sd_bus *b) { char *e, *f, *start; sd_id128_t peer; unsigned i; int r; assert(b); /* We expect two response lines: "OK" and possibly * "AGREE_UNIX_FD" */ e = memmem_safe(b->rbuffer, b->rbuffer_size, "\r\n", 2); if (!e) return 0; if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD) { f = memmem(e + 2, b->rbuffer_size - (e - (char*) b->rbuffer) - 2, "\r\n", 2); if (!f) return 0; start = f + 2; } else { f = NULL; start = e + 2; } /* Nice! We got all the lines we need. First check the OK * line */ if (e - (char*) b->rbuffer != 3 + 32) return -EPERM; if (memcmp(b->rbuffer, "OK ", 3)) return -EPERM; b->auth = b->anonymous_auth ? BUS_AUTH_ANONYMOUS : BUS_AUTH_EXTERNAL; for (i = 0; i < 32; i += 2) { int x, y; x = unhexchar(((char*) b->rbuffer)[3 + i]); y = unhexchar(((char*) b->rbuffer)[3 + i + 1]); if (x < 0 || y < 0) return -EINVAL; peer.bytes[i/2] = ((uint8_t) x << 4 | (uint8_t) y); } if (!sd_id128_equal(b->server_id, SD_ID128_NULL) && !sd_id128_equal(b->server_id, peer)) return -EPERM; b->server_id = peer; /* And possibly check the second line, too */ if (f) b->can_fds = (f - e == strlen("\r\nAGREE_UNIX_FD")) && memcmp(e + 2, "AGREE_UNIX_FD", strlen("AGREE_UNIX_FD")) == 0; b->rbuffer_size -= (start - (char*) b->rbuffer); memmove(b->rbuffer, start, b->rbuffer_size); r = bus_start_running(b); if (r < 0) return r; return 1; } static bool line_equals(const char *s, size_t m, const char *line) { size_t l; l = strlen(line); if (l != m) return false; return memcmp(s, line, l) == 0; } static bool line_begins(const char *s, size_t m, const char *word) { size_t l; l = strlen(word); if (m < l) return false; if (memcmp(s, word, l) != 0) return false; return m == l || (m > l && s[l] == ' '); } static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) { _cleanup_free_ char *token = NULL; size_t len; int r; if (!b->anonymous_auth) return 0; if (l <= 0) return 1; assert(p[0] == ' '); p++; l--; if (l % 2 != 0) return 0; r = unhexmem(p, l, (void **) &token, &len); if (r < 0) return 0; if (memchr(token, 0, len)) return 0; return !!utf8_is_valid(token); } static int verify_external_token(sd_bus *b, const char *p, size_t l) { _cleanup_free_ char *token = NULL; size_t len; uid_t u; int r; /* We don't do any real authentication here. Instead, we if * the owner of this bus wanted authentication he should have * checked SO_PEERCRED before even creating the bus object. */ if (!b->anonymous_auth && !b->ucred_valid) return 0; if (l <= 0) return 1; assert(p[0] == ' '); p++; l--; if (l % 2 != 0) return 0; r = unhexmem(p, l, (void**) &token, &len); if (r < 0) return 0; if (memchr(token, 0, len)) return 0; r = parse_uid(token, &u); if (r < 0) return 0; /* We ignore the passed value if anonymous authentication is * on anyway. */ if (!b->anonymous_auth && u != b->ucred.uid) return 0; return 1; } static int bus_socket_auth_write(sd_bus *b, const char *t) { char *p; size_t l; assert(b); assert(t); /* We only make use of the first iovec */ assert(b->auth_index == 0 || b->auth_index == 1); l = strlen(t); p = malloc(b->auth_iovec[0].iov_len + l); if (!p) return -ENOMEM; memcpy(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len); memcpy(p + b->auth_iovec[0].iov_len, t, l); b->auth_iovec[0].iov_base = p; b->auth_iovec[0].iov_len += l; free(b->auth_buffer); b->auth_buffer = p; b->auth_index = 0; return 0; } static int bus_socket_auth_write_ok(sd_bus *b) { char t[3 + 32 + 2 + 1]; assert(b); xsprintf(t, "OK " SD_ID128_FORMAT_STR "\r\n", SD_ID128_FORMAT_VAL(b->server_id)); return bus_socket_auth_write(b, t); } static int bus_socket_auth_verify_server(sd_bus *b) { char *e; const char *line; size_t l; bool processed = false; int r; assert(b); if (b->rbuffer_size < 1) return 0; /* First char must be a NUL byte */ if (*(char*) b->rbuffer != 0) return -EIO; if (b->rbuffer_size < 3) return 0; /* Begin with the first line */ if (b->auth_rbegin <= 0) b->auth_rbegin = 1; for (;;) { /* Check if line is complete */ line = (char*) b->rbuffer + b->auth_rbegin; e = memmem(line, b->rbuffer_size - b->auth_rbegin, "\r\n", 2); if (!e) return processed; l = e - line; if (line_begins(line, l, "AUTH ANONYMOUS")) { r = verify_anonymous_token(b, line + 14, l - 14); if (r < 0) return r; if (r == 0) r = bus_socket_auth_write(b, "REJECTED\r\n"); else { b->auth = BUS_AUTH_ANONYMOUS; r = bus_socket_auth_write_ok(b); } } else if (line_begins(line, l, "AUTH EXTERNAL")) { r = verify_external_token(b, line + 13, l - 13); if (r < 0) return r; if (r == 0) r = bus_socket_auth_write(b, "REJECTED\r\n"); else { b->auth = BUS_AUTH_EXTERNAL; r = bus_socket_auth_write_ok(b); } } else if (line_begins(line, l, "AUTH")) r = bus_socket_auth_write(b, "REJECTED EXTERNAL ANONYMOUS\r\n"); else if (line_equals(line, l, "CANCEL") || line_begins(line, l, "ERROR")) { b->auth = _BUS_AUTH_INVALID; r = bus_socket_auth_write(b, "REJECTED\r\n"); } else if (line_equals(line, l, "BEGIN")) { if (b->auth == _BUS_AUTH_INVALID) r = bus_socket_auth_write(b, "ERROR\r\n"); else { /* We can't leave from the auth phase * before we haven't written * everything queued, so let's check * that */ if (bus_socket_auth_needs_write(b)) return 1; b->rbuffer_size -= (e + 2 - (char*) b->rbuffer); memmove(b->rbuffer, e + 2, b->rbuffer_size); return bus_start_running(b); } } else if (line_begins(line, l, "DATA")) { if (b->auth == _BUS_AUTH_INVALID) r = bus_socket_auth_write(b, "ERROR\r\n"); else { if (b->auth == BUS_AUTH_ANONYMOUS) r = verify_anonymous_token(b, line + 4, l - 4); else r = verify_external_token(b, line + 4, l - 4); if (r < 0) return r; if (r == 0) { b->auth = _BUS_AUTH_INVALID; r = bus_socket_auth_write(b, "REJECTED\r\n"); } else r = bus_socket_auth_write_ok(b); } } else if (line_equals(line, l, "NEGOTIATE_UNIX_FD")) { if (b->auth == _BUS_AUTH_INVALID || !(b->hello_flags & KDBUS_HELLO_ACCEPT_FD)) r = bus_socket_auth_write(b, "ERROR\r\n"); else { b->can_fds = true; r = bus_socket_auth_write(b, "AGREE_UNIX_FD\r\n"); } } else r = bus_socket_auth_write(b, "ERROR\r\n"); if (r < 0) return r; b->auth_rbegin = e + 2 - (char*) b->rbuffer; processed = true; } } static int bus_socket_auth_verify(sd_bus *b) { assert(b); if (b->is_server) return bus_socket_auth_verify_server(b); else return bus_socket_auth_verify_client(b); } static int bus_socket_read_auth(sd_bus *b) { struct msghdr mh; struct iovec iov = {}; size_t n; ssize_t k; int r; void *p; union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)]; } control; bool handle_cmsg = false; assert(b); assert(b->state == BUS_AUTHENTICATING); r = bus_socket_auth_verify(b); if (r != 0) return r; n = MAX(256u, b->rbuffer_size * 2); if (n > BUS_AUTH_SIZE_MAX) n = BUS_AUTH_SIZE_MAX; if (b->rbuffer_size >= n) return -ENOBUFS; p = realloc(b->rbuffer, n); if (!p) return -ENOMEM; b->rbuffer = p; iov.iov_base = (uint8_t*) b->rbuffer + b->rbuffer_size; iov.iov_len = n - b->rbuffer_size; if (b->prefer_readv) k = readv(b->input_fd, &iov, 1); else { zero(mh); mh.msg_iov = &iov; mh.msg_iovlen = 1; mh.msg_control = &control; mh.msg_controllen = sizeof(control); k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC); if (k < 0 && errno == ENOTSOCK) { b->prefer_readv = true; k = readv(b->input_fd, &iov, 1); } else handle_cmsg = true; } if (k < 0) return errno == EAGAIN ? 0 : -errno; if (k == 0) return -ECONNRESET; b->rbuffer_size += k; if (handle_cmsg) { struct cmsghdr *cmsg; CMSG_FOREACH(cmsg, &mh) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { int j; /* Whut? We received fds during the auth * protocol? Somebody is playing games with * us. Close them all, and fail */ j = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); close_many((int*) CMSG_DATA(cmsg), j); return -EIO; } else log_debug("Got unexpected auxiliary data with level=%d and type=%d", cmsg->cmsg_level, cmsg->cmsg_type); } r = bus_socket_auth_verify(b); if (r != 0) return r; return 1; } void bus_socket_setup(sd_bus *b) { assert(b); /* Increase the buffers to 8 MB */ fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE); fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE); b->is_kernel = false; b->message_version = 1; b->message_endian = 0; } static void bus_get_peercred(sd_bus *b) { int r; assert(b); /* Get the peer for socketpair() sockets */ b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0; /* Get the SELinux context of the peer */ if (mac_selinux_have()) { r = getpeersec(b->input_fd, &b->label); if (r < 0 && r != -EOPNOTSUPP) log_debug_errno(r, "Failed to determine peer security context: %m"); } } static int bus_socket_start_auth_client(sd_bus *b) { size_t l; const char *auth_suffix, *auth_prefix; assert(b); if (b->anonymous_auth) { auth_prefix = "\0AUTH ANONYMOUS "; /* For ANONYMOUS auth we send some arbitrary "trace" string */ l = 9; b->auth_buffer = hexmem("anonymous", l); } else { char text[DECIMAL_STR_MAX(uid_t) + 1]; auth_prefix = "\0AUTH EXTERNAL "; xsprintf(text, UID_FMT, geteuid()); l = strlen(text); b->auth_buffer = hexmem(text, l); } if (!b->auth_buffer) return -ENOMEM; if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD) auth_suffix = "\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n"; else auth_suffix = "\r\nBEGIN\r\n"; b->auth_iovec[0].iov_base = (void*) auth_prefix; b->auth_iovec[0].iov_len = 1 + strlen(auth_prefix + 1); b->auth_iovec[1].iov_base = (void*) b->auth_buffer; b->auth_iovec[1].iov_len = l * 2; b->auth_iovec[2].iov_base = (void*) auth_suffix; b->auth_iovec[2].iov_len = strlen(auth_suffix); return bus_socket_write_auth(b); } int bus_socket_start_auth(sd_bus *b) { assert(b); bus_get_peercred(b); b->state = BUS_AUTHENTICATING; b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_DEFAULT_TIMEOUT; if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0) b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD; if (b->output_fd != b->input_fd) if (sd_is_socket(b->output_fd, AF_UNIX, 0, 0) <= 0) b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD; if (b->is_server) return bus_socket_read_auth(b); else return bus_socket_start_auth_client(b); } int bus_socket_connect(sd_bus *b) { int r; assert(b); assert(b->input_fd < 0); assert(b->output_fd < 0); assert(b->sockaddr.sa.sa_family != AF_UNSPEC); b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (b->input_fd < 0) return -errno; b->output_fd = b->input_fd; bus_socket_setup(b); r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size); if (r < 0) { if (errno == EINPROGRESS) return 1; return -errno; } return bus_socket_start_auth(b); } int bus_socket_exec(sd_bus *b) { int s[2], r; pid_t pid; assert(b); assert(b->input_fd < 0); assert(b->output_fd < 0); assert(b->exec_path); r = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s); if (r < 0) return -errno; pid = fork(); if (pid < 0) { safe_close_pair(s); return -errno; } if (pid == 0) { /* Child */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); close_all_fds(s+1, 1); assert_se(dup3(s[1], STDIN_FILENO, 0) == STDIN_FILENO); assert_se(dup3(s[1], STDOUT_FILENO, 0) == STDOUT_FILENO); if (s[1] != STDIN_FILENO && s[1] != STDOUT_FILENO) safe_close(s[1]); fd_cloexec(STDIN_FILENO, false); fd_cloexec(STDOUT_FILENO, false); fd_nonblock(STDIN_FILENO, false); fd_nonblock(STDOUT_FILENO, false); if (b->exec_argv) execvp(b->exec_path, b->exec_argv); else { const char *argv[] = { b->exec_path, NULL }; execvp(b->exec_path, (char**) argv); } _exit(EXIT_FAILURE); } safe_close(s[1]); b->output_fd = b->input_fd = s[0]; bus_socket_setup(b); return bus_socket_start_auth(b); } int bus_socket_take_fd(sd_bus *b) { assert(b); bus_socket_setup(b); return bus_socket_start_auth(b); } int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) { struct iovec *iov; ssize_t k; size_t n; unsigned j; int r; assert(bus); assert(m); assert(idx); assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO); if (*idx >= BUS_MESSAGE_SIZE(m)) return 0; r = bus_message_setup_iovec(m); if (r < 0) return r; n = m->n_iovec * sizeof(struct iovec); iov = alloca(n); memcpy(iov, m->iovec, n); j = 0; iovec_advance(iov, &j, *idx); if (bus->prefer_writev) k = writev(bus->output_fd, iov, m->n_iovec); else { struct msghdr mh = { .msg_iov = iov, .msg_iovlen = m->n_iovec, }; if (m->n_fds > 0) { struct cmsghdr *control; mh.msg_control = control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds)); mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds); control->cmsg_level = SOL_SOCKET; control->cmsg_type = SCM_RIGHTS; memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds); } k = sendmsg(bus->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL); if (k < 0 && errno == ENOTSOCK) { bus->prefer_writev = true; k = writev(bus->output_fd, iov, m->n_iovec); } } if (k < 0) return errno == EAGAIN ? 0 : -errno; *idx += (size_t) k; return 1; } static int bus_socket_read_message_need(sd_bus *bus, size_t *need) { uint32_t a, b; uint8_t e; uint64_t sum; assert(bus); assert(need); assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO); if (bus->rbuffer_size < sizeof(struct bus_header)) { *need = sizeof(struct bus_header) + 8; /* Minimum message size: * * Header + * * Method Call: +2 string headers * Signal: +3 string headers * Method Error: +1 string headers * +1 uint32 headers * Method Reply: +1 uint32 headers * * A string header is at least 9 bytes * A uint32 header is at least 8 bytes * * Hence the minimum message size of a valid message * is header + 8 bytes */ return 0; } a = ((const uint32_t*) bus->rbuffer)[1]; b = ((const uint32_t*) bus->rbuffer)[3]; e = ((const uint8_t*) bus->rbuffer)[0]; if (e == BUS_LITTLE_ENDIAN) { a = le32toh(a); b = le32toh(b); } else if (e == BUS_BIG_ENDIAN) { a = be32toh(a); b = be32toh(b); } else return -EBADMSG; sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN_TO(b, 8) + (uint64_t) a; if (sum >= BUS_MESSAGE_SIZE_MAX) return -ENOBUFS; *need = (size_t) sum; return 0; } static int bus_socket_make_message(sd_bus *bus, size_t size) { sd_bus_message *t; void *b; int r; assert(bus); assert(bus->rbuffer_size >= size); assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO); r = bus_rqueue_make_room(bus); if (r < 0) return r; if (bus->rbuffer_size > size) { b = memdup((const uint8_t*) bus->rbuffer + size, bus->rbuffer_size - size); if (!b) return -ENOMEM; } else b = NULL; r = bus_message_from_malloc(bus, bus->rbuffer, size, bus->fds, bus->n_fds, NULL, &t); if (r < 0) { free(b); return r; } bus->rbuffer = b; bus->rbuffer_size -= size; bus->fds = NULL; bus->n_fds = 0; bus->rqueue[bus->rqueue_size++] = t; return 1; } int bus_socket_read_message(sd_bus *bus) { struct msghdr mh; struct iovec iov = {}; ssize_t k; size_t need; int r; void *b; union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)]; } control; bool handle_cmsg = false; assert(bus); assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO); r = bus_socket_read_message_need(bus, &need); if (r < 0) return r; if (bus->rbuffer_size >= need) return bus_socket_make_message(bus, need); b = realloc(bus->rbuffer, need); if (!b) return -ENOMEM; bus->rbuffer = b; iov.iov_base = (uint8_t*) bus->rbuffer + bus->rbuffer_size; iov.iov_len = need - bus->rbuffer_size; if (bus->prefer_readv) k = readv(bus->input_fd, &iov, 1); else { zero(mh); mh.msg_iov = &iov; mh.msg_iovlen = 1; mh.msg_control = &control; mh.msg_controllen = sizeof(control); k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC); if (k < 0 && errno == ENOTSOCK) { bus->prefer_readv = true; k = readv(bus->input_fd, &iov, 1); } else handle_cmsg = true; } if (k < 0) return errno == EAGAIN ? 0 : -errno; if (k == 0) return -ECONNRESET; bus->rbuffer_size += k; if (handle_cmsg) { struct cmsghdr *cmsg; CMSG_FOREACH(cmsg, &mh) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { int n, *f; n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); if (!bus->can_fds) { /* Whut? We received fds but this * isn't actually enabled? Close them, * and fail */ close_many((int*) CMSG_DATA(cmsg), n); return -EIO; } f = realloc(bus->fds, sizeof(int) * (bus->n_fds + n)); if (!f) { close_many((int*) CMSG_DATA(cmsg), n); return -ENOMEM; } memcpy(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int)); bus->fds = f; bus->n_fds += n; } else log_debug("Got unexpected auxiliary data with level=%d and type=%d", cmsg->cmsg_level, cmsg->cmsg_type); } r = bus_socket_read_message_need(bus, &need); if (r < 0) return r; if (bus->rbuffer_size >= need) return bus_socket_make_message(bus, need); return 1; } int bus_socket_process_opening(sd_bus *b) { int error = 0; socklen_t slen = sizeof(error); struct pollfd p = { .fd = b->output_fd, .events = POLLOUT, }; int r; assert(b->state == BUS_OPENING); r = poll(&p, 1, 0); if (r < 0) return -errno; if (!(p.revents & (POLLOUT|POLLERR|POLLHUP))) return 0; r = getsockopt(b->output_fd, SOL_SOCKET, SO_ERROR, &error, &slen); if (r < 0) b->last_connect_error = errno; else if (error != 0) b->last_connect_error = error; else if (p.revents & (POLLERR|POLLHUP)) b->last_connect_error = ECONNREFUSED; else return bus_socket_start_auth(b); return bus_next_address(b); } int bus_socket_process_authenticating(sd_bus *b) { int r; assert(b); assert(b->state == BUS_AUTHENTICATING); if (now(CLOCK_MONOTONIC) >= b->auth_timeout) return -ETIMEDOUT; r = bus_socket_write_auth(b); if (r != 0) return r; return bus_socket_read_auth(b); } systemd-229/src/libsystemd/sd-bus/bus-socket.h000066400000000000000000000022431265713322000214550ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" void bus_socket_setup(sd_bus *b); int bus_socket_connect(sd_bus *b); int bus_socket_exec(sd_bus *b); int bus_socket_take_fd(sd_bus *b); int bus_socket_start_auth(sd_bus *b); int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx); int bus_socket_read_message(sd_bus *bus); int bus_socket_process_opening(sd_bus *b); int bus_socket_process_authenticating(sd_bus *b); bool bus_socket_auth_needs_write(sd_bus *b); systemd-229/src/libsystemd/sd-bus/bus-track.c000066400000000000000000000212771265713322000212740ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "alloc-util.h" #include "bus-internal.h" #include "bus-track.h" #include "bus-util.h" struct sd_bus_track { unsigned n_ref; sd_bus *bus; sd_bus_track_handler_t handler; void *userdata; Hashmap *names; LIST_FIELDS(sd_bus_track, queue); Iterator iterator; bool in_queue; bool modified; }; #define MATCH_PREFIX \ "type='signal'," \ "sender='org.freedesktop.DBus'," \ "path='/org/freedesktop/DBus'," \ "interface='org.freedesktop.DBus'," \ "member='NameOwnerChanged'," \ "arg0='" #define MATCH_SUFFIX \ "'" #define MATCH_FOR_NAME(name) \ ({ \ char *_x; \ size_t _l = strlen(name); \ _x = alloca(strlen(MATCH_PREFIX)+_l+strlen(MATCH_SUFFIX)+1); \ strcpy(stpcpy(stpcpy(_x, MATCH_PREFIX), name), MATCH_SUFFIX); \ _x; \ }) static void bus_track_add_to_queue(sd_bus_track *track) { assert(track); if (track->in_queue) return; if (!track->handler) return; LIST_PREPEND(queue, track->bus->track_queue, track); track->in_queue = true; } static void bus_track_remove_from_queue(sd_bus_track *track) { assert(track); if (!track->in_queue) return; LIST_REMOVE(queue, track->bus->track_queue, track); track->in_queue = false; } _public_ int sd_bus_track_new( sd_bus *bus, sd_bus_track **track, sd_bus_track_handler_t handler, void *userdata) { sd_bus_track *t; assert_return(bus, -EINVAL); assert_return(track, -EINVAL); if (!bus->bus_client) return -EINVAL; t = new0(sd_bus_track, 1); if (!t) return -ENOMEM; t->n_ref = 1; t->handler = handler; t->userdata = userdata; t->bus = sd_bus_ref(bus); bus_track_add_to_queue(t); *track = t; return 0; } _public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) { if (!track) return NULL; assert(track->n_ref > 0); track->n_ref++; return track; } _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { const char *n; if (!track) return NULL; assert(track->n_ref > 0); if (track->n_ref > 1) { track->n_ref --; return NULL; } while ((n = hashmap_first_key(track->names))) sd_bus_track_remove_name(track, n); bus_track_remove_from_queue(track); hashmap_free(track->names); sd_bus_unref(track->bus); free(track); return NULL; } static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { sd_bus_track *track = userdata; const char *name, *old, *new; int r; assert(message); assert(track); r = sd_bus_message_read(message, "sss", &name, &old, &new); if (r < 0) return 0; sd_bus_track_remove_name(track, name); return 0; } _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; _cleanup_free_ char *n = NULL; const char *match; int r; assert_return(track, -EINVAL); assert_return(service_name_is_valid(name), -EINVAL); r = hashmap_ensure_allocated(&track->names, &string_hash_ops); if (r < 0) return r; n = strdup(name); if (!n) return -ENOMEM; /* First, subscribe to this name */ match = MATCH_FOR_NAME(n); r = sd_bus_add_match(track->bus, &slot, match, on_name_owner_changed, track); if (r < 0) return r; r = hashmap_put(track->names, n, slot); if (r == -EEXIST) return 0; if (r < 0) return r; /* Second, check if it is currently existing, or maybe * doesn't, or maybe disappeared already. */ r = sd_bus_get_name_creds(track->bus, n, 0, NULL); if (r < 0) { hashmap_remove(track->names, n); return r; } n = NULL; slot = NULL; bus_track_remove_from_queue(track); track->modified = true; return 1; } _public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) { _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; _cleanup_free_ char *n = NULL; assert_return(name, -EINVAL); if (!track) return 0; slot = hashmap_remove2(track->names, (char*) name, (void**) &n); if (!slot) return 0; if (hashmap_isempty(track->names)) bus_track_add_to_queue(track); track->modified = true; return 1; } _public_ unsigned sd_bus_track_count(sd_bus_track *track) { if (!track) return 0; return hashmap_size(track->names); } _public_ const char* sd_bus_track_contains(sd_bus_track *track, const char *name) { assert_return(track, NULL); assert_return(name, NULL); return hashmap_get(track->names, (void*) name) ? name : NULL; } _public_ const char* sd_bus_track_first(sd_bus_track *track) { const char *n = NULL; if (!track) return NULL; track->modified = false; track->iterator = ITERATOR_FIRST; hashmap_iterate(track->names, &track->iterator, NULL, (const void**) &n); return n; } _public_ const char* sd_bus_track_next(sd_bus_track *track) { const char *n = NULL; if (!track) return NULL; if (track->modified) return NULL; hashmap_iterate(track->names, &track->iterator, NULL, (const void**) &n); return n; } _public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) { const char *sender; assert_return(track, -EINVAL); assert_return(m, -EINVAL); sender = sd_bus_message_get_sender(m); if (!sender) return -EINVAL; return sd_bus_track_add_name(track, sender); } _public_ int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m) { const char *sender; assert_return(track, -EINVAL); assert_return(m, -EINVAL); sender = sd_bus_message_get_sender(m); if (!sender) return -EINVAL; return sd_bus_track_remove_name(track, sender); } _public_ sd_bus* sd_bus_track_get_bus(sd_bus_track *track) { assert_return(track, NULL); return track->bus; } void bus_track_dispatch(sd_bus_track *track) { int r; assert(track); assert(track->in_queue); assert(track->handler); bus_track_remove_from_queue(track); sd_bus_track_ref(track); r = track->handler(track, track->userdata); if (r < 0) log_debug_errno(r, "Failed to process track handler: %m"); else if (r == 0) bus_track_add_to_queue(track); sd_bus_track_unref(track); } _public_ void *sd_bus_track_get_userdata(sd_bus_track *track) { assert_return(track, NULL); return track->userdata; } _public_ void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata) { void *ret; assert_return(track, NULL); ret = track->userdata; track->userdata = userdata; return ret; } systemd-229/src/libsystemd/sd-bus/bus-track.h000066400000000000000000000014131265713322000212670ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ void bus_track_dispatch(sd_bus_track *track); systemd-229/src/libsystemd/sd-bus/bus-type.c000066400000000000000000000117501265713322000211440ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-type.h" bool bus_type_is_valid(char c) { static const char valid[] = { SD_BUS_TYPE_BYTE, SD_BUS_TYPE_BOOLEAN, SD_BUS_TYPE_INT16, SD_BUS_TYPE_UINT16, SD_BUS_TYPE_INT32, SD_BUS_TYPE_UINT32, SD_BUS_TYPE_INT64, SD_BUS_TYPE_UINT64, SD_BUS_TYPE_DOUBLE, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_ARRAY, SD_BUS_TYPE_VARIANT, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY, SD_BUS_TYPE_UNIX_FD }; return !!memchr(valid, c, sizeof(valid)); } bool bus_type_is_valid_in_signature(char c) { static const char valid[] = { SD_BUS_TYPE_BYTE, SD_BUS_TYPE_BOOLEAN, SD_BUS_TYPE_INT16, SD_BUS_TYPE_UINT16, SD_BUS_TYPE_INT32, SD_BUS_TYPE_UINT32, SD_BUS_TYPE_INT64, SD_BUS_TYPE_UINT64, SD_BUS_TYPE_DOUBLE, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_ARRAY, SD_BUS_TYPE_VARIANT, SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_STRUCT_END, SD_BUS_TYPE_DICT_ENTRY_BEGIN, SD_BUS_TYPE_DICT_ENTRY_END, SD_BUS_TYPE_UNIX_FD }; return !!memchr(valid, c, sizeof(valid)); } bool bus_type_is_basic(char c) { static const char valid[] = { SD_BUS_TYPE_BYTE, SD_BUS_TYPE_BOOLEAN, SD_BUS_TYPE_INT16, SD_BUS_TYPE_UINT16, SD_BUS_TYPE_INT32, SD_BUS_TYPE_UINT32, SD_BUS_TYPE_INT64, SD_BUS_TYPE_UINT64, SD_BUS_TYPE_DOUBLE, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_UNIX_FD }; return !!memchr(valid, c, sizeof(valid)); } bool bus_type_is_trivial(char c) { static const char valid[] = { SD_BUS_TYPE_BYTE, SD_BUS_TYPE_BOOLEAN, SD_BUS_TYPE_INT16, SD_BUS_TYPE_UINT16, SD_BUS_TYPE_INT32, SD_BUS_TYPE_UINT32, SD_BUS_TYPE_INT64, SD_BUS_TYPE_UINT64, SD_BUS_TYPE_DOUBLE }; return !!memchr(valid, c, sizeof(valid)); } bool bus_type_is_container(char c) { static const char valid[] = { SD_BUS_TYPE_ARRAY, SD_BUS_TYPE_VARIANT, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY }; return !!memchr(valid, c, sizeof(valid)); } int bus_type_get_alignment(char c) { switch (c) { case SD_BUS_TYPE_BYTE: case SD_BUS_TYPE_SIGNATURE: case SD_BUS_TYPE_VARIANT: return 1; case SD_BUS_TYPE_INT16: case SD_BUS_TYPE_UINT16: return 2; case SD_BUS_TYPE_BOOLEAN: case SD_BUS_TYPE_INT32: case SD_BUS_TYPE_UINT32: case SD_BUS_TYPE_STRING: case SD_BUS_TYPE_OBJECT_PATH: case SD_BUS_TYPE_ARRAY: case SD_BUS_TYPE_UNIX_FD: return 4; case SD_BUS_TYPE_INT64: case SD_BUS_TYPE_UINT64: case SD_BUS_TYPE_DOUBLE: case SD_BUS_TYPE_STRUCT: case SD_BUS_TYPE_STRUCT_BEGIN: case SD_BUS_TYPE_DICT_ENTRY: case SD_BUS_TYPE_DICT_ENTRY_BEGIN: return 8; } return -EINVAL; } int bus_type_get_size(char c) { switch (c) { case SD_BUS_TYPE_BYTE: return 1; case SD_BUS_TYPE_INT16: case SD_BUS_TYPE_UINT16: return 2; case SD_BUS_TYPE_BOOLEAN: case SD_BUS_TYPE_INT32: case SD_BUS_TYPE_UINT32: case SD_BUS_TYPE_UNIX_FD: return 4; case SD_BUS_TYPE_INT64: case SD_BUS_TYPE_UINT64: case SD_BUS_TYPE_DOUBLE: return 8; } return -EINVAL; } systemd-229/src/libsystemd/sd-bus/bus-type.h000066400000000000000000000023151265713322000211460ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "macro.h" bool bus_type_is_valid(char c) _const_; bool bus_type_is_valid_in_signature(char c) _const_; bool bus_type_is_basic(char c) _const_; /* "trivial" is systemd's term for what the D-Bus Specification calls * a "fixed type": that is, a basic type of fixed length */ bool bus_type_is_trivial(char c) _const_; bool bus_type_is_container(char c) _const_; int bus_type_get_alignment(char c) _const_; int bus_type_get_size(char c) _const_; systemd-229/src/libsystemd/sd-bus/busctl-introspect.c000066400000000000000000001001131265713322000230500ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "alloc-util.h" #include "busctl-introspect.h" #include "string-util.h" #include "util.h" #include "xml.h" #define NODE_DEPTH_MAX 16 typedef struct Context { const XMLIntrospectOps *ops; void *userdata; char *interface_name; uint64_t interface_flags; char *member_name; char *member_signature; char *member_result; uint64_t member_flags; bool member_writable; const char *current; void *xml_state; } Context; static void context_reset_member(Context *c) { free(c->member_name); free(c->member_signature); free(c->member_result); c->member_name = c->member_signature = c->member_result = NULL; c->member_flags = 0; c->member_writable = false; } static void context_reset_interface(Context *c) { c->interface_name = mfree(c->interface_name); c->interface_flags = 0; context_reset_member(c); } static int parse_xml_annotation(Context *context, uint64_t *flags) { enum { STATE_ANNOTATION, STATE_NAME, STATE_VALUE } state = STATE_ANNOTATION; _cleanup_free_ char *field = NULL, *value = NULL; assert(context); for (;;) { _cleanup_free_ char *name = NULL; int t; t = xml_tokenize(&context->current, &name, &context->xml_state, NULL); if (t < 0) { log_error("XML parse error."); return t; } if (t == XML_END) { log_error("Premature end of XML data."); return -EBADMSG; } switch (state) { case STATE_ANNOTATION: if (t == XML_ATTRIBUTE_NAME) { if (streq_ptr(name, "name")) state = STATE_NAME; else if (streq_ptr(name, "value")) state = STATE_VALUE; else { log_error("Unexpected attribute %s.", name); return -EBADMSG; } } else if (t == XML_TAG_CLOSE_EMPTY || (t == XML_TAG_CLOSE && streq_ptr(name, "annotation"))) { if (flags) { if (streq_ptr(field, "org.freedesktop.DBus.Deprecated")) { if (streq_ptr(value, "true")) *flags |= SD_BUS_VTABLE_DEPRECATED; } else if (streq_ptr(field, "org.freedesktop.DBus.Method.NoReply")) { if (streq_ptr(value, "true")) *flags |= SD_BUS_VTABLE_METHOD_NO_REPLY; } else if (streq_ptr(field, "org.freedesktop.DBus.Property.EmitsChangedSignal")) { if (streq_ptr(value, "const")) *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE)) | SD_BUS_VTABLE_PROPERTY_CONST; else if (streq_ptr(value, "invalidates")) *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST)) | SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION; else if (streq_ptr(value, "false")) *flags = *flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION); } } return 0; } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { log_error("Unexpected token in . (1)"); return -EINVAL; } break; case STATE_NAME: if (t == XML_ATTRIBUTE_VALUE) { free(field); field = name; name = NULL; state = STATE_ANNOTATION; } else { log_error("Unexpected token in . (2)"); return -EINVAL; } break; case STATE_VALUE: if (t == XML_ATTRIBUTE_VALUE) { free(value); value = name; name = NULL; state = STATE_ANNOTATION; } else { log_error("Unexpected token in . (3)"); return -EINVAL; } break; default: assert_not_reached("Bad state"); } } } static int parse_xml_node(Context *context, const char *prefix, unsigned n_depth) { enum { STATE_NODE, STATE_NODE_NAME, STATE_INTERFACE, STATE_INTERFACE_NAME, STATE_METHOD, STATE_METHOD_NAME, STATE_METHOD_ARG, STATE_METHOD_ARG_NAME, STATE_METHOD_ARG_TYPE, STATE_METHOD_ARG_DIRECTION, STATE_SIGNAL, STATE_SIGNAL_NAME, STATE_SIGNAL_ARG, STATE_SIGNAL_ARG_NAME, STATE_SIGNAL_ARG_TYPE, STATE_PROPERTY, STATE_PROPERTY_NAME, STATE_PROPERTY_TYPE, STATE_PROPERTY_ACCESS, } state = STATE_NODE; _cleanup_free_ char *node_path = NULL, *argument_type = NULL, *argument_direction = NULL; const char *np = prefix; int r; assert(context); assert(prefix); if (n_depth > NODE_DEPTH_MAX) { log_error(" depth too high."); return -EINVAL; } for (;;) { _cleanup_free_ char *name = NULL; int t; t = xml_tokenize(&context->current, &name, &context->xml_state, NULL); if (t < 0) { log_error("XML parse error."); return t; } if (t == XML_END) { log_error("Premature end of XML data."); return -EBADMSG; } switch (state) { case STATE_NODE: if (t == XML_ATTRIBUTE_NAME) { if (streq_ptr(name, "name")) state = STATE_NODE_NAME; else { log_error("Unexpected attribute %s.", name); return -EBADMSG; } } else if (t == XML_TAG_OPEN) { if (streq_ptr(name, "interface")) state = STATE_INTERFACE; else if (streq_ptr(name, "node")) { r = parse_xml_node(context, np, n_depth+1); if (r < 0) return r; } else { log_error("Unexpected tag %s.", name); return -EBADMSG; } } else if (t == XML_TAG_CLOSE_EMPTY || (t == XML_TAG_CLOSE && streq_ptr(name, "node"))) { if (context->ops->on_path) { r = context->ops->on_path(node_path ? node_path : np, context->userdata); if (r < 0) return r; } return 0; } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { log_error("Unexpected token in . (1)"); return -EINVAL; } break; case STATE_NODE_NAME: if (t == XML_ATTRIBUTE_VALUE) { free(node_path); if (name[0] == '/') { node_path = name; name = NULL; } else { if (endswith(prefix, "/")) node_path = strappend(prefix, name); else node_path = strjoin(prefix, "/", name, NULL); if (!node_path) return log_oom(); } np = node_path; state = STATE_NODE; } else { log_error("Unexpected token in . (2)"); return -EINVAL; } break; case STATE_INTERFACE: if (t == XML_ATTRIBUTE_NAME) { if (streq_ptr(name, "name")) state = STATE_INTERFACE_NAME; else { log_error("Unexpected attribute %s.", name); return -EBADMSG; } } else if (t == XML_TAG_OPEN) { if (streq_ptr(name, "method")) state = STATE_METHOD; else if (streq_ptr(name, "signal")) state = STATE_SIGNAL; else if (streq_ptr(name, "property")) { context->member_flags |= SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE; state = STATE_PROPERTY; } else if (streq_ptr(name, "annotation")) { r = parse_xml_annotation(context, &context->interface_flags); if (r < 0) return r; } else { log_error("Unexpected tag %s.", name); return -EINVAL; } } else if (t == XML_TAG_CLOSE_EMPTY || (t == XML_TAG_CLOSE && streq_ptr(name, "interface"))) { if (n_depth == 0) { if (context->ops->on_interface) { r = context->ops->on_interface(context->interface_name, context->interface_flags, context->userdata); if (r < 0) return r; } context_reset_interface(context); } state = STATE_NODE; } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { log_error("Unexpected token in . (1)"); return -EINVAL; } break; case STATE_INTERFACE_NAME: if (t == XML_ATTRIBUTE_VALUE) { if (n_depth == 0) { free(context->interface_name); context->interface_name = name; name = NULL; } state = STATE_INTERFACE; } else { log_error("Unexpected token in . (2)"); return -EINVAL; } break; case STATE_METHOD: if (t == XML_ATTRIBUTE_NAME) { if (streq_ptr(name, "name")) state = STATE_METHOD_NAME; else { log_error("Unexpected attribute %s", name); return -EBADMSG; } } else if (t == XML_TAG_OPEN) { if (streq_ptr(name, "arg")) state = STATE_METHOD_ARG; else if (streq_ptr(name, "annotation")) { r = parse_xml_annotation(context, &context->member_flags); if (r < 0) return r; } else { log_error("Unexpected tag %s.", name); return -EINVAL; } } else if (t == XML_TAG_CLOSE_EMPTY || (t == XML_TAG_CLOSE && streq_ptr(name, "method"))) { if (n_depth == 0) { if (context->ops->on_method) { r = context->ops->on_method(context->interface_name, context->member_name, context->member_signature, context->member_result, context->member_flags, context->userdata); if (r < 0) return r; } context_reset_member(context); } state = STATE_INTERFACE; } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { log_error("Unexpected token in (1)."); return -EINVAL; } break; case STATE_METHOD_NAME: if (t == XML_ATTRIBUTE_VALUE) { if (n_depth == 0) { free(context->member_name); context->member_name = name; name = NULL; } state = STATE_METHOD; } else { log_error("Unexpected token in (2)."); return -EINVAL; } break; case STATE_METHOD_ARG: if (t == XML_ATTRIBUTE_NAME) { if (streq_ptr(name, "name")) state = STATE_METHOD_ARG_NAME; else if (streq_ptr(name, "type")) state = STATE_METHOD_ARG_TYPE; else if (streq_ptr(name, "direction")) state = STATE_METHOD_ARG_DIRECTION; else { log_error("Unexpected method attribute %s.", name); return -EBADMSG; } } else if (t == XML_TAG_OPEN) { if (streq_ptr(name, "annotation")) { r = parse_xml_annotation(context, NULL); if (r < 0) return r; } else { log_error("Unexpected method tag %s.", name); return -EINVAL; } } else if (t == XML_TAG_CLOSE_EMPTY || (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) { if (n_depth == 0) { if (argument_type) { if (!argument_direction || streq(argument_direction, "in")) { if (!strextend(&context->member_signature, argument_type, NULL)) return log_oom(); } else if (streq(argument_direction, "out")) { if (!strextend(&context->member_result, argument_type, NULL)) return log_oom(); } } argument_type = mfree(argument_type); argument_direction = mfree(argument_direction); } state = STATE_METHOD; } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { log_error("Unexpected token in method . (1)"); return -EINVAL; } break; case STATE_METHOD_ARG_NAME: if (t == XML_ATTRIBUTE_VALUE) state = STATE_METHOD_ARG; else { log_error("Unexpected token in method . (2)"); return -EINVAL; } break; case STATE_METHOD_ARG_TYPE: if (t == XML_ATTRIBUTE_VALUE) { free(argument_type); argument_type = name; name = NULL; state = STATE_METHOD_ARG; } else { log_error("Unexpected token in method . (3)"); return -EINVAL; } break; case STATE_METHOD_ARG_DIRECTION: if (t == XML_ATTRIBUTE_VALUE) { free(argument_direction); argument_direction = name; name = NULL; state = STATE_METHOD_ARG; } else { log_error("Unexpected token in method . (4)"); return -EINVAL; } break; case STATE_SIGNAL: if (t == XML_ATTRIBUTE_NAME) { if (streq_ptr(name, "name")) state = STATE_SIGNAL_NAME; else { log_error("Unexpected attribute %s.", name); return -EBADMSG; } } else if (t == XML_TAG_OPEN) { if (streq_ptr(name, "arg")) state = STATE_SIGNAL_ARG; else if (streq_ptr(name, "annotation")) { r = parse_xml_annotation(context, &context->member_flags); if (r < 0) return r; } else { log_error("Unexpected tag %s.", name); return -EINVAL; } } else if (t == XML_TAG_CLOSE_EMPTY || (t == XML_TAG_CLOSE && streq_ptr(name, "signal"))) { if (n_depth == 0) { if (context->ops->on_signal) { r = context->ops->on_signal(context->interface_name, context->member_name, context->member_signature, context->member_flags, context->userdata); if (r < 0) return r; } context_reset_member(context); } state = STATE_INTERFACE; } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { log_error("Unexpected token in . (1)"); return -EINVAL; } break; case STATE_SIGNAL_NAME: if (t == XML_ATTRIBUTE_VALUE) { if (n_depth == 0) { free(context->member_name); context->member_name = name; name = NULL; } state = STATE_SIGNAL; } else { log_error("Unexpected token in . (2)"); return -EINVAL; } break; case STATE_SIGNAL_ARG: if (t == XML_ATTRIBUTE_NAME) { if (streq_ptr(name, "name")) state = STATE_SIGNAL_ARG_NAME; else if (streq_ptr(name, "type")) state = STATE_SIGNAL_ARG_TYPE; else { log_error("Unexpected signal attribute %s.", name); return -EBADMSG; } } else if (t == XML_TAG_OPEN) { if (streq_ptr(name, "annotation")) { r = parse_xml_annotation(context, NULL); if (r < 0) return r; } else { log_error("Unexpected signal tag %s.", name); return -EINVAL; } } else if (t == XML_TAG_CLOSE_EMPTY || (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) { if (argument_type) { if (!strextend(&context->member_signature, argument_type, NULL)) return log_oom(); argument_type = mfree(argument_type); } state = STATE_SIGNAL; } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { log_error("Unexpected token in signal (1)."); return -EINVAL; } break; case STATE_SIGNAL_ARG_NAME: if (t == XML_ATTRIBUTE_VALUE) state = STATE_SIGNAL_ARG; else { log_error("Unexpected token in signal (2)."); return -EINVAL; } break; case STATE_SIGNAL_ARG_TYPE: if (t == XML_ATTRIBUTE_VALUE) { free(argument_type); argument_type = name; name = NULL; state = STATE_SIGNAL_ARG; } else { log_error("Unexpected token in signal (3)."); return -EINVAL; } break; case STATE_PROPERTY: if (t == XML_ATTRIBUTE_NAME) { if (streq_ptr(name, "name")) state = STATE_PROPERTY_NAME; else if (streq_ptr(name, "type")) state = STATE_PROPERTY_TYPE; else if (streq_ptr(name, "access")) state = STATE_PROPERTY_ACCESS; else { log_error("Unexpected attribute %s.", name); return -EBADMSG; } } else if (t == XML_TAG_OPEN) { if (streq_ptr(name, "annotation")) { r = parse_xml_annotation(context, &context->member_flags); if (r < 0) return r; } else { log_error("Unexpected tag %s.", name); return -EINVAL; } } else if (t == XML_TAG_CLOSE_EMPTY || (t == XML_TAG_CLOSE && streq_ptr(name, "property"))) { if (n_depth == 0) { if (context->ops->on_property) { r = context->ops->on_property(context->interface_name, context->member_name, context->member_signature, context->member_writable, context->member_flags, context->userdata); if (r < 0) return r; } context_reset_member(context); } state = STATE_INTERFACE; } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { log_error("Unexpected token in . (1)"); return -EINVAL; } break; case STATE_PROPERTY_NAME: if (t == XML_ATTRIBUTE_VALUE) { if (n_depth == 0) { free(context->member_name); context->member_name = name; name = NULL; } state = STATE_PROPERTY; } else { log_error("Unexpected token in . (2)"); return -EINVAL; } break; case STATE_PROPERTY_TYPE: if (t == XML_ATTRIBUTE_VALUE) { if (n_depth == 0) { free(context->member_signature); context->member_signature = name; name = NULL; } state = STATE_PROPERTY; } else { log_error("Unexpected token in . (3)"); return -EINVAL; } break; case STATE_PROPERTY_ACCESS: if (t == XML_ATTRIBUTE_VALUE) { if (streq(name, "readwrite") || streq(name, "write")) context->member_writable = true; state = STATE_PROPERTY; } else { log_error("Unexpected token in . (4)"); return -EINVAL; } break; } } } int parse_xml_introspect(const char *prefix, const char *xml, const XMLIntrospectOps *ops, void *userdata) { Context context = { .ops = ops, .userdata = userdata, .current = xml, }; int r; assert(prefix); assert(xml); assert(ops); for (;;) { _cleanup_free_ char *name = NULL; r = xml_tokenize(&context.current, &name, &context.xml_state, NULL); if (r < 0) { log_error("XML parse error"); goto finish; } if (r == XML_END) { r = 0; break; } if (r == XML_TAG_OPEN) { if (streq(name, "node")) { r = parse_xml_node(&context, prefix, 0); if (r < 0) goto finish; } else { log_error("Unexpected tag '%s' in introspection data.", name); r = -EBADMSG; goto finish; } } else if (r != XML_TEXT || !in_charset(name, WHITESPACE)) { log_error("Unexpected token."); r = -EBADMSG; goto finish; } } finish: context_reset_interface(&context); return r; } systemd-229/src/libsystemd/sd-bus/busctl-introspect.h000066400000000000000000000026621265713322000230670ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include typedef struct XMLIntrospectOps { int (*on_path)(const char *path, void *userdata); int (*on_interface)(const char *name, uint64_t flags, void *userdata); int (*on_method)(const char *interface, const char *name, const char *signature, const char *result, uint64_t flags, void *userdata); int (*on_signal)(const char *interface, const char *name, const char *signature, uint64_t flags, void *userdata); int (*on_property)(const char *interface, const char *name, const char *signature, bool writable, uint64_t flags, void *userdata); } XMLIntrospectOps; int parse_xml_introspect(const char *prefix, const char *xml, const XMLIntrospectOps *ops, void *userdata); systemd-229/src/libsystemd/sd-bus/busctl.c000066400000000000000000002041541265713322000206720ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-dump.h" #include "bus-internal.h" #include "bus-signature.h" #include "bus-type.h" #include "bus-util.h" #include "busctl-introspect.h" #include "escape.h" #include "fd-util.h" #include "locale-util.h" #include "log.h" #include "pager.h" #include "parse-util.h" #include "path-util.h" #include "set.h" #include "strv.h" #include "terminal-util.h" #include "user-util.h" #include "util.h" static bool arg_no_pager = false; static bool arg_legend = true; static char *arg_address = NULL; static bool arg_unique = false; static bool arg_acquired = false; static bool arg_activatable = false; static bool arg_show_machine = false; static char **arg_matches = NULL; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static char *arg_host = NULL; static bool arg_user = false; static size_t arg_snaplen = 4096; static bool arg_list = false; static bool arg_quiet = false; static bool arg_verbose = false; static bool arg_expect_reply = true; static bool arg_auto_start = true; static bool arg_allow_interactive_authorization = true; static bool arg_augment_creds = true; static usec_t arg_timeout = 0; static void pager_open_if_enabled(void) { /* Cache result before we open the pager */ if (arg_no_pager) return; pager_open(false); } #define NAME_IS_ACQUIRED INT_TO_PTR(1) #define NAME_IS_ACTIVATABLE INT_TO_PTR(2) static int list_bus_names(sd_bus *bus, char **argv) { _cleanup_strv_free_ char **acquired = NULL, **activatable = NULL; _cleanup_free_ char **merged = NULL; _cleanup_hashmap_free_ Hashmap *names = NULL; char **i; int r; size_t max_i = 0; unsigned n = 0; void *v; char *k; Iterator iterator; assert(bus); if (!arg_unique && !arg_acquired && !arg_activatable) arg_unique = arg_acquired = arg_activatable = true; r = sd_bus_list_names(bus, (arg_acquired || arg_unique) ? &acquired : NULL, arg_activatable ? &activatable : NULL); if (r < 0) return log_error_errno(r, "Failed to list names: %m"); pager_open_if_enabled(); names = hashmap_new(&string_hash_ops); if (!names) return log_oom(); STRV_FOREACH(i, acquired) { max_i = MAX(max_i, strlen(*i)); r = hashmap_put(names, *i, NAME_IS_ACQUIRED); if (r < 0) return log_error_errno(r, "Failed to add to hashmap: %m"); } STRV_FOREACH(i, activatable) { max_i = MAX(max_i, strlen(*i)); r = hashmap_put(names, *i, NAME_IS_ACTIVATABLE); if (r < 0 && r != -EEXIST) return log_error_errno(r, "Failed to add to hashmap: %m"); } merged = new(char*, hashmap_size(names) + 1); HASHMAP_FOREACH_KEY(v, k, names, iterator) merged[n++] = k; merged[n] = NULL; strv_sort(merged); if (arg_legend) { printf("%-*s %*s %-*s %-*s %-*s %-*s %-*s %-*s", (int) max_i, "NAME", 10, "PID", 15, "PROCESS", 16, "USER", 13, "CONNECTION", 25, "UNIT", 10, "SESSION", 19, "DESCRIPTION"); if (arg_show_machine) puts(" MACHINE"); else putchar('\n'); } STRV_FOREACH(i, merged) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; sd_id128_t mid; if (hashmap_get(names, *i) == NAME_IS_ACTIVATABLE) { /* Activatable */ printf("%-*s", (int) max_i, *i); printf(" - - - (activatable) - - "); if (arg_show_machine) puts(" -"); else putchar('\n'); continue; } if (!arg_unique && (*i)[0] == ':') continue; if (!arg_acquired && (*i)[0] != ':') continue; printf("%-*s", (int) max_i, *i); r = sd_bus_get_name_creds( bus, *i, (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM| SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_SESSION| SD_BUS_CREDS_DESCRIPTION, &creds); if (r >= 0) { const char *unique, *session, *unit, *cn; pid_t pid; uid_t uid; r = sd_bus_creds_get_pid(creds, &pid); if (r >= 0) { const char *comm = NULL; sd_bus_creds_get_comm(creds, &comm); printf(" %10lu %-15s", (unsigned long) pid, strna(comm)); } else fputs(" - - ", stdout); r = sd_bus_creds_get_euid(creds, &uid); if (r >= 0) { _cleanup_free_ char *u = NULL; u = uid_to_name(uid); if (!u) return log_oom(); if (strlen(u) > 16) u[16] = 0; printf(" %-16s", u); } else fputs(" - ", stdout); r = sd_bus_creds_get_unique_name(creds, &unique); if (r >= 0) printf(" %-13s", unique); else fputs(" - ", stdout); r = sd_bus_creds_get_unit(creds, &unit); if (r >= 0) { _cleanup_free_ char *e; e = ellipsize(unit, 25, 100); if (!e) return log_oom(); printf(" %-25s", e); } else fputs(" - ", stdout); r = sd_bus_creds_get_session(creds, &session); if (r >= 0) printf(" %-10s", session); else fputs(" - ", stdout); r = sd_bus_creds_get_description(creds, &cn); if (r >= 0) printf(" %-19s", cn); else fputs(" - ", stdout); } else printf(" - - - - - - - "); if (arg_show_machine) { r = sd_bus_get_name_machine_id(bus, *i, &mid); if (r >= 0) { char m[SD_ID128_STRING_MAX]; printf(" %s\n", sd_id128_to_string(mid, m)); } else puts(" -"); } else putchar('\n'); } return 0; } static void print_subtree(const char *prefix, const char *path, char **l) { const char *vertical, *space; char **n; /* We assume the list is sorted. Let's first skip over the * entry we are looking at. */ for (;;) { if (!*l) return; if (!streq(*l, path)) break; l++; } vertical = strjoina(prefix, draw_special_char(DRAW_TREE_VERTICAL)); space = strjoina(prefix, draw_special_char(DRAW_TREE_SPACE)); for (;;) { bool has_more = false; if (!*l || !path_startswith(*l, path)) break; n = l + 1; for (;;) { if (!*n || !path_startswith(*n, path)) break; if (!path_startswith(*n, *l)) { has_more = true; break; } n++; } printf("%s%s%s\n", prefix, draw_special_char(has_more ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT), *l); print_subtree(has_more ? vertical : space, *l, l); l = n; } } static void print_tree(const char *prefix, char **l) { pager_open_if_enabled(); prefix = strempty(prefix); if (arg_list) { char **i; STRV_FOREACH(i, l) printf("%s%s\n", prefix, *i); return; } if (strv_isempty(l)) { printf("No objects discovered.\n"); return; } if (streq(l[0], "/") && !l[1]) { printf("Only root object discovered.\n"); return; } print_subtree(prefix, "/", l); } static int on_path(const char *path, void *userdata) { Set *paths = userdata; int r; assert(paths); r = set_put_strdup(paths, path); if (r < 0) return log_oom(); return 0; } static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths, bool many) { static const XMLIntrospectOps ops = { .on_path = on_path, }; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *xml; int r; r = sd_bus_call_method(bus, service, path, "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); if (r < 0) { if (many) printf("Failed to introspect object %s of service %s: %s\n", path, service, bus_error_message(&error, r)); else log_error("Failed to introspect object %s of service %s: %s", path, service, bus_error_message(&error, r)); return r; } r = sd_bus_message_read(reply, "s", &xml); if (r < 0) return bus_log_parse_error(r); return parse_xml_introspect(path, xml, &ops, paths); } static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool many) { _cleanup_set_free_free_ Set *paths = NULL, *done = NULL, *failed = NULL; _cleanup_free_ char **l = NULL; char *m; int r; paths = set_new(&string_hash_ops); if (!paths) return log_oom(); done = set_new(&string_hash_ops); if (!done) return log_oom(); failed = set_new(&string_hash_ops); if (!failed) return log_oom(); m = strdup("/"); if (!m) return log_oom(); r = set_put(paths, m); if (r < 0) { free(m); return log_oom(); } for (;;) { _cleanup_free_ char *p = NULL; int q; p = set_steal_first(paths); if (!p) break; if (set_contains(done, p) || set_contains(failed, p)) continue; q = find_nodes(bus, service, p, paths, many); if (q < 0) { if (r >= 0) r = q; q = set_put(failed, p); } else q = set_put(done, p); if (q < 0) return log_oom(); assert(q != 0); p = NULL; } pager_open_if_enabled(); l = set_get_strv(done); if (!l) return log_oom(); strv_sort(l); print_tree(prefix, l); fflush(stdout); return r; } static int tree(sd_bus *bus, char **argv) { char **i; int r = 0; if (!arg_unique && !arg_acquired) arg_acquired = true; if (strv_length(argv) <= 1) { _cleanup_strv_free_ char **names = NULL; bool not_first = false; r = sd_bus_list_names(bus, &names, NULL); if (r < 0) return log_error_errno(r, "Failed to get name list: %m"); pager_open_if_enabled(); STRV_FOREACH(i, names) { int q; if (!arg_unique && (*i)[0] == ':') continue; if (!arg_acquired && (*i)[0] == ':') continue; if (not_first) printf("\n"); printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal()); q = tree_one(bus, *i, NULL, true); if (q < 0 && r >= 0) r = q; not_first = true; } } else { STRV_FOREACH(i, argv+1) { int q; if (i > argv+1) printf("\n"); if (argv[2]) { pager_open_if_enabled(); printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal()); } q = tree_one(bus, *i, NULL, !!argv[2]); if (q < 0 && r >= 0) r = q; } } return r; } static int format_cmdline(sd_bus_message *m, FILE *f, bool needs_space) { int r; for (;;) { const char *contents = NULL; char type; union { uint8_t u8; uint16_t u16; int16_t s16; uint32_t u32; int32_t s32; uint64_t u64; int64_t s64; double d64; const char *string; int i; } basic; r = sd_bus_message_peek_type(m, &type, &contents); if (r <= 0) return r; if (bus_type_is_container(type) > 0) { r = sd_bus_message_enter_container(m, type, contents); if (r < 0) return r; if (type == SD_BUS_TYPE_ARRAY) { unsigned n = 0; /* count array entries */ for (;;) { r = sd_bus_message_skip(m, contents); if (r < 0) return r; if (r == 0) break; n++; } r = sd_bus_message_rewind(m, false); if (r < 0) return r; if (needs_space) fputc(' ', f); fprintf(f, "%u", n); } else if (type == SD_BUS_TYPE_VARIANT) { if (needs_space) fputc(' ', f); fprintf(f, "%s", contents); } r = format_cmdline(m, f, needs_space || IN_SET(type, SD_BUS_TYPE_ARRAY, SD_BUS_TYPE_VARIANT)); if (r < 0) return r; r = sd_bus_message_exit_container(m); if (r < 0) return r; continue; } r = sd_bus_message_read_basic(m, type, &basic); if (r < 0) return r; if (needs_space) fputc(' ', f); switch (type) { case SD_BUS_TYPE_BYTE: fprintf(f, "%u", basic.u8); break; case SD_BUS_TYPE_BOOLEAN: fputs(true_false(basic.i), f); break; case SD_BUS_TYPE_INT16: fprintf(f, "%i", basic.s16); break; case SD_BUS_TYPE_UINT16: fprintf(f, "%u", basic.u16); break; case SD_BUS_TYPE_INT32: fprintf(f, "%i", basic.s32); break; case SD_BUS_TYPE_UINT32: fprintf(f, "%u", basic.u32); break; case SD_BUS_TYPE_INT64: fprintf(f, "%" PRIi64, basic.s64); break; case SD_BUS_TYPE_UINT64: fprintf(f, "%" PRIu64, basic.u64); break; case SD_BUS_TYPE_DOUBLE: fprintf(f, "%g", basic.d64); break; case SD_BUS_TYPE_STRING: case SD_BUS_TYPE_OBJECT_PATH: case SD_BUS_TYPE_SIGNATURE: { _cleanup_free_ char *b = NULL; b = cescape(basic.string); if (!b) return -ENOMEM; fprintf(f, "\"%s\"", b); break; } case SD_BUS_TYPE_UNIX_FD: fprintf(f, "%i", basic.i); break; default: assert_not_reached("Unknown basic type."); } needs_space = true; } } typedef struct Member { const char *type; char *interface; char *name; char *signature; char *result; char *value; bool writable; uint64_t flags; } Member; static void member_hash_func(const void *p, struct siphash *state) { const Member *m = p; uint64_t arity = 1; assert(m); assert(m->type); string_hash_func(m->type, state); arity += !!m->name + !!m->interface; uint64_hash_func(&arity, state); if (m->name) string_hash_func(m->name, state); if (m->interface) string_hash_func(m->interface, state); } static int member_compare_func(const void *a, const void *b) { const Member *x = a, *y = b; int d; assert(x); assert(y); assert(x->type); assert(y->type); d = strcmp_ptr(x->interface, y->interface); if (d != 0) return d; d = strcmp(x->type, y->type); if (d != 0) return d; return strcmp_ptr(x->name, y->name); } static int member_compare_funcp(const void *a, const void *b) { const Member *const * x = (const Member *const *) a, * const *y = (const Member *const *) b; return member_compare_func(*x, *y); } static void member_free(Member *m) { if (!m) return; free(m->interface); free(m->name); free(m->signature); free(m->result); free(m->value); free(m); } DEFINE_TRIVIAL_CLEANUP_FUNC(Member*, member_free); static void member_set_free(Set *s) { Member *m; while ((m = set_steal_first(s))) member_free(m); set_free(s); } DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, member_set_free); static int on_interface(const char *interface, uint64_t flags, void *userdata) { _cleanup_(member_freep) Member *m; Set *members = userdata; int r; assert(interface); assert(members); m = new0(Member, 1); if (!m) return log_oom(); m->type = "interface"; m->flags = flags; r = free_and_strdup(&m->interface, interface); if (r < 0) return log_oom(); r = set_put(members, m); if (r <= 0) { log_error("Duplicate interface"); return -EINVAL; } m = NULL; return 0; } static int on_method(const char *interface, const char *name, const char *signature, const char *result, uint64_t flags, void *userdata) { _cleanup_(member_freep) Member *m; Set *members = userdata; int r; assert(interface); assert(name); m = new0(Member, 1); if (!m) return log_oom(); m->type = "method"; m->flags = flags; r = free_and_strdup(&m->interface, interface); if (r < 0) return log_oom(); r = free_and_strdup(&m->name, name); if (r < 0) return log_oom(); r = free_and_strdup(&m->signature, signature); if (r < 0) return log_oom(); r = free_and_strdup(&m->result, result); if (r < 0) return log_oom(); r = set_put(members, m); if (r <= 0) { log_error("Duplicate method"); return -EINVAL; } m = NULL; return 0; } static int on_signal(const char *interface, const char *name, const char *signature, uint64_t flags, void *userdata) { _cleanup_(member_freep) Member *m; Set *members = userdata; int r; assert(interface); assert(name); m = new0(Member, 1); if (!m) return log_oom(); m->type = "signal"; m->flags = flags; r = free_and_strdup(&m->interface, interface); if (r < 0) return log_oom(); r = free_and_strdup(&m->name, name); if (r < 0) return log_oom(); r = free_and_strdup(&m->signature, signature); if (r < 0) return log_oom(); r = set_put(members, m); if (r <= 0) { log_error("Duplicate signal"); return -EINVAL; } m = NULL; return 0; } static int on_property(const char *interface, const char *name, const char *signature, bool writable, uint64_t flags, void *userdata) { _cleanup_(member_freep) Member *m; Set *members = userdata; int r; assert(interface); assert(name); m = new0(Member, 1); if (!m) return log_oom(); m->type = "property"; m->flags = flags; m->writable = writable; r = free_and_strdup(&m->interface, interface); if (r < 0) return log_oom(); r = free_and_strdup(&m->name, name); if (r < 0) return log_oom(); r = free_and_strdup(&m->signature, signature); if (r < 0) return log_oom(); r = set_put(members, m); if (r <= 0) { log_error("Duplicate property"); return -EINVAL; } m = NULL; return 0; } static const char *strdash(const char *x) { return isempty(x) ? "-" : x; } static int introspect(sd_bus *bus, char **argv) { static const struct hash_ops member_hash_ops = { .hash = member_hash_func, .compare = member_compare_func, }; static const XMLIntrospectOps ops = { .on_interface = on_interface, .on_method = on_method, .on_signal = on_signal, .on_property = on_property, }; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(member_set_freep) Set *members = NULL; Iterator i; Member *m; const char *xml; int r; unsigned name_width, type_width, signature_width, result_width; Member **sorted = NULL; unsigned k = 0, j, n_args; n_args = strv_length(argv); if (n_args < 3) { log_error("Requires service and object path argument."); return -EINVAL; } if (n_args > 4) { log_error("Too many arguments."); return -EINVAL; } members = set_new(&member_hash_ops); if (!members) return log_oom(); r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); if (r < 0) { log_error("Failed to introspect object %s of service %s: %s", argv[2], argv[1], bus_error_message(&error, r)); return r; } r = sd_bus_message_read(reply, "s", &xml); if (r < 0) return bus_log_parse_error(r); /* First, get list of all properties */ r = parse_xml_introspect(argv[2], xml, &ops, members); if (r < 0) return r; /* Second, find the current values for them */ SET_FOREACH(m, members, i) { if (!streq(m->type, "property")) continue; if (m->value) continue; if (argv[3] && !streq(argv[3], m->interface)) continue; r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", m->interface); if (r < 0) { log_error("%s", bus_error_message(&error, r)); return r; } r = sd_bus_message_enter_container(reply, 'a', "{sv}"); if (r < 0) return bus_log_parse_error(r); for (;;) { Member *z; _cleanup_free_ char *buf = NULL; _cleanup_fclose_ FILE *mf = NULL; size_t sz = 0; const char *name; r = sd_bus_message_enter_container(reply, 'e', "sv"); if (r < 0) return bus_log_parse_error(r); if (r == 0) break; r = sd_bus_message_read(reply, "s", &name); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_enter_container(reply, 'v', NULL); if (r < 0) return bus_log_parse_error(r); mf = open_memstream(&buf, &sz); if (!mf) return log_oom(); r = format_cmdline(reply, mf, false); if (r < 0) return bus_log_parse_error(r); fclose(mf); mf = NULL; z = set_get(members, &((Member) { .type = "property", .interface = m->interface, .name = (char*) name })); if (z) { free(z->value); z->value = buf; buf = NULL; } r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); } r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); } pager_open_if_enabled(); name_width = strlen("NAME"); type_width = strlen("TYPE"); signature_width = strlen("SIGNATURE"); result_width = strlen("RESULT/VALUE"); sorted = newa(Member*, set_size(members)); SET_FOREACH(m, members, i) { if (argv[3] && !streq(argv[3], m->interface)) continue; if (m->interface) name_width = MAX(name_width, strlen(m->interface)); if (m->name) name_width = MAX(name_width, strlen(m->name) + 1); if (m->type) type_width = MAX(type_width, strlen(m->type)); if (m->signature) signature_width = MAX(signature_width, strlen(m->signature)); if (m->result) result_width = MAX(result_width, strlen(m->result)); if (m->value) result_width = MAX(result_width, strlen(m->value)); sorted[k++] = m; } if (result_width > 40) result_width = 40; qsort(sorted, k, sizeof(Member*), member_compare_funcp); if (arg_legend) { printf("%-*s %-*s %-*s %-*s %s\n", (int) name_width, "NAME", (int) type_width, "TYPE", (int) signature_width, "SIGNATURE", (int) result_width, "RESULT/VALUE", "FLAGS"); } for (j = 0; j < k; j++) { _cleanup_free_ char *ellipsized = NULL; const char *rv; bool is_interface; m = sorted[j]; if (argv[3] && !streq(argv[3], m->interface)) continue; is_interface = streq(m->type, "interface"); if (argv[3] && is_interface) continue; if (m->value) { ellipsized = ellipsize(m->value, result_width, 100); if (!ellipsized) return log_oom(); rv = ellipsized; } else rv = strdash(m->result); printf("%s%s%-*s%s %-*s %-*s %-*s%s%s%s%s%s%s\n", is_interface ? ansi_highlight() : "", is_interface ? "" : ".", - !is_interface + (int) name_width, strdash(streq_ptr(m->type, "interface") ? m->interface : m->name), is_interface ? ansi_normal() : "", (int) type_width, strdash(m->type), (int) signature_width, strdash(m->signature), (int) result_width, rv, (m->flags & SD_BUS_VTABLE_DEPRECATED) ? " deprecated" : (m->flags || m->writable ? "" : " -"), (m->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) ? " no-reply" : "", (m->flags & SD_BUS_VTABLE_PROPERTY_CONST) ? " const" : "", (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) ? " emits-change" : "", (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) ? " emits-invalidation" : "", m->writable ? " writable" : ""); } return 0; } static int message_dump(sd_bus_message *m, FILE *f) { return bus_message_dump(m, f, BUS_MESSAGE_DUMP_WITH_HEADER); } static int message_pcap(sd_bus_message *m, FILE *f) { return bus_message_pcap_frame(m, arg_snaplen, f); } static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FILE *f)) { bool added_something = false; char **i; int r; STRV_FOREACH(i, argv+1) { _cleanup_free_ char *m = NULL; if (!service_name_is_valid(*i)) { log_error("Invalid service name '%s'", *i); return -EINVAL; } m = strjoin("sender='", *i, "'", NULL); if (!m) return log_oom(); r = sd_bus_add_match(bus, NULL, m, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to add match: %m"); free(m); m = strjoin("destination='", *i, "'", NULL); if (!m) return log_oom(); r = sd_bus_add_match(bus, NULL, m, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to add match: %m"); added_something = true; } STRV_FOREACH(i, arg_matches) { r = sd_bus_add_match(bus, NULL, *i, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to add match: %m"); added_something = true; } if (!added_something) { r = sd_bus_add_match(bus, NULL, "", NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to add match: %m"); } log_info("Monitoring bus message stream."); for (;;) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; r = sd_bus_process(bus, &m); if (r < 0) return log_error_errno(r, "Failed to process bus: %m"); if (m) { dump(m, stdout); fflush(stdout); if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected") > 0) { log_info("Connection terminated, exiting."); return 0; } continue; } if (r > 0) continue; r = sd_bus_wait(bus, (uint64_t) -1); if (r < 0) return log_error_errno(r, "Failed to wait for bus: %m"); } } static int capture(sd_bus *bus, char *argv[]) { int r; if (isatty(fileno(stdout)) > 0) { log_error("Refusing to write message data to console, please redirect output to a file."); return -EINVAL; } bus_pcap_header(arg_snaplen, stdout); r = monitor(bus, argv, message_pcap); if (r < 0) return r; if (ferror(stdout)) { log_error("Couldn't write capture file."); return -EIO; } return r; } static int status(sd_bus *bus, char *argv[]) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; pid_t pid; int r; assert(bus); if (strv_length(argv) > 2) { log_error("Expects no or one argument."); return -EINVAL; } if (argv[1]) { r = parse_pid(argv[1], &pid); if (r < 0) r = sd_bus_get_name_creds( bus, argv[1], (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | _SD_BUS_CREDS_ALL, &creds); else r = sd_bus_creds_new_from_pid( &creds, pid, _SD_BUS_CREDS_ALL); } else { const char *scope, *address; sd_id128_t bus_id; r = sd_bus_get_address(bus, &address); if (r >= 0) printf("BusAddress=%s%s%s\n", ansi_highlight(), address, ansi_normal()); r = sd_bus_get_scope(bus, &scope); if (r >= 0) printf("BusScope=%s%s%s\n", ansi_highlight(), scope, ansi_normal()); r = sd_bus_get_bus_id(bus, &bus_id); if (r >= 0) printf("BusID=%s" SD_ID128_FORMAT_STR "%s\n", ansi_highlight(), SD_ID128_FORMAT_VAL(bus_id), ansi_normal()); r = sd_bus_get_owner_creds( bus, (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | _SD_BUS_CREDS_ALL, &creds); } if (r < 0) return log_error_errno(r, "Failed to get credentials: %m"); bus_creds_dump(creds, NULL, false); return 0; } static int message_append_cmdline(sd_bus_message *m, const char *signature, char ***x) { char **p; int r; assert(m); assert(signature); assert(x); p = *x; for (;;) { const char *v; char t; t = *signature; v = *p; if (t == 0) break; if (!v) { log_error("Too few parameters for signature."); return -EINVAL; } signature++; p++; switch (t) { case SD_BUS_TYPE_BOOLEAN: r = parse_boolean(v); if (r < 0) { log_error("Failed to parse as boolean: %s", v); return r; } r = sd_bus_message_append_basic(m, t, &r); break; case SD_BUS_TYPE_BYTE: { uint8_t z; r = safe_atou8(v, &z); if (r < 0) { log_error("Failed to parse as byte (unsigned 8bit integer): %s", v); return r; } r = sd_bus_message_append_basic(m, t, &z); break; } case SD_BUS_TYPE_INT16: { int16_t z; r = safe_atoi16(v, &z); if (r < 0) { log_error("Failed to parse as signed 16bit integer: %s", v); return r; } r = sd_bus_message_append_basic(m, t, &z); break; } case SD_BUS_TYPE_UINT16: { uint16_t z; r = safe_atou16(v, &z); if (r < 0) { log_error("Failed to parse as unsigned 16bit integer: %s", v); return r; } r = sd_bus_message_append_basic(m, t, &z); break; } case SD_BUS_TYPE_INT32: { int32_t z; r = safe_atoi32(v, &z); if (r < 0) { log_error("Failed to parse as signed 32bit integer: %s", v); return r; } r = sd_bus_message_append_basic(m, t, &z); break; } case SD_BUS_TYPE_UINT32: { uint32_t z; r = safe_atou32(v, &z); if (r < 0) { log_error("Failed to parse as unsigned 32bit integer: %s", v); return r; } r = sd_bus_message_append_basic(m, t, &z); break; } case SD_BUS_TYPE_INT64: { int64_t z; r = safe_atoi64(v, &z); if (r < 0) { log_error("Failed to parse as signed 64bit integer: %s", v); return r; } r = sd_bus_message_append_basic(m, t, &z); break; } case SD_BUS_TYPE_UINT64: { uint64_t z; r = safe_atou64(v, &z); if (r < 0) { log_error("Failed to parse as unsigned 64bit integer: %s", v); return r; } r = sd_bus_message_append_basic(m, t, &z); break; } case SD_BUS_TYPE_DOUBLE: { double z; r = safe_atod(v, &z); if (r < 0) { log_error("Failed to parse as double precision floating point: %s", v); return r; } r = sd_bus_message_append_basic(m, t, &z); break; } case SD_BUS_TYPE_STRING: case SD_BUS_TYPE_OBJECT_PATH: case SD_BUS_TYPE_SIGNATURE: r = sd_bus_message_append_basic(m, t, v); break; case SD_BUS_TYPE_ARRAY: { uint32_t n; size_t k; r = safe_atou32(v, &n); if (r < 0) { log_error("Failed to parse number of array entries: %s", v); return r; } r = signature_element_length(signature, &k); if (r < 0) { log_error("Invalid array signature."); return r; } { unsigned i; char s[k + 1]; memcpy(s, signature, k); s[k] = 0; r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s); if (r < 0) return bus_log_create_error(r); for (i = 0; i < n; i++) { r = message_append_cmdline(m, s, &p); if (r < 0) return r; } } signature += k; r = sd_bus_message_close_container(m); break; } case SD_BUS_TYPE_VARIANT: r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, v); if (r < 0) return bus_log_create_error(r); r = message_append_cmdline(m, v, &p); if (r < 0) return r; r = sd_bus_message_close_container(m); break; case SD_BUS_TYPE_STRUCT_BEGIN: case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { size_t k; signature--; p--; r = signature_element_length(signature, &k); if (r < 0) { log_error("Invalid struct/dict entry signature."); return r; } { char s[k-1]; memcpy(s, signature + 1, k - 2); s[k - 2] = 0; r = sd_bus_message_open_container(m, t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s); if (r < 0) return bus_log_create_error(r); r = message_append_cmdline(m, s, &p); if (r < 0) return r; } signature += k; r = sd_bus_message_close_container(m); break; } case SD_BUS_TYPE_UNIX_FD: log_error("UNIX file descriptor not supported as type."); return -EINVAL; default: log_error("Unknown signature type %c.", t); return -EINVAL; } if (r < 0) return bus_log_create_error(r); } *x = p; return 0; } static int call(sd_bus *bus, char *argv[]) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; int r; assert(bus); if (strv_length(argv) < 5) { log_error("Expects at least four arguments."); return -EINVAL; } r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], argv[3], argv[4]); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_set_expect_reply(m, arg_expect_reply); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_set_auto_start(m, arg_auto_start); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_set_allow_interactive_authorization(m, arg_allow_interactive_authorization); if (r < 0) return bus_log_create_error(r); if (!isempty(argv[5])) { char **p; p = argv+6; r = message_append_cmdline(m, argv[5], &p); if (r < 0) return r; if (*p) { log_error("Too many parameters for signature."); return -EINVAL; } } if (!arg_expect_reply) { r = sd_bus_send(bus, m, NULL); if (r < 0) { log_error("Failed to send message."); return r; } return 0; } r = sd_bus_call(bus, m, arg_timeout, &error, &reply); if (r < 0) { log_error("%s", bus_error_message(&error, r)); return r; } r = sd_bus_message_is_empty(reply); if (r < 0) return bus_log_parse_error(r); if (r == 0 && !arg_quiet) { if (arg_verbose) { pager_open_if_enabled(); r = bus_message_dump(reply, stdout, 0); if (r < 0) return r; } else { fputs(sd_bus_message_get_signature(reply, true), stdout); fputc(' ', stdout); r = format_cmdline(reply, stdout, false); if (r < 0) return bus_log_parse_error(r); fputc('\n', stdout); } } return 0; } static int get_property(sd_bus *bus, char *argv[]) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; unsigned n; char **i; int r; assert(bus); n = strv_length(argv); if (n < 5) { log_error("Expects at least four arguments."); return -EINVAL; } STRV_FOREACH(i, argv + 4) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *contents = NULL; char type; r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Get", &error, &reply, "ss", argv[3], *i); if (r < 0) { log_error("%s", bus_error_message(&error, r)); return r; } r = sd_bus_message_peek_type(reply, &type, &contents); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_enter_container(reply, 'v', contents); if (r < 0) return bus_log_parse_error(r); if (arg_verbose) { pager_open_if_enabled(); r = bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_SUBTREE_ONLY); if (r < 0) return r; } else { fputs(contents, stdout); fputc(' ', stdout); r = format_cmdline(reply, stdout, false); if (r < 0) return bus_log_parse_error(r); fputc('\n', stdout); } r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); } return 0; } static int set_property(sd_bus *bus, char *argv[]) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; unsigned n; char **p; int r; assert(bus); n = strv_length(argv); if (n < 6) { log_error("Expects at least five arguments."); return -EINVAL; } r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Set"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append(m, "ss", argv[3], argv[4]); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'v', argv[5]); if (r < 0) return bus_log_create_error(r); p = argv+6; r = message_append_cmdline(m, argv[5], &p); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); if (*p) { log_error("Too many parameters for signature."); return -EINVAL; } r = sd_bus_call(bus, m, arg_timeout, &error, NULL); if (r < 0) { log_error("%s", bus_error_message(&error, r)); return r; } return 0; } static int help(void) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" "Introspect the bus.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " --no-legend Do not show the headers and footers\n" " --system Connect to system bus\n" " --user Connect to user bus\n" " -H --host=[USER@]HOST Operate on remote host\n" " -M --machine=CONTAINER Operate on local container\n" " --address=ADDRESS Connect to bus specified by address\n" " --show-machine Show machine ID column in list\n" " --unique Only show unique names\n" " --acquired Only show acquired names\n" " --activatable Only show activatable names\n" " --match=MATCH Only show matching messages\n" " --size=SIZE Maximum length of captured packet\n" " --list Don't show tree, but simple object path list\n" " --quiet Don't show method call reply\n" " --verbose Show result values in long format\n" " --expect-reply=BOOL Expect a method call reply\n" " --auto-start=BOOL Auto-start destination service\n" " --allow-interactive-authorization=BOOL\n" " Allow interactive authorization for operation\n" " --timeout=SECS Maximum time to wait for method call completion\n" " --augment-creds=BOOL Extend credential data with data read from /proc/$PID\n\n" "Commands:\n" " list List bus names\n" " status [SERVICE] Show bus service, process or bus owner credentials\n" " monitor [SERVICE...] Show bus traffic\n" " capture [SERVICE...] Capture bus traffic as pcap\n" " tree [SERVICE...] Show object tree of service\n" " introspect SERVICE OBJECT [INTERFACE]\n" " call SERVICE OBJECT INTERFACE METHOD [SIGNATURE [ARGUMENT...]]\n" " Call a method\n" " get-property SERVICE OBJECT INTERFACE PROPERTY...\n" " Get property value\n" " set-property SERVICE OBJECT INTERFACE PROPERTY SIGNATURE ARGUMENT...\n" " Set property value\n" " help Show this help\n" , program_invocation_short_name); return 0; } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_LEGEND, ARG_SYSTEM, ARG_USER, ARG_ADDRESS, ARG_MATCH, ARG_SHOW_MACHINE, ARG_UNIQUE, ARG_ACQUIRED, ARG_ACTIVATABLE, ARG_SIZE, ARG_LIST, ARG_VERBOSE, ARG_EXPECT_REPLY, ARG_AUTO_START, ARG_ALLOW_INTERACTIVE_AUTHORIZATION, ARG_TIMEOUT, ARG_AUGMENT_CREDS, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, { "system", no_argument, NULL, ARG_SYSTEM }, { "user", no_argument, NULL, ARG_USER }, { "address", required_argument, NULL, ARG_ADDRESS }, { "show-machine", no_argument, NULL, ARG_SHOW_MACHINE }, { "unique", no_argument, NULL, ARG_UNIQUE }, { "acquired", no_argument, NULL, ARG_ACQUIRED }, { "activatable", no_argument, NULL, ARG_ACTIVATABLE }, { "match", required_argument, NULL, ARG_MATCH }, { "host", required_argument, NULL, 'H' }, { "machine", required_argument, NULL, 'M' }, { "size", required_argument, NULL, ARG_SIZE }, { "list", no_argument, NULL, ARG_LIST }, { "quiet", no_argument, NULL, 'q' }, { "verbose", no_argument, NULL, ARG_VERBOSE }, { "expect-reply", required_argument, NULL, ARG_EXPECT_REPLY }, { "auto-start", required_argument, NULL, ARG_AUTO_START }, { "allow-interactive-authorization", required_argument, NULL, ARG_ALLOW_INTERACTIVE_AUTHORIZATION }, { "timeout", required_argument, NULL, ARG_TIMEOUT }, { "augment-creds",required_argument, NULL, ARG_AUGMENT_CREDS}, {}, }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "hH:M:q", options, NULL)) >= 0) switch (c) { case 'h': return help(); case ARG_VERSION: return version(); case ARG_NO_PAGER: arg_no_pager = true; break; case ARG_NO_LEGEND: arg_legend = false; break; case ARG_USER: arg_user = true; break; case ARG_SYSTEM: arg_user = false; break; case ARG_ADDRESS: arg_address = optarg; break; case ARG_SHOW_MACHINE: arg_show_machine = true; break; case ARG_UNIQUE: arg_unique = true; break; case ARG_ACQUIRED: arg_acquired = true; break; case ARG_ACTIVATABLE: arg_activatable = true; break; case ARG_MATCH: if (strv_extend(&arg_matches, optarg) < 0) return log_oom(); break; case ARG_SIZE: { uint64_t sz; r = parse_size(optarg, 1024, &sz); if (r < 0) { log_error("Failed to parse size: %s", optarg); return r; } if ((uint64_t) (size_t) sz != sz) { log_error("Size out of range."); return -E2BIG; } arg_snaplen = (size_t) sz; break; } case ARG_LIST: arg_list = true; break; case 'H': arg_transport = BUS_TRANSPORT_REMOTE; arg_host = optarg; break; case 'M': arg_transport = BUS_TRANSPORT_MACHINE; arg_host = optarg; break; case 'q': arg_quiet = true; break; case ARG_VERBOSE: arg_verbose = true; break; case ARG_EXPECT_REPLY: r = parse_boolean(optarg); if (r < 0) { log_error("Failed to parse --expect-reply= parameter."); return r; } arg_expect_reply = !!r; break; case ARG_AUTO_START: r = parse_boolean(optarg); if (r < 0) { log_error("Failed to parse --auto-start= parameter."); return r; } arg_auto_start = !!r; break; case ARG_ALLOW_INTERACTIVE_AUTHORIZATION: r = parse_boolean(optarg); if (r < 0) { log_error("Failed to parse --allow-interactive-authorization= parameter."); return r; } arg_allow_interactive_authorization = !!r; break; case ARG_TIMEOUT: r = parse_sec(optarg, &arg_timeout); if (r < 0) { log_error("Failed to parse --timeout= parameter."); return r; } break; case ARG_AUGMENT_CREDS: r = parse_boolean(optarg); if (r < 0) { log_error("Failed to parse --augment-creds= parameter."); return r; } arg_augment_creds = !!r; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } static int busctl_main(sd_bus *bus, int argc, char *argv[]) { assert(bus); if (optind >= argc || streq(argv[optind], "list")) return list_bus_names(bus, argv + optind); if (streq(argv[optind], "monitor")) return monitor(bus, argv + optind, message_dump); if (streq(argv[optind], "capture")) return capture(bus, argv + optind); if (streq(argv[optind], "status")) return status(bus, argv + optind); if (streq(argv[optind], "tree")) return tree(bus, argv + optind); if (streq(argv[optind], "introspect")) return introspect(bus, argv + optind); if (streq(argv[optind], "call")) return call(bus, argv + optind); if (streq(argv[optind], "get-property")) return get_property(bus, argv + optind); if (streq(argv[optind], "set-property")) return set_property(bus, argv + optind); if (streq(argv[optind], "help")) return help(); log_error("Unknown command '%s'", argv[optind]); return -EINVAL; } int main(int argc, char *argv[]) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = sd_bus_new(&bus); if (r < 0) { log_error_errno(r, "Failed to allocate bus: %m"); goto finish; } if (streq_ptr(argv[optind], "monitor") || streq_ptr(argv[optind], "capture")) { r = sd_bus_set_monitor(bus, true); if (r < 0) { log_error_errno(r, "Failed to set monitor mode: %m"); goto finish; } r = sd_bus_negotiate_creds(bus, true, _SD_BUS_CREDS_ALL); if (r < 0) { log_error_errno(r, "Failed to enable credentials: %m"); goto finish; } r = sd_bus_negotiate_timestamp(bus, true); if (r < 0) { log_error_errno(r, "Failed to enable timestamps: %m"); goto finish; } r = sd_bus_negotiate_fds(bus, true); if (r < 0) { log_error_errno(r, "Failed to enable fds: %m"); goto finish; } } r = sd_bus_set_bus_client(bus, true); if (r < 0) { log_error_errno(r, "Failed to set bus client: %m"); goto finish; } if (arg_address) r = sd_bus_set_address(bus, arg_address); else { switch (arg_transport) { case BUS_TRANSPORT_LOCAL: if (arg_user) { bus->is_user = true; r = bus_set_address_user(bus); } else { bus->is_system = true; r = bus_set_address_system(bus); } break; case BUS_TRANSPORT_REMOTE: r = bus_set_address_system_remote(bus, arg_host); break; case BUS_TRANSPORT_MACHINE: r = bus_set_address_system_machine(bus, arg_host); break; default: assert_not_reached("Hmm, unknown transport type."); } } if (r < 0) { log_error_errno(r, "Failed to set address: %m"); goto finish; } r = sd_bus_start(bus); if (r < 0) { log_error_errno(r, "Failed to connect to bus: %m"); goto finish; } r = busctl_main(bus, argc, argv); finish: pager_close(); strv_free(arg_matches); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/libsystemd/sd-bus/kdbus.h000066400000000000000000000755611265713322000205230ustar00rootroot00000000000000/* * kdbus is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at * your option) any later version. */ #ifndef _UAPI_KDBUS_H_ #define _UAPI_KDBUS_H_ #include #include #define KDBUS_IOCTL_MAGIC 0x95 #define KDBUS_SRC_ID_KERNEL (0) #define KDBUS_DST_ID_NAME (0) #define KDBUS_MATCH_ID_ANY (~0ULL) #define KDBUS_DST_ID_BROADCAST (~0ULL) #define KDBUS_FLAG_NEGOTIATE (1ULL << 63) /** * struct kdbus_notify_id_change - name registry change message * @id: New or former owner of the name * @flags: flags field from KDBUS_HELLO_* * * Sent from kernel to userspace when the owner or activator of * a well-known name changes. * * Attached to: * KDBUS_ITEM_ID_ADD * KDBUS_ITEM_ID_REMOVE */ struct kdbus_notify_id_change { __u64 id; __u64 flags; } __attribute__((__aligned__(8))); /** * struct kdbus_notify_name_change - name registry change message * @old_id: ID and flags of former owner of a name * @new_id: ID and flags of new owner of a name * @name: Well-known name * * Sent from kernel to userspace when the owner or activator of * a well-known name changes. * * Attached to: * KDBUS_ITEM_NAME_ADD * KDBUS_ITEM_NAME_REMOVE * KDBUS_ITEM_NAME_CHANGE */ struct kdbus_notify_name_change { struct kdbus_notify_id_change old_id; struct kdbus_notify_id_change new_id; char name[0]; } __attribute__((__aligned__(8))); /** * struct kdbus_creds - process credentials * @uid: User ID * @euid: Effective UID * @suid: Saved UID * @fsuid: Filesystem UID * @gid: Group ID * @egid: Effective GID * @sgid: Saved GID * @fsgid: Filesystem GID * * Attached to: * KDBUS_ITEM_CREDS */ struct kdbus_creds { __u64 uid; __u64 euid; __u64 suid; __u64 fsuid; __u64 gid; __u64 egid; __u64 sgid; __u64 fsgid; } __attribute__((__aligned__(8))); /** * struct kdbus_pids - process identifiers * @pid: Process ID * @tid: Thread ID * @ppid: Parent process ID * * The PID and TID of a process. * * Attached to: * KDBUS_ITEM_PIDS */ struct kdbus_pids { __u64 pid; __u64 tid; __u64 ppid; } __attribute__((__aligned__(8))); /** * struct kdbus_caps - process capabilities * @last_cap: Highest currently known capability bit * @caps: Variable number of 32-bit capabilities flags * * Contains a variable number of 32-bit capabilities flags. * * Attached to: * KDBUS_ITEM_CAPS */ struct kdbus_caps { __u32 last_cap; __u32 caps[0]; } __attribute__((__aligned__(8))); /** * struct kdbus_audit - audit information * @sessionid: The audit session ID * @loginuid: The audit login uid * * Attached to: * KDBUS_ITEM_AUDIT */ struct kdbus_audit { __u32 sessionid; __u32 loginuid; } __attribute__((__aligned__(8))); /** * struct kdbus_timestamp * @seqnum: Global per-domain message sequence number * @monotonic_ns: Monotonic timestamp, in nanoseconds * @realtime_ns: Realtime timestamp, in nanoseconds * * Attached to: * KDBUS_ITEM_TIMESTAMP */ struct kdbus_timestamp { __u64 seqnum; __u64 monotonic_ns; __u64 realtime_ns; } __attribute__((__aligned__(8))); /** * struct kdbus_vec - I/O vector for kdbus payload items * @size: The size of the vector * @address: Memory address of data buffer * @offset: Offset in the in-message payload memory, * relative to the message head * * Attached to: * KDBUS_ITEM_PAYLOAD_VEC, KDBUS_ITEM_PAYLOAD_OFF */ struct kdbus_vec { __u64 size; union { __u64 address; __u64 offset; }; } __attribute__((__aligned__(8))); /** * struct kdbus_bloom_parameter - bus-wide bloom parameters * @size: Size of the bit field in bytes (m / 8) * @n_hash: Number of hash functions used (k) */ struct kdbus_bloom_parameter { __u64 size; __u64 n_hash; } __attribute__((__aligned__(8))); /** * struct kdbus_bloom_filter - bloom filter containing n elements * @generation: Generation of the element set in the filter * @data: Bit field, multiple of 8 bytes */ struct kdbus_bloom_filter { __u64 generation; __u64 data[0]; } __attribute__((__aligned__(8))); /** * struct kdbus_memfd - a kdbus memfd * @start: The offset into the memfd where the segment starts * @size: The size of the memfd segment * @fd: The file descriptor number * @__pad: Padding to ensure proper alignment and size * * Attached to: * KDBUS_ITEM_PAYLOAD_MEMFD */ struct kdbus_memfd { __u64 start; __u64 size; int fd; __u32 __pad; } __attribute__((__aligned__(8))); /** * struct kdbus_name - a registered well-known name with its flags * @flags: Flags from KDBUS_NAME_* * @name: Well-known name * * Attached to: * KDBUS_ITEM_OWNED_NAME */ struct kdbus_name { __u64 flags; char name[0]; } __attribute__((__aligned__(8))); /** * enum kdbus_policy_access_type - permissions of a policy record * @_KDBUS_POLICY_ACCESS_NULL: Uninitialized/invalid * @KDBUS_POLICY_ACCESS_USER: Grant access to a uid * @KDBUS_POLICY_ACCESS_GROUP: Grant access to gid * @KDBUS_POLICY_ACCESS_WORLD: World-accessible */ enum kdbus_policy_access_type { _KDBUS_POLICY_ACCESS_NULL, KDBUS_POLICY_ACCESS_USER, KDBUS_POLICY_ACCESS_GROUP, KDBUS_POLICY_ACCESS_WORLD, }; /** * enum kdbus_policy_access_flags - mode flags * @KDBUS_POLICY_OWN: Allow to own a well-known name * Implies KDBUS_POLICY_TALK and KDBUS_POLICY_SEE * @KDBUS_POLICY_TALK: Allow communication to a well-known name * Implies KDBUS_POLICY_SEE * @KDBUS_POLICY_SEE: Allow to see a well-known name */ enum kdbus_policy_type { KDBUS_POLICY_SEE = 0, KDBUS_POLICY_TALK, KDBUS_POLICY_OWN, }; /** * struct kdbus_policy_access - policy access item * @type: One of KDBUS_POLICY_ACCESS_* types * @access: Access to grant * @id: For KDBUS_POLICY_ACCESS_USER, the uid * For KDBUS_POLICY_ACCESS_GROUP, the gid */ struct kdbus_policy_access { __u64 type; /* USER, GROUP, WORLD */ __u64 access; /* OWN, TALK, SEE */ __u64 id; /* uid, gid, 0 */ } __attribute__((__aligned__(8))); /** * enum kdbus_attach_flags - flags for metadata attachments * @KDBUS_ATTACH_TIMESTAMP: Timestamp * @KDBUS_ATTACH_CREDS: Credentials * @KDBUS_ATTACH_PIDS: PIDs * @KDBUS_ATTACH_AUXGROUPS: Auxiliary groups * @KDBUS_ATTACH_NAMES: Well-known names * @KDBUS_ATTACH_TID_COMM: The "comm" process identifier of the TID * @KDBUS_ATTACH_PID_COMM: The "comm" process identifier of the PID * @KDBUS_ATTACH_EXE: The path of the executable * @KDBUS_ATTACH_CMDLINE: The process command line * @KDBUS_ATTACH_CGROUP: The croup membership * @KDBUS_ATTACH_CAPS: The process capabilities * @KDBUS_ATTACH_SECLABEL: The security label * @KDBUS_ATTACH_AUDIT: The audit IDs * @KDBUS_ATTACH_CONN_DESCRIPTION: The human-readable connection name * @_KDBUS_ATTACH_ALL: All of the above * @_KDBUS_ATTACH_ANY: Wildcard match to enable any kind of * metatdata. */ enum kdbus_attach_flags { KDBUS_ATTACH_TIMESTAMP = 1ULL << 0, KDBUS_ATTACH_CREDS = 1ULL << 1, KDBUS_ATTACH_PIDS = 1ULL << 2, KDBUS_ATTACH_AUXGROUPS = 1ULL << 3, KDBUS_ATTACH_NAMES = 1ULL << 4, KDBUS_ATTACH_TID_COMM = 1ULL << 5, KDBUS_ATTACH_PID_COMM = 1ULL << 6, KDBUS_ATTACH_EXE = 1ULL << 7, KDBUS_ATTACH_CMDLINE = 1ULL << 8, KDBUS_ATTACH_CGROUP = 1ULL << 9, KDBUS_ATTACH_CAPS = 1ULL << 10, KDBUS_ATTACH_SECLABEL = 1ULL << 11, KDBUS_ATTACH_AUDIT = 1ULL << 12, KDBUS_ATTACH_CONN_DESCRIPTION = 1ULL << 13, _KDBUS_ATTACH_ALL = (1ULL << 14) - 1, _KDBUS_ATTACH_ANY = ~0ULL }; /** * enum kdbus_item_type - item types to chain data in a list * @_KDBUS_ITEM_NULL: Uninitialized/invalid * @_KDBUS_ITEM_USER_BASE: Start of user items * @KDBUS_ITEM_NEGOTIATE: Negotiate supported items * @KDBUS_ITEM_PAYLOAD_VEC: Vector to data * @KDBUS_ITEM_PAYLOAD_OFF: Data at returned offset to message head * @KDBUS_ITEM_PAYLOAD_MEMFD: Data as sealed memfd * @KDBUS_ITEM_FDS: Attached file descriptors * @KDBUS_ITEM_CANCEL_FD: FD used to cancel a synchronous * operation by writing to it from * userspace * @KDBUS_ITEM_BLOOM_PARAMETER: Bus-wide bloom parameters, used with * KDBUS_CMD_BUS_MAKE, carries a * struct kdbus_bloom_parameter * @KDBUS_ITEM_BLOOM_FILTER: Bloom filter carried with a message, * used to match against a bloom mask of a * connection, carries a struct * kdbus_bloom_filter * @KDBUS_ITEM_BLOOM_MASK: Bloom mask used to match against a * message'sbloom filter * @KDBUS_ITEM_DST_NAME: Destination's well-known name * @KDBUS_ITEM_MAKE_NAME: Name of domain, bus, endpoint * @KDBUS_ITEM_ATTACH_FLAGS_SEND: Attach-flags, used for updating which * metadata a connection opts in to send * @KDBUS_ITEM_ATTACH_FLAGS_RECV: Attach-flags, used for updating which * metadata a connection requests to * receive for each reeceived message * @KDBUS_ITEM_ID: Connection ID * @KDBUS_ITEM_NAME: Well-know name with flags * @_KDBUS_ITEM_ATTACH_BASE: Start of metadata attach items * @KDBUS_ITEM_TIMESTAMP: Timestamp * @KDBUS_ITEM_CREDS: Process credentials * @KDBUS_ITEM_PIDS: Process identifiers * @KDBUS_ITEM_AUXGROUPS: Auxiliary process groups * @KDBUS_ITEM_OWNED_NAME: A name owned by the associated * connection * @KDBUS_ITEM_TID_COMM: Thread ID "comm" identifier * (Don't trust this, see below.) * @KDBUS_ITEM_PID_COMM: Process ID "comm" identifier * (Don't trust this, see below.) * @KDBUS_ITEM_EXE: The path of the executable * (Don't trust this, see below.) * @KDBUS_ITEM_CMDLINE: The process command line * (Don't trust this, see below.) * @KDBUS_ITEM_CGROUP: The croup membership * @KDBUS_ITEM_CAPS: The process capabilities * @KDBUS_ITEM_SECLABEL: The security label * @KDBUS_ITEM_AUDIT: The audit IDs * @KDBUS_ITEM_CONN_DESCRIPTION: The connection's human-readable name * (debugging) * @_KDBUS_ITEM_POLICY_BASE: Start of policy items * @KDBUS_ITEM_POLICY_ACCESS: Policy access block * @_KDBUS_ITEM_KERNEL_BASE: Start of kernel-generated message items * @KDBUS_ITEM_NAME_ADD: Notification in kdbus_notify_name_change * @KDBUS_ITEM_NAME_REMOVE: Notification in kdbus_notify_name_change * @KDBUS_ITEM_NAME_CHANGE: Notification in kdbus_notify_name_change * @KDBUS_ITEM_ID_ADD: Notification in kdbus_notify_id_change * @KDBUS_ITEM_ID_REMOVE: Notification in kdbus_notify_id_change * @KDBUS_ITEM_REPLY_TIMEOUT: Timeout has been reached * @KDBUS_ITEM_REPLY_DEAD: Destination died * * N.B: The process and thread COMM fields, as well as the CMDLINE and * EXE fields may be altered by unprivileged processes und should * hence *not* used for security decisions. Peers should make use of * these items only for informational purposes, such as generating log * records. */ enum kdbus_item_type { _KDBUS_ITEM_NULL, _KDBUS_ITEM_USER_BASE, KDBUS_ITEM_NEGOTIATE = _KDBUS_ITEM_USER_BASE, KDBUS_ITEM_PAYLOAD_VEC, KDBUS_ITEM_PAYLOAD_OFF, KDBUS_ITEM_PAYLOAD_MEMFD, KDBUS_ITEM_FDS, KDBUS_ITEM_CANCEL_FD, KDBUS_ITEM_BLOOM_PARAMETER, KDBUS_ITEM_BLOOM_FILTER, KDBUS_ITEM_BLOOM_MASK, KDBUS_ITEM_DST_NAME, KDBUS_ITEM_MAKE_NAME, KDBUS_ITEM_ATTACH_FLAGS_SEND, KDBUS_ITEM_ATTACH_FLAGS_RECV, KDBUS_ITEM_ID, KDBUS_ITEM_NAME, KDBUS_ITEM_DST_ID, /* keep these item types in sync with KDBUS_ATTACH_* flags */ _KDBUS_ITEM_ATTACH_BASE = 0x1000, KDBUS_ITEM_TIMESTAMP = _KDBUS_ITEM_ATTACH_BASE, KDBUS_ITEM_CREDS, KDBUS_ITEM_PIDS, KDBUS_ITEM_AUXGROUPS, KDBUS_ITEM_OWNED_NAME, KDBUS_ITEM_TID_COMM, KDBUS_ITEM_PID_COMM, KDBUS_ITEM_EXE, KDBUS_ITEM_CMDLINE, KDBUS_ITEM_CGROUP, KDBUS_ITEM_CAPS, KDBUS_ITEM_SECLABEL, KDBUS_ITEM_AUDIT, KDBUS_ITEM_CONN_DESCRIPTION, _KDBUS_ITEM_POLICY_BASE = 0x2000, KDBUS_ITEM_POLICY_ACCESS = _KDBUS_ITEM_POLICY_BASE, _KDBUS_ITEM_KERNEL_BASE = 0x8000, KDBUS_ITEM_NAME_ADD = _KDBUS_ITEM_KERNEL_BASE, KDBUS_ITEM_NAME_REMOVE, KDBUS_ITEM_NAME_CHANGE, KDBUS_ITEM_ID_ADD, KDBUS_ITEM_ID_REMOVE, KDBUS_ITEM_REPLY_TIMEOUT, KDBUS_ITEM_REPLY_DEAD, }; /** * struct kdbus_item - chain of data blocks * @size: Overall data record size * @type: Kdbus_item type of data * @data: Generic bytes * @data32: Generic 32 bit array * @data64: Generic 64 bit array * @str: Generic string * @id: Connection ID * @vec: KDBUS_ITEM_PAYLOAD_VEC * @creds: KDBUS_ITEM_CREDS * @audit: KDBUS_ITEM_AUDIT * @timestamp: KDBUS_ITEM_TIMESTAMP * @name: KDBUS_ITEM_NAME * @bloom_parameter: KDBUS_ITEM_BLOOM_PARAMETER * @bloom_filter: KDBUS_ITEM_BLOOM_FILTER * @memfd: KDBUS_ITEM_PAYLOAD_MEMFD * @name_change: KDBUS_ITEM_NAME_ADD * KDBUS_ITEM_NAME_REMOVE * KDBUS_ITEM_NAME_CHANGE * @id_change: KDBUS_ITEM_ID_ADD * KDBUS_ITEM_ID_REMOVE * @policy: KDBUS_ITEM_POLICY_ACCESS */ struct kdbus_item { __u64 size; __u64 type; union { __u8 data[0]; __u32 data32[0]; __u64 data64[0]; char str[0]; __u64 id; struct kdbus_vec vec; struct kdbus_creds creds; struct kdbus_pids pids; struct kdbus_audit audit; struct kdbus_caps caps; struct kdbus_timestamp timestamp; struct kdbus_name name; struct kdbus_bloom_parameter bloom_parameter; struct kdbus_bloom_filter bloom_filter; struct kdbus_memfd memfd; int fds[0]; struct kdbus_notify_name_change name_change; struct kdbus_notify_id_change id_change; struct kdbus_policy_access policy_access; }; } __attribute__((__aligned__(8))); /** * enum kdbus_msg_flags - type of message * @KDBUS_MSG_EXPECT_REPLY: Expect a reply message, used for * method calls. The userspace-supplied * cookie identifies the message and the * respective reply carries the cookie * in cookie_reply * @KDBUS_MSG_NO_AUTO_START: Do not start a service if the addressed * name is not currently active. This flag is * not looked at by the kernel but only * serves as hint for userspace implementations. * @KDBUS_MSG_SIGNAL: Treat this message as signal */ enum kdbus_msg_flags { KDBUS_MSG_EXPECT_REPLY = 1ULL << 0, KDBUS_MSG_NO_AUTO_START = 1ULL << 1, KDBUS_MSG_SIGNAL = 1ULL << 2, }; /** * enum kdbus_payload_type - type of payload carried by message * @KDBUS_PAYLOAD_KERNEL: Kernel-generated simple message * @KDBUS_PAYLOAD_DBUS: D-Bus marshalling "DBusDBus" * * Any payload-type is accepted. Common types will get added here once * established. */ enum kdbus_payload_type { KDBUS_PAYLOAD_KERNEL, KDBUS_PAYLOAD_DBUS = 0x4442757344427573ULL, }; /** * struct kdbus_msg - the representation of a kdbus message * @size: Total size of the message * @flags: Message flags (KDBUS_MSG_*), userspace → kernel * @priority: Message queue priority value * @dst_id: 64-bit ID of the destination connection * @src_id: 64-bit ID of the source connection * @payload_type: Payload type (KDBUS_PAYLOAD_*) * @cookie: Userspace-supplied cookie, for the connection * to identify its messages * @timeout_ns: The time to wait for a message reply from the peer. * If there is no reply, and the send command is * executed asynchronously, a kernel-generated message * with an attached KDBUS_ITEM_REPLY_TIMEOUT item * is sent to @src_id. For synchronously executed send * command, the value denotes the maximum time the call * blocks to wait for a reply. The timeout is expected in * nanoseconds and as absolute CLOCK_MONOTONIC value. * @cookie_reply: A reply to the requesting message with the same * cookie. The requesting connection can match its * request and the reply with this value * @items: A list of kdbus_items containing the message payload */ struct kdbus_msg { __u64 size; __u64 flags; __s64 priority; __u64 dst_id; __u64 src_id; __u64 payload_type; __u64 cookie; union { __u64 timeout_ns; __u64 cookie_reply; }; struct kdbus_item items[0]; } __attribute__((__aligned__(8))); /** * struct kdbus_msg_info - returned message container * @offset: Offset of kdbus_msg slice in pool * @msg_size: Copy of the kdbus_msg.size field * @return_flags: Command return flags, kernel → userspace */ struct kdbus_msg_info { __u64 offset; __u64 msg_size; __u64 return_flags; } __attribute__((__aligned__(8))); /** * enum kdbus_send_flags - flags for sending messages * @KDBUS_SEND_SYNC_REPLY: Wait for destination connection to * reply to this message. The * KDBUS_CMD_SEND ioctl() will block * until the reply is received, and * reply in struct kdbus_cmd_send will * yield the offset in the sender's pool * where the reply can be found. * This flag is only valid if * @KDBUS_MSG_EXPECT_REPLY is set as well. */ enum kdbus_send_flags { KDBUS_SEND_SYNC_REPLY = 1ULL << 0, }; /** * struct kdbus_cmd_send - send message * @size: Overall size of this structure * @flags: Flags to change send behavior (KDBUS_SEND_*) * @return_flags: Command return flags, kernel → userspace * @msg_address: Storage address of the kdbus_msg to send * @reply: Storage for message reply if KDBUS_SEND_SYNC_REPLY * was given * @items: Additional items for this command */ struct kdbus_cmd_send { __u64 size; __u64 flags; __u64 return_flags; __u64 msg_address; struct kdbus_msg_info reply; struct kdbus_item items[0]; } __attribute__((__aligned__(8))); /** * enum kdbus_recv_flags - flags for de-queuing messages * @KDBUS_RECV_PEEK: Return the next queued message without * actually de-queuing it, and without installing * any file descriptors or other resources. It is * usually used to determine the activating * connection of a bus name. * @KDBUS_RECV_DROP: Drop and free the next queued message and all * its resources without actually receiving it. * @KDBUS_RECV_USE_PRIORITY: Only de-queue messages with the specified or * higher priority (lowest values); if not set, * the priority value is ignored. */ enum kdbus_recv_flags { KDBUS_RECV_PEEK = 1ULL << 0, KDBUS_RECV_DROP = 1ULL << 1, KDBUS_RECV_USE_PRIORITY = 1ULL << 2, }; /** * enum kdbus_recv_return_flags - return flags for message receive commands * @KDBUS_RECV_RETURN_INCOMPLETE_FDS: One or more file descriptors could not * be installed. These descriptors in * KDBUS_ITEM_FDS will carry the value -1. * @KDBUS_RECV_RETURN_DROPPED_MSGS: There have been dropped messages since * the last time a message was received. * The 'dropped_msgs' counter contains the * number of messages dropped pool * overflows or other missed broadcasts. */ enum kdbus_recv_return_flags { KDBUS_RECV_RETURN_INCOMPLETE_FDS = 1ULL << 0, KDBUS_RECV_RETURN_DROPPED_MSGS = 1ULL << 1, }; /** * struct kdbus_cmd_recv - struct to de-queue a buffered message * @size: Overall size of this object * @flags: KDBUS_RECV_* flags, userspace → kernel * @return_flags: Command return flags, kernel → userspace * @priority: Minimum priority of the messages to de-queue. Lowest * values have the highest priority. * @dropped_msgs: In case there were any dropped messages since the last * time a message was received, this will be set to the * number of lost messages and * KDBUS_RECV_RETURN_DROPPED_MSGS will be set in * 'return_flags'. This can only happen if the ioctl * returns 0 or EAGAIN. * @msg: Return storage for received message. * @items: Additional items for this command. * * This struct is used with the KDBUS_CMD_RECV ioctl. */ struct kdbus_cmd_recv { __u64 size; __u64 flags; __u64 return_flags; __s64 priority; __u64 dropped_msgs; struct kdbus_msg_info msg; struct kdbus_item items[0]; } __attribute__((__aligned__(8))); /** * struct kdbus_cmd_free - struct to free a slice of memory in the pool * @size: Overall size of this structure * @flags: Flags for the free command, userspace → kernel * @return_flags: Command return flags, kernel → userspace * @offset: The offset of the memory slice, as returned by other * ioctls * @items: Additional items to modify the behavior * * This struct is used with the KDBUS_CMD_FREE ioctl. */ struct kdbus_cmd_free { __u64 size; __u64 flags; __u64 return_flags; __u64 offset; struct kdbus_item items[0]; } __attribute__((__aligned__(8))); /** * enum kdbus_hello_flags - flags for struct kdbus_cmd_hello * @KDBUS_HELLO_ACCEPT_FD: The connection allows the reception of * any passed file descriptors * @KDBUS_HELLO_ACTIVATOR: Special-purpose connection which registers * a well-know name for a process to be started * when traffic arrives * @KDBUS_HELLO_POLICY_HOLDER: Special-purpose connection which registers * policy entries for a name. The provided name * is not activated and not registered with the * name database, it only allows unprivileged * connections to acquire a name, talk or discover * a service * @KDBUS_HELLO_MONITOR: Special-purpose connection to monitor * bus traffic */ enum kdbus_hello_flags { KDBUS_HELLO_ACCEPT_FD = 1ULL << 0, KDBUS_HELLO_ACTIVATOR = 1ULL << 1, KDBUS_HELLO_POLICY_HOLDER = 1ULL << 2, KDBUS_HELLO_MONITOR = 1ULL << 3, }; /** * struct kdbus_cmd_hello - struct to say hello to kdbus * @size: The total size of the structure * @flags: Connection flags (KDBUS_HELLO_*), userspace → kernel * @return_flags: Command return flags, kernel → userspace * @attach_flags_send: Mask of metadata to attach to each message sent * off by this connection (KDBUS_ATTACH_*) * @attach_flags_recv: Mask of metadata to attach to each message receieved * by the new connection (KDBUS_ATTACH_*) * @bus_flags: The flags field copied verbatim from the original * KDBUS_CMD_BUS_MAKE ioctl. It's intended to be useful * to do negotiation of features of the payload that is * transferred (kernel → userspace) * @id: The ID of this connection (kernel → userspace) * @pool_size: Size of the connection's buffer where the received * messages are placed * @offset: Pool offset where items are returned to report * additional information about the bus and the newly * created connection. * @items_size: Size of buffer returned in the pool slice at @offset. * @id128: Unique 128-bit ID of the bus (kernel → userspace) * @items: A list of items * * This struct is used with the KDBUS_CMD_HELLO ioctl. */ struct kdbus_cmd_hello { __u64 size; __u64 flags; __u64 return_flags; __u64 attach_flags_send; __u64 attach_flags_recv; __u64 bus_flags; __u64 id; __u64 pool_size; __u64 offset; __u64 items_size; __u8 id128[16]; struct kdbus_item items[0]; } __attribute__((__aligned__(8))); /** * struct kdbus_info - connection information * @size: total size of the struct * @id: 64bit object ID * @flags: object creation flags * @items: list of items * * Note that the user is responsible for freeing the allocated memory with * the KDBUS_CMD_FREE ioctl. */ struct kdbus_info { __u64 size; __u64 id; __u64 flags; struct kdbus_item items[0]; } __attribute__((__aligned__(8))); /** * enum kdbus_list_flags - what to include into the returned list * @KDBUS_LIST_UNIQUE: active connections * @KDBUS_LIST_ACTIVATORS: activator connections * @KDBUS_LIST_NAMES: known well-known names * @KDBUS_LIST_QUEUED: queued-up names */ enum kdbus_list_flags { KDBUS_LIST_UNIQUE = 1ULL << 0, KDBUS_LIST_NAMES = 1ULL << 1, KDBUS_LIST_ACTIVATORS = 1ULL << 2, KDBUS_LIST_QUEUED = 1ULL << 3, }; /** * struct kdbus_cmd_list - list connections * @size: overall size of this object * @flags: flags for the query (KDBUS_LIST_*), userspace → kernel * @return_flags: command return flags, kernel → userspace * @offset: Offset in the caller's pool buffer where an array of * kdbus_info objects is stored. * The user must use KDBUS_CMD_FREE to free the * allocated memory. * @list_size: size of returned list in bytes * @items: Items for the command. Reserved for future use. * * This structure is used with the KDBUS_CMD_LIST ioctl. */ struct kdbus_cmd_list { __u64 size; __u64 flags; __u64 return_flags; __u64 offset; __u64 list_size; struct kdbus_item items[0]; } __attribute__((__aligned__(8))); /** * struct kdbus_cmd_info - struct used for KDBUS_CMD_CONN_INFO ioctl * @size: The total size of the struct * @flags: Flags for this ioctl, userspace → kernel * @return_flags: Command return flags, kernel → userspace * @id: The 64-bit ID of the connection. If set to zero, passing * @name is required. kdbus will look up the name to * determine the ID in this case. * @attach_flags: Set of attach flags to specify the set of information * to receive, userspace → kernel * @offset: Returned offset in the caller's pool buffer where the * kdbus_info struct result is stored. The user must * use KDBUS_CMD_FREE to free the allocated memory. * @info_size: Output buffer to report size of data at @offset. * @items: The optional item list, containing the * well-known name to look up as a KDBUS_ITEM_NAME. * Only needed in case @id is zero. * * On success, the KDBUS_CMD_CONN_INFO ioctl will return 0 and @offset will * tell the user the offset in the connection pool buffer at which to find the * result in a struct kdbus_info. */ struct kdbus_cmd_info { __u64 size; __u64 flags; __u64 return_flags; __u64 id; __u64 attach_flags; __u64 offset; __u64 info_size; struct kdbus_item items[0]; } __attribute__((__aligned__(8))); /** * enum kdbus_cmd_match_flags - flags to control the KDBUS_CMD_MATCH_ADD ioctl * @KDBUS_MATCH_REPLACE: If entries with the supplied cookie already * exists, remove them before installing the new * matches. */ enum kdbus_cmd_match_flags { KDBUS_MATCH_REPLACE = 1ULL << 0, }; /** * struct kdbus_cmd_match - struct to add or remove matches * @size: The total size of the struct * @flags: Flags for match command (KDBUS_MATCH_*), * userspace → kernel * @return_flags: Command return flags, kernel → userspace * @cookie: Userspace supplied cookie. When removing, the cookie * identifies the match to remove * @items: A list of items for additional information * * This structure is used with the KDBUS_CMD_MATCH_ADD and * KDBUS_CMD_MATCH_REMOVE ioctl. */ struct kdbus_cmd_match { __u64 size; __u64 flags; __u64 return_flags; __u64 cookie; struct kdbus_item items[0]; } __attribute__((__aligned__(8))); /** * enum kdbus_make_flags - Flags for KDBUS_CMD_{BUS,ENDPOINT}_MAKE * @KDBUS_MAKE_ACCESS_GROUP: Make the bus or endpoint node group-accessible * @KDBUS_MAKE_ACCESS_WORLD: Make the bus or endpoint node world-accessible */ enum kdbus_make_flags { KDBUS_MAKE_ACCESS_GROUP = 1ULL << 0, KDBUS_MAKE_ACCESS_WORLD = 1ULL << 1, }; /** * enum kdbus_name_flags - flags for KDBUS_CMD_NAME_ACQUIRE * @KDBUS_NAME_REPLACE_EXISTING: Try to replace name of other connections * @KDBUS_NAME_ALLOW_REPLACEMENT: Allow the replacement of the name * @KDBUS_NAME_QUEUE: Name should be queued if busy * @KDBUS_NAME_IN_QUEUE: Name is queued * @KDBUS_NAME_ACTIVATOR: Name is owned by a activator connection */ enum kdbus_name_flags { KDBUS_NAME_REPLACE_EXISTING = 1ULL << 0, KDBUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1, KDBUS_NAME_QUEUE = 1ULL << 2, KDBUS_NAME_IN_QUEUE = 1ULL << 3, KDBUS_NAME_ACTIVATOR = 1ULL << 4, }; /** * struct kdbus_cmd - generic ioctl payload * @size: Overall size of this structure * @flags: Flags for this ioctl, userspace → kernel * @return_flags: Ioctl return flags, kernel → userspace * @items: Additional items to modify the behavior * * This is a generic ioctl payload object. It's used by all ioctls that only * take flags and items as input. */ struct kdbus_cmd { __u64 size; __u64 flags; __u64 return_flags; struct kdbus_item items[0]; } __attribute__((__aligned__(8))); /** * Ioctl API * * KDBUS_CMD_BUS_MAKE: After opening the "control" node, this command * creates a new bus with the specified * name. The bus is immediately shut down and * cleaned up when the opened file descriptor is * closed. * * KDBUS_CMD_ENDPOINT_MAKE: Creates a new named special endpoint to talk to * the bus. Such endpoints usually carry a more * restrictive policy and grant restricted access * to specific applications. * KDBUS_CMD_ENDPOINT_UPDATE: Update the properties of a custom enpoint. Used * to update the policy. * * KDBUS_CMD_HELLO: By opening the bus node, a connection is * created. After a HELLO the opened connection * becomes an active peer on the bus. * KDBUS_CMD_UPDATE: Update the properties of a connection. Used to * update the metadata subscription mask and * policy. * KDBUS_CMD_BYEBYE: Disconnect a connection. If there are no * messages queued up in the connection's pool, * the call succeeds, and the handle is rendered * unusable. Otherwise, -EBUSY is returned without * any further side-effects. * KDBUS_CMD_FREE: Release the allocated memory in the receiver's * pool. * KDBUS_CMD_CONN_INFO: Retrieve credentials and properties of the * initial creator of the connection. The data was * stored at registration time and does not * necessarily represent the connected process or * the actual state of the process. * KDBUS_CMD_BUS_CREATOR_INFO: Retrieve information of the creator of the bus * a connection is attached to. * * KDBUS_CMD_SEND: Send a message and pass data from userspace to * the kernel. * KDBUS_CMD_RECV: Receive a message from the kernel which is * placed in the receiver's pool. * * KDBUS_CMD_NAME_ACQUIRE: Request a well-known bus name to associate with * the connection. Well-known names are used to * address a peer on the bus. * KDBUS_CMD_NAME_RELEASE: Release a well-known name the connection * currently owns. * KDBUS_CMD_LIST: Retrieve the list of all currently registered * well-known and unique names. * * KDBUS_CMD_MATCH_ADD: Install a match which broadcast messages should * be delivered to the connection. * KDBUS_CMD_MATCH_REMOVE: Remove a current match for broadcast messages. */ enum kdbus_ioctl_type { /* bus owner (00-0f) */ KDBUS_CMD_BUS_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x00, struct kdbus_cmd), /* endpoint owner (10-1f) */ KDBUS_CMD_ENDPOINT_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x10, struct kdbus_cmd), KDBUS_CMD_ENDPOINT_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x11, struct kdbus_cmd), /* connection owner (80-ff) */ KDBUS_CMD_HELLO = _IOWR(KDBUS_IOCTL_MAGIC, 0x80, struct kdbus_cmd_hello), KDBUS_CMD_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x81, struct kdbus_cmd), KDBUS_CMD_BYEBYE = _IOW(KDBUS_IOCTL_MAGIC, 0x82, struct kdbus_cmd), KDBUS_CMD_FREE = _IOW(KDBUS_IOCTL_MAGIC, 0x83, struct kdbus_cmd_free), KDBUS_CMD_CONN_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x84, struct kdbus_cmd_info), KDBUS_CMD_BUS_CREATOR_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x85, struct kdbus_cmd_info), KDBUS_CMD_LIST = _IOR(KDBUS_IOCTL_MAGIC, 0x86, struct kdbus_cmd_list), KDBUS_CMD_SEND = _IOW(KDBUS_IOCTL_MAGIC, 0x90, struct kdbus_cmd_send), KDBUS_CMD_RECV = _IOR(KDBUS_IOCTL_MAGIC, 0x91, struct kdbus_cmd_recv), KDBUS_CMD_NAME_ACQUIRE = _IOW(KDBUS_IOCTL_MAGIC, 0xa0, struct kdbus_cmd), KDBUS_CMD_NAME_RELEASE = _IOW(KDBUS_IOCTL_MAGIC, 0xa1, struct kdbus_cmd), KDBUS_CMD_MATCH_ADD = _IOW(KDBUS_IOCTL_MAGIC, 0xb0, struct kdbus_cmd_match), KDBUS_CMD_MATCH_REMOVE = _IOW(KDBUS_IOCTL_MAGIC, 0xb1, struct kdbus_cmd_match), }; #endif /* _UAPI_KDBUS_H_ */ systemd-229/src/libsystemd/sd-bus/sd-bus.c000066400000000000000000003305121265713322000205710ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-container.h" #include "bus-control.h" #include "bus-internal.h" #include "bus-kernel.h" #include "bus-label.h" #include "bus-message.h" #include "bus-objects.h" #include "bus-protocol.h" #include "bus-slot.h" #include "bus-socket.h" #include "bus-track.h" #include "bus-type.h" #include "bus-util.h" #include "cgroup-util.h" #include "def.h" #include "fd-util.h" #include "hexdecoct.h" #include "hostname-util.h" #include "macro.h" #include "missing.h" #include "parse-util.h" #include "string-util.h" #include "strv.h" #include "util.h" #define log_debug_bus_message(m) \ do { \ sd_bus_message *_mm = (m); \ log_debug("Got message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error=%s", \ bus_message_type_to_string(_mm->header->type), \ strna(sd_bus_message_get_sender(_mm)), \ strna(sd_bus_message_get_destination(_mm)), \ strna(sd_bus_message_get_path(_mm)), \ strna(sd_bus_message_get_interface(_mm)), \ strna(sd_bus_message_get_member(_mm)), \ BUS_MESSAGE_COOKIE(_mm), \ _mm->reply_cookie, \ strna(_mm->error.message)); \ } while (false) static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec); static int attach_io_events(sd_bus *b); static void detach_io_events(sd_bus *b); static thread_local sd_bus *default_system_bus = NULL; static thread_local sd_bus *default_user_bus = NULL; static thread_local sd_bus *default_starter_bus = NULL; static void bus_close_fds(sd_bus *b) { assert(b); detach_io_events(b); if (b->input_fd != b->output_fd) safe_close(b->output_fd); b->output_fd = b->input_fd = safe_close(b->input_fd); } static void bus_reset_queues(sd_bus *b) { assert(b); while (b->rqueue_size > 0) sd_bus_message_unref(b->rqueue[--b->rqueue_size]); b->rqueue = mfree(b->rqueue); b->rqueue_allocated = 0; while (b->wqueue_size > 0) sd_bus_message_unref(b->wqueue[--b->wqueue_size]); b->wqueue = mfree(b->wqueue); b->wqueue_allocated = 0; } static void bus_free(sd_bus *b) { sd_bus_slot *s; assert(b); assert(!b->track_queue); b->state = BUS_CLOSED; sd_bus_detach_event(b); while ((s = b->slots)) { /* At this point only floating slots can still be * around, because the non-floating ones keep a * reference to the bus, and we thus couldn't be * destructing right now... We forcibly disconnect the * slots here, so that they still can be referenced by * apps, but are dead. */ assert(s->floating); bus_slot_disconnect(s); sd_bus_slot_unref(s); } if (b->default_bus_ptr) *b->default_bus_ptr = NULL; bus_close_fds(b); if (b->kdbus_buffer) munmap(b->kdbus_buffer, KDBUS_POOL_SIZE); free(b->label); free(b->rbuffer); free(b->unique_name); free(b->auth_buffer); free(b->address); free(b->kernel); free(b->machine); free(b->fake_label); free(b->cgroup_root); free(b->description); free(b->exec_path); strv_free(b->exec_argv); close_many(b->fds, b->n_fds); free(b->fds); bus_reset_queues(b); ordered_hashmap_free_free(b->reply_callbacks); prioq_free(b->reply_callbacks_prioq); assert(b->match_callbacks.type == BUS_MATCH_ROOT); bus_match_free(&b->match_callbacks); hashmap_free_free(b->vtable_methods); hashmap_free_free(b->vtable_properties); assert(hashmap_isempty(b->nodes)); hashmap_free(b->nodes); bus_kernel_flush_memfd(b); assert_se(pthread_mutex_destroy(&b->memfd_cache_mutex) == 0); free(b); } _public_ int sd_bus_new(sd_bus **ret) { sd_bus *r; assert_return(ret, -EINVAL); r = new0(sd_bus, 1); if (!r) return -ENOMEM; r->n_ref = REFCNT_INIT; r->input_fd = r->output_fd = -1; r->message_version = 1; r->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME; r->hello_flags |= KDBUS_HELLO_ACCEPT_FD; r->attach_flags |= KDBUS_ATTACH_NAMES; r->original_pid = getpid(); assert_se(pthread_mutex_init(&r->memfd_cache_mutex, NULL) == 0); /* We guarantee that wqueue always has space for at least one * entry */ if (!GREEDY_REALLOC(r->wqueue, r->wqueue_allocated, 1)) { free(r); return -ENOMEM; } *ret = r; return 0; } _public_ int sd_bus_set_address(sd_bus *bus, const char *address) { char *a; assert_return(bus, -EINVAL); assert_return(bus->state == BUS_UNSET, -EPERM); assert_return(address, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); a = strdup(address); if (!a) return -ENOMEM; free(bus->address); bus->address = a; return 0; } _public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) { assert_return(bus, -EINVAL); assert_return(bus->state == BUS_UNSET, -EPERM); assert_return(input_fd >= 0, -EBADF); assert_return(output_fd >= 0, -EBADF); assert_return(!bus_pid_changed(bus), -ECHILD); bus->input_fd = input_fd; bus->output_fd = output_fd; return 0; } _public_ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) { char *p, **a; assert_return(bus, -EINVAL); assert_return(bus->state == BUS_UNSET, -EPERM); assert_return(path, -EINVAL); assert_return(!strv_isempty(argv), -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); p = strdup(path); if (!p) return -ENOMEM; a = strv_copy(argv); if (!a) { free(p); return -ENOMEM; } free(bus->exec_path); strv_free(bus->exec_argv); bus->exec_path = p; bus->exec_argv = a; return 0; } _public_ int sd_bus_set_bus_client(sd_bus *bus, int b) { assert_return(bus, -EINVAL); assert_return(bus->state == BUS_UNSET, -EPERM); assert_return(!bus_pid_changed(bus), -ECHILD); bus->bus_client = !!b; return 0; } _public_ int sd_bus_set_monitor(sd_bus *bus, int b) { assert_return(bus, -EINVAL); assert_return(bus->state == BUS_UNSET, -EPERM); assert_return(!bus_pid_changed(bus), -ECHILD); SET_FLAG(bus->hello_flags, KDBUS_HELLO_MONITOR, b); return 0; } _public_ int sd_bus_negotiate_fds(sd_bus *bus, int b) { assert_return(bus, -EINVAL); assert_return(bus->state == BUS_UNSET, -EPERM); assert_return(!bus_pid_changed(bus), -ECHILD); SET_FLAG(bus->hello_flags, KDBUS_HELLO_ACCEPT_FD, b); return 0; } _public_ int sd_bus_negotiate_timestamp(sd_bus *bus, int b) { uint64_t new_flags; assert_return(bus, -EINVAL); assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM); assert_return(!bus_pid_changed(bus), -ECHILD); new_flags = bus->attach_flags; SET_FLAG(new_flags, KDBUS_ATTACH_TIMESTAMP, b); if (bus->attach_flags == new_flags) return 0; bus->attach_flags = new_flags; if (bus->state != BUS_UNSET && bus->is_kernel) bus_kernel_realize_attach_flags(bus); return 0; } _public_ int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t mask) { uint64_t new_flags; assert_return(bus, -EINVAL); assert_return(mask <= _SD_BUS_CREDS_ALL, -EINVAL); assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM); assert_return(!bus_pid_changed(bus), -ECHILD); if (b) bus->creds_mask |= mask; else bus->creds_mask &= ~mask; /* The well knowns we need unconditionally, so that matches can work */ bus->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME; /* Make sure we don't lose the timestamp flag */ new_flags = (bus->attach_flags & KDBUS_ATTACH_TIMESTAMP) | attach_flags_to_kdbus(bus->creds_mask); if (bus->attach_flags == new_flags) return 0; bus->attach_flags = new_flags; if (bus->state != BUS_UNSET && bus->is_kernel) bus_kernel_realize_attach_flags(bus); return 0; } _public_ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) { assert_return(bus, -EINVAL); assert_return(b || sd_id128_equal(server_id, SD_ID128_NULL), -EINVAL); assert_return(bus->state == BUS_UNSET, -EPERM); assert_return(!bus_pid_changed(bus), -ECHILD); bus->is_server = !!b; bus->server_id = server_id; return 0; } _public_ int sd_bus_set_anonymous(sd_bus *bus, int b) { assert_return(bus, -EINVAL); assert_return(bus->state == BUS_UNSET, -EPERM); assert_return(!bus_pid_changed(bus), -ECHILD); bus->anonymous_auth = !!b; return 0; } _public_ int sd_bus_set_trusted(sd_bus *bus, int b) { assert_return(bus, -EINVAL); assert_return(bus->state == BUS_UNSET, -EPERM); assert_return(!bus_pid_changed(bus), -ECHILD); bus->trusted = !!b; return 0; } _public_ int sd_bus_set_description(sd_bus *bus, const char *description) { assert_return(bus, -EINVAL); assert_return(bus->state == BUS_UNSET, -EPERM); assert_return(!bus_pid_changed(bus), -ECHILD); return free_and_strdup(&bus->description, description); } _public_ int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); bus->allow_interactive_authorization = !!b; return 0; } _public_ int sd_bus_get_allow_interactive_authorization(sd_bus *bus) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); return bus->allow_interactive_authorization; } static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) { const char *s; sd_bus *bus; int r; assert(reply); bus = reply->bus; assert(bus); assert(bus->state == BUS_HELLO || bus->state == BUS_CLOSING); r = sd_bus_message_get_errno(reply); if (r > 0) return -r; r = sd_bus_message_read(reply, "s", &s); if (r < 0) return r; if (!service_name_is_valid(s) || s[0] != ':') return -EBADMSG; bus->unique_name = strdup(s); if (!bus->unique_name) return -ENOMEM; if (bus->state == BUS_HELLO) bus->state = BUS_RUNNING; return 1; } static int bus_send_hello(sd_bus *bus) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; int r; assert(bus); if (!bus->bus_client || bus->is_kernel) return 0; r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "Hello"); if (r < 0) return r; return sd_bus_call_async(bus, NULL, m, hello_callback, NULL, 0); } int bus_start_running(sd_bus *bus) { assert(bus); if (bus->bus_client && !bus->is_kernel) { bus->state = BUS_HELLO; return 1; } bus->state = BUS_RUNNING; return 1; } static int parse_address_key(const char **p, const char *key, char **value) { size_t l, n = 0, allocated = 0; const char *a; char *r = NULL; assert(p); assert(*p); assert(value); if (key) { l = strlen(key); if (strncmp(*p, key, l) != 0) return 0; if ((*p)[l] != '=') return 0; if (*value) return -EINVAL; a = *p + l + 1; } else a = *p; while (*a != ';' && *a != ',' && *a != 0) { char c; if (*a == '%') { int x, y; x = unhexchar(a[1]); if (x < 0) { free(r); return x; } y = unhexchar(a[2]); if (y < 0) { free(r); return y; } c = (char) ((x << 4) | y); a += 3; } else { c = *a; a++; } if (!GREEDY_REALLOC(r, allocated, n + 2)) return -ENOMEM; r[n++] = c; } if (!r) { r = strdup(""); if (!r) return -ENOMEM; } else r[n] = 0; if (*a == ',') a++; *p = a; free(*value); *value = r; return 1; } static void skip_address_key(const char **p) { assert(p); assert(*p); *p += strcspn(*p, ","); if (**p == ',') (*p) ++; } static int parse_unix_address(sd_bus *b, const char **p, char **guid) { _cleanup_free_ char *path = NULL, *abstract = NULL; size_t l; int r; assert(b); assert(p); assert(*p); assert(guid); while (**p != 0 && **p != ';') { r = parse_address_key(p, "guid", guid); if (r < 0) return r; else if (r > 0) continue; r = parse_address_key(p, "path", &path); if (r < 0) return r; else if (r > 0) continue; r = parse_address_key(p, "abstract", &abstract); if (r < 0) return r; else if (r > 0) continue; skip_address_key(p); } if (!path && !abstract) return -EINVAL; if (path && abstract) return -EINVAL; if (path) { l = strlen(path); if (l > sizeof(b->sockaddr.un.sun_path)) return -E2BIG; b->sockaddr.un.sun_family = AF_UNIX; strncpy(b->sockaddr.un.sun_path, path, sizeof(b->sockaddr.un.sun_path)); b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l; } else if (abstract) { l = strlen(abstract); if (l > sizeof(b->sockaddr.un.sun_path) - 1) return -E2BIG; b->sockaddr.un.sun_family = AF_UNIX; b->sockaddr.un.sun_path[0] = 0; strncpy(b->sockaddr.un.sun_path+1, abstract, sizeof(b->sockaddr.un.sun_path)-1); b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + 1 + l; } return 0; } static int parse_tcp_address(sd_bus *b, const char **p, char **guid) { _cleanup_free_ char *host = NULL, *port = NULL, *family = NULL; int r; struct addrinfo *result, hints = { .ai_socktype = SOCK_STREAM, .ai_flags = AI_ADDRCONFIG, }; assert(b); assert(p); assert(*p); assert(guid); while (**p != 0 && **p != ';') { r = parse_address_key(p, "guid", guid); if (r < 0) return r; else if (r > 0) continue; r = parse_address_key(p, "host", &host); if (r < 0) return r; else if (r > 0) continue; r = parse_address_key(p, "port", &port); if (r < 0) return r; else if (r > 0) continue; r = parse_address_key(p, "family", &family); if (r < 0) return r; else if (r > 0) continue; skip_address_key(p); } if (!host || !port) return -EINVAL; if (family) { if (streq(family, "ipv4")) hints.ai_family = AF_INET; else if (streq(family, "ipv6")) hints.ai_family = AF_INET6; else return -EINVAL; } r = getaddrinfo(host, port, &hints, &result); if (r == EAI_SYSTEM) return -errno; else if (r != 0) return -EADDRNOTAVAIL; memcpy(&b->sockaddr, result->ai_addr, result->ai_addrlen); b->sockaddr_size = result->ai_addrlen; freeaddrinfo(result); return 0; } static int parse_exec_address(sd_bus *b, const char **p, char **guid) { char *path = NULL; unsigned n_argv = 0, j; char **argv = NULL; size_t allocated = 0; int r; assert(b); assert(p); assert(*p); assert(guid); while (**p != 0 && **p != ';') { r = parse_address_key(p, "guid", guid); if (r < 0) goto fail; else if (r > 0) continue; r = parse_address_key(p, "path", &path); if (r < 0) goto fail; else if (r > 0) continue; if (startswith(*p, "argv")) { unsigned ul; errno = 0; ul = strtoul(*p + 4, (char**) p, 10); if (errno > 0 || **p != '=' || ul > 256) { r = -EINVAL; goto fail; } (*p) ++; if (ul >= n_argv) { if (!GREEDY_REALLOC0(argv, allocated, ul + 2)) { r = -ENOMEM; goto fail; } n_argv = ul + 1; } r = parse_address_key(p, NULL, argv + ul); if (r < 0) goto fail; continue; } skip_address_key(p); } if (!path) { r = -EINVAL; goto fail; } /* Make sure there are no holes in the array, with the * exception of argv[0] */ for (j = 1; j < n_argv; j++) if (!argv[j]) { r = -EINVAL; goto fail; } if (argv && argv[0] == NULL) { argv[0] = strdup(path); if (!argv[0]) { r = -ENOMEM; goto fail; } } b->exec_path = path; b->exec_argv = argv; return 0; fail: for (j = 0; j < n_argv; j++) free(argv[j]); free(argv); free(path); return r; } static int parse_kernel_address(sd_bus *b, const char **p, char **guid) { _cleanup_free_ char *path = NULL; int r; assert(b); assert(p); assert(*p); assert(guid); while (**p != 0 && **p != ';') { r = parse_address_key(p, "guid", guid); if (r < 0) return r; else if (r > 0) continue; r = parse_address_key(p, "path", &path); if (r < 0) return r; else if (r > 0) continue; skip_address_key(p); } if (!path) return -EINVAL; free(b->kernel); b->kernel = path; path = NULL; return 0; } static int parse_container_unix_address(sd_bus *b, const char **p, char **guid) { _cleanup_free_ char *machine = NULL, *pid = NULL; int r; assert(b); assert(p); assert(*p); assert(guid); while (**p != 0 && **p != ';') { r = parse_address_key(p, "guid", guid); if (r < 0) return r; else if (r > 0) continue; r = parse_address_key(p, "machine", &machine); if (r < 0) return r; else if (r > 0) continue; r = parse_address_key(p, "pid", &pid); if (r < 0) return r; else if (r > 0) continue; skip_address_key(p); } if (!machine == !pid) return -EINVAL; if (machine) { if (!machine_name_is_valid(machine)) return -EINVAL; free(b->machine); b->machine = machine; machine = NULL; } else { b->machine = mfree(b->machine); } if (pid) { r = parse_pid(pid, &b->nspid); if (r < 0) return r; } else b->nspid = 0; b->sockaddr.un.sun_family = AF_UNIX; strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path)); b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + strlen("/var/run/dbus/system_bus_socket"); return 0; } static int parse_container_kernel_address(sd_bus *b, const char **p, char **guid) { _cleanup_free_ char *machine = NULL, *pid = NULL; int r; assert(b); assert(p); assert(*p); assert(guid); while (**p != 0 && **p != ';') { r = parse_address_key(p, "guid", guid); if (r < 0) return r; else if (r > 0) continue; r = parse_address_key(p, "machine", &machine); if (r < 0) return r; else if (r > 0) continue; r = parse_address_key(p, "pid", &pid); if (r < 0) return r; else if (r > 0) continue; skip_address_key(p); } if (!machine == !pid) return -EINVAL; if (machine) { if (!machine_name_is_valid(machine)) return -EINVAL; free(b->machine); b->machine = machine; machine = NULL; } else { b->machine = mfree(b->machine); } if (pid) { r = parse_pid(pid, &b->nspid); if (r < 0) return r; } else b->nspid = 0; r = free_and_strdup(&b->kernel, "/sys/fs/kdbus/0-system/bus"); if (r < 0) return r; return 0; } static void bus_reset_parsed_address(sd_bus *b) { assert(b); zero(b->sockaddr); b->sockaddr_size = 0; b->exec_argv = strv_free(b->exec_argv); b->exec_path = mfree(b->exec_path); b->server_id = SD_ID128_NULL; b->kernel = mfree(b->kernel); b->machine = mfree(b->machine); b->nspid = 0; } static int bus_parse_next_address(sd_bus *b) { _cleanup_free_ char *guid = NULL; const char *a; int r; assert(b); if (!b->address) return 0; if (b->address[b->address_index] == 0) return 0; bus_reset_parsed_address(b); a = b->address + b->address_index; while (*a != 0) { if (*a == ';') { a++; continue; } if (startswith(a, "unix:")) { a += 5; r = parse_unix_address(b, &a, &guid); if (r < 0) return r; break; } else if (startswith(a, "tcp:")) { a += 4; r = parse_tcp_address(b, &a, &guid); if (r < 0) return r; break; } else if (startswith(a, "unixexec:")) { a += 9; r = parse_exec_address(b, &a, &guid); if (r < 0) return r; break; } else if (startswith(a, "kernel:")) { a += 7; r = parse_kernel_address(b, &a, &guid); if (r < 0) return r; break; } else if (startswith(a, "x-machine-unix:")) { a += 15; r = parse_container_unix_address(b, &a, &guid); if (r < 0) return r; break; } else if (startswith(a, "x-machine-kernel:")) { a += 17; r = parse_container_kernel_address(b, &a, &guid); if (r < 0) return r; break; } a = strchr(a, ';'); if (!a) return 0; } if (guid) { r = sd_id128_from_string(guid, &b->server_id); if (r < 0) return r; } b->address_index = a - b->address; return 1; } static int bus_start_address(sd_bus *b) { bool container_kdbus_available = false; bool kdbus_available = false; int r; assert(b); for (;;) { bool skipped = false; bus_close_fds(b); /* * Usually, if you provide multiple different bus-addresses, we * try all of them in order. We use the first one that * succeeds. However, if you mix kernel and unix addresses, we * never try unix-addresses if a previous kernel address was * tried and kdbus was available. This is required to prevent * clients to fallback to the bus-proxy if kdbus is available * but failed (eg., too many connections). */ if (b->exec_path) r = bus_socket_exec(b); else if ((b->nspid > 0 || b->machine) && b->kernel) { r = bus_container_connect_kernel(b); if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT)) container_kdbus_available = true; } else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC) { if (!container_kdbus_available) r = bus_container_connect_socket(b); else skipped = true; } else if (b->kernel) { r = bus_kernel_connect(b); if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT)) kdbus_available = true; } else if (b->sockaddr.sa.sa_family != AF_UNSPEC) { if (!kdbus_available) r = bus_socket_connect(b); else skipped = true; } else skipped = true; if (!skipped) { if (r >= 0) { r = attach_io_events(b); if (r >= 0) return r; } b->last_connect_error = -r; } r = bus_parse_next_address(b); if (r < 0) return r; if (r == 0) return b->last_connect_error ? -b->last_connect_error : -ECONNREFUSED; } } int bus_next_address(sd_bus *b) { assert(b); bus_reset_parsed_address(b); return bus_start_address(b); } static int bus_start_fd(sd_bus *b) { struct stat st; int r; assert(b); assert(b->input_fd >= 0); assert(b->output_fd >= 0); r = fd_nonblock(b->input_fd, true); if (r < 0) return r; r = fd_cloexec(b->input_fd, true); if (r < 0) return r; if (b->input_fd != b->output_fd) { r = fd_nonblock(b->output_fd, true); if (r < 0) return r; r = fd_cloexec(b->output_fd, true); if (r < 0) return r; } if (fstat(b->input_fd, &st) < 0) return -errno; if (S_ISCHR(b->input_fd)) return bus_kernel_take_fd(b); else return bus_socket_take_fd(b); } _public_ int sd_bus_start(sd_bus *bus) { int r; assert_return(bus, -EINVAL); assert_return(bus->state == BUS_UNSET, -EPERM); assert_return(!bus_pid_changed(bus), -ECHILD); bus->state = BUS_OPENING; if (bus->is_server && bus->bus_client) return -EINVAL; if (bus->input_fd >= 0) r = bus_start_fd(bus); else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel || bus->machine) r = bus_start_address(bus); else return -EINVAL; if (r < 0) { sd_bus_close(bus); return r; } return bus_send_hello(bus); } _public_ int sd_bus_open(sd_bus **ret) { const char *e; sd_bus *b; int r; assert_return(ret, -EINVAL); /* Let's connect to the starter bus if it is set, and * otherwise to the bus that is appropropriate for the scope * we are running in */ e = secure_getenv("DBUS_STARTER_BUS_TYPE"); if (e) { if (streq(e, "system")) return sd_bus_open_system(ret); else if (STR_IN_SET(e, "session", "user")) return sd_bus_open_user(ret); } e = secure_getenv("DBUS_STARTER_ADDRESS"); if (!e) { if (cg_pid_get_owner_uid(0, NULL) >= 0) return sd_bus_open_user(ret); else return sd_bus_open_system(ret); } r = sd_bus_new(&b); if (r < 0) return r; r = sd_bus_set_address(b, e); if (r < 0) goto fail; b->bus_client = true; /* We don't know whether the bus is trusted or not, so better * be safe, and authenticate everything */ b->trusted = false; b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS; b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS; r = sd_bus_start(b); if (r < 0) goto fail; *ret = b; return 0; fail: bus_free(b); return r; } int bus_set_address_system(sd_bus *b) { const char *e; assert(b); e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS"); if (e) return sd_bus_set_address(b, e); return sd_bus_set_address(b, DEFAULT_SYSTEM_BUS_ADDRESS); } _public_ int sd_bus_open_system(sd_bus **ret) { sd_bus *b; int r; assert_return(ret, -EINVAL); r = sd_bus_new(&b); if (r < 0) return r; r = bus_set_address_system(b); if (r < 0) goto fail; b->bus_client = true; b->is_system = true; /* Let's do per-method access control on the system bus. We * need the caller's UID and capability set for that. */ b->trusted = false; b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS; b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS; r = sd_bus_start(b); if (r < 0) goto fail; *ret = b; return 0; fail: bus_free(b); return r; } int bus_set_address_user(sd_bus *b) { const char *e; uid_t uid; int r; assert(b); e = secure_getenv("DBUS_SESSION_BUS_ADDRESS"); if (e) return sd_bus_set_address(b, e); r = cg_pid_get_owner_uid(0, &uid); if (r < 0) uid = getuid(); e = secure_getenv("XDG_RUNTIME_DIR"); if (e) { _cleanup_free_ char *ee = NULL; ee = bus_address_escape(e); if (!ee) return -ENOMEM; (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT, uid, ee); } else (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT, uid); if (!b->address) return -ENOMEM; return 0; } _public_ int sd_bus_open_user(sd_bus **ret) { sd_bus *b; int r; assert_return(ret, -EINVAL); r = sd_bus_new(&b); if (r < 0) return r; r = bus_set_address_user(b); if (r < 0) return r; b->bus_client = true; b->is_user = true; /* We don't do any per-method access control on the user * bus. */ b->trusted = true; r = sd_bus_start(b); if (r < 0) goto fail; *ret = b; return 0; fail: bus_free(b); return r; } int bus_set_address_system_remote(sd_bus *b, const char *host) { _cleanup_free_ char *e = NULL; char *m = NULL, *c = NULL; assert(b); assert(host); /* Let's see if we shall enter some container */ m = strchr(host, ':'); if (m) { m++; /* Let's make sure this is not a port of some kind, * and is a valid machine name. */ if (!in_charset(m, "0123456789") && machine_name_is_valid(m)) { char *t; /* Cut out the host part */ t = strndupa(host, m - host - 1); e = bus_address_escape(t); if (!e) return -ENOMEM; c = strjoina(",argv4=--machine=", m); } } if (!e) { e = bus_address_escape(host); if (!e) return -ENOMEM; } b->address = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", c, NULL); if (!b->address) return -ENOMEM; return 0; } _public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) { sd_bus *bus; int r; assert_return(host, -EINVAL); assert_return(ret, -EINVAL); r = sd_bus_new(&bus); if (r < 0) return r; r = bus_set_address_system_remote(bus, host); if (r < 0) goto fail; bus->bus_client = true; bus->trusted = false; bus->is_system = true; r = sd_bus_start(bus); if (r < 0) goto fail; *ret = bus; return 0; fail: bus_free(bus); return r; } int bus_set_address_system_machine(sd_bus *b, const char *machine) { _cleanup_free_ char *e = NULL; assert(b); assert(machine); e = bus_address_escape(machine); if (!e) return -ENOMEM; b->address = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL); if (!b->address) return -ENOMEM; return 0; } _public_ int sd_bus_open_system_machine(sd_bus **ret, const char *machine) { sd_bus *bus; int r; assert_return(machine, -EINVAL); assert_return(ret, -EINVAL); assert_return(machine_name_is_valid(machine), -EINVAL); r = sd_bus_new(&bus); if (r < 0) return r; r = bus_set_address_system_machine(bus, machine); if (r < 0) goto fail; bus->bus_client = true; bus->trusted = false; bus->is_system = true; r = sd_bus_start(bus); if (r < 0) goto fail; *ret = bus; return 0; fail: bus_free(bus); return r; } _public_ void sd_bus_close(sd_bus *bus) { if (!bus) return; if (bus->state == BUS_CLOSED) return; if (bus_pid_changed(bus)) return; bus->state = BUS_CLOSED; sd_bus_detach_event(bus); /* Drop all queued messages so that they drop references to * the bus object and the bus may be freed */ bus_reset_queues(bus); if (!bus->is_kernel) bus_close_fds(bus); /* We'll leave the fd open in case this is a kernel bus, since * there might still be memblocks around that reference this * bus, and they might need to invoke the KDBUS_CMD_FREE * ioctl on the fd when they are freed. */ } _public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) { if (!bus) return NULL; sd_bus_flush(bus); sd_bus_close(bus); return sd_bus_unref(bus); } static void bus_enter_closing(sd_bus *bus) { assert(bus); if (bus->state != BUS_OPENING && bus->state != BUS_AUTHENTICATING && bus->state != BUS_HELLO && bus->state != BUS_RUNNING) return; bus->state = BUS_CLOSING; } _public_ sd_bus *sd_bus_ref(sd_bus *bus) { if (!bus) return NULL; assert_se(REFCNT_INC(bus->n_ref) >= 2); return bus; } _public_ sd_bus *sd_bus_unref(sd_bus *bus) { unsigned i; if (!bus) return NULL; i = REFCNT_DEC(bus->n_ref); if (i > 0) return NULL; bus_free(bus); return NULL; } _public_ int sd_bus_is_open(sd_bus *bus) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); return BUS_IS_OPEN(bus->state); } _public_ int sd_bus_can_send(sd_bus *bus, char type) { int r; assert_return(bus, -EINVAL); assert_return(bus->state != BUS_UNSET, -ENOTCONN); assert_return(!bus_pid_changed(bus), -ECHILD); if (bus->hello_flags & KDBUS_HELLO_MONITOR) return 0; if (type == SD_BUS_TYPE_UNIX_FD) { if (!(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)) return 0; r = bus_ensure_running(bus); if (r < 0) return r; return bus->can_fds; } return bus_type_is_valid(type); } _public_ int sd_bus_get_bus_id(sd_bus *bus, sd_id128_t *id) { int r; assert_return(bus, -EINVAL); assert_return(id, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); r = bus_ensure_running(bus); if (r < 0) return r; *id = bus->server_id; return 0; } static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) { assert(b); assert(m); if (m->sealed) { /* If we copy the same message to multiple * destinations, avoid using the same cookie * numbers. */ b->cookie = MAX(b->cookie, BUS_MESSAGE_COOKIE(m)); return 0; } if (timeout == 0) timeout = BUS_DEFAULT_TIMEOUT; return bus_message_seal(m, ++b->cookie, timeout); } static int bus_remarshal_message(sd_bus *b, sd_bus_message **m) { bool remarshal = false; assert(b); /* wrong packet version */ if (b->message_version != 0 && b->message_version != (*m)->header->version) remarshal = true; /* wrong packet endianness */ if (b->message_endian != 0 && b->message_endian != (*m)->header->endian) remarshal = true; /* TODO: kdbus-messages received from the kernel contain data which is * not allowed to be passed to KDBUS_CMD_SEND. Therefore, we have to * force remarshaling of the message. Technically, we could just * recreate the kdbus message, but that is non-trivial as other parts of * the message refer to m->kdbus already. This should be fixed! */ if ((*m)->kdbus && (*m)->release_kdbus) remarshal = true; return remarshal ? bus_message_remarshal(b, m) : 0; } int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) { assert(b); assert(m); /* Fake some timestamps, if they were requested, and not * already initialized */ if (b->attach_flags & KDBUS_ATTACH_TIMESTAMP) { if (m->realtime <= 0) m->realtime = now(CLOCK_REALTIME); if (m->monotonic <= 0) m->monotonic = now(CLOCK_MONOTONIC); } /* The bus specification says the serial number cannot be 0, * hence let's fill something in for synthetic messages. Since * synthetic messages might have a fake sender and we don't * want to interfere with the real sender's serial numbers we * pick a fixed, artificial one. We use (uint32_t) -1 rather * than (uint64_t) -1 since dbus1 only had 32bit identifiers, * even though kdbus can do 64bit. */ return bus_message_seal(m, 0xFFFFFFFFULL, 0); } static int bus_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call, size_t *idx) { int r; assert(bus); assert(m); if (bus->is_kernel) r = bus_kernel_write_message(bus, m, hint_sync_call); else r = bus_socket_write_message(bus, m, idx); if (r <= 0) return r; if (bus->is_kernel || *idx >= BUS_MESSAGE_SIZE(m)) log_debug("Sent message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error=%s", bus_message_type_to_string(m->header->type), strna(sd_bus_message_get_sender(m)), strna(sd_bus_message_get_destination(m)), strna(sd_bus_message_get_path(m)), strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m)), BUS_MESSAGE_COOKIE(m), m->reply_cookie, strna(m->error.message)); return r; } static int dispatch_wqueue(sd_bus *bus) { int r, ret = 0; assert(bus); assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO); while (bus->wqueue_size > 0) { r = bus_write_message(bus, bus->wqueue[0], false, &bus->windex); if (r < 0) return r; else if (r == 0) /* Didn't do anything this time */ return ret; else if (bus->is_kernel || bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) { /* Fully written. Let's drop the entry from * the queue. * * This isn't particularly optimized, but * well, this is supposed to be our worst-case * buffer only, and the socket buffer is * supposed to be our primary buffer, and if * it got full, then all bets are off * anyway. */ bus->wqueue_size --; sd_bus_message_unref(bus->wqueue[0]); memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size); bus->windex = 0; ret = 1; } } return ret; } static int bus_read_message(sd_bus *bus, bool hint_priority, int64_t priority) { assert(bus); if (bus->is_kernel) return bus_kernel_read_message(bus, hint_priority, priority); else return bus_socket_read_message(bus); } int bus_rqueue_make_room(sd_bus *bus) { assert(bus); if (bus->rqueue_size >= BUS_RQUEUE_MAX) return -ENOBUFS; if (!GREEDY_REALLOC(bus->rqueue, bus->rqueue_allocated, bus->rqueue_size + 1)) return -ENOMEM; return 0; } static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **m) { int r, ret = 0; assert(bus); assert(m); assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO); /* Note that the priority logic is only available on kdbus, * where the rqueue is unused. We check the rqueue here * anyway, because it's simple... */ for (;;) { if (bus->rqueue_size > 0) { /* Dispatch a queued message */ *m = bus->rqueue[0]; bus->rqueue_size --; memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size); return 1; } /* Try to read a new message */ r = bus_read_message(bus, hint_priority, priority); if (r < 0) return r; if (r == 0) return ret; ret = 1; } } static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie, bool hint_sync_call) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m); int r; assert_return(m, -EINVAL); if (!bus) bus = m->bus; assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; if (m->n_fds > 0) { r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD); if (r < 0) return r; if (r == 0) return -EOPNOTSUPP; } /* If the cookie number isn't kept, then we know that no reply * is expected */ if (!cookie && !m->sealed) m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; r = bus_seal_message(bus, m, 0); if (r < 0) return r; /* Remarshall if we have to. This will possibly unref the * message and place a replacement in m */ r = bus_remarshal_message(bus, &m); if (r < 0) return r; /* If this is a reply and no reply was requested, then let's * suppress this, if we can */ if (m->dont_send) goto finish; if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) { size_t idx = 0; r = bus_write_message(bus, m, hint_sync_call, &idx); if (r < 0) { if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) { bus_enter_closing(bus); return -ECONNRESET; } return r; } if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m)) { /* Wasn't fully written. So let's remember how * much was written. Note that the first entry * of the wqueue array is always allocated so * that we always can remember how much was * written. */ bus->wqueue[0] = sd_bus_message_ref(m); bus->wqueue_size = 1; bus->windex = idx; } } else { /* Just append it to the queue. */ if (bus->wqueue_size >= BUS_WQUEUE_MAX) return -ENOBUFS; if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1)) return -ENOMEM; bus->wqueue[bus->wqueue_size ++] = sd_bus_message_ref(m); } finish: if (cookie) *cookie = BUS_MESSAGE_COOKIE(m); return 1; } _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie) { return bus_send_internal(bus, m, cookie, false); } _public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie) { int r; assert_return(m, -EINVAL); if (!bus) bus = m->bus; assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; if (!streq_ptr(m->destination, destination)) { if (!destination) return -EEXIST; r = sd_bus_message_set_destination(m, destination); if (r < 0) return r; } return sd_bus_send(bus, m, cookie); } static usec_t calc_elapse(uint64_t usec) { if (usec == (uint64_t) -1) return 0; return now(CLOCK_MONOTONIC) + usec; } static int timeout_compare(const void *a, const void *b) { const struct reply_callback *x = a, *y = b; if (x->timeout != 0 && y->timeout == 0) return -1; if (x->timeout == 0 && y->timeout != 0) return 1; if (x->timeout < y->timeout) return -1; if (x->timeout > y->timeout) return 1; return 0; } _public_ int sd_bus_call_async( sd_bus *bus, sd_bus_slot **slot, sd_bus_message *_m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m); _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *s = NULL; int r; assert_return(m, -EINVAL); assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL); assert_return(callback, -EINVAL); if (!bus) bus = m->bus; assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS); if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; r = ordered_hashmap_ensure_allocated(&bus->reply_callbacks, &uint64_hash_ops); if (r < 0) return r; r = prioq_ensure_allocated(&bus->reply_callbacks_prioq, timeout_compare); if (r < 0) return r; r = bus_seal_message(bus, m, usec); if (r < 0) return r; r = bus_remarshal_message(bus, &m); if (r < 0) return r; s = bus_slot_allocate(bus, !slot, BUS_REPLY_CALLBACK, sizeof(struct reply_callback), userdata); if (!s) return -ENOMEM; s->reply_callback.callback = callback; s->reply_callback.cookie = BUS_MESSAGE_COOKIE(m); r = ordered_hashmap_put(bus->reply_callbacks, &s->reply_callback.cookie, &s->reply_callback); if (r < 0) { s->reply_callback.cookie = 0; return r; } s->reply_callback.timeout = calc_elapse(m->timeout); if (s->reply_callback.timeout != 0) { r = prioq_put(bus->reply_callbacks_prioq, &s->reply_callback, &s->reply_callback.prioq_idx); if (r < 0) { s->reply_callback.timeout = 0; return r; } } r = sd_bus_send(bus, m, &s->reply_callback.cookie); if (r < 0) return r; if (slot) *slot = s; s = NULL; return r; } int bus_ensure_running(sd_bus *bus) { int r; assert(bus); if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED || bus->state == BUS_CLOSING) return -ENOTCONN; if (bus->state == BUS_RUNNING) return 1; for (;;) { r = sd_bus_process(bus, NULL); if (r < 0) return r; if (bus->state == BUS_RUNNING) return 1; if (r > 0) continue; r = sd_bus_wait(bus, (uint64_t) -1); if (r < 0) return r; } } _public_ int sd_bus_call( sd_bus *bus, sd_bus_message *_m, uint64_t usec, sd_bus_error *error, sd_bus_message **reply) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m); usec_t timeout; uint64_t cookie; unsigned i; int r; bus_assert_return(m, -EINVAL, error); bus_assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL, error); bus_assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL, error); bus_assert_return(!bus_error_is_dirty(error), -EINVAL, error); if (!bus) bus = m->bus; bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); bus_assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS, error); if (!BUS_IS_OPEN(bus->state)) { r = -ENOTCONN; goto fail; } r = bus_ensure_running(bus); if (r < 0) goto fail; i = bus->rqueue_size; r = bus_seal_message(bus, m, usec); if (r < 0) goto fail; r = bus_remarshal_message(bus, &m); if (r < 0) goto fail; r = bus_send_internal(bus, m, &cookie, true); if (r < 0) goto fail; timeout = calc_elapse(m->timeout); for (;;) { usec_t left; while (i < bus->rqueue_size) { sd_bus_message *incoming = NULL; incoming = bus->rqueue[i]; if (incoming->reply_cookie == cookie) { /* Found a match! */ memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); bus->rqueue_size--; log_debug_bus_message(incoming); if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) { if (incoming->n_fds <= 0 || (bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)) { if (reply) *reply = incoming; else sd_bus_message_unref(incoming); return 1; } r = sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry."); sd_bus_message_unref(incoming); return r; } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) { r = sd_bus_error_copy(error, &incoming->error); sd_bus_message_unref(incoming); return r; } else { r = -EIO; goto fail; } } else if (BUS_MESSAGE_COOKIE(incoming) == cookie && bus->unique_name && incoming->sender && streq(bus->unique_name, incoming->sender)) { memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); bus->rqueue_size--; /* Our own message? Somebody is trying * to send its own client a message, * let's not dead-lock, let's fail * immediately. */ sd_bus_message_unref(incoming); r = -ELOOP; goto fail; } /* Try to read more, right-away */ i++; } r = bus_read_message(bus, false, 0); if (r < 0) { if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) { bus_enter_closing(bus); r = -ECONNRESET; } goto fail; } if (r > 0) continue; if (timeout > 0) { usec_t n; n = now(CLOCK_MONOTONIC); if (n >= timeout) { r = -ETIMEDOUT; goto fail; } left = timeout - n; } else left = (uint64_t) -1; r = bus_poll(bus, true, left); if (r < 0) goto fail; if (r == 0) { r = -ETIMEDOUT; goto fail; } r = dispatch_wqueue(bus); if (r < 0) { if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) { bus_enter_closing(bus); r = -ECONNRESET; } goto fail; } } fail: return sd_bus_error_set_errno(error, r); } _public_ int sd_bus_get_fd(sd_bus *bus) { assert_return(bus, -EINVAL); assert_return(bus->input_fd == bus->output_fd, -EPERM); assert_return(!bus_pid_changed(bus), -ECHILD); return bus->input_fd; } _public_ int sd_bus_get_events(sd_bus *bus) { int flags = 0; assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state) && bus->state != BUS_CLOSING) return -ENOTCONN; if (bus->state == BUS_OPENING) flags |= POLLOUT; else if (bus->state == BUS_AUTHENTICATING) { if (bus_socket_auth_needs_write(bus)) flags |= POLLOUT; flags |= POLLIN; } else if (bus->state == BUS_RUNNING || bus->state == BUS_HELLO) { if (bus->rqueue_size <= 0) flags |= POLLIN; if (bus->wqueue_size > 0) flags |= POLLOUT; } return flags; } _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) { struct reply_callback *c; assert_return(bus, -EINVAL); assert_return(timeout_usec, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!BUS_IS_OPEN(bus->state) && bus->state != BUS_CLOSING) return -ENOTCONN; if (bus->track_queue) { *timeout_usec = 0; return 1; } if (bus->state == BUS_CLOSING) { *timeout_usec = 0; return 1; } if (bus->state == BUS_AUTHENTICATING) { *timeout_usec = bus->auth_timeout; return 1; } if (bus->state != BUS_RUNNING && bus->state != BUS_HELLO) { *timeout_usec = (uint64_t) -1; return 0; } if (bus->rqueue_size > 0) { *timeout_usec = 0; return 1; } c = prioq_peek(bus->reply_callbacks_prioq); if (!c) { *timeout_usec = (uint64_t) -1; return 0; } if (c->timeout == 0) { *timeout_usec = (uint64_t) -1; return 0; } *timeout_usec = c->timeout; return 1; } static int process_timeout(sd_bus *bus) { _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message* m = NULL; struct reply_callback *c; sd_bus_slot *slot; usec_t n; int r; assert(bus); c = prioq_peek(bus->reply_callbacks_prioq); if (!c) return 0; n = now(CLOCK_MONOTONIC); if (c->timeout > n) return 0; r = bus_message_new_synthetic_error( bus, c->cookie, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out"), &m); if (r < 0) return r; r = bus_seal_synthetic_message(bus, m); if (r < 0) return r; assert_se(prioq_pop(bus->reply_callbacks_prioq) == c); c->timeout = 0; ordered_hashmap_remove(bus->reply_callbacks, &c->cookie); c->cookie = 0; slot = container_of(c, sd_bus_slot, reply_callback); bus->iteration_counter ++; bus->current_message = m; bus->current_slot = sd_bus_slot_ref(slot); bus->current_handler = c->callback; bus->current_userdata = slot->userdata; r = c->callback(m, slot->userdata, &error_buffer); bus->current_userdata = NULL; bus->current_handler = NULL; bus->current_slot = NULL; bus->current_message = NULL; if (slot->floating) { bus_slot_disconnect(slot); sd_bus_slot_unref(slot); } sd_bus_slot_unref(slot); return bus_maybe_reply_error(m, r, &error_buffer); } static int process_hello(sd_bus *bus, sd_bus_message *m) { assert(bus); assert(m); if (bus->state != BUS_HELLO) return 0; /* Let's make sure the first message on the bus is the HELLO * reply. But note that we don't actually parse the message * here (we leave that to the usual handling), we just verify * we don't let any earlier msg through. */ if (m->header->type != SD_BUS_MESSAGE_METHOD_RETURN && m->header->type != SD_BUS_MESSAGE_METHOD_ERROR) return -EIO; if (m->reply_cookie != 1) return -EIO; return 0; } static int process_reply(sd_bus *bus, sd_bus_message *m) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *synthetic_reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; struct reply_callback *c; sd_bus_slot *slot; int r; assert(bus); assert(m); if (m->header->type != SD_BUS_MESSAGE_METHOD_RETURN && m->header->type != SD_BUS_MESSAGE_METHOD_ERROR) return 0; if (bus->is_kernel && (bus->hello_flags & KDBUS_HELLO_MONITOR)) return 0; if (m->destination && bus->unique_name && !streq_ptr(m->destination, bus->unique_name)) return 0; c = ordered_hashmap_remove(bus->reply_callbacks, &m->reply_cookie); if (!c) return 0; c->cookie = 0; slot = container_of(c, sd_bus_slot, reply_callback); if (m->n_fds > 0 && !(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)) { /* If the reply contained a file descriptor which we * didn't want we pass an error instead. */ r = bus_message_new_synthetic_error( bus, m->reply_cookie, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptor"), &synthetic_reply); if (r < 0) return r; /* Copy over original timestamp */ synthetic_reply->realtime = m->realtime; synthetic_reply->monotonic = m->monotonic; synthetic_reply->seqnum = m->seqnum; r = bus_seal_synthetic_message(bus, synthetic_reply); if (r < 0) return r; m = synthetic_reply; } else { r = sd_bus_message_rewind(m, true); if (r < 0) return r; } if (c->timeout != 0) { prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx); c->timeout = 0; } bus->current_slot = sd_bus_slot_ref(slot); bus->current_handler = c->callback; bus->current_userdata = slot->userdata; r = c->callback(m, slot->userdata, &error_buffer); bus->current_userdata = NULL; bus->current_handler = NULL; bus->current_slot = NULL; if (slot->floating) { bus_slot_disconnect(slot); sd_bus_slot_unref(slot); } sd_bus_slot_unref(slot); return bus_maybe_reply_error(m, r, &error_buffer); } static int process_filter(sd_bus *bus, sd_bus_message *m) { _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; struct filter_callback *l; int r; assert(bus); assert(m); do { bus->filter_callbacks_modified = false; LIST_FOREACH(callbacks, l, bus->filter_callbacks) { sd_bus_slot *slot; if (bus->filter_callbacks_modified) break; /* Don't run this more than once per iteration */ if (l->last_iteration == bus->iteration_counter) continue; l->last_iteration = bus->iteration_counter; r = sd_bus_message_rewind(m, true); if (r < 0) return r; slot = container_of(l, sd_bus_slot, filter_callback); bus->current_slot = sd_bus_slot_ref(slot); bus->current_handler = l->callback; bus->current_userdata = slot->userdata; r = l->callback(m, slot->userdata, &error_buffer); bus->current_userdata = NULL; bus->current_handler = NULL; bus->current_slot = sd_bus_slot_unref(slot); r = bus_maybe_reply_error(m, r, &error_buffer); if (r != 0) return r; } } while (bus->filter_callbacks_modified); return 0; } static int process_match(sd_bus *bus, sd_bus_message *m) { int r; assert(bus); assert(m); do { bus->match_callbacks_modified = false; r = bus_match_run(bus, &bus->match_callbacks, m); if (r != 0) return r; } while (bus->match_callbacks_modified); return 0; } static int process_builtin(sd_bus *bus, sd_bus_message *m) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(bus); assert(m); if (bus->hello_flags & KDBUS_HELLO_MONITOR) return 0; if (bus->manual_peer_interface) return 0; if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL) return 0; if (!streq_ptr(m->interface, "org.freedesktop.DBus.Peer")) return 0; if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 1; if (streq_ptr(m->member, "Ping")) r = sd_bus_message_new_method_return(m, &reply); else if (streq_ptr(m->member, "GetMachineId")) { sd_id128_t id; char sid[33]; r = sd_id128_get_machine(&id); if (r < 0) return r; r = sd_bus_message_new_method_return(m, &reply); if (r < 0) return r; r = sd_bus_message_append(reply, "s", sd_id128_to_string(id, sid)); } else { r = sd_bus_message_new_method_errorf( m, &reply, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s' on interface '%s'.", m->member, m->interface); } if (r < 0) return r; r = sd_bus_send(bus, reply, NULL); if (r < 0) return r; return 1; } static int process_fd_check(sd_bus *bus, sd_bus_message *m) { assert(bus); assert(m); /* If we got a message with a file descriptor which we didn't * want to accept, then let's drop it. How can this even * happen? For example, when the kernel queues a message into * an activatable names's queue which allows fds, and then is * delivered to us later even though we ourselves did not * negotiate it. */ if (bus->hello_flags & KDBUS_HELLO_MONITOR) return 0; if (m->n_fds <= 0) return 0; if (bus->hello_flags & KDBUS_HELLO_ACCEPT_FD) return 0; if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL) return 1; /* just eat it up */ return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Message contains file descriptors, which I cannot accept. Sorry."); } static int process_message(sd_bus *bus, sd_bus_message *m) { int r; assert(bus); assert(m); bus->current_message = m; bus->iteration_counter++; log_debug_bus_message(m); r = process_hello(bus, m); if (r != 0) goto finish; r = process_reply(bus, m); if (r != 0) goto finish; r = process_fd_check(bus, m); if (r != 0) goto finish; r = process_filter(bus, m); if (r != 0) goto finish; r = process_match(bus, m); if (r != 0) goto finish; r = process_builtin(bus, m); if (r != 0) goto finish; r = bus_process_object(bus, m); finish: bus->current_message = NULL; return r; } static int dispatch_track(sd_bus *bus) { assert(bus); if (!bus->track_queue) return 0; bus_track_dispatch(bus->track_queue); return 1; } static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **ret) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; int r; assert(bus); assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO); r = process_timeout(bus); if (r != 0) goto null_message; r = dispatch_wqueue(bus); if (r != 0) goto null_message; r = dispatch_track(bus); if (r != 0) goto null_message; r = dispatch_rqueue(bus, hint_priority, priority, &m); if (r < 0) return r; if (!m) goto null_message; r = process_message(bus, m); if (r != 0) goto null_message; if (ret) { r = sd_bus_message_rewind(m, true); if (r < 0) return r; *ret = m; m = NULL; return 1; } if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) { log_debug("Unprocessed message call sender=%s object=%s interface=%s member=%s", strna(sd_bus_message_get_sender(m)), strna(sd_bus_message_get_path(m)), strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m))); r = sd_bus_reply_method_errorf( m, SD_BUS_ERROR_UNKNOWN_OBJECT, "Unknown object '%s'.", m->path); if (r < 0) return r; } return 1; null_message: if (r >= 0 && ret) *ret = NULL; return r; } static int process_closing(sd_bus *bus, sd_bus_message **ret) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; struct reply_callback *c; int r; assert(bus); assert(bus->state == BUS_CLOSING); c = ordered_hashmap_first(bus->reply_callbacks); if (c) { _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; sd_bus_slot *slot; /* First, fail all outstanding method calls */ r = bus_message_new_synthetic_error( bus, c->cookie, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"), &m); if (r < 0) return r; r = bus_seal_synthetic_message(bus, m); if (r < 0) return r; if (c->timeout != 0) { prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx); c->timeout = 0; } ordered_hashmap_remove(bus->reply_callbacks, &c->cookie); c->cookie = 0; slot = container_of(c, sd_bus_slot, reply_callback); bus->iteration_counter++; bus->current_message = m; bus->current_slot = sd_bus_slot_ref(slot); bus->current_handler = c->callback; bus->current_userdata = slot->userdata; r = c->callback(m, slot->userdata, &error_buffer); bus->current_userdata = NULL; bus->current_handler = NULL; bus->current_slot = NULL; bus->current_message = NULL; if (slot->floating) { bus_slot_disconnect(slot); sd_bus_slot_unref(slot); } sd_bus_slot_unref(slot); return bus_maybe_reply_error(m, r, &error_buffer); } /* Then, synthesize a Disconnected message */ r = sd_bus_message_new_signal( bus, &m, "/org/freedesktop/DBus/Local", "org.freedesktop.DBus.Local", "Disconnected"); if (r < 0) return r; bus_message_set_sender_local(bus, m); r = bus_seal_synthetic_message(bus, m); if (r < 0) return r; sd_bus_close(bus); bus->current_message = m; bus->iteration_counter++; r = process_filter(bus, m); if (r != 0) goto finish; r = process_match(bus, m); if (r != 0) goto finish; if (ret) { *ret = m; m = NULL; } r = 1; finish: bus->current_message = NULL; return r; } static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **ret) { BUS_DONT_DESTROY(bus); int r; /* Returns 0 when we didn't do anything. This should cause the * caller to invoke sd_bus_wait() before returning the next * time. Returns > 0 when we did something, which possibly * means *ret is filled in with an unprocessed message. */ assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); /* We don't allow recursively invoking sd_bus_process(). */ assert_return(!bus->current_message, -EBUSY); assert(!bus->current_slot); switch (bus->state) { case BUS_UNSET: return -ENOTCONN; case BUS_CLOSED: return -ECONNRESET; case BUS_OPENING: r = bus_socket_process_opening(bus); if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) { bus_enter_closing(bus); r = 1; } else if (r < 0) return r; if (ret) *ret = NULL; return r; case BUS_AUTHENTICATING: r = bus_socket_process_authenticating(bus); if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) { bus_enter_closing(bus); r = 1; } else if (r < 0) return r; if (ret) *ret = NULL; return r; case BUS_RUNNING: case BUS_HELLO: r = process_running(bus, hint_priority, priority, ret); if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) { bus_enter_closing(bus); r = 1; if (ret) *ret = NULL; } return r; case BUS_CLOSING: return process_closing(bus, ret); } assert_not_reached("Unknown state"); } _public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) { return bus_process_internal(bus, false, 0, ret); } _public_ int sd_bus_process_priority(sd_bus *bus, int64_t priority, sd_bus_message **ret) { return bus_process_internal(bus, true, priority, ret); } static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) { struct pollfd p[2] = {}; int r, e, n; struct timespec ts; usec_t m = USEC_INFINITY; assert(bus); if (bus->state == BUS_CLOSING) return 1; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; e = sd_bus_get_events(bus); if (e < 0) return e; if (need_more) /* The caller really needs some more data, he doesn't * care about what's already read, or any timeouts * except its own. */ e |= POLLIN; else { usec_t until; /* The caller wants to process if there's something to * process, but doesn't care otherwise */ r = sd_bus_get_timeout(bus, &until); if (r < 0) return r; if (r > 0) { usec_t nw; nw = now(CLOCK_MONOTONIC); m = until > nw ? until - nw : 0; } } if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m)) m = timeout_usec; p[0].fd = bus->input_fd; if (bus->output_fd == bus->input_fd) { p[0].events = e; n = 1; } else { p[0].events = e & POLLIN; p[1].fd = bus->output_fd; p[1].events = e & POLLOUT; n = 2; } r = ppoll(p, n, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL); if (r < 0) return -errno; return r > 0 ? 1 : 0; } _public_ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (bus->state == BUS_CLOSING) return 0; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; if (bus->rqueue_size > 0) return 0; return bus_poll(bus, false, timeout_usec); } _public_ int sd_bus_flush(sd_bus *bus) { int r; assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (bus->state == BUS_CLOSING) return 0; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; r = bus_ensure_running(bus); if (r < 0) return r; if (bus->wqueue_size <= 0) return 0; for (;;) { r = dispatch_wqueue(bus); if (r < 0) { if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) { bus_enter_closing(bus); return -ECONNRESET; } return r; } if (bus->wqueue_size <= 0) return 0; r = bus_poll(bus, false, (uint64_t) -1); if (r < 0) return r; } } _public_ int sd_bus_add_filter( sd_bus *bus, sd_bus_slot **slot, sd_bus_message_handler_t callback, void *userdata) { sd_bus_slot *s; assert_return(bus, -EINVAL); assert_return(callback, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); s = bus_slot_allocate(bus, !slot, BUS_FILTER_CALLBACK, sizeof(struct filter_callback), userdata); if (!s) return -ENOMEM; s->filter_callback.callback = callback; bus->filter_callbacks_modified = true; LIST_PREPEND(callbacks, bus->filter_callbacks, &s->filter_callback); if (slot) *slot = s; return 0; } _public_ int sd_bus_add_match( sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata) { struct bus_match_component *components = NULL; unsigned n_components = 0; sd_bus_slot *s = NULL; int r = 0; assert_return(bus, -EINVAL); assert_return(match, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); r = bus_match_parse(match, &components, &n_components); if (r < 0) goto finish; s = bus_slot_allocate(bus, !slot, BUS_MATCH_CALLBACK, sizeof(struct match_callback), userdata); if (!s) { r = -ENOMEM; goto finish; } s->match_callback.callback = callback; s->match_callback.cookie = ++bus->match_cookie; if (bus->bus_client) { enum bus_match_scope scope; scope = bus_match_get_scope(components, n_components); /* Do not install server-side matches for matches * against the local service, interface or bus * path. */ if (scope != BUS_MATCH_LOCAL) { if (!bus->is_kernel) { /* When this is not a kernel transport, we * store the original match string, so that we * can use it to remove the match again */ s->match_callback.match_string = strdup(match); if (!s->match_callback.match_string) { r = -ENOMEM; goto finish; } } r = bus_add_match_internal(bus, s->match_callback.match_string, components, n_components, s->match_callback.cookie); if (r < 0) goto finish; s->match_added = true; } } bus->match_callbacks_modified = true; r = bus_match_add(&bus->match_callbacks, components, n_components, &s->match_callback); if (r < 0) goto finish; if (slot) *slot = s; s = NULL; finish: bus_match_parse_free(components, n_components); sd_bus_slot_unref(s); return r; } int bus_remove_match_by_string( sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) { struct bus_match_component *components = NULL; unsigned n_components = 0; struct match_callback *c; int r = 0; assert_return(bus, -EINVAL); assert_return(match, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); r = bus_match_parse(match, &components, &n_components); if (r < 0) goto finish; r = bus_match_find(&bus->match_callbacks, components, n_components, NULL, NULL, &c); if (r <= 0) goto finish; sd_bus_slot_unref(container_of(c, sd_bus_slot, match_callback)); finish: bus_match_parse_free(components, n_components); return r; } bool bus_pid_changed(sd_bus *bus) { assert(bus); /* We don't support people creating a bus connection and * keeping it around over a fork(). Let's complain. */ return bus->original_pid != getpid(); } static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) { sd_bus *bus = userdata; int r; assert(bus); r = sd_bus_process(bus, NULL); if (r < 0) return r; return 1; } static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) { sd_bus *bus = userdata; int r; assert(bus); r = sd_bus_process(bus, NULL); if (r < 0) return r; return 1; } static int prepare_callback(sd_event_source *s, void *userdata) { sd_bus *bus = userdata; int r, e; usec_t until; assert(s); assert(bus); e = sd_bus_get_events(bus); if (e < 0) return e; if (bus->output_fd != bus->input_fd) { r = sd_event_source_set_io_events(bus->input_io_event_source, e & POLLIN); if (r < 0) return r; r = sd_event_source_set_io_events(bus->output_io_event_source, e & POLLOUT); if (r < 0) return r; } else { r = sd_event_source_set_io_events(bus->input_io_event_source, e); if (r < 0) return r; } r = sd_bus_get_timeout(bus, &until); if (r < 0) return r; if (r > 0) { int j; j = sd_event_source_set_time(bus->time_event_source, until); if (j < 0) return j; } r = sd_event_source_set_enabled(bus->time_event_source, r > 0); if (r < 0) return r; return 1; } static int quit_callback(sd_event_source *event, void *userdata) { sd_bus *bus = userdata; assert(event); sd_bus_flush(bus); sd_bus_close(bus); return 1; } static int attach_io_events(sd_bus *bus) { int r; assert(bus); if (bus->input_fd < 0) return 0; if (!bus->event) return 0; if (!bus->input_io_event_source) { r = sd_event_add_io(bus->event, &bus->input_io_event_source, bus->input_fd, 0, io_callback, bus); if (r < 0) return r; r = sd_event_source_set_prepare(bus->input_io_event_source, prepare_callback); if (r < 0) return r; r = sd_event_source_set_priority(bus->input_io_event_source, bus->event_priority); if (r < 0) return r; r = sd_event_source_set_description(bus->input_io_event_source, "bus-input"); } else r = sd_event_source_set_io_fd(bus->input_io_event_source, bus->input_fd); if (r < 0) return r; if (bus->output_fd != bus->input_fd) { assert(bus->output_fd >= 0); if (!bus->output_io_event_source) { r = sd_event_add_io(bus->event, &bus->output_io_event_source, bus->output_fd, 0, io_callback, bus); if (r < 0) return r; r = sd_event_source_set_priority(bus->output_io_event_source, bus->event_priority); if (r < 0) return r; r = sd_event_source_set_description(bus->input_io_event_source, "bus-output"); } else r = sd_event_source_set_io_fd(bus->output_io_event_source, bus->output_fd); if (r < 0) return r; } return 0; } static void detach_io_events(sd_bus *bus) { assert(bus); if (bus->input_io_event_source) { sd_event_source_set_enabled(bus->input_io_event_source, SD_EVENT_OFF); bus->input_io_event_source = sd_event_source_unref(bus->input_io_event_source); } if (bus->output_io_event_source) { sd_event_source_set_enabled(bus->output_io_event_source, SD_EVENT_OFF); bus->output_io_event_source = sd_event_source_unref(bus->output_io_event_source); } } _public_ int sd_bus_attach_event(sd_bus *bus, sd_event *event, int priority) { int r; assert_return(bus, -EINVAL); assert_return(!bus->event, -EBUSY); assert(!bus->input_io_event_source); assert(!bus->output_io_event_source); assert(!bus->time_event_source); if (event) bus->event = sd_event_ref(event); else { r = sd_event_default(&bus->event); if (r < 0) return r; } bus->event_priority = priority; r = sd_event_add_time(bus->event, &bus->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, bus); if (r < 0) goto fail; r = sd_event_source_set_priority(bus->time_event_source, priority); if (r < 0) goto fail; r = sd_event_source_set_description(bus->time_event_source, "bus-time"); if (r < 0) goto fail; r = sd_event_add_exit(bus->event, &bus->quit_event_source, quit_callback, bus); if (r < 0) goto fail; r = sd_event_source_set_description(bus->quit_event_source, "bus-exit"); if (r < 0) goto fail; r = attach_io_events(bus); if (r < 0) goto fail; return 0; fail: sd_bus_detach_event(bus); return r; } _public_ int sd_bus_detach_event(sd_bus *bus) { assert_return(bus, -EINVAL); if (!bus->event) return 0; detach_io_events(bus); if (bus->time_event_source) { sd_event_source_set_enabled(bus->time_event_source, SD_EVENT_OFF); bus->time_event_source = sd_event_source_unref(bus->time_event_source); } if (bus->quit_event_source) { sd_event_source_set_enabled(bus->quit_event_source, SD_EVENT_OFF); bus->quit_event_source = sd_event_source_unref(bus->quit_event_source); } bus->event = sd_event_unref(bus->event); return 1; } _public_ sd_event* sd_bus_get_event(sd_bus *bus) { assert_return(bus, NULL); return bus->event; } _public_ sd_bus_message* sd_bus_get_current_message(sd_bus *bus) { assert_return(bus, NULL); return bus->current_message; } _public_ sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus) { assert_return(bus, NULL); return bus->current_slot; } _public_ sd_bus_message_handler_t sd_bus_get_current_handler(sd_bus *bus) { assert_return(bus, NULL); return bus->current_handler; } _public_ void* sd_bus_get_current_userdata(sd_bus *bus) { assert_return(bus, NULL); return bus->current_userdata; } static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus **ret) { sd_bus *b = NULL; int r; assert(bus_open); assert(default_bus); if (!ret) return !!*default_bus; if (*default_bus) { *ret = sd_bus_ref(*default_bus); return 0; } r = bus_open(&b); if (r < 0) return r; b->default_bus_ptr = default_bus; b->tid = gettid(); *default_bus = b; *ret = b; return 1; } _public_ int sd_bus_default_system(sd_bus **ret) { return bus_default(sd_bus_open_system, &default_system_bus, ret); } _public_ int sd_bus_default_user(sd_bus **ret) { return bus_default(sd_bus_open_user, &default_user_bus, ret); } _public_ int sd_bus_default(sd_bus **ret) { const char *e; /* Let's try our best to reuse another cached connection. If * the starter bus type is set, connect via our normal * connection logic, ignoring $DBUS_STARTER_ADDRESS, so that * we can share the connection with the user/system default * bus. */ e = secure_getenv("DBUS_STARTER_BUS_TYPE"); if (e) { if (streq(e, "system")) return sd_bus_default_system(ret); else if (STR_IN_SET(e, "user", "session")) return sd_bus_default_user(ret); } /* No type is specified, so we have not other option than to * use the starter address if it is set. */ e = secure_getenv("DBUS_STARTER_ADDRESS"); if (e) { return bus_default(sd_bus_open, &default_starter_bus, ret); } /* Finally, if nothing is set use the cached connection for * the right scope */ if (cg_pid_get_owner_uid(0, NULL) >= 0) return sd_bus_default_user(ret); else return sd_bus_default_system(ret); } _public_ int sd_bus_get_tid(sd_bus *b, pid_t *tid) { assert_return(b, -EINVAL); assert_return(tid, -EINVAL); assert_return(!bus_pid_changed(b), -ECHILD); if (b->tid != 0) { *tid = b->tid; return 0; } if (b->event) return sd_event_get_tid(b->event, tid); return -ENXIO; } _public_ int sd_bus_path_encode(const char *prefix, const char *external_id, char **ret_path) { _cleanup_free_ char *e = NULL; char *ret; assert_return(object_path_is_valid(prefix), -EINVAL); assert_return(external_id, -EINVAL); assert_return(ret_path, -EINVAL); e = bus_label_escape(external_id); if (!e) return -ENOMEM; ret = strjoin(prefix, "/", e, NULL); if (!ret) return -ENOMEM; *ret_path = ret; return 0; } _public_ int sd_bus_path_decode(const char *path, const char *prefix, char **external_id) { const char *e; char *ret; assert_return(object_path_is_valid(path), -EINVAL); assert_return(object_path_is_valid(prefix), -EINVAL); assert_return(external_id, -EINVAL); e = object_path_startswith(path, prefix); if (!e) { *external_id = NULL; return 0; } ret = bus_label_unescape(e); if (!ret) return -ENOMEM; *external_id = ret; return 1; } _public_ int sd_bus_path_encode_many(char **out, const char *path_template, ...) { _cleanup_strv_free_ char **labels = NULL; char *path, *path_pos, **label_pos; const char *sep, *template_pos; size_t path_length; va_list list; int r; assert_return(out, -EINVAL); assert_return(path_template, -EINVAL); path_length = strlen(path_template); va_start(list, path_template); for (sep = strchr(path_template, '%'); sep; sep = strchr(sep + 1, '%')) { const char *arg; char *label; arg = va_arg(list, const char *); if (!arg) { va_end(list); return -EINVAL; } label = bus_label_escape(arg); if (!label) { va_end(list); return -ENOMEM; } r = strv_consume(&labels, label); if (r < 0) { va_end(list); return r; } /* add label length, but account for the format character */ path_length += strlen(label) - 1; } va_end(list); path = malloc(path_length + 1); if (!path) return -ENOMEM; path_pos = path; label_pos = labels; for (template_pos = path_template; *template_pos; ) { sep = strchrnul(template_pos, '%'); path_pos = mempcpy(path_pos, template_pos, sep - template_pos); if (!*sep) break; path_pos = stpcpy(path_pos, *label_pos++); template_pos = sep + 1; } *path_pos = 0; *out = path; return 0; } _public_ int sd_bus_path_decode_many(const char *path, const char *path_template, ...) { _cleanup_strv_free_ char **labels = NULL; const char *template_pos, *path_pos; char **label_pos; va_list list; int r; /* * This decodes an object-path based on a template argument. The * template consists of a verbatim path, optionally including special * directives: * * - Each occurrence of '%' in the template matches an arbitrary * substring of a label in the given path. At most one such * directive is allowed per label. For each such directive, the * caller must provide an output parameter (char **) via va_arg. If * NULL is passed, the given label is verified, but not returned. * For each matched label, the *decoded* label is stored in the * passed output argument, and the caller is responsible to free * it. Note that the output arguments are only modified if the * actualy path matched the template. Otherwise, they're left * untouched. * * This function returns <0 on error, 0 if the path does not match the * template, 1 if it matched. */ assert_return(path, -EINVAL); assert_return(path_template, -EINVAL); path_pos = path; for (template_pos = path_template; *template_pos; ) { const char *sep; size_t length; char *label; /* verify everything until the next '%' matches verbatim */ sep = strchrnul(template_pos, '%'); length = sep - template_pos; if (strncmp(path_pos, template_pos, length)) return 0; path_pos += length; template_pos += length; if (!*template_pos) break; /* We found the next '%' character. Everything up until here * matched. We now skip ahead to the end of this label and make * sure it matches the tail of the label in the path. Then we * decode the string in-between and save it for later use. */ ++template_pos; /* skip over '%' */ sep = strchrnul(template_pos, '/'); length = sep - template_pos; /* length of suffix to match verbatim */ /* verify the suffixes match */ sep = strchrnul(path_pos, '/'); if (sep - path_pos < (ssize_t)length || strncmp(sep - length, template_pos, length)) return 0; template_pos += length; /* skip over matched label */ length = sep - path_pos - length; /* length of sub-label to decode */ /* store unescaped label for later use */ label = bus_label_unescape_n(path_pos, length); if (!label) return -ENOMEM; r = strv_consume(&labels, label); if (r < 0) return r; path_pos = sep; /* skip decoded label and suffix */ } /* end of template must match end of path */ if (*path_pos) return 0; /* copy the labels over to the caller */ va_start(list, path_template); for (label_pos = labels; label_pos && *label_pos; ++label_pos) { char **arg; arg = va_arg(list, char **); if (arg) *arg = *label_pos; else free(*label_pos); } va_end(list); free(labels); labels = NULL; return 1; } _public_ int sd_bus_try_close(sd_bus *bus) { int r; assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (!bus->is_kernel) return -EOPNOTSUPP; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; if (bus->rqueue_size > 0) return -EBUSY; if (bus->wqueue_size > 0) return -EBUSY; r = bus_kernel_try_close(bus); if (r < 0) return r; sd_bus_close(bus); return 0; } _public_ int sd_bus_get_description(sd_bus *bus, const char **description) { assert_return(bus, -EINVAL); assert_return(description, -EINVAL); assert_return(bus->description, -ENXIO); assert_return(!bus_pid_changed(bus), -ECHILD); *description = bus->description; return 0; } int bus_get_root_path(sd_bus *bus) { int r; if (bus->cgroup_root) return 0; r = cg_get_root_path(&bus->cgroup_root); if (r == -ENOENT) { bus->cgroup_root = strdup("/"); if (!bus->cgroup_root) return -ENOMEM; r = 0; } return r; } _public_ int sd_bus_get_scope(sd_bus *bus, const char **scope) { int r; assert_return(bus, -EINVAL); assert_return(scope, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (bus->is_kernel) { _cleanup_free_ char *n = NULL; const char *dash; r = bus_kernel_get_bus_name(bus, &n); if (r < 0) return r; if (streq(n, "0-system")) { *scope = "system"; return 0; } dash = strchr(n, '-'); if (streq_ptr(dash, "-user")) { *scope = "user"; return 0; } } if (bus->is_user) { *scope = "user"; return 0; } if (bus->is_system) { *scope = "system"; return 0; } return -ENODATA; } _public_ int sd_bus_get_address(sd_bus *bus, const char **address) { assert_return(bus, -EINVAL); assert_return(address, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); if (bus->address) { *address = bus->address; return 0; } return -ENODATA; } _public_ int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *mask) { assert_return(bus, -EINVAL); assert_return(mask, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); *mask = bus->creds_mask; return 0; } _public_ int sd_bus_is_bus_client(sd_bus *bus) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); return bus->bus_client; } _public_ int sd_bus_is_server(sd_bus *bus) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); return bus->is_server; } _public_ int sd_bus_is_anonymous(sd_bus *bus) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); return bus->anonymous_auth; } _public_ int sd_bus_is_trusted(sd_bus *bus) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); return bus->trusted; } _public_ int sd_bus_is_monitor(sd_bus *bus) { assert_return(bus, -EINVAL); assert_return(!bus_pid_changed(bus), -ECHILD); return !!(bus->hello_flags & KDBUS_HELLO_MONITOR); } static void flush_close(sd_bus *bus) { if (!bus) return; /* Flushes and closes the specified bus. We take a ref before, * to ensure the flushing does not cause the bus to be * unreferenced. */ sd_bus_flush_close_unref(sd_bus_ref(bus)); } _public_ void sd_bus_default_flush_close(void) { flush_close(default_starter_bus); flush_close(default_user_bus); flush_close(default_system_bus); } systemd-229/src/libsystemd/sd-bus/test-bus-benchmark.c000066400000000000000000000262201265713322000230700ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-internal.h" #include "bus-kernel.h" #include "bus-util.h" #include "def.h" #include "fd-util.h" #include "time-util.h" #include "util.h" #define MAX_SIZE (2*1024*1024) static usec_t arg_loop_usec = 100 * USEC_PER_MSEC; typedef enum Type { TYPE_KDBUS, TYPE_LEGACY, TYPE_DIRECT, } Type; static void server(sd_bus *b, size_t *result) { int r; for (;;) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; r = sd_bus_process(b, &m); assert_se(r >= 0); if (r == 0) assert_se(sd_bus_wait(b, USEC_INFINITY) >= 0); if (!m) continue; if (sd_bus_message_is_method_call(m, "benchmark.server", "Ping")) assert_se(sd_bus_reply_method_return(m, NULL) >= 0); else if (sd_bus_message_is_method_call(m, "benchmark.server", "Work")) { const void *p; size_t sz; /* Make sure the mmap is mapped */ assert_se(sd_bus_message_read_array(m, 'y', &p, &sz) > 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); } else if (sd_bus_message_is_method_call(m, "benchmark.server", "Exit")) { uint64_t res; assert_se(sd_bus_message_read(m, "t", &res) > 0); *result = res; return; } else if (!sd_bus_message_is_signal(m, NULL, NULL)) assert_not_reached("Unknown method"); } } static void transaction(sd_bus *b, size_t sz, const char *server_name) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; uint8_t *p; assert_se(sd_bus_message_new_method_call(b, &m, server_name, "/", "benchmark.server", "Work") >= 0); assert_se(sd_bus_message_append_array_space(m, 'y', sz, (void**) &p) >= 0); memset(p, 0x80, sz); assert_se(sd_bus_call(b, m, 0, NULL, &reply) >= 0); } static void client_bisect(const char *address, const char *server_name) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *x = NULL; size_t lsize, rsize, csize; sd_bus *b; int r; r = sd_bus_new(&b); assert_se(r >= 0); r = sd_bus_set_address(b, address); assert_se(r >= 0); r = sd_bus_start(b); assert_se(r >= 0); r = sd_bus_call_method(b, server_name, "/", "benchmark.server", "Ping", NULL, NULL, NULL); assert_se(r >= 0); lsize = 1; rsize = MAX_SIZE; printf("SIZE\tCOPY\tMEMFD\n"); for (;;) { usec_t t; unsigned n_copying, n_memfd; csize = (lsize + rsize) / 2; if (csize <= lsize) break; if (csize <= 0) break; printf("%zu\t", csize); b->use_memfd = 0; t = now(CLOCK_MONOTONIC); for (n_copying = 0;; n_copying++) { transaction(b, csize, server_name); if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec) break; } printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec)); b->use_memfd = -1; t = now(CLOCK_MONOTONIC); for (n_memfd = 0;; n_memfd++) { transaction(b, csize, server_name); if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec) break; } printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec)); if (n_copying == n_memfd) break; if (n_copying > n_memfd) lsize = csize; else rsize = csize; } b->use_memfd = 1; assert_se(sd_bus_message_new_method_call(b, &x, server_name, "/", "benchmark.server", "Exit") >= 0); assert_se(sd_bus_message_append(x, "t", csize) >= 0); assert_se(sd_bus_send(b, x, NULL) >= 0); sd_bus_unref(b); } static void client_chart(Type type, const char *address, const char *server_name, int fd) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *x = NULL; size_t csize; sd_bus *b; int r; r = sd_bus_new(&b); assert_se(r >= 0); if (type == TYPE_DIRECT) { r = sd_bus_set_fd(b, fd, fd); assert_se(r >= 0); } else { r = sd_bus_set_address(b, address); assert_se(r >= 0); r = sd_bus_set_bus_client(b, true); assert_se(r >= 0); } r = sd_bus_start(b); assert_se(r >= 0); r = sd_bus_call_method(b, server_name, "/", "benchmark.server", "Ping", NULL, NULL, NULL); assert_se(r >= 0); switch (type) { case TYPE_KDBUS: printf("SIZE\tCOPY\tMEMFD\n"); break; case TYPE_LEGACY: printf("SIZE\tLEGACY\n"); break; case TYPE_DIRECT: printf("SIZE\tDIRECT\n"); break; } for (csize = 1; csize <= MAX_SIZE; csize *= 2) { usec_t t; unsigned n_copying, n_memfd; printf("%zu\t", csize); if (type == TYPE_KDBUS) { b->use_memfd = 0; t = now(CLOCK_MONOTONIC); for (n_copying = 0;; n_copying++) { transaction(b, csize, server_name); if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec) break; } printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec)); b->use_memfd = -1; } t = now(CLOCK_MONOTONIC); for (n_memfd = 0;; n_memfd++) { transaction(b, csize, server_name); if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec) break; } printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec)); } b->use_memfd = 1; assert_se(sd_bus_message_new_method_call(b, &x, server_name, "/", "benchmark.server", "Exit") >= 0); assert_se(sd_bus_message_append(x, "t", csize) >= 0); assert_se(sd_bus_send(b, x, NULL) >= 0); sd_bus_unref(b); } int main(int argc, char *argv[]) { enum { MODE_BISECT, MODE_CHART, } mode = MODE_BISECT; Type type = TYPE_KDBUS; int i, pair[2] = { -1, -1 }; _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *server_name = NULL; _cleanup_close_ int bus_ref = -1; const char *unique; cpu_set_t cpuset; size_t result; sd_bus *b; pid_t pid; int r; for (i = 1; i < argc; i++) { if (streq(argv[i], "chart")) { mode = MODE_CHART; continue; } else if (streq(argv[i], "legacy")) { type = TYPE_LEGACY; continue; } else if (streq(argv[i], "direct")) { type = TYPE_DIRECT; continue; } assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0); } assert_se(!MODE_BISECT || TYPE_KDBUS); assert_se(arg_loop_usec > 0); if (type == TYPE_KDBUS) { assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0); bus_ref = bus_kernel_create_bus(name, false, &bus_name); if (bus_ref == -ENOENT) exit(EXIT_TEST_SKIP); assert_se(bus_ref >= 0); address = strappend("kernel:path=", bus_name); assert_se(address); } else if (type == TYPE_LEGACY) { const char *e; e = secure_getenv("DBUS_SESSION_BUS_ADDRESS"); assert_se(e); address = strdup(e); assert_se(address); } r = sd_bus_new(&b); assert_se(r >= 0); if (type == TYPE_DIRECT) { assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0); r = sd_bus_set_fd(b, pair[0], pair[0]); assert_se(r >= 0); r = sd_bus_set_server(b, true, SD_ID128_NULL); assert_se(r >= 0); } else { r = sd_bus_set_address(b, address); assert_se(r >= 0); r = sd_bus_set_bus_client(b, true); assert_se(r >= 0); } r = sd_bus_start(b); assert_se(r >= 0); if (type != TYPE_DIRECT) { r = sd_bus_get_unique_name(b, &unique); assert_se(r >= 0); server_name = strdup(unique); assert_se(server_name); } sync(); setpriority(PRIO_PROCESS, 0, -19); pid = fork(); assert_se(pid >= 0); if (pid == 0) { CPU_ZERO(&cpuset); CPU_SET(0, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); safe_close(bus_ref); sd_bus_unref(b); switch (mode) { case MODE_BISECT: client_bisect(address, server_name); break; case MODE_CHART: client_chart(type, address, server_name, pair[1]); break; } _exit(0); } CPU_ZERO(&cpuset); CPU_SET(1, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); server(b, &result); if (mode == MODE_BISECT) printf("Copying/memfd are equally fast at %zu bytes\n", result); assert_se(waitpid(pid, NULL, 0) == pid); safe_close(pair[1]); sd_bus_unref(b); return 0; } systemd-229/src/libsystemd/sd-bus/test-bus-chat.c000066400000000000000000000435331265713322000220630ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-internal.h" #include "bus-match.h" #include "bus-util.h" #include "fd-util.h" #include "formats-util.h" #include "log.h" #include "macro.h" #include "util.h" static int match_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m))); return 0; } static int object_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { int r; if (sd_bus_message_is_method_error(m, NULL)) return 0; if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) { log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m)); r = sd_bus_reply_method_return(m, NULL); if (r < 0) return log_error_errno(r, "Failed to send reply: %m"); return 1; } return 0; } static int server_init(sd_bus **_bus) { sd_bus *bus = NULL; sd_id128_t id; int r; const char *unique; assert_se(_bus); r = sd_bus_open_user(&bus); if (r < 0) { log_error_errno(r, "Failed to connect to user bus: %m"); goto fail; } r = sd_bus_get_bus_id(bus, &id); if (r < 0) { log_error_errno(r, "Failed to get server ID: %m"); goto fail; } r = sd_bus_get_unique_name(bus, &unique); if (r < 0) { log_error_errno(r, "Failed to get unique name: %m"); goto fail; } log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id)); log_info("Unique ID: %s", unique); log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h')); r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0); if (r < 0) { log_error_errno(r, "Failed to acquire name: %m"); goto fail; } r = sd_bus_add_fallback(bus, NULL, "/foo/bar", object_callback, NULL); if (r < 0) { log_error_errno(r, "Failed to add object: %m"); goto fail; } r = sd_bus_add_match(bus, NULL, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL); if (r < 0) { log_error_errno(r, "Failed to add match: %m"); goto fail; } r = sd_bus_add_match(bus, NULL, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL); if (r < 0) { log_error_errno(r, "Failed to add match: %m"); goto fail; } bus_match_dump(&bus->match_callbacks, 0); *_bus = bus; return 0; fail: sd_bus_unref(bus); return r; } static int server(sd_bus *bus) { int r; bool client1_gone = false, client2_gone = false; while (!client1_gone || !client2_gone) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; pid_t pid = 0; const char *label = NULL; r = sd_bus_process(bus, &m); if (r < 0) { log_error_errno(r, "Failed to process requests: %m"); goto fail; } if (r == 0) { r = sd_bus_wait(bus, (uint64_t) -1); if (r < 0) { log_error_errno(r, "Failed to wait: %m"); goto fail; } continue; } if (!m) continue; sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid); sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label); log_info("Got message! member=%s pid="PID_FMT" label=%s", strna(sd_bus_message_get_member(m)), pid, strna(label)); /* bus_message_dump(m); */ /* sd_bus_message_rewind(m, true); */ if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) { const char *hello; _cleanup_free_ char *lowercase = NULL; r = sd_bus_message_read(m, "s", &hello); if (r < 0) { log_error_errno(r, "Failed to get parameter: %m"); goto fail; } lowercase = strdup(hello); if (!lowercase) { r = log_oom(); goto fail; } ascii_strlower(lowercase); r = sd_bus_reply_method_return(m, "s", lowercase); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) { r = sd_bus_reply_method_return(m, NULL); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } client1_gone = true; } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) { r = sd_bus_reply_method_return(m, NULL); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } client2_gone = true; } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) { sleep(1); r = sd_bus_reply_method_return(m, NULL); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) { int fd; static const char x = 'X'; r = sd_bus_message_read(m, "h", &fd); if (r < 0) { log_error_errno(r, "Failed to get parameter: %m"); goto fail; } log_info("Received fd=%d", fd); if (write(fd, &x, 1) < 0) { log_error_errno(errno, "Failed to write to fd: %m"); safe_close(fd); goto fail; } r = sd_bus_reply_method_return(m, NULL); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } } else if (sd_bus_message_is_method_call(m, NULL, NULL)) { r = sd_bus_reply_method_error( m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method.")); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } } } r = 0; fail: if (bus) { sd_bus_flush(bus); sd_bus_unref(bus); } return r; } static void* client1(void*p) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *hello; int r; _cleanup_close_pair_ int pp[2] = { -1, -1 }; char x; r = sd_bus_open_user(&bus); if (r < 0) { log_error_errno(r, "Failed to connect to user bus: %m"); goto finish; } r = sd_bus_call_method( bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.systemd.test", "LowerCase", &error, &reply, "s", "HELLO"); if (r < 0) { log_error_errno(r, "Failed to issue method call: %m"); goto finish; } r = sd_bus_message_read(reply, "s", &hello); if (r < 0) { log_error_errno(r, "Failed to get string: %m"); goto finish; } assert_se(streq(hello, "hello")); if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) { log_error_errno(errno, "Failed to allocate pipe: %m"); r = -errno; goto finish; } log_info("Sending fd=%d", pp[1]); r = sd_bus_call_method( bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.systemd.test", "FileDescriptor", &error, NULL, "h", pp[1]); if (r < 0) { log_error_errno(r, "Failed to issue method call: %m"); goto finish; } errno = 0; if (read(pp[0], &x, 1) <= 0) { log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read"); goto finish; } r = 0; finish: if (bus) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *q; r = sd_bus_message_new_method_call( bus, &q, "org.freedesktop.systemd.test", "/", "org.freedesktop.systemd.test", "ExitClient1"); if (r < 0) log_error_errno(r, "Failed to allocate method call: %m"); else sd_bus_send(bus, q, NULL); } return INT_TO_PTR(r); } static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { bool *x = userdata; log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m))); *x = 1; return 1; } static void* client2(void*p) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; bool quit = false; const char *mid; int r; r = sd_bus_open_user(&bus); if (r < 0) { log_error_errno(r, "Failed to connect to user bus: %m"); goto finish; } r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd.test", "/foo/bar/waldo/piep", "org.object.test", "Foobar"); if (r < 0) { log_error_errno(r, "Failed to allocate method call: %m"); goto finish; } r = sd_bus_send(bus, m, NULL); if (r < 0) { log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); goto finish; } m = sd_bus_message_unref(m); r = sd_bus_message_new_signal( bus, &m, "/foobar", "foo.bar", "Notify"); if (r < 0) { log_error_errno(r, "Failed to allocate signal: %m"); goto finish; } r = sd_bus_send(bus, m, NULL); if (r < 0) { log_error("Failed to issue signal: %s", bus_error_message(&error, -r)); goto finish; } m = sd_bus_message_unref(m); r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Peer", "GetMachineId"); if (r < 0) { log_error_errno(r, "Failed to allocate method call: %m"); goto finish; } r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) { log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); goto finish; } r = sd_bus_message_read(reply, "s", &mid); if (r < 0) { log_error_errno(r, "Failed to parse machine ID: %m"); goto finish; } log_info("Machine ID is %s.", mid); m = sd_bus_message_unref(m); r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd.test", "/", "org.freedesktop.systemd.test", "Slow"); if (r < 0) { log_error_errno(r, "Failed to allocate method call: %m"); goto finish; } reply = sd_bus_message_unref(reply); r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply); if (r < 0) log_info("Failed to issue method call: %s", bus_error_message(&error, -r)); else log_info("Slow call succeed."); m = sd_bus_message_unref(m); r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd.test", "/", "org.freedesktop.systemd.test", "Slow"); if (r < 0) { log_error_errno(r, "Failed to allocate method call: %m"); goto finish; } r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC); if (r < 0) { log_info("Failed to issue method call: %s", bus_error_message(&error, -r)); goto finish; } while (!quit) { r = sd_bus_process(bus, NULL); if (r < 0) { log_error_errno(r, "Failed to process requests: %m"); goto finish; } if (r == 0) { r = sd_bus_wait(bus, (uint64_t) -1); if (r < 0) { log_error_errno(r, "Failed to wait: %m"); goto finish; } } } r = 0; finish: if (bus) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *q; r = sd_bus_message_new_method_call( bus, &q, "org.freedesktop.systemd.test", "/", "org.freedesktop.systemd.test", "ExitClient2"); if (r < 0) { log_error_errno(r, "Failed to allocate method call: %m"); goto finish; } (void) sd_bus_send(bus, q, NULL); } return INT_TO_PTR(r); } int main(int argc, char *argv[]) { pthread_t c1, c2; sd_bus *bus; void *p; int q, r; r = server_init(&bus); if (r < 0) { log_info("Failed to connect to bus, skipping tests."); return EXIT_TEST_SKIP; } log_info("Initialized..."); r = pthread_create(&c1, NULL, client1, bus); if (r != 0) return EXIT_FAILURE; r = pthread_create(&c2, NULL, client2, bus); if (r != 0) return EXIT_FAILURE; r = server(bus); q = pthread_join(c1, &p); if (q != 0) return EXIT_FAILURE; if (PTR_TO_INT(p) < 0) return EXIT_FAILURE; q = pthread_join(c2, &p); if (q != 0) return EXIT_FAILURE; if (PTR_TO_INT(p) < 0) return EXIT_FAILURE; if (r < 0) return EXIT_FAILURE; return EXIT_SUCCESS; } systemd-229/src/libsystemd/sd-bus/test-bus-cleanup.c000066400000000000000000000054231265713322000225670ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-util.h" #include "refcnt.h" static void test_bus_new(void) { _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; assert_se(sd_bus_new(&bus) == 0); printf("after new: refcount %u\n", REFCNT_GET(bus->n_ref)); } static int test_bus_open(void) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; r = sd_bus_open_system(&bus); if (r == -ECONNREFUSED || r == -ENOENT) return r; assert_se(r >= 0); printf("after open: refcount %u\n", REFCNT_GET(bus->n_ref)); return 0; } static void test_bus_new_method_call(void) { sd_bus *bus = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; assert_se(sd_bus_open_system(&bus) >= 0); assert_se(sd_bus_message_new_method_call(bus, &m, "a.service.name", "/an/object/path", "an.interface.name", "AMethodName") >= 0); printf("after message_new_method_call: refcount %u\n", REFCNT_GET(bus->n_ref)); sd_bus_flush_close_unref(bus); printf("after bus_flush_close_unref: refcount %u\n", m->n_ref); } static void test_bus_new_signal(void) { sd_bus *bus = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; assert_se(sd_bus_open_system(&bus) >= 0); assert_se(sd_bus_message_new_signal(bus, &m, "/an/object/path", "an.interface.name", "Name") >= 0); printf("after message_new_signal: refcount %u\n", REFCNT_GET(bus->n_ref)); sd_bus_flush_close_unref(bus); printf("after bus_flush_close_unref: refcount %u\n", m->n_ref); } int main(int argc, char **argv) { int r; log_parse_environment(); log_open(); test_bus_new(); r = test_bus_open(); if (r < 0) { log_info("Failed to connect to bus, skipping tests."); return EXIT_TEST_SKIP; } test_bus_new_method_call(); test_bus_new_signal(); return EXIT_SUCCESS; } systemd-229/src/libsystemd/sd-bus/test-bus-creds.c000066400000000000000000000027601265713322000222410ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "bus-dump.h" #include "bus-util.h" #include "cgroup-util.h" int main(int argc, char *argv[]) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; int r; if (cg_unified() == -ENOMEDIUM) { puts("Skipping test: /sys/fs/cgroup/ not available"); return EXIT_TEST_SKIP; } r = sd_bus_creds_new_from_pid(&creds, 0, _SD_BUS_CREDS_ALL); assert_se(r >= 0); bus_creds_dump(creds, NULL, true); creds = sd_bus_creds_unref(creds); r = sd_bus_creds_new_from_pid(&creds, 1, _SD_BUS_CREDS_ALL); if (r != -EACCES) { assert_se(r >= 0); putchar('\n'); bus_creds_dump(creds, NULL, true); } return 0; } systemd-229/src/libsystemd/sd-bus/test-bus-error.c000066400000000000000000000242711265713322000222730ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" #include "errno-list.h" static void test_error(void) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL; const sd_bus_error const_error = SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "const error"); const sd_bus_error temporarily_const_error = { .name = SD_BUS_ERROR_ACCESS_DENIED, .message = "oh! no", ._need_free = -1 }; assert_se(!sd_bus_error_is_set(&error)); assert_se(sd_bus_error_set(&error, SD_BUS_ERROR_NOT_SUPPORTED, "xxx") == -EOPNOTSUPP); assert_se(streq(error.name, SD_BUS_ERROR_NOT_SUPPORTED)); assert_se(streq(error.message, "xxx")); assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_NOT_SUPPORTED)); assert_se(sd_bus_error_get_errno(&error) == EOPNOTSUPP); assert_se(sd_bus_error_is_set(&error)); sd_bus_error_free(&error); /* Check with no error */ assert_se(!sd_bus_error_is_set(&error)); assert_se(sd_bus_error_setf(&error, NULL, "yyy %i", -1) == 0); assert_se(error.name == NULL); assert_se(error.message == NULL); assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); assert_se(sd_bus_error_get_errno(&error) == 0); assert_se(!sd_bus_error_is_set(&error)); assert_se(sd_bus_error_setf(&error, SD_BUS_ERROR_FILE_NOT_FOUND, "yyy %i", -1) == -ENOENT); assert_se(streq(error.name, SD_BUS_ERROR_FILE_NOT_FOUND)); assert_se(streq(error.message, "yyy -1")); assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); assert_se(sd_bus_error_get_errno(&error) == ENOENT); assert_se(sd_bus_error_is_set(&error)); assert_se(!sd_bus_error_is_set(&second)); assert_se(second._need_free == 0); assert_se(error._need_free > 0); assert_se(sd_bus_error_copy(&second, &error) == -ENOENT); assert_se(second._need_free > 0); assert_se(streq(error.name, second.name)); assert_se(streq(error.message, second.message)); assert_se(sd_bus_error_get_errno(&second) == ENOENT); assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_NOT_FOUND)); assert_se(sd_bus_error_is_set(&second)); sd_bus_error_free(&error); sd_bus_error_free(&second); assert_se(!sd_bus_error_is_set(&second)); assert_se(const_error._need_free == 0); assert_se(sd_bus_error_copy(&second, &const_error) == -EEXIST); assert_se(second._need_free == 0); assert_se(streq(const_error.name, second.name)); assert_se(streq(const_error.message, second.message)); assert_se(sd_bus_error_get_errno(&second) == EEXIST); assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_EXISTS)); assert_se(sd_bus_error_is_set(&second)); sd_bus_error_free(&second); assert_se(!sd_bus_error_is_set(&second)); assert_se(temporarily_const_error._need_free < 0); assert_se(sd_bus_error_copy(&second, &temporarily_const_error) == -EACCES); assert_se(second._need_free > 0); assert_se(streq(temporarily_const_error.name, second.name)); assert_se(streq(temporarily_const_error.message, second.message)); assert_se(sd_bus_error_get_errno(&second) == EACCES); assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_ACCESS_DENIED)); assert_se(sd_bus_error_is_set(&second)); assert_se(!sd_bus_error_is_set(&error)); assert_se(sd_bus_error_set_const(&error, "System.Error.EUCLEAN", "Hallo") == -EUCLEAN); assert_se(streq(error.name, "System.Error.EUCLEAN")); assert_se(streq(error.message, "Hallo")); assert_se(sd_bus_error_has_name(&error, "System.Error.EUCLEAN")); assert_se(sd_bus_error_get_errno(&error) == EUCLEAN); assert_se(sd_bus_error_is_set(&error)); sd_bus_error_free(&error); assert_se(!sd_bus_error_is_set(&error)); assert_se(sd_bus_error_set_errno(&error, EBUSY) == -EBUSY); assert_se(streq(error.name, "System.Error.EBUSY")); assert_se(streq(error.message, strerror(EBUSY))); assert_se(sd_bus_error_has_name(&error, "System.Error.EBUSY")); assert_se(sd_bus_error_get_errno(&error) == EBUSY); assert_se(sd_bus_error_is_set(&error)); sd_bus_error_free(&error); assert_se(!sd_bus_error_is_set(&error)); assert_se(sd_bus_error_set_errnof(&error, EIO, "Waldi %c", 'X') == -EIO); assert_se(streq(error.name, SD_BUS_ERROR_IO_ERROR)); assert_se(streq(error.message, "Waldi X")); assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR)); assert_se(sd_bus_error_get_errno(&error) == EIO); assert_se(sd_bus_error_is_set(&error)); sd_bus_error_free(&error); /* Check with no error */ assert_se(!sd_bus_error_is_set(&error)); assert_se(sd_bus_error_set_errnof(&error, 0, "Waldi %c", 'X') == 0); assert_se(error.name == NULL); assert_se(error.message == NULL); assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR)); assert_se(sd_bus_error_get_errno(&error) == 0); assert_se(!sd_bus_error_is_set(&error)); } extern const sd_bus_error_map __start_BUS_ERROR_MAP[]; extern const sd_bus_error_map __stop_BUS_ERROR_MAP[]; static void dump_mapping_table(void) { const sd_bus_error_map *m; printf("----- errno mappings ------\n"); m = __start_BUS_ERROR_MAP; while (m < __stop_BUS_ERROR_MAP) { if (m->code == BUS_ERROR_MAP_END_MARKER) { m = ALIGN8_PTR(m+1); continue; } printf("%s -> %i/%s\n", strna(m->name), m->code, strna(errno_to_name(m->code))); m ++; } printf("---------------------------\n"); } static void test_errno_mapping_standard(void) { assert_se(sd_bus_error_set(NULL, "System.Error.EUCLEAN", NULL) == -EUCLEAN); assert_se(sd_bus_error_set(NULL, "System.Error.EBUSY", NULL) == -EBUSY); assert_se(sd_bus_error_set(NULL, "System.Error.EINVAL", NULL) == -EINVAL); assert_se(sd_bus_error_set(NULL, "System.Error.WHATSIT", NULL) == -EIO); } BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors[] = { SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error", 5), SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-2", 52), SD_BUS_ERROR_MAP_END }; BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors2[] = { SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-3", 33), SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-4", 44), SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-33", 333), SD_BUS_ERROR_MAP_END }; static const sd_bus_error_map test_errors3[] = { SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-88", 888), SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-99", 999), SD_BUS_ERROR_MAP_END }; static const sd_bus_error_map test_errors4[] = { SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-77", 777), SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-78", 778), SD_BUS_ERROR_MAP_END }; static const sd_bus_error_map test_errors_bad1[] = { SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-1", 0), SD_BUS_ERROR_MAP_END }; static const sd_bus_error_map test_errors_bad2[] = { SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-1", -1), SD_BUS_ERROR_MAP_END }; static void test_errno_mapping_custom(void) { assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error", NULL) == -5); assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-2", NULL) == -52); assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-x", NULL) == -EIO); assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-33", NULL) == -333); assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-88", NULL) == -EIO); assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-99", NULL) == -EIO); assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-77", NULL) == -EIO); assert_se(sd_bus_error_add_map(test_errors3) > 0); assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-88", NULL) == -888); assert_se(sd_bus_error_add_map(test_errors4) > 0); assert_se(sd_bus_error_add_map(test_errors4) == 0); assert_se(sd_bus_error_add_map(test_errors3) == 0); assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-99", NULL) == -999); assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-77", NULL) == -777); assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-78", NULL) == -778); assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-2", NULL) == -52); assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-y", NULL) == -EIO); assert_se(sd_bus_error_set(NULL, BUS_ERROR_NO_SUCH_UNIT, NULL) == -ENOENT); assert_se(sd_bus_error_add_map(test_errors_bad1) == -EINVAL); assert_se(sd_bus_error_add_map(test_errors_bad2) == -EINVAL); } int main(int argc, char *argv[]) { dump_mapping_table(); test_error(); test_errno_mapping_standard(); test_errno_mapping_custom(); return 0; } systemd-229/src/libsystemd/sd-bus/test-bus-gvariant.c000066400000000000000000000226131265713322000227530ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #ifdef HAVE_GLIB #include #endif #include "sd-bus.h" #include "alloc-util.h" #include "bus-dump.h" #include "bus-gvariant.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-util.h" #include "macro.h" #include "util.h" static void test_bus_gvariant_is_fixed_size(void) { assert_se(bus_gvariant_is_fixed_size("") > 0); assert_se(bus_gvariant_is_fixed_size("()") > 0); assert_se(bus_gvariant_is_fixed_size("y") > 0); assert_se(bus_gvariant_is_fixed_size("u") > 0); assert_se(bus_gvariant_is_fixed_size("b") > 0); assert_se(bus_gvariant_is_fixed_size("n") > 0); assert_se(bus_gvariant_is_fixed_size("q") > 0); assert_se(bus_gvariant_is_fixed_size("i") > 0); assert_se(bus_gvariant_is_fixed_size("t") > 0); assert_se(bus_gvariant_is_fixed_size("d") > 0); assert_se(bus_gvariant_is_fixed_size("s") == 0); assert_se(bus_gvariant_is_fixed_size("o") == 0); assert_se(bus_gvariant_is_fixed_size("g") == 0); assert_se(bus_gvariant_is_fixed_size("h") > 0); assert_se(bus_gvariant_is_fixed_size("ay") == 0); assert_se(bus_gvariant_is_fixed_size("v") == 0); assert_se(bus_gvariant_is_fixed_size("(u)") > 0); assert_se(bus_gvariant_is_fixed_size("(uuuuy)") > 0); assert_se(bus_gvariant_is_fixed_size("(uusuuy)") == 0); assert_se(bus_gvariant_is_fixed_size("a{ss}") == 0); assert_se(bus_gvariant_is_fixed_size("((u)yyy(b(iiii)))") > 0); assert_se(bus_gvariant_is_fixed_size("((u)yyy(b(iiivi)))") == 0); } static void test_bus_gvariant_get_size(void) { assert_se(bus_gvariant_get_size("") == 0); assert_se(bus_gvariant_get_size("()") == 1); assert_se(bus_gvariant_get_size("y") == 1); assert_se(bus_gvariant_get_size("u") == 4); assert_se(bus_gvariant_get_size("b") == 1); assert_se(bus_gvariant_get_size("n") == 2); assert_se(bus_gvariant_get_size("q") == 2); assert_se(bus_gvariant_get_size("i") == 4); assert_se(bus_gvariant_get_size("t") == 8); assert_se(bus_gvariant_get_size("d") == 8); assert_se(bus_gvariant_get_size("s") < 0); assert_se(bus_gvariant_get_size("o") < 0); assert_se(bus_gvariant_get_size("g") < 0); assert_se(bus_gvariant_get_size("h") == 4); assert_se(bus_gvariant_get_size("ay") < 0); assert_se(bus_gvariant_get_size("v") < 0); assert_se(bus_gvariant_get_size("(u)") == 4); assert_se(bus_gvariant_get_size("(uuuuy)") == 20); assert_se(bus_gvariant_get_size("(uusuuy)") < 0); assert_se(bus_gvariant_get_size("a{ss}") < 0); assert_se(bus_gvariant_get_size("((u)yyy(b(iiii)))") == 28); assert_se(bus_gvariant_get_size("((u)yyy(b(iiivi)))") < 0); assert_se(bus_gvariant_get_size("((b)(t))") == 16); assert_se(bus_gvariant_get_size("((b)(b)(t))") == 16); assert_se(bus_gvariant_get_size("(bt)") == 16); assert_se(bus_gvariant_get_size("((t)(b))") == 16); assert_se(bus_gvariant_get_size("(tb)") == 16); assert_se(bus_gvariant_get_size("((b)(b))") == 2); assert_se(bus_gvariant_get_size("((t)(t))") == 16); } static void test_bus_gvariant_get_alignment(void) { assert_se(bus_gvariant_get_alignment("") == 1); assert_se(bus_gvariant_get_alignment("()") == 1); assert_se(bus_gvariant_get_alignment("y") == 1); assert_se(bus_gvariant_get_alignment("b") == 1); assert_se(bus_gvariant_get_alignment("u") == 4); assert_se(bus_gvariant_get_alignment("s") == 1); assert_se(bus_gvariant_get_alignment("o") == 1); assert_se(bus_gvariant_get_alignment("g") == 1); assert_se(bus_gvariant_get_alignment("v") == 8); assert_se(bus_gvariant_get_alignment("h") == 4); assert_se(bus_gvariant_get_alignment("i") == 4); assert_se(bus_gvariant_get_alignment("t") == 8); assert_se(bus_gvariant_get_alignment("x") == 8); assert_se(bus_gvariant_get_alignment("q") == 2); assert_se(bus_gvariant_get_alignment("n") == 2); assert_se(bus_gvariant_get_alignment("d") == 8); assert_se(bus_gvariant_get_alignment("ay") == 1); assert_se(bus_gvariant_get_alignment("as") == 1); assert_se(bus_gvariant_get_alignment("au") == 4); assert_se(bus_gvariant_get_alignment("an") == 2); assert_se(bus_gvariant_get_alignment("ans") == 2); assert_se(bus_gvariant_get_alignment("ant") == 8); assert_se(bus_gvariant_get_alignment("(ss)") == 1); assert_se(bus_gvariant_get_alignment("(ssu)") == 4); assert_se(bus_gvariant_get_alignment("a(ssu)") == 4); assert_se(bus_gvariant_get_alignment("(u)") == 4); assert_se(bus_gvariant_get_alignment("(uuuuy)") == 4); assert_se(bus_gvariant_get_alignment("(uusuuy)") == 4); assert_se(bus_gvariant_get_alignment("a{ss}") == 1); assert_se(bus_gvariant_get_alignment("((u)yyy(b(iiii)))") == 4); assert_se(bus_gvariant_get_alignment("((u)yyy(b(iiivi)))") == 8); assert_se(bus_gvariant_get_alignment("((b)(t))") == 8); assert_se(bus_gvariant_get_alignment("((b)(b)(t))") == 8); assert_se(bus_gvariant_get_alignment("(bt)") == 8); assert_se(bus_gvariant_get_alignment("((t)(b))") == 8); assert_se(bus_gvariant_get_alignment("(tb)") == 8); assert_se(bus_gvariant_get_alignment("((b)(b))") == 1); assert_se(bus_gvariant_get_alignment("((t)(t))") == 8); } static void test_marshal(void) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *n = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_free_ void *blob; size_t sz; int r; r = sd_bus_open_system(&bus); if (r < 0) exit(EXIT_TEST_SKIP); bus->message_version = 2; /* dirty hack to enable gvariant */ assert_se(sd_bus_message_new_method_call(bus, &m, "a.service.name", "/an/object/path/which/is/really/really/long/so/that/we/hit/the/eight/bit/boundary/by/quite/some/margin/to/test/this/stuff/that/it/really/works", "an.interface.name", "AMethodName") >= 0); assert_cc(sizeof(struct bus_header) == 16); assert_se(sd_bus_message_append(m, "a(usv)", 3, 4711, "first-string-parameter", "(st)", "X", (uint64_t) 1111, 4712, "second-string-parameter", "(a(si))", 2, "Y", 5, "Z", 6, 4713, "third-string-parameter", "(uu)", 1, 2) >= 0); assert_se(bus_message_seal(m, 4711, 0) >= 0); #ifdef HAVE_GLIB { GVariant *v; char *t; #if !defined(GLIB_VERSION_2_36) g_type_init(); #endif v = g_variant_new_from_data(G_VARIANT_TYPE("(yyyyuta{tv})"), m->header, sizeof(struct bus_header) + m->fields_size, false, NULL, NULL); assert_se(g_variant_is_normal_form(v)); t = g_variant_print(v, TRUE); printf("%s\n", t); g_free(t); g_variant_unref(v); v = g_variant_new_from_data(G_VARIANT_TYPE("(a(usv))"), m->body.data, m->user_body_size, false, NULL, NULL); assert_se(g_variant_is_normal_form(v)); t = g_variant_print(v, TRUE); printf("%s\n", t); g_free(t); g_variant_unref(v); } #endif assert_se(bus_message_dump(m, NULL, BUS_MESSAGE_DUMP_WITH_HEADER) >= 0); assert_se(bus_message_get_blob(m, &blob, &sz) >= 0); #ifdef HAVE_GLIB { GVariant *v; char *t; v = g_variant_new_from_data(G_VARIANT_TYPE("(yyyyuta{tv}v)"), blob, sz, false, NULL, NULL); assert_se(g_variant_is_normal_form(v)); t = g_variant_print(v, TRUE); printf("%s\n", t); g_free(t); g_variant_unref(v); } #endif assert_se(bus_message_from_malloc(bus, blob, sz, NULL, 0, NULL, &n) >= 0); blob = NULL; assert_se(bus_message_dump(n, NULL, BUS_MESSAGE_DUMP_WITH_HEADER) >= 0); m = sd_bus_message_unref(m); assert_se(sd_bus_message_new_method_call(bus, &m, "a.x", "/a/x", "a.x", "Ax") >= 0); assert_se(sd_bus_message_append(m, "as", 0) >= 0); assert_se(bus_message_seal(m, 4712, 0) >= 0); assert_se(bus_message_dump(m, NULL, BUS_MESSAGE_DUMP_WITH_HEADER) >= 0); } int main(int argc, char *argv[]) { test_bus_gvariant_is_fixed_size(); test_bus_gvariant_get_size(); test_bus_gvariant_get_alignment(); test_marshal(); return 0; } systemd-229/src/libsystemd/sd-bus/test-bus-introspect.c000066400000000000000000000050171265713322000233310ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-introspect.h" #include "log.h" static int prop_get(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { return -EINVAL; } static int prop_set(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { return -EINVAL; } static const sd_bus_vtable vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_METHOD("Hello", "ssas", "a(uu)", NULL, 0), SD_BUS_METHOD("DeprecatedHello", "", "", NULL, SD_BUS_VTABLE_DEPRECATED), SD_BUS_METHOD("DeprecatedHelloNoReply", "", "", NULL, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_METHOD_NO_REPLY), SD_BUS_SIGNAL("Wowza", "sss", 0), SD_BUS_SIGNAL("DeprecatedWowza", "ut", SD_BUS_VTABLE_DEPRECATED), SD_BUS_WRITABLE_PROPERTY("AProperty", "s", prop_get, prop_set, 0, 0), SD_BUS_PROPERTY("AReadOnlyDeprecatedProperty", "(ut)", prop_get, 0, SD_BUS_VTABLE_DEPRECATED), SD_BUS_PROPERTY("ChangingProperty", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Invalidating", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), SD_BUS_PROPERTY("Constant", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EXPLICIT), SD_BUS_VTABLE_END }; int main(int argc, char *argv[]) { struct introspect intro; log_set_max_level(LOG_DEBUG); assert_se(introspect_begin(&intro, false) >= 0); fprintf(intro.f, " \n"); assert_se(introspect_write_interface(&intro, vtable) >= 0); fputs(" \n", intro.f); fflush(intro.f); fputs(intro.introspection, stdout); introspect_free(&intro); return 0; } systemd-229/src/libsystemd/sd-bus/test-bus-kernel-bloom.c000066400000000000000000000142601265713322000235250ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "alloc-util.h" #include "bus-kernel.h" #include "bus-util.h" #include "fd-util.h" #include "log.h" #include "util.h" static int test_match(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { int *found = userdata; *found = 1; return 0; } static void test_one( const char *path, const char *interface, const char *member, bool as_list, const char *arg0, const char *match, bool good) { _cleanup_close_ int bus_ref = -1; _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; sd_bus *a, *b; int r, found = 0; assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0); bus_ref = bus_kernel_create_bus(name, false, &bus_name); if (bus_ref == -ENOENT) exit(EXIT_TEST_SKIP); assert_se(bus_ref >= 0); address = strappend("kernel:path=", bus_name); assert_se(address); r = sd_bus_new(&a); assert_se(r >= 0); r = sd_bus_new(&b); assert_se(r >= 0); r = sd_bus_set_address(a, address); assert_se(r >= 0); r = sd_bus_set_address(b, address); assert_se(r >= 0); r = sd_bus_start(a); assert_se(r >= 0); r = sd_bus_start(b); assert_se(r >= 0); log_debug("match"); r = sd_bus_add_match(b, NULL, match, test_match, &found); assert_se(r >= 0); log_debug("signal"); if (as_list) r = sd_bus_emit_signal(a, path, interface, member, "as", 1, arg0); else r = sd_bus_emit_signal(a, path, interface, member, "s", arg0); assert_se(r >= 0); r = sd_bus_process(b, &m); assert_se(r >= 0 && good == !!found); sd_bus_unref(a); sd_bus_unref(b); } int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/tuut'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "interface='waldo.com'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "member='Piep'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "member='Pi_ep'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "arg0='foobar'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "arg0='foo_bar'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0='foobar'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0='foo_bar'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0has='foobar'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0has='foo_bar'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar2'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/quux'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar/waldo'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/quux'", false); test_one("/", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar/waldo/'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/bar/waldo", "arg0path='/foo/'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo'", true); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo/bar/waldo'", false); test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/", "arg0path='/foo/bar/waldo'", true); return 0; } systemd-229/src/libsystemd/sd-bus/test-bus-kernel.c000066400000000000000000000132761265713322000224250ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-dump.h" #include "bus-kernel.h" #include "bus-util.h" #include "fd-util.h" #include "log.h" #include "util.h" int main(int argc, char *argv[]) { _cleanup_close_ int bus_ref = -1; _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *bname = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *ua = NULL, *ub = NULL, *the_string = NULL; sd_bus *a, *b; int r, pipe_fds[2]; const char *nn; log_set_max_level(LOG_DEBUG); assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0); bus_ref = bus_kernel_create_bus(name, false, &bus_name); if (bus_ref == -ENOENT) return EXIT_TEST_SKIP; assert_se(bus_ref >= 0); address = strappend("kernel:path=", bus_name); assert_se(address); r = sd_bus_new(&a); assert_se(r >= 0); r = sd_bus_new(&b); assert_se(r >= 0); r = sd_bus_set_description(a, "a"); assert_se(r >= 0); r = sd_bus_set_address(a, address); assert_se(r >= 0); r = sd_bus_set_address(b, address); assert_se(r >= 0); assert_se(sd_bus_negotiate_timestamp(a, 1) >= 0); assert_se(sd_bus_negotiate_creds(a, true, _SD_BUS_CREDS_ALL) >= 0); assert_se(sd_bus_negotiate_timestamp(b, 0) >= 0); assert_se(sd_bus_negotiate_creds(b, true, 0) >= 0); r = sd_bus_start(a); assert_se(r >= 0); r = sd_bus_start(b); assert_se(r >= 0); assert_se(sd_bus_negotiate_timestamp(b, 1) >= 0); assert_se(sd_bus_negotiate_creds(b, true, _SD_BUS_CREDS_ALL) >= 0); r = sd_bus_get_unique_name(a, &ua); assert_se(r >= 0); printf("unique a: %s\n", ua); r = sd_bus_get_description(a, &nn); assert_se(r >= 0); printf("name of a: %s\n", nn); r = sd_bus_get_unique_name(b, &ub); assert_se(r >= 0); printf("unique b: %s\n", ub); r = sd_bus_get_description(b, &nn); assert_se(r >= 0); printf("name of b: %s\n", nn); assert_se(bus_kernel_get_bus_name(b, &bname) >= 0); assert_se(endswith(bname, name)); r = sd_bus_call_method(a, "this.doesnt.exist", "/foo", "meh.mah", "muh", &error, NULL, "s", "yayayay"); assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_SERVICE_UNKNOWN)); assert_se(r == -EHOSTUNREACH); r = sd_bus_add_match(b, NULL, "interface='waldo.com',member='Piep'", NULL, NULL); assert_se(r >= 0); r = sd_bus_emit_signal(a, "/foo/bar/waldo", "waldo.com", "Piep", "sss", "I am a string", "/this/is/a/path", "and.this.a.domain.name"); assert_se(r >= 0); r = sd_bus_try_close(b); assert_se(r == -EBUSY); r = sd_bus_process_priority(b, -10, &m); assert_se(r == 0); r = sd_bus_process(b, &m); assert_se(r > 0); assert_se(m); bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); assert_se(sd_bus_message_rewind(m, true) >= 0); r = sd_bus_message_read(m, "s", &the_string); assert_se(r >= 0); assert_se(streq(the_string, "I am a string")); sd_bus_message_unref(m); m = NULL; r = sd_bus_request_name(a, "net.x0pointer.foobar", 0); assert_se(r >= 0); r = sd_bus_message_new_method_call(b, &m, "net.x0pointer.foobar", "/a/path", "an.inter.face", "AMethod"); assert_se(r >= 0); assert_se(pipe2(pipe_fds, O_CLOEXEC) >= 0); assert_se(write(pipe_fds[1], "x", 1) == 1); pipe_fds[1] = safe_close(pipe_fds[1]); r = sd_bus_message_append(m, "h", pipe_fds[0]); assert_se(r >= 0); pipe_fds[0] = safe_close(pipe_fds[0]); r = sd_bus_send(b, m, NULL); assert_se(r >= 0); for (;;) { sd_bus_message_unref(m); m = NULL; r = sd_bus_process(a, &m); assert_se(r > 0); assert_se(m); bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); assert_se(sd_bus_message_rewind(m, true) >= 0); if (sd_bus_message_is_method_call(m, "an.inter.face", "AMethod")) { int fd; char x; r = sd_bus_message_read(m, "h", &fd); assert_se(r >= 0); assert_se(read(fd, &x, 1) == 1); assert_se(x == 'x'); break; } } r = sd_bus_release_name(a, "net.x0pointer.foobar"); assert_se(r >= 0); r = sd_bus_release_name(a, "net.x0pointer.foobar"); assert_se(r == -ESRCH); r = sd_bus_try_close(a); assert_se(r >= 0); sd_bus_unref(a); sd_bus_unref(b); return 0; } systemd-229/src/libsystemd/sd-bus/test-bus-marshal.c000066400000000000000000000360331265713322000225700ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #ifdef HAVE_GLIB #include #endif #ifdef HAVE_DBUS #include #endif #include "sd-bus.h" #include "alloc-util.h" #include "bus-dump.h" #include "bus-label.h" #include "bus-message.h" #include "bus-util.h" #include "fd-util.h" #include "hexdecoct.h" #include "log.h" #include "util.h" static void test_bus_path_encode_unique(void) { _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL; assert_se(bus_path_encode_unique(NULL, "/foo/bar", "some.sender", "a.suffix", &a) >= 0 && streq_ptr(a, "/foo/bar/some_2esender/a_2esuffix")); assert_se(bus_path_decode_unique(a, "/foo/bar", &b, &c) > 0 && streq_ptr(b, "some.sender") && streq_ptr(c, "a.suffix")); assert_se(bus_path_decode_unique(a, "/bar/foo", &d, &d) == 0 && !d); assert_se(bus_path_decode_unique("/foo/bar/onlyOneSuffix", "/foo/bar", &d, &d) == 0 && !d); assert_se(bus_path_decode_unique("/foo/bar/_/_", "/foo/bar", &d, &e) > 0 && streq_ptr(d, "") && streq_ptr(e, "")); } static void test_bus_path_encode(void) { _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *f = NULL; assert_se(sd_bus_path_encode("/foo/bar", "waldo", &a) >= 0 && streq(a, "/foo/bar/waldo")); assert_se(sd_bus_path_decode(a, "/waldo", &b) == 0 && b == NULL); assert_se(sd_bus_path_decode(a, "/foo/bar", &b) > 0 && streq(b, "waldo")); assert_se(sd_bus_path_encode("xxxx", "waldo", &c) < 0); assert_se(sd_bus_path_encode("/foo/", "waldo", &c) < 0); assert_se(sd_bus_path_encode("/foo/bar", "", &c) >= 0 && streq(c, "/foo/bar/_")); assert_se(sd_bus_path_decode(c, "/foo/bar", &d) > 0 && streq(d, "")); assert_se(sd_bus_path_encode("/foo/bar", "foo.bar", &e) >= 0 && streq(e, "/foo/bar/foo_2ebar")); assert_se(sd_bus_path_decode(e, "/foo/bar", &f) > 0 && streq(f, "foo.bar")); } static void test_bus_path_encode_many(void) { _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *f = NULL; assert_se(sd_bus_path_decode_many("/foo/bar", "/prefix/%", NULL) == 0); assert_se(sd_bus_path_decode_many("/prefix/bar", "/prefix/%bar", NULL) == 1); assert_se(sd_bus_path_decode_many("/foo/bar", "/prefix/%/suffix", NULL) == 0); assert_se(sd_bus_path_decode_many("/prefix/foobar/suffix", "/prefix/%/suffix", &a) == 1 && streq_ptr(a, "foobar")); assert_se(sd_bus_path_decode_many("/prefix/one_foo_two/mid/three_bar_four/suffix", "/prefix/one_%_two/mid/three_%_four/suffix", &b, &c) == 1 && streq_ptr(b, "foo") && streq_ptr(c, "bar")); assert_se(sd_bus_path_decode_many("/prefix/one_foo_two/mid/three_bar_four/suffix", "/prefix/one_%_two/mid/three_%_four/suffix", NULL, &d) == 1 && streq_ptr(d, "bar")); assert_se(sd_bus_path_decode_many("/foo/bar", "/foo/bar/%", NULL) == 0); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/bar%", NULL) == 0); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/bar", NULL) == 0); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%bar", NULL) == 0); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/bar/suffix") == 1); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%%/suffix", NULL, NULL) == 0); /* multiple '%' are treated verbatim */ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/suffi", NULL) == 0); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/suffix", &e) == 1 && streq_ptr(e, "bar")); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/%", NULL, NULL) == 1); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%/%", NULL, NULL, NULL) == 1); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "%/%/%", NULL, NULL, NULL) == 0); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%", NULL, NULL) == 0); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%/", NULL, NULL) == 0); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/", NULL) == 0); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%", NULL) == 0); assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "%", NULL) == 0); assert_se(sd_bus_path_encode_many(&f, "/prefix/one_%_two/mid/three_%_four/suffix", "foo", "bar") >= 0 && streq_ptr(f, "/prefix/one_foo_two/mid/three_bar_four/suffix")); } static void test_bus_label_escape_one(const char *a, const char *b) { _cleanup_free_ char *t = NULL, *x = NULL, *y = NULL; assert_se(t = bus_label_escape(a)); assert_se(streq(t, b)); assert_se(x = bus_label_unescape(t)); assert_se(streq(a, x)); assert_se(y = bus_label_unescape(b)); assert_se(streq(a, y)); } static void test_bus_label_escape(void) { test_bus_label_escape_one("foo123bar", "foo123bar"); test_bus_label_escape_one("foo.bar", "foo_2ebar"); test_bus_label_escape_one("foo_2ebar", "foo_5f2ebar"); test_bus_label_escape_one("", "_"); test_bus_label_escape_one("_", "_5f"); test_bus_label_escape_one("1", "_31"); test_bus_label_escape_one(":1", "_3a1"); } int main(int argc, char *argv[]) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *copy = NULL; int r, boolean; const char *x, *x2, *y, *z, *a, *b, *c, *d, *a_signature; uint8_t u, v; void *buffer = NULL; size_t sz; char *h; const int32_t integer_array[] = { -1, -2, 0, 1, 2 }, *return_array; char *s; _cleanup_free_ char *first = NULL, *second = NULL, *third = NULL; _cleanup_fclose_ FILE *ms = NULL; size_t first_size = 0, second_size = 0, third_size = 0; _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; double dbl; uint64_t u64; r = sd_bus_default_system(&bus); if (r < 0) return EXIT_TEST_SKIP; r = sd_bus_message_new_method_call(bus, &m, "foobar.waldo", "/", "foobar.waldo", "Piep"); assert_se(r >= 0); r = sd_bus_message_append(m, ""); assert_se(r >= 0); r = sd_bus_message_append(m, "s", "a string"); assert_se(r >= 0); r = sd_bus_message_append(m, "s", NULL); assert_se(r >= 0); r = sd_bus_message_append(m, "asg", 2, "string #1", "string #2", "sba(tt)ss"); assert_se(r >= 0); r = sd_bus_message_append(m, "sass", "foobar", 5, "foo", "bar", "waldo", "piep", "pap", "after"); assert_se(r >= 0); r = sd_bus_message_append(m, "a{yv}", 2, 3, "s", "foo", 5, "s", "waldo"); assert_se(r >= 0); r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10); assert_se(r >= 0); r = sd_bus_message_append(m, "()"); assert_se(r >= 0); r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3"); assert_se(r >= 0); r = sd_bus_message_open_container(m, 'a', "s"); assert_se(r >= 0); r = sd_bus_message_append_basic(m, 's', "foobar"); assert_se(r >= 0); r = sd_bus_message_append_basic(m, 's', "waldo"); assert_se(r >= 0); r = sd_bus_message_close_container(m); assert_se(r >= 0); r = sd_bus_message_append_string_space(m, 5, &s); assert_se(r >= 0); strcpy(s, "hallo"); r = sd_bus_message_append_array(m, 'i', integer_array, sizeof(integer_array)); assert_se(r >= 0); r = sd_bus_message_append_array(m, 'u', NULL, 0); assert_se(r >= 0); r = sd_bus_message_append(m, "a(stdo)", 1, "foo", 815ULL, 47.0, "/"); assert_se(r >= 0); r = bus_message_seal(m, 4711, 0); assert_se(r >= 0); bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); ms = open_memstream(&first, &first_size); bus_message_dump(m, ms, 0); fflush(ms); assert_se(!ferror(ms)); r = bus_message_get_blob(m, &buffer, &sz); assert_se(r >= 0); h = hexmem(buffer, sz); assert_se(h); log_info("message size = %zu, contents =\n%s", sz, h); free(h); #ifdef HAVE_GLIB { GDBusMessage *g; char *p; #if !defined(GLIB_VERSION_2_36) g_type_init(); #endif g = g_dbus_message_new_from_blob(buffer, sz, 0, NULL); p = g_dbus_message_print(g, 0); log_info("%s", p); g_free(p); g_object_unref(g); } #endif #ifdef HAVE_DBUS { DBusMessage *w; DBusError error; dbus_error_init(&error); w = dbus_message_demarshal(buffer, sz, &error); if (!w) log_error("%s", error.message); else dbus_message_unref(w); dbus_error_free(&error); } #endif m = sd_bus_message_unref(m); r = bus_message_from_malloc(bus, buffer, sz, NULL, 0, NULL, &m); assert_se(r >= 0); bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); fclose(ms); ms = open_memstream(&second, &second_size); bus_message_dump(m, ms, 0); fflush(ms); assert_se(!ferror(ms)); assert_se(first_size == second_size); assert_se(memcmp(first, second, first_size) == 0); assert_se(sd_bus_message_rewind(m, true) >= 0); r = sd_bus_message_read(m, "ssasg", &x, &x2, 2, &y, &z, &a_signature); assert_se(r > 0); assert_se(streq(x, "a string")); assert_se(streq(x2, "")); assert_se(streq(y, "string #1")); assert_se(streq(z, "string #2")); assert_se(streq(a_signature, "sba(tt)ss")); r = sd_bus_message_read(m, "sass", &x, 5, &y, &z, &a, &b, &c, &d); assert_se(r > 0); assert_se(streq(x, "foobar")); assert_se(streq(y, "foo")); assert_se(streq(z, "bar")); assert_se(streq(a, "waldo")); assert_se(streq(b, "piep")); assert_se(streq(c, "pap")); assert_se(streq(d, "after")); r = sd_bus_message_read(m, "a{yv}", 2, &u, "s", &x, &v, "s", &y); assert_se(r > 0); assert_se(u == 3); assert_se(streq(x, "foo")); assert_se(v == 5); assert_se(streq(y, "waldo")); r = sd_bus_message_read(m, "y(ty)", &v, &u64, &u); assert_se(r > 0); assert_se(v == 8); assert_se(u64 == 777); assert_se(u == 7); r = sd_bus_message_read(m, "y(yt)", &v, &u, &u64); assert_se(r > 0); assert_se(v == 9); assert_se(u == 77); assert_se(u64 == 7777); r = sd_bus_message_read(m, "y", &v); assert_se(r > 0); assert_se(v == 10); r = sd_bus_message_read(m, "()"); assert_se(r > 0); r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d); assert_se(r > 0); assert_se(boolean); assert_se(streq(x, "aaa")); assert_se(streq(y, "1")); assert_se(streq(a, "bbb")); assert_se(streq(b, "2")); assert_se(streq(c, "ccc")); assert_se(streq(d, "3")); assert_se(sd_bus_message_verify_type(m, 'a', "s") > 0); r = sd_bus_message_read(m, "as", 2, &x, &y); assert_se(r > 0); assert_se(streq(x, "foobar")); assert_se(streq(y, "waldo")); r = sd_bus_message_read_basic(m, 's', &s); assert_se(r > 0); assert_se(streq(s, "hallo")); r = sd_bus_message_read_array(m, 'i', (const void**) &return_array, &sz); assert_se(r > 0); assert_se(sz == sizeof(integer_array)); assert_se(memcmp(integer_array, return_array, sz) == 0); r = sd_bus_message_read_array(m, 'u', (const void**) &return_array, &sz); assert_se(r > 0); assert_se(sz == 0); r = sd_bus_message_read(m, "a(stdo)", 1, &x, &u64, &dbl, &y); assert_se(r > 0); assert_se(streq(x, "foo")); assert_se(u64 == 815ULL); assert_se(fabs(dbl - 47.0) < 0.1); assert_se(streq(y, "/")); r = sd_bus_message_peek_type(m, NULL, NULL); assert_se(r == 0); r = sd_bus_message_new_method_call(bus, ©, "foobar.waldo", "/", "foobar.waldo", "Piep"); assert_se(r >= 0); r = sd_bus_message_rewind(m, true); assert_se(r >= 0); r = sd_bus_message_copy(copy, m, true); assert_se(r >= 0); r = bus_message_seal(copy, 4712, 0); assert_se(r >= 0); fclose(ms); ms = open_memstream(&third, &third_size); bus_message_dump(copy, ms, 0); fflush(ms); assert_se(!ferror(ms)); printf("<%.*s>\n", (int) first_size, first); printf("<%.*s>\n", (int) third_size, third); assert_se(first_size == third_size); assert_se(memcmp(first, third, third_size) == 0); r = sd_bus_message_rewind(m, true); assert_se(r >= 0); assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0); r = sd_bus_message_skip(m, "ssasg"); assert_se(r > 0); assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0); r = sd_bus_message_skip(m, "sass"); assert_se(r >= 0); assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0); r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y()"); assert_se(r >= 0); assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0); r = sd_bus_message_read(m, "b", &boolean); assert_se(r > 0); assert_se(boolean); r = sd_bus_message_enter_container(m, 0, NULL); assert_se(r > 0); r = sd_bus_message_read(m, "(ss)", &x, &y); assert_se(r > 0); r = sd_bus_message_read(m, "(ss)", &a, &b); assert_se(r > 0); r = sd_bus_message_read(m, "(ss)", &c, &d); assert_se(r > 0); r = sd_bus_message_read(m, "(ss)", &x, &y); assert_se(r == 0); r = sd_bus_message_exit_container(m); assert_se(r >= 0); assert_se(streq(x, "aaa")); assert_se(streq(y, "1")); assert_se(streq(a, "bbb")); assert_se(streq(b, "2")); assert_se(streq(c, "ccc")); assert_se(streq(d, "3")); test_bus_label_escape(); test_bus_path_encode(); test_bus_path_encode_unique(); test_bus_path_encode_many(); return 0; } systemd-229/src/libsystemd/sd-bus/test-bus-match.c000066400000000000000000000142131265713322000222310ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-match.h" #include "bus-message.h" #include "bus-slot.h" #include "bus-util.h" #include "log.h" #include "macro.h" static bool mask[32]; static int filter(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { log_info("Ran %u", PTR_TO_UINT(userdata)); assert_se(PTR_TO_UINT(userdata) < ELEMENTSOF(mask)); mask[PTR_TO_UINT(userdata)] = true; return 0; } static bool mask_contains(unsigned a[], unsigned n) { unsigned i, j; for (i = 0; i < ELEMENTSOF(mask); i++) { bool found = false; for (j = 0; j < n; j++) if (a[j] == i) { found = true; break; } if (found != mask[i]) return false; } return true; } static int match_add(sd_bus_slot *slots, struct bus_match_node *root, const char *match, int value) { struct bus_match_component *components = NULL; unsigned n_components = 0; sd_bus_slot *s; int r; s = slots + value; zero(*s); r = bus_match_parse(match, &components, &n_components); if (r < 0) return r; s->userdata = INT_TO_PTR(value); s->match_callback.callback = filter; r = bus_match_add(root, components, n_components, &s->match_callback); bus_match_parse_free(components, n_components); return r; } static void test_match_scope(const char *match, enum bus_match_scope scope) { struct bus_match_component *components = NULL; unsigned n_components = 0; assert_se(bus_match_parse(match, &components, &n_components) >= 0); assert_se(bus_match_get_scope(components, n_components) == scope); bus_match_parse_free(components, n_components); } int main(int argc, char *argv[]) { struct bus_match_node root = { .type = BUS_MATCH_ROOT, }; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; enum bus_match_node_type i; sd_bus_slot slots[19]; int r; r = sd_bus_open_system(&bus); if (r < 0) return EXIT_TEST_SKIP; assert_se(match_add(slots, &root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar.x',", 1) >= 0); assert_se(match_add(slots, &root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar.x',", 2) >= 0); assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='signal',interface='bar.x',", 3) >= 0); assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='method_call',interface='bar.x',", 4) >= 0); assert_se(match_add(slots, &root, "", 5) >= 0); assert_se(match_add(slots, &root, "interface='quux.x'", 6) >= 0); assert_se(match_add(slots, &root, "interface='bar.x'", 7) >= 0); assert_se(match_add(slots, &root, "member='waldo',path='/foo/bar'", 8) >= 0); assert_se(match_add(slots, &root, "path='/foo/bar'", 9) >= 0); assert_se(match_add(slots, &root, "path_namespace='/foo'", 10) >= 0); assert_se(match_add(slots, &root, "path_namespace='/foo/quux'", 11) >= 0); assert_se(match_add(slots, &root, "arg1='two'", 12) >= 0); assert_se(match_add(slots, &root, "member='waldo',arg2path='/prefix/'", 13) >= 0); assert_se(match_add(slots, &root, "member=waldo,path='/foo/bar',arg3namespace='prefix'", 14) >= 0); assert_se(match_add(slots, &root, "arg4has='pi'", 15) >= 0); assert_se(match_add(slots, &root, "arg4has='pa'", 16) >= 0); assert_se(match_add(slots, &root, "arg4has='po'", 17) >= 0); assert_se(match_add(slots, &root, "arg4='pi'", 18) >= 0); bus_match_dump(&root, 0); assert_se(sd_bus_message_new_signal(bus, &m, "/foo/bar", "bar.x", "waldo") >= 0); assert_se(sd_bus_message_append(m, "ssssas", "one", "two", "/prefix/three", "prefix.four", 3, "pi", "pa", "po") >= 0); assert_se(bus_message_seal(m, 1, 0) >= 0); zero(mask); assert_se(bus_match_run(NULL, &root, m) == 0); assert_se(mask_contains((unsigned[]) { 9, 8, 7, 5, 10, 12, 13, 14, 15, 16, 17 }, 11)); assert_se(bus_match_remove(&root, &slots[8].match_callback) >= 0); assert_se(bus_match_remove(&root, &slots[13].match_callback) >= 0); bus_match_dump(&root, 0); zero(mask); assert_se(bus_match_run(NULL, &root, m) == 0); assert_se(mask_contains((unsigned[]) { 9, 5, 10, 12, 14, 7, 15, 16, 17 }, 9)); for (i = 0; i < _BUS_MATCH_NODE_TYPE_MAX; i++) { char buf[32]; const char *x; assert_se(x = bus_match_node_type_to_string(i, buf, sizeof(buf))); if (i >= BUS_MATCH_MESSAGE_TYPE) assert_se(bus_match_node_type_from_string(x, strlen(x)) == i); } bus_match_free(&root); test_match_scope("interface='foobar'", BUS_MATCH_GENERIC); test_match_scope("", BUS_MATCH_GENERIC); test_match_scope("interface='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL); test_match_scope("sender='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL); test_match_scope("member='gurke',path='/org/freedesktop/DBus/Local'", BUS_MATCH_LOCAL); test_match_scope("arg2='piep',sender='org.freedesktop.DBus',member='waldo'", BUS_MATCH_DRIVER); return 0; } systemd-229/src/libsystemd/sd-bus/test-bus-objects.c000066400000000000000000000461431265713322000225750ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-dump.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-util.h" #include "log.h" #include "macro.h" #include "strv.h" #include "util.h" struct context { int fds[2]; bool quit; char *something; char *automatic_string_property; uint32_t automatic_integer_property; }; static int something_handler(sd_bus_message *m, void *userdata, sd_bus_error *error) { struct context *c = userdata; const char *s; char *n = NULL; int r; r = sd_bus_message_read(m, "s", &s); assert_se(r > 0); n = strjoin("<<<", s, ">>>", NULL); assert_se(n); free(c->something); c->something = n; log_info("AlterSomething() called, got %s, returning %s", s, n); /* This should fail, since the return type doesn't match */ assert_se(sd_bus_reply_method_return(m, "u", 4711) == -ENOMSG); r = sd_bus_reply_method_return(m, "s", n); assert_se(r >= 0); return 1; } static int exit_handler(sd_bus_message *m, void *userdata, sd_bus_error *error) { struct context *c = userdata; int r; c->quit = true; log_info("Exit called"); r = sd_bus_reply_method_return(m, ""); assert_se(r >= 0); return 1; } static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { struct context *c = userdata; int r; log_info("property get for %s called, returning \"%s\".", property, c->something); r = sd_bus_message_append(reply, "s", c->something); assert_se(r >= 0); return 1; } static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) { struct context *c = userdata; const char *s; char *n; int r; log_info("property set for %s called", property); r = sd_bus_message_read(value, "s", &s); assert_se(r >= 0); n = strdup(s); assert_se(n); free(c->something); c->something = n; return 1; } static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_free_ char *s = NULL; const char *x; int r; assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0); r = sd_bus_message_append(reply, "s", s); assert_se(r >= 0); assert_se(x = startswith(path, "/value/")); assert_se(PTR_TO_UINT(userdata) == 30); return 1; } static int notify_test(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; assert_se(sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL) >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); return 1; } static int notify_test2(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; assert_se(sd_bus_emit_properties_changed_strv(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", NULL) >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); return 1; } static int emit_interfaces_added(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; assert_se(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); return 1; } static int emit_interfaces_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; assert_se(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); return 1; } static int emit_object_added(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), "/value/a/x") >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); return 1; } static int emit_object_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { int r; assert_se(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), "/value/a/x") >= 0); r = sd_bus_reply_method_return(m, NULL); assert_se(r >= 0); return 1; } static const sd_bus_vtable vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_METHOD("AlterSomething", "s", "s", something_handler, 0), SD_BUS_METHOD("Exit", "", "", exit_handler, 0), SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0), SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL, offsetof(struct context, automatic_string_property), 0), SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL, offsetof(struct context, automatic_integer_property), 0), SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0), SD_BUS_METHOD("EmitInterfacesAdded", NULL, NULL, emit_interfaces_added, 0), SD_BUS_METHOD("EmitInterfacesRemoved", NULL, NULL, emit_interfaces_removed, 0), SD_BUS_METHOD("EmitObjectAdded", NULL, NULL, emit_object_added, 0), SD_BUS_METHOD("EmitObjectRemoved", NULL, NULL, emit_object_removed, 0), SD_BUS_VTABLE_END }; static const sd_bus_vtable vtable2[] = { SD_BUS_VTABLE_START(0), SD_BUS_METHOD("NotifyTest", "", "", notify_test, 0), SD_BUS_METHOD("NotifyTest2", "", "", notify_test2, 0), SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0), SD_BUS_PROPERTY("AnExplicitProperty", "s", NULL, offsetof(struct context, something), SD_BUS_VTABLE_PROPERTY_EXPLICIT|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), SD_BUS_VTABLE_END }; static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { if (object_path_startswith("/value", path)) assert_se(*nodes = strv_new("/value/a", "/value/b", "/value/c", NULL)); return 1; } static int enumerator2_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { if (object_path_startswith("/value/a", path)) assert_se(*nodes = strv_new("/value/a/x", "/value/a/y", "/value/a/z", NULL)); return 1; } static void *server(void *p) { struct context *c = p; sd_bus *bus = NULL; sd_id128_t id; int r; c->quit = false; assert_se(sd_id128_randomize(&id) >= 0); assert_se(sd_bus_new(&bus) >= 0); assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0); assert_se(sd_bus_set_server(bus, 1, id) >= 0); assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0); assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0); assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0); assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0); assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/a", enumerator2_callback, NULL) >= 0); assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0); assert_se(sd_bus_add_object_manager(bus, NULL, "/value/a") >= 0); assert_se(sd_bus_start(bus) >= 0); log_error("Entering event loop on server"); while (!c->quit) { log_error("Loop!"); r = sd_bus_process(bus, NULL); if (r < 0) { log_error_errno(r, "Failed to process requests: %m"); goto fail; } if (r == 0) { r = sd_bus_wait(bus, (uint64_t) -1); if (r < 0) { log_error_errno(r, "Failed to wait: %m"); goto fail; } continue; } } r = 0; fail: if (bus) { sd_bus_flush(bus); sd_bus_unref(bus); } return INT_TO_PTR(r); } static int client(struct context *c) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *s; int r; assert_se(sd_bus_new(&bus) >= 0); assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0); assert_se(sd_bus_start(bus) >= 0); r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "NoOperation", &error, NULL, NULL); assert_se(r >= 0); r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "s", "hallo"); assert_se(r >= 0); r = sd_bus_message_read(reply, "s", &s); assert_se(r >= 0); assert_se(streq(s, "<<>>")); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, ""); assert_se(r < 0); assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)); sd_bus_error_free(&error); r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo"); assert_se(r < 0); assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS)); sd_bus_error_free(&error); r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s"); assert_se(r >= 0); r = sd_bus_message_read(reply, "s", &s); assert_se(r >= 0); assert_se(streq(s, "<<>>")); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test"); assert_se(r >= 0); r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s"); assert_se(r >= 0); r = sd_bus_message_read(reply, "s", &s); assert_se(r >= 0); assert_se(streq(s, "test")); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815); assert_se(r >= 0); assert_se(c->automatic_integer_property == 815); r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticStringProperty", &error, "s", "Du Dödel, Du!"); assert_se(r >= 0); assert_se(streq(c->automatic_string_property, "Du Dödel, Du!")); r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); assert_se(r >= 0); r = sd_bus_message_read(reply, "s", &s); assert_se(r >= 0); fputs(s, stdout); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s"); assert_se(r >= 0); r = sd_bus_message_read(reply, "s", &s); assert_se(r >= 0); log_info("read %s", s); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); assert_se(r >= 0); r = sd_bus_message_read(reply, "s", &s); assert_se(r >= 0); fputs(s, stdout); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); assert_se(r >= 0); r = sd_bus_message_read(reply, "s", &s); assert_se(r >= 0); fputs(s, stdout); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); assert_se(r >= 0); r = sd_bus_message_read(reply, "s", &s); assert_se(r >= 0); fputs(s, stdout); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", ""); assert_se(r >= 0); bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2"); assert_se(r < 0); assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_INTERFACE)); sd_bus_error_free(&error); r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, ""); assert_se(r < 0); assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)); sd_bus_error_free(&error); r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, ""); assert_se(r >= 0); bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, ""); assert_se(r >= 0); r = sd_bus_process(bus, &reply); assert_se(r > 0); assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged")); bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest2", &error, NULL, ""); assert_se(r >= 0); r = sd_bus_process(bus, &reply); assert_se(r > 0); assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged")); bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, ""); assert_se(r >= 0); r = sd_bus_process(bus, &reply); assert_se(r > 0); assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded")); bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, ""); assert_se(r >= 0); r = sd_bus_process(bus, &reply); assert_se(r > 0); assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved")); bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectAdded", &error, NULL, ""); assert_se(r >= 0); r = sd_bus_process(bus, &reply); assert_se(r > 0); assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded")); bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectRemoved", &error, NULL, ""); assert_se(r >= 0); r = sd_bus_process(bus, &reply); assert_se(r > 0); assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved")); bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); sd_bus_message_unref(reply); reply = NULL; r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, ""); assert_se(r >= 0); sd_bus_flush(bus); return 0; } int main(int argc, char *argv[]) { struct context c = {}; pthread_t s; void *p; int r, q; zero(c); c.automatic_integer_property = 4711; assert_se(c.automatic_string_property = strdup("dudeldu")); assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0); r = pthread_create(&s, NULL, server, &c); if (r != 0) return -r; r = client(&c); q = pthread_join(s, &p); if (q != 0) return -q; if (r < 0) return r; if (PTR_TO_INT(p) < 0) return PTR_TO_INT(p); free(c.something); free(c.automatic_string_property); return EXIT_SUCCESS; } systemd-229/src/libsystemd/sd-bus/test-bus-proxy.c000066400000000000000000000064201265713322000223170ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 David Herrmann systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-dump.h" #include "bus-kernel.h" #include "bus-util.h" #include "log.h" #include "util.h" typedef struct { const char *sender; int matched_acquired; } TestProxyMatch; static int test_proxy_acquired(sd_bus_message *m, void *userdata, sd_bus_error *error) { TestProxyMatch *match = userdata; const char *name; int r; r = sd_bus_message_read(m, "s", &name); assert_se(r >= 0); if (!streq_ptr(match->sender, name)) return 0; ++match->matched_acquired; return 1; } static void test_proxy_matched(void) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *a = NULL; _cleanup_free_ char *matchstr = NULL; TestProxyMatch match = {}; const char *me; int r; /* open bus 'a' */ r = sd_bus_new(&a); assert_se(r >= 0); r = sd_bus_set_address(a, "unix:path=/var/run/dbus/system_bus_socket"); assert_se(r >= 0); r = sd_bus_set_bus_client(a, true); assert_se(r >= 0); r = sd_bus_start(a); assert_se(r >= 0); r = sd_bus_get_unique_name(a, &me); assert_se(r >= 0); matchstr = strjoin("type='signal'," "member='NameAcquired'," "destination='", me, "'", NULL); assert_se(matchstr); r = sd_bus_add_match(a, NULL, matchstr, test_proxy_acquired, &match); assert_se(r >= 0); r = sd_bus_get_unique_name(a, &match.sender); assert_se(r >= 0); /* barrier to guarantee proxy/dbus-daemon handled the previous data */ r = sd_bus_call_method(a, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetId", NULL, NULL, NULL); assert_se(r >= 0); /* now we can be sure the Name* signals were sent */ do { r = sd_bus_process(a, NULL); } while (r > 0); assert_se(r == 0); assert_se(match.matched_acquired == 1); } int main(int argc, char **argv) { if (access("/var/run/dbus/system_bus_socket", F_OK) < 0) return EXIT_TEST_SKIP; log_parse_environment(); test_proxy_matched(); return EXIT_SUCCESS; } systemd-229/src/libsystemd/sd-bus/test-bus-server.c000066400000000000000000000150261265713322000224460ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-bus.h" #include "bus-internal.h" #include "bus-util.h" #include "log.h" #include "macro.h" #include "util.h" struct context { int fds[2]; bool client_negotiate_unix_fds; bool server_negotiate_unix_fds; bool client_anonymous_auth; bool server_anonymous_auth; }; static void *server(void *p) { struct context *c = p; sd_bus *bus = NULL; sd_id128_t id; bool quit = false; int r; assert_se(sd_id128_randomize(&id) >= 0); assert_se(sd_bus_new(&bus) >= 0); assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0); assert_se(sd_bus_set_server(bus, 1, id) >= 0); assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0); assert_se(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0); assert_se(sd_bus_start(bus) >= 0); while (!quit) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; r = sd_bus_process(bus, &m); if (r < 0) { log_error_errno(r, "Failed to process requests: %m"); goto fail; } if (r == 0) { r = sd_bus_wait(bus, (uint64_t) -1); if (r < 0) { log_error_errno(r, "Failed to wait: %m"); goto fail; } continue; } if (!m) continue; log_info("Got message! member=%s", strna(sd_bus_message_get_member(m))); if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) { assert_se((sd_bus_can_send(bus, 'h') >= 1) == (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds)); r = sd_bus_message_new_method_return(m, &reply); if (r < 0) { log_error_errno(r, "Failed to allocate return: %m"); goto fail; } quit = true; } else if (sd_bus_message_is_method_call(m, NULL, NULL)) { r = sd_bus_message_new_method_error( m, &reply, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method.")); if (r < 0) { log_error_errno(r, "Failed to allocate return: %m"); goto fail; } } if (reply) { r = sd_bus_send(bus, reply, NULL); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } } } r = 0; fail: if (bus) { sd_bus_flush(bus); sd_bus_unref(bus); } return INT_TO_PTR(r); } static int client(struct context *c) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert_se(sd_bus_new(&bus) >= 0); assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0); assert_se(sd_bus_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0); assert_se(sd_bus_set_anonymous(bus, c->client_anonymous_auth) >= 0); assert_se(sd_bus_start(bus) >= 0); r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd.test", "/", "org.freedesktop.systemd.test", "Exit"); if (r < 0) return log_error_errno(r, "Failed to allocate method call: %m"); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) { log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); return r; } return 0; } static int test_one(bool client_negotiate_unix_fds, bool server_negotiate_unix_fds, bool client_anonymous_auth, bool server_anonymous_auth) { struct context c; pthread_t s; void *p; int r, q; zero(c); assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0); c.client_negotiate_unix_fds = client_negotiate_unix_fds; c.server_negotiate_unix_fds = server_negotiate_unix_fds; c.client_anonymous_auth = client_anonymous_auth; c.server_anonymous_auth = server_anonymous_auth; r = pthread_create(&s, NULL, server, &c); if (r != 0) return -r; r = client(&c); q = pthread_join(s, &p); if (q != 0) return -q; if (r < 0) return r; if (PTR_TO_INT(p) < 0) return PTR_TO_INT(p); return 0; } int main(int argc, char *argv[]) { int r; r = test_one(true, true, false, false); assert_se(r >= 0); r = test_one(true, false, false, false); assert_se(r >= 0); r = test_one(false, true, false, false); assert_se(r >= 0); r = test_one(false, false, false, false); assert_se(r >= 0); r = test_one(true, true, true, true); assert_se(r >= 0); r = test_one(true, true, false, true); assert_se(r >= 0); r = test_one(true, true, true, false); assert_se(r == -EPERM); return EXIT_SUCCESS; } systemd-229/src/libsystemd/sd-bus/test-bus-signature.c000066400000000000000000000165131265713322000231430ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bus-internal.h" #include "bus-signature.h" #include "log.h" #include "string-util.h" int main(int argc, char *argv[]) { char prefix[256]; int r; assert_se(signature_is_single("y", false)); assert_se(signature_is_single("u", false)); assert_se(signature_is_single("v", false)); assert_se(signature_is_single("as", false)); assert_se(signature_is_single("(ss)", false)); assert_se(signature_is_single("()", false)); assert_se(signature_is_single("(()()()()())", false)); assert_se(signature_is_single("(((())))", false)); assert_se(signature_is_single("((((s))))", false)); assert_se(signature_is_single("{ss}", true)); assert_se(signature_is_single("a{ss}", false)); assert_se(!signature_is_single("uu", false)); assert_se(!signature_is_single("", false)); assert_se(!signature_is_single("(", false)); assert_se(!signature_is_single(")", false)); assert_se(!signature_is_single("())", false)); assert_se(!signature_is_single("((())", false)); assert_se(!signature_is_single("{)", false)); assert_se(!signature_is_single("{}", true)); assert_se(!signature_is_single("{sss}", true)); assert_se(!signature_is_single("{s}", true)); assert_se(!signature_is_single("{ss}", false)); assert_se(!signature_is_single("{ass}", true)); assert_se(!signature_is_single("a}", true)); assert_se(signature_is_pair("yy")); assert_se(signature_is_pair("ss")); assert_se(signature_is_pair("sas")); assert_se(signature_is_pair("sv")); assert_se(signature_is_pair("sa(vs)")); assert_se(!signature_is_pair("")); assert_se(!signature_is_pair("va")); assert_se(!signature_is_pair("sss")); assert_se(!signature_is_pair("{s}ss")); assert_se(signature_is_valid("ssa{ss}sssub", true)); assert_se(signature_is_valid("ssa{ss}sssub", false)); assert_se(signature_is_valid("{ss}", true)); assert_se(!signature_is_valid("{ss}", false)); assert_se(signature_is_valid("", true)); assert_se(signature_is_valid("", false)); assert_se(signature_is_valid("sssusa(uuubbba(uu)uuuu)a{u(uuuvas)}", false)); assert_se(!signature_is_valid("a", false)); assert_se(signature_is_valid("as", false)); assert_se(signature_is_valid("aas", false)); assert_se(signature_is_valid("aaas", false)); assert_se(signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad", false)); assert_se(signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas", false)); assert_se(!signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaau", false)); assert_se(signature_is_valid("(((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))", false)); assert_se(!signature_is_valid("((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))", false)); assert_se(namespace_complex_pattern("", "")); assert_se(namespace_complex_pattern("foobar", "foobar")); assert_se(namespace_complex_pattern("foobar.waldo", "foobar.waldo")); assert_se(namespace_complex_pattern("foobar.", "foobar.waldo")); assert_se(namespace_complex_pattern("foobar.waldo", "foobar.")); assert_se(!namespace_complex_pattern("foobar.waldo", "foobar")); assert_se(!namespace_complex_pattern("foobar", "foobar.waldo")); assert_se(!namespace_complex_pattern("", "foo")); assert_se(!namespace_complex_pattern("foo", "")); assert_se(!namespace_complex_pattern("foo.", "")); assert_se(path_complex_pattern("", "")); assert_se(!path_complex_pattern("", "/")); assert_se(!path_complex_pattern("/", "")); assert_se(path_complex_pattern("/", "/")); assert_se(path_complex_pattern("/foobar/", "/")); assert_se(!path_complex_pattern("/foobar/", "/foobar")); assert_se(path_complex_pattern("/foobar", "/foobar")); assert_se(!path_complex_pattern("/foobar", "/foobar/")); assert_se(!path_complex_pattern("/foobar", "/foobar/waldo")); assert_se(path_complex_pattern("/foobar/", "/foobar/waldo")); assert_se(path_complex_pattern("/foobar/waldo", "/foobar/")); assert_se(path_simple_pattern("/foo/", "/foo/bar/waldo")); assert_se(namespace_simple_pattern("", "")); assert_se(namespace_simple_pattern("", ".foobar")); assert_se(namespace_simple_pattern("foobar", "foobar")); assert_se(namespace_simple_pattern("foobar.waldo", "foobar.waldo")); assert_se(namespace_simple_pattern("foobar", "foobar.waldo")); assert_se(!namespace_simple_pattern("foobar.waldo", "foobar")); assert_se(!namespace_simple_pattern("", "foo")); assert_se(!namespace_simple_pattern("foo", "")); assert_se(namespace_simple_pattern("foo.", "foo.bar.waldo")); assert_se(streq(object_path_startswith("/foo/bar", "/foo"), "bar")); assert_se(streq(object_path_startswith("/foo", "/foo"), "")); assert_se(streq(object_path_startswith("/foo", "/"), "foo")); assert_se(streq(object_path_startswith("/", "/"), "")); assert_se(!object_path_startswith("/foo", "/bar")); assert_se(!object_path_startswith("/", "/bar")); assert_se(!object_path_startswith("/foo", "")); assert_se(object_path_is_valid("/foo/bar")); assert_se(object_path_is_valid("/foo")); assert_se(object_path_is_valid("/")); assert_se(object_path_is_valid("/foo5")); assert_se(object_path_is_valid("/foo_5")); assert_se(!object_path_is_valid("")); assert_se(!object_path_is_valid("/foo/")); assert_se(!object_path_is_valid("//")); assert_se(!object_path_is_valid("//foo")); assert_se(!object_path_is_valid("/foo//bar")); assert_se(!object_path_is_valid("/foo/aaaäöä")); OBJECT_PATH_FOREACH_PREFIX(prefix, "/") { log_info("<%s>", prefix); assert_not_reached("???"); } r = 0; OBJECT_PATH_FOREACH_PREFIX(prefix, "/xxx") { log_info("<%s>", prefix); assert_se(streq(prefix, "/")); assert_se(r == 0); r++; } assert_se(r == 1); r = 0; OBJECT_PATH_FOREACH_PREFIX(prefix, "/xxx/yyy/zzz") { log_info("<%s>", prefix); assert_se(r != 0 || streq(prefix, "/xxx/yyy")); assert_se(r != 1 || streq(prefix, "/xxx")); assert_se(r != 2 || streq(prefix, "/")); r++; } assert_se(r == 3); return 0; } systemd-229/src/libsystemd/sd-bus/test-bus-zero-copy.c000066400000000000000000000131111265713322000230600ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-dump.h" #include "bus-kernel.h" #include "bus-message.h" #include "fd-util.h" #include "log.h" #include "memfd-util.h" #include "string-util.h" #include "util.h" #define FIRST_ARRAY 17 #define SECOND_ARRAY 33 #define STRING_SIZE 123 int main(int argc, char *argv[]) { _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL; const char *unique; uint8_t *p; sd_bus *a, *b; int r, bus_ref; sd_bus_message *m; int f; uint64_t sz; uint32_t u32; size_t i, l; char *s; _cleanup_close_ int sfd = -1; log_set_max_level(LOG_DEBUG); assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0); bus_ref = bus_kernel_create_bus(name, false, &bus_name); if (bus_ref == -ENOENT) return EXIT_TEST_SKIP; assert_se(bus_ref >= 0); address = strappend("kernel:path=", bus_name); assert_se(address); r = sd_bus_new(&a); assert_se(r >= 0); r = sd_bus_new(&b); assert_se(r >= 0); r = sd_bus_set_address(a, address); assert_se(r >= 0); r = sd_bus_set_address(b, address); assert_se(r >= 0); r = sd_bus_start(a); assert_se(r >= 0); r = sd_bus_start(b); assert_se(r >= 0); r = sd_bus_get_unique_name(a, &unique); assert_se(r >= 0); r = sd_bus_message_new_method_call(b, &m, unique, "/a/path", "an.inter.face", "AMethod"); assert_se(r >= 0); r = sd_bus_message_open_container(m, 'r', "aysay"); assert_se(r >= 0); r = sd_bus_message_append_array_space(m, 'y', FIRST_ARRAY, (void**) &p); assert_se(r >= 0); p[0] = '<'; memset(p+1, 'L', FIRST_ARRAY-2); p[FIRST_ARRAY-1] = '>'; f = memfd_new_and_map(NULL, STRING_SIZE, (void**) &s); assert_se(f >= 0); s[0] = '<'; for (i = 1; i < STRING_SIZE-2; i++) s[i] = '0' + (i % 10); s[STRING_SIZE-2] = '>'; s[STRING_SIZE-1] = 0; munmap(s, STRING_SIZE); r = memfd_get_size(f, &sz); assert_se(r >= 0); assert_se(sz == STRING_SIZE); r = sd_bus_message_append_string_memfd(m, f, 0, (uint64_t) -1); assert_se(r >= 0); close(f); f = memfd_new_and_map(NULL, SECOND_ARRAY, (void**) &p); assert_se(f >= 0); p[0] = '<'; memset(p+1, 'P', SECOND_ARRAY-2); p[SECOND_ARRAY-1] = '>'; munmap(p, SECOND_ARRAY); r = memfd_get_size(f, &sz); assert_se(r >= 0); assert_se(sz == SECOND_ARRAY); r = sd_bus_message_append_array_memfd(m, 'y', f, 0, (uint64_t) -1); assert_se(r >= 0); close(f); r = sd_bus_message_close_container(m); assert_se(r >= 0); r = sd_bus_message_append(m, "u", 4711); assert_se(r >= 0); assert_se((sfd = memfd_new_and_map(NULL, 6, (void**) &p)) >= 0); memcpy(p, "abcd\0", 6); munmap(p, 6); assert_se(sd_bus_message_append_string_memfd(m, sfd, 1, 4) >= 0); r = bus_message_seal(m, 55, 99*USEC_PER_SEC); assert_se(r >= 0); bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); r = sd_bus_send(b, m, NULL); assert_se(r >= 0); sd_bus_message_unref(m); r = sd_bus_process(a, &m); assert_se(r > 0); bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); sd_bus_message_rewind(m, true); r = sd_bus_message_enter_container(m, 'r', "aysay"); assert_se(r > 0); r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l); assert_se(r > 0); assert_se(l == FIRST_ARRAY); assert_se(p[0] == '<'); for (i = 1; i < l-1; i++) assert_se(p[i] == 'L'); assert_se(p[l-1] == '>'); r = sd_bus_message_read(m, "s", &s); assert_se(r > 0); assert_se(s[0] == '<'); for (i = 1; i < STRING_SIZE-2; i++) assert_se(s[i] == (char) ('0' + (i % 10))); assert_se(s[STRING_SIZE-2] == '>'); assert_se(s[STRING_SIZE-1] == 0); r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l); assert_se(r > 0); assert_se(l == SECOND_ARRAY); assert_se(p[0] == '<'); for (i = 1; i < l-1; i++) assert_se(p[i] == 'P'); assert_se(p[l-1] == '>'); r = sd_bus_message_exit_container(m); assert_se(r > 0); r = sd_bus_message_read(m, "u", &u32); assert_se(r > 0); assert_se(u32 == 4711); r = sd_bus_message_read(m, "s", &s); assert_se(r > 0); assert_se(streq_ptr(s, "bcd")); sd_bus_message_unref(m); sd_bus_unref(a); sd_bus_unref(b); return 0; } systemd-229/src/libsystemd/sd-daemon/000077500000000000000000000000001265713322000176765ustar00rootroot00000000000000systemd-229/src/libsystemd/sd-daemon/Makefile000077700000000000000000000000001265713322000232042../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd/sd-daemon/sd-daemon.c000066400000000000000000000417661265713322000217270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sd-daemon.h" #include "alloc-util.h" #include "fd-util.h" #include "fs-util.h" #include "parse-util.h" #include "path-util.h" #include "socket-util.h" #include "strv.h" #include "util.h" #define SNDBUF_SIZE (8*1024*1024) static void unsetenv_all(bool unset_environment) { if (!unset_environment) return; unsetenv("LISTEN_PID"); unsetenv("LISTEN_FDS"); unsetenv("LISTEN_FDNAMES"); } _public_ int sd_listen_fds(int unset_environment) { const char *e; int n, r, fd; pid_t pid; e = getenv("LISTEN_PID"); if (!e) { r = 0; goto finish; } r = parse_pid(e, &pid); if (r < 0) goto finish; /* Is this for us? */ if (getpid() != pid) { r = 0; goto finish; } e = getenv("LISTEN_FDS"); if (!e) { r = 0; goto finish; } r = safe_atoi(e, &n); if (r < 0) goto finish; assert_cc(SD_LISTEN_FDS_START < INT_MAX); if (n <= 0 || n > INT_MAX - SD_LISTEN_FDS_START) { r = -EINVAL; goto finish; } for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) { r = fd_cloexec(fd, true); if (r < 0) goto finish; } r = n; finish: unsetenv_all(unset_environment); return r; } _public_ int sd_listen_fds_with_names(int unset_environment, char ***names) { _cleanup_strv_free_ char **l = NULL; bool have_names; int n_names = 0, n_fds; const char *e; int r; if (!names) return sd_listen_fds(unset_environment); e = getenv("LISTEN_FDNAMES"); if (e) { n_names = strv_split_extract(&l, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS); if (n_names < 0) { unsetenv_all(unset_environment); return n_names; } have_names = true; } else have_names = false; n_fds = sd_listen_fds(unset_environment); if (n_fds <= 0) return n_fds; if (have_names) { if (n_names != n_fds) return -EINVAL; } else { r = strv_extend_n(&l, "unknown", n_fds); if (r < 0) return r; } *names = l; l = NULL; return n_fds; } _public_ int sd_is_fifo(int fd, const char *path) { struct stat st_fd; assert_return(fd >= 0, -EBADF); if (fstat(fd, &st_fd) < 0) return -errno; if (!S_ISFIFO(st_fd.st_mode)) return 0; if (path) { struct stat st_path; if (stat(path, &st_path) < 0) { if (errno == ENOENT || errno == ENOTDIR) return 0; return -errno; } return st_path.st_dev == st_fd.st_dev && st_path.st_ino == st_fd.st_ino; } return 1; } _public_ int sd_is_special(int fd, const char *path) { struct stat st_fd; assert_return(fd >= 0, -EBADF); if (fstat(fd, &st_fd) < 0) return -errno; if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode)) return 0; if (path) { struct stat st_path; if (stat(path, &st_path) < 0) { if (errno == ENOENT || errno == ENOTDIR) return 0; return -errno; } if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode)) return st_path.st_dev == st_fd.st_dev && st_path.st_ino == st_fd.st_ino; else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode)) return st_path.st_rdev == st_fd.st_rdev; else return 0; } return 1; } static int sd_is_socket_internal(int fd, int type, int listening) { struct stat st_fd; assert_return(fd >= 0, -EBADF); assert_return(type >= 0, -EINVAL); if (fstat(fd, &st_fd) < 0) return -errno; if (!S_ISSOCK(st_fd.st_mode)) return 0; if (type != 0) { int other_type = 0; socklen_t l = sizeof(other_type); if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0) return -errno; if (l != sizeof(other_type)) return -EINVAL; if (other_type != type) return 0; } if (listening >= 0) { int accepting = 0; socklen_t l = sizeof(accepting); if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0) return -errno; if (l != sizeof(accepting)) return -EINVAL; if (!accepting != !listening) return 0; } return 1; } _public_ int sd_is_socket(int fd, int family, int type, int listening) { int r; assert_return(fd >= 0, -EBADF); assert_return(family >= 0, -EINVAL); r = sd_is_socket_internal(fd, type, listening); if (r <= 0) return r; if (family > 0) { union sockaddr_union sockaddr = {}; socklen_t l = sizeof(sockaddr); if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; if (l < sizeof(sa_family_t)) return -EINVAL; return sockaddr.sa.sa_family == family; } return 1; } _public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { union sockaddr_union sockaddr = {}; socklen_t l = sizeof(sockaddr); int r; assert_return(fd >= 0, -EBADF); assert_return(IN_SET(family, 0, AF_INET, AF_INET6), -EINVAL); r = sd_is_socket_internal(fd, type, listening); if (r <= 0) return r; if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; if (l < sizeof(sa_family_t)) return -EINVAL; if (sockaddr.sa.sa_family != AF_INET && sockaddr.sa.sa_family != AF_INET6) return 0; if (family != 0) if (sockaddr.sa.sa_family != family) return 0; if (port > 0) { if (sockaddr.sa.sa_family == AF_INET) { if (l < sizeof(struct sockaddr_in)) return -EINVAL; return htons(port) == sockaddr.in.sin_port; } else { if (l < sizeof(struct sockaddr_in6)) return -EINVAL; return htons(port) == sockaddr.in6.sin6_port; } } return 1; } _public_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { union sockaddr_union sockaddr = {}; socklen_t l = sizeof(sockaddr); int r; assert_return(fd >= 0, -EBADF); r = sd_is_socket_internal(fd, type, listening); if (r <= 0) return r; if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; if (l < sizeof(sa_family_t)) return -EINVAL; if (sockaddr.sa.sa_family != AF_UNIX) return 0; if (path) { if (length == 0) length = strlen(path); if (length == 0) /* Unnamed socket */ return l == offsetof(struct sockaddr_un, sun_path); if (path[0]) /* Normal path socket */ return (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) && memcmp(path, sockaddr.un.sun_path, length+1) == 0; else /* Abstract namespace socket */ return (l == offsetof(struct sockaddr_un, sun_path) + length) && memcmp(path, sockaddr.un.sun_path, length) == 0; } return 1; } _public_ int sd_is_mq(int fd, const char *path) { struct mq_attr attr; /* Check that the fd is valid */ assert_return(fcntl(fd, F_GETFD) >= 0, -errno); if (mq_getattr(fd, &attr) < 0) { if (errno == EBADF) /* A non-mq fd (or an invalid one, but we ruled that out above) */ return 0; return -errno; } if (path) { char fpath[PATH_MAX]; struct stat a, b; assert_return(path_is_absolute(path), -EINVAL); if (fstat(fd, &a) < 0) return -errno; strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12); fpath[sizeof(fpath)-1] = 0; if (stat(fpath, &b) < 0) return -errno; if (a.st_dev != b.st_dev || a.st_ino != b.st_ino) return 0; } return 1; } _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char *state, const int *fds, unsigned n_fds) { union sockaddr_union sockaddr = { .sa.sa_family = AF_UNIX, }; struct iovec iovec = { .iov_base = (char*) state, }; struct msghdr msghdr = { .msg_iov = &iovec, .msg_iovlen = 1, .msg_name = &sockaddr, }; _cleanup_close_ int fd = -1; struct cmsghdr *cmsg = NULL; const char *e; bool have_pid; int r; if (!state) { r = -EINVAL; goto finish; } if (n_fds > 0 && !fds) { r = -EINVAL; goto finish; } e = getenv("NOTIFY_SOCKET"); if (!e) return 0; /* Must be an abstract socket, or an absolute path */ if ((e[0] != '@' && e[0] != '/') || e[1] == 0) { r = -EINVAL; goto finish; } if (strlen(e) > sizeof(sockaddr.un.sun_path)) { r = -EINVAL; goto finish; } fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); if (fd < 0) { r = -errno; goto finish; } fd_inc_sndbuf(fd, SNDBUF_SIZE); iovec.iov_len = strlen(state); strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path)); if (sockaddr.un.sun_path[0] == '@') sockaddr.un.sun_path[0] = 0; msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e); if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) msghdr.msg_namelen = sizeof(struct sockaddr_un); have_pid = pid != 0 && pid != getpid(); if (n_fds > 0 || have_pid) { /* CMSG_SPACE(0) may return value different then zero, which results in miscalculated controllen. */ msghdr.msg_controllen = (n_fds > 0 ? CMSG_SPACE(sizeof(int) * n_fds) : 0) + (have_pid ? CMSG_SPACE(sizeof(struct ucred)) : 0); msghdr.msg_control = alloca0(msghdr.msg_controllen); cmsg = CMSG_FIRSTHDR(&msghdr); if (n_fds > 0) { cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int) * n_fds); memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * n_fds); if (have_pid) assert_se(cmsg = CMSG_NXTHDR(&msghdr, cmsg)); } if (have_pid) { struct ucred *ucred; cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_CREDENTIALS; cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); ucred = (struct ucred*) CMSG_DATA(cmsg); ucred->pid = pid; ucred->uid = getuid(); ucred->gid = getgid(); } } /* First try with fake ucred data, as requested */ if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) { r = 1; goto finish; } /* If that failed, try with our own ucred instead */ if (have_pid) { msghdr.msg_controllen -= CMSG_SPACE(sizeof(struct ucred)); if (msghdr.msg_controllen == 0) msghdr.msg_control = NULL; if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) { r = 1; goto finish; } } r = -errno; finish: if (unset_environment) unsetenv("NOTIFY_SOCKET"); return r; } _public_ int sd_pid_notify(pid_t pid, int unset_environment, const char *state) { return sd_pid_notify_with_fds(pid, unset_environment, state, NULL, 0); } _public_ int sd_notify(int unset_environment, const char *state) { return sd_pid_notify_with_fds(0, unset_environment, state, NULL, 0); } _public_ int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...) { _cleanup_free_ char *p = NULL; int r; if (format) { va_list ap; va_start(ap, format); r = vasprintf(&p, format, ap); va_end(ap); if (r < 0 || !p) return -ENOMEM; } return sd_pid_notify(pid, unset_environment, p); } _public_ int sd_notifyf(int unset_environment, const char *format, ...) { _cleanup_free_ char *p = NULL; int r; if (format) { va_list ap; va_start(ap, format); r = vasprintf(&p, format, ap); va_end(ap); if (r < 0 || !p) return -ENOMEM; } return sd_pid_notify(0, unset_environment, p); } _public_ int sd_booted(void) { /* We test whether the runtime unit file directory has been * created. This takes place in mount-setup.c, so is * guaranteed to happen very early during boot. */ return laccess("/run/systemd/system/", F_OK) >= 0; } _public_ int sd_watchdog_enabled(int unset_environment, uint64_t *usec) { const char *s, *p = ""; /* p is set to dummy value to do unsetting */ uint64_t u; int r = 0; s = getenv("WATCHDOG_USEC"); if (!s) goto finish; r = safe_atou64(s, &u); if (r < 0) goto finish; if (u <= 0 || u >= USEC_INFINITY) { r = -EINVAL; goto finish; } p = getenv("WATCHDOG_PID"); if (p) { pid_t pid; r = parse_pid(p, &pid); if (r < 0) goto finish; /* Is this for us? */ if (getpid() != pid) { r = 0; goto finish; } } if (usec) *usec = u; r = 1; finish: if (unset_environment && s) unsetenv("WATCHDOG_USEC"); if (unset_environment && p) unsetenv("WATCHDOG_PID"); return r; } systemd-229/src/libsystemd/sd-device/000077500000000000000000000000001265713322000176725ustar00rootroot00000000000000systemd-229/src/libsystemd/sd-device/Makefile000077700000000000000000000000001265713322000232002../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd/sd-device/device-enumerator-private.h000066400000000000000000000027131265713322000251340ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-device.h" int device_enumerator_scan_devices(sd_device_enumerator *enumeartor); int device_enumerator_scan_subsystems(sd_device_enumerator *enumeartor); int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device); int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator); sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator); sd_device *device_enumerator_get_next(sd_device_enumerator *enumerator); #define FOREACH_DEVICE_AND_SUBSYSTEM(enumerator, device) \ for (device = device_enumerator_get_first(enumerator); \ device; \ device = device_enumerator_get_next(enumerator)) systemd-229/src/libsystemd/sd-device/device-enumerator.c000066400000000000000000000715251265713322000234660ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers Copyright 2014-2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-device.h" #include "alloc-util.h" #include "device-enumerator-private.h" #include "device-util.h" #include "dirent-util.h" #include "fd-util.h" #include "prioq.h" #include "set.h" #include "string-util.h" #include "strv.h" #include "util.h" #define DEVICE_ENUMERATE_MAX_DEPTH 256 typedef enum DeviceEnumerationType { DEVICE_ENUMERATION_TYPE_DEVICES, DEVICE_ENUMERATION_TYPE_SUBSYSTEMS, _DEVICE_ENUMERATION_TYPE_MAX, _DEVICE_ENUMERATION_TYPE_INVALID = -1, } DeviceEnumerationType; struct sd_device_enumerator { unsigned n_ref; DeviceEnumerationType type; Prioq *devices; bool scan_uptodate; Set *match_subsystem; Set *nomatch_subsystem; Hashmap *match_sysattr; Hashmap *nomatch_sysattr; Hashmap *match_property; Set *match_sysname; Set *match_tag; sd_device *match_parent; bool match_allow_uninitialized; }; _public_ int sd_device_enumerator_new(sd_device_enumerator **ret) { _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *enumerator = NULL; assert(ret); enumerator = new0(sd_device_enumerator, 1); if (!enumerator) return -ENOMEM; enumerator->n_ref = 1; enumerator->type = _DEVICE_ENUMERATION_TYPE_INVALID; *ret = enumerator; enumerator = NULL; return 0; } _public_ sd_device_enumerator *sd_device_enumerator_ref(sd_device_enumerator *enumerator) { assert_return(enumerator, NULL); assert_se((++ enumerator->n_ref) >= 2); return enumerator; } _public_ sd_device_enumerator *sd_device_enumerator_unref(sd_device_enumerator *enumerator) { if (enumerator && (-- enumerator->n_ref) == 0) { sd_device *device; while ((device = prioq_pop(enumerator->devices))) sd_device_unref(device); prioq_free(enumerator->devices); set_free_free(enumerator->match_subsystem); set_free_free(enumerator->nomatch_subsystem); hashmap_free_free_free(enumerator->match_sysattr); hashmap_free_free_free(enumerator->nomatch_sysattr); hashmap_free_free_free(enumerator->match_property); set_free_free(enumerator->match_sysname); set_free_free(enumerator->match_tag); sd_device_unref(enumerator->match_parent); free(enumerator); } return NULL; } _public_ int sd_device_enumerator_add_match_subsystem(sd_device_enumerator *enumerator, const char *subsystem, int match) { Set **set; int r; assert_return(enumerator, -EINVAL); assert_return(subsystem, -EINVAL); if (match) set = &enumerator->match_subsystem; else set = &enumerator->nomatch_subsystem; r = set_ensure_allocated(set, NULL); if (r < 0) return r; r = set_put_strdup(*set, subsystem); if (r < 0) return r; enumerator->scan_uptodate = false; return 0; } _public_ int sd_device_enumerator_add_match_sysattr(sd_device_enumerator *enumerator, const char *_sysattr, const char *_value, int match) { _cleanup_free_ char *sysattr = NULL, *value = NULL; Hashmap **hashmap; int r; assert_return(enumerator, -EINVAL); assert_return(_sysattr, -EINVAL); if (match) hashmap = &enumerator->match_sysattr; else hashmap = &enumerator->nomatch_sysattr; r = hashmap_ensure_allocated(hashmap, NULL); if (r < 0) return r; sysattr = strdup(_sysattr); if (!sysattr) return -ENOMEM; if (_value) { value = strdup(_value); if (!value) return -ENOMEM; } r = hashmap_put(*hashmap, sysattr, value); if (r < 0) return r; sysattr = NULL; value = NULL; enumerator->scan_uptodate = false; return 0; } _public_ int sd_device_enumerator_add_match_property(sd_device_enumerator *enumerator, const char *_property, const char *_value) { _cleanup_free_ char *property = NULL, *value = NULL; int r; assert_return(enumerator, -EINVAL); assert_return(_property, -EINVAL); r = hashmap_ensure_allocated(&enumerator->match_property, NULL); if (r < 0) return r; property = strdup(_property); if (!property) return -ENOMEM; if (_value) { value = strdup(_value); if (!value) return -ENOMEM; } r = hashmap_put(enumerator->match_property, property, value); if (r < 0) return r; property = NULL; value = NULL; enumerator->scan_uptodate = false; return 0; } _public_ int sd_device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname) { int r; assert_return(enumerator, -EINVAL); assert_return(sysname, -EINVAL); r = set_ensure_allocated(&enumerator->match_sysname, NULL); if (r < 0) return r; r = set_put_strdup(enumerator->match_sysname, sysname); if (r < 0) return r; enumerator->scan_uptodate = false; return 0; } _public_ int sd_device_enumerator_add_match_tag(sd_device_enumerator *enumerator, const char *tag) { int r; assert_return(enumerator, -EINVAL); assert_return(tag, -EINVAL); r = set_ensure_allocated(&enumerator->match_tag, NULL); if (r < 0) return r; r = set_put_strdup(enumerator->match_tag, tag); if (r < 0) return r; enumerator->scan_uptodate = false; return 0; } _public_ int sd_device_enumerator_add_match_parent(sd_device_enumerator *enumerator, sd_device *parent) { assert_return(enumerator, -EINVAL); assert_return(parent, -EINVAL); sd_device_unref(enumerator->match_parent); enumerator->match_parent = sd_device_ref(parent); enumerator->scan_uptodate = false; return 0; } _public_ int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator) { assert_return(enumerator, -EINVAL); enumerator->match_allow_uninitialized = true; enumerator->scan_uptodate = false; return 0; } int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator) { assert_return(enumerator, -EINVAL); enumerator->match_allow_uninitialized = false; enumerator->scan_uptodate = false; return 0; } static int device_compare(const void *_a, const void *_b) { sd_device *a = (sd_device *)_a, *b = (sd_device *)_b; const char *devpath_a, *devpath_b, *sound_a; bool delay_a, delay_b; assert_se(sd_device_get_devpath(a, &devpath_a) >= 0); assert_se(sd_device_get_devpath(b, &devpath_b) >= 0); sound_a = strstr(devpath_a, "/sound/card"); if (sound_a) { /* For sound cards the control device must be enumerated last to * make sure it's the final device node that gets ACLs applied. * Applications rely on this fact and use ACL changes on the * control node as an indicator that the ACL change of the * entire sound card completed. The kernel makes this guarantee * when creating those devices, and hence we should too when * enumerating them. */ sound_a += strlen("/sound/card"); sound_a = strchr(sound_a, '/'); if (sound_a) { unsigned prefix_len; prefix_len = sound_a - devpath_a; if (strncmp(devpath_a, devpath_b, prefix_len) == 0) { const char *sound_b; sound_b = devpath_b + prefix_len; if (startswith(sound_a, "/controlC") && !startswith(sound_b, "/contolC")) return 1; if (!startswith(sound_a, "/controlC") && startswith(sound_b, "/controlC")) return -1; } } } /* md and dm devices are enumerated after all other devices */ delay_a = strstr(devpath_a, "/block/md") || strstr(devpath_a, "/block/dm-"); delay_b = strstr(devpath_b, "/block/md") || strstr(devpath_b, "/block/dm-"); if (delay_a != delay_b) return delay_a - delay_b; return strcmp(devpath_a, devpath_b); } int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device) { int r; assert_return(enumerator, -EINVAL); assert_return(device, -EINVAL); r = prioq_ensure_allocated(&enumerator->devices, device_compare); if (r < 0) return r; r = prioq_put(enumerator->devices, device, NULL); if (r < 0) return r; sd_device_ref(device); return 0; } static bool match_sysattr_value(sd_device *device, const char *sysattr, const char *match_value) { const char *value; int r; assert(device); assert(sysattr); r = sd_device_get_sysattr_value(device, sysattr, &value); if (r < 0) return false; if (!match_value) return true; if (fnmatch(match_value, value, 0) == 0) return true; return false; } static bool match_sysattr(sd_device_enumerator *enumerator, sd_device *device) { const char *sysattr; const char *value; Iterator i; assert(enumerator); assert(device); HASHMAP_FOREACH_KEY(value, sysattr, enumerator->nomatch_sysattr, i) if (match_sysattr_value(device, sysattr, value)) return false; HASHMAP_FOREACH_KEY(value, sysattr, enumerator->match_sysattr, i) if (!match_sysattr_value(device, sysattr, value)) return false; return true; } static bool match_property(sd_device_enumerator *enumerator, sd_device *device) { const char *property; const char *value; Iterator i; assert(enumerator); assert(device); if (hashmap_isempty(enumerator->match_property)) return true; HASHMAP_FOREACH_KEY(value, property, enumerator->match_property, i) { const char *property_dev, *value_dev; FOREACH_DEVICE_PROPERTY(device, property_dev, value_dev) { if (fnmatch(property, property_dev, 0) != 0) continue; if (!value && !value_dev) return true; if (!value || !value_dev) continue; if (fnmatch(value, value_dev, 0) == 0) return true; } } return false; } static bool match_tag(sd_device_enumerator *enumerator, sd_device *device) { const char *tag; Iterator i; assert(enumerator); assert(device); SET_FOREACH(tag, enumerator->match_tag, i) if (!sd_device_has_tag(device, tag)) return false; return true; } static bool match_parent(sd_device_enumerator *enumerator, sd_device *device) { const char *devpath, *devpath_dev; int r; assert(enumerator); assert(device); if (!enumerator->match_parent) return true; r = sd_device_get_devpath(enumerator->match_parent, &devpath); assert(r >= 0); r = sd_device_get_devpath(device, &devpath_dev); assert(r >= 0); return startswith(devpath_dev, devpath); } static bool match_sysname(sd_device_enumerator *enumerator, const char *sysname) { const char *sysname_match; Iterator i; assert(enumerator); assert(sysname); if (set_isempty(enumerator->match_sysname)) return true; SET_FOREACH(sysname_match, enumerator->match_sysname, i) if (fnmatch(sysname_match, sysname, 0) == 0) return true; return false; } static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator, const char *basedir, const char *subdir1, const char *subdir2) { _cleanup_closedir_ DIR *dir = NULL; char *path; struct dirent *dent; int r = 0; assert(enumerator); assert(basedir); path = strjoina("/sys/", basedir, "/"); if (subdir1) path = strjoina(path, subdir1, "/"); if (subdir2) path = strjoina(path, subdir2, "/"); dir = opendir(path); if (!dir) return -errno; FOREACH_DIRENT_ALL(dent, dir, return -errno) { _cleanup_(sd_device_unrefp) sd_device *device = NULL; char syspath[strlen(path) + 1 + strlen(dent->d_name) + 1]; dev_t devnum; int ifindex, initialized, k; if (dent->d_name[0] == '.') continue; if (!match_sysname(enumerator, dent->d_name)) continue; (void)sprintf(syspath, "%s%s", path, dent->d_name); k = sd_device_new_from_syspath(&device, syspath); if (k < 0) { if (k != -ENODEV) /* this is necessarily racey, so ignore missing devices */ r = k; continue; } k = sd_device_get_devnum(device, &devnum); if (k < 0) { r = k; continue; } k = sd_device_get_ifindex(device, &ifindex); if (k < 0) { r = k; continue; } k = sd_device_get_is_initialized(device, &initialized); if (k < 0) { r = k; continue; } /* * All devices with a device node or network interfaces * possibly need udev to adjust the device node permission * or context, or rename the interface before it can be * reliably used from other processes. * * For now, we can only check these types of devices, we * might not store a database, and have no way to find out * for all other types of devices. */ if (!enumerator->match_allow_uninitialized && !initialized && (major(devnum) > 0 || ifindex > 0)) continue; if (!match_parent(enumerator, device)) continue; if (!match_tag(enumerator, device)) continue; if (!match_property(enumerator, device)) continue; if (!match_sysattr(enumerator, device)) continue; k = device_enumerator_add_device(enumerator, device); if (k < 0) r = k; } return r; } static bool match_subsystem(sd_device_enumerator *enumerator, const char *subsystem) { const char *subsystem_match; Iterator i; assert(enumerator); if (!subsystem) return false; SET_FOREACH(subsystem_match, enumerator->nomatch_subsystem, i) if (fnmatch(subsystem_match, subsystem, 0) == 0) return false; if (set_isempty(enumerator->match_subsystem)) return true; SET_FOREACH(subsystem_match, enumerator->match_subsystem, i) if (fnmatch(subsystem_match, subsystem, 0) == 0) return true; return false; } static int enumerator_scan_dir(sd_device_enumerator *enumerator, const char *basedir, const char *subdir, const char *subsystem) { _cleanup_closedir_ DIR *dir = NULL; char *path; struct dirent *dent; int r = 0; path = strjoina("/sys/", basedir); dir = opendir(path); if (!dir) return -errno; log_debug(" device-enumerator: scanning %s", path); FOREACH_DIRENT_ALL(dent, dir, return -errno) { int k; if (dent->d_name[0] == '.') continue; if (!match_subsystem(enumerator, subsystem ? : dent->d_name)) continue; k = enumerator_scan_dir_and_add_devices(enumerator, basedir, dent->d_name, subdir); if (k < 0) r = k; } return r; } static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const char *tag) { _cleanup_closedir_ DIR *dir = NULL; char *path; struct dirent *dent; int r = 0; assert(enumerator); assert(tag); path = strjoina("/run/udev/tags/", tag); dir = opendir(path); if (!dir) { if (errno == ENOENT) return 0; else { log_error("sd-device-enumerator: could not open tags directory %s: %m", path); return -errno; } } /* TODO: filter away subsystems? */ FOREACH_DIRENT_ALL(dent, dir, return -errno) { _cleanup_(sd_device_unrefp) sd_device *device = NULL; const char *subsystem, *sysname; int k; if (dent->d_name[0] == '.') continue; k = sd_device_new_from_device_id(&device, dent->d_name); if (k < 0) { if (k != -ENODEV) /* this is necessarily racy, so ignore missing devices */ r = k; continue; } k = sd_device_get_subsystem(device, &subsystem); if (k < 0) { r = k; continue; } if (!match_subsystem(enumerator, subsystem)) continue; k = sd_device_get_sysname(device, &sysname); if (k < 0) { r = k; continue; } if (!match_sysname(enumerator, sysname)) continue; if (!match_parent(enumerator, device)) continue; if (!match_property(enumerator, device)) continue; if (!match_sysattr(enumerator, device)) continue; k = device_enumerator_add_device(enumerator, device); if (k < 0) { r = k; continue; } } return r; } static int enumerator_scan_devices_tags(sd_device_enumerator *enumerator) { const char *tag; Iterator i; int r; assert(enumerator); SET_FOREACH(tag, enumerator->match_tag, i) { r = enumerator_scan_devices_tag(enumerator, tag); if (r < 0) return r; } return 0; } static int parent_add_child(sd_device_enumerator *enumerator, const char *path) { _cleanup_(sd_device_unrefp) sd_device *device = NULL; const char *subsystem, *sysname; int r; r = sd_device_new_from_syspath(&device, path); if (r == -ENODEV) /* this is necessarily racy, so ignore missing devices */ return 0; else if (r < 0) return r; r = sd_device_get_subsystem(device, &subsystem); if (r == -ENOENT) return 0; if (r < 0) return r; if (!match_subsystem(enumerator, subsystem)) return 0; r = sd_device_get_sysname(device, &sysname); if (r < 0) return r; if (!match_sysname(enumerator, sysname)) return 0; if (!match_property(enumerator, device)) return 0; if (!match_sysattr(enumerator, device)) return 0; r = device_enumerator_add_device(enumerator, device); if (r < 0) return r; return 1; } static int parent_crawl_children(sd_device_enumerator *enumerator, const char *path, unsigned maxdepth) { _cleanup_closedir_ DIR *dir = NULL; struct dirent *dent; int r = 0; dir = opendir(path); if (!dir) { log_debug("sd-device-enumerate: could not open parent directory %s: %m", path); return -errno; } FOREACH_DIRENT_ALL(dent, dir, return -errno) { _cleanup_free_ char *child = NULL; int k; if (dent->d_name[0] == '.') continue; if (dent->d_type != DT_DIR) continue; child = strjoin(path, "/", dent->d_name, NULL); if (!child) return -ENOMEM; k = parent_add_child(enumerator, child); if (k < 0) r = k; if (maxdepth > 0) parent_crawl_children(enumerator, child, maxdepth - 1); else log_debug("device-enumerate: max depth reached, %s: ignoring devices", child); } return r; } static int enumerator_scan_devices_children(sd_device_enumerator *enumerator) { const char *path; int r = 0, k; r = sd_device_get_syspath(enumerator->match_parent, &path); if (r < 0) return r; k = parent_add_child(enumerator, path); if (k < 0) r = k; k = parent_crawl_children(enumerator, path, DEVICE_ENUMERATE_MAX_DEPTH); if (k < 0) r = k; return r; } static int enumerator_scan_devices_all(sd_device_enumerator *enumerator) { int r = 0; log_debug("device-enumerator: scan all dirs"); if (access("/sys/subsystem", F_OK) >= 0) { /* we have /subsystem/, forget all the old stuff */ r = enumerator_scan_dir(enumerator, "subsystem", "devices", NULL); if (r < 0) return log_debug_errno(r, "device-enumerator: failed to scan /sys/subsystem: %m"); } else { int k; k = enumerator_scan_dir(enumerator, "bus", "devices", NULL); if (k < 0) { log_debug_errno(k, "device-enumerator: failed to scan /sys/bus: %m"); r = k; } k = enumerator_scan_dir(enumerator, "class", NULL, NULL); if (k < 0) { log_debug_errno(k, "device-enumerator: failed to scan /sys/class: %m"); r = k; } } return r; } int device_enumerator_scan_devices(sd_device_enumerator *enumerator) { sd_device *device; int r; assert(enumerator); if (enumerator->scan_uptodate && enumerator->type == DEVICE_ENUMERATION_TYPE_DEVICES) return 0; while ((device = prioq_pop(enumerator->devices))) sd_device_unref(device); if (!set_isempty(enumerator->match_tag)) { r = enumerator_scan_devices_tags(enumerator); if (r < 0) return r; } else if (enumerator->match_parent) { r = enumerator_scan_devices_children(enumerator); if (r < 0) return r; } else { r = enumerator_scan_devices_all(enumerator); if (r < 0) return r; } enumerator->scan_uptodate = true; return 0; } _public_ sd_device *sd_device_enumerator_get_device_first(sd_device_enumerator *enumerator) { int r; assert_return(enumerator, NULL); r = device_enumerator_scan_devices(enumerator); if (r < 0) return NULL; enumerator->type = DEVICE_ENUMERATION_TYPE_DEVICES; return prioq_peek(enumerator->devices); } _public_ sd_device *sd_device_enumerator_get_device_next(sd_device_enumerator *enumerator) { assert_return(enumerator, NULL); if (!enumerator->scan_uptodate || enumerator->type != DEVICE_ENUMERATION_TYPE_DEVICES) return NULL; sd_device_unref(prioq_pop(enumerator->devices)); return prioq_peek(enumerator->devices); } int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) { sd_device *device; const char *subsysdir; int r = 0, k; assert(enumerator); if (enumerator->scan_uptodate && enumerator->type == DEVICE_ENUMERATION_TYPE_SUBSYSTEMS) return 0; while ((device = prioq_pop(enumerator->devices))) sd_device_unref(device); /* modules */ if (match_subsystem(enumerator, "module")) { k = enumerator_scan_dir_and_add_devices(enumerator, "module", NULL, NULL); if (k < 0) { log_debug_errno(k, "device-enumerator: failed to scan modules: %m"); r = k; } } if (access("/sys/subsystem", F_OK) >= 0) subsysdir = "subsystem"; else subsysdir = "bus"; /* subsystems (only buses support coldplug) */ if (match_subsystem(enumerator, "subsystem")) { k = enumerator_scan_dir_and_add_devices(enumerator, subsysdir, NULL, NULL); if (k < 0) { log_debug_errno(k, "device-enumerator: failed to scan subsystems: %m"); r = k; } } /* subsystem drivers */ if (match_subsystem(enumerator, "drivers")) { k = enumerator_scan_dir(enumerator, subsysdir, "drivers", "drivers"); if (k < 0) { log_debug_errno(k, "device-enumerator: failed to scan drivers: %m"); r = k; } } enumerator->scan_uptodate = true; return r; } _public_ sd_device *sd_device_enumerator_get_subsystem_first(sd_device_enumerator *enumerator) { int r; assert_return(enumerator, NULL); r = device_enumerator_scan_subsystems(enumerator); if (r < 0) return NULL; enumerator->type = DEVICE_ENUMERATION_TYPE_SUBSYSTEMS; return prioq_peek(enumerator->devices); } _public_ sd_device *sd_device_enumerator_get_subsystem_next(sd_device_enumerator *enumerator) { assert_return(enumerator, NULL); if (enumerator->scan_uptodate || enumerator->type != DEVICE_ENUMERATION_TYPE_SUBSYSTEMS) return NULL; sd_device_unref(prioq_pop(enumerator->devices)); return prioq_peek(enumerator->devices); } sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator) { assert_return(enumerator, NULL); return prioq_peek(enumerator->devices); } sd_device *device_enumerator_get_next(sd_device_enumerator *enumerator) { assert_return(enumerator, NULL); sd_device_unref(prioq_pop(enumerator->devices)); return prioq_peek(enumerator->devices); } systemd-229/src/libsystemd/sd-device/device-internal.h000066400000000000000000000110561265713322000231170ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "hashmap.h" #include "set.h" struct sd_device { uint64_t n_ref; sd_device *parent; bool parent_set; /* no need to try to reload parent */ OrderedHashmap *properties; Iterator properties_iterator; uint64_t properties_generation; /* changes whenever the properties are changed */ uint64_t properties_iterator_generation; /* generation when iteration was started */ /* the subset of the properties that should be written to the db*/ OrderedHashmap *properties_db; Hashmap *sysattr_values; /* cached sysattr values */ Set *sysattrs; /* names of sysattrs */ Iterator sysattrs_iterator; bool sysattrs_read; /* don't try to re-read sysattrs once read */ Set *tags; Iterator tags_iterator; uint64_t tags_generation; /* changes whenever the tags are changed */ uint64_t tags_iterator_generation; /* generation when iteration was started */ bool property_tags_outdated; /* need to update TAGS= property */ Set *devlinks; Iterator devlinks_iterator; uint64_t devlinks_generation; /* changes whenever the devlinks are changed */ uint64_t devlinks_iterator_generation; /* generation when iteration was started */ bool property_devlinks_outdated; /* need to update DEVLINKS= property */ int devlink_priority; char **properties_strv; /* the properties hashmap as a strv */ uint8_t *properties_nulstr; /* the same as a nulstr */ size_t properties_nulstr_len; bool properties_buf_outdated; /* need to reread hashmap */ int watch_handle; char *syspath; const char *devpath; const char *sysnum; char *sysname; bool sysname_set; /* don't reread sysname */ char *devtype; int ifindex; char *devname; dev_t devnum; char *subsystem; bool subsystem_set; /* don't reread subsystem */ char *driver; bool driver_set; /* don't reread driver */ char *id_filename; bool is_initialized; uint64_t usec_initialized; mode_t devmode; uid_t devuid; gid_t devgid; bool uevent_loaded; /* don't reread uevent */ bool db_loaded; /* don't reread db */ bool sealed; /* don't read more information from uevent/db */ bool db_persist; /* don't clean up the db when switching from initrd to real root */ }; typedef enum DeviceAction { DEVICE_ACTION_ADD, DEVICE_ACTION_REMOVE, DEVICE_ACTION_CHANGE, DEVICE_ACTION_MOVE, DEVICE_ACTION_ONLINE, DEVICE_ACTION_OFFLINE, _DEVICE_ACTION_MAX, _DEVICE_ACTION_INVALID = -1, } DeviceAction; int device_new_aux(sd_device **ret); int device_add_property_aux(sd_device *device, const char *key, const char *value, bool db); int device_add_property_internal(sd_device *device, const char *key, const char *value); int device_read_uevent_file(sd_device *device); int device_read_db_aux(sd_device *device, bool force); int device_set_syspath(sd_device *device, const char *_syspath, bool verify); int device_set_ifindex(sd_device *device, const char *ifindex); int device_set_devmode(sd_device *device, const char *devmode); int device_set_devname(sd_device *device, const char *_devname); int device_set_devtype(sd_device *device, const char *_devtype); int device_set_devnum(sd_device *device, const char *major, const char *minor); int device_set_subsystem(sd_device *device, const char *_subsystem); int device_set_driver(sd_device *device, const char *_driver); int device_set_usec_initialized(sd_device *device, const char *initialized); DeviceAction device_action_from_string(const char *s) _pure_; const char *device_action_to_string(DeviceAction a) _const_; systemd-229/src/libsystemd/sd-device/device-private.c000066400000000000000000000737211265713322000227570ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-device.h" #include "alloc-util.h" #include "device-internal.h" #include "device-private.h" #include "device-util.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "hashmap.h" #include "macro.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" #include "refcnt.h" #include "set.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "strxcpyx.h" #include "user-util.h" #include "util.h" int device_add_property(sd_device *device, const char *key, const char *value) { int r; assert(device); assert(key); r = device_add_property_aux(device, key, value, false); if (r < 0) return r; if (key[0] != '.') { r = device_add_property_aux(device, key, value, true); if (r < 0) return r; } return 0; } static int device_add_property_internal_from_string(sd_device *device, const char *str) { _cleanup_free_ char *key = NULL; char *value; assert(device); assert(str); key = strdup(str); if (!key) return -ENOMEM; value = strchr(key, '='); if (!value) return -EINVAL; *value = '\0'; if (isempty(++value)) value = NULL; return device_add_property_internal(device, key, value); } static int handle_db_line(sd_device *device, char key, const char *value) { char *path; int r; assert(device); assert(value); switch (key) { case 'S': path = strjoina("/dev/", value); r = device_add_devlink(device, path); if (r < 0) return r; break; case 'L': r = safe_atoi(value, &device->devlink_priority); if (r < 0) return r; break; case 'E': r = device_add_property_internal_from_string(device, value); if (r < 0) return r; break; case 'G': r = device_add_tag(device, value); if (r < 0) return r; break; case 'W': r = safe_atoi(value, &device->watch_handle); if (r < 0) return r; break; case 'I': r = device_set_usec_initialized(device, value); if (r < 0) return r; break; default: log_debug("device db: unknown key '%c'", key); } return 0; } void device_set_devlink_priority(sd_device *device, int priority) { assert(device); device->devlink_priority = priority; } void device_set_is_initialized(sd_device *device) { assert(device); device->is_initialized = true; } int device_ensure_usec_initialized(sd_device *device, sd_device *device_old) { char num[DECIMAL_STR_MAX(usec_t)]; usec_t usec_initialized; int r; assert(device); if (device_old && device_old->usec_initialized > 0) usec_initialized = device_old->usec_initialized; else usec_initialized = now(CLOCK_MONOTONIC); r = snprintf(num, sizeof(num), USEC_FMT, usec_initialized); if (r < 0) return -errno; r = device_set_usec_initialized(device, num); if (r < 0) return r; return 0; } static int device_read_db(sd_device *device) { _cleanup_free_ char *db = NULL; char *path; const char *id, *value; char key; size_t db_len; unsigned i; int r; enum { PRE_KEY, KEY, PRE_VALUE, VALUE, INVALID_LINE, } state = PRE_KEY; assert(device); if (device->db_loaded || device->sealed) return 0; r = device_get_id_filename(device, &id); if (r < 0) return r; path = strjoina("/run/udev/data/", id); r = read_full_file(path, &db, &db_len); if (r < 0) { if (r == -ENOENT) return 0; else return log_debug_errno(r, "sd-device: failed to read db '%s': %m", path); } /* devices with a database entry are initialized */ device_set_is_initialized(device); for (i = 0; i < db_len; i++) { switch (state) { case PRE_KEY: if (!strchr(NEWLINE, db[i])) { key = db[i]; state = KEY; } break; case KEY: if (db[i] != ':') { log_debug("sd-device: ignoring invalid db entry with key '%c'", key); state = INVALID_LINE; } else { db[i] = '\0'; state = PRE_VALUE; } break; case PRE_VALUE: value = &db[i]; state = VALUE; break; case INVALID_LINE: if (strchr(NEWLINE, db[i])) state = PRE_KEY; break; case VALUE: if (strchr(NEWLINE, db[i])) { db[i] = '\0'; r = handle_db_line(device, key, value); if (r < 0) log_debug_errno(r, "sd-device: failed to handle db entry '%c:%s': %m", key, value); state = PRE_KEY; } break; default: assert_not_reached("invalid state when parsing db"); } } device->db_loaded = true; return 0; } uint64_t device_get_properties_generation(sd_device *device) { assert(device); return device->properties_generation; } uint64_t device_get_tags_generation(sd_device *device) { assert(device); return device->tags_generation; } uint64_t device_get_devlinks_generation(sd_device *device) { assert(device); return device->devlinks_generation; } int device_get_devnode_mode(sd_device *device, mode_t *mode) { int r; assert(device); assert(mode); r = device_read_db(device); if (r < 0) return r; *mode = device->devmode; return 0; } int device_get_devnode_uid(sd_device *device, uid_t *uid) { int r; assert(device); assert(uid); r = device_read_db(device); if (r < 0) return r; *uid = device->devuid; return 0; } static int device_set_devuid(sd_device *device, const char *uid) { unsigned u; int r; assert(device); assert(uid); r = safe_atou(uid, &u); if (r < 0) return r; r = device_add_property_internal(device, "DEVUID", uid); if (r < 0) return r; device->devuid = u; return 0; } int device_get_devnode_gid(sd_device *device, gid_t *gid) { int r; assert(device); assert(gid); r = device_read_db(device); if (r < 0) return r; *gid = device->devgid; return 0; } static int device_set_devgid(sd_device *device, const char *gid) { unsigned g; int r; assert(device); assert(gid); r = safe_atou(gid, &g); if (r < 0) return r; r = device_add_property_internal(device, "DEVGID", gid); if (r < 0) return r; device->devgid = g; return 0; } static int device_amend(sd_device *device, const char *key, const char *value) { int r; assert(device); assert(key); assert(value); if (streq(key, "DEVPATH")) { char *path; path = strjoina("/sys", value); /* the caller must verify or trust this data (e.g., if it comes from the kernel) */ r = device_set_syspath(device, path, false); if (r < 0) return log_debug_errno(r, "sd-device: could not set syspath to '%s': %m", path); } else if (streq(key, "SUBSYSTEM")) { r = device_set_subsystem(device, value); if (r < 0) return log_debug_errno(r, "sd-device: could not set subsystem to '%s': %m", value); } else if (streq(key, "DEVTYPE")) { r = device_set_devtype(device, value); if (r < 0) return log_debug_errno(r, "sd-device: could not set devtype to '%s': %m", value); } else if (streq(key, "DEVNAME")) { r = device_set_devname(device, value); if (r < 0) return log_debug_errno(r, "sd-device: could not set devname to '%s': %m", value); } else if (streq(key, "USEC_INITIALIZED")) { r = device_set_usec_initialized(device, value); if (r < 0) return log_debug_errno(r, "sd-device: could not set usec-initialized to '%s': %m", value); } else if (streq(key, "DRIVER")) { r = device_set_driver(device, value); if (r < 0) return log_debug_errno(r, "sd-device: could not set driver to '%s': %m", value); } else if (streq(key, "IFINDEX")) { r = device_set_ifindex(device, value); if (r < 0) return log_debug_errno(r, "sd-device: could not set ifindex to '%s': %m", value); } else if (streq(key, "DEVMODE")) { r = device_set_devmode(device, value); if (r < 0) return log_debug_errno(r, "sd-device: could not set devmode to '%s': %m", value); } else if (streq(key, "DEVUID")) { r = device_set_devuid(device, value); if (r < 0) return log_debug_errno(r, "sd-device: could not set devuid to '%s': %m", value); } else if (streq(key, "DEVGID")) { r = device_set_devgid(device, value); if (r < 0) return log_debug_errno(r, "sd-device: could not set devgid to '%s': %m", value); } else if (streq(key, "DEVLINKS")) { const char *word, *state; size_t l; FOREACH_WORD(word, l, value, state) { char devlink[l + 1]; strncpy(devlink, word, l); devlink[l] = '\0'; r = device_add_devlink(device, devlink); if (r < 0) return log_debug_errno(r, "sd-device: could not add devlink '%s': %m", devlink); } } else if (streq(key, "TAGS")) { const char *word, *state; size_t l; FOREACH_WORD_SEPARATOR(word, l, value, ":", state) { char tag[l + 1]; (void)strncpy(tag, word, l); tag[l] = '\0'; r = device_add_tag(device, tag); if (r < 0) return log_debug_errno(r, "sd-device: could not add tag '%s': %m", tag); } } else { r = device_add_property_internal(device, key, value); if (r < 0) return log_debug_errno(r, "sd-device: could not add property '%s=%s': %m", key, value); } return 0; } static const char* const device_action_table[_DEVICE_ACTION_MAX] = { [DEVICE_ACTION_ADD] = "add", [DEVICE_ACTION_REMOVE] = "remove", [DEVICE_ACTION_CHANGE] = "change", [DEVICE_ACTION_MOVE] = "move", [DEVICE_ACTION_ONLINE] = "online", [DEVICE_ACTION_OFFLINE] = "offline", }; DEFINE_STRING_TABLE_LOOKUP(device_action, DeviceAction); static int device_append(sd_device *device, char *key, const char **_major, const char **_minor, uint64_t *_seqnum, DeviceAction *_action) { DeviceAction action = _DEVICE_ACTION_INVALID; uint64_t seqnum = 0; const char *major = NULL, *minor = NULL; char *value; int r; assert(device); assert(key); assert(_major); assert(_minor); assert(_seqnum); assert(_action); value = strchr(key, '='); if (!value) { log_debug("sd-device: not a key-value pair: '%s'", key); return -EINVAL; } *value = '\0'; value++; if (streq(key, "MAJOR")) major = value; else if (streq(key, "MINOR")) minor = value; else { if (streq(key, "ACTION")) { action = device_action_from_string(value); if (action == _DEVICE_ACTION_INVALID) return -EINVAL; } else if (streq(key, "SEQNUM")) { r = safe_atou64(value, &seqnum); if (r < 0) return r; else if (seqnum == 0) /* kernel only sends seqnum > 0 */ return -EINVAL; } r = device_amend(device, key, value); if (r < 0) return r; } if (major != 0) *_major = major; if (minor != 0) *_minor = minor; if (action != _DEVICE_ACTION_INVALID) *_action = action; if (seqnum > 0) *_seqnum = seqnum; return 0; } void device_seal(sd_device *device) { assert(device); device->sealed = true; } static int device_verify(sd_device *device, DeviceAction action, uint64_t seqnum) { assert(device); if (!device->devpath || !device->subsystem || action == _DEVICE_ACTION_INVALID || seqnum == 0) { log_debug("sd-device: device created from strv lacks devpath, subsystem, action or seqnum"); return -EINVAL; } device->sealed = true; return 0; } int device_new_from_strv(sd_device **ret, char **strv) { _cleanup_(sd_device_unrefp) sd_device *device = NULL; char **key; const char *major = NULL, *minor = NULL; DeviceAction action = _DEVICE_ACTION_INVALID; uint64_t seqnum; int r; assert(ret); assert(strv); r = device_new_aux(&device); if (r < 0) return r; STRV_FOREACH(key, strv) { r = device_append(device, *key, &major, &minor, &seqnum, &action); if (r < 0) return r; } if (major) { r = device_set_devnum(device, major, minor); if (r < 0) return log_debug_errno(r, "sd-device: could not set devnum %s:%s: %m", major, minor); } r = device_verify(device, action, seqnum); if (r < 0) return r; *ret = device; device = NULL; return 0; } int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) { _cleanup_(sd_device_unrefp) sd_device *device = NULL; const char *major = NULL, *minor = NULL; DeviceAction action = _DEVICE_ACTION_INVALID; uint64_t seqnum; unsigned i = 0; int r; assert(ret); assert(nulstr); assert(len); r = device_new_aux(&device); if (r < 0) return r; while (i < len) { char *key; const char *end; key = (char*)&nulstr[i]; end = memchr(key, '\0', len - i); if (!end) { log_debug("sd-device: failed to parse nulstr"); return -EINVAL; } i += end - key + 1; r = device_append(device, key, &major, &minor, &seqnum, &action); if (r < 0) return r; } if (major) { r = device_set_devnum(device, major, minor); if (r < 0) return log_debug_errno(r, "sd-device: could not set devnum %s:%s: %m", major, minor); } r = device_verify(device, action, seqnum); if (r < 0) return r; *ret = device; device = NULL; return 0; } static int device_update_properties_bufs(sd_device *device) { const char *val, *prop; _cleanup_free_ char **buf_strv = NULL; _cleanup_free_ uint8_t *buf_nulstr = NULL; size_t allocated_nulstr = 0; size_t nulstr_len = 0, num = 0, i = 0; assert(device); if (!device->properties_buf_outdated) return 0; FOREACH_DEVICE_PROPERTY(device, prop, val) { size_t len = 0; len = strlen(prop) + 1 + strlen(val); buf_nulstr = GREEDY_REALLOC0(buf_nulstr, allocated_nulstr, nulstr_len + len + 2); if (!buf_nulstr) return -ENOMEM; strscpyl((char *)buf_nulstr + nulstr_len, len + 1, prop, "=", val, NULL); nulstr_len += len + 1; ++num; } /* build buf_strv from buf_nulstr */ buf_strv = new0(char *, num + 1); if (!buf_strv) return -ENOMEM; NULSTR_FOREACH(val, (char*) buf_nulstr) { buf_strv[i] = (char *) val; assert(i < num); i++; } free(device->properties_nulstr); device->properties_nulstr = buf_nulstr; buf_nulstr = NULL; device->properties_nulstr_len = nulstr_len; free(device->properties_strv); device->properties_strv = buf_strv; buf_strv = NULL; device->properties_buf_outdated = false; return 0; } int device_get_properties_nulstr(sd_device *device, const uint8_t **nulstr, size_t *len) { int r; assert(device); assert(nulstr); assert(len); r = device_update_properties_bufs(device); if (r < 0) return r; *nulstr = device->properties_nulstr; *len = device->properties_nulstr_len; return 0; } int device_get_properties_strv(sd_device *device, char ***strv) { int r; assert(device); assert(strv); r = device_update_properties_bufs(device); if (r < 0) return r; *strv = device->properties_strv; return 0; } int device_get_devlink_priority(sd_device *device, int *priority) { int r; assert(device); assert(priority); r = device_read_db(device); if (r < 0) return r; *priority = device->devlink_priority; return 0; } int device_get_watch_handle(sd_device *device, int *handle) { int r; assert(device); assert(handle); r = device_read_db(device); if (r < 0) return r; *handle = device->watch_handle; return 0; } void device_set_watch_handle(sd_device *device, int handle) { assert(device); device->watch_handle = handle; } int device_rename(sd_device *device, const char *name) { _cleanup_free_ char *dirname = NULL; char *new_syspath; const char *interface; int r; assert(device); assert(name); dirname = dirname_malloc(device->syspath); if (!dirname) return -ENOMEM; new_syspath = strjoina(dirname, "/", name); /* the user must trust that the new name is correct */ r = device_set_syspath(device, new_syspath, false); if (r < 0) return r; r = sd_device_get_property_value(device, "INTERFACE", &interface); if (r >= 0) { r = device_add_property_internal(device, "INTERFACE", name); if (r < 0) return r; /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */ r = device_add_property_internal(device, "INTERFACE_OLD", interface); if (r < 0) return r; } else if (r != -ENOENT) return r; return 0; } int device_shallow_clone(sd_device *old_device, sd_device **new_device) { _cleanup_(sd_device_unrefp) sd_device *ret = NULL; int r; assert(old_device); assert(new_device); r = device_new_aux(&ret); if (r < 0) return r; r = device_set_syspath(ret, old_device->syspath, false); if (r < 0) return r; r = device_set_subsystem(ret, old_device->subsystem); if (r < 0) return r; ret->devnum = old_device->devnum; *new_device = ret; ret = NULL; return 0; } int device_clone_with_db(sd_device *old_device, sd_device **new_device) { _cleanup_(sd_device_unrefp) sd_device *ret = NULL; int r; assert(old_device); assert(new_device); r = device_shallow_clone(old_device, &ret); if (r < 0) return r; r = device_read_db(ret); if (r < 0) return r; ret->sealed = true; *new_device = ret; ret = NULL; return 0; } int device_new_from_synthetic_event(sd_device **new_device, const char *syspath, const char *action) { _cleanup_(sd_device_unrefp) sd_device *ret = NULL; int r; assert(new_device); assert(syspath); assert(action); r = sd_device_new_from_syspath(&ret, syspath); if (r < 0) return r; r = device_read_uevent_file(ret); if (r < 0) return r; r = device_add_property_internal(ret, "ACTION", action); if (r < 0) return r; *new_device = ret; ret = NULL; return 0; } int device_copy_properties(sd_device *device_dst, sd_device *device_src) { const char *property, *value; int r; assert(device_dst); assert(device_src); FOREACH_DEVICE_PROPERTY(device_src, property, value) { r = device_add_property(device_dst, property, value); if (r < 0) return r; } return 0; } void device_cleanup_tags(sd_device *device) { assert(device); set_free_free(device->tags); device->tags = NULL; device->property_tags_outdated = true; device->tags_generation ++; } void device_cleanup_devlinks(sd_device *device) { assert(device); set_free_free(device->devlinks); device->devlinks = NULL; device->property_devlinks_outdated = true; device->devlinks_generation ++; } void device_remove_tag(sd_device *device, const char *tag) { assert(device); assert(tag); free(set_remove(device->tags, tag)); device->property_tags_outdated = true; device->tags_generation ++; } static int device_tag(sd_device *device, const char *tag, bool add) { const char *id; char *path; int r; assert(device); assert(tag); r = device_get_id_filename(device, &id); if (r < 0) return r; path = strjoina("/run/udev/tags/", tag, "/", id); if (add) { r = touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0444); if (r < 0) return r; } else { r = unlink(path); if (r < 0 && errno != ENOENT) return -errno; } return 0; } int device_tag_index(sd_device *device, sd_device *device_old, bool add) { const char *tag; int r = 0, k; if (add && device_old) { /* delete possible left-over tags */ FOREACH_DEVICE_TAG(device_old, tag) { if (!sd_device_has_tag(device, tag)) { k = device_tag(device_old, tag, false); if (r >= 0 && k < 0) r = k; } } } FOREACH_DEVICE_TAG(device, tag) { k = device_tag(device, tag, add); if (r >= 0 && k < 0) r = k; } return r; } static bool device_has_info(sd_device *device) { assert(device); if (!set_isempty(device->devlinks)) return true; if (device->devlink_priority != 0) return true; if (!ordered_hashmap_isempty(device->properties_db)) return true; if (!set_isempty(device->tags)) return true; if (device->watch_handle >= 0) return true; return false; } void device_set_db_persist(sd_device *device) { assert(device); device->db_persist = true; } int device_update_db(sd_device *device) { const char *id; char *path; _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *path_tmp = NULL; bool has_info; int r; assert(device); has_info = device_has_info(device); r = device_get_id_filename(device, &id); if (r < 0) return r; path = strjoina("/run/udev/data/", id); /* do not store anything for otherwise empty devices */ if (!has_info && major(device->devnum) == 0 && device->ifindex == 0) { r = unlink(path); if (r < 0 && errno != ENOENT) return -errno; return 0; } /* write a database file */ r = mkdir_parents(path, 0755); if (r < 0) return r; r = fopen_temporary(path, &f, &path_tmp); if (r < 0) return r; /* * set 'sticky' bit to indicate that we should not clean the * database when we transition from initramfs to the real root */ if (device->db_persist) { r = fchmod(fileno(f), 01644); if (r < 0) { r = -errno; goto fail; } } else { r = fchmod(fileno(f), 0644); if (r < 0) { r = -errno; goto fail; } } if (has_info) { const char *property, *value, *tag; Iterator i; if (major(device->devnum) > 0) { const char *devlink; FOREACH_DEVICE_DEVLINK(device, devlink) fprintf(f, "S:%s\n", devlink + strlen("/dev/")); if (device->devlink_priority != 0) fprintf(f, "L:%i\n", device->devlink_priority); if (device->watch_handle >= 0) fprintf(f, "W:%i\n", device->watch_handle); } if (device->usec_initialized > 0) fprintf(f, "I:"USEC_FMT"\n", device->usec_initialized); ORDERED_HASHMAP_FOREACH_KEY(value, property, device->properties_db, i) fprintf(f, "E:%s=%s\n", property, value); FOREACH_DEVICE_TAG(device, tag) fprintf(f, "G:%s\n", tag); } r = fflush_and_check(f); if (r < 0) goto fail; r = rename(path_tmp, path); if (r < 0) { r = -errno; goto fail; } log_debug("created %s file '%s' for '%s'", has_info ? "db" : "empty", path, device->devpath); return 0; fail: (void) unlink(path); (void) unlink(path_tmp); return log_error_errno(r, "failed to create %s file '%s' for '%s'", has_info ? "db" : "empty", path, device->devpath); } int device_delete_db(sd_device *device) { const char *id; char *path; int r; assert(device); r = device_get_id_filename(device, &id); if (r < 0) return r; path = strjoina("/run/udev/data/", id); r = unlink(path); if (r < 0 && errno != ENOENT) return -errno; return 0; } int device_read_db_force(sd_device *device) { assert(device); return device_read_db_aux(device, true); } systemd-229/src/libsystemd/sd-device/device-private.h000066400000000000000000000056011265713322000227540ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-device.h" int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len); int device_new_from_strv(sd_device **ret, char **strv); int device_get_id_filename(sd_device *device, const char **ret); int device_get_devlink_priority(sd_device *device, int *priority); int device_get_watch_handle(sd_device *device, int *handle); int device_get_devnode_mode(sd_device *device, mode_t *mode); int device_get_devnode_uid(sd_device *device, uid_t *uid); int device_get_devnode_gid(sd_device *device, gid_t *gid); void device_seal(sd_device *device); void device_set_is_initialized(sd_device *device); void device_set_watch_handle(sd_device *device, int fd); void device_set_db_persist(sd_device *device); void device_set_devlink_priority(sd_device *device, int priority); int device_ensure_usec_initialized(sd_device *device, sd_device *device_old); int device_add_devlink(sd_device *device, const char *devlink); int device_add_property(sd_device *device, const char *property, const char *value); int device_add_tag(sd_device *device, const char *tag); void device_remove_tag(sd_device *device, const char *tag); void device_cleanup_tags(sd_device *device); void device_cleanup_devlinks(sd_device *device); uint64_t device_get_properties_generation(sd_device *device); uint64_t device_get_tags_generation(sd_device *device); uint64_t device_get_devlinks_generation(sd_device *device); int device_get_properties_nulstr(sd_device *device, const uint8_t **nulstr, size_t *len); int device_get_properties_strv(sd_device *device, char ***strv); int device_rename(sd_device *device, const char *name); int device_shallow_clone(sd_device *old_device, sd_device **new_device); int device_clone_with_db(sd_device *old_device, sd_device **new_device); int device_copy_properties(sd_device *device_dst, sd_device *device_src); int device_new_from_synthetic_event(sd_device **new_device, const char *syspath, const char *action); int device_tag_index(sd_device *dev, sd_device *dev_old, bool add); int device_update_db(sd_device *device); int device_delete_db(sd_device *device); int device_read_db_force(sd_device *device); systemd-229/src/libsystemd/sd-device/device-util.h000066400000000000000000000044411265713322000222600ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014-2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "util.h" #define FOREACH_DEVICE_PROPERTY(device, key, value) \ for (key = sd_device_get_property_first(device, &(value)); \ key; \ key = sd_device_get_property_next(device, &(value))) #define FOREACH_DEVICE_TAG(device, tag) \ for (tag = sd_device_get_tag_first(device); \ tag; \ tag = sd_device_get_tag_next(device)) #define FOREACH_DEVICE_SYSATTR(device, attr) \ for (attr = sd_device_get_sysattr_first(device); \ attr; \ attr = sd_device_get_sysattr_next(device)) #define FOREACH_DEVICE_DEVLINK(device, devlink) \ for (devlink = sd_device_get_devlink_first(device); \ devlink; \ devlink = sd_device_get_devlink_next(device)) #define FOREACH_DEVICE(enumerator, device) \ for (device = sd_device_enumerator_get_device_first(enumerator); \ device; \ device = sd_device_enumerator_get_device_next(enumerator)) #define FOREACH_SUBSYSTEM(enumerator, device) \ for (device = sd_device_enumerator_get_subsystem_first(enumerator); \ device; \ device = sd_device_enumerator_get_subsystem_next(enumerator)) systemd-229/src/libsystemd/sd-device/sd-device.c000066400000000000000000001474731265713322000217210ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-device.h" #include "alloc-util.h" #include "device-internal.h" #include "device-private.h" #include "device-util.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "hashmap.h" #include "macro.h" #include "parse-util.h" #include "path-util.h" #include "set.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" #include "strxcpyx.h" #include "util.h" int device_new_aux(sd_device **ret) { _cleanup_(sd_device_unrefp) sd_device *device = NULL; assert(ret); device = new0(sd_device, 1); if (!device) return -ENOMEM; device->n_ref = 1; device->watch_handle = -1; *ret = device; device = NULL; return 0; } _public_ sd_device *sd_device_ref(sd_device *device) { if (device) assert_se(++ device->n_ref >= 2); return device; } _public_ sd_device *sd_device_unref(sd_device *device) { if (device && -- device->n_ref == 0) { sd_device_unref(device->parent); free(device->syspath); free(device->sysname); free(device->devtype); free(device->devname); free(device->subsystem); free(device->driver); free(device->id_filename); free(device->properties_strv); free(device->properties_nulstr); ordered_hashmap_free_free_free(device->properties); ordered_hashmap_free_free_free(device->properties_db); hashmap_free_free_free(device->sysattr_values); set_free_free(device->sysattrs); set_free_free(device->tags); set_free_free(device->devlinks); free(device); } return NULL; } int device_add_property_aux(sd_device *device, const char *_key, const char *_value, bool db) { OrderedHashmap **properties; assert(device); assert(_key); if (db) properties = &device->properties_db; else properties = &device->properties; if (_value) { _cleanup_free_ char *key = NULL, *value = NULL, *old_key = NULL, *old_value = NULL; int r; r = ordered_hashmap_ensure_allocated(properties, &string_hash_ops); if (r < 0) return r; key = strdup(_key); if (!key) return -ENOMEM; value = strdup(_value); if (!value) return -ENOMEM; old_value = ordered_hashmap_get2(*properties, key, (void**) &old_key); r = ordered_hashmap_replace(*properties, key, value); if (r < 0) return r; key = NULL; value = NULL; } else { _cleanup_free_ char *key = NULL; _cleanup_free_ char *value = NULL; value = ordered_hashmap_remove2(*properties, _key, (void**) &key); } if (!db) { device->properties_generation ++; device->properties_buf_outdated = true; } return 0; } int device_add_property_internal(sd_device *device, const char *key, const char *value) { return device_add_property_aux(device, key, value, false); } int device_set_syspath(sd_device *device, const char *_syspath, bool verify) { _cleanup_free_ char *syspath = NULL; const char *devpath; int r; assert(device); assert(_syspath); /* must be a subdirectory of /sys */ if (!path_startswith(_syspath, "/sys/")) { log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath); return -EINVAL; } if (verify) { r = readlink_and_canonicalize(_syspath, &syspath); if (r == -ENOENT) /* the device does not exist (any more?) */ return -ENODEV; else if (r == -EINVAL) { /* not a symlink */ syspath = canonicalize_file_name(_syspath); if (!syspath) { if (errno == ENOENT) /* the device does not exist (any more?) */ return -ENODEV; return log_debug_errno(errno, "sd-device: could not canonicalize '%s': %m", _syspath); } } else if (r < 0) { log_debug_errno(r, "sd-device: could not get target of '%s': %m", _syspath); return r; } if (path_startswith(syspath, "/sys/devices/")) { char *path; /* all 'devices' require an 'uevent' file */ path = strjoina(syspath, "/uevent"); r = access(path, F_OK); if (r < 0) { if (errno == ENOENT) /* this is not a valid device */ return -ENODEV; log_debug("sd-device: %s does not have an uevent file: %m", syspath); return -errno; } } else { /* everything else just just needs to be a directory */ if (!is_dir(syspath, false)) return -ENODEV; } } else { syspath = strdup(_syspath); if (!syspath) return -ENOMEM; } devpath = syspath + strlen("/sys"); r = device_add_property_internal(device, "DEVPATH", devpath); if (r < 0) return r; free(device->syspath); device->syspath = syspath; syspath = NULL; device->devpath = devpath; return 0; } _public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) { _cleanup_(sd_device_unrefp) sd_device *device = NULL; int r; assert_return(ret, -EINVAL); assert_return(syspath, -EINVAL); r = device_new_aux(&device); if (r < 0) return r; r = device_set_syspath(device, syspath, true); if (r < 0) return r; *ret = device; device = NULL; return 0; } _public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum) { char *syspath; char id[DECIMAL_STR_MAX(unsigned) * 2 + 1]; assert_return(ret, -EINVAL); assert_return(type == 'b' || type == 'c', -EINVAL); /* use /sys/dev/{block,char}/: link */ snprintf(id, sizeof(id), "%u:%u", major(devnum), minor(devnum)); syspath = strjoina("/sys/dev/", (type == 'b' ? "block" : "char"), "/", id); return sd_device_new_from_syspath(ret, syspath); } _public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, const char *sysname) { char *syspath; assert_return(ret, -EINVAL); assert_return(subsystem, -EINVAL); assert_return(sysname, -EINVAL); if (streq(subsystem, "subsystem")) { syspath = strjoina("/sys/subsystem/", sysname); if (access(syspath, F_OK) >= 0) return sd_device_new_from_syspath(ret, syspath); syspath = strjoina("/sys/bus/", sysname); if (access(syspath, F_OK) >= 0) return sd_device_new_from_syspath(ret, syspath); syspath = strjoina("/sys/class/", sysname); if (access(syspath, F_OK) >= 0) return sd_device_new_from_syspath(ret, syspath); } else if (streq(subsystem, "module")) { syspath = strjoina("/sys/module/", sysname); if (access(syspath, F_OK) >= 0) return sd_device_new_from_syspath(ret, syspath); } else if (streq(subsystem, "drivers")) { char subsys[PATH_MAX]; char *driver; strscpy(subsys, sizeof(subsys), sysname); driver = strchr(subsys, ':'); if (driver) { driver[0] = '\0'; driver++; syspath = strjoina("/sys/subsystem/", subsys, "/drivers/", driver); if (access(syspath, F_OK) >= 0) return sd_device_new_from_syspath(ret, syspath); syspath = strjoina("/sys/bus/", subsys, "/drivers/", driver); if (access(syspath, F_OK) >= 0) return sd_device_new_from_syspath(ret, syspath); } else return -EINVAL; } else { char *name; size_t len = 0; /* translate sysname back to sysfs filename */ name = strdupa(sysname); while (name[len] != '\0') { if (name[len] == '/') name[len] = '!'; len ++; } syspath = strjoina("/sys/subsystem/", subsystem, "/devices/", name); if (access(syspath, F_OK) >= 0) return sd_device_new_from_syspath(ret, syspath); syspath = strjoina("/sys/bus/", subsystem, "/devices/", name); if (access(syspath, F_OK) >= 0) return sd_device_new_from_syspath(ret, syspath); syspath = strjoina("/sys/class/", subsystem, "/", name); if (access(syspath, F_OK) >= 0) return sd_device_new_from_syspath(ret, syspath); } return -ENODEV; } int device_set_devtype(sd_device *device, const char *_devtype) { _cleanup_free_ char *devtype = NULL; int r; assert(device); assert(_devtype); devtype = strdup(_devtype); if (!devtype) return -ENOMEM; r = device_add_property_internal(device, "DEVTYPE", devtype); if (r < 0) return r; free(device->devtype); device->devtype = devtype; devtype = NULL; return 0; } int device_set_ifindex(sd_device *device, const char *_ifindex) { int ifindex, r; assert(device); assert(_ifindex); r = parse_ifindex(_ifindex, &ifindex); if (r < 0) return r; r = device_add_property_internal(device, "IFINDEX", _ifindex); if (r < 0) return r; device->ifindex = ifindex; return 0; } int device_set_devname(sd_device *device, const char *_devname) { _cleanup_free_ char *devname = NULL; int r; assert(device); assert(_devname); if (_devname[0] != '/') { r = asprintf(&devname, "/dev/%s", _devname); if (r < 0) return -ENOMEM; } else { devname = strdup(_devname); if (!devname) return -ENOMEM; } r = device_add_property_internal(device, "DEVNAME", devname); if (r < 0) return r; free(device->devname); device->devname = devname; devname = NULL; return 0; } int device_set_devmode(sd_device *device, const char *_devmode) { unsigned devmode; int r; assert(device); assert(_devmode); r = safe_atou(_devmode, &devmode); if (r < 0) return r; if (devmode > 07777) return -EINVAL; r = device_add_property_internal(device, "DEVMODE", _devmode); if (r < 0) return r; device->devmode = devmode; return 0; } int device_set_devnum(sd_device *device, const char *major, const char *minor) { unsigned maj = 0, min = 0; int r; assert(device); assert(major); r = safe_atou(major, &maj); if (r < 0) return r; if (!maj) return 0; if (minor) { r = safe_atou(minor, &min); if (r < 0) return r; } r = device_add_property_internal(device, "MAJOR", major); if (r < 0) return r; if (minor) { r = device_add_property_internal(device, "MINOR", minor); if (r < 0) return r; } device->devnum = makedev(maj, min); return 0; } static int handle_uevent_line(sd_device *device, const char *key, const char *value, const char **major, const char **minor) { int r; assert(device); assert(key); assert(value); assert(major); assert(minor); if (streq(key, "DEVTYPE")) { r = device_set_devtype(device, value); if (r < 0) return r; } else if (streq(key, "IFINDEX")) { r = device_set_ifindex(device, value); if (r < 0) return r; } else if (streq(key, "DEVNAME")) { r = device_set_devname(device, value); if (r < 0) return r; } else if (streq(key, "DEVMODE")) { r = device_set_devmode(device, value); if (r < 0) return r; } else if (streq(key, "MAJOR")) *major = value; else if (streq(key, "MINOR")) *minor = value; else { r = device_add_property_internal(device, key, value); if (r < 0) return r; } return 0; } int device_read_uevent_file(sd_device *device) { _cleanup_free_ char *uevent = NULL; const char *syspath, *key = NULL, *value = NULL, *major = NULL, *minor = NULL; char *path; size_t uevent_len; unsigned i; int r; enum { PRE_KEY, KEY, PRE_VALUE, VALUE, INVALID_LINE, } state = PRE_KEY; assert(device); if (device->uevent_loaded || device->sealed) return 0; device->uevent_loaded = true; r = sd_device_get_syspath(device, &syspath); if (r < 0) return r; path = strjoina(syspath, "/uevent"); r = read_full_file(path, &uevent, &uevent_len); if (r == -EACCES) /* empty uevent files may be write-only */ return 0; else if (r == -ENOENT) /* some devices may not have uevent files, see set_syspath() */ return 0; else if (r < 0) { log_debug_errno(r, "sd-device: failed to read uevent file '%s': %m", path); return r; } for (i = 0; i < uevent_len; i++) { switch (state) { case PRE_KEY: if (!strchr(NEWLINE, uevent[i])) { key = &uevent[i]; state = KEY; } break; case KEY: if (uevent[i] == '=') { uevent[i] = '\0'; state = PRE_VALUE; } else if (strchr(NEWLINE, uevent[i])) { uevent[i] = '\0'; log_debug("sd-device: ignoring invalid uevent line '%s'", key); state = PRE_KEY; } break; case PRE_VALUE: value = &uevent[i]; state = VALUE; break; case VALUE: if (strchr(NEWLINE, uevent[i])) { uevent[i] = '\0'; r = handle_uevent_line(device, key, value, &major, &minor); if (r < 0) log_debug_errno(r, "sd-device: failed to handle uevent entry '%s=%s': %m", key, value); state = PRE_KEY; } break; default: assert_not_reached("invalid state when parsing uevent file"); } } if (major) { r = device_set_devnum(device, major, minor); if (r < 0) log_debug_errno(r, "sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major, minor, path); } return 0; } _public_ int sd_device_get_ifindex(sd_device *device, int *ifindex) { int r; assert_return(device, -EINVAL); assert_return(ifindex, -EINVAL); r = device_read_uevent_file(device); if (r < 0) return r; *ifindex = device->ifindex; return 0; } _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) { int r; assert_return(ret, -EINVAL); assert_return(id, -EINVAL); switch (id[0]) { case 'b': case 'c': { char type; int maj, min; r = sscanf(id, "%c%i:%i", &type, &maj, &min); if (r != 3) return -EINVAL; return sd_device_new_from_devnum(ret, type, makedev(maj, min)); } case 'n': { _cleanup_(sd_device_unrefp) sd_device *device = NULL; _cleanup_close_ int sk = -1; struct ifreq ifr = {}; int ifindex; r = parse_ifindex(&id[1], &ifr.ifr_ifindex); if (r < 0) return r; sk = socket(PF_INET, SOCK_DGRAM, 0); if (sk < 0) return -errno; r = ioctl(sk, SIOCGIFNAME, &ifr); if (r < 0) return -errno; r = sd_device_new_from_subsystem_sysname(&device, "net", ifr.ifr_name); if (r < 0) return r; r = sd_device_get_ifindex(device, &ifindex); if (r < 0) return r; /* this is racey, so we might end up with the wrong device */ if (ifr.ifr_ifindex != ifindex) return -ENODEV; *ret = device; device = NULL; return 0; } case '+': { char subsys[PATH_MAX]; char *sysname; (void)strscpy(subsys, sizeof(subsys), id + 1); sysname = strchr(subsys, ':'); if (!sysname) return -EINVAL; sysname[0] = '\0'; sysname ++; return sd_device_new_from_subsystem_sysname(ret, subsys, sysname); } default: return -EINVAL; } } _public_ int sd_device_get_syspath(sd_device *device, const char **ret) { assert_return(device, -EINVAL); assert_return(ret, -EINVAL); assert(path_startswith(device->syspath, "/sys/")); *ret = device->syspath; return 0; } static int device_new_from_child(sd_device **ret, sd_device *child) { _cleanup_free_ char *path = NULL; const char *subdir, *syspath; int r; assert(ret); assert(child); r = sd_device_get_syspath(child, &syspath); if (r < 0) return r; path = strdup(syspath); if (!path) return -ENOMEM; subdir = path + strlen("/sys"); for (;;) { char *pos; pos = strrchr(subdir, '/'); if (!pos || pos < subdir + 2) break; *pos = '\0'; r = sd_device_new_from_syspath(ret, path); if (r < 0) continue; return 0; } return -ENODEV; } _public_ int sd_device_get_parent(sd_device *child, sd_device **ret) { assert_return(ret, -EINVAL); assert_return(child, -EINVAL); if (!child->parent_set) { child->parent_set = true; (void)device_new_from_child(&child->parent, child); } if (!child->parent) return -ENOENT; *ret = child->parent; return 0; } int device_set_subsystem(sd_device *device, const char *_subsystem) { _cleanup_free_ char *subsystem = NULL; int r; assert(device); assert(_subsystem); subsystem = strdup(_subsystem); if (!subsystem) return -ENOMEM; r = device_add_property_internal(device, "SUBSYSTEM", subsystem); if (r < 0) return r; free(device->subsystem); device->subsystem = subsystem; subsystem = NULL; device->subsystem_set = true; return 0; } _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) { assert_return(ret, -EINVAL); assert_return(device, -EINVAL); if (!device->subsystem_set) { _cleanup_free_ char *subsystem = NULL; const char *syspath; char *path; int r; /* read 'subsystem' link */ r = sd_device_get_syspath(device, &syspath); if (r < 0) return r; path = strjoina(syspath, "/subsystem"); r = readlink_value(path, &subsystem); if (r >= 0) r = device_set_subsystem(device, subsystem); /* use implicit names */ else if (path_startswith(device->devpath, "/module/")) r = device_set_subsystem(device, "module"); else if (strstr(device->devpath, "/drivers/")) r = device_set_subsystem(device, "drivers"); else if (path_startswith(device->devpath, "/subsystem/") || path_startswith(device->devpath, "/class/") || path_startswith(device->devpath, "/bus/")) r = device_set_subsystem(device, "subsystem"); if (r < 0 && r != -ENOENT) return log_debug_errno(r, "sd-device: could not set subsystem for %s: %m", device->devpath); device->subsystem_set = true; } if (!device->subsystem) return -ENOENT; *ret = device->subsystem; return 0; } _public_ int sd_device_get_devtype(sd_device *device, const char **devtype) { int r; assert(devtype); assert(device); r = device_read_uevent_file(device); if (r < 0) return r; *devtype = device->devtype; return 0; } _public_ int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *subsystem, const char *devtype, sd_device **ret) { sd_device *parent = NULL; int r; assert_return(child, -EINVAL); assert_return(subsystem, -EINVAL); r = sd_device_get_parent(child, &parent); while (r >= 0) { const char *parent_subsystem = NULL; const char *parent_devtype = NULL; (void)sd_device_get_subsystem(parent, &parent_subsystem); if (streq_ptr(parent_subsystem, subsystem)) { if (!devtype) break; (void)sd_device_get_devtype(parent, &parent_devtype); if (streq_ptr(parent_devtype, devtype)) break; } r = sd_device_get_parent(parent, &parent); } if (r < 0) return r; *ret = parent; return 0; } _public_ int sd_device_get_devnum(sd_device *device, dev_t *devnum) { int r; assert_return(device, -EINVAL); assert_return(devnum, -EINVAL); r = device_read_uevent_file(device); if (r < 0) return r; *devnum = device->devnum; return 0; } int device_set_driver(sd_device *device, const char *_driver) { _cleanup_free_ char *driver = NULL; int r; assert(device); assert(_driver); driver = strdup(_driver); if (!driver) return -ENOMEM; r = device_add_property_internal(device, "DRIVER", driver); if (r < 0) return r; free(device->driver); device->driver = driver; driver = NULL; device->driver_set = true; return 0; } _public_ int sd_device_get_driver(sd_device *device, const char **ret) { assert_return(device, -EINVAL); assert_return(ret, -EINVAL); if (!device->driver_set) { _cleanup_free_ char *driver = NULL; const char *syspath; char *path; int r; r = sd_device_get_syspath(device, &syspath); if (r < 0) return r; path = strjoina(syspath, "/driver"); r = readlink_value(path, &driver); if (r >= 0) { r = device_set_driver(device, driver); if (r < 0) return log_debug_errno(r, "sd-device: could not set driver for %s: %m", device->devpath); } else if (r == -ENOENT) device->driver_set = true; else return log_debug_errno(r, "sd-device: could not set driver for %s: %m", device->devpath); } if (!device->driver) return -ENOENT; *ret = device->driver; return 0; } _public_ int sd_device_get_devpath(sd_device *device, const char **devpath) { assert_return(device, -EINVAL); assert_return(devpath, -EINVAL); assert(device->devpath); assert(device->devpath[0] == '/'); *devpath = device->devpath; return 0; } _public_ int sd_device_get_devname(sd_device *device, const char **devname) { int r; assert_return(device, -EINVAL); assert_return(devname, -EINVAL); r = device_read_uevent_file(device); if (r < 0) return r; if (!device->devname) return -ENOENT; assert(path_startswith(device->devname, "/dev/")); *devname = device->devname; return 0; } static int device_set_sysname(sd_device *device) { _cleanup_free_ char *sysname = NULL; const char *sysnum = NULL; const char *pos; size_t len = 0; pos = strrchr(device->devpath, '/'); if (!pos) return -EINVAL; pos ++; /* devpath is not a root directory */ if (*pos == '\0' || pos <= device->devpath) return -EINVAL; sysname = strdup(pos); if (!sysname) return -ENOMEM; /* some devices have '!' in their name, change that to '/' */ while (sysname[len] != '\0') { if (sysname[len] == '!') sysname[len] = '/'; len ++; } /* trailing number */ while (len > 0 && isdigit(sysname[--len])) sysnum = &sysname[len]; if (len == 0) sysnum = NULL; free(device->sysname); device->sysname = sysname; sysname = NULL; device->sysnum = sysnum; device->sysname_set = true; return 0; } _public_ int sd_device_get_sysname(sd_device *device, const char **ret) { int r; assert_return(device, -EINVAL); assert_return(ret, -EINVAL); if (!device->sysname_set) { r = device_set_sysname(device); if (r < 0) return r; } assert_return(device->sysname, -ENOENT); *ret = device->sysname; return 0; } _public_ int sd_device_get_sysnum(sd_device *device, const char **ret) { int r; assert_return(device, -EINVAL); assert_return(ret, -EINVAL); if (!device->sysname_set) { r = device_set_sysname(device); if (r < 0) return r; } *ret = device->sysnum; return 0; } static bool is_valid_tag(const char *tag) { assert(tag); return !strchr(tag, ':') && !strchr(tag, ' '); } int device_add_tag(sd_device *device, const char *tag) { int r; assert(device); assert(tag); if (!is_valid_tag(tag)) return -EINVAL; r = set_ensure_allocated(&device->tags, &string_hash_ops); if (r < 0) return r; r = set_put_strdup(device->tags, tag); if (r < 0) return r; device->tags_generation ++; device->property_tags_outdated = true; return 0; } int device_add_devlink(sd_device *device, const char *devlink) { int r; assert(device); assert(devlink); r = set_ensure_allocated(&device->devlinks, &string_hash_ops); if (r < 0) return r; r = set_put_strdup(device->devlinks, devlink); if (r < 0) return r; device->devlinks_generation ++; device->property_devlinks_outdated = true; return 0; } static int device_add_property_internal_from_string(sd_device *device, const char *str) { _cleanup_free_ char *key = NULL; char *value; assert(device); assert(str); key = strdup(str); if (!key) return -ENOMEM; value = strchr(key, '='); if (!value) return -EINVAL; *value = '\0'; if (isempty(++value)) value = NULL; return device_add_property_internal(device, key, value); } int device_set_usec_initialized(sd_device *device, const char *initialized) { uint64_t usec_initialized; int r; assert(device); assert(initialized); r = safe_atou64(initialized, &usec_initialized); if (r < 0) return r; r = device_add_property_internal(device, "USEC_INITIALIZED", initialized); if (r < 0) return r; device->usec_initialized = usec_initialized; return 0; } static int handle_db_line(sd_device *device, char key, const char *value) { char *path; int r; assert(device); assert(value); switch (key) { case 'G': r = device_add_tag(device, value); if (r < 0) return r; break; case 'S': path = strjoina("/dev/", value); r = device_add_devlink(device, path); if (r < 0) return r; break; case 'E': r = device_add_property_internal_from_string(device, value); if (r < 0) return r; break; case 'I': r = device_set_usec_initialized(device, value); if (r < 0) return r; break; case 'L': r = safe_atoi(value, &device->devlink_priority); if (r < 0) return r; break; case 'W': r = safe_atoi(value, &device->watch_handle); if (r < 0) return r; break; default: log_debug("device db: unknown key '%c'", key); } return 0; } int device_get_id_filename(sd_device *device, const char **ret) { assert(device); assert(ret); if (!device->id_filename) { _cleanup_free_ char *id = NULL; const char *subsystem; dev_t devnum; int ifindex, r; r = sd_device_get_subsystem(device, &subsystem); if (r < 0) return r; r = sd_device_get_devnum(device, &devnum); if (r < 0) return r; r = sd_device_get_ifindex(device, &ifindex); if (r < 0) return r; if (major(devnum) > 0) { assert(subsystem); /* use dev_t -- b259:131072, c254:0 */ r = asprintf(&id, "%c%u:%u", streq(subsystem, "block") ? 'b' : 'c', major(devnum), minor(devnum)); if (r < 0) return -ENOMEM; } else if (ifindex > 0) { /* use netdev ifindex -- n3 */ r = asprintf(&id, "n%u", ifindex); if (r < 0) return -ENOMEM; } else { /* use $subsys:$sysname -- pci:0000:00:1f.2 * sysname() has '!' translated, get it from devpath */ const char *sysname; sysname = basename(device->devpath); if (!sysname) return -EINVAL; if (!subsystem) return -EINVAL; r = asprintf(&id, "+%s:%s", subsystem, sysname); if (r < 0) return -ENOMEM; } device->id_filename = id; id = NULL; } *ret = device->id_filename; return 0; } int device_read_db_aux(sd_device *device, bool force) { _cleanup_free_ char *db = NULL; char *path; const char *id, *value; char key; size_t db_len; unsigned i; int r; enum { PRE_KEY, KEY, PRE_VALUE, VALUE, INVALID_LINE, } state = PRE_KEY; if (device->db_loaded || (!force && device->sealed)) return 0; device->db_loaded = true; r = device_get_id_filename(device, &id); if (r < 0) return r; path = strjoina("/run/udev/data/", id); r = read_full_file(path, &db, &db_len); if (r < 0) { if (r == -ENOENT) return 0; else return log_debug_errno(r, "sd-device: failed to read db '%s': %m", path); } /* devices with a database entry are initialized */ device->is_initialized = true; for (i = 0; i < db_len; i++) { switch (state) { case PRE_KEY: if (!strchr(NEWLINE, db[i])) { key = db[i]; state = KEY; } break; case KEY: if (db[i] != ':') { log_debug("sd-device: ignoring invalid db entry with key '%c'", key); state = INVALID_LINE; } else { db[i] = '\0'; state = PRE_VALUE; } break; case PRE_VALUE: value = &db[i]; state = VALUE; break; case INVALID_LINE: if (strchr(NEWLINE, db[i])) state = PRE_KEY; break; case VALUE: if (strchr(NEWLINE, db[i])) { db[i] = '\0'; r = handle_db_line(device, key, value); if (r < 0) log_debug_errno(r, "sd-device: failed to handle db entry '%c:%s': %m", key, value); state = PRE_KEY; } break; default: assert_not_reached("invalid state when parsing db"); } } return 0; } static int device_read_db(sd_device *device) { return device_read_db_aux(device, false); } _public_ int sd_device_get_is_initialized(sd_device *device, int *initialized) { int r; assert_return(device, -EINVAL); assert_return(initialized, -EINVAL); r = device_read_db(device); if (r < 0) return r; *initialized = device->is_initialized; return 0; } _public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec) { usec_t now_ts; int r; assert_return(device, -EINVAL); assert_return(usec, -EINVAL); r = device_read_db(device); if (r < 0) return r; if (!device->is_initialized) return -EBUSY; if (!device->usec_initialized) return -ENODATA; now_ts = now(clock_boottime_or_monotonic()); if (now_ts < device->usec_initialized) return -EIO; *usec = now_ts - device->usec_initialized; return 0; } _public_ const char *sd_device_get_tag_first(sd_device *device) { void *v; assert_return(device, NULL); (void) device_read_db(device); device->tags_iterator_generation = device->tags_generation; device->tags_iterator = ITERATOR_FIRST; set_iterate(device->tags, &device->tags_iterator, &v); return v; } _public_ const char *sd_device_get_tag_next(sd_device *device) { void *v; assert_return(device, NULL); (void) device_read_db(device); if (device->tags_iterator_generation != device->tags_generation) return NULL; set_iterate(device->tags, &device->tags_iterator, &v); return v; } _public_ const char *sd_device_get_devlink_first(sd_device *device) { void *v; assert_return(device, NULL); (void) device_read_db(device); device->devlinks_iterator_generation = device->devlinks_generation; device->devlinks_iterator = ITERATOR_FIRST; set_iterate(device->devlinks, &device->devlinks_iterator, &v); return v; } _public_ const char *sd_device_get_devlink_next(sd_device *device) { void *v; assert_return(device, NULL); (void) device_read_db(device); if (device->devlinks_iterator_generation != device->devlinks_generation) return NULL; set_iterate(device->devlinks, &device->devlinks_iterator, &v); return v; } static int device_properties_prepare(sd_device *device) { int r; assert(device); r = device_read_uevent_file(device); if (r < 0) return r; r = device_read_db(device); if (r < 0) return r; if (device->property_devlinks_outdated) { char *devlinks = NULL; const char *devlink; devlink = sd_device_get_devlink_first(device); if (devlink) devlinks = strdupa(devlink); while ((devlink = sd_device_get_devlink_next(device))) devlinks = strjoina(devlinks, " ", devlink); r = device_add_property_internal(device, "DEVLINKS", devlinks); if (r < 0) return r; device->property_devlinks_outdated = false; } if (device->property_tags_outdated) { char *tags = NULL; const char *tag; tag = sd_device_get_tag_first(device); if (tag) tags = strjoina(":", tag); while ((tag = sd_device_get_tag_next(device))) tags = strjoina(tags, ":", tag); tags = strjoina(tags, ":"); r = device_add_property_internal(device, "TAGS", tags); if (r < 0) return r; device->property_tags_outdated = false; } return 0; } _public_ const char *sd_device_get_property_first(sd_device *device, const char **_value) { const char *key; const char *value; int r; assert_return(device, NULL); r = device_properties_prepare(device); if (r < 0) return NULL; device->properties_iterator_generation = device->properties_generation; device->properties_iterator = ITERATOR_FIRST; ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)&value, (const void**)&key); if (_value) *_value = value; return key; } _public_ const char *sd_device_get_property_next(sd_device *device, const char **_value) { const char *key; const char *value; int r; assert_return(device, NULL); r = device_properties_prepare(device); if (r < 0) return NULL; if (device->properties_iterator_generation != device->properties_generation) return NULL; ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)&value, (const void**)&key); if (_value) *_value = value; return key; } static int device_sysattrs_read_all(sd_device *device) { _cleanup_closedir_ DIR *dir = NULL; const char *syspath; struct dirent *dent; int r; assert(device); if (device->sysattrs_read) return 0; r = sd_device_get_syspath(device, &syspath); if (r < 0) return r; dir = opendir(syspath); if (!dir) return -errno; r = set_ensure_allocated(&device->sysattrs, &string_hash_ops); if (r < 0) return r; for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { char *path; struct stat statbuf; /* only handle symlinks and regular files */ if (dent->d_type != DT_LNK && dent->d_type != DT_REG) continue; path = strjoina(syspath, "/", dent->d_name); if (lstat(path, &statbuf) != 0) continue; if (!(statbuf.st_mode & S_IRUSR)) continue; r = set_put_strdup(device->sysattrs, dent->d_name); if (r < 0) return r; } device->sysattrs_read = true; return 0; } _public_ const char *sd_device_get_sysattr_first(sd_device *device) { void *v; int r; assert_return(device, NULL); if (!device->sysattrs_read) { r = device_sysattrs_read_all(device); if (r < 0) { errno = -r; return NULL; } } device->sysattrs_iterator = ITERATOR_FIRST; set_iterate(device->sysattrs, &device->sysattrs_iterator, &v); return v; } _public_ const char *sd_device_get_sysattr_next(sd_device *device) { void *v; assert_return(device, NULL); if (!device->sysattrs_read) return NULL; set_iterate(device->sysattrs, &device->sysattrs_iterator, &v); return v; } _public_ int sd_device_has_tag(sd_device *device, const char *tag) { assert_return(device, -EINVAL); assert_return(tag, -EINVAL); (void) device_read_db(device); return !!set_contains(device->tags, tag); } _public_ int sd_device_get_property_value(sd_device *device, const char *key, const char **_value) { char *value; int r; assert_return(device, -EINVAL); assert_return(key, -EINVAL); assert_return(_value, -EINVAL); r = device_properties_prepare(device); if (r < 0) return r; value = ordered_hashmap_get(device->properties, key); if (!value) return -ENOENT; *_value = value; return 0; } /* replaces the value if it already exists */ static int device_add_sysattr_value(sd_device *device, const char *_key, char *value) { _cleanup_free_ char *key = NULL; _cleanup_free_ char *value_old = NULL; int r; assert(device); assert(_key); r = hashmap_ensure_allocated(&device->sysattr_values, &string_hash_ops); if (r < 0) return r; value_old = hashmap_remove2(device->sysattr_values, _key, (void **)&key); if (!key) { key = strdup(_key); if (!key) return -ENOMEM; } r = hashmap_put(device->sysattr_values, key, value); if (r < 0) return r; key = NULL; return 0; } static int device_get_sysattr_value(sd_device *device, const char *_key, const char **_value) { const char *key = NULL, *value; assert(device); assert(_key); value = hashmap_get2(device->sysattr_values, _key, (void **) &key); if (!key) return -ENOENT; if (_value) *_value = value; return 0; } /* We cache all sysattr lookups. If an attribute does not exist, it is stored * with a NULL value in the cache, otherwise the returned string is stored */ _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value) { _cleanup_free_ char *value = NULL; const char *syspath, *cached_value = NULL; char *path; struct stat statbuf; int r; assert_return(device, -EINVAL); assert_return(sysattr, -EINVAL); /* look for possibly already cached result */ r = device_get_sysattr_value(device, sysattr, &cached_value); if (r != -ENOENT) { if (r < 0) return r; if (!cached_value) /* we looked up the sysattr before and it did not exist */ return -ENOENT; if (_value) *_value = cached_value; return 0; } r = sd_device_get_syspath(device, &syspath); if (r < 0) return r; path = strjoina(syspath, "/", sysattr); r = lstat(path, &statbuf); if (r < 0) { /* remember that we could not access the sysattr */ r = device_add_sysattr_value(device, sysattr, NULL); if (r < 0) return r; return -ENOENT; } else if (S_ISLNK(statbuf.st_mode)) { /* Some core links return only the last element of the target path, * these are just values, the paths should not be exposed. */ if (STR_IN_SET(sysattr, "driver", "subsystem", "module")) { r = readlink_value(path, &value); if (r < 0) return r; } else return -EINVAL; } else if (S_ISDIR(statbuf.st_mode)) { /* skip directories */ return -EINVAL; } else if (!(statbuf.st_mode & S_IRUSR)) { /* skip non-readable files */ return -EPERM; } else { size_t size; /* read attribute value */ r = read_full_file(path, &value, &size); if (r < 0) return r; /* drop trailing newlines */ while (size > 0 && value[--size] == '\n') value[size] = '\0'; } r = device_add_sysattr_value(device, sysattr, value); if (r < 0) return r; *_value = value; value = NULL; return 0; } static void device_remove_sysattr_value(sd_device *device, const char *_key) { _cleanup_free_ char *key = NULL; _cleanup_free_ char *value = NULL; assert(device); assert(_key); value = hashmap_remove2(device->sysattr_values, _key, (void **) &key); return; } /* set the attribute and save it in the cache. If a NULL value is passed the * attribute is cleared from the cache */ _public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, char *_value) { _cleanup_close_ int fd = -1; _cleanup_free_ char *value = NULL; const char *syspath; char *path; struct stat statbuf; size_t value_len = 0; ssize_t size; int r; assert_return(device, -EINVAL); assert_return(sysattr, -EINVAL); if (!_value) { device_remove_sysattr_value(device, sysattr); return 0; } r = sd_device_get_syspath(device, &syspath); if (r < 0) return r; path = strjoina(syspath, "/", sysattr); r = lstat(path, &statbuf); if (r < 0) { value = strdup(""); if (!value) return -ENOMEM; r = device_add_sysattr_value(device, sysattr, value); if (r < 0) return r; return -ENXIO; } if (S_ISLNK(statbuf.st_mode)) return -EINVAL; /* skip directories */ if (S_ISDIR(statbuf.st_mode)) return -EISDIR; /* skip non-readable files */ if ((statbuf.st_mode & S_IRUSR) == 0) return -EACCES; value_len = strlen(_value); /* drop trailing newlines */ while (value_len > 0 && _value[value_len - 1] == '\n') _value[--value_len] = '\0'; /* value length is limited to 4k */ if (value_len > 4096) return -EINVAL; fd = open(path, O_WRONLY | O_CLOEXEC); if (fd < 0) return -errno; value = strdup(_value); if (!value) return -ENOMEM; size = write(fd, value, value_len); if (size < 0) return -errno; if ((size_t)size != value_len) return -EIO; r = device_add_sysattr_value(device, sysattr, value); if (r < 0) return r; value = NULL; return 0; } systemd-229/src/libsystemd/sd-event/000077500000000000000000000000001265713322000175545ustar00rootroot00000000000000systemd-229/src/libsystemd/sd-event/Makefile000077700000000000000000000000001265713322000232752../../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd/sd-event/sd-event.c000066400000000000000000002402041265713322000214470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-daemon.h" #include "sd-event.h" #include "sd-id128.h" #include "alloc-util.h" #include "fd-util.h" #include "hashmap.h" #include "list.h" #include "macro.h" #include "missing.h" #include "prioq.h" #include "process-util.h" #include "set.h" #include "signal-util.h" #include "string-table.h" #include "string-util.h" #include "time-util.h" #include "util.h" #define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC) typedef enum EventSourceType { SOURCE_IO, SOURCE_TIME_REALTIME, SOURCE_TIME_BOOTTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM, SOURCE_SIGNAL, SOURCE_CHILD, SOURCE_DEFER, SOURCE_POST, SOURCE_EXIT, SOURCE_WATCHDOG, _SOURCE_EVENT_SOURCE_TYPE_MAX, _SOURCE_EVENT_SOURCE_TYPE_INVALID = -1 } EventSourceType; static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = { [SOURCE_IO] = "io", [SOURCE_TIME_REALTIME] = "realtime", [SOURCE_TIME_BOOTTIME] = "bootime", [SOURCE_TIME_MONOTONIC] = "monotonic", [SOURCE_TIME_REALTIME_ALARM] = "realtime-alarm", [SOURCE_TIME_BOOTTIME_ALARM] = "boottime-alarm", [SOURCE_SIGNAL] = "signal", [SOURCE_CHILD] = "child", [SOURCE_DEFER] = "defer", [SOURCE_POST] = "post", [SOURCE_EXIT] = "exit", [SOURCE_WATCHDOG] = "watchdog", }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int); /* All objects we use in epoll events start with this value, so that * we know how to dispatch it */ typedef enum WakeupType { WAKEUP_NONE, WAKEUP_EVENT_SOURCE, WAKEUP_CLOCK_DATA, WAKEUP_SIGNAL_DATA, _WAKEUP_TYPE_MAX, _WAKEUP_TYPE_INVALID = -1, } WakeupType; #define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_BOOTTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM) struct sd_event_source { WakeupType wakeup; unsigned n_ref; sd_event *event; void *userdata; sd_event_handler_t prepare; char *description; EventSourceType type:5; int enabled:3; bool pending:1; bool dispatching:1; bool floating:1; int64_t priority; unsigned pending_index; unsigned prepare_index; unsigned pending_iteration; unsigned prepare_iteration; LIST_FIELDS(sd_event_source, sources); union { struct { sd_event_io_handler_t callback; int fd; uint32_t events; uint32_t revents; bool registered:1; } io; struct { sd_event_time_handler_t callback; usec_t next, accuracy; unsigned earliest_index; unsigned latest_index; } time; struct { sd_event_signal_handler_t callback; struct signalfd_siginfo siginfo; int sig; } signal; struct { sd_event_child_handler_t callback; siginfo_t siginfo; pid_t pid; int options; } child; struct { sd_event_handler_t callback; } defer; struct { sd_event_handler_t callback; } post; struct { sd_event_handler_t callback; unsigned prioq_index; } exit; }; }; struct clock_data { WakeupType wakeup; int fd; /* For all clocks we maintain two priority queues each, one * ordered for the earliest times the events may be * dispatched, and one ordered by the latest times they must * have been dispatched. The range between the top entries in * the two prioqs is the time window we can freely schedule * wakeups in */ Prioq *earliest; Prioq *latest; usec_t next; bool needs_rearm:1; }; struct signal_data { WakeupType wakeup; /* For each priority we maintain one signal fd, so that we * only have to dequeue a single event per priority at a * time. */ int fd; int64_t priority; sigset_t sigset; sd_event_source *current; }; struct sd_event { unsigned n_ref; int epoll_fd; int watchdog_fd; Prioq *pending; Prioq *prepare; /* timerfd_create() only supports these five clocks so far. We * can add support for more clocks when the kernel learns to * deal with them, too. */ struct clock_data realtime; struct clock_data boottime; struct clock_data monotonic; struct clock_data realtime_alarm; struct clock_data boottime_alarm; usec_t perturb; sd_event_source **signal_sources; /* indexed by signal number */ Hashmap *signal_data; /* indexed by priority */ Hashmap *child_sources; unsigned n_enabled_child_sources; Set *post_sources; Prioq *exit; pid_t original_pid; unsigned iteration; dual_timestamp timestamp; usec_t timestamp_boottime; int state; bool exit_requested:1; bool need_process_child:1; bool watchdog:1; bool profile_delays:1; int exit_code; pid_t tid; sd_event **default_event_ptr; usec_t watchdog_last, watchdog_period; unsigned n_sources; LIST_HEAD(sd_event_source, sources); usec_t last_run, last_log; unsigned delays[sizeof(usec_t) * 8]; }; static void source_disconnect(sd_event_source *s); static int pending_prioq_compare(const void *a, const void *b) { const sd_event_source *x = a, *y = b; assert(x->pending); assert(y->pending); /* Enabled ones first */ if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) return -1; if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) return 1; /* Lower priority values first */ if (x->priority < y->priority) return -1; if (x->priority > y->priority) return 1; /* Older entries first */ if (x->pending_iteration < y->pending_iteration) return -1; if (x->pending_iteration > y->pending_iteration) return 1; return 0; } static int prepare_prioq_compare(const void *a, const void *b) { const sd_event_source *x = a, *y = b; assert(x->prepare); assert(y->prepare); /* Enabled ones first */ if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) return -1; if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) return 1; /* Move most recently prepared ones last, so that we can stop * preparing as soon as we hit one that has already been * prepared in the current iteration */ if (x->prepare_iteration < y->prepare_iteration) return -1; if (x->prepare_iteration > y->prepare_iteration) return 1; /* Lower priority values first */ if (x->priority < y->priority) return -1; if (x->priority > y->priority) return 1; return 0; } static int earliest_time_prioq_compare(const void *a, const void *b) { const sd_event_source *x = a, *y = b; assert(EVENT_SOURCE_IS_TIME(x->type)); assert(x->type == y->type); /* Enabled ones first */ if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) return -1; if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) return 1; /* Move the pending ones to the end */ if (!x->pending && y->pending) return -1; if (x->pending && !y->pending) return 1; /* Order by time */ if (x->time.next < y->time.next) return -1; if (x->time.next > y->time.next) return 1; return 0; } static usec_t time_event_source_latest(const sd_event_source *s) { return usec_add(s->time.next, s->time.accuracy); } static int latest_time_prioq_compare(const void *a, const void *b) { const sd_event_source *x = a, *y = b; assert(EVENT_SOURCE_IS_TIME(x->type)); assert(x->type == y->type); /* Enabled ones first */ if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) return -1; if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) return 1; /* Move the pending ones to the end */ if (!x->pending && y->pending) return -1; if (x->pending && !y->pending) return 1; /* Order by time */ if (time_event_source_latest(x) < time_event_source_latest(y)) return -1; if (time_event_source_latest(x) > time_event_source_latest(y)) return 1; return 0; } static int exit_prioq_compare(const void *a, const void *b) { const sd_event_source *x = a, *y = b; assert(x->type == SOURCE_EXIT); assert(y->type == SOURCE_EXIT); /* Enabled ones first */ if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) return -1; if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) return 1; /* Lower priority values first */ if (x->priority < y->priority) return -1; if (x->priority > y->priority) return 1; return 0; } static void free_clock_data(struct clock_data *d) { assert(d); assert(d->wakeup == WAKEUP_CLOCK_DATA); safe_close(d->fd); prioq_free(d->earliest); prioq_free(d->latest); } static void event_free(sd_event *e) { sd_event_source *s; assert(e); while ((s = e->sources)) { assert(s->floating); source_disconnect(s); sd_event_source_unref(s); } assert(e->n_sources == 0); if (e->default_event_ptr) *(e->default_event_ptr) = NULL; safe_close(e->epoll_fd); safe_close(e->watchdog_fd); free_clock_data(&e->realtime); free_clock_data(&e->boottime); free_clock_data(&e->monotonic); free_clock_data(&e->realtime_alarm); free_clock_data(&e->boottime_alarm); prioq_free(e->pending); prioq_free(e->prepare); prioq_free(e->exit); free(e->signal_sources); hashmap_free(e->signal_data); hashmap_free(e->child_sources); set_free(e->post_sources); free(e); } _public_ int sd_event_new(sd_event** ret) { sd_event *e; int r; assert_return(ret, -EINVAL); e = new0(sd_event, 1); if (!e) return -ENOMEM; e->n_ref = 1; e->watchdog_fd = e->epoll_fd = e->realtime.fd = e->boottime.fd = e->monotonic.fd = e->realtime_alarm.fd = e->boottime_alarm.fd = -1; e->realtime.next = e->boottime.next = e->monotonic.next = e->realtime_alarm.next = e->boottime_alarm.next = USEC_INFINITY; e->realtime.wakeup = e->boottime.wakeup = e->monotonic.wakeup = e->realtime_alarm.wakeup = e->boottime_alarm.wakeup = WAKEUP_CLOCK_DATA; e->original_pid = getpid(); e->perturb = USEC_INFINITY; r = prioq_ensure_allocated(&e->pending, pending_prioq_compare); if (r < 0) goto fail; e->epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (e->epoll_fd < 0) { r = -errno; goto fail; } if (secure_getenv("SD_EVENT_PROFILE_DELAYS")) { log_debug("Event loop profiling enabled. Logarithmic histogram of event loop iterations in the range 2^0 ... 2^63 us will be logged every 5s."); e->profile_delays = true; } *ret = e; return 0; fail: event_free(e); return r; } _public_ sd_event* sd_event_ref(sd_event *e) { if (!e) return NULL; assert(e->n_ref >= 1); e->n_ref++; return e; } _public_ sd_event* sd_event_unref(sd_event *e) { if (!e) return NULL; assert(e->n_ref >= 1); e->n_ref--; if (e->n_ref <= 0) event_free(e); return NULL; } static bool event_pid_changed(sd_event *e) { assert(e); /* We don't support people creating an event loop and keeping * it around over a fork(). Let's complain. */ return e->original_pid != getpid(); } static void source_io_unregister(sd_event_source *s) { int r; assert(s); assert(s->type == SOURCE_IO); if (event_pid_changed(s->event)) return; if (!s->io.registered) return; r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->io.fd, NULL); if (r < 0) log_debug_errno(errno, "Failed to remove source %s (type %s) from epoll: %m", strna(s->description), event_source_type_to_string(s->type)); s->io.registered = false; } static int source_io_register( sd_event_source *s, int enabled, uint32_t events) { struct epoll_event ev = {}; int r; assert(s); assert(s->type == SOURCE_IO); assert(enabled != SD_EVENT_OFF); ev.events = events; ev.data.ptr = s; if (enabled == SD_EVENT_ONESHOT) ev.events |= EPOLLONESHOT; if (s->io.registered) r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_MOD, s->io.fd, &ev); else r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_ADD, s->io.fd, &ev); if (r < 0) return -errno; s->io.registered = true; return 0; } static clockid_t event_source_type_to_clock(EventSourceType t) { switch (t) { case SOURCE_TIME_REALTIME: return CLOCK_REALTIME; case SOURCE_TIME_BOOTTIME: return CLOCK_BOOTTIME; case SOURCE_TIME_MONOTONIC: return CLOCK_MONOTONIC; case SOURCE_TIME_REALTIME_ALARM: return CLOCK_REALTIME_ALARM; case SOURCE_TIME_BOOTTIME_ALARM: return CLOCK_BOOTTIME_ALARM; default: return (clockid_t) -1; } } static EventSourceType clock_to_event_source_type(clockid_t clock) { switch (clock) { case CLOCK_REALTIME: return SOURCE_TIME_REALTIME; case CLOCK_BOOTTIME: return SOURCE_TIME_BOOTTIME; case CLOCK_MONOTONIC: return SOURCE_TIME_MONOTONIC; case CLOCK_REALTIME_ALARM: return SOURCE_TIME_REALTIME_ALARM; case CLOCK_BOOTTIME_ALARM: return SOURCE_TIME_BOOTTIME_ALARM; default: return _SOURCE_EVENT_SOURCE_TYPE_INVALID; } } static struct clock_data* event_get_clock_data(sd_event *e, EventSourceType t) { assert(e); switch (t) { case SOURCE_TIME_REALTIME: return &e->realtime; case SOURCE_TIME_BOOTTIME: return &e->boottime; case SOURCE_TIME_MONOTONIC: return &e->monotonic; case SOURCE_TIME_REALTIME_ALARM: return &e->realtime_alarm; case SOURCE_TIME_BOOTTIME_ALARM: return &e->boottime_alarm; default: return NULL; } } static int event_make_signal_data( sd_event *e, int sig, struct signal_data **ret) { struct epoll_event ev = {}; struct signal_data *d; bool added = false; sigset_t ss_copy; int64_t priority; int r; assert(e); if (event_pid_changed(e)) return -ECHILD; if (e->signal_sources && e->signal_sources[sig]) priority = e->signal_sources[sig]->priority; else priority = 0; d = hashmap_get(e->signal_data, &priority); if (d) { if (sigismember(&d->sigset, sig) > 0) { if (ret) *ret = d; return 0; } } else { r = hashmap_ensure_allocated(&e->signal_data, &uint64_hash_ops); if (r < 0) return r; d = new0(struct signal_data, 1); if (!d) return -ENOMEM; d->wakeup = WAKEUP_SIGNAL_DATA; d->fd = -1; d->priority = priority; r = hashmap_put(e->signal_data, &d->priority, d); if (r < 0) { free(d); return r; } added = true; } ss_copy = d->sigset; assert_se(sigaddset(&ss_copy, sig) >= 0); r = signalfd(d->fd, &ss_copy, SFD_NONBLOCK|SFD_CLOEXEC); if (r < 0) { r = -errno; goto fail; } d->sigset = ss_copy; if (d->fd >= 0) { if (ret) *ret = d; return 0; } d->fd = r; ev.events = EPOLLIN; ev.data.ptr = d; r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev); if (r < 0) { r = -errno; goto fail; } if (ret) *ret = d; return 0; fail: if (added) { d->fd = safe_close(d->fd); hashmap_remove(e->signal_data, &d->priority); free(d); } return r; } static void event_unmask_signal_data(sd_event *e, struct signal_data *d, int sig) { assert(e); assert(d); /* Turns off the specified signal in the signal data * object. If the signal mask of the object becomes empty that * way removes it. */ if (sigismember(&d->sigset, sig) == 0) return; assert_se(sigdelset(&d->sigset, sig) >= 0); if (sigisemptyset(&d->sigset)) { /* If all the mask is all-zero we can get rid of the structure */ hashmap_remove(e->signal_data, &d->priority); assert(!d->current); safe_close(d->fd); free(d); return; } assert(d->fd >= 0); if (signalfd(d->fd, &d->sigset, SFD_NONBLOCK|SFD_CLOEXEC) < 0) log_debug_errno(errno, "Failed to unset signal bit, ignoring: %m"); } static void event_gc_signal_data(sd_event *e, const int64_t *priority, int sig) { struct signal_data *d; static const int64_t zero_priority = 0; assert(e); /* Rechecks if the specified signal is still something we are * interested in. If not, we'll unmask it, and possibly drop * the signalfd for it. */ if (sig == SIGCHLD && e->n_enabled_child_sources > 0) return; if (e->signal_sources && e->signal_sources[sig] && e->signal_sources[sig]->enabled != SD_EVENT_OFF) return; /* * The specified signal might be enabled in three different queues: * * 1) the one that belongs to the priority passed (if it is non-NULL) * 2) the one that belongs to the priority of the event source of the signal (if there is one) * 3) the 0 priority (to cover the SIGCHLD case) * * Hence, let's remove it from all three here. */ if (priority) { d = hashmap_get(e->signal_data, priority); if (d) event_unmask_signal_data(e, d, sig); } if (e->signal_sources && e->signal_sources[sig]) { d = hashmap_get(e->signal_data, &e->signal_sources[sig]->priority); if (d) event_unmask_signal_data(e, d, sig); } d = hashmap_get(e->signal_data, &zero_priority); if (d) event_unmask_signal_data(e, d, sig); } static void source_disconnect(sd_event_source *s) { sd_event *event; assert(s); if (!s->event) return; assert(s->event->n_sources > 0); switch (s->type) { case SOURCE_IO: if (s->io.fd >= 0) source_io_unregister(s); break; case SOURCE_TIME_REALTIME: case SOURCE_TIME_BOOTTIME: case SOURCE_TIME_MONOTONIC: case SOURCE_TIME_REALTIME_ALARM: case SOURCE_TIME_BOOTTIME_ALARM: { struct clock_data *d; d = event_get_clock_data(s->event, s->type); assert(d); prioq_remove(d->earliest, s, &s->time.earliest_index); prioq_remove(d->latest, s, &s->time.latest_index); d->needs_rearm = true; break; } case SOURCE_SIGNAL: if (s->signal.sig > 0) { if (s->event->signal_sources) s->event->signal_sources[s->signal.sig] = NULL; event_gc_signal_data(s->event, &s->priority, s->signal.sig); } break; case SOURCE_CHILD: if (s->child.pid > 0) { if (s->enabled != SD_EVENT_OFF) { assert(s->event->n_enabled_child_sources > 0); s->event->n_enabled_child_sources--; } (void) hashmap_remove(s->event->child_sources, PID_TO_PTR(s->child.pid)); event_gc_signal_data(s->event, &s->priority, SIGCHLD); } break; case SOURCE_DEFER: /* nothing */ break; case SOURCE_POST: set_remove(s->event->post_sources, s); break; case SOURCE_EXIT: prioq_remove(s->event->exit, s, &s->exit.prioq_index); break; default: assert_not_reached("Wut? I shouldn't exist."); } if (s->pending) prioq_remove(s->event->pending, s, &s->pending_index); if (s->prepare) prioq_remove(s->event->prepare, s, &s->prepare_index); event = s->event; s->type = _SOURCE_EVENT_SOURCE_TYPE_INVALID; s->event = NULL; LIST_REMOVE(sources, event->sources, s); event->n_sources--; if (!s->floating) sd_event_unref(event); } static void source_free(sd_event_source *s) { assert(s); source_disconnect(s); free(s->description); free(s); } static int source_set_pending(sd_event_source *s, bool b) { int r; assert(s); assert(s->type != SOURCE_EXIT); if (s->pending == b) return 0; s->pending = b; if (b) { s->pending_iteration = s->event->iteration; r = prioq_put(s->event->pending, s, &s->pending_index); if (r < 0) { s->pending = false; return r; } } else assert_se(prioq_remove(s->event->pending, s, &s->pending_index)); if (EVENT_SOURCE_IS_TIME(s->type)) { struct clock_data *d; d = event_get_clock_data(s->event, s->type); assert(d); prioq_reshuffle(d->earliest, s, &s->time.earliest_index); prioq_reshuffle(d->latest, s, &s->time.latest_index); d->needs_rearm = true; } if (s->type == SOURCE_SIGNAL && !b) { struct signal_data *d; d = hashmap_get(s->event->signal_data, &s->priority); if (d && d->current == s) d->current = NULL; } return 0; } static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType type) { sd_event_source *s; assert(e); s = new0(sd_event_source, 1); if (!s) return NULL; s->n_ref = 1; s->event = e; s->floating = floating; s->type = type; s->pending_index = s->prepare_index = PRIOQ_IDX_NULL; if (!floating) sd_event_ref(e); LIST_PREPEND(sources, e->sources, s); e->n_sources ++; return s; } _public_ int sd_event_add_io( sd_event *e, sd_event_source **ret, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata) { sd_event_source *s; int r; assert_return(e, -EINVAL); assert_return(fd >= 0, -EBADF); assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL); assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); s = source_new(e, !ret, SOURCE_IO); if (!s) return -ENOMEM; s->wakeup = WAKEUP_EVENT_SOURCE; s->io.fd = fd; s->io.events = events; s->io.callback = callback; s->userdata = userdata; s->enabled = SD_EVENT_ON; r = source_io_register(s, s->enabled, events); if (r < 0) { source_free(s); return r; } if (ret) *ret = s; return 0; } static void initialize_perturb(sd_event *e) { sd_id128_t bootid = {}; /* When we sleep for longer, we try to realign the wakeup to the same time wihtin each minute/second/250ms, so that events all across the system can be coalesced into a single CPU wakeup. However, let's take some system-specific randomness for this value, so that in a network of systems with synced clocks timer events are distributed a bit. Here, we calculate a perturbation usec offset from the boot ID. */ if (_likely_(e->perturb != USEC_INFINITY)) return; if (sd_id128_get_boot(&bootid) >= 0) e->perturb = (bootid.qwords[0] ^ bootid.qwords[1]) % USEC_PER_MINUTE; } static int event_setup_timer_fd( sd_event *e, struct clock_data *d, clockid_t clock) { struct epoll_event ev = {}; int r, fd; assert(e); assert(d); if (_likely_(d->fd >= 0)) return 0; fd = timerfd_create(clock, TFD_NONBLOCK|TFD_CLOEXEC); if (fd < 0) return -errno; ev.events = EPOLLIN; ev.data.ptr = d; r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev); if (r < 0) { safe_close(fd); return -errno; } d->fd = fd; return 0; } static int time_exit_callback(sd_event_source *s, uint64_t usec, void *userdata) { assert(s); return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); } _public_ int sd_event_add_time( sd_event *e, sd_event_source **ret, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata) { EventSourceType type; sd_event_source *s; struct clock_data *d; int r; assert_return(e, -EINVAL); assert_return(accuracy != (uint64_t) -1, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); if (!callback) callback = time_exit_callback; type = clock_to_event_source_type(clock); assert_return(type >= 0, -EOPNOTSUPP); d = event_get_clock_data(e, type); assert(d); r = prioq_ensure_allocated(&d->earliest, earliest_time_prioq_compare); if (r < 0) return r; r = prioq_ensure_allocated(&d->latest, latest_time_prioq_compare); if (r < 0) return r; if (d->fd < 0) { r = event_setup_timer_fd(e, d, clock); if (r < 0) return r; } s = source_new(e, !ret, type); if (!s) return -ENOMEM; s->time.next = usec; s->time.accuracy = accuracy == 0 ? DEFAULT_ACCURACY_USEC : accuracy; s->time.callback = callback; s->time.earliest_index = s->time.latest_index = PRIOQ_IDX_NULL; s->userdata = userdata; s->enabled = SD_EVENT_ONESHOT; d->needs_rearm = true; r = prioq_put(d->earliest, s, &s->time.earliest_index); if (r < 0) goto fail; r = prioq_put(d->latest, s, &s->time.latest_index); if (r < 0) goto fail; if (ret) *ret = s; return 0; fail: source_free(s); return r; } static int signal_exit_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { assert(s); return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); } _public_ int sd_event_add_signal( sd_event *e, sd_event_source **ret, int sig, sd_event_signal_handler_t callback, void *userdata) { sd_event_source *s; struct signal_data *d; sigset_t ss; int r; assert_return(e, -EINVAL); assert_return(sig > 0, -EINVAL); assert_return(sig < _NSIG, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); if (!callback) callback = signal_exit_callback; r = pthread_sigmask(SIG_SETMASK, NULL, &ss); if (r != 0) return -r; if (!sigismember(&ss, sig)) return -EBUSY; if (!e->signal_sources) { e->signal_sources = new0(sd_event_source*, _NSIG); if (!e->signal_sources) return -ENOMEM; } else if (e->signal_sources[sig]) return -EBUSY; s = source_new(e, !ret, SOURCE_SIGNAL); if (!s) return -ENOMEM; s->signal.sig = sig; s->signal.callback = callback; s->userdata = userdata; s->enabled = SD_EVENT_ON; e->signal_sources[sig] = s; r = event_make_signal_data(e, sig, &d); if (r < 0) { source_free(s); return r; } /* Use the signal name as description for the event source by default */ (void) sd_event_source_set_description(s, signal_to_string(sig)); if (ret) *ret = s; return 0; } _public_ int sd_event_add_child( sd_event *e, sd_event_source **ret, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata) { sd_event_source *s; int r; assert_return(e, -EINVAL); assert_return(pid > 1, -EINVAL); assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL); assert_return(options != 0, -EINVAL); assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); r = hashmap_ensure_allocated(&e->child_sources, NULL); if (r < 0) return r; if (hashmap_contains(e->child_sources, PID_TO_PTR(pid))) return -EBUSY; s = source_new(e, !ret, SOURCE_CHILD); if (!s) return -ENOMEM; s->child.pid = pid; s->child.options = options; s->child.callback = callback; s->userdata = userdata; s->enabled = SD_EVENT_ONESHOT; r = hashmap_put(e->child_sources, PID_TO_PTR(pid), s); if (r < 0) { source_free(s); return r; } e->n_enabled_child_sources ++; r = event_make_signal_data(e, SIGCHLD, NULL); if (r < 0) { e->n_enabled_child_sources--; source_free(s); return r; } e->need_process_child = true; if (ret) *ret = s; return 0; } _public_ int sd_event_add_defer( sd_event *e, sd_event_source **ret, sd_event_handler_t callback, void *userdata) { sd_event_source *s; int r; assert_return(e, -EINVAL); assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); s = source_new(e, !ret, SOURCE_DEFER); if (!s) return -ENOMEM; s->defer.callback = callback; s->userdata = userdata; s->enabled = SD_EVENT_ONESHOT; r = source_set_pending(s, true); if (r < 0) { source_free(s); return r; } if (ret) *ret = s; return 0; } _public_ int sd_event_add_post( sd_event *e, sd_event_source **ret, sd_event_handler_t callback, void *userdata) { sd_event_source *s; int r; assert_return(e, -EINVAL); assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); r = set_ensure_allocated(&e->post_sources, NULL); if (r < 0) return r; s = source_new(e, !ret, SOURCE_POST); if (!s) return -ENOMEM; s->post.callback = callback; s->userdata = userdata; s->enabled = SD_EVENT_ON; r = set_put(e->post_sources, s); if (r < 0) { source_free(s); return r; } if (ret) *ret = s; return 0; } _public_ int sd_event_add_exit( sd_event *e, sd_event_source **ret, sd_event_handler_t callback, void *userdata) { sd_event_source *s; int r; assert_return(e, -EINVAL); assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); r = prioq_ensure_allocated(&e->exit, exit_prioq_compare); if (r < 0) return r; s = source_new(e, !ret, SOURCE_EXIT); if (!s) return -ENOMEM; s->exit.callback = callback; s->userdata = userdata; s->exit.prioq_index = PRIOQ_IDX_NULL; s->enabled = SD_EVENT_ONESHOT; r = prioq_put(s->event->exit, s, &s->exit.prioq_index); if (r < 0) { source_free(s); return r; } if (ret) *ret = s; return 0; } _public_ sd_event_source* sd_event_source_ref(sd_event_source *s) { if (!s) return NULL; assert(s->n_ref >= 1); s->n_ref++; return s; } _public_ sd_event_source* sd_event_source_unref(sd_event_source *s) { if (!s) return NULL; assert(s->n_ref >= 1); s->n_ref--; if (s->n_ref <= 0) { /* Here's a special hack: when we are called from a * dispatch handler we won't free the event source * immediately, but we will detach the fd from the * epoll. This way it is safe for the caller to unref * the event source and immediately close the fd, but * we still retain a valid event source object after * the callback. */ if (s->dispatching) { if (s->type == SOURCE_IO) source_io_unregister(s); source_disconnect(s); } else source_free(s); } return NULL; } _public_ int sd_event_source_set_description(sd_event_source *s, const char *description) { assert_return(s, -EINVAL); assert_return(!event_pid_changed(s->event), -ECHILD); return free_and_strdup(&s->description, description); } _public_ int sd_event_source_get_description(sd_event_source *s, const char **description) { assert_return(s, -EINVAL); assert_return(description, -EINVAL); assert_return(s->description, -ENXIO); assert_return(!event_pid_changed(s->event), -ECHILD); *description = s->description; return 0; } _public_ sd_event *sd_event_source_get_event(sd_event_source *s) { assert_return(s, NULL); return s->event; } _public_ int sd_event_source_get_pending(sd_event_source *s) { assert_return(s, -EINVAL); assert_return(s->type != SOURCE_EXIT, -EDOM); assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(s->event), -ECHILD); return s->pending; } _public_ int sd_event_source_get_io_fd(sd_event_source *s) { assert_return(s, -EINVAL); assert_return(s->type == SOURCE_IO, -EDOM); assert_return(!event_pid_changed(s->event), -ECHILD); return s->io.fd; } _public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) { int r; assert_return(s, -EINVAL); assert_return(fd >= 0, -EBADF); assert_return(s->type == SOURCE_IO, -EDOM); assert_return(!event_pid_changed(s->event), -ECHILD); if (s->io.fd == fd) return 0; if (s->enabled == SD_EVENT_OFF) { s->io.fd = fd; s->io.registered = false; } else { int saved_fd; saved_fd = s->io.fd; assert(s->io.registered); s->io.fd = fd; s->io.registered = false; r = source_io_register(s, s->enabled, s->io.events); if (r < 0) { s->io.fd = saved_fd; s->io.registered = true; return r; } epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, saved_fd, NULL); } return 0; } _public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) { assert_return(s, -EINVAL); assert_return(events, -EINVAL); assert_return(s->type == SOURCE_IO, -EDOM); assert_return(!event_pid_changed(s->event), -ECHILD); *events = s->io.events; return 0; } _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) { int r; assert_return(s, -EINVAL); assert_return(s->type == SOURCE_IO, -EDOM); assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL); assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(s->event), -ECHILD); /* edge-triggered updates are never skipped, so we can reset edges */ if (s->io.events == events && !(events & EPOLLET)) return 0; if (s->enabled != SD_EVENT_OFF) { r = source_io_register(s, s->enabled, events); if (r < 0) return r; } s->io.events = events; source_set_pending(s, false); return 0; } _public_ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents) { assert_return(s, -EINVAL); assert_return(revents, -EINVAL); assert_return(s->type == SOURCE_IO, -EDOM); assert_return(s->pending, -ENODATA); assert_return(!event_pid_changed(s->event), -ECHILD); *revents = s->io.revents; return 0; } _public_ int sd_event_source_get_signal(sd_event_source *s) { assert_return(s, -EINVAL); assert_return(s->type == SOURCE_SIGNAL, -EDOM); assert_return(!event_pid_changed(s->event), -ECHILD); return s->signal.sig; } _public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *priority) { assert_return(s, -EINVAL); assert_return(!event_pid_changed(s->event), -ECHILD); return s->priority; } _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) { int r; assert_return(s, -EINVAL); assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(s->event), -ECHILD); if (s->priority == priority) return 0; if (s->type == SOURCE_SIGNAL && s->enabled != SD_EVENT_OFF) { struct signal_data *old, *d; /* Move us from the signalfd belonging to the old * priority to the signalfd of the new priority */ assert_se(old = hashmap_get(s->event->signal_data, &s->priority)); s->priority = priority; r = event_make_signal_data(s->event, s->signal.sig, &d); if (r < 0) { s->priority = old->priority; return r; } event_unmask_signal_data(s->event, old, s->signal.sig); } else s->priority = priority; if (s->pending) prioq_reshuffle(s->event->pending, s, &s->pending_index); if (s->prepare) prioq_reshuffle(s->event->prepare, s, &s->prepare_index); if (s->type == SOURCE_EXIT) prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); return 0; } _public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) { assert_return(s, -EINVAL); assert_return(m, -EINVAL); assert_return(!event_pid_changed(s->event), -ECHILD); *m = s->enabled; return 0; } _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { int r; assert_return(s, -EINVAL); assert_return(m == SD_EVENT_OFF || m == SD_EVENT_ON || m == SD_EVENT_ONESHOT, -EINVAL); assert_return(!event_pid_changed(s->event), -ECHILD); /* If we are dead anyway, we are fine with turning off * sources, but everything else needs to fail. */ if (s->event->state == SD_EVENT_FINISHED) return m == SD_EVENT_OFF ? 0 : -ESTALE; if (s->enabled == m) return 0; if (m == SD_EVENT_OFF) { switch (s->type) { case SOURCE_IO: source_io_unregister(s); s->enabled = m; break; case SOURCE_TIME_REALTIME: case SOURCE_TIME_BOOTTIME: case SOURCE_TIME_MONOTONIC: case SOURCE_TIME_REALTIME_ALARM: case SOURCE_TIME_BOOTTIME_ALARM: { struct clock_data *d; s->enabled = m; d = event_get_clock_data(s->event, s->type); assert(d); prioq_reshuffle(d->earliest, s, &s->time.earliest_index); prioq_reshuffle(d->latest, s, &s->time.latest_index); d->needs_rearm = true; break; } case SOURCE_SIGNAL: s->enabled = m; event_gc_signal_data(s->event, &s->priority, s->signal.sig); break; case SOURCE_CHILD: s->enabled = m; assert(s->event->n_enabled_child_sources > 0); s->event->n_enabled_child_sources--; event_gc_signal_data(s->event, &s->priority, SIGCHLD); break; case SOURCE_EXIT: s->enabled = m; prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); break; case SOURCE_DEFER: case SOURCE_POST: s->enabled = m; break; default: assert_not_reached("Wut? I shouldn't exist."); } } else { switch (s->type) { case SOURCE_IO: r = source_io_register(s, m, s->io.events); if (r < 0) return r; s->enabled = m; break; case SOURCE_TIME_REALTIME: case SOURCE_TIME_BOOTTIME: case SOURCE_TIME_MONOTONIC: case SOURCE_TIME_REALTIME_ALARM: case SOURCE_TIME_BOOTTIME_ALARM: { struct clock_data *d; s->enabled = m; d = event_get_clock_data(s->event, s->type); assert(d); prioq_reshuffle(d->earliest, s, &s->time.earliest_index); prioq_reshuffle(d->latest, s, &s->time.latest_index); d->needs_rearm = true; break; } case SOURCE_SIGNAL: s->enabled = m; r = event_make_signal_data(s->event, s->signal.sig, NULL); if (r < 0) { s->enabled = SD_EVENT_OFF; event_gc_signal_data(s->event, &s->priority, s->signal.sig); return r; } break; case SOURCE_CHILD: if (s->enabled == SD_EVENT_OFF) s->event->n_enabled_child_sources++; s->enabled = m; r = event_make_signal_data(s->event, SIGCHLD, NULL); if (r < 0) { s->enabled = SD_EVENT_OFF; s->event->n_enabled_child_sources--; event_gc_signal_data(s->event, &s->priority, SIGCHLD); return r; } break; case SOURCE_EXIT: s->enabled = m; prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); break; case SOURCE_DEFER: case SOURCE_POST: s->enabled = m; break; default: assert_not_reached("Wut? I shouldn't exist."); } } if (s->pending) prioq_reshuffle(s->event->pending, s, &s->pending_index); if (s->prepare) prioq_reshuffle(s->event->prepare, s, &s->prepare_index); return 0; } _public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) { assert_return(s, -EINVAL); assert_return(usec, -EINVAL); assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); assert_return(!event_pid_changed(s->event), -ECHILD); *usec = s->time.next; return 0; } _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) { struct clock_data *d; assert_return(s, -EINVAL); assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(s->event), -ECHILD); s->time.next = usec; source_set_pending(s, false); d = event_get_clock_data(s->event, s->type); assert(d); prioq_reshuffle(d->earliest, s, &s->time.earliest_index); prioq_reshuffle(d->latest, s, &s->time.latest_index); d->needs_rearm = true; return 0; } _public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) { assert_return(s, -EINVAL); assert_return(usec, -EINVAL); assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); assert_return(!event_pid_changed(s->event), -ECHILD); *usec = s->time.accuracy; return 0; } _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) { struct clock_data *d; assert_return(s, -EINVAL); assert_return(usec != (uint64_t) -1, -EINVAL); assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(s->event), -ECHILD); if (usec == 0) usec = DEFAULT_ACCURACY_USEC; s->time.accuracy = usec; source_set_pending(s, false); d = event_get_clock_data(s->event, s->type); assert(d); prioq_reshuffle(d->latest, s, &s->time.latest_index); d->needs_rearm = true; return 0; } _public_ int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock) { assert_return(s, -EINVAL); assert_return(clock, -EINVAL); assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); assert_return(!event_pid_changed(s->event), -ECHILD); *clock = event_source_type_to_clock(s->type); return 0; } _public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) { assert_return(s, -EINVAL); assert_return(pid, -EINVAL); assert_return(s->type == SOURCE_CHILD, -EDOM); assert_return(!event_pid_changed(s->event), -ECHILD); *pid = s->child.pid; return 0; } _public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) { int r; assert_return(s, -EINVAL); assert_return(s->type != SOURCE_EXIT, -EDOM); assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(s->event), -ECHILD); if (s->prepare == callback) return 0; if (callback && s->prepare) { s->prepare = callback; return 0; } r = prioq_ensure_allocated(&s->event->prepare, prepare_prioq_compare); if (r < 0) return r; s->prepare = callback; if (callback) { r = prioq_put(s->event->prepare, s, &s->prepare_index); if (r < 0) return r; } else prioq_remove(s->event->prepare, s, &s->prepare_index); return 0; } _public_ void* sd_event_source_get_userdata(sd_event_source *s) { assert_return(s, NULL); return s->userdata; } _public_ void *sd_event_source_set_userdata(sd_event_source *s, void *userdata) { void *ret; assert_return(s, NULL); ret = s->userdata; s->userdata = userdata; return ret; } static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) { usec_t c; assert(e); assert(a <= b); if (a <= 0) return 0; if (a >= USEC_INFINITY) return USEC_INFINITY; if (b <= a + 1) return a; initialize_perturb(e); /* Find a good time to wake up again between times a and b. We have two goals here: a) We want to wake up as seldom as possible, hence prefer later times over earlier times. b) But if we have to wake up, then let's make sure to dispatch as much as possible on the entire system. We implement this by waking up everywhere at the same time within any given minute if we can, synchronised via the perturbation value determined from the boot ID. If we can't, then we try to find the same spot in every 10s, then 1s and then 250ms step. Otherwise, we pick the last possible time to wake up. */ c = (b / USEC_PER_MINUTE) * USEC_PER_MINUTE + e->perturb; if (c >= b) { if (_unlikely_(c < USEC_PER_MINUTE)) return b; c -= USEC_PER_MINUTE; } if (c >= a) return c; c = (b / (USEC_PER_SEC*10)) * (USEC_PER_SEC*10) + (e->perturb % (USEC_PER_SEC*10)); if (c >= b) { if (_unlikely_(c < USEC_PER_SEC*10)) return b; c -= USEC_PER_SEC*10; } if (c >= a) return c; c = (b / USEC_PER_SEC) * USEC_PER_SEC + (e->perturb % USEC_PER_SEC); if (c >= b) { if (_unlikely_(c < USEC_PER_SEC)) return b; c -= USEC_PER_SEC; } if (c >= a) return c; c = (b / (USEC_PER_MSEC*250)) * (USEC_PER_MSEC*250) + (e->perturb % (USEC_PER_MSEC*250)); if (c >= b) { if (_unlikely_(c < USEC_PER_MSEC*250)) return b; c -= USEC_PER_MSEC*250; } if (c >= a) return c; return b; } static int event_arm_timer( sd_event *e, struct clock_data *d) { struct itimerspec its = {}; sd_event_source *a, *b; usec_t t; int r; assert(e); assert(d); if (!d->needs_rearm) return 0; else d->needs_rearm = false; a = prioq_peek(d->earliest); if (!a || a->enabled == SD_EVENT_OFF || a->time.next == USEC_INFINITY) { if (d->fd < 0) return 0; if (d->next == USEC_INFINITY) return 0; /* disarm */ r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL); if (r < 0) return r; d->next = USEC_INFINITY; return 0; } b = prioq_peek(d->latest); assert_se(b && b->enabled != SD_EVENT_OFF); t = sleep_between(e, a->time.next, time_event_source_latest(b)); if (d->next == t) return 0; assert_se(d->fd >= 0); if (t == 0) { /* We don' want to disarm here, just mean some time looooong ago. */ its.it_value.tv_sec = 0; its.it_value.tv_nsec = 1; } else timespec_store(&its.it_value, t); r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL); if (r < 0) return -errno; d->next = t; return 0; } static int process_io(sd_event *e, sd_event_source *s, uint32_t revents) { assert(e); assert(s); assert(s->type == SOURCE_IO); /* If the event source was already pending, we just OR in the * new revents, otherwise we reset the value. The ORing is * necessary to handle EPOLLONESHOT events properly where * readability might happen independently of writability, and * we need to keep track of both */ if (s->pending) s->io.revents |= revents; else s->io.revents = revents; return source_set_pending(s, true); } static int flush_timer(sd_event *e, int fd, uint32_t events, usec_t *next) { uint64_t x; ssize_t ss; assert(e); assert(fd >= 0); assert_return(events == EPOLLIN, -EIO); ss = read(fd, &x, sizeof(x)); if (ss < 0) { if (errno == EAGAIN || errno == EINTR) return 0; return -errno; } if (_unlikely_(ss != sizeof(x))) return -EIO; if (next) *next = USEC_INFINITY; return 0; } static int process_timer( sd_event *e, usec_t n, struct clock_data *d) { sd_event_source *s; int r; assert(e); assert(d); for (;;) { s = prioq_peek(d->earliest); if (!s || s->time.next > n || s->enabled == SD_EVENT_OFF || s->pending) break; r = source_set_pending(s, true); if (r < 0) return r; prioq_reshuffle(d->earliest, s, &s->time.earliest_index); prioq_reshuffle(d->latest, s, &s->time.latest_index); d->needs_rearm = true; } return 0; } static int process_child(sd_event *e) { sd_event_source *s; Iterator i; int r; assert(e); e->need_process_child = false; /* So, this is ugly. We iteratively invoke waitid() with P_PID + WNOHANG for each PID we wait for, instead of using P_ALL. This is because we only want to get child information of very specific child processes, and not all of them. We might not have processed the SIGCHLD even of a previous invocation and we don't want to maintain a unbounded *per-child* event queue, hence we really don't want anything flushed out of the kernel's queue that we don't care about. Since this is O(n) this means that if you have a lot of processes you probably want to handle SIGCHLD yourself. We do not reap the children here (by using WNOWAIT), this is only done after the event source is dispatched so that the callback still sees the process as a zombie. */ HASHMAP_FOREACH(s, e->child_sources, i) { assert(s->type == SOURCE_CHILD); if (s->pending) continue; if (s->enabled == SD_EVENT_OFF) continue; zero(s->child.siginfo); r = waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options); if (r < 0) return -errno; if (s->child.siginfo.si_pid != 0) { bool zombie = s->child.siginfo.si_code == CLD_EXITED || s->child.siginfo.si_code == CLD_KILLED || s->child.siginfo.si_code == CLD_DUMPED; if (!zombie && (s->child.options & WEXITED)) { /* If the child isn't dead then let's * immediately remove the state change * from the queue, since there's no * benefit in leaving it queued */ assert(s->child.options & (WSTOPPED|WCONTINUED)); waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|(s->child.options & (WSTOPPED|WCONTINUED))); } r = source_set_pending(s, true); if (r < 0) return r; } } return 0; } static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { bool read_one = false; int r; assert(e); assert_return(events == EPOLLIN, -EIO); /* If there's a signal queued on this priority and SIGCHLD is on this priority too, then make sure to recheck the children we watch. This is because we only ever dequeue the first signal per priority, and if we dequeue one, and SIGCHLD might be enqueued later we wouldn't know, but we might have higher priority children we care about hence we need to check that explicitly. */ if (sigismember(&d->sigset, SIGCHLD)) e->need_process_child = true; /* If there's already an event source pending for this * priority we don't read another */ if (d->current) return 0; for (;;) { struct signalfd_siginfo si; ssize_t n; sd_event_source *s = NULL; n = read(d->fd, &si, sizeof(si)); if (n < 0) { if (errno == EAGAIN || errno == EINTR) return read_one; return -errno; } if (_unlikely_(n != sizeof(si))) return -EIO; assert(si.ssi_signo < _NSIG); read_one = true; if (e->signal_sources) s = e->signal_sources[si.ssi_signo]; if (!s) continue; if (s->pending) continue; s->signal.siginfo = si; d->current = s; r = source_set_pending(s, true); if (r < 0) return r; return 1; } } static int source_dispatch(sd_event_source *s) { int r = 0; assert(s); assert(s->pending || s->type == SOURCE_EXIT); if (s->type != SOURCE_DEFER && s->type != SOURCE_EXIT) { r = source_set_pending(s, false); if (r < 0) return r; } if (s->type != SOURCE_POST) { sd_event_source *z; Iterator i; /* If we execute a non-post source, let's mark all * post sources as pending */ SET_FOREACH(z, s->event->post_sources, i) { if (z->enabled == SD_EVENT_OFF) continue; r = source_set_pending(z, true); if (r < 0) return r; } } if (s->enabled == SD_EVENT_ONESHOT) { r = sd_event_source_set_enabled(s, SD_EVENT_OFF); if (r < 0) return r; } s->dispatching = true; switch (s->type) { case SOURCE_IO: r = s->io.callback(s, s->io.fd, s->io.revents, s->userdata); break; case SOURCE_TIME_REALTIME: case SOURCE_TIME_BOOTTIME: case SOURCE_TIME_MONOTONIC: case SOURCE_TIME_REALTIME_ALARM: case SOURCE_TIME_BOOTTIME_ALARM: r = s->time.callback(s, s->time.next, s->userdata); break; case SOURCE_SIGNAL: r = s->signal.callback(s, &s->signal.siginfo, s->userdata); break; case SOURCE_CHILD: { bool zombie; zombie = s->child.siginfo.si_code == CLD_EXITED || s->child.siginfo.si_code == CLD_KILLED || s->child.siginfo.si_code == CLD_DUMPED; r = s->child.callback(s, &s->child.siginfo, s->userdata); /* Now, reap the PID for good. */ if (zombie) waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED); break; } case SOURCE_DEFER: r = s->defer.callback(s, s->userdata); break; case SOURCE_POST: r = s->post.callback(s, s->userdata); break; case SOURCE_EXIT: r = s->exit.callback(s, s->userdata); break; case SOURCE_WATCHDOG: case _SOURCE_EVENT_SOURCE_TYPE_MAX: case _SOURCE_EVENT_SOURCE_TYPE_INVALID: assert_not_reached("Wut? I shouldn't exist."); } s->dispatching = false; if (r < 0) log_debug_errno(r, "Event source %s (type %s) returned error, disabling: %m", strna(s->description), event_source_type_to_string(s->type)); if (s->n_ref == 0) source_free(s); else if (r < 0) sd_event_source_set_enabled(s, SD_EVENT_OFF); return 1; } static int event_prepare(sd_event *e) { int r; assert(e); for (;;) { sd_event_source *s; s = prioq_peek(e->prepare); if (!s || s->prepare_iteration == e->iteration || s->enabled == SD_EVENT_OFF) break; s->prepare_iteration = e->iteration; r = prioq_reshuffle(e->prepare, s, &s->prepare_index); if (r < 0) return r; assert(s->prepare); s->dispatching = true; r = s->prepare(s, s->userdata); s->dispatching = false; if (r < 0) log_debug_errno(r, "Prepare callback of event source %s (type %s) returned error, disabling: %m", strna(s->description), event_source_type_to_string(s->type)); if (s->n_ref == 0) source_free(s); else if (r < 0) sd_event_source_set_enabled(s, SD_EVENT_OFF); } return 0; } static int dispatch_exit(sd_event *e) { sd_event_source *p; int r; assert(e); p = prioq_peek(e->exit); if (!p || p->enabled == SD_EVENT_OFF) { e->state = SD_EVENT_FINISHED; return 0; } sd_event_ref(e); e->iteration++; e->state = SD_EVENT_EXITING; r = source_dispatch(p); e->state = SD_EVENT_INITIAL; sd_event_unref(e); return r; } static sd_event_source* event_next_pending(sd_event *e) { sd_event_source *p; assert(e); p = prioq_peek(e->pending); if (!p) return NULL; if (p->enabled == SD_EVENT_OFF) return NULL; return p; } static int arm_watchdog(sd_event *e) { struct itimerspec its = {}; usec_t t; int r; assert(e); assert(e->watchdog_fd >= 0); t = sleep_between(e, e->watchdog_last + (e->watchdog_period / 2), e->watchdog_last + (e->watchdog_period * 3 / 4)); timespec_store(&its.it_value, t); /* Make sure we never set the watchdog to 0, which tells the * kernel to disable it. */ if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0) its.it_value.tv_nsec = 1; r = timerfd_settime(e->watchdog_fd, TFD_TIMER_ABSTIME, &its, NULL); if (r < 0) return -errno; return 0; } static int process_watchdog(sd_event *e) { assert(e); if (!e->watchdog) return 0; /* Don't notify watchdog too often */ if (e->watchdog_last + e->watchdog_period / 4 > e->timestamp.monotonic) return 0; sd_notify(false, "WATCHDOG=1"); e->watchdog_last = e->timestamp.monotonic; return arm_watchdog(e); } _public_ int sd_event_prepare(sd_event *e) { int r; assert_return(e, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); if (e->exit_requested) goto pending; e->iteration++; e->state = SD_EVENT_PREPARING; r = event_prepare(e); e->state = SD_EVENT_INITIAL; if (r < 0) return r; r = event_arm_timer(e, &e->realtime); if (r < 0) return r; r = event_arm_timer(e, &e->boottime); if (r < 0) return r; r = event_arm_timer(e, &e->monotonic); if (r < 0) return r; r = event_arm_timer(e, &e->realtime_alarm); if (r < 0) return r; r = event_arm_timer(e, &e->boottime_alarm); if (r < 0) return r; if (event_next_pending(e) || e->need_process_child) goto pending; e->state = SD_EVENT_ARMED; return 0; pending: e->state = SD_EVENT_ARMED; r = sd_event_wait(e, 0); if (r == 0) e->state = SD_EVENT_ARMED; return r; } _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { struct epoll_event *ev_queue; unsigned ev_queue_max; int r, m, i; assert_return(e, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(e->state == SD_EVENT_ARMED, -EBUSY); if (e->exit_requested) { e->state = SD_EVENT_PENDING; return 1; } ev_queue_max = MAX(e->n_sources, 1u); ev_queue = newa(struct epoll_event, ev_queue_max); m = epoll_wait(e->epoll_fd, ev_queue, ev_queue_max, timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC)); if (m < 0) { if (errno == EINTR) { e->state = SD_EVENT_PENDING; return 1; } r = -errno; goto finish; } dual_timestamp_get(&e->timestamp); e->timestamp_boottime = now(CLOCK_BOOTTIME); for (i = 0; i < m; i++) { if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_WATCHDOG)) r = flush_timer(e, e->watchdog_fd, ev_queue[i].events, NULL); else { WakeupType *t = ev_queue[i].data.ptr; switch (*t) { case WAKEUP_EVENT_SOURCE: r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events); break; case WAKEUP_CLOCK_DATA: { struct clock_data *d = ev_queue[i].data.ptr; r = flush_timer(e, d->fd, ev_queue[i].events, &d->next); break; } case WAKEUP_SIGNAL_DATA: r = process_signal(e, ev_queue[i].data.ptr, ev_queue[i].events); break; default: assert_not_reached("Invalid wake-up pointer"); } } if (r < 0) goto finish; } r = process_watchdog(e); if (r < 0) goto finish; r = process_timer(e, e->timestamp.realtime, &e->realtime); if (r < 0) goto finish; r = process_timer(e, e->timestamp_boottime, &e->boottime); if (r < 0) goto finish; r = process_timer(e, e->timestamp.monotonic, &e->monotonic); if (r < 0) goto finish; r = process_timer(e, e->timestamp.realtime, &e->realtime_alarm); if (r < 0) goto finish; r = process_timer(e, e->timestamp_boottime, &e->boottime_alarm); if (r < 0) goto finish; if (e->need_process_child) { r = process_child(e); if (r < 0) goto finish; } if (event_next_pending(e)) { e->state = SD_EVENT_PENDING; return 1; } r = 0; finish: e->state = SD_EVENT_INITIAL; return r; } _public_ int sd_event_dispatch(sd_event *e) { sd_event_source *p; int r; assert_return(e, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(e->state == SD_EVENT_PENDING, -EBUSY); if (e->exit_requested) return dispatch_exit(e); p = event_next_pending(e); if (p) { sd_event_ref(e); e->state = SD_EVENT_RUNNING; r = source_dispatch(p); e->state = SD_EVENT_INITIAL; sd_event_unref(e); return r; } e->state = SD_EVENT_INITIAL; return 1; } static void event_log_delays(sd_event *e) { char b[ELEMENTSOF(e->delays) * DECIMAL_STR_MAX(unsigned) + 1]; unsigned i; int o; for (i = o = 0; i < ELEMENTSOF(e->delays); i++) { o += snprintf(&b[o], sizeof(b) - o, "%u ", e->delays[i]); e->delays[i] = 0; } log_debug("Event loop iterations: %.*s", o, b); } _public_ int sd_event_run(sd_event *e, uint64_t timeout) { int r; assert_return(e, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); if (e->profile_delays && e->last_run) { usec_t this_run; unsigned l; this_run = now(CLOCK_MONOTONIC); l = u64log2(this_run - e->last_run); assert(l < sizeof(e->delays)); e->delays[l]++; if (this_run - e->last_log >= 5*USEC_PER_SEC) { event_log_delays(e); e->last_log = this_run; } } r = sd_event_prepare(e); if (r == 0) /* There was nothing? Then wait... */ r = sd_event_wait(e, timeout); if (e->profile_delays) e->last_run = now(CLOCK_MONOTONIC); if (r > 0) { /* There's something now, then let's dispatch it */ r = sd_event_dispatch(e); if (r < 0) return r; return 1; } return r; } _public_ int sd_event_loop(sd_event *e) { int r; assert_return(e, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); sd_event_ref(e); while (e->state != SD_EVENT_FINISHED) { r = sd_event_run(e, (uint64_t) -1); if (r < 0) goto finish; } r = e->exit_code; finish: sd_event_unref(e); return r; } _public_ int sd_event_get_fd(sd_event *e) { assert_return(e, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); return e->epoll_fd; } _public_ int sd_event_get_state(sd_event *e) { assert_return(e, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); return e->state; } _public_ int sd_event_get_exit_code(sd_event *e, int *code) { assert_return(e, -EINVAL); assert_return(code, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); if (!e->exit_requested) return -ENODATA; *code = e->exit_code; return 0; } _public_ int sd_event_exit(sd_event *e, int code) { assert_return(e, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); e->exit_requested = true; e->exit_code = code; return 0; } _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) { assert_return(e, -EINVAL); assert_return(usec, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); assert_return(IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM), -EOPNOTSUPP); if (!dual_timestamp_is_set(&e->timestamp)) { /* Implicitly fall back to now() if we never ran * before and thus have no cached time. */ *usec = now(clock); return 1; } switch (clock) { case CLOCK_REALTIME: case CLOCK_REALTIME_ALARM: *usec = e->timestamp.realtime; break; case CLOCK_MONOTONIC: *usec = e->timestamp.monotonic; break; default: *usec = e->timestamp_boottime; break; } return 0; } _public_ int sd_event_default(sd_event **ret) { static thread_local sd_event *default_event = NULL; sd_event *e = NULL; int r; if (!ret) return !!default_event; if (default_event) { *ret = sd_event_ref(default_event); return 0; } r = sd_event_new(&e); if (r < 0) return r; e->default_event_ptr = &default_event; e->tid = gettid(); default_event = e; *ret = e; return 1; } _public_ int sd_event_get_tid(sd_event *e, pid_t *tid) { assert_return(e, -EINVAL); assert_return(tid, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); if (e->tid != 0) { *tid = e->tid; return 0; } return -ENXIO; } _public_ int sd_event_set_watchdog(sd_event *e, int b) { int r; assert_return(e, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); if (e->watchdog == !!b) return e->watchdog; if (b) { struct epoll_event ev = {}; r = sd_watchdog_enabled(false, &e->watchdog_period); if (r <= 0) return r; /* Issue first ping immediately */ sd_notify(false, "WATCHDOG=1"); e->watchdog_last = now(CLOCK_MONOTONIC); e->watchdog_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC); if (e->watchdog_fd < 0) return -errno; r = arm_watchdog(e); if (r < 0) goto fail; ev.events = EPOLLIN; ev.data.ptr = INT_TO_PTR(SOURCE_WATCHDOG); r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev); if (r < 0) { r = -errno; goto fail; } } else { if (e->watchdog_fd >= 0) { epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, e->watchdog_fd, NULL); e->watchdog_fd = safe_close(e->watchdog_fd); } } e->watchdog = !!b; return e->watchdog; fail: e->watchdog_fd = safe_close(e->watchdog_fd); return r; } _public_ int sd_event_get_watchdog(sd_event *e) { assert_return(e, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); return e->watchdog; } systemd-229/src/libsystemd/sd-event/test-event.c000066400000000000000000000300261265713322000220170ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-event.h" #include "fd-util.h" #include "log.h" #include "macro.h" #include "signal-util.h" #include "util.h" static int prepare_handler(sd_event_source *s, void *userdata) { log_info("preparing %c", PTR_TO_INT(userdata)); return 1; } static bool got_a, got_b, got_c, got_unref; static unsigned got_d; static int unref_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { sd_event_source_unref(s); got_unref = true; return 0; } static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { log_info("got IO on %c", PTR_TO_INT(userdata)); if (userdata == INT_TO_PTR('a')) { assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0); assert_se(!got_a); got_a = true; } else if (userdata == INT_TO_PTR('b')) { assert_se(!got_b); got_b = true; } else if (userdata == INT_TO_PTR('d')) { got_d++; if (got_d < 2) assert_se(sd_event_source_set_enabled(s, SD_EVENT_ONESHOT) >= 0); else assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0); } else assert_not_reached("Yuck!"); return 1; } static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) { assert_se(s); assert_se(si); log_info("got child on %c", PTR_TO_INT(userdata)); assert_se(userdata == INT_TO_PTR('f')); assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0); sd_event_source_unref(s); return 1; } static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { sd_event_source *p = NULL; pid_t pid; assert_se(s); assert_se(si); log_info("got signal on %c", PTR_TO_INT(userdata)); assert_se(userdata == INT_TO_PTR('e')); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0); pid = fork(); assert_se(pid >= 0); if (pid == 0) _exit(0); assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0); assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); sd_event_source_unref(s); return 1; } static int defer_handler(sd_event_source *s, void *userdata) { sd_event_source *p = NULL; assert_se(s); log_info("got defer on %c", PTR_TO_INT(userdata)); assert_se(userdata == INT_TO_PTR('d')); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1, -1) >= 0); assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0); assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); raise(SIGUSR1); sd_event_source_unref(s); return 1; } static bool do_quit = false; static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) { log_info("got timer on %c", PTR_TO_INT(userdata)); if (userdata == INT_TO_PTR('c')) { if (do_quit) { sd_event_source *p; assert_se(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')) >= 0); assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); } else { assert_se(!got_c); got_c = true; } } else assert_not_reached("Huh?"); return 2; } static bool got_exit = false; static int exit_handler(sd_event_source *s, void *userdata) { log_info("got quit handler on %c", PTR_TO_INT(userdata)); got_exit = true; return 3; } static bool got_post = false; static int post_handler(sd_event_source *s, void *userdata) { log_info("got post handler"); got_post = true; return 2; } static void test_basic(void) { sd_event *e = NULL; sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL; static const char ch = 'x'; int a[2] = { -1, -1 }, b[2] = { -1, -1}, d[2] = { -1, -1}, k[2] = { -1, -1 }; uint64_t event_now; assert_se(pipe(a) >= 0); assert_se(pipe(b) >= 0); assert_se(pipe(d) >= 0); assert_se(pipe(k) >= 0); assert_se(sd_event_default(&e) >= 0); assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0); assert_se(sd_event_set_watchdog(e, true) >= 0); /* Test whether we cleanly can destroy an io event source from its own handler */ got_unref = false; assert_se(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL) >= 0); assert_se(write(k[1], &ch, 1) == 1); assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(got_unref); got_a = false, got_b = false, got_c = false, got_d = 0; /* Add a oneshot handler, trigger it, re-enable it, and trigger * it again. */ assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0); assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0); assert_se(write(d[1], &ch, 1) >= 0); assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(got_d == 1); assert_se(write(d[1], &ch, 1) >= 0); assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(got_d == 2); assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0); assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0); assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0); assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0); assert_se(sd_event_source_set_priority(x, 99) >= 0); assert_se(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT) >= 0); assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0); assert_se(sd_event_source_set_priority(z, 50) >= 0); assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0); assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0); /* Test for floating event sources */ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1, -1) >= 0); assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0); assert_se(write(a[1], &ch, 1) >= 0); assert_se(write(b[1], &ch, 1) >= 0); assert_se(!got_a && !got_b && !got_c); assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(!got_a && got_b && !got_c); assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(!got_a && got_b && got_c); assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(got_a && got_b && got_c); sd_event_source_unref(x); sd_event_source_unref(y); do_quit = true; assert_se(sd_event_add_post(e, NULL, post_handler, NULL) >= 0); assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0); assert_se(sd_event_source_set_time(z, event_now + 200 * USEC_PER_MSEC) >= 0); assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0); assert_se(sd_event_loop(e) >= 0); assert_se(got_post); assert_se(got_exit); sd_event_source_unref(z); sd_event_source_unref(q); sd_event_source_unref(w); sd_event_unref(e); safe_close_pair(a); safe_close_pair(b); safe_close_pair(d); safe_close_pair(k); } static void test_sd_event_now(void) { _cleanup_(sd_event_unrefp) sd_event *e = NULL; uint64_t event_now; assert_se(sd_event_new(&e) >= 0); assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0); assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) > 0); assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) > 0); assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) > 0); assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) > 0); assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP); assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP); assert_se(sd_event_run(e, 0) == 0); assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0); assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) == 0); assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) == 0); assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) == 0); assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) == 0); assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP); assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP); } static int last_rtqueue_sigval = 0; static int n_rtqueue = 0; static int rtqueue_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { last_rtqueue_sigval = si->ssi_int; n_rtqueue ++; return 0; } static void test_rtqueue(void) { sd_event_source *u = NULL, *v = NULL, *s = NULL; sd_event *e = NULL; assert_se(sd_event_default(&e) >= 0); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2, -1) >= 0); assert_se(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL) >= 0); assert_se(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL) >= 0); assert_se(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL) >= 0); assert_se(sd_event_source_set_priority(v, -10) >= 0); assert(sigqueue(getpid(), SIGRTMIN+2, (union sigval) { .sival_int = 1 }) >= 0); assert(sigqueue(getpid(), SIGRTMIN+3, (union sigval) { .sival_int = 2 }) >= 0); assert(sigqueue(getpid(), SIGUSR2, (union sigval) { .sival_int = 3 }) >= 0); assert(sigqueue(getpid(), SIGRTMIN+3, (union sigval) { .sival_int = 4 }) >= 0); assert(sigqueue(getpid(), SIGUSR2, (union sigval) { .sival_int = 5 }) >= 0); assert_se(n_rtqueue == 0); assert_se(last_rtqueue_sigval == 0); assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(n_rtqueue == 1); assert_se(last_rtqueue_sigval == 2); /* first SIGRTMIN+3 */ assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(n_rtqueue == 2); assert_se(last_rtqueue_sigval == 4); /* second SIGRTMIN+3 */ assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(n_rtqueue == 3); assert_se(last_rtqueue_sigval == 3); /* first SIGUSR2 */ assert_se(sd_event_run(e, (uint64_t) -1) >= 1); assert_se(n_rtqueue == 4); assert_se(last_rtqueue_sigval == 1); /* SIGRTMIN+2 */ assert_se(sd_event_run(e, 0) == 0); /* the other SIGUSR2 is dropped, because the first one was still queued */ assert_se(n_rtqueue == 4); assert_se(last_rtqueue_sigval == 1); sd_event_source_unref(u); sd_event_source_unref(v); sd_event_source_unref(s); sd_event_unref(e); } int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); log_parse_environment(); test_basic(); test_sd_event_now(); test_rtqueue(); return 0; } systemd-229/src/libsystemd/sd-hwdb/000077500000000000000000000000001265713322000173575ustar00rootroot00000000000000systemd-229/src/libsystemd/sd-hwdb/Makefile000077700000000000000000000000001265713322000231002../../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd/sd-hwdb/hwdb-internal.h000066400000000000000000000041631265713322000222720ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "sparse-endian.h" #include "util.h" #define HWDB_SIG { 'K', 'S', 'L', 'P', 'H', 'H', 'R', 'H' } /* on-disk trie objects */ struct trie_header_f { uint8_t signature[8]; /* version of tool which created the file */ le64_t tool_version; le64_t file_size; /* size of structures to allow them to grow */ le64_t header_size; le64_t node_size; le64_t child_entry_size; le64_t value_entry_size; /* offset of the root trie node */ le64_t nodes_root_off; /* size of the nodes and string section */ le64_t nodes_len; le64_t strings_len; } _packed_; struct trie_node_f { /* prefix of lookup string, shared by all children */ le64_t prefix_off; /* size of children entry array appended to the node */ uint8_t children_count; uint8_t padding[7]; /* size of value entry array appended to the node */ le64_t values_count; } _packed_; /* array of child entries, follows directly the node record */ struct trie_child_entry_f { /* index of the child node */ uint8_t c; uint8_t padding[7]; /* offset of the child node */ le64_t child_off; } _packed_; /* array of value entries, follows directly the node record/child array */ struct trie_value_entry_f { le64_t key_off; le64_t value_off; } _packed_; systemd-229/src/libsystemd/sd-hwdb/hwdb-util.h000066400000000000000000000014621265713322000214320ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-hwdb.h" #include "util.h" bool hwdb_validate(sd_hwdb *hwdb); systemd-229/src/libsystemd/sd-hwdb/sd-hwdb.c000066400000000000000000000342371265713322000210640ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Kay Sievers Copyright 2008 Alan Jenkins Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "sd-hwdb.h" #include "alloc-util.h" #include "fd-util.h" #include "hashmap.h" #include "hwdb-internal.h" #include "hwdb-util.h" #include "refcnt.h" #include "string-util.h" struct sd_hwdb { RefCount n_ref; int refcount; FILE *f; struct stat st; union { struct trie_header_f *head; const char *map; }; char *modalias; OrderedHashmap *properties; Iterator properties_iterator; bool properties_modified; }; struct linebuf { char bytes[LINE_MAX]; size_t size; size_t len; }; static void linebuf_init(struct linebuf *buf) { buf->size = 0; buf->len = 0; } static const char *linebuf_get(struct linebuf *buf) { if (buf->len + 1 >= sizeof(buf->bytes)) return NULL; buf->bytes[buf->len] = '\0'; return buf->bytes; } static bool linebuf_add(struct linebuf *buf, const char *s, size_t len) { if (buf->len + len >= sizeof(buf->bytes)) return false; memcpy(buf->bytes + buf->len, s, len); buf->len += len; return true; } static bool linebuf_add_char(struct linebuf *buf, char c) { if (buf->len + 1 >= sizeof(buf->bytes)) return false; buf->bytes[buf->len++] = c; return true; } static void linebuf_rem(struct linebuf *buf, size_t count) { assert(buf->len >= count); buf->len -= count; } static void linebuf_rem_char(struct linebuf *buf) { linebuf_rem(buf, 1); } static const struct trie_child_entry_f *trie_node_children(sd_hwdb *hwdb, const struct trie_node_f *node) { return (const struct trie_child_entry_f *)((const char *)node + le64toh(hwdb->head->node_size)); } static const struct trie_value_entry_f *trie_node_values(sd_hwdb *hwdb, const struct trie_node_f *node) { const char *base = (const char *)node; base += le64toh(hwdb->head->node_size); base += node->children_count * le64toh(hwdb->head->child_entry_size); return (const struct trie_value_entry_f *)base; } static const struct trie_node_f *trie_node_from_off(sd_hwdb *hwdb, le64_t off) { return (const struct trie_node_f *)(hwdb->map + le64toh(off)); } static const char *trie_string(sd_hwdb *hwdb, le64_t off) { return hwdb->map + le64toh(off); } static int trie_children_cmp_f(const void *v1, const void *v2) { const struct trie_child_entry_f *n1 = v1; const struct trie_child_entry_f *n2 = v2; return n1->c - n2->c; } static const struct trie_node_f *node_lookup_f(sd_hwdb *hwdb, const struct trie_node_f *node, uint8_t c) { struct trie_child_entry_f *child; struct trie_child_entry_f search; search.c = c; child = bsearch(&search, trie_node_children(hwdb, node), node->children_count, le64toh(hwdb->head->child_entry_size), trie_children_cmp_f); if (child) return trie_node_from_off(hwdb, child->child_off); return NULL; } static int hwdb_add_property(sd_hwdb *hwdb, const char *key, const char *value) { int r; assert(hwdb); assert(key); assert(value); /* * Silently ignore all properties which do not start with a * space; future extensions might use additional prefixes. */ if (key[0] != ' ') return 0; key++; r = ordered_hashmap_ensure_allocated(&hwdb->properties, &string_hash_ops); if (r < 0) return r; r = ordered_hashmap_replace(hwdb->properties, key, (char*)value); if (r < 0) return r; hwdb->properties_modified = true; return 0; } static int trie_fnmatch_f(sd_hwdb *hwdb, const struct trie_node_f *node, size_t p, struct linebuf *buf, const char *search) { size_t len; size_t i; const char *prefix; int err; prefix = trie_string(hwdb, node->prefix_off); len = strlen(prefix + p); linebuf_add(buf, prefix + p, len); for (i = 0; i < node->children_count; i++) { const struct trie_child_entry_f *child = &trie_node_children(hwdb, node)[i]; linebuf_add_char(buf, child->c); err = trie_fnmatch_f(hwdb, trie_node_from_off(hwdb, child->child_off), 0, buf, search); if (err < 0) return err; linebuf_rem_char(buf); } if (le64toh(node->values_count) && fnmatch(linebuf_get(buf), search, 0) == 0) for (i = 0; i < le64toh(node->values_count); i++) { err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_values(hwdb, node)[i].key_off), trie_string(hwdb, trie_node_values(hwdb, node)[i].value_off)); if (err < 0) return err; } linebuf_rem(buf, len); return 0; } static int trie_search_f(sd_hwdb *hwdb, const char *search) { struct linebuf buf; const struct trie_node_f *node; size_t i = 0; int err; linebuf_init(&buf); node = trie_node_from_off(hwdb, hwdb->head->nodes_root_off); while (node) { const struct trie_node_f *child; size_t p = 0; if (node->prefix_off) { uint8_t c; for (; (c = trie_string(hwdb, node->prefix_off)[p]); p++) { if (c == '*' || c == '?' || c == '[') return trie_fnmatch_f(hwdb, node, p, &buf, search + i + p); if (c != search[i + p]) return 0; } i += p; } child = node_lookup_f(hwdb, node, '*'); if (child) { linebuf_add_char(&buf, '*'); err = trie_fnmatch_f(hwdb, child, 0, &buf, search + i); if (err < 0) return err; linebuf_rem_char(&buf); } child = node_lookup_f(hwdb, node, '?'); if (child) { linebuf_add_char(&buf, '?'); err = trie_fnmatch_f(hwdb, child, 0, &buf, search + i); if (err < 0) return err; linebuf_rem_char(&buf); } child = node_lookup_f(hwdb, node, '['); if (child) { linebuf_add_char(&buf, '['); err = trie_fnmatch_f(hwdb, child, 0, &buf, search + i); if (err < 0) return err; linebuf_rem_char(&buf); } if (search[i] == '\0') { size_t n; for (n = 0; n < le64toh(node->values_count); n++) { err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_values(hwdb, node)[n].key_off), trie_string(hwdb, trie_node_values(hwdb, node)[n].value_off)); if (err < 0) return err; } return 0; } child = node_lookup_f(hwdb, node, search[i]); node = child; i++; } return 0; } static const char hwdb_bin_paths[] = "/etc/systemd/hwdb/hwdb.bin\0" "/etc/udev/hwdb.bin\0" "/usr/lib/systemd/hwdb/hwdb.bin\0" #ifdef HAVE_SPLIT_USR "/lib/systemd/hwdb/hwdb.bin\0" #endif UDEVLIBEXECDIR "/hwdb.bin\0"; _public_ int sd_hwdb_new(sd_hwdb **ret) { _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; const char *hwdb_bin_path; const char sig[] = HWDB_SIG; assert_return(ret, -EINVAL); hwdb = new0(sd_hwdb, 1); if (!hwdb) return -ENOMEM; hwdb->n_ref = REFCNT_INIT; /* find hwdb.bin in hwdb_bin_paths */ NULSTR_FOREACH(hwdb_bin_path, hwdb_bin_paths) { hwdb->f = fopen(hwdb_bin_path, "re"); if (hwdb->f) break; else if (errno == ENOENT) continue; else return log_debug_errno(errno, "error reading %s: %m", hwdb_bin_path); } if (!hwdb->f) { log_debug("hwdb.bin does not exist, please run udevadm hwdb --update"); return -ENOENT; } if (fstat(fileno(hwdb->f), &hwdb->st) < 0 || (size_t)hwdb->st.st_size < offsetof(struct trie_header_f, strings_len) + 8) return log_debug_errno(errno, "error reading %s: %m", hwdb_bin_path); hwdb->map = mmap(0, hwdb->st.st_size, PROT_READ, MAP_SHARED, fileno(hwdb->f), 0); if (hwdb->map == MAP_FAILED) return log_debug_errno(errno, "error mapping %s: %m", hwdb_bin_path); if (memcmp(hwdb->map, sig, sizeof(hwdb->head->signature)) != 0 || (size_t)hwdb->st.st_size != le64toh(hwdb->head->file_size)) { log_debug("error recognizing the format of %s", hwdb_bin_path); return -EINVAL; } log_debug("=== trie on-disk ==="); log_debug("tool version: %"PRIu64, le64toh(hwdb->head->tool_version)); log_debug("file size: %8"PRIi64" bytes", hwdb->st.st_size); log_debug("header size %8"PRIu64" bytes", le64toh(hwdb->head->header_size)); log_debug("strings %8"PRIu64" bytes", le64toh(hwdb->head->strings_len)); log_debug("nodes %8"PRIu64" bytes", le64toh(hwdb->head->nodes_len)); *ret = hwdb; hwdb = NULL; return 0; } _public_ sd_hwdb *sd_hwdb_ref(sd_hwdb *hwdb) { assert_return(hwdb, NULL); assert_se(REFCNT_INC(hwdb->n_ref) >= 2); return hwdb; } _public_ sd_hwdb *sd_hwdb_unref(sd_hwdb *hwdb) { if (hwdb && REFCNT_DEC(hwdb->n_ref) == 0) { if (hwdb->map) munmap((void *)hwdb->map, hwdb->st.st_size); safe_fclose(hwdb->f); free(hwdb->modalias); ordered_hashmap_free(hwdb->properties); free(hwdb); } return NULL; } bool hwdb_validate(sd_hwdb *hwdb) { bool found = false; const char* p; struct stat st; if (!hwdb) return false; if (!hwdb->f) return false; /* if hwdb.bin doesn't exist anywhere, we need to update */ NULSTR_FOREACH(p, hwdb_bin_paths) { if (stat(p, &st) >= 0) { found = true; break; } } if (!found) return true; if (timespec_load(&hwdb->st.st_mtim) != timespec_load(&st.st_mtim)) return true; return false; } static int properties_prepare(sd_hwdb *hwdb, const char *modalias) { _cleanup_free_ char *mod = NULL; int r; assert(hwdb); assert(modalias); if (streq_ptr(modalias, hwdb->modalias)) return 0; mod = strdup(modalias); if (!mod) return -ENOMEM; ordered_hashmap_clear(hwdb->properties); hwdb->properties_modified = true; r = trie_search_f(hwdb, modalias); if (r < 0) return r; free(hwdb->modalias); hwdb->modalias = mod; mod = NULL; return 0; } _public_ int sd_hwdb_get(sd_hwdb *hwdb, const char *modalias, const char *key, const char **_value) { const char *value; int r; assert_return(hwdb, -EINVAL); assert_return(hwdb->f, -EINVAL); assert_return(modalias, -EINVAL); assert_return(_value, -EINVAL); r = properties_prepare(hwdb, modalias); if (r < 0) return r; value = ordered_hashmap_get(hwdb->properties, key); if (!value) return -ENOENT; *_value = value; return 0; } _public_ int sd_hwdb_seek(sd_hwdb *hwdb, const char *modalias) { int r; assert_return(hwdb, -EINVAL); assert_return(hwdb->f, -EINVAL); assert_return(modalias, -EINVAL); r = properties_prepare(hwdb, modalias); if (r < 0) return r; hwdb->properties_modified = false; hwdb->properties_iterator = ITERATOR_FIRST; return 0; } _public_ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **value) { const void *k; void *v; assert_return(hwdb, -EINVAL); assert_return(key, -EINVAL); assert_return(value, -EINVAL); if (hwdb->properties_modified) return -EAGAIN; ordered_hashmap_iterate(hwdb->properties, &hwdb->properties_iterator, &v, &k); if (!k) return 0; *key = k; *value = v; return 1; } systemd-229/src/libsystemd/sd-id128/000077500000000000000000000000001265713322000172625ustar00rootroot00000000000000systemd-229/src/libsystemd/sd-id128/Makefile000077700000000000000000000000001265713322000230032../../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd/sd-id128/sd-id128.c000066400000000000000000000132221265713322000206610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-id128.h" #include "fd-util.h" #include "hexdecoct.h" #include "io-util.h" #include "macro.h" #include "random-util.h" #include "util.h" _public_ char *sd_id128_to_string(sd_id128_t id, char s[SD_ID128_STRING_MAX]) { unsigned n; assert_return(s, NULL); for (n = 0; n < 16; n++) { s[n*2] = hexchar(id.bytes[n] >> 4); s[n*2+1] = hexchar(id.bytes[n] & 0xF); } s[32] = 0; return s; } _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) { unsigned n, i; sd_id128_t t; bool is_guid = false; assert_return(s, -EINVAL); assert_return(ret, -EINVAL); for (n = 0, i = 0; n < 16;) { int a, b; if (s[i] == '-') { /* Is this a GUID? Then be nice, and skip over * the dashes */ if (i == 8) is_guid = true; else if (i == 13 || i == 18 || i == 23) { if (!is_guid) return -EINVAL; } else return -EINVAL; i++; continue; } a = unhexchar(s[i++]); if (a < 0) return -EINVAL; b = unhexchar(s[i++]); if (b < 0) return -EINVAL; t.bytes[n++] = (a << 4) | b; } if (i != (is_guid ? 36 : 32)) return -EINVAL; if (s[i] != 0) return -EINVAL; *ret = t; return 0; } static sd_id128_t make_v4_uuid(sd_id128_t id) { /* Stolen from generate_random_uuid() of drivers/char/random.c * in the kernel sources */ /* Set UUID version to 4 --- truly random generation */ id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40; /* Set the UUID variant to DCE */ id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80; return id; } _public_ int sd_id128_get_machine(sd_id128_t *ret) { static thread_local sd_id128_t saved_machine_id; static thread_local bool saved_machine_id_valid = false; _cleanup_close_ int fd = -1; char buf[33]; unsigned j; sd_id128_t t; int r; assert_return(ret, -EINVAL); if (saved_machine_id_valid) { *ret = saved_machine_id; return 0; } fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return -errno; r = loop_read_exact(fd, buf, 33, false); if (r < 0) return r; if (buf[32] !='\n') return -EIO; for (j = 0; j < 16; j++) { int a, b; a = unhexchar(buf[j*2]); b = unhexchar(buf[j*2+1]); if (a < 0 || b < 0) return -EIO; t.bytes[j] = a << 4 | b; } saved_machine_id = t; saved_machine_id_valid = true; *ret = t; return 0; } _public_ int sd_id128_get_boot(sd_id128_t *ret) { static thread_local sd_id128_t saved_boot_id; static thread_local bool saved_boot_id_valid = false; _cleanup_close_ int fd = -1; char buf[36]; unsigned j; sd_id128_t t; char *p; int r; assert_return(ret, -EINVAL); if (saved_boot_id_valid) { *ret = saved_boot_id; return 0; } fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return -errno; r = loop_read_exact(fd, buf, 36, false); if (r < 0) return r; for (j = 0, p = buf; j < 16; j++) { int a, b; if (p >= buf + 35) return -EIO; if (*p == '-') { p++; if (p >= buf + 35) return -EIO; } a = unhexchar(p[0]); b = unhexchar(p[1]); if (a < 0 || b < 0) return -EIO; t.bytes[j] = a << 4 | b; p += 2; } saved_boot_id = t; saved_boot_id_valid = true; *ret = t; return 0; } _public_ int sd_id128_randomize(sd_id128_t *ret) { sd_id128_t t; int r; assert_return(ret, -EINVAL); r = dev_urandom(&t, sizeof(t)); if (r < 0) return r; /* Turn this into a valid v4 UUID, to be nice. Note that we * only guarantee this for newly generated UUIDs, not for * pre-existing ones. */ *ret = make_v4_uuid(t); return 0; } systemd-229/src/libsystemd/sd-login/000077500000000000000000000000001265713322000175435ustar00rootroot00000000000000systemd-229/src/libsystemd/sd-login/Makefile000077700000000000000000000000001265713322000230512../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd/sd-login/sd-login.c000066400000000000000000000645121265713322000214330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-login.h" #include "alloc-util.h" #include "cgroup-util.h" #include "dirent-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "hostname-util.h" #include "io-util.h" #include "login-util.h" #include "macro.h" #include "parse-util.h" #include "path-util.h" #include "socket-util.h" #include "string-util.h" #include "strv.h" #include "user-util.h" #include "util.h" /* Error codes: * * invalid input parameters → -EINVAL * invalid fd → -EBADF * process does not exist → -ESRCH * cgroup does not exist → -ENOENT * machine, session does not exist → -ENXIO * requested metadata on object is missing → -ENODATA */ _public_ int sd_pid_get_session(pid_t pid, char **session) { assert_return(pid >= 0, -EINVAL); assert_return(session, -EINVAL); return cg_pid_get_session(pid, session); } _public_ int sd_pid_get_unit(pid_t pid, char **unit) { assert_return(pid >= 0, -EINVAL); assert_return(unit, -EINVAL); return cg_pid_get_unit(pid, unit); } _public_ int sd_pid_get_user_unit(pid_t pid, char **unit) { assert_return(pid >= 0, -EINVAL); assert_return(unit, -EINVAL); return cg_pid_get_user_unit(pid, unit); } _public_ int sd_pid_get_machine_name(pid_t pid, char **name) { assert_return(pid >= 0, -EINVAL); assert_return(name, -EINVAL); return cg_pid_get_machine_name(pid, name); } _public_ int sd_pid_get_slice(pid_t pid, char **slice) { assert_return(pid >= 0, -EINVAL); assert_return(slice, -EINVAL); return cg_pid_get_slice(pid, slice); } _public_ int sd_pid_get_user_slice(pid_t pid, char **slice) { assert_return(pid >= 0, -EINVAL); assert_return(slice, -EINVAL); return cg_pid_get_user_slice(pid, slice); } _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) { assert_return(pid >= 0, -EINVAL); assert_return(uid, -EINVAL); return cg_pid_get_owner_uid(pid, uid); } _public_ int sd_pid_get_cgroup(pid_t pid, char **cgroup) { char *c; int r; assert_return(pid >= 0, -EINVAL); assert_return(cgroup, -EINVAL); r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &c); if (r < 0) return r; /* The internal APIs return the empty string for the root * cgroup, let's return the "/" in the public APIs instead, as * that's easier and less ambigious for people to grok. */ if (isempty(c)) { free(c); c = strdup("/"); if (!c) return -ENOMEM; } *cgroup = c; return 0; } _public_ int sd_peer_get_session(int fd, char **session) { struct ucred ucred = {}; int r; assert_return(fd >= 0, -EBADF); assert_return(session, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; return cg_pid_get_session(ucred.pid, session); } _public_ int sd_peer_get_owner_uid(int fd, uid_t *uid) { struct ucred ucred; int r; assert_return(fd >= 0, -EBADF); assert_return(uid, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; return cg_pid_get_owner_uid(ucred.pid, uid); } _public_ int sd_peer_get_unit(int fd, char **unit) { struct ucred ucred; int r; assert_return(fd >= 0, -EBADF); assert_return(unit, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; return cg_pid_get_unit(ucred.pid, unit); } _public_ int sd_peer_get_user_unit(int fd, char **unit) { struct ucred ucred; int r; assert_return(fd >= 0, -EBADF); assert_return(unit, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; return cg_pid_get_user_unit(ucred.pid, unit); } _public_ int sd_peer_get_machine_name(int fd, char **machine) { struct ucred ucred; int r; assert_return(fd >= 0, -EBADF); assert_return(machine, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; return cg_pid_get_machine_name(ucred.pid, machine); } _public_ int sd_peer_get_slice(int fd, char **slice) { struct ucred ucred; int r; assert_return(fd >= 0, -EBADF); assert_return(slice, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; return cg_pid_get_slice(ucred.pid, slice); } _public_ int sd_peer_get_user_slice(int fd, char **slice) { struct ucred ucred; int r; assert_return(fd >= 0, -EBADF); assert_return(slice, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; return cg_pid_get_user_slice(ucred.pid, slice); } _public_ int sd_peer_get_cgroup(int fd, char **cgroup) { struct ucred ucred; int r; assert_return(fd >= 0, -EBADF); assert_return(cgroup, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; return sd_pid_get_cgroup(ucred.pid, cgroup); } static int file_of_uid(uid_t uid, char **p) { assert_return(uid_is_valid(uid), -EINVAL); assert(p); if (asprintf(p, "/run/systemd/users/" UID_FMT, uid) < 0) return -ENOMEM; return 0; } _public_ int sd_uid_get_state(uid_t uid, char**state) { _cleanup_free_ char *p = NULL; char *s = NULL; int r; assert_return(state, -EINVAL); r = file_of_uid(uid, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "STATE", &s, NULL); if (r == -ENOENT) { free(s); s = strdup("offline"); if (!s) return -ENOMEM; } if (r < 0) { free(s); return r; } if (isempty(s)) { free(s); return -EIO; } *state = s; return 0; } _public_ int sd_uid_get_display(uid_t uid, char **session) { _cleanup_free_ char *p = NULL, *s = NULL; int r; assert_return(session, -EINVAL); r = file_of_uid(uid, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "DISPLAY", &s, NULL); if (r == -ENOENT) return -ENODATA; if (r < 0) return r; if (isempty(s)) return -ENODATA; *session = s; s = NULL; return 0; } static int file_of_seat(const char *seat, char **_p) { char *p; int r; assert(_p); if (seat) { if (!filename_is_valid(seat)) return -EINVAL; p = strappend("/run/systemd/seats/", seat); } else { _cleanup_free_ char *buf = NULL; r = sd_session_get_seat(NULL, &buf); if (r < 0) return r; p = strappend("/run/systemd/seats/", buf); } if (!p) return -ENOMEM; *_p = p; p = NULL; return 0; } _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) { _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL; size_t l; int r; const char *word, *variable, *state; assert_return(uid_is_valid(uid), -EINVAL); r = file_of_seat(seat, &p); if (r < 0) return r; variable = require_active ? "ACTIVE_UID" : "UIDS"; r = parse_env_file(p, NEWLINE, variable, &s, NULL); if (r == -ENOENT) return 0; if (r < 0) return r; if (isempty(s)) return 0; if (asprintf(&t, UID_FMT, uid) < 0) return -ENOMEM; FOREACH_WORD(word, l, s, state) if (strneq(t, word, l)) return 1; return 0; } static int uid_get_array(uid_t uid, const char *variable, char ***array) { _cleanup_free_ char *p = NULL, *s = NULL; char **a; int r; assert(variable); r = file_of_uid(uid, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, variable, &s, NULL); if (r == -ENOENT || (r >= 0 && isempty(s))) { if (array) *array = NULL; return 0; } if (r < 0) return r; a = strv_split(s, " "); if (!a) return -ENOMEM; strv_uniq(a); r = strv_length(a); if (array) *array = a; else strv_free(a); return r; } _public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) { return uid_get_array( uid, require_active == 0 ? "ONLINE_SESSIONS" : require_active > 0 ? "ACTIVE_SESSIONS" : "SESSIONS", sessions); } _public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) { return uid_get_array( uid, require_active == 0 ? "ONLINE_SEATS" : require_active > 0 ? "ACTIVE_SEATS" : "SEATS", seats); } static int file_of_session(const char *session, char **_p) { char *p; int r; assert(_p); if (session) { if (!session_id_valid(session)) return -EINVAL; p = strappend("/run/systemd/sessions/", session); } else { _cleanup_free_ char *buf = NULL; r = sd_pid_get_session(0, &buf); if (r < 0) return r; p = strappend("/run/systemd/sessions/", buf); } if (!p) return -ENOMEM; *_p = p; return 0; } _public_ int sd_session_is_active(const char *session) { _cleanup_free_ char *p = NULL, *s = NULL; int r; r = file_of_session(session, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL); if (r == -ENOENT) return -ENXIO; if (r < 0) return r; if (isempty(s)) return -EIO; return parse_boolean(s); } _public_ int sd_session_is_remote(const char *session) { _cleanup_free_ char *p = NULL, *s = NULL; int r; r = file_of_session(session, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "REMOTE", &s, NULL); if (r == -ENOENT) return -ENXIO; if (r < 0) return r; if (isempty(s)) return -ENODATA; return parse_boolean(s); } _public_ int sd_session_get_state(const char *session, char **state) { _cleanup_free_ char *p = NULL, *s = NULL; int r; assert_return(state, -EINVAL); r = file_of_session(session, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "STATE", &s, NULL); if (r == -ENOENT) return -ENXIO; if (r < 0) return r; if (isempty(s)) return -EIO; *state = s; s = NULL; return 0; } _public_ int sd_session_get_uid(const char *session, uid_t *uid) { int r; _cleanup_free_ char *p = NULL, *s = NULL; assert_return(uid, -EINVAL); r = file_of_session(session, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "UID", &s, NULL); if (r == -ENOENT) return -ENXIO; if (r < 0) return r; if (isempty(s)) return -EIO; return parse_uid(s, uid); } static int session_get_string(const char *session, const char *field, char **value) { _cleanup_free_ char *p = NULL, *s = NULL; int r; assert_return(value, -EINVAL); assert(field); r = file_of_session(session, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, field, &s, NULL); if (r == -ENOENT) return -ENXIO; if (r < 0) return r; if (isempty(s)) return -ENODATA; *value = s; s = NULL; return 0; } _public_ int sd_session_get_seat(const char *session, char **seat) { return session_get_string(session, "SEAT", seat); } _public_ int sd_session_get_tty(const char *session, char **tty) { return session_get_string(session, "TTY", tty); } _public_ int sd_session_get_vt(const char *session, unsigned *vtnr) { _cleanup_free_ char *vtnr_string = NULL; unsigned u; int r; assert_return(vtnr, -EINVAL); r = session_get_string(session, "VTNR", &vtnr_string); if (r < 0) return r; r = safe_atou(vtnr_string, &u); if (r < 0) return r; *vtnr = u; return 0; } _public_ int sd_session_get_service(const char *session, char **service) { return session_get_string(session, "SERVICE", service); } _public_ int sd_session_get_type(const char *session, char **type) { return session_get_string(session, "TYPE", type); } _public_ int sd_session_get_class(const char *session, char **class) { return session_get_string(session, "CLASS", class); } _public_ int sd_session_get_desktop(const char *session, char **desktop) { _cleanup_free_ char *escaped = NULL; char *t; int r; assert_return(desktop, -EINVAL); r = session_get_string(session, "DESKTOP", &escaped); if (r < 0) return r; r = cunescape(escaped, 0, &t); if (r < 0) return r; *desktop = t; return 0; } _public_ int sd_session_get_display(const char *session, char **display) { return session_get_string(session, "DISPLAY", display); } _public_ int sd_session_get_remote_user(const char *session, char **remote_user) { return session_get_string(session, "REMOTE_USER", remote_user); } _public_ int sd_session_get_remote_host(const char *session, char **remote_host) { return session_get_string(session, "REMOTE_HOST", remote_host); } _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) { _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL; int r; assert_return(session || uid, -EINVAL); r = file_of_seat(seat, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "ACTIVE", &s, "ACTIVE_UID", &t, NULL); if (r == -ENOENT) return -ENXIO; if (r < 0) return r; if (session && !s) return -ENODATA; if (uid && !t) return -ENODATA; if (uid && t) { r = parse_uid(t, uid); if (r < 0) return r; } if (session && s) { *session = s; s = NULL; } return 0; } _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) { _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL; _cleanup_strv_free_ char **a = NULL; _cleanup_free_ uid_t *b = NULL; unsigned n = 0; int r; r = file_of_seat(seat, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "SESSIONS", &s, "ACTIVE_SESSIONS", &t, NULL); if (r == -ENOENT) return -ENXIO; if (r < 0) return r; if (s) { a = strv_split(s, " "); if (!a) return -ENOMEM; } if (uids && t) { const char *word, *state; size_t l; FOREACH_WORD(word, l, t, state) n++; if (n > 0) { unsigned i = 0; b = new(uid_t, n); if (!b) return -ENOMEM; FOREACH_WORD(word, l, t, state) { _cleanup_free_ char *k = NULL; k = strndup(word, l); if (!k) return -ENOMEM; r = parse_uid(k, b + i); if (r < 0) continue; i++; } } } r = strv_length(a); if (sessions) { *sessions = a; a = NULL; } if (uids) { *uids = b; b = NULL; } if (n_uids) *n_uids = n; return r; } static int seat_get_can(const char *seat, const char *variable) { _cleanup_free_ char *p = NULL, *s = NULL; int r; assert(variable); r = file_of_seat(seat, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, variable, &s, NULL); if (r == -ENOENT) return -ENXIO; if (r < 0) return r; if (isempty(s)) return -ENODATA; return parse_boolean(s); } _public_ int sd_seat_can_multi_session(const char *seat) { return seat_get_can(seat, "CAN_MULTI_SESSION"); } _public_ int sd_seat_can_tty(const char *seat) { return seat_get_can(seat, "CAN_TTY"); } _public_ int sd_seat_can_graphical(const char *seat) { return seat_get_can(seat, "CAN_GRAPHICAL"); } _public_ int sd_get_seats(char ***seats) { return get_files_in_directory("/run/systemd/seats/", seats); } _public_ int sd_get_sessions(char ***sessions) { return get_files_in_directory("/run/systemd/sessions/", sessions); } _public_ int sd_get_uids(uid_t **users) { _cleanup_closedir_ DIR *d; int r = 0; unsigned n = 0; _cleanup_free_ uid_t *l = NULL; d = opendir("/run/systemd/users/"); if (!d) return -errno; for (;;) { struct dirent *de; int k; uid_t uid; errno = 0; de = readdir(d); if (!de && errno > 0) return -errno; if (!de) break; dirent_ensure_type(d, de); if (!dirent_is_file(de)) continue; k = parse_uid(de->d_name, &uid); if (k < 0) continue; if (users) { if ((unsigned) r >= n) { uid_t *t; n = MAX(16, 2*r); t = realloc(l, sizeof(uid_t) * n); if (!t) return -ENOMEM; l = t; } assert((unsigned) r < n); l[r++] = uid; } else r++; } if (users) { *users = l; l = NULL; } return r; } _public_ int sd_get_machine_names(char ***machines) { char **l = NULL, **a, **b; int r; assert_return(machines, -EINVAL); r = get_files_in_directory("/run/systemd/machines/", &l); if (r < 0) return r; if (l) { r = 0; /* Filter out the unit: symlinks */ for (a = l, b = l; *a; a++) { if (startswith(*a, "unit:") || !machine_name_is_valid(*a)) free(*a); else { *b = *a; b++; r++; } } *b = NULL; } *machines = l; return r; } _public_ int sd_machine_get_class(const char *machine, char **class) { _cleanup_free_ char *c = NULL; const char *p; int r; assert_return(machine_name_is_valid(machine), -EINVAL); assert_return(class, -EINVAL); p = strjoina("/run/systemd/machines/", machine); r = parse_env_file(p, NEWLINE, "CLASS", &c, NULL); if (r == -ENOENT) return -ENXIO; if (r < 0) return r; if (!c) return -EIO; *class = c; c = NULL; return 0; } _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) { _cleanup_free_ char *netif = NULL; size_t l, allocated = 0, nr = 0; int *ni = NULL; const char *p, *word, *state; int r; assert_return(machine_name_is_valid(machine), -EINVAL); assert_return(ifindices, -EINVAL); p = strjoina("/run/systemd/machines/", machine); r = parse_env_file(p, NEWLINE, "NETIF", &netif, NULL); if (r == -ENOENT) return -ENXIO; if (r < 0) return r; if (!netif) { *ifindices = NULL; return 0; } FOREACH_WORD(word, l, netif, state) { char buf[l+1]; int ifi; *(char*) (mempcpy(buf, word, l)) = 0; if (parse_ifindex(buf, &ifi) < 0) continue; if (!GREEDY_REALLOC(ni, allocated, nr+1)) { free(ni); return -ENOMEM; } ni[nr++] = ifi; } *ifindices = ni; return nr; } static inline int MONITOR_TO_FD(sd_login_monitor *m) { return (int) (unsigned long) m - 1; } static inline sd_login_monitor* FD_TO_MONITOR(int fd) { return (sd_login_monitor*) (unsigned long) (fd + 1); } _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) { int fd, k; bool good = false; assert_return(m, -EINVAL); fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (fd < 0) return -errno; if (!category || streq(category, "seat")) { k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE); if (k < 0) { safe_close(fd); return -errno; } good = true; } if (!category || streq(category, "session")) { k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE); if (k < 0) { safe_close(fd); return -errno; } good = true; } if (!category || streq(category, "uid")) { k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE); if (k < 0) { safe_close(fd); return -errno; } good = true; } if (!category || streq(category, "machine")) { k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE); if (k < 0) { safe_close(fd); return -errno; } good = true; } if (!good) { close_nointr(fd); return -EINVAL; } *m = FD_TO_MONITOR(fd); return 0; } _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) { int fd; if (!m) return NULL; fd = MONITOR_TO_FD(m); close_nointr(fd); return NULL; } _public_ int sd_login_monitor_flush(sd_login_monitor *m) { assert_return(m, -EINVAL); return flush_fd(MONITOR_TO_FD(m)); } _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) { assert_return(m, -EINVAL); return MONITOR_TO_FD(m); } _public_ int sd_login_monitor_get_events(sd_login_monitor *m) { assert_return(m, -EINVAL); /* For now we will only return POLLIN here, since we don't * need anything else ever for inotify. However, let's have * this API to keep our options open should we later on need * it. */ return POLLIN; } _public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) { assert_return(m, -EINVAL); assert_return(timeout_usec, -EINVAL); /* For now we will only return (uint64_t) -1, since we don't * need any timeout. However, let's have this API to keep our * options open should we later on need it. */ *timeout_usec = (uint64_t) -1; return 0; } systemd-229/src/libsystemd/sd-login/test-login.c000066400000000000000000000175471265713322000220120ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-login.h" #include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "string-util.h" #include "strv.h" #include "util.h" static void test_login(void) { _cleanup_close_pair_ int pair[2] = { -1, -1 }; _cleanup_free_ char *pp = NULL, *qq = NULL; int r, k; uid_t u, u2; char *seat, *type, *class, *display, *remote_user, *remote_host, *display_session, *cgroup; char *session; char *state; char *session2; char *t; char **seats, **sessions, **machines; uid_t *uids; unsigned n; struct pollfd pollfd; sd_login_monitor *m = NULL; assert_se(sd_pid_get_session(0, &session) == 0); printf("session = %s\n", session); assert_se(sd_pid_get_owner_uid(0, &u2) == 0); printf("user = "UID_FMT"\n", u2); assert_se(sd_pid_get_cgroup(0, &cgroup) == 0); printf("cgroup = %s\n", cgroup); free(cgroup); display_session = NULL; r = sd_uid_get_display(u2, &display_session); assert_se(r >= 0 || r == -ENODATA); printf("user's display session = %s\n", strna(display_session)); free(display_session); assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0); sd_peer_get_session(pair[0], &pp); sd_peer_get_session(pair[1], &qq); assert_se(streq_ptr(pp, qq)); r = sd_uid_get_sessions(u2, false, &sessions); assert_se(r >= 0); assert_se(r == (int) strv_length(sessions)); assert_se(t = strv_join(sessions, ", ")); strv_free(sessions); printf("sessions = %s\n", t); free(t); assert_se(r == sd_uid_get_sessions(u2, false, NULL)); r = sd_uid_get_seats(u2, false, &seats); assert_se(r >= 0); assert_se(r == (int) strv_length(seats)); assert_se(t = strv_join(seats, ", ")); strv_free(seats); printf("seats = %s\n", t); free(t); assert_se(r == sd_uid_get_seats(u2, false, NULL)); r = sd_session_is_active(session); assert_se(r >= 0); printf("active = %s\n", yes_no(r)); r = sd_session_is_remote(session); assert_se(r >= 0); printf("remote = %s\n", yes_no(r)); r = sd_session_get_state(session, &state); assert_se(r >= 0); printf("state = %s\n", state); free(state); assert_se(sd_session_get_uid(session, &u) >= 0); printf("uid = "UID_FMT"\n", u); assert_se(u == u2); assert_se(sd_session_get_type(session, &type) >= 0); printf("type = %s\n", type); free(type); assert_se(sd_session_get_class(session, &class) >= 0); printf("class = %s\n", class); free(class); display = NULL; r = sd_session_get_display(session, &display); assert_se(r >= 0 || r == -ENODATA); printf("display = %s\n", strna(display)); free(display); remote_user = NULL; r = sd_session_get_remote_user(session, &remote_user); assert_se(r >= 0 || r == -ENODATA); printf("remote_user = %s\n", strna(remote_user)); free(remote_user); remote_host = NULL; r = sd_session_get_remote_host(session, &remote_host); assert_se(r >= 0 || r == -ENODATA); printf("remote_host = %s\n", strna(remote_host)); free(remote_host); assert_se(sd_session_get_seat(session, &seat) >= 0); printf("seat = %s\n", seat); r = sd_seat_can_multi_session(seat); assert_se(r >= 0); printf("can do multi session = %s\n", yes_no(r)); r = sd_seat_can_tty(seat); assert_se(r >= 0); printf("can do tty = %s\n", yes_no(r)); r = sd_seat_can_graphical(seat); assert_se(r >= 0); printf("can do graphical = %s\n", yes_no(r)); assert_se(sd_uid_get_state(u, &state) >= 0); printf("state = %s\n", state); assert_se(sd_uid_is_on_seat(u, 0, seat) > 0); k = sd_uid_is_on_seat(u, 1, seat); assert_se(k >= 0); assert_se(!!r == !!r); assert_se(sd_seat_get_active(seat, &session2, &u2) >= 0); printf("session2 = %s\n", session2); printf("uid2 = "UID_FMT"\n", u2); r = sd_seat_get_sessions(seat, &sessions, &uids, &n); assert_se(r >= 0); printf("n_sessions = %i\n", r); assert_se(r == (int) strv_length(sessions)); assert_se(t = strv_join(sessions, ", ")); strv_free(sessions); printf("sessions = %s\n", t); free(t); printf("uids ="); for (k = 0; k < (int) n; k++) printf(" "UID_FMT, uids[k]); printf("\n"); free(uids); assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r); free(session); free(state); free(session2); free(seat); r = sd_get_seats(&seats); assert_se(r >= 0); assert_se(r == (int) strv_length(seats)); assert_se(t = strv_join(seats, ", ")); strv_free(seats); printf("n_seats = %i\n", r); printf("seats = %s\n", t); free(t); assert_se(sd_get_seats(NULL) == r); r = sd_seat_get_active(NULL, &t, NULL); assert_se(r >= 0); printf("active session on current seat = %s\n", t); free(t); r = sd_get_sessions(&sessions); assert_se(r >= 0); assert_se(r == (int) strv_length(sessions)); assert_se(t = strv_join(sessions, ", ")); strv_free(sessions); printf("n_sessions = %i\n", r); printf("sessions = %s\n", t); free(t); assert_se(sd_get_sessions(NULL) == r); r = sd_get_uids(&uids); assert_se(r >= 0); printf("uids ="); for (k = 0; k < r; k++) printf(" "UID_FMT, uids[k]); printf("\n"); free(uids); printf("n_uids = %i\n", r); assert_se(sd_get_uids(NULL) == r); r = sd_get_machine_names(&machines); assert_se(r >= 0); assert_se(r == (int) strv_length(machines)); assert_se(t = strv_join(machines, ", ")); strv_free(machines); printf("n_machines = %i\n", r); printf("machines = %s\n", t); free(t); r = sd_login_monitor_new("session", &m); assert_se(r >= 0); for (n = 0; n < 5; n++) { usec_t timeout, nw; zero(pollfd); assert_se((pollfd.fd = sd_login_monitor_get_fd(m)) >= 0); assert_se((pollfd.events = sd_login_monitor_get_events(m)) >= 0); assert_se(sd_login_monitor_get_timeout(m, &timeout) >= 0); nw = now(CLOCK_MONOTONIC); r = poll(&pollfd, 1, timeout == (uint64_t) -1 ? -1 : timeout > nw ? (int) ((timeout - nw) / 1000) : 0); assert_se(r >= 0); sd_login_monitor_flush(m); printf("Wake!\n"); } sd_login_monitor_unref(m); } int main(int argc, char* argv[]) { log_parse_environment(); log_open(); test_login(); return 0; } systemd-229/src/libsystemd/sd-netlink/000077500000000000000000000000001265713322000200775ustar00rootroot00000000000000systemd-229/src/libsystemd/sd-netlink/Makefile000077700000000000000000000000001265713322000236202../../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd/sd-netlink/local-addresses.c000066400000000000000000000211531265713322000233120ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2011 Lennart Poettering Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-netlink.h" #include "alloc-util.h" #include "local-addresses.h" #include "macro.h" #include "netlink-util.h" static int address_compare(const void *_a, const void *_b) { const struct local_address *a = _a, *b = _b; /* Order lowest scope first, IPv4 before IPv6, lowest interface index first */ if (a->family == AF_INET && b->family == AF_INET6) return -1; if (a->family == AF_INET6 && b->family == AF_INET) return 1; if (a->scope < b->scope) return -1; if (a->scope > b->scope) return 1; if (a->metric < b->metric) return -1; if (a->metric > b->metric) return 1; if (a->ifindex < b->ifindex) return -1; if (a->ifindex > b->ifindex) return 1; return memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(a->family)); } int local_addresses(sd_netlink *context, int ifindex, int af, struct local_address **ret) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_free_ struct local_address *list = NULL; size_t n_list = 0, n_allocated = 0; sd_netlink_message *m; int r; assert(ret); if (context) rtnl = sd_netlink_ref(context); else { r = sd_netlink_open(&rtnl); if (r < 0) return r; } r = sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, af); if (r < 0) return r; r = sd_netlink_call(rtnl, req, 0, &reply); if (r < 0) return r; for (m = reply; m; m = sd_netlink_message_next(m)) { struct local_address *a; unsigned char flags; uint16_t type; int ifi, family; r = sd_netlink_message_get_errno(m); if (r < 0) return r; r = sd_netlink_message_get_type(m, &type); if (r < 0) return r; if (type != RTM_NEWADDR) continue; r = sd_rtnl_message_addr_get_ifindex(m, &ifi); if (r < 0) return r; if (ifindex > 0 && ifi != ifindex) continue; r = sd_rtnl_message_addr_get_family(m, &family); if (r < 0) return r; if (af != AF_UNSPEC && af != family) continue; r = sd_rtnl_message_addr_get_flags(m, &flags); if (r < 0) return r; if (flags & IFA_F_DEPRECATED) continue; if (!GREEDY_REALLOC0(list, n_allocated, n_list+1)) return -ENOMEM; a = list + n_list; r = sd_rtnl_message_addr_get_scope(m, &a->scope); if (r < 0) return r; if (ifindex == 0 && (a->scope == RT_SCOPE_HOST || a->scope == RT_SCOPE_NOWHERE)) continue; switch (family) { case AF_INET: r = sd_netlink_message_read_in_addr(m, IFA_LOCAL, &a->address.in); if (r < 0) { r = sd_netlink_message_read_in_addr(m, IFA_ADDRESS, &a->address.in); if (r < 0) continue; } break; case AF_INET6: r = sd_netlink_message_read_in6_addr(m, IFA_LOCAL, &a->address.in6); if (r < 0) { r = sd_netlink_message_read_in6_addr(m, IFA_ADDRESS, &a->address.in6); if (r < 0) continue; } break; default: continue; } a->ifindex = ifi; a->family = family; n_list++; }; if (n_list > 0) qsort(list, n_list, sizeof(struct local_address), address_compare); *ret = list; list = NULL; return (int) n_list; } int local_gateways(sd_netlink *context, int ifindex, int af, struct local_address **ret) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_free_ struct local_address *list = NULL; sd_netlink_message *m = NULL; size_t n_list = 0, n_allocated = 0; int r; assert(ret); if (context) rtnl = sd_netlink_ref(context); else { r = sd_netlink_open(&rtnl); if (r < 0) return r; } r = sd_rtnl_message_new_route(rtnl, &req, RTM_GETROUTE, af, RTPROT_UNSPEC); if (r < 0) return r; r = sd_netlink_message_request_dump(req, true); if (r < 0) return r; r = sd_netlink_call(rtnl, req, 0, &reply); if (r < 0) return r; for (m = reply; m; m = sd_netlink_message_next(m)) { struct local_address *a; uint16_t type; unsigned char dst_len, src_len; uint32_t ifi; int family; r = sd_netlink_message_get_errno(m); if (r < 0) return r; r = sd_netlink_message_get_type(m, &type); if (r < 0) return r; if (type != RTM_NEWROUTE) continue; /* We only care for default routes */ r = sd_rtnl_message_route_get_dst_prefixlen(m, &dst_len); if (r < 0) return r; if (dst_len != 0) continue; r = sd_rtnl_message_route_get_src_prefixlen(m, &src_len); if (r < 0) return r; if (src_len != 0) continue; r = sd_netlink_message_read_u32(m, RTA_OIF, &ifi); if (r < 0) return r; if (ifindex > 0 && (int) ifi != ifindex) continue; r = sd_rtnl_message_route_get_family(m, &family); if (r < 0) return r; if (af != AF_UNSPEC && af != family) continue; if (!GREEDY_REALLOC0(list, n_allocated, n_list + 1)) return -ENOMEM; a = list + n_list; switch (family) { case AF_INET: r = sd_netlink_message_read_in_addr(m, RTA_GATEWAY, &a->address.in); if (r < 0) continue; break; case AF_INET6: r = sd_netlink_message_read_in6_addr(m, RTA_GATEWAY, &a->address.in6); if (r < 0) continue; break; default: continue; } sd_netlink_message_read_u32(m, RTA_PRIORITY, &a->metric); a->ifindex = ifi; a->family = family; n_list++; } if (n_list > 0) qsort(list, n_list, sizeof(struct local_address), address_compare); *ret = list; list = NULL; return (int) n_list; } systemd-229/src/libsystemd/sd-netlink/local-addresses.h000066400000000000000000000021321265713322000233130ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2008-2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-netlink.h" #include "in-addr-util.h" struct local_address { int family, ifindex; unsigned char scope; uint32_t metric; union in_addr_union address; }; int local_addresses(sd_netlink *rtnl, int ifindex, int af, struct local_address **ret); int local_gateways(sd_netlink *rtnl, int ifindex, int af, struct local_address **ret); systemd-229/src/libsystemd/sd-netlink/netlink-internal.h000066400000000000000000000075301265713322000235330ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-netlink.h" #include "list.h" #include "netlink-types.h" #include "prioq.h" #include "refcnt.h" #define RTNL_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) #define RTNL_WQUEUE_MAX 1024 #define RTNL_RQUEUE_MAX 64*1024 #define RTNL_CONTAINER_DEPTH 32 struct reply_callback { sd_netlink_message_handler_t callback; void *userdata; usec_t timeout; uint64_t serial; unsigned prioq_idx; }; struct match_callback { sd_netlink_message_handler_t callback; uint16_t type; void *userdata; LIST_FIELDS(struct match_callback, match_callbacks); }; struct sd_netlink { RefCount n_ref; int fd; union { struct sockaddr sa; struct sockaddr_nl nl; } sockaddr; Hashmap *broadcast_group_refs; bool broadcast_group_dont_leave:1; /* until we can rely on 4.2 */ sd_netlink_message **rqueue; unsigned rqueue_size; size_t rqueue_allocated; sd_netlink_message **rqueue_partial; unsigned rqueue_partial_size; size_t rqueue_partial_allocated; struct nlmsghdr *rbuffer; size_t rbuffer_allocated; bool processing:1; uint32_t serial; struct Prioq *reply_callbacks_prioq; Hashmap *reply_callbacks; LIST_HEAD(struct match_callback, match_callbacks); pid_t original_pid; sd_event_source *io_event_source; sd_event_source *time_event_source; sd_event_source *exit_event_source; sd_event *event; }; struct netlink_attribute { size_t offset; /* offset from hdr to attribute */ bool nested:1; bool net_byteorder:1; }; struct netlink_container { const struct NLTypeSystem *type_system; /* the type system of the container */ size_t offset; /* offset from hdr to the start of the container */ struct netlink_attribute *attributes; unsigned short n_attributes; /* number of attributes in container */ }; struct sd_netlink_message { RefCount n_ref; sd_netlink *rtnl; struct nlmsghdr *hdr; struct netlink_container containers[RTNL_CONTAINER_DEPTH]; unsigned n_containers; /* number of containers */ bool sealed:1; bool broadcast:1; sd_netlink_message *next; /* next in a chain of multi-part messages */ }; int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type); int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret); int socket_open(int family); int socket_bind(sd_netlink *nl); int socket_broadcast_group_ref(sd_netlink *nl, unsigned group); int socket_broadcast_group_unref(sd_netlink *nl, unsigned group); int socket_write_message(sd_netlink *nl, sd_netlink_message *m); int socket_read_message(sd_netlink *nl); int rtnl_rqueue_make_room(sd_netlink *rtnl); int rtnl_rqueue_partial_make_room(sd_netlink *rtnl); /* Make sure callbacks don't destroy the rtnl connection */ #define NETLINK_DONT_DESTROY(rtnl) \ _cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl) systemd-229/src/libsystemd/sd-netlink/netlink-message.c000066400000000000000000000703201265713322000233330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-netlink.h" #include "alloc-util.h" #include "formats-util.h" #include "missing.h" #include "netlink-internal.h" #include "netlink-types.h" #include "netlink-util.h" #include "refcnt.h" #include "socket-util.h" #include "util.h" #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL) #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr; #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK) #define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK) int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) { sd_netlink_message *m; assert_return(ret, -EINVAL); /* Note that 'rtnl' is currently unused, if we start using it internally we must take care to avoid problems due to mutual references between buses and their queued messages. See sd-bus. */ m = new0(sd_netlink_message, 1); if (!m) return -ENOMEM; m->n_ref = REFCNT_INIT; m->sealed = false; *ret = m; return 0; } int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; const NLType *nl_type; size_t size; int r; r = type_system_get_type(&type_system_root, &nl_type, type); if (r < 0) return r; if (type_get_type(nl_type) != NETLINK_TYPE_NESTED) return -EINVAL; r = message_new_empty(rtnl, &m); if (r < 0) return r; size = NLMSG_SPACE(type_get_size(nl_type)); assert(size >= sizeof(struct nlmsghdr)); m->hdr = malloc0(size); if (!m->hdr) return -ENOMEM; m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; type_get_type_system(nl_type, &m->containers[0].type_system); m->hdr->nlmsg_len = size; m->hdr->nlmsg_type = type; *ret = m; m = NULL; return 0; } int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) { assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(m->hdr->nlmsg_type == RTM_GETLINK || m->hdr->nlmsg_type == RTM_GETADDR || m->hdr->nlmsg_type == RTM_GETROUTE || m->hdr->nlmsg_type == RTM_GETNEIGH, -EINVAL); if (dump) m->hdr->nlmsg_flags |= NLM_F_DUMP; else m->hdr->nlmsg_flags &= ~NLM_F_DUMP; return 0; } sd_netlink_message *sd_netlink_message_ref(sd_netlink_message *m) { if (m) assert_se(REFCNT_INC(m->n_ref) >= 2); return m; } sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) { if (m && REFCNT_DEC(m->n_ref) == 0) { unsigned i; free(m->hdr); for (i = 0; i <= m->n_containers; i++) free(m->containers[i].attributes); sd_netlink_message_unref(m->next); free(m); } return NULL; } int sd_netlink_message_get_type(sd_netlink_message *m, uint16_t *type) { assert_return(m, -EINVAL); assert_return(type, -EINVAL); *type = m->hdr->nlmsg_type; return 0; } int sd_netlink_message_set_flags(sd_netlink_message *m, uint16_t flags) { assert_return(m, -EINVAL); assert_return(flags, -EINVAL); m->hdr->nlmsg_flags = flags; return 0; } int sd_netlink_message_is_broadcast(sd_netlink_message *m) { assert_return(m, -EINVAL); return m->broadcast; } /* If successful the updated message will be correctly aligned, if unsuccessful the old message is untouched. */ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *data, size_t data_length) { uint32_t rta_length; size_t message_length, padding_length; struct nlmsghdr *new_hdr; struct rtattr *rta; char *padding; unsigned i; int offset; assert(m); assert(m->hdr); assert(!m->sealed); assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len); assert(!data || data_length); /* get offset of the new attribute */ offset = m->hdr->nlmsg_len; /* get the size of the new rta attribute (with padding at the end) */ rta_length = RTA_LENGTH(data_length); /* get the new message size (with padding at the end) */ message_length = offset + RTA_ALIGN(rta_length); /* realloc to fit the new attribute */ new_hdr = realloc(m->hdr, message_length); if (!new_hdr) return -ENOMEM; m->hdr = new_hdr; /* get pointer to the attribute we are about to add */ rta = (struct rtattr *) ((uint8_t *) m->hdr + offset); /* if we are inside containers, extend them */ for (i = 0; i < m->n_containers; i++) GET_CONTAINER(m, i)->rta_len += message_length - offset; /* fill in the attribute */ rta->rta_type = type; rta->rta_len = rta_length; if (data) /* we don't deal with the case where the user lies about the type * and gives us too little data (so don't do that) */ padding = mempcpy(RTA_DATA(rta), data, data_length); else { /* if no data was passed, make sure we still initialize the padding note that we can have data_length > 0 (used by some containers) */ padding = RTA_DATA(rta); } /* make sure also the padding at the end of the message is initialized */ padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding; memzero(padding, padding_length); /* update message size */ m->hdr->nlmsg_len = message_length; return offset; } static int message_attribute_has_type(sd_netlink_message *m, size_t *out_size, uint16_t attribute_type, uint16_t data_type) { const NLType *type; int r; assert(m); r = type_system_get_type(m->containers[m->n_containers].type_system, &type, attribute_type); if (r < 0) return r; if (type_get_type(type) != data_type) return -EINVAL; if (out_size) *out_size = type_get_size(type); return 0; } int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data) { size_t length, size; int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(data, -EINVAL); r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_STRING); if (r < 0) return r; if (size) { length = strnlen(data, size+1); if (length > size) return -EINVAL; } else length = strlen(data); r = add_rtattr(m, type, data, length + 1); if (r < 0) return r; return 0; } int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type) { size_t size; int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_FLAG); if (r < 0) return r; r = add_rtattr(m, type, NULL, 0); if (r < 0) return r; return 0; } int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uint8_t data) { int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U8); if (r < 0) return r; r = add_rtattr(m, type, &data, sizeof(uint8_t)); if (r < 0) return r; return 0; } int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, uint16_t data) { int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U16); if (r < 0) return r; r = add_rtattr(m, type, &data, sizeof(uint16_t)); if (r < 0) return r; return 0; } int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, uint32_t data) { int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U32); if (r < 0) return r; r = add_rtattr(m, type, &data, sizeof(uint32_t)); if (r < 0) return r; return 0; } int sd_netlink_message_append_data(sd_netlink_message *m, unsigned short type, const void *data, size_t len) { int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); r = add_rtattr(m, type, &data, len); if (r < 0) return r; return 0; } int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data) { int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(data, -EINVAL); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); if (r < 0) return r; r = add_rtattr(m, type, data, sizeof(struct in_addr)); if (r < 0) return r; return 0; } int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short type, const struct in6_addr *data) { int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(data, -EINVAL); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); if (r < 0) return r; r = add_rtattr(m, type, data, sizeof(struct in6_addr)); if (r < 0) return r; return 0; } int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short type, const struct ether_addr *data) { int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(data, -EINVAL); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR); if (r < 0) return r; r = add_rtattr(m, type, data, ETH_ALEN); if (r < 0) return r; return 0; } int sd_netlink_message_append_cache_info(sd_netlink_message *m, unsigned short type, const struct ifa_cacheinfo *info) { int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(info, -EINVAL); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_CACHE_INFO); if (r < 0) return r; r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo)); if (r < 0) return r; return 0; } int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type) { size_t size; int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE); r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_NESTED); if (r < 0) { const NLTypeSystemUnion *type_system_union; int family; r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_UNION); if (r < 0) return r; r = sd_rtnl_message_get_family(m, &family); if (r < 0) return r; r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type); if (r < 0) return r; r = type_system_union_protocol_get_type_system(type_system_union, &m->containers[m->n_containers + 1].type_system, family); if (r < 0) return r; } else { r = type_system_get_type_system(m->containers[m->n_containers].type_system, &m->containers[m->n_containers + 1].type_system, type); if (r < 0) return r; } r = add_rtattr(m, type | NLA_F_NESTED, NULL, size); if (r < 0) return r; m->containers[m->n_containers ++].offset = r; return 0; } int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned short type, const char *key) { const NLTypeSystemUnion *type_system_union; int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type); if (r < 0) return r; r = type_system_union_get_type_system(type_system_union, &m->containers[m->n_containers + 1].type_system, key); if (r < 0) return r; r = sd_netlink_message_append_string(m, type_system_union->match, key); if (r < 0) return r; /* do we evere need non-null size */ r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0); if (r < 0) return r; m->containers[m->n_containers ++].offset = r; return 0; } int sd_netlink_message_close_container(sd_netlink_message *m) { assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(m->n_containers > 0, -EINVAL); m->containers[m->n_containers].type_system = NULL; m->n_containers --; return 0; } static int netlink_message_read_internal(sd_netlink_message *m, unsigned short type, void **data, bool *net_byteorder) { struct netlink_attribute *attribute; struct rtattr *rta; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); assert_return(data, -EINVAL); assert(m->n_containers < RTNL_CONTAINER_DEPTH); assert(m->containers[m->n_containers].attributes); assert(type < m->containers[m->n_containers].n_attributes); attribute = &m->containers[m->n_containers].attributes[type]; if(!attribute->offset) return -ENODATA; rta = (struct rtattr*)((uint8_t *) m->hdr + attribute->offset); *data = RTA_DATA(rta); if (net_byteorder) *net_byteorder = attribute->net_byteorder; return RTA_PAYLOAD(rta); } int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data) { int r; void *attr_data; assert_return(m, -EINVAL); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_STRING); if (r < 0) return r; r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if (strnlen(attr_data, r) >= (size_t) r) return -EIO; if (data) *data = (const char *) attr_data; return 0; } int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8_t *data) { int r; void *attr_data; assert_return(m, -EINVAL); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U8); if (r < 0) return r; r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t) r < sizeof(uint8_t)) return -EIO; if (data) *data = *(uint8_t *) attr_data; return 0; } int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data) { void *attr_data; bool net_byteorder; int r; assert_return(m, -EINVAL); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U16); if (r < 0) return r; r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder); if (r < 0) return r; else if ((size_t) r < sizeof(uint16_t)) return -EIO; if (data) { if (net_byteorder) *data = be16toh(*(uint16_t *) attr_data); else *data = *(uint16_t *) attr_data; } return 0; } int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data) { void *attr_data; bool net_byteorder; int r; assert_return(m, -EINVAL); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U32); if (r < 0) return r; r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder); if (r < 0) return r; else if ((size_t)r < sizeof(uint32_t)) return -EIO; if (data) { if (net_byteorder) *data = be32toh(*(uint32_t *) attr_data); else *data = *(uint32_t *) attr_data; } return 0; } int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short type, struct ether_addr *data) { int r; void *attr_data; assert_return(m, -EINVAL); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR); if (r < 0) return r; r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t)r < sizeof(struct ether_addr)) return -EIO; if (data) memcpy(data, attr_data, sizeof(struct ether_addr)); return 0; } int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short type, struct ifa_cacheinfo *info) { int r; void *attr_data; assert_return(m, -EINVAL); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_CACHE_INFO); if (r < 0) return r; r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t)r < sizeof(struct ifa_cacheinfo)) return -EIO; if (info) memcpy(info, attr_data, sizeof(struct ifa_cacheinfo)); return 0; } int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data) { int r; void *attr_data; assert_return(m, -EINVAL); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); if (r < 0) return r; r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t)r < sizeof(struct in_addr)) return -EIO; if (data) memcpy(data, attr_data, sizeof(struct in_addr)); return 0; } int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data) { int r; void *attr_data; assert_return(m, -EINVAL); r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); if (r < 0) return r; r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t)r < sizeof(struct in6_addr)) return -EIO; if (data) memcpy(data, attr_data, sizeof(struct in6_addr)); return 0; } static int netlink_container_parse(sd_netlink_message *m, struct netlink_container *container, int count, struct rtattr *rta, unsigned int rt_len) { _cleanup_free_ struct netlink_attribute *attributes = NULL; attributes = new0(struct netlink_attribute, count); if(!attributes) return -ENOMEM; for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) { unsigned short type; type = RTA_TYPE(rta); /* if the kernel is newer than the headers we used when building, we ignore out-of-range attributes */ if (type >= count) continue; if (attributes[type].offset) log_debug("rtnl: message parse - overwriting repeated attribute"); attributes[type].offset = (uint8_t *) rta - (uint8_t *) m->hdr; attributes[type].nested = RTA_FLAGS(rta) & NLA_F_NESTED; attributes[type].net_byteorder = RTA_FLAGS(rta) & NLA_F_NET_BYTEORDER; } container->attributes = attributes; attributes = NULL; container->n_attributes = count; return 0; } int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type_id) { const NLType *nl_type; const NLTypeSystem *type_system; void *container; uint16_t type; size_t size; int r; assert_return(m, -EINVAL); assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL); r = type_system_get_type(m->containers[m->n_containers].type_system, &nl_type, type_id); if (r < 0) return r; type = type_get_type(nl_type); if (type == NETLINK_TYPE_NESTED) { r = type_system_get_type_system(m->containers[m->n_containers].type_system, &type_system, type_id); if (r < 0) return r; } else if (type == NETLINK_TYPE_UNION) { const NLTypeSystemUnion *type_system_union; r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type_id); if (r < 0) return r; switch (type_system_union->match_type) { case NL_MATCH_SIBLING: { const char *key; r = sd_netlink_message_read_string(m, type_system_union->match, &key); if (r < 0) return r; r = type_system_union_get_type_system(type_system_union, &type_system, key); if (r < 0) return r; break; } case NL_MATCH_PROTOCOL: { int family; r = sd_rtnl_message_get_family(m, &family); if (r < 0) return r; r = type_system_union_protocol_get_type_system(type_system_union, &type_system, family); if (r < 0) return r; break; } default: assert_not_reached("sd-netlink: invalid type system union type"); } } else return -EINVAL; r = netlink_message_read_internal(m, type_id, &container, NULL); if (r < 0) return r; else size = (size_t)r; m->n_containers ++; r = netlink_container_parse(m, &m->containers[m->n_containers], type_system_get_count(type_system), container, size); if (r < 0) { m->n_containers --; return r; } m->containers[m->n_containers].type_system = type_system; return 0; } int sd_netlink_message_exit_container(sd_netlink_message *m) { assert_return(m, -EINVAL); assert_return(m->sealed, -EINVAL); assert_return(m->n_containers > 0, -EINVAL); m->containers[m->n_containers].attributes = mfree(m->containers[m->n_containers].attributes); m->containers[m->n_containers].type_system = NULL; m->n_containers --; return 0; } uint32_t rtnl_message_get_serial(sd_netlink_message *m) { assert(m); assert(m->hdr); return m->hdr->nlmsg_seq; } int sd_netlink_message_is_error(sd_netlink_message *m) { assert_return(m, 0); assert_return(m->hdr, 0); return m->hdr->nlmsg_type == NLMSG_ERROR; } int sd_netlink_message_get_errno(sd_netlink_message *m) { struct nlmsgerr *err; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); if (!sd_netlink_message_is_error(m)) return 0; err = NLMSG_DATA(m->hdr); return err->error; } int sd_netlink_message_rewind(sd_netlink_message *m) { const NLType *nl_type; uint16_t type; size_t size; unsigned i; int r; assert_return(m, -EINVAL); /* don't allow appending to message once parsed */ if (!m->sealed) rtnl_message_seal(m); for (i = 1; i <= m->n_containers; i++) m->containers[i].attributes = mfree(m->containers[i].attributes); m->n_containers = 0; if (m->containers[0].attributes) /* top-level attributes have already been parsed */ return 0; assert(m->hdr); r = type_system_get_type(&type_system_root, &nl_type, m->hdr->nlmsg_type); if (r < 0) return r; type = type_get_type(nl_type); size = type_get_size(nl_type); if (type == NETLINK_TYPE_NESTED) { const NLTypeSystem *type_system; type_get_type_system(nl_type, &type_system); m->containers[0].type_system = type_system; r = netlink_container_parse(m, &m->containers[m->n_containers], type_system_get_count(type_system), (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)), NLMSG_PAYLOAD(m->hdr, size)); if (r < 0) return r; } return 0; } void rtnl_message_seal(sd_netlink_message *m) { assert(m); assert(!m->sealed); m->sealed = true; } sd_netlink_message *sd_netlink_message_next(sd_netlink_message *m) { assert_return(m, NULL); return m->next; } systemd-229/src/libsystemd/sd-netlink/netlink-socket.c000066400000000000000000000336661265713322000232130ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-netlink.h" #include "alloc-util.h" #include "formats-util.h" #include "missing.h" #include "netlink-internal.h" #include "netlink-types.h" #include "netlink-util.h" #include "refcnt.h" #include "socket-util.h" #include "util.h" int socket_open(int family) { int fd; fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, family); if (fd < 0) return -errno; return fd; } static int broadcast_groups_get(sd_netlink *nl) { _cleanup_free_ uint32_t *groups = NULL; socklen_t len = 0, old_len; unsigned i, j; int r; assert(nl); assert(nl->fd >= 0); r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len); if (r < 0) { if (errno == ENOPROTOOPT) { nl->broadcast_group_dont_leave = true; return 0; } else return -errno; } if (len == 0) return 0; groups = new0(uint32_t, len); if (!groups) return -ENOMEM; old_len = len; r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, groups, &len); if (r < 0) return -errno; if (old_len != len) return -EIO; r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL); if (r < 0) return r; for (i = 0; i < len; i++) { for (j = 0; j < sizeof(uint32_t) * 8; j ++) { uint32_t offset; unsigned group; offset = 1U << j; if (!(groups[i] & offset)) continue; group = i * sizeof(uint32_t) * 8 + j + 1; r = hashmap_put(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(1)); if (r < 0) return r; } } return 0; } int socket_bind(sd_netlink *nl) { socklen_t addrlen; int r, one = 1; r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_PKTINFO, &one, sizeof(one)); if (r < 0) return -errno; addrlen = sizeof(nl->sockaddr); r = bind(nl->fd, &nl->sockaddr.sa, addrlen); /* ignore EINVAL to allow opening an already bound socket */ if (r < 0 && errno != EINVAL) return -errno; r = getsockname(nl->fd, &nl->sockaddr.sa, &addrlen); if (r < 0) return -errno; r = broadcast_groups_get(nl); if (r < 0) return r; return 0; } static unsigned broadcast_group_get_ref(sd_netlink *nl, unsigned group) { assert(nl); return PTR_TO_UINT(hashmap_get(nl->broadcast_group_refs, UINT_TO_PTR(group))); } static int broadcast_group_set_ref(sd_netlink *nl, unsigned group, unsigned n_ref) { int r; assert(nl); r = hashmap_replace(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(n_ref)); if (r < 0) return r; return 0; } static int broadcast_group_join(sd_netlink *nl, unsigned group) { int r; assert(nl); assert(nl->fd >= 0); assert(group > 0); r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)); if (r < 0) return -errno; return 0; } int socket_broadcast_group_ref(sd_netlink *nl, unsigned group) { unsigned n_ref; int r; assert(nl); n_ref = broadcast_group_get_ref(nl, group); n_ref ++; r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL); if (r < 0) return r; r = broadcast_group_set_ref(nl, group, n_ref); if (r < 0) return r; if (n_ref > 1) /* not yet in the group */ return 0; r = broadcast_group_join(nl, group); if (r < 0) return r; return 0; } static int broadcast_group_leave(sd_netlink *nl, unsigned group) { int r; assert(nl); assert(nl->fd >= 0); assert(group > 0); if (nl->broadcast_group_dont_leave) return 0; r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, &group, sizeof(group)); if (r < 0) return -errno; return 0; } int socket_broadcast_group_unref(sd_netlink *nl, unsigned group) { unsigned n_ref; int r; assert(nl); n_ref = broadcast_group_get_ref(nl, group); assert(n_ref > 0); n_ref --; r = broadcast_group_set_ref(nl, group, n_ref); if (r < 0) return r; if (n_ref > 0) /* still refs left */ return 0; r = broadcast_group_leave(nl, group); if (r < 0) return r; return 0; } /* returns the number of bytes sent, or a negative error code */ int socket_write_message(sd_netlink *nl, sd_netlink_message *m) { union { struct sockaddr sa; struct sockaddr_nl nl; } addr = { .nl.nl_family = AF_NETLINK, }; ssize_t k; assert(nl); assert(m); assert(m->hdr); k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len, 0, &addr.sa, sizeof(addr)); if (k < 0) return -errno; return k; } static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) { union sockaddr_union sender; uint8_t cmsg_buffer[CMSG_SPACE(sizeof(struct nl_pktinfo))]; struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1, .msg_name = &sender, .msg_namelen = sizeof(sender), .msg_control = cmsg_buffer, .msg_controllen = sizeof(cmsg_buffer), }; struct cmsghdr *cmsg; uint32_t group = 0; int r; assert(fd >= 0); assert(iov); r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0)); if (r < 0) { /* no data */ if (errno == ENOBUFS) log_debug("rtnl: kernel receive buffer overrun"); else if (errno == EAGAIN) log_debug("rtnl: no data in socket"); return (errno == EAGAIN || errno == EINTR) ? 0 : -errno; } if (sender.nl.nl_pid != 0) { /* not from the kernel, ignore */ log_debug("rtnl: ignoring message from portid %"PRIu32, sender.nl.nl_pid); if (peek) { /* drop the message */ r = recvmsg(fd, &msg, 0); if (r < 0) return (errno == EAGAIN || errno == EINTR) ? 0 : -errno; } return 0; } CMSG_FOREACH(cmsg, &msg) { if (cmsg->cmsg_level == SOL_NETLINK && cmsg->cmsg_type == NETLINK_PKTINFO && cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) { struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg); /* multi-cast group */ group = pktinfo->group; } } if (_group) *_group = group; return r; } /* On success, the number of bytes received is returned and *ret points to the received message * which has a valid header and the correct size. * If nothing useful was received 0 is returned. * On failure, a negative error code is returned. */ int socket_read_message(sd_netlink *rtnl) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *first = NULL; struct iovec iov = {}; uint32_t group = 0; bool multi_part = false, done = false; struct nlmsghdr *new_msg; size_t len; int r; unsigned i = 0; assert(rtnl); assert(rtnl->rbuffer); assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr)); /* read nothing, just get the pending message size */ r = socket_recv_message(rtnl->fd, &iov, NULL, true); if (r <= 0) return r; else len = (size_t)r; /* make room for the pending message */ if (!greedy_realloc((void **)&rtnl->rbuffer, &rtnl->rbuffer_allocated, len, sizeof(uint8_t))) return -ENOMEM; iov.iov_base = rtnl->rbuffer; iov.iov_len = rtnl->rbuffer_allocated; /* read the pending message */ r = socket_recv_message(rtnl->fd, &iov, &group, false); if (r <= 0) return r; else len = (size_t)r; if (len > rtnl->rbuffer_allocated) /* message did not fit in read buffer */ return -EIO; if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) { multi_part = true; for (i = 0; i < rtnl->rqueue_partial_size; i++) { if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) == rtnl->rbuffer->nlmsg_seq) { first = rtnl->rqueue_partial[i]; break; } } } for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; const NLType *nl_type; if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid) /* not broadcast and not for us */ continue; if (new_msg->nlmsg_type == NLMSG_NOOP) /* silently drop noop messages */ continue; if (new_msg->nlmsg_type == NLMSG_DONE) { /* finished reading multi-part message */ done = true; /* if first is not defined, put NLMSG_DONE into the receive queue. */ if (first) continue; } /* check that we support this message type */ r = type_system_get_type(&type_system_root, &nl_type, new_msg->nlmsg_type); if (r < 0) { if (r == -EOPNOTSUPP) log_debug("sd-netlink: ignored message with unknown type: %i", new_msg->nlmsg_type); continue; } /* check that the size matches the message type */ if (new_msg->nlmsg_len < NLMSG_LENGTH(type_get_size(nl_type))) { log_debug("sd-netlink: message larger than expected, dropping"); continue; } r = message_new_empty(rtnl, &m); if (r < 0) return r; m->broadcast = !!group; m->hdr = memdup(new_msg, new_msg->nlmsg_len); if (!m->hdr) return -ENOMEM; /* seal and parse the top-level message */ r = sd_netlink_message_rewind(m); if (r < 0) return r; /* push the message onto the multi-part message stack */ if (first) m->next = first; first = m; m = NULL; } if (len) log_debug("sd-netlink: discarding %zu bytes of incoming message", len); if (!first) return 0; if (!multi_part || done) { /* we got a complete message, push it on the read queue */ r = rtnl_rqueue_make_room(rtnl); if (r < 0) return r; rtnl->rqueue[rtnl->rqueue_size ++] = first; first = NULL; if (multi_part && (i < rtnl->rqueue_partial_size)) { /* remove the message form the partial read queue */ memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1, sizeof(sd_netlink_message*) * (rtnl->rqueue_partial_size - i - 1)); rtnl->rqueue_partial_size --; } return 1; } else { /* we only got a partial multi-part message, push it on the partial read queue */ if (i < rtnl->rqueue_partial_size) { rtnl->rqueue_partial[i] = first; } else { r = rtnl_rqueue_partial_make_room(rtnl); if (r < 0) return r; rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first; } first = NULL; return 0; } } systemd-229/src/libsystemd/sd-netlink/netlink-types.c000066400000000000000000000724351265713322000230640ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include "macro.h" #include "missing.h" #include "netlink-types.h" #include "string-table.h" #include "util.h" /* Maximum ARP IP target defined in kernel */ #define BOND_MAX_ARP_TARGETS 16 typedef enum { BOND_ARP_TARGETS_0, BOND_ARP_TARGETS_1, BOND_ARP_TARGETS_2, BOND_ARP_TARGETS_3, BOND_ARP_TARGETS_4, BOND_ARP_TARGETS_5, BOND_ARP_TARGETS_6, BOND_ARP_TARGETS_7, BOND_ARP_TARGETS_8, BOND_ARP_TARGETS_9, BOND_ARP_TARGETS_10, BOND_ARP_TARGETS_11, BOND_ARP_TARGETS_12, BOND_ARP_TARGETS_13, BOND_ARP_TARGETS_14, BOND_ARP_TARGETS_MAX = BOND_MAX_ARP_TARGETS, } BondArpTargets; struct NLType { uint16_t type; size_t size; const NLTypeSystem *type_system; const NLTypeSystemUnion *type_system_union; }; struct NLTypeSystem { uint16_t count; const NLType *types; }; static const NLTypeSystem rtnl_link_type_system; static const NLType empty_types[1] = { /* fake array to avoid .types==NULL, which denotes invalid type-systems */ }; static const NLTypeSystem empty_type_system = { .count = 0, .types = empty_types, }; static const NLType rtnl_link_info_data_veth_types[] = { [VETH_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, }; static const NLType rtnl_link_info_data_ipvlan_types[] = { [IFLA_IPVLAN_MODE] = { .type = NETLINK_TYPE_U16 }, }; static const NLType rtnl_link_info_data_macvlan_types[] = { [IFLA_MACVLAN_MODE] = { .type = NETLINK_TYPE_U32 }, [IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 }, }; static const NLType rtnl_link_info_data_bridge_types[] = { [IFLA_BR_FORWARD_DELAY] = { .type = NETLINK_TYPE_U32 }, [IFLA_BR_HELLO_TIME] = { .type = NETLINK_TYPE_U32 }, [IFLA_BR_MAX_AGE] = { .type = NETLINK_TYPE_U32 }, [IFLA_BR_AGEING_TIME] = { .type = NETLINK_TYPE_U32 }, [IFLA_BR_STP_STATE] = { .type = NETLINK_TYPE_U32 }, [IFLA_BR_PRIORITY] = { .type = NETLINK_TYPE_U16 }, }; static const NLType rtnl_link_info_data_vlan_types[] = { [IFLA_VLAN_ID] = { .type = NETLINK_TYPE_U16 }, /* [IFLA_VLAN_FLAGS] = { .len = sizeof(struct ifla_vlan_flags) }, [IFLA_VLAN_EGRESS_QOS] = { .type = NETLINK_TYPE_NESTED }, [IFLA_VLAN_INGRESS_QOS] = { .type = NETLINK_TYPE_NESTED }, */ [IFLA_VLAN_PROTOCOL] = { .type = NETLINK_TYPE_U16 }, }; static const NLType rtnl_link_info_data_vxlan_types[] = { [IFLA_VXLAN_ID] = { .type = NETLINK_TYPE_U32 }, [IFLA_VXLAN_GROUP] = { .type = NETLINK_TYPE_IN_ADDR }, [IFLA_VXLAN_LINK] = { .type = NETLINK_TYPE_U32 }, [IFLA_VXLAN_LOCAL] = { .type = NETLINK_TYPE_U32}, [IFLA_VXLAN_TTL] = { .type = NETLINK_TYPE_U8 }, [IFLA_VXLAN_TOS] = { .type = NETLINK_TYPE_U8 }, [IFLA_VXLAN_LEARNING] = { .type = NETLINK_TYPE_U8 }, [IFLA_VXLAN_AGEING] = { .type = NETLINK_TYPE_U32 }, [IFLA_VXLAN_LIMIT] = { .type = NETLINK_TYPE_U32 }, [IFLA_VXLAN_PORT_RANGE] = { .type = NETLINK_TYPE_U32}, [IFLA_VXLAN_PROXY] = { .type = NETLINK_TYPE_U8 }, [IFLA_VXLAN_RSC] = { .type = NETLINK_TYPE_U8 }, [IFLA_VXLAN_L2MISS] = { .type = NETLINK_TYPE_U8 }, [IFLA_VXLAN_L3MISS] = { .type = NETLINK_TYPE_U8 }, [IFLA_VXLAN_PORT] = { .type = NETLINK_TYPE_U16 }, [IFLA_VXLAN_GROUP6] = { .type = NETLINK_TYPE_IN_ADDR }, [IFLA_VXLAN_LOCAL6] = { .type = NETLINK_TYPE_IN_ADDR }, [IFLA_VXLAN_UDP_CSUM] = { .type = NETLINK_TYPE_U8 }, [IFLA_VXLAN_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 }, [IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 }, [IFLA_VXLAN_REMCSUM_TX] = { .type = NETLINK_TYPE_U8 }, [IFLA_VXLAN_REMCSUM_RX] = { .type = NETLINK_TYPE_U8 }, [IFLA_VXLAN_GBP] = { .type = NETLINK_TYPE_FLAG }, [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG }, }; static const NLType rtnl_bond_arp_target_types[] = { [BOND_ARP_TARGETS_0] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_1] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_2] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_3] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_4] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_5] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_6] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_7] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_8] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_9] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_10] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_11] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_12] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_13] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_14] = { .type = NETLINK_TYPE_U32 }, [BOND_ARP_TARGETS_MAX] = { .type = NETLINK_TYPE_U32 }, }; static const NLTypeSystem rtnl_bond_arp_type_system = { .count = ELEMENTSOF(rtnl_bond_arp_target_types), .types = rtnl_bond_arp_target_types, }; static const NLType rtnl_link_info_data_bond_types[] = { [IFLA_BOND_MODE] = { .type = NETLINK_TYPE_U8 }, [IFLA_BOND_ACTIVE_SLAVE] = { .type = NETLINK_TYPE_U32 }, [IFLA_BOND_MIIMON] = { .type = NETLINK_TYPE_U32 }, [IFLA_BOND_UPDELAY] = { .type = NETLINK_TYPE_U32 }, [IFLA_BOND_DOWNDELAY] = { .type = NETLINK_TYPE_U32 }, [IFLA_BOND_USE_CARRIER] = { .type = NETLINK_TYPE_U8 }, [IFLA_BOND_ARP_INTERVAL] = { .type = NETLINK_TYPE_U32 }, [IFLA_BOND_ARP_IP_TARGET] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bond_arp_type_system }, [IFLA_BOND_ARP_VALIDATE] = { .type = NETLINK_TYPE_U32 }, [IFLA_BOND_ARP_ALL_TARGETS] = { .type = NETLINK_TYPE_U32 }, [IFLA_BOND_PRIMARY] = { .type = NETLINK_TYPE_U32 }, [IFLA_BOND_PRIMARY_RESELECT] = { .type = NETLINK_TYPE_U8 }, [IFLA_BOND_FAIL_OVER_MAC] = { .type = NETLINK_TYPE_U8 }, [IFLA_BOND_XMIT_HASH_POLICY] = { .type = NETLINK_TYPE_U8 }, [IFLA_BOND_RESEND_IGMP] = { .type = NETLINK_TYPE_U32 }, [IFLA_BOND_NUM_PEER_NOTIF] = { .type = NETLINK_TYPE_U8 }, [IFLA_BOND_ALL_SLAVES_ACTIVE] = { .type = NETLINK_TYPE_U8 }, [IFLA_BOND_MIN_LINKS] = { .type = NETLINK_TYPE_U32 }, [IFLA_BOND_LP_INTERVAL] = { .type = NETLINK_TYPE_U32 }, [IFLA_BOND_PACKETS_PER_SLAVE] = { .type = NETLINK_TYPE_U32 }, [IFLA_BOND_AD_LACP_RATE] = { .type = NETLINK_TYPE_U8 }, [IFLA_BOND_AD_SELECT] = { .type = NETLINK_TYPE_U8 }, [IFLA_BOND_AD_INFO] = { .type = NETLINK_TYPE_NESTED }, }; static const NLType rtnl_link_info_data_iptun_types[] = { [IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 }, [IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, [IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, [IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 }, [IFLA_IPTUN_TOS] = { .type = NETLINK_TYPE_U8 }, [IFLA_IPTUN_PMTUDISC] = { .type = NETLINK_TYPE_U8 }, [IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U16 }, [IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 }, [IFLA_IPTUN_6RD_PREFIX] = { .type = NETLINK_TYPE_IN_ADDR }, [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NETLINK_TYPE_U32 }, [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NETLINK_TYPE_U16 }, [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NETLINK_TYPE_U16 }, [IFLA_IPTUN_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 }, [IFLA_IPTUN_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 }, [IFLA_IPTUN_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 }, [IFLA_IPTUN_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 }, }; static const NLType rtnl_link_info_data_ipgre_types[] = { [IFLA_GRE_LINK] = { .type = NETLINK_TYPE_U32 }, [IFLA_GRE_IFLAGS] = { .type = NETLINK_TYPE_U16 }, [IFLA_GRE_OFLAGS] = { .type = NETLINK_TYPE_U16 }, [IFLA_GRE_IKEY] = { .type = NETLINK_TYPE_U32 }, [IFLA_GRE_OKEY] = { .type = NETLINK_TYPE_U32 }, [IFLA_GRE_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, [IFLA_GRE_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, [IFLA_GRE_TTL] = { .type = NETLINK_TYPE_U8 }, [IFLA_GRE_TOS] = { .type = NETLINK_TYPE_U8 }, [IFLA_GRE_PMTUDISC] = { .type = NETLINK_TYPE_U8 }, [IFLA_GRE_FLOWINFO] = { .type = NETLINK_TYPE_U32 }, [IFLA_GRE_FLAGS] = { .type = NETLINK_TYPE_U32 }, [IFLA_GRE_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 }, [IFLA_GRE_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 }, [IFLA_GRE_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 }, [IFLA_GRE_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 }, }; static const NLType rtnl_link_info_data_ipvti_types[] = { [IFLA_VTI_LINK] = { .type = NETLINK_TYPE_U32 }, [IFLA_VTI_IKEY] = { .type = NETLINK_TYPE_U32 }, [IFLA_VTI_OKEY] = { .type = NETLINK_TYPE_U32 }, [IFLA_VTI_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, [IFLA_VTI_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, }; static const NLType rtnl_link_info_data_ip6tnl_types[] = { [IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 }, [IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, [IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, [IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 }, [IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U32 }, [IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 }, [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NETLINK_TYPE_U8 }, [IFLA_IPTUN_FLOWINFO] = { .type = NETLINK_TYPE_U32 }, }; /* these strings must match the .kind entries in the kernel */ static const char* const nl_union_link_info_data_table[] = { [NL_UNION_LINK_INFO_DATA_BOND] = "bond", [NL_UNION_LINK_INFO_DATA_BRIDGE] = "bridge", [NL_UNION_LINK_INFO_DATA_VLAN] = "vlan", [NL_UNION_LINK_INFO_DATA_VETH] = "veth", [NL_UNION_LINK_INFO_DATA_DUMMY] = "dummy", [NL_UNION_LINK_INFO_DATA_MACVLAN] = "macvlan", [NL_UNION_LINK_INFO_DATA_MACVTAP] = "macvtap", [NL_UNION_LINK_INFO_DATA_IPVLAN] = "ipvlan", [NL_UNION_LINK_INFO_DATA_VXLAN] = "vxlan", [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = "ipip", [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = "gre", [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = "gretap", [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = "ip6gre", [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = "ip6gretap", [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = "sit", [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = "vti", [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = "vti6", [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = "ip6tnl", }; DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData); static const NLTypeSystem rtnl_link_info_data_type_systems[] = { [NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types), .types = rtnl_link_info_data_bond_types }, [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types), .types = rtnl_link_info_data_bridge_types }, [NL_UNION_LINK_INFO_DATA_VLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types), .types = rtnl_link_info_data_vlan_types }, [NL_UNION_LINK_INFO_DATA_VETH] = { .count = ELEMENTSOF(rtnl_link_info_data_veth_types), .types = rtnl_link_info_data_veth_types }, [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), .types = rtnl_link_info_data_macvlan_types }, [NL_UNION_LINK_INFO_DATA_MACVTAP] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), .types = rtnl_link_info_data_macvlan_types }, [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types), .types = rtnl_link_info_data_ipvlan_types }, [NL_UNION_LINK_INFO_DATA_VXLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types), .types = rtnl_link_info_data_vxlan_types }, [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), .types = rtnl_link_info_data_iptun_types }, [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), .types = rtnl_link_info_data_ipgre_types }, [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), .types = rtnl_link_info_data_ipgre_types }, [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), .types = rtnl_link_info_data_ipgre_types }, [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), .types = rtnl_link_info_data_ipgre_types }, [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), .types = rtnl_link_info_data_iptun_types }, [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), .types = rtnl_link_info_data_ipvti_types }, [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), .types = rtnl_link_info_data_ipvti_types }, [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types), .types = rtnl_link_info_data_ip6tnl_types }, }; static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = { .num = _NL_UNION_LINK_INFO_DATA_MAX, .lookup = nl_union_link_info_data_from_string, .type_systems = rtnl_link_info_data_type_systems, .match_type = NL_MATCH_SIBLING, .match = IFLA_INFO_KIND, }; static const NLType rtnl_link_info_types[] = { [IFLA_INFO_KIND] = { .type = NETLINK_TYPE_STRING }, [IFLA_INFO_DATA] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_link_info_data_type_system_union}, /* [IFLA_INFO_XSTATS], [IFLA_INFO_SLAVE_KIND] = { .type = NETLINK_TYPE_STRING }, [IFLA_INFO_SLAVE_DATA] = { .type = NETLINK_TYPE_NESTED }, */ }; static const NLTypeSystem rtnl_link_info_type_system = { .count = ELEMENTSOF(rtnl_link_info_types), .types = rtnl_link_info_types, }; static const struct NLType rtnl_prot_info_bridge_port_types[] = { [IFLA_BRPORT_STATE] = { .type = NETLINK_TYPE_U8 }, [IFLA_BRPORT_COST] = { .type = NETLINK_TYPE_U32 }, [IFLA_BRPORT_PRIORITY] = { .type = NETLINK_TYPE_U16 }, [IFLA_BRPORT_MODE] = { .type = NETLINK_TYPE_U8 }, [IFLA_BRPORT_GUARD] = { .type = NETLINK_TYPE_U8 }, [IFLA_BRPORT_PROTECT] = { .type = NETLINK_TYPE_U8 }, [IFLA_BRPORT_FAST_LEAVE] = { .type = NETLINK_TYPE_U8 }, [IFLA_BRPORT_LEARNING] = { .type = NETLINK_TYPE_U8 }, [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NETLINK_TYPE_U8 }, [IFLA_BRPORT_PROXYARP] = { .type = NETLINK_TYPE_U8 }, [IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 }, }; static const NLTypeSystem rtnl_prot_info_type_systems[] = { [AF_BRIDGE] = { .count = ELEMENTSOF(rtnl_prot_info_bridge_port_types), .types = rtnl_prot_info_bridge_port_types }, }; static const NLTypeSystemUnion rtnl_prot_info_type_system_union = { .num = AF_MAX, .type_systems = rtnl_prot_info_type_systems, .match_type = NL_MATCH_PROTOCOL, }; static const struct NLType rtnl_af_spec_inet6_types[] = { [IFLA_INET6_FLAGS] = { .type = NETLINK_TYPE_U32 }, /* IFLA_INET6_CONF, IFLA_INET6_STATS, IFLA_INET6_MCAST, IFLA_INET6_CACHEINFO, IFLA_INET6_ICMP6STATS, */ [IFLA_INET6_TOKEN] = { .type = NETLINK_TYPE_IN_ADDR }, [IFLA_INET6_ADDR_GEN_MODE] = { .type = NETLINK_TYPE_U8 }, }; static const NLTypeSystem rtnl_af_spec_inet6_type_system = { .count = ELEMENTSOF(rtnl_af_spec_inet6_types), .types = rtnl_af_spec_inet6_types, }; static const NLType rtnl_af_spec_types[] = { [AF_INET6] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_inet6_type_system }, }; static const NLTypeSystem rtnl_af_spec_type_system = { .count = ELEMENTSOF(rtnl_af_spec_types), .types = rtnl_af_spec_types, }; static const NLType rtnl_link_types[] = { [IFLA_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR }, [IFLA_BROADCAST] = { .type = NETLINK_TYPE_ETHER_ADDR }, [IFLA_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 }, [IFLA_MTU] = { .type = NETLINK_TYPE_U32 }, [IFLA_LINK] = { .type = NETLINK_TYPE_U32 }, /* [IFLA_QDISC], [IFLA_STATS], [IFLA_COST], [IFLA_PRIORITY], */ [IFLA_MASTER] = { .type = NETLINK_TYPE_U32 }, /* [IFLA_WIRELESS], */ [IFLA_PROTINFO] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_prot_info_type_system_union }, [IFLA_TXQLEN] = { .type = NETLINK_TYPE_U32 }, /* [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, */ [IFLA_WEIGHT] = { .type = NETLINK_TYPE_U32 }, [IFLA_OPERSTATE] = { .type = NETLINK_TYPE_U8 }, [IFLA_LINKMODE] = { .type = NETLINK_TYPE_U8 }, [IFLA_LINKINFO] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_info_type_system }, [IFLA_NET_NS_PID] = { .type = NETLINK_TYPE_U32 }, [IFLA_IFALIAS] = { .type = NETLINK_TYPE_STRING, .size = IFALIASZ - 1 }, /* [IFLA_NUM_VF], [IFLA_VFINFO_LIST] = {. type = NETLINK_TYPE_NESTED, }, [IFLA_STATS64], [IFLA_VF_PORTS] = { .type = NETLINK_TYPE_NESTED }, [IFLA_PORT_SELF] = { .type = NETLINK_TYPE_NESTED }, */ [IFLA_AF_SPEC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_type_system }, /* [IFLA_VF_PORTS], [IFLA_PORT_SELF], [IFLA_AF_SPEC], */ [IFLA_GROUP] = { .type = NETLINK_TYPE_U32 }, [IFLA_NET_NS_FD] = { .type = NETLINK_TYPE_U32 }, [IFLA_EXT_MASK] = { .type = NETLINK_TYPE_U32 }, [IFLA_PROMISCUITY] = { .type = NETLINK_TYPE_U32 }, [IFLA_NUM_TX_QUEUES] = { .type = NETLINK_TYPE_U32 }, [IFLA_NUM_RX_QUEUES] = { .type = NETLINK_TYPE_U32 }, [IFLA_CARRIER] = { .type = NETLINK_TYPE_U8 }, /* [IFLA_PHYS_PORT_ID] = { .type = NETLINK_TYPE_BINARY, .len = MAX_PHYS_PORT_ID_LEN }, */ }; static const NLTypeSystem rtnl_link_type_system = { .count = ELEMENTSOF(rtnl_link_types), .types = rtnl_link_types, }; /* IFA_FLAGS was defined in kernel 3.14, but we still support older * kernels where IFA_MAX is lower. */ static const NLType rtnl_address_types[] = { [IFA_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR }, [IFA_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, [IFA_LABEL] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 }, [IFA_BROADCAST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ [IFA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct ifa_cacheinfo) }, /* [IFA_ANYCAST], [IFA_MULTICAST], */ [IFA_FLAGS] = { .type = NETLINK_TYPE_U32 }, }; static const NLTypeSystem rtnl_address_type_system = { .count = ELEMENTSOF(rtnl_address_types), .types = rtnl_address_types, }; static const NLType rtnl_route_types[] = { [RTA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ [RTA_SRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ [RTA_IIF] = { .type = NETLINK_TYPE_U32 }, [RTA_OIF] = { .type = NETLINK_TYPE_U32 }, [RTA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR }, [RTA_PRIORITY] = { .type = NETLINK_TYPE_U32 }, [RTA_PREFSRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ /* [RTA_METRICS] = { .type = NETLINK_TYPE_NESTED }, [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) }, */ [RTA_FLOW] = { .type = NETLINK_TYPE_U32 }, /* 6? */ /* RTA_CACHEINFO, RTA_TABLE, RTA_MARK, RTA_MFC_STATS, RTA_VIA, RTA_NEWDST, */ [RTA_PREF] = { .type = NETLINK_TYPE_U8 }, }; static const NLTypeSystem rtnl_route_type_system = { .count = ELEMENTSOF(rtnl_route_types), .types = rtnl_route_types, }; static const NLType rtnl_neigh_types[] = { [NDA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, [NDA_LLADDR] = { .type = NETLINK_TYPE_ETHER_ADDR }, [NDA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) }, [NDA_PROBES] = { .type = NETLINK_TYPE_U32 }, [NDA_VLAN] = { .type = NETLINK_TYPE_U16 }, [NDA_PORT] = { .type = NETLINK_TYPE_U16 }, [NDA_VNI] = { .type = NETLINK_TYPE_U32 }, [NDA_IFINDEX] = { .type = NETLINK_TYPE_U32 }, }; static const NLTypeSystem rtnl_neigh_type_system = { .count = ELEMENTSOF(rtnl_neigh_types), .types = rtnl_neigh_types, }; static const NLType rtnl_types[] = { [NLMSG_DONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 }, [NLMSG_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) }, [RTM_NEWLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, [RTM_DELLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, [RTM_GETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, [RTM_SETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, [RTM_NEWADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, [RTM_DELADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, [RTM_GETADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, [RTM_NEWROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, [RTM_DELROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, [RTM_GETROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, [RTM_NEWNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, [RTM_DELNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, [RTM_GETNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, }; const NLTypeSystem type_system_root = { .count = ELEMENTSOF(rtnl_types), .types = rtnl_types, }; uint16_t type_get_type(const NLType *type) { assert(type); return type->type; } size_t type_get_size(const NLType *type) { assert(type); return type->size; } void type_get_type_system(const NLType *nl_type, const NLTypeSystem **ret) { assert(nl_type); assert(ret); assert(nl_type->type == NETLINK_TYPE_NESTED); assert(nl_type->type_system); *ret = nl_type->type_system; } void type_get_type_system_union(const NLType *nl_type, const NLTypeSystemUnion **ret) { assert(nl_type); assert(ret); assert(nl_type->type == NETLINK_TYPE_UNION); assert(nl_type->type_system_union); *ret = nl_type->type_system_union; } uint16_t type_system_get_count(const NLTypeSystem *type_system) { assert(type_system); return type_system->count; } int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type) { const NLType *nl_type; assert(ret); assert(type_system); assert(type_system->types); if (type >= type_system->count) return -EOPNOTSUPP; nl_type = &type_system->types[type]; if (nl_type->type == NETLINK_TYPE_UNSPEC) return -EOPNOTSUPP; *ret = nl_type; return 0; } int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type) { const NLType *nl_type; int r; assert(ret); r = type_system_get_type(type_system, &nl_type, type); if (r < 0) return r; type_get_type_system(nl_type, ret); return 0; } int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type) { const NLType *nl_type; int r; assert(ret); r = type_system_get_type(type_system, &nl_type, type); if (r < 0) return r; type_get_type_system_union(nl_type, ret); return 0; } int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, const char *key) { int type; assert(type_system_union); assert(type_system_union->match_type == NL_MATCH_SIBLING); assert(type_system_union->lookup); assert(type_system_union->type_systems); assert(ret); assert(key); type = type_system_union->lookup(key); if (type < 0) return -EOPNOTSUPP; assert(type < type_system_union->num); *ret = &type_system_union->type_systems[type]; return 0; } int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, uint16_t protocol) { const NLTypeSystem *type_system; assert(type_system_union); assert(type_system_union->type_systems); assert(type_system_union->match_type == NL_MATCH_PROTOCOL); assert(ret); if (protocol >= type_system_union->num) return -EOPNOTSUPP; type_system = &type_system_union->type_systems[protocol]; if (!type_system->types) return -EOPNOTSUPP; *ret = type_system; return 0; } systemd-229/src/libsystemd/sd-netlink/netlink-types.h000066400000000000000000000073021265713322000230600ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "macro.h" enum { NETLINK_TYPE_UNSPEC, NETLINK_TYPE_U8, /* NLA_U8 */ NETLINK_TYPE_U16, /* NLA_U16 */ NETLINK_TYPE_U32, /* NLA_U32 */ NETLINK_TYPE_U64, /* NLA_U64 */ NETLINK_TYPE_STRING, /* NLA_STRING */ NETLINK_TYPE_FLAG, /* NLA_FLAG */ NETLINK_TYPE_IN_ADDR, NETLINK_TYPE_ETHER_ADDR, NETLINK_TYPE_CACHE_INFO, NETLINK_TYPE_NESTED, /* NLA_NESTED */ NETLINK_TYPE_UNION, }; typedef enum NLMatchType { NL_MATCH_SIBLING, NL_MATCH_PROTOCOL, } NLMatchType; typedef struct NLTypeSystemUnion NLTypeSystemUnion; typedef struct NLTypeSystem NLTypeSystem; typedef struct NLType NLType; struct NLTypeSystemUnion { int num; NLMatchType match_type; uint16_t match; int (*lookup)(const char *); const NLTypeSystem *type_systems; }; extern const NLTypeSystem type_system_root; uint16_t type_get_type(const NLType *type); size_t type_get_size(const NLType *type); void type_get_type_system(const NLType *type, const NLTypeSystem **ret); void type_get_type_system_union(const NLType *type, const NLTypeSystemUnion **ret); uint16_t type_system_get_count(const NLTypeSystem *type_system); int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type); int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type); int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type); int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, const char *key); int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, uint16_t protocol); typedef enum NLUnionLinkInfoData { NL_UNION_LINK_INFO_DATA_BOND, NL_UNION_LINK_INFO_DATA_BRIDGE, NL_UNION_LINK_INFO_DATA_VLAN, NL_UNION_LINK_INFO_DATA_VETH, NL_UNION_LINK_INFO_DATA_DUMMY, NL_UNION_LINK_INFO_DATA_MACVLAN, NL_UNION_LINK_INFO_DATA_MACVTAP, NL_UNION_LINK_INFO_DATA_IPVLAN, NL_UNION_LINK_INFO_DATA_VXLAN, NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL, NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL, NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL, NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL, NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL, NL_UNION_LINK_INFO_DATA_SIT_TUNNEL, NL_UNION_LINK_INFO_DATA_VTI_TUNNEL, NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL, NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL, _NL_UNION_LINK_INFO_DATA_MAX, _NL_UNION_LINK_INFO_DATA_INVALID = -1 } NLUnionLinkInfoData; const char *nl_union_link_info_data_to_string(NLUnionLinkInfoData p) _const_; NLUnionLinkInfoData nl_union_link_info_data_from_string(const char *p) _pure_; systemd-229/src/libsystemd/sd-netlink/netlink-util.c000066400000000000000000000110431265713322000226610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-netlink.h" #include "netlink-internal.h" #include "netlink-util.h" int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; int r; assert(rtnl); assert(ifindex > 0); assert(name); if (!*rtnl) { r = sd_netlink_open(rtnl); if (r < 0) return r; } r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex); if (r < 0) return r; r = sd_netlink_message_append_string(message, IFLA_IFNAME, name); if (r < 0) return r; r = sd_netlink_call(*rtnl, message, 0, NULL); if (r < 0) return r; return 0; } int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, unsigned mtu) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; int r; assert(rtnl); assert(ifindex > 0); if (!alias && !mac && mtu == 0) return 0; if (!*rtnl) { r = sd_netlink_open(rtnl); if (r < 0) return r; } r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex); if (r < 0) return r; if (alias) { r = sd_netlink_message_append_string(message, IFLA_IFALIAS, alias); if (r < 0) return r; } if (mac) { r = sd_netlink_message_append_ether_addr(message, IFLA_ADDRESS, mac); if (r < 0) return r; } if (mtu > 0) { r = sd_netlink_message_append_u32(message, IFLA_MTU, mtu); if (r < 0) return r; } r = sd_netlink_call(*rtnl, message, 0, NULL); if (r < 0) return r; return 0; } int rtnl_message_new_synthetic_error(int error, uint32_t serial, sd_netlink_message **ret) { struct nlmsgerr *err; int r; assert(error <= 0); r = message_new(NULL, ret, NLMSG_ERROR); if (r < 0) return r; (*ret)->hdr->nlmsg_seq = serial; err = NLMSG_DATA((*ret)->hdr); err->error = error; return 0; } bool rtnl_message_type_is_neigh(uint16_t type) { switch (type) { case RTM_NEWNEIGH: case RTM_GETNEIGH: case RTM_DELNEIGH: return true; default: return false; } } bool rtnl_message_type_is_route(uint16_t type) { switch (type) { case RTM_NEWROUTE: case RTM_GETROUTE: case RTM_DELROUTE: return true; default: return false; } } bool rtnl_message_type_is_link(uint16_t type) { switch (type) { case RTM_NEWLINK: case RTM_SETLINK: case RTM_GETLINK: case RTM_DELLINK: return true; default: return false; } } bool rtnl_message_type_is_addr(uint16_t type) { switch (type) { case RTM_NEWADDR: case RTM_GETADDR: case RTM_DELADDR: return true; default: return false; } } int rtnl_log_parse_error(int r) { return log_error_errno(r, "Failed to parse netlink message: %m"); } int rtnl_log_create_error(int r) { return log_error_errno(r, "Failed to create netlink message: %m"); } systemd-229/src/libsystemd/sd-netlink/netlink-util.h000066400000000000000000000026431265713322000226740ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-netlink.h" #include "util.h" int rtnl_message_new_synthetic_error(int error, uint32_t serial, sd_netlink_message **ret); uint32_t rtnl_message_get_serial(sd_netlink_message *m); void rtnl_message_seal(sd_netlink_message *m); bool rtnl_message_type_is_link(uint16_t type); bool rtnl_message_type_is_addr(uint16_t type); bool rtnl_message_type_is_route(uint16_t type); bool rtnl_message_type_is_neigh(uint16_t type); int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name); int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, unsigned mtu); int rtnl_log_parse_error(int r); int rtnl_log_create_error(int r); systemd-229/src/libsystemd/sd-netlink/rtnl-message.c000066400000000000000000000443611265713322000226540ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-netlink.h" #include "formats-util.h" #include "missing.h" #include "netlink-internal.h" #include "netlink-types.h" #include "netlink-util.h" #include "refcnt.h" #include "socket-util.h" #include "util.h" int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char prefixlen) { struct rtmsg *rtm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); rtm = NLMSG_DATA(m->hdr); if ((rtm->rtm_family == AF_INET && prefixlen > 32) || (rtm->rtm_family == AF_INET6 && prefixlen > 128)) return -ERANGE; rtm->rtm_dst_len = prefixlen; return 0; } int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char prefixlen) { struct rtmsg *rtm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); rtm = NLMSG_DATA(m->hdr); if ((rtm->rtm_family == AF_INET && prefixlen > 32) || (rtm->rtm_family == AF_INET6 && prefixlen > 128)) return -ERANGE; rtm->rtm_src_len = prefixlen; return 0; } int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope) { struct rtmsg *rtm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); rtm = NLMSG_DATA(m->hdr); rtm->rtm_scope = scope; return 0; } int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags) { struct rtmsg *rtm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); rtm = NLMSG_DATA(m->hdr); rtm->rtm_flags = flags; return 0; } int sd_rtnl_message_route_get_flags(sd_netlink_message *m, unsigned *flags) { struct rtmsg *rtm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); assert_return(flags, -EINVAL); rtm = NLMSG_DATA(m->hdr); *flags = rtm->rtm_flags; return 0; } int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family) { struct rtmsg *rtm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); assert_return(family, -EINVAL); rtm = NLMSG_DATA(m->hdr); *family = rtm->rtm_family; return 0; } int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol) { struct rtmsg *rtm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); assert_return(protocol, -EINVAL); rtm = NLMSG_DATA(m->hdr); *protocol = rtm->rtm_protocol; return 0; } int sd_rtnl_message_route_get_scope(sd_netlink_message *m, unsigned char *scope) { struct rtmsg *rtm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); assert_return(scope, -EINVAL); rtm = NLMSG_DATA(m->hdr); *scope = rtm->rtm_scope; return 0; } int sd_rtnl_message_route_get_tos(sd_netlink_message *m, unsigned char *tos) { struct rtmsg *rtm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); assert_return(tos, -EINVAL); rtm = NLMSG_DATA(m->hdr); *tos = rtm->rtm_tos; return 0; } int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table) { struct rtmsg *rtm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); assert_return(table, -EINVAL); rtm = NLMSG_DATA(m->hdr); *table = rtm->rtm_table; return 0; } int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char *dst_len) { struct rtmsg *rtm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); assert_return(dst_len, -EINVAL); rtm = NLMSG_DATA(m->hdr); *dst_len = rtm->rtm_dst_len; return 0; } int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len) { struct rtmsg *rtm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); assert_return(src_len, -EINVAL); rtm = NLMSG_DATA(m->hdr); *src_len = rtm->rtm_src_len; return 0; } int sd_rtnl_message_new_route(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int rtm_family, unsigned char rtm_protocol) { struct rtmsg *rtm; int r; assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL); assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) || rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL); assert_return(ret, -EINVAL); r = message_new(rtnl, ret, nlmsg_type); if (r < 0) return r; if (nlmsg_type == RTM_NEWROUTE) (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND; rtm = NLMSG_DATA((*ret)->hdr); rtm->rtm_family = rtm_family; rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_type = RTN_UNICAST; rtm->rtm_table = RT_TABLE_MAIN; rtm->rtm_protocol = rtm_protocol; return 0; } int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags) { struct ndmsg *ndm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); ndm = NLMSG_DATA(m->hdr); ndm->ndm_flags |= flags; return 0; } int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state) { struct ndmsg *ndm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); ndm = NLMSG_DATA(m->hdr); ndm->ndm_state |= state; return 0; } int sd_rtnl_message_neigh_get_flags(sd_netlink_message *m, uint8_t *flags) { struct ndmsg *ndm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); ndm = NLMSG_DATA(m->hdr); *flags = ndm->ndm_flags; return 0; } int sd_rtnl_message_neigh_get_state(sd_netlink_message *m, uint16_t *state) { struct ndmsg *ndm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); ndm = NLMSG_DATA(m->hdr); *state = ndm->ndm_state; return 0; } int sd_rtnl_message_neigh_get_family(sd_netlink_message *m, int *family) { struct ndmsg *ndm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); assert_return(family, -EINVAL); ndm = NLMSG_DATA(m->hdr); *family = ndm->ndm_family; return 0; } int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message *m, int *index) { struct ndmsg *ndm; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); assert_return(index, -EINVAL); ndm = NLMSG_DATA(m->hdr); *index = ndm->ndm_ifindex; return 0; } int sd_rtnl_message_new_neigh(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int index, int ndm_family) { struct ndmsg *ndm; int r; assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL); assert_return(ndm_family == AF_INET || ndm_family == AF_INET6 || ndm_family == PF_BRIDGE, -EINVAL); assert_return(ret, -EINVAL); r = message_new(rtnl, ret, nlmsg_type); if (r < 0) return r; if (nlmsg_type == RTM_NEWNEIGH) (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND; ndm = NLMSG_DATA((*ret)->hdr); ndm->ndm_family = ndm_family; ndm->ndm_ifindex = index; return 0; } int sd_rtnl_message_link_set_flags(sd_netlink_message *m, unsigned flags, unsigned change) { struct ifinfomsg *ifi; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); assert_return(change, -EINVAL); ifi = NLMSG_DATA(m->hdr); ifi->ifi_flags = flags; ifi->ifi_change = change; return 0; } int sd_rtnl_message_link_set_type(sd_netlink_message *m, unsigned type) { struct ifinfomsg *ifi; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); ifi = NLMSG_DATA(m->hdr); ifi->ifi_type = type; return 0; } int sd_rtnl_message_link_set_family(sd_netlink_message *m, unsigned family) { struct ifinfomsg *ifi; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); ifi = NLMSG_DATA(m->hdr); ifi->ifi_family = family; return 0; } int sd_rtnl_message_new_link(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int index) { struct ifinfomsg *ifi; int r; assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL); assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL); assert_return(ret, -EINVAL); r = message_new(rtnl, ret, nlmsg_type); if (r < 0) return r; if (nlmsg_type == RTM_NEWLINK) (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; ifi = NLMSG_DATA((*ret)->hdr); ifi->ifi_family = AF_UNSPEC; ifi->ifi_index = index; return 0; } int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen) { struct ifaddrmsg *ifa; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); ifa = NLMSG_DATA(m->hdr); if ((ifa->ifa_family == AF_INET && prefixlen > 32) || (ifa->ifa_family == AF_INET6 && prefixlen > 128)) return -ERANGE; ifa->ifa_prefixlen = prefixlen; return 0; } int sd_rtnl_message_addr_set_flags(sd_netlink_message *m, unsigned char flags) { struct ifaddrmsg *ifa; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); ifa = NLMSG_DATA(m->hdr); ifa->ifa_flags = flags; return 0; } int sd_rtnl_message_addr_set_scope(sd_netlink_message *m, unsigned char scope) { struct ifaddrmsg *ifa; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); ifa = NLMSG_DATA(m->hdr); ifa->ifa_scope = scope; return 0; } int sd_rtnl_message_addr_get_family(sd_netlink_message *m, int *family) { struct ifaddrmsg *ifa; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); assert_return(family, -EINVAL); ifa = NLMSG_DATA(m->hdr); *family = ifa->ifa_family; return 0; } int sd_rtnl_message_addr_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen) { struct ifaddrmsg *ifa; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); assert_return(prefixlen, -EINVAL); ifa = NLMSG_DATA(m->hdr); *prefixlen = ifa->ifa_prefixlen; return 0; } int sd_rtnl_message_addr_get_scope(sd_netlink_message *m, unsigned char *scope) { struct ifaddrmsg *ifa; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); assert_return(scope, -EINVAL); ifa = NLMSG_DATA(m->hdr); *scope = ifa->ifa_scope; return 0; } int sd_rtnl_message_addr_get_flags(sd_netlink_message *m, unsigned char *flags) { struct ifaddrmsg *ifa; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); assert_return(flags, -EINVAL); ifa = NLMSG_DATA(m->hdr); *flags = ifa->ifa_flags; return 0; } int sd_rtnl_message_addr_get_ifindex(sd_netlink_message *m, int *ifindex) { struct ifaddrmsg *ifa; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); assert_return(ifindex, -EINVAL); ifa = NLMSG_DATA(m->hdr); *ifindex = ifa->ifa_index; return 0; } int sd_rtnl_message_new_addr(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int index, int family) { struct ifaddrmsg *ifa; int r; assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL); assert_return((nlmsg_type == RTM_GETADDR && index == 0) || index > 0, -EINVAL); assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) || family == AF_INET || family == AF_INET6, -EINVAL); assert_return(ret, -EINVAL); r = message_new(rtnl, ret, nlmsg_type); if (r < 0) return r; if (nlmsg_type == RTM_GETADDR) (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP; ifa = NLMSG_DATA((*ret)->hdr); ifa->ifa_index = index; ifa->ifa_family = family; if (family == AF_INET) ifa->ifa_prefixlen = 32; else if (family == AF_INET6) ifa->ifa_prefixlen = 128; return 0; } int sd_rtnl_message_new_addr_update(sd_netlink *rtnl, sd_netlink_message **ret, int index, int family) { int r; r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family); if (r < 0) return r; (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE; return 0; } int sd_rtnl_message_link_get_ifindex(sd_netlink_message *m, int *ifindex) { struct ifinfomsg *ifi; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); assert_return(ifindex, -EINVAL); ifi = NLMSG_DATA(m->hdr); *ifindex = ifi->ifi_index; return 0; } int sd_rtnl_message_link_get_flags(sd_netlink_message *m, unsigned *flags) { struct ifinfomsg *ifi; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); assert_return(flags, -EINVAL); ifi = NLMSG_DATA(m->hdr); *flags = ifi->ifi_flags; return 0; } int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned *type) { struct ifinfomsg *ifi; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); assert_return(type, -EINVAL); ifi = NLMSG_DATA(m->hdr); *type = ifi->ifi_type; return 0; } int sd_rtnl_message_get_family(sd_netlink_message *m, int *family) { assert_return(m, -EINVAL); assert_return(family, -EINVAL); assert(m->hdr); if (rtnl_message_type_is_link(m->hdr->nlmsg_type)) { struct ifinfomsg *ifi; ifi = NLMSG_DATA(m->hdr); *family = ifi->ifi_family; return 0; } else if (rtnl_message_type_is_route(m->hdr->nlmsg_type)) { struct rtmsg *rtm; rtm = NLMSG_DATA(m->hdr); *family = rtm->rtm_family; return 0; } else if (rtnl_message_type_is_neigh(m->hdr->nlmsg_type)) { struct ndmsg *ndm; ndm = NLMSG_DATA(m->hdr); *family = ndm->ndm_family; return 0; } else if (rtnl_message_type_is_addr(m->hdr->nlmsg_type)) { struct ifaddrmsg *ifa; ifa = NLMSG_DATA(m->hdr); *family = ifa->ifa_family; return 0; } return -EOPNOTSUPP; } systemd-229/src/libsystemd/sd-netlink/sd-netlink.c000066400000000000000000000651051265713322000223220ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-netlink.h" #include "alloc-util.h" #include "fd-util.h" #include "hashmap.h" #include "macro.h" #include "missing.h" #include "netlink-internal.h" #include "netlink-util.h" #include "socket-util.h" #include "util.h" static int sd_netlink_new(sd_netlink **ret) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; assert_return(ret, -EINVAL); rtnl = new0(sd_netlink, 1); if (!rtnl) return -ENOMEM; rtnl->n_ref = REFCNT_INIT; rtnl->fd = -1; rtnl->sockaddr.nl.nl_family = AF_NETLINK; rtnl->original_pid = getpid(); LIST_HEAD_INIT(rtnl->match_callbacks); /* We guarantee that the read buffer has at least space for * a message header */ if (!greedy_realloc((void**)&rtnl->rbuffer, &rtnl->rbuffer_allocated, sizeof(struct nlmsghdr), sizeof(uint8_t))) return -ENOMEM; /* Change notification responses have sequence 0, so we must * start our request sequence numbers at 1, or we may confuse our * responses with notifications from the kernel */ rtnl->serial = 1; *ret = rtnl; rtnl = NULL; return 0; } int sd_netlink_new_from_netlink(sd_netlink **ret, int fd) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; socklen_t addrlen; int r; assert_return(ret, -EINVAL); r = sd_netlink_new(&rtnl); if (r < 0) return r; addrlen = sizeof(rtnl->sockaddr); r = getsockname(fd, &rtnl->sockaddr.sa, &addrlen); if (r < 0) return -errno; if (rtnl->sockaddr.nl.nl_family != AF_NETLINK) return -EINVAL; rtnl->fd = fd; *ret = rtnl; rtnl = NULL; return 0; } static bool rtnl_pid_changed(sd_netlink *rtnl) { assert(rtnl); /* We don't support people creating an rtnl connection and * keeping it around over a fork(). Let's complain. */ return rtnl->original_pid != getpid(); } int sd_netlink_open_fd(sd_netlink **ret, int fd) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; int r; assert_return(ret, -EINVAL); assert_return(fd >= 0, -EBADF); r = sd_netlink_new(&rtnl); if (r < 0) return r; rtnl->fd = fd; r = socket_bind(rtnl); if (r < 0) { rtnl->fd = -1; /* on failure, the caller remains owner of the fd, hence don't close it here */ return r; } *ret = rtnl; rtnl = NULL; return 0; } int sd_netlink_open(sd_netlink **ret) { _cleanup_close_ int fd = -1; int r; fd = socket_open(NETLINK_ROUTE); if (fd < 0) return fd; r = sd_netlink_open_fd(ret, fd); if (r < 0) return r; fd = -1; return 0; } int sd_netlink_inc_rcvbuf(const sd_netlink *const rtnl, const int size) { return fd_inc_rcvbuf(rtnl->fd, size); } sd_netlink *sd_netlink_ref(sd_netlink *rtnl) { assert_return(rtnl, NULL); assert_return(!rtnl_pid_changed(rtnl), NULL); if (rtnl) assert_se(REFCNT_INC(rtnl->n_ref) >= 2); return rtnl; } sd_netlink *sd_netlink_unref(sd_netlink *rtnl) { if (!rtnl) return NULL; assert_return(!rtnl_pid_changed(rtnl), NULL); if (REFCNT_DEC(rtnl->n_ref) == 0) { struct match_callback *f; unsigned i; for (i = 0; i < rtnl->rqueue_size; i++) sd_netlink_message_unref(rtnl->rqueue[i]); free(rtnl->rqueue); for (i = 0; i < rtnl->rqueue_partial_size; i++) sd_netlink_message_unref(rtnl->rqueue_partial[i]); free(rtnl->rqueue_partial); free(rtnl->rbuffer); hashmap_free_free(rtnl->reply_callbacks); prioq_free(rtnl->reply_callbacks_prioq); sd_event_source_unref(rtnl->io_event_source); sd_event_source_unref(rtnl->time_event_source); sd_event_unref(rtnl->event); while ((f = rtnl->match_callbacks)) { sd_netlink_remove_match(rtnl, f->type, f->callback, f->userdata); } hashmap_free(rtnl->broadcast_group_refs); safe_close(rtnl->fd); free(rtnl); } return NULL; } static void rtnl_seal_message(sd_netlink *rtnl, sd_netlink_message *m) { assert(rtnl); assert(!rtnl_pid_changed(rtnl)); assert(m); assert(m->hdr); /* don't use seq == 0, as that is used for broadcasts, so we would get confused by replies to such messages */ m->hdr->nlmsg_seq = rtnl->serial++ ? : rtnl->serial++; rtnl_message_seal(m); return; } int sd_netlink_send(sd_netlink *nl, sd_netlink_message *message, uint32_t *serial) { int r; assert_return(nl, -EINVAL); assert_return(!rtnl_pid_changed(nl), -ECHILD); assert_return(message, -EINVAL); assert_return(!message->sealed, -EPERM); rtnl_seal_message(nl, message); r = socket_write_message(nl, message); if (r < 0) return r; if (serial) *serial = rtnl_message_get_serial(message); return 1; } int rtnl_rqueue_make_room(sd_netlink *rtnl) { assert(rtnl); if (rtnl->rqueue_size >= RTNL_RQUEUE_MAX) { log_debug("rtnl: exhausted the read queue size (%d)", RTNL_RQUEUE_MAX); return -ENOBUFS; } if (!GREEDY_REALLOC(rtnl->rqueue, rtnl->rqueue_allocated, rtnl->rqueue_size + 1)) return -ENOMEM; return 0; } int rtnl_rqueue_partial_make_room(sd_netlink *rtnl) { assert(rtnl); if (rtnl->rqueue_partial_size >= RTNL_RQUEUE_MAX) { log_debug("rtnl: exhausted the partial read queue size (%d)", RTNL_RQUEUE_MAX); return -ENOBUFS; } if (!GREEDY_REALLOC(rtnl->rqueue_partial, rtnl->rqueue_partial_allocated, rtnl->rqueue_partial_size + 1)) return -ENOMEM; return 0; } static int dispatch_rqueue(sd_netlink *rtnl, sd_netlink_message **message) { int r; assert(rtnl); assert(message); if (rtnl->rqueue_size <= 0) { /* Try to read a new message */ r = socket_read_message(rtnl); if (r <= 0) return r; } /* Dispatch a queued message */ *message = rtnl->rqueue[0]; rtnl->rqueue_size --; memmove(rtnl->rqueue, rtnl->rqueue + 1, sizeof(sd_netlink_message*) * rtnl->rqueue_size); return 1; } static int process_timeout(sd_netlink *rtnl) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; struct reply_callback *c; usec_t n; int r; assert(rtnl); c = prioq_peek(rtnl->reply_callbacks_prioq); if (!c) return 0; n = now(CLOCK_MONOTONIC); if (c->timeout > n) return 0; r = rtnl_message_new_synthetic_error(-ETIMEDOUT, c->serial, &m); if (r < 0) return r; assert_se(prioq_pop(rtnl->reply_callbacks_prioq) == c); hashmap_remove(rtnl->reply_callbacks, &c->serial); r = c->callback(rtnl, m, c->userdata); if (r < 0) log_debug_errno(r, "sd-netlink: timedout callback failed: %m"); free(c); return 1; } static int process_reply(sd_netlink *rtnl, sd_netlink_message *m) { _cleanup_free_ struct reply_callback *c = NULL; uint64_t serial; uint16_t type; int r; assert(rtnl); assert(m); serial = rtnl_message_get_serial(m); c = hashmap_remove(rtnl->reply_callbacks, &serial); if (!c) return 0; if (c->timeout != 0) prioq_remove(rtnl->reply_callbacks_prioq, c, &c->prioq_idx); r = sd_netlink_message_get_type(m, &type); if (r < 0) return 0; if (type == NLMSG_DONE) m = NULL; r = c->callback(rtnl, m, c->userdata); if (r < 0) log_debug_errno(r, "sd-netlink: callback failed: %m"); return 1; } static int process_match(sd_netlink *rtnl, sd_netlink_message *m) { struct match_callback *c; uint16_t type; int r; assert(rtnl); assert(m); r = sd_netlink_message_get_type(m, &type); if (r < 0) return r; LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks) { if (type == c->type) { r = c->callback(rtnl, m, c->userdata); if (r != 0) { if (r < 0) log_debug_errno(r, "sd-netlink: match callback failed: %m"); break; } } } return 1; } static int process_running(sd_netlink *rtnl, sd_netlink_message **ret) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; assert(rtnl); r = process_timeout(rtnl); if (r != 0) goto null_message; r = dispatch_rqueue(rtnl, &m); if (r < 0) return r; if (!m) goto null_message; if (sd_netlink_message_is_broadcast(m)) { r = process_match(rtnl, m); if (r != 0) goto null_message; } else { r = process_reply(rtnl, m); if (r != 0) goto null_message; } if (ret) { *ret = m; m = NULL; return 1; } return 1; null_message: if (r >= 0 && ret) *ret = NULL; return r; } int sd_netlink_process(sd_netlink *rtnl, sd_netlink_message **ret) { NETLINK_DONT_DESTROY(rtnl); int r; assert_return(rtnl, -EINVAL); assert_return(!rtnl_pid_changed(rtnl), -ECHILD); assert_return(!rtnl->processing, -EBUSY); rtnl->processing = true; r = process_running(rtnl, ret); rtnl->processing = false; return r; } static usec_t calc_elapse(uint64_t usec) { if (usec == (uint64_t) -1) return 0; if (usec == 0) usec = RTNL_DEFAULT_TIMEOUT; return now(CLOCK_MONOTONIC) + usec; } static int rtnl_poll(sd_netlink *rtnl, bool need_more, uint64_t timeout_usec) { struct pollfd p[1] = {}; struct timespec ts; usec_t m = USEC_INFINITY; int r, e; assert(rtnl); e = sd_netlink_get_events(rtnl); if (e < 0) return e; if (need_more) /* Caller wants more data, and doesn't care about * what's been read or any other timeouts. */ e |= POLLIN; else { usec_t until; /* Caller wants to process if there is something to * process, but doesn't care otherwise */ r = sd_netlink_get_timeout(rtnl, &until); if (r < 0) return r; if (r > 0) { usec_t nw; nw = now(CLOCK_MONOTONIC); m = until > nw ? until - nw : 0; } } if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m)) m = timeout_usec; p[0].fd = rtnl->fd; p[0].events = e; r = ppoll(p, 1, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL); if (r < 0) return -errno; return r > 0 ? 1 : 0; } int sd_netlink_wait(sd_netlink *nl, uint64_t timeout_usec) { assert_return(nl, -EINVAL); assert_return(!rtnl_pid_changed(nl), -ECHILD); if (nl->rqueue_size > 0) return 0; return rtnl_poll(nl, false, timeout_usec); } static int timeout_compare(const void *a, const void *b) { const struct reply_callback *x = a, *y = b; if (x->timeout != 0 && y->timeout == 0) return -1; if (x->timeout == 0 && y->timeout != 0) return 1; if (x->timeout < y->timeout) return -1; if (x->timeout > y->timeout) return 1; return 0; } int sd_netlink_call_async(sd_netlink *nl, sd_netlink_message *m, sd_netlink_message_handler_t callback, void *userdata, uint64_t usec, uint32_t *serial) { struct reply_callback *c; uint32_t s; int r, k; assert_return(nl, -EINVAL); assert_return(m, -EINVAL); assert_return(callback, -EINVAL); assert_return(!rtnl_pid_changed(nl), -ECHILD); r = hashmap_ensure_allocated(&nl->reply_callbacks, &uint64_hash_ops); if (r < 0) return r; if (usec != (uint64_t) -1) { r = prioq_ensure_allocated(&nl->reply_callbacks_prioq, timeout_compare); if (r < 0) return r; } c = new0(struct reply_callback, 1); if (!c) return -ENOMEM; c->callback = callback; c->userdata = userdata; c->timeout = calc_elapse(usec); k = sd_netlink_send(nl, m, &s); if (k < 0) { free(c); return k; } c->serial = s; r = hashmap_put(nl->reply_callbacks, &c->serial, c); if (r < 0) { free(c); return r; } if (c->timeout != 0) { r = prioq_put(nl->reply_callbacks_prioq, c, &c->prioq_idx); if (r > 0) { c->timeout = 0; sd_netlink_call_async_cancel(nl, c->serial); return r; } } if (serial) *serial = s; return k; } int sd_netlink_call_async_cancel(sd_netlink *nl, uint32_t serial) { struct reply_callback *c; uint64_t s = serial; assert_return(nl, -EINVAL); assert_return(serial != 0, -EINVAL); assert_return(!rtnl_pid_changed(nl), -ECHILD); c = hashmap_remove(nl->reply_callbacks, &s); if (!c) return 0; if (c->timeout != 0) prioq_remove(nl->reply_callbacks_prioq, c, &c->prioq_idx); free(c); return 1; } int sd_netlink_call(sd_netlink *rtnl, sd_netlink_message *message, uint64_t usec, sd_netlink_message **ret) { usec_t timeout; uint32_t serial; int r; assert_return(rtnl, -EINVAL); assert_return(!rtnl_pid_changed(rtnl), -ECHILD); assert_return(message, -EINVAL); r = sd_netlink_send(rtnl, message, &serial); if (r < 0) return r; timeout = calc_elapse(usec); for (;;) { usec_t left; unsigned i; for (i = 0; i < rtnl->rqueue_size; i++) { uint32_t received_serial; received_serial = rtnl_message_get_serial(rtnl->rqueue[i]); if (received_serial == serial) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *incoming = NULL; uint16_t type; incoming = rtnl->rqueue[i]; /* found a match, remove from rqueue and return it */ memmove(rtnl->rqueue + i,rtnl->rqueue + i + 1, sizeof(sd_netlink_message*) * (rtnl->rqueue_size - i - 1)); rtnl->rqueue_size--; r = sd_netlink_message_get_errno(incoming); if (r < 0) return r; r = sd_netlink_message_get_type(incoming, &type); if (r < 0) return r; if (type == NLMSG_DONE) { *ret = NULL; return 0; } if (ret) { *ret = incoming; incoming = NULL; } return 1; } } r = socket_read_message(rtnl); if (r < 0) return r; if (r > 0) /* received message, so try to process straight away */ continue; if (timeout > 0) { usec_t n; n = now(CLOCK_MONOTONIC); if (n >= timeout) return -ETIMEDOUT; left = timeout - n; } else left = (uint64_t) -1; r = rtnl_poll(rtnl, true, left); if (r < 0) return r; else if (r == 0) return -ETIMEDOUT; } } int sd_netlink_get_events(sd_netlink *rtnl) { assert_return(rtnl, -EINVAL); assert_return(!rtnl_pid_changed(rtnl), -ECHILD); if (rtnl->rqueue_size == 0) return POLLIN; else return 0; } int sd_netlink_get_timeout(sd_netlink *rtnl, uint64_t *timeout_usec) { struct reply_callback *c; assert_return(rtnl, -EINVAL); assert_return(timeout_usec, -EINVAL); assert_return(!rtnl_pid_changed(rtnl), -ECHILD); if (rtnl->rqueue_size > 0) { *timeout_usec = 0; return 1; } c = prioq_peek(rtnl->reply_callbacks_prioq); if (!c) { *timeout_usec = (uint64_t) -1; return 0; } *timeout_usec = c->timeout; return 1; } static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) { sd_netlink *rtnl = userdata; int r; assert(rtnl); r = sd_netlink_process(rtnl, NULL); if (r < 0) return r; return 1; } static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) { sd_netlink *rtnl = userdata; int r; assert(rtnl); r = sd_netlink_process(rtnl, NULL); if (r < 0) return r; return 1; } static int prepare_callback(sd_event_source *s, void *userdata) { sd_netlink *rtnl = userdata; int r, e; usec_t until; assert(s); assert(rtnl); e = sd_netlink_get_events(rtnl); if (e < 0) return e; r = sd_event_source_set_io_events(rtnl->io_event_source, e); if (r < 0) return r; r = sd_netlink_get_timeout(rtnl, &until); if (r < 0) return r; if (r > 0) { int j; j = sd_event_source_set_time(rtnl->time_event_source, until); if (j < 0) return j; } r = sd_event_source_set_enabled(rtnl->time_event_source, r > 0); if (r < 0) return r; return 1; } int sd_netlink_attach_event(sd_netlink *rtnl, sd_event *event, int priority) { int r; assert_return(rtnl, -EINVAL); assert_return(!rtnl->event, -EBUSY); assert(!rtnl->io_event_source); assert(!rtnl->time_event_source); if (event) rtnl->event = sd_event_ref(event); else { r = sd_event_default(&rtnl->event); if (r < 0) return r; } r = sd_event_add_io(rtnl->event, &rtnl->io_event_source, rtnl->fd, 0, io_callback, rtnl); if (r < 0) goto fail; r = sd_event_source_set_priority(rtnl->io_event_source, priority); if (r < 0) goto fail; r = sd_event_source_set_description(rtnl->io_event_source, "rtnl-receive-message"); if (r < 0) goto fail; r = sd_event_source_set_prepare(rtnl->io_event_source, prepare_callback); if (r < 0) goto fail; r = sd_event_add_time(rtnl->event, &rtnl->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, rtnl); if (r < 0) goto fail; r = sd_event_source_set_priority(rtnl->time_event_source, priority); if (r < 0) goto fail; r = sd_event_source_set_description(rtnl->time_event_source, "rtnl-timer"); if (r < 0) goto fail; return 0; fail: sd_netlink_detach_event(rtnl); return r; } int sd_netlink_detach_event(sd_netlink *rtnl) { assert_return(rtnl, -EINVAL); assert_return(rtnl->event, -ENXIO); rtnl->io_event_source = sd_event_source_unref(rtnl->io_event_source); rtnl->time_event_source = sd_event_source_unref(rtnl->time_event_source); rtnl->event = sd_event_unref(rtnl->event); return 0; } int sd_netlink_add_match(sd_netlink *rtnl, uint16_t type, sd_netlink_message_handler_t callback, void *userdata) { _cleanup_free_ struct match_callback *c = NULL; int r; assert_return(rtnl, -EINVAL); assert_return(callback, -EINVAL); assert_return(!rtnl_pid_changed(rtnl), -ECHILD); c = new0(struct match_callback, 1); if (!c) return -ENOMEM; c->callback = callback; c->type = type; c->userdata = userdata; switch (type) { case RTM_NEWLINK: case RTM_DELLINK: r = socket_broadcast_group_ref(rtnl, RTNLGRP_LINK); if (r < 0) return r; break; case RTM_NEWADDR: case RTM_DELADDR: r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_IFADDR); if (r < 0) return r; r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_IFADDR); if (r < 0) return r; break; case RTM_NEWROUTE: case RTM_DELROUTE: r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_ROUTE); if (r < 0) return r; r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_ROUTE); if (r < 0) return r; break; default: return -EOPNOTSUPP; } LIST_PREPEND(match_callbacks, rtnl->match_callbacks, c); c = NULL; return 0; } int sd_netlink_remove_match(sd_netlink *rtnl, uint16_t type, sd_netlink_message_handler_t callback, void *userdata) { struct match_callback *c; int r; assert_return(rtnl, -EINVAL); assert_return(callback, -EINVAL); assert_return(!rtnl_pid_changed(rtnl), -ECHILD); LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks) if (c->callback == callback && c->type == type && c->userdata == userdata) { LIST_REMOVE(match_callbacks, rtnl->match_callbacks, c); free(c); switch (type) { case RTM_NEWLINK: case RTM_DELLINK: r = socket_broadcast_group_unref(rtnl, RTNLGRP_LINK); if (r < 0) return r; break; case RTM_NEWADDR: case RTM_DELADDR: r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV4_IFADDR); if (r < 0) return r; r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV6_IFADDR); if (r < 0) return r; break; case RTM_NEWROUTE: case RTM_DELROUTE: r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV4_ROUTE); if (r < 0) return r; r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV6_ROUTE); if (r < 0) return r; break; default: return -EOPNOTSUPP; } return 1; } return 0; } systemd-229/src/libsystemd/sd-netlink/test-local-addresses.c000066400000000000000000000032711265713322000242700ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "af-list.h" #include "alloc-util.h" #include "in-addr-util.h" #include "local-addresses.h" static void print_local_addresses(struct local_address *a, unsigned n) { unsigned i; for (i = 0; i < n; i++) { _cleanup_free_ char *b = NULL; assert_se(in_addr_to_string(a[i].family, &a[i].address, &b) >= 0); printf("%s if%i scope=%i metric=%u address=%s\n", af_to_name(a[i].family), a[i].ifindex, a[i].scope, a[i].metric, b); } } int main(int argc, char *argv[]) { struct local_address *a; int n; a = NULL; n = local_addresses(NULL, 0, AF_UNSPEC, &a); assert_se(n >= 0); printf("Local Addresses:\n"); print_local_addresses(a, (unsigned) n); a = mfree(a); n = local_gateways(NULL, 0, AF_UNSPEC, &a); assert_se(n >= 0); printf("Local Gateways:\n"); print_local_addresses(a, (unsigned) n); free(a); return 0; } systemd-229/src/libsystemd/sd-netlink/test-netlink.c000066400000000000000000000374551265713322000227020ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-netlink.h" #include "ether-addr-util.h" #include "macro.h" #include "missing.h" #include "netlink-util.h" #include "socket-util.h" #include "string-util.h" #include "util.h" static void test_message_link_bridge(sd_netlink *rtnl) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; uint32_t cost; assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0); assert_se(sd_rtnl_message_link_set_family(message, PF_BRIDGE) >= 0); assert_se(sd_netlink_message_open_container(message, IFLA_PROTINFO) >= 0); assert_se(sd_netlink_message_append_u32(message, IFLA_BRPORT_COST, 10) >= 0); assert_se(sd_netlink_message_close_container(message) >= 0); assert_se(sd_netlink_message_rewind(message) >= 0); assert_se(sd_netlink_message_enter_container(message, IFLA_PROTINFO) >= 0); assert_se(sd_netlink_message_read_u32(message, IFLA_BRPORT_COST, &cost) >= 0); assert_se(cost == 10); assert_se(sd_netlink_message_exit_container(message) >= 0); } static void test_link_configure(sd_netlink *rtnl, int ifindex) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; const char *mac = "98:fe:94:3f:c6:18", *name = "test"; char buffer[ETHER_ADDR_TO_STRING_MAX]; unsigned int mtu = 1450, mtu_out; const char *name_out; struct ether_addr mac_out; /* we'd really like to test NEWLINK, but let's not mess with the running kernel */ assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0); assert_se(sd_netlink_message_append_string(message, IFLA_IFNAME, name) >= 0); assert_se(sd_netlink_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0); assert_se(sd_netlink_message_append_u32(message, IFLA_MTU, mtu) >= 0); assert_se(sd_netlink_call(rtnl, message, 0, NULL) == 1); assert_se(sd_netlink_message_rewind(message) >= 0); assert_se(sd_netlink_message_read_string(message, IFLA_IFNAME, &name_out) >= 0); assert_se(streq(name, name_out)); assert_se(sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &mac_out) >= 0); assert_se(streq(mac, ether_addr_to_string(&mac_out, buffer))); assert_se(sd_netlink_message_read_u32(message, IFLA_MTU, &mtu_out) >= 0); assert_se(mtu == mtu_out); } static void test_link_get(sd_netlink *rtnl, int ifindex) { sd_netlink_message *m; sd_netlink_message *r; unsigned int mtu = 1500; const char *str_data; uint8_t u8_data; uint32_t u32_data; struct ether_addr eth_data; assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); assert_se(m); /* u8 test cases */ assert_se(sd_netlink_message_append_u8(m, IFLA_CARRIER, 0) >= 0); assert_se(sd_netlink_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0); assert_se(sd_netlink_message_append_u8(m, IFLA_LINKMODE, 0) >= 0); /* u32 test cases */ assert_se(sd_netlink_message_append_u32(m, IFLA_MTU, mtu) >= 0); assert_se(sd_netlink_message_append_u32(m, IFLA_GROUP, 0) >= 0); assert_se(sd_netlink_message_append_u32(m, IFLA_TXQLEN, 0) >= 0); assert_se(sd_netlink_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0); assert_se(sd_netlink_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0); assert_se(sd_netlink_call(rtnl, m, -1, &r) == 1); assert_se(sd_netlink_message_read_string(r, IFLA_IFNAME, &str_data) == 0); assert_se(sd_netlink_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0); assert_se(sd_netlink_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0); assert_se(sd_netlink_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0); assert_se(sd_netlink_message_read_u32(r, IFLA_MTU, &u32_data) == 0); assert_se(sd_netlink_message_read_u32(r, IFLA_GROUP, &u32_data) == 0); assert_se(sd_netlink_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0); assert_se(sd_netlink_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0); assert_se(sd_netlink_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0); assert_se(sd_netlink_message_read_ether_addr(r, IFLA_ADDRESS, ð_data) == 0); assert_se((m = sd_netlink_message_unref(m)) == NULL); assert_se((r = sd_netlink_message_unref(r)) == NULL); } static void test_address_get(sd_netlink *rtnl, int ifindex) { sd_netlink_message *m; sd_netlink_message *r; struct in_addr in_data; struct ifa_cacheinfo cache; const char *label; assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0); assert_se(m); assert_se(sd_netlink_call(rtnl, m, -1, &r) == 1); assert_se(sd_netlink_message_read_in_addr(r, IFA_LOCAL, &in_data) == 0); assert_se(sd_netlink_message_read_in_addr(r, IFA_ADDRESS, &in_data) == 0); assert_se(sd_netlink_message_read_string(r, IFA_LABEL, &label) == 0); assert_se(sd_netlink_message_read_cache_info(r, IFA_CACHEINFO, &cache) == 0); assert_se((m = sd_netlink_message_unref(m)) == NULL); assert_se((r = sd_netlink_message_unref(r)) == NULL); } static void test_route(void) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req; struct in_addr addr, addr_data; uint32_t index = 2, u32_data; int r; r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC); if (r < 0) { log_error_errno(r, "Could not create RTM_NEWROUTE message: %m"); return; } addr.s_addr = htonl(INADDR_LOOPBACK); r = sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &addr); if (r < 0) { log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m"); return; } r = sd_netlink_message_append_u32(req, RTA_OIF, index); if (r < 0) { log_error_errno(r, "Could not append RTA_OIF attribute: %m"); return; } assert_se(sd_netlink_message_rewind(req) >= 0); assert_se(sd_netlink_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0); assert_se(addr_data.s_addr == addr.s_addr); assert_se(sd_netlink_message_read_u32(req, RTA_OIF, &u32_data) >= 0); assert_se(u32_data == index); assert_se((req = sd_netlink_message_unref(req)) == NULL); } static void test_multiple(void) { sd_netlink *rtnl1, *rtnl2; assert_se(sd_netlink_open(&rtnl1) >= 0); assert_se(sd_netlink_open(&rtnl2) >= 0); rtnl1 = sd_netlink_unref(rtnl1); rtnl2 = sd_netlink_unref(rtnl2); } static int link_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { char *ifname = userdata; const char *data; assert_se(rtnl); assert_se(m); log_info("got link info about %s", ifname); free(ifname); assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &data) >= 0); assert_se(streq(data, "lo")); return 1; } static void test_event_loop(int ifindex) { _cleanup_(sd_event_unrefp) sd_event *event = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; char *ifname; ifname = strdup("lo2"); assert_se(ifname); assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); assert_se(sd_netlink_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0); assert_se(sd_event_default(&event) >= 0); assert_se(sd_netlink_attach_event(rtnl, event, 0) >= 0); assert_se(sd_event_run(event, 0) >= 0); assert_se(sd_netlink_detach_event(rtnl) >= 0); assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); } static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { int *counter = userdata; int r; (*counter) --; r = sd_netlink_message_get_errno(m); log_info_errno(r, "%d left in pipe. got reply: %m", *counter); assert_se(r >= 0); return 1; } static void test_async(int ifindex) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL; uint32_t serial; char *ifname; ifname = strdup("lo"); assert_se(ifname); assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); assert_se(sd_netlink_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0); assert_se(sd_netlink_wait(rtnl, 0) >= 0); assert_se(sd_netlink_process(rtnl, &r) >= 0); assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); } static void test_pipe(int ifindex) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m1 = NULL, *m2 = NULL; int counter = 0; assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0); assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0); counter ++; assert_se(sd_netlink_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0); counter ++; assert_se(sd_netlink_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0); while (counter > 0) { assert_se(sd_netlink_wait(rtnl, 0) >= 0); assert_se(sd_netlink_process(rtnl, NULL) >= 0); } assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); } static void test_container(void) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; uint16_t u16_data; uint32_t u32_data; const char *string_data; assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0); assert_se(sd_netlink_message_open_container(m, IFLA_LINKINFO) >= 0); assert_se(sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "vlan") >= 0); assert_se(sd_netlink_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0); assert_se(sd_netlink_message_close_container(m) >= 0); assert_se(sd_netlink_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0); assert_se(sd_netlink_message_close_container(m) >= 0); assert_se(sd_netlink_message_close_container(m) == -EINVAL); assert_se(sd_netlink_message_rewind(m) >= 0); assert_se(sd_netlink_message_enter_container(m, IFLA_LINKINFO) >= 0); assert_se(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0); assert_se(streq("vlan", string_data)); assert_se(sd_netlink_message_enter_container(m, IFLA_INFO_DATA) >= 0); assert_se(sd_netlink_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0); assert_se(sd_netlink_message_exit_container(m) >= 0); assert_se(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0); assert_se(streq("vlan", string_data)); assert_se(sd_netlink_message_exit_container(m) >= 0); assert_se(sd_netlink_message_read_u32(m, IFLA_LINKINFO, &u32_data) < 0); assert_se(sd_netlink_message_exit_container(m) == -EINVAL); } static void test_match(void) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(sd_netlink_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0); assert_se(sd_netlink_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0); assert_se(sd_netlink_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1); assert_se(sd_netlink_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1); assert_se(sd_netlink_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0); assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); } static void test_get_addresses(sd_netlink *rtnl) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; sd_netlink_message *m; assert_se(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC) >= 0); assert_se(sd_netlink_call(rtnl, req, 0, &reply) >= 0); for (m = reply; m; m = sd_netlink_message_next(m)) { uint16_t type; unsigned char scope, flags; int family, ifindex; assert_se(sd_netlink_message_get_type(m, &type) >= 0); assert_se(type == RTM_NEWADDR); assert_se(sd_rtnl_message_addr_get_ifindex(m, &ifindex) >= 0); assert_se(sd_rtnl_message_addr_get_family(m, &family) >= 0); assert_se(sd_rtnl_message_addr_get_scope(m, &scope) >= 0); assert_se(sd_rtnl_message_addr_get_flags(m, &flags) >= 0); assert_se(ifindex > 0); assert_se(family == AF_INET || family == AF_INET6); log_info("got IPv%u address on ifindex %i", family == AF_INET ? 4: 6, ifindex); } } static void test_message(void) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; assert_se(rtnl_message_new_synthetic_error(-ETIMEDOUT, 1, &m) >= 0); assert_se(sd_netlink_message_get_errno(m) == -ETIMEDOUT); } int main(void) { sd_netlink *rtnl; sd_netlink_message *m; sd_netlink_message *r; const char *string_data; int if_loopback; uint16_t type; test_message(); test_match(); test_multiple(); test_route(); test_container(); assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(rtnl); if_loopback = (int) if_nametoindex("lo"); assert_se(if_loopback > 0); test_async(if_loopback); test_pipe(if_loopback); test_event_loop(if_loopback); test_link_configure(rtnl, if_loopback); test_get_addresses(rtnl); test_message_link_bridge(rtnl); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0); assert_se(m); assert_se(sd_netlink_message_get_type(m, &type) >= 0); assert_se(type == RTM_GETLINK); assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM); assert_se(sd_netlink_call(rtnl, m, 0, &r) == 1); assert_se(sd_netlink_message_get_type(r, &type) >= 0); assert_se(type == RTM_NEWLINK); assert_se((r = sd_netlink_message_unref(r)) == NULL); assert_se(sd_netlink_call(rtnl, m, -1, &r) == -EPERM); assert_se((m = sd_netlink_message_unref(m)) == NULL); assert_se((r = sd_netlink_message_unref(r)) == NULL); test_link_get(rtnl, if_loopback); test_address_get(rtnl, if_loopback); assert_se((m = sd_netlink_message_unref(m)) == NULL); assert_se((r = sd_netlink_message_unref(r)) == NULL); assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); return EXIT_SUCCESS; } systemd-229/src/libsystemd/sd-network/000077500000000000000000000000001265713322000201245ustar00rootroot00000000000000systemd-229/src/libsystemd/sd-network/Makefile000077700000000000000000000000001265713322000234322../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd/sd-network/network-util.c000066400000000000000000000022261265713322000227360ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "fd-util.h" #include "network-util.h" #include "strv.h" bool network_is_online(void) { _cleanup_free_ char *state = NULL; int r; r = sd_network_get_operational_state(&state); if (r < 0) /* if we don't know anything, we consider the system online */ return true; if (STR_IN_SET(state, "routable", "degraded")) return true; return false; } systemd-229/src/libsystemd/sd-network/network-util.h000066400000000000000000000014401265713322000227400ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Thomas Hindø Paabøl Andersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-network.h" bool network_is_online(void); systemd-229/src/libsystemd/sd-network/sd-network.c000066400000000000000000000235441265713322000223750ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-network.h" #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "macro.h" #include "parse-util.h" #include "string-util.h" #include "strv.h" #include "util.h" _public_ int sd_network_get_operational_state(char **state) { _cleanup_free_ char *s = NULL; int r; assert_return(state, -EINVAL); r = parse_env_file("/run/systemd/netif/state", NEWLINE, "OPER_STATE", &s, NULL); if (r == -ENOENT) return -ENODATA; if (r < 0) return r; if (isempty(s)) return -ENODATA; *state = s; s = NULL; return 0; } static int network_get_strv(const char *key, char ***ret) { _cleanup_strv_free_ char **a = NULL; _cleanup_free_ char *s = NULL; int r; assert_return(ret, -EINVAL); r = parse_env_file("/run/systemd/netif/state", NEWLINE, key, &s, NULL); if (r == -ENOENT) return -ENODATA; if (r < 0) return r; if (isempty(s)) { *ret = NULL; return 0; } a = strv_split(s, " "); if (!a) return -ENOMEM; strv_uniq(a); r = strv_length(a); *ret = a; a = NULL; return r; } _public_ int sd_network_get_dns(char ***ret) { return network_get_strv("DNS", ret); } _public_ int sd_network_get_ntp(char ***ret) { return network_get_strv("NTP", ret); } _public_ int sd_network_get_search_domains(char ***ret) { return network_get_strv("DOMAINS", ret); } _public_ int sd_network_get_route_domains(char ***ret) { return network_get_strv("ROUTE_DOMAINS", ret); } static int network_link_get_string(int ifindex, const char *field, char **ret) { _cleanup_free_ char *s = NULL, *p = NULL; int r; assert_return(ifindex > 0, -EINVAL); assert_return(ret, -EINVAL); if (asprintf(&p, "/run/systemd/netif/links/%i", ifindex) < 0) return -ENOMEM; r = parse_env_file(p, NEWLINE, field, &s, NULL); if (r == -ENOENT) return -ENODATA; if (r < 0) return r; if (isempty(s)) return -ENODATA; *ret = s; s = NULL; return 0; } static int network_link_get_strv(int ifindex, const char *key, char ***ret) { _cleanup_free_ char *p = NULL, *s = NULL; _cleanup_strv_free_ char **a = NULL; int r; assert_return(ifindex > 0, -EINVAL); assert_return(ret, -EINVAL); if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) return -ENOMEM; r = parse_env_file(p, NEWLINE, key, &s, NULL); if (r == -ENOENT) return -ENODATA; if (r < 0) return r; if (isempty(s)) { *ret = NULL; return 0; } a = strv_split(s, " "); if (!a) return -ENOMEM; strv_uniq(a); r = strv_length(a); *ret = a; a = NULL; return r; } _public_ int sd_network_link_get_setup_state(int ifindex, char **state) { return network_link_get_string(ifindex, "ADMIN_STATE", state); } _public_ int sd_network_link_get_network_file(int ifindex, char **filename) { return network_link_get_string(ifindex, "NETWORK_FILE", filename); } _public_ int sd_network_link_get_operational_state(int ifindex, char **state) { return network_link_get_string(ifindex, "OPER_STATE", state); } _public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) { return network_link_get_string(ifindex, "LLMNR", llmnr); } _public_ int sd_network_link_get_mdns(int ifindex, char **mdns) { return network_link_get_string(ifindex, "MDNS", mdns); } _public_ int sd_network_link_get_dnssec(int ifindex, char **dnssec) { return network_link_get_string(ifindex, "DNSSEC", dnssec); } _public_ int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta) { return network_link_get_strv(ifindex, "DNSSEC_NTA", nta); } _public_ int sd_network_link_get_lldp(int ifindex, char **lldp) { _cleanup_free_ char *s = NULL, *p = NULL; size_t size; int r; assert_return(ifindex > 0, -EINVAL); assert_return(lldp, -EINVAL); if (asprintf(&p, "/run/systemd/netif/lldp/%d", ifindex) < 0) return -ENOMEM; r = read_full_file(p, &s, &size); if (r == -ENOENT) return -ENODATA; if (r < 0) return r; if (size <= 0) return -ENODATA; *lldp = s; s = NULL; return 0; } int sd_network_link_get_timezone(int ifindex, char **ret) { return network_link_get_string(ifindex, "TIMEZONE", ret); } _public_ int sd_network_link_get_dns(int ifindex, char ***ret) { return network_link_get_strv(ifindex, "DNS", ret); } _public_ int sd_network_link_get_ntp(int ifindex, char ***ret) { return network_link_get_strv(ifindex, "NTP", ret); } _public_ int sd_network_link_get_search_domains(int ifindex, char ***ret) { return network_link_get_strv(ifindex, "DOMAINS", ret); } _public_ int sd_network_link_get_route_domains(int ifindex, char ***ret) { return network_link_get_strv(ifindex, "ROUTE_DOMAINS", ret); } _public_ int sd_network_link_get_carrier_bound_to(int ifindex, char ***ret) { return network_link_get_strv(ifindex, "CARRIER_BOUND_TO", ret); } _public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) { return network_link_get_strv(ifindex, "CARRIER_BOUND_BY", ret); } static inline int MONITOR_TO_FD(sd_network_monitor *m) { return (int) (unsigned long) m - 1; } static inline sd_network_monitor* FD_TO_MONITOR(int fd) { return (sd_network_monitor*) (unsigned long) (fd + 1); } static int monitor_add_inotify_watch(int fd) { int k; k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE); if (k >= 0) return 0; else if (errno != ENOENT) return -errno; k = inotify_add_watch(fd, "/run/systemd/netif/", IN_CREATE|IN_ISDIR); if (k >= 0) return 0; else if (errno != ENOENT) return -errno; k = inotify_add_watch(fd, "/run/systemd/", IN_CREATE|IN_ISDIR); if (k < 0) return -errno; return 0; } _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) { _cleanup_close_ int fd = -1; int k; bool good = false; assert_return(m, -EINVAL); fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (fd < 0) return -errno; if (!category || streq(category, "links")) { k = monitor_add_inotify_watch(fd); if (k < 0) return k; good = true; } if (!good) return -EINVAL; *m = FD_TO_MONITOR(fd); fd = -1; return 0; } _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) { int fd; if (m) { fd = MONITOR_TO_FD(m); close_nointr(fd); } return NULL; } _public_ int sd_network_monitor_flush(sd_network_monitor *m) { union inotify_event_buffer buffer; struct inotify_event *e; ssize_t l; int fd, k; assert_return(m, -EINVAL); fd = MONITOR_TO_FD(m); l = read(fd, &buffer, sizeof(buffer)); if (l < 0) { if (errno == EAGAIN || errno == EINTR) return 0; return -errno; } FOREACH_INOTIFY_EVENT(e, buffer, l) { if (e->mask & IN_ISDIR) { k = monitor_add_inotify_watch(fd); if (k < 0) return k; k = inotify_rm_watch(fd, e->wd); if (k < 0) return -errno; } } return 0; } _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) { assert_return(m, -EINVAL); return MONITOR_TO_FD(m); } _public_ int sd_network_monitor_get_events(sd_network_monitor *m) { assert_return(m, -EINVAL); /* For now we will only return POLLIN here, since we don't * need anything else ever for inotify. However, let's have * this API to keep our options open should we later on need * it. */ return POLLIN; } _public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) { assert_return(m, -EINVAL); assert_return(timeout_usec, -EINVAL); /* For now we will only return (uint64_t) -1, since we don't * need any timeout. However, let's have this API to keep our * options open should we later on need it. */ *timeout_usec = (uint64_t) -1; return 0; } systemd-229/src/libsystemd/sd-path/000077500000000000000000000000001265713322000173675ustar00rootroot00000000000000systemd-229/src/libsystemd/sd-path/Makefile000077700000000000000000000000001265713322000226752../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd/sd-path/sd-path.c000066400000000000000000000444131265713322000211010ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-path.h" #include "alloc-util.h" #include "architecture.h" #include "fd-util.h" #include "fileio.h" #include "missing.h" #include "path-util.h" #include "string-util.h" #include "strv.h" #include "user-util.h" #include "util.h" static int from_environment(const char *envname, const char *fallback, const char **ret) { assert(ret); if (envname) { const char *e; e = secure_getenv(envname); if (e && path_is_absolute(e)) { *ret = e; return 0; } } if (fallback) { *ret = fallback; return 0; } return -ENXIO; } static int from_home_dir(const char *envname, const char *suffix, char **buffer, const char **ret) { _cleanup_free_ char *h = NULL; char *cc = NULL; int r; assert(suffix); assert(buffer); assert(ret); if (envname) { const char *e = NULL; e = secure_getenv(envname); if (e && path_is_absolute(e)) { *ret = e; return 0; } } r = get_home_dir(&h); if (r < 0) return r; if (endswith(h, "/")) cc = strappend(h, suffix); else cc = strjoin(h, "/", suffix, NULL); if (!cc) return -ENOMEM; *buffer = cc; *ret = cc; return 0; } static int from_user_dir(const char *field, char **buffer, const char **ret) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *b = NULL; const char *fn = NULL; char line[LINE_MAX]; size_t n; int r; assert(field); assert(buffer); assert(ret); r = from_home_dir(NULL, ".config/user-dirs.dirs", &b, &fn); if (r < 0) return r; f = fopen(fn, "re"); if (!f) { if (errno == ENOENT) goto fallback; return -errno; } /* This is an awful parse, but it follows closely what * xdg-user-dirs does upstream */ n = strlen(field); FOREACH_LINE(line, f, return -errno) { char *l, *p, *e; l = strstrip(line); if (!strneq(l, field, n)) continue; p = l + n; p += strspn(p, WHITESPACE); if (*p != '=') continue; p++; p += strspn(p, WHITESPACE); if (*p != '"') continue; p++; e = strrchr(p, '"'); if (!e) continue; *e = 0; /* Three syntaxes permitted: relative to $HOME, $HOME itself, and absolute path */ if (startswith(p, "$HOME/")) { _cleanup_free_ char *h = NULL; char *cc; r = get_home_dir(&h); if (r < 0) return r; cc = strappend(h, p+5); if (!cc) return -ENOMEM; *buffer = cc; *ret = cc; return 0; } else if (streq(p, "$HOME")) { r = get_home_dir(buffer); if (r < 0) return r; *ret = *buffer; return 0; } else if (path_is_absolute(p)) { char *copy; copy = strdup(p); if (!copy) return -ENOMEM; *buffer = copy; *ret = copy; return 0; } } fallback: /* The desktop directory defaults to $HOME/Desktop, the others to $HOME */ if (streq(field, "XDG_DESKTOP_DIR")) { _cleanup_free_ char *h = NULL; char *cc; r = get_home_dir(&h); if (r < 0) return r; cc = strappend(h, "/Desktop"); if (!cc) return -ENOMEM; *buffer = cc; *ret = cc; } else { r = get_home_dir(buffer); if (r < 0) return r; *ret = *buffer; } return 0; } static int get_path(uint64_t type, char **buffer, const char **ret) { int r; assert(buffer); assert(ret); switch (type) { case SD_PATH_TEMPORARY: return from_environment("TMPDIR", "/tmp", ret); case SD_PATH_TEMPORARY_LARGE: return from_environment("TMPDIR", "/var/tmp", ret); case SD_PATH_SYSTEM_BINARIES: *ret = "/usr/bin"; return 0; case SD_PATH_SYSTEM_INCLUDE: *ret = "/usr/include"; return 0; case SD_PATH_SYSTEM_LIBRARY_PRIVATE: *ret = "/usr/lib"; return 0; case SD_PATH_SYSTEM_LIBRARY_ARCH: *ret = LIBDIR; return 0; case SD_PATH_SYSTEM_SHARED: *ret = "/usr/share"; return 0; case SD_PATH_SYSTEM_CONFIGURATION_FACTORY: *ret = "/usr/share/factory/etc"; return 0; case SD_PATH_SYSTEM_STATE_FACTORY: *ret = "/usr/share/factory/var"; return 0; case SD_PATH_SYSTEM_CONFIGURATION: *ret = "/etc"; return 0; case SD_PATH_SYSTEM_RUNTIME: *ret = "/run"; return 0; case SD_PATH_SYSTEM_RUNTIME_LOGS: *ret = "/run/log"; return 0; case SD_PATH_SYSTEM_STATE_PRIVATE: *ret = "/var/lib"; return 0; case SD_PATH_SYSTEM_STATE_LOGS: *ret = "/var/log"; return 0; case SD_PATH_SYSTEM_STATE_CACHE: *ret = "/var/cache"; return 0; case SD_PATH_SYSTEM_STATE_SPOOL: *ret = "/var/spool"; return 0; case SD_PATH_USER_BINARIES: return from_home_dir(NULL, ".local/bin", buffer, ret); case SD_PATH_USER_LIBRARY_PRIVATE: return from_home_dir(NULL, ".local/lib", buffer, ret); case SD_PATH_USER_LIBRARY_ARCH: return from_home_dir(NULL, ".local/lib/" LIB_ARCH_TUPLE, buffer, ret); case SD_PATH_USER_SHARED: return from_home_dir("XDG_DATA_HOME", ".local/share", buffer, ret); case SD_PATH_USER_CONFIGURATION: return from_home_dir("XDG_CONFIG_HOME", ".config", buffer, ret); case SD_PATH_USER_RUNTIME: return from_environment("XDG_RUNTIME_DIR", NULL, ret); case SD_PATH_USER_STATE_CACHE: return from_home_dir("XDG_CACHE_HOME", ".cache", buffer, ret); case SD_PATH_USER: r = get_home_dir(buffer); if (r < 0) return r; *ret = *buffer; return 0; case SD_PATH_USER_DOCUMENTS: return from_user_dir("XDG_DOCUMENTS_DIR", buffer, ret); case SD_PATH_USER_MUSIC: return from_user_dir("XDG_MUSIC_DIR", buffer, ret); case SD_PATH_USER_PICTURES: return from_user_dir("XDG_PICTURES_DIR", buffer, ret); case SD_PATH_USER_VIDEOS: return from_user_dir("XDG_VIDEOS_DIR", buffer, ret); case SD_PATH_USER_DOWNLOAD: return from_user_dir("XDG_DOWNLOAD_DIR", buffer, ret); case SD_PATH_USER_PUBLIC: return from_user_dir("XDG_PUBLICSHARE_DIR", buffer, ret); case SD_PATH_USER_TEMPLATES: return from_user_dir("XDG_TEMPLATES_DIR", buffer, ret); case SD_PATH_USER_DESKTOP: return from_user_dir("XDG_DESKTOP_DIR", buffer, ret); } return -EOPNOTSUPP; } _public_ int sd_path_home(uint64_t type, const char *suffix, char **path) { char *buffer = NULL, *cc; const char *ret; int r; assert_return(path, -EINVAL); if (IN_SET(type, SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION)) { _cleanup_strv_free_ char **l = NULL; r = sd_path_search(type, suffix, &l); if (r < 0) return r; buffer = strv_join(l, ":"); if (!buffer) return -ENOMEM; *path = buffer; return 0; } r = get_path(type, &buffer, &ret); if (r < 0) return r; if (!suffix) { if (!buffer) { buffer = strdup(ret); if (!buffer) return -ENOMEM; } *path = buffer; return 0; } suffix += strspn(suffix, "/"); if (endswith(ret, "/")) cc = strappend(ret, suffix); else cc = strjoin(ret, "/", suffix, NULL); free(buffer); if (!cc) return -ENOMEM; *path = cc; return 0; } static int search_from_environment( char ***list, const char *env_home, const char *home_suffix, const char *env_search, bool env_search_sufficient, const char *first, ...) { const char *e; char *h = NULL; char **l = NULL; int r; assert(list); if (env_search) { e = secure_getenv(env_search); if (e) { l = strv_split(e, ":"); if (!l) return -ENOMEM; if (env_search_sufficient) { *list = l; return 0; } } } if (!l && first) { va_list ap; va_start(ap, first); l = strv_new_ap(first, ap); va_end(ap); if (!l) return -ENOMEM; } if (env_home) { e = secure_getenv(env_home); if (e && path_is_absolute(e)) { h = strdup(e); if (!h) { strv_free(l); return -ENOMEM; } } } if (!h && home_suffix) { e = secure_getenv("HOME"); if (e && path_is_absolute(e)) { if (endswith(e, "/")) h = strappend(e, home_suffix); else h = strjoin(e, "/", home_suffix, NULL); if (!h) { strv_free(l); return -ENOMEM; } } } if (h) { r = strv_consume_prepend(&l, h); if (r < 0) { strv_free(l); return -ENOMEM; } } *list = l; return 0; } static int get_search(uint64_t type, char ***list) { assert(list); switch(type) { case SD_PATH_SEARCH_BINARIES: return search_from_environment(list, NULL, ".local/bin", "PATH", true, "/usr/local/sbin", "/usr/local/bin", "/usr/sbin", "/usr/bin", #ifdef HAVE_SPLIT_USR "/sbin", "/bin", #endif NULL); case SD_PATH_SEARCH_LIBRARY_PRIVATE: return search_from_environment(list, NULL, ".local/lib", NULL, false, "/usr/local/lib", "/usr/lib", #ifdef HAVE_SPLIT_USR "/lib", #endif NULL); case SD_PATH_SEARCH_LIBRARY_ARCH: return search_from_environment(list, NULL, ".local/lib/" LIB_ARCH_TUPLE, "LD_LIBRARY_PATH", true, LIBDIR, #ifdef HAVE_SPLIT_USR ROOTLIBDIR, #endif NULL); case SD_PATH_SEARCH_SHARED: return search_from_environment(list, "XDG_DATA_HOME", ".local/share", "XDG_DATA_DIRS", false, "/usr/local/share", "/usr/share", NULL); case SD_PATH_SEARCH_CONFIGURATION_FACTORY: return search_from_environment(list, NULL, NULL, NULL, false, "/usr/local/share/factory/etc", "/usr/share/factory/etc", NULL); case SD_PATH_SEARCH_STATE_FACTORY: return search_from_environment(list, NULL, NULL, NULL, false, "/usr/local/share/factory/var", "/usr/share/factory/var", NULL); case SD_PATH_SEARCH_CONFIGURATION: return search_from_environment(list, "XDG_CONFIG_HOME", ".config", "XDG_CONFIG_DIRS", false, "/etc", NULL); } return -EOPNOTSUPP; } _public_ int sd_path_search(uint64_t type, const char *suffix, char ***paths) { char **l, **i, **j, **n; int r; assert_return(paths, -EINVAL); if (!IN_SET(type, SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION)) { char *p; r = sd_path_home(type, suffix, &p); if (r < 0) return r; l = new(char*, 2); if (!l) { free(p); return -ENOMEM; } l[0] = p; l[1] = NULL; *paths = l; return 0; } r = get_search(type, &l); if (r < 0) return r; if (!suffix) { *paths = l; return 0; } n = new(char*, strv_length(l)+1); if (!n) { strv_free(l); return -ENOMEM; } j = n; STRV_FOREACH(i, l) { if (endswith(*i, "/")) *j = strappend(*i, suffix); else *j = strjoin(*i, "/", suffix, NULL); if (!*j) { strv_free(l); strv_free(n); return -ENOMEM; } j++; } *j = NULL; *paths = n; return 0; } systemd-229/src/libsystemd/sd-resolve/000077500000000000000000000000001265713322000201125ustar00rootroot00000000000000systemd-229/src/libsystemd/sd-resolve/Makefile000077700000000000000000000000001265713322000236332../../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd/sd-resolve/sd-resolve.c000066400000000000000000001036041265713322000223450ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2005-2008 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include "sd-resolve.h" #include "alloc-util.h" #include "fd-util.h" #include "io-util.h" #include "list.h" #include "missing.h" #include "socket-util.h" #include "util.h" #define WORKERS_MIN 1U #define WORKERS_MAX 16U #define QUERIES_MAX 256U #define BUFSIZE 10240U typedef enum { REQUEST_ADDRINFO, RESPONSE_ADDRINFO, REQUEST_NAMEINFO, RESPONSE_NAMEINFO, REQUEST_TERMINATE, RESPONSE_DIED } QueryType; enum { REQUEST_RECV_FD, REQUEST_SEND_FD, RESPONSE_RECV_FD, RESPONSE_SEND_FD, _FD_MAX }; struct sd_resolve { unsigned n_ref; bool dead:1; pid_t original_pid; int fds[_FD_MAX]; pthread_t workers[WORKERS_MAX]; unsigned n_valid_workers; unsigned current_id; sd_resolve_query* query_array[QUERIES_MAX]; unsigned n_queries, n_done, n_outstanding; sd_event_source *event_source; sd_event *event; sd_resolve_query *current; sd_resolve **default_resolve_ptr; pid_t tid; LIST_HEAD(sd_resolve_query, queries); }; struct sd_resolve_query { unsigned n_ref; sd_resolve *resolve; QueryType type:4; bool done:1; bool floating:1; unsigned id; int ret; int _errno; int _h_errno; struct addrinfo *addrinfo; char *serv, *host; union { sd_resolve_getaddrinfo_handler_t getaddrinfo_handler; sd_resolve_getnameinfo_handler_t getnameinfo_handler; }; void *userdata; LIST_FIELDS(sd_resolve_query, queries); }; typedef struct RHeader { QueryType type; unsigned id; size_t length; } RHeader; typedef struct AddrInfoRequest { struct RHeader header; bool hints_valid; int ai_flags; int ai_family; int ai_socktype; int ai_protocol; size_t node_len, service_len; } AddrInfoRequest; typedef struct AddrInfoResponse { struct RHeader header; int ret; int _errno; int _h_errno; /* followed by addrinfo_serialization[] */ } AddrInfoResponse; typedef struct AddrInfoSerialization { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; size_t canonname_len; /* Followed by ai_addr amd ai_canonname with variable lengths */ } AddrInfoSerialization; typedef struct NameInfoRequest { struct RHeader header; int flags; socklen_t sockaddr_len; bool gethost:1, getserv:1; } NameInfoRequest; typedef struct NameInfoResponse { struct RHeader header; size_t hostlen, servlen; int ret; int _errno; int _h_errno; } NameInfoResponse; typedef union Packet { RHeader rheader; AddrInfoRequest addrinfo_request; AddrInfoResponse addrinfo_response; NameInfoRequest nameinfo_request; NameInfoResponse nameinfo_response; } Packet; static int getaddrinfo_done(sd_resolve_query* q); static int getnameinfo_done(sd_resolve_query *q); static void resolve_query_disconnect(sd_resolve_query *q); #define RESOLVE_DONT_DESTROY(resolve) \ _cleanup_(sd_resolve_unrefp) _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve) static int send_died(int out_fd) { RHeader rh = { .type = RESPONSE_DIED, .length = sizeof(RHeader), }; assert(out_fd >= 0); if (send(out_fd, &rh, rh.length, MSG_NOSIGNAL) < 0) return -errno; return 0; } static void *serialize_addrinfo(void *p, const struct addrinfo *ai, size_t *length, size_t maxlength) { AddrInfoSerialization s; size_t cnl, l; assert(p); assert(ai); assert(length); assert(*length <= maxlength); cnl = ai->ai_canonname ? strlen(ai->ai_canonname)+1 : 0; l = sizeof(AddrInfoSerialization) + ai->ai_addrlen + cnl; if (*length + l > maxlength) return NULL; s.ai_flags = ai->ai_flags; s.ai_family = ai->ai_family; s.ai_socktype = ai->ai_socktype; s.ai_protocol = ai->ai_protocol; s.ai_addrlen = ai->ai_addrlen; s.canonname_len = cnl; memcpy((uint8_t*) p, &s, sizeof(AddrInfoSerialization)); memcpy((uint8_t*) p + sizeof(AddrInfoSerialization), ai->ai_addr, ai->ai_addrlen); if (ai->ai_canonname) memcpy((char*) p + sizeof(AddrInfoSerialization) + ai->ai_addrlen, ai->ai_canonname, cnl); *length += l; return (uint8_t*) p + l; } static int send_addrinfo_reply( int out_fd, unsigned id, int ret, struct addrinfo *ai, int _errno, int _h_errno) { AddrInfoResponse resp = { .header.type = RESPONSE_ADDRINFO, .header.id = id, .header.length = sizeof(AddrInfoResponse), .ret = ret, ._errno = _errno, ._h_errno = _h_errno, }; struct msghdr mh = {}; struct iovec iov[2]; union { AddrInfoSerialization ais; uint8_t space[BUFSIZE]; } buffer; assert(out_fd >= 0); if (ret == 0 && ai) { void *p = &buffer; struct addrinfo *k; for (k = ai; k; k = k->ai_next) { p = serialize_addrinfo(p, k, &resp.header.length, (uint8_t*) &buffer + BUFSIZE - (uint8_t*) p); if (!p) { freeaddrinfo(ai); return -ENOBUFS; } } } if (ai) freeaddrinfo(ai); iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(AddrInfoResponse) }; iov[1] = (struct iovec) { .iov_base = &buffer, .iov_len = resp.header.length - sizeof(AddrInfoResponse) }; mh.msg_iov = iov; mh.msg_iovlen = ELEMENTSOF(iov); if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0) return -errno; return 0; } static int send_nameinfo_reply( int out_fd, unsigned id, int ret, const char *host, const char *serv, int _errno, int _h_errno) { NameInfoResponse resp = { .header.type = RESPONSE_NAMEINFO, .header.id = id, .ret = ret, ._errno = _errno, ._h_errno = _h_errno, }; struct msghdr mh = {}; struct iovec iov[3]; size_t hl, sl; assert(out_fd >= 0); sl = serv ? strlen(serv)+1 : 0; hl = host ? strlen(host)+1 : 0; resp.header.length = sizeof(NameInfoResponse) + hl + sl; resp.hostlen = hl; resp.servlen = sl; iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(NameInfoResponse) }; iov[1] = (struct iovec) { .iov_base = (void*) host, .iov_len = hl }; iov[2] = (struct iovec) { .iov_base = (void*) serv, .iov_len = sl }; mh.msg_iov = iov; mh.msg_iovlen = ELEMENTSOF(iov); if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0) return -errno; return 0; } static int handle_request(int out_fd, const Packet *packet, size_t length) { const RHeader *req; assert(out_fd >= 0); assert(packet); req = &packet->rheader; assert(length >= sizeof(RHeader)); assert(length == req->length); switch (req->type) { case REQUEST_ADDRINFO: { const AddrInfoRequest *ai_req = &packet->addrinfo_request; struct addrinfo hints = {}, *result = NULL; const char *node, *service; int ret; assert(length >= sizeof(AddrInfoRequest)); assert(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len); hints.ai_flags = ai_req->ai_flags; hints.ai_family = ai_req->ai_family; hints.ai_socktype = ai_req->ai_socktype; hints.ai_protocol = ai_req->ai_protocol; node = ai_req->node_len ? (const char*) ai_req + sizeof(AddrInfoRequest) : NULL; service = ai_req->service_len ? (const char*) ai_req + sizeof(AddrInfoRequest) + ai_req->node_len : NULL; ret = getaddrinfo( node, service, ai_req->hints_valid ? &hints : NULL, &result); /* send_addrinfo_reply() frees result */ return send_addrinfo_reply(out_fd, req->id, ret, result, errno, h_errno); } case REQUEST_NAMEINFO: { const NameInfoRequest *ni_req = &packet->nameinfo_request; char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV]; union sockaddr_union sa; int ret; assert(length >= sizeof(NameInfoRequest)); assert(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len); assert(sizeof(sa) >= ni_req->sockaddr_len); memcpy(&sa, (const uint8_t *) ni_req + sizeof(NameInfoRequest), ni_req->sockaddr_len); ret = getnameinfo(&sa.sa, ni_req->sockaddr_len, ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0, ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0, ni_req->flags); return send_nameinfo_reply(out_fd, req->id, ret, ret == 0 && ni_req->gethost ? hostbuf : NULL, ret == 0 && ni_req->getserv ? servbuf : NULL, errno, h_errno); } case REQUEST_TERMINATE: /* Quit */ return -ECONNRESET; default: assert_not_reached("Unknown request"); } return 0; } static void* thread_worker(void *p) { sd_resolve *resolve = p; sigset_t fullset; /* No signals in this thread please */ assert_se(sigfillset(&fullset) == 0); assert_se(pthread_sigmask(SIG_BLOCK, &fullset, NULL) == 0); /* Assign a pretty name to this thread */ prctl(PR_SET_NAME, (unsigned long) "sd-resolve"); while (!resolve->dead) { union { Packet packet; uint8_t space[BUFSIZE]; } buf; ssize_t length; length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof(buf), 0); if (length < 0) { if (errno == EINTR) continue; break; } if (length == 0) break; if (resolve->dead) break; if (handle_request(resolve->fds[RESPONSE_SEND_FD], &buf.packet, (size_t) length) < 0) break; } send_died(resolve->fds[RESPONSE_SEND_FD]); return NULL; } static int start_threads(sd_resolve *resolve, unsigned extra) { unsigned n; int r; n = resolve->n_outstanding + extra; n = CLAMP(n, WORKERS_MIN, WORKERS_MAX); while (resolve->n_valid_workers < n) { r = pthread_create(&resolve->workers[resolve->n_valid_workers], NULL, thread_worker, resolve); if (r != 0) return -r; resolve->n_valid_workers ++; } return 0; } static bool resolve_pid_changed(sd_resolve *r) { assert(r); /* We don't support people creating a resolver and keeping it * around after fork(). Let's complain. */ return r->original_pid != getpid(); } _public_ int sd_resolve_new(sd_resolve **ret) { sd_resolve *resolve = NULL; int i, r; assert_return(ret, -EINVAL); resolve = new0(sd_resolve, 1); if (!resolve) return -ENOMEM; resolve->n_ref = 1; resolve->original_pid = getpid(); for (i = 0; i < _FD_MAX; i++) resolve->fds[i] = -1; r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD); if (r < 0) { r = -errno; goto fail; } r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD); if (r < 0) { r = -errno; goto fail; } fd_inc_sndbuf(resolve->fds[REQUEST_SEND_FD], QUERIES_MAX * BUFSIZE); fd_inc_rcvbuf(resolve->fds[REQUEST_RECV_FD], QUERIES_MAX * BUFSIZE); fd_inc_sndbuf(resolve->fds[RESPONSE_SEND_FD], QUERIES_MAX * BUFSIZE); fd_inc_rcvbuf(resolve->fds[RESPONSE_RECV_FD], QUERIES_MAX * BUFSIZE); fd_nonblock(resolve->fds[RESPONSE_RECV_FD], true); *ret = resolve; return 0; fail: sd_resolve_unref(resolve); return r; } _public_ int sd_resolve_default(sd_resolve **ret) { static thread_local sd_resolve *default_resolve = NULL; sd_resolve *e = NULL; int r; if (!ret) return !!default_resolve; if (default_resolve) { *ret = sd_resolve_ref(default_resolve); return 0; } r = sd_resolve_new(&e); if (r < 0) return r; e->default_resolve_ptr = &default_resolve; e->tid = gettid(); default_resolve = e; *ret = e; return 1; } _public_ int sd_resolve_get_tid(sd_resolve *resolve, pid_t *tid) { assert_return(resolve, -EINVAL); assert_return(tid, -EINVAL); assert_return(!resolve_pid_changed(resolve), -ECHILD); if (resolve->tid != 0) { *tid = resolve->tid; return 0; } if (resolve->event) return sd_event_get_tid(resolve->event, tid); return -ENXIO; } static void resolve_free(sd_resolve *resolve) { PROTECT_ERRNO; sd_resolve_query *q; unsigned i; assert(resolve); while ((q = resolve->queries)) { assert(q->floating); resolve_query_disconnect(q); sd_resolve_query_unref(q); } if (resolve->default_resolve_ptr) *(resolve->default_resolve_ptr) = NULL; resolve->dead = true; sd_resolve_detach_event(resolve); if (resolve->fds[REQUEST_SEND_FD] >= 0) { RHeader req = { .type = REQUEST_TERMINATE, .length = sizeof(req) }; /* Send one termination packet for each worker */ for (i = 0; i < resolve->n_valid_workers; i++) (void) send(resolve->fds[REQUEST_SEND_FD], &req, req.length, MSG_NOSIGNAL); } /* Now terminate them and wait until they are gone. */ for (i = 0; i < resolve->n_valid_workers; i++) pthread_join(resolve->workers[i], NULL); /* Close all communication channels */ for (i = 0; i < _FD_MAX; i++) safe_close(resolve->fds[i]); free(resolve); } _public_ sd_resolve* sd_resolve_ref(sd_resolve *resolve) { assert_return(resolve, NULL); assert(resolve->n_ref >= 1); resolve->n_ref++; return resolve; } _public_ sd_resolve* sd_resolve_unref(sd_resolve *resolve) { if (!resolve) return NULL; assert(resolve->n_ref >= 1); resolve->n_ref--; if (resolve->n_ref <= 0) resolve_free(resolve); return NULL; } _public_ int sd_resolve_get_fd(sd_resolve *resolve) { assert_return(resolve, -EINVAL); assert_return(!resolve_pid_changed(resolve), -ECHILD); return resolve->fds[RESPONSE_RECV_FD]; } _public_ int sd_resolve_get_events(sd_resolve *resolve) { assert_return(resolve, -EINVAL); assert_return(!resolve_pid_changed(resolve), -ECHILD); return resolve->n_queries > resolve->n_done ? POLLIN : 0; } _public_ int sd_resolve_get_timeout(sd_resolve *resolve, uint64_t *usec) { assert_return(resolve, -EINVAL); assert_return(usec, -EINVAL); assert_return(!resolve_pid_changed(resolve), -ECHILD); *usec = (uint64_t) -1; return 0; } static sd_resolve_query *lookup_query(sd_resolve *resolve, unsigned id) { sd_resolve_query *q; assert(resolve); q = resolve->query_array[id % QUERIES_MAX]; if (q) if (q->id == id) return q; return NULL; } static int complete_query(sd_resolve *resolve, sd_resolve_query *q) { int r; assert(q); assert(!q->done); assert(q->resolve == resolve); q->done = true; resolve->n_done ++; resolve->current = sd_resolve_query_ref(q); switch (q->type) { case REQUEST_ADDRINFO: r = getaddrinfo_done(q); break; case REQUEST_NAMEINFO: r = getnameinfo_done(q); break; default: assert_not_reached("Cannot complete unknown query type"); } resolve->current = NULL; if (q->floating) { resolve_query_disconnect(q); sd_resolve_query_unref(q); } sd_resolve_query_unref(q); return r; } static int unserialize_addrinfo(const void **p, size_t *length, struct addrinfo **ret_ai) { AddrInfoSerialization s; size_t l; struct addrinfo *ai; assert(p); assert(*p); assert(ret_ai); assert(length); if (*length < sizeof(AddrInfoSerialization)) return -EBADMSG; memcpy(&s, *p, sizeof(s)); l = sizeof(AddrInfoSerialization) + s.ai_addrlen + s.canonname_len; if (*length < l) return -EBADMSG; ai = new0(struct addrinfo, 1); if (!ai) return -ENOMEM; ai->ai_flags = s.ai_flags; ai->ai_family = s.ai_family; ai->ai_socktype = s.ai_socktype; ai->ai_protocol = s.ai_protocol; ai->ai_addrlen = s.ai_addrlen; if (s.ai_addrlen > 0) { ai->ai_addr = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization), s.ai_addrlen); if (!ai->ai_addr) { free(ai); return -ENOMEM; } } if (s.canonname_len > 0) { ai->ai_canonname = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization) + s.ai_addrlen, s.canonname_len); if (!ai->ai_canonname) { free(ai->ai_addr); free(ai); return -ENOMEM; } } *length -= l; *ret_ai = ai; *p = ((const uint8_t*) *p) + l; return 0; } static int handle_response(sd_resolve *resolve, const Packet *packet, size_t length) { const RHeader *resp; sd_resolve_query *q; int r; assert(resolve); resp = &packet->rheader; assert(resp); assert(length >= sizeof(RHeader)); assert(length == resp->length); if (resp->type == RESPONSE_DIED) { resolve->dead = true; return 0; } assert(resolve->n_outstanding > 0); resolve->n_outstanding--; q = lookup_query(resolve, resp->id); if (!q) return 0; switch (resp->type) { case RESPONSE_ADDRINFO: { const AddrInfoResponse *ai_resp = &packet->addrinfo_response; const void *p; size_t l; struct addrinfo *prev = NULL; assert(length >= sizeof(AddrInfoResponse)); assert(q->type == REQUEST_ADDRINFO); q->ret = ai_resp->ret; q->_errno = ai_resp->_errno; q->_h_errno = ai_resp->_h_errno; l = length - sizeof(AddrInfoResponse); p = (const uint8_t*) resp + sizeof(AddrInfoResponse); while (l > 0 && p) { struct addrinfo *ai = NULL; r = unserialize_addrinfo(&p, &l, &ai); if (r < 0) { q->ret = EAI_SYSTEM; q->_errno = -r; q->_h_errno = 0; freeaddrinfo(q->addrinfo); q->addrinfo = NULL; break; } if (prev) prev->ai_next = ai; else q->addrinfo = ai; prev = ai; } return complete_query(resolve, q); } case RESPONSE_NAMEINFO: { const NameInfoResponse *ni_resp = &packet->nameinfo_response; assert(length >= sizeof(NameInfoResponse)); assert(q->type == REQUEST_NAMEINFO); q->ret = ni_resp->ret; q->_errno = ni_resp->_errno; q->_h_errno = ni_resp->_h_errno; if (ni_resp->hostlen > 0) { q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse), ni_resp->hostlen-1); if (!q->host) { q->ret = EAI_MEMORY; q->_errno = ENOMEM; q->_h_errno = 0; } } if (ni_resp->servlen > 0) { q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen, ni_resp->servlen-1); if (!q->serv) { q->ret = EAI_MEMORY; q->_errno = ENOMEM; q->_h_errno = 0; } } return complete_query(resolve, q); } default: return 0; } } _public_ int sd_resolve_process(sd_resolve *resolve) { RESOLVE_DONT_DESTROY(resolve); union { Packet packet; uint8_t space[BUFSIZE]; } buf; ssize_t l; int r; assert_return(resolve, -EINVAL); assert_return(!resolve_pid_changed(resolve), -ECHILD); /* We don't allow recursively invoking sd_resolve_process(). */ assert_return(!resolve->current, -EBUSY); l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof(buf), 0); if (l < 0) { if (errno == EAGAIN) return 0; return -errno; } if (l == 0) return -ECONNREFUSED; r = handle_response(resolve, &buf.packet, (size_t) l); if (r < 0) return r; return 1; } _public_ int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec) { int r; assert_return(resolve, -EINVAL); assert_return(!resolve_pid_changed(resolve), -ECHILD); if (resolve->n_done >= resolve->n_queries) return 0; do { r = fd_wait_for_event(resolve->fds[RESPONSE_RECV_FD], POLLIN, timeout_usec); } while (r == -EINTR); if (r < 0) return r; return sd_resolve_process(resolve); } static int alloc_query(sd_resolve *resolve, bool floating, sd_resolve_query **_q) { sd_resolve_query *q; int r; assert(resolve); assert(_q); if (resolve->n_queries >= QUERIES_MAX) return -ENOBUFS; r = start_threads(resolve, 1); if (r < 0) return r; while (resolve->query_array[resolve->current_id % QUERIES_MAX]) resolve->current_id++; q = resolve->query_array[resolve->current_id % QUERIES_MAX] = new0(sd_resolve_query, 1); if (!q) return -ENOMEM; q->n_ref = 1; q->resolve = resolve; q->floating = floating; q->id = resolve->current_id++; if (!floating) sd_resolve_ref(resolve); LIST_PREPEND(queries, resolve->queries, q); resolve->n_queries++; *_q = q; return 0; } _public_ int sd_resolve_getaddrinfo( sd_resolve *resolve, sd_resolve_query **_q, const char *node, const char *service, const struct addrinfo *hints, sd_resolve_getaddrinfo_handler_t callback, void *userdata) { AddrInfoRequest req = {}; struct msghdr mh = {}; struct iovec iov[3]; sd_resolve_query *q; int r; assert_return(resolve, -EINVAL); assert_return(node || service, -EINVAL); assert_return(callback, -EINVAL); assert_return(!resolve_pid_changed(resolve), -ECHILD); r = alloc_query(resolve, !_q, &q); if (r < 0) return r; q->type = REQUEST_ADDRINFO; q->getaddrinfo_handler = callback; q->userdata = userdata; req.node_len = node ? strlen(node)+1 : 0; req.service_len = service ? strlen(service)+1 : 0; req.header.id = q->id; req.header.type = REQUEST_ADDRINFO; req.header.length = sizeof(AddrInfoRequest) + req.node_len + req.service_len; if (hints) { req.hints_valid = true; req.ai_flags = hints->ai_flags; req.ai_family = hints->ai_family; req.ai_socktype = hints->ai_socktype; req.ai_protocol = hints->ai_protocol; } iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(AddrInfoRequest) }; if (node) iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) node, .iov_len = req.node_len }; if (service) iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) service, .iov_len = req.service_len }; mh.msg_iov = iov; if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) { sd_resolve_query_unref(q); return -errno; } resolve->n_outstanding++; if (_q) *_q = q; return 0; } static int getaddrinfo_done(sd_resolve_query* q) { assert(q); assert(q->done); assert(q->getaddrinfo_handler); errno = q->_errno; h_errno = q->_h_errno; return q->getaddrinfo_handler(q, q->ret, q->addrinfo, q->userdata); } _public_ int sd_resolve_getnameinfo( sd_resolve *resolve, sd_resolve_query**_q, const struct sockaddr *sa, socklen_t salen, int flags, uint64_t get, sd_resolve_getnameinfo_handler_t callback, void *userdata) { NameInfoRequest req = {}; struct msghdr mh = {}; struct iovec iov[2]; sd_resolve_query *q; int r; assert_return(resolve, -EINVAL); assert_return(sa, -EINVAL); assert_return(salen >= sizeof(struct sockaddr), -EINVAL); assert_return(salen <= sizeof(union sockaddr_union), -EINVAL); assert_return((get & ~SD_RESOLVE_GET_BOTH) == 0, -EINVAL); assert_return(callback, -EINVAL); assert_return(!resolve_pid_changed(resolve), -ECHILD); r = alloc_query(resolve, !_q, &q); if (r < 0) return r; q->type = REQUEST_NAMEINFO; q->getnameinfo_handler = callback; q->userdata = userdata; req.header.id = q->id; req.header.type = REQUEST_NAMEINFO; req.header.length = sizeof(NameInfoRequest) + salen; req.flags = flags; req.sockaddr_len = salen; req.gethost = !!(get & SD_RESOLVE_GET_HOST); req.getserv = !!(get & SD_RESOLVE_GET_SERVICE); iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(NameInfoRequest) }; iov[1] = (struct iovec) { .iov_base = (void*) sa, .iov_len = salen }; mh.msg_iov = iov; mh.msg_iovlen = 2; if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) { sd_resolve_query_unref(q); return -errno; } resolve->n_outstanding++; if (_q) *_q = q; return 0; } static int getnameinfo_done(sd_resolve_query *q) { assert(q); assert(q->done); assert(q->getnameinfo_handler); errno = q->_errno; h_errno= q->_h_errno; return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata); } _public_ sd_resolve_query* sd_resolve_query_ref(sd_resolve_query *q) { assert_return(q, NULL); assert(q->n_ref >= 1); q->n_ref++; return q; } static void resolve_freeaddrinfo(struct addrinfo *ai) { while (ai) { struct addrinfo *next = ai->ai_next; free(ai->ai_addr); free(ai->ai_canonname); free(ai); ai = next; } } static void resolve_query_disconnect(sd_resolve_query *q) { sd_resolve *resolve; unsigned i; assert(q); if (!q->resolve) return; resolve = q->resolve; assert(resolve->n_queries > 0); if (q->done) { assert(resolve->n_done > 0); resolve->n_done--; } i = q->id % QUERIES_MAX; assert(resolve->query_array[i] == q); resolve->query_array[i] = NULL; LIST_REMOVE(queries, resolve->queries, q); resolve->n_queries--; q->resolve = NULL; if (!q->floating) sd_resolve_unref(resolve); } static void resolve_query_free(sd_resolve_query *q) { assert(q); resolve_query_disconnect(q); resolve_freeaddrinfo(q->addrinfo); free(q->host); free(q->serv); free(q); } _public_ sd_resolve_query* sd_resolve_query_unref(sd_resolve_query* q) { if (!q) return NULL; assert(q->n_ref >= 1); q->n_ref--; if (q->n_ref <= 0) resolve_query_free(q); return NULL; } _public_ int sd_resolve_query_is_done(sd_resolve_query *q) { assert_return(q, -EINVAL); assert_return(!resolve_pid_changed(q->resolve), -ECHILD); return q->done; } _public_ void* sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata) { void *ret; assert_return(q, NULL); assert_return(!resolve_pid_changed(q->resolve), NULL); ret = q->userdata; q->userdata = userdata; return ret; } _public_ void* sd_resolve_query_get_userdata(sd_resolve_query *q) { assert_return(q, NULL); assert_return(!resolve_pid_changed(q->resolve), NULL); return q->userdata; } _public_ sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q) { assert_return(q, NULL); assert_return(!resolve_pid_changed(q->resolve), NULL); return q->resolve; } static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) { sd_resolve *resolve = userdata; int r; assert(resolve); r = sd_resolve_process(resolve); if (r < 0) return r; return 1; } _public_ int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int priority) { int r; assert_return(resolve, -EINVAL); assert_return(!resolve->event, -EBUSY); assert(!resolve->event_source); if (event) resolve->event = sd_event_ref(event); else { r = sd_event_default(&resolve->event); if (r < 0) return r; } r = sd_event_add_io(resolve->event, &resolve->event_source, resolve->fds[RESPONSE_RECV_FD], POLLIN, io_callback, resolve); if (r < 0) goto fail; r = sd_event_source_set_priority(resolve->event_source, priority); if (r < 0) goto fail; return 0; fail: sd_resolve_detach_event(resolve); return r; } _public_ int sd_resolve_detach_event(sd_resolve *resolve) { assert_return(resolve, -EINVAL); if (!resolve->event) return 0; if (resolve->event_source) { sd_event_source_set_enabled(resolve->event_source, SD_EVENT_OFF); resolve->event_source = sd_event_source_unref(resolve->event_source); } resolve->event = sd_event_unref(resolve->event); return 1; } _public_ sd_event *sd_resolve_get_event(sd_resolve *resolve) { assert_return(resolve, NULL); return resolve->event; } systemd-229/src/libsystemd/sd-resolve/test-resolve.c000066400000000000000000000072161265713322000227200ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2005-2008 Lennart Poettering Copyright 2014 Daniel Buch systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "sd-resolve.h" #include "alloc-util.h" #include "macro.h" #include "socket-util.h" #include "string-util.h" static int getaddrinfo_handler(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata) { const struct addrinfo *i; assert_se(q); if (ret != 0) { log_error("getaddrinfo error: %s %i", gai_strerror(ret), ret); return 0; } for (i = ai; i; i = i->ai_next) { _cleanup_free_ char *addr = NULL; assert_se(sockaddr_pretty(i->ai_addr, i->ai_addrlen, false, true, &addr) == 0); puts(addr); } printf("canonical name: %s\n", strna(ai->ai_canonname)); return 0; } static int getnameinfo_handler(sd_resolve_query *q, int ret, const char *host, const char *serv, void *userdata) { assert_se(q); if (ret != 0) { log_error("getnameinfo error: %s %i", gai_strerror(ret), ret); return 0; } printf("Host: %s -- Serv: %s\n", strna(host), strna(serv)); return 0; } int main(int argc, char *argv[]) { _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q1 = NULL, *q2 = NULL; _cleanup_(sd_resolve_unrefp) sd_resolve *resolve = NULL; int r = 0; struct addrinfo hints = { .ai_family = PF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_flags = AI_CANONNAME }; struct sockaddr_in sa = { .sin_family = AF_INET, .sin_port = htons(80) }; assert_se(sd_resolve_default(&resolve) >= 0); /* Test a floating resolver query */ sd_resolve_getaddrinfo(resolve, NULL, "redhat.com", "http", NULL, getaddrinfo_handler, NULL); /* Make a name -> address query */ r = sd_resolve_getaddrinfo(resolve, &q1, argc >= 2 ? argv[1] : "www.heise.de", NULL, &hints, getaddrinfo_handler, NULL); if (r < 0) log_error_errno(r, "sd_resolve_getaddrinfo(): %m"); /* Make an address -> name query */ sa.sin_addr.s_addr = inet_addr(argc >= 3 ? argv[2] : "193.99.144.71"); r = sd_resolve_getnameinfo(resolve, &q2, (struct sockaddr*) &sa, sizeof(sa), 0, SD_RESOLVE_GET_BOTH, getnameinfo_handler, NULL); if (r < 0) log_error_errno(r, "sd_resolve_getnameinfo(): %m"); /* Wait until all queries are completed */ for (;;) { r = sd_resolve_wait(resolve, (uint64_t) -1); if (r == 0) break; if (r < 0) { log_error_errno(r, "sd_resolve_wait(): %m"); assert_not_reached("sd_resolve_wait() failed"); } } return 0; } systemd-229/src/libsystemd/sd-utf8/000077500000000000000000000000001265713322000173215ustar00rootroot00000000000000systemd-229/src/libsystemd/sd-utf8/Makefile000077700000000000000000000000001265713322000230422../../Makefileustar00rootroot00000000000000systemd-229/src/libsystemd/sd-utf8/sd-utf8.c000066400000000000000000000020031265713322000207520ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-utf8.h" #include "utf8.h" #include "util.h" _public_ const char *sd_utf8_is_valid(const char *s) { assert_return(s, NULL); return utf8_is_valid(s); } _public_ const char *sd_ascii_is_valid(const char *s) { assert_return(s, NULL); return ascii_is_valid(s); } systemd-229/src/libudev/000077500000000000000000000000001265713322000153025ustar00rootroot00000000000000systemd-229/src/libudev/.gitignore000066400000000000000000000000141265713322000172650ustar00rootroot00000000000000/libudev.pc systemd-229/src/libudev/Makefile000077700000000000000000000000001265713322000206102../Makefileustar00rootroot00000000000000systemd-229/src/libudev/libudev-device-internal.h000066400000000000000000000030641265713322000221570ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers Copyright 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "libudev.h" #include "sd-device.h" #include "libudev-private.h" /** * udev_device: * * Opaque object representing one kernel sys device. */ struct udev_device { struct udev *udev; /* real device object */ sd_device *device; /* legacy */ int refcount; struct udev_device *parent; bool parent_set; struct udev_list properties; uint64_t properties_generation; struct udev_list tags; uint64_t tags_generation; struct udev_list devlinks; uint64_t devlinks_generation; bool properties_read:1; bool tags_read:1; bool devlinks_read:1; struct udev_list sysattrs; bool sysattrs_read; }; struct udev_device *udev_device_new(struct udev *udev); systemd-229/src/libudev/libudev-device-private.c000066400000000000000000000235531265713322000220150ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers Copyright 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "libudev.h" #include "device-private.h" #include "libudev-device-internal.h" #include "libudev-private.h" int udev_device_tag_index(struct udev_device *udev_device, struct udev_device *udev_device_old, bool add) { sd_device *device_old = NULL; int r; assert(udev_device); if (udev_device_old) device_old = udev_device_old->device; r = device_tag_index(udev_device->device, device_old, add); if (r < 0) return r; return 0; } int udev_device_update_db(struct udev_device *udev_device) { int r; assert(udev_device); r = device_update_db(udev_device->device); if (r < 0) return r; return 0; } int udev_device_delete_db(struct udev_device *udev_device) { int r; assert(udev_device); r = device_delete_db(udev_device->device); if (r < 0) return r; return 0; } int udev_device_get_ifindex(struct udev_device *udev_device) { int r, ifindex; assert(udev_device); r = sd_device_get_ifindex(udev_device->device, &ifindex); if (r < 0) return r; return ifindex; } const char *udev_device_get_devpath_old(struct udev_device *udev_device) { const char *devpath_old = NULL; int r; assert(udev_device); r = sd_device_get_property_value(udev_device->device, "DEVPATH_OLD", &devpath_old); if (r < 0 && r != -ENOENT) { errno = -r; return NULL; } return devpath_old; } mode_t udev_device_get_devnode_mode(struct udev_device *udev_device) { mode_t mode; int r; assert(udev_device); r = device_get_devnode_mode(udev_device->device, &mode); if (r < 0) { errno = -r; return 0; } return mode; } uid_t udev_device_get_devnode_uid(struct udev_device *udev_device) { uid_t uid; int r; assert(udev_device); r = device_get_devnode_uid(udev_device->device, &uid); if (r < 0) { errno = -r; return 0; } return uid; } gid_t udev_device_get_devnode_gid(struct udev_device *udev_device) { gid_t gid; int r; assert(udev_device); r = device_get_devnode_gid(udev_device->device, &gid); if (r < 0) { errno = -r; return 0; } return gid; } void udev_device_ensure_usec_initialized(struct udev_device *udev_device, struct udev_device *udev_device_old) { assert(udev_device); device_ensure_usec_initialized(udev_device->device, udev_device_old ? udev_device_old->device : NULL); } char **udev_device_get_properties_envp(struct udev_device *udev_device) { char **envp; int r; assert(udev_device); r = device_get_properties_strv(udev_device->device, &envp); if (r < 0) { errno = -r; return NULL; } return envp; } ssize_t udev_device_get_properties_monitor_buf(struct udev_device *udev_device, const char **buf) { const char *nulstr; size_t len; int r; assert(udev_device); assert(buf); r = device_get_properties_nulstr(udev_device->device, (const uint8_t **)&nulstr, &len); if (r < 0) return r; *buf = nulstr; return len; } int udev_device_get_devlink_priority(struct udev_device *udev_device) { int priority, r; assert(udev_device); r = device_get_devlink_priority(udev_device->device, &priority); if (r < 0) return r; return priority; } int udev_device_get_watch_handle(struct udev_device *udev_device) { int handle, r; assert(udev_device); r = device_get_watch_handle(udev_device->device, &handle); if (r < 0) return r; return handle; } void udev_device_set_is_initialized(struct udev_device *udev_device) { assert(udev_device); device_set_is_initialized(udev_device->device); } int udev_device_rename(struct udev_device *udev_device, const char *name) { int r; assert(udev_device); r = device_rename(udev_device->device, name); if (r < 0) return r; return 0; } struct udev_device *udev_device_shallow_clone(struct udev_device *old_device) { struct udev_device *device; int r; assert(old_device); device = udev_device_new(old_device->udev); if (!device) return NULL; r = device_shallow_clone(old_device->device, &device->device); if (r < 0) { udev_device_unref(device); errno = -r; return NULL; } return device; } struct udev_device *udev_device_clone_with_db(struct udev_device *udev_device_old) { struct udev_device *udev_device; int r; assert(udev_device_old); udev_device = udev_device_new(udev_device_old->udev); if (!udev_device) return NULL; r = device_clone_with_db(udev_device_old->device, &udev_device->device); if (r < 0) { udev_device_unref(udev_device); errno = -r; return NULL; } return udev_device; } struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr, ssize_t buflen) { struct udev_device *device; int r; device = udev_device_new(udev); if (!device) return NULL; r = device_new_from_nulstr(&device->device, (uint8_t*)nulstr, buflen); if (r < 0) { udev_device_unref(device); errno = -r; return NULL; } return device; } struct udev_device *udev_device_new_from_synthetic_event(struct udev *udev, const char *syspath, const char *action) { struct udev_device *device; int r; device = udev_device_new(udev); if (!device) return NULL; r = device_new_from_synthetic_event(&device->device, syspath, action); if (r < 0) { udev_device_unref(device); errno = -r; return NULL; } return device; } int udev_device_copy_properties(struct udev_device *udev_device_dst, struct udev_device *udev_device_src) { int r; assert(udev_device_dst); assert(udev_device_src); r = device_copy_properties(udev_device_dst->device, udev_device_src->device); if (r < 0) return r; return 0; } const char *udev_device_get_id_filename(struct udev_device *udev_device) { const char *filename; int r; assert(udev_device); r = device_get_id_filename(udev_device->device, &filename); if (r < 0) { errno = -r; return NULL; } return filename; } int udev_device_set_watch_handle(struct udev_device *udev_device, int handle) { assert(udev_device); device_set_watch_handle(udev_device->device, handle); return 0; } void udev_device_set_db_persist(struct udev_device *udev_device) { assert(udev_device); device_set_db_persist(udev_device->device); } int udev_device_set_devlink_priority(struct udev_device *udev_device, int priority) { assert(udev_device); device_set_devlink_priority(udev_device->device, priority); return 0; } int udev_device_add_devlink(struct udev_device *udev_device, const char *devlink) { int r; assert(udev_device); r = device_add_devlink(udev_device->device, devlink); if (r < 0) return r; return 0; } int udev_device_add_property(struct udev_device *udev_device, const char *property, const char *value) { int r; assert(udev_device); r = device_add_property(udev_device->device, property, value); if (r < 0) return r; return 0; } int udev_device_add_tag(struct udev_device *udev_device, const char *tag) { int r; assert(udev_device); r = device_add_tag(udev_device->device, tag); if (r < 0) return r; return 0; } void udev_device_remove_tag(struct udev_device *udev_device, const char *tag) { assert(udev_device); device_remove_tag(udev_device->device, tag); } void udev_device_cleanup_tags_list(struct udev_device *udev_device) { assert(udev_device); device_cleanup_tags(udev_device->device); } void udev_device_cleanup_devlinks_list(struct udev_device *udev_device) { assert(udev_device); device_cleanup_devlinks(udev_device->device); } void udev_device_set_info_loaded(struct udev_device *udev_device) { assert(udev_device); device_seal(udev_device->device); } void udev_device_read_db(struct udev_device *udev_device) { assert(udev_device); device_read_db_force(udev_device->device); } systemd-229/src/libudev/libudev-device.c000066400000000000000000000656461265713322000203560ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers Copyright 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libudev.h" #include "sd-device.h" #include "alloc-util.h" #include "device-private.h" #include "device-util.h" #include "libudev-device-internal.h" #include "libudev-private.h" #include "parse-util.h" /** * SECTION:libudev-device * @short_description: kernel sys devices * * Representation of kernel sys devices. Devices are uniquely identified * by their syspath, every device has exactly one path in the kernel sys * filesystem. Devices usually belong to a kernel subsystem, and have * a unique name inside that subsystem. */ /** * udev_device_get_seqnum: * @udev_device: udev device * * This is only valid if the device was received through a monitor. Devices read from * sys do not have a sequence number. * * Returns: the kernel event sequence number, or 0 if there is no sequence number available. **/ _public_ unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device) { const char *seqnum; unsigned long long ret; int r; assert_return_errno(udev_device, 0, EINVAL); r = sd_device_get_property_value(udev_device->device, "SEQNUM", &seqnum); if (r == -ENOENT) return 0; else if (r < 0) { errno = -r; return 0; } r = safe_atollu(seqnum, &ret); if (r < 0) { errno = -r; return 0; } return ret; } /** * udev_device_get_devnum: * @udev_device: udev device * * Get the device major/minor number. * * Returns: the dev_t number. **/ _public_ dev_t udev_device_get_devnum(struct udev_device *udev_device) { dev_t devnum; int r; assert_return_errno(udev_device, makedev(0, 0), EINVAL); r = sd_device_get_devnum(udev_device->device, &devnum); if (r < 0) { errno = -r; return makedev(0, 0); } return devnum; } /** * udev_device_get_driver: * @udev_device: udev device * * Get the kernel driver name. * * Returns: the driver name string, or #NULL if there is no driver attached. **/ _public_ const char *udev_device_get_driver(struct udev_device *udev_device) { const char *driver; int r; assert_return_errno(udev_device, NULL, EINVAL); r = sd_device_get_driver(udev_device->device, &driver); if (r < 0) { errno = -r; return NULL; } return driver; } /** * udev_device_get_devtype: * @udev_device: udev device * * Retrieve the devtype string of the udev device. * * Returns: the devtype name of the udev device, or #NULL if it can not be determined **/ _public_ const char *udev_device_get_devtype(struct udev_device *udev_device) { const char *devtype; int r; assert_return_errno(udev_device, NULL, EINVAL); r = sd_device_get_devtype(udev_device->device, &devtype); if (r < 0) { errno = -r; return NULL; } return devtype; } /** * udev_device_get_subsystem: * @udev_device: udev device * * Retrieve the subsystem string of the udev device. The string does not * contain any "/". * * Returns: the subsystem name of the udev device, or #NULL if it can not be determined **/ _public_ const char *udev_device_get_subsystem(struct udev_device *udev_device) { const char *subsystem; int r; assert_return_errno(udev_device, NULL, EINVAL); r = sd_device_get_subsystem(udev_device->device, &subsystem); if (r < 0) { errno = -r; return NULL; } else if (!subsystem) errno = ENODATA; return subsystem; } /** * udev_device_get_property_value: * @udev_device: udev device * @key: property name * * Get the value of a given property. * * Returns: the property string, or #NULL if there is no such property. **/ _public_ const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key) { const char *value = NULL; int r; assert_return_errno(udev_device && key, NULL, EINVAL); r = sd_device_get_property_value(udev_device->device, key, &value); if (r < 0) { errno = -r; return NULL; } return value; } struct udev_device *udev_device_new(struct udev *udev) { struct udev_device *udev_device; assert_return_errno(udev, NULL, EINVAL); udev_device = new0(struct udev_device, 1); if (!udev_device) { errno = ENOMEM; return NULL; } udev_device->refcount = 1; udev_device->udev = udev; udev_list_init(udev, &udev_device->properties, true); udev_list_init(udev, &udev_device->tags, true); udev_list_init(udev, &udev_device->sysattrs, true); udev_list_init(udev, &udev_device->devlinks, true); return udev_device; } /** * udev_device_new_from_syspath: * @udev: udev library context * @syspath: sys device path including sys directory * * Create new udev device, and fill in information from the sys * device and the udev database entry. The syspath is the absolute * path to the device, including the sys mount point. * * The initial refcount is 1, and needs to be decremented to * release the resources of the udev device. * * Returns: a new udev device, or #NULL, if it does not exist **/ _public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) { struct udev_device *udev_device; int r; udev_device = udev_device_new(udev); if (!udev_device) return NULL; r = sd_device_new_from_syspath(&udev_device->device, syspath); if (r < 0) { errno = -r; udev_device_unref(udev_device); return NULL; } return udev_device; } /** * udev_device_new_from_devnum: * @udev: udev library context * @type: char or block device * @devnum: device major/minor number * * Create new udev device, and fill in information from the sys * device and the udev database entry. The device is looked-up * by its major/minor number and type. Character and block device * numbers are not unique across the two types. * * The initial refcount is 1, and needs to be decremented to * release the resources of the udev device. * * Returns: a new udev device, or #NULL, if it does not exist **/ _public_ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) { struct udev_device *udev_device; int r; udev_device = udev_device_new(udev); if (!udev_device) return NULL; r = sd_device_new_from_devnum(&udev_device->device, type, devnum); if (r < 0) { errno = -r; udev_device_unref(udev_device); return NULL; } return udev_device; } /** * udev_device_new_from_device_id: * @udev: udev library context * @id: text string identifying a kernel device * * Create new udev device, and fill in information from the sys * device and the udev database entry. The device is looked-up * by a special string: * b8:2 - block device major:minor * c128:1 - char device major:minor * n3 - network device ifindex * +sound:card29 - kernel driver core subsystem:device name * * The initial refcount is 1, and needs to be decremented to * release the resources of the udev device. * * Returns: a new udev device, or #NULL, if it does not exist **/ _public_ struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id) { struct udev_device *udev_device; int r; udev_device = udev_device_new(udev); if (!udev_device) return NULL; r = sd_device_new_from_device_id(&udev_device->device, id); if (r < 0) { errno = -r; udev_device_unref(udev_device); return NULL; } return udev_device; } /** * udev_device_new_from_subsystem_sysname: * @udev: udev library context * @subsystem: the subsystem of the device * @sysname: the name of the device * * Create new udev device, and fill in information from the sys device * and the udev database entry. The device is looked up by the subsystem * and name string of the device, like "mem" / "zero", or "block" / "sda". * * The initial refcount is 1, and needs to be decremented to * release the resources of the udev device. * * Returns: a new udev device, or #NULL, if it does not exist **/ _public_ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) { struct udev_device *udev_device; int r; udev_device = udev_device_new(udev); if (!udev_device) return NULL; r = sd_device_new_from_subsystem_sysname(&udev_device->device, subsystem, sysname); if (r < 0) { errno = -r; udev_device_unref(udev_device); return NULL; } return udev_device; } /** * udev_device_new_from_environment * @udev: udev library context * * Create new udev device, and fill in information from the * current process environment. This only works reliable if * the process is called from a udev rule. It is usually used * for tools executed from IMPORT= rules. * * The initial refcount is 1, and needs to be decremented to * release the resources of the udev device. * * Returns: a new udev device, or #NULL, if it does not exist **/ _public_ struct udev_device *udev_device_new_from_environment(struct udev *udev) { struct udev_device *udev_device; int r; udev_device = udev_device_new(udev); if (!udev_device) return NULL; r = device_new_from_strv(&udev_device->device, environ); if (r < 0) { errno = -r; udev_device_unref(udev_device); return NULL; } return udev_device; } static struct udev_device *device_new_from_parent(struct udev_device *child) { struct udev_device *parent; int r; assert_return_errno(child, NULL, EINVAL); parent = udev_device_new(child->udev); if (!parent) return NULL; r = sd_device_get_parent(child->device, &parent->device); if (r < 0) { errno = -r; udev_device_unref(parent); return NULL; } /* the parent is unref'ed with the child, so take a ref from libudev as well */ sd_device_ref(parent->device); return parent; } /** * udev_device_get_parent: * @udev_device: the device to start searching from * * Find the next parent device, and fill in information from the sys * device and the udev database entry. * * Returned device is not referenced. It is attached to the child * device, and will be cleaned up when the child device is cleaned up. * * It is not necessarily just the upper level directory, empty or not * recognized sys directories are ignored. * * It can be called as many times as needed, without caring about * references. * * Returns: a new udev device, or #NULL, if it no parent exist. **/ _public_ struct udev_device *udev_device_get_parent(struct udev_device *udev_device) { assert_return_errno(udev_device, NULL, EINVAL); if (!udev_device->parent_set) { udev_device->parent_set = true; udev_device->parent = device_new_from_parent(udev_device); } /* TODO: errno will differ here in case parent == NULL */ return udev_device->parent; } /** * udev_device_get_parent_with_subsystem_devtype: * @udev_device: udev device to start searching from * @subsystem: the subsystem of the device * @devtype: the type (DEVTYPE) of the device * * Find the next parent device, with a matching subsystem and devtype * value, and fill in information from the sys device and the udev * database entry. * * If devtype is #NULL, only subsystem is checked, and any devtype will * match. * * Returned device is not referenced. It is attached to the child * device, and will be cleaned up when the child device is cleaned up. * * It can be called as many times as needed, without caring about * references. * * Returns: a new udev device, or #NULL if no matching parent exists. **/ _public_ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype) { sd_device *parent; int r; assert_return_errno(udev_device, NULL, EINVAL); /* this relies on the fact that finding the subdevice of a parent or the parent of a subdevice commute */ /* first find the correct sd_device */ r = sd_device_get_parent_with_subsystem_devtype(udev_device->device, subsystem, devtype, &parent); if (r < 0) { errno = -r; return NULL; } /* then walk the chain of udev_device parents until the correspanding one is found */ while ((udev_device = udev_device_get_parent(udev_device))) { if (udev_device->device == parent) return udev_device; } errno = ENOENT; return NULL; } /** * udev_device_get_udev: * @udev_device: udev device * * Retrieve the udev library context the device was created with. * * Returns: the udev library context **/ _public_ struct udev *udev_device_get_udev(struct udev_device *udev_device) { assert_return_errno(udev_device, NULL, EINVAL); return udev_device->udev; } /** * udev_device_ref: * @udev_device: udev device * * Take a reference of a udev device. * * Returns: the passed udev device **/ _public_ struct udev_device *udev_device_ref(struct udev_device *udev_device) { if (udev_device) udev_device->refcount++; return udev_device; } /** * udev_device_unref: * @udev_device: udev device * * Drop a reference of a udev device. If the refcount reaches zero, * the resources of the device will be released. * * Returns: #NULL **/ _public_ struct udev_device *udev_device_unref(struct udev_device *udev_device) { if (udev_device && (-- udev_device->refcount) == 0) { sd_device_unref(udev_device->device); udev_device_unref(udev_device->parent); udev_list_cleanup(&udev_device->properties); udev_list_cleanup(&udev_device->sysattrs); udev_list_cleanup(&udev_device->tags); udev_list_cleanup(&udev_device->devlinks); free(udev_device); } return NULL; } /** * udev_device_get_devpath: * @udev_device: udev device * * Retrieve the kernel devpath value of the udev device. The path * does not contain the sys mount point, and starts with a '/'. * * Returns: the devpath of the udev device **/ _public_ const char *udev_device_get_devpath(struct udev_device *udev_device) { const char *devpath; int r; assert_return_errno(udev_device, NULL, EINVAL); r = sd_device_get_devpath(udev_device->device, &devpath); if (r < 0) { errno = -r; return NULL; } return devpath; } /** * udev_device_get_syspath: * @udev_device: udev device * * Retrieve the sys path of the udev device. The path is an * absolute path and starts with the sys mount point. * * Returns: the sys path of the udev device **/ _public_ const char *udev_device_get_syspath(struct udev_device *udev_device) { const char *syspath; int r; assert_return_errno(udev_device, NULL, EINVAL); r = sd_device_get_syspath(udev_device->device, &syspath); if (r < 0) { errno = -r; return NULL; } return syspath; } /** * udev_device_get_sysname: * @udev_device: udev device * * Get the kernel device name in /sys. * * Returns: the name string of the device device **/ _public_ const char *udev_device_get_sysname(struct udev_device *udev_device) { const char *sysname; int r; assert_return_errno(udev_device, NULL, EINVAL); r = sd_device_get_sysname(udev_device->device, &sysname); if (r < 0) { errno = -r; return NULL; } return sysname; } /** * udev_device_get_sysnum: * @udev_device: udev device * * Get the instance number of the device. * * Returns: the trailing number string of the device name **/ _public_ const char *udev_device_get_sysnum(struct udev_device *udev_device) { const char *sysnum; int r; assert_return_errno(udev_device, NULL, EINVAL); r = sd_device_get_sysnum(udev_device->device, &sysnum); if (r < 0) { errno = -r; return NULL; } return sysnum; } /** * udev_device_get_devnode: * @udev_device: udev device * * Retrieve the device node file name belonging to the udev device. * The path is an absolute path, and starts with the device directory. * * Returns: the device node file name of the udev device, or #NULL if no device node exists **/ _public_ const char *udev_device_get_devnode(struct udev_device *udev_device) { const char *devnode; int r; assert_return_errno(udev_device, NULL, EINVAL); r = sd_device_get_devname(udev_device->device, &devnode); if (r < 0) { errno = -r; return NULL; } return devnode; } /** * udev_device_get_devlinks_list_entry: * @udev_device: udev device * * Retrieve the list of device links pointing to the device file of * the udev device. The next list entry can be retrieved with * udev_list_entry_get_next(), which returns #NULL if no more entries exist. * The devlink path can be retrieved from the list entry by * udev_list_entry_get_name(). The path is an absolute path, and starts with * the device directory. * * Returns: the first entry of the device node link list **/ _public_ struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device) { assert_return_errno(udev_device, NULL, EINVAL); if (device_get_devlinks_generation(udev_device->device) != udev_device->devlinks_generation || !udev_device->devlinks_read) { const char *devlink; udev_list_cleanup(&udev_device->devlinks); FOREACH_DEVICE_DEVLINK(udev_device->device, devlink) udev_list_entry_add(&udev_device->devlinks, devlink, NULL); udev_device->devlinks_read = true; udev_device->devlinks_generation = device_get_devlinks_generation(udev_device->device); } return udev_list_get_entry(&udev_device->devlinks); } /** * udev_device_get_event_properties_entry: * @udev_device: udev device * * Retrieve the list of key/value device properties of the udev * device. The next list entry can be retrieved with udev_list_entry_get_next(), * which returns #NULL if no more entries exist. The property name * can be retrieved from the list entry by udev_list_entry_get_name(), * the property value by udev_list_entry_get_value(). * * Returns: the first entry of the property list **/ _public_ struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device) { assert_return_errno(udev_device, NULL, EINVAL); if (device_get_properties_generation(udev_device->device) != udev_device->properties_generation || !udev_device->properties_read) { const char *key, *value; udev_list_cleanup(&udev_device->properties); FOREACH_DEVICE_PROPERTY(udev_device->device, key, value) udev_list_entry_add(&udev_device->properties, key, value); udev_device->properties_read = true; udev_device->properties_generation = device_get_properties_generation(udev_device->device); } return udev_list_get_entry(&udev_device->properties); } /** * udev_device_get_action: * @udev_device: udev device * * This is only valid if the device was received through a monitor. Devices read from * sys do not have an action string. Usual actions are: add, remove, change, online, * offline. * * Returns: the kernel action value, or #NULL if there is no action value available. **/ _public_ const char *udev_device_get_action(struct udev_device *udev_device) { const char *action = NULL; int r; assert_return_errno(udev_device, NULL, EINVAL); r = sd_device_get_property_value(udev_device->device, "ACTION", &action); if (r < 0 && r != -ENOENT) { errno = -r; return NULL; } return action; } /** * udev_device_get_usec_since_initialized: * @udev_device: udev device * * Return the number of microseconds passed since udev set up the * device for the first time. * * This is only implemented for devices with need to store properties * in the udev database. All other devices return 0 here. * * Returns: the number of microseconds since the device was first seen. **/ _public_ unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device) { usec_t ts; int r; assert_return(udev_device, -EINVAL); r = sd_device_get_usec_since_initialized(udev_device->device, &ts); if (r < 0) { errno = EINVAL; return 0; } return ts; } /** * udev_device_get_sysattr_value: * @udev_device: udev device * @sysattr: attribute name * * The retrieved value is cached in the device. Repeated calls will return the same * value and not open the attribute again. * * Returns: the content of a sys attribute file, or #NULL if there is no sys attribute value. **/ _public_ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) { const char *value; int r; assert_return_errno(udev_device, NULL, EINVAL); r = sd_device_get_sysattr_value(udev_device->device, sysattr, &value); if (r < 0) { errno = -r; return NULL; } return value; } /** * udev_device_set_sysattr_value: * @udev_device: udev device * @sysattr: attribute name * @value: new value to be set * * Update the contents of the sys attribute and the cached value of the device. * * Returns: Negative error code on failure or 0 on success. **/ _public_ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value) { int r; assert_return(udev_device, -EINVAL); r = sd_device_set_sysattr_value(udev_device->device, sysattr, value); if (r < 0) return r; return 0; } /** * udev_device_get_sysattr_list_entry: * @udev_device: udev device * * Retrieve the list of available sysattrs, with value being empty; * This just return all available sysfs attributes for a particular * device without reading their values. * * Returns: the first entry of the property list **/ _public_ struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device) { assert_return_errno(udev_device, NULL, EINVAL); if (!udev_device->sysattrs_read) { const char *sysattr; udev_list_cleanup(&udev_device->sysattrs); FOREACH_DEVICE_SYSATTR(udev_device->device, sysattr) udev_list_entry_add(&udev_device->sysattrs, sysattr, NULL); udev_device->sysattrs_read = true; } return udev_list_get_entry(&udev_device->sysattrs); } /** * udev_device_get_is_initialized: * @udev_device: udev device * * Check if udev has already handled the device and has set up * device node permissions and context, or has renamed a network * device. * * This is only implemented for devices with a device node * or network interfaces. All other devices return 1 here. * * Returns: 1 if the device is set up. 0 otherwise. **/ _public_ int udev_device_get_is_initialized(struct udev_device *udev_device) { int r, initialized; assert_return(udev_device, -EINVAL); r = sd_device_get_is_initialized(udev_device->device, &initialized); if (r < 0) { errno = -r; return 0; } return initialized; } /** * udev_device_get_tags_list_entry: * @udev_device: udev device * * Retrieve the list of tags attached to the udev device. The next * list entry can be retrieved with udev_list_entry_get_next(), * which returns #NULL if no more entries exist. The tag string * can be retrieved from the list entry by udev_list_entry_get_name(). * * Returns: the first entry of the tag list **/ _public_ struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) { assert_return_errno(udev_device, NULL, EINVAL); if (device_get_tags_generation(udev_device->device) != udev_device->tags_generation || !udev_device->tags_read) { const char *tag; udev_list_cleanup(&udev_device->tags); FOREACH_DEVICE_TAG(udev_device->device, tag) udev_list_entry_add(&udev_device->tags, tag, NULL); udev_device->tags_read = true; udev_device->tags_generation = device_get_tags_generation(udev_device->device); } return udev_list_get_entry(&udev_device->tags); } /** * udev_device_has_tag: * @udev_device: udev device * @tag: tag name * * Check if a given device has a certain tag associated. * * Returns: 1 if the tag is found. 0 otherwise. **/ _public_ int udev_device_has_tag(struct udev_device *udev_device, const char *tag) { assert_return(udev_device, 0); return sd_device_has_tag(udev_device->device, tag); } systemd-229/src/libudev/libudev-enumerate.c000066400000000000000000000306111265713322000210640ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers Copyright 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include "libudev.h" #include "sd-device.h" #include "alloc-util.h" #include "device-enumerator-private.h" #include "device-util.h" #include "libudev-device-internal.h" /** * SECTION:libudev-enumerate * @short_description: lookup and sort sys devices * * Lookup devices in the sys filesystem, filter devices by properties, * and return a sorted list of devices. */ /** * udev_enumerate: * * Opaque object representing one device lookup/sort context. */ struct udev_enumerate { struct udev *udev; int refcount; struct udev_list devices_list; bool devices_uptodate:1; sd_device_enumerator *enumerator; }; /** * udev_enumerate_new: * @udev: udev library context * * Create an enumeration context to scan /sys. * * Returns: an enumeration context. **/ _public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev) { _cleanup_free_ struct udev_enumerate *udev_enumerate = NULL; struct udev_enumerate *ret; int r; assert_return_errno(udev, NULL, EINVAL); udev_enumerate = new0(struct udev_enumerate, 1); if (!udev_enumerate) { errno = ENOMEM; return NULL; } r = sd_device_enumerator_new(&udev_enumerate->enumerator); if (r < 0) { errno = -r; return NULL; } r = sd_device_enumerator_allow_uninitialized(udev_enumerate->enumerator); if (r < 0) { errno = -r; return NULL; } udev_enumerate->refcount = 1; udev_enumerate->udev = udev; udev_list_init(udev, &udev_enumerate->devices_list, false); ret = udev_enumerate; udev_enumerate = NULL; return ret; } /** * udev_enumerate_ref: * @udev_enumerate: context * * Take a reference of a enumeration context. * * Returns: the passed enumeration context **/ _public_ struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) { if (udev_enumerate) udev_enumerate->refcount ++; return udev_enumerate; } /** * udev_enumerate_unref: * @udev_enumerate: context * * Drop a reference of an enumeration context. If the refcount reaches zero, * all resources of the enumeration context will be released. * * Returns: #NULL **/ _public_ struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) { if (udev_enumerate && (-- udev_enumerate->refcount) == 0) { udev_list_cleanup(&udev_enumerate->devices_list); sd_device_enumerator_unref(udev_enumerate->enumerator); free(udev_enumerate); } return NULL; } /** * udev_enumerate_get_udev: * @udev_enumerate: context * * Get the udev library context. * * Returns: a pointer to the context. */ _public_ struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) { assert_return_errno(udev_enumerate, NULL, EINVAL); return udev_enumerate->udev; } /** * udev_enumerate_get_list_entry: * @udev_enumerate: context * * Get the first entry of the sorted list of device paths. * * Returns: a udev_list_entry. */ _public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) { assert_return_errno(udev_enumerate, NULL, EINVAL); if (!udev_enumerate->devices_uptodate) { sd_device *device; udev_list_cleanup(&udev_enumerate->devices_list); FOREACH_DEVICE_AND_SUBSYSTEM(udev_enumerate->enumerator, device) { const char *syspath; int r; r = sd_device_get_syspath(device, &syspath); if (r < 0) { errno = -r; return NULL; } udev_list_entry_add(&udev_enumerate->devices_list, syspath, NULL); } udev_enumerate->devices_uptodate = true; } return udev_list_get_entry(&udev_enumerate->devices_list); } /** * udev_enumerate_add_match_subsystem: * @udev_enumerate: context * @subsystem: filter for a subsystem of the device to include in the list * * Match only devices belonging to a certain kernel subsystem. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { assert_return(udev_enumerate, -EINVAL); if (!subsystem) return 0; return sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, true); } /** * udev_enumerate_add_nomatch_subsystem: * @udev_enumerate: context * @subsystem: filter for a subsystem of the device to exclude from the list * * Match only devices not belonging to a certain kernel subsystem. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { assert_return(udev_enumerate, -EINVAL); if (!subsystem) return 0; return sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, false); } /** * udev_enumerate_add_match_sysattr: * @udev_enumerate: context * @sysattr: filter for a sys attribute at the device to include in the list * @value: optional value of the sys attribute * * Match only devices with a certain /sys device attribute. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) { assert_return(udev_enumerate, -EINVAL); if (!sysattr) return 0; return sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, true); } /** * udev_enumerate_add_nomatch_sysattr: * @udev_enumerate: context * @sysattr: filter for a sys attribute at the device to exclude from the list * @value: optional value of the sys attribute * * Match only devices not having a certain /sys device attribute. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) { assert_return(udev_enumerate, -EINVAL); if (!sysattr) return 0; return sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, false); } /** * udev_enumerate_add_match_property: * @udev_enumerate: context * @property: filter for a property of the device to include in the list * @value: value of the property * * Match only devices with a certain property. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) { assert_return(udev_enumerate, -EINVAL); if (!property) return 0; return sd_device_enumerator_add_match_property(udev_enumerate->enumerator, property, value); } /** * udev_enumerate_add_match_tag: * @udev_enumerate: context * @tag: filter for a tag of the device to include in the list * * Match only devices with a certain tag. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) { assert_return(udev_enumerate, -EINVAL); if (!tag) return 0; return sd_device_enumerator_add_match_tag(udev_enumerate->enumerator, tag); } /** * udev_enumerate_add_match_parent: * @udev_enumerate: context * @parent: parent device where to start searching * * Return the devices on the subtree of one given device. The parent * itself is included in the list. * * A reference for the device is held until the udev_enumerate context * is cleaned up. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) { assert_return(udev_enumerate, -EINVAL); if (!parent) return 0; return sd_device_enumerator_add_match_parent(udev_enumerate->enumerator, parent->device); } /** * udev_enumerate_add_match_is_initialized: * @udev_enumerate: context * * Match only devices which udev has set up already. This makes * sure, that the device node permissions and context are properly set * and that network devices are fully renamed. * * Usually, devices which are found in the kernel but not already * handled by udev, have still pending events. Services should subscribe * to monitor events and wait for these devices to become ready, instead * of using uninitialized devices. * * For now, this will not affect devices which do not have a device node * and are not network interfaces. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) { assert_return(udev_enumerate, -EINVAL); return device_enumerator_add_match_is_initialized(udev_enumerate->enumerator); } /** * udev_enumerate_add_match_sysname: * @udev_enumerate: context * @sysname: filter for the name of the device to include in the list * * Match only devices with a given /sys device name. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) { assert_return(udev_enumerate, -EINVAL); if (!sysname) return 0; return sd_device_enumerator_add_match_sysname(udev_enumerate->enumerator, sysname); } /** * udev_enumerate_add_syspath: * @udev_enumerate: context * @syspath: path of a device * * Add a device to the list of devices, to retrieve it back sorted in dependency order. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) { _cleanup_(sd_device_unrefp) sd_device *device = NULL; int r; assert_return(udev_enumerate, -EINVAL); if (!syspath) return 0; r = sd_device_new_from_syspath(&device, syspath); if (r < 0) return r; r = device_enumerator_add_device(udev_enumerate->enumerator, device); if (r < 0) return r; return 0; } /** * udev_enumerate_scan_devices: * @udev_enumerate: udev enumeration context * * Scan /sys for all devices which match the given filters. No matches * will return all currently available devices. * * Returns: 0 on success, otherwise a negative error value. **/ _public_ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) { assert_return(udev_enumerate, -EINVAL); return device_enumerator_scan_devices(udev_enumerate->enumerator); } /** * udev_enumerate_scan_subsystems: * @udev_enumerate: udev enumeration context * * Scan /sys for all kernel subsystems, including buses, classes, drivers. * * Returns: 0 on success, otherwise a negative error value. **/ _public_ int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) { assert_return(udev_enumerate, -EINVAL); return device_enumerator_scan_subsystems(udev_enumerate->enumerator); } systemd-229/src/libudev/libudev-hwdb.c000066400000000000000000000073641265713322000200340ustar00rootroot00000000000000/*** This file is part of systemd. Copyright Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-hwdb.h" #include "alloc-util.h" #include "hwdb-util.h" #include "libudev-private.h" /** * SECTION:libudev-hwdb * @short_description: retrieve properties from the hardware database * * Libudev hardware database interface. */ /** * udev_hwdb: * * Opaque object representing the hardware database. */ struct udev_hwdb { struct udev *udev; int refcount; sd_hwdb *hwdb; struct udev_list properties_list; }; /** * udev_hwdb_new: * @udev: udev library context * * Create a hardware database context to query properties for devices. * * Returns: a hwdb context. **/ _public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) { _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb_internal = NULL; struct udev_hwdb *hwdb; int r; assert_return(udev, NULL); r = sd_hwdb_new(&hwdb_internal); if (r < 0) return NULL; hwdb = new0(struct udev_hwdb, 1); if (!hwdb) return NULL; hwdb->refcount = 1; hwdb->hwdb = hwdb_internal; hwdb_internal = NULL; udev_list_init(udev, &hwdb->properties_list, true); return hwdb; } /** * udev_hwdb_ref: * @hwdb: context * * Take a reference of a hwdb context. * * Returns: the passed enumeration context **/ _public_ struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) { if (!hwdb) return NULL; hwdb->refcount++; return hwdb; } /** * udev_hwdb_unref: * @hwdb: context * * Drop a reference of a hwdb context. If the refcount reaches zero, * all resources of the hwdb context will be released. * * Returns: #NULL **/ _public_ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) { if (!hwdb) return NULL; hwdb->refcount--; if (hwdb->refcount > 0) return NULL; sd_hwdb_unref(hwdb->hwdb); udev_list_cleanup(&hwdb->properties_list); free(hwdb); return NULL; } /** * udev_hwdb_get_properties_list_entry: * @hwdb: context * @modalias: modalias string * @flags: (unused) * * Lookup a matching device in the hardware database. The lookup key is a * modalias string, whose formats are defined for the Linux kernel modules. * Examples are: pci:v00008086d00001C2D*, usb:v04F2pB221*. The first entry * of a list of retrieved properties is returned. * * Returns: a udev_list_entry. */ _public_ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) { const char *key, *value; if (!hwdb || !modalias) { errno = EINVAL; return NULL; } udev_list_cleanup(&hwdb->properties_list); SD_HWDB_FOREACH_PROPERTY(hwdb->hwdb, modalias, key, value) { if (udev_list_entry_add(&hwdb->properties_list, key, value) == NULL) { errno = ENOMEM; return NULL; } } return udev_list_get_entry(&hwdb->properties_list); } systemd-229/src/libudev/libudev-list.c000066400000000000000000000243221265713322000200540ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "libudev-private.h" /** * SECTION:libudev-list * @short_description: list operation * * Libudev list operations. */ /** * udev_list_entry: * * Opaque object representing one entry in a list. An entry contains * contains a name, and optionally a value. */ struct udev_list_entry { struct udev_list_node node; struct udev_list *list; char *name; char *value; int num; }; /* the list's head points to itself if empty */ void udev_list_node_init(struct udev_list_node *list) { list->next = list; list->prev = list; } int udev_list_node_is_empty(struct udev_list_node *list) { return list->next == list; } static void udev_list_node_insert_between(struct udev_list_node *new, struct udev_list_node *prev, struct udev_list_node *next) { next->prev = new; new->next = next; new->prev = prev; prev->next = new; } void udev_list_node_append(struct udev_list_node *new, struct udev_list_node *list) { udev_list_node_insert_between(new, list->prev, list); } void udev_list_node_remove(struct udev_list_node *entry) { struct udev_list_node *prev = entry->prev; struct udev_list_node *next = entry->next; next->prev = prev; prev->next = next; entry->prev = NULL; entry->next = NULL; } /* return list entry which embeds this node */ static inline struct udev_list_entry *list_node_to_entry(struct udev_list_node *node) { return container_of(node, struct udev_list_entry, node); } void udev_list_init(struct udev *udev, struct udev_list *list, bool unique) { memzero(list, sizeof(struct udev_list)); list->udev = udev; list->unique = unique; udev_list_node_init(&list->node); } /* insert entry into a list as the last element */ static void udev_list_entry_append(struct udev_list_entry *new, struct udev_list *list) { /* inserting before the list head make the node the last node in the list */ udev_list_node_insert_between(&new->node, list->node.prev, &list->node); new->list = list; } /* insert entry into a list, before a given existing entry */ static void udev_list_entry_insert_before(struct udev_list_entry *new, struct udev_list_entry *entry) { udev_list_node_insert_between(&new->node, entry->node.prev, &entry->node); new->list = entry->list; } /* binary search in sorted array */ static int list_search(struct udev_list *list, const char *name) { unsigned int first, last; first = 0; last = list->entries_cur; while (first < last) { unsigned int i; int cmp; i = (first + last)/2; cmp = strcmp(name, list->entries[i]->name); if (cmp < 0) last = i; else if (cmp > 0) first = i+1; else return i; } /* not found, return negative insertion-index+1 */ return -(first+1); } struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *name, const char *value) { struct udev_list_entry *entry; int i = 0; if (list->unique) { /* lookup existing name or insertion-index */ i = list_search(list, name); if (i >= 0) { entry = list->entries[i]; free(entry->value); if (value == NULL) { entry->value = NULL; return entry; } entry->value = strdup(value); if (entry->value == NULL) return NULL; return entry; } } /* add new name */ entry = new0(struct udev_list_entry, 1); if (entry == NULL) return NULL; entry->name = strdup(name); if (entry->name == NULL) { free(entry); return NULL; } if (value != NULL) { entry->value = strdup(value); if (entry->value == NULL) { free(entry->name); free(entry); return NULL; } } if (list->unique) { /* allocate or enlarge sorted array if needed */ if (list->entries_cur >= list->entries_max) { struct udev_list_entry **entries; unsigned int add; add = list->entries_max; if (add < 1) add = 64; entries = realloc(list->entries, (list->entries_max + add) * sizeof(struct udev_list_entry *)); if (entries == NULL) { free(entry->name); free(entry->value); free(entry); return NULL; } list->entries = entries; list->entries_max += add; } /* the negative i returned the insertion index */ i = (-i)-1; /* insert into sorted list */ if ((unsigned int)i < list->entries_cur) udev_list_entry_insert_before(entry, list->entries[i]); else udev_list_entry_append(entry, list); /* insert into sorted array */ memmove(&list->entries[i+1], &list->entries[i], (list->entries_cur - i) * sizeof(struct udev_list_entry *)); list->entries[i] = entry; list->entries_cur++; } else { udev_list_entry_append(entry, list); } return entry; } void udev_list_entry_delete(struct udev_list_entry *entry) { if (entry->list->entries != NULL) { int i; struct udev_list *list = entry->list; /* remove entry from sorted array */ i = list_search(list, entry->name); if (i >= 0) { memmove(&list->entries[i], &list->entries[i+1], ((list->entries_cur-1) - i) * sizeof(struct udev_list_entry *)); list->entries_cur--; } } udev_list_node_remove(&entry->node); free(entry->name); free(entry->value); free(entry); } void udev_list_cleanup(struct udev_list *list) { struct udev_list_entry *entry_loop; struct udev_list_entry *entry_tmp; list->entries = mfree(list->entries); list->entries_cur = 0; list->entries_max = 0; udev_list_entry_foreach_safe(entry_loop, entry_tmp, udev_list_get_entry(list)) udev_list_entry_delete(entry_loop); } struct udev_list_entry *udev_list_get_entry(struct udev_list *list) { if (udev_list_node_is_empty(&list->node)) return NULL; return list_node_to_entry(list->node.next); } /** * udev_list_entry_get_next: * @list_entry: current entry * * Get the next entry from the list. * * Returns: udev_list_entry, #NULL if no more entries are available. */ _public_ struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) { struct udev_list_node *next; if (list_entry == NULL) return NULL; next = list_entry->node.next; /* empty list or no more entries */ if (next == &list_entry->list->node) return NULL; return list_node_to_entry(next); } /** * udev_list_entry_get_by_name: * @list_entry: current entry * @name: name string to match * * Lookup an entry in the list with a certain name. * * Returns: udev_list_entry, #NULL if no matching entry is found. */ _public_ struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name) { int i; if (list_entry == NULL) return NULL; if (!list_entry->list->unique) return NULL; i = list_search(list_entry->list, name); if (i < 0) return NULL; return list_entry->list->entries[i]; } /** * udev_list_entry_get_name: * @list_entry: current entry * * Get the name of a list entry. * * Returns: the name string of this entry. */ _public_ const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) { if (list_entry == NULL) return NULL; return list_entry->name; } /** * udev_list_entry_get_value: * @list_entry: current entry * * Get the value of list entry. * * Returns: the value string of this entry. */ _public_ const char *udev_list_entry_get_value(struct udev_list_entry *list_entry) { if (list_entry == NULL) return NULL; return list_entry->value; } int udev_list_entry_get_num(struct udev_list_entry *list_entry) { if (list_entry == NULL) return -EINVAL; return list_entry->num; } void udev_list_entry_set_num(struct udev_list_entry *list_entry, int num) { if (list_entry == NULL) return; list_entry->num = num; } systemd-229/src/libudev/libudev-monitor.c000066400000000000000000000716671265713322000206060ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include "libudev.h" #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "libudev-private.h" #include "missing.h" #include "mount-util.h" #include "socket-util.h" #include "string-util.h" /** * SECTION:libudev-monitor * @short_description: device event source * * Connects to a device event source. */ /** * udev_monitor: * * Opaque object handling an event source. */ struct udev_monitor { struct udev *udev; int refcount; int sock; union sockaddr_union snl; union sockaddr_union snl_trusted_sender; union sockaddr_union snl_destination; socklen_t addrlen; struct udev_list filter_subsystem_list; struct udev_list filter_tag_list; bool bound; }; enum udev_monitor_netlink_group { UDEV_MONITOR_NONE, UDEV_MONITOR_KERNEL, UDEV_MONITOR_UDEV, }; #define UDEV_MONITOR_MAGIC 0xfeedcafe struct udev_monitor_netlink_header { /* "libudev" prefix to distinguish libudev and kernel messages */ char prefix[8]; /* * magic to protect against daemon <-> library message format mismatch * used in the kernel from socket filter rules; needs to be stored in network order */ unsigned int magic; /* total length of header structure known to the sender */ unsigned int header_size; /* properties string buffer */ unsigned int properties_off; unsigned int properties_len; /* * hashes of primary device properties strings, to let libudev subscribers * use in-kernel socket filters; values need to be stored in network order */ unsigned int filter_subsystem_hash; unsigned int filter_devtype_hash; unsigned int filter_tag_bloom_hi; unsigned int filter_tag_bloom_lo; }; static struct udev_monitor *udev_monitor_new(struct udev *udev) { struct udev_monitor *udev_monitor; udev_monitor = new0(struct udev_monitor, 1); if (udev_monitor == NULL) return NULL; udev_monitor->refcount = 1; udev_monitor->udev = udev; udev_list_init(udev, &udev_monitor->filter_subsystem_list, false); udev_list_init(udev, &udev_monitor->filter_tag_list, true); return udev_monitor; } /* we consider udev running when /dev is on devtmpfs */ static bool udev_has_devtmpfs(struct udev *udev) { union file_handle_union h = FILE_HANDLE_INIT; _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX], *e; int mount_id; int r; r = name_to_handle_at(AT_FDCWD, "/dev", &h.handle, &mount_id, 0); if (r < 0) { if (errno != EOPNOTSUPP) log_debug_errno(errno, "name_to_handle_at on /dev: %m"); return false; } f = fopen("/proc/self/mountinfo", "re"); if (!f) return false; FOREACH_LINE(line, f, return false) { int mid; if (sscanf(line, "%i", &mid) != 1) continue; if (mid != mount_id) continue; e = strstr(line, " - "); if (!e) continue; /* accept any name that starts with the currently expected type */ if (startswith(e + 3, "devtmpfs")) return true; } return false; } static void monitor_set_nl_address(struct udev_monitor *udev_monitor) { union sockaddr_union snl; socklen_t addrlen; int r; assert(udev_monitor); /* get the address the kernel has assigned us * it is usually, but not necessarily the pid */ addrlen = sizeof(struct sockaddr_nl); r = getsockname(udev_monitor->sock, &snl.sa, &addrlen); if (r >= 0) udev_monitor->snl.nl.nl_pid = snl.nl.nl_pid; } struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const char *name, int fd) { struct udev_monitor *udev_monitor; unsigned int group; if (udev == NULL) return NULL; if (name == NULL) group = UDEV_MONITOR_NONE; else if (streq(name, "udev")) { /* * We do not support subscribing to uevents if no instance of * udev is running. Uevents would otherwise broadcast the * processing data of the host into containers, which is not * desired. * * Containers will currently not get any udev uevents, until * a supporting infrastructure is available. * * We do not set a netlink multicast group here, so the socket * will not receive any messages. */ if (access("/run/udev/control", F_OK) < 0 && !udev_has_devtmpfs(udev)) { log_debug("the udev service seems not to be active, disable the monitor"); group = UDEV_MONITOR_NONE; } else group = UDEV_MONITOR_UDEV; } else if (streq(name, "kernel")) group = UDEV_MONITOR_KERNEL; else return NULL; udev_monitor = udev_monitor_new(udev); if (udev_monitor == NULL) return NULL; if (fd < 0) { udev_monitor->sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); if (udev_monitor->sock < 0) { log_debug_errno(errno, "error getting socket: %m"); free(udev_monitor); return NULL; } } else { udev_monitor->bound = true; udev_monitor->sock = fd; monitor_set_nl_address(udev_monitor); } udev_monitor->snl.nl.nl_family = AF_NETLINK; udev_monitor->snl.nl.nl_groups = group; /* default destination for sending */ udev_monitor->snl_destination.nl.nl_family = AF_NETLINK; udev_monitor->snl_destination.nl.nl_groups = UDEV_MONITOR_UDEV; return udev_monitor; } /** * udev_monitor_new_from_netlink: * @udev: udev library context * @name: name of event source * * Create new udev monitor and connect to a specified event * source. Valid sources identifiers are "udev" and "kernel". * * Applications should usually not connect directly to the * "kernel" events, because the devices might not be useable * at that time, before udev has configured them, and created * device nodes. Accessing devices at the same time as udev, * might result in unpredictable behavior. The "udev" events * are sent out after udev has finished its event processing, * all rules have been processed, and needed device nodes are * created. * * The initial refcount is 1, and needs to be decremented to * release the resources of the udev monitor. * * Returns: a new udev monitor, or #NULL, in case of an error **/ _public_ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) { return udev_monitor_new_from_netlink_fd(udev, name, -1); } static inline void bpf_stmt(struct sock_filter *inss, unsigned int *i, unsigned short code, unsigned int data) { struct sock_filter *ins = &inss[*i]; ins->code = code; ins->k = data; (*i)++; } static inline void bpf_jmp(struct sock_filter *inss, unsigned int *i, unsigned short code, unsigned int data, unsigned short jt, unsigned short jf) { struct sock_filter *ins = &inss[*i]; ins->code = code; ins->jt = jt; ins->jf = jf; ins->k = data; (*i)++; } /** * udev_monitor_filter_update: * @udev_monitor: monitor * * Update the installed socket filter. This is only needed, * if the filter was removed or changed. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_monitor_filter_update(struct udev_monitor *udev_monitor) { struct sock_filter ins[512]; struct sock_fprog filter; unsigned int i; struct udev_list_entry *list_entry; int err; if (udev_list_get_entry(&udev_monitor->filter_subsystem_list) == NULL && udev_list_get_entry(&udev_monitor->filter_tag_list) == NULL) return 0; memzero(ins, sizeof(ins)); i = 0; /* load magic in A */ bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, magic)); /* jump if magic matches */ bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, UDEV_MONITOR_MAGIC, 1, 0); /* wrong magic, pass packet */ bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff); if (udev_list_get_entry(&udev_monitor->filter_tag_list) != NULL) { int tag_matches; /* count tag matches, to calculate end of tag match block */ tag_matches = 0; udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_tag_list)) tag_matches++; /* add all tags matches */ udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_tag_list)) { uint64_t tag_bloom_bits = util_string_bloom64(udev_list_entry_get_name(list_entry)); uint32_t tag_bloom_hi = tag_bloom_bits >> 32; uint32_t tag_bloom_lo = tag_bloom_bits & 0xffffffff; /* load device bloom bits in A */ bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_tag_bloom_hi)); /* clear bits (tag bits & bloom bits) */ bpf_stmt(ins, &i, BPF_ALU|BPF_AND|BPF_K, tag_bloom_hi); /* jump to next tag if it does not match */ bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, tag_bloom_hi, 0, 3); /* load device bloom bits in A */ bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_tag_bloom_lo)); /* clear bits (tag bits & bloom bits) */ bpf_stmt(ins, &i, BPF_ALU|BPF_AND|BPF_K, tag_bloom_lo); /* jump behind end of tag match block if tag matches */ tag_matches--; bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, tag_bloom_lo, 1 + (tag_matches * 6), 0); } /* nothing matched, drop packet */ bpf_stmt(ins, &i, BPF_RET|BPF_K, 0); } /* add all subsystem matches */ if (udev_list_get_entry(&udev_monitor->filter_subsystem_list) != NULL) { udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_subsystem_list)) { unsigned int hash = util_string_hash32(udev_list_entry_get_name(list_entry)); /* load device subsystem value in A */ bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_subsystem_hash)); if (udev_list_entry_get_value(list_entry) == NULL) { /* jump if subsystem does not match */ bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1); } else { /* jump if subsystem does not match */ bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 3); /* load device devtype value in A */ bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_devtype_hash)); /* jump if value does not match */ hash = util_string_hash32(udev_list_entry_get_value(list_entry)); bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1); } /* matched, pass packet */ bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff); if (i+1 >= ELEMENTSOF(ins)) return -E2BIG; } /* nothing matched, drop packet */ bpf_stmt(ins, &i, BPF_RET|BPF_K, 0); } /* matched, pass packet */ bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff); /* install filter */ memzero(&filter, sizeof(filter)); filter.len = i; filter.filter = ins; err = setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)); return err < 0 ? -errno : 0; } int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct udev_monitor *sender) { udev_monitor->snl_trusted_sender.nl.nl_pid = sender->snl.nl.nl_pid; return 0; } /** * udev_monitor_enable_receiving: * @udev_monitor: the monitor which should receive events * * Binds the @udev_monitor socket to the event source. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) { int err = 0; const int on = 1; udev_monitor_filter_update(udev_monitor); if (!udev_monitor->bound) { err = bind(udev_monitor->sock, &udev_monitor->snl.sa, sizeof(struct sockaddr_nl)); if (err == 0) udev_monitor->bound = true; } if (err >= 0) monitor_set_nl_address(udev_monitor); else return log_debug_errno(errno, "bind failed: %m"); /* enable receiving of sender credentials */ err = setsockopt(udev_monitor->sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); if (err < 0) log_debug_errno(errno, "setting SO_PASSCRED failed: %m"); return 0; } /** * udev_monitor_set_receive_buffer_size: * @udev_monitor: the monitor which should receive events * @size: the size in bytes * * Set the size of the kernel socket buffer. This call needs the * appropriate privileges to succeed. * * Returns: 0 on success, otherwise -1 on error. */ _public_ int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) { if (udev_monitor == NULL) return -EINVAL; return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size)); } int udev_monitor_disconnect(struct udev_monitor *udev_monitor) { int err; err = close(udev_monitor->sock); udev_monitor->sock = -1; return err < 0 ? -errno : 0; } /** * udev_monitor_ref: * @udev_monitor: udev monitor * * Take a reference of a udev monitor. * * Returns: the passed udev monitor **/ _public_ struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor) { if (udev_monitor == NULL) return NULL; udev_monitor->refcount++; return udev_monitor; } /** * udev_monitor_unref: * @udev_monitor: udev monitor * * Drop a reference of a udev monitor. If the refcount reaches zero, * the bound socket will be closed, and the resources of the monitor * will be released. * * Returns: #NULL **/ _public_ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) { if (udev_monitor == NULL) return NULL; udev_monitor->refcount--; if (udev_monitor->refcount > 0) return NULL; if (udev_monitor->sock >= 0) close(udev_monitor->sock); udev_list_cleanup(&udev_monitor->filter_subsystem_list); udev_list_cleanup(&udev_monitor->filter_tag_list); free(udev_monitor); return NULL; } /** * udev_monitor_get_udev: * @udev_monitor: udev monitor * * Retrieve the udev library context the monitor was created with. * * Returns: the udev library context **/ _public_ struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) { if (udev_monitor == NULL) return NULL; return udev_monitor->udev; } /** * udev_monitor_get_fd: * @udev_monitor: udev monitor * * Retrieve the socket file descriptor associated with the monitor. * * Returns: the socket file descriptor **/ _public_ int udev_monitor_get_fd(struct udev_monitor *udev_monitor) { if (udev_monitor == NULL) return -EINVAL; return udev_monitor->sock; } static int passes_filter(struct udev_monitor *udev_monitor, struct udev_device *udev_device) { struct udev_list_entry *list_entry; if (udev_list_get_entry(&udev_monitor->filter_subsystem_list) == NULL) goto tag; udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_subsystem_list)) { const char *subsys = udev_list_entry_get_name(list_entry); const char *dsubsys = udev_device_get_subsystem(udev_device); const char *devtype; const char *ddevtype; if (!streq(dsubsys, subsys)) continue; devtype = udev_list_entry_get_value(list_entry); if (devtype == NULL) goto tag; ddevtype = udev_device_get_devtype(udev_device); if (ddevtype == NULL) continue; if (streq(ddevtype, devtype)) goto tag; } return 0; tag: if (udev_list_get_entry(&udev_monitor->filter_tag_list) == NULL) return 1; udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_tag_list)) { const char *tag = udev_list_entry_get_name(list_entry); if (udev_device_has_tag(udev_device, tag)) return 1; } return 0; } /** * udev_monitor_receive_device: * @udev_monitor: udev monitor * * Receive data from the udev monitor socket, allocate a new udev * device, fill in the received data, and return the device. * * Only socket connections with uid=0 are accepted. * * The monitor socket is by default set to NONBLOCK. A variant of poll() on * the file descriptor returned by udev_monitor_get_fd() should to be used to * wake up when new devices arrive, or alternatively the file descriptor * switched into blocking mode. * * The initial refcount is 1, and needs to be decremented to * release the resources of the udev device. * * Returns: a new udev device, or #NULL, in case of an error **/ _public_ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) { struct udev_device *udev_device; struct msghdr smsg; struct iovec iov; char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; struct cmsghdr *cmsg; union sockaddr_union snl; struct ucred *cred; union { struct udev_monitor_netlink_header nlh; char raw[8192]; } buf; ssize_t buflen; ssize_t bufpos; bool is_initialized = false; retry: if (udev_monitor == NULL) return NULL; iov.iov_base = &buf; iov.iov_len = sizeof(buf); memzero(&smsg, sizeof(struct msghdr)); smsg.msg_iov = &iov; smsg.msg_iovlen = 1; smsg.msg_control = cred_msg; smsg.msg_controllen = sizeof(cred_msg); smsg.msg_name = &snl; smsg.msg_namelen = sizeof(snl); buflen = recvmsg(udev_monitor->sock, &smsg, 0); if (buflen < 0) { if (errno != EINTR) log_debug("unable to receive message"); return NULL; } if (buflen < 32 || (smsg.msg_flags & MSG_TRUNC)) { log_debug("invalid message length"); return NULL; } if (snl.nl.nl_groups == 0) { /* unicast message, check if we trust the sender */ if (udev_monitor->snl_trusted_sender.nl.nl_pid == 0 || snl.nl.nl_pid != udev_monitor->snl_trusted_sender.nl.nl_pid) { log_debug("unicast netlink message ignored"); return NULL; } } else if (snl.nl.nl_groups == UDEV_MONITOR_KERNEL) { if (snl.nl.nl_pid > 0) { log_debug("multicast kernel netlink message from PID %"PRIu32" ignored", snl.nl.nl_pid); return NULL; } } cmsg = CMSG_FIRSTHDR(&smsg); if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { log_debug("no sender credentials received, message ignored"); return NULL; } cred = (struct ucred *)CMSG_DATA(cmsg); if (cred->uid != 0) { log_debug("sender uid="UID_FMT", message ignored", cred->uid); return NULL; } if (memcmp(buf.raw, "libudev", 8) == 0) { /* udev message needs proper version magic */ if (buf.nlh.magic != htonl(UDEV_MONITOR_MAGIC)) { log_debug("unrecognized message signature (%x != %x)", buf.nlh.magic, htonl(UDEV_MONITOR_MAGIC)); return NULL; } if (buf.nlh.properties_off+32 > (size_t)buflen) { log_debug("message smaller than expected (%u > %zd)", buf.nlh.properties_off+32, buflen); return NULL; } bufpos = buf.nlh.properties_off; /* devices received from udev are always initialized */ is_initialized = true; } else { /* kernel message with header */ bufpos = strlen(buf.raw) + 1; if ((size_t)bufpos < sizeof("a@/d") || bufpos >= buflen) { log_debug("invalid message length"); return NULL; } /* check message header */ if (strstr(buf.raw, "@/") == NULL) { log_debug("unrecognized message header"); return NULL; } } udev_device = udev_device_new_from_nulstr(udev_monitor->udev, &buf.raw[bufpos], buflen - bufpos); if (!udev_device) { log_debug("could not create device: %m"); return NULL; } if (is_initialized) udev_device_set_is_initialized(udev_device); /* skip device, if it does not pass the current filter */ if (!passes_filter(udev_monitor, udev_device)) { struct pollfd pfd[1]; int rc; udev_device_unref(udev_device); /* if something is queued, get next device */ pfd[0].fd = udev_monitor->sock; pfd[0].events = POLLIN; rc = poll(pfd, 1, 0); if (rc > 0) goto retry; return NULL; } return udev_device; } int udev_monitor_send_device(struct udev_monitor *udev_monitor, struct udev_monitor *destination, struct udev_device *udev_device) { const char *buf, *val; ssize_t blen, count; struct udev_monitor_netlink_header nlh = { .prefix = "libudev", .magic = htonl(UDEV_MONITOR_MAGIC), .header_size = sizeof nlh, }; struct iovec iov[2] = { { .iov_base = &nlh, .iov_len = sizeof nlh }, }; struct msghdr smsg = { .msg_iov = iov, .msg_iovlen = 2, }; struct udev_list_entry *list_entry; uint64_t tag_bloom_bits; blen = udev_device_get_properties_monitor_buf(udev_device, &buf); if (blen < 32) { log_debug("device buffer is too small to contain a valid device"); return -EINVAL; } /* fill in versioned header */ val = udev_device_get_subsystem(udev_device); nlh.filter_subsystem_hash = htonl(util_string_hash32(val)); val = udev_device_get_devtype(udev_device); if (val != NULL) nlh.filter_devtype_hash = htonl(util_string_hash32(val)); /* add tag bloom filter */ tag_bloom_bits = 0; udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device)) tag_bloom_bits |= util_string_bloom64(udev_list_entry_get_name(list_entry)); if (tag_bloom_bits > 0) { nlh.filter_tag_bloom_hi = htonl(tag_bloom_bits >> 32); nlh.filter_tag_bloom_lo = htonl(tag_bloom_bits & 0xffffffff); } /* add properties list */ nlh.properties_off = iov[0].iov_len; nlh.properties_len = blen; iov[1].iov_base = (char *)buf; iov[1].iov_len = blen; /* * Use custom address for target, or the default one. * * If we send to a multicast group, we will get * ECONNREFUSED, which is expected. */ if (destination) smsg.msg_name = &destination->snl; else smsg.msg_name = &udev_monitor->snl_destination; smsg.msg_namelen = sizeof(struct sockaddr_nl); count = sendmsg(udev_monitor->sock, &smsg, 0); if (count < 0) { if (!destination && errno == ECONNREFUSED) { log_debug("passed device to netlink monitor %p", udev_monitor); return 0; } else return -errno; } log_debug("passed %zi byte device to netlink monitor %p", count, udev_monitor); return count; } /** * udev_monitor_filter_add_match_subsystem_devtype: * @udev_monitor: the monitor * @subsystem: the subsystem value to match the incoming devices against * @devtype: the devtype value to match the incoming devices against * * This filter is efficiently executed inside the kernel, and libudev subscribers * will usually not be woken up for devices which do not match. * * The filter must be installed before the monitor is switched to listening mode. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype) { if (udev_monitor == NULL) return -EINVAL; if (subsystem == NULL) return -EINVAL; if (udev_list_entry_add(&udev_monitor->filter_subsystem_list, subsystem, devtype) == NULL) return -ENOMEM; return 0; } /** * udev_monitor_filter_add_match_tag: * @udev_monitor: the monitor * @tag: the name of a tag * * This filter is efficiently executed inside the kernel, and libudev subscribers * will usually not be woken up for devices which do not match. * * The filter must be installed before the monitor is switched to listening mode. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag) { if (udev_monitor == NULL) return -EINVAL; if (tag == NULL) return -EINVAL; if (udev_list_entry_add(&udev_monitor->filter_tag_list, tag, NULL) == NULL) return -ENOMEM; return 0; } /** * udev_monitor_filter_remove: * @udev_monitor: monitor * * Remove all filters from monitor. * * Returns: 0 on success, otherwise a negative error value. */ _public_ int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) { static struct sock_fprog filter = { 0, NULL }; udev_list_cleanup(&udev_monitor->filter_subsystem_list); return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)); } systemd-229/src/libudev/libudev-private.h000066400000000000000000000163731265713322000205670ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #ifndef _LIBUDEV_PRIVATE_H_ #define _LIBUDEV_PRIVATE_H_ #include #include #include #include "libudev.h" #include "macro.h" #include "mkdir.h" #include "strxcpyx.h" #include "util.h" #define READ_END 0 #define WRITE_END 1 /* libudev.c */ int udev_get_rules_path(struct udev *udev, char **path[], usec_t *ts_usec[]); /* libudev-device.c */ struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr, ssize_t buflen); struct udev_device *udev_device_new_from_synthetic_event(struct udev *udev, const char *syspath, const char *action); struct udev_device *udev_device_shallow_clone(struct udev_device *old_device); struct udev_device *udev_device_clone_with_db(struct udev_device *old_device); int udev_device_copy_properties(struct udev_device *dst, struct udev_device *src); mode_t udev_device_get_devnode_mode(struct udev_device *udev_device); uid_t udev_device_get_devnode_uid(struct udev_device *udev_device); gid_t udev_device_get_devnode_gid(struct udev_device *udev_device); int udev_device_rename(struct udev_device *udev_device, const char *new_name); int udev_device_add_devlink(struct udev_device *udev_device, const char *devlink); void udev_device_cleanup_devlinks_list(struct udev_device *udev_device); int udev_device_add_property(struct udev_device *udev_device, const char *key, const char *value); char **udev_device_get_properties_envp(struct udev_device *udev_device); ssize_t udev_device_get_properties_monitor_buf(struct udev_device *udev_device, const char **buf); const char *udev_device_get_devpath_old(struct udev_device *udev_device); const char *udev_device_get_id_filename(struct udev_device *udev_device); void udev_device_set_is_initialized(struct udev_device *udev_device); int udev_device_add_tag(struct udev_device *udev_device, const char *tag); void udev_device_remove_tag(struct udev_device *udev_device, const char *tag); void udev_device_cleanup_tags_list(struct udev_device *udev_device); usec_t udev_device_get_usec_initialized(struct udev_device *udev_device); void udev_device_ensure_usec_initialized(struct udev_device *udev_device, struct udev_device *old_device); int udev_device_get_devlink_priority(struct udev_device *udev_device); int udev_device_set_devlink_priority(struct udev_device *udev_device, int prio); int udev_device_get_watch_handle(struct udev_device *udev_device); int udev_device_set_watch_handle(struct udev_device *udev_device, int handle); int udev_device_get_ifindex(struct udev_device *udev_device); void udev_device_set_info_loaded(struct udev_device *device); bool udev_device_get_db_persist(struct udev_device *udev_device); void udev_device_set_db_persist(struct udev_device *udev_device); void udev_device_read_db(struct udev_device *udev_device); /* libudev-device-private.c */ int udev_device_update_db(struct udev_device *udev_device); int udev_device_delete_db(struct udev_device *udev_device); int udev_device_tag_index(struct udev_device *dev, struct udev_device *dev_old, bool add); /* libudev-monitor.c - netlink/unix socket communication */ int udev_monitor_disconnect(struct udev_monitor *udev_monitor); int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct udev_monitor *sender); int udev_monitor_send_device(struct udev_monitor *udev_monitor, struct udev_monitor *destination, struct udev_device *udev_device); struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const char *name, int fd); /* libudev-list.c */ struct udev_list_node { struct udev_list_node *next, *prev; }; struct udev_list { struct udev *udev; struct udev_list_node node; struct udev_list_entry **entries; unsigned int entries_cur; unsigned int entries_max; bool unique; }; void udev_list_node_init(struct udev_list_node *list); int udev_list_node_is_empty(struct udev_list_node *list); void udev_list_node_append(struct udev_list_node *new, struct udev_list_node *list); void udev_list_node_remove(struct udev_list_node *entry); #define udev_list_node_foreach(node, list) \ for (node = (list)->next; \ node != list; \ node = (node)->next) #define udev_list_node_foreach_safe(node, tmp, list) \ for (node = (list)->next, tmp = (node)->next; \ node != list; \ node = tmp, tmp = (tmp)->next) void udev_list_init(struct udev *udev, struct udev_list *list, bool unique); void udev_list_cleanup(struct udev_list *list); struct udev_list_entry *udev_list_get_entry(struct udev_list *list); struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *name, const char *value); void udev_list_entry_delete(struct udev_list_entry *entry); int udev_list_entry_get_num(struct udev_list_entry *list_entry); void udev_list_entry_set_num(struct udev_list_entry *list_entry, int num); #define udev_list_entry_foreach_safe(entry, tmp, first) \ for (entry = first, tmp = udev_list_entry_get_next(entry); \ entry != NULL; \ entry = tmp, tmp = udev_list_entry_get_next(tmp)) /* libudev-queue.c */ unsigned long long int udev_get_kernel_seqnum(struct udev *udev); int udev_queue_read_seqnum(FILE *queue_file, unsigned long long int *seqnum); ssize_t udev_queue_read_devpath(FILE *queue_file, char *devpath, size_t size); ssize_t udev_queue_skip_devpath(FILE *queue_file); /* libudev-queue-private.c */ struct udev_queue_export *udev_queue_export_new(struct udev *udev); struct udev_queue_export *udev_queue_export_unref(struct udev_queue_export *udev_queue_export); void udev_queue_export_cleanup(struct udev_queue_export *udev_queue_export); int udev_queue_export_device_queued(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device); int udev_queue_export_device_finished(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device); /* libudev-util.c */ #define UTIL_PATH_SIZE 1024 #define UTIL_NAME_SIZE 512 #define UTIL_LINE_SIZE 16384 #define UDEV_ALLOWED_CHARS_INPUT "/ $%?," int util_log_priority(const char *priority); size_t util_path_encode(const char *src, char *dest, size_t size); void util_remove_trailing_chars(char *path, char c); int util_replace_whitespace(const char *str, char *to, size_t len); int util_replace_chars(char *str, const char *white); unsigned int util_string_hash32(const char *key); uint64_t util_string_bloom64(const char *str); /* libudev-util-private.c */ int util_resolve_subsys_kernel(struct udev *udev, const char *string, char *result, size_t maxsize, int read_value); #endif systemd-229/src/libudev/libudev-queue.c000066400000000000000000000146761265713322000202400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers Copyright 2009 Alan Jenkins systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "io-util.h" #include "libudev-private.h" /** * SECTION:libudev-queue * @short_description: access to currently active events * * This exports the current state of the udev processing queue. */ /** * udev_queue: * * Opaque object representing the current event queue in the udev daemon. */ struct udev_queue { struct udev *udev; int refcount; int fd; }; /** * udev_queue_new: * @udev: udev library context * * The initial refcount is 1, and needs to be decremented to * release the resources of the udev queue context. * * Returns: the udev queue context, or #NULL on error. **/ _public_ struct udev_queue *udev_queue_new(struct udev *udev) { struct udev_queue *udev_queue; if (udev == NULL) return NULL; udev_queue = new0(struct udev_queue, 1); if (udev_queue == NULL) return NULL; udev_queue->refcount = 1; udev_queue->udev = udev; udev_queue->fd = -1; return udev_queue; } /** * udev_queue_ref: * @udev_queue: udev queue context * * Take a reference of a udev queue context. * * Returns: the same udev queue context. **/ _public_ struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue) { if (udev_queue == NULL) return NULL; udev_queue->refcount++; return udev_queue; } /** * udev_queue_unref: * @udev_queue: udev queue context * * Drop a reference of a udev queue context. If the refcount reaches zero, * the resources of the queue context will be released. * * Returns: #NULL **/ _public_ struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue) { if (udev_queue == NULL) return NULL; udev_queue->refcount--; if (udev_queue->refcount > 0) return NULL; safe_close(udev_queue->fd); free(udev_queue); return NULL; } /** * udev_queue_get_udev: * @udev_queue: udev queue context * * Retrieve the udev library context the queue context was created with. * * Returns: the udev library context. **/ _public_ struct udev *udev_queue_get_udev(struct udev_queue *udev_queue) { if (udev_queue == NULL) return NULL; return udev_queue->udev; } /** * udev_queue_get_kernel_seqnum: * @udev_queue: udev queue context * * This function is deprecated. * * Returns: 0. **/ _public_ unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) { return 0; } /** * udev_queue_get_udev_seqnum: * @udev_queue: udev queue context * * This function is deprecated. * * Returns: 0. **/ _public_ unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) { return 0; } /** * udev_queue_get_udev_is_active: * @udev_queue: udev queue context * * Check if udev is active on the system. * * Returns: a flag indicating if udev is active. **/ _public_ int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) { return access("/run/udev/control", F_OK) >= 0; } /** * udev_queue_get_queue_is_empty: * @udev_queue: udev queue context * * Check if udev is currently processing any events. * * Returns: a flag indicating if udev is currently handling events. **/ _public_ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) { return access("/run/udev/queue", F_OK) < 0; } /** * udev_queue_get_seqnum_sequence_is_finished: * @udev_queue: udev queue context * @start: first event sequence number * @end: last event sequence number * * This function is deprecated, it just returns the result of * udev_queue_get_queue_is_empty(). * * Returns: a flag indicating if udev is currently handling events. **/ _public_ int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue, unsigned long long int start, unsigned long long int end) { return udev_queue_get_queue_is_empty(udev_queue); } /** * udev_queue_get_seqnum_is_finished: * @udev_queue: udev queue context * @seqnum: sequence number * * This function is deprecated, it just returns the result of * udev_queue_get_queue_is_empty(). * * Returns: a flag indicating if udev is currently handling events. **/ _public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) { return udev_queue_get_queue_is_empty(udev_queue); } /** * udev_queue_get_queued_list_entry: * @udev_queue: udev queue context * * This function is deprecated. * * Returns: NULL. **/ _public_ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) { return NULL; } /** * udev_queue_get_fd: * @udev_queue: udev queue context * * Returns: a file descriptor to watch for a queue to become empty. */ _public_ int udev_queue_get_fd(struct udev_queue *udev_queue) { int fd; int r; if (udev_queue->fd >= 0) return udev_queue->fd; fd = inotify_init1(IN_CLOEXEC); if (fd < 0) return -errno; r = inotify_add_watch(fd, "/run/udev" , IN_DELETE); if (r < 0) { r = -errno; close(fd); return r; } udev_queue->fd = fd; return fd; } /** * udev_queue_flush: * @udev_queue: udev queue context * * Returns: the result of clearing the watch for queue changes. */ _public_ int udev_queue_flush(struct udev_queue *udev_queue) { if (udev_queue->fd < 0) return -EINVAL; return flush_fd(udev_queue->fd); } systemd-229/src/libudev/libudev-util.c000066400000000000000000000170531265713322000200610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "libudev.h" #include "MurmurHash2.h" #include "device-nodes.h" #include "libudev-private.h" #include "syslog-util.h" #include "utf8.h" /** * SECTION:libudev-util * @short_description: utils * * Utilities useful when dealing with devices and device node names. */ /* handle "[/]" format */ int util_resolve_subsys_kernel(struct udev *udev, const char *string, char *result, size_t maxsize, int read_value) { char temp[UTIL_PATH_SIZE]; char *subsys; char *sysname; struct udev_device *dev; char *attr; if (string[0] != '[') return -1; strscpy(temp, sizeof(temp), string); subsys = &temp[1]; sysname = strchr(subsys, '/'); if (sysname == NULL) return -1; sysname[0] = '\0'; sysname = &sysname[1]; attr = strchr(sysname, ']'); if (attr == NULL) return -1; attr[0] = '\0'; attr = &attr[1]; if (attr[0] == '/') attr = &attr[1]; if (attr[0] == '\0') attr = NULL; if (read_value && attr == NULL) return -1; dev = udev_device_new_from_subsystem_sysname(udev, subsys, sysname); if (dev == NULL) return -1; if (read_value) { const char *val; val = udev_device_get_sysattr_value(dev, attr); if (val != NULL) strscpy(result, maxsize, val); else result[0] = '\0'; log_debug("value '[%s/%s]%s' is '%s'", subsys, sysname, attr, result); } else { size_t l; char *s; s = result; l = strpcpyl(&s, maxsize, udev_device_get_syspath(dev), NULL); if (attr != NULL) strpcpyl(&s, l, "/", attr, NULL); log_debug("path '[%s/%s]%s' is '%s'", subsys, sysname, attr, result); } udev_device_unref(dev); return 0; } int util_log_priority(const char *priority) { char *endptr; int prio; prio = strtoul(priority, &endptr, 10); if (endptr[0] == '\0' || isspace(endptr[0])) { if (prio >= 0 && prio <= 7) return prio; else return -ERANGE; } return log_level_from_string(priority); } size_t util_path_encode(const char *src, char *dest, size_t size) { size_t i, j; for (i = 0, j = 0; src[i] != '\0'; i++) { if (src[i] == '/') { if (j+4 >= size) { j = 0; break; } memcpy(&dest[j], "\\x2f", 4); j += 4; } else if (src[i] == '\\') { if (j+4 >= size) { j = 0; break; } memcpy(&dest[j], "\\x5c", 4); j += 4; } else { if (j+1 >= size) { j = 0; break; } dest[j] = src[i]; j++; } } dest[j] = '\0'; return j; } void util_remove_trailing_chars(char *path, char c) { size_t len; if (path == NULL) return; len = strlen(path); while (len > 0 && path[len-1] == c) path[--len] = '\0'; } int util_replace_whitespace(const char *str, char *to, size_t len) { size_t i, j; /* strip trailing whitespace */ len = strnlen(str, len); while (len && isspace(str[len-1])) len--; /* strip leading whitespace */ i = 0; while ((i < len) && isspace(str[i])) i++; j = 0; while (i < len) { /* substitute multiple whitespace with a single '_' */ if (isspace(str[i])) { while (isspace(str[i])) i++; to[j++] = '_'; } to[j++] = str[i++]; } to[j] = '\0'; return 0; } /* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */ int util_replace_chars(char *str, const char *white) { size_t i = 0; int replaced = 0; while (str[i] != '\0') { int len; if (whitelisted_char_for_devnode(str[i], white)) { i++; continue; } /* accept hex encoding */ if (str[i] == '\\' && str[i+1] == 'x') { i += 2; continue; } /* accept valid utf8 */ len = utf8_encoded_valid_unichar(&str[i]); if (len > 1) { i += len; continue; } /* if space is allowed, replace whitespace with ordinary space */ if (isspace(str[i]) && white != NULL && strchr(white, ' ') != NULL) { str[i] = ' '; i++; replaced++; continue; } /* everything else is replaced with '_' */ str[i] = '_'; i++; replaced++; } return replaced; } /** * udev_util_encode_string: * @str: input string to be encoded * @str_enc: output string to store the encoded input string * @len: maximum size of the output string, which may be * four times as long as the input string * * Encode all potentially unsafe characters of a string to the * corresponding 2 char hex value prefixed by '\x'. * * Returns: 0 if the entire string was copied, non-zero otherwise. **/ _public_ int udev_util_encode_string(const char *str, char *str_enc, size_t len) { return encode_devnode_name(str, str_enc, len); } unsigned int util_string_hash32(const char *str) { return MurmurHash2(str, strlen(str), 0); } /* get a bunch of bit numbers out of the hash, and set the bits in our bit field */ uint64_t util_string_bloom64(const char *str) { uint64_t bits = 0; unsigned int hash = util_string_hash32(str); bits |= 1LLU << (hash & 63); bits |= 1LLU << ((hash >> 6) & 63); bits |= 1LLU << ((hash >> 12) & 63); bits |= 1LLU << ((hash >> 18) & 63); return bits; } systemd-229/src/libudev/libudev.c000066400000000000000000000162121265713322000171020ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2014 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "libudev.h" #include "alloc-util.h" #include "fd-util.h" #include "libudev-private.h" #include "missing.h" #include "string-util.h" /** * SECTION:libudev * @short_description: libudev context * * The context contains the default values read from the udev config file, * and is passed to all library operations. */ /** * udev: * * Opaque object representing the library context. */ struct udev { int refcount; void (*log_fn)(struct udev *udev, int priority, const char *file, int line, const char *fn, const char *format, va_list args); void *userdata; }; /** * udev_get_userdata: * @udev: udev library context * * Retrieve stored data pointer from library context. This might be useful * to access from callbacks. * * Returns: stored userdata **/ _public_ void *udev_get_userdata(struct udev *udev) { if (udev == NULL) return NULL; return udev->userdata; } /** * udev_set_userdata: * @udev: udev library context * @userdata: data pointer * * Store custom @userdata in the library context. **/ _public_ void udev_set_userdata(struct udev *udev, void *userdata) { if (udev == NULL) return; udev->userdata = userdata; } /** * udev_new: * * Create udev library context. This reads the udev configuration * file, and fills in the default values. * * The initial refcount is 1, and needs to be decremented to * release the resources of the udev library context. * * Returns: a new udev library context **/ _public_ struct udev *udev_new(void) { struct udev *udev; _cleanup_fclose_ FILE *f = NULL; udev = new0(struct udev, 1); if (udev == NULL) return NULL; udev->refcount = 1; f = fopen("/etc/udev/udev.conf", "re"); if (f != NULL) { char line[UTIL_LINE_SIZE]; unsigned line_nr = 0; while (fgets(line, sizeof(line), f)) { size_t len; char *key; char *val; line_nr++; /* find key */ key = line; while (isspace(key[0])) key++; /* comment or empty line */ if (key[0] == '#' || key[0] == '\0') continue; /* split key/value */ val = strchr(key, '='); if (val == NULL) { log_debug("/etc/udev/udev.conf:%u: missing assignment, skipping line.", line_nr); continue; } val[0] = '\0'; val++; /* find value */ while (isspace(val[0])) val++; /* terminate key */ len = strlen(key); if (len == 0) continue; while (isspace(key[len-1])) len--; key[len] = '\0'; /* terminate value */ len = strlen(val); if (len == 0) continue; while (isspace(val[len-1])) len--; val[len] = '\0'; if (len == 0) continue; /* unquote */ if (val[0] == '"' || val[0] == '\'') { if (val[len-1] != val[0]) { log_debug("/etc/udev/udev.conf:%u: inconsistent quoting, skipping line.", line_nr); continue; } val[len-1] = '\0'; val++; } if (streq(key, "udev_log")) { int prio; prio = util_log_priority(val); if (prio < 0) log_debug("/etc/udev/udev.conf:%u: invalid log level '%s', ignoring.", line_nr, val); else log_set_max_level(prio); continue; } } } return udev; } /** * udev_ref: * @udev: udev library context * * Take a reference of the udev library context. * * Returns: the passed udev library context **/ _public_ struct udev *udev_ref(struct udev *udev) { if (udev == NULL) return NULL; udev->refcount++; return udev; } /** * udev_unref: * @udev: udev library context * * Drop a reference of the udev library context. If the refcount * reaches zero, the resources of the context will be released. * * Returns: the passed udev library context if it has still an active reference, or #NULL otherwise. **/ _public_ struct udev *udev_unref(struct udev *udev) { if (udev == NULL) return NULL; udev->refcount--; if (udev->refcount > 0) return udev; free(udev); return NULL; } /** * udev_set_log_fn: * @udev: udev library context * @log_fn: function to be called for log messages * * This function is deprecated. * **/ _public_ void udev_set_log_fn(struct udev *udev, void (*log_fn)(struct udev *udev, int priority, const char *file, int line, const char *fn, const char *format, va_list args)) { return; } /** * udev_get_log_priority: * @udev: udev library context * * This function is deprecated. * **/ _public_ int udev_get_log_priority(struct udev *udev) { return log_get_max_level(); } /** * udev_set_log_priority: * @udev: udev library context * @priority: the new log priority * * This function is deprecated. * **/ _public_ void udev_set_log_priority(struct udev *udev, int priority) { log_set_max_level(priority); } systemd-229/src/libudev/libudev.h000066400000000000000000000240171265713322000171110ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #ifndef _LIBUDEV_H_ #define _LIBUDEV_H_ #include #include #ifdef __cplusplus extern "C" { #endif /* * udev - library context * * reads the udev config and system environment * allows custom logging */ struct udev; struct udev *udev_ref(struct udev *udev); struct udev *udev_unref(struct udev *udev); struct udev *udev_new(void); void udev_set_log_fn(struct udev *udev, void (*log_fn)(struct udev *udev, int priority, const char *file, int line, const char *fn, const char *format, va_list args)) __attribute__ ((deprecated)); int udev_get_log_priority(struct udev *udev) __attribute__ ((deprecated)); void udev_set_log_priority(struct udev *udev, int priority) __attribute__ ((deprecated)); void *udev_get_userdata(struct udev *udev); void udev_set_userdata(struct udev *udev, void *userdata); /* * udev_list * * access to libudev generated lists */ struct udev_list_entry; struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry); struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name); const char *udev_list_entry_get_name(struct udev_list_entry *list_entry); const char *udev_list_entry_get_value(struct udev_list_entry *list_entry); /** * udev_list_entry_foreach: * @list_entry: entry to store the current position * @first_entry: first entry to start with * * Helper to iterate over all entries of a list. */ #define udev_list_entry_foreach(list_entry, first_entry) \ for (list_entry = first_entry; \ list_entry != NULL; \ list_entry = udev_list_entry_get_next(list_entry)) /* * udev_device * * access to sysfs/kernel devices */ struct udev_device; struct udev_device *udev_device_ref(struct udev_device *udev_device); struct udev_device *udev_device_unref(struct udev_device *udev_device); struct udev *udev_device_get_udev(struct udev_device *udev_device); struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath); struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum); struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname); struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id); struct udev_device *udev_device_new_from_environment(struct udev *udev); /* udev_device_get_parent_*() does not take a reference on the returned device, it is automatically unref'd with the parent */ struct udev_device *udev_device_get_parent(struct udev_device *udev_device); struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype); /* retrieve device properties */ const char *udev_device_get_devpath(struct udev_device *udev_device); const char *udev_device_get_subsystem(struct udev_device *udev_device); const char *udev_device_get_devtype(struct udev_device *udev_device); const char *udev_device_get_syspath(struct udev_device *udev_device); const char *udev_device_get_sysname(struct udev_device *udev_device); const char *udev_device_get_sysnum(struct udev_device *udev_device); const char *udev_device_get_devnode(struct udev_device *udev_device); int udev_device_get_is_initialized(struct udev_device *udev_device); struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device); struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device); struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device); struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device); const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key); const char *udev_device_get_driver(struct udev_device *udev_device); dev_t udev_device_get_devnum(struct udev_device *udev_device); const char *udev_device_get_action(struct udev_device *udev_device); unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device); unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device); const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr); int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value); int udev_device_has_tag(struct udev_device *udev_device, const char *tag); /* * udev_monitor * * access to kernel uevents and udev events */ struct udev_monitor; struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor); struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor); struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor); /* kernel and udev generated events over netlink */ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name); /* bind socket */ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor); int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size); int udev_monitor_get_fd(struct udev_monitor *udev_monitor); struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor); /* in-kernel socket filters to select messages that get delivered to a listener */ int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype); int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag); int udev_monitor_filter_update(struct udev_monitor *udev_monitor); int udev_monitor_filter_remove(struct udev_monitor *udev_monitor); /* * udev_enumerate * * search sysfs for specific devices and provide a sorted list */ struct udev_enumerate; struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate); struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate); struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate); struct udev_enumerate *udev_enumerate_new(struct udev *udev); /* device properties filter */ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem); int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem); int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value); int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value); int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value); int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname); int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag); int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent); int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate); int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath); /* run enumeration with active filters */ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate); int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate); /* return device list */ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate); /* * udev_queue * * access to the currently running udev events */ struct udev_queue; struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue); struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue); struct udev *udev_queue_get_udev(struct udev_queue *udev_queue); struct udev_queue *udev_queue_new(struct udev *udev); unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) __attribute__ ((deprecated)); unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) __attribute__ ((deprecated)); int udev_queue_get_udev_is_active(struct udev_queue *udev_queue); int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue); int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) __attribute__ ((deprecated)); int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue, unsigned long long int start, unsigned long long int end) __attribute__ ((deprecated)); int udev_queue_get_fd(struct udev_queue *udev_queue); int udev_queue_flush(struct udev_queue *udev_queue); struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) __attribute__ ((deprecated)); /* * udev_hwdb * * access to the static hardware properties database */ struct udev_hwdb; struct udev_hwdb *udev_hwdb_new(struct udev *udev); struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb); struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb); struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags); /* * udev_util * * udev specific utilities */ int udev_util_encode_string(const char *str, char *str_enc, size_t len); #ifdef __cplusplus } /* extern "C" */ #endif #endif systemd-229/src/libudev/libudev.pc.in000066400000000000000000000010001265713322000176540ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libudev Description: Library to access udev device information Version: @VERSION@ Libs: -L${libdir} -ludev Cflags: -I${includedir} systemd-229/src/libudev/libudev.sym000066400000000000000000000071331265713322000174720ustar00rootroot00000000000000/*** This file is part of systemd. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. ***/ LIBUDEV_183 { global: udev_device_get_action; udev_device_get_devlinks_list_entry; udev_device_get_devnode; udev_device_get_devnum; udev_device_get_devpath; udev_device_get_devtype; udev_device_get_driver; udev_device_get_is_initialized; udev_device_get_parent; udev_device_get_parent_with_subsystem_devtype; udev_device_get_properties_list_entry; udev_device_get_property_value; udev_device_get_seqnum; udev_device_get_subsystem; udev_device_get_sysattr_list_entry; udev_device_get_sysattr_value; udev_device_get_sysname; udev_device_get_sysnum; udev_device_get_syspath; udev_device_get_tags_list_entry; udev_device_get_udev; udev_device_get_usec_since_initialized; udev_device_has_tag; udev_device_new_from_devnum; udev_device_new_from_environment; udev_device_new_from_subsystem_sysname; udev_device_new_from_syspath; udev_device_ref; udev_device_unref; udev_enumerate_add_match_is_initialized; udev_enumerate_add_match_parent; udev_enumerate_add_match_property; udev_enumerate_add_match_subsystem; udev_enumerate_add_match_sysattr; udev_enumerate_add_match_sysname; udev_enumerate_add_match_tag; udev_enumerate_add_nomatch_subsystem; udev_enumerate_add_nomatch_sysattr; udev_enumerate_add_syspath; udev_enumerate_get_list_entry; udev_enumerate_get_udev; udev_enumerate_new; udev_enumerate_ref; udev_enumerate_scan_devices; udev_enumerate_scan_subsystems; udev_enumerate_unref; udev_get_log_priority; udev_get_userdata; udev_list_entry_get_by_name; udev_list_entry_get_name; udev_list_entry_get_next; udev_list_entry_get_value; udev_monitor_enable_receiving; udev_monitor_filter_add_match_subsystem_devtype; udev_monitor_filter_add_match_tag; udev_monitor_filter_remove; udev_monitor_filter_update; udev_monitor_get_fd; udev_monitor_get_udev; udev_monitor_new_from_netlink; udev_monitor_receive_device; udev_monitor_ref; udev_monitor_set_receive_buffer_size; udev_monitor_unref; udev_new; udev_queue_get_kernel_seqnum; udev_queue_get_queue_is_empty; udev_queue_get_queued_list_entry; udev_queue_get_seqnum_is_finished; udev_queue_get_seqnum_sequence_is_finished; udev_queue_get_udev; udev_queue_get_udev_is_active; udev_queue_get_udev_seqnum; udev_queue_new; udev_queue_ref; udev_queue_unref; udev_ref; udev_set_log_fn; udev_set_log_priority; udev_set_userdata; udev_unref; udev_util_encode_string; local: *; }; LIBUDEV_189 { global: udev_device_new_from_device_id; } LIBUDEV_183; LIBUDEV_196 { global: udev_hwdb_new; udev_hwdb_ref; udev_hwdb_unref; udev_hwdb_get_properties_list_entry; } LIBUDEV_189; LIBUDEV_199 { global: udev_device_set_sysattr_value; } LIBUDEV_196; LIBUDEV_215 { global: udev_queue_flush; udev_queue_get_fd; } LIBUDEV_199; systemd-229/src/locale/000077500000000000000000000000001265713322000151075ustar00rootroot00000000000000systemd-229/src/locale/.gitignore000066400000000000000000000000371265713322000170770ustar00rootroot00000000000000org.freedesktop.locale1.policy systemd-229/src/locale/Makefile000077700000000000000000000000001265713322000204152../Makefileustar00rootroot00000000000000systemd-229/src/locale/kbd-model-map000066400000000000000000000067541265713322000174570ustar00rootroot00000000000000# Generated from system-config-keyboard's model list # consolelayout xlayout xmodel xvariant xoptions sg ch pc105 de_nodeadkeys terminate:ctrl_alt_bksp nl nl pc105 - terminate:ctrl_alt_bksp mk-utf mk,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll trq tr pc105 - terminate:ctrl_alt_bksp uk gb pc105 - terminate:ctrl_alt_bksp is-latin1 is pc105 - terminate:ctrl_alt_bksp de de pc105 - terminate:ctrl_alt_bksp la-latin1 latam pc105 - terminate:ctrl_alt_bksp us us pc105+inet - terminate:ctrl_alt_bksp ko kr pc105 - terminate:ctrl_alt_bksp ro-std ro pc105 std terminate:ctrl_alt_bksp de-latin1 de pc105 - terminate:ctrl_alt_bksp slovene si pc105 - terminate:ctrl_alt_bksp hu101 hu pc105 qwerty terminate:ctrl_alt_bksp jp106 jp jp106 - terminate:ctrl_alt_bksp croat hr pc105 - terminate:ctrl_alt_bksp it2 it pc105 - terminate:ctrl_alt_bksp hu hu pc105 - terminate:ctrl_alt_bksp sr-latin rs pc105 latin terminate:ctrl_alt_bksp fi fi pc105 - terminate:ctrl_alt_bksp fr_CH ch pc105 fr terminate:ctrl_alt_bksp dk-latin1 dk pc105 - terminate:ctrl_alt_bksp fr fr pc105 - terminate:ctrl_alt_bksp it it pc105 - terminate:ctrl_alt_bksp ua-utf ua,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll fr-latin1 fr pc105 - terminate:ctrl_alt_bksp sg-latin1 ch pc105 de_nodeadkeys terminate:ctrl_alt_bksp be-latin1 be pc105 - terminate:ctrl_alt_bksp dk dk pc105 - terminate:ctrl_alt_bksp fr-pc fr pc105 - terminate:ctrl_alt_bksp bg_pho-utf8 bg,us pc105 ,phonetic terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll it-ibm it pc105 - terminate:ctrl_alt_bksp cz-us-qwertz cz,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll br-abnt2 br abnt2 - terminate:ctrl_alt_bksp ro ro pc105 - terminate:ctrl_alt_bksp us-acentos us pc105 intl terminate:ctrl_alt_bksp pt-latin1 pt pc105 - terminate:ctrl_alt_bksp ro-std-cedilla ro pc105 std_cedilla terminate:ctrl_alt_bksp tj_alt-UTF8 tj pc105 - terminate:ctrl_alt_bksp de-latin1-nodeadkeys de pc105 nodeadkeys terminate:ctrl_alt_bksp no no pc105 - terminate:ctrl_alt_bksp bg_bds-utf8 bg,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll dvorak us pc105 dvorak terminate:ctrl_alt_bksp dvorak us pc105 dvorak-alt-intl terminate:ctrl_alt_bksp ru ru,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll cz-lat2 cz pc105 qwerty terminate:ctrl_alt_bksp pl2 pl pc105 - terminate:ctrl_alt_bksp es es pc105 - terminate:ctrl_alt_bksp ro-cedilla ro pc105 cedilla terminate:ctrl_alt_bksp ie ie pc105 - terminate:ctrl_alt_bksp et ee pc105 - terminate:ctrl_alt_bksp sk-qwerty sk pc105 - terminate:ctrl_alt_bksp,qwerty sk-qwertz sk pc105 - terminate:ctrl_alt_bksp fr-latin9 fr pc105 latin9 terminate:ctrl_alt_bksp fr_CH-latin1 ch pc105 fr terminate:ctrl_alt_bksp cf ca pc105 - terminate:ctrl_alt_bksp sv-latin1 se pc105 - terminate:ctrl_alt_bksp sr-cy rs pc105 - terminate:ctrl_alt_bksp gr gr,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll by by,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll il il pc105 - terminate:ctrl_alt_bksp kazakh kz,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll lt.baltic lt pc105 - terminate:ctrl_alt_bksp lt.l4 lt pc105 - terminate:ctrl_alt_bksp lt lt pc105 - terminate:ctrl_alt_bksp khmer kh,us pc105 - terminate:ctrl_alt_bksp systemd-229/src/locale/language-fallback-map000066400000000000000000000002221265713322000211210ustar00rootroot00000000000000csb_PL csb:pl en_AU en_AU:en_GB en_IE en_IE:en_GB en_NZ en_NZ:en_GB en_ZA en_ZA:en_GB it_CH it_CH:it_IT mai_IN mai:hi nds_DE nds:de szl_PL szl:pl systemd-229/src/locale/localectl.c000066400000000000000000000537111265713322000172240ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering Copyright 2013 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "sd-bus.h" #include "bus-error.h" #include "bus-util.h" #include "def.h" #include "fd-util.h" #include "fileio.h" #include "locale-util.h" #include "pager.h" #include "set.h" #include "spawn-polkit-agent.h" #include "strv.h" #include "util.h" #include "virt.h" static bool arg_no_pager = false; static bool arg_ask_password = true; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static char *arg_host = NULL; static bool arg_convert = true; static void pager_open_if_enabled(void) { if (arg_no_pager) return; pager_open(false); } static void polkit_agent_open_if_enabled(void) { /* Open the polkit agent as a child process if necessary */ if (!arg_ask_password) return; if (arg_transport != BUS_TRANSPORT_LOCAL) return; polkit_agent_open(); } typedef struct StatusInfo { char **locale; char *vconsole_keymap; char *vconsole_keymap_toggle; char *x11_layout; char *x11_model; char *x11_variant; char *x11_options; } StatusInfo; static void status_info_clear(StatusInfo *info) { if (info) { strv_free(info->locale); free(info->vconsole_keymap); free(info->vconsole_keymap_toggle); free(info->x11_layout); free(info->x11_model); free(info->x11_variant); free(info->x11_options); zero(*info); } } static void print_overridden_variables(void) { int r; char *variables[_VARIABLE_LC_MAX] = {}; LocaleVariable j; bool print_warning = true; if (detect_container() > 0 || arg_host) return; r = parse_env_file("/proc/cmdline", WHITESPACE, "locale.LANG", &variables[VARIABLE_LANG], "locale.LANGUAGE", &variables[VARIABLE_LANGUAGE], "locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE], "locale.LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC], "locale.LC_TIME", &variables[VARIABLE_LC_TIME], "locale.LC_COLLATE", &variables[VARIABLE_LC_COLLATE], "locale.LC_MONETARY", &variables[VARIABLE_LC_MONETARY], "locale.LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES], "locale.LC_PAPER", &variables[VARIABLE_LC_PAPER], "locale.LC_NAME", &variables[VARIABLE_LC_NAME], "locale.LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS], "locale.LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE], "locale.LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT], "locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION], NULL); if (r < 0 && r != -ENOENT) { log_warning_errno(r, "Failed to read /proc/cmdline: %m"); goto finish; } for (j = 0; j < _VARIABLE_LC_MAX; j++) if (variables[j]) { if (print_warning) { log_warning("Warning: Settings on kernel command line override system locale settings in /etc/locale.conf.\n" " Command Line: %s=%s", locale_variable_to_string(j), variables[j]); print_warning = false; } else log_warning(" %s=%s", locale_variable_to_string(j), variables[j]); } finish: for (j = 0; j < _VARIABLE_LC_MAX; j++) free(variables[j]); } static void print_status_info(StatusInfo *i) { assert(i); if (strv_isempty(i->locale)) puts(" System Locale: n/a\n"); else { char **j; printf(" System Locale: %s\n", i->locale[0]); STRV_FOREACH(j, i->locale + 1) printf(" %s\n", *j); } printf(" VC Keymap: %s\n", strna(i->vconsole_keymap)); if (!isempty(i->vconsole_keymap_toggle)) printf("VC Toggle Keymap: %s\n", i->vconsole_keymap_toggle); printf(" X11 Layout: %s\n", strna(i->x11_layout)); if (!isempty(i->x11_model)) printf(" X11 Model: %s\n", i->x11_model); if (!isempty(i->x11_variant)) printf(" X11 Variant: %s\n", i->x11_variant); if (!isempty(i->x11_options)) printf(" X11 Options: %s\n", i->x11_options); } static int show_status(sd_bus *bus, char **args, unsigned n) { _cleanup_(status_info_clear) StatusInfo info = {}; static const struct bus_properties_map map[] = { { "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) }, { "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) }, { "VConsoleKeymapToggle", "s", NULL, offsetof(StatusInfo, vconsole_keymap_toggle) }, { "X11Layout", "s", NULL, offsetof(StatusInfo, x11_layout) }, { "X11Model", "s", NULL, offsetof(StatusInfo, x11_model) }, { "X11Variant", "s", NULL, offsetof(StatusInfo, x11_variant) }, { "X11Options", "s", NULL, offsetof(StatusInfo, x11_options) }, { "Locale", "as", NULL, offsetof(StatusInfo, locale) }, {} }; int r; assert(bus); r = bus_map_all_properties(bus, "org.freedesktop.locale1", "/org/freedesktop/locale1", map, &info); if (r < 0) return log_error_errno(r, "Could not get properties: %m"); print_overridden_variables(); print_status_info(&info); return r; } static int set_locale(sd_bus *bus, char **args, unsigned n) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); assert(args); polkit_agent_open_if_enabled(); r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.locale1", "/org/freedesktop/locale1", "org.freedesktop.locale1", "SetLocale"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append_strv(m, args + 1); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append(m, "b", arg_ask_password); if (r < 0) return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, NULL); if (r < 0) { log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); return r; } return 0; } static int list_locales(sd_bus *bus, char **args, unsigned n) { _cleanup_strv_free_ char **l = NULL; int r; assert(args); r = get_locales(&l); if (r < 0) return log_error_errno(r, "Failed to read list of locales: %m"); pager_open_if_enabled(); strv_print(l); return 0; } static int set_vconsole_keymap(sd_bus *bus, char **args, unsigned n) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *map, *toggle_map; int r; assert(bus); assert(args); if (n > 3) { log_error("Too many arguments."); return -EINVAL; } polkit_agent_open_if_enabled(); map = args[1]; toggle_map = n > 2 ? args[2] : ""; r = sd_bus_call_method( bus, "org.freedesktop.locale1", "/org/freedesktop/locale1", "org.freedesktop.locale1", "SetVConsoleKeyboard", &error, NULL, "ssbb", map, toggle_map, arg_convert, arg_ask_password); if (r < 0) log_error("Failed to set keymap: %s", bus_error_message(&error, -r)); return r; } static Set *keymaps = NULL; static int nftw_cb( const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf) { char *p, *e; int r; if (tflag != FTW_F) return 0; if (!endswith(fpath, ".map") && !endswith(fpath, ".map.gz")) return 0; p = strdup(basename(fpath)); if (!p) return log_oom(); e = endswith(p, ".map"); if (e) *e = 0; e = endswith(p, ".map.gz"); if (e) *e = 0; r = set_consume(keymaps, p); if (r < 0 && r != -EEXIST) return log_error_errno(r, "Can't add keymap: %m"); return 0; } static int list_vconsole_keymaps(sd_bus *bus, char **args, unsigned n) { _cleanup_strv_free_ char **l = NULL; const char *dir; keymaps = set_new(&string_hash_ops); if (!keymaps) return log_oom(); NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) nftw(dir, nftw_cb, 20, FTW_MOUNT|FTW_PHYS); l = set_get_strv(keymaps); if (!l) { set_free_free(keymaps); return log_oom(); } set_free(keymaps); if (strv_isempty(l)) { log_error("Couldn't find any console keymaps."); return -ENOENT; } strv_sort(l); pager_open_if_enabled(); strv_print(l); return 0; } static int set_x11_keymap(sd_bus *bus, char **args, unsigned n) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *layout, *model, *variant, *options; int r; assert(bus); assert(args); if (n > 5) { log_error("Too many arguments."); return -EINVAL; } polkit_agent_open_if_enabled(); layout = args[1]; model = n > 2 ? args[2] : ""; variant = n > 3 ? args[3] : ""; options = n > 4 ? args[4] : ""; r = sd_bus_call_method( bus, "org.freedesktop.locale1", "/org/freedesktop/locale1", "org.freedesktop.locale1", "SetX11Keyboard", &error, NULL, "ssssbb", layout, model, variant, options, arg_convert, arg_ask_password); if (r < 0) log_error("Failed to set keymap: %s", bus_error_message(&error, -r)); return r; } static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) { _cleanup_fclose_ FILE *f = NULL; _cleanup_strv_free_ char **list = NULL; char line[LINE_MAX]; enum { NONE, MODELS, LAYOUTS, VARIANTS, OPTIONS } state = NONE, look_for; int r; if (n > 2) { log_error("Too many arguments."); return -EINVAL; } f = fopen("/usr/share/X11/xkb/rules/base.lst", "re"); if (!f) return log_error_errno(errno, "Failed to open keyboard mapping list. %m"); if (streq(args[0], "list-x11-keymap-models")) look_for = MODELS; else if (streq(args[0], "list-x11-keymap-layouts")) look_for = LAYOUTS; else if (streq(args[0], "list-x11-keymap-variants")) look_for = VARIANTS; else if (streq(args[0], "list-x11-keymap-options")) look_for = OPTIONS; else assert_not_reached("Wrong parameter"); FOREACH_LINE(line, f, break) { char *l, *w; l = strstrip(line); if (isempty(l)) continue; if (l[0] == '!') { if (startswith(l, "! model")) state = MODELS; else if (startswith(l, "! layout")) state = LAYOUTS; else if (startswith(l, "! variant")) state = VARIANTS; else if (startswith(l, "! option")) state = OPTIONS; else state = NONE; continue; } if (state != look_for) continue; w = l + strcspn(l, WHITESPACE); if (n > 1) { char *e; if (*w == 0) continue; *w = 0; w++; w += strspn(w, WHITESPACE); e = strchr(w, ':'); if (!e) continue; *e = 0; if (!streq(w, args[1])) continue; } else *w = 0; r = strv_extend(&list, l); if (r < 0) return log_oom(); } if (strv_isempty(list)) { log_error("Couldn't find any entries."); return -ENOENT; } strv_sort(list); strv_uniq(list); pager_open_if_enabled(); strv_print(list); return 0; } static void help(void) { printf("%s [OPTIONS...] COMMAND ...\n\n" "Query or change system locale and keyboard settings.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " --no-ask-password Do not prompt for password\n" " -H --host=[USER@]HOST Operate on remote host\n" " -M --machine=CONTAINER Operate on local container\n" " --no-convert Don't convert keyboard mappings\n\n" "Commands:\n" " status Show current locale settings\n" " set-locale LOCALE... Set system locale\n" " list-locales Show known locales\n" " set-keymap MAP [MAP] Set console and X11 keyboard mappings\n" " list-keymaps Show known virtual console keyboard mappings\n" " set-x11-keymap LAYOUT [MODEL [VARIANT [OPTIONS]]]\n" " Set X11 and console keyboard mappings\n" " list-x11-keymap-models Show known X11 keyboard mapping models\n" " list-x11-keymap-layouts Show known X11 keyboard mapping layouts\n" " list-x11-keymap-variants [LAYOUT]\n" " Show known X11 keyboard mapping variants\n" " list-x11-keymap-options Show known X11 keyboard mapping options\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_CONVERT, ARG_NO_ASK_PASSWORD }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "host", required_argument, NULL, 'H' }, { "machine", required_argument, NULL, 'M' }, { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, { "no-convert", no_argument, NULL, ARG_NO_CONVERT }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_NO_CONVERT: arg_convert = false; break; case ARG_NO_PAGER: arg_no_pager = true; break; case ARG_NO_ASK_PASSWORD: arg_ask_password = false; break; case 'H': arg_transport = BUS_TRANSPORT_REMOTE; arg_host = optarg; break; case 'M': arg_transport = BUS_TRANSPORT_MACHINE; arg_host = optarg; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } static int localectl_main(sd_bus *bus, int argc, char *argv[]) { static const struct { const char* verb; const enum { MORE, LESS, EQUAL } argc_cmp; const int argc; int (* const dispatch)(sd_bus *bus, char **args, unsigned n); } verbs[] = { { "status", LESS, 1, show_status }, { "set-locale", MORE, 2, set_locale }, { "list-locales", EQUAL, 1, list_locales }, { "set-keymap", MORE, 2, set_vconsole_keymap }, { "list-keymaps", EQUAL, 1, list_vconsole_keymaps }, { "set-x11-keymap", MORE, 2, set_x11_keymap }, { "list-x11-keymap-models", EQUAL, 1, list_x11_keymaps }, { "list-x11-keymap-layouts", EQUAL, 1, list_x11_keymaps }, { "list-x11-keymap-variants", LESS, 2, list_x11_keymaps }, { "list-x11-keymap-options", EQUAL, 1, list_x11_keymaps }, }; int left; unsigned i; assert(argc >= 0); assert(argv); left = argc - optind; if (left <= 0) /* Special rule: no arguments means "status" */ i = 0; else { if (streq(argv[optind], "help")) { help(); return 0; } for (i = 0; i < ELEMENTSOF(verbs); i++) if (streq(argv[optind], verbs[i].verb)) break; if (i >= ELEMENTSOF(verbs)) { log_error("Unknown operation %s", argv[optind]); return -EINVAL; } } switch (verbs[i].argc_cmp) { case EQUAL: if (left != verbs[i].argc) { log_error("Invalid number of arguments."); return -EINVAL; } break; case MORE: if (left < verbs[i].argc) { log_error("Too few arguments."); return -EINVAL; } break; case LESS: if (left > verbs[i].argc) { log_error("Too many arguments."); return -EINVAL; } break; default: assert_not_reached("Unknown comparison operator."); } return verbs[i].dispatch(bus, argv + optind, left); } int main(int argc, char*argv[]) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = bus_connect_transport(arg_transport, arg_host, false, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; } r = localectl_main(bus, argc, argv); finish: pager_close(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/locale/localed.c000066400000000000000000001302211265713322000166550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering Copyright 2013 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #ifdef HAVE_XKBCOMMON #include #endif #include "sd-bus.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-message.h" #include "bus-util.h" #include "def.h" #include "env-util.h" #include "fd-util.h" #include "fileio-label.h" #include "fileio.h" #include "locale-util.h" #include "mkdir.h" #include "path-util.h" #include "selinux-util.h" #include "strv.h" #include "user-util.h" #include "util.h" enum { /* We don't list LC_ALL here on purpose. People should be * using LANG instead. */ LOCALE_LANG, LOCALE_LANGUAGE, LOCALE_LC_CTYPE, LOCALE_LC_NUMERIC, LOCALE_LC_TIME, LOCALE_LC_COLLATE, LOCALE_LC_MONETARY, LOCALE_LC_MESSAGES, LOCALE_LC_PAPER, LOCALE_LC_NAME, LOCALE_LC_ADDRESS, LOCALE_LC_TELEPHONE, LOCALE_LC_MEASUREMENT, LOCALE_LC_IDENTIFICATION, _LOCALE_MAX }; static const char * const names[_LOCALE_MAX] = { [LOCALE_LANG] = "LANG", [LOCALE_LANGUAGE] = "LANGUAGE", [LOCALE_LC_CTYPE] = "LC_CTYPE", [LOCALE_LC_NUMERIC] = "LC_NUMERIC", [LOCALE_LC_TIME] = "LC_TIME", [LOCALE_LC_COLLATE] = "LC_COLLATE", [LOCALE_LC_MONETARY] = "LC_MONETARY", [LOCALE_LC_MESSAGES] = "LC_MESSAGES", [LOCALE_LC_PAPER] = "LC_PAPER", [LOCALE_LC_NAME] = "LC_NAME", [LOCALE_LC_ADDRESS] = "LC_ADDRESS", [LOCALE_LC_TELEPHONE] = "LC_TELEPHONE", [LOCALE_LC_MEASUREMENT] = "LC_MEASUREMENT", [LOCALE_LC_IDENTIFICATION] = "LC_IDENTIFICATION" }; typedef struct Context { char *locale[_LOCALE_MAX]; char *x11_layout; char *x11_model; char *x11_variant; char *x11_options; char *vc_keymap; char *vc_keymap_toggle; Hashmap *polkit_registry; } Context; static const char* nonempty(const char *s) { return isempty(s) ? NULL : s; } static bool startswith_comma(const char *s, const char *prefix) { const char *t; return s && (t = startswith(s, prefix)) && (*t == ','); } static void context_free_x11(Context *c) { c->x11_layout = mfree(c->x11_layout); c->x11_options = mfree(c->x11_options); c->x11_model = mfree(c->x11_model); c->x11_variant = mfree(c->x11_variant); } static void context_free_vconsole(Context *c) { c->vc_keymap = mfree(c->vc_keymap); c->vc_keymap_toggle = mfree(c->vc_keymap_toggle); } static void context_free_locale(Context *c) { int p; for (p = 0; p < _LOCALE_MAX; p++) c->locale[p] = mfree(c->locale[p]); } static void context_free(Context *c) { context_free_locale(c); context_free_x11(c); context_free_vconsole(c); bus_verify_polkit_async_registry_free(c->polkit_registry); }; static void locale_simplify(Context *c) { int p; for (p = LOCALE_LANG+1; p < _LOCALE_MAX; p++) if (isempty(c->locale[p]) || streq_ptr(c->locale[LOCALE_LANG], c->locale[p])) c->locale[p] = mfree(c->locale[p]); } static int locale_read_data(Context *c) { int r; context_free_locale(c); r = parse_env_file("/etc/locale.conf", NEWLINE, "LANG", &c->locale[LOCALE_LANG], "LANGUAGE", &c->locale[LOCALE_LANGUAGE], "LC_CTYPE", &c->locale[LOCALE_LC_CTYPE], "LC_NUMERIC", &c->locale[LOCALE_LC_NUMERIC], "LC_TIME", &c->locale[LOCALE_LC_TIME], "LC_COLLATE", &c->locale[LOCALE_LC_COLLATE], "LC_MONETARY", &c->locale[LOCALE_LC_MONETARY], "LC_MESSAGES", &c->locale[LOCALE_LC_MESSAGES], "LC_PAPER", &c->locale[LOCALE_LC_PAPER], "LC_NAME", &c->locale[LOCALE_LC_NAME], "LC_ADDRESS", &c->locale[LOCALE_LC_ADDRESS], "LC_TELEPHONE", &c->locale[LOCALE_LC_TELEPHONE], "LC_MEASUREMENT", &c->locale[LOCALE_LC_MEASUREMENT], "LC_IDENTIFICATION", &c->locale[LOCALE_LC_IDENTIFICATION], NULL); if (r == -ENOENT) { int p; /* Fill in what we got passed from systemd. */ for (p = 0; p < _LOCALE_MAX; p++) { assert(names[p]); r = free_and_strdup(&c->locale[p], nonempty(getenv(names[p]))); if (r < 0) return r; } r = 0; } locale_simplify(c); return r; } static int vconsole_read_data(Context *c) { int r; context_free_vconsole(c); r = parse_env_file("/etc/vconsole.conf", NEWLINE, "KEYMAP", &c->vc_keymap, "KEYMAP_TOGGLE", &c->vc_keymap_toggle, NULL); if (r < 0 && r != -ENOENT) return r; return 0; } static int x11_read_data(Context *c) { _cleanup_fclose_ FILE *f; char line[LINE_MAX]; bool in_section = false; int r; context_free_x11(c); f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re"); if (!f) return errno == ENOENT ? 0 : -errno; while (fgets(line, sizeof(line), f)) { char *l; char_array_0(line); l = strstrip(line); if (l[0] == 0 || l[0] == '#') continue; if (in_section && first_word(l, "Option")) { _cleanup_strv_free_ char **a = NULL; r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_QUOTES); if (r < 0) return r; if (strv_length(a) == 3) { char **p = NULL; if (streq(a[1], "XkbLayout")) p = &c->x11_layout; else if (streq(a[1], "XkbModel")) p = &c->x11_model; else if (streq(a[1], "XkbVariant")) p = &c->x11_variant; else if (streq(a[1], "XkbOptions")) p = &c->x11_options; if (p) { free(*p); *p = a[2]; a[2] = NULL; } } } else if (!in_section && first_word(l, "Section")) { _cleanup_strv_free_ char **a = NULL; r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_QUOTES); if (r < 0) return -ENOMEM; if (strv_length(a) == 2 && streq(a[1], "InputClass")) in_section = true; } else if (in_section && first_word(l, "EndSection")) in_section = false; } return 0; } static int context_read_data(Context *c) { int r, q, p; r = locale_read_data(c); q = vconsole_read_data(c); p = x11_read_data(c); return r < 0 ? r : q < 0 ? q : p; } static int locale_write_data(Context *c, char ***settings) { int r, p; _cleanup_strv_free_ char **l = NULL; /* Set values will be returned as strv in *settings on success. */ r = load_env_file(NULL, "/etc/locale.conf", NULL, &l); if (r < 0 && r != -ENOENT) return r; for (p = 0; p < _LOCALE_MAX; p++) { _cleanup_free_ char *t = NULL; char **u; assert(names[p]); if (isempty(c->locale[p])) { l = strv_env_unset(l, names[p]); continue; } if (asprintf(&t, "%s=%s", names[p], c->locale[p]) < 0) return -ENOMEM; u = strv_env_set(l, t); if (!u) return -ENOMEM; strv_free(l); l = u; } if (strv_isempty(l)) { if (unlink("/etc/locale.conf") < 0) return errno == ENOENT ? 0 : -errno; return 0; } r = write_env_file_label("/etc/locale.conf", l); if (r < 0) return r; *settings = l; l = NULL; return 0; } static int locale_update_system_manager(Context *c, sd_bus *bus) { _cleanup_free_ char **l_unset = NULL; _cleanup_strv_free_ char **l_set = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; unsigned c_set, c_unset, p; int r; assert(bus); l_unset = new0(char*, _LOCALE_MAX); if (!l_unset) return -ENOMEM; l_set = new0(char*, _LOCALE_MAX); if (!l_set) return -ENOMEM; for (p = 0, c_set = 0, c_unset = 0; p < _LOCALE_MAX; p++) { assert(names[p]); if (isempty(c->locale[p])) l_unset[c_set++] = (char*) names[p]; else { char *s; if (asprintf(&s, "%s=%s", names[p], c->locale[p]) < 0) return -ENOMEM; l_set[c_unset++] = s; } } assert(c_set + c_unset == _LOCALE_MAX); r = sd_bus_message_new_method_call(bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment"); if (r < 0) return r; r = sd_bus_message_append_strv(m, l_unset); if (r < 0) return r; r = sd_bus_message_append_strv(m, l_set); if (r < 0) return r; r = sd_bus_call(bus, m, 0, &error, NULL); if (r < 0) log_error_errno(r, "Failed to update the manager environment: %m"); return 0; } static int vconsole_write_data(Context *c) { int r; _cleanup_strv_free_ char **l = NULL; r = load_env_file(NULL, "/etc/vconsole.conf", NULL, &l); if (r < 0 && r != -ENOENT) return r; if (isempty(c->vc_keymap)) l = strv_env_unset(l, "KEYMAP"); else { _cleanup_free_ char *s = NULL; char **u; s = strappend("KEYMAP=", c->vc_keymap); if (!s) return -ENOMEM; u = strv_env_set(l, s); if (!u) return -ENOMEM; strv_free(l); l = u; } if (isempty(c->vc_keymap_toggle)) l = strv_env_unset(l, "KEYMAP_TOGGLE"); else { _cleanup_free_ char *s = NULL; char **u; s = strappend("KEYMAP_TOGGLE=", c->vc_keymap_toggle); if (!s) return -ENOMEM; u = strv_env_set(l, s); if (!u) return -ENOMEM; strv_free(l); l = u; } if (strv_isempty(l)) { if (unlink("/etc/vconsole.conf") < 0) return errno == ENOENT ? 0 : -errno; return 0; } return write_env_file_label("/etc/vconsole.conf", l); } static int x11_write_data(Context *c) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *temp_path = NULL; int r; if (isempty(c->x11_layout) && isempty(c->x11_model) && isempty(c->x11_variant) && isempty(c->x11_options)) { if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) return errno == ENOENT ? 0 : -errno; return 0; } mkdir_p_label("/etc/X11/xorg.conf.d", 0755); r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path); if (r < 0) return r; fchmod(fileno(f), 0644); fputs("# Read and parsed by systemd-localed. It's probably wise not to edit this file\n" "# manually too freely.\n" "Section \"InputClass\"\n" " Identifier \"system-keyboard\"\n" " MatchIsKeyboard \"on\"\n", f); if (!isempty(c->x11_layout)) fprintf(f, " Option \"XkbLayout\" \"%s\"\n", c->x11_layout); if (!isempty(c->x11_model)) fprintf(f, " Option \"XkbModel\" \"%s\"\n", c->x11_model); if (!isempty(c->x11_variant)) fprintf(f, " Option \"XkbVariant\" \"%s\"\n", c->x11_variant); if (!isempty(c->x11_options)) fprintf(f, " Option \"XkbOptions\" \"%s\"\n", c->x11_options); fputs("EndSection\n", f); r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) { r = -errno; goto fail; } return 0; fail: (void) unlink("/etc/X11/xorg.conf.d/00-keyboard.conf"); if (temp_path) (void) unlink(temp_path); return r; } static int vconsole_reload(sd_bus *bus) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); r = sd_bus_call_method(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "RestartUnit", &error, NULL, "ss", "systemd-vconsole-setup.service", "replace"); if (r < 0) log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); return r; } static const char* strnulldash(const char *s) { return isempty(s) || streq(s, "-") ? NULL : s; } static int read_next_mapping(const char* filename, unsigned min_fields, unsigned max_fields, FILE *f, unsigned *n, char ***a) { assert(f); assert(n); assert(a); for (;;) { char line[LINE_MAX]; char *l, **b; int r; size_t length; errno = 0; if (!fgets(line, sizeof(line), f)) { if (ferror(f)) return errno > 0 ? -errno : -EIO; return 0; } (*n) ++; l = strstrip(line); if (l[0] == 0 || l[0] == '#') continue; r = strv_split_extract(&b, l, WHITESPACE, EXTRACT_QUOTES); if (r < 0) return r; length = strv_length(b); if (length < min_fields || length > max_fields) { log_error("Invalid line %s:%u, ignoring.", filename, *n); strv_free(b); continue; } *a = b; return 1; } } static int vconsole_convert_to_x11(Context *c, sd_bus *bus) { bool modified = false; assert(bus); if (isempty(c->vc_keymap)) { modified = !isempty(c->x11_layout) || !isempty(c->x11_model) || !isempty(c->x11_variant) || !isempty(c->x11_options); context_free_x11(c); } else { _cleanup_fclose_ FILE *f = NULL; unsigned n = 0; f = fopen(SYSTEMD_KBD_MODEL_MAP, "re"); if (!f) return -errno; for (;;) { _cleanup_strv_free_ char **a = NULL; int r; r = read_next_mapping(SYSTEMD_KBD_MODEL_MAP, 5, UINT_MAX, f, &n, &a); if (r < 0) return r; if (r == 0) break; if (!streq(c->vc_keymap, a[0])) continue; if (!streq_ptr(c->x11_layout, strnulldash(a[1])) || !streq_ptr(c->x11_model, strnulldash(a[2])) || !streq_ptr(c->x11_variant, strnulldash(a[3])) || !streq_ptr(c->x11_options, strnulldash(a[4]))) { if (free_and_strdup(&c->x11_layout, strnulldash(a[1])) < 0 || free_and_strdup(&c->x11_model, strnulldash(a[2])) < 0 || free_and_strdup(&c->x11_variant, strnulldash(a[3])) < 0 || free_and_strdup(&c->x11_options, strnulldash(a[4])) < 0) return -ENOMEM; modified = true; } break; } } if (modified) { int r; r = x11_write_data(c); if (r < 0) return log_error_errno(r, "Failed to set X11 keyboard layout: %m"); log_info("Changed X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'", strempty(c->x11_layout), strempty(c->x11_model), strempty(c->x11_variant), strempty(c->x11_options)); sd_bus_emit_properties_changed(bus, "/org/freedesktop/locale1", "org.freedesktop.locale1", "X11Layout", "X11Model", "X11Variant", "X11Options", NULL); } else log_debug("X11 keyboard layout was not modified."); return 0; } static int find_converted_keymap(const char *x11_layout, const char *x11_variant, char **new_keymap) { const char *dir; _cleanup_free_ char *n; if (x11_variant) n = strjoin(x11_layout, "-", x11_variant, NULL); else n = strdup(x11_layout); if (!n) return -ENOMEM; NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) { _cleanup_free_ char *p = NULL, *pz = NULL; bool uncompressed; p = strjoin(dir, "xkb/", n, ".map", NULL); pz = strjoin(dir, "xkb/", n, ".map.gz", NULL); if (!p || !pz) return -ENOMEM; uncompressed = access(p, F_OK) == 0; if (uncompressed || access(pz, F_OK) == 0) { log_debug("Found converted keymap %s at %s", n, uncompressed ? p : pz); *new_keymap = n; n = NULL; return 1; } } return 0; } static int find_legacy_keymap(Context *c, char **new_keymap) { _cleanup_fclose_ FILE *f; unsigned n = 0; unsigned best_matching = 0; int r; f = fopen(SYSTEMD_KBD_MODEL_MAP, "re"); if (!f) return -errno; for (;;) { _cleanup_strv_free_ char **a = NULL; unsigned matching = 0; r = read_next_mapping(SYSTEMD_KBD_MODEL_MAP, 5, UINT_MAX, f, &n, &a); if (r < 0) return r; if (r == 0) break; /* Determine how well matching this entry is */ if (streq_ptr(c->x11_layout, a[1])) /* If we got an exact match, this is best */ matching = 10; else { /* We have multiple X layouts, look for an * entry that matches our key with everything * but the first layout stripped off. */ if (startswith_comma(c->x11_layout, a[1])) matching = 5; else { char *x; /* If that didn't work, strip off the * other layouts from the entry, too */ x = strndupa(a[1], strcspn(a[1], ",")); if (startswith_comma(c->x11_layout, x)) matching = 1; } } if (matching > 0) { if (isempty(c->x11_model) || streq_ptr(c->x11_model, a[2])) { matching++; if (streq_ptr(c->x11_variant, a[3])) { matching++; if (streq_ptr(c->x11_options, a[4])) matching++; } } } /* The best matching entry so far, then let's save that */ if (matching >= MAX(best_matching, 1u)) { log_debug("Found legacy keymap %s with score %u", a[0], matching); if (matching > best_matching) { best_matching = matching; r = free_and_strdup(new_keymap, a[0]); if (r < 0) return r; } } } if (best_matching < 10 && c->x11_layout) { /* The best match is only the first part of the X11 * keymap. Check if we have a converted map which * matches just the first layout. */ char *l, *v = NULL, *converted; l = strndupa(c->x11_layout, strcspn(c->x11_layout, ",")); if (c->x11_variant) v = strndupa(c->x11_variant, strcspn(c->x11_variant, ",")); r = find_converted_keymap(l, v, &converted); if (r < 0) return r; if (r > 0) { free(*new_keymap); *new_keymap = converted; } } return 0; } static int find_language_fallback(const char *lang, char **language) { _cleanup_fclose_ FILE *f = NULL; unsigned n = 0; assert(language); f = fopen(SYSTEMD_LANGUAGE_FALLBACK_MAP, "re"); if (!f) return -errno; for (;;) { _cleanup_strv_free_ char **a = NULL; int r; r = read_next_mapping(SYSTEMD_LANGUAGE_FALLBACK_MAP, 2, 2, f, &n, &a); if (r <= 0) return r; if (streq(lang, a[0])) { assert(strv_length(a) == 2); *language = a[1]; a[1] = NULL; return 1; } } assert_not_reached("should not be here"); } static int x11_convert_to_vconsole(Context *c, sd_bus *bus) { bool modified = false; int r; assert(bus); if (isempty(c->x11_layout)) { modified = !isempty(c->vc_keymap) || !isempty(c->vc_keymap_toggle); context_free_x11(c); } else { char *new_keymap = NULL; r = find_converted_keymap(c->x11_layout, c->x11_variant, &new_keymap); if (r < 0) return r; else if (r == 0) { r = find_legacy_keymap(c, &new_keymap); if (r < 0) return r; } if (!streq_ptr(c->vc_keymap, new_keymap)) { free(c->vc_keymap); c->vc_keymap = new_keymap; c->vc_keymap_toggle = mfree(c->vc_keymap_toggle); modified = true; } else free(new_keymap); } if (modified) { r = vconsole_write_data(c); if (r < 0) log_error_errno(r, "Failed to set virtual console keymap: %m"); log_info("Changed virtual console keymap to '%s' toggle '%s'", strempty(c->vc_keymap), strempty(c->vc_keymap_toggle)); sd_bus_emit_properties_changed(bus, "/org/freedesktop/locale1", "org.freedesktop.locale1", "VConsoleKeymap", "VConsoleKeymapToggle", NULL); return vconsole_reload(bus); } else log_debug("Virtual console keymap was not modified."); return 0; } static int property_get_locale( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Context *c = userdata; _cleanup_strv_free_ char **l = NULL; int p, q; l = new0(char*, _LOCALE_MAX+1); if (!l) return -ENOMEM; for (p = 0, q = 0; p < _LOCALE_MAX; p++) { char *t; if (isempty(c->locale[p])) continue; if (asprintf(&t, "%s=%s", names[p], c->locale[p]) < 0) return -ENOMEM; l[q++] = t; } return sd_bus_message_append_strv(reply, l); } static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *error) { Context *c = userdata; _cleanup_strv_free_ char **l = NULL; char **i; const char *lang = NULL; int interactive; bool modified = false; bool have[_LOCALE_MAX] = {}; int p; int r; assert(m); assert(c); r = bus_message_read_strv_extend(m, &l); if (r < 0) return r; r = sd_bus_message_read_basic(m, 'b', &interactive); if (r < 0) return r; /* Check whether a variable changed and if it is valid */ STRV_FOREACH(i, l) { bool valid = false; for (p = 0; p < _LOCALE_MAX; p++) { size_t k; k = strlen(names[p]); if (startswith(*i, names[p]) && (*i)[k] == '=' && locale_is_valid((*i) + k + 1)) { valid = true; have[p] = true; if (p == LOCALE_LANG) lang = (*i) + k + 1; if (!streq_ptr(*i + k + 1, c->locale[p])) modified = true; break; } } if (!valid) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data."); } /* If LANG was specified, but not LANGUAGE, check if we should * set it based on the language fallback table. */ if (have[LOCALE_LANG] && !have[LOCALE_LANGUAGE]) { _cleanup_free_ char *language = NULL; assert(lang); (void) find_language_fallback(lang, &language); if (language) { log_debug("Converted LANG=%s to LANGUAGE=%s", lang, language); if (!streq_ptr(language, c->locale[LOCALE_LANGUAGE])) { r = strv_extendf(&l, "LANGUAGE=%s", language); if (r < 0) return r; have[LOCALE_LANGUAGE] = true; modified = true; } } } /* Check whether a variable is unset */ if (!modified) for (p = 0; p < _LOCALE_MAX; p++) if (!isempty(c->locale[p]) && !have[p]) { modified = true; break; } if (modified) { _cleanup_strv_free_ char **settings = NULL; r = bus_verify_polkit_async( m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-locale", NULL, interactive, UID_INVALID, &c->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ STRV_FOREACH(i, l) for (p = 0; p < _LOCALE_MAX; p++) { size_t k; k = strlen(names[p]); if (startswith(*i, names[p]) && (*i)[k] == '=') { r = free_and_strdup(&c->locale[p], *i + k + 1); if (r < 0) return r; break; } } for (p = 0; p < _LOCALE_MAX; p++) { if (have[p]) continue; c->locale[p] = mfree(c->locale[p]); } locale_simplify(c); r = locale_write_data(c, &settings); if (r < 0) { log_error_errno(r, "Failed to set locale: %m"); return sd_bus_error_set_errnof(error, r, "Failed to set locale: %s", strerror(-r)); } locale_update_system_manager(c, sd_bus_message_get_bus(m)); if (settings) { _cleanup_free_ char *line; line = strv_join(settings, ", "); log_info("Changed locale to %s.", strnull(line)); } else log_info("Changed locale to unset."); (void) sd_bus_emit_properties_changed( sd_bus_message_get_bus(m), "/org/freedesktop/locale1", "org.freedesktop.locale1", "Locale", NULL); } else log_debug("Locale settings were not modified."); return sd_bus_reply_method_return(m, NULL); } static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_error *error) { Context *c = userdata; const char *keymap, *keymap_toggle; int convert, interactive; int r; assert(m); assert(c); r = sd_bus_message_read(m, "ssbb", &keymap, &keymap_toggle, &convert, &interactive); if (r < 0) return r; if (isempty(keymap)) keymap = NULL; if (isempty(keymap_toggle)) keymap_toggle = NULL; if (!streq_ptr(keymap, c->vc_keymap) || !streq_ptr(keymap_toggle, c->vc_keymap_toggle)) { if ((keymap && (!filename_is_valid(keymap) || !string_is_safe(keymap))) || (keymap_toggle && (!filename_is_valid(keymap_toggle) || !string_is_safe(keymap_toggle)))) return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keymap data"); r = bus_verify_polkit_async( m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-keyboard", NULL, interactive, UID_INVALID, &c->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ if (free_and_strdup(&c->vc_keymap, keymap) < 0 || free_and_strdup(&c->vc_keymap_toggle, keymap_toggle) < 0) return -ENOMEM; r = vconsole_write_data(c); if (r < 0) { log_error_errno(r, "Failed to set virtual console keymap: %m"); return sd_bus_error_set_errnof(error, r, "Failed to set virtual console keymap: %s", strerror(-r)); } log_info("Changed virtual console keymap to '%s' toggle '%s'", strempty(c->vc_keymap), strempty(c->vc_keymap_toggle)); r = vconsole_reload(sd_bus_message_get_bus(m)); if (r < 0) log_error_errno(r, "Failed to request keymap reload: %m"); (void) sd_bus_emit_properties_changed( sd_bus_message_get_bus(m), "/org/freedesktop/locale1", "org.freedesktop.locale1", "VConsoleKeymap", "VConsoleKeymapToggle", NULL); if (convert) { r = vconsole_convert_to_x11(c, sd_bus_message_get_bus(m)); if (r < 0) log_error_errno(r, "Failed to convert keymap data: %m"); } } return sd_bus_reply_method_return(m, NULL); } #ifdef HAVE_XKBCOMMON _printf_(3, 0) static void log_xkb(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) { const char *fmt; fmt = strjoina("libxkbcommon: ", format); log_internalv(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, fmt, args); } static int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) { const struct xkb_rule_names rmlvo = { .model = model, .layout = layout, .variant = variant, .options = options, }; struct xkb_context *ctx = NULL; struct xkb_keymap *km = NULL; int r; /* compile keymap from RMLVO information to check out its validity */ ctx = xkb_context_new(XKB_CONTEXT_NO_ENVIRONMENT_NAMES); if (!ctx) { r = -ENOMEM; goto exit; } xkb_context_set_log_fn(ctx, log_xkb); km = xkb_keymap_new_from_names(ctx, &rmlvo, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!km) { r = -EINVAL; goto exit; } r = 0; exit: xkb_keymap_unref(km); xkb_context_unref(ctx); return r; } #else static int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) { return 0; } #endif static int method_set_x11_keyboard(sd_bus_message *m, void *userdata, sd_bus_error *error) { Context *c = userdata; const char *layout, *model, *variant, *options; int convert, interactive; int r; assert(m); assert(c); r = sd_bus_message_read(m, "ssssbb", &layout, &model, &variant, &options, &convert, &interactive); if (r < 0) return r; if (isempty(layout)) layout = NULL; if (isempty(model)) model = NULL; if (isempty(variant)) variant = NULL; if (isempty(options)) options = NULL; if (!streq_ptr(layout, c->x11_layout) || !streq_ptr(model, c->x11_model) || !streq_ptr(variant, c->x11_variant) || !streq_ptr(options, c->x11_options)) { if ((layout && !string_is_safe(layout)) || (model && !string_is_safe(model)) || (variant && !string_is_safe(variant)) || (options && !string_is_safe(options))) return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keyboard data"); r = bus_verify_polkit_async( m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-keyboard", NULL, interactive, UID_INVALID, &c->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = verify_xkb_rmlvo(model, layout, variant, options); if (r < 0) { log_error_errno(r, "Cannot compile XKB keymap for new x11 keyboard layout ('%s' / '%s' / '%s' / '%s'): %m", strempty(model), strempty(layout), strempty(variant), strempty(options)); return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot compile XKB keymap, refusing"); } if (free_and_strdup(&c->x11_layout, layout) < 0 || free_and_strdup(&c->x11_model, model) < 0 || free_and_strdup(&c->x11_variant, variant) < 0 || free_and_strdup(&c->x11_options, options) < 0) return -ENOMEM; r = x11_write_data(c); if (r < 0) { log_error_errno(r, "Failed to set X11 keyboard layout: %m"); return sd_bus_error_set_errnof(error, r, "Failed to set X11 keyboard layout: %s", strerror(-r)); } log_info("Changed X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'", strempty(c->x11_layout), strempty(c->x11_model), strempty(c->x11_variant), strempty(c->x11_options)); (void) sd_bus_emit_properties_changed( sd_bus_message_get_bus(m), "/org/freedesktop/locale1", "org.freedesktop.locale1", "X11Layout", "X11Model", "X11Variant", "X11Options", NULL); if (convert) { r = x11_convert_to_vconsole(c, sd_bus_message_get_bus(m)); if (r < 0) log_error_errno(r, "Failed to convert keymap data: %m"); } } return sd_bus_reply_method_return(m, NULL); } static const sd_bus_vtable locale_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Locale", "as", property_get_locale, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("X11Layout", "s", NULL, offsetof(Context, x11_layout), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("X11Model", "s", NULL, offsetof(Context, x11_model), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("X11Variant", "s", NULL, offsetof(Context, x11_variant), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("X11Options", "s", NULL, offsetof(Context, x11_options), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("VConsoleKeymap", "s", NULL, offsetof(Context, vc_keymap), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("VConsoleKeymapToggle", "s", NULL, offsetof(Context, vc_keymap_toggle), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_METHOD("SetLocale", "asb", NULL, method_set_locale, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetVConsoleKeyboard", "ssbb", NULL, method_set_vc_keyboard, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetX11Keyboard", "ssssbb", NULL, method_set_x11_keyboard, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; assert(c); assert(event); assert(_bus); r = sd_bus_default_system(&bus); if (r < 0) return log_error_errno(r, "Failed to get system bus connection: %m"); r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/locale1", "org.freedesktop.locale1", locale_vtable, c); if (r < 0) return log_error_errno(r, "Failed to register object: %m"); r = sd_bus_request_name(bus, "org.freedesktop.locale1", 0); if (r < 0) return log_error_errno(r, "Failed to register name: %m"); r = sd_bus_attach_event(bus, event, 0); if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop: %m"); *_bus = bus; bus = NULL; return 0; } int main(int argc, char *argv[]) { _cleanup_(context_free) Context context = {}; _cleanup_(sd_event_unrefp) sd_event *event = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); mac_selinux_init("/etc"); if (argc != 1) { log_error("This program takes no arguments."); r = -EINVAL; goto finish; } r = sd_event_default(&event); if (r < 0) { log_error_errno(r, "Failed to allocate event loop: %m"); goto finish; } sd_event_set_watchdog(event, true); r = connect_bus(&context, event, &bus); if (r < 0) goto finish; r = context_read_data(&context); if (r < 0) { log_error_errno(r, "Failed to read locale data: %m"); goto finish; } r = bus_event_loop_with_idle(event, bus, "org.freedesktop.locale1", DEFAULT_EXIT_USEC, NULL, NULL); if (r < 0) { log_error_errno(r, "Failed to run event loop: %m"); goto finish; } finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/locale/org.freedesktop.locale1.conf000066400000000000000000000016511265713322000224010ustar00rootroot00000000000000 systemd-229/src/locale/org.freedesktop.locale1.policy.in000066400000000000000000000034011265713322000233530ustar00rootroot00000000000000 The systemd Project http://www.freedesktop.org/wiki/Software/systemd <_description>Set system locale <_message>Authentication is required to set the system locale. auth_admin_keep auth_admin_keep auth_admin_keep org.freedesktop.locale1.set-keyboard <_description>Set system keyboard settings <_message>Authentication is required to set the system keyboard settings. auth_admin_keep auth_admin_keep auth_admin_keep systemd-229/src/locale/org.freedesktop.locale1.service000066400000000000000000000006371265713322000231170ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] Name=org.freedesktop.locale1 Exec=/bin/false User=root SystemdService=dbus-org.freedesktop.locale1.service systemd-229/src/login/000077500000000000000000000000001265713322000147605ustar00rootroot00000000000000systemd-229/src/login/.gitignore000066400000000000000000000001401265713322000167430ustar00rootroot00000000000000/logind-gperf.c /org.freedesktop.login1.policy /71-seat.rules /73-seat-late.rules /systemd-user systemd-229/src/login/70-power-switch.rules000066400000000000000000000016561265713322000207230ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. ACTION=="remove", GOTO="power_switch_end" SUBSYSTEM=="input", KERNEL=="event*", SUBSYSTEMS=="acpi", TAG+="power-switch" SUBSYSTEM=="input", KERNEL=="event*", KERNELS=="thinkpad_acpi", TAG+="power-switch" SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="twl4030_pwrbutton", TAG+="power-switch" SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="tps65217_pwr_but", TAG+="power-switch" SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="* WMI hotkeys", TAG+="power-switch" SUBSYSTEM=="input", KERNEL=="event*", \ SUBSYSTEMS=="platform", DRIVERS=="gpio-keys", ATTRS{keys}=="*,116|116,*|116|*,116,*", TAG+="power-switch" LABEL="power_switch_end" systemd-229/src/login/70-uaccess.rules000066400000000000000000000050371265713322000177130ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. ACTION=="remove", GOTO="uaccess_end" ENV{MAJOR}=="", GOTO="uaccess_end" # PTP/MTP protocol devices, cameras, portable media players SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="*:060101:*", TAG+="uaccess" # Digicams with proprietary protocol ENV{ID_GPHOTO2}=="?*", TAG+="uaccess" # SCSI and USB scanners ENV{libsane_matched}=="yes", TAG+="uaccess" # HPLIP devices (necessary for ink level check and HP tool maintenance) ENV{ID_HPLIP}=="1", TAG+="uaccess" # optical drives SUBSYSTEM=="block", ENV{ID_CDROM}=="1", TAG+="uaccess" SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", TAG+="uaccess" # Sound devices SUBSYSTEM=="sound", TAG+="uaccess" \ OPTIONS+="static_node=snd/timer", OPTIONS+="static_node=snd/seq" # ffado is an userspace driver for firewire sound cards SUBSYSTEM=="firewire", ENV{ID_FFADO}=="1", TAG+="uaccess" # Webcams, frame grabber, TV cards SUBSYSTEM=="video4linux", TAG+="uaccess" SUBSYSTEM=="dvb", TAG+="uaccess" # IIDC devices: industrial cameras and some webcams SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*", TAG+="uaccess" SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", TAG+="uaccess" # AV/C devices: camcorders, set-top boxes, TV sets, audio devices, and more SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", TAG+="uaccess" SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", TAG+="uaccess" # DRI video devices SUBSYSTEM=="drm", KERNEL=="card*|renderD*", TAG+="uaccess" # KVM SUBSYSTEM=="misc", KERNEL=="kvm", TAG+="uaccess" # smart-card readers ENV{ID_SMARTCARD_READER}=="?*", TAG+="uaccess" # (USB) authentication devices ENV{ID_SECURITY_TOKEN}=="?*", TAG+="uaccess" # PDA devices ENV{ID_PDA}=="?*", TAG+="uaccess" # Programmable remote control ENV{ID_REMOTE_CONTROL}=="1", TAG+="uaccess" # joysticks SUBSYSTEM=="input", ENV{ID_INPUT_JOYSTICK}=="?*", TAG+="uaccess" # color measurement devices ENV{COLOR_MEASUREMENT_DEVICE}=="?*", TAG+="uaccess" # DDC/CI device, usually high-end monitors such as the DreamColor ENV{DDC_DEVICE}=="?*", TAG+="uaccess" # media player raw devices (for user-mode drivers, Android SDK, etc.) SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="uaccess" # software-defined radio communication devices ENV{ID_SOFTWARE_RADIO}=="?*", TAG+="uaccess" LABEL="uaccess_end" systemd-229/src/login/71-seat.rules.in000066400000000000000000000052461265713322000176310ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. ACTION=="remove", GOTO="seat_end" TAG=="uaccess", SUBSYSTEM!="sound", TAG+="seat" SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat" SUBSYSTEM=="input", KERNEL=="input*", TAG+="seat" SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat", TAG+="master-of-seat" SUBSYSTEM=="drm", KERNEL=="card[0-9]*", TAG+="seat", TAG+="master-of-seat" SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat" # 'Plugable' USB hub, sound, network, graphics adapter SUBSYSTEM=="usb", ATTR{idVendor}=="2230", ATTR{idProduct}=="000[13]", ENV{ID_AUTOSEAT}="1" # qemu (version 2.4+) has a PCI-PCI bridge (-device pci-bridge-seat) to group # devices belonging to one seat. See: # http://git.qemu.org/?p=qemu.git;a=blob;f=docs/multiseat.txt SUBSYSTEM=="pci", ATTR{vendor}=="0x1b36", ATTR{device}=="0x000a", TAG+="seat", ENV{ID_AUTOSEAT}="1" # Mimo 720, with integrated USB hub, displaylink graphics, and e2i # touchscreen. This device carries no proper VID/PID in the USB hub, # but it does carry good ID data in the graphics component, hence we # check it from the parent. There's a bit of a race here however, # given that the child devices might not exist yet at the time this # rule is executed. To work around this we'll trigger the parent from # the child if we notice that the parent wasn't recognized yet. # Match parent SUBSYSTEM=="usb", ATTR{idVendor}=="058f", ATTR{idProduct}=="6254", \ ATTR{%k.2/idVendor}=="17e9", ATTR{%k.2/idProduct}=="401a", ATTR{%k.2/product}=="mimo inc", \ ENV{ID_AUTOSEAT}="1", ENV{ID_AVOID_LOOP}="1" # Match child, look for parent's ID_AVOID_LOOP SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product}=="mimo inc", \ ATTR{../idVendor}=="058f", ATTR{../idProduct}=="6254", \ IMPORT{parent}="ID_AVOID_LOOP" # Match child, retrigger parent SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product}=="mimo inc", \ ATTR{../idVendor}=="058f", ATTR{../idProduct}=="6254", \ ENV{ID_AVOID_LOOP}=="", \ RUN+="@rootbindir@/udevadm trigger --parent-match=%p/.." TAG=="seat", ENV{ID_PATH}=="", IMPORT{builtin}="path_id" TAG=="seat", ENV{ID_FOR_SEAT}=="", ENV{ID_PATH_TAG}!="", ENV{ID_FOR_SEAT}="$env{SUBSYSTEM}-$env{ID_PATH_TAG}" SUBSYSTEM=="input", ATTR{name}=="Wiebetech LLC Wiebetech", RUN+="@rootbindir@/loginctl lock-sessions" LABEL="seat_end" systemd-229/src/login/73-seat-late.rules.in000066400000000000000000000011241265713322000205450ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. ACTION=="remove", GOTO="seat_late_end" ENV{ID_SEAT}=="", ENV{ID_AUTOSEAT}=="1", ENV{ID_FOR_SEAT}!="", ENV{ID_SEAT}="seat-$env{ID_FOR_SEAT}" ENV{ID_SEAT}=="", IMPORT{parent}="ID_SEAT" ENV{ID_SEAT}!="", TAG+="$env{ID_SEAT}" TAG=="uaccess", ENV{MAJOR}!="", RUN{builtin}+="uaccess" LABEL="seat_late_end" systemd-229/src/login/Makefile000077700000000000000000000000001265713322000202662../Makefileustar00rootroot00000000000000systemd-229/src/login/inhibit.c000066400000000000000000000221361265713322000165560ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "fd-util.h" #include "formats-util.h" #include "process-util.h" #include "signal-util.h" #include "strv.h" #include "user-util.h" #include "util.h" static const char* arg_what = "idle:sleep:shutdown"; static const char* arg_who = NULL; static const char* arg_why = "Unknown reason"; static const char* arg_mode = NULL; static enum { ACTION_INHIBIT, ACTION_LIST } arg_action = ACTION_INHIBIT; static int inhibit(sd_bus *bus, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; int fd; r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "Inhibit", error, &reply, "ssss", arg_what, arg_who, arg_why, arg_mode); if (r < 0) return r; r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_UNIX_FD, &fd); if (r < 0) return r; r = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (r < 0) return -errno; return r; } static int print_inhibitors(sd_bus *bus, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *what, *who, *why, *mode; unsigned int uid, pid; unsigned n = 0; int r; r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "ListInhibitors", error, &reply, ""); if (r < 0) return r; r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) { _cleanup_free_ char *comm = NULL, *u = NULL; if (arg_mode && !streq(mode, arg_mode)) continue; get_process_comm(pid, &comm); u = uid_to_name(uid); printf(" Who: %s (UID "UID_FMT"/%s, PID "PID_FMT"/%s)\n" " What: %s\n" " Why: %s\n" " Mode: %s\n\n", who, uid, strna(u), pid, strna(comm), what, why, mode); n++; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); printf("%u inhibitors listed.\n", n); return 0; } static void help(void) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" "Execute a process while inhibiting shutdown/sleep/idle.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --what=WHAT Operations to inhibit, colon separated list of:\n" " shutdown, sleep, idle, handle-power-key,\n" " handle-suspend-key, handle-hibernate-key,\n" " handle-lid-switch\n" " --who=STRING A descriptive string who is inhibiting\n" " --why=STRING A descriptive string why is being inhibited\n" " --mode=MODE One of block or delay\n" " --list List active inhibitors\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_WHAT, ARG_WHO, ARG_WHY, ARG_MODE, ARG_LIST, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "what", required_argument, NULL, ARG_WHAT }, { "who", required_argument, NULL, ARG_WHO }, { "why", required_argument, NULL, ARG_WHY }, { "mode", required_argument, NULL, ARG_MODE }, { "list", no_argument, NULL, ARG_LIST }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "+h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_WHAT: arg_what = optarg; break; case ARG_WHO: arg_who = optarg; break; case ARG_WHY: arg_why = optarg; break; case ARG_MODE: arg_mode = optarg; break; case ARG_LIST: arg_action = ACTION_LIST; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (arg_action == ACTION_INHIBIT && optind == argc) arg_action = ACTION_LIST; else if (arg_action == ACTION_INHIBIT && optind >= argc) { log_error("Missing command line to execute."); return -EINVAL; } return 1; } int main(int argc, char *argv[]) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r < 0) return EXIT_FAILURE; if (r == 0) return EXIT_SUCCESS; r = sd_bus_default_system(&bus); if (r < 0) { log_error_errno(r, "Failed to connect to bus: %m"); return EXIT_FAILURE; } if (arg_action == ACTION_LIST) { r = print_inhibitors(bus, &error); if (r < 0) { log_error("Failed to list inhibitors: %s", bus_error_message(&error, -r)); return EXIT_FAILURE; } } else { _cleanup_close_ int fd = -1; _cleanup_free_ char *w = NULL; pid_t pid; if (!arg_who) arg_who = w = strv_join(argv + optind, " "); if (!arg_mode) arg_mode = "block"; fd = inhibit(bus, &error); if (fd < 0) { log_error("Failed to inhibit: %s", bus_error_message(&error, fd)); return EXIT_FAILURE; } pid = fork(); if (pid < 0) { log_error_errno(errno, "Failed to fork: %m"); return EXIT_FAILURE; } if (pid == 0) { /* Child */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); close_all_fds(NULL, 0); execvp(argv[optind], argv + optind); log_error_errno(errno, "Failed to execute %s: %m", argv[optind]); _exit(EXIT_FAILURE); } r = wait_for_terminate_and_warn(argv[optind], pid, true); return r < 0 ? EXIT_FAILURE : r; } return 0; } systemd-229/src/login/loginctl.c000066400000000000000000001531301265713322000167420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "cgroup-show.h" #include "cgroup-util.h" #include "log.h" #include "logs-show.h" #include "macro.h" #include "pager.h" #include "parse-util.h" #include "process-util.h" #include "signal-util.h" #include "spawn-polkit-agent.h" #include "strv.h" #include "sysfs-show.h" #include "terminal-util.h" #include "unit-name.h" #include "user-util.h" #include "util.h" #include "verbs.h" static char **arg_property = NULL; static bool arg_all = false; static bool arg_full = false; static bool arg_no_pager = false; static bool arg_legend = true; static const char *arg_kill_who = NULL; static int arg_signal = SIGTERM; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static char *arg_host = NULL; static bool arg_ask_password = true; static unsigned arg_lines = 10; static OutputMode arg_output = OUTPUT_SHORT; static void pager_open_if_enabled(void) { if (arg_no_pager) return; pager_open(false); } static void polkit_agent_open_if_enabled(void) { /* Open the polkit agent as a child process if necessary */ if (!arg_ask_password) return; if (arg_transport != BUS_TRANSPORT_LOCAL) return; polkit_agent_open(); } static OutputFlags get_output_flags(void) { return arg_all * OUTPUT_SHOW_ALL | arg_full * OUTPUT_FULL_WIDTH | (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH | colors_enabled() * OUTPUT_COLOR; } static int list_sessions(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *id, *user, *seat, *object; sd_bus *bus = userdata; unsigned k = 0; uint32_t uid; int r; assert(bus); assert(argv); pager_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "ListSessions", &error, &reply, ""); if (r < 0) { log_error("Failed to list sessions: %s", bus_error_message(&error, r)); return r; } r = sd_bus_message_enter_container(reply, 'a', "(susso)"); if (r < 0) return bus_log_parse_error(r); if (arg_legend) printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT"); while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) { printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat); k++; } if (r < 0) return bus_log_parse_error(r); if (arg_legend) printf("\n%u sessions listed.\n", k); return 0; } static int list_users(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *user, *object; sd_bus *bus = userdata; unsigned k = 0; uint32_t uid; int r; assert(bus); assert(argv); pager_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "ListUsers", &error, &reply, ""); if (r < 0) { log_error("Failed to list users: %s", bus_error_message(&error, r)); return r; } r = sd_bus_message_enter_container(reply, 'a', "(uso)"); if (r < 0) return bus_log_parse_error(r); if (arg_legend) printf("%10s %-16s\n", "UID", "USER"); while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) { printf("%10u %-16s\n", (unsigned) uid, user); k++; } if (r < 0) return bus_log_parse_error(r); if (arg_legend) printf("\n%u users listed.\n", k); return 0; } static int list_seats(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *seat, *object; sd_bus *bus = userdata; unsigned k = 0; int r; assert(bus); assert(argv); pager_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "ListSeats", &error, &reply, ""); if (r < 0) { log_error("Failed to list seats: %s", bus_error_message(&error, r)); return r; } r = sd_bus_message_enter_container(reply, 'a', "(so)"); if (r < 0) return bus_log_parse_error(r); if (arg_legend) printf("%-16s\n", "SEAT"); while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) { printf("%-16s\n", seat); k++; } if (r < 0) return bus_log_parse_error(r); if (arg_legend) printf("\n%u seats listed.\n", k); return 0; } static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *path = NULL; const char *cgroup; int r; unsigned c; assert(bus); assert(unit); if (arg_transport != BUS_TRANSPORT_LOCAL) return 0; path = unit_dbus_path_from_name(unit); if (!path) return -ENOMEM; r = sd_bus_get_property( bus, "org.freedesktop.systemd1", path, interface, "ControlGroup", &error, &reply, "s"); if (r < 0) return r; r = sd_bus_message_read(reply, "s", &cgroup); if (r < 0) return r; if (isempty(cgroup)) return 0; if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0) return 0; c = columns(); if (c > 18) c -= 18; else c = 0; show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags()); return 0; } typedef struct SessionStatusInfo { char *id; uid_t uid; char *name; struct dual_timestamp timestamp; unsigned int vtnr; char *seat; char *tty; char *display; bool remote; char *remote_host; char *remote_user; char *service; pid_t leader; char *type; char *class; char *state; char *scope; char *desktop; } SessionStatusInfo; typedef struct UserStatusInfo { uid_t uid; char *name; struct dual_timestamp timestamp; char *state; char **sessions; char *display; char *slice; } UserStatusInfo; typedef struct SeatStatusInfo { char *id; char *active_session; char **sessions; } SeatStatusInfo; static void session_status_info_clear(SessionStatusInfo *info) { if (info) { free(info->id); free(info->name); free(info->seat); free(info->tty); free(info->display); free(info->remote_host); free(info->remote_user); free(info->service); free(info->type); free(info->class); free(info->state); free(info->scope); free(info->desktop); zero(*info); } } static void user_status_info_clear(UserStatusInfo *info) { if (info) { free(info->name); free(info->state); strv_free(info->sessions); free(info->display); free(info->slice); zero(*info); } } static void seat_status_info_clear(SeatStatusInfo *info) { if (info) { free(info->id); free(info->active_session); strv_free(info->sessions); zero(*info); } } static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { const char *contents; int r; r = sd_bus_message_peek_type(m, NULL, &contents); if (r < 0) return r; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents); if (r < 0) return r; if (contents[0] == 's' || contents[0] == 'o') { const char *s; char **p = (char **) userdata; r = sd_bus_message_read_basic(m, contents[0], &s); if (r < 0) return r; r = free_and_strdup(p, s); if (r < 0) return r; } else { r = sd_bus_message_read_basic(m, contents[0], userdata); if (r < 0) return r; } r = sd_bus_message_skip(m, contents+1); if (r < 0) return r; r = sd_bus_message_exit_container(m); if (r < 0) return r; return 0; } static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { const char *name; int r; assert(bus); assert(m); r = sd_bus_message_enter_container(m, 'a', "(so)"); if (r < 0) return r; while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) { r = strv_extend(userdata, name); if (r < 0) return r; } if (r < 0) return r; return sd_bus_message_exit_container(m); } static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) { static const struct bus_properties_map map[] = { { "Id", "s", NULL, offsetof(SessionStatusInfo, id) }, { "Name", "s", NULL, offsetof(SessionStatusInfo, name) }, { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) }, { "Display", "s", NULL, offsetof(SessionStatusInfo, display) }, { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) }, { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) }, { "Service", "s", NULL, offsetof(SessionStatusInfo, service) }, { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) }, { "Type", "s", NULL, offsetof(SessionStatusInfo, type) }, { "Class", "s", NULL, offsetof(SessionStatusInfo, class) }, { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) }, { "State", "s", NULL, offsetof(SessionStatusInfo, state) }, { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) }, { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) }, { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) }, { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) }, { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) }, { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) }, { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) }, {} }; char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char since2[FORMAT_TIMESTAMP_MAX], *s2; _cleanup_(session_status_info_clear) SessionStatusInfo i = {}; int r; r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i); if (r < 0) return log_error_errno(r, "Could not get properties: %m"); if (*new_line) printf("\n"); *new_line = true; printf("%s - ", strna(i.id)); if (i.name) printf("%s (%u)\n", i.name, (unsigned) i.uid); else printf("%u\n", (unsigned) i.uid); s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime); s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime); if (s1) printf("\t Since: %s; %s\n", s2, s1); else if (s2) printf("\t Since: %s\n", s2); if (i.leader > 0) { _cleanup_free_ char *t = NULL; printf("\t Leader: %u", (unsigned) i.leader); get_process_comm(i.leader, &t); if (t) printf(" (%s)", t); printf("\n"); } if (!isempty(i.seat)) { printf("\t Seat: %s", i.seat); if (i.vtnr > 0) printf("; vc%u", i.vtnr); printf("\n"); } if (i.tty) printf("\t TTY: %s\n", i.tty); else if (i.display) printf("\t Display: %s\n", i.display); if (i.remote_host && i.remote_user) printf("\t Remote: %s@%s\n", i.remote_user, i.remote_host); else if (i.remote_host) printf("\t Remote: %s\n", i.remote_host); else if (i.remote_user) printf("\t Remote: user %s\n", i.remote_user); else if (i.remote) printf("\t Remote: Yes\n"); if (i.service) { printf("\t Service: %s", i.service); if (i.type) printf("; type %s", i.type); if (i.class) printf("; class %s", i.class); printf("\n"); } else if (i.type) { printf("\t Type: %s", i.type); if (i.class) printf("; class %s", i.class); printf("\n"); } else if (i.class) printf("\t Class: %s\n", i.class); if (!isempty(i.desktop)) printf("\t Desktop: %s\n", i.desktop); if (i.state) printf("\t State: %s\n", i.state); if (i.scope) { printf("\t Unit: %s\n", i.scope); show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader); if (arg_transport == BUS_TRANSPORT_LOCAL) { show_journal_by_unit( stdout, i.scope, arg_output, 0, i.timestamp.monotonic, arg_lines, 0, get_output_flags() | OUTPUT_BEGIN_NEWLINE, SD_JOURNAL_LOCAL_ONLY, true, NULL); } } return 0; } static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) { static const struct bus_properties_map map[] = { { "Name", "s", NULL, offsetof(UserStatusInfo, name) }, { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) }, { "State", "s", NULL, offsetof(UserStatusInfo, state) }, { "UID", "u", NULL, offsetof(UserStatusInfo, uid) }, { "Timestamp", "t", NULL, offsetof(UserStatusInfo, timestamp.realtime) }, { "TimestampMonotonic", "t", NULL, offsetof(UserStatusInfo, timestamp.monotonic) }, { "Display", "(so)", prop_map_first_of_struct, offsetof(UserStatusInfo, display) }, { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(UserStatusInfo, sessions) }, {} }; char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char since2[FORMAT_TIMESTAMP_MAX], *s2; _cleanup_(user_status_info_clear) UserStatusInfo i = {}; int r; r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i); if (r < 0) return log_error_errno(r, "Could not get properties: %m"); if (*new_line) printf("\n"); *new_line = true; if (i.name) printf("%s (%u)\n", i.name, (unsigned) i.uid); else printf("%u\n", (unsigned) i.uid); s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime); s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime); if (s1) printf("\t Since: %s; %s\n", s2, s1); else if (s2) printf("\t Since: %s\n", s2); if (!isempty(i.state)) printf("\t State: %s\n", i.state); if (!strv_isempty(i.sessions)) { char **l; printf("\tSessions:"); STRV_FOREACH(l, i.sessions) { if (streq_ptr(*l, i.display)) printf(" *%s", *l); else printf(" %s", *l); } printf("\n"); } if (i.slice) { printf("\t Unit: %s\n", i.slice); show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0); show_journal_by_unit( stdout, i.slice, arg_output, 0, i.timestamp.monotonic, arg_lines, 0, get_output_flags() | OUTPUT_BEGIN_NEWLINE, SD_JOURNAL_LOCAL_ONLY, true, NULL); } return 0; } static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) { static const struct bus_properties_map map[] = { { "Id", "s", NULL, offsetof(SeatStatusInfo, id) }, { "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) }, { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) }, {} }; _cleanup_(seat_status_info_clear) SeatStatusInfo i = {}; int r; r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i); if (r < 0) return log_error_errno(r, "Could not get properties: %m"); if (*new_line) printf("\n"); *new_line = true; printf("%s\n", strna(i.id)); if (!strv_isempty(i.sessions)) { char **l; printf("\tSessions:"); STRV_FOREACH(l, i.sessions) { if (streq_ptr(*l, i.active_session)) printf(" *%s", *l); else printf(" %s", *l); } printf("\n"); } if (arg_transport == BUS_TRANSPORT_LOCAL) { unsigned c; c = columns(); if (c > 21) c -= 21; else c = 0; printf("\t Devices:\n"); show_sysfs(i.id, "\t\t ", c); } return 0; } static int print_property(const char *name, sd_bus_message *m, const char *contents) { int r; assert(name); assert(m); assert(contents); if (arg_property && !strv_find(arg_property, name)) /* skip what we didn't read */ return sd_bus_message_skip(m, contents); switch (contents[0]) { case SD_BUS_TYPE_STRUCT_BEGIN: if (contents[1] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) { const char *s; r = sd_bus_message_read(m, "(so)", &s, NULL); if (r < 0) return bus_log_parse_error(r); if (arg_all || !isempty(s)) printf("%s=%s\n", name, s); return 0; } else if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "User")) { uint32_t uid; r = sd_bus_message_read(m, "(uo)", &uid, NULL); if (r < 0) return bus_log_parse_error(r); if (!uid_is_valid(uid)) { log_error("Invalid user ID: " UID_FMT, uid); return -EINVAL; } printf("%s=" UID_FMT "\n", name, uid); return 0; } break; case SD_BUS_TYPE_ARRAY: if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) { const char *s; bool space = false; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(so)"); if (r < 0) return bus_log_parse_error(r); printf("%s=", name); while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) { printf("%s%s", space ? " " : "", s); space = true; } printf("\n"); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); return 0; } break; } r = bus_print_property(name, m, arg_all); if (r < 0) return bus_log_parse_error(r); if (r == 0) { r = sd_bus_message_skip(m, contents); if (r < 0) return bus_log_parse_error(r); if (arg_all) printf("%s=[unprintable]\n", name); } return 0; } static int show_properties(sd_bus *bus, const char *path, bool *new_line) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); assert(path); assert(new_line); r = sd_bus_call_method( bus, "org.freedesktop.login1", path, "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", ""); if (r < 0) return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r)); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}"); if (r < 0) return bus_log_parse_error(r); if (*new_line) printf("\n"); *new_line = true; while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { const char *name, *contents; r = sd_bus_message_read(reply, "s", &name); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_peek_type(reply, NULL, &contents); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents); if (r < 0) return bus_log_parse_error(r); r = print_property(name, reply, contents); if (r < 0) return r; r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); return 0; } static int show_session(int argc, char *argv[], void *userdata) { bool properties, new_line = false; sd_bus *bus = userdata; int r, i; assert(bus); assert(argv); properties = !strstr(argv[0], "status"); pager_open_if_enabled(); if (argc <= 1) { /* If not argument is specified inspect the manager * itself */ if (properties) return show_properties(bus, "/org/freedesktop/login1", &new_line); /* And in the pretty case, show data of the calling session */ return print_session_status_info(bus, "/org/freedesktop/login1/session/self", &new_line); } for (i = 1; i < argc; i++) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL; const char *path = NULL; r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "GetSession", &error, &reply, "s", argv[i]); if (r < 0) { log_error("Failed to get session: %s", bus_error_message(&error, r)); return r; } r = sd_bus_message_read(reply, "o", &path); if (r < 0) return bus_log_parse_error(r); if (properties) r = show_properties(bus, path, &new_line); else r = print_session_status_info(bus, path, &new_line); if (r < 0) return r; } return 0; } static int show_user(int argc, char *argv[], void *userdata) { bool properties, new_line = false; sd_bus *bus = userdata; int r, i; assert(bus); assert(argv); properties = !strstr(argv[0], "status"); pager_open_if_enabled(); if (argc <= 1) { /* If not argument is specified inspect the manager * itself */ if (properties) return show_properties(bus, "/org/freedesktop/login1", &new_line); return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line); } for (i = 1; i < argc; i++) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL; const char *path = NULL; uid_t uid; r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to look up user %s: %m", argv[i]); r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "GetUser", &error, &reply, "u", (uint32_t) uid); if (r < 0) { log_error("Failed to get user: %s", bus_error_message(&error, r)); return r; } r = sd_bus_message_read(reply, "o", &path); if (r < 0) return bus_log_parse_error(r); if (properties) r = show_properties(bus, path, &new_line); else r = print_user_status_info(bus, path, &new_line); if (r < 0) return r; } return 0; } static int show_seat(int argc, char *argv[], void *userdata) { bool properties, new_line = false; sd_bus *bus = userdata; int r, i; assert(bus); assert(argv); properties = !strstr(argv[0], "status"); pager_open_if_enabled(); if (argc <= 1) { /* If not argument is specified inspect the manager * itself */ if (properties) return show_properties(bus, "/org/freedesktop/login1", &new_line); return print_seat_status_info(bus, "/org/freedesktop/login1/seat/self", &new_line); } for (i = 1; i < argc; i++) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL; const char *path = NULL; r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "GetSeat", &error, &reply, "s", argv[i]); if (r < 0) { log_error("Failed to get seat: %s", bus_error_message(&error, r)); return r; } r = sd_bus_message_read(reply, "o", &path); if (r < 0) return bus_log_parse_error(r); if (properties) r = show_properties(bus, path, &new_line); else r = print_seat_status_info(bus, path, &new_line); if (r < 0) return r; } return 0; } static int activate(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; char *short_argv[3]; int r, i; assert(bus); assert(argv); polkit_agent_open_if_enabled(); if (argc < 2) { /* No argument? Let's convert this into the empty * session name, which the calls will then resolve to * the caller's session. */ short_argv[0] = argv[0]; short_argv[1] = (char*) ""; short_argv[2] = NULL; argv = short_argv; argc = 2; } for (i = 1; i < argc; i++) { r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", streq(argv[0], "lock-session") ? "LockSession" : streq(argv[0], "unlock-session") ? "UnlockSession" : streq(argv[0], "terminate-session") ? "TerminateSession" : "ActivateSession", &error, NULL, "s", argv[i]); if (r < 0) { log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); return r; } } return 0; } static int kill_session(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r, i; assert(bus); assert(argv); polkit_agent_open_if_enabled(); if (!arg_kill_who) arg_kill_who = "all"; for (i = 1; i < argc; i++) { r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "KillSession", &error, NULL, "ssi", argv[i], arg_kill_who, arg_signal); if (r < 0) { log_error("Could not kill session: %s", bus_error_message(&error, -r)); return r; } } return 0; } static int enable_linger(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; char* short_argv[3]; bool b; int r, i; assert(bus); assert(argv); polkit_agent_open_if_enabled(); b = streq(argv[0], "enable-linger"); if (argc < 2) { short_argv[0] = argv[0]; short_argv[1] = (char*) ""; short_argv[2] = NULL; argv = short_argv; argc = 2; } for (i = 1; i < argc; i++) { uid_t uid; if (isempty(argv[i])) uid = UID_INVALID; else { r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to look up user %s: %m", argv[i]); } r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "SetUserLinger", &error, NULL, "ubb", (uint32_t) uid, b, true); if (r < 0) { log_error("Could not enable linger: %s", bus_error_message(&error, -r)); return r; } } return 0; } static int terminate_user(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r, i; assert(bus); assert(argv); polkit_agent_open_if_enabled(); for (i = 1; i < argc; i++) { uid_t uid; r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to look up user %s: %m", argv[i]); r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "TerminateUser", &error, NULL, "u", (uint32_t) uid); if (r < 0) { log_error("Could not terminate user: %s", bus_error_message(&error, -r)); return r; } } return 0; } static int kill_user(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r, i; assert(bus); assert(argv); polkit_agent_open_if_enabled(); if (!arg_kill_who) arg_kill_who = "all"; for (i = 1; i < argc; i++) { uid_t uid; r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to look up user %s: %m", argv[i]); r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "KillUser", &error, NULL, "ui", (uint32_t) uid, arg_signal); if (r < 0) { log_error("Could not kill user: %s", bus_error_message(&error, -r)); return r; } } return 0; } static int attach(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r, i; assert(bus); assert(argv); polkit_agent_open_if_enabled(); for (i = 2; i < argc; i++) { r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "AttachDevice", &error, NULL, "ssb", argv[1], argv[i], true); if (r < 0) { log_error("Could not attach device: %s", bus_error_message(&error, -r)); return r; } } return 0; } static int flush_devices(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r; assert(bus); assert(argv); polkit_agent_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "FlushDevices", &error, NULL, "b", true); if (r < 0) log_error("Could not flush devices: %s", bus_error_message(&error, -r)); return r; } static int lock_sessions(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r; assert(bus); assert(argv); polkit_agent_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions", &error, NULL, NULL); if (r < 0) log_error("Could not lock sessions: %s", bus_error_message(&error, -r)); return r; } static int terminate_seat(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r, i; assert(bus); assert(argv); polkit_agent_open_if_enabled(); for (i = 1; i < argc; i++) { r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "TerminateSeat", &error, NULL, "s", argv[i]); if (r < 0) { log_error("Could not terminate seat: %s", bus_error_message(&error, -r)); return r; } } return 0; } static int help(int argc, char *argv[], void *userdata) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" "Send control commands to or query the login manager.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " --no-legend Do not show the headers and footers\n" " --no-ask-password Don't prompt for password\n" " -H --host=[USER@]HOST Operate on remote host\n" " -M --machine=CONTAINER Operate on local container\n" " -p --property=NAME Show only properties by this name\n" " -a --all Show all properties, including empty ones\n" " -l --full Do not ellipsize output\n" " --kill-who=WHO Who to send signal to\n" " -s --signal=SIGNAL Which signal to send\n" " -n --lines=INTEGER Number of journal entries to show\n" " -o --output=STRING Change journal output mode (short, short-monotonic,\n" " verbose, export, json, json-pretty, json-sse, cat)\n\n" "Session Commands:\n" " list-sessions List sessions\n" " session-status [ID...] Show session status\n" " show-session [ID...] Show properties of sessions or the manager\n" " activate [ID] Activate a session\n" " lock-session [ID...] Screen lock one or more sessions\n" " unlock-session [ID...] Screen unlock one or more sessions\n" " lock-sessions Screen lock all current sessions\n" " unlock-sessions Screen unlock all current sessions\n" " terminate-session ID... Terminate one or more sessions\n" " kill-session ID... Send signal to processes of a session\n\n" "User Commands:\n" " list-users List users\n" " user-status [USER...] Show user status\n" " show-user [USER...] Show properties of users or the manager\n" " enable-linger [USER...] Enable linger state of one or more users\n" " disable-linger [USER...] Disable linger state of one or more users\n" " terminate-user USER... Terminate all sessions of one or more users\n" " kill-user USER... Send signal to processes of a user\n\n" "Seat Commands:\n" " list-seats List seats\n" " seat-status [NAME...] Show seat status\n" " show-seat [NAME...] Show properties of seats or the manager\n" " attach NAME DEVICE... Attach one or more devices to a seat\n" " flush-devices Flush all device associations\n" " terminate-seat NAME... Terminate all sessions on one or more seats\n" , program_invocation_short_name); return 0; } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_LEGEND, ARG_KILL_WHO, ARG_NO_ASK_PASSWORD, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "property", required_argument, NULL, 'p' }, { "all", no_argument, NULL, 'a' }, { "full", no_argument, NULL, 'l' }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, { "kill-who", required_argument, NULL, ARG_KILL_WHO }, { "signal", required_argument, NULL, 's' }, { "host", required_argument, NULL, 'H' }, { "machine", required_argument, NULL, 'M' }, { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, { "lines", required_argument, NULL, 'n' }, { "output", required_argument, NULL, 'o' }, {} }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:", options, NULL)) >= 0) switch (c) { case 'h': help(0, NULL, NULL); return 0; case ARG_VERSION: return version(); case 'p': { r = strv_extend(&arg_property, optarg); if (r < 0) return log_oom(); /* If the user asked for a particular * property, show it to him, even if it is * empty. */ arg_all = true; break; } case 'a': arg_all = true; break; case 'l': arg_full = true; break; case 'n': if (safe_atou(optarg, &arg_lines) < 0) { log_error("Failed to parse lines '%s'", optarg); return -EINVAL; } break; case 'o': arg_output = output_mode_from_string(optarg); if (arg_output < 0) { log_error("Unknown output '%s'.", optarg); return -EINVAL; } break; case ARG_NO_PAGER: arg_no_pager = true; break; case ARG_NO_LEGEND: arg_legend = false; break; case ARG_NO_ASK_PASSWORD: arg_ask_password = false; break; case ARG_KILL_WHO: arg_kill_who = optarg; break; case 's': arg_signal = signal_from_string_try_harder(optarg); if (arg_signal < 0) { log_error("Failed to parse signal string %s.", optarg); return -EINVAL; } break; case 'H': arg_transport = BUS_TRANSPORT_REMOTE; arg_host = optarg; break; case 'M': arg_transport = BUS_TRANSPORT_MACHINE; arg_host = optarg; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } static int loginctl_main(int argc, char *argv[], sd_bus *bus) { static const Verb verbs[] = { { "help", VERB_ANY, VERB_ANY, 0, help }, { "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions }, { "session-status", VERB_ANY, VERB_ANY, 0, show_session }, { "show-session", VERB_ANY, VERB_ANY, 0, show_session }, { "activate", VERB_ANY, 2, 0, activate }, { "lock-session", VERB_ANY, VERB_ANY, 0, activate }, { "unlock-session", VERB_ANY, VERB_ANY, 0, activate }, { "lock-sessions", VERB_ANY, 1, 0, lock_sessions }, { "unlock-sessions", VERB_ANY, 1, 0, lock_sessions }, { "terminate-session", 2, VERB_ANY, 0, activate }, { "kill-session", 2, VERB_ANY, 0, kill_session }, { "list-users", VERB_ANY, 1, 0, list_users }, { "user-status", VERB_ANY, VERB_ANY, 0, show_user }, { "show-user", VERB_ANY, VERB_ANY, 0, show_user }, { "enable-linger", VERB_ANY, VERB_ANY, 0, enable_linger }, { "disable-linger", VERB_ANY, VERB_ANY, 0, enable_linger }, { "terminate-user", 2, VERB_ANY, 0, terminate_user }, { "kill-user", 2, VERB_ANY, 0, kill_user }, { "list-seats", VERB_ANY, 1, 0, list_seats }, { "seat-status", VERB_ANY, VERB_ANY, 0, show_seat }, { "show-seat", VERB_ANY, VERB_ANY, 0, show_seat }, { "attach", 3, VERB_ANY, 0, attach }, { "flush-devices", VERB_ANY, 1, 0, flush_devices }, { "terminate-seat", 2, VERB_ANY, 0, terminate_seat }, {} }; return dispatch_verb(argc, argv, verbs, bus); } int main(int argc, char *argv[]) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = bus_connect_transport(arg_transport, arg_host, false, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; } sd_bus_set_allow_interactive_authorization(bus, arg_ask_password); r = loginctl_main(argc, argv, bus); finish: pager_close(); polkit_agent_close(); strv_free(arg_property); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/login/logind-acl.c000066400000000000000000000206521265713322000171420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "acl-util.h" #include "alloc-util.h" #include "dirent-util.h" #include "escape.h" #include "fd-util.h" #include "formats-util.h" #include "logind-acl.h" #include "set.h" #include "string-util.h" #include "udev-util.h" #include "util.h" static int flush_acl(acl_t acl) { acl_entry_t i; int found; bool changed = false; assert(acl); for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); found > 0; found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { acl_tag_t tag; if (acl_get_tag_type(i, &tag) < 0) return -errno; if (tag != ACL_USER) continue; if (acl_delete_entry(acl, i) < 0) return -errno; changed = true; } if (found < 0) return -errno; return changed; } int devnode_acl(const char *path, bool flush, bool del, uid_t old_uid, bool add, uid_t new_uid) { acl_t acl; int r = 0; bool changed = false; assert(path); acl = acl_get_file(path, ACL_TYPE_ACCESS); if (!acl) return -errno; if (flush) { r = flush_acl(acl); if (r < 0) goto finish; if (r > 0) changed = true; } else if (del && old_uid > 0) { acl_entry_t entry; r = acl_find_uid(acl, old_uid, &entry); if (r < 0) goto finish; if (r > 0) { if (acl_delete_entry(acl, entry) < 0) { r = -errno; goto finish; } changed = true; } } if (add && new_uid > 0) { acl_entry_t entry; acl_permset_t permset; int rd, wt; r = acl_find_uid(acl, new_uid, &entry); if (r < 0) goto finish; if (r == 0) { if (acl_create_entry(&acl, &entry) < 0) { r = -errno; goto finish; } if (acl_set_tag_type(entry, ACL_USER) < 0 || acl_set_qualifier(entry, &new_uid) < 0) { r = -errno; goto finish; } } if (acl_get_permset(entry, &permset) < 0) { r = -errno; goto finish; } rd = acl_get_perm(permset, ACL_READ); if (rd < 0) { r = -errno; goto finish; } wt = acl_get_perm(permset, ACL_WRITE); if (wt < 0) { r = -errno; goto finish; } if (!rd || !wt) { if (acl_add_perm(permset, ACL_READ|ACL_WRITE) < 0) { r = -errno; goto finish; } changed = true; } } if (!changed) goto finish; if (acl_calc_mask(&acl) < 0) { r = -errno; goto finish; } if (acl_set_file(path, ACL_TYPE_ACCESS, acl) < 0) { r = -errno; goto finish; } r = 0; finish: acl_free(acl); return r; } int devnode_acl_all(struct udev *udev, const char *seat, bool flush, bool del, uid_t old_uid, bool add, uid_t new_uid) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; struct udev_list_entry *item = NULL, *first = NULL; _cleanup_set_free_free_ Set *nodes = NULL; _cleanup_closedir_ DIR *dir = NULL; struct dirent *dent; Iterator i; char *n; int r; assert(udev); nodes = set_new(&string_hash_ops); if (!nodes) return -ENOMEM; e = udev_enumerate_new(udev); if (!e) return -ENOMEM; if (isempty(seat)) seat = "seat0"; /* We can only match by one tag in libudev. We choose * "uaccess" for that. If we could match for two tags here we * could add the seat name as second match tag, but this would * be hardly optimizable in libudev, and hence checking the * second tag manually in our loop is a good solution. */ r = udev_enumerate_add_match_tag(e, "uaccess"); if (r < 0) return r; r = udev_enumerate_add_match_is_initialized(e); if (r < 0) return r; r = udev_enumerate_scan_devices(e); if (r < 0) return r; first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; const char *node, *sn; d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!d) return -ENOMEM; sn = udev_device_get_property_value(d, "ID_SEAT"); if (isempty(sn)) sn = "seat0"; if (!streq(seat, sn)) continue; node = udev_device_get_devnode(d); /* In case people mistag devices with nodes, we need to ignore this */ if (!node) continue; n = strdup(node); if (!n) return -ENOMEM; log_debug("Found udev node %s for seat %s", n, seat); r = set_consume(nodes, n); if (r < 0) return r; } /* udev exports "dead" device nodes to allow module on-demand loading, * these devices are not known to the kernel at this moment */ dir = opendir("/run/udev/static_node-tags/uaccess"); if (dir) { FOREACH_DIRENT(dent, dir, return -errno) { _cleanup_free_ char *unescaped_devname = NULL; if (cunescape(dent->d_name, UNESCAPE_RELAX, &unescaped_devname) < 0) return -ENOMEM; n = strappend("/dev/", unescaped_devname); if (!n) return -ENOMEM; log_debug("Found static node %s for seat %s", n, seat); r = set_consume(nodes, n); if (r == -EEXIST) continue; if (r < 0) return r; } } r = 0; SET_FOREACH(n, nodes, i) { int k; log_debug("Changing ACLs at %s for seat %s (uid "UID_FMT"→"UID_FMT"%s%s)", n, seat, old_uid, new_uid, del ? " del" : "", add ? " add" : ""); k = devnode_acl(n, flush, del, old_uid, add, new_uid); if (k == -ENOENT) log_debug("Device %s disappeared while setting ACLs", n); else if (k < 0 && r == 0) r = k; } return r; } systemd-229/src/login/logind-acl.h000066400000000000000000000031621265713322000171440ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "libudev.h" #ifdef HAVE_ACL int devnode_acl(const char *path, bool flush, bool del, uid_t old_uid, bool add, uid_t new_uid); int devnode_acl_all(struct udev *udev, const char *seat, bool flush, bool del, uid_t old_uid, bool add, uid_t new_uid); #else static inline int devnode_acl(const char *path, bool flush, bool del, uid_t old_uid, bool add, uid_t new_uid) { return 0; } static inline int devnode_acl_all(struct udev *udev, const char *seat, bool flush, bool del, uid_t old_uid, bool add, uid_t new_uid) { return 0; } #endif systemd-229/src/login/logind-action.c000066400000000000000000000152751265713322000176650ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "conf-parser.h" #include "formats-util.h" #include "logind-action.h" #include "process-util.h" #include "sleep-config.h" #include "special.h" #include "string-table.h" #include "terminal-util.h" #include "user-util.h" int manager_handle_action( Manager *m, InhibitWhat inhibit_key, HandleAction handle, bool ignore_inhibited, bool is_edge) { static const char * const message_table[_HANDLE_ACTION_MAX] = { [HANDLE_POWEROFF] = "Powering Off...", [HANDLE_REBOOT] = "Rebooting...", [HANDLE_HALT] = "Halting...", [HANDLE_KEXEC] = "Rebooting via kexec...", [HANDLE_SUSPEND] = "Suspending...", [HANDLE_HIBERNATE] = "Hibernating...", [HANDLE_HYBRID_SLEEP] = "Hibernating and suspending..." }; static const char * const target_table[_HANDLE_ACTION_MAX] = { [HANDLE_POWEROFF] = SPECIAL_POWEROFF_TARGET, [HANDLE_REBOOT] = SPECIAL_REBOOT_TARGET, [HANDLE_HALT] = SPECIAL_HALT_TARGET, [HANDLE_KEXEC] = SPECIAL_KEXEC_TARGET, [HANDLE_SUSPEND] = SPECIAL_SUSPEND_TARGET, [HANDLE_HIBERNATE] = SPECIAL_HIBERNATE_TARGET, [HANDLE_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET }; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; InhibitWhat inhibit_operation; Inhibitor *offending = NULL; bool supported; int r; assert(m); /* If the key handling is turned off, don't do anything */ if (handle == HANDLE_IGNORE) { log_debug("Refusing operation, as it is turned off."); return 0; } if (inhibit_key == INHIBIT_HANDLE_LID_SWITCH) { /* If the last system suspend or startup is too close, * let's not suspend for now, to give USB docking * stations some time to settle so that we can * properly watch its displays. */ if (m->lid_switch_ignore_event_source) { log_debug("Ignoring lid switch request, system startup or resume too close."); return 0; } } /* If the key handling is inhibited, don't do anything */ if (inhibit_key > 0) { if (manager_is_inhibited(m, inhibit_key, INHIBIT_BLOCK, NULL, true, false, 0, NULL)) { log_debug("Refusing operation, %s is inhibited.", inhibit_what_to_string(inhibit_key)); return 0; } } /* Locking is handled differently from the rest. */ if (handle == HANDLE_LOCK) { if (!is_edge) return 0; log_info("Locking sessions..."); session_send_lock_all(m, true); return 1; } if (handle == HANDLE_SUSPEND) supported = can_sleep("suspend") > 0; else if (handle == HANDLE_HIBERNATE) supported = can_sleep("hibernate") > 0; else if (handle == HANDLE_HYBRID_SLEEP) supported = can_sleep("hybrid-sleep") > 0; else if (handle == HANDLE_KEXEC) supported = access(KEXEC, X_OK) >= 0; else supported = true; if (!supported) { log_warning("Requested operation not supported, ignoring."); return -EOPNOTSUPP; } if (m->action_what) { log_debug("Action already in progress, ignoring."); return -EALREADY; } inhibit_operation = handle == HANDLE_SUSPEND || handle == HANDLE_HIBERNATE || handle == HANDLE_HYBRID_SLEEP ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN; /* If the actual operation is inhibited, warn and fail */ if (!ignore_inhibited && manager_is_inhibited(m, inhibit_operation, INHIBIT_BLOCK, NULL, false, false, 0, &offending)) { _cleanup_free_ char *comm = NULL, *u = NULL; get_process_comm(offending->pid, &comm); u = uid_to_name(offending->uid); /* If this is just a recheck of the lid switch then don't warn about anything */ if (!is_edge) { log_debug("Refusing operation, %s is inhibited by UID "UID_FMT"/%s, PID "PID_FMT"/%s.", inhibit_what_to_string(inhibit_operation), offending->uid, strna(u), offending->pid, strna(comm)); return 0; } log_error("Refusing operation, %s is inhibited by UID "UID_FMT"/%s, PID "PID_FMT"/%s.", inhibit_what_to_string(inhibit_operation), offending->uid, strna(u), offending->pid, strna(comm)); return -EPERM; } log_info("%s", message_table[handle]); r = bus_manager_shutdown_or_sleep_now_or_later(m, target_table[handle], inhibit_operation, &error); if (r < 0) { log_error("Failed to execute operation: %s", bus_error_message(&error, r)); return r; } return 1; } static const char* const handle_action_table[_HANDLE_ACTION_MAX] = { [HANDLE_IGNORE] = "ignore", [HANDLE_POWEROFF] = "poweroff", [HANDLE_REBOOT] = "reboot", [HANDLE_HALT] = "halt", [HANDLE_KEXEC] = "kexec", [HANDLE_SUSPEND] = "suspend", [HANDLE_HIBERNATE] = "hibernate", [HANDLE_HYBRID_SLEEP] = "hybrid-sleep", [HANDLE_LOCK] = "lock" }; DEFINE_STRING_TABLE_LOOKUP(handle_action, HandleAction); DEFINE_CONFIG_PARSE_ENUM(config_parse_handle_action, handle_action, HandleAction, "Failed to parse handle action setting"); systemd-229/src/login/logind-action.h000066400000000000000000000031531265713322000176620ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef enum HandleAction { HANDLE_IGNORE, HANDLE_POWEROFF, HANDLE_REBOOT, HANDLE_HALT, HANDLE_KEXEC, HANDLE_SUSPEND, HANDLE_HIBERNATE, HANDLE_HYBRID_SLEEP, HANDLE_LOCK, _HANDLE_ACTION_MAX, _HANDLE_ACTION_INVALID = -1 } HandleAction; #include "logind-inhibit.h" #include "logind.h" int manager_handle_action( Manager *m, InhibitWhat inhibit_key, HandleAction handle, bool ignore_inhibited, bool is_edge); const char* handle_action_to_string(HandleAction h) _const_; HandleAction handle_action_from_string(const char *s) _pure_; int config_parse_handle_action(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); systemd-229/src/login/logind-button.c000066400000000000000000000212001265713322000177040ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "sd-messages.h" #include "alloc-util.h" #include "fd-util.h" #include "logind-button.h" #include "string-util.h" #include "util.h" Button* button_new(Manager *m, const char *name) { Button *b; assert(m); assert(name); b = new0(Button, 1); if (!b) return NULL; b->name = strdup(name); if (!b->name) { free(b); return NULL; } if (hashmap_put(m->buttons, b->name, b) < 0) { free(b->name); free(b); return NULL; } b->manager = m; b->fd = -1; return b; } void button_free(Button *b) { assert(b); hashmap_remove(b->manager->buttons, b->name); sd_event_source_unref(b->io_event_source); sd_event_source_unref(b->check_event_source); if (b->fd >= 0) /* If the device has been unplugged close() returns * ENODEV, let's ignore this, hence we don't use * safe_close() */ (void) close(b->fd); free(b->name); free(b->seat); free(b); } int button_set_seat(Button *b, const char *sn) { char *s; assert(b); assert(sn); s = strdup(sn); if (!s) return -ENOMEM; free(b->seat); b->seat = s; return 0; } static void button_lid_switch_handle_action(Manager *manager, bool is_edge) { HandleAction handle_action; assert(manager); /* If we are docked, handle the lid switch differently */ if (manager_is_docked_or_external_displays(manager)) handle_action = manager->handle_lid_switch_docked; else handle_action = manager->handle_lid_switch; manager_handle_action(manager, INHIBIT_HANDLE_LID_SWITCH, handle_action, manager->lid_switch_ignore_inhibited, is_edge); } static int button_recheck(sd_event_source *e, void *userdata) { Button *b = userdata; assert(b); assert(b->lid_closed); button_lid_switch_handle_action(b->manager, false); return 1; } static int button_install_check_event_source(Button *b) { int r; assert(b); /* Install a post handler, so that we keep rechecking as long as the lid is closed. */ if (b->check_event_source) return 0; r = sd_event_add_post(b->manager->event, &b->check_event_source, button_recheck, b); if (r < 0) return r; return sd_event_source_set_priority(b->check_event_source, SD_EVENT_PRIORITY_IDLE+1); } static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Button *b = userdata; struct input_event ev; ssize_t l; assert(s); assert(fd == b->fd); assert(b); l = read(b->fd, &ev, sizeof(ev)); if (l < 0) return errno != EAGAIN ? -errno : 0; if ((size_t) l < sizeof(ev)) return -EIO; if (ev.type == EV_KEY && ev.value > 0) { switch (ev.code) { case KEY_POWER: case KEY_POWER2: log_struct(LOG_INFO, LOG_MESSAGE("Power key pressed."), LOG_MESSAGE_ID(SD_MESSAGE_POWER_KEY), NULL); manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true); break; /* The kernel is a bit confused here: KEY_SLEEP = suspend-to-ram, which everybody else calls "suspend" KEY_SUSPEND = suspend-to-disk, which everybody else calls "hibernate" */ case KEY_SLEEP: log_struct(LOG_INFO, LOG_MESSAGE("Suspend key pressed."), LOG_MESSAGE_ID(SD_MESSAGE_SUSPEND_KEY), NULL); manager_handle_action(b->manager, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true); break; case KEY_SUSPEND: log_struct(LOG_INFO, LOG_MESSAGE("Hibernate key pressed."), LOG_MESSAGE_ID(SD_MESSAGE_HIBERNATE_KEY), NULL); manager_handle_action(b->manager, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true); break; } } else if (ev.type == EV_SW && ev.value > 0) { if (ev.code == SW_LID) { log_struct(LOG_INFO, LOG_MESSAGE("Lid closed."), LOG_MESSAGE_ID(SD_MESSAGE_LID_CLOSED), NULL); b->lid_closed = true; button_lid_switch_handle_action(b->manager, true); button_install_check_event_source(b); } else if (ev.code == SW_DOCK) { log_struct(LOG_INFO, LOG_MESSAGE("System docked."), LOG_MESSAGE_ID(SD_MESSAGE_SYSTEM_DOCKED), NULL); b->docked = true; } } else if (ev.type == EV_SW && ev.value == 0) { if (ev.code == SW_LID) { log_struct(LOG_INFO, LOG_MESSAGE("Lid opened."), LOG_MESSAGE_ID(SD_MESSAGE_LID_OPENED), NULL); b->lid_closed = false; b->check_event_source = sd_event_source_unref(b->check_event_source); } else if (ev.code == SW_DOCK) { log_struct(LOG_INFO, LOG_MESSAGE("System undocked."), LOG_MESSAGE_ID(SD_MESSAGE_SYSTEM_UNDOCKED), NULL); b->docked = false; } } return 0; } int button_open(Button *b) { char *p, name[256]; int r; assert(b); b->fd = safe_close(b->fd); p = strjoina("/dev/input/", b->name); b->fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); if (b->fd < 0) return log_warning_errno(errno, "Failed to open %s: %m", b->name); if (ioctl(b->fd, EVIOCGNAME(sizeof(name)), name) < 0) { r = log_error_errno(errno, "Failed to get input name: %m"); goto fail; } r = sd_event_add_io(b->manager->event, &b->io_event_source, b->fd, EPOLLIN, button_dispatch, b); if (r < 0) { log_error_errno(r, "Failed to add button event: %m"); goto fail; } log_info("Watching system buttons on /dev/input/%s (%s)", b->name, name); return 0; fail: b->fd = safe_close(b->fd); return r; } int button_check_switches(Button *b) { uint8_t switches[SW_MAX/8+1] = {}; assert(b); if (b->fd < 0) return -EINVAL; if (ioctl(b->fd, EVIOCGSW(sizeof(switches)), switches) < 0) return -errno; b->lid_closed = (switches[SW_LID/8] >> (SW_LID % 8)) & 1; b->docked = (switches[SW_DOCK/8] >> (SW_DOCK % 8)) & 1; if (b->lid_closed) button_install_check_event_source(b); return 0; } systemd-229/src/login/logind-button.h000066400000000000000000000022771265713322000177260ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Button Button; #include "logind.h" struct Button { Manager *manager; sd_event_source *io_event_source; sd_event_source *check_event_source; char *name; char *seat; int fd; bool lid_closed; bool docked; }; Button* button_new(Manager *m, const char *name); void button_free(Button*b); int button_open(Button *b); int button_set_seat(Button *b, const char *sn); int button_check_switches(Button *b); systemd-229/src/login/logind-core.c000066400000000000000000000355571265713322000173450ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "cgroup-util.h" #include "fd-util.h" #include "logind.h" #include "strv.h" #include "terminal-util.h" #include "udev-util.h" #include "user-util.h" int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) { Device *d; assert(m); assert(sysfs); d = hashmap_get(m->devices, sysfs); if (d) /* we support adding master-flags, but not removing them */ d->master = d->master || master; else { d = device_new(m, sysfs, master); if (!d) return -ENOMEM; } if (_device) *_device = d; return 0; } int manager_add_seat(Manager *m, const char *id, Seat **_seat) { Seat *s; assert(m); assert(id); s = hashmap_get(m->seats, id); if (!s) { s = seat_new(m, id); if (!s) return -ENOMEM; } if (_seat) *_seat = s; return 0; } int manager_add_session(Manager *m, const char *id, Session **_session) { Session *s; assert(m); assert(id); s = hashmap_get(m->sessions, id); if (!s) { s = session_new(m, id); if (!s) return -ENOMEM; } if (_session) *_session = s; return 0; } int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) { User *u; int r; assert(m); assert(name); u = hashmap_get(m->users, UID_TO_PTR(uid)); if (!u) { r = user_new(&u, m, uid, gid, name); if (r < 0) return r; } if (_user) *_user = u; return 0; } int manager_add_user_by_name(Manager *m, const char *name, User **_user) { uid_t uid; gid_t gid; int r; assert(m); assert(name); r = get_user_creds(&name, &uid, &gid, NULL, NULL); if (r < 0) return r; return manager_add_user(m, uid, gid, name, _user); } int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) { struct passwd *p; assert(m); errno = 0; p = getpwuid(uid); if (!p) return errno > 0 ? -errno : -ENOENT; return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user); } int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) { Inhibitor *i; assert(m); assert(id); i = hashmap_get(m->inhibitors, id); if (i) { if (_inhibitor) *_inhibitor = i; return 0; } i = inhibitor_new(m, id); if (!i) return -ENOMEM; if (_inhibitor) *_inhibitor = i; return 0; } int manager_add_button(Manager *m, const char *name, Button **_button) { Button *b; assert(m); assert(name); b = hashmap_get(m->buttons, name); if (!b) { b = button_new(m, name); if (!b) return -ENOMEM; } if (_button) *_button = b; return 0; } int manager_process_seat_device(Manager *m, struct udev_device *d) { Device *device; int r; assert(m); if (streq_ptr(udev_device_get_action(d), "remove")) { device = hashmap_get(m->devices, udev_device_get_syspath(d)); if (!device) return 0; seat_add_to_gc_queue(device->seat); device_free(device); } else { const char *sn; Seat *seat = NULL; bool master; sn = udev_device_get_property_value(d, "ID_SEAT"); if (isempty(sn)) sn = "seat0"; if (!seat_name_is_valid(sn)) { log_warning("Device with invalid seat name %s found, ignoring.", sn); return 0; } seat = hashmap_get(m->seats, sn); master = udev_device_has_tag(d, "master-of-seat"); /* Ignore non-master devices for unknown seats */ if (!master && !seat) return 0; r = manager_add_device(m, udev_device_get_syspath(d), master, &device); if (r < 0) return r; if (!seat) { r = manager_add_seat(m, sn, &seat); if (r < 0) { if (!device->seat) device_free(device); return r; } } device_attach(device, seat); seat_start(seat); } return 0; } int manager_process_button_device(Manager *m, struct udev_device *d) { Button *b; int r; assert(m); if (streq_ptr(udev_device_get_action(d), "remove")) { b = hashmap_get(m->buttons, udev_device_get_sysname(d)); if (!b) return 0; button_free(b); } else { const char *sn; r = manager_add_button(m, udev_device_get_sysname(d), &b); if (r < 0) return r; sn = udev_device_get_property_value(d, "ID_SEAT"); if (isempty(sn)) sn = "seat0"; button_set_seat(b, sn); button_open(b); } return 0; } int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) { _cleanup_free_ char *unit = NULL; Session *s; int r; assert(m); if (pid < 1) return -EINVAL; r = cg_pid_get_unit(pid, &unit); if (r < 0) return 0; s = hashmap_get(m->session_units, unit); if (!s) return 0; if (session) *session = s; return 1; } int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) { _cleanup_free_ char *unit = NULL; User *u; int r; assert(m); assert(user); if (pid < 1) return -EINVAL; r = cg_pid_get_slice(pid, &unit); if (r < 0) return 0; u = hashmap_get(m->user_units, unit); if (!u) return 0; *user = u; return 1; } int manager_get_idle_hint(Manager *m, dual_timestamp *t) { Session *s; bool idle_hint; dual_timestamp ts = DUAL_TIMESTAMP_NULL; Iterator i; assert(m); idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0, NULL); HASHMAP_FOREACH(s, m->sessions, i) { dual_timestamp k; int ih; ih = session_get_idle_hint(s, &k); if (ih < 0) return ih; if (!ih) { if (!idle_hint) { if (k.monotonic < ts.monotonic) ts = k; } else { idle_hint = false; ts = k; } } else if (idle_hint) { if (k.monotonic > ts.monotonic) ts = k; } } if (t) *t = ts; return idle_hint; } bool manager_shall_kill(Manager *m, const char *user) { assert(m); assert(user); if (!m->kill_user_processes) return false; if (strv_contains(m->kill_exclude_users, user)) return false; if (strv_isempty(m->kill_only_users)) return true; return strv_contains(m->kill_only_users, user); } static int vt_is_busy(unsigned int vtnr) { struct vt_stat vt_stat; int r = 0; _cleanup_close_ int fd; assert(vtnr >= 1); /* We explicitly open /dev/tty1 here instead of /dev/tty0. If * we'd open the latter we'd open the foreground tty which * hence would be unconditionally busy. By opening /dev/tty1 * we avoid this. Since tty1 is special and needs to be an * explicitly loaded getty or DM this is safe. */ fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) return -errno; if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0) r = -errno; else r = !!(vt_stat.v_state & (1 << vtnr)); return r; } int manager_spawn_autovt(Manager *m, unsigned int vtnr) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char name[sizeof("autovt@tty.service") + DECIMAL_STR_MAX(unsigned int)]; int r; assert(m); assert(vtnr >= 1); if (vtnr > m->n_autovts && vtnr != m->reserve_vt) return 0; if (vtnr != m->reserve_vt) { /* If this is the reserved TTY, we'll start the getty * on it in any case, but otherwise only if it is not * busy. */ r = vt_is_busy(vtnr); if (r < 0) return r; else if (r > 0) return -EBUSY; } snprintf(name, sizeof(name), "autovt@tty%u.service", vtnr); r = sd_bus_call_method( m->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit", &error, NULL, "ss", name, "fail"); if (r < 0) log_error("Failed to start %s: %s", name, bus_error_message(&error, r)); return r; } static bool manager_is_docked(Manager *m) { Iterator i; Button *b; HASHMAP_FOREACH(b, m->buttons, i) if (b->docked) return true; return false; } static int manager_count_external_displays(Manager *m) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; struct udev_list_entry *item = NULL, *first = NULL; int r; int n = 0; e = udev_enumerate_new(m->udev); if (!e) return -ENOMEM; r = udev_enumerate_add_match_subsystem(e, "drm"); if (r < 0) return r; r = udev_enumerate_scan_devices(e); if (r < 0) return r; first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; struct udev_device *p; const char *status, *enabled, *dash, *nn, *i; bool external = false; d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item)); if (!d) return -ENOMEM; p = udev_device_get_parent(d); if (!p) continue; /* If the parent shares the same subsystem as the * device we are looking at then it is a connector, * which is what we are interested in. */ if (!streq_ptr(udev_device_get_subsystem(p), "drm")) continue; nn = udev_device_get_sysname(d); if (!nn) continue; /* Ignore internal displays: the type is encoded in * the sysfs name, as the second dash seperated item * (the first is the card name, the last the connector * number). We implement a whitelist of external * displays here, rather than a whitelist, to ensure * we don't block suspends too eagerly. */ dash = strchr(nn, '-'); if (!dash) continue; dash++; FOREACH_STRING(i, "VGA-", "DVI-I-", "DVI-D-", "DVI-A-" "Composite-", "SVIDEO-", "Component-", "DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-") { if (startswith(dash, i)) { external = true; break; } } if (!external) continue; /* Ignore ports that are not enabled */ enabled = udev_device_get_sysattr_value(d, "enabled"); if (!enabled) continue; if (!streq_ptr(enabled, "enabled")) continue; /* We count any connector which is not explicitly * "disconnected" as connected. */ status = udev_device_get_sysattr_value(d, "status"); if (!streq_ptr(status, "disconnected")) n++; } return n; } bool manager_is_docked_or_external_displays(Manager *m) { int n; /* If we are docked don't react to lid closing */ if (manager_is_docked(m)) { log_debug("System is docked."); return true; } /* If we have more than one display connected, * assume that we are docked. */ n = manager_count_external_displays(m); if (n < 0) log_warning_errno(n, "Display counting failed: %m"); else if (n >= 1) { log_debug("External (%i) displays connected.", n); return true; } return false; } systemd-229/src/login/logind-dbus.c000066400000000000000000003136351265713322000173460ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-messages.h" #include "alloc-util.h" #include "audit-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" #include "dirent-util.h" #include "efivars.h" #include "escape.h" #include "fd-util.h" #include "fileio-label.h" #include "formats-util.h" #include "fs-util.h" #include "logind.h" #include "mkdir.h" #include "path-util.h" #include "process-util.h" #include "selinux-util.h" #include "sleep-config.h" #include "special.h" #include "strv.h" #include "terminal-util.h" #include "udev-util.h" #include "unit-name.h" #include "user-util.h" #include "utmp-wtmp.h" int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; Session *session; int r; assert(m); assert(message); assert(ret); if (isempty(name)) { r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds); if (r < 0) return r; r = sd_bus_creds_get_session(creds, &name); if (r < 0) return r; } session = hashmap_get(m->sessions, name); if (!session) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name); *ret = session; return 0; } int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) { User *user; int r; assert(m); assert(message); assert(ret); if (uid == UID_INVALID) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; /* Note that we get the owner UID of the session, not the actual client UID here! */ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); if (r < 0) return r; r = sd_bus_creds_get_owner_uid(creds, &uid); if (r < 0) return r; } user = hashmap_get(m->users, UID_TO_PTR(uid)); if (!user) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid); *ret = user; return 0; } int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) { Seat *seat; int r; assert(m); assert(message); assert(ret); if (isempty(name)) { Session *session; r = manager_get_session_from_creds(m, message, NULL, error, &session); if (r < 0) return r; seat = session->seat; if (!seat) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat."); } else { seat = hashmap_get(m->seats, name); if (!seat) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name); } *ret = seat; return 0; } static int property_get_idle_hint( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; assert(bus); assert(reply); assert(m); return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0); } static int property_get_idle_since_hint( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; dual_timestamp t = DUAL_TIMESTAMP_NULL; assert(bus); assert(reply); assert(m); manager_get_idle_hint(m, &t); return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic); } static int property_get_inhibited( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; InhibitWhat w; assert(bus); assert(reply); assert(m); w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY); return sd_bus_message_append(reply, "s", inhibit_what_to_string(w)); } static int property_get_preparing( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; bool b; assert(bus); assert(reply); assert(m); if (streq(property, "PreparingForShutdown")) b = !!(m->action_what & INHIBIT_SHUTDOWN); else b = !!(m->action_what & INHIBIT_SLEEP); return sd_bus_message_append(reply, "b", b); } static int property_get_scheduled_shutdown( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; int r; assert(bus); assert(reply); assert(m); r = sd_bus_message_open_container(reply, 'r', "st"); if (r < 0) return r; r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout); if (r < 0) return r; return sd_bus_message_close_container(reply); } static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction); static int property_get_docked( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; assert(bus); assert(reply); assert(m); return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m)); } static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Manager *m = userdata; const char *name; Session *session; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = manager_get_session_from_creds(m, message, name, error, &session); if (r < 0) return r; p = session_bus_path(session); if (!p) return -ENOMEM; return sd_bus_reply_method_return(message, "o", p); } static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Session *session = NULL; Manager *m = userdata; pid_t pid; int r; assert(message); assert(m); assert_cc(sizeof(pid_t) == sizeof(uint32_t)); r = sd_bus_message_read(message, "u", &pid); if (r < 0) return r; if (pid < 0) return -EINVAL; if (pid == 0) { r = manager_get_session_from_creds(m, message, NULL, error, &session); if (r < 0) return r; } else { r = manager_get_session_by_pid(m, pid, &session); if (r < 0) return r; if (!session) return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid); } p = session_bus_path(session); if (!p) return -ENOMEM; return sd_bus_reply_method_return(message, "o", p); } static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Manager *m = userdata; uint32_t uid; User *user; int r; assert(message); assert(m); r = sd_bus_message_read(message, "u", &uid); if (r < 0) return r; r = manager_get_user_from_creds(m, message, uid, error, &user); if (r < 0) return r; p = user_bus_path(user); if (!p) return -ENOMEM; return sd_bus_reply_method_return(message, "o", p); } static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Manager *m = userdata; User *user = NULL; pid_t pid; int r; assert(message); assert(m); assert_cc(sizeof(pid_t) == sizeof(uint32_t)); r = sd_bus_message_read(message, "u", &pid); if (r < 0) return r; if (pid < 0) return -EINVAL; if (pid == 0) { r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user); if (r < 0) return r; } else { r = manager_get_user_by_pid(m, pid, &user); if (r < 0) return r; if (!user) return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "PID "PID_FMT" does not belong to any known or logged in user", pid); } p = user_bus_path(user); if (!p) return -ENOMEM; return sd_bus_reply_method_return(message, "o", p); } static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Manager *m = userdata; const char *name; Seat *seat; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = manager_get_seat_from_creds(m, message, name, error, &seat); if (r < 0) return r; p = seat_bus_path(seat); if (!p) return -ENOMEM; return sd_bus_reply_method_return(message, "o", p); } static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; Session *session; Iterator i; int r; assert(message); assert(m); r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "(susso)"); if (r < 0) return r; HASHMAP_FOREACH(session, m->sessions, i) { _cleanup_free_ char *p = NULL; p = session_bus_path(session); if (!p) return -ENOMEM; r = sd_bus_message_append(reply, "(susso)", session->id, (uint32_t) session->user->uid, session->user->name, session->seat ? session->seat->id : "", p); if (r < 0) return r; } r = sd_bus_message_close_container(reply); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); } static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; User *user; Iterator i; int r; assert(message); assert(m); r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "(uso)"); if (r < 0) return r; HASHMAP_FOREACH(user, m->users, i) { _cleanup_free_ char *p = NULL; p = user_bus_path(user); if (!p) return -ENOMEM; r = sd_bus_message_append(reply, "(uso)", (uint32_t) user->uid, user->name, p); if (r < 0) return r; } r = sd_bus_message_close_container(reply); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); } static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; Seat *seat; Iterator i; int r; assert(message); assert(m); r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "(so)"); if (r < 0) return r; HASHMAP_FOREACH(seat, m->seats, i) { _cleanup_free_ char *p = NULL; p = seat_bus_path(seat); if (!p) return -ENOMEM; r = sd_bus_message_append(reply, "(so)", seat->id, p); if (r < 0) return r; } r = sd_bus_message_close_container(reply); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); } static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; Inhibitor *inhibitor; Iterator i; int r; assert(message); assert(m); r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "(ssssuu)"); if (r < 0) return r; HASHMAP_FOREACH(inhibitor, m->inhibitors, i) { r = sd_bus_message_append(reply, "(ssssuu)", strempty(inhibit_what_to_string(inhibitor->what)), strempty(inhibitor->who), strempty(inhibitor->why), strempty(inhibit_mode_to_string(inhibitor->mode)), (uint32_t) inhibitor->uid, (uint32_t) inhibitor->pid); if (r < 0) return r; } r = sd_bus_message_close_container(reply); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); } static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop; uint32_t audit_id = 0; _cleanup_free_ char *id = NULL; Session *session = NULL; Manager *m = userdata; User *user = NULL; Seat *seat = NULL; pid_t leader; uid_t uid; int remote; uint32_t vtnr = 0; SessionType t; SessionClass c; int r; assert(message); assert(m); assert_cc(sizeof(pid_t) == sizeof(uint32_t)); assert_cc(sizeof(uid_t) == sizeof(uint32_t)); r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host); if (r < 0) return r; if (!uid_is_valid(uid)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID"); if (leader < 0 || leader == 1) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID"); if (isempty(type)) t = _SESSION_TYPE_INVALID; else { t = session_type_from_string(type); if (t < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type); } if (isempty(class)) c = _SESSION_CLASS_INVALID; else { c = session_class_from_string(class); if (c < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class); } if (isempty(desktop)) desktop = NULL; else { if (!string_is_safe(desktop)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop); } if (isempty(cseat)) seat = NULL; else { seat = hashmap_get(m->seats, cseat); if (!seat) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat); } if (tty_is_vc(tty)) { int v; if (!seat) seat = m->seat0; else if (seat != m->seat0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TTY %s is virtual console but seat %s is not seat0", tty, seat->id); v = vtnr_from_tty(tty); if (v <= 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty); if (!vtnr) vtnr = (uint32_t) v; else if (vtnr != (uint32_t) v) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match"); } else if (tty_is_console(tty)) { if (!seat) seat = m->seat0; else if (seat != m->seat0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0"); if (vtnr != 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0"); } if (seat) { if (seat_has_vts(seat)) { if (!vtnr || vtnr > 63) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range"); } else { if (vtnr != 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0"); } } r = sd_bus_message_enter_container(message, 'a', "(sv)"); if (r < 0) return r; if (t == _SESSION_TYPE_INVALID) { if (!isempty(display)) t = SESSION_X11; else if (!isempty(tty)) t = SESSION_TTY; else t = SESSION_UNSPECIFIED; } if (c == _SESSION_CLASS_INVALID) { if (t == SESSION_UNSPECIFIED) c = SESSION_BACKGROUND; else c = SESSION_USER; } if (leader == 0) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); if (r < 0) return r; r = sd_bus_creds_get_pid(creds, (pid_t*) &leader); if (r < 0) return r; } r = manager_get_session_by_pid(m, leader, NULL); if (r > 0) return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session"); /* * Old gdm and lightdm start the user-session on the same VT as * the greeter session. But they destroy the greeter session * after the user-session and want the user-session to take * over the VT. We need to support this for * backwards-compatibility, so make sure we allow new sessions * on a VT that a greeter is running on. Furthermore, to allow * re-logins, we have to allow a greeter to take over a used VT for * the exact same reasons. */ if (c != SESSION_GREETER && vtnr > 0 && vtnr < m->seat0->position_count && m->seat0->positions[vtnr] && m->seat0->positions[vtnr]->class != SESSION_GREETER) return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session"); audit_session_from_pid(leader, &audit_id); if (audit_id > 0) { /* Keep our session IDs and the audit session IDs in sync */ if (asprintf(&id, "%"PRIu32, audit_id) < 0) return -ENOMEM; /* Wut? There's already a session by this name and we * didn't find it above? Weird, then let's not trust * the audit data and let's better register a new * ID */ if (hashmap_get(m->sessions, id)) { log_warning("Existing logind session ID %s used by new audit session, ignoring", id); audit_id = 0; id = mfree(id); } } if (!id) { do { id = mfree(id); if (asprintf(&id, "c%lu", ++m->session_counter) < 0) return -ENOMEM; } while (hashmap_get(m->sessions, id)); } r = manager_add_user_by_uid(m, uid, &user); if (r < 0) goto fail; r = manager_add_session(m, id, &session); if (r < 0) goto fail; session_set_user(session, user); session->leader = leader; session->audit_id = audit_id; session->type = t; session->class = c; session->remote = remote; session->vtnr = vtnr; if (!isempty(tty)) { session->tty = strdup(tty); if (!session->tty) { r = -ENOMEM; goto fail; } } if (!isempty(display)) { session->display = strdup(display); if (!session->display) { r = -ENOMEM; goto fail; } } if (!isempty(remote_user)) { session->remote_user = strdup(remote_user); if (!session->remote_user) { r = -ENOMEM; goto fail; } } if (!isempty(remote_host)) { session->remote_host = strdup(remote_host); if (!session->remote_host) { r = -ENOMEM; goto fail; } } if (!isempty(service)) { session->service = strdup(service); if (!session->service) { r = -ENOMEM; goto fail; } } if (!isempty(desktop)) { session->desktop = strdup(desktop); if (!session->desktop) { r = -ENOMEM; goto fail; } } if (seat) { r = seat_attach_session(seat, session); if (r < 0) goto fail; } r = session_start(session); if (r < 0) goto fail; session->create_message = sd_bus_message_ref(message); /* Now, let's wait until the slice unit and stuff got * created. We send the reply back from * session_send_create_reply(). */ return 1; fail: if (session) session_add_to_gc_queue(session); if (user) user_add_to_gc_queue(user); return r; } static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Session *session; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = manager_get_session_from_creds(m, message, name, error, &session); if (r < 0) return r; r = session_release(session); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Session *session; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = manager_get_session_from_creds(m, message, name, error, &session); if (r < 0) return r; return bus_session_method_activate(message, session, error); } static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *session_name, *seat_name; Manager *m = userdata; Session *session; Seat *seat; int r; assert(message); assert(m); /* Same as ActivateSession() but refuses to work if * the seat doesn't match */ r = sd_bus_message_read(message, "ss", &session_name, &seat_name); if (r < 0) return r; r = manager_get_session_from_creds(m, message, session_name, error, &session); if (r < 0) return r; r = manager_get_seat_from_creds(m, message, seat_name, error, &seat); if (r < 0) return r; if (session->seat != seat) return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name); r = session_activate(session); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Session *session; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = manager_get_session_from_creds(m, message, name, error, &session); if (r < 0) return r; return bus_session_method_lock(message, session, error); } static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; int r; assert(message); assert(m); r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, "org.freedesktop.login1.lock-sessions", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions")); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *name; Manager *m = userdata; Session *session; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = manager_get_session_from_creds(m, message, name, error, &session); if (r < 0) return r; return bus_session_method_kill(message, session, error); } static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; uint32_t uid; User *user; int r; assert(message); assert(m); r = sd_bus_message_read(message, "u", &uid); if (r < 0) return r; r = manager_get_user_from_creds(m, message, uid, error, &user); if (r < 0) return r; return bus_user_method_kill(message, user, error); } static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; const char *name; Session *session; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = manager_get_session_from_creds(m, message, name, error, &session); if (r < 0) return r; return bus_session_method_terminate(message, session, error); } static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; uint32_t uid; User *user; int r; assert(message); assert(m); r = sd_bus_message_read(message, "u", &uid); if (r < 0) return r; r = manager_get_user_from_creds(m, message, uid, error, &user); if (r < 0) return r; return bus_user_method_terminate(message, user, error); } static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; const char *name; Seat *seat; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = manager_get_seat_from_creds(m, message, name, error, &seat); if (r < 0) return r; return bus_seat_method_terminate(message, seat, error); } static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *cc = NULL; Manager *m = userdata; int b, r; struct passwd *pw; const char *path; uint32_t uid; int interactive; assert(message); assert(m); r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive); if (r < 0) return r; if (uid == UID_INVALID) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; /* Note that we get the owner UID of the session, not the actual client UID here! */ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); if (r < 0) return r; r = sd_bus_creds_get_owner_uid(creds, &uid); if (r < 0) return r; } else if (!uid_is_valid(uid)) return -EINVAL; errno = 0; pw = getpwuid(uid); if (!pw) return errno > 0 ? -errno : -ENOENT; r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, "org.freedesktop.login1.set-user-linger", NULL, interactive, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ mkdir_p_label("/var/lib/systemd", 0755); r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0); if (r < 0) return r; cc = cescape(pw->pw_name); if (!cc) return -ENOMEM; path = strjoina("/var/lib/systemd/linger/", cc); if (b) { User *u; r = touch(path); if (r < 0) return r; if (manager_add_user_by_uid(m, uid, &u) >= 0) user_start(u); } else { User *u; r = unlink(path); if (r < 0 && errno != ENOENT) return -errno; u = hashmap_get(m->users, UID_TO_PTR(uid)); if (u) user_add_to_gc_queue(u); } return sd_bus_reply_method_return(message, NULL); } static int trigger_device(Manager *m, struct udev_device *d) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; struct udev_list_entry *first, *item; int r; assert(m); e = udev_enumerate_new(m->udev); if (!e) return -ENOMEM; if (d) { r = udev_enumerate_add_match_parent(e, d); if (r < 0) return r; } r = udev_enumerate_scan_devices(e); if (r < 0) return r; first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_free_ char *t = NULL; const char *p; p = udev_list_entry_get_name(item); t = strappend(p, "/uevent"); if (!t) return -ENOMEM; write_string_file(t, "change", WRITE_STRING_FILE_CREATE); } return 0; } static int attach_device(Manager *m, const char *seat, const char *sysfs) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; _cleanup_free_ char *rule = NULL, *file = NULL; const char *id_for_seat; int r; assert(m); assert(seat); assert(sysfs); d = udev_device_new_from_syspath(m->udev, sysfs); if (!d) return -ENODEV; if (!udev_device_has_tag(d, "seat")) return -ENODEV; id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT"); if (!id_for_seat) return -ENODEV; if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0) return -ENOMEM; if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0) return -ENOMEM; mkdir_p_label("/etc/udev/rules.d", 0755); r = write_string_file_atomic_label(file, rule); if (r < 0) return r; return trigger_device(m, d); } static int flush_devices(Manager *m) { _cleanup_closedir_ DIR *d; assert(m); d = opendir("/etc/udev/rules.d"); if (!d) { if (errno != ENOENT) log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m"); } else { struct dirent *de; while ((de = readdir(d))) { if (!dirent_is_file(de)) continue; if (!startswith(de->d_name, "72-seat-")) continue; if (!endswith(de->d_name, ".rules")) continue; if (unlinkat(dirfd(d), de->d_name, 0) < 0) log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name); } } return trigger_device(m, NULL); } static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *sysfs, *seat; Manager *m = userdata; int interactive, r; assert(message); assert(m); r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive); if (r < 0) return r; if (!path_startswith(sysfs, "/sys")) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs); if (!seat_name_is_valid(seat)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat); r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, "org.freedesktop.login1.attach-device", NULL, interactive, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = attach_device(m, seat, sysfs); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; int interactive, r; assert(message); assert(m); r = sd_bus_message_read(message, "b", &interactive); if (r < 0) return r; r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, "org.freedesktop.login1.flush-devices", NULL, interactive, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = flush_devices(m); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int have_multiple_sessions( Manager *m, uid_t uid) { Session *session; Iterator i; assert(m); /* Check for other users' sessions. Greeter sessions do not * count, and non-login sessions do not count either. */ HASHMAP_FOREACH(session, m->sessions, i) if (session->class == SESSION_USER && session->user->uid != uid) return true; return false; } static int bus_manager_log_shutdown( Manager *m, InhibitWhat w, const char *unit_name) { const char *p, *q; assert(m); assert(unit_name); if (w != INHIBIT_SHUTDOWN) return 0; if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) { p = "MESSAGE=System is powering down"; q = "SHUTDOWN=power-off"; } else if (streq(unit_name, SPECIAL_HALT_TARGET)) { p = "MESSAGE=System is halting"; q = "SHUTDOWN=halt"; } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) { p = "MESSAGE=System is rebooting"; q = "SHUTDOWN=reboot"; } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) { p = "MESSAGE=System is rebooting with kexec"; q = "SHUTDOWN=kexec"; } else { p = "MESSAGE=System is shutting down"; q = NULL; } if (isempty(m->wall_message)) p = strjoina(p, "."); else p = strjoina(p, " (", m->wall_message, ")."); return log_struct(LOG_NOTICE, LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN), p, q, NULL); } static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) { Manager *m = userdata; assert(e); assert(m); m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source); return 0; } int manager_set_lid_switch_ignore(Manager *m, usec_t until) { int r; assert(m); if (until <= now(CLOCK_MONOTONIC)) return 0; /* We want to ignore the lid switch for a while after each * suspend, and after boot-up. Hence let's install a timer for * this. As long as the event source exists we ignore the lid * switch. */ if (m->lid_switch_ignore_event_source) { usec_t u; r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u); if (r < 0) return r; if (until <= u) return 0; r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until); } else r = sd_event_add_time( m->event, &m->lid_switch_ignore_event_source, CLOCK_MONOTONIC, until, 0, lid_switch_ignore_handler, m); return r; } static void reset_scheduled_shutdown(Manager *m) { m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source); m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source); m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source); m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type); m->scheduled_shutdown_timeout = 0; m->shutdown_dry_run = false; if (m->unlink_nologin) { (void) unlink("/run/nologin"); m->unlink_nologin = false; } } static int execute_shutdown_or_sleep( Manager *m, InhibitWhat w, const char *unit_name, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; char *c = NULL; const char *p; int r; assert(m); assert(w >= 0); assert(w < _INHIBIT_WHAT_MAX); assert(unit_name); bus_manager_log_shutdown(m, w, unit_name); if (m->shutdown_dry_run) { log_info("Running in dry run, suppressing action."); reset_scheduled_shutdown(m); } else { r = sd_bus_call_method( m->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit", error, &reply, "ss", unit_name, "replace-irreversibly"); if (r < 0) return r; r = sd_bus_message_read(reply, "o", &p); if (r < 0) return r; c = strdup(p); if (!c) return -ENOMEM; } m->action_unit = unit_name; free(m->action_job); m->action_job = c; m->action_what = w; /* Make sure the lid switch is ignored for a while */ manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec); return 0; } int manager_dispatch_delayed(Manager *manager, bool timeout) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; Inhibitor *offending = NULL; int r; assert(manager); if (manager->action_what == 0 || manager->action_job) return 0; if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) { _cleanup_free_ char *comm = NULL, *u = NULL; if (!timeout) return 0; (void) get_process_comm(offending->pid, &comm); u = uid_to_name(offending->uid); log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.", offending->uid, strna(u), offending->pid, strna(comm)); } /* Actually do the operation */ r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error); if (r < 0) { log_warning("Failed to send delayed message: %s", bus_error_message(&error, r)); manager->action_unit = NULL; manager->action_what = 0; return r; } return 1; } static int manager_inhibit_timeout_handler( sd_event_source *s, uint64_t usec, void *userdata) { Manager *manager = userdata; int r; assert(manager); assert(manager->inhibit_timeout_source == s); r = manager_dispatch_delayed(manager, true); return (r < 0) ? r : 0; } static int delay_shutdown_or_sleep( Manager *m, InhibitWhat w, const char *unit_name) { int r; usec_t timeout_val; assert(m); assert(w >= 0); assert(w < _INHIBIT_WHAT_MAX); assert(unit_name); timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max; if (m->inhibit_timeout_source) { r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val); if (r < 0) return log_error_errno(r, "sd_event_source_set_time() failed: %m"); r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT); if (r < 0) return log_error_errno(r, "sd_event_source_set_enabled() failed: %m"); } else { r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC, timeout_val, 0, manager_inhibit_timeout_handler, m); if (r < 0) return r; } m->action_unit = unit_name; m->action_what = w; return 0; } static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { static const char * const signal_name[_INHIBIT_WHAT_MAX] = { [INHIBIT_SHUTDOWN] = "PrepareForShutdown", [INHIBIT_SLEEP] = "PrepareForSleep" }; int active = _active; assert(m); assert(w >= 0); assert(w < _INHIBIT_WHAT_MAX); assert(signal_name[w]); return sd_bus_emit_signal(m->bus, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", signal_name[w], "b", active); } int bus_manager_shutdown_or_sleep_now_or_later( Manager *m, const char *unit_name, InhibitWhat w, sd_bus_error *error) { bool delayed; int r; assert(m); assert(unit_name); assert(w >= 0); assert(w <= _INHIBIT_WHAT_MAX); assert(!m->action_job); /* Tell everybody to prepare for shutdown/sleep */ send_prepare_for(m, w, true); delayed = m->inhibit_delay_max > 0 && manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL); if (delayed) /* Shutdown is delayed, keep in mind what we * want to do, and start a timeout */ r = delay_shutdown_or_sleep(m, w, unit_name); else /* Shutdown is not delayed, execute it * immediately */ r = execute_shutdown_or_sleep(m, w, unit_name, error); return r; } static int verify_shutdown_creds( Manager *m, sd_bus_message *message, InhibitWhat w, bool interactive, const char *action, const char *action_multiple_sessions, const char *action_ignore_inhibit, sd_bus_error *error) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; bool multiple_sessions, blocked; uid_t uid; int r; assert(m); assert(message); assert(w >= 0); assert(w <= _INHIBIT_WHAT_MAX); r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); if (r < 0) return r; r = sd_bus_creds_get_euid(creds, &uid); if (r < 0) return r; r = have_multiple_sessions(m, uid); if (r < 0) return r; multiple_sessions = r > 0; blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL); if (multiple_sessions && action_multiple_sessions) { r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ } if (blocked && action_ignore_inhibit) { r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ } if (!multiple_sessions && !blocked && action) { r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ } return 0; } static int method_do_shutdown_or_sleep( Manager *m, sd_bus_message *message, const char *unit_name, InhibitWhat w, const char *action, const char *action_multiple_sessions, const char *action_ignore_inhibit, const char *sleep_verb, sd_bus_error *error) { int interactive, r; assert(m); assert(message); assert(unit_name); assert(w >= 0); assert(w <= _INHIBIT_WHAT_MAX); r = sd_bus_message_read(message, "b", &interactive); if (r < 0) return r; /* Don't allow multiple jobs being executed at the same time */ if (m->action_what) return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress"); if (sleep_verb) { r = can_sleep(sleep_verb); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported"); } r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions, action_ignore_inhibit, error); if (r != 0) return r; r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; return method_do_shutdown_or_sleep( m, message, SPECIAL_POWEROFF_TARGET, INHIBIT_SHUTDOWN, "org.freedesktop.login1.power-off", "org.freedesktop.login1.power-off-multiple-sessions", "org.freedesktop.login1.power-off-ignore-inhibit", NULL, error); } static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; return method_do_shutdown_or_sleep( m, message, SPECIAL_REBOOT_TARGET, INHIBIT_SHUTDOWN, "org.freedesktop.login1.reboot", "org.freedesktop.login1.reboot-multiple-sessions", "org.freedesktop.login1.reboot-ignore-inhibit", NULL, error); } static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; return method_do_shutdown_or_sleep( m, message, SPECIAL_SUSPEND_TARGET, INHIBIT_SLEEP, "org.freedesktop.login1.suspend", "org.freedesktop.login1.suspend-multiple-sessions", "org.freedesktop.login1.suspend-ignore-inhibit", "suspend", error); } static int nologin_timeout_handler( sd_event_source *s, uint64_t usec, void *userdata) { Manager *m = userdata; int r; log_info("Creating /run/nologin, blocking further logins..."); r = write_string_file_atomic_label("/run/nologin", "System is going down."); if (r < 0) log_error_errno(r, "Failed to create /run/nologin: %m"); else m->unlink_nologin = true; return 0; } static int update_schedule_file(Manager *m) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(m); r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0); if (r < 0) return log_error_errno(r, "Failed to create shutdown subdirectory: %m"); r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path); if (r < 0) return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m"); (void) fchmod(fileno(f), 0644); fprintf(f, "USEC="USEC_FMT"\n" "WARN_WALL=%i\n" "MODE=%s\n", m->scheduled_shutdown_timeout, m->enable_wall_messages, m->scheduled_shutdown_type); if (!isempty(m->wall_message)) { _cleanup_free_ char *t; t = cescape(m->wall_message); if (!t) { r = -ENOMEM; goto fail; } fprintf(f, "WALL_MESSAGE=%s\n", t); } r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) { r = -errno; goto fail; } return 0; fail: (void) unlink(temp_path); (void) unlink("/run/systemd/shutdown/scheduled"); return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m"); } static int manager_scheduled_shutdown_handler( sd_event_source *s, uint64_t usec, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; Manager *m = userdata; const char *target; int r; assert(m); if (isempty(m->scheduled_shutdown_type)) return 0; if (streq(m->scheduled_shutdown_type, "halt")) target = SPECIAL_HALT_TARGET; else if (streq(m->scheduled_shutdown_type, "poweroff")) target = SPECIAL_POWEROFF_TARGET; else target = SPECIAL_REBOOT_TARGET; r = execute_shutdown_or_sleep(m, 0, target, &error); if (r < 0) return log_error_errno(r, "Unable to execute transition to %s: %m", target); return 0; } static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *action_multiple_sessions = NULL; const char *action_ignore_inhibit = NULL; const char *action = NULL; uint64_t elapse; char *type; int r; assert(m); assert(message); r = sd_bus_message_read(message, "st", &type, &elapse); if (r < 0) return r; if (startswith(type, "dry-")) { type += 4; m->shutdown_dry_run = true; } if (streq(type, "reboot")) { action = "org.freedesktop.login1.reboot"; action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions"; action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit"; } else if (streq(type, "halt")) { action = "org.freedesktop.login1.halt"; action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions"; action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit"; } else if (streq(type, "poweroff")) { action = "org.freedesktop.login1.power-off"; action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions"; action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit"; } else return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type"); r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false, action, action_multiple_sessions, action_ignore_inhibit, error); if (r != 0) return r; if (m->scheduled_shutdown_timeout_source) { r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse); if (r < 0) return log_error_errno(r, "sd_event_source_set_time() failed: %m"); r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT); if (r < 0) return log_error_errno(r, "sd_event_source_set_enabled() failed: %m"); } else { r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source, CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m); if (r < 0) return log_error_errno(r, "sd_event_add_time() failed: %m"); } r = free_and_strdup(&m->scheduled_shutdown_type, type); if (r < 0) { m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source); return log_oom(); } if (m->nologin_timeout_source) { r = sd_event_source_set_time(m->nologin_timeout_source, elapse); if (r < 0) return log_error_errno(r, "sd_event_source_set_time() failed: %m"); r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT); if (r < 0) return log_error_errno(r, "sd_event_source_set_enabled() failed: %m"); } else { r = sd_event_add_time(m->event, &m->nologin_timeout_source, CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m); if (r < 0) return log_error_errno(r, "sd_event_add_time() failed: %m"); } m->scheduled_shutdown_timeout = elapse; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds); if (r >= 0) { const char *tty = NULL; (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid); (void) sd_bus_creds_get_tty(creds, &tty); r = free_and_strdup(&m->scheduled_shutdown_tty, tty); if (r < 0) { m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source); return log_oom(); } } r = manager_setup_wall_message_timer(m); if (r < 0) return r; if (!isempty(type)) { r = update_schedule_file(m); if (r < 0) return r; } else (void) unlink("/run/systemd/shutdown/scheduled"); return sd_bus_reply_method_return(message, NULL); } static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; bool cancelled; assert(m); assert(message); cancelled = m->scheduled_shutdown_type != NULL; reset_scheduled_shutdown(m); if (cancelled) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *tty = NULL; uid_t uid = 0; int r; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds); if (r >= 0) { (void) sd_bus_creds_get_uid(creds, &uid); (void) sd_bus_creds_get_tty(creds, &tty); } utmp_wall("The system shutdown has been cancelled", uid_to_name(uid), tty, logind_wall_tty_filter, m); } return sd_bus_reply_method_return(message, "b", cancelled); } static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; return method_do_shutdown_or_sleep( m, message, SPECIAL_HIBERNATE_TARGET, INHIBIT_SLEEP, "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", "hibernate", error); } static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; return method_do_shutdown_or_sleep( m, message, SPECIAL_HYBRID_SLEEP_TARGET, INHIBIT_SLEEP, "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", "hybrid-sleep", error); } static int method_can_shutdown_or_sleep( Manager *m, sd_bus_message *message, InhibitWhat w, const char *action, const char *action_multiple_sessions, const char *action_ignore_inhibit, const char *sleep_verb, sd_bus_error *error) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; bool multiple_sessions, challenge, blocked; const char *result = NULL; uid_t uid; int r; assert(m); assert(message); assert(w >= 0); assert(w <= _INHIBIT_WHAT_MAX); assert(action); assert(action_multiple_sessions); assert(action_ignore_inhibit); if (sleep_verb) { r = can_sleep(sleep_verb); if (r < 0) return r; if (r == 0) return sd_bus_reply_method_return(message, "s", "na"); } r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); if (r < 0) return r; r = sd_bus_creds_get_euid(creds, &uid); if (r < 0) return r; r = have_multiple_sessions(m, uid); if (r < 0) return r; multiple_sessions = r > 0; blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL); if (multiple_sessions) { r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error); if (r < 0) return r; if (r > 0) result = "yes"; else if (challenge) result = "challenge"; else result = "no"; } if (blocked) { r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error); if (r < 0) return r; if (r > 0 && !result) result = "yes"; else if (challenge && (!result || streq(result, "yes"))) result = "challenge"; else result = "no"; } if (!multiple_sessions && !blocked) { /* If neither inhibit nor multiple sessions * apply then just check the normal policy */ r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error); if (r < 0) return r; if (r > 0) result = "yes"; else if (challenge) result = "challenge"; else result = "no"; } return sd_bus_reply_method_return(message, "s", result); } static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; return method_can_shutdown_or_sleep( m, message, INHIBIT_SHUTDOWN, "org.freedesktop.login1.power-off", "org.freedesktop.login1.power-off-multiple-sessions", "org.freedesktop.login1.power-off-ignore-inhibit", NULL, error); } static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; return method_can_shutdown_or_sleep( m, message, INHIBIT_SHUTDOWN, "org.freedesktop.login1.reboot", "org.freedesktop.login1.reboot-multiple-sessions", "org.freedesktop.login1.reboot-ignore-inhibit", NULL, error); } static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; return method_can_shutdown_or_sleep( m, message, INHIBIT_SLEEP, "org.freedesktop.login1.suspend", "org.freedesktop.login1.suspend-multiple-sessions", "org.freedesktop.login1.suspend-ignore-inhibit", "suspend", error); } static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; return method_can_shutdown_or_sleep( m, message, INHIBIT_SLEEP, "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", "hibernate", error); } static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; return method_can_shutdown_or_sleep( m, message, INHIBIT_SLEEP, "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", "hybrid-sleep", error); } static int property_get_reboot_to_firmware_setup( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { int r; assert(bus); assert(reply); assert(userdata); r = efi_get_reboot_to_firmware(); if (r < 0 && r != -EOPNOTSUPP) return r; return sd_bus_message_append(reply, "b", r > 0); } static int method_set_reboot_to_firmware_setup( sd_bus_message *message, void *userdata, sd_bus_error *error) { int b, r; Manager *m = userdata; assert(message); assert(m); r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; r = bus_verify_polkit_async(message, CAP_SYS_ADMIN, "org.freedesktop.login1.set-reboot-to-firmware-setup", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = efi_set_reboot_to_firmware(b); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_can_reboot_to_firmware_setup( sd_bus_message *message, void *userdata, sd_bus_error *error) { int r; bool challenge; const char *result; Manager *m = userdata; assert(message); assert(m); r = efi_reboot_to_firmware_supported(); if (r == -EOPNOTSUPP) return sd_bus_reply_method_return(message, "s", "na"); else if (r < 0) return r; r = bus_test_polkit(message, CAP_SYS_ADMIN, "org.freedesktop.login1.set-reboot-to-firmware-setup", NULL, UID_INVALID, &challenge, error); if (r < 0) return r; if (r > 0) result = "yes"; else if (challenge) result = "challenge"; else result = "no"; return sd_bus_reply_method_return(message, "s", result); } static int method_set_wall_message( sd_bus_message *message, void *userdata, sd_bus_error *error) { int r; Manager *m = userdata; char *wall_message; int enable_wall_messages; assert(message); assert(m); r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages); if (r < 0) return r; r = bus_verify_polkit_async(message, CAP_SYS_ADMIN, "org.freedesktop.login1.set-wall-message", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ if (isempty(wall_message)) m->wall_message = mfree(m->wall_message); else { r = free_and_strdup(&m->wall_message, wall_message); if (r < 0) return log_oom(); } m->enable_wall_messages = enable_wall_messages; return sd_bus_reply_method_return(message, NULL); } static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *who, *why, *what, *mode; _cleanup_free_ char *id = NULL; _cleanup_close_ int fifo_fd = -1; Manager *m = userdata; Inhibitor *i = NULL; InhibitMode mm; InhibitWhat w; pid_t pid; uid_t uid; int r; assert(message); assert(m); r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode); if (r < 0) return r; w = inhibit_what_from_string(what); if (w <= 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what); mm = inhibit_mode_from_string(mode); if (mm < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode); /* Delay is only supported for shutdown/sleep */ if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP))) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep"); /* Don't allow taking delay locks while we are already * executing the operation. We shouldn't create the impression * that the lock was successful if the machine is about to go * down/suspend any moment. */ if (m->action_what & w) return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running"); r = bus_verify_polkit_async( message, CAP_SYS_BOOT, w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") : w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") : w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" : w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" : w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" : w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" : "org.freedesktop.login1.inhibit-handle-lid-switch", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds); if (r < 0) return r; r = sd_bus_creds_get_euid(creds, &uid); if (r < 0) return r; r = sd_bus_creds_get_pid(creds, &pid); if (r < 0) return r; do { id = mfree(id); if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0) return -ENOMEM; } while (hashmap_get(m->inhibitors, id)); r = manager_add_inhibitor(m, id, &i); if (r < 0) return r; i->what = w; i->mode = mm; i->pid = pid; i->uid = uid; i->why = strdup(why); i->who = strdup(who); if (!i->why || !i->who) { r = -ENOMEM; goto fail; } fifo_fd = inhibitor_create_fifo(i); if (fifo_fd < 0) { r = fifo_fd; goto fail; } inhibitor_start(i); return sd_bus_reply_method_return(message, "h", fifo_fd); fail: if (i) inhibitor_free(i); return r; } const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0), SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0), SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0), SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0), SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0), SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0), SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0), SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0), SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("SessionNew", "so", 0), SD_BUS_SIGNAL("SessionRemoved", "so", 0), SD_BUS_SIGNAL("UserNew", "uo", 0), SD_BUS_SIGNAL("UserRemoved", "uo", 0), SD_BUS_SIGNAL("SeatNew", "so", 0), SD_BUS_SIGNAL("SeatRemoved", "so", 0), SD_BUS_SIGNAL("PrepareForShutdown", "b", 0), SD_BUS_SIGNAL("PrepareForSleep", "b", 0), SD_BUS_VTABLE_END }; static int session_jobs_reply(Session *s, const char *unit, const char *result) { int r = 0; assert(s); assert(unit); if (!s->started) return r; if (streq(result, "done")) r = session_send_create_reply(s, NULL); else { _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL; sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result); r = session_send_create_reply(s, &e); } return r; } int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *path, *result, *unit; Manager *m = userdata; Session *session; uint32_t id; User *user; int r; assert(message); assert(m); r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result); if (r < 0) { bus_log_parse_error(r); return 0; } if (m->action_job && streq(m->action_job, path)) { log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what)); /* Tell people that they now may take a lock again */ send_prepare_for(m, m->action_what, false); m->action_job = mfree(m->action_job); m->action_unit = NULL; m->action_what = 0; return 0; } session = hashmap_get(m->session_units, unit); if (session && streq_ptr(path, session->scope_job)) { session->scope_job = mfree(session->scope_job); session_jobs_reply(session, unit, result); session_save(session); user_save(session->user); session_add_to_gc_queue(session); } user = hashmap_get(m->user_units, unit); if (user && (streq_ptr(path, user->service_job) || streq_ptr(path, user->slice_job))) { if (streq_ptr(path, user->service_job)) user->service_job = mfree(user->service_job); if (streq_ptr(path, user->slice_job)) user->slice_job = mfree(user->slice_job); LIST_FOREACH(sessions_by_user, session, user->sessions) session_jobs_reply(session, unit, result); user_save(user); user_add_to_gc_queue(user); } return 0; } int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *path, *unit; Manager *m = userdata; Session *session; User *user; int r; assert(message); assert(m); r = sd_bus_message_read(message, "so", &unit, &path); if (r < 0) { bus_log_parse_error(r); return 0; } session = hashmap_get(m->session_units, unit); if (session) session_add_to_gc_queue(session); user = hashmap_get(m->user_units, unit); if (user) user_add_to_gc_queue(user); return 0; } int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *unit = NULL; Manager *m = userdata; const char *path; Session *session; User *user; int r; assert(message); assert(m); path = sd_bus_message_get_path(message); if (!path) return 0; r = unit_name_from_dbus_path(path, &unit); if (r == -EINVAL) /* not a unit */ return 0; if (r < 0) { log_oom(); return 0; } session = hashmap_get(m->session_units, unit); if (session) session_add_to_gc_queue(session); user = hashmap_get(m->user_units, unit); if (user) user_add_to_gc_queue(user); return 0; } int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Session *session; Iterator i; int b, r; assert(message); assert(m); r = sd_bus_message_read(message, "b", &b); if (r < 0) { bus_log_parse_error(r); return 0; } if (b) return 0; /* systemd finished reloading, let's recheck all our sessions */ log_debug("System manager has been reloaded, rechecking sessions..."); HASHMAP_FOREACH(session, m->sessions, i) session_add_to_gc_queue(session); return 0; } int manager_send_changed(Manager *manager, const char *property, ...) { char **l; assert(manager); l = strv_from_stdarg_alloca(property); return sd_bus_emit_properties_changed_strv( manager->bus, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", l); } static int strdup_job(sd_bus_message *reply, char **job) { const char *j; char *copy; int r; r = sd_bus_message_read(reply, "o", &j); if (r < 0) return r; copy = strdup(j); if (!copy) return -ENOMEM; *job = copy; return 1; } int manager_start_slice( Manager *manager, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; int r; assert(manager); assert(slice); assert(job); r = sd_bus_message_new_method_call( manager->bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartTransientUnit"); if (r < 0) return r; r = sd_bus_message_append(m, "ss", strempty(slice), "fail"); if (r < 0) return r; r = sd_bus_message_open_container(m, 'a', "(sv)"); if (r < 0) return r; if (!isempty(description)) { r = sd_bus_message_append(m, "(sv)", "Description", "s", description); if (r < 0) return r; } if (!isempty(after)) { r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after); if (r < 0) return r; } if (!isempty(after2)) { r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2); if (r < 0) return r; } r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_append(m, "a(sa(sv))", 0); if (r < 0) return r; r = sd_bus_call(manager->bus, m, 0, error, &reply); if (r < 0) return r; return strdup_job(reply, job); } int manager_start_scope( Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; int r; assert(manager); assert(scope); assert(pid > 1); assert(job); r = sd_bus_message_new_method_call( manager->bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartTransientUnit"); if (r < 0) return r; r = sd_bus_message_append(m, "ss", strempty(scope), "fail"); if (r < 0) return r; r = sd_bus_message_open_container(m, 'a', "(sv)"); if (r < 0) return r; if (!isempty(slice)) { r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice); if (r < 0) return r; } if (!isempty(description)) { r = sd_bus_message_append(m, "(sv)", "Description", "s", description); if (r < 0) return r; } if (!isempty(after)) { r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after); if (r < 0) return r; } if (!isempty(after2)) { r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2); if (r < 0) return r; } /* cgroup empty notification is not available in containers * currently. To make this less problematic, let's shorten the * stop timeout for sessions, so that we don't wait * forever. */ /* Make sure that the session shells are terminated with * SIGHUP since bash and friends tend to ignore SIGTERM */ r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true); if (r < 0) return r; r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid); if (r < 0) return r; r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_append(m, "a(sa(sv))", 0); if (r < 0) return r; r = sd_bus_call(manager->bus, m, 0, error, &reply); if (r < 0) return r; return strdup_job(reply, job); } int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(manager); assert(unit); assert(job); r = sd_bus_call_method( manager->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit", error, &reply, "ss", unit, "replace"); if (r < 0) return r; return strdup_job(reply, job); } int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(manager); assert(unit); assert(job); r = sd_bus_call_method( manager->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StopUnit", error, &reply, "ss", unit, "fail"); if (r < 0) { if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) || sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) { *job = NULL; sd_bus_error_free(error); return 0; } return r; } return strdup_job(reply, job); } int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) { _cleanup_free_ char *path = NULL; int r; assert(manager); assert(scope); path = unit_dbus_path_from_name(scope); if (!path) return -ENOMEM; r = sd_bus_call_method( manager->bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Scope", "Abandon", error, NULL, NULL); if (r < 0) { if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) || sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) || sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) { sd_bus_error_free(error); return 0; } return r; } return 1; } int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) { assert(manager); assert(unit); return sd_bus_call_method( manager->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "KillUnit", error, NULL, "ssi", unit, who == KILL_LEADER ? "main" : "all", signo); } int manager_unit_is_active(Manager *manager, const char *unit) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *path = NULL; const char *state; int r; assert(manager); assert(unit); path = unit_dbus_path_from_name(unit); if (!path) return -ENOMEM; r = sd_bus_get_property( manager->bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Unit", "ActiveState", &error, &reply, "s"); if (r < 0) { /* systemd might have droppped off momentarily, let's * not make this an error */ if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) return true; /* If the unit is already unloaded then it's not * active */ if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) || sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) return false; return r; } r = sd_bus_message_read(reply, "s", &state); if (r < 0) return -EINVAL; return !streq(state, "inactive") && !streq(state, "failed"); } int manager_job_is_active(Manager *manager, const char *path) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(manager); assert(path); r = sd_bus_get_property( manager->bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Job", "State", &error, &reply, "s"); if (r < 0) { if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) return true; if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT)) return false; return r; } /* We don't actually care about the state really. The fact * that we could read the job state is enough for us */ return true; } systemd-229/src/login/logind-device.c000066400000000000000000000063651265713322000176470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "logind-device.h" #include "util.h" Device* device_new(Manager *m, const char *sysfs, bool master) { Device *d; assert(m); assert(sysfs); d = new0(Device, 1); if (!d) return NULL; d->sysfs = strdup(sysfs); if (!d->sysfs) { free(d); return NULL; } if (hashmap_put(m->devices, d->sysfs, d) < 0) { free(d->sysfs); free(d); return NULL; } d->manager = m; d->master = master; dual_timestamp_get(&d->timestamp); return d; } static void device_detach(Device *d) { Seat *s; SessionDevice *sd; assert(d); if (!d->seat) return; while ((sd = d->session_devices)) session_device_free(sd); s = d->seat; LIST_REMOVE(devices, d->seat->devices, d); d->seat = NULL; if (!seat_has_master_device(s)) { seat_add_to_gc_queue(s); seat_send_changed(s, "CanGraphical", NULL); } } void device_free(Device *d) { assert(d); device_detach(d); hashmap_remove(d->manager->devices, d->sysfs); free(d->sysfs); free(d); } void device_attach(Device *d, Seat *s) { Device *i; bool had_master; assert(d); assert(s); if (d->seat == s) return; if (d->seat) device_detach(d); d->seat = s; had_master = seat_has_master_device(s); /* We keep the device list sorted by the "master" flag. That is, master * devices are at the front, other devices at the tail. As there is no * way to easily add devices at the list-tail, we need to iterate the * list to find the first non-master device when adding non-master * devices. We assume there is only a few (normally 1) master devices * per seat, so we iterate only a few times. */ if (d->master || !s->devices) LIST_PREPEND(devices, s->devices, d); else { LIST_FOREACH(devices, i, s->devices) { if (!i->devices_next || !i->master) { LIST_INSERT_AFTER(devices, s->devices, i, d); break; } } } if (!had_master && d->master) seat_send_changed(s, "CanGraphical", NULL); } systemd-229/src/login/logind-device.h000066400000000000000000000023011265713322000176360ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Device Device; #include "list.h" #include "logind-seat.h" #include "logind-session-device.h" struct Device { Manager *manager; char *sysfs; Seat *seat; bool master; dual_timestamp timestamp; LIST_FIELDS(struct Device, devices); LIST_HEAD(SessionDevice, session_devices); }; Device* device_new(Manager *m, const char *sysfs, bool master); void device_free(Device *d); void device_attach(Device *d, Seat *s); systemd-229/src/login/logind-gperf.gperf000066400000000000000000000047101265713322000203640ustar00rootroot00000000000000%{ #include #include "conf-parser.h" #include "logind.h" %} struct ConfigPerfItem; %null_strings %language=ANSI-C %define slot-name section_and_lvalue %define hash-function-name logind_gperf_hash %define lookup-function-name logind_gperf_lookup %readonly-tables %omit-struct-type %struct-type %includes %% Login.NAutoVTs, config_parse_unsigned, 0, offsetof(Manager, n_autovts) Login.ReserveVT, config_parse_unsigned, 0, offsetof(Manager, reserve_vt) Login.KillUserProcesses, config_parse_bool, 0, offsetof(Manager, kill_user_processes) Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manager, kill_only_users) Login.KillExcludeUsers, config_parse_strv, 0, offsetof(Manager, kill_exclude_users) Login.InhibitDelayMaxSec, config_parse_sec, 0, offsetof(Manager, inhibit_delay_max) Login.HandlePowerKey, config_parse_handle_action, 0, offsetof(Manager, handle_power_key) Login.HandleSuspendKey, config_parse_handle_action, 0, offsetof(Manager, handle_suspend_key) Login.HandleHibernateKey, config_parse_handle_action, 0, offsetof(Manager, handle_hibernate_key) Login.HandleLidSwitch, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch) Login.HandleLidSwitchDocked, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_docked) Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, power_key_ignore_inhibited) Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, suspend_key_ignore_inhibited) Login.HibernateKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, hibernate_key_ignore_inhibited) Login.LidSwitchIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, lid_switch_ignore_inhibited) Login.HoldoffTimeoutSec, config_parse_sec, 0, offsetof(Manager, holdoff_timeout_usec) Login.IdleAction, config_parse_handle_action, 0, offsetof(Manager, idle_action) Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec) Login.RuntimeDirectorySize, config_parse_tmpfs_size, 0, offsetof(Manager, runtime_dir_size) Login.RemoveIPC, config_parse_bool, 0, offsetof(Manager, remove_ipc) Login.UserTasksMax, config_parse_uint64, 0, offsetof(Manager, user_tasks_max) systemd-229/src/login/logind-inhibit.c000066400000000000000000000310271265713322000200270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "logind-inhibit.h" #include "mkdir.h" #include "parse-util.h" #include "string-table.h" #include "string-util.h" #include "user-util.h" #include "util.h" Inhibitor* inhibitor_new(Manager *m, const char* id) { Inhibitor *i; assert(m); i = new0(Inhibitor, 1); if (!i) return NULL; i->state_file = strappend("/run/systemd/inhibit/", id); if (!i->state_file) { free(i); return NULL; } i->id = basename(i->state_file); if (hashmap_put(m->inhibitors, i->id, i) < 0) { free(i->state_file); free(i); return NULL; } i->manager = m; i->fifo_fd = -1; return i; } void inhibitor_free(Inhibitor *i) { assert(i); hashmap_remove(i->manager->inhibitors, i->id); inhibitor_remove_fifo(i); free(i->who); free(i->why); if (i->state_file) { unlink(i->state_file); free(i->state_file); } free(i); } int inhibitor_save(Inhibitor *i) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(i); r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0); if (r < 0) goto fail; r = fopen_temporary(i->state_file, &f, &temp_path); if (r < 0) goto fail; fchmod(fileno(f), 0644); fprintf(f, "# This is private data. Do not parse.\n" "WHAT=%s\n" "MODE=%s\n" "UID="UID_FMT"\n" "PID="PID_FMT"\n", inhibit_what_to_string(i->what), inhibit_mode_to_string(i->mode), i->uid, i->pid); if (i->who) { _cleanup_free_ char *cc = NULL; cc = cescape(i->who); if (!cc) { r = -ENOMEM; goto fail; } fprintf(f, "WHO=%s\n", cc); } if (i->why) { _cleanup_free_ char *cc = NULL; cc = cescape(i->why); if (!cc) { r = -ENOMEM; goto fail; } fprintf(f, "WHY=%s\n", cc); } if (i->fifo_path) fprintf(f, "FIFO=%s\n", i->fifo_path); r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, i->state_file) < 0) { r = -errno; goto fail; } return 0; fail: (void) unlink(i->state_file); if (temp_path) (void) unlink(temp_path); return log_error_errno(r, "Failed to save inhibit data %s: %m", i->state_file); } int inhibitor_start(Inhibitor *i) { assert(i); if (i->started) return 0; dual_timestamp_get(&i->since); log_debug("Inhibitor %s (%s) pid="PID_FMT" uid="UID_FMT" mode=%s started.", strna(i->who), strna(i->why), i->pid, i->uid, inhibit_mode_to_string(i->mode)); inhibitor_save(i); i->started = true; manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited" : "DelayInhibited", NULL); return 0; } int inhibitor_stop(Inhibitor *i) { assert(i); if (i->started) log_debug("Inhibitor %s (%s) pid="PID_FMT" uid="UID_FMT" mode=%s stopped.", strna(i->who), strna(i->why), i->pid, i->uid, inhibit_mode_to_string(i->mode)); if (i->state_file) unlink(i->state_file); i->started = false; manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited" : "DelayInhibited", NULL); return 0; } int inhibitor_load(Inhibitor *i) { _cleanup_free_ char *what = NULL, *uid = NULL, *pid = NULL, *who = NULL, *why = NULL, *mode = NULL; InhibitWhat w; InhibitMode mm; char *cc; int r; r = parse_env_file(i->state_file, NEWLINE, "WHAT", &what, "UID", &uid, "PID", &pid, "WHO", &who, "WHY", &why, "MODE", &mode, "FIFO", &i->fifo_path, NULL); if (r < 0) return r; w = what ? inhibit_what_from_string(what) : 0; if (w >= 0) i->what = w; mm = mode ? inhibit_mode_from_string(mode) : INHIBIT_BLOCK; if (mm >= 0) i->mode = mm; if (uid) { r = parse_uid(uid, &i->uid); if (r < 0) return r; } if (pid) { r = parse_pid(pid, &i->pid); if (r < 0) return r; } if (who) { r = cunescape(who, 0, &cc); if (r < 0) return r; free(i->who); i->who = cc; } if (why) { r = cunescape(why, 0, &cc); if (r < 0) return r; free(i->why); i->why = cc; } if (i->fifo_path) { int fd; fd = inhibitor_create_fifo(i); safe_close(fd); } return 0; } static int inhibitor_dispatch_fifo(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Inhibitor *i = userdata; assert(s); assert(fd == i->fifo_fd); assert(i); inhibitor_stop(i); inhibitor_free(i); return 0; } int inhibitor_create_fifo(Inhibitor *i) { int r; assert(i); /* Create FIFO */ if (!i->fifo_path) { r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0); if (r < 0) return r; i->fifo_path = strjoin("/run/systemd/inhibit/", i->id, ".ref", NULL); if (!i->fifo_path) return -ENOMEM; if (mkfifo(i->fifo_path, 0600) < 0 && errno != EEXIST) return -errno; } /* Open reading side */ if (i->fifo_fd < 0) { i->fifo_fd = open(i->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY); if (i->fifo_fd < 0) return -errno; } if (!i->event_source) { r = sd_event_add_io(i->manager->event, &i->event_source, i->fifo_fd, 0, inhibitor_dispatch_fifo, i); if (r < 0) return r; r = sd_event_source_set_priority(i->event_source, SD_EVENT_PRIORITY_IDLE); if (r < 0) return r; } /* Open writing side */ r = open(i->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY); if (r < 0) return -errno; return r; } void inhibitor_remove_fifo(Inhibitor *i) { assert(i); i->event_source = sd_event_source_unref(i->event_source); i->fifo_fd = safe_close(i->fifo_fd); if (i->fifo_path) { unlink(i->fifo_path); i->fifo_path = mfree(i->fifo_path); } } InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm) { Inhibitor *i; Iterator j; InhibitWhat what = 0; assert(m); HASHMAP_FOREACH(i, m->inhibitors, j) if (i->mode == mm) what |= i->what; return what; } static int pid_is_active(Manager *m, pid_t pid) { Session *s; int r; r = manager_get_session_by_pid(m, pid, &s); if (r < 0) return r; /* If there's no session assigned to it, then it's globally * active on all ttys */ if (r == 0) return 1; return session_is_active(s); } bool manager_is_inhibited( Manager *m, InhibitWhat w, InhibitMode mm, dual_timestamp *since, bool ignore_inactive, bool ignore_uid, uid_t uid, Inhibitor **offending) { Inhibitor *i; Iterator j; struct dual_timestamp ts = DUAL_TIMESTAMP_NULL; bool inhibited = false; assert(m); assert(w > 0 && w < _INHIBIT_WHAT_MAX); HASHMAP_FOREACH(i, m->inhibitors, j) { if (!(i->what & w)) continue; if (i->mode != mm) continue; if (ignore_inactive && pid_is_active(m, i->pid) <= 0) continue; if (ignore_uid && i->uid == uid) continue; if (!inhibited || i->since.monotonic < ts.monotonic) ts = i->since; inhibited = true; if (offending) *offending = i; } if (since) *since = ts; return inhibited; } const char *inhibit_what_to_string(InhibitWhat w) { static thread_local char buffer[97]; char *p; if (w < 0 || w >= _INHIBIT_WHAT_MAX) return NULL; p = buffer; if (w & INHIBIT_SHUTDOWN) p = stpcpy(p, "shutdown:"); if (w & INHIBIT_SLEEP) p = stpcpy(p, "sleep:"); if (w & INHIBIT_IDLE) p = stpcpy(p, "idle:"); if (w & INHIBIT_HANDLE_POWER_KEY) p = stpcpy(p, "handle-power-key:"); if (w & INHIBIT_HANDLE_SUSPEND_KEY) p = stpcpy(p, "handle-suspend-key:"); if (w & INHIBIT_HANDLE_HIBERNATE_KEY) p = stpcpy(p, "handle-hibernate-key:"); if (w & INHIBIT_HANDLE_LID_SWITCH) p = stpcpy(p, "handle-lid-switch:"); if (p > buffer) *(p-1) = 0; else *p = 0; return buffer; } InhibitWhat inhibit_what_from_string(const char *s) { InhibitWhat what = 0; const char *word, *state; size_t l; FOREACH_WORD_SEPARATOR(word, l, s, ":", state) { if (l == 8 && strneq(word, "shutdown", l)) what |= INHIBIT_SHUTDOWN; else if (l == 5 && strneq(word, "sleep", l)) what |= INHIBIT_SLEEP; else if (l == 4 && strneq(word, "idle", l)) what |= INHIBIT_IDLE; else if (l == 16 && strneq(word, "handle-power-key", l)) what |= INHIBIT_HANDLE_POWER_KEY; else if (l == 18 && strneq(word, "handle-suspend-key", l)) what |= INHIBIT_HANDLE_SUSPEND_KEY; else if (l == 20 && strneq(word, "handle-hibernate-key", l)) what |= INHIBIT_HANDLE_HIBERNATE_KEY; else if (l == 17 && strneq(word, "handle-lid-switch", l)) what |= INHIBIT_HANDLE_LID_SWITCH; else return _INHIBIT_WHAT_INVALID; } return what; } static const char* const inhibit_mode_table[_INHIBIT_MODE_MAX] = { [INHIBIT_BLOCK] = "block", [INHIBIT_DELAY] = "delay" }; DEFINE_STRING_TABLE_LOOKUP(inhibit_mode, InhibitMode); systemd-229/src/login/logind-inhibit.h000066400000000000000000000045571265713322000200440ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Inhibitor Inhibitor; typedef enum InhibitWhat { INHIBIT_SHUTDOWN = 1, INHIBIT_SLEEP = 2, INHIBIT_IDLE = 4, INHIBIT_HANDLE_POWER_KEY = 8, INHIBIT_HANDLE_SUSPEND_KEY = 16, INHIBIT_HANDLE_HIBERNATE_KEY = 32, INHIBIT_HANDLE_LID_SWITCH = 64, _INHIBIT_WHAT_MAX = 128, _INHIBIT_WHAT_INVALID = -1 } InhibitWhat; typedef enum InhibitMode { INHIBIT_BLOCK, INHIBIT_DELAY, _INHIBIT_MODE_MAX, _INHIBIT_MODE_INVALID = -1 } InhibitMode; #include "logind.h" struct Inhibitor { Manager *manager; sd_event_source *event_source; char *id; char *state_file; bool started; InhibitWhat what; char *who; char *why; InhibitMode mode; pid_t pid; uid_t uid; dual_timestamp since; char *fifo_path; int fifo_fd; }; Inhibitor* inhibitor_new(Manager *m, const char *id); void inhibitor_free(Inhibitor *i); int inhibitor_save(Inhibitor *i); int inhibitor_load(Inhibitor *i); int inhibitor_start(Inhibitor *i); int inhibitor_stop(Inhibitor *i); int inhibitor_create_fifo(Inhibitor *i); void inhibitor_remove_fifo(Inhibitor *i); InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm); bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timestamp *since, bool ignore_inactive, bool ignore_uid, uid_t uid, Inhibitor **offending); const char *inhibit_what_to_string(InhibitWhat k); InhibitWhat inhibit_what_from_string(const char *s); const char *inhibit_mode_to_string(InhibitMode k); InhibitMode inhibit_mode_from_string(const char *s); systemd-229/src/login/logind-seat-dbus.c000066400000000000000000000330361265713322000202720ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-label.h" #include "bus-util.h" #include "logind-seat.h" #include "logind.h" #include "strv.h" #include "user-util.h" #include "util.h" static int property_get_active_session( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Seat *s = userdata; assert(bus); assert(reply); assert(s); p = s->active ? session_bus_path(s->active) : strdup("/"); if (!p) return -ENOMEM; return sd_bus_message_append(reply, "(so)", s->active ? s->active->id : "", p); } static int property_get_can_multi_session( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Seat *s = userdata; assert(bus); assert(reply); assert(s); return sd_bus_message_append(reply, "b", seat_can_multi_session(s)); } static int property_get_can_tty( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Seat *s = userdata; assert(bus); assert(reply); assert(s); return sd_bus_message_append(reply, "b", seat_can_tty(s)); } static int property_get_can_graphical( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Seat *s = userdata; assert(bus); assert(reply); assert(s); return sd_bus_message_append(reply, "b", seat_can_graphical(s)); } static int property_get_sessions( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Seat *s = userdata; Session *session; int r; assert(bus); assert(reply); assert(s); r = sd_bus_message_open_container(reply, 'a', "(so)"); if (r < 0) return r; LIST_FOREACH(sessions_by_seat, session, s->sessions) { _cleanup_free_ char *p = NULL; p = session_bus_path(session); if (!p) return -ENOMEM; r = sd_bus_message_append(reply, "(so)", session->id, p); if (r < 0) return r; } r = sd_bus_message_close_container(reply); if (r < 0) return r; return 1; } static int property_get_idle_hint( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Seat *s = userdata; assert(bus); assert(reply); assert(s); return sd_bus_message_append(reply, "b", seat_get_idle_hint(s, NULL) > 0); } static int property_get_idle_since_hint( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Seat *s = userdata; dual_timestamp t; uint64_t u; int r; assert(bus); assert(reply); assert(s); r = seat_get_idle_hint(s, &t); if (r < 0) return r; u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic; return sd_bus_message_append(reply, "t", u); } int bus_seat_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) { Seat *s = userdata; int r; assert(message); assert(s); r = bus_verify_polkit_async( message, CAP_KILL, "org.freedesktop.login1.manage", NULL, false, UID_INVALID, &s->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = seat_stop_sessions(s, true); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { Seat *s = userdata; const char *name; Session *session; int r; assert(message); assert(s); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; session = hashmap_get(s->manager->sessions, name); if (!session) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name); if (session->seat != s) return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id); r = session_activate(session); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_switch_to(sd_bus_message *message, void *userdata, sd_bus_error *error) { Seat *s = userdata; unsigned int to; int r; assert(message); assert(s); r = sd_bus_message_read(message, "u", &to); if (r < 0) return r; if (to <= 0) return -EINVAL; r = seat_switch_to(s, to); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_switch_to_next(sd_bus_message *message, void *userdata, sd_bus_error *error) { Seat *s = userdata; int r; assert(message); assert(s); r = seat_switch_to_next(s); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_switch_to_previous(sd_bus_message *message, void *userdata, sd_bus_error *error) { Seat *s = userdata; int r; assert(message); assert(s); r = seat_switch_to_previous(s); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } const sd_bus_vtable seat_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Seat, id), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ActiveSession", "(so)", property_get_active_session, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("CanMultiSession", "b", property_get_can_multi_session, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CanTTY", "b", property_get_can_tty, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CanGraphical", "b", property_get_can_graphical, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_METHOD("Terminate", NULL, NULL, bus_seat_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SwitchTo", "u", NULL, method_switch_to, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SwitchToNext", NULL, NULL, method_switch_to_next, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SwitchToPrevious", NULL, NULL, method_switch_to_previous, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; Seat *seat; int r; assert(bus); assert(path); assert(interface); assert(found); assert(m); if (streq(path, "/org/freedesktop/login1/seat/self")) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; sd_bus_message *message; Session *session; const char *name; message = sd_bus_get_current_message(bus); if (!message) return 0; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds); if (r < 0) return r; r = sd_bus_creds_get_session(creds, &name); if (r < 0) return r; session = hashmap_get(m->sessions, name); if (!session) return 0; seat = session->seat; } else { _cleanup_free_ char *e = NULL; const char *p; p = startswith(path, "/org/freedesktop/login1/seat/"); if (!p) return 0; e = bus_label_unescape(p); if (!e) return -ENOMEM; seat = hashmap_get(m->seats, e); } if (!seat) return 0; *found = seat; return 1; } char *seat_bus_path(Seat *s) { _cleanup_free_ char *t = NULL; assert(s); t = bus_label_escape(s->id); if (!t) return NULL; return strappend("/org/freedesktop/login1/seat/", t); } int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; sd_bus_message *message; Manager *m = userdata; Seat *seat; Iterator i; int r; assert(bus); assert(path); assert(nodes); HASHMAP_FOREACH(seat, m->seats, i) { char *p; p = seat_bus_path(seat); if (!p) return -ENOMEM; r = strv_consume(&l, p); if (r < 0) return r; } message = sd_bus_get_current_message(bus); if (message) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *name; Session *session; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds); if (r >= 0) { r = sd_bus_creds_get_session(creds, &name); if (r >= 0) { session = hashmap_get(m->sessions, name); if (session && session->seat) { r = strv_extend(&l, "/org/freedesktop/login1/seat/self"); if (r < 0) return r; } } } } *nodes = l; l = NULL; return 1; } int seat_send_signal(Seat *s, bool new_seat) { _cleanup_free_ char *p = NULL; assert(s); p = seat_bus_path(s); if (!p) return -ENOMEM; return sd_bus_emit_signal( s->manager->bus, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", new_seat ? "SeatNew" : "SeatRemoved", "so", s->id, p); } int seat_send_changed(Seat *s, const char *properties, ...) { _cleanup_free_ char *p = NULL; char **l; assert(s); if (!s->started) return 0; p = seat_bus_path(s); if (!p) return -ENOMEM; l = strv_from_stdarg_alloca(properties); return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Seat", l); } systemd-229/src/login/logind-seat.c000066400000000000000000000423571265713322000173450ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-messages.h" #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "logind-acl.h" #include "logind-seat.h" #include "mkdir.h" #include "parse-util.h" #include "stdio-util.h" #include "string-util.h" #include "terminal-util.h" #include "util.h" Seat *seat_new(Manager *m, const char *id) { Seat *s; assert(m); assert(id); s = new0(Seat, 1); if (!s) return NULL; s->state_file = strappend("/run/systemd/seats/", id); if (!s->state_file) { free(s); return NULL; } s->id = basename(s->state_file); s->manager = m; if (hashmap_put(m->seats, s->id, s) < 0) { free(s->state_file); free(s); return NULL; } return s; } void seat_free(Seat *s) { assert(s); if (s->in_gc_queue) LIST_REMOVE(gc_queue, s->manager->seat_gc_queue, s); while (s->sessions) session_free(s->sessions); assert(!s->active); while (s->devices) device_free(s->devices); hashmap_remove(s->manager->seats, s->id); free(s->positions); free(s->state_file); free(s); } int seat_save(Seat *s) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(s); if (!s->started) return 0; r = mkdir_safe_label("/run/systemd/seats", 0755, 0, 0); if (r < 0) goto fail; r = fopen_temporary(s->state_file, &f, &temp_path); if (r < 0) goto fail; fchmod(fileno(f), 0644); fprintf(f, "# This is private data. Do not parse.\n" "IS_SEAT0=%i\n" "CAN_MULTI_SESSION=%i\n" "CAN_TTY=%i\n" "CAN_GRAPHICAL=%i\n", seat_is_seat0(s), seat_can_multi_session(s), seat_can_tty(s), seat_can_graphical(s)); if (s->active) { assert(s->active->user); fprintf(f, "ACTIVE=%s\n" "ACTIVE_UID="UID_FMT"\n", s->active->id, s->active->user->uid); } if (s->sessions) { Session *i; fputs("SESSIONS=", f); LIST_FOREACH(sessions_by_seat, i, s->sessions) { fprintf(f, "%s%c", i->id, i->sessions_by_seat_next ? ' ' : '\n'); } fputs("UIDS=", f); LIST_FOREACH(sessions_by_seat, i, s->sessions) fprintf(f, UID_FMT"%c", i->user->uid, i->sessions_by_seat_next ? ' ' : '\n'); } r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, s->state_file) < 0) { r = -errno; goto fail; } return 0; fail: (void) unlink(s->state_file); if (temp_path) (void) unlink(temp_path); return log_error_errno(r, "Failed to save seat data %s: %m", s->state_file); } int seat_load(Seat *s) { assert(s); /* There isn't actually anything to read here ... */ return 0; } static int vt_allocate(unsigned int vtnr) { char p[sizeof("/dev/tty") + DECIMAL_STR_MAX(unsigned int)]; _cleanup_close_ int fd = -1; assert(vtnr >= 1); xsprintf(p, "/dev/tty%u", vtnr); fd = open_terminal(p, O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) return -errno; return 0; } int seat_preallocate_vts(Seat *s) { int r = 0; unsigned i; assert(s); assert(s->manager); log_debug("Preallocating VTs..."); if (s->manager->n_autovts <= 0) return 0; if (!seat_has_vts(s)) return 0; for (i = 1; i <= s->manager->n_autovts; i++) { int q; q = vt_allocate(i); if (q < 0) { log_error_errno(q, "Failed to preallocate VT %u: %m", i); r = q; } } return r; } int seat_apply_acls(Seat *s, Session *old_active) { int r; assert(s); r = devnode_acl_all(s->manager->udev, s->id, false, !!old_active, old_active ? old_active->user->uid : 0, !!s->active, s->active ? s->active->user->uid : 0); if (r < 0) log_error_errno(r, "Failed to apply ACLs: %m"); return r; } int seat_set_active(Seat *s, Session *session) { Session *old_active; assert(s); assert(!session || session->seat == s); if (session == s->active) return 0; old_active = s->active; s->active = session; if (old_active) { session_device_pause_all(old_active); session_send_changed(old_active, "Active", NULL); } seat_apply_acls(s, old_active); if (session && session->started) { session_send_changed(session, "Active", NULL); session_device_resume_all(session); } if (!session || session->started) seat_send_changed(s, "ActiveSession", NULL); seat_save(s); if (session) { session_save(session); user_save(session->user); } if (old_active) { session_save(old_active); if (!session || session->user != old_active->user) user_save(old_active->user); } return 0; } int seat_switch_to(Seat *s, unsigned int num) { /* Public session positions skip 0 (there is only F1-F12). Maybe it * will get reassigned in the future, so return error for now. */ if (num == 0) return -EINVAL; if (num >= s->position_count || !s->positions[num]) { /* allow switching to unused VTs to trigger auto-activate */ if (seat_has_vts(s) && num < 64) return chvt(num); return -EINVAL; } return session_activate(s->positions[num]); } int seat_switch_to_next(Seat *s) { unsigned int start, i; if (s->position_count == 0) return -EINVAL; start = 1; if (s->active && s->active->position > 0) start = s->active->position; for (i = start + 1; i < s->position_count; ++i) if (s->positions[i]) return session_activate(s->positions[i]); for (i = 1; i < start; ++i) if (s->positions[i]) return session_activate(s->positions[i]); return -EINVAL; } int seat_switch_to_previous(Seat *s) { unsigned int start, i; if (s->position_count == 0) return -EINVAL; start = 1; if (s->active && s->active->position > 0) start = s->active->position; for (i = start - 1; i > 0; --i) if (s->positions[i]) return session_activate(s->positions[i]); for (i = s->position_count - 1; i > start; --i) if (s->positions[i]) return session_activate(s->positions[i]); return -EINVAL; } int seat_active_vt_changed(Seat *s, unsigned int vtnr) { Session *i, *new_active = NULL; int r; assert(s); assert(vtnr >= 1); if (!seat_has_vts(s)) return -EINVAL; log_debug("VT changed to %u", vtnr); /* we might have earlier closing sessions on the same VT, so try to * find a running one first */ LIST_FOREACH(sessions_by_seat, i, s->sessions) if (i->vtnr == vtnr && !i->stopping) { new_active = i; break; } if (!new_active) { /* no running one? then we can't decide which one is the * active one, let the first one win */ LIST_FOREACH(sessions_by_seat, i, s->sessions) if (i->vtnr == vtnr) { new_active = i; break; } } r = seat_set_active(s, new_active); manager_spawn_autovt(s->manager, vtnr); return r; } int seat_read_active_vt(Seat *s) { char t[64]; ssize_t k; unsigned int vtnr; int r; assert(s); if (!seat_has_vts(s)) return 0; lseek(s->manager->console_active_fd, SEEK_SET, 0); k = read(s->manager->console_active_fd, t, sizeof(t)-1); if (k <= 0) { log_error("Failed to read current console: %s", k < 0 ? strerror(-errno) : "EOF"); return k < 0 ? -errno : -EIO; } t[k] = 0; truncate_nl(t); if (!startswith(t, "tty")) { log_error("Hm, /sys/class/tty/tty0/active is badly formatted."); return -EIO; } r = safe_atou(t+3, &vtnr); if (r < 0) { log_error("Failed to parse VT number %s", t+3); return r; } if (!vtnr) { log_error("VT number invalid: %s", t+3); return -EIO; } return seat_active_vt_changed(s, vtnr); } int seat_start(Seat *s) { assert(s); if (s->started) return 0; log_struct(LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_SEAT_START), "SEAT_ID=%s", s->id, LOG_MESSAGE("New seat %s.", s->id), NULL); /* Initialize VT magic stuff */ seat_preallocate_vts(s); /* Read current VT */ seat_read_active_vt(s); s->started = true; /* Save seat data */ seat_save(s); seat_send_signal(s, true); return 0; } int seat_stop(Seat *s, bool force) { int r = 0; assert(s); if (s->started) log_struct(LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_SEAT_STOP), "SEAT_ID=%s", s->id, LOG_MESSAGE("Removed seat %s.", s->id), NULL); seat_stop_sessions(s, force); unlink(s->state_file); seat_add_to_gc_queue(s); if (s->started) seat_send_signal(s, false); s->started = false; return r; } int seat_stop_sessions(Seat *s, bool force) { Session *session; int r = 0, k; assert(s); LIST_FOREACH(sessions_by_seat, session, s->sessions) { k = session_stop(session, force); if (k < 0) r = k; } return r; } void seat_evict_position(Seat *s, Session *session) { Session *iter; unsigned int pos = session->position; session->position = 0; if (pos == 0) return; if (pos < s->position_count && s->positions[pos] == session) { s->positions[pos] = NULL; /* There might be another session claiming the same * position (eg., during gdm->session transition), so let's look * for it and set it on the free slot. */ LIST_FOREACH(sessions_by_seat, iter, s->sessions) { if (iter->position == pos && session_get_state(iter) != SESSION_CLOSING) { s->positions[pos] = iter; break; } } } } void seat_claim_position(Seat *s, Session *session, unsigned int pos) { /* with VTs, the position is always the same as the VTnr */ if (seat_has_vts(s)) pos = session->vtnr; if (!GREEDY_REALLOC0(s->positions, s->position_count, pos + 1)) return; seat_evict_position(s, session); session->position = pos; if (pos > 0) s->positions[pos] = session; } static void seat_assign_position(Seat *s, Session *session) { unsigned int pos; if (session->position > 0) return; for (pos = 1; pos < s->position_count; ++pos) if (!s->positions[pos]) break; seat_claim_position(s, session, pos); } int seat_attach_session(Seat *s, Session *session) { assert(s); assert(session); assert(!session->seat); if (!seat_has_vts(s) != !session->vtnr) return -EINVAL; session->seat = s; LIST_PREPEND(sessions_by_seat, s->sessions, session); seat_assign_position(s, session); seat_send_changed(s, "Sessions", NULL); /* On seats with VTs, the VT logic defines which session is active. On * seats without VTs, we automatically activate new sessions. */ if (!seat_has_vts(s)) seat_set_active(s, session); return 0; } void seat_complete_switch(Seat *s) { Session *session; assert(s); /* if no session-switch is pending or if it got canceled, do nothing */ if (!s->pending_switch) return; session = s->pending_switch; s->pending_switch = NULL; seat_set_active(s, session); } bool seat_has_vts(Seat *s) { assert(s); return seat_is_seat0(s) && s->manager->console_active_fd >= 0; } bool seat_is_seat0(Seat *s) { assert(s); return s->manager->seat0 == s; } bool seat_can_multi_session(Seat *s) { assert(s); return seat_has_vts(s); } bool seat_can_tty(Seat *s) { assert(s); return seat_has_vts(s); } bool seat_has_master_device(Seat *s) { assert(s); /* device list is ordered by "master" flag */ return !!s->devices && s->devices->master; } bool seat_can_graphical(Seat *s) { assert(s); return seat_has_master_device(s); } int seat_get_idle_hint(Seat *s, dual_timestamp *t) { Session *session; bool idle_hint = true; dual_timestamp ts = DUAL_TIMESTAMP_NULL; assert(s); LIST_FOREACH(sessions_by_seat, session, s->sessions) { dual_timestamp k; int ih; ih = session_get_idle_hint(session, &k); if (ih < 0) return ih; if (!ih) { if (!idle_hint) { if (k.monotonic > ts.monotonic) ts = k; } else { idle_hint = false; ts = k; } } else if (idle_hint) { if (k.monotonic > ts.monotonic) ts = k; } } if (t) *t = ts; return idle_hint; } bool seat_check_gc(Seat *s, bool drop_not_started) { assert(s); if (drop_not_started && !s->started) return false; if (seat_is_seat0(s)) return true; return seat_has_master_device(s); } void seat_add_to_gc_queue(Seat *s) { assert(s); if (s->in_gc_queue) return; LIST_PREPEND(gc_queue, s->manager->seat_gc_queue, s); s->in_gc_queue = true; } static bool seat_name_valid_char(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '_'; } bool seat_name_is_valid(const char *name) { const char *p; assert(name); if (!startswith(name, "seat")) return false; if (!name[4]) return false; for (p = name; *p; p++) if (!seat_name_valid_char(*p)) return false; if (strlen(name) > 255) return false; return true; } systemd-229/src/login/logind-seat.h000066400000000000000000000054651265713322000173510ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Seat Seat; #include "list.h" #include "logind-session.h" struct Seat { Manager *manager; char *id; char *state_file; LIST_HEAD(Device, devices); Session *active; Session *pending_switch; LIST_HEAD(Session, sessions); Session **positions; size_t position_count; bool in_gc_queue:1; bool started:1; LIST_FIELDS(Seat, gc_queue); }; Seat *seat_new(Manager *m, const char *id); void seat_free(Seat *s); int seat_save(Seat *s); int seat_load(Seat *s); int seat_apply_acls(Seat *s, Session *old_active); int seat_set_active(Seat *s, Session *session); int seat_switch_to(Seat *s, unsigned int num); int seat_switch_to_next(Seat *s); int seat_switch_to_previous(Seat *s); int seat_active_vt_changed(Seat *s, unsigned int vtnr); int seat_read_active_vt(Seat *s); int seat_preallocate_vts(Seat *s); int seat_attach_session(Seat *s, Session *session); void seat_complete_switch(Seat *s); void seat_evict_position(Seat *s, Session *session); void seat_claim_position(Seat *s, Session *session, unsigned int pos); bool seat_has_vts(Seat *s); bool seat_is_seat0(Seat *s); bool seat_can_multi_session(Seat *s); bool seat_can_tty(Seat *s); bool seat_has_master_device(Seat *s); bool seat_can_graphical(Seat *s); int seat_get_idle_hint(Seat *s, dual_timestamp *t); int seat_start(Seat *s); int seat_stop(Seat *s, bool force); int seat_stop_sessions(Seat *s, bool force); bool seat_check_gc(Seat *s, bool drop_not_started); void seat_add_to_gc_queue(Seat *s); bool seat_name_is_valid(const char *name); extern const sd_bus_vtable seat_vtable[]; int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); char *seat_bus_path(Seat *s); int seat_send_signal(Seat *s, bool new_seat); int seat_send_changed(Seat *s, const char *properties, ...) _sentinel_; int bus_seat_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error); systemd-229/src/login/logind-session-dbus.c000066400000000000000000000573751265713322000210350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-label.h" #include "bus-util.h" #include "fd-util.h" #include "logind-session-device.h" #include "logind-session.h" #include "logind.h" #include "strv.h" #include "util.h" static int property_get_user( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Session *s = userdata; assert(bus); assert(reply); assert(s); p = user_bus_path(s->user); if (!p) return -ENOMEM; return sd_bus_message_append(reply, "(uo)", (uint32_t) s->user->uid, p); } static int property_get_name( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Session *s = userdata; assert(bus); assert(reply); assert(s); return sd_bus_message_append(reply, "s", s->user->name); } static int property_get_seat( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Session *s = userdata; assert(bus); assert(reply); assert(s); p = s->seat ? seat_bus_path(s->seat) : strdup("/"); if (!p) return -ENOMEM; return sd_bus_message_append(reply, "(so)", s->seat ? s->seat->id : "", p); } static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, session_type, SessionType); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, session_class, SessionClass); static int property_get_active( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Session *s = userdata; assert(bus); assert(reply); assert(s); return sd_bus_message_append(reply, "b", session_is_active(s)); } static int property_get_state( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Session *s = userdata; assert(bus); assert(reply); assert(s); return sd_bus_message_append(reply, "s", session_state_to_string(session_get_state(s))); } static int property_get_idle_hint( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Session *s = userdata; assert(bus); assert(reply); assert(s); return sd_bus_message_append(reply, "b", session_get_idle_hint(s, NULL) > 0); } static int property_get_idle_since_hint( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Session *s = userdata; dual_timestamp t = DUAL_TIMESTAMP_NULL; uint64_t u; int r; assert(bus); assert(reply); assert(s); r = session_get_idle_hint(s, &t); if (r < 0) return r; u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic; return sd_bus_message_append(reply, "t", u); } int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) { Session *s = userdata; int r; assert(message); assert(s); r = bus_verify_polkit_async( message, CAP_KILL, "org.freedesktop.login1.manage", NULL, false, s->user->uid, &s->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = session_stop(s, true); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error) { Session *s = userdata; int r; assert(message); assert(s); r = session_activate(s); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error) { Session *s = userdata; int r; assert(message); assert(s); r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, "org.freedesktop.login1.lock-sessions", NULL, false, s->user->uid, &s->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = session_send_lock(s, strstr(sd_bus_message_get_member(message), "Lock")); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; Session *s = userdata; uid_t uid; int r, b; assert(message); assert(s); r = sd_bus_message_read(message, "b", &b); if (r < 0) return r; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); if (r < 0) return r; r = sd_bus_creds_get_euid(creds, &uid); if (r < 0) return r; if (uid != 0 && uid != s->user->uid) return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set idle hint"); session_set_idle_hint(s, b); return sd_bus_reply_method_return(message, NULL); } int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) { Session *s = userdata; const char *swho; int32_t signo; KillWho who; int r; assert(message); assert(s); r = sd_bus_message_read(message, "si", &swho, &signo); if (r < 0) return r; if (isempty(swho)) who = KILL_ALL; else { who = kill_who_from_string(swho); if (who < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho); } if (signo <= 0 || signo >= _NSIG) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo); r = bus_verify_polkit_async( message, CAP_KILL, "org.freedesktop.login1.manage", NULL, false, s->user->uid, &s->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = session_kill(s, who, signo); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; Session *s = userdata; int r, force; uid_t uid; assert(message); assert(s); r = sd_bus_message_read(message, "b", &force); if (r < 0) return r; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); if (r < 0) return r; r = sd_bus_creds_get_euid(creds, &uid); if (r < 0) return r; if (uid != 0 && (force || uid != s->user->uid)) return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may take control"); r = session_set_controller(s, sd_bus_message_get_sender(message), force); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } static int method_release_control(sd_bus_message *message, void *userdata, sd_bus_error *error) { Session *s = userdata; assert(message); assert(s); if (!session_is_controller(s, sd_bus_message_get_sender(message))) return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session"); session_drop_controller(s); return sd_bus_reply_method_return(message, NULL); } static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_error *error) { Session *s = userdata; uint32_t major, minor; SessionDevice *sd; dev_t dev; int r; assert(message); assert(s); r = sd_bus_message_read(message, "uu", &major, &minor); if (r < 0) return r; if (!session_is_controller(s, sd_bus_message_get_sender(message))) return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session"); dev = makedev(major, minor); sd = hashmap_get(s->devices, &dev); if (sd) /* We don't allow retrieving a device multiple times. * The related ReleaseDevice call is not ref-counted. * The caller should use dup() if it requires more * than one fd (it would be functionally * equivalent). */ return sd_bus_error_setf(error, BUS_ERROR_DEVICE_IS_TAKEN, "Device already taken"); r = session_device_new(s, dev, &sd); if (r < 0) return r; r = sd_bus_reply_method_return(message, "hb", sd->fd, !sd->active); if (r < 0) session_device_free(sd); return r; } static int method_release_device(sd_bus_message *message, void *userdata, sd_bus_error *error) { Session *s = userdata; uint32_t major, minor; SessionDevice *sd; dev_t dev; int r; assert(message); assert(s); r = sd_bus_message_read(message, "uu", &major, &minor); if (r < 0) return r; if (!session_is_controller(s, sd_bus_message_get_sender(message))) return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session"); dev = makedev(major, minor); sd = hashmap_get(s->devices, &dev); if (!sd) return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken"); session_device_free(sd); return sd_bus_reply_method_return(message, NULL); } static int method_pause_device_complete(sd_bus_message *message, void *userdata, sd_bus_error *error) { Session *s = userdata; uint32_t major, minor; SessionDevice *sd; dev_t dev; int r; assert(message); assert(s); r = sd_bus_message_read(message, "uu", &major, &minor); if (r < 0) return r; if (!session_is_controller(s, sd_bus_message_get_sender(message))) return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session"); dev = makedev(major, minor); sd = hashmap_get(s->devices, &dev); if (!sd) return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken"); session_device_complete_pause(sd); return sd_bus_reply_method_return(message, NULL); } const sd_bus_vtable session_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Session, id), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("User", "(uo)", property_get_user, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Session, timestamp), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("VTNr", "u", NULL, offsetof(Session, vtnr), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Seat", "(so)", property_get_seat, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TTY", "s", NULL, offsetof(Session, tty), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Display", "s", NULL, offsetof(Session, display), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool, offsetof(Session, remote), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RemoteHost", "s", NULL, offsetof(Session, remote_host), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RemoteUser", "s", NULL, offsetof(Session, remote_user), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Session, service), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Session, scope), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid, offsetof(Session, leader), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Audit", "u", NULL, offsetof(Session, audit_id), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Session, type), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Session, class), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Active", "b", property_get_active, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0), SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_METHOD("Terminate", NULL, NULL, bus_session_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Activate", NULL, NULL, bus_session_method_activate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Lock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Unlock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Kill", "si", NULL, bus_session_method_kill, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("TakeControl", "b", NULL, method_take_control, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ReleaseControl", NULL, NULL, method_release_control, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ReleaseDevice", "uu", NULL, method_release_device, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("PauseDeviceComplete", "uu", NULL, method_pause_device_complete, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("PauseDevice", "uus", 0), SD_BUS_SIGNAL("ResumeDevice", "uuh", 0), SD_BUS_SIGNAL("Lock", NULL, 0), SD_BUS_SIGNAL("Unlock", NULL, 0), SD_BUS_VTABLE_END }; int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; Session *session; int r; assert(bus); assert(path); assert(interface); assert(found); assert(m); if (streq(path, "/org/freedesktop/login1/session/self")) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; sd_bus_message *message; const char *name; message = sd_bus_get_current_message(bus); if (!message) return 0; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds); if (r < 0) return r; r = sd_bus_creds_get_session(creds, &name); if (r < 0) return r; session = hashmap_get(m->sessions, name); } else { _cleanup_free_ char *e = NULL; const char *p; p = startswith(path, "/org/freedesktop/login1/session/"); if (!p) return 0; e = bus_label_unescape(p); if (!e) return -ENOMEM; session = hashmap_get(m->sessions, e); } if (!session) return 0; *found = session; return 1; } char *session_bus_path(Session *s) { _cleanup_free_ char *t = NULL; assert(s); t = bus_label_escape(s->id); if (!t) return NULL; return strappend("/org/freedesktop/login1/session/", t); } int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; sd_bus_message *message; Manager *m = userdata; Session *session; Iterator i; int r; assert(bus); assert(path); assert(nodes); HASHMAP_FOREACH(session, m->sessions, i) { char *p; p = session_bus_path(session); if (!p) return -ENOMEM; r = strv_consume(&l, p); if (r < 0) return r; } message = sd_bus_get_current_message(bus); if (message) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *name; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds); if (r >= 0) { r = sd_bus_creds_get_session(creds, &name); if (r >= 0) { session = hashmap_get(m->sessions, name); if (session) { r = strv_extend(&l, "/org/freedesktop/login1/session/self"); if (r < 0) return r; } } } } *nodes = l; l = NULL; return 1; } int session_send_signal(Session *s, bool new_session) { _cleanup_free_ char *p = NULL; assert(s); p = session_bus_path(s); if (!p) return -ENOMEM; return sd_bus_emit_signal( s->manager->bus, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", new_session ? "SessionNew" : "SessionRemoved", "so", s->id, p); } int session_send_changed(Session *s, const char *properties, ...) { _cleanup_free_ char *p = NULL; char **l; assert(s); if (!s->started) return 0; p = session_bus_path(s); if (!p) return -ENOMEM; l = strv_from_stdarg_alloca(properties); return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Session", l); } int session_send_lock(Session *s, bool lock) { _cleanup_free_ char *p = NULL; assert(s); p = session_bus_path(s); if (!p) return -ENOMEM; return sd_bus_emit_signal( s->manager->bus, p, "org.freedesktop.login1.Session", lock ? "Lock" : "Unlock", NULL); } int session_send_lock_all(Manager *m, bool lock) { Session *session; Iterator i; int r = 0; assert(m); HASHMAP_FOREACH(session, m->sessions, i) { int k; k = session_send_lock(session, lock); if (k < 0) r = k; } return r; } int session_send_create_reply(Session *s, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL; _cleanup_close_ int fifo_fd = -1; _cleanup_free_ char *p = NULL; assert(s); /* This is called after the session scope and the user service * were successfully created, and finishes where * bus_manager_create_session() left off. */ if (!s->create_message) return 0; if (!sd_bus_error_is_set(error) && (s->scope_job || s->user->service_job)) return 0; c = s->create_message; s->create_message = NULL; if (error) return sd_bus_reply_method_error(c, error); fifo_fd = session_create_fifo(s); if (fifo_fd < 0) return fifo_fd; /* Update the session state file before we notify the client * about the result. */ session_save(s); p = session_bus_path(s); if (!p) return -ENOMEM; log_debug("Sending reply about created session: " "id=%s object_path=%s uid=%u runtime_path=%s " "session_fd=%d seat=%s vtnr=%u", s->id, p, (uint32_t) s->user->uid, s->user->runtime_path, fifo_fd, s->seat ? s->seat->id : "", (uint32_t) s->vtnr); return sd_bus_reply_method_return( c, "soshusub", s->id, p, s->user->runtime_path, fifo_fd, (uint32_t) s->user->uid, s->seat ? s->seat->id : "", (uint32_t) s->vtnr, false); } systemd-229/src/login/logind-session-device.c000066400000000000000000000336141265713322000213250ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 David Herrmann systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "libudev.h" #include "alloc-util.h" #include "bus-util.h" #include "fd-util.h" #include "logind-session-device.h" #include "missing.h" #include "util.h" enum SessionDeviceNotifications { SESSION_DEVICE_RESUME, SESSION_DEVICE_TRY_PAUSE, SESSION_DEVICE_PAUSE, SESSION_DEVICE_RELEASE, }; static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotifications type) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_free_ char *path = NULL; const char *t = NULL; uint32_t major, minor; int r; assert(sd); major = major(sd->dev); minor = minor(sd->dev); if (!sd->session->controller) return 0; path = session_bus_path(sd->session); if (!path) return -ENOMEM; r = sd_bus_message_new_signal( sd->session->manager->bus, &m, path, "org.freedesktop.login1.Session", (type == SESSION_DEVICE_RESUME) ? "ResumeDevice" : "PauseDevice"); if (!m) return r; r = sd_bus_message_set_destination(m, sd->session->controller); if (r < 0) return r; switch (type) { case SESSION_DEVICE_RESUME: r = sd_bus_message_append(m, "uuh", major, minor, sd->fd); if (r < 0) return r; break; case SESSION_DEVICE_TRY_PAUSE: t = "pause"; break; case SESSION_DEVICE_PAUSE: t = "force"; break; case SESSION_DEVICE_RELEASE: t = "gone"; break; default: return -EINVAL; } if (t) { r = sd_bus_message_append(m, "uus", major, minor, t); if (r < 0) return r; } return sd_bus_send(sd->session->manager->bus, m, NULL); } static int sd_eviocrevoke(int fd) { static bool warned; int r; assert(fd >= 0); r = ioctl(fd, EVIOCREVOKE, NULL); if (r < 0) { r = -errno; if (r == -EINVAL && !warned) { warned = true; log_warning("kernel does not support evdev-revocation"); } } return 0; } static int sd_drmsetmaster(int fd) { int r; assert(fd >= 0); r = ioctl(fd, DRM_IOCTL_SET_MASTER, 0); if (r < 0) return -errno; return 0; } static int sd_drmdropmaster(int fd) { int r; assert(fd >= 0); r = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0); if (r < 0) return -errno; return 0; } static int session_device_open(SessionDevice *sd, bool active) { int fd, r; assert(sd->type != DEVICE_TYPE_UNKNOWN); /* open device and try to get an udev_device from it */ fd = open(sd->node, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); if (fd < 0) return -errno; switch (sd->type) { case DEVICE_TYPE_DRM: if (active) { /* Weird legacy DRM semantics might return an error * even though we're master. No way to detect that so * fail at all times and let caller retry in inactive * state. */ r = sd_drmsetmaster(fd); if (r < 0) { close_nointr(fd); return r; } } else { /* DRM-Master is granted to the first user who opens a * device automatically (ughh, racy!). Hence, we just * drop DRM-Master in case we were the first. */ sd_drmdropmaster(fd); } break; case DEVICE_TYPE_EVDEV: if (!active) sd_eviocrevoke(fd); break; case DEVICE_TYPE_UNKNOWN: default: /* fallback for devices wihout synchronizations */ break; } return fd; } static int session_device_start(SessionDevice *sd) { int r; assert(sd); assert(session_is_active(sd->session)); if (sd->active) return 0; switch (sd->type) { case DEVICE_TYPE_DRM: /* Device is kept open. Simply call drmSetMaster() and hope * there is no-one else. In case it fails, we keep the device * paused. Maybe at some point we have a drmStealMaster(). */ r = sd_drmsetmaster(sd->fd); if (r < 0) return r; break; case DEVICE_TYPE_EVDEV: /* Evdev devices are revoked while inactive. Reopen it and we * are fine. */ r = session_device_open(sd, true); if (r < 0) return r; close_nointr(sd->fd); sd->fd = r; break; case DEVICE_TYPE_UNKNOWN: default: /* fallback for devices wihout synchronizations */ break; } sd->active = true; return 0; } static void session_device_stop(SessionDevice *sd) { assert(sd); if (!sd->active) return; switch (sd->type) { case DEVICE_TYPE_DRM: /* On DRM devices we simply drop DRM-Master but keep it open. * This allows the user to keep resources allocated. The * CAP_SYS_ADMIN restriction to DRM-Master prevents users from * circumventing this. */ sd_drmdropmaster(sd->fd); break; case DEVICE_TYPE_EVDEV: /* Revoke access on evdev file-descriptors during deactivation. * This will basically prevent any operations on the fd and * cannot be undone. Good side is: it needs no CAP_SYS_ADMIN * protection this way. */ sd_eviocrevoke(sd->fd); break; case DEVICE_TYPE_UNKNOWN: default: /* fallback for devices without synchronization */ break; } sd->active = false; } static DeviceType detect_device_type(struct udev_device *dev) { const char *sysname, *subsystem; DeviceType type; sysname = udev_device_get_sysname(dev); subsystem = udev_device_get_subsystem(dev); type = DEVICE_TYPE_UNKNOWN; if (streq_ptr(subsystem, "drm")) { if (startswith(sysname, "card")) type = DEVICE_TYPE_DRM; } else if (streq_ptr(subsystem, "input")) { if (startswith(sysname, "event")) type = DEVICE_TYPE_EVDEV; } return type; } static int session_device_verify(SessionDevice *sd) { struct udev_device *dev, *p = NULL; const char *sp, *node; int r; dev = udev_device_new_from_devnum(sd->session->manager->udev, 'c', sd->dev); if (!dev) return -ENODEV; sp = udev_device_get_syspath(dev); node = udev_device_get_devnode(dev); if (!node) { r = -EINVAL; goto err_dev; } /* detect device type so we can find the correct sysfs parent */ sd->type = detect_device_type(dev); if (sd->type == DEVICE_TYPE_UNKNOWN) { r = -ENODEV; goto err_dev; } else if (sd->type == DEVICE_TYPE_EVDEV) { /* for evdev devices we need the parent node as device */ p = dev; dev = udev_device_get_parent_with_subsystem_devtype(p, "input", NULL); if (!dev) { r = -ENODEV; goto err_dev; } sp = udev_device_get_syspath(dev); } else if (sd->type != DEVICE_TYPE_DRM) { /* Prevent opening unsupported devices. Especially devices of * subsystem "input" must be opened via the evdev node as * we require EVIOCREVOKE. */ r = -ENODEV; goto err_dev; } /* search for an existing seat device and return it if available */ sd->device = hashmap_get(sd->session->manager->devices, sp); if (!sd->device) { /* The caller might have gotten the udev event before we were * able to process it. Hence, fake the "add" event and let the * logind-manager handle the new device. */ r = manager_process_seat_device(sd->session->manager, dev); if (r < 0) goto err_dev; /* if it's still not available, then the device is invalid */ sd->device = hashmap_get(sd->session->manager->devices, sp); if (!sd->device) { r = -ENODEV; goto err_dev; } } if (sd->device->seat != sd->session->seat) { r = -EPERM; goto err_dev; } sd->node = strdup(node); if (!sd->node) { r = -ENOMEM; goto err_dev; } r = 0; err_dev: udev_device_unref(p ? : dev); return r; } int session_device_new(Session *s, dev_t dev, SessionDevice **out) { SessionDevice *sd; int r; assert(s); assert(out); if (!s->seat) return -EPERM; sd = new0(SessionDevice, 1); if (!sd) return -ENOMEM; sd->session = s; sd->dev = dev; sd->fd = -1; sd->type = DEVICE_TYPE_UNKNOWN; r = session_device_verify(sd); if (r < 0) goto error; r = hashmap_put(s->devices, &sd->dev, sd); if (r < 0) { r = -ENOMEM; goto error; } /* Open the device for the first time. We need a valid fd to pass back * to the caller. If the session is not active, this _might_ immediately * revoke access and thus invalidate the fd. But this is still needed * to pass a valid fd back. */ sd->active = session_is_active(s); r = session_device_open(sd, sd->active); if (r < 0) { /* EINVAL _may_ mean a master is active; retry inactive */ if (sd->active && r == -EINVAL) { sd->active = false; r = session_device_open(sd, false); } if (r < 0) goto error; } sd->fd = r; LIST_PREPEND(sd_by_device, sd->device->session_devices, sd); *out = sd; return 0; error: hashmap_remove(s->devices, &sd->dev); free(sd->node); free(sd); return r; } void session_device_free(SessionDevice *sd) { assert(sd); session_device_stop(sd); session_device_notify(sd, SESSION_DEVICE_RELEASE); close_nointr(sd->fd); LIST_REMOVE(sd_by_device, sd->device->session_devices, sd); hashmap_remove(sd->session->devices, &sd->dev); free(sd->node); free(sd); } void session_device_complete_pause(SessionDevice *sd) { SessionDevice *iter; Iterator i; if (!sd->active) return; session_device_stop(sd); /* if not all devices are paused, wait for further completion events */ HASHMAP_FOREACH(iter, sd->session->devices, i) if (iter->active) return; /* complete any pending session switch */ seat_complete_switch(sd->session->seat); } void session_device_resume_all(Session *s) { SessionDevice *sd; Iterator i; int r; assert(s); HASHMAP_FOREACH(sd, s->devices, i) { if (!sd->active) { r = session_device_start(sd); if (!r) session_device_notify(sd, SESSION_DEVICE_RESUME); } } } void session_device_pause_all(Session *s) { SessionDevice *sd; Iterator i; assert(s); HASHMAP_FOREACH(sd, s->devices, i) { if (sd->active) { session_device_stop(sd); session_device_notify(sd, SESSION_DEVICE_PAUSE); } } } unsigned int session_device_try_pause_all(Session *s) { SessionDevice *sd; Iterator i; unsigned int num_pending = 0; assert(s); HASHMAP_FOREACH(sd, s->devices, i) { if (sd->active) { session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE); ++num_pending; } } return num_pending; } systemd-229/src/login/logind-session-device.h000066400000000000000000000027341265713322000213310ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 David Herrmann systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef enum DeviceType DeviceType; typedef struct SessionDevice SessionDevice; #include "list.h" #include "logind.h" enum DeviceType { DEVICE_TYPE_UNKNOWN, DEVICE_TYPE_DRM, DEVICE_TYPE_EVDEV, }; struct SessionDevice { Session *session; Device *device; dev_t dev; char *node; int fd; bool active; DeviceType type; LIST_FIELDS(struct SessionDevice, sd_by_device); }; int session_device_new(Session *s, dev_t dev, SessionDevice **out); void session_device_free(SessionDevice *sd); void session_device_complete_pause(SessionDevice *sd); void session_device_resume_all(Session *s); void session_device_pause_all(Session *s); unsigned int session_device_try_pause_all(Session *s); systemd-229/src/login/logind-session.c000066400000000000000000001055021265713322000200640ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "sd-messages.h" #include "alloc-util.h" #include "audit-util.h" #include "bus-error.h" #include "bus-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "io-util.h" #include "logind-session.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" #include "string-table.h" #include "terminal-util.h" #include "user-util.h" #include "util.h" #define RELEASE_USEC (20*USEC_PER_SEC) static void session_remove_fifo(Session *s); Session* session_new(Manager *m, const char *id) { Session *s; assert(m); assert(id); assert(session_id_valid(id)); s = new0(Session, 1); if (!s) return NULL; s->state_file = strappend("/run/systemd/sessions/", id); if (!s->state_file) { free(s); return NULL; } s->devices = hashmap_new(&devt_hash_ops); if (!s->devices) { free(s->state_file); free(s); return NULL; } s->id = basename(s->state_file); if (hashmap_put(m->sessions, s->id, s) < 0) { hashmap_free(s->devices); free(s->state_file); free(s); return NULL; } s->manager = m; s->fifo_fd = -1; s->vtfd = -1; return s; } void session_free(Session *s) { SessionDevice *sd; assert(s); if (s->in_gc_queue) LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s); s->timer_event_source = sd_event_source_unref(s->timer_event_source); session_remove_fifo(s); session_drop_controller(s); while ((sd = hashmap_first(s->devices))) session_device_free(sd); hashmap_free(s->devices); if (s->user) { LIST_REMOVE(sessions_by_user, s->user->sessions, s); if (s->user->display == s) s->user->display = NULL; } if (s->seat) { if (s->seat->active == s) s->seat->active = NULL; if (s->seat->pending_switch == s) s->seat->pending_switch = NULL; seat_evict_position(s->seat, s); LIST_REMOVE(sessions_by_seat, s->seat->sessions, s); } if (s->scope) { hashmap_remove(s->manager->session_units, s->scope); free(s->scope); } free(s->scope_job); sd_bus_message_unref(s->create_message); free(s->tty); free(s->display); free(s->remote_host); free(s->remote_user); free(s->service); free(s->desktop); hashmap_remove(s->manager->sessions, s->id); free(s->state_file); free(s); } void session_set_user(Session *s, User *u) { assert(s); assert(!s->user); s->user = u; LIST_PREPEND(sessions_by_user, u->sessions, s); } int session_save(Session *s) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; int r = 0; assert(s); if (!s->user) return -ESTALE; if (!s->started) return 0; r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0); if (r < 0) goto fail; r = fopen_temporary(s->state_file, &f, &temp_path); if (r < 0) goto fail; assert(s->user); fchmod(fileno(f), 0644); fprintf(f, "# This is private data. Do not parse.\n" "UID="UID_FMT"\n" "USER=%s\n" "ACTIVE=%i\n" "STATE=%s\n" "REMOTE=%i\n", s->user->uid, s->user->name, session_is_active(s), session_state_to_string(session_get_state(s)), s->remote); if (s->type >= 0) fprintf(f, "TYPE=%s\n", session_type_to_string(s->type)); if (s->class >= 0) fprintf(f, "CLASS=%s\n", session_class_to_string(s->class)); if (s->scope) fprintf(f, "SCOPE=%s\n", s->scope); if (s->scope_job) fprintf(f, "SCOPE_JOB=%s\n", s->scope_job); if (s->fifo_path) fprintf(f, "FIFO=%s\n", s->fifo_path); if (s->seat) fprintf(f, "SEAT=%s\n", s->seat->id); if (s->tty) fprintf(f, "TTY=%s\n", s->tty); if (s->display) fprintf(f, "DISPLAY=%s\n", s->display); if (s->remote_host) { _cleanup_free_ char *escaped; escaped = cescape(s->remote_host); if (!escaped) { r = -ENOMEM; goto fail; } fprintf(f, "REMOTE_HOST=%s\n", escaped); } if (s->remote_user) { _cleanup_free_ char *escaped; escaped = cescape(s->remote_user); if (!escaped) { r = -ENOMEM; goto fail; } fprintf(f, "REMOTE_USER=%s\n", escaped); } if (s->service) { _cleanup_free_ char *escaped; escaped = cescape(s->service); if (!escaped) { r = -ENOMEM; goto fail; } fprintf(f, "SERVICE=%s\n", escaped); } if (s->desktop) { _cleanup_free_ char *escaped; escaped = cescape(s->desktop); if (!escaped) { r = -ENOMEM; goto fail; } fprintf(f, "DESKTOP=%s\n", escaped); } if (s->seat && seat_has_vts(s->seat)) fprintf(f, "VTNR=%u\n", s->vtnr); if (!s->vtnr) fprintf(f, "POSITION=%u\n", s->position); if (s->leader > 0) fprintf(f, "LEADER="PID_FMT"\n", s->leader); if (s->audit_id > 0) fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id); if (dual_timestamp_is_set(&s->timestamp)) fprintf(f, "REALTIME="USEC_FMT"\n" "MONOTONIC="USEC_FMT"\n", s->timestamp.realtime, s->timestamp.monotonic); if (s->controller) fprintf(f, "CONTROLLER=%s\n", s->controller); r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, s->state_file) < 0) { r = -errno; goto fail; } return 0; fail: (void) unlink(s->state_file); if (temp_path) (void) unlink(temp_path); return log_error_errno(r, "Failed to save session data %s: %m", s->state_file); } int session_load(Session *s) { _cleanup_free_ char *remote = NULL, *seat = NULL, *vtnr = NULL, *state = NULL, *position = NULL, *leader = NULL, *type = NULL, *class = NULL, *uid = NULL, *realtime = NULL, *monotonic = NULL, *controller = NULL; int k, r; assert(s); r = parse_env_file(s->state_file, NEWLINE, "REMOTE", &remote, "SCOPE", &s->scope, "SCOPE_JOB", &s->scope_job, "FIFO", &s->fifo_path, "SEAT", &seat, "TTY", &s->tty, "DISPLAY", &s->display, "REMOTE_HOST", &s->remote_host, "REMOTE_USER", &s->remote_user, "SERVICE", &s->service, "DESKTOP", &s->desktop, "VTNR", &vtnr, "STATE", &state, "POSITION", &position, "LEADER", &leader, "TYPE", &type, "CLASS", &class, "UID", &uid, "REALTIME", &realtime, "MONOTONIC", &monotonic, "CONTROLLER", &controller, NULL); if (r < 0) return log_error_errno(r, "Failed to read %s: %m", s->state_file); if (!s->user) { uid_t u; User *user; if (!uid) { log_error("UID not specified for session %s", s->id); return -ENOENT; } r = parse_uid(uid, &u); if (r < 0) { log_error("Failed to parse UID value %s for session %s.", uid, s->id); return r; } user = hashmap_get(s->manager->users, UID_TO_PTR(u)); if (!user) { log_error("User of session %s not known.", s->id); return -ENOENT; } session_set_user(s, user); } if (remote) { k = parse_boolean(remote); if (k >= 0) s->remote = k; } if (vtnr) safe_atou(vtnr, &s->vtnr); if (seat && !s->seat) { Seat *o; o = hashmap_get(s->manager->seats, seat); if (o) r = seat_attach_session(o, s); if (!o || r < 0) log_error("Cannot attach session %s to seat %s", s->id, seat); } if (!s->seat || !seat_has_vts(s->seat)) s->vtnr = 0; if (position && s->seat) { unsigned int npos; safe_atou(position, &npos); seat_claim_position(s->seat, s, npos); } if (leader) { k = parse_pid(leader, &s->leader); if (k >= 0) audit_session_from_pid(s->leader, &s->audit_id); } if (type) { SessionType t; t = session_type_from_string(type); if (t >= 0) s->type = t; } if (class) { SessionClass c; c = session_class_from_string(class); if (c >= 0) s->class = c; } if (state && streq(state, "closing")) s->stopping = true; if (s->fifo_path) { int fd; /* If we open an unopened pipe for reading we will not get an EOF. to trigger an EOF we hence open it for writing, but close it right away which then will trigger the EOF. This will happen immediately if no other process has the FIFO open for writing, i. e. when the session died before logind (re)started. */ fd = session_create_fifo(s); safe_close(fd); } if (realtime) { unsigned long long l; if (sscanf(realtime, "%llu", &l) > 0) s->timestamp.realtime = l; } if (monotonic) { unsigned long long l; if (sscanf(monotonic, "%llu", &l) > 0) s->timestamp.monotonic = l; } if (controller) { if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) session_set_controller(s, controller, false); else session_restore_vt(s); } return r; } int session_activate(Session *s) { unsigned int num_pending; assert(s); assert(s->user); if (!s->seat) return -EOPNOTSUPP; if (s->seat->active == s) return 0; /* on seats with VTs, we let VTs manage session-switching */ if (seat_has_vts(s->seat)) { if (!s->vtnr) return -EOPNOTSUPP; return chvt(s->vtnr); } /* On seats without VTs, we implement session-switching in logind. We * try to pause all session-devices and wait until the session * controller acknowledged them. Once all devices are asleep, we simply * switch the active session and be done. * We save the session we want to switch to in seat->pending_switch and * seat_complete_switch() will perform the final switch. */ s->seat->pending_switch = s; /* if no devices are running, immediately perform the session switch */ num_pending = session_device_try_pause_all(s); if (!num_pending) seat_complete_switch(s->seat); return 0; } static int session_start_scope(Session *s) { int r; assert(s); assert(s->user); if (!s->scope) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *scope, *job = NULL; const char *description; scope = strjoin("session-", s->id, ".scope", NULL); if (!scope) return log_oom(); description = strjoina("Session ", s->id, " of user ", s->user->name, NULL); r = manager_start_scope( s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-sessions.service", (uint64_t) -1, /* disable TasksMax= for the scope, rely on the slice setting for it */ &error, &job); if (r < 0) { log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(&error, r)); free(scope); return r; } else { s->scope = scope; free(s->scope_job); s->scope_job = job; } } if (s->scope) (void) hashmap_put(s->manager->session_units, s->scope, s); return 0; } int session_start(Session *s) { int r; assert(s); if (!s->user) return -ESTALE; if (s->started) return 0; r = user_start(s->user); if (r < 0) return r; /* Create cgroup */ r = session_start_scope(s); if (r < 0) return r; log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_SESSION_START), "SESSION_ID=%s", s->id, "USER_ID=%s", s->user->name, "LEADER="PID_FMT, s->leader, LOG_MESSAGE("New session %s of user %s.", s->id, s->user->name), NULL); if (!dual_timestamp_is_set(&s->timestamp)) dual_timestamp_get(&s->timestamp); if (s->seat) seat_read_active_vt(s->seat); s->started = true; user_elect_display(s->user); /* Save data */ session_save(s); user_save(s->user); if (s->seat) seat_save(s->seat); /* Send signals */ session_send_signal(s, true); user_send_changed(s->user, "Sessions", "Display", NULL); if (s->seat) { if (s->seat->active == s) seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL); else seat_send_changed(s->seat, "Sessions", NULL); } return 0; } static int session_stop_scope(Session *s, bool force) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *job = NULL; int r; assert(s); if (!s->scope) return 0; if (force || manager_shall_kill(s->manager, s->user->name)) { r = manager_stop_unit(s->manager, s->scope, &error, &job); if (r < 0) { log_error("Failed to stop session scope: %s", bus_error_message(&error, r)); return r; } free(s->scope_job); s->scope_job = job; } else { r = manager_abandon_scope(s->manager, s->scope, &error); if (r < 0) { log_error("Failed to abandon session scope: %s", bus_error_message(&error, r)); return r; } } return 0; } int session_stop(Session *s, bool force) { int r; assert(s); if (!s->user) return -ESTALE; s->timer_event_source = sd_event_source_unref(s->timer_event_source); if (s->seat) seat_evict_position(s->seat, s); /* We are going down, don't care about FIFOs anymore */ session_remove_fifo(s); /* Kill cgroup */ r = session_stop_scope(s, force); s->stopping = true; user_elect_display(s->user); session_save(s); user_save(s->user); return r; } int session_finalize(Session *s) { SessionDevice *sd; assert(s); if (!s->user) return -ESTALE; if (s->started) log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_SESSION_STOP), "SESSION_ID=%s", s->id, "USER_ID=%s", s->user->name, "LEADER="PID_FMT, s->leader, LOG_MESSAGE("Removed session %s.", s->id), NULL); s->timer_event_source = sd_event_source_unref(s->timer_event_source); if (s->seat) seat_evict_position(s->seat, s); /* Kill session devices */ while ((sd = hashmap_first(s->devices))) session_device_free(sd); (void) unlink(s->state_file); session_add_to_gc_queue(s); user_add_to_gc_queue(s->user); if (s->started) { session_send_signal(s, false); s->started = false; } if (s->seat) { if (s->seat->active == s) seat_set_active(s->seat, NULL); seat_save(s->seat); seat_send_changed(s->seat, "Sessions", NULL); } user_save(s->user); user_send_changed(s->user, "Sessions", "Display", NULL); return 0; } static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) { Session *s = userdata; assert(es); assert(s); session_stop(s, false); return 0; } int session_release(Session *s) { assert(s); if (!s->started || s->stopping) return 0; if (s->timer_event_source) return 0; return sd_event_add_time(s->manager->event, &s->timer_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + RELEASE_USEC, 0, release_timeout_callback, s); } bool session_is_active(Session *s) { assert(s); if (!s->seat) return true; return s->seat->active == s; } static int get_tty_atime(const char *tty, usec_t *atime) { _cleanup_free_ char *p = NULL; struct stat st; assert(tty); assert(atime); if (!path_is_absolute(tty)) { p = strappend("/dev/", tty); if (!p) return -ENOMEM; tty = p; } else if (!path_startswith(tty, "/dev/")) return -ENOENT; if (lstat(tty, &st) < 0) return -errno; *atime = timespec_load(&st.st_atim); return 0; } static int get_process_ctty_atime(pid_t pid, usec_t *atime) { _cleanup_free_ char *p = NULL; int r; assert(pid > 0); assert(atime); r = get_ctty(pid, NULL, &p); if (r < 0) return r; return get_tty_atime(p, atime); } int session_get_idle_hint(Session *s, dual_timestamp *t) { usec_t atime = 0, n; int r; assert(s); /* Explicit idle hint is set */ if (s->idle_hint) { if (t) *t = s->idle_hint_timestamp; return s->idle_hint; } /* Graphical sessions should really implement a real * idle hint logic */ if (s->display) goto dont_know; /* For sessions with an explicitly configured tty, let's check * its atime */ if (s->tty) { r = get_tty_atime(s->tty, &atime); if (r >= 0) goto found_atime; } /* For sessions with a leader but no explicitly configured * tty, let's check the controlling tty of the leader */ if (s->leader > 0) { r = get_process_ctty_atime(s->leader, &atime); if (r >= 0) goto found_atime; } dont_know: if (t) *t = s->idle_hint_timestamp; return 0; found_atime: if (t) dual_timestamp_from_realtime(t, atime); n = now(CLOCK_REALTIME); if (s->manager->idle_action_usec <= 0) return 0; return atime + s->manager->idle_action_usec <= n; } void session_set_idle_hint(Session *s, bool b) { assert(s); if (s->idle_hint == b) return; s->idle_hint = b; dual_timestamp_get(&s->idle_hint_timestamp); session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL); if (s->seat) seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL); user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL); manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL); } static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) { Session *s = userdata; assert(s); assert(s->fifo_fd == fd); /* EOF on the FIFO means the session died abnormally. */ session_remove_fifo(s); session_stop(s, false); return 1; } int session_create_fifo(Session *s) { int r; assert(s); /* Create FIFO */ if (!s->fifo_path) { r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0); if (r < 0) return r; if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0) return -ENOMEM; if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST) return -errno; } /* Open reading side */ if (s->fifo_fd < 0) { s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY); if (s->fifo_fd < 0) return -errno; } if (!s->fifo_event_source) { r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s); if (r < 0) return r; r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE); if (r < 0) return r; } /* Open writing side */ r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY); if (r < 0) return -errno; return r; } static void session_remove_fifo(Session *s) { assert(s); s->fifo_event_source = sd_event_source_unref(s->fifo_event_source); s->fifo_fd = safe_close(s->fifo_fd); if (s->fifo_path) { unlink(s->fifo_path); s->fifo_path = mfree(s->fifo_path); } } bool session_check_gc(Session *s, bool drop_not_started) { assert(s); if (drop_not_started && !s->started) return false; if (!s->user) return false; if (s->fifo_fd >= 0) { if (pipe_eof(s->fifo_fd) <= 0) return true; } if (s->scope_job && manager_job_is_active(s->manager, s->scope_job)) return true; if (s->scope && manager_unit_is_active(s->manager, s->scope)) return true; return false; } void session_add_to_gc_queue(Session *s) { assert(s); if (s->in_gc_queue) return; LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s); s->in_gc_queue = true; } SessionState session_get_state(Session *s) { assert(s); /* always check closing first */ if (s->stopping || s->timer_event_source) return SESSION_CLOSING; if (s->scope_job || s->fifo_fd < 0) return SESSION_OPENING; if (session_is_active(s)) return SESSION_ACTIVE; return SESSION_ONLINE; } int session_kill(Session *s, KillWho who, int signo) { assert(s); if (!s->scope) return -ESRCH; return manager_kill_unit(s->manager, s->scope, who, signo, NULL); } static int session_open_vt(Session *s) { char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)]; if (s->vtnr < 1) return -ENODEV; if (s->vtfd >= 0) return s->vtfd; sprintf(path, "/dev/tty%u", s->vtnr); s->vtfd = open_terminal(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY); if (s->vtfd < 0) return log_error_errno(s->vtfd, "cannot open VT %s of session %s: %m", path, s->id); return s->vtfd; } int session_prepare_vt(Session *s) { int vt, r; struct vt_mode mode = { 0 }; if (s->vtnr < 1) return 0; vt = session_open_vt(s); if (vt < 0) return vt; r = fchown(vt, s->user->uid, -1); if (r < 0) { r = log_error_errno(errno, "Cannot change owner of /dev/tty%u: %m", s->vtnr); goto error; } r = ioctl(vt, KDSKBMODE, K_OFF); if (r < 0) { r = log_error_errno(errno, "Cannot set K_OFF on /dev/tty%u: %m", s->vtnr); goto error; } r = ioctl(vt, KDSETMODE, KD_GRAPHICS); if (r < 0) { r = log_error_errno(errno, "Cannot set KD_GRAPHICS on /dev/tty%u: %m", s->vtnr); goto error; } /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS. * So we need a dummy handler here which just acknowledges *all* VT * switch requests. */ mode.mode = VT_PROCESS; mode.relsig = SIGRTMIN; mode.acqsig = SIGRTMIN + 1; r = ioctl(vt, VT_SETMODE, &mode); if (r < 0) { r = log_error_errno(errno, "Cannot set VT_PROCESS on /dev/tty%u: %m", s->vtnr); goto error; } return 0; error: session_restore_vt(s); return r; } void session_restore_vt(Session *s) { static const struct vt_mode mode = { .mode = VT_AUTO, }; _cleanup_free_ char *utf8 = NULL; int vt, kb, old_fd; /* We need to get a fresh handle to the virtual terminal, * since the old file-descriptor is potentially in a hung-up * state after the controlling process exited; we do a * little dance to avoid having the terminal be available * for reuse before we've cleaned it up. */ old_fd = s->vtfd; s->vtfd = -1; vt = session_open_vt(s); safe_close(old_fd); if (vt < 0) return; (void) ioctl(vt, KDSETMODE, KD_TEXT); if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1') kb = K_UNICODE; else kb = K_XLATE; (void) ioctl(vt, KDSKBMODE, kb); (void) ioctl(vt, VT_SETMODE, &mode); (void) fchown(vt, 0, (gid_t) -1); s->vtfd = safe_close(s->vtfd); } void session_leave_vt(Session *s) { int r; assert(s); /* This is called whenever we get a VT-switch signal from the kernel. * We acknowledge all of them unconditionally. Note that session are * free to overwrite those handlers and we only register them for * sessions with controllers. Legacy sessions are not affected. * However, if we switch from a non-legacy to a legacy session, we must * make sure to pause all device before acknowledging the switch. We * process the real switch only after we are notified via sysfs, so the * legacy session might have already started using the devices. If we * don't pause the devices before the switch, we might confuse the * session we switch to. */ if (s->vtfd < 0) return; session_device_pause_all(s); r = ioctl(s->vtfd, VT_RELDISP, 1); if (r < 0) log_debug_errno(errno, "Cannot release VT of session %s: %m", s->id); } bool session_is_controller(Session *s, const char *sender) { assert(s); return streq_ptr(s->controller, sender); } static void session_release_controller(Session *s, bool notify) { _cleanup_free_ char *name = NULL; SessionDevice *sd; if (!s->controller) return; name = s->controller; /* By resetting the controller before releasing the devices, we won't * send notification signals. This avoids sending useless notifications * if the controller is released on disconnects. */ if (!notify) s->controller = NULL; while ((sd = hashmap_first(s->devices))) session_device_free(sd); s->controller = NULL; s->track = sd_bus_track_unref(s->track); } static int on_bus_track(sd_bus_track *track, void *userdata) { Session *s = userdata; assert(track); assert(s); session_drop_controller(s); return 0; } int session_set_controller(Session *s, const char *sender, bool force) { _cleanup_free_ char *name = NULL; int r; assert(s); assert(sender); if (session_is_controller(s, sender)) return 0; if (s->controller && !force) return -EBUSY; name = strdup(sender); if (!name) return -ENOMEM; s->track = sd_bus_track_unref(s->track); r = sd_bus_track_new(s->manager->bus, &s->track, on_bus_track, s); if (r < 0) return r; r = sd_bus_track_add_name(s->track, name); if (r < 0) return r; /* When setting a session controller, we forcibly mute the VT and set * it into graphics-mode. Applications can override that by changing * VT state after calling TakeControl(). However, this serves as a good * default and well-behaving controllers can now ignore VTs entirely. * Note that we reset the VT on ReleaseControl() and if the controller * exits. * If logind crashes/restarts, we restore the controller during restart * or reset the VT in case it crashed/exited, too. */ r = session_prepare_vt(s); if (r < 0) { s->track = sd_bus_track_unref(s->track); return r; } session_release_controller(s, true); s->controller = name; name = NULL; session_save(s); return 0; } void session_drop_controller(Session *s) { assert(s); if (!s->controller) return; s->track = sd_bus_track_unref(s->track); session_release_controller(s, false); session_save(s); session_restore_vt(s); } static const char* const session_state_table[_SESSION_STATE_MAX] = { [SESSION_OPENING] = "opening", [SESSION_ONLINE] = "online", [SESSION_ACTIVE] = "active", [SESSION_CLOSING] = "closing" }; DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState); static const char* const session_type_table[_SESSION_TYPE_MAX] = { [SESSION_UNSPECIFIED] = "unspecified", [SESSION_TTY] = "tty", [SESSION_X11] = "x11", [SESSION_WAYLAND] = "wayland", [SESSION_MIR] = "mir", [SESSION_WEB] = "web", }; DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType); static const char* const session_class_table[_SESSION_CLASS_MAX] = { [SESSION_USER] = "user", [SESSION_GREETER] = "greeter", [SESSION_LOCK_SCREEN] = "lock-screen", [SESSION_BACKGROUND] = "background" }; DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass); static const char* const kill_who_table[_KILL_WHO_MAX] = { [KILL_LEADER] = "leader", [KILL_ALL] = "all" }; DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho); systemd-229/src/login/logind-session.h000066400000000000000000000125331265713322000200720ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Session Session; typedef enum KillWho KillWho; #include "list.h" #include "login-util.h" #include "logind-user.h" typedef enum SessionState { SESSION_OPENING, /* Session scope is being created */ SESSION_ONLINE, /* Logged in */ SESSION_ACTIVE, /* Logged in and in the fg */ SESSION_CLOSING, /* Logged out, but scope is still there */ _SESSION_STATE_MAX, _SESSION_STATE_INVALID = -1 } SessionState; typedef enum SessionClass { SESSION_USER, SESSION_GREETER, SESSION_LOCK_SCREEN, SESSION_BACKGROUND, _SESSION_CLASS_MAX, _SESSION_CLASS_INVALID = -1 } SessionClass; typedef enum SessionType { SESSION_UNSPECIFIED, SESSION_TTY, SESSION_X11, SESSION_WAYLAND, SESSION_MIR, SESSION_WEB, _SESSION_TYPE_MAX, _SESSION_TYPE_INVALID = -1 } SessionType; #define SESSION_TYPE_IS_GRAPHICAL(type) IN_SET(type, SESSION_X11, SESSION_WAYLAND, SESSION_MIR) enum KillWho { KILL_LEADER, KILL_ALL, _KILL_WHO_MAX, _KILL_WHO_INVALID = -1 }; struct Session { Manager *manager; const char *id; unsigned int position; SessionType type; SessionClass class; char *state_file; User *user; dual_timestamp timestamp; char *tty; char *display; bool remote; char *remote_user; char *remote_host; char *service; char *desktop; char *scope; char *scope_job; Seat *seat; unsigned int vtnr; int vtfd; pid_t leader; uint32_t audit_id; int fifo_fd; char *fifo_path; sd_event_source *fifo_event_source; bool idle_hint; dual_timestamp idle_hint_timestamp; bool in_gc_queue:1; bool started:1; bool stopping:1; sd_bus_message *create_message; sd_event_source *timer_event_source; char *controller; Hashmap *devices; sd_bus_track *track; LIST_FIELDS(Session, sessions_by_user); LIST_FIELDS(Session, sessions_by_seat); LIST_FIELDS(Session, gc_queue); }; Session *session_new(Manager *m, const char *id); void session_free(Session *s); void session_set_user(Session *s, User *u); bool session_check_gc(Session *s, bool drop_not_started); void session_add_to_gc_queue(Session *s); int session_activate(Session *s); bool session_is_active(Session *s); int session_get_idle_hint(Session *s, dual_timestamp *t); void session_set_idle_hint(Session *s, bool b); int session_create_fifo(Session *s); int session_start(Session *s); int session_stop(Session *s, bool force); int session_finalize(Session *s); int session_release(Session *s); int session_save(Session *s); int session_load(Session *s); int session_kill(Session *s, KillWho who, int signo); SessionState session_get_state(Session *u); extern const sd_bus_vtable session_vtable[]; int session_node_enumerator(sd_bus *bus, const char *path,void *userdata, char ***nodes, sd_bus_error *error); int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); char *session_bus_path(Session *s); int session_send_signal(Session *s, bool new_session); int session_send_changed(Session *s, const char *properties, ...) _sentinel_; int session_send_lock(Session *s, bool lock); int session_send_lock_all(Manager *m, bool lock); int session_send_create_reply(Session *s, sd_bus_error *error); const char* session_state_to_string(SessionState t) _const_; SessionState session_state_from_string(const char *s) _pure_; const char* session_type_to_string(SessionType t) _const_; SessionType session_type_from_string(const char *s) _pure_; const char* session_class_to_string(SessionClass t) _const_; SessionClass session_class_from_string(const char *s) _pure_; const char *kill_who_to_string(KillWho k) _const_; KillWho kill_who_from_string(const char *s) _pure_; int session_prepare_vt(Session *s); void session_restore_vt(Session *s); void session_leave_vt(Session *s); bool session_is_controller(Session *s, const char *sender); int session_set_controller(Session *s, const char *sender, bool force); void session_drop_controller(Session *s); int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error); systemd-229/src/login/logind-user-dbus.c000066400000000000000000000273761265713322000203260ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "bus-util.h" #include "formats-util.h" #include "logind-user.h" #include "logind.h" #include "strv.h" #include "user-util.h" static int property_get_display( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; User *u = userdata; assert(bus); assert(reply); assert(u); p = u->display ? session_bus_path(u->display) : strdup("/"); if (!p) return -ENOMEM; return sd_bus_message_append(reply, "(so)", u->display ? u->display->id : "", p); } static int property_get_state( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { User *u = userdata; assert(bus); assert(reply); assert(u); return sd_bus_message_append(reply, "s", user_state_to_string(user_get_state(u))); } static int property_get_sessions( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { User *u = userdata; Session *session; int r; assert(bus); assert(reply); assert(u); r = sd_bus_message_open_container(reply, 'a', "(so)"); if (r < 0) return r; LIST_FOREACH(sessions_by_user, session, u->sessions) { _cleanup_free_ char *p = NULL; p = session_bus_path(session); if (!p) return -ENOMEM; r = sd_bus_message_append(reply, "(so)", session->id, p); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_idle_hint( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { User *u = userdata; assert(bus); assert(reply); assert(u); return sd_bus_message_append(reply, "b", user_get_idle_hint(u, NULL) > 0); } static int property_get_idle_since_hint( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { User *u = userdata; dual_timestamp t = DUAL_TIMESTAMP_NULL; uint64_t k; assert(bus); assert(reply); assert(u); user_get_idle_hint(u, &t); k = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic; return sd_bus_message_append(reply, "t", k); } static int property_get_linger( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { User *u = userdata; int r; assert(bus); assert(reply); assert(u); r = user_check_linger_file(u); return sd_bus_message_append(reply, "b", r > 0); } int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) { User *u = userdata; int r; assert(message); assert(u); r = bus_verify_polkit_async( message, CAP_KILL, "org.freedesktop.login1.manage", NULL, false, u->uid, &u->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = user_stop(u, true); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) { User *u = userdata; int32_t signo; int r; assert(message); assert(u); r = bus_verify_polkit_async( message, CAP_KILL, "org.freedesktop.login1.manage", NULL, false, u->uid, &u->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = sd_bus_message_read(message, "i", &signo); if (r < 0) return r; if (signo <= 0 || signo >= _NSIG) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo); r = user_kill(u, signo); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } const sd_bus_vtable user_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(User, uid), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(User, gid), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Name", "s", NULL, offsetof(User, name), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(User, timestamp), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RuntimePath", "s", NULL, offsetof(User, runtime_path), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Service", "s", NULL, offsetof(User, service), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Slice", "s", NULL, offsetof(User, slice), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Display", "(so)", property_get_display, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0), SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Linger", "b", property_get_linger, 0, 0), SD_BUS_METHOD("Terminate", NULL, NULL, bus_user_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Kill", "i", NULL, bus_user_method_kill, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; uid_t uid; User *user; int r; assert(bus); assert(path); assert(interface); assert(found); assert(m); if (streq(path, "/org/freedesktop/login1/user/self")) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; sd_bus_message *message; message = sd_bus_get_current_message(bus); if (!message) return 0; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); if (r < 0) return r; r = sd_bus_creds_get_owner_uid(creds, &uid); } else { const char *p; p = startswith(path, "/org/freedesktop/login1/user/_"); if (!p) return 0; r = parse_uid(p, &uid); } if (r < 0) return 0; user = hashmap_get(m->users, UID_TO_PTR(uid)); if (!user) return 0; *found = user; return 1; } char *user_bus_path(User *u) { char *s; assert(u); if (asprintf(&s, "/org/freedesktop/login1/user/_"UID_FMT, u->uid) < 0) return NULL; return s; } int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; sd_bus_message *message; Manager *m = userdata; User *user; Iterator i; int r; assert(bus); assert(path); assert(nodes); HASHMAP_FOREACH(user, m->users, i) { char *p; p = user_bus_path(user); if (!p) return -ENOMEM; r = strv_consume(&l, p); if (r < 0) return r; } message = sd_bus_get_current_message(bus); if (message) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; uid_t uid; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); if (r >= 0) { r = sd_bus_creds_get_owner_uid(creds, &uid); if (r >= 0) { user = hashmap_get(m->users, UID_TO_PTR(uid)); if (user) { r = strv_extend(&l, "/org/freedesktop/login1/user/self"); if (r < 0) return r; } } } } *nodes = l; l = NULL; return 1; } int user_send_signal(User *u, bool new_user) { _cleanup_free_ char *p = NULL; assert(u); p = user_bus_path(u); if (!p) return -ENOMEM; return sd_bus_emit_signal( u->manager->bus, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", new_user ? "UserNew" : "UserRemoved", "uo", (uint32_t) u->uid, p); } int user_send_changed(User *u, const char *properties, ...) { _cleanup_free_ char *p = NULL; char **l; assert(u); if (!u->started) return 0; p = user_bus_path(u); if (!p) return -ENOMEM; l = strv_from_stdarg_alloca(properties); return sd_bus_emit_properties_changed_strv(u->manager->bus, p, "org.freedesktop.login1.User", l); } systemd-229/src/login/logind-user.c000066400000000000000000000631661265713322000173700ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" #include "clean-ipc.h" #include "conf-parser.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "hashmap.h" #include "label.h" #include "logind-user.h" #include "mkdir.h" #include "mount-util.h" #include "parse-util.h" #include "path-util.h" #include "rm-rf.h" #include "smack-util.h" #include "special.h" #include "stdio-util.h" #include "string-table.h" #include "unit-name.h" #include "user-util.h" #include "util.h" int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) { _cleanup_(user_freep) User *u = NULL; char lu[DECIMAL_STR_MAX(uid_t) + 1]; int r; assert(out); assert(m); assert(name); u = new0(User, 1); if (!u) return -ENOMEM; u->manager = m; u->uid = uid; u->gid = gid; xsprintf(lu, UID_FMT, uid); u->name = strdup(name); if (!u->name) return -ENOMEM; if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0) return -ENOMEM; if (asprintf(&u->runtime_path, "/run/user/"UID_FMT, uid) < 0) return -ENOMEM; r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &u->slice); if (r < 0) return r; r = unit_name_build("user", lu, ".service", &u->service); if (r < 0) return r; r = hashmap_put(m->users, UID_TO_PTR(uid), u); if (r < 0) return r; r = hashmap_put(m->user_units, u->slice, u); if (r < 0) return r; r = hashmap_put(m->user_units, u->service, u); if (r < 0) return r; *out = u; u = NULL; return 0; } User *user_free(User *u) { if (!u) return NULL; if (u->in_gc_queue) LIST_REMOVE(gc_queue, u->manager->user_gc_queue, u); while (u->sessions) session_free(u->sessions); if (u->service) hashmap_remove_value(u->manager->user_units, u->service, u); if (u->slice) hashmap_remove_value(u->manager->user_units, u->slice, u); hashmap_remove_value(u->manager->users, UID_TO_PTR(u->uid), u); u->slice_job = mfree(u->slice_job); u->service_job = mfree(u->service_job); u->service = mfree(u->service); u->slice = mfree(u->slice); u->runtime_path = mfree(u->runtime_path); u->state_file = mfree(u->state_file); u->name = mfree(u->name); return mfree(u); } static int user_save_internal(User *u) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(u); assert(u->state_file); r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0); if (r < 0) goto fail; r = fopen_temporary(u->state_file, &f, &temp_path); if (r < 0) goto fail; fchmod(fileno(f), 0644); fprintf(f, "# This is private data. Do not parse.\n" "NAME=%s\n" "STATE=%s\n", u->name, user_state_to_string(user_get_state(u))); /* LEGACY: no-one reads RUNTIME= anymore, drop it at some point */ if (u->runtime_path) fprintf(f, "RUNTIME=%s\n", u->runtime_path); if (u->service_job) fprintf(f, "SERVICE_JOB=%s\n", u->service_job); if (u->slice_job) fprintf(f, "SLICE_JOB=%s\n", u->slice_job); if (u->display) fprintf(f, "DISPLAY=%s\n", u->display->id); if (dual_timestamp_is_set(&u->timestamp)) fprintf(f, "REALTIME="USEC_FMT"\n" "MONOTONIC="USEC_FMT"\n", u->timestamp.realtime, u->timestamp.monotonic); if (u->sessions) { Session *i; bool first; fputs("SESSIONS=", f); first = true; LIST_FOREACH(sessions_by_user, i, u->sessions) { if (first) first = false; else fputc(' ', f); fputs(i->id, f); } fputs("\nSEATS=", f); first = true; LIST_FOREACH(sessions_by_user, i, u->sessions) { if (!i->seat) continue; if (first) first = false; else fputc(' ', f); fputs(i->seat->id, f); } fputs("\nACTIVE_SESSIONS=", f); first = true; LIST_FOREACH(sessions_by_user, i, u->sessions) { if (!session_is_active(i)) continue; if (first) first = false; else fputc(' ', f); fputs(i->id, f); } fputs("\nONLINE_SESSIONS=", f); first = true; LIST_FOREACH(sessions_by_user, i, u->sessions) { if (session_get_state(i) == SESSION_CLOSING) continue; if (first) first = false; else fputc(' ', f); fputs(i->id, f); } fputs("\nACTIVE_SEATS=", f); first = true; LIST_FOREACH(sessions_by_user, i, u->sessions) { if (!session_is_active(i) || !i->seat) continue; if (first) first = false; else fputc(' ', f); fputs(i->seat->id, f); } fputs("\nONLINE_SEATS=", f); first = true; LIST_FOREACH(sessions_by_user, i, u->sessions) { if (session_get_state(i) == SESSION_CLOSING || !i->seat) continue; if (first) first = false; else fputc(' ', f); fputs(i->seat->id, f); } fputc('\n', f); } r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, u->state_file) < 0) { r = -errno; goto fail; } return 0; fail: (void) unlink(u->state_file); if (temp_path) (void) unlink(temp_path); return log_error_errno(r, "Failed to save user data %s: %m", u->state_file); } int user_save(User *u) { assert(u); if (!u->started) return 0; return user_save_internal (u); } int user_load(User *u) { _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL; Session *s = NULL; int r; assert(u); r = parse_env_file(u->state_file, NEWLINE, "SERVICE_JOB", &u->service_job, "SLICE_JOB", &u->slice_job, "DISPLAY", &display, "REALTIME", &realtime, "MONOTONIC", &monotonic, NULL); if (r < 0) { if (r == -ENOENT) return 0; log_error_errno(r, "Failed to read %s: %m", u->state_file); return r; } if (display) s = hashmap_get(u->manager->sessions, display); if (s && s->display && display_is_local(s->display)) u->display = s; if (realtime) { unsigned long long l; if (sscanf(realtime, "%llu", &l) > 0) u->timestamp.realtime = l; } if (monotonic) { unsigned long long l; if (sscanf(monotonic, "%llu", &l) > 0) u->timestamp.monotonic = l; } return r; } static int user_mkdir_runtime_path(User *u) { int r; assert(u); r = mkdir_safe_label("/run/user", 0755, 0, 0); if (r < 0) return log_error_errno(r, "Failed to create /run/user: %m"); if (path_is_mount_point(u->runtime_path, 0) <= 0) { _cleanup_free_ char *t = NULL; (void) mkdir_label(u->runtime_path, 0700); if (mac_smack_use()) r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size); else r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size); if (r < 0) { r = log_oom(); goto fail; } r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, t); if (r < 0) { if (errno != EPERM) { r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", u->runtime_path); goto fail; } /* Lacking permissions, maybe * CAP_SYS_ADMIN-less container? In this case, * just use a normal directory. */ r = chmod_and_chown(u->runtime_path, 0700, u->uid, u->gid); if (r < 0) { log_error_errno(r, "Failed to change runtime directory ownership and mode: %m"); goto fail; } } r = label_fix(u->runtime_path, false, false); if (r < 0) log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", u->runtime_path); } return 0; fail: /* Try to clean up, but ignore errors */ (void) rmdir(u->runtime_path); return r; } static int user_start_slice(User *u) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *description; char *job; int r; assert(u); u->slice_job = mfree(u->slice_job); description = strjoina("User Slice of ", u->name); r = manager_start_slice( u->manager, u->slice, description, "systemd-logind.service", "systemd-user-sessions.service", u->manager->user_tasks_max, &error, &job); if (r >= 0) u->slice_job = job; else if (!sd_bus_error_has_name(&error, BUS_ERROR_UNIT_EXISTS)) /* we don't fail due to this, let's try to continue */ log_error_errno(r, "Failed to start user slice %s, ignoring: %s (%s)", u->slice, bus_error_message(&error, r), error.name); return 0; } static int user_start_service(User *u) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *job; int r; assert(u); u->service_job = mfree(u->service_job); r = manager_start_unit( u->manager, u->service, &error, &job); if (r < 0) { /* we don't fail due to this, let's try to continue */ log_error_errno(r, "Failed to start user service, ignoring: %s", bus_error_message(&error, r)); } else { u->service_job = job; } return 0; } int user_start(User *u) { int r; assert(u); if (u->started && !u->stopping) return 0; /* * If u->stopping is set, the user is marked for removal and the slice * and service stop-jobs are queued. We have to clear that flag before * queing the start-jobs again. If they succeed, the user object can be * re-used just fine (pid1 takes care of job-ordering and proper * restart), but if they fail, we want to force another user_stop() so * possibly pending units are stopped. * Note that we don't clear u->started, as we have no clue what state * the user is in on failure here. Hence, we pretend the user is * running so it will be properly taken down by GC. However, we clearly * return an error from user_start() in that case, so no further * reference to the user is taken. */ u->stopping = false; if (!u->started) { log_debug("New user %s logged in.", u->name); /* Make XDG_RUNTIME_DIR */ r = user_mkdir_runtime_path(u); if (r < 0) return r; } /* Create cgroup */ r = user_start_slice(u); if (r < 0) return r; /* Save the user data so far, because pam_systemd will read the * XDG_RUNTIME_DIR out of it while starting up systemd --user. * We need to do user_save_internal() because we have not * "officially" started yet. */ user_save_internal(u); /* Spawn user systemd */ r = user_start_service(u); if (r < 0) return r; if (!u->started) { if (!dual_timestamp_is_set(&u->timestamp)) dual_timestamp_get(&u->timestamp); user_send_signal(u, true); u->started = true; } /* Save new user data */ user_save(u); return 0; } static int user_stop_slice(User *u) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *job; int r; assert(u); r = manager_stop_unit(u->manager, u->slice, &error, &job); if (r < 0) { log_error("Failed to stop user slice: %s", bus_error_message(&error, r)); return r; } free(u->slice_job); u->slice_job = job; return r; } static int user_stop_service(User *u) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *job; int r; assert(u); r = manager_stop_unit(u->manager, u->service, &error, &job); if (r < 0) { log_error("Failed to stop user service: %s", bus_error_message(&error, r)); return r; } free(u->service_job); u->service_job = job; return r; } static int user_remove_runtime_path(User *u) { int r; assert(u); r = rm_rf(u->runtime_path, 0); if (r < 0) log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path); /* Ignore cases where the directory isn't mounted, as that's * quite possible, if we lacked the permissions to mount * something */ r = umount2(u->runtime_path, MNT_DETACH); if (r < 0 && errno != EINVAL && errno != ENOENT) log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", u->runtime_path); r = rm_rf(u->runtime_path, REMOVE_ROOT); if (r < 0) log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path); return r; } int user_stop(User *u, bool force) { Session *s; int r = 0, k; assert(u); /* Stop jobs have already been queued */ if (u->stopping) { user_save(u); return r; } LIST_FOREACH(sessions_by_user, s, u->sessions) { k = session_stop(s, force); if (k < 0) r = k; } /* Kill systemd */ k = user_stop_service(u); if (k < 0) r = k; /* Kill cgroup */ k = user_stop_slice(u); if (k < 0) r = k; u->stopping = true; user_save(u); return r; } int user_finalize(User *u) { Session *s; int r = 0, k; assert(u); if (u->started) log_debug("User %s logged out.", u->name); LIST_FOREACH(sessions_by_user, s, u->sessions) { k = session_finalize(s); if (k < 0) r = k; } /* Kill XDG_RUNTIME_DIR */ k = user_remove_runtime_path(u); if (k < 0) r = k; /* Clean SysV + POSIX IPC objects */ if (u->manager->remove_ipc) { k = clean_ipc(u->uid); if (k < 0) r = k; } unlink(u->state_file); user_add_to_gc_queue(u); if (u->started) { user_send_signal(u, false); u->started = false; } return r; } int user_get_idle_hint(User *u, dual_timestamp *t) { Session *s; bool idle_hint = true; dual_timestamp ts = DUAL_TIMESTAMP_NULL; assert(u); LIST_FOREACH(sessions_by_user, s, u->sessions) { dual_timestamp k; int ih; ih = session_get_idle_hint(s, &k); if (ih < 0) return ih; if (!ih) { if (!idle_hint) { if (k.monotonic < ts.monotonic) ts = k; } else { idle_hint = false; ts = k; } } else if (idle_hint) { if (k.monotonic > ts.monotonic) ts = k; } } if (t) *t = ts; return idle_hint; } int user_check_linger_file(User *u) { _cleanup_free_ char *cc = NULL; char *p = NULL; cc = cescape(u->name); if (!cc) return -ENOMEM; p = strjoina("/var/lib/systemd/linger/", cc); return access(p, F_OK) >= 0; } bool user_check_gc(User *u, bool drop_not_started) { assert(u); if (drop_not_started && !u->started) return false; if (u->sessions) return true; if (user_check_linger_file(u) > 0) return true; if (u->slice_job && manager_job_is_active(u->manager, u->slice_job)) return true; if (u->service_job && manager_job_is_active(u->manager, u->service_job)) return true; return false; } void user_add_to_gc_queue(User *u) { assert(u); if (u->in_gc_queue) return; LIST_PREPEND(gc_queue, u->manager->user_gc_queue, u); u->in_gc_queue = true; } UserState user_get_state(User *u) { Session *i; assert(u); if (u->stopping) return USER_CLOSING; if (!u->started || u->slice_job || u->service_job) return USER_OPENING; if (u->sessions) { bool all_closing = true; LIST_FOREACH(sessions_by_user, i, u->sessions) { SessionState state; state = session_get_state(i); if (state == SESSION_ACTIVE) return USER_ACTIVE; if (state != SESSION_CLOSING) all_closing = false; } return all_closing ? USER_CLOSING : USER_ONLINE; } if (user_check_linger_file(u) > 0) return USER_LINGERING; return USER_CLOSING; } int user_kill(User *u, int signo) { assert(u); return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL); } static bool elect_display_filter(Session *s) { /* Return true if the session is a candidate for the user’s ‘primary * session’ or ‘display’. */ assert(s); return (s->class == SESSION_USER && !s->stopping); } static int elect_display_compare(Session *s1, Session *s2) { /* Indexed by SessionType. Lower numbers mean more preferred. */ const int type_ranks[_SESSION_TYPE_MAX] = { [SESSION_UNSPECIFIED] = 0, [SESSION_TTY] = -2, [SESSION_X11] = -3, [SESSION_WAYLAND] = -3, [SESSION_MIR] = -3, [SESSION_WEB] = -1, }; /* Calculate the partial order relationship between s1 and s2, * returning < 0 if s1 is preferred as the user’s ‘primary session’, * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2 * is preferred. * * s1 or s2 may be NULL. */ if (!s1 && !s2) return 0; if ((s1 == NULL) != (s2 == NULL)) return (s1 == NULL) - (s2 == NULL); if (s1->stopping != s2->stopping) return s1->stopping - s2->stopping; if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER)) return (s1->class != SESSION_USER) - (s2->class != SESSION_USER); if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID)) return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID); if (s1->type != s2->type) return type_ranks[s1->type] - type_ranks[s2->type]; return 0; } void user_elect_display(User *u) { Session *s; assert(u); /* This elects a primary session for each user, which we call * the "display". We try to keep the assignment stable, but we * "upgrade" to better choices. */ log_debug("Electing new display for user %s", u->name); LIST_FOREACH(sessions_by_user, s, u->sessions) { if (!elect_display_filter(s)) { log_debug("Ignoring session %s", s->id); continue; } if (elect_display_compare(s, u->display) < 0) { log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-"); u->display = s; } } } static const char* const user_state_table[_USER_STATE_MAX] = { [USER_OFFLINE] = "offline", [USER_OPENING] = "opening", [USER_LINGERING] = "lingering", [USER_ONLINE] = "online", [USER_ACTIVE] = "active", [USER_CLOSING] = "closing" }; DEFINE_STRING_TABLE_LOOKUP(user_state, UserState); int config_parse_tmpfs_size( const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { size_t *sz = data; const char *e; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); e = endswith(rvalue, "%"); if (e) { unsigned long ul; char *f; errno = 0; ul = strtoul(rvalue, &f, 10); if (errno > 0 || f != e) { log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse percentage value, ignoring: %s", rvalue); return 0; } if (ul <= 0 || ul >= 100) { log_syntax(unit, LOG_ERR, filename, line, 0, "Percentage value out of range, ignoring: %s", rvalue); return 0; } *sz = PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) ul) / (uint64_t) 100)); } else { uint64_t k; r = parse_size(rvalue, 1024, &k); if (r < 0 || (uint64_t) (size_t) k != k) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue); return 0; } *sz = PAGE_ALIGN((size_t) k); } return 0; } systemd-229/src/login/logind-user.h000066400000000000000000000057711265713322000173730ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct User User; #include "list.h" #include "logind.h" typedef enum UserState { USER_OFFLINE, /* Not logged in at all */ USER_OPENING, /* Is logging in */ USER_LINGERING, /* Lingering has been enabled by the admin for this user */ USER_ONLINE, /* User logged in */ USER_ACTIVE, /* User logged in and has a session in the fg */ USER_CLOSING, /* User logged out, but processes still remain and lingering is not enabled */ _USER_STATE_MAX, _USER_STATE_INVALID = -1 } UserState; struct User { Manager *manager; uid_t uid; gid_t gid; char *name; char *state_file; char *runtime_path; char *slice; char *service; char *service_job; char *slice_job; Session *display; dual_timestamp timestamp; bool in_gc_queue:1; bool started:1; bool stopping:1; LIST_HEAD(Session, sessions); LIST_FIELDS(User, gc_queue); }; int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name); User *user_free(User *u); DEFINE_TRIVIAL_CLEANUP_FUNC(User *, user_free); bool user_check_gc(User *u, bool drop_not_started); void user_add_to_gc_queue(User *u); int user_start(User *u); int user_stop(User *u, bool force); int user_finalize(User *u); UserState user_get_state(User *u); int user_get_idle_hint(User *u, dual_timestamp *t); int user_save(User *u); int user_load(User *u); int user_kill(User *u, int signo); int user_check_linger_file(User *u); void user_elect_display(User *u); extern const sd_bus_vtable user_vtable[]; int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); char *user_bus_path(User *s); int user_send_signal(User *u, bool new_user); int user_send_changed(User *u, const char *properties, ...) _sentinel_; const char* user_state_to_string(UserState s) _const_; UserState user_state_from_string(const char *s) _pure_; int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error); systemd-229/src/login/logind-utmp.c000066400000000000000000000123371265713322000173710ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Daniel Mack systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-messages.h" #include "alloc-util.h" #include "audit-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" #include "formats-util.h" #include "logind.h" #include "special.h" #include "strv.h" #include "unit-name.h" #include "user-util.h" #include "utmp-wtmp.h" _const_ static usec_t when_wall(usec_t n, usec_t elapse) { usec_t left; unsigned int i; static const int wall_timers[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 25, 40, 55, 70, 100, 130, 150, 180, }; /* If the time is already passed, then don't announce */ if (n >= elapse) return 0; left = elapse - n; for (i = 1; i < ELEMENTSOF(wall_timers); i++) if (wall_timers[i] * USEC_PER_MINUTE >= left) return left - wall_timers[i-1] * USEC_PER_MINUTE; return left % USEC_PER_HOUR; } bool logind_wall_tty_filter(const char *tty, void *userdata) { Manager *m = userdata; assert(m); if (!startswith(tty, "/dev/")) return true; return !streq(tty + 5, m->scheduled_shutdown_tty); } static int warn_wall(Manager *m, usec_t n) { char date[FORMAT_TIMESTAMP_MAX] = {}; _cleanup_free_ char *l = NULL; usec_t left; int r; assert(m); if (!m->enable_wall_messages) return 0; left = m->scheduled_shutdown_timeout > n; r = asprintf(&l, "%s%sThe system is going down for %s %s%s!", strempty(m->wall_message), isempty(m->wall_message) ? "" : "\n", m->scheduled_shutdown_type, left ? "at " : "NOW", left ? format_timestamp(date, sizeof(date), m->scheduled_shutdown_timeout) : ""); if (r < 0) { log_oom(); return 0; } utmp_wall(l, uid_to_name(m->scheduled_shutdown_uid), m->scheduled_shutdown_tty, logind_wall_tty_filter, m); return 1; } static int wall_message_timeout_handler( sd_event_source *s, uint64_t usec, void *userdata) { Manager *m = userdata; usec_t n, next; int r; assert(m); assert(s == m->wall_message_timeout_source); n = now(CLOCK_REALTIME); r = warn_wall(m, n); if (r == 0) return 0; next = when_wall(n, m->scheduled_shutdown_timeout); if (next > 0) { r = sd_event_source_set_time(s, n + next); if (r < 0) return log_error_errno(r, "sd_event_source_set_time() failed. %m"); r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT); if (r < 0) return log_error_errno(r, "sd_event_source_set_enabled() failed. %m"); } return 0; } int manager_setup_wall_message_timer(Manager *m) { usec_t n, elapse; int r; assert(m); n = now(CLOCK_REALTIME); elapse = m->scheduled_shutdown_timeout; /* wall message handling */ if (isempty(m->scheduled_shutdown_type)) { warn_wall(m, n); return 0; } if (elapse < n) return 0; /* Warn immediately if less than 15 minutes are left */ if (elapse - n < 15 * USEC_PER_MINUTE) { r = warn_wall(m, n); if (r == 0) return 0; } elapse = when_wall(n, elapse); if (elapse == 0) return 0; if (m->wall_message_timeout_source) { r = sd_event_source_set_time(m->wall_message_timeout_source, n + elapse); if (r < 0) return log_error_errno(r, "sd_event_source_set_time() failed. %m"); r = sd_event_source_set_enabled(m->wall_message_timeout_source, SD_EVENT_ONESHOT); if (r < 0) return log_error_errno(r, "sd_event_source_set_enabled() failed. %m"); } else { r = sd_event_add_time(m->event, &m->wall_message_timeout_source, CLOCK_REALTIME, n + elapse, 0, wall_message_timeout_handler, m); if (r < 0) return log_error_errno(r, "sd_event_add_time() failed. %m"); } return 0; } systemd-229/src/login/logind.c000066400000000000000000001123001265713322000163750ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "libudev.h" #include "sd-daemon.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "conf-parser.h" #include "def.h" #include "dirent-util.h" #include "fd-util.h" #include "formats-util.h" #include "logind.h" #include "selinux-util.h" #include "signal-util.h" #include "strv.h" #include "udev-util.h" static void manager_free(Manager *m); static Manager *manager_new(void) { Manager *m; int r; m = new0(Manager, 1); if (!m) return NULL; m->console_active_fd = -1; m->reserve_vt_fd = -1; m->n_autovts = 6; m->reserve_vt = 6; m->remove_ipc = true; m->inhibit_delay_max = 5 * USEC_PER_SEC; m->handle_power_key = HANDLE_POWEROFF; m->handle_suspend_key = HANDLE_SUSPEND; m->handle_hibernate_key = HANDLE_HIBERNATE; m->handle_lid_switch = HANDLE_SUSPEND; m->handle_lid_switch_docked = HANDLE_IGNORE; m->lid_switch_ignore_inhibited = true; m->holdoff_timeout_usec = 30 * USEC_PER_SEC; m->idle_action_usec = 30 * USEC_PER_MINUTE; m->idle_action = HANDLE_IGNORE; m->idle_action_not_before_usec = now(CLOCK_MONOTONIC); m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */ m->user_tasks_max = UINT64_C(12288); m->devices = hashmap_new(&string_hash_ops); m->seats = hashmap_new(&string_hash_ops); m->sessions = hashmap_new(&string_hash_ops); m->users = hashmap_new(NULL); m->inhibitors = hashmap_new(&string_hash_ops); m->buttons = hashmap_new(&string_hash_ops); m->user_units = hashmap_new(&string_hash_ops); m->session_units = hashmap_new(&string_hash_ops); if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units) goto fail; m->kill_exclude_users = strv_new("root", NULL); if (!m->kill_exclude_users) goto fail; m->udev = udev_new(); if (!m->udev) goto fail; r = sd_event_default(&m->event); if (r < 0) goto fail; sd_event_set_watchdog(m->event, true); return m; fail: manager_free(m); return NULL; } static void manager_free(Manager *m) { Session *session; User *u; Device *d; Seat *s; Inhibitor *i; Button *b; assert(m); while ((session = hashmap_first(m->sessions))) session_free(session); while ((u = hashmap_first(m->users))) user_free(u); while ((d = hashmap_first(m->devices))) device_free(d); while ((s = hashmap_first(m->seats))) seat_free(s); while ((i = hashmap_first(m->inhibitors))) inhibitor_free(i); while ((b = hashmap_first(m->buttons))) button_free(b); hashmap_free(m->devices); hashmap_free(m->seats); hashmap_free(m->sessions); hashmap_free(m->users); hashmap_free(m->inhibitors); hashmap_free(m->buttons); hashmap_free(m->user_units); hashmap_free(m->session_units); sd_event_source_unref(m->idle_action_event_source); sd_event_source_unref(m->inhibit_timeout_source); sd_event_source_unref(m->scheduled_shutdown_timeout_source); sd_event_source_unref(m->nologin_timeout_source); sd_event_source_unref(m->wall_message_timeout_source); sd_event_source_unref(m->console_active_event_source); sd_event_source_unref(m->udev_seat_event_source); sd_event_source_unref(m->udev_device_event_source); sd_event_source_unref(m->udev_vcsa_event_source); sd_event_source_unref(m->udev_button_event_source); sd_event_source_unref(m->lid_switch_ignore_event_source); safe_close(m->console_active_fd); udev_monitor_unref(m->udev_seat_monitor); udev_monitor_unref(m->udev_device_monitor); udev_monitor_unref(m->udev_vcsa_monitor); udev_monitor_unref(m->udev_button_monitor); udev_unref(m->udev); if (m->unlink_nologin) (void) unlink("/run/nologin"); bus_verify_polkit_async_registry_free(m->polkit_registry); sd_bus_unref(m->bus); sd_event_unref(m->event); safe_close(m->reserve_vt_fd); strv_free(m->kill_only_users); strv_free(m->kill_exclude_users); free(m->scheduled_shutdown_type); free(m->scheduled_shutdown_tty); free(m->wall_message); free(m->action_job); free(m); } static int manager_enumerate_devices(Manager *m) { struct udev_list_entry *item = NULL, *first = NULL; _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; int r; assert(m); /* Loads devices from udev and creates seats for them as * necessary */ e = udev_enumerate_new(m->udev); if (!e) return -ENOMEM; r = udev_enumerate_add_match_tag(e, "master-of-seat"); if (r < 0) return r; r = udev_enumerate_add_match_is_initialized(e); if (r < 0) return r; r = udev_enumerate_scan_devices(e); if (r < 0) return r; first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; int k; d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item)); if (!d) return -ENOMEM; k = manager_process_seat_device(m, d); if (k < 0) r = k; } return r; } static int manager_enumerate_buttons(Manager *m) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; struct udev_list_entry *item = NULL, *first = NULL; int r; assert(m); /* Loads buttons from udev */ if (m->handle_power_key == HANDLE_IGNORE && m->handle_suspend_key == HANDLE_IGNORE && m->handle_hibernate_key == HANDLE_IGNORE && m->handle_lid_switch == HANDLE_IGNORE && m->handle_lid_switch_docked == HANDLE_IGNORE) return 0; e = udev_enumerate_new(m->udev); if (!e) return -ENOMEM; r = udev_enumerate_add_match_subsystem(e, "input"); if (r < 0) return r; r = udev_enumerate_add_match_tag(e, "power-switch"); if (r < 0) return r; r = udev_enumerate_add_match_is_initialized(e); if (r < 0) return r; r = udev_enumerate_scan_devices(e); if (r < 0) return r; first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; int k; d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item)); if (!d) return -ENOMEM; k = manager_process_button_device(m, d); if (k < 0) r = k; } return r; } static int manager_enumerate_seats(Manager *m) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0; assert(m); /* This loads data about seats stored on disk, but does not * actually create any seats. Removes data of seats that no * longer exist. */ d = opendir("/run/systemd/seats"); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open /run/systemd/seats: %m"); } FOREACH_DIRENT(de, d, return -errno) { Seat *s; int k; if (!dirent_is_file(de)) continue; s = hashmap_get(m->seats, de->d_name); if (!s) { unlinkat(dirfd(d), de->d_name, 0); continue; } k = seat_load(s); if (k < 0) r = k; } return r; } static int manager_enumerate_linger_users(Manager *m) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0; assert(m); d = opendir("/var/lib/systemd/linger"); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open /var/lib/systemd/linger/: %m"); } FOREACH_DIRENT(de, d, return -errno) { int k; if (!dirent_is_file(de)) continue; k = manager_add_user_by_name(m, de->d_name, NULL); if (k < 0) { log_notice_errno(k, "Couldn't add lingering user %s: %m", de->d_name); r = k; } } return r; } static int manager_enumerate_users(Manager *m) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r, k; assert(m); /* Add lingering users */ r = manager_enumerate_linger_users(m); /* Read in user data stored on disk */ d = opendir("/run/systemd/users"); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open /run/systemd/users: %m"); } FOREACH_DIRENT(de, d, return -errno) { User *u; if (!dirent_is_file(de)) continue; k = manager_add_user_by_name(m, de->d_name, &u); if (k < 0) { log_error_errno(k, "Failed to add user by file name %s: %m", de->d_name); r = k; continue; } user_add_to_gc_queue(u); k = user_load(u); if (k < 0) r = k; } return r; } static int manager_enumerate_sessions(Manager *m) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0; assert(m); /* Read in session data stored on disk */ d = opendir("/run/systemd/sessions"); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open /run/systemd/sessions: %m"); } FOREACH_DIRENT(de, d, return -errno) { struct Session *s; int k; if (!dirent_is_file(de)) continue; if (!session_id_valid(de->d_name)) { log_warning("Invalid session file name '%s', ignoring.", de->d_name); r = -EINVAL; continue; } k = manager_add_session(m, de->d_name, &s); if (k < 0) { log_error_errno(k, "Failed to add session by file name %s: %m", de->d_name); r = k; continue; } session_add_to_gc_queue(s); k = session_load(s); if (k < 0) r = k; } return r; } static int manager_enumerate_inhibitors(Manager *m) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0; assert(m); d = opendir("/run/systemd/inhibit"); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open /run/systemd/inhibit: %m"); } FOREACH_DIRENT(de, d, return -errno) { int k; Inhibitor *i; if (!dirent_is_file(de)) continue; k = manager_add_inhibitor(m, de->d_name, &i); if (k < 0) { log_notice_errno(k, "Couldn't add inhibitor %s: %m", de->d_name); r = k; continue; } k = inhibitor_load(i); if (k < 0) r = k; } return r; } static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; Manager *m = userdata; assert(m); d = udev_monitor_receive_device(m->udev_seat_monitor); if (!d) return -ENOMEM; manager_process_seat_device(m, d); return 0; } static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; Manager *m = userdata; assert(m); d = udev_monitor_receive_device(m->udev_device_monitor); if (!d) return -ENOMEM; manager_process_seat_device(m, d); return 0; } static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; Manager *m = userdata; const char *name; assert(m); d = udev_monitor_receive_device(m->udev_vcsa_monitor); if (!d) return -ENOMEM; name = udev_device_get_sysname(d); /* Whenever a VCSA device is removed try to reallocate our * VTs, to make sure our auto VTs never go away. */ if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove")) seat_preallocate_vts(m->seat0); return 0; } static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; Manager *m = userdata; assert(m); d = udev_monitor_receive_device(m->udev_button_monitor); if (!d) return -ENOMEM; manager_process_button_device(m, d); return 0; } static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; assert(m); assert(m->seat0); assert(m->console_active_fd == fd); seat_read_active_vt(m->seat0); return 0; } static int manager_reserve_vt(Manager *m) { _cleanup_free_ char *p = NULL; assert(m); if (m->reserve_vt <= 0) return 0; if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0) return log_oom(); m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (m->reserve_vt_fd < 0) { /* Don't complain on VT-less systems */ if (errno != ENOENT) log_warning_errno(errno, "Failed to pin reserved VT: %m"); return -errno; } return 0; } static int manager_connect_bus(Manager *m) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(m); assert(!m->bus); r = sd_bus_default_system(&m->bus); if (r < 0) return log_error_errno(r, "Failed to connect to system bus: %m"); r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m); if (r < 0) return log_error_errno(r, "Failed to add manager object vtable: %m"); r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m); if (r < 0) return log_error_errno(r, "Failed to add seat object vtable: %m"); r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m); if (r < 0) return log_error_errno(r, "Failed to add seat enumerator: %m"); r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m); if (r < 0) return log_error_errno(r, "Failed to add session object vtable: %m"); r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m); if (r < 0) return log_error_errno(r, "Failed to add session enumerator: %m"); r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m); if (r < 0) return log_error_errno(r, "Failed to add user object vtable: %m"); r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m); if (r < 0) return log_error_errno(r, "Failed to add user enumerator: %m"); r = sd_bus_add_match(m->bus, NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," "member='JobRemoved'," "path='/org/freedesktop/systemd1'", match_job_removed, m); if (r < 0) return log_error_errno(r, "Failed to add match for JobRemoved: %m"); r = sd_bus_add_match(m->bus, NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," "member='UnitRemoved'," "path='/org/freedesktop/systemd1'", match_unit_removed, m); if (r < 0) return log_error_errno(r, "Failed to add match for UnitRemoved: %m"); r = sd_bus_add_match(m->bus, NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.DBus.Properties'," "member='PropertiesChanged'", match_properties_changed, m); if (r < 0) return log_error_errno(r, "Failed to add match for PropertiesChanged: %m"); r = sd_bus_add_match(m->bus, NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," "member='Reloading'," "path='/org/freedesktop/systemd1'", match_reloading, m); if (r < 0) return log_error_errno(r, "Failed to add match for Reloading: %m"); r = sd_bus_call_method( m->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Subscribe", &error, NULL, NULL); if (r < 0) { log_error("Failed to enable subscription: %s", bus_error_message(&error, r)); return r; } r = sd_bus_request_name(m->bus, "org.freedesktop.login1", 0); if (r < 0) return log_error_errno(r, "Failed to register name: %m"); r = sd_bus_attach_event(m->bus, m->event, 0); if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop: %m"); return 0; } static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo *si, void *data) { Manager *m = data; Session *active, *iter; /* * We got a VT-switch signal and we have to acknowledge it immediately. * Preferably, we'd just use m->seat0->active->vtfd, but unfortunately, * old user-space might run multiple sessions on a single VT, *sigh*. * Therefore, we have to iterate all sessions and find one with a vtfd * on the requested VT. * As only VTs with active controllers have VT_PROCESS set, our current * notion of the active VT might be wrong (for instance if the switch * happens while we setup VT_PROCESS). Therefore, read the current VT * first and then use s->active->vtnr as reference. Note that this is * not racy, as no further VT-switch can happen as long as we're in * synchronous VT_PROCESS mode. */ assert(m->seat0); seat_read_active_vt(m->seat0); active = m->seat0->active; if (!active || active->vtnr < 1) { log_warning("Received VT_PROCESS signal without a registered session on that VT."); return 0; } if (active->vtfd >= 0) { session_leave_vt(active); } else { LIST_FOREACH(sessions_by_seat, iter, m->seat0->sessions) { if (iter->vtnr == active->vtnr && iter->vtfd >= 0) { session_leave_vt(iter); break; } } } return 0; } static int manager_connect_console(Manager *m) { int r; assert(m); assert(m->console_active_fd < 0); /* On certain architectures (S390 and Xen, and containers), /dev/tty0 does not exist, so don't fail if we can't open it. */ if (access("/dev/tty0", F_OK) < 0) return 0; m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC); if (m->console_active_fd < 0) { /* On some systems the device node /dev/tty0 may exist * even though /sys/class/tty/tty0 does not. */ if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m"); } r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m); if (r < 0) { log_error("Failed to watch foreground console"); return r; } /* * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used * as VT-acquire signal. We ignore any acquire-events (yes, we still * have to provide a valid signal-number for it!) and acknowledge all * release events immediately. */ if (SIGRTMIN + 1 > SIGRTMAX) { log_error("Not enough real-time signals available: %u-%u", SIGRTMIN, SIGRTMAX); return -EINVAL; } assert_se(ignore_signals(SIGRTMIN + 1, -1) >= 0); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN, -1) >= 0); r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m); if (r < 0) return r; return 0; } static int manager_connect_udev(Manager *m) { int r; assert(m); assert(!m->udev_seat_monitor); assert(!m->udev_device_monitor); assert(!m->udev_vcsa_monitor); assert(!m->udev_button_monitor); m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev"); if (!m->udev_seat_monitor) return -ENOMEM; r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat"); if (r < 0) return r; r = udev_monitor_enable_receiving(m->udev_seat_monitor); if (r < 0) return r; r = sd_event_add_io(m->event, &m->udev_seat_event_source, udev_monitor_get_fd(m->udev_seat_monitor), EPOLLIN, manager_dispatch_seat_udev, m); if (r < 0) return r; m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev"); if (!m->udev_device_monitor) return -ENOMEM; r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL); if (r < 0) return r; r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL); if (r < 0) return r; r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL); if (r < 0) return r; r = udev_monitor_enable_receiving(m->udev_device_monitor); if (r < 0) return r; r = sd_event_add_io(m->event, &m->udev_device_event_source, udev_monitor_get_fd(m->udev_device_monitor), EPOLLIN, manager_dispatch_device_udev, m); if (r < 0) return r; /* Don't watch keys if nobody cares */ if (m->handle_power_key != HANDLE_IGNORE || m->handle_suspend_key != HANDLE_IGNORE || m->handle_hibernate_key != HANDLE_IGNORE || m->handle_lid_switch != HANDLE_IGNORE || m->handle_lid_switch_docked != HANDLE_IGNORE) { m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev"); if (!m->udev_button_monitor) return -ENOMEM; r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch"); if (r < 0) return r; r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL); if (r < 0) return r; r = udev_monitor_enable_receiving(m->udev_button_monitor); if (r < 0) return r; r = sd_event_add_io(m->event, &m->udev_button_event_source, udev_monitor_get_fd(m->udev_button_monitor), EPOLLIN, manager_dispatch_button_udev, m); if (r < 0) return r; } /* Don't bother watching VCSA devices, if nobody cares */ if (m->n_autovts > 0 && m->console_active_fd >= 0) { m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev"); if (!m->udev_vcsa_monitor) return -ENOMEM; r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL); if (r < 0) return r; r = udev_monitor_enable_receiving(m->udev_vcsa_monitor); if (r < 0) return r; r = sd_event_add_io(m->event, &m->udev_vcsa_event_source, udev_monitor_get_fd(m->udev_vcsa_monitor), EPOLLIN, manager_dispatch_vcsa_udev, m); if (r < 0) return r; } return 0; } static void manager_gc(Manager *m, bool drop_not_started) { Seat *seat; Session *session; User *user; assert(m); while ((seat = m->seat_gc_queue)) { LIST_REMOVE(gc_queue, m->seat_gc_queue, seat); seat->in_gc_queue = false; if (!seat_check_gc(seat, drop_not_started)) { seat_stop(seat, false); seat_free(seat); } } while ((session = m->session_gc_queue)) { LIST_REMOVE(gc_queue, m->session_gc_queue, session); session->in_gc_queue = false; /* First, if we are not closing yet, initiate stopping */ if (!session_check_gc(session, drop_not_started) && session_get_state(session) != SESSION_CLOSING) session_stop(session, false); /* Normally, this should make the session referenced * again, if it doesn't then let's get rid of it * immediately */ if (!session_check_gc(session, drop_not_started)) { session_finalize(session); session_free(session); } } while ((user = m->user_gc_queue)) { LIST_REMOVE(gc_queue, m->user_gc_queue, user); user->in_gc_queue = false; /* First step: queue stop jobs */ if (!user_check_gc(user, drop_not_started)) user_stop(user, false); /* Second step: finalize user */ if (!user_check_gc(user, drop_not_started)) { user_finalize(user); user_free(user); } } } static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) { Manager *m = userdata; struct dual_timestamp since; usec_t n, elapse; int r; assert(m); if (m->idle_action == HANDLE_IGNORE || m->idle_action_usec <= 0) return 0; n = now(CLOCK_MONOTONIC); r = manager_get_idle_hint(m, &since); if (r <= 0) /* Not idle. Let's check if after a timeout it might be idle then. */ elapse = n + m->idle_action_usec; else { /* Idle! Let's see if it's time to do something, or if * we shall sleep for longer. */ if (n >= since.monotonic + m->idle_action_usec && (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) { log_info("System idle. Taking action."); manager_handle_action(m, 0, m->idle_action, false, false); m->idle_action_not_before_usec = n; } elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec; } if (!m->idle_action_event_source) { r = sd_event_add_time( m->event, &m->idle_action_event_source, CLOCK_MONOTONIC, elapse, USEC_PER_SEC*30, manager_dispatch_idle_action, m); if (r < 0) return log_error_errno(r, "Failed to add idle event source: %m"); r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10); if (r < 0) return log_error_errno(r, "Failed to set idle event source priority: %m"); } else { r = sd_event_source_set_time(m->idle_action_event_source, elapse); if (r < 0) return log_error_errno(r, "Failed to set idle event timer: %m"); r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT); if (r < 0) return log_error_errno(r, "Failed to enable idle event timer: %m"); } return 0; } static int manager_startup(Manager *m) { int r; Seat *seat; Session *session; User *user; Button *button; Inhibitor *inhibitor; Iterator i; assert(m); /* Connect to console */ r = manager_connect_console(m); if (r < 0) return r; /* Connect to udev */ r = manager_connect_udev(m); if (r < 0) return log_error_errno(r, "Failed to create udev watchers: %m"); /* Connect to the bus */ r = manager_connect_bus(m); if (r < 0) return r; /* Instantiate magic seat 0 */ r = manager_add_seat(m, "seat0", &m->seat0); if (r < 0) return log_error_errno(r, "Failed to add seat0: %m"); r = manager_set_lid_switch_ignore(m, 0 + m->holdoff_timeout_usec); if (r < 0) log_warning_errno(r, "Failed to set up lid switch ignore event source: %m"); /* Deserialize state */ r = manager_enumerate_devices(m); if (r < 0) log_warning_errno(r, "Device enumeration failed: %m"); r = manager_enumerate_seats(m); if (r < 0) log_warning_errno(r, "Seat enumeration failed: %m"); r = manager_enumerate_users(m); if (r < 0) log_warning_errno(r, "User enumeration failed: %m"); r = manager_enumerate_sessions(m); if (r < 0) log_warning_errno(r, "Session enumeration failed: %m"); r = manager_enumerate_inhibitors(m); if (r < 0) log_warning_errno(r, "Inhibitor enumeration failed: %m"); r = manager_enumerate_buttons(m); if (r < 0) log_warning_errno(r, "Button enumeration failed: %m"); /* Remove stale objects before we start them */ manager_gc(m, false); /* Reserve the special reserved VT */ manager_reserve_vt(m); /* And start everything */ HASHMAP_FOREACH(seat, m->seats, i) seat_start(seat); HASHMAP_FOREACH(user, m->users, i) user_start(user); HASHMAP_FOREACH(session, m->sessions, i) session_start(session); HASHMAP_FOREACH(inhibitor, m->inhibitors, i) inhibitor_start(inhibitor); HASHMAP_FOREACH(button, m->buttons, i) button_check_switches(button); manager_dispatch_idle_action(NULL, 0, m); return 0; } static int manager_run(Manager *m) { int r; assert(m); for (;;) { r = sd_event_get_state(m->event); if (r < 0) return r; if (r == SD_EVENT_FINISHED) return 0; manager_gc(m, true); r = manager_dispatch_delayed(m, false); if (r < 0) return r; if (r > 0) continue; r = sd_event_run(m->event, (uint64_t) -1); if (r < 0) return r; } } static int manager_parse_config_file(Manager *m) { assert(m); return config_parse_many(PKGSYSCONFDIR "/logind.conf", CONF_PATHS_NULSTR("systemd/logind.conf.d"), "Login\0", config_item_perf_lookup, logind_gperf_lookup, false, m); } int main(int argc, char *argv[]) { Manager *m = NULL; int r; log_set_target(LOG_TARGET_AUTO); log_set_facility(LOG_AUTH); log_parse_environment(); log_open(); umask(0022); if (argc != 1) { log_error("This program takes no arguments."); r = -EINVAL; goto finish; } r = mac_selinux_init("/run"); if (r < 0) { log_error_errno(r, "Could not initialize labelling: %m"); goto finish; } /* Always create the directories people can create inotify * watches in. Note that some applications might check for the * existence of /run/systemd/seats/ to determine whether * logind is available, so please always make sure this check * stays in. */ mkdir_label("/run/systemd/seats", 0755); mkdir_label("/run/systemd/users", 0755); mkdir_label("/run/systemd/sessions", 0755); m = manager_new(); if (!m) { r = log_oom(); goto finish; } manager_parse_config_file(m); r = manager_startup(m); if (r < 0) { log_error_errno(r, "Failed to fully start up daemon: %m"); goto finish; } log_debug("systemd-logind running as pid "PID_FMT, getpid()); sd_notify(false, "READY=1\n" "STATUS=Processing requests..."); r = manager_run(m); log_debug("systemd-logind stopped as pid "PID_FMT, getpid()); finish: sd_notify(false, "STOPPING=1\n" "STATUS=Shutting down..."); manager_free(m); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/login/logind.conf000066400000000000000000000017321265713322000171060ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # Entries in this file show the compile time defaults. # You can change settings by editing this file. # Defaults can be restored by simply deleting this file. # # See logind.conf(5) for details. [Login] #NAutoVTs=6 #ReserveVT=6 #KillUserProcesses=no #KillOnlyUsers= #KillExcludeUsers=root #InhibitDelayMaxSec=5 #HandlePowerKey=poweroff #HandleSuspendKey=suspend #HandleHibernateKey=hibernate #HandleLidSwitch=suspend #HandleLidSwitchDocked=ignore #PowerKeyIgnoreInhibited=no #SuspendKeyIgnoreInhibited=no #HibernateKeyIgnoreInhibited=no #LidSwitchIgnoreInhibited=yes #HoldoffTimeoutSec=30s #IdleAction=ignore #IdleActionSec=30min #RuntimeDirectorySize=10% #RemoveIPC=yes #UserTasksMax=12288 systemd-229/src/login/logind.h000066400000000000000000000165561265713322000164220ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "libudev.h" #include "sd-bus.h" #include "sd-event.h" #include "hashmap.h" #include "list.h" #include "set.h" typedef struct Manager Manager; #include "logind-action.h" #include "logind-button.h" #include "logind-device.h" #include "logind-inhibit.h" struct Manager { sd_event *event; sd_bus *bus; Hashmap *devices; Hashmap *seats; Hashmap *sessions; Hashmap *users; Hashmap *inhibitors; Hashmap *buttons; LIST_HEAD(Seat, seat_gc_queue); LIST_HEAD(Session, session_gc_queue); LIST_HEAD(User, user_gc_queue); struct udev *udev; struct udev_monitor *udev_seat_monitor, *udev_device_monitor, *udev_vcsa_monitor, *udev_button_monitor; sd_event_source *console_active_event_source; sd_event_source *udev_seat_event_source; sd_event_source *udev_device_event_source; sd_event_source *udev_vcsa_event_source; sd_event_source *udev_button_event_source; int console_active_fd; unsigned n_autovts; unsigned reserve_vt; int reserve_vt_fd; Seat *seat0; char **kill_only_users, **kill_exclude_users; bool kill_user_processes; unsigned long session_counter; unsigned long inhibit_counter; Hashmap *session_units; Hashmap *user_units; usec_t inhibit_delay_max; /* If an action is currently being executed or is delayed, * this is != 0 and encodes what is being done */ InhibitWhat action_what; /* If a shutdown/suspend was delayed due to a inhibitor this contains the unit name we are supposed to start after the delay is over */ const char *action_unit; /* If a shutdown/suspend is currently executed, then this is * the job of it */ char *action_job; sd_event_source *inhibit_timeout_source; char *scheduled_shutdown_type; usec_t scheduled_shutdown_timeout; sd_event_source *scheduled_shutdown_timeout_source; uid_t scheduled_shutdown_uid; char *scheduled_shutdown_tty; sd_event_source *nologin_timeout_source; bool unlink_nologin; char *wall_message; unsigned enable_wall_messages; sd_event_source *wall_message_timeout_source; bool shutdown_dry_run; sd_event_source *idle_action_event_source; usec_t idle_action_usec; usec_t idle_action_not_before_usec; HandleAction idle_action; HandleAction handle_power_key; HandleAction handle_suspend_key; HandleAction handle_hibernate_key; HandleAction handle_lid_switch; HandleAction handle_lid_switch_docked; bool power_key_ignore_inhibited; bool suspend_key_ignore_inhibited; bool hibernate_key_ignore_inhibited; bool lid_switch_ignore_inhibited; bool remove_ipc; Hashmap *polkit_registry; usec_t holdoff_timeout_usec; sd_event_source *lid_switch_ignore_event_source; size_t runtime_dir_size; uint64_t user_tasks_max; }; int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device); int manager_add_button(Manager *m, const char *name, Button **_button); int manager_add_seat(Manager *m, const char *id, Seat **_seat); int manager_add_session(Manager *m, const char *id, Session **_session); int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user); int manager_add_user_by_name(Manager *m, const char *name, User **_user); int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user); int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor); int manager_process_seat_device(Manager *m, struct udev_device *d); int manager_process_button_device(Manager *m, struct udev_device *d); int manager_spawn_autovt(Manager *m, unsigned int vtnr); bool manager_shall_kill(Manager *m, const char *user); int manager_get_idle_hint(Manager *m, dual_timestamp *t); int manager_get_user_by_pid(Manager *m, pid_t pid, User **user); int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session); bool manager_is_docked_or_external_displays(Manager *m); extern const sd_bus_vtable manager_vtable[]; int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error); int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error); int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error); int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error); int match_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name, InhibitWhat w, sd_bus_error *error); int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_; int manager_start_slice(Manager *manager, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job); int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job); int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error); int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error); int manager_unit_is_active(Manager *manager, const char *unit); int manager_job_is_active(Manager *manager, const char *path); /* gperf lookup function */ const struct ConfigPerfItem* logind_gperf_lookup(const char *key, unsigned length); int manager_set_lid_switch_ignore(Manager *m, usec_t until); int config_parse_tmpfs_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret); int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret); int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret); int manager_setup_wall_message_timer(Manager *m); bool logind_wall_tty_filter(const char *tty, void *userdata); int manager_dispatch_delayed(Manager *manager, bool timeout); systemd-229/src/login/org.freedesktop.login1.conf000066400000000000000000000300251265713322000221200ustar00rootroot00000000000000 systemd-229/src/login/org.freedesktop.login1.policy.in000066400000000000000000000425141265713322000231050ustar00rootroot00000000000000 The systemd Project http://www.freedesktop.org/wiki/Software/systemd <_description>Allow applications to inhibit system shutdown <_message>Authentication is required for an application to inhibit system shutdown. no yes yes org.freedesktop.login1.inhibit-delay-shutdown org.freedesktop.login1.inhibit-block-sleep org.freedesktop.login1.inhibit-delay-sleep org.freedesktop.login1.inhibit-block-idle <_description>Allow applications to delay system shutdown <_message>Authentication is required for an application to delay system shutdown. yes yes yes org.freedesktop.login1.inhibit-delay-sleep <_description>Allow applications to inhibit system sleep <_message>Authentication is required for an application to inhibit system sleep. no yes yes org.freedesktop.login1.inhibit-delay-sleep org.freedesktop.login1.inhibit-block-idle <_description>Allow applications to delay system sleep <_message>Authentication is required for an application to delay system sleep. yes yes yes <_description>Allow applications to inhibit automatic system suspend <_message>Authentication is required for an application to inhibit automatic system suspend. yes yes yes <_description>Allow applications to inhibit system handling of the power key <_message>Authentication is required for an application to inhibit system handling of the power key. no yes yes org.freedesktop.login1.inhibit-handle-suspend-key org.freedesktop.login1.inhibit-handle-hibernate-key org.freedesktop.login1.inhibit-handle-lid-switch <_description>Allow applications to inhibit system handling of the suspend key <_message>Authentication is required for an application to inhibit system handling of the suspend key. no yes yes org.freedesktop.login1.inhibit-handle-hibernate-key org.freedesktop.login1.inhibit-handle-lid-switch <_description>Allow applications to inhibit system handling of the hibernate key <_message>Authentication is required for an application to inhibit system handling of the hibernate key. no yes yes <_description>Allow applications to inhibit system handling of the lid switch <_message>Authentication is required for an application to inhibit system handling of the lid switch. no yes yes <_description>Allow non-logged-in users to run programs <_message>Authentication is required to run programs as a non-logged-in user. auth_admin_keep auth_admin_keep auth_admin_keep <_description>Allow attaching devices to seats <_message>Authentication is required for attaching a device to a seat. auth_admin_keep auth_admin_keep auth_admin_keep org.freedesktop.login1.flush-devices <_description>Flush device to seat attachments <_message>Authentication is required for resetting how devices are attached to seats. auth_admin_keep auth_admin_keep auth_admin_keep <_description>Power off the system <_message>Authentication is required for powering off the system. auth_admin_keep auth_admin_keep yes org.freedesktop.login1.set-wall-message <_description>Power off the system while other users are logged in <_message>Authentication is required for powering off the system while other users are logged in. auth_admin_keep auth_admin_keep yes org.freedesktop.login1.power-off <_description>Power off the system while an application asked to inhibit it <_message>Authentication is required for powering off the system while an application asked to inhibit it. auth_admin_keep auth_admin_keep auth_admin_keep org.freedesktop.login1.power-off <_description>Reboot the system <_message>Authentication is required for rebooting the system. auth_admin_keep auth_admin_keep yes org.freedesktop.login1.set-wall-message <_description>Reboot the system while other users are logged in <_message>Authentication is required for rebooting the system while other users are logged in. auth_admin_keep auth_admin_keep yes org.freedesktop.login1.reboot <_description>Reboot the system while an application asked to inhibit it <_message>Authentication is required for rebooting the system while an application asked to inhibit it. auth_admin_keep auth_admin_keep auth_admin_keep org.freedesktop.login1.reboot <_description>Suspend the system <_message>Authentication is required for suspending the system. auth_admin_keep auth_admin_keep yes <_description>Suspend the system while other users are logged in <_message>Authentication is required for suspending the system while other users are logged in. auth_admin_keep auth_admin_keep yes org.freedesktop.login1.suspend <_description>Suspend the system while an application asked to inhibit it <_message>Authentication is required for suspending the system while an application asked to inhibit it. auth_admin_keep auth_admin_keep auth_admin_keep org.freedesktop.login1.suspend <_description>Hibernate the system <_message>Authentication is required for hibernating the system. auth_admin_keep auth_admin_keep yes <_description>Hibernate the system while other users are logged in <_message>Authentication is required for hibernating the system while other users are logged in. auth_admin_keep auth_admin_keep yes org.freedesktop.login1.hibernate <_description>Hibernate the system while an application asked to inhibit it <_message>Authentication is required for hibernating the system while an application asked to inhibit it. auth_admin_keep auth_admin_keep auth_admin_keep org.freedesktop.login1.hibernate <_description>Manage active sessions, users and seats <_message>Authentication is required for managing active sessions, users and seats. auth_admin_keep auth_admin_keep auth_admin_keep <_description>Lock or unlock active sessions <_message>Authentication is required to lock or unlock active sessions. auth_admin_keep auth_admin_keep auth_admin_keep <_description>Allow indication to the firmware to boot to setup interface <_message>Authentication is required to indicate to the firmware to boot to setup interface. auth_admin_keep auth_admin_keep auth_admin_keep <_description>Set a wall message <_message>Authentication is required to set a wall message auth_admin_keep auth_admin_keep auth_admin_keep systemd-229/src/login/org.freedesktop.login1.service000066400000000000000000000006351265713322000226370ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] Name=org.freedesktop.login1 Exec=/bin/false User=root SystemdService=dbus-org.freedesktop.login1.service systemd-229/src/login/pam_systemd.c000066400000000000000000000467001265713322000174600ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "audit-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" #include "def.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "hostname-util.h" #include "login-util.h" #include "macro.h" #include "parse-util.h" #include "socket-util.h" #include "strv.h" #include "terminal-util.h" #include "util.h" static int parse_argv( pam_handle_t *handle, int argc, const char **argv, const char **class, const char **type, bool *debug) { unsigned i; assert(argc >= 0); assert(argc == 0 || argv); for (i = 0; i < (unsigned) argc; i++) { if (startswith(argv[i], "class=")) { if (class) *class = argv[i] + 6; } else if (startswith(argv[i], "type=")) { if (type) *type = argv[i] + 5; } else if (streq(argv[i], "debug")) { if (debug) *debug = true; } else if (startswith(argv[i], "debug=")) { int k; k = parse_boolean(argv[i] + 6); if (k < 0) pam_syslog(handle, LOG_WARNING, "Failed to parse debug= argument, ignoring."); else if (debug) *debug = k; } else pam_syslog(handle, LOG_WARNING, "Unknown parameter '%s', ignoring", argv[i]); } return 0; } static int get_user_data( pam_handle_t *handle, const char **ret_username, struct passwd **ret_pw) { const char *username = NULL; struct passwd *pw = NULL; int r; assert(handle); assert(ret_username); assert(ret_pw); r = pam_get_user(handle, &username, NULL); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to get user name."); return r; } if (isempty(username)) { pam_syslog(handle, LOG_ERR, "User name not valid."); return PAM_AUTH_ERR; } pw = pam_modutil_getpwnam(handle, username); if (!pw) { pam_syslog(handle, LOG_ERR, "Failed to get user data."); return PAM_USER_UNKNOWN; } *ret_pw = pw; *ret_username = username; return PAM_SUCCESS; } static int get_seat_from_display(const char *display, const char **seat, uint32_t *vtnr) { union sockaddr_union sa = { .un.sun_family = AF_UNIX, }; _cleanup_free_ char *p = NULL, *tty = NULL; _cleanup_close_ int fd = -1; struct ucred ucred; int v, r; assert(display); assert(vtnr); /* We deduce the X11 socket from the display name, then use * SO_PEERCRED to determine the X11 server process, ask for * the controlling tty of that and if it's a VC then we know * the seat and the virtual terminal. Sounds ugly, is only * semi-ugly. */ r = socket_from_display(display, &p); if (r < 0) return r; strncpy(sa.un.sun_path, p, sizeof(sa.un.sun_path)-1); fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); if (fd < 0) return -errno; if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) return -errno; r = getpeercred(fd, &ucred); if (r < 0) return r; r = get_ctty(ucred.pid, NULL, &tty); if (r < 0) return r; v = vtnr_from_tty(tty); if (v < 0) return v; else if (v == 0) return -ENOENT; if (seat) *seat = "seat0"; *vtnr = (uint32_t) v; return 0; } static int export_legacy_dbus_address( pam_handle_t *handle, uid_t uid, const char *runtime) { _cleanup_free_ char *s = NULL; int r = PAM_BUF_ERR; if (is_kdbus_available()) { if (asprintf(&s, KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT, uid, runtime) < 0) goto error; } else { /* FIXME: We *really* should move the access() check into the * daemons that spawn dbus-daemon, instead of forcing * DBUS_SESSION_BUS_ADDRESS= here. */ s = strjoin(runtime, "/bus", NULL); if (!s) goto error; if (access(s, F_OK) < 0) return PAM_SUCCESS; s = mfree(s); if (asprintf(&s, UNIX_USER_BUS_ADDRESS_FMT, runtime) < 0) goto error; } r = pam_misc_setenv(handle, "DBUS_SESSION_BUS_ADDRESS", s, 0); if (r != PAM_SUCCESS) goto error; return PAM_SUCCESS; error: pam_syslog(handle, LOG_ERR, "Failed to set bus variable."); return r; } _public_ PAM_EXTERN int pam_sm_open_session( pam_handle_t *handle, int flags, int argc, const char **argv) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *username, *id, *object_path, *runtime_path, *service = NULL, *tty = NULL, *display = NULL, *remote_user = NULL, *remote_host = NULL, *seat = NULL, *type = NULL, *class = NULL, *class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int session_fd = -1, existing, r; bool debug = false, remote; struct passwd *pw; uint32_t vtnr = 0; uid_t original_uid; assert(handle); /* Make this a NOP on non-logind systems */ if (!logind_running()) return PAM_SUCCESS; if (parse_argv(handle, argc, argv, &class_pam, &type_pam, &debug) < 0) return PAM_SESSION_ERR; if (debug) pam_syslog(handle, LOG_DEBUG, "pam-systemd initializing"); r = get_user_data(handle, &username, &pw); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to get user data."); return r; } /* Make sure we don't enter a loop by talking to * systemd-logind when it is actually waiting for the * background to finish start-up. If the service is * "systemd-user" we simply set XDG_RUNTIME_DIR and * leave. */ pam_get_item(handle, PAM_SERVICE, (const void**) &service); if (streq_ptr(service, "systemd-user")) { _cleanup_free_ char *rt = NULL; if (asprintf(&rt, "/run/user/"UID_FMT, pw->pw_uid) < 0) return PAM_BUF_ERR; r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); return r; } r = export_legacy_dbus_address(handle, pw->pw_uid, rt); if (r != PAM_SUCCESS) return r; return PAM_SUCCESS; } /* Otherwise, we ask logind to create a session for us */ pam_get_item(handle, PAM_XDISPLAY, (const void**) &display); pam_get_item(handle, PAM_TTY, (const void**) &tty); pam_get_item(handle, PAM_RUSER, (const void**) &remote_user); pam_get_item(handle, PAM_RHOST, (const void**) &remote_host); seat = pam_getenv(handle, "XDG_SEAT"); if (isempty(seat)) seat = getenv("XDG_SEAT"); cvtnr = pam_getenv(handle, "XDG_VTNR"); if (isempty(cvtnr)) cvtnr = getenv("XDG_VTNR"); type = pam_getenv(handle, "XDG_SESSION_TYPE"); if (isempty(type)) type = getenv("XDG_SESSION_TYPE"); if (isempty(type)) type = type_pam; class = pam_getenv(handle, "XDG_SESSION_CLASS"); if (isempty(class)) class = getenv("XDG_SESSION_CLASS"); if (isempty(class)) class = class_pam; desktop = pam_getenv(handle, "XDG_SESSION_DESKTOP"); if (isempty(desktop)) desktop = getenv("XDG_SESSION_DESKTOP"); tty = strempty(tty); if (strchr(tty, ':')) { /* A tty with a colon is usually an X11 display, * placed there to show up in utmp. We rearrange * things and don't pretend that an X display was a * tty. */ if (isempty(display)) display = tty; tty = NULL; } else if (streq(tty, "cron")) { /* cron has been setting PAM_TTY to "cron" for a very * long time and it probably shouldn't stop doing that * for compatibility reasons. */ type = "unspecified"; class = "background"; tty = NULL; } else if (streq(tty, "ssh")) { /* ssh has been setting PAM_TTY to "ssh" for a very * long time and probably shouldn't stop doing that * for compatibility reasons. */ type ="tty"; class = "user"; tty = NULL; } /* If this fails vtnr will be 0, that's intended */ if (!isempty(cvtnr)) (void) safe_atou32(cvtnr, &vtnr); if (!isempty(display) && !vtnr) { if (isempty(seat)) get_seat_from_display(display, &seat, &vtnr); else if (streq(seat, "seat0")) get_seat_from_display(display, NULL, &vtnr); } if (seat && !streq(seat, "seat0") && vtnr != 0) { pam_syslog(handle, LOG_DEBUG, "Ignoring vtnr %"PRIu32" for %s which is not seat0", vtnr, seat); vtnr = 0; } if (isempty(type)) type = !isempty(display) ? "x11" : !isempty(tty) ? "tty" : "unspecified"; if (isempty(class)) class = streq(type, "unspecified") ? "background" : "user"; remote = !isempty(remote_host) && !is_localhost(remote_host); /* Talk to logind over the message bus */ r = sd_bus_open_system(&bus); if (r < 0) { pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror(-r)); return PAM_SESSION_ERR; } if (debug) pam_syslog(handle, LOG_DEBUG, "Asking logind to create session: " "uid="UID_FMT" pid="PID_FMT" service=%s type=%s class=%s desktop=%s seat=%s vtnr=%"PRIu32" tty=%s display=%s remote=%s remote_user=%s remote_host=%s", pw->pw_uid, getpid(), strempty(service), type, class, strempty(desktop), strempty(seat), vtnr, strempty(tty), strempty(display), yes_no(remote), strempty(remote_user), strempty(remote_host)); r = sd_bus_call_method(bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "CreateSession", &error, &reply, "uusssssussbssa(sv)", (uint32_t) pw->pw_uid, (uint32_t) getpid(), service, type, class, desktop, seat, vtnr, tty, display, remote, remote_user, remote_host, 0); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_SESSION_BUSY)) { pam_syslog(handle, LOG_DEBUG, "Cannot create session: %s", bus_error_message(&error, r)); return PAM_SUCCESS; } else { pam_syslog(handle, LOG_ERR, "Failed to create session: %s", bus_error_message(&error, r)); return PAM_SYSTEM_ERR; } } r = sd_bus_message_read(reply, "soshusub", &id, &object_path, &runtime_path, &session_fd, &original_uid, &seat, &vtnr, &existing); if (r < 0) { pam_syslog(handle, LOG_ERR, "Failed to parse message: %s", strerror(-r)); return PAM_SESSION_ERR; } if (debug) pam_syslog(handle, LOG_DEBUG, "Reply from logind: " "id=%s object_path=%s runtime_path=%s session_fd=%d seat=%s vtnr=%u original_uid=%u", id, object_path, runtime_path, session_fd, seat, vtnr, original_uid); r = pam_misc_setenv(handle, "XDG_SESSION_ID", id, 0); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to set session id."); return r; } if (original_uid == pw->pw_uid) { /* Don't set $XDG_RUNTIME_DIR if the user we now * authenticated for does not match the original user * of the session. We do this in order not to result * in privileged apps clobbering the runtime directory * unnecessarily. */ r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", runtime_path, 0); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); return r; } r = export_legacy_dbus_address(handle, pw->pw_uid, runtime_path); if (r != PAM_SUCCESS) return r; } if (!isempty(seat)) { r = pam_misc_setenv(handle, "XDG_SEAT", seat, 0); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to set seat."); return r; } } if (vtnr > 0) { char buf[DECIMAL_STR_MAX(vtnr)]; sprintf(buf, "%u", vtnr); r = pam_misc_setenv(handle, "XDG_VTNR", buf, 0); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to set virtual terminal number."); return r; } } r = pam_set_data(handle, "systemd.existing", INT_TO_PTR(!!existing), NULL); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to install existing flag."); return r; } if (session_fd >= 0) { session_fd = fcntl(session_fd, F_DUPFD_CLOEXEC, 3); if (session_fd < 0) { pam_syslog(handle, LOG_ERR, "Failed to dup session fd: %m"); return PAM_SESSION_ERR; } r = pam_set_data(handle, "systemd.session-fd", FD_TO_PTR(session_fd), NULL); if (r != PAM_SUCCESS) { pam_syslog(handle, LOG_ERR, "Failed to install session fd."); safe_close(session_fd); return r; } } return PAM_SUCCESS; } _public_ PAM_EXTERN int pam_sm_close_session( pam_handle_t *handle, int flags, int argc, const char **argv) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; const void *existing = NULL; const char *id; int r; assert(handle); /* Only release session if it wasn't pre-existing when we * tried to create it */ pam_get_data(handle, "systemd.existing", &existing); id = pam_getenv(handle, "XDG_SESSION_ID"); if (id && !existing) { /* Before we go and close the FIFO we need to tell * logind that this is a clean session shutdown, so * that it doesn't just go and slaughter us * immediately after closing the fd */ r = sd_bus_open_system(&bus); if (r < 0) { pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror(-r)); return PAM_SESSION_ERR; } r = sd_bus_call_method(bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "ReleaseSession", &error, NULL, "s", id); if (r < 0) { pam_syslog(handle, LOG_ERR, "Failed to release session: %s", bus_error_message(&error, r)); return PAM_SESSION_ERR; } } /* Note that we are knowingly leaking the FIFO fd here. This * way, logind can watch us die. If we closed it here it would * not have any clue when that is completed. Given that one * cannot really have multiple PAM sessions open from the same * process this means we will leak one FD at max. */ return PAM_SUCCESS; } systemd-229/src/login/pam_systemd.sym000066400000000000000000000005721265713322000200430ustar00rootroot00000000000000/*** This file is part of systemd. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. ***/ { global: pam_sm_close_session; pam_sm_open_session; local: *; }; systemd-229/src/login/sysfs-show.c000066400000000000000000000146321265713322000172570ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "libudev.h" #include "alloc-util.h" #include "locale-util.h" #include "path-util.h" #include "string-util.h" #include "sysfs-show.h" #include "terminal-util.h" #include "udev-util.h" #include "util.h" static int show_sysfs_one( struct udev *udev, const char *seat, struct udev_list_entry **item, const char *sub, const char *prefix, unsigned n_columns) { assert(udev); assert(seat); assert(item); assert(prefix); while (*item) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; struct udev_list_entry *next, *lookahead; const char *sn, *name, *sysfs, *subsystem, *sysname; _cleanup_free_ char *k = NULL, *l = NULL; bool is_master; sysfs = udev_list_entry_get_name(*item); if (!path_startswith(sysfs, sub)) return 0; d = udev_device_new_from_syspath(udev, sysfs); if (!d) { *item = udev_list_entry_get_next(*item); continue; } sn = udev_device_get_property_value(d, "ID_SEAT"); if (isempty(sn)) sn = "seat0"; /* Explicitly also check for tag 'seat' here */ if (!streq(seat, sn) || !udev_device_has_tag(d, "seat")) { *item = udev_list_entry_get_next(*item); continue; } is_master = udev_device_has_tag(d, "master-of-seat"); name = udev_device_get_sysattr_value(d, "name"); if (!name) name = udev_device_get_sysattr_value(d, "id"); subsystem = udev_device_get_subsystem(d); sysname = udev_device_get_sysname(d); /* Look if there's more coming after this */ lookahead = next = udev_list_entry_get_next(*item); while (lookahead) { const char *lookahead_sysfs; lookahead_sysfs = udev_list_entry_get_name(lookahead); if (path_startswith(lookahead_sysfs, sub) && !path_startswith(lookahead_sysfs, sysfs)) { _cleanup_udev_device_unref_ struct udev_device *lookahead_d = NULL; lookahead_d = udev_device_new_from_syspath(udev, lookahead_sysfs); if (lookahead_d) { const char *lookahead_sn; lookahead_sn = udev_device_get_property_value(d, "ID_SEAT"); if (isempty(lookahead_sn)) lookahead_sn = "seat0"; if (streq(seat, lookahead_sn) && udev_device_has_tag(lookahead_d, "seat")) break; } } lookahead = udev_list_entry_get_next(lookahead); } k = ellipsize(sysfs, n_columns, 20); if (!k) return -ENOMEM; printf("%s%s%s\n", prefix, draw_special_char(lookahead ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT), k); if (asprintf(&l, "%s%s:%s%s%s%s", is_master ? "[MASTER] " : "", subsystem, sysname, name ? " \"" : "", strempty(name), name ? "\"" : "") < 0) return -ENOMEM; free(k); k = ellipsize(l, n_columns, 70); if (!k) return -ENOMEM; printf("%s%s%s\n", prefix, lookahead ? draw_special_char(DRAW_TREE_VERTICAL) : " ", k); *item = next; if (*item) { _cleanup_free_ char *p = NULL; p = strappend(prefix, lookahead ? draw_special_char(DRAW_TREE_VERTICAL) : " "); if (!p) return -ENOMEM; show_sysfs_one(udev, seat, item, sysfs, p, n_columns - 2); } } return 0; } int show_sysfs(const char *seat, const char *prefix, unsigned n_columns) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; struct udev_list_entry *first = NULL; int r; if (n_columns <= 0) n_columns = columns(); if (!prefix) prefix = ""; if (isempty(seat)) seat = "seat0"; udev = udev_new(); if (!udev) return -ENOMEM; e = udev_enumerate_new(udev); if (!e) return -ENOMEM; if (!streq(seat, "seat0")) r = udev_enumerate_add_match_tag(e, seat); else r = udev_enumerate_add_match_tag(e, "seat"); if (r < 0) return r; r = udev_enumerate_add_match_is_initialized(e); if (r < 0) return r; r = udev_enumerate_scan_devices(e); if (r < 0) return r; first = udev_enumerate_get_list_entry(e); if (first) show_sysfs_one(udev, seat, &first, "/", prefix, n_columns); else printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_RIGHT), "(none)"); return r; } systemd-229/src/login/sysfs-show.h000066400000000000000000000014451265713322000172620ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int show_sysfs(const char *seat, const char *prefix, unsigned columns); systemd-229/src/login/systemd-user.m4000066400000000000000000000003671265713322000176740ustar00rootroot00000000000000# This file is part of systemd. # # Used by systemd --user instances. account include system-auth m4_ifdef(`HAVE_SELINUX', session required pam_selinux.so close session required pam_selinux.so nottys open )m4_dnl session include system-auth systemd-229/src/login/test-inhibit.c000066400000000000000000000065351265713322000175400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "bus-util.h" #include "fd-util.h" #include "macro.h" #include "util.h" static int inhibit(sd_bus *bus, const char *what) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *who = "Test Tool", *reason = "Just because!", *mode = "block"; int fd; int r; r = sd_bus_call_method(bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "Inhibit", &error, &reply, "ssss", what, who, reason, mode); assert_se(r >= 0); r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_UNIX_FD, &fd); assert_se(r >= 0); assert_se(fd >= 0); return dup(fd); } static void print_inhibitors(sd_bus *bus) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *what, *who, *why, *mode; uint32_t uid, pid; unsigned n = 0; int r; r = sd_bus_call_method(bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "ListInhibitors", &error, &reply, ""); assert_se(r >= 0); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)"); assert_se(r >= 0); while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) { printf("what=<%s> who=<%s> why=<%s> mode=<%s> uid=<%"PRIu32"> pid=<%"PRIu32">\n", what, who, why, mode, uid, pid); n++; } assert_se(r >= 0); printf("%u inhibitors\n", n); } int main(int argc, char*argv[]) { _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; int fd1, fd2; int r; r = sd_bus_open_system(&bus); assert_se(r >= 0); print_inhibitors(bus); fd1 = inhibit(bus, "sleep"); assert_se(fd1 >= 0); print_inhibitors(bus); fd2 = inhibit(bus, "idle:shutdown"); assert_se(fd2 >= 0); print_inhibitors(bus); safe_close(fd1); sleep(1); print_inhibitors(bus); safe_close(fd2); sleep(1); print_inhibitors(bus); return 0; } systemd-229/src/login/test-login-shared.c000066400000000000000000000022371265713322000204610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "login-util.h" #include "macro.h" static void test_session_id_valid(void) { assert_se(session_id_valid("c1")); assert_se(session_id_valid("1234")); assert_se(!session_id_valid("1-2")); assert_se(!session_id_valid("")); assert_se(!session_id_valid("\tid")); } int main(int argc, char* argv[]) { log_parse_environment(); log_open(); test_session_id_valid(); return 0; } systemd-229/src/login/test-login-tables.c000066400000000000000000000022651265713322000204660ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "logind-action.h" #include "logind-session.h" #include "test-tables.h" int main(int argc, char **argv) { test_table(handle_action, HANDLE_ACTION); test_table(inhibit_mode, INHIBIT_MODE); test_table(kill_who, KILL_WHO); test_table(session_class, SESSION_CLASS); test_table(session_state, SESSION_STATE); test_table(session_type, SESSION_TYPE); test_table(user_state, USER_STATE); return EXIT_SUCCESS; } systemd-229/src/machine-id-setup/000077500000000000000000000000001265713322000170045ustar00rootroot00000000000000systemd-229/src/machine-id-setup/Makefile000077700000000000000000000000001265713322000223122../Makefileustar00rootroot00000000000000systemd-229/src/machine-id-setup/machine-id-setup-main.c000066400000000000000000000064121265713322000232310ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "log.h" #include "machine-id-setup.h" #include "path-util.h" #include "util.h" static char *arg_root = NULL; static bool arg_commit = false; static void help(void) { printf("%s [OPTIONS...]\n\n" "Initialize /etc/machine-id from a random source.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --root=ROOT Filesystem root\n" " --commit Commit transient ID\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_ROOT, ARG_COMMIT, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "root", required_argument, NULL, ARG_ROOT }, { "commit", no_argument, NULL, ARG_COMMIT }, {} }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "hqcv", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_ROOT: r = parse_path_argument_and_warn(optarg, true, &arg_root); if (r < 0) return r; break; case ARG_COMMIT: arg_commit = true; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (optind < argc) { log_error("Extraneous arguments"); return -EINVAL; } return 1; } int main(int argc, char *argv[]) { int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; if (arg_commit) r = machine_id_commit(arg_root); else r = machine_id_setup(arg_root, SD_ID128_NULL); finish: free(arg_root); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/machine/000077500000000000000000000000001265713322000152545ustar00rootroot00000000000000systemd-229/src/machine/.gitignore000066400000000000000000000000411265713322000172370ustar00rootroot00000000000000/org.freedesktop.machine1.policy systemd-229/src/machine/Makefile000077700000000000000000000000001265713322000205622../Makefileustar00rootroot00000000000000systemd-229/src/machine/image-dbus.c000066400000000000000000000252161265713322000174430ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-label.h" #include "bus-util.h" #include "image-dbus.h" #include "io-util.h" #include "machine-image.h" #include "strv.h" #include "user-util.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, image_type, ImageType); int bus_image_method_remove( sd_bus_message *message, void *userdata, sd_bus_error *error) { Image *image = userdata; Manager *m = image->userdata; int r; assert(message); assert(image); r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, "org.freedesktop.machine1.manage-images", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = image_remove(image); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } int bus_image_method_rename( sd_bus_message *message, void *userdata, sd_bus_error *error) { Image *image = userdata; Manager *m = image->userdata; const char *new_name; int r; assert(message); assert(image); r = sd_bus_message_read(message, "s", &new_name); if (r < 0) return r; if (!image_name_is_valid(new_name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name); r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, "org.freedesktop.machine1.manage-images", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = image_rename(image, new_name); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } int bus_image_method_clone( sd_bus_message *message, void *userdata, sd_bus_error *error) { Image *image = userdata; Manager *m = image->userdata; const char *new_name; int r, read_only; assert(message); assert(image); r = sd_bus_message_read(message, "sb", &new_name, &read_only); if (r < 0) return r; if (!image_name_is_valid(new_name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name); r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, "org.freedesktop.machine1.manage-images", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = image_clone(image, new_name, read_only); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } int bus_image_method_mark_read_only( sd_bus_message *message, void *userdata, sd_bus_error *error) { Image *image = userdata; Manager *m = image->userdata; int r, read_only; assert(message); r = sd_bus_message_read(message, "b", &read_only); if (r < 0) return r; r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, "org.freedesktop.machine1.manage-images", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = image_read_only(image, read_only); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } int bus_image_method_set_limit( sd_bus_message *message, void *userdata, sd_bus_error *error) { Image *image = userdata; Manager *m = image->userdata; uint64_t limit; int r; assert(message); r = sd_bus_message_read(message, "t", &limit); if (r < 0) return r; if (!FILE_SIZE_VALID_OR_INFINITY(limit)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range"); r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, "org.freedesktop.machine1.manage-images", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = image_set_limit(image, limit); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } const sd_bus_vtable image_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Image, name), 0), SD_BUS_PROPERTY("Path", "s", NULL, offsetof(Image, path), 0), SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Image, type), 0), SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool, offsetof(Image, read_only), 0), SD_BUS_PROPERTY("CreationTimestamp", "t", NULL, offsetof(Image, crtime), 0), SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL, offsetof(Image, mtime), 0), SD_BUS_PROPERTY("Usage", "t", NULL, offsetof(Image, usage), 0), SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0), SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0), SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0), SD_BUS_METHOD("Remove", NULL, NULL, bus_image_method_remove, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Rename", "s", NULL, bus_image_method_rename, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Clone", "sb", NULL, bus_image_method_clone, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetLimit", "t", NULL, bus_image_method_set_limit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; static int image_flush_cache(sd_event_source *s, void *userdata) { Manager *m = userdata; Image *i; assert(s); assert(m); while ((i = hashmap_steal_first(m->image_cache))) image_unref(i); return 0; } int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { _cleanup_free_ char *e = NULL; Manager *m = userdata; Image *image = NULL; const char *p; int r; assert(bus); assert(path); assert(interface); assert(found); p = startswith(path, "/org/freedesktop/machine1/image/"); if (!p) return 0; e = bus_label_unescape(p); if (!e) return -ENOMEM; image = hashmap_get(m->image_cache, e); if (image) { *found = image; return 1; } r = hashmap_ensure_allocated(&m->image_cache, &string_hash_ops); if (r < 0) return r; if (!m->image_cache_defer_event) { r = sd_event_add_defer(m->event, &m->image_cache_defer_event, image_flush_cache, m); if (r < 0) return r; r = sd_event_source_set_priority(m->image_cache_defer_event, SD_EVENT_PRIORITY_IDLE); if (r < 0) return r; } r = sd_event_source_set_enabled(m->image_cache_defer_event, SD_EVENT_ONESHOT); if (r < 0) return r; r = image_find(e, &image); if (r <= 0) return r; image->userdata = m; r = hashmap_put(m->image_cache, image->name, image); if (r < 0) { image_unref(image); return r; } *found = image; return 1; } char *image_bus_path(const char *name) { _cleanup_free_ char *e = NULL; assert(name); e = bus_label_escape(name); if (!e) return NULL; return strappend("/org/freedesktop/machine1/image/", e); } int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_(image_hashmap_freep) Hashmap *images = NULL; _cleanup_strv_free_ char **l = NULL; Image *image; Iterator i; int r; assert(bus); assert(path); assert(nodes); images = hashmap_new(&string_hash_ops); if (!images) return -ENOMEM; r = image_discover(images); if (r < 0) return r; HASHMAP_FOREACH(image, images, i) { char *p; p = image_bus_path(image->name); if (!p) return -ENOMEM; r = strv_consume(&l, p); if (r < 0) return r; } *nodes = l; l = NULL; return 1; } systemd-229/src/machine/image-dbus.h000066400000000000000000000030111265713322000174350ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "machined.h" extern const sd_bus_vtable image_vtable[]; char *image_bus_path(const char *name); int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); int bus_image_method_remove(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_image_method_rename(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_image_method_clone(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_image_method_mark_read_only(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_image_method_set_limit(sd_bus_message *message, void *userdata, sd_bus_error *error); systemd-229/src/machine/machine-dbus.c000066400000000000000000001375531265713322000177750ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include /* When we include libgen.h because we need dirname() we immediately * undefine basename() since libgen.h defines it as a macro to the POSIX * version which is really broken. We prefer GNU basename(). */ #include #undef basename #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-internal.h" #include "bus-label.h" #include "bus-util.h" #include "copy.h" #include "env-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "in-addr-util.h" #include "local-addresses.h" #include "machine-dbus.h" #include "machine.h" #include "mkdir.h" #include "path-util.h" #include "process-util.h" #include "strv.h" #include "terminal-util.h" #include "user-util.h" static int property_get_id( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Machine *m = userdata; assert(bus); assert(reply); assert(m); return sd_bus_message_append_array(reply, 'y', &m->id, 16); } static int property_get_state( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Machine *m = userdata; const char *state; int r; assert(bus); assert(reply); assert(m); state = machine_state_to_string(machine_get_state(m)); r = sd_bus_message_append_basic(reply, 's', state); if (r < 0) return r; return 1; } static int property_get_netif( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Machine *m = userdata; assert(bus); assert(reply); assert(m); assert_cc(sizeof(int) == sizeof(int32_t)); return sd_bus_message_append_array(reply, 'i', m->netif, m->n_netif * sizeof(int)); } static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass); int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) { Machine *m = userdata; int r; assert(message); assert(m); r = bus_verify_polkit_async( message, CAP_KILL, "org.freedesktop.machine1.manage-machines", NULL, false, UID_INVALID, &m->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = machine_stop(m); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) { Machine *m = userdata; const char *swho; int32_t signo; KillWho who; int r; assert(message); assert(m); r = sd_bus_message_read(message, "si", &swho, &signo); if (r < 0) return r; if (isempty(swho)) who = KILL_ALL; else { who = kill_who_from_string(swho); if (who < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho); } if (signo <= 0 || signo >= _NSIG) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo); r = bus_verify_polkit_async( message, CAP_KILL, "org.freedesktop.machine1.manage-machines", NULL, false, UID_INVALID, &m->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ r = machine_kill(m, who, signo); if (r < 0) return r; return sd_bus_reply_method_return(message, NULL); } int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Machine *m = userdata; int r; assert(message); assert(m); r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "(iay)"); if (r < 0) return r; switch (m->class) { case MACHINE_HOST: { _cleanup_free_ struct local_address *addresses = NULL; struct local_address *a; int n, i; n = local_addresses(NULL, 0, AF_UNSPEC, &addresses); if (n < 0) return n; for (a = addresses, i = 0; i < n; a++, i++) { r = sd_bus_message_open_container(reply, 'r', "iay"); if (r < 0) return r; r = sd_bus_message_append(reply, "i", addresses[i].family); if (r < 0) return r; r = sd_bus_message_append_array(reply, 'y', &addresses[i].address, FAMILY_ADDRESS_SIZE(addresses[i].family)); if (r < 0) return r; r = sd_bus_message_close_container(reply); if (r < 0) return r; } break; } case MACHINE_CONTAINER: { _cleanup_close_pair_ int pair[2] = { -1, -1 }; _cleanup_free_ char *us = NULL, *them = NULL; _cleanup_close_ int netns_fd = -1; const char *p; siginfo_t si; pid_t child; r = readlink_malloc("/proc/self/ns/net", &us); if (r < 0) return r; p = procfs_file_alloca(m->leader, "ns/net"); r = readlink_malloc(p, &them); if (r < 0) return r; if (streq(us, them)) return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name); r = namespace_open(m->leader, NULL, NULL, &netns_fd, NULL, NULL); if (r < 0) return r; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0) return -errno; child = fork(); if (child < 0) return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m"); if (child == 0) { _cleanup_free_ struct local_address *addresses = NULL; struct local_address *a; int i, n; pair[0] = safe_close(pair[0]); r = namespace_enter(-1, -1, netns_fd, -1, -1); if (r < 0) _exit(EXIT_FAILURE); n = local_addresses(NULL, 0, AF_UNSPEC, &addresses); if (n < 0) _exit(EXIT_FAILURE); for (a = addresses, i = 0; i < n; a++, i++) { struct iovec iov[2] = { { .iov_base = &a->family, .iov_len = sizeof(a->family) }, { .iov_base = &a->address, .iov_len = FAMILY_ADDRESS_SIZE(a->family) }, }; r = writev(pair[1], iov, 2); if (r < 0) _exit(EXIT_FAILURE); } pair[1] = safe_close(pair[1]); _exit(EXIT_SUCCESS); } pair[1] = safe_close(pair[1]); for (;;) { int family; ssize_t n; union in_addr_union in_addr; struct iovec iov[2]; struct msghdr mh = { .msg_iov = iov, .msg_iovlen = 2, }; iov[0] = (struct iovec) { .iov_base = &family, .iov_len = sizeof(family) }; iov[1] = (struct iovec) { .iov_base = &in_addr, .iov_len = sizeof(in_addr) }; n = recvmsg(pair[0], &mh, 0); if (n < 0) return -errno; if ((size_t) n < sizeof(family)) break; r = sd_bus_message_open_container(reply, 'r', "iay"); if (r < 0) return r; r = sd_bus_message_append(reply, "i", family); if (r < 0) return r; switch (family) { case AF_INET: if (n != sizeof(struct in_addr) + sizeof(family)) return -EIO; r = sd_bus_message_append_array(reply, 'y', &in_addr.in, sizeof(in_addr.in)); break; case AF_INET6: if (n != sizeof(struct in6_addr) + sizeof(family)) return -EIO; r = sd_bus_message_append_array(reply, 'y', &in_addr.in6, sizeof(in_addr.in6)); break; } if (r < 0) return r; r = sd_bus_message_close_container(reply); if (r < 0) return r; } r = wait_for_terminate(child, &si); if (r < 0) return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m"); if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS) return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally."); break; } default: return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting IP address data is only supported on container machines."); } r = sd_bus_message_close_container(reply); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); } int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_strv_free_ char **l = NULL; Machine *m = userdata; char **k, **v; int r; assert(message); assert(m); switch (m->class) { case MACHINE_HOST: r = load_env_file_pairs(NULL, "/etc/os-release", NULL, &l); if (r < 0) return r; break; case MACHINE_CONTAINER: { _cleanup_close_ int mntns_fd = -1, root_fd = -1; _cleanup_close_pair_ int pair[2] = { -1, -1 }; _cleanup_fclose_ FILE *f = NULL; siginfo_t si; pid_t child; r = namespace_open(m->leader, NULL, &mntns_fd, NULL, NULL, &root_fd); if (r < 0) return r; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0) return -errno; child = fork(); if (child < 0) return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m"); if (child == 0) { _cleanup_close_ int fd = -1; pair[0] = safe_close(pair[0]); r = namespace_enter(-1, mntns_fd, -1, -1, root_fd); if (r < 0) _exit(EXIT_FAILURE); fd = open("/etc/os-release", O_RDONLY|O_CLOEXEC); if (fd < 0) { fd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC); if (fd < 0) _exit(EXIT_FAILURE); } r = copy_bytes(fd, pair[1], (uint64_t) -1, false); if (r < 0) _exit(EXIT_FAILURE); _exit(EXIT_SUCCESS); } pair[1] = safe_close(pair[1]); f = fdopen(pair[0], "re"); if (!f) return -errno; pair[0] = -1; r = load_env_file_pairs(f, "/etc/os-release", NULL, &l); if (r < 0) return r; r = wait_for_terminate(child, &si); if (r < 0) return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m"); if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS) return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally."); break; } default: return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting OS release data is only supported on container machines."); } r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "{ss}"); if (r < 0) return r; STRV_FOREACH_PAIR(k, v, l) { r = sd_bus_message_append(reply, "{ss}", *k, *v); if (r < 0) return r; } r = sd_bus_message_close_container(reply); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); } int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *pty_name = NULL; _cleanup_close_ int master = -1; Machine *m = userdata; int r; assert(message); assert(m); r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-open-pty" : "org.freedesktop.machine1.open-pty", NULL, false, UID_INVALID, &m->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC); if (master < 0) return master; r = ptsname_namespace(master, &pty_name); if (r < 0) return r; r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; r = sd_bus_message_append(reply, "hs", master, pty_name); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); } static int container_bus_new(Machine *m, sd_bus_error *error, sd_bus **ret) { int r; assert(m); assert(ret); switch (m->class) { case MACHINE_HOST: *ret = NULL; break; case MACHINE_CONTAINER: { _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; char *address; r = sd_bus_new(&bus); if (r < 0) return r; if (asprintf(&address, "x-machine-kernel:pid=%1$" PID_PRI ";x-machine-unix:pid=%1$" PID_PRI, m->leader) < 0) return -ENOMEM; bus->address = address; bus->bus_client = true; bus->trusted = false; bus->is_system = true; r = sd_bus_start(bus); if (r == -ENOENT) return sd_bus_error_set_errnof(error, r, "There is no system bus in container %s.", m->name); if (r < 0) return r; *ret = bus; bus = NULL; break; } default: return -EOPNOTSUPP; } return 0; } int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *pty_name = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *allocated_bus = NULL; _cleanup_close_ int master = -1; sd_bus *container_bus = NULL; Machine *m = userdata; const char *p, *getty; int r; assert(message); assert(m); r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-login" : "org.freedesktop.machine1.login", NULL, false, UID_INVALID, &m->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC); if (master < 0) return master; r = ptsname_namespace(master, &pty_name); if (r < 0) return r; p = path_startswith(pty_name, "/dev/pts/"); if (!p) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PTS name %s is invalid", pty_name); r = container_bus_new(m, error, &allocated_bus); if (r < 0) return r; container_bus = allocated_bus ?: m->manager->bus; getty = strjoina("container-getty@", p, ".service"); r = sd_bus_call_method( container_bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit", error, NULL, "ss", getty, "replace"); if (r < 0) return r; r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; r = sd_bus_message_append(reply, "hs", master, pty_name); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); } int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *tm = NULL; _cleanup_free_ char *pty_name = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *allocated_bus = NULL; sd_bus *container_bus = NULL; _cleanup_close_ int master = -1, slave = -1; _cleanup_strv_free_ char **env = NULL, **args = NULL; Machine *m = userdata; const char *p, *unit, *user, *path, *description, *utmp_id; int r; assert(message); assert(m); r = sd_bus_message_read(message, "ss", &user, &path); if (r < 0) return r; if (isempty(user)) user = NULL; if (isempty(path)) path = "/bin/sh"; if (!path_is_absolute(path)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified path '%s' is not absolute", path); r = sd_bus_message_read_strv(message, &args); if (r < 0) return r; if (strv_isempty(args)) { args = strv_free(args); args = strv_new(path, NULL); if (!args) return -ENOMEM; args[0][0] = '-'; /* Tell /bin/sh that this shall be a login shell */ } r = sd_bus_message_read_strv(message, &env); if (r < 0) return r; if (!strv_env_is_valid(env)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments"); r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-shell" : "org.freedesktop.machine1.shell", NULL, false, UID_INVALID, &m->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC); if (master < 0) return master; r = ptsname_namespace(master, &pty_name); if (r < 0) return r; p = path_startswith(pty_name, "/dev/pts/"); assert(p); slave = machine_open_terminal(m, pty_name, O_RDWR|O_NOCTTY|O_CLOEXEC); if (slave < 0) return slave; utmp_id = path_startswith(pty_name, "/dev/"); assert(utmp_id); r = container_bus_new(m, error, &allocated_bus); if (r < 0) return r; container_bus = allocated_bus ?: m->manager->bus; r = sd_bus_message_new_method_call( container_bus, &tm, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartTransientUnit"); if (r < 0) return r; /* Name and mode */ unit = strjoina("container-shell@", p, ".service", NULL); r = sd_bus_message_append(tm, "ss", unit, "fail"); if (r < 0) return r; /* Properties */ r = sd_bus_message_open_container(tm, 'a', "(sv)"); if (r < 0) return r; description = strjoina("Shell for User ", isempty(user) ? "root" : user); r = sd_bus_message_append(tm, "(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)", "Description", "s", description, "StandardInputFileDescriptor", "h", slave, "StandardOutputFileDescriptor", "h", slave, "StandardErrorFileDescriptor", "h", slave, "SendSIGHUP", "b", true, "IgnoreSIGPIPE", "b", false, "KillMode", "s", "mixed", "TTYReset", "b", true, "UtmpIdentifier", "s", utmp_id, "UtmpMode", "s", "user", "PAMName", "s", "login", "WorkingDirectory", "s", "-~"); if (r < 0) return r; r = sd_bus_message_append(tm, "(sv)", "User", "s", isempty(user) ? "root" : user); if (r < 0) return r; if (!strv_isempty(env)) { r = sd_bus_message_open_container(tm, 'r', "sv"); if (r < 0) return r; r = sd_bus_message_append(tm, "s", "Environment"); if (r < 0) return r; r = sd_bus_message_open_container(tm, 'v', "as"); if (r < 0) return r; r = sd_bus_message_append_strv(tm, env); if (r < 0) return r; r = sd_bus_message_close_container(tm); if (r < 0) return r; r = sd_bus_message_close_container(tm); if (r < 0) return r; } /* Exec container */ r = sd_bus_message_open_container(tm, 'r', "sv"); if (r < 0) return r; r = sd_bus_message_append(tm, "s", "ExecStart"); if (r < 0) return r; r = sd_bus_message_open_container(tm, 'v', "a(sasb)"); if (r < 0) return r; r = sd_bus_message_open_container(tm, 'a', "(sasb)"); if (r < 0) return r; r = sd_bus_message_open_container(tm, 'r', "sasb"); if (r < 0) return r; r = sd_bus_message_append(tm, "s", path); if (r < 0) return r; r = sd_bus_message_append_strv(tm, args); if (r < 0) return r; r = sd_bus_message_append(tm, "b", true); if (r < 0) return r; r = sd_bus_message_close_container(tm); if (r < 0) return r; r = sd_bus_message_close_container(tm); if (r < 0) return r; r = sd_bus_message_close_container(tm); if (r < 0) return r; r = sd_bus_message_close_container(tm); if (r < 0) return r; r = sd_bus_message_close_container(tm); if (r < 0) return r; /* Auxiliary units */ r = sd_bus_message_append(tm, "a(sa(sv))", 0); if (r < 0) return r; r = sd_bus_call(container_bus, tm, 0, error, NULL); if (r < 0) return r; slave = safe_close(slave); r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; r = sd_bus_message_append(reply, "hs", master, pty_name); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); } int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 }; char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p; bool mount_slave_created = false, mount_slave_mounted = false, mount_tmp_created = false, mount_tmp_mounted = false, mount_outside_created = false, mount_outside_mounted = false; const char *dest, *src; Machine *m = userdata; int read_only, make_directory; pid_t child; siginfo_t si; int r; assert(message); assert(m); if (m->class != MACHINE_CONTAINER) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Bind mounting is only supported on container machines."); r = sd_bus_message_read(message, "ssbb", &src, &dest, &read_only, &make_directory); if (r < 0) return r; if (!path_is_absolute(src) || !path_is_safe(src)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and not contain ../."); if (isempty(dest)) dest = src; else if (!path_is_absolute(dest) || !path_is_safe(dest)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and not contain ../."); r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, "org.freedesktop.machine1.manage-machines", NULL, false, UID_INVALID, &m->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ /* One day, when bind mounting /proc/self/fd/n works across * namespace boundaries we should rework this logic to make * use of it... */ p = strjoina("/run/systemd/nspawn/propagate/", m->name, "/"); if (laccess(p, F_OK) < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Container does not allow propagation of mount points."); /* Our goal is to install a new bind mount into the container, possibly read-only. This is irritatingly complex unfortunately, currently. First, we start by creating a private playground in /tmp, that we can mount MS_SLAVE. (Which is necessary, since MS_MOVE cannot be applied to mounts with MS_SHARED parent mounts.) */ if (!mkdtemp(mount_slave)) return sd_bus_error_set_errnof(error, errno, "Failed to create playground %s: %m", mount_slave); mount_slave_created = true; if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to make bind mount %s: %m", mount_slave); goto finish; } mount_slave_mounted = true; if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to remount slave %s: %m", mount_slave); goto finish; } /* Second, we mount the source directory to a directory inside of our MS_SLAVE playground. */ mount_tmp = strjoina(mount_slave, "/mount"); if (mkdir(mount_tmp, 0700) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount point %s: %m", mount_tmp); goto finish; } mount_tmp_created = true; if (mount(src, mount_tmp, NULL, MS_BIND, NULL) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to overmount %s: %m", mount_tmp); goto finish; } mount_tmp_mounted = true; /* Third, we remount the new bind mount read-only if requested. */ if (read_only) if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to remount read-only %s: %m", mount_tmp); goto finish; } /* Fourth, we move the new bind mount into the propagation * directory. This way it will appear there read-only * right-away. */ mount_outside = strjoina("/run/systemd/nspawn/propagate/", m->name, "/XXXXXX"); if (!mkdtemp(mount_outside)) { r = sd_bus_error_set_errnof(error, errno, "Cannot create propagation directory %s: %m", mount_outside); goto finish; } mount_outside_created = true; if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to move %s to %s: %m", mount_tmp, mount_outside); goto finish; } mount_outside_mounted = true; mount_tmp_mounted = false; (void) rmdir(mount_tmp); mount_tmp_created = false; (void) umount(mount_slave); mount_slave_mounted = false; (void) rmdir(mount_slave); mount_slave_created = false; if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m"); goto finish; } child = fork(); if (child < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m"); goto finish; } if (child == 0) { const char *mount_inside; int mntfd; const char *q; errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]); q = procfs_file_alloca(m->leader, "ns/mnt"); mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC); if (mntfd < 0) { r = log_error_errno(errno, "Failed to open mount namespace of leader: %m"); goto child_fail; } if (setns(mntfd, CLONE_NEWNS) < 0) { r = log_error_errno(errno, "Failed to join namespace of leader: %m"); goto child_fail; } if (make_directory) (void) mkdir_p(dest, 0755); /* Fifth, move the mount to the right place inside */ mount_inside = strjoina("/run/systemd/nspawn/incoming/", basename(mount_outside)); if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) { r = log_error_errno(errno, "Failed to mount: %m"); goto child_fail; } _exit(EXIT_SUCCESS); child_fail: (void) write(errno_pipe_fd[1], &r, sizeof(r)); errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); _exit(EXIT_FAILURE); } errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); r = wait_for_terminate(child, &si); if (r < 0) { r = sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m"); goto finish; } if (si.si_code != CLD_EXITED) { r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally."); goto finish; } if (si.si_status != EXIT_SUCCESS) { if (read(errno_pipe_fd[0], &r, sizeof(r)) == sizeof(r)) r = sd_bus_error_set_errnof(error, r, "Failed to mount: %m"); else r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child failed."); goto finish; } r = sd_bus_reply_method_return(message, NULL); finish: if (mount_outside_mounted) umount(mount_outside); if (mount_outside_created) rmdir(mount_outside); if (mount_tmp_mounted) umount(mount_tmp); if (mount_tmp_created) rmdir(mount_tmp); if (mount_slave_mounted) umount(mount_slave); if (mount_slave_created) rmdir(mount_slave); return r; } static int machine_operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; MachineOperation *o = userdata; int r; assert(o); assert(si); o->pid = 0; if (si->si_code != CLD_EXITED) { r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child died abnormally."); goto fail; } if (si->si_status != EXIT_SUCCESS) { if (read(o->errno_fd, &r, sizeof(r)) == sizeof(r)) r = sd_bus_error_set_errnof(&error, r, "%m"); else r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child failed."); goto fail; } r = sd_bus_reply_method_return(o->message, NULL); if (r < 0) log_error_errno(r, "Failed to reply to message: %m"); machine_operation_unref(o); return 0; fail: r = sd_bus_reply_method_error(o->message, &error); if (r < 0) log_error_errno(r, "Failed to reply to message: %m"); machine_operation_unref(o); return 0; } int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *src, *dest, *host_path, *container_path, *host_basename, *host_dirname, *container_basename, *container_dirname; _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 }; _cleanup_close_ int hostfd = -1; Machine *m = userdata; MachineOperation *o; bool copy_from; pid_t child; char *t; int r; assert(message); assert(m); if (m->n_operations >= MACHINE_OPERATIONS_MAX) return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing copies."); if (m->class != MACHINE_CONTAINER) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Copying files is only supported on container machines."); r = sd_bus_message_read(message, "ss", &src, &dest); if (r < 0) return r; if (!path_is_absolute(src)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute."); if (isempty(dest)) dest = src; else if (!path_is_absolute(dest)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute."); r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, "org.freedesktop.machine1.manage-machines", NULL, false, UID_INVALID, &m->manager->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ copy_from = strstr(sd_bus_message_get_member(message), "CopyFrom"); if (copy_from) { container_path = src; host_path = dest; } else { host_path = src; container_path = dest; } host_basename = basename(host_path); t = strdupa(host_path); host_dirname = dirname(t); container_basename = basename(container_path); t = strdupa(container_path); container_dirname = dirname(t); hostfd = open(host_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY); if (hostfd < 0) return sd_bus_error_set_errnof(error, errno, "Failed to open host directory %s: %m", host_dirname); if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m"); child = fork(); if (child < 0) return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m"); if (child == 0) { int containerfd; const char *q; int mntfd; errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]); q = procfs_file_alloca(m->leader, "ns/mnt"); mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC); if (mntfd < 0) { r = log_error_errno(errno, "Failed to open mount namespace of leader: %m"); goto child_fail; } if (setns(mntfd, CLONE_NEWNS) < 0) { r = log_error_errno(errno, "Failed to join namespace of leader: %m"); goto child_fail; } containerfd = open(container_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY); if (containerfd < 0) { r = log_error_errno(errno, "Failed top open destination directory: %m"); goto child_fail; } if (copy_from) r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, true); else r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, true); hostfd = safe_close(hostfd); containerfd = safe_close(containerfd); if (r < 0) { r = log_error_errno(r, "Failed to copy tree: %m"); goto child_fail; } _exit(EXIT_SUCCESS); child_fail: (void) write(errno_pipe_fd[1], &r, sizeof(r)); errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); _exit(EXIT_FAILURE); } errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); /* Copying might take a while, hence install a watch the * child, and return */ o = new0(MachineOperation, 1); if (!o) return log_oom(); o->pid = child; o->message = sd_bus_message_ref(message); o->errno_fd = errno_pipe_fd[0]; errno_pipe_fd[0] = -1; r = sd_event_add_child(m->manager->event, &o->event_source, child, WEXITED, machine_operation_done, o); if (r < 0) { machine_operation_unref(o); return log_oom(); } LIST_PREPEND(operations, m->operations, o); m->n_operations++; o->machine = m; return 1; } const sd_bus_vtable machine_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Id", "ay", property_get_id, 0, SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Machine, timestamp), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Machine, service), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Unit", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("Leader", "u", NULL, offsetof(Machine, leader), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NetworkInterfaces", "ai", property_get_netif, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0), SD_BUS_METHOD("Terminate", NULL, NULL, bus_machine_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Kill", "si", NULL, bus_machine_method_kill, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetAddresses", NULL, "a(iay)", bus_machine_method_get_addresses, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_machine_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("OpenPTY", NULL, "hs", bus_machine_method_open_pty, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("OpenLogin", NULL, "hs", bus_machine_method_open_login, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("OpenShell", "ssasas", "hs", bus_machine_method_open_shell, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("BindMount", "ssbb", NULL, bus_machine_method_bind_mount, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CopyFrom", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CopyTo", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; Machine *machine; int r; assert(bus); assert(path); assert(interface); assert(found); assert(m); if (streq(path, "/org/freedesktop/machine1/machine/self")) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; sd_bus_message *message; pid_t pid; message = sd_bus_get_current_message(bus); if (!message) return 0; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); if (r < 0) return r; r = sd_bus_creds_get_pid(creds, &pid); if (r < 0) return r; r = manager_get_machine_by_pid(m, pid, &machine); if (r <= 0) return 0; } else { _cleanup_free_ char *e = NULL; const char *p; p = startswith(path, "/org/freedesktop/machine1/machine/"); if (!p) return 0; e = bus_label_unescape(p); if (!e) return -ENOMEM; machine = hashmap_get(m->machines, e); if (!machine) return 0; } *found = machine; return 1; } char *machine_bus_path(Machine *m) { _cleanup_free_ char *e = NULL; assert(m); e = bus_label_escape(m->name); if (!e) return NULL; return strappend("/org/freedesktop/machine1/machine/", e); } int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; Machine *machine = NULL; Manager *m = userdata; Iterator i; int r; assert(bus); assert(path); assert(nodes); HASHMAP_FOREACH(machine, m->machines, i) { char *p; p = machine_bus_path(machine); if (!p) return -ENOMEM; r = strv_consume(&l, p); if (r < 0) return r; } *nodes = l; l = NULL; return 1; } int machine_send_signal(Machine *m, bool new_machine) { _cleanup_free_ char *p = NULL; assert(m); p = machine_bus_path(m); if (!p) return -ENOMEM; return sd_bus_emit_signal( m->manager->bus, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", new_machine ? "MachineNew" : "MachineRemoved", "so", m->name, p); } int machine_send_create_reply(Machine *m, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL; _cleanup_free_ char *p = NULL; assert(m); if (!m->create_message) return 0; c = m->create_message; m->create_message = NULL; if (error) return sd_bus_reply_method_error(c, error); /* Update the machine state file before we notify the client * about the result. */ machine_save(m); p = machine_bus_path(m); if (!p) return -ENOMEM; return sd_bus_reply_method_return(c, "o", p); } systemd-229/src/machine/machine-dbus.h000066400000000000000000000040461265713322000177700ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "machine.h" extern const sd_bus_vtable machine_vtable[]; char *machine_bus_path(Machine *s); int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_error *error); int machine_send_signal(Machine *m, bool new_machine); int machine_send_create_reply(Machine *m, sd_bus_error *error); systemd-229/src/machine/machine.c000066400000000000000000000422531265713322000170320ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-messages.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "escape.h" #include "extract-word.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "hashmap.h" #include "machine-dbus.h" #include "machine.h" #include "mkdir.h" #include "parse-util.h" #include "process-util.h" #include "special.h" #include "string-table.h" #include "terminal-util.h" #include "unit-name.h" #include "util.h" Machine* machine_new(Manager *manager, MachineClass class, const char *name) { Machine *m; assert(manager); assert(class < _MACHINE_CLASS_MAX); assert(name); /* Passing class == _MACHINE_CLASS_INVALID here is fine. It * means as much as "we don't know yet", and that we'll figure * it out later when loading the state file. */ m = new0(Machine, 1); if (!m) return NULL; m->name = strdup(name); if (!m->name) goto fail; if (class != MACHINE_HOST) { m->state_file = strappend("/run/systemd/machines/", m->name); if (!m->state_file) goto fail; } m->class = class; if (hashmap_put(manager->machines, m->name, m) < 0) goto fail; m->manager = manager; return m; fail: free(m->state_file); free(m->name); free(m); return NULL; } void machine_free(Machine *m) { assert(m); while (m->operations) machine_operation_unref(m->operations); if (m->in_gc_queue) LIST_REMOVE(gc_queue, m->manager->machine_gc_queue, m); machine_release_unit(m); free(m->scope_job); (void) hashmap_remove(m->manager->machines, m->name); if (m->manager->host_machine == m) m->manager->host_machine = NULL; if (m->leader > 0) (void) hashmap_remove_value(m->manager->machine_leaders, PID_TO_PTR(m->leader), m); sd_bus_message_unref(m->create_message); free(m->name); free(m->state_file); free(m->service); free(m->root_directory); free(m->netif); free(m); } int machine_save(Machine *m) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(m); if (!m->state_file) return 0; if (!m->started) return 0; r = mkdir_safe_label("/run/systemd/machines", 0755, 0, 0); if (r < 0) goto fail; r = fopen_temporary(m->state_file, &f, &temp_path); if (r < 0) goto fail; (void) fchmod(fileno(f), 0644); fprintf(f, "# This is private data. Do not parse.\n" "NAME=%s\n", m->name); if (m->unit) { _cleanup_free_ char *escaped; escaped = cescape(m->unit); if (!escaped) { r = -ENOMEM; goto fail; } fprintf(f, "SCOPE=%s\n", escaped); /* We continue to call this "SCOPE=" because it is internal only, and we want to stay compatible with old files */ } if (m->scope_job) fprintf(f, "SCOPE_JOB=%s\n", m->scope_job); if (m->service) { _cleanup_free_ char *escaped; escaped = cescape(m->service); if (!escaped) { r = -ENOMEM; goto fail; } fprintf(f, "SERVICE=%s\n", escaped); } if (m->root_directory) { _cleanup_free_ char *escaped; escaped = cescape(m->root_directory); if (!escaped) { r = -ENOMEM; goto fail; } fprintf(f, "ROOT=%s\n", escaped); } if (!sd_id128_equal(m->id, SD_ID128_NULL)) fprintf(f, "ID=" SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(m->id)); if (m->leader != 0) fprintf(f, "LEADER="PID_FMT"\n", m->leader); if (m->class != _MACHINE_CLASS_INVALID) fprintf(f, "CLASS=%s\n", machine_class_to_string(m->class)); if (dual_timestamp_is_set(&m->timestamp)) fprintf(f, "REALTIME="USEC_FMT"\n" "MONOTONIC="USEC_FMT"\n", m->timestamp.realtime, m->timestamp.monotonic); if (m->n_netif > 0) { unsigned i; fputs("NETIF=", f); for (i = 0; i < m->n_netif; i++) { if (i != 0) fputc(' ', f); fprintf(f, "%i", m->netif[i]); } fputc('\n', f); } r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, m->state_file) < 0) { r = -errno; goto fail; } if (m->unit) { char *sl; /* Create a symlink from the unit name to the machine * name, so that we can quickly find the machine for * each given unit. Ignore error. */ sl = strjoina("/run/systemd/machines/unit:", m->unit); (void) symlink(m->name, sl); } return 0; fail: (void) unlink(m->state_file); if (temp_path) (void) unlink(temp_path); return log_error_errno(r, "Failed to save machine data %s: %m", m->state_file); } static void machine_unlink(Machine *m) { assert(m); if (m->unit) { char *sl; sl = strjoina("/run/systemd/machines/unit:", m->unit); (void) unlink(sl); } if (m->state_file) (void) unlink(m->state_file); } int machine_load(Machine *m) { _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *id = NULL, *leader = NULL, *class = NULL, *netif = NULL; int r; assert(m); if (!m->state_file) return 0; r = parse_env_file(m->state_file, NEWLINE, "SCOPE", &m->unit, "SCOPE_JOB", &m->scope_job, "SERVICE", &m->service, "ROOT", &m->root_directory, "ID", &id, "LEADER", &leader, "CLASS", &class, "REALTIME", &realtime, "MONOTONIC", &monotonic, "NETIF", &netif, NULL); if (r < 0) { if (r == -ENOENT) return 0; return log_error_errno(r, "Failed to read %s: %m", m->state_file); } if (id) sd_id128_from_string(id, &m->id); if (leader) parse_pid(leader, &m->leader); if (class) { MachineClass c; c = machine_class_from_string(class); if (c >= 0) m->class = c; } if (realtime) { unsigned long long l; if (sscanf(realtime, "%llu", &l) > 0) m->timestamp.realtime = l; } if (monotonic) { unsigned long long l; if (sscanf(monotonic, "%llu", &l) > 0) m->timestamp.monotonic = l; } if (netif) { size_t allocated = 0, nr = 0; const char *p; int *ni = NULL; p = netif; for(;;) { _cleanup_free_ char *word = NULL; int ifi; r = extract_first_word(&p, &word, NULL, 0); if (r == 0) break; if (r == -ENOMEM) return log_oom(); if (r < 0) { log_warning_errno(r, "Failed to parse NETIF: %s", netif); break; } if (parse_ifindex(word, &ifi) < 0) continue; if (!GREEDY_REALLOC(ni, allocated, nr+1)) { free(ni); return log_oom(); } ni[nr++] = ifi; } free(m->netif); m->netif = ni; m->n_netif = nr; } return r; } static int machine_start_scope(Machine *m, sd_bus_message *properties, sd_bus_error *error) { int r = 0; assert(m); assert(m->class != MACHINE_HOST); if (!m->unit) { _cleanup_free_ char *escaped = NULL; char *scope, *description, *job = NULL; escaped = unit_name_escape(m->name); if (!escaped) return log_oom(); scope = strjoin("machine-", escaped, ".scope", NULL); if (!scope) return log_oom(); description = strjoina(m->class == MACHINE_VM ? "Virtual Machine " : "Container ", m->name); r = manager_start_scope(m->manager, scope, m->leader, SPECIAL_MACHINE_SLICE, description, properties, error, &job); if (r < 0) { log_error("Failed to start machine scope: %s", bus_error_message(error, r)); free(scope); return r; } else { m->unit = scope; free(m->scope_job); m->scope_job = job; } } if (m->unit) hashmap_put(m->manager->machine_units, m->unit, m); return r; } int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) { int r; assert(m); if (!IN_SET(m->class, MACHINE_CONTAINER, MACHINE_VM)) return -EOPNOTSUPP; if (m->started) return 0; r = hashmap_put(m->manager->machine_leaders, PID_TO_PTR(m->leader), m); if (r < 0) return r; /* Create cgroup */ r = machine_start_scope(m, properties, error); if (r < 0) return r; log_struct(LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_MACHINE_START), "NAME=%s", m->name, "LEADER="PID_FMT, m->leader, LOG_MESSAGE("New machine %s.", m->name), NULL); if (!dual_timestamp_is_set(&m->timestamp)) dual_timestamp_get(&m->timestamp); m->started = true; /* Save new machine data */ machine_save(m); machine_send_signal(m, true); return 0; } static int machine_stop_scope(Machine *m) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *job = NULL; int r; assert(m); assert(m->class != MACHINE_HOST); if (!m->unit) return 0; r = manager_stop_unit(m->manager, m->unit, &error, &job); if (r < 0) { log_error("Failed to stop machine scope: %s", bus_error_message(&error, r)); return r; } free(m->scope_job); m->scope_job = job; return 0; } int machine_stop(Machine *m) { int r; assert(m); if (!IN_SET(m->class, MACHINE_CONTAINER, MACHINE_VM)) return -EOPNOTSUPP; r = machine_stop_scope(m); m->stopping = true; machine_save(m); return r; } int machine_finalize(Machine *m) { assert(m); if (m->started) log_struct(LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_MACHINE_STOP), "NAME=%s", m->name, "LEADER="PID_FMT, m->leader, LOG_MESSAGE("Machine %s terminated.", m->name), NULL); machine_unlink(m); machine_add_to_gc_queue(m); if (m->started) { machine_send_signal(m, false); m->started = false; } return 0; } bool machine_check_gc(Machine *m, bool drop_not_started) { assert(m); if (m->class == MACHINE_HOST) return true; if (drop_not_started && !m->started) return false; if (m->scope_job && manager_job_is_active(m->manager, m->scope_job)) return true; if (m->unit && manager_unit_is_active(m->manager, m->unit)) return true; return false; } void machine_add_to_gc_queue(Machine *m) { assert(m); if (m->in_gc_queue) return; LIST_PREPEND(gc_queue, m->manager->machine_gc_queue, m); m->in_gc_queue = true; } MachineState machine_get_state(Machine *s) { assert(s); if (s->class == MACHINE_HOST) return MACHINE_RUNNING; if (s->stopping) return MACHINE_CLOSING; if (s->scope_job) return MACHINE_OPENING; return MACHINE_RUNNING; } int machine_kill(Machine *m, KillWho who, int signo) { assert(m); if (!IN_SET(m->class, MACHINE_VM, MACHINE_CONTAINER)) return -EOPNOTSUPP; if (!m->unit) return -ESRCH; if (who == KILL_LEADER) { /* If we shall simply kill the leader, do so directly */ if (kill(m->leader, signo) < 0) return -errno; return 0; } /* Otherwise, make PID 1 do it for us, for the entire cgroup */ return manager_kill_unit(m->manager, m->unit, signo, NULL); } int machine_openpt(Machine *m, int flags) { assert(m); switch (m->class) { case MACHINE_HOST: { int fd; fd = posix_openpt(flags); if (fd < 0) return -errno; if (unlockpt(fd) < 0) return -errno; return fd; } case MACHINE_CONTAINER: if (m->leader <= 0) return -EINVAL; return openpt_in_namespace(m->leader, flags); default: return -EOPNOTSUPP; } } int machine_open_terminal(Machine *m, const char *path, int mode) { assert(m); switch (m->class) { case MACHINE_HOST: return open_terminal(path, mode); case MACHINE_CONTAINER: if (m->leader <= 0) return -EINVAL; return open_terminal_in_namespace(m->leader, path, mode); default: return -EOPNOTSUPP; } } MachineOperation *machine_operation_unref(MachineOperation *o) { if (!o) return NULL; sd_event_source_unref(o->event_source); safe_close(o->errno_fd); if (o->pid > 1) (void) kill(o->pid, SIGKILL); sd_bus_message_unref(o->message); if (o->machine) { LIST_REMOVE(operations, o->machine->operations, o); o->machine->n_operations--; } free(o); return NULL; } void machine_release_unit(Machine *m) { assert(m); if (!m->unit) return; (void) hashmap_remove(m->manager->machine_units, m->unit); m->unit = mfree(m->unit); } static const char* const machine_class_table[_MACHINE_CLASS_MAX] = { [MACHINE_CONTAINER] = "container", [MACHINE_VM] = "vm", [MACHINE_HOST] = "host", }; DEFINE_STRING_TABLE_LOOKUP(machine_class, MachineClass); static const char* const machine_state_table[_MACHINE_STATE_MAX] = { [MACHINE_OPENING] = "opening", [MACHINE_RUNNING] = "running", [MACHINE_CLOSING] = "closing" }; DEFINE_STRING_TABLE_LOOKUP(machine_state, MachineState); static const char* const kill_who_table[_KILL_WHO_MAX] = { [KILL_LEADER] = "leader", [KILL_ALL] = "all" }; DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho); systemd-229/src/machine/machine.h000066400000000000000000000064561265713322000170440ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Machine Machine; typedef struct MachineOperation MachineOperation; typedef enum KillWho KillWho; #include "list.h" #include "machined.h" typedef enum MachineState { MACHINE_OPENING, /* Machine is being registered */ MACHINE_RUNNING, /* Machine is running */ MACHINE_CLOSING, /* Machine is terminating */ _MACHINE_STATE_MAX, _MACHINE_STATE_INVALID = -1 } MachineState; typedef enum MachineClass { MACHINE_CONTAINER, MACHINE_VM, MACHINE_HOST, _MACHINE_CLASS_MAX, _MACHINE_CLASS_INVALID = -1 } MachineClass; enum KillWho { KILL_LEADER, KILL_ALL, _KILL_WHO_MAX, _KILL_WHO_INVALID = -1 }; #define MACHINE_OPERATIONS_MAX 64 struct MachineOperation { Machine *machine; pid_t pid; sd_bus_message *message; int errno_fd; sd_event_source *event_source; LIST_FIELDS(MachineOperation, operations); }; struct Machine { Manager *manager; char *name; sd_id128_t id; MachineClass class; char *state_file; char *service; char *root_directory; char *unit; char *scope_job; pid_t leader; dual_timestamp timestamp; bool in_gc_queue:1; bool started:1; bool stopping:1; sd_bus_message *create_message; int *netif; unsigned n_netif; LIST_FIELDS(Machine, gc_queue); MachineOperation *operations; unsigned n_operations; }; Machine* machine_new(Manager *manager, MachineClass class, const char *name); void machine_free(Machine *m); bool machine_check_gc(Machine *m, bool drop_not_started); void machine_add_to_gc_queue(Machine *m); int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error); int machine_stop(Machine *m); int machine_finalize(Machine *m); int machine_save(Machine *m); int machine_load(Machine *m); int machine_kill(Machine *m, KillWho who, int signo); void machine_release_unit(Machine *m); MachineState machine_get_state(Machine *u); MachineOperation *machine_operation_unref(MachineOperation *o); const char* machine_class_to_string(MachineClass t) _const_; MachineClass machine_class_from_string(const char *s) _pure_; const char* machine_state_to_string(MachineState t) _const_; MachineState machine_state_from_string(const char *s) _pure_; const char *kill_who_to_string(KillWho k) _const_; KillWho kill_who_from_string(const char *s) _pure_; int machine_openpt(Machine *m, int flags); int machine_open_terminal(Machine *m, const char *path, int mode); systemd-229/src/machine/machinectl.c000066400000000000000000002701051265713322000175340ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include "sd-bus.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "cgroup-show.h" #include "cgroup-util.h" #include "copy.h" #include "env-util.h" #include "fd-util.h" #include "hostname-util.h" #include "import-util.h" #include "log.h" #include "logs-show.h" #include "macro.h" #include "mkdir.h" #include "pager.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "ptyfwd.h" #include "signal-util.h" #include "spawn-polkit-agent.h" #include "strv.h" #include "terminal-util.h" #include "unit-name.h" #include "util.h" #include "verbs.h" #include "web-util.h" static char **arg_property = NULL; static bool arg_all = false; static bool arg_full = false; static bool arg_no_pager = false; static bool arg_legend = true; static const char *arg_kill_who = NULL; static int arg_signal = SIGTERM; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static char *arg_host = NULL; static bool arg_read_only = false; static bool arg_mkdir = false; static bool arg_quiet = false; static bool arg_ask_password = true; static unsigned arg_lines = 10; static OutputMode arg_output = OUTPUT_SHORT; static bool arg_force = false; static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE; static const char* arg_format = NULL; static const char *arg_uid = NULL; static char **arg_setenv = NULL; static void pager_open_if_enabled(void) { if (arg_no_pager) return; pager_open(false); } static void polkit_agent_open_if_enabled(void) { /* Open the polkit agent as a child process if necessary */ if (!arg_ask_password) return; if (arg_transport != BUS_TRANSPORT_LOCAL) return; polkit_agent_open(); } static OutputFlags get_output_flags(void) { return arg_all * OUTPUT_SHOW_ALL | arg_full * OUTPUT_FULL_WIDTH | (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH | colors_enabled() * OUTPUT_COLOR | !arg_quiet * OUTPUT_WARN_CUTOFF; } typedef struct MachineInfo { const char *name; const char *class; const char *service; } MachineInfo; static int compare_machine_info(const void *a, const void *b) { const MachineInfo *x = a, *y = b; return strcmp(x->name, y->name); } static int list_machines(int argc, char *argv[], void *userdata) { size_t max_name = strlen("MACHINE"), max_class = strlen("CLASS"), max_service = strlen("SERVICE"); _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ MachineInfo *machines = NULL; const char *name, *class, *service, *object; size_t n_machines = 0, n_allocated = 0, j; sd_bus *bus = userdata; int r; assert(bus); pager_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "ListMachines", &error, &reply, NULL); if (r < 0) { log_error("Could not get machines: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_enter_container(reply, 'a', "(ssso)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) { size_t l; if (name[0] == '.' && !arg_all) continue; if (!GREEDY_REALLOC(machines, n_allocated, n_machines + 1)) return log_oom(); machines[n_machines].name = name; machines[n_machines].class = class; machines[n_machines].service = service; l = strlen(name); if (l > max_name) max_name = l; l = strlen(class); if (l > max_class) max_class = l; l = strlen(service); if (l > max_service) max_service = l; n_machines ++; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); qsort_safe(machines, n_machines, sizeof(MachineInfo), compare_machine_info); if (arg_legend) printf("%-*s %-*s %-*s\n", (int) max_name, "MACHINE", (int) max_class, "CLASS", (int) max_service, "SERVICE"); for (j = 0; j < n_machines; j++) printf("%-*s %-*s %-*s\n", (int) max_name, machines[j].name, (int) max_class, machines[j].class, (int) max_service, machines[j].service); if (arg_legend) printf("\n%zu machines listed.\n", n_machines); return 0; } typedef struct ImageInfo { const char *name; const char *type; bool read_only; usec_t crtime; usec_t mtime; uint64_t size; } ImageInfo; static int compare_image_info(const void *a, const void *b) { const ImageInfo *x = a, *y = b; return strcmp(x->name, y->name); } static int list_images(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; size_t max_name = strlen("NAME"), max_type = strlen("TYPE"), max_size = strlen("USAGE"), max_crtime = strlen("CREATED"), max_mtime = strlen("MODIFIED"); _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ ImageInfo *images = NULL; size_t n_images = 0, n_allocated = 0, j; const char *name, *type, *object; sd_bus *bus = userdata; uint64_t crtime, mtime, size; int read_only, r; assert(bus); pager_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "ListImages", &error, &reply, ""); if (r < 0) { log_error("Could not get images: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbttto)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &read_only, &crtime, &mtime, &size, &object)) > 0) { char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_BYTES_MAX)]; size_t l; if (name[0] == '.' && !arg_all) continue; if (!GREEDY_REALLOC(images, n_allocated, n_images + 1)) return log_oom(); images[n_images].name = name; images[n_images].type = type; images[n_images].read_only = read_only; images[n_images].crtime = crtime; images[n_images].mtime = mtime; images[n_images].size = size; l = strlen(name); if (l > max_name) max_name = l; l = strlen(type); if (l > max_type) max_type = l; if (crtime != 0) { l = strlen(strna(format_timestamp(buf, sizeof(buf), crtime))); if (l > max_crtime) max_crtime = l; } if (mtime != 0) { l = strlen(strna(format_timestamp(buf, sizeof(buf), mtime))); if (l > max_mtime) max_mtime = l; } if (size != (uint64_t) -1) { l = strlen(strna(format_bytes(buf, sizeof(buf), size))); if (l > max_size) max_size = l; } n_images++; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); qsort_safe(images, n_images, sizeof(ImageInfo), compare_image_info); if (arg_legend) printf("%-*s %-*s %-3s %-*s %-*s %-*s\n", (int) max_name, "NAME", (int) max_type, "TYPE", "RO", (int) max_size, "USAGE", (int) max_crtime, "CREATED", (int) max_mtime, "MODIFIED"); for (j = 0; j < n_images; j++) { char crtime_buf[FORMAT_TIMESTAMP_MAX], mtime_buf[FORMAT_TIMESTAMP_MAX], size_buf[FORMAT_BYTES_MAX]; printf("%-*s %-*s %s%-3s%s %-*s %-*s %-*s\n", (int) max_name, images[j].name, (int) max_type, images[j].type, images[j].read_only ? ansi_highlight_red() : "", yes_no(images[j].read_only), images[j].read_only ? ansi_normal() : "", (int) max_size, strna(format_bytes(size_buf, sizeof(size_buf), images[j].size)), (int) max_crtime, strna(format_timestamp(crtime_buf, sizeof(crtime_buf), images[j].crtime)), (int) max_mtime, strna(format_timestamp(mtime_buf, sizeof(mtime_buf), images[j].mtime))); } if (arg_legend) printf("\n%zu images listed.\n", n_images); return 0; } static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *path = NULL; const char *cgroup; int r; unsigned c; assert(bus); assert(unit); if (arg_transport == BUS_TRANSPORT_REMOTE) return 0; path = unit_dbus_path_from_name(unit); if (!path) return log_oom(); r = sd_bus_get_property( bus, "org.freedesktop.systemd1", path, unit_dbus_interface_from_name(unit), "ControlGroup", &error, &reply, "s"); if (r < 0) { log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_read(reply, "s", &cgroup); if (r < 0) return bus_log_parse_error(r); if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0) return 0; c = columns(); if (c > 18) c -= 18; else c = 0; show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags()); return 0; } static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(bus); assert(name); assert(prefix); assert(prefix2); r = sd_bus_call_method(bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "GetMachineAddresses", NULL, &reply, "s", name); if (r < 0) return r; r = sd_bus_message_enter_container(reply, 'a', "(iay)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) { int family; const void *a; size_t sz; char buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)]; r = sd_bus_message_read(reply, "i", &family); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_read_array(reply, 'y', &a, &sz); if (r < 0) return bus_log_parse_error(r); fputs(prefix, stdout); fputs(inet_ntop(family, a, buffer, sizeof(buffer)), stdout); if (family == AF_INET6 && ifi > 0) printf("%%%i", ifi); fputc('\n', stdout); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); if (prefix != prefix2) prefix = prefix2; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); return 0; } static int print_os_release(sd_bus *bus, const char *name, const char *prefix) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *k, *v, *pretty = NULL; int r; assert(bus); assert(name); assert(prefix); r = sd_bus_call_method(bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "GetMachineOSRelease", NULL, &reply, "s", name); if (r < 0) return r; r = sd_bus_message_enter_container(reply, 'a', "{ss}"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) { if (streq(k, "PRETTY_NAME")) pretty = v; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); if (pretty) printf("%s%s\n", prefix, pretty); return 0; } typedef struct MachineStatusInfo { char *name; sd_id128_t id; char *class; char *service; char *unit; char *root_directory; pid_t leader; struct dual_timestamp timestamp; int *netif; unsigned n_netif; } MachineStatusInfo; static void machine_status_info_clear(MachineStatusInfo *info) { if (info) { free(info->name); free(info->class); free(info->service); free(info->unit); free(info->root_directory); free(info->netif); zero(*info); } } static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) { char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char since2[FORMAT_TIMESTAMP_MAX], *s2; int ifi = -1; assert(bus); assert(i); fputs(strna(i->name), stdout); if (!sd_id128_equal(i->id, SD_ID128_NULL)) printf("(" SD_ID128_FORMAT_STR ")\n", SD_ID128_FORMAT_VAL(i->id)); else putchar('\n'); s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp.realtime); s2 = format_timestamp(since2, sizeof(since2), i->timestamp.realtime); if (s1) printf("\t Since: %s; %s\n", s2, s1); else if (s2) printf("\t Since: %s\n", s2); if (i->leader > 0) { _cleanup_free_ char *t = NULL; printf("\t Leader: %u", (unsigned) i->leader); get_process_comm(i->leader, &t); if (t) printf(" (%s)", t); putchar('\n'); } if (i->service) { printf("\t Service: %s", i->service); if (i->class) printf("; class %s", i->class); putchar('\n'); } else if (i->class) printf("\t Class: %s\n", i->class); if (i->root_directory) printf("\t Root: %s\n", i->root_directory); if (i->n_netif > 0) { unsigned c; fputs("\t Iface:", stdout); for (c = 0; c < i->n_netif; c++) { char name[IF_NAMESIZE+1] = ""; if (if_indextoname(i->netif[c], name)) { fputc(' ', stdout); fputs(name, stdout); if (ifi < 0) ifi = i->netif[c]; else ifi = 0; } else printf(" %i", i->netif[c]); } fputc('\n', stdout); } print_addresses(bus, i->name, ifi, "\t Address: ", "\t "); print_os_release(bus, i->name, "\t OS: "); if (i->unit) { printf("\t Unit: %s\n", i->unit); show_unit_cgroup(bus, i->unit, i->leader); if (arg_transport == BUS_TRANSPORT_LOCAL) show_journal_by_unit( stdout, i->unit, arg_output, 0, i->timestamp.monotonic, arg_lines, 0, get_output_flags() | OUTPUT_BEGIN_NEWLINE, SD_JOURNAL_LOCAL_ONLY, true, NULL); } } static int map_netif(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { MachineStatusInfo *i = userdata; size_t l; const void *v; int r; assert_cc(sizeof(int32_t) == sizeof(int)); r = sd_bus_message_read_array(m, SD_BUS_TYPE_INT32, &v, &l); if (r < 0) return r; if (r == 0) return -EBADMSG; i->n_netif = l / sizeof(int32_t); i->netif = memdup(v, l); if (!i->netif) return -ENOMEM; return 0; } static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) { static const struct bus_properties_map map[] = { { "Name", "s", NULL, offsetof(MachineStatusInfo, name) }, { "Class", "s", NULL, offsetof(MachineStatusInfo, class) }, { "Service", "s", NULL, offsetof(MachineStatusInfo, service) }, { "Unit", "s", NULL, offsetof(MachineStatusInfo, unit) }, { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) }, { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) }, { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp.realtime) }, { "TimestampMonotonic", "t", NULL, offsetof(MachineStatusInfo, timestamp.monotonic) }, { "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) }, { "NetworkInterfaces", "ai", map_netif, 0 }, {} }; _cleanup_(machine_status_info_clear) MachineStatusInfo info = {}; int r; assert(verb); assert(bus); assert(path); assert(new_line); r = bus_map_all_properties(bus, "org.freedesktop.machine1", path, map, &info); if (r < 0) return log_error_errno(r, "Could not get properties: %m"); if (*new_line) printf("\n"); *new_line = true; print_machine_status_info(bus, &info); return r; } static int show_machine_properties(sd_bus *bus, const char *path, bool *new_line) { int r; assert(bus); assert(path); assert(new_line); if (*new_line) printf("\n"); *new_line = true; r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all); if (r < 0) log_error_errno(r, "Could not get properties: %m"); return r; } static int show_machine(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; bool properties, new_line = false; sd_bus *bus = userdata; int r = 0, i; assert(bus); properties = !strstr(argv[0], "status"); pager_open_if_enabled(); if (properties && argc <= 1) { /* If no argument is specified, inspect the manager * itself */ r = show_machine_properties(bus, "/org/freedesktop/machine1", &new_line); if (r < 0) return r; } for (i = 1; i < argc; i++) { const char *path = NULL; r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "GetMachine", &error, &reply, "s", argv[i]); if (r < 0) { log_error("Could not get path to machine: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_read(reply, "o", &path); if (r < 0) return bus_log_parse_error(r); if (properties) r = show_machine_properties(bus, path, &new_line); else r = show_machine_info(argv[0], bus, path, &new_line); } return r; } typedef struct ImageStatusInfo { char *name; char *path; char *type; int read_only; usec_t crtime; usec_t mtime; uint64_t usage; uint64_t limit; uint64_t usage_exclusive; uint64_t limit_exclusive; } ImageStatusInfo; static void image_status_info_clear(ImageStatusInfo *info) { if (info) { free(info->name); free(info->path); free(info->type); zero(*info); } } static void print_image_status_info(sd_bus *bus, ImageStatusInfo *i) { char ts_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char ts_absolute[FORMAT_TIMESTAMP_MAX], *s2; char bs[FORMAT_BYTES_MAX], *s3; char bs_exclusive[FORMAT_BYTES_MAX], *s4; assert(bus); assert(i); if (i->name) { fputs(i->name, stdout); putchar('\n'); } if (i->type) printf("\t Type: %s\n", i->type); if (i->path) printf("\t Path: %s\n", i->path); printf("\t RO: %s%s%s\n", i->read_only ? ansi_highlight_red() : "", i->read_only ? "read-only" : "writable", i->read_only ? ansi_normal() : ""); s1 = format_timestamp_relative(ts_relative, sizeof(ts_relative), i->crtime); s2 = format_timestamp(ts_absolute, sizeof(ts_absolute), i->crtime); if (s1 && s2) printf("\t Created: %s; %s\n", s2, s1); else if (s2) printf("\t Created: %s\n", s2); s1 = format_timestamp_relative(ts_relative, sizeof(ts_relative), i->mtime); s2 = format_timestamp(ts_absolute, sizeof(ts_absolute), i->mtime); if (s1 && s2) printf("\tModified: %s; %s\n", s2, s1); else if (s2) printf("\tModified: %s\n", s2); s3 = format_bytes(bs, sizeof(bs), i->usage); s4 = i->usage_exclusive != i->usage ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->usage_exclusive) : NULL; if (s3 && s4) printf("\t Usage: %s (exclusive: %s)\n", s3, s4); else if (s3) printf("\t Usage: %s\n", s3); s3 = format_bytes(bs, sizeof(bs), i->limit); s4 = i->limit_exclusive != i->limit ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->limit_exclusive) : NULL; if (s3 && s4) printf("\t Limit: %s (exclusive: %s)\n", s3, s4); else if (s3) printf("\t Limit: %s\n", s3); } static int show_image_info(sd_bus *bus, const char *path, bool *new_line) { static const struct bus_properties_map map[] = { { "Name", "s", NULL, offsetof(ImageStatusInfo, name) }, { "Path", "s", NULL, offsetof(ImageStatusInfo, path) }, { "Type", "s", NULL, offsetof(ImageStatusInfo, type) }, { "ReadOnly", "b", NULL, offsetof(ImageStatusInfo, read_only) }, { "CreationTimestamp", "t", NULL, offsetof(ImageStatusInfo, crtime) }, { "ModificationTimestamp", "t", NULL, offsetof(ImageStatusInfo, mtime) }, { "Usage", "t", NULL, offsetof(ImageStatusInfo, usage) }, { "Limit", "t", NULL, offsetof(ImageStatusInfo, limit) }, { "UsageExclusive", "t", NULL, offsetof(ImageStatusInfo, usage_exclusive) }, { "LimitExclusive", "t", NULL, offsetof(ImageStatusInfo, limit_exclusive) }, {} }; _cleanup_(image_status_info_clear) ImageStatusInfo info = {}; int r; assert(bus); assert(path); assert(new_line); r = bus_map_all_properties(bus, "org.freedesktop.machine1", path, map, &info); if (r < 0) return log_error_errno(r, "Could not get properties: %m"); if (*new_line) printf("\n"); *new_line = true; print_image_status_info(bus, &info); return r; } typedef struct PoolStatusInfo { char *path; uint64_t usage; uint64_t limit; } PoolStatusInfo; static void pool_status_info_clear(PoolStatusInfo *info) { if (info) { free(info->path); zero(*info); info->usage = -1; info->limit = -1; } } static void print_pool_status_info(sd_bus *bus, PoolStatusInfo *i) { char bs[FORMAT_BYTES_MAX], *s; if (i->path) printf("\t Path: %s\n", i->path); s = format_bytes(bs, sizeof(bs), i->usage); if (s) printf("\t Usage: %s\n", s); s = format_bytes(bs, sizeof(bs), i->limit); if (s) printf("\t Limit: %s\n", s); } static int show_pool_info(sd_bus *bus) { static const struct bus_properties_map map[] = { { "PoolPath", "s", NULL, offsetof(PoolStatusInfo, path) }, { "PoolUsage", "t", NULL, offsetof(PoolStatusInfo, usage) }, { "PoolLimit", "t", NULL, offsetof(PoolStatusInfo, limit) }, {} }; _cleanup_(pool_status_info_clear) PoolStatusInfo info = { .usage = (uint64_t) -1, .limit = (uint64_t) -1, }; int r; assert(bus); r = bus_map_all_properties(bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", map, &info); if (r < 0) return log_error_errno(r, "Could not get properties: %m"); print_pool_status_info(bus, &info); return 0; } static int show_image_properties(sd_bus *bus, const char *path, bool *new_line) { int r; assert(bus); assert(path); assert(new_line); if (*new_line) printf("\n"); *new_line = true; r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all); if (r < 0) log_error_errno(r, "Could not get properties: %m"); return r; } static int show_image(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; bool properties, new_line = false; sd_bus *bus = userdata; int r = 0, i; assert(bus); properties = !strstr(argv[0], "status"); pager_open_if_enabled(); if (argc <= 1) { /* If no argument is specified, inspect the manager * itself */ if (properties) r = show_image_properties(bus, "/org/freedesktop/machine1", &new_line); else r = show_pool_info(bus); if (r < 0) return r; } for (i = 1; i < argc; i++) { const char *path = NULL; r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "GetImage", &error, &reply, "s", argv[i]); if (r < 0) { log_error("Could not get path to image: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_read(reply, "o", &path); if (r < 0) return bus_log_parse_error(r); if (properties) r = show_image_properties(bus, path, &new_line); else r = show_image_info(bus, path, &new_line); } return r; } static int kill_machine(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r, i; assert(bus); polkit_agent_open_if_enabled(); if (!arg_kill_who) arg_kill_who = "all"; for (i = 1; i < argc; i++) { r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "KillMachine", &error, NULL, "ssi", argv[i], arg_kill_who, arg_signal); if (r < 0) { log_error("Could not kill machine: %s", bus_error_message(&error, -r)); return r; } } return 0; } static int reboot_machine(int argc, char *argv[], void *userdata) { arg_kill_who = "leader"; arg_signal = SIGINT; /* sysvinit + systemd */ return kill_machine(argc, argv, userdata); } static int poweroff_machine(int argc, char *argv[], void *userdata) { arg_kill_who = "leader"; arg_signal = SIGRTMIN+4; /* only systemd */ return kill_machine(argc, argv, userdata); } static int terminate_machine(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r, i; assert(bus); polkit_agent_open_if_enabled(); for (i = 1; i < argc; i++) { r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "TerminateMachine", &error, NULL, "s", argv[i]); if (r < 0) { log_error("Could not terminate machine: %s", bus_error_message(&error, -r)); return r; } } return 0; } static int copy_files(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *abs_host_path = NULL; char *dest, *host_path, *container_path; sd_bus *bus = userdata; bool copy_from; int r; assert(bus); polkit_agent_open_if_enabled(); copy_from = streq(argv[0], "copy-from"); dest = argv[3] ?: argv[2]; host_path = copy_from ? dest : argv[2]; container_path = copy_from ? argv[2] : dest; if (!path_is_absolute(host_path)) { r = path_make_absolute_cwd(host_path, &abs_host_path); if (r < 0) return log_error_errno(r, "Failed to make path absolute: %m"); host_path = abs_host_path; } r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", copy_from ? "CopyFromMachine" : "CopyToMachine", &error, NULL, "sss", argv[1], copy_from ? container_path : host_path, copy_from ? host_path : container_path); if (r < 0) return log_error_errno(r, "Failed to copy: %s", bus_error_message(&error, r)); return 0; } static int bind_mount(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r; assert(bus); polkit_agent_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "BindMountMachine", &error, NULL, "sssbb", argv[1], argv[2], argv[3], arg_read_only, arg_mkdir); if (r < 0) { log_error("Failed to bind mount: %s", bus_error_message(&error, -r)); return r; } return 0; } static int on_machine_removed(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { PTYForward ** forward = (PTYForward**) userdata; int r; assert(m); assert(forward); if (*forward) { /* If the forwarder is already initialized, tell it to * exit on the next vhangup(), so that we still flush * out what might be queued and exit then. */ r = pty_forward_set_ignore_vhangup(*forward, false); if (r >= 0) return 0; log_error_errno(r, "Failed to set ignore_vhangup flag: %m"); } /* On error, or when the forwarder is not initialized yet, quit immediately */ sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), EXIT_FAILURE); return 0; } static int process_forward(sd_event *event, PTYForward **forward, int master, PTYForwardFlags flags, const char *name) { char last_char = 0; bool machine_died; int ret = 0, r; assert(event); assert(master >= 0); assert(name); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0); if (streq(name, ".host")) log_info("Connected to the local host. Press ^] three times within 1s to exit session."); else log_info("Connected to machine %s. Press ^] three times within 1s to exit session.", name); sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); r = pty_forward_new(event, master, flags, forward); if (r < 0) return log_error_errno(r, "Failed to create PTY forwarder: %m"); r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); pty_forward_get_last_char(*forward, &last_char); machine_died = (flags & PTY_FORWARD_IGNORE_VHANGUP) && pty_forward_get_ignore_vhangup(*forward) == 0; *forward = pty_forward_free(*forward); if (last_char != '\n') fputc('\n', stdout); if (machine_died) log_info("Machine %s terminated.", name); else if (streq(name, ".host")) log_info("Connection to the local host terminated."); else log_info("Connection to machine %s terminated.", name); sd_event_get_exit_code(event, &ret); return ret; } static int login_machine(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(pty_forward_freep) PTYForward *forward = NULL; _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; int master = -1, r; sd_bus *bus = userdata; const char *pty, *match, *machine; assert(bus); if (!strv_isempty(arg_setenv) || arg_uid) { log_error("--setenv= and --uid= are not supported for 'login'. Use 'shell' instead."); return -EINVAL; } if (arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) { log_error("Login only supported on local machines."); return -EOPNOTSUPP; } polkit_agent_open_if_enabled(); r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to get event loop: %m"); r = sd_bus_attach_event(bus, event, 0); if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop: %m"); machine = argc < 2 || isempty(argv[1]) ? ".host" : argv[1]; match = strjoina("type='signal'," "sender='org.freedesktop.machine1'," "path='/org/freedesktop/machine1',", "interface='org.freedesktop.machine1.Manager'," "member='MachineRemoved'," "arg0='", machine, "'"); r = sd_bus_add_match(bus, &slot, match, on_machine_removed, &forward); if (r < 0) return log_error_errno(r, "Failed to add machine removal match: %m"); r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "OpenMachineLogin", &error, &reply, "s", machine); if (r < 0) { log_error("Failed to get login PTY: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_read(reply, "hs", &master, &pty); if (r < 0) return bus_log_parse_error(r); return process_forward(event, &forward, master, PTY_FORWARD_IGNORE_VHANGUP, machine); } static int shell_machine(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(pty_forward_freep) PTYForward *forward = NULL; _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; int master = -1, r; sd_bus *bus = userdata; const char *pty, *match, *machine, *path, *uid = NULL; assert(bus); if (arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) { log_error("Shell only supported on local machines."); return -EOPNOTSUPP; } /* Pass $TERM to shell session, if not explicitly specified. */ if (!strv_find_prefix(arg_setenv, "TERM=")) { const char *t; t = strv_find_prefix(environ, "TERM="); if (t) { if (strv_extend(&arg_setenv, t) < 0) return log_oom(); } } polkit_agent_open_if_enabled(); r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to get event loop: %m"); r = sd_bus_attach_event(bus, event, 0); if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop: %m"); machine = argc < 2 || isempty(argv[1]) ? NULL : argv[1]; if (arg_uid) uid = arg_uid; else if (machine) { const char *at; at = strchr(machine, '@'); if (at) { uid = strndupa(machine, at - machine); machine = at + 1; } } if (isempty(machine)) machine = ".host"; match = strjoina("type='signal'," "sender='org.freedesktop.machine1'," "path='/org/freedesktop/machine1',", "interface='org.freedesktop.machine1.Manager'," "member='MachineRemoved'," "arg0='", machine, "'"); r = sd_bus_add_match(bus, &slot, match, on_machine_removed, &forward); if (r < 0) return log_error_errno(r, "Failed to add machine removal match: %m"); r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "OpenMachineShell"); if (r < 0) return bus_log_create_error(r); path = argc < 3 || isempty(argv[2]) ? NULL : argv[2]; r = sd_bus_message_append(m, "sss", machine, uid, path); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append_strv(m, strv_length(argv) <= 3 ? NULL : argv + 2); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append_strv(m, arg_setenv); if (r < 0) return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) { log_error("Failed to get shell PTY: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_read(reply, "hs", &master, &pty); if (r < 0) return bus_log_parse_error(r); return process_forward(event, &forward, master, 0, machine); } static int remove_image(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r, i; assert(bus); polkit_agent_open_if_enabled(); for (i = 1; i < argc; i++) { r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "RemoveImage", &error, NULL, "s", argv[i]); if (r < 0) { log_error("Could not remove image: %s", bus_error_message(&error, -r)); return r; } } return 0; } static int rename_image(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r; polkit_agent_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "RenameImage", &error, NULL, "ss", argv[1], argv[2]); if (r < 0) { log_error("Could not rename image: %s", bus_error_message(&error, -r)); return r; } return 0; } static int clone_image(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r; polkit_agent_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "CloneImage", &error, NULL, "ssb", argv[1], argv[2], arg_read_only); if (r < 0) { log_error("Could not clone image: %s", bus_error_message(&error, -r)); return r; } return 0; } static int read_only_image(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int b = true, r; if (argc > 2) { b = parse_boolean(argv[2]); if (b < 0) { log_error("Failed to parse boolean argument: %s", argv[2]); return -EINVAL; } } polkit_agent_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "MarkImageReadOnly", &error, NULL, "sb", argv[1], b); if (r < 0) { log_error("Could not mark image read-only: %s", bus_error_message(&error, -r)); return r; } return 0; } static int make_service_name(const char *name, char **ret) { _cleanup_free_ char *e = NULL; int r; assert(name); assert(ret); if (!machine_name_is_valid(name)) { log_error("Invalid machine name %s.", name); return -EINVAL; } e = unit_name_escape(name); if (!e) return log_oom(); r = unit_name_build("systemd-nspawn", e, ".service", ret); if (r < 0) return log_error_errno(r, "Failed to build unit name: %m"); return 0; } static int start_machine(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; sd_bus *bus = userdata; int r, i; assert(bus); polkit_agent_open_if_enabled(); r = bus_wait_for_jobs_new(bus, &w); if (r < 0) return log_oom(); for (i = 1; i < argc; i++) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *unit = NULL; const char *object; r = make_service_name(argv[i], &unit); if (r < 0) return r; r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit", &error, &reply, "ss", unit, "fail"); if (r < 0) { log_error("Failed to start unit: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_read(reply, "o", &object); if (r < 0) return bus_log_parse_error(r); r = bus_wait_for_jobs_add(w, object); if (r < 0) return log_oom(); } r = bus_wait_for_jobs(w, arg_quiet, NULL); if (r < 0) return r; return 0; } static int enable_machine(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int carries_install_info = 0; const char *method = NULL; sd_bus *bus = userdata; int r, i; assert(bus); polkit_agent_open_if_enabled(); method = streq(argv[0], "enable") ? "EnableUnitFiles" : "DisableUnitFiles"; r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", method); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'a', "s"); if (r < 0) return bus_log_create_error(r); for (i = 1; i < argc; i++) { _cleanup_free_ char *unit = NULL; r = make_service_name(argv[i], &unit); if (r < 0) return r; r = sd_bus_message_append(m, "s", unit); if (r < 0) return bus_log_create_error(r); } r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); if (streq(argv[0], "enable")) r = sd_bus_message_append(m, "bb", false, false); else r = sd_bus_message_append(m, "b", false); if (r < 0) return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) { log_error("Failed to enable or disable unit: %s", bus_error_message(&error, -r)); return r; } if (streq(argv[0], "enable")) { r = sd_bus_message_read(reply, "b", carries_install_info); if (r < 0) return bus_log_parse_error(r); } r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) return r; r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reload", &error, NULL, NULL); if (r < 0) { log_error("Failed to reload daemon: %s", bus_error_message(&error, -r)); return r; } return 0; } static int match_log_message(sd_bus_message *m, void *userdata, sd_bus_error *error) { const char **our_path = userdata, *line; unsigned priority; int r; assert(m); assert(our_path); r = sd_bus_message_read(m, "us", &priority, &line); if (r < 0) { bus_log_parse_error(r); return 0; } if (!streq_ptr(*our_path, sd_bus_message_get_path(m))) return 0; if (arg_quiet && LOG_PRI(priority) >= LOG_INFO) return 0; log_full(priority, "%s", line); return 0; } static int match_transfer_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { const char **our_path = userdata, *path, *result; uint32_t id; int r; assert(m); assert(our_path); r = sd_bus_message_read(m, "uos", &id, &path, &result); if (r < 0) { bus_log_parse_error(r); return 0; } if (!streq_ptr(*our_path, path)) return 0; sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), !streq_ptr(result, "done")); return 0; } static int transfer_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { assert(s); assert(si); if (!arg_quiet) log_info("Continuing download in the background. Use \"machinectl cancel-transfer %" PRIu32 "\" to abort transfer.", PTR_TO_UINT32(userdata)); sd_event_exit(sd_event_source_get_event(s), EINTR); return 0; } static int transfer_image_common(sd_bus *bus, sd_bus_message *m) { _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot_job_removed = NULL, *slot_log_message = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_event_unrefp) sd_event* event = NULL; const char *path = NULL; uint32_t id; int r; assert(bus); assert(m); polkit_agent_open_if_enabled(); r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to get event loop: %m"); r = sd_bus_attach_event(bus, event, 0); if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop: %m"); r = sd_bus_add_match( bus, &slot_job_removed, "type='signal'," "sender='org.freedesktop.import1'," "interface='org.freedesktop.import1.Manager'," "member='TransferRemoved'," "path='/org/freedesktop/import1'", match_transfer_removed, &path); if (r < 0) return log_error_errno(r, "Failed to install match: %m"); r = sd_bus_add_match( bus, &slot_log_message, "type='signal'," "sender='org.freedesktop.import1'," "interface='org.freedesktop.import1.Transfer'," "member='LogMessage'", match_log_message, &path); if (r < 0) return log_error_errno(r, "Failed to install match: %m"); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) { log_error("Failed transfer image: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_read(reply, "uo", &id, &path); if (r < 0) return bus_log_parse_error(r); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); if (!arg_quiet) log_info("Enqueued transfer job %u. Press C-c to continue download in background.", id); sd_event_add_signal(event, NULL, SIGINT, transfer_signal_handler, UINT32_TO_PTR(id)); sd_event_add_signal(event, NULL, SIGTERM, transfer_signal_handler, UINT32_TO_PTR(id)); r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); return -r; } static int import_tar(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_free_ char *ll = NULL; _cleanup_close_ int fd = -1; const char *local = NULL, *path = NULL; sd_bus *bus = userdata; int r; assert(bus); if (argc >= 2) path = argv[1]; if (isempty(path) || streq(path, "-")) path = NULL; if (argc >= 3) local = argv[2]; else if (path) local = basename(path); if (isempty(local) || streq(local, "-")) local = NULL; if (!local) { log_error("Need either path or local name."); return -EINVAL; } r = tar_strip_suffixes(local, &ll); if (r < 0) return log_oom(); local = ll; if (!machine_name_is_valid(local)) { log_error("Local name %s is not a suitable machine name.", local); return -EINVAL; } if (path) { fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return log_error_errno(errno, "Failed to open %s: %m", path); } r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.import1", "/org/freedesktop/import1", "org.freedesktop.import1.Manager", "ImportTar"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append( m, "hsbb", fd >= 0 ? fd : STDIN_FILENO, local, arg_force, arg_read_only); if (r < 0) return bus_log_create_error(r); return transfer_image_common(bus, m); } static int import_raw(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_free_ char *ll = NULL; _cleanup_close_ int fd = -1; const char *local = NULL, *path = NULL; sd_bus *bus = userdata; int r; assert(bus); if (argc >= 2) path = argv[1]; if (isempty(path) || streq(path, "-")) path = NULL; if (argc >= 3) local = argv[2]; else if (path) local = basename(path); if (isempty(local) || streq(local, "-")) local = NULL; if (!local) { log_error("Need either path or local name."); return -EINVAL; } r = raw_strip_suffixes(local, &ll); if (r < 0) return log_oom(); local = ll; if (!machine_name_is_valid(local)) { log_error("Local name %s is not a suitable machine name.", local); return -EINVAL; } if (path) { fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return log_error_errno(errno, "Failed to open %s: %m", path); } r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.import1", "/org/freedesktop/import1", "org.freedesktop.import1.Manager", "ImportRaw"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append( m, "hsbb", fd >= 0 ? fd : STDIN_FILENO, local, arg_force, arg_read_only); if (r < 0) return bus_log_create_error(r); return transfer_image_common(bus, m); } static void determine_compression_from_filename(const char *p) { if (arg_format) return; if (!p) return; if (endswith(p, ".xz")) arg_format = "xz"; else if (endswith(p, ".gz")) arg_format = "gzip"; else if (endswith(p, ".bz2")) arg_format = "bzip2"; } static int export_tar(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_close_ int fd = -1; const char *local = NULL, *path = NULL; sd_bus *bus = userdata; int r; assert(bus); local = argv[1]; if (!machine_name_is_valid(local)) { log_error("Machine name %s is not valid.", local); return -EINVAL; } if (argc >= 3) path = argv[2]; if (isempty(path) || streq(path, "-")) path = NULL; if (path) { determine_compression_from_filename(path); fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666); if (fd < 0) return log_error_errno(errno, "Failed to open %s: %m", path); } r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.import1", "/org/freedesktop/import1", "org.freedesktop.import1.Manager", "ExportTar"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append( m, "shs", local, fd >= 0 ? fd : STDOUT_FILENO, arg_format); if (r < 0) return bus_log_create_error(r); return transfer_image_common(bus, m); } static int export_raw(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_close_ int fd = -1; const char *local = NULL, *path = NULL; sd_bus *bus = userdata; int r; assert(bus); local = argv[1]; if (!machine_name_is_valid(local)) { log_error("Machine name %s is not valid.", local); return -EINVAL; } if (argc >= 3) path = argv[2]; if (isempty(path) || streq(path, "-")) path = NULL; if (path) { determine_compression_from_filename(path); fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666); if (fd < 0) return log_error_errno(errno, "Failed to open %s: %m", path); } r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.import1", "/org/freedesktop/import1", "org.freedesktop.import1.Manager", "ExportRaw"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append( m, "shs", local, fd >= 0 ? fd : STDOUT_FILENO, arg_format); if (r < 0) return bus_log_create_error(r); return transfer_image_common(bus, m); } static int pull_tar(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_free_ char *l = NULL, *ll = NULL; const char *local, *remote; sd_bus *bus = userdata; int r; assert(bus); remote = argv[1]; if (!http_url_is_valid(remote)) { log_error("URL '%s' is not valid.", remote); return -EINVAL; } if (argc >= 3) local = argv[2]; else { r = import_url_last_component(remote, &l); if (r < 0) return log_error_errno(r, "Failed to get final component of URL: %m"); local = l; } if (isempty(local) || streq(local, "-")) local = NULL; if (local) { r = tar_strip_suffixes(local, &ll); if (r < 0) return log_oom(); local = ll; if (!machine_name_is_valid(local)) { log_error("Local name %s is not a suitable machine name.", local); return -EINVAL; } } r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.import1", "/org/freedesktop/import1", "org.freedesktop.import1.Manager", "PullTar"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append( m, "sssb", remote, local, import_verify_to_string(arg_verify), arg_force); if (r < 0) return bus_log_create_error(r); return transfer_image_common(bus, m); } static int pull_raw(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_free_ char *l = NULL, *ll = NULL; const char *local, *remote; sd_bus *bus = userdata; int r; assert(bus); remote = argv[1]; if (!http_url_is_valid(remote)) { log_error("URL '%s' is not valid.", remote); return -EINVAL; } if (argc >= 3) local = argv[2]; else { r = import_url_last_component(remote, &l); if (r < 0) return log_error_errno(r, "Failed to get final component of URL: %m"); local = l; } if (isempty(local) || streq(local, "-")) local = NULL; if (local) { r = raw_strip_suffixes(local, &ll); if (r < 0) return log_oom(); local = ll; if (!machine_name_is_valid(local)) { log_error("Local name %s is not a suitable machine name.", local); return -EINVAL; } } r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.import1", "/org/freedesktop/import1", "org.freedesktop.import1.Manager", "PullRaw"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append( m, "sssb", remote, local, import_verify_to_string(arg_verify), arg_force); if (r < 0) return bus_log_create_error(r); return transfer_image_common(bus, m); } typedef struct TransferInfo { uint32_t id; const char *type; const char *remote; const char *local; double progress; } TransferInfo; static int compare_transfer_info(const void *a, const void *b) { const TransferInfo *x = a, *y = b; return strcmp(x->local, y->local); } static int list_transfers(int argc, char *argv[], void *userdata) { size_t max_type = strlen("TYPE"), max_local = strlen("LOCAL"), max_remote = strlen("REMOTE"); _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ TransferInfo *transfers = NULL; size_t n_transfers = 0, n_allocated = 0, j; const char *type, *remote, *local, *object; sd_bus *bus = userdata; uint32_t id, max_id = 0; double progress; int r; pager_open_if_enabled(); r = sd_bus_call_method( bus, "org.freedesktop.import1", "/org/freedesktop/import1", "org.freedesktop.import1.Manager", "ListTransfers", &error, &reply, NULL); if (r < 0) { log_error("Could not get transfers: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_enter_container(reply, 'a', "(usssdo)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(reply, "(usssdo)", &id, &type, &remote, &local, &progress, &object)) > 0) { size_t l; if (!GREEDY_REALLOC(transfers, n_allocated, n_transfers + 1)) return log_oom(); transfers[n_transfers].id = id; transfers[n_transfers].type = type; transfers[n_transfers].remote = remote; transfers[n_transfers].local = local; transfers[n_transfers].progress = progress; l = strlen(type); if (l > max_type) max_type = l; l = strlen(remote); if (l > max_remote) max_remote = l; l = strlen(local); if (l > max_local) max_local = l; if (id > max_id) max_id = id; n_transfers ++; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); qsort_safe(transfers, n_transfers, sizeof(TransferInfo), compare_transfer_info); if (arg_legend) printf("%-*s %-*s %-*s %-*s %-*s\n", (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), "ID", (int) 7, "PERCENT", (int) max_type, "TYPE", (int) max_local, "LOCAL", (int) max_remote, "REMOTE"); for (j = 0; j < n_transfers; j++) printf("%*" PRIu32 " %*u%% %-*s %-*s %-*s\n", (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), transfers[j].id, (int) 6, (unsigned) (transfers[j].progress * 100), (int) max_type, transfers[j].type, (int) max_local, transfers[j].local, (int) max_remote, transfers[j].remote); if (arg_legend) printf("\n%zu transfers listed.\n", n_transfers); return 0; } static int cancel_transfer(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; int r, i; assert(bus); polkit_agent_open_if_enabled(); for (i = 1; i < argc; i++) { uint32_t id; r = safe_atou32(argv[i], &id); if (r < 0) return log_error_errno(r, "Failed to parse transfer id: %s", argv[i]); r = sd_bus_call_method( bus, "org.freedesktop.import1", "/org/freedesktop/import1", "org.freedesktop.import1.Manager", "CancelTransfer", &error, NULL, "u", id); if (r < 0) { log_error("Could not cancel transfer: %s", bus_error_message(&error, -r)); return r; } } return 0; } static int set_limit(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus = userdata; uint64_t limit; int r; if (STR_IN_SET(argv[argc-1], "-", "none", "infinity")) limit = (uint64_t) -1; else { r = parse_size(argv[argc-1], 1024, &limit); if (r < 0) return log_error("Failed to parse size: %s", argv[argc-1]); } if (argc > 2) /* With two arguments changes the quota limit of the * specified image */ r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "SetImageLimit", &error, NULL, "st", argv[1], limit); else /* With one argument changes the pool quota limit */ r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "SetPoolLimit", &error, NULL, "t", limit); if (r < 0) { log_error("Could not set limit: %s", bus_error_message(&error, -r)); return r; } return 0; } static int help(int argc, char *argv[], void *userdata) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" "Send control commands to or query the virtual machine and container\n" "registration manager.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " --no-legend Do not show the headers and footers\n" " --no-ask-password Do not ask for system passwords\n" " -H --host=[USER@]HOST Operate on remote host\n" " -M --machine=CONTAINER Operate on local container\n" " -p --property=NAME Show only properties by this name\n" " -q --quiet Suppress output\n" " -a --all Show all properties, including empty ones\n" " -l --full Do not ellipsize output\n" " --kill-who=WHO Who to send signal to\n" " -s --signal=SIGNAL Which signal to send\n" " --uid=USER Specify user ID to invoke shell as\n" " --setenv=VAR=VALUE Add an environment variable for shell\n" " --read-only Create read-only bind mount\n" " --mkdir Create directory before bind mounting, if missing\n" " -n --lines=INTEGER Number of journal entries to show\n" " -o --output=STRING Change journal output mode (short,\n" " short-monotonic, verbose, export, json,\n" " json-pretty, json-sse, cat)\n" " --verify=MODE Verification mode for downloaded images (no,\n" " checksum, signature)\n" " --force Download image even if already exists\n\n" "Machine Commands:\n" " list List running VMs and containers\n" " status NAME... Show VM/container details\n" " show [NAME...] Show properties of one or more VMs/containers\n" " start NAME... Start container as a service\n" " login [NAME] Get a login prompt in a container or on the\n" " local host\n" " shell [[USER@]NAME [COMMAND...]]\n" " Invoke a shell (or other command) in a container\n" " or on the local host\n" " enable NAME... Enable automatic container start at boot\n" " disable NAME... Disable automatic container start at boot\n" " poweroff NAME... Power off one or more containers\n" " reboot NAME... Reboot one or more containers\n" " terminate NAME... Terminate one or more VMs/containers\n" " kill NAME... Send signal to processes of a VM/container\n" " copy-to NAME PATH [PATH] Copy files from the host to a container\n" " copy-from NAME PATH [PATH] Copy files from a container to the host\n" " bind NAME PATH [PATH] Bind mount a path from the host into a container\n\n" "Image Commands:\n" " list-images Show available container and VM images\n" " image-status [NAME...] Show image details\n" " show-image [NAME...] Show properties of image\n" " clone NAME NAME Clone an image\n" " rename NAME NAME Rename an image\n" " read-only NAME [BOOL] Mark or unmark image read-only\n" " remove NAME... Remove an image\n" " set-limit [NAME] BYTES Set image or pool size limit (disk quota)\n\n" "Image Transfer Commands:\n" " pull-tar URL [NAME] Download a TAR container image\n" " pull-raw URL [NAME] Download a RAW container or VM image\n" " import-tar FILE [NAME] Import a local TAR container image\n" " import-raw FILE [NAME] Import a local RAW container or VM image\n" " export-tar NAME [FILE] Export a TAR container image locally\n" " export-raw NAME [FILE] Export a RAW container or VM image locally\n" " list-transfers Show list of downloads in progress\n" " cancel-transfer Cancel a download\n" , program_invocation_short_name); return 0; } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_LEGEND, ARG_KILL_WHO, ARG_READ_ONLY, ARG_MKDIR, ARG_NO_ASK_PASSWORD, ARG_VERIFY, ARG_FORCE, ARG_FORMAT, ARG_UID, ARG_SETENV, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "property", required_argument, NULL, 'p' }, { "all", no_argument, NULL, 'a' }, { "full", no_argument, NULL, 'l' }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, { "kill-who", required_argument, NULL, ARG_KILL_WHO }, { "signal", required_argument, NULL, 's' }, { "host", required_argument, NULL, 'H' }, { "machine", required_argument, NULL, 'M' }, { "read-only", no_argument, NULL, ARG_READ_ONLY }, { "mkdir", no_argument, NULL, ARG_MKDIR }, { "quiet", no_argument, NULL, 'q' }, { "lines", required_argument, NULL, 'n' }, { "output", required_argument, NULL, 'o' }, { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, { "verify", required_argument, NULL, ARG_VERIFY }, { "force", no_argument, NULL, ARG_FORCE }, { "format", required_argument, NULL, ARG_FORMAT }, { "uid", required_argument, NULL, ARG_UID }, { "setenv", required_argument, NULL, ARG_SETENV }, {} }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "hp:als:H:M:qn:o:", options, NULL)) >= 0) switch (c) { case 'h': return help(0, NULL, NULL); case ARG_VERSION: return version(); case 'p': r = strv_extend(&arg_property, optarg); if (r < 0) return log_oom(); /* If the user asked for a particular * property, show it to him, even if it is * empty. */ arg_all = true; break; case 'a': arg_all = true; break; case 'l': arg_full = true; break; case 'n': if (safe_atou(optarg, &arg_lines) < 0) { log_error("Failed to parse lines '%s'", optarg); return -EINVAL; } break; case 'o': arg_output = output_mode_from_string(optarg); if (arg_output < 0) { log_error("Unknown output '%s'.", optarg); return -EINVAL; } break; case ARG_NO_PAGER: arg_no_pager = true; break; case ARG_NO_LEGEND: arg_legend = false; break; case ARG_KILL_WHO: arg_kill_who = optarg; break; case 's': arg_signal = signal_from_string_try_harder(optarg); if (arg_signal < 0) { log_error("Failed to parse signal string %s.", optarg); return -EINVAL; } break; case ARG_NO_ASK_PASSWORD: arg_ask_password = false; break; case 'H': arg_transport = BUS_TRANSPORT_REMOTE; arg_host = optarg; break; case 'M': arg_transport = BUS_TRANSPORT_MACHINE; arg_host = optarg; break; case ARG_READ_ONLY: arg_read_only = true; break; case ARG_MKDIR: arg_mkdir = true; break; case 'q': arg_quiet = true; break; case ARG_VERIFY: arg_verify = import_verify_from_string(optarg); if (arg_verify < 0) { log_error("Failed to parse --verify= setting: %s", optarg); return -EINVAL; } break; case ARG_FORCE: arg_force = true; break; case ARG_FORMAT: if (!STR_IN_SET(optarg, "uncompressed", "xz", "gzip", "bzip2")) { log_error("Unknown format: %s", optarg); return -EINVAL; } arg_format = optarg; break; case ARG_UID: arg_uid = optarg; break; case ARG_SETENV: if (!env_assignment_is_valid(optarg)) { log_error("Environment assignment invalid: %s", optarg); return -EINVAL; } r = strv_extend(&arg_setenv, optarg); if (r < 0) return log_oom(); break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } static int machinectl_main(int argc, char *argv[], sd_bus *bus) { static const Verb verbs[] = { { "help", VERB_ANY, VERB_ANY, 0, help }, { "list", VERB_ANY, 1, VERB_DEFAULT, list_machines }, { "list-images", VERB_ANY, 1, 0, list_images }, { "status", 2, VERB_ANY, 0, show_machine }, { "image-status", VERB_ANY, VERB_ANY, 0, show_image }, { "show", VERB_ANY, VERB_ANY, 0, show_machine }, { "show-image", VERB_ANY, VERB_ANY, 0, show_image }, { "terminate", 2, VERB_ANY, 0, terminate_machine }, { "reboot", 2, VERB_ANY, 0, reboot_machine }, { "poweroff", 2, VERB_ANY, 0, poweroff_machine }, { "kill", 2, VERB_ANY, 0, kill_machine }, { "login", VERB_ANY, 2, 0, login_machine }, { "shell", VERB_ANY, VERB_ANY, 0, shell_machine }, { "bind", 3, 4, 0, bind_mount }, { "copy-to", 3, 4, 0, copy_files }, { "copy-from", 3, 4, 0, copy_files }, { "remove", 2, VERB_ANY, 0, remove_image }, { "rename", 3, 3, 0, rename_image }, { "clone", 3, 3, 0, clone_image }, { "read-only", 2, 3, 0, read_only_image }, { "start", 2, VERB_ANY, 0, start_machine }, { "enable", 2, VERB_ANY, 0, enable_machine }, { "disable", 2, VERB_ANY, 0, enable_machine }, { "import-tar", 2, 3, 0, import_tar }, { "import-raw", 2, 3, 0, import_raw }, { "export-tar", 2, 3, 0, export_tar }, { "export-raw", 2, 3, 0, export_raw }, { "pull-tar", 2, 3, 0, pull_tar }, { "pull-raw", 2, 3, 0, pull_raw }, { "list-transfers", VERB_ANY, 1, 0, list_transfers }, { "cancel-transfer", 2, VERB_ANY, 0, cancel_transfer }, { "set-limit", 2, 3, 0, set_limit }, {} }; return dispatch_verb(argc, argv, verbs, bus); } int main(int argc, char*argv[]) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = bus_connect_transport(arg_transport, arg_host, false, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; } sd_bus_set_allow_interactive_authorization(bus, arg_ask_password); r = machinectl_main(argc, argv, bus); finish: pager_close(); polkit_agent_close(); strv_free(arg_property); strv_free(arg_setenv); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/machine/machined-dbus.c000066400000000000000000001452451265713322000201360ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-id128.h" #include "alloc-util.h" #include "btrfs-util.h" #include "bus-common-errors.h" #include "bus-util.h" #include "cgroup-util.h" #include "fd-util.h" #include "formats-util.h" #include "hostname-util.h" #include "image-dbus.h" #include "io-util.h" #include "machine-dbus.h" #include "machine-image.h" #include "machine-pool.h" #include "machined.h" #include "path-util.h" #include "process-util.h" #include "stdio-util.h" #include "strv.h" #include "unit-name.h" #include "user-util.h" static int property_get_pool_path( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { assert(bus); assert(reply); return sd_bus_message_append(reply, "s", "/var/lib/machines"); } static int property_get_pool_usage( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_close_ int fd = -1; uint64_t usage = (uint64_t) -1; struct stat st; assert(bus); assert(reply); /* We try to read the quota info from /var/lib/machines, as * well as the usage of the loopback file * /var/lib/machines.raw, and pick the larger value. */ fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY); if (fd >= 0) { BtrfsQuotaInfo q; if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0) usage = q.referenced; } if (stat("/var/lib/machines.raw", &st) >= 0) { if (usage == (uint64_t) -1 || st.st_blocks * 512ULL > usage) usage = st.st_blocks * 512ULL; } return sd_bus_message_append(reply, "t", usage); } static int property_get_pool_limit( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_close_ int fd = -1; uint64_t size = (uint64_t) -1; struct stat st; assert(bus); assert(reply); /* We try to read the quota limit from /var/lib/machines, as * well as the size of the loopback file * /var/lib/machines.raw, and pick the smaller value. */ fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY); if (fd >= 0) { BtrfsQuotaInfo q; if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0) size = q.referenced_max; } if (stat("/var/lib/machines.raw", &st) >= 0) { if (size == (uint64_t) -1 || (uint64_t) st.st_size < size) size = st.st_size; } return sd_bus_message_append(reply, "t", size); } static int method_get_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Manager *m = userdata; Machine *machine; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; machine = hashmap_get(m->machines, name); if (!machine) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); p = machine_bus_path(machine); if (!p) return -ENOMEM; return sd_bus_reply_method_return(message, "o", p); } static int method_get_image(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Manager *m = userdata; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = image_find(name, NULL); if (r == 0) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name); if (r < 0) return r; p = image_bus_path(name); if (!p) return -ENOMEM; return sd_bus_reply_method_return(message, "o", p); } static int method_get_machine_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Manager *m = userdata; Machine *machine = NULL; pid_t pid; int r; assert(message); assert(m); assert_cc(sizeof(pid_t) == sizeof(uint32_t)); r = sd_bus_message_read(message, "u", &pid); if (r < 0) return r; if (pid < 0) return -EINVAL; if (pid == 0) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); if (r < 0) return r; r = sd_bus_creds_get_pid(creds, &pid); if (r < 0) return r; } r = manager_get_machine_by_pid(m, pid, &machine); if (r < 0) return r; if (!machine) return sd_bus_error_setf(error, BUS_ERROR_NO_MACHINE_FOR_PID, "PID "PID_FMT" does not belong to any known machine", pid); p = machine_bus_path(machine); if (!p) return -ENOMEM; return sd_bus_reply_method_return(message, "o", p); } static int method_list_machines(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; Machine *machine; Iterator i; int r; assert(message); assert(m); r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return sd_bus_error_set_errno(error, r); r = sd_bus_message_open_container(reply, 'a', "(ssso)"); if (r < 0) return sd_bus_error_set_errno(error, r); HASHMAP_FOREACH(machine, m->machines, i) { _cleanup_free_ char *p = NULL; p = machine_bus_path(machine); if (!p) return -ENOMEM; r = sd_bus_message_append(reply, "(ssso)", machine->name, strempty(machine_class_to_string(machine->class)), machine->service, p); if (r < 0) return sd_bus_error_set_errno(error, r); } r = sd_bus_message_close_container(reply); if (r < 0) return sd_bus_error_set_errno(error, r); return sd_bus_send(NULL, reply, NULL); } static int method_create_or_register_machine(Manager *manager, sd_bus_message *message, bool read_network, Machine **_m, sd_bus_error *error) { const char *name, *service, *class, *root_directory; const int32_t *netif = NULL; MachineClass c; uint32_t leader; sd_id128_t id; const void *v; Machine *m; size_t n, n_netif = 0; int r; assert(manager); assert(message); assert(_m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; if (!machine_name_is_valid(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name"); r = sd_bus_message_read_array(message, 'y', &v, &n); if (r < 0) return r; if (n == 0) id = SD_ID128_NULL; else if (n == 16) memcpy(&id, v, n); else return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter"); r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory); if (r < 0) return r; if (read_network) { size_t i; r = sd_bus_message_read_array(message, 'i', (const void**) &netif, &n_netif); if (r < 0) return r; n_netif /= sizeof(int32_t); for (i = 0; i < n_netif; i++) { if (netif[i] <= 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid network interface index %i", netif[i]); } } if (isempty(class)) c = _MACHINE_CLASS_INVALID; else { c = machine_class_from_string(class); if (c < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter"); } if (leader == 1) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID"); if (!isempty(root_directory) && !path_is_absolute(root_directory)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path"); if (leader == 0) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); if (r < 0) return r; assert_cc(sizeof(uint32_t) == sizeof(pid_t)); r = sd_bus_creds_get_pid(creds, (pid_t*) &leader); if (r < 0) return r; } if (hashmap_get(manager->machines, name)) return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name); r = manager_add_machine(manager, name, &m); if (r < 0) return r; m->leader = leader; m->class = c; m->id = id; if (!isempty(service)) { m->service = strdup(service); if (!m->service) { r = -ENOMEM; goto fail; } } if (!isempty(root_directory)) { m->root_directory = strdup(root_directory); if (!m->root_directory) { r = -ENOMEM; goto fail; } } if (n_netif > 0) { assert_cc(sizeof(int32_t) == sizeof(int)); m->netif = memdup(netif, sizeof(int32_t) * n_netif); if (!m->netif) { r = -ENOMEM; goto fail; } m->n_netif = n_netif; } *_m = m; return 1; fail: machine_add_to_gc_queue(m); return r; } static int method_create_machine_internal(sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) { Manager *manager = userdata; Machine *m = NULL; int r; assert(message); assert(manager); r = method_create_or_register_machine(manager, message, read_network, &m, error); if (r < 0) return r; r = sd_bus_message_enter_container(message, 'a', "(sv)"); if (r < 0) goto fail; r = machine_start(m, message, error); if (r < 0) goto fail; m->create_message = sd_bus_message_ref(message); return 1; fail: machine_add_to_gc_queue(m); return r; } static int method_create_machine_with_network(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_create_machine_internal(message, true, userdata, error); } static int method_create_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_create_machine_internal(message, false, userdata, error); } static int method_register_machine_internal(sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) { Manager *manager = userdata; _cleanup_free_ char *p = NULL; Machine *m = NULL; int r; assert(message); assert(manager); r = method_create_or_register_machine(manager, message, read_network, &m, error); if (r < 0) return r; r = cg_pid_get_unit(m->leader, &m->unit); if (r < 0) { r = sd_bus_error_set_errnof(error, r, "Failed to determine unit of process "PID_FMT" : %s", m->leader, strerror(-r)); goto fail; } r = machine_start(m, NULL, error); if (r < 0) goto fail; p = machine_bus_path(m); if (!p) { r = -ENOMEM; goto fail; } return sd_bus_reply_method_return(message, "o", p); fail: machine_add_to_gc_queue(m); return r; } static int method_register_machine_with_network(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_register_machine_internal(message, true, userdata, error); } static int method_register_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { return method_register_machine_internal(message, false, userdata, error); } static int method_terminate_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Machine *machine; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return sd_bus_error_set_errno(error, r); machine = hashmap_get(m->machines, name); if (!machine) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); return bus_machine_method_terminate(message, machine, error); } static int method_kill_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Machine *machine; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return sd_bus_error_set_errno(error, r); machine = hashmap_get(m->machines, name); if (!machine) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); return bus_machine_method_kill(message, machine, error); } static int method_get_machine_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Machine *machine; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return sd_bus_error_set_errno(error, r); machine = hashmap_get(m->machines, name); if (!machine) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); return bus_machine_method_get_addresses(message, machine, error); } static int method_get_machine_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Machine *machine; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return sd_bus_error_set_errno(error, r); machine = hashmap_get(m->machines, name); if (!machine) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); return bus_machine_method_get_os_release(message, machine, error); } static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(image_hashmap_freep) Hashmap *images = NULL; Manager *m = userdata; Image *image; Iterator i; int r; assert(message); assert(m); images = hashmap_new(&string_hash_ops); if (!images) return -ENOMEM; r = image_discover(images); if (r < 0) return r; r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "(ssbttto)"); if (r < 0) return r; HASHMAP_FOREACH(image, images, i) { _cleanup_free_ char *p = NULL; p = image_bus_path(image->name); if (!p) return -ENOMEM; r = sd_bus_message_append(reply, "(ssbttto)", image->name, image_type_to_string(image->type), image->read_only, image->crtime, image->mtime, image->usage, p); if (r < 0) return r; } r = sd_bus_message_close_container(reply); if (r < 0) return r; return sd_bus_send(NULL, reply, NULL); } static int method_open_machine_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Machine *machine; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return sd_bus_error_set_errno(error, r); machine = hashmap_get(m->machines, name); if (!machine) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); return bus_machine_method_open_pty(message, machine, error); } static int method_open_machine_login(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Machine *machine; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; machine = hashmap_get(m->machines, name); if (!machine) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); return bus_machine_method_open_login(message, machine, error); } static int method_open_machine_shell(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Machine *machine; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; machine = hashmap_get(m->machines, name); if (!machine) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); return bus_machine_method_open_shell(message, machine, error); } static int method_bind_mount_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Machine *machine; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; machine = hashmap_get(m->machines, name); if (!machine) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); return bus_machine_method_bind_mount(message, machine, error); } static int method_copy_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Machine *machine; const char *name; int r; assert(message); assert(m); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; machine = hashmap_get(m->machines, name); if (!machine) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); return bus_machine_method_copy(message, machine, error); } static int method_remove_image(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(image_unrefp) Image* i = NULL; const char *name; int r; assert(message); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; if (!image_name_is_valid(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name); r = image_find(name, &i); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name); i->userdata = userdata; return bus_image_method_remove(message, i, error); } static int method_rename_image(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(image_unrefp) Image* i = NULL; const char *old_name; int r; assert(message); r = sd_bus_message_read(message, "s", &old_name); if (r < 0) return r; if (!image_name_is_valid(old_name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name); r = image_find(old_name, &i); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name); i->userdata = userdata; return bus_image_method_rename(message, i, error); } static int method_clone_image(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(image_unrefp) Image *i = NULL; const char *old_name; int r; assert(message); r = sd_bus_message_read(message, "s", &old_name); if (r < 0) return r; if (!image_name_is_valid(old_name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name); r = image_find(old_name, &i); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name); i->userdata = userdata; return bus_image_method_clone(message, i, error); } static int method_mark_image_read_only(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(image_unrefp) Image *i = NULL; const char *name; int r; assert(message); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; if (!image_name_is_valid(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name); r = image_find(name, &i); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name); i->userdata = userdata; return bus_image_method_mark_read_only(message, i, error); } static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; uint64_t limit; int r; assert(message); r = sd_bus_message_read(message, "t", &limit); if (r < 0) return r; if (!FILE_SIZE_VALID_OR_INFINITY(limit)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range"); r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, "org.freedesktop.machine1.manage-machines", NULL, false, UID_INVALID, &m->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* Will call us back */ /* Set up the machine directory if necessary */ r = setup_machine_directory(limit, error); if (r < 0) return r; /* Resize the backing loopback device, if there is one, except if we asked to drop any limit */ if (limit != (uint64_t) -1) { r = btrfs_resize_loopback("/var/lib/machines", limit, false); if (r == -ENOTTY) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs."); if (r < 0 && r != -ENODEV) /* ignore ENODEV, as that's what is returned if the file system is not on loopback */ return sd_bus_error_set_errnof(error, r, "Failed to adjust loopback limit: %m"); } (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, limit); r = btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, limit); if (r == -ENOTTY) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs."); if (r < 0) return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m"); return sd_bus_reply_method_return(message, NULL); } static int method_set_image_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(image_unrefp) Image *i = NULL; const char *name; int r; assert(message); r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; if (!image_name_is_valid(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name); r = image_find(name, &i); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name); i->userdata = userdata; return bus_image_method_set_limit(message, i, error); } static int method_map_from_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_fclose_ FILE *f = NULL; Manager *m = userdata; const char *name, *p; Machine *machine; uint32_t uid; int r; r = sd_bus_message_read(message, "su", &name, &uid); if (r < 0) return r; if (!uid_is_valid(uid)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid); machine = hashmap_get(m->machines, name); if (!machine) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); if (machine->class != MACHINE_CONTAINER) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines."); p = procfs_file_alloca(machine->leader, "uid_map"); f = fopen(p, "re"); if (!f) return -errno; for (;;) { uid_t uid_base, uid_shift, uid_range, converted; int k; errno = 0; k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range); if (k < 0 && feof(f)) break; if (k != 3) { if (ferror(f) && errno > 0) return -errno; return -EIO; } if (uid < uid_base || uid >= uid_base + uid_range) continue; converted = uid - uid_base + uid_shift; if (!uid_is_valid(converted)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid); return sd_bus_reply_method_return(message, "u", (uint32_t) converted); } return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "Machine '%s' has no matching user mappings.", name); } static int method_map_to_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Machine *machine; uid_t uid; Iterator i; int r; r = sd_bus_message_read(message, "u", &uid); if (r < 0) return r; if (!uid_is_valid(uid)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid); if (uid < 0x10000) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "User " UID_FMT " belongs to host UID range", uid); HASHMAP_FOREACH(machine, m->machines, i) { _cleanup_fclose_ FILE *f = NULL; char p[strlen("/proc//uid_map") + DECIMAL_STR_MAX(pid_t) + 1]; if (machine->class != MACHINE_CONTAINER) continue; xsprintf(p, "/proc/" UID_FMT "/uid_map", machine->leader); f = fopen(p, "re"); if (!f) { log_warning_errno(errno, "Failed top open %s, ignoring,", p); continue; } for (;;) { _cleanup_free_ char *o = NULL; uid_t uid_base, uid_shift, uid_range, converted; int k; errno = 0; k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range); if (k < 0 && feof(f)) break; if (k != 3) { if (ferror(f) && errno > 0) return -errno; return -EIO; } if (uid < uid_shift || uid >= uid_shift + uid_range) continue; converted = (uid - uid_shift + uid_base); if (!uid_is_valid(converted)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid); o = machine_bus_path(machine); if (!o) return -ENOMEM; return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted); } } return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "No matching user mapping for " UID_FMT ".", uid); } static int method_map_from_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) { _cleanup_fclose_ FILE *f = NULL; Manager *m = groupdata; const char *name, *p; Machine *machine; uint32_t gid; int r; r = sd_bus_message_read(message, "su", &name, &gid); if (r < 0) return r; if (!gid_is_valid(gid)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid); machine = hashmap_get(m->machines, name); if (!machine) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); if (machine->class != MACHINE_CONTAINER) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines."); p = procfs_file_alloca(machine->leader, "gid_map"); f = fopen(p, "re"); if (!f) return -errno; for (;;) { gid_t gid_base, gid_shift, gid_range, converted; int k; errno = 0; k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range); if (k < 0 && feof(f)) break; if (k != 3) { if (ferror(f) && errno > 0) return -errno; return -EIO; } if (gid < gid_base || gid >= gid_base + gid_range) continue; converted = gid - gid_base + gid_shift; if (!gid_is_valid(converted)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid); return sd_bus_reply_method_return(message, "u", (uint32_t) converted); } return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Machine '%s' has no matching group mappings.", name); } static int method_map_to_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) { Manager *m = groupdata; Machine *machine; gid_t gid; Iterator i; int r; r = sd_bus_message_read(message, "u", &gid); if (r < 0) return r; if (!gid_is_valid(gid)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid); if (gid < 0x10000) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Group " GID_FMT " belongs to host GID range", gid); HASHMAP_FOREACH(machine, m->machines, i) { _cleanup_fclose_ FILE *f = NULL; char p[strlen("/proc//gid_map") + DECIMAL_STR_MAX(pid_t) + 1]; if (machine->class != MACHINE_CONTAINER) continue; xsprintf(p, "/proc/" GID_FMT "/gid_map", machine->leader); f = fopen(p, "re"); if (!f) { log_warning_errno(errno, "Failed top open %s, ignoring,", p); continue; } for (;;) { _cleanup_free_ char *o = NULL; gid_t gid_base, gid_shift, gid_range, converted; int k; errno = 0; k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range); if (k < 0 && feof(f)) break; if (k != 3) { if (ferror(f) && errno > 0) return -errno; return -EIO; } if (gid < gid_shift || gid >= gid_shift + gid_range) continue; converted = (gid - gid_shift + gid_base); if (!gid_is_valid(converted)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid); o = machine_bus_path(machine); if (!o) return -ENOMEM; return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted); } } return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "No matching group mapping for " GID_FMT ".", gid); } const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0), SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0), SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0), SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ListImages", NULL, "a(ssbttto)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0), SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0), SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0), SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0), SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0), SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("OpenMachineShell", "sssasas", "hs", method_open_machine_shell, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("BindMountMachine", "sssbb", NULL, method_bind_mount_machine, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CopyFromMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CopyToMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("RenameImage", "ss", NULL, method_rename_image, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CloneImage", "ssb", NULL, method_clone_image, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("MapFromMachineUser", "su", "u", method_map_from_machine_user, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("MapToMachineUser", "u", "sou", method_map_to_machine_user, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("MapFromMachineGroup", "su", "u", method_map_from_machine_group, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("MapToMachineGroup", "u", "sou", method_map_to_machine_group, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("MachineNew", "so", 0), SD_BUS_SIGNAL("MachineRemoved", "so", 0), SD_BUS_VTABLE_END }; int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *path, *result, *unit; Manager *m = userdata; Machine *machine; uint32_t id; int r; assert(message); assert(m); r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result); if (r < 0) { bus_log_parse_error(r); return 0; } machine = hashmap_get(m->machine_units, unit); if (!machine) return 0; if (streq_ptr(path, machine->scope_job)) { machine->scope_job = mfree(machine->scope_job); if (machine->started) { if (streq(result, "done")) machine_send_create_reply(machine, NULL); else { _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL; sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result); machine_send_create_reply(machine, &e); } } machine_save(machine); } machine_add_to_gc_queue(machine); return 0; } int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *unit = NULL; const char *path; Manager *m = userdata; Machine *machine; int r; assert(message); assert(m); path = sd_bus_message_get_path(message); if (!path) return 0; r = unit_name_from_dbus_path(path, &unit); if (r == -EINVAL) /* not for a unit */ return 0; if (r < 0){ log_oom(); return 0; } machine = hashmap_get(m->machine_units, unit); if (!machine) return 0; machine_add_to_gc_queue(machine); return 0; } int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *path, *unit; Manager *m = userdata; Machine *machine; int r; assert(message); assert(m); r = sd_bus_message_read(message, "so", &unit, &path); if (r < 0) { bus_log_parse_error(r); return 0; } machine = hashmap_get(m->machine_units, unit); if (!machine) return 0; machine_add_to_gc_queue(machine); return 0; } int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; Machine *machine; Iterator i; int b, r; assert(message); assert(m); r = sd_bus_message_read(message, "b", &b); if (r < 0) { bus_log_parse_error(r); return 0; } if (b) return 0; /* systemd finished reloading, let's recheck all our machines */ log_debug("System manager has been reloaded, rechecking machines..."); HASHMAP_FOREACH(machine, m->machines, i) machine_add_to_gc_queue(machine); return 0; } int manager_start_scope( Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, sd_bus_message *more_properties, sd_bus_error *error, char **job) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; int r; assert(manager); assert(scope); assert(pid > 1); r = sd_bus_message_new_method_call( manager->bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartTransientUnit"); if (r < 0) return r; r = sd_bus_message_append(m, "ss", strempty(scope), "fail"); if (r < 0) return r; r = sd_bus_message_open_container(m, 'a', "(sv)"); if (r < 0) return r; if (!isempty(slice)) { r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice); if (r < 0) return r; } if (!isempty(description)) { r = sd_bus_message_append(m, "(sv)", "Description", "s", description); if (r < 0) return r; } r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid); if (r < 0) return r; r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1); if (r < 0) return r; r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", UINT64_C(16384)); if (r < 0) return bus_log_create_error(r); if (more_properties) { r = sd_bus_message_copy(m, more_properties, true); if (r < 0) return r; } r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_append(m, "a(sa(sv))", 0); if (r < 0) return r; r = sd_bus_call(manager->bus, m, 0, error, &reply); if (r < 0) return r; if (job) { const char *j; char *copy; r = sd_bus_message_read(reply, "o", &j); if (r < 0) return r; copy = strdup(j); if (!copy) return -ENOMEM; *job = copy; } return 1; } int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(manager); assert(unit); r = sd_bus_call_method( manager->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StopUnit", error, &reply, "ss", unit, "fail"); if (r < 0) { if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) || sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) { if (job) *job = NULL; sd_bus_error_free(error); return 0; } return r; } if (job) { const char *j; char *copy; r = sd_bus_message_read(reply, "o", &j); if (r < 0) return r; copy = strdup(j); if (!copy) return -ENOMEM; *job = copy; } return 1; } int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) { assert(manager); assert(unit); return sd_bus_call_method( manager->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "KillUnit", error, NULL, "ssi", unit, "all", signo); } int manager_unit_is_active(Manager *manager, const char *unit) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *path = NULL; const char *state; int r; assert(manager); assert(unit); path = unit_dbus_path_from_name(unit); if (!path) return -ENOMEM; r = sd_bus_get_property( manager->bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Unit", "ActiveState", &error, &reply, "s"); if (r < 0) { if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) return true; if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) || sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) return false; return r; } r = sd_bus_message_read(reply, "s", &state); if (r < 0) return -EINVAL; return !STR_IN_SET(state, "inactive", "failed"); } int manager_job_is_active(Manager *manager, const char *path) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(manager); assert(path); r = sd_bus_get_property( manager->bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Job", "State", &error, &reply, "s"); if (r < 0) { if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) return true; if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT)) return false; return r; } /* We don't actually care about the state really. The fact * that we could read the job state is enough for us */ return true; } int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) { Machine *mm; int r; assert(m); assert(pid >= 1); assert(machine); mm = hashmap_get(m->machine_leaders, PID_TO_PTR(pid)); if (!mm) { _cleanup_free_ char *unit = NULL; r = cg_pid_get_unit(pid, &unit); if (r >= 0) mm = hashmap_get(m->machine_units, unit); } if (!mm) return 0; *machine = mm; return 1; } int manager_add_machine(Manager *m, const char *name, Machine **_machine) { Machine *machine; assert(m); assert(name); machine = hashmap_get(m->machines, name); if (!machine) { machine = machine_new(m, _MACHINE_CLASS_INVALID, name); if (!machine) return -ENOMEM; } if (_machine) *_machine = machine; return 0; } systemd-229/src/machine/machined.c000066400000000000000000000306201265713322000171710ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-daemon.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "cgroup-util.h" #include "dirent-util.h" #include "fd-util.h" #include "formats-util.h" #include "hostname-util.h" #include "label.h" #include "machine-image.h" #include "machined.h" #include "signal-util.h" Manager *manager_new(void) { Manager *m; int r; m = new0(Manager, 1); if (!m) return NULL; m->machines = hashmap_new(&string_hash_ops); m->machine_units = hashmap_new(&string_hash_ops); m->machine_leaders = hashmap_new(NULL); if (!m->machines || !m->machine_units || !m->machine_leaders) { manager_free(m); return NULL; } r = sd_event_default(&m->event); if (r < 0) { manager_free(m); return NULL; } sd_event_set_watchdog(m->event, true); return m; } void manager_free(Manager *m) { Machine *machine; Image *i; assert(m); while ((machine = hashmap_first(m->machines))) machine_free(machine); hashmap_free(m->machines); hashmap_free(m->machine_units); hashmap_free(m->machine_leaders); while ((i = hashmap_steal_first(m->image_cache))) image_unref(i); hashmap_free(m->image_cache); sd_event_source_unref(m->image_cache_defer_event); bus_verify_polkit_async_registry_free(m->polkit_registry); sd_bus_unref(m->bus); sd_event_unref(m->event); free(m); } static int manager_add_host_machine(Manager *m) { _cleanup_free_ char *rd = NULL, *unit = NULL; sd_id128_t mid; Machine *t; int r; if (m->host_machine) return 0; r = sd_id128_get_machine(&mid); if (r < 0) return log_error_errno(r, "Failed to get machine ID: %m"); rd = strdup("/"); if (!rd) return log_oom(); unit = strdup("-.slice"); if (!unit) return log_oom(); t = machine_new(m, MACHINE_HOST, ".host"); if (!t) return log_oom(); t->leader = 1; t->id = mid; t->root_directory = rd; t->unit = unit; rd = unit = NULL; dual_timestamp_from_boottime_or_monotonic(&t->timestamp, 0); m->host_machine = t; return 0; } int manager_enumerate_machines(Manager *m) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0; assert(m); r = manager_add_host_machine(m); if (r < 0) return r; /* Read in machine data stored on disk */ d = opendir("/run/systemd/machines"); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open /run/systemd/machines: %m"); } FOREACH_DIRENT(de, d, return -errno) { struct Machine *machine; int k; if (!dirent_is_file(de)) continue; /* Ignore symlinks that map the unit name to the machine */ if (startswith(de->d_name, "unit:")) continue; if (!machine_name_is_valid(de->d_name)) continue; k = manager_add_machine(m, de->d_name, &machine); if (k < 0) { r = log_error_errno(k, "Failed to add machine by file name %s: %m", de->d_name); continue; } machine_add_to_gc_queue(machine); k = machine_load(machine); if (k < 0) r = k; } return r; } static int manager_connect_bus(Manager *m) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(m); assert(!m->bus); r = sd_bus_default_system(&m->bus); if (r < 0) return log_error_errno(r, "Failed to connect to system bus: %m"); r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m); if (r < 0) return log_error_errno(r, "Failed to add manager object vtable: %m"); r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m); if (r < 0) return log_error_errno(r, "Failed to add machine object vtable: %m"); r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/machine", machine_node_enumerator, m); if (r < 0) return log_error_errno(r, "Failed to add machine enumerator: %m"); r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/image", "org.freedesktop.machine1.Image", image_vtable, image_object_find, m); if (r < 0) return log_error_errno(r, "Failed to add image object vtable: %m"); r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/image", image_node_enumerator, m); if (r < 0) return log_error_errno(r, "Failed to add image enumerator: %m"); r = sd_bus_add_match(m->bus, NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," "member='JobRemoved'," "path='/org/freedesktop/systemd1'", match_job_removed, m); if (r < 0) return log_error_errno(r, "Failed to add match for JobRemoved: %m"); r = sd_bus_add_match(m->bus, NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," "member='UnitRemoved'," "path='/org/freedesktop/systemd1'", match_unit_removed, m); if (r < 0) return log_error_errno(r, "Failed to add match for UnitRemoved: %m"); r = sd_bus_add_match(m->bus, NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.DBus.Properties'," "member='PropertiesChanged'," "arg0='org.freedesktop.systemd1.Unit'", match_properties_changed, m); if (r < 0) return log_error_errno(r, "Failed to add match for PropertiesChanged: %m"); r = sd_bus_add_match(m->bus, NULL, "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," "member='Reloading'," "path='/org/freedesktop/systemd1'", match_reloading, m); if (r < 0) return log_error_errno(r, "Failed to add match for Reloading: %m"); r = sd_bus_call_method( m->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Subscribe", &error, NULL, NULL); if (r < 0) { log_error("Failed to enable subscription: %s", bus_error_message(&error, r)); return r; } r = sd_bus_request_name(m->bus, "org.freedesktop.machine1", 0); if (r < 0) return log_error_errno(r, "Failed to register name: %m"); r = sd_bus_attach_event(m->bus, m->event, 0); if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop: %m"); return 0; } void manager_gc(Manager *m, bool drop_not_started) { Machine *machine; assert(m); while ((machine = m->machine_gc_queue)) { LIST_REMOVE(gc_queue, m->machine_gc_queue, machine); machine->in_gc_queue = false; /* First, if we are not closing yet, initiate stopping */ if (!machine_check_gc(machine, drop_not_started) && machine_get_state(machine) != MACHINE_CLOSING) machine_stop(machine); /* Now, the stop stop probably made this referenced * again, but if it didn't, then it's time to let it * go entirely. */ if (!machine_check_gc(machine, drop_not_started)) { machine_finalize(machine); machine_free(machine); } } } int manager_startup(Manager *m) { Machine *machine; Iterator i; int r; assert(m); /* Connect to the bus */ r = manager_connect_bus(m); if (r < 0) return r; /* Deserialize state */ manager_enumerate_machines(m); /* Remove stale objects before we start them */ manager_gc(m, false); /* And start everything */ HASHMAP_FOREACH(machine, m->machines, i) machine_start(machine, NULL, NULL); return 0; } static bool check_idle(void *userdata) { Manager *m = userdata; manager_gc(m, true); return hashmap_isempty(m->machines); } int manager_run(Manager *m) { assert(m); return bus_event_loop_with_idle( m->event, m->bus, "org.freedesktop.machine1", DEFAULT_EXIT_USEC, check_idle, m); } int main(int argc, char *argv[]) { Manager *m = NULL; int r; log_set_target(LOG_TARGET_AUTO); log_set_facility(LOG_AUTH); log_parse_environment(); log_open(); umask(0022); if (argc != 1) { log_error("This program takes no arguments."); r = -EINVAL; goto finish; } /* Always create the directories people can create inotify * watches in. Note that some applications might check for the * existence of /run/systemd/machines/ to determine whether * machined is available, so please always make sure this * check stays in. */ mkdir_label("/run/systemd/machines", 0755); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0); m = manager_new(); if (!m) { r = log_oom(); goto finish; } r = manager_startup(m); if (r < 0) { log_error_errno(r, "Failed to fully start up daemon: %m"); goto finish; } log_debug("systemd-machined running as pid "PID_FMT, getpid()); sd_notify(false, "READY=1\n" "STATUS=Processing requests..."); r = manager_run(m); log_debug("systemd-machined stopped as pid "PID_FMT, getpid()); finish: manager_free(m); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/machine/machined.h000066400000000000000000000047741265713322000172110ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "sd-event.h" #include "hashmap.h" #include "list.h" typedef struct Manager Manager; #include "image-dbus.h" #include "machine-dbus.h" #include "machine.h" struct Manager { sd_event *event; sd_bus *bus; Hashmap *machines; Hashmap *machine_units; Hashmap *machine_leaders; Hashmap *polkit_registry; Hashmap *image_cache; sd_event_source *image_cache_defer_event; LIST_HEAD(Machine, machine_gc_queue); Machine *host_machine; }; Manager *manager_new(void); void manager_free(Manager *m); int manager_add_machine(Manager *m, const char *name, Machine **_machine); int manager_enumerate_machines(Manager *m); int manager_startup(Manager *m); int manager_run(Manager *m); void manager_gc(Manager *m, bool drop_not_started); int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine); extern const sd_bus_vtable manager_vtable[]; int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error); int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error); int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error); int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error); int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, sd_bus_message *more_properties, sd_bus_error *error, char **job); int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error); int manager_unit_is_active(Manager *manager, const char *unit); int manager_job_is_active(Manager *manager, const char *path); systemd-229/src/machine/org.freedesktop.machine1.conf000066400000000000000000000213241265713322000227120ustar00rootroot00000000000000 systemd-229/src/machine/org.freedesktop.machine1.policy.in000066400000000000000000000120101265713322000236610ustar00rootroot00000000000000 The systemd Project http://www.freedesktop.org/wiki/Software/systemd <_description>Log into a local container <_message>Authentication is required to log into a local container. auth_admin auth_admin auth_admin_keep <_description>Log into the local host <_message>Authentication is required to log into the local host. auth_admin auth_admin yes <_description>Acquire a shell in a local container <_message>Authentication is required to acquire a shell in a local container. auth_admin auth_admin auth_admin_keep org.freedesktop.login1.login <_description>Acquire a shell on the local host <_message>Authentication is required to acquire a shell on the local host. auth_admin auth_admin auth_admin_keep org.freedesktop.login1.host-login <_description>Acquire a pseudo TTY in a local container <_message>Authentication is required to acquire a pseudo TTY in a local container. auth_admin auth_admin auth_admin_keep <_description>Acquire a pseudo TTY on the local host <_message>Authentication is required to acquire a pseudo TTY on the local host. auth_admin auth_admin auth_admin_keep <_description>Manage local virtual machines and containers <_message>Authentication is required to manage local virtual machines and containers. auth_admin auth_admin auth_admin_keep org.freedesktop.login1.shell org.freedesktop.login1.login <_description>Manage local virtual machine and container images <_message>Authentication is required to manage local virtual machine and container images. auth_admin auth_admin auth_admin_keep systemd-229/src/machine/org.freedesktop.machine1.service000066400000000000000000000006411265713322000234240ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] Name=org.freedesktop.machine1 Exec=/bin/false User=root SystemdService=dbus-org.freedesktop.machine1.service systemd-229/src/machine/test-machine-tables.c000066400000000000000000000017251265713322000212560ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "machine.h" #include "test-tables.h" int main(int argc, char **argv) { test_table(machine_class, MACHINE_CLASS); test_table(machine_state, MACHINE_STATE); test_table(kill_who, KILL_WHO); return EXIT_SUCCESS; } systemd-229/src/modules-load/000077500000000000000000000000001265713322000162355ustar00rootroot00000000000000systemd-229/src/modules-load/Makefile000077700000000000000000000000001265713322000215432../Makefileustar00rootroot00000000000000systemd-229/src/modules-load/modules-load.c000066400000000000000000000202311265713322000207640ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "conf-files.h" #include "def.h" #include "fd-util.h" #include "fileio.h" #include "log.h" #include "proc-cmdline.h" #include "string-util.h" #include "strv.h" #include "util.h" static char **arg_proc_cmdline_modules = NULL; static const char conf_file_dirs[] = CONF_PATHS_NULSTR("modules-load.d"); static void systemd_kmod_log(void *data, int priority, const char *file, int line, const char *fn, const char *format, va_list args) { DISABLE_WARNING_FORMAT_NONLITERAL; log_internalv(priority, 0, file, line, fn, format, args); REENABLE_WARNING; } static int add_modules(const char *p) { _cleanup_strv_free_ char **k = NULL; k = strv_split(p, ","); if (!k) return log_oom(); if (strv_extend_strv(&arg_proc_cmdline_modules, k, true) < 0) return log_oom(); return 0; } static int parse_proc_cmdline_item(const char *key, const char *value) { int r; if (STR_IN_SET(key, "modules-load", "rd.modules-load") && value) { r = add_modules(value); if (r < 0) return r; } return 0; } static int load_module(struct kmod_ctx *ctx, const char *m) { const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST; struct kmod_list *itr, *modlist = NULL; int r = 0; log_debug("load: %s", m); r = kmod_module_new_from_lookup(ctx, m, &modlist); if (r < 0) return log_error_errno(r, "Failed to lookup alias '%s': %m", m); if (!modlist) { log_error("Failed to find module '%s'", m); return -ENOENT; } kmod_list_foreach(itr, modlist) { struct kmod_module *mod; int state, err; mod = kmod_module_get_module(itr); state = kmod_module_get_initstate(mod); switch (state) { case KMOD_MODULE_BUILTIN: log_info("Module '%s' is builtin", kmod_module_get_name(mod)); break; case KMOD_MODULE_LIVE: log_debug("Module '%s' is already loaded", kmod_module_get_name(mod)); break; default: err = kmod_module_probe_insert_module(mod, probe_flags, NULL, NULL, NULL, NULL); if (err == 0) log_info("Inserted module '%s'", kmod_module_get_name(mod)); else if (err == KMOD_PROBE_APPLY_BLACKLIST) log_info("Module '%s' is blacklisted", kmod_module_get_name(mod)); else { log_error_errno(err, "Failed to insert '%s': %m", kmod_module_get_name(mod)); r = err; } } kmod_module_unref(mod); } kmod_module_unref_list(modlist); return r; } static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent) { _cleanup_fclose_ FILE *f = NULL; int r; assert(ctx); assert(path); r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f); if (r < 0) { if (ignore_enoent && r == -ENOENT) return 0; return log_error_errno(r, "Failed to open %s, ignoring: %m", path); } log_debug("apply: %s", path); for (;;) { char line[LINE_MAX], *l; int k; if (!fgets(line, sizeof(line), f)) { if (feof(f)) break; return log_error_errno(errno, "Failed to read file '%s', ignoring: %m", path); } l = strstrip(line); if (!*l) continue; if (strchr(COMMENTS "\n", *l)) continue; k = load_module(ctx, l); if (k < 0 && r == 0) r = k; } return r; } static void help(void) { printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n" "Loads statically configured kernel modules.\n\n" " -h --help Show this help\n" " --version Show package version\n", program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } int main(int argc, char *argv[]) { int r, k; struct kmod_ctx *ctx; r = parse_argv(argc, argv); if (r <= 0) return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); r = parse_proc_cmdline(parse_proc_cmdline_item); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); ctx = kmod_new(NULL, NULL); if (!ctx) { log_error("Failed to allocate memory for kmod."); goto finish; } kmod_load_resources(ctx); kmod_set_log_fn(ctx, systemd_kmod_log, NULL); r = 0; if (argc > optind) { int i; for (i = optind; i < argc; i++) { k = apply_file(ctx, argv[i], false); if (k < 0 && r == 0) r = k; } } else { _cleanup_strv_free_ char **files = NULL; char **fn, **i; STRV_FOREACH(i, arg_proc_cmdline_modules) { k = load_module(ctx, *i); if (k < 0 && r == 0) r = k; } k = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs); if (k < 0) { log_error_errno(k, "Failed to enumerate modules-load.d files: %m"); if (r == 0) r = k; goto finish; } STRV_FOREACH(fn, files) { k = apply_file(ctx, *fn, true); if (k < 0 && r == 0) r = k; } } finish: kmod_unref(ctx); strv_free(arg_proc_cmdline_modules); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/network/000077500000000000000000000000001265713322000153415ustar00rootroot00000000000000systemd-229/src/network/.gitignore000066400000000000000000000000631265713322000173300ustar00rootroot00000000000000/networkd-network-gperf.c /networkd-netdev-gperf.c systemd-229/src/network/Makefile000077700000000000000000000000001265713322000206472../Makefileustar00rootroot00000000000000systemd-229/src/network/networkctl.c000066400000000000000000001100051265713322000176760ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-device.h" #include "sd-hwdb.h" #include "sd-netlink.h" #include "sd-network.h" #include "alloc-util.h" #include "arphrd-list.h" #include "device-util.h" #include "ether-addr-util.h" #include "hwdb-util.h" #include "lldp.h" #include "local-addresses.h" #include "locale-util.h" #include "netlink-util.h" #include "pager.h" #include "parse-util.h" #include "socket-util.h" #include "stdio-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "util.h" #include "verbs.h" static bool arg_no_pager = false; static bool arg_legend = true; static bool arg_all = false; static void pager_open_if_enabled(void) { if (arg_no_pager) return; pager_open(false); } static int link_get_type_string(int iftype, sd_device *d, char **ret) { const char *t; char *p; assert(ret); if (iftype == ARPHRD_ETHER && d) { const char *devtype = NULL, *id = NULL; /* WLANs have iftype ARPHRD_ETHER, but we want * to show a more useful type string for * them */ (void)sd_device_get_devtype(d, &devtype); if (streq_ptr(devtype, "wlan")) id = "wlan"; else if (streq_ptr(devtype, "wwan")) id = "wwan"; if (id) { p = strdup(id); if (!p) return -ENOMEM; *ret = p; return 1; } } t = arphrd_to_name(iftype); if (!t) { *ret = NULL; return 0; } p = strdup(t); if (!p) return -ENOMEM; ascii_strlower(p); *ret = p; return 0; } typedef struct LinkInfo { const char *name; int ifindex; unsigned iftype; } LinkInfo; static int link_info_compare(const void *a, const void *b) { const LinkInfo *x = a, *y = b; return x->ifindex - y->ifindex; } static int decode_and_sort_links(sd_netlink_message *m, LinkInfo **ret) { _cleanup_free_ LinkInfo *links = NULL; size_t size = 0, c = 0; sd_netlink_message *i; int r; for (i = m; i; i = sd_netlink_message_next(i)) { const char *name; unsigned iftype; uint16_t type; int ifindex; r = sd_netlink_message_get_type(i, &type); if (r < 0) return r; if (type != RTM_NEWLINK) continue; r = sd_rtnl_message_link_get_ifindex(i, &ifindex); if (r < 0) return r; r = sd_netlink_message_read_string(i, IFLA_IFNAME, &name); if (r < 0) return r; r = sd_rtnl_message_link_get_type(i, &iftype); if (r < 0) return r; if (!GREEDY_REALLOC(links, size, c+1)) return -ENOMEM; links[c].name = name; links[c].ifindex = ifindex; links[c].iftype = iftype; c++; } qsort_safe(links, c, sizeof(LinkInfo), link_info_compare); *ret = links; links = NULL; return (int) c; } static void operational_state_to_color(const char *state, const char **on, const char **off) { assert(on); assert(off); if (streq_ptr(state, "routable")) { *on = ansi_highlight_green(); *off = ansi_normal(); } else if (streq_ptr(state, "degraded")) { *on = ansi_highlight_yellow(); *off = ansi_normal(); } else *on = *off = ""; } static void setup_state_to_color(const char *state, const char **on, const char **off) { assert(on); assert(off); if (streq_ptr(state, "configured")) { *on = ansi_highlight_green(); *off = ansi_normal(); } else if (streq_ptr(state, "configuring")) { *on = ansi_highlight_yellow(); *off = ansi_normal(); } else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) { *on = ansi_highlight_red(); *off = ansi_normal(); } else *on = *off = ""; } static int list_links(int argc, char *argv[], void *userdata) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_free_ LinkInfo *links = NULL; int r, c, i; pager_open_if_enabled(); r = sd_netlink_open(&rtnl); if (r < 0) return log_error_errno(r, "Failed to connect to netlink: %m"); r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0); if (r < 0) return rtnl_log_create_error(r); r = sd_netlink_message_request_dump(req, true); if (r < 0) return rtnl_log_create_error(r); r = sd_netlink_call(rtnl, req, 0, &reply); if (r < 0) return log_error_errno(r, "Failed to enumerate links: %m"); if (arg_legend) printf("%3s %-16s %-18s %-11s %-10s\n", "IDX", "LINK", "TYPE", "OPERATIONAL", "SETUP"); c = decode_and_sort_links(reply, &links); if (c < 0) return rtnl_log_parse_error(c); for (i = 0; i < c; i++) { _cleanup_free_ char *setup_state = NULL, *operational_state = NULL; _cleanup_(sd_device_unrefp) sd_device *d = NULL; const char *on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup; char devid[2 + DECIMAL_STR_MAX(int)]; _cleanup_free_ char *t = NULL; sd_network_link_get_operational_state(links[i].ifindex, &operational_state); operational_state_to_color(operational_state, &on_color_operational, &off_color_operational); sd_network_link_get_setup_state(links[i].ifindex, &setup_state); setup_state_to_color(setup_state, &on_color_setup, &off_color_setup); sprintf(devid, "n%i", links[i].ifindex); (void)sd_device_new_from_device_id(&d, devid); link_get_type_string(links[i].iftype, d, &t); printf("%3i %-16s %-18s %s%-11s%s %s%-10s%s\n", links[i].ifindex, links[i].name, strna(t), on_color_operational, strna(operational_state), off_color_operational, on_color_setup, strna(setup_state), off_color_setup); } if (arg_legend) printf("\n%i links listed.\n", c); return 0; } /* IEEE Organizationally Unique Identifier vendor string */ static int ieee_oui(sd_hwdb *hwdb, struct ether_addr *mac, char **ret) { const char *description; char modalias[strlen("OUI:XXYYXXYYXXYY") + 1], *desc; int r; assert(ret); if (!hwdb) return -EINVAL; if (!mac) return -EINVAL; /* skip commonly misused 00:00:00 (Xerox) prefix */ if (memcmp(mac, "\0\0\0", 3) == 0) return -EINVAL; xsprintf(modalias, "OUI:" ETHER_ADDR_FORMAT_STR, ETHER_ADDR_FORMAT_VAL(*mac)); r = sd_hwdb_get(hwdb, modalias, "ID_OUI_FROM_DATABASE", &description); if (r < 0) return r; desc = strdup(description); if (!desc) return -ENOMEM; *ret = desc; return 0; } static int get_gateway_description( sd_netlink *rtnl, sd_hwdb *hwdb, int ifindex, int family, union in_addr_union *gateway, char **gateway_description) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; sd_netlink_message *m; int r; assert(rtnl); assert(ifindex >= 0); assert(family == AF_INET || family == AF_INET6); assert(gateway); assert(gateway_description); r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_GETNEIGH, ifindex, family); if (r < 0) return r; r = sd_netlink_message_request_dump(req, true); if (r < 0) return r; r = sd_netlink_call(rtnl, req, 0, &reply); if (r < 0) return r; for (m = reply; m; m = sd_netlink_message_next(m)) { union in_addr_union gw = {}; struct ether_addr mac = {}; uint16_t type; int ifi, fam; r = sd_netlink_message_get_errno(m); if (r < 0) { log_error_errno(r, "got error: %m"); continue; } r = sd_netlink_message_get_type(m, &type); if (r < 0) { log_error_errno(r, "could not get type: %m"); continue; } if (type != RTM_NEWNEIGH) { log_error("type is not RTM_NEWNEIGH"); continue; } r = sd_rtnl_message_neigh_get_family(m, &fam); if (r < 0) { log_error_errno(r, "could not get family: %m"); continue; } if (fam != family) { log_error("family is not correct"); continue; } r = sd_rtnl_message_neigh_get_ifindex(m, &ifi); if (r < 0) { log_error_errno(r, "could not get ifindex: %m"); continue; } if (ifindex > 0 && ifi != ifindex) continue; switch (fam) { case AF_INET: r = sd_netlink_message_read_in_addr(m, NDA_DST, &gw.in); if (r < 0) continue; break; case AF_INET6: r = sd_netlink_message_read_in6_addr(m, NDA_DST, &gw.in6); if (r < 0) continue; break; default: continue; } if (!in_addr_equal(fam, &gw, gateway)) continue; r = sd_netlink_message_read_ether_addr(m, NDA_LLADDR, &mac); if (r < 0) continue; r = ieee_oui(hwdb, &mac, gateway_description); if (r < 0) continue; return 0; } return -ENODATA; } static int dump_gateways( sd_netlink *rtnl, sd_hwdb *hwdb, const char *prefix, int ifindex) { _cleanup_free_ struct local_address *local = NULL; int r, n, i; n = local_gateways(rtnl, ifindex, AF_UNSPEC, &local); if (n < 0) return n; for (i = 0; i < n; i++) { _cleanup_free_ char *gateway = NULL, *description = NULL; r = in_addr_to_string(local[i].family, &local[i].address, &gateway); if (r < 0) return r; r = get_gateway_description(rtnl, hwdb, local[i].ifindex, local[i].family, &local[i].address, &description); if (r < 0) log_debug_errno(r, "Could not get description of gateway: %m"); printf("%*s%s", (int) strlen(prefix), i == 0 ? prefix : "", gateway); if (description) printf(" (%s)", description); /* Show interface name for the entry if we show * entries for all interfaces */ if (ifindex <= 0) { char name[IF_NAMESIZE+1]; if (if_indextoname(local[i].ifindex, name)) { fputs(" on ", stdout); fputs(name, stdout); } else printf(" on %%%i", local[i].ifindex); } fputc('\n', stdout); } return 0; } static int dump_addresses( sd_netlink *rtnl, const char *prefix, int ifindex) { _cleanup_free_ struct local_address *local = NULL; int r, n, i; n = local_addresses(rtnl, ifindex, AF_UNSPEC, &local); if (n < 0) return n; for (i = 0; i < n; i++) { _cleanup_free_ char *pretty = NULL; r = in_addr_to_string(local[i].family, &local[i].address, &pretty); if (r < 0) return r; printf("%*s%s", (int) strlen(prefix), i == 0 ? prefix : "", pretty); if (ifindex <= 0) { char name[IF_NAMESIZE+1]; if (if_indextoname(local[i].ifindex, name)) { fputs(" on ", stdout); fputs(name, stdout); } else printf(" on %%%i", local[i].ifindex); } fputc('\n', stdout); } return 0; } static void dump_list(const char *prefix, char **l) { char **i; if (strv_isempty(l)) return; STRV_FOREACH(i, l) { printf("%*s%s\n", (int) strlen(prefix), i == l ? prefix : "", *i); } } static int link_status_one( sd_netlink *rtnl, sd_hwdb *hwdb, const char *name) { _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL; _cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; _cleanup_(sd_device_unrefp) sd_device *d = NULL; char devid[2 + DECIMAL_STR_MAX(int)]; _cleanup_free_ char *t = NULL, *network = NULL; const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL; const char *on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup; _cleanup_strv_free_ char **carrier_bound_to = NULL; _cleanup_strv_free_ char **carrier_bound_by = NULL; struct ether_addr e; unsigned iftype; int r, ifindex; bool have_mac; uint32_t mtu; assert(rtnl); assert(name); if (parse_ifindex(name, &ifindex) >= 0) r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, ifindex); else { r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0); if (r < 0) return rtnl_log_create_error(r); r = sd_netlink_message_append_string(req, IFLA_IFNAME, name); } if (r < 0) return rtnl_log_create_error(r); r = sd_netlink_call(rtnl, req, 0, &reply); if (r < 0) return log_error_errno(r, "Failed to query link: %m"); r = sd_rtnl_message_link_get_ifindex(reply, &ifindex); if (r < 0) return rtnl_log_parse_error(r); r = sd_netlink_message_read_string(reply, IFLA_IFNAME, &name); if (r < 0) return rtnl_log_parse_error(r); r = sd_rtnl_message_link_get_type(reply, &iftype); if (r < 0) return rtnl_log_parse_error(r); have_mac = sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &e) >= 0; if (have_mac) { const uint8_t *p; bool all_zeroes = true; for (p = (uint8_t*) &e; p < (uint8_t*) &e + sizeof(e); p++) if (*p != 0) { all_zeroes = false; break; } if (all_zeroes) have_mac = false; } (void) sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu); (void) sd_network_link_get_operational_state(ifindex, &operational_state); operational_state_to_color(operational_state, &on_color_operational, &off_color_operational); (void) sd_network_link_get_setup_state(ifindex, &setup_state); setup_state_to_color(setup_state, &on_color_setup, &off_color_setup); (void) sd_network_link_get_dns(ifindex, &dns); (void) sd_network_link_get_search_domains(ifindex, &search_domains); (void) sd_network_link_get_route_domains(ifindex, &route_domains); (void) sd_network_link_get_ntp(ifindex, &ntp); sprintf(devid, "n%i", ifindex); (void) sd_device_new_from_device_id(&d, devid); if (d) { (void) sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link); (void) sd_device_get_property_value(d, "ID_NET_DRIVER", &driver); (void) sd_device_get_property_value(d, "ID_PATH", &path); r = sd_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE", &vendor); if (r < 0) (void) sd_device_get_property_value(d, "ID_VENDOR", &vendor); r = sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model); if (r < 0) (void) sd_device_get_property_value(d, "ID_MODEL", &model); } link_get_type_string(iftype, d, &t); sd_network_link_get_network_file(ifindex, &network); sd_network_link_get_carrier_bound_to(ifindex, &carrier_bound_to); sd_network_link_get_carrier_bound_by(ifindex, &carrier_bound_by); printf("%s%s%s %i: %s\n", on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational, ifindex, name); printf(" Link File: %s\n" " Network File: %s\n" " Type: %s\n" " State: %s%s%s (%s%s%s)\n", strna(link), strna(network), strna(t), on_color_operational, strna(operational_state), off_color_operational, on_color_setup, strna(setup_state), off_color_setup); if (path) printf(" Path: %s\n", path); if (driver) printf(" Driver: %s\n", driver); if (vendor) printf(" Vendor: %s\n", vendor); if (model) printf(" Model: %s\n", model); if (have_mac) { _cleanup_free_ char *description = NULL; char ea[ETHER_ADDR_TO_STRING_MAX]; ieee_oui(hwdb, &e, &description); if (description) printf(" HW Address: %s (%s)\n", ether_addr_to_string(&e, ea), description); else printf(" HW Address: %s\n", ether_addr_to_string(&e, ea)); } if (mtu > 0) printf(" MTU: %u\n", mtu); dump_addresses(rtnl, " Address: ", ifindex); dump_gateways(rtnl, hwdb, " Gateway: ", ifindex); dump_list(" DNS: ", dns); dump_list(" Search Domains: ", search_domains); dump_list(" Route Domains: ", route_domains); dump_list(" NTP: ", ntp); dump_list("Carrier Bound To: ", carrier_bound_to); dump_list("Carrier Bound By: ", carrier_bound_by); (void) sd_network_link_get_timezone(ifindex, &tz); if (tz) printf(" Time Zone: %s", tz); return 0; } static int link_status(int argc, char *argv[], void *userdata) { _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; char **name; int r; r = sd_netlink_open(&rtnl); if (r < 0) return log_error_errno(r, "Failed to connect to netlink: %m"); r = sd_hwdb_new(&hwdb); if (r < 0) log_debug_errno(r, "Failed to open hardware database: %m"); if (argc <= 1 && !arg_all) { _cleanup_free_ char *operational_state = NULL; _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains; const char *on_color_operational, *off_color_operational; sd_network_get_operational_state(&operational_state); operational_state_to_color(operational_state, &on_color_operational, &off_color_operational); printf("%s%s%s State: %s%s%s\n", on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational, on_color_operational, strna(operational_state), off_color_operational); dump_addresses(rtnl, " Address: ", 0); dump_gateways(rtnl, hwdb, " Gateway: ", 0); sd_network_get_dns(&dns); dump_list(" DNS: ", dns); sd_network_get_search_domains(&search_domains); dump_list("Search Domains: ", search_domains); sd_network_get_route_domains(&route_domains); dump_list(" Route Domains: ", route_domains); sd_network_get_ntp(&ntp); dump_list(" NTP: ", ntp); return 0; } pager_open_if_enabled(); if (arg_all) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; _cleanup_free_ LinkInfo *links = NULL; int c, i; r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0); if (r < 0) return rtnl_log_create_error(r); r = sd_netlink_message_request_dump(req, true); if (r < 0) return rtnl_log_create_error(r); r = sd_netlink_call(rtnl, req, 0, &reply); if (r < 0) return log_error_errno(r, "Failed to enumerate links: %m"); c = decode_and_sort_links(reply, &links); if (c < 0) return rtnl_log_parse_error(c); for (i = 0; i < c; i++) { if (i > 0) fputc('\n', stdout); link_status_one(rtnl, hwdb, links[i].name); } } else { STRV_FOREACH(name, argv + 1) { if (name != argv + 1) fputc('\n', stdout); link_status_one(rtnl, hwdb, *name); } } return 0; } const char *lldp_system_capability_to_string(LLDPSystemCapabilities d) _const_; LLDPSystemCapabilities lldp_system_capability_from_string(const char *d) _pure_; static const char* const lldp_system_capability_table[_LLDP_SYSTEM_CAPABILITIES_MAX + 1] = { [LLDP_SYSTEM_CAPABILITIES_OTHER] = "O", [LLDP_SYSTEM_CAPABILITIES_REPEATER] = "P", [LLDP_SYSTEM_CAPABILITIES_BRIDGE] = "B", [LLDP_SYSTEM_CAPABILITIES_WLAN_AP] = "W", [LLDP_SYSTEM_CAPABILITIES_ROUTER] = "R", [LLDP_SYSTEM_CAPABILITIES_PHONE] = "T", [LLDP_SYSTEM_CAPABILITIES_DOCSIS] = "D", [LLDP_SYSTEM_CAPABILITIES_STATION] = "A", [LLDP_SYSTEM_CAPABILITIES_CVLAN] = "C", [LLDP_SYSTEM_CAPABILITIES_SVLAN] = "S", [LLDP_SYSTEM_CAPABILITIES_TPMR] = "M", [_LLDP_SYSTEM_CAPABILITIES_MAX] = "N/A", }; DEFINE_STRING_TABLE_LOOKUP(lldp_system_capability, LLDPSystemCapabilities); static char *lldp_system_caps(uint16_t cap) { _cleanup_free_ char *s = NULL, *t = NULL; char *capability; t = strdup("[ "); if (!t) return NULL; if (cap & LLDP_SYSTEM_CAPABILITIES_OTHER) { s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_OTHER), " ", NULL); if (!s) return NULL; free(t); t = s; } if (cap & LLDP_SYSTEM_CAPABILITIES_REPEATER) { s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_REPEATER), " ", NULL); if (!s) return NULL; free(t); t = s; } if (cap & LLDP_SYSTEM_CAPABILITIES_BRIDGE) { s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_BRIDGE), " ", NULL); if (!s) return NULL; free(t); t = s; } if (cap & LLDP_SYSTEM_CAPABILITIES_WLAN_AP) { s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_WLAN_AP), " ", NULL); if (!s) return NULL; free(t); t = s; } if (cap & LLDP_SYSTEM_CAPABILITIES_ROUTER) { s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_ROUTER), " ", NULL); if (!s) return NULL; free(t); t = s; } if (cap & LLDP_SYSTEM_CAPABILITIES_PHONE) { s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_PHONE), " ", NULL); if (!s) return NULL; free(t); t = s; } if (cap & LLDP_SYSTEM_CAPABILITIES_DOCSIS) { s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_DOCSIS), " ", NULL); if (!s) return NULL; free(t); t = s; } if (cap & LLDP_SYSTEM_CAPABILITIES_STATION) { s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_STATION), " ", NULL); if (!s) return NULL; free(t); t = s; } if (cap & LLDP_SYSTEM_CAPABILITIES_CVLAN) { s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_CVLAN), " ", NULL); if (!s) return NULL; free(t); t = s; } if (cap & LLDP_SYSTEM_CAPABILITIES_SVLAN) { s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_SVLAN), " ", NULL); if (!s) return NULL; free(t); t = s; } if (cap & LLDP_SYSTEM_CAPABILITIES_TPMR) { s = strappend(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_TPMR)); if (!s) return NULL; free(t); } if (!s) { s = strappend(t, lldp_system_capability_to_string(_LLDP_SYSTEM_CAPABILITIES_MAX)); if (!s) return NULL; free(t); } t = strappend(s, "]"); if (!t) return NULL; free(s); capability = t; s = NULL; t = NULL; return capability; } static int link_lldp_status(int argc, char *argv[], void *userdata) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_free_ LinkInfo *links = NULL; double ttl = -1; uint32_t capability; int i, r, c, j; const char *p; char **s; pager_open_if_enabled(); r = sd_netlink_open(&rtnl); if (r < 0) return log_error_errno(r, "Failed to connect to netlink: %m"); r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0); if (r < 0) return rtnl_log_create_error(r); r = sd_netlink_message_request_dump(req, true); if (r < 0) return rtnl_log_create_error(r); r = sd_netlink_call(rtnl, req, 0, &reply); if (r < 0) return log_error_errno(r, "Failed to enumerate links: %m"); c = decode_and_sort_links(reply, &links); if (c < 0) return rtnl_log_parse_error(c); if (arg_legend) printf("%s %16s %24s %16s %16s\n", "Local Intf", "Device ID", "Port ID", "TTL", "Capability"); for (i = j = 0; i < c; i++) { _cleanup_free_ char *chassis = NULL, *port = NULL, *cap = NULL, *lldp = NULL; _cleanup_strv_free_ char **l = NULL; r = sd_network_link_get_lldp(links[i].ifindex, &lldp); if (r < 0) continue; l = strv_split_newlines(lldp); if (!l) return -ENOMEM; STRV_FOREACH(s, l) { p = *s; for (;;) { _cleanup_free_ char *a = NULL, *b = NULL, *word = NULL; r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES); if (r < 0) return log_error_errno(r, "Failed to parse LLDP syntax \"%s\": %m", *s); if (r == 0) break; r = split_pair(word, "=", &a, &b); if (r < 0) continue; if (streq(a, "_Chassis")) { r = free_and_strdup(&chassis, b); if (r < 0) return r; } else if (streq(a, "_Port")) { r = free_and_strdup(&port, b); if (r < 0) return r; } else if (streq(a, "_TTL")) { long long unsigned x = 0; usec_t time; r = safe_atollu(b, &x); if (r < 0 || (usec_t) x != x) return log_warning_errno(r < 0 ? r : ERANGE, "Failed to parse TTL \"%s\": %m", b); time = now(clock_boottime_or_monotonic()); if (x < time) continue; ttl = (double) (x - time) / USEC_PER_SEC; } else if (streq(a, "_CAP")) { sscanf(b, "%x", &capability); cap = lldp_system_caps(capability); } } if (ttl >= 0) { printf("%10s %24s %16s %16f %16s\n", links[i].name, strna(chassis), strna(port), ttl, cap); j++; } } } if (arg_legend) { printf("\nCapability Codes:\n" "(O) - Other, (P) - Repeater, (B) - Bridge , (W) - WLAN Access Point, (R) = Router,\n" "(T) - Telephone, (D) - Data Over Cable Service Interface Specifications, (A) - Station,\n" "(C) - Customer VLAN, (S) - Service VLAN, (M) - Two-port MAC Relay (TPMR)\n\n"); printf("Total entries displayed: %d\n", j); } return 0; } static void help(void) { printf("%s [OPTIONS...]\n\n" "Query and control the networking subsystem.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " --no-legend Do not show the headers and footers\n" " -a --all Show status for all links\n\n" "Commands:\n" " list List links\n" " status [LINK...] Show link status\n" " lldp Show lldp information\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_LEGEND, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, { "all", no_argument, NULL, 'a' }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "ha", options, NULL)) >= 0) { switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_NO_PAGER: arg_no_pager = true; break; case ARG_NO_LEGEND: arg_legend = false; break; case 'a': arg_all = true; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } } return 1; } static int networkctl_main(int argc, char *argv[]) { const Verb verbs[] = { { "list", VERB_ANY, 1, VERB_DEFAULT, list_links }, { "status", 1, VERB_ANY, 0, link_status }, { "lldp", VERB_ANY, 1, VERB_DEFAULT, link_lldp_status }, {} }; return dispatch_verb(argc, argv, verbs, NULL); } int main(int argc, char* argv[]) { int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = networkctl_main(argc, argv); finish: pager_close(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/network/networkd-address-pool.c000066400000000000000000000111611265713322000217340ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "networkd-address-pool.h" #include "networkd.h" #include "set.h" #include "string-util.h" int address_pool_new( Manager *m, AddressPool **ret, int family, const union in_addr_union *u, unsigned prefixlen) { AddressPool *p; assert(m); assert(ret); assert(u); p = new0(AddressPool, 1); if (!p) return -ENOMEM; p->manager = m; p->family = family; p->prefixlen = prefixlen; p->in_addr = *u; LIST_PREPEND(address_pools, m->address_pools, p); *ret = p; return 0; } int address_pool_new_from_string( Manager *m, AddressPool **ret, int family, const char *p, unsigned prefixlen) { union in_addr_union u; int r; assert(m); assert(ret); assert(p); r = in_addr_from_string(family, p, &u); if (r < 0) return r; return address_pool_new(m, ret, family, &u, prefixlen); } void address_pool_free(AddressPool *p) { if (!p) return; if (p->manager) LIST_REMOVE(address_pools, p->manager->address_pools, p); free(p); } static bool address_pool_prefix_is_taken( AddressPool *p, const union in_addr_union *u, unsigned prefixlen) { Iterator i; Link *l; Network *n; assert(p); assert(u); HASHMAP_FOREACH(l, p->manager->links, i) { Address *a; Iterator j; /* Don't clash with assigned addresses */ SET_FOREACH(a, l->addresses, j) { if (a->family != p->family) continue; if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen)) return true; } /* Don't clash with addresses already pulled from the pool, but not assigned yet */ LIST_FOREACH(addresses, a, l->pool_addresses) { if (a->family != p->family) continue; if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen)) return true; } } /* And don't clash with configured but un-assigned addresses either */ LIST_FOREACH(networks, n, p->manager->networks) { Address *a; LIST_FOREACH(addresses, a, n->static_addresses) { if (a->family != p->family) continue; if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen)) return true; } } return false; } int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found) { union in_addr_union u; assert(p); assert(prefixlen > 0); assert(found); if (p->prefixlen > prefixlen) return 0; u = p->in_addr; for (;;) { if (!address_pool_prefix_is_taken(p, &u, prefixlen)) { _cleanup_free_ char *s = NULL; in_addr_to_string(p->family, &u, &s); log_debug("Found range %s/%u", strna(s), prefixlen); *found = u; return 1; } if (!in_addr_prefix_next(p->family, &u, prefixlen)) return 0; if (!in_addr_prefix_intersect(p->family, &p->in_addr, p->prefixlen, &u, prefixlen)) return 0; } return 0; } systemd-229/src/network/networkd-address-pool.h000066400000000000000000000025311265713322000217420ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct AddressPool AddressPool; #include "in-addr-util.h" #include "networkd.h" struct AddressPool { Manager *manager; int family; unsigned prefixlen; union in_addr_union in_addr; LIST_FIELDS(AddressPool, address_pools); }; int address_pool_new(Manager *m, AddressPool **ret, int family, const union in_addr_union *u, unsigned prefixlen); int address_pool_new_from_string(Manager *m, AddressPool **ret, int family, const char *p, unsigned prefixlen); void address_pool_free(AddressPool *p); int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found); systemd-229/src/network/networkd-address.c000066400000000000000000000612741265713322000207770ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "conf-parser.h" #include "firewall-util.h" #include "netlink-util.h" #include "networkd-address.h" #include "networkd.h" #include "parse-util.h" #include "set.h" #include "string-util.h" #include "utf8.h" #include "util.h" int address_new(Address **ret) { _cleanup_address_free_ Address *address = NULL; address = new0(Address, 1); if (!address) return -ENOMEM; address->family = AF_UNSPEC; address->scope = RT_SCOPE_UNIVERSE; address->cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME; address->cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME; *ret = address; address = NULL; return 0; } int address_new_static(Network *network, unsigned section, Address **ret) { _cleanup_address_free_ Address *address = NULL; int r; if (section) { address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section)); if (address) { *ret = address; address = NULL; return 0; } } r = address_new(&address); if (r < 0) return r; address->network = network; LIST_APPEND(addresses, network->static_addresses, address); if (section) { address->section = section; hashmap_put(network->addresses_by_section, UINT_TO_PTR(address->section), address); } *ret = address; address = NULL; return 0; } void address_free(Address *address) { if (!address) return; if (address->network) { LIST_REMOVE(addresses, address->network->static_addresses, address); if (address->section) hashmap_remove(address->network->addresses_by_section, UINT_TO_PTR(address->section)); } if (address->link) { set_remove(address->link->addresses, address); set_remove(address->link->addresses_foreign, address); } free(address); } static void address_hash_func(const void *b, struct siphash *state) { const Address *a = b; assert(a); siphash24_compress(&a->family, sizeof(a->family), state); switch (a->family) { case AF_INET: siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state); /* peer prefix */ if (a->prefixlen != 0) { uint32_t prefix; if (a->in_addr_peer.in.s_addr != 0) prefix = be32toh(a->in_addr_peer.in.s_addr) >> (32 - a->prefixlen); else prefix = be32toh(a->in_addr.in.s_addr) >> (32 - a->prefixlen); siphash24_compress(&prefix, sizeof(prefix), state); } /* fallthrough */ case AF_INET6: /* local address */ siphash24_compress(&a->in_addr, FAMILY_ADDRESS_SIZE(a->family), state); break; default: /* treat any other address family as AF_UNSPEC */ break; } } static int address_compare_func(const void *c1, const void *c2) { const Address *a1 = c1, *a2 = c2; if (a1->family < a2->family) return -1; if (a1->family > a2->family) return 1; switch (a1->family) { /* use the same notion of equality as the kernel does */ case AF_INET: if (a1->prefixlen < a2->prefixlen) return -1; if (a1->prefixlen > a2->prefixlen) return 1; /* compare the peer prefixes */ if (a1->prefixlen != 0) { /* make sure we don't try to shift by 32. * See ISO/IEC 9899:TC3 § 6.5.7.3. */ uint32_t b1, b2; if (a1->in_addr_peer.in.s_addr != 0) b1 = be32toh(a1->in_addr_peer.in.s_addr) >> (32 - a1->prefixlen); else b1 = be32toh(a1->in_addr.in.s_addr) >> (32 - a1->prefixlen); if (a2->in_addr_peer.in.s_addr != 0) b2 = be32toh(a2->in_addr_peer.in.s_addr) >> (32 - a1->prefixlen); else b2 = be32toh(a2->in_addr.in.s_addr) >> (32 - a1->prefixlen); if (b1 < b2) return -1; if (b1 > b2) return 1; } /* fall-through */ case AF_INET6: return memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family)); default: /* treat any other address family as AF_UNSPEC */ return 0; } } static const struct hash_ops address_hash_ops = { .hash = address_hash_func, .compare = address_compare_func }; bool address_equal(Address *a1, Address *a2) { if (a1 == a2) return true; if (!a1 || !a2) return false; return address_compare_func(a1, a2) == 0; } static int address_establish(Address *address, Link *link) { bool masq; int r; assert(address); assert(link); masq = link->network && link->network->ip_masquerade && address->family == AF_INET && address->scope < RT_SCOPE_LINK; /* Add firewall entry if this is requested */ if (address->ip_masquerade_done != masq) { union in_addr_union masked = address->in_addr; in_addr_mask(address->family, &masked, address->prefixlen); r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0); if (r < 0) log_link_warning_errno(link, r, "Could not enable IP masquerading: %m"); address->ip_masquerade_done = masq; } return 0; } static int address_add_internal(Link *link, Set **addresses, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { _cleanup_address_free_ Address *address = NULL; int r; assert(link); assert(addresses); assert(in_addr); r = address_new(&address); if (r < 0) return r; address->family = family; address->in_addr = *in_addr; address->prefixlen = prefixlen; /* Consider address tentative until we get the real flags from the kernel */ address->flags = IFA_F_TENTATIVE; r = set_ensure_allocated(addresses, &address_hash_ops); if (r < 0) return r; r = set_put(*addresses, address); if (r < 0) return r; address->link = link; if (ret) *ret = address; address = NULL; return 0; } int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { return address_add_internal(link, &link->addresses_foreign, family, in_addr, prefixlen, ret); } int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { Address *address; int r; r = address_get(link, family, in_addr, prefixlen, &address); if (r == -ENOENT) { /* Address does not exist, create a new one */ r = address_add_internal(link, &link->addresses, family, in_addr, prefixlen, &address); if (r < 0) return r; } else if (r == 0) { /* Take over a foreign address */ r = set_ensure_allocated(&link->addresses, &address_hash_ops); if (r < 0) return r; r = set_put(link->addresses, address); if (r < 0) return r; set_remove(link->addresses_foreign, address); } else if (r == 1) { /* Already exists, do nothing */ ; } else return r; if (ret) *ret = address; return 0; } static int address_release(Address *address) { int r; assert(address); assert(address->link); /* Remove masquerading firewall entry if it was added */ if (address->ip_masquerade_done) { union in_addr_union masked = address->in_addr; in_addr_mask(address->family, &masked, address->prefixlen); r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0); if (r < 0) log_link_warning_errno(address->link, r, "Failed to disable IP masquerading: %m"); address->ip_masquerade_done = false; } return 0; } int address_update(Address *address, unsigned char flags, unsigned char scope, struct ifa_cacheinfo *cinfo) { bool ready; int r; assert(address); assert(cinfo); ready = address_is_ready(address); address->flags = flags; address->scope = scope; address->cinfo = *cinfo; if (address->link) { link_update_operstate(address->link); if (!ready && address_is_ready(address)) { link_check_ready(address->link); if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 && in_addr_is_null(AF_INET6, (const union in_addr_union*) &address->link->ipv6ll_address) > 0) { r = link_ipv6ll_gained(address->link, &address->in_addr.in6); if (r < 0) return r; } } } return 0; } int address_drop(Address *address) { Link *link; bool ready; assert(address); ready = address_is_ready(address); link = address->link; address_release(address); address_free(address); link_update_operstate(link); if (link && !ready) link_check_ready(link); return 0; } int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { Address address = {}, *existing; assert(link); assert(in_addr); assert(ret); address.family = family; address.in_addr = *in_addr; address.prefixlen = prefixlen; existing = set_get(link->addresses, &address); if (existing) { *ret = existing; return 1; } else { existing = set_get(link->addresses_foreign, &address); if (!existing) return -ENOENT; } *ret = existing; return 0; } int address_remove(Address *address, Link *link, sd_netlink_message_handler_t callback) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(address); assert(address->family == AF_INET || address->family == AF_INET6); assert(link); assert(link->ifindex > 0); assert(link->manager); assert(link->manager->rtnl); r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR, link->ifindex, address->family); if (r < 0) return log_error_errno(r, "Could not allocate RTM_DELADDR message: %m"); r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen); if (r < 0) return log_error_errno(r, "Could not set prefixlen: %m"); if (address->family == AF_INET) r = sd_netlink_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in); else if (address->family == AF_INET6) r = sd_netlink_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6); if (r < 0) return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m"); r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL); if (r < 0) return log_error_errno(r, "Could not send rtnetlink message: %m"); link_ref(link); return 0; } static int address_acquire(Link *link, Address *original, Address **ret) { union in_addr_union in_addr = {}; struct in_addr broadcast = {}; _cleanup_address_free_ Address *na = NULL; int r; assert(link); assert(original); assert(ret); /* Something useful was configured? just use it */ if (in_addr_is_null(original->family, &original->in_addr) <= 0) return 0; /* The address is configured to be 0.0.0.0 or [::] by the user? * Then let's acquire something more useful from the pool. */ r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr); if (r < 0) return log_link_error_errno(link, r, "Failed to acquire address from pool: %m"); if (r == 0) { log_link_error(link, "Couldn't find free address for interface, all taken."); return -EBUSY; } if (original->family == AF_INET) { /* Pick first address in range for ourselves ... */ in_addr.in.s_addr = in_addr.in.s_addr | htobe32(1); /* .. and use last as broadcast address */ broadcast.s_addr = in_addr.in.s_addr | htobe32(0xFFFFFFFFUL >> original->prefixlen); } else if (original->family == AF_INET6) in_addr.in6.s6_addr[15] |= 1; r = address_new(&na); if (r < 0) return r; na->family = original->family; na->prefixlen = original->prefixlen; na->scope = original->scope; na->cinfo = original->cinfo; if (original->label) { na->label = strdup(original->label); if (!na->label) return -ENOMEM; } na->broadcast = broadcast; na->in_addr = in_addr; LIST_PREPEND(addresses, link->pool_addresses, na); *ret = na; na = NULL; return 0; } int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback, bool update) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(address); assert(address->family == AF_INET || address->family == AF_INET6); assert(link); assert(link->ifindex > 0); assert(link->manager); assert(link->manager->rtnl); r = address_acquire(link, address, &address); if (r < 0) return r; if (update) r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req, link->ifindex, address->family); else r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR, link->ifindex, address->family); if (r < 0) return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m"); r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen); if (r < 0) return log_error_errno(r, "Could not set prefixlen: %m"); address->flags |= IFA_F_PERMANENT; r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff)); if (r < 0) return log_error_errno(r, "Could not set flags: %m"); if (address->flags & ~0xff) { r = sd_netlink_message_append_u32(req, IFA_FLAGS, address->flags); if (r < 0) return log_error_errno(r, "Could not set extended flags: %m"); } r = sd_rtnl_message_addr_set_scope(req, address->scope); if (r < 0) return log_error_errno(r, "Could not set scope: %m"); if (address->family == AF_INET) r = sd_netlink_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in); else if (address->family == AF_INET6) r = sd_netlink_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6); if (r < 0) return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m"); if (!in_addr_is_null(address->family, &address->in_addr_peer)) { if (address->family == AF_INET) r = sd_netlink_message_append_in_addr(req, IFA_ADDRESS, &address->in_addr_peer.in); else if (address->family == AF_INET6) r = sd_netlink_message_append_in6_addr(req, IFA_ADDRESS, &address->in_addr_peer.in6); if (r < 0) return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m"); } else { if (address->family == AF_INET) { r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast); if (r < 0) return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m"); } } if (address->label) { r = sd_netlink_message_append_string(req, IFA_LABEL, address->label); if (r < 0) return log_error_errno(r, "Could not append IFA_LABEL attribute: %m"); } r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo); if (r < 0) return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m"); r = address_establish(address, link); if (r < 0) return r; r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL); if (r < 0) { address_release(address); return log_error_errno(r, "Could not send rtnetlink message: %m"); } link_ref(link); r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL); if (r < 0) { address_release(address); return log_error_errno(r, "Could not add address: %m"); } return 0; } int config_parse_broadcast( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *network = userdata; _cleanup_address_free_ Address *n = NULL; int r; assert(filename); assert(section); assert(lvalue); assert(rvalue); assert(data); r = address_new_static(network, section_line, &n); if (r < 0) return r; if (n->family == AF_INET6) { log_syntax(unit, LOG_ERR, filename, line, 0, "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue); return 0; } r = in_addr_from_string(AF_INET, rvalue, (union in_addr_union*) &n->broadcast); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Broadcast is invalid, ignoring assignment: %s", rvalue); return 0; } n->family = AF_INET; n = NULL; return 0; } int config_parse_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *network = userdata; _cleanup_address_free_ Address *n = NULL; const char *address, *e; union in_addr_union buffer; int r, f; assert(filename); assert(section); assert(lvalue); assert(rvalue); assert(data); if (streq(section, "Network")) { /* we are not in an Address section, so treat * this as the special '0' section */ section_line = 0; } r = address_new_static(network, section_line, &n); if (r < 0) return r; /* Address=address/prefixlen */ /* prefixlen */ e = strchr(rvalue, '/'); if (e) { unsigned i; r = safe_atou(e + 1, &i); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Prefix length is invalid, ignoring assignment: %s", e + 1); return 0; } n->prefixlen = (unsigned char) i; address = strndupa(rvalue, e - rvalue); } else address = rvalue; r = in_addr_from_string_auto(address, &f, &buffer); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Address is invalid, ignoring assignment: %s", address); return 0; } if (!e && f == AF_INET) { r = in_addr_default_prefixlen(&buffer.in, &n->prefixlen); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Prefix length not specified, and a default one can not be deduced for '%s', ignoring assignment", address); return 0; } } if (n->family != AF_UNSPEC && f != n->family) { log_syntax(unit, LOG_ERR, filename, line, 0, "Address is incompatible, ignoring assignment: %s", address); return 0; } n->family = f; if (streq(lvalue, "Address")) n->in_addr = buffer; else n->in_addr_peer = buffer; if (n->family == AF_INET && n->broadcast.s_addr == 0) n->broadcast.s_addr = n->in_addr.in.s_addr | htonl(0xfffffffflu >> n->prefixlen); n = NULL; return 0; } int config_parse_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *network = userdata; _cleanup_address_free_ Address *n = NULL; char *label; int r; assert(filename); assert(section); assert(lvalue); assert(rvalue); assert(data); r = address_new_static(network, section_line, &n); if (r < 0) return r; label = strdup(rvalue); if (!label) return log_oom(); if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) { log_syntax(unit, LOG_ERR, filename, line, 0, "Interface label is not ASCII clean or is too long, ignoring assignment: %s", rvalue); free(label); return 0; } free(n->label); if (*label) n->label = label; else { free(label); n->label = NULL; } n = NULL; return 0; } bool address_is_ready(const Address *a) { assert(a); return !(a->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED)); } systemd-229/src/network/networkd-address.h000066400000000000000000000060101265713322000207670ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "in-addr-util.h" typedef struct Address Address; #include "networkd-link.h" #include "networkd-network.h" #include "networkd.h" #define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU struct Address { Network *network; unsigned section; Link *link; int family; unsigned char prefixlen; unsigned char scope; uint32_t flags; char *label; struct in_addr broadcast; struct ifa_cacheinfo cinfo; union in_addr_union in_addr; union in_addr_union in_addr_peer; bool ip_masquerade_done:1; LIST_FIELDS(Address, addresses); }; int address_new_static(Network *network, unsigned section, Address **ret); int address_new(Address **ret); void address_free(Address *address); int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); int address_update(Address *address, unsigned char flags, unsigned char scope, struct ifa_cacheinfo *cinfo); int address_drop(Address *address); int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback, bool update); int address_remove(Address *address, Link *link, sd_netlink_message_handler_t callback); bool address_equal(Address *a1, Address *a2); bool address_is_ready(const Address *a); DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free); #define _cleanup_address_free_ _cleanup_(address_freep) int config_parse_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_broadcast(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); systemd-229/src/network/networkd-dhcp4.c000066400000000000000000000564631265713322000203600ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013-2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "dhcp-lease-internal.h" #include "hostname-util.h" #include "network-internal.h" #include "networkd-link.h" static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(link); assert(link->dhcp4_messages > 0); link->dhcp4_messages --; r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) { log_link_error_errno(link, r, "Could not set DHCPv4 route: %m"); link_enter_failed(link); } if (link->dhcp4_messages == 0) { link->dhcp4_configured = true; link_check_ready(link); } return 1; } static int link_set_dhcp_routes(Link *link) { struct in_addr gateway; _cleanup_free_ sd_dhcp_route **static_routes = NULL; int r, n, i; assert(link); assert(link->dhcp_lease); r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway); if (r < 0 && r != -ENODATA) return log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m"); if (r >= 0) { struct in_addr address; _cleanup_route_free_ Route *route = NULL; _cleanup_route_free_ Route *route_gw = NULL; r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); if (r < 0) return log_link_warning_errno(link, r, "DHCP error: could not get address: %m"); r = route_new(&route); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); route->protocol = RTPROT_DHCP; r = route_new(&route_gw); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); /* The dhcp netmask may mask out the gateway. Add an explicit * route for the gw host so that we can route no matter the * netmask or existing kernel route tables. */ route_gw->family = AF_INET; route_gw->dst.in = gateway; route_gw->dst_prefixlen = 32; route_gw->prefsrc.in = address; route_gw->scope = RT_SCOPE_LINK; route_gw->protocol = RTPROT_DHCP; route_gw->priority = link->network->dhcp_route_metric; r = route_configure(route_gw, link, &dhcp4_route_handler); if (r < 0) return log_link_warning_errno(link, r, "Could not set host route: %m"); link->dhcp4_messages ++; route->family = AF_INET; route->gw.in = gateway; route->prefsrc.in = address; route->priority = link->network->dhcp_route_metric; r = route_configure(route, link, &dhcp4_route_handler); if (r < 0) { log_link_warning_errno(link, r, "Could not set routes: %m"); link_enter_failed(link); return r; } link->dhcp4_messages ++; } n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes); if (n == -ENODATA) return 0; if (n < 0) return log_link_warning_errno(link, n, "DHCP error: could not get routes: %m"); for (i = 0; i < n; i++) { _cleanup_route_free_ Route *route = NULL; r = route_new(&route); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); route->family = AF_INET; route->protocol = RTPROT_DHCP; assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0); assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0); assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0); route->priority = link->network->dhcp_route_metric; r = route_configure(route, link, &dhcp4_route_handler); if (r < 0) return log_link_warning_errno(link, r, "Could not set host route: %m"); link->dhcp4_messages ++; } return 0; } static int dhcp_lease_lost(Link *link) { _cleanup_address_free_ Address *address = NULL; struct in_addr addr; struct in_addr netmask; struct in_addr gateway; unsigned prefixlen = 0; int r; assert(link); assert(link->dhcp_lease); log_link_warning(link, "DHCP lease lost"); if (link->network->dhcp_use_routes) { _cleanup_free_ sd_dhcp_route **routes = NULL; int n, i; n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes); if (n >= 0) { for (i = 0; i < n; i++) { _cleanup_route_free_ Route *route = NULL; r = route_new(&route); if (r >= 0) { route->family = AF_INET; assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0); assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0); assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0); route_remove(route, link, &link_route_remove_handler); } } } } r = address_new(&address); if (r >= 0) { r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway); if (r >= 0) { _cleanup_route_free_ Route *route_gw = NULL; _cleanup_route_free_ Route *route = NULL; r = route_new(&route_gw); if (r >= 0) { route_gw->family = AF_INET; route_gw->dst.in = gateway; route_gw->dst_prefixlen = 32; route_gw->scope = RT_SCOPE_LINK; route_remove(route_gw, link, &link_route_remove_handler); } r = route_new(&route); if (r >= 0) { route->family = AF_INET; route->gw.in = gateway; route_remove(route, link, &link_route_remove_handler); } } r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr); if (r >= 0) { r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask); if (r >= 0) prefixlen = in_addr_netmask_to_prefixlen(&netmask); address->family = AF_INET; address->in_addr.in = addr; address->prefixlen = prefixlen; address_remove(address, link, &link_address_remove_handler); } } if (link->network->dhcp_use_mtu) { uint16_t mtu; r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu); if (r >= 0 && link->original_mtu != mtu) { r = link_set_mtu(link, link->original_mtu); if (r < 0) { log_link_warning(link, "DHCP error: could not reset MTU"); link_enter_failed(link); return r; } } } if (link->network->dhcp_use_hostname) { const char *hostname = NULL; if (link->network->dhcp_hostname) hostname = link->network->dhcp_hostname; else (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname); if (hostname) { /* If a hostname was set due to the lease, then unset it now. */ r = link_set_hostname(link, NULL); if (r < 0) log_link_warning_errno(link, r, "Failed to reset transient hostname: %m"); } } link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease); link_dirty(link); link->dhcp4_configured = false; return 0; } static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(link); r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) { log_link_error_errno(link, r, "Could not set DHCPv4 address: %m"); link_enter_failed(link); } else if (r >= 0) manager_rtnl_process_address(rtnl, m, link->manager); link_set_dhcp_routes(link); return 1; } static int dhcp4_update_address(Link *link, struct in_addr *address, struct in_addr *netmask, uint32_t lifetime) { _cleanup_address_free_ Address *addr = NULL; unsigned prefixlen; int r; assert(address); assert(netmask); assert(lifetime); prefixlen = in_addr_netmask_to_prefixlen(netmask); r = address_new(&addr); if (r < 0) return r; addr->family = AF_INET; addr->in_addr.in.s_addr = address->s_addr; addr->cinfo.ifa_prefered = lifetime; addr->cinfo.ifa_valid = lifetime; addr->prefixlen = prefixlen; addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr; /* allow reusing an existing address and simply update its lifetime * in case it already exists */ r = address_configure(addr, link, &dhcp4_address_handler, true); if (r < 0) return r; return 0; } static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) { sd_dhcp_lease *lease; struct in_addr address; struct in_addr netmask; uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME; int r; assert(link); assert(client); assert(link->network); r = sd_dhcp_client_get_lease(client, &lease); if (r < 0) return log_link_warning_errno(link, r, "DHCP error: no lease: %m"); sd_dhcp_lease_unref(link->dhcp_lease); link->dhcp4_configured = false; link->dhcp_lease = sd_dhcp_lease_ref(lease); link_dirty(link); r = sd_dhcp_lease_get_address(lease, &address); if (r < 0) return log_link_warning_errno(link, r, "DHCP error: no address: %m"); r = sd_dhcp_lease_get_netmask(lease, &netmask); if (r < 0) return log_link_warning_errno(link, r, "DHCP error: no netmask: %m"); if (!link->network->dhcp_critical) { r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime); if (r < 0) return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m"); } r = dhcp4_update_address(link, &address, &netmask, lifetime); if (r < 0) { log_link_warning_errno(link, r, "Could not update IP address: %m"); link_enter_failed(link); return r; } return 0; } static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { sd_dhcp_lease *lease; struct in_addr address; struct in_addr netmask; struct in_addr gateway; unsigned prefixlen; uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME; int r; assert(client); assert(link); r = sd_dhcp_client_get_lease(client, &lease); if (r < 0) return log_link_error_errno(link, r, "DHCP error: No lease: %m"); r = sd_dhcp_lease_get_address(lease, &address); if (r < 0) return log_link_error_errno(link, r, "DHCP error: No address: %m"); r = sd_dhcp_lease_get_netmask(lease, &netmask); if (r < 0) return log_link_error_errno(link, r, "DHCP error: No netmask: %m"); prefixlen = in_addr_netmask_to_prefixlen(&netmask); r = sd_dhcp_lease_get_router(lease, &gateway); if (r < 0 && r != -ENODATA) return log_link_error_errno(link, r, "DHCP error: Could not get gateway: %m"); if (r >= 0) log_struct(LOG_INFO, LOG_LINK_INTERFACE(link), LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u", ADDRESS_FMT_VAL(address), prefixlen, ADDRESS_FMT_VAL(gateway)), "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address), "PREFIXLEN=%u", prefixlen, "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(gateway), NULL); else log_struct(LOG_INFO, LOG_LINK_INTERFACE(link), LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u", ADDRESS_FMT_VAL(address), prefixlen), "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address), "PREFIXLEN=%u", prefixlen, NULL); link->dhcp_lease = sd_dhcp_lease_ref(lease); link_dirty(link); if (link->network->dhcp_use_mtu) { uint16_t mtu; r = sd_dhcp_lease_get_mtu(lease, &mtu); if (r >= 0) { r = link_set_mtu(link, mtu); if (r < 0) log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu); } } if (link->network->dhcp_use_hostname) { const char *hostname = NULL; if (link->network->dhcp_hostname) hostname = link->network->dhcp_hostname; else (void) sd_dhcp_lease_get_hostname(lease, &hostname); if (hostname) { r = link_set_hostname(link, hostname); if (r < 0) log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname); } } if (link->network->dhcp_use_timezone) { const char *tz = NULL; (void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz); if (tz) { r = link_set_timezone(link, tz); if (r < 0) log_link_error_errno(link, r, "Failed to set timezone to '%s': %m", tz); } } if (!link->network->dhcp_critical) { r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime); if (r < 0) { log_link_warning_errno(link, r, "DHCP error: no lifetime: %m"); return r; } } r = dhcp4_update_address(link, &address, &netmask, lifetime); if (r < 0) { log_link_warning_errno(link, r, "Could not update IP address: %m"); link_enter_failed(link); return r; } return 0; } static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) { Link *link = userdata; int r = 0; assert(link); assert(link->network); assert(link->manager); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return; switch (event) { case SD_DHCP_CLIENT_EVENT_EXPIRED: case SD_DHCP_CLIENT_EVENT_STOP: case SD_DHCP_CLIENT_EVENT_IP_CHANGE: if (link->network->dhcp_critical) { log_link_error(link, "DHCPv4 connection considered system critical, ignoring request to reconfigure it."); return; } if (link->dhcp_lease) { r = dhcp_lease_lost(link); if (r < 0) { link_enter_failed(link); return; } } if (event == SD_DHCP_CLIENT_EVENT_IP_CHANGE) { r = dhcp_lease_acquired(client, link); if (r < 0) { link_enter_failed(link); return; } } break; case SD_DHCP_CLIENT_EVENT_RENEW: r = dhcp_lease_renew(client, link); if (r < 0) { link_enter_failed(link); return; } break; case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE: r = dhcp_lease_acquired(client, link); if (r < 0) { link_enter_failed(link); return; } break; default: if (event < 0) log_link_warning_errno(link, event, "DHCP error: Client failed: %m"); else log_link_warning(link, "DHCP unknown event: %i", event); break; } return; } int dhcp4_configure(Link *link) { int r; assert(link); assert(link->network); assert(link->network->dhcp & ADDRESS_FAMILY_IPV4); if (!link->dhcp_client) { r = sd_dhcp_client_new(&link->dhcp_client); if (r < 0) return r; } r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0); if (r < 0) return r; r = sd_dhcp_client_set_mac(link->dhcp_client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER); if (r < 0) return r; r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex); if (r < 0) return r; r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp4_handler, link); if (r < 0) return r; r = sd_dhcp_client_set_request_broadcast(link->dhcp_client, link->network->dhcp_broadcast); if (r < 0) return r; if (link->mtu) { r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu); if (r < 0) return r; } if (link->network->dhcp_use_mtu) { r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_INTERFACE_MTU); if (r < 0) return r; } if (link->network->dhcp_use_routes) { r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_STATIC_ROUTE); if (r < 0) return r; r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE); if (r < 0) return r; } /* Always acquire the timezone and NTP */ r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER); if (r < 0) return r; r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE); if (r < 0) return r; if (link->network->dhcp_send_hostname) { _cleanup_free_ char *hostname = NULL; const char *hn = NULL; if (!link->network->dhcp_hostname) { hostname = gethostname_malloc(); if (!hostname) return -ENOMEM; hn = hostname; } else hn = link->network->dhcp_hostname; if (!is_localhost(hn)) { r = sd_dhcp_client_set_hostname(link->dhcp_client, hn); if (r < 0) return r; } } if (link->network->dhcp_vendor_class_identifier) { r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client, link->network->dhcp_vendor_class_identifier); if (r < 0) return r; } switch (link->network->dhcp_client_identifier) { case DHCP_CLIENT_ID_DUID: /* Library defaults to this. */ break; case DHCP_CLIENT_ID_MAC: r = sd_dhcp_client_set_client_id(link->dhcp_client, ARPHRD_ETHER, (const uint8_t *) &link->mac, sizeof (link->mac)); if (r < 0) return r; break; default: assert_not_reached("Unknown client identifier type."); } return 0; } systemd-229/src/network/networkd-dhcp6.c000066400000000000000000000163701265713322000203530ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-dhcp6-client.h" #include "network-internal.h" #include "networkd-link.h" static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link); static int dhcp6_lease_information_acquired(sd_dhcp6_client *client, Link *link) { return 0; } static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(link); r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) { if (link->rtnl_extended_attrs) { log_link_warning(link, "Could not set extended netlink attributes, reverting to fallback mechanism"); link->rtnl_extended_attrs = false; dhcp6_lease_address_acquired(link->dhcp6_client, link); return 1; } log_link_error_errno(link, r, "Could not set DHCPv6 address: %m"); link_enter_failed(link); } else if (r >= 0) manager_rtnl_process_address(rtnl, m, link->manager); return 1; } static int dhcp6_address_change(Link *link, struct in6_addr *ip6_addr, uint32_t lifetime_preferred, uint32_t lifetime_valid) { int r; _cleanup_address_free_ Address *addr = NULL; r = address_new(&addr); if (r < 0) return r; addr->family = AF_INET6; memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr)); addr->flags = IFA_F_NOPREFIXROUTE; addr->prefixlen = 128; addr->cinfo.ifa_prefered = lifetime_preferred; addr->cinfo.ifa_valid = lifetime_valid; log_link_info(link, "DHCPv6 address "SD_NDISC_ADDRESS_FORMAT_STR"/%d timeout preferred %d valid %d", SD_NDISC_ADDRESS_FORMAT_VAL(addr->in_addr.in6), addr->prefixlen, lifetime_preferred, lifetime_valid); r = address_configure(addr, link, dhcp6_address_handler, true); if (r < 0) log_link_warning_errno(link, r, "Could not assign DHCPv6 address: %m"); return r; } static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) { int r; sd_dhcp6_lease *lease; struct in6_addr ip6_addr; uint32_t lifetime_preferred, lifetime_valid; r = sd_dhcp6_client_get_lease(client, &lease); if (r < 0) return r; sd_dhcp6_lease_reset_address_iter(lease); while (sd_dhcp6_lease_get_address(lease, &ip6_addr, &lifetime_preferred, &lifetime_valid) >= 0) { r = dhcp6_address_change(link, &ip6_addr, lifetime_preferred, lifetime_valid); if (r < 0) return r; } return 0; } static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) { int r; Link *link = userdata; assert(link); assert(link->network); assert(link->manager); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return; switch(event) { case SD_DHCP6_CLIENT_EVENT_STOP: case SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE: case SD_DHCP6_CLIENT_EVENT_RETRANS_MAX: if (sd_dhcp6_client_get_lease(client, NULL) >= 0) log_link_warning(link, "DHCPv6 lease lost"); link->dhcp6_configured = false; break; case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE: r = dhcp6_lease_address_acquired(client, link); if (r < 0) { link_enter_failed(link); return; } /* fall through */ case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST: r = dhcp6_lease_information_acquired(client, link); if (r < 0) { link_enter_failed(link); return; } link->dhcp6_configured = true; break; default: if (event < 0) log_link_warning_errno(link, event, "DHCPv6 error: %m"); else log_link_warning(link, "DHCPv6 unknown event: %d", event); return; } link_check_ready(link); } int dhcp6_request_address(Link *link) { int r, inf_req; bool running; assert(link); assert(link->dhcp6_client); r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req); if (r < 0) return r; if (!inf_req) return 0; r = sd_dhcp6_client_is_running(link->dhcp6_client); if (r < 0) return r; else running = !!r; if (running) { r = sd_dhcp6_client_stop(link->dhcp6_client); if (r < 0) return r; } r = sd_dhcp6_client_set_information_request(link->dhcp6_client, false); if (r < 0) return r; if (running) { r = sd_dhcp6_client_start(link->dhcp6_client); if (r < 0) return r; } return 0; } int dhcp6_configure(Link *link) { sd_dhcp6_client *client = NULL; int r; assert(link); if (link->dhcp6_client) return 0; r = sd_dhcp6_client_new(&client); if (r < 0) return r; r = sd_dhcp6_client_attach_event(client, NULL, 0); if (r < 0) goto error; r = sd_dhcp6_client_set_information_request(client, true); if (r < 0) goto error; r = sd_dhcp6_client_set_mac(client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER); if (r < 0) goto error; r = sd_dhcp6_client_set_index(client, link->ifindex); if (r < 0) goto error; r = sd_dhcp6_client_set_callback(client, dhcp6_handler, link); if (r < 0) goto error; link->dhcp6_client = client; return 0; error: sd_dhcp6_client_unref(client); return r; } systemd-229/src/network/networkd-fdb.c000066400000000000000000000170421265713322000200770ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "conf-parser.h" #include "netlink-util.h" #include "networkd-fdb.h" #include "networkd.h" #include "util.h" /* create a new FDB entry or get an existing one. */ int fdb_entry_new_static(Network *const network, const unsigned section, FdbEntry **ret) { _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL; struct ether_addr *mac_addr = NULL; assert(network); /* search entry in hashmap first. */ if(section) { fdb_entry = hashmap_get(network->fdb_entries_by_section, UINT_TO_PTR(section)); if (fdb_entry) { *ret = fdb_entry; fdb_entry = NULL; return 0; } } /* allocate space for MAC address. */ mac_addr = new0(struct ether_addr, 1); if (!mac_addr) return -ENOMEM; /* allocate space for and FDB entry. */ fdb_entry = new0(FdbEntry, 1); if (!fdb_entry) { /* free previously allocated space for mac_addr. */ free(mac_addr); return -ENOMEM; } /* init FDB structure. */ fdb_entry->network = network; fdb_entry->mac_addr = mac_addr; LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry); if (section) { fdb_entry->section = section; hashmap_put(network->fdb_entries_by_section, UINT_TO_PTR(fdb_entry->section), fdb_entry); } /* return allocated FDB structure. */ *ret = fdb_entry; fdb_entry = NULL; return 0; } static int set_fdb_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { Link *link = userdata; int r; assert(link); r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) log_link_error_errno(link, r, "Could not add FDB entry: %m"); return 1; } /* send a request to the kernel to add a FDB entry in its static MAC table. */ int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; sd_netlink *rtnl; int r; assert(link); assert(link->manager); assert(fdb_entry); rtnl = link->manager->rtnl; /* create new RTM message */ r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE); if (r < 0) return rtnl_log_create_error(r); /* only NTF_SELF flag supported. */ r = sd_rtnl_message_neigh_set_flags(req, NTF_SELF); if (r < 0) return rtnl_log_create_error(r); /* only NUD_PERMANENT state supported. */ r = sd_rtnl_message_neigh_set_state(req, NUD_NOARP | NUD_PERMANENT); if (r < 0) return rtnl_log_create_error(r); r = sd_netlink_message_append_ether_addr(req, NDA_LLADDR, fdb_entry->mac_addr); if (r < 0) return rtnl_log_create_error(r); /* VLAN Id is optional. We'll add VLAN Id only if it's specified. */ if (0 != fdb_entry->vlan_id) { r = sd_netlink_message_append_u16(req, NDA_VLAN, fdb_entry->vlan_id); if (r < 0) return rtnl_log_create_error(r); } /* send message to the kernel to update its internal static MAC table. */ r = sd_netlink_call_async(rtnl, req, set_fdb_handler, link, 0, NULL); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return 0; } /* remove and FDB entry. */ void fdb_entry_free(FdbEntry *fdb_entry) { if(!fdb_entry) return; if(fdb_entry->network) { LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, fdb_entry); if (fdb_entry->section) hashmap_remove(fdb_entry->network->fdb_entries_by_section, UINT_TO_PTR(fdb_entry->section)); } free(fdb_entry->mac_addr); free(fdb_entry); } /* parse the HW address from config files. */ int config_parse_fdb_hwaddr( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *network = userdata; _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL; int r; assert(filename); assert(section); assert(lvalue); assert(rvalue); assert(data); r = fdb_entry_new_static(network, section_line, &fdb_entry); if (r < 0) return log_oom(); /* read in the MAC address for the FDB table. */ r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &fdb_entry->mac_addr->ether_addr_octet[0], &fdb_entry->mac_addr->ether_addr_octet[1], &fdb_entry->mac_addr->ether_addr_octet[2], &fdb_entry->mac_addr->ether_addr_octet[3], &fdb_entry->mac_addr->ether_addr_octet[4], &fdb_entry->mac_addr->ether_addr_octet[5]); if (ETHER_ADDR_LEN != r) { log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue); return 0; } fdb_entry = NULL; return 0; } /* parse the VLAN Id from config files. */ int config_parse_fdb_vlan_id( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *network = userdata; _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL; int r; assert(filename); assert(section); assert(lvalue); assert(rvalue); assert(data); r = fdb_entry_new_static(network, section_line, &fdb_entry); if (r < 0) return log_oom(); r = config_parse_unsigned(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &fdb_entry->vlan_id, userdata); if (r < 0) return r; fdb_entry = NULL; return 0; } systemd-229/src/network/networkd-fdb.h000066400000000000000000000033521265713322000201030ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright (C) 2014 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct FdbEntry FdbEntry; #include "networkd-network.h" #include "networkd.h" struct FdbEntry { Network *network; unsigned section; struct ether_addr *mac_addr; uint16_t vlan_id; LIST_FIELDS(FdbEntry, static_fdb_entries); }; int fdb_entry_new_static(Network *const network, const unsigned section, FdbEntry **ret); void fdb_entry_free(FdbEntry *fdb_entry); int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry); DEFINE_TRIVIAL_CLEANUP_FUNC(FdbEntry*, fdb_entry_free); #define _cleanup_fdbentry_free_ _cleanup_(fdb_entry_freep) int config_parse_fdb_hwaddr(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_fdb_vlan_id(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); systemd-229/src/network/networkd-ipv4ll.c000066400000000000000000000157001265713322000205550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013-2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "network-internal.h" #include "networkd-link.h" static int ipv4ll_address_lost(Link *link) { _cleanup_address_free_ Address *address = NULL; _cleanup_route_free_ Route *route = NULL; struct in_addr addr; int r; assert(link); link->ipv4ll_route = false; link->ipv4ll_address = false; r = sd_ipv4ll_get_address(link->ipv4ll, &addr); if (r < 0) return 0; log_link_debug(link, "IPv4 link-local release %u.%u.%u.%u", ADDRESS_FMT_VAL(addr)); r = address_new(&address); if (r < 0) { log_link_error_errno(link, r, "Could not allocate address: %m"); return r; } address->family = AF_INET; address->in_addr.in = addr; address->prefixlen = 16; address->scope = RT_SCOPE_LINK; address_remove(address, link, &link_address_remove_handler); r = route_new(&route); if (r < 0) { log_link_error_errno(link, r, "Could not allocate route: %m"); return r; } route->family = AF_INET; route->scope = RT_SCOPE_LINK; route->priority = IPV4LL_ROUTE_METRIC; route_remove(route, link, &link_route_remove_handler); link_check_ready(link); return 0; } static int ipv4ll_route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(link); assert(!link->ipv4ll_route); r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) { log_link_error_errno(link, r, "could not set ipv4ll route: %m"); link_enter_failed(link); } link->ipv4ll_route = true; if (link->ipv4ll_address == true) link_check_ready(link); return 1; } static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(link); assert(!link->ipv4ll_address); r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) { log_link_error_errno(link, r, "could not set ipv4ll address: %m"); link_enter_failed(link); } else if (r >= 0) manager_rtnl_process_address(rtnl, m, link->manager); link->ipv4ll_address = true; if (link->ipv4ll_route == true) link_check_ready(link); return 1; } static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) { _cleanup_address_free_ Address *ll_addr = NULL; _cleanup_route_free_ Route *route = NULL; struct in_addr address; int r; assert(ll); assert(link); r = sd_ipv4ll_get_address(ll, &address); if (r == -ENOENT) return 0; else if (r < 0) return r; log_link_debug(link, "IPv4 link-local claim %u.%u.%u.%u", ADDRESS_FMT_VAL(address)); r = address_new(&ll_addr); if (r < 0) return r; ll_addr->family = AF_INET; ll_addr->in_addr.in = address; ll_addr->prefixlen = 16; ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen); ll_addr->scope = RT_SCOPE_LINK; r = address_configure(ll_addr, link, ipv4ll_address_handler, false); if (r < 0) return r; link->ipv4ll_address = false; r = route_new(&route); if (r < 0) return r; route->family = AF_INET; route->scope = RT_SCOPE_LINK; route->protocol = RTPROT_STATIC; route->priority = IPV4LL_ROUTE_METRIC; r = route_configure(route, link, ipv4ll_route_handler); if (r < 0) return r; link->ipv4ll_route = false; return 0; } static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){ Link *link = userdata; int r; assert(link); assert(link->network); assert(link->manager); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return; switch(event) { case SD_IPV4LL_EVENT_STOP: case SD_IPV4LL_EVENT_CONFLICT: r = ipv4ll_address_lost(link); if (r < 0) { link_enter_failed(link); return; } break; case SD_IPV4LL_EVENT_BIND: r = ipv4ll_address_claimed(ll, link); if (r < 0) { link_enter_failed(link); return; } break; default: log_link_warning(link, "IPv4 link-local unknown event: %d", event); break; } } int ipv4ll_configure(Link *link) { uint64_t seed; int r; assert(link); assert(link->network); assert(link->network->link_local & ADDRESS_FAMILY_IPV4); if (!link->ipv4ll) { r = sd_ipv4ll_new(&link->ipv4ll); if (r < 0) return r; } if (link->udev_device) { r = net_get_unique_predictable_data(link->udev_device, &seed); if (r >= 0) { assert_cc(sizeof(unsigned) <= 8); r = sd_ipv4ll_set_address_seed(link->ipv4ll, (unsigned)seed); if (r < 0) return r; } } r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0); if (r < 0) return r; r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac); if (r < 0) return r; r = sd_ipv4ll_set_index(link->ipv4ll, link->ifindex); if (r < 0) return r; r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link); if (r < 0) return r; return 0; } systemd-229/src/network/networkd-link-bus.c000066400000000000000000000075501265713322000210730ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-util.h" #include "networkd-link.h" #include "networkd.h" #include "parse-util.h" #include "strv.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState); const sd_bus_vtable link_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Link, operstate), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_VTABLE_END }; static char *link_bus_path(Link *link) { _cleanup_free_ char *ifindex = NULL; char *p; int r; assert(link); assert(link->ifindex > 0); if (asprintf(&ifindex, "%d", link->ifindex) < 0) return NULL; r = sd_bus_path_encode("/org/freedesktop/network1/link", ifindex, &p); if (r < 0) return NULL; return p; } int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; Manager *m = userdata; unsigned c = 0; Link *link; Iterator i; assert(bus); assert(path); assert(m); assert(nodes); l = new0(char*, hashmap_size(m->links) + 1); if (!l) return -ENOMEM; HASHMAP_FOREACH(link, m->links, i) { char *p; p = link_bus_path(link); if (!p) return -ENOMEM; l[c++] = p; } l[c] = NULL; *nodes = l; l = NULL; return 1; } int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { _cleanup_free_ char *identifier = NULL; Manager *m = userdata; Link *link; int ifindex, r; assert(bus); assert(path); assert(interface); assert(m); assert(found); r = sd_bus_path_decode(path, "/org/freedesktop/network1/link", &identifier); if (r <= 0) return 0; r = parse_ifindex(identifier, &ifindex); if (r < 0) return 0; r = link_get(m, ifindex, &link); if (r < 0) return 0; *found = link; return 1; } int link_send_changed(Link *link, const char *property, ...) { _cleanup_free_ char *p = NULL; char **l; assert(link); assert(link->manager); if (!link->manager->bus) return 0; /* replace with assert when we have kdbus */ l = strv_from_stdarg_alloca(property); p = link_bus_path(link); if (!p) return -ENOMEM; return sd_bus_emit_properties_changed_strv( link->manager->bus, p, "org.freedesktop.network1.Link", l); } systemd-229/src/network/networkd-link.c000066400000000000000000003041271265713322000203040ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "bus-util.h" #include "dhcp-lease-internal.h" #include "fd-util.h" #include "fileio.h" #include "netlink-util.h" #include "network-internal.h" #include "networkd-link.h" #include "networkd-netdev.h" #include "set.h" #include "socket-util.h" #include "stdio-util.h" #include "string-table.h" #include "udev-util.h" #include "util.h" #include "virt.h" bool link_dhcp6_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; if (!link->network) return false; return link->network->dhcp & ADDRESS_FAMILY_IPV6; } bool link_dhcp4_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; if (!link->network) return false; return link->network->dhcp & ADDRESS_FAMILY_IPV4; } bool link_dhcp4_server_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; if (!link->network) return false; return link->network->dhcp_server; } bool link_ipv4ll_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; if (!link->network) return false; return link->network->link_local & ADDRESS_FAMILY_IPV4; } bool link_ipv6ll_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; if (!link->network) return false; return link->network->link_local & ADDRESS_FAMILY_IPV6; } bool link_lldp_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; if (!link->network) return false; if (link->network->bridge) return false; return link->network->lldp; } static bool link_ipv4_forward_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; if (!link->network) return false; if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID) return false; return link->network->ip_forward & ADDRESS_FAMILY_IPV4; } static bool link_ipv6_forward_enabled(Link *link) { if (!socket_ipv6_is_supported()) return false; if (link->flags & IFF_LOOPBACK) return false; if (!link->network) return false; if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID) return false; return link->network->ip_forward & ADDRESS_FAMILY_IPV6; } bool link_ipv6_accept_ra_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; if (!link->network) return false; /* If unset use system default (enabled if local forwarding is disabled. * disabled if local forwarding is enabled). * If set, ignore or enforce RA independent of local forwarding state. */ if (link->network->ipv6_accept_ra < 0) /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */ return !link_ipv6_forward_enabled(link); else if (link->network->ipv6_accept_ra > 0) /* accept RA even if ip_forward is enabled */ return true; else /* ignore RA */ return false; } static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) { if (!socket_ipv6_is_supported()) return _IPV6_PRIVACY_EXTENSIONS_INVALID; if (link->flags & IFF_LOOPBACK) return _IPV6_PRIVACY_EXTENSIONS_INVALID; if (!link->network) return _IPV6_PRIVACY_EXTENSIONS_INVALID; return link->network->ipv6_privacy_extensions; } void link_update_operstate(Link *link) { LinkOperationalState operstate; assert(link); if (link->kernel_operstate == IF_OPER_DORMANT) operstate = LINK_OPERSTATE_DORMANT; else if (link_has_carrier(link)) { Address *address; uint8_t scope = RT_SCOPE_NOWHERE; Iterator i; /* if we have carrier, check what addresses we have */ SET_FOREACH(address, link->addresses, i) { if (!address_is_ready(address)) continue; if (address->scope < scope) scope = address->scope; } /* for operstate we also take foreign addresses into account */ SET_FOREACH(address, link->addresses_foreign, i) { if (!address_is_ready(address)) continue; if (address->scope < scope) scope = address->scope; } if (scope < RT_SCOPE_SITE) /* universally accessible addresses found */ operstate = LINK_OPERSTATE_ROUTABLE; else if (scope < RT_SCOPE_HOST) /* only link or site local addresses found */ operstate = LINK_OPERSTATE_DEGRADED; else /* no useful addresses found */ operstate = LINK_OPERSTATE_CARRIER; } else if (link->flags & IFF_UP) operstate = LINK_OPERSTATE_NO_CARRIER; else operstate = LINK_OPERSTATE_OFF; if (link->operstate != operstate) { link->operstate = operstate; link_send_changed(link, "OperationalState", NULL); link_dirty(link); manager_dirty(link->manager); } } #define FLAG_STRING(string, flag, old, new) \ (((old ^ new) & flag) \ ? ((old & flag) ? (" -" string) : (" +" string)) \ : "") static int link_update_flags(Link *link, sd_netlink_message *m) { unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags; uint8_t operstate; int r; assert(link); r = sd_rtnl_message_link_get_flags(m, &flags); if (r < 0) return log_link_warning_errno(link, r, "Could not get link flags: %m"); r = sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &operstate); if (r < 0) /* if we got a message without operstate, take it to mean the state was unchanged */ operstate = link->kernel_operstate; if ((link->flags == flags) && (link->kernel_operstate == operstate)) return 0; if (link->flags != flags) { log_link_debug(link, "Flags change:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags), FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags), FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags), FLAG_STRING("UP", IFF_UP, link->flags, flags), FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags), FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags), FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags), FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags), FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags), FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags), FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags), FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags), FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags), FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags), FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags), FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags), FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags), FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags), FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags)); unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP | IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING | IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT | IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL | IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP | IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO); unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags); unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags); /* link flags are currently at most 18 bits, let's align to * printing 20 */ if (unknown_flags_added) log_link_debug(link, "Unknown link flags gained: %#.5x (ignoring)", unknown_flags_added); if (unknown_flags_removed) log_link_debug(link, "Unknown link flags lost: %#.5x (ignoring)", unknown_flags_removed); } link->flags = flags; link->kernel_operstate = operstate; link_update_operstate(link); return 0; } static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { _cleanup_link_unref_ Link *link = NULL; uint16_t type; const char *ifname; int r, ifindex; assert(manager); assert(message); assert(ret); r = sd_netlink_message_get_type(message, &type); if (r < 0) return r; else if (type != RTM_NEWLINK) return -EINVAL; r = sd_rtnl_message_link_get_ifindex(message, &ifindex); if (r < 0) return r; else if (ifindex <= 0) return -EINVAL; r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname); if (r < 0) return r; link = new0(Link, 1); if (!link) return -ENOMEM; link->n_ref = 1; link->manager = manager; link->state = LINK_STATE_PENDING; link->rtnl_extended_attrs = true; link->ifindex = ifindex; link->ifname = strdup(ifname); if (!link->ifname) return -ENOMEM; r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac); if (r < 0) log_link_debug(link, "MAC address not found for new device, continuing without"); r = asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex); if (r < 0) return -ENOMEM; r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex); if (r < 0) return -ENOMEM; r = asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex); if (r < 0) return -ENOMEM; r = hashmap_ensure_allocated(&manager->links, NULL); if (r < 0) return r; r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link); if (r < 0) return r; r = link_update_flags(link, message); if (r < 0) return r; *ret = link; link = NULL; return 0; } static void link_free(Link *link) { Address *address; Iterator i; Link *carrier; if (!link) return; while (!set_isempty(link->addresses)) address_free(set_first(link->addresses)); while (!set_isempty(link->addresses_foreign)) address_free(set_first(link->addresses_foreign)); link->addresses = set_free(link->addresses); link->addresses_foreign = set_free(link->addresses_foreign); while ((address = link->pool_addresses)) { LIST_REMOVE(addresses, link->pool_addresses, address); address_free(address); } sd_dhcp_server_unref(link->dhcp_server); sd_dhcp_client_unref(link->dhcp_client); sd_dhcp_lease_unref(link->dhcp_lease); free(link->lease_file); sd_lldp_unref(link->lldp); free(link->lldp_file); sd_ipv4ll_unref(link->ipv4ll); sd_dhcp6_client_unref(link->dhcp6_client); sd_ndisc_unref(link->ndisc_router_discovery); if (link->manager) hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)); free(link->ifname); (void)unlink(link->state_file); free(link->state_file); udev_device_unref(link->udev_device); HASHMAP_FOREACH (carrier, link->bound_to_links, i) hashmap_remove(link->bound_to_links, INT_TO_PTR(carrier->ifindex)); hashmap_free(link->bound_to_links); HASHMAP_FOREACH (carrier, link->bound_by_links, i) hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex)); hashmap_free(link->bound_by_links); free(link); } Link *link_unref(Link *link) { if (!link) return NULL; assert(link->n_ref > 0); link->n_ref --; if (link->n_ref > 0) return NULL; link_free(link); return NULL; } Link *link_ref(Link *link) { if (!link) return NULL; assert(link->n_ref > 0); link->n_ref ++; return link; } int link_get(Manager *m, int ifindex, Link **ret) { Link *link; assert(m); assert(ifindex); assert(ret); link = hashmap_get(m->links, INT_TO_PTR(ifindex)); if (!link) return -ENODEV; *ret = link; return 0; } static void link_set_state(Link *link, LinkState state) { assert(link); if (link->state == state) return; link->state = state; link_send_changed(link, "AdministrativeState", NULL); return; } static void link_enter_unmanaged(Link *link) { assert(link); log_link_debug(link, "Unmanaged"); link_set_state(link, LINK_STATE_UNMANAGED); link_dirty(link); } static int link_stop_clients(Link *link) { int r = 0, k; assert(link); assert(link->manager); assert(link->manager->event); if (link->dhcp_client) { k = sd_dhcp_client_stop(link->dhcp_client); if (k < 0) r = log_link_warning_errno(link, r, "Could not stop DHCPv4 client: %m"); } if (link->ipv4ll) { k = sd_ipv4ll_stop(link->ipv4ll); if (k < 0) r = log_link_warning_errno(link, r, "Could not stop IPv4 link-local: %m"); } if (link->dhcp6_client) { k = sd_dhcp6_client_stop(link->dhcp6_client); if (k < 0) r = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m"); } if (link->ndisc_router_discovery) { k = sd_ndisc_stop(link->ndisc_router_discovery); if (k < 0) r = log_link_warning_errno(link, r, "Could not stop IPv6 Router Discovery: %m"); } if (link->lldp) { k = sd_lldp_stop(link->lldp); if (k < 0) r = log_link_warning_errno(link, r, "Could not stop LLDP: %m"); } return r; } void link_enter_failed(Link *link) { assert(link); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return; log_link_warning(link, "Failed"); link_set_state(link, LINK_STATE_FAILED); link_stop_clients(link); link_dirty(link); } static Address* link_find_dhcp_server_address(Link *link) { Address *address; assert(link); assert(link->network); /* The first statically configured address if there is any */ LIST_FOREACH(addresses, address, link->network->static_addresses) { if (address->family != AF_INET) continue; if (in_addr_is_null(address->family, &address->in_addr)) continue; return address; } /* If that didn't work, find a suitable address we got from the pool */ LIST_FOREACH(addresses, address, link->pool_addresses) { if (address->family != AF_INET) continue; return address; } return NULL; } static int link_enter_configured(Link *link) { assert(link); assert(link->network); assert(link->state == LINK_STATE_SETTING_ROUTES); log_link_info(link, "Configured"); link_set_state(link, LINK_STATE_CONFIGURED); link_dirty(link); return 0; } void link_check_ready(Link *link) { Address *a; Iterator i; assert(link); if (!link->network) return; if (!link->static_configured) return; if (link_ipv4ll_enabled(link)) if (!link->ipv4ll_address || !link->ipv4ll_route) return; if (link_ipv6ll_enabled(link)) if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) > 0) return; if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) && !link->dhcp4_configured) || (link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) && !link->dhcp6_configured) || (link_dhcp4_enabled(link) && link_dhcp6_enabled(link) && !link->dhcp4_configured && !link->dhcp6_configured)) return; if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured) return; SET_FOREACH(a, link->addresses, i) if (!address_is_ready(a)) return; if (link->state != LINK_STATE_CONFIGURED) link_enter_configured(link); return; } static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(link->link_messages > 0); assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES, LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED, LINK_STATE_LINGER)); link->link_messages --; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) log_link_warning_errno(link, r, "Could not set route: %m"); if (link->link_messages == 0) { log_link_debug(link, "Routes set"); link->static_configured = true; link_check_ready(link); } return 1; } static int link_enter_set_routes(Link *link) { Route *rt; int r; assert(link); assert(link->network); assert(link->state == LINK_STATE_SETTING_ADDRESSES); link_set_state(link, LINK_STATE_SETTING_ROUTES); LIST_FOREACH(routes, rt, link->network->static_routes) { r = route_configure(rt, link, &route_handler); if (r < 0) { log_link_warning_errno(link, r, "Could not set routes: %m"); link_enter_failed(link); return r; } link->link_messages ++; } if (link->link_messages == 0) { link->static_configured = true; link_check_ready(link); } else log_link_debug(link, "Setting routes"); return 0; } int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(m); assert(link); assert(link->ifname); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); if (r < 0 && r != -ESRCH) log_link_warning_errno(link, r, "Could not drop route: %m"); return 1; } static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(rtnl); assert(m); assert(link); assert(link->ifname); assert(link->link_messages > 0); assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES, LINK_STATE_FAILED, LINK_STATE_LINGER)); link->link_messages --; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) log_link_warning_errno(link, r, "could not set address: %m"); else if (r >= 0) manager_rtnl_process_address(rtnl, m, link->manager); if (link->link_messages == 0) { log_link_debug(link, "Addresses set"); link_enter_set_routes(link); } return 1; } static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) { _cleanup_free_ struct in_addr *addresses = NULL; size_t n_addresses = 0, n_allocated = 0; char **a; log_debug("Copying DNS server information from %s", link->ifname); if (!link->network) return 0; STRV_FOREACH(a, link->network->dns) { struct in_addr ia; /* Only look for IPv4 addresses */ if (inet_pton(AF_INET, *a, &ia) <= 0) continue; if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) return log_oom(); addresses[n_addresses++] = ia; } if (link->network->dhcp_use_dns && link->dhcp_lease) { const struct in_addr *da = NULL; int n; n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da); if (n > 0) { if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n)) return log_oom(); memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr)); n_addresses += n; } } if (n_addresses <= 0) return 0; return sd_dhcp_server_set_dns(s, addresses, n_addresses); } static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) { _cleanup_free_ struct in_addr *addresses = NULL; size_t n_addresses = 0, n_allocated = 0; char **a; if (!link->network) return 0; log_debug("Copying NTP server information from %s", link->ifname); STRV_FOREACH(a, link->network->ntp) { struct in_addr ia; /* Only look for IPv4 addresses */ if (inet_pton(AF_INET, *a, &ia) <= 0) continue; if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) return log_oom(); addresses[n_addresses++] = ia; } if (link->network->dhcp_use_ntp && link->dhcp_lease) { const struct in_addr *da = NULL; int n; n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da); if (n > 0) { if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n)) return log_oom(); memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr)); n_addresses += n; } } if (n_addresses <= 0) return 0; return sd_dhcp_server_set_ntp(s, addresses, n_addresses); } static int link_enter_set_addresses(Link *link) { Address *ad; int r; assert(link); assert(link->network); assert(link->state != _LINK_STATE_INVALID); link_set_state(link, LINK_STATE_SETTING_ADDRESSES); LIST_FOREACH(addresses, ad, link->network->static_addresses) { r = address_configure(ad, link, &address_handler, false); if (r < 0) { log_link_warning_errno(link, r, "Could not set addresses: %m"); link_enter_failed(link); return r; } link->link_messages ++; } /* now that we can figure out a default address for the dhcp server, start it */ if (link_dhcp4_server_enabled(link)) { Address *address; Link *uplink = NULL; bool acquired_uplink = false; address = link_find_dhcp_server_address(link); if (!address) { log_link_warning(link, "Failed to find suitable address for DHCPv4 server instance."); link_enter_failed(link); return 0; } /* use the server address' subnet as the pool */ r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen, link->network->dhcp_server_pool_offset, link->network->dhcp_server_pool_size); if (r < 0) return r; /* TODO: r = sd_dhcp_server_set_router(link->dhcp_server, &main_address->in_addr.in); if (r < 0) return r; */ if (link->network->dhcp_server_max_lease_time_usec > 0) { r = sd_dhcp_server_set_max_lease_time( link->dhcp_server, DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC)); if (r < 0) return r; } if (link->network->dhcp_server_default_lease_time_usec > 0) { r = sd_dhcp_server_set_default_lease_time( link->dhcp_server, DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC)); if (r < 0) return r; } if (link->network->dhcp_server_emit_dns) { if (link->network->n_dhcp_server_dns > 0) r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns); else { uplink = manager_find_uplink(link->manager, link); acquired_uplink = true; if (!uplink) { log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink."); r = 0; } else r = link_push_dns_to_dhcp_server(uplink, link->dhcp_server); } if (r < 0) log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m"); } if (link->network->dhcp_server_emit_ntp) { if (link->network->n_dhcp_server_ntp > 0) r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp); else { if (!acquired_uplink) uplink = manager_find_uplink(link->manager, link); if (!uplink) { log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink."); r = 0; } else r = link_push_ntp_to_dhcp_server(uplink, link->dhcp_server); } if (r < 0) log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m"); } if (link->network->dhcp_server_emit_timezone) { _cleanup_free_ char *buffer = NULL; const char *tz = NULL; if (link->network->dhcp_server_timezone) tz = link->network->dhcp_server_timezone; else { r = get_timezone(&buffer); if (r < 0) log_warning_errno(r, "Failed to determine timezone: %m"); else tz = buffer; } if (tz) { r = sd_dhcp_server_set_timezone(link->dhcp_server, tz); if (r < 0) return r; } } r = sd_dhcp_server_start(link->dhcp_server); if (r < 0) { log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m"); link_enter_failed(link); return 0; } log_link_debug(link, "Offering DHCPv4 leases"); } if (link->link_messages == 0) link_enter_set_routes(link); else log_link_debug(link, "Setting addresses"); return 0; } int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(m); assert(link); assert(link->ifname); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EADDRNOTAVAIL) log_link_warning_errno(link, r, "Could not drop address: %m"); return 1; } static int link_set_bridge_fdb(Link *const link) { FdbEntry *fdb_entry; int r = 0; LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) { r = fdb_entry_configure(link, fdb_entry); if(r < 0) { log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m"); break; } } return r; } static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; log_link_debug(link, "Set link"); r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) { log_link_error_errno(link, r, "Could not join netdev: %m"); link_enter_failed(link); return 1; } return 0; } static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { _cleanup_link_unref_ Link *link = userdata; const sd_bus_error *e; assert(m); assert(link); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; e = sd_bus_message_get_error(m); if (e) log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message); return 1; } int link_set_hostname(Link *link, const char *hostname) { int r; assert(link); assert(link->manager); log_link_debug(link, "Setting transient hostname: '%s'", strna(hostname)); if (!link->manager->bus) { /* TODO: replace by assert when we can rely on kdbus */ log_link_info(link, "Not connected to system bus, ignoring transient hostname."); return 0; } r = sd_bus_call_method_async( link->manager->bus, NULL, "org.freedesktop.hostname1", "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "SetHostname", set_hostname_handler, link, "sb", hostname, false); if (r < 0) return log_link_error_errno(link, r, "Could not set transient hostname: %m"); link_ref(link); return 0; } static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { _cleanup_link_unref_ Link *link = userdata; const sd_bus_error *e; assert(m); assert(link); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; e = sd_bus_message_get_error(m); if (e) log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message); return 1; } int link_set_timezone(Link *link, const char *tz) { int r; assert(link); assert(link->manager); assert(tz); log_link_debug(link, "Setting system timezone: '%s'", tz); if (!link->manager->bus) { log_link_info(link, "Not connected to system bus, ignoring timezone."); return 0; } r = sd_bus_call_method_async( link->manager->bus, NULL, "org.freedesktop.timedate1", "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "SetTimezone", set_timezone_handler, link, "sb", tz, false); if (r < 0) return log_link_error_errno(link, r, "Could not set timezone: %m"); link_ref(link); return 0; } static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(m); assert(link); assert(link->ifname); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); if (r < 0) log_link_warning_errno(link, r, "Could not set MTU: %m"); return 1; } int link_set_mtu(Link *link, uint32_t mtu) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(link); assert(link->manager); assert(link->manager->rtnl); log_link_debug(link, "Setting MTU: %" PRIu32, mtu); r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); if (r < 0) return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); r = sd_netlink_message_append_u32(req, IFLA_MTU, mtu); if (r < 0) return log_link_error_errno(link, r, "Could not append MTU: %m"); r = sd_netlink_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); link_ref(link); return 0; } static int link_set_bridge(Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(link); assert(link->network); r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); if (r < 0) return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); r = sd_rtnl_message_link_set_family(req, PF_BRIDGE); if (r < 0) return log_link_error_errno(link, r, "Could not set message family: %m"); r = sd_netlink_message_open_container(req, IFLA_PROTINFO); if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m"); r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu); if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m"); r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin); if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m"); r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave); if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m"); r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root); if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m"); r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood); if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m"); if(link->network->cost != 0) { r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost); if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m"); } r = sd_netlink_message_close_container(req); if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m"); r = sd_netlink_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); link_ref(link); return r; } static void lldp_handler(sd_lldp *lldp, int event, void *userdata) { Link *link = userdata; int r; assert(link); assert(link->network); assert(link->manager); switch (event) { case SD_LLDP_EVENT_UPDATE_INFO: r = sd_lldp_save(link->lldp, link->lldp_file); if (r < 0) log_link_warning_errno(link, r, "Could not save LLDP: %m"); break; default: break; } } static int link_acquire_ipv6_conf(Link *link) { int r; assert(link); if (link_dhcp6_enabled(link)) { assert(link->dhcp6_client); assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0); log_link_debug(link, "Acquiring DHCPv6 lease"); r = sd_dhcp6_client_set_local_address(link->dhcp6_client, &link->ipv6ll_address); if (r < 0 && r != -EBUSY) return log_link_warning_errno(link, r, "Could not set IPv6LL address in DHCP client: %m"); r = sd_dhcp6_client_start(link->dhcp6_client); if (r < 0 && r != -EBUSY) return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m"); } if (link_ipv6_accept_ra_enabled(link)) { assert(link->ndisc_router_discovery); log_link_debug(link, "Discovering IPv6 routers"); r = sd_ndisc_router_discovery_start(link->ndisc_router_discovery); if (r < 0 && r != -EBUSY) return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m"); } return 0; } static int link_acquire_conf(Link *link) { int r; assert(link); assert(link->network); assert(link->manager); assert(link->manager->event); if (link_ipv4ll_enabled(link)) { assert(link->ipv4ll); log_link_debug(link, "Acquiring IPv4 link-local address"); r = sd_ipv4ll_start(link->ipv4ll); if (r < 0) return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m"); } if (link_dhcp4_enabled(link)) { assert(link->dhcp_client); log_link_debug(link, "Acquiring DHCPv4 lease"); r = sd_dhcp_client_start(link->dhcp_client); if (r < 0) return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m"); } if (link_lldp_enabled(link)) { assert(link->lldp); log_link_debug(link, "Starting LLDP"); r = sd_lldp_start(link->lldp); if (r < 0) return log_link_warning_errno(link, r, "Could not start LLDP: %m"); } return 0; } bool link_has_carrier(Link *link) { /* see Documentation/networking/operstates.txt in the kernel sources */ if (link->kernel_operstate == IF_OPER_UP) return true; if (link->kernel_operstate == IF_OPER_UNKNOWN) /* operstate may not be implemented, so fall back to flags */ if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT)) return true; return false; } static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(link); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); if (r < 0) /* we warn but don't fail the link, as it may be brought up later */ log_link_warning_errno(link, r, "Could not bring up interface: %m"); return 1; } static int link_up(Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; uint8_t ipv6ll_mode; int r; assert(link); assert(link->network); assert(link->manager); assert(link->manager->rtnl); log_link_debug(link, "Bringing link up"); r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); if (r < 0) return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP); if (r < 0) return log_link_error_errno(link, r, "Could not set link flags: %m"); if (link->network->mac) { r = sd_netlink_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac); if (r < 0) return log_link_error_errno(link, r, "Could not set MAC address: %m"); } if (link->network->mtu) { r = sd_netlink_message_append_u32(req, IFLA_MTU, link->network->mtu); if (r < 0) return log_link_error_errno(link, r, "Could not set MTU: %m"); } r = sd_netlink_message_open_container(req, IFLA_AF_SPEC); if (r < 0) return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m"); if (socket_ipv6_is_supported()) { /* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */ r = sd_netlink_message_open_container(req, AF_INET6); if (r < 0) return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m"); ipv6ll_mode = link_ipv6ll_enabled(link) ? IN6_ADDR_GEN_MODE_EUI64 : IN6_ADDR_GEN_MODE_NONE; r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode); if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m"); if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) { r = sd_netlink_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6); if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_INET6_TOKEN: %m"); } r = sd_netlink_message_close_container(req); if (r < 0) return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m"); } r = sd_netlink_message_close_container(req); if (r < 0) return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m"); r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); link_ref(link); return 0; } static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(link); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); if (r < 0) log_link_warning_errno(link, r, "Could not bring down interface: %m"); return 1; } static int link_down(Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(link); assert(link->manager); assert(link->manager->rtnl); log_link_debug(link, "Bringing link down"); r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); if (r < 0) return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP); if (r < 0) return log_link_error_errno(link, r, "Could not set link flags: %m"); r = sd_netlink_call_async(link->manager->rtnl, req, link_down_handler, link, 0, NULL); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); link_ref(link); return 0; } static int link_handle_bound_to_list(Link *link) { Link *l; Iterator i; int r; bool required_up = false; bool link_is_up = false; assert(link); if (hashmap_isempty(link->bound_to_links)) return 0; if (link->flags & IFF_UP) link_is_up = true; HASHMAP_FOREACH (l, link->bound_to_links, i) if (link_has_carrier(l)) { required_up = true; break; } if (!required_up && link_is_up) { r = link_down(link); if (r < 0) return r; } else if (required_up && !link_is_up) { r = link_up(link); if (r < 0) return r; } return 0; } static int link_handle_bound_by_list(Link *link) { Iterator i; Link *l; int r; assert(link); if (hashmap_isempty(link->bound_by_links)) return 0; HASHMAP_FOREACH (l, link->bound_by_links, i) { r = link_handle_bound_to_list(l); if (r < 0) return r; } return 0; } static int link_put_carrier(Link *link, Link *carrier, Hashmap **h) { int r; assert(link); assert(carrier); if (link == carrier) return 0; if (hashmap_get(*h, INT_TO_PTR(carrier->ifindex))) return 0; r = hashmap_ensure_allocated(h, NULL); if (r < 0) return r; r = hashmap_put(*h, INT_TO_PTR(carrier->ifindex), carrier); if (r < 0) return r; return 0; } static int link_new_bound_by_list(Link *link) { Manager *m; Link *carrier; Iterator i; int r; bool list_updated = false; assert(link); assert(link->manager); m = link->manager; HASHMAP_FOREACH (carrier, m->links, i) { if (!carrier->network) continue; if (strv_isempty(carrier->network->bind_carrier)) continue; if (strv_fnmatch(carrier->network->bind_carrier, link->ifname, 0)) { r = link_put_carrier(link, carrier, &link->bound_by_links); if (r < 0) return r; list_updated = true; } } if (list_updated) link_dirty(link); HASHMAP_FOREACH (carrier, link->bound_by_links, i) { r = link_put_carrier(carrier, link, &carrier->bound_to_links); if (r < 0) return r; link_dirty(carrier); } return 0; } static int link_new_bound_to_list(Link *link) { Manager *m; Link *carrier; Iterator i; int r; bool list_updated = false; assert(link); assert(link->manager); if (!link->network) return 0; if (strv_isempty(link->network->bind_carrier)) return 0; m = link->manager; HASHMAP_FOREACH (carrier, m->links, i) { if (strv_fnmatch(link->network->bind_carrier, carrier->ifname, 0)) { r = link_put_carrier(link, carrier, &link->bound_to_links); if (r < 0) return r; list_updated = true; } } if (list_updated) link_dirty(link); HASHMAP_FOREACH (carrier, link->bound_to_links, i) { r = link_put_carrier(carrier, link, &carrier->bound_by_links); if (r < 0) return r; link_dirty(carrier); } return 0; } static int link_new_carrier_maps(Link *link) { int r; r = link_new_bound_by_list(link); if (r < 0) return r; r = link_handle_bound_by_list(link); if (r < 0) return r; r = link_new_bound_to_list(link); if (r < 0) return r; r = link_handle_bound_to_list(link); if (r < 0) return r; return 0; } static void link_free_bound_to_list(Link *link) { Link *bound_to; Iterator i; HASHMAP_FOREACH (bound_to, link->bound_to_links, i) { hashmap_remove(link->bound_to_links, INT_TO_PTR(bound_to->ifindex)); if (hashmap_remove(bound_to->bound_by_links, INT_TO_PTR(link->ifindex))) link_dirty(bound_to); } return; } static void link_free_bound_by_list(Link *link) { Link *bound_by; Iterator i; HASHMAP_FOREACH (bound_by, link->bound_by_links, i) { hashmap_remove(link->bound_by_links, INT_TO_PTR(bound_by->ifindex)); if (hashmap_remove(bound_by->bound_to_links, INT_TO_PTR(link->ifindex))) { link_dirty(bound_by); link_handle_bound_to_list(bound_by); } } return; } static void link_free_carrier_maps(Link *link) { bool list_updated = false; assert(link); if (!hashmap_isempty(link->bound_to_links)) { link_free_bound_to_list(link); list_updated = true; } if (!hashmap_isempty(link->bound_by_links)) { link_free_bound_by_list(link); list_updated = true; } if (list_updated) link_dirty(link); return; } void link_drop(Link *link) { if (!link || link->state == LINK_STATE_LINGER) return; link_set_state(link, LINK_STATE_LINGER); link_free_carrier_maps(link); log_link_debug(link, "Link removed"); (void)unlink(link->state_file); link_unref(link); return; } static int link_joined(Link *link) { int r; assert(link); assert(link->network); if (!hashmap_isempty(link->bound_to_links)) { r = link_handle_bound_to_list(link); if (r < 0) return r; } else if (!(link->flags & IFF_UP)) { r = link_up(link); if (r < 0) { link_enter_failed(link); return r; } } if(link->network->bridge) { r = link_set_bridge(link); if (r < 0) log_link_error_errno(link, r, "Could not set bridge message: %m"); } return link_enter_set_addresses(link); } static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(link); assert(link->network); link->enslaving --; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) { log_link_error_errno(link, r, "Could not join netdev: %m"); link_enter_failed(link); return 1; } else log_link_debug(link, "Joined netdev"); if (link->enslaving <= 0) link_joined(link); return 1; } static int link_enter_join_netdev(Link *link) { NetDev *netdev; Iterator i; int r; assert(link); assert(link->network); assert(link->state == LINK_STATE_PENDING); link_set_state(link, LINK_STATE_ENSLAVING); link_dirty(link); if (!link->network->bridge && !link->network->bond && hashmap_isempty(link->network->stacked_netdevs)) return link_joined(link); if (link->network->bond) { log_struct(LOG_DEBUG, LOG_LINK_INTERFACE(link), LOG_NETDEV_INTERFACE(link->network->bond), LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bond->ifname), NULL); r = netdev_join(link->network->bond, link, netdev_join_handler); if (r < 0) { log_struct_errno(LOG_WARNING, r, LOG_LINK_INTERFACE(link), LOG_NETDEV_INTERFACE(link->network->bond), LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bond->ifname), NULL); link_enter_failed(link); return r; } link->enslaving ++; } if (link->network->bridge) { log_struct(LOG_DEBUG, LOG_LINK_INTERFACE(link), LOG_NETDEV_INTERFACE(link->network->bridge), LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bridge->ifname), NULL); r = netdev_join(link->network->bridge, link, netdev_join_handler); if (r < 0) { log_struct_errno(LOG_WARNING, r, LOG_LINK_INTERFACE(link), LOG_NETDEV_INTERFACE(link->network->bridge), LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bridge->ifname), NULL), link_enter_failed(link); return r; } link->enslaving ++; } HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) { log_struct(LOG_DEBUG, LOG_LINK_INTERFACE(link), LOG_NETDEV_INTERFACE(netdev), LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname), NULL); r = netdev_join(netdev, link, netdev_join_handler); if (r < 0) { log_struct_errno(LOG_WARNING, r, LOG_LINK_INTERFACE(link), LOG_NETDEV_INTERFACE(netdev), LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", netdev->ifname), NULL); link_enter_failed(link); return r; } link->enslaving ++; } return 0; } static int link_set_ipv4_forward(Link *link) { int r; if (!link_ipv4_forward_enabled(link)) return 0; /* We propagate the forwarding flag from one interface to the * global setting one way. This means: as long as at least one * interface was configured at any time that had IP forwarding * enabled the setting will stay on for good. We do this * primarily to keep IPv4 and IPv6 packet forwarding behaviour * somewhat in sync (see below). */ r = write_string_file("/proc/sys/net/ipv4/ip_forward", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE); if (r < 0) log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m"); return 0; } static int link_set_ipv6_forward(Link *link) { int r; if (!link_ipv6_forward_enabled(link)) return 0; /* On Linux, the IPv6 stack does not not know a per-interface * packet forwarding setting: either packet forwarding is on * for all, or off for all. We hence don't bother with a * per-interface setting, but simply propagate the interface * flag, if it is set, to the global flag, one-way. Note that * while IPv4 would allow a per-interface flag, we expose the * same behaviour there and also propagate the setting from * one to all, to keep things simple (see above). */ r = write_string_file("/proc/sys/net/ipv6/conf/all/forwarding", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE); if (r < 0) log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m"); return 0; } static int link_set_ipv6_privacy_extensions(Link *link) { char buf[DECIMAL_STR_MAX(unsigned) + 1]; IPv6PrivacyExtensions s; const char *p = NULL; int r; s = link_ipv6_privacy_extensions(link); if (s < 0) return 0; p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr"); xsprintf(buf, "%u", (unsigned) link->network->ipv6_privacy_extensions); r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE); if (r < 0) log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m"); return 0; } static int link_set_ipv6_accept_ra(Link *link) { const char *p = NULL; int r; /* Make this a NOP if IPv6 is not available */ if (!socket_ipv6_is_supported()) return 0; if (link->flags & IFF_LOOPBACK) return 0; if (!link->network) return 0; p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra"); /* We handle router advertisments ourselves, tell the kernel to GTFO */ r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE); if (r < 0) log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m"); return 0; } static int link_set_ipv6_dad_transmits(Link *link) { char buf[DECIMAL_STR_MAX(int) + 1]; const char *p = NULL; int r; /* Make this a NOP if IPv6 is not available */ if (!socket_ipv6_is_supported()) return 0; if (link->flags & IFF_LOOPBACK) return 0; if (!link->network) return 0; if (link->network->ipv6_dad_transmits < 0) return 0; p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/dad_transmits"); xsprintf(buf, "%i", link->network->ipv6_dad_transmits); r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE); if (r < 0) log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m"); return 0; } static int link_set_ipv6_hop_limit(Link *link) { char buf[DECIMAL_STR_MAX(int) + 1]; const char *p = NULL; int r; /* Make this a NOP if IPv6 is not available */ if (!socket_ipv6_is_supported()) return 0; if (link->flags & IFF_LOOPBACK) return 0; if (!link->network) return 0; if (link->network->ipv6_hop_limit < 0) return 0; p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/hop_limit"); xsprintf(buf, "%i", link->network->ipv6_hop_limit); r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE); if (r < 0) log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m"); return 0; } static int link_drop_foreign_config(Link *link) { Address *address; Route *route; Iterator i; int r; SET_FOREACH(address, link->addresses_foreign, i) { /* we consider IPv6LL addresses to be managed by the kernel */ if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1) continue; r = address_remove(address, link, link_address_remove_handler); if (r < 0) return r; } SET_FOREACH(route, link->routes_foreign, i) { /* do not touch routes managed by the kernel */ if (route->protocol == RTPROT_KERNEL) continue; r = route_remove(route, link, link_address_remove_handler); if (r < 0) return r; } return 0; } static int link_configure(Link *link) { int r; assert(link); assert(link->network); assert(link->state == LINK_STATE_PENDING); /* Drop foreign config, but ignore loopback or critical devices. * We do not want to remove loopback address or addresses used for root NFS. */ if (!(link->flags & IFF_LOOPBACK) && !(link->network->dhcp_critical)) { r = link_drop_foreign_config(link); if (r < 0) return r; } r = link_set_bridge_fdb(link); if (r < 0) return r; r = link_set_ipv4_forward(link); if (r < 0) return r; r = link_set_ipv6_forward(link); if (r < 0) return r; r = link_set_ipv6_privacy_extensions(link); if (r < 0) return r; r = link_set_ipv6_accept_ra(link); if (r < 0) return r; r = link_set_ipv6_dad_transmits(link); if (r < 0) return r; r = link_set_ipv6_hop_limit(link); if (r < 0) return r; if (link_ipv4ll_enabled(link)) { r = ipv4ll_configure(link); if (r < 0) return r; } if (link_dhcp4_enabled(link)) { r = dhcp4_configure(link); if (r < 0) return r; } if (link_dhcp4_server_enabled(link)) { r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex); if (r < 0) return r; r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0); if (r < 0) return r; } if (link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link)) { r = dhcp6_configure(link); if (r < 0) return r; } if (link_ipv6_accept_ra_enabled(link)) { r = ndisc_configure(link); if (r < 0) return r; } if (link_lldp_enabled(link)) { r = sd_lldp_new(link->ifindex, link->ifname, &link->mac, &link->lldp); if (r < 0) return r; r = sd_lldp_attach_event(link->lldp, NULL, 0); if (r < 0) return r; r = sd_lldp_set_callback(link->lldp, lldp_handler, link); if (r < 0) return r; } if (link_has_carrier(link)) { r = link_acquire_conf(link); if (r < 0) return r; if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) == 0) { r = link_acquire_ipv6_conf(link); if (r < 0) return r; } } return link_enter_join_netdev(link); } static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; Network *network; int r; assert(link); assert(link->ifname); assert(link->manager); if (link->state != LINK_STATE_PENDING) return 1; log_link_debug(link, "Link state is up-to-date"); r = link_new_bound_by_list(link); if (r < 0) return r; r = link_handle_bound_by_list(link); if (r < 0) return r; if (!link->network) { r = network_get(link->manager, link->udev_device, link->ifname, &link->mac, &network); if (r == -ENOENT) { link_enter_unmanaged(link); return 1; } else if (r < 0) return r; if (link->flags & IFF_LOOPBACK) { if (network->link_local != ADDRESS_FAMILY_NO) log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link"); if (network->dhcp != ADDRESS_FAMILY_NO) log_link_debug(link, "Ignoring DHCP clients for loopback link"); if (network->dhcp_server) log_link_debug(link, "Ignoring DHCP server for loopback link"); } r = network_apply(link->manager, network, link); if (r < 0) return r; } r = link_new_bound_to_list(link); if (r < 0) return r; r = link_configure(link); if (r < 0) return r; return 1; } int link_initialized(Link *link, struct udev_device *device) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(link); assert(link->manager); assert(link->manager->rtnl); assert(device); if (link->state != LINK_STATE_PENDING) return 0; if (link->udev_device) return 0; log_link_debug(link, "udev initialized link"); link->udev_device = udev_device_ref(device); /* udev has initialized the link, but we don't know if we have yet * processed the NEWLINK messages with the latest state. Do a GETLINK, * when it returns we know that the pending NEWLINKs have already been * processed and that we are up-to-date */ r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK, link->ifindex); if (r < 0) return r; r = sd_netlink_call_async(link->manager->rtnl, req, link_initialized_and_synced, link, 0, NULL); if (r < 0) return r; link_ref(link); return 0; } static int link_load(Link *link) { _cleanup_free_ char *network_file = NULL, *addresses = NULL, *routes = NULL, *dhcp4_address = NULL, *ipv4ll_address = NULL; union in_addr_union address; union in_addr_union route_dst; const char *p; int r; assert(link); r = parse_env_file(link->state_file, NEWLINE, "NETWORK_FILE", &network_file, "ADDRESSES", &addresses, "ROUTES", &routes, "DHCP4_ADDRESS", &dhcp4_address, "IPV4LL_ADDRESS", &ipv4ll_address, NULL); if (r < 0 && r != -ENOENT) return log_link_error_errno(link, r, "Failed to read %s: %m", link->state_file); if (network_file) { Network *network; char *suffix; /* drop suffix */ suffix = strrchr(network_file, '.'); if (!suffix) { log_link_debug(link, "Failed to get network name from %s", network_file); goto network_file_fail; } *suffix = '\0'; r = network_get_by_name(link->manager, basename(network_file), &network); if (r < 0) { log_link_debug_errno(link, r, "Failed to get network %s: %m", basename(network_file)); goto network_file_fail; } r = network_apply(link->manager, network, link); if (r < 0) return log_link_error_errno(link, r, "Failed to apply network %s: %m", basename(network_file)); } network_file_fail: if (addresses) { p = addresses; for (;;) { _cleanup_free_ char *address_str = NULL; char *prefixlen_str; int family; unsigned char prefixlen; r = extract_first_word(&p, &address_str, NULL, 0); if (r < 0) { log_link_debug_errno(link, r, "Failed to extract next address string: %m"); continue; } if (r == 0) break; prefixlen_str = strchr(address_str, '/'); if (!prefixlen_str) { log_link_debug(link, "Failed to parse address and prefix length %s", address_str); continue; } *prefixlen_str ++ = '\0'; r = sscanf(prefixlen_str, "%hhu", &prefixlen); if (r != 1) { log_link_error(link, "Failed to parse prefixlen %s", prefixlen_str); continue; } r = in_addr_from_string_auto(address_str, &family, &address); if (r < 0) { log_link_debug_errno(link, r, "Failed to parse address %s: %m", address_str); continue; } r = address_add(link, family, &address, prefixlen, NULL); if (r < 0) return log_link_error_errno(link, r, "Failed to add address: %m"); } } if (routes) { p = routes; for (;;) { Route *route; _cleanup_free_ char *route_str = NULL; _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; usec_t lifetime; char *prefixlen_str; int family; unsigned char prefixlen, tos, table; uint32_t priority; r = extract_first_word(&p, &route_str, NULL, 0); if (r < 0) { log_link_debug_errno(link, r, "Failed to extract next route string: %m"); continue; } if (r == 0) break; prefixlen_str = strchr(route_str, '/'); if (!prefixlen_str) { log_link_debug(link, "Failed to parse route %s", route_str); continue; } *prefixlen_str ++ = '\0'; r = sscanf(prefixlen_str, "%hhu/%hhu/%"SCNu32"/%hhu/"USEC_FMT, &prefixlen, &tos, &priority, &table, &lifetime); if (r != 5) { log_link_debug(link, "Failed to parse destination prefix length, tos, priority, table or expiration %s", prefixlen_str); continue; } r = in_addr_from_string_auto(route_str, &family, &route_dst); if (r < 0) { log_link_debug_errno(link, r, "Failed to parse route destination %s: %m", route_str); continue; } r = route_add(link, family, &route_dst, prefixlen, tos, priority, table, &route); if (r < 0) return log_link_error_errno(link, r, "Failed to add route: %m"); if (lifetime != USEC_INFINITY) { r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), lifetime, 0, route_expire_handler, route); if (r < 0) log_link_warning_errno(link, r, "Could not arm route expiration handler: %m"); } route->lifetime = lifetime; sd_event_source_unref(route->expire); route->expire = expire; expire = NULL; } } if (dhcp4_address) { r = in_addr_from_string(AF_INET, dhcp4_address, &address); if (r < 0) { log_link_debug_errno(link, r, "Falied to parse DHCPv4 address %s: %m", dhcp4_address); goto dhcp4_address_fail; } r = sd_dhcp_client_new(&link->dhcp_client); if (r < 0) return log_link_error_errno(link, r, "Falied to create DHCPv4 client: %m"); r = sd_dhcp_client_set_request_address(link->dhcp_client, &address.in); if (r < 0) return log_link_error_errno(link, r, "Falied to set inital DHCPv4 address %s: %m", dhcp4_address); } dhcp4_address_fail: if (ipv4ll_address) { r = in_addr_from_string(AF_INET, ipv4ll_address, &address); if (r < 0) { log_link_debug_errno(link, r, "Falied to parse IPv4LL address %s: %m", ipv4ll_address); goto ipv4ll_address_fail; } r = sd_ipv4ll_new(&link->ipv4ll); if (r < 0) return log_link_error_errno(link, r, "Falied to create IPv4LL client: %m"); r = sd_ipv4ll_set_address(link->ipv4ll, &address.in); if (r < 0) return log_link_error_errno(link, r, "Falied to set inital IPv4LL address %s: %m", ipv4ll_address); } ipv4ll_address_fail: return 0; } int link_add(Manager *m, sd_netlink_message *message, Link **ret) { Link *link; _cleanup_udev_device_unref_ struct udev_device *device = NULL; char ifindex_str[2 + DECIMAL_STR_MAX(int)]; int r; assert(m); assert(m->rtnl); assert(message); assert(ret); r = link_new(m, message, ret); if (r < 0) return r; link = *ret; log_link_debug(link, "Link %d added", link->ifindex); r = link_load(link); if (r < 0) return r; if (detect_container() <= 0) { /* not in a container, udev will be around */ sprintf(ifindex_str, "n%d", link->ifindex); device = udev_device_new_from_device_id(m->udev, ifindex_str); if (!device) { r = log_link_warning_errno(link, errno, "Could not find udev device: %m"); goto failed; } if (udev_device_get_is_initialized(device) <= 0) { /* not yet ready */ log_link_debug(link, "link pending udev initialization..."); return 0; } r = link_initialized(link, device); if (r < 0) goto failed; } else { /* we are calling a callback directly, so must take a ref */ link_ref(link); r = link_initialized_and_synced(m->rtnl, NULL, link); if (r < 0) goto failed; } return 0; failed: link_enter_failed(link); return r; } int link_ipv6ll_gained(Link *link, const struct in6_addr *address) { int r; assert(link); log_link_info(link, "Gained IPv6LL"); link->ipv6ll_address = *address; link_check_ready(link); if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) { r = link_acquire_ipv6_conf(link); if (r < 0) { link_enter_failed(link); return r; } } return 0; } static int link_carrier_gained(Link *link) { int r; assert(link); if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) { r = link_acquire_conf(link); if (r < 0) { link_enter_failed(link); return r; } } r = link_handle_bound_by_list(link); if (r < 0) return r; return 0; } static int link_carrier_lost(Link *link) { int r; assert(link); r = link_stop_clients(link); if (r < 0) { link_enter_failed(link); return r; } r = link_handle_bound_by_list(link); if (r < 0) return r; return 0; } int link_carrier_reset(Link *link) { int r; assert(link); if (link_has_carrier(link)) { r = link_carrier_lost(link); if (r < 0) return r; r = link_carrier_gained(link); if (r < 0) return r; log_link_info(link, "Reset carrier"); } return 0; } int link_update(Link *link, sd_netlink_message *m) { struct ether_addr mac; const char *ifname; uint32_t mtu; bool had_carrier, carrier_gained, carrier_lost; int r; assert(link); assert(link->ifname); assert(m); if (link->state == LINK_STATE_LINGER) { link_ref(link); log_link_info(link, "Link readded"); link_set_state(link, LINK_STATE_ENSLAVING); r = link_new_carrier_maps(link); if (r < 0) return r; } r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname); if (r >= 0 && !streq(ifname, link->ifname)) { log_link_info(link, "Renamed to %s", ifname); link_free_carrier_maps(link); r = free_and_strdup(&link->ifname, ifname); if (r < 0) return r; r = link_new_carrier_maps(link); if (r < 0) return r; } r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu); if (r >= 0 && mtu > 0) { link->mtu = mtu; if (!link->original_mtu) { link->original_mtu = mtu; log_link_debug(link, "Saved original MTU: %" PRIu32, link->original_mtu); } if (link->dhcp_client) { r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu); if (r < 0) { log_link_warning_errno(link, r, "Could not update MTU in DHCP client: %m"); return r; } } } /* The kernel may broadcast NEWLINK messages without the MAC address set, simply ignore them. */ r = sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &mac); if (r >= 0) { if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN)) { memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN); log_link_debug(link, "MAC address: " "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac.ether_addr_octet[0], mac.ether_addr_octet[1], mac.ether_addr_octet[2], mac.ether_addr_octet[3], mac.ether_addr_octet[4], mac.ether_addr_octet[5]); if (link->ipv4ll) { r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac); if (r < 0) return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m"); } if (link->dhcp_client) { r = sd_dhcp_client_set_mac(link->dhcp_client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER); if (r < 0) return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m"); } if (link->dhcp6_client) { r = sd_dhcp6_client_set_mac(link->dhcp6_client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER); if (r < 0) return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m"); } } } had_carrier = link_has_carrier(link); r = link_update_flags(link, m); if (r < 0) return r; carrier_gained = !had_carrier && link_has_carrier(link); carrier_lost = had_carrier && !link_has_carrier(link); if (carrier_gained) { log_link_info(link, "Gained carrier"); r = link_carrier_gained(link); if (r < 0) return r; } else if (carrier_lost) { log_link_info(link, "Lost carrier"); r = link_carrier_lost(link); if (r < 0) return r; } return 0; } int link_save(Link *link) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; const char *admin_state, *oper_state; Address *a; Route *route; Iterator i; int r; assert(link); assert(link->state_file); assert(link->lease_file); assert(link->manager); if (link->state == LINK_STATE_LINGER) { unlink(link->state_file); return 0; } admin_state = link_state_to_string(link->state); assert(admin_state); oper_state = link_operstate_to_string(link->operstate); assert(oper_state); r = fopen_temporary(link->state_file, &f, &temp_path); if (r < 0) goto fail; fchmod(fileno(f), 0644); fprintf(f, "# This is private data. Do not parse.\n" "ADMIN_STATE=%s\n" "OPER_STATE=%s\n", admin_state, oper_state); if (link->network) { bool space; sd_dhcp6_lease *dhcp6_lease = NULL; const char *dhcp_domainname = NULL; char **dhcp6_domains = NULL; if (link->dhcp6_client) { r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease); if (r < 0 && r != -ENOMSG) log_link_debug(link, "No DHCPv6 lease"); } fprintf(f, "NETWORK_FILE=%s\n", link->network->filename); fputs("DNS=", f); space = false; fputstrv(f, link->network->dns, NULL, &space); if (link->network->dhcp_use_dns && link->dhcp_lease) { const struct in_addr *addresses; r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses); if (r > 0) { if (space) fputc(' ', f); serialize_in_addrs(f, addresses, r); space = true; } } if (link->network->dhcp_use_dns && dhcp6_lease) { struct in6_addr *in6_addrs; r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs); if (r > 0) { if (space) fputc(' ', f); serialize_in6_addrs(f, in6_addrs, r); } } fputc('\n', f); fputs("NTP=", f); space = false; fputstrv(f, link->network->ntp, NULL, &space); if (link->network->dhcp_use_ntp && link->dhcp_lease) { const struct in_addr *addresses; r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses); if (r > 0) { if (space) fputc(' ', f); serialize_in_addrs(f, addresses, r); space = true; } } if (link->network->dhcp_use_ntp && dhcp6_lease) { struct in6_addr *in6_addrs; char **hosts; r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease, &in6_addrs); if (r > 0) { if (space) fputc(' ', f); serialize_in6_addrs(f, in6_addrs, r); space = true; } r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts); if (r > 0) fputstrv(f, hosts, NULL, &space); } fputc('\n', f); if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) { if (link->dhcp_lease) (void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname); if (dhcp6_lease) (void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains); } fputs("DOMAINS=", f); fputstrv(f, link->network->search_domains, NULL, &space); if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp_domainname) fputs_with_space(f, dhcp_domainname, NULL, &space); if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp6_domains) fputstrv(f, dhcp6_domains, NULL, &space); fputc('\n', f); fputs("ROUTE_DOMAINS=", f); fputstrv(f, link->network->route_domains, NULL, NULL); if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp_domainname) fputs_with_space(f, dhcp_domainname, NULL, &space); if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp6_domains) fputstrv(f, dhcp6_domains, NULL, &space); fputc('\n', f); fprintf(f, "LLMNR=%s\n", resolve_support_to_string(link->network->llmnr)); fprintf(f, "MDNS=%s\n", resolve_support_to_string(link->network->mdns)); if (link->network->dnssec_mode != _DNSSEC_MODE_INVALID) fprintf(f, "DNSSEC=%s\n", dnssec_mode_to_string(link->network->dnssec_mode)); if (!set_isempty(link->network->dnssec_negative_trust_anchors)) { const char *n; fputs("DNSSEC_NTA=", f); space = false; SET_FOREACH(n, link->network->dnssec_negative_trust_anchors, i) fputs_with_space(f, n, NULL, &space); fputc('\n', f); } fputs("ADDRESSES=", f); space = false; SET_FOREACH(a, link->addresses, i) { _cleanup_free_ char *address_str = NULL; r = in_addr_to_string(a->family, &a->in_addr, &address_str); if (r < 0) goto fail; fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen); space = true; } fputc('\n', f); fputs("ROUTES=", f); space = false; SET_FOREACH(route, link->routes, i) { _cleanup_free_ char *route_str = NULL; r = in_addr_to_string(route->family, &route->dst, &route_str); if (r < 0) goto fail; fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%hhu/"USEC_FMT, space ? " " : "", route_str, route->dst_prefixlen, route->tos, route->priority, route->table, route->lifetime); space = true; } fputc('\n', f); } if (!hashmap_isempty(link->bound_to_links)) { Link *carrier; bool space = false; fputs("CARRIER_BOUND_TO=", f); HASHMAP_FOREACH(carrier, link->bound_to_links, i) fputs_with_space(f, carrier->ifname, NULL, &space); fputc('\n', f); } if (!hashmap_isempty(link->bound_by_links)) { Link *carrier; bool space = false; fputs("CARRIER_BOUND_BY=", f); HASHMAP_FOREACH(carrier, link->bound_by_links, i) fputs_with_space(f, carrier->ifname, NULL, &space); fputc('\n', f); } if (link->dhcp_lease) { struct in_addr address; const char *tz = NULL; assert(link->network); r = sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz); if (r >= 0) fprintf(f, "TIMEZONE=%s\n", tz); r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); if (r >= 0) { fputs("DHCP4_ADDRESS=", f); serialize_in_addrs(f, &address, 1); fputc('\n', f); } r = dhcp_lease_save(link->dhcp_lease, link->lease_file); if (r < 0) goto fail; fprintf(f, "DHCP_LEASE=%s\n", link->lease_file); } else unlink(link->lease_file); if (link->ipv4ll) { struct in_addr address; r = sd_ipv4ll_get_address(link->ipv4ll, &address); if (r >= 0) { fputs("IPV4LL_ADDRESS=", f); serialize_in_addrs(f, &address, 1); fputc('\n', f); } } if (link->lldp) { assert(link->network); r = sd_lldp_save(link->lldp, link->lldp_file); if (r < 0) goto fail; fprintf(f, "LLDP_FILE=%s\n", link->lldp_file); } else unlink(link->lldp_file); r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, link->state_file) < 0) { r = -errno; goto fail; } return 0; fail: (void) unlink(link->state_file); if (temp_path) (void) unlink(temp_path); return log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file); } /* The serialized state in /run is no longer up-to-date. */ void link_dirty(Link *link) { int r; assert(link); r = set_ensure_allocated(&link->manager->dirty_links, NULL); if (r < 0) /* allocation errors are ignored */ return; r = set_put(link->manager->dirty_links, link); if (r < 0) /* allocation errors are ignored */ return; link_ref(link); } /* The serialized state in /run is up-to-date */ void link_clean(Link *link) { assert(link); assert(link->manager); set_remove(link->manager->dirty_links, link); link_unref(link); } static const char* const link_state_table[_LINK_STATE_MAX] = { [LINK_STATE_PENDING] = "pending", [LINK_STATE_ENSLAVING] = "configuring", [LINK_STATE_SETTING_ADDRESSES] = "configuring", [LINK_STATE_SETTING_ROUTES] = "configuring", [LINK_STATE_CONFIGURED] = "configured", [LINK_STATE_UNMANAGED] = "unmanaged", [LINK_STATE_FAILED] = "failed", [LINK_STATE_LINGER] = "linger", }; DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState); static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = { [LINK_OPERSTATE_OFF] = "off", [LINK_OPERSTATE_NO_CARRIER] = "no-carrier", [LINK_OPERSTATE_DORMANT] = "dormant", [LINK_OPERSTATE_CARRIER] = "carrier", [LINK_OPERSTATE_DEGRADED] = "degraded", [LINK_OPERSTATE_ROUTABLE] = "routable", }; DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState); systemd-229/src/network/networkd-link.h000066400000000000000000000156671265713322000203210ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-dhcp-client.h" #include "sd-dhcp-server.h" #include "sd-dhcp6-client.h" #include "sd-ipv4ll.h" #include "sd-lldp.h" #include "sd-ndisc.h" typedef struct Link Link; typedef enum LinkState { LINK_STATE_PENDING, LINK_STATE_ENSLAVING, LINK_STATE_SETTING_ADDRESSES, LINK_STATE_SETTING_ROUTES, LINK_STATE_CONFIGURED, LINK_STATE_UNMANAGED, LINK_STATE_FAILED, LINK_STATE_LINGER, _LINK_STATE_MAX, _LINK_STATE_INVALID = -1 } LinkState; typedef enum LinkOperationalState { LINK_OPERSTATE_OFF, LINK_OPERSTATE_NO_CARRIER, LINK_OPERSTATE_DORMANT, LINK_OPERSTATE_CARRIER, LINK_OPERSTATE_DEGRADED, LINK_OPERSTATE_ROUTABLE, _LINK_OPERSTATE_MAX, _LINK_OPERSTATE_INVALID = -1 } LinkOperationalState; #include "networkd-address.h" #include "networkd-network.h" #include "networkd.h" struct Link { Manager *manager; int n_ref; int ifindex; char *ifname; char *state_file; struct ether_addr mac; struct in6_addr ipv6ll_address; uint32_t mtu; struct udev_device *udev_device; unsigned flags; uint8_t kernel_operstate; Network *network; LinkState state; LinkOperationalState operstate; unsigned link_messages; unsigned enslaving; Set *addresses; Set *addresses_foreign; Set *routes; Set *routes_foreign; sd_dhcp_client *dhcp_client; sd_dhcp_lease *dhcp_lease; char *lease_file; uint16_t original_mtu; unsigned dhcp4_messages; bool dhcp4_configured; bool dhcp6_configured; unsigned ndisc_messages; bool ndisc_configured; sd_ipv4ll *ipv4ll; bool ipv4ll_address:1; bool ipv4ll_route:1; bool static_configured; LIST_HEAD(Address, pool_addresses); sd_dhcp_server *dhcp_server; sd_ndisc *ndisc_router_discovery; sd_dhcp6_client *dhcp6_client; bool rtnl_extended_attrs; sd_lldp *lldp; char *lldp_file; Hashmap *bound_by_links; Hashmap *bound_to_links; }; Link *link_unref(Link *link); Link *link_ref(Link *link); int link_get(Manager *m, int ifindex, Link **ret); int link_add(Manager *manager, sd_netlink_message *message, Link **ret); void link_drop(Link *link); int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata); int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata); void link_enter_failed(Link *link); int link_initialized(Link *link, struct udev_device *device); void link_check_ready(Link *link); void link_update_operstate(Link *link); int link_update(Link *link, sd_netlink_message *message); void link_dirty(Link *link); void link_clean(Link *link); int link_save(Link *link); int link_carrier_reset(Link *link); bool link_has_carrier(Link *link); int link_ipv6ll_gained(Link *link, const struct in6_addr *address); int link_set_mtu(Link *link, uint32_t mtu); int link_set_hostname(Link *link, const char *hostname); int link_set_timezone(Link *link, const char *timezone); int ipv4ll_configure(Link *link); int dhcp4_configure(Link *link); int dhcp6_configure(Link *link); int dhcp6_request_address(Link *link); int ndisc_configure(Link *link); bool link_lldp_enabled(Link *link); bool link_ipv4ll_enabled(Link *link); bool link_ipv6ll_enabled(Link *link); bool link_dhcp4_server_enabled(Link *link); bool link_dhcp4_enabled(Link *link); bool link_dhcp6_enabled(Link *link); bool link_ipv6_accept_ra_enabled(Link *link); const char* link_state_to_string(LinkState s) _const_; LinkState link_state_from_string(const char *s) _pure_; const char* link_operstate_to_string(LinkOperationalState s) _const_; LinkOperationalState link_operstate_from_string(const char *s) _pure_; extern const sd_bus_vtable link_vtable[]; int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); int link_send_changed(Link *link, const char *property, ...) _sentinel_; DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); #define _cleanup_link_unref_ _cleanup_(link_unrefp) /* Macros which append INTERFACE= to the message */ #define log_link_full(link, level, error, ...) \ ({ \ Link *_l = (link); \ _l ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _l->ifname, ##__VA_ARGS__) : \ log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ }) \ #define log_link_debug(link, ...) log_link_full(link, LOG_DEBUG, 0, ##__VA_ARGS__) #define log_link_info(link, ...) log_link_full(link, LOG_INFO, 0, ##__VA_ARGS__) #define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, 0, ##__VA_ARGS__) #define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, 0, ##__VA_ARGS__) #define log_link_error(link, ...) log_link_full(link, LOG_ERR, 0, ##__VA_ARGS__) #define log_link_debug_errno(link, error, ...) log_link_full(link, LOG_DEBUG, error, ##__VA_ARGS__) #define log_link_info_errno(link, error, ...) log_link_full(link, LOG_INFO, error, ##__VA_ARGS__) #define log_link_notice_errno(link, error, ...) log_link_full(link, LOG_NOTICE, error, ##__VA_ARGS__) #define log_link_warning_errno(link, error, ...) log_link_full(link, LOG_WARNING, error, ##__VA_ARGS__) #define log_link_error_errno(link, error, ...) log_link_full(link, LOG_ERR, error, ##__VA_ARGS__) #define LOG_LINK_MESSAGE(link, fmt, ...) "MESSAGE=%s: " fmt, (link)->ifname, ##__VA_ARGS__ #define LOG_LINK_INTERFACE(link) "INTERFACE=%s", (link)->ifname #define ADDRESS_FMT_VAL(address) \ be32toh((address).s_addr) >> 24, \ (be32toh((address).s_addr) >> 16) & 0xFFu, \ (be32toh((address).s_addr) >> 8) & 0xFFu, \ be32toh((address).s_addr) & 0xFFu systemd-229/src/network/networkd-manager-bus.c000066400000000000000000000031601265713322000215410ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-util.h" #include "networkd.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState); const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Manager, operational_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_VTABLE_END }; int manager_send_changed(Manager *manager, const char *property, ...) { char **l; assert(manager); if (!manager->bus) return 0; /* replace by assert when we have kdbus */ l = strv_from_stdarg_alloca(property); return sd_bus_emit_properties_changed_strv( manager->bus, "/org/freedesktop/network1", "org.freedesktop.network1.Manager", l); } systemd-229/src/network/networkd-manager.c000066400000000000000000001232661265713322000207640ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-daemon.h" #include "sd-netlink.h" #include "alloc-util.h" #include "bus-util.h" #include "conf-parser.h" #include "def.h" #include "dns-domain.h" #include "fd-util.h" #include "fileio.h" #include "libudev-private.h" #include "local-addresses.h" #include "netlink-util.h" #include "networkd.h" #include "ordered-set.h" #include "path-util.h" #include "set.h" #include "udev-util.h" #include "virt.h" /* use 8 MB for receive socket kernel queue. */ #define RCVBUF_SIZE (8*1024*1024) const char* const network_dirs[] = { "/etc/systemd/network", "/run/systemd/network", "/usr/lib/systemd/network", #ifdef HAVE_SPLIT_USR "/lib/systemd/network", #endif NULL}; static int setup_default_address_pool(Manager *m) { AddressPool *p; int r; assert(m); /* Add in the well-known private address ranges. */ r = address_pool_new_from_string(m, &p, AF_INET6, "fc00::", 7); if (r < 0) return r; r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16); if (r < 0) return r; r = address_pool_new_from_string(m, &p, AF_INET, "172.16.0.0", 12); if (r < 0) return r; r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8); if (r < 0) return r; return 0; } static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) { Manager *m = userdata; assert(s); assert(m); m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source); manager_connect_bus(m); return 0; } static int manager_reset_all(Manager *m) { Link *link; Iterator i; int r; assert(m); HASHMAP_FOREACH(link, m->links, i) { r = link_carrier_reset(link); if (r < 0) log_link_warning_errno(link, r, "Could not reset carrier: %m"); } return 0; } static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { Manager *m = userdata; int b, r; assert(message); r = sd_bus_message_read(message, "b", &b); if (r < 0) { log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m"); return 0; } if (b) return 0; log_debug("Coming back from suspend, resetting all connections..."); manager_reset_all(m); return 0; } int manager_connect_bus(Manager *m) { int r; assert(m); r = sd_bus_default_system(&m->bus); if (r == -ENOENT) { /* We failed to connect? Yuck, we must be in early * boot. Let's try in 5s again. As soon as we have * kdbus we can stop doing this... */ log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m"); r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m); if (r < 0) return log_error_errno(r, "Failed to install bus reconnect time event: %m"); return 0; } if (r < 0) return r; r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot, "type='signal'," "sender='org.freedesktop.login1'," "interface='org.freedesktop.login1.Manager'," "member='PrepareForSleep'," "path='/org/freedesktop/login1'", match_prepare_for_sleep, m); if (r < 0) return log_error_errno(r, "Failed to add match for PrepareForSleep: %m"); r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/network1", "org.freedesktop.network1.Manager", manager_vtable, m); if (r < 0) return log_error_errno(r, "Failed to add manager object vtable: %m"); r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.Link", link_vtable, link_object_find, m); if (r < 0) return log_error_errno(r, "Failed to add link object vtable: %m"); r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/link", link_node_enumerator, m); if (r < 0) return log_error_errno(r, "Failed to add link enumerator: %m"); r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/network", "org.freedesktop.network1.Network", network_vtable, network_object_find, m); if (r < 0) return log_error_errno(r, "Failed to add network object vtable: %m"); r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/network", network_node_enumerator, m); if (r < 0) return log_error_errno(r, "Failed to add network enumerator: %m"); r = sd_bus_request_name(m->bus, "org.freedesktop.network1", 0); if (r < 0) return log_error_errno(r, "Failed to register name: %m"); r = sd_bus_attach_event(m->bus, m->event, 0); if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop: %m"); return 0; } static int manager_udev_process_link(Manager *m, struct udev_device *device) { Link *link = NULL; int r, ifindex; assert(m); assert(device); if (!streq_ptr(udev_device_get_action(device), "add")) return 0; ifindex = udev_device_get_ifindex(device); if (ifindex <= 0) { log_debug("Ignoring udev ADD event for device with invalid ifindex"); return 0; } r = link_get(m, ifindex, &link); if (r == -ENODEV) return 0; else if (r < 0) return r; r = link_initialized(link, device); if (r < 0) return r; return 0; } static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; struct udev_monitor *monitor = m->udev_monitor; _cleanup_udev_device_unref_ struct udev_device *device = NULL; device = udev_monitor_receive_device(monitor); if (!device) return -ENOMEM; manager_udev_process_link(m, device); return 0; } static int manager_connect_udev(Manager *m) { int r; /* udev does not initialize devices inside containers, * so we rely on them being already initialized before * entering the container */ if (detect_container() > 0) return 0; m->udev = udev_new(); if (!m->udev) return -ENOMEM; m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"); if (!m->udev_monitor) return -ENOMEM; r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL); if (r < 0) return log_error_errno(r, "Could not add udev monitor filter: %m"); r = udev_monitor_enable_receiving(m->udev_monitor); if (r < 0) { log_error("Could not enable udev monitor"); return r; } r = sd_event_add_io(m->event, &m->udev_event_source, udev_monitor_get_fd(m->udev_monitor), EPOLLIN, manager_dispatch_link_udev, m); if (r < 0) return r; r = sd_event_source_set_description(m->udev_event_source, "networkd-udev"); if (r < 0) return r; return 0; } int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { Manager *m = userdata; Link *link = NULL; uint16_t type; uint32_t ifindex, priority = 0; unsigned char protocol, scope, tos, table; int family; unsigned char dst_prefixlen, src_prefixlen; union in_addr_union dst = {}, gw = {}, src = {}, prefsrc = {}; Route *route = NULL; int r; assert(rtnl); assert(message); assert(m); if (sd_netlink_message_is_error(message)) { r = sd_netlink_message_get_errno(message); if (r < 0) log_warning_errno(r, "rtnl: failed to receive route: %m"); return 0; } r = sd_netlink_message_get_type(message, &type); if (r < 0) { log_warning_errno(r, "rtnl: could not get message type: %m"); return 0; } else if (type != RTM_NEWROUTE && type != RTM_DELROUTE) { log_warning("rtnl: received unexpected message type when processing route"); return 0; } r = sd_netlink_message_read_u32(message, RTA_OIF, &ifindex); if (r == -ENODATA) { log_debug("rtnl: received route without ifindex, ignoring"); return 0; } else if (r < 0) { log_warning_errno(r, "rtnl: could not get ifindex from route, ignoring: %m"); return 0; } else if (ifindex <= 0) { log_warning("rtnl: received route message with invalid ifindex, ignoring: %d", ifindex); return 0; } else { r = link_get(m, ifindex, &link); if (r < 0 || !link) { /* when enumerating we might be out of sync, but we will * get the route again, so just ignore it */ if (!m->enumerating) log_warning("rtnl: received route for nonexistent link (%d), ignoring", ifindex); return 0; } } r = sd_rtnl_message_route_get_family(message, &family); if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) { log_link_warning(link, "rtnl: received address with invalid family, ignoring."); return 0; } r = sd_rtnl_message_route_get_protocol(message, &protocol); if (r < 0) { log_warning_errno(r, "rtnl: could not get route protocol: %m"); return 0; } switch (family) { case AF_INET: r = sd_netlink_message_read_in_addr(message, RTA_DST, &dst.in); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route without valid destination, ignoring: %m"); return 0; } r = sd_netlink_message_read_in_addr(message, RTA_GATEWAY, &gw.in); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route with invalid gateway, ignoring: %m"); return 0; } r = sd_netlink_message_read_in_addr(message, RTA_SRC, &src.in); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route with invalid source, ignoring: %m"); return 0; } r = sd_netlink_message_read_in_addr(message, RTA_PREFSRC, &prefsrc.in); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route with invalid preferred source, ignoring: %m"); return 0; } break; case AF_INET6: r = sd_netlink_message_read_in6_addr(message, RTA_DST, &dst.in6); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route without valid destination, ignoring: %m"); return 0; } r = sd_netlink_message_read_in6_addr(message, RTA_GATEWAY, &gw.in6); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route with invalid gateway, ignoring: %m"); return 0; } r = sd_netlink_message_read_in6_addr(message, RTA_SRC, &src.in6); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route with invalid source, ignoring: %m"); return 0; } r = sd_netlink_message_read_in6_addr(message, RTA_PREFSRC, &prefsrc.in6); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route with invalid preferred source, ignoring: %m"); return 0; } break; default: log_link_debug(link, "rtnl: ignoring unsupported address family: %d", family); return 0; } r = sd_rtnl_message_route_get_dst_prefixlen(message, &dst_prefixlen); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route with invalid destination prefixlen, ignoring: %m"); return 0; } r = sd_rtnl_message_route_get_src_prefixlen(message, &src_prefixlen); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route with invalid source prefixlen, ignoring: %m"); return 0; } r = sd_rtnl_message_route_get_scope(message, &scope); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route with invalid scope, ignoring: %m"); return 0; } r = sd_rtnl_message_route_get_tos(message, &tos); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route with invalid tos, ignoring: %m"); return 0; } r = sd_rtnl_message_route_get_table(message, &table); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route with invalid table, ignoring: %m"); return 0; } r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &priority); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route with invalid priority, ignoring: %m"); return 0; } route_get(link, family, &dst, dst_prefixlen, tos, priority, table, &route); switch (type) { case RTM_NEWROUTE: if (!route) { /* A route appeared that we did not request */ r = route_add_foreign(link, family, &dst, dst_prefixlen, tos, priority, table, &route); if (r < 0) return 0; } route_update(route, &src, src_prefixlen, &gw, &prefsrc, scope, protocol); break; case RTM_DELROUTE: if (route) route_drop(route); break; default: assert_not_reached("Received invalid RTNL message type"); } return 1; } int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { Manager *m = userdata; Link *link = NULL; uint16_t type; unsigned char flags; int family; unsigned char prefixlen; unsigned char scope; union in_addr_union in_addr; struct ifa_cacheinfo cinfo; Address *address = NULL; char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX]; const char *valid_str = NULL; int r, ifindex; assert(rtnl); assert(message); assert(m); if (sd_netlink_message_is_error(message)) { r = sd_netlink_message_get_errno(message); if (r < 0) log_warning_errno(r, "rtnl: failed to receive address: %m"); return 0; } r = sd_netlink_message_get_type(message, &type); if (r < 0) { log_warning_errno(r, "rtnl: could not get message type: %m"); return 0; } else if (type != RTM_NEWADDR && type != RTM_DELADDR) { log_warning("rtnl: received unexpected message type when processing address"); return 0; } r = sd_rtnl_message_addr_get_ifindex(message, &ifindex); if (r < 0) { log_warning_errno(r, "rtnl: could not get ifindex from address: %m"); return 0; } else if (ifindex <= 0) { log_warning("rtnl: received address message with invalid ifindex: %d", ifindex); return 0; } else { r = link_get(m, ifindex, &link); if (r < 0 || !link) { /* when enumerating we might be out of sync, but we will * get the address again, so just ignore it */ if (!m->enumerating) log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex); return 0; } } r = sd_rtnl_message_addr_get_family(message, &family); if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) { log_link_warning(link, "rtnl: received address with invalid family, ignoring."); return 0; } r = sd_rtnl_message_addr_get_prefixlen(message, &prefixlen); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m"); return 0; } r = sd_rtnl_message_addr_get_scope(message, &scope); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m"); return 0; } r = sd_rtnl_message_addr_get_flags(message, &flags); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m"); return 0; } switch (family) { case AF_INET: r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &in_addr.in); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m"); return 0; } break; case AF_INET6: r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &in_addr.in6); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m"); return 0; } break; default: log_link_debug(link, "rtnl: ignoring unsupported address family: %d", family); } if (!inet_ntop(family, &in_addr, buf, INET6_ADDRSTRLEN)) { log_link_warning(link, "Could not print address"); return 0; } r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo); if (r >= 0) { if (cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME) valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX, cinfo.ifa_valid * USEC_PER_SEC, USEC_PER_SEC); } address_get(link, family, &in_addr, prefixlen, &address); switch (type) { case RTM_NEWADDR: if (address) log_link_debug(link, "Updating address: %s/%u (valid %s%s)", buf, prefixlen, valid_str ? "for " : "forever", valid_str ?: ""); else { /* An address appeared that we did not request */ r = address_add_foreign(link, family, &in_addr, prefixlen, &address); if (r < 0) { log_link_warning_errno(link, r, "Failed to add address %s/%u: %m", buf, prefixlen); return 0; } else log_link_debug(link, "Adding address: %s/%u (valid %s%s)", buf, prefixlen, valid_str ? "for " : "forever", valid_str ?: ""); } address_update(address, flags, scope, &cinfo); break; case RTM_DELADDR: if (address) { log_link_debug(link, "Removing address: %s/%u (valid %s%s)", buf, prefixlen, valid_str ? "for " : "forever", valid_str ?: ""); address_drop(address); } else log_link_warning(link, "Removing non-existent address: %s/%u (valid %s%s)", buf, prefixlen, valid_str ? "for " : "forever", valid_str ?: ""); break; default: assert_not_reached("Received invalid RTNL message type"); } return 1; } static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { Manager *m = userdata; Link *link = NULL; NetDev *netdev = NULL; uint16_t type; const char *name; int r, ifindex; assert(rtnl); assert(message); assert(m); if (sd_netlink_message_is_error(message)) { r = sd_netlink_message_get_errno(message); if (r < 0) log_warning_errno(r, "rtnl: Could not receive link: %m"); return 0; } r = sd_netlink_message_get_type(message, &type); if (r < 0) { log_warning_errno(r, "rtnl: Could not get message type: %m"); return 0; } else if (type != RTM_NEWLINK && type != RTM_DELLINK) { log_warning("rtnl: Received unexpected message type when processing link"); return 0; } r = sd_rtnl_message_link_get_ifindex(message, &ifindex); if (r < 0) { log_warning_errno(r, "rtnl: Could not get ifindex from link: %m"); return 0; } else if (ifindex <= 0) { log_warning("rtnl: received link message with invalid ifindex: %d", ifindex); return 0; } r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name); if (r < 0) { log_warning_errno(r, "rtnl: Received link message without ifname: %m"); return 0; } (void) link_get(m, ifindex, &link); (void) netdev_get(m, name, &netdev); switch (type) { case RTM_NEWLINK: if (!link) { /* link is new, so add it */ r = link_add(m, message, &link); if (r < 0) { log_warning_errno(r, "Could not add new link: %m"); return 0; } } if (netdev) { /* netdev exists, so make sure the ifindex matches */ r = netdev_set_ifindex(netdev, message); if (r < 0) { log_warning_errno(r, "Could not set ifindex on netdev: %m"); return 0; } } r = link_update(link, message); if (r < 0) return 0; break; case RTM_DELLINK: link_drop(link); netdev_drop(netdev); break; default: assert_not_reached("Received invalid RTNL message type."); } return 1; } static int systemd_netlink_fd(void) { int n, fd, rtnl_fd = -EINVAL; n = sd_listen_fds(true); if (n <= 0) return -EINVAL; for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) { if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) { if (rtnl_fd >= 0) return -EINVAL; rtnl_fd = fd; } } return rtnl_fd; } static int manager_connect_rtnl(Manager *m) { int fd, r; assert(m); fd = systemd_netlink_fd(); if (fd < 0) r = sd_netlink_open(&m->rtnl); else r = sd_netlink_open_fd(&m->rtnl, fd); if (r < 0) return r; r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE); if (r < 0) return r; r = sd_netlink_attach_event(m->rtnl, m->event, 0); if (r < 0) return r; r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m); if (r < 0) return r; r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m); if (r < 0) return r; r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, &manager_rtnl_process_address, m); if (r < 0) return r; r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, &manager_rtnl_process_address, m); if (r < 0) return r; r = sd_netlink_add_match(m->rtnl, RTM_NEWROUTE, &manager_rtnl_process_route, m); if (r < 0) return r; r = sd_netlink_add_match(m->rtnl, RTM_DELROUTE, &manager_rtnl_process_route, m); if (r < 0) return r; return 0; } static int ordered_set_put_in_addr(OrderedSet *s, const struct in_addr *address) { char *p; int r; assert(s); r = in_addr_to_string(AF_INET, (const union in_addr_union*) address, &p); if (r < 0) return r; r = ordered_set_consume(s, p); if (r == -EEXIST) return 0; return r; } static int ordered_set_put_in_addrv(OrderedSet *s, const struct in_addr *addresses, int n) { int r, i, c = 0; assert(s); assert(n <= 0 || addresses); for (i = 0; i < n; i++) { r = ordered_set_put_in_addr(s, addresses+i); if (r < 0) return r; c += r; } return c; } static void print_string_set(FILE *f, const char *field, OrderedSet *s) { bool space = false; Iterator i; char *p; if (ordered_set_isempty(s)) return; fputs(field, f); ORDERED_SET_FOREACH(p, s, i) fputs_with_space(f, p, NULL, &space); fputc('\n', f); } static int manager_save(Manager *m) { _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *search_domains = NULL, *route_domains = NULL; Link *link; Iterator i; _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; LinkOperationalState operstate = LINK_OPERSTATE_OFF; const char *operstate_str; int r; assert(m); assert(m->state_file); /* We add all NTP and DNS server to a set, to filter out duplicates */ dns = ordered_set_new(&string_hash_ops); if (!dns) return -ENOMEM; ntp = ordered_set_new(&string_hash_ops); if (!ntp) return -ENOMEM; search_domains = ordered_set_new(&dns_name_hash_ops); if (!search_domains) return -ENOMEM; route_domains = ordered_set_new(&dns_name_hash_ops); if (!route_domains) return -ENOMEM; HASHMAP_FOREACH(link, m->links, i) { if (link->flags & IFF_LOOPBACK) continue; if (link->operstate > operstate) operstate = link->operstate; if (!link->network) continue; /* First add the static configured entries */ r = ordered_set_put_strdupv(dns, link->network->dns); if (r < 0) return r; r = ordered_set_put_strdupv(ntp, link->network->ntp); if (r < 0) return r; r = ordered_set_put_strdupv(search_domains, link->network->search_domains); if (r < 0) return r; r = ordered_set_put_strdupv(route_domains, link->network->route_domains); if (r < 0) return r; if (!link->dhcp_lease) continue; /* Secondly, add the entries acquired via DHCP */ if (link->network->dhcp_use_dns) { const struct in_addr *addresses; r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses); if (r > 0) { r = ordered_set_put_in_addrv(dns, addresses, r); if (r < 0) return r; } else if (r < 0 && r != -ENODATA) return r; } if (link->network->dhcp_use_ntp) { const struct in_addr *addresses; r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses); if (r > 0) { r = ordered_set_put_in_addrv(ntp, addresses, r); if (r < 0) return r; } else if (r < 0 && r != -ENODATA) return r; } if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) { const char *domainname; r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname); if (r >= 0) { if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) r = ordered_set_put_strdup(search_domains, domainname); else r = ordered_set_put_strdup(route_domains, domainname); if (r < 0) return r; } else if (r != -ENODATA) return r; } } operstate_str = link_operstate_to_string(operstate); assert(operstate_str); r = fopen_temporary(m->state_file, &f, &temp_path); if (r < 0) return r; fchmod(fileno(f), 0644); fprintf(f, "# This is private data. Do not parse.\n" "OPER_STATE=%s\n", operstate_str); print_string_set(f, "DNS=", dns); print_string_set(f, "NTP=", ntp); print_string_set(f, "DOMAINS=", search_domains); print_string_set(f, "ROUTE_DOMAINS=", route_domains); r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, m->state_file) < 0) { r = -errno; goto fail; } if (m->operational_state != operstate) { m->operational_state = operstate; r = manager_send_changed(m, "OperationalState", NULL); if (r < 0) log_error_errno(r, "Could not emit changed OperationalState: %m"); } m->dirty = false; return 0; fail: (void) unlink(m->state_file); (void) unlink(temp_path); return log_error_errno(r, "Failed to save network state to %s: %m", m->state_file); } static int manager_dirty_handler(sd_event_source *s, void *userdata) { Manager *m = userdata; Link *link; Iterator i; int r; assert(m); if (m->dirty) manager_save(m); SET_FOREACH(link, m->dirty_links, i) { r = link_save(link); if (r >= 0) link_clean(link); } return 1; } int manager_new(Manager **ret) { _cleanup_manager_free_ Manager *m = NULL; int r; m = new0(Manager, 1); if (!m) return -ENOMEM; m->state_file = strdup("/run/systemd/netif/state"); if (!m->state_file) return -ENOMEM; r = sd_event_default(&m->event); if (r < 0) return r; sd_event_set_watchdog(m->event, true); sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); r = sd_event_add_post(m->event, NULL, manager_dirty_handler, m); if (r < 0) return r; r = manager_connect_rtnl(m); if (r < 0) return r; r = manager_connect_udev(m); if (r < 0) return r; m->netdevs = hashmap_new(&string_hash_ops); if (!m->netdevs) return -ENOMEM; LIST_HEAD_INIT(m->networks); r = setup_default_address_pool(m); if (r < 0) return r; *ret = m; m = NULL; return 0; } void manager_free(Manager *m) { Network *network; NetDev *netdev; Link *link; AddressPool *pool; if (!m) return; free(m->state_file); while ((link = hashmap_first(m->links))) link_unref(link); hashmap_free(m->links); while ((network = m->networks)) network_free(network); hashmap_free(m->networks_by_name); while ((netdev = hashmap_first(m->netdevs))) netdev_unref(netdev); hashmap_free(m->netdevs); while ((pool = m->address_pools)) address_pool_free(pool); sd_netlink_unref(m->rtnl); sd_event_unref(m->event); sd_event_source_unref(m->udev_event_source); udev_monitor_unref(m->udev_monitor); udev_unref(m->udev); sd_bus_unref(m->bus); sd_bus_slot_unref(m->prepare_for_sleep_slot); sd_event_source_unref(m->bus_retry_event_source); free(m); } static bool manager_check_idle(void *userdata) { Manager *m = userdata; Link *link; Iterator i; assert(m); HASHMAP_FOREACH(link, m->links, i) { /* we are not woken on udev activity, so let's just wait for the * pending udev event */ if (link->state == LINK_STATE_PENDING) return false; if (!link->network) continue; /* we are not woken on netork activity, so let's stay around */ if (link_lldp_enabled(link) || link_ipv4ll_enabled(link) || link_dhcp4_server_enabled(link) || link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link)) return false; } return true; } int manager_run(Manager *m) { Link *link; Iterator i; assert(m); /* The dirty handler will deal with future serialization, but the first one must be done explicitly. */ manager_save(m); HASHMAP_FOREACH(link, m->links, i) link_save(link); if (m->bus) return bus_event_loop_with_idle( m->event, m->bus, "org.freedesktop.network1", DEFAULT_EXIT_USEC, manager_check_idle, m); else /* failed to connect to the bus, so we lose exit-on-idle logic, this should not happen except if dbus is not around at all */ return sd_event_loop(m->event); } int manager_load_config(Manager *m) { int r; /* update timestamp */ paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true); r = netdev_load(m); if (r < 0) return r; r = network_load(m); if (r < 0) return r; return 0; } bool manager_should_reload(Manager *m) { return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false); } int manager_rtnl_enumerate_links(Manager *m) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; sd_netlink_message *link; int r; assert(m); assert(m->rtnl); r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0); if (r < 0) return r; r = sd_netlink_message_request_dump(req, true); if (r < 0) return r; r = sd_netlink_call(m->rtnl, req, 0, &reply); if (r < 0) return r; for (link = reply; link; link = sd_netlink_message_next(link)) { int k; m->enumerating = true; k = manager_rtnl_process_link(m->rtnl, link, m); if (k < 0) r = k; m->enumerating = false; } return r; } int manager_rtnl_enumerate_addresses(Manager *m) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; sd_netlink_message *addr; int r; assert(m); assert(m->rtnl); r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, 0); if (r < 0) return r; r = sd_netlink_message_request_dump(req, true); if (r < 0) return r; r = sd_netlink_call(m->rtnl, req, 0, &reply); if (r < 0) return r; for (addr = reply; addr; addr = sd_netlink_message_next(addr)) { int k; m->enumerating = true; k = manager_rtnl_process_address(m->rtnl, addr, m); if (k < 0) r = k; m->enumerating = false; } return r; } int manager_rtnl_enumerate_routes(Manager *m) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; sd_netlink_message *route; int r; assert(m); assert(m->rtnl); r = sd_rtnl_message_new_route(m->rtnl, &req, RTM_GETROUTE, 0, 0); if (r < 0) return r; r = sd_netlink_message_request_dump(req, true); if (r < 0) return r; r = sd_netlink_call(m->rtnl, req, 0, &reply); if (r < 0) return r; for (route = reply; route; route = sd_netlink_message_next(route)) { int k; m->enumerating = true; k = manager_rtnl_process_route(m->rtnl, route, m); if (k < 0) r = k; m->enumerating = false; } return r; } int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) { AddressPool *p; int r; assert(m); assert(prefixlen > 0); assert(found); LIST_FOREACH(address_pools, p, m->address_pools) { if (p->family != family) continue; r = address_pool_acquire(p, prefixlen, found); if (r != 0) return r; } return 0; } Link* manager_find_uplink(Manager *m, Link *exclude) { _cleanup_free_ struct local_address *gateways = NULL; int n, i; assert(m); /* Looks for a suitable "uplink", via black magic: an * interface that is up and where the default route with the * highest priority points to. */ n = local_gateways(m->rtnl, 0, AF_UNSPEC, &gateways); if (n < 0) { log_warning_errno(n, "Failed to determine list of default gateways: %m"); return NULL; } for (i = 0; i < n; i++) { Link *link; link = hashmap_get(m->links, INT_TO_PTR(gateways[i].ifindex)); if (!link) { log_debug("Weird, found a gateway for a link we don't know. Ignoring."); continue; } if (link == exclude) continue; if (link->operstate < LINK_OPERSTATE_ROUTABLE) continue; return link; } return NULL; } void manager_dirty(Manager *manager) { assert(manager); /* the serialized state in /run is no longer up-to-date */ manager->dirty = true; } systemd-229/src/network/networkd-ndisc.c000066400000000000000000000206511265713322000204440ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2014 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-ndisc.h" #include "networkd-link.h" static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; assert(link); assert(link->ndisc_messages > 0); link->ndisc_messages --; r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) { log_link_error_errno(link, r, "Could not set NDisc route or address: %m"); link_enter_failed(link); } if (link->ndisc_messages == 0) { link->ndisc_configured = true; link_check_ready(link); } return 1; } static void ndisc_prefix_autonomous_handler(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen, unsigned lifetime_preferred, unsigned lifetime_valid, void *userdata) { _cleanup_address_free_ Address *address = NULL; Link *link = userdata; usec_t time_now; int r; assert(nd); assert(link); assert(link->network); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return; r = address_new(&address); if (r < 0) { log_link_error_errno(link, r, "Could not allocate address: %m"); return; } assert_se(sd_event_now(link->manager->event, clock_boottime_or_monotonic(), &time_now) >= 0); address->family = AF_INET6; address->in_addr.in6 = *prefix; if (in_addr_is_null(AF_INET6, (const union in_addr_union *) &link->network->ipv6_token) == 0) memcpy(((char *)&address->in_addr.in6) + 8, ((char *)&link->network->ipv6_token) + 8, 8); else { /* see RFC4291 section 2.5.1 */ address->in_addr.in6.__in6_u.__u6_addr8[8] = link->mac.ether_addr_octet[0]; address->in_addr.in6.__in6_u.__u6_addr8[8] ^= 1 << 1; address->in_addr.in6.__in6_u.__u6_addr8[9] = link->mac.ether_addr_octet[1]; address->in_addr.in6.__in6_u.__u6_addr8[10] = link->mac.ether_addr_octet[2]; address->in_addr.in6.__in6_u.__u6_addr8[11] = 0xff; address->in_addr.in6.__in6_u.__u6_addr8[12] = 0xfe; address->in_addr.in6.__in6_u.__u6_addr8[13] = link->mac.ether_addr_octet[3]; address->in_addr.in6.__in6_u.__u6_addr8[14] = link->mac.ether_addr_octet[4]; address->in_addr.in6.__in6_u.__u6_addr8[15] = link->mac.ether_addr_octet[5]; } address->prefixlen = prefixlen; address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR; address->cinfo.ifa_prefered = lifetime_preferred; address->cinfo.ifa_valid = lifetime_valid; r = address_configure(address, link, ndisc_netlink_handler, true); if (r < 0) { log_link_warning_errno(link, r, "Could not set SLAAC address: %m"); link_enter_failed(link); return; } link->ndisc_messages ++; } static void ndisc_prefix_onlink_handler(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen, unsigned lifetime, void *userdata) { _cleanup_route_free_ Route *route = NULL; Link *link = userdata; usec_t time_now; int r; assert(nd); assert(link); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return; r = route_new(&route); if (r < 0) { log_link_error_errno(link, r, "Could not allocate route: %m"); return; } assert_se(sd_event_now(link->manager->event, clock_boottime_or_monotonic(), &time_now) >= 0); route->family = AF_INET6; route->table = RT_TABLE_MAIN; route->protocol = RTPROT_RA; route->flags = RTM_F_PREFIX; route->dst.in6 = *prefix; route->dst_prefixlen = prefixlen; route->lifetime = time_now + lifetime * USEC_PER_SEC; r = route_configure(route, link, ndisc_netlink_handler); if (r < 0) { log_link_warning_errno(link, r, "Could not set prefix route: %m"); link_enter_failed(link); return; } link->ndisc_messages ++; } static void ndisc_router_handler(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata) { _cleanup_route_free_ Route *route = NULL; Link *link = userdata; usec_t time_now; int r; assert(link); assert(link->network); assert(link->manager); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return; if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) { if (flags & ND_RA_FLAG_MANAGED) dhcp6_request_address(link); r = sd_dhcp6_client_start(link->dhcp6_client); if (r < 0 && r != -EBUSY) log_link_warning_errno(link, r, "Starting DHCPv6 client on NDisc request failed: %m"); } if (!gateway) return; r = route_new(&route); if (r < 0) { log_link_error_errno(link, r, "Could not allocate route: %m"); return; } assert_se(sd_event_now(link->manager->event, clock_boottime_or_monotonic(), &time_now) >= 0); route->family = AF_INET6; route->table = RT_TABLE_MAIN; route->protocol = RTPROT_RA; route->pref = pref; route->gw.in6 = *gateway; route->lifetime = time_now + lifetime * USEC_PER_SEC; r = route_configure(route, link, ndisc_netlink_handler); if (r < 0) { log_link_warning_errno(link, r, "Could not set default route: %m"); link_enter_failed(link); return; } link->ndisc_messages ++; } static void ndisc_handler(sd_ndisc *nd, int event, void *userdata) { Link *link = userdata; int r; assert(link); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return; switch (event) { case SD_NDISC_EVENT_TIMEOUT: dhcp6_request_address(link); r = sd_dhcp6_client_start(link->dhcp6_client); if (r < 0 && r != -EBUSY) log_link_warning_errno(link, r, "Starting DHCPv6 client after NDisc timeout failed: %m"); link->ndisc_configured = true; link_check_ready(link); break; case SD_NDISC_EVENT_STOP: break; default: log_link_warning(link, "IPv6 Neighbor Discovery unknown event: %d", event); } } int ndisc_configure(Link *link) { int r; assert_return(link, -EINVAL); r = sd_ndisc_new(&link->ndisc_router_discovery); if (r < 0) return r; r = sd_ndisc_attach_event(link->ndisc_router_discovery, NULL, 0); if (r < 0) return r; r = sd_ndisc_set_mac(link->ndisc_router_discovery, &link->mac); if (r < 0) return r; r = sd_ndisc_set_index(link->ndisc_router_discovery, link->ifindex); if (r < 0) return r; r = sd_ndisc_set_callback(link->ndisc_router_discovery, ndisc_router_handler, ndisc_prefix_onlink_handler, ndisc_prefix_autonomous_handler, ndisc_handler, link); return r; } systemd-229/src/network/networkd-netdev-bond.c000066400000000000000000000440151265713322000215510ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen Copyright 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-netlink.h" #include "alloc-util.h" #include "conf-parser.h" #include "missing.h" #include "networkd-netdev-bond.h" #include "string-table.h" #include "string-util.h" /* * Number of seconds between instances where the bonding * driver sends learning packets to each slaves peer switch */ #define LEARNING_PACKETS_INTERVAL_MIN_SEC (1 * USEC_PER_SEC) #define LEARNING_PACKETS_INTERVAL_MAX_SEC (0x7fffffff * USEC_PER_SEC) /* Number of IGMP membership reports to be issued after * a failover event. */ #define RESEND_IGMP_MIN 0 #define RESEND_IGMP_MAX 255 #define RESEND_IGMP_DEFAULT 1 /* * Number of packets to transmit through a slave before * moving to the next one. */ #define PACKETS_PER_SLAVE_MIN 0 #define PACKETS_PER_SLAVE_MAX 65535 #define PACKETS_PER_SLAVE_DEFAULT 1 /* * Number of peer notifications (gratuitous ARPs and * unsolicited IPv6 Neighbor Advertisements) to be issued after a * failover event. */ #define GRATUITOUS_ARP_MIN 0 #define GRATUITOUS_ARP_MAX 255 #define GRATUITOUS_ARP_DEFAULT 1 static const char* const bond_mode_table[_NETDEV_BOND_MODE_MAX] = { [NETDEV_BOND_MODE_BALANCE_RR] = "balance-rr", [NETDEV_BOND_MODE_ACTIVE_BACKUP] = "active-backup", [NETDEV_BOND_MODE_BALANCE_XOR] = "balance-xor", [NETDEV_BOND_MODE_BROADCAST] = "broadcast", [NETDEV_BOND_MODE_802_3AD] = "802.3ad", [NETDEV_BOND_MODE_BALANCE_TLB] = "balance-tlb", [NETDEV_BOND_MODE_BALANCE_ALB] = "balance-alb", }; DEFINE_STRING_TABLE_LOOKUP(bond_mode, BondMode); DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_mode, bond_mode, BondMode, "Failed to parse bond mode"); static const char* const bond_xmit_hash_policy_table[_NETDEV_BOND_XMIT_HASH_POLICY_MAX] = { [NETDEV_BOND_XMIT_HASH_POLICY_LAYER2] = "layer2", [NETDEV_BOND_XMIT_HASH_POLICY_LAYER34] = "layer3+4", [NETDEV_BOND_XMIT_HASH_POLICY_LAYER23] = "layer2+3", [NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23] = "encap2+3", [NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34] = "encap3+4", }; DEFINE_STRING_TABLE_LOOKUP(bond_xmit_hash_policy, BondXmitHashPolicy); DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_xmit_hash_policy, bond_xmit_hash_policy, BondXmitHashPolicy, "Failed to parse bond transmit hash policy") static const char* const bond_lacp_rate_table[_NETDEV_BOND_LACP_RATE_MAX] = { [NETDEV_BOND_LACP_RATE_SLOW] = "slow", [NETDEV_BOND_LACP_RATE_FAST] = "fast", }; DEFINE_STRING_TABLE_LOOKUP(bond_lacp_rate, BondLacpRate); DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_lacp_rate, bond_lacp_rate, BondLacpRate, "Failed to parse bond lacp rate") static const char* const bond_ad_select_table[_NETDEV_BOND_AD_SELECT_MAX] = { [NETDEV_BOND_AD_SELECT_STABLE] = "stable", [NETDEV_BOND_AD_SELECT_BANDWIDTH] = "bandwidth", [NETDEV_BOND_AD_SELECT_COUNT] = "count", }; DEFINE_STRING_TABLE_LOOKUP(bond_ad_select, BondAdSelect); DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_ad_select, bond_ad_select, BondAdSelect, "Failed to parse bond AD select"); static const char* const bond_fail_over_mac_table[_NETDEV_BOND_FAIL_OVER_MAC_MAX] = { [NETDEV_BOND_FAIL_OVER_MAC_NONE] = "none", [NETDEV_BOND_FAIL_OVER_MAC_ACTIVE] = "active", [NETDEV_BOND_FAIL_OVER_MAC_FOLLOW] = "follow", }; DEFINE_STRING_TABLE_LOOKUP(bond_fail_over_mac, BondFailOverMac); DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_fail_over_mac, bond_fail_over_mac, BondFailOverMac, "Failed to parse bond fail over MAC"); static const char *const bond_arp_validate_table[_NETDEV_BOND_ARP_VALIDATE_MAX] = { [NETDEV_BOND_ARP_VALIDATE_NONE] = "none", [NETDEV_BOND_ARP_VALIDATE_ACTIVE]= "active", [NETDEV_BOND_ARP_VALIDATE_BACKUP]= "backup", [NETDEV_BOND_ARP_VALIDATE_ALL]= "all", }; DEFINE_STRING_TABLE_LOOKUP(bond_arp_validate, BondArpValidate); DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_arp_validate, bond_arp_validate, BondArpValidate, "Failed to parse bond arp validate"); static const char *const bond_arp_all_targets_table[_NETDEV_BOND_ARP_ALL_TARGETS_MAX] = { [NETDEV_BOND_ARP_ALL_TARGETS_ANY] = "any", [NETDEV_BOND_ARP_ALL_TARGETS_ALL] = "all", }; DEFINE_STRING_TABLE_LOOKUP(bond_arp_all_targets, BondArpAllTargets); DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_arp_all_targets, bond_arp_all_targets, BondArpAllTargets, "Failed to parse bond Arp all targets"); static const char *bond_primary_reselect_table[_NETDEV_BOND_PRIMARY_RESELECT_MAX] = { [NETDEV_BOND_PRIMARY_RESELECT_ALWAYS] = "always", [NETDEV_BOND_PRIMARY_RESELECT_BETTER]= "better", [NETDEV_BOND_PRIMARY_RESELECT_FAILURE]= "failure", }; DEFINE_STRING_TABLE_LOOKUP(bond_primary_reselect, BondPrimaryReselect); DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_primary_reselect, bond_primary_reselect, BondPrimaryReselect, "Failed to parse bond primary reselect"); static uint8_t bond_mode_to_kernel(BondMode mode) { switch (mode) { case NETDEV_BOND_MODE_BALANCE_RR: return BOND_MODE_ROUNDROBIN; case NETDEV_BOND_MODE_ACTIVE_BACKUP: return BOND_MODE_ACTIVEBACKUP; case NETDEV_BOND_MODE_BALANCE_XOR: return BOND_MODE_XOR; case NETDEV_BOND_MODE_BROADCAST: return BOND_MODE_BROADCAST; case NETDEV_BOND_MODE_802_3AD: return BOND_MODE_8023AD; case NETDEV_BOND_MODE_BALANCE_TLB: return BOND_MODE_TLB; case NETDEV_BOND_MODE_BALANCE_ALB: return BOND_MODE_ALB; default: return (uint8_t) -1; } } static uint8_t bond_xmit_hash_policy_to_kernel(BondXmitHashPolicy policy) { switch (policy) { case NETDEV_BOND_XMIT_HASH_POLICY_LAYER2: return BOND_XMIT_POLICY_LAYER2; case NETDEV_BOND_XMIT_HASH_POLICY_LAYER34: return BOND_XMIT_POLICY_LAYER34; case NETDEV_BOND_XMIT_HASH_POLICY_LAYER23: return BOND_XMIT_POLICY_LAYER23; case NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23: return BOND_XMIT_POLICY_ENCAP23; case NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34: return BOND_XMIT_POLICY_ENCAP34; default: return (uint8_t) -1; } } static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { Bond *b; ArpIpTarget *target = NULL; int r, i = 0; assert(netdev); assert(!link); assert(m); b = BOND(netdev); assert(b); if (b->mode != _NETDEV_BOND_MODE_INVALID) { r = sd_netlink_message_append_u8(m, IFLA_BOND_MODE, bond_mode_to_kernel(b->mode)); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_MODE attribute: %m"); } if (b->xmit_hash_policy != _NETDEV_BOND_XMIT_HASH_POLICY_INVALID) { r = sd_netlink_message_append_u8(m, IFLA_BOND_XMIT_HASH_POLICY, bond_xmit_hash_policy_to_kernel(b->xmit_hash_policy)); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_XMIT_HASH_POLICY attribute: %m"); } if (b->lacp_rate != _NETDEV_BOND_LACP_RATE_INVALID && b->mode == NETDEV_BOND_MODE_802_3AD) { r = sd_netlink_message_append_u8(m, IFLA_BOND_AD_LACP_RATE, b->lacp_rate ); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_LACP_RATE attribute: %m"); } if (b->miimon != 0) { r = sd_netlink_message_append_u32(m, IFLA_BOND_MIIMON, b->miimon / USEC_PER_MSEC); if (r < 0) log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_BOND_MIIMON attribute: %m"); } if (b->downdelay != 0) { r = sd_netlink_message_append_u32(m, IFLA_BOND_DOWNDELAY, b->downdelay / USEC_PER_MSEC); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_DOWNDELAY attribute: %m"); } if (b->updelay != 0) { r = sd_netlink_message_append_u32(m, IFLA_BOND_UPDELAY, b->updelay / USEC_PER_MSEC); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_UPDELAY attribute: %m"); } if (b->arp_interval != 0) { r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_INTERVAL, b->arp_interval / USEC_PER_MSEC); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_INTERVAL attribute: %m"); if ((b->lp_interval >= LEARNING_PACKETS_INTERVAL_MIN_SEC) && (b->lp_interval <= LEARNING_PACKETS_INTERVAL_MAX_SEC)) { r = sd_netlink_message_append_u32(m, IFLA_BOND_LP_INTERVAL, b->lp_interval / USEC_PER_SEC); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_LP_INTERVAL attribute: %m"); } } if (b->ad_select != _NETDEV_BOND_AD_SELECT_INVALID && b->mode == NETDEV_BOND_MODE_802_3AD) { r = sd_netlink_message_append_u8(m, IFLA_BOND_AD_SELECT, b->ad_select); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_SELECT attribute: %m"); } if (b->fail_over_mac != _NETDEV_BOND_FAIL_OVER_MAC_INVALID && b->mode == NETDEV_BOND_MODE_ACTIVE_BACKUP) { r = sd_netlink_message_append_u8(m, IFLA_BOND_FAIL_OVER_MAC, b->fail_over_mac); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_FAIL_OVER_MAC attribute: %m"); } if (b->arp_validate != _NETDEV_BOND_ARP_VALIDATE_INVALID) { r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_VALIDATE, b->arp_validate); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_VALIDATE attribute: %m"); } if (b->arp_all_targets != _NETDEV_BOND_ARP_ALL_TARGETS_INVALID) { r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_ALL_TARGETS, b->arp_all_targets); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_VALIDATE attribute: %m"); } if (b->primary_reselect != _NETDEV_BOND_PRIMARY_RESELECT_INVALID) { r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_ALL_TARGETS, b->primary_reselect); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m"); } if (b->resend_igmp <= RESEND_IGMP_MAX) { r = sd_netlink_message_append_u32(m, IFLA_BOND_RESEND_IGMP, b->resend_igmp); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_RESEND_IGMP attribute: %m"); } if (b->packets_per_slave <= PACKETS_PER_SLAVE_MAX && b->mode == NETDEV_BOND_MODE_BALANCE_RR) { r = sd_netlink_message_append_u32(m, IFLA_BOND_PACKETS_PER_SLAVE, b->packets_per_slave); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_PACKETS_PER_SLAVE attribute: %m"); } if (b->num_grat_arp <= GRATUITOUS_ARP_MAX) { r = sd_netlink_message_append_u8(m, IFLA_BOND_NUM_PEER_NOTIF, b->num_grat_arp); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_NUM_PEER_NOTIF attribute: %m"); } if (b->min_links != 0) { r = sd_netlink_message_append_u32(m, IFLA_BOND_MIN_LINKS, b->min_links); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_MIN_LINKS attribute: %m"); } r = sd_netlink_message_append_u8(m, IFLA_BOND_ALL_SLAVES_ACTIVE, b->all_slaves_active); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ALL_SLAVES_ACTIVE attribute: %m"); if (b->arp_interval > 0) { if (b->n_arp_ip_targets > 0) { r = sd_netlink_message_open_container(m, IFLA_BOND_ARP_IP_TARGET); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not open contaniner IFLA_BOND_ARP_IP_TARGET : %m"); LIST_FOREACH(arp_ip_target, target, b->arp_ip_targets) { r = sd_netlink_message_append_u32(m, i++, target->ip.in.s_addr); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m"); } r = sd_netlink_message_close_container(m); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not close contaniner IFLA_BOND_ARP_IP_TARGET : %m"); } } return 0; } int config_parse_arp_ip_target_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Bond *b = userdata; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); for (;;) { _cleanup_free_ ArpIpTarget *buffer = NULL; _cleanup_free_ char *n = NULL; int f; r = extract_first_word(&rvalue, &n, NULL, 0); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Bond ARP ip target address, ignoring assignment: %s", rvalue); return 0; } if (r == 0) break; buffer = new0(ArpIpTarget, 1); if (!buffer) return -ENOMEM; r = in_addr_from_string_auto(n, &f, &buffer->ip); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Bond ARP ip target address is invalid, ignoring assignment: %s", n); return 0; } if (f != AF_INET) { log_syntax(unit, LOG_ERR, filename, line, 0, "Bond ARP ip target address is invalid, ignoring assignment: %s", n); return 0; } LIST_PREPEND(arp_ip_target, b->arp_ip_targets, buffer); b->n_arp_ip_targets ++; buffer = NULL; } if (b->n_arp_ip_targets > NETDEV_BOND_ARP_TARGETS_MAX) log_syntax(unit, LOG_WARNING, filename, line, 0, "More than the maximum number of kernel-supported ARP ip targets specified: %d > %d", b->n_arp_ip_targets, NETDEV_BOND_ARP_TARGETS_MAX); return 0; } static void bond_done(NetDev *netdev) { ArpIpTarget *t = NULL, *n = NULL; Bond *b; assert(netdev); b = BOND(netdev); assert(b); LIST_FOREACH_SAFE(arp_ip_target, t, n, b->arp_ip_targets) free(t); b->arp_ip_targets = NULL; } static void bond_init(NetDev *netdev) { Bond *b; assert(netdev); b = BOND(netdev); assert(b); b->mode = _NETDEV_BOND_MODE_INVALID; b->xmit_hash_policy = _NETDEV_BOND_XMIT_HASH_POLICY_INVALID; b->lacp_rate = _NETDEV_BOND_LACP_RATE_INVALID; b->ad_select = _NETDEV_BOND_AD_SELECT_INVALID; b->fail_over_mac = _NETDEV_BOND_FAIL_OVER_MAC_INVALID; b->arp_validate = _NETDEV_BOND_ARP_VALIDATE_INVALID; b->arp_all_targets = _NETDEV_BOND_ARP_ALL_TARGETS_INVALID; b->primary_reselect = _NETDEV_BOND_PRIMARY_RESELECT_INVALID; b->all_slaves_active = false; b->resend_igmp = RESEND_IGMP_DEFAULT; b->packets_per_slave = PACKETS_PER_SLAVE_DEFAULT; b->num_grat_arp = GRATUITOUS_ARP_DEFAULT; b->lp_interval = LEARNING_PACKETS_INTERVAL_MIN_SEC; LIST_HEAD_INIT(b->arp_ip_targets); b->n_arp_ip_targets = 0; } const NetDevVTable bond_vtable = { .object_size = sizeof(Bond), .init = bond_init, .done = bond_done, .sections = "Match\0NetDev\0Bond\0", .fill_message_create = netdev_bond_fill_message_create, .create_type = NETDEV_CREATE_MASTER, }; systemd-229/src/network/networkd-netdev-bond.h000066400000000000000000000157121265713322000215600ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "in-addr-util.h" typedef struct Bond Bond; #include "networkd-netdev.h" /* * Maximum number of targets supported by the kernel for a single * bond netdev. */ #define NETDEV_BOND_ARP_TARGETS_MAX 16 typedef enum BondMode { NETDEV_BOND_MODE_BALANCE_RR, NETDEV_BOND_MODE_ACTIVE_BACKUP, NETDEV_BOND_MODE_BALANCE_XOR, NETDEV_BOND_MODE_BROADCAST, NETDEV_BOND_MODE_802_3AD, NETDEV_BOND_MODE_BALANCE_TLB, NETDEV_BOND_MODE_BALANCE_ALB, _NETDEV_BOND_MODE_MAX, _NETDEV_BOND_MODE_INVALID = -1 } BondMode; typedef enum BondXmitHashPolicy { NETDEV_BOND_XMIT_HASH_POLICY_LAYER2, NETDEV_BOND_XMIT_HASH_POLICY_LAYER34, NETDEV_BOND_XMIT_HASH_POLICY_LAYER23, NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23, NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34, _NETDEV_BOND_XMIT_HASH_POLICY_MAX, _NETDEV_BOND_XMIT_HASH_POLICY_INVALID = -1 } BondXmitHashPolicy; typedef enum BondLacpRate { NETDEV_BOND_LACP_RATE_SLOW, NETDEV_BOND_LACP_RATE_FAST, _NETDEV_BOND_LACP_RATE_MAX, _NETDEV_BOND_LACP_RATE_INVALID = -1, } BondLacpRate; typedef enum BondAdSelect { NETDEV_BOND_AD_SELECT_STABLE, NETDEV_BOND_AD_SELECT_BANDWIDTH, NETDEV_BOND_AD_SELECT_COUNT, _NETDEV_BOND_AD_SELECT_MAX, _NETDEV_BOND_AD_SELECT_INVALID = -1, } BondAdSelect; typedef enum BondFailOverMac { NETDEV_BOND_FAIL_OVER_MAC_NONE, NETDEV_BOND_FAIL_OVER_MAC_ACTIVE, NETDEV_BOND_FAIL_OVER_MAC_FOLLOW, _NETDEV_BOND_FAIL_OVER_MAC_MAX, _NETDEV_BOND_FAIL_OVER_MAC_INVALID = -1, } BondFailOverMac; typedef enum BondArpValidate { NETDEV_BOND_ARP_VALIDATE_NONE, NETDEV_BOND_ARP_VALIDATE_ACTIVE, NETDEV_BOND_ARP_VALIDATE_BACKUP, NETDEV_BOND_ARP_VALIDATE_ALL, _NETDEV_BOND_ARP_VALIDATE_MAX, _NETDEV_BOND_ARP_VALIDATE_INVALID = -1, } BondArpValidate; typedef enum BondArpAllTargets { NETDEV_BOND_ARP_ALL_TARGETS_ANY, NETDEV_BOND_ARP_ALL_TARGETS_ALL, _NETDEV_BOND_ARP_ALL_TARGETS_MAX, _NETDEV_BOND_ARP_ALL_TARGETS_INVALID = -1, } BondArpAllTargets; typedef enum BondPrimaryReselect { NETDEV_BOND_PRIMARY_RESELECT_ALWAYS, NETDEV_BOND_PRIMARY_RESELECT_BETTER, NETDEV_BOND_PRIMARY_RESELECT_FAILURE, _NETDEV_BOND_PRIMARY_RESELECT_MAX, _NETDEV_BOND_PRIMARY_RESELECT_INVALID = -1, } BondPrimaryReselect; typedef struct ArpIpTarget { union in_addr_union ip; LIST_FIELDS(struct ArpIpTarget, arp_ip_target); } ArpIpTarget; struct Bond { NetDev meta; BondMode mode; BondXmitHashPolicy xmit_hash_policy; BondLacpRate lacp_rate; BondAdSelect ad_select; BondFailOverMac fail_over_mac; BondArpValidate arp_validate; BondArpAllTargets arp_all_targets; BondPrimaryReselect primary_reselect; bool all_slaves_active; unsigned resend_igmp; unsigned packets_per_slave; unsigned num_grat_arp; unsigned min_links; usec_t miimon; usec_t updelay; usec_t downdelay; usec_t arp_interval; usec_t lp_interval; int n_arp_ip_targets; ArpIpTarget *arp_ip_targets; }; extern const NetDevVTable bond_vtable; const char *bond_mode_to_string(BondMode d) _const_; BondMode bond_mode_from_string(const char *d) _pure_; const char *bond_xmit_hash_policy_to_string(BondXmitHashPolicy d) _const_; BondXmitHashPolicy bond_xmit_hash_policy_from_string(const char *d) _pure_; const char *bond_lacp_rate_to_string(BondLacpRate d) _const_; BondLacpRate bond_lacp_rate_from_string(const char *d) _pure_; const char *bond_fail_over_mac_to_string(BondFailOverMac d) _const_; BondFailOverMac bond_fail_over_mac_from_string(const char *d) _pure_; const char *bond_ad_select_to_string(BondAdSelect d) _const_; BondAdSelect bond_ad_select_from_string(const char *d) _pure_; const char *bond_arp_validate_to_string(BondArpValidate d) _const_; BondArpValidate bond_arp_validate_from_string(const char *d) _pure_; const char *bond_arp_all_targets_to_string(BondArpAllTargets d) _const_; BondArpAllTargets bond_arp_all_targets_from_string(const char *d) _pure_; const char *bond_primary_reselect_to_string(BondPrimaryReselect d) _const_; BondPrimaryReselect bond_primary_reselect_from_string(const char *d) _pure_; int config_parse_bond_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bond_xmit_hash_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bond_lacp_rate(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bond_ad_select(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bond_fail_over_mac(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bond_arp_validate(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bond_arp_all_targets(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bond_primary_reselect(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_arp_ip_target_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); systemd-229/src/network/networkd-netdev-bridge.c000066400000000000000000000103551265713322000220630ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen Copyright 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "missing.h" #include "netlink-util.h" #include "networkd-netdev-bridge.h" /* callback for brige netdev's parameter set */ static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_netdev_unref_ NetDev *netdev = userdata; int r; assert(netdev); assert(m); r = sd_netlink_message_get_errno(m); if (r < 0) { log_netdev_warning_errno(netdev, r, "Bridge parameters could not be set: %m"); return 1; } log_netdev_debug(netdev, "Bridge parametres set success"); return 1; } static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_message *m) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; Bridge *b; int r; assert(netdev); b = BRIDGE(netdev); assert(b); r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, netdev->ifindex); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not allocate RTM_SETLINK message: %m"); r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK); if (r < 0) return log_link_error_errno(link, r, "Could not set netlink flags: %m"); r = sd_netlink_message_open_container(req, IFLA_LINKINFO); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_PROTINFO attribute: %m"); r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind)); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); /* convert to jiffes */ if (b->forward_delay > 0) { r = sd_netlink_message_append_u32(req, IFLA_BR_FORWARD_DELAY, usec_to_jiffies(b->forward_delay)); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_FORWARD_DELAY attribute: %m"); } if (b->hello_time > 0) { r = sd_netlink_message_append_u32(req, IFLA_BR_HELLO_TIME, usec_to_jiffies(b->hello_time)); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_HELLO_TIME attribute: %m"); } if (b->max_age > 0) { r = sd_netlink_message_append_u32(req, IFLA_BR_MAX_AGE, usec_to_jiffies(b->max_age)); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MAX_AGE attribute: %m"); } r = sd_netlink_message_close_container(req); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); r = sd_netlink_message_close_container(req); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); r = sd_netlink_call_async(netdev->manager->rtnl, req, netdev_bridge_set_handler, netdev, 0, NULL); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); netdev_ref(netdev); return r; } const NetDevVTable bridge_vtable = { .object_size = sizeof(Bridge), .sections = "Match\0NetDev\0Bridge\0", .post_create = netdev_bridge_post_create, .create_type = NETDEV_CREATE_MASTER, }; systemd-229/src/network/networkd-netdev-bridge.h000066400000000000000000000017071265713322000220710ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once typedef struct Bridge Bridge; #include "networkd-netdev.h" struct Bridge { NetDev meta; usec_t forward_delay; usec_t hello_time; usec_t max_age; }; extern const NetDevVTable bridge_vtable; systemd-229/src/network/networkd-netdev-dummy.c000066400000000000000000000017421265713322000217620ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Susant Sahani Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "networkd-netdev-dummy.h" const NetDevVTable dummy_vtable = { .object_size = sizeof(Dummy), .sections = "Match\0NetDev\0", .create_type = NETDEV_CREATE_INDEPENDENT, }; systemd-229/src/network/networkd-netdev-dummy.h000066400000000000000000000015611265713322000217660ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once typedef struct Dummy Dummy; #include "networkd-netdev.h" struct Dummy { NetDev meta; }; extern const NetDevVTable dummy_vtable; systemd-229/src/network/networkd-netdev-gperf.gperf000066400000000000000000000225141265713322000226130ustar00rootroot00000000000000%{ #include #include "conf-parser.h" #include "networkd-netdev.h" #include "networkd-netdev-tunnel.h" #include "networkd-netdev-bond.h" #include "networkd-netdev-macvlan.h" #include "network-internal.h" %} struct ConfigPerfItem; %null_strings %language=ANSI-C %define slot-name section_and_lvalue %define hash-function-name network_netdev_gperf_hash %define lookup-function-name network_netdev_gperf_lookup %readonly-tables %omit-struct-type %struct-type %includes %% Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(NetDev, match_host) Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(NetDev, match_virt) Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(NetDev, match_kernel) Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(NetDev, match_arch) NetDev.Description, config_parse_string, 0, offsetof(NetDev, description) NetDev.Name, config_parse_ifname, 0, offsetof(NetDev, ifname) NetDev.Kind, config_parse_netdev_kind, 0, offsetof(NetDev, kind) NetDev.MTUBytes, config_parse_iec_size, 0, offsetof(NetDev, mtu) NetDev.MACAddress, config_parse_hwaddr, 0, offsetof(NetDev, mac) VLAN.Id, config_parse_uint64, 0, offsetof(VLan, id) MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) MACVTAP.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) IPVLAN.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode) Tunnel.Local, config_parse_tunnel_address, 0, offsetof(Tunnel, local) Tunnel.Remote, config_parse_tunnel_address, 0, offsetof(Tunnel, remote) Tunnel.TOS, config_parse_unsigned, 0, offsetof(Tunnel, tos) Tunnel.TTL, config_parse_unsigned, 0, offsetof(Tunnel, ttl) Tunnel.DiscoverPathMTU, config_parse_bool, 0, offsetof(Tunnel, pmtudisc) Tunnel.Mode, config_parse_ip6tnl_mode, 0, offsetof(Tunnel, ip6tnl_mode) Tunnel.IPv6FlowLabel, config_parse_ipv6_flowlabel, 0, offsetof(Tunnel, ipv6_flowlabel) Tunnel.CopyDSCP, config_parse_bool, 0, offsetof(Tunnel, copy_dscp) Tunnel.EncapsulationLimit, config_parse_encap_limit, 0, offsetof(Tunnel, encap_limit) Peer.Name, config_parse_ifname, 0, offsetof(Veth, ifname_peer) Peer.MACAddress, config_parse_hwaddr, 0, offsetof(Veth, mac_peer) VXLAN.Id, config_parse_uint64, 0, offsetof(VxLan, id) VXLAN.Group, config_parse_vxlan_group_address, 0, offsetof(VxLan, group) VXLAN.TOS, config_parse_unsigned, 0, offsetof(VxLan, tos) VXLAN.TTL, config_parse_unsigned, 0, offsetof(VxLan, ttl) VXLAN.MacLearning, config_parse_bool, 0, offsetof(VxLan, learning) VXLAN.ARPProxy, config_parse_bool, 0, offsetof(VxLan, arp_proxy) VXLAN.L2MissNotification, config_parse_bool, 0, offsetof(VxLan, l2miss) VXLAN.L3MissNotification, config_parse_bool, 0, offsetof(VxLan, l3miss) VXLAN.RouteShortCircuit, config_parse_bool, 0, offsetof(VxLan, route_short_circuit) VXLAN.UDPCheckSum, config_parse_bool, 0, offsetof(VxLan, udpcsum) VXLAN.UDP6ZeroCheckSumRx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumrx) VXLAN.UDP6ZeroCheckSumTx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumtx) VXLAN.FDBAgeingSec, config_parse_sec, 0, offsetof(VxLan, fdb_ageing) VXLAN.GroupPolicyExtension, config_parse_bool, 0, offsetof(VxLan, group_policy) VXLAN.MaximumFDBEntries, config_parse_unsigned, 0, offsetof(VxLan, max_fdb) VXLAN.PortRange, config_parse_port_range, 0, 0 VXLAN.DestinationPort, config_parse_destination_port, 0, offsetof(VxLan, dest_port) Tun.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue) Tun.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue) Tun.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info) Tun.User, config_parse_string, 0, offsetof(TunTap, user_name) Tun.Group, config_parse_string, 0, offsetof(TunTap, group_name) Tap.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue) Tap.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue) Tap.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info) Tap.VNetHeader, config_parse_bool, 0, offsetof(TunTap, vnet_hdr) Tap.User, config_parse_string, 0, offsetof(TunTap, user_name) Tap.Group, config_parse_string, 0, offsetof(TunTap, group_name) Bond.Mode, config_parse_bond_mode, 0, offsetof(Bond, mode) Bond.TransmitHashPolicy, config_parse_bond_xmit_hash_policy, 0, offsetof(Bond, xmit_hash_policy) Bond.LACPTransmitRate, config_parse_bond_lacp_rate, 0, offsetof(Bond, lacp_rate) Bond.AdSelect, config_parse_bond_ad_select, 0, offsetof(Bond, ad_select) Bond.FailOverMACPolicy, config_parse_bond_fail_over_mac, 0, offsetof(Bond, fail_over_mac) Bond.ARPIPTargets, config_parse_arp_ip_target_address, 0, 0 Bond.ARPValidate, config_parse_bond_arp_validate, 0, offsetof(Bond, arp_validate) Bond.ARPAllTargets, config_parse_bond_arp_all_targets, 0, offsetof(Bond, arp_all_targets) Bond.PrimaryReselectPolicy, config_parse_bond_primary_reselect, 0, offsetof(Bond, primary_reselect) Bond.ResendIGMP, config_parse_unsigned, 0, offsetof(Bond, resend_igmp) Bond.PacketsPerSlave, config_parse_unsigned, 0, offsetof(Bond, packets_per_slave) Bond.GratuitousARP, config_parse_unsigned, 0, offsetof(Bond, num_grat_arp) Bond.AllSlavesActive, config_parse_unsigned, 0, offsetof(Bond, all_slaves_active) Bond.MinLinks, config_parse_unsigned, 0, offsetof(Bond, min_links) Bond.MIIMonitorSec, config_parse_sec, 0, offsetof(Bond, miimon) Bond.UpDelaySec, config_parse_sec, 0, offsetof(Bond, updelay) Bond.DownDelaySec, config_parse_sec, 0, offsetof(Bond, downdelay) Bond.ARPIntervalSec, config_parse_sec, 0, offsetof(Bond, arp_interval) Bond.LearnPacketIntervalSec, config_parse_sec, 0, offsetof(Bond, lp_interval) Bridge.HelloTimeSec, config_parse_sec, 0, offsetof(Bridge, hello_time) Bridge.MaxAgeSec, config_parse_sec, 0, offsetof(Bridge, max_age) Bridge.ForwardDelaySec, config_parse_sec, 0, offsetof(Bridge, forward_delay) systemd-229/src/network/networkd-netdev-ipvlan.c000066400000000000000000000041761265713322000221240ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013-2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "conf-parser.h" #include "networkd-netdev-ipvlan.h" #include "string-table.h" static const char* const ipvlan_mode_table[_NETDEV_IPVLAN_MODE_MAX] = { [NETDEV_IPVLAN_MODE_L2] = "L2", [NETDEV_IPVLAN_MODE_L3] = "L3", }; DEFINE_STRING_TABLE_LOOKUP(ipvlan_mode, IPVlanMode); DEFINE_CONFIG_PARSE_ENUM(config_parse_ipvlan_mode, ipvlan_mode, IPVlanMode, "Failed to parse ipvlan mode"); static int netdev_ipvlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) { IPVlan *m; int r; assert(netdev); assert(link); assert(netdev->ifname); m = IPVLAN(netdev); assert(m); if (m->mode != _NETDEV_IPVLAN_MODE_INVALID) { r = sd_netlink_message_append_u16(req, IFLA_IPVLAN_MODE, m->mode); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPVLAN_MODE attribute: %m"); } return 0; } static void ipvlan_init(NetDev *n) { IPVlan *m; assert(n); m = IPVLAN(n); assert(m); m->mode = _NETDEV_IPVLAN_MODE_INVALID; } const NetDevVTable ipvlan_vtable = { .object_size = sizeof(IPVlan), .init = ipvlan_init, .sections = "Match\0NetDev\0IPVLAN\0", .fill_message_create = netdev_ipvlan_fill_message_create, .create_type = NETDEV_CREATE_STACKED, }; systemd-229/src/network/networkd-netdev-ipvlan.h000066400000000000000000000027011265713322000221210ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014-2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once typedef struct IPVlan IPVlan; #include "missing.h" #include "networkd-netdev.h" typedef enum IPVlanMode { NETDEV_IPVLAN_MODE_L2 = IPVLAN_MODE_L2, NETDEV_IPVLAN_MODE_L3 = IPVLAN_MODE_L3, _NETDEV_IPVLAN_MODE_MAX, _NETDEV_IPVLAN_MODE_INVALID = -1 } IPVlanMode; struct IPVlan { NetDev meta; IPVlanMode mode; }; extern const NetDevVTable ipvlan_vtable; const char *ipvlan_mode_to_string(IPVlanMode d) _const_; IPVlanMode ipvlan_mode_from_string(const char *d) _pure_; int config_parse_ipvlan_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); systemd-229/src/network/networkd-netdev-macvlan.c000066400000000000000000000053441265713322000222520ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "conf-parser.h" #include "networkd-netdev-macvlan.h" #include "string-table.h" static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = { [NETDEV_MACVLAN_MODE_PRIVATE] = "private", [NETDEV_MACVLAN_MODE_VEPA] = "vepa", [NETDEV_MACVLAN_MODE_BRIDGE] = "bridge", [NETDEV_MACVLAN_MODE_PASSTHRU] = "passthru", }; DEFINE_STRING_TABLE_LOOKUP(macvlan_mode, MacVlanMode); DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode, "Failed to parse macvlan mode"); static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) { MacVlan *m; int r; assert(netdev); assert(link); assert(netdev->ifname); if (netdev->kind == NETDEV_KIND_MACVLAN) m = MACVLAN(netdev); else m = MACVTAP(netdev); assert(m); if (m->mode != _NETDEV_MACVLAN_MODE_INVALID) { r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_MODE, m->mode); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_MACVLAN_MODE attribute: %m"); } return 0; } static void macvlan_init(NetDev *n) { MacVlan *m; assert(n); if (n->kind == NETDEV_KIND_MACVLAN) m = MACVLAN(n); else m = MACVTAP(n); assert(m); m->mode = _NETDEV_MACVLAN_MODE_INVALID; } const NetDevVTable macvtap_vtable = { .object_size = sizeof(MacVlan), .init = macvlan_init, .sections = "Match\0NetDev\0MACVTAP\0", .fill_message_create = netdev_macvlan_fill_message_create, .create_type = NETDEV_CREATE_STACKED, }; const NetDevVTable macvlan_vtable = { .object_size = sizeof(MacVlan), .init = macvlan_init, .sections = "Match\0NetDev\0MACVLAN\0", .fill_message_create = netdev_macvlan_fill_message_create, .create_type = NETDEV_CREATE_STACKED, }; systemd-229/src/network/networkd-netdev-macvlan.h000066400000000000000000000031511265713322000222510ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once typedef struct MacVlan MacVlan; #include "networkd-netdev.h" typedef enum MacVlanMode { NETDEV_MACVLAN_MODE_PRIVATE = MACVLAN_MODE_PRIVATE, NETDEV_MACVLAN_MODE_VEPA = MACVLAN_MODE_VEPA, NETDEV_MACVLAN_MODE_BRIDGE = MACVLAN_MODE_BRIDGE, NETDEV_MACVLAN_MODE_PASSTHRU = MACVLAN_MODE_PASSTHRU, _NETDEV_MACVLAN_MODE_MAX, _NETDEV_MACVLAN_MODE_INVALID = -1 } MacVlanMode; struct MacVlan { NetDev meta; MacVlanMode mode; }; extern const NetDevVTable macvlan_vtable; extern const NetDevVTable macvtap_vtable; const char *macvlan_mode_to_string(MacVlanMode d) _const_; MacVlanMode macvlan_mode_from_string(const char *d) _pure_; int config_parse_macvlan_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); systemd-229/src/network/networkd-netdev-tunnel.c000066400000000000000000000531241265713322000221350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-netlink.h" #include "conf-parser.h" #include "missing.h" #include "networkd-link.h" #include "networkd-netdev-tunnel.h" #include "parse-util.h" #include "string-table.h" #include "string-util.h" #include "util.h" #define DEFAULT_TNL_HOP_LIMIT 64 #define IP6_FLOWINFO_FLOWLABEL htonl(0x000FFFFF) static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = { [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6", [NETDEV_IP6_TNL_MODE_IPIP6] = "ipip6", [NETDEV_IP6_TNL_MODE_ANYIP6] = "any", }; DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode); DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode, "Failed to parse ip6 tunnel Mode"); static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { Tunnel *t = IPIP(netdev); int r; assert(netdev); assert(link); assert(m); assert(t); assert(t->family == AF_INET || t->family != -1); r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m"); return r; } static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { Tunnel *t = SIT(netdev); int r; assert(netdev); assert(link); assert(m); assert(t); assert(t->family == AF_INET || t->family != -1); r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m"); return r; } static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { Tunnel *t; int r; assert(netdev); if (netdev->kind == NETDEV_KIND_GRE) t = GRE(netdev); else t = GRETAP(netdev); assert(t); assert(t->family == AF_INET || t->family != -1); assert(link); assert(m); r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link->ifindex); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m"); r = sd_netlink_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m"); r = sd_netlink_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in); if (r < 0) log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_GRE_TOS, t->tos); if (r < 0) log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TOS attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_GRE_PMTUDISC, t->pmtudisc); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_PMTUDISC attribute: %m"); return r; } static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { Tunnel *t; int r; assert(netdev); if (netdev->kind == NETDEV_KIND_IP6GRE) t = IP6GRE(netdev); else t = IP6GRETAP(netdev); assert(t); assert(t->family == AF_INET6); assert(link); assert(m); r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link->ifindex); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m"); r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m"); r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m"); if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) { r = sd_netlink_message_append_u32(m, IFLA_GRE_FLOWINFO, t->ipv6_flowlabel); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLOWINFO attribute: %m"); } r = sd_netlink_message_append_u32(m, IFLA_GRE_FLAGS, t->flags); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLAGS attribute: %m"); return r; } static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { Tunnel *t = VTI(netdev); int r; assert(netdev); assert(link); assert(m); assert(t); assert(t->family == AF_INET); r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link->ifindex); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); r = sd_netlink_message_append_in_addr(m, IFLA_VTI_LOCAL, &t->local.in); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); r = sd_netlink_message_append_in_addr(m, IFLA_VTI_REMOTE, &t->remote.in); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); return r; } static int netdev_vti6_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { Tunnel *t = VTI6(netdev); int r; assert(netdev); assert(link); assert(m); assert(t); assert(t->family == AF_INET6); r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link->ifindex); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); r = sd_netlink_message_append_in6_addr(m, IFLA_VTI_LOCAL, &t->local.in6); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); r = sd_netlink_message_append_in6_addr(m, IFLA_VTI_REMOTE, &t->remote.in6); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); return r; } static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { Tunnel *t = IP6TNL(netdev); uint8_t proto; int r; assert(netdev); assert(link); assert(m); assert(t); assert(t->family == AF_INET6); r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m"); if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) { r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLOWINFO attribute: %m"); } if (t->copy_dscp) t->flags |= IP6_TNL_F_RCV_DSCP_COPY; if (t->encap_limit != IPV6_DEFAULT_TNL_ENCAP_LIMIT) { r = sd_netlink_message_append_u8(m, IFLA_IPTUN_ENCAP_LIMIT, t->encap_limit); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_LIMIT attribute: %m"); } r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m"); switch (t->ip6tnl_mode) { case NETDEV_IP6_TNL_MODE_IP6IP6: proto = IPPROTO_IPV6; break; case NETDEV_IP6_TNL_MODE_IPIP6: proto = IPPROTO_IPIP; break; case NETDEV_IP6_TNL_MODE_ANYIP6: default: proto = 0; break; } r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_MODE attribute: %m"); return r; } static int netdev_tunnel_verify(NetDev *netdev, const char *filename) { Tunnel *t = NULL; assert(netdev); assert(filename); switch (netdev->kind) { case NETDEV_KIND_IPIP: t = IPIP(netdev); break; case NETDEV_KIND_SIT: t = SIT(netdev); break; case NETDEV_KIND_GRE: t = GRE(netdev); break; case NETDEV_KIND_GRETAP: t = GRETAP(netdev); break; case NETDEV_KIND_IP6GRE: t = IP6GRE(netdev); break; case NETDEV_KIND_IP6GRETAP: t = IP6GRETAP(netdev); break; case NETDEV_KIND_VTI: t = VTI(netdev); break; case NETDEV_KIND_VTI6: t = VTI6(netdev); break; case NETDEV_KIND_IP6TNL: t = IP6TNL(netdev); break; default: assert_not_reached("Invalid tunnel kind"); } assert(t); if (t->family != AF_INET && t->family != AF_INET6 && t->family != 0) { log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename); return -EINVAL; } if (netdev->kind == NETDEV_KIND_IP6TNL) { if (t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID) { log_warning("IP6 Tunnel without mode configured in %s. Ignoring", filename); return -EINVAL; } } return 0; } int config_parse_tunnel_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Tunnel *t = userdata; union in_addr_union *addr = data, buffer; int r, f; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (streq(rvalue, "any")) { t->family = 0; return 0; } else { r = in_addr_from_string_auto(rvalue, &f, &buffer); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Tunnel address is invalid, ignoring assignment: %s", rvalue); return 0; } if (t->family != AF_UNSPEC && t->family != f) { log_syntax(unit, LOG_ERR, filename, line, 0, "Tunnel addresses incompatible, ignoring assignment: %s", rvalue); return 0; } } t->family = f; *addr = buffer; return 0; } int config_parse_ipv6_flowlabel(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { IPv6FlowLabel *ipv6_flowlabel = data; Tunnel *t = userdata; int k = 0; int r; assert(filename); assert(lvalue); assert(rvalue); assert(ipv6_flowlabel); if (streq(rvalue, "inherit")) { *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL; t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL; } else { r = config_parse_int(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata); if (r < 0) return r; if (k > 0xFFFFF) log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue); else { *ipv6_flowlabel = htonl(k) & IP6_FLOWINFO_FLOWLABEL; t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL; } } return 0; } int config_parse_encap_limit(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Tunnel *t = userdata; int k = 0; int r; assert(filename); assert(lvalue); assert(rvalue); if (streq(rvalue, "none")) t->flags |= IP6_TNL_F_IGN_ENCAP_LIMIT; else { r = safe_atoi(rvalue, &k); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Tunnel Encapsulation Limit option, ignoring: %s", rvalue); return 0; } if (k > 255 || k < 0) log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid Tunnel Encapsulation value, ignoring: %d", k); else { t->encap_limit = k; t->flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT; } } return 0; } static void ipip_init(NetDev *n) { Tunnel *t = IPIP(n); assert(n); assert(t); t->pmtudisc = true; t->family = -1; } static void sit_init(NetDev *n) { Tunnel *t = SIT(n); assert(n); assert(t); t->pmtudisc = true; t->family = -1; } static void vti_init(NetDev *n) { Tunnel *t; assert(n); if (n->kind == NETDEV_KIND_VTI) t = VTI(n); else t = VTI6(n); assert(t); t->pmtudisc = true; } static void gre_init(NetDev *n) { Tunnel *t; assert(n); if (n->kind == NETDEV_KIND_GRE) t = GRE(n); else t = GRETAP(n); assert(t); t->pmtudisc = true; t->family = -1; } static void ip6gre_init(NetDev *n) { Tunnel *t; assert(n); if (n->kind == NETDEV_KIND_IP6GRE) t = IP6GRE(n); else t = IP6GRETAP(n); assert(t); t->ttl = DEFAULT_TNL_HOP_LIMIT; } static void ip6tnl_init(NetDev *n) { Tunnel *t = IP6TNL(n); assert(n); assert(t); t->ttl = DEFAULT_TNL_HOP_LIMIT; t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT; t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID; t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID; } const NetDevVTable ipip_vtable = { .object_size = sizeof(Tunnel), .init = ipip_init, .sections = "Match\0NetDev\0Tunnel\0", .fill_message_create = netdev_ipip_fill_message_create, .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_tunnel_verify, }; const NetDevVTable sit_vtable = { .object_size = sizeof(Tunnel), .init = sit_init, .sections = "Match\0NetDev\0Tunnel\0", .fill_message_create = netdev_sit_fill_message_create, .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_tunnel_verify, }; const NetDevVTable vti_vtable = { .object_size = sizeof(Tunnel), .init = vti_init, .sections = "Match\0NetDev\0Tunnel\0", .fill_message_create = netdev_vti_fill_message_create, .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_tunnel_verify, }; const NetDevVTable vti6_vtable = { .object_size = sizeof(Tunnel), .init = vti_init, .sections = "Match\0NetDev\0Tunnel\0", .fill_message_create = netdev_vti6_fill_message_create, .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_tunnel_verify, }; const NetDevVTable gre_vtable = { .object_size = sizeof(Tunnel), .init = gre_init, .sections = "Match\0NetDev\0Tunnel\0", .fill_message_create = netdev_gre_fill_message_create, .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_tunnel_verify, }; const NetDevVTable gretap_vtable = { .object_size = sizeof(Tunnel), .init = gre_init, .sections = "Match\0NetDev\0Tunnel\0", .fill_message_create = netdev_gre_fill_message_create, .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_tunnel_verify, }; const NetDevVTable ip6gre_vtable = { .object_size = sizeof(Tunnel), .init = ip6gre_init, .sections = "Match\0NetDev\0Tunnel\0", .fill_message_create = netdev_ip6gre_fill_message_create, .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_tunnel_verify, }; const NetDevVTable ip6gretap_vtable = { .object_size = sizeof(Tunnel), .init = ip6gre_init, .sections = "Match\0NetDev\0Tunnel\0", .fill_message_create = netdev_ip6gre_fill_message_create, .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_tunnel_verify, }; const NetDevVTable ip6tnl_vtable = { .object_size = sizeof(Tunnel), .init = ip6tnl_init, .sections = "Match\0NetDev\0Tunnel\0", .fill_message_create = netdev_ip6tnl_fill_message_create, .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_tunnel_verify, }; systemd-229/src/network/networkd-netdev-tunnel.h000066400000000000000000000066741265713322000221520ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once typedef struct Tunnel Tunnel; #include "networkd-netdev.h" typedef enum Ip6TnlMode { NETDEV_IP6_TNL_MODE_IP6IP6, NETDEV_IP6_TNL_MODE_IPIP6, NETDEV_IP6_TNL_MODE_ANYIP6, _NETDEV_IP6_TNL_MODE_MAX, _NETDEV_IP6_TNL_MODE_INVALID = -1, } Ip6TnlMode; typedef enum IPv6FlowLabel { NETDEV_IPV6_FLOWLABEL_INHERIT = 0xFFFFF + 1, _NETDEV_IPV6_FLOWLABEL_MAX, _NETDEV_IPV6_FLOWLABEL_INVALID = -1, } IPv6FlowLabel; struct Tunnel { NetDev meta; uint8_t encap_limit; int family; int ipv6_flowlabel; unsigned ttl; unsigned tos; unsigned flags; union in_addr_union local; union in_addr_union remote; Ip6TnlMode ip6tnl_mode; bool pmtudisc; bool copy_dscp; }; extern const NetDevVTable ipip_vtable; extern const NetDevVTable sit_vtable; extern const NetDevVTable vti_vtable; extern const NetDevVTable vti6_vtable; extern const NetDevVTable gre_vtable; extern const NetDevVTable gretap_vtable; extern const NetDevVTable ip6gre_vtable; extern const NetDevVTable ip6gretap_vtable; extern const NetDevVTable ip6tnl_vtable; const char *ip6tnl_mode_to_string(Ip6TnlMode d) _const_; Ip6TnlMode ip6tnl_mode_from_string(const char *d) _pure_; int config_parse_ip6tnl_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_tunnel_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_ipv6_flowlabel(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_encap_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); systemd-229/src/network/networkd-netdev-tuntap.c000066400000000000000000000120141265713322000221340ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "networkd-netdev-tuntap.h" #include "user-util.h" #define TUN_DEV "/dev/net/tun" static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) { TunTap *t; assert(netdev); assert(netdev->ifname); assert(ifr); if (netdev->kind == NETDEV_KIND_TAP) { t = TAP(netdev); ifr->ifr_flags |= IFF_TAP; } else { t = TUN(netdev); ifr->ifr_flags |= IFF_TUN; } if (!t->packet_info) ifr->ifr_flags |= IFF_NO_PI; if (t->one_queue) ifr->ifr_flags |= IFF_ONE_QUEUE; if (t->multi_queue) ifr->ifr_flags |= IFF_MULTI_QUEUE; if (t->vnet_hdr) ifr->ifr_flags |= IFF_VNET_HDR; strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1); return 0; } static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) { _cleanup_close_ int fd; TunTap *t = NULL; const char *user; const char *group; uid_t uid; gid_t gid; int r; assert(netdev); assert(ifr); fd = open(TUN_DEV, O_RDWR); if (fd < 0) return log_netdev_error_errno(netdev, -errno, "Failed to open tun dev: %m"); r = ioctl(fd, TUNSETIFF, ifr); if (r < 0) return log_netdev_error_errno(netdev, -errno, "TUNSETIFF failed on tun dev: %m"); if (netdev->kind == NETDEV_KIND_TAP) t = TAP(netdev); else t = TUN(netdev); assert(t); if(t->user_name) { user = t->user_name; r = get_user_creds(&user, &uid, NULL, NULL, NULL); if (r < 0) return log_netdev_error_errno(netdev, r, "Cannot resolve user name %s: %m", t->user_name); r = ioctl(fd, TUNSETOWNER, uid); if (r < 0) return log_netdev_error_errno(netdev, -errno, "TUNSETOWNER failed on tun dev: %m"); } if (t->group_name) { group = t->group_name; r = get_group_creds(&group, &gid); if (r < 0) return log_netdev_error_errno(netdev, r, "Cannot resolve group name %s: %m", t->group_name); r = ioctl(fd, TUNSETGROUP, gid); if (r < 0) return log_netdev_error_errno(netdev, -errno, "TUNSETGROUP failed on tun dev: %m"); } r = ioctl(fd, TUNSETPERSIST, 1); if (r < 0) return log_netdev_error_errno(netdev, -errno, "TUNSETPERSIST failed on tun dev: %m"); return 0; } static int netdev_create_tuntap(NetDev *netdev) { struct ifreq ifr = {}; int r; r = netdev_fill_tuntap_message(netdev, &ifr); if(r < 0) return r; return netdev_tuntap_add(netdev, &ifr); } static void tuntap_done(NetDev *netdev) { TunTap *t = NULL; assert(netdev); if (netdev->kind == NETDEV_KIND_TUN) t = TUN(netdev); else t = TAP(netdev); assert(t); t->user_name = mfree(t->user_name); t->group_name = mfree(t->group_name); } static int tuntap_verify(NetDev *netdev, const char *filename) { assert(netdev); if (netdev->mtu) log_netdev_warning(netdev, "MTU configured for %s, ignoring", netdev_kind_to_string(netdev->kind)); if (netdev->mac) log_netdev_warning(netdev, "MAC configured for %s, ignoring", netdev_kind_to_string(netdev->kind)); return 0; } const NetDevVTable tun_vtable = { .object_size = sizeof(TunTap), .sections = "Match\0NetDev\0Tun\0", .config_verify = tuntap_verify, .done = tuntap_done, .create = netdev_create_tuntap, .create_type = NETDEV_CREATE_INDEPENDENT, }; const NetDevVTable tap_vtable = { .object_size = sizeof(TunTap), .sections = "Match\0NetDev\0Tap\0", .config_verify = tuntap_verify, .done = tuntap_done, .create = netdev_create_tuntap, .create_type = NETDEV_CREATE_INDEPENDENT, }; systemd-229/src/network/networkd-netdev-tuntap.h000066400000000000000000000020571265713322000221470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once typedef struct TunTap TunTap; #include "networkd-netdev.h" struct TunTap { NetDev meta; char *user_name; char *group_name; bool one_queue; bool multi_queue; bool packet_info; bool vnet_hdr; }; extern const NetDevVTable tun_vtable; extern const NetDevVTable tap_vtable; systemd-229/src/network/networkd-netdev-veth.c000066400000000000000000000062731265713322000216010ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-netlink.h" #include "networkd-netdev-veth.h" static int netdev_veth_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { Veth *v; int r; assert(netdev); assert(!link); assert(m); v = VETH(netdev); assert(v); r = sd_netlink_message_open_container(m, VETH_INFO_PEER); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append VETH_INFO_PEER attribute: %m"); if (v->ifname_peer) { r = sd_netlink_message_append_string(m, IFLA_IFNAME, v->ifname_peer); if (r < 0) return log_error_errno(r, "Failed to add netlink interface name: %m"); } if (v->mac_peer) { r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, v->mac_peer); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m"); } r = sd_netlink_message_close_container(m); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); return r; } static int netdev_veth_verify(NetDev *netdev, const char *filename) { Veth *v; int r; assert(netdev); assert(filename); v = VETH(netdev); assert(v); if (!v->ifname_peer) { log_warning("Veth NetDev without peer name configured in %s. Ignoring", filename); return -EINVAL; } if (!v->mac_peer) { r = netdev_get_mac(v->ifname_peer, &v->mac_peer); if (r < 0) { log_warning("Failed to generate predictable MAC address for %s. Ignoring", v->ifname_peer); return -EINVAL; } } return 0; } static void veth_done(NetDev *n) { Veth *v; assert(n); v = VETH(n); assert(v); free(v->ifname_peer); free(v->mac_peer); } const NetDevVTable veth_vtable = { .object_size = sizeof(Veth), .sections = "Match\0NetDev\0Peer\0", .done = veth_done, .fill_message_create = netdev_veth_fill_message_create, .create_type = NETDEV_CREATE_INDEPENDENT, .config_verify = netdev_veth_verify, }; systemd-229/src/network/networkd-netdev-veth.h000066400000000000000000000016561265713322000216060ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once typedef struct Veth Veth; #include "networkd-netdev.h" struct Veth { NetDev meta; char *ifname_peer; struct ether_addr *mac_peer; }; extern const NetDevVTable veth_vtable; systemd-229/src/network/networkd-netdev-vlan.c000066400000000000000000000041621265713322000215660ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "networkd-netdev-vlan.h" static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) { VLan *v; int r; assert(netdev); assert(link); assert(req); v = VLAN(netdev); assert(v); if (v->id <= VLANID_MAX) { r = sd_netlink_message_append_u16(req, IFLA_VLAN_ID, v->id); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VLAN_ID attribute: %m"); } return 0; } static int netdev_vlan_verify(NetDev *netdev, const char *filename) { VLan *v; assert(netdev); assert(filename); v = VLAN(netdev); assert(v); if (v->id > VLANID_MAX) { log_warning("VLAN without valid Id (%"PRIu64") configured in %s. Ignoring", v->id, filename); return -EINVAL; } return 0; } static void vlan_init(NetDev *netdev) { VLan *v = VLAN(netdev); assert(netdev); assert(v); v->id = VLANID_MAX + 1; } const NetDevVTable vlan_vtable = { .object_size = sizeof(VLan), .init = vlan_init, .sections = "Match\0NetDev\0VLAN\0", .fill_message_create = netdev_vlan_fill_message_create, .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_vlan_verify, }; systemd-229/src/network/networkd-netdev-vlan.h000066400000000000000000000016341265713322000215740ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once typedef struct VLan VLan; #include "networkd-netdev.h" #define VLANID_MAX 4094 struct VLan { NetDev meta; uint64_t id; }; extern const NetDevVTable vlan_vtable; systemd-229/src/network/networkd-netdev-vxlan.c000066400000000000000000000246531265713322000217650ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-netlink.h" #include "conf-parser.h" #include "alloc-util.h" #include "parse-util.h" #include "missing.h" #include "networkd-link.h" #include "networkd-netdev-vxlan.h" static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { VxLan *v; int r; assert(netdev); assert(link); assert(m); v = VXLAN(netdev); assert(v); if (v->id <= VXLAN_VID_MAX) { r = sd_netlink_message_append_u32(m, IFLA_VXLAN_ID, v->id); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_ID attribute: %m"); } r = sd_netlink_message_append_in_addr(m, IFLA_VXLAN_GROUP, &v->group.in); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_GROUP attribute: %m"); r = sd_netlink_message_append_u32(m, IFLA_VXLAN_LINK, link->ifindex); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LINK attribute: %m"); if(v->ttl) { r = sd_netlink_message_append_u8(m, IFLA_VXLAN_TTL, v->ttl); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TTL attribute: %m"); } if(v->tos) { r = sd_netlink_message_append_u8(m, IFLA_VXLAN_TOS, v->tos); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TOS attribute: %m"); } r = sd_netlink_message_append_u8(m, IFLA_VXLAN_LEARNING, v->learning); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LEARNING attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_VXLAN_RSC, v->route_short_circuit); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_RSC attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_VXLAN_PROXY, v->arp_proxy); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PROXY attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_VXLAN_L2MISS, v->l2miss); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_L2MISS attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_VXLAN_L3MISS, v->l3miss); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_L3MISS attribute: %m"); if(v->fdb_ageing) { r = sd_netlink_message_append_u32(m, IFLA_VXLAN_AGEING, v->fdb_ageing / USEC_PER_SEC); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_AGEING attribute: %m"); } if (v->max_fdb) { r = sd_netlink_message_append_u32(m, IFLA_VXLAN_LIMIT, v->max_fdb); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LIMIT attribute: %m"); } r = sd_netlink_message_append_u8(m, IFLA_VXLAN_UDP_CSUM, v->udpcsum); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_CSUM attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, v->udp6zerocsumtx); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_TX attribute: %m"); r = sd_netlink_message_append_u8(m, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, v->udp6zerocsumrx); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX attribute: %m"); r = sd_netlink_message_append_u16(m, IFLA_VXLAN_PORT, htobe16(v->dest_port)); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PORT attribute: %m"); if (v->port_range.low || v->port_range.high) { struct ifla_vxlan_port_range port_range; port_range.low = htobe16(v->port_range.low); port_range.high = htobe16(v->port_range.high); r = sd_netlink_message_append_data(m, IFLA_VXLAN_PORT_RANGE, &port_range, sizeof(port_range)); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PORT_RANGE attribute: %m"); } if (v->group_policy) { r = sd_netlink_message_append_flag(m, IFLA_VXLAN_GBP); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_GBP attribute: %m"); } return r; } int config_parse_vxlan_group_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { VxLan *v = userdata; union in_addr_union *addr = data, buffer; int r, f; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = in_addr_from_string_auto(rvalue, &f, &buffer); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "vxlan multicast group address is invalid, ignoring assignment: %s", rvalue); return 0; } if (v->family != AF_UNSPEC && v->family != f) { log_syntax(unit, LOG_ERR, filename, line, 0, "vxlan multicast group incompatible, ignoring assignment: %s", rvalue); return 0; } v->family = f; *addr = buffer; return 0; } int config_parse_port_range(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { _cleanup_free_ char *word = NULL; VxLan *v = userdata; unsigned low, high; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = extract_first_word(&rvalue, &word, NULL, 0); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract VXLAN port range, ignoring: %s", rvalue); return 0; } if (r == 0) return 0; r = parse_range(word, &low, &high); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN port range '%s'", word); return 0; } if (low <= 0 || low > 65535 || high <= 0 || high > 65535) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN port range '%s'. Port should be greater than 0 and less than 65535.", word); return 0; } if (high < low) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN port range '%s'. Port range %u .. %u not valid", word, low, high); return 0; } v->port_range.low = low; v->port_range.high = high; return 0; } int config_parse_destination_port(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { VxLan *v = userdata; uint16_t port; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = safe_atou16(rvalue, &port); if (r < 0 || port <= 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN destination port '%s'.", rvalue); return 0; } v->dest_port = port; return 0; } static int netdev_vxlan_verify(NetDev *netdev, const char *filename) { VxLan *v = VXLAN(netdev); assert(netdev); assert(v); assert(filename); if (v->id > VXLAN_VID_MAX) { log_warning("VXLAN without valid Id configured in %s. Ignoring", filename); return -EINVAL; } return 0; } static void vxlan_init(NetDev *netdev) { VxLan *v; assert(netdev); v = VXLAN(netdev); assert(v); v->id = VXLAN_VID_MAX + 1; v->learning = true; v->udpcsum = false; v->udp6zerocsumtx = false; v->udp6zerocsumrx = false; } const NetDevVTable vxlan_vtable = { .object_size = sizeof(VxLan), .init = vxlan_init, .sections = "Match\0NetDev\0VXLAN\0", .fill_message_create = netdev_vxlan_fill_message_create, .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_vxlan_verify, }; systemd-229/src/network/networkd-netdev-vxlan.h000066400000000000000000000056211265713322000217640ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once typedef struct VxLan VxLan; #include "in-addr-util.h" #include "networkd-netdev.h" #define VXLAN_VID_MAX (1u << 24) - 1 struct VxLan { NetDev meta; uint64_t id; int family; union in_addr_union group; unsigned tos; unsigned ttl; unsigned max_fdb; uint16_t dest_port; usec_t fdb_ageing; bool learning; bool arp_proxy; bool route_short_circuit; bool l2miss; bool l3miss; bool udpcsum; bool udp6zerocsumtx; bool udp6zerocsumrx; bool group_policy; struct ifla_vxlan_port_range port_range; }; extern const NetDevVTable vxlan_vtable; int config_parse_vxlan_group_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_port_range(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_destination_port(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); systemd-229/src/network/networkd-netdev.c000066400000000000000000000565231265713322000206400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "conf-files.h" #include "conf-parser.h" #include "fd-util.h" #include "list.h" #include "netlink-util.h" #include "network-internal.h" #include "networkd-netdev.h" #include "networkd.h" #include "siphash24.h" #include "stat-util.h" #include "string-table.h" #include "string-util.h" const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = { [NETDEV_KIND_BRIDGE] = &bridge_vtable, [NETDEV_KIND_BOND] = &bond_vtable, [NETDEV_KIND_VLAN] = &vlan_vtable, [NETDEV_KIND_MACVLAN] = &macvlan_vtable, [NETDEV_KIND_MACVTAP] = &macvtap_vtable, [NETDEV_KIND_IPVLAN] = &ipvlan_vtable, [NETDEV_KIND_VXLAN] = &vxlan_vtable, [NETDEV_KIND_IPIP] = &ipip_vtable, [NETDEV_KIND_GRE] = &gre_vtable, [NETDEV_KIND_GRETAP] = &gretap_vtable, [NETDEV_KIND_IP6GRE] = &ip6gre_vtable, [NETDEV_KIND_IP6GRETAP] = &ip6gretap_vtable, [NETDEV_KIND_SIT] = &sit_vtable, [NETDEV_KIND_VTI] = &vti_vtable, [NETDEV_KIND_VTI6] = &vti6_vtable, [NETDEV_KIND_VETH] = &veth_vtable, [NETDEV_KIND_DUMMY] = &dummy_vtable, [NETDEV_KIND_TUN] = &tun_vtable, [NETDEV_KIND_TAP] = &tap_vtable, [NETDEV_KIND_IP6TNL] = &ip6tnl_vtable, }; static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = { [NETDEV_KIND_BRIDGE] = "bridge", [NETDEV_KIND_BOND] = "bond", [NETDEV_KIND_VLAN] = "vlan", [NETDEV_KIND_MACVLAN] = "macvlan", [NETDEV_KIND_MACVTAP] = "macvtap", [NETDEV_KIND_IPVLAN] = "ipvlan", [NETDEV_KIND_VXLAN] = "vxlan", [NETDEV_KIND_IPIP] = "ipip", [NETDEV_KIND_GRE] = "gre", [NETDEV_KIND_GRETAP] = "gretap", [NETDEV_KIND_IP6GRE] = "ip6gre", [NETDEV_KIND_IP6GRETAP] = "ip6gretap", [NETDEV_KIND_SIT] = "sit", [NETDEV_KIND_VETH] = "veth", [NETDEV_KIND_VTI] = "vti", [NETDEV_KIND_VTI6] = "vti6", [NETDEV_KIND_DUMMY] = "dummy", [NETDEV_KIND_TUN] = "tun", [NETDEV_KIND_TAP] = "tap", [NETDEV_KIND_IP6TNL] = "ip6tnl", }; DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind); DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Failed to parse netdev kind"); static void netdev_cancel_callbacks(NetDev *netdev) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; netdev_join_callback *callback; if (!netdev) return; rtnl_message_new_synthetic_error(-ENODEV, 0, &m); while ((callback = netdev->callbacks)) { if (m) { assert(callback->link); assert(callback->callback); assert(netdev->manager); assert(netdev->manager->rtnl); callback->callback(netdev->manager->rtnl, m, callback->link); } LIST_REMOVE(callbacks, netdev->callbacks, callback); link_unref(callback->link); free(callback); } } static void netdev_free(NetDev *netdev) { if (!netdev) return; netdev_cancel_callbacks(netdev); if (netdev->ifname) hashmap_remove(netdev->manager->netdevs, netdev->ifname); free(netdev->filename); free(netdev->description); free(netdev->ifname); free(netdev->mac); condition_free_list(netdev->match_host); condition_free_list(netdev->match_virt); condition_free_list(netdev->match_kernel); condition_free_list(netdev->match_arch); if (NETDEV_VTABLE(netdev) && NETDEV_VTABLE(netdev)->done) NETDEV_VTABLE(netdev)->done(netdev); free(netdev); } NetDev *netdev_unref(NetDev *netdev) { if (netdev && (-- netdev->n_ref <= 0)) netdev_free(netdev); return NULL; } NetDev *netdev_ref(NetDev *netdev) { if (netdev) assert_se(++ netdev->n_ref >= 2); return netdev; } void netdev_drop(NetDev *netdev) { if (!netdev || netdev->state == NETDEV_STATE_LINGER) return; netdev->state = NETDEV_STATE_LINGER; log_netdev_debug(netdev, "netdev removed"); netdev_cancel_callbacks(netdev); netdev_unref(netdev); return; } int netdev_get(Manager *manager, const char *name, NetDev **ret) { NetDev *netdev; assert(manager); assert(name); assert(ret); netdev = hashmap_get(manager->netdevs, name); if (!netdev) { *ret = NULL; return -ENOENT; } *ret = netdev; return 0; } static int netdev_enter_failed(NetDev *netdev) { netdev->state = NETDEV_STATE_FAILED; netdev_cancel_callbacks(netdev); return 0; } static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_netlink_message_handler_t callback) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(netdev); assert(netdev->state == NETDEV_STATE_READY); assert(netdev->manager); assert(netdev->manager->rtnl); assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND)); assert(link); assert(callback); r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_SETLINK, link->ifindex); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not allocate RTM_SETLINK message: %m"); r = sd_netlink_message_append_u32(req, IFLA_MASTER, netdev->ifindex); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_MASTER attribute: %m"); r = sd_netlink_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL); if (r < 0) return log_netdev_error(netdev, "Could not send rtnetlink message: %m"); link_ref(link); log_netdev_debug(netdev, "Enslaving link '%s'", link->ifname); return 0; } static int netdev_enter_ready(NetDev *netdev) { netdev_join_callback *callback, *callback_next; int r; assert(netdev); assert(netdev->ifname); if (netdev->state != NETDEV_STATE_CREATING) return 0; netdev->state = NETDEV_STATE_READY; log_netdev_info(netdev, "netdev ready"); LIST_FOREACH_SAFE(callbacks, callback, callback_next, netdev->callbacks) { /* enslave the links that were attempted to be enslaved before the * link was ready */ r = netdev_enslave_ready(netdev, callback->link, callback->callback); if (r < 0) return r; LIST_REMOVE(callbacks, netdev->callbacks, callback); link_unref(callback->link); free(callback); } if (NETDEV_VTABLE(netdev)->post_create) NETDEV_VTABLE(netdev)->post_create(netdev, NULL, NULL); return 0; } /* callback for netdev's created without a backing Link */ static int netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_netdev_unref_ NetDev *netdev = userdata; int r; assert(netdev->state != _NETDEV_STATE_INVALID); r = sd_netlink_message_get_errno(m); if (r == -EEXIST) log_netdev_info(netdev, "netdev exists, using existing without changing its parameters"); else if (r < 0) { log_netdev_warning_errno(netdev, r, "netdev could not be created: %m"); netdev_drop(netdev); return 1; } log_netdev_debug(netdev, "Created"); return 1; } int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t callback) { int r; assert(netdev); assert(netdev->manager); assert(netdev->manager->rtnl); assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND)); if (netdev->state == NETDEV_STATE_READY) { r = netdev_enslave_ready(netdev, link, callback); if (r < 0) return r; } else if (IN_SET(netdev->state, NETDEV_STATE_LINGER, NETDEV_STATE_FAILED)) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; r = rtnl_message_new_synthetic_error(-ENODEV, 0, &m); if (r >= 0) callback(netdev->manager->rtnl, m, link); } else { /* the netdev is not yet read, save this request for when it is */ netdev_join_callback *cb; cb = new0(netdev_join_callback, 1); if (!cb) return log_oom(); cb->callback = callback; cb->link = link; link_ref(link); LIST_PREPEND(callbacks, netdev->callbacks, cb); log_netdev_debug(netdev, "Will enslave '%s', when ready", link->ifname); } return 0; } int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) { uint16_t type; const char *kind; const char *received_kind; const char *received_name; int r, ifindex; assert(netdev); assert(message); r = sd_netlink_message_get_type(message, &type); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not get rtnl message type: %m"); if (type != RTM_NEWLINK) { log_netdev_error(netdev, "Cannot set ifindex from unexpected rtnl message type."); return -EINVAL; } r = sd_rtnl_message_link_get_ifindex(message, &ifindex); if (r < 0) { log_netdev_error_errno(netdev, r, "Could not get ifindex: %m"); netdev_enter_failed(netdev); return r; } else if (ifindex <= 0) { log_netdev_error(netdev, "Got invalid ifindex: %d", ifindex); netdev_enter_failed(netdev); return -EINVAL; } if (netdev->ifindex > 0) { if (netdev->ifindex != ifindex) { log_netdev_error(netdev, "Could not set ifindex to %d, already set to %d", ifindex, netdev->ifindex); netdev_enter_failed(netdev); return -EEXIST; } else /* ifindex already set to the same for this netdev */ return 0; } r = sd_netlink_message_read_string(message, IFLA_IFNAME, &received_name); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not get IFNAME: %m"); if (!streq(netdev->ifname, received_name)) { log_netdev_error(netdev, "Received newlink with wrong IFNAME %s", received_name); netdev_enter_failed(netdev); return r; } r = sd_netlink_message_enter_container(message, IFLA_LINKINFO); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not get LINKINFO: %m"); r = sd_netlink_message_read_string(message, IFLA_INFO_KIND, &received_kind); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not get KIND: %m"); r = sd_netlink_message_exit_container(message); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not exit container: %m"); if (netdev->kind == NETDEV_KIND_TAP) /* the kernel does not distinguish between tun and tap */ kind = "tun"; else { kind = netdev_kind_to_string(netdev->kind); if (!kind) { log_netdev_error(netdev, "Could not get kind"); netdev_enter_failed(netdev); return -EINVAL; } } if (!streq(kind, received_kind)) { log_netdev_error(netdev, "Received newlink with wrong KIND %s, " "expected %s", received_kind, kind); netdev_enter_failed(netdev); return r; } netdev->ifindex = ifindex; log_netdev_debug(netdev, "netdev has index %d", netdev->ifindex); netdev_enter_ready(netdev); return 0; } #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48) int netdev_get_mac(const char *ifname, struct ether_addr **ret) { _cleanup_free_ struct ether_addr *mac = NULL; uint64_t result; size_t l, sz; uint8_t *v; int r; assert(ifname); assert(ret); mac = new0(struct ether_addr, 1); if (!mac) return -ENOMEM; l = strlen(ifname); sz = sizeof(sd_id128_t) + l; v = alloca(sz); /* fetch some persistent data unique to the machine */ r = sd_id128_get_machine((sd_id128_t*) v); if (r < 0) return r; /* combine with some data unique (on this machine) to this * netdev */ memcpy(v + sizeof(sd_id128_t), ifname, l); /* Let's hash the host machine ID plus the container name. We * use a fixed, but originally randomly created hash key here. */ result = siphash24(v, sz, HASH_KEY.bytes); assert_cc(ETH_ALEN <= sizeof(result)); memcpy(mac->ether_addr_octet, &result, ETH_ALEN); /* see eth_random_addr in the kernel */ mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */ mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */ *ret = mac; mac = NULL; return 0; } static int netdev_create(NetDev *netdev, Link *link, sd_netlink_message_handler_t callback) { int r; assert(netdev); assert(!link || callback); /* create netdev */ if (NETDEV_VTABLE(netdev)->create) { assert(!link); r = NETDEV_VTABLE(netdev)->create(netdev); if (r < 0) return r; log_netdev_debug(netdev, "Created"); } else { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not allocate RTM_NEWLINK message: %m"); r = sd_netlink_message_append_string(m, IFLA_IFNAME, netdev->ifname); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_IFNAME, attribute: %m"); if (netdev->mac) { r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m"); } if (netdev->mtu) { r = sd_netlink_message_append_u32(m, IFLA_MTU, netdev->mtu); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_MTU attribute: %m"); } if (link) { r = sd_netlink_message_append_u32(m, IFLA_LINK, link->ifindex); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINK attribute: %m"); } r = sd_netlink_message_open_container(m, IFLA_LINKINFO); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind)); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); if (NETDEV_VTABLE(netdev)->fill_message_create) { r = NETDEV_VTABLE(netdev)->fill_message_create(netdev, link, m); if (r < 0) return r; } r = sd_netlink_message_close_container(m); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); r = sd_netlink_message_close_container(m); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); if (link) { r = sd_netlink_call_async(netdev->manager->rtnl, m, callback, link, 0, NULL); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); link_ref(link); } else { r = sd_netlink_call_async(netdev->manager->rtnl, m, netdev_create_handler, netdev, 0, NULL); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); netdev_ref(netdev); } netdev->state = NETDEV_STATE_CREATING; log_netdev_debug(netdev, "Creating"); } return 0; } /* the callback must be called, possibly after a timeout, as otherwise the Link will hang */ int netdev_join(NetDev *netdev, Link *link, sd_netlink_message_handler_t callback) { int r; assert(netdev); assert(netdev->manager); assert(netdev->manager->rtnl); assert(NETDEV_VTABLE(netdev)); switch (NETDEV_VTABLE(netdev)->create_type) { case NETDEV_CREATE_MASTER: r = netdev_enslave(netdev, link, callback); if (r < 0) return r; break; case NETDEV_CREATE_STACKED: r = netdev_create(netdev, link, callback); if (r < 0) return r; break; default: assert_not_reached("Can not join independent netdev"); } return 0; } static int netdev_load_one(Manager *manager, const char *filename) { _cleanup_netdev_unref_ NetDev *netdev = NULL; _cleanup_free_ NetDev *netdev_raw = NULL; _cleanup_fclose_ FILE *file = NULL; int r; assert(manager); assert(filename); file = fopen(filename, "re"); if (!file) { if (errno == ENOENT) return 0; else return -errno; } if (null_or_empty_fd(fileno(file))) { log_debug("Skipping empty file: %s", filename); return 0; } netdev_raw = new0(NetDev, 1); if (!netdev_raw) return log_oom(); netdev_raw->kind = _NETDEV_KIND_INVALID; r = config_parse(NULL, filename, file, "Match\0NetDev\0", config_item_perf_lookup, network_netdev_gperf_lookup, true, false, true, netdev_raw); if (r < 0) return r; r = fseek(file, 0, SEEK_SET); if (r < 0) return -errno; /* skip out early if configuration does not match the environment */ if (net_match_config(NULL, NULL, NULL, NULL, NULL, netdev_raw->match_host, netdev_raw->match_virt, netdev_raw->match_kernel, netdev_raw->match_arch, NULL, NULL, NULL, NULL, NULL, NULL) <= 0) return 0; if (!NETDEV_VTABLE(netdev_raw)) { log_warning("NetDev with invalid Kind configured in %s. Ignoring", filename); return 0; } if (!netdev_raw->ifname) { log_warning("NetDev without Name configured in %s. Ignoring", filename); return 0; } netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size); if (!netdev) return log_oom(); netdev->n_ref = 1; netdev->manager = manager; netdev->state = _NETDEV_STATE_INVALID; netdev->kind = netdev_raw->kind; netdev->ifname = netdev_raw->ifname; if (NETDEV_VTABLE(netdev)->init) NETDEV_VTABLE(netdev)->init(netdev); r = config_parse(NULL, filename, file, NETDEV_VTABLE(netdev)->sections, config_item_perf_lookup, network_netdev_gperf_lookup, false, false, false, netdev); if (r < 0) return r; /* verify configuration */ if (NETDEV_VTABLE(netdev)->config_verify) { r = NETDEV_VTABLE(netdev)->config_verify(netdev, filename); if (r < 0) return 0; } netdev->filename = strdup(filename); if (!netdev->filename) return log_oom(); if (!netdev->mac) { r = netdev_get_mac(netdev->ifname, &netdev->mac); if (r < 0) return log_error_errno(r, "Failed to generate predictable MAC address for %s: %m", netdev->ifname); } r = hashmap_put(netdev->manager->netdevs, netdev->ifname, netdev); if (r < 0) return r; LIST_HEAD_INIT(netdev->callbacks); log_netdev_debug(netdev, "loaded %s", netdev_kind_to_string(netdev->kind)); switch (NETDEV_VTABLE(netdev)->create_type) { case NETDEV_CREATE_MASTER: case NETDEV_CREATE_INDEPENDENT: r = netdev_create(netdev, NULL, NULL); if (r < 0) return 0; break; default: break; } netdev = NULL; return 0; } int netdev_load(Manager *manager) { _cleanup_strv_free_ char **files = NULL; NetDev *netdev; char **f; int r; assert(manager); while ((netdev = hashmap_first(manager->netdevs))) netdev_unref(netdev); r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs); if (r < 0) return log_error_errno(r, "Failed to enumerate netdev files: %m"); STRV_FOREACH_BACKWARDS(f, files) { r = netdev_load_one(manager, *f); if (r < 0) return r; } return 0; } systemd-229/src/network/networkd-netdev.h000066400000000000000000000202521265713322000206330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "list.h" typedef struct NetDev NetDev; typedef struct NetDevVTable NetDevVTable; #include "networkd-link.h" #include "networkd.h" typedef struct netdev_join_callback netdev_join_callback; struct netdev_join_callback { sd_netlink_message_handler_t callback; Link *link; LIST_FIELDS(netdev_join_callback, callbacks); }; typedef enum NetDevKind { NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP, NETDEV_KIND_IPVLAN, NETDEV_KIND_VXLAN, NETDEV_KIND_IPIP, NETDEV_KIND_GRE, NETDEV_KIND_GRETAP, NETDEV_KIND_IP6GRE, NETDEV_KIND_IP6GRETAP, NETDEV_KIND_SIT, NETDEV_KIND_VETH, NETDEV_KIND_VTI, NETDEV_KIND_VTI6, NETDEV_KIND_IP6TNL, NETDEV_KIND_DUMMY, NETDEV_KIND_TUN, NETDEV_KIND_TAP, _NETDEV_KIND_MAX, _NETDEV_KIND_INVALID = -1 } NetDevKind; typedef enum NetDevState { NETDEV_STATE_FAILED, NETDEV_STATE_CREATING, NETDEV_STATE_READY, NETDEV_STATE_LINGER, _NETDEV_STATE_MAX, _NETDEV_STATE_INVALID = -1, } NetDevState; typedef enum NetDevCreateType { NETDEV_CREATE_INDEPENDENT, NETDEV_CREATE_MASTER, NETDEV_CREATE_STACKED, _NETDEV_CREATE_MAX, _NETDEV_CREATE_INVALID = -1, } NetDevCreateType; struct NetDev { Manager *manager; int n_ref; char *filename; Condition *match_host; Condition *match_virt; Condition *match_kernel; Condition *match_arch; NetDevState state; NetDevKind kind; char *description; char *ifname; struct ether_addr *mac; size_t mtu; int ifindex; LIST_HEAD(netdev_join_callback, callbacks); }; #include "networkd-netdev-bond.h" #include "networkd-netdev-bridge.h" #include "networkd-netdev-dummy.h" #include "networkd-netdev-ipvlan.h" #include "networkd-netdev-macvlan.h" #include "networkd-netdev-tunnel.h" #include "networkd-netdev-tuntap.h" #include "networkd-netdev-veth.h" #include "networkd-netdev-vlan.h" #include "networkd-netdev-vxlan.h" struct NetDevVTable { /* How much memory does an object of this unit type need */ size_t object_size; /* Config file sections this netdev kind understands, separated * by NUL chars */ const char *sections; /* This should reset all type-specific variables. This should * not allocate memory, and is called with zero-initialized * data. It should hence only initialize variables that need * to be set != 0. */ void (*init)(NetDev *n); /* This should free all kind-specific variables. It should be * idempotent. */ void (*done)(NetDev *n); /* fill in message to create netdev */ int (*fill_message_create)(NetDev *netdev, Link *link, sd_netlink_message *message); /* specifies if netdev is independent, or a master device or a stacked device */ NetDevCreateType create_type; /* create netdev, if not done via rtnl */ int (*create)(NetDev *netdev); /* perform additional configuration after netdev has been createad */ int (*post_create)(NetDev *netdev, Link *link, sd_netlink_message *message); /* verify that compulsory configuration options were specified */ int (*config_verify)(NetDev *netdev, const char *filename); }; extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX]; #define NETDEV_VTABLE(n) netdev_vtable[(n)->kind] /* For casting a netdev into the various netdev kinds */ #define DEFINE_CAST(UPPERCASE, MixedCase) \ static inline MixedCase* UPPERCASE(NetDev *n) { \ if (_unlikely_(!n || n->kind != NETDEV_KIND_##UPPERCASE)) \ return NULL; \ \ return (MixedCase*) n; \ } /* For casting the various netdev kinds into a netdev */ #define NETDEV(n) (&(n)->meta) DEFINE_CAST(BRIDGE, Bridge); DEFINE_CAST(BOND, Bond); DEFINE_CAST(VLAN, VLan); DEFINE_CAST(MACVLAN, MacVlan); DEFINE_CAST(MACVTAP, MacVlan); DEFINE_CAST(IPVLAN, IPVlan); DEFINE_CAST(VXLAN, VxLan); DEFINE_CAST(IPIP, Tunnel); DEFINE_CAST(GRE, Tunnel); DEFINE_CAST(GRETAP, Tunnel); DEFINE_CAST(IP6GRE, Tunnel); DEFINE_CAST(IP6GRETAP, Tunnel); DEFINE_CAST(SIT, Tunnel); DEFINE_CAST(VTI, Tunnel); DEFINE_CAST(VTI6, Tunnel); DEFINE_CAST(IP6TNL, Tunnel); DEFINE_CAST(VETH, Veth); DEFINE_CAST(DUMMY, Dummy); DEFINE_CAST(TUN, TunTap); DEFINE_CAST(TAP, TunTap); int netdev_load(Manager *manager); void netdev_drop(NetDev *netdev); NetDev *netdev_unref(NetDev *netdev); NetDev *netdev_ref(NetDev *netdev); DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref); #define _cleanup_netdev_unref_ _cleanup_(netdev_unrefp) int netdev_get(Manager *manager, const char *name, NetDev **ret); int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink); int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t callback); int netdev_get_mac(const char *ifname, struct ether_addr **ret); int netdev_join(NetDev *netdev, Link *link, sd_netlink_message_handler_t cb); const char *netdev_kind_to_string(NetDevKind d) _const_; NetDevKind netdev_kind_from_string(const char *d) _pure_; int config_parse_netdev_kind(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); /* gperf */ const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, unsigned length); /* Macros which append INTERFACE= to the message */ #define log_netdev_full(netdev, level, error, ...) \ ({ \ NetDev *_n = (netdev); \ _n ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _n->ifname, ##__VA_ARGS__) : \ log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ }) #define log_netdev_debug(netdev, ...) log_netdev_full(netdev, LOG_DEBUG, 0, ##__VA_ARGS__) #define log_netdev_info(netdev, ...) log_netdev_full(netdev, LOG_INFO, 0, ##__VA_ARGS__) #define log_netdev_notice(netdev, ...) log_netdev_full(netdev, LOG_NOTICE, 0, ##__VA_ARGS__) #define log_netdev_warning(netdev, ...) log_netdev_full(netdev, LOG_WARNING, 0, ## __VA_ARGS__) #define log_netdev_error(netdev, ...) log_netdev_full(netdev, LOG_ERR, 0, ##__VA_ARGS__) #define log_netdev_debug_errno(netdev, error, ...) log_netdev_full(netdev, LOG_DEBUG, error, ##__VA_ARGS__) #define log_netdev_info_errno(netdev, error, ...) log_netdev_full(netdev, LOG_INFO, error, ##__VA_ARGS__) #define log_netdev_notice_errno(netdev, error, ...) log_netdev_full(netdev, LOG_NOTICE, error, ##__VA_ARGS__) #define log_netdev_warning_errno(netdev, error, ...) log_netdev_full(netdev, LOG_WARNING, error, ##__VA_ARGS__) #define log_netdev_error_errno(netdev, error, ...) log_netdev_full(netdev, LOG_ERR, error, ##__VA_ARGS__) #define LOG_NETDEV_MESSAGE(netdev, fmt, ...) "MESSAGE=%s: " fmt, (netdev)->ifname, ##__VA_ARGS__ #define LOG_NETDEV_INTERFACE(netdev) "INTERFACE=%s", (netdev)->ifname systemd-229/src/network/networkd-network-bus.c000066400000000000000000000106301265713322000216200ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "networkd.h" #include "string-util.h" #include "strv.h" static int property_get_ether_addrs( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Network *n = userdata; const char *ether = NULL; int r; assert(bus); assert(reply); assert(n); if (n->match_mac) ether = ether_ntoa(n->match_mac); r = sd_bus_message_open_container(reply, 'a', "s"); if (r < 0) return r; if (ether) { r = sd_bus_message_append(reply, "s", strempty(ether)); if (r < 0) return r; } return sd_bus_message_close_container(reply); } const sd_bus_vtable network_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Description", "s", NULL, offsetof(Network, description), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Network, filename), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MatchMAC", "as", property_get_ether_addrs, offsetof(Network, match_mac), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MatchPath", "as", NULL, offsetof(Network, match_path), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MatchDriver", "as", NULL, offsetof(Network, match_driver), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MatchType", "as", NULL, offsetof(Network, match_type), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MatchName", "as", NULL, offsetof(Network, match_name), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_VTABLE_END }; static char *network_bus_path(Network *network) { _cleanup_free_ char *name = NULL; char *networkname, *d, *path; int r; assert(network); assert(network->filename); name = strdup(network->filename); if (!name) return NULL; networkname = basename(name); d = strrchr(networkname, '.'); if (!d) return NULL; assert(streq(d, ".network")); *d = '\0'; r = sd_bus_path_encode("/org/freedesktop/network1/network", networkname, &path); if (r < 0) return NULL; return path; } int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; Manager *m = userdata; Network *network; int r; assert(bus); assert(path); assert(m); assert(nodes); LIST_FOREACH(networks, network, m->networks) { char *p; p = network_bus_path(network); if (!p) return -ENOMEM; r = strv_consume(&l, p); if (r < 0) return r; } *nodes = l; l = NULL; return 1; } int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; Network *network; _cleanup_free_ char *name = NULL; int r; assert(bus); assert(path); assert(interface); assert(m); assert(found); r = sd_bus_path_decode(path, "/org/freedesktop/network1/network", &name); if (r < 0) return 0; r = network_get_by_name(m, name, &network); if (r < 0) return 0; *found = network; return 1; } systemd-229/src/network/networkd-network-gperf.gperf000066400000000000000000000324161265713322000230210ustar00rootroot00000000000000%{ #include #include "conf-parser.h" #include "networkd.h" #include "network-internal.h" %} struct ConfigPerfItem; %null_strings %language=ANSI-C %define slot-name section_and_lvalue %define hash-function-name network_network_gperf_hash %define lookup-function-name network_network_gperf_lookup %readonly-tables %omit-struct-type %struct-type %includes %% Match.MACAddress, config_parse_hwaddr, 0, offsetof(Network, match_mac) Match.Path, config_parse_strv, 0, offsetof(Network, match_path) Match.Driver, config_parse_strv, 0, offsetof(Network, match_driver) Match.Type, config_parse_strv, 0, offsetof(Network, match_type) Match.Name, config_parse_ifnames, 0, offsetof(Network, match_name) Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, match_host) Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, match_virt) Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, match_kernel) Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch) Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac) Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu) Network.Description, config_parse_string, 0, offsetof(Network, description) Network.Bridge, config_parse_netdev, 0, offsetof(Network, bridge) Network.Bond, config_parse_netdev, 0, offsetof(Network, bond) Network.VLAN, config_parse_netdev, 0, 0 Network.MACVLAN, config_parse_netdev, 0, 0 Network.MACVTAP, config_parse_netdev, 0, 0 Network.IPVLAN, config_parse_netdev, 0, 0 Network.VXLAN, config_parse_netdev, 0, 0 Network.Tunnel, config_parse_tunnel, 0, 0 Network.DHCP, config_parse_dhcp, 0, offsetof(Network, dhcp) Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server) Network.LinkLocalAddressing, config_parse_address_family_boolean, 0, offsetof(Network, link_local) Network.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route) Network.IPv6Token, config_parse_ipv6token, 0, offsetof(Network, ipv6_token) Network.LLDP, config_parse_bool, 0, offsetof(Network, lldp) Network.Address, config_parse_address, 0, 0 Network.Gateway, config_parse_gateway, 0, 0 Network.Domains, config_parse_domains, 0, 0 Network.DNS, config_parse_strv, 0, offsetof(Network, dns) Network.LLMNR, config_parse_resolve_support, 0, offsetof(Network, llmnr) Network.MulticastDNS, config_parse_resolve_support, 0, offsetof(Network, mdns) Network.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Network, dnssec_mode) Network.DNSSECNegativeTrustAnchors, config_parse_dnssec_negative_trust_anchors, 0, offsetof(Network, dnssec_negative_trust_anchors) Network.NTP, config_parse_strv, 0, offsetof(Network, ntp) Network.IPForward, config_parse_address_family_boolean_with_kernel,0, offsetof(Network, ip_forward) Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade) Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Network, ipv6_privacy_extensions) Network.IPv6AcceptRouterAdvertisements, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra) Network.IPv6DuplicateAddressDetection, config_parse_int, 0, offsetof(Network, ipv6_dad_transmits) Network.IPv6HopLimit, config_parse_int, 0, offsetof(Network, ipv6_hop_limit) Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier) Address.Address, config_parse_address, 0, 0 Address.Peer, config_parse_address, 0, 0 Address.Broadcast, config_parse_broadcast, 0, 0 Address.Label, config_parse_label, 0, 0 Route.Gateway, config_parse_gateway, 0, 0 Route.Destination, config_parse_destination, 0, 0 Route.Source, config_parse_destination, 0, 0 Route.Metric, config_parse_route_priority, 0, 0 Route.Scope, config_parse_route_scope, 0, 0 Route.PreferredSource, config_parse_preferred_src, 0, 0 DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns) DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_use_ntp) DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu) DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname) DHCP.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_use_routes) DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_send_hostname) DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname) DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast) DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical) DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier) DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric) DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec) DHCPServer.DefaultLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec) DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_dns) DHCPServer.DNS, config_parse_dhcp_server_dns, 0, 0 DHCPServer.EmitNTP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_ntp) DHCPServer.NTP, config_parse_dhcp_server_ntp, 0, 0 DHCPServer.EmitTimezone, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_timezone) DHCPServer.Timezone, config_parse_timezone, 0, offsetof(Network, dhcp_server_timezone) DHCPServer.PoolOffset, config_parse_uint32, 0, offsetof(Network, dhcp_server_pool_offset) DHCPServer.PoolSize, config_parse_uint32, 0, offsetof(Network, dhcp_server_pool_size) Bridge.Cost, config_parse_unsigned, 0, offsetof(Network, cost) Bridge.UseBPDU, config_parse_bool, 0, offsetof(Network, use_bpdu) Bridge.HairPin, config_parse_bool, 0, offsetof(Network, hairpin) Bridge.FastLeave, config_parse_bool, 0, offsetof(Network, fast_leave) Bridge.AllowPortToBeRoot, config_parse_bool, 0, offsetof(Network, allow_port_to_be_root) Bridge.UnicastFlood, config_parse_bool, 0, offsetof(Network, unicast_flood) BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0 BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0 /* backwards compatibility: do not add new entries to this section */ Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local) DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns) DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu) DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname) DHCP.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) DHCPv4.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) DHCPv4.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical) systemd-229/src/network/networkd-network.c000066400000000000000000000772501265713322000210440ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "conf-files.h" #include "conf-parser.h" #include "dns-domain.h" #include "fd-util.h" #include "hostname-util.h" #include "network-internal.h" #include "networkd-network.h" #include "networkd.h" #include "parse-util.h" #include "set.h" #include "stat-util.h" #include "string-table.h" #include "string-util.h" #include "util.h" static int network_load_one(Manager *manager, const char *filename) { _cleanup_network_free_ Network *network = NULL; _cleanup_fclose_ FILE *file = NULL; char *d; Route *route; Address *address; int r; assert(manager); assert(filename); file = fopen(filename, "re"); if (!file) { if (errno == ENOENT) return 0; else return -errno; } if (null_or_empty_fd(fileno(file))) { log_debug("Skipping empty file: %s", filename); return 0; } network = new0(Network, 1); if (!network) return log_oom(); network->manager = manager; LIST_HEAD_INIT(network->static_addresses); LIST_HEAD_INIT(network->static_routes); LIST_HEAD_INIT(network->static_fdb_entries); network->stacked_netdevs = hashmap_new(&string_hash_ops); if (!network->stacked_netdevs) return log_oom(); network->addresses_by_section = hashmap_new(NULL); if (!network->addresses_by_section) return log_oom(); network->routes_by_section = hashmap_new(NULL); if (!network->routes_by_section) return log_oom(); network->fdb_entries_by_section = hashmap_new(NULL); if (!network->fdb_entries_by_section) return log_oom(); network->filename = strdup(filename); if (!network->filename) return log_oom(); network->name = strdup(basename(filename)); if (!network->name) return log_oom(); d = strrchr(network->name, '.'); if (!d) return -EINVAL; assert(streq(d, ".network")); *d = '\0'; network->dhcp = ADDRESS_FAMILY_NO; network->dhcp_use_ntp = true; network->dhcp_use_dns = true; network->dhcp_use_hostname = true; network->dhcp_use_routes = true; network->dhcp_send_hostname = true; network->dhcp_route_metric = DHCP_ROUTE_METRIC; network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID; network->dhcp_server_emit_dns = true; network->dhcp_server_emit_ntp = true; network->dhcp_server_emit_timezone = true; network->use_bpdu = true; network->allow_port_to_be_root = true; network->unicast_flood = true; network->llmnr = RESOLVE_SUPPORT_YES; network->mdns = RESOLVE_SUPPORT_NO; network->dnssec_mode = _DNSSEC_MODE_INVALID; network->link_local = ADDRESS_FAMILY_IPV6; network->ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO; network->ipv6_accept_ra = -1; network->ipv6_dad_transmits = -1; network->ipv6_hop_limit = -1; r = config_parse(NULL, filename, file, "Match\0" "Link\0" "Network\0" "Address\0" "Route\0" "DHCP\0" "DHCPv4\0" /* compat */ "DHCPServer\0" "Bridge\0" "BridgeFDB\0", config_item_perf_lookup, network_network_gperf_lookup, false, false, true, network); if (r < 0) return r; /* IPMasquerade=yes implies IPForward=yes */ if (network->ip_masquerade) network->ip_forward |= ADDRESS_FAMILY_IPV4; LIST_PREPEND(networks, manager->networks, network); r = hashmap_ensure_allocated(&manager->networks_by_name, &string_hash_ops); if (r < 0) return r; r = hashmap_put(manager->networks_by_name, network->name, network); if (r < 0) return r; LIST_FOREACH(routes, route, network->static_routes) { if (!route->family) { log_warning("Route section without Gateway field configured in %s. " "Ignoring", filename); return 0; } } LIST_FOREACH(addresses, address, network->static_addresses) { if (!address->family) { log_warning("Address section without Address field configured in %s. " "Ignoring", filename); return 0; } } network = NULL; return 0; } int network_load(Manager *manager) { Network *network; _cleanup_strv_free_ char **files = NULL; char **f; int r; assert(manager); while ((network = manager->networks)) network_free(network); r = conf_files_list_strv(&files, ".network", NULL, network_dirs); if (r < 0) return log_error_errno(r, "Failed to enumerate network files: %m"); STRV_FOREACH_BACKWARDS(f, files) { r = network_load_one(manager, *f); if (r < 0) return r; } return 0; } void network_free(Network *network) { NetDev *netdev; Route *route; Address *address; FdbEntry *fdb_entry; Iterator i; if (!network) return; free(network->filename); free(network->match_mac); strv_free(network->match_path); strv_free(network->match_driver); strv_free(network->match_type); strv_free(network->match_name); free(network->description); free(network->dhcp_vendor_class_identifier); free(network->dhcp_hostname); free(network->mac); strv_free(network->ntp); strv_free(network->dns); strv_free(network->search_domains); strv_free(network->route_domains); strv_free(network->bind_carrier); netdev_unref(network->bridge); netdev_unref(network->bond); HASHMAP_FOREACH(netdev, network->stacked_netdevs, i) { hashmap_remove(network->stacked_netdevs, netdev->ifname); netdev_unref(netdev); } hashmap_free(network->stacked_netdevs); while ((route = network->static_routes)) route_free(route); while ((address = network->static_addresses)) address_free(address); while ((fdb_entry = network->static_fdb_entries)) fdb_entry_free(fdb_entry); hashmap_free(network->addresses_by_section); hashmap_free(network->routes_by_section); hashmap_free(network->fdb_entries_by_section); if (network->manager) { if (network->manager->networks) LIST_REMOVE(networks, network->manager->networks, network); if (network->manager->networks_by_name) hashmap_remove(network->manager->networks_by_name, network->name); } free(network->name); condition_free_list(network->match_host); condition_free_list(network->match_virt); condition_free_list(network->match_kernel); condition_free_list(network->match_arch); free(network->dhcp_server_timezone); free(network->dhcp_server_dns); free(network->dhcp_server_ntp); set_free_free(network->dnssec_negative_trust_anchors); free(network); } int network_get_by_name(Manager *manager, const char *name, Network **ret) { Network *network; assert(manager); assert(name); assert(ret); network = hashmap_get(manager->networks_by_name, name); if (!network) return -ENOENT; *ret = network; return 0; } int network_get(Manager *manager, struct udev_device *device, const char *ifname, const struct ether_addr *address, Network **ret) { Network *network; struct udev_device *parent; const char *path = NULL, *parent_driver = NULL, *driver = NULL, *devtype = NULL; assert(manager); assert(ret); if (device) { path = udev_device_get_property_value(device, "ID_PATH"); parent = udev_device_get_parent(device); if (parent) parent_driver = udev_device_get_driver(parent); driver = udev_device_get_property_value(device, "ID_NET_DRIVER"); devtype = udev_device_get_devtype(device); } LIST_FOREACH(networks, network, manager->networks) { if (net_match_config(network->match_mac, network->match_path, network->match_driver, network->match_type, network->match_name, network->match_host, network->match_virt, network->match_kernel, network->match_arch, address, path, parent_driver, driver, devtype, ifname)) { if (network->match_name && device) { const char *attr; uint8_t name_assign_type = NET_NAME_UNKNOWN; attr = udev_device_get_sysattr_value(device, "name_assign_type"); if (attr) (void) safe_atou8(attr, &name_assign_type); if (name_assign_type == NET_NAME_ENUM) log_warning("%s: found matching network '%s', based on potentially unpredictable ifname", ifname, network->filename); else log_debug("%s: found matching network '%s'", ifname, network->filename); } else log_debug("%s: found matching network '%s'", ifname, network->filename); *ret = network; return 0; } } *ret = NULL; return -ENOENT; } int network_apply(Manager *manager, Network *network, Link *link) { int r; assert(manager); assert(network); assert(link); link->network = network; if (network->ipv4ll_route) { Route *route; r = route_new_static(network, 0, &route); if (r < 0) return r; r = inet_pton(AF_INET, "169.254.0.0", &route->dst.in); if (r == 0) return -EINVAL; if (r < 0) return -errno; route->family = AF_INET; route->dst_prefixlen = 16; route->scope = RT_SCOPE_LINK; route->priority = IPV4LL_ROUTE_METRIC; route->protocol = RTPROT_STATIC; } if (!strv_isempty(network->dns) || !strv_isempty(network->ntp) || !strv_isempty(network->search_domains) || !strv_isempty(network->route_domains)) { manager_dirty(manager); link_dirty(link); } return 0; } int config_parse_netdev(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *network = userdata; _cleanup_free_ char *kind_string = NULL; char *p; NetDev *netdev; NetDevKind kind; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); kind_string = strdup(lvalue); if (!kind_string) return log_oom(); /* the keys are CamelCase versions of the kind */ for (p = kind_string; *p; p++) *p = tolower(*p); kind = netdev_kind_from_string(kind_string); if (kind == _NETDEV_KIND_INVALID) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid NetDev kind: %s", lvalue); return 0; } r = netdev_get(network->manager, rvalue, &netdev); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "%s could not be found, ignoring assignment: %s", lvalue, rvalue); return 0; } if (netdev->kind != kind) { log_syntax(unit, LOG_ERR, filename, line, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue, rvalue); return 0; } switch (kind) { case NETDEV_KIND_BRIDGE: network->bridge = netdev; break; case NETDEV_KIND_BOND: network->bond = netdev; break; case NETDEV_KIND_VLAN: case NETDEV_KIND_MACVLAN: case NETDEV_KIND_MACVTAP: case NETDEV_KIND_IPVLAN: case NETDEV_KIND_VXLAN: r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Can not add VLAN '%s' to network: %m", rvalue); return 0; } break; default: assert_not_reached("Can not parse NetDev"); } netdev_ref(netdev); return 0; } int config_parse_domains( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { const char *p; Network *n = data; int r; assert(n); assert(lvalue); assert(rvalue); if (isempty(rvalue)) { n->search_domains = strv_free(n->search_domains); n->route_domains = strv_free(n->route_domains); return 0; } p = rvalue; for (;;) { _cleanup_free_ char *w = NULL, *normalized = NULL; const char *domain; bool is_route; r = extract_first_word(&p, &w, NULL, 0); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract search or route domain, ignoring: %s", rvalue); break; } if (r == 0) break; is_route = w[0] == '~'; domain = is_route ? w + 1 : w; if (dns_name_is_root(domain) || streq(domain, "*")) { /* If the root domain appears as is, or the special token "*" is found, we'll consider this as * routing domain, unconditionally. */ is_route = true; domain = "."; /* make sure we don't allow empty strings, thus write the root domain as "." */ } else { r = dns_name_normalize(domain, &normalized); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "'%s' is not a valid domain name, ignoring.", domain); continue; } domain = normalized; if (is_localhost(domain)) { log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain); continue; } } if (is_route) { r = strv_extend(&n->route_domains, domain); if (r < 0) return log_oom(); } else { r = strv_extend(&n->search_domains, domain); if (r < 0) return log_oom(); } } strv_uniq(n->route_domains); strv_uniq(n->search_domains); return 0; } int config_parse_tunnel(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *network = userdata; NetDev *netdev; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = netdev_get(network->manager, rvalue, &netdev); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Tunnel is invalid, ignoring assignment: %s", rvalue); return 0; } if (netdev->kind != NETDEV_KIND_IPIP && netdev->kind != NETDEV_KIND_SIT && netdev->kind != NETDEV_KIND_GRE && netdev->kind != NETDEV_KIND_GRETAP && netdev->kind != NETDEV_KIND_IP6GRE && netdev->kind != NETDEV_KIND_IP6GRETAP && netdev->kind != NETDEV_KIND_VTI && netdev->kind != NETDEV_KIND_VTI6 && netdev->kind != NETDEV_KIND_IP6TNL ) { log_syntax(unit, LOG_ERR, filename, line, 0, "NetDev is not a tunnel, ignoring assignment: %s", rvalue); return 0; } r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue); return 0; } netdev_ref(netdev); return 0; } int config_parse_ipv4ll( const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { AddressFamilyBoolean *link_local = data; assert(filename); assert(lvalue); assert(rvalue); assert(data); /* Note that this is mostly like * config_parse_address_family_boolean(), except that it * applies only to IPv4 */ if (parse_boolean(rvalue)) *link_local |= ADDRESS_FAMILY_IPV4; else *link_local &= ~ADDRESS_FAMILY_IPV4; return 0; } int config_parse_dhcp( const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { AddressFamilyBoolean *dhcp = data, s; assert(filename); assert(lvalue); assert(rvalue); assert(data); /* Note that this is mostly like * config_parse_address_family_boolean(), except that it * understands some old names for the enum values */ s = address_family_boolean_from_string(rvalue); if (s < 0) { /* Previously, we had a slightly different enum here, * support its values for compatbility. */ if (streq(rvalue, "none")) s = ADDRESS_FAMILY_NO; else if (streq(rvalue, "v4")) s = ADDRESS_FAMILY_IPV4; else if (streq(rvalue, "v6")) s = ADDRESS_FAMILY_IPV6; else if (streq(rvalue, "both")) s = ADDRESS_FAMILY_YES; else { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DHCP option, ignoring: %s", rvalue); return 0; } } *dhcp = s; return 0; } static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = { [DHCP_CLIENT_ID_MAC] = "mac", [DHCP_CLIENT_ID_DUID] = "duid" }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DCHPClientIdentifier); DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DCHPClientIdentifier, "Failed to parse client identifier type"); int config_parse_ipv6token( const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { union in_addr_union buffer; struct in6_addr *token = data; int r; assert(filename); assert(lvalue); assert(rvalue); assert(token); r = in_addr_from_string(AF_INET6, rvalue, &buffer); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IPv6 token, ignoring: %s", rvalue); return 0; } r = in_addr_is_null(AF_INET6, &buffer); if (r != 0) { log_syntax(unit, LOG_ERR, filename, line, r, "IPv6 token can not be the ANY address, ignoring: %s", rvalue); return 0; } if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue); return 0; } *token = buffer.in6; return 0; } static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = { [IPV6_PRIVACY_EXTENSIONS_NO] = "no", [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public", [IPV6_PRIVACY_EXTENSIONS_YES] = "yes", }; DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions); int config_parse_ipv6_privacy_extensions( const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { IPv6PrivacyExtensions *ipv6_privacy_extensions = data; int k; assert(filename); assert(lvalue); assert(rvalue); assert(ipv6_privacy_extensions); /* Our enum shall be a superset of booleans, hence first try * to parse as boolean, and then as enum */ k = parse_boolean(rvalue); if (k > 0) *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES; else if (k == 0) *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO; else { IPv6PrivacyExtensions s; s = ipv6_privacy_extensions_from_string(rvalue); if (s < 0) { if (streq(rvalue, "kernel")) s = _IPV6_PRIVACY_EXTENSIONS_INVALID; else { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue); return 0; } } *ipv6_privacy_extensions = s; } return 0; } int config_parse_hostname( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { char **hostname = data, *hn = NULL; int r; assert(filename); assert(lvalue); assert(rvalue); r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata); if (r < 0) return r; if (!hostname_is_valid(hn, false)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Hostname is not valid, ignoring assignment: %s", rvalue); free(hn); return 0; } free(*hostname); *hostname = hostname_cleanup(hn); return 0; } int config_parse_timezone( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { char **datap = data, *tz = NULL; int r; assert(filename); assert(lvalue); assert(rvalue); r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata); if (r < 0) return r; if (!timezone_is_valid(tz)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Timezone is not valid, ignoring assignment: %s", rvalue); free(tz); return 0; } free(*datap); *datap = tz; return 0; } int config_parse_dhcp_server_dns( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *n = data; const char *p = rvalue; int r; assert(filename); assert(lvalue); assert(rvalue); for (;;) { _cleanup_free_ char *w = NULL; struct in_addr a, *m; r = extract_first_word(&p, &w, NULL, 0); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue); return 0; } if (r == 0) return 0; if (inet_pton(AF_INET, w, &a) <= 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DNS server address, ignoring: %s", w); continue; } m = realloc(n->dhcp_server_dns, (n->n_dhcp_server_dns + 1) * sizeof(struct in_addr)); if (!m) return log_oom(); m[n->n_dhcp_server_dns++] = a; n->dhcp_server_dns = m; } } int config_parse_dhcp_server_ntp( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *n = data; const char *p = rvalue; int r; assert(filename); assert(lvalue); assert(rvalue); for (;;) { _cleanup_free_ char *w = NULL; struct in_addr a, *m; r = extract_first_word(&p, &w, NULL, 0); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue); return 0; } if (r == 0) return 0; if (inet_pton(AF_INET, w, &a) <= 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse NTP server address, ignoring: %s", w); continue; } m = realloc(n->dhcp_server_ntp, (n->n_dhcp_server_ntp + 1) * sizeof(struct in_addr)); if (!m) return log_oom(); m[n->n_dhcp_server_ntp++] = a; n->dhcp_server_ntp = m; } } int config_parse_dnssec_negative_trust_anchors( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { const char *p = rvalue; Network *n = data; int r; assert(n); assert(lvalue); assert(rvalue); if (isempty(rvalue)) { n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors); return 0; } for (;;) { _cleanup_free_ char *w = NULL; r = extract_first_word(&p, &w, NULL, 0); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue); break; } if (r == 0) break; r = dns_name_is_valid(w); if (r <= 0) { log_syntax(unit, LOG_ERR, filename, line, r, "%s is not a valid domain name, ignoring.", w); continue; } r = set_put(n->dnssec_negative_trust_anchors, w); if (r < 0) return log_oom(); if (r > 0) w = NULL; } return 0; } DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, "Failed to parse DHCP use domains setting"); static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = { [DHCP_USE_DOMAINS_NO] = "no", [DHCP_USE_DOMAINS_ROUTE] = "route", [DHCP_USE_DOMAINS_YES] = "yes", }; DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES); systemd-229/src/network/networkd-network.h000066400000000000000000000206321265713322000210410ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "condition.h" #include "resolve-util.h" typedef struct Network Network; #include "networkd-address.h" #include "networkd-fdb.h" #include "networkd-netdev.h" #include "networkd-route.h" #include "networkd-util.h" #include "networkd.h" #define DHCP_ROUTE_METRIC 1024 #define IPV4LL_ROUTE_METRIC 2048 typedef enum DCHPClientIdentifier { DHCP_CLIENT_ID_MAC, DHCP_CLIENT_ID_DUID, _DHCP_CLIENT_ID_MAX, _DHCP_CLIENT_ID_INVALID = -1, } DCHPClientIdentifier; typedef enum IPv6PrivacyExtensions { /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */ IPV6_PRIVACY_EXTENSIONS_NO, IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC, IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */ _IPV6_PRIVACY_EXTENSIONS_MAX, _IPV6_PRIVACY_EXTENSIONS_INVALID = -1, } IPv6PrivacyExtensions; typedef enum DHCPUseDomains { DHCP_USE_DOMAINS_NO, DHCP_USE_DOMAINS_YES, DHCP_USE_DOMAINS_ROUTE, _DHCP_USE_DOMAINS_MAX, _DHCP_USE_DOMAINS_INVALID = -1, } DHCPUseDomains; struct Network { Manager *manager; char *filename; char *name; struct ether_addr *match_mac; char **match_path; char **match_driver; char **match_type; char **match_name; Condition *match_host; Condition *match_virt; Condition *match_kernel; Condition *match_arch; char *description; NetDev *bridge; NetDev *bond; Hashmap *stacked_netdevs; /* DHCP Client Support */ AddressFamilyBoolean dhcp; DCHPClientIdentifier dhcp_client_identifier; char *dhcp_vendor_class_identifier; char *dhcp_hostname; bool dhcp_use_dns; bool dhcp_use_ntp; bool dhcp_use_mtu; bool dhcp_use_hostname; DHCPUseDomains dhcp_use_domains; bool dhcp_send_hostname; bool dhcp_broadcast; bool dhcp_critical; bool dhcp_use_routes; bool dhcp_use_timezone; unsigned dhcp_route_metric; /* DHCP Server Support */ bool dhcp_server; bool dhcp_server_emit_dns; struct in_addr *dhcp_server_dns; unsigned n_dhcp_server_dns; bool dhcp_server_emit_ntp; struct in_addr *dhcp_server_ntp; unsigned n_dhcp_server_ntp; bool dhcp_server_emit_timezone; char *dhcp_server_timezone; usec_t dhcp_server_default_lease_time_usec, dhcp_server_max_lease_time_usec; uint32_t dhcp_server_pool_offset; uint32_t dhcp_server_pool_size; /* IPV4LL Support */ AddressFamilyBoolean link_local; bool ipv4ll_route; /* Bridge Support */ bool use_bpdu; bool hairpin; bool fast_leave; bool allow_port_to_be_root; bool unicast_flood; unsigned cost; AddressFamilyBoolean ip_forward; bool ip_masquerade; int ipv6_accept_ra; int ipv6_dad_transmits; int ipv6_hop_limit; union in_addr_union ipv6_token; IPv6PrivacyExtensions ipv6_privacy_extensions; struct ether_addr *mac; unsigned mtu; bool lldp; LIST_HEAD(Address, static_addresses); LIST_HEAD(Route, static_routes); LIST_HEAD(FdbEntry, static_fdb_entries); Hashmap *addresses_by_section; Hashmap *routes_by_section; Hashmap *fdb_entries_by_section; char **search_domains, **route_domains, **dns, **ntp, **bind_carrier; ResolveSupport llmnr; ResolveSupport mdns; DnssecMode dnssec_mode; Set *dnssec_negative_trust_anchors; LIST_FIELDS(Network, networks); }; void network_free(Network *network); DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free); #define _cleanup_network_free_ _cleanup_(network_freep) int network_load(Manager *manager); int network_get_by_name(Manager *manager, const char *name, Network **ret); int network_get(Manager *manager, struct udev_device *device, const char *ifname, const struct ether_addr *mac, Network **ret); int network_apply(Manager *manager, Network *network, Link *link); int config_parse_netdev(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_tunnel(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_dhcp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_dhcp_client_identifier(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_ipv6token(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_ipv6_privacy_extensions(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_hostname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_timezone(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_dhcp_server_dns(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_dhcp_server_ntp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_dnssec_negative_trust_anchors(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_dhcp_use_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); /* Legacy IPv4LL support */ int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, unsigned length); extern const sd_bus_vtable network_vtable[]; int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_; IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_; const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_; DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_; systemd-229/src/network/networkd-route.c000066400000000000000000000622271265713322000205070ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "conf-parser.h" #include "in-addr-util.h" #include "netlink-util.h" #include "networkd-route.h" #include "networkd.h" #include "parse-util.h" #include "set.h" #include "string-util.h" #include "util.h" int route_new(Route **ret) { _cleanup_route_free_ Route *route = NULL; route = new0(Route, 1); if (!route) return -ENOMEM; route->family = AF_UNSPEC; route->scope = RT_SCOPE_UNIVERSE; route->protocol = RTPROT_UNSPEC; route->table = RT_TABLE_DEFAULT; route->lifetime = USEC_INFINITY; *ret = route; route = NULL; return 0; } int route_new_static(Network *network, unsigned section, Route **ret) { _cleanup_route_free_ Route *route = NULL; int r; if (section) { route = hashmap_get(network->routes_by_section, UINT_TO_PTR(section)); if (route) { *ret = route; route = NULL; return 0; } } r = route_new(&route); if (r < 0) return r; route->protocol = RTPROT_STATIC; route->network = network; LIST_PREPEND(routes, network->static_routes, route); if (section) { route->section = section; hashmap_put(network->routes_by_section, UINT_TO_PTR(route->section), route); } *ret = route; route = NULL; return 0; } void route_free(Route *route) { if (!route) return; if (route->network) { LIST_REMOVE(routes, route->network->static_routes, route); if (route->section) hashmap_remove(route->network->routes_by_section, UINT_TO_PTR(route->section)); } if (route->link) { set_remove(route->link->routes, route); set_remove(route->link->routes_foreign, route); } sd_event_source_unref(route->expire); free(route); } static void route_hash_func(const void *b, struct siphash *state) { const Route *route = b; assert(route); siphash24_compress(&route->family, sizeof(route->family), state); switch (route->family) { case AF_INET: case AF_INET6: /* Equality of routes are given by the 4-touple (dst_prefix,dst_prefixlen,tos,priority,table) */ siphash24_compress(&route->dst, FAMILY_ADDRESS_SIZE(route->family), state); siphash24_compress(&route->dst_prefixlen, sizeof(route->dst_prefixlen), state); siphash24_compress(&route->tos, sizeof(route->tos), state); siphash24_compress(&route->priority, sizeof(route->priority), state); siphash24_compress(&route->table, sizeof(route->table), state); break; default: /* treat any other address family as AF_UNSPEC */ break; } } static int route_compare_func(const void *_a, const void *_b) { const Route *a = _a, *b = _b; if (a->family < b->family) return -1; if (a->family > b->family) return 1; switch (a->family) { case AF_INET: case AF_INET6: if (a->dst_prefixlen < b->dst_prefixlen) return -1; if (a->dst_prefixlen > b->dst_prefixlen) return 1; if (a->tos < b->tos) return -1; if (a->tos > b->tos) return 1; if (a->priority < b->priority) return -1; if (a->priority > b->priority) return 1; if (a->table < b->table) return -1; if (a->table > b->table) return 1; return memcmp(&a->dst, &b->dst, FAMILY_ADDRESS_SIZE(a->family)); default: /* treat any other address family as AF_UNSPEC */ return 0; } } static const struct hash_ops route_hash_ops = { .hash = route_hash_func, .compare = route_compare_func }; int route_get(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret) { Route route = { .family = family, .dst_prefixlen = dst_prefixlen, .tos = tos, .priority = priority, .table = table, }, *existing; assert(link); assert(dst); assert(ret); route.dst = *dst; existing = set_get(link->routes, &route); if (existing) { *ret = existing; return 1; } else { existing = set_get(link->routes_foreign, &route); if (!existing) return -ENOENT; } *ret = existing; return 0; } static int route_add_internal(Link *link, Set **routes, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret) { _cleanup_route_free_ Route *route = NULL; int r; assert(link); assert(routes); assert(dst); r = route_new(&route); if (r < 0) return r; route->family = family; route->dst = *dst; route->dst_prefixlen = dst_prefixlen; route->tos = tos; route->priority = priority; route->table = table; r = set_ensure_allocated(routes, &route_hash_ops); if (r < 0) return r; r = set_put(*routes, route); if (r < 0) return r; route->link = link; if (ret) *ret = route; route = NULL; return 0; } int route_add_foreign(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret) { return route_add_internal(link, &link->routes_foreign, family, dst, dst_prefixlen, tos, priority, table, ret); } int route_add(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret) { Route *route; int r; r = route_get(link, family, dst, dst_prefixlen, tos, priority, table, &route); if (r == -ENOENT) { /* Route does not exist, create a new one */ r = route_add_internal(link, &link->routes, family, dst, dst_prefixlen, tos, priority, table, &route); if (r < 0) return r; } else if (r == 0) { /* Take over a foreign route */ r = set_ensure_allocated(&link->routes, &route_hash_ops); if (r < 0) return r; r = set_put(link->routes, route); if (r < 0) return r; set_remove(link->routes_foreign, route); } else if (r == 1) { /* Route exists, do nothing */ ; } else return r; *ret = route; return 0; } int route_update(Route *route, union in_addr_union *src, unsigned char src_prefixlen, union in_addr_union *gw, union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol) { assert(route); assert(src); assert(gw); assert(prefsrc); route->src = *src; route->src_prefixlen = src_prefixlen; route->gw = *gw; route->prefsrc = *prefsrc; route->scope = scope; route->protocol = protocol; return 0; } void route_drop(Route *route) { assert(route); route_free(route); } int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; assert(link); assert(link->manager); assert(link->manager->rtnl); assert(link->ifindex > 0); assert(route->family == AF_INET || route->family == AF_INET6); r = sd_rtnl_message_new_route(link->manager->rtnl, &req, RTM_DELROUTE, route->family, route->protocol); if (r < 0) return log_error_errno(r, "Could not create RTM_DELROUTE message: %m"); if (!in_addr_is_null(route->family, &route->gw)) { if (route->family == AF_INET) r = sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &route->gw.in); else if (route->family == AF_INET6) r = sd_netlink_message_append_in6_addr(req, RTA_GATEWAY, &route->gw.in6); if (r < 0) return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m"); } if (route->dst_prefixlen) { if (route->family == AF_INET) r = sd_netlink_message_append_in_addr(req, RTA_DST, &route->dst.in); else if (route->family == AF_INET6) r = sd_netlink_message_append_in6_addr(req, RTA_DST, &route->dst.in6); if (r < 0) return log_error_errno(r, "Could not append RTA_DST attribute: %m"); r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen); if (r < 0) return log_error_errno(r, "Could not set destination prefix length: %m"); } if (route->src_prefixlen) { if (route->family == AF_INET) r = sd_netlink_message_append_in_addr(req, RTA_SRC, &route->src.in); else if (route->family == AF_INET6) r = sd_netlink_message_append_in6_addr(req, RTA_SRC, &route->src.in6); if (r < 0) return log_error_errno(r, "Could not append RTA_DST attribute: %m"); r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen); if (r < 0) return log_error_errno(r, "Could not set source prefix length: %m"); } if (!in_addr_is_null(route->family, &route->prefsrc)) { if (route->family == AF_INET) r = sd_netlink_message_append_in_addr(req, RTA_PREFSRC, &route->prefsrc.in); else if (route->family == AF_INET6) r = sd_netlink_message_append_in6_addr(req, RTA_PREFSRC, &route->prefsrc.in6); if (r < 0) return log_error_errno(r, "Could not append RTA_PREFSRC attribute: %m"); } r = sd_rtnl_message_route_set_scope(req, route->scope); if (r < 0) return log_error_errno(r, "Could not set scope: %m"); r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority); if (r < 0) return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m"); r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex); if (r < 0) return log_error_errno(r, "Could not append RTA_OIF attribute: %m"); r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL); if (r < 0) return log_error_errno(r, "Could not send rtnetlink message: %m"); link_ref(link); return 0; } int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) { Route *route = userdata; int r; assert(route); r = route_remove(route, route->link, NULL); if (r < 0) log_warning_errno(r, "Could not remove route: %m"); return 1; } int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; usec_t lifetime; int r; assert(link); assert(link->manager); assert(link->manager->rtnl); assert(link->ifindex > 0); assert(route->family == AF_INET || route->family == AF_INET6); r = sd_rtnl_message_new_route(link->manager->rtnl, &req, RTM_NEWROUTE, route->family, route->protocol); if (r < 0) return log_error_errno(r, "Could not create RTM_NEWROUTE message: %m"); if (!in_addr_is_null(route->family, &route->gw)) { if (route->family == AF_INET) r = sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &route->gw.in); else if (route->family == AF_INET6) r = sd_netlink_message_append_in6_addr(req, RTA_GATEWAY, &route->gw.in6); if (r < 0) return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m"); } if (route->dst_prefixlen) { if (route->family == AF_INET) r = sd_netlink_message_append_in_addr(req, RTA_DST, &route->dst.in); else if (route->family == AF_INET6) r = sd_netlink_message_append_in6_addr(req, RTA_DST, &route->dst.in6); if (r < 0) return log_error_errno(r, "Could not append RTA_DST attribute: %m"); r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen); if (r < 0) return log_error_errno(r, "Could not set destination prefix length: %m"); } if (route->src_prefixlen) { if (route->family == AF_INET) r = sd_netlink_message_append_in_addr(req, RTA_SRC, &route->src.in); else if (route->family == AF_INET6) r = sd_netlink_message_append_in6_addr(req, RTA_SRC, &route->src.in6); if (r < 0) return log_error_errno(r, "Could not append RTA_SRC attribute: %m"); r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen); if (r < 0) return log_error_errno(r, "Could not set source prefix length: %m"); } if (!in_addr_is_null(route->family, &route->prefsrc)) { if (route->family == AF_INET) r = sd_netlink_message_append_in_addr(req, RTA_PREFSRC, &route->prefsrc.in); else if (route->family == AF_INET6) r = sd_netlink_message_append_in6_addr(req, RTA_PREFSRC, &route->prefsrc.in6); if (r < 0) return log_error_errno(r, "Could not append RTA_PREFSRC attribute: %m"); } r = sd_rtnl_message_route_set_scope(req, route->scope); if (r < 0) return log_error_errno(r, "Could not set scope: %m"); r = sd_rtnl_message_route_set_flags(req, route->flags); if (r < 0) return log_error_errno(r, "Colud not set flags: %m"); r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority); if (r < 0) return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m"); r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref); if (r < 0) return log_error_errno(r, "Could not append RTA_PREF attribute: %m"); r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex); if (r < 0) return log_error_errno(r, "Could not append RTA_OIF attribute: %m"); r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL); if (r < 0) return log_error_errno(r, "Could not send rtnetlink message: %m"); link_ref(link); lifetime = route->lifetime; r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, &route); if (r < 0) return log_error_errno(r, "Could not add route: %m"); /* TODO: drop expiration handling once it can be pushed into the kernel */ route->lifetime = lifetime; if (route->lifetime != USEC_INFINITY) { r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), route->lifetime, 0, route_expire_handler, route); if (r < 0) return log_error_errno(r, "Could not arm expiration timer: %m"); } sd_event_source_unref(route->expire); route->expire = expire; expire = NULL; return 0; } int config_parse_gateway(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *network = userdata; _cleanup_route_free_ Route *n = NULL; union in_addr_union buffer; int r, f; assert(filename); assert(section); assert(lvalue); assert(rvalue); assert(data); if (streq(section, "Network")) { /* we are not in an Route section, so treat * this as the special '0' section */ section_line = 0; } r = route_new_static(network, section_line, &n); if (r < 0) return r; r = in_addr_from_string_auto(rvalue, &f, &buffer); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Route is invalid, ignoring assignment: %s", rvalue); return 0; } n->family = f; n->gw = buffer; n = NULL; return 0; } int config_parse_preferred_src(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *network = userdata; _cleanup_route_free_ Route *n = NULL; union in_addr_union buffer; int r, f; assert(filename); assert(section); assert(lvalue); assert(rvalue); assert(data); r = route_new_static(network, section_line, &n); if (r < 0) return r; r = in_addr_from_string_auto(rvalue, &f, &buffer); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Preferred source is invalid, ignoring assignment: %s", rvalue); return 0; } n->family = f; n->prefsrc = buffer; n = NULL; return 0; } int config_parse_destination(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *network = userdata; _cleanup_route_free_ Route *n = NULL; const char *address, *e; union in_addr_union buffer; unsigned char prefixlen; int r, f; assert(filename); assert(section); assert(lvalue); assert(rvalue); assert(data); r = route_new_static(network, section_line, &n); if (r < 0) return r; /* Destination|Source=address/prefixlen */ /* address */ e = strchr(rvalue, '/'); if (e) address = strndupa(rvalue, e - rvalue); else address = rvalue; r = in_addr_from_string_auto(address, &f, &buffer); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Destination is invalid, ignoring assignment: %s", address); return 0; } if (f != AF_INET && f != AF_INET6) { log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown address family, ignoring assignment: %s", address); return 0; } /* prefixlen */ if (e) { r = safe_atou8(e + 1, &prefixlen); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Route destination prefix length is invalid, ignoring assignment: %s", e + 1); return 0; } } else { switch (f) { case AF_INET: prefixlen = 32; break; case AF_INET6: prefixlen = 128; break; } } n->family = f; if (streq(lvalue, "Destination")) { n->dst = buffer; n->dst_prefixlen = prefixlen; } else if (streq(lvalue, "Source")) { n->src = buffer; n->src_prefixlen = prefixlen; } else assert_not_reached(lvalue); n = NULL; return 0; } int config_parse_route_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *network = userdata; _cleanup_route_free_ Route *n = NULL; int r; assert(filename); assert(section); assert(lvalue); assert(rvalue); assert(data); r = route_new_static(network, section_line, &n); if (r < 0) return r; r = config_parse_uint32(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &n->priority, userdata); if (r < 0) return r; n = NULL; return 0; } int config_parse_route_scope(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Network *network = userdata; _cleanup_route_free_ Route *n = NULL; int r; assert(filename); assert(section); assert(lvalue); assert(rvalue); assert(data); r = route_new_static(network, section_line, &n); if (r < 0) return r; if (streq(rvalue, "host")) n->scope = RT_SCOPE_HOST; else if (streq(rvalue, "link")) n->scope = RT_SCOPE_LINK; else if (streq(rvalue, "global")) n->scope = RT_SCOPE_UNIVERSE; else { log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown route scope: %s", rvalue); return 0; } n = NULL; return 0; } systemd-229/src/network/networkd-route.h000066400000000000000000000072371265713322000205140ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Route Route; #include "networkd-network.h" #include "networkd.h" struct Route { Network *network; unsigned section; Link *link; int family; unsigned char dst_prefixlen; unsigned char src_prefixlen; unsigned char scope; unsigned char protocol; /* RTPROT_* */ unsigned char tos; uint32_t priority; /* note that ip(8) calls this 'metric' */ unsigned char table; unsigned char pref; unsigned flags; union in_addr_union gw; union in_addr_union dst; union in_addr_union src; union in_addr_union prefsrc; usec_t lifetime; sd_event_source *expire; LIST_FIELDS(Route, routes); }; int route_new_static(Network *network, unsigned section, Route **ret); int route_new(Route **ret); void route_free(Route *route); int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback); int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback); int route_get(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); int route_add(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); int route_add_foreign(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); int route_update(Route *route, union in_addr_union *src, unsigned char src_prefixlen, union in_addr_union *gw, union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol); void route_drop(Route *route); int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata); DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free); #define _cleanup_route_free_ _cleanup_(route_freep) int config_parse_gateway(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_preferred_src(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_destination(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_route_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_route_scope(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); systemd-229/src/network/networkd-util.c000066400000000000000000000063051265713322000203210ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "conf-parser.h" #include "networkd-util.h" #include "parse-util.h" #include "string-table.h" #include "string-util.h" #include "util.h" const char *address_family_boolean_to_string(AddressFamilyBoolean b) { if (b == ADDRESS_FAMILY_YES || b == ADDRESS_FAMILY_NO) return yes_no(b == ADDRESS_FAMILY_YES); if (b == ADDRESS_FAMILY_IPV4) return "ipv4"; if (b == ADDRESS_FAMILY_IPV6) return "ipv6"; return NULL; } AddressFamilyBoolean address_family_boolean_from_string(const char *s) { int r; /* Make this a true superset of a boolean */ r = parse_boolean(s); if (r > 0) return ADDRESS_FAMILY_YES; if (r == 0) return ADDRESS_FAMILY_NO; if (streq(s, "ipv4")) return ADDRESS_FAMILY_IPV4; if (streq(s, "ipv6")) return ADDRESS_FAMILY_IPV6; return _ADDRESS_FAMILY_BOOLEAN_INVALID; } DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option"); int config_parse_address_family_boolean_with_kernel( const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { AddressFamilyBoolean *fwd = data, s; assert(filename); assert(lvalue); assert(rvalue); assert(data); /* This function is mostly obsolete now. It simply redirects * "kernel" to "no". In older networkd versions we used to * distuingish IPForward=off from IPForward=kernel, where the * former would explicitly turn off forwarding while the * latter would simply not touch the setting. But that logic * is gone, hence silently accept the old setting, but turn it * to "no". */ s = address_family_boolean_from_string(rvalue); if (s < 0) { if (streq(rvalue, "kernel")) s = ADDRESS_FAMILY_NO; else { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPForward= option, ignoring: %s", rvalue); return 0; } } *fwd = s; return 0; } systemd-229/src/network/networkd-util.h000066400000000000000000000032661265713322000203310ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "macro.h" typedef enum AddressFamilyBoolean { /* This is a bitmask, though it usually doesn't feel that way! */ ADDRESS_FAMILY_NO = 0, ADDRESS_FAMILY_IPV4 = 1, ADDRESS_FAMILY_IPV6 = 2, ADDRESS_FAMILY_YES = 3, _ADDRESS_FAMILY_BOOLEAN_MAX, _ADDRESS_FAMILY_BOOLEAN_INVALID = -1, } AddressFamilyBoolean; int config_parse_address_family_boolean(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_address_family_boolean_with_kernel(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_; AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_; systemd-229/src/network/networkd-wait-online-link.c000066400000000000000000000063701265713322000225270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-network.h" #include "alloc-util.h" #include "networkd-wait-online-link.h" #include "string-util.h" int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) { _cleanup_(link_freep) Link *l = NULL; int r; assert(m); assert(ifindex > 0); r = hashmap_ensure_allocated(&m->links, NULL); if (r < 0) return r; r = hashmap_ensure_allocated(&m->links_by_name, &string_hash_ops); if (r < 0) return r; l = new0(Link, 1); if (!l) return -ENOMEM; l->manager = m; l->ifname = strdup(ifname); if (!l->ifname) return -ENOMEM; r = hashmap_put(m->links_by_name, l->ifname, l); if (r < 0) return r; l->ifindex = ifindex; r = hashmap_put(m->links, INT_TO_PTR(ifindex), l); if (r < 0) return r; if (ret) *ret = l; l = NULL; return 0; } Link *link_free(Link *l) { if (!l) return NULL; if (l->manager) { hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex)); hashmap_remove(l->manager->links_by_name, l->ifname); } free(l->ifname); free(l); return NULL; } int link_update_rtnl(Link *l, sd_netlink_message *m) { const char *ifname; int r; assert(l); assert(l->manager); assert(m); r = sd_rtnl_message_link_get_flags(m, &l->flags); if (r < 0) return r; r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname); if (r < 0) return r; if (!streq(l->ifname, ifname)) { char *new_ifname; new_ifname = strdup(ifname); if (!new_ifname) return -ENOMEM; hashmap_remove(l->manager->links_by_name, l->ifname); free(l->ifname); l->ifname = new_ifname; r = hashmap_put(l->manager->links_by_name, l->ifname, l); if (r < 0) return r; } return 0; } int link_update_monitor(Link *l) { assert(l); l->operational_state = mfree(l->operational_state); sd_network_link_get_operational_state(l->ifindex, &l->operational_state); l->state = mfree(l->state); sd_network_link_get_setup_state(l->ifindex, &l->state); return 0; } systemd-229/src/network/networkd-wait-online-link.h000066400000000000000000000023471265713322000225340ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct Link Link; #include "networkd-wait-online.h" struct Link { Manager *manager; int ifindex; char *ifname; unsigned flags; char *operational_state; char *state; }; int link_new(Manager *m, Link **ret, int ifindex, const char *ifname); Link *link_free(Link *l); int link_update_rtnl(Link *l, sd_netlink_message *m); int link_update_monitor(Link *l); bool link_relevant(Link *l); DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free); systemd-229/src/network/networkd-wait-online-manager.c000066400000000000000000000221131265713322000231750ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "netlink-util.h" #include "network-internal.h" #include "networkd-wait-online-link.h" #include "networkd-wait-online.h" #include "time-util.h" #include "util.h" bool manager_ignore_link(Manager *m, Link *link) { char **ignore; assert(m); assert(link); /* always ignore the loopback interface */ if (link->flags & IFF_LOOPBACK) return true; /* if interfaces are given on the command line, ignore all others */ if (m->interfaces && !strv_contains(m->interfaces, link->ifname)) return true; /* ignore interfaces we explicitly are asked to ignore */ STRV_FOREACH(ignore, m->ignore) if (fnmatch(*ignore, link->ifname, 0) == 0) return true; return false; } bool manager_all_configured(Manager *m) { Iterator i; Link *l; char **ifname; bool one_ready = false; /* wait for all the links given on the command line to appear */ STRV_FOREACH(ifname, m->interfaces) { l = hashmap_get(m->links_by_name, *ifname); if (!l) { log_debug("still waiting for %s", *ifname); return false; } } /* wait for all links networkd manages to be in admin state 'configured' and at least one link to gain a carrier */ HASHMAP_FOREACH(l, m->links, i) { if (manager_ignore_link(m, l)) { log_info("ignoring: %s", l->ifname); continue; } if (!l->state) { log_debug("link %s has not yet been processed by udev", l->ifname); return false; } if (STR_IN_SET(l->state, "configuring", "pending")) { log_debug("link %s is being processed by networkd", l->ifname); return false; } if (l->operational_state && STR_IN_SET(l->operational_state, "degraded", "routable")) /* we wait for at least one link to be ready, regardless of who manages it */ one_ready = true; } return one_ready; } static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) { Manager *m = userdata; uint16_t type; Link *l; const char *ifname; int ifindex, r; assert(rtnl); assert(m); assert(mm); r = sd_netlink_message_get_type(mm, &type); if (r < 0) goto fail; r = sd_rtnl_message_link_get_ifindex(mm, &ifindex); if (r < 0) goto fail; r = sd_netlink_message_read_string(mm, IFLA_IFNAME, &ifname); if (r < 0) goto fail; l = hashmap_get(m->links, INT_TO_PTR(ifindex)); switch (type) { case RTM_NEWLINK: if (!l) { log_debug("Found link %i", ifindex); r = link_new(m, &l, ifindex, ifname); if (r < 0) goto fail; r = link_update_monitor(l); if (r < 0) goto fail; } r = link_update_rtnl(l, mm); if (r < 0) goto fail; break; case RTM_DELLINK: if (l) { log_debug("Removing link %i", l->ifindex); link_free(l); } break; } return 0; fail: log_warning_errno(r, "Failed to process RTNL link message: %m"); return 0; } static int on_rtnl_event(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) { Manager *m = userdata; int r; r = manager_process_link(rtnl, mm, m); if (r < 0) return r; if (manager_all_configured(m)) sd_event_exit(m->event, 0); return 1; } static int manager_rtnl_listen(Manager *m) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; sd_netlink_message *i; int r; assert(m); /* First, subscribe to interfaces coming and going */ r = sd_netlink_open(&m->rtnl); if (r < 0) return r; r = sd_netlink_attach_event(m->rtnl, m->event, 0); if (r < 0) return r; r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, on_rtnl_event, m); if (r < 0) return r; r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, on_rtnl_event, m); if (r < 0) return r; /* Then, enumerate all links */ r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0); if (r < 0) return r; r = sd_netlink_message_request_dump(req, true); if (r < 0) return r; r = sd_netlink_call(m->rtnl, req, 0, &reply); if (r < 0) return r; for (i = reply; i; i = sd_netlink_message_next(i)) { r = manager_process_link(m->rtnl, i, m); if (r < 0) return r; } return r; } static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; Iterator i; Link *l; int r; assert(m); sd_network_monitor_flush(m->network_monitor); HASHMAP_FOREACH(l, m->links, i) { r = link_update_monitor(l); if (r < 0) log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex); } if (manager_all_configured(m)) sd_event_exit(m->event, 0); return 0; } static int manager_network_monitor_listen(Manager *m) { int r, fd, events; assert(m); r = sd_network_monitor_new(&m->network_monitor, NULL); if (r < 0) return r; fd = sd_network_monitor_get_fd(m->network_monitor); if (fd < 0) return fd; events = sd_network_monitor_get_events(m->network_monitor); if (events < 0) return events; r = sd_event_add_io(m->event, &m->network_monitor_event_source, fd, events, &on_network_event, m); if (r < 0) return r; return 0; } int manager_new(Manager **ret, char **interfaces, char **ignore, usec_t timeout) { _cleanup_(manager_freep) Manager *m = NULL; int r; assert(ret); m = new0(Manager, 1); if (!m) return -ENOMEM; m->interfaces = interfaces; m->ignore = ignore; r = sd_event_default(&m->event); if (r < 0) return r; sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); if (timeout > 0) { usec_t usec; usec = now(clock_boottime_or_monotonic()) + timeout; r = sd_event_add_time(m->event, NULL, clock_boottime_or_monotonic(), usec, 0, NULL, INT_TO_PTR(-ETIMEDOUT)); if (r < 0) return r; } sd_event_set_watchdog(m->event, true); r = manager_network_monitor_listen(m); if (r < 0) return r; r = manager_rtnl_listen(m); if (r < 0) return r; *ret = m; m = NULL; return 0; } void manager_free(Manager *m) { Link *l; if (!m) return; while ((l = hashmap_first(m->links))) link_free(l); hashmap_free(m->links); hashmap_free(m->links_by_name); sd_event_source_unref(m->network_monitor_event_source); sd_network_monitor_unref(m->network_monitor); sd_event_source_unref(m->rtnl_event_source); sd_netlink_unref(m->rtnl); sd_event_unref(m->event); free(m); return; } systemd-229/src/network/networkd-wait-online.c000066400000000000000000000115641265713322000215750ustar00rootroot00000000000000 /*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-daemon.h" #include "networkd-wait-online.h" #include "signal-util.h" #include "strv.h" static bool arg_quiet = false; static usec_t arg_timeout = 120 * USEC_PER_SEC; static char **arg_interfaces = NULL; static char **arg_ignore = NULL; static void help(void) { printf("%s [OPTIONS...]\n\n" "Block until network is configured.\n\n" " -h --help Show this help\n" " --version Print version string\n" " -q --quiet Do not show status information\n" " -i --interface=INTERFACE Block until at least these interfaces have appeared\n" " --ignore=INTERFACE Don't take these interfaces into account\n" " --timeout=SECS Maximum time to wait for network connectivity\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_IGNORE, ARG_TIMEOUT, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "quiet", no_argument, NULL, 'q' }, { "interface", required_argument, NULL, 'i' }, { "ignore", required_argument, NULL, ARG_IGNORE }, { "timeout", required_argument, NULL, ARG_TIMEOUT }, {} }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "+hi:q", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case 'q': arg_quiet = true; break; case ARG_VERSION: return version(); case 'i': if (strv_extend(&arg_interfaces, optarg) < 0) return log_oom(); break; case ARG_IGNORE: if (strv_extend(&arg_ignore, optarg) < 0) return log_oom(); break; case ARG_TIMEOUT: r = parse_sec(optarg, &arg_timeout); if (r < 0) return r; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } int main(int argc, char *argv[]) { _cleanup_(manager_freep) Manager *m = NULL; int r; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); r = parse_argv(argc, argv); if (r <= 0) return r; if (arg_quiet) log_set_max_level(LOG_WARNING); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); r = manager_new(&m, arg_interfaces, arg_ignore, arg_timeout); if (r < 0) { log_error_errno(r, "Could not create manager: %m"); goto finish; } if (manager_all_configured(m)) { r = 0; goto finish; } sd_notify(false, "READY=1\n" "STATUS=Waiting for network connections..."); r = sd_event_loop(m->event); if (r < 0) { log_error_errno(r, "Event loop failed: %m"); goto finish; } finish: strv_free(arg_interfaces); strv_free(arg_ignore); if (r >= 0) { sd_notify(false, "STATUS=All interfaces configured..."); return EXIT_SUCCESS; } else { sd_notify(false, "STATUS=Failed waiting for network connectivity..."); return EXIT_FAILURE; } } systemd-229/src/network/networkd-wait-online.h000066400000000000000000000027251265713322000216010ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "sd-event.h" #include "sd-netlink.h" #include "sd-network.h" #include "hashmap.h" typedef struct Manager Manager; #include "networkd-wait-online-link.h" struct Manager { Hashmap *links; Hashmap *links_by_name; char **interfaces; char **ignore; sd_netlink *rtnl; sd_event_source *rtnl_event_source; sd_network_monitor *network_monitor; sd_event_source *network_monitor_event_source; sd_event *event; }; void manager_free(Manager *m); int manager_new(Manager **ret, char **interfaces, char **ignore, usec_t timeout); DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); bool manager_all_configured(Manager *m); bool manager_ignore_link(Manager *m, Link *link); systemd-229/src/network/networkd.c000066400000000000000000000101211265713322000173350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-daemon.h" #include "capability-util.h" #include "networkd.h" #include "signal-util.h" #include "user-util.h" int main(int argc, char *argv[]) { _cleanup_manager_free_ Manager *m = NULL; const char *user = "systemd-network"; uid_t uid; gid_t gid; int r; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); if (argc != 1) { log_error("This program takes no arguments."); r = -EINVAL; goto out; } r = get_user_creds(&user, &uid, &gid, NULL, NULL); if (r < 0) { log_error_errno(r, "Cannot resolve user name %s: %m", user); goto out; } /* Always create the directories people can create inotify * watches in. */ r = mkdir_safe_label("/run/systemd/netif", 0755, uid, gid); if (r < 0) log_warning_errno(r, "Could not create runtime directory: %m"); r = mkdir_safe_label("/run/systemd/netif/links", 0755, uid, gid); if (r < 0) log_warning_errno(r, "Could not create runtime directory 'links': %m"); r = mkdir_safe_label("/run/systemd/netif/leases", 0755, uid, gid); if (r < 0) log_warning_errno(r, "Could not create runtime directory 'leases': %m"); r = mkdir_safe_label("/run/systemd/netif/lldp", 0755, uid, gid); if (r < 0) log_warning_errno(r, "Could not create runtime directory 'lldp': %m"); r = drop_privileges(uid, gid, (1ULL << CAP_NET_ADMIN) | (1ULL << CAP_NET_BIND_SERVICE) | (1ULL << CAP_NET_BROADCAST) | (1ULL << CAP_NET_RAW)); if (r < 0) goto out; assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); r = manager_new(&m); if (r < 0) { log_error_errno(r, "Could not create manager: %m"); goto out; } r = manager_connect_bus(m); if (r < 0) { log_error_errno(r, "Could not connect to bus: %m"); goto out; } r = manager_load_config(m); if (r < 0) { log_error_errno(r, "Could not load configuration files: %m"); goto out; } r = manager_rtnl_enumerate_links(m); if (r < 0) { log_error_errno(r, "Could not enumerate links: %m"); goto out; } r = manager_rtnl_enumerate_addresses(m); if (r < 0) { log_error_errno(r, "Could not enumerate addresses: %m"); goto out; } r = manager_rtnl_enumerate_routes(m); if (r < 0) { log_error_errno(r, "Could not enumerate routes: %m"); goto out; } log_info("Enumeration completed"); sd_notify(false, "READY=1\n" "STATUS=Processing requests..."); r = manager_run(m); if (r < 0) { log_error_errno(r, "Event loop failed: %m"); goto out; } out: sd_notify(false, "STOPPING=1\n" "STATUS=Shutting down..."); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/network/networkd.h000066400000000000000000000052541265713322000173550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include #include "sd-bus.h" #include "sd-event.h" #include "sd-netlink.h" #include "hashmap.h" #include "list.h" #include "udev.h" typedef struct Manager Manager; #include "networkd-address-pool.h" #include "networkd-link.h" #include "networkd-network.h" #include "networkd-util.h" struct Manager { sd_netlink *rtnl; sd_event *event; sd_event_source *bus_retry_event_source; sd_bus *bus; sd_bus_slot *prepare_for_sleep_slot; struct udev *udev; struct udev_monitor *udev_monitor; sd_event_source *udev_event_source; bool enumerating:1; bool dirty:1; Set *dirty_links; char *state_file; LinkOperationalState operational_state; Hashmap *links; Hashmap *netdevs; Hashmap *networks_by_name; LIST_HEAD(Network, networks); LIST_HEAD(AddressPool, address_pools); usec_t network_dirs_ts_usec; }; extern const char* const network_dirs[]; /* Manager */ extern const sd_bus_vtable manager_vtable[]; int manager_new(Manager **ret); void manager_free(Manager *m); int manager_connect_bus(Manager *m); int manager_run(Manager *m); int manager_load_config(Manager *m); bool manager_should_reload(Manager *m); int manager_rtnl_enumerate_links(Manager *m); int manager_rtnl_enumerate_addresses(Manager *m); int manager_rtnl_enumerate_routes(Manager *m); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, void *userdata); int manager_rtnl_process_route(sd_netlink *nl, sd_netlink_message *message, void *userdata); int manager_send_changed(Manager *m, const char *property, ...) _sentinel_; void manager_dirty(Manager *m); int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found); Link* manager_find_uplink(Manager *m, Link *exclude); DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); #define _cleanup_manager_free_ _cleanup_(manager_freep) systemd-229/src/network/org.freedesktop.network1.conf000066400000000000000000000031041265713322000230600ustar00rootroot00000000000000 systemd-229/src/network/org.freedesktop.network1.service000066400000000000000000000006411265713322000235760ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] Name=org.freedesktop.network1 Exec=/bin/false User=root SystemdService=dbus-org.freedesktop.network1.service systemd-229/src/network/test-network-tables.c000066400000000000000000000017051265713322000214260ustar00rootroot00000000000000#include "dhcp6-internal.h" #include "dhcp6-protocol.h" #include "ethtool-util.h" #include "netlink-internal.h" #include "networkd-netdev-bond.h" #include "networkd-netdev-macvlan.h" #include "networkd.h" #include "test-tables.h" int main(int argc, char **argv) { test_table(bond_mode, NETDEV_BOND_MODE); /* test_table(link_state, LINK_STATE); -- not a reversible mapping */ test_table(link_operstate, LINK_OPERSTATE); test_table(address_family_boolean, ADDRESS_FAMILY_BOOLEAN); test_table(netdev_kind, NETDEV_KIND); test_table(dhcp6_message_status, DHCP6_STATUS); test_table(duplex, DUP); test_table(wol, WOL); test_table(nl_union_link_info_data, NL_UNION_LINK_INFO_DATA); test_table_sparse(macvlan_mode, NETDEV_MACVLAN_MODE); test_table_sparse(ipvlan_mode, NETDEV_IPVLAN_MODE); test_table_sparse(dhcp6_message_type, DHCP6_MESSAGE); return EXIT_SUCCESS; } systemd-229/src/network/test-network.c000066400000000000000000000201451265713322000201550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "dhcp-lease-internal.h" #include "network-internal.h" #include "networkd.h" static void test_deserialize_in_addr(void) { _cleanup_free_ struct in_addr *addresses = NULL; _cleanup_free_ struct in6_addr *addresses6 = NULL; struct in_addr a, b, c; struct in6_addr d, e, f; int size; const char *addresses_string = "192.168.0.1 0:0:0:0:0:FFFF:204.152.189.116 192.168.0.2 ::1 192.168.0.3 1:0:0:0:0:0:0:8"; assert_se(inet_pton(AF_INET, "0:0:0:0:0:FFFF:204.152.189.116", &a) == 0); assert_se(inet_pton(AF_INET6, "192.168.0.1", &d) == 0); assert_se(inet_pton(AF_INET, "192.168.0.1", &a) == 1); assert_se(inet_pton(AF_INET, "192.168.0.2", &b) == 1); assert_se(inet_pton(AF_INET, "192.168.0.3", &c) == 1); assert_se(inet_pton(AF_INET6, "0:0:0:0:0:FFFF:204.152.189.116", &d) == 1); assert_se(inet_pton(AF_INET6, "::1", &e) == 1); assert_se(inet_pton(AF_INET6, "1:0:0:0:0:0:0:8", &f) == 1); assert_se((size = deserialize_in_addrs(&addresses, addresses_string)) >= 0); assert_se(size == 3); assert_se(!memcmp(&a, &addresses[0], sizeof(struct in_addr))); assert_se(!memcmp(&b, &addresses[1], sizeof(struct in_addr))); assert_se(!memcmp(&c, &addresses[2], sizeof(struct in_addr))); assert_se((size = deserialize_in6_addrs(&addresses6, addresses_string)) >= 0); assert_se(size == 3); assert_se(!memcmp(&d, &addresses6[0], sizeof(struct in6_addr))); assert_se(!memcmp(&e, &addresses6[1], sizeof(struct in6_addr))); assert_se(!memcmp(&f, &addresses6[2], sizeof(struct in6_addr))); } static void test_deserialize_dhcp_routes(void) { size_t size, allocated; { _cleanup_free_ struct sd_dhcp_route *routes = NULL; assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, "") >= 0); assert_se(size == 0); } { /* no errors */ _cleanup_free_ struct sd_dhcp_route *routes = NULL; const char *routes_string = "192.168.0.0/16,192.168.0.1 10.1.2.0/24,10.1.2.1 0.0.0.0/0,10.0.1.1"; assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, routes_string) >= 0); assert_se(size == 3); assert_se(routes[0].dst_addr.s_addr == inet_addr("192.168.0.0")); assert_se(routes[0].gw_addr.s_addr == inet_addr("192.168.0.1")); assert_se(routes[0].dst_prefixlen == 16); assert_se(routes[1].dst_addr.s_addr == inet_addr("10.1.2.0")); assert_se(routes[1].gw_addr.s_addr == inet_addr("10.1.2.1")); assert_se(routes[1].dst_prefixlen == 24); assert_se(routes[2].dst_addr.s_addr == inet_addr("0.0.0.0")); assert_se(routes[2].gw_addr.s_addr == inet_addr("10.0.1.1")); assert_se(routes[2].dst_prefixlen == 0); } { /* error in second word */ _cleanup_free_ struct sd_dhcp_route *routes = NULL; const char *routes_string = "192.168.0.0/16,192.168.0.1 10.1.2.0#24,10.1.2.1 0.0.0.0/0,10.0.1.1"; assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, routes_string) >= 0); assert_se(size == 2); assert_se(routes[0].dst_addr.s_addr == inet_addr("192.168.0.0")); assert_se(routes[0].gw_addr.s_addr == inet_addr("192.168.0.1")); assert_se(routes[0].dst_prefixlen == 16); assert_se(routes[1].dst_addr.s_addr == inet_addr("0.0.0.0")); assert_se(routes[1].gw_addr.s_addr == inet_addr("10.0.1.1")); assert_se(routes[1].dst_prefixlen == 0); } { /* error in every word */ _cleanup_free_ struct sd_dhcp_route *routes = NULL; const char *routes_string = "192.168.0.0/55,192.168.0.1 10.1.2.0#24,10.1.2.1 0.0.0.0/0,10.0.1.X"; assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, routes_string) >= 0); assert_se(size == 0); } } static int test_load_config(Manager *manager) { int r; /* TODO: should_reload, is false if the config dirs do not exist, so * so we can't do this test here, move it to a test for paths_check_timestamps * directly * * assert_se(network_should_reload(manager) == true); */ r = manager_load_config(manager); if (r == -EPERM) return r; assert_se(r >= 0); assert_se(manager_should_reload(manager) == false); return 0; } static void test_network_get(Manager *manager, struct udev_device *loopback) { Network *network; const struct ether_addr mac = {}; /* let's assume that the test machine does not have a .network file that applies to the loopback device... */ assert_se(network_get(manager, loopback, "lo", &mac, &network) == -ENOENT); assert_se(!network); } static void test_address_equality(void) { _cleanup_address_free_ Address *a1 = NULL, *a2 = NULL; assert_se(address_new(&a1) >= 0); assert_se(address_new(&a2) >= 0); assert_se(address_equal(NULL, NULL)); assert_se(!address_equal(a1, NULL)); assert_se(!address_equal(NULL, a2)); assert_se(address_equal(a1, a2)); a1->family = AF_INET; assert_se(!address_equal(a1, a2)); a2->family = AF_INET; assert_se(address_equal(a1, a2)); assert_se(inet_pton(AF_INET, "192.168.3.9", &a1->in_addr.in)); assert_se(!address_equal(a1, a2)); assert_se(inet_pton(AF_INET, "192.168.3.9", &a2->in_addr.in)); assert_se(address_equal(a1, a2)); assert_se(inet_pton(AF_INET, "192.168.3.10", &a1->in_addr_peer.in)); assert_se(address_equal(a1, a2)); assert_se(inet_pton(AF_INET, "192.168.3.11", &a2->in_addr_peer.in)); assert_se(address_equal(a1, a2)); a1->prefixlen = 10; assert_se(!address_equal(a1, a2)); a2->prefixlen = 10; assert_se(address_equal(a1, a2)); a1->family = AF_INET6; assert_se(!address_equal(a1, a2)); a2->family = AF_INET6; assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a1->in_addr.in6)); assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a2->in_addr.in6)); assert_se(address_equal(a1, a2)); a2->prefixlen = 8; assert_se(address_equal(a1, a2)); assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::1", &a2->in_addr.in6)); assert_se(!address_equal(a1, a2)); } int main(void) { _cleanup_manager_free_ Manager *manager = NULL; struct udev *udev; struct udev_device *loopback; int r; test_deserialize_in_addr(); test_deserialize_dhcp_routes(); test_address_equality(); assert_se(manager_new(&manager) >= 0); r = test_load_config(manager); if (r == -EPERM) return EXIT_TEST_SKIP; udev = udev_new(); assert_se(udev); loopback = udev_device_new_from_syspath(udev, "/sys/class/net/lo"); assert_se(loopback); assert_se(udev_device_get_ifindex(loopback) == 1); test_network_get(manager, loopback); assert_se(manager_rtnl_enumerate_links(manager) >= 0); udev_device_unref(loopback); udev_unref(udev); } systemd-229/src/notify/000077500000000000000000000000001265713322000151605ustar00rootroot00000000000000systemd-229/src/notify/Makefile000077700000000000000000000000001265713322000204662../Makefileustar00rootroot00000000000000systemd-229/src/notify/notify.c000066400000000000000000000133541265713322000166420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-daemon.h" #include "alloc-util.h" #include "env-util.h" #include "formats-util.h" #include "log.h" #include "parse-util.h" #include "string-util.h" #include "strv.h" #include "util.h" static bool arg_ready = false; static pid_t arg_pid = 0; static const char *arg_status = NULL; static bool arg_booted = false; static void help(void) { printf("%s [OPTIONS...] [VARIABLE=VALUE...]\n\n" "Notify the init system about service status updates.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --ready Inform the init system about service start-up completion\n" " --pid[=PID] Set main pid of daemon\n" " --status=TEXT Set status text\n" " --booted Check if the system was booted up with systemd\n", program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_READY = 0x100, ARG_VERSION, ARG_PID, ARG_STATUS, ARG_BOOTED, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "ready", no_argument, NULL, ARG_READY }, { "pid", optional_argument, NULL, ARG_PID }, { "status", required_argument, NULL, ARG_STATUS }, { "booted", no_argument, NULL, ARG_BOOTED }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) { switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_READY: arg_ready = true; break; case ARG_PID: if (optarg) { if (parse_pid(optarg, &arg_pid) < 0) { log_error("Failed to parse PID %s.", optarg); return -EINVAL; } } else arg_pid = getppid(); break; case ARG_STATUS: arg_status = optarg; break; case ARG_BOOTED: arg_booted = true; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } } if (optind >= argc && !arg_ready && !arg_status && !arg_pid && !arg_booted) { help(); return -EINVAL; } return 1; } int main(int argc, char* argv[]) { _cleanup_free_ char *status = NULL, *cpid = NULL, *n = NULL; _cleanup_strv_free_ char **final_env = NULL; char* our_env[4]; unsigned i = 0; int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; if (arg_booted) return sd_booted() <= 0; if (arg_ready) our_env[i++] = (char*) "READY=1"; if (arg_status) { status = strappend("STATUS=", arg_status); if (!status) { r = log_oom(); goto finish; } our_env[i++] = status; } if (arg_pid > 0) { if (asprintf(&cpid, "MAINPID="PID_FMT, arg_pid) < 0) { r = log_oom(); goto finish; } our_env[i++] = cpid; } our_env[i++] = NULL; final_env = strv_env_merge(2, our_env, argv + optind); if (!final_env) { r = log_oom(); goto finish; } if (strv_length(final_env) <= 0) { r = 0; goto finish; } n = strv_join(final_env, "\n"); if (!n) { r = log_oom(); goto finish; } r = sd_pid_notify(arg_pid ? arg_pid : getppid(), false, n); if (r < 0) { log_error_errno(r, "Failed to notify init system: %m"); goto finish; } else if (r == 0) { log_error("No status data could be sent: $NOTIFY_SOCKET was not set"); r = -EOPNOTSUPP; } finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/nspawn/000077500000000000000000000000001265713322000151565ustar00rootroot00000000000000systemd-229/src/nspawn/.gitignore000066400000000000000000000000201265713322000171360ustar00rootroot00000000000000/nspawn-gperf.c systemd-229/src/nspawn/Makefile000077700000000000000000000000001265713322000204642../Makefileustar00rootroot00000000000000systemd-229/src/nspawn/nspawn-cgroup.c000066400000000000000000000136261265713322000201350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "cgroup-util.h" #include "fd-util.h" #include "fileio.h" #include "mkdir.h" #include "nspawn-cgroup.h" #include "string-util.h" #include "strv.h" #include "util.h" int chown_cgroup(pid_t pid, uid_t uid_shift) { _cleanup_free_ char *path = NULL, *fs = NULL; _cleanup_close_ int fd = -1; const char *fn; int r; r = cg_pid_get_path(NULL, pid, &path); if (r < 0) return log_error_errno(r, "Failed to get container cgroup path: %m"); r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs); if (r < 0) return log_error_errno(r, "Failed to get file system path for container cgroup: %m"); fd = open(fs, O_RDONLY|O_CLOEXEC|O_DIRECTORY); if (fd < 0) return log_error_errno(errno, "Failed to open %s: %m", fs); FOREACH_STRING(fn, ".", "tasks", "notify_on_release", "cgroup.procs", "cgroup.events", "cgroup.clone_children", "cgroup.controllers", "cgroup.subtree_control", "cgroup.populated") if (fchownat(fd, fn, uid_shift, uid_shift, 0) < 0) log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, "Failed to chown() cgroup file %s, ignoring: %m", fn); return 0; } int sync_cgroup(pid_t pid, bool unified_requested) { _cleanup_free_ char *cgroup = NULL; char tree[] = "/tmp/unifiedXXXXXX", pid_string[DECIMAL_STR_MAX(pid) + 1]; bool undo_mount = false; const char *fn; int unified, r; unified = cg_unified(); if (unified < 0) return log_error_errno(unified, "Failed to determine whether the unified hierachy is used: %m"); if ((unified > 0) == unified_requested) return 0; /* When the host uses the legacy cgroup setup, but the * container shall use the unified hierarchy, let's make sure * we copy the path from the name=systemd hierarchy into the * unified hierarchy. Similar for the reverse situation. */ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup); if (r < 0) return log_error_errno(r, "Failed to get control group of " PID_FMT ": %m", pid); /* In order to access the unified hierarchy we need to mount it */ if (!mkdtemp(tree)) return log_error_errno(errno, "Failed to generate temporary mount point for unified hierarchy: %m"); if (unified) r = mount("cgroup", tree, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr"); else r = mount("cgroup", tree, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "__DEVEL__sane_behavior"); if (r < 0) { r = log_error_errno(errno, "Failed to mount unified hierarchy: %m"); goto finish; } undo_mount = true; fn = strjoina(tree, cgroup, "/cgroup.procs"); (void) mkdir_parents(fn, 0755); sprintf(pid_string, PID_FMT, pid); r = write_string_file(fn, pid_string, 0); if (r < 0) log_error_errno(r, "Failed to move process: %m"); finish: if (undo_mount) (void) umount(tree); (void) rmdir(tree); return r; } int create_subcgroup(pid_t pid, bool unified_requested) { _cleanup_free_ char *cgroup = NULL; const char *child; int unified, r; CGroupMask supported; /* In the unified hierarchy inner nodes may only only contain * subgroups, but not processes. Hence, if we running in the * unified hierarchy and the container does the same, and we * did not create a scope unit for the container move us and * the container into two separate subcgroups. */ if (!unified_requested) return 0; unified = cg_unified(); if (unified < 0) return log_error_errno(unified, "Failed to determine whether the unified hierachy is used: %m"); if (unified == 0) return 0; r = cg_mask_supported(&supported); if (r < 0) return log_error_errno(r, "Failed to determine supported controllers: %m"); r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup); if (r < 0) return log_error_errno(r, "Failed to get our control group: %m"); child = strjoina(cgroup, "/payload"); r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, child, pid); if (r < 0) return log_error_errno(r, "Failed to create %s subcgroup: %m", child); child = strjoina(cgroup, "/supervisor"); r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, child, 0); if (r < 0) return log_error_errno(r, "Failed to create %s subcgroup: %m", child); /* Try to enable as many controllers as possible for the new payload. */ (void) cg_enable_everywhere(supported, supported, cgroup); return 0; } systemd-229/src/nspawn/nspawn-cgroup.h000066400000000000000000000016451265713322000201400ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include int chown_cgroup(pid_t pid, uid_t uid_shift); int sync_cgroup(pid_t pid, bool unified_requested); int create_subcgroup(pid_t pid, bool unified_requested); systemd-229/src/nspawn/nspawn-expose-ports.c000066400000000000000000000162211265713322000213000ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-netlink.h" #include "alloc-util.h" #include "fd-util.h" #include "firewall-util.h" #include "in-addr-util.h" #include "local-addresses.h" #include "netlink-util.h" #include "nspawn-expose-ports.h" #include "parse-util.h" #include "socket-util.h" #include "string-util.h" #include "util.h" int expose_port_parse(ExposePort **l, const char *s) { const char *split, *e; uint16_t container_port, host_port; int protocol; ExposePort *p; int r; assert(l); assert(s); if ((e = startswith(s, "tcp:"))) protocol = IPPROTO_TCP; else if ((e = startswith(s, "udp:"))) protocol = IPPROTO_UDP; else { e = s; protocol = IPPROTO_TCP; } split = strchr(e, ':'); if (split) { char v[split - e + 1]; memcpy(v, e, split - e); v[split - e] = 0; r = safe_atou16(v, &host_port); if (r < 0 || host_port <= 0) return -EINVAL; r = safe_atou16(split + 1, &container_port); } else { r = safe_atou16(e, &container_port); host_port = container_port; } if (r < 0 || container_port <= 0) return -EINVAL; LIST_FOREACH(ports, p, *l) if (p->protocol == protocol && p->host_port == host_port) return -EEXIST; p = new(ExposePort, 1); if (!p) return -ENOMEM; p->protocol = protocol; p->host_port = host_port; p->container_port = container_port; LIST_PREPEND(ports, *l, p); return 0; } void expose_port_free_all(ExposePort *p) { while (p) { ExposePort *q = p; LIST_REMOVE(ports, p, q); free(q); } } int expose_port_flush(ExposePort* l, union in_addr_union *exposed) { ExposePort *p; int r, af = AF_INET; assert(exposed); if (!l) return 0; if (in_addr_is_null(af, exposed)) return 0; log_debug("Lost IP address."); LIST_FOREACH(ports, p, l) { r = fw_add_local_dnat(false, af, p->protocol, NULL, NULL, 0, NULL, 0, p->host_port, exposed, p->container_port, NULL); if (r < 0) log_warning_errno(r, "Failed to modify firewall: %m"); } *exposed = IN_ADDR_NULL; return 0; } int expose_port_execute(sd_netlink *rtnl, ExposePort *l, union in_addr_union *exposed) { _cleanup_free_ struct local_address *addresses = NULL; _cleanup_free_ char *pretty = NULL; union in_addr_union new_exposed; ExposePort *p; bool add; int af = AF_INET, r; assert(exposed); /* Invoked each time an address is added or removed inside the * container */ if (!l) return 0; r = local_addresses(rtnl, 0, af, &addresses); if (r < 0) return log_error_errno(r, "Failed to enumerate local addresses: %m"); add = r > 0 && addresses[0].family == af && addresses[0].scope < RT_SCOPE_LINK; if (!add) return expose_port_flush(l, exposed); new_exposed = addresses[0].address; if (in_addr_equal(af, exposed, &new_exposed)) return 0; in_addr_to_string(af, &new_exposed, &pretty); log_debug("New container IP is %s.", strna(pretty)); LIST_FOREACH(ports, p, l) { r = fw_add_local_dnat(true, af, p->protocol, NULL, NULL, 0, NULL, 0, p->host_port, &new_exposed, p->container_port, in_addr_is_null(af, exposed) ? NULL : exposed); if (r < 0) log_warning_errno(r, "Failed to modify firewall: %m"); } *exposed = new_exposed; return 0; } int expose_port_send_rtnl(int send_fd) { _cleanup_close_ int fd = -1; int r; assert(send_fd >= 0); fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_ROUTE); if (fd < 0) return log_error_errno(errno, "Failed to allocate container netlink: %m"); /* Store away the fd in the socket, so that it stays open as * long as we run the child */ r = send_one_fd(send_fd, fd, 0); if (r < 0) return log_error_errno(r, "Failed to send netlink fd: %m"); return 0; } int expose_port_watch_rtnl( sd_event *event, int recv_fd, sd_netlink_message_handler_t handler, union in_addr_union *exposed, sd_netlink **ret) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; int fd, r; assert(event); assert(recv_fd >= 0); assert(ret); fd = receive_one_fd(recv_fd, 0); if (fd < 0) return log_error_errno(fd, "Failed to recv netlink fd: %m"); r = sd_netlink_open_fd(&rtnl, fd); if (r < 0) { safe_close(fd); return log_error_errno(r, "Failed to create rtnl object: %m"); } r = sd_netlink_add_match(rtnl, RTM_NEWADDR, handler, exposed); if (r < 0) return log_error_errno(r, "Failed to subscribe to RTM_NEWADDR messages: %m"); r = sd_netlink_add_match(rtnl, RTM_DELADDR, handler, exposed); if (r < 0) return log_error_errno(r, "Failed to subscribe to RTM_DELADDR messages: %m"); r = sd_netlink_attach_event(rtnl, event, 0); if (r < 0) return log_error_errno(r, "Failed to add to even loop: %m"); *ret = rtnl; rtnl = NULL; return 0; } systemd-229/src/nspawn/nspawn-expose-ports.h000066400000000000000000000026631265713322000213120ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-event.h" #include "sd-netlink.h" #include "in-addr-util.h" #include "list.h" typedef struct ExposePort { int protocol; uint16_t host_port; uint16_t container_port; LIST_FIELDS(struct ExposePort, ports); } ExposePort; void expose_port_free_all(ExposePort *p); int expose_port_parse(ExposePort **l, const char *s); int expose_port_watch_rtnl(sd_event *event, int recv_fd, sd_netlink_message_handler_t handler, union in_addr_union *exposed, sd_netlink **ret); int expose_port_send_rtnl(int send_fd); int expose_port_execute(sd_netlink *rtnl, ExposePort *l, union in_addr_union *exposed); int expose_port_flush(ExposePort* l, union in_addr_union *exposed); systemd-229/src/nspawn/nspawn-gperf.gperf000066400000000000000000000045441265713322000206210ustar00rootroot00000000000000%{ #include #include "conf-parser.h" #include "nspawn-settings.h" #include "nspawn-expose-ports.h" %} struct ConfigPerfItem; %null_strings %language=ANSI-C %define slot-name section_and_lvalue %define hash-function-name nspawn_gperf_hash %define lookup-function-name nspawn_gperf_lookup %readonly-tables %omit-struct-type %struct-type %includes %% Exec.Boot, config_parse_boot, 0, 0 Exec.ProcessTwo, config_parse_pid2, 0, 0, Exec.Parameters, config_parse_strv, 0, offsetof(Settings, parameters) Exec.Environment, config_parse_strv, 0, offsetof(Settings, environment) Exec.User, config_parse_string, 0, offsetof(Settings, user) Exec.Capability, config_parse_capability, 0, offsetof(Settings, capability) Exec.DropCapability, config_parse_capability, 0, offsetof(Settings, drop_capability) Exec.KillSignal, config_parse_signal, 0, offsetof(Settings, kill_signal) Exec.Personality, config_parse_personality, 0, offsetof(Settings, personality) Exec.MachineID, config_parse_id128, 0, offsetof(Settings, machine_id) Exec.WorkingDirectory, config_parse_path, 0, offsetof(Settings, working_directory) Files.ReadOnly, config_parse_tristate, 0, offsetof(Settings, read_only) Files.Volatile, config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode) Files.Bind, config_parse_bind, 0, 0 Files.BindReadOnly, config_parse_bind, 1, 0 Files.TemporaryFileSystem, config_parse_tmpfs, 0, 0 Network.Private, config_parse_tristate, 0, offsetof(Settings, private_network) Network.Interface, config_parse_strv, 0, offsetof(Settings, network_interfaces) Network.MACVLAN, config_parse_strv, 0, offsetof(Settings, network_macvlan) Network.IPVLAN, config_parse_strv, 0, offsetof(Settings, network_ipvlan) Network.VirtualEthernet, config_parse_tristate, 0, offsetof(Settings, network_veth) Network.VirtualEthernetExtra, config_parse_veth_extra, 0, 0 Network.Bridge, config_parse_string, 0, offsetof(Settings, network_bridge) Network.Port, config_parse_expose_port, 0, 0 systemd-229/src/nspawn/nspawn-mount.c000066400000000000000000000763071265713322000200050ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "cgroup-util.h" #include "escape.h" #include "fs-util.h" #include "label.h" #include "mkdir.h" #include "mount-util.h" #include "nspawn-mount.h" #include "parse-util.h" #include "path-util.h" #include "rm-rf.h" #include "set.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" #include "user-util.h" #include "util.h" CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t) { CustomMount *c, *ret; assert(l); assert(n); assert(t >= 0); assert(t < _CUSTOM_MOUNT_TYPE_MAX); c = realloc(*l, (*n + 1) * sizeof(CustomMount)); if (!c) return NULL; *l = c; ret = *l + *n; (*n)++; *ret = (CustomMount) { .type = t }; return ret; } void custom_mount_free_all(CustomMount *l, unsigned n) { unsigned i; for (i = 0; i < n; i++) { CustomMount *m = l + i; free(m->source); free(m->destination); free(m->options); if (m->work_dir) { (void) rm_rf(m->work_dir, REMOVE_ROOT|REMOVE_PHYSICAL); free(m->work_dir); } strv_free(m->lower); } free(l); } int custom_mount_compare(const void *a, const void *b) { const CustomMount *x = a, *y = b; int r; r = path_compare(x->destination, y->destination); if (r != 0) return r; if (x->type < y->type) return -1; if (x->type > y->type) return 1; return 0; } int bind_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only) { _cleanup_free_ char *source = NULL, *destination = NULL, *opts = NULL; const char *p = s; CustomMount *m; int r; assert(l); assert(n); r = extract_many_words(&p, ":", EXTRACT_DONT_COALESCE_SEPARATORS, &source, &destination, NULL); if (r < 0) return r; if (r == 0) return -EINVAL; if (r == 1) { destination = strdup(source); if (!destination) return -ENOMEM; } if (r == 2 && !isempty(p)) { opts = strdup(p); if (!opts) return -ENOMEM; } if (!path_is_absolute(source)) return -EINVAL; if (!path_is_absolute(destination)) return -EINVAL; m = custom_mount_add(l, n, CUSTOM_MOUNT_BIND); if (!m) return log_oom(); m->source = source; m->destination = destination; m->read_only = read_only; m->options = opts; source = destination = opts = NULL; return 0; } int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s) { _cleanup_free_ char *path = NULL, *opts = NULL; const char *p = s; CustomMount *m; int r; assert(l); assert(n); assert(s); r = extract_first_word(&p, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS); if (r < 0) return r; if (r == 0) return -EINVAL; if (isempty(p)) opts = strdup("mode=0755"); else opts = strdup(p); if (!opts) return -ENOMEM; if (!path_is_absolute(path)) return -EINVAL; m = custom_mount_add(l, n, CUSTOM_MOUNT_TMPFS); if (!m) return -ENOMEM; m->destination = path; m->options = opts; path = opts = NULL; return 0; } static int tmpfs_patch_options( const char *options, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, char **ret) { char *buf = NULL; if (userns && uid_shift != 0) { assert(uid_shift != UID_INVALID); if (options) (void) asprintf(&buf, "%s,uid=" UID_FMT ",gid=" UID_FMT, options, uid_shift, uid_shift); else (void) asprintf(&buf, "uid=" UID_FMT ",gid=" UID_FMT, uid_shift, uid_shift); if (!buf) return -ENOMEM; options = buf; } #ifdef HAVE_SELINUX if (selinux_apifs_context) { char *t; if (options) t = strjoin(options, ",context=\"", selinux_apifs_context, "\"", NULL); else t = strjoin("context=\"", selinux_apifs_context, "\"", NULL); if (!t) { free(buf); return -ENOMEM; } free(buf); buf = t; } #endif *ret = buf; return !!buf; } int mount_sysfs(const char *dest) { const char *full, *top, *x; int r; top = prefix_roota(dest, "/sys"); r = path_check_fstype(top, SYSFS_MAGIC); if (r < 0) return log_error_errno(r, "Failed to determine filesystem type of %s: %m", top); /* /sys might already be mounted as sysfs by the outer child in the * !netns case. In this case, it's all good. Don't touch it because we * don't have the right to do so, see https://github.com/systemd/systemd/issues/1555. */ if (r > 0) return 0; full = prefix_roota(top, "/full"); (void) mkdir(full, 0755); if (mount("sysfs", full, "sysfs", MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) < 0) return log_error_errno(errno, "Failed to mount sysfs to %s: %m", full); FOREACH_STRING(x, "block", "bus", "class", "dev", "devices", "kernel") { _cleanup_free_ char *from = NULL, *to = NULL; from = prefix_root(full, x); if (!from) return log_oom(); to = prefix_root(top, x); if (!to) return log_oom(); (void) mkdir(to, 0755); if (mount(from, to, NULL, MS_BIND, NULL) < 0) return log_error_errno(errno, "Failed to mount /sys/%s into place: %m", x); if (mount(NULL, to, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL) < 0) return log_error_errno(errno, "Failed to mount /sys/%s read-only: %m", x); } if (umount(full) < 0) return log_error_errno(errno, "Failed to unmount %s: %m", full); if (rmdir(full) < 0) return log_error_errno(errno, "Failed to remove %s: %m", full); x = prefix_roota(top, "/fs/kdbus"); (void) mkdir(x, 0755); if (mount(NULL, top, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL) < 0) return log_error_errno(errno, "Failed to make %s read-only: %m", top); return 0; } int mount_all(const char *dest, bool use_userns, bool in_userns, bool use_netns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context) { typedef struct MountPoint { const char *what; const char *where; const char *type; const char *options; unsigned long flags; bool fatal; bool in_userns; bool use_netns; } MountPoint; static const MountPoint mount_table[] = { { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true, true, false }, { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true, true, false }, /* Bind mount first */ { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, true, true, false }, /* Then, make it r/o */ { "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false, true }, { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false, false }, { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false, false }, { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false, false }, { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false, false }, { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true, false, false }, #ifdef HAVE_SELINUX { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false, false, false }, /* Bind mount first */ { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, false, false, false }, /* Then, make it r/o */ #endif }; unsigned k; int r; for (k = 0; k < ELEMENTSOF(mount_table); k++) { _cleanup_free_ char *where = NULL, *options = NULL; const char *o; if (in_userns != mount_table[k].in_userns) continue; if (!use_netns && mount_table[k].use_netns) continue; where = prefix_root(dest, mount_table[k].where); if (!where) return log_oom(); r = path_is_mount_point(where, AT_SYMLINK_FOLLOW); if (r < 0 && r != -ENOENT) return log_error_errno(r, "Failed to detect whether %s is a mount point: %m", where); /* Skip this entry if it is not a remount. */ if (mount_table[k].what && r > 0) continue; r = mkdir_p(where, 0755); if (r < 0) { if (mount_table[k].fatal) return log_error_errno(r, "Failed to create directory %s: %m", where); log_warning_errno(r, "Failed to create directory %s: %m", where); continue; } o = mount_table[k].options; if (streq_ptr(mount_table[k].type, "tmpfs")) { r = tmpfs_patch_options(o, use_userns, uid_shift, uid_range, selinux_apifs_context, &options); if (r < 0) return log_oom(); if (r > 0) o = options; } if (mount(mount_table[k].what, where, mount_table[k].type, mount_table[k].flags, o) < 0) { if (mount_table[k].fatal) return log_error_errno(errno, "mount(%s) failed: %m", where); log_warning_errno(errno, "mount(%s) failed, ignoring: %m", where); } } return 0; } static int parse_mount_bind_options(const char *options, unsigned long *mount_flags, char **mount_opts) { const char *p = options; unsigned long flags = *mount_flags; char *opts = NULL; assert(options); for (;;) { _cleanup_free_ char *word = NULL; int r = extract_first_word(&p, &word, ",", 0); if (r < 0) return log_error_errno(r, "Failed to extract mount option: %m"); if (r == 0) break; if (streq(word, "rbind")) flags |= MS_REC; else if (streq(word, "norbind")) flags &= ~MS_REC; else { log_error("Invalid bind mount option: %s", word); return -EINVAL; } } *mount_flags = flags; /* in the future mount_opts will hold string options for mount(2) */ *mount_opts = opts; return 0; } static int mount_bind(const char *dest, CustomMount *m) { struct stat source_st, dest_st; const char *where; unsigned long mount_flags = MS_BIND | MS_REC; _cleanup_free_ char *mount_opts = NULL; int r; assert(m); if (m->options) { r = parse_mount_bind_options(m->options, &mount_flags, &mount_opts); if (r < 0) return r; } if (stat(m->source, &source_st) < 0) return log_error_errno(errno, "Failed to stat %s: %m", m->source); where = prefix_roota(dest, m->destination); if (stat(where, &dest_st) >= 0) { if (S_ISDIR(source_st.st_mode) && !S_ISDIR(dest_st.st_mode)) { log_error("Cannot bind mount directory %s on file %s.", m->source, where); return -EINVAL; } if (!S_ISDIR(source_st.st_mode) && S_ISDIR(dest_st.st_mode)) { log_error("Cannot bind mount file %s on directory %s.", m->source, where); return -EINVAL; } } else if (errno == ENOENT) { r = mkdir_parents_label(where, 0755); if (r < 0) return log_error_errno(r, "Failed to make parents of %s: %m", where); } else { return log_error_errno(errno, "Failed to stat %s: %m", where); } /* Create the mount point. Any non-directory file can be * mounted on any non-directory file (regular, fifo, socket, * char, block). */ if (S_ISDIR(source_st.st_mode)) r = mkdir_label(where, 0755); else r = touch(where); if (r < 0 && r != -EEXIST) return log_error_errno(r, "Failed to create mount point %s: %m", where); if (mount(m->source, where, NULL, mount_flags, mount_opts) < 0) return log_error_errno(errno, "mount(%s) failed: %m", where); if (m->read_only) { r = bind_remount_recursive(where, true); if (r < 0) return log_error_errno(r, "Read-only bind mount failed: %m"); } return 0; } static int mount_tmpfs( const char *dest, CustomMount *m, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context) { const char *where, *options; _cleanup_free_ char *buf = NULL; int r; assert(dest); assert(m); where = prefix_roota(dest, m->destination); r = mkdir_p_label(where, 0755); if (r < 0 && r != -EEXIST) return log_error_errno(r, "Creating mount point for tmpfs %s failed: %m", where); r = tmpfs_patch_options(m->options, userns, uid_shift, uid_range, selinux_apifs_context, &buf); if (r < 0) return log_oom(); options = r > 0 ? buf : m->options; if (mount("tmpfs", where, "tmpfs", MS_NODEV|MS_STRICTATIME, options) < 0) return log_error_errno(errno, "tmpfs mount to %s failed: %m", where); return 0; } static char *joined_and_escaped_lower_dirs(char * const *lower) { _cleanup_strv_free_ char **sv = NULL; sv = strv_copy(lower); if (!sv) return NULL; strv_reverse(sv); if (!strv_shell_escape(sv, ",:")) return NULL; return strv_join(sv, ":"); } static int mount_overlay(const char *dest, CustomMount *m) { _cleanup_free_ char *lower = NULL; const char *where, *options; int r; assert(dest); assert(m); where = prefix_roota(dest, m->destination); r = mkdir_label(where, 0755); if (r < 0 && r != -EEXIST) return log_error_errno(r, "Creating mount point for overlay %s failed: %m", where); (void) mkdir_p_label(m->source, 0755); lower = joined_and_escaped_lower_dirs(m->lower); if (!lower) return log_oom(); if (m->read_only) { _cleanup_free_ char *escaped_source = NULL; escaped_source = shell_escape(m->source, ",:"); if (!escaped_source) return log_oom(); options = strjoina("lowerdir=", escaped_source, ":", lower); } else { _cleanup_free_ char *escaped_source = NULL, *escaped_work_dir = NULL; assert(m->work_dir); (void) mkdir_label(m->work_dir, 0700); escaped_source = shell_escape(m->source, ",:"); if (!escaped_source) return log_oom(); escaped_work_dir = shell_escape(m->work_dir, ",:"); if (!escaped_work_dir) return log_oom(); options = strjoina("lowerdir=", lower, ",upperdir=", escaped_source, ",workdir=", escaped_work_dir); } if (mount("overlay", where, "overlay", m->read_only ? MS_RDONLY : 0, options) < 0) return log_error_errno(errno, "overlay mount to %s failed: %m", where); return 0; } int mount_custom( const char *dest, CustomMount *mounts, unsigned n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context) { unsigned i; int r; assert(dest); for (i = 0; i < n; i++) { CustomMount *m = mounts + i; switch (m->type) { case CUSTOM_MOUNT_BIND: r = mount_bind(dest, m); break; case CUSTOM_MOUNT_TMPFS: r = mount_tmpfs(dest, m, userns, uid_shift, uid_range, selinux_apifs_context); break; case CUSTOM_MOUNT_OVERLAY: r = mount_overlay(dest, m); break; default: assert_not_reached("Unknown custom mount type"); } if (r < 0) return r; } return 0; } static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controller, const char *hierarchy, bool read_only) { char *to; int r; to = strjoina(strempty(dest), "/sys/fs/cgroup/", hierarchy); r = path_is_mount_point(to, 0); if (r < 0 && r != -ENOENT) return log_error_errno(r, "Failed to determine if %s is mounted already: %m", to); if (r > 0) return 0; mkdir_p(to, 0755); /* The superblock mount options of the mount point need to be * identical to the hosts', and hence writable... */ if (mount("cgroup", to, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, controller) < 0) return log_error_errno(errno, "Failed to mount to %s: %m", to); /* ... hence let's only make the bind mount read-only, not the * superblock. */ if (read_only) { if (mount(NULL, to, NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL) < 0) return log_error_errno(errno, "Failed to remount %s read-only: %m", to); } return 1; } static int mount_legacy_cgroups( const char *dest, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context) { _cleanup_set_free_free_ Set *controllers = NULL; const char *cgroup_root; int r; cgroup_root = prefix_roota(dest, "/sys/fs/cgroup"); (void) mkdir_p(cgroup_root, 0755); /* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */ r = path_is_mount_point(cgroup_root, AT_SYMLINK_FOLLOW); if (r < 0) return log_error_errno(r, "Failed to determine if /sys/fs/cgroup is already mounted: %m"); if (r == 0) { _cleanup_free_ char *options = NULL; r = tmpfs_patch_options("mode=755", userns, uid_shift, uid_range, selinux_apifs_context, &options); if (r < 0) return log_oom(); if (mount("tmpfs", cgroup_root, "tmpfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options) < 0) return log_error_errno(errno, "Failed to mount /sys/fs/cgroup: %m"); } if (cg_unified() > 0) goto skip_controllers; controllers = set_new(&string_hash_ops); if (!controllers) return log_oom(); r = cg_kernel_controllers(controllers); if (r < 0) return log_error_errno(r, "Failed to determine cgroup controllers: %m"); for (;;) { _cleanup_free_ char *controller = NULL, *origin = NULL, *combined = NULL; controller = set_steal_first(controllers); if (!controller) break; origin = prefix_root("/sys/fs/cgroup/", controller); if (!origin) return log_oom(); r = readlink_malloc(origin, &combined); if (r == -EINVAL) { /* Not a symbolic link, but directly a single cgroup hierarchy */ r = mount_legacy_cgroup_hierarchy(dest, controller, controller, true); if (r < 0) return r; } else if (r < 0) return log_error_errno(r, "Failed to read link %s: %m", origin); else { _cleanup_free_ char *target = NULL; target = prefix_root(dest, origin); if (!target) return log_oom(); /* A symbolic link, a combination of controllers in one hierarchy */ if (!filename_is_valid(combined)) { log_warning("Ignoring invalid combined hierarchy %s.", combined); continue; } r = mount_legacy_cgroup_hierarchy(dest, combined, combined, true); if (r < 0) return r; r = symlink_idempotent(combined, target); if (r == -EINVAL) { log_error("Invalid existing symlink for combined hierarchy"); return r; } if (r < 0) return log_error_errno(r, "Failed to create symlink for combined hierarchy: %m"); } } skip_controllers: r = mount_legacy_cgroup_hierarchy(dest, "none,name=systemd,xattr", "systemd", false); if (r < 0) return r; if (mount(NULL, cgroup_root, NULL, MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755") < 0) return log_error_errno(errno, "Failed to remount %s read-only: %m", cgroup_root); return 0; } static int mount_unified_cgroups(const char *dest) { const char *p; int r; assert(dest); p = prefix_roota(dest, "/sys/fs/cgroup"); (void) mkdir_p(p, 0755); r = path_is_mount_point(p, AT_SYMLINK_FOLLOW); if (r < 0) return log_error_errno(r, "Failed to determine if %s is mounted already: %m", p); if (r > 0) { p = prefix_roota(dest, "/sys/fs/cgroup/cgroup.procs"); if (access(p, F_OK) >= 0) return 0; if (errno != ENOENT) return log_error_errno(errno, "Failed to determine if mount point %s contains the unified cgroup hierarchy: %m", p); log_error("%s is already mounted but not a unified cgroup hierarchy. Refusing.", p); return -EINVAL; } if (mount("cgroup", p, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "__DEVEL__sane_behavior") < 0) return log_error_errno(errno, "Failed to mount unified cgroup hierarchy to %s: %m", p); return 0; } int mount_cgroups( const char *dest, bool unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context) { if (unified_requested) return mount_unified_cgroups(dest); else return mount_legacy_cgroups(dest, userns, uid_shift, uid_range, selinux_apifs_context); } int mount_systemd_cgroup_writable( const char *dest, bool unified_requested) { _cleanup_free_ char *own_cgroup_path = NULL; const char *systemd_root, *systemd_own; int r; assert(dest); r = cg_pid_get_path(NULL, 0, &own_cgroup_path); if (r < 0) return log_error_errno(r, "Failed to determine our own cgroup path: %m"); /* If we are living in the top-level, then there's nothing to do... */ if (path_equal(own_cgroup_path, "/")) return 0; if (unified_requested) { systemd_own = strjoina(dest, "/sys/fs/cgroup", own_cgroup_path); systemd_root = prefix_roota(dest, "/sys/fs/cgroup"); } else { systemd_own = strjoina(dest, "/sys/fs/cgroup/systemd", own_cgroup_path); systemd_root = prefix_roota(dest, "/sys/fs/cgroup/systemd"); } /* Make our own cgroup a (writable) bind mount */ if (mount(systemd_own, systemd_own, NULL, MS_BIND, NULL) < 0) return log_error_errno(errno, "Failed to turn %s into a bind mount: %m", own_cgroup_path); /* And then remount the systemd cgroup root read-only */ if (mount(NULL, systemd_root, NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL) < 0) return log_error_errno(errno, "Failed to mount cgroup root read-only: %m"); return 0; } int setup_volatile_state( const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context) { _cleanup_free_ char *buf = NULL; const char *p, *options; int r; assert(directory); if (mode != VOLATILE_STATE) return 0; /* --volatile=state means we simply overmount /var with a tmpfs, and the rest read-only. */ r = bind_remount_recursive(directory, true); if (r < 0) return log_error_errno(r, "Failed to remount %s read-only: %m", directory); p = prefix_roota(directory, "/var"); r = mkdir(p, 0755); if (r < 0 && errno != EEXIST) return log_error_errno(errno, "Failed to create %s: %m", directory); options = "mode=755"; r = tmpfs_patch_options(options, userns, uid_shift, uid_range, selinux_apifs_context, &buf); if (r < 0) return log_oom(); if (r > 0) options = buf; if (mount("tmpfs", p, "tmpfs", MS_STRICTATIME, options) < 0) return log_error_errno(errno, "Failed to mount tmpfs to /var: %m"); return 0; } int setup_volatile( const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context) { bool tmpfs_mounted = false, bind_mounted = false; char template[] = "/tmp/nspawn-volatile-XXXXXX"; _cleanup_free_ char *buf = NULL; const char *f, *t, *options; int r; assert(directory); if (mode != VOLATILE_YES) return 0; /* --volatile=yes means we mount a tmpfs to the root dir, and the original /usr to use inside it, and that read-only. */ if (!mkdtemp(template)) return log_error_errno(errno, "Failed to create temporary directory: %m"); options = "mode=755"; r = tmpfs_patch_options(options, userns, uid_shift, uid_range, selinux_apifs_context, &buf); if (r < 0) return log_oom(); if (r > 0) options = buf; if (mount("tmpfs", template, "tmpfs", MS_STRICTATIME, options) < 0) { r = log_error_errno(errno, "Failed to mount tmpfs for root directory: %m"); goto fail; } tmpfs_mounted = true; f = prefix_roota(directory, "/usr"); t = prefix_roota(template, "/usr"); r = mkdir(t, 0755); if (r < 0 && errno != EEXIST) { r = log_error_errno(errno, "Failed to create %s: %m", t); goto fail; } if (mount(f, t, NULL, MS_BIND|MS_REC, NULL) < 0) { r = log_error_errno(errno, "Failed to create /usr bind mount: %m"); goto fail; } bind_mounted = true; r = bind_remount_recursive(t, true); if (r < 0) { log_error_errno(r, "Failed to remount %s read-only: %m", t); goto fail; } if (mount(template, directory, NULL, MS_MOVE, NULL) < 0) { r = log_error_errno(errno, "Failed to move root mount: %m"); goto fail; } (void) rmdir(template); return 0; fail: if (bind_mounted) (void) umount(t); if (tmpfs_mounted) (void) umount(template); (void) rmdir(template); return r; } VolatileMode volatile_mode_from_string(const char *s) { int b; if (isempty(s)) return _VOLATILE_MODE_INVALID; b = parse_boolean(s); if (b > 0) return VOLATILE_YES; if (b == 0) return VOLATILE_NO; if (streq(s, "state")) return VOLATILE_STATE; return _VOLATILE_MODE_INVALID; } systemd-229/src/nspawn/nspawn-mount.h000066400000000000000000000051441265713322000200010ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include typedef enum VolatileMode { VOLATILE_NO, VOLATILE_YES, VOLATILE_STATE, _VOLATILE_MODE_MAX, _VOLATILE_MODE_INVALID = -1 } VolatileMode; typedef enum CustomMountType { CUSTOM_MOUNT_BIND, CUSTOM_MOUNT_TMPFS, CUSTOM_MOUNT_OVERLAY, _CUSTOM_MOUNT_TYPE_MAX, _CUSTOM_MOUNT_TYPE_INVALID = -1 } CustomMountType; typedef struct CustomMount { CustomMountType type; bool read_only; char *source; /* for overlayfs this is the upper directory */ char *destination; char *options; char *work_dir; char **lower; } CustomMount; CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t); void custom_mount_free_all(CustomMount *l, unsigned n); int bind_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only); int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s); int custom_mount_compare(const void *a, const void *b); int mount_all(const char *dest, bool use_userns, bool in_userns, bool use_netns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); int mount_sysfs(const char *dest); int mount_cgroups(const char *dest, bool unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); int mount_systemd_cgroup_writable(const char *dest, bool unified_requested); int mount_custom(const char *dest, CustomMount *mounts, unsigned n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); int setup_volatile(const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); int setup_volatile_state(const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); VolatileMode volatile_mode_from_string(const char *s); systemd-229/src/nspawn/nspawn-network.c000066400000000000000000000455711265713322000203330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "libudev.h" #include "sd-id128.h" #include "sd-netlink.h" #include "alloc-util.h" #include "ether-addr-util.h" #include "netlink-util.h" #include "nspawn-network.h" #include "siphash24.h" #include "string-util.h" #include "udev-util.h" #include "util.h" #define HOST_HASH_KEY SD_ID128_MAKE(1a,37,6f,c7,46,ec,45,0b,ad,a3,d5,31,06,60,5d,b1) #define CONTAINER_HASH_KEY SD_ID128_MAKE(c3,c4,f9,19,b5,57,b2,1c,e6,cf,14,27,03,9c,ee,a2) #define VETH_EXTRA_HOST_HASH_KEY SD_ID128_MAKE(48,c7,f6,b7,ea,9d,4c,9e,b7,28,d4,de,91,d5,bf,66) #define VETH_EXTRA_CONTAINER_HASH_KEY SD_ID128_MAKE(af,50,17,61,ce,f9,4d,35,84,0d,2b,20,54,be,ce,59) #define MACVLAN_HASH_KEY SD_ID128_MAKE(00,13,6d,bc,66,83,44,81,bb,0c,f9,51,1f,24,a6,6f) static int generate_mac( const char *machine_name, struct ether_addr *mac, sd_id128_t hash_key, uint64_t idx) { uint64_t result; size_t l, sz; uint8_t *v, *i; int r; l = strlen(machine_name); sz = sizeof(sd_id128_t) + l; if (idx > 0) sz += sizeof(idx); v = alloca(sz); /* fetch some persistent data unique to the host */ r = sd_id128_get_machine((sd_id128_t*) v); if (r < 0) return r; /* combine with some data unique (on this host) to this * container instance */ i = mempcpy(v + sizeof(sd_id128_t), machine_name, l); if (idx > 0) { idx = htole64(idx); memcpy(i, &idx, sizeof(idx)); } /* Let's hash the host machine ID plus the container name. We * use a fixed, but originally randomly created hash key here. */ result = htole64(siphash24(v, sz, hash_key.bytes)); assert_cc(ETH_ALEN <= sizeof(result)); memcpy(mac->ether_addr_octet, &result, ETH_ALEN); /* see eth_random_addr in the kernel */ mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */ mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */ return 0; } static int add_veth( sd_netlink *rtnl, pid_t pid, const char *ifname_host, const struct ether_addr *mac_host, const char *ifname_container, const struct ether_addr *mac_container) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; assert(rtnl); assert(ifname_host); assert(mac_host); assert(ifname_container); assert(mac_container); r = sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0); if (r < 0) return log_error_errno(r, "Failed to allocate netlink message: %m"); r = sd_netlink_message_append_string(m, IFLA_IFNAME, ifname_host); if (r < 0) return log_error_errno(r, "Failed to add netlink interface name: %m"); r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, mac_host); if (r < 0) return log_error_errno(r, "Failed to add netlink MAC address: %m"); r = sd_netlink_message_open_container(m, IFLA_LINKINFO); if (r < 0) return log_error_errno(r, "Failed to open netlink container: %m"); r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "veth"); if (r < 0) return log_error_errno(r, "Failed to open netlink container: %m"); r = sd_netlink_message_open_container(m, VETH_INFO_PEER); if (r < 0) return log_error_errno(r, "Failed to open netlink container: %m"); r = sd_netlink_message_append_string(m, IFLA_IFNAME, ifname_container); if (r < 0) return log_error_errno(r, "Failed to add netlink interface name: %m"); r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, mac_container); if (r < 0) return log_error_errno(r, "Failed to add netlink MAC address: %m"); r = sd_netlink_message_append_u32(m, IFLA_NET_NS_PID, pid); if (r < 0) return log_error_errno(r, "Failed to add netlink namespace field: %m"); r = sd_netlink_message_close_container(m); if (r < 0) return log_error_errno(r, "Failed to close netlink container: %m"); r = sd_netlink_message_close_container(m); if (r < 0) return log_error_errno(r, "Failed to close netlink container: %m"); r = sd_netlink_message_close_container(m); if (r < 0) return log_error_errno(r, "Failed to close netlink container: %m"); r = sd_netlink_call(rtnl, m, 0, NULL); if (r < 0) return log_error_errno(r, "Failed to add new veth interfaces (%s:%s): %m", ifname_host, ifname_container); return 0; } int setup_veth(const char *machine_name, pid_t pid, char iface_name[IFNAMSIZ], bool bridge) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; struct ether_addr mac_host, mac_container; int r, i; assert(machine_name); assert(pid > 0); assert(iface_name); /* Use two different interface name prefixes depending whether * we are in bridge mode or not. */ snprintf(iface_name, IFNAMSIZ - 1, "%s-%s", bridge ? "vb" : "ve", machine_name); r = generate_mac(machine_name, &mac_container, CONTAINER_HASH_KEY, 0); if (r < 0) return log_error_errno(r, "Failed to generate predictable MAC address for container side: %m"); r = generate_mac(machine_name, &mac_host, HOST_HASH_KEY, 0); if (r < 0) return log_error_errno(r, "Failed to generate predictable MAC address for host side: %m"); r = sd_netlink_open(&rtnl); if (r < 0) return log_error_errno(r, "Failed to connect to netlink: %m"); r = add_veth(rtnl, pid, iface_name, &mac_host, "host0", &mac_container); if (r < 0) return r; i = (int) if_nametoindex(iface_name); if (i <= 0) return log_error_errno(errno, "Failed to resolve interface %s: %m", iface_name); return i; } int setup_veth_extra( const char *machine_name, pid_t pid, char **pairs) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; uint64_t idx = 0; char **a, **b; int r; assert(machine_name); assert(pid > 0); if (strv_isempty(pairs)) return 0; r = sd_netlink_open(&rtnl); if (r < 0) return log_error_errno(r, "Failed to connect to netlink: %m"); STRV_FOREACH_PAIR(a, b, pairs) { struct ether_addr mac_host, mac_container; r = generate_mac(machine_name, &mac_container, VETH_EXTRA_CONTAINER_HASH_KEY, idx); if (r < 0) return log_error_errno(r, "Failed to generate predictable MAC address for container side of extra veth link: %m"); r = generate_mac(machine_name, &mac_host, VETH_EXTRA_HOST_HASH_KEY, idx); if (r < 0) return log_error_errno(r, "Failed to generate predictable MAC address for container side of extra veth link: %m"); r = add_veth(rtnl, pid, *a, &mac_host, *b, &mac_container); if (r < 0) return r; idx ++; } return 0; } int setup_bridge(const char *veth_name, const char *bridge_name) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; int r, bridge_ifi; assert(veth_name); assert(bridge_name); bridge_ifi = (int) if_nametoindex(bridge_name); if (bridge_ifi <= 0) return log_error_errno(errno, "Failed to resolve interface %s: %m", bridge_name); r = sd_netlink_open(&rtnl); if (r < 0) return log_error_errno(r, "Failed to connect to netlink: %m"); r = sd_rtnl_message_new_link(rtnl, &m, RTM_SETLINK, 0); if (r < 0) return log_error_errno(r, "Failed to allocate netlink message: %m"); r = sd_rtnl_message_link_set_flags(m, IFF_UP, IFF_UP); if (r < 0) return log_error_errno(r, "Failed to set IFF_UP flag: %m"); r = sd_netlink_message_append_string(m, IFLA_IFNAME, veth_name); if (r < 0) return log_error_errno(r, "Failed to add netlink interface name field: %m"); r = sd_netlink_message_append_u32(m, IFLA_MASTER, bridge_ifi); if (r < 0) return log_error_errno(r, "Failed to add netlink master field: %m"); r = sd_netlink_call(rtnl, m, 0, NULL); if (r < 0) return log_error_errno(r, "Failed to add veth interface to bridge: %m"); return bridge_ifi; } static int parse_interface(struct udev *udev, const char *name) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; char ifi_str[2 + DECIMAL_STR_MAX(int)]; int ifi; ifi = (int) if_nametoindex(name); if (ifi <= 0) return log_error_errno(errno, "Failed to resolve interface %s: %m", name); sprintf(ifi_str, "n%i", ifi); d = udev_device_new_from_device_id(udev, ifi_str); if (!d) return log_error_errno(errno, "Failed to get udev device for interface %s: %m", name); if (udev_device_get_is_initialized(d) <= 0) { log_error("Network interface %s is not initialized yet.", name); return -EBUSY; } return ifi; } int move_network_interfaces(pid_t pid, char **ifaces) { _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; char **i; int r; if (strv_isempty(ifaces)) return 0; r = sd_netlink_open(&rtnl); if (r < 0) return log_error_errno(r, "Failed to connect to netlink: %m"); udev = udev_new(); if (!udev) { log_error("Failed to connect to udev."); return -ENOMEM; } STRV_FOREACH(i, ifaces) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int ifi; ifi = parse_interface(udev, *i); if (ifi < 0) return ifi; r = sd_rtnl_message_new_link(rtnl, &m, RTM_SETLINK, ifi); if (r < 0) return log_error_errno(r, "Failed to allocate netlink message: %m"); r = sd_netlink_message_append_u32(m, IFLA_NET_NS_PID, pid); if (r < 0) return log_error_errno(r, "Failed to append namespace PID to netlink message: %m"); r = sd_netlink_call(rtnl, m, 0, NULL); if (r < 0) return log_error_errno(r, "Failed to move interface %s to namespace: %m", *i); } return 0; } int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) { _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; unsigned idx = 0; char **i; int r; if (strv_isempty(ifaces)) return 0; r = sd_netlink_open(&rtnl); if (r < 0) return log_error_errno(r, "Failed to connect to netlink: %m"); udev = udev_new(); if (!udev) { log_error("Failed to connect to udev."); return -ENOMEM; } STRV_FOREACH(i, ifaces) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; _cleanup_free_ char *n = NULL; struct ether_addr mac; int ifi; ifi = parse_interface(udev, *i); if (ifi < 0) return ifi; r = generate_mac(machine_name, &mac, MACVLAN_HASH_KEY, idx++); if (r < 0) return log_error_errno(r, "Failed to create MACVLAN MAC address: %m"); r = sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0); if (r < 0) return log_error_errno(r, "Failed to allocate netlink message: %m"); r = sd_netlink_message_append_u32(m, IFLA_LINK, ifi); if (r < 0) return log_error_errno(r, "Failed to add netlink interface index: %m"); n = strappend("mv-", *i); if (!n) return log_oom(); strshorten(n, IFNAMSIZ-1); r = sd_netlink_message_append_string(m, IFLA_IFNAME, n); if (r < 0) return log_error_errno(r, "Failed to add netlink interface name: %m"); r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, &mac); if (r < 0) return log_error_errno(r, "Failed to add netlink MAC address: %m"); r = sd_netlink_message_append_u32(m, IFLA_NET_NS_PID, pid); if (r < 0) return log_error_errno(r, "Failed to add netlink namespace field: %m"); r = sd_netlink_message_open_container(m, IFLA_LINKINFO); if (r < 0) return log_error_errno(r, "Failed to open netlink container: %m"); r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "macvlan"); if (r < 0) return log_error_errno(r, "Failed to open netlink container: %m"); r = sd_netlink_message_append_u32(m, IFLA_MACVLAN_MODE, MACVLAN_MODE_BRIDGE); if (r < 0) return log_error_errno(r, "Failed to append macvlan mode: %m"); r = sd_netlink_message_close_container(m); if (r < 0) return log_error_errno(r, "Failed to close netlink container: %m"); r = sd_netlink_message_close_container(m); if (r < 0) return log_error_errno(r, "Failed to close netlink container: %m"); r = sd_netlink_call(rtnl, m, 0, NULL); if (r < 0) return log_error_errno(r, "Failed to add new macvlan interfaces: %m"); } return 0; } int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) { _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; char **i; int r; if (strv_isempty(ifaces)) return 0; r = sd_netlink_open(&rtnl); if (r < 0) return log_error_errno(r, "Failed to connect to netlink: %m"); udev = udev_new(); if (!udev) { log_error("Failed to connect to udev."); return -ENOMEM; } STRV_FOREACH(i, ifaces) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; _cleanup_free_ char *n = NULL; int ifi; ifi = parse_interface(udev, *i); if (ifi < 0) return ifi; r = sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0); if (r < 0) return log_error_errno(r, "Failed to allocate netlink message: %m"); r = sd_netlink_message_append_u32(m, IFLA_LINK, ifi); if (r < 0) return log_error_errno(r, "Failed to add netlink interface index: %m"); n = strappend("iv-", *i); if (!n) return log_oom(); strshorten(n, IFNAMSIZ-1); r = sd_netlink_message_append_string(m, IFLA_IFNAME, n); if (r < 0) return log_error_errno(r, "Failed to add netlink interface name: %m"); r = sd_netlink_message_append_u32(m, IFLA_NET_NS_PID, pid); if (r < 0) return log_error_errno(r, "Failed to add netlink namespace field: %m"); r = sd_netlink_message_open_container(m, IFLA_LINKINFO); if (r < 0) return log_error_errno(r, "Failed to open netlink container: %m"); r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "ipvlan"); if (r < 0) return log_error_errno(r, "Failed to open netlink container: %m"); r = sd_netlink_message_append_u16(m, IFLA_IPVLAN_MODE, IPVLAN_MODE_L2); if (r < 0) return log_error_errno(r, "Failed to add ipvlan mode: %m"); r = sd_netlink_message_close_container(m); if (r < 0) return log_error_errno(r, "Failed to close netlink container: %m"); r = sd_netlink_message_close_container(m); if (r < 0) return log_error_errno(r, "Failed to close netlink container: %m"); r = sd_netlink_call(rtnl, m, 0, NULL); if (r < 0) return log_error_errno(r, "Failed to add new ipvlan interfaces: %m"); } return 0; } int veth_extra_parse(char ***l, const char *p) { _cleanup_free_ char *a = NULL, *b = NULL; int r; r = extract_first_word(&p, &a, ":", EXTRACT_DONT_COALESCE_SEPARATORS); if (r < 0) return r; if (r == 0 || isempty(a)) return -EINVAL; r = extract_first_word(&p, &b, ":", EXTRACT_DONT_COALESCE_SEPARATORS); if (r < 0) return r; if (r == 0 || isempty(b)) { free(b); b = strdup(a); if (!b) return -ENOMEM; } if (p) return -EINVAL; r = strv_push_pair(l, a, b); if (r < 0) return -ENOMEM; a = b = NULL; return 0; } systemd-229/src/nspawn/nspawn-network.h000066400000000000000000000023761265713322000203340ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include int setup_veth(const char *machine_name, pid_t pid, char iface_name[IFNAMSIZ], bool bridge); int setup_veth_extra(const char *machine_name, pid_t pid, char **pairs); int setup_bridge(const char *veth_name, const char *bridge_name); int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces); int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces); int move_network_interfaces(pid_t pid, char **ifaces); int veth_extra_parse(char ***l, const char *p); systemd-229/src/nspawn/nspawn-register.c000066400000000000000000000225271265713322000204620ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "bus-error.h" #include "bus-util.h" #include "nspawn-register.h" #include "stat-util.h" #include "strv.h" #include "util.h" int register_machine( const char *machine_name, pid_t pid, const char *directory, sd_id128_t uuid, int local_ifindex, const char *slice, CustomMount *mounts, unsigned n_mounts, int kill_signal, char **properties, bool keep_unit, const char *service) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; r = sd_bus_default_system(&bus); if (r < 0) return log_error_errno(r, "Failed to open system bus: %m"); if (keep_unit) { r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "RegisterMachineWithNetwork", &error, NULL, "sayssusai", machine_name, SD_BUS_MESSAGE_APPEND_ID128(uuid), service, "container", (uint32_t) pid, strempty(directory), local_ifindex > 0 ? 1 : 0, local_ifindex); } else { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; char **i; unsigned j; r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "CreateMachineWithNetwork"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append( m, "sayssusai", machine_name, SD_BUS_MESSAGE_APPEND_ID128(uuid), service, "container", (uint32_t) pid, strempty(directory), local_ifindex > 0 ? 1 : 0, local_ifindex); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'a', "(sv)"); if (r < 0) return bus_log_create_error(r); if (!isempty(slice)) { r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice); if (r < 0) return bus_log_create_error(r); } r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "strict"); if (r < 0) return bus_log_create_error(r); /* If you make changes here, also make sure to update * systemd-nspawn@.service, to keep the device * policies in sync regardless if we are run with or * without the --keep-unit switch. */ r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 9, /* Allow the container to * access and create the API * device nodes, so that * PrivateDevices= in the * container can work * fine */ "/dev/null", "rwm", "/dev/zero", "rwm", "/dev/full", "rwm", "/dev/random", "rwm", "/dev/urandom", "rwm", "/dev/tty", "rwm", "/dev/net/tun", "rwm", /* Allow the container * access to ptys. However, * do not permit the * container to ever create * these device nodes. */ "/dev/pts/ptmx", "rw", "char-pts", "rw"); if (r < 0) return bus_log_create_error(r); for (j = 0; j < n_mounts; j++) { CustomMount *cm = mounts + j; if (cm->type != CUSTOM_MOUNT_BIND) continue; r = is_device_node(cm->source); if (r < 0) return log_error_errno(r, "Failed to stat %s: %m", cm->source); if (r) { r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1, cm->source, cm->read_only ? "r" : "rw"); if (r < 0) return log_error_errno(r, "Failed to append message arguments: %m"); } } if (kill_signal != 0) { r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed"); if (r < 0) return bus_log_create_error(r); } STRV_FOREACH(i, properties) { r = bus_append_unit_property_assignment(m, *i); if (r < 0) return r; } r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, NULL); } if (r < 0) { log_error("Failed to register machine: %s", bus_error_message(&error, r)); return r; } return 0; } int terminate_machine(pid_t pid) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; const char *path; int r; r = sd_bus_default_system(&bus); if (r < 0) return log_error_errno(r, "Failed to open system bus: %m"); r = sd_bus_call_method( bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "GetMachineByPID", &error, &reply, "u", (uint32_t) pid); if (r < 0) { /* Note that the machine might already have been * cleaned up automatically, hence don't consider it a * failure if we cannot get the machine object. */ log_debug("Failed to get machine: %s", bus_error_message(&error, r)); return 0; } r = sd_bus_message_read(reply, "o", &path); if (r < 0) return bus_log_parse_error(r); r = sd_bus_call_method( bus, "org.freedesktop.machine1", path, "org.freedesktop.machine1.Machine", "Terminate", &error, NULL, NULL); if (r < 0) { log_debug("Failed to terminate machine: %s", bus_error_message(&error, r)); return 0; } return 0; } systemd-229/src/nspawn/nspawn-register.h000066400000000000000000000021031265713322000204530ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-id128.h" #include "nspawn-mount.h" int register_machine(const char *machine_name, pid_t pid, const char *directory, sd_id128_t uuid, int local_ifindex, const char *slice, CustomMount *mounts, unsigned n_mounts, int kill_signal, char **properties, bool keep_unit, const char *service); int terminate_machine(pid_t pid); systemd-229/src/nspawn/nspawn-settings.c000066400000000000000000000253061265713322000204740ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "cap-list.h" #include "conf-parser.h" #include "nspawn-network.h" #include "nspawn-settings.h" #include "parse-util.h" #include "process-util.h" #include "strv.h" #include "util.h" int settings_load(FILE *f, const char *path, Settings **ret) { _cleanup_(settings_freep) Settings *s = NULL; int r; assert(path); assert(ret); s = new0(Settings, 1); if (!s) return -ENOMEM; s->start_mode = _START_MODE_INVALID; s->personality = PERSONALITY_INVALID; s->read_only = -1; s->volatile_mode = _VOLATILE_MODE_INVALID; s->private_network = -1; s->network_veth = -1; r = config_parse(NULL, path, f, "Exec\0" "Network\0" "Files\0", config_item_perf_lookup, nspawn_gperf_lookup, false, false, true, s); if (r < 0) return r; *ret = s; s = NULL; return 0; } Settings* settings_free(Settings *s) { if (!s) return NULL; strv_free(s->parameters); strv_free(s->environment); free(s->user); free(s->working_directory); strv_free(s->network_interfaces); strv_free(s->network_macvlan); strv_free(s->network_ipvlan); strv_free(s->network_veth_extra); free(s->network_bridge); expose_port_free_all(s->expose_ports); custom_mount_free_all(s->custom_mounts, s->n_custom_mounts); free(s); return NULL; } bool settings_private_network(Settings *s) { assert(s); return s->private_network > 0 || s->network_veth > 0 || s->network_bridge || s->network_interfaces || s->network_macvlan || s->network_ipvlan || s->network_veth_extra; } bool settings_network_veth(Settings *s) { assert(s); return s->network_veth > 0 || s->network_bridge; } DEFINE_CONFIG_PARSE_ENUM(config_parse_volatile_mode, volatile_mode, VolatileMode, "Failed to parse volatile mode"); int config_parse_expose_port( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Settings *s = data; int r; assert(filename); assert(lvalue); assert(rvalue); r = expose_port_parse(&s->expose_ports, rvalue); if (r == -EEXIST) { log_syntax(unit, LOG_ERR, filename, line, r, "Duplicate port specification, ignoring: %s", rvalue); return 0; } if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse host port %s: %m", rvalue); return 0; } return 0; } int config_parse_capability( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { uint64_t u = 0, *result = data; int r; assert(filename); assert(lvalue); assert(rvalue); for (;;) { _cleanup_free_ char *word = NULL; int cap; r = extract_first_word(&rvalue, &word, NULL, 0); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract capability string, ignoring: %s", rvalue); return 0; } if (r == 0) break; cap = capability_from_name(word); if (cap < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability, ignoring: %s", word); continue; } u |= 1 << ((uint64_t) cap); } if (u == 0) return 0; *result |= u; return 0; } int config_parse_id128( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { sd_id128_t t, *result = data; int r; assert(filename); assert(lvalue); assert(rvalue); r = sd_id128_from_string(rvalue, &t); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse 128bit ID/UUID, ignoring: %s", rvalue); return 0; } *result = t; return 0; } int config_parse_bind( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Settings *settings = data; int r; assert(filename); assert(lvalue); assert(rvalue); r = bind_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue, ltype); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Invalid bind mount specification %s: %m", rvalue); return 0; } return 0; } int config_parse_tmpfs( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Settings *settings = data; int r; assert(filename); assert(lvalue); assert(rvalue); r = tmpfs_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Invalid temporary file system specification %s: %m", rvalue); return 0; } return 0; } int config_parse_veth_extra( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Settings *settings = data; int r; assert(filename); assert(lvalue); assert(rvalue); r = veth_extra_parse(&settings->network_veth_extra, rvalue); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Invalid extra virtual Ethernet link specification %s: %m", rvalue); return 0; } return 0; } int config_parse_boot( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Settings *settings = data; int r; assert(filename); assert(lvalue); assert(rvalue); r = parse_boolean(rvalue); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Boot= parameter %s, ignoring: %m", rvalue); return 0; } if (r > 0) { if (settings->start_mode == START_PID2) goto conflict; settings->start_mode = START_BOOT; } else { if (settings->start_mode == START_BOOT) goto conflict; if (settings->start_mode < 0) settings->start_mode = START_PID1; } return 0; conflict: log_syntax(unit, LOG_ERR, filename, line, r, "Conflicting Boot= or ProcessTwo= setting found. Ignoring."); return 0; } int config_parse_pid2( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Settings *settings = data; int r; assert(filename); assert(lvalue); assert(rvalue); r = parse_boolean(rvalue); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse ProcessTwo= parameter %s, ignoring: %m", rvalue); return 0; } if (r > 0) { if (settings->start_mode == START_BOOT) goto conflict; settings->start_mode = START_PID2; } else { if (settings->start_mode == START_PID2) goto conflict; if (settings->start_mode < 0) settings->start_mode = START_PID1; } return 0; conflict: log_syntax(unit, LOG_ERR, filename, line, r, "Conflicting Boot= or ProcessTwo= setting found. Ignoring."); return 0; } systemd-229/src/nspawn/nspawn-settings.h000066400000000000000000000112741265713322000205000ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" #include "nspawn-expose-ports.h" #include "nspawn-mount.h" typedef enum StartMode { START_PID1, /* Run parameters as command line as process 1 */ START_PID2, /* Use stub init process as PID 1, run parameters as command line as process 2 */ START_BOOT, /* Search for init system, pass arguments as parameters */ _START_MODE_MAX, _START_MODE_INVALID = -1 } StartMode; typedef enum SettingsMask { SETTING_START_MODE = 1 << 0, SETTING_ENVIRONMENT = 1 << 1, SETTING_USER = 1 << 2, SETTING_CAPABILITY = 1 << 3, SETTING_KILL_SIGNAL = 1 << 4, SETTING_PERSONALITY = 1 << 5, SETTING_MACHINE_ID = 1 << 6, SETTING_NETWORK = 1 << 7, SETTING_EXPOSE_PORTS = 1 << 8, SETTING_READ_ONLY = 1 << 9, SETTING_VOLATILE_MODE = 1 << 10, SETTING_CUSTOM_MOUNTS = 1 << 11, SETTING_WORKING_DIRECTORY = 1 << 12, _SETTINGS_MASK_ALL = (1 << 13) -1 } SettingsMask; typedef struct Settings { /* [Run] */ StartMode start_mode; char **parameters; char **environment; char *user; uint64_t capability; uint64_t drop_capability; int kill_signal; unsigned long personality; sd_id128_t machine_id; char *working_directory; /* [Image] */ int read_only; VolatileMode volatile_mode; CustomMount *custom_mounts; unsigned n_custom_mounts; /* [Network] */ int private_network; int network_veth; char *network_bridge; char **network_interfaces; char **network_macvlan; char **network_ipvlan; char **network_veth_extra; ExposePort *expose_ports; } Settings; int settings_load(FILE *f, const char *path, Settings **ret); Settings* settings_free(Settings *s); bool settings_network_veth(Settings *s); bool settings_private_network(Settings *s); DEFINE_TRIVIAL_CLEANUP_FUNC(Settings*, settings_free); const struct ConfigPerfItem* nspawn_gperf_lookup(const char *key, unsigned length); int config_parse_capability(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_id128(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_expose_port(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_volatile_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bind(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_tmpfs(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_veth_extra(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_boot(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_pid2(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); systemd-229/src/nspawn/nspawn-setuid.c000066400000000000000000000171501265713322000201270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "mkdir.h" #include "nspawn-setuid.h" #include "process-util.h" #include "signal-util.h" #include "string-util.h" #include "user-util.h" #include "util.h" static int spawn_getent(const char *database, const char *key, pid_t *rpid) { int pipe_fds[2]; pid_t pid; assert(database); assert(key); assert(rpid); if (pipe2(pipe_fds, O_CLOEXEC) < 0) return log_error_errno(errno, "Failed to allocate pipe: %m"); pid = fork(); if (pid < 0) return log_error_errno(errno, "Failed to fork getent child: %m"); else if (pid == 0) { int nullfd; char *empty_env = NULL; if (dup3(pipe_fds[1], STDOUT_FILENO, 0) < 0) _exit(EXIT_FAILURE); if (pipe_fds[0] > 2) safe_close(pipe_fds[0]); if (pipe_fds[1] > 2) safe_close(pipe_fds[1]); nullfd = open("/dev/null", O_RDWR); if (nullfd < 0) _exit(EXIT_FAILURE); if (dup3(nullfd, STDIN_FILENO, 0) < 0) _exit(EXIT_FAILURE); if (dup3(nullfd, STDERR_FILENO, 0) < 0) _exit(EXIT_FAILURE); if (nullfd > 2) safe_close(nullfd); (void) reset_all_signal_handlers(); (void) reset_signal_mask(); close_all_fds(NULL, 0); execle("/usr/bin/getent", "getent", database, key, NULL, &empty_env); execle("/bin/getent", "getent", database, key, NULL, &empty_env); _exit(EXIT_FAILURE); } pipe_fds[1] = safe_close(pipe_fds[1]); *rpid = pid; return pipe_fds[0]; } int change_uid_gid(const char *user, char **_home) { char line[LINE_MAX], *x, *u, *g, *h; const char *word, *state; _cleanup_free_ uid_t *uids = NULL; _cleanup_free_ char *home = NULL; _cleanup_fclose_ FILE *f = NULL; _cleanup_close_ int fd = -1; unsigned n_uids = 0; size_t sz = 0, l; uid_t uid; gid_t gid; pid_t pid; int r; assert(_home); if (!user || streq(user, "root") || streq(user, "0")) { /* Reset everything fully to 0, just in case */ r = reset_uid_gid(); if (r < 0) return log_error_errno(r, "Failed to become root: %m"); *_home = NULL; return 0; } /* First, get user credentials */ fd = spawn_getent("passwd", user, &pid); if (fd < 0) return fd; f = fdopen(fd, "r"); if (!f) return log_oom(); fd = -1; if (!fgets(line, sizeof(line), f)) { if (!ferror(f)) { log_error("Failed to resolve user %s.", user); return -ESRCH; } log_error_errno(errno, "Failed to read from getent: %m"); return -errno; } truncate_nl(line); wait_for_terminate_and_warn("getent passwd", pid, true); x = strchr(line, ':'); if (!x) { log_error("/etc/passwd entry has invalid user field."); return -EIO; } u = strchr(x+1, ':'); if (!u) { log_error("/etc/passwd entry has invalid password field."); return -EIO; } u++; g = strchr(u, ':'); if (!g) { log_error("/etc/passwd entry has invalid UID field."); return -EIO; } *g = 0; g++; x = strchr(g, ':'); if (!x) { log_error("/etc/passwd entry has invalid GID field."); return -EIO; } *x = 0; h = strchr(x+1, ':'); if (!h) { log_error("/etc/passwd entry has invalid GECOS field."); return -EIO; } h++; x = strchr(h, ':'); if (!x) { log_error("/etc/passwd entry has invalid home directory field."); return -EIO; } *x = 0; r = parse_uid(u, &uid); if (r < 0) { log_error("Failed to parse UID of user."); return -EIO; } r = parse_gid(g, &gid); if (r < 0) { log_error("Failed to parse GID of user."); return -EIO; } home = strdup(h); if (!home) return log_oom(); /* Second, get group memberships */ fd = spawn_getent("initgroups", user, &pid); if (fd < 0) return fd; fclose(f); f = fdopen(fd, "r"); if (!f) return log_oom(); fd = -1; if (!fgets(line, sizeof(line), f)) { if (!ferror(f)) { log_error("Failed to resolve user %s.", user); return -ESRCH; } log_error_errno(errno, "Failed to read from getent: %m"); return -errno; } truncate_nl(line); wait_for_terminate_and_warn("getent initgroups", pid, true); /* Skip over the username and subsequent separator whitespace */ x = line; x += strcspn(x, WHITESPACE); x += strspn(x, WHITESPACE); FOREACH_WORD(word, l, x, state) { char c[l+1]; memcpy(c, word, l); c[l] = 0; if (!GREEDY_REALLOC(uids, sz, n_uids+1)) return log_oom(); r = parse_uid(c, &uids[n_uids++]); if (r < 0) { log_error("Failed to parse group data from getent."); return -EIO; } } r = mkdir_parents(home, 0775); if (r < 0) return log_error_errno(r, "Failed to make home root directory: %m"); r = mkdir_safe(home, 0755, uid, gid); if (r < 0 && r != -EEXIST) return log_error_errno(r, "Failed to make home directory: %m"); (void) fchown(STDIN_FILENO, uid, gid); (void) fchown(STDOUT_FILENO, uid, gid); (void) fchown(STDERR_FILENO, uid, gid); if (setgroups(n_uids, uids) < 0) return log_error_errno(errno, "Failed to set auxiliary groups: %m"); if (setresgid(gid, gid, gid) < 0) return log_error_errno(errno, "setresgid() failed: %m"); if (setresuid(uid, uid, uid) < 0) return log_error_errno(errno, "setresuid() failed: %m"); if (_home) { *_home = home; home = NULL; } return 0; } systemd-229/src/nspawn/nspawn-setuid.h000066400000000000000000000014171265713322000201330ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int change_uid_gid(const char *user, char **ret); systemd-229/src/nspawn/nspawn-stub-pid1.c000066400000000000000000000145421265713322000204440ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2016 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "fd-util.h" #include "log.h" #include "nspawn-stub-pid1.h" #include "process-util.h" #include "signal-util.h" #include "time-util.h" #include "def.h" int stub_pid1(void) { enum { STATE_RUNNING, STATE_REBOOT, STATE_POWEROFF, } state = STATE_RUNNING; sigset_t fullmask, oldmask, waitmask; usec_t quit_usec = USEC_INFINITY; pid_t pid; int r; /* Implements a stub PID 1, that reaps all processes and processes a couple of standard signals. This is useful * for allowing arbitrary processes run in a container, and still have all zombies reaped. */ assert_se(sigfillset(&fullmask) >= 0); assert_se(sigprocmask(SIG_BLOCK, &fullmask, &oldmask) >= 0); pid = fork(); if (pid < 0) return log_error_errno(errno, "Failed to fork child pid: %m"); if (pid == 0) { /* Return in the child */ assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) >= 0); setsid(); return 0; } reset_all_signal_handlers(); log_close(); close_all_fds(NULL, 0); log_open(); rename_process("STUBINIT"); assert_se(sigemptyset(&waitmask) >= 0); assert_se(sigset_add_many(&waitmask, SIGCHLD, /* posix: process died */ SIGINT, /* sysv: ctrl-alt-del */ SIGRTMIN+3, /* systemd: halt */ SIGRTMIN+4, /* systemd: poweroff */ SIGRTMIN+5, /* systemd: reboot */ SIGRTMIN+6, /* systemd: kexec */ SIGRTMIN+13, /* systemd: halt */ SIGRTMIN+14, /* systemd: poweroff */ SIGRTMIN+15, /* systemd: reboot */ SIGRTMIN+16, /* systemd: kexec */ -1) >= 0); /* Note that we ignore SIGTERM (sysv's reexec), SIGHUP (reload), and all other signals here, since we don't * support reexec/reloading in this stub process. */ for (;;) { siginfo_t si; usec_t current_usec; si.si_pid = 0; r = waitid(P_ALL, 0, &si, WEXITED|WNOHANG); if (r < 0) { r = log_error_errno(errno, "Failed to reap children: %m"); goto finish; } current_usec = now(CLOCK_MONOTONIC); if (si.si_pid == pid || current_usec >= quit_usec) { /* The child we started ourselves died or we reached a timeout. */ if (state == STATE_REBOOT) { /* dispatch a queued reboot */ (void) reboot(RB_AUTOBOOT); r = log_error_errno(errno, "Failed to reboot: %m"); goto finish; } else if (state == STATE_POWEROFF) (void) reboot(RB_POWER_OFF); /* if this fails, fall back to normal exit. */ if (si.si_pid == pid && si.si_code == CLD_EXITED) r = si.si_status; /* pass on exit code */ else r = 255; /* signal, coredump, timeout, … */ goto finish; } if (si.si_pid != 0) /* We reaped something. Retry until there's nothing more to reap. */ continue; if (quit_usec == USEC_INFINITY) r = sigwaitinfo(&waitmask, &si); else { struct timespec ts; r = sigtimedwait(&waitmask, &si, timespec_store(&ts, quit_usec - current_usec)); } if (r < 0) { if (errno == EINTR) /* strace -p attach can result in EINTR, let's handle this nicely. */ continue; if (errno == EAGAIN) /* timeout reached */ continue; r = log_error_errno(errno, "Failed to wait for signal: %m"); goto finish; } if (si.si_signo == SIGCHLD) continue; /* Let's reap this */ if (state != STATE_RUNNING) continue; /* Would love to use a switch() statement here, but SIGRTMIN is actually a function call, not a * constant… */ if (si.si_signo == SIGRTMIN+3 || si.si_signo == SIGRTMIN+4 || si.si_signo == SIGRTMIN+13 || si.si_signo == SIGRTMIN+14) state = STATE_POWEROFF; else if (si.si_signo == SIGINT || si.si_signo == SIGRTMIN+5 || si.si_signo == SIGRTMIN+6 || si.si_signo == SIGRTMIN+15 || si.si_signo == SIGRTMIN+16) state = STATE_REBOOT; else assert_not_reached("Got unexpected signal"); /* (void) kill_and_sigcont(pid, SIGTERM); */ quit_usec = now(CLOCK_MONOTONIC) + DEFAULT_TIMEOUT_USEC; } finish: _exit(r < 0 ? EXIT_FAILURE : r); } systemd-229/src/nspawn/nspawn-stub-pid1.h000066400000000000000000000013621265713322000204450ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2016 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int stub_pid1(void); systemd-229/src/nspawn/nspawn.c000066400000000000000000004235461265713322000166460ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #ifdef HAVE_BLKID #include #endif #include #include #include #include #ifdef HAVE_SECCOMP #include #endif #ifdef HAVE_SELINUX #include #endif #include #include #include #include #include #include #include #include #include #include #include "sd-daemon.h" #include "sd-id128.h" #include "alloc-util.h" #include "barrier.h" #include "base-filesystem.h" #include "blkid-util.h" #include "btrfs-util.h" #include "cap-list.h" #include "capability-util.h" #include "cgroup-util.h" #include "copy.h" #include "dev-setup.h" #include "env-util.h" #include "fd-util.h" #include "fdset.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "gpt.h" #include "hostname-util.h" #include "log.h" #include "loopback-setup.h" #include "machine-image.h" #include "macro.h" #include "missing.h" #include "mkdir.h" #include "mount-util.h" #include "netlink-util.h" #include "nspawn-cgroup.h" #include "nspawn-expose-ports.h" #include "nspawn-mount.h" #include "nspawn-network.h" #include "nspawn-register.h" #include "nspawn-settings.h" #include "nspawn-setuid.h" #include "nspawn-stub-pid1.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "ptyfwd.h" #include "random-util.h" #include "rm-rf.h" #ifdef HAVE_SECCOMP #include "seccomp-util.h" #endif #include "signal-util.h" #include "socket-util.h" #include "stat-util.h" #include "stdio-util.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "udev-util.h" #include "umask-util.h" #include "user-util.h" #include "util.h" typedef enum ContainerStatus { CONTAINER_TERMINATED, CONTAINER_REBOOTED } ContainerStatus; typedef enum LinkJournal { LINK_NO, LINK_AUTO, LINK_HOST, LINK_GUEST } LinkJournal; static char *arg_directory = NULL; static char *arg_template = NULL; static char *arg_chdir = NULL; static char *arg_user = NULL; static sd_id128_t arg_uuid = {}; static char *arg_machine = NULL; static const char *arg_selinux_context = NULL; static const char *arg_selinux_apifs_context = NULL; static const char *arg_slice = NULL; static bool arg_private_network = false; static bool arg_read_only = false; static StartMode arg_start_mode = START_PID1; static bool arg_ephemeral = false; static LinkJournal arg_link_journal = LINK_AUTO; static bool arg_link_journal_try = false; static uint64_t arg_retain = (1ULL << CAP_CHOWN) | (1ULL << CAP_DAC_OVERRIDE) | (1ULL << CAP_DAC_READ_SEARCH) | (1ULL << CAP_FOWNER) | (1ULL << CAP_FSETID) | (1ULL << CAP_IPC_OWNER) | (1ULL << CAP_KILL) | (1ULL << CAP_LEASE) | (1ULL << CAP_LINUX_IMMUTABLE) | (1ULL << CAP_NET_BIND_SERVICE) | (1ULL << CAP_NET_BROADCAST) | (1ULL << CAP_NET_RAW) | (1ULL << CAP_SETGID) | (1ULL << CAP_SETFCAP) | (1ULL << CAP_SETPCAP) | (1ULL << CAP_SETUID) | (1ULL << CAP_SYS_ADMIN) | (1ULL << CAP_SYS_CHROOT) | (1ULL << CAP_SYS_NICE) | (1ULL << CAP_SYS_PTRACE) | (1ULL << CAP_SYS_TTY_CONFIG) | (1ULL << CAP_SYS_RESOURCE) | (1ULL << CAP_SYS_BOOT) | (1ULL << CAP_AUDIT_WRITE) | (1ULL << CAP_AUDIT_CONTROL) | (1ULL << CAP_MKNOD); static CustomMount *arg_custom_mounts = NULL; static unsigned arg_n_custom_mounts = 0; static char **arg_setenv = NULL; static bool arg_quiet = false; static bool arg_share_system = false; static bool arg_register = true; static bool arg_keep_unit = false; static char **arg_network_interfaces = NULL; static char **arg_network_macvlan = NULL; static char **arg_network_ipvlan = NULL; static bool arg_network_veth = false; static char **arg_network_veth_extra = NULL; static char *arg_network_bridge = NULL; static unsigned long arg_personality = PERSONALITY_INVALID; static char *arg_image = NULL; static VolatileMode arg_volatile_mode = VOLATILE_NO; static ExposePort *arg_expose_ports = NULL; static char **arg_property = NULL; static uid_t arg_uid_shift = UID_INVALID, arg_uid_range = 0x10000U; static bool arg_userns = false; static int arg_kill_signal = 0; static bool arg_unified_cgroup_hierarchy = false; static SettingsMask arg_settings_mask = 0; static int arg_settings_trusted = -1; static char **arg_parameters = NULL; static const char *arg_container_service_name = "systemd-nspawn"; static void help(void) { printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n" "Spawn a minimal namespace container for debugging, testing and building.\n\n" " -h --help Show this help\n" " --version Print version string\n" " -q --quiet Do not show status information\n" " -D --directory=PATH Root directory for the container\n" " --template=PATH Initialize root directory from template directory,\n" " if missing\n" " -x --ephemeral Run container with snapshot of root directory, and\n" " remove it after exit\n" " -i --image=PATH File system device or disk image for the container\n" " -a --as-pid2 Maintain a stub init as PID1, invoke binary as PID2\n" " -b --boot Boot up full system (i.e. invoke init)\n" " --chdir=PATH Set working directory in the container\n" " -u --user=USER Run the command under specified user or uid\n" " -M --machine=NAME Set the machine name for the container\n" " --uuid=UUID Set a specific machine UUID for the container\n" " -S --slice=SLICE Place the container in the specified slice\n" " --property=NAME=VALUE Set scope unit property\n" " --private-users[=UIDBASE[:NUIDS]]\n" " Run within user namespace\n" " --private-network Disable network in container\n" " --network-interface=INTERFACE\n" " Assign an existing network interface to the\n" " container\n" " --network-macvlan=INTERFACE\n" " Create a macvlan network interface based on an\n" " existing network interface to the container\n" " --network-ipvlan=INTERFACE\n" " Create a ipvlan network interface based on an\n" " existing network interface to the container\n" " -n --network-veth Add a virtual Ethernet connection between host\n" " and container\n" " --network-veth-extra=HOSTIF[:CONTAINERIF]\n" " Add an additional virtual Ethernet link between\n" " host and container\n" " --network-bridge=INTERFACE\n" " Add a virtual Ethernet connection between host\n" " and container and add it to an existing bridge on\n" " the host\n" " -p --port=[PROTOCOL:]HOSTPORT[:CONTAINERPORT]\n" " Expose a container IP port on the host\n" " -Z --selinux-context=SECLABEL\n" " Set the SELinux security context to be used by\n" " processes in the container\n" " -L --selinux-apifs-context=SECLABEL\n" " Set the SELinux security context to be used by\n" " API/tmpfs file systems in the container\n" " --capability=CAP In addition to the default, retain specified\n" " capability\n" " --drop-capability=CAP Drop the specified capability from the default set\n" " --kill-signal=SIGNAL Select signal to use for shutting down PID 1\n" " --link-journal=MODE Link up guest journal, one of no, auto, guest, \n" " host, try-guest, try-host\n" " -j Equivalent to --link-journal=try-guest\n" " --read-only Mount the root directory read-only\n" " --bind=PATH[:PATH[:OPTIONS]]\n" " Bind mount a file or directory from the host into\n" " the container\n" " --bind-ro=PATH[:PATH[:OPTIONS]\n" " Similar, but creates a read-only bind mount\n" " --tmpfs=PATH:[OPTIONS] Mount an empty tmpfs to the specified directory\n" " --overlay=PATH[:PATH...]:PATH\n" " Create an overlay mount from the host to \n" " the container\n" " --overlay-ro=PATH[:PATH...]:PATH\n" " Similar, but creates a read-only overlay mount\n" " --setenv=NAME=VALUE Pass an environment variable to PID 1\n" " --share-system Share system namespaces with host\n" " --register=BOOLEAN Register container as machine\n" " --keep-unit Do not register a scope for the machine, reuse\n" " the service unit nspawn is running in\n" " --volatile[=MODE] Run the system in volatile mode\n" " --settings=BOOLEAN Load additional settings from .nspawn file\n" , program_invocation_short_name); } static int custom_mounts_prepare(void) { unsigned i; int r; /* Ensure the mounts are applied prefix first. */ qsort_safe(arg_custom_mounts, arg_n_custom_mounts, sizeof(CustomMount), custom_mount_compare); /* Allocate working directories for the overlay file systems that need it */ for (i = 0; i < arg_n_custom_mounts; i++) { CustomMount *m = &arg_custom_mounts[i]; if (arg_userns && arg_uid_shift == UID_INVALID && path_equal(m->destination, "/")) { log_error("--private-users with automatic UID shift may not be combined with custom root mounts."); return -EINVAL; } if (m->type != CUSTOM_MOUNT_OVERLAY) continue; if (m->work_dir) continue; if (m->read_only) continue; r = tempfn_random(m->source, NULL, &m->work_dir); if (r < 0) return log_error_errno(r, "Failed to generate work directory from %s: %m", m->source); } return 0; } static int detect_unified_cgroup_hierarchy(void) { const char *e; int r; /* Allow the user to control whether the unified hierarchy is used */ e = getenv("UNIFIED_CGROUP_HIERARCHY"); if (e) { r = parse_boolean(e); if (r < 0) return log_error_errno(r, "Failed to parse $UNIFIED_CGROUP_HIERARCHY."); arg_unified_cgroup_hierarchy = r; return 0; } /* Otherwise inherit the default from the host system */ r = cg_unified(); if (r < 0) return log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m"); arg_unified_cgroup_hierarchy = r; return 0; } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_PRIVATE_NETWORK, ARG_UUID, ARG_READ_ONLY, ARG_CAPABILITY, ARG_DROP_CAPABILITY, ARG_LINK_JOURNAL, ARG_BIND, ARG_BIND_RO, ARG_TMPFS, ARG_OVERLAY, ARG_OVERLAY_RO, ARG_SETENV, ARG_SHARE_SYSTEM, ARG_REGISTER, ARG_KEEP_UNIT, ARG_NETWORK_INTERFACE, ARG_NETWORK_MACVLAN, ARG_NETWORK_IPVLAN, ARG_NETWORK_BRIDGE, ARG_NETWORK_VETH_EXTRA, ARG_PERSONALITY, ARG_VOLATILE, ARG_TEMPLATE, ARG_PROPERTY, ARG_PRIVATE_USERS, ARG_KILL_SIGNAL, ARG_SETTINGS, ARG_CHDIR, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "directory", required_argument, NULL, 'D' }, { "template", required_argument, NULL, ARG_TEMPLATE }, { "ephemeral", no_argument, NULL, 'x' }, { "user", required_argument, NULL, 'u' }, { "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK }, { "as-pid2", no_argument, NULL, 'a' }, { "boot", no_argument, NULL, 'b' }, { "uuid", required_argument, NULL, ARG_UUID }, { "read-only", no_argument, NULL, ARG_READ_ONLY }, { "capability", required_argument, NULL, ARG_CAPABILITY }, { "drop-capability", required_argument, NULL, ARG_DROP_CAPABILITY }, { "link-journal", required_argument, NULL, ARG_LINK_JOURNAL }, { "bind", required_argument, NULL, ARG_BIND }, { "bind-ro", required_argument, NULL, ARG_BIND_RO }, { "tmpfs", required_argument, NULL, ARG_TMPFS }, { "overlay", required_argument, NULL, ARG_OVERLAY }, { "overlay-ro", required_argument, NULL, ARG_OVERLAY_RO }, { "machine", required_argument, NULL, 'M' }, { "slice", required_argument, NULL, 'S' }, { "setenv", required_argument, NULL, ARG_SETENV }, { "selinux-context", required_argument, NULL, 'Z' }, { "selinux-apifs-context", required_argument, NULL, 'L' }, { "quiet", no_argument, NULL, 'q' }, { "share-system", no_argument, NULL, ARG_SHARE_SYSTEM }, { "register", required_argument, NULL, ARG_REGISTER }, { "keep-unit", no_argument, NULL, ARG_KEEP_UNIT }, { "network-interface", required_argument, NULL, ARG_NETWORK_INTERFACE }, { "network-macvlan", required_argument, NULL, ARG_NETWORK_MACVLAN }, { "network-ipvlan", required_argument, NULL, ARG_NETWORK_IPVLAN }, { "network-veth", no_argument, NULL, 'n' }, { "network-veth-extra", required_argument, NULL, ARG_NETWORK_VETH_EXTRA}, { "network-bridge", required_argument, NULL, ARG_NETWORK_BRIDGE }, { "personality", required_argument, NULL, ARG_PERSONALITY }, { "image", required_argument, NULL, 'i' }, { "volatile", optional_argument, NULL, ARG_VOLATILE }, { "port", required_argument, NULL, 'p' }, { "property", required_argument, NULL, ARG_PROPERTY }, { "private-users", optional_argument, NULL, ARG_PRIVATE_USERS }, { "kill-signal", required_argument, NULL, ARG_KILL_SIGNAL }, { "settings", required_argument, NULL, ARG_SETTINGS }, { "chdir", required_argument, NULL, ARG_CHDIR }, {} }; int c, r; const char *p, *e; uint64_t plus = 0, minus = 0; bool mask_all_settings = false, mask_no_settings = false; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "+hD:u:abL:M:jS:Z:qi:xp:n", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case 'D': r = parse_path_argument_and_warn(optarg, false, &arg_directory); if (r < 0) return r; break; case ARG_TEMPLATE: r = parse_path_argument_and_warn(optarg, false, &arg_template); if (r < 0) return r; break; case 'i': r = parse_path_argument_and_warn(optarg, false, &arg_image); if (r < 0) return r; break; case 'x': arg_ephemeral = true; break; case 'u': r = free_and_strdup(&arg_user, optarg); if (r < 0) return log_oom(); arg_settings_mask |= SETTING_USER; break; case ARG_NETWORK_BRIDGE: r = free_and_strdup(&arg_network_bridge, optarg); if (r < 0) return log_oom(); /* fall through */ case 'n': arg_network_veth = true; arg_private_network = true; arg_settings_mask |= SETTING_NETWORK; break; case ARG_NETWORK_VETH_EXTRA: r = veth_extra_parse(&arg_network_veth_extra, optarg); if (r < 0) return log_error_errno(r, "Failed to parse --network-veth-extra= parameter: %s", optarg); arg_private_network = true; arg_settings_mask |= SETTING_NETWORK; break; case ARG_NETWORK_INTERFACE: if (strv_extend(&arg_network_interfaces, optarg) < 0) return log_oom(); arg_private_network = true; arg_settings_mask |= SETTING_NETWORK; break; case ARG_NETWORK_MACVLAN: if (strv_extend(&arg_network_macvlan, optarg) < 0) return log_oom(); arg_private_network = true; arg_settings_mask |= SETTING_NETWORK; break; case ARG_NETWORK_IPVLAN: if (strv_extend(&arg_network_ipvlan, optarg) < 0) return log_oom(); /* fall through */ case ARG_PRIVATE_NETWORK: arg_private_network = true; arg_settings_mask |= SETTING_NETWORK; break; case 'b': if (arg_start_mode == START_PID2) { log_error("--boot and --as-pid2 may not be combined."); return -EINVAL; } arg_start_mode = START_BOOT; arg_settings_mask |= SETTING_START_MODE; break; case 'a': if (arg_start_mode == START_BOOT) { log_error("--boot and --as-pid2 may not be combined."); return -EINVAL; } arg_start_mode = START_PID2; arg_settings_mask |= SETTING_START_MODE; break; case ARG_UUID: r = sd_id128_from_string(optarg, &arg_uuid); if (r < 0) { log_error("Invalid UUID: %s", optarg); return r; } arg_settings_mask |= SETTING_MACHINE_ID; break; case 'S': arg_slice = optarg; break; case 'M': if (isempty(optarg)) arg_machine = mfree(arg_machine); else { if (!machine_name_is_valid(optarg)) { log_error("Invalid machine name: %s", optarg); return -EINVAL; } r = free_and_strdup(&arg_machine, optarg); if (r < 0) return log_oom(); break; } case 'Z': arg_selinux_context = optarg; break; case 'L': arg_selinux_apifs_context = optarg; break; case ARG_READ_ONLY: arg_read_only = true; arg_settings_mask |= SETTING_READ_ONLY; break; case ARG_CAPABILITY: case ARG_DROP_CAPABILITY: { p = optarg; for(;;) { _cleanup_free_ char *t = NULL; r = extract_first_word(&p, &t, ",", 0); if (r < 0) return log_error_errno(r, "Failed to parse capability %s.", t); if (r == 0) break; if (streq(t, "all")) { if (c == ARG_CAPABILITY) plus = (uint64_t) -1; else minus = (uint64_t) -1; } else { int cap; cap = capability_from_name(t); if (cap < 0) { log_error("Failed to parse capability %s.", t); return -EINVAL; } if (c == ARG_CAPABILITY) plus |= 1ULL << (uint64_t) cap; else minus |= 1ULL << (uint64_t) cap; } } arg_settings_mask |= SETTING_CAPABILITY; break; } case 'j': arg_link_journal = LINK_GUEST; arg_link_journal_try = true; break; case ARG_LINK_JOURNAL: if (streq(optarg, "auto")) { arg_link_journal = LINK_AUTO; arg_link_journal_try = false; } else if (streq(optarg, "no")) { arg_link_journal = LINK_NO; arg_link_journal_try = false; } else if (streq(optarg, "guest")) { arg_link_journal = LINK_GUEST; arg_link_journal_try = false; } else if (streq(optarg, "host")) { arg_link_journal = LINK_HOST; arg_link_journal_try = false; } else if (streq(optarg, "try-guest")) { arg_link_journal = LINK_GUEST; arg_link_journal_try = true; } else if (streq(optarg, "try-host")) { arg_link_journal = LINK_HOST; arg_link_journal_try = true; } else { log_error("Failed to parse link journal mode %s", optarg); return -EINVAL; } break; case ARG_BIND: case ARG_BIND_RO: r = bind_mount_parse(&arg_custom_mounts, &arg_n_custom_mounts, optarg, c == ARG_BIND_RO); if (r < 0) return log_error_errno(r, "Failed to parse --bind(-ro)= argument %s: %m", optarg); arg_settings_mask |= SETTING_CUSTOM_MOUNTS; break; case ARG_TMPFS: r = tmpfs_mount_parse(&arg_custom_mounts, &arg_n_custom_mounts, optarg); if (r < 0) return log_error_errno(r, "Failed to parse --tmpfs= argument %s: %m", optarg); arg_settings_mask |= SETTING_CUSTOM_MOUNTS; break; case ARG_OVERLAY: case ARG_OVERLAY_RO: { _cleanup_free_ char *upper = NULL, *destination = NULL; _cleanup_strv_free_ char **lower = NULL; CustomMount *m; unsigned n = 0; char **i; r = strv_split_extract(&lower, optarg, ":", EXTRACT_DONT_COALESCE_SEPARATORS); if (r == -ENOMEM) return log_oom(); else if (r < 0) { log_error("Invalid overlay specification: %s", optarg); return r; } STRV_FOREACH(i, lower) { if (!path_is_absolute(*i)) { log_error("Overlay path %s is not absolute.", *i); return -EINVAL; } n++; } if (n < 2) { log_error("--overlay= needs at least two colon-separated directories specified."); return -EINVAL; } if (n == 2) { /* If two parameters are specified, * the first one is the lower, the * second one the upper directory. And * we'll also define the destination * mount point the same as the upper. */ upper = lower[1]; lower[1] = NULL; destination = strdup(upper); if (!destination) return log_oom(); } else { upper = lower[n - 2]; destination = lower[n - 1]; lower[n - 2] = NULL; } m = custom_mount_add(&arg_custom_mounts, &arg_n_custom_mounts, CUSTOM_MOUNT_OVERLAY); if (!m) return log_oom(); m->destination = destination; m->source = upper; m->lower = lower; m->read_only = c == ARG_OVERLAY_RO; upper = destination = NULL; lower = NULL; arg_settings_mask |= SETTING_CUSTOM_MOUNTS; break; } case ARG_SETENV: { char **n; if (!env_assignment_is_valid(optarg)) { log_error("Environment variable assignment '%s' is not valid.", optarg); return -EINVAL; } n = strv_env_set(arg_setenv, optarg); if (!n) return log_oom(); strv_free(arg_setenv); arg_setenv = n; arg_settings_mask |= SETTING_ENVIRONMENT; break; } case 'q': arg_quiet = true; break; case ARG_SHARE_SYSTEM: arg_share_system = true; break; case ARG_REGISTER: r = parse_boolean(optarg); if (r < 0) { log_error("Failed to parse --register= argument: %s", optarg); return r; } arg_register = r; break; case ARG_KEEP_UNIT: arg_keep_unit = true; break; case ARG_PERSONALITY: arg_personality = personality_from_string(optarg); if (arg_personality == PERSONALITY_INVALID) { log_error("Unknown or unsupported personality '%s'.", optarg); return -EINVAL; } arg_settings_mask |= SETTING_PERSONALITY; break; case ARG_VOLATILE: if (!optarg) arg_volatile_mode = VOLATILE_YES; else { VolatileMode m; m = volatile_mode_from_string(optarg); if (m < 0) { log_error("Failed to parse --volatile= argument: %s", optarg); return -EINVAL; } else arg_volatile_mode = m; } arg_settings_mask |= SETTING_VOLATILE_MODE; break; case 'p': r = expose_port_parse(&arg_expose_ports, optarg); if (r == -EEXIST) return log_error_errno(r, "Duplicate port specification: %s", optarg); if (r < 0) return log_error_errno(r, "Failed to parse host port %s: %m", optarg); arg_settings_mask |= SETTING_EXPOSE_PORTS; break; case ARG_PROPERTY: if (strv_extend(&arg_property, optarg) < 0) return log_oom(); break; case ARG_PRIVATE_USERS: if (optarg) { _cleanup_free_ char *buffer = NULL; const char *range, *shift; range = strchr(optarg, ':'); if (range) { buffer = strndup(optarg, range - optarg); if (!buffer) return log_oom(); shift = buffer; range++; if (safe_atou32(range, &arg_uid_range) < 0 || arg_uid_range <= 0) { log_error("Failed to parse UID range: %s", range); return -EINVAL; } } else shift = optarg; if (parse_uid(shift, &arg_uid_shift) < 0) { log_error("Failed to parse UID: %s", optarg); return -EINVAL; } } arg_userns = true; break; case ARG_KILL_SIGNAL: arg_kill_signal = signal_from_string_try_harder(optarg); if (arg_kill_signal < 0) { log_error("Cannot parse signal: %s", optarg); return -EINVAL; } arg_settings_mask |= SETTING_KILL_SIGNAL; break; case ARG_SETTINGS: /* no → do not read files * yes → read files, do not override cmdline, trust only subset * override → read files, override cmdline, trust only subset * trusted → read files, do not override cmdline, trust all */ r = parse_boolean(optarg); if (r < 0) { if (streq(optarg, "trusted")) { mask_all_settings = false; mask_no_settings = false; arg_settings_trusted = true; } else if (streq(optarg, "override")) { mask_all_settings = false; mask_no_settings = true; arg_settings_trusted = -1; } else return log_error_errno(r, "Failed to parse --settings= argument: %s", optarg); } else if (r > 0) { /* yes */ mask_all_settings = false; mask_no_settings = false; arg_settings_trusted = -1; } else { /* no */ mask_all_settings = true; mask_no_settings = false; arg_settings_trusted = false; } break; case ARG_CHDIR: if (!path_is_absolute(optarg)) { log_error("Working directory %s is not an absolute path.", optarg); return -EINVAL; } r = free_and_strdup(&arg_chdir, optarg); if (r < 0) return log_oom(); arg_settings_mask |= SETTING_WORKING_DIRECTORY; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (arg_share_system) arg_register = false; if (arg_start_mode != START_PID1 && arg_share_system) { log_error("--boot and --share-system may not be combined."); return -EINVAL; } if (arg_keep_unit && cg_pid_get_owner_uid(0, NULL) >= 0) { log_error("--keep-unit may not be used when invoked from a user session."); return -EINVAL; } if (arg_directory && arg_image) { log_error("--directory= and --image= may not be combined."); return -EINVAL; } if (arg_template && arg_image) { log_error("--template= and --image= may not be combined."); return -EINVAL; } if (arg_template && !(arg_directory || arg_machine)) { log_error("--template= needs --directory= or --machine=."); return -EINVAL; } if (arg_ephemeral && arg_template) { log_error("--ephemeral and --template= may not be combined."); return -EINVAL; } if (arg_ephemeral && arg_image) { log_error("--ephemeral and --image= may not be combined."); return -EINVAL; } if (arg_ephemeral && !IN_SET(arg_link_journal, LINK_NO, LINK_AUTO)) { log_error("--ephemeral and --link-journal= may not be combined."); return -EINVAL; } if (arg_userns && access("/proc/self/uid_map", F_OK) < 0) return log_error_errno(EOPNOTSUPP, "--private-users= is not supported, kernel compiled without user namespace support."); if (argc > optind) { arg_parameters = strv_copy(argv + optind); if (!arg_parameters) return log_oom(); arg_settings_mask |= SETTING_START_MODE; } /* Load all settings from .nspawn files */ if (mask_no_settings) arg_settings_mask = 0; /* Don't load any settings from .nspawn files */ if (mask_all_settings) arg_settings_mask = _SETTINGS_MASK_ALL; arg_retain = (arg_retain | plus | (arg_private_network ? 1ULL << CAP_NET_ADMIN : 0)) & ~minus; r = detect_unified_cgroup_hierarchy(); if (r < 0) return r; e = getenv("SYSTEMD_NSPAWN_CONTAINER_SERVICE"); if (e) arg_container_service_name = e; return 1; } static int verify_arguments(void) { if (arg_volatile_mode != VOLATILE_NO && arg_read_only) { log_error("Cannot combine --read-only with --volatile. Note that --volatile already implies a read-only base hierarchy."); return -EINVAL; } if (arg_expose_ports && !arg_private_network) { log_error("Cannot use --port= without private networking."); return -EINVAL; } if (arg_start_mode == START_BOOT && arg_kill_signal <= 0) arg_kill_signal = SIGRTMIN+3; return 0; } static int userns_lchown(const char *p, uid_t uid, gid_t gid) { assert(p); if (!arg_userns) return 0; if (uid == UID_INVALID && gid == GID_INVALID) return 0; if (uid != UID_INVALID) { uid += arg_uid_shift; if (uid < arg_uid_shift || uid >= arg_uid_shift + arg_uid_range) return -EOVERFLOW; } if (gid != GID_INVALID) { gid += (gid_t) arg_uid_shift; if (gid < (gid_t) arg_uid_shift || gid >= (gid_t) (arg_uid_shift + arg_uid_range)) return -EOVERFLOW; } if (lchown(p, uid, gid) < 0) return -errno; return 0; } static int userns_mkdir(const char *root, const char *path, mode_t mode, uid_t uid, gid_t gid) { const char *q; q = prefix_roota(root, path); if (mkdir(q, mode) < 0) { if (errno == EEXIST) return 0; return -errno; } return userns_lchown(q, uid, gid); } static int setup_timezone(const char *dest) { _cleanup_free_ char *p = NULL, *q = NULL; const char *where, *check, *what; char *z, *y; int r; assert(dest); /* Fix the timezone, if possible */ r = readlink_malloc("/etc/localtime", &p); if (r < 0) { log_warning("/etc/localtime is not a symlink, not updating container timezone."); return 0; } z = path_startswith(p, "../usr/share/zoneinfo/"); if (!z) z = path_startswith(p, "/usr/share/zoneinfo/"); if (!z) { log_warning("/etc/localtime does not point into /usr/share/zoneinfo/, not updating container timezone."); return 0; } where = prefix_roota(dest, "/etc/localtime"); r = readlink_malloc(where, &q); if (r >= 0) { y = path_startswith(q, "../usr/share/zoneinfo/"); if (!y) y = path_startswith(q, "/usr/share/zoneinfo/"); /* Already pointing to the right place? Then do nothing .. */ if (y && streq(y, z)) return 0; } check = strjoina("/usr/share/zoneinfo/", z); check = prefix_roota(dest, check); if (laccess(check, F_OK) < 0) { log_warning("Timezone %s does not exist in container, not updating container timezone.", z); return 0; } r = unlink(where); if (r < 0 && errno != ENOENT) { log_error_errno(errno, "Failed to remove existing timezone info %s in container: %m", where); return 0; } what = strjoina("../usr/share/zoneinfo/", z); if (symlink(what, where) < 0) { log_error_errno(errno, "Failed to correct timezone of container: %m"); return 0; } r = userns_lchown(where, 0, 0); if (r < 0) return log_warning_errno(r, "Failed to chown /etc/localtime: %m"); return 0; } static int setup_resolv_conf(const char *dest) { const char *where = NULL; int r; assert(dest); if (arg_private_network) return 0; /* Fix resolv.conf, if possible */ where = prefix_roota(dest, "/etc/resolv.conf"); r = copy_file("/etc/resolv.conf", where, O_TRUNC|O_NOFOLLOW, 0644, 0); if (r < 0) { /* If the file already exists as symlink, let's * suppress the warning, under the assumption that * resolved or something similar runs inside and the * symlink points there. * * If the disk image is read-only, there's also no * point in complaining. */ log_full_errno(IN_SET(r, -ELOOP, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, "Failed to copy /etc/resolv.conf to %s: %m", where); return 0; } r = userns_lchown(where, 0, 0); if (r < 0) log_warning_errno(r, "Failed to chown /etc/resolv.conf: %m"); return 0; } static char* id128_format_as_uuid(sd_id128_t id, char s[37]) { assert(s); snprintf(s, 37, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", SD_ID128_FORMAT_VAL(id)); return s; } static int setup_boot_id(const char *dest) { const char *from, *to; sd_id128_t rnd = {}; char as_uuid[37]; int r; if (arg_share_system) return 0; /* Generate a new randomized boot ID, so that each boot-up of * the container gets a new one */ from = prefix_roota(dest, "/run/proc-sys-kernel-random-boot-id"); to = prefix_roota(dest, "/proc/sys/kernel/random/boot_id"); r = sd_id128_randomize(&rnd); if (r < 0) return log_error_errno(r, "Failed to generate random boot id: %m"); id128_format_as_uuid(rnd, as_uuid); r = write_string_file(from, as_uuid, WRITE_STRING_FILE_CREATE); if (r < 0) return log_error_errno(r, "Failed to write boot id: %m"); if (mount(from, to, NULL, MS_BIND, NULL) < 0) r = log_error_errno(errno, "Failed to bind mount boot id: %m"); else if (mount(NULL, to, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL) < 0) log_warning_errno(errno, "Failed to make boot id read-only: %m"); unlink(from); return r; } static int copy_devnodes(const char *dest) { static const char devnodes[] = "null\0" "zero\0" "full\0" "random\0" "urandom\0" "tty\0" "net/tun\0"; const char *d; int r = 0; _cleanup_umask_ mode_t u; assert(dest); u = umask(0000); /* Create /dev/net, so that we can create /dev/net/tun in it */ if (userns_mkdir(dest, "/dev/net", 0755, 0, 0) < 0) return log_error_errno(r, "Failed to create /dev/net directory: %m"); NULSTR_FOREACH(d, devnodes) { _cleanup_free_ char *from = NULL, *to = NULL; struct stat st; from = strappend("/dev/", d); to = prefix_root(dest, from); if (stat(from, &st) < 0) { if (errno != ENOENT) return log_error_errno(errno, "Failed to stat %s: %m", from); } else if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) { log_error("%s is not a char or block device, cannot copy.", from); return -EIO; } else { if (mknod(to, st.st_mode, st.st_rdev) < 0) { if (errno != EPERM) return log_error_errno(errno, "mknod(%s) failed: %m", to); /* Some systems abusively restrict mknod but * allow bind mounts. */ r = touch(to); if (r < 0) return log_error_errno(r, "touch (%s) failed: %m", to); if (mount(from, to, NULL, MS_BIND, NULL) < 0) return log_error_errno(errno, "Both mknod and bind mount (%s) failed: %m", to); } r = userns_lchown(to, 0, 0); if (r < 0) return log_error_errno(r, "chown() of device node %s failed: %m", to); } } return r; } static int setup_pts(const char *dest) { _cleanup_free_ char *options = NULL; const char *p; int r; #ifdef HAVE_SELINUX if (arg_selinux_apifs_context) (void) asprintf(&options, "newinstance,ptmxmode=0666,mode=620,gid=" GID_FMT ",context=\"%s\"", arg_uid_shift + TTY_GID, arg_selinux_apifs_context); else #endif (void) asprintf(&options, "newinstance,ptmxmode=0666,mode=620,gid=" GID_FMT, arg_uid_shift + TTY_GID); if (!options) return log_oom(); /* Mount /dev/pts itself */ p = prefix_roota(dest, "/dev/pts"); if (mkdir(p, 0755) < 0) return log_error_errno(errno, "Failed to create /dev/pts: %m"); if (mount("devpts", p, "devpts", MS_NOSUID|MS_NOEXEC, options) < 0) return log_error_errno(errno, "Failed to mount /dev/pts: %m"); r = userns_lchown(p, 0, 0); if (r < 0) return log_error_errno(r, "Failed to chown /dev/pts: %m"); /* Create /dev/ptmx symlink */ p = prefix_roota(dest, "/dev/ptmx"); if (symlink("pts/ptmx", p) < 0) return log_error_errno(errno, "Failed to create /dev/ptmx symlink: %m"); r = userns_lchown(p, 0, 0); if (r < 0) return log_error_errno(r, "Failed to chown /dev/ptmx: %m"); /* And fix /dev/pts/ptmx ownership */ p = prefix_roota(dest, "/dev/pts/ptmx"); r = userns_lchown(p, 0, 0); if (r < 0) return log_error_errno(r, "Failed to chown /dev/pts/ptmx: %m"); return 0; } static int setup_dev_console(const char *dest, const char *console) { _cleanup_umask_ mode_t u; const char *to; int r; assert(dest); assert(console); u = umask(0000); r = chmod_and_chown(console, 0600, arg_uid_shift, arg_uid_shift); if (r < 0) return log_error_errno(r, "Failed to correct access mode for TTY: %m"); /* We need to bind mount the right tty to /dev/console since * ptys can only exist on pts file systems. To have something * to bind mount things on we create a empty regular file. */ to = prefix_roota(dest, "/dev/console"); r = touch(to); if (r < 0) return log_error_errno(r, "touch() for /dev/console failed: %m"); if (mount(console, to, NULL, MS_BIND, NULL) < 0) return log_error_errno(errno, "Bind mount for /dev/console failed: %m"); return 0; } static int setup_kmsg(const char *dest, int kmsg_socket) { const char *from, *to; _cleanup_umask_ mode_t u; int fd, r; assert(kmsg_socket >= 0); u = umask(0000); /* We create the kmsg FIFO as /run/kmsg, but immediately * delete it after bind mounting it to /proc/kmsg. While FIFOs * on the reading side behave very similar to /proc/kmsg, * their writing side behaves differently from /dev/kmsg in * that writing blocks when nothing is reading. In order to * avoid any problems with containers deadlocking due to this * we simply make /dev/kmsg unavailable to the container. */ from = prefix_roota(dest, "/run/kmsg"); to = prefix_roota(dest, "/proc/kmsg"); if (mkfifo(from, 0600) < 0) return log_error_errno(errno, "mkfifo() for /run/kmsg failed: %m"); if (mount(from, to, NULL, MS_BIND, NULL) < 0) return log_error_errno(errno, "Bind mount for /proc/kmsg failed: %m"); fd = open(from, O_RDWR|O_NDELAY|O_CLOEXEC); if (fd < 0) return log_error_errno(errno, "Failed to open fifo: %m"); /* Store away the fd in the socket, so that it stays open as * long as we run the child */ r = send_one_fd(kmsg_socket, fd, 0); safe_close(fd); if (r < 0) return log_error_errno(r, "Failed to send FIFO fd: %m"); /* And now make the FIFO unavailable as /run/kmsg... */ (void) unlink(from); return 0; } static int on_address_change(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { union in_addr_union *exposed = userdata; assert(rtnl); assert(m); assert(exposed); expose_port_execute(rtnl, arg_expose_ports, exposed); return 0; } static int setup_hostname(void) { if (arg_share_system) return 0; if (sethostname_idempotent(arg_machine) < 0) return -errno; return 0; } static int setup_journal(const char *directory) { sd_id128_t machine_id, this_id; _cleanup_free_ char *b = NULL, *d = NULL; const char *etc_machine_id, *p, *q; bool try; char *id; int r; /* Don't link journals in ephemeral mode */ if (arg_ephemeral) return 0; if (arg_link_journal == LINK_NO) return 0; try = arg_link_journal_try || arg_link_journal == LINK_AUTO; etc_machine_id = prefix_roota(directory, "/etc/machine-id"); r = read_one_line_file(etc_machine_id, &b); if (r == -ENOENT && try) return 0; else if (r < 0) return log_error_errno(r, "Failed to read machine ID from %s: %m", etc_machine_id); id = strstrip(b); if (isempty(id) && try) return 0; /* Verify validity */ r = sd_id128_from_string(id, &machine_id); if (r < 0) return log_error_errno(r, "Failed to parse machine ID from %s: %m", etc_machine_id); r = sd_id128_get_machine(&this_id); if (r < 0) return log_error_errno(r, "Failed to retrieve machine ID: %m"); if (sd_id128_equal(machine_id, this_id)) { log_full(try ? LOG_WARNING : LOG_ERR, "Host and machine ids are equal (%s): refusing to link journals", id); if (try) return 0; return -EEXIST; } r = userns_mkdir(directory, "/var", 0755, 0, 0); if (r < 0) return log_error_errno(r, "Failed to create /var: %m"); r = userns_mkdir(directory, "/var/log", 0755, 0, 0); if (r < 0) return log_error_errno(r, "Failed to create /var/log: %m"); r = userns_mkdir(directory, "/var/log/journal", 0755, 0, 0); if (r < 0) return log_error_errno(r, "Failed to create /var/log/journal: %m"); p = strjoina("/var/log/journal/", id); q = prefix_roota(directory, p); if (path_is_mount_point(p, 0) > 0) { if (try) return 0; log_error("%s: already a mount point, refusing to use for journal", p); return -EEXIST; } if (path_is_mount_point(q, 0) > 0) { if (try) return 0; log_error("%s: already a mount point, refusing to use for journal", q); return -EEXIST; } r = readlink_and_make_absolute(p, &d); if (r >= 0) { if ((arg_link_journal == LINK_GUEST || arg_link_journal == LINK_AUTO) && path_equal(d, q)) { r = userns_mkdir(directory, p, 0755, 0, 0); if (r < 0) log_warning_errno(r, "Failed to create directory %s: %m", q); return 0; } if (unlink(p) < 0) return log_error_errno(errno, "Failed to remove symlink %s: %m", p); } else if (r == -EINVAL) { if (arg_link_journal == LINK_GUEST && rmdir(p) < 0) { if (errno == ENOTDIR) { log_error("%s already exists and is neither a symlink nor a directory", p); return r; } else return log_error_errno(errno, "Failed to remove %s: %m", p); } } else if (r != -ENOENT) return log_error_errno(r, "readlink(%s) failed: %m", p); if (arg_link_journal == LINK_GUEST) { if (symlink(q, p) < 0) { if (try) { log_debug_errno(errno, "Failed to symlink %s to %s, skipping journal setup: %m", q, p); return 0; } else return log_error_errno(errno, "Failed to symlink %s to %s: %m", q, p); } r = userns_mkdir(directory, p, 0755, 0, 0); if (r < 0) log_warning_errno(r, "Failed to create directory %s: %m", q); return 0; } if (arg_link_journal == LINK_HOST) { /* don't create parents here -- if the host doesn't have * permanent journal set up, don't force it here */ if (mkdir(p, 0755) < 0 && errno != EEXIST) { if (try) { log_debug_errno(errno, "Failed to create %s, skipping journal setup: %m", p); return 0; } else return log_error_errno(errno, "Failed to create %s: %m", p); } } else if (access(p, F_OK) < 0) return 0; if (dir_is_empty(q) == 0) log_warning("%s is not empty, proceeding anyway.", q); r = userns_mkdir(directory, p, 0755, 0, 0); if (r < 0) return log_error_errno(r, "Failed to create %s: %m", q); if (mount(p, q, NULL, MS_BIND, NULL) < 0) return log_error_errno(errno, "Failed to bind mount journal from host into guest: %m"); return 0; } static int drop_capabilities(void) { return capability_bounding_set_drop(arg_retain, false); } static int reset_audit_loginuid(void) { _cleanup_free_ char *p = NULL; int r; if (arg_share_system) return 0; r = read_one_line_file("/proc/self/loginuid", &p); if (r == -ENOENT) return 0; if (r < 0) return log_error_errno(r, "Failed to read /proc/self/loginuid: %m"); /* Already reset? */ if (streq(p, "4294967295")) return 0; r = write_string_file("/proc/self/loginuid", "4294967295", 0); if (r < 0) { log_error_errno(r, "Failed to reset audit login UID. This probably means that your kernel is too\n" "old and you have audit enabled. Note that the auditing subsystem is known to\n" "be incompatible with containers on old kernels. Please make sure to upgrade\n" "your kernel or to off auditing with 'audit=0' on the kernel command line before\n" "using systemd-nspawn. Sleeping for 5s... (%m)"); sleep(5); } return 0; } static int setup_seccomp(void) { #ifdef HAVE_SECCOMP static const struct { uint64_t capability; int syscall_num; } blacklist[] = { { CAP_SYS_RAWIO, SCMP_SYS(iopl) }, { CAP_SYS_RAWIO, SCMP_SYS(ioperm) }, { CAP_SYS_BOOT, SCMP_SYS(kexec_load) }, { CAP_SYS_ADMIN, SCMP_SYS(swapon) }, { CAP_SYS_ADMIN, SCMP_SYS(swapoff) }, { CAP_SYS_ADMIN, SCMP_SYS(open_by_handle_at) }, { CAP_SYS_MODULE, SCMP_SYS(init_module) }, { CAP_SYS_MODULE, SCMP_SYS(finit_module) }, { CAP_SYS_MODULE, SCMP_SYS(delete_module) }, { CAP_SYSLOG, SCMP_SYS(syslog) }, }; scmp_filter_ctx seccomp; unsigned i; int r; seccomp = seccomp_init(SCMP_ACT_ALLOW); if (!seccomp) return log_oom(); r = seccomp_add_secondary_archs(seccomp); if (r < 0) { log_error_errno(r, "Failed to add secondary archs to seccomp filter: %m"); goto finish; } for (i = 0; i < ELEMENTSOF(blacklist); i++) { if (arg_retain & (1ULL << blacklist[i].capability)) continue; r = seccomp_rule_add(seccomp, SCMP_ACT_ERRNO(EPERM), blacklist[i].syscall_num, 0); if (r == -EFAULT) continue; /* unknown syscall */ if (r < 0) { log_error_errno(r, "Failed to block syscall: %m"); goto finish; } } /* Audit is broken in containers, much of the userspace audit hookup will fail if running inside a container. We don't care and just turn off creation of audit sockets. This will make socket(AF_NETLINK, *, NETLINK_AUDIT) fail with EAFNOSUPPORT which audit userspace uses as indication that audit is disabled in the kernel. */ r = seccomp_rule_add( seccomp, SCMP_ACT_ERRNO(EAFNOSUPPORT), SCMP_SYS(socket), 2, SCMP_A0(SCMP_CMP_EQ, AF_NETLINK), SCMP_A2(SCMP_CMP_EQ, NETLINK_AUDIT)); if (r < 0) { log_error_errno(r, "Failed to add audit seccomp rule: %m"); goto finish; } r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); if (r < 0) { log_error_errno(r, "Failed to unset NO_NEW_PRIVS: %m"); goto finish; } r = seccomp_load(seccomp); if (r == -EINVAL) { log_debug_errno(r, "Kernel is probably not configured with CONFIG_SECCOMP. Disabling seccomp audit filter: %m"); r = 0; goto finish; } if (r < 0) { log_error_errno(r, "Failed to install seccomp audit filter: %m"); goto finish; } finish: seccomp_release(seccomp); return r; #else return 0; #endif } static int setup_propagate(const char *root) { const char *p, *q; int r; (void) mkdir_p("/run/systemd/nspawn/", 0755); (void) mkdir_p("/run/systemd/nspawn/propagate", 0600); p = strjoina("/run/systemd/nspawn/propagate/", arg_machine); (void) mkdir_p(p, 0600); r = userns_mkdir(root, "/run/systemd", 0755, 0, 0); if (r < 0) return log_error_errno(r, "Failed to create /run/systemd: %m"); r = userns_mkdir(root, "/run/systemd/nspawn", 0755, 0, 0); if (r < 0) return log_error_errno(r, "Failed to create /run/systemd/nspawn: %m"); r = userns_mkdir(root, "/run/systemd/nspawn/incoming", 0600, 0, 0); if (r < 0) return log_error_errno(r, "Failed to create /run/systemd/nspawn/incoming: %m"); q = prefix_roota(root, "/run/systemd/nspawn/incoming"); if (mount(p, q, NULL, MS_BIND, NULL) < 0) return log_error_errno(errno, "Failed to install propagation bind mount."); if (mount(NULL, q, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) return log_error_errno(errno, "Failed to make propagation mount read-only"); return 0; } static int setup_image(char **device_path, int *loop_nr) { struct loop_info64 info = { .lo_flags = LO_FLAGS_AUTOCLEAR|LO_FLAGS_PARTSCAN }; _cleanup_close_ int fd = -1, control = -1, loop = -1; _cleanup_free_ char* loopdev = NULL; struct stat st; int r, nr; assert(device_path); assert(loop_nr); assert(arg_image); fd = open(arg_image, O_CLOEXEC|(arg_read_only ? O_RDONLY : O_RDWR)|O_NONBLOCK|O_NOCTTY); if (fd < 0) return log_error_errno(errno, "Failed to open %s: %m", arg_image); if (fstat(fd, &st) < 0) return log_error_errno(errno, "Failed to stat %s: %m", arg_image); if (S_ISBLK(st.st_mode)) { char *p; p = strdup(arg_image); if (!p) return log_oom(); *device_path = p; *loop_nr = -1; r = fd; fd = -1; return r; } if (!S_ISREG(st.st_mode)) { log_error("%s is not a regular file or block device.", arg_image); return -EINVAL; } control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); if (control < 0) return log_error_errno(errno, "Failed to open /dev/loop-control: %m"); nr = ioctl(control, LOOP_CTL_GET_FREE); if (nr < 0) return log_error_errno(errno, "Failed to allocate loop device: %m"); if (asprintf(&loopdev, "/dev/loop%i", nr) < 0) return log_oom(); loop = open(loopdev, O_CLOEXEC|(arg_read_only ? O_RDONLY : O_RDWR)|O_NONBLOCK|O_NOCTTY); if (loop < 0) return log_error_errno(errno, "Failed to open loop device %s: %m", loopdev); if (ioctl(loop, LOOP_SET_FD, fd) < 0) return log_error_errno(errno, "Failed to set loopback file descriptor on %s: %m", loopdev); if (arg_read_only) info.lo_flags |= LO_FLAGS_READ_ONLY; if (ioctl(loop, LOOP_SET_STATUS64, &info) < 0) return log_error_errno(errno, "Failed to set loopback settings on %s: %m", loopdev); *device_path = loopdev; loopdev = NULL; *loop_nr = nr; r = loop; loop = -1; return r; } #define PARTITION_TABLE_BLURB \ "Note that the disk image needs to either contain only a single MBR partition of\n" \ "type 0x83 that is marked bootable, or a single GPT partition of type " \ "0FC63DAF-8483-4772-8E79-3D69D8477DE4 or follow\n" \ " http://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec/\n" \ "to be bootable with systemd-nspawn." static int dissect_image( int fd, char **root_device, bool *root_device_rw, char **home_device, bool *home_device_rw, char **srv_device, bool *srv_device_rw, bool *secondary) { #ifdef HAVE_BLKID int home_nr = -1, srv_nr = -1; #ifdef GPT_ROOT_NATIVE int root_nr = -1; #endif #ifdef GPT_ROOT_SECONDARY int secondary_root_nr = -1; #endif _cleanup_free_ char *home = NULL, *root = NULL, *secondary_root = NULL, *srv = NULL, *generic = NULL; _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; _cleanup_udev_device_unref_ struct udev_device *d = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; struct udev_list_entry *first, *item; bool home_rw = true, root_rw = true, secondary_root_rw = true, srv_rw = true, generic_rw = true; bool is_gpt, is_mbr, multiple_generic = false; const char *pttype = NULL; blkid_partlist pl; struct stat st; unsigned i; int r; assert(fd >= 0); assert(root_device); assert(home_device); assert(srv_device); assert(secondary); assert(arg_image); b = blkid_new_probe(); if (!b) return log_oom(); errno = 0; r = blkid_probe_set_device(b, fd, 0, 0); if (r != 0) { if (errno == 0) return log_oom(); return log_error_errno(errno, "Failed to set device on blkid probe: %m"); } blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == -2 || r == 1) { log_error("Failed to identify any partition table on\n" " %s\n" PARTITION_TABLE_BLURB, arg_image); return -EINVAL; } else if (r != 0) { if (errno == 0) errno = EIO; return log_error_errno(errno, "Failed to probe: %m"); } (void) blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL); is_gpt = streq_ptr(pttype, "gpt"); is_mbr = streq_ptr(pttype, "dos"); if (!is_gpt && !is_mbr) { log_error("No GPT or MBR partition table discovered on\n" " %s\n" PARTITION_TABLE_BLURB, arg_image); return -EINVAL; } errno = 0; pl = blkid_probe_get_partitions(b); if (!pl) { if (errno == 0) return log_oom(); log_error("Failed to list partitions of %s", arg_image); return -errno; } udev = udev_new(); if (!udev) return log_oom(); if (fstat(fd, &st) < 0) return log_error_errno(errno, "Failed to stat block device: %m"); d = udev_device_new_from_devnum(udev, 'b', st.st_rdev); if (!d) return log_oom(); for (i = 0;; i++) { int n, m; if (i >= 10) { log_error("Kernel partitions never appeared."); return -ENXIO; } e = udev_enumerate_new(udev); if (!e) return log_oom(); r = udev_enumerate_add_match_parent(e, d); if (r < 0) return log_oom(); r = udev_enumerate_scan_devices(e); if (r < 0) return log_error_errno(r, "Failed to scan for partition devices of %s: %m", arg_image); /* Count the partitions enumerated by the kernel */ n = 0; first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) n++; /* Count the partitions enumerated by blkid */ m = blkid_partlist_numof_partitions(pl); if (n == m + 1) break; if (n > m + 1) { log_error("blkid and kernel partition list do not match."); return -EIO; } if (n < m + 1) { unsigned j; /* The kernel has probed fewer partitions than * blkid? Maybe the kernel prober is still * running or it got EBUSY because udev * already opened the device. Let's reprobe * the device, which is a synchronous call * that waits until probing is complete. */ for (j = 0; j < 20; j++) { r = ioctl(fd, BLKRRPART, 0); if (r < 0) r = -errno; if (r >= 0 || r != -EBUSY) break; /* If something else has the device * open, such as an udev rule, the * ioctl will return EBUSY. Since * there's no way to wait until it * isn't busy anymore, let's just wait * a bit, and try again. * * This is really something they * should fix in the kernel! */ usleep(50 * USEC_PER_MSEC); } if (r < 0) return log_error_errno(r, "Failed to reread partition table: %m"); } e = udev_enumerate_unref(e); } first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *q; const char *node; unsigned long long flags; blkid_partition pp; dev_t qn; int nr; errno = 0; q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!q) { if (!errno) errno = ENOMEM; return log_error_errno(errno, "Failed to get partition device of %s: %m", arg_image); } qn = udev_device_get_devnum(q); if (major(qn) == 0) continue; if (st.st_rdev == qn) continue; node = udev_device_get_devnode(q); if (!node) continue; pp = blkid_partlist_devno_to_partition(pl, qn); if (!pp) continue; flags = blkid_partition_get_flags(pp); nr = blkid_partition_get_partno(pp); if (nr < 0) continue; if (is_gpt) { sd_id128_t type_id; const char *stype; if (flags & GPT_FLAG_NO_AUTO) continue; stype = blkid_partition_get_type_string(pp); if (!stype) continue; if (sd_id128_from_string(stype, &type_id) < 0) continue; if (sd_id128_equal(type_id, GPT_HOME)) { if (home && nr >= home_nr) continue; home_nr = nr; home_rw = !(flags & GPT_FLAG_READ_ONLY); r = free_and_strdup(&home, node); if (r < 0) return log_oom(); } else if (sd_id128_equal(type_id, GPT_SRV)) { if (srv && nr >= srv_nr) continue; srv_nr = nr; srv_rw = !(flags & GPT_FLAG_READ_ONLY); r = free_and_strdup(&srv, node); if (r < 0) return log_oom(); } #ifdef GPT_ROOT_NATIVE else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE)) { if (root && nr >= root_nr) continue; root_nr = nr; root_rw = !(flags & GPT_FLAG_READ_ONLY); r = free_and_strdup(&root, node); if (r < 0) return log_oom(); } #endif #ifdef GPT_ROOT_SECONDARY else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY)) { if (secondary_root && nr >= secondary_root_nr) continue; secondary_root_nr = nr; secondary_root_rw = !(flags & GPT_FLAG_READ_ONLY); r = free_and_strdup(&secondary_root, node); if (r < 0) return log_oom(); } #endif else if (sd_id128_equal(type_id, GPT_LINUX_GENERIC)) { if (generic) multiple_generic = true; else { generic_rw = !(flags & GPT_FLAG_READ_ONLY); r = free_and_strdup(&generic, node); if (r < 0) return log_oom(); } } } else if (is_mbr) { int type; if (flags != 0x80) /* Bootable flag */ continue; type = blkid_partition_get_type(pp); if (type != 0x83) /* Linux partition */ continue; if (generic) multiple_generic = true; else { generic_rw = true; r = free_and_strdup(&root, node); if (r < 0) return log_oom(); } } } if (root) { *root_device = root; root = NULL; *root_device_rw = root_rw; *secondary = false; } else if (secondary_root) { *root_device = secondary_root; secondary_root = NULL; *root_device_rw = secondary_root_rw; *secondary = true; } else if (generic) { /* There were no partitions with precise meanings * around, but we found generic partitions. In this * case, if there's only one, we can go ahead and boot * it, otherwise we bail out, because we really cannot * make any sense of it. */ if (multiple_generic) { log_error("Identified multiple bootable Linux partitions on\n" " %s\n" PARTITION_TABLE_BLURB, arg_image); return -EINVAL; } *root_device = generic; generic = NULL; *root_device_rw = generic_rw; *secondary = false; } else { log_error("Failed to identify root partition in disk image\n" " %s\n" PARTITION_TABLE_BLURB, arg_image); return -EINVAL; } if (home) { *home_device = home; home = NULL; *home_device_rw = home_rw; } if (srv) { *srv_device = srv; srv = NULL; *srv_device_rw = srv_rw; } return 0; #else log_error("--image= is not supported, compiled without blkid support."); return -EOPNOTSUPP; #endif } static int mount_device(const char *what, const char *where, const char *directory, bool rw) { #ifdef HAVE_BLKID _cleanup_blkid_free_probe_ blkid_probe b = NULL; const char *fstype, *p; int r; assert(what); assert(where); if (arg_read_only) rw = false; if (directory) p = strjoina(where, directory); else p = where; errno = 0; b = blkid_new_probe_from_filename(what); if (!b) { if (errno == 0) return log_oom(); return log_error_errno(errno, "Failed to allocate prober for %s: %m", what); } blkid_probe_enable_superblocks(b, 1); blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE); errno = 0; r = blkid_do_safeprobe(b); if (r == -1 || r == 1) { log_error("Cannot determine file system type of %s", what); return -EINVAL; } else if (r != 0) { if (errno == 0) errno = EIO; return log_error_errno(errno, "Failed to probe %s: %m", what); } errno = 0; if (blkid_probe_lookup_value(b, "TYPE", &fstype, NULL) < 0) { if (errno == 0) errno = EINVAL; log_error("Failed to determine file system type of %s", what); return -errno; } if (streq(fstype, "crypto_LUKS")) { log_error("nspawn currently does not support LUKS disk images."); return -EOPNOTSUPP; } if (mount(what, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), NULL) < 0) return log_error_errno(errno, "Failed to mount %s: %m", what); return 0; #else log_error("--image= is not supported, compiled without blkid support."); return -EOPNOTSUPP; #endif } static int mount_devices( const char *where, const char *root_device, bool root_device_rw, const char *home_device, bool home_device_rw, const char *srv_device, bool srv_device_rw) { int r; assert(where); if (root_device) { r = mount_device(root_device, arg_directory, NULL, root_device_rw); if (r < 0) return log_error_errno(r, "Failed to mount root directory: %m"); } if (home_device) { r = mount_device(home_device, arg_directory, "/home", home_device_rw); if (r < 0) return log_error_errno(r, "Failed to mount home directory: %m"); } if (srv_device) { r = mount_device(srv_device, arg_directory, "/srv", srv_device_rw); if (r < 0) return log_error_errno(r, "Failed to mount server data directory: %m"); } return 0; } static void loop_remove(int nr, int *image_fd) { _cleanup_close_ int control = -1; int r; if (nr < 0) return; if (image_fd && *image_fd >= 0) { r = ioctl(*image_fd, LOOP_CLR_FD); if (r < 0) log_debug_errno(errno, "Failed to close loop image: %m"); *image_fd = safe_close(*image_fd); } control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); if (control < 0) { log_warning_errno(errno, "Failed to open /dev/loop-control: %m"); return; } r = ioctl(control, LOOP_CTL_REMOVE, nr); if (r < 0) log_debug_errno(errno, "Failed to remove loop %d: %m", nr); } /* * Return values: * < 0 : wait_for_terminate() failed to get the state of the * container, the container was terminated by a signal, or * failed for an unknown reason. No change is made to the * container argument. * > 0 : The program executed in the container terminated with an * error. The exit code of the program executed in the * container is returned. The container argument has been set * to CONTAINER_TERMINATED. * 0 : The container is being rebooted, has been shut down or exited * successfully. The container argument has been set to either * CONTAINER_TERMINATED or CONTAINER_REBOOTED. * * That is, success is indicated by a return value of zero, and an * error is indicated by a non-zero value. */ static int wait_for_container(pid_t pid, ContainerStatus *container) { siginfo_t status; int r; r = wait_for_terminate(pid, &status); if (r < 0) return log_warning_errno(r, "Failed to wait for container: %m"); switch (status.si_code) { case CLD_EXITED: if (status.si_status == 0) { log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, "Container %s exited successfully.", arg_machine); } else log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, "Container %s failed with error code %i.", arg_machine, status.si_status); *container = CONTAINER_TERMINATED; return status.si_status; case CLD_KILLED: if (status.si_status == SIGINT) { log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, "Container %s has been shut down.", arg_machine); *container = CONTAINER_TERMINATED; return 0; } else if (status.si_status == SIGHUP) { log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, "Container %s is being rebooted.", arg_machine); *container = CONTAINER_REBOOTED; return 0; } /* CLD_KILLED fallthrough */ case CLD_DUMPED: log_error("Container %s terminated by signal %s.", arg_machine, signal_to_string(status.si_status)); return -EIO; default: log_error("Container %s failed due to unknown reason.", arg_machine); return -EIO; } return r; } static int on_orderly_shutdown(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { pid_t pid; pid = PTR_TO_PID(userdata); if (pid > 0) { if (kill(pid, arg_kill_signal) >= 0) { log_info("Trying to halt container. Send SIGTERM again to trigger immediate termination."); sd_event_source_set_userdata(s, NULL); return 0; } } sd_event_exit(sd_event_source_get_event(s), 0); return 0; } static int determine_names(void) { int r; if (arg_template && !arg_directory && arg_machine) { /* If --template= was specified then we should not * search for a machine, but instead create a new one * in /var/lib/machine. */ arg_directory = strjoin("/var/lib/machines/", arg_machine, NULL); if (!arg_directory) return log_oom(); } if (!arg_image && !arg_directory) { if (arg_machine) { _cleanup_(image_unrefp) Image *i = NULL; r = image_find(arg_machine, &i); if (r < 0) return log_error_errno(r, "Failed to find image for machine '%s': %m", arg_machine); else if (r == 0) { log_error("No image for machine '%s': %m", arg_machine); return -ENOENT; } if (i->type == IMAGE_RAW) r = free_and_strdup(&arg_image, i->path); else r = free_and_strdup(&arg_directory, i->path); if (r < 0) return log_error_errno(r, "Invalid image directory: %m"); if (!arg_ephemeral) arg_read_only = arg_read_only || i->read_only; } else arg_directory = get_current_dir_name(); if (!arg_directory && !arg_machine) { log_error("Failed to determine path, please use -D or -i."); return -EINVAL; } } if (!arg_machine) { if (arg_directory && path_equal(arg_directory, "/")) arg_machine = gethostname_malloc(); else arg_machine = strdup(basename(arg_image ?: arg_directory)); if (!arg_machine) return log_oom(); hostname_cleanup(arg_machine); if (!machine_name_is_valid(arg_machine)) { log_error("Failed to determine machine name automatically, please use -M."); return -EINVAL; } if (arg_ephemeral) { char *b; /* Add a random suffix when this is an * ephemeral machine, so that we can run many * instances at once without manually having * to specify -M each time. */ if (asprintf(&b, "%s-%016" PRIx64, arg_machine, random_u64()) < 0) return log_oom(); free(arg_machine); arg_machine = b; } } return 0; } static int determine_uid_shift(const char *directory) { int r; if (!arg_userns) { arg_uid_shift = 0; return 0; } if (arg_uid_shift == UID_INVALID) { struct stat st; r = stat(directory, &st); if (r < 0) return log_error_errno(errno, "Failed to determine UID base of %s: %m", directory); arg_uid_shift = st.st_uid & UINT32_C(0xffff0000); if (arg_uid_shift != (st.st_gid & UINT32_C(0xffff0000))) { log_error("UID and GID base of %s don't match.", directory); return -EINVAL; } arg_uid_range = UINT32_C(0x10000); } if (arg_uid_shift > (uid_t) -1 - arg_uid_range) { log_error("UID base too high for UID range."); return -EINVAL; } log_info("Using user namespaces with base " UID_FMT " and range " UID_FMT ".", arg_uid_shift, arg_uid_range); return 0; } static int inner_child( Barrier *barrier, const char *directory, bool secondary, int kmsg_socket, int rtnl_socket, FDSet *fds) { _cleanup_free_ char *home = NULL; unsigned n_env = 1; const char *envp[] = { "PATH=" DEFAULT_PATH_SPLIT_USR, NULL, /* container */ NULL, /* TERM */ NULL, /* HOME */ NULL, /* USER */ NULL, /* LOGNAME */ NULL, /* container_uuid */ NULL, /* LISTEN_FDS */ NULL, /* LISTEN_PID */ NULL }; _cleanup_strv_free_ char **env_use = NULL; int r; assert(barrier); assert(directory); assert(kmsg_socket >= 0); cg_unified_flush(); if (arg_userns) { /* Tell the parent, that it now can write the UID map. */ (void) barrier_place(barrier); /* #1 */ /* Wait until the parent wrote the UID map */ if (!barrier_place_and_sync(barrier)) { /* #2 */ log_error("Parent died too early"); return -ESRCH; } } r = mount_all(NULL, arg_userns, true, arg_uid_shift, arg_private_network, arg_uid_range, arg_selinux_apifs_context); if (r < 0) return r; r = mount_sysfs(NULL); if (r < 0) return r; /* Wait until we are cgroup-ified, so that we * can mount the right cgroup path writable */ if (!barrier_place_and_sync(barrier)) { /* #3 */ log_error("Parent died too early"); return -ESRCH; } r = mount_systemd_cgroup_writable("", arg_unified_cgroup_hierarchy); if (r < 0) return r; r = reset_uid_gid(); if (r < 0) return log_error_errno(r, "Couldn't become new root: %m"); r = setup_boot_id(NULL); if (r < 0) return r; r = setup_kmsg(NULL, kmsg_socket); if (r < 0) return r; kmsg_socket = safe_close(kmsg_socket); umask(0022); if (setsid() < 0) return log_error_errno(errno, "setsid() failed: %m"); if (arg_private_network) loopback_setup(); if (arg_expose_ports) { r = expose_port_send_rtnl(rtnl_socket); if (r < 0) return r; rtnl_socket = safe_close(rtnl_socket); } r = drop_capabilities(); if (r < 0) return log_error_errno(r, "drop_capabilities() failed: %m"); setup_hostname(); if (arg_personality != PERSONALITY_INVALID) { if (personality(arg_personality) < 0) return log_error_errno(errno, "personality() failed: %m"); } else if (secondary) { if (personality(PER_LINUX32) < 0) return log_error_errno(errno, "personality() failed: %m"); } #ifdef HAVE_SELINUX if (arg_selinux_context) if (setexeccon((security_context_t) arg_selinux_context) < 0) return log_error_errno(errno, "setexeccon(\"%s\") failed: %m", arg_selinux_context); #endif r = change_uid_gid(arg_user, &home); if (r < 0) return r; /* LXC sets container=lxc, so follow the scheme here */ envp[n_env++] = strjoina("container=", arg_container_service_name); envp[n_env] = strv_find_prefix(environ, "TERM="); if (envp[n_env]) n_env ++; if ((asprintf((char**)(envp + n_env++), "HOME=%s", home ? home: "/root") < 0) || (asprintf((char**)(envp + n_env++), "USER=%s", arg_user ? arg_user : "root") < 0) || (asprintf((char**)(envp + n_env++), "LOGNAME=%s", arg_user ? arg_user : "root") < 0)) return log_oom(); if (!sd_id128_equal(arg_uuid, SD_ID128_NULL)) { char as_uuid[37]; if (asprintf((char**)(envp + n_env++), "container_uuid=%s", id128_format_as_uuid(arg_uuid, as_uuid)) < 0) return log_oom(); } if (fdset_size(fds) > 0) { r = fdset_cloexec(fds, false); if (r < 0) return log_error_errno(r, "Failed to unset O_CLOEXEC for file descriptors."); if ((asprintf((char **)(envp + n_env++), "LISTEN_FDS=%u", fdset_size(fds)) < 0) || (asprintf((char **)(envp + n_env++), "LISTEN_PID=1") < 0)) return log_oom(); } env_use = strv_env_merge(2, envp, arg_setenv); if (!env_use) return log_oom(); /* Let the parent know that we are ready and * wait until the parent is ready with the * setup, too... */ if (!barrier_place_and_sync(barrier)) { /* #4 */ log_error("Parent died too early"); return -ESRCH; } if (arg_chdir) if (chdir(arg_chdir) < 0) return log_error_errno(errno, "Failed to change to specified working directory %s: %m", arg_chdir); if (arg_start_mode == START_PID2) { r = stub_pid1(); if (r < 0) return r; } /* Now, explicitly close the log, so that we * then can close all remaining fds. Closing * the log explicitly first has the benefit * that the logging subsystem knows about it, * and is thus ready to be reopened should we * need it again. Note that the other fds * closed here are at least the locking and * barrier fds. */ log_close(); (void) fdset_close_others(fds); if (arg_start_mode == START_BOOT) { char **a; size_t m; /* Automatically search for the init system */ m = 1 + strv_length(arg_parameters); a = newa(char*, m + 1); if (strv_isempty(arg_parameters)) a[1] = NULL; else memcpy(a + 1, arg_parameters, m * sizeof(char*)); a[0] = (char*) "/usr/lib/systemd/systemd"; execve(a[0], a, env_use); a[0] = (char*) "/lib/systemd/systemd"; execve(a[0], a, env_use); a[0] = (char*) "/sbin/init"; execve(a[0], a, env_use); } else if (!strv_isempty(arg_parameters)) execvpe(arg_parameters[0], arg_parameters, env_use); else { if (!arg_chdir) chdir(home ?: "/root"); execle("/bin/bash", "-bash", NULL, env_use); execle("/bin/sh", "-sh", NULL, env_use); } r = -errno; (void) log_open(); return log_error_errno(r, "execv() failed: %m"); } static int outer_child( Barrier *barrier, const char *directory, const char *console, const char *root_device, bool root_device_rw, const char *home_device, bool home_device_rw, const char *srv_device, bool srv_device_rw, bool interactive, bool secondary, int pid_socket, int kmsg_socket, int rtnl_socket, int uid_shift_socket, FDSet *fds) { pid_t pid; ssize_t l; int r; assert(barrier); assert(directory); assert(console); assert(pid_socket >= 0); assert(kmsg_socket >= 0); cg_unified_flush(); if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0) return log_error_errno(errno, "PR_SET_PDEATHSIG failed: %m"); if (interactive) { close_nointr(STDIN_FILENO); close_nointr(STDOUT_FILENO); close_nointr(STDERR_FILENO); r = open_terminal(console, O_RDWR); if (r != STDIN_FILENO) { if (r >= 0) { safe_close(r); r = -EINVAL; } return log_error_errno(r, "Failed to open console: %m"); } if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO || dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) return log_error_errno(errno, "Failed to duplicate console: %m"); } r = reset_audit_loginuid(); if (r < 0) return r; /* Mark everything as slave, so that we still * receive mounts from the real root, but don't * propagate mounts to the real root. */ if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) return log_error_errno(errno, "MS_SLAVE|MS_REC failed: %m"); r = mount_devices(directory, root_device, root_device_rw, home_device, home_device_rw, srv_device, srv_device_rw); if (r < 0) return r; r = determine_uid_shift(directory); if (r < 0) return r; if (arg_userns) { l = send(uid_shift_socket, &arg_uid_shift, sizeof(arg_uid_shift), MSG_NOSIGNAL); if (l < 0) return log_error_errno(errno, "Failed to send UID shift: %m"); if (l != sizeof(arg_uid_shift)) { log_error("Short write while sending UID shift."); return -EIO; } } /* Turn directory into bind mount */ if (mount(directory, directory, NULL, MS_BIND|MS_REC, NULL) < 0) return log_error_errno(errno, "Failed to make bind mount: %m"); r = setup_volatile(directory, arg_volatile_mode, arg_userns, arg_uid_shift, arg_uid_range, arg_selinux_context); if (r < 0) return r; r = setup_volatile_state(directory, arg_volatile_mode, arg_userns, arg_uid_shift, arg_uid_range, arg_selinux_context); if (r < 0) return r; r = base_filesystem_create(directory, arg_uid_shift, (gid_t) arg_uid_shift); if (r < 0) return r; if (arg_read_only) { r = bind_remount_recursive(directory, true); if (r < 0) return log_error_errno(r, "Failed to make tree read-only: %m"); } r = mount_all(directory, arg_userns, false, arg_private_network, arg_uid_shift, arg_uid_range, arg_selinux_apifs_context); if (r < 0) return r; r = copy_devnodes(directory); if (r < 0) return r; dev_setup(directory, arg_uid_shift, arg_uid_shift); r = setup_pts(directory); if (r < 0) return r; r = setup_propagate(directory); if (r < 0) return r; r = setup_dev_console(directory, console); if (r < 0) return r; r = setup_seccomp(); if (r < 0) return r; r = setup_timezone(directory); if (r < 0) return r; r = setup_resolv_conf(directory); if (r < 0) return r; r = setup_journal(directory); if (r < 0) return r; r = mount_custom(directory, arg_custom_mounts, arg_n_custom_mounts, arg_userns, arg_uid_shift, arg_uid_range, arg_selinux_apifs_context); if (r < 0) return r; r = mount_cgroups(directory, arg_unified_cgroup_hierarchy, arg_userns, arg_uid_shift, arg_uid_range, arg_selinux_apifs_context); if (r < 0) return r; r = mount_move_root(directory); if (r < 0) return log_error_errno(r, "Failed to move root directory: %m"); pid = raw_clone(SIGCHLD|CLONE_NEWNS| (arg_share_system ? 0 : CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS) | (arg_private_network ? CLONE_NEWNET : 0) | (arg_userns ? CLONE_NEWUSER : 0), NULL); if (pid < 0) return log_error_errno(errno, "Failed to fork inner child: %m"); if (pid == 0) { pid_socket = safe_close(pid_socket); uid_shift_socket = safe_close(uid_shift_socket); /* The inner child has all namespaces that are * requested, so that we all are owned by the user if * user namespaces are turned on. */ r = inner_child(barrier, directory, secondary, kmsg_socket, rtnl_socket, fds); if (r < 0) _exit(EXIT_FAILURE); _exit(EXIT_SUCCESS); } l = send(pid_socket, &pid, sizeof(pid), MSG_NOSIGNAL); if (l < 0) return log_error_errno(errno, "Failed to send PID: %m"); if (l != sizeof(pid)) { log_error("Short write while sending PID."); return -EIO; } pid_socket = safe_close(pid_socket); kmsg_socket = safe_close(kmsg_socket); rtnl_socket = safe_close(rtnl_socket); return 0; } static int setup_uid_map(pid_t pid) { char uid_map[strlen("/proc//uid_map") + DECIMAL_STR_MAX(uid_t) + 1], line[DECIMAL_STR_MAX(uid_t)*3+3+1]; int r; assert(pid > 1); xsprintf(uid_map, "/proc/" PID_FMT "/uid_map", pid); xsprintf(line, UID_FMT " " UID_FMT " " UID_FMT "\n", 0, arg_uid_shift, arg_uid_range); r = write_string_file(uid_map, line, 0); if (r < 0) return log_error_errno(r, "Failed to write UID map: %m"); /* We always assign the same UID and GID ranges */ xsprintf(uid_map, "/proc/" PID_FMT "/gid_map", pid); r = write_string_file(uid_map, line, 0); if (r < 0) return log_error_errno(r, "Failed to write GID map: %m"); return 0; } static int load_settings(void) { _cleanup_(settings_freep) Settings *settings = NULL; _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; const char *fn, *i; int r; /* If all settings are masked, there's no point in looking for * the settings file */ if ((arg_settings_mask & _SETTINGS_MASK_ALL) == _SETTINGS_MASK_ALL) return 0; fn = strjoina(arg_machine, ".nspawn"); /* We first look in the admin's directories in /etc and /run */ FOREACH_STRING(i, "/etc/systemd/nspawn", "/run/systemd/nspawn") { _cleanup_free_ char *j = NULL; j = strjoin(i, "/", fn, NULL); if (!j) return log_oom(); f = fopen(j, "re"); if (f) { p = j; j = NULL; /* By default, we trust configuration from /etc and /run */ if (arg_settings_trusted < 0) arg_settings_trusted = true; break; } if (errno != ENOENT) return log_error_errno(errno, "Failed to open %s: %m", j); } if (!f) { /* After that, let's look for a file next to the * actual image we shall boot. */ if (arg_image) { p = file_in_same_dir(arg_image, fn); if (!p) return log_oom(); } else if (arg_directory) { p = file_in_same_dir(arg_directory, fn); if (!p) return log_oom(); } if (p) { f = fopen(p, "re"); if (!f && errno != ENOENT) return log_error_errno(errno, "Failed to open %s: %m", p); /* By default, we do not trust configuration from /var/lib/machines */ if (arg_settings_trusted < 0) arg_settings_trusted = false; } } if (!f) return 0; log_debug("Settings are trusted: %s", yes_no(arg_settings_trusted)); r = settings_load(f, p, &settings); if (r < 0) return r; /* Copy over bits from the settings, unless they have been * explicitly masked by command line switches. */ if ((arg_settings_mask & SETTING_START_MODE) == 0 && settings->start_mode >= 0) { arg_start_mode = settings->start_mode; strv_free(arg_parameters); arg_parameters = settings->parameters; settings->parameters = NULL; } if ((arg_settings_mask & SETTING_WORKING_DIRECTORY) == 0 && settings->working_directory) { free(arg_chdir); arg_chdir = settings->working_directory; settings->working_directory = NULL; } if ((arg_settings_mask & SETTING_ENVIRONMENT) == 0 && settings->environment) { strv_free(arg_setenv); arg_setenv = settings->environment; settings->environment = NULL; } if ((arg_settings_mask & SETTING_USER) == 0 && settings->user) { free(arg_user); arg_user = settings->user; settings->user = NULL; } if ((arg_settings_mask & SETTING_CAPABILITY) == 0) { uint64_t plus; plus = settings->capability; if (settings_private_network(settings)) plus |= (1ULL << CAP_NET_ADMIN); if (!arg_settings_trusted && plus != 0) { if (settings->capability != 0) log_warning("Ignoring Capability= setting, file %s is not trusted.", p); } else arg_retain |= plus; arg_retain &= ~settings->drop_capability; } if ((arg_settings_mask & SETTING_KILL_SIGNAL) == 0 && settings->kill_signal > 0) arg_kill_signal = settings->kill_signal; if ((arg_settings_mask & SETTING_PERSONALITY) == 0 && settings->personality != PERSONALITY_INVALID) arg_personality = settings->personality; if ((arg_settings_mask & SETTING_MACHINE_ID) == 0 && !sd_id128_is_null(settings->machine_id)) { if (!arg_settings_trusted) log_warning("Ignoring MachineID= setting, file %s is not trusted.", p); else arg_uuid = settings->machine_id; } if ((arg_settings_mask & SETTING_READ_ONLY) == 0 && settings->read_only >= 0) arg_read_only = settings->read_only; if ((arg_settings_mask & SETTING_VOLATILE_MODE) == 0 && settings->volatile_mode != _VOLATILE_MODE_INVALID) arg_volatile_mode = settings->volatile_mode; if ((arg_settings_mask & SETTING_CUSTOM_MOUNTS) == 0 && settings->n_custom_mounts > 0) { if (!arg_settings_trusted) log_warning("Ignoring TemporaryFileSystem=, Bind= and BindReadOnly= settings, file %s is not trusted.", p); else { custom_mount_free_all(arg_custom_mounts, arg_n_custom_mounts); arg_custom_mounts = settings->custom_mounts; arg_n_custom_mounts = settings->n_custom_mounts; settings->custom_mounts = NULL; settings->n_custom_mounts = 0; } } if ((arg_settings_mask & SETTING_NETWORK) == 0 && (settings->private_network >= 0 || settings->network_veth >= 0 || settings->network_bridge || settings->network_interfaces || settings->network_macvlan || settings->network_ipvlan || settings->network_veth_extra)) { if (!arg_settings_trusted) log_warning("Ignoring network settings, file %s is not trusted.", p); else { arg_network_veth = settings_network_veth(settings); arg_private_network = settings_private_network(settings); strv_free(arg_network_interfaces); arg_network_interfaces = settings->network_interfaces; settings->network_interfaces = NULL; strv_free(arg_network_macvlan); arg_network_macvlan = settings->network_macvlan; settings->network_macvlan = NULL; strv_free(arg_network_ipvlan); arg_network_ipvlan = settings->network_ipvlan; settings->network_ipvlan = NULL; strv_free(arg_network_veth_extra); arg_network_veth_extra = settings->network_veth_extra; settings->network_veth_extra = NULL; free(arg_network_bridge); arg_network_bridge = settings->network_bridge; settings->network_bridge = NULL; } } if ((arg_settings_mask & SETTING_EXPOSE_PORTS) == 0 && settings->expose_ports) { if (!arg_settings_trusted) log_warning("Ignoring Port= setting, file %s is not trusted.", p); else { expose_port_free_all(arg_expose_ports); arg_expose_ports = settings->expose_ports; settings->expose_ports = NULL; } } return 0; } int main(int argc, char *argv[]) { _cleanup_free_ char *device_path = NULL, *root_device = NULL, *home_device = NULL, *srv_device = NULL, *console = NULL; bool root_device_rw = true, home_device_rw = true, srv_device_rw = true; _cleanup_close_ int master = -1, image_fd = -1; _cleanup_fdset_free_ FDSet *fds = NULL; int r, n_fd_passed, loop_nr = -1; char veth_name[IFNAMSIZ]; bool secondary = false, remove_subvol = false; sigset_t mask_chld; pid_t pid = 0; int ret = EXIT_SUCCESS; union in_addr_union exposed = {}; _cleanup_release_lock_file_ LockFile tree_global_lock = LOCK_FILE_INIT, tree_local_lock = LOCK_FILE_INIT; bool interactive; log_parse_environment(); log_open(); /* Make sure rename_process() in the stub init process can work */ saved_argv = argv; saved_argc = argc; r = parse_argv(argc, argv); if (r <= 0) goto finish; if (geteuid() != 0) { log_error("Need to be root."); r = -EPERM; goto finish; } r = determine_names(); if (r < 0) goto finish; r = load_settings(); if (r < 0) goto finish; r = verify_arguments(); if (r < 0) goto finish; n_fd_passed = sd_listen_fds(false); if (n_fd_passed > 0) { r = fdset_new_listen_fds(&fds, false); if (r < 0) { log_error_errno(r, "Failed to collect file descriptors: %m"); goto finish; } } if (arg_directory) { assert(!arg_image); if (path_equal(arg_directory, "/") && !arg_ephemeral) { log_error("Spawning container on root directory is not supported. Consider using --ephemeral."); r = -EINVAL; goto finish; } if (arg_ephemeral) { _cleanup_free_ char *np = NULL; /* If the specified path is a mount point we * generate the new snapshot immediately * inside it under a random name. However if * the specified is not a mount point we * create the new snapshot in the parent * directory, just next to it. */ r = path_is_mount_point(arg_directory, 0); if (r < 0) { log_error_errno(r, "Failed to determine whether directory %s is mount point: %m", arg_directory); goto finish; } if (r > 0) r = tempfn_random_child(arg_directory, "machine.", &np); else r = tempfn_random(arg_directory, "machine.", &np); if (r < 0) { log_error_errno(r, "Failed to generate name for snapshot: %m"); goto finish; } r = image_path_lock(np, (arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB, &tree_global_lock, &tree_local_lock); if (r < 0) { log_error_errno(r, "Failed to lock %s: %m", np); goto finish; } r = btrfs_subvol_snapshot(arg_directory, np, (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY | BTRFS_SNAPSHOT_RECURSIVE | BTRFS_SNAPSHOT_QUOTA); if (r < 0) { log_error_errno(r, "Failed to create snapshot %s from %s: %m", np, arg_directory); goto finish; } free(arg_directory); arg_directory = np; np = NULL; remove_subvol = true; } else { r = image_path_lock(arg_directory, (arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB, &tree_global_lock, &tree_local_lock); if (r == -EBUSY) { log_error_errno(r, "Directory tree %s is currently busy.", arg_directory); goto finish; } if (r < 0) { log_error_errno(r, "Failed to lock %s: %m", arg_directory); return r; } if (arg_template) { r = btrfs_subvol_snapshot(arg_template, arg_directory, (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY | BTRFS_SNAPSHOT_RECURSIVE | BTRFS_SNAPSHOT_QUOTA); if (r == -EEXIST) { if (!arg_quiet) log_info("Directory %s already exists, not populating from template %s.", arg_directory, arg_template); } else if (r < 0) { log_error_errno(r, "Couldn't create snapshot %s from %s: %m", arg_directory, arg_template); goto finish; } else { if (!arg_quiet) log_info("Populated %s from template %s.", arg_directory, arg_template); } } } if (arg_start_mode == START_BOOT) { if (path_is_os_tree(arg_directory) <= 0) { log_error("Directory %s doesn't look like an OS root directory (os-release file is missing). Refusing.", arg_directory); r = -EINVAL; goto finish; } } else { const char *p; p = strjoina(arg_directory, "/usr/"); if (laccess(p, F_OK) < 0) { log_error("Directory %s doesn't look like it has an OS tree. Refusing.", arg_directory); r = -EINVAL; goto finish; } } } else { char template[] = "/tmp/nspawn-root-XXXXXX"; assert(arg_image); assert(!arg_template); r = image_path_lock(arg_image, (arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB, &tree_global_lock, &tree_local_lock); if (r == -EBUSY) { r = log_error_errno(r, "Disk image %s is currently busy.", arg_image); goto finish; } if (r < 0) { r = log_error_errno(r, "Failed to create image lock: %m"); goto finish; } if (!mkdtemp(template)) { log_error_errno(errno, "Failed to create temporary directory: %m"); r = -errno; goto finish; } arg_directory = strdup(template); if (!arg_directory) { r = log_oom(); goto finish; } image_fd = setup_image(&device_path, &loop_nr); if (image_fd < 0) { r = image_fd; goto finish; } r = dissect_image(image_fd, &root_device, &root_device_rw, &home_device, &home_device_rw, &srv_device, &srv_device_rw, &secondary); if (r < 0) goto finish; } r = custom_mounts_prepare(); if (r < 0) goto finish; interactive = isatty(STDIN_FILENO) > 0 && isatty(STDOUT_FILENO) > 0; master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY); if (master < 0) { r = log_error_errno(errno, "Failed to acquire pseudo tty: %m"); goto finish; } r = ptsname_malloc(master, &console); if (r < 0) { r = log_error_errno(r, "Failed to determine tty name: %m"); goto finish; } if (unlockpt(master) < 0) { r = log_error_errno(errno, "Failed to unlock tty: %m"); goto finish; } if (!arg_quiet) log_info("Spawning container %s on %s.\nPress ^] three times within 1s to kill container.", arg_machine, arg_image ?: arg_directory); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1) >= 0); assert_se(sigemptyset(&mask_chld) == 0); assert_se(sigaddset(&mask_chld, SIGCHLD) == 0); if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) { r = log_error_errno(errno, "Failed to become subreaper: %m"); goto finish; } for (;;) { _cleanup_close_pair_ int kmsg_socket_pair[2] = { -1, -1 }, rtnl_socket_pair[2] = { -1, -1 }, pid_socket_pair[2] = { -1, -1 }, uid_shift_socket_pair[2] = { -1, -1 }; ContainerStatus container_status; _cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL; static const struct sigaction sa = { .sa_handler = nop_signal_handler, .sa_flags = SA_NOCLDSTOP, }; int ifi = 0; ssize_t l; _cleanup_(sd_event_unrefp) sd_event *event = NULL; _cleanup_(pty_forward_freep) PTYForward *forward = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; char last_char = 0; r = barrier_create(&barrier); if (r < 0) { log_error_errno(r, "Cannot initialize IPC barrier: %m"); goto finish; } if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) { r = log_error_errno(errno, "Failed to create kmsg socket pair: %m"); goto finish; } if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, rtnl_socket_pair) < 0) { r = log_error_errno(errno, "Failed to create rtnl socket pair: %m"); goto finish; } if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pid_socket_pair) < 0) { r = log_error_errno(errno, "Failed to create pid socket pair: %m"); goto finish; } if (arg_userns) if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, uid_shift_socket_pair) < 0) { r = log_error_errno(errno, "Failed to create uid shift socket pair: %m"); goto finish; } /* Child can be killed before execv(), so handle SIGCHLD * in order to interrupt parent's blocking calls and * give it a chance to call wait() and terminate. */ r = sigprocmask(SIG_UNBLOCK, &mask_chld, NULL); if (r < 0) { r = log_error_errno(errno, "Failed to change the signal mask: %m"); goto finish; } r = sigaction(SIGCHLD, &sa, NULL); if (r < 0) { r = log_error_errno(errno, "Failed to install SIGCHLD handler: %m"); goto finish; } pid = raw_clone(SIGCHLD|CLONE_NEWNS, NULL); if (pid < 0) { if (errno == EINVAL) r = log_error_errno(errno, "clone() failed, do you have namespace support enabled in your kernel? (You need UTS, IPC, PID and NET namespacing built in): %m"); else r = log_error_errno(errno, "clone() failed: %m"); goto finish; } if (pid == 0) { /* The outer child only has a file system namespace. */ barrier_set_role(&barrier, BARRIER_CHILD); master = safe_close(master); kmsg_socket_pair[0] = safe_close(kmsg_socket_pair[0]); rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]); pid_socket_pair[0] = safe_close(pid_socket_pair[0]); uid_shift_socket_pair[0] = safe_close(uid_shift_socket_pair[0]); (void) reset_all_signal_handlers(); (void) reset_signal_mask(); r = outer_child(&barrier, arg_directory, console, root_device, root_device_rw, home_device, home_device_rw, srv_device, srv_device_rw, interactive, secondary, pid_socket_pair[1], kmsg_socket_pair[1], rtnl_socket_pair[1], uid_shift_socket_pair[1], fds); if (r < 0) _exit(EXIT_FAILURE); _exit(EXIT_SUCCESS); } barrier_set_role(&barrier, BARRIER_PARENT); fds = fdset_free(fds); kmsg_socket_pair[1] = safe_close(kmsg_socket_pair[1]); rtnl_socket_pair[1] = safe_close(rtnl_socket_pair[1]); pid_socket_pair[1] = safe_close(pid_socket_pair[1]); uid_shift_socket_pair[1] = safe_close(uid_shift_socket_pair[1]); /* Wait for the outer child. */ r = wait_for_terminate_and_warn("namespace helper", pid, NULL); if (r < 0) goto finish; if (r != 0) { r = -EIO; goto finish; } pid = 0; /* And now retrieve the PID of the inner child. */ l = recv(pid_socket_pair[0], &pid, sizeof(pid), 0); if (l < 0) { r = log_error_errno(errno, "Failed to read inner child PID: %m"); goto finish; } if (l != sizeof(pid)) { log_error("Short read while reading inner child PID."); r = EIO; goto finish; } log_debug("Init process invoked as PID " PID_FMT, pid); if (arg_userns) { if (!barrier_place_and_sync(&barrier)) { /* #1 */ log_error("Child died too early."); r = -ESRCH; goto finish; } l = recv(uid_shift_socket_pair[0], &arg_uid_shift, sizeof(arg_uid_shift), 0); if (l < 0) { r = log_error_errno(errno, "Failed to read UID shift: %m"); goto finish; } if (l != sizeof(arg_uid_shift)) { log_error("Short read while reading UID shift."); r = EIO; goto finish; } r = setup_uid_map(pid); if (r < 0) goto finish; (void) barrier_place(&barrier); /* #2 */ } if (arg_private_network) { r = move_network_interfaces(pid, arg_network_interfaces); if (r < 0) goto finish; if (arg_network_veth) { r = setup_veth(arg_machine, pid, veth_name, !!arg_network_bridge); if (r < 0) goto finish; else if (r > 0) ifi = r; if (arg_network_bridge) { r = setup_bridge(veth_name, arg_network_bridge); if (r < 0) goto finish; if (r > 0) ifi = r; } } r = setup_veth_extra(arg_machine, pid, arg_network_veth_extra); if (r < 0) goto finish; r = setup_macvlan(arg_machine, pid, arg_network_macvlan); if (r < 0) goto finish; r = setup_ipvlan(arg_machine, pid, arg_network_ipvlan); if (r < 0) goto finish; } if (arg_register) { r = register_machine( arg_machine, pid, arg_directory, arg_uuid, ifi, arg_slice, arg_custom_mounts, arg_n_custom_mounts, arg_kill_signal, arg_property, arg_keep_unit, arg_container_service_name); if (r < 0) goto finish; } r = sync_cgroup(pid, arg_unified_cgroup_hierarchy); if (r < 0) goto finish; if (arg_keep_unit) { r = create_subcgroup(pid, arg_unified_cgroup_hierarchy); if (r < 0) goto finish; } r = chown_cgroup(pid, arg_uid_shift); if (r < 0) goto finish; /* Notify the child that the parent is ready with all * its setup (including cgroup-ification), and that * the child can now hand over control to the code to * run inside the container. */ (void) barrier_place(&barrier); /* #3 */ /* Block SIGCHLD here, before notifying child. * process_pty() will handle it with the other signals. */ assert_se(sigprocmask(SIG_BLOCK, &mask_chld, NULL) >= 0); /* Reset signal to default */ r = default_signals(SIGCHLD, -1); if (r < 0) { log_error_errno(r, "Failed to reset SIGCHLD: %m"); goto finish; } /* Let the child know that we are ready and wait that the child is completely ready now. */ if (!barrier_place_and_sync(&barrier)) { /* #4 */ log_error("Child died too early."); r = -ESRCH; goto finish; } sd_notifyf(false, "READY=1\n" "STATUS=Container running.\n" "X_NSPAWN_LEADER_PID=" PID_FMT, pid); r = sd_event_new(&event); if (r < 0) { log_error_errno(r, "Failed to get default event source: %m"); goto finish; } if (arg_kill_signal > 0) { /* Try to kill the init system on SIGINT or SIGTERM */ sd_event_add_signal(event, NULL, SIGINT, on_orderly_shutdown, PID_TO_PTR(pid)); sd_event_add_signal(event, NULL, SIGTERM, on_orderly_shutdown, PID_TO_PTR(pid)); } else { /* Immediately exit */ sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); } /* simply exit on sigchld */ sd_event_add_signal(event, NULL, SIGCHLD, NULL, NULL); if (arg_expose_ports) { r = expose_port_watch_rtnl(event, rtnl_socket_pair[0], on_address_change, &exposed, &rtnl); if (r < 0) goto finish; (void) expose_port_execute(rtnl, arg_expose_ports, &exposed); } rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]); r = pty_forward_new(event, master, PTY_FORWARD_IGNORE_VHANGUP | (interactive ? 0 : PTY_FORWARD_READ_ONLY), &forward); if (r < 0) { log_error_errno(r, "Failed to create PTY forwarder: %m"); goto finish; } r = sd_event_loop(event); if (r < 0) { log_error_errno(r, "Failed to run event loop: %m"); goto finish; } pty_forward_get_last_char(forward, &last_char); forward = pty_forward_free(forward); if (!arg_quiet && last_char != '\n') putc('\n', stdout); /* Kill if it is not dead yet anyway */ if (arg_register && !arg_keep_unit) terminate_machine(pid); /* Normally redundant, but better safe than sorry */ kill(pid, SIGKILL); r = wait_for_container(pid, &container_status); pid = 0; if (r < 0) /* We failed to wait for the container, or the * container exited abnormally */ goto finish; else if (r > 0 || container_status == CONTAINER_TERMINATED){ /* The container exited with a non-zero * status, or with zero status and no reboot * was requested. */ ret = r; break; } /* CONTAINER_REBOOTED, loop again */ if (arg_keep_unit) { /* Special handling if we are running as a * service: instead of simply restarting the * machine we want to restart the entire * service, so let's inform systemd about this * with the special exit code 133. The service * file uses RestartForceExitStatus=133 so * that this results in a full nspawn * restart. This is necessary since we might * have cgroup parameters set we want to have * flushed out. */ ret = 133; r = 0; break; } expose_port_flush(arg_expose_ports, &exposed); } finish: sd_notify(false, "STOPPING=1\n" "STATUS=Terminating..."); if (pid > 0) kill(pid, SIGKILL); /* Try to flush whatever is still queued in the pty */ if (master >= 0) (void) copy_bytes(master, STDOUT_FILENO, (uint64_t) -1, false); loop_remove(loop_nr, &image_fd); if (remove_subvol && arg_directory) { int k; k = btrfs_subvol_remove(arg_directory, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); if (k < 0) log_warning_errno(k, "Cannot remove subvolume '%s', ignoring: %m", arg_directory); } if (arg_machine) { const char *p; p = strjoina("/run/systemd/nspawn/propagate/", arg_machine); (void) rm_rf(p, REMOVE_ROOT); } expose_port_flush(arg_expose_ports, &exposed); free(arg_directory); free(arg_template); free(arg_image); free(arg_machine); free(arg_user); free(arg_chdir); strv_free(arg_setenv); free(arg_network_bridge); strv_free(arg_network_interfaces); strv_free(arg_network_macvlan); strv_free(arg_network_ipvlan); strv_free(arg_network_veth_extra); strv_free(arg_parameters); custom_mount_free_all(arg_custom_mounts, arg_n_custom_mounts); expose_port_free_all(arg_expose_ports); return r < 0 ? EXIT_FAILURE : ret; } systemd-229/src/nss-myhostname/000077500000000000000000000000001265713322000166355ustar00rootroot00000000000000systemd-229/src/nss-myhostname/Makefile000077700000000000000000000000001265713322000221432../Makefileustar00rootroot00000000000000systemd-229/src/nss-myhostname/nss-myhostname.c000066400000000000000000000404471265713322000217770ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "alloc-util.h" #include "hostname-util.h" #include "local-addresses.h" #include "macro.h" #include "nss-util.h" #include "signal-util.h" #include "string-util.h" #include "util.h" /* We use 127.0.0.2 as IPv4 address. This has the advantage over * 127.0.0.1 that it can be translated back to the local hostname. For * IPv6 we use ::1 which unfortunately will not translate back to the * hostname but instead something like "localhost" or so. */ #define LOCALADDRESS_IPV4 (htonl(0x7F000002)) #define LOCALADDRESS_IPV6 &in6addr_loopback NSS_GETHOSTBYNAME_PROTOTYPES(myhostname); NSS_GETHOSTBYADDR_PROTOTYPES(myhostname); enum nss_status _nss_myhostname_gethostbyname4_r( const char *name, struct gaih_addrtuple **pat, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp) { struct gaih_addrtuple *r_tuple, *r_tuple_prev = NULL; _cleanup_free_ struct local_address *addresses = NULL; _cleanup_free_ char *hn = NULL; const char *canonical = NULL; int n_addresses = 0, lo_ifi; uint32_t local_address_ipv4; struct local_address *a; size_t l, idx, ms; char *r_name; unsigned n; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); assert(pat); assert(buffer); assert(errnop); assert(h_errnop); if (is_localhost(name)) { /* We respond to 'localhost', so that /etc/hosts * is optional */ canonical = "localhost"; local_address_ipv4 = htonl(INADDR_LOOPBACK); } else if (is_gateway_hostname(name)) { n_addresses = local_gateways(NULL, 0, AF_UNSPEC, &addresses); if (n_addresses <= 0) { *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } canonical = "gateway"; } else { hn = gethostname_malloc(); if (!hn) { *errnop = ENOMEM; *h_errnop = NO_RECOVERY; return NSS_STATUS_TRYAGAIN; } /* We respond to our local host name, our our hostname suffixed with a single dot. */ if (!streq(name, hn) && !streq_ptr(startswith(name, hn), ".")) { *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } n_addresses = local_addresses(NULL, 0, AF_UNSPEC, &addresses); if (n_addresses < 0) n_addresses = 0; canonical = hn; local_address_ipv4 = LOCALADDRESS_IPV4; } /* If this call fails we fill in 0 as scope. Which is fine */ lo_ifi = n_addresses <= 0 ? LOOPBACK_IFINDEX : 0; l = strlen(canonical); ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * (n_addresses > 0 ? n_addresses : 2); if (buflen < ms) { *errnop = ENOMEM; *h_errnop = NO_RECOVERY; return NSS_STATUS_TRYAGAIN; } /* First, fill in hostname */ r_name = buffer; memcpy(r_name, canonical, l+1); idx = ALIGN(l+1); if (n_addresses <= 0) { /* Second, fill in IPv6 tuple */ r_tuple = (struct gaih_addrtuple*) (buffer + idx); r_tuple->next = r_tuple_prev; r_tuple->name = r_name; r_tuple->family = AF_INET6; memcpy(r_tuple->addr, LOCALADDRESS_IPV6, 16); r_tuple->scopeid = (uint32_t) lo_ifi; idx += ALIGN(sizeof(struct gaih_addrtuple)); r_tuple_prev = r_tuple; /* Third, fill in IPv4 tuple */ r_tuple = (struct gaih_addrtuple*) (buffer + idx); r_tuple->next = r_tuple_prev; r_tuple->name = r_name; r_tuple->family = AF_INET; *(uint32_t*) r_tuple->addr = local_address_ipv4; r_tuple->scopeid = (uint32_t) lo_ifi; idx += ALIGN(sizeof(struct gaih_addrtuple)); r_tuple_prev = r_tuple; } /* Fourth, fill actual addresses in, but in backwards order */ for (a = addresses + n_addresses - 1, n = 0; (int) n < n_addresses; n++, a--) { r_tuple = (struct gaih_addrtuple*) (buffer + idx); r_tuple->next = r_tuple_prev; r_tuple->name = r_name; r_tuple->family = a->family; r_tuple->scopeid = a->ifindex; memcpy(r_tuple->addr, &a->address, 16); idx += ALIGN(sizeof(struct gaih_addrtuple)); r_tuple_prev = r_tuple; } /* Verify the size matches */ assert(idx == ms); /* Nscd expects us to store the first record in **pat. */ if (*pat) **pat = *r_tuple_prev; else *pat = r_tuple_prev; if (ttlp) *ttlp = 0; /* Explicitly reset all error variables */ *errnop = 0; *h_errnop = NETDB_SUCCESS; h_errno = 0; return NSS_STATUS_SUCCESS; } static enum nss_status fill_in_hostent( const char *canonical, const char *additional, int af, struct local_address *addresses, unsigned n_addresses, uint32_t local_address_ipv4, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) { size_t l_canonical, l_additional, idx, ms, alen; char *r_addr, *r_name, *r_aliases, *r_alias = NULL, *r_addr_list; struct local_address *a; unsigned n, c; assert(canonical); assert(result); assert(buffer); assert(errnop); assert(h_errnop); alen = FAMILY_ADDRESS_SIZE(af); for (a = addresses, n = 0, c = 0; n < n_addresses; a++, n++) if (af == a->family) c++; l_canonical = strlen(canonical); l_additional = additional ? strlen(additional) : 0; ms = ALIGN(l_canonical+1)+ (additional ? ALIGN(l_additional+1) : 0) + sizeof(char*) + (additional ? sizeof(char*) : 0) + (c > 0 ? c : 1) * ALIGN(alen) + (c > 0 ? c+1 : 2) * sizeof(char*); if (buflen < ms) { *errnop = ENOMEM; *h_errnop = NO_RECOVERY; return NSS_STATUS_TRYAGAIN; } /* First, fill in hostnames */ r_name = buffer; memcpy(r_name, canonical, l_canonical+1); idx = ALIGN(l_canonical+1); if (additional) { r_alias = buffer + idx; memcpy(r_alias, additional, l_additional+1); idx += ALIGN(l_additional+1); } /* Second, create aliases array */ r_aliases = buffer + idx; if (additional) { ((char**) r_aliases)[0] = r_alias; ((char**) r_aliases)[1] = NULL; idx += 2*sizeof(char*); } else { ((char**) r_aliases)[0] = NULL; idx += sizeof(char*); } /* Third, add addresses */ r_addr = buffer + idx; if (c > 0) { unsigned i = 0; for (a = addresses, n = 0; n < n_addresses; a++, n++) { if (af != a->family) continue; memcpy(r_addr + i*ALIGN(alen), &a->address, alen); i++; } assert(i == c); idx += c*ALIGN(alen); } else { if (af == AF_INET) *(uint32_t*) r_addr = local_address_ipv4; else memcpy(r_addr, LOCALADDRESS_IPV6, 16); idx += ALIGN(alen); } /* Fourth, add address pointer array */ r_addr_list = buffer + idx; if (c > 0) { unsigned i; for (i = 0; i < c; i++) ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen); ((char**) r_addr_list)[i] = NULL; idx += (c+1) * sizeof(char*); } else { ((char**) r_addr_list)[0] = r_addr; ((char**) r_addr_list)[1] = NULL; idx += 2 * sizeof(char*); } /* Verify the size matches */ assert(idx == ms); result->h_name = r_name; result->h_aliases = (char**) r_aliases; result->h_addrtype = af; result->h_length = alen; result->h_addr_list = (char**) r_addr_list; if (ttlp) *ttlp = 0; if (canonp) *canonp = r_name; /* Explicitly reset all error variables */ *errnop = 0; *h_errnop = NETDB_SUCCESS; h_errno = 0; return NSS_STATUS_SUCCESS; } enum nss_status _nss_myhostname_gethostbyname3_r( const char *name, int af, struct hostent *host, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) { _cleanup_free_ struct local_address *addresses = NULL; const char *canonical, *additional = NULL; _cleanup_free_ char *hn = NULL; uint32_t local_address_ipv4 = 0; int n_addresses = 0; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); assert(host); assert(buffer); assert(errnop); assert(h_errnop); if (af == AF_UNSPEC) af = AF_INET; if (af != AF_INET && af != AF_INET6) { *errnop = EAFNOSUPPORT; *h_errnop = NO_DATA; return NSS_STATUS_UNAVAIL; } if (is_localhost(name)) { canonical = "localhost"; local_address_ipv4 = htonl(INADDR_LOOPBACK); } else if (is_gateway_hostname(name)) { n_addresses = local_gateways(NULL, 0, af, &addresses); if (n_addresses <= 0) { *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } canonical = "gateway"; } else { hn = gethostname_malloc(); if (!hn) { *errnop = ENOMEM; *h_errnop = NO_RECOVERY; return NSS_STATUS_TRYAGAIN; } if (!streq(name, hn) && !streq_ptr(startswith(name, hn), ".")) { *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } n_addresses = local_addresses(NULL, 0, af, &addresses); if (n_addresses < 0) n_addresses = 0; canonical = hn; additional = n_addresses <= 0 && af == AF_INET6 ? "localhost" : NULL; local_address_ipv4 = LOCALADDRESS_IPV4; } return fill_in_hostent( canonical, additional, af, addresses, n_addresses, local_address_ipv4, host, buffer, buflen, errnop, h_errnop, ttlp, canonp); } enum nss_status _nss_myhostname_gethostbyaddr2_r( const void* addr, socklen_t len, int af, struct hostent *host, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp) { const char *canonical = NULL, *additional = NULL; uint32_t local_address_ipv4 = LOCALADDRESS_IPV4; _cleanup_free_ struct local_address *addresses = NULL; _cleanup_free_ char *hn = NULL; int n_addresses = 0; struct local_address *a; bool additional_from_hostname = false; unsigned n; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(addr); assert(host); assert(buffer); assert(errnop); assert(h_errnop); if (!IN_SET(af, AF_INET, AF_INET6)) { *errnop = EAFNOSUPPORT; *h_errnop = NO_DATA; return NSS_STATUS_UNAVAIL; } if (len != FAMILY_ADDRESS_SIZE(af)) { *errnop = EINVAL; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; } if (af == AF_INET) { if ((*(uint32_t*) addr) == LOCALADDRESS_IPV4) goto found; if ((*(uint32_t*) addr) == htonl(INADDR_LOOPBACK)) { canonical = "localhost"; local_address_ipv4 = htonl(INADDR_LOOPBACK); goto found; } } else { assert(af == AF_INET6); if (memcmp(addr, LOCALADDRESS_IPV6, 16) == 0) { canonical = "localhost"; additional_from_hostname = true; goto found; } } n_addresses = local_addresses(NULL, 0, AF_UNSPEC, &addresses); if (n_addresses > 0) { for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { if (af != a->family) continue; if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) goto found; } } addresses = mfree(addresses); n_addresses = local_gateways(NULL, 0, AF_UNSPEC, &addresses); if (n_addresses > 0) { for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { if (af != a->family) continue; if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) { canonical = "gateway"; goto found; } } } *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; found: if (!canonical || (!additional && additional_from_hostname)) { hn = gethostname_malloc(); if (!hn) { *errnop = ENOMEM; *h_errnop = NO_RECOVERY; return NSS_STATUS_TRYAGAIN; } if (!canonical) canonical = hn; if (!additional && additional_from_hostname) additional = hn; } return fill_in_hostent( canonical, additional, af, addresses, n_addresses, local_address_ipv4, host, buffer, buflen, errnop, h_errnop, ttlp, NULL); } NSS_GETHOSTBYNAME_FALLBACKS(myhostname); NSS_GETHOSTBYADDR_FALLBACKS(myhostname); systemd-229/src/nss-myhostname/nss-myhostname.sym000066400000000000000000000010711265713322000223530ustar00rootroot00000000000000/*** This file is part of systemd. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. ***/ { global: _nss_myhostname_gethostbyname_r; _nss_myhostname_gethostbyname2_r; _nss_myhostname_gethostbyname3_r; _nss_myhostname_gethostbyname4_r; _nss_myhostname_gethostbyaddr_r; _nss_myhostname_gethostbyaddr2_r; local: *; }; systemd-229/src/nss-mymachines/000077500000000000000000000000001265713322000166065ustar00rootroot00000000000000systemd-229/src/nss-mymachines/Makefile000077700000000000000000000000001265713322000221142../Makefileustar00rootroot00000000000000systemd-229/src/nss-mymachines/nss-mymachines.c000066400000000000000000000512101265713322000217070ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-bus.h" #include "sd-login.h" #include "alloc-util.h" #include "bus-common-errors.h" #include "hostname-util.h" #include "in-addr-util.h" #include "macro.h" #include "nss-util.h" #include "signal-util.h" #include "string-util.h" #include "user-util.h" #include "util.h" NSS_GETHOSTBYNAME_PROTOTYPES(mymachines); NSS_GETPW_PROTOTYPES(mymachines); NSS_GETGR_PROTOTYPES(mymachines); #define HOST_UID_LIMIT ((uid_t) UINT32_C(0x10000)) #define HOST_GID_LIMIT ((gid_t) UINT32_C(0x10000)) static int count_addresses(sd_bus_message *m, int af, unsigned *ret) { unsigned c = 0; int r; assert(m); assert(ret); while ((r = sd_bus_message_enter_container(m, 'r', "iay")) > 0) { int family; r = sd_bus_message_read(m, "i", &family); if (r < 0) return r; r = sd_bus_message_skip(m, "ay"); if (r < 0) return r; r = sd_bus_message_exit_container(m); if (r < 0) return r; if (af != AF_UNSPEC && family != af) continue; c ++; } if (r < 0) return r; r = sd_bus_message_rewind(m, false); if (r < 0) return r; *ret = c; return 0; } enum nss_status _nss_mymachines_gethostbyname4_r( const char *name, struct gaih_addrtuple **pat, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp) { struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_free_ int *ifindices = NULL; _cleanup_free_ char *class = NULL; size_t l, ms, idx; unsigned i = 0, c = 0; char *r_name; int n_ifindices, r; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); assert(pat); assert(buffer); assert(errnop); assert(h_errnop); r = sd_machine_get_class(name, &class); if (r < 0) goto fail; if (!streq(class, "container")) { r = -ENOTTY; goto fail; } n_ifindices = sd_machine_get_ifindices(name, &ifindices); if (n_ifindices < 0) { r = n_ifindices; goto fail; } r = sd_bus_open_system(&bus); if (r < 0) goto fail; r = sd_bus_call_method(bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "GetMachineAddresses", NULL, &reply, "s", name); if (r < 0) goto fail; r = sd_bus_message_enter_container(reply, 'a', "(iay)"); if (r < 0) goto fail; r = count_addresses(reply, AF_UNSPEC, &c); if (r < 0) goto fail; if (c <= 0) { *errnop = ESRCH; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } l = strlen(name); ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c; if (buflen < ms) { *errnop = ENOMEM; *h_errnop = TRY_AGAIN; return NSS_STATUS_TRYAGAIN; } /* First, append name */ r_name = buffer; memcpy(r_name, name, l+1); idx = ALIGN(l+1); /* Second, append addresses */ r_tuple_first = (struct gaih_addrtuple*) (buffer + idx); while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) { int family; const void *a; size_t sz; r = sd_bus_message_read(reply, "i", &family); if (r < 0) goto fail; r = sd_bus_message_read_array(reply, 'y', &a, &sz); if (r < 0) goto fail; r = sd_bus_message_exit_container(reply); if (r < 0) goto fail; if (!IN_SET(family, AF_INET, AF_INET6)) { r = -EAFNOSUPPORT; goto fail; } if (sz != FAMILY_ADDRESS_SIZE(family)) { r = -EINVAL; goto fail; } r_tuple = (struct gaih_addrtuple*) (buffer + idx); r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple))); r_tuple->name = r_name; r_tuple->family = family; r_tuple->scopeid = n_ifindices == 1 ? ifindices[0] : 0; memcpy(r_tuple->addr, a, sz); idx += ALIGN(sizeof(struct gaih_addrtuple)); i++; } assert(i == c); r = sd_bus_message_exit_container(reply); if (r < 0) goto fail; assert(idx == ms); if (*pat) **pat = *r_tuple_first; else *pat = r_tuple_first; if (ttlp) *ttlp = 0; /* Explicitly reset all error variables */ *errnop = 0; *h_errnop = NETDB_SUCCESS; h_errno = 0; return NSS_STATUS_SUCCESS; fail: *errnop = -r; *h_errnop = NO_DATA; return NSS_STATUS_UNAVAIL; } enum nss_status _nss_mymachines_gethostbyname3_r( const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) { _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_free_ char *class = NULL; unsigned c = 0, i = 0; char *r_name, *r_aliases, *r_addr, *r_addr_list; size_t l, idx, ms, alen; int r; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); assert(result); assert(buffer); assert(errnop); assert(h_errnop); if (af == AF_UNSPEC) af = AF_INET; if (af != AF_INET && af != AF_INET6) { r = -EAFNOSUPPORT; goto fail; } r = sd_machine_get_class(name, &class); if (r < 0) goto fail; if (!streq(class, "container")) { r = -ENOTTY; goto fail; } r = sd_bus_open_system(&bus); if (r < 0) goto fail; r = sd_bus_call_method(bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "GetMachineAddresses", NULL, &reply, "s", name); if (r < 0) goto fail; r = sd_bus_message_enter_container(reply, 'a', "(iay)"); if (r < 0) goto fail; r = count_addresses(reply, af, &c); if (r < 0) goto fail; if (c <= 0) { *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } alen = FAMILY_ADDRESS_SIZE(af); l = strlen(name); ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*); if (buflen < ms) { *errnop = ENOMEM; *h_errnop = NO_RECOVERY; return NSS_STATUS_TRYAGAIN; } /* First, append name */ r_name = buffer; memcpy(r_name, name, l+1); idx = ALIGN(l+1); /* Second, create aliases array */ r_aliases = buffer + idx; ((char**) r_aliases)[0] = NULL; idx += sizeof(char*); /* Third, append addresses */ r_addr = buffer + idx; while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) { int family; const void *a; size_t sz; r = sd_bus_message_read(reply, "i", &family); if (r < 0) goto fail; r = sd_bus_message_read_array(reply, 'y', &a, &sz); if (r < 0) goto fail; r = sd_bus_message_exit_container(reply); if (r < 0) goto fail; if (family != af) continue; if (sz != alen) { r = -EINVAL; goto fail; } memcpy(r_addr + i*ALIGN(alen), a, alen); i++; } assert(i == c); idx += c * ALIGN(alen); r = sd_bus_message_exit_container(reply); if (r < 0) goto fail; /* Third, append address pointer array */ r_addr_list = buffer + idx; for (i = 0; i < c; i++) ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen); ((char**) r_addr_list)[i] = NULL; idx += (c+1) * sizeof(char*); assert(idx == ms); result->h_name = r_name; result->h_aliases = (char**) r_aliases; result->h_addrtype = af; result->h_length = alen; result->h_addr_list = (char**) r_addr_list; if (ttlp) *ttlp = 0; if (canonp) *canonp = r_name; /* Explicitly reset all error variables */ *errnop = 0; *h_errnop = NETDB_SUCCESS; h_errno = 0; return NSS_STATUS_SUCCESS; fail: *errnop = -r; *h_errnop = NO_DATA; return NSS_STATUS_UNAVAIL; } NSS_GETHOSTBYNAME_FALLBACKS(mymachines); enum nss_status _nss_mymachines_getpwnam_r( const char *name, struct passwd *pwd, char *buffer, size_t buflen, int *errnop) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; const char *p, *e, *machine; uint32_t mapped; uid_t uid; size_t l; int r; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); assert(pwd); p = startswith(name, "vu-"); if (!p) goto not_found; e = strrchr(p, '-'); if (!e || e == p) goto not_found; if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */ goto not_found; r = parse_uid(e + 1, &uid); if (r < 0) goto not_found; machine = strndupa(p, e - p); if (!machine_name_is_valid(machine)) goto not_found; r = sd_bus_open_system(&bus); if (r < 0) goto fail; r = sd_bus_call_method(bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "MapFromMachineUser", &error, &reply, "su", machine, (uint32_t) uid); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING)) goto not_found; goto fail; } r = sd_bus_message_read(reply, "u", &mapped); if (r < 0) goto fail; /* Refuse to work if the mapped address is in the host UID range, or if there was no mapping at all. */ if (mapped < HOST_UID_LIMIT || mapped == uid) goto not_found; l = strlen(name); if (buflen < l+1) { *errnop = ENOMEM; return NSS_STATUS_TRYAGAIN; } memcpy(buffer, name, l+1); pwd->pw_name = buffer; pwd->pw_uid = mapped; pwd->pw_gid = 65534; /* nobody */ pwd->pw_gecos = buffer; pwd->pw_passwd = (char*) "*"; /* locked */ pwd->pw_dir = (char*) "/"; pwd->pw_shell = (char*) "/sbin/nologin"; *errnop = 0; return NSS_STATUS_SUCCESS; not_found: *errnop = 0; return NSS_STATUS_NOTFOUND; fail: *errnop = -r; return NSS_STATUS_UNAVAIL; } enum nss_status _nss_mymachines_getpwuid_r( uid_t uid, struct passwd *pwd, char *buffer, size_t buflen, int *errnop) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; const char *machine, *object; uint32_t mapped; int r; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); if (!uid_is_valid(uid)) { r = -EINVAL; goto fail; } /* We consider all uids < 65536 host uids */ if (uid < HOST_UID_LIMIT) goto not_found; r = sd_bus_open_system(&bus); if (r < 0) goto fail; r = sd_bus_call_method(bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "MapToMachineUser", &error, &reply, "u", (uint32_t) uid); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING)) goto not_found; goto fail; } r = sd_bus_message_read(reply, "sou", &machine, &object, &mapped); if (r < 0) goto fail; if (mapped == uid) goto not_found; if (snprintf(buffer, buflen, "vu-%s-" UID_FMT, machine, (uid_t) mapped) >= (int) buflen) { *errnop = ENOMEM; return NSS_STATUS_TRYAGAIN; } pwd->pw_name = buffer; pwd->pw_uid = uid; pwd->pw_gid = 65534; /* nobody */ pwd->pw_gecos = buffer; pwd->pw_passwd = (char*) "*"; /* locked */ pwd->pw_dir = (char*) "/"; pwd->pw_shell = (char*) "/sbin/nologin"; *errnop = 0; return NSS_STATUS_SUCCESS; not_found: *errnop = 0; return NSS_STATUS_NOTFOUND; fail: *errnop = -r; return NSS_STATUS_UNAVAIL; } enum nss_status _nss_mymachines_getgrnam_r( const char *name, struct group *gr, char *buffer, size_t buflen, int *errnop) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; const char *p, *e, *machine; uint32_t mapped; uid_t gid; size_t l; int r; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); assert(gr); p = startswith(name, "vg-"); if (!p) goto not_found; e = strrchr(p, '-'); if (!e || e == p) goto not_found; if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */ goto not_found; r = parse_gid(e + 1, &gid); if (r < 0) goto not_found; machine = strndupa(p, e - p); if (!machine_name_is_valid(machine)) goto not_found; r = sd_bus_open_system(&bus); if (r < 0) goto fail; r = sd_bus_call_method(bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "MapFromMachineGroup", &error, &reply, "su", machine, (uint32_t) gid); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING)) goto not_found; goto fail; } r = sd_bus_message_read(reply, "u", &mapped); if (r < 0) goto fail; if (mapped < HOST_GID_LIMIT || mapped == gid) goto not_found; l = sizeof(char*) + strlen(name) + 1; if (buflen < l) { *errnop = ENOMEM; return NSS_STATUS_TRYAGAIN; } memzero(buffer, sizeof(char*)); strcpy(buffer + sizeof(char*), name); gr->gr_name = buffer + sizeof(char*); gr->gr_gid = gid; gr->gr_passwd = (char*) "*"; /* locked */ gr->gr_mem = (char**) buffer; *errnop = 0; return NSS_STATUS_SUCCESS; not_found: *errnop = 0; return NSS_STATUS_NOTFOUND; fail: *errnop = -r; return NSS_STATUS_UNAVAIL; } enum nss_status _nss_mymachines_getgrgid_r( gid_t gid, struct group *gr, char *buffer, size_t buflen, int *errnop) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; const char *machine, *object; uint32_t mapped; int r; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); if (!gid_is_valid(gid)) { r = -EINVAL; goto fail; } /* We consider all gids < 65536 host gids */ if (gid < HOST_GID_LIMIT) goto not_found; r = sd_bus_open_system(&bus); if (r < 0) goto fail; r = sd_bus_call_method(bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "MapToMachineGroup", &error, &reply, "u", (uint32_t) gid); if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING)) goto not_found; goto fail; } r = sd_bus_message_read(reply, "sou", &machine, &object, &mapped); if (r < 0) goto fail; if (mapped == gid) goto not_found; if (buflen < sizeof(char*) + 1) { *errnop = ENOMEM; return NSS_STATUS_TRYAGAIN; } memzero(buffer, sizeof(char*)); if (snprintf(buffer + sizeof(char*), buflen - sizeof(char*), "vg-%s-" GID_FMT, machine, (gid_t) mapped) >= (int) buflen) { *errnop = ENOMEM; return NSS_STATUS_TRYAGAIN; } gr->gr_name = buffer + sizeof(char*); gr->gr_gid = gid; gr->gr_passwd = (char*) "*"; /* locked */ gr->gr_mem = (char**) buffer; *errnop = 0; return NSS_STATUS_SUCCESS; not_found: *errnop = 0; return NSS_STATUS_NOTFOUND; fail: *errnop = -r; return NSS_STATUS_UNAVAIL; } systemd-229/src/nss-mymachines/nss-mymachines.sym000066400000000000000000000011661265713322000223020ustar00rootroot00000000000000/*** This file is part of systemd. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. ***/ { global: _nss_mymachines_gethostbyname_r; _nss_mymachines_gethostbyname2_r; _nss_mymachines_gethostbyname3_r; _nss_mymachines_gethostbyname4_r; _nss_mymachines_getpwnam_r; _nss_mymachines_getpwuid_r; _nss_mymachines_getgrnam_r; _nss_mymachines_getgrgid_r; local: *; }; systemd-229/src/nss-resolve/000077500000000000000000000000001265713322000161305ustar00rootroot00000000000000systemd-229/src/nss-resolve/Makefile000077700000000000000000000000001265713322000214362../Makefileustar00rootroot00000000000000systemd-229/src/nss-resolve/nss-resolve.c000066400000000000000000000512501265713322000205570ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "sd-bus.h" #include "bus-common-errors.h" #include "in-addr-util.h" #include "macro.h" #include "nss-util.h" #include "string-util.h" #include "util.h" #include "signal-util.h" NSS_GETHOSTBYNAME_PROTOTYPES(resolve); NSS_GETHOSTBYADDR_PROTOTYPES(resolve); #define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC) typedef void (*voidfunc_t)(void); static voidfunc_t find_fallback(const char *module, const char *symbol) { void *dl; /* Try to find a fallback NSS module symbol */ dl = dlopen(module, RTLD_LAZY|RTLD_NODELETE); if (!dl) return NULL; return dlsym(dl, symbol); } static bool bus_error_shall_fallback(sd_bus_error *e) { return sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) || sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER) || sd_bus_error_has_name(e, SD_BUS_ERROR_NO_REPLY) || sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED); } static int count_addresses(sd_bus_message *m, int af, const char **canonical) { int c = 0, r; assert(m); assert(canonical); r = sd_bus_message_enter_container(m, 'a', "(iiay)"); if (r < 0) return r; while ((r = sd_bus_message_enter_container(m, 'r', "iiay")) > 0) { int family, ifindex; assert_cc(sizeof(int32_t) == sizeof(int)); r = sd_bus_message_read(m, "ii", &ifindex, &family); if (r < 0) return r; r = sd_bus_message_skip(m, "ay"); if (r < 0) return r; r = sd_bus_message_exit_container(m); if (r < 0) return r; if (af != AF_UNSPEC && family != af) continue; c ++; } if (r < 0) return r; r = sd_bus_message_exit_container(m); if (r < 0) return r; r = sd_bus_message_read(m, "s", canonical); if (r < 0) return r; r = sd_bus_message_rewind(m, true); if (r < 0) return r; return c; } enum nss_status _nss_resolve_gethostbyname4_r( const char *name, struct gaih_addrtuple **pat, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp) { enum nss_status (*fallback)( const char *name, struct gaih_addrtuple **pat, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp); _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; const char *canonical = NULL; size_t l, ms, idx; char *r_name; int c, r, i = 0; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); assert(pat); assert(buffer); assert(errnop); assert(h_errnop); r = sd_bus_open_system(&bus); if (r < 0) goto fallback; r = sd_bus_message_new_method_call( bus, &req, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "ResolveHostname"); if (r < 0) goto fail; r = sd_bus_message_set_auto_start(req, false); if (r < 0) goto fail; r = sd_bus_message_append(req, "isit", 0, name, AF_UNSPEC, (uint64_t) 0); if (r < 0) goto fail; r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) { if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) { *errnop = ESRCH; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } if (bus_error_shall_fallback(&error)) goto fallback; goto fail; } c = count_addresses(reply, AF_UNSPEC, &canonical); if (c < 0) { r = c; goto fail; } if (c == 0) { *errnop = ESRCH; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } if (isempty(canonical)) canonical = name; l = strlen(canonical); ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c; if (buflen < ms) { *errnop = ENOMEM; *h_errnop = TRY_AGAIN; return NSS_STATUS_TRYAGAIN; } /* First, append name */ r_name = buffer; memcpy(r_name, canonical, l+1); idx = ALIGN(l+1); /* Second, append addresses */ r_tuple_first = (struct gaih_addrtuple*) (buffer + idx); r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); if (r < 0) goto fail; while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { int family, ifindex; const void *a; size_t sz; assert_cc(sizeof(int32_t) == sizeof(int)); r = sd_bus_message_read(reply, "ii", &ifindex, &family); if (r < 0) goto fail; if (ifindex < 0) { r = -EINVAL; goto fail; } r = sd_bus_message_read_array(reply, 'y', &a, &sz); if (r < 0) goto fail; r = sd_bus_message_exit_container(reply); if (r < 0) goto fail; if (!IN_SET(family, AF_INET, AF_INET6)) continue; if (sz != FAMILY_ADDRESS_SIZE(family)) { r = -EINVAL; goto fail; } r_tuple = (struct gaih_addrtuple*) (buffer + idx); r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple))); r_tuple->name = r_name; r_tuple->family = family; r_tuple->scopeid = ifindex; memcpy(r_tuple->addr, a, sz); idx += ALIGN(sizeof(struct gaih_addrtuple)); i++; } if (r < 0) goto fail; assert(i == c); assert(idx == ms); if (*pat) **pat = *r_tuple_first; else *pat = r_tuple_first; if (ttlp) *ttlp = 0; /* Explicitly reset all error variables */ *errnop = 0; *h_errnop = NETDB_SUCCESS; h_errno = 0; return NSS_STATUS_SUCCESS; fallback: fallback = (enum nss_status (*)(const char *name, struct gaih_addrtuple **pat, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp)) find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r"); if (fallback) return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp); fail: *errnop = -r; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; } enum nss_status _nss_resolve_gethostbyname3_r( const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) { enum nss_status (*fallback)( const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp); _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *r_name, *r_aliases, *r_addr, *r_addr_list; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; size_t l, idx, ms, alen; const char *canonical; int c, r, i = 0; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(name); assert(result); assert(buffer); assert(errnop); assert(h_errnop); if (af == AF_UNSPEC) af = AF_INET; if (af != AF_INET && af != AF_INET6) { r = -EAFNOSUPPORT; goto fail; } r = sd_bus_open_system(&bus); if (r < 0) goto fallback; r = sd_bus_message_new_method_call( bus, &req, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "ResolveHostname"); if (r < 0) goto fail; r = sd_bus_message_set_auto_start(req, false); if (r < 0) goto fail; r = sd_bus_message_append(req, "isit", 0, name, af, (uint64_t) 0); if (r < 0) goto fail; r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) { if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) { *errnop = ESRCH; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } if (bus_error_shall_fallback(&error)) goto fallback; goto fail; } c = count_addresses(reply, af, &canonical); if (c < 0) { r = c; goto fail; } if (c == 0) { *errnop = ESRCH; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } if (isempty(canonical)) canonical = name; alen = FAMILY_ADDRESS_SIZE(af); l = strlen(canonical); ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*); if (buflen < ms) { *errnop = ENOMEM; *h_errnop = TRY_AGAIN; return NSS_STATUS_TRYAGAIN; } /* First, append name */ r_name = buffer; memcpy(r_name, canonical, l+1); idx = ALIGN(l+1); /* Second, create empty aliases array */ r_aliases = buffer + idx; ((char**) r_aliases)[0] = NULL; idx += sizeof(char*); /* Third, append addresses */ r_addr = buffer + idx; r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); if (r < 0) goto fail; while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { int ifindex, family; const void *a; size_t sz; r = sd_bus_message_read(reply, "ii", &ifindex, &family); if (r < 0) goto fail; if (ifindex < 0) { r = -EINVAL; goto fail; } r = sd_bus_message_read_array(reply, 'y', &a, &sz); if (r < 0) goto fail; r = sd_bus_message_exit_container(reply); if (r < 0) goto fail; if (family != af) continue; if (sz != alen) { r = -EINVAL; goto fail; } memcpy(r_addr + i*ALIGN(alen), a, alen); i++; } if (r < 0) goto fail; assert(i == c); idx += c * ALIGN(alen); /* Fourth, append address pointer array */ r_addr_list = buffer + idx; for (i = 0; i < c; i++) ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen); ((char**) r_addr_list)[i] = NULL; idx += (c+1) * sizeof(char*); assert(idx == ms); result->h_name = r_name; result->h_aliases = (char**) r_aliases; result->h_addrtype = af; result->h_length = alen; result->h_addr_list = (char**) r_addr_list; /* Explicitly reset all error variables */ *errnop = 0; *h_errnop = NETDB_SUCCESS; h_errno = 0; if (ttlp) *ttlp = 0; if (canonp) *canonp = r_name; return NSS_STATUS_SUCCESS; fallback: fallback = (enum nss_status (*)(const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp)) find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r"); if (fallback) return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp); fail: *errnop = -r; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; } enum nss_status _nss_resolve_gethostbyaddr2_r( const void* addr, socklen_t len, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp) { enum nss_status (*fallback)( const void* addr, socklen_t len, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp); _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *r_name, *r_aliases, *r_addr, *r_addr_list; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; unsigned c = 0, i = 0; size_t ms = 0, idx; const char *n; int r, ifindex; BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); assert(addr); assert(result); assert(buffer); assert(errnop); assert(h_errnop); if (!IN_SET(af, AF_INET, AF_INET6)) { *errnop = EAFNOSUPPORT; *h_errnop = NO_DATA; return NSS_STATUS_UNAVAIL; } if (len != FAMILY_ADDRESS_SIZE(af)) { *errnop = EINVAL; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; } r = sd_bus_open_system(&bus); if (r < 0) goto fallback; r = sd_bus_message_new_method_call( bus, &req, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "ResolveAddress"); if (r < 0) goto fail; r = sd_bus_message_set_auto_start(req, false); if (r < 0) goto fail; r = sd_bus_message_append(req, "ii", 0, af); if (r < 0) goto fail; r = sd_bus_message_append_array(req, 'y', addr, len); if (r < 0) goto fail; r = sd_bus_message_append(req, "t", (uint64_t) 0); if (r < 0) goto fail; r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) { if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) { *errnop = ESRCH; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } if (bus_error_shall_fallback(&error)) goto fallback; *errnop = -r; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; } r = sd_bus_message_enter_container(reply, 'a', "(is)"); if (r < 0) goto fail; while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) { if (ifindex < 0) { r = -EINVAL; goto fail; } c++; ms += ALIGN(strlen(n) + 1); } if (r < 0) goto fail; r = sd_bus_message_rewind(reply, false); if (r < 0) return r; if (c <= 0) { *errnop = ESRCH; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } ms += ALIGN(len) + /* the address */ 2 * sizeof(char*) + /* pointers to the address, plus trailing NULL */ c * sizeof(char*); /* pointers to aliases, plus trailing NULL */ if (buflen < ms) { *errnop = ENOMEM; *h_errnop = TRY_AGAIN; return NSS_STATUS_TRYAGAIN; } /* First, place address */ r_addr = buffer; memcpy(r_addr, addr, len); idx = ALIGN(len); /* Second, place address list */ r_addr_list = buffer + idx; ((char**) r_addr_list)[0] = r_addr; ((char**) r_addr_list)[1] = NULL; idx += sizeof(char*) * 2; /* Third, reserve space for the aliases array */ r_aliases = buffer + idx; idx += sizeof(char*) * c; /* Fourth, place aliases */ i = 0; r_name = buffer + idx; while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) { char *p; size_t l; l = strlen(n); p = buffer + idx; memcpy(p, n, l+1); if (i > 0) ((char**) r_aliases)[i-1] = p; i++; idx += ALIGN(l+1); } if (r < 0) goto fail; ((char**) r_aliases)[c-1] = NULL; assert(idx == ms); result->h_name = r_name; result->h_aliases = (char**) r_aliases; result->h_addrtype = af; result->h_length = len; result->h_addr_list = (char**) r_addr_list; if (ttlp) *ttlp = 0; /* Explicitly reset all error variables */ *errnop = 0; *h_errnop = NETDB_SUCCESS; h_errno = 0; return NSS_STATUS_SUCCESS; fallback: fallback = (enum nss_status (*)( const void* addr, socklen_t len, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp)) find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyaddr2_r"); if (fallback) return fallback(addr, len, af, result, buffer, buflen, errnop, h_errnop, ttlp); fail: *errnop = -r; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; } NSS_GETHOSTBYNAME_FALLBACKS(resolve); NSS_GETHOSTBYADDR_FALLBACKS(resolve); systemd-229/src/nss-resolve/nss-resolve.sym000066400000000000000000000010471265713322000211440ustar00rootroot00000000000000/*** This file is part of systemd. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. ***/ { global: _nss_resolve_gethostbyname_r; _nss_resolve_gethostbyname2_r; _nss_resolve_gethostbyname3_r; _nss_resolve_gethostbyname4_r; _nss_resolve_gethostbyaddr_r; _nss_resolve_gethostbyaddr2_r; local: *; }; systemd-229/src/path/000077500000000000000000000000001265713322000146045ustar00rootroot00000000000000systemd-229/src/path/Makefile000077700000000000000000000000001265713322000201122../Makefileustar00rootroot00000000000000systemd-229/src/path/path.c000066400000000000000000000144671265713322000157200ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-path.h" #include "alloc-util.h" #include "log.h" #include "macro.h" #include "string-util.h" #include "util.h" static const char *arg_suffix = NULL; static const char* const path_table[_SD_PATH_MAX] = { [SD_PATH_TEMPORARY] = "temporary", [SD_PATH_TEMPORARY_LARGE] = "temporary-large", [SD_PATH_SYSTEM_BINARIES] = "system-binaries", [SD_PATH_SYSTEM_INCLUDE] = "system-include", [SD_PATH_SYSTEM_LIBRARY_PRIVATE] = "system-library-private", [SD_PATH_SYSTEM_LIBRARY_ARCH] = "system-library-arch", [SD_PATH_SYSTEM_SHARED] = "system-shared", [SD_PATH_SYSTEM_CONFIGURATION_FACTORY] = "system-configuration-factory", [SD_PATH_SYSTEM_STATE_FACTORY] = "system-state-factory", [SD_PATH_SYSTEM_CONFIGURATION] = "system-configuration", [SD_PATH_SYSTEM_RUNTIME] = "system-runtime", [SD_PATH_SYSTEM_RUNTIME_LOGS] = "system-runtime-logs", [SD_PATH_SYSTEM_STATE_PRIVATE] = "system-state-private", [SD_PATH_SYSTEM_STATE_LOGS] = "system-state-logs", [SD_PATH_SYSTEM_STATE_CACHE] = "system-state-cache", [SD_PATH_SYSTEM_STATE_SPOOL] = "system-state-spool", [SD_PATH_USER_BINARIES] = "user-binaries", [SD_PATH_USER_LIBRARY_PRIVATE] = "user-library-private", [SD_PATH_USER_LIBRARY_ARCH] = "user-library-arch", [SD_PATH_USER_SHARED] = "user-shared", [SD_PATH_USER_CONFIGURATION] = "user-configuration", [SD_PATH_USER_RUNTIME] = "user-runtime", [SD_PATH_USER_STATE_CACHE] = "user-state-cache", [SD_PATH_USER] = "user", [SD_PATH_USER_DOCUMENTS] = "user-documents", [SD_PATH_USER_MUSIC] = "user-music", [SD_PATH_USER_PICTURES] = "user-pictures", [SD_PATH_USER_VIDEOS] = "user-videos", [SD_PATH_USER_DOWNLOAD] = "user-download", [SD_PATH_USER_PUBLIC] = "user-public", [SD_PATH_USER_TEMPLATES] = "user-templates", [SD_PATH_USER_DESKTOP] = "user-desktop", [SD_PATH_SEARCH_BINARIES] = "search-binaries", [SD_PATH_SEARCH_LIBRARY_PRIVATE] = "search-library-private", [SD_PATH_SEARCH_LIBRARY_ARCH] = "search-library-arch", [SD_PATH_SEARCH_SHARED] = "search-shared", [SD_PATH_SEARCH_CONFIGURATION_FACTORY] = "search-configuration-factory", [SD_PATH_SEARCH_STATE_FACTORY] = "search-state-factory", [SD_PATH_SEARCH_CONFIGURATION] = "search-configuration", }; static int list_homes(void) { uint64_t i = 0; int r = 0; for (i = 0; i < ELEMENTSOF(path_table); i++) { _cleanup_free_ char *p = NULL; int q; q = sd_path_home(i, arg_suffix, &p); if (q == -ENXIO) continue; if (q < 0) { log_error_errno(r, "Failed to query %s: %m", path_table[i]); r = q; continue; } printf("%s: %s\n", path_table[i], p); } return r; } static int print_home(const char *n) { uint64_t i = 0; int r; for (i = 0; i < ELEMENTSOF(path_table); i++) { if (streq(path_table[i], n)) { _cleanup_free_ char *p = NULL; r = sd_path_home(i, arg_suffix, &p); if (r < 0) return log_error_errno(r, "Failed to query %s: %m", n); printf("%s\n", p); return 0; } } log_error("Path %s not known.", n); return -EOPNOTSUPP; } static void help(void) { printf("%s [OPTIONS...] [NAME...]\n\n" "Show system and user paths.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --suffix=SUFFIX Suffix to append to paths\n", program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_SUFFIX, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "suffix", required_argument, NULL, ARG_SUFFIX }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_SUFFIX: arg_suffix = optarg; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } int main(int argc, char* argv[]) { int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; if (argc > optind) { int i, q; for (i = optind; i < argc; i++) { q = print_home(argv[i]); if (q < 0) r = q; } } else r = list_homes(); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/quotacheck/000077500000000000000000000000001265713322000157775ustar00rootroot00000000000000systemd-229/src/quotacheck/Makefile000077700000000000000000000000001265713322000213052../Makefileustar00rootroot00000000000000systemd-229/src/quotacheck/quotacheck.c000066400000000000000000000070251265713322000202760ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "proc-cmdline.h" #include "process-util.h" #include "signal-util.h" #include "string-util.h" #include "util.h" static bool arg_skip = false; static bool arg_force = false; static int parse_proc_cmdline_item(const char *key, const char *value) { if (streq(key, "quotacheck.mode") && value) { if (streq(value, "auto")) arg_force = arg_skip = false; else if (streq(value, "force")) arg_force = true; else if (streq(value, "skip")) arg_skip = true; else log_warning("Invalid quotacheck.mode= parameter '%s'. Ignoring.", value); } #ifdef HAVE_SYSV_COMPAT else if (streq(key, "forcequotacheck") && !value) { log_warning("Please use 'quotacheck.mode=force' rather than 'forcequotacheck' on the kernel command line."); arg_force = true; } #endif return 0; } static void test_files(void) { #ifdef HAVE_SYSV_COMPAT if (access("/forcequotacheck", F_OK) >= 0) { log_error("Please pass 'quotacheck.mode=force' on the kernel command line rather than creating /forcequotacheck on the root file system."); arg_force = true; } #endif } int main(int argc, char *argv[]) { static const char * const cmdline[] = { QUOTACHECK, "-anug", NULL }; pid_t pid; int r; if (argc > 1) { log_error("This program takes no arguments."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); r = parse_proc_cmdline(parse_proc_cmdline_item); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); test_files(); if (!arg_force) { if (arg_skip) return EXIT_SUCCESS; if (access("/run/systemd/quotacheck", F_OK) < 0) return EXIT_SUCCESS; } pid = fork(); if (pid < 0) { log_error_errno(errno, "fork(): %m"); return EXIT_FAILURE; } else if (pid == 0) { /* Child */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); execv(cmdline[0], (char**) cmdline); _exit(1); /* Operational error */ } r = wait_for_terminate_and_warn("quotacheck", pid, true); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/random-seed/000077500000000000000000000000001265713322000160465ustar00rootroot00000000000000systemd-229/src/random-seed/Makefile000077700000000000000000000000001265713322000213542../Makefileustar00rootroot00000000000000systemd-229/src/random-seed/random-seed.c000066400000000000000000000142511265713322000204130ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "io-util.h" #include "log.h" #include "mkdir.h" #include "string-util.h" #include "util.h" #define POOL_SIZE_MIN 512 int main(int argc, char *argv[]) { _cleanup_close_ int seed_fd = -1, random_fd = -1; _cleanup_free_ void* buf = NULL; size_t buf_size = 0; ssize_t k; int r, open_rw_error; FILE *f; bool refresh_seed_file = true; if (argc != 2) { log_error("This program requires one argument."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); /* Read pool size, if possible */ f = fopen("/proc/sys/kernel/random/poolsize", "re"); if (f) { if (fscanf(f, "%zu", &buf_size) > 0) /* poolsize is in bits on 2.6, but we want bytes */ buf_size /= 8; fclose(f); } if (buf_size <= POOL_SIZE_MIN) buf_size = POOL_SIZE_MIN; buf = malloc(buf_size); if (!buf) { r = log_oom(); goto finish; } r = mkdir_parents_label(RANDOM_SEED, 0755); if (r < 0) { log_error_errno(r, "Failed to create directory " RANDOM_SEED_DIR ": %m"); goto finish; } /* When we load the seed we read it and write it to the device * and then immediately update the saved seed with new data, * to make sure the next boot gets seeded differently. */ if (streq(argv[1], "load")) { seed_fd = open(RANDOM_SEED, O_RDWR|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600); open_rw_error = -errno; if (seed_fd < 0) { refresh_seed_file = false; seed_fd = open(RANDOM_SEED, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (seed_fd < 0) { bool missing = errno == ENOENT; log_full_errno(missing ? LOG_DEBUG : LOG_ERR, open_rw_error, "Failed to open " RANDOM_SEED " for writing: %m"); r = log_full_errno(missing ? LOG_DEBUG : LOG_ERR, errno, "Failed to open " RANDOM_SEED " for reading: %m"); if (missing) r = 0; goto finish; } } random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY, 0600); if (random_fd < 0) { random_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY, 0600); if (random_fd < 0) { r = log_error_errno(errno, "Failed to open /dev/urandom: %m"); goto finish; } } k = loop_read(seed_fd, buf, buf_size, false); if (k < 0) r = log_error_errno(k, "Failed to read seed from " RANDOM_SEED ": %m"); else if (k == 0) { r = 0; log_debug("Seed file " RANDOM_SEED " not yet initialized, proceeding."); } else { (void) lseek(seed_fd, 0, SEEK_SET); r = loop_write(random_fd, buf, (size_t) k, false); if (r < 0) log_error_errno(r, "Failed to write seed to /dev/urandom: %m"); } } else if (streq(argv[1], "save")) { seed_fd = open(RANDOM_SEED, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600); if (seed_fd < 0) { r = log_error_errno(errno, "Failed to open " RANDOM_SEED ": %m"); goto finish; } random_fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (random_fd < 0) { r = log_error_errno(errno, "Failed to open /dev/urandom: %m"); goto finish; } } else { log_error("Unknown verb '%s'.", argv[1]); r = -EINVAL; goto finish; } if (refresh_seed_file) { /* This is just a safety measure. Given that we are root and * most likely created the file ourselves the mode and owner * should be correct anyway. */ (void) fchmod(seed_fd, 0600); (void) fchown(seed_fd, 0, 0); k = loop_read(random_fd, buf, buf_size, false); if (k < 0) { r = log_error_errno(k, "Failed to read new seed from /dev/urandom: %m"); goto finish; } if (k == 0) { log_error("Got EOF while reading from /dev/urandom."); r = -EIO; goto finish; } r = loop_write(seed_fd, buf, (size_t) k, false); if (r < 0) log_error_errno(r, "Failed to write new random seed file: %m"); } finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/rc-local-generator/000077500000000000000000000000001265713322000173305ustar00rootroot00000000000000systemd-229/src/rc-local-generator/Makefile000077700000000000000000000000001265713322000226362../Makefileustar00rootroot00000000000000systemd-229/src/rc-local-generator/rc-local-generator.c000066400000000000000000000053461265713322000231640ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2011 Michal Schmidt systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "log.h" #include "mkdir.h" #include "string-util.h" #include "util.h" #ifndef RC_LOCAL_SCRIPT_PATH_START #define RC_LOCAL_SCRIPT_PATH_START "/etc/rc.d/rc.local" #endif #ifndef RC_LOCAL_SCRIPT_PATH_STOP #define RC_LOCAL_SCRIPT_PATH_STOP "/sbin/halt.local" #endif const char *arg_dest = "/tmp"; static int add_symlink(const char *service, const char *where) { _cleanup_free_ char *from = NULL, *to = NULL; int r; assert(service); assert(where); from = strjoin(SYSTEM_DATA_UNIT_PATH, "/", service, NULL); if (!from) return log_oom(); to = strjoin(arg_dest, "/", where, ".wants/", service, NULL); if (!to) return log_oom(); mkdir_parents_label(to, 0755); r = symlink(from, to); if (r < 0) { if (errno == EEXIST) return 0; return log_error_errno(errno, "Failed to create symlink %s: %m", to); } return 1; } int main(int argc, char *argv[]) { int r = EXIT_SUCCESS; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); return EXIT_FAILURE; } if (argc > 1) arg_dest = argv[1]; log_set_target(LOG_TARGET_SAFE); log_parse_environment(); log_open(); umask(0022); if (access(RC_LOCAL_SCRIPT_PATH_START, X_OK) >= 0) { log_debug("Automatically adding rc-local.service."); if (add_symlink("rc-local.service", "multi-user.target") < 0) r = EXIT_FAILURE; } if (access(RC_LOCAL_SCRIPT_PATH_STOP, X_OK) >= 0) { log_debug("Automatically adding halt-local.service."); if (add_symlink("halt-local.service", "final.target") < 0) r = EXIT_FAILURE; } return r; } systemd-229/src/remount-fs/000077500000000000000000000000001265713322000157475ustar00rootroot00000000000000systemd-229/src/remount-fs/Makefile000077700000000000000000000000001265713322000212552../Makefileustar00rootroot00000000000000systemd-229/src/remount-fs/remount-fs.c000066400000000000000000000111671265713322000202200ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "exit-status.h" #include "log.h" #include "mount-setup.h" #include "mount-util.h" #include "path-util.h" #include "process-util.h" #include "signal-util.h" #include "strv.h" #include "util.h" /* Goes through /etc/fstab and remounts all API file systems, applying * options that are in /etc/fstab that systemd might not have * respected */ int main(int argc, char *argv[]) { _cleanup_hashmap_free_free_ Hashmap *pids = NULL; _cleanup_endmntent_ FILE *f = NULL; struct mntent* me; int r; if (argc > 1) { log_error("This program takes no argument."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); f = setmntent("/etc/fstab", "r"); if (!f) { if (errno == ENOENT) { r = 0; goto finish; } r = log_error_errno(errno, "Failed to open /etc/fstab: %m"); goto finish; } pids = hashmap_new(NULL); if (!pids) { r = log_oom(); goto finish; } while ((me = getmntent(f))) { pid_t pid; int k; char *s; /* Remount the root fs, /usr and all API VFS */ if (!mount_point_is_api(me->mnt_dir) && !path_equal(me->mnt_dir, "/") && !path_equal(me->mnt_dir, "/usr")) continue; log_debug("Remounting %s", me->mnt_dir); pid = fork(); if (pid < 0) { r = log_error_errno(errno, "Failed to fork: %m"); goto finish; } if (pid == 0) { /* Child */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); (void) prctl(PR_SET_PDEATHSIG, SIGTERM); execv(MOUNT_PATH, STRV_MAKE(MOUNT_PATH, me->mnt_dir, "-o", "remount")); log_error_errno(errno, "Failed to execute " MOUNT_PATH ": %m"); _exit(EXIT_FAILURE); } /* Parent */ s = strdup(me->mnt_dir); if (!s) { r = log_oom(); goto finish; } k = hashmap_put(pids, PID_TO_PTR(pid), s); if (k < 0) { free(s); r = log_oom(); goto finish; } } r = 0; while (!hashmap_isempty(pids)) { siginfo_t si = {}; char *s; if (waitid(P_ALL, 0, &si, WEXITED) < 0) { if (errno == EINTR) continue; r = log_error_errno(errno, "waitid() failed: %m"); goto finish; } s = hashmap_remove(pids, PID_TO_PTR(si.si_pid)); if (s) { if (!is_clean_exit(si.si_code, si.si_status, NULL)) { if (si.si_code == CLD_EXITED) log_error(MOUNT_PATH " for %s exited with exit status %i.", s, si.si_status); else log_error(MOUNT_PATH " for %s terminated by signal %s.", s, signal_to_string(si.si_status)); r = -ENOEXEC; } free(s); } } finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/reply-password/000077500000000000000000000000001265713322000166435ustar00rootroot00000000000000systemd-229/src/reply-password/Makefile000077700000000000000000000000001265713322000221512../Makefileustar00rootroot00000000000000systemd-229/src/reply-password/reply-password.c000066400000000000000000000055231265713322000220070ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "fd-util.h" #include "log.h" #include "macro.h" #include "string-util.h" #include "util.h" static int send_on_socket(int fd, const char *socket_name, const void *packet, size_t size) { union { struct sockaddr sa; struct sockaddr_un un; } sa = { .un.sun_family = AF_UNIX, }; assert(fd >= 0); assert(socket_name); assert(packet); strncpy(sa.un.sun_path, socket_name, sizeof(sa.un.sun_path)); if (sendto(fd, packet, size, MSG_NOSIGNAL, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(socket_name)) < 0) return log_error_errno(errno, "Failed to send: %m"); return 0; } int main(int argc, char *argv[]) { _cleanup_close_ int fd = -1; char packet[LINE_MAX]; size_t length; int r; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); if (argc != 3) { log_error("Wrong number of arguments."); return EXIT_FAILURE; } if (streq(argv[1], "1")) { packet[0] = '+'; if (!fgets(packet+1, sizeof(packet)-1, stdin)) { r = log_error_errno(errno, "Failed to read password: %m"); goto finish; } truncate_nl(packet+1); length = 1 + strlen(packet+1) + 1; } else if (streq(argv[1], "0")) { packet[0] = '-'; length = 1; } else { log_error("Invalid first argument %s", argv[1]); r = -EINVAL; goto finish; } fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (fd < 0) { r = log_error_errno(errno, "socket() failed: %m"); goto finish; } r = send_on_socket(fd, argv[2], packet, length); finish: memory_erase(packet, sizeof(packet)); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/resolve/000077500000000000000000000000001265713322000153275ustar00rootroot00000000000000systemd-229/src/resolve/.gitignore000066400000000000000000000001701265713322000173150ustar00rootroot00000000000000/resolved-gperf.c /resolved.conf /dns_type-from-name.gperf /dns_type-from-name.h /dns_type-list.txt /dns_type-to-name.h systemd-229/src/resolve/Makefile000077700000000000000000000000001265713322000206352../Makefileustar00rootroot00000000000000systemd-229/src/resolve/RFCs000066400000000000000000000115751265713322000160600ustar00rootroot00000000000000Y = Comprehensively Implemented, to the point appropriate for resolved D = Comprehensively Implemented, by a dependency of resolved ! = Missing and something we might want to implement ~ = Needs no explicit support or doesn't apply ? = Is this relevant today? = We are working on this Y https://tools.ietf.org/html/rfc1034 → DOMAIN NAMES - CONCEPTS AND FACILITIES Y https://tools.ietf.org/html/rfc1035 → DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION ? https://tools.ietf.org/html/rfc1101 → DNS Encoding of Network Names and Other Types Y https://tools.ietf.org/html/rfc1123 → Requirements for Internet Hosts -- Application and Support ~ https://tools.ietf.org/html/rfc1464 → Using the Domain Name System To Store Arbitrary String Attributes Y https://tools.ietf.org/html/rfc1536 → Common DNS Implementation Errors and Suggested Fixes Y https://tools.ietf.org/html/rfc1876 → A Means for Expressing Location Information in the Domain Name System Y https://tools.ietf.org/html/rfc2181 → Clarifications to the DNS Specification Y https://tools.ietf.org/html/rfc2308 → Negative Caching of DNS Queries (DNS NCACHE) Y https://tools.ietf.org/html/rfc2782 → A DNS RR for specifying the location of services (DNS SRV) D https://tools.ietf.org/html/rfc3492 → Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA) Y https://tools.ietf.org/html/rfc3596 → DNS Extensions to Support IP Version 6 Y https://tools.ietf.org/html/rfc3597 → Handling of Unknown DNS Resource Record (RR) Types Y https://tools.ietf.org/html/rfc4033 → DNS Security Introduction and Requirements Y https://tools.ietf.org/html/rfc4034 → Resource Records for the DNS Security Extensions Y https://tools.ietf.org/html/rfc4035 → Protocol Modifications for the DNS Security Extensions ! https://tools.ietf.org/html/rfc4183 → A Suggested Scheme for DNS Resolution of Networks and Gateways Y https://tools.ietf.org/html/rfc4255 → Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints Y https://tools.ietf.org/html/rfc4343 → Domain Name System (DNS) Case Insensitivity Clarification ~ https://tools.ietf.org/html/rfc4470 → Minimally Covering NSEC Records and DNSSEC On-line Signing Y https://tools.ietf.org/html/rfc4501 → Domain Name System Uniform Resource Identifiers Y https://tools.ietf.org/html/rfc4509 → Use of SHA-256 in DNSSEC Delegation Signer (DS) Resource Records (RRs) ~ https://tools.ietf.org/html/rfc4592 → The Role of Wildcards in the Domain Name System ~ https://tools.ietf.org/html/rfc4697 → Observed DNS Resolution Misbehavior Y https://tools.ietf.org/html/rfc4795 → Link-Local Multicast Name Resolution (LLMNR) Y https://tools.ietf.org/html/rfc5011 → Automated Updates of DNS Security (DNSSEC) Trust Anchors Y https://tools.ietf.org/html/rfc5155 → DNS Security (DNSSEC) Hashed Authenticated Denial of Existence Y https://tools.ietf.org/html/rfc5452 → Measures for Making DNS More Resilient against Forged Answers Y https://tools.ietf.org/html/rfc5702 → Use of SHA-2 Algorithms with RSA in DNSKEY and RRSIG Resource Records for DNSSEC Y https://tools.ietf.org/html/rfc5890 → Internationalized Domain Names for Applications (IDNA): Definitions and Document Framework Y https://tools.ietf.org/html/rfc5891 → Internationalized Domain Names in Applications (IDNA): Protocol Y https://tools.ietf.org/html/rfc5966 → DNS Transport over TCP - Implementation Requirements Y https://tools.ietf.org/html/rfc6303 → Locally Served DNS Zones Y https://tools.ietf.org/html/rfc6604 → xNAME RCODE and Status Bits Clarification Y https://tools.ietf.org/html/rfc6605 → Elliptic Curve Digital Signature Algorithm (DSA) for DNSSEC https://tools.ietf.org/html/rfc6672 → DNAME Redirection in the DNS ! https://tools.ietf.org/html/rfc6731 → Improved Recursive DNS Server Selection for Multi-Interfaced Nodes Y https://tools.ietf.org/html/rfc6761 → Special-Use Domain Names https://tools.ietf.org/html/rfc6762 → Multicast DNS https://tools.ietf.org/html/rfc6763 → DNS-Based Service Discovery ~ https://tools.ietf.org/html/rfc6781 → DNSSEC Operational Practices, Version 2 Y https://tools.ietf.org/html/rfc6840 → Clarifications and Implementation Notes for DNS Security (DNSSEC) Y https://tools.ietf.org/html/rfc6891 → Extension Mechanisms for DNS (EDNS(0)) Y https://tools.ietf.org/html/rfc6944 → Applicability Statement: DNS Security (DNSSEC) DNSKEY Algorithm Implementation Status Y https://tools.ietf.org/html/rfc6975 → Signaling Cryptographic Algorithm Understanding in DNS Security Extensions (DNSSEC) Y https://tools.ietf.org/html/rfc7129 → Authenticated Denial of Existence in the DNS Y https://tools.ietf.org/html/rfc7646 → Definition and Use of DNSSEC Negative Trust Anchors ~ https://tools.ietf.org/html/rfc7719 → DNS Terminology Also relevant: https://www.iab.org/documents/correspondence-reports-documents/2013-2/iab-statement-dotless-domains-considered-harmful/ systemd-229/src/resolve/dns-type.c000066400000000000000000000201041265713322000172330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "dns-type.h" #include "parse-util.h" #include "string-util.h" typedef const struct { uint16_t type; const char *name; } dns_type; static const struct dns_type_name * lookup_dns_type (register const char *str, register unsigned int len); #include "dns_type-from-name.h" #include "dns_type-to-name.h" int dns_type_from_string(const char *s) { const struct dns_type_name *sc; assert(s); sc = lookup_dns_type(s, strlen(s)); if (sc) return sc->id; s = startswith_no_case(s, "TYPE"); if (s) { unsigned x; if (safe_atou(s, &x) >= 0 && x <= UINT16_MAX) return (int) x; } return _DNS_TYPE_INVALID; } bool dns_type_is_pseudo(uint16_t type) { /* Checks whether the specified type is a "pseudo-type". What * a "pseudo-type" precisely is, is defined only very weakly, * but apparently entails all RR types that are not actually * stored as RRs on the server and should hence also not be * cached. We use this list primarily to validate NSEC type * bitfields, and to verify what to cache. */ return IN_SET(type, 0, /* A Pseudo RR type, according to RFC 2931 */ DNS_TYPE_ANY, DNS_TYPE_AXFR, DNS_TYPE_IXFR, DNS_TYPE_OPT, DNS_TYPE_TSIG, DNS_TYPE_TKEY ); } bool dns_class_is_pseudo(uint16_t class) { return class == DNS_TYPE_ANY; } bool dns_type_is_valid_query(uint16_t type) { /* The types valid as questions in packets */ return !IN_SET(type, 0, DNS_TYPE_OPT, DNS_TYPE_TSIG, DNS_TYPE_TKEY, /* RRSIG are technically valid as questions, but we refuse doing explicit queries for them, as * they aren't really payload, but signatures for payload, and cannot be validated on their * own. After all they are the signatures, and have no signatures of their own validating * them. */ DNS_TYPE_RRSIG); } bool dns_type_is_valid_rr(uint16_t type) { /* The types valid as RR in packets (but not necessarily * stored on servers). */ return !IN_SET(type, DNS_TYPE_ANY, DNS_TYPE_AXFR, DNS_TYPE_IXFR); } bool dns_class_is_valid_rr(uint16_t class) { return class != DNS_CLASS_ANY; } bool dns_type_may_redirect(uint16_t type) { /* The following record types should never be redirected using * CNAME/DNAME RRs. See * . */ if (dns_type_is_pseudo(type)) return false; return !IN_SET(type, DNS_TYPE_CNAME, DNS_TYPE_DNAME, DNS_TYPE_NSEC3, DNS_TYPE_NSEC, DNS_TYPE_RRSIG, DNS_TYPE_NXT, DNS_TYPE_SIG, DNS_TYPE_KEY); } bool dns_type_may_wildcard(uint16_t type) { /* The following records may not be expanded from wildcard RRsets */ if (dns_type_is_pseudo(type)) return false; return !IN_SET(type, DNS_TYPE_NSEC3, DNS_TYPE_SOA, /* Prohibited by https://tools.ietf.org/html/rfc4592#section-4.4 */ DNS_TYPE_DNAME); } bool dns_type_apex_only(uint16_t type) { /* Returns true for all RR types that may only appear signed in a zone apex */ return IN_SET(type, DNS_TYPE_SOA, DNS_TYPE_NS, /* this one can appear elsewhere, too, but not signed */ DNS_TYPE_DNSKEY, DNS_TYPE_NSEC3PARAM); } bool dns_type_is_dnssec(uint16_t type) { return IN_SET(type, DNS_TYPE_DS, DNS_TYPE_DNSKEY, DNS_TYPE_RRSIG, DNS_TYPE_NSEC, DNS_TYPE_NSEC3, DNS_TYPE_NSEC3PARAM); } bool dns_type_is_obsolete(uint16_t type) { return IN_SET(type, /* Obsoleted by RFC 973 */ DNS_TYPE_MD, DNS_TYPE_MF, DNS_TYPE_MAILA, /* Kinda obsoleted by RFC 2505 */ DNS_TYPE_MB, DNS_TYPE_MG, DNS_TYPE_MR, DNS_TYPE_MINFO, DNS_TYPE_MAILB, /* RFC1127 kinda obsoleted this by recommending against its use */ DNS_TYPE_WKS, /* Declared historical by RFC 6563 */ DNS_TYPE_A6, /* Obsoleted by DNSSEC-bis */ DNS_TYPE_NXT, /* RFC 1035 removed support for concepts that needed this from RFC 883 */ DNS_TYPE_NULL); } int dns_type_to_af(uint16_t t) { switch (t) { case DNS_TYPE_A: return AF_INET; case DNS_TYPE_AAAA: return AF_INET6; case DNS_TYPE_ANY: return AF_UNSPEC; default: return -EINVAL; } } const char *dns_class_to_string(uint16_t class) { switch (class) { case DNS_CLASS_IN: return "IN"; case DNS_CLASS_ANY: return "ANY"; } return NULL; } int dns_class_from_string(const char *s) { if (!s) return _DNS_CLASS_INVALID; if (strcaseeq(s, "IN")) return DNS_CLASS_IN; else if (strcaseeq(s, "ANY")) return DNS_CLASS_ANY; return _DNS_CLASS_INVALID; } const char* tlsa_cert_usage_to_string(uint8_t cert_usage) { switch (cert_usage) { case 0: return "CA constraint"; case 1: return "Service certificate constraint"; case 2: return "Trust anchor assertion"; case 3: return "Domain-issued certificate"; case 4 ... 254: return "Unassigned"; case 255: return "Private use"; } return NULL; /* clang cannot count that we covered everything */ } const char* tlsa_selector_to_string(uint8_t selector) { switch (selector) { case 0: return "Full Certificate"; case 1: return "SubjectPublicKeyInfo"; case 2 ... 254: return "Unassigned"; case 255: return "Private use"; } return NULL; } const char* tlsa_matching_type_to_string(uint8_t selector) { switch (selector) { case 0: return "No hash used"; case 1: return "SHA-256"; case 2: return "SHA-512"; case 3 ... 254: return "Unassigned"; case 255: return "Private use"; } return NULL; } systemd-229/src/resolve/dns-type.h000066400000000000000000000101421265713322000172410ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "macro.h" /* DNS record types, taken from * http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml. */ enum { /* Normal records */ DNS_TYPE_A = 0x01, DNS_TYPE_NS, DNS_TYPE_MD, DNS_TYPE_MF, DNS_TYPE_CNAME, DNS_TYPE_SOA, DNS_TYPE_MB, DNS_TYPE_MG, DNS_TYPE_MR, DNS_TYPE_NULL, DNS_TYPE_WKS, DNS_TYPE_PTR, DNS_TYPE_HINFO, DNS_TYPE_MINFO, DNS_TYPE_MX, DNS_TYPE_TXT, DNS_TYPE_RP, DNS_TYPE_AFSDB, DNS_TYPE_X25, DNS_TYPE_ISDN, DNS_TYPE_RT, DNS_TYPE_NSAP, DNS_TYPE_NSAP_PTR, DNS_TYPE_SIG, DNS_TYPE_KEY, DNS_TYPE_PX, DNS_TYPE_GPOS, DNS_TYPE_AAAA, DNS_TYPE_LOC, DNS_TYPE_NXT, DNS_TYPE_EID, DNS_TYPE_NIMLOC, DNS_TYPE_SRV, DNS_TYPE_ATMA, DNS_TYPE_NAPTR, DNS_TYPE_KX, DNS_TYPE_CERT, DNS_TYPE_A6, DNS_TYPE_DNAME, DNS_TYPE_SINK, DNS_TYPE_OPT, /* EDNS0 option */ DNS_TYPE_APL, DNS_TYPE_DS, DNS_TYPE_SSHFP, DNS_TYPE_IPSECKEY, DNS_TYPE_RRSIG, DNS_TYPE_NSEC, DNS_TYPE_DNSKEY, DNS_TYPE_DHCID, DNS_TYPE_NSEC3, DNS_TYPE_NSEC3PARAM, DNS_TYPE_TLSA, DNS_TYPE_HIP = 0x37, DNS_TYPE_NINFO, DNS_TYPE_RKEY, DNS_TYPE_TALINK, DNS_TYPE_CDS, DNS_TYPE_CDNSKEY, DNS_TYPE_OPENPGPKEY, DNS_TYPE_SPF = 0x63, DNS_TYPE_NID, DNS_TYPE_L32, DNS_TYPE_L64, DNS_TYPE_LP, DNS_TYPE_EUI48, DNS_TYPE_EUI64, DNS_TYPE_TKEY = 0xF9, DNS_TYPE_TSIG, DNS_TYPE_IXFR, DNS_TYPE_AXFR, DNS_TYPE_MAILB, DNS_TYPE_MAILA, DNS_TYPE_ANY, DNS_TYPE_URI, DNS_TYPE_CAA, DNS_TYPE_TA = 0x8000, DNS_TYPE_DLV, _DNS_TYPE_MAX, _DNS_TYPE_INVALID = -1 }; assert_cc(DNS_TYPE_SSHFP == 44); assert_cc(DNS_TYPE_TLSA == 52); assert_cc(DNS_TYPE_ANY == 255); /* DNS record classes, see RFC 1035 */ enum { DNS_CLASS_IN = 0x01, DNS_CLASS_ANY = 0xFF, _DNS_CLASS_MAX, _DNS_CLASS_INVALID = -1 }; bool dns_type_is_pseudo(uint16_t type); bool dns_type_is_valid_query(uint16_t type); bool dns_type_is_valid_rr(uint16_t type); bool dns_type_may_redirect(uint16_t type); bool dns_type_is_dnssec(uint16_t type); bool dns_type_is_obsolete(uint16_t type); bool dns_type_may_wildcard(uint16_t type); bool dns_type_apex_only(uint16_t type); int dns_type_to_af(uint16_t t); bool dns_class_is_pseudo(uint16_t class); bool dns_class_is_valid_rr(uint16_t class); /* TYPE?? follows http://tools.ietf.org/html/rfc3597#section-5 */ const char *dns_type_to_string(int type); int dns_type_from_string(const char *s); const char *dns_class_to_string(uint16_t type); int dns_class_from_string(const char *name); /* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.2 */ const char *tlsa_cert_usage_to_string(uint8_t cert_usage); /* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.3 */ const char *tlsa_selector_to_string(uint8_t selector); /* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.4 */ const char *tlsa_matching_type_to_string(uint8_t selector); systemd-229/src/resolve/org.freedesktop.resolve1.conf000066400000000000000000000016711265713322000230430ustar00rootroot00000000000000 systemd-229/src/resolve/org.freedesktop.resolve1.service000066400000000000000000000006411265713322000235520ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] Name=org.freedesktop.resolve1 Exec=/bin/false User=root SystemdService=dbus-org.freedesktop.resolve1.service systemd-229/src/resolve/resolve-tool.c000066400000000000000000001317751265713322000201430ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-bus.h" #include "af-list.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "escape.h" #include "in-addr-util.h" #include "parse-util.h" #include "resolved-def.h" #include "resolved-dns-packet.h" #include "terminal-util.h" #define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC) static int arg_family = AF_UNSPEC; static int arg_ifindex = 0; static uint16_t arg_type = 0; static uint16_t arg_class = 0; static bool arg_legend = true; static uint64_t arg_flags = 0; static enum { MODE_RESOLVE_HOST, MODE_RESOLVE_RECORD, MODE_RESOLVE_SERVICE, MODE_STATISTICS, MODE_RESET_STATISTICS, } arg_mode = MODE_RESOLVE_HOST; static void print_source(uint64_t flags, usec_t rtt) { char rtt_str[FORMAT_TIMESTAMP_MAX]; if (!arg_legend) return; if (flags == 0) return; fputs("\n-- Information acquired via", stdout); if (flags != 0) printf(" protocol%s%s%s%s%s", flags & SD_RESOLVED_DNS ? " DNS" :"", flags & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "", flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "", flags & SD_RESOLVED_MDNS_IPV4 ? "mDNS/IPv4" : "", flags & SD_RESOLVED_MDNS_IPV6 ? "mDNS/IPv6" : ""); assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100)); printf(" in %s", rtt_str); fputc('.', stdout); fputc('\n', stdout); printf("-- Data is authenticated: %s\n", yes_no(flags & SD_RESOLVED_AUTHENTICATED)); } static int resolve_host(sd_bus *bus, const char *name) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *canonical = NULL; char ifname[IF_NAMESIZE] = ""; unsigned c = 0; int r; uint64_t flags; usec_t ts; assert(name); if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname)) return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex); log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname); r = sd_bus_message_new_method_call( bus, &req, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "ResolveHostname"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags); if (r < 0) return bus_log_create_error(r); ts = now(CLOCK_MONOTONIC); r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) return log_error_errno(r, "%s: resolve call failed: %s", name, bus_error_message(&error, r)); ts = now(CLOCK_MONOTONIC) - ts; r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { _cleanup_free_ char *pretty = NULL; int ifindex, family; const void *a; size_t sz; assert_cc(sizeof(int) == sizeof(int32_t)); r = sd_bus_message_read(reply, "ii", &ifindex, &family); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_read_array(reply, 'y', &a, &sz); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); if (!IN_SET(family, AF_INET, AF_INET6)) { log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown"); continue; } if (sz != FAMILY_ADDRESS_SIZE(family)) { log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown"); return -EINVAL; } ifname[0] = 0; if (ifindex > 0 && !if_indextoname(ifindex, ifname)) log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex); r = in_addr_to_string(family, a, &pretty); if (r < 0) return log_error_errno(r, "Failed to print address for %s: %m", name); printf("%*s%s %s%s%s\n", (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ", pretty, isempty(ifname) ? "" : "%", ifname); c++; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_read(reply, "st", &canonical, &flags); if (r < 0) return bus_log_parse_error(r); if (!streq(name, canonical)) printf("%*s%s (%s)\n", (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ", canonical); if (c == 0) { log_error("%s: no addresses found", name); return -ESRCH; } print_source(flags, ts); return 0; } static int resolve_address(sd_bus *bus, int family, const union in_addr_union *address, int ifindex) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *pretty = NULL; char ifname[IF_NAMESIZE] = ""; uint64_t flags; unsigned c = 0; usec_t ts; int r; assert(bus); assert(IN_SET(family, AF_INET, AF_INET6)); assert(address); if (ifindex <= 0) ifindex = arg_ifindex; r = in_addr_to_string(family, address, &pretty); if (r < 0) return log_oom(); if (ifindex > 0 && !if_indextoname(ifindex, ifname)) return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex); log_debug("Resolving %s%s%s.", pretty, isempty(ifname) ? "" : "%", ifname); r = sd_bus_message_new_method_call( bus, &req, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "ResolveAddress"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append(req, "ii", ifindex, family); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append_array(req, 'y', address, FAMILY_ADDRESS_SIZE(family)); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append(req, "t", arg_flags); if (r < 0) return bus_log_create_error(r); ts = now(CLOCK_MONOTONIC); r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) { log_error("%s: resolve call failed: %s", pretty, bus_error_message(&error, r)); return r; } ts = now(CLOCK_MONOTONIC) - ts; r = sd_bus_message_enter_container(reply, 'a', "(is)"); if (r < 0) return bus_log_create_error(r); while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) { const char *n; assert_cc(sizeof(int) == sizeof(int32_t)); r = sd_bus_message_read(reply, "is", &ifindex, &n); if (r < 0) return r; r = sd_bus_message_exit_container(reply); if (r < 0) return r; ifname[0] = 0; if (ifindex > 0 && !if_indextoname(ifindex, ifname)) log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex); printf("%*s%*s%*s%s %s\n", (int) strlen(pretty), c == 0 ? pretty : "", isempty(ifname) ? 0 : 1, c > 0 || isempty(ifname) ? "" : "%", (int) strlen(ifname), c == 0 ? ifname : "", c == 0 ? ":" : " ", n); c++; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_read(reply, "t", &flags); if (r < 0) return bus_log_parse_error(r); if (c == 0) { log_error("%s: no names found", pretty); return -ESRCH; } print_source(flags, ts); return 0; } static int parse_address(const char *s, int *family, union in_addr_union *address, int *ifindex) { const char *percent, *a; int ifi = 0; int r; percent = strchr(s, '%'); if (percent) { if (parse_ifindex(percent+1, &ifi) < 0) { ifi = if_nametoindex(percent+1); if (ifi <= 0) return -EINVAL; } a = strndupa(s, percent - s); } else a = s; r = in_addr_from_string_auto(a, family, address); if (r < 0) return r; *ifindex = ifi; return 0; } static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char ifname[IF_NAMESIZE] = ""; unsigned n = 0; uint64_t flags; int r; usec_t ts; assert(name); if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname)) return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex); log_debug("Resolving %s %s %s (interface %s).", name, dns_class_to_string(class), dns_type_to_string(type), isempty(ifname) ? "*" : ifname); r = sd_bus_message_new_method_call( bus, &req, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "ResolveRecord"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append(req, "isqqt", arg_ifindex, name, class, type, arg_flags); if (r < 0) return bus_log_create_error(r); ts = now(CLOCK_MONOTONIC); r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) { log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r)); return r; } ts = now(CLOCK_MONOTONIC) - ts; r = sd_bus_message_enter_container(reply, 'a', "(iqqay)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_enter_container(reply, 'r', "iqqay")) > 0) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; const char *s; uint16_t c, t; int ifindex; const void *d; size_t l; assert_cc(sizeof(int) == sizeof(int32_t)); r = sd_bus_message_read(reply, "iqq", &ifindex, &c, &t); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_read_array(reply, 'y', &d, &l); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0); if (r < 0) return log_oom(); p->refuse_compression = true; r = dns_packet_append_blob(p, d, l, NULL); if (r < 0) return log_oom(); r = dns_packet_read_rr(p, &rr, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to parse RR: %m"); s = dns_resource_record_to_string(rr); if (!s) return log_oom(); ifname[0] = 0; if (ifindex > 0 && !if_indextoname(ifindex, ifname)) log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex); printf("%s%s%s\n", s, isempty(ifname) ? "" : " # interface ", ifname); n++; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_read(reply, "t", &flags); if (r < 0) return bus_log_parse_error(r); if (n == 0) { log_error("%s: no records found", name); return -ESRCH; } print_source(flags, ts); return 0; } static int resolve_rfc4501(sd_bus *bus, const char *name) { uint16_t type = 0, class = 0; const char *p, *q, *n; int r; assert(bus); assert(name); assert(startswith(name, "dns:")); /* Parse RFC 4501 dns: URIs */ p = name + 4; if (p[0] == '/') { const char *e; if (p[1] != '/') goto invalid; e = strchr(p + 2, '/'); if (!e) goto invalid; if (e != p + 2) log_warning("DNS authority specification not supported; ignoring specified authority."); p = e + 1; } q = strchr(p, '?'); if (q) { n = strndupa(p, q - p); q++; for (;;) { const char *f; f = startswith_no_case(q, "class="); if (f) { _cleanup_free_ char *t = NULL; const char *e; if (class != 0) { log_error("DNS class specified twice."); return -EINVAL; } e = strchrnul(f, ';'); t = strndup(f, e - f); if (!t) return log_oom(); r = dns_class_from_string(t); if (r < 0) { log_error("Unknown DNS class %s.", t); return -EINVAL; } class = r; if (*e == ';') { q = e + 1; continue; } break; } f = startswith_no_case(q, "type="); if (f) { _cleanup_free_ char *t = NULL; const char *e; if (type != 0) { log_error("DNS type specified twice."); return -EINVAL; } e = strchrnul(f, ';'); t = strndup(f, e - f); if (!t) return log_oom(); r = dns_type_from_string(t); if (r < 0) { log_error("Unknown DNS type %s.", t); return -EINVAL; } type = r; if (*e == ';') { q = e + 1; continue; } break; } goto invalid; } } else n = p; if (type == 0) type = arg_type; if (type == 0) type = DNS_TYPE_A; if (class == 0) class = arg_class; if (class == 0) class = DNS_CLASS_IN; return resolve_record(bus, n, class, type); invalid: log_error("Invalid DNS URI: %s", name); return -EINVAL; } static int resolve_service(sd_bus *bus, const char *name, const char *type, const char *domain) { const char *canonical_name, *canonical_type, *canonical_domain; _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char ifname[IF_NAMESIZE] = ""; size_t indent, sz; uint64_t flags; const char *p; unsigned c; usec_t ts; int r; assert(bus); assert(domain); if (isempty(name)) name = NULL; if (isempty(type)) type = NULL; if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname)) return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex); if (name) log_debug("Resolving service \"%s\" of type %s in %s (family %s, interface %s).", name, type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname); else if (type) log_debug("Resolving service type %s of %s (family %s, interface %s).", type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname); else log_debug("Resolving service type %s (family %s, interface %s).", domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname); r = sd_bus_message_new_method_call( bus, &req, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "ResolveService"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append(req, "isssit", arg_ifindex, name, type, domain, arg_family, arg_flags); if (r < 0) return bus_log_create_error(r); ts = now(CLOCK_MONOTONIC); r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) return log_error_errno(r, "Resolve call failed: %s", bus_error_message(&error, r)); ts = now(CLOCK_MONOTONIC) - ts; r = sd_bus_message_enter_container(reply, 'a', "(qqqsa(iiay)s)"); if (r < 0) return bus_log_parse_error(r); indent = (name ? strlen(name) + 1 : 0) + (type ? strlen(type) + 1 : 0) + strlen(domain) + 2; c = 0; while ((r = sd_bus_message_enter_container(reply, 'r', "qqqsa(iiay)s")) > 0) { uint16_t priority, weight, port; const char *hostname, *canonical; r = sd_bus_message_read(reply, "qqqs", &priority, &weight, &port, &hostname); if (r < 0) return bus_log_parse_error(r); if (name) printf("%*s%s", (int) strlen(name), c == 0 ? name : "", c == 0 ? "/" : " "); if (type) printf("%*s%s", (int) strlen(type), c == 0 ? type : "", c == 0 ? "/" : " "); printf("%*s%s %s:%u [priority=%u, weight=%u]\n", (int) strlen(domain), c == 0 ? domain : "", c == 0 ? ":" : " ", hostname, port, priority, weight); r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { _cleanup_free_ char *pretty = NULL; int ifindex, family; const void *a; assert_cc(sizeof(int) == sizeof(int32_t)); r = sd_bus_message_read(reply, "ii", &ifindex, &family); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_read_array(reply, 'y', &a, &sz); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); if (!IN_SET(family, AF_INET, AF_INET6)) { log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown"); continue; } if (sz != FAMILY_ADDRESS_SIZE(family)) { log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown"); return -EINVAL; } ifname[0] = 0; if (ifindex > 0 && !if_indextoname(ifindex, ifname)) log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex); r = in_addr_to_string(family, a, &pretty); if (r < 0) return log_error_errno(r, "Failed to print address for %s: %m", name); printf("%*s%s%s%s\n", (int) indent, "", pretty, isempty(ifname) ? "" : "%s", ifname); } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_read(reply, "s", &canonical); if (r < 0) return bus_log_parse_error(r); if (!streq(hostname, canonical)) printf("%*s(%s)\n", (int) indent, "", canonical); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); c++; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_enter_container(reply, 'a', "ay"); if (r < 0) return bus_log_parse_error(r); c = 0; while ((r = sd_bus_message_read_array(reply, 'y', (const void**) &p, &sz)) > 0) { _cleanup_free_ char *escaped = NULL; escaped = cescape_length(p, sz); if (!escaped) return log_oom(); printf("%*s%s\n", (int) indent, "", escaped); c++; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_read(reply, "ssst", &canonical_name, &canonical_type, &canonical_domain, &flags); if (r < 0) return bus_log_parse_error(r); if (isempty(canonical_name)) canonical_name = NULL; if (isempty(canonical_type)) canonical_type = NULL; if (!streq_ptr(name, canonical_name) || !streq_ptr(type, canonical_type) || !streq_ptr(domain, canonical_domain)) { printf("%*s(", (int) indent, ""); if (canonical_name) printf("%s/", canonical_name); if (canonical_type) printf("%s/", canonical_type); printf("%s)\n", canonical_domain); } print_source(flags, ts); return 0; } static int show_statistics(sd_bus *bus) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; uint64_t n_current_transactions, n_total_transactions, cache_size, n_cache_hit, n_cache_miss, n_dnssec_secure, n_dnssec_insecure, n_dnssec_bogus, n_dnssec_indeterminate; int r, dnssec_supported; assert(bus); r = sd_bus_get_property_trivial(bus, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "DNSSECSupported", &error, 'b', &dnssec_supported); if (r < 0) return log_error_errno(r, "Failed to get DNSSEC supported state: %s", bus_error_message(&error, r)); printf("DNSSEC supported by current servers: %s%s%s\n\n", ansi_highlight(), yes_no(dnssec_supported), ansi_normal()); r = sd_bus_get_property(bus, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "TransactionStatistics", &error, &reply, "(tt)"); if (r < 0) return log_error_errno(r, "Failed to get transaction statistics: %s", bus_error_message(&error, r)); r = sd_bus_message_read(reply, "(tt)", &n_current_transactions, &n_total_transactions); if (r < 0) return bus_log_parse_error(r); printf("%sTransactions%s\n" "Current Transactions: %" PRIu64 "\n" " Total Transactions: %" PRIu64 "\n", ansi_highlight(), ansi_normal(), n_current_transactions, n_total_transactions); reply = sd_bus_message_unref(reply); r = sd_bus_get_property(bus, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "CacheStatistics", &error, &reply, "(ttt)"); if (r < 0) return log_error_errno(r, "Failed to get cache statistics: %s", bus_error_message(&error, r)); r = sd_bus_message_read(reply, "(ttt)", &cache_size, &n_cache_hit, &n_cache_miss); if (r < 0) return bus_log_parse_error(r); printf("\n%sCache%s\n" " Current Cache Size: %" PRIu64 "\n" " Cache Hits: %" PRIu64 "\n" " Cache Misses: %" PRIu64 "\n", ansi_highlight(), ansi_normal(), cache_size, n_cache_hit, n_cache_miss); reply = sd_bus_message_unref(reply); r = sd_bus_get_property(bus, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "DNSSECStatistics", &error, &reply, "(tttt)"); if (r < 0) return log_error_errno(r, "Failed to get DNSSEC statistics: %s", bus_error_message(&error, r)); r = sd_bus_message_read(reply, "(tttt)", &n_dnssec_secure, &n_dnssec_insecure, &n_dnssec_bogus, &n_dnssec_indeterminate); if (r < 0) return bus_log_parse_error(r); printf("\n%sDNSSEC Verdicts%s\n" " Secure: %" PRIu64 "\n" " Insecure: %" PRIu64 "\n" " Bogus: %" PRIu64 "\n" " Indeterminate: %" PRIu64 "\n", ansi_highlight(), ansi_normal(), n_dnssec_secure, n_dnssec_insecure, n_dnssec_bogus, n_dnssec_indeterminate); return 0; } static int reset_statistics(sd_bus *bus) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; r = sd_bus_call_method(bus, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "ResetStatistics", &error, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to reset statistics: %s", bus_error_message(&error, r)); return 0; } static void help_protocol_types(void) { if (arg_legend) puts("Known protocol types:"); puts("dns\nllmnr\nllmnr-ipv4\nllmnr-ipv6"); } static void help_dns_types(void) { int i; const char *t; if (arg_legend) puts("Known DNS RR types:"); for (i = 0; i < _DNS_TYPE_MAX; i++) { t = dns_type_to_string(i); if (t) puts(t); } } static void help_dns_classes(void) { int i; const char *t; if (arg_legend) puts("Known DNS RR classes:"); for (i = 0; i < _DNS_CLASS_MAX; i++) { t = dns_class_to_string(i); if (t) puts(t); } } static void help(void) { printf("%s [OPTIONS...] NAME...\n" "%s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n\n" "Resolve domain names, IPv4 and IPv6 addresses, DNS resource records, and services.\n\n" " -h --help Show this help\n" " --version Show package version\n" " -4 Resolve IPv4 addresses\n" " -6 Resolve IPv6 addresses\n" " -i --interface=INTERFACE Look on interface\n" " -p --protocol=PROTOCOL|help Look via protocol\n" " -t --type=TYPE|help Query RR with DNS type\n" " -c --class=CLASS|help Query RR with DNS class\n" " --service Resolve service (SRV)\n" " --service-address=BOOL Do [not] resolve address for services\n" " --service-txt=BOOL Do [not] resolve TXT records for services\n" " --cname=BOOL Do [not] follow CNAME redirects\n" " --search=BOOL Do [not] use search domains\n" " --legend=BOOL Do [not] print column headers and meta information\n" " --statistics Show resolver statistics\n" " --reset-statistics Reset resolver statistics\n" , program_invocation_short_name, program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_LEGEND, ARG_SERVICE, ARG_CNAME, ARG_SERVICE_ADDRESS, ARG_SERVICE_TXT, ARG_SEARCH, ARG_STATISTICS, ARG_RESET_STATISTICS, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "type", required_argument, NULL, 't' }, { "class", required_argument, NULL, 'c' }, { "legend", required_argument, NULL, ARG_LEGEND }, { "interface", required_argument, NULL, 'i' }, { "protocol", required_argument, NULL, 'p' }, { "cname", required_argument, NULL, ARG_CNAME }, { "service", no_argument, NULL, ARG_SERVICE }, { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS }, { "service-txt", required_argument, NULL, ARG_SERVICE_TXT }, { "search", required_argument, NULL, ARG_SEARCH }, { "statistics", no_argument, NULL, ARG_STATISTICS, }, { "reset-statistics", no_argument, NULL, ARG_RESET_STATISTICS }, {} }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0) switch(c) { case 'h': help(); return 0; /* done */; case ARG_VERSION: return version(); case '4': arg_family = AF_INET; break; case '6': arg_family = AF_INET6; break; case 'i': { int ifi; if (parse_ifindex(optarg, &ifi) >= 0) arg_ifindex = ifi; else { ifi = if_nametoindex(optarg); if (ifi <= 0) return log_error_errno(errno, "Unknown interface %s: %m", optarg); arg_ifindex = ifi; } break; } case 't': if (streq(optarg, "help")) { help_dns_types(); return 0; } r = dns_type_from_string(optarg); if (r < 0) { log_error("Failed to parse RR record type %s", optarg); return r; } arg_type = (uint16_t) r; assert((int) arg_type == r); arg_mode = MODE_RESOLVE_RECORD; break; case 'c': if (streq(optarg, "help")) { help_dns_classes(); return 0; } r = dns_class_from_string(optarg); if (r < 0) { log_error("Failed to parse RR record class %s", optarg); return r; } arg_class = (uint16_t) r; assert((int) arg_class == r); break; case ARG_LEGEND: r = parse_boolean(optarg); if (r < 0) return log_error_errno(r, "Failed to parse --legend= argument"); arg_legend = r; break; case 'p': if (streq(optarg, "help")) { help_protocol_types(); return 0; } else if (streq(optarg, "dns")) arg_flags |= SD_RESOLVED_DNS; else if (streq(optarg, "llmnr")) arg_flags |= SD_RESOLVED_LLMNR; else if (streq(optarg, "llmnr-ipv4")) arg_flags |= SD_RESOLVED_LLMNR_IPV4; else if (streq(optarg, "llmnr-ipv6")) arg_flags |= SD_RESOLVED_LLMNR_IPV6; else { log_error("Unknown protocol specifier: %s", optarg); return -EINVAL; } break; case ARG_SERVICE: arg_mode = MODE_RESOLVE_SERVICE; break; case ARG_CNAME: r = parse_boolean(optarg); if (r < 0) return log_error_errno(r, "Failed to parse --cname= argument."); if (r == 0) arg_flags |= SD_RESOLVED_NO_CNAME; else arg_flags &= ~SD_RESOLVED_NO_CNAME; break; case ARG_SERVICE_ADDRESS: r = parse_boolean(optarg); if (r < 0) return log_error_errno(r, "Failed to parse --service-address= argument."); if (r == 0) arg_flags |= SD_RESOLVED_NO_ADDRESS; else arg_flags &= ~SD_RESOLVED_NO_ADDRESS; break; case ARG_SERVICE_TXT: r = parse_boolean(optarg); if (r < 0) return log_error_errno(r, "Failed to parse --service-txt= argument."); if (r == 0) arg_flags |= SD_RESOLVED_NO_TXT; else arg_flags &= ~SD_RESOLVED_NO_TXT; break; case ARG_SEARCH: r = parse_boolean(optarg); if (r < 0) return log_error_errno(r, "Failed to parse --search argument."); if (r == 0) arg_flags |= SD_RESOLVED_NO_SEARCH; else arg_flags &= ~SD_RESOLVED_NO_SEARCH; break; case ARG_STATISTICS: arg_mode = MODE_STATISTICS; break; case ARG_RESET_STATISTICS: arg_mode = MODE_RESET_STATISTICS; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (arg_type == 0 && arg_class != 0) { log_error("--class= may only be used in conjunction with --type=."); return -EINVAL; } if (arg_type != 0 && arg_mode != MODE_RESOLVE_RECORD) { log_error("--service and --type= may not be combined."); return -EINVAL; } if (arg_type != 0 && arg_class == 0) arg_class = DNS_CLASS_IN; if (arg_class != 0 && arg_type == 0) arg_type = DNS_TYPE_A; return 1 /* work to do */; } int main(int argc, char **argv) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = sd_bus_open_system(&bus); if (r < 0) { log_error_errno(r, "sd_bus_open_system: %m"); goto finish; } switch (arg_mode) { case MODE_RESOLVE_HOST: if (optind >= argc) { log_error("No arguments passed."); r = -EINVAL; goto finish; } while (argv[optind]) { int family, ifindex, k; union in_addr_union a; if (startswith(argv[optind], "dns:")) k = resolve_rfc4501(bus, argv[optind]); else { k = parse_address(argv[optind], &family, &a, &ifindex); if (k >= 0) k = resolve_address(bus, family, &a, ifindex); else k = resolve_host(bus, argv[optind]); } if (r == 0) r = k; optind++; } break; case MODE_RESOLVE_RECORD: if (optind >= argc) { log_error("No arguments passed."); r = -EINVAL; goto finish; } while (argv[optind]) { int k; k = resolve_record(bus, argv[optind], arg_class, arg_type); if (r == 0) r = k; optind++; } break; case MODE_RESOLVE_SERVICE: if (argc < optind + 1) { log_error("Domain specification required."); r = -EINVAL; goto finish; } else if (argc == optind + 1) r = resolve_service(bus, NULL, NULL, argv[optind]); else if (argc == optind + 2) r = resolve_service(bus, NULL, argv[optind], argv[optind+1]); else if (argc == optind + 3) r = resolve_service(bus, argv[optind], argv[optind+1], argv[optind+2]); else { log_error("Too many arguments."); r = -EINVAL; goto finish; } break; case MODE_STATISTICS: if (argc > optind) { log_error("Too many arguments."); r = -EINVAL; goto finish; } r = show_statistics(bus); break; case MODE_RESET_STATISTICS: if (argc > optind) { log_error("Too many arguments."); r = -EINVAL; goto finish; } r = reset_statistics(bus); break; } finish: return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } systemd-229/src/resolve/resolved-bus.c000066400000000000000000001473151265713322000201200ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-util.h" #include "dns-domain.h" #include "resolved-bus.h" #include "resolved-def.h" #include "resolved-link-bus.h" static int reply_query_state(DnsQuery *q) { switch (q->state) { case DNS_TRANSACTION_NO_SERVERS: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found"); case DNS_TRANSACTION_TIMEOUT: return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out"); case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED: return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed"); case DNS_TRANSACTION_INVALID_REPLY: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply"); case DNS_TRANSACTION_ERRNO: return sd_bus_reply_method_errnof(q->request, q->answer_errno, "Lookup failed due to system error: %m"); case DNS_TRANSACTION_ABORTED: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted"); case DNS_TRANSACTION_DNSSEC_FAILED: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_DNSSEC_FAILED, "DNSSEC validation failed: %s", dnssec_result_to_string(q->answer_dnssec_result)); case DNS_TRANSACTION_NO_TRUST_ANCHOR: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_TRUST_ANCHOR, "No suitable trust anchor known"); case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_RR_TYPE_UNSUPPORTED, "Server does not support requested resource record type"); case DNS_TRANSACTION_NETWORK_DOWN: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NETWORK_DOWN, "Network is down"); case DNS_TRANSACTION_NOT_FOUND: /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */ return sd_bus_reply_method_errorf(q->request, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q)); case DNS_TRANSACTION_RCODE_FAILURE: { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; if (q->answer_rcode == DNS_RCODE_NXDOMAIN) sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q)); else { const char *rc, *n; char p[DECIMAL_STR_MAX(q->answer_rcode)]; rc = dns_rcode_to_string(q->answer_rcode); if (!rc) { sprintf(p, "%i", q->answer_rcode); rc = p; } n = strjoina(_BUS_ERROR_DNS, rc); sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", dns_query_string(q), rc); } return sd_bus_reply_method_error(q->request, &error); } case DNS_TRANSACTION_NULL: case DNS_TRANSACTION_PENDING: case DNS_TRANSACTION_VALIDATING: case DNS_TRANSACTION_SUCCESS: default: assert_not_reached("Impossible state"); } } static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) { int r; assert(reply); assert(rr); r = sd_bus_message_open_container(reply, 'r', "iiay"); if (r < 0) return r; r = sd_bus_message_append(reply, "i", ifindex); if (r < 0) return r; if (rr->key->type == DNS_TYPE_A) { r = sd_bus_message_append(reply, "i", AF_INET); if (r < 0) return r; r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr)); } else if (rr->key->type == DNS_TYPE_AAAA) { r = sd_bus_message_append(reply, "i", AF_INET6); if (r < 0) return r; r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr)); } else return -EAFNOSUPPORT; if (r < 0) return r; r = sd_bus_message_close_container(reply); if (r < 0) return r; return 0; } static void bus_method_resolve_hostname_complete(DnsQuery *q) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; DnsResourceRecord *rr; unsigned added = 0; int ifindex, r; assert(q); if (q->state != DNS_TRANSACTION_SUCCESS) { r = reply_query_state(q); goto finish; } r = dns_query_process_cname(q); if (r == -ELOOP) { r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); goto finish; } if (r < 0) goto finish; if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ return; r = sd_bus_message_new_method_return(q->request, &reply); if (r < 0) goto finish; r = sd_bus_message_open_container(reply, 'a', "(iiay)"); if (r < 0) goto finish; DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) { DnsQuestion *question; question = dns_query_question_for_protocol(q, q->answer_protocol); r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain)); if (r < 0) goto finish; if (r == 0) continue; r = append_address(reply, rr, ifindex); if (r < 0) goto finish; if (!canonical) canonical = dns_resource_record_ref(rr); added ++; } if (added <= 0) { r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q)); goto finish; } r = sd_bus_message_close_container(reply); if (r < 0) goto finish; /* Return the precise spelling and uppercasing and CNAME target reported by the server */ assert(canonical); r = sd_bus_message_append( reply, "st", DNS_RESOURCE_KEY_NAME(canonical->key), SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated)); if (r < 0) goto finish; r = sd_bus_send(q->manager->bus, reply, NULL); finish: if (r < 0) { log_error_errno(r, "Failed to send hostname reply: %m"); sd_bus_reply_method_errno(q->request, r, NULL); } dns_query_free(q); } static int check_ifindex_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) { assert(flags); if (ifindex < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index"); if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter"); if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */ *flags |= SD_RESOLVED_PROTOCOLS_ALL; return 0; } static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL; Manager *m = userdata; const char *hostname; int family, ifindex; uint64_t flags; DnsQuery *q; int r; assert(message); assert(m); assert_cc(sizeof(int) == sizeof(int32_t)); r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags); if (r < 0) return r; if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); r = dns_name_is_valid(hostname); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname); r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error); if (r < 0) return r; r = dns_question_new_address(&question_utf8, family, hostname, false); if (r < 0) return r; r = dns_question_new_address(&question_idna, family, hostname, true); if (r < 0) return r; r = dns_query_new(m, &q, question_utf8, question_idna, ifindex, flags); if (r < 0) return r; q->request = sd_bus_message_ref(message); q->request_family = family; q->complete = bus_method_resolve_hostname_complete; q->suppress_unroutable_family = family == AF_UNSPEC; r = dns_query_bus_track(q, message); if (r < 0) goto fail; r = dns_query_go(q); if (r < 0) goto fail; return 1; fail: dns_query_free(q); return r; } static void bus_method_resolve_address_complete(DnsQuery *q) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; DnsQuestion *question; DnsResourceRecord *rr; unsigned added = 0; int ifindex, r; assert(q); if (q->state != DNS_TRANSACTION_SUCCESS) { r = reply_query_state(q); goto finish; } r = dns_query_process_cname(q); if (r == -ELOOP) { r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); goto finish; } if (r < 0) goto finish; if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ return; r = sd_bus_message_new_method_return(q->request, &reply); if (r < 0) goto finish; r = sd_bus_message_open_container(reply, 'a', "(is)"); if (r < 0) goto finish; question = dns_query_question_for_protocol(q, q->answer_protocol); DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) { r = dns_question_matches_rr(question, rr, NULL); if (r < 0) goto finish; if (r == 0) continue; r = sd_bus_message_append(reply, "(is)", ifindex, rr->ptr.name); if (r < 0) goto finish; added ++; } if (added <= 0) { _cleanup_free_ char *ip = NULL; in_addr_to_string(q->request_family, &q->request_address, &ip); r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", strna(ip)); goto finish; } r = sd_bus_message_close_container(reply); if (r < 0) goto finish; r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated)); if (r < 0) goto finish; r = sd_bus_send(q->manager->bus, reply, NULL); finish: if (r < 0) { log_error_errno(r, "Failed to send address reply: %m"); sd_bus_reply_method_errno(q->request, r, NULL); } dns_query_free(q); } static int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL; Manager *m = userdata; int family, ifindex; uint64_t flags; const void *d; DnsQuery *q; size_t sz; int r; assert(message); assert(m); assert_cc(sizeof(int) == sizeof(int32_t)); r = sd_bus_message_read(message, "ii", &ifindex, &family); if (r < 0) return r; if (!IN_SET(family, AF_INET, AF_INET6)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); r = sd_bus_message_read_array(message, 'y', &d, &sz); if (r < 0) return r; if (sz != FAMILY_ADDRESS_SIZE(family)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size"); r = sd_bus_message_read(message, "t", &flags); if (r < 0) return r; r = check_ifindex_flags(ifindex, &flags, 0, error); if (r < 0) return r; r = dns_question_new_reverse(&question, family, d); if (r < 0) return r; r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH); if (r < 0) return r; q->request = sd_bus_message_ref(message); q->request_family = family; memcpy(&q->request_address, d, sz); q->complete = bus_method_resolve_address_complete; r = dns_query_bus_track(q, message); if (r < 0) goto fail; r = dns_query_go(q); if (r < 0) goto fail; return 1; fail: dns_query_free(q); return r; } static int bus_message_append_rr(sd_bus_message *m, DnsResourceRecord *rr, int ifindex) { int r; assert(m); assert(rr); r = sd_bus_message_open_container(m, 'r', "iqqay"); if (r < 0) return r; r = sd_bus_message_append(m, "iqq", ifindex, rr->key->class, rr->key->type); if (r < 0) return r; r = dns_resource_record_to_wire_format(rr, false); if (r < 0) return r; r = sd_bus_message_append_array(m, 'y', rr->wire_format, rr->wire_format_size); if (r < 0) return r; return sd_bus_message_close_container(m); } static void bus_method_resolve_record_complete(DnsQuery *q) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; DnsResourceRecord *rr; DnsQuestion *question; unsigned added = 0; int ifindex; int r; assert(q); if (q->state != DNS_TRANSACTION_SUCCESS) { r = reply_query_state(q); goto finish; } r = dns_query_process_cname(q); if (r == -ELOOP) { r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); goto finish; } if (r < 0) goto finish; if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ return; r = sd_bus_message_new_method_return(q->request, &reply); if (r < 0) goto finish; r = sd_bus_message_open_container(reply, 'a', "(iqqay)"); if (r < 0) goto finish; question = dns_query_question_for_protocol(q, q->answer_protocol); DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) { r = dns_question_matches_rr(question, rr, NULL); if (r < 0) goto finish; if (r == 0) continue; r = bus_message_append_rr(reply, rr, ifindex); if (r < 0) goto finish; added ++; } if (added <= 0) { r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Name '%s' does not have any RR of the requested type", dns_query_string(q)); goto finish; } r = sd_bus_message_close_container(reply); if (r < 0) goto finish; r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated)); if (r < 0) goto finish; r = sd_bus_send(q->manager->bus, reply, NULL); finish: if (r < 0) { log_error_errno(r, "Failed to send record reply: %m"); sd_bus_reply_method_errno(q->request, r, NULL); } dns_query_free(q); } static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL; Manager *m = userdata; uint16_t class, type; const char *name; int r, ifindex; uint64_t flags; DnsQuery *q; assert(message); assert(m); assert_cc(sizeof(int) == sizeof(int32_t)); r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags); if (r < 0) return r; r = dns_name_is_valid(name); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name); if (!dns_type_is_valid_query(type)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified resource record type %" PRIu16 " may not be used in a query.", type); if (dns_type_is_obsolete(type)) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Specified DNS resource record type %" PRIu16 " is obsolete.", type); r = check_ifindex_flags(ifindex, &flags, 0, error); if (r < 0) return r; question = dns_question_new(1); if (!question) return -ENOMEM; key = dns_resource_key_new(class, type, name); if (!key) return -ENOMEM; r = dns_question_add(question, key); if (r < 0) return r; r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH); if (r < 0) return r; q->request = sd_bus_message_ref(message); q->complete = bus_method_resolve_record_complete; r = dns_query_bus_track(q, message); if (r < 0) goto fail; r = dns_query_go(q); if (r < 0) goto fail; return 1; fail: dns_query_free(q); return r; } static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL; DnsQuery *aux; int r; assert(q); assert(reply); assert(rr); assert(rr->key); if (rr->key->type != DNS_TYPE_SRV) return 0; if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) { /* First, let's see if we could find an appropriate A or AAAA * record for the SRV record */ LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) { DnsResourceRecord *zz; DnsQuestion *question; if (aux->state != DNS_TRANSACTION_SUCCESS) continue; if (aux->auxiliary_result != 0) continue; question = dns_query_question_for_protocol(aux, aux->answer_protocol); r = dns_name_equal(dns_question_first_name(question), rr->srv.name); if (r < 0) return r; if (r == 0) continue; DNS_ANSWER_FOREACH(zz, aux->answer) { r = dns_question_matches_rr(question, zz, NULL); if (r < 0) return r; if (r == 0) continue; canonical = dns_resource_record_ref(zz); break; } if (canonical) break; } /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */ if (!canonical) return 0; } r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s"); if (r < 0) return r; r = sd_bus_message_append( reply, "qqqs", rr->srv.priority, rr->srv.weight, rr->srv.port, rr->srv.name); if (r < 0) return r; r = sd_bus_message_open_container(reply, 'a', "(iiay)"); if (r < 0) return r; if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) { LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) { DnsResourceRecord *zz; DnsQuestion *question; int ifindex; if (aux->state != DNS_TRANSACTION_SUCCESS) continue; if (aux->auxiliary_result != 0) continue; question = dns_query_question_for_protocol(aux, aux->answer_protocol); r = dns_name_equal(dns_question_first_name(question), rr->srv.name); if (r < 0) return r; if (r == 0) continue; DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) { r = dns_question_matches_rr(question, zz, NULL); if (r < 0) return r; if (r == 0) continue; r = append_address(reply, zz, ifindex); if (r < 0) return r; } } } r = sd_bus_message_close_container(reply); if (r < 0) return r; /* Note that above we appended the hostname as encoded in the * SRV, and here the canonical hostname this maps to. */ r = sd_bus_message_append(reply, "s", canonical ? DNS_RESOURCE_KEY_NAME(canonical->key) : rr->srv.name); if (r < 0) return r; r = sd_bus_message_close_container(reply); if (r < 0) return r; return 1; } static int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) { DnsTxtItem *i; int r; assert(reply); assert(rr); assert(rr->key); if (rr->key->type != DNS_TYPE_TXT) return 0; LIST_FOREACH(items, i, rr->txt.items) { if (i->length <= 0) continue; r = sd_bus_message_append_array(reply, 'y', i->data, i->length); if (r < 0) return r; } return 1; } static void resolve_service_all_complete(DnsQuery *q) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL; DnsQuestion *question; DnsResourceRecord *rr; unsigned added = 0; DnsQuery *aux; int r; assert(q); if (q->block_all_complete > 0) return; if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) { DnsQuery *bad = NULL; bool have_success = false; LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) { switch (aux->state) { case DNS_TRANSACTION_PENDING: /* If an auxiliary query is still pending, let's wait */ return; case DNS_TRANSACTION_SUCCESS: if (aux->auxiliary_result == 0) have_success = true; else bad = aux; break; default: bad = aux; break; } } if (!have_success) { /* We can only return one error, hence pick the last error we encountered */ assert(bad); if (bad->state == DNS_TRANSACTION_SUCCESS) { assert(bad->auxiliary_result != 0); if (bad->auxiliary_result == -ELOOP) { r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(bad)); goto finish; } r = bad->auxiliary_result; goto finish; } r = reply_query_state(bad); goto finish; } } r = sd_bus_message_new_method_return(q->request, &reply); if (r < 0) goto finish; r = sd_bus_message_open_container(reply, 'a', "(qqqsa(iiay)s)"); if (r < 0) goto finish; question = dns_query_question_for_protocol(q, q->answer_protocol); DNS_ANSWER_FOREACH(rr, q->answer) { r = dns_question_matches_rr(question, rr, NULL); if (r < 0) goto finish; if (r == 0) continue; r = append_srv(q, reply, rr); if (r < 0) goto finish; if (r == 0) /* not an SRV record */ continue; if (!canonical) canonical = dns_resource_record_ref(rr); added++; } if (added <= 0) { r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q)); goto finish; } r = sd_bus_message_close_container(reply); if (r < 0) goto finish; r = sd_bus_message_open_container(reply, 'a', "ay"); if (r < 0) goto finish; DNS_ANSWER_FOREACH(rr, q->answer) { r = dns_question_matches_rr(question, rr, NULL); if (r < 0) goto finish; if (r == 0) continue; r = append_txt(reply, rr); if (r < 0) goto finish; } r = sd_bus_message_close_container(reply); if (r < 0) goto finish; assert(canonical); r = dns_service_split(DNS_RESOURCE_KEY_NAME(canonical->key), &name, &type, &domain); if (r < 0) goto finish; r = sd_bus_message_append( reply, "ssst", name, type, domain, SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated)); if (r < 0) goto finish; r = sd_bus_send(q->manager->bus, reply, NULL); finish: if (r < 0) { log_error_errno(r, "Failed to send service reply: %m"); sd_bus_reply_method_errno(q->request, r, NULL); } dns_query_free(q); } static void resolve_service_hostname_complete(DnsQuery *q) { int r; assert(q); assert(q->auxiliary_for); if (q->state != DNS_TRANSACTION_SUCCESS) { resolve_service_all_complete(q->auxiliary_for); return; } r = dns_query_process_cname(q); if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ return; /* This auxiliary lookup is finished or failed, let's see if all are finished now. */ q->auxiliary_result = r; resolve_service_all_complete(q->auxiliary_for); } static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) { _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL; DnsQuery *aux; int r; assert(q); assert(rr); assert(rr->key); assert(rr->key->type == DNS_TYPE_SRV); /* OK, we found an SRV record for the service. Let's resolve * the hostname included in it */ r = dns_question_new_address(&question, q->request_family, rr->srv.name, false); if (r < 0) return r; r = dns_query_new(q->manager, &aux, question, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH); if (r < 0) return r; aux->request_family = q->request_family; aux->complete = resolve_service_hostname_complete; r = dns_query_make_auxiliary(aux, q); if (r == -EAGAIN) { /* Too many auxiliary lookups? If so, don't complain, * let's just not add this one, we already have more * than enough */ dns_query_free(aux); return 0; } if (r < 0) goto fail; /* Note that auxiliary queries do not track the original bus * client, only the primary request does that. */ r = dns_query_go(aux); if (r < 0) goto fail; return 1; fail: dns_query_free(aux); return r; } static void bus_method_resolve_service_complete(DnsQuery *q) { bool has_root_domain = false; DnsResourceRecord *rr; DnsQuestion *question; unsigned found = 0; int ifindex, r; assert(q); if (q->state != DNS_TRANSACTION_SUCCESS) { r = reply_query_state(q); goto finish; } r = dns_query_process_cname(q); if (r == -ELOOP) { r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); goto finish; } if (r < 0) goto finish; if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ return; question = dns_query_question_for_protocol(q, q->answer_protocol); DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) { r = dns_question_matches_rr(question, rr, NULL); if (r < 0) goto finish; if (r == 0) continue; if (rr->key->type != DNS_TYPE_SRV) continue; if (dns_name_is_root(rr->srv.name)) { has_root_domain = true; continue; } if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) { q->block_all_complete ++; r = resolve_service_hostname(q, rr, ifindex); q->block_all_complete --; if (r < 0) goto finish; } found++; } if (has_root_domain && found <= 0) { /* If there's exactly one SRV RR and it uses * the root domain as host name, then the * service is explicitly not offered on the * domain. Report this as a recognizable * error. See RFC 2782, Section "Usage * Rules". */ r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_SERVICE, "'%s' does not provide the requested service", dns_query_string(q)); goto finish; } if (found <= 0) { r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q)); goto finish; } /* Maybe we are already finished? check now... */ resolve_service_all_complete(q); return; finish: if (r < 0) { log_error_errno(r, "Failed to send service reply: %m"); sd_bus_reply_method_errno(q->request, r, NULL); } dns_query_free(q); } static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL; const char *name, *type, *domain; _cleanup_free_ char *n = NULL; Manager *m = userdata; int family, ifindex; uint64_t flags; DnsQuery *q; int r; assert(message); assert(m); assert_cc(sizeof(int) == sizeof(int32_t)); r = sd_bus_message_read(message, "isssit", &ifindex, &name, &type, &domain, &family, &flags); if (r < 0) return r; if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); if (isempty(name)) name = NULL; else if (!dns_service_name_is_valid(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service name '%s'", name); if (isempty(type)) type = NULL; else if (!dns_srv_type_is_valid(type)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SRV service type '%s'", type); r = dns_name_is_valid(domain); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid domain '%s'", domain); if (name && !type) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type."); r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error); if (r < 0) return r; r = dns_question_new_service(&question_utf8, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), false); if (r < 0) return r; r = dns_question_new_service(&question_idna, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), true); if (r < 0) return r; r = dns_query_new(m, &q, question_utf8, question_idna, ifindex, flags|SD_RESOLVED_NO_SEARCH); if (r < 0) return r; q->request = sd_bus_message_ref(message); q->request_family = family; q->complete = bus_method_resolve_service_complete; r = dns_query_bus_track(q, message); if (r < 0) goto fail; r = dns_query_go(q); if (r < 0) goto fail; return 1; fail: dns_query_free(q); return r; } int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex) { int r; assert(reply); assert(s); r = sd_bus_message_open_container(reply, 'r', with_ifindex ? "iiay" : "iay"); if (r < 0) return r; if (with_ifindex) { r = sd_bus_message_append(reply, "i", s->link ? s->link->ifindex : 0); if (r < 0) return r; } r = sd_bus_message_append(reply, "i", s->family); if (r < 0) return r; r = sd_bus_message_append_array(reply, 'y', &s->address, FAMILY_ADDRESS_SIZE(s->family)); if (r < 0) return r; return sd_bus_message_close_container(reply); } static int bus_property_get_dns_servers( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; unsigned c = 0; DnsServer *s; Iterator i; Link *l; int r; assert(reply); assert(m); r = sd_bus_message_open_container(reply, 'a', "(iiay)"); if (r < 0) return r; LIST_FOREACH(servers, s, m->dns_servers) { r = bus_dns_server_append(reply, s, true); if (r < 0) return r; c++; } HASHMAP_FOREACH(l, m->links, i) { LIST_FOREACH(servers, s, l->dns_servers) { r = bus_dns_server_append(reply, s, true); if (r < 0) return r; c++; } } if (c == 0) { LIST_FOREACH(servers, s, m->fallback_dns_servers) { r = bus_dns_server_append(reply, s, true); if (r < 0) return r; } } return sd_bus_message_close_container(reply); } static int bus_property_get_search_domains( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; DnsSearchDomain *d; Iterator i; Link *l; int r; assert(reply); assert(m); r = sd_bus_message_open_container(reply, 'a', "(isb)"); if (r < 0) return r; LIST_FOREACH(domains, d, m->search_domains) { r = sd_bus_message_append(reply, "(isb)", 0, d->name, d->route_only); if (r < 0) return r; } HASHMAP_FOREACH(l, m->links, i) { LIST_FOREACH(domains, d, l->search_domains) { r = sd_bus_message_append(reply, "(isb)", l->ifindex, d->name, d->route_only); if (r < 0) return r; } } return sd_bus_message_close_container(reply); } static int bus_property_get_transaction_statistics( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; assert(reply); assert(m); return sd_bus_message_append(reply, "(tt)", (uint64_t) hashmap_size(m->dns_transactions), (uint64_t) m->n_transactions_total); } static int bus_property_get_cache_statistics( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { uint64_t size = 0, hit = 0, miss = 0; Manager *m = userdata; DnsScope *s; assert(reply); assert(m); LIST_FOREACH(scopes, s, m->dns_scopes) { size += dns_cache_size(&s->cache); hit += s->cache.n_hit; miss += s->cache.n_miss; } return sd_bus_message_append(reply, "(ttt)", size, hit, miss); } static int bus_property_get_dnssec_statistics( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; assert(reply); assert(m); return sd_bus_message_append(reply, "(tttt)", (uint64_t) m->n_dnssec_verdict[DNSSEC_SECURE], (uint64_t) m->n_dnssec_verdict[DNSSEC_INSECURE], (uint64_t) m->n_dnssec_verdict[DNSSEC_BOGUS], (uint64_t) m->n_dnssec_verdict[DNSSEC_INDETERMINATE]); } static int bus_property_get_dnssec_supported( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Manager *m = userdata; assert(reply); assert(m); return sd_bus_message_append(reply, "b", manager_dnssec_supported(m)); } static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; DnsScope *s; assert(message); assert(m); LIST_FOREACH(scopes, s, m->dns_scopes) s->cache.n_hit = s->cache.n_miss = 0; m->n_transactions_total = 0; zero(m->n_dnssec_verdict); return sd_bus_reply_method_return(message, NULL); } static int get_any_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) { Link *l; assert(m); assert(ret); if (ifindex <= 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index"); l = hashmap_get(m->links, INT_TO_PTR(ifindex)); if (!l) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %i not known", ifindex); *ret = l; return 0; } static int get_unmanaged_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) { Link *l; int r; assert(m); assert(ret); r = get_any_link(m, ifindex, &l, error); if (r < 0) return r; if (l->flags & IFF_LOOPBACK) return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is loopback device.", l->name); if (l->is_managed) return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is managed.", l->name); *ret = l; return 0; } static int call_link_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) { int ifindex, r; Link *l; assert(m); assert(message); assert(handler); assert_cc(sizeof(int) == sizeof(int32_t)); r = sd_bus_message_read(message, "i", &ifindex); if (r < 0) return r; r = get_unmanaged_link(m, ifindex, &l, error); if (r < 0) return r; return handler(message, l, error); } static int bus_method_set_link_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) { return call_link_method(userdata, message, bus_link_method_set_dns_servers, error); } static int bus_method_set_link_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) { return call_link_method(userdata, message, bus_link_method_set_search_domains, error); } static int bus_method_set_link_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) { return call_link_method(userdata, message, bus_link_method_set_llmnr, error); } static int bus_method_set_link_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) { return call_link_method(userdata, message, bus_link_method_set_mdns, error); } static int bus_method_set_link_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) { return call_link_method(userdata, message, bus_link_method_set_dnssec, error); } static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) { return call_link_method(userdata, message, bus_link_method_set_dnssec_negative_trust_anchors, error); } static int bus_method_revert_link(sd_bus_message *message, void *userdata, sd_bus_error *error) { return call_link_method(userdata, message, bus_link_method_revert, error); } static int bus_method_get_link(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Manager *m = userdata; int r, ifindex; Link *l; assert(message); assert(m); assert_cc(sizeof(int) == sizeof(int32_t)); r = sd_bus_message_read(message, "i", &ifindex); if (r < 0) return r; r = get_any_link(m, ifindex, &l, error); if (r < 0) return r; p = link_bus_path(l); if (!p) return -ENOMEM; return sd_bus_reply_method_return(message, "o", p); } static const sd_bus_vtable resolve_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0), SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, 0), SD_BUS_PROPERTY("SearchDomains", "a(isb)", bus_property_get_search_domains, 0, 0), SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0), SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0), SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0), SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported, 0, 0), SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, 0), SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, 0), SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_search_domains, 0), SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, 0), SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, 0), SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, 0), SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL, bus_method_set_link_dnssec_negative_trust_anchors, 0), SD_BUS_METHOD("RevertLink", "i", NULL, bus_method_revert_link, 0), SD_BUS_VTABLE_END, }; static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) { Manager *m = userdata; assert(s); assert(m); m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source); manager_connect_bus(m); return 0; } static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { Manager *m = userdata; int b, r; assert(message); assert(m); r = sd_bus_message_read(message, "b", &b); if (r < 0) { log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m"); return 0; } if (b) return 0; log_debug("Coming back from suspend, verifying all RRs..."); manager_verify_all(m); return 0; } int manager_connect_bus(Manager *m) { int r; assert(m); if (m->bus) return 0; r = sd_bus_default_system(&m->bus); if (r < 0) { /* We failed to connect? Yuck, we must be in early * boot. Let's try in 5s again. As soon as we have * kdbus we can stop doing this... */ log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m"); r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m); if (r < 0) return log_error_errno(r, "Failed to install bus reconnect time event: %m"); (void) sd_event_source_set_description(m->bus_retry_event_source, "bus-retry"); return 0; } r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m); if (r < 0) return log_error_errno(r, "Failed to register object: %m"); r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/resolve1/link", "org.freedesktop.resolve1.Link", link_vtable, link_object_find, m); if (r < 0) return log_error_errno(r, "Failed to register link objects: %m"); r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/resolve1/link", link_node_enumerator, m); if (r < 0) return log_error_errno(r, "Failed to register link enumerator: %m"); r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0); if (r < 0) return log_error_errno(r, "Failed to register name: %m"); r = sd_bus_attach_event(m->bus, m->event, 0); if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop: %m"); r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot, "type='signal'," "sender='org.freedesktop.login1'," "interface='org.freedesktop.login1.Manager'," "member='PrepareForSleep'," "path='/org/freedesktop/login1'", match_prepare_for_sleep, m); if (r < 0) log_error_errno(r, "Failed to add match for PrepareForSleep: %m"); return 0; } systemd-229/src/resolve/resolved-bus.h000066400000000000000000000015641265713322000201200ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "resolved-manager.h" int manager_connect_bus(Manager *m); int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex); systemd-229/src/resolve/resolved-conf.c000066400000000000000000000156361265713322000202540ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "conf-parser.h" #include "def.h" #include "extract-word.h" #include "parse-util.h" #include "resolved-conf.h" #include "string-util.h" int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) { union in_addr_union address; int family, r; DnsServer *s; assert(m); assert(word); r = in_addr_from_string_auto(word, &family, &address); if (r < 0) return r; /* Filter out duplicates */ s = dns_server_find(manager_get_first_dns_server(m, type), family, &address); if (s) { /* * Drop the marker. This is used to find the servers * that ceased to exist, see * manager_mark_dns_servers() and * manager_flush_marked_dns_servers(). */ dns_server_move_back_and_unmark(s); return 0; } return dns_server_new(m, NULL, type, NULL, family, &address); } int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string) { int r; assert(m); assert(string); for(;;) { _cleanup_free_ char *word = NULL; r = extract_first_word(&string, &word, NULL, 0); if (r < 0) return r; if (r == 0) break; r = manager_add_dns_server_by_string(m, type, word); if (r < 0) log_warning_errno(r, "Failed to add DNS server address '%s', ignoring.", word); } return 0; } int manager_add_search_domain_by_string(Manager *m, const char *domain) { DnsSearchDomain *d; bool route_only; int r; assert(m); assert(domain); route_only = *domain == '~'; if (route_only) domain++; if (dns_name_is_root(domain) || streq(domain, "*")) { route_only = true; domain = "."; } r = dns_search_domain_find(m->search_domains, domain, &d); if (r < 0) return r; if (r > 0) dns_search_domain_move_back_and_unmark(d); else { r = dns_search_domain_new(m, &d, DNS_SEARCH_DOMAIN_SYSTEM, NULL, domain); if (r < 0) return r; } d->route_only = route_only; return 0; } int manager_parse_search_domains_and_warn(Manager *m, const char *string) { int r; assert(m); assert(string); for(;;) { _cleanup_free_ char *word = NULL; r = extract_first_word(&string, &word, NULL, EXTRACT_QUOTES); if (r < 0) return r; if (r == 0) break; r = manager_add_search_domain_by_string(m, word); if (r < 0) log_warning_errno(r, "Failed to add search domain '%s', ignoring.", word); } return 0; } int config_parse_dns_servers( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Manager *m = userdata; int r; assert(filename); assert(lvalue); assert(rvalue); assert(m); if (isempty(rvalue)) /* Empty assignment means clear the list */ dns_server_unlink_all(manager_get_first_dns_server(m, ltype)); else { /* Otherwise, add to the list */ r = manager_parse_dns_server_string_and_warn(m, ltype, rvalue); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DNS server string '%s'. Ignoring.", rvalue); return 0; } } /* If we have a manual setting, then we stop reading * /etc/resolv.conf */ if (ltype == DNS_SERVER_SYSTEM) m->read_resolv_conf = false; if (ltype == DNS_SERVER_FALLBACK) m->need_builtin_fallbacks = false; return 0; } int config_parse_search_domains( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Manager *m = userdata; int r; assert(filename); assert(lvalue); assert(rvalue); assert(m); if (isempty(rvalue)) /* Empty assignment means clear the list */ dns_search_domain_unlink_all(m->search_domains); else { /* Otherwise, add to the list */ r = manager_parse_search_domains_and_warn(m, rvalue); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse search domains string '%s'. Ignoring.", rvalue); return 0; } } /* If we have a manual setting, then we stop reading * /etc/resolv.conf */ m->read_resolv_conf = false; return 0; } int manager_parse_config_file(Manager *m) { int r; assert(m); r = config_parse_many(PKGSYSCONFDIR "/resolved.conf", CONF_PATHS_NULSTR("systemd/resolved.conf.d"), "Resolve\0", config_item_perf_lookup, resolved_gperf_lookup, false, m); if (r < 0) return r; if (m->need_builtin_fallbacks) { r = manager_parse_dns_server_string_and_warn(m, DNS_SERVER_FALLBACK, DNS_SERVERS); if (r < 0) return r; } return 0; } systemd-229/src/resolve/resolved-conf.h000066400000000000000000000035061265713322000202520ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "resolved-manager.h" int manager_parse_config_file(Manager *m); int manager_add_search_domain_by_string(Manager *m, const char *domain); int manager_parse_search_domains_and_warn(Manager *m, const char *string); int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word); int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string); const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, unsigned length); int config_parse_dns_servers(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_search_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_dnssec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); systemd-229/src/resolve/resolved-def.h000066400000000000000000000030011265713322000200510ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #define SD_RESOLVED_DNS (UINT64_C(1) << 0) #define SD_RESOLVED_LLMNR_IPV4 (UINT64_C(1) << 1) #define SD_RESOLVED_LLMNR_IPV6 (UINT64_C(1) << 2) #define SD_RESOLVED_MDNS_IPV4 (UINT64_C(1) << 3) #define SD_RESOLVED_MDNS_IPV6 (UINT64_C(1) << 4) #define SD_RESOLVED_NO_CNAME (UINT64_C(1) << 5) #define SD_RESOLVED_NO_TXT (UINT64_C(1) << 6) #define SD_RESOLVED_NO_ADDRESS (UINT64_C(1) << 7) #define SD_RESOLVED_NO_SEARCH (UINT64_C(1) << 8) #define SD_RESOLVED_AUTHENTICATED (UINT64_C(1) << 9) #define SD_RESOLVED_LLMNR (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6) #define SD_RESOLVED_MDNS (SD_RESOLVED_MDNS_IPV4|SD_RESOLVED_MDNS_IPV6) #define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS) systemd-229/src/resolve/resolved-dns-answer.c000066400000000000000000000570421265713322000214050ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "dns-domain.h" #include "resolved-dns-answer.h" #include "resolved-dns-dnssec.h" #include "string-util.h" DnsAnswer *dns_answer_new(unsigned n) { DnsAnswer *a; a = malloc0(offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * n); if (!a) return NULL; a->n_ref = 1; a->n_allocated = n; return a; } DnsAnswer *dns_answer_ref(DnsAnswer *a) { if (!a) return NULL; assert(a->n_ref > 0); a->n_ref++; return a; } static void dns_answer_flush(DnsAnswer *a) { DnsResourceRecord *rr; if (!a) return; DNS_ANSWER_FOREACH(rr, a) dns_resource_record_unref(rr); a->n_rrs = 0; } DnsAnswer *dns_answer_unref(DnsAnswer *a) { if (!a) return NULL; assert(a->n_ref > 0); if (a->n_ref == 1) { dns_answer_flush(a); free(a); } else a->n_ref--; return NULL; } static int dns_answer_add_raw(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) { assert(rr); if (!a) return -ENOSPC; if (a->n_rrs >= a->n_allocated) return -ENOSPC; a->items[a->n_rrs++] = (DnsAnswerItem) { .rr = dns_resource_record_ref(rr), .ifindex = ifindex, .flags = flags, }; return 1; } static int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) { DnsResourceRecord *rr; DnsAnswerFlags flags; int ifindex, r; DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, source) { r = dns_answer_add_raw(a, rr, ifindex, flags); if (r < 0) return r; } return 0; } int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) { unsigned i; int r; assert(rr); if (!a) return -ENOSPC; if (a->n_ref > 1) return -EBUSY; for (i = 0; i < a->n_rrs; i++) { if (a->items[i].ifindex != ifindex) continue; r = dns_resource_record_equal(a->items[i].rr, rr); if (r < 0) return r; if (r > 0) { /* Don't mix contradicting TTLs (see below) */ if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0)) return -EINVAL; /* Entry already exists, keep the entry with * the higher RR. */ if (rr->ttl > a->items[i].rr->ttl) { dns_resource_record_ref(rr); dns_resource_record_unref(a->items[i].rr); a->items[i].rr = rr; } a->items[i].flags |= flags; return 0; } r = dns_resource_key_equal(a->items[i].rr->key, rr->key); if (r < 0) return r; if (r > 0) { /* There's already an RR of the same RRset in * place! Let's see if the TTLs more or less * match. We don't really care if they match * precisely, but we do care whether one is 0 * and the other is not. See RFC 2181, Section * 5.2.*/ if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0)) return -EINVAL; } } return dns_answer_add_raw(a, rr, ifindex, flags); } static int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) { DnsResourceRecord *rr; DnsAnswerFlags flags; int ifindex, r; DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, b) { r = dns_answer_add(a, rr, ifindex, flags); if (r < 0) return r; } return 0; } int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) { int r; assert(a); assert(rr); r = dns_answer_reserve_or_clone(a, 1); if (r < 0) return r; return dns_answer_add(*a, rr, ifindex, flags); } int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *soa = NULL; soa = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SOA, name); if (!soa) return -ENOMEM; soa->ttl = ttl; soa->soa.mname = strdup(name); if (!soa->soa.mname) return -ENOMEM; soa->soa.rname = strappend("root.", name); if (!soa->soa.rname) return -ENOMEM; soa->soa.serial = 1; soa->soa.refresh = 1; soa->soa.retry = 1; soa->soa.expire = 1; soa->soa.minimum = ttl; return dns_answer_add(a, soa, 0, DNS_ANSWER_AUTHENTICATED); } int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) { DnsAnswerFlags flags = 0, i_flags; DnsResourceRecord *i; bool found = false; int r; assert(key); DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) { r = dns_resource_key_match_rr(key, i, NULL); if (r < 0) return r; if (r == 0) continue; if (!ret_flags) return 1; if (found) flags &= i_flags; else { flags = i_flags; found = true; } } if (ret_flags) *ret_flags = flags; return found; } int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr, DnsAnswerFlags *ret_flags) { DnsAnswerFlags flags = 0, i_flags; DnsResourceRecord *i; bool found = false; int r; assert(rr); DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) { r = dns_resource_record_equal(i, rr); if (r < 0) return r; if (r == 0) continue; if (!ret_flags) return 1; if (found) flags &= i_flags; else { flags = i_flags; found = true; } } if (ret_flags) *ret_flags = flags; return found; } int dns_answer_contains_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) { DnsAnswerFlags flags = 0, i_flags; DnsResourceRecord *i; bool found = false; int r; assert(key); DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) { r = dns_resource_key_equal(i->key, key); if (r < 0) return r; if (r == 0) continue; if (!ret_flags) return true; if (found) flags &= i_flags; else { flags = i_flags; found = true; } } if (ret_flags) *ret_flags = flags; return found; } int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) { DnsResourceRecord *i; DNS_ANSWER_FOREACH(i, a) { if (IN_SET(i->key->type, DNS_TYPE_NSEC, DNS_TYPE_NSEC3)) return true; } return false; } int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone) { DnsResourceRecord *rr; int r; /* Checks whether the specified answer contains at least one NSEC3 RR in the specified zone */ DNS_ANSWER_FOREACH(rr, answer) { const char *p; if (rr->key->type != DNS_TYPE_NSEC3) continue; p = DNS_RESOURCE_KEY_NAME(rr->key); r = dns_name_parent(&p); if (r < 0) return r; if (r == 0) continue; r = dns_name_equal(p, zone); if (r != 0) return r; } return false; } int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) { DnsResourceRecord *rr, *soa = NULL; DnsAnswerFlags rr_flags, soa_flags = 0; int r; assert(key); /* For a SOA record we can never find a matching SOA record */ if (key->type == DNS_TYPE_SOA) return 0; DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a) { r = dns_resource_key_match_soa(key, rr->key); if (r < 0) return r; if (r > 0) { if (soa) { r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(soa->key)); if (r < 0) return r; if (r > 0) continue; } soa = rr; soa_flags = rr_flags; } } if (!soa) return 0; if (ret) *ret = soa; if (flags) *flags = soa_flags; return 1; } int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) { DnsResourceRecord *rr; DnsAnswerFlags rr_flags; int r; assert(key); /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */ if (!dns_type_may_redirect(key->type)) return 0; DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a) { r = dns_resource_key_match_cname_or_dname(key, rr->key, NULL); if (r < 0) return r; if (r > 0) { if (ret) *ret = rr; if (flags) *flags = rr_flags; return 1; } } return 0; } int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret) { _cleanup_(dns_answer_unrefp) DnsAnswer *k = NULL; int r; assert(ret); if (dns_answer_size(a) <= 0) { *ret = dns_answer_ref(b); return 0; } if (dns_answer_size(b) <= 0) { *ret = dns_answer_ref(a); return 0; } k = dns_answer_new(a->n_rrs + b->n_rrs); if (!k) return -ENOMEM; r = dns_answer_add_raw_all(k, a); if (r < 0) return r; r = dns_answer_add_all(k, b); if (r < 0) return r; *ret = k; k = NULL; return 0; } int dns_answer_extend(DnsAnswer **a, DnsAnswer *b) { DnsAnswer *merged; int r; assert(a); r = dns_answer_merge(*a, b, &merged); if (r < 0) return r; dns_answer_unref(*a); *a = merged; return 0; } int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) { bool found = false, other = false; DnsResourceRecord *rr; unsigned i; int r; assert(a); assert(key); /* Remove all entries matching the specified key from *a */ DNS_ANSWER_FOREACH(rr, *a) { r = dns_resource_key_equal(rr->key, key); if (r < 0) return r; if (r > 0) found = true; else other = true; if (found && other) break; } if (!found) return 0; if (!other) { *a = dns_answer_unref(*a); /* Return NULL for the empty answer */ return 1; } if ((*a)->n_ref > 1) { _cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL; DnsAnswerFlags flags; int ifindex; copy = dns_answer_new((*a)->n_rrs); if (!copy) return -ENOMEM; DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a) { r = dns_resource_key_equal(rr->key, key); if (r < 0) return r; if (r > 0) continue; r = dns_answer_add_raw(copy, rr, ifindex, flags); if (r < 0) return r; } dns_answer_unref(*a); *a = copy; copy = NULL; return 1; } /* Only a single reference, edit in-place */ i = 0; for (;;) { if (i >= (*a)->n_rrs) break; r = dns_resource_key_equal((*a)->items[i].rr->key, key); if (r < 0) return r; if (r > 0) { /* Kill this entry */ dns_resource_record_unref((*a)->items[i].rr); memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1)); (*a)->n_rrs --; continue; } else /* Keep this entry */ i++; } return 1; } int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rm) { bool found = false, other = false; DnsResourceRecord *rr; unsigned i; int r; assert(a); assert(rm); /* Remove all entries matching the specified RR from *a */ DNS_ANSWER_FOREACH(rr, *a) { r = dns_resource_record_equal(rr, rm); if (r < 0) return r; if (r > 0) found = true; else other = true; if (found && other) break; } if (!found) return 0; if (!other) { *a = dns_answer_unref(*a); /* Return NULL for the empty answer */ return 1; } if ((*a)->n_ref > 1) { _cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL; DnsAnswerFlags flags; int ifindex; copy = dns_answer_new((*a)->n_rrs); if (!copy) return -ENOMEM; DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a) { r = dns_resource_record_equal(rr, rm); if (r < 0) return r; if (r > 0) continue; r = dns_answer_add_raw(copy, rr, ifindex, flags); if (r < 0) return r; } dns_answer_unref(*a); *a = copy; copy = NULL; return 1; } /* Only a single reference, edit in-place */ i = 0; for (;;) { if (i >= (*a)->n_rrs) break; r = dns_resource_record_equal((*a)->items[i].rr, rm); if (r < 0) return r; if (r > 0) { /* Kill this entry */ dns_resource_record_unref((*a)->items[i].rr); memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1)); (*a)->n_rrs --; continue; } else /* Keep this entry */ i++; } return 1; } int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags) { DnsResourceRecord *rr_source; int ifindex_source, r; DnsAnswerFlags flags_source; assert(a); assert(key); /* Copy all RRs matching the specified key from source into *a */ DNS_ANSWER_FOREACH_FULL(rr_source, ifindex_source, flags_source, source) { r = dns_resource_key_equal(rr_source->key, key); if (r < 0) return r; if (r == 0) continue; /* Make space for at least one entry */ r = dns_answer_reserve_or_clone(a, 1); if (r < 0) return r; r = dns_answer_add(*a, rr_source, ifindex_source, flags_source|or_flags); if (r < 0) return r; } return 0; } int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags) { int r; assert(to); assert(from); assert(key); r = dns_answer_copy_by_key(to, *from, key, or_flags); if (r < 0) return r; return dns_answer_remove_by_key(from, key); } void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local) { DnsAnswerItem *items; unsigned i, start, end; if (!a) return; if (a->n_rrs <= 1) return; start = 0; end = a->n_rrs-1; /* RFC 4795, Section 2.6 suggests we should order entries * depending on whether the sender is a link-local address. */ items = newa(DnsAnswerItem, a->n_rrs); for (i = 0; i < a->n_rrs; i++) { if (a->items[i].rr->key->class == DNS_CLASS_IN && ((a->items[i].rr->key->type == DNS_TYPE_A && in_addr_is_link_local(AF_INET, (union in_addr_union*) &a->items[i].rr->a.in_addr) != prefer_link_local) || (a->items[i].rr->key->type == DNS_TYPE_AAAA && in_addr_is_link_local(AF_INET6, (union in_addr_union*) &a->items[i].rr->aaaa.in6_addr) != prefer_link_local))) /* Order address records that are are not preferred to the end of the array */ items[end--] = a->items[i]; else /* Order all other records to the beginning of the array */ items[start++] = a->items[i]; } assert(start == end+1); memcpy(a->items, items, sizeof(DnsAnswerItem) * a->n_rrs); } int dns_answer_reserve(DnsAnswer **a, unsigned n_free) { DnsAnswer *n; assert(a); if (n_free <= 0) return 0; if (*a) { unsigned ns; if ((*a)->n_ref > 1) return -EBUSY; ns = (*a)->n_rrs + n_free; if ((*a)->n_allocated >= ns) return 0; /* Allocate more than we need */ ns *= 2; n = realloc(*a, offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * ns); if (!n) return -ENOMEM; n->n_allocated = ns; } else { n = dns_answer_new(n_free); if (!n) return -ENOMEM; } *a = n; return 0; } int dns_answer_reserve_or_clone(DnsAnswer **a, unsigned n_free) { _cleanup_(dns_answer_unrefp) DnsAnswer *n = NULL; int r; assert(a); /* Tries to extend the DnsAnswer object. And if that's not * possibly, since we are not the sole owner, then allocate a * new, appropriately sized one. Either way, after this call * the object will only have a single reference, and has room * for at least the specified number of RRs. */ r = dns_answer_reserve(a, n_free); if (r != -EBUSY) return r; assert(*a); n = dns_answer_new(((*a)->n_rrs + n_free) * 2); if (!n) return -ENOMEM; r = dns_answer_add_raw_all(n, *a); if (r < 0) return r; dns_answer_unref(*a); *a = n; n = NULL; return 0; } void dns_answer_dump(DnsAnswer *answer, FILE *f) { DnsResourceRecord *rr; DnsAnswerFlags flags; int ifindex; if (!f) f = stdout; DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer) { const char *t; fputc('\t', f); t = dns_resource_record_to_string(rr); if (!t) { log_oom(); continue; } fputs(t, f); if (ifindex != 0 || flags & (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE|DNS_ANSWER_SHARED_OWNER)) fputs("\t;", f); if (ifindex != 0) printf(" ifindex=%i", ifindex); if (flags & DNS_ANSWER_AUTHENTICATED) fputs(" authenticated", f); if (flags & DNS_ANSWER_CACHEABLE) fputs(" cachable", f); if (flags & DNS_ANSWER_SHARED_OWNER) fputs(" shared-owner", f); fputc('\n', f); } } bool dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname) { DnsResourceRecord *rr; int r; assert(cname); /* Checks whether the answer contains a DNAME record that indicates that the specified CNAME record is * synthesized from it */ if (cname->key->type != DNS_TYPE_CNAME) return 0; DNS_ANSWER_FOREACH(rr, a) { _cleanup_free_ char *n = NULL; if (rr->key->type != DNS_TYPE_DNAME) continue; if (rr->key->class != cname->key->class) continue; r = dns_name_change_suffix(cname->cname.name, rr->dname.name, DNS_RESOURCE_KEY_NAME(rr->key), &n); if (r < 0) return r; if (r == 0) continue; r = dns_name_equal(n, DNS_RESOURCE_KEY_NAME(cname->key)); if (r < 0) return r; if (r > 0) return 1; } return 0; } systemd-229/src/resolve/resolved-dns-answer.h000066400000000000000000000161761265713322000214150ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct DnsAnswer DnsAnswer; typedef struct DnsAnswerItem DnsAnswerItem; #include "macro.h" #include "resolved-dns-rr.h" /* A simple array of resource records. We keep track of the * originating ifindex for each RR where that makes sense, so that we * can qualify A and AAAA RRs referring to a local link with the * right ifindex. * * Note that we usually encode the the empty DnsAnswer object as a simple NULL. */ typedef enum DnsAnswerFlags { DNS_ANSWER_AUTHENTICATED = 1, /* Item has been authenticated */ DNS_ANSWER_CACHEABLE = 2, /* Item is subject to caching */ DNS_ANSWER_SHARED_OWNER = 4, /* For mDNS: RRset may be owner by multiple peers */ } DnsAnswerFlags; struct DnsAnswerItem { DnsResourceRecord *rr; int ifindex; DnsAnswerFlags flags; }; struct DnsAnswer { unsigned n_ref; unsigned n_rrs, n_allocated; DnsAnswerItem items[0]; }; DnsAnswer *dns_answer_new(unsigned n); DnsAnswer *dns_answer_ref(DnsAnswer *a); DnsAnswer *dns_answer_unref(DnsAnswer *a); int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags); int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags); int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl); int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *combined_flags); int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr, DnsAnswerFlags *combined_flags); int dns_answer_contains_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *combined_flags); int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a); int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone); int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags); int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags); int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret); int dns_answer_extend(DnsAnswer **a, DnsAnswer *b); void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local); int dns_answer_reserve(DnsAnswer **a, unsigned n_free); int dns_answer_reserve_or_clone(DnsAnswer **a, unsigned n_free); int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key); int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rr); int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags); int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags); bool dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname); static inline unsigned dns_answer_size(DnsAnswer *a) { return a ? a->n_rrs : 0; } void dns_answer_dump(DnsAnswer *answer, FILE *f); DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref); #define _DNS_ANSWER_FOREACH(q, kk, a) \ for (unsigned UNIQ_T(i, q) = ({ \ (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \ 0; \ }); \ (a) && (UNIQ_T(i, q) < (a)->n_rrs); \ UNIQ_T(i, q)++, (kk) = (UNIQ_T(i, q) < (a)->n_rrs ? (a)->items[UNIQ_T(i, q)].rr : NULL)) #define DNS_ANSWER_FOREACH(kk, a) _DNS_ANSWER_FOREACH(UNIQ, kk, a) #define _DNS_ANSWER_FOREACH_IFINDEX(q, kk, ifi, a) \ for (unsigned UNIQ_T(i, q) = ({ \ (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \ (ifi) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].ifindex : 0; \ 0; \ }); \ (a) && (UNIQ_T(i, q) < (a)->n_rrs); \ UNIQ_T(i, q)++, \ (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \ (ifi) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].ifindex : 0)) #define DNS_ANSWER_FOREACH_IFINDEX(kk, ifindex, a) _DNS_ANSWER_FOREACH_IFINDEX(UNIQ, kk, ifindex, a) #define _DNS_ANSWER_FOREACH_FLAGS(q, kk, fl, a) \ for (unsigned UNIQ_T(i, q) = ({ \ (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \ (fl) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].flags : 0; \ 0; \ }); \ (a) && (UNIQ_T(i, q) < (a)->n_rrs); \ UNIQ_T(i, q)++, \ (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \ (fl) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].flags : 0)) #define DNS_ANSWER_FOREACH_FLAGS(kk, flags, a) _DNS_ANSWER_FOREACH_FLAGS(UNIQ, kk, flags, a) #define _DNS_ANSWER_FOREACH_FULL(q, kk, ifi, fl, a) \ for (unsigned UNIQ_T(i, q) = ({ \ (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \ (ifi) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].ifindex : 0; \ (fl) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].flags : 0; \ 0; \ }); \ (a) && (UNIQ_T(i, q) < (a)->n_rrs); \ UNIQ_T(i, q)++, \ (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \ (ifi) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].ifindex : 0), \ (fl) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].flags : 0)) #define DNS_ANSWER_FOREACH_FULL(kk, ifindex, flags, a) _DNS_ANSWER_FOREACH_FULL(UNIQ, kk, ifindex, flags, a) systemd-229/src/resolve/resolved-dns-cache.c000066400000000000000000001026551265713322000211520ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "dns-domain.h" #include "resolved-dns-answer.h" #include "resolved-dns-cache.h" #include "resolved-dns-packet.h" #include "string-util.h" /* Never cache more than 4K entries. RFC 1536, Section 5 suggests to * leave DNS caches unbounded, but that's crazy. */ #define CACHE_MAX 4096 /* We never keep any item longer than 2h in our cache */ #define CACHE_TTL_MAX_USEC (2 * USEC_PER_HOUR) typedef enum DnsCacheItemType DnsCacheItemType; typedef struct DnsCacheItem DnsCacheItem; enum DnsCacheItemType { DNS_CACHE_POSITIVE, DNS_CACHE_NODATA, DNS_CACHE_NXDOMAIN, }; struct DnsCacheItem { DnsCacheItemType type; DnsResourceKey *key; DnsResourceRecord *rr; usec_t until; bool authenticated:1; bool shared_owner:1; int ifindex; int owner_family; union in_addr_union owner_address; unsigned prioq_idx; LIST_FIELDS(DnsCacheItem, by_key); }; static void dns_cache_item_free(DnsCacheItem *i) { if (!i) return; dns_resource_record_unref(i->rr); dns_resource_key_unref(i->key); free(i); } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsCacheItem*, dns_cache_item_free); static void dns_cache_item_unlink_and_free(DnsCache *c, DnsCacheItem *i) { DnsCacheItem *first; assert(c); if (!i) return; first = hashmap_get(c->by_key, i->key); LIST_REMOVE(by_key, first, i); if (first) assert_se(hashmap_replace(c->by_key, first->key, first) >= 0); else hashmap_remove(c->by_key, i->key); prioq_remove(c->by_expiry, i, &i->prioq_idx); dns_cache_item_free(i); } static bool dns_cache_remove_by_rr(DnsCache *c, DnsResourceRecord *rr) { DnsCacheItem *first, *i; int r; first = hashmap_get(c->by_key, rr->key); LIST_FOREACH(by_key, i, first) { r = dns_resource_record_equal(i->rr, rr); if (r < 0) return r; if (r > 0) { dns_cache_item_unlink_and_free(c, i); return true; } } return false; } static bool dns_cache_remove_by_key(DnsCache *c, DnsResourceKey *key) { DnsCacheItem *first, *i, *n; assert(c); assert(key); first = hashmap_remove(c->by_key, key); if (!first) return false; LIST_FOREACH_SAFE(by_key, i, n, first) { prioq_remove(c->by_expiry, i, &i->prioq_idx); dns_cache_item_free(i); } return true; } void dns_cache_flush(DnsCache *c) { DnsResourceKey *key; assert(c); while ((key = hashmap_first_key(c->by_key))) dns_cache_remove_by_key(c, key); assert(hashmap_size(c->by_key) == 0); assert(prioq_size(c->by_expiry) == 0); c->by_key = hashmap_free(c->by_key); c->by_expiry = prioq_free(c->by_expiry); } static void dns_cache_make_space(DnsCache *c, unsigned add) { assert(c); if (add <= 0) return; /* Makes space for n new entries. Note that we actually allow * the cache to grow beyond CACHE_MAX, but only when we shall * add more RRs to the cache than CACHE_MAX at once. In that * case the cache will be emptied completely otherwise. */ for (;;) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; DnsCacheItem *i; if (prioq_size(c->by_expiry) <= 0) break; if (prioq_size(c->by_expiry) + add < CACHE_MAX) break; i = prioq_peek(c->by_expiry); assert(i); /* Take an extra reference to the key so that it * doesn't go away in the middle of the remove call */ key = dns_resource_key_ref(i->key); dns_cache_remove_by_key(c, key); } } void dns_cache_prune(DnsCache *c) { usec_t t = 0; assert(c); /* Remove all entries that are past their TTL */ for (;;) { DnsCacheItem *i; i = prioq_peek(c->by_expiry); if (!i) break; if (t <= 0) t = now(clock_boottime_or_monotonic()); if (i->until > t) break; /* Depending whether this is an mDNS shared entry * either remove only this one RR or the whole * RRset */ if (i->shared_owner) dns_cache_item_unlink_and_free(c, i); else { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; /* Take an extra reference to the key so that it * doesn't go away in the middle of the remove call */ key = dns_resource_key_ref(i->key); dns_cache_remove_by_key(c, key); } } } static int dns_cache_item_prioq_compare_func(const void *a, const void *b) { const DnsCacheItem *x = a, *y = b; if (x->until < y->until) return -1; if (x->until > y->until) return 1; return 0; } static int dns_cache_init(DnsCache *c) { int r; assert(c); r = prioq_ensure_allocated(&c->by_expiry, dns_cache_item_prioq_compare_func); if (r < 0) return r; r = hashmap_ensure_allocated(&c->by_key, &dns_resource_key_hash_ops); if (r < 0) return r; return r; } static int dns_cache_link_item(DnsCache *c, DnsCacheItem *i) { DnsCacheItem *first; int r; assert(c); assert(i); r = prioq_put(c->by_expiry, i, &i->prioq_idx); if (r < 0) return r; first = hashmap_get(c->by_key, i->key); if (first) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL; /* Keep a reference to the original key, while we manipulate the list. */ k = dns_resource_key_ref(first->key); /* Now, try to reduce the number of keys we keep */ dns_resource_key_reduce(&first->key, &i->key); if (first->rr) dns_resource_key_reduce(&first->rr->key, &i->key); if (i->rr) dns_resource_key_reduce(&i->rr->key, &i->key); LIST_PREPEND(by_key, first, i); assert_se(hashmap_replace(c->by_key, first->key, first) >= 0); } else { r = hashmap_put(c->by_key, i->key, i); if (r < 0) { prioq_remove(c->by_expiry, i, &i->prioq_idx); return r; } } return 0; } static DnsCacheItem* dns_cache_get(DnsCache *c, DnsResourceRecord *rr) { DnsCacheItem *i; assert(c); assert(rr); LIST_FOREACH(by_key, i, hashmap_get(c->by_key, rr->key)) if (i->rr && dns_resource_record_equal(i->rr, rr) > 0) return i; return NULL; } static usec_t calculate_until(DnsResourceRecord *rr, uint32_t nsec_ttl, usec_t timestamp, bool use_soa_minimum) { uint32_t ttl; usec_t u; assert(rr); ttl = MIN(rr->ttl, nsec_ttl); if (rr->key->type == DNS_TYPE_SOA && use_soa_minimum) { /* If this is a SOA RR, and it is requested, clamp to * the SOA's minimum field. This is used when we do * negative caching, to determine the TTL for the * negative caching entry. See RFC 2308, Section * 5. */ if (ttl > rr->soa.minimum) ttl = rr->soa.minimum; } u = ttl * USEC_PER_SEC; if (u > CACHE_TTL_MAX_USEC) u = CACHE_TTL_MAX_USEC; if (rr->expiry != USEC_INFINITY) { usec_t left; /* Make use of the DNSSEC RRSIG expiry info, if we * have it */ left = LESS_BY(rr->expiry, now(CLOCK_REALTIME)); if (u > left) u = left; } return timestamp + u; } static void dns_cache_item_update_positive( DnsCache *c, DnsCacheItem *i, DnsResourceRecord *rr, bool authenticated, bool shared_owner, usec_t timestamp, int ifindex, int owner_family, const union in_addr_union *owner_address) { assert(c); assert(i); assert(rr); assert(owner_address); i->type = DNS_CACHE_POSITIVE; if (!i->by_key_prev) /* We are the first item in the list, we need to * update the key used in the hashmap */ assert_se(hashmap_replace(c->by_key, rr->key, i) >= 0); dns_resource_record_ref(rr); dns_resource_record_unref(i->rr); i->rr = rr; dns_resource_key_unref(i->key); i->key = dns_resource_key_ref(rr->key); i->until = calculate_until(rr, (uint32_t) -1, timestamp, false); i->authenticated = authenticated; i->shared_owner = shared_owner; i->ifindex = ifindex; i->owner_family = owner_family; i->owner_address = *owner_address; prioq_reshuffle(c->by_expiry, i, &i->prioq_idx); } static int dns_cache_put_positive( DnsCache *c, DnsResourceRecord *rr, bool authenticated, bool shared_owner, usec_t timestamp, int ifindex, int owner_family, const union in_addr_union *owner_address) { _cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL; _cleanup_free_ char *key_str = NULL; DnsCacheItem *existing; int r, k; assert(c); assert(rr); assert(owner_address); /* Never cache pseudo RRs */ if (dns_class_is_pseudo(rr->key->class)) return 0; if (dns_type_is_pseudo(rr->key->type)) return 0; /* New TTL is 0? Delete this specific entry... */ if (rr->ttl <= 0) { k = dns_cache_remove_by_rr(c, rr); if (log_get_max_level() >= LOG_DEBUG) { r = dns_resource_key_to_string(rr->key, &key_str); if (r < 0) return r; if (k > 0) log_debug("Removed zero TTL entry from cache: %s", key_str); else log_debug("Not caching zero TTL cache entry: %s", key_str); } return 0; } /* Entry exists already? Update TTL, timestamp and owner*/ existing = dns_cache_get(c, rr); if (existing) { dns_cache_item_update_positive( c, existing, rr, authenticated, shared_owner, timestamp, ifindex, owner_family, owner_address); return 0; } /* Otherwise, add the new RR */ r = dns_cache_init(c); if (r < 0) return r; dns_cache_make_space(c, 1); i = new0(DnsCacheItem, 1); if (!i) return -ENOMEM; i->type = DNS_CACHE_POSITIVE; i->key = dns_resource_key_ref(rr->key); i->rr = dns_resource_record_ref(rr); i->until = calculate_until(rr, (uint32_t) -1, timestamp, false); i->authenticated = authenticated; i->shared_owner = shared_owner; i->ifindex = ifindex; i->owner_family = owner_family; i->owner_address = *owner_address; i->prioq_idx = PRIOQ_IDX_NULL; r = dns_cache_link_item(c, i); if (r < 0) return r; if (log_get_max_level() >= LOG_DEBUG) { r = dns_resource_key_to_string(i->key, &key_str); if (r < 0) return r; log_debug("Added positive cache entry for %s", key_str); } i = NULL; return 0; } static int dns_cache_put_negative( DnsCache *c, DnsResourceKey *key, int rcode, bool authenticated, uint32_t nsec_ttl, usec_t timestamp, DnsResourceRecord *soa, int owner_family, const union in_addr_union *owner_address) { _cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL; _cleanup_free_ char *key_str = NULL; int r; assert(c); assert(key); assert(soa); assert(owner_address); /* Never cache pseudo RR keys. DNS_TYPE_ANY is particularly * important to filter out as we use this as a pseudo-type for * NXDOMAIN entries */ if (dns_class_is_pseudo(key->class)) return 0; if (dns_type_is_pseudo(key->type)) return 0; if (nsec_ttl <= 0 || soa->soa.minimum <= 0 || soa->ttl <= 0) { if (log_get_max_level() >= LOG_DEBUG) { r = dns_resource_key_to_string(key, &key_str); if (r < 0) return r; log_debug("Not caching negative entry with zero SOA/NSEC/NSEC3 TTL: %s", key_str); } return 0; } if (!IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN)) return 0; r = dns_cache_init(c); if (r < 0) return r; dns_cache_make_space(c, 1); i = new0(DnsCacheItem, 1); if (!i) return -ENOMEM; i->type = rcode == DNS_RCODE_SUCCESS ? DNS_CACHE_NODATA : DNS_CACHE_NXDOMAIN; i->until = calculate_until(soa, nsec_ttl, timestamp, true); i->authenticated = authenticated; i->owner_family = owner_family; i->owner_address = *owner_address; i->prioq_idx = PRIOQ_IDX_NULL; if (i->type == DNS_CACHE_NXDOMAIN) { /* NXDOMAIN entries should apply equally to all types, so we use ANY as * a pseudo type for this purpose here. */ i->key = dns_resource_key_new(key->class, DNS_TYPE_ANY, DNS_RESOURCE_KEY_NAME(key)); if (!i->key) return -ENOMEM; /* Make sure to remove any previous entry for this * specific ANY key. (For non-ANY keys the cache data * is already cleared by the caller.) Note that we * don't bother removing positive or NODATA cache * items in this case, because it would either be slow * or require explicit indexing by name */ dns_cache_remove_by_key(c, key); } else i->key = dns_resource_key_ref(key); r = dns_cache_link_item(c, i); if (r < 0) return r; if (log_get_max_level() >= LOG_DEBUG) { r = dns_resource_key_to_string(i->key, &key_str); if (r < 0) return r; log_debug("Added %s cache entry for %s", i->type == DNS_CACHE_NODATA ? "NODATA" : "NXDOMAIN", key_str); } i = NULL; return 0; } static void dns_cache_remove_previous( DnsCache *c, DnsResourceKey *key, DnsAnswer *answer) { DnsResourceRecord *rr; DnsAnswerFlags flags; assert(c); /* First, if we were passed a key (i.e. on LLMNR/DNS, but * not on mDNS), delete all matching old RRs, so that we only * keep complete by_key in place. */ if (key) dns_cache_remove_by_key(c, key); /* Second, flush all entries matching the answer, unless this * is an RR that is explicitly marked to be "shared" between * peers (i.e. mDNS RRs without the flush-cache bit set). */ DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { if ((flags & DNS_ANSWER_CACHEABLE) == 0) continue; if (flags & DNS_ANSWER_SHARED_OWNER) continue; dns_cache_remove_by_key(c, rr->key); } } static bool rr_eligible(DnsResourceRecord *rr) { assert(rr); /* When we see an NSEC/NSEC3 RR, we'll only cache it if it is from the lower zone, not the upper zone, since * that's where the interesting bits are (with exception of DS RRs). Of course, this way we cannot derive DS * existence from any cached NSEC/NSEC3, but that should be fine. */ switch (rr->key->type) { case DNS_TYPE_NSEC: return !bitmap_isset(rr->nsec.types, DNS_TYPE_NS) || bitmap_isset(rr->nsec.types, DNS_TYPE_SOA); case DNS_TYPE_NSEC3: return !bitmap_isset(rr->nsec3.types, DNS_TYPE_NS) || bitmap_isset(rr->nsec3.types, DNS_TYPE_SOA); default: return true; } } int dns_cache_put( DnsCache *c, DnsResourceKey *key, int rcode, DnsAnswer *answer, bool authenticated, uint32_t nsec_ttl, usec_t timestamp, int owner_family, const union in_addr_union *owner_address) { DnsResourceRecord *soa = NULL, *rr; DnsAnswerFlags flags; unsigned cache_keys; int r, ifindex; assert(c); assert(owner_address); dns_cache_remove_previous(c, key, answer); if (dns_answer_size(answer) <= 0) { if (log_get_max_level() >= LOG_DEBUG) { _cleanup_free_ char *key_str = NULL; r = dns_resource_key_to_string(key, &key_str); if (r < 0) return r; log_debug("Not caching negative entry without a SOA record: %s", key_str); } return 0; } /* We only care for positive replies and NXDOMAINs, on all * other replies we will simply flush the respective entries, * and that's it */ if (!IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN)) return 0; cache_keys = dns_answer_size(answer); if (key) cache_keys ++; /* Make some space for our new entries */ dns_cache_make_space(c, cache_keys); if (timestamp <= 0) timestamp = now(clock_boottime_or_monotonic()); /* Second, add in positive entries for all contained RRs */ DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer) { if ((flags & DNS_ANSWER_CACHEABLE) == 0) continue; r = rr_eligible(rr); if (r < 0) return r; if (r == 0) continue; r = dns_cache_put_positive( c, rr, flags & DNS_ANSWER_AUTHENTICATED, flags & DNS_ANSWER_SHARED_OWNER, timestamp, ifindex, owner_family, owner_address); if (r < 0) goto fail; } if (!key) /* mDNS doesn't know negative caching, really */ return 0; /* Third, add in negative entries if the key has no RR */ r = dns_answer_match_key(answer, key, NULL); if (r < 0) goto fail; if (r > 0) return 0; /* But not if it has a matching CNAME/DNAME (the negative * caching will be done on the canonical name, not on the * alias) */ r = dns_answer_find_cname_or_dname(answer, key, NULL, NULL); if (r < 0) goto fail; if (r > 0) return 0; /* See https://tools.ietf.org/html/rfc2308, which say that a * matching SOA record in the packet is used to to enable * negative caching. */ r = dns_answer_find_soa(answer, key, &soa, &flags); if (r < 0) goto fail; if (r == 0) return 0; /* Refuse using the SOA data if it is unsigned, but the key is * signed */ if (authenticated && (flags & DNS_ANSWER_AUTHENTICATED) == 0) return 0; r = dns_cache_put_negative( c, key, rcode, authenticated, nsec_ttl, timestamp, soa, owner_family, owner_address); if (r < 0) goto fail; return 0; fail: /* Adding all RRs failed. Let's clean up what we already * added, just in case */ if (key) dns_cache_remove_by_key(c, key); DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { if ((flags & DNS_ANSWER_CACHEABLE) == 0) continue; dns_cache_remove_by_key(c, rr->key); } return r; } static DnsCacheItem *dns_cache_get_by_key_follow_cname_dname_nsec(DnsCache *c, DnsResourceKey *k) { DnsCacheItem *i; const char *n; int r; assert(c); assert(k); /* If we hit some OOM error, or suchlike, we don't care too * much, after all this is just a cache */ i = hashmap_get(c->by_key, k); if (i) return i; n = DNS_RESOURCE_KEY_NAME(k); /* Check if we have an NXDOMAIN cache item for the name, notice that we use * the pseudo-type ANY for NXDOMAIN cache items. */ i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_ANY, n)); if (i && i->type == DNS_CACHE_NXDOMAIN) return i; if (dns_type_may_redirect(k->type)) { /* Check if we have a CNAME record instead */ i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_CNAME, n)); if (i) return i; /* OK, let's look for cached DNAME records. */ for (;;) { if (isempty(n)) return NULL; i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_DNAME, n)); if (i) return i; /* Jump one label ahead */ r = dns_name_parent(&n); if (r <= 0) return NULL; } } if (k->type != DNS_TYPE_NSEC) { /* Check if we have an NSEC record instead for the name. */ i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_NSEC, n)); if (i) return i; } return NULL; } int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **ret, bool *authenticated) { _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; unsigned n = 0; int r; bool nxdomain = false; _cleanup_free_ char *key_str = NULL; DnsCacheItem *j, *first, *nsec = NULL; bool have_authenticated = false, have_non_authenticated = false; assert(c); assert(key); assert(rcode); assert(ret); assert(authenticated); if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) { /* If we have ANY lookups we don't use the cache, so * that the caller refreshes via the network. */ if (log_get_max_level() >= LOG_DEBUG) { r = dns_resource_key_to_string(key, &key_str); if (r < 0) return r; log_debug("Ignoring cache for ANY lookup: %s", key_str); } c->n_miss++; *ret = NULL; *rcode = DNS_RCODE_SUCCESS; return 0; } first = dns_cache_get_by_key_follow_cname_dname_nsec(c, key); if (!first) { /* If one question cannot be answered we need to refresh */ if (log_get_max_level() >= LOG_DEBUG) { r = dns_resource_key_to_string(key, &key_str); if (r < 0) return r; log_debug("Cache miss for %s", key_str); } c->n_miss++; *ret = NULL; *rcode = DNS_RCODE_SUCCESS; return 0; } LIST_FOREACH(by_key, j, first) { if (j->rr) { if (j->rr->key->type == DNS_TYPE_NSEC) nsec = j; n++; } else if (j->type == DNS_CACHE_NXDOMAIN) nxdomain = true; if (j->authenticated) have_authenticated = true; else have_non_authenticated = true; } if (nsec && !IN_SET(key->type, DNS_TYPE_NSEC, DNS_TYPE_DS)) { /* Note that we won't derive information for DS RRs from an NSEC, because we only cache NSEC RRs from * the lower-zone of a zone cut, but the DS RRs are on the upper zone. */ if (log_get_max_level() >= LOG_DEBUG) { r = dns_resource_key_to_string(key, &key_str); if (r < 0) return r; log_debug("NSEC NODATA cache hit for %s", key_str); } /* We only found an NSEC record that matches our name. * If it says the type doesn't exist report * NODATA. Otherwise report a cache miss. */ *ret = NULL; *rcode = DNS_RCODE_SUCCESS; *authenticated = nsec->authenticated; if (!bitmap_isset(nsec->rr->nsec.types, key->type) && !bitmap_isset(nsec->rr->nsec.types, DNS_TYPE_CNAME) && !bitmap_isset(nsec->rr->nsec.types, DNS_TYPE_DNAME)) { c->n_hit++; return 1; } c->n_miss++; return 0; } if (log_get_max_level() >= LOG_DEBUG) { r = dns_resource_key_to_string(key, &key_str); if (r < 0) return r; log_debug("%s cache hit for %s", n > 0 ? "Positive" : nxdomain ? "NXDOMAIN" : "NODATA", key_str); } if (n <= 0) { c->n_hit++; *ret = NULL; *rcode = nxdomain ? DNS_RCODE_NXDOMAIN : DNS_RCODE_SUCCESS; *authenticated = have_authenticated && !have_non_authenticated; return 1; } answer = dns_answer_new(n); if (!answer) return -ENOMEM; LIST_FOREACH(by_key, j, first) { if (!j->rr) continue; r = dns_answer_add(answer, j->rr, j->ifindex, j->authenticated ? DNS_ANSWER_AUTHENTICATED : 0); if (r < 0) return r; } c->n_hit++; *ret = answer; *rcode = DNS_RCODE_SUCCESS; *authenticated = have_authenticated && !have_non_authenticated; answer = NULL; return n; } int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address) { DnsCacheItem *i, *first; bool same_owner = true; assert(cache); assert(rr); dns_cache_prune(cache); /* See if there's a cache entry for the same key. If there * isn't there's no conflict */ first = hashmap_get(cache->by_key, rr->key); if (!first) return 0; /* See if the RR key is owned by the same owner, if so, there * isn't a conflict either */ LIST_FOREACH(by_key, i, first) { if (i->owner_family != owner_family || !in_addr_equal(owner_family, &i->owner_address, owner_address)) { same_owner = false; break; } } if (same_owner) return 0; /* See if there's the exact same RR in the cache. If yes, then * there's no conflict. */ if (dns_cache_get(cache, rr)) return 0; /* There's a conflict */ return 1; } int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) { unsigned ancount = 0; Iterator iterator; DnsCacheItem *i; int r; assert(cache); assert(p); HASHMAP_FOREACH(i, cache->by_key, iterator) { DnsCacheItem *j; LIST_FOREACH(by_key, j, i) { if (!j->rr) continue; if (!j->shared_owner) continue; r = dns_packet_append_rr(p, j->rr, NULL, NULL); if (r == -EMSGSIZE && p->protocol == DNS_PROTOCOL_MDNS) { /* For mDNS, if we're unable to stuff all known answers into the given packet, * allocate a new one, push the RR into that one and link it to the current one. */ DNS_PACKET_HEADER(p)->ancount = htobe16(ancount); ancount = 0; r = dns_packet_new_query(&p->more, p->protocol, 0, true); if (r < 0) return r; /* continue with new packet */ p = p->more; r = dns_packet_append_rr(p, j->rr, NULL, NULL); } if (r < 0) return r; ancount ++; } } DNS_PACKET_HEADER(p)->ancount = htobe16(ancount); return 0; } void dns_cache_dump(DnsCache *cache, FILE *f) { Iterator iterator; DnsCacheItem *i; int r; if (!cache) return; if (!f) f = stdout; HASHMAP_FOREACH(i, cache->by_key, iterator) { DnsCacheItem *j; LIST_FOREACH(by_key, j, i) { fputc('\t', f); if (j->rr) { const char *t; t = dns_resource_record_to_string(j->rr); if (!t) { log_oom(); continue; } fputs(t, f); fputc('\n', f); } else { _cleanup_free_ char *z = NULL; r = dns_resource_key_to_string(j->key, &z); if (r < 0) { log_oom(); continue; } fputs(z, f); fputs(" -- ", f); fputs(j->type == DNS_CACHE_NODATA ? "NODATA" : "NXDOMAIN", f); fputc('\n', f); } } } } bool dns_cache_is_empty(DnsCache *cache) { if (!cache) return true; return hashmap_isempty(cache->by_key); } unsigned dns_cache_size(DnsCache *cache) { if (!cache) return 0; return hashmap_size(cache->by_key); } systemd-229/src/resolve/resolved-dns-cache.h000066400000000000000000000034111265713322000211450ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "hashmap.h" #include "list.h" #include "prioq.h" #include "time-util.h" typedef struct DnsCache { Hashmap *by_key; Prioq *by_expiry; unsigned n_hit; unsigned n_miss; } DnsCache; #include "resolved-dns-answer.h" #include "resolved-dns-packet.h" #include "resolved-dns-question.h" #include "resolved-dns-rr.h" void dns_cache_flush(DnsCache *c); void dns_cache_prune(DnsCache *c); int dns_cache_put(DnsCache *c, DnsResourceKey *key, int rcode, DnsAnswer *answer, bool authenticated, uint32_t nsec_ttl, usec_t timestamp, int owner_family, const union in_addr_union *owner_address); int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **answer, bool *authenticated); int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address); void dns_cache_dump(DnsCache *cache, FILE *f); bool dns_cache_is_empty(DnsCache *cache); unsigned dns_cache_size(DnsCache *cache); int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p); systemd-229/src/resolve/resolved-dns-dnssec.c000066400000000000000000002255041265713322000213650ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #ifdef HAVE_GCRYPT #include #endif #include "alloc-util.h" #include "dns-domain.h" #include "hexdecoct.h" #include "resolved-dns-dnssec.h" #include "resolved-dns-packet.h" #include "string-table.h" #define VERIFY_RRS_MAX 256 #define MAX_KEY_SIZE (32*1024) /* Permit a maximum clock skew of 1h 10min. This should be enough to deal with DST confusion */ #define SKEW_MAX (1*USEC_PER_HOUR + 10*USEC_PER_MINUTE) /* Maximum number of NSEC3 iterations we'll do. RFC5155 says 2500 shall be the maximum useful value */ #define NSEC3_ITERATIONS_MAX 2500 /* * The DNSSEC Chain of trust: * * Normal RRs are protected via RRSIG RRs in combination with DNSKEY RRs, all in the same zone * DNSKEY RRs are either protected like normal RRs, or via a DS from a zone "higher" up the tree * DS RRs are protected like normal RRs * * Example chain: * Normal RR → RRSIG/DNSKEY+ → DS → RRSIG/DNSKEY+ → DS → ... → DS → RRSIG/DNSKEY+ → DS */ uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke) { const uint8_t *p; uint32_t sum, f; size_t i; /* The algorithm from RFC 4034, Appendix B. */ assert(dnskey); assert(dnskey->key->type == DNS_TYPE_DNSKEY); f = (uint32_t) dnskey->dnskey.flags; if (mask_revoke) f &= ~DNSKEY_FLAG_REVOKE; sum = f + ((((uint32_t) dnskey->dnskey.protocol) << 8) + (uint32_t) dnskey->dnskey.algorithm); p = dnskey->dnskey.key; for (i = 0; i < dnskey->dnskey.key_size; i++) sum += (i & 1) == 0 ? (uint32_t) p[i] << 8 : (uint32_t) p[i]; sum += (sum >> 16) & UINT32_C(0xFFFF); return sum & UINT32_C(0xFFFF); } int dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max) { size_t c = 0; int r; /* Converts the specified hostname into DNSSEC canonicalized * form. */ if (buffer_max < 2) return -ENOBUFS; for (;;) { r = dns_label_unescape(&n, buffer, buffer_max); if (r < 0) return r; if (r == 0) break; if (buffer_max < (size_t) r + 2) return -ENOBUFS; /* The DNSSEC canonical form is not clear on what to * do with dots appearing in labels, the way DNS-SD * does it. Refuse it for now. */ if (memchr(buffer, '.', r)) return -EINVAL; ascii_strlower_n(buffer, (size_t) r); buffer[r] = '.'; buffer += r + 1; c += r + 1; buffer_max -= r + 1; } if (c <= 0) { /* Not even a single label: this is the root domain name */ assert(buffer_max > 2); buffer[0] = '.'; buffer[1] = 0; return 1; } return (int) c; } #ifdef HAVE_GCRYPT static void initialize_libgcrypt(void) { const char *p; if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P)) return; p = gcry_check_version("1.4.5"); assert(p); gcry_control(GCRYCTL_DISABLE_SECMEM); gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); } static int rr_compare(const void *a, const void *b) { DnsResourceRecord **x = (DnsResourceRecord**) a, **y = (DnsResourceRecord**) b; size_t m; int r; /* Let's order the RRs according to RFC 4034, Section 6.3 */ assert(x); assert(*x); assert((*x)->wire_format); assert(y); assert(*y); assert((*y)->wire_format); m = MIN(DNS_RESOURCE_RECORD_RDATA_SIZE(*x), DNS_RESOURCE_RECORD_RDATA_SIZE(*y)); r = memcmp(DNS_RESOURCE_RECORD_RDATA(*x), DNS_RESOURCE_RECORD_RDATA(*y), m); if (r != 0) return r; if (DNS_RESOURCE_RECORD_RDATA_SIZE(*x) < DNS_RESOURCE_RECORD_RDATA_SIZE(*y)) return -1; else if (DNS_RESOURCE_RECORD_RDATA_SIZE(*x) > DNS_RESOURCE_RECORD_RDATA_SIZE(*y)) return 1; return 0; } static int dnssec_rsa_verify_raw( const char *hash_algorithm, const void *signature, size_t signature_size, const void *data, size_t data_size, const void *exponent, size_t exponent_size, const void *modulus, size_t modulus_size) { gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL; gcry_mpi_t n = NULL, e = NULL, s = NULL; gcry_error_t ge; int r; assert(hash_algorithm); ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature, signature_size, NULL); if (ge != 0) { r = -EIO; goto finish; } ge = gcry_mpi_scan(&e, GCRYMPI_FMT_USG, exponent, exponent_size, NULL); if (ge != 0) { r = -EIO; goto finish; } ge = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, modulus, modulus_size, NULL); if (ge != 0) { r = -EIO; goto finish; } ge = gcry_sexp_build(&signature_sexp, NULL, "(sig-val (rsa (s %m)))", s); if (ge != 0) { r = -EIO; goto finish; } ge = gcry_sexp_build(&data_sexp, NULL, "(data (flags pkcs1) (hash %s %b))", hash_algorithm, (int) data_size, data); if (ge != 0) { r = -EIO; goto finish; } ge = gcry_sexp_build(&public_key_sexp, NULL, "(public-key (rsa (n %m) (e %m)))", n, e); if (ge != 0) { r = -EIO; goto finish; } ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp); if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE) r = 0; else if (ge != 0) { log_debug("RSA signature check failed: %s", gpg_strerror(ge)); r = -EIO; } else r = 1; finish: if (e) gcry_mpi_release(e); if (n) gcry_mpi_release(n); if (s) gcry_mpi_release(s); if (public_key_sexp) gcry_sexp_release(public_key_sexp); if (signature_sexp) gcry_sexp_release(signature_sexp); if (data_sexp) gcry_sexp_release(data_sexp); return r; } static int dnssec_rsa_verify( const char *hash_algorithm, const void *hash, size_t hash_size, DnsResourceRecord *rrsig, DnsResourceRecord *dnskey) { size_t exponent_size, modulus_size; void *exponent, *modulus; assert(hash_algorithm); assert(hash); assert(hash_size > 0); assert(rrsig); assert(dnskey); if (*(uint8_t*) dnskey->dnskey.key == 0) { /* exponent is > 255 bytes long */ exponent = (uint8_t*) dnskey->dnskey.key + 3; exponent_size = ((size_t) (((uint8_t*) dnskey->dnskey.key)[1]) << 8) | ((size_t) ((uint8_t*) dnskey->dnskey.key)[2]); if (exponent_size < 256) return -EINVAL; if (3 + exponent_size >= dnskey->dnskey.key_size) return -EINVAL; modulus = (uint8_t*) dnskey->dnskey.key + 3 + exponent_size; modulus_size = dnskey->dnskey.key_size - 3 - exponent_size; } else { /* exponent is <= 255 bytes long */ exponent = (uint8_t*) dnskey->dnskey.key + 1; exponent_size = (size_t) ((uint8_t*) dnskey->dnskey.key)[0]; if (exponent_size <= 0) return -EINVAL; if (1 + exponent_size >= dnskey->dnskey.key_size) return -EINVAL; modulus = (uint8_t*) dnskey->dnskey.key + 1 + exponent_size; modulus_size = dnskey->dnskey.key_size - 1 - exponent_size; } return dnssec_rsa_verify_raw( hash_algorithm, rrsig->rrsig.signature, rrsig->rrsig.signature_size, hash, hash_size, exponent, exponent_size, modulus, modulus_size); } static int dnssec_ecdsa_verify_raw( const char *hash_algorithm, const char *curve, const void *signature_r, size_t signature_r_size, const void *signature_s, size_t signature_s_size, const void *data, size_t data_size, const void *key, size_t key_size) { gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL; gcry_mpi_t q = NULL, r = NULL, s = NULL; gcry_error_t ge; int k; assert(hash_algorithm); ge = gcry_mpi_scan(&r, GCRYMPI_FMT_USG, signature_r, signature_r_size, NULL); if (ge != 0) { k = -EIO; goto finish; } ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature_s, signature_s_size, NULL); if (ge != 0) { k = -EIO; goto finish; } ge = gcry_mpi_scan(&q, GCRYMPI_FMT_USG, key, key_size, NULL); if (ge != 0) { k = -EIO; goto finish; } ge = gcry_sexp_build(&signature_sexp, NULL, "(sig-val (ecdsa (r %m) (s %m)))", r, s); if (ge != 0) { k = -EIO; goto finish; } ge = gcry_sexp_build(&data_sexp, NULL, "(data (flags rfc6979) (hash %s %b))", hash_algorithm, (int) data_size, data); if (ge != 0) { k = -EIO; goto finish; } ge = gcry_sexp_build(&public_key_sexp, NULL, "(public-key (ecc (curve %s) (q %m)))", curve, q); if (ge != 0) { k = -EIO; goto finish; } ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp); if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE) k = 0; else if (ge != 0) { log_debug("ECDSA signature check failed: %s", gpg_strerror(ge)); k = -EIO; } else k = 1; finish: if (r) gcry_mpi_release(r); if (s) gcry_mpi_release(s); if (q) gcry_mpi_release(q); if (public_key_sexp) gcry_sexp_release(public_key_sexp); if (signature_sexp) gcry_sexp_release(signature_sexp); if (data_sexp) gcry_sexp_release(data_sexp); return k; } static int dnssec_ecdsa_verify( const char *hash_algorithm, int algorithm, const void *hash, size_t hash_size, DnsResourceRecord *rrsig, DnsResourceRecord *dnskey) { const char *curve; size_t key_size; uint8_t *q; assert(hash); assert(hash_size); assert(rrsig); assert(dnskey); if (algorithm == DNSSEC_ALGORITHM_ECDSAP256SHA256) { key_size = 32; curve = "NIST P-256"; } else if (algorithm == DNSSEC_ALGORITHM_ECDSAP384SHA384) { key_size = 48; curve = "NIST P-384"; } else return -EOPNOTSUPP; if (dnskey->dnskey.key_size != key_size * 2) return -EINVAL; if (rrsig->rrsig.signature_size != key_size * 2) return -EINVAL; q = alloca(key_size*2 + 1); q[0] = 0x04; /* Prepend 0x04 to indicate an uncompressed key */ memcpy(q+1, dnskey->dnskey.key, key_size*2); return dnssec_ecdsa_verify_raw( hash_algorithm, curve, rrsig->rrsig.signature, key_size, (uint8_t*) rrsig->rrsig.signature + key_size, key_size, hash, hash_size, q, key_size*2+1); } static void md_add_uint8(gcry_md_hd_t md, uint8_t v) { gcry_md_write(md, &v, sizeof(v)); } static void md_add_uint16(gcry_md_hd_t md, uint16_t v) { v = htobe16(v); gcry_md_write(md, &v, sizeof(v)); } static void md_add_uint32(gcry_md_hd_t md, uint32_t v) { v = htobe32(v); gcry_md_write(md, &v, sizeof(v)); } static int dnssec_rrsig_prepare(DnsResourceRecord *rrsig) { int n_key_labels, n_signer_labels; const char *name; int r; /* Checks whether the specified RRSIG RR is somewhat valid, and initializes the .n_skip_labels_source and * .n_skip_labels_signer fields so that we can use them later on. */ assert(rrsig); assert(rrsig->key->type == DNS_TYPE_RRSIG); /* Check if this RRSIG RR is already prepared */ if (rrsig->n_skip_labels_source != (unsigned) -1) return 0; if (rrsig->rrsig.inception > rrsig->rrsig.expiration) return -EINVAL; name = DNS_RESOURCE_KEY_NAME(rrsig->key); n_key_labels = dns_name_count_labels(name); if (n_key_labels < 0) return n_key_labels; if (rrsig->rrsig.labels > n_key_labels) return -EINVAL; n_signer_labels = dns_name_count_labels(rrsig->rrsig.signer); if (n_signer_labels < 0) return n_signer_labels; if (n_signer_labels > rrsig->rrsig.labels) return -EINVAL; r = dns_name_skip(name, n_key_labels - n_signer_labels, &name); if (r < 0) return r; if (r == 0) return -EINVAL; /* Check if the signer is really a suffix of us */ r = dns_name_equal(name, rrsig->rrsig.signer); if (r < 0) return r; if (r == 0) return -EINVAL; rrsig->n_skip_labels_source = n_key_labels - rrsig->rrsig.labels; rrsig->n_skip_labels_signer = n_key_labels - n_signer_labels; return 0; } static int dnssec_rrsig_expired(DnsResourceRecord *rrsig, usec_t realtime) { usec_t expiration, inception, skew; assert(rrsig); assert(rrsig->key->type == DNS_TYPE_RRSIG); if (realtime == USEC_INFINITY) realtime = now(CLOCK_REALTIME); expiration = rrsig->rrsig.expiration * USEC_PER_SEC; inception = rrsig->rrsig.inception * USEC_PER_SEC; /* Consider inverted validity intervals as expired */ if (inception > expiration) return true; /* Permit a certain amount of clock skew of 10% of the valid * time range. This takes inspiration from unbound's * resolver. */ skew = (expiration - inception) / 10; if (skew > SKEW_MAX) skew = SKEW_MAX; if (inception < skew) inception = 0; else inception -= skew; if (expiration + skew < expiration) expiration = USEC_INFINITY; else expiration += skew; return realtime < inception || realtime > expiration; } static int algorithm_to_gcrypt_md(uint8_t algorithm) { /* Translates a DNSSEC signature algorithm into a gcrypt * digest identifier. * * Note that we implement all algorithms listed as "Must * implement" and "Recommended to Implement" in RFC6944. We * don't implement any algorithms that are listed as * "Optional" or "Must Not Implement". Specifically, we do not * implement RSAMD5, DSASHA1, DH, DSA-NSEC3-SHA1, and * GOST-ECC. */ switch (algorithm) { case DNSSEC_ALGORITHM_RSASHA1: case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1: return GCRY_MD_SHA1; case DNSSEC_ALGORITHM_RSASHA256: case DNSSEC_ALGORITHM_ECDSAP256SHA256: return GCRY_MD_SHA256; case DNSSEC_ALGORITHM_ECDSAP384SHA384: return GCRY_MD_SHA384; case DNSSEC_ALGORITHM_RSASHA512: return GCRY_MD_SHA512; default: return -EOPNOTSUPP; } } static void dnssec_fix_rrset_ttl( DnsResourceRecord *list[], unsigned n, DnsResourceRecord *rrsig, usec_t realtime) { unsigned k; assert(list); assert(n > 0); assert(rrsig); for (k = 0; k < n; k++) { DnsResourceRecord *rr = list[k]; /* Pick the TTL as the minimum of the RR's TTL, the * RR's original TTL according to the RRSIG and the * RRSIG's own TTL, see RFC 4035, Section 5.3.3 */ rr->ttl = MIN3(rr->ttl, rrsig->rrsig.original_ttl, rrsig->ttl); rr->expiry = rrsig->rrsig.expiration * USEC_PER_SEC; /* Copy over information about the signer and wildcard source of synthesis */ rr->n_skip_labels_source = rrsig->n_skip_labels_source; rr->n_skip_labels_signer = rrsig->n_skip_labels_signer; } rrsig->expiry = rrsig->rrsig.expiration * USEC_PER_SEC; } int dnssec_verify_rrset( DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, usec_t realtime, DnssecResult *result) { uint8_t wire_format_name[DNS_WIRE_FOMAT_HOSTNAME_MAX]; DnsResourceRecord **list, *rr; const char *source, *name; gcry_md_hd_t md = NULL; int r, md_algorithm; size_t k, n = 0; size_t hash_size; void *hash; bool wildcard; assert(key); assert(rrsig); assert(dnskey); assert(result); assert(rrsig->key->type == DNS_TYPE_RRSIG); assert(dnskey->key->type == DNS_TYPE_DNSKEY); /* Verifies the the RRSet matching the specified "key" in "a", * using the signature "rrsig" and the key "dnskey". It's * assumed the RRSIG and DNSKEY match. */ md_algorithm = algorithm_to_gcrypt_md(rrsig->rrsig.algorithm); if (md_algorithm == -EOPNOTSUPP) { *result = DNSSEC_UNSUPPORTED_ALGORITHM; return 0; } if (md_algorithm < 0) return md_algorithm; r = dnssec_rrsig_prepare(rrsig); if (r == -EINVAL) { *result = DNSSEC_INVALID; return r; } if (r < 0) return r; r = dnssec_rrsig_expired(rrsig, realtime); if (r < 0) return r; if (r > 0) { *result = DNSSEC_SIGNATURE_EXPIRED; return 0; } name = DNS_RESOURCE_KEY_NAME(key); /* Some keys may only appear signed in the zone apex, and are invalid anywhere else. (SOA, NS...) */ if (dns_type_apex_only(rrsig->rrsig.type_covered)) { r = dns_name_equal(rrsig->rrsig.signer, name); if (r < 0) return r; if (r == 0) { *result = DNSSEC_INVALID; return 0; } } /* OTOH DS RRs may not appear in the zone apex, but are valid everywhere else. */ if (rrsig->rrsig.type_covered == DNS_TYPE_DS) { r = dns_name_equal(rrsig->rrsig.signer, name); if (r < 0) return r; if (r > 0) { *result = DNSSEC_INVALID; return 0; } } /* Determine the "Source of Synthesis" and whether this is a wildcard RRSIG */ r = dns_name_suffix(name, rrsig->rrsig.labels, &source); if (r < 0) return r; if (r > 0 && !dns_type_may_wildcard(rrsig->rrsig.type_covered)) { /* We refuse to validate NSEC3 or SOA RRs that are synthesized from wildcards */ *result = DNSSEC_INVALID; return 0; } if (r == 1) { /* If we stripped a single label, then let's see if that maybe was "*". If so, we are not really * synthesized from a wildcard, we are the wildcard itself. Treat that like a normal name. */ r = dns_name_startswith(name, "*"); if (r < 0) return r; if (r > 0) source = name; wildcard = r == 0; } else wildcard = r > 0; /* Collect all relevant RRs in a single array, so that we can look at the RRset */ list = newa(DnsResourceRecord *, dns_answer_size(a)); DNS_ANSWER_FOREACH(rr, a) { r = dns_resource_key_equal(key, rr->key); if (r < 0) return r; if (r == 0) continue; /* We need the wire format for ordering, and digest calculation */ r = dns_resource_record_to_wire_format(rr, true); if (r < 0) return r; list[n++] = rr; if (n > VERIFY_RRS_MAX) return -E2BIG; } if (n <= 0) return -ENODATA; /* Bring the RRs into canonical order */ qsort_safe(list, n, sizeof(DnsResourceRecord*), rr_compare); /* OK, the RRs are now in canonical order. Let's calculate the digest */ initialize_libgcrypt(); hash_size = gcry_md_get_algo_dlen(md_algorithm); assert(hash_size > 0); gcry_md_open(&md, md_algorithm, 0); if (!md) return -EIO; md_add_uint16(md, rrsig->rrsig.type_covered); md_add_uint8(md, rrsig->rrsig.algorithm); md_add_uint8(md, rrsig->rrsig.labels); md_add_uint32(md, rrsig->rrsig.original_ttl); md_add_uint32(md, rrsig->rrsig.expiration); md_add_uint32(md, rrsig->rrsig.inception); md_add_uint16(md, rrsig->rrsig.key_tag); r = dns_name_to_wire_format(rrsig->rrsig.signer, wire_format_name, sizeof(wire_format_name), true); if (r < 0) goto finish; gcry_md_write(md, wire_format_name, r); /* Convert the source of synthesis into wire format */ r = dns_name_to_wire_format(source, wire_format_name, sizeof(wire_format_name), true); if (r < 0) goto finish; for (k = 0; k < n; k++) { size_t l; rr = list[k]; /* Hash the source of synthesis. If this is a wildcard, then prefix it with the *. label */ if (wildcard) gcry_md_write(md, (uint8_t[]) { 1, '*'}, 2); gcry_md_write(md, wire_format_name, r); md_add_uint16(md, rr->key->type); md_add_uint16(md, rr->key->class); md_add_uint32(md, rrsig->rrsig.original_ttl); l = DNS_RESOURCE_RECORD_RDATA_SIZE(rr); assert(l <= 0xFFFF); md_add_uint16(md, (uint16_t) l); gcry_md_write(md, DNS_RESOURCE_RECORD_RDATA(rr), l); } hash = gcry_md_read(md, 0); if (!hash) { r = -EIO; goto finish; } switch (rrsig->rrsig.algorithm) { case DNSSEC_ALGORITHM_RSASHA1: case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1: case DNSSEC_ALGORITHM_RSASHA256: case DNSSEC_ALGORITHM_RSASHA512: r = dnssec_rsa_verify( gcry_md_algo_name(md_algorithm), hash, hash_size, rrsig, dnskey); break; case DNSSEC_ALGORITHM_ECDSAP256SHA256: case DNSSEC_ALGORITHM_ECDSAP384SHA384: r = dnssec_ecdsa_verify( gcry_md_algo_name(md_algorithm), rrsig->rrsig.algorithm, hash, hash_size, rrsig, dnskey); break; } if (r < 0) goto finish; /* Now, fix the ttl, expiry, and remember the synthesizing source and the signer */ if (r > 0) dnssec_fix_rrset_ttl(list, n, rrsig, realtime); if (r == 0) *result = DNSSEC_INVALID; else if (wildcard) *result = DNSSEC_VALIDATED_WILDCARD; else *result = DNSSEC_VALIDATED; r = 0; finish: gcry_md_close(md); return r; } int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) { assert(rrsig); assert(dnskey); /* Checks if the specified DNSKEY RR matches the key used for * the signature in the specified RRSIG RR */ if (rrsig->key->type != DNS_TYPE_RRSIG) return -EINVAL; if (dnskey->key->type != DNS_TYPE_DNSKEY) return 0; if (dnskey->key->class != rrsig->key->class) return 0; if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0) return 0; if (!revoked_ok && (dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE)) return 0; if (dnskey->dnskey.protocol != 3) return 0; if (dnskey->dnskey.algorithm != rrsig->rrsig.algorithm) return 0; if (dnssec_keytag(dnskey, false) != rrsig->rrsig.key_tag) return 0; return dns_name_equal(DNS_RESOURCE_KEY_NAME(dnskey->key), rrsig->rrsig.signer); } int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) { assert(key); assert(rrsig); /* Checks if the specified RRSIG RR protects the RRSet of the specified RR key. */ if (rrsig->key->type != DNS_TYPE_RRSIG) return 0; if (rrsig->key->class != key->class) return 0; if (rrsig->rrsig.type_covered != key->type) return 0; return dns_name_equal(DNS_RESOURCE_KEY_NAME(rrsig->key), DNS_RESOURCE_KEY_NAME(key)); } int dnssec_verify_rrset_search( DnsAnswer *a, const DnsResourceKey *key, DnsAnswer *validated_dnskeys, usec_t realtime, DnssecResult *result, DnsResourceRecord **ret_rrsig) { bool found_rrsig = false, found_invalid = false, found_expired_rrsig = false, found_unsupported_algorithm = false; DnsResourceRecord *rrsig; int r; assert(key); assert(result); /* Verifies all RRs from "a" that match the key "key" against DNSKEYs in "validated_dnskeys" */ if (!a || a->n_rrs <= 0) return -ENODATA; /* Iterate through each RRSIG RR. */ DNS_ANSWER_FOREACH(rrsig, a) { DnsResourceRecord *dnskey; DnsAnswerFlags flags; /* Is this an RRSIG RR that applies to RRs matching our key? */ r = dnssec_key_match_rrsig(key, rrsig); if (r < 0) return r; if (r == 0) continue; found_rrsig = true; /* Look for a matching key */ DNS_ANSWER_FOREACH_FLAGS(dnskey, flags, validated_dnskeys) { DnssecResult one_result; if ((flags & DNS_ANSWER_AUTHENTICATED) == 0) continue; /* Is this a DNSKEY RR that matches they key of our RRSIG? */ r = dnssec_rrsig_match_dnskey(rrsig, dnskey, false); if (r < 0) return r; if (r == 0) continue; /* Take the time here, if it isn't set yet, so * that we do all validations with the same * time. */ if (realtime == USEC_INFINITY) realtime = now(CLOCK_REALTIME); /* Yay, we found a matching RRSIG with a matching * DNSKEY, awesome. Now let's verify all entries of * the RRSet against the RRSIG and DNSKEY * combination. */ r = dnssec_verify_rrset(a, key, rrsig, dnskey, realtime, &one_result); if (r < 0) return r; switch (one_result) { case DNSSEC_VALIDATED: case DNSSEC_VALIDATED_WILDCARD: /* Yay, the RR has been validated, * return immediately, but fix up the expiry */ if (ret_rrsig) *ret_rrsig = rrsig; *result = one_result; return 0; case DNSSEC_INVALID: /* If the signature is invalid, let's try another key and/or signature. After all they key_tags and stuff are not unique, and might be shared by multiple keys. */ found_invalid = true; continue; case DNSSEC_UNSUPPORTED_ALGORITHM: /* If the key algorithm is unsupported, try another RRSIG/DNSKEY pair, but remember we encountered this, so that we can return a proper error when we encounter nothing better. */ found_unsupported_algorithm = true; continue; case DNSSEC_SIGNATURE_EXPIRED: /* If the signature is expired, try another one, but remember it, so that we can return this */ found_expired_rrsig = true; continue; default: assert_not_reached("Unexpected DNSSEC validation result"); } } } if (found_expired_rrsig) *result = DNSSEC_SIGNATURE_EXPIRED; else if (found_unsupported_algorithm) *result = DNSSEC_UNSUPPORTED_ALGORITHM; else if (found_invalid) *result = DNSSEC_INVALID; else if (found_rrsig) *result = DNSSEC_MISSING_KEY; else *result = DNSSEC_NO_SIGNATURE; if (ret_rrsig) *ret_rrsig = NULL; return 0; } int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) { DnsResourceRecord *rr; int r; /* Checks whether there's at least one RRSIG in 'a' that proctects RRs of the specified key */ DNS_ANSWER_FOREACH(rr, a) { r = dnssec_key_match_rrsig(key, rr); if (r < 0) return r; if (r > 0) return 1; } return 0; } static int digest_to_gcrypt_md(uint8_t algorithm) { /* Translates a DNSSEC digest algorithm into a gcrypt digest identifier */ switch (algorithm) { case DNSSEC_DIGEST_SHA1: return GCRY_MD_SHA1; case DNSSEC_DIGEST_SHA256: return GCRY_MD_SHA256; case DNSSEC_DIGEST_SHA384: return GCRY_MD_SHA384; default: return -EOPNOTSUPP; } } int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) { char owner_name[DNSSEC_CANONICAL_HOSTNAME_MAX]; gcry_md_hd_t md = NULL; size_t hash_size; int md_algorithm, r; void *result; assert(dnskey); assert(ds); /* Implements DNSKEY verification by a DS, according to RFC 4035, section 5.2 */ if (dnskey->key->type != DNS_TYPE_DNSKEY) return -EINVAL; if (ds->key->type != DNS_TYPE_DS) return -EINVAL; if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0) return -EKEYREJECTED; if (!mask_revoke && (dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE)) return -EKEYREJECTED; if (dnskey->dnskey.protocol != 3) return -EKEYREJECTED; if (dnskey->dnskey.algorithm != ds->ds.algorithm) return 0; if (dnssec_keytag(dnskey, mask_revoke) != ds->ds.key_tag) return 0; initialize_libgcrypt(); md_algorithm = digest_to_gcrypt_md(ds->ds.digest_type); if (md_algorithm < 0) return md_algorithm; hash_size = gcry_md_get_algo_dlen(md_algorithm); assert(hash_size > 0); if (ds->ds.digest_size != hash_size) return 0; r = dnssec_canonicalize(DNS_RESOURCE_KEY_NAME(dnskey->key), owner_name, sizeof(owner_name)); if (r < 0) return r; gcry_md_open(&md, md_algorithm, 0); if (!md) return -EIO; gcry_md_write(md, owner_name, r); if (mask_revoke) md_add_uint16(md, dnskey->dnskey.flags & ~DNSKEY_FLAG_REVOKE); else md_add_uint16(md, dnskey->dnskey.flags); md_add_uint8(md, dnskey->dnskey.protocol); md_add_uint8(md, dnskey->dnskey.algorithm); gcry_md_write(md, dnskey->dnskey.key, dnskey->dnskey.key_size); result = gcry_md_read(md, 0); if (!result) { r = -EIO; goto finish; } r = memcmp(result, ds->ds.digest, ds->ds.digest_size) != 0; finish: gcry_md_close(md); return r; } int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) { DnsResourceRecord *ds; DnsAnswerFlags flags; int r; assert(dnskey); if (dnskey->key->type != DNS_TYPE_DNSKEY) return 0; DNS_ANSWER_FOREACH_FLAGS(ds, flags, validated_ds) { if ((flags & DNS_ANSWER_AUTHENTICATED) == 0) continue; if (ds->key->type != DNS_TYPE_DS) continue; if (ds->key->class != dnskey->key->class) continue; r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dnskey->key), DNS_RESOURCE_KEY_NAME(ds->key)); if (r < 0) return r; if (r == 0) continue; r = dnssec_verify_dnskey_by_ds(dnskey, ds, false); if (IN_SET(r, -EKEYREJECTED, -EOPNOTSUPP)) return 0; /* The DNSKEY is revoked or otherwise invalid, or we don't support the digest algorithm */ if (r < 0) return r; if (r > 0) return 1; } return 0; } static int nsec3_hash_to_gcrypt_md(uint8_t algorithm) { /* Translates a DNSSEC NSEC3 hash algorithm into a gcrypt digest identifier */ switch (algorithm) { case NSEC3_ALGORITHM_SHA1: return GCRY_MD_SHA1; default: return -EOPNOTSUPP; } } int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) { uint8_t wire_format[DNS_WIRE_FOMAT_HOSTNAME_MAX]; gcry_md_hd_t md = NULL; size_t hash_size; int algorithm; void *result; unsigned k; int r; assert(nsec3); assert(name); assert(ret); if (nsec3->key->type != DNS_TYPE_NSEC3) return -EINVAL; if (nsec3->nsec3.iterations > NSEC3_ITERATIONS_MAX) { log_debug("Ignoring NSEC3 RR %s with excessive number of iterations.", dns_resource_record_to_string(nsec3)); return -EOPNOTSUPP; } algorithm = nsec3_hash_to_gcrypt_md(nsec3->nsec3.algorithm); if (algorithm < 0) return algorithm; initialize_libgcrypt(); hash_size = gcry_md_get_algo_dlen(algorithm); assert(hash_size > 0); if (nsec3->nsec3.next_hashed_name_size != hash_size) return -EINVAL; r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true); if (r < 0) return r; gcry_md_open(&md, algorithm, 0); if (!md) return -EIO; gcry_md_write(md, wire_format, r); gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size); result = gcry_md_read(md, 0); if (!result) { r = -EIO; goto finish; } for (k = 0; k < nsec3->nsec3.iterations; k++) { uint8_t tmp[hash_size]; memcpy(tmp, result, hash_size); gcry_md_reset(md); gcry_md_write(md, tmp, hash_size); gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size); result = gcry_md_read(md, 0); if (!result) { r = -EIO; goto finish; } } memcpy(ret, result, hash_size); r = (int) hash_size; finish: gcry_md_close(md); return r; } static int nsec3_is_good(DnsResourceRecord *rr, DnsResourceRecord *nsec3) { const char *a, *b; int r; assert(rr); if (rr->key->type != DNS_TYPE_NSEC3) return 0; /* RFC 5155, Section 8.2 says we MUST ignore NSEC3 RRs with flags != 0 or 1 */ if (!IN_SET(rr->nsec3.flags, 0, 1)) return 0; /* Ignore NSEC3 RRs whose algorithm we don't know */ if (nsec3_hash_to_gcrypt_md(rr->nsec3.algorithm) < 0) return 0; /* Ignore NSEC3 RRs with an excessive number of required iterations */ if (rr->nsec3.iterations > NSEC3_ITERATIONS_MAX) return 0; /* Ignore NSEC3 RRs generated from wildcards. If these NSEC3 RRs weren't correctly signed we can't make this * check (since rr->n_skip_labels_source is -1), but that's OK, as we won't trust them anyway in that case. */ if (rr->n_skip_labels_source != 0 && rr->n_skip_labels_source != (unsigned) -1) return 0; /* Ignore NSEC3 RRs that are located anywhere else than one label below the zone */ if (rr->n_skip_labels_signer != 1 && rr->n_skip_labels_signer != (unsigned) -1) return 0; if (!nsec3) return 1; /* If a second NSEC3 RR is specified, also check if they are from the same zone. */ if (nsec3 == rr) /* Shortcut */ return 1; if (rr->key->class != nsec3->key->class) return 0; if (rr->nsec3.algorithm != nsec3->nsec3.algorithm) return 0; if (rr->nsec3.iterations != nsec3->nsec3.iterations) return 0; if (rr->nsec3.salt_size != nsec3->nsec3.salt_size) return 0; if (memcmp(rr->nsec3.salt, nsec3->nsec3.salt, rr->nsec3.salt_size) != 0) return 0; a = DNS_RESOURCE_KEY_NAME(rr->key); r = dns_name_parent(&a); /* strip off hash */ if (r < 0) return r; if (r == 0) return 0; b = DNS_RESOURCE_KEY_NAME(nsec3->key); r = dns_name_parent(&b); /* strip off hash */ if (r < 0) return r; if (r == 0) return 0; /* Make sure both have the same parent */ return dns_name_equal(a, b); } static int nsec3_hashed_domain_format(const uint8_t *hashed, size_t hashed_size, const char *zone, char **ret) { _cleanup_free_ char *l = NULL; char *j; assert(hashed); assert(hashed_size > 0); assert(zone); assert(ret); l = base32hexmem(hashed, hashed_size, false); if (!l) return -ENOMEM; j = strjoin(l, ".", zone, NULL); if (!j) return -ENOMEM; *ret = j; return (int) hashed_size; } static int nsec3_hashed_domain_make(DnsResourceRecord *nsec3, const char *domain, const char *zone, char **ret) { uint8_t hashed[DNSSEC_HASH_SIZE_MAX]; int hashed_size; assert(nsec3); assert(domain); assert(zone); assert(ret); hashed_size = dnssec_nsec3_hash(nsec3, domain, hashed); if (hashed_size < 0) return hashed_size; return nsec3_hashed_domain_format(hashed, (size_t) hashed_size, zone, ret); } /* See RFC 5155, Section 8 * First try to find a NSEC3 record that matches our query precisely, if that fails, find the closest * enclosure. Secondly, find a proof that there is no closer enclosure and either a proof that there * is no wildcard domain as a direct descendant of the closest enclosure, or find an NSEC3 record that * matches the wildcard domain. * * Based on this we can prove either the existence of the record in @key, or NXDOMAIN or NODATA, or * that there is no proof either way. The latter is the case if a the proof of non-existence of a given * name uses an NSEC3 record with the opt-out bit set. Lastly, if we are given insufficient NSEC3 records * to conclude anything we indicate this by returning NO_RR. */ static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) { _cleanup_free_ char *next_closer_domain = NULL, *wildcard_domain = NULL; const char *zone, *p, *pp = NULL, *wildcard; DnsResourceRecord *rr, *enclosure_rr, *zone_rr, *wildcard_rr = NULL; DnsAnswerFlags flags; int hashed_size, r; bool a, no_closer = false, no_wildcard = false, optout = false; assert(key); assert(result); /* First step, find the zone name and the NSEC3 parameters of the zone. * it is sufficient to look for the longest common suffix we find with * any NSEC3 RR in the response. Any NSEC3 record will do as all NSEC3 * records from a given zone in a response must use the same * parameters. */ zone = DNS_RESOURCE_KEY_NAME(key); for (;;) { DNS_ANSWER_FOREACH_FLAGS(zone_rr, flags, answer) { r = nsec3_is_good(zone_rr, NULL); if (r < 0) return r; if (r == 0) continue; r = dns_name_equal_skip(DNS_RESOURCE_KEY_NAME(zone_rr->key), 1, zone); if (r < 0) return r; if (r > 0) goto found_zone; } /* Strip one label from the front */ r = dns_name_parent(&zone); if (r < 0) return r; if (r == 0) break; } *result = DNSSEC_NSEC_NO_RR; return 0; found_zone: /* Second step, find the closest encloser NSEC3 RR in 'answer' that matches 'key' */ p = DNS_RESOURCE_KEY_NAME(key); for (;;) { _cleanup_free_ char *hashed_domain = NULL; hashed_size = nsec3_hashed_domain_make(zone_rr, p, zone, &hashed_domain); if (hashed_size == -EOPNOTSUPP) { *result = DNSSEC_NSEC_UNSUPPORTED_ALGORITHM; return 0; } if (hashed_size < 0) return hashed_size; DNS_ANSWER_FOREACH_FLAGS(enclosure_rr, flags, answer) { r = nsec3_is_good(enclosure_rr, zone_rr); if (r < 0) return r; if (r == 0) continue; if (enclosure_rr->nsec3.next_hashed_name_size != (size_t) hashed_size) continue; r = dns_name_equal(DNS_RESOURCE_KEY_NAME(enclosure_rr->key), hashed_domain); if (r < 0) return r; if (r > 0) { a = flags & DNS_ANSWER_AUTHENTICATED; goto found_closest_encloser; } } /* We didn't find the closest encloser with this name, * but let's remember this domain name, it might be * the next closer name */ pp = p; /* Strip one label from the front */ r = dns_name_parent(&p); if (r < 0) return r; if (r == 0) break; } *result = DNSSEC_NSEC_NO_RR; return 0; found_closest_encloser: /* We found a closest encloser in 'p'; next closer is 'pp' */ if (!pp) { /* We have an exact match! If we area looking for a DS RR, then we must insist that we got the NSEC3 RR * from the parent. Otherwise the one from the child. Do so, by checking whether SOA and NS are * appropriately set. */ if (key->type == DNS_TYPE_DS) { if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA)) return -EBADMSG; } else { if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) && !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA)) return -EBADMSG; } /* No next closer NSEC3 RR. That means there's a direct NSEC3 RR for our key. */ if (bitmap_isset(enclosure_rr->nsec3.types, key->type)) *result = DNSSEC_NSEC_FOUND; else if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_CNAME)) *result = DNSSEC_NSEC_CNAME; else *result = DNSSEC_NSEC_NODATA; if (authenticated) *authenticated = a; if (ttl) *ttl = enclosure_rr->ttl; return 0; } /* Ensure this is not a DNAME domain, see RFC5155, section 8.3. */ if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_DNAME)) return -EBADMSG; /* Ensure that this data is from the delegated domain * (i.e. originates from the "lower" DNS server), and isn't * just glue records (i.e. doesn't originate from the "upper" * DNS server). */ if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) && !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA)) return -EBADMSG; /* Prove that there is no next closer and whether or not there is a wildcard domain. */ wildcard = strjoina("*.", p); r = nsec3_hashed_domain_make(enclosure_rr, wildcard, zone, &wildcard_domain); if (r < 0) return r; if (r != hashed_size) return -EBADMSG; r = nsec3_hashed_domain_make(enclosure_rr, pp, zone, &next_closer_domain); if (r < 0) return r; if (r != hashed_size) return -EBADMSG; DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { _cleanup_free_ char *next_hashed_domain = NULL; r = nsec3_is_good(rr, zone_rr); if (r < 0) return r; if (r == 0) continue; r = nsec3_hashed_domain_format(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, zone, &next_hashed_domain); if (r < 0) return r; r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), next_closer_domain, next_hashed_domain); if (r < 0) return r; if (r > 0) { if (rr->nsec3.flags & 1) optout = true; a = a && (flags & DNS_ANSWER_AUTHENTICATED); no_closer = true; } r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), wildcard_domain); if (r < 0) return r; if (r > 0) { a = a && (flags & DNS_ANSWER_AUTHENTICATED); wildcard_rr = rr; } r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), wildcard_domain, next_hashed_domain); if (r < 0) return r; if (r > 0) { if (rr->nsec3.flags & 1) /* This only makes sense if we have a wildcard delegation, which is * very unlikely, see RFC 4592, Section 4.2, but we cannot rely on * this not happening, so hence cannot simply conclude NXDOMAIN as * we would wish */ optout = true; a = a && (flags & DNS_ANSWER_AUTHENTICATED); no_wildcard = true; } } if (wildcard_rr && no_wildcard) return -EBADMSG; if (!no_closer) { *result = DNSSEC_NSEC_NO_RR; return 0; } if (wildcard_rr) { /* A wildcard exists that matches our query. */ if (optout) /* This is not specified in any RFC to the best of my knowledge, but * if the next closer enclosure is covered by an opt-out NSEC3 RR * it means that we cannot prove that the source of synthesis is * correct, as there may be a closer match. */ *result = DNSSEC_NSEC_OPTOUT; else if (bitmap_isset(wildcard_rr->nsec3.types, key->type)) *result = DNSSEC_NSEC_FOUND; else if (bitmap_isset(wildcard_rr->nsec3.types, DNS_TYPE_CNAME)) *result = DNSSEC_NSEC_CNAME; else *result = DNSSEC_NSEC_NODATA; } else { if (optout) /* The RFC only specifies that we have to care for optout for NODATA for * DS records. However, children of an insecure opt-out delegation should * also be considered opt-out, rather than verified NXDOMAIN. * Note that we do not require a proof of wildcard non-existence if the * next closer domain is covered by an opt-out, as that would not provide * any additional information. */ *result = DNSSEC_NSEC_OPTOUT; else if (no_wildcard) *result = DNSSEC_NSEC_NXDOMAIN; else { *result = DNSSEC_NSEC_NO_RR; return 0; } } if (authenticated) *authenticated = a; if (ttl) *ttl = enclosure_rr->ttl; return 0; } static int dnssec_nsec_wildcard_equal(DnsResourceRecord *rr, const char *name) { char label[DNS_LABEL_MAX]; const char *n; int r; assert(rr); assert(rr->key->type == DNS_TYPE_NSEC); /* Checks whether the specified RR has a name beginning in "*.", and if the rest is a suffix of our name */ if (rr->n_skip_labels_source != 1) return 0; n = DNS_RESOURCE_KEY_NAME(rr->key); r = dns_label_unescape(&n, label, sizeof(label)); if (r <= 0) return r; if (r != 1 || label[0] != '*') return 0; return dns_name_endswith(name, n); } static int dnssec_nsec_in_path(DnsResourceRecord *rr, const char *name) { const char *nn, *common_suffix; int r; assert(rr); assert(rr->key->type == DNS_TYPE_NSEC); /* Checks whether the specified nsec RR indicates that name is an empty non-terminal (ENT) * * A couple of examples: * * NSEC bar → waldo.foo.bar: indicates that foo.bar exists and is an ENT * NSEC waldo.foo.bar → yyy.zzz.xoo.bar: indicates that xoo.bar and zzz.xoo.bar exist and are ENTs * NSEC yyy.zzz.xoo.bar → bar: indicates pretty much nothing about ENTs */ /* First, determine parent of next domain. */ nn = rr->nsec.next_domain_name; r = dns_name_parent(&nn); if (r <= 0) return r; /* If the name we just determined is not equal or child of the name we are interested in, then we can't say * anything at all. */ r = dns_name_endswith(nn, name); if (r <= 0) return r; /* If the name we we are interested in is not a prefix of the common suffix of the NSEC RR's owner and next domain names, then we can't say anything either. */ r = dns_name_common_suffix(DNS_RESOURCE_KEY_NAME(rr->key), rr->nsec.next_domain_name, &common_suffix); if (r < 0) return r; return dns_name_endswith(name, common_suffix); } static int dnssec_nsec_from_parent_zone(DnsResourceRecord *rr, const char *name) { int r; assert(rr); assert(rr->key->type == DNS_TYPE_NSEC); /* Checks whether this NSEC originates to the parent zone or the child zone. */ r = dns_name_parent(&name); if (r <= 0) return r; r = dns_name_equal(name, DNS_RESOURCE_KEY_NAME(rr->key)); if (r <= 0) return r; /* DNAME, and NS without SOA is an indication for a delegation. */ if (bitmap_isset(rr->nsec.types, DNS_TYPE_DNAME)) return 1; if (bitmap_isset(rr->nsec.types, DNS_TYPE_NS) && !bitmap_isset(rr->nsec.types, DNS_TYPE_SOA)) return 1; return 0; } static int dnssec_nsec_covers(DnsResourceRecord *rr, const char *name) { const char *common_suffix, *p; int r; assert(rr); assert(rr->key->type == DNS_TYPE_NSEC); /* Checks whether the "Next Closer" is witin the space covered by the specified RR. */ r = dns_name_common_suffix(DNS_RESOURCE_KEY_NAME(rr->key), rr->nsec.next_domain_name, &common_suffix); if (r < 0) return r; for (;;) { p = name; r = dns_name_parent(&name); if (r < 0) return r; if (r == 0) return 0; r = dns_name_equal(name, common_suffix); if (r < 0) return r; if (r > 0) break; } /* p is now the "Next Closer". */ return dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), p, rr->nsec.next_domain_name); } static int dnssec_nsec_covers_wildcard(DnsResourceRecord *rr, const char *name) { const char *common_suffix, *wc; int r; assert(rr); assert(rr->key->type == DNS_TYPE_NSEC); /* Checks whether the "Wildcard at the Closest Encloser" is within the space covered by the specified * RR. Specifically, checks whether 'name' has the common suffix of the NSEC RR's owner and next names as * suffix, and whether the NSEC covers the name generated by that suffix prepended with an asterisk label. * * NSEC bar → waldo.foo.bar: indicates that *.bar and *.foo.bar do not exist * NSEC waldo.foo.bar → yyy.zzz.xoo.bar: indicates that *.xoo.bar and *.zzz.xoo.bar do not exist (and more ...) * NSEC yyy.zzz.xoo.bar → bar: indicates that a number of wildcards don#t exist either... */ r = dns_name_common_suffix(DNS_RESOURCE_KEY_NAME(rr->key), rr->nsec.next_domain_name, &common_suffix); if (r < 0) return r; /* If the common suffix is not shared by the name we are interested in, it has nothing to say for us. */ r = dns_name_endswith(name, common_suffix); if (r <= 0) return r; wc = strjoina("*.", common_suffix, NULL); return dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), wc, rr->nsec.next_domain_name); } int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) { bool have_nsec3 = false, covering_rr_authenticated = false, wildcard_rr_authenticated = false; DnsResourceRecord *rr, *covering_rr = NULL, *wildcard_rr = NULL; DnsAnswerFlags flags; const char *name; int r; assert(key); assert(result); /* Look for any NSEC/NSEC3 RRs that say something about the specified key. */ name = DNS_RESOURCE_KEY_NAME(key); DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { if (rr->key->class != key->class) continue; have_nsec3 = have_nsec3 || (rr->key->type == DNS_TYPE_NSEC3); if (rr->key->type != DNS_TYPE_NSEC) continue; /* The following checks only make sense for NSEC RRs that are not expanded from a wildcard */ r = dns_resource_record_is_synthetic(rr); if (r < 0) return r; if (r > 0) continue; /* Check if this is a direct match. If so, we have encountered a NODATA case */ r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), name); if (r < 0) return r; if (r == 0) { /* If it's not a direct match, maybe it's a wild card match? */ r = dnssec_nsec_wildcard_equal(rr, name); if (r < 0) return r; } if (r > 0) { if (key->type == DNS_TYPE_DS) { /* If we look for a DS RR and the server sent us the NSEC RR of the child zone * we have a problem. For DS RRs we want the NSEC RR from the parent */ if (bitmap_isset(rr->nsec.types, DNS_TYPE_SOA)) continue; } else { /* For all RR types, ensure that if NS is set SOA is set too, so that we know * we got the child's NSEC. */ if (bitmap_isset(rr->nsec.types, DNS_TYPE_NS) && !bitmap_isset(rr->nsec.types, DNS_TYPE_SOA)) continue; } if (bitmap_isset(rr->nsec.types, key->type)) *result = DNSSEC_NSEC_FOUND; else if (bitmap_isset(rr->nsec.types, DNS_TYPE_CNAME)) *result = DNSSEC_NSEC_CNAME; else *result = DNSSEC_NSEC_NODATA; if (authenticated) *authenticated = flags & DNS_ANSWER_AUTHENTICATED; if (ttl) *ttl = rr->ttl; return 0; } /* Check if the name we are looking for is an empty non-terminal within the owner or next name * of the NSEC RR. */ r = dnssec_nsec_in_path(rr, name); if (r < 0) return r; if (r > 0) { *result = DNSSEC_NSEC_NODATA; if (authenticated) *authenticated = flags & DNS_ANSWER_AUTHENTICATED; if (ttl) *ttl = rr->ttl; return 0; } /* The following two "covering" checks, are not useful if the NSEC is from the parent */ r = dnssec_nsec_from_parent_zone(rr, name); if (r < 0) return r; if (r > 0) continue; /* Check if this NSEC RR proves the absence of an explicit RR under this name */ r = dnssec_nsec_covers(rr, name); if (r < 0) return r; if (r > 0 && (!covering_rr || !covering_rr_authenticated)) { covering_rr = rr; covering_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED; } /* Check if this NSEC RR proves the absence of a wildcard RR under this name */ r = dnssec_nsec_covers_wildcard(rr, name); if (r < 0) return r; if (r > 0 && (!wildcard_rr || !wildcard_rr_authenticated)) { wildcard_rr = rr; wildcard_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED; } } if (covering_rr && wildcard_rr) { /* If we could prove that neither the name itself, nor the wildcard at the closest encloser exists, we * proved the NXDOMAIN case. */ *result = DNSSEC_NSEC_NXDOMAIN; if (authenticated) *authenticated = covering_rr_authenticated && wildcard_rr_authenticated; if (ttl) *ttl = MIN(covering_rr->ttl, wildcard_rr->ttl); return 0; } /* OK, this was not sufficient. Let's see if NSEC3 can help. */ if (have_nsec3) return dnssec_test_nsec3(answer, key, result, authenticated, ttl); /* No approproate NSEC RR found, report this. */ *result = DNSSEC_NSEC_NO_RR; return 0; } static int dnssec_nsec_test_enclosed(DnsAnswer *answer, uint16_t type, const char *name, const char *zone, bool *authenticated) { DnsResourceRecord *rr; DnsAnswerFlags flags; int r; assert(name); assert(zone); /* Checks whether there's an NSEC/NSEC3 that proves that the specified 'name' is non-existing in the specified * 'zone'. The 'zone' must be a suffix of the 'name'. */ DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { bool found = false; if (rr->key->type != type && type != DNS_TYPE_ANY) continue; switch (rr->key->type) { case DNS_TYPE_NSEC: /* We only care for NSEC RRs from the indicated zone */ r = dns_resource_record_is_signer(rr, zone); if (r < 0) return r; if (r == 0) continue; r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), name, rr->nsec.next_domain_name); if (r < 0) return r; found = r > 0; break; case DNS_TYPE_NSEC3: { _cleanup_free_ char *hashed_domain = NULL, *next_hashed_domain = NULL; /* We only care for NSEC3 RRs from the indicated zone */ r = dns_resource_record_is_signer(rr, zone); if (r < 0) return r; if (r == 0) continue; r = nsec3_is_good(rr, NULL); if (r < 0) return r; if (r == 0) break; /* Format the domain we are testing with the NSEC3 RR's hash function */ r = nsec3_hashed_domain_make( rr, name, zone, &hashed_domain); if (r < 0) return r; if ((size_t) r != rr->nsec3.next_hashed_name_size) break; /* Format the NSEC3's next hashed name as proper domain name */ r = nsec3_hashed_domain_format( rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, zone, &next_hashed_domain); if (r < 0) return r; r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), hashed_domain, next_hashed_domain); if (r < 0) return r; found = r > 0; break; } default: continue; } if (found) { if (authenticated) *authenticated = flags & DNS_ANSWER_AUTHENTICATED; return 1; } } return 0; } static int dnssec_test_positive_wildcard_nsec3( DnsAnswer *answer, const char *name, const char *source, const char *zone, bool *authenticated) { const char *next_closer = NULL; int r; /* Run a positive NSEC3 wildcard proof. Specifically: * * A proof that the the "next closer" of the generating wildcard does not exist. * * Note a key difference between the NSEC3 and NSEC versions of the proof. NSEC RRs don't have to exist for * empty non-transients. NSEC3 RRs however have to. This means it's sufficient to check if the next closer name * exists for the NSEC3 RR and we are done. * * To prove that a.b.c.d.e.f is rightfully synthesized from a wildcard *.d.e.f all we have to check is that * c.d.e.f does not exist. */ for (;;) { next_closer = name; r = dns_name_parent(&name); if (r < 0) return r; if (r == 0) return 0; r = dns_name_equal(name, source); if (r < 0) return r; if (r > 0) break; } return dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC3, next_closer, zone, authenticated); } static int dnssec_test_positive_wildcard_nsec( DnsAnswer *answer, const char *name, const char *source, const char *zone, bool *_authenticated) { bool authenticated = true; int r; /* Run a positive NSEC wildcard proof. Specifically: * * A proof that there's neither a wildcard name nor a non-wildcard name that is a suffix of the name "name" and * a prefix of the synthesizing source "source" in the zone "zone". * * See RFC 5155, Section 8.8 and RFC 4035, Section 5.3.4 * * Note that if we want to prove that a.b.c.d.e.f is rightfully synthesized from a wildcard *.d.e.f, then we * have to prove that none of the following exist: * * 1) a.b.c.d.e.f * 2) *.b.c.d.e.f * 3) b.c.d.e.f * 4) *.c.d.e.f * 5) c.d.e.f * */ for (;;) { _cleanup_free_ char *wc = NULL; bool a = false; /* Check if there's an NSEC or NSEC3 RR that proves that the mame we determined is really non-existing, * i.e between the owner name and the next name of an NSEC RR. */ r = dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC, name, zone, &a); if (r <= 0) return r; authenticated = authenticated && a; /* Strip one label off */ r = dns_name_parent(&name); if (r <= 0) return r; /* Did we reach the source of synthesis? */ r = dns_name_equal(name, source); if (r < 0) return r; if (r > 0) { /* Successful exit */ *_authenticated = authenticated; return 1; } /* Safety check, that the source of synthesis is still our suffix */ r = dns_name_endswith(name, source); if (r < 0) return r; if (r == 0) return -EBADMSG; /* Replace the label we stripped off with an asterisk */ wc = strappend("*.", name); if (!wc) return -ENOMEM; /* And check if the proof holds for the asterisk name, too */ r = dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC, wc, zone, &a); if (r <= 0) return r; authenticated = authenticated && a; /* In the next iteration we'll check the non-asterisk-prefixed version */ } } int dnssec_test_positive_wildcard( DnsAnswer *answer, const char *name, const char *source, const char *zone, bool *authenticated) { int r; assert(name); assert(source); assert(zone); assert(authenticated); r = dns_answer_contains_zone_nsec3(answer, zone); if (r < 0) return r; if (r > 0) return dnssec_test_positive_wildcard_nsec3(answer, name, source, zone, authenticated); else return dnssec_test_positive_wildcard_nsec(answer, name, source, zone, authenticated); } #else int dnssec_verify_rrset( DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, usec_t realtime, DnssecResult *result) { return -EOPNOTSUPP; } int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) { return -EOPNOTSUPP; } int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) { return -EOPNOTSUPP; } int dnssec_verify_rrset_search( DnsAnswer *a, const DnsResourceKey *key, DnsAnswer *validated_dnskeys, usec_t realtime, DnssecResult *result, DnsResourceRecord **ret_rrsig) { return -EOPNOTSUPP; } int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) { return -EOPNOTSUPP; } int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) { return -EOPNOTSUPP; } int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) { return -EOPNOTSUPP; } int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) { return -EOPNOTSUPP; } int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) { return -EOPNOTSUPP; } int dnssec_test_positive_wildcard( DnsAnswer *answer, const char *name, const char *source, const char *zone, bool *authenticated) { return -EOPNOTSUPP; } #endif static const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = { [DNSSEC_VALIDATED] = "validated", [DNSSEC_VALIDATED_WILDCARD] = "validated-wildcard", [DNSSEC_INVALID] = "invalid", [DNSSEC_SIGNATURE_EXPIRED] = "signature-expired", [DNSSEC_UNSUPPORTED_ALGORITHM] = "unsupported-algorithm", [DNSSEC_NO_SIGNATURE] = "no-signature", [DNSSEC_MISSING_KEY] = "missing-key", [DNSSEC_UNSIGNED] = "unsigned", [DNSSEC_FAILED_AUXILIARY] = "failed-auxiliary", [DNSSEC_NSEC_MISMATCH] = "nsec-mismatch", [DNSSEC_INCOMPATIBLE_SERVER] = "incompatible-server", }; DEFINE_STRING_TABLE_LOOKUP(dnssec_result, DnssecResult); static const char* const dnssec_verdict_table[_DNSSEC_VERDICT_MAX] = { [DNSSEC_SECURE] = "secure", [DNSSEC_INSECURE] = "insecure", [DNSSEC_BOGUS] = "bogus", [DNSSEC_INDETERMINATE] = "indeterminate", }; DEFINE_STRING_TABLE_LOOKUP(dnssec_verdict, DnssecVerdict); systemd-229/src/resolve/resolved-dns-dnssec.h000066400000000000000000000074071265713322000213720ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef enum DnssecResult DnssecResult; typedef enum DnssecVerdict DnssecVerdict; #include "dns-domain.h" #include "resolved-dns-answer.h" #include "resolved-dns-rr.h" enum DnssecResult { /* These five are returned by dnssec_verify_rrset() */ DNSSEC_VALIDATED, DNSSEC_VALIDATED_WILDCARD, /* Validated via a wildcard RRSIG, further NSEC/NSEC3 checks necessary */ DNSSEC_INVALID, DNSSEC_SIGNATURE_EXPIRED, DNSSEC_UNSUPPORTED_ALGORITHM, /* These two are added by dnssec_verify_rrset_search() */ DNSSEC_NO_SIGNATURE, DNSSEC_MISSING_KEY, /* These two are added by the DnsTransaction logic */ DNSSEC_UNSIGNED, DNSSEC_FAILED_AUXILIARY, DNSSEC_NSEC_MISMATCH, DNSSEC_INCOMPATIBLE_SERVER, _DNSSEC_RESULT_MAX, _DNSSEC_RESULT_INVALID = -1 }; enum DnssecVerdict { DNSSEC_SECURE, DNSSEC_INSECURE, DNSSEC_BOGUS, DNSSEC_INDETERMINATE, _DNSSEC_VERDICT_MAX, _DNSSEC_VERDICT_INVALID = -1 }; #define DNSSEC_CANONICAL_HOSTNAME_MAX (DNS_HOSTNAME_MAX + 2) /* The longest digest we'll ever generate, of all digest algorithms we support */ #define DNSSEC_HASH_SIZE_MAX (MAX(20, 32)) int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok); int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig); int dnssec_verify_rrset(DnsAnswer *answer, const DnsResourceKey *key, DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, usec_t realtime, DnssecResult *result); int dnssec_verify_rrset_search(DnsAnswer *answer, const DnsResourceKey *key, DnsAnswer *validated_dnskeys, usec_t realtime, DnssecResult *result, DnsResourceRecord **rrsig); int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke); int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds); int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key); uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke); int dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max); int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret); typedef enum DnssecNsecResult { DNSSEC_NSEC_NO_RR, /* No suitable NSEC/NSEC3 RR found */ DNSSEC_NSEC_CNAME, /* Didn't find what was asked for, but did find CNAME */ DNSSEC_NSEC_UNSUPPORTED_ALGORITHM, DNSSEC_NSEC_NXDOMAIN, DNSSEC_NSEC_NODATA, DNSSEC_NSEC_FOUND, DNSSEC_NSEC_OPTOUT, } DnssecNsecResult; int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl); int dnssec_test_positive_wildcard(DnsAnswer *a, const char *name, const char *source, const char *zone, bool *authenticated); const char* dnssec_result_to_string(DnssecResult m) _const_; DnssecResult dnssec_result_from_string(const char *s) _pure_; const char* dnssec_verdict_to_string(DnssecVerdict m) _const_; DnssecVerdict dnssec_verdict_from_string(const char *s) _pure_; systemd-229/src/resolve/resolved-dns-packet.c000066400000000000000000002074601265713322000213560ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "dns-domain.h" #include "resolved-dns-packet.h" #include "string-table.h" #include "strv.h" #include "unaligned.h" #include "utf8.h" #include "util.h" #define EDNS0_OPT_DO (1<<15) int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) { DnsPacket *p; size_t a; assert(ret); if (mtu <= UDP_PACKET_HEADER_SIZE) a = DNS_PACKET_SIZE_START; else a = mtu - UDP_PACKET_HEADER_SIZE; if (a < DNS_PACKET_HEADER_SIZE) a = DNS_PACKET_HEADER_SIZE; /* round up to next page size */ a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket)); /* make sure we never allocate more than useful */ if (a > DNS_PACKET_SIZE_MAX) a = DNS_PACKET_SIZE_MAX; p = malloc0(ALIGN(sizeof(DnsPacket)) + a); if (!p) return -ENOMEM; p->size = p->rindex = DNS_PACKET_HEADER_SIZE; p->allocated = a; p->protocol = protocol; p->opt_start = p->opt_size = (size_t) -1; p->n_ref = 1; *ret = p; return 0; } void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated) { DnsPacketHeader *h; assert(p); h = DNS_PACKET_HEADER(p); switch(p->protocol) { case DNS_PROTOCOL_LLMNR: assert(!truncated); h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */, 0 /* opcode */, 0 /* c */, 0 /* tc */, 0 /* t */, 0 /* ra */, 0 /* ad */, 0 /* cd */, 0 /* rcode */)); break; case DNS_PROTOCOL_MDNS: h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */, 0 /* opcode */, 0 /* aa */, truncated /* tc */, 0 /* rd (ask for recursion) */, 0 /* ra */, 0 /* ad */, 0 /* cd */, 0 /* rcode */)); break; default: assert(!truncated); h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */, 0 /* opcode */, 0 /* aa */, 0 /* tc */, 1 /* rd (ask for recursion) */, 0 /* ra */, 0 /* ad */, dnssec_checking_disabled /* cd */, 0 /* rcode */)); } } int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled) { DnsPacket *p; int r; assert(ret); r = dns_packet_new(&p, protocol, mtu); if (r < 0) return r; /* Always set the TC bit to 0 initially. * If there are multiple packets later, we'll update the bit shortly before sending. */ dns_packet_set_flags(p, dnssec_checking_disabled, false); *ret = p; return 0; } DnsPacket *dns_packet_ref(DnsPacket *p) { if (!p) return NULL; assert(!p->on_stack); assert(p->n_ref > 0); p->n_ref++; return p; } static void dns_packet_free(DnsPacket *p) { char *s; assert(p); dns_question_unref(p->question); dns_answer_unref(p->answer); dns_resource_record_unref(p->opt); while ((s = hashmap_steal_first_key(p->names))) free(s); hashmap_free(p->names); free(p->_data); if (!p->on_stack) free(p); } DnsPacket *dns_packet_unref(DnsPacket *p) { if (!p) return NULL; assert(p->n_ref > 0); dns_packet_unref(p->more); if (p->n_ref == 1) dns_packet_free(p); else p->n_ref--; return NULL; } int dns_packet_validate(DnsPacket *p) { assert(p); if (p->size < DNS_PACKET_HEADER_SIZE) return -EBADMSG; if (p->size > DNS_PACKET_SIZE_MAX) return -EBADMSG; return 1; } int dns_packet_validate_reply(DnsPacket *p) { int r; assert(p); r = dns_packet_validate(p); if (r < 0) return r; if (DNS_PACKET_QR(p) != 1) return 0; if (DNS_PACKET_OPCODE(p) != 0) return -EBADMSG; switch (p->protocol) { case DNS_PROTOCOL_LLMNR: /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */ if (DNS_PACKET_QDCOUNT(p) != 1) return -EBADMSG; break; case DNS_PROTOCOL_MDNS: /* RFC 6762, Section 18 */ if (DNS_PACKET_RCODE(p) != 0) return -EBADMSG; break; default: break; } return 1; } int dns_packet_validate_query(DnsPacket *p) { int r; assert(p); r = dns_packet_validate(p); if (r < 0) return r; if (DNS_PACKET_QR(p) != 0) return 0; if (DNS_PACKET_OPCODE(p) != 0) return -EBADMSG; if (DNS_PACKET_TC(p)) return -EBADMSG; switch (p->protocol) { case DNS_PROTOCOL_LLMNR: /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */ if (DNS_PACKET_QDCOUNT(p) != 1) return -EBADMSG; /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */ if (DNS_PACKET_ANCOUNT(p) > 0) return -EBADMSG; /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */ if (DNS_PACKET_NSCOUNT(p) > 0) return -EBADMSG; break; case DNS_PROTOCOL_MDNS: /* RFC 6762, Section 18 */ if (DNS_PACKET_AA(p) != 0 || DNS_PACKET_RD(p) != 0 || DNS_PACKET_RA(p) != 0 || DNS_PACKET_AD(p) != 0 || DNS_PACKET_CD(p) != 0 || DNS_PACKET_RCODE(p) != 0) return -EBADMSG; break; default: break; } return 1; } static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) { assert(p); if (p->size + add > p->allocated) { size_t a; a = PAGE_ALIGN((p->size + add) * 2); if (a > DNS_PACKET_SIZE_MAX) a = DNS_PACKET_SIZE_MAX; if (p->size + add > a) return -EMSGSIZE; if (p->_data) { void *d; d = realloc(p->_data, a); if (!d) return -ENOMEM; p->_data = d; } else { p->_data = malloc(a); if (!p->_data) return -ENOMEM; memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size); memzero((uint8_t*) p->_data + p->size, a - p->size); } p->allocated = a; } if (start) *start = p->size; if (ret) *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size; p->size += add; return 0; } void dns_packet_truncate(DnsPacket *p, size_t sz) { Iterator i; char *s; void *n; assert(p); if (p->size <= sz) return; HASHMAP_FOREACH_KEY(n, s, p->names, i) { if (PTR_TO_SIZE(n) < sz) continue; hashmap_remove(p->names, s); free(s); } p->size = sz; } int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) { void *q; int r; assert(p); r = dns_packet_extend(p, l, &q, start); if (r < 0) return r; memcpy(q, d, l); return 0; } int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) { void *d; int r; assert(p); r = dns_packet_extend(p, sizeof(uint8_t), &d, start); if (r < 0) return r; ((uint8_t*) d)[0] = v; return 0; } int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) { void *d; int r; assert(p); r = dns_packet_extend(p, sizeof(uint16_t), &d, start); if (r < 0) return r; unaligned_write_be16(d, v); return 0; } int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) { void *d; int r; assert(p); r = dns_packet_extend(p, sizeof(uint32_t), &d, start); if (r < 0) return r; unaligned_write_be32(d, v); return 0; } int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) { assert(p); assert(s); return dns_packet_append_raw_string(p, s, strlen(s), start); } int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start) { void *d; int r; assert(p); assert(s || size == 0); if (size > 255) return -E2BIG; r = dns_packet_extend(p, 1 + size, &d, start); if (r < 0) return r; ((uint8_t*) d)[0] = (uint8_t) size; if (size > 0) memcpy(((uint8_t*) d) + 1, s, size); return 0; } int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, bool canonical_candidate, size_t *start) { uint8_t *w; int r; /* Append a label to a packet. Optionally, does this in DNSSEC * canonical form, if this label is marked as a candidate for * it, and the canonical form logic is enabled for the * packet */ assert(p); assert(d); if (l > DNS_LABEL_MAX) return -E2BIG; r = dns_packet_extend(p, 1 + l, (void**) &w, start); if (r < 0) return r; *(w++) = (uint8_t) l; if (p->canonical_form && canonical_candidate) { size_t i; /* Generate in canonical form, as defined by DNSSEC * RFC 4034, Section 6.2, i.e. all lower-case. */ for (i = 0; i < l; i++) w[i] = (uint8_t) ascii_tolower(d[i]); } else /* Otherwise, just copy the string unaltered. This is * essential for DNS-SD, where the casing of labels * matters and needs to be retained. */ memcpy(w, d, l); return 0; } int dns_packet_append_name( DnsPacket *p, const char *name, bool allow_compression, bool canonical_candidate, size_t *start) { size_t saved_size; int r; assert(p); assert(name); if (p->refuse_compression) allow_compression = false; saved_size = p->size; while (!dns_name_is_root(name)) { const char *z = name; char label[DNS_LABEL_MAX]; size_t n = 0; if (allow_compression) n = PTR_TO_SIZE(hashmap_get(p->names, name)); if (n > 0) { assert(n < p->size); if (n < 0x4000) { r = dns_packet_append_uint16(p, 0xC000 | n, NULL); if (r < 0) goto fail; goto done; } } r = dns_label_unescape(&name, label, sizeof(label)); if (r < 0) goto fail; r = dns_packet_append_label(p, label, r, canonical_candidate, &n); if (r < 0) goto fail; if (allow_compression) { _cleanup_free_ char *s = NULL; s = strdup(z); if (!s) { r = -ENOMEM; goto fail; } r = hashmap_ensure_allocated(&p->names, &dns_name_hash_ops); if (r < 0) goto fail; r = hashmap_put(p->names, s, SIZE_TO_PTR(n)); if (r < 0) goto fail; s = NULL; } } r = dns_packet_append_uint8(p, 0, NULL); if (r < 0) return r; done: if (start) *start = saved_size; return 0; fail: dns_packet_truncate(p, saved_size); return r; } int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) { size_t saved_size; int r; assert(p); assert(k); saved_size = p->size; r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, true, NULL); if (r < 0) goto fail; r = dns_packet_append_uint16(p, k->type, NULL); if (r < 0) goto fail; r = dns_packet_append_uint16(p, k->class, NULL); if (r < 0) goto fail; if (start) *start = saved_size; return 0; fail: dns_packet_truncate(p, saved_size); return r; } static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, const uint8_t *types, size_t *start) { size_t saved_size; int r; assert(p); assert(types); assert(length > 0); saved_size = p->size; r = dns_packet_append_uint8(p, window, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, length, NULL); if (r < 0) goto fail; r = dns_packet_append_blob(p, types, length, NULL); if (r < 0) goto fail; if (start) *start = saved_size; return 0; fail: dns_packet_truncate(p, saved_size); return r; } static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) { Iterator i; uint8_t window = 0; uint8_t entry = 0; uint8_t bitmaps[32] = {}; unsigned n; size_t saved_size; int r; assert(p); saved_size = p->size; BITMAP_FOREACH(n, types, i) { assert(n <= 0xffff); if ((n >> 8) != window && bitmaps[entry / 8] != 0) { r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL); if (r < 0) goto fail; zero(bitmaps); } window = n >> 8; entry = n & 255; bitmaps[entry / 8] |= 1 << (7 - (entry % 8)); } if (bitmaps[entry / 8] != 0) { r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL); if (r < 0) goto fail; } if (start) *start = saved_size; return 0; fail: dns_packet_truncate(p, saved_size); return r; } /* Append the OPT pseudo-RR described in RFC6891 */ int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start) { size_t saved_size; int r; assert(p); /* we must never advertise supported packet size smaller than the legacy max */ assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX); if (p->opt_start != (size_t) -1) return -EBUSY; assert(p->opt_size == (size_t) -1); saved_size = p->size; /* empty name */ r = dns_packet_append_uint8(p, 0, NULL); if (r < 0) return r; /* type */ r = dns_packet_append_uint16(p, DNS_TYPE_OPT, NULL); if (r < 0) goto fail; /* maximum udp packet that can be received */ r = dns_packet_append_uint16(p, max_udp_size, NULL); if (r < 0) goto fail; /* extended RCODE and VERSION */ r = dns_packet_append_uint16(p, 0, NULL); if (r < 0) goto fail; /* flags: DNSSEC OK (DO), see RFC3225 */ r = dns_packet_append_uint16(p, edns0_do ? EDNS0_OPT_DO : 0, NULL); if (r < 0) goto fail; /* RDLENGTH */ if (edns0_do) { /* If DO is on, also append RFC6975 Algorithm data */ static const uint8_t rfc6975[] = { 0, 5, /* OPTION_CODE: DAU */ 0, 6, /* LIST_LENGTH */ DNSSEC_ALGORITHM_RSASHA1, DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1, DNSSEC_ALGORITHM_RSASHA256, DNSSEC_ALGORITHM_RSASHA512, DNSSEC_ALGORITHM_ECDSAP256SHA256, DNSSEC_ALGORITHM_ECDSAP384SHA384, 0, 6, /* OPTION_CODE: DHU */ 0, 3, /* LIST_LENGTH */ DNSSEC_DIGEST_SHA1, DNSSEC_DIGEST_SHA256, DNSSEC_DIGEST_SHA384, 0, 7, /* OPTION_CODE: N3U */ 0, 1, /* LIST_LENGTH */ NSEC3_ALGORITHM_SHA1, }; r = dns_packet_append_uint16(p, sizeof(rfc6975), NULL); if (r < 0) goto fail; r = dns_packet_append_blob(p, rfc6975, sizeof(rfc6975), NULL); } else r = dns_packet_append_uint16(p, 0, NULL); if (r < 0) goto fail; DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) + 1); p->opt_start = saved_size; p->opt_size = p->size - saved_size; if (start) *start = saved_size; return 0; fail: dns_packet_truncate(p, saved_size); return r; } int dns_packet_truncate_opt(DnsPacket *p) { assert(p); if (p->opt_start == (size_t) -1) { assert(p->opt_size == (size_t) -1); return 0; } assert(p->opt_size != (size_t) -1); assert(DNS_PACKET_ARCOUNT(p) > 0); if (p->opt_start + p->opt_size != p->size) return -EBUSY; dns_packet_truncate(p, p->opt_start); DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) - 1); p->opt_start = p->opt_size = (size_t) -1; return 1; } int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start, size_t *rdata_start) { size_t saved_size, rdlength_offset, end, rdlength, rds; int r; assert(p); assert(rr); saved_size = p->size; r = dns_packet_append_key(p, rr->key, NULL); if (r < 0) goto fail; r = dns_packet_append_uint32(p, rr->ttl, NULL); if (r < 0) goto fail; /* Initially we write 0 here */ r = dns_packet_append_uint16(p, 0, &rdlength_offset); if (r < 0) goto fail; rds = p->size - saved_size; switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { case DNS_TYPE_SRV: r = dns_packet_append_uint16(p, rr->srv.priority, NULL); if (r < 0) goto fail; r = dns_packet_append_uint16(p, rr->srv.weight, NULL); if (r < 0) goto fail; r = dns_packet_append_uint16(p, rr->srv.port, NULL); if (r < 0) goto fail; r = dns_packet_append_name(p, rr->srv.name, true, false, NULL); break; case DNS_TYPE_PTR: case DNS_TYPE_NS: case DNS_TYPE_CNAME: case DNS_TYPE_DNAME: r = dns_packet_append_name(p, rr->ptr.name, true, false, NULL); break; case DNS_TYPE_HINFO: r = dns_packet_append_string(p, rr->hinfo.cpu, NULL); if (r < 0) goto fail; r = dns_packet_append_string(p, rr->hinfo.os, NULL); break; case DNS_TYPE_SPF: /* exactly the same as TXT */ case DNS_TYPE_TXT: if (!rr->txt.items) { /* RFC 6763, section 6.1 suggests to generate * single empty string for an empty array. */ r = dns_packet_append_raw_string(p, NULL, 0, NULL); if (r < 0) goto fail; } else { DnsTxtItem *i; LIST_FOREACH(items, i, rr->txt.items) { r = dns_packet_append_raw_string(p, i->data, i->length, NULL); if (r < 0) goto fail; } } r = 0; break; case DNS_TYPE_A: r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL); break; case DNS_TYPE_AAAA: r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL); break; case DNS_TYPE_SOA: r = dns_packet_append_name(p, rr->soa.mname, true, false, NULL); if (r < 0) goto fail; r = dns_packet_append_name(p, rr->soa.rname, true, false, NULL); if (r < 0) goto fail; r = dns_packet_append_uint32(p, rr->soa.serial, NULL); if (r < 0) goto fail; r = dns_packet_append_uint32(p, rr->soa.refresh, NULL); if (r < 0) goto fail; r = dns_packet_append_uint32(p, rr->soa.retry, NULL); if (r < 0) goto fail; r = dns_packet_append_uint32(p, rr->soa.expire, NULL); if (r < 0) goto fail; r = dns_packet_append_uint32(p, rr->soa.minimum, NULL); break; case DNS_TYPE_MX: r = dns_packet_append_uint16(p, rr->mx.priority, NULL); if (r < 0) goto fail; r = dns_packet_append_name(p, rr->mx.exchange, true, false, NULL); break; case DNS_TYPE_LOC: r = dns_packet_append_uint8(p, rr->loc.version, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->loc.size, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL); if (r < 0) goto fail; r = dns_packet_append_uint32(p, rr->loc.latitude, NULL); if (r < 0) goto fail; r = dns_packet_append_uint32(p, rr->loc.longitude, NULL); if (r < 0) goto fail; r = dns_packet_append_uint32(p, rr->loc.altitude, NULL); break; case DNS_TYPE_DS: r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL); if (r < 0) goto fail; r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL); break; case DNS_TYPE_SSHFP: r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL); if (r < 0) goto fail; r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL); break; case DNS_TYPE_DNSKEY: r = dns_packet_append_uint16(p, rr->dnskey.flags, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->dnskey.protocol, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL); if (r < 0) goto fail; r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL); break; case DNS_TYPE_RRSIG: r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL); if (r < 0) goto fail; r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL); if (r < 0) goto fail; r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL); if (r < 0) goto fail; r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL); if (r < 0) goto fail; r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL); if (r < 0) goto fail; r = dns_packet_append_name(p, rr->rrsig.signer, false, true, NULL); if (r < 0) goto fail; r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL); break; case DNS_TYPE_NSEC: r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, false, NULL); if (r < 0) goto fail; r = dns_packet_append_types(p, rr->nsec.types, NULL); if (r < 0) goto fail; break; case DNS_TYPE_NSEC3: r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL); if (r < 0) goto fail; r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL); if (r < 0) goto fail; r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL); if (r < 0) goto fail; r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL); if (r < 0) goto fail; r = dns_packet_append_types(p, rr->nsec3.types, NULL); if (r < 0) goto fail; break; case DNS_TYPE_TLSA: r = dns_packet_append_uint8(p, rr->tlsa.cert_usage, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->tlsa.selector, NULL); if (r < 0) goto fail; r = dns_packet_append_uint8(p, rr->tlsa.matching_type, NULL); if (r < 0) goto fail; r = dns_packet_append_blob(p, rr->tlsa.data, rr->tlsa.data_size, NULL); break; case DNS_TYPE_OPT: case DNS_TYPE_OPENPGPKEY: case _DNS_TYPE_INVALID: /* unparseable */ default: r = dns_packet_append_blob(p, rr->generic.data, rr->generic.data_size, NULL); break; } if (r < 0) goto fail; /* Let's calculate the actual data size and update the field */ rdlength = p->size - rdlength_offset - sizeof(uint16_t); if (rdlength > 0xFFFF) { r = -ENOSPC; goto fail; } end = p->size; p->size = rdlength_offset; r = dns_packet_append_uint16(p, rdlength, NULL); if (r < 0) goto fail; p->size = end; if (start) *start = saved_size; if (rdata_start) *rdata_start = rds; return 0; fail: dns_packet_truncate(p, saved_size); return r; } int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) { assert(p); if (p->rindex + sz > p->size) return -EMSGSIZE; if (ret) *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex; if (start) *start = p->rindex; p->rindex += sz; return 0; } void dns_packet_rewind(DnsPacket *p, size_t idx) { assert(p); assert(idx <= p->size); assert(idx >= DNS_PACKET_HEADER_SIZE); p->rindex = idx; } int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) { const void *q; int r; assert(p); assert(d); r = dns_packet_read(p, sz, &q, start); if (r < 0) return r; memcpy(d, q, sz); return 0; } static int dns_packet_read_memdup( DnsPacket *p, size_t size, void **ret, size_t *ret_size, size_t *ret_start) { const void *src; size_t start; int r; assert(p); assert(ret); r = dns_packet_read(p, size, &src, &start); if (r < 0) return r; if (size <= 0) *ret = NULL; else { void *copy; copy = memdup(src, size); if (!copy) return -ENOMEM; *ret = copy; } if (ret_size) *ret_size = size; if (ret_start) *ret_start = start; return 0; } int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) { const void *d; int r; assert(p); r = dns_packet_read(p, sizeof(uint8_t), &d, start); if (r < 0) return r; *ret = ((uint8_t*) d)[0]; return 0; } int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) { const void *d; int r; assert(p); r = dns_packet_read(p, sizeof(uint16_t), &d, start); if (r < 0) return r; *ret = unaligned_read_be16(d); return 0; } int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) { const void *d; int r; assert(p); r = dns_packet_read(p, sizeof(uint32_t), &d, start); if (r < 0) return r; *ret = unaligned_read_be32(d); return 0; } int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) { size_t saved_rindex; const void *d; char *t; uint8_t c; int r; assert(p); saved_rindex = p->rindex; r = dns_packet_read_uint8(p, &c, NULL); if (r < 0) goto fail; r = dns_packet_read(p, c, &d, NULL); if (r < 0) goto fail; if (memchr(d, 0, c)) { r = -EBADMSG; goto fail; } t = strndup(d, c); if (!t) { r = -ENOMEM; goto fail; } if (!utf8_is_valid(t)) { free(t); r = -EBADMSG; goto fail; } *ret = t; if (start) *start = saved_rindex; return 0; fail: dns_packet_rewind(p, saved_rindex); return r; } int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start) { size_t saved_rindex; uint8_t c; int r; assert(p); saved_rindex = p->rindex; r = dns_packet_read_uint8(p, &c, NULL); if (r < 0) goto fail; r = dns_packet_read(p, c, ret, NULL); if (r < 0) goto fail; if (size) *size = c; if (start) *start = saved_rindex; return 0; fail: dns_packet_rewind(p, saved_rindex); return r; } int dns_packet_read_name( DnsPacket *p, char **_ret, bool allow_compression, size_t *start) { size_t saved_rindex, after_rindex = 0, jump_barrier; _cleanup_free_ char *ret = NULL; size_t n = 0, allocated = 0; bool first = true; int r; assert(p); assert(_ret); if (p->refuse_compression) allow_compression = false; saved_rindex = p->rindex; jump_barrier = p->rindex; for (;;) { uint8_t c, d; r = dns_packet_read_uint8(p, &c, NULL); if (r < 0) goto fail; if (c == 0) /* End of name */ break; else if (c <= 63) { const char *label; /* Literal label */ r = dns_packet_read(p, c, (const void**) &label, NULL); if (r < 0) goto fail; if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) { r = -ENOMEM; goto fail; } if (first) first = false; else ret[n++] = '.'; r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX); if (r < 0) goto fail; n += r; continue; } else if (allow_compression && (c & 0xc0) == 0xc0) { uint16_t ptr; /* Pointer */ r = dns_packet_read_uint8(p, &d, NULL); if (r < 0) goto fail; ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d; if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) { r = -EBADMSG; goto fail; } if (after_rindex == 0) after_rindex = p->rindex; /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */ jump_barrier = ptr; p->rindex = ptr; } else { r = -EBADMSG; goto fail; } } if (!GREEDY_REALLOC(ret, allocated, n + 1)) { r = -ENOMEM; goto fail; } ret[n] = 0; if (after_rindex != 0) p->rindex= after_rindex; *_ret = ret; ret = NULL; if (start) *start = saved_rindex; return 0; fail: dns_packet_rewind(p, saved_rindex); return r; } static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) { uint8_t window; uint8_t length; const uint8_t *bitmap; uint8_t bit = 0; unsigned i; bool found = false; size_t saved_rindex; int r; assert(p); assert(types); saved_rindex = p->rindex; r = bitmap_ensure_allocated(types); if (r < 0) goto fail; r = dns_packet_read_uint8(p, &window, NULL); if (r < 0) goto fail; r = dns_packet_read_uint8(p, &length, NULL); if (r < 0) goto fail; if (length == 0 || length > 32) return -EBADMSG; r = dns_packet_read(p, length, (const void **)&bitmap, NULL); if (r < 0) goto fail; for (i = 0; i < length; i++) { uint8_t bitmask = 1 << 7; if (!bitmap[i]) { found = false; bit += 8; continue; } found = true; while (bitmask) { if (bitmap[i] & bitmask) { uint16_t n; n = (uint16_t) window << 8 | (uint16_t) bit; /* Ignore pseudo-types. see RFC4034 section 4.1.2 */ if (dns_type_is_pseudo(n)) continue; r = bitmap_set(*types, n); if (r < 0) goto fail; } bit ++; bitmask >>= 1; } } if (!found) return -EBADMSG; if (start) *start = saved_rindex; return 0; fail: dns_packet_rewind(p, saved_rindex); return r; } static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) { size_t saved_rindex; int r; saved_rindex = p->rindex; while (p->rindex < saved_rindex + size) { r = dns_packet_read_type_window(p, types, NULL); if (r < 0) goto fail; /* don't read past end of current RR */ if (p->rindex > saved_rindex + size) { r = -EBADMSG; goto fail; } } if (p->rindex != saved_rindex + size) { r = -EBADMSG; goto fail; } if (start) *start = saved_rindex; return 0; fail: dns_packet_rewind(p, saved_rindex); return r; } int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start) { _cleanup_free_ char *name = NULL; bool cache_flush = false; uint16_t class, type; DnsResourceKey *key; size_t saved_rindex; int r; assert(p); assert(ret); saved_rindex = p->rindex; r = dns_packet_read_name(p, &name, true, NULL); if (r < 0) goto fail; r = dns_packet_read_uint16(p, &type, NULL); if (r < 0) goto fail; r = dns_packet_read_uint16(p, &class, NULL); if (r < 0) goto fail; if (p->protocol == DNS_PROTOCOL_MDNS) { /* See RFC6762, Section 10.2 */ if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH)) { class &= ~MDNS_RR_CACHE_FLUSH; cache_flush = true; } } key = dns_resource_key_new_consume(class, type, name); if (!key) { r = -ENOMEM; goto fail; } name = NULL; *ret = key; if (ret_cache_flush) *ret_cache_flush = cache_flush; if (start) *start = saved_rindex; return 0; fail: dns_packet_rewind(p, saved_rindex); return r; } static bool loc_size_ok(uint8_t size) { uint8_t m = size >> 4, e = size & 0xF; return m <= 9 && e <= 9 && (m > 0 || e == 0); } int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; size_t saved_rindex, offset; uint16_t rdlength; bool cache_flush; int r; assert(p); assert(ret); saved_rindex = p->rindex; r = dns_packet_read_key(p, &key, &cache_flush, NULL); if (r < 0) goto fail; if (!dns_class_is_valid_rr(key->class)|| !dns_type_is_valid_rr(key->type)) { r = -EBADMSG; goto fail; } rr = dns_resource_record_new(key); if (!rr) { r = -ENOMEM; goto fail; } r = dns_packet_read_uint32(p, &rr->ttl, NULL); if (r < 0) goto fail; /* RFC 2181, Section 8, suggests to * treat a TTL with the MSB set as a zero TTL. */ if (rr->ttl & UINT32_C(0x80000000)) rr->ttl = 0; r = dns_packet_read_uint16(p, &rdlength, NULL); if (r < 0) goto fail; if (p->rindex + rdlength > p->size) { r = -EBADMSG; goto fail; } offset = p->rindex; switch (rr->key->type) { case DNS_TYPE_SRV: r = dns_packet_read_uint16(p, &rr->srv.priority, NULL); if (r < 0) goto fail; r = dns_packet_read_uint16(p, &rr->srv.weight, NULL); if (r < 0) goto fail; r = dns_packet_read_uint16(p, &rr->srv.port, NULL); if (r < 0) goto fail; r = dns_packet_read_name(p, &rr->srv.name, true, NULL); break; case DNS_TYPE_PTR: case DNS_TYPE_NS: case DNS_TYPE_CNAME: case DNS_TYPE_DNAME: r = dns_packet_read_name(p, &rr->ptr.name, true, NULL); break; case DNS_TYPE_HINFO: r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL); if (r < 0) goto fail; r = dns_packet_read_string(p, &rr->hinfo.os, NULL); break; case DNS_TYPE_SPF: /* exactly the same as TXT */ case DNS_TYPE_TXT: if (rdlength <= 0) { DnsTxtItem *i; /* RFC 6763, section 6.1 suggests to treat * empty TXT RRs as equivalent to a TXT record * with a single empty string. */ i = malloc0(offsetof(DnsTxtItem, data) + 1); /* for safety reasons we add an extra NUL byte */ if (!i) return -ENOMEM; rr->txt.items = i; } else { DnsTxtItem *last = NULL; while (p->rindex < offset + rdlength) { DnsTxtItem *i; const void *data; size_t sz; r = dns_packet_read_raw_string(p, &data, &sz, NULL); if (r < 0) return r; i = malloc0(offsetof(DnsTxtItem, data) + sz + 1); /* extra NUL byte at the end */ if (!i) return -ENOMEM; memcpy(i->data, data, sz); i->length = sz; LIST_INSERT_AFTER(items, rr->txt.items, last, i); last = i; } } r = 0; break; case DNS_TYPE_A: r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL); break; case DNS_TYPE_AAAA: r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL); break; case DNS_TYPE_SOA: r = dns_packet_read_name(p, &rr->soa.mname, true, NULL); if (r < 0) goto fail; r = dns_packet_read_name(p, &rr->soa.rname, true, NULL); if (r < 0) goto fail; r = dns_packet_read_uint32(p, &rr->soa.serial, NULL); if (r < 0) goto fail; r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL); if (r < 0) goto fail; r = dns_packet_read_uint32(p, &rr->soa.retry, NULL); if (r < 0) goto fail; r = dns_packet_read_uint32(p, &rr->soa.expire, NULL); if (r < 0) goto fail; r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL); break; case DNS_TYPE_MX: r = dns_packet_read_uint16(p, &rr->mx.priority, NULL); if (r < 0) goto fail; r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL); break; case DNS_TYPE_LOC: { uint8_t t; size_t pos; r = dns_packet_read_uint8(p, &t, &pos); if (r < 0) goto fail; if (t == 0) { rr->loc.version = t; r = dns_packet_read_uint8(p, &rr->loc.size, NULL); if (r < 0) goto fail; if (!loc_size_ok(rr->loc.size)) { r = -EBADMSG; goto fail; } r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL); if (r < 0) goto fail; if (!loc_size_ok(rr->loc.horiz_pre)) { r = -EBADMSG; goto fail; } r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL); if (r < 0) goto fail; if (!loc_size_ok(rr->loc.vert_pre)) { r = -EBADMSG; goto fail; } r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL); if (r < 0) goto fail; r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL); if (r < 0) goto fail; r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL); if (r < 0) goto fail; break; } else { dns_packet_rewind(p, pos); rr->unparseable = true; goto unparseable; } } case DNS_TYPE_DS: r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL); if (r < 0) goto fail; r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL); if (r < 0) goto fail; r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL); if (r < 0) goto fail; r = dns_packet_read_memdup(p, rdlength - 4, &rr->ds.digest, &rr->ds.digest_size, NULL); if (r < 0) goto fail; if (rr->ds.digest_size <= 0) { /* the accepted size depends on the algorithm, but for now just ensure that the value is greater than zero */ r = -EBADMSG; goto fail; } break; case DNS_TYPE_SSHFP: r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL); if (r < 0) goto fail; r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL); if (r < 0) goto fail; r = dns_packet_read_memdup(p, rdlength - 2, &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size, NULL); if (rr->sshfp.fingerprint_size <= 0) { /* the accepted size depends on the algorithm, but for now just ensure that the value is greater than zero */ r = -EBADMSG; goto fail; } break; case DNS_TYPE_DNSKEY: r = dns_packet_read_uint16(p, &rr->dnskey.flags, NULL); if (r < 0) goto fail; r = dns_packet_read_uint8(p, &rr->dnskey.protocol, NULL); if (r < 0) goto fail; r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL); if (r < 0) goto fail; r = dns_packet_read_memdup(p, rdlength - 4, &rr->dnskey.key, &rr->dnskey.key_size, NULL); if (rr->dnskey.key_size <= 0) { /* the accepted size depends on the algorithm, but for now just ensure that the value is greater than zero */ r = -EBADMSG; goto fail; } break; case DNS_TYPE_RRSIG: r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL); if (r < 0) goto fail; r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL); if (r < 0) goto fail; r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL); if (r < 0) goto fail; r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL); if (r < 0) goto fail; r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL); if (r < 0) goto fail; r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL); if (r < 0) goto fail; r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL); if (r < 0) goto fail; r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL); if (r < 0) goto fail; r = dns_packet_read_memdup(p, offset + rdlength - p->rindex, &rr->rrsig.signature, &rr->rrsig.signature_size, NULL); if (rr->rrsig.signature_size <= 0) { /* the accepted size depends on the algorithm, but for now just ensure that the value is greater than zero */ r = -EBADMSG; goto fail; } break; case DNS_TYPE_NSEC: { /* * RFC6762, section 18.14 explictly states mDNS should use name compression. * This contradicts RFC3845, section 2.1.1 */ bool allow_compressed = p->protocol == DNS_PROTOCOL_MDNS; r = dns_packet_read_name(p, &rr->nsec.next_domain_name, allow_compressed, NULL); if (r < 0) goto fail; r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL); if (r < 0) goto fail; /* We accept empty NSEC bitmaps. The bit indicating the presence of the NSEC record itself * is redundant and in e.g., RFC4956 this fact is used to define a use for NSEC records * without the NSEC bit set. */ break; } case DNS_TYPE_NSEC3: { uint8_t size; r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL); if (r < 0) goto fail; r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL); if (r < 0) goto fail; r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL); if (r < 0) goto fail; /* this may be zero */ r = dns_packet_read_uint8(p, &size, NULL); if (r < 0) goto fail; r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL); if (r < 0) goto fail; r = dns_packet_read_uint8(p, &size, NULL); if (r < 0) goto fail; if (size <= 0) { r = -EBADMSG; goto fail; } r = dns_packet_read_memdup(p, size, &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, NULL); if (r < 0) goto fail; r = dns_packet_read_type_windows(p, &rr->nsec3.types, offset + rdlength - p->rindex, NULL); if (r < 0) goto fail; /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */ break; } case DNS_TYPE_TLSA: r = dns_packet_read_uint8(p, &rr->tlsa.cert_usage, NULL); if (r < 0) goto fail; r = dns_packet_read_uint8(p, &rr->tlsa.selector, NULL); if (r < 0) goto fail; r = dns_packet_read_uint8(p, &rr->tlsa.matching_type, NULL); if (r < 0) goto fail; r = dns_packet_read_memdup(p, rdlength - 3, &rr->tlsa.data, &rr->tlsa.data_size, NULL); if (rr->tlsa.data_size <= 0) { /* the accepted size depends on the algorithm, but for now just ensure that the value is greater than zero */ r = -EBADMSG; goto fail; } break; case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */ case DNS_TYPE_OPENPGPKEY: default: unparseable: r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.data_size, NULL); if (r < 0) goto fail; break; } if (r < 0) goto fail; if (p->rindex != offset + rdlength) { r = -EBADMSG; goto fail; } *ret = rr; rr = NULL; if (ret_cache_flush) *ret_cache_flush = cache_flush; if (start) *start = saved_rindex; return 0; fail: dns_packet_rewind(p, saved_rindex); return r; } static bool opt_is_good(DnsResourceRecord *rr, bool *rfc6975) { const uint8_t* p; bool found_dau_dhu_n3u = false; size_t l; /* Checks whether the specified OPT RR is well-formed and whether it contains RFC6975 data (which is not OK in * a reply). */ assert(rr); assert(rr->key->type == DNS_TYPE_OPT); /* Check that the version is 0 */ if (((rr->ttl >> 16) & UINT32_C(0xFF)) != 0) return false; p = rr->opt.data; l = rr->opt.data_size; while (l > 0) { uint16_t option_code, option_length; /* At least four bytes for OPTION-CODE and OPTION-LENGTH are required */ if (l < 4U) return false; option_code = unaligned_read_be16(p); option_length = unaligned_read_be16(p + 2); if (l < option_length + 4U) return false; /* RFC 6975 DAU, DHU or N3U fields found. */ if (IN_SET(option_code, 5, 6, 7)) found_dau_dhu_n3u = true; p += option_length + 4U; l -= option_length + 4U; } *rfc6975 = found_dau_dhu_n3u; return true; } int dns_packet_extract(DnsPacket *p) { _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL; _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; size_t saved_rindex; unsigned n, i; int r; if (p->extracted) return 0; saved_rindex = p->rindex; dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE); n = DNS_PACKET_QDCOUNT(p); if (n > 0) { question = dns_question_new(n); if (!question) { r = -ENOMEM; goto finish; } for (i = 0; i < n; i++) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; bool cache_flush; r = dns_packet_read_key(p, &key, &cache_flush, NULL); if (r < 0) goto finish; if (cache_flush) { r = -EBADMSG; goto finish; } if (!dns_type_is_valid_query(key->type)) { r = -EBADMSG; goto finish; } r = dns_question_add(question, key); if (r < 0) goto finish; } } n = DNS_PACKET_RRCOUNT(p); if (n > 0) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *previous = NULL; bool bad_opt = false; answer = dns_answer_new(n); if (!answer) { r = -ENOMEM; goto finish; } for (i = 0; i < n; i++) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; bool cache_flush; r = dns_packet_read_rr(p, &rr, &cache_flush, NULL); if (r < 0) goto finish; /* Try to reduce memory usage a bit */ if (previous) dns_resource_key_reduce(&rr->key, &previous->key); if (rr->key->type == DNS_TYPE_OPT) { bool has_rfc6975; if (p->opt || bad_opt) { /* Multiple OPT RRs? if so, let's ignore all, because there's something wrong * with the server, and if one is valid we wouldn't know which one. */ log_debug("Multiple OPT RRs detected, ignoring all."); bad_opt = true; continue; } if (!dns_name_is_root(DNS_RESOURCE_KEY_NAME(rr->key))) { /* If the OPT RR is not owned by the root domain, then it is bad, let's ignore * it. */ log_debug("OPT RR is not owned by root domain, ignoring."); bad_opt = true; continue; } if (i < DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)) { /* OPT RR is in the wrong section? Some Belkin routers do this. This is a hint * the EDNS implementation is borked, like the Belkin one is, hence ignore * it. */ log_debug("OPT RR in wrong section, ignoring."); bad_opt = true; continue; } if (!opt_is_good(rr, &has_rfc6975)) { log_debug("Malformed OPT RR, ignoring."); bad_opt = true; continue; } if (has_rfc6975) { /* If the OPT RR contains RFC6975 algorithm data, then this is indication that * the server just copied the OPT it got from us (which contained that data) * back into the reply. If so, then it doesn't properly support EDNS, as * RFC6975 makes it very clear that the algorithm data should only be contained * in questions, never in replies. Crappy Belkin routers copy the OPT data for * example, hence let's detect this so that we downgrade early. */ log_debug("OPT RR contained RFC6975 data, ignoring."); bad_opt = true; continue; } p->opt = dns_resource_record_ref(rr); } else { /* According to RFC 4795, section 2.9. only the RRs from the Answer section shall be * cached. Hence mark only those RRs as cacheable by default, but not the ones from the * Additional or Authority sections. */ r = dns_answer_add(answer, rr, p->ifindex, (i < DNS_PACKET_ANCOUNT(p) ? DNS_ANSWER_CACHEABLE : 0) | (p->protocol == DNS_PROTOCOL_MDNS && !cache_flush ? DNS_ANSWER_SHARED_OWNER : 0)); if (r < 0) goto finish; } /* Remember this RR, so that we potentically can merge it's ->key object with the next RR. Note * that we only do this if we actually decided to keep the RR around. */ dns_resource_record_unref(previous); previous = dns_resource_record_ref(rr); } if (bad_opt) p->opt = dns_resource_record_unref(p->opt); } p->question = question; question = NULL; p->answer = answer; answer = NULL; p->extracted = true; r = 0; finish: p->rindex = saved_rindex; return r; } int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) { int r; assert(p); assert(key); /* Checks if the specified packet is a reply for the specified * key and the specified key is the only one in the question * section. */ if (DNS_PACKET_QR(p) != 1) return 0; /* Let's unpack the packet, if that hasn't happened yet. */ r = dns_packet_extract(p); if (r < 0) return r; if (p->question->n_keys != 1) return 0; return dns_resource_key_equal(p->question->keys[0], key); } static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = { [DNS_RCODE_SUCCESS] = "SUCCESS", [DNS_RCODE_FORMERR] = "FORMERR", [DNS_RCODE_SERVFAIL] = "SERVFAIL", [DNS_RCODE_NXDOMAIN] = "NXDOMAIN", [DNS_RCODE_NOTIMP] = "NOTIMP", [DNS_RCODE_REFUSED] = "REFUSED", [DNS_RCODE_YXDOMAIN] = "YXDOMAIN", [DNS_RCODE_YXRRSET] = "YRRSET", [DNS_RCODE_NXRRSET] = "NXRRSET", [DNS_RCODE_NOTAUTH] = "NOTAUTH", [DNS_RCODE_NOTZONE] = "NOTZONE", [DNS_RCODE_BADVERS] = "BADVERS", [DNS_RCODE_BADKEY] = "BADKEY", [DNS_RCODE_BADTIME] = "BADTIME", [DNS_RCODE_BADMODE] = "BADMODE", [DNS_RCODE_BADNAME] = "BADNAME", [DNS_RCODE_BADALG] = "BADALG", [DNS_RCODE_BADTRUNC] = "BADTRUNC", }; DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int); static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = { [DNS_PROTOCOL_DNS] = "dns", [DNS_PROTOCOL_MDNS] = "mdns", [DNS_PROTOCOL_LLMNR] = "llmnr", }; DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol); systemd-229/src/resolve/resolved-dns-packet.h000066400000000000000000000245451265713322000213640ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "hashmap.h" #include "in-addr-util.h" #include "macro.h" #include "sparse-endian.h" typedef struct DnsPacketHeader DnsPacketHeader; typedef struct DnsPacket DnsPacket; #include "resolved-def.h" #include "resolved-dns-answer.h" #include "resolved-dns-question.h" #include "resolved-dns-rr.h" typedef enum DnsProtocol { DNS_PROTOCOL_DNS, DNS_PROTOCOL_MDNS, DNS_PROTOCOL_LLMNR, _DNS_PROTOCOL_MAX, _DNS_PROTOCOL_INVALID = -1 } DnsProtocol; struct DnsPacketHeader { uint16_t id; be16_t flags; be16_t qdcount; be16_t ancount; be16_t nscount; be16_t arcount; }; #define DNS_PACKET_HEADER_SIZE sizeof(DnsPacketHeader) #define UDP_PACKET_HEADER_SIZE (sizeof(struct iphdr) + sizeof(struct udphdr)) /* The various DNS protocols deviate in how large a packet can grow, but the TCP transport has a 16bit size field, hence that appears to be the absolute maximum. */ #define DNS_PACKET_SIZE_MAX 0xFFFF /* RFC 1035 say 512 is the maximum, for classic unicast DNS */ #define DNS_PACKET_UNICAST_SIZE_MAX 512 /* With EDNS0 we can use larger packets, default to 4096, which is what is commonly used */ #define DNS_PACKET_UNICAST_SIZE_LARGE_MAX 4096 #define DNS_PACKET_SIZE_START 512 struct DnsPacket { int n_ref; DnsProtocol protocol; size_t size, allocated, rindex; void *_data; /* don't access directly, use DNS_PACKET_DATA()! */ Hashmap *names; /* For name compression */ size_t opt_start, opt_size; /* Parsed data */ DnsQuestion *question; DnsAnswer *answer; DnsResourceRecord *opt; /* Packet reception metadata */ int ifindex; int family, ipproto; union in_addr_union sender, destination; uint16_t sender_port, destination_port; uint32_t ttl; /* For support of truncated packets */ DnsPacket *more; bool on_stack:1; bool extracted:1; bool refuse_compression:1; bool canonical_form:1; }; static inline uint8_t* DNS_PACKET_DATA(DnsPacket *p) { if (_unlikely_(!p)) return NULL; if (p->_data) return p->_data; return ((uint8_t*) p) + ALIGN(sizeof(DnsPacket)); } #define DNS_PACKET_HEADER(p) ((DnsPacketHeader*) DNS_PACKET_DATA(p)) #define DNS_PACKET_ID(p) DNS_PACKET_HEADER(p)->id #define DNS_PACKET_QR(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 15) & 1) #define DNS_PACKET_OPCODE(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 11) & 15) #define DNS_PACKET_AA(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 10) & 1) #define DNS_PACKET_TC(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 9) & 1) #define DNS_PACKET_RD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 8) & 1) #define DNS_PACKET_RA(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 7) & 1) #define DNS_PACKET_AD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 5) & 1) #define DNS_PACKET_CD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 4) & 1) static inline uint16_t DNS_PACKET_RCODE(DnsPacket *p) { uint16_t rcode; if (p->opt) rcode = (uint16_t) (p->opt->ttl >> 24); else rcode = 0; return rcode | (be16toh(DNS_PACKET_HEADER(p)->flags) & 15); } /* LLMNR defines some bits differently */ #define DNS_PACKET_LLMNR_C(p) DNS_PACKET_AA(p) #define DNS_PACKET_LLMNR_T(p) DNS_PACKET_RD(p) #define DNS_PACKET_QDCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->qdcount) #define DNS_PACKET_ANCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->ancount) #define DNS_PACKET_NSCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->nscount) #define DNS_PACKET_ARCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->arcount) #define DNS_PACKET_MAKE_FLAGS(qr, opcode, aa, tc, rd, ra, ad, cd, rcode) \ (((uint16_t) !!(qr) << 15) | \ ((uint16_t) ((opcode) & 15) << 11) | \ ((uint16_t) !!(aa) << 10) | /* on LLMNR: c */ \ ((uint16_t) !!(tc) << 9) | \ ((uint16_t) !!(rd) << 8) | /* on LLMNR: t */ \ ((uint16_t) !!(ra) << 7) | \ ((uint16_t) !!(ad) << 5) | \ ((uint16_t) !!(cd) << 4) | \ ((uint16_t) ((rcode) & 15))) static inline unsigned DNS_PACKET_RRCOUNT(DnsPacket *p) { return (unsigned) DNS_PACKET_ANCOUNT(p) + (unsigned) DNS_PACKET_NSCOUNT(p) + (unsigned) DNS_PACKET_ARCOUNT(p); } int dns_packet_new(DnsPacket **p, DnsProtocol protocol, size_t mtu); int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled); void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated); DnsPacket *dns_packet_ref(DnsPacket *p); DnsPacket *dns_packet_unref(DnsPacket *p); DEFINE_TRIVIAL_CLEANUP_FUNC(DnsPacket*, dns_packet_unref); int dns_packet_validate(DnsPacket *p); int dns_packet_validate_reply(DnsPacket *p); int dns_packet_validate_query(DnsPacket *p); int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key); int dns_packet_append_blob(DnsPacket *p, const void *d, size_t sz, size_t *start); int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start); int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start); int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start); int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start); int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start); int dns_packet_append_label(DnsPacket *p, const char *s, size_t l, bool canonical_candidate, size_t *start); int dns_packet_append_name(DnsPacket *p, const char *name, bool allow_compression, bool canonical_candidate, size_t *start); int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *key, size_t *start); int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start, size_t *rdata_start); int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start); void dns_packet_truncate(DnsPacket *p, size_t sz); int dns_packet_truncate_opt(DnsPacket *p); int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start); int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start); int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start); int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start); int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start); int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start); int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start); int dns_packet_read_name(DnsPacket *p, char **ret, bool allow_compression, size_t *start); int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start); int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start); void dns_packet_rewind(DnsPacket *p, size_t idx); int dns_packet_skip_question(DnsPacket *p); int dns_packet_extract(DnsPacket *p); static inline bool DNS_PACKET_SHALL_CACHE(DnsPacket *p) { /* Never cache data originating from localhost, under the * assumption, that it's coming from a locally DNS forwarder * or server, that is caching on its own. */ return in_addr_is_localhost(p->family, &p->sender) == 0; } /* https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 */ enum { DNS_RCODE_SUCCESS = 0, DNS_RCODE_FORMERR = 1, DNS_RCODE_SERVFAIL = 2, DNS_RCODE_NXDOMAIN = 3, DNS_RCODE_NOTIMP = 4, DNS_RCODE_REFUSED = 5, DNS_RCODE_YXDOMAIN = 6, DNS_RCODE_YXRRSET = 7, DNS_RCODE_NXRRSET = 8, DNS_RCODE_NOTAUTH = 9, DNS_RCODE_NOTZONE = 10, DNS_RCODE_BADVERS = 16, DNS_RCODE_BADSIG = 16, /* duplicate value! */ DNS_RCODE_BADKEY = 17, DNS_RCODE_BADTIME = 18, DNS_RCODE_BADMODE = 19, DNS_RCODE_BADNAME = 20, DNS_RCODE_BADALG = 21, DNS_RCODE_BADTRUNC = 22, _DNS_RCODE_MAX_DEFINED }; const char* dns_rcode_to_string(int i) _const_; int dns_rcode_from_string(const char *s) _pure_; const char* dns_protocol_to_string(DnsProtocol p) _const_; DnsProtocol dns_protocol_from_string(const char *s) _pure_; #define LLMNR_MULTICAST_IPV4_ADDRESS ((struct in_addr) { .s_addr = htobe32(224U << 24 | 252U) }) #define LLMNR_MULTICAST_IPV6_ADDRESS ((struct in6_addr) { .s6_addr = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03 } }) #define MDNS_MULTICAST_IPV4_ADDRESS ((struct in_addr) { .s_addr = htobe32(224U << 24 | 251U) }) #define MDNS_MULTICAST_IPV6_ADDRESS ((struct in6_addr) { .s6_addr = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb } }) static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family, bool authenticated) { uint64_t f; /* Converts a protocol + family into a flags field as used in queries and responses */ f = authenticated ? SD_RESOLVED_AUTHENTICATED : 0; switch (protocol) { case DNS_PROTOCOL_DNS: return f|SD_RESOLVED_DNS; case DNS_PROTOCOL_LLMNR: return f|(family == AF_INET6 ? SD_RESOLVED_LLMNR_IPV6 : SD_RESOLVED_LLMNR_IPV4); case DNS_PROTOCOL_MDNS: return family == AF_INET6 ? SD_RESOLVED_MDNS_IPV6 : SD_RESOLVED_MDNS_IPV4; default: break; } return 0; } systemd-229/src/resolve/resolved-dns-query.c000066400000000000000000001020551265713322000212460ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "dns-domain.h" #include "dns-type.h" #include "hostname-util.h" #include "local-addresses.h" #include "resolved-dns-query.h" #include "resolved-dns-synthesize.h" #include "resolved-etc-hosts.h" #include "string-util.h" /* How long to wait for the query in total */ #define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC) #define CNAME_MAX 8 #define QUERIES_MAX 2048 #define AUXILIARY_QUERIES_MAX 64 static int dns_query_candidate_new(DnsQueryCandidate **ret, DnsQuery *q, DnsScope *s) { DnsQueryCandidate *c; assert(ret); assert(q); assert(s); c = new0(DnsQueryCandidate, 1); if (!c) return -ENOMEM; c->query = q; c->scope = s; LIST_PREPEND(candidates_by_query, q->candidates, c); LIST_PREPEND(candidates_by_scope, s->query_candidates, c); *ret = c; return 0; } static void dns_query_candidate_stop(DnsQueryCandidate *c) { DnsTransaction *t; assert(c); while ((t = set_steal_first(c->transactions))) { set_remove(t->notify_query_candidates, c); dns_transaction_gc(t); } } DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) { if (!c) return NULL; dns_query_candidate_stop(c); set_free(c->transactions); dns_search_domain_unref(c->search_domain); if (c->query) LIST_REMOVE(candidates_by_query, c->query->candidates, c); if (c->scope) LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c); free(c); return NULL; } static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) { DnsSearchDomain *next = NULL; assert(c); if (c->search_domain && c->search_domain->linked) next = c->search_domain->domains_next; else next = dns_scope_get_search_domains(c->scope); for (;;) { if (!next) /* We hit the end of the list */ return 0; if (!next->route_only) break; /* Skip over route-only domains */ next = next->domains_next; } dns_search_domain_unref(c->search_domain); c->search_domain = dns_search_domain_ref(next); return 1; } static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResourceKey *key) { DnsTransaction *t; int r; assert(c); assert(key); t = dns_scope_find_transaction(c->scope, key, true); if (!t) { r = dns_transaction_new(&t, c->scope, key); if (r < 0) return r; } else { if (set_contains(c->transactions, t)) return 0; } r = set_ensure_allocated(&c->transactions, NULL); if (r < 0) goto gc; r = set_ensure_allocated(&t->notify_query_candidates, NULL); if (r < 0) goto gc; r = set_put(t->notify_query_candidates, c); if (r < 0) goto gc; r = set_put(c->transactions, t); if (r < 0) { (void) set_remove(t->notify_query_candidates, c); goto gc; } return 1; gc: dns_transaction_gc(t); return r; } static int dns_query_candidate_go(DnsQueryCandidate *c) { DnsTransaction *t; Iterator i; int r; unsigned n = 0; assert(c); /* Start the transactions that are not started yet */ SET_FOREACH(t, c->transactions, i) { if (t->state != DNS_TRANSACTION_NULL) continue; r = dns_transaction_go(t); if (r < 0) return r; n++; } /* If there was nothing to start, then let's proceed immediately */ if (n == 0) dns_query_candidate_notify(c); return 0; } static DnsTransactionState dns_query_candidate_state(DnsQueryCandidate *c) { DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS; DnsTransaction *t; Iterator i; assert(c); if (c->error_code != 0) return DNS_TRANSACTION_ERRNO; SET_FOREACH(t, c->transactions, i) { switch (t->state) { case DNS_TRANSACTION_NULL: /* If there's a NULL transaction pending, then * this means not all transactions where * started yet, and we were called from within * the stackframe that is supposed to start * remaining transactions. In this case, * simply claim the candidate is pending. */ case DNS_TRANSACTION_PENDING: case DNS_TRANSACTION_VALIDATING: /* If there's one transaction currently in * VALIDATING state, then this means there's * also one in PENDING state, hence we can * return PENDING immediately. */ return DNS_TRANSACTION_PENDING; case DNS_TRANSACTION_SUCCESS: state = t->state; break; default: if (state != DNS_TRANSACTION_SUCCESS) state = t->state; break; } } return state; } static bool dns_query_candidate_is_routable(DnsQueryCandidate *c, uint16_t type) { int family; assert(c); /* Checks whether the specified RR type matches an address family that is routable on the link(s) the scope of * this candidate belongs to. Specifically, whether there's a routable IPv4 address on it if we query an A RR, * or a routable IPv6 address if we query an AAAA RR. */ if (!c->query->suppress_unroutable_family) return true; if (c->scope->protocol != DNS_PROTOCOL_DNS) return true; family = dns_type_to_af(type); if (family < 0) return true; if (c->scope->link) return link_relevant(c->scope->link, family, false); else return manager_routable(c->scope->manager, family); } static int dns_query_candidate_setup_transactions(DnsQueryCandidate *c) { DnsQuestion *question; DnsResourceKey *key; int n = 0, r; assert(c); dns_query_candidate_stop(c); question = dns_query_question_for_protocol(c->query, c->scope->protocol); /* Create one transaction per question key */ DNS_QUESTION_FOREACH(key, question) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *new_key = NULL; DnsResourceKey *qkey; if (!dns_query_candidate_is_routable(c, key->type)) continue; if (c->search_domain) { r = dns_resource_key_new_append_suffix(&new_key, key, c->search_domain->name); if (r < 0) goto fail; qkey = new_key; } else qkey = key; if (!dns_scope_good_key(c->scope, qkey)) continue; r = dns_query_candidate_add_transaction(c, qkey); if (r < 0) goto fail; n++; } return n; fail: dns_query_candidate_stop(c); return r; } void dns_query_candidate_notify(DnsQueryCandidate *c) { DnsTransactionState state; int r; assert(c); state = dns_query_candidate_state(c); if (DNS_TRANSACTION_IS_LIVE(state)) return; if (state != DNS_TRANSACTION_SUCCESS && c->search_domain) { r = dns_query_candidate_next_search_domain(c); if (r < 0) goto fail; if (r > 0) { /* OK, there's another search domain to try, let's do so. */ r = dns_query_candidate_setup_transactions(c); if (r < 0) goto fail; if (r > 0) { /* New transactions where queued. Start them and wait */ r = dns_query_candidate_go(c); if (r < 0) goto fail; return; } } } dns_query_ready(c->query); return; fail: log_warning_errno(r, "Failed to follow search domains: %m"); c->error_code = r; dns_query_ready(c->query); } static void dns_query_stop(DnsQuery *q) { DnsQueryCandidate *c; assert(q); q->timeout_event_source = sd_event_source_unref(q->timeout_event_source); LIST_FOREACH(candidates_by_query, c, q->candidates) dns_query_candidate_stop(c); } static void dns_query_free_candidates(DnsQuery *q) { assert(q); while (q->candidates) dns_query_candidate_free(q->candidates); } static void dns_query_reset_answer(DnsQuery *q) { assert(q); q->answer = dns_answer_unref(q->answer); q->answer_rcode = 0; q->answer_dnssec_result = _DNSSEC_RESULT_INVALID; q->answer_errno = 0; q->answer_authenticated = false; q->answer_protocol = _DNS_PROTOCOL_INVALID; q->answer_family = AF_UNSPEC; q->answer_search_domain = dns_search_domain_unref(q->answer_search_domain); } DnsQuery *dns_query_free(DnsQuery *q) { if (!q) return NULL; while (q->auxiliary_queries) dns_query_free(q->auxiliary_queries); if (q->auxiliary_for) { assert(q->auxiliary_for->n_auxiliary_queries > 0); q->auxiliary_for->n_auxiliary_queries--; LIST_REMOVE(auxiliary_queries, q->auxiliary_for->auxiliary_queries, q); } dns_query_free_candidates(q); dns_question_unref(q->question_idna); dns_question_unref(q->question_utf8); dns_query_reset_answer(q); sd_bus_message_unref(q->request); sd_bus_track_unref(q->bus_track); free(q->request_address_string); if (q->manager) { LIST_REMOVE(queries, q->manager->dns_queries, q); q->manager->n_dns_queries--; } free(q); return NULL; } int dns_query_new( Manager *m, DnsQuery **ret, DnsQuestion *question_utf8, DnsQuestion *question_idna, int ifindex, uint64_t flags) { _cleanup_(dns_query_freep) DnsQuery *q = NULL; DnsResourceKey *key; bool good = false; int r; assert(m); if (dns_question_size(question_utf8) > 0) { r = dns_question_is_valid_for_query(question_utf8); if (r < 0) return r; if (r == 0) return -EINVAL; good = true; } /* If the IDNA and UTF8 questions are the same, merge their references */ r = dns_question_is_equal(question_idna, question_utf8); if (r < 0) return r; if (r > 0) question_idna = question_utf8; else { if (dns_question_size(question_idna) > 0) { r = dns_question_is_valid_for_query(question_idna); if (r < 0) return r; if (r == 0) return -EINVAL; good = true; } } if (!good) /* don't allow empty queries */ return -EINVAL; if (m->n_dns_queries >= QUERIES_MAX) return -EBUSY; q = new0(DnsQuery, 1); if (!q) return -ENOMEM; q->question_utf8 = dns_question_ref(question_utf8); q->question_idna = dns_question_ref(question_idna); q->ifindex = ifindex; q->flags = flags; q->answer_dnssec_result = _DNSSEC_RESULT_INVALID; q->answer_protocol = _DNS_PROTOCOL_INVALID; q->answer_family = AF_UNSPEC; /* First dump UTF8 question */ DNS_QUESTION_FOREACH(key, question_utf8) { _cleanup_free_ char *p = NULL; r = dns_resource_key_to_string(key, &p); if (r < 0) return r; log_debug("Looking up RR for %s.", strstrip(p)); } /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */ DNS_QUESTION_FOREACH(key, question_idna) { _cleanup_free_ char *p = NULL; r = dns_question_contains(question_utf8, key); if (r < 0) return r; if (r > 0) continue; r = dns_resource_key_to_string(key, &p); if (r < 0) return r; log_debug("Looking up IDNA RR for %s.", strstrip(p)); } LIST_PREPEND(queries, m->dns_queries, q); m->n_dns_queries++; q->manager = m; if (ret) *ret = q; q = NULL; return 0; } int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for) { assert(q); assert(auxiliary_for); /* Ensure that that the query is not auxiliary yet, and * nothing else is auxiliary to it either */ assert(!q->auxiliary_for); assert(!q->auxiliary_queries); /* Ensure that the unit we shall be made auxiliary for isn't * auxiliary itself */ assert(!auxiliary_for->auxiliary_for); if (auxiliary_for->n_auxiliary_queries >= AUXILIARY_QUERIES_MAX) return -EAGAIN; LIST_PREPEND(auxiliary_queries, auxiliary_for->auxiliary_queries, q); q->auxiliary_for = auxiliary_for; auxiliary_for->n_auxiliary_queries++; return 0; } static void dns_query_complete(DnsQuery *q, DnsTransactionState state) { assert(q); assert(!DNS_TRANSACTION_IS_LIVE(state)); assert(DNS_TRANSACTION_IS_LIVE(q->state)); /* Note that this call might invalidate the query. Callers * should hence not attempt to access the query or transaction * after calling this function. */ q->state = state; dns_query_stop(q); if (q->complete) q->complete(q); } static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) { DnsQuery *q = userdata; assert(s); assert(q); dns_query_complete(q, DNS_TRANSACTION_TIMEOUT); return 0; } static int dns_query_add_candidate(DnsQuery *q, DnsScope *s) { DnsQueryCandidate *c; int r; assert(q); assert(s); r = dns_query_candidate_new(&c, q, s); if (r < 0) return r; /* If this a single-label domain on DNS, we might append a suitable search domain first. */ if ((q->flags & SD_RESOLVED_NO_SEARCH) == 0) { r = dns_scope_name_needs_search_domain(s, dns_question_first_name(q->question_idna)); if (r < 0) goto fail; if (r > 0) { /* OK, we need a search domain now. Let's find one for this scope */ r = dns_query_candidate_next_search_domain(c); if (r <= 0) /* if there's no search domain, then we won't add any transaction. */ goto fail; } } r = dns_query_candidate_setup_transactions(c); if (r < 0) goto fail; return 0; fail: dns_query_candidate_free(c); return r; } static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) { _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; int r; assert(q); assert(state); /* Tries to synthesize localhost RR replies (and others) where appropriate. Note that this is done *after* the * the normal lookup finished. The data from the network hence takes precedence over the data we * synthesize. (But note that many scopes refuse to resolve certain domain names) */ if (!IN_SET(*state, DNS_TRANSACTION_RCODE_FAILURE, DNS_TRANSACTION_NO_SERVERS, DNS_TRANSACTION_TIMEOUT, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED, DNS_TRANSACTION_NETWORK_DOWN, DNS_TRANSACTION_NOT_FOUND)) return 0; r = dns_synthesize_answer( q->manager, q->question_utf8, q->ifindex, &answer); if (r <= 0) return r; dns_query_reset_answer(q); q->answer = answer; answer = NULL; q->answer_rcode = DNS_RCODE_SUCCESS; q->answer_protocol = dns_synthesize_protocol(q->flags); q->answer_family = dns_synthesize_family(q->flags); q->answer_authenticated = true; *state = DNS_TRANSACTION_SUCCESS; return 1; } static int dns_query_try_etc_hosts(DnsQuery *q) { _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; int r; assert(q); /* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is done. The * data from /etc/hosts hence takes precedence over the network. */ r = manager_etc_hosts_lookup( q->manager, q->question_utf8, &answer); if (r <= 0) return r; dns_query_reset_answer(q); q->answer = answer; answer = NULL; q->answer_rcode = DNS_RCODE_SUCCESS; q->answer_protocol = dns_synthesize_protocol(q->flags); q->answer_family = dns_synthesize_family(q->flags); q->answer_authenticated = true; return 1; } int dns_query_go(DnsQuery *q) { DnsScopeMatch found = DNS_SCOPE_NO; DnsScope *s, *first = NULL; DnsQueryCandidate *c; int r; assert(q); if (q->state != DNS_TRANSACTION_NULL) return 0; r = dns_query_try_etc_hosts(q); if (r < 0) return r; if (r > 0) { dns_query_complete(q, DNS_TRANSACTION_SUCCESS); return 1; } LIST_FOREACH(scopes, s, q->manager->dns_scopes) { DnsScopeMatch match; const char *name; name = dns_question_first_name(dns_query_question_for_protocol(q, s->protocol)); if (!name) continue; match = dns_scope_good_domain(s, q->ifindex, q->flags, name); if (match < 0) return match; if (match == DNS_SCOPE_NO) continue; found = match; if (match == DNS_SCOPE_YES) { first = s; break; } else { assert(match == DNS_SCOPE_MAYBE); if (!first) first = s; } } if (found == DNS_SCOPE_NO) { DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS; r = dns_query_synthesize_reply(q, &state); if (r < 0) return r; dns_query_complete(q, state); return 1; } r = dns_query_add_candidate(q, first); if (r < 0) goto fail; LIST_FOREACH(scopes, s, first->scopes_next) { DnsScopeMatch match; const char *name; name = dns_question_first_name(dns_query_question_for_protocol(q, s->protocol)); if (!name) continue; match = dns_scope_good_domain(s, q->ifindex, q->flags, name); if (match < 0) goto fail; if (match != found) continue; r = dns_query_add_candidate(q, s); if (r < 0) goto fail; } dns_query_reset_answer(q); r = sd_event_add_time( q->manager->event, &q->timeout_event_source, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC, 0, on_query_timeout, q); if (r < 0) goto fail; (void) sd_event_source_set_description(q->timeout_event_source, "query-timeout"); q->state = DNS_TRANSACTION_PENDING; q->block_ready++; /* Start the transactions */ LIST_FOREACH(candidates_by_query, c, q->candidates) { r = dns_query_candidate_go(c); if (r < 0) { q->block_ready--; goto fail; } } q->block_ready--; dns_query_ready(q); return 1; fail: dns_query_stop(q); return r; } static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) { DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS; bool has_authenticated = false, has_non_authenticated = false; DnssecResult dnssec_result_authenticated = _DNSSEC_RESULT_INVALID, dnssec_result_non_authenticated = _DNSSEC_RESULT_INVALID; DnsTransaction *t; Iterator i; int r; assert(q); if (!c) { r = dns_query_synthesize_reply(q, &state); if (r < 0) goto fail; dns_query_complete(q, state); return; } if (c->error_code != 0) { /* If the candidate had an error condition of its own, start with that. */ state = DNS_TRANSACTION_ERRNO; q->answer = dns_answer_unref(q->answer); q->answer_rcode = 0; q->answer_dnssec_result = _DNSSEC_RESULT_INVALID; q->answer_errno = c->error_code; } SET_FOREACH(t, c->transactions, i) { switch (t->state) { case DNS_TRANSACTION_SUCCESS: { /* We found a successfuly reply, merge it into the answer */ r = dns_answer_extend(&q->answer, t->answer); if (r < 0) goto fail; q->answer_rcode = t->answer_rcode; q->answer_errno = 0; if (t->answer_authenticated) { has_authenticated = true; dnssec_result_authenticated = t->answer_dnssec_result; } else { has_non_authenticated = true; dnssec_result_non_authenticated = t->answer_dnssec_result; } state = DNS_TRANSACTION_SUCCESS; break; } case DNS_TRANSACTION_NULL: case DNS_TRANSACTION_PENDING: case DNS_TRANSACTION_VALIDATING: case DNS_TRANSACTION_ABORTED: /* Ignore transactions that didn't complete */ continue; default: /* Any kind of failure? Store the data away, * if there's nothing stored yet. */ if (state == DNS_TRANSACTION_SUCCESS) continue; q->answer = dns_answer_unref(q->answer); q->answer_rcode = t->answer_rcode; q->answer_dnssec_result = t->answer_dnssec_result; q->answer_errno = t->answer_errno; state = t->state; break; } } if (state == DNS_TRANSACTION_SUCCESS) { q->answer_authenticated = has_authenticated && !has_non_authenticated; q->answer_dnssec_result = q->answer_authenticated ? dnssec_result_authenticated : dnssec_result_non_authenticated; } q->answer_protocol = c->scope->protocol; q->answer_family = c->scope->family; dns_search_domain_unref(q->answer_search_domain); q->answer_search_domain = dns_search_domain_ref(c->search_domain); r = dns_query_synthesize_reply(q, &state); if (r < 0) goto fail; dns_query_complete(q, state); return; fail: q->answer_errno = -r; dns_query_complete(q, DNS_TRANSACTION_ERRNO); } void dns_query_ready(DnsQuery *q) { DnsQueryCandidate *bad = NULL, *c; bool pending = false; assert(q); assert(DNS_TRANSACTION_IS_LIVE(q->state)); /* Note that this call might invalidate the query. Callers * should hence not attempt to access the query or transaction * after calling this function, unless the block_ready * counter was explicitly bumped before doing so. */ if (q->block_ready > 0) return; LIST_FOREACH(candidates_by_query, c, q->candidates) { DnsTransactionState state; state = dns_query_candidate_state(c); switch (state) { case DNS_TRANSACTION_SUCCESS: /* One of the candidates is successful, * let's use it, and copy its data out */ dns_query_accept(q, c); return; case DNS_TRANSACTION_NULL: case DNS_TRANSACTION_PENDING: case DNS_TRANSACTION_VALIDATING: /* One of the candidates is still going on, * let's maybe wait for it */ pending = true; break; default: /* Any kind of failure */ bad = c; break; } } if (pending) return; dns_query_accept(q, bad); } static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) { _cleanup_(dns_question_unrefp) DnsQuestion *nq_idna = NULL, *nq_utf8 = NULL; int r, k; assert(q); q->n_cname_redirects ++; if (q->n_cname_redirects > CNAME_MAX) return -ELOOP; r = dns_question_cname_redirect(q->question_idna, cname, &nq_idna); if (r < 0) return r; else if (r > 0) log_debug("Following CNAME/DNAME %s → %s.", dns_question_first_name(q->question_idna), dns_question_first_name(nq_idna)); k = dns_question_is_equal(q->question_idna, q->question_utf8); if (k < 0) return r; if (k > 0) { /* Same question? Shortcut new question generation */ nq_utf8 = dns_question_ref(nq_idna); k = r; } else { k = dns_question_cname_redirect(q->question_utf8, cname, &nq_utf8); if (k < 0) return k; else if (k > 0) log_debug("Following UTF8 CNAME/DNAME %s → %s.", dns_question_first_name(q->question_utf8), dns_question_first_name(nq_utf8)); } if (r == 0 && k == 0) /* No actual cname happened? */ return -ELOOP; if (q->answer_protocol == DNS_PROTOCOL_DNS) { /* Don't permit CNAME redirects from unicast DNS to LLMNR or MulticastDNS, so that global resources * cannot invade the local namespace. The opposite way we permit: local names may redirect to global * ones. */ q->flags &= ~(SD_RESOLVED_LLMNR|SD_RESOLVED_MDNS); /* mask away the local protocols */ } /* Turn off searching for the new name */ q->flags |= SD_RESOLVED_NO_SEARCH; dns_question_unref(q->question_idna); q->question_idna = nq_idna; nq_idna = NULL; dns_question_unref(q->question_utf8); q->question_utf8 = nq_utf8; nq_utf8 = NULL; dns_query_free_candidates(q); dns_query_reset_answer(q); q->state = DNS_TRANSACTION_NULL; return 0; } int dns_query_process_cname(DnsQuery *q) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL; DnsQuestion *question; DnsResourceRecord *rr; int r; assert(q); if (!IN_SET(q->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_NULL)) return DNS_QUERY_NOMATCH; question = dns_query_question_for_protocol(q, q->answer_protocol); DNS_ANSWER_FOREACH(rr, q->answer) { r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain)); if (r < 0) return r; if (r > 0) return DNS_QUERY_MATCH; /* The answer matches directly, no need to follow cnames */ r = dns_question_matches_cname_or_dname(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain)); if (r < 0) return r; if (r > 0 && !cname) cname = dns_resource_record_ref(rr); } if (!cname) return DNS_QUERY_NOMATCH; /* No match and no cname to follow */ if (q->flags & SD_RESOLVED_NO_CNAME) return -ELOOP; /* OK, let's actually follow the CNAME */ r = dns_query_cname_redirect(q, cname); if (r < 0) return r; /* Let's see if the answer can already answer the new * redirected question */ r = dns_query_process_cname(q); if (r != DNS_QUERY_NOMATCH) return r; /* OK, it cannot, let's begin with the new query */ r = dns_query_go(q); if (r < 0) return r; return DNS_QUERY_RESTARTED; /* We restarted the query for a new cname */ } static int on_bus_track(sd_bus_track *t, void *userdata) { DnsQuery *q = userdata; assert(t); assert(q); log_debug("Client of active query vanished, aborting query."); dns_query_complete(q, DNS_TRANSACTION_ABORTED); return 0; } int dns_query_bus_track(DnsQuery *q, sd_bus_message *m) { int r; assert(q); assert(m); if (!q->bus_track) { r = sd_bus_track_new(sd_bus_message_get_bus(m), &q->bus_track, on_bus_track, q); if (r < 0) return r; } r = sd_bus_track_add_sender(q->bus_track, m); if (r < 0) return r; return 0; } DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol) { assert(q); switch (protocol) { case DNS_PROTOCOL_DNS: return q->question_idna; case DNS_PROTOCOL_MDNS: case DNS_PROTOCOL_LLMNR: return q->question_utf8; default: return NULL; } } const char *dns_query_string(DnsQuery *q) { const char *name; int r; /* Returns a somewhat useful human-readable lookup key string for this query */ if (q->request_address_string) return q->request_address_string; if (q->request_address_valid) { r = in_addr_to_string(q->request_family, &q->request_address, &q->request_address_string); if (r >= 0) return q->request_address_string; } name = dns_question_first_name(q->question_utf8); if (name) return name; return dns_question_first_name(q->question_idna); } systemd-229/src/resolve/resolved-dns-query.h000066400000000000000000000103301265713322000212450ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "set.h" typedef struct DnsQueryCandidate DnsQueryCandidate; typedef struct DnsQuery DnsQuery; #include "resolved-dns-answer.h" #include "resolved-dns-question.h" #include "resolved-dns-stream.h" #include "resolved-dns-search-domain.h" struct DnsQueryCandidate { DnsQuery *query; DnsScope *scope; DnsSearchDomain *search_domain; int error_code; Set *transactions; LIST_FIELDS(DnsQueryCandidate, candidates_by_query); LIST_FIELDS(DnsQueryCandidate, candidates_by_scope); }; struct DnsQuery { Manager *manager; /* When resolving a service, we first create a TXT+SRV query, * and then for the hostnames we discover auxiliary A+AAAA * queries. This pointer always points from the auxiliary * queries back to the TXT+SRV query. */ DnsQuery *auxiliary_for; LIST_HEAD(DnsQuery, auxiliary_queries); unsigned n_auxiliary_queries; int auxiliary_result; /* The question, formatted in IDNA for use on classic DNS, and as UTF8 for use in LLMNR or mDNS. Note that even * on classic DNS some labels might use UTF8 encoding. Specifically, DNS-SD service names (in contrast to their * domain suffixes) use UTF-8 encoding even on DNS. Thus, the difference between these two fields is mostly * relevant only for explicit *hostname* lookups as well as the domain suffixes of service lookups. */ DnsQuestion *question_idna; DnsQuestion *question_utf8; uint64_t flags; int ifindex; /* If true, A or AAAA RR lookups will be suppressed on links with no routable address of the matching address * family */ bool suppress_unroutable_family; DnsTransactionState state; unsigned n_cname_redirects; LIST_HEAD(DnsQueryCandidate, candidates); sd_event_source *timeout_event_source; /* Discovered data */ DnsAnswer *answer; int answer_rcode; DnssecResult answer_dnssec_result; bool answer_authenticated; DnsProtocol answer_protocol; int answer_family; DnsSearchDomain *answer_search_domain; int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */ /* Bus client information */ sd_bus_message *request; int request_family; bool request_address_valid; union in_addr_union request_address; unsigned block_all_complete; char *request_address_string; /* Completion callback */ void (*complete)(DnsQuery* q); unsigned block_ready; sd_bus_track *bus_track; LIST_FIELDS(DnsQuery, queries); LIST_FIELDS(DnsQuery, auxiliary_queries); }; enum { DNS_QUERY_MATCH, DNS_QUERY_NOMATCH, DNS_QUERY_RESTARTED, }; DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c); void dns_query_candidate_notify(DnsQueryCandidate *c); int dns_query_new(Manager *m, DnsQuery **q, DnsQuestion *question_utf8, DnsQuestion *question_idna, int family, uint64_t flags); DnsQuery *dns_query_free(DnsQuery *q); int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for); int dns_query_go(DnsQuery *q); void dns_query_ready(DnsQuery *q); int dns_query_process_cname(DnsQuery *q); int dns_query_bus_track(DnsQuery *q, sd_bus_message *m); DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol); const char *dns_query_string(DnsQuery *q); DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuery*, dns_query_free); systemd-229/src/resolve/resolved-dns-question.c000066400000000000000000000304241265713322000217500ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "dns-domain.h" #include "dns-type.h" #include "resolved-dns-question.h" DnsQuestion *dns_question_new(unsigned n) { DnsQuestion *q; assert(n > 0); q = malloc0(offsetof(DnsQuestion, keys) + sizeof(DnsResourceKey*) * n); if (!q) return NULL; q->n_ref = 1; q->n_allocated = n; return q; } DnsQuestion *dns_question_ref(DnsQuestion *q) { if (!q) return NULL; assert(q->n_ref > 0); q->n_ref++; return q; } DnsQuestion *dns_question_unref(DnsQuestion *q) { if (!q) return NULL; assert(q->n_ref > 0); if (q->n_ref == 1) { unsigned i; for (i = 0; i < q->n_keys; i++) dns_resource_key_unref(q->keys[i]); free(q); } else q->n_ref--; return NULL; } int dns_question_add(DnsQuestion *q, DnsResourceKey *key) { unsigned i; int r; assert(key); if (!q) return -ENOSPC; for (i = 0; i < q->n_keys; i++) { r = dns_resource_key_equal(q->keys[i], key); if (r < 0) return r; if (r > 0) return 0; } if (q->n_keys >= q->n_allocated) return -ENOSPC; q->keys[q->n_keys++] = dns_resource_key_ref(key); return 0; } int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) { unsigned i; int r; assert(rr); if (!q) return 0; for (i = 0; i < q->n_keys; i++) { r = dns_resource_key_match_rr(q->keys[i], rr, search_domain); if (r != 0) return r; } return 0; } int dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) { unsigned i; int r; assert(rr); if (!q) return 0; if (!IN_SET(rr->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME)) return 0; for (i = 0; i < q->n_keys; i++) { /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */ if (!dns_type_may_redirect(q->keys[i]->type)) return 0; r = dns_resource_key_match_cname_or_dname(q->keys[i], rr->key, search_domain); if (r != 0) return r; } return 0; } int dns_question_is_valid_for_query(DnsQuestion *q) { const char *name; unsigned i; int r; if (!q) return 0; if (q->n_keys <= 0) return 0; if (q->n_keys > 65535) return 0; name = DNS_RESOURCE_KEY_NAME(q->keys[0]); if (!name) return 0; /* Check that all keys in this question bear the same name */ for (i = 0; i < q->n_keys; i++) { assert(q->keys[i]); if (i > 0) { r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), name); if (r <= 0) return r; } if (!dns_type_is_valid_query(q->keys[i]->type)) return 0; } return 1; } int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k) { unsigned j; int r; assert(k); if (!a) return 0; for (j = 0; j < a->n_keys; j++) { r = dns_resource_key_equal(a->keys[j], k); if (r != 0) return r; } return 0; } int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) { unsigned j; int r; if (a == b) return 1; if (!a) return !b || b->n_keys == 0; if (!b) return a->n_keys == 0; /* Checks if all keys in a are also contained b, and vice versa */ for (j = 0; j < a->n_keys; j++) { r = dns_question_contains(b, a->keys[j]); if (r <= 0) return r; } for (j = 0; j < b->n_keys; j++) { r = dns_question_contains(a, b->keys[j]); if (r <= 0) return r; } return 1; } int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret) { _cleanup_(dns_question_unrefp) DnsQuestion *n = NULL; DnsResourceKey *key; bool same = true; int r; assert(cname); assert(ret); assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME)); if (dns_question_size(q) <= 0) { *ret = NULL; return 0; } DNS_QUESTION_FOREACH(key, q) { _cleanup_free_ char *destination = NULL; const char *d; if (cname->key->type == DNS_TYPE_CNAME) d = cname->cname.name; else { r = dns_name_change_suffix(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname->key), cname->dname.name, &destination); if (r < 0) return r; if (r == 0) continue; d = destination; } r = dns_name_equal(DNS_RESOURCE_KEY_NAME(key), d); if (r < 0) return r; if (r == 0) { same = false; break; } } /* Fully the same, indicate we didn't do a thing */ if (same) { *ret = NULL; return 0; } n = dns_question_new(q->n_keys); if (!n) return -ENOMEM; /* Create a new question, and patch in the new name */ DNS_QUESTION_FOREACH(key, q) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL; k = dns_resource_key_new_redirect(key, cname); if (!k) return -ENOMEM; r = dns_question_add(n, k); if (r < 0) return r; } *ret = n; n = NULL; return 1; } const char *dns_question_first_name(DnsQuestion *q) { if (!q) return NULL; if (q->n_keys < 1) return NULL; return DNS_RESOURCE_KEY_NAME(q->keys[0]); } int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bool convert_idna) { _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL; _cleanup_free_ char *buf = NULL; int r; assert(ret); assert(name); if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC)) return -EAFNOSUPPORT; if (convert_idna) { r = dns_name_apply_idna(name, &buf); if (r < 0) return r; name = buf; } q = dns_question_new(family == AF_UNSPEC ? 2 : 1); if (!q) return -ENOMEM; if (family != AF_INET6) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, name); if (!key) return -ENOMEM; r = dns_question_add(q, key); if (r < 0) return r; } if (family != AF_INET) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, name); if (!key) return -ENOMEM; r = dns_question_add(q, key); if (r < 0) return r; } *ret = q; q = NULL; return 0; } int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL; _cleanup_free_ char *reverse = NULL; int r; assert(ret); assert(a); if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC)) return -EAFNOSUPPORT; r = dns_name_reverse(family, a, &reverse); if (r < 0) return r; q = dns_question_new(1); if (!q) return -ENOMEM; key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse); if (!key) return -ENOMEM; reverse = NULL; r = dns_question_add(q, key); if (r < 0) return r; *ret = q; q = NULL; return 0; } int dns_question_new_service( DnsQuestion **ret, const char *service, const char *type, const char *domain, bool with_txt, bool convert_idna) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL; _cleanup_free_ char *buf = NULL, *joined = NULL; const char *name; int r; assert(ret); /* We support three modes of invocation: * * 1. Only a domain is specified, in which case we assume a properly encoded SRV RR name, including service * type and possibly a service name. If specified in this way we assume it's already IDNA converted if * that's necessary. * * 2. Both service type and a domain specified, in which case a normal SRV RR is assumed, without a DNS-SD * style prefix. In this case we'll IDNA convert the domain, if that's requested. * * 3. All three of service name, type and domain are specified, in which case a DNS-SD service is put * together. The service name is never IDNA converted, and the domain is if requested. * * It's not supported to specify a service name without a type, or no domain name. */ if (!domain) return -EINVAL; if (type) { if (convert_idna) { r = dns_name_apply_idna(domain, &buf); if (r < 0) return r; domain = buf; } r = dns_service_join(service, type, domain, &joined); if (r < 0) return r; name = joined; } else { if (service) return -EINVAL; name = domain; } q = dns_question_new(1 + with_txt); if (!q) return -ENOMEM; key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_SRV, name); if (!key) return -ENOMEM; r = dns_question_add(q, key); if (r < 0) return r; if (with_txt) { dns_resource_key_unref(key); key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_TXT, name); if (!key) return -ENOMEM; r = dns_question_add(q, key); if (r < 0) return r; } *ret = q; q = NULL; return 0; } systemd-229/src/resolve/resolved-dns-question.h000066400000000000000000000054361265713322000217620ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct DnsQuestion DnsQuestion; #include "macro.h" #include "resolved-dns-rr.h" /* A simple array of resource keys */ struct DnsQuestion { unsigned n_ref; unsigned n_keys, n_allocated; DnsResourceKey* keys[0]; }; DnsQuestion *dns_question_new(unsigned n); DnsQuestion *dns_question_ref(DnsQuestion *q); DnsQuestion *dns_question_unref(DnsQuestion *q); int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bool convert_idna); int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a); int dns_question_new_service(DnsQuestion **ret, const char *service, const char *type, const char *domain, bool with_txt, bool convert_idna); int dns_question_add(DnsQuestion *q, DnsResourceKey *key); int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain); int dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, const char* search_domain); int dns_question_is_valid_for_query(DnsQuestion *q); int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k); int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b); int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret); const char *dns_question_first_name(DnsQuestion *q); static inline unsigned dns_question_size(DnsQuestion *q) { return q ? q->n_keys : 0; } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuestion*, dns_question_unref); #define _DNS_QUESTION_FOREACH(u, key, q) \ for (unsigned UNIQ_T(i, u) = ({ \ (key) = ((q) && (q)->n_keys > 0) ? (q)->keys[0] : NULL; \ 0; \ }); \ (q) && (UNIQ_T(i, u) < (q)->n_keys); \ UNIQ_T(i, u)++, (key) = (UNIQ_T(i, u) < (q)->n_keys ? (q)->keys[UNIQ_T(i, u)] : NULL)) #define DNS_QUESTION_FOREACH(key, q) _DNS_QUESTION_FOREACH(UNIQ, key, q) systemd-229/src/resolve/resolved-dns-rr.c000066400000000000000000001414531265713322000205310ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "dns-domain.h" #include "dns-type.h" #include "hexdecoct.h" #include "resolved-dns-dnssec.h" #include "resolved-dns-packet.h" #include "resolved-dns-rr.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) { DnsResourceKey *k; size_t l; assert(name); l = strlen(name); k = malloc0(sizeof(DnsResourceKey) + l + 1); if (!k) return NULL; k->n_ref = 1; k->class = class; k->type = type; strcpy((char*) k + sizeof(DnsResourceKey), name); return k; } DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname) { int r; assert(key); assert(cname); assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME)); if (cname->key->type == DNS_TYPE_CNAME) return dns_resource_key_new(key->class, key->type, cname->cname.name); else { DnsResourceKey *k; char *destination = NULL; r = dns_name_change_suffix(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname->key), cname->dname.name, &destination); if (r < 0) return NULL; if (r == 0) return dns_resource_key_ref((DnsResourceKey*) key); k = dns_resource_key_new_consume(key->class, key->type, destination); if (!k) { free(destination); return NULL; } return k; } } int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name) { DnsResourceKey *new_key; char *joined; int r; assert(ret); assert(key); assert(name); if (dns_name_is_root(name)) { *ret = dns_resource_key_ref(key); return 0; } r = dns_name_concat(DNS_RESOURCE_KEY_NAME(key), name, &joined); if (r < 0) return r; new_key = dns_resource_key_new_consume(key->class, key->type, joined); if (!new_key) { free(joined); return -ENOMEM; } *ret = new_key; return 0; } DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) { DnsResourceKey *k; assert(name); k = new0(DnsResourceKey, 1); if (!k) return NULL; k->n_ref = 1; k->class = class; k->type = type; k->_name = name; return k; } DnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) { if (!k) return NULL; /* Static/const keys created with DNS_RESOURCE_KEY_CONST will * set this to -1, they should not be reffed/unreffed */ assert(k->n_ref != (unsigned) -1); assert(k->n_ref > 0); k->n_ref++; return k; } DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) { if (!k) return NULL; assert(k->n_ref != (unsigned) -1); assert(k->n_ref > 0); if (k->n_ref == 1) { free(k->_name); free(k); } else k->n_ref--; return NULL; } bool dns_resource_key_is_address(const DnsResourceKey *key) { assert(key); /* Check if this is an A or AAAA resource key */ return key->class == DNS_CLASS_IN && IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_AAAA); } int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) { int r; if (a == b) return 1; r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b)); if (r <= 0) return r; if (a->class != b->class) return 0; if (a->type != b->type) return 0; return 1; } int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain) { int r; assert(key); assert(rr); if (key == rr->key) return 1; /* Checks if an rr matches the specified key. If a search * domain is specified, it will also be checked if the key * with the search domain suffixed might match the RR. */ if (rr->key->class != key->class && key->class != DNS_CLASS_ANY) return 0; if (rr->key->type != key->type && key->type != DNS_TYPE_ANY) return 0; r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key)); if (r != 0) return r; if (search_domain) { _cleanup_free_ char *joined = NULL; r = dns_name_concat(DNS_RESOURCE_KEY_NAME(key), search_domain, &joined); if (r < 0) return r; return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), joined); } return 0; } int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain) { int r; assert(key); assert(cname); if (cname->class != key->class && key->class != DNS_CLASS_ANY) return 0; if (cname->type == DNS_TYPE_CNAME) r = dns_name_equal(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname)); else if (cname->type == DNS_TYPE_DNAME) r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname)); else return 0; if (r != 0) return r; if (search_domain) { _cleanup_free_ char *joined = NULL; r = dns_name_concat(DNS_RESOURCE_KEY_NAME(key), search_domain, &joined); if (r < 0) return r; if (cname->type == DNS_TYPE_CNAME) return dns_name_equal(joined, DNS_RESOURCE_KEY_NAME(cname)); else if (cname->type == DNS_TYPE_DNAME) return dns_name_endswith(joined, DNS_RESOURCE_KEY_NAME(cname)); } return 0; } int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa) { assert(soa); assert(key); /* Checks whether 'soa' is a SOA record for the specified key. */ if (soa->class != key->class) return 0; if (soa->type != DNS_TYPE_SOA) return 0; return dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(soa)); } static void dns_resource_key_hash_func(const void *i, struct siphash *state) { const DnsResourceKey *k = i; assert(k); dns_name_hash_func(DNS_RESOURCE_KEY_NAME(k), state); siphash24_compress(&k->class, sizeof(k->class), state); siphash24_compress(&k->type, sizeof(k->type), state); } static int dns_resource_key_compare_func(const void *a, const void *b) { const DnsResourceKey *x = a, *y = b; int ret; ret = dns_name_compare_func(DNS_RESOURCE_KEY_NAME(x), DNS_RESOURCE_KEY_NAME(y)); if (ret != 0) return ret; if (x->type < y->type) return -1; if (x->type > y->type) return 1; if (x->class < y->class) return -1; if (x->class > y->class) return 1; return 0; } const struct hash_ops dns_resource_key_hash_ops = { .hash = dns_resource_key_hash_func, .compare = dns_resource_key_compare_func }; int dns_resource_key_to_string(const DnsResourceKey *key, char **ret) { char cbuf[strlen("CLASS") + DECIMAL_STR_MAX(uint16_t)], tbuf[strlen("TYPE") + DECIMAL_STR_MAX(uint16_t)]; const char *c, *t, *n; char *s; /* If we cannot convert the CLASS/TYPE into a known string, use the format recommended by RFC 3597, Section 5. */ c = dns_class_to_string(key->class); if (!c) { sprintf(cbuf, "CLASS%u", key->class); c = cbuf; } t = dns_type_to_string(key->type); if (!t){ sprintf(tbuf, "TYPE%u", key->type); t = tbuf; } n = DNS_RESOURCE_KEY_NAME(key); if (asprintf(&s, "%s%s %s %-5s", n, endswith(n, ".") ? "" : ".", c, t) < 0) return -ENOMEM; *ret = s; return 0; } bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b) { assert(a); assert(b); /* Try to replace one RR key by another if they are identical, thus saving a bit of memory. Note that we do * this only for RR keys, not for RRs themselves, as they carry a lot of additional metadata (where they come * from, validity data, and suchlike), and cannot be replaced so easily by other RRs that have the same * superficial data. */ if (!*a) return false; if (!*b) return false; /* We refuse merging const keys */ if ((*a)->n_ref == (unsigned) -1) return false; if ((*b)->n_ref == (unsigned) -1) return false; /* Already the same? */ if (*a == *b) return true; /* Are they really identical? */ if (dns_resource_key_equal(*a, *b) <= 0) return false; /* Keep the one which already has more references. */ if ((*a)->n_ref > (*b)->n_ref) { dns_resource_key_unref(*b); *b = dns_resource_key_ref(*a); } else { dns_resource_key_unref(*a); *a = dns_resource_key_ref(*b); } return true; } DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) { DnsResourceRecord *rr; rr = new0(DnsResourceRecord, 1); if (!rr) return NULL; rr->n_ref = 1; rr->key = dns_resource_key_ref(key); rr->expiry = USEC_INFINITY; rr->n_skip_labels_signer = rr->n_skip_labels_source = (unsigned) -1; return rr; } DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; key = dns_resource_key_new(class, type, name); if (!key) return NULL; return dns_resource_record_new(key); } DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr) { if (!rr) return NULL; assert(rr->n_ref > 0); rr->n_ref++; return rr; } DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) { if (!rr) return NULL; assert(rr->n_ref > 0); if (rr->n_ref > 1) { rr->n_ref--; return NULL; } if (rr->key) { switch(rr->key->type) { case DNS_TYPE_SRV: free(rr->srv.name); break; case DNS_TYPE_PTR: case DNS_TYPE_NS: case DNS_TYPE_CNAME: case DNS_TYPE_DNAME: free(rr->ptr.name); break; case DNS_TYPE_HINFO: free(rr->hinfo.cpu); free(rr->hinfo.os); break; case DNS_TYPE_TXT: case DNS_TYPE_SPF: dns_txt_item_free_all(rr->txt.items); break; case DNS_TYPE_SOA: free(rr->soa.mname); free(rr->soa.rname); break; case DNS_TYPE_MX: free(rr->mx.exchange); break; case DNS_TYPE_DS: free(rr->ds.digest); break; case DNS_TYPE_SSHFP: free(rr->sshfp.fingerprint); break; case DNS_TYPE_DNSKEY: free(rr->dnskey.key); break; case DNS_TYPE_RRSIG: free(rr->rrsig.signer); free(rr->rrsig.signature); break; case DNS_TYPE_NSEC: free(rr->nsec.next_domain_name); bitmap_free(rr->nsec.types); break; case DNS_TYPE_NSEC3: free(rr->nsec3.next_hashed_name); free(rr->nsec3.salt); bitmap_free(rr->nsec3.types); break; case DNS_TYPE_LOC: case DNS_TYPE_A: case DNS_TYPE_AAAA: break; case DNS_TYPE_TLSA: free(rr->tlsa.data); break; case DNS_TYPE_OPENPGPKEY: default: free(rr->generic.data); } free(rr->wire_format); dns_resource_key_unref(rr->key); } free(rr->to_string); free(rr); return NULL; } int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; _cleanup_free_ char *ptr = NULL; int r; assert(ret); assert(address); assert(hostname); r = dns_name_reverse(family, address, &ptr); if (r < 0) return r; key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr); if (!key) return -ENOMEM; ptr = NULL; rr = dns_resource_record_new(key); if (!rr) return -ENOMEM; rr->ptr.name = strdup(hostname); if (!rr->ptr.name) return -ENOMEM; *ret = rr; rr = NULL; return 0; } int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name) { DnsResourceRecord *rr; assert(ret); assert(address); assert(family); if (family == AF_INET) { rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, name); if (!rr) return -ENOMEM; rr->a.in_addr = address->in; } else if (family == AF_INET6) { rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, name); if (!rr) return -ENOMEM; rr->aaaa.in6_addr = address->in6; } else return -EAFNOSUPPORT; *ret = rr; return 0; } #define FIELD_EQUAL(a, b, field) \ ((a).field ## _size == (b).field ## _size && \ memcmp((a).field, (b).field, (a).field ## _size) == 0) int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) { int r; assert(a); assert(b); if (a == b) return 1; r = dns_resource_key_equal(a->key, b->key); if (r <= 0) return r; if (a->unparseable != b->unparseable) return 0; switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) { case DNS_TYPE_SRV: r = dns_name_equal(a->srv.name, b->srv.name); if (r <= 0) return r; return a->srv.priority == b->srv.priority && a->srv.weight == b->srv.weight && a->srv.port == b->srv.port; case DNS_TYPE_PTR: case DNS_TYPE_NS: case DNS_TYPE_CNAME: case DNS_TYPE_DNAME: return dns_name_equal(a->ptr.name, b->ptr.name); case DNS_TYPE_HINFO: return strcaseeq(a->hinfo.cpu, b->hinfo.cpu) && strcaseeq(a->hinfo.os, b->hinfo.os); case DNS_TYPE_SPF: /* exactly the same as TXT */ case DNS_TYPE_TXT: return dns_txt_item_equal(a->txt.items, b->txt.items); case DNS_TYPE_A: return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0; case DNS_TYPE_AAAA: return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0; case DNS_TYPE_SOA: r = dns_name_equal(a->soa.mname, b->soa.mname); if (r <= 0) return r; r = dns_name_equal(a->soa.rname, b->soa.rname); if (r <= 0) return r; return a->soa.serial == b->soa.serial && a->soa.refresh == b->soa.refresh && a->soa.retry == b->soa.retry && a->soa.expire == b->soa.expire && a->soa.minimum == b->soa.minimum; case DNS_TYPE_MX: if (a->mx.priority != b->mx.priority) return 0; return dns_name_equal(a->mx.exchange, b->mx.exchange); case DNS_TYPE_LOC: assert(a->loc.version == b->loc.version); return a->loc.size == b->loc.size && a->loc.horiz_pre == b->loc.horiz_pre && a->loc.vert_pre == b->loc.vert_pre && a->loc.latitude == b->loc.latitude && a->loc.longitude == b->loc.longitude && a->loc.altitude == b->loc.altitude; case DNS_TYPE_DS: return a->ds.key_tag == b->ds.key_tag && a->ds.algorithm == b->ds.algorithm && a->ds.digest_type == b->ds.digest_type && FIELD_EQUAL(a->ds, b->ds, digest); case DNS_TYPE_SSHFP: return a->sshfp.algorithm == b->sshfp.algorithm && a->sshfp.fptype == b->sshfp.fptype && FIELD_EQUAL(a->sshfp, b->sshfp, fingerprint); case DNS_TYPE_DNSKEY: return a->dnskey.flags == b->dnskey.flags && a->dnskey.protocol == b->dnskey.protocol && a->dnskey.algorithm == b->dnskey.algorithm && FIELD_EQUAL(a->dnskey, b->dnskey, key); case DNS_TYPE_RRSIG: /* do the fast comparisons first */ return a->rrsig.type_covered == b->rrsig.type_covered && a->rrsig.algorithm == b->rrsig.algorithm && a->rrsig.labels == b->rrsig.labels && a->rrsig.original_ttl == b->rrsig.original_ttl && a->rrsig.expiration == b->rrsig.expiration && a->rrsig.inception == b->rrsig.inception && a->rrsig.key_tag == b->rrsig.key_tag && FIELD_EQUAL(a->rrsig, b->rrsig, signature) && dns_name_equal(a->rrsig.signer, b->rrsig.signer); case DNS_TYPE_NSEC: return dns_name_equal(a->nsec.next_domain_name, b->nsec.next_domain_name) && bitmap_equal(a->nsec.types, b->nsec.types); case DNS_TYPE_NSEC3: return a->nsec3.algorithm == b->nsec3.algorithm && a->nsec3.flags == b->nsec3.flags && a->nsec3.iterations == b->nsec3.iterations && FIELD_EQUAL(a->nsec3, b->nsec3, salt) && FIELD_EQUAL(a->nsec3, b->nsec3, next_hashed_name) && bitmap_equal(a->nsec3.types, b->nsec3.types); case DNS_TYPE_TLSA: return a->tlsa.cert_usage == b->tlsa.cert_usage && a->tlsa.selector == b->tlsa.selector && a->tlsa.matching_type == b->tlsa.matching_type && FIELD_EQUAL(a->tlsa, b->tlsa, data); default: return FIELD_EQUAL(a->generic, b->generic, data); } } static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude, uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) { char *s; char NS = latitude >= 1U<<31 ? 'N' : 'S'; char EW = longitude >= 1U<<31 ? 'E' : 'W'; int lat = latitude >= 1U<<31 ? (int) (latitude - (1U<<31)) : (int) ((1U<<31) - latitude); int lon = longitude >= 1U<<31 ? (int) (longitude - (1U<<31)) : (int) ((1U<<31) - longitude); double alt = altitude >= 10000000u ? altitude - 10000000u : -(double)(10000000u - altitude); double siz = (size >> 4) * exp10((double) (size & 0xF)); double hor = (horiz_pre >> 4) * exp10((double) (horiz_pre & 0xF)); double ver = (vert_pre >> 4) * exp10((double) (vert_pre & 0xF)); if (asprintf(&s, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm", (lat / 60000 / 60), (lat / 60000) % 60, (lat % 60000) / 1000., NS, (lon / 60000 / 60), (lon / 60000) % 60, (lon % 60000) / 1000., EW, alt / 100., siz / 100., hor / 100., ver / 100.) < 0) return NULL; return s; } static int format_timestamp_dns(char *buf, size_t l, time_t sec) { struct tm tm; assert(buf); assert(l > strlen("YYYYMMDDHHmmSS")); if (!gmtime_r(&sec, &tm)) return -EINVAL; if (strftime(buf, l, "%Y%m%d%H%M%S", &tm) <= 0) return -EINVAL; return 0; } static char *format_types(Bitmap *types) { _cleanup_strv_free_ char **strv = NULL; _cleanup_free_ char *str = NULL; Iterator i; unsigned type; int r; BITMAP_FOREACH(type, types, i) { if (dns_type_to_string(type)) { r = strv_extend(&strv, dns_type_to_string(type)); if (r < 0) return NULL; } else { char *t; r = asprintf(&t, "TYPE%u", type); if (r < 0) return NULL; r = strv_consume(&strv, t); if (r < 0) return NULL; } } str = strv_join(strv, " "); if (!str) return NULL; return strjoin("( ", str, " )", NULL); } static char *format_txt(DnsTxtItem *first) { DnsTxtItem *i; size_t c = 1; char *p, *s; LIST_FOREACH(items, i, first) c += i->length * 4 + 3; p = s = new(char, c); if (!s) return NULL; LIST_FOREACH(items, i, first) { size_t j; if (i != first) *(p++) = ' '; *(p++) = '"'; for (j = 0; j < i->length; j++) { if (i->data[j] < ' ' || i->data[j] == '"' || i->data[j] >= 127) { *(p++) = '\\'; *(p++) = '0' + (i->data[j] / 100); *(p++) = '0' + ((i->data[j] / 10) % 10); *(p++) = '0' + (i->data[j] % 10); } else *(p++) = i->data[j]; } *(p++) = '"'; } *p = 0; return s; } const char *dns_resource_record_to_string(DnsResourceRecord *rr) { _cleanup_free_ char *k = NULL, *t = NULL; char *s; int r; assert(rr); if (rr->to_string) return rr->to_string; r = dns_resource_key_to_string(rr->key, &k); if (r < 0) return NULL; switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { case DNS_TYPE_SRV: r = asprintf(&s, "%s %u %u %u %s", k, rr->srv.priority, rr->srv.weight, rr->srv.port, strna(rr->srv.name)); if (r < 0) return NULL; break; case DNS_TYPE_PTR: case DNS_TYPE_NS: case DNS_TYPE_CNAME: case DNS_TYPE_DNAME: s = strjoin(k, " ", rr->ptr.name, NULL); if (!s) return NULL; break; case DNS_TYPE_HINFO: s = strjoin(k, " ", rr->hinfo.cpu, " ", rr->hinfo.os, NULL); if (!s) return NULL; break; case DNS_TYPE_SPF: /* exactly the same as TXT */ case DNS_TYPE_TXT: t = format_txt(rr->txt.items); if (!t) return NULL; s = strjoin(k, " ", t, NULL); if (!s) return NULL; break; case DNS_TYPE_A: { _cleanup_free_ char *x = NULL; r = in_addr_to_string(AF_INET, (const union in_addr_union*) &rr->a.in_addr, &x); if (r < 0) return NULL; s = strjoin(k, " ", x, NULL); if (!s) return NULL; break; } case DNS_TYPE_AAAA: r = in_addr_to_string(AF_INET6, (const union in_addr_union*) &rr->aaaa.in6_addr, &t); if (r < 0) return NULL; s = strjoin(k, " ", t, NULL); if (!s) return NULL; break; case DNS_TYPE_SOA: r = asprintf(&s, "%s %s %s %u %u %u %u %u", k, strna(rr->soa.mname), strna(rr->soa.rname), rr->soa.serial, rr->soa.refresh, rr->soa.retry, rr->soa.expire, rr->soa.minimum); if (r < 0) return NULL; break; case DNS_TYPE_MX: r = asprintf(&s, "%s %u %s", k, rr->mx.priority, rr->mx.exchange); if (r < 0) return NULL; break; case DNS_TYPE_LOC: assert(rr->loc.version == 0); t = format_location(rr->loc.latitude, rr->loc.longitude, rr->loc.altitude, rr->loc.size, rr->loc.horiz_pre, rr->loc.vert_pre); if (!t) return NULL; s = strjoin(k, " ", t, NULL); if (!s) return NULL; break; case DNS_TYPE_DS: t = hexmem(rr->ds.digest, rr->ds.digest_size); if (!t) return NULL; r = asprintf(&s, "%s %u %u %u %s", k, rr->ds.key_tag, rr->ds.algorithm, rr->ds.digest_type, t); if (r < 0) return NULL; break; case DNS_TYPE_SSHFP: t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size); if (!t) return NULL; r = asprintf(&s, "%s %u %u %s", k, rr->sshfp.algorithm, rr->sshfp.fptype, t); if (r < 0) return NULL; break; case DNS_TYPE_DNSKEY: { _cleanup_free_ char *alg = NULL; char *ss; int n, n1; uint16_t key_tag; key_tag = dnssec_keytag(rr, true); r = dnssec_algorithm_to_string_alloc(rr->dnskey.algorithm, &alg); if (r < 0) return NULL; r = asprintf(&s, "%s %n%u %u %s %n", k, &n1, rr->dnskey.flags, rr->dnskey.protocol, alg, &n); if (r < 0) return NULL; r = base64_append(&s, n, rr->dnskey.key, rr->dnskey.key_size, 8, columns()); if (r < 0) return NULL; r = asprintf(&ss, "%s\n" "%*s-- Flags:%s%s%s\n" "%*s-- Key tag: %u", s, n1, "", rr->dnskey.flags & DNSKEY_FLAG_SEP ? " SEP" : "", rr->dnskey.flags & DNSKEY_FLAG_REVOKE ? " REVOKE" : "", rr->dnskey.flags & DNSKEY_FLAG_ZONE_KEY ? " ZONE_KEY" : "", n1, "", key_tag); if (r < 0) return NULL; free(s); s = ss; break; } case DNS_TYPE_RRSIG: { _cleanup_free_ char *alg = NULL; char expiration[strlen("YYYYMMDDHHmmSS") + 1], inception[strlen("YYYYMMDDHHmmSS") + 1]; const char *type; int n; type = dns_type_to_string(rr->rrsig.type_covered); r = dnssec_algorithm_to_string_alloc(rr->rrsig.algorithm, &alg); if (r < 0) return NULL; r = format_timestamp_dns(expiration, sizeof(expiration), rr->rrsig.expiration); if (r < 0) return NULL; r = format_timestamp_dns(inception, sizeof(inception), rr->rrsig.inception); if (r < 0) return NULL; /* TYPE?? follows * http://tools.ietf.org/html/rfc3597#section-5 */ r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s %n", k, type ?: "TYPE", type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered, alg, rr->rrsig.labels, rr->rrsig.original_ttl, expiration, inception, rr->rrsig.key_tag, rr->rrsig.signer, &n); if (r < 0) return NULL; r = base64_append(&s, n, rr->rrsig.signature, rr->rrsig.signature_size, 8, columns()); if (r < 0) return NULL; break; } case DNS_TYPE_NSEC: t = format_types(rr->nsec.types); if (!t) return NULL; r = asprintf(&s, "%s %s %s", k, rr->nsec.next_domain_name, t); if (r < 0) return NULL; break; case DNS_TYPE_NSEC3: { _cleanup_free_ char *salt = NULL, *hash = NULL; if (rr->nsec3.salt_size > 0) { salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size); if (!salt) return NULL; } hash = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false); if (!hash) return NULL; t = format_types(rr->nsec3.types); if (!t) return NULL; r = asprintf(&s, "%s %"PRIu8" %"PRIu8" %"PRIu16" %s %s %s", k, rr->nsec3.algorithm, rr->nsec3.flags, rr->nsec3.iterations, rr->nsec3.salt_size > 0 ? salt : "-", hash, t); if (r < 0) return NULL; break; } case DNS_TYPE_TLSA: { const char *cert_usage, *selector, *matching_type; char *ss; int n; cert_usage = tlsa_cert_usage_to_string(rr->tlsa.cert_usage); selector = tlsa_selector_to_string(rr->tlsa.selector); matching_type = tlsa_matching_type_to_string(rr->tlsa.matching_type); r = asprintf(&s, "%s %u %u %u %n", k, rr->tlsa.cert_usage, rr->tlsa.selector, rr->tlsa.matching_type, &n); if (r < 0) return NULL; r = base64_append(&s, n, rr->tlsa.data, rr->tlsa.data_size, 8, columns()); if (r < 0) return NULL; r = asprintf(&ss, "%s\n" "%*s-- Cert. usage: %s\n" "%*s-- Selector: %s\n" "%*s-- Matching type: %s", s, n - 6, "", cert_usage, n - 6, "", selector, n - 6, "", matching_type); if (r < 0) return NULL; free(s); s = ss; break; } case DNS_TYPE_OPENPGPKEY: { int n; r = asprintf(&s, "%s %n", k, &n); if (r < 0) return NULL; r = base64_append(&s, n, rr->generic.data, rr->generic.data_size, 8, columns()); if (r < 0) return NULL; break; } default: t = hexmem(rr->generic.data, rr->generic.data_size); if (!t) return NULL; /* Format as documented in RFC 3597, Section 5 */ r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.data_size, t); if (r < 0) return NULL; break; } rr->to_string = s; return s; } int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical) { DnsPacket packet = { .n_ref = 1, .protocol = DNS_PROTOCOL_DNS, .on_stack = true, .refuse_compression = true, .canonical_form = canonical, }; size_t start, rds; int r; assert(rr); /* Generates the RR in wire-format, optionally in the * canonical form as discussed in the DNSSEC RFC 4034, Section * 6.2. We allocate a throw-away DnsPacket object on the stack * here, because we need some book-keeping for memory * management, and can reuse the DnsPacket serializer, that * can generate the canonical form, too, but also knows label * compression and suchlike. */ if (rr->wire_format && rr->wire_format_canonical == canonical) return 0; r = dns_packet_append_rr(&packet, rr, &start, &rds); if (r < 0) return r; assert(start == 0); assert(packet._data); free(rr->wire_format); rr->wire_format = packet._data; rr->wire_format_size = packet.size; rr->wire_format_rdata_offset = rds; rr->wire_format_canonical = canonical; packet._data = NULL; dns_packet_unref(&packet); return 0; } int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) { const char *n; int r; assert(rr); assert(ret); /* Returns the RRset's signer, if it is known. */ if (rr->n_skip_labels_signer == (unsigned) -1) return -ENODATA; n = DNS_RESOURCE_KEY_NAME(rr->key); r = dns_name_skip(n, rr->n_skip_labels_signer, &n); if (r < 0) return r; if (r == 0) return -EINVAL; *ret = n; return 0; } int dns_resource_record_source(DnsResourceRecord *rr, const char **ret) { const char *n; int r; assert(rr); assert(ret); /* Returns the RRset's synthesizing source, if it is known. */ if (rr->n_skip_labels_source == (unsigned) -1) return -ENODATA; n = DNS_RESOURCE_KEY_NAME(rr->key); r = dns_name_skip(n, rr->n_skip_labels_source, &n); if (r < 0) return r; if (r == 0) return -EINVAL; *ret = n; return 0; } int dns_resource_record_is_signer(DnsResourceRecord *rr, const char *zone) { const char *signer; int r; assert(rr); r = dns_resource_record_signer(rr, &signer); if (r < 0) return r; return dns_name_equal(zone, signer); } int dns_resource_record_is_synthetic(DnsResourceRecord *rr) { int r; assert(rr); /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */ if (rr->n_skip_labels_source == (unsigned) -1) return -ENODATA; if (rr->n_skip_labels_source == 0) return 0; if (rr->n_skip_labels_source > 1) return 1; r = dns_name_startswith(DNS_RESOURCE_KEY_NAME(rr->key), "*"); if (r < 0) return r; return !r; } static void dns_resource_record_hash_func(const void *i, struct siphash *state) { const DnsResourceRecord *rr = i; assert(rr); dns_resource_key_hash_func(rr->key, state); switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { case DNS_TYPE_SRV: siphash24_compress(&rr->srv.priority, sizeof(rr->srv.priority), state); siphash24_compress(&rr->srv.weight, sizeof(rr->srv.weight), state); siphash24_compress(&rr->srv.port, sizeof(rr->srv.port), state); dns_name_hash_func(rr->srv.name, state); break; case DNS_TYPE_PTR: case DNS_TYPE_NS: case DNS_TYPE_CNAME: case DNS_TYPE_DNAME: dns_name_hash_func(rr->ptr.name, state); break; case DNS_TYPE_HINFO: string_hash_func(rr->hinfo.cpu, state); string_hash_func(rr->hinfo.os, state); break; case DNS_TYPE_TXT: case DNS_TYPE_SPF: { DnsTxtItem *j; LIST_FOREACH(items, j, rr->txt.items) { siphash24_compress(j->data, j->length, state); /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab" * followed by "". */ siphash24_compress_byte(0, state); } break; } case DNS_TYPE_A: siphash24_compress(&rr->a.in_addr, sizeof(rr->a.in_addr), state); break; case DNS_TYPE_AAAA: siphash24_compress(&rr->aaaa.in6_addr, sizeof(rr->aaaa.in6_addr), state); break; case DNS_TYPE_SOA: dns_name_hash_func(rr->soa.mname, state); dns_name_hash_func(rr->soa.rname, state); siphash24_compress(&rr->soa.serial, sizeof(rr->soa.serial), state); siphash24_compress(&rr->soa.refresh, sizeof(rr->soa.refresh), state); siphash24_compress(&rr->soa.retry, sizeof(rr->soa.retry), state); siphash24_compress(&rr->soa.expire, sizeof(rr->soa.expire), state); siphash24_compress(&rr->soa.minimum, sizeof(rr->soa.minimum), state); break; case DNS_TYPE_MX: siphash24_compress(&rr->mx.priority, sizeof(rr->mx.priority), state); dns_name_hash_func(rr->mx.exchange, state); break; case DNS_TYPE_LOC: siphash24_compress(&rr->loc.version, sizeof(rr->loc.version), state); siphash24_compress(&rr->loc.size, sizeof(rr->loc.size), state); siphash24_compress(&rr->loc.horiz_pre, sizeof(rr->loc.horiz_pre), state); siphash24_compress(&rr->loc.vert_pre, sizeof(rr->loc.vert_pre), state); siphash24_compress(&rr->loc.latitude, sizeof(rr->loc.latitude), state); siphash24_compress(&rr->loc.longitude, sizeof(rr->loc.longitude), state); siphash24_compress(&rr->loc.altitude, sizeof(rr->loc.altitude), state); break; case DNS_TYPE_SSHFP: siphash24_compress(&rr->sshfp.algorithm, sizeof(rr->sshfp.algorithm), state); siphash24_compress(&rr->sshfp.fptype, sizeof(rr->sshfp.fptype), state); siphash24_compress(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, state); break; case DNS_TYPE_DNSKEY: siphash24_compress(&rr->dnskey.flags, sizeof(rr->dnskey.flags), state); siphash24_compress(&rr->dnskey.protocol, sizeof(rr->dnskey.protocol), state); siphash24_compress(&rr->dnskey.algorithm, sizeof(rr->dnskey.algorithm), state); siphash24_compress(rr->dnskey.key, rr->dnskey.key_size, state); break; case DNS_TYPE_RRSIG: siphash24_compress(&rr->rrsig.type_covered, sizeof(rr->rrsig.type_covered), state); siphash24_compress(&rr->rrsig.algorithm, sizeof(rr->rrsig.algorithm), state); siphash24_compress(&rr->rrsig.labels, sizeof(rr->rrsig.labels), state); siphash24_compress(&rr->rrsig.original_ttl, sizeof(rr->rrsig.original_ttl), state); siphash24_compress(&rr->rrsig.expiration, sizeof(rr->rrsig.expiration), state); siphash24_compress(&rr->rrsig.inception, sizeof(rr->rrsig.inception), state); siphash24_compress(&rr->rrsig.key_tag, sizeof(rr->rrsig.key_tag), state); dns_name_hash_func(rr->rrsig.signer, state); siphash24_compress(rr->rrsig.signature, rr->rrsig.signature_size, state); break; case DNS_TYPE_NSEC: dns_name_hash_func(rr->nsec.next_domain_name, state); /* FIXME: we leave out the type bitmap here. Hash * would be better if we'd take it into account * too. */ break; case DNS_TYPE_DS: siphash24_compress(&rr->ds.key_tag, sizeof(rr->ds.key_tag), state); siphash24_compress(&rr->ds.algorithm, sizeof(rr->ds.algorithm), state); siphash24_compress(&rr->ds.digest_type, sizeof(rr->ds.digest_type), state); siphash24_compress(rr->ds.digest, rr->ds.digest_size, state); break; case DNS_TYPE_NSEC3: siphash24_compress(&rr->nsec3.algorithm, sizeof(rr->nsec3.algorithm), state); siphash24_compress(&rr->nsec3.flags, sizeof(rr->nsec3.flags), state); siphash24_compress(&rr->nsec3.iterations, sizeof(rr->nsec3.iterations), state); siphash24_compress(rr->nsec3.salt, rr->nsec3.salt_size, state); siphash24_compress(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, state); /* FIXME: We leave the bitmaps out */ break; case DNS_TYPE_TLSA: siphash24_compress(&rr->tlsa.cert_usage, sizeof(rr->tlsa.cert_usage), state); siphash24_compress(&rr->tlsa.selector, sizeof(rr->tlsa.selector), state); siphash24_compress(&rr->tlsa.matching_type, sizeof(rr->tlsa.matching_type), state); siphash24_compress(&rr->tlsa.data, rr->tlsa.data_size, state); break; case DNS_TYPE_OPENPGPKEY: default: siphash24_compress(rr->generic.data, rr->generic.data_size, state); break; } } static int dns_resource_record_compare_func(const void *a, const void *b) { const DnsResourceRecord *x = a, *y = b; int ret; ret = dns_resource_key_compare_func(x->key, y->key); if (ret != 0) return ret; if (dns_resource_record_equal(x, y)) return 0; /* This is a bit dirty, we don't implement proper ordering, but * the hashtable doesn't need ordering anyway, hence we don't * care. */ return x < y ? -1 : 1; } const struct hash_ops dns_resource_record_hash_ops = { .hash = dns_resource_record_hash_func, .compare = dns_resource_record_compare_func, }; DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i) { DnsTxtItem *n; if (!i) return NULL; n = i->items_next; free(i); return dns_txt_item_free_all(n); } bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b) { if (a == b) return true; if (!a != !b) return false; if (!a) return true; if (a->length != b->length) return false; if (memcmp(a->data, b->data, a->length) != 0) return false; return dns_txt_item_equal(a->items_next, b->items_next); } static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = { /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */ [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5", [DNSSEC_ALGORITHM_DH] = "DH", [DNSSEC_ALGORITHM_DSA] = "DSA", [DNSSEC_ALGORITHM_ECC] = "ECC", [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1", [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1] = "DSA-NSEC3-SHA1", [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1", [DNSSEC_ALGORITHM_RSASHA256] = "RSASHA256", [DNSSEC_ALGORITHM_RSASHA512] = "RSASHA512", [DNSSEC_ALGORITHM_ECC_GOST] = "ECC-GOST", [DNSSEC_ALGORITHM_ECDSAP256SHA256] = "ECDSAP256SHA256", [DNSSEC_ALGORITHM_ECDSAP384SHA384] = "ECDSAP384SHA384", [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT", [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS", [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID", }; DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm, int, 255); static const char* const dnssec_digest_table[_DNSSEC_DIGEST_MAX_DEFINED] = { /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */ [DNSSEC_DIGEST_SHA1] = "SHA-1", [DNSSEC_DIGEST_SHA256] = "SHA-256", [DNSSEC_DIGEST_GOST_R_34_11_94] = "GOST_R_34.11-94", [DNSSEC_DIGEST_SHA384] = "SHA-384", }; DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest, int, 255); systemd-229/src/resolve/resolved-dns-rr.h000066400000000000000000000277611265713322000205430ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "bitmap.h" #include "dns-type.h" #include "hashmap.h" #include "in-addr-util.h" #include "list.h" typedef struct DnsResourceKey DnsResourceKey; typedef struct DnsResourceRecord DnsResourceRecord; typedef struct DnsTxtItem DnsTxtItem; /* DNSKEY RR flags */ #define DNSKEY_FLAG_SEP (UINT16_C(1) << 0) #define DNSKEY_FLAG_REVOKE (UINT16_C(1) << 7) #define DNSKEY_FLAG_ZONE_KEY (UINT16_C(1) << 8) /* mDNS RR flags */ #define MDNS_RR_CACHE_FLUSH (UINT16_C(1) << 15) /* DNSSEC algorithm identifiers, see * http://tools.ietf.org/html/rfc4034#appendix-A.1 and * https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */ enum { DNSSEC_ALGORITHM_RSAMD5 = 1, DNSSEC_ALGORITHM_DH, DNSSEC_ALGORITHM_DSA, DNSSEC_ALGORITHM_ECC, DNSSEC_ALGORITHM_RSASHA1, DNSSEC_ALGORITHM_DSA_NSEC3_SHA1, DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1, DNSSEC_ALGORITHM_RSASHA256 = 8, /* RFC 5702 */ DNSSEC_ALGORITHM_RSASHA512 = 10, /* RFC 5702 */ DNSSEC_ALGORITHM_ECC_GOST = 12, /* RFC 5933 */ DNSSEC_ALGORITHM_ECDSAP256SHA256 = 13, /* RFC 6605 */ DNSSEC_ALGORITHM_ECDSAP384SHA384 = 14, /* RFC 6605 */ DNSSEC_ALGORITHM_INDIRECT = 252, DNSSEC_ALGORITHM_PRIVATEDNS, DNSSEC_ALGORITHM_PRIVATEOID, _DNSSEC_ALGORITHM_MAX_DEFINED }; /* DNSSEC digest identifiers, see * https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */ enum { DNSSEC_DIGEST_SHA1 = 1, DNSSEC_DIGEST_SHA256 = 2, /* RFC 4509 */ DNSSEC_DIGEST_GOST_R_34_11_94 = 3, /* RFC 5933 */ DNSSEC_DIGEST_SHA384 = 4, /* RFC 6605 */ _DNSSEC_DIGEST_MAX_DEFINED }; /* DNSSEC NSEC3 hash algorithms, see * https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */ enum { NSEC3_ALGORITHM_SHA1 = 1, _NSEC3_ALGORITHM_MAX_DEFINED }; struct DnsResourceKey { unsigned n_ref; /* (unsigned -1) for const keys, see below */ uint16_t class, type; char *_name; /* don't access directy, use DNS_RESOURCE_KEY_NAME()! */ }; /* Creates a temporary resource key. This is only useful to quickly * look up something, without allocating a full DnsResourceKey object * for it. Note that it is not OK to take references to this kind of * resource key object. */ #define DNS_RESOURCE_KEY_CONST(c, t, n) \ ((DnsResourceKey) { \ .n_ref = (unsigned) -1, \ .class = c, \ .type = t, \ ._name = (char*) n, \ }) struct DnsTxtItem { size_t length; LIST_FIELDS(DnsTxtItem, items); uint8_t data[]; }; struct DnsResourceRecord { unsigned n_ref; DnsResourceKey *key; char *to_string; uint32_t ttl; usec_t expiry; /* RRSIG signature expiry */ /* How many labels to strip to determine "signer" of the RRSIG (aka, the zone). -1 if not signed. */ unsigned n_skip_labels_signer; /* How many labels to strip to determine "synthesizing source" of this RR, i.e. the wildcard's immediate parent. -1 if not signed. */ unsigned n_skip_labels_source; bool unparseable:1; bool wire_format_canonical:1; void *wire_format; size_t wire_format_size; size_t wire_format_rdata_offset; union { struct { void *data; size_t data_size; } generic, opt; struct { uint16_t priority; uint16_t weight; uint16_t port; char *name; } srv; struct { char *name; } ptr, ns, cname, dname; struct { char *cpu; char *os; } hinfo; struct { DnsTxtItem *items; } txt, spf; struct { struct in_addr in_addr; } a; struct { struct in6_addr in6_addr; } aaaa; struct { char *mname; char *rname; uint32_t serial; uint32_t refresh; uint32_t retry; uint32_t expire; uint32_t minimum; } soa; struct { uint16_t priority; char *exchange; } mx; /* https://tools.ietf.org/html/rfc1876 */ struct { uint8_t version; uint8_t size; uint8_t horiz_pre; uint8_t vert_pre; uint32_t latitude; uint32_t longitude; uint32_t altitude; } loc; /* https://tools.ietf.org/html/rfc4255#section-3.1 */ struct { uint8_t algorithm; uint8_t fptype; void *fingerprint; size_t fingerprint_size; } sshfp; /* http://tools.ietf.org/html/rfc4034#section-2.1 */ struct { uint16_t flags; uint8_t protocol; uint8_t algorithm; void* key; size_t key_size; } dnskey; /* http://tools.ietf.org/html/rfc4034#section-3.1 */ struct { uint16_t type_covered; uint8_t algorithm; uint8_t labels; uint32_t original_ttl; uint32_t expiration; uint32_t inception; uint16_t key_tag; char *signer; void *signature; size_t signature_size; } rrsig; /* https://tools.ietf.org/html/rfc4034#section-4.1 */ struct { char *next_domain_name; Bitmap *types; } nsec; /* https://tools.ietf.org/html/rfc4034#section-5.1 */ struct { uint16_t key_tag; uint8_t algorithm; uint8_t digest_type; void *digest; size_t digest_size; } ds; struct { uint8_t algorithm; uint8_t flags; uint16_t iterations; void *salt; size_t salt_size; void *next_hashed_name; size_t next_hashed_name_size; Bitmap *types; } nsec3; /* https://tools.ietf.org/html/draft-ietf-dane-protocol-23 */ struct { uint8_t cert_usage; uint8_t selector; uint8_t matching_type; void *data; size_t data_size; } tlsa; }; }; static inline const char* DNS_RESOURCE_KEY_NAME(const DnsResourceKey *key) { if (!key) return NULL; if (key->_name) return key->_name; return (char*) key + sizeof(DnsResourceKey); } static inline const void* DNS_RESOURCE_RECORD_RDATA(DnsResourceRecord *rr) { if (!rr) return NULL; if (!rr->wire_format) return NULL; assert(rr->wire_format_rdata_offset <= rr->wire_format_size); return (uint8_t*) rr->wire_format + rr->wire_format_rdata_offset; } static inline size_t DNS_RESOURCE_RECORD_RDATA_SIZE(DnsResourceRecord *rr) { if (!rr) return 0; if (!rr->wire_format) return 0; assert(rr->wire_format_rdata_offset <= rr->wire_format_size); return rr->wire_format_size - rr->wire_format_rdata_offset; } DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name); DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname); int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name); DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name); DnsResourceKey* dns_resource_key_ref(DnsResourceKey *key); DnsResourceKey* dns_resource_key_unref(DnsResourceKey *key); bool dns_resource_key_is_address(const DnsResourceKey *key); int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b); int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain); int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain); int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa); int dns_resource_key_to_string(const DnsResourceKey *key, char **ret); DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceKey*, dns_resource_key_unref); static inline bool dns_key_is_shared(const DnsResourceKey *key) { return IN_SET(key->type, DNS_TYPE_PTR); } bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b); DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key); DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name); DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr); DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr); int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name); int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name); int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b); const char* dns_resource_record_to_string(DnsResourceRecord *rr); DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceRecord*, dns_resource_record_unref); int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical); int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret); int dns_resource_record_source(DnsResourceRecord *rr, const char **ret); int dns_resource_record_is_signer(DnsResourceRecord *rr, const char *zone); int dns_resource_record_is_synthetic(DnsResourceRecord *rr); DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i); bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b); extern const struct hash_ops dns_resource_key_hash_ops; extern const struct hash_ops dns_resource_record_hash_ops; int dnssec_algorithm_to_string_alloc(int i, char **ret); int dnssec_algorithm_from_string(const char *s) _pure_; int dnssec_digest_to_string_alloc(int i, char **ret); int dnssec_digest_from_string(const char *s) _pure_; systemd-229/src/resolve/resolved-dns-scope.c000066400000000000000000001046221265713322000212140ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "af-list.h" #include "alloc-util.h" #include "dns-domain.h" #include "fd-util.h" #include "hostname-util.h" #include "missing.h" #include "random-util.h" #include "resolved-dns-scope.h" #include "resolved-llmnr.h" #include "resolved-mdns.h" #include "socket-util.h" #include "strv.h" #define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC) #define MULTICAST_RATELIMIT_BURST 1000 /* After how much time to repeat LLMNR requests, see RFC 4795 Section 7 */ #define MULTICAST_RESEND_TIMEOUT_MIN_USEC (100 * USEC_PER_MSEC) #define MULTICAST_RESEND_TIMEOUT_MAX_USEC (1 * USEC_PER_SEC) int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int family) { DnsScope *s; assert(m); assert(ret); s = new0(DnsScope, 1); if (!s) return -ENOMEM; s->manager = m; s->link = l; s->protocol = protocol; s->family = family; s->resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC; if (protocol == DNS_PROTOCOL_DNS) { /* Copy DNSSEC mode from the link if it is set there, * otherwise take the manager's DNSSEC mode. Note that * we copy this only at scope creation time, and do * not update it from the on, even if the setting * changes. */ if (l) s->dnssec_mode = link_get_dnssec_mode(l); else s->dnssec_mode = manager_get_dnssec_mode(m); } else s->dnssec_mode = DNSSEC_NO; LIST_PREPEND(scopes, m->dns_scopes, s); dns_scope_llmnr_membership(s, true); dns_scope_mdns_membership(s, true); log_debug("New scope on link %s, protocol %s, family %s", l ? l->name : "*", dns_protocol_to_string(protocol), family == AF_UNSPEC ? "*" : af_to_name(family)); /* Enforce ratelimiting for the multicast protocols */ RATELIMIT_INIT(s->ratelimit, MULTICAST_RATELIMIT_INTERVAL_USEC, MULTICAST_RATELIMIT_BURST); *ret = s; return 0; } static void dns_scope_abort_transactions(DnsScope *s) { assert(s); while (s->transactions) { DnsTransaction *t = s->transactions; /* Abort the transaction, but make sure it is not * freed while we still look at it */ t->block_gc++; if (DNS_TRANSACTION_IS_LIVE(t->state)) dns_transaction_complete(t, DNS_TRANSACTION_ABORTED); t->block_gc--; dns_transaction_free(t); } } DnsScope* dns_scope_free(DnsScope *s) { DnsResourceRecord *rr; if (!s) return NULL; log_debug("Removing scope on link %s, protocol %s, family %s", s->link ? s->link->name : "*", dns_protocol_to_string(s->protocol), s->family == AF_UNSPEC ? "*" : af_to_name(s->family)); dns_scope_llmnr_membership(s, false); dns_scope_mdns_membership(s, false); dns_scope_abort_transactions(s); while (s->query_candidates) dns_query_candidate_free(s->query_candidates); hashmap_free(s->transactions_by_key); while ((rr = ordered_hashmap_steal_first(s->conflict_queue))) dns_resource_record_unref(rr); ordered_hashmap_free(s->conflict_queue); sd_event_source_unref(s->conflict_event_source); dns_cache_flush(&s->cache); dns_zone_flush(&s->zone); LIST_REMOVE(scopes, s->manager->dns_scopes, s); free(s); return NULL; } DnsServer *dns_scope_get_dns_server(DnsScope *s) { assert(s); if (s->protocol != DNS_PROTOCOL_DNS) return NULL; if (s->link) return link_get_dns_server(s->link); else return manager_get_dns_server(s->manager); } void dns_scope_next_dns_server(DnsScope *s) { assert(s); if (s->protocol != DNS_PROTOCOL_DNS) return; if (s->link) link_next_dns_server(s->link); else manager_next_dns_server(s->manager); } void dns_scope_packet_received(DnsScope *s, usec_t rtt) { assert(s); if (rtt <= s->max_rtt) return; s->max_rtt = rtt; s->resend_timeout = MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC, s->max_rtt * 2), MULTICAST_RESEND_TIMEOUT_MAX_USEC); } void dns_scope_packet_lost(DnsScope *s, usec_t usec) { assert(s); if (s->resend_timeout <= usec) s->resend_timeout = MIN(s->resend_timeout * 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC); } static int dns_scope_emit_one(DnsScope *s, int fd, DnsPacket *p) { union in_addr_union addr; int ifindex = 0, r; int family; uint32_t mtu; assert(s); assert(p); assert(p->protocol == s->protocol); if (s->link) { mtu = s->link->mtu; ifindex = s->link->ifindex; } else mtu = manager_find_mtu(s->manager); switch (s->protocol) { case DNS_PROTOCOL_DNS: assert(fd >= 0); if (DNS_PACKET_QDCOUNT(p) > 1) return -EOPNOTSUPP; if (p->size > DNS_PACKET_UNICAST_SIZE_MAX) return -EMSGSIZE; if (p->size + UDP_PACKET_HEADER_SIZE > mtu) return -EMSGSIZE; r = manager_write(s->manager, fd, p); if (r < 0) return r; break; case DNS_PROTOCOL_LLMNR: assert(fd < 0); if (DNS_PACKET_QDCOUNT(p) > 1) return -EOPNOTSUPP; if (!ratelimit_test(&s->ratelimit)) return -EBUSY; family = s->family; if (family == AF_INET) { addr.in = LLMNR_MULTICAST_IPV4_ADDRESS; fd = manager_llmnr_ipv4_udp_fd(s->manager); } else if (family == AF_INET6) { addr.in6 = LLMNR_MULTICAST_IPV6_ADDRESS; fd = manager_llmnr_ipv6_udp_fd(s->manager); } else return -EAFNOSUPPORT; if (fd < 0) return fd; r = manager_send(s->manager, fd, ifindex, family, &addr, LLMNR_PORT, p); if (r < 0) return r; break; case DNS_PROTOCOL_MDNS: assert(fd < 0); if (!ratelimit_test(&s->ratelimit)) return -EBUSY; family = s->family; if (family == AF_INET) { addr.in = MDNS_MULTICAST_IPV4_ADDRESS; fd = manager_mdns_ipv4_fd(s->manager); } else if (family == AF_INET6) { addr.in6 = MDNS_MULTICAST_IPV6_ADDRESS; fd = manager_mdns_ipv6_fd(s->manager); } else return -EAFNOSUPPORT; if (fd < 0) return fd; r = manager_send(s->manager, fd, ifindex, family, &addr, MDNS_PORT, p); if (r < 0) return r; break; default: return -EAFNOSUPPORT; } return 1; } int dns_scope_emit_udp(DnsScope *s, int fd, DnsPacket *p) { int r; assert(s); assert(p); assert(p->protocol == s->protocol); assert((s->protocol == DNS_PROTOCOL_DNS) == (fd >= 0)); do { /* If there are multiple linked packets, set the TC bit in all but the last of them */ if (p->more) { assert(p->protocol == DNS_PROTOCOL_MDNS); dns_packet_set_flags(p, true, true); } r = dns_scope_emit_one(s, fd, p); if (r < 0) return r; p = p->more; } while (p); return 0; } static int dns_scope_socket( DnsScope *s, int type, int family, const union in_addr_union *address, DnsServer *server, uint16_t port) { _cleanup_close_ int fd = -1; union sockaddr_union sa = {}; socklen_t salen; static const int one = 1; int ret, r; assert(s); if (server) { assert(family == AF_UNSPEC); assert(!address); sa.sa.sa_family = server->family; if (server->family == AF_INET) { sa.in.sin_port = htobe16(port); sa.in.sin_addr = server->address.in; salen = sizeof(sa.in); } else if (server->family == AF_INET6) { sa.in6.sin6_port = htobe16(port); sa.in6.sin6_addr = server->address.in6; sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0; salen = sizeof(sa.in6); } else return -EAFNOSUPPORT; } else { assert(family != AF_UNSPEC); assert(address); sa.sa.sa_family = family; if (family == AF_INET) { sa.in.sin_port = htobe16(port); sa.in.sin_addr = address->in; salen = sizeof(sa.in); } else if (family == AF_INET6) { sa.in6.sin6_port = htobe16(port); sa.in6.sin6_addr = address->in6; sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0; salen = sizeof(sa.in6); } else return -EAFNOSUPPORT; } fd = socket(sa.sa.sa_family, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (fd < 0) return -errno; if (type == SOCK_STREAM) { r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); if (r < 0) return -errno; } if (s->link) { uint32_t ifindex = htobe32(s->link->ifindex); if (sa.sa.sa_family == AF_INET) { r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex)); if (r < 0) return -errno; } else if (sa.sa.sa_family == AF_INET6) { r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex)); if (r < 0) return -errno; } } if (s->protocol == DNS_PROTOCOL_LLMNR) { /* RFC 4795, section 2.5 requires the TTL to be set to 1 */ if (sa.sa.sa_family == AF_INET) { r = setsockopt(fd, IPPROTO_IP, IP_TTL, &one, sizeof(one)); if (r < 0) return -errno; } else if (sa.sa.sa_family == AF_INET6) { r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one)); if (r < 0) return -errno; } } r = connect(fd, &sa.sa, salen); if (r < 0 && errno != EINPROGRESS) return -errno; ret = fd; fd = -1; return ret; } int dns_scope_socket_udp(DnsScope *s, DnsServer *server, uint16_t port) { return dns_scope_socket(s, SOCK_DGRAM, AF_UNSPEC, NULL, server, port); } int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port) { return dns_scope_socket(s, SOCK_STREAM, family, address, server, port); } DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) { DnsSearchDomain *d; assert(s); assert(domain); /* Checks if the specified domain is something to look up on * this scope. Note that this accepts non-qualified hostnames, * i.e. those without any search path prefixed yet. */ if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex)) return DNS_SCOPE_NO; if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, 0) & flags) == 0) return DNS_SCOPE_NO; /* Never resolve any loopback hostname or IP address via DNS, * LLMNR or mDNS. Instead, always rely on synthesized RRs for * these. */ if (is_localhost(domain) || dns_name_endswith(domain, "127.in-addr.arpa") > 0 || dns_name_equal(domain, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) return DNS_SCOPE_NO; /* Never respond to some of the domains listed in RFC6303 */ if (dns_name_endswith(domain, "0.in-addr.arpa") > 0 || dns_name_equal(domain, "255.255.255.255.in-addr.arpa") > 0 || dns_name_equal(domain, "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) return DNS_SCOPE_NO; /* Never respond to some of the domains listed in RFC6761 */ if (dns_name_endswith(domain, "invalid") > 0) return DNS_SCOPE_NO; /* Always honour search domains for routing queries. Note that * we return DNS_SCOPE_YES here, rather than just * DNS_SCOPE_MAYBE, which means wildcard scopes won't be * considered anymore. */ LIST_FOREACH(domains, d, dns_scope_get_search_domains(s)) if (dns_name_endswith(domain, d->name) > 0) return DNS_SCOPE_YES; switch (s->protocol) { case DNS_PROTOCOL_DNS: /* Exclude link-local IP ranges */ if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 && dns_name_endswith(domain, "8.e.f.ip6.arpa") == 0 && dns_name_endswith(domain, "9.e.f.ip6.arpa") == 0 && dns_name_endswith(domain, "a.e.f.ip6.arpa") == 0 && dns_name_endswith(domain, "b.e.f.ip6.arpa") == 0 && /* If networks use .local in their private setups, they are supposed to also add .local to their search * domains, which we already checked above. Otherwise, we consider .local specific to mDNS and won't * send such queries ordinary DNS servers. */ dns_name_endswith(domain, "local") == 0) return DNS_SCOPE_MAYBE; return DNS_SCOPE_NO; case DNS_PROTOCOL_MDNS: if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) || (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) || (dns_name_endswith(domain, "local") > 0 && /* only resolve names ending in .local via mDNS */ dns_name_equal(domain, "local") == 0 && /* but not the single-label "local" name itself */ manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via mDNS */ return DNS_SCOPE_MAYBE; return DNS_SCOPE_NO; case DNS_PROTOCOL_LLMNR: if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) || (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) || (dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */ !is_gateway_hostname(domain) && /* don't resolve "gateway" with LLMNR, let nss-myhostname handle this */ manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via LLMNR */ return DNS_SCOPE_MAYBE; return DNS_SCOPE_NO; default: assert_not_reached("Unknown scope protocol"); } } bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key) { int key_family; assert(s); assert(key); /* Check if it makes sense to resolve the specified key on * this scope. Note that this call assumes as fully qualified * name, i.e. the search suffixes already appended. */ if (key->class != DNS_CLASS_IN) return false; if (s->protocol == DNS_PROTOCOL_DNS) { /* On classic DNS, looking up non-address RRs is always * fine. (Specifically, we want to permit looking up * DNSKEY and DS records on the root and top-level * domains.) */ if (!dns_resource_key_is_address(key)) return true; /* However, we refuse to look up A and AAAA RRs on the * root and single-label domains, under the assumption * that those should be resolved via LLMNR or search * path only, and should not be leaked onto the * internet. */ return !(dns_name_is_single_label(DNS_RESOURCE_KEY_NAME(key)) || dns_name_is_root(DNS_RESOURCE_KEY_NAME(key))); } /* On mDNS and LLMNR, send A and AAAA queries only on the * respective scopes */ key_family = dns_type_to_af(key->type); if (key_family < 0) return true; return key_family == s->family; } static int dns_scope_multicast_membership(DnsScope *s, bool b, struct in_addr in, struct in6_addr in6) { int fd; assert(s); assert(s->link); if (s->family == AF_INET) { struct ip_mreqn mreqn = { .imr_multiaddr = in, .imr_ifindex = s->link->ifindex, }; fd = manager_llmnr_ipv4_udp_fd(s->manager); if (fd < 0) return fd; /* Always first try to drop membership before we add * one. This is necessary on some devices, such as * veth. */ if (b) (void) setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)); if (setsockopt(fd, IPPROTO_IP, b ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0) return -errno; } else if (s->family == AF_INET6) { struct ipv6_mreq mreq = { .ipv6mr_multiaddr = in6, .ipv6mr_interface = s->link->ifindex, }; fd = manager_llmnr_ipv6_udp_fd(s->manager); if (fd < 0) return fd; if (b) (void) setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); if (setsockopt(fd, IPPROTO_IPV6, b ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) return -errno; } else return -EAFNOSUPPORT; return 0; } int dns_scope_llmnr_membership(DnsScope *s, bool b) { if (s->protocol != DNS_PROTOCOL_LLMNR) return 0; return dns_scope_multicast_membership(s, b, LLMNR_MULTICAST_IPV4_ADDRESS, LLMNR_MULTICAST_IPV6_ADDRESS); } int dns_scope_mdns_membership(DnsScope *s, bool b) { if (s->protocol != DNS_PROTOCOL_MDNS) return 0; return dns_scope_multicast_membership(s, b, MDNS_MULTICAST_IPV4_ADDRESS, MDNS_MULTICAST_IPV6_ADDRESS); } static int dns_scope_make_reply_packet( DnsScope *s, uint16_t id, int rcode, DnsQuestion *q, DnsAnswer *answer, DnsAnswer *soa, bool tentative, DnsPacket **ret) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; unsigned i; int r; assert(s); assert(ret); if ((!q || q->n_keys <= 0) && (!answer || answer->n_rrs <= 0) && (!soa || soa->n_rrs <= 0)) return -EINVAL; r = dns_packet_new(&p, s->protocol, 0); if (r < 0) return r; DNS_PACKET_HEADER(p)->id = id; DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS( 1 /* qr */, 0 /* opcode */, 0 /* c */, 0 /* tc */, tentative, 0 /* (ra) */, 0 /* (ad) */, 0 /* (cd) */, rcode)); if (q) { for (i = 0; i < q->n_keys; i++) { r = dns_packet_append_key(p, q->keys[i], NULL); if (r < 0) return r; } DNS_PACKET_HEADER(p)->qdcount = htobe16(q->n_keys); } if (answer) { for (i = 0; i < answer->n_rrs; i++) { r = dns_packet_append_rr(p, answer->items[i].rr, NULL, NULL); if (r < 0) return r; } DNS_PACKET_HEADER(p)->ancount = htobe16(answer->n_rrs); } if (soa) { for (i = 0; i < soa->n_rrs; i++) { r = dns_packet_append_rr(p, soa->items[i].rr, NULL, NULL); if (r < 0) return r; } DNS_PACKET_HEADER(p)->arcount = htobe16(soa->n_rrs); } *ret = p; p = NULL; return 0; } static void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) { unsigned n; assert(s); assert(p); if (p->question) for (n = 0; n < p->question->n_keys; n++) dns_zone_verify_conflicts(&s->zone, p->question->keys[n]); if (p->answer) for (n = 0; n < p->answer->n_rrs; n++) dns_zone_verify_conflicts(&s->zone, p->answer->items[n].rr->key); } void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) { _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL; _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL; DnsResourceKey *key = NULL; bool tentative = false; int r, fd; assert(s); assert(p); if (p->protocol != DNS_PROTOCOL_LLMNR) return; if (p->ipproto == IPPROTO_UDP) { /* Don't accept UDP queries directed to anything but * the LLMNR multicast addresses. See RFC 4795, * section 2.5. */ if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS)) return; if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS)) return; } r = dns_packet_extract(p); if (r < 0) { log_debug_errno(r, "Failed to extract resources from incoming packet: %m"); return; } if (DNS_PACKET_LLMNR_C(p)) { /* Somebody notified us about a possible conflict */ dns_scope_verify_conflicts(s, p); return; } assert(p->question->n_keys == 1); key = p->question->keys[0]; r = dns_zone_lookup(&s->zone, key, &answer, &soa, &tentative); if (r < 0) { log_debug_errno(r, "Failed to lookup key: %m"); return; } if (r == 0) return; if (answer) dns_answer_order_by_scope(answer, in_addr_is_link_local(p->family, &p->sender) > 0); r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, soa, tentative, &reply); if (r < 0) { log_debug_errno(r, "Failed to build reply packet: %m"); return; } if (stream) r = dns_stream_write_packet(stream, reply); else { if (!ratelimit_test(&s->ratelimit)) return; if (p->family == AF_INET) fd = manager_llmnr_ipv4_udp_fd(s->manager); else if (p->family == AF_INET6) fd = manager_llmnr_ipv6_udp_fd(s->manager); else { log_debug("Unknown protocol"); return; } if (fd < 0) { log_debug_errno(fd, "Failed to get reply socket: %m"); return; } /* Note that we always immediately reply to all LLMNR * requests, and do not wait any time, since we * verified uniqueness for all records. Also see RFC * 4795, Section 2.7 */ r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, reply); } if (r < 0) { log_debug_errno(r, "Failed to send reply packet: %m"); return; } } DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok) { DnsTransaction *t; assert(scope); assert(key); /* Try to find an ongoing transaction that is a equal to the * specified question */ t = hashmap_get(scope->transactions_by_key, key); if (!t) return NULL; /* Refuse reusing transactions that completed based on cached * data instead of a real packet, if that's requested. */ if (!cache_ok && IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_RCODE_FAILURE) && t->answer_source != DNS_TRANSACTION_NETWORK) return NULL; return t; } static int dns_scope_make_conflict_packet( DnsScope *s, DnsResourceRecord *rr, DnsPacket **ret) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; int r; assert(s); assert(rr); assert(ret); r = dns_packet_new(&p, s->protocol, 0); if (r < 0) return r; DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS( 0 /* qr */, 0 /* opcode */, 1 /* conflict */, 0 /* tc */, 0 /* t */, 0 /* (ra) */, 0 /* (ad) */, 0 /* (cd) */, 0)); /* For mDNS, the transaction ID should always be 0 */ if (s->protocol != DNS_PROTOCOL_MDNS) random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t)); DNS_PACKET_HEADER(p)->qdcount = htobe16(1); DNS_PACKET_HEADER(p)->arcount = htobe16(1); r = dns_packet_append_key(p, rr->key, NULL); if (r < 0) return r; r = dns_packet_append_rr(p, rr, NULL, NULL); if (r < 0) return r; *ret = p; p = NULL; return 0; } static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata) { DnsScope *scope = userdata; int r; assert(es); assert(scope); scope->conflict_event_source = sd_event_source_unref(scope->conflict_event_source); for (;;) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; rr = ordered_hashmap_steal_first(scope->conflict_queue); if (!rr) break; r = dns_scope_make_conflict_packet(scope, rr, &p); if (r < 0) { log_error_errno(r, "Failed to make conflict packet: %m"); return 0; } r = dns_scope_emit_udp(scope, -1, p); if (r < 0) log_debug_errno(r, "Failed to send conflict packet: %m"); } return 0; } int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr) { usec_t jitter; int r; assert(scope); assert(rr); /* We don't send these queries immediately. Instead, we queue * them, and send them after some jitter delay. */ r = ordered_hashmap_ensure_allocated(&scope->conflict_queue, &dns_resource_key_hash_ops); if (r < 0) { log_oom(); return r; } /* We only place one RR per key in the conflict * messages, not all of them. That should be enough to * indicate where there might be a conflict */ r = ordered_hashmap_put(scope->conflict_queue, rr->key, rr); if (r == -EEXIST || r == 0) return 0; if (r < 0) return log_debug_errno(r, "Failed to queue conflicting RR: %m"); dns_resource_record_ref(rr); if (scope->conflict_event_source) return 0; random_bytes(&jitter, sizeof(jitter)); jitter %= LLMNR_JITTER_INTERVAL_USEC; r = sd_event_add_time(scope->manager->event, &scope->conflict_event_source, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + jitter, LLMNR_JITTER_INTERVAL_USEC, on_conflict_dispatch, scope); if (r < 0) return log_debug_errno(r, "Failed to add conflict dispatch event: %m"); (void) sd_event_source_set_description(scope->conflict_event_source, "scope-conflict"); return 0; } void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p) { unsigned i; int r; assert(scope); assert(p); if (p->protocol != DNS_PROTOCOL_LLMNR) return; if (DNS_PACKET_RRCOUNT(p) <= 0) return; if (DNS_PACKET_LLMNR_C(p) != 0) return; if (DNS_PACKET_LLMNR_T(p) != 0) return; if (manager_our_packet(scope->manager, p)) return; r = dns_packet_extract(p); if (r < 0) { log_debug_errno(r, "Failed to extract packet: %m"); return; } log_debug("Checking for conflicts..."); for (i = 0; i < p->answer->n_rrs; i++) { /* Check for conflicts against the local zone. If we * found one, we won't check any further */ r = dns_zone_check_conflicts(&scope->zone, p->answer->items[i].rr); if (r != 0) continue; /* Check for conflicts against the local cache. If so, * send out an advisory query, to inform everybody */ r = dns_cache_check_conflicts(&scope->cache, p->answer->items[i].rr, p->family, &p->sender); if (r <= 0) continue; dns_scope_notify_conflict(scope, p->answer->items[i].rr); } } void dns_scope_dump(DnsScope *s, FILE *f) { assert(s); if (!f) f = stdout; fputs("[Scope protocol=", f); fputs(dns_protocol_to_string(s->protocol), f); if (s->link) { fputs(" interface=", f); fputs(s->link->name, f); } if (s->family != AF_UNSPEC) { fputs(" family=", f); fputs(af_to_name(s->family), f); } fputs("]\n", f); if (!dns_zone_is_empty(&s->zone)) { fputs("ZONE:\n", f); dns_zone_dump(&s->zone, f); } if (!dns_cache_is_empty(&s->cache)) { fputs("CACHE:\n", f); dns_cache_dump(&s->cache, f); } } DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s) { assert(s); if (s->protocol != DNS_PROTOCOL_DNS) return NULL; if (s->link) return s->link->search_domains; return s->manager->search_domains; } bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name) { assert(s); if (s->protocol != DNS_PROTOCOL_DNS) return false; return dns_name_is_single_label(name); } bool dns_scope_network_good(DnsScope *s) { /* Checks whether the network is in good state for lookups on this scope. For mDNS/LLMNR/Classic DNS scopes * bound to links this is easy, as they don't even exist if the link isn't in a suitable state. For the global * DNS scope we check whether there are any links that are up and have an address. */ if (s->link) return true; return manager_routable(s->manager, AF_UNSPEC); } systemd-229/src/resolve/resolved-dns-scope.h000066400000000000000000000070231265713322000212160ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "list.h" typedef struct DnsScope DnsScope; #include "resolved-dns-cache.h" #include "resolved-dns-dnssec.h" #include "resolved-dns-packet.h" #include "resolved-dns-server.h" #include "resolved-dns-zone.h" #include "resolved-link.h" typedef enum DnsScopeMatch { DNS_SCOPE_NO, DNS_SCOPE_MAYBE, DNS_SCOPE_YES, _DNS_SCOPE_MATCH_MAX, _DNS_SCOPE_INVALID = -1 } DnsScopeMatch; struct DnsScope { Manager *manager; DnsProtocol protocol; int family; DnssecMode dnssec_mode; Link *link; DnsCache cache; DnsZone zone; OrderedHashmap *conflict_queue; sd_event_source *conflict_event_source; RateLimit ratelimit; usec_t resend_timeout; usec_t max_rtt; LIST_HEAD(DnsQueryCandidate, query_candidates); /* Note that we keep track of ongoing transactions in two * ways: once in a hashmap, indexed by the rr key, and once in * a linked list. We use the hashmap to quickly find * transactions we can reuse for a key. But note that there * might be multiple transactions for the same key (because * the zone probing can't reuse a transaction answered from * the zone or the cache), and the hashmap only tracks the * most recent entry. */ Hashmap *transactions_by_key; LIST_HEAD(DnsTransaction, transactions); LIST_FIELDS(DnsScope, scopes); }; int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol p, int family); DnsScope* dns_scope_free(DnsScope *s); void dns_scope_packet_received(DnsScope *s, usec_t rtt); void dns_scope_packet_lost(DnsScope *s, usec_t usec); int dns_scope_emit_udp(DnsScope *s, int fd, DnsPacket *p); int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port); int dns_scope_socket_udp(DnsScope *s, DnsServer *server, uint16_t port); DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain); bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key); DnsServer *dns_scope_get_dns_server(DnsScope *s); void dns_scope_next_dns_server(DnsScope *s); int dns_scope_llmnr_membership(DnsScope *s, bool b); int dns_scope_mdns_membership(DnsScope *s, bool b); void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p); DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok); int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr); void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p); void dns_scope_dump(DnsScope *s, FILE *f); DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s); bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name); bool dns_scope_network_good(DnsScope *s); systemd-229/src/resolve/resolved-dns-search-domain.c000066400000000000000000000131541265713322000226140ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "dns-domain.h" #include "resolved-dns-search-domain.h" int dns_search_domain_new( Manager *m, DnsSearchDomain **ret, DnsSearchDomainType type, Link *l, const char *name) { _cleanup_free_ char *normalized = NULL; DnsSearchDomain *d; int r; assert(m); assert((type == DNS_SEARCH_DOMAIN_LINK) == !!l); assert(name); r = dns_name_normalize(name, &normalized); if (r < 0) return r; if (l) { if (l->n_search_domains >= LINK_SEARCH_DOMAINS_MAX) return -E2BIG; } else { if (m->n_search_domains >= MANAGER_SEARCH_DOMAINS_MAX) return -E2BIG; } d = new0(DnsSearchDomain, 1); if (!d) return -ENOMEM; d->n_ref = 1; d->manager = m; d->type = type; d->name = normalized; normalized = NULL; switch (type) { case DNS_SEARCH_DOMAIN_LINK: d->link = l; LIST_APPEND(domains, l->search_domains, d); l->n_search_domains++; break; case DNS_SERVER_SYSTEM: LIST_APPEND(domains, m->search_domains, d); m->n_search_domains++; break; default: assert_not_reached("Unknown search domain type"); } d->linked = true; if (ret) *ret = d; return 0; } DnsSearchDomain* dns_search_domain_ref(DnsSearchDomain *d) { if (!d) return NULL; assert(d->n_ref > 0); d->n_ref++; return d; } DnsSearchDomain* dns_search_domain_unref(DnsSearchDomain *d) { if (!d) return NULL; assert(d->n_ref > 0); d->n_ref--; if (d->n_ref > 0) return NULL; free(d->name); free(d); return NULL; } void dns_search_domain_unlink(DnsSearchDomain *d) { assert(d); assert(d->manager); if (!d->linked) return; switch (d->type) { case DNS_SEARCH_DOMAIN_LINK: assert(d->link); assert(d->link->n_search_domains > 0); LIST_REMOVE(domains, d->link->search_domains, d); d->link->n_search_domains--; break; case DNS_SEARCH_DOMAIN_SYSTEM: assert(d->manager->n_search_domains > 0); LIST_REMOVE(domains, d->manager->search_domains, d); d->manager->n_search_domains--; break; } d->linked = false; dns_search_domain_unref(d); } void dns_search_domain_move_back_and_unmark(DnsSearchDomain *d) { DnsSearchDomain *tail; assert(d); if (!d->marked) return; d->marked = false; if (!d->linked || !d->domains_next) return; switch (d->type) { case DNS_SEARCH_DOMAIN_LINK: assert(d->link); LIST_FIND_TAIL(domains, d, tail); LIST_REMOVE(domains, d->link->search_domains, d); LIST_INSERT_AFTER(domains, d->link->search_domains, tail, d); break; case DNS_SEARCH_DOMAIN_SYSTEM: LIST_FIND_TAIL(domains, d, tail); LIST_REMOVE(domains, d->manager->search_domains, d); LIST_INSERT_AFTER(domains, d->manager->search_domains, tail, d); break; default: assert_not_reached("Unknown search domain type"); } } void dns_search_domain_unlink_all(DnsSearchDomain *first) { DnsSearchDomain *next; if (!first) return; next = first->domains_next; dns_search_domain_unlink(first); dns_search_domain_unlink_all(next); } void dns_search_domain_unlink_marked(DnsSearchDomain *first) { DnsSearchDomain *next; if (!first) return; next = first->domains_next; if (first->marked) dns_search_domain_unlink(first); dns_search_domain_unlink_marked(next); } void dns_search_domain_mark_all(DnsSearchDomain *first) { if (!first) return; first->marked = true; dns_search_domain_mark_all(first->domains_next); } int dns_search_domain_find(DnsSearchDomain *first, const char *name, DnsSearchDomain **ret) { DnsSearchDomain *d; int r; assert(name); assert(ret); LIST_FOREACH(domains, d, first) { r = dns_name_equal(name, d->name); if (r < 0) return r; if (r > 0) { *ret = d; return 1; } } *ret = NULL; return 0; } systemd-229/src/resolve/resolved-dns-search-domain.h000066400000000000000000000041551265713322000226220ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "macro.h" typedef struct DnsSearchDomain DnsSearchDomain; typedef enum DnsSearchDomainType { DNS_SEARCH_DOMAIN_SYSTEM, DNS_SEARCH_DOMAIN_LINK, } DnsSearchDomainType; #include "resolved-link.h" #include "resolved-manager.h" struct DnsSearchDomain { Manager *manager; unsigned n_ref; DnsSearchDomainType type; Link *link; char *name; bool marked:1; bool route_only:1; bool linked:1; LIST_FIELDS(DnsSearchDomain, domains); }; int dns_search_domain_new( Manager *m, DnsSearchDomain **ret, DnsSearchDomainType type, Link *link, const char *name); DnsSearchDomain* dns_search_domain_ref(DnsSearchDomain *d); DnsSearchDomain* dns_search_domain_unref(DnsSearchDomain *d); void dns_search_domain_unlink(DnsSearchDomain *d); void dns_search_domain_move_back_and_unmark(DnsSearchDomain *d); void dns_search_domain_unlink_all(DnsSearchDomain *first); void dns_search_domain_unlink_marked(DnsSearchDomain *first); void dns_search_domain_mark_all(DnsSearchDomain *first); int dns_search_domain_find(DnsSearchDomain *first, const char *name, DnsSearchDomain **ret); static inline const char* DNS_SEARCH_DOMAIN_NAME(DnsSearchDomain *d) { return d ? d->name : NULL; } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsSearchDomain*, dns_search_domain_unref); systemd-229/src/resolve/resolved-dns-server.c000066400000000000000000000626731265713322000214220ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "resolved-dns-server.h" #include "resolved-resolv-conf.h" #include "siphash24.h" #include "string-table.h" #include "string-util.h" /* After how much time to repeat classic DNS requests */ #define DNS_TIMEOUT_MIN_USEC (500 * USEC_PER_MSEC) #define DNS_TIMEOUT_MAX_USEC (5 * USEC_PER_SEC) /* The amount of time to wait before retrying with a full feature set */ #define DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC (6 * USEC_PER_HOUR) #define DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC (5 * USEC_PER_MINUTE) /* The number of times we will attempt a certain feature set before degrading */ #define DNS_SERVER_FEATURE_RETRY_ATTEMPTS 3 int dns_server_new( Manager *m, DnsServer **ret, DnsServerType type, Link *l, int family, const union in_addr_union *in_addr) { DnsServer *s; assert(m); assert((type == DNS_SERVER_LINK) == !!l); assert(in_addr); if (!IN_SET(family, AF_INET, AF_INET6)) return -EAFNOSUPPORT; if (l) { if (l->n_dns_servers >= LINK_DNS_SERVERS_MAX) return -E2BIG; } else { if (m->n_dns_servers >= MANAGER_DNS_SERVERS_MAX) return -E2BIG; } s = new0(DnsServer, 1); if (!s) return -ENOMEM; s->n_ref = 1; s->manager = m; s->verified_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID; s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST; s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC; s->received_udp_packet_max = DNS_PACKET_UNICAST_SIZE_MAX; s->type = type; s->family = family; s->address = *in_addr; s->resend_timeout = DNS_TIMEOUT_MIN_USEC; switch (type) { case DNS_SERVER_LINK: s->link = l; LIST_APPEND(servers, l->dns_servers, s); l->n_dns_servers++; break; case DNS_SERVER_SYSTEM: LIST_APPEND(servers, m->dns_servers, s); m->n_dns_servers++; break; case DNS_SERVER_FALLBACK: LIST_APPEND(servers, m->fallback_dns_servers, s); m->n_dns_servers++; break; default: assert_not_reached("Unknown server type"); } s->linked = true; /* A new DNS server that isn't fallback is added and the one * we used so far was a fallback one? Then let's try to pick * the new one */ if (type != DNS_SERVER_FALLBACK && m->current_dns_server && m->current_dns_server->type == DNS_SERVER_FALLBACK) manager_set_dns_server(m, NULL); if (ret) *ret = s; return 0; } DnsServer* dns_server_ref(DnsServer *s) { if (!s) return NULL; assert(s->n_ref > 0); s->n_ref ++; return s; } DnsServer* dns_server_unref(DnsServer *s) { if (!s) return NULL; assert(s->n_ref > 0); s->n_ref --; if (s->n_ref > 0) return NULL; free(s->server_string); free(s); return NULL; } void dns_server_unlink(DnsServer *s) { assert(s); assert(s->manager); /* This removes the specified server from the linked list of * servers, but any server might still stay around if it has * refs, for example from an ongoing transaction. */ if (!s->linked) return; switch (s->type) { case DNS_SERVER_LINK: assert(s->link); assert(s->link->n_dns_servers > 0); LIST_REMOVE(servers, s->link->dns_servers, s); break; case DNS_SERVER_SYSTEM: assert(s->manager->n_dns_servers > 0); LIST_REMOVE(servers, s->manager->dns_servers, s); s->manager->n_dns_servers--; break; case DNS_SERVER_FALLBACK: assert(s->manager->n_dns_servers > 0); LIST_REMOVE(servers, s->manager->fallback_dns_servers, s); s->manager->n_dns_servers--; break; } s->linked = false; if (s->link && s->link->current_dns_server == s) link_set_dns_server(s->link, NULL); if (s->manager->current_dns_server == s) manager_set_dns_server(s->manager, NULL); dns_server_unref(s); } void dns_server_move_back_and_unmark(DnsServer *s) { DnsServer *tail; assert(s); if (!s->marked) return; s->marked = false; if (!s->linked || !s->servers_next) return; /* Move us to the end of the list, so that the order is * strictly kept, if we are not at the end anyway. */ switch (s->type) { case DNS_SERVER_LINK: assert(s->link); LIST_FIND_TAIL(servers, s, tail); LIST_REMOVE(servers, s->link->dns_servers, s); LIST_INSERT_AFTER(servers, s->link->dns_servers, tail, s); break; case DNS_SERVER_SYSTEM: LIST_FIND_TAIL(servers, s, tail); LIST_REMOVE(servers, s->manager->dns_servers, s); LIST_INSERT_AFTER(servers, s->manager->dns_servers, tail, s); break; case DNS_SERVER_FALLBACK: LIST_FIND_TAIL(servers, s, tail); LIST_REMOVE(servers, s->manager->fallback_dns_servers, s); LIST_INSERT_AFTER(servers, s->manager->fallback_dns_servers, tail, s); break; default: assert_not_reached("Unknown server type"); } } static void dns_server_verified(DnsServer *s, DnsServerFeatureLevel level) { assert(s); if (s->verified_feature_level > level) return; if (s->verified_feature_level != level) { log_debug("Verified we get a response at feature level %s from DNS server %s.", dns_server_feature_level_to_string(level), dns_server_string(s)); s->verified_feature_level = level; } assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &s->verified_usec) >= 0); } void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t rtt, size_t size) { assert(s); if (protocol == IPPROTO_UDP) { if (s->possible_feature_level == level) s->n_failed_udp = 0; /* If the RRSIG data is missing, then we can only validate EDNS0 at max */ if (s->packet_rrsig_missing && level >= DNS_SERVER_FEATURE_LEVEL_DO) level = DNS_SERVER_FEATURE_LEVEL_DO - 1; /* If the OPT RR got lost, then we can only validate UDP at max */ if (s->packet_bad_opt && level >= DNS_SERVER_FEATURE_LEVEL_EDNS0) level = DNS_SERVER_FEATURE_LEVEL_EDNS0 - 1; /* Even if we successfully receive a reply to a request announcing support for large packets, that does not mean we can necessarily receive large packets. */ if (level == DNS_SERVER_FEATURE_LEVEL_LARGE) level = DNS_SERVER_FEATURE_LEVEL_LARGE - 1; } else if (protocol == IPPROTO_TCP) { if (s->possible_feature_level == level) s->n_failed_tcp = 0; /* Successful TCP connections are only useful to verify the TCP feature level. */ level = DNS_SERVER_FEATURE_LEVEL_TCP; } dns_server_verified(s, level); /* Remember the size of the largest UDP packet we received from a server, we know that we can always announce support for packets with at least this size. */ if (protocol == IPPROTO_UDP && s->received_udp_packet_max < size) s->received_udp_packet_max = size; if (s->max_rtt < rtt) { s->max_rtt = rtt; s->resend_timeout = CLAMP(s->max_rtt * 2, DNS_TIMEOUT_MIN_USEC, DNS_TIMEOUT_MAX_USEC); } } void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t usec) { assert(s); assert(s->manager); if (s->possible_feature_level == level) { if (protocol == IPPROTO_UDP) s->n_failed_udp ++; else if (protocol == IPPROTO_TCP) s->n_failed_tcp ++; } if (s->resend_timeout > usec) return; s->resend_timeout = MIN(s->resend_timeout * 2, DNS_TIMEOUT_MAX_USEC); } void dns_server_packet_failed(DnsServer *s, DnsServerFeatureLevel level) { assert(s); /* Invoked whenever we get a FORMERR, SERVFAIL or NOTIMP rcode from a server. */ if (s->possible_feature_level != level) return; s->packet_failed = true; } void dns_server_packet_truncated(DnsServer *s, DnsServerFeatureLevel level) { assert(s); /* Invoked whenever we get a packet with TC bit set. */ if (s->possible_feature_level != level) return; s->packet_truncated = true; } void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level) { assert(s); if (level < DNS_SERVER_FEATURE_LEVEL_DO) return; /* If the RRSIG RRs are missing, we have to downgrade what we previously verified */ if (s->verified_feature_level >= DNS_SERVER_FEATURE_LEVEL_DO) s->verified_feature_level = DNS_SERVER_FEATURE_LEVEL_DO-1; s->packet_rrsig_missing = true; } void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level) { assert(s); if (level < DNS_SERVER_FEATURE_LEVEL_EDNS0) return; /* If the OPT RR got lost, we have to downgrade what we previously verified */ if (s->verified_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0) s->verified_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0-1; s->packet_bad_opt = true; } static bool dns_server_grace_period_expired(DnsServer *s) { usec_t ts; assert(s); assert(s->manager); if (s->verified_usec == 0) return false; assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); if (s->verified_usec + s->features_grace_period_usec > ts) return false; s->features_grace_period_usec = MIN(s->features_grace_period_usec * 2, DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC); return true; } static void dns_server_reset_counters(DnsServer *s) { assert(s); s->n_failed_udp = 0; s->n_failed_tcp = 0; s->packet_failed = false; s->packet_truncated = false; s->verified_usec = 0; /* Note that we do not reset s->packet_bad_opt and s->packet_rrsig_missing here. We reset them only when the * grace period ends, but not when lowering the possible feature level, as a lower level feature level should * not make RRSIGs appear or OPT appear, but rather make them disappear. If the reappear anyway, then that's * indication for a differently broken OPT/RRSIG implementation, and we really don't want to support that * either. * * This is particularly important to deal with certain Belkin routers which break OPT for certain lookups (A), * but pass traffic through for others (AAAA). If we detect the broken behaviour on one lookup we should not * reenable it for another, because we cannot validate things anyway, given that the RRSIG/OPT data will be * incomplete. */ } DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) { assert(s); if (s->possible_feature_level != DNS_SERVER_FEATURE_LEVEL_BEST && dns_server_grace_period_expired(s)) { s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST; dns_server_reset_counters(s); s->packet_bad_opt = false; s->packet_rrsig_missing = false; log_info("Grace period over, resuming full feature set (%s) for DNS server %s.", dns_server_feature_level_to_string(s->possible_feature_level), dns_server_string(s)); } else if (s->possible_feature_level <= s->verified_feature_level) s->possible_feature_level = s->verified_feature_level; else { DnsServerFeatureLevel p = s->possible_feature_level; if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS && s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_TCP) { /* We are at the TCP (lowest) level, and we tried a couple of TCP connections, and it didn't * work. Upgrade back to UDP again. */ log_debug("Reached maximum number of failed TCP connection attempts, trying UDP again..."); s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP; } else if (s->packet_bad_opt && s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0) { /* A reply to one of our EDNS0 queries didn't carry a valid OPT RR, then downgrade to below * EDNS0 levels. After all, some records generate different responses with and without OPT RR * in the request. Example: * https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html */ log_debug("Server doesn't support EDNS(0) properly, downgrading feature level..."); s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP; } else if (s->packet_rrsig_missing && s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_DO) { /* RRSIG data was missing on a EDNS0 packet with DO bit set. This means the server doesn't * augment responses with DNSSEC RRs. If so, let's better not ask the server for it anymore, * after all some servers generate different replies depending if an OPT RR is in the query or * not. */ log_debug("Detected server responses lack RRSIG records, downgrading feature level..."); s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0; } else if (s->n_failed_udp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS && s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_UDP) { /* We lost too many UDP packets in a row, and are on a feature level of UDP or higher. If the * packets are lost, maybe the server cannot parse them, hence downgrading sounds like a good * idea. We might downgrade all the way down to TCP this way. */ log_debug("Lost too many UDP packets, downgrading feature level..."); s->possible_feature_level--; } else if (s->packet_failed && s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP) { /* We got a failure packet, and are at a feature level above UDP. Note that in this case we * downgrade no further than UDP, under the assumption that a failure packet indicates an * incompatible packet contents, but not a problem with the transport. */ log_debug("Got server failure, downgrading feature level..."); s->possible_feature_level--; } else if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS && s->packet_truncated && s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP) { /* We got too many TCP connection failures in a row, we had at least one truncated packet, and * are on a feature level above UDP. By downgrading things and getting rid of DNSSEC or EDNS0 * data we hope to make the packet smaller, so that it still works via UDP given that TCP * appears not to be a fallback. Note that if we are already at the lowest UDP level, we don't * go further down, since that's TCP, and TCP failed too often after all. */ log_debug("Got too many failed TCP connection failures and truncated UDP packets, downgrading feature level..."); s->possible_feature_level--; } if (p != s->possible_feature_level) { /* We changed the feature level, reset the counting */ dns_server_reset_counters(s); log_warning("Using degraded feature set (%s) for DNS server %s.", dns_server_feature_level_to_string(s->possible_feature_level), dns_server_string(s)); } } return s->possible_feature_level; } int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeatureLevel level) { size_t packet_size; bool edns_do; int r; assert(server); assert(packet); assert(packet->protocol == DNS_PROTOCOL_DNS); /* Fix the OPT field in the packet to match our current feature level. */ r = dns_packet_truncate_opt(packet); if (r < 0) return r; if (level < DNS_SERVER_FEATURE_LEVEL_EDNS0) return 0; edns_do = level >= DNS_SERVER_FEATURE_LEVEL_DO; if (level >= DNS_SERVER_FEATURE_LEVEL_LARGE) packet_size = DNS_PACKET_UNICAST_SIZE_LARGE_MAX; else packet_size = server->received_udp_packet_max; return dns_packet_append_opt(packet, packet_size, edns_do, NULL); } const char *dns_server_string(DnsServer *server) { assert(server); if (!server->server_string) (void) in_addr_to_string(server->family, &server->address, &server->server_string); return strna(server->server_string); } bool dns_server_dnssec_supported(DnsServer *server) { assert(server); /* Returns whether the server supports DNSSEC according to what we know about it */ if (server->possible_feature_level < DNS_SERVER_FEATURE_LEVEL_DO) return false; if (server->packet_bad_opt) return false; if (server->packet_rrsig_missing) return false; /* DNSSEC servers need to support TCP properly (see RFC5966), if they don't, we assume DNSSEC is borked too */ if (server->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS) return false; return true; } void dns_server_warn_downgrade(DnsServer *server) { assert(server); if (server->warned_downgrade) return; log_struct(LOG_NOTICE, LOG_MESSAGE_ID(SD_MESSAGE_DNSSEC_DOWNGRADE), LOG_MESSAGE("Server %s does not support DNSSEC, downgrading to non-DNSSEC mode.", dns_server_string(server)), "DNS_SERVER=%s", dns_server_string(server), "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(server->possible_feature_level), NULL); server->warned_downgrade = true; } static void dns_server_hash_func(const void *p, struct siphash *state) { const DnsServer *s = p; assert(s); siphash24_compress(&s->family, sizeof(s->family), state); siphash24_compress(&s->address, FAMILY_ADDRESS_SIZE(s->family), state); } static int dns_server_compare_func(const void *a, const void *b) { const DnsServer *x = a, *y = b; if (x->family < y->family) return -1; if (x->family > y->family) return 1; return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family)); } const struct hash_ops dns_server_hash_ops = { .hash = dns_server_hash_func, .compare = dns_server_compare_func }; void dns_server_unlink_all(DnsServer *first) { DnsServer *next; if (!first) return; next = first->servers_next; dns_server_unlink(first); dns_server_unlink_all(next); } void dns_server_unlink_marked(DnsServer *first) { DnsServer *next; if (!first) return; next = first->servers_next; if (first->marked) dns_server_unlink(first); dns_server_unlink_marked(next); } void dns_server_mark_all(DnsServer *first) { if (!first) return; first->marked = true; dns_server_mark_all(first->servers_next); } DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr) { DnsServer *s; LIST_FOREACH(servers, s, first) if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0) return s; return NULL; } DnsServer *manager_get_first_dns_server(Manager *m, DnsServerType t) { assert(m); switch (t) { case DNS_SERVER_SYSTEM: return m->dns_servers; case DNS_SERVER_FALLBACK: return m->fallback_dns_servers; default: return NULL; } } DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) { assert(m); if (m->current_dns_server == s) return s; if (s) log_info("Switching to %s DNS server %s.", dns_server_type_to_string(s->type), dns_server_string(s)); dns_server_unref(m->current_dns_server); m->current_dns_server = dns_server_ref(s); if (m->unicast_scope) dns_cache_flush(&m->unicast_scope->cache); return s; } DnsServer *manager_get_dns_server(Manager *m) { Link *l; assert(m); /* Try to read updates resolv.conf */ manager_read_resolv_conf(m); /* If no DNS server was chosen so far, pick the first one */ if (!m->current_dns_server) manager_set_dns_server(m, m->dns_servers); if (!m->current_dns_server) { bool found = false; Iterator i; /* No DNS servers configured, let's see if there are * any on any links. If not, we use the fallback * servers */ HASHMAP_FOREACH(l, m->links, i) if (l->dns_servers) { found = true; break; } if (!found) manager_set_dns_server(m, m->fallback_dns_servers); } return m->current_dns_server; } void manager_next_dns_server(Manager *m) { assert(m); /* If there's currently no DNS server set, then the next * manager_get_dns_server() will find one */ if (!m->current_dns_server) return; /* Change to the next one, but make sure to follow the linked * list only if the server is still linked. */ if (m->current_dns_server->linked && m->current_dns_server->servers_next) { manager_set_dns_server(m, m->current_dns_server->servers_next); return; } /* If there was no next one, then start from the beginning of * the list */ if (m->current_dns_server->type == DNS_SERVER_FALLBACK) manager_set_dns_server(m, m->fallback_dns_servers); else manager_set_dns_server(m, m->dns_servers); } static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = { [DNS_SERVER_SYSTEM] = "system", [DNS_SERVER_FALLBACK] = "fallback", [DNS_SERVER_LINK] = "link", }; DEFINE_STRING_TABLE_LOOKUP(dns_server_type, DnsServerType); static const char* const dns_server_feature_level_table[_DNS_SERVER_FEATURE_LEVEL_MAX] = { [DNS_SERVER_FEATURE_LEVEL_TCP] = "TCP", [DNS_SERVER_FEATURE_LEVEL_UDP] = "UDP", [DNS_SERVER_FEATURE_LEVEL_EDNS0] = "UDP+EDNS0", [DNS_SERVER_FEATURE_LEVEL_DO] = "UDP+EDNS0+DO", [DNS_SERVER_FEATURE_LEVEL_LARGE] = "UDP+EDNS0+DO+LARGE", }; DEFINE_STRING_TABLE_LOOKUP(dns_server_feature_level, DnsServerFeatureLevel); systemd-229/src/resolve/resolved-dns-server.h000066400000000000000000000110231265713322000214060ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "in-addr-util.h" typedef struct DnsServer DnsServer; typedef enum DnsServerType { DNS_SERVER_SYSTEM, DNS_SERVER_FALLBACK, DNS_SERVER_LINK, } DnsServerType; #define _DNS_SERVER_TYPE_MAX (DNS_SERVER_LINK + 1) const char* dns_server_type_to_string(DnsServerType i) _const_; DnsServerType dns_server_type_from_string(const char *s) _pure_; typedef enum DnsServerFeatureLevel { DNS_SERVER_FEATURE_LEVEL_TCP, DNS_SERVER_FEATURE_LEVEL_UDP, DNS_SERVER_FEATURE_LEVEL_EDNS0, DNS_SERVER_FEATURE_LEVEL_DO, DNS_SERVER_FEATURE_LEVEL_LARGE, _DNS_SERVER_FEATURE_LEVEL_MAX, _DNS_SERVER_FEATURE_LEVEL_INVALID = -1 } DnsServerFeatureLevel; #define DNS_SERVER_FEATURE_LEVEL_WORST 0 #define DNS_SERVER_FEATURE_LEVEL_BEST (_DNS_SERVER_FEATURE_LEVEL_MAX - 1) const char* dns_server_feature_level_to_string(int i) _const_; int dns_server_feature_level_from_string(const char *s) _pure_; #include "resolved-link.h" #include "resolved-manager.h" struct DnsServer { Manager *manager; unsigned n_ref; DnsServerType type; Link *link; int family; union in_addr_union address; char *server_string; usec_t resend_timeout; usec_t max_rtt; DnsServerFeatureLevel verified_feature_level; DnsServerFeatureLevel possible_feature_level; size_t received_udp_packet_max; unsigned n_failed_udp; unsigned n_failed_tcp; bool packet_failed:1; bool packet_truncated:1; bool packet_bad_opt:1; bool packet_rrsig_missing:1; usec_t verified_usec; usec_t features_grace_period_usec; /* Whether we already warned about downgrading to non-DNSSEC mode for this server */ bool warned_downgrade:1; /* Used when GC'ing old DNS servers when configuration changes. */ bool marked:1; /* If linked is set, then this server appears in the servers linked list */ bool linked:1; LIST_FIELDS(DnsServer, servers); }; int dns_server_new( Manager *m, DnsServer **ret, DnsServerType type, Link *link, int family, const union in_addr_union *address); DnsServer* dns_server_ref(DnsServer *s); DnsServer* dns_server_unref(DnsServer *s); void dns_server_unlink(DnsServer *s); void dns_server_move_back_and_unmark(DnsServer *s); void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t rtt, size_t size); void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t usec); void dns_server_packet_failed(DnsServer *s, DnsServerFeatureLevel level); void dns_server_packet_truncated(DnsServer *s, DnsServerFeatureLevel level); void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level); void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level); DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s); int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeatureLevel level); const char *dns_server_string(DnsServer *server); bool dns_server_dnssec_supported(DnsServer *server); void dns_server_warn_downgrade(DnsServer *server); DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr); void dns_server_unlink_all(DnsServer *first); void dns_server_unlink_marked(DnsServer *first); void dns_server_mark_all(DnsServer *first); DnsServer *manager_get_first_dns_server(Manager *m, DnsServerType t); DnsServer *manager_set_dns_server(Manager *m, DnsServer *s); DnsServer *manager_get_dns_server(Manager *m); void manager_next_dns_server(Manager *m); DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServer*, dns_server_unref); extern const struct hash_ops dns_server_hash_ops; systemd-229/src/resolve/resolved-dns-stream.c000066400000000000000000000360451265713322000214010ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "fd-util.h" #include "io-util.h" #include "missing.h" #include "resolved-dns-stream.h" #define DNS_STREAM_TIMEOUT_USEC (10 * USEC_PER_SEC) #define DNS_STREAMS_MAX 128 static void dns_stream_stop(DnsStream *s) { assert(s); s->io_event_source = sd_event_source_unref(s->io_event_source); s->timeout_event_source = sd_event_source_unref(s->timeout_event_source); s->fd = safe_close(s->fd); } static int dns_stream_update_io(DnsStream *s) { int f = 0; assert(s); if (s->write_packet && s->n_written < sizeof(s->write_size) + s->write_packet->size) f |= EPOLLOUT; if (!s->read_packet || s->n_read < sizeof(s->read_size) + s->read_packet->size) f |= EPOLLIN; return sd_event_source_set_io_events(s->io_event_source, f); } static int dns_stream_complete(DnsStream *s, int error) { assert(s); dns_stream_stop(s); if (s->complete) s->complete(s, error); else dns_stream_free(s); return 0; } static int dns_stream_identify(DnsStream *s) { union { struct cmsghdr header; /* For alignment */ uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo)) + EXTRA_CMSG_SPACE /* kernel appears to require extra space */]; } control; struct msghdr mh = {}; struct cmsghdr *cmsg; socklen_t sl; int r; assert(s); if (s->identified) return 0; /* Query the local side */ s->local_salen = sizeof(s->local); r = getsockname(s->fd, &s->local.sa, &s->local_salen); if (r < 0) return -errno; if (s->local.sa.sa_family == AF_INET6 && s->ifindex <= 0) s->ifindex = s->local.in6.sin6_scope_id; /* Query the remote side */ s->peer_salen = sizeof(s->peer); r = getpeername(s->fd, &s->peer.sa, &s->peer_salen); if (r < 0) return -errno; if (s->peer.sa.sa_family == AF_INET6 && s->ifindex <= 0) s->ifindex = s->peer.in6.sin6_scope_id; /* Check consistency */ assert(s->peer.sa.sa_family == s->local.sa.sa_family); assert(IN_SET(s->peer.sa.sa_family, AF_INET, AF_INET6)); /* Query connection meta information */ sl = sizeof(control); if (s->peer.sa.sa_family == AF_INET) { r = getsockopt(s->fd, IPPROTO_IP, IP_PKTOPTIONS, &control, &sl); if (r < 0) return -errno; } else if (s->peer.sa.sa_family == AF_INET6) { r = getsockopt(s->fd, IPPROTO_IPV6, IPV6_2292PKTOPTIONS, &control, &sl); if (r < 0) return -errno; } else return -EAFNOSUPPORT; mh.msg_control = &control; mh.msg_controllen = sl; CMSG_FOREACH(cmsg, &mh) { if (cmsg->cmsg_level == IPPROTO_IPV6) { assert(s->peer.sa.sa_family == AF_INET6); switch (cmsg->cmsg_type) { case IPV6_PKTINFO: { struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg); if (s->ifindex <= 0) s->ifindex = i->ipi6_ifindex; break; } case IPV6_HOPLIMIT: s->ttl = *(int *) CMSG_DATA(cmsg); break; } } else if (cmsg->cmsg_level == IPPROTO_IP) { assert(s->peer.sa.sa_family == AF_INET); switch (cmsg->cmsg_type) { case IP_PKTINFO: { struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg); if (s->ifindex <= 0) s->ifindex = i->ipi_ifindex; break; } case IP_TTL: s->ttl = *(int *) CMSG_DATA(cmsg); break; } } } /* The Linux kernel sets the interface index to the loopback * device if the connection came from the local host since it * avoids the routing table in such a case. Let's unset the * interface index in such a case. */ if (s->ifindex == LOOPBACK_IFINDEX) s->ifindex = 0; /* If we don't know the interface index still, we look for the * first local interface with a matching address. Yuck! */ if (s->ifindex <= 0) s->ifindex = manager_find_ifindex(s->manager, s->local.sa.sa_family, s->local.sa.sa_family == AF_INET ? (union in_addr_union*) &s->local.in.sin_addr : (union in_addr_union*) &s->local.in6.sin6_addr); if (s->protocol == DNS_PROTOCOL_LLMNR && s->ifindex > 0) { uint32_t ifindex = htobe32(s->ifindex); /* Make sure all packets for this connection are sent on the same interface */ if (s->local.sa.sa_family == AF_INET) { r = setsockopt(s->fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex)); if (r < 0) log_debug_errno(errno, "Failed to invoke IP_UNICAST_IF: %m"); } else if (s->local.sa.sa_family == AF_INET6) { r = setsockopt(s->fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex)); if (r < 0) log_debug_errno(errno, "Failed to invoke IPV6_UNICAST_IF: %m"); } } s->identified = true; return 0; } static int on_stream_timeout(sd_event_source *es, usec_t usec, void *userdata) { DnsStream *s = userdata; assert(s); return dns_stream_complete(s, ETIMEDOUT); } static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *userdata) { DnsStream *s = userdata; int r; assert(s); r = dns_stream_identify(s); if (r < 0) return dns_stream_complete(s, -r); if ((revents & EPOLLOUT) && s->write_packet && s->n_written < sizeof(s->write_size) + s->write_packet->size) { struct iovec iov[2]; ssize_t ss; iov[0].iov_base = &s->write_size; iov[0].iov_len = sizeof(s->write_size); iov[1].iov_base = DNS_PACKET_DATA(s->write_packet); iov[1].iov_len = s->write_packet->size; IOVEC_INCREMENT(iov, 2, s->n_written); ss = writev(fd, iov, 2); if (ss < 0) { if (errno != EINTR && errno != EAGAIN) return dns_stream_complete(s, errno); } else s->n_written += ss; /* Are we done? If so, disable the event source for EPOLLOUT */ if (s->n_written >= sizeof(s->write_size) + s->write_packet->size) { r = dns_stream_update_io(s); if (r < 0) return dns_stream_complete(s, -r); } } if ((revents & (EPOLLIN|EPOLLHUP|EPOLLRDHUP)) && (!s->read_packet || s->n_read < sizeof(s->read_size) + s->read_packet->size)) { if (s->n_read < sizeof(s->read_size)) { ssize_t ss; ss = read(fd, (uint8_t*) &s->read_size + s->n_read, sizeof(s->read_size) - s->n_read); if (ss < 0) { if (errno != EINTR && errno != EAGAIN) return dns_stream_complete(s, errno); } else if (ss == 0) return dns_stream_complete(s, ECONNRESET); else s->n_read += ss; } if (s->n_read >= sizeof(s->read_size)) { if (be16toh(s->read_size) < DNS_PACKET_HEADER_SIZE) return dns_stream_complete(s, EBADMSG); if (s->n_read < sizeof(s->read_size) + be16toh(s->read_size)) { ssize_t ss; if (!s->read_packet) { r = dns_packet_new(&s->read_packet, s->protocol, be16toh(s->read_size)); if (r < 0) return dns_stream_complete(s, -r); s->read_packet->size = be16toh(s->read_size); s->read_packet->ipproto = IPPROTO_TCP; s->read_packet->family = s->peer.sa.sa_family; s->read_packet->ttl = s->ttl; s->read_packet->ifindex = s->ifindex; if (s->read_packet->family == AF_INET) { s->read_packet->sender.in = s->peer.in.sin_addr; s->read_packet->sender_port = be16toh(s->peer.in.sin_port); s->read_packet->destination.in = s->local.in.sin_addr; s->read_packet->destination_port = be16toh(s->local.in.sin_port); } else { assert(s->read_packet->family == AF_INET6); s->read_packet->sender.in6 = s->peer.in6.sin6_addr; s->read_packet->sender_port = be16toh(s->peer.in6.sin6_port); s->read_packet->destination.in6 = s->local.in6.sin6_addr; s->read_packet->destination_port = be16toh(s->local.in6.sin6_port); if (s->read_packet->ifindex == 0) s->read_packet->ifindex = s->peer.in6.sin6_scope_id; if (s->read_packet->ifindex == 0) s->read_packet->ifindex = s->local.in6.sin6_scope_id; } } ss = read(fd, (uint8_t*) DNS_PACKET_DATA(s->read_packet) + s->n_read - sizeof(s->read_size), sizeof(s->read_size) + be16toh(s->read_size) - s->n_read); if (ss < 0) { if (errno != EINTR && errno != EAGAIN) return dns_stream_complete(s, errno); } else if (ss == 0) return dns_stream_complete(s, ECONNRESET); else s->n_read += ss; } /* Are we done? If so, disable the event source for EPOLLIN */ if (s->n_read >= sizeof(s->read_size) + be16toh(s->read_size)) { r = dns_stream_update_io(s); if (r < 0) return dns_stream_complete(s, -r); /* If there's a packet handler * installed, call that. Note that * this is optional... */ if (s->on_packet) return s->on_packet(s); } } } if ((s->write_packet && s->n_written >= sizeof(s->write_size) + s->write_packet->size) && (s->read_packet && s->n_read >= sizeof(s->read_size) + s->read_packet->size)) return dns_stream_complete(s, 0); return 0; } DnsStream *dns_stream_free(DnsStream *s) { if (!s) return NULL; dns_stream_stop(s); if (s->manager) { LIST_REMOVE(streams, s->manager->dns_streams, s); s->manager->n_dns_streams--; } dns_packet_unref(s->write_packet); dns_packet_unref(s->read_packet); free(s); return 0; } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsStream*, dns_stream_free); int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd) { _cleanup_(dns_stream_freep) DnsStream *s = NULL; int r; assert(m); assert(fd >= 0); if (m->n_dns_streams > DNS_STREAMS_MAX) return -EBUSY; s = new0(DnsStream, 1); if (!s) return -ENOMEM; s->fd = -1; s->protocol = protocol; r = sd_event_add_io(m->event, &s->io_event_source, fd, EPOLLIN, on_stream_io, s); if (r < 0) return r; (void) sd_event_source_set_description(s->io_event_source, "dns-stream-io"); r = sd_event_add_time( m->event, &s->timeout_event_source, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + DNS_STREAM_TIMEOUT_USEC, 0, on_stream_timeout, s); if (r < 0) return r; (void) sd_event_source_set_description(s->timeout_event_source, "dns-stream-timeout"); LIST_PREPEND(streams, m->dns_streams, s); s->manager = m; s->fd = fd; m->n_dns_streams++; *ret = s; s = NULL; return 0; } int dns_stream_write_packet(DnsStream *s, DnsPacket *p) { assert(s); if (s->write_packet) return -EBUSY; s->write_packet = dns_packet_ref(p); s->write_size = htobe16(p->size); s->n_written = 0; return dns_stream_update_io(s); } systemd-229/src/resolve/resolved-dns-stream.h000066400000000000000000000032731265713322000214030ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "socket-util.h" typedef struct DnsStream DnsStream; #include "resolved-dns-packet.h" #include "resolved-dns-transaction.h" struct DnsStream { Manager *manager; DnsProtocol protocol; int fd; union sockaddr_union peer; socklen_t peer_salen; union sockaddr_union local; socklen_t local_salen; int ifindex; uint32_t ttl; bool identified; sd_event_source *io_event_source; sd_event_source *timeout_event_source; be16_t write_size, read_size; DnsPacket *write_packet, *read_packet; size_t n_written, n_read; int (*on_packet)(DnsStream *s); int (*complete)(DnsStream *s, int error); DnsTransaction *transaction; LIST_FIELDS(DnsStream, streams); }; int dns_stream_new(Manager *m, DnsStream **s, DnsProtocol protocol, int fd); DnsStream *dns_stream_free(DnsStream *s); int dns_stream_write_packet(DnsStream *s, DnsPacket *p); systemd-229/src/resolve/resolved-dns-synthesize.c000066400000000000000000000335441265713322000223140ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "hostname-util.h" #include "local-addresses.h" #include "resolved-dns-synthesize.h" int dns_synthesize_ifindex(int ifindex) { /* When the caller asked for resolving on a specific * interface, we synthesize the answer for that * interface. However, if nothing specific was claimed and we * only return localhost RRs, we synthesize the answer for * localhost. */ if (ifindex > 0) return ifindex; return LOOPBACK_IFINDEX; } int dns_synthesize_family(uint64_t flags) { /* Picks an address family depending on set flags. This is * purely for synthesized answers, where the family we return * for the reply should match what was requested in the * question, even though we are synthesizing the answer * here. */ if (!(flags & SD_RESOLVED_DNS)) { if (flags & (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_MDNS_IPV4)) return AF_INET; if (flags & (SD_RESOLVED_LLMNR_IPV6|SD_RESOLVED_MDNS_IPV6)) return AF_INET6; } return AF_UNSPEC; } DnsProtocol dns_synthesize_protocol(uint64_t flags) { /* Similar as dns_synthesize_family() but does this for the * protocol. If resolving via DNS was requested, we claim it * was DNS. Similar, if nothing specific was * requested. However, if only resolving via LLMNR was * requested we return that. */ if (flags & SD_RESOLVED_DNS) return DNS_PROTOCOL_DNS; if (flags & SD_RESOLVED_LLMNR) return DNS_PROTOCOL_LLMNR; if (flags & SD_RESOLVED_MDNS) return DNS_PROTOCOL_MDNS; return DNS_PROTOCOL_DNS; } static int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) { int r; assert(m); assert(key); assert(answer); r = dns_answer_reserve(answer, 2); if (r < 0) return r; if (IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY)) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key)); if (!rr) return -ENOMEM; rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK); r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; } if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key)); if (!rr) return -ENOMEM; rr->aaaa.in6_addr = in6addr_loopback; r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; } return 0; } static int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to, int ifindex, DnsAnswerFlags flags) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from); if (!rr) return -ENOMEM; rr->ptr.name = strdup(to); if (!rr->ptr.name) return -ENOMEM; return dns_answer_add(*answer, rr, ifindex, flags); } static int synthesize_localhost_ptr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) { int r; assert(m); assert(key); assert(answer); if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) { r = dns_answer_reserve(answer, 1); if (r < 0) return r; r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; } return 0; } static int answer_add_addresses_rr( DnsAnswer **answer, const char *name, struct local_address *addresses, unsigned n_addresses) { unsigned j; int r; assert(answer); assert(name); r = dns_answer_reserve(answer, n_addresses); if (r < 0) return r; for (j = 0; j < n_addresses; j++) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name); if (r < 0) return r; r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; } return 0; } static int answer_add_addresses_ptr( DnsAnswer **answer, const char *name, struct local_address *addresses, unsigned n_addresses, int af, const union in_addr_union *match) { unsigned j; int r; assert(answer); assert(name); for (j = 0; j < n_addresses; j++) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; if (af != AF_UNSPEC) { if (addresses[j].family != af) continue; if (match && !in_addr_equal(af, match, &addresses[j].address)) continue; } r = dns_answer_reserve(answer, 1); if (r < 0) return r; r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name); if (r < 0) return r; r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; } return 0; } static int synthesize_system_hostname_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) { _cleanup_free_ struct local_address *addresses = NULL; int n = 0, af; assert(m); assert(key); assert(answer); af = dns_type_to_af(key->type); if (af >= 0) { n = local_addresses(m->rtnl, ifindex, af, &addresses); if (n < 0) return n; if (n == 0) { struct local_address buffer[2]; /* If we have no local addresses then use ::1 * and 127.0.0.2 as local ones. */ if (af == AF_INET || af == AF_UNSPEC) buffer[n++] = (struct local_address) { .family = AF_INET, .ifindex = dns_synthesize_ifindex(ifindex), .address.in.s_addr = htobe32(0x7F000002), }; if (af == AF_INET6 || af == AF_UNSPEC) buffer[n++] = (struct local_address) { .family = AF_INET6, .ifindex = dns_synthesize_ifindex(ifindex), .address.in6 = in6addr_loopback, }; return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n); } } return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n); } static int synthesize_system_hostname_ptr(Manager *m, int af, const union in_addr_union *address, int ifindex, DnsAnswer **answer) { _cleanup_free_ struct local_address *addresses = NULL; int n, r; assert(m); assert(address); assert(answer); if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) { /* Always map the IPv4 address 127.0.0.2 to the local * hostname, in addition to "localhost": */ r = dns_answer_reserve(answer, 3); if (r < 0) return r; r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->llmnr_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->mdns_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; return 0; } n = local_addresses(m->rtnl, ifindex, af, &addresses); if (n < 0) return n; r = answer_add_addresses_ptr(answer, m->llmnr_hostname, addresses, n, af, address); if (r < 0) return r; return answer_add_addresses_ptr(answer, m->mdns_hostname, addresses, n, af, address); } static int synthesize_gateway_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) { _cleanup_free_ struct local_address *addresses = NULL; int n = 0, af; assert(m); assert(key); assert(answer); af = dns_type_to_af(key->type); if (af >= 0) { n = local_gateways(m->rtnl, ifindex, af, &addresses); if (n < 0) return n; } return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n); } static int synthesize_gateway_ptr(Manager *m, int af, const union in_addr_union *address, int ifindex, DnsAnswer **answer) { _cleanup_free_ struct local_address *addresses = NULL; int n; assert(m); assert(address); assert(answer); n = local_gateways(m->rtnl, ifindex, af, &addresses); if (n < 0) return n; return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address); } int dns_synthesize_answer( Manager *m, DnsQuestion *q, int ifindex, DnsAnswer **ret) { _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; DnsResourceKey *key; bool found = false; int r; assert(m); assert(q); DNS_QUESTION_FOREACH(key, q) { union in_addr_union address; const char *name; int af; if (key->class != DNS_CLASS_IN && key->class != DNS_CLASS_ANY) continue; name = DNS_RESOURCE_KEY_NAME(key); if (is_localhost(name)) { r = synthesize_localhost_rr(m, key, ifindex, &answer); if (r < 0) return log_error_errno(r, "Failed to synthesize localhost RRs: %m"); } else if (manager_is_own_hostname(m, name)) { r = synthesize_system_hostname_rr(m, key, ifindex, &answer); if (r < 0) return log_error_errno(r, "Failed to synthesize system hostname RRs: %m"); } else if (is_gateway_hostname(name)) { r = synthesize_gateway_rr(m, key, ifindex, &answer); if (r < 0) return log_error_errno(r, "Failed to synthesize gateway RRs: %m"); } else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) || dns_name_equal(name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) { r = synthesize_localhost_ptr(m, key, ifindex, &answer); if (r < 0) return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m"); } else if (dns_name_address(name, &af, &address) > 0) { r = synthesize_system_hostname_ptr(m, af, &address, ifindex, &answer); if (r < 0) return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m"); r = synthesize_gateway_ptr(m, af, &address, ifindex, &answer); if (r < 0) return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m"); } else continue; found = true; } r = found; if (ret) { *ret = answer; answer = NULL; } return r; } systemd-229/src/resolve/resolved-dns-synthesize.h000066400000000000000000000020371265713322000223120ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2016 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "resolved-dns-answer.h" #include "resolved-dns-question.h" #include "resolved-manager.h" int dns_synthesize_ifindex(int ifindex); int dns_synthesize_family(uint64_t flags); DnsProtocol dns_synthesize_protocol(uint64_t flags); int dns_synthesize_answer(Manager *m, DnsQuestion *q, int ifindex, DnsAnswer **ret); systemd-229/src/resolve/resolved-dns-transaction.c000066400000000000000000003423571265713322000224410ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "af-list.h" #include "alloc-util.h" #include "dns-domain.h" #include "errno-list.h" #include "fd-util.h" #include "random-util.h" #include "resolved-dns-cache.h" #include "resolved-dns-transaction.h" #include "resolved-llmnr.h" #include "string-table.h" #define TRANSACTIONS_MAX 4096 static void dns_transaction_reset_answer(DnsTransaction *t) { assert(t); t->received = dns_packet_unref(t->received); t->answer = dns_answer_unref(t->answer); t->answer_rcode = 0; t->answer_dnssec_result = _DNSSEC_RESULT_INVALID; t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID; t->answer_authenticated = false; t->answer_nsec_ttl = (uint32_t) -1; t->answer_errno = 0; } static void dns_transaction_flush_dnssec_transactions(DnsTransaction *t) { DnsTransaction *z; assert(t); while ((z = set_steal_first(t->dnssec_transactions))) { set_remove(z->notify_transactions, t); dns_transaction_gc(z); } } static void dns_transaction_close_connection(DnsTransaction *t) { assert(t); t->stream = dns_stream_free(t->stream); t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source); t->dns_udp_fd = safe_close(t->dns_udp_fd); } static void dns_transaction_stop_timeout(DnsTransaction *t) { assert(t); t->timeout_event_source = sd_event_source_unref(t->timeout_event_source); } DnsTransaction* dns_transaction_free(DnsTransaction *t) { DnsQueryCandidate *c; DnsZoneItem *i; DnsTransaction *z; if (!t) return NULL; log_debug("Freeing transaction %" PRIu16 ".", t->id); dns_transaction_close_connection(t); dns_transaction_stop_timeout(t); dns_packet_unref(t->sent); dns_transaction_reset_answer(t); dns_server_unref(t->server); if (t->scope) { hashmap_remove_value(t->scope->transactions_by_key, t->key, t); LIST_REMOVE(transactions_by_scope, t->scope->transactions, t); if (t->id != 0) hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id)); } while ((c = set_steal_first(t->notify_query_candidates))) set_remove(c->transactions, t); set_free(t->notify_query_candidates); while ((i = set_steal_first(t->notify_zone_items))) i->probe_transaction = NULL; set_free(t->notify_zone_items); while ((z = set_steal_first(t->notify_transactions))) set_remove(z->dnssec_transactions, t); set_free(t->notify_transactions); dns_transaction_flush_dnssec_transactions(t); set_free(t->dnssec_transactions); dns_answer_unref(t->validated_keys); dns_resource_key_unref(t->key); free(t->key_string); free(t); return NULL; } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free); bool dns_transaction_gc(DnsTransaction *t) { assert(t); if (t->block_gc > 0) return true; if (set_isempty(t->notify_query_candidates) && set_isempty(t->notify_zone_items) && set_isempty(t->notify_transactions)) { dns_transaction_free(t); return false; } return true; } static uint16_t pick_new_id(Manager *m) { uint16_t new_id; /* Find a fresh, unused transaction id. Note that this loop is bounded because there's a limit on the number of * transactions, and it's much lower than the space of IDs. */ assert_cc(TRANSACTIONS_MAX < 0xFFFF); do random_bytes(&new_id, sizeof(new_id)); while (new_id == 0 || hashmap_get(m->dns_transactions, UINT_TO_PTR(new_id))); return new_id; } int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) { _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL; int r; assert(ret); assert(s); assert(key); /* Don't allow looking up invalid or pseudo RRs */ if (!dns_type_is_valid_query(key->type)) return -EINVAL; if (dns_type_is_obsolete(key->type)) return -EOPNOTSUPP; /* We only support the IN class */ if (key->class != DNS_CLASS_IN && key->class != DNS_CLASS_ANY) return -EOPNOTSUPP; if (hashmap_size(s->manager->dns_transactions) >= TRANSACTIONS_MAX) return -EBUSY; r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL); if (r < 0) return r; r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops); if (r < 0) return r; t = new0(DnsTransaction, 1); if (!t) return -ENOMEM; t->dns_udp_fd = -1; t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID; t->answer_dnssec_result = _DNSSEC_RESULT_INVALID; t->answer_nsec_ttl = (uint32_t) -1; t->key = dns_resource_key_ref(key); t->current_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID; t->id = pick_new_id(s->manager); r = hashmap_put(s->manager->dns_transactions, UINT_TO_PTR(t->id), t); if (r < 0) { t->id = 0; return r; } r = hashmap_replace(s->transactions_by_key, t->key, t); if (r < 0) { hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id)); return r; } LIST_PREPEND(transactions_by_scope, s->transactions, t); t->scope = s; s->manager->n_transactions_total ++; if (ret) *ret = t; t = NULL; return 0; } static void dns_transaction_shuffle_id(DnsTransaction *t) { uint16_t new_id; assert(t); /* Pick a new ID for this transaction. */ new_id = pick_new_id(t->scope->manager); assert_se(hashmap_remove_and_put(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id), UINT_TO_PTR(new_id), t) >= 0); log_debug("Transaction %" PRIu16 " is now %" PRIu16 ".", t->id, new_id); t->id = new_id; /* Make sure we generate a new packet with the new ID */ t->sent = dns_packet_unref(t->sent); } static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) { _cleanup_free_ char *pretty = NULL; DnsZoneItem *z; assert(t); assert(p); if (manager_our_packet(t->scope->manager, p) != 0) return; in_addr_to_string(p->family, &p->sender, &pretty); log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s got tentative packet from %s.", t->id, dns_transaction_key_string(t), dns_protocol_to_string(t->scope->protocol), t->scope->link ? t->scope->link->name : "*", t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family), pretty); /* RFC 4795, Section 4.1 says that the peer with the * lexicographically smaller IP address loses */ if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) >= 0) { log_debug("Peer has lexicographically larger IP address and thus lost in the conflict."); return; } log_debug("We have the lexicographically larger IP address and thus lost in the conflict."); t->block_gc++; while ((z = set_first(t->notify_zone_items))) { /* First, make sure the zone item drops the reference * to us */ dns_zone_item_probe_stop(z); /* Secondly, report this as conflict, so that we might * look for a different hostname */ dns_zone_item_conflict(z); } t->block_gc--; dns_transaction_gc(t); } void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) { DnsQueryCandidate *c; DnsZoneItem *z; DnsTransaction *d; Iterator i; const char *st; assert(t); assert(!DNS_TRANSACTION_IS_LIVE(state)); if (state == DNS_TRANSACTION_DNSSEC_FAILED) log_struct(LOG_NOTICE, LOG_MESSAGE_ID(SD_MESSAGE_DNSSEC_FAILURE), LOG_MESSAGE("DNSSEC validation failed for question %s: %s", dns_transaction_key_string(t), dnssec_result_to_string(t->answer_dnssec_result)), "DNS_TRANSACTION=%" PRIu16, t->id, "DNS_QUESTION=%s", dns_transaction_key_string(t), "DNSSEC_RESULT=%s", dnssec_result_to_string(t->answer_dnssec_result), "DNS_SERVER=%s", dns_server_string(t->server), "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(t->server->possible_feature_level), NULL); /* Note that this call might invalidate the query. Callers * should hence not attempt to access the query or transaction * after calling this function. */ if (state == DNS_TRANSACTION_ERRNO) st = errno_to_name(t->answer_errno); else st = dns_transaction_state_to_string(state); log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s now complete with <%s> from %s (%s).", t->id, dns_transaction_key_string(t), dns_protocol_to_string(t->scope->protocol), t->scope->link ? t->scope->link->name : "*", t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family), st, t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source), t->answer_authenticated ? "authenticated" : "unsigned"); t->state = state; dns_transaction_close_connection(t); dns_transaction_stop_timeout(t); /* Notify all queries that are interested, but make sure the * transaction isn't freed while we are still looking at it */ t->block_gc++; SET_FOREACH(c, t->notify_query_candidates, i) dns_query_candidate_notify(c); SET_FOREACH(z, t->notify_zone_items, i) dns_zone_item_notify(z); if (!set_isempty(t->notify_transactions)) { DnsTransaction **nt; unsigned j, n = 0; /* We need to be careful when notifying other * transactions, as that might destroy other * transactions in our list. Hence, in order to be * able to safely iterate through the list of * transactions, take a GC lock on all of them * first. Then, in a second loop, notify them, but * first unlock that specific transaction. */ nt = newa(DnsTransaction*, set_size(t->notify_transactions)); SET_FOREACH(d, t->notify_transactions, i) { nt[n++] = d; d->block_gc++; } assert(n == set_size(t->notify_transactions)); for (j = 0; j < n; j++) { if (set_contains(t->notify_transactions, nt[j])) dns_transaction_notify(nt[j], t); nt[j]->block_gc--; dns_transaction_gc(nt[j]); } } t->block_gc--; dns_transaction_gc(t); } static int dns_transaction_pick_server(DnsTransaction *t) { DnsServer *server; assert(t); assert(t->scope->protocol == DNS_PROTOCOL_DNS); server = dns_scope_get_dns_server(t->scope); if (!server) return -ESRCH; t->current_feature_level = dns_server_possible_feature_level(server); if (server == t->server) return 0; dns_server_unref(t->server); t->server = dns_server_ref(server); return 1; } static void dns_transaction_retry(DnsTransaction *t) { int r; assert(t); log_debug("Retrying transaction %" PRIu16 ".", t->id); /* Before we try again, switch to a new server. */ dns_scope_next_dns_server(t->scope); r = dns_transaction_go(t); if (r < 0) { t->answer_errno = -r; dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); } } static int dns_transaction_maybe_restart(DnsTransaction *t) { assert(t); if (!t->server) return 0; if (t->current_feature_level <= dns_server_possible_feature_level(t->server)) return 0; /* The server's current feature level is lower than when we sent the original query. We learnt something from the response or possibly an auxiliary DNSSEC response that we didn't know before. We take that as reason to restart the whole transaction. This is a good idea to deal with servers that respond rubbish if we include OPT RR or DO bit. One of these cases is documented here, for example: https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html */ log_debug("Server feature level is now lower than when we began our transaction. Restarting with new ID."); dns_transaction_shuffle_id(t); return dns_transaction_go(t); } static int on_stream_complete(DnsStream *s, int error) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; DnsTransaction *t; assert(s); assert(s->transaction); /* Copy the data we care about out of the stream before we * destroy it. */ t = s->transaction; p = dns_packet_ref(s->read_packet); t->stream = dns_stream_free(t->stream); if (ERRNO_IS_DISCONNECT(error)) { usec_t usec; if (t->scope->protocol == DNS_PROTOCOL_LLMNR) { /* If the LLMNR/TCP connection failed, the host doesn't support LLMNR, and we cannot answer the * question on this scope. */ dns_transaction_complete(t, DNS_TRANSACTION_NOT_FOUND); return 0; } log_debug_errno(error, "Connection failure for DNS TCP stream: %m"); assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0); dns_server_packet_lost(t->server, IPPROTO_TCP, t->current_feature_level, usec - t->start_usec); dns_transaction_retry(t); return 0; } if (error != 0) { t->answer_errno = error; dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); return 0; } if (dns_packet_validate_reply(p) <= 0) { log_debug("Invalid TCP reply packet."); dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); return 0; } dns_scope_check_conflicts(t->scope, p); t->block_gc++; dns_transaction_process_reply(t, p); t->block_gc--; /* If the response wasn't useful, then complete the transition * now. After all, we are the worst feature set now with TCP * sockets, and there's really no point in retrying. */ if (t->state == DNS_TRANSACTION_PENDING) dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); else dns_transaction_gc(t); return 0; } static int dns_transaction_open_tcp(DnsTransaction *t) { _cleanup_close_ int fd = -1; int r; assert(t); dns_transaction_close_connection(t); switch (t->scope->protocol) { case DNS_PROTOCOL_DNS: r = dns_transaction_pick_server(t); if (r < 0) return r; if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(t->key->type)) return -EOPNOTSUPP; r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level); if (r < 0) return r; fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, 53); break; case DNS_PROTOCOL_LLMNR: /* When we already received a reply to this (but it was truncated), send to its sender address */ if (t->received) fd = dns_scope_socket_tcp(t->scope, t->received->family, &t->received->sender, NULL, t->received->sender_port); else { union in_addr_union address; int family = AF_UNSPEC; /* Otherwise, try to talk to the owner of a * the IP address, in case this is a reverse * PTR lookup */ r = dns_name_address(DNS_RESOURCE_KEY_NAME(t->key), &family, &address); if (r < 0) return r; if (r == 0) return -EINVAL; if (family != t->scope->family) return -ESRCH; fd = dns_scope_socket_tcp(t->scope, family, &address, NULL, LLMNR_PORT); } break; default: return -EAFNOSUPPORT; } if (fd < 0) return fd; r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd); if (r < 0) return r; fd = -1; r = dns_stream_write_packet(t->stream, t->sent); if (r < 0) { t->stream = dns_stream_free(t->stream); return r; } t->stream->complete = on_stream_complete; t->stream->transaction = t; /* The interface index is difficult to determine if we are * connecting to the local host, hence fill this in right away * instead of determining it from the socket */ if (t->scope->link) t->stream->ifindex = t->scope->link->ifindex; dns_transaction_reset_answer(t); t->tried_stream = true; return 0; } static void dns_transaction_cache_answer(DnsTransaction *t) { assert(t); /* For mDNS we cache whenever we get the packet, rather than * in each transaction. */ if (!IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR)) return; /* We never cache if this packet is from the local host, under * the assumption that a locally running DNS server would * cache this anyway, and probably knows better when to flush * the cache then we could. */ if (!DNS_PACKET_SHALL_CACHE(t->received)) return; dns_cache_put(&t->scope->cache, t->key, t->answer_rcode, t->answer, t->answer_authenticated, t->answer_nsec_ttl, 0, t->received->family, &t->received->sender); } static bool dns_transaction_dnssec_is_live(DnsTransaction *t) { DnsTransaction *dt; Iterator i; assert(t); SET_FOREACH(dt, t->dnssec_transactions, i) if (DNS_TRANSACTION_IS_LIVE(dt->state)) return true; return false; } static int dns_transaction_dnssec_ready(DnsTransaction *t) { DnsTransaction *dt; Iterator i; assert(t); /* Checks whether the auxiliary DNSSEC transactions of our transaction have completed, or are still * ongoing. Returns 0, if we aren't ready for the DNSSEC validation, positive if we are. */ SET_FOREACH(dt, t->dnssec_transactions, i) { switch (dt->state) { case DNS_TRANSACTION_NULL: case DNS_TRANSACTION_PENDING: case DNS_TRANSACTION_VALIDATING: /* Still ongoing */ return 0; case DNS_TRANSACTION_RCODE_FAILURE: if (dt->answer_rcode != DNS_RCODE_NXDOMAIN) { log_debug("Auxiliary DNSSEC RR query failed with rcode=%s.", dns_rcode_to_string(dt->answer_rcode)); goto fail; } /* Fall-through: NXDOMAIN is good enough for us. This is because some DNS servers erronously * return NXDOMAIN for empty non-terminals (Akamai...), and we need to handle that nicely, when * asking for parent SOA or similar RRs to make unsigned proofs. */ case DNS_TRANSACTION_SUCCESS: /* All good. */ break; case DNS_TRANSACTION_DNSSEC_FAILED: /* We handle DNSSEC failures different from other errors, as we care about the DNSSEC * validationr result */ log_debug("Auxiliary DNSSEC RR query failed validation: %s", dnssec_result_to_string(dt->answer_dnssec_result)); t->answer_dnssec_result = dt->answer_dnssec_result; /* Copy error code over */ dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED); return 0; default: log_debug("Auxiliary DNSSEC RR query failed with %s", dns_transaction_state_to_string(dt->state)); goto fail; } } /* All is ready, we can go and validate */ return 1; fail: t->answer_dnssec_result = DNSSEC_FAILED_AUXILIARY; dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED); return 0; } static void dns_transaction_process_dnssec(DnsTransaction *t) { int r; assert(t); /* Are there ongoing DNSSEC transactions? If so, let's wait for them. */ r = dns_transaction_dnssec_ready(t); if (r < 0) goto fail; if (r == 0) /* We aren't ready yet (or one of our auxiliary transactions failed, and we shouldn't validate now */ return; /* See if we learnt things from the additional DNSSEC transactions, that we didn't know before, and better * restart the lookup immediately. */ r = dns_transaction_maybe_restart(t); if (r < 0) goto fail; if (r > 0) /* Transaction got restarted... */ return; /* All our auxiliary DNSSEC transactions are complete now. Try * to validate our RRset now. */ r = dns_transaction_validate_dnssec(t); if (r == -EBADMSG) { dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); return; } if (r < 0) goto fail; if (t->answer_dnssec_result == DNSSEC_INCOMPATIBLE_SERVER && t->scope->dnssec_mode == DNSSEC_YES) { /* We are not in automatic downgrade mode, and the * server is bad, refuse operation. */ dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED); return; } if (!IN_SET(t->answer_dnssec_result, _DNSSEC_RESULT_INVALID, /* No DNSSEC validation enabled */ DNSSEC_VALIDATED, /* Answer is signed and validated successfully */ DNSSEC_UNSIGNED, /* Answer is right-fully unsigned */ DNSSEC_INCOMPATIBLE_SERVER)) { /* Server does not do DNSSEC (Yay, we are downgrade attack vulnerable!) */ dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED); return; } if (t->answer_dnssec_result == DNSSEC_INCOMPATIBLE_SERVER) dns_server_warn_downgrade(t->server); dns_transaction_cache_answer(t); if (t->answer_rcode == DNS_RCODE_SUCCESS) dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); else dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE); return; fail: t->answer_errno = -r; dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); } static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) { int r; assert(t); /* Checks whether the answer is positive, i.e. either a direct * answer to the question, or a CNAME/DNAME for it */ r = dns_answer_match_key(t->answer, t->key, flags); if (r != 0) return r; r = dns_answer_find_cname_or_dname(t->answer, t->key, NULL, flags); if (r != 0) return r; return false; } static int dns_transaction_fix_rcode(DnsTransaction *t) { int r; assert(t); /* Fix up the RCODE to SUCCESS if we get at least one matching RR in a response. Note that this contradicts the * DNS RFCs a bit. Specifically, RFC 6604 Section 3 clarifies that the RCODE shall say something about a * CNAME/DNAME chain element coming after the last chain element contained in the message, and not the first * one included. However, it also indicates that not all DNS servers implement this correctly. Moreover, when * using DNSSEC we usually only can prove the first element of a CNAME/DNAME chain anyway, hence let's settle * on always processing the RCODE as referring to the immediate look-up we do, i.e. the first element of a * CNAME/DNAME chain. This way, we uniformly handle CNAME/DNAME chains, regardless if the DNS server * incorrectly implements RCODE, whether DNSSEC is in use, or whether the DNS server only supplied us with an * incomplete CNAME/DNAME chain. * * Or in other words: if we get at least one positive reply in a message we patch NXDOMAIN to become SUCCESS, * and then rely on the CNAME chasing logic to figure out that there's actually a CNAME error with a new * lookup. */ if (t->answer_rcode != DNS_RCODE_NXDOMAIN) return 0; r = dns_transaction_has_positive_answer(t, NULL); if (r <= 0) return r; t->answer_rcode = DNS_RCODE_SUCCESS; return 0; } void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { usec_t ts; int r; assert(t); assert(p); assert(t->scope); assert(t->scope->manager); if (t->state != DNS_TRANSACTION_PENDING) return; /* Note that this call might invalidate the query. Callers * should hence not attempt to access the query or transaction * after calling this function. */ log_debug("Processing incoming packet on transaction %" PRIu16".", t->id); switch (t->scope->protocol) { case DNS_PROTOCOL_LLMNR: assert(t->scope->link); /* For LLMNR we will not accept any packets from other * interfaces */ if (p->ifindex != t->scope->link->ifindex) return; if (p->family != t->scope->family) return; /* Tentative packets are not full responses but still * useful for identifying uniqueness conflicts during * probing. */ if (DNS_PACKET_LLMNR_T(p)) { dns_transaction_tentative(t, p); return; } break; case DNS_PROTOCOL_MDNS: assert(t->scope->link); /* For mDNS we will not accept any packets from other interfaces */ if (p->ifindex != t->scope->link->ifindex) return; if (p->family != t->scope->family) return; break; case DNS_PROTOCOL_DNS: /* Note that we do not need to verify the * addresses/port numbers of incoming traffic, as we * invoked connect() on our UDP socket in which case * the kernel already does the needed verification for * us. */ break; default: assert_not_reached("Invalid DNS protocol."); } if (t->received != p) { dns_packet_unref(t->received); t->received = dns_packet_ref(p); } t->answer_source = DNS_TRANSACTION_NETWORK; if (p->ipproto == IPPROTO_TCP) { if (DNS_PACKET_TC(p)) { /* Truncated via TCP? Somebody must be fucking with us */ dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); return; } if (DNS_PACKET_ID(p) != t->id) { /* Not the reply to our query? Somebody must be fucking with us */ dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); return; } } assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); switch (t->scope->protocol) { case DNS_PROTOCOL_DNS: assert(t->server); if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) { /* Request failed, immediately try again with reduced features */ log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p))); dns_server_packet_failed(t->server, t->current_feature_level); dns_transaction_retry(t); return; } else if (DNS_PACKET_TC(p)) dns_server_packet_truncated(t->server, t->current_feature_level); break; case DNS_PROTOCOL_LLMNR: case DNS_PROTOCOL_MDNS: dns_scope_packet_received(t->scope, ts - t->start_usec); break; default: assert_not_reached("Invalid DNS protocol."); } if (DNS_PACKET_TC(p)) { /* Truncated packets for mDNS are not allowed. Give up immediately. */ if (t->scope->protocol == DNS_PROTOCOL_MDNS) { dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); return; } log_debug("Reply truncated, retrying via TCP."); /* Response was truncated, let's try again with good old TCP */ r = dns_transaction_open_tcp(t); if (r == -ESRCH) { /* No servers found? Damn! */ dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS); return; } if (r == -EOPNOTSUPP) { /* Tried to ask for DNSSEC RRs, on a server that doesn't do DNSSEC */ dns_transaction_complete(t, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED); return; } if (r < 0) { /* On LLMNR, if we cannot connect to the host, * we immediately give up */ if (t->scope->protocol != DNS_PROTOCOL_DNS) goto fail; /* On DNS, couldn't send? Try immediately again, with a new server */ dns_transaction_retry(t); } return; } /* After the superficial checks, actually parse the message. */ r = dns_packet_extract(p); if (r < 0) { dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); return; } /* Report that the OPT RR was missing */ if (t->server) { if (!p->opt) dns_server_packet_bad_opt(t->server, t->current_feature_level); dns_server_packet_received(t->server, p->ipproto, t->current_feature_level, ts - t->start_usec, p->size); } /* See if we know things we didn't know before that indicate we better restart the lookup immediately. */ r = dns_transaction_maybe_restart(t); if (r < 0) goto fail; if (r > 0) /* Transaction got restarted... */ return; if (IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR)) { /* Only consider responses with equivalent query section to the request */ r = dns_packet_is_reply_for(p, t->key); if (r < 0) goto fail; if (r == 0) { dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); return; } /* Install the answer as answer to the transaction */ dns_answer_unref(t->answer); t->answer = dns_answer_ref(p->answer); t->answer_rcode = DNS_PACKET_RCODE(p); t->answer_dnssec_result = _DNSSEC_RESULT_INVALID; t->answer_authenticated = false; r = dns_transaction_fix_rcode(t); if (r < 0) goto fail; /* Block GC while starting requests for additional DNSSEC RRs */ t->block_gc++; r = dns_transaction_request_dnssec_keys(t); t->block_gc--; /* Maybe the transaction is ready for GC'ing now? If so, free it and return. */ if (!dns_transaction_gc(t)) return; /* Requesting additional keys might have resulted in * this transaction to fail, since the auxiliary * request failed for some reason. If so, we are not * in pending state anymore, and we should exit * quickly. */ if (t->state != DNS_TRANSACTION_PENDING) return; if (r < 0) goto fail; if (r > 0) { /* There are DNSSEC transactions pending now. Update the state accordingly. */ t->state = DNS_TRANSACTION_VALIDATING; dns_transaction_close_connection(t); dns_transaction_stop_timeout(t); return; } } dns_transaction_process_dnssec(t); return; fail: t->answer_errno = -r; dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); } static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; DnsTransaction *t = userdata; int r; assert(t); assert(t->scope); r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p); if (ERRNO_IS_DISCONNECT(-r)) { usec_t usec; /* UDP connection failure get reported via ICMP and then are possible delivered to us on the next * recvmsg(). Treat this like a lost packet. */ log_debug_errno(r, "Connection failure for DNS UDP packet: %m"); assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0); dns_server_packet_lost(t->server, IPPROTO_UDP, t->current_feature_level, usec - t->start_usec); dns_transaction_retry(t); return 0; } if (r < 0) { dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); t->answer_errno = -r; return 0; } r = dns_packet_validate_reply(p); if (r < 0) { log_debug_errno(r, "Received invalid DNS packet as response, ignoring: %m"); return 0; } if (r == 0) { log_debug("Received inappropriate DNS packet as response, ignoring."); return 0; } if (DNS_PACKET_ID(p) != t->id) { log_debug("Received packet with incorrect transaction ID, ignoring."); return 0; } dns_transaction_process_reply(t, p); return 0; } static int dns_transaction_emit_udp(DnsTransaction *t) { int r; assert(t); if (t->scope->protocol == DNS_PROTOCOL_DNS) { r = dns_transaction_pick_server(t); if (r < 0) return r; if (t->current_feature_level < DNS_SERVER_FEATURE_LEVEL_UDP) return -EAGAIN; if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(t->key->type)) return -EOPNOTSUPP; if (r > 0 || t->dns_udp_fd < 0) { /* Server changed, or no connection yet. */ int fd; dns_transaction_close_connection(t); fd = dns_scope_socket_udp(t->scope, t->server, 53); if (fd < 0) return fd; r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t); if (r < 0) { safe_close(fd); return r; } (void) sd_event_source_set_description(t->dns_udp_event_source, "dns-transaction-udp"); t->dns_udp_fd = fd; } r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level); if (r < 0) return r; } else dns_transaction_close_connection(t); r = dns_scope_emit_udp(t->scope, t->dns_udp_fd, t->sent); if (r < 0) return r; dns_transaction_reset_answer(t); return 0; } static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) { DnsTransaction *t = userdata; assert(s); assert(t); if (!t->initial_jitter_scheduled || t->initial_jitter_elapsed) { /* Timeout reached? Increase the timeout for the server used */ switch (t->scope->protocol) { case DNS_PROTOCOL_DNS: assert(t->server); dns_server_packet_lost(t->server, t->stream ? IPPROTO_TCP : IPPROTO_UDP, t->current_feature_level, usec - t->start_usec); break; case DNS_PROTOCOL_LLMNR: case DNS_PROTOCOL_MDNS: dns_scope_packet_lost(t->scope, usec - t->start_usec); break; default: assert_not_reached("Invalid DNS protocol."); } if (t->initial_jitter_scheduled) t->initial_jitter_elapsed = true; } log_debug("Timeout reached on transaction %" PRIu16 ".", t->id); dns_transaction_retry(t); return 0; } static usec_t transaction_get_resend_timeout(DnsTransaction *t) { assert(t); assert(t->scope); switch (t->scope->protocol) { case DNS_PROTOCOL_DNS: assert(t->server); return t->server->resend_timeout; case DNS_PROTOCOL_MDNS: assert(t->n_attempts > 0); return (1 << (t->n_attempts - 1)) * USEC_PER_SEC; case DNS_PROTOCOL_LLMNR: return t->scope->resend_timeout; default: assert_not_reached("Invalid DNS protocol."); } } static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) { int r; assert(t); dns_transaction_stop_timeout(t); r = dns_scope_network_good(t->scope); if (r < 0) return r; if (r == 0) { dns_transaction_complete(t, DNS_TRANSACTION_NETWORK_DOWN); return 0; } if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) { dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED); return 0; } if (t->scope->protocol == DNS_PROTOCOL_LLMNR && t->tried_stream) { /* If we already tried via a stream, then we don't * retry on LLMNR. See RFC 4795, Section 2.7. */ dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED); return 0; } t->n_attempts++; t->start_usec = ts; dns_transaction_reset_answer(t); dns_transaction_flush_dnssec_transactions(t); /* Check the trust anchor. Do so only on classic DNS, since DNSSEC does not apply otherwise. */ if (t->scope->protocol == DNS_PROTOCOL_DNS) { r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, t->key, &t->answer); if (r < 0) return r; if (r > 0) { t->answer_rcode = DNS_RCODE_SUCCESS; t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR; t->answer_authenticated = true; dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); return 0; } if (dns_name_is_root(DNS_RESOURCE_KEY_NAME(t->key)) && t->key->type == DNS_TYPE_DS) { /* Hmm, this is a request for the root DS? A * DS RR doesn't exist in the root zone, and * if our trust anchor didn't know it either, * this means we cannot do any DNSSEC logic * anymore. */ if (t->scope->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE) { /* We are in downgrade mode. In this * case, synthesize an unsigned empty * response, so that the any lookup * depending on this one can continue * assuming there was no DS, and hence * the root zone was unsigned. */ t->answer_rcode = DNS_RCODE_SUCCESS; t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR; t->answer_authenticated = false; dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); } else /* If we are not in downgrade mode, * then fail the lookup, because we * cannot reasonably answer it. There * might be DS RRs, but we don't know * them, and the DNS server won't tell * them to us (and even if it would, * we couldn't validate it and trust * it). */ dns_transaction_complete(t, DNS_TRANSACTION_NO_TRUST_ANCHOR); return 0; } } /* Check the zone, but only if this transaction is not used * for probing or verifying a zone item. */ if (set_isempty(t->notify_zone_items)) { r = dns_zone_lookup(&t->scope->zone, t->key, &t->answer, NULL, NULL); if (r < 0) return r; if (r > 0) { t->answer_rcode = DNS_RCODE_SUCCESS; t->answer_source = DNS_TRANSACTION_ZONE; t->answer_authenticated = true; dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); return 0; } } /* Check the cache, but only if this transaction is not used * for probing or verifying a zone item. */ if (set_isempty(t->notify_zone_items)) { /* Before trying the cache, let's make sure we figured out a * server to use. Should this cause a change of server this * might flush the cache. */ dns_scope_get_dns_server(t->scope); /* Let's then prune all outdated entries */ dns_cache_prune(&t->scope->cache); r = dns_cache_lookup(&t->scope->cache, t->key, &t->answer_rcode, &t->answer, &t->answer_authenticated); if (r < 0) return r; if (r > 0) { t->answer_source = DNS_TRANSACTION_CACHE; if (t->answer_rcode == DNS_RCODE_SUCCESS) dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); else dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE); return 0; } } return 1; } static int dns_transaction_make_packet_mdns(DnsTransaction *t) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; bool add_known_answers = false; DnsTransaction *other; unsigned qdcount; usec_t ts; int r; assert(t); assert(t->scope->protocol == DNS_PROTOCOL_MDNS); /* Discard any previously prepared packet, so we can start over and coalesce again */ t->sent = dns_packet_unref(t->sent); r = dns_packet_new_query(&p, t->scope->protocol, 0, false); if (r < 0) return r; r = dns_packet_append_key(p, t->key, NULL); if (r < 0) return r; qdcount = 1; if (dns_key_is_shared(t->key)) add_known_answers = true; /* * For mDNS, we want to coalesce as many open queries in pending transactions into one single * query packet on the wire as possible. To achieve that, we iterate through all pending transactions * in our current scope, and see whether their timing contraints allow them to be sent. */ assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); LIST_FOREACH(transactions_by_scope, other, t->scope->transactions) { /* Skip ourselves */ if (other == t) continue; if (other->state != DNS_TRANSACTION_PENDING) continue; if (other->next_attempt_after > ts) continue; if (qdcount >= UINT16_MAX) break; r = dns_packet_append_key(p, other->key, NULL); /* * If we can't stuff more questions into the packet, just give up. * One of the 'other' transactions will fire later and take care of the rest. */ if (r == -EMSGSIZE) break; if (r < 0) return r; r = dns_transaction_prepare(other, ts); if (r <= 0) continue; ts += transaction_get_resend_timeout(other); r = sd_event_add_time( other->scope->manager->event, &other->timeout_event_source, clock_boottime_or_monotonic(), ts, 0, on_transaction_timeout, other); if (r < 0) return r; (void) sd_event_source_set_description(t->timeout_event_source, "dns-transaction-timeout"); other->state = DNS_TRANSACTION_PENDING; other->next_attempt_after = ts; qdcount ++; if (dns_key_is_shared(other->key)) add_known_answers = true; } DNS_PACKET_HEADER(p)->qdcount = htobe16(qdcount); /* Append known answer section if we're asking for any shared record */ if (add_known_answers) { r = dns_cache_export_shared_to_packet(&t->scope->cache, p); if (r < 0) return r; } t->sent = p; p = NULL; return 0; } static int dns_transaction_make_packet(DnsTransaction *t) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; int r; assert(t); if (t->scope->protocol == DNS_PROTOCOL_MDNS) return dns_transaction_make_packet_mdns(t); if (t->sent) return 0; r = dns_packet_new_query(&p, t->scope->protocol, 0, t->scope->dnssec_mode != DNSSEC_NO); if (r < 0) return r; r = dns_packet_append_key(p, t->key, NULL); if (r < 0) return r; DNS_PACKET_HEADER(p)->qdcount = htobe16(1); DNS_PACKET_HEADER(p)->id = t->id; t->sent = p; p = NULL; return 0; } int dns_transaction_go(DnsTransaction *t) { usec_t ts; int r; assert(t); assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); r = dns_transaction_prepare(t, ts); if (r <= 0) return r; log_debug("Excercising transaction %" PRIu16 " for <%s> on scope %s on %s/%s.", t->id, dns_transaction_key_string(t), dns_protocol_to_string(t->scope->protocol), t->scope->link ? t->scope->link->name : "*", t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family)); if (!t->initial_jitter_scheduled && (t->scope->protocol == DNS_PROTOCOL_LLMNR || t->scope->protocol == DNS_PROTOCOL_MDNS)) { usec_t jitter, accuracy; /* RFC 4795 Section 2.7 suggests all queries should be * delayed by a random time from 0 to JITTER_INTERVAL. */ t->initial_jitter_scheduled = true; random_bytes(&jitter, sizeof(jitter)); switch (t->scope->protocol) { case DNS_PROTOCOL_LLMNR: jitter %= LLMNR_JITTER_INTERVAL_USEC; accuracy = LLMNR_JITTER_INTERVAL_USEC; break; case DNS_PROTOCOL_MDNS: jitter %= MDNS_JITTER_RANGE_USEC; jitter += MDNS_JITTER_MIN_USEC; accuracy = MDNS_JITTER_RANGE_USEC; break; default: assert_not_reached("bad protocol"); } r = sd_event_add_time( t->scope->manager->event, &t->timeout_event_source, clock_boottime_or_monotonic(), ts + jitter, accuracy, on_transaction_timeout, t); if (r < 0) return r; (void) sd_event_source_set_description(t->timeout_event_source, "dns-transaction-timeout"); t->n_attempts = 0; t->next_attempt_after = ts; t->state = DNS_TRANSACTION_PENDING; log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter); return 0; } /* Otherwise, we need to ask the network */ r = dns_transaction_make_packet(t); if (r < 0) return r; if (t->scope->protocol == DNS_PROTOCOL_LLMNR && (dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "in-addr.arpa") > 0 || dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), "ip6.arpa") > 0)) { /* RFC 4795, Section 2.4. says reverse lookups shall * always be made via TCP on LLMNR */ r = dns_transaction_open_tcp(t); } else { /* Try via UDP, and if that fails due to large size or lack of * support try via TCP */ r = dns_transaction_emit_udp(t); if (r == -EMSGSIZE) log_debug("Sending query via TCP since it is too large."); if (r == -EAGAIN) log_debug("Sending query via TCP since server doesn't support UDP."); if (r == -EMSGSIZE || r == -EAGAIN) r = dns_transaction_open_tcp(t); } if (r == -ESRCH) { /* No servers to send this to? */ dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS); return 0; } if (r == -EOPNOTSUPP) { /* Tried to ask for DNSSEC RRs, on a server that doesn't do DNSSEC */ dns_transaction_complete(t, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED); return 0; } if (t->scope->protocol == DNS_PROTOCOL_LLMNR && ERRNO_IS_DISCONNECT(-r)) { /* On LLMNR, if we cannot connect to a host via TCP when doing reverse lookups. This means we cannot * answer this request with this protocol. */ dns_transaction_complete(t, DNS_TRANSACTION_NOT_FOUND); return 0; } if (r < 0) { if (t->scope->protocol != DNS_PROTOCOL_DNS) return r; /* Couldn't send? Try immediately again, with a new server */ dns_scope_next_dns_server(t->scope); return dns_transaction_go(t); } ts += transaction_get_resend_timeout(t); r = sd_event_add_time( t->scope->manager->event, &t->timeout_event_source, clock_boottime_or_monotonic(), ts, 0, on_transaction_timeout, t); if (r < 0) return r; (void) sd_event_source_set_description(t->timeout_event_source, "dns-transaction-timeout"); t->state = DNS_TRANSACTION_PENDING; t->next_attempt_after = ts; return 1; } static int dns_transaction_find_cyclic(DnsTransaction *t, DnsTransaction *aux) { DnsTransaction *n; Iterator i; int r; assert(t); assert(aux); /* Try to find cyclic dependencies between transaction objects */ if (t == aux) return 1; SET_FOREACH(n, aux->dnssec_transactions, i) { r = dns_transaction_find_cyclic(t, n); if (r != 0) return r; } return 0; } static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResourceKey *key, DnsTransaction **ret) { DnsTransaction *aux; int r; assert(t); assert(ret); assert(key); aux = dns_scope_find_transaction(t->scope, key, true); if (!aux) { r = dns_transaction_new(&aux, t->scope, key); if (r < 0) return r; } else { if (set_contains(t->dnssec_transactions, aux)) { *ret = aux; return 0; } r = dns_transaction_find_cyclic(t, aux); if (r < 0) return r; if (r > 0) { log_debug("Detected potential cyclic dependency, refusing to add transaction %" PRIu16 " (%s) as dependency for %" PRIu16 " (%s).", aux->id, strna(dns_transaction_key_string(aux)), t->id, strna(dns_transaction_key_string(t))); return -ELOOP; } } r = set_ensure_allocated(&t->dnssec_transactions, NULL); if (r < 0) goto gc; r = set_ensure_allocated(&aux->notify_transactions, NULL); if (r < 0) goto gc; r = set_put(t->dnssec_transactions, aux); if (r < 0) goto gc; r = set_put(aux->notify_transactions, t); if (r < 0) { (void) set_remove(t->dnssec_transactions, aux); goto gc; } *ret = aux; return 1; gc: dns_transaction_gc(aux); return r; } static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *key) { _cleanup_(dns_answer_unrefp) DnsAnswer *a = NULL; DnsTransaction *aux; int r; assert(t); assert(key); /* Try to get the data from the trust anchor */ r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, key, &a); if (r < 0) return r; if (r > 0) { r = dns_answer_extend(&t->validated_keys, a); if (r < 0) return r; return 0; } /* This didn't work, ask for it via the network/cache then. */ r = dns_transaction_add_dnssec_transaction(t, key, &aux); if (r == -ELOOP) /* This would result in a cyclic dependency */ return 0; if (r < 0) return r; if (aux->state == DNS_TRANSACTION_NULL) { r = dns_transaction_go(aux); if (r < 0) return r; } return 1; } static int dns_transaction_negative_trust_anchor_lookup(DnsTransaction *t, const char *name) { int r; assert(t); /* Check whether the specified name is in the the NTA * database, either in the global one, or the link-local * one. */ r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, name); if (r != 0) return r; if (!t->scope->link) return 0; return set_contains(t->scope->link->dnssec_negative_trust_anchors, name); } static int dns_transaction_has_unsigned_negative_answer(DnsTransaction *t) { int r; assert(t); /* Checks whether the answer is negative, and lacks NSEC/NSEC3 * RRs to prove it */ r = dns_transaction_has_positive_answer(t, NULL); if (r < 0) return r; if (r > 0) return false; /* Is this key explicitly listed as a negative trust anchor? * If so, it's nothing we need to care about */ r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(t->key)); if (r < 0) return r; if (r > 0) return false; /* The answer does not contain any RRs that match to the * question. If so, let's see if there are any NSEC/NSEC3 RRs * included. If not, the answer is unsigned. */ r = dns_answer_contains_nsec_or_nsec3(t->answer); if (r < 0) return r; if (r > 0) return false; return true; } static int dns_transaction_is_primary_response(DnsTransaction *t, DnsResourceRecord *rr) { int r; assert(t); assert(rr); /* Check if the specified RR is the "primary" response, * i.e. either matches the question precisely or is a * CNAME/DNAME for it. */ r = dns_resource_key_match_rr(t->key, rr, NULL); if (r != 0) return r; return dns_resource_key_match_cname_or_dname(t->key, rr->key, NULL); } static bool dns_transaction_dnssec_supported(DnsTransaction *t) { assert(t); /* Checks whether our transaction's DNS server is assumed to be compatible with DNSSEC. Returns false as soon * as we changed our mind about a server, and now believe it is incompatible with DNSSEC. */ if (t->scope->protocol != DNS_PROTOCOL_DNS) return false; /* If we have picked no server, then we are working from the cache or some other source, and DNSSEC might well * be supported, hence return true. */ if (!t->server) return true; if (t->current_feature_level < DNS_SERVER_FEATURE_LEVEL_DO) return false; return dns_server_dnssec_supported(t->server); } static bool dns_transaction_dnssec_supported_full(DnsTransaction *t) { DnsTransaction *dt; Iterator i; assert(t); /* Checks whether our transaction our any of the auxiliary transactions couldn't do DNSSEC. */ if (!dns_transaction_dnssec_supported(t)) return false; SET_FOREACH(dt, t->dnssec_transactions, i) if (!dns_transaction_dnssec_supported(dt)) return false; return true; } int dns_transaction_request_dnssec_keys(DnsTransaction *t) { DnsResourceRecord *rr; int r; assert(t); /* * Retrieve all auxiliary RRs for the answer we got, so that * we can verify signatures or prove that RRs are rightfully * unsigned. Specifically: * * - For RRSIG we get the matching DNSKEY * - For DNSKEY we get the matching DS * - For unsigned SOA/NS we get the matching DS * - For unsigned CNAME/DNAME/DS we get the parent SOA RR * - For other unsigned RRs we get the matching SOA RR * - For SOA/NS/DS queries with no matching response RRs, and no NSEC/NSEC3, the parent's SOA RR * - For other queries with no matching response RRs, and no NSEC/NSEC3, the SOA RR */ if (t->scope->dnssec_mode == DNSSEC_NO) return 0; if (t->answer_source != DNS_TRANSACTION_NETWORK) return 0; /* We only need to validate stuff from the network */ if (!dns_transaction_dnssec_supported(t)) return 0; /* If we can't do DNSSEC anyway there's no point in geting the auxiliary RRs */ DNS_ANSWER_FOREACH(rr, t->answer) { if (dns_type_is_pseudo(rr->key->type)) continue; /* If this RR is in the negative trust anchor, we don't need to validate it. */ r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(rr->key)); if (r < 0) return r; if (r > 0) continue; switch (rr->key->type) { case DNS_TYPE_RRSIG: { /* For each RRSIG we request the matching DNSKEY */ _cleanup_(dns_resource_key_unrefp) DnsResourceKey *dnskey = NULL; /* If this RRSIG is about a DNSKEY RR and the * signer is the same as the owner, then we * already have the DNSKEY, and we don't have * to look for more. */ if (rr->rrsig.type_covered == DNS_TYPE_DNSKEY) { r = dns_name_equal(rr->rrsig.signer, DNS_RESOURCE_KEY_NAME(rr->key)); if (r < 0) return r; if (r > 0) continue; } /* If the signer is not a parent of our * original query, then this is about an * auxiliary RRset, but not anything we asked * for. In this case we aren't interested, * because we don't want to request additional * RRs for stuff we didn't really ask for, and * also to avoid request loops, where * additional RRs from one transaction result * in another transaction whose additonal RRs * point back to the original transaction, and * we deadlock. */ r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), rr->rrsig.signer); if (r < 0) return r; if (r == 0) continue; dnskey = dns_resource_key_new(rr->key->class, DNS_TYPE_DNSKEY, rr->rrsig.signer); if (!dnskey) return -ENOMEM; log_debug("Requesting DNSKEY to validate transaction %" PRIu16" (%s, RRSIG with key tag: %" PRIu16 ").", t->id, DNS_RESOURCE_KEY_NAME(rr->key), rr->rrsig.key_tag); r = dns_transaction_request_dnssec_rr(t, dnskey); if (r < 0) return r; break; } case DNS_TYPE_DNSKEY: { /* For each DNSKEY we request the matching DS */ _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL; /* If the DNSKEY we are looking at is not for * zone we are interested in, nor any of its * parents, we aren't interested, and don't * request it. After all, we don't want to end * up in request loops, and want to keep * additional traffic down. */ r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(t->key), DNS_RESOURCE_KEY_NAME(rr->key)); if (r < 0) return r; if (r == 0) continue; ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(rr->key)); if (!ds) return -ENOMEM; log_debug("Requesting DS to validate transaction %" PRIu16" (%s, DNSKEY with key tag: %" PRIu16 ").", t->id, DNS_RESOURCE_KEY_NAME(rr->key), dnssec_keytag(rr, false)); r = dns_transaction_request_dnssec_rr(t, ds); if (r < 0) return r; break; } case DNS_TYPE_SOA: case DNS_TYPE_NS: { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL; /* For an unsigned SOA or NS, try to acquire * the matching DS RR, as we are at a zone cut * then, and whether a DS exists tells us * whether the zone is signed. Do so only if * this RR matches our original question, * however. */ r = dns_resource_key_match_rr(t->key, rr, NULL); if (r < 0) return r; if (r == 0) continue; r = dnssec_has_rrsig(t->answer, rr->key); if (r < 0) return r; if (r > 0) continue; ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(rr->key)); if (!ds) return -ENOMEM; log_debug("Requesting DS to validate transaction %" PRIu16 " (%s, unsigned SOA/NS RRset).", t->id, DNS_RESOURCE_KEY_NAME(rr->key)); r = dns_transaction_request_dnssec_rr(t, ds); if (r < 0) return r; break; } case DNS_TYPE_DS: case DNS_TYPE_CNAME: case DNS_TYPE_DNAME: { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL; const char *name; /* CNAMEs and DNAMEs cannot be located at a * zone apex, hence ask for the parent SOA for * unsigned CNAME/DNAME RRs, maybe that's the * apex. But do all that only if this is * actually a response to our original * question. * * Similar for DS RRs, which are signed when * the parent SOA is signed. */ r = dns_transaction_is_primary_response(t, rr); if (r < 0) return r; if (r == 0) continue; r = dnssec_has_rrsig(t->answer, rr->key); if (r < 0) return r; if (r > 0) continue; r = dns_answer_has_dname_for_cname(t->answer, rr); if (r < 0) return r; if (r > 0) continue; name = DNS_RESOURCE_KEY_NAME(rr->key); r = dns_name_parent(&name); if (r < 0) return r; if (r == 0) continue; soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, name); if (!soa) return -ENOMEM; log_debug("Requesting parent SOA to validate transaction %" PRIu16 " (%s, unsigned CNAME/DNAME/DS RRset).", t->id, DNS_RESOURCE_KEY_NAME(rr->key)); r = dns_transaction_request_dnssec_rr(t, soa); if (r < 0) return r; break; } default: { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL; /* For other unsigned RRsets (including * NSEC/NSEC3!), look for proof the zone is * unsigned, by requesting the SOA RR of the * zone. However, do so only if they are * directly relevant to our original * question. */ r = dns_transaction_is_primary_response(t, rr); if (r < 0) return r; if (r == 0) continue; r = dnssec_has_rrsig(t->answer, rr->key); if (r < 0) return r; if (r > 0) continue; soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, DNS_RESOURCE_KEY_NAME(rr->key)); if (!soa) return -ENOMEM; log_debug("Requesting SOA to validate transaction %" PRIu16 " (%s, unsigned non-SOA/NS RRset <%s>).", t->id, DNS_RESOURCE_KEY_NAME(rr->key), dns_resource_record_to_string(rr)); r = dns_transaction_request_dnssec_rr(t, soa); if (r < 0) return r; break; }} } /* Above, we requested everything necessary to validate what * we got. Now, let's request what we need to validate what we * didn't get... */ r = dns_transaction_has_unsigned_negative_answer(t); if (r < 0) return r; if (r > 0) { const char *name; name = DNS_RESOURCE_KEY_NAME(t->key); /* If this was a SOA or NS request, then this * indicates that we are not at a zone apex, hence ask * the parent name instead. If this was a DS request, * then it's signed when the parent zone is signed, * hence ask the parent in that case, too. */ if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS, DNS_TYPE_DS)) { r = dns_name_parent(&name); if (r < 0) return r; if (r > 0) log_debug("Requesting parent SOA to validate transaction %" PRIu16 " (%s, unsigned empty SOA/NS/DS response).", t->id, DNS_RESOURCE_KEY_NAME(t->key)); else name = NULL; } else log_debug("Requesting SOA to validate transaction %" PRIu16 " (%s, unsigned empty non-SOA/NS/DS response).", t->id, DNS_RESOURCE_KEY_NAME(t->key)); if (name) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL; soa = dns_resource_key_new(t->key->class, DNS_TYPE_SOA, name); if (!soa) return -ENOMEM; r = dns_transaction_request_dnssec_rr(t, soa); if (r < 0) return r; } } return dns_transaction_dnssec_is_live(t); } void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source) { assert(t); assert(source); /* Invoked whenever any of our auxiliary DNSSEC transactions completed its work. If the state is still PENDING, we are still in the loop that adds further DNSSEC transactions, hence don't check if we are ready yet. If the state is VALIDATING however, we should check if we are complete now. */ if (t->state == DNS_TRANSACTION_VALIDATING) dns_transaction_process_dnssec(t); } static int dns_transaction_validate_dnskey_by_ds(DnsTransaction *t) { DnsResourceRecord *rr; int ifindex, r; assert(t); /* Add all DNSKEY RRs from the answer that are validated by DS * RRs from the list of validated keys to the list of * validated keys. */ DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, t->answer) { r = dnssec_verify_dnskey_by_ds_search(rr, t->validated_keys); if (r < 0) return r; if (r == 0) continue; /* If so, the DNSKEY is validated too. */ r = dns_answer_add_extend(&t->validated_keys, rr, ifindex, DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; } return 0; } static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *rr) { int r; assert(t); assert(rr); /* Checks if the RR we are looking for must be signed with an * RRSIG. This is used for positive responses. */ if (t->scope->dnssec_mode == DNSSEC_NO) return false; if (dns_type_is_pseudo(rr->key->type)) return -EINVAL; r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(rr->key)); if (r < 0) return r; if (r > 0) return false; switch (rr->key->type) { case DNS_TYPE_RRSIG: /* RRSIGs are the signatures themselves, they need no signing. */ return false; case DNS_TYPE_SOA: case DNS_TYPE_NS: { DnsTransaction *dt; Iterator i; /* For SOA or NS RRs we look for a matching DS transaction */ SET_FOREACH(dt, t->dnssec_transactions, i) { if (dt->key->class != rr->key->class) continue; if (dt->key->type != DNS_TYPE_DS) continue; r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), DNS_RESOURCE_KEY_NAME(rr->key)); if (r < 0) return r; if (r == 0) continue; /* We found a DS transactions for the SOA/NS * RRs we are looking at. If it discovered signed DS * RRs, then we need to be signed, too. */ if (!dt->answer_authenticated) return false; return dns_answer_match_key(dt->answer, dt->key, NULL); } /* We found nothing that proves this is safe to leave * this unauthenticated, hence ask inist on * authentication. */ return true; } case DNS_TYPE_DS: case DNS_TYPE_CNAME: case DNS_TYPE_DNAME: { const char *parent = NULL; DnsTransaction *dt; Iterator i; /* * CNAME/DNAME RRs cannot be located at a zone apex, hence look directly for the parent SOA. * * DS RRs are signed if the parent is signed, hence also look at the parent SOA */ SET_FOREACH(dt, t->dnssec_transactions, i) { if (dt->key->class != rr->key->class) continue; if (dt->key->type != DNS_TYPE_SOA) continue; if (!parent) { parent = DNS_RESOURCE_KEY_NAME(rr->key); r = dns_name_parent(&parent); if (r < 0) return r; if (r == 0) { if (rr->key->type == DNS_TYPE_DS) return true; /* A CNAME/DNAME without a parent? That's sooo weird. */ log_debug("Transaction %" PRIu16 " claims CNAME/DNAME at root. Refusing.", t->id); return -EBADMSG; } } r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), parent); if (r < 0) return r; if (r == 0) continue; return t->answer_authenticated; } return true; } default: { DnsTransaction *dt; Iterator i; /* Any other kind of RR (including DNSKEY/NSEC/NSEC3). Let's see if our SOA lookup was authenticated */ SET_FOREACH(dt, t->dnssec_transactions, i) { if (dt->key->class != rr->key->class) continue; if (dt->key->type != DNS_TYPE_SOA) continue; r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), DNS_RESOURCE_KEY_NAME(rr->key)); if (r < 0) return r; if (r == 0) continue; /* We found the transaction that was supposed to find * the SOA RR for us. It was successful, but found no * RR for us. This means we are not at a zone cut. In * this case, we require authentication if the SOA * lookup was authenticated too. */ return t->answer_authenticated; } return true; }} } static int dns_transaction_in_private_tld(DnsTransaction *t, const DnsResourceKey *key) { DnsTransaction *dt; const char *tld; Iterator i; int r; /* If DNSSEC downgrade mode is on, checks whether the * specified RR is one level below a TLD we have proven not to * exist. In such a case we assume that this is a private * domain, and permit it. * * This detects cases like the Fritz!Box router networks. Each * Fritz!Box router serves a private "fritz.box" zone, in the * non-existing TLD "box". Requests for the "fritz.box" domain * are served by the router itself, while requests for the * "box" domain will result in NXDOMAIN. * * Note that this logic is unable to detect cases where a * router serves a private DNS zone directly under * non-existing TLD. In such a case we cannot detect whether * the TLD is supposed to exist or not, as all requests we * make for it will be answered by the router's zone, and not * by the root zone. */ assert(t); if (t->scope->dnssec_mode != DNSSEC_ALLOW_DOWNGRADE) return false; /* In strict DNSSEC mode what doesn't exist, doesn't exist */ tld = DNS_RESOURCE_KEY_NAME(key); r = dns_name_parent(&tld); if (r < 0) return r; if (r == 0) return false; /* Already the root domain */ if (!dns_name_is_single_label(tld)) return false; SET_FOREACH(dt, t->dnssec_transactions, i) { if (dt->key->class != key->class) continue; r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), tld); if (r < 0) return r; if (r == 0) continue; /* We found an auxiliary lookup we did for the TLD. If * that returned with NXDOMAIN, we know the TLD didn't * exist, and hence this might be a private zone. */ return dt->answer_rcode == DNS_RCODE_NXDOMAIN; } return false; } static int dns_transaction_requires_nsec(DnsTransaction *t) { DnsTransaction *dt; const char *name; Iterator i; int r; assert(t); /* Checks if we need to insist on NSEC/NSEC3 RRs for proving * this negative reply */ if (t->scope->dnssec_mode == DNSSEC_NO) return false; if (dns_type_is_pseudo(t->key->type)) return -EINVAL; r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(t->key)); if (r < 0) return r; if (r > 0) return false; r = dns_transaction_in_private_tld(t, t->key); if (r < 0) return r; if (r > 0) { /* The lookup is from a TLD that is proven not to * exist, and we are in downgrade mode, hence ignore * that fact that we didn't get any NSEC RRs.*/ log_info("Detected a negative query %s in a private DNS zone, permitting unsigned response.", dns_transaction_key_string(t)); return false; } name = DNS_RESOURCE_KEY_NAME(t->key); if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS, DNS_TYPE_DS)) { /* We got a negative reply for this SOA/NS lookup? If * so, then we are not at a zone apex, and thus should * look at the result of the parent SOA lookup. * * We got a negative reply for this DS lookup? DS RRs * are signed when their parent zone is signed, hence * also check the parent SOA in this case. */ r = dns_name_parent(&name); if (r < 0) return r; if (r == 0) return true; } /* For all other RRs we check the SOA on the same level to see * if it's signed. */ SET_FOREACH(dt, t->dnssec_transactions, i) { if (dt->key->class != t->key->class) continue; if (dt->key->type != DNS_TYPE_SOA) continue; r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), name); if (r < 0) return r; if (r == 0) continue; return dt->answer_authenticated; } /* If in doubt, require NSEC/NSEC3 */ return true; } static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRecord *rr) { DnsResourceRecord *rrsig; bool found = false; int r; /* Checks whether any of the DNSKEYs used for the RRSIGs for * the specified RRset is authenticated (i.e. has a matching * DS RR). */ r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(rr->key)); if (r < 0) return r; if (r > 0) return false; DNS_ANSWER_FOREACH(rrsig, t->answer) { DnsTransaction *dt; Iterator i; r = dnssec_key_match_rrsig(rr->key, rrsig); if (r < 0) return r; if (r == 0) continue; SET_FOREACH(dt, t->dnssec_transactions, i) { if (dt->key->class != rr->key->class) continue; if (dt->key->type == DNS_TYPE_DNSKEY) { r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), rrsig->rrsig.signer); if (r < 0) return r; if (r == 0) continue; /* OK, we found an auxiliary DNSKEY * lookup. If that lookup is * authenticated, report this. */ if (dt->answer_authenticated) return true; found = true; } else if (dt->key->type == DNS_TYPE_DS) { r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dt->key), rrsig->rrsig.signer); if (r < 0) return r; if (r == 0) continue; /* OK, we found an auxiliary DS * lookup. If that lookup is * authenticated and non-zero, we * won! */ if (!dt->answer_authenticated) return false; return dns_answer_match_key(dt->answer, dt->key, NULL); } } } return found ? false : -ENXIO; } static int dns_transaction_known_signed(DnsTransaction *t, DnsResourceRecord *rr) { assert(t); assert(rr); /* We know that the root domain is signed, hence if it appears * not to be signed, there's a problem with the DNS server */ return rr->key->class == DNS_CLASS_IN && dns_name_is_root(DNS_RESOURCE_KEY_NAME(rr->key)); } static int dns_transaction_check_revoked_trust_anchors(DnsTransaction *t) { DnsResourceRecord *rr; int r; assert(t); /* Maybe warn the user that we encountered a revoked DNSKEY * for a key from our trust anchor. Note that we don't care * whether the DNSKEY can be authenticated or not. It's * sufficient if it is self-signed. */ DNS_ANSWER_FOREACH(rr, t->answer) { r = dns_trust_anchor_check_revoked(&t->scope->manager->trust_anchor, rr, t->answer); if (r < 0) return r; } return 0; } static int dns_transaction_invalidate_revoked_keys(DnsTransaction *t) { bool changed; int r; assert(t); /* Removes all DNSKEY/DS objects from t->validated_keys that * our trust anchors database considers revoked. */ do { DnsResourceRecord *rr; changed = false; DNS_ANSWER_FOREACH(rr, t->validated_keys) { r = dns_trust_anchor_is_revoked(&t->scope->manager->trust_anchor, rr); if (r < 0) return r; if (r > 0) { r = dns_answer_remove_by_rr(&t->validated_keys, rr); if (r < 0) return r; assert(r > 0); changed = true; break; } } } while (changed); return 0; } static int dns_transaction_copy_validated(DnsTransaction *t) { DnsTransaction *dt; Iterator i; int r; assert(t); /* Copy all validated RRs from the auxiliary DNSSEC transactions into our set of validated RRs */ SET_FOREACH(dt, t->dnssec_transactions, i) { if (DNS_TRANSACTION_IS_LIVE(dt->state)) continue; if (!dt->answer_authenticated) continue; r = dns_answer_extend(&t->validated_keys, dt->answer); if (r < 0) return r; } return 0; } int dns_transaction_validate_dnssec(DnsTransaction *t) { _cleanup_(dns_answer_unrefp) DnsAnswer *validated = NULL; enum { PHASE_DNSKEY, /* Phase #1, only validate DNSKEYs */ PHASE_NSEC, /* Phase #2, only validate NSEC+NSEC3 */ PHASE_ALL, /* Phase #3, validate everything else */ } phase; DnsResourceRecord *rr; DnsAnswerFlags flags; int r; assert(t); /* We have now collected all DS and DNSKEY RRs in * t->validated_keys, let's see which RRs we can now * authenticate with that. */ if (t->scope->dnssec_mode == DNSSEC_NO) return 0; /* Already validated */ if (t->answer_dnssec_result != _DNSSEC_RESULT_INVALID) return 0; /* Our own stuff needs no validation */ if (IN_SET(t->answer_source, DNS_TRANSACTION_ZONE, DNS_TRANSACTION_TRUST_ANCHOR)) { t->answer_dnssec_result = DNSSEC_VALIDATED; t->answer_authenticated = true; return 0; } /* Cached stuff is not affected by validation. */ if (t->answer_source != DNS_TRANSACTION_NETWORK) return 0; if (!dns_transaction_dnssec_supported_full(t)) { /* The server does not support DNSSEC, or doesn't augment responses with RRSIGs. */ t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER; log_debug("Not validating response for %" PRIu16 ", server lacks DNSSEC support.", t->id); return 0; } log_debug("Validating response from transaction %" PRIu16 " (%s).", t->id, dns_transaction_key_string(t)); /* First, see if this response contains any revoked trust * anchors we care about */ r = dns_transaction_check_revoked_trust_anchors(t); if (r < 0) return r; /* Third, copy all RRs we acquired successfully from auxiliary RRs over. */ r = dns_transaction_copy_validated(t); if (r < 0) return r; /* Second, see if there are DNSKEYs we already know a * validated DS for. */ r = dns_transaction_validate_dnskey_by_ds(t); if (r < 0) return r; /* Fourth, remove all DNSKEY and DS RRs again that our trust * anchor says are revoked. After all we might have marked * some keys revoked above, but they might still be lingering * in our validated_keys list. */ r = dns_transaction_invalidate_revoked_keys(t); if (r < 0) return r; phase = PHASE_DNSKEY; for (;;) { bool changed = false, have_nsec = false; DNS_ANSWER_FOREACH(rr, t->answer) { DnsResourceRecord *rrsig = NULL; DnssecResult result; switch (rr->key->type) { case DNS_TYPE_RRSIG: continue; case DNS_TYPE_DNSKEY: /* We validate DNSKEYs only in the DNSKEY and ALL phases */ if (phase == PHASE_NSEC) continue; break; case DNS_TYPE_NSEC: case DNS_TYPE_NSEC3: have_nsec = true; /* We validate NSEC/NSEC3 only in the NSEC and ALL phases */ if (phase == PHASE_DNSKEY) continue; break; default: /* We validate all other RRs only in the ALL phases */ if (phase != PHASE_ALL) continue; break; } r = dnssec_verify_rrset_search(t->answer, rr->key, t->validated_keys, USEC_INFINITY, &result, &rrsig); if (r < 0) return r; log_debug("Looking at %s: %s", strna(dns_resource_record_to_string(rr)), dnssec_result_to_string(result)); if (result == DNSSEC_VALIDATED) { if (rr->key->type == DNS_TYPE_DNSKEY) { /* If we just validated a * DNSKEY RRset, then let's * add these keys to the set * of validated keys for this * transaction. */ r = dns_answer_copy_by_key(&t->validated_keys, t->answer, rr->key, DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; /* some of the DNSKEYs we just * added might already have * been revoked, remove them * again in that case. */ r = dns_transaction_invalidate_revoked_keys(t); if (r < 0) return r; } /* Add the validated RRset to the new * list of validated RRsets, and * remove it from the unvalidated * RRsets. We mark the RRset as * authenticated and cacheable. */ r = dns_answer_move_by_key(&validated, &t->answer, rr->key, DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE); if (r < 0) return r; manager_dnssec_verdict(t->scope->manager, DNSSEC_SECURE, rr->key); /* Exit the loop, we dropped something from the answer, start from the beginning */ changed = true; break; } /* If we haven't read all DNSKEYs yet a negative result of the validation is irrelevant, as * there might be more DNSKEYs coming. Similar, if we haven't read all NSEC/NSEC3 RRs yet, we * cannot do positive wildcard proofs yet, as those require the NSEC/NSEC3 RRs. */ if (phase != PHASE_ALL) continue; if (result == DNSSEC_VALIDATED_WILDCARD) { bool authenticated = false; const char *source; /* This RRset validated, but as a wildcard. This means we need to prove via NSEC/NSEC3 * that no matching non-wildcard RR exists.*/ /* First step, determine the source of synthesis */ r = dns_resource_record_source(rrsig, &source); if (r < 0) return r; r = dnssec_test_positive_wildcard( validated, DNS_RESOURCE_KEY_NAME(rr->key), source, rrsig->rrsig.signer, &authenticated); /* Unless the NSEC proof showed that the key really doesn't exist something is off. */ if (r == 0) result = DNSSEC_INVALID; else { r = dns_answer_move_by_key(&validated, &t->answer, rr->key, authenticated ? (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE) : 0); if (r < 0) return r; manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, rr->key); /* Exit the loop, we dropped something from the answer, start from the beginning */ changed = true; break; } } if (result == DNSSEC_NO_SIGNATURE) { r = dns_transaction_requires_rrsig(t, rr); if (r < 0) return r; if (r == 0) { /* Data does not require signing. In that case, just copy it over, * but remember that this is by no means authenticated.*/ r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0); if (r < 0) return r; manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key); changed = true; break; } r = dns_transaction_known_signed(t, rr); if (r < 0) return r; if (r > 0) { /* This is an RR we know has to be signed. If it isn't this means * the server is not attaching RRSIGs, hence complain. */ dns_server_packet_rrsig_missing(t->server, t->current_feature_level); if (t->scope->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE) { /* Downgrading is OK? If so, just consider the information unsigned */ r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0); if (r < 0) return r; manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key); changed = true; break; } /* Otherwise, fail */ t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER; return 0; } r = dns_transaction_in_private_tld(t, rr->key); if (r < 0) return r; if (r > 0) { _cleanup_free_ char *s = NULL; /* The data is from a TLD that is proven not to exist, and we are in downgrade * mode, hence ignore the fact that this was not signed. */ (void) dns_resource_key_to_string(rr->key, &s); log_info("Detected RRset %s is in a private DNS zone, permitting unsigned RRs.", strna(s ? strstrip(s) : NULL)); r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0); if (r < 0) return r; manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key); changed = true; break; } } if (IN_SET(result, DNSSEC_MISSING_KEY, DNSSEC_SIGNATURE_EXPIRED, DNSSEC_UNSUPPORTED_ALGORITHM)) { r = dns_transaction_dnskey_authenticated(t, rr); if (r < 0 && r != -ENXIO) return r; if (r == 0) { /* The DNSKEY transaction was not authenticated, this means there's * no DS for this, which means it's OK if no keys are found for this signature. */ r = dns_answer_move_by_key(&validated, &t->answer, rr->key, 0); if (r < 0) return r; manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key); changed = true; break; } } r = dns_transaction_is_primary_response(t, rr); if (r < 0) return r; if (r > 0) { /* Look for a matching DNAME for this CNAME */ r = dns_answer_has_dname_for_cname(t->answer, rr); if (r < 0) return r; if (r == 0) { /* Also look among the stuff we already validated */ r = dns_answer_has_dname_for_cname(validated, rr); if (r < 0) return r; } if (r == 0) { if (IN_SET(result, DNSSEC_INVALID, DNSSEC_SIGNATURE_EXPIRED, DNSSEC_NO_SIGNATURE)) manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, rr->key); else /* DNSSEC_MISSING_KEY or DNSSEC_UNSUPPORTED_ALGORITHM */ manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, rr->key); /* This is a primary response to our question, and it failed validation. That's * fatal. */ t->answer_dnssec_result = result; return 0; } /* This is a primary response, but we do have a DNAME RR in the RR that can replay this * CNAME, hence rely on that, and we can remove the CNAME in favour of it. */ } /* This is just some auxiliary data. Just remove the RRset and continue. */ r = dns_answer_remove_by_key(&t->answer, rr->key); if (r < 0) return r; /* Exit the loop, we dropped something from the answer, start from the beginning */ changed = true; break; } /* Restart the inner loop as long as we managed to achieve something */ if (changed) continue; if (phase == PHASE_DNSKEY && have_nsec) { /* OK, we processed all DNSKEYs, and there are NSEC/NSEC3 RRs, look at those now. */ phase = PHASE_NSEC; continue; } if (phase != PHASE_ALL) { /* OK, we processed all DNSKEYs and NSEC/NSEC3 RRs, look at all the rest now. Note that in this * third phase we start to remove RRs we couldn't validate. */ phase = PHASE_ALL; continue; } /* We're done */ break; } dns_answer_unref(t->answer); t->answer = validated; validated = NULL; /* At this point the answer only contains validated * RRsets. Now, let's see if it actually answers the question * we asked. If so, great! If it doesn't, then see if * NSEC/NSEC3 can prove this. */ r = dns_transaction_has_positive_answer(t, &flags); if (r > 0) { /* Yes, it answers the question! */ if (flags & DNS_ANSWER_AUTHENTICATED) { /* The answer is fully authenticated, yay. */ t->answer_dnssec_result = DNSSEC_VALIDATED; t->answer_rcode = DNS_RCODE_SUCCESS; t->answer_authenticated = true; } else { /* The answer is not fully authenticated. */ t->answer_dnssec_result = DNSSEC_UNSIGNED; t->answer_authenticated = false; } } else if (r == 0) { DnssecNsecResult nr; bool authenticated = false; /* Bummer! Let's check NSEC/NSEC3 */ r = dnssec_nsec_test(t->answer, t->key, &nr, &authenticated, &t->answer_nsec_ttl); if (r < 0) return r; switch (nr) { case DNSSEC_NSEC_NXDOMAIN: /* NSEC proves the domain doesn't exist. Very good. */ log_debug("Proved NXDOMAIN via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t)); t->answer_dnssec_result = DNSSEC_VALIDATED; t->answer_rcode = DNS_RCODE_NXDOMAIN; t->answer_authenticated = authenticated; manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, t->key); break; case DNSSEC_NSEC_NODATA: /* NSEC proves that there's no data here, very good. */ log_debug("Proved NODATA via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t)); t->answer_dnssec_result = DNSSEC_VALIDATED; t->answer_rcode = DNS_RCODE_SUCCESS; t->answer_authenticated = authenticated; manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, t->key); break; case DNSSEC_NSEC_OPTOUT: /* NSEC3 says the data might not be signed */ log_debug("Data is NSEC3 opt-out via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t)); t->answer_dnssec_result = DNSSEC_UNSIGNED; t->answer_authenticated = false; manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, t->key); break; case DNSSEC_NSEC_NO_RR: /* No NSEC data? Bummer! */ r = dns_transaction_requires_nsec(t); if (r < 0) return r; if (r > 0) { t->answer_dnssec_result = DNSSEC_NO_SIGNATURE; manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, t->key); } else { t->answer_dnssec_result = DNSSEC_UNSIGNED; t->answer_authenticated = false; manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, t->key); } break; case DNSSEC_NSEC_UNSUPPORTED_ALGORITHM: /* We don't know the NSEC3 algorithm used? */ t->answer_dnssec_result = DNSSEC_UNSUPPORTED_ALGORITHM; manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, t->key); break; case DNSSEC_NSEC_FOUND: case DNSSEC_NSEC_CNAME: /* NSEC says it needs to be there, but we couldn't find it? Bummer! */ t->answer_dnssec_result = DNSSEC_NSEC_MISMATCH; manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, t->key); break; default: assert_not_reached("Unexpected NSEC result."); } } return 1; } const char *dns_transaction_key_string(DnsTransaction *t) { assert(t); if (!t->key_string) { if (dns_resource_key_to_string(t->key, &t->key_string) < 0) return "n/a"; } return strstrip(t->key_string); } static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = { [DNS_TRANSACTION_NULL] = "null", [DNS_TRANSACTION_PENDING] = "pending", [DNS_TRANSACTION_VALIDATING] = "validating", [DNS_TRANSACTION_RCODE_FAILURE] = "rcode-failure", [DNS_TRANSACTION_SUCCESS] = "success", [DNS_TRANSACTION_NO_SERVERS] = "no-servers", [DNS_TRANSACTION_TIMEOUT] = "timeout", [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached", [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply", [DNS_TRANSACTION_ERRNO] = "errno", [DNS_TRANSACTION_ABORTED] = "aborted", [DNS_TRANSACTION_DNSSEC_FAILED] = "dnssec-failed", [DNS_TRANSACTION_NO_TRUST_ANCHOR] = "no-trust-anchor", [DNS_TRANSACTION_RR_TYPE_UNSUPPORTED] = "rr-type-unsupported", [DNS_TRANSACTION_NETWORK_DOWN] = "network-down", [DNS_TRANSACTION_NOT_FOUND] = "not-found", }; DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState); static const char* const dns_transaction_source_table[_DNS_TRANSACTION_SOURCE_MAX] = { [DNS_TRANSACTION_NETWORK] = "network", [DNS_TRANSACTION_CACHE] = "cache", [DNS_TRANSACTION_ZONE] = "zone", [DNS_TRANSACTION_TRUST_ANCHOR] = "trust-anchor", }; DEFINE_STRING_TABLE_LOOKUP(dns_transaction_source, DnsTransactionSource); systemd-229/src/resolve/resolved-dns-transaction.h000066400000000000000000000144051265713322000224340ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct DnsTransaction DnsTransaction; typedef enum DnsTransactionState DnsTransactionState; typedef enum DnsTransactionSource DnsTransactionSource; enum DnsTransactionState { DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING, DNS_TRANSACTION_RCODE_FAILURE, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_NO_SERVERS, DNS_TRANSACTION_TIMEOUT, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED, DNS_TRANSACTION_INVALID_REPLY, DNS_TRANSACTION_ERRNO, DNS_TRANSACTION_ABORTED, DNS_TRANSACTION_DNSSEC_FAILED, DNS_TRANSACTION_NO_TRUST_ANCHOR, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED, DNS_TRANSACTION_NETWORK_DOWN, DNS_TRANSACTION_NOT_FOUND, /* like NXDOMAIN, but when LLMNR/TCP connections fail */ _DNS_TRANSACTION_STATE_MAX, _DNS_TRANSACTION_STATE_INVALID = -1 }; #define DNS_TRANSACTION_IS_LIVE(state) IN_SET((state), DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING) enum DnsTransactionSource { DNS_TRANSACTION_NETWORK, DNS_TRANSACTION_CACHE, DNS_TRANSACTION_ZONE, DNS_TRANSACTION_TRUST_ANCHOR, _DNS_TRANSACTION_SOURCE_MAX, _DNS_TRANSACTION_SOURCE_INVALID = -1 }; #include "resolved-dns-answer.h" #include "resolved-dns-packet.h" #include "resolved-dns-question.h" #include "resolved-dns-scope.h" struct DnsTransaction { DnsScope *scope; DnsResourceKey *key; char *key_string; DnsTransactionState state; uint16_t id; bool tried_stream:1; bool initial_jitter_scheduled:1; bool initial_jitter_elapsed:1; DnsPacket *sent, *received; DnsAnswer *answer; int answer_rcode; DnssecResult answer_dnssec_result; DnsTransactionSource answer_source; uint32_t answer_nsec_ttl; int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */ /* Indicates whether the primary answer is authenticated, * i.e. whether the RRs from answer which directly match the * question are authenticated, or, if there are none, whether * the NODATA or NXDOMAIN case is. It says nothing about * additional RRs listed in the answer, however they have * their own DNS_ANSWER_AUTHORIZED FLAGS. Note that this bit * is defined different than the AD bit in DNS packets, as * that covers more than just the actual primary answer. */ bool answer_authenticated; /* Contains DNSKEY, DS, SOA RRs we already verified and need * to authenticate this reply */ DnsAnswer *validated_keys; usec_t start_usec; usec_t next_attempt_after; sd_event_source *timeout_event_source; unsigned n_attempts; /* UDP connection logic, if we need it */ int dns_udp_fd; sd_event_source *dns_udp_event_source; /* TCP connection logic, if we need it */ DnsStream *stream; /* The active server */ DnsServer *server; /* The features of the DNS server at time of transaction start */ DnsServerFeatureLevel current_feature_level; /* Query candidates this transaction is referenced by and that * shall be notified about this specific transaction * completing. */ Set *notify_query_candidates; /* Zone items this transaction is referenced by and that shall * be notified about completion. */ Set *notify_zone_items; /* Other transactions that this transactions is referenced by * and that shall be notified about completion. This is used * when transactions want to validate their RRsets, but need * another DNSKEY or DS RR to do so. */ Set *notify_transactions; /* The opposite direction: the transactions this transaction * created in order to request DNSKEY or DS RRs. */ Set *dnssec_transactions; unsigned block_gc; LIST_FIELDS(DnsTransaction, transactions_by_scope); }; int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key); DnsTransaction* dns_transaction_free(DnsTransaction *t); bool dns_transaction_gc(DnsTransaction *t); int dns_transaction_go(DnsTransaction *t); void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p); void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state); void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source); int dns_transaction_validate_dnssec(DnsTransaction *t); int dns_transaction_request_dnssec_keys(DnsTransaction *t); const char *dns_transaction_key_string(DnsTransaction *t); const char* dns_transaction_state_to_string(DnsTransactionState p) _const_; DnsTransactionState dns_transaction_state_from_string(const char *s) _pure_; const char* dns_transaction_source_to_string(DnsTransactionSource p) _const_; DnsTransactionSource dns_transaction_source_from_string(const char *s) _pure_; /* LLMNR Jitter interval, see RFC 4795 Section 7 */ #define LLMNR_JITTER_INTERVAL_USEC (100 * USEC_PER_MSEC) /* mDNS Jitter interval, see RFC 6762 Section 5.2 */ #define MDNS_JITTER_MIN_USEC (20 * USEC_PER_MSEC) #define MDNS_JITTER_RANGE_USEC (100 * USEC_PER_MSEC) /* Maximum attempts to send DNS requests, across all DNS servers */ #define DNS_TRANSACTION_ATTEMPTS_MAX 16 /* Maximum attempts to send LLMNR requests, see RFC 4795 Section 2.7 */ #define LLMNR_TRANSACTION_ATTEMPTS_MAX 3 #define TRANSACTION_ATTEMPTS_MAX(p) ((p) == DNS_PROTOCOL_LLMNR ? LLMNR_TRANSACTION_ATTEMPTS_MAX : DNS_TRANSACTION_ATTEMPTS_MAX) systemd-229/src/resolve/resolved-dns-trust-anchor.c000066400000000000000000000633071265713322000225400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "conf-files.h" #include "def.h" #include "dns-domain.h" #include "fd-util.h" #include "fileio.h" #include "hexdecoct.h" #include "parse-util.h" #include "resolved-dns-trust-anchor.h" #include "resolved-dns-dnssec.h" #include "set.h" #include "string-util.h" #include "strv.h" static const char trust_anchor_dirs[] = CONF_PATHS_NULSTR("dnssec-trust-anchors.d"); /* The DS RR from https://data.iana.org/root-anchors/root-anchors.xml, retrieved December 2015 */ static const uint8_t root_digest[] = { 0x49, 0xAA, 0xC1, 0x1D, 0x7B, 0x6F, 0x64, 0x46, 0x70, 0x2E, 0x54, 0xA1, 0x60, 0x73, 0x71, 0x60, 0x7A, 0x1A, 0x41, 0x85, 0x52, 0x00, 0xFD, 0x2C, 0xE1, 0xCD, 0xDE, 0x32, 0xF2, 0x4E, 0x8F, 0xB5 }; static bool dns_trust_anchor_knows_domain_positive(DnsTrustAnchor *d, const char *name) { assert(d); /* Returns true if there's an entry for the specified domain * name in our trust anchor */ return hashmap_contains(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_DNSKEY, name)) || hashmap_contains(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_DS, name)); } static int dns_trust_anchor_add_builtin_positive(DnsTrustAnchor *d) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; int r; assert(d); r = hashmap_ensure_allocated(&d->positive_by_key, &dns_resource_key_hash_ops); if (r < 0) return r; /* Only add the built-in trust anchor if there's neither a DS * nor a DNSKEY defined for the root domain. That way users * have an easy way to override the root domain DS/DNSKEY * data. */ if (dns_trust_anchor_knows_domain_positive(d, ".")) return 0; /* Add the RR from https://data.iana.org/root-anchors/root-anchors.xml */ rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, ""); if (!rr) return -ENOMEM; rr->ds.key_tag = 19036; rr->ds.algorithm = DNSSEC_ALGORITHM_RSASHA256; rr->ds.digest_type = DNSSEC_DIGEST_SHA256; rr->ds.digest_size = sizeof(root_digest); rr->ds.digest = memdup(root_digest, rr->ds.digest_size); if (!rr->ds.digest) return -ENOMEM; answer = dns_answer_new(1); if (!answer) return -ENOMEM; r = dns_answer_add(answer, rr, 0, DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; r = hashmap_put(d->positive_by_key, rr->key, answer); if (r < 0) return r; answer = NULL; return 0; } static int dns_trust_anchor_add_builtin_negative(DnsTrustAnchor *d) { static const char private_domains[] = /* RFC 6761 says that .test is a special domain for * testing and not to be installed in the root zone */ "test\0" /* RFC 6761 says that these reverse IP lookup ranges * are for private addresses, and hence should not * show up in the root zone */ "10.in-addr.arpa\0" "16.172.in-addr.arpa\0" "17.172.in-addr.arpa\0" "18.172.in-addr.arpa\0" "19.172.in-addr.arpa\0" "20.172.in-addr.arpa\0" "21.172.in-addr.arpa\0" "22.172.in-addr.arpa\0" "23.172.in-addr.arpa\0" "24.172.in-addr.arpa\0" "25.172.in-addr.arpa\0" "26.172.in-addr.arpa\0" "27.172.in-addr.arpa\0" "28.172.in-addr.arpa\0" "29.172.in-addr.arpa\0" "30.172.in-addr.arpa\0" "31.172.in-addr.arpa\0" "168.192.in-addr.arpa\0" /* RFC 6762 reserves the .local domain for Multicast * DNS, it hence cannot appear in the root zone. (Note * that we by default do not route .local traffic to * DNS anyway, except when a configured search domain * suggests so.) */ "local\0" /* These two are well known, popular private zone * TLDs, that are blocked from delegation, according * to: * http://icannwiki.com/Name_Collision#NGPC_Resolution * * There's also ongoing work on making this official * in an RRC: * https://www.ietf.org/archive/id/draft-chapin-additional-reserved-tlds-02.txt */ "home\0" "corp\0" /* The following four TLDs are suggested for private * zones in RFC 6762, Appendix G, and are hence very * unlikely to be made official TLDs any day soon */ "lan\0" "intranet\0" "internal\0" "private\0"; const char *name; int r; assert(d); /* Only add the built-in trust anchor if there's no negative * trust anchor defined at all. This enables easy overriding * of negative trust anchors. */ if (set_size(d->negative_by_name) > 0) return 0; r = set_ensure_allocated(&d->negative_by_name, &dns_name_hash_ops); if (r < 0) return r; /* We add a couple of domains as default negative trust * anchors, where it's very unlikely they will be installed in * the root zone. If they exist they must be private, and thus * unsigned. */ NULSTR_FOREACH(name, private_domains) { if (dns_trust_anchor_knows_domain_positive(d, name)) continue; r = set_put_strdup(d->negative_by_name, name); if (r < 0) return r; } return 0; } static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, unsigned line, const char *s) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; _cleanup_free_ char *domain = NULL, *class = NULL, *type = NULL; _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; DnsAnswer *old_answer = NULL; const char *p = s; int r; assert(d); assert(line); r = extract_first_word(&p, &domain, NULL, EXTRACT_QUOTES); if (r < 0) return log_warning_errno(r, "Unable to parse domain in line %s:%u: %m", path, line); if (!dns_name_is_valid(domain)) { log_warning("Domain name %s is invalid, at line %s:%u, ignoring line.", domain, path, line); return -EINVAL; } r = extract_many_words(&p, NULL, 0, &class, &type, NULL); if (r < 0) return log_warning_errno(r, "Unable to parse class and type in line %s:%u: %m", path, line); if (r != 2) { log_warning("Missing class or type in line %s:%u", path, line); return -EINVAL; } if (!strcaseeq(class, "IN")) { log_warning("RR class %s is not supported, ignoring line %s:%u.", class, path, line); return -EINVAL; } if (strcaseeq(type, "DS")) { _cleanup_free_ char *key_tag = NULL, *algorithm = NULL, *digest_type = NULL, *digest = NULL; _cleanup_free_ void *dd = NULL; uint16_t kt; int a, dt; size_t l; r = extract_many_words(&p, NULL, 0, &key_tag, &algorithm, &digest_type, &digest, NULL); if (r < 0) { log_warning_errno(r, "Failed to parse DS parameters on line %s:%u: %m", path, line); return -EINVAL; } if (r != 4) { log_warning("Missing DS parameters on line %s:%u", path, line); return -EINVAL; } r = safe_atou16(key_tag, &kt); if (r < 0) return log_warning_errno(r, "Failed to parse DS key tag %s on line %s:%u: %m", key_tag, path, line); a = dnssec_algorithm_from_string(algorithm); if (a < 0) { log_warning("Failed to parse DS algorithm %s on line %s:%u", algorithm, path, line); return -EINVAL; } dt = dnssec_digest_from_string(digest_type); if (dt < 0) { log_warning("Failed to parse DS digest type %s on line %s:%u", digest_type, path, line); return -EINVAL; } r = unhexmem(digest, strlen(digest), &dd, &l); if (r < 0) { log_warning("Failed to parse DS digest %s on line %s:%u", digest, path, line); return -EINVAL; } rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, domain); if (!rr) return log_oom(); rr->ds.key_tag = kt; rr->ds.algorithm = a; rr->ds.digest_type = dt; rr->ds.digest_size = l; rr->ds.digest = dd; dd = NULL; } else if (strcaseeq(type, "DNSKEY")) { _cleanup_free_ char *flags = NULL, *protocol = NULL, *algorithm = NULL, *key = NULL; _cleanup_free_ void *k = NULL; uint16_t f; size_t l; int a; r = extract_many_words(&p, NULL, 0, &flags, &protocol, &algorithm, &key, NULL); if (r < 0) return log_warning_errno(r, "Failed to parse DNSKEY parameters on line %s:%u: %m", path, line); if (r != 4) { log_warning("Missing DNSKEY parameters on line %s:%u", path, line); return -EINVAL; } if (!streq(protocol, "3")) { log_warning("DNSKEY Protocol is not 3 on line %s:%u", path, line); return -EINVAL; } r = safe_atou16(flags, &f); if (r < 0) return log_warning_errno(r, "Failed to parse DNSKEY flags field %s on line %s:%u", flags, path, line); if ((f & DNSKEY_FLAG_ZONE_KEY) == 0) { log_warning("DNSKEY lacks zone key bit set on line %s:%u", path, line); return -EINVAL; } if ((f & DNSKEY_FLAG_REVOKE)) { log_warning("DNSKEY is already revoked on line %s:%u", path, line); return -EINVAL; } a = dnssec_algorithm_from_string(algorithm); if (a < 0) { log_warning("Failed to parse DNSKEY algorithm %s on line %s:%u", algorithm, path, line); return -EINVAL; } r = unbase64mem(key, strlen(key), &k, &l); if (r < 0) return log_warning_errno(r, "Failed to parse DNSKEY key data %s on line %s:%u", key, path, line); rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, domain); if (!rr) return log_oom(); rr->dnskey.flags = f; rr->dnskey.protocol = 3; rr->dnskey.algorithm = a; rr->dnskey.key_size = l; rr->dnskey.key = k; k = NULL; } else { log_warning("RR type %s is not supported, ignoring line %s:%u.", type, path, line); return -EINVAL; } if (!isempty(p)) { log_warning("Trailing garbage on line %s:%u, ignoring line.", path, line); return -EINVAL; } r = hashmap_ensure_allocated(&d->positive_by_key, &dns_resource_key_hash_ops); if (r < 0) return log_oom(); old_answer = hashmap_get(d->positive_by_key, rr->key); answer = dns_answer_ref(old_answer); r = dns_answer_add_extend(&answer, rr, 0, DNS_ANSWER_AUTHENTICATED); if (r < 0) return log_error_errno(r, "Failed to add trust anchor RR: %m"); r = hashmap_replace(d->positive_by_key, rr->key, answer); if (r < 0) return log_error_errno(r, "Failed to add answer to trust anchor: %m"); old_answer = dns_answer_unref(old_answer); answer = NULL; return 0; } static int dns_trust_anchor_load_negative(DnsTrustAnchor *d, const char *path, unsigned line, const char *s) { _cleanup_free_ char *domain = NULL; const char *p = s; int r; assert(d); assert(line); r = extract_first_word(&p, &domain, NULL, EXTRACT_QUOTES); if (r < 0) return log_warning_errno(r, "Unable to parse line %s:%u: %m", path, line); if (!dns_name_is_valid(domain)) { log_warning("Domain name %s is invalid, at line %s:%u, ignoring line.", domain, path, line); return -EINVAL; } if (!isempty(p)) { log_warning("Trailing garbage at line %s:%u, ignoring line.", path, line); return -EINVAL; } r = set_ensure_allocated(&d->negative_by_name, &dns_name_hash_ops); if (r < 0) return log_oom(); r = set_put(d->negative_by_name, domain); if (r < 0) return log_oom(); if (r > 0) domain = NULL; return 0; } static int dns_trust_anchor_load_files( DnsTrustAnchor *d, const char *suffix, int (*loader)(DnsTrustAnchor *d, const char *path, unsigned n, const char *line)) { _cleanup_strv_free_ char **files = NULL; char **f; int r; assert(d); assert(suffix); assert(loader); r = conf_files_list_nulstr(&files, suffix, NULL, trust_anchor_dirs); if (r < 0) return log_error_errno(r, "Failed to enumerate %s trust anchor files: %m", suffix); STRV_FOREACH(f, files) { _cleanup_fclose_ FILE *g = NULL; char line[LINE_MAX]; unsigned n = 0; g = fopen(*f, "r"); if (!g) { if (errno == ENOENT) continue; log_warning_errno(errno, "Failed to open %s: %m", *f); continue; } FOREACH_LINE(line, g, log_warning_errno(errno, "Failed to read %s, ignoring: %m", *f)) { char *l; n++; l = strstrip(line); if (isempty(l)) continue; if (*l == ';') continue; (void) loader(d, *f, n, l); } } return 0; } static int domain_name_cmp(const void *a, const void *b) { char **x = (char**) a, **y = (char**) b; return dns_name_compare_func(*x, *y); } static int dns_trust_anchor_dump(DnsTrustAnchor *d) { DnsAnswer *a; Iterator i; assert(d); if (hashmap_isempty(d->positive_by_key)) log_info("No positive trust anchors defined."); else { log_info("Positive Trust Anchors:"); HASHMAP_FOREACH(a, d->positive_by_key, i) { DnsResourceRecord *rr; DNS_ANSWER_FOREACH(rr, a) log_info("%s", dns_resource_record_to_string(rr)); } } if (set_isempty(d->negative_by_name)) log_info("No negative trust anchors defined."); else { _cleanup_free_ char **l = NULL, *j = NULL; l = set_get_strv(d->negative_by_name); if (!l) return log_oom(); qsort_safe(l, set_size(d->negative_by_name), sizeof(char*), domain_name_cmp); j = strv_join(l, " "); if (!j) return log_oom(); log_info("Negative trust anchors: %s", j); } return 0; } int dns_trust_anchor_load(DnsTrustAnchor *d) { int r; assert(d); /* If loading things from disk fails, we don't consider this fatal */ (void) dns_trust_anchor_load_files(d, ".positive", dns_trust_anchor_load_positive); (void) dns_trust_anchor_load_files(d, ".negative", dns_trust_anchor_load_negative); /* However, if the built-in DS fails, then we have a problem. */ r = dns_trust_anchor_add_builtin_positive(d); if (r < 0) return log_error_errno(r, "Failed to add built-in positive trust anchor: %m"); r = dns_trust_anchor_add_builtin_negative(d); if (r < 0) return log_error_errno(r, "Failed to add built-in negative trust anchor: %m"); dns_trust_anchor_dump(d); return 0; } void dns_trust_anchor_flush(DnsTrustAnchor *d) { DnsAnswer *a; DnsResourceRecord *rr; assert(d); while ((a = hashmap_steal_first(d->positive_by_key))) dns_answer_unref(a); d->positive_by_key = hashmap_free(d->positive_by_key); while ((rr = set_steal_first(d->revoked_by_rr))) dns_resource_record_unref(rr); d->revoked_by_rr = set_free(d->revoked_by_rr); d->negative_by_name = set_free_free(d->negative_by_name); } int dns_trust_anchor_lookup_positive(DnsTrustAnchor *d, const DnsResourceKey *key, DnsAnswer **ret) { DnsAnswer *a; assert(d); assert(key); assert(ret); /* We only serve DS and DNSKEY RRs. */ if (!IN_SET(key->type, DNS_TYPE_DS, DNS_TYPE_DNSKEY)) return 0; a = hashmap_get(d->positive_by_key, key); if (!a) return 0; *ret = dns_answer_ref(a); return 1; } int dns_trust_anchor_lookup_negative(DnsTrustAnchor *d, const char *name) { assert(d); assert(name); return set_contains(d->negative_by_name, name); } static int dns_trust_anchor_revoked_put(DnsTrustAnchor *d, DnsResourceRecord *rr) { int r; assert(d); r = set_ensure_allocated(&d->revoked_by_rr, &dns_resource_record_hash_ops); if (r < 0) return r; r = set_put(d->revoked_by_rr, rr); if (r < 0) return r; if (r > 0) dns_resource_record_ref(rr); return r; } static int dns_trust_anchor_remove_revoked(DnsTrustAnchor *d, DnsResourceRecord *rr) { _cleanup_(dns_answer_unrefp) DnsAnswer *new_answer = NULL; DnsAnswer *old_answer; int r; /* Remember that this is a revoked trust anchor RR */ r = dns_trust_anchor_revoked_put(d, rr); if (r < 0) return r; /* Remove this from the positive trust anchor */ old_answer = hashmap_get(d->positive_by_key, rr->key); if (!old_answer) return 0; new_answer = dns_answer_ref(old_answer); r = dns_answer_remove_by_rr(&new_answer, rr); if (r <= 0) return r; /* We found the key! Warn the user */ log_struct(LOG_WARNING, LOG_MESSAGE_ID(SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED), LOG_MESSAGE("DNSSEC Trust anchor %s has been revoked. Please update the trust anchor, or upgrade your operating system."), strna(dns_resource_record_to_string(rr)), "TRUST_ANCHOR=%s", dns_resource_record_to_string(rr), NULL); if (dns_answer_size(new_answer) <= 0) { assert_se(hashmap_remove(d->positive_by_key, rr->key) == old_answer); dns_answer_unref(old_answer); return 1; } r = hashmap_replace(d->positive_by_key, new_answer->items[0].rr->key, new_answer); if (r < 0) return r; new_answer = NULL; dns_answer_unref(old_answer); return 1; } static int dns_trust_anchor_check_revoked_one(DnsTrustAnchor *d, DnsResourceRecord *revoked_dnskey) { DnsAnswer *a; int r; assert(d); assert(revoked_dnskey); assert(revoked_dnskey->key->type == DNS_TYPE_DNSKEY); assert(revoked_dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE); a = hashmap_get(d->positive_by_key, revoked_dnskey->key); if (a) { DnsResourceRecord *anchor; /* First, look for the precise DNSKEY in our trust anchor database */ DNS_ANSWER_FOREACH(anchor, a) { if (anchor->dnskey.protocol != revoked_dnskey->dnskey.protocol) continue; if (anchor->dnskey.algorithm != revoked_dnskey->dnskey.algorithm) continue; if (anchor->dnskey.key_size != revoked_dnskey->dnskey.key_size) continue; /* Note that we allow the REVOKE bit to be * different! It will be set in the revoked * key, but unset in our version of it */ if (((anchor->dnskey.flags ^ revoked_dnskey->dnskey.flags) | DNSKEY_FLAG_REVOKE) != DNSKEY_FLAG_REVOKE) continue; if (memcmp(anchor->dnskey.key, revoked_dnskey->dnskey.key, anchor->dnskey.key_size) != 0) continue; dns_trust_anchor_remove_revoked(d, anchor); break; } } a = hashmap_get(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(revoked_dnskey->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(revoked_dnskey->key))); if (a) { DnsResourceRecord *anchor; /* Second, look for DS RRs matching this DNSKEY in our trust anchor database */ DNS_ANSWER_FOREACH(anchor, a) { /* We set mask_revoke to true here, since our * DS fingerprint will be the one of the * unrevoked DNSKEY, but the one we got passed * here has the bit set. */ r = dnssec_verify_dnskey_by_ds(revoked_dnskey, anchor, true); if (r < 0) return r; if (r == 0) continue; dns_trust_anchor_remove_revoked(d, anchor); break; } } return 0; } int dns_trust_anchor_check_revoked(DnsTrustAnchor *d, DnsResourceRecord *dnskey, DnsAnswer *rrs) { DnsResourceRecord *rrsig; int r; assert(d); assert(dnskey); /* Looks if "dnskey" is a self-signed RR that has been revoked * and matches one of our trust anchor entries. If so, removes * it from the trust anchor and returns > 0. */ if (dnskey->key->type != DNS_TYPE_DNSKEY) return 0; /* Is this DNSKEY revoked? */ if ((dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE) == 0) return 0; /* Could this be interesting to us at all? If not, * there's no point in looking for and verifying a * self-signed RRSIG. */ if (!dns_trust_anchor_knows_domain_positive(d, DNS_RESOURCE_KEY_NAME(dnskey->key))) return 0; /* Look for a self-signed RRSIG in the other rrs belonging to this DNSKEY */ DNS_ANSWER_FOREACH(rrsig, rrs) { DnssecResult result; if (rrsig->key->type != DNS_TYPE_RRSIG) continue; r = dnssec_rrsig_match_dnskey(rrsig, dnskey, true); if (r < 0) return r; if (r == 0) continue; r = dnssec_verify_rrset(rrs, dnskey->key, rrsig, dnskey, USEC_INFINITY, &result); if (r < 0) return r; if (result != DNSSEC_VALIDATED) continue; /* Bingo! This is a revoked self-signed DNSKEY. Let's * see if this precise one exists in our trust anchor * database, too. */ r = dns_trust_anchor_check_revoked_one(d, dnskey); if (r < 0) return r; return 1; } return 0; } int dns_trust_anchor_is_revoked(DnsTrustAnchor *d, DnsResourceRecord *rr) { assert(d); if (!IN_SET(rr->key->type, DNS_TYPE_DS, DNS_TYPE_DNSKEY)) return 0; return set_contains(d->revoked_by_rr, rr); } systemd-229/src/resolve/resolved-dns-trust-anchor.h000066400000000000000000000027551265713322000225450ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef struct DnsTrustAnchor DnsTrustAnchor; #include "hashmap.h" #include "resolved-dns-answer.h" #include "resolved-dns-rr.h" /* This contains a fixed database mapping domain names to DS or DNSKEY records. */ struct DnsTrustAnchor { Hashmap *positive_by_key; Set *negative_by_name; Set *revoked_by_rr; }; int dns_trust_anchor_load(DnsTrustAnchor *d); void dns_trust_anchor_flush(DnsTrustAnchor *d); int dns_trust_anchor_lookup_positive(DnsTrustAnchor *d, const DnsResourceKey* key, DnsAnswer **answer); int dns_trust_anchor_lookup_negative(DnsTrustAnchor *d, const char *name); int dns_trust_anchor_check_revoked(DnsTrustAnchor *d, DnsResourceRecord *dnskey, DnsAnswer *rrs); int dns_trust_anchor_is_revoked(DnsTrustAnchor *d, DnsResourceRecord *rr); systemd-229/src/resolve/resolved-dns-zone.c000066400000000000000000000470741265713322000210650ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "dns-domain.h" #include "list.h" #include "resolved-dns-packet.h" #include "resolved-dns-zone.h" #include "string-util.h" /* Never allow more than 1K entries */ #define ZONE_MAX 1024 void dns_zone_item_probe_stop(DnsZoneItem *i) { DnsTransaction *t; assert(i); if (!i->probe_transaction) return; t = i->probe_transaction; i->probe_transaction = NULL; set_remove(t->notify_zone_items, i); dns_transaction_gc(t); } static void dns_zone_item_free(DnsZoneItem *i) { if (!i) return; dns_zone_item_probe_stop(i); dns_resource_record_unref(i->rr); free(i); } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsZoneItem*, dns_zone_item_free); static void dns_zone_item_remove_and_free(DnsZone *z, DnsZoneItem *i) { DnsZoneItem *first; assert(z); if (!i) return; first = hashmap_get(z->by_key, i->rr->key); LIST_REMOVE(by_key, first, i); if (first) assert_se(hashmap_replace(z->by_key, first->rr->key, first) >= 0); else hashmap_remove(z->by_key, i->rr->key); first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(i->rr->key)); LIST_REMOVE(by_name, first, i); if (first) assert_se(hashmap_replace(z->by_name, DNS_RESOURCE_KEY_NAME(first->rr->key), first) >= 0); else hashmap_remove(z->by_name, DNS_RESOURCE_KEY_NAME(i->rr->key)); dns_zone_item_free(i); } void dns_zone_flush(DnsZone *z) { DnsZoneItem *i; assert(z); while ((i = hashmap_first(z->by_key))) dns_zone_item_remove_and_free(z, i); assert(hashmap_size(z->by_key) == 0); assert(hashmap_size(z->by_name) == 0); z->by_key = hashmap_free(z->by_key); z->by_name = hashmap_free(z->by_name); } static DnsZoneItem* dns_zone_get(DnsZone *z, DnsResourceRecord *rr) { DnsZoneItem *i; assert(z); assert(rr); LIST_FOREACH(by_key, i, hashmap_get(z->by_key, rr->key)) if (dns_resource_record_equal(i->rr, rr) > 0) return i; return NULL; } void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr) { DnsZoneItem *i; assert(z); assert(rr); i = dns_zone_get(z, rr); if (i) dns_zone_item_remove_and_free(z, i); } static int dns_zone_init(DnsZone *z) { int r; assert(z); r = hashmap_ensure_allocated(&z->by_key, &dns_resource_key_hash_ops); if (r < 0) return r; r = hashmap_ensure_allocated(&z->by_name, &dns_name_hash_ops); if (r < 0) return r; return 0; } static int dns_zone_link_item(DnsZone *z, DnsZoneItem *i) { DnsZoneItem *first; int r; first = hashmap_get(z->by_key, i->rr->key); if (first) { LIST_PREPEND(by_key, first, i); assert_se(hashmap_replace(z->by_key, first->rr->key, first) >= 0); } else { r = hashmap_put(z->by_key, i->rr->key, i); if (r < 0) return r; } first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(i->rr->key)); if (first) { LIST_PREPEND(by_name, first, i); assert_se(hashmap_replace(z->by_name, DNS_RESOURCE_KEY_NAME(first->rr->key), first) >= 0); } else { r = hashmap_put(z->by_name, DNS_RESOURCE_KEY_NAME(i->rr->key), i); if (r < 0) return r; } return 0; } static int dns_zone_item_probe_start(DnsZoneItem *i) { DnsTransaction *t; int r; assert(i); if (i->probe_transaction) return 0; t = dns_scope_find_transaction(i->scope, &DNS_RESOURCE_KEY_CONST(i->rr->key->class, DNS_TYPE_ANY, DNS_RESOURCE_KEY_NAME(i->rr->key)), false); if (!t) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; key = dns_resource_key_new(i->rr->key->class, DNS_TYPE_ANY, DNS_RESOURCE_KEY_NAME(i->rr->key)); if (!key) return -ENOMEM; r = dns_transaction_new(&t, i->scope, key); if (r < 0) return r; } r = set_ensure_allocated(&t->notify_zone_items, NULL); if (r < 0) goto gc; r = set_put(t->notify_zone_items, i); if (r < 0) goto gc; i->probe_transaction = t; if (t->state == DNS_TRANSACTION_NULL) { i->block_ready++; r = dns_transaction_go(t); i->block_ready--; if (r < 0) { dns_zone_item_probe_stop(i); return r; } } dns_zone_item_notify(i); return 0; gc: dns_transaction_gc(t); return r; } int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe) { _cleanup_(dns_zone_item_freep) DnsZoneItem *i = NULL; DnsZoneItem *existing; int r; assert(z); assert(s); assert(rr); if (dns_class_is_pseudo(rr->key->class)) return -EINVAL; if (dns_type_is_pseudo(rr->key->type)) return -EINVAL; existing = dns_zone_get(z, rr); if (existing) return 0; r = dns_zone_init(z); if (r < 0) return r; i = new0(DnsZoneItem, 1); if (!i) return -ENOMEM; i->scope = s; i->rr = dns_resource_record_ref(rr); i->probing_enabled = probe; r = dns_zone_link_item(z, i); if (r < 0) return r; if (probe) { DnsZoneItem *first, *j; bool established = false; /* Check if there's already an RR with the same name * established. If so, it has been probed already, and * we don't ned to probe again. */ LIST_FIND_HEAD(by_name, i, first); LIST_FOREACH(by_name, j, first) { if (i == j) continue; if (j->state == DNS_ZONE_ITEM_ESTABLISHED) established = true; } if (established) i->state = DNS_ZONE_ITEM_ESTABLISHED; else { i->state = DNS_ZONE_ITEM_PROBING; r = dns_zone_item_probe_start(i); if (r < 0) { dns_zone_item_remove_and_free(z, i); i = NULL; return r; } } } else i->state = DNS_ZONE_ITEM_ESTABLISHED; i = NULL; return 0; } int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) { _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL; unsigned n_answer = 0; DnsZoneItem *j, *first; bool tentative = true, need_soa = false; int r; assert(z); assert(key); assert(ret_answer); /* First iteration, count what we have */ if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) { bool found = false, added = false; int k; /* If this is a generic match, then we have to * go through the list by the name and look * for everything manually */ first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key)); LIST_FOREACH(by_name, j, first) { if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) continue; found = true; k = dns_resource_key_match_rr(key, j->rr, NULL); if (k < 0) return k; if (k > 0) { n_answer++; added = true; } } if (found && !added) need_soa = true; } else { bool found = false; /* If this is a specific match, then look for * the right key immediately */ first = hashmap_get(z->by_key, key); LIST_FOREACH(by_key, j, first) { if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) continue; found = true; n_answer++; } if (!found) { first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key)); LIST_FOREACH(by_name, j, first) { if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) continue; need_soa = true; break; } } } if (n_answer <= 0 && !need_soa) goto return_empty; if (n_answer > 0) { answer = dns_answer_new(n_answer); if (!answer) return -ENOMEM; } if (need_soa) { soa = dns_answer_new(1); if (!soa) return -ENOMEM; } /* Second iteration, actually add the RRs to the answers */ if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) { bool found = false, added = false; int k; first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key)); LIST_FOREACH(by_name, j, first) { if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) continue; found = true; if (j->state != DNS_ZONE_ITEM_PROBING) tentative = false; k = dns_resource_key_match_rr(key, j->rr, NULL); if (k < 0) return k; if (k > 0) { r = dns_answer_add(answer, j->rr, 0, DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; added = true; } } if (found && !added) { r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(key), LLMNR_DEFAULT_TTL); if (r < 0) return r; } } else { bool found = false; first = hashmap_get(z->by_key, key); LIST_FOREACH(by_key, j, first) { if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) continue; found = true; if (j->state != DNS_ZONE_ITEM_PROBING) tentative = false; r = dns_answer_add(answer, j->rr, 0, DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; } if (!found) { bool add_soa = false; first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key)); LIST_FOREACH(by_name, j, first) { if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) continue; if (j->state != DNS_ZONE_ITEM_PROBING) tentative = false; add_soa = true; } if (add_soa) { r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(key), LLMNR_DEFAULT_TTL); if (r < 0) return r; } } } /* If the caller sets ret_tentative to NULL, then use this as * indication to not return tentative entries */ if (!ret_tentative && tentative) goto return_empty; *ret_answer = answer; answer = NULL; if (ret_soa) { *ret_soa = soa; soa = NULL; } if (ret_tentative) *ret_tentative = tentative; return 1; return_empty: *ret_answer = NULL; if (ret_soa) *ret_soa = NULL; if (ret_tentative) *ret_tentative = false; return 0; } void dns_zone_item_conflict(DnsZoneItem *i) { assert(i); if (!IN_SET(i->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_VERIFYING, DNS_ZONE_ITEM_ESTABLISHED)) return; log_info("Detected conflict on %s", strna(dns_resource_record_to_string(i->rr))); dns_zone_item_probe_stop(i); /* Withdraw the conflict item */ i->state = DNS_ZONE_ITEM_WITHDRAWN; /* Maybe change the hostname */ if (manager_is_own_hostname(i->scope->manager, DNS_RESOURCE_KEY_NAME(i->rr->key)) > 0) manager_next_hostname(i->scope->manager); } void dns_zone_item_notify(DnsZoneItem *i) { assert(i); assert(i->probe_transaction); if (i->block_ready > 0) return; if (IN_SET(i->probe_transaction->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING)) return; if (i->probe_transaction->state == DNS_TRANSACTION_SUCCESS) { bool we_lost = false; /* The probe got a successful reply. If we so far * weren't established we just give up. If we already * were established, and the peer has the * lexicographically larger IP address we continue * and defend it. */ if (!IN_SET(i->state, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) { log_debug("Got a successful probe for not yet established RR, we lost."); we_lost = true; } else { assert(i->probe_transaction->received); we_lost = memcmp(&i->probe_transaction->received->sender, &i->probe_transaction->received->destination, FAMILY_ADDRESS_SIZE(i->probe_transaction->received->family)) < 0; if (we_lost) log_debug("Got a successful probe reply for an established RR, and we have a lexicographically larger IP address and thus lost."); } if (we_lost) { dns_zone_item_conflict(i); return; } log_debug("Got a successful probe reply, but peer has lexicographically lower IP address and thus lost."); } log_debug("Record %s successfully probed.", strna(dns_resource_record_to_string(i->rr))); dns_zone_item_probe_stop(i); i->state = DNS_ZONE_ITEM_ESTABLISHED; } static int dns_zone_item_verify(DnsZoneItem *i) { int r; assert(i); if (i->state != DNS_ZONE_ITEM_ESTABLISHED) return 0; log_debug("Verifying RR %s", strna(dns_resource_record_to_string(i->rr))); i->state = DNS_ZONE_ITEM_VERIFYING; r = dns_zone_item_probe_start(i); if (r < 0) { log_error_errno(r, "Failed to start probing for verifying RR: %m"); i->state = DNS_ZONE_ITEM_ESTABLISHED; return r; } return 0; } int dns_zone_check_conflicts(DnsZone *zone, DnsResourceRecord *rr) { DnsZoneItem *i, *first; int c = 0; assert(zone); assert(rr); /* This checks whether a response RR we received from somebody * else is one that we actually thought was uniquely ours. If * so, we'll verify our RRs. */ /* No conflict if we don't have the name at all. */ first = hashmap_get(zone->by_name, DNS_RESOURCE_KEY_NAME(rr->key)); if (!first) return 0; /* No conflict if we have the exact same RR */ if (dns_zone_get(zone, rr)) return 0; /* OK, somebody else has RRs for the same name. Yuck! Let's * start probing again */ LIST_FOREACH(by_name, i, first) { if (dns_resource_record_equal(i->rr, rr)) continue; dns_zone_item_verify(i); c++; } return c; } int dns_zone_verify_conflicts(DnsZone *zone, DnsResourceKey *key) { DnsZoneItem *i, *first; int c = 0; assert(zone); /* Somebody else notified us about a possible conflict. Let's * verify if that's true. */ first = hashmap_get(zone->by_name, DNS_RESOURCE_KEY_NAME(key)); if (!first) return 0; LIST_FOREACH(by_name, i, first) { dns_zone_item_verify(i); c++; } return c; } void dns_zone_verify_all(DnsZone *zone) { DnsZoneItem *i; Iterator iterator; assert(zone); HASHMAP_FOREACH(i, zone->by_key, iterator) { DnsZoneItem *j; LIST_FOREACH(by_key, j, i) dns_zone_item_verify(j); } } void dns_zone_dump(DnsZone *zone, FILE *f) { Iterator iterator; DnsZoneItem *i; if (!zone) return; if (!f) f = stdout; HASHMAP_FOREACH(i, zone->by_key, iterator) { DnsZoneItem *j; LIST_FOREACH(by_key, j, i) { const char *t; t = dns_resource_record_to_string(j->rr); if (!t) { log_oom(); continue; } fputc('\t', f); fputs(t, f); fputc('\n', f); } } } bool dns_zone_is_empty(DnsZone *zone) { if (!zone) return true; return hashmap_isempty(zone->by_key); } systemd-229/src/resolve/resolved-dns-zone.h000066400000000000000000000044031265713322000210570ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "hashmap.h" typedef struct DnsZone { Hashmap *by_key; Hashmap *by_name; } DnsZone; typedef struct DnsZoneItem DnsZoneItem; typedef enum DnsZoneItemState DnsZoneItemState; #include "resolved-dns-answer.h" #include "resolved-dns-question.h" #include "resolved-dns-rr.h" #include "resolved-dns-transaction.h" /* RFC 4795 Section 2.8. suggests a TTL of 30s by default */ #define LLMNR_DEFAULT_TTL (30) enum DnsZoneItemState { DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING, DNS_ZONE_ITEM_WITHDRAWN, }; struct DnsZoneItem { DnsScope *scope; DnsResourceRecord *rr; DnsZoneItemState state; unsigned block_ready; bool probing_enabled; LIST_FIELDS(DnsZoneItem, by_key); LIST_FIELDS(DnsZoneItem, by_name); DnsTransaction *probe_transaction; }; void dns_zone_flush(DnsZone *z); int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe); void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr); int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **answer, DnsAnswer **soa, bool *tentative); void dns_zone_item_conflict(DnsZoneItem *i); void dns_zone_item_notify(DnsZoneItem *i); int dns_zone_check_conflicts(DnsZone *zone, DnsResourceRecord *rr); int dns_zone_verify_conflicts(DnsZone *zone, DnsResourceKey *key); void dns_zone_verify_all(DnsZone *zone); void dns_zone_item_probe_stop(DnsZoneItem *i); void dns_zone_dump(DnsZone *zone, FILE *f); bool dns_zone_is_empty(DnsZone *zone); systemd-229/src/resolve/resolved-etc-hosts.c000066400000000000000000000345311265713322000212330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2016 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "fd-util.h" #include "fileio.h" #include "hostname-util.h" #include "resolved-etc-hosts.h" #include "resolved-dns-synthesize.h" #include "string-util.h" #include "strv.h" #include "time-util.h" /* Recheck /etc/hosts at most once every 2s */ #define ETC_HOSTS_RECHECK_USEC (2*USEC_PER_SEC) typedef struct EtcHostsItem { int family; union in_addr_union address; char **names; } EtcHostsItem; typedef struct EtcHostsItemByName { char *name; EtcHostsItem **items; size_t n_items, n_allocated; } EtcHostsItemByName; void manager_etc_hosts_flush(Manager *m) { EtcHostsItem *item; EtcHostsItemByName *bn; while ((item = set_steal_first(m->etc_hosts_by_address))) { strv_free(item->names); free(item); } while ((bn = hashmap_steal_first(m->etc_hosts_by_name))) { free(bn->name); free(bn->items); free(bn); } m->etc_hosts_by_address = set_free(m->etc_hosts_by_address); m->etc_hosts_by_name = hashmap_free(m->etc_hosts_by_name); m->etc_hosts_mtime = USEC_INFINITY; } static void etc_hosts_item_hash_func(const void *p, struct siphash *state) { const EtcHostsItem *item = p; siphash24_compress(&item->family, sizeof(item->family), state); if (item->family == AF_INET) siphash24_compress(&item->address.in, sizeof(item->address.in), state); else if (item->family == AF_INET6) siphash24_compress(&item->address.in6, sizeof(item->address.in6), state); } static int etc_hosts_item_compare_func(const void *a, const void *b) { const EtcHostsItem *x = a, *y = b; if (x->family != y->family) return x->family - y->family; if (x->family == AF_INET) return memcmp(&x->address.in.s_addr, &y->address.in.s_addr, sizeof(struct in_addr)); if (x->family == AF_INET6) return memcmp(&x->address.in6.s6_addr, &y->address.in6.s6_addr, sizeof(struct in6_addr)); return trivial_compare_func(a, b); } static const struct hash_ops etc_hosts_item_ops = { .hash = etc_hosts_item_hash_func, .compare = etc_hosts_item_compare_func, }; static int add_item(Manager *m, int family, const union in_addr_union *address, char **names) { EtcHostsItem key = { .family = family, .address = *address, }; EtcHostsItem *item; char **n; int r; assert(m); assert(address); r = in_addr_is_null(family, address); if (r < 0) return r; if (r > 0) /* This is an 0.0.0.0 or :: item, which we assume means that we shall map the specified hostname to * nothing. */ item = NULL; else { /* If this is a normal address, then, simply add entry mapping it to the specified names */ item = set_get(m->etc_hosts_by_address, &key); if (item) { r = strv_extend_strv(&item->names, names, true); if (r < 0) return log_oom(); } else { r = set_ensure_allocated(&m->etc_hosts_by_address, &etc_hosts_item_ops); if (r < 0) return log_oom(); item = new0(EtcHostsItem, 1); if (!item) return log_oom(); item->family = family; item->address = *address; item->names = names; r = set_put(m->etc_hosts_by_address, item); if (r < 0) { free(item); return log_oom(); } } } STRV_FOREACH(n, names) { EtcHostsItemByName *bn; bn = hashmap_get(m->etc_hosts_by_name, *n); if (!bn) { r = hashmap_ensure_allocated(&m->etc_hosts_by_name, &dns_name_hash_ops); if (r < 0) return log_oom(); bn = new0(EtcHostsItemByName, 1); if (!bn) return log_oom(); bn->name = strdup(*n); if (!bn->name) { free(bn); return log_oom(); } r = hashmap_put(m->etc_hosts_by_name, bn->name, bn); if (r < 0) { free(bn->name); free(bn); return log_oom(); } } if (item) { if (!GREEDY_REALLOC(bn->items, bn->n_allocated, bn->n_items+1)) return log_oom(); bn->items[bn->n_items++] = item; } } return 0; } static int parse_line(Manager *m, unsigned nr, const char *line) { _cleanup_free_ char *address = NULL; _cleanup_strv_free_ char **names = NULL; union in_addr_union in; bool suppressed = false; int family, r; assert(m); assert(line); r = extract_first_word(&line, &address, NULL, EXTRACT_RELAX); if (r < 0) return log_error_errno(r, "Couldn't extract address, in line /etc/hosts:%u.", nr); if (r == 0) { log_error("Premature end of line, in line /etc/hosts:%u.", nr); return -EINVAL; } r = in_addr_from_string_auto(address, &family, &in); if (r < 0) return log_error_errno(r, "Address '%s' is invalid, in line /etc/hosts:%u.", address, nr); for (;;) { _cleanup_free_ char *name = NULL; r = extract_first_word(&line, &name, NULL, EXTRACT_RELAX); if (r < 0) return log_error_errno(r, "Couldn't extract host name, in line /etc/hosts:%u.", nr); if (r == 0) break; r = dns_name_is_valid(name); if (r <= 0) return log_error_errno(r, "Hostname %s is not valid, ignoring, in line /etc/hosts:%u.", name, nr); if (is_localhost(name)) { /* Suppress the "localhost" line that is often seen */ suppressed = true; continue; } r = strv_push(&names, name); if (r < 0) return log_oom(); name = NULL; } if (strv_isempty(names)) { if (suppressed) return 0; log_error("Line is missing any host names, in line /etc/hosts:%u.", nr); return -EINVAL; } /* Takes possession of the names strv */ r = add_item(m, family, &in, names); if (r < 0) return r; names = NULL; return r; } int manager_etc_hosts_read(Manager *m) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; struct stat st; usec_t ts; unsigned nr = 0; int r; assert_se(sd_event_now(m->event, clock_boottime_or_monotonic(), &ts) >= 0); /* See if we checked /etc/hosts recently already */ if (m->etc_hosts_last != USEC_INFINITY && m->etc_hosts_last + ETC_HOSTS_RECHECK_USEC > ts) return 0; m->etc_hosts_last = ts; if (m->etc_hosts_mtime != USEC_INFINITY) { if (stat("/etc/hosts", &st) < 0) { if (errno == ENOENT) { r = 0; goto clear; } return log_error_errno(errno, "Failed to stat /etc/hosts: %m"); } /* Did the mtime change? If not, there's no point in re-reading the file. */ if (timespec_load(&st.st_mtim) == m->etc_hosts_mtime) return 0; } f = fopen("/etc/hosts", "re"); if (!f) { if (errno == ENOENT) { r = 0; goto clear; } return log_error_errno(errno, "Failed to open /etc/hosts: %m"); } /* Take the timestamp at the beginning of processing, so that any changes made later are read on the next * invocation */ r = fstat(fileno(f), &st); if (r < 0) return log_error_errno(errno, "Failed to fstat() /etc/hosts: %m"); manager_etc_hosts_flush(m); FOREACH_LINE(line, f, return log_error_errno(errno, "Failed to read /etc/hosts: %m")) { char *l; nr ++; l = strstrip(line); if (isempty(l)) continue; if (l[0] == '#') continue; r = parse_line(m, nr, l); if (r == -ENOMEM) /* On OOM we abandon the half-built-up structure. All other errors we ignore and proceed */ goto clear; } m->etc_hosts_mtime = timespec_load(&st.st_mtim); m->etc_hosts_last = ts; return 1; clear: manager_etc_hosts_flush(m); return r; } int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer) { bool found_a = false, found_aaaa = false; EtcHostsItemByName *bn; EtcHostsItem k = {}; DnsResourceKey *t; const char *name; unsigned i; int r; assert(m); assert(q); assert(answer); r = manager_etc_hosts_read(m); if (r < 0) return r; name = dns_question_first_name(q); if (!name) return 0; r = dns_name_address(name, &k.family, &k.address); if (r > 0) { EtcHostsItem *item; DnsResourceKey *found_ptr = NULL; item = set_get(m->etc_hosts_by_address, &k); if (!item) return 0; /* We have an address in /etc/hosts that matches the queried name. Let's return successful. Actual data * we'll only return if the request was for PTR. */ DNS_QUESTION_FOREACH(t, q) { if (!IN_SET(t->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) continue; if (!IN_SET(t->class, DNS_CLASS_IN, DNS_CLASS_ANY)) continue; r = dns_name_equal(DNS_RESOURCE_KEY_NAME(t), name); if (r < 0) return r; if (r > 0) { found_ptr = t; break; } } if (found_ptr) { char **n; r = dns_answer_reserve(answer, strv_length(item->names)); if (r < 0) return r; STRV_FOREACH(n, item->names) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; rr = dns_resource_record_new(found_ptr); if (!rr) return -ENOMEM; rr->ptr.name = strdup(*n); if (!rr->ptr.name) return -ENOMEM; r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; } } return 1; } bn = hashmap_get(m->etc_hosts_by_name, name); if (!bn) return 0; r = dns_answer_reserve(answer, bn->n_items); if (r < 0) return r; DNS_QUESTION_FOREACH(t, q) { if (!IN_SET(t->type, DNS_TYPE_A, DNS_TYPE_AAAA, DNS_TYPE_ANY)) continue; if (!IN_SET(t->class, DNS_CLASS_IN, DNS_CLASS_ANY)) continue; r = dns_name_equal(DNS_RESOURCE_KEY_NAME(t), name); if (r < 0) return r; if (r == 0) continue; if (IN_SET(t->type, DNS_TYPE_A, DNS_TYPE_ANY)) found_a = true; if (IN_SET(t->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) found_aaaa = true; if (found_a && found_aaaa) break; } for (i = 0; i < bn->n_items; i++) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; if ((found_a && bn->items[i]->family != AF_INET) && (found_aaaa && bn->items[i]->family != AF_INET6)) continue; r = dns_resource_record_new_address(&rr, bn->items[i]->family, &bn->items[i]->address, bn->name); if (r < 0) return r; r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED); if (r < 0) return r; } return 1; } systemd-229/src/resolve/resolved-etc-hosts.h000066400000000000000000000017401265713322000212340ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2016 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "resolved-manager.h" #include "resolved-dns-question.h" #include "resolved-dns-answer.h" void manager_etc_hosts_flush(Manager *m); int manager_etc_hosts_read(Manager *m); int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer); systemd-229/src/resolve/resolved-gperf.gperf000066400000000000000000000013731265713322000213040ustar00rootroot00000000000000%{ #include #include "conf-parser.h" #include "resolved-conf.h" %} struct ConfigPerfItem; %null_strings %language=ANSI-C %define slot-name section_and_lvalue %define hash-function-name resolved_gperf_hash %define lookup-function-name resolved_gperf_lookup %readonly-tables %omit-struct-type %struct-type %includes %% Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0 Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0 Resolve.Domains, config_parse_search_domains, 0, 0 Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support) Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode) systemd-229/src/resolve/resolved-link-bus.c000066400000000000000000000402331265713322000210420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2016 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "bus-util.h" #include "parse-util.h" #include "resolve-util.h" #include "resolved-bus.h" #include "resolved-link-bus.h" #include "strv.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_resolve_support, resolve_support, ResolveSupport); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_dnssec_mode, dnssec_mode, DnssecMode); static int property_get_dns( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Link *l = userdata; DnsServer *s; int r; assert(reply); assert(l); r = sd_bus_message_open_container(reply, 'a', "(iay)"); if (r < 0) return r; LIST_FOREACH(servers, s, l->dns_servers) { r = bus_dns_server_append(reply, s, false); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_domains( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Link *l = userdata; DnsSearchDomain *d; int r; assert(reply); assert(l); r = sd_bus_message_open_container(reply, 'a', "(sb)"); if (r < 0) return r; LIST_FOREACH(domains, d, l->search_domains) { r = sd_bus_message_append(reply, "(sb)", d->name, d->route_only); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_scopes_mask( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Link *l = userdata; uint64_t mask; assert(reply); assert(l); mask = (l->unicast_scope ? SD_RESOLVED_DNS : 0) | (l->llmnr_ipv4_scope ? SD_RESOLVED_LLMNR_IPV4 : 0) | (l->llmnr_ipv6_scope ? SD_RESOLVED_LLMNR_IPV6 : 0) | (l->mdns_ipv4_scope ? SD_RESOLVED_MDNS_IPV4 : 0) | (l->mdns_ipv6_scope ? SD_RESOLVED_MDNS_IPV6 : 0); return sd_bus_message_append(reply, "t", mask); } static int property_get_ntas( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Link *l = userdata; const char *name; Iterator i; int r; assert(reply); assert(l); r = sd_bus_message_open_container(reply, 'a', "s"); if (r < 0) return r; SET_FOREACH(name, l->dnssec_negative_trust_anchors, i) { r = sd_bus_message_append(reply, "s", name); if (r < 0) return r; } return sd_bus_message_close_container(reply); } static int property_get_dnssec_supported( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { Link *l = userdata; assert(reply); assert(l); return sd_bus_message_append(reply, "b", link_dnssec_supported(l)); } int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ struct in_addr_data *dns = NULL; size_t allocated = 0, n = 0; Link *l = userdata; unsigned i; int r; assert(message); assert(l); r = sd_bus_message_enter_container(message, 'a', "(iay)"); if (r < 0) return r; for (;;) { int family; size_t sz; const void *d; assert_cc(sizeof(int) == sizeof(int32_t)); r = sd_bus_message_enter_container(message, 'r', "iay"); if (r < 0) return r; if (r == 0) break; r = sd_bus_message_read(message, "i", &family); if (r < 0) return r; if (!IN_SET(family, AF_INET, AF_INET6)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); r = sd_bus_message_read_array(message, 'y', &d, &sz); if (r < 0) return r; if (sz != FAMILY_ADDRESS_SIZE(family)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size"); r = sd_bus_message_exit_container(message); if (r < 0) return r; if (!GREEDY_REALLOC(dns, allocated, n+1)) return -ENOMEM; dns[n].family = family; memcpy(&dns[n].address, d, sz); n++; } r = sd_bus_message_exit_container(message); if (r < 0) return r; dns_server_mark_all(l->dns_servers); for (i = 0; i < n; i++) { DnsServer *s; s = dns_server_find(l->dns_servers, dns[i].family, &dns[i].address); if (s) dns_server_move_back_and_unmark(s); else { r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address); if (r < 0) goto clear; } } dns_server_unlink_marked(l->dns_servers); link_allocate_scopes(l); return sd_bus_reply_method_return(message, NULL); clear: dns_server_unlink_all(l->dns_servers); return r; } int bus_link_method_set_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) { Link *l = userdata; int r; assert(message); assert(l); r = sd_bus_message_enter_container(message, 'a', "(sb)"); if (r < 0) return r; for (;;) { const char *name; int route_only; r = sd_bus_message_read(message, "(sb)", &name, &route_only); if (r < 0) return r; if (r == 0) break; r = dns_name_is_valid(name); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name); if (!route_only && dns_name_is_root(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain"); } dns_search_domain_mark_all(l->search_domains); r = sd_bus_message_rewind(message, false); if (r < 0) return r; for (;;) { DnsSearchDomain *d; const char *name; int route_only; r = sd_bus_message_read(message, "(sb)", &name, &route_only); if (r < 0) goto clear; if (r == 0) break; r = dns_search_domain_find(l->search_domains, name, &d); if (r < 0) goto clear; if (r > 0) dns_search_domain_move_back_and_unmark(d); else { r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name); if (r < 0) goto clear; } d->route_only = route_only; } r = sd_bus_message_exit_container(message); if (r < 0) goto clear; dns_search_domain_unlink_marked(l->search_domains); return sd_bus_reply_method_return(message, NULL); clear: dns_search_domain_unlink_all(l->search_domains); return r; } int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) { Link *l = userdata; ResolveSupport mode; const char *llmnr; int r; assert(message); assert(l); r = sd_bus_message_read(message, "s", &llmnr); if (r < 0) return r; if (isempty(llmnr)) mode = RESOLVE_SUPPORT_YES; else { mode = resolve_support_from_string(llmnr); if (mode < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid LLMNR setting: %s", llmnr); } l->llmnr_support = mode; link_allocate_scopes(l); link_add_rrs(l, false); return sd_bus_reply_method_return(message, NULL); } int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) { Link *l = userdata; ResolveSupport mode; const char *mdns; int r; assert(message); assert(l); r = sd_bus_message_read(message, "s", &mdns); if (r < 0) return r; if (isempty(mdns)) mode = RESOLVE_SUPPORT_NO; else { mode = resolve_support_from_string(mdns); if (mode < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid MulticastDNS setting: %s", mdns); } l->mdns_support = mode; link_allocate_scopes(l); link_add_rrs(l, false); return sd_bus_reply_method_return(message, NULL); } int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) { Link *l = userdata; const char *dnssec; DnssecMode mode; int r; assert(message); assert(l); r = sd_bus_message_read(message, "s", &dnssec); if (r < 0) return r; if (isempty(dnssec)) mode = _DNSSEC_MODE_INVALID; else { mode = dnssec_mode_from_string(dnssec); if (mode < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSSEC setting: %s", dnssec); } link_set_dnssec_mode(l, mode); return sd_bus_reply_method_return(message, NULL); } int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_set_free_free_ Set *ns = NULL; _cleanup_free_ char **ntas = NULL; Link *l = userdata; int r; char **i; assert(message); assert(l); r = sd_bus_message_read_strv(message, &ntas); if (r < 0) return r; STRV_FOREACH(i, ntas) { r = dns_name_is_valid(*i); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid negative trust anchor domain: %s", *i); } ns = set_new(&dns_name_hash_ops); if (!ns) return -ENOMEM; STRV_FOREACH(i, ntas) { r = set_put_strdup(ns, *i); if (r < 0) return r; } set_free_free(l->dnssec_negative_trust_anchors); l->dnssec_negative_trust_anchors = ns; ns = NULL; return sd_bus_reply_method_return(message, NULL); } int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error *error) { Link *l = userdata; assert(message); assert(l); link_flush_settings(l); link_allocate_scopes(l); link_add_rrs(l, false); return sd_bus_reply_method_return(message, NULL); } const sd_bus_vtable link_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask, 0, 0), SD_BUS_PROPERTY("DNS", "a(iay)", property_get_dns, 0, 0), SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains, 0, 0), SD_BUS_PROPERTY("LLMNR", "s", property_get_resolve_support, offsetof(Link, llmnr_support), 0), SD_BUS_PROPERTY("MulticastDNS", "s", property_get_resolve_support, offsetof(Link, mdns_support), 0), SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode, offsetof(Link, dnssec_mode), 0), SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", property_get_ntas, 0, 0), SD_BUS_PROPERTY("DNSSECSupport", "b", property_get_dnssec_supported, 0, 0), SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, 0), SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_search_domains, 0), SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, 0), SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, 0), SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, 0), SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL, bus_link_method_set_dnssec_negative_trust_anchors, 0), SD_BUS_METHOD("Revert", NULL, NULL, bus_link_method_revert, 0), SD_BUS_VTABLE_END }; int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { _cleanup_free_ char *e = NULL; Manager *m = userdata; int ifindex; Link *link; int r; assert(bus); assert(path); assert(interface); assert(found); assert(m); r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/link", &e); if (r <= 0) return 0; r = parse_ifindex(e, &ifindex); if (r < 0) return 0; link = hashmap_get(m->links, INT_TO_PTR(ifindex)); if (!link) return 0; *found = link; return 1; } char *link_bus_path(Link *link) { _cleanup_free_ char *ifindex = NULL; char *p; int r; assert(link); if (asprintf(&ifindex, "%i", link->ifindex) < 0) return NULL; r = sd_bus_path_encode("/org/freedesktop/resolve1/link", ifindex, &p); if (r < 0) return NULL; return p; } int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; Manager *m = userdata; Link *link; Iterator i; unsigned c = 0; assert(bus); assert(path); assert(m); assert(nodes); l = new0(char*, hashmap_size(m->links) + 1); if (!l) return -ENOMEM; HASHMAP_FOREACH(link, m->links, i) { char *p; p = link_bus_path(link); if (!p) return -ENOMEM; l[c++] = p; } l[c] = NULL; *nodes = l; l = NULL; return 1; } systemd-229/src/resolve/resolved-link-bus.h000066400000000000000000000033661265713322000210550ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2016 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-bus.h" #include "resolved-link.h" extern const sd_bus_vtable link_vtable[]; int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); char *link_bus_path(Link *link); int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_link_method_set_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error *error); systemd-229/src/resolve/resolved-link.c000066400000000000000000000646761265713322000202740ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-network.h" #include "alloc-util.h" #include "missing.h" #include "parse-util.h" #include "resolved-link.h" #include "string-util.h" #include "strv.h" int link_new(Manager *m, Link **ret, int ifindex) { _cleanup_(link_freep) Link *l = NULL; int r; assert(m); assert(ifindex > 0); r = hashmap_ensure_allocated(&m->links, NULL); if (r < 0) return r; l = new0(Link, 1); if (!l) return -ENOMEM; l->ifindex = ifindex; l->llmnr_support = RESOLVE_SUPPORT_YES; l->mdns_support = RESOLVE_SUPPORT_NO; l->dnssec_mode = _DNSSEC_MODE_INVALID; l->operstate = IF_OPER_UNKNOWN; r = hashmap_put(m->links, INT_TO_PTR(ifindex), l); if (r < 0) return r; l->manager = m; if (ret) *ret = l; l = NULL; return 0; } void link_flush_settings(Link *l) { assert(l); l->llmnr_support = RESOLVE_SUPPORT_YES; l->mdns_support = RESOLVE_SUPPORT_NO; l->dnssec_mode = _DNSSEC_MODE_INVALID; dns_server_unlink_all(l->dns_servers); dns_search_domain_unlink_all(l->search_domains); l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors); } Link *link_free(Link *l) { if (!l) return NULL; link_flush_settings(l); while (l->addresses) (void) link_address_free(l->addresses); if (l->manager) hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex)); dns_scope_free(l->unicast_scope); dns_scope_free(l->llmnr_ipv4_scope); dns_scope_free(l->llmnr_ipv6_scope); dns_scope_free(l->mdns_ipv4_scope); dns_scope_free(l->mdns_ipv6_scope); free(l); return NULL; } void link_allocate_scopes(Link *l) { int r; assert(l); if (link_relevant(l, AF_UNSPEC, false) && l->dns_servers) { if (!l->unicast_scope) { r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC); if (r < 0) log_warning_errno(r, "Failed to allocate DNS scope: %m"); } } else l->unicast_scope = dns_scope_free(l->unicast_scope); if (link_relevant(l, AF_INET, true) && l->llmnr_support != RESOLVE_SUPPORT_NO && l->manager->llmnr_support != RESOLVE_SUPPORT_NO) { if (!l->llmnr_ipv4_scope) { r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET); if (r < 0) log_warning_errno(r, "Failed to allocate LLMNR IPv4 scope: %m"); } } else l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope); if (link_relevant(l, AF_INET6, true) && l->llmnr_support != RESOLVE_SUPPORT_NO && l->manager->llmnr_support != RESOLVE_SUPPORT_NO && socket_ipv6_is_supported()) { if (!l->llmnr_ipv6_scope) { r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6); if (r < 0) log_warning_errno(r, "Failed to allocate LLMNR IPv6 scope: %m"); } } else l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope); if (link_relevant(l, AF_INET, true) && l->mdns_support != RESOLVE_SUPPORT_NO && l->manager->mdns_support != RESOLVE_SUPPORT_NO) { if (!l->mdns_ipv4_scope) { r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, l, DNS_PROTOCOL_MDNS, AF_INET); if (r < 0) log_warning_errno(r, "Failed to allocate mDNS IPv4 scope: %m"); } } else l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope); if (link_relevant(l, AF_INET6, true) && l->mdns_support != RESOLVE_SUPPORT_NO && l->manager->mdns_support != RESOLVE_SUPPORT_NO) { if (!l->mdns_ipv6_scope) { r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, l, DNS_PROTOCOL_MDNS, AF_INET6); if (r < 0) log_warning_errno(r, "Failed to allocate mDNS IPv6 scope: %m"); } } else l->mdns_ipv6_scope = dns_scope_free(l->mdns_ipv6_scope); } void link_add_rrs(Link *l, bool force_remove) { LinkAddress *a; LIST_FOREACH(addresses, a, l->addresses) link_address_add_rrs(a, force_remove); } int link_update_rtnl(Link *l, sd_netlink_message *m) { const char *n = NULL; int r; assert(l); assert(m); r = sd_rtnl_message_link_get_flags(m, &l->flags); if (r < 0) return r; (void) sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu); (void) sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &l->operstate); if (sd_netlink_message_read_string(m, IFLA_IFNAME, &n) >= 0) { strncpy(l->name, n, sizeof(l->name)-1); char_array_0(l->name); } link_allocate_scopes(l); link_add_rrs(l, false); return 0; } static int link_update_dns_servers(Link *l) { _cleanup_strv_free_ char **nameservers = NULL; char **nameserver; int r; assert(l); r = sd_network_link_get_dns(l->ifindex, &nameservers); if (r == -ENODATA) { r = 0; goto clear; } if (r < 0) goto clear; dns_server_mark_all(l->dns_servers); STRV_FOREACH(nameserver, nameservers) { union in_addr_union a; DnsServer *s; int family; r = in_addr_from_string_auto(*nameserver, &family, &a); if (r < 0) goto clear; s = dns_server_find(l->dns_servers, family, &a); if (s) dns_server_move_back_and_unmark(s); else { r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a); if (r < 0) goto clear; } } dns_server_unlink_marked(l->dns_servers); return 0; clear: dns_server_unlink_all(l->dns_servers); return r; } static int link_update_llmnr_support(Link *l) { _cleanup_free_ char *b = NULL; int r; assert(l); r = sd_network_link_get_llmnr(l->ifindex, &b); if (r == -ENODATA) { r = 0; goto clear; } if (r < 0) goto clear; l->llmnr_support = resolve_support_from_string(b); if (l->llmnr_support < 0) { r = -EINVAL; goto clear; } return 0; clear: l->llmnr_support = RESOLVE_SUPPORT_YES; return r; } static int link_update_mdns_support(Link *l) { _cleanup_free_ char *b = NULL; int r; assert(l); r = sd_network_link_get_mdns(l->ifindex, &b); if (r == -ENODATA) { r = 0; goto clear; } if (r < 0) goto clear; l->mdns_support = resolve_support_from_string(b); if (l->mdns_support < 0) { r = -EINVAL; goto clear; } return 0; clear: l->mdns_support = RESOLVE_SUPPORT_NO; return r; } void link_set_dnssec_mode(Link *l, DnssecMode mode) { assert(l); if (l->dnssec_mode == mode) return; if ((l->dnssec_mode == _DNSSEC_MODE_INVALID) || (l->dnssec_mode == DNSSEC_NO && mode != DNSSEC_NO) || (l->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE && mode == DNSSEC_YES)) { /* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the * allow-downgrade mode to full DNSSEC mode, flush it too. */ if (l->unicast_scope) dns_cache_flush(&l->unicast_scope->cache); } l->dnssec_mode = mode; } static int link_update_dnssec_mode(Link *l) { _cleanup_free_ char *m = NULL; DnssecMode mode; int r; assert(l); r = sd_network_link_get_dnssec(l->ifindex, &m); if (r == -ENODATA) { r = 0; goto clear; } if (r < 0) goto clear; mode = dnssec_mode_from_string(m); if (mode < 0) { r = -EINVAL; goto clear; } link_set_dnssec_mode(l, mode); return 0; clear: l->dnssec_mode = _DNSSEC_MODE_INVALID; return r; } static int link_update_dnssec_negative_trust_anchors(Link *l) { _cleanup_strv_free_ char **ntas = NULL; _cleanup_set_free_free_ Set *ns = NULL; char **i; int r; assert(l); r = sd_network_link_get_dnssec_negative_trust_anchors(l->ifindex, &ntas); if (r == -ENODATA) { r = 0; goto clear; } if (r < 0) goto clear; ns = set_new(&dns_name_hash_ops); if (!ns) return -ENOMEM; STRV_FOREACH(i, ntas) { r = set_put_strdup(ns, *i); if (r < 0) return r; } set_free_free(l->dnssec_negative_trust_anchors); l->dnssec_negative_trust_anchors = ns; ns = NULL; return 0; clear: l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors); return r; } static int link_update_search_domain_one(Link *l, const char *name, bool route_only) { DnsSearchDomain *d; int r; r = dns_search_domain_find(l->search_domains, name, &d); if (r < 0) return r; if (r > 0) dns_search_domain_move_back_and_unmark(d); else { r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name); if (r < 0) return r; } d->route_only = route_only; return 0; } static int link_update_search_domains(Link *l) { _cleanup_strv_free_ char **sdomains = NULL, **rdomains = NULL; char **i; int r, q; assert(l); r = sd_network_link_get_search_domains(l->ifindex, &sdomains); if (r < 0 && r != -ENODATA) goto clear; q = sd_network_link_get_route_domains(l->ifindex, &rdomains); if (q < 0 && q != -ENODATA) { r = q; goto clear; } if (r == -ENODATA && q == -ENODATA) { /* networkd knows nothing about this interface, and that's fine. */ r = 0; goto clear; } dns_search_domain_mark_all(l->search_domains); STRV_FOREACH(i, sdomains) { r = link_update_search_domain_one(l, *i, false); if (r < 0) goto clear; } STRV_FOREACH(i, rdomains) { r = link_update_search_domain_one(l, *i, true); if (r < 0) goto clear; } dns_search_domain_unlink_marked(l->search_domains); return 0; clear: dns_search_domain_unlink_all(l->search_domains); return r; } static int link_is_unmanaged(Link *l) { _cleanup_free_ char *state = NULL; int r; assert(l); r = sd_network_link_get_setup_state(l->ifindex, &state); if (r == -ENODATA) return 1; if (r < 0) return r; return STR_IN_SET(state, "pending", "unmanaged"); } static void link_read_settings(Link *l) { int r; assert(l); /* Read settings from networkd, except when networkd is not managing this interface. */ r = link_is_unmanaged(l); if (r < 0) { log_warning_errno(r, "Failed to determine whether interface %s is managed: %m", l->name); return; } if (r > 0) { /* If this link used to be managed, but is now unmanaged, flush all our settings -- but only once. */ if (l->is_managed) link_flush_settings(l); l->is_managed = false; return; } l->is_managed = true; r = link_update_dns_servers(l); if (r < 0) log_warning_errno(r, "Failed to read DNS servers for interface %s, ignoring: %m", l->name); r = link_update_llmnr_support(l); if (r < 0) log_warning_errno(r, "Failed to read LLMNR support for interface %s, ignoring: %m", l->name); r = link_update_mdns_support(l); if (r < 0) log_warning_errno(r, "Failed to read mDNS support for interface %s, ignoring: %m", l->name); r = link_update_dnssec_mode(l); if (r < 0) log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name); r = link_update_dnssec_negative_trust_anchors(l); if (r < 0) log_warning_errno(r, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l->name); r = link_update_search_domains(l); if (r < 0) log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name); } int link_update_monitor(Link *l) { assert(l); link_read_settings(l); link_allocate_scopes(l); link_add_rrs(l, false); return 0; } bool link_relevant(Link *l, int family, bool local_multicast) { _cleanup_free_ char *state = NULL; LinkAddress *a; assert(l); /* A link is relevant for local multicast traffic if it isn't a loopback or pointopoint device, has a link * beat, can do multicast and has at least one link-local (or better) IP address. * * A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at * least one routable address.*/ if (l->flags & (IFF_LOOPBACK|IFF_DORMANT)) return false; if ((l->flags & (IFF_UP|IFF_LOWER_UP)) != (IFF_UP|IFF_LOWER_UP)) return false; if (local_multicast) { if (l->flags & IFF_POINTOPOINT) return false; if ((l->flags & IFF_MULTICAST) != IFF_MULTICAST) return false; } /* Check kernel operstate * https://www.kernel.org/doc/Documentation/networking/operstates.txt */ if (!IN_SET(l->operstate, IF_OPER_UNKNOWN, IF_OPER_UP)) return false; (void) sd_network_link_get_operational_state(l->ifindex, &state); if (state && !STR_IN_SET(state, "unknown", "degraded", "routable")) return false; LIST_FOREACH(addresses, a, l->addresses) if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a, local_multicast)) return true; return false; } LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) { LinkAddress *a; assert(l); LIST_FOREACH(addresses, a, l->addresses) if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr)) return a; return NULL; } DnsServer* link_set_dns_server(Link *l, DnsServer *s) { assert(l); if (l->current_dns_server == s) return s; if (s) log_info("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name); dns_server_unref(l->current_dns_server); l->current_dns_server = dns_server_ref(s); if (l->unicast_scope) dns_cache_flush(&l->unicast_scope->cache); return s; } DnsServer *link_get_dns_server(Link *l) { assert(l); if (!l->current_dns_server) link_set_dns_server(l, l->dns_servers); return l->current_dns_server; } void link_next_dns_server(Link *l) { assert(l); if (!l->current_dns_server) return; /* Change to the next one, but make sure to follow the linked * list only if this server is actually still linked. */ if (l->current_dns_server->linked && l->current_dns_server->servers_next) { link_set_dns_server(l, l->current_dns_server->servers_next); return; } link_set_dns_server(l, l->dns_servers); } DnssecMode link_get_dnssec_mode(Link *l) { assert(l); if (l->dnssec_mode != _DNSSEC_MODE_INVALID) return l->dnssec_mode; return manager_get_dnssec_mode(l->manager); } bool link_dnssec_supported(Link *l) { DnsServer *server; assert(l); if (link_get_dnssec_mode(l) == DNSSEC_NO) return false; server = link_get_dns_server(l); if (server) return dns_server_dnssec_supported(server); return true; } int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) { LinkAddress *a; assert(l); assert(in_addr); a = new0(LinkAddress, 1); if (!a) return -ENOMEM; a->family = family; a->in_addr = *in_addr; a->link = l; LIST_PREPEND(addresses, l->addresses, a); if (ret) *ret = a; return 0; } LinkAddress *link_address_free(LinkAddress *a) { if (!a) return NULL; if (a->link) { LIST_REMOVE(addresses, a->link->addresses, a); if (a->llmnr_address_rr) { if (a->family == AF_INET && a->link->llmnr_ipv4_scope) dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr); else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope) dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr); } if (a->llmnr_ptr_rr) { if (a->family == AF_INET && a->link->llmnr_ipv4_scope) dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr); else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope) dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr); } } dns_resource_record_unref(a->llmnr_address_rr); dns_resource_record_unref(a->llmnr_ptr_rr); free(a); return NULL; } void link_address_add_rrs(LinkAddress *a, bool force_remove) { int r; assert(a); if (a->family == AF_INET) { if (!force_remove && link_address_relevant(a, true) && a->link->llmnr_ipv4_scope && a->link->llmnr_support == RESOLVE_SUPPORT_YES && a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) { if (!a->link->manager->llmnr_host_ipv4_key) { a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname); if (!a->link->manager->llmnr_host_ipv4_key) { r = -ENOMEM; goto fail; } } if (!a->llmnr_address_rr) { a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key); if (!a->llmnr_address_rr) { r = -ENOMEM; goto fail; } a->llmnr_address_rr->a.in_addr = a->in_addr.in; a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL; } if (!a->llmnr_ptr_rr) { r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname); if (r < 0) goto fail; a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL; } r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true); if (r < 0) log_warning_errno(r, "Failed to add A record to LLMNR zone: %m"); r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false); if (r < 0) log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m"); } else { if (a->llmnr_address_rr) { if (a->link->llmnr_ipv4_scope) dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr); a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr); } if (a->llmnr_ptr_rr) { if (a->link->llmnr_ipv4_scope) dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr); a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr); } } } if (a->family == AF_INET6) { if (!force_remove && link_address_relevant(a, true) && a->link->llmnr_ipv6_scope && a->link->llmnr_support == RESOLVE_SUPPORT_YES && a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) { if (!a->link->manager->llmnr_host_ipv6_key) { a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname); if (!a->link->manager->llmnr_host_ipv6_key) { r = -ENOMEM; goto fail; } } if (!a->llmnr_address_rr) { a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key); if (!a->llmnr_address_rr) { r = -ENOMEM; goto fail; } a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6; a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL; } if (!a->llmnr_ptr_rr) { r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname); if (r < 0) goto fail; a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL; } r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true); if (r < 0) log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m"); r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false); if (r < 0) log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m"); } else { if (a->llmnr_address_rr) { if (a->link->llmnr_ipv6_scope) dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr); a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr); } if (a->llmnr_ptr_rr) { if (a->link->llmnr_ipv6_scope) dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr); a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr); } } } return; fail: log_debug_errno(r, "Failed to update address RRs: %m"); } int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) { int r; assert(a); assert(m); r = sd_rtnl_message_addr_get_flags(m, &a->flags); if (r < 0) return r; sd_rtnl_message_addr_get_scope(m, &a->scope); link_allocate_scopes(a->link); link_add_rrs(a->link, false); return 0; } bool link_address_relevant(LinkAddress *a, bool local_multicast) { assert(a); if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE)) return false; if (a->scope >= (local_multicast ? RT_SCOPE_HOST : RT_SCOPE_LINK)) return false; return true; } systemd-229/src/resolve/resolved-link.h000066400000000000000000000062461265713322000202660ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "in-addr-util.h" #include "ratelimit.h" #include "resolve-util.h" typedef struct Link Link; typedef struct LinkAddress LinkAddress; #include "resolved-dns-rr.h" #include "resolved-dns-search-domain.h" #include "resolved-dns-server.h" #include "resolved-manager.h" #define LINK_SEARCH_DOMAINS_MAX 32 #define LINK_DNS_SERVERS_MAX 32 struct LinkAddress { Link *link; int family; union in_addr_union in_addr; unsigned char flags, scope; DnsResourceRecord *llmnr_address_rr; DnsResourceRecord *llmnr_ptr_rr; LIST_FIELDS(LinkAddress, addresses); }; struct Link { Manager *manager; int ifindex; unsigned flags; LIST_HEAD(LinkAddress, addresses); LIST_HEAD(DnsServer, dns_servers); DnsServer *current_dns_server; unsigned n_dns_servers; LIST_HEAD(DnsSearchDomain, search_domains); unsigned n_search_domains; ResolveSupport llmnr_support; ResolveSupport mdns_support; DnssecMode dnssec_mode; Set *dnssec_negative_trust_anchors; DnsScope *unicast_scope; DnsScope *llmnr_ipv4_scope; DnsScope *llmnr_ipv6_scope; DnsScope *mdns_ipv4_scope; DnsScope *mdns_ipv6_scope; bool is_managed; char name[IF_NAMESIZE]; uint32_t mtu; uint8_t operstate; }; int link_new(Manager *m, Link **ret, int ifindex); Link *link_free(Link *l); int link_update_rtnl(Link *l, sd_netlink_message *m); int link_update_monitor(Link *l); bool link_relevant(Link *l, int family, bool local_multicast); LinkAddress* link_find_address(Link *l, int family, const union in_addr_union *in_addr); void link_add_rrs(Link *l, bool force_remove); void link_flush_settings(Link *l); void link_set_dnssec_mode(Link *l, DnssecMode mode); void link_allocate_scopes(Link *l); DnsServer* link_set_dns_server(Link *l, DnsServer *s); DnsServer* link_get_dns_server(Link *l); void link_next_dns_server(Link *l); DnssecMode link_get_dnssec_mode(Link *l); bool link_dnssec_supported(Link *l); int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr); LinkAddress *link_address_free(LinkAddress *a); int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m); bool link_address_relevant(LinkAddress *l, bool local_multicast); void link_address_add_rrs(LinkAddress *a, bool force_remove); DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free); systemd-229/src/resolve/resolved-llmnr.c000066400000000000000000000344411265713322000204460ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "fd-util.h" #include "resolved-llmnr.h" #include "resolved-manager.h" void manager_llmnr_stop(Manager *m) { assert(m); m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source); m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd); m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source); m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd); m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source); m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd); m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source); m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd); } int manager_llmnr_start(Manager *m) { int r; assert(m); if (m->llmnr_support == RESOLVE_SUPPORT_NO) return 0; r = manager_llmnr_ipv4_udp_fd(m); if (r == -EADDRINUSE) goto eaddrinuse; if (r < 0) return r; r = manager_llmnr_ipv4_tcp_fd(m); if (r == -EADDRINUSE) goto eaddrinuse; if (r < 0) return r; if (socket_ipv6_is_supported()) { r = manager_llmnr_ipv6_udp_fd(m); if (r == -EADDRINUSE) goto eaddrinuse; if (r < 0) return r; r = manager_llmnr_ipv6_tcp_fd(m); if (r == -EADDRINUSE) goto eaddrinuse; if (r < 0) return r; } return 0; eaddrinuse: log_warning("There appears to be another LLMNR responder running. Turning off LLMNR support."); m->llmnr_support = RESOLVE_SUPPORT_NO; manager_llmnr_stop(m); return 0; } static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; DnsTransaction *t = NULL; Manager *m = userdata; DnsScope *scope; int r; r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p); if (r <= 0) return r; scope = manager_find_scope(m, p); if (!scope) { log_warning("Got LLMNR UDP packet on unknown scope. Ignoring."); return 0; } if (dns_packet_validate_reply(p) > 0) { log_debug("Got LLMNR reply packet for id %u", DNS_PACKET_ID(p)); dns_scope_check_conflicts(scope, p); t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p))); if (t) dns_transaction_process_reply(t, p); } else if (dns_packet_validate_query(p) > 0) { log_debug("Got LLMNR query packet for id %u", DNS_PACKET_ID(p)); dns_scope_process_query(scope, NULL, p); } else log_debug("Invalid LLMNR UDP packet, ignoring."); return 0; } int manager_llmnr_ipv4_udp_fd(Manager *m) { union sockaddr_union sa = { .in.sin_family = AF_INET, .in.sin_port = htobe16(LLMNR_PORT), }; static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255; int r; assert(m); if (m->llmnr_ipv4_udp_fd >= 0) return m->llmnr_ipv4_udp_fd; m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (m->llmnr_ipv4_udp_fd < 0) return -errno; /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */ r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } /* Disable Don't-Fragment bit in the IP header */ r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu)); if (r < 0) { r = -errno; goto fail; } r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in)); if (r < 0) { r = -errno; goto fail; } r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m); if (r < 0) goto fail; (void) sd_event_source_set_description(m->llmnr_ipv4_udp_event_source, "llmnr-ipv4-udp"); return m->llmnr_ipv4_udp_fd; fail: m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd); return r; } int manager_llmnr_ipv6_udp_fd(Manager *m) { union sockaddr_union sa = { .in6.sin6_family = AF_INET6, .in6.sin6_port = htobe16(LLMNR_PORT), }; static const int one = 1, ttl = 255; int r; assert(m); if (m->llmnr_ipv6_udp_fd >= 0) return m->llmnr_ipv6_udp_fd; m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (m->llmnr_ipv6_udp_fd < 0) return -errno; r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); if (r < 0) { r = -errno; goto fail; } /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */ r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6)); if (r < 0) { r = -errno; goto fail; } r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m); if (r < 0) goto fail; (void) sd_event_source_set_description(m->llmnr_ipv6_udp_event_source, "llmnr-ipv6-udp"); return m->llmnr_ipv6_udp_fd; fail: m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd); return r; } static int on_llmnr_stream_packet(DnsStream *s) { DnsScope *scope; assert(s); scope = manager_find_scope(s->manager, s->read_packet); if (!scope) { log_warning("Got LLMNR TCP packet on unknown scope. Ignroing."); return 0; } if (dns_packet_validate_query(s->read_packet) > 0) { log_debug("Got query packet for id %u", DNS_PACKET_ID(s->read_packet)); dns_scope_process_query(scope, s, s->read_packet); /* If no reply packet was set, we free the stream */ if (s->write_packet) return 0; } else log_debug("Invalid LLMNR TCP packet."); dns_stream_free(s); return 0; } static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) { DnsStream *stream; Manager *m = userdata; int cfd, r; cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); if (cfd < 0) { if (errno == EAGAIN || errno == EINTR) return 0; return -errno; } r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd); if (r < 0) { safe_close(cfd); return r; } stream->on_packet = on_llmnr_stream_packet; return 0; } int manager_llmnr_ipv4_tcp_fd(Manager *m) { union sockaddr_union sa = { .in.sin_family = AF_INET, .in.sin_port = htobe16(LLMNR_PORT), }; static const int one = 1, pmtu = IP_PMTUDISC_DONT; int r; assert(m); if (m->llmnr_ipv4_tcp_fd >= 0) return m->llmnr_ipv4_tcp_fd; m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (m->llmnr_ipv4_tcp_fd < 0) return -errno; /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */ r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } /* Disable Don't-Fragment bit in the IP header */ r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu)); if (r < 0) { r = -errno; goto fail; } r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in)); if (r < 0) { r = -errno; goto fail; } r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN); if (r < 0) { r = -errno; goto fail; } r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m); if (r < 0) goto fail; (void) sd_event_source_set_description(m->llmnr_ipv4_tcp_event_source, "llmnr-ipv4-tcp"); return m->llmnr_ipv4_tcp_fd; fail: m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd); return r; } int manager_llmnr_ipv6_tcp_fd(Manager *m) { union sockaddr_union sa = { .in6.sin6_family = AF_INET6, .in6.sin6_port = htobe16(LLMNR_PORT), }; static const int one = 1; int r; assert(m); if (m->llmnr_ipv6_tcp_fd >= 0) return m->llmnr_ipv6_tcp_fd; m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (m->llmnr_ipv6_tcp_fd < 0) return -errno; /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */ r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6)); if (r < 0) { r = -errno; goto fail; } r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN); if (r < 0) { r = -errno; goto fail; } r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m); if (r < 0) goto fail; (void) sd_event_source_set_description(m->llmnr_ipv6_tcp_event_source, "llmnr-ipv6-tcp"); return m->llmnr_ipv6_tcp_fd; fail: m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd); return r; } systemd-229/src/resolve/resolved-llmnr.h000066400000000000000000000020141265713322000204420ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "resolved-manager.h" #define LLMNR_PORT 5355 int manager_llmnr_ipv4_udp_fd(Manager *m); int manager_llmnr_ipv6_udp_fd(Manager *m); int manager_llmnr_ipv4_tcp_fd(Manager *m); int manager_llmnr_ipv6_tcp_fd(Manager *m); void manager_llmnr_stop(Manager *m); int manager_llmnr_start(Manager *m); systemd-229/src/resolve/resolved-manager.c000066400000000000000000001035111265713322000207270ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "af-list.h" #include "alloc-util.h" #include "dns-domain.h" #include "fd-util.h" #include "fileio-label.h" #include "hostname-util.h" #include "io-util.h" #include "netlink-util.h" #include "network-internal.h" #include "ordered-set.h" #include "parse-util.h" #include "random-util.h" #include "resolved-bus.h" #include "resolved-conf.h" #include "resolved-etc-hosts.h" #include "resolved-llmnr.h" #include "resolved-manager.h" #include "resolved-mdns.h" #include "resolved-resolv-conf.h" #include "socket-util.h" #include "string-table.h" #include "string-util.h" #include "utf8.h" #define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC) static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) { Manager *m = userdata; uint16_t type; Link *l; int ifindex, r; assert(rtnl); assert(m); assert(mm); r = sd_netlink_message_get_type(mm, &type); if (r < 0) goto fail; r = sd_rtnl_message_link_get_ifindex(mm, &ifindex); if (r < 0) goto fail; l = hashmap_get(m->links, INT_TO_PTR(ifindex)); switch (type) { case RTM_NEWLINK:{ bool is_new = !l; if (!l) { r = link_new(m, &l, ifindex); if (r < 0) goto fail; } r = link_update_rtnl(l, mm); if (r < 0) goto fail; r = link_update_monitor(l); if (r < 0) goto fail; if (is_new) log_debug("Found new link %i/%s", ifindex, l->name); break; } case RTM_DELLINK: if (l) { log_debug("Removing link %i/%s", l->ifindex, l->name); link_free(l); } break; } return 0; fail: log_warning_errno(r, "Failed to process RTNL link message: %m"); return 0; } static int manager_process_address(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) { Manager *m = userdata; union in_addr_union address; uint16_t type; int r, ifindex, family; LinkAddress *a; Link *l; assert(rtnl); assert(mm); assert(m); r = sd_netlink_message_get_type(mm, &type); if (r < 0) goto fail; r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex); if (r < 0) goto fail; l = hashmap_get(m->links, INT_TO_PTR(ifindex)); if (!l) return 0; r = sd_rtnl_message_addr_get_family(mm, &family); if (r < 0) goto fail; switch (family) { case AF_INET: r = sd_netlink_message_read_in_addr(mm, IFA_LOCAL, &address.in); if (r < 0) { r = sd_netlink_message_read_in_addr(mm, IFA_ADDRESS, &address.in); if (r < 0) goto fail; } break; case AF_INET6: r = sd_netlink_message_read_in6_addr(mm, IFA_LOCAL, &address.in6); if (r < 0) { r = sd_netlink_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6); if (r < 0) goto fail; } break; default: return 0; } a = link_find_address(l, family, &address); switch (type) { case RTM_NEWADDR: if (!a) { r = link_address_new(l, &a, family, &address); if (r < 0) return r; } r = link_address_update_rtnl(a, mm); if (r < 0) return r; break; case RTM_DELADDR: link_address_free(a); break; } return 0; fail: log_warning_errno(r, "Failed to process RTNL address message: %m"); return 0; } static int manager_rtnl_listen(Manager *m) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; sd_netlink_message *i; int r; assert(m); /* First, subscribe to interfaces coming and going */ r = sd_netlink_open(&m->rtnl); if (r < 0) return r; r = sd_netlink_attach_event(m->rtnl, m->event, SD_EVENT_PRIORITY_IMPORTANT); if (r < 0) return r; r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m); if (r < 0) return r; r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m); if (r < 0) return r; r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m); if (r < 0) return r; r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m); if (r < 0) return r; /* Then, enumerate all links */ r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0); if (r < 0) return r; r = sd_netlink_message_request_dump(req, true); if (r < 0) return r; r = sd_netlink_call(m->rtnl, req, 0, &reply); if (r < 0) return r; for (i = reply; i; i = sd_netlink_message_next(i)) { r = manager_process_link(m->rtnl, i, m); if (r < 0) return r; } req = sd_netlink_message_unref(req); reply = sd_netlink_message_unref(reply); /* Finally, enumerate all addresses, too */ r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC); if (r < 0) return r; r = sd_netlink_message_request_dump(req, true); if (r < 0) return r; r = sd_netlink_call(m->rtnl, req, 0, &reply); if (r < 0) return r; for (i = reply; i; i = sd_netlink_message_next(i)) { r = manager_process_address(m->rtnl, i, m); if (r < 0) return r; } return r; } static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; Iterator i; Link *l; int r; assert(m); sd_network_monitor_flush(m->network_monitor); HASHMAP_FOREACH(l, m->links, i) { r = link_update_monitor(l); if (r < 0) log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex); } r = manager_write_resolv_conf(m); if (r < 0) log_warning_errno(r, "Could not update "PRIVATE_RESOLV_CONF": %m"); return 0; } static int manager_network_monitor_listen(Manager *m) { int r, fd, events; assert(m); r = sd_network_monitor_new(&m->network_monitor, NULL); if (r < 0) return r; fd = sd_network_monitor_get_fd(m->network_monitor); if (fd < 0) return fd; events = sd_network_monitor_get_events(m->network_monitor); if (events < 0) return events; r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m); if (r < 0) return r; r = sd_event_source_set_priority(m->network_event_source, SD_EVENT_PRIORITY_IMPORTANT+5); if (r < 0) return r; (void) sd_event_source_set_description(m->network_event_source, "network-monitor"); return 0; } static int determine_hostname(char **llmnr_hostname, char **mdns_hostname) { _cleanup_free_ char *h = NULL, *n = NULL; char label[DNS_LABEL_MAX]; const char *p; int r, k; assert(llmnr_hostname); assert(mdns_hostname); /* Extract and normalize the first label of the locally * configured hostname, and check it's not "localhost". */ h = gethostname_malloc(); if (!h) return log_oom(); p = h; r = dns_label_unescape(&p, label, sizeof(label)); if (r < 0) return log_error_errno(r, "Failed to unescape host name: %m"); if (r == 0) { log_error("Couldn't find a single label in hosntame."); return -EINVAL; } k = dns_label_undo_idna(label, r, label, sizeof(label)); if (k < 0) return log_error_errno(k, "Failed to undo IDNA: %m"); if (k > 0) r = k; if (!utf8_is_valid(label)) { log_error("System hostname is not UTF-8 clean."); return -EINVAL; } r = dns_label_escape_new(label, r, &n); if (r < 0) return log_error_errno(r, "Failed to escape host name: %m"); if (is_localhost(n)) { log_debug("System hostname is 'localhost', ignoring."); return -EINVAL; } r = dns_name_concat(n, "local", mdns_hostname); if (r < 0) return log_error_errno(r, "Failed to determine mDNS hostname: %m"); *llmnr_hostname = n; n = NULL; return 0; } static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) { _cleanup_free_ char *llmnr_hostname = NULL, *mdns_hostname = NULL; Manager *m = userdata; int r; assert(m); r = determine_hostname(&llmnr_hostname, &mdns_hostname); if (r < 0) return 0; /* ignore invalid hostnames */ if (streq(llmnr_hostname, m->llmnr_hostname) && streq(mdns_hostname, m->mdns_hostname)) return 0; log_info("System hostname changed to '%s'.", llmnr_hostname); free(m->llmnr_hostname); free(m->mdns_hostname); m->llmnr_hostname = llmnr_hostname; m->mdns_hostname = mdns_hostname; llmnr_hostname = mdns_hostname = NULL; manager_refresh_rrs(m); return 0; } static int manager_watch_hostname(Manager *m) { int r; assert(m); m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY); if (m->hostname_fd < 0) { log_warning_errno(errno, "Failed to watch hostname: %m"); return 0; } r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m); if (r < 0) { if (r == -EPERM) /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */ m->hostname_fd = safe_close(m->hostname_fd); else return log_error_errno(r, "Failed to add hostname event source: %m"); } (void) sd_event_source_set_description(m->hostname_event_source, "hostname"); r = determine_hostname(&m->llmnr_hostname, &m->mdns_hostname); if (r < 0) { log_info("Defaulting to hostname 'linux'."); m->llmnr_hostname = strdup("linux"); if (!m->llmnr_hostname) return log_oom(); m->mdns_hostname = strdup("linux.local"); if (!m->mdns_hostname) return log_oom(); } else log_info("Using system hostname '%s'.", m->llmnr_hostname); return 0; } static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { _cleanup_free_ char *buffer = NULL; _cleanup_fclose_ FILE *f = NULL; Manager *m = userdata; size_t size = 0; DnsScope *scope; assert(s); assert(si); assert(m); f = open_memstream(&buffer, &size); if (!f) return log_oom(); LIST_FOREACH(scopes, scope, m->dns_scopes) dns_scope_dump(scope, f); if (fflush_and_check(f) < 0) return log_oom(); log_dump(LOG_INFO, buffer); return 0; } int manager_new(Manager **ret) { _cleanup_(manager_freep) Manager *m = NULL; int r; assert(ret); m = new0(Manager, 1); if (!m) return -ENOMEM; m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1; m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1; m->mdns_ipv4_fd = m->mdns_ipv6_fd = -1; m->hostname_fd = -1; m->llmnr_support = RESOLVE_SUPPORT_YES; m->mdns_support = RESOLVE_SUPPORT_NO; m->dnssec_mode = DNSSEC_NO; m->read_resolv_conf = true; m->need_builtin_fallbacks = true; m->etc_hosts_last = m->etc_hosts_mtime = USEC_INFINITY; r = dns_trust_anchor_load(&m->trust_anchor); if (r < 0) return r; r = manager_parse_config_file(m); if (r < 0) return r; r = sd_event_default(&m->event); if (r < 0) return r; sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); sd_event_set_watchdog(m->event, true); r = manager_watch_hostname(m); if (r < 0) return r; r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC); if (r < 0) return r; r = manager_network_monitor_listen(m); if (r < 0) return r; r = manager_rtnl_listen(m); if (r < 0) return r; r = manager_connect_bus(m); if (r < 0) return r; (void) sd_event_add_signal(m->event, &m->sigusr1_event_source, SIGUSR1, manager_sigusr1, m); *ret = m; m = NULL; return 0; } int manager_start(Manager *m) { int r; assert(m); r = manager_llmnr_start(m); if (r < 0) return r; r = manager_mdns_start(m); if (r < 0) return r; return 0; } Manager *manager_free(Manager *m) { Link *l; if (!m) return NULL; dns_server_unlink_all(m->dns_servers); dns_server_unlink_all(m->fallback_dns_servers); dns_search_domain_unlink_all(m->search_domains); while ((l = hashmap_first(m->links))) link_free(l); while (m->dns_queries) dns_query_free(m->dns_queries); dns_scope_free(m->unicast_scope); hashmap_free(m->links); hashmap_free(m->dns_transactions); sd_event_source_unref(m->network_event_source); sd_network_monitor_unref(m->network_monitor); sd_netlink_unref(m->rtnl); sd_event_source_unref(m->rtnl_event_source); manager_llmnr_stop(m); manager_mdns_stop(m); sd_bus_slot_unref(m->prepare_for_sleep_slot); sd_event_source_unref(m->bus_retry_event_source); sd_bus_unref(m->bus); sd_event_source_unref(m->sigusr1_event_source); sd_event_unref(m->event); dns_resource_key_unref(m->llmnr_host_ipv4_key); dns_resource_key_unref(m->llmnr_host_ipv6_key); sd_event_source_unref(m->hostname_event_source); safe_close(m->hostname_fd); free(m->llmnr_hostname); free(m->mdns_hostname); dns_trust_anchor_flush(&m->trust_anchor); manager_etc_hosts_flush(m); free(m); return NULL; } int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; union { struct cmsghdr header; /* For alignment */ uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo)) + CMSG_SPACE(int) /* ttl/hoplimit */ + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */]; } control; union sockaddr_union sa; struct msghdr mh = {}; struct cmsghdr *cmsg; struct iovec iov; int ms = 0, r; ssize_t l; assert(m); assert(fd >= 0); assert(ret); r = ioctl(fd, FIONREAD, &ms); if (r < 0) return -errno; if (ms < 0) return -EIO; r = dns_packet_new(&p, protocol, ms); if (r < 0) return r; iov.iov_base = DNS_PACKET_DATA(p); iov.iov_len = p->allocated; mh.msg_name = &sa.sa; mh.msg_namelen = sizeof(sa); mh.msg_iov = &iov; mh.msg_iovlen = 1; mh.msg_control = &control; mh.msg_controllen = sizeof(control); l = recvmsg(fd, &mh, 0); if (l < 0) { if (errno == EAGAIN || errno == EINTR) return 0; return -errno; } if (l <= 0) return -EIO; assert(!(mh.msg_flags & MSG_CTRUNC)); assert(!(mh.msg_flags & MSG_TRUNC)); p->size = (size_t) l; p->family = sa.sa.sa_family; p->ipproto = IPPROTO_UDP; if (p->family == AF_INET) { p->sender.in = sa.in.sin_addr; p->sender_port = be16toh(sa.in.sin_port); } else if (p->family == AF_INET6) { p->sender.in6 = sa.in6.sin6_addr; p->sender_port = be16toh(sa.in6.sin6_port); p->ifindex = sa.in6.sin6_scope_id; } else return -EAFNOSUPPORT; CMSG_FOREACH(cmsg, &mh) { if (cmsg->cmsg_level == IPPROTO_IPV6) { assert(p->family == AF_INET6); switch (cmsg->cmsg_type) { case IPV6_PKTINFO: { struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg); if (p->ifindex <= 0) p->ifindex = i->ipi6_ifindex; p->destination.in6 = i->ipi6_addr; break; } case IPV6_HOPLIMIT: p->ttl = *(int *) CMSG_DATA(cmsg); break; } } else if (cmsg->cmsg_level == IPPROTO_IP) { assert(p->family == AF_INET); switch (cmsg->cmsg_type) { case IP_PKTINFO: { struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg); if (p->ifindex <= 0) p->ifindex = i->ipi_ifindex; p->destination.in = i->ipi_addr; break; } case IP_TTL: p->ttl = *(int *) CMSG_DATA(cmsg); break; } } } /* The Linux kernel sets the interface index to the loopback * device if the packet came from the local host since it * avoids the routing table in such a case. Let's unset the * interface index in such a case. */ if (p->ifindex == LOOPBACK_IFINDEX) p->ifindex = 0; if (protocol != DNS_PROTOCOL_DNS) { /* If we don't know the interface index still, we look for the * first local interface with a matching address. Yuck! */ if (p->ifindex <= 0) p->ifindex = manager_find_ifindex(m, p->family, &p->destination); } *ret = p; p = NULL; return 1; } static int sendmsg_loop(int fd, struct msghdr *mh, int flags) { int r; assert(fd >= 0); assert(mh); for (;;) { if (sendmsg(fd, mh, flags) >= 0) return 0; if (errno == EINTR) continue; if (errno != EAGAIN) return -errno; r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC); if (r < 0) return r; if (r == 0) return -ETIMEDOUT; } } static int write_loop(int fd, void *message, size_t length) { int r; assert(fd >= 0); assert(message); for (;;) { if (write(fd, message, length) >= 0) return 0; if (errno == EINTR) continue; if (errno != EAGAIN) return -errno; r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC); if (r < 0) return r; if (r == 0) return -ETIMEDOUT; } } int manager_write(Manager *m, int fd, DnsPacket *p) { int r; log_debug("Sending %s packet with id %" PRIu16 ".", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p)); r = write_loop(fd, DNS_PACKET_DATA(p), p->size); if (r < 0) return r; return 0; } static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) { union sockaddr_union sa = { .in.sin_family = AF_INET, }; union { struct cmsghdr header; /* For alignment */ uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))]; } control; struct msghdr mh = {}; struct iovec iov; assert(m); assert(fd >= 0); assert(addr); assert(port > 0); assert(p); iov.iov_base = DNS_PACKET_DATA(p); iov.iov_len = p->size; sa.in.sin_addr = *addr; sa.in.sin_port = htobe16(port), mh.msg_iov = &iov; mh.msg_iovlen = 1; mh.msg_name = &sa.sa; mh.msg_namelen = sizeof(sa.in); if (ifindex > 0) { struct cmsghdr *cmsg; struct in_pktinfo *pi; zero(control); mh.msg_control = &control; mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo)); cmsg = CMSG_FIRSTHDR(&mh); cmsg->cmsg_len = mh.msg_controllen; cmsg->cmsg_level = IPPROTO_IP; cmsg->cmsg_type = IP_PKTINFO; pi = (struct in_pktinfo*) CMSG_DATA(cmsg); pi->ipi_ifindex = ifindex; } return sendmsg_loop(fd, &mh, 0); } static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) { union sockaddr_union sa = { .in6.sin6_family = AF_INET6, }; union { struct cmsghdr header; /* For alignment */ uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))]; } control; struct msghdr mh = {}; struct iovec iov; assert(m); assert(fd >= 0); assert(addr); assert(port > 0); assert(p); iov.iov_base = DNS_PACKET_DATA(p); iov.iov_len = p->size; sa.in6.sin6_addr = *addr; sa.in6.sin6_port = htobe16(port), sa.in6.sin6_scope_id = ifindex; mh.msg_iov = &iov; mh.msg_iovlen = 1; mh.msg_name = &sa.sa; mh.msg_namelen = sizeof(sa.in6); if (ifindex > 0) { struct cmsghdr *cmsg; struct in6_pktinfo *pi; zero(control); mh.msg_control = &control; mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo)); cmsg = CMSG_FIRSTHDR(&mh); cmsg->cmsg_len = mh.msg_controllen; cmsg->cmsg_level = IPPROTO_IPV6; cmsg->cmsg_type = IPV6_PKTINFO; pi = (struct in6_pktinfo*) CMSG_DATA(cmsg); pi->ipi6_ifindex = ifindex; } return sendmsg_loop(fd, &mh, 0); } int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) { assert(m); assert(fd >= 0); assert(addr); assert(port > 0); assert(p); log_debug("Sending %s packet with id %" PRIu16 " on interface %i/%s.", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family)); if (family == AF_INET) return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p); else if (family == AF_INET6) return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p); return -EAFNOSUPPORT; } uint32_t manager_find_mtu(Manager *m) { uint32_t mtu = 0; Link *l; Iterator i; /* If we don't know on which link a DNS packet would be * delivered, let's find the largest MTU that works on all * interfaces we know of */ HASHMAP_FOREACH(l, m->links, i) { if (l->mtu <= 0) continue; if (mtu <= 0 || l->mtu < mtu) mtu = l->mtu; } return mtu; } int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) { LinkAddress *a; assert(m); a = manager_find_link_address(m, family, in_addr); if (a) return a->link->ifindex; return 0; } void manager_refresh_rrs(Manager *m) { Iterator i; Link *l; assert(m); m->llmnr_host_ipv4_key = dns_resource_key_unref(m->llmnr_host_ipv4_key); m->llmnr_host_ipv6_key = dns_resource_key_unref(m->llmnr_host_ipv6_key); HASHMAP_FOREACH(l, m->links, i) { link_add_rrs(l, true); link_add_rrs(l, false); } } int manager_next_hostname(Manager *m) { const char *p; uint64_t u, a; char *h, *k; int r; assert(m); p = strchr(m->llmnr_hostname, 0); assert(p); while (p > m->llmnr_hostname) { if (!strchr("0123456789", p[-1])) break; p--; } if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0) u = 1; /* Add a random number to the old value. This way we can avoid * that two hosts pick the same hostname, win on IPv4 and lose * on IPv6 (or vice versa), and pick the same hostname * replacement hostname, ad infinitum. We still want the * numbers to go up monotonically, hence we just add a random * value 1..10 */ random_bytes(&a, sizeof(a)); u += 1 + a % 10; if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->llmnr_hostname), m->llmnr_hostname, u) < 0) return -ENOMEM; r = dns_name_concat(h, "local", &k); if (r < 0) { free(h); return r; } log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->llmnr_hostname, h); free(m->llmnr_hostname); m->llmnr_hostname = h; free(m->mdns_hostname); m->mdns_hostname = k; manager_refresh_rrs(m); return 0; } LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) { Iterator i; Link *l; assert(m); HASHMAP_FOREACH(l, m->links, i) { LinkAddress *a; a = link_find_address(l, family, in_addr); if (a) return a; } return NULL; } bool manager_our_packet(Manager *m, DnsPacket *p) { assert(m); assert(p); return !!manager_find_link_address(m, p->family, &p->sender); } DnsScope* manager_find_scope(Manager *m, DnsPacket *p) { Link *l; assert(m); assert(p); l = hashmap_get(m->links, INT_TO_PTR(p->ifindex)); if (!l) return NULL; switch (p->protocol) { case DNS_PROTOCOL_LLMNR: if (p->family == AF_INET) return l->llmnr_ipv4_scope; else if (p->family == AF_INET6) return l->llmnr_ipv6_scope; break; case DNS_PROTOCOL_MDNS: if (p->family == AF_INET) return l->mdns_ipv4_scope; else if (p->family == AF_INET6) return l->mdns_ipv6_scope; break; default: break; } return NULL; } void manager_verify_all(Manager *m) { DnsScope *s; assert(m); LIST_FOREACH(scopes, s, m->dns_scopes) dns_zone_verify_all(&s->zone); } int manager_is_own_hostname(Manager *m, const char *name) { int r; assert(m); assert(name); if (m->llmnr_hostname) { r = dns_name_equal(name, m->llmnr_hostname); if (r != 0) return r; } if (m->mdns_hostname) return dns_name_equal(name, m->mdns_hostname); return 0; } int manager_compile_dns_servers(Manager *m, OrderedSet **dns) { DnsServer *s; Iterator i; Link *l; int r; assert(m); assert(dns); r = ordered_set_ensure_allocated(dns, &dns_server_hash_ops); if (r < 0) return r; /* First add the system-wide servers and domains */ LIST_FOREACH(servers, s, m->dns_servers) { r = ordered_set_put(*dns, s); if (r == -EEXIST) continue; if (r < 0) return r; } /* Then, add the per-link servers */ HASHMAP_FOREACH(l, m->links, i) { LIST_FOREACH(servers, s, l->dns_servers) { r = ordered_set_put(*dns, s); if (r == -EEXIST) continue; if (r < 0) return r; } } /* If we found nothing, add the fallback servers */ if (ordered_set_isempty(*dns)) { LIST_FOREACH(servers, s, m->fallback_dns_servers) { r = ordered_set_put(*dns, s); if (r == -EEXIST) continue; if (r < 0) return r; } } return 0; } int manager_compile_search_domains(Manager *m, OrderedSet **domains) { DnsSearchDomain *d; Iterator i; Link *l; int r; assert(m); assert(domains); r = ordered_set_ensure_allocated(domains, &dns_name_hash_ops); if (r < 0) return r; LIST_FOREACH(domains, d, m->search_domains) { r = ordered_set_put(*domains, d->name); if (r == -EEXIST) continue; if (r < 0) return r; } HASHMAP_FOREACH(l, m->links, i) { LIST_FOREACH(domains, d, l->search_domains) { r = ordered_set_put(*domains, d->name); if (r == -EEXIST) continue; if (r < 0) return r; } } return 0; } DnssecMode manager_get_dnssec_mode(Manager *m) { assert(m); if (m->dnssec_mode != _DNSSEC_MODE_INVALID) return m->dnssec_mode; return DNSSEC_NO; } bool manager_dnssec_supported(Manager *m) { DnsServer *server; Iterator i; Link *l; assert(m); if (manager_get_dnssec_mode(m) == DNSSEC_NO) return false; server = manager_get_dns_server(m); if (server && !dns_server_dnssec_supported(server)) return false; HASHMAP_FOREACH(l, m->links, i) if (!link_dnssec_supported(l)) return false; return true; } void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResourceKey *key) { assert(verdict >= 0); assert(verdict < _DNSSEC_VERDICT_MAX); if (log_get_max_level() >= LOG_DEBUG) { _cleanup_free_ char *s = NULL; (void) dns_resource_key_to_string(key, &s); log_debug("Found verdict for lookup %s: %s", s ? strstrip(s) : "n/a", dnssec_verdict_to_string(verdict)); } m->n_dnssec_verdict[verdict]++; } bool manager_routable(Manager *m, int family) { Iterator i; Link *l; assert(m); /* Returns true if the host has at least one interface with a routable address of the specified type */ HASHMAP_FOREACH(l, m->links, i) if (link_relevant(l, family, false)) return true; return false; } systemd-229/src/resolve/resolved-manager.h000066400000000000000000000116571265713322000207450ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-event.h" #include "sd-netlink.h" #include "sd-network.h" #include "hashmap.h" #include "list.h" #include "ordered-set.h" #include "resolve-util.h" typedef struct Manager Manager; #include "resolved-dns-query.h" #include "resolved-dns-search-domain.h" #include "resolved-dns-server.h" #include "resolved-dns-stream.h" #include "resolved-dns-trust-anchor.h" #include "resolved-link.h" #define MANAGER_SEARCH_DOMAINS_MAX 32 #define MANAGER_DNS_SERVERS_MAX 32 struct Manager { sd_event *event; ResolveSupport llmnr_support; ResolveSupport mdns_support; DnssecMode dnssec_mode; /* Network */ Hashmap *links; sd_netlink *rtnl; sd_event_source *rtnl_event_source; sd_network_monitor *network_monitor; sd_event_source *network_event_source; /* DNS query management */ Hashmap *dns_transactions; LIST_HEAD(DnsQuery, dns_queries); unsigned n_dns_queries; LIST_HEAD(DnsStream, dns_streams); unsigned n_dns_streams; /* Unicast dns */ LIST_HEAD(DnsServer, dns_servers); LIST_HEAD(DnsServer, fallback_dns_servers); unsigned n_dns_servers; /* counts both main and fallback */ DnsServer *current_dns_server; LIST_HEAD(DnsSearchDomain, search_domains); unsigned n_search_domains; bool permit_domain_search; bool need_builtin_fallbacks:1; bool read_resolv_conf:1; usec_t resolv_conf_mtime; DnsTrustAnchor trust_anchor; LIST_HEAD(DnsScope, dns_scopes); DnsScope *unicast_scope; /* LLMNR */ int llmnr_ipv4_udp_fd; int llmnr_ipv6_udp_fd; int llmnr_ipv4_tcp_fd; int llmnr_ipv6_tcp_fd; sd_event_source *llmnr_ipv4_udp_event_source; sd_event_source *llmnr_ipv6_udp_event_source; sd_event_source *llmnr_ipv4_tcp_event_source; sd_event_source *llmnr_ipv6_tcp_event_source; /* mDNS */ int mdns_ipv4_fd; int mdns_ipv6_fd; sd_event_source *mdns_ipv4_event_source; sd_event_source *mdns_ipv6_event_source; /* dbus */ sd_bus *bus; sd_event_source *bus_retry_event_source; /* The hostname we publish on LLMNR and mDNS */ char *llmnr_hostname; char *mdns_hostname; DnsResourceKey *llmnr_host_ipv4_key; DnsResourceKey *llmnr_host_ipv6_key; /* Watch the system hostname */ int hostname_fd; sd_event_source *hostname_event_source; /* Watch for system suspends */ sd_bus_slot *prepare_for_sleep_slot; sd_event_source *sigusr1_event_source; unsigned n_transactions_total; unsigned n_dnssec_verdict[_DNSSEC_VERDICT_MAX]; /* Data from /etc/hosts */ Set* etc_hosts_by_address; Hashmap* etc_hosts_by_name; usec_t etc_hosts_last, etc_hosts_mtime; }; /* Manager */ int manager_new(Manager **ret); Manager* manager_free(Manager *m); int manager_start(Manager *m); uint32_t manager_find_mtu(Manager *m); int manager_write(Manager *m, int fd, DnsPacket *p); int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p); int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret); int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr); LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr); void manager_refresh_rrs(Manager *m); int manager_next_hostname(Manager *m); bool manager_our_packet(Manager *m, DnsPacket *p); DnsScope* manager_find_scope(Manager *m, DnsPacket *p); void manager_verify_all(Manager *m); DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); #define EXTRA_CMSG_SPACE 1024 int manager_is_own_hostname(Manager *m, const char *name); int manager_compile_dns_servers(Manager *m, OrderedSet **servers); int manager_compile_search_domains(Manager *m, OrderedSet **domains); DnssecMode manager_get_dnssec_mode(Manager *m); bool manager_dnssec_supported(Manager *m); void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResourceKey *key); bool manager_routable(Manager *m, int family); systemd-229/src/resolve/resolved-mdns.c000066400000000000000000000216501265713322000202610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Daniel Mack systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "fd-util.h" #include "resolved-manager.h" #include "resolved-mdns.h" void manager_mdns_stop(Manager *m) { assert(m); m->mdns_ipv4_event_source = sd_event_source_unref(m->mdns_ipv4_event_source); m->mdns_ipv4_fd = safe_close(m->mdns_ipv4_fd); m->mdns_ipv6_event_source = sd_event_source_unref(m->mdns_ipv6_event_source); m->mdns_ipv6_fd = safe_close(m->mdns_ipv6_fd); } int manager_mdns_start(Manager *m) { int r; assert(m); if (m->mdns_support == RESOLVE_SUPPORT_NO) return 0; r = manager_mdns_ipv4_fd(m); if (r == -EADDRINUSE) goto eaddrinuse; if (r < 0) return r; if (socket_ipv6_is_supported()) { r = manager_mdns_ipv6_fd(m); if (r == -EADDRINUSE) goto eaddrinuse; if (r < 0) return r; } return 0; eaddrinuse: log_warning("There appears to be another mDNS responder running. Turning off mDNS support."); m->mdns_support = RESOLVE_SUPPORT_NO; manager_mdns_stop(m); return 0; } static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; Manager *m = userdata; DnsScope *scope; int r; r = manager_recv(m, fd, DNS_PROTOCOL_MDNS, &p); if (r <= 0) return r; scope = manager_find_scope(m, p); if (!scope) { log_warning("Got mDNS UDP packet on unknown scope. Ignoring."); return 0; } if (dns_packet_validate_reply(p) > 0) { DnsResourceRecord *rr; log_debug("Got mDNS reply packet"); /* * mDNS is different from regular DNS and LLMNR with regard to handling responses. * While on other protocols, we can ignore every answer that doesn't match a question * we broadcast earlier, RFC6762, section 18.1 recommends looking at and caching all * incoming information, regardless of the DNS packet ID. * * Hence, extract the packet here, and try to find a transaction for answer the we got * and complete it. Also store the new information in scope's cache. */ r = dns_packet_extract(p); if (r < 0) { log_debug("mDNS packet extraction failed."); return 0; } dns_scope_check_conflicts(scope, p); DNS_ANSWER_FOREACH(rr, p->answer) { const char *name = DNS_RESOURCE_KEY_NAME(rr->key); DnsTransaction *t; /* If the received reply packet contains ANY record that is not .local or .in-addr.arpa, * we assume someone's playing tricks on us and discard the packet completely. */ if (!(dns_name_endswith(name, "in-addr.arpa") > 0 || dns_name_endswith(name, "local") > 0)) return 0; t = dns_scope_find_transaction(scope, rr->key, false); if (t) dns_transaction_process_reply(t, p); } dns_cache_put(&scope->cache, NULL, DNS_PACKET_RCODE(p), p->answer, false, (uint32_t) -1, 0, p->family, &p->sender); } else if (dns_packet_validate_query(p) > 0) { log_debug("Got mDNS query packet for id %u", DNS_PACKET_ID(p)); dns_scope_process_query(scope, NULL, p); } else log_debug("Invalid mDNS UDP packet."); return 0; } int manager_mdns_ipv4_fd(Manager *m) { union sockaddr_union sa = { .in.sin_family = AF_INET, .in.sin_port = htobe16(MDNS_PORT), }; static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255; int r; assert(m); if (m->mdns_ipv4_fd >= 0) return m->mdns_ipv4_fd; m->mdns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (m->mdns_ipv4_fd < 0) return -errno; r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->mdns_ipv4_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } /* Disable Don't-Fragment bit in the IP header */ r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu)); if (r < 0) { r = -errno; goto fail; } r = bind(m->mdns_ipv4_fd, &sa.sa, sizeof(sa.in)); if (r < 0) { r = -errno; goto fail; } r = sd_event_add_io(m->event, &m->mdns_ipv4_event_source, m->mdns_ipv4_fd, EPOLLIN, on_mdns_packet, m); if (r < 0) goto fail; return m->mdns_ipv4_fd; fail: m->mdns_ipv4_fd = safe_close(m->mdns_ipv4_fd); return r; } int manager_mdns_ipv6_fd(Manager *m) { union sockaddr_union sa = { .in6.sin6_family = AF_INET6, .in6.sin6_port = htobe16(MDNS_PORT), }; static const int one = 1, ttl = 255; int r; assert(m); if (m->mdns_ipv6_fd >= 0) return m->mdns_ipv6_fd; m->mdns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (m->mdns_ipv6_fd < 0) return -errno; r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); if (r < 0) { r = -errno; goto fail; } /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */ r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->mdns_ipv6_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one)); if (r < 0) { r = -errno; goto fail; } r = bind(m->mdns_ipv6_fd, &sa.sa, sizeof(sa.in6)); if (r < 0) { r = -errno; goto fail; } r = sd_event_add_io(m->event, &m->mdns_ipv6_event_source, m->mdns_ipv6_fd, EPOLLIN, on_mdns_packet, m); if (r < 0) goto fail; return m->mdns_ipv6_fd; fail: m->mdns_ipv6_fd = safe_close(m->mdns_ipv6_fd); return r; } systemd-229/src/resolve/resolved-mdns.h000066400000000000000000000016421265713322000202650ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Daniel Mack systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "resolved-manager.h" #define MDNS_PORT 5353 int manager_mdns_ipv4_fd(Manager *m); int manager_mdns_ipv6_fd(Manager *m); void manager_mdns_stop(Manager *m); int manager_mdns_start(Manager *m); systemd-229/src/resolve/resolved-resolv-conf.c000066400000000000000000000207651265713322000215630ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "dns-domain.h" #include "fd-util.h" #include "fileio-label.h" #include "fileio.h" #include "ordered-set.h" #include "resolved-conf.h" #include "resolved-resolv-conf.h" #include "string-util.h" #include "strv.h" int manager_read_resolv_conf(Manager *m) { _cleanup_fclose_ FILE *f = NULL; struct stat st, own; char line[LINE_MAX]; usec_t t; int r; assert(m); /* Reads the system /etc/resolv.conf, if it exists and is not * symlinked to our own resolv.conf instance */ if (!m->read_resolv_conf) return 0; r = stat("/etc/resolv.conf", &st); if (r < 0) { if (errno == ENOENT) return 0; r = log_warning_errno(errno, "Failed to stat /etc/resolv.conf: %m"); goto clear; } /* Have we already seen the file? */ t = timespec_load(&st.st_mtim); if (t == m->resolv_conf_mtime) return 0; /* Is it symlinked to our own file? */ if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 && st.st_dev == own.st_dev && st.st_ino == own.st_ino) return 0; f = fopen("/etc/resolv.conf", "re"); if (!f) { if (errno == ENOENT) return 0; r = log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m"); goto clear; } if (fstat(fileno(f), &st) < 0) { r = log_error_errno(errno, "Failed to stat open file: %m"); goto clear; } dns_server_mark_all(m->dns_servers); dns_search_domain_mark_all(m->search_domains); FOREACH_LINE(line, f, r = -errno; goto clear) { const char *a; char *l; l = strstrip(line); if (*l == '#' || *l == ';') continue; a = first_word(l, "nameserver"); if (a) { r = manager_add_dns_server_by_string(m, DNS_SERVER_SYSTEM, a); if (r < 0) log_warning_errno(r, "Failed to parse DNS server address '%s', ignoring.", a); continue; } a = first_word(l, "domain"); if (!a) /* We treat "domain" lines, and "search" lines as equivalent, and add both to our list. */ a = first_word(l, "search"); if (a) { r = manager_parse_search_domains_and_warn(m, a); if (r < 0) log_warning_errno(r, "Failed to parse search domain string '%s', ignoring.", a); } } m->resolv_conf_mtime = t; /* Flush out all servers and search domains that are still * marked. Those are then ones that didn't appear in the new * /etc/resolv.conf */ dns_server_unlink_marked(m->dns_servers); dns_search_domain_unlink_marked(m->search_domains); /* Whenever /etc/resolv.conf changes, start using the first * DNS server of it. This is useful to deal with broken * network managing implementations (like NetworkManager), * that when connecting to a VPN place both the VPN DNS * servers and the local ones in /etc/resolv.conf. Without * resetting the DNS server to use back to the first entry we * will continue to use the local one thus being unable to * resolve VPN domains. */ manager_set_dns_server(m, m->dns_servers); /* Unconditionally flush the cache when /etc/resolv.conf is * modified, even if the data it contained was completely * identical to the previous version we used. We do this * because altering /etc/resolv.conf is typically done when * the network configuration changes, and that should be * enough to flush the global unicast DNS cache. */ if (m->unicast_scope) dns_cache_flush(&m->unicast_scope->cache); return 0; clear: dns_server_unlink_all(m->dns_servers); dns_search_domain_unlink_all(m->search_domains); return r; } static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) { assert(s); assert(f); assert(count); (void) dns_server_string(s); if (!s->server_string) { log_warning("Our of memory, or invalid DNS address. Ignoring server."); return; } if (*count == MAXNS) fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f); (*count) ++; fprintf(f, "nameserver %s\n", s->server_string); } static void write_resolv_conf_search( const char *domain, FILE *f, unsigned *count, unsigned *length) { assert(domain); assert(f); assert(length); if (*count >= MAXDNSRCH || *length + strlen(domain) > 256) { if (*count == MAXDNSRCH) fputs(" # Too many search domains configured, remaining ones ignored.", f); if (*length <= 256) fputs(" # Total length of all search domains is too long, remaining ones ignored.", f); return; } (*length) += strlen(domain); (*count) ++; fputc(' ', f); fputs(domain, f); } static int write_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) { Iterator i; fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n" "# Third party programs must not access this file directly, but\n" "# only through the symlink at /etc/resolv.conf. To manage\n" "# resolv.conf(5) in a different way, replace the symlink by a\n" "# static file or a different symlink.\n\n", f); if (ordered_set_isempty(dns)) fputs("# No DNS servers known.\n", f); else { unsigned count = 0; DnsServer *s; ORDERED_SET_FOREACH(s, dns, i) write_resolv_conf_server(s, f, &count); } if (!ordered_set_isempty(domains)) { unsigned length = 0, count = 0; char *domain; fputs("search", f); ORDERED_SET_FOREACH(domain, domains, i) write_resolv_conf_search(domain, f, &count, &length); fputs("\n", f); } return fflush_and_check(f); } int manager_write_resolv_conf(Manager *m) { _cleanup_ordered_set_free_ OrderedSet *dns = NULL, *domains = NULL; _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(m); /* Read the system /etc/resolv.conf first */ manager_read_resolv_conf(m); /* Add the full list to a set, to filter out duplicates */ r = manager_compile_dns_servers(m, &dns); if (r < 0) return r; r = manager_compile_search_domains(m, &domains); if (r < 0) return r; r = fopen_temporary_label(PRIVATE_RESOLV_CONF, PRIVATE_RESOLV_CONF, &f, &temp_path); if (r < 0) return r; fchmod(fileno(f), 0644); r = write_resolv_conf_contents(f, dns, domains); if (r < 0) goto fail; if (rename(temp_path, PRIVATE_RESOLV_CONF) < 0) { r = -errno; goto fail; } return 0; fail: (void) unlink(PRIVATE_RESOLV_CONF); (void) unlink(temp_path); return r; } systemd-229/src/resolve/resolved-resolv-conf.h000066400000000000000000000016321265713322000215600ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "resolved-manager.h" #define PRIVATE_RESOLV_CONF "/run/systemd/resolve/resolv.conf" int manager_read_resolv_conf(Manager *m); int manager_write_resolv_conf(Manager *m); systemd-229/src/resolve/resolved.c000066400000000000000000000063401265713322000173210ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-daemon.h" #include "sd-event.h" #include "capability-util.h" #include "mkdir.h" #include "resolved-conf.h" #include "resolved-manager.h" #include "resolved-resolv-conf.h" #include "selinux-util.h" #include "signal-util.h" #include "user-util.h" int main(int argc, char *argv[]) { _cleanup_(manager_freep) Manager *m = NULL; const char *user = "systemd-resolve"; uid_t uid; gid_t gid; int r; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); if (argc != 1) { log_error("This program takes no arguments."); r = -EINVAL; goto finish; } umask(0022); r = mac_selinux_init(NULL); if (r < 0) { log_error_errno(r, "SELinux setup failed: %m"); goto finish; } r = get_user_creds(&user, &uid, &gid, NULL, NULL); if (r < 0) { log_error_errno(r, "Cannot resolve user name %s: %m", user); goto finish; } /* Always create the directory where resolv.conf will live */ r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid); if (r < 0) { log_error_errno(r, "Could not create runtime directory: %m"); goto finish; } r = drop_privileges(uid, gid, 0); if (r < 0) goto finish; assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, -1) >= 0); r = manager_new(&m); if (r < 0) { log_error_errno(r, "Could not create manager: %m"); goto finish; } r = manager_start(m); if (r < 0) { log_error_errno(r, "Failed to start manager: %m"); goto finish; } /* Write finish default resolv.conf to avoid a dangling * symlink */ r = manager_write_resolv_conf(m); if (r < 0) log_warning_errno(r, "Could not create "PRIVATE_RESOLV_CONF": %m"); sd_notify(false, "READY=1\n" "STATUS=Processing requests..."); r = sd_event_loop(m->event); if (r < 0) { log_error_errno(r, "Event loop failed: %m"); goto finish; } sd_event_get_exit_code(m->event, &r); finish: sd_notify(false, "STOPPING=1\n" "STATUS=Shutting down..."); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/resolve/resolved.conf.in000066400000000000000000000010661265713322000204310ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # Entries in this file show the compile time defaults. # You can change settings by editing this file. # Defaults can be restored by simply deleting this file. # # See resolved.conf(5) for details [Resolve] #DNS= #FallbackDNS=@DNS_SERVERS@ #Domains= #LLMNR=yes #DNSSEC=no systemd-229/src/resolve/test-dnssec-complex.c000066400000000000000000000237111265713322000214000ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2016 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" #include "af-list.h" #include "alloc-util.h" #include "bus-common-errors.h" #include "dns-type.h" #include "random-util.h" #include "string-util.h" #include "time-util.h" #define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC) static void prefix_random(const char *name, char **ret) { uint64_t i, u; char *m = NULL; u = 1 + (random_u64() & 3); for (i = 0; i < u; i++) { _cleanup_free_ char *b = NULL; char *x; assert_se(asprintf(&b, "x%" PRIu64 "x", random_u64())); x = strjoin(b, ".", name, NULL); assert_se(x); free(m); m = x; } *ret = m; } static void test_rr_lookup(sd_bus *bus, const char *name, uint16_t type, const char *result) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *m = NULL; int r; /* If the name starts with a dot, we prefix one to three random labels */ if (startswith(name, ".")) { prefix_random(name + 1, &m); name = m; } assert_se(sd_bus_message_new_method_call( bus, &req, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "ResolveRecord") >= 0); assert_se(sd_bus_message_append(req, "isqqt", 0, name, DNS_CLASS_IN, type, UINT64_C(0)) >= 0); r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) { assert_se(result); assert_se(sd_bus_error_has_name(&error, result)); log_info("[OK] %s/%s resulted in <%s>.", name, dns_type_to_string(type), error.name); } else { assert_se(!result); log_info("[OK] %s/%s succeeded.", name, dns_type_to_string(type)); } } static void test_hostname_lookup(sd_bus *bus, const char *name, int family, const char *result) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *m = NULL; const char *af; int r; af = family == AF_UNSPEC ? "AF_UNSPEC" : af_to_name(family); /* If the name starts with a dot, we prefix one to three random labels */ if (startswith(name, ".")) { prefix_random(name + 1, &m); name = m; } assert_se(sd_bus_message_new_method_call( bus, &req, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "ResolveHostname") >= 0); assert_se(sd_bus_message_append(req, "isit", 0, name, family, UINT64_C(0)) >= 0); r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) { assert_se(result); assert_se(sd_bus_error_has_name(&error, result)); log_info("[OK] %s/%s resulted in <%s>.", name, af, error.name); } else { assert_se(!result); log_info("[OK] %s/%s succeeded.", name, af); } } int main(int argc, char* argv[]) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; /* Note that this is a manual test as it requires: * * Full network access * A DNSSEC capable DNS server * That zones contacted are still set up as they were when I wrote this. */ assert_se(sd_bus_open_system(&bus) >= 0); /* Normally signed */ test_rr_lookup(bus, "www.eurid.eu", DNS_TYPE_A, NULL); test_hostname_lookup(bus, "www.eurid.eu", AF_UNSPEC, NULL); test_rr_lookup(bus, "sigok.verteiltesysteme.net", DNS_TYPE_A, NULL); test_hostname_lookup(bus, "sigok.verteiltesysteme.net", AF_UNSPEC, NULL); /* Normally signed, NODATA */ test_rr_lookup(bus, "www.eurid.eu", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR); test_rr_lookup(bus, "sigok.verteiltesysteme.net", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR); /* Invalid signature */ test_rr_lookup(bus, "sigfail.verteiltesysteme.net", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED); test_hostname_lookup(bus, "sigfail.verteiltesysteme.net", AF_INET, BUS_ERROR_DNSSEC_FAILED); /* Invalid signature, RSA, wildcard */ test_rr_lookup(bus, ".wilda.rhybar.0skar.cz", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED); test_hostname_lookup(bus, ".wilda.rhybar.0skar.cz", AF_INET, BUS_ERROR_DNSSEC_FAILED); /* Invalid signature, ECDSA, wildcard */ test_rr_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED); test_hostname_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", AF_INET, BUS_ERROR_DNSSEC_FAILED); /* NXDOMAIN in NSEC domain */ test_rr_lookup(bus, "hhh.nasa.gov", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN"); test_hostname_lookup(bus, "hhh.nasa.gov", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN"); /* wildcard, NSEC zone */ test_rr_lookup(bus, ".wilda.nsec.0skar.cz", DNS_TYPE_A, NULL); test_hostname_lookup(bus, ".wilda.nsec.0skar.cz", AF_INET, NULL); /* wildcard, NSEC zone, NODATA */ test_rr_lookup(bus, ".wilda.nsec.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR); /* wildcard, NSEC3 zone */ test_rr_lookup(bus, ".wilda.0skar.cz", DNS_TYPE_A, NULL); test_hostname_lookup(bus, ".wilda.0skar.cz", AF_INET, NULL); /* wildcard, NSEC3 zone, NODATA */ test_rr_lookup(bus, ".wilda.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR); /* wildcard, NSEC zone, CNAME */ test_rr_lookup(bus, ".wild.nsec.0skar.cz", DNS_TYPE_A, NULL); test_hostname_lookup(bus, ".wild.nsec.0skar.cz", AF_UNSPEC, NULL); test_hostname_lookup(bus, ".wild.nsec.0skar.cz", AF_INET, NULL); /* wildcard, NSEC zone, NODATA, CNAME */ test_rr_lookup(bus, ".wild.nsec.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR); /* wildcard, NSEC3 zone, CNAME */ test_rr_lookup(bus, ".wild.0skar.cz", DNS_TYPE_A, NULL); test_hostname_lookup(bus, ".wild.0skar.cz", AF_UNSPEC, NULL); test_hostname_lookup(bus, ".wild.0skar.cz", AF_INET, NULL); /* wildcard, NSEC3 zone, NODATA, CNAME */ test_rr_lookup(bus, ".wild.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR); /* NODATA due to empty non-terminal in NSEC domain */ test_rr_lookup(bus, "herndon.nasa.gov", DNS_TYPE_A, BUS_ERROR_NO_SUCH_RR); test_hostname_lookup(bus, "herndon.nasa.gov", AF_UNSPEC, BUS_ERROR_NO_SUCH_RR); test_hostname_lookup(bus, "herndon.nasa.gov", AF_INET, BUS_ERROR_NO_SUCH_RR); test_hostname_lookup(bus, "herndon.nasa.gov", AF_INET6, BUS_ERROR_NO_SUCH_RR); /* NXDOMAIN in NSEC root zone: */ test_rr_lookup(bus, "jasdhjas.kjkfgjhfjg", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN"); test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN"); test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_INET, _BUS_ERROR_DNS "NXDOMAIN"); test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN"); /* NXDOMAIN in NSEC3 .com zone: */ test_rr_lookup(bus, "kjkfgjhfjgsdfdsfd.com", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN"); test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_INET, _BUS_ERROR_DNS "NXDOMAIN"); test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN"); test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN"); /* Unsigned A */ test_rr_lookup(bus, "poettering.de", DNS_TYPE_A, NULL); test_rr_lookup(bus, "poettering.de", DNS_TYPE_AAAA, NULL); test_hostname_lookup(bus, "poettering.de", AF_UNSPEC, NULL); test_hostname_lookup(bus, "poettering.de", AF_INET, NULL); test_hostname_lookup(bus, "poettering.de", AF_INET6, NULL); #ifdef HAVE_LIBIDN /* Unsigned A with IDNA conversion necessary */ test_hostname_lookup(bus, "pöttering.de", AF_UNSPEC, NULL); test_hostname_lookup(bus, "pöttering.de", AF_INET, NULL); test_hostname_lookup(bus, "pöttering.de", AF_INET6, NULL); #endif /* DNAME, pointing to NXDOMAIN */ test_rr_lookup(bus, ".ireallyhpoethisdoesnexist.xn--kprw13d.", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN"); test_rr_lookup(bus, ".ireallyhpoethisdoesnexist.xn--kprw13d.", DNS_TYPE_RP, _BUS_ERROR_DNS "NXDOMAIN"); test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN"); test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_INET, _BUS_ERROR_DNS "NXDOMAIN"); test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN"); return 0; } systemd-229/src/resolve/test-dnssec.c000066400000000000000000000410771265713322000177400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "resolved-dns-dnssec.h" #include "resolved-dns-rr.h" #include "string-util.h" #include "hexdecoct.h" static void test_dnssec_verify_rrset2(void) { static const uint8_t signature_blob[] = { 0x48, 0x45, 0xc8, 0x8b, 0xc0, 0x14, 0x92, 0xf5, 0x15, 0xc6, 0x84, 0x9d, 0x2f, 0xe3, 0x32, 0x11, 0x7d, 0xf1, 0xe6, 0x87, 0xb9, 0x42, 0xd3, 0x8b, 0x9e, 0xaf, 0x92, 0x31, 0x0a, 0x53, 0xad, 0x8b, 0xa7, 0x5c, 0x83, 0x39, 0x8c, 0x28, 0xac, 0xce, 0x6e, 0x9c, 0x18, 0xe3, 0x31, 0x16, 0x6e, 0xca, 0x38, 0x31, 0xaf, 0xd9, 0x94, 0xf1, 0x84, 0xb1, 0xdf, 0x5a, 0xc2, 0x73, 0x22, 0xf6, 0xcb, 0xa2, 0xe7, 0x8c, 0x77, 0x0c, 0x74, 0x2f, 0xc2, 0x13, 0xb0, 0x93, 0x51, 0xa9, 0x4f, 0xae, 0x0a, 0xda, 0x45, 0xcc, 0xfd, 0x43, 0x99, 0x36, 0x9a, 0x0d, 0x21, 0xe0, 0xeb, 0x30, 0x65, 0xd4, 0xa0, 0x27, 0x37, 0x3b, 0xe4, 0xc1, 0xc5, 0xa1, 0x2a, 0xd1, 0x76, 0xc4, 0x7e, 0x64, 0x0e, 0x5a, 0xa6, 0x50, 0x24, 0xd5, 0x2c, 0xcc, 0x6d, 0xe5, 0x37, 0xea, 0xbd, 0x09, 0x34, 0xed, 0x24, 0x06, 0xa1, 0x22, }; static const uint8_t dnskey_blob[] = { 0x03, 0x01, 0x00, 0x01, 0xc3, 0x7f, 0x1d, 0xd1, 0x1c, 0x97, 0xb1, 0x13, 0x34, 0x3a, 0x9a, 0xea, 0xee, 0xd9, 0x5a, 0x11, 0x1b, 0x17, 0xc7, 0xe3, 0xd4, 0xda, 0x20, 0xbc, 0x5d, 0xba, 0x74, 0xe3, 0x37, 0x99, 0xec, 0x25, 0xce, 0x93, 0x7f, 0xbd, 0x22, 0x73, 0x7e, 0x14, 0x71, 0xe0, 0x60, 0x07, 0xd4, 0x39, 0x8b, 0x5e, 0xe9, 0xba, 0x25, 0xe8, 0x49, 0xe9, 0x34, 0xef, 0xfe, 0x04, 0x5c, 0xa5, 0x27, 0xcd, 0xa9, 0xda, 0x70, 0x05, 0x21, 0xab, 0x15, 0x82, 0x24, 0xc3, 0x94, 0xf5, 0xd7, 0xb7, 0xc4, 0x66, 0xcb, 0x32, 0x6e, 0x60, 0x2b, 0x55, 0x59, 0x28, 0x89, 0x8a, 0x72, 0xde, 0x88, 0x56, 0x27, 0x95, 0xd9, 0xac, 0x88, 0x4f, 0x65, 0x2b, 0x68, 0xfc, 0xe6, 0x41, 0xc1, 0x1b, 0xef, 0x4e, 0xd6, 0xc2, 0x0f, 0x64, 0x88, 0x95, 0x5e, 0xdd, 0x3a, 0x02, 0x07, 0x50, 0xa9, 0xda, 0xa4, 0x49, 0x74, 0x62, 0xfe, 0xd7, }; _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *nsec = NULL, *rrsig = NULL, *dnskey = NULL; _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; DnssecResult result; nsec = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_NSEC, "nasa.gov"); assert_se(nsec); nsec->nsec.next_domain_name = strdup("3D-Printing.nasa.gov"); assert_se(nsec->nsec.next_domain_name); nsec->nsec.types = bitmap_new(); assert_se(nsec->nsec.types); assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_A) >= 0); assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_NS) >= 0); assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_SOA) >= 0); assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_MX) >= 0); assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_TXT) >= 0); assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_RRSIG) >= 0); assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_NSEC) >= 0); assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_DNSKEY) >= 0); assert_se(bitmap_set(nsec->nsec.types, 65534) >= 0); log_info("NSEC: %s", strna(dns_resource_record_to_string(nsec))); rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV."); assert_se(rrsig); rrsig->rrsig.type_covered = DNS_TYPE_NSEC; rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_RSASHA256; rrsig->rrsig.labels = 2; rrsig->rrsig.original_ttl = 300; rrsig->rrsig.expiration = 0x5689002f; rrsig->rrsig.inception = 0x56617230; rrsig->rrsig.key_tag = 30390; rrsig->rrsig.signer = strdup("Nasa.Gov."); assert_se(rrsig->rrsig.signer); rrsig->rrsig.signature_size = sizeof(signature_blob); rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size); assert_se(rrsig->rrsig.signature); log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig))); dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV"); assert_se(dnskey); dnskey->dnskey.flags = 256; dnskey->dnskey.protocol = 3; dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256; dnskey->dnskey.key_size = sizeof(dnskey_blob); dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob)); assert_se(dnskey->dnskey.key); log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey))); log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false)); assert_se(dnssec_key_match_rrsig(nsec->key, rrsig) > 0); assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0); answer = dns_answer_new(1); assert_se(answer); assert_se(dns_answer_add(answer, nsec, 0, DNS_ANSWER_AUTHENTICATED) >= 0); /* Validate the RR as it if was 2015-12-11 today */ assert_se(dnssec_verify_rrset(answer, nsec->key, rrsig, dnskey, 1449849318*USEC_PER_SEC, &result) >= 0); assert_se(result == DNSSEC_VALIDATED); } static void test_dnssec_verify_rrset(void) { static const uint8_t signature_blob[] = { 0x7f, 0x79, 0xdd, 0x5e, 0x89, 0x79, 0x18, 0xd0, 0x34, 0x86, 0x8c, 0x72, 0x77, 0x75, 0x48, 0x4d, 0xc3, 0x7d, 0x38, 0x04, 0xab, 0xcd, 0x9e, 0x4c, 0x82, 0xb0, 0x92, 0xca, 0xe9, 0x66, 0xe9, 0x6e, 0x47, 0xc7, 0x68, 0x8c, 0x94, 0xf6, 0x69, 0xcb, 0x75, 0x94, 0xe6, 0x30, 0xa6, 0xfb, 0x68, 0x64, 0x96, 0x1a, 0x84, 0xe1, 0xdc, 0x16, 0x4c, 0x83, 0x6c, 0x44, 0xf2, 0x74, 0x4d, 0x74, 0x79, 0x8f, 0xf3, 0xf4, 0x63, 0x0d, 0xef, 0x5a, 0xe7, 0xe2, 0xfd, 0xf2, 0x2b, 0x38, 0x7c, 0x28, 0x96, 0x9d, 0xb6, 0xcd, 0x5c, 0x3b, 0x57, 0xe2, 0x24, 0x78, 0x65, 0xd0, 0x9e, 0x77, 0x83, 0x09, 0x6c, 0xff, 0x3d, 0x52, 0x3f, 0x6e, 0xd1, 0xed, 0x2e, 0xf9, 0xee, 0x8e, 0xa6, 0xbe, 0x9a, 0xa8, 0x87, 0x76, 0xd8, 0x77, 0xcc, 0x96, 0xa0, 0x98, 0xa1, 0xd1, 0x68, 0x09, 0x43, 0xcf, 0x56, 0xd9, 0xd1, 0x66, }; static const uint8_t dnskey_blob[] = { 0x03, 0x01, 0x00, 0x01, 0x9b, 0x49, 0x9b, 0xc1, 0xf9, 0x9a, 0xe0, 0x4e, 0xcf, 0xcb, 0x14, 0x45, 0x2e, 0xc9, 0xf9, 0x74, 0xa7, 0x18, 0xb5, 0xf3, 0xde, 0x39, 0x49, 0xdf, 0x63, 0x33, 0x97, 0x52, 0xe0, 0x8e, 0xac, 0x50, 0x30, 0x8e, 0x09, 0xd5, 0x24, 0x3d, 0x26, 0xa4, 0x49, 0x37, 0x2b, 0xb0, 0x6b, 0x1b, 0xdf, 0xde, 0x85, 0x83, 0xcb, 0x22, 0x4e, 0x60, 0x0a, 0x91, 0x1a, 0x1f, 0xc5, 0x40, 0xb1, 0xc3, 0x15, 0xc1, 0x54, 0x77, 0x86, 0x65, 0x53, 0xec, 0x10, 0x90, 0x0c, 0x91, 0x00, 0x5e, 0x15, 0xdc, 0x08, 0x02, 0x4c, 0x8c, 0x0d, 0xc0, 0xac, 0x6e, 0xc4, 0x3e, 0x1b, 0x80, 0x19, 0xe4, 0xf7, 0x5f, 0x77, 0x51, 0x06, 0x87, 0x61, 0xde, 0xa2, 0x18, 0x0f, 0x40, 0x8b, 0x79, 0x72, 0xfa, 0x8d, 0x1a, 0x44, 0x47, 0x0d, 0x8e, 0x3a, 0x2d, 0xc7, 0x39, 0xbf, 0x56, 0x28, 0x97, 0xd9, 0x20, 0x4f, 0x00, 0x51, 0x3b, }; _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *a = NULL, *rrsig = NULL, *dnskey = NULL; _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; DnssecResult result; a = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, "nAsA.gov"); assert_se(a); a->a.in_addr.s_addr = inet_addr("52.0.14.116"); log_info("A: %s", strna(dns_resource_record_to_string(a))); rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV."); assert_se(rrsig); rrsig->rrsig.type_covered = DNS_TYPE_A; rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_RSASHA256; rrsig->rrsig.labels = 2; rrsig->rrsig.original_ttl = 600; rrsig->rrsig.expiration = 0x5683135c; rrsig->rrsig.inception = 0x565b7da8; rrsig->rrsig.key_tag = 63876; rrsig->rrsig.signer = strdup("Nasa.Gov."); assert_se(rrsig->rrsig.signer); rrsig->rrsig.signature_size = sizeof(signature_blob); rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size); assert_se(rrsig->rrsig.signature); log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig))); dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV"); assert_se(dnskey); dnskey->dnskey.flags = 256; dnskey->dnskey.protocol = 3; dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256; dnskey->dnskey.key_size = sizeof(dnskey_blob); dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob)); assert_se(dnskey->dnskey.key); log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey))); log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false)); assert_se(dnssec_key_match_rrsig(a->key, rrsig) > 0); assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0); answer = dns_answer_new(1); assert_se(answer); assert_se(dns_answer_add(answer, a, 0, DNS_ANSWER_AUTHENTICATED) >= 0); /* Validate the RR as it if was 2015-12-2 today */ assert_se(dnssec_verify_rrset(answer, a->key, rrsig, dnskey, 1449092754*USEC_PER_SEC, &result) >= 0); assert_se(result == DNSSEC_VALIDATED); } static void test_dnssec_verify_dns_key(void) { static const uint8_t ds1_fprint[] = { 0x46, 0x8B, 0xC8, 0xDD, 0xC7, 0xE8, 0x27, 0x03, 0x40, 0xBB, 0x8A, 0x1F, 0x3B, 0x2E, 0x45, 0x9D, 0x80, 0x67, 0x14, 0x01, }; static const uint8_t ds2_fprint[] = { 0x8A, 0xEE, 0x80, 0x47, 0x05, 0x5F, 0x83, 0xD1, 0x48, 0xBA, 0x8F, 0xF6, 0xDD, 0xA7, 0x60, 0xCE, 0x94, 0xF7, 0xC7, 0x5E, 0x52, 0x4C, 0xF2, 0xE9, 0x50, 0xB9, 0x2E, 0xCB, 0xEF, 0x96, 0xB9, 0x98, }; static const uint8_t dnskey_blob[] = { 0x03, 0x01, 0x00, 0x01, 0xa8, 0x12, 0xda, 0x4f, 0xd2, 0x7d, 0x54, 0x14, 0x0e, 0xcc, 0x5b, 0x5e, 0x45, 0x9c, 0x96, 0x98, 0xc0, 0xc0, 0x85, 0x81, 0xb1, 0x47, 0x8c, 0x7d, 0xe8, 0x39, 0x50, 0xcc, 0xc5, 0xd0, 0xf2, 0x00, 0x81, 0x67, 0x79, 0xf6, 0xcc, 0x9d, 0xad, 0x6c, 0xbb, 0x7b, 0x6f, 0x48, 0x97, 0x15, 0x1c, 0xfd, 0x0b, 0xfe, 0xd3, 0xd7, 0x7d, 0x9f, 0x81, 0x26, 0xd3, 0xc5, 0x65, 0x49, 0xcf, 0x46, 0x62, 0xb0, 0x55, 0x6e, 0x47, 0xc7, 0x30, 0xef, 0x51, 0xfb, 0x3e, 0xc6, 0xef, 0xde, 0x27, 0x3f, 0xfa, 0x57, 0x2d, 0xa7, 0x1d, 0x80, 0x46, 0x9a, 0x5f, 0x14, 0xb3, 0xb0, 0x2c, 0xbe, 0x72, 0xca, 0xdf, 0xb2, 0xff, 0x36, 0x5b, 0x4f, 0xec, 0x58, 0x8e, 0x8d, 0x01, 0xe9, 0xa9, 0xdf, 0xb5, 0x60, 0xad, 0x52, 0x4d, 0xfc, 0xa9, 0x3e, 0x8d, 0x35, 0x95, 0xb3, 0x4e, 0x0f, 0xca, 0x45, 0x1b, 0xf7, 0xef, 0x3a, 0x88, 0x25, 0x08, 0xc7, 0x4e, 0x06, 0xc1, 0x62, 0x1a, 0xce, 0xd8, 0x77, 0xbd, 0x02, 0x65, 0xf8, 0x49, 0xfb, 0xce, 0xf6, 0xa8, 0x09, 0xfc, 0xde, 0xb2, 0x09, 0x9d, 0x39, 0xf8, 0x63, 0x9c, 0x32, 0x42, 0x7c, 0xa0, 0x30, 0x86, 0x72, 0x7a, 0x4a, 0xc6, 0xd4, 0xb3, 0x2d, 0x24, 0xef, 0x96, 0x3f, 0xc2, 0xda, 0xd3, 0xf2, 0x15, 0x6f, 0xda, 0x65, 0x4b, 0x81, 0x28, 0x68, 0xf4, 0xfe, 0x3e, 0x71, 0x4f, 0x50, 0x96, 0x72, 0x58, 0xa1, 0x89, 0xdd, 0x01, 0x61, 0x39, 0x39, 0xc6, 0x76, 0xa4, 0xda, 0x02, 0x70, 0x3d, 0xc0, 0xdc, 0x8d, 0x70, 0x72, 0x04, 0x90, 0x79, 0xd4, 0xec, 0x65, 0xcf, 0x49, 0x35, 0x25, 0x3a, 0x14, 0x1a, 0x45, 0x20, 0xeb, 0x31, 0xaf, 0x92, 0xba, 0x20, 0xd3, 0xcd, 0xa7, 0x13, 0x44, 0xdc, 0xcf, 0xf0, 0x27, 0x34, 0xb9, 0xe7, 0x24, 0x6f, 0x73, 0xe7, 0xea, 0x77, 0x03, }; _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds1 = NULL, *ds2 = NULL; /* The two DS RRs in effect for nasa.gov on 2015-12-01. */ ds1 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "nasa.gov"); assert_se(ds1); ds1->ds.key_tag = 47857; ds1->ds.algorithm = DNSSEC_ALGORITHM_RSASHA256; ds1->ds.digest_type = DNSSEC_DIGEST_SHA1; ds1->ds.digest_size = sizeof(ds1_fprint); ds1->ds.digest = memdup(ds1_fprint, ds1->ds.digest_size); assert_se(ds1->ds.digest); log_info("DS1: %s", strna(dns_resource_record_to_string(ds1))); ds2 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "NASA.GOV"); assert_se(ds2); ds2->ds.key_tag = 47857; ds2->ds.algorithm = DNSSEC_ALGORITHM_RSASHA256; ds2->ds.digest_type = DNSSEC_DIGEST_SHA256; ds2->ds.digest_size = sizeof(ds2_fprint); ds2->ds.digest = memdup(ds2_fprint, ds2->ds.digest_size); assert_se(ds2->ds.digest); log_info("DS2: %s", strna(dns_resource_record_to_string(ds2))); dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nasa.GOV"); assert_se(dnskey); dnskey->dnskey.flags = 257; dnskey->dnskey.protocol = 3; dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256; dnskey->dnskey.key_size = sizeof(dnskey_blob); dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob)); assert_se(dnskey->dnskey.key); log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey))); log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false)); assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds1, false) > 0); assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds2, false) > 0); } static void test_dnssec_canonicalize_one(const char *original, const char *canonical, int r) { char canonicalized[DNSSEC_CANONICAL_HOSTNAME_MAX]; assert_se(dnssec_canonicalize(original, canonicalized, sizeof(canonicalized)) == r); if (r < 0) return; assert_se(streq(canonicalized, canonical)); } static void test_dnssec_canonicalize(void) { test_dnssec_canonicalize_one("", ".", 1); test_dnssec_canonicalize_one(".", ".", 1); test_dnssec_canonicalize_one("foo", "foo.", 4); test_dnssec_canonicalize_one("foo.", "foo.", 4); test_dnssec_canonicalize_one("FOO.", "foo.", 4); test_dnssec_canonicalize_one("FOO.bar.", "foo.bar.", 8); test_dnssec_canonicalize_one("FOO..bar.", NULL, -EINVAL); } static void test_dnssec_nsec3_hash(void) { static const uint8_t salt[] = { 0xB0, 0x1D, 0xFA, 0xCE }; static const uint8_t next_hashed_name[] = { 0x84, 0x10, 0x26, 0x53, 0xc9, 0xfa, 0x4d, 0x85, 0x6c, 0x97, 0x82, 0xe2, 0x8f, 0xdf, 0x2d, 0x5e, 0x87, 0x69, 0xc4, 0x52 }; _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; uint8_t h[DNSSEC_HASH_SIZE_MAX]; _cleanup_free_ char *b = NULL; int k; /* The NSEC3 RR for eurid.eu on 2015-12-14. */ rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_NSEC3, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM.eurid.eu."); assert_se(rr); rr->nsec3.algorithm = DNSSEC_DIGEST_SHA1; rr->nsec3.flags = 1; rr->nsec3.iterations = 1; rr->nsec3.salt = memdup(salt, sizeof(salt)); assert_se(rr->nsec3.salt); rr->nsec3.salt_size = sizeof(salt); rr->nsec3.next_hashed_name = memdup(next_hashed_name, sizeof(next_hashed_name)); assert_se(rr->nsec3.next_hashed_name); rr->nsec3.next_hashed_name_size = sizeof(next_hashed_name); log_info("NSEC3: %s", strna(dns_resource_record_to_string(rr))); k = dnssec_nsec3_hash(rr, "eurid.eu", &h); assert_se(k >= 0); b = base32hexmem(h, k, false); assert_se(b); assert_se(strcasecmp(b, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM") == 0); } int main(int argc, char*argv[]) { test_dnssec_canonicalize(); test_dnssec_verify_dns_key(); test_dnssec_verify_rrset(); test_dnssec_verify_rrset2(); test_dnssec_nsec3_hash(); return 0; } systemd-229/src/resolve/test-resolve-tables.c000066400000000000000000000015711265713322000214030ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "dns-type.h" #include "test-tables.h" int main(int argc, char **argv) { test_table_sparse(dns_type, DNS_TYPE); return EXIT_SUCCESS; } systemd-229/src/rfkill/000077500000000000000000000000001265713322000151335ustar00rootroot00000000000000systemd-229/src/rfkill/Makefile000077700000000000000000000000001265713322000204412../Makefileustar00rootroot00000000000000systemd-229/src/rfkill/rfkill.c000066400000000000000000000334061265713322000165700ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "libudev.h" #include "sd-daemon.h" #include "alloc-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "io-util.h" #include "mkdir.h" #include "parse-util.h" #include "proc-cmdline.h" #include "string-table.h" #include "string-util.h" #include "udev-util.h" #include "util.h" #define EXIT_USEC (5 * USEC_PER_SEC) static const char* const rfkill_type_table[NUM_RFKILL_TYPES] = { [RFKILL_TYPE_ALL] = "all", [RFKILL_TYPE_WLAN] = "wlan", [RFKILL_TYPE_BLUETOOTH] = "bluetooth", [RFKILL_TYPE_UWB] = "uwb", [RFKILL_TYPE_WIMAX] = "wimax", [RFKILL_TYPE_WWAN] = "wwan", [RFKILL_TYPE_GPS] = "gps", [RFKILL_TYPE_FM] = "fm", [RFKILL_TYPE_NFC] = "nfc", }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(rfkill_type, int); static int find_device( struct udev *udev, const struct rfkill_event *event, struct udev_device **ret) { _cleanup_free_ char *sysname = NULL; struct udev_device *device; const char *name; assert(udev); assert(event); assert(ret); if (asprintf(&sysname, "rfkill%i", event->idx) < 0) return log_oom(); device = udev_device_new_from_subsystem_sysname(udev, "rfkill", sysname); if (!device) return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open device: %m"); name = udev_device_get_sysattr_value(device, "name"); if (!name) { log_debug("Device has no name, ignoring."); udev_device_unref(device); return -ENOENT; } log_debug("Operating on rfkill device '%s'.", name); *ret = device; return 0; } static int wait_for_initialized( struct udev *udev, struct udev_device *device, struct udev_device **ret) { _cleanup_udev_monitor_unref_ struct udev_monitor *monitor = NULL; struct udev_device *d; const char *sysname; int watch_fd, r; assert(udev); assert(device); assert(ret); if (udev_device_get_is_initialized(device) != 0) { *ret = udev_device_ref(device); return 0; } assert_se(sysname = udev_device_get_sysname(device)); /* Wait until the device is initialized, so that we can get * access to the ID_PATH property */ monitor = udev_monitor_new_from_netlink(udev, "udev"); if (!monitor) return log_error_errno(errno, "Failed to acquire monitor: %m"); r = udev_monitor_filter_add_match_subsystem_devtype(monitor, "rfkill", NULL); if (r < 0) return log_error_errno(r, "Failed to add rfkill udev match to monitor: %m"); r = udev_monitor_enable_receiving(monitor); if (r < 0) return log_error_errno(r, "Failed to enable udev receiving: %m"); watch_fd = udev_monitor_get_fd(monitor); if (watch_fd < 0) return log_error_errno(watch_fd, "Failed to get watch fd: %m"); /* Check again, maybe things changed */ d = udev_device_new_from_subsystem_sysname(udev, "rfkill", sysname); if (!d) return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open device: %m"); if (udev_device_get_is_initialized(d) != 0) { *ret = d; return 0; } for (;;) { _cleanup_udev_device_unref_ struct udev_device *t = NULL; r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY); if (r == -EINTR) continue; if (r < 0) return log_error_errno(r, "Failed to watch udev monitor: %m"); t = udev_monitor_receive_device(monitor); if (!t) continue; if (streq_ptr(udev_device_get_sysname(device), sysname)) { *ret = udev_device_ref(t); return 0; } } } static int determine_state_file( struct udev *udev, const struct rfkill_event *event, struct udev_device *d, char **ret) { _cleanup_udev_device_unref_ struct udev_device *device = NULL; const char *path_id, *type; char *state_file; int r; assert(event); assert(d); assert(ret); r = wait_for_initialized(udev, d, &device); if (r < 0) return r; assert_se(type = rfkill_type_to_string(event->type)); path_id = udev_device_get_property_value(device, "ID_PATH"); if (path_id) { _cleanup_free_ char *escaped_path_id = NULL; escaped_path_id = cescape(path_id); if (!escaped_path_id) return log_oom(); state_file = strjoin("/var/lib/systemd/rfkill/", escaped_path_id, ":", type, NULL); } else state_file = strjoin("/var/lib/systemd/rfkill/", type, NULL); if (!state_file) return log_oom(); *ret = state_file; return 0; } static int load_state( int rfkill_fd, struct udev *udev, const struct rfkill_event *event) { _cleanup_udev_device_unref_ struct udev_device *device = NULL; _cleanup_free_ char *state_file = NULL, *value = NULL; struct rfkill_event we; ssize_t l; int b, r; assert(rfkill_fd >= 0); assert(udev); assert(event); if (shall_restore_state() == 0) return 0; r = find_device(udev, event, &device); if (r < 0) return r; r = determine_state_file(udev, event, device, &state_file); if (r < 0) return r; r = read_one_line_file(state_file, &value); if (r == -ENOENT) { /* No state file? Then save the current state */ r = write_string_file(state_file, one_zero(event->soft), WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC); if (r < 0) return log_error_errno(r, "Failed to write state file %s: %m", state_file); log_debug("Saved state '%s' to %s.", one_zero(event->soft), state_file); return 0; } if (r < 0) return log_error_errno(r, "Failed to read state file %s: %m", state_file); b = parse_boolean(value); if (b < 0) return log_error_errno(b, "Failed to parse state file %s: %m", state_file); we = (struct rfkill_event) { .op = RFKILL_OP_CHANGE, .idx = event->idx, .soft = b, }; l = write(rfkill_fd, &we, sizeof(we)); if (l < 0) return log_error_errno(errno, "Failed to restore rfkill state for %i: %m", event->idx); if (l != sizeof(we)) { log_error("Couldn't write rfkill event structure, too short."); return -EIO; } log_debug("Loaded state '%s' from %s.", one_zero(b), state_file); return 0; } static int save_state( int rfkill_fd, struct udev *udev, const struct rfkill_event *event) { _cleanup_udev_device_unref_ struct udev_device *device = NULL; _cleanup_free_ char *state_file = NULL; int r; assert(rfkill_fd >= 0); assert(udev); assert(event); r = find_device(udev, event, &device); if (r < 0) return r; r = determine_state_file(udev, event, device, &state_file); if (r < 0) return r; r = write_string_file(state_file, one_zero(event->soft), WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC); if (r < 0) return log_error_errno(r, "Failed to write state file %s: %m", state_file); log_debug("Saved state '%s' to %s.", one_zero(event->soft), state_file); return 0; } int main(int argc, char *argv[]) { _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_close_ int rfkill_fd = -1; bool ready = false; int r, n; if (argc > 1) { log_error("This program requires no arguments."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); udev = udev_new(); if (!udev) { r = log_oom(); goto finish; } r = mkdir_p("/var/lib/systemd/rfkill", 0755); if (r < 0) { log_error_errno(r, "Failed to create rfkill directory: %m"); goto finish; } n = sd_listen_fds(false); if (n < 0) { r = log_error_errno(n, "Failed to determine whether we got any file descriptors passed: %m"); goto finish; } if (n > 1) { log_error("Got too many file descriptors."); r = -EINVAL; goto finish; } if (n == 0) { rfkill_fd = open("/dev/rfkill", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); if (rfkill_fd < 0) { if (errno == ENOENT) { log_debug_errno(errno, "Missing rfkill subsystem, or no device present, exiting."); r = 0; goto finish; } r = log_error_errno(errno, "Failed to open /dev/rfkill: %m"); goto finish; } } else { rfkill_fd = SD_LISTEN_FDS_START; r = fd_nonblock(rfkill_fd, 1); if (r < 0) { log_error_errno(r, "Failed to make /dev/rfkill socket non-blocking: %m"); goto finish; } } for (;;) { struct rfkill_event event; const char *type; ssize_t l; l = read(rfkill_fd, &event, sizeof(event)); if (l < 0) { if (errno == EAGAIN) { if (!ready) { /* Notify manager that we are * now finished with * processing whatever was * queued */ (void) sd_notify(false, "READY=1"); ready = true; } /* Hang around for a bit, maybe there's more coming */ r = fd_wait_for_event(rfkill_fd, POLLIN, EXIT_USEC); if (r == -EINTR) continue; if (r < 0) { log_error_errno(r, "Failed to poll() on device: %m"); goto finish; } if (r > 0) continue; log_debug("All events read and idle, exiting."); break; } log_error_errno(errno, "Failed to read from /dev/rfkill: %m"); } if (l != RFKILL_EVENT_SIZE_V1) { log_error("Read event structure of invalid size."); r = -EIO; goto finish; } type = rfkill_type_to_string(event.type); if (!type) { log_debug("An rfkill device of unknown type %i discovered, ignoring.", event.type); continue; } switch (event.op) { case RFKILL_OP_ADD: log_debug("A new rfkill device has been added with index %i and type %s.", event.idx, type); (void) load_state(rfkill_fd, udev, &event); break; case RFKILL_OP_DEL: log_debug("An rfkill device has been removed with index %i and type %s", event.idx, type); break; case RFKILL_OP_CHANGE: log_debug("An rfkill device has changed state with index %i and type %s", event.idx, type); (void) save_state(rfkill_fd, udev, &event); break; default: log_debug("Unknown event %i from /dev/rfkill for index %i and type %s, ignoring.", event.op, event.idx, type); break; } } r = 0; finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/run/000077500000000000000000000000001265713322000144545ustar00rootroot00000000000000systemd-229/src/run/Makefile000077700000000000000000000000001265713322000177622../Makefileustar00rootroot00000000000000systemd-229/src/run/run.c000066400000000000000000001257001265713322000154310ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-bus.h" #include "sd-event.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "calendarspec.h" #include "env-util.h" #include "fd-util.h" #include "formats-util.h" #include "parse-util.h" #include "path-util.h" #include "ptyfwd.h" #include "signal-util.h" #include "spawn-polkit-agent.h" #include "strv.h" #include "terminal-util.h" #include "unit-name.h" #include "user-util.h" static bool arg_ask_password = true; static bool arg_scope = false; static bool arg_remain_after_exit = false; static bool arg_no_block = false; static const char *arg_unit = NULL; static const char *arg_description = NULL; static const char *arg_slice = NULL; static bool arg_send_sighup = false; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static const char *arg_host = NULL; static bool arg_user = false; static const char *arg_service_type = NULL; static const char *arg_exec_user = NULL; static const char *arg_exec_group = NULL; static int arg_nice = 0; static bool arg_nice_set = false; static char **arg_environment = NULL; static char **arg_property = NULL; static bool arg_pty = false; static usec_t arg_on_active = 0; static usec_t arg_on_boot = 0; static usec_t arg_on_startup = 0; static usec_t arg_on_unit_active = 0; static usec_t arg_on_unit_inactive = 0; static const char *arg_on_calendar = NULL; static char **arg_timer_property = NULL; static bool arg_quiet = false; static void polkit_agent_open_if_enabled(void) { /* Open the polkit agent as a child process if necessary */ if (!arg_ask_password) return; if (arg_transport != BUS_TRANSPORT_LOCAL) return; polkit_agent_open(); } static void help(void) { printf("%s [OPTIONS...] {COMMAND} [ARGS...]\n\n" "Run the specified command in a transient scope or service or timer\n" "unit. If timer option is specified and unit is exist which is\n" "specified with --unit option then command can be omitted.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --no-ask-password Do not prompt for password\n" " --user Run as user unit\n" " -H --host=[USER@]HOST Operate on remote host\n" " -M --machine=CONTAINER Operate on local container\n" " --scope Run this as scope rather than service\n" " --unit=UNIT Run under the specified unit name\n" " -p --property=NAME=VALUE Set unit property\n" " --description=TEXT Description for unit\n" " --slice=SLICE Run in the specified slice\n" " --no-block Do not wait until operation finished\n" " -r --remain-after-exit Leave service around until explicitly stopped\n" " --send-sighup Send SIGHUP when terminating\n" " --service-type=TYPE Service type\n" " --uid=USER Run as system user\n" " --gid=GROUP Run as system group\n" " --nice=NICE Nice level\n" " --setenv=NAME=VALUE Set environment\n" " -t --pty Run service on pseudo tty\n" " -q --quiet Suppress information messages during runtime\n\n" "Timer options:\n\n" " --on-active=SECONDS Run after SECONDS delay\n" " --on-boot=SECONDS Run SECONDS after machine was booted up\n" " --on-startup=SECONDS Run SECONDS after systemd activation\n" " --on-unit-active=SECONDS Run SECONDS after the last activation\n" " --on-unit-inactive=SECONDS Run SECONDS after the last deactivation\n" " --on-calendar=SPEC Realtime timer\n" " --timer-property=NAME=VALUE Set timer unit property\n", program_invocation_short_name); } static bool with_timer(void) { return arg_on_active || arg_on_boot || arg_on_startup || arg_on_unit_active || arg_on_unit_inactive || arg_on_calendar; } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_NO_ASK_PASSWORD, ARG_USER, ARG_SYSTEM, ARG_SCOPE, ARG_UNIT, ARG_DESCRIPTION, ARG_SLICE, ARG_SEND_SIGHUP, ARG_EXEC_USER, ARG_EXEC_GROUP, ARG_SERVICE_TYPE, ARG_NICE, ARG_SETENV, ARG_TTY, ARG_ON_ACTIVE, ARG_ON_BOOT, ARG_ON_STARTUP, ARG_ON_UNIT_ACTIVE, ARG_ON_UNIT_INACTIVE, ARG_ON_CALENDAR, ARG_TIMER_PROPERTY, ARG_NO_BLOCK, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "user", no_argument, NULL, ARG_USER }, { "system", no_argument, NULL, ARG_SYSTEM }, { "scope", no_argument, NULL, ARG_SCOPE }, { "unit", required_argument, NULL, ARG_UNIT }, { "description", required_argument, NULL, ARG_DESCRIPTION }, { "slice", required_argument, NULL, ARG_SLICE }, { "remain-after-exit", no_argument, NULL, 'r' }, { "send-sighup", no_argument, NULL, ARG_SEND_SIGHUP }, { "host", required_argument, NULL, 'H' }, { "machine", required_argument, NULL, 'M' }, { "service-type", required_argument, NULL, ARG_SERVICE_TYPE }, { "uid", required_argument, NULL, ARG_EXEC_USER }, { "gid", required_argument, NULL, ARG_EXEC_GROUP }, { "nice", required_argument, NULL, ARG_NICE }, { "setenv", required_argument, NULL, ARG_SETENV }, { "property", required_argument, NULL, 'p' }, { "tty", no_argument, NULL, 't' }, { "quiet", no_argument, NULL, 'q' }, { "on-active", required_argument, NULL, ARG_ON_ACTIVE }, { "on-boot", required_argument, NULL, ARG_ON_BOOT }, { "on-startup", required_argument, NULL, ARG_ON_STARTUP }, { "on-unit-active", required_argument, NULL, ARG_ON_UNIT_ACTIVE }, { "on-unit-inactive", required_argument, NULL, ARG_ON_UNIT_INACTIVE }, { "on-calendar", required_argument, NULL, ARG_ON_CALENDAR }, { "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY }, { "no-block", no_argument, NULL, ARG_NO_BLOCK }, { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, {}, }; int r, c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "+hrH:M:p:tq", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_NO_ASK_PASSWORD: arg_ask_password = false; break; case ARG_VERSION: return version(); case ARG_USER: arg_user = true; break; case ARG_SYSTEM: arg_user = false; break; case ARG_SCOPE: arg_scope = true; break; case ARG_UNIT: arg_unit = optarg; break; case ARG_DESCRIPTION: arg_description = optarg; break; case ARG_SLICE: arg_slice = optarg; break; case ARG_SEND_SIGHUP: arg_send_sighup = true; break; case 'r': arg_remain_after_exit = true; break; case 'H': arg_transport = BUS_TRANSPORT_REMOTE; arg_host = optarg; break; case 'M': arg_transport = BUS_TRANSPORT_MACHINE; arg_host = optarg; break; case ARG_SERVICE_TYPE: arg_service_type = optarg; break; case ARG_EXEC_USER: arg_exec_user = optarg; break; case ARG_EXEC_GROUP: arg_exec_group = optarg; break; case ARG_NICE: r = safe_atoi(optarg, &arg_nice); if (r < 0 || arg_nice < PRIO_MIN || arg_nice >= PRIO_MAX) { log_error("Failed to parse nice value"); return -EINVAL; } arg_nice_set = true; break; case ARG_SETENV: if (strv_extend(&arg_environment, optarg) < 0) return log_oom(); break; case 'p': if (strv_extend(&arg_property, optarg) < 0) return log_oom(); break; case 't': arg_pty = true; break; case 'q': arg_quiet = true; break; case ARG_ON_ACTIVE: r = parse_sec(optarg, &arg_on_active); if (r < 0) { log_error("Failed to parse timer value: %s", optarg); return r; } break; case ARG_ON_BOOT: r = parse_sec(optarg, &arg_on_boot); if (r < 0) { log_error("Failed to parse timer value: %s", optarg); return r; } break; case ARG_ON_STARTUP: r = parse_sec(optarg, &arg_on_startup); if (r < 0) { log_error("Failed to parse timer value: %s", optarg); return r; } break; case ARG_ON_UNIT_ACTIVE: r = parse_sec(optarg, &arg_on_unit_active); if (r < 0) { log_error("Failed to parse timer value: %s", optarg); return r; } break; case ARG_ON_UNIT_INACTIVE: r = parse_sec(optarg, &arg_on_unit_inactive); if (r < 0) { log_error("Failed to parse timer value: %s", optarg); return r; } break; case ARG_ON_CALENDAR: { CalendarSpec *spec = NULL; r = calendar_spec_from_string(optarg, &spec); if (r < 0) { log_error("Invalid calendar spec: %s", optarg); return r; } calendar_spec_free(spec); arg_on_calendar = optarg; break; } case ARG_TIMER_PROPERTY: if (strv_extend(&arg_timer_property, optarg) < 0) return log_oom(); break; case ARG_NO_BLOCK: arg_no_block = true; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if ((optind >= argc) && (!arg_unit || !with_timer())) { log_error("Command line to execute required."); return -EINVAL; } if (arg_user && arg_transport != BUS_TRANSPORT_LOCAL) { log_error("Execution in user context is not supported on non-local systems."); return -EINVAL; } if (arg_scope && arg_transport != BUS_TRANSPORT_LOCAL) { log_error("Scope execution is not supported on non-local systems."); return -EINVAL; } if (arg_scope && (arg_remain_after_exit || arg_service_type)) { log_error("--remain-after-exit and --service-type= are not supported in --scope mode."); return -EINVAL; } if (arg_pty && (with_timer() || arg_scope)) { log_error("--pty is not compatible in timer or --scope mode."); return -EINVAL; } if (arg_pty && arg_transport == BUS_TRANSPORT_REMOTE) { log_error("--pty is only supported when connecting to the local system or containers."); return -EINVAL; } if (arg_scope && with_timer()) { log_error("Timer options are not supported in --scope mode."); return -EINVAL; } if (arg_timer_property && !with_timer()) { log_error("--timer-property= has no effect without any other timer options."); return -EINVAL; } return 1; } static int transient_unit_set_properties(sd_bus_message *m, char **properties) { char **i; int r; r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description); if (r < 0) return r; STRV_FOREACH(i, properties) { r = bus_append_unit_property_assignment(m, *i); if (r < 0) return r; } return 0; } static int transient_cgroup_set_properties(sd_bus_message *m) { int r; assert(m); if (!isempty(arg_slice)) { _cleanup_free_ char *slice; r = unit_name_mangle_with_suffix(arg_slice, UNIT_NAME_NOGLOB, ".slice", &slice); if (r < 0) return r; r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice); if (r < 0) return r; } return 0; } static int transient_kill_set_properties(sd_bus_message *m) { assert(m); if (arg_send_sighup) return sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup); else return 0; } static int transient_service_set_properties(sd_bus_message *m, char **argv, const char *pty_path) { int r; assert(m); r = transient_unit_set_properties(m, arg_property); if (r < 0) return r; r = transient_kill_set_properties(m); if (r < 0) return r; r = transient_cgroup_set_properties(m); if (r < 0) return r; if (arg_remain_after_exit) { r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit); if (r < 0) return r; } if (arg_service_type) { r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_service_type); if (r < 0) return r; } if (arg_exec_user) { r = sd_bus_message_append(m, "(sv)", "User", "s", arg_exec_user); if (r < 0) return r; } if (arg_exec_group) { r = sd_bus_message_append(m, "(sv)", "Group", "s", arg_exec_group); if (r < 0) return r; } if (arg_nice_set) { r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice); if (r < 0) return r; } if (pty_path) { const char *e; r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)", "StandardInput", "s", "tty", "StandardOutput", "s", "tty", "StandardError", "s", "tty", "TTYPath", "s", pty_path); if (r < 0) return r; e = getenv("TERM"); if (e) { char *n; n = strjoina("TERM=", e); r = sd_bus_message_append(m, "(sv)", "Environment", "as", 1, n); if (r < 0) return r; } } if (!strv_isempty(arg_environment)) { r = sd_bus_message_open_container(m, 'r', "sv"); if (r < 0) return r; r = sd_bus_message_append(m, "s", "Environment"); if (r < 0) return r; r = sd_bus_message_open_container(m, 'v', "as"); if (r < 0) return r; r = sd_bus_message_append_strv(m, arg_environment); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; } /* Exec container */ { r = sd_bus_message_open_container(m, 'r', "sv"); if (r < 0) return r; r = sd_bus_message_append(m, "s", "ExecStart"); if (r < 0) return r; r = sd_bus_message_open_container(m, 'v', "a(sasb)"); if (r < 0) return r; r = sd_bus_message_open_container(m, 'a', "(sasb)"); if (r < 0) return r; r = sd_bus_message_open_container(m, 'r', "sasb"); if (r < 0) return r; r = sd_bus_message_append(m, "s", argv[0]); if (r < 0) return r; r = sd_bus_message_append_strv(m, argv); if (r < 0) return r; r = sd_bus_message_append(m, "b", false); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; } return 0; } static int transient_scope_set_properties(sd_bus_message *m) { int r; assert(m); r = transient_unit_set_properties(m, arg_property); if (r < 0) return r; r = transient_kill_set_properties(m); if (r < 0) return r; r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid()); if (r < 0) return r; return 0; } static int transient_timer_set_properties(sd_bus_message *m) { int r; assert(m); r = transient_unit_set_properties(m, arg_timer_property); if (r < 0) return r; /* Automatically clean up our transient timers */ r = sd_bus_message_append(m, "(sv)", "RemainAfterElapse", "b", false); if (r < 0) return r; if (arg_on_active) { r = sd_bus_message_append(m, "(sv)", "OnActiveSec", "t", arg_on_active); if (r < 0) return r; } if (arg_on_boot) { r = sd_bus_message_append(m, "(sv)", "OnBootSec", "t", arg_on_boot); if (r < 0) return r; } if (arg_on_startup) { r = sd_bus_message_append(m, "(sv)", "OnStartupSec", "t", arg_on_startup); if (r < 0) return r; } if (arg_on_unit_active) { r = sd_bus_message_append(m, "(sv)", "OnUnitActiveSec", "t", arg_on_unit_active); if (r < 0) return r; } if (arg_on_unit_inactive) { r = sd_bus_message_append(m, "(sv)", "OnUnitInactiveSec", "t", arg_on_unit_inactive); if (r < 0) return r; } if (arg_on_calendar) { r = sd_bus_message_append(m, "(sv)", "OnCalendar", "s", arg_on_calendar); if (r < 0) return r; } return 0; } static int make_unit_name(sd_bus *bus, UnitType t, char **ret) { const char *unique, *id; char *p; int r; assert(bus); assert(t >= 0); assert(t < _UNIT_TYPE_MAX); r = sd_bus_get_unique_name(bus, &unique); if (r < 0) { sd_id128_t rnd; /* We couldn't get the unique name, which is a pretty * common case if we are connected to systemd * directly. In that case, just pick a random uuid as * name */ r = sd_id128_randomize(&rnd); if (r < 0) return log_error_errno(r, "Failed to generate random run unit name: %m"); if (asprintf(ret, "run-r" SD_ID128_FORMAT_STR ".%s", SD_ID128_FORMAT_VAL(rnd), unit_type_to_string(t)) < 0) return log_oom(); return 0; } /* We managed to get the unique name, then let's use that to * name our transient units. */ id = startswith(unique, ":1."); if (!id) { log_error("Unique name %s has unexpected format.", unique); return -EINVAL; } p = strjoin("run-u", id, ".", unit_type_to_string(t), NULL); if (!p) return log_oom(); *ret = p; return 0; } static int start_transient_service( sd_bus *bus, char **argv) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; _cleanup_free_ char *service = NULL, *pty_path = NULL; _cleanup_close_ int master = -1; int r; assert(bus); assert(argv); if (arg_pty) { if (arg_transport == BUS_TRANSPORT_LOCAL) { master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY); if (master < 0) return log_error_errno(errno, "Failed to acquire pseudo tty: %m"); r = ptsname_malloc(master, &pty_path); if (r < 0) return log_error_errno(r, "Failed to determine tty name: %m"); if (unlockpt(master) < 0) return log_error_errno(errno, "Failed to unlock tty: %m"); } else if (arg_transport == BUS_TRANSPORT_MACHINE) { _cleanup_(sd_bus_unrefp) sd_bus *system_bus = NULL; const char *s; r = sd_bus_default_system(&system_bus); if (r < 0) return log_error_errno(r, "Failed to connect to system bus: %m"); r = sd_bus_call_method(system_bus, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "OpenMachinePTY", &error, &reply, "s", arg_host); if (r < 0) { log_error("Failed to get machine PTY: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_read(reply, "hs", &master, &s); if (r < 0) return bus_log_parse_error(r); reply = sd_bus_message_unref(reply); master = fcntl(master, F_DUPFD_CLOEXEC, 3); if (master < 0) return log_error_errno(errno, "Failed to duplicate master fd: %m"); pty_path = strdup(s); if (!pty_path) return log_oom(); } else assert_not_reached("Can't allocate tty via ssh"); } if (!arg_no_block) { r = bus_wait_for_jobs_new(bus, &w); if (r < 0) return log_error_errno(r, "Could not watch jobs: %m"); } if (arg_unit) { r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); } else { r = make_unit_name(bus, UNIT_SERVICE, &service); if (r < 0) return r; } r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartTransientUnit"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); if (r < 0) return bus_log_create_error(r); /* Name and mode */ r = sd_bus_message_append(m, "ss", service, "fail"); if (r < 0) return bus_log_create_error(r); /* Properties */ r = sd_bus_message_open_container(m, 'a', "(sv)"); if (r < 0) return bus_log_create_error(r); r = transient_service_set_properties(m, argv, pty_path); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); /* Auxiliary units */ r = sd_bus_message_append(m, "a(sa(sv))", 0); if (r < 0) return bus_log_create_error(r); polkit_agent_open_if_enabled(); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) return log_error_errno(r, "Failed to start transient service unit: %s", bus_error_message(&error, r)); if (w) { const char *object; r = sd_bus_message_read(reply, "o", &object); if (r < 0) return bus_log_parse_error(r); r = bus_wait_for_jobs_one(w, object, arg_quiet); if (r < 0) return r; } if (master >= 0) { _cleanup_(pty_forward_freep) PTYForward *forward = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; char last_char = 0; r = sd_event_default(&event); if (r < 0) return log_error_errno(r, "Failed to get event loop: %m"); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0); (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); if (!arg_quiet) log_info("Running as unit %s.\nPress ^] three times within 1s to disconnect TTY.", service); r = pty_forward_new(event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &forward); if (r < 0) return log_error_errno(r, "Failed to create PTY forwarder: %m"); r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); pty_forward_get_last_char(forward, &last_char); forward = pty_forward_free(forward); if (!arg_quiet && last_char != '\n') fputc('\n', stdout); } else if (!arg_quiet) log_info("Running as unit %s.", service); return 0; } static int start_transient_scope( sd_bus *bus, char **argv) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; _cleanup_strv_free_ char **env = NULL, **user_env = NULL; _cleanup_free_ char *scope = NULL; const char *object = NULL; int r; assert(bus); assert(argv); r = bus_wait_for_jobs_new(bus, &w); if (r < 0) return log_oom(); if (arg_unit) { r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".scope", &scope); if (r < 0) return log_error_errno(r, "Failed to mangle scope name: %m"); } else { r = make_unit_name(bus, UNIT_SCOPE, &scope); if (r < 0) return r; } r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartTransientUnit"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); if (r < 0) return bus_log_create_error(r); /* Name and Mode */ r = sd_bus_message_append(m, "ss", scope, "fail"); if (r < 0) return bus_log_create_error(r); /* Properties */ r = sd_bus_message_open_container(m, 'a', "(sv)"); if (r < 0) return bus_log_create_error(r); r = transient_scope_set_properties(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); /* Auxiliary units */ r = sd_bus_message_append(m, "a(sa(sv))", 0); if (r < 0) return bus_log_create_error(r); polkit_agent_open_if_enabled(); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) { log_error("Failed to start transient scope unit: %s", bus_error_message(&error, -r)); return r; } if (arg_nice_set) { if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0) return log_error_errno(errno, "Failed to set nice level: %m"); } if (arg_exec_group) { gid_t gid; r = get_group_creds(&arg_exec_group, &gid); if (r < 0) return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group); if (setresgid(gid, gid, gid) < 0) return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid); } if (arg_exec_user) { const char *home, *shell; uid_t uid; gid_t gid; r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell); if (r < 0) return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user); r = strv_extendf(&user_env, "HOME=%s", home); if (r < 0) return log_oom(); r = strv_extendf(&user_env, "SHELL=%s", shell); if (r < 0) return log_oom(); r = strv_extendf(&user_env, "USER=%s", arg_exec_user); if (r < 0) return log_oom(); r = strv_extendf(&user_env, "LOGNAME=%s", arg_exec_user); if (r < 0) return log_oom(); if (!arg_exec_group) { if (setresgid(gid, gid, gid) < 0) return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid); } if (setresuid(uid, uid, uid) < 0) return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid); } env = strv_env_merge(3, environ, user_env, arg_environment); if (!env) return log_oom(); r = sd_bus_message_read(reply, "o", &object); if (r < 0) return bus_log_parse_error(r); r = bus_wait_for_jobs_one(w, object, arg_quiet); if (r < 0) return r; if (!arg_quiet) log_info("Running scope as unit %s.", scope); execvpe(argv[0], argv, env); return log_error_errno(errno, "Failed to execute: %m"); } static int start_transient_timer( sd_bus *bus, char **argv) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; _cleanup_free_ char *timer = NULL, *service = NULL; const char *object = NULL; int r; assert(bus); assert(argv); r = bus_wait_for_jobs_new(bus, &w); if (r < 0) return log_oom(); if (arg_unit) { switch (unit_name_to_type(arg_unit)) { case UNIT_SERVICE: service = strdup(arg_unit); if (!service) return log_oom(); r = unit_name_change_suffix(service, ".timer", &timer); if (r < 0) return log_error_errno(r, "Failed to change unit suffix: %m"); break; case UNIT_TIMER: timer = strdup(arg_unit); if (!timer) return log_oom(); r = unit_name_change_suffix(timer, ".service", &service); if (r < 0) return log_error_errno(r, "Failed to change unit suffix: %m"); break; default: r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".timer", &timer); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); break; } } else { r = make_unit_name(bus, UNIT_SERVICE, &service); if (r < 0) return r; r = unit_name_change_suffix(service, ".timer", &timer); if (r < 0) return log_error_errno(r, "Failed to change unit suffix: %m"); } r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartTransientUnit"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); if (r < 0) return bus_log_create_error(r); /* Name and Mode */ r = sd_bus_message_append(m, "ss", timer, "fail"); if (r < 0) return bus_log_create_error(r); /* Properties */ r = sd_bus_message_open_container(m, 'a', "(sv)"); if (r < 0) return bus_log_create_error(r); r = transient_timer_set_properties(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'a', "(sa(sv))"); if (r < 0) return bus_log_create_error(r); if (argv[0]) { r = sd_bus_message_open_container(m, 'r', "sa(sv)"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append(m, "s", service); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'a', "(sv)"); if (r < 0) return bus_log_create_error(r); r = transient_service_set_properties(m, argv, NULL); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); } r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); polkit_agent_open_if_enabled(); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) { log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_read(reply, "o", &object); if (r < 0) return bus_log_parse_error(r); r = bus_wait_for_jobs_one(w, object, arg_quiet); if (r < 0) return r; log_info("Running timer as unit %s.", timer); if (argv[0]) log_info("Will run service as unit %s.", service); return 0; } int main(int argc, char* argv[]) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_free_ char *description = NULL, *command = NULL; int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; if (argc > optind && arg_transport == BUS_TRANSPORT_LOCAL) { /* Patch in an absolute path */ r = find_binary(argv[optind], &command); if (r < 0) { log_error_errno(r, "Failed to find executable %s: %m", argv[optind]); goto finish; } argv[optind] = command; } if (!arg_description) { description = strv_join(argv + optind, " "); if (!description) { r = log_oom(); goto finish; } if (arg_unit && isempty(description)) { r = free_and_strdup(&description, arg_unit); if (r < 0) goto finish; } arg_description = description; } r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; } if (arg_scope) r = start_transient_scope(bus, argv + optind); else if (with_timer()) r = start_transient_timer(bus, argv + optind); else r = start_transient_service(bus, argv + optind); finish: strv_free(arg_environment); strv_free(arg_property); strv_free(arg_timer_property); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/shared/000077500000000000000000000000001265713322000151165ustar00rootroot00000000000000systemd-229/src/shared/Makefile000077700000000000000000000000001265713322000204242../Makefileustar00rootroot00000000000000systemd-229/src/shared/acl-util.c000066400000000000000000000270301265713322000167760ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011,2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "acl-util.h" #include "alloc-util.h" #include "string-util.h" #include "strv.h" #include "user-util.h" #include "util.h" int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) { acl_entry_t i; int r; assert(acl); assert(entry); for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); r > 0; r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { acl_tag_t tag; uid_t *u; bool b; if (acl_get_tag_type(i, &tag) < 0) return -errno; if (tag != ACL_USER) continue; u = acl_get_qualifier(i); if (!u) return -errno; b = *u == uid; acl_free(u); if (b) { *entry = i; return 1; } } if (r < 0) return -errno; return 0; } int calc_acl_mask_if_needed(acl_t *acl_p) { acl_entry_t i; int r; bool need = false; assert(acl_p); for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i); r > 0; r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) { acl_tag_t tag; if (acl_get_tag_type(i, &tag) < 0) return -errno; if (tag == ACL_MASK) return 0; if (IN_SET(tag, ACL_USER, ACL_GROUP)) need = true; } if (r < 0) return -errno; if (need && acl_calc_mask(acl_p) < 0) return -errno; return need; } int add_base_acls_if_needed(acl_t *acl_p, const char *path) { acl_entry_t i; int r; bool have_user_obj = false, have_group_obj = false, have_other = false; struct stat st; _cleanup_(acl_freep) acl_t basic = NULL; assert(acl_p); for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i); r > 0; r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) { acl_tag_t tag; if (acl_get_tag_type(i, &tag) < 0) return -errno; if (tag == ACL_USER_OBJ) have_user_obj = true; else if (tag == ACL_GROUP_OBJ) have_group_obj = true; else if (tag == ACL_OTHER) have_other = true; if (have_user_obj && have_group_obj && have_other) return 0; } if (r < 0) return -errno; r = stat(path, &st); if (r < 0) return -errno; basic = acl_from_mode(st.st_mode); if (!basic) return -errno; for (r = acl_get_entry(basic, ACL_FIRST_ENTRY, &i); r > 0; r = acl_get_entry(basic, ACL_NEXT_ENTRY, &i)) { acl_tag_t tag; acl_entry_t dst; if (acl_get_tag_type(i, &tag) < 0) return -errno; if ((tag == ACL_USER_OBJ && have_user_obj) || (tag == ACL_GROUP_OBJ && have_group_obj) || (tag == ACL_OTHER && have_other)) continue; r = acl_create_entry(acl_p, &dst); if (r < 0) return -errno; r = acl_copy_entry(dst, i); if (r < 0) return -errno; } if (r < 0) return -errno; return 0; } int acl_search_groups(const char *path, char ***ret_groups) { _cleanup_strv_free_ char **g = NULL; _cleanup_(acl_free) acl_t acl = NULL; bool ret = false; acl_entry_t entry; int r; assert(path); acl = acl_get_file(path, ACL_TYPE_DEFAULT); if (!acl) return -errno; r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); for (;;) { _cleanup_(acl_free_gid_tpp) gid_t *gid = NULL; acl_tag_t tag; if (r < 0) return -errno; if (r == 0) break; if (acl_get_tag_type(entry, &tag) < 0) return -errno; if (tag != ACL_GROUP) goto next; gid = acl_get_qualifier(entry); if (!gid) return -errno; if (in_gid(*gid) > 0) { if (!ret_groups) return true; ret = true; } if (ret_groups) { char *name; name = gid_to_name(*gid); if (!name) return -ENOMEM; r = strv_consume(&g, name); if (r < 0) return r; } next: r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); } if (ret_groups) { *ret_groups = g; g = NULL; } return ret; } int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) { _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not be freed */ _cleanup_strv_free_ char **split; char **entry; int r = -EINVAL; _cleanup_(acl_freep) acl_t a_acl = NULL, d_acl = NULL; split = strv_split(text, ","); if (!split) return -ENOMEM; STRV_FOREACH(entry, split) { char *p; p = startswith(*entry, "default:"); if (!p) p = startswith(*entry, "d:"); if (p) r = strv_push(&d, p); else r = strv_push(&a, *entry); if (r < 0) return r; } if (!strv_isempty(a)) { _cleanup_free_ char *join; join = strv_join(a, ","); if (!join) return -ENOMEM; a_acl = acl_from_text(join); if (!a_acl) return -errno; if (want_mask) { r = calc_acl_mask_if_needed(&a_acl); if (r < 0) return r; } } if (!strv_isempty(d)) { _cleanup_free_ char *join; join = strv_join(d, ","); if (!join) return -ENOMEM; d_acl = acl_from_text(join); if (!d_acl) return -errno; if (want_mask) { r = calc_acl_mask_if_needed(&d_acl); if (r < 0) return r; } } *acl_access = a_acl; *acl_default = d_acl; a_acl = d_acl = NULL; return 0; } static int acl_entry_equal(acl_entry_t a, acl_entry_t b) { acl_tag_t tag_a, tag_b; if (acl_get_tag_type(a, &tag_a) < 0) return -errno; if (acl_get_tag_type(b, &tag_b) < 0) return -errno; if (tag_a != tag_b) return false; switch (tag_a) { case ACL_USER_OBJ: case ACL_GROUP_OBJ: case ACL_MASK: case ACL_OTHER: /* can have only one of those */ return true; case ACL_USER: { _cleanup_(acl_free_uid_tpp) uid_t *uid_a = NULL, *uid_b = NULL; uid_a = acl_get_qualifier(a); if (!uid_a) return -errno; uid_b = acl_get_qualifier(b); if (!uid_b) return -errno; return *uid_a == *uid_b; } case ACL_GROUP: { _cleanup_(acl_free_gid_tpp) gid_t *gid_a = NULL, *gid_b = NULL; gid_a = acl_get_qualifier(a); if (!gid_a) return -errno; gid_b = acl_get_qualifier(b); if (!gid_b) return -errno; return *gid_a == *gid_b; } default: assert_not_reached("Unknown acl tag type"); } } static int find_acl_entry(acl_t acl, acl_entry_t entry, acl_entry_t *out) { acl_entry_t i; int r; for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); r > 0; r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { r = acl_entry_equal(i, entry); if (r < 0) return r; if (r > 0) { *out = i; return 1; } } if (r < 0) return -errno; return 0; } int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) { _cleanup_(acl_freep) acl_t old; acl_entry_t i; int r; old = acl_get_file(path, type); if (!old) return -errno; for (r = acl_get_entry(new, ACL_FIRST_ENTRY, &i); r > 0; r = acl_get_entry(new, ACL_NEXT_ENTRY, &i)) { acl_entry_t j; r = find_acl_entry(old, i, &j); if (r < 0) return r; if (r == 0) if (acl_create_entry(&old, &j) < 0) return -errno; if (acl_copy_entry(j, i) < 0) return -errno; } if (r < 0) return -errno; *acl = old; old = NULL; return 0; } int add_acls_for_user(int fd, uid_t uid) { _cleanup_(acl_freep) acl_t acl = NULL; acl_entry_t entry; acl_permset_t permset; int r; acl = acl_get_fd(fd); if (!acl) return -errno; r = acl_find_uid(acl, uid, &entry); if (r <= 0) { if (acl_create_entry(&acl, &entry) < 0 || acl_set_tag_type(entry, ACL_USER) < 0 || acl_set_qualifier(entry, &uid) < 0) return -errno; } /* We do not recalculate the mask unconditionally here, * so that the fchmod() mask above stays intact. */ if (acl_get_permset(entry, &permset) < 0 || acl_add_perm(permset, ACL_READ) < 0) return -errno; r = calc_acl_mask_if_needed(&acl); if (r < 0) return r; return acl_set_fd(fd, acl); } systemd-229/src/shared/acl-util.h000066400000000000000000000032111265713322000167760ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #ifdef HAVE_ACL #include #include #include #include "macro.h" int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry); int calc_acl_mask_if_needed(acl_t *acl_p); int add_base_acls_if_needed(acl_t *acl_p, const char *path); int acl_search_groups(const char* path, char ***ret_groups); int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask); int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl); int add_acls_for_user(int fd, uid_t uid); /* acl_free takes multiple argument types. * Multiple cleanup functions are necessary. */ DEFINE_TRIVIAL_CLEANUP_FUNC(acl_t, acl_free); #define acl_free_charp acl_free DEFINE_TRIVIAL_CLEANUP_FUNC(char*, acl_free_charp); #define acl_free_uid_tp acl_free DEFINE_TRIVIAL_CLEANUP_FUNC(uid_t*, acl_free_uid_tp); #define acl_free_gid_tp acl_free DEFINE_TRIVIAL_CLEANUP_FUNC(gid_t*, acl_free_gid_tp); #endif systemd-229/src/shared/acpi-fpdt.c000066400000000000000000000111751265713322000171360ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "acpi-fpdt.h" #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "time-util.h" struct acpi_table_header { char signature[4]; uint32_t length; uint8_t revision; uint8_t checksum; char oem_id[6]; char oem_table_id[8]; uint32_t oem_revision; char asl_compiler_id[4]; uint32_t asl_compiler_revision; }; enum { ACPI_FPDT_TYPE_BOOT = 0, ACPI_FPDT_TYPE_S3PERF = 1, }; struct acpi_fpdt_header { uint16_t type; uint8_t length; uint8_t revision; uint8_t reserved[4]; uint64_t ptr; }; struct acpi_fpdt_boot_header { char signature[4]; uint32_t length; }; enum { ACPI_FPDT_S3PERF_RESUME_REC = 0, ACPI_FPDT_S3PERF_SUSPEND_REC = 1, ACPI_FPDT_BOOT_REC = 2, }; struct acpi_fpdt_boot { uint16_t type; uint8_t length; uint8_t revision; uint8_t reserved[4]; uint64_t reset_end; uint64_t load_start; uint64_t startup_start; uint64_t exit_services_entry; uint64_t exit_services_exit; }; int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit) { _cleanup_free_ char *buf = NULL; struct acpi_table_header *tbl; size_t l = 0; struct acpi_fpdt_header *rec; int r; uint64_t ptr = 0; _cleanup_close_ int fd = -1; struct acpi_fpdt_boot_header hbrec; struct acpi_fpdt_boot brec; r = read_full_file("/sys/firmware/acpi/tables/FPDT", &buf, &l); if (r < 0) return r; if (l < sizeof(struct acpi_table_header) + sizeof(struct acpi_fpdt_header)) return -EINVAL; tbl = (struct acpi_table_header *)buf; if (l != tbl->length) return -EINVAL; if (memcmp(tbl->signature, "FPDT", 4) != 0) return -EINVAL; /* find Firmware Basic Boot Performance Pointer Record */ for (rec = (struct acpi_fpdt_header *)(buf + sizeof(struct acpi_table_header)); (char *)rec < buf + l; rec = (struct acpi_fpdt_header *)((char *)rec + rec->length)) { if (rec->length <= 0) break; if (rec->type != ACPI_FPDT_TYPE_BOOT) continue; if (rec->length != sizeof(struct acpi_fpdt_header)) continue; ptr = rec->ptr; break; } if (ptr == 0) return -EINVAL; /* read Firmware Basic Boot Performance Data Record */ fd = open("/dev/mem", O_CLOEXEC|O_RDONLY); if (fd < 0) return -errno; l = pread(fd, &hbrec, sizeof(struct acpi_fpdt_boot_header), ptr); if (l != sizeof(struct acpi_fpdt_boot_header)) return -EINVAL; if (memcmp(hbrec.signature, "FBPT", 4) != 0) return -EINVAL; if (hbrec.length < sizeof(struct acpi_fpdt_boot_header) + sizeof(struct acpi_fpdt_boot)) return -EINVAL; l = pread(fd, &brec, sizeof(struct acpi_fpdt_boot), ptr + sizeof(struct acpi_fpdt_boot_header)); if (l != sizeof(struct acpi_fpdt_boot)) return -EINVAL; if (brec.length != sizeof(struct acpi_fpdt_boot)) return -EINVAL; if (brec.type != ACPI_FPDT_BOOT_REC) return -EINVAL; if (brec.startup_start == 0 || brec.exit_services_exit < brec.startup_start) return -EINVAL; if (brec.exit_services_exit > NSEC_PER_HOUR) return -EINVAL; if (loader_start) *loader_start = brec.startup_start / 1000; if (loader_exit) *loader_exit = brec.exit_services_exit / 1000; return 0; } systemd-229/src/shared/acpi-fpdt.h000066400000000000000000000014611265713322000171400ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit); systemd-229/src/shared/apparmor-util.c000066400000000000000000000022521265713322000200570ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "apparmor-util.h" #include "fileio.h" #include "parse-util.h" bool mac_apparmor_use(void) { static int cached_use = -1; if (cached_use < 0) { _cleanup_free_ char *p = NULL; cached_use = read_one_line_file("/sys/module/apparmor/parameters/enabled", &p) >= 0 && parse_boolean(p) > 0; } return cached_use; } systemd-229/src/shared/apparmor-util.h000066400000000000000000000014201265713322000200600ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include bool mac_apparmor_use(void); systemd-229/src/shared/architecture.c000066400000000000000000000166731265713322000177610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "architecture.h" #include "macro.h" #include "string-table.h" #include "string-util.h" int uname_architecture(void) { /* Return a sanitized enum identifying the architecture we are * running on. This is based on uname(), and the user may * hence control what this returns by using * personality(). This puts the user in control on systems * that can run binaries of multiple architectures. * * We do not translate the string returned by uname() * 1:1. Instead we try to clean it up and break down the * confusion on x86 and arm in particular. * * We do not try to distinguish CPUs not CPU features, but * actual architectures, i.e. that have genuinely different * code. */ static const struct { const char *machine; int arch; } arch_map[] = { #if defined(__x86_64__) || defined(__i386__) { "x86_64", ARCHITECTURE_X86_64 }, { "i686", ARCHITECTURE_X86 }, { "i586", ARCHITECTURE_X86 }, { "i486", ARCHITECTURE_X86 }, { "i386", ARCHITECTURE_X86 }, #elif defined(__powerpc__) || defined(__powerpc64__) { "ppc64", ARCHITECTURE_PPC64 }, { "ppc64le", ARCHITECTURE_PPC64_LE }, { "ppc", ARCHITECTURE_PPC }, { "ppcle", ARCHITECTURE_PPC_LE }, #elif defined(__ia64__) { "ia64", ARCHITECTURE_IA64 }, #elif defined(__hppa__) || defined(__hppa64__) { "parisc64", ARCHITECTURE_PARISC64 }, { "parisc", ARCHITECTURE_PARISC }, #elif defined(__s390__) || defined(__s390x__) { "s390x", ARCHITECTURE_S390X }, { "s390", ARCHITECTURE_S390 }, #elif defined(__sparc__) || defined(__sparc64__) { "sparc64", ARCHITECTURE_SPARC64 }, { "sparc", ARCHITECTURE_SPARC }, #elif defined(__mips__) || defined(__mips64__) { "mips64", ARCHITECTURE_MIPS64 }, { "mips", ARCHITECTURE_MIPS }, #elif defined(__alpha__) { "alpha" , ARCHITECTURE_ALPHA }, #elif defined(__arm__) || defined(__aarch64__) { "aarch64", ARCHITECTURE_ARM64 }, { "aarch64_be", ARCHITECTURE_ARM64_BE }, { "armv4l", ARCHITECTURE_ARM }, { "armv4b", ARCHITECTURE_ARM_BE }, { "armv4tl", ARCHITECTURE_ARM }, { "armv4tb", ARCHITECTURE_ARM_BE }, { "armv5tl", ARCHITECTURE_ARM }, { "armv5tb", ARCHITECTURE_ARM_BE }, { "armv5tel", ARCHITECTURE_ARM }, { "armv5teb" , ARCHITECTURE_ARM_BE }, { "armv5tejl", ARCHITECTURE_ARM }, { "armv5tejb", ARCHITECTURE_ARM_BE }, { "armv6l", ARCHITECTURE_ARM }, { "armv6b", ARCHITECTURE_ARM_BE }, { "armv7l", ARCHITECTURE_ARM }, { "armv7b", ARCHITECTURE_ARM_BE }, { "armv7ml", ARCHITECTURE_ARM }, { "armv7mb", ARCHITECTURE_ARM_BE }, { "armv4l", ARCHITECTURE_ARM }, { "armv4b", ARCHITECTURE_ARM_BE }, { "armv4tl", ARCHITECTURE_ARM }, { "armv4tb", ARCHITECTURE_ARM_BE }, { "armv5tl", ARCHITECTURE_ARM }, { "armv5tb", ARCHITECTURE_ARM_BE }, { "armv5tel", ARCHITECTURE_ARM }, { "armv5teb", ARCHITECTURE_ARM_BE }, { "armv5tejl", ARCHITECTURE_ARM }, { "armv5tejb", ARCHITECTURE_ARM_BE }, { "armv6l", ARCHITECTURE_ARM }, { "armv6b", ARCHITECTURE_ARM_BE }, { "armv7l", ARCHITECTURE_ARM }, { "armv7b", ARCHITECTURE_ARM_BE }, { "armv7ml", ARCHITECTURE_ARM }, { "armv7mb", ARCHITECTURE_ARM_BE }, { "armv8l", ARCHITECTURE_ARM }, { "armv8b", ARCHITECTURE_ARM_BE }, #elif defined(__sh__) || defined(__sh64__) { "sh5", ARCHITECTURE_SH64 }, { "sh2", ARCHITECTURE_SH }, { "sh2a", ARCHITECTURE_SH }, { "sh3", ARCHITECTURE_SH }, { "sh4", ARCHITECTURE_SH }, { "sh4a", ARCHITECTURE_SH }, #elif defined(__m68k__) { "m68k", ARCHITECTURE_M68K }, #elif defined(__tilegx__) { "tilegx", ARCHITECTURE_TILEGX }, #elif defined(__cris__) { "crisv32", ARCHITECTURE_CRIS }, #else #error "Please register your architecture here!" #endif }; static int cached = _ARCHITECTURE_INVALID; struct utsname u; unsigned i; if (cached != _ARCHITECTURE_INVALID) return cached; assert_se(uname(&u) >= 0); for (i = 0; i < ELEMENTSOF(arch_map); i++) if (streq(arch_map[i].machine, u.machine)) return cached = arch_map[i].arch; assert_not_reached("Couldn't identify architecture. You need to patch systemd."); return _ARCHITECTURE_INVALID; } static const char *const architecture_table[_ARCHITECTURE_MAX] = { [ARCHITECTURE_X86] = "x86", [ARCHITECTURE_X86_64] = "x86-64", [ARCHITECTURE_PPC] = "ppc", [ARCHITECTURE_PPC_LE] = "ppc-le", [ARCHITECTURE_PPC64] = "ppc64", [ARCHITECTURE_PPC64_LE] = "ppc64-le", [ARCHITECTURE_IA64] = "ia64", [ARCHITECTURE_PARISC] = "parisc", [ARCHITECTURE_PARISC64] = "parisc64", [ARCHITECTURE_S390] = "s390", [ARCHITECTURE_S390X] = "s390x", [ARCHITECTURE_SPARC] = "sparc", [ARCHITECTURE_SPARC64] = "sparc64", [ARCHITECTURE_MIPS] = "mips", [ARCHITECTURE_MIPS_LE] = "mips-le", [ARCHITECTURE_MIPS64] = "mips64", [ARCHITECTURE_MIPS64_LE] = "mips64-le", [ARCHITECTURE_ALPHA] = "alpha", [ARCHITECTURE_ARM] = "arm", [ARCHITECTURE_ARM_BE] = "arm-be", [ARCHITECTURE_ARM64] = "arm64", [ARCHITECTURE_ARM64_BE] = "arm64-be", [ARCHITECTURE_SH] = "sh", [ARCHITECTURE_SH64] = "sh64", [ARCHITECTURE_M68K] = "m68k", [ARCHITECTURE_TILEGX] = "tilegx", [ARCHITECTURE_CRIS] = "cris", }; DEFINE_STRING_TABLE_LOOKUP(architecture, int); systemd-229/src/shared/architecture.h000066400000000000000000000152141265713322000177540ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" #include "util.h" /* A cleaned up architecture definition. We don't want to get lost in * processor features, models, generations or even ABIs. Hence we * focus on general family, and distinguish word width and * endianness. */ enum { ARCHITECTURE_X86 = 0, ARCHITECTURE_X86_64, ARCHITECTURE_PPC, ARCHITECTURE_PPC_LE, ARCHITECTURE_PPC64, ARCHITECTURE_PPC64_LE, ARCHITECTURE_IA64, ARCHITECTURE_PARISC, ARCHITECTURE_PARISC64, ARCHITECTURE_S390, ARCHITECTURE_S390X, ARCHITECTURE_SPARC, ARCHITECTURE_SPARC64, ARCHITECTURE_MIPS, ARCHITECTURE_MIPS_LE, ARCHITECTURE_MIPS64, ARCHITECTURE_MIPS64_LE, ARCHITECTURE_ALPHA, ARCHITECTURE_ARM, ARCHITECTURE_ARM_BE, ARCHITECTURE_ARM64, ARCHITECTURE_ARM64_BE, ARCHITECTURE_SH, ARCHITECTURE_SH64, ARCHITECTURE_M68K, ARCHITECTURE_TILEGX, ARCHITECTURE_CRIS, _ARCHITECTURE_MAX, _ARCHITECTURE_INVALID = -1 }; int uname_architecture(void); /* * LIB_ARCH_TUPLE should resolve to the local library path * architecture tuple systemd is built for, according to the Debian * tuple list: * * https://wiki.debian.org/Multiarch/Tuples * * This is used in library search paths that should understand * Debian's paths on all distributions. */ #if defined(__x86_64__) # define native_architecture() ARCHITECTURE_X86_64 # define LIB_ARCH_TUPLE "x86_64-linux-gnu" # define PROC_CPUINFO_MODEL "model name" #elif defined(__i386__) # define native_architecture() ARCHITECTURE_X86 # define LIB_ARCH_TUPLE "i386-linux-gnu" # define PROC_CPUINFO_MODEL "model name" #elif defined(__powerpc64__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_PPC64 # define LIB_ARCH_TUPLE "ppc64-linux-gnu" # else # define native_architecture() ARCHITECTURE_PPC64_LE # define LIB_ARCH_TUPLE "powerpc64le-linux-gnu" # endif # define PROC_CPUINFO_MODEL "cpu" #elif defined(__powerpc__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_PPC # define LIB_ARCH_TUPLE "powerpc-linux-gnu" # else # define native_architecture() ARCHITECTURE_PPC_LE # error "Missing LIB_ARCH_TUPLE for PPCLE" # endif # define PROC_CPUINFO_MODEL "cpu" #elif defined(__ia64__) # define native_architecture() ARCHITECTURE_IA64 # define LIB_ARCH_TUPLE "ia64-linux-gnu" #elif defined(__hppa64__) # define native_architecture() ARCHITECTURE_PARISC64 # error "Missing LIB_ARCH_TUPLE for HPPA64" # define PROC_CPUINFO_MODEL "cpu" #elif defined(__hppa__) # define native_architecture() ARCHITECTURE_PARISC # define LIB_ARCH_TUPLE "hppa‑linux‑gnu" # define PROC_CPUINFO_MODEL "cpu" #elif defined(__s390x__) # define native_architecture() ARCHITECTURE_S390X # define LIB_ARCH_TUPLE "s390x-linux-gnu" #elif defined(__s390__) # define native_architecture() ARCHITECTURE_S390 # define LIB_ARCH_TUPLE "s390-linux-gnu" #elif defined(__sparc64__) # define native_architecture() ARCHITECTURE_SPARC64 # define LIB_ARCH_TUPLE "sparc64-linux-gnu" # define PROC_CPUINFO_MODEL "cpu" #elif defined(__sparc__) # define native_architecture() ARCHITECTURE_SPARC # define LIB_ARCH_TUPLE "sparc-linux-gnu" # define PROC_CPUINFO_MODEL "cpu" #elif defined(__mips64__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_MIPS64 # error "Missing LIB_ARCH_TUPLE for MIPS64" # else # define native_architecture() ARCHITECTURE_MIPS64_LE # error "Missing LIB_ARCH_TUPLE for MIPS64_LE" # endif # define PROC_CPUINFO_MODEL "cpu model" #elif defined(__mips__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_MIPS # define LIB_ARCH_TUPLE "mips-linux-gnu" # else # define native_architecture() ARCHITECTURE_MIPS_LE # define LIB_ARCH_TUPLE "mipsel-linux-gnu" # endif # define PROC_CPUINFO_MODEL "cpu model" #elif defined(__alpha__) # define native_architecture() ARCHITECTURE_ALPHA # define LIB_ARCH_TUPLE "alpha-linux-gnu" #elif defined(__aarch64__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_ARM64_BE # define LIB_ARCH_TUPLE "aarch64_be-linux-gnu" # else # define native_architecture() ARCHITECTURE_ARM64 # define LIB_ARCH_TUPLE "aarch64-linux-gnu" # endif #elif defined(__arm__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_ARM_BE # if defined(__ARM_EABI__) # if defined(__ARM_PCS_VFP) # define LIB_ARCH_TUPLE "armeb-linux-gnueabihf" # else # define LIB_ARCH_TUPLE "armeb-linux-gnueabi" # endif # else # define LIB_ARCH_TUPLE "armeb-linux-gnu" # endif # else # define native_architecture() ARCHITECTURE_ARM # if defined(__ARM_EABI__) # if defined(__ARM_PCS_VFP) # define LIB_ARCH_TUPLE "arm-linux-gnueabihf" # else # define LIB_ARCH_TUPLE "arm-linux-gnueabi" # endif # else # define LIB_ARCH_TUPLE "arm-linux-gnu" # endif # endif # define PROC_CPUINFO_MODEL "model name" #elif defined(__sh64__) # define native_architecture() ARCHITECTURE_SH64 # error "Missing LIB_ARCH_TUPLE for SH64" #elif defined(__sh__) # define native_architecture() ARCHITECTURE_SH # define LIB_ARCH_TUPLE "sh4-linux-gnu" #elif defined(__m68k__) # define native_architecture() ARCHITECTURE_M68K # define LIB_ARCH_TUPLE "m68k-linux-gnu" #elif defined(__tilegx__) # define native_architecture() ARCHITECTURE_TILEGX # error "Missing LIB_ARCH_TUPLE for TILEGX" #elif defined(__cris__) # define native_architecture() ARCHITECTURE_CRIS # error "Missing LIB_ARCH_TUPLE for CRIS" #else # error "Please register your architecture here!" #endif #ifndef PROC_CPUINFO_MODEL #warning "PROC_CPUINFO_MODEL not defined for your architecture" #define PROC_CPUINFO_MODEL "model name" #endif const char *architecture_to_string(int a) _const_; int architecture_from_string(const char *s) _pure_; systemd-229/src/shared/ask-password-api.c000066400000000000000000000513211265713322000204510ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "ask-password-api.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "io-util.h" #include "log.h" #include "macro.h" #include "missing.h" #include "mkdir.h" #include "random-util.h" #include "signal-util.h" #include "socket-util.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "time-util.h" #include "umask-util.h" #include "utf8.h" #include "util.h" #define KEYRING_TIMEOUT_USEC ((5 * USEC_PER_MINUTE) / 2) static int lookup_key(const char *keyname, key_serial_t *ret) { key_serial_t serial; assert(keyname); assert(ret); serial = request_key("user", keyname, NULL, 0); if (serial == -1) return negative_errno(); *ret = serial; return 0; } static int retrieve_key(key_serial_t serial, char ***ret) { _cleanup_free_ char *p = NULL; long m = 100, n; char **l; assert(ret); for (;;) { p = new(char, m); if (!p) return -ENOMEM; n = keyctl(KEYCTL_READ, (unsigned long) serial, (unsigned long) p, (unsigned long) m, 0); if (n < 0) return -errno; if (n < m) break; memory_erase(p, n); free(p); m *= 2; } l = strv_parse_nulstr(p, n); if (!l) return -ENOMEM; memory_erase(p, n); *ret = l; return 0; } static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **passwords) { _cleanup_strv_free_erase_ char **l = NULL; _cleanup_free_ char *p = NULL; key_serial_t serial; size_t n; int r; assert(keyname); assert(passwords); if (!(flags & ASK_PASSWORD_PUSH_CACHE)) return 0; r = lookup_key(keyname, &serial); if (r >= 0) { r = retrieve_key(serial, &l); if (r < 0) return r; } else if (r != -ENOKEY) return r; r = strv_extend_strv(&l, passwords, true); if (r <= 0) return r; r = strv_make_nulstr(l, &p, &n); if (r < 0) return r; /* Truncate trailing NUL */ assert(n > 0); assert(p[n-1] == 0); serial = add_key("user", keyname, p, n-1, KEY_SPEC_USER_KEYRING); memory_erase(p, n); if (serial == -1) return -errno; if (keyctl(KEYCTL_SET_TIMEOUT, (unsigned long) serial, (unsigned long) DIV_ROUND_UP(KEYRING_TIMEOUT_USEC, USEC_PER_SEC), 0, 0) < 0) log_debug_errno(errno, "Failed to adjust timeout: %m"); log_debug("Added key to keyring as %" PRIi32 ".", serial); return 1; } static int add_to_keyring_and_log(const char *keyname, AskPasswordFlags flags, char **passwords) { int r; assert(keyname); assert(passwords); r = add_to_keyring(keyname, flags, passwords); if (r < 0) return log_debug_errno(r, "Failed to add password to keyring: %m"); return 0; } int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret) { key_serial_t serial; int r; assert(keyname); assert(ret); if (!(flags & ASK_PASSWORD_ACCEPT_CACHED)) return -EUNATCH; r = lookup_key(keyname, &serial); if (r == -ENOSYS) /* when retrieving the distinction doesn't matter */ return -ENOKEY; if (r < 0) return r; return retrieve_key(serial, ret); } static void backspace_chars(int ttyfd, size_t p) { if (ttyfd < 0) return; while (p > 0) { p--; loop_write(ttyfd, "\b \b", 3, false); } } int ask_password_tty( const char *message, const char *keyname, usec_t until, AskPasswordFlags flags, const char *flag_file, char **ret) { struct termios old_termios, new_termios; char passphrase[LINE_MAX + 1] = {}, *x; size_t p = 0, codepoint = 0; int r; _cleanup_close_ int ttyfd = -1, notify = -1; struct pollfd pollfd[2]; bool reset_tty = false; bool dirty = false; enum { POLL_TTY, POLL_INOTIFY }; assert(ret); if (flags & ASK_PASSWORD_NO_TTY) return -EUNATCH; if (!message) message = "Password:"; if (flag_file) { notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); if (notify < 0) { r = -errno; goto finish; } if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0) { r = -errno; goto finish; } } ttyfd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC); if (ttyfd >= 0) { if (tcgetattr(ttyfd, &old_termios) < 0) { r = -errno; goto finish; } loop_write(ttyfd, ANSI_HIGHLIGHT, strlen(ANSI_HIGHLIGHT), false); loop_write(ttyfd, message, strlen(message), false); loop_write(ttyfd, " ", 1, false); loop_write(ttyfd, ANSI_NORMAL, strlen(ANSI_NORMAL), false); new_termios = old_termios; new_termios.c_lflag &= ~(ICANON|ECHO); new_termios.c_cc[VMIN] = 1; new_termios.c_cc[VTIME] = 0; if (tcsetattr(ttyfd, TCSADRAIN, &new_termios) < 0) { r = -errno; goto finish; } reset_tty = true; } zero(pollfd); pollfd[POLL_TTY].fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO; pollfd[POLL_TTY].events = POLLIN; pollfd[POLL_INOTIFY].fd = notify; pollfd[POLL_INOTIFY].events = POLLIN; for (;;) { char c; int sleep_for = -1, k; ssize_t n; if (until > 0) { usec_t y; y = now(CLOCK_MONOTONIC); if (y > until) { r = -ETIME; goto finish; } sleep_for = (int) ((until - y) / USEC_PER_MSEC); } if (flag_file) if (access(flag_file, F_OK) < 0) { r = -errno; goto finish; } k = poll(pollfd, notify >= 0 ? 2 : 1, sleep_for); if (k < 0) { if (errno == EINTR) continue; r = -errno; goto finish; } else if (k == 0) { r = -ETIME; goto finish; } if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0) flush_fd(notify); if (pollfd[POLL_TTY].revents == 0) continue; n = read(ttyfd >= 0 ? ttyfd : STDIN_FILENO, &c, 1); if (n < 0) { if (errno == EINTR || errno == EAGAIN) continue; r = -errno; goto finish; } else if (n == 0) break; if (c == '\n') break; else if (c == 21) { /* C-u */ if (!(flags & ASK_PASSWORD_SILENT)) backspace_chars(ttyfd, p); p = 0; } else if (c == '\b' || c == 127) { if (p > 0) { if (!(flags & ASK_PASSWORD_SILENT)) backspace_chars(ttyfd, 1); p--; } else if (!dirty && !(flags & ASK_PASSWORD_SILENT)) { flags |= ASK_PASSWORD_SILENT; /* There are two ways to enter silent * mode. Either by pressing backspace * as first key (and only as first * key), or ... */ if (ttyfd >= 0) loop_write(ttyfd, "(no echo) ", 10, false); } else if (ttyfd >= 0) loop_write(ttyfd, "\a", 1, false); } else if (c == '\t' && !(flags & ASK_PASSWORD_SILENT)) { backspace_chars(ttyfd, p); flags |= ASK_PASSWORD_SILENT; /* ... or by pressing TAB at any time. */ if (ttyfd >= 0) loop_write(ttyfd, "(no echo) ", 10, false); } else { if (p >= sizeof(passphrase)-1) { loop_write(ttyfd, "\a", 1, false); continue; } passphrase[p++] = c; if (!(flags & ASK_PASSWORD_SILENT) && ttyfd >= 0) { n = utf8_encoded_valid_unichar(passphrase + codepoint); if (n >= 0) { codepoint = p; loop_write(ttyfd, (flags & ASK_PASSWORD_ECHO) ? &c : "*", 1, false); } } dirty = true; } c = 'x'; } x = strndup(passphrase, p); memory_erase(passphrase, p); if (!x) { r = -ENOMEM; goto finish; } if (keyname) (void) add_to_keyring_and_log(keyname, flags, STRV_MAKE(x)); *ret = x; r = 0; finish: if (ttyfd >= 0 && reset_tty) { loop_write(ttyfd, "\n", 1, false); tcsetattr(ttyfd, TCSADRAIN, &old_termios); } return r; } static int create_socket(char **name) { union sockaddr_union sa = { .un.sun_family = AF_UNIX, }; _cleanup_close_ int fd = -1; static const int one = 1; char *c; int r; assert(name); fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (fd < 0) return -errno; snprintf(sa.un.sun_path, sizeof(sa.un.sun_path)-1, "/run/systemd/ask-password/sck.%" PRIx64, random_u64()); RUN_WITH_UMASK(0177) { if (bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) return -errno; } if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) return -errno; c = strdup(sa.un.sun_path); if (!c) return -ENOMEM; *name = c; r = fd; fd = -1; return r; } int ask_password_agent( const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flags, char ***ret) { enum { FD_SOCKET, FD_SIGNAL, _FD_MAX }; _cleanup_close_ int socket_fd = -1, signal_fd = -1, fd = -1; char temp[] = "/run/systemd/ask-password/tmp.XXXXXX"; char final[sizeof(temp)] = ""; _cleanup_free_ char *socket_name = NULL; _cleanup_strv_free_ char **l = NULL; _cleanup_fclose_ FILE *f = NULL; struct pollfd pollfd[_FD_MAX]; sigset_t mask, oldmask; int r; assert(ret); if (flags & ASK_PASSWORD_NO_AGENT) return -EUNATCH; assert_se(sigemptyset(&mask) >= 0); assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0); assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) >= 0); (void) mkdir_p_label("/run/systemd/ask-password", 0755); fd = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC); if (fd < 0) { r = fd; goto finish; } (void) fchmod(fd, 0644); f = fdopen(fd, "w"); if (!f) { r = -errno; goto finish; } fd = -1; signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); if (signal_fd < 0) { r = -errno; goto finish; } socket_fd = create_socket(&socket_name); if (socket_fd < 0) { r = socket_fd; goto finish; } fprintf(f, "[Ask]\n" "PID="PID_FMT"\n" "Socket=%s\n" "AcceptCached=%i\n" "Echo=%i\n" "NotAfter="USEC_FMT"\n", getpid(), socket_name, (flags & ASK_PASSWORD_ACCEPT_CACHED) ? 1 : 0, (flags & ASK_PASSWORD_ECHO) ? 1 : 0, until); if (message) fprintf(f, "Message=%s\n", message); if (icon) fprintf(f, "Icon=%s\n", icon); if (id) fprintf(f, "Id=%s\n", id); r = fflush_and_check(f); if (r < 0) goto finish; memcpy(final, temp, sizeof(temp)); final[sizeof(final)-11] = 'a'; final[sizeof(final)-10] = 's'; final[sizeof(final)-9] = 'k'; if (rename(temp, final) < 0) { r = -errno; goto finish; } zero(pollfd); pollfd[FD_SOCKET].fd = socket_fd; pollfd[FD_SOCKET].events = POLLIN; pollfd[FD_SIGNAL].fd = signal_fd; pollfd[FD_SIGNAL].events = POLLIN; for (;;) { char passphrase[LINE_MAX+1]; struct msghdr msghdr; struct iovec iovec; struct ucred *ucred; union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; } control; ssize_t n; int k; usec_t t; t = now(CLOCK_MONOTONIC); if (until > 0 && until <= t) { r = -ETIME; goto finish; } k = poll(pollfd, _FD_MAX, until > 0 ? (int) ((until-t)/USEC_PER_MSEC) : -1); if (k < 0) { if (errno == EINTR) continue; r = -errno; goto finish; } if (k <= 0) { r = -ETIME; goto finish; } if (pollfd[FD_SIGNAL].revents & POLLIN) { r = -EINTR; goto finish; } if (pollfd[FD_SOCKET].revents != POLLIN) { r = -EIO; goto finish; } zero(iovec); iovec.iov_base = passphrase; iovec.iov_len = sizeof(passphrase); zero(control); zero(msghdr); msghdr.msg_iov = &iovec; msghdr.msg_iovlen = 1; msghdr.msg_control = &control; msghdr.msg_controllen = sizeof(control); n = recvmsg(socket_fd, &msghdr, 0); if (n < 0) { if (errno == EAGAIN || errno == EINTR) continue; r = -errno; goto finish; } cmsg_close_all(&msghdr); if (n <= 0) { log_debug("Message too short"); continue; } if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) || control.cmsghdr.cmsg_level != SOL_SOCKET || control.cmsghdr.cmsg_type != SCM_CREDENTIALS || control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) { log_debug("Received message without credentials. Ignoring."); continue; } ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr); if (ucred->uid != 0) { log_debug("Got request from unprivileged user. Ignoring."); continue; } if (passphrase[0] == '+') { /* An empty message refers to the empty password */ if (n == 1) l = strv_new("", NULL); else l = strv_parse_nulstr(passphrase+1, n-1); memory_erase(passphrase, n); if (!l) { r = -ENOMEM; goto finish; } if (strv_length(l) <= 0) { l = strv_free(l); log_debug("Invalid packet"); continue; } break; } if (passphrase[0] == '-') { r = -ECANCELED; goto finish; } log_debug("Invalid packet"); } if (keyname) (void) add_to_keyring_and_log(keyname, flags, l); *ret = l; l = NULL; r = 0; finish: if (socket_name) (void) unlink(socket_name); (void) unlink(temp); if (final[0]) (void) unlink(final); assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0); return r; } int ask_password_auto( const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flags, char ***ret) { int r; assert(ret); if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname) { r = ask_password_keyring(keyname, flags, ret); if (r != -ENOKEY) return r; } if (!(flags & ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO)) { char *s = NULL, **l = NULL; r = ask_password_tty(message, keyname, until, flags, NULL, &s); if (r < 0) return r; r = strv_push(&l, s); if (r < 0) { string_erase(s); free(s); return -ENOMEM; } *ret = l; return 0; } if (!(flags & ASK_PASSWORD_NO_AGENT)) return ask_password_agent(message, icon, id, keyname, until, flags, ret); return -EUNATCH; } systemd-229/src/shared/ask-password-api.h000066400000000000000000000032521265713322000204560ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "time-util.h" typedef enum AskPasswordFlags { ASK_PASSWORD_ACCEPT_CACHED = 1, ASK_PASSWORD_PUSH_CACHE = 2, ASK_PASSWORD_ECHO = 4, /* show the password literally while reading, instead of "*" */ ASK_PASSWORD_SILENT = 8, /* do no show any password at all while reading */ ASK_PASSWORD_NO_TTY = 16, ASK_PASSWORD_NO_AGENT = 32, } AskPasswordFlags; int ask_password_tty(const char *message, const char *keyname, usec_t until, AskPasswordFlags flags, const char *flag_file, char **ret); int ask_password_agent(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret); int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret); int ask_password_auto(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret); systemd-229/src/shared/base-filesystem.c000066400000000000000000000115751265713322000203670ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "alloc-util.h" #include "base-filesystem.h" #include "fd-util.h" #include "log.h" #include "macro.h" #include "string-util.h" #include "umask-util.h" #include "user-util.h" #include "util.h" typedef struct BaseFilesystem { const char *dir; mode_t mode; const char *target; const char *exists; bool ignore_failure; } BaseFilesystem; static const BaseFilesystem table[] = { { "bin", 0, "usr/bin\0", NULL }, { "lib", 0, "usr/lib\0", NULL }, { "root", 0755, NULL, NULL, true }, { "sbin", 0, "usr/sbin\0", NULL }, { "usr", 0755, NULL, NULL }, { "var", 0755, NULL, NULL }, { "etc", 0755, NULL, NULL }, #if defined(__i386__) || defined(__x86_64__) { "lib64", 0, "usr/lib/x86_64-linux-gnu\0" "usr/lib64\0", "ld-linux-x86-64.so.2" }, #endif }; int base_filesystem_create(const char *root, uid_t uid, gid_t gid) { _cleanup_close_ int fd = -1; unsigned i; int r = 0; fd = open(root, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); if (fd < 0) return log_error_errno(errno, "Failed to open root file system: %m"); for (i = 0; i < ELEMENTSOF(table); i ++) { if (faccessat(fd, table[i].dir, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) continue; if (table[i].target) { const char *target = NULL, *s; /* check if one of the targets exists */ NULSTR_FOREACH(s, table[i].target) { if (faccessat(fd, s, F_OK, AT_SYMLINK_NOFOLLOW) < 0) continue; /* check if a specific file exists at the target path */ if (table[i].exists) { _cleanup_free_ char *p = NULL; p = strjoin(s, "/", table[i].exists, NULL); if (!p) return log_oom(); if (faccessat(fd, p, F_OK, AT_SYMLINK_NOFOLLOW) < 0) continue; } target = s; break; } if (!target) continue; r = symlinkat(target, fd, table[i].dir); if (r < 0 && errno != EEXIST) return log_error_errno(errno, "Failed to create symlink at %s/%s: %m", root, table[i].dir); if (uid != UID_INVALID || gid != UID_INVALID) { if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0) return log_error_errno(errno, "Failed to chown symlink at %s/%s: %m", root, table[i].dir); } continue; } RUN_WITH_UMASK(0000) r = mkdirat(fd, table[i].dir, table[i].mode); if (r < 0 && errno != EEXIST) { log_full_errno(table[i].ignore_failure ? LOG_DEBUG : LOG_ERR, errno, "Failed to create directory at %s/%s: %m", root, table[i].dir); if (!table[i].ignore_failure) return -errno; } if (uid != UID_INVALID || gid != UID_INVALID) { if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0) return log_error_errno(errno, "Failed to chown directory at %s/%s: %m", root, table[i].dir); } } return 0; } systemd-229/src/shared/base-filesystem.h000066400000000000000000000014621265713322000203660ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include int base_filesystem_create(const char *root, uid_t uid, gid_t gid); systemd-229/src/shared/boot-timestamps.c000066400000000000000000000037761265713322000204260ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering Copyright 2013 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "acpi-fpdt.h" #include "boot-timestamps.h" #include "efivars.h" #include "macro.h" #include "time-util.h" int boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader) { usec_t x = 0, y = 0, a; int r; dual_timestamp _n; assert(firmware); assert(loader); if (!n) { dual_timestamp_get(&_n); n = &_n; } r = acpi_get_boot_usec(&x, &y); if (r < 0) { r = efi_loader_get_boot_usec(&x, &y); if (r < 0) return r; } /* Let's convert this to timestamps where the firmware * began/loader began working. To make this more confusing: * since usec_t is unsigned and the kernel's monotonic clock * begins at kernel initialization we'll actually initialize * the monotonic timestamps here as negative of the actual * value. */ firmware->monotonic = y; loader->monotonic = y - x; a = n->monotonic + firmware->monotonic; firmware->realtime = n->realtime > a ? n->realtime - a : 0; a = n->monotonic + loader->monotonic; loader->realtime = n->realtime > a ? n->realtime - a : 0; return 0; } systemd-229/src/shared/boot-timestamps.h000066400000000000000000000015621265713322000204220ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering Copyright 2013 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include int boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader); systemd-229/src/shared/bus-util.c000066400000000000000000002242561265713322000170410ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include "sd-bus-protocol.h" #include "sd-bus.h" #include "sd-daemon.h" #include "sd-event.h" #include "sd-id128.h" #include "alloc-util.h" #include "bus-internal.h" #include "bus-label.h" #include "bus-message.h" #include "bus-util.h" #include "cgroup-util.h" #include "def.h" #include "env-util.h" #include "escape.h" #include "extract-word.h" #include "fd-util.h" #include "hashmap.h" #include "install.h" #include "kdbus.h" #include "log.h" #include "macro.h" #include "missing.h" #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" #include "process-util.h" #include "rlimit-util.h" #include "set.h" #include "signal-util.h" #include "stdio-util.h" #include "string-util.h" #include "strv.h" #include "syslog-util.h" #include "time-util.h" #include "unit-name.h" #include "user-util.h" #include "utf8.h" #include "util.h" static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { sd_event *e = userdata; assert(m); assert(e); sd_bus_close(sd_bus_message_get_bus(m)); sd_event_exit(e, 0); return 1; } int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) { _cleanup_free_ char *match = NULL; const char *unique; int r; assert(e); assert(bus); assert(name); /* We unregister the name here and then wait for the * NameOwnerChanged signal for this event to arrive before we * quit. We do this in order to make sure that any queued * requests are still processed before we really exit. */ r = sd_bus_get_unique_name(bus, &unique); if (r < 0) return r; r = asprintf(&match, "sender='org.freedesktop.DBus'," "type='signal'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'," "path='/org/freedesktop/DBus'," "arg0='%s'," "arg1='%s'," "arg2=''", name, unique); if (r < 0) return -ENOMEM; r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e); if (r < 0) return r; r = sd_bus_release_name(bus, name); if (r < 0) return r; return 0; } int bus_event_loop_with_idle( sd_event *e, sd_bus *bus, const char *name, usec_t timeout, check_idle_t check_idle, void *userdata) { bool exiting = false; int r, code; assert(e); assert(bus); assert(name); for (;;) { bool idle; r = sd_event_get_state(e); if (r < 0) return r; if (r == SD_EVENT_FINISHED) break; if (check_idle) idle = check_idle(userdata); else idle = true; r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout); if (r < 0) return r; if (r == 0 && !exiting && idle) { r = sd_bus_try_close(bus); if (r == -EBUSY) continue; /* Fallback for dbus1 connections: we * unregister the name and wait for the * response to come through for it */ if (r == -EOPNOTSUPP) { /* Inform the service manager that we * are going down, so that it will * queue all further start requests, * instead of assuming we are already * running. */ sd_notify(false, "STOPPING=1"); r = bus_async_unregister_and_exit(e, bus, name); if (r < 0) return r; exiting = true; continue; } if (r < 0) return r; sd_event_exit(e, 0); break; } } r = sd_event_get_exit_code(e, &code); if (r < 0) return r; return code; } int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *rep = NULL; int r, has_owner = 0; assert(c); assert(name); r = sd_bus_call_method(c, "org.freedesktop.DBus", "/org/freedesktop/dbus", "org.freedesktop.DBus", "NameHasOwner", error, &rep, "s", name); if (r < 0) return r; r = sd_bus_message_read_basic(rep, 'b', &has_owner); if (r < 0) return sd_bus_error_set_errno(error, r); return has_owner; } static int check_good_user(sd_bus_message *m, uid_t good_user) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; uid_t sender_uid; int r; assert(m); if (good_user == UID_INVALID) return 0; r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds); if (r < 0) return r; /* Don't trust augmented credentials for authorization */ assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM); r = sd_bus_creds_get_euid(creds, &sender_uid); if (r < 0) return r; return sender_uid == good_user; } int bus_test_polkit( sd_bus_message *call, int capability, const char *action, const char **details, uid_t good_user, bool *_challenge, sd_bus_error *e) { int r; assert(call); assert(action); /* Tests non-interactively! */ r = check_good_user(call, good_user); if (r != 0) return r; r = sd_bus_query_sender_privilege(call, capability); if (r < 0) return r; else if (r > 0) return 1; #ifdef ENABLE_POLKIT else { _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int authorized = false, challenge = false; const char *sender, **k, **v; sender = sd_bus_message_get_sender(call); if (!sender) return -EBADMSG; r = sd_bus_message_new_method_call( call->bus, &request, "org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority", "org.freedesktop.PolicyKit1.Authority", "CheckAuthorization"); if (r < 0) return r; r = sd_bus_message_append( request, "(sa{sv})s", "system-bus-name", 1, "name", "s", sender, action); if (r < 0) return r; r = sd_bus_message_open_container(request, 'a', "{ss}"); if (r < 0) return r; STRV_FOREACH_PAIR(k, v, details) { r = sd_bus_message_append(request, "{ss}", *k, *v); if (r < 0) return r; } r = sd_bus_message_close_container(request); if (r < 0) return r; r = sd_bus_message_append(request, "us", 0, NULL); if (r < 0) return r; r = sd_bus_call(call->bus, request, 0, e, &reply); if (r < 0) { /* Treat no PK available as access denied */ if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) { sd_bus_error_free(e); return -EACCES; } return r; } r = sd_bus_message_enter_container(reply, 'r', "bba{ss}"); if (r < 0) return r; r = sd_bus_message_read(reply, "bb", &authorized, &challenge); if (r < 0) return r; if (authorized) return 1; if (_challenge) { *_challenge = challenge; return 0; } } #endif return -EACCES; } #ifdef ENABLE_POLKIT typedef struct AsyncPolkitQuery { sd_bus_message *request, *reply; sd_bus_message_handler_t callback; void *userdata; sd_bus_slot *slot; Hashmap *registry; } AsyncPolkitQuery; static void async_polkit_query_free(AsyncPolkitQuery *q) { if (!q) return; sd_bus_slot_unref(q->slot); if (q->registry && q->request) hashmap_remove(q->registry, q->request); sd_bus_message_unref(q->request); sd_bus_message_unref(q->reply); free(q); } static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; AsyncPolkitQuery *q = userdata; int r; assert(reply); assert(q); q->slot = sd_bus_slot_unref(q->slot); q->reply = sd_bus_message_ref(reply); r = sd_bus_message_rewind(q->request, true); if (r < 0) { r = sd_bus_reply_method_errno(q->request, r, NULL); goto finish; } r = q->callback(q->request, q->userdata, &error_buffer); r = bus_maybe_reply_error(q->request, r, &error_buffer); finish: async_polkit_query_free(q); return r; } #endif int bus_verify_polkit_async( sd_bus_message *call, int capability, const char *action, const char **details, bool interactive, uid_t good_user, Hashmap **registry, sd_bus_error *error) { #ifdef ENABLE_POLKIT _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL; AsyncPolkitQuery *q; const char *sender, **k, **v; sd_bus_message_handler_t callback; void *userdata; int c; #endif int r; assert(call); assert(action); assert(registry); r = check_good_user(call, good_user); if (r != 0) return r; #ifdef ENABLE_POLKIT q = hashmap_get(*registry, call); if (q) { int authorized, challenge; /* This is the second invocation of this function, and * there's already a response from polkit, let's * process it */ assert(q->reply); if (sd_bus_message_is_method_error(q->reply, NULL)) { const sd_bus_error *e; /* Copy error from polkit reply */ e = sd_bus_message_get_error(q->reply); sd_bus_error_copy(error, e); /* Treat no PK available as access denied */ if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) return -EACCES; return -sd_bus_error_get_errno(e); } r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}"); if (r >= 0) r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge); if (r < 0) return r; if (authorized) return 1; if (challenge) return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required."); return -EACCES; } #endif r = sd_bus_query_sender_privilege(call, capability); if (r < 0) return r; else if (r > 0) return 1; #ifdef ENABLE_POLKIT if (sd_bus_get_current_message(call->bus) != call) return -EINVAL; callback = sd_bus_get_current_handler(call->bus); if (!callback) return -EINVAL; userdata = sd_bus_get_current_userdata(call->bus); sender = sd_bus_message_get_sender(call); if (!sender) return -EBADMSG; c = sd_bus_message_get_allow_interactive_authorization(call); if (c < 0) return c; if (c > 0) interactive = true; r = hashmap_ensure_allocated(registry, NULL); if (r < 0) return r; r = sd_bus_message_new_method_call( call->bus, &pk, "org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority", "org.freedesktop.PolicyKit1.Authority", "CheckAuthorization"); if (r < 0) return r; r = sd_bus_message_append( pk, "(sa{sv})s", "system-bus-name", 1, "name", "s", sender, action); if (r < 0) return r; r = sd_bus_message_open_container(pk, 'a', "{ss}"); if (r < 0) return r; STRV_FOREACH_PAIR(k, v, details) { r = sd_bus_message_append(pk, "{ss}", *k, *v); if (r < 0) return r; } r = sd_bus_message_close_container(pk); if (r < 0) return r; r = sd_bus_message_append(pk, "us", !!interactive, NULL); if (r < 0) return r; q = new0(AsyncPolkitQuery, 1); if (!q) return -ENOMEM; q->request = sd_bus_message_ref(call); q->callback = callback; q->userdata = userdata; r = hashmap_put(*registry, call, q); if (r < 0) { async_polkit_query_free(q); return r; } q->registry = *registry; r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0); if (r < 0) { async_polkit_query_free(q); return r; } return 0; #endif return -EACCES; } void bus_verify_polkit_async_registry_free(Hashmap *registry) { #ifdef ENABLE_POLKIT AsyncPolkitQuery *q; while ((q = hashmap_steal_first(registry))) async_polkit_query_free(q); hashmap_free(registry); #endif } int bus_check_peercred(sd_bus *c) { struct ucred ucred; socklen_t l; int fd; assert(c); fd = sd_bus_get_fd(c); if (fd < 0) return fd; l = sizeof(struct ucred); if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0) return -errno; if (l != sizeof(struct ucred)) return -E2BIG; if (ucred.uid != 0 && ucred.uid != geteuid()) return -EPERM; return 1; } int bus_connect_system_systemd(sd_bus **_bus) { _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; int r; assert(_bus); if (geteuid() != 0) return sd_bus_default_system(_bus); /* If we are root and kdbus is not available, then let's talk * directly to the system instance, instead of going via the * bus */ r = sd_bus_new(&bus); if (r < 0) return r; r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS); if (r < 0) return r; bus->bus_client = true; r = sd_bus_start(bus); if (r >= 0) { *_bus = bus; bus = NULL; return 0; } bus = sd_bus_unref(bus); r = sd_bus_new(&bus); if (r < 0) return r; r = sd_bus_set_address(bus, "unix:path=/run/systemd/private"); if (r < 0) return r; r = sd_bus_start(bus); if (r < 0) return sd_bus_default_system(_bus); r = bus_check_peercred(bus); if (r < 0) return r; *_bus = bus; bus = NULL; return 0; } int bus_connect_user_systemd(sd_bus **_bus) { _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; _cleanup_free_ char *ee = NULL; const char *e; int r; /* Try via kdbus first, and then directly */ assert(_bus); r = sd_bus_new(&bus); if (r < 0) return r; if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0) return -ENOMEM; bus->bus_client = true; r = sd_bus_start(bus); if (r >= 0) { *_bus = bus; bus = NULL; return 0; } bus = sd_bus_unref(bus); e = secure_getenv("XDG_RUNTIME_DIR"); if (!e) return sd_bus_default_user(_bus); ee = bus_address_escape(e); if (!ee) return -ENOMEM; r = sd_bus_new(&bus); if (r < 0) return r; bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL); if (!bus->address) return -ENOMEM; r = sd_bus_start(bus); if (r < 0) return sd_bus_default_user(_bus); r = bus_check_peercred(bus); if (r < 0) return r; *_bus = bus; bus = NULL; return 0; } int bus_print_property(const char *name, sd_bus_message *property, bool all) { char type; const char *contents; int r; assert(name); assert(property); r = sd_bus_message_peek_type(property, &type, &contents); if (r < 0) return r; switch (type) { case SD_BUS_TYPE_STRING: { const char *s; r = sd_bus_message_read_basic(property, type, &s); if (r < 0) return r; if (all || !isempty(s)) { _cleanup_free_ char *escaped = NULL; escaped = xescape(s, "\n"); if (!escaped) return -ENOMEM; printf("%s=%s\n", name, escaped); } return 1; } case SD_BUS_TYPE_BOOLEAN: { int b; r = sd_bus_message_read_basic(property, type, &b); if (r < 0) return r; printf("%s=%s\n", name, yes_no(b)); return 1; } case SD_BUS_TYPE_UINT64: { uint64_t u; r = sd_bus_message_read_basic(property, type, &u); if (r < 0) return r; /* Yes, heuristics! But we can change this check * should it turn out to not be sufficient */ if (endswith(name, "Timestamp")) { char timestamp[FORMAT_TIMESTAMP_MAX], *t; t = format_timestamp(timestamp, sizeof(timestamp), u); if (t || all) printf("%s=%s\n", name, strempty(t)); } else if (strstr(name, "USec")) { char timespan[FORMAT_TIMESPAN_MAX]; printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0)); } else printf("%s=%llu\n", name, (unsigned long long) u); return 1; } case SD_BUS_TYPE_INT64: { int64_t i; r = sd_bus_message_read_basic(property, type, &i); if (r < 0) return r; printf("%s=%lld\n", name, (long long) i); return 1; } case SD_BUS_TYPE_UINT32: { uint32_t u; r = sd_bus_message_read_basic(property, type, &u); if (r < 0) return r; if (strstr(name, "UMask") || strstr(name, "Mode")) printf("%s=%04o\n", name, u); else printf("%s=%u\n", name, (unsigned) u); return 1; } case SD_BUS_TYPE_INT32: { int32_t i; r = sd_bus_message_read_basic(property, type, &i); if (r < 0) return r; printf("%s=%i\n", name, (int) i); return 1; } case SD_BUS_TYPE_DOUBLE: { double d; r = sd_bus_message_read_basic(property, type, &d); if (r < 0) return r; printf("%s=%g\n", name, d); return 1; } case SD_BUS_TYPE_ARRAY: if (streq(contents, "s")) { bool first = true; const char *str; r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents); if (r < 0) return r; while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) { _cleanup_free_ char *escaped = NULL; if (first) printf("%s=", name); escaped = xescape(str, "\n "); if (!escaped) return -ENOMEM; printf("%s%s", first ? "" : " ", escaped); first = false; } if (r < 0) return r; if (first && all) printf("%s=", name); if (!first || all) puts(""); r = sd_bus_message_exit_container(property); if (r < 0) return r; return 1; } else if (streq(contents, "y")) { const uint8_t *u; size_t n; r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n); if (r < 0) return r; if (all || n > 0) { unsigned int i; printf("%s=", name); for (i = 0; i < n; i++) printf("%02x", u[i]); puts(""); } return 1; } else if (streq(contents, "u")) { uint32_t *u; size_t n; r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n); if (r < 0) return r; if (all || n > 0) { unsigned int i; printf("%s=", name); for (i = 0; i < n; i++) printf("%08x", u[i]); puts(""); } return 1; } break; } return 0; } int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); assert(path); r = sd_bus_call_method(bus, dest, path, "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", ""); if (r < 0) return r; r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}"); if (r < 0) return r; while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { const char *name; const char *contents; r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name); if (r < 0) return r; if (!filter || strv_find(filter, name)) { r = sd_bus_message_peek_type(reply, NULL, &contents); if (r < 0) return r; r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents); if (r < 0) return r; r = bus_print_property(name, reply, all); if (r < 0) return r; if (r == 0) { if (all) printf("%s=[unprintable]\n", name); /* skip what we didn't read */ r = sd_bus_message_skip(reply, contents); if (r < 0) return r; } r = sd_bus_message_exit_container(reply); if (r < 0) return r; } else { r = sd_bus_message_skip(reply, "v"); if (r < 0) return r; } r = sd_bus_message_exit_container(reply); if (r < 0) return r; } if (r < 0) return r; r = sd_bus_message_exit_container(reply); if (r < 0) return r; return 0; } int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { sd_id128_t *p = userdata; const void *v; size_t n; int r; r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n); if (r < 0) return r; if (n == 0) *p = SD_ID128_NULL; else if (n == 16) memcpy((*p).bytes, v, n); else return -EINVAL; return 0; } static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { char type; int r; r = sd_bus_message_peek_type(m, &type, NULL); if (r < 0) return r; switch (type) { case SD_BUS_TYPE_STRING: { const char *s; char **p = userdata; r = sd_bus_message_read_basic(m, type, &s); if (r < 0) break; if (isempty(s)) break; r = free_and_strdup(p, s); break; } case SD_BUS_TYPE_ARRAY: { _cleanup_strv_free_ char **l = NULL; char ***p = userdata; r = bus_message_read_strv_extend(m, &l); if (r < 0) break; strv_free(*p); *p = l; l = NULL; break; } case SD_BUS_TYPE_BOOLEAN: { unsigned b; bool *p = userdata; r = sd_bus_message_read_basic(m, type, &b); if (r < 0) break; *p = b; break; } case SD_BUS_TYPE_UINT32: { uint64_t u; uint32_t *p = userdata; r = sd_bus_message_read_basic(m, type, &u); if (r < 0) break; *p = u; break; } case SD_BUS_TYPE_UINT64: { uint64_t t; uint64_t *p = userdata; r = sd_bus_message_read_basic(m, type, &t); if (r < 0) break; *p = t; break; } default: break; } return r; } int bus_message_map_all_properties( sd_bus_message *m, const struct bus_properties_map *map, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(m); assert(map); r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}"); if (r < 0) return r; while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { const struct bus_properties_map *prop; const char *member; const char *contents; void *v; unsigned i; r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member); if (r < 0) return r; for (i = 0, prop = NULL; map[i].member; i++) if (streq(map[i].member, member)) { prop = &map[i]; break; } if (prop) { r = sd_bus_message_peek_type(m, NULL, &contents); if (r < 0) return r; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents); if (r < 0) return r; v = (uint8_t *)userdata + prop->offset; if (map[i].set) r = prop->set(sd_bus_message_get_bus(m), member, m, &error, v); else r = map_basic(sd_bus_message_get_bus(m), member, m, &error, v); if (r < 0) return r; r = sd_bus_message_exit_container(m); if (r < 0) return r; } else { r = sd_bus_message_skip(m, "v"); if (r < 0) return r; } r = sd_bus_message_exit_container(m); if (r < 0) return r; } if (r < 0) return r; return sd_bus_message_exit_container(m); } int bus_message_map_properties_changed( sd_bus_message *m, const struct bus_properties_map *map, void *userdata) { const char *member; int r, invalidated, i; assert(m); assert(map); r = bus_message_map_all_properties(m, map, userdata); if (r < 0) return r; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s"); if (r < 0) return r; invalidated = 0; while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0) for (i = 0; map[i].member; i++) if (streq(map[i].member, member)) { ++invalidated; break; } if (r < 0) return r; r = sd_bus_message_exit_container(m); if (r < 0) return r; return invalidated; } int bus_map_all_properties( sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map, void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); assert(destination); assert(path); assert(map); r = sd_bus_call_method( bus, destination, path, "org.freedesktop.DBus.Properties", "GetAll", &error, &m, "s", ""); if (r < 0) return r; return bus_message_map_all_properties(m, map, userdata); } int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) { int r; assert(transport >= 0); assert(transport < _BUS_TRANSPORT_MAX); assert(bus); assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL); assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP); switch (transport) { case BUS_TRANSPORT_LOCAL: if (user) r = sd_bus_default_user(bus); else r = sd_bus_default_system(bus); break; case BUS_TRANSPORT_REMOTE: r = sd_bus_open_system_remote(bus, host); break; case BUS_TRANSPORT_MACHINE: r = sd_bus_open_system_machine(bus, host); break; default: assert_not_reached("Hmm, unknown transport type."); } return r; } int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) { int r; assert(transport >= 0); assert(transport < _BUS_TRANSPORT_MAX); assert(bus); assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL); assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP); switch (transport) { case BUS_TRANSPORT_LOCAL: if (user) r = bus_connect_user_systemd(bus); else r = bus_connect_system_systemd(bus); break; case BUS_TRANSPORT_REMOTE: r = sd_bus_open_system_remote(bus, host); break; case BUS_TRANSPORT_MACHINE: r = sd_bus_open_system_machine(bus, host); break; default: assert_not_reached("Hmm, unknown transport type."); } return r; } int bus_property_get_bool( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { int b = *(bool*) userdata; return sd_bus_message_append_basic(reply, 'b', &b); } #if __SIZEOF_SIZE_T__ != 8 int bus_property_get_size( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { uint64_t sz = *(size_t*) userdata; return sd_bus_message_append_basic(reply, 't', &sz); } #endif #if __SIZEOF_LONG__ != 8 int bus_property_get_long( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { int64_t l = *(long*) userdata; return sd_bus_message_append_basic(reply, 'x', &l); } int bus_property_get_ulong( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { uint64_t ul = *(unsigned long*) userdata; return sd_bus_message_append_basic(reply, 't', &ul); } #endif int bus_log_parse_error(int r) { return log_error_errno(r, "Failed to parse bus message: %m"); } int bus_log_create_error(int r) { return log_error_errno(r, "Failed to create bus message: %m"); } int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) { assert(message); assert(u); u->machine = NULL; return sd_bus_message_read( message, "(ssssssouso)", &u->id, &u->description, &u->load_state, &u->active_state, &u->sub_state, &u->following, &u->unit_path, &u->job_id, &u->job_type, &u->job_path); } int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) { const char *eq, *field; int r, rl; assert(m); assert(assignment); eq = strchr(assignment, '='); if (!eq) { log_error("Not an assignment: %s", assignment); return -EINVAL; } r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); if (r < 0) return bus_log_create_error(r); field = strndupa(assignment, eq - assignment); eq ++; if (streq(field, "CPUQuota")) { if (isempty(eq)) r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", USEC_INFINITY); else if (endswith(eq, "%")) { double percent; if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) { log_error("CPU quota '%s' invalid.", eq); return -EINVAL; } r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", (usec_t) percent * USEC_PER_SEC / 100); } else { log_error("CPU quota needs to be in percent."); return -EINVAL; } goto finish; } else if (streq(field, "EnvironmentFile")) { r = sd_bus_message_append(m, "sv", "EnvironmentFiles", "a(sb)", 1, eq[0] == '-' ? eq + 1 : eq, eq[0] == '-'); goto finish; } else if (STR_IN_SET(field, "AccuracySec", "RandomizedDelaySec", "RuntimeMaxSec")) { char *n; usec_t t; size_t l; r = parse_sec(eq, &t); if (r < 0) return log_error_errno(r, "Failed to parse %s= parameter: %s", field, eq); l = strlen(field); n = newa(char, l + 2); if (!n) return log_oom(); /* Change suffix Sec → USec */ strcpy(mempcpy(n, field, l - 3), "USec"); r = sd_bus_message_append(m, "sv", n, "t", t); goto finish; } r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field); if (r < 0) return bus_log_create_error(r); rl = rlimit_from_string(field); if (rl >= 0) { const char *sn; struct rlimit l; r = rlimit_parse(rl, eq, &l); if (r < 0) return log_error_errno(r, "Failed to parse resource limit: %s", eq); r = sd_bus_message_append(m, "v", "t", l.rlim_max); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); if (r < 0) return bus_log_create_error(r); sn = strjoina(field, "Soft"); r = sd_bus_message_append(m, "sv", sn, "t", l.rlim_cur); } else if (STR_IN_SET(field, "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting", "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies", "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit", "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges", "SyslogLevelPrefix", "Delegate", "RemainAfterElapse")) { r = parse_boolean(eq); if (r < 0) return log_error_errno(r, "Failed to parse boolean assignment %s.", assignment); r = sd_bus_message_append(m, "v", "b", r); } else if (streq(field, "MemoryLimit")) { uint64_t bytes; if (isempty(eq) || streq(eq, "infinity")) bytes = (uint64_t) -1; else { r = parse_size(eq, 1024, &bytes); if (r < 0) { log_error("Failed to parse bytes specification %s", assignment); return -EINVAL; } } r = sd_bus_message_append(m, "v", "t", bytes); } else if (streq(field, "TasksMax")) { uint64_t n; if (isempty(eq) || streq(eq, "infinity")) n = (uint64_t) -1; else { r = safe_atou64(eq, &n); if (r < 0) { log_error("Failed to parse maximum tasks specification %s", assignment); return -EINVAL; } } r = sd_bus_message_append(m, "v", "t", n); } else if (STR_IN_SET(field, "CPUShares", "StartupCPUShares")) { uint64_t u; r = cg_cpu_shares_parse(eq, &u); if (r < 0) { log_error("Failed to parse %s value %s.", field, eq); return -EINVAL; } r = sd_bus_message_append(m, "v", "t", u); } else if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight")) { uint64_t u; r = cg_cpu_shares_parse(eq, &u); if (r < 0) { log_error("Failed to parse %s value %s.", field, eq); return -EINVAL; } r = sd_bus_message_append(m, "v", "t", u); } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode", "UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath", "StandardInput", "StandardOutput", "StandardError", "Description", "Slice", "Type", "WorkingDirectory", "RootDirectory", "SyslogIdentifier", "ProtectSystem", "ProtectHome")) r = sd_bus_message_append(m, "v", "s", eq); else if (streq(field, "SyslogLevel")) { int level; level = log_level_from_string(eq); if (level < 0) { log_error("Failed to parse %s value %s.", field, eq); return -EINVAL; } r = sd_bus_message_append(m, "v", "i", level); } else if (streq(field, "SyslogFacility")) { int facility; facility = log_facility_unshifted_from_string(eq); if (facility < 0) { log_error("Failed to parse %s value %s.", field, eq); return -EINVAL; } r = sd_bus_message_append(m, "v", "i", facility); } else if (streq(field, "DeviceAllow")) { if (isempty(eq)) r = sd_bus_message_append(m, "v", "a(ss)", 0); else { const char *path, *rwm, *e; e = strchr(eq, ' '); if (e) { path = strndupa(eq, e - eq); rwm = e+1; } else { path = eq; rwm = ""; } if (!path_startswith(path, "/dev")) { log_error("%s is not a device file in /dev.", path); return -EINVAL; } r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm); } } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) { if (isempty(eq)) r = sd_bus_message_append(m, "v", "a(st)", 0); else { const char *path, *bandwidth, *e; uint64_t bytes; e = strchr(eq, ' '); if (e) { path = strndupa(eq, e - eq); bandwidth = e+1; } else { log_error("Failed to parse %s value %s.", field, eq); return -EINVAL; } if (!path_startswith(path, "/dev")) { log_error("%s is not a device file in /dev.", path); return -EINVAL; } r = parse_size(bandwidth, 1000, &bytes); if (r < 0) { log_error("Failed to parse byte value %s.", bandwidth); return -EINVAL; } r = sd_bus_message_append(m, "v", "a(st)", 1, path, bytes); } } else if (streq(field, "BlockIODeviceWeight")) { if (isempty(eq)) r = sd_bus_message_append(m, "v", "a(st)", 0); else { const char *path, *weight, *e; uint64_t u; e = strchr(eq, ' '); if (e) { path = strndupa(eq, e - eq); weight = e+1; } else { log_error("Failed to parse %s value %s.", field, eq); return -EINVAL; } if (!path_startswith(path, "/dev")) { log_error("%s is not a device file in /dev.", path); return -EINVAL; } r = safe_atou64(weight, &u); if (r < 0) { log_error("Failed to parse %s value %s.", field, weight); return -EINVAL; } r = sd_bus_message_append(m, "v", "a(st)", path, u); } } else if (streq(field, "Nice")) { int32_t i; r = safe_atoi32(eq, &i); if (r < 0) { log_error("Failed to parse %s value %s.", field, eq); return -EINVAL; } r = sd_bus_message_append(m, "v", "i", i); } else if (STR_IN_SET(field, "Environment", "PassEnvironment")) { const char *p; r = sd_bus_message_open_container(m, 'v', "as"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'a', "s"); if (r < 0) return bus_log_create_error(r); p = eq; for (;;) { _cleanup_free_ char *word = NULL; r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE); if (r < 0) { log_error("Failed to parse Environment value %s", eq); return -EINVAL; } if (r == 0) break; if (streq(field, "Environment")) { if (!env_assignment_is_valid(word)) { log_error("Invalid environment assignment: %s", word); return -EINVAL; } } else { /* PassEnvironment */ if (!env_name_is_valid(word)) { log_error("Invalid environment variable name: %s", word); return -EINVAL; } } r = sd_bus_message_append_basic(m, 's', word); if (r < 0) return bus_log_create_error(r); } r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); } else if (streq(field, "KillSignal")) { int sig; sig = signal_from_string_try_harder(eq); if (sig < 0) { log_error("Failed to parse %s value %s.", field, eq); return -EINVAL; } r = sd_bus_message_append(m, "v", "i", sig); } else if (streq(field, "TimerSlackNSec")) { nsec_t n; r = parse_nsec(eq, &n); if (r < 0) { log_error("Failed to parse %s value %s", field, eq); return -EINVAL; } r = sd_bus_message_append(m, "v", "t", n); } else if (streq(field, "OOMScoreAdjust")) { int oa; r = safe_atoi(eq, &oa); if (r < 0) { log_error("Failed to parse %s value %s", field, eq); return -EINVAL; } if (!oom_score_adjust_is_valid(oa)) { log_error("OOM score adjust value out of range"); return -EINVAL; } r = sd_bus_message_append(m, "v", "i", oa); } else if (STR_IN_SET(field, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) { const char *p; r = sd_bus_message_open_container(m, 'v', "as"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'a', "s"); if (r < 0) return bus_log_create_error(r); p = eq; for (;;) { _cleanup_free_ char *word = NULL; int offset; r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES); if (r < 0) { log_error("Failed to parse %s value %s", field, eq); return -EINVAL; } if (r == 0) break; if (!utf8_is_valid(word)) { log_error("Failed to parse %s value %s", field, eq); return -EINVAL; } offset = word[0] == '-'; if (!path_is_absolute(word + offset)) { log_error("Failed to parse %s value %s", field, eq); return -EINVAL; } path_kill_slashes(word + offset); r = sd_bus_message_append_basic(m, 's', word); if (r < 0) return bus_log_create_error(r); } r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); } else if (streq(field, "RuntimeDirectory")) { const char *p; r = sd_bus_message_open_container(m, 'v', "as"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'a', "s"); if (r < 0) return bus_log_create_error(r); p = eq; for (;;) { _cleanup_free_ char *word = NULL; r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES); if (r < 0) return log_error_errno(r, "Failed to parse %s value %s", field, eq); if (r == 0) break; r = sd_bus_message_append_basic(m, 's', word); if (r < 0) return bus_log_create_error(r); } r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); } else { log_error("Unknown assignment %s.", assignment); return -EINVAL; } finish: if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); return 0; } typedef struct BusWaitForJobs { sd_bus *bus; Set *jobs; char *name; char *result; sd_bus_slot *slot_job_removed; sd_bus_slot *slot_disconnected; } BusWaitForJobs; static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) { assert(m); log_error("Warning! D-Bus connection terminated."); sd_bus_close(sd_bus_message_get_bus(m)); return 0; } static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { const char *path, *unit, *result; BusWaitForJobs *d = userdata; uint32_t id; char *found; int r; assert(m); assert(d); r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result); if (r < 0) { bus_log_parse_error(r); return 0; } found = set_remove(d->jobs, (char*) path); if (!found) return 0; free(found); if (!isempty(result)) d->result = strdup(result); if (!isempty(unit)) d->name = strdup(unit); return 0; } void bus_wait_for_jobs_free(BusWaitForJobs *d) { if (!d) return; set_free_free(d->jobs); sd_bus_slot_unref(d->slot_disconnected); sd_bus_slot_unref(d->slot_job_removed); sd_bus_unref(d->bus); free(d->name); free(d->result); free(d); } int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) { _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL; int r; assert(bus); assert(ret); d = new0(BusWaitForJobs, 1); if (!d) return -ENOMEM; d->bus = sd_bus_ref(bus); /* When we are a bus client we match by sender. Direct * connections OTOH have no initialized sender field, and * hence we ignore the sender then */ r = sd_bus_add_match( bus, &d->slot_job_removed, bus->bus_client ? "type='signal'," "sender='org.freedesktop.systemd1'," "interface='org.freedesktop.systemd1.Manager'," "member='JobRemoved'," "path='/org/freedesktop/systemd1'" : "type='signal'," "interface='org.freedesktop.systemd1.Manager'," "member='JobRemoved'," "path='/org/freedesktop/systemd1'", match_job_removed, d); if (r < 0) return r; r = sd_bus_add_match( bus, &d->slot_disconnected, "type='signal'," "sender='org.freedesktop.DBus.Local'," "interface='org.freedesktop.DBus.Local'," "member='Disconnected'", match_disconnected, d); if (r < 0) return r; *ret = d; d = NULL; return 0; } static int bus_process_wait(sd_bus *bus) { int r; for (;;) { r = sd_bus_process(bus, NULL); if (r < 0) return r; if (r > 0) return 0; r = sd_bus_wait(bus, (uint64_t) -1); if (r < 0) return r; } } static int bus_job_get_service_result(BusWaitForJobs *d, char **result) { _cleanup_free_ char *dbus_path = NULL; assert(d); assert(d->name); assert(result); dbus_path = unit_dbus_path_from_name(d->name); if (!dbus_path) return -ENOMEM; return sd_bus_get_property_string(d->bus, "org.freedesktop.systemd1", dbus_path, "org.freedesktop.systemd1.Service", "Result", NULL, result); } static const struct { const char *result, *explanation; } explanations [] = { { "resources", "a configured resource limit was exceeded" }, { "timeout", "a timeout was exceeded" }, { "exit-code", "the control process exited with error code" }, { "signal", "a fatal signal was delivered to the control process" }, { "core-dump", "a fatal signal was delivered causing the control process to dump core" }, { "watchdog", "the service failed to send watchdog ping" }, { "start-limit", "start of the service was attempted too often" } }; static void log_job_error_with_service_result(const char* service, const char *result, const char *extra_args) { _cleanup_free_ char *service_shell_quoted = NULL, *systemctl_extra_args = NULL; assert(service); service_shell_quoted = shell_maybe_quote(service); systemctl_extra_args = strjoin("systemctl ", extra_args, " ", NULL); if (!systemctl_extra_args) { log_oom(); return; } systemctl_extra_args = strstrip(systemctl_extra_args); if (!isempty(result)) { unsigned i; for (i = 0; i < ELEMENTSOF(explanations); ++i) if (streq(result, explanations[i].result)) break; if (i < ELEMENTSOF(explanations)) { log_error("Job for %s failed because %s. See \"%s status %s\" and \"journalctl -xe\" for details.\n", service, explanations[i].explanation, systemctl_extra_args, strna(service_shell_quoted)); goto finish; } } log_error("Job for %s failed. See \"%s status %s\" and \"journalctl -xe\" for details.\n", service, systemctl_extra_args, strna(service_shell_quoted)); finish: /* For some results maybe additional explanation is required */ if (streq_ptr(result, "start-limit")) log_info("To force a start use \"%1$s reset-failed %2$s\" followed by \"%1$s start %2$s\" again.", systemctl_extra_args, strna(service_shell_quoted)); } static int check_wait_response(BusWaitForJobs *d, bool quiet, const char *extra_args) { int r = 0; assert(d->result); if (!quiet) { if (streq(d->result, "canceled")) log_error("Job for %s canceled.", strna(d->name)); else if (streq(d->result, "timeout")) log_error("Job for %s timed out.", strna(d->name)); else if (streq(d->result, "dependency")) log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name)); else if (streq(d->result, "invalid")) log_error("%s is not active, cannot reload.", strna(d->name)); else if (streq(d->result, "assert")) log_error("Assertion failed on job for %s.", strna(d->name)); else if (streq(d->result, "unsupported")) log_error("Operation on or unit type of %s not supported on this system.", strna(d->name)); else if (!streq(d->result, "done") && !streq(d->result, "skipped")) { if (d->name) { int q; _cleanup_free_ char *result = NULL; q = bus_job_get_service_result(d, &result); if (q < 0) log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name); log_job_error_with_service_result(d->name, result, extra_args); } else log_error("Job failed. See \"journalctl -xe\" for details."); } } if (streq(d->result, "canceled")) r = -ECANCELED; else if (streq(d->result, "timeout")) r = -ETIME; else if (streq(d->result, "dependency")) r = -EIO; else if (streq(d->result, "invalid")) r = -ENOEXEC; else if (streq(d->result, "assert")) r = -EPROTO; else if (streq(d->result, "unsupported")) r = -EOPNOTSUPP; else if (!streq(d->result, "done") && !streq(d->result, "skipped")) r = -EIO; return r; } int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char *extra_args) { int r = 0; assert(d); while (!set_isempty(d->jobs)) { int q; q = bus_process_wait(d->bus); if (q < 0) return log_error_errno(q, "Failed to wait for response: %m"); if (d->result) { q = check_wait_response(d, quiet, extra_args); /* Return the first error as it is most likely to be * meaningful. */ if (q < 0 && r == 0) r = q; log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name)); } d->name = mfree(d->name); d->result = mfree(d->result); } return r; } int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) { int r; assert(d); r = set_ensure_allocated(&d->jobs, &string_hash_ops); if (r < 0) return r; return set_put_strdup(d->jobs, path); } int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) { int r; r = bus_wait_for_jobs_add(d, path); if (r < 0) return log_oom(); return bus_wait_for_jobs(d, quiet, NULL); } int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) { const char *type, *path, *source; int r; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) { if (!quiet) { if (streq(type, "symlink")) log_info("Created symlink from %s to %s.", path, source); else log_info("Removed symlink %s.", path); } r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source); if (r < 0) return r; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); return 0; } /** * bus_path_encode_unique() - encode unique object path * @b: bus connection or NULL * @prefix: object path prefix * @sender_id: unique-name of client, or NULL * @external_id: external ID to be chosen by client, or NULL * @ret_path: storage for encoded object path pointer * * Whenever we provide a bus API that allows clients to create and manage * server-side objects, we need to provide a unique name for these objects. If * we let the server choose the name, we suffer from a race condition: If a * client creates an object asynchronously, it cannot destroy that object until * it received the method reply. It cannot know the name of the new object, * thus, it cannot destroy it. Furthermore, it enforces a round-trip. * * Therefore, many APIs allow the client to choose the unique name for newly * created objects. There're two problems to solve, though: * 1) Object names are usually defined via dbus object paths, which are * usually globally namespaced. Therefore, multiple clients must be able * to choose unique object names without interference. * 2) If multiple libraries share the same bus connection, they must be * able to choose unique object names without interference. * The first problem is solved easily by prefixing a name with the * unique-bus-name of a connection. The server side must enforce this and * reject any other name. The second problem is solved by providing unique * suffixes from within sd-bus. * * This helper allows clients to create unique object-paths. It uses the * template '/prefix/sender_id/external_id' and returns the new path in * @ret_path (must be freed by the caller). * If @sender_id is NULL, the unique-name of @b is used. If @external_id is * NULL, this function allocates a unique suffix via @b (by requesting a new * cookie). If both @sender_id and @external_id are given, @b can be passed as * NULL. * * Returns: 0 on success, negative error code on failure. */ int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) { _cleanup_free_ char *sender_label = NULL, *external_label = NULL; char external_buf[DECIMAL_STR_MAX(uint64_t)], *p; int r; assert_return(b || (sender_id && external_id), -EINVAL); assert_return(object_path_is_valid(prefix), -EINVAL); assert_return(ret_path, -EINVAL); if (!sender_id) { r = sd_bus_get_unique_name(b, &sender_id); if (r < 0) return r; } if (!external_id) { xsprintf(external_buf, "%"PRIu64, ++b->cookie); external_id = external_buf; } sender_label = bus_label_escape(sender_id); if (!sender_label) return -ENOMEM; external_label = bus_label_escape(external_id); if (!external_label) return -ENOMEM; p = strjoin(prefix, "/", sender_label, "/", external_label, NULL); if (!p) return -ENOMEM; *ret_path = p; return 0; } /** * bus_path_decode_unique() - decode unique object path * @path: object path to decode * @prefix: object path prefix * @ret_sender: output parameter for sender-id label * @ret_external: output parameter for external-id label * * This does the reverse of bus_path_encode_unique() (see its description for * details). Both trailing labels, sender-id and external-id, are unescaped and * returned in the given output parameters (the caller must free them). * * Note that this function returns 0 if the path does not match the template * (see bus_path_encode_unique()), 1 if it matched. * * Returns: Negative error code on failure, 0 if the given object path does not * match the template (return parameters are set to NULL), 1 if it was * parsed successfully (return parameters contain allocated labels). */ int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) { const char *p, *q; char *sender, *external; assert(object_path_is_valid(path)); assert(object_path_is_valid(prefix)); assert(ret_sender); assert(ret_external); p = object_path_startswith(path, prefix); if (!p) { *ret_sender = NULL; *ret_external = NULL; return 0; } q = strchr(p, '/'); if (!q) { *ret_sender = NULL; *ret_external = NULL; return 0; } sender = bus_label_unescape_n(p, q - p); external = bus_label_unescape(q + 1); if (!sender || !external) { free(sender); free(external); return -ENOMEM; } *ret_sender = sender; *ret_external = external; return 1; } bool is_kdbus_wanted(void) { _cleanup_free_ char *value = NULL; #ifdef ENABLE_KDBUS const bool configured = true; #else const bool configured = false; #endif int r; if (get_proc_cmdline_key("kdbus", NULL) > 0) return true; r = get_proc_cmdline_key("kdbus=", &value); if (r <= 0) return configured; return parse_boolean(value) == 1; } bool is_kdbus_available(void) { _cleanup_close_ int fd = -1; struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE }; if (!is_kdbus_wanted()) return false; fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY); if (fd < 0) return false; return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0; } int bus_property_get_rlimit( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { struct rlimit *rl; uint64_t u; rlim_t x; const char *is_soft; assert(bus); assert(reply); assert(userdata); is_soft = endswith(property, "Soft"); rl = *(struct rlimit**) userdata; if (rl) x = is_soft ? rl->rlim_cur : rl->rlim_max; else { struct rlimit buf = {}; int z; const char *s; s = is_soft ? strndupa(property, is_soft - property) : property; z = rlimit_from_string(strstr(s, "Limit")); assert(z >= 0); getrlimit(z, &buf); x = is_soft ? buf.rlim_cur : buf.rlim_max; } /* rlim_t might have different sizes, let's map * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on * all archs */ u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x; return sd_bus_message_append(reply, "t", u); } systemd-229/src/shared/bus-util.h000066400000000000000000000214571265713322000170440ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-bus-vtable.h" #include "sd-bus.h" #include "sd-event.h" #include "hashmap.h" #include "install.h" #include "macro.h" #include "string-util.h" #include "time-util.h" typedef enum BusTransport { BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_REMOTE, BUS_TRANSPORT_MACHINE, _BUS_TRANSPORT_MAX, _BUS_TRANSPORT_INVALID = -1 } BusTransport; typedef int (*bus_property_set_t) (sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata); struct bus_properties_map { const char *member; const char *signature; bus_property_set_t set; size_t offset; }; int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata); int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, void *userdata); int bus_message_map_properties_changed(sd_bus_message *m, const struct bus_properties_map *map, void *userdata); int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map, void *userdata); int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name); typedef bool (*check_idle_t)(void *userdata); int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout, check_idle_t check_idle, void *userdata); int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error); int bus_check_peercred(sd_bus *c); int bus_test_polkit(sd_bus_message *call, int capability, const char *action, const char **details, uid_t good_user, bool *_challenge, sd_bus_error *e); int bus_verify_polkit_async(sd_bus_message *call, int capability, const char *action, const char **details, bool interactive, uid_t good_user, Hashmap **registry, sd_bus_error *error); void bus_verify_polkit_async_registry_free(Hashmap *registry); int bus_connect_system_systemd(sd_bus **_bus); int bus_connect_user_systemd(sd_bus **_bus); int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus); int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus); int bus_print_property(const char *name, sd_bus_message *property, bool all); int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all); int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); #define bus_property_get_usec ((sd_bus_property_get_t) NULL) #define bus_property_set_usec ((sd_bus_property_set_t) NULL) assert_cc(sizeof(int) == sizeof(int32_t)); #define bus_property_get_int ((sd_bus_property_get_t) NULL) assert_cc(sizeof(unsigned) == sizeof(unsigned)); #define bus_property_get_unsigned ((sd_bus_property_get_t) NULL) /* On 64bit machines we can use the default serializer for size_t and * friends, otherwise we need to cast this manually */ #if __SIZEOF_SIZE_T__ == 8 #define bus_property_get_size ((sd_bus_property_get_t) NULL) #else int bus_property_get_size(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); #endif #if __SIZEOF_LONG__ == 8 #define bus_property_get_long ((sd_bus_property_get_t) NULL) #define bus_property_get_ulong ((sd_bus_property_get_t) NULL) #else int bus_property_get_long(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); int bus_property_get_ulong(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); #endif /* uid_t and friends on Linux 32 bit. This means we can just use the * default serializer for 32bit unsigned, for serializing it, and map * it to NULL here */ assert_cc(sizeof(uid_t) == sizeof(uint32_t)); #define bus_property_get_uid ((sd_bus_property_get_t) NULL) assert_cc(sizeof(gid_t) == sizeof(uint32_t)); #define bus_property_get_gid ((sd_bus_property_get_t) NULL) assert_cc(sizeof(pid_t) == sizeof(uint32_t)); #define bus_property_get_pid ((sd_bus_property_get_t) NULL) assert_cc(sizeof(mode_t) == sizeof(uint32_t)); #define bus_property_get_mode ((sd_bus_property_get_t) NULL) int bus_log_parse_error(int r); int bus_log_create_error(int r); typedef struct UnitInfo { const char *machine; const char *id; const char *description; const char *load_state; const char *active_state; const char *sub_state; const char *following; const char *unit_path; uint32_t job_id; const char *job_type; const char *job_path; } UnitInfo; int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u); #define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \ int function(sd_bus *bus, \ const char *path, \ const char *interface, \ const char *property, \ sd_bus_message *reply, \ void *userdata, \ sd_bus_error *error) { \ \ const char *value; \ type *field = userdata; \ int r; \ \ assert(bus); \ assert(reply); \ assert(field); \ \ value = strempty(name##_to_string(*field)); \ \ r = sd_bus_message_append_basic(reply, 's', value); \ if (r < 0) \ return r; \ \ return 1; \ } \ struct __useless_struct_to_allow_trailing_semicolon__ #define BUS_PROPERTY_DUAL_TIMESTAMP(name, offset, flags) \ SD_BUS_PROPERTY(name, "t", bus_property_get_usec, (offset) + offsetof(struct dual_timestamp, realtime), (flags)), \ SD_BUS_PROPERTY(name "Monotonic", "t", bus_property_get_usec, (offset) + offsetof(struct dual_timestamp, monotonic), (flags)) int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment); typedef struct BusWaitForJobs BusWaitForJobs; int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret); void bus_wait_for_jobs_free(BusWaitForJobs *d); int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path); int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char *extra_args); int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet); DEFINE_TRIVIAL_CLEANUP_FUNC(BusWaitForJobs*, bus_wait_for_jobs_free); int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes); int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path); int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external); bool is_kdbus_wanted(void); bool is_kdbus_available(void); int bus_property_get_rlimit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); systemd-229/src/shared/cgroup-show.c000066400000000000000000000204211265713322000175360ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "alloc-util.h" #include "cgroup-show.h" #include "cgroup-util.h" #include "fd-util.h" #include "formats-util.h" #include "locale-util.h" #include "macro.h" #include "output-mode.h" #include "path-util.h" #include "process-util.h" #include "string-util.h" #include "terminal-util.h" static int compare(const void *a, const void *b) { const pid_t *p = a, *q = b; if (*p < *q) return -1; if (*p > *q) return 1; return 0; } static void show_pid_array(pid_t pids[], unsigned n_pids, const char *prefix, unsigned n_columns, bool extra, bool more, bool kernel_threads, OutputFlags flags) { unsigned i, j, pid_width; if (n_pids == 0) return; qsort(pids, n_pids, sizeof(pid_t), compare); /* Filter duplicates */ for (j = 0, i = 1; i < n_pids; i++) { if (pids[i] == pids[j]) continue; pids[++j] = pids[i]; } n_pids = j + 1; pid_width = DECIMAL_STR_WIDTH(pids[j]); if (flags & OUTPUT_FULL_WIDTH) n_columns = 0; else { if (n_columns > pid_width+2) n_columns -= pid_width+2; else n_columns = 20; } for (i = 0; i < n_pids; i++) { _cleanup_free_ char *t = NULL; get_process_cmdline(pids[i], n_columns, true, &t); if (extra) printf("%s%s ", prefix, draw_special_char(DRAW_TRIANGULAR_BULLET)); else printf("%s%s", prefix, draw_special_char(((more || i < n_pids-1) ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT))); printf("%*"PID_PRI" %s\n", pid_width, pids[i], strna(t)); } } static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigned n_columns, bool more, bool kernel_threads, OutputFlags flags) { char *fn; _cleanup_fclose_ FILE *f = NULL; size_t n = 0, n_allocated = 0; _cleanup_free_ pid_t *pids = NULL; _cleanup_free_ char *p = NULL; pid_t pid; int r; r = cg_mangle_path(path, &p); if (r < 0) return r; fn = strjoina(p, "/cgroup.procs"); f = fopen(fn, "re"); if (!f) return -errno; while ((r = cg_read_pid(f, &pid)) > 0) { if (!kernel_threads && is_kernel_thread(pid) > 0) continue; if (!GREEDY_REALLOC(pids, n_allocated, n + 1)) return -ENOMEM; assert(n < n_allocated); pids[n++] = pid; } if (r < 0) return r; show_pid_array(pids, n, prefix, n_columns, false, more, kernel_threads, flags); return 0; } int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) { _cleanup_free_ char *fn = NULL, *p1 = NULL, *last = NULL, *p2 = NULL; _cleanup_closedir_ DIR *d = NULL; char *gn = NULL; bool shown_pids = false; int r; assert(path); if (n_columns <= 0) n_columns = columns(); if (!prefix) prefix = ""; r = cg_mangle_path(path, &fn); if (r < 0) return r; d = opendir(fn); if (!d) return -errno; while ((r = cg_read_subgroup(d, &gn)) > 0) { _cleanup_free_ char *k = NULL; k = strjoin(fn, "/", gn, NULL); free(gn); if (!k) return -ENOMEM; if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k) > 0) continue; if (!shown_pids) { show_cgroup_one_by_path(path, prefix, n_columns, true, kernel_threads, flags); shown_pids = true; } if (last) { printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_BRANCH), cg_unescape(basename(last))); if (!p1) { p1 = strappend(prefix, draw_special_char(DRAW_TREE_VERTICAL)); if (!p1) return -ENOMEM; } show_cgroup_by_path(last, p1, n_columns-2, kernel_threads, flags); free(last); } last = k; k = NULL; } if (r < 0) return r; if (!shown_pids) show_cgroup_one_by_path(path, prefix, n_columns, !!last, kernel_threads, flags); if (last) { printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_RIGHT), cg_unescape(basename(last))); if (!p2) { p2 = strappend(prefix, " "); if (!p2) return -ENOMEM; } show_cgroup_by_path(last, p2, n_columns-2, kernel_threads, flags); } return 0; } int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) { _cleanup_free_ char *p = NULL; int r; assert(path); r = cg_get_path(controller, path, NULL, &p); if (r < 0) return r; return show_cgroup_by_path(p, prefix, n_columns, kernel_threads, flags); } static int show_extra_pids(const char *controller, const char *path, const char *prefix, unsigned n_columns, const pid_t pids[], unsigned n_pids, OutputFlags flags) { _cleanup_free_ pid_t *copy = NULL; unsigned i, j; int r; assert(path); if (n_pids <= 0) return 0; if (n_columns <= 0) n_columns = columns(); prefix = strempty(prefix); copy = new(pid_t, n_pids); if (!copy) return -ENOMEM; for (i = 0, j = 0; i < n_pids; i++) { _cleanup_free_ char *k = NULL; r = cg_pid_get_path(controller, pids[i], &k); if (r < 0) return r; if (path_startswith(k, path)) continue; copy[j++] = pids[i]; } show_pid_array(copy, j, prefix, n_columns, true, false, false, flags); return 0; } int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags) { int r; assert(path); r = show_cgroup(controller, path, prefix, n_columns, kernel_threads, flags); if (r < 0) return r; return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags); } int show_cgroup_and_extra_by_spec(const char *spec, const char *prefix, unsigned n_columns, bool kernel_threads, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags) { _cleanup_free_ char *controller = NULL, *path = NULL; int r; assert(spec); r = cg_split_spec(spec, &controller, &path); if (r < 0) return r; return show_cgroup_and_extra(controller, path, prefix, n_columns, kernel_threads, extra_pids, n_extra_pids, flags); } systemd-229/src/shared/cgroup-show.h000066400000000000000000000026721265713322000175530ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "logs-show.h" #include "output-mode.h" int show_cgroup_by_path(const char *path, const char *prefix, unsigned columns, bool kernel_threads, OutputFlags flags); int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned columns, bool kernel_threads, OutputFlags flags); int show_cgroup_and_extra_by_spec(const char *spec, const char *prefix, unsigned n_columns, bool kernel_threads, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); systemd-229/src/shared/clean-ipc.c000066400000000000000000000255321265713322000171240ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "clean-ipc.h" #include "dirent-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "log.h" #include "macro.h" #include "string-util.h" #include "strv.h" static int clean_sysvipc_shm(uid_t delete_uid) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; bool first = true; int ret = 0; f = fopen("/proc/sysvipc/shm", "re"); if (!f) { if (errno == ENOENT) return 0; return log_warning_errno(errno, "Failed to open /proc/sysvipc/shm: %m"); } FOREACH_LINE(line, f, goto fail) { unsigned n_attached; pid_t cpid, lpid; uid_t uid, cuid; gid_t gid, cgid; int shmid; if (first) { first = false; continue; } truncate_nl(line); if (sscanf(line, "%*i %i %*o %*u " PID_FMT " " PID_FMT " %u " UID_FMT " " GID_FMT " " UID_FMT " " GID_FMT, &shmid, &cpid, &lpid, &n_attached, &uid, &gid, &cuid, &cgid) != 8) continue; if (n_attached > 0) continue; if (uid != delete_uid) continue; if (shmctl(shmid, IPC_RMID, NULL) < 0) { /* Ignore entries that are already deleted */ if (errno == EIDRM || errno == EINVAL) continue; ret = log_warning_errno(errno, "Failed to remove SysV shared memory segment %i: %m", shmid); } } return ret; fail: return log_warning_errno(errno, "Failed to read /proc/sysvipc/shm: %m"); } static int clean_sysvipc_sem(uid_t delete_uid) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; bool first = true; int ret = 0; f = fopen("/proc/sysvipc/sem", "re"); if (!f) { if (errno == ENOENT) return 0; return log_warning_errno(errno, "Failed to open /proc/sysvipc/sem: %m"); } FOREACH_LINE(line, f, goto fail) { uid_t uid, cuid; gid_t gid, cgid; int semid; if (first) { first = false; continue; } truncate_nl(line); if (sscanf(line, "%*i %i %*o %*u " UID_FMT " " GID_FMT " " UID_FMT " " GID_FMT, &semid, &uid, &gid, &cuid, &cgid) != 5) continue; if (uid != delete_uid) continue; if (semctl(semid, 0, IPC_RMID) < 0) { /* Ignore entries that are already deleted */ if (errno == EIDRM || errno == EINVAL) continue; ret = log_warning_errno(errno, "Failed to remove SysV semaphores object %i: %m", semid); } } return ret; fail: return log_warning_errno(errno, "Failed to read /proc/sysvipc/sem: %m"); } static int clean_sysvipc_msg(uid_t delete_uid) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; bool first = true; int ret = 0; f = fopen("/proc/sysvipc/msg", "re"); if (!f) { if (errno == ENOENT) return 0; return log_warning_errno(errno, "Failed to open /proc/sysvipc/msg: %m"); } FOREACH_LINE(line, f, goto fail) { uid_t uid, cuid; gid_t gid, cgid; pid_t cpid, lpid; int msgid; if (first) { first = false; continue; } truncate_nl(line); if (sscanf(line, "%*i %i %*o %*u %*u " PID_FMT " " PID_FMT " " UID_FMT " " GID_FMT " " UID_FMT " " GID_FMT, &msgid, &cpid, &lpid, &uid, &gid, &cuid, &cgid) != 7) continue; if (uid != delete_uid) continue; if (msgctl(msgid, IPC_RMID, NULL) < 0) { /* Ignore entries that are already deleted */ if (errno == EIDRM || errno == EINVAL) continue; ret = log_warning_errno(errno, "Failed to remove SysV message queue %i: %m", msgid); } } return ret; fail: return log_warning_errno(errno, "Failed to read /proc/sysvipc/msg: %m"); } static int clean_posix_shm_internal(DIR *dir, uid_t uid) { struct dirent *de; int ret = 0, r; assert(dir); FOREACH_DIRENT(de, dir, goto fail) { struct stat st; if (STR_IN_SET(de->d_name, "..", ".")) continue; if (fstatat(dirfd(dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { if (errno == ENOENT) continue; log_warning_errno(errno, "Failed to stat() POSIX shared memory segment %s: %m", de->d_name); ret = -errno; continue; } if (st.st_uid != uid) continue; if (S_ISDIR(st.st_mode)) { _cleanup_closedir_ DIR *kid; kid = xopendirat(dirfd(dir), de->d_name, O_NOFOLLOW|O_NOATIME); if (!kid) { if (errno != ENOENT) { log_warning_errno(errno, "Failed to enter shared memory directory %s: %m", de->d_name); ret = -errno; } } else { r = clean_posix_shm_internal(kid, uid); if (r < 0) ret = r; } if (unlinkat(dirfd(dir), de->d_name, AT_REMOVEDIR) < 0) { if (errno == ENOENT) continue; log_warning_errno(errno, "Failed to remove POSIX shared memory directory %s: %m", de->d_name); ret = -errno; } } else { if (unlinkat(dirfd(dir), de->d_name, 0) < 0) { if (errno == ENOENT) continue; log_warning_errno(errno, "Failed to remove POSIX shared memory segment %s: %m", de->d_name); ret = -errno; } } } return ret; fail: log_warning_errno(errno, "Failed to read /dev/shm: %m"); return -errno; } static int clean_posix_shm(uid_t uid) { _cleanup_closedir_ DIR *dir = NULL; dir = opendir("/dev/shm"); if (!dir) { if (errno == ENOENT) return 0; return log_warning_errno(errno, "Failed to open /dev/shm: %m"); } return clean_posix_shm_internal(dir, uid); } static int clean_posix_mq(uid_t uid) { _cleanup_closedir_ DIR *dir = NULL; struct dirent *de; int ret = 0; dir = opendir("/dev/mqueue"); if (!dir) { if (errno == ENOENT) return 0; return log_warning_errno(errno, "Failed to open /dev/mqueue: %m"); } FOREACH_DIRENT(de, dir, goto fail) { struct stat st; char fn[1+strlen(de->d_name)+1]; if (STR_IN_SET(de->d_name, "..", ".")) continue; if (fstatat(dirfd(dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { if (errno == ENOENT) continue; ret = log_warning_errno(errno, "Failed to stat() MQ segment %s: %m", de->d_name); continue; } if (st.st_uid != uid) continue; fn[0] = '/'; strcpy(fn+1, de->d_name); if (mq_unlink(fn) < 0) { if (errno == ENOENT) continue; ret = log_warning_errno(errno, "Failed to unlink POSIX message queue %s: %m", fn); } } return ret; fail: return log_warning_errno(errno, "Failed to read /dev/mqueue: %m"); } int clean_ipc(uid_t uid) { int ret = 0, r; /* Refuse to clean IPC of the root and system users */ if (uid <= SYSTEM_UID_MAX) return 0; r = clean_sysvipc_shm(uid); if (r < 0) ret = r; r = clean_sysvipc_sem(uid); if (r < 0) ret = r; r = clean_sysvipc_msg(uid); if (r < 0) ret = r; r = clean_posix_shm(uid); if (r < 0) ret = r; r = clean_posix_mq(uid); if (r < 0) ret = r; return ret; } systemd-229/src/shared/clean-ipc.h000066400000000000000000000014171265713322000171250ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include int clean_ipc(uid_t uid); systemd-229/src/shared/condition.c000066400000000000000000000401521265713322000172520ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include "sd-id128.h" #include "alloc-util.h" #include "apparmor-util.h" #include "architecture.h" #include "audit-util.h" #include "cap-list.h" #include "condition.h" #include "extract-word.h" #include "fd-util.h" #include "glob-util.h" #include "hostname-util.h" #include "ima-util.h" #include "list.h" #include "macro.h" #include "mount-util.h" #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" #include "selinux-util.h" #include "smack-util.h" #include "stat-util.h" #include "string-table.h" #include "string-util.h" #include "util.h" #include "virt.h" Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) { Condition *c; int r; assert(type >= 0); assert(type < _CONDITION_TYPE_MAX); assert((!parameter) == (type == CONDITION_NULL)); c = new0(Condition, 1); if (!c) return NULL; c->type = type; c->trigger = trigger; c->negate = negate; r = free_and_strdup(&c->parameter, parameter); if (r < 0) { free(c); return NULL; } return c; } void condition_free(Condition *c) { assert(c); free(c->parameter); free(c); } Condition* condition_free_list(Condition *first) { Condition *c, *n; LIST_FOREACH_SAFE(conditions, c, n, first) condition_free(c); return NULL; } static int condition_test_kernel_command_line(Condition *c) { _cleanup_free_ char *line = NULL; const char *p; bool equal; int r; assert(c); assert(c->parameter); assert(c->type == CONDITION_KERNEL_COMMAND_LINE); r = proc_cmdline(&line); if (r < 0) return r; equal = !!strchr(c->parameter, '='); p = line; for (;;) { _cleanup_free_ char *word = NULL; bool found; r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); if (r < 0) return r; if (r == 0) break; if (equal) found = streq(word, c->parameter); else { const char *f; f = startswith(word, c->parameter); found = f && (*f == '=' || *f == 0); } if (found) return true; } return false; } static int condition_test_virtualization(Condition *c) { int b, v; assert(c); assert(c->parameter); assert(c->type == CONDITION_VIRTUALIZATION); v = detect_virtualization(); if (v < 0) return v; /* First, compare with yes/no */ b = parse_boolean(c->parameter); if (v > 0 && b > 0) return true; if (v == 0 && b == 0) return true; /* Then, compare categorization */ if (VIRTUALIZATION_IS_VM(v) && streq(c->parameter, "vm")) return true; if (VIRTUALIZATION_IS_CONTAINER(v) && streq(c->parameter, "container")) return true; /* Finally compare id */ return v != VIRTUALIZATION_NONE && streq(c->parameter, virtualization_to_string(v)); } static int condition_test_architecture(Condition *c) { int a, b; assert(c); assert(c->parameter); assert(c->type == CONDITION_ARCHITECTURE); a = uname_architecture(); if (a < 0) return a; if (streq(c->parameter, "native")) b = native_architecture(); else b = architecture_from_string(c->parameter); if (b < 0) return b; return a == b; } static int condition_test_host(Condition *c) { _cleanup_free_ char *h = NULL; sd_id128_t x, y; int r; assert(c); assert(c->parameter); assert(c->type == CONDITION_HOST); if (sd_id128_from_string(c->parameter, &x) >= 0) { r = sd_id128_get_machine(&y); if (r < 0) return r; return sd_id128_equal(x, y); } h = gethostname_malloc(); if (!h) return -ENOMEM; return fnmatch(c->parameter, h, FNM_CASEFOLD) == 0; } static int condition_test_ac_power(Condition *c) { int r; assert(c); assert(c->parameter); assert(c->type == CONDITION_AC_POWER); r = parse_boolean(c->parameter); if (r < 0) return r; return (on_ac_power() != 0) == !!r; } static int condition_test_security(Condition *c) { assert(c); assert(c->parameter); assert(c->type == CONDITION_SECURITY); if (streq(c->parameter, "selinux")) return mac_selinux_have(); if (streq(c->parameter, "smack")) return mac_smack_use(); if (streq(c->parameter, "apparmor")) return mac_apparmor_use(); if (streq(c->parameter, "audit")) return use_audit(); if (streq(c->parameter, "ima")) return use_ima(); return false; } static int condition_test_capability(Condition *c) { _cleanup_fclose_ FILE *f = NULL; int value; char line[LINE_MAX]; unsigned long long capabilities = -1; assert(c); assert(c->parameter); assert(c->type == CONDITION_CAPABILITY); /* If it's an invalid capability, we don't have it */ value = capability_from_name(c->parameter); if (value < 0) return -EINVAL; /* If it's a valid capability we default to assume * that we have it */ f = fopen("/proc/self/status", "re"); if (!f) return -errno; while (fgets(line, sizeof(line), f)) { truncate_nl(line); if (startswith(line, "CapBnd:")) { (void) sscanf(line+7, "%llx", &capabilities); break; } } return !!(capabilities & (1ULL << value)); } static int condition_test_needs_update(Condition *c) { const char *p; struct stat usr, other; assert(c); assert(c->parameter); assert(c->type == CONDITION_NEEDS_UPDATE); /* If the file system is read-only we shouldn't suggest an update */ if (path_is_read_only_fs(c->parameter) > 0) return false; /* Any other failure means we should allow the condition to be true, * so that we rather invoke too many update tools then too * few. */ if (!path_is_absolute(c->parameter)) return true; p = strjoina(c->parameter, "/.updated"); if (lstat(p, &other) < 0) return true; if (lstat("/usr/", &usr) < 0) return true; return usr.st_mtim.tv_sec > other.st_mtim.tv_sec || (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec); } static int condition_test_first_boot(Condition *c) { int r; assert(c); assert(c->parameter); assert(c->type == CONDITION_FIRST_BOOT); r = parse_boolean(c->parameter); if (r < 0) return r; return (access("/run/systemd/first-boot", F_OK) >= 0) == !!r; } static int condition_test_path_exists(Condition *c) { assert(c); assert(c->parameter); assert(c->type == CONDITION_PATH_EXISTS); return access(c->parameter, F_OK) >= 0; } static int condition_test_path_exists_glob(Condition *c) { assert(c); assert(c->parameter); assert(c->type == CONDITION_PATH_EXISTS_GLOB); return glob_exists(c->parameter) > 0; } static int condition_test_path_is_directory(Condition *c) { assert(c); assert(c->parameter); assert(c->type == CONDITION_PATH_IS_DIRECTORY); return is_dir(c->parameter, true) > 0; } static int condition_test_path_is_symbolic_link(Condition *c) { assert(c); assert(c->parameter); assert(c->type == CONDITION_PATH_IS_SYMBOLIC_LINK); return is_symlink(c->parameter) > 0; } static int condition_test_path_is_mount_point(Condition *c) { assert(c); assert(c->parameter); assert(c->type == CONDITION_PATH_IS_MOUNT_POINT); return path_is_mount_point(c->parameter, AT_SYMLINK_FOLLOW) > 0; } static int condition_test_path_is_read_write(Condition *c) { assert(c); assert(c->parameter); assert(c->type == CONDITION_PATH_IS_READ_WRITE); return path_is_read_only_fs(c->parameter) <= 0; } static int condition_test_directory_not_empty(Condition *c) { int r; assert(c); assert(c->parameter); assert(c->type == CONDITION_DIRECTORY_NOT_EMPTY); r = dir_is_empty(c->parameter); return r <= 0 && r != -ENOENT; } static int condition_test_file_not_empty(Condition *c) { struct stat st; assert(c); assert(c->parameter); assert(c->type == CONDITION_FILE_NOT_EMPTY); return (stat(c->parameter, &st) >= 0 && S_ISREG(st.st_mode) && st.st_size > 0); } static int condition_test_file_is_executable(Condition *c) { struct stat st; assert(c); assert(c->parameter); assert(c->type == CONDITION_FILE_IS_EXECUTABLE); return (stat(c->parameter, &st) >= 0 && S_ISREG(st.st_mode) && (st.st_mode & 0111)); } static int condition_test_null(Condition *c) { assert(c); assert(c->type == CONDITION_NULL); /* Note that during parsing we already evaluate the string and * store it in c->negate */ return true; } int condition_test(Condition *c) { static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c) = { [CONDITION_PATH_EXISTS] = condition_test_path_exists, [CONDITION_PATH_EXISTS_GLOB] = condition_test_path_exists_glob, [CONDITION_PATH_IS_DIRECTORY] = condition_test_path_is_directory, [CONDITION_PATH_IS_SYMBOLIC_LINK] = condition_test_path_is_symbolic_link, [CONDITION_PATH_IS_MOUNT_POINT] = condition_test_path_is_mount_point, [CONDITION_PATH_IS_READ_WRITE] = condition_test_path_is_read_write, [CONDITION_DIRECTORY_NOT_EMPTY] = condition_test_directory_not_empty, [CONDITION_FILE_NOT_EMPTY] = condition_test_file_not_empty, [CONDITION_FILE_IS_EXECUTABLE] = condition_test_file_is_executable, [CONDITION_KERNEL_COMMAND_LINE] = condition_test_kernel_command_line, [CONDITION_VIRTUALIZATION] = condition_test_virtualization, [CONDITION_SECURITY] = condition_test_security, [CONDITION_CAPABILITY] = condition_test_capability, [CONDITION_HOST] = condition_test_host, [CONDITION_AC_POWER] = condition_test_ac_power, [CONDITION_ARCHITECTURE] = condition_test_architecture, [CONDITION_NEEDS_UPDATE] = condition_test_needs_update, [CONDITION_FIRST_BOOT] = condition_test_first_boot, [CONDITION_NULL] = condition_test_null, }; int r, b; assert(c); assert(c->type >= 0); assert(c->type < _CONDITION_TYPE_MAX); r = condition_tests[c->type](c); if (r < 0) { c->result = CONDITION_ERROR; return r; } b = (r > 0) == !c->negate; c->result = b ? CONDITION_SUCCEEDED : CONDITION_FAILED; return b; } void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) { assert(c); assert(f); if (!prefix) prefix = ""; fprintf(f, "%s\t%s: %s%s%s %s\n", prefix, to_string(c->type), c->trigger ? "|" : "", c->negate ? "!" : "", c->parameter, condition_result_to_string(c->result)); } void condition_dump_list(Condition *first, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) { Condition *c; LIST_FOREACH(conditions, c, first) condition_dump(c, f, prefix, to_string); } static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { [CONDITION_ARCHITECTURE] = "ConditionArchitecture", [CONDITION_VIRTUALIZATION] = "ConditionVirtualization", [CONDITION_HOST] = "ConditionHost", [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine", [CONDITION_SECURITY] = "ConditionSecurity", [CONDITION_CAPABILITY] = "ConditionCapability", [CONDITION_AC_POWER] = "ConditionACPower", [CONDITION_NEEDS_UPDATE] = "ConditionNeedsUpdate", [CONDITION_FIRST_BOOT] = "ConditionFirstBoot", [CONDITION_PATH_EXISTS] = "ConditionPathExists", [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob", [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory", [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink", [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint", [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite", [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty", [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty", [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable", [CONDITION_NULL] = "ConditionNull" }; DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType); static const char* const assert_type_table[_CONDITION_TYPE_MAX] = { [CONDITION_ARCHITECTURE] = "AssertArchitecture", [CONDITION_VIRTUALIZATION] = "AssertVirtualization", [CONDITION_HOST] = "AssertHost", [CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine", [CONDITION_SECURITY] = "AssertSecurity", [CONDITION_CAPABILITY] = "AssertCapability", [CONDITION_AC_POWER] = "AssertACPower", [CONDITION_NEEDS_UPDATE] = "AssertNeedsUpdate", [CONDITION_FIRST_BOOT] = "AssertFirstBoot", [CONDITION_PATH_EXISTS] = "AssertPathExists", [CONDITION_PATH_EXISTS_GLOB] = "AssertPathExistsGlob", [CONDITION_PATH_IS_DIRECTORY] = "AssertPathIsDirectory", [CONDITION_PATH_IS_SYMBOLIC_LINK] = "AssertPathIsSymbolicLink", [CONDITION_PATH_IS_MOUNT_POINT] = "AssertPathIsMountPoint", [CONDITION_PATH_IS_READ_WRITE] = "AssertPathIsReadWrite", [CONDITION_DIRECTORY_NOT_EMPTY] = "AssertDirectoryNotEmpty", [CONDITION_FILE_NOT_EMPTY] = "AssertFileNotEmpty", [CONDITION_FILE_IS_EXECUTABLE] = "AssertFileIsExecutable", [CONDITION_NULL] = "AssertNull" }; DEFINE_STRING_TABLE_LOOKUP(assert_type, ConditionType); static const char* const condition_result_table[_CONDITION_RESULT_MAX] = { [CONDITION_UNTESTED] = "untested", [CONDITION_SUCCEEDED] = "succeeded", [CONDITION_FAILED] = "failed", [CONDITION_ERROR] = "error", }; DEFINE_STRING_TABLE_LOOKUP(condition_result, ConditionResult); systemd-229/src/shared/condition.h000066400000000000000000000054321265713322000172610ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "list.h" #include "macro.h" typedef enum ConditionType { CONDITION_ARCHITECTURE, CONDITION_VIRTUALIZATION, CONDITION_HOST, CONDITION_KERNEL_COMMAND_LINE, CONDITION_SECURITY, CONDITION_CAPABILITY, CONDITION_AC_POWER, CONDITION_NEEDS_UPDATE, CONDITION_FIRST_BOOT, CONDITION_PATH_EXISTS, CONDITION_PATH_EXISTS_GLOB, CONDITION_PATH_IS_DIRECTORY, CONDITION_PATH_IS_SYMBOLIC_LINK, CONDITION_PATH_IS_MOUNT_POINT, CONDITION_PATH_IS_READ_WRITE, CONDITION_DIRECTORY_NOT_EMPTY, CONDITION_FILE_NOT_EMPTY, CONDITION_FILE_IS_EXECUTABLE, CONDITION_NULL, _CONDITION_TYPE_MAX, _CONDITION_TYPE_INVALID = -1 } ConditionType; typedef enum ConditionResult { CONDITION_UNTESTED, CONDITION_SUCCEEDED, CONDITION_FAILED, CONDITION_ERROR, _CONDITION_RESULT_MAX, _CONDITION_RESULT_INVALID = -1 } ConditionResult; typedef struct Condition { ConditionType type:8; bool trigger:1; bool negate:1; ConditionResult result:6; char *parameter; LIST_FIELDS(struct Condition, conditions); } Condition; Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate); void condition_free(Condition *c); Condition* condition_free_list(Condition *c); int condition_test(Condition *c); void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)); void condition_dump_list(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)); const char* condition_type_to_string(ConditionType t) _const_; ConditionType condition_type_from_string(const char *s) _pure_; const char* assert_type_to_string(ConditionType t) _const_; ConditionType assert_type_from_string(const char *s) _pure_; const char* condition_result_to_string(ConditionResult r) _const_; ConditionResult condition_result_from_string(const char *s) _pure_; systemd-229/src/shared/conf-parser.c000066400000000000000000000644411265713322000175120ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "alloc-util.h" #include "conf-files.h" #include "conf-parser.h" #include "extract-word.h" #include "fd-util.h" #include "fs-util.h" #include "log.h" #include "macro.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "signal-util.h" #include "string-util.h" #include "strv.h" #include "syslog-util.h" #include "time-util.h" #include "utf8.h" int config_item_table_lookup( const void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata) { const ConfigTableItem *t; assert(table); assert(lvalue); assert(func); assert(ltype); assert(data); for (t = table; t->lvalue; t++) { if (!streq(lvalue, t->lvalue)) continue; if (!streq_ptr(section, t->section)) continue; *func = t->parse; *ltype = t->ltype; *data = t->data; return 1; } return 0; } int config_item_perf_lookup( const void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata) { ConfigPerfItemLookup lookup = (ConfigPerfItemLookup) table; const ConfigPerfItem *p; assert(table); assert(lvalue); assert(func); assert(ltype); assert(data); if (!section) p = lookup(lvalue, strlen(lvalue)); else { char *key; key = strjoin(section, ".", lvalue, NULL); if (!key) return -ENOMEM; p = lookup(key, strlen(key)); free(key); } if (!p) return 0; *func = p->parse; *ltype = p->ltype; *data = (uint8_t*) userdata + p->offset; return 1; } /* Run the user supplied parser for an assignment */ static int next_assignment(const char *unit, const char *filename, unsigned line, ConfigItemLookup lookup, const void *table, const char *section, unsigned section_line, const char *lvalue, const char *rvalue, bool relaxed, void *userdata) { ConfigParserCallback func = NULL; int ltype = 0; void *data = NULL; int r; assert(filename); assert(line > 0); assert(lookup); assert(lvalue); assert(rvalue); r = lookup(table, section, lvalue, &func, <ype, &data, userdata); if (r < 0) return r; if (r > 0) { if (func) return func(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata); return 0; } /* Warn about unknown non-extension fields. */ if (!relaxed && !startswith(lvalue, "X-")) log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown lvalue '%s' in section '%s'", lvalue, section); return 0; } /* Parse a variable assignment line */ static int parse_line(const char* unit, const char *filename, unsigned line, const char *sections, ConfigItemLookup lookup, const void *table, bool relaxed, bool allow_include, char **section, unsigned *section_line, bool *section_ignored, char *l, void *userdata) { char *e; assert(filename); assert(line > 0); assert(lookup); assert(l); l = strstrip(l); if (!*l) return 0; if (strchr(COMMENTS "\n", *l)) return 0; if (startswith(l, ".include ")) { _cleanup_free_ char *fn = NULL; /* .includes are a bad idea, we only support them here * for historical reasons. They create cyclic include * problems and make it difficult to detect * configuration file changes with an easy * stat(). Better approaches, such as .d/ drop-in * snippets exist. * * Support for them should be eventually removed. */ if (!allow_include) { log_syntax(unit, LOG_ERR, filename, line, 0, ".include not allowed here. Ignoring."); return 0; } fn = file_in_same_dir(filename, strstrip(l+9)); if (!fn) return -ENOMEM; return config_parse(unit, fn, NULL, sections, lookup, table, relaxed, false, false, userdata); } if (*l == '[') { size_t k; char *n; k = strlen(l); assert(k > 0); if (l[k-1] != ']') { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid section header '%s'", l); return -EBADMSG; } n = strndup(l+1, k-2); if (!n) return -ENOMEM; if (sections && !nulstr_contains(sections, n)) { if (!relaxed && !startswith(n, "X-")) log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown section '%s'. Ignoring.", n); free(n); *section = mfree(*section); *section_line = 0; *section_ignored = true; } else { free(*section); *section = n; *section_line = line; *section_ignored = false; } return 0; } if (sections && !*section) { if (!relaxed && !*section_ignored) log_syntax(unit, LOG_WARNING, filename, line, 0, "Assignment outside of section. Ignoring."); return 0; } e = strchr(l, '='); if (!e) { log_syntax(unit, LOG_WARNING, filename, line, 0, "Missing '='."); return -EINVAL; } *e = 0; e++; return next_assignment(unit, filename, line, lookup, table, *section, *section_line, strstrip(l), strstrip(e), relaxed, userdata); } /* Go through the file and parse each line */ int config_parse(const char *unit, const char *filename, FILE *f, const char *sections, ConfigItemLookup lookup, const void *table, bool relaxed, bool allow_include, bool warn, void *userdata) { _cleanup_free_ char *section = NULL, *continuation = NULL; _cleanup_fclose_ FILE *ours = NULL; unsigned line = 0, section_line = 0; bool section_ignored = false; int r; assert(filename); assert(lookup); if (!f) { f = ours = fopen(filename, "re"); if (!f) { /* Only log on request, except for ENOENT, * since we return 0 to the caller. */ if (warn || errno == ENOENT) log_full(errno == ENOENT ? LOG_DEBUG : LOG_ERR, "Failed to open configuration file '%s': %m", filename); return errno == ENOENT ? 0 : -errno; } } fd_warn_permissions(filename, fileno(f)); while (!feof(f)) { char l[LINE_MAX], *p, *c = NULL, *e; bool escaped = false; if (!fgets(l, sizeof(l), f)) { if (feof(f)) break; log_error_errno(errno, "Failed to read configuration file '%s': %m", filename); return -errno; } truncate_nl(l); if (continuation) { c = strappend(continuation, l); if (!c) { if (warn) log_oom(); return -ENOMEM; } continuation = mfree(continuation); p = c; } else p = l; for (e = p; *e; e++) { if (escaped) escaped = false; else if (*e == '\\') escaped = true; } if (escaped) { *(e-1) = ' '; if (c) continuation = c; else { continuation = strdup(l); if (!continuation) { if (warn) log_oom(); return -ENOMEM; } } continue; } r = parse_line(unit, filename, ++line, sections, lookup, table, relaxed, allow_include, §ion, §ion_line, §ion_ignored, p, userdata); free(c); if (r < 0) { if (warn) log_warning_errno(r, "Failed to parse file '%s': %m", filename); return r; } } return 0; } /* Parse each config file in the specified directories. */ int config_parse_many(const char *conf_file, const char *conf_file_dirs, const char *sections, ConfigItemLookup lookup, const void *table, bool relaxed, void *userdata) { _cleanup_strv_free_ char **files = NULL; char **fn; int r; r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs); if (r < 0) return r; if (conf_file) { r = config_parse(NULL, conf_file, NULL, sections, lookup, table, relaxed, false, true, userdata); if (r < 0) return r; } STRV_FOREACH(fn, files) { r = config_parse(NULL, *fn, NULL, sections, lookup, table, relaxed, false, true, userdata); if (r < 0) return r; } return 0; } #define DEFINE_PARSER(type, vartype, conv_func) \ int config_parse_##type( \ const char *unit, \ const char *filename, \ unsigned line, \ const char *section, \ unsigned section_line, \ const char *lvalue, \ int ltype, \ const char *rvalue, \ void *data, \ void *userdata) { \ \ vartype *i = data; \ int r; \ \ assert(filename); \ assert(lvalue); \ assert(rvalue); \ assert(data); \ \ r = conv_func(rvalue, i); \ if (r < 0) \ log_syntax(unit, LOG_ERR, filename, line, r, \ "Failed to parse %s value, ignoring: %s", \ #type, rvalue); \ \ return 0; \ } \ struct __useless_struct_to_allow_trailing_semicolon__ DEFINE_PARSER(int, int, safe_atoi); DEFINE_PARSER(long, long, safe_atoli); DEFINE_PARSER(uint32, uint32_t, safe_atou32); DEFINE_PARSER(uint64, uint64_t, safe_atou64); DEFINE_PARSER(unsigned, unsigned, safe_atou); DEFINE_PARSER(double, double, safe_atod); DEFINE_PARSER(nsec, nsec_t, parse_nsec); DEFINE_PARSER(sec, usec_t, parse_sec); DEFINE_PARSER(mode, mode_t, parse_mode); int config_parse_iec_size(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { size_t *sz = data; uint64_t v; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = parse_size(rvalue, 1024, &v); if (r < 0 || (uint64_t) (size_t) v != v) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue); return 0; } *sz = (size_t) v; return 0; } int config_parse_si_size(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { size_t *sz = data; uint64_t v; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = parse_size(rvalue, 1000, &v); if (r < 0 || (uint64_t) (size_t) v != v) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue); return 0; } *sz = (size_t) v; return 0; } int config_parse_iec_uint64(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { uint64_t *bytes = data; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); r = parse_size(rvalue, 1024, bytes); if (r < 0) log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue); return 0; } int config_parse_bool(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { int k; bool *b = data; assert(filename); assert(lvalue); assert(rvalue); assert(data); k = parse_boolean(rvalue); if (k < 0) { log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue); return 0; } *b = !!k; return 0; } int config_parse_tristate( const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { int k, *t = data; assert(filename); assert(lvalue); assert(rvalue); assert(data); /* A tristate is pretty much a boolean, except that it can * also take the special value -1, indicating "uninitialized", * much like NULL is for a pointer type. */ k = parse_boolean(rvalue); if (k < 0) { log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue); return 0; } *t = !!k; return 0; } int config_parse_string( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { char **s = data, *n; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (!utf8_is_valid(rvalue)) { log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); return 0; } if (isempty(rvalue)) n = NULL; else { n = strdup(rvalue); if (!n) return log_oom(); } free(*s); *s = n; return 0; } int config_parse_path( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { char **s = data, *n; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (!utf8_is_valid(rvalue)) { log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); return 0; } if (!path_is_absolute(rvalue)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", rvalue); return 0; } n = strdup(rvalue); if (!n) return log_oom(); path_kill_slashes(n); free(*s); *s = n; return 0; } int config_parse_strv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { char ***sv = data; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { char **empty; /* Empty assignment resets the list. As a special rule * we actually fill in a real empty array here rather * than NULL, since some code wants to know if * something was set at all... */ empty = strv_new(NULL, NULL); if (!empty) return log_oom(); strv_free(*sv); *sv = empty; return 0; } for (;;) { char *word = NULL; int r; r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES); if (r == 0) break; if (r == -ENOMEM) return log_oom(); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); break; } if (!utf8_is_valid(word)) { log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); free(word); continue; } r = strv_consume(sv, word); if (r < 0) return log_oom(); } return 0; } int config_parse_log_facility( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { int *o = data, x; assert(filename); assert(lvalue); assert(rvalue); assert(data); x = log_facility_unshifted_from_string(rvalue); if (x < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log facility, ignoring: %s", rvalue); return 0; } *o = (x << 3) | LOG_PRI(*o); return 0; } int config_parse_log_level( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { int *o = data, x; assert(filename); assert(lvalue); assert(rvalue); assert(data); x = log_level_from_string(rvalue); if (x < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log level, ignoring: %s", rvalue); return 0; } *o = (*o & LOG_FACMASK) | x; return 0; } int config_parse_signal( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { int *sig = data, r; assert(filename); assert(lvalue); assert(rvalue); assert(sig); r = signal_from_string_try_harder(rvalue); if (r <= 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse signal name, ignoring: %s", rvalue); return 0; } *sig = r; return 0; } int config_parse_personality( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { unsigned long *personality = data, p; assert(filename); assert(lvalue); assert(rvalue); assert(personality); p = personality_from_string(rvalue); if (p == PERSONALITY_INVALID) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse personality, ignoring: %s", rvalue); return 0; } *personality = p; return 0; } systemd-229/src/shared/conf-parser.h000066400000000000000000000401021265713322000175030ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "log.h" #include "macro.h" /* An abstract parser for simple, line based, shallow configuration * files consisting of variable assignments only. */ /* Prototype for a parser for a specific configuration setting */ typedef int (*ConfigParserCallback)(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); /* Wraps information for parsing a specific configuration variable, to * be stored in a simple array */ typedef struct ConfigTableItem { const char *section; /* Section */ const char *lvalue; /* Name of the variable */ ConfigParserCallback parse; /* Function that is called to parse the variable's value */ int ltype; /* Distinguish different variables passed to the same callback */ void *data; /* Where to store the variable's data */ } ConfigTableItem; /* Wraps information for parsing a specific configuration variable, to * be stored in a gperf perfect hashtable */ typedef struct ConfigPerfItem { const char *section_and_lvalue; /* Section + "." + name of the variable */ ConfigParserCallback parse; /* Function that is called to parse the variable's value */ int ltype; /* Distinguish different variables passed to the same callback */ size_t offset; /* Offset where to store data, from the beginning of userdata */ } ConfigPerfItem; /* Prototype for a low-level gperf lookup function */ typedef const ConfigPerfItem* (*ConfigPerfItemLookup)(const char *section_and_lvalue, unsigned length); /* Prototype for a generic high-level lookup function */ typedef int (*ConfigItemLookup)( const void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata); /* Linear table search implementation of ConfigItemLookup, based on * ConfigTableItem arrays */ int config_item_table_lookup(const void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata); /* gperf implementation of ConfigItemLookup, based on gperf * ConfigPerfItem tables */ int config_item_perf_lookup(const void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata); int config_parse(const char *unit, const char *filename, FILE *f, const char *sections, /* nulstr */ ConfigItemLookup lookup, const void *table, bool relaxed, bool allow_include, bool warn, void *userdata); int config_parse_many(const char *conf_file, /* possibly NULL */ const char *conf_file_dirs, /* nulstr */ const char *sections, /* nulstr */ ConfigItemLookup lookup, const void *table, bool relaxed, void *userdata); /* Generic parsers */ int config_parse_int(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_unsigned(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_long(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_uint32(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_uint64(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_double(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_iec_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_si_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_iec_uint64(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bool(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_tristate(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_string(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_path(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_strv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_sec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_nsec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_log_facility(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_log_level(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_signal(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_personality(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); #define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \ int function(const char *unit, \ const char *filename, \ unsigned line, \ const char *section, \ unsigned section_line, \ const char *lvalue, \ int ltype, \ const char *rvalue, \ void *data, \ void *userdata) { \ \ type *i = data, x; \ \ assert(filename); \ assert(lvalue); \ assert(rvalue); \ assert(data); \ \ if ((x = name##_from_string(rvalue)) < 0) { \ log_syntax(unit, LOG_ERR, filename, line, -x, \ msg ", ignoring: %s", rvalue); \ return 0; \ } \ \ *i = x; \ return 0; \ } #define DEFINE_CONFIG_PARSE_ENUMV(function,name,type,invalid,msg) \ int function(const char *unit, \ const char *filename, \ unsigned line, \ const char *section, \ unsigned section_line, \ const char *lvalue, \ int ltype, \ const char *rvalue, \ void *data, \ void *userdata) { \ \ type **enums = data, x, *ys; \ _cleanup_free_ type *xs = NULL; \ const char *word, *state; \ size_t l, i = 0; \ \ assert(filename); \ assert(lvalue); \ assert(rvalue); \ assert(data); \ \ xs = new0(type, 1); \ if(!xs) \ return -ENOMEM; \ \ *xs = invalid; \ \ FOREACH_WORD(word, l, rvalue, state) { \ _cleanup_free_ char *en = NULL; \ type *new_xs; \ \ en = strndup(word, l); \ if (!en) \ return -ENOMEM; \ \ if ((x = name##_from_string(en)) < 0) { \ log_syntax(unit, LOG_ERR, filename, line, \ -x, msg ", ignoring: %s", en); \ continue; \ } \ \ for (ys = xs; x != invalid && *ys != invalid; ys++) { \ if (*ys == x) { \ log_syntax(unit, LOG_ERR, filename, \ line, -x, \ "Duplicate entry, ignoring: %s", \ en); \ x = invalid; \ } \ } \ \ if (x == invalid) \ continue; \ \ *(xs + i) = x; \ new_xs = realloc(xs, (++i + 1) * sizeof(type)); \ if (new_xs) \ xs = new_xs; \ else \ return -ENOMEM; \ \ *(xs + i) = invalid; \ } \ \ free(*enums); \ *enums = xs; \ xs = NULL; \ \ return 0; \ } systemd-229/src/shared/dev-setup.c000066400000000000000000000043711265713322000172030ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010-2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "dev-setup.h" #include "label.h" #include "log.h" #include "path-util.h" #include "user-util.h" #include "util.h" int dev_setup(const char *prefix, uid_t uid, gid_t gid) { static const char symlinks[] = "-/proc/kcore\0" "/dev/core\0" "/proc/self/fd\0" "/dev/fd\0" "/proc/self/fd/0\0" "/dev/stdin\0" "/proc/self/fd/1\0" "/dev/stdout\0" "/proc/self/fd/2\0" "/dev/stderr\0"; const char *j, *k; int r; NULSTR_FOREACH_PAIR(j, k, symlinks) { _cleanup_free_ char *link_name = NULL; const char *n; if (j[0] == '-') { j++; if (access(j, F_OK) < 0) continue; } if (prefix) { link_name = prefix_root(prefix, k); if (!link_name) return -ENOMEM; n = link_name; } else n = k; r = symlink_label(j, n); if (r < 0) log_debug_errno(r, "Failed to symlink %s to %s: %m", j, n); if (uid != UID_INVALID || gid != GID_INVALID) if (lchown(n, uid, gid) < 0) log_debug_errno(errno, "Failed to chown %s: %m", n); } return 0; } systemd-229/src/shared/dev-setup.h000066400000000000000000000014631265713322000172070ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010-2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include int dev_setup(const char *prefix, uid_t uid, gid_t gid); systemd-229/src/shared/dns-domain.c000066400000000000000000001117251265713322000173220ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #ifdef HAVE_LIBIDN #include #include #endif #include #include #include #include #include #include "alloc-util.h" #include "dns-domain.h" #include "hashmap.h" #include "hexdecoct.h" #include "in-addr-util.h" #include "macro.h" #include "parse-util.h" #include "string-util.h" #include "strv.h" #include "utf8.h" int dns_label_unescape(const char **name, char *dest, size_t sz) { const char *n; char *d; int r = 0; assert(name); assert(*name); n = *name; d = dest; for (;;) { if (*n == '.') { n++; break; } if (*n == 0) break; if (r >= DNS_LABEL_MAX) return -EINVAL; if (sz <= 0) return -ENOBUFS; if (*n == '\\') { /* Escaped character */ n++; if (*n == 0) /* Ending NUL */ return -EINVAL; else if (*n == '\\' || *n == '.') { /* Escaped backslash or dot */ if (d) *(d++) = *n; sz--; r++; n++; } else if (n[0] >= '0' && n[0] <= '9') { unsigned k; /* Escaped literal ASCII character */ if (!(n[1] >= '0' && n[1] <= '9') || !(n[2] >= '0' && n[2] <= '9')) return -EINVAL; k = ((unsigned) (n[0] - '0') * 100) + ((unsigned) (n[1] - '0') * 10) + ((unsigned) (n[2] - '0')); /* Don't allow anything that doesn't * fit in 8bit. Note that we do allow * control characters, as some servers * (e.g. cloudflare) are happy to * generate labels with them * inside. */ if (k > 255) return -EINVAL; if (d) *(d++) = (char) k; sz--; r++; n += 3; } else return -EINVAL; } else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) { /* Normal character */ if (d) *(d++) = *n; sz--; r++; n++; } else return -EINVAL; } /* Empty label that is not at the end? */ if (r == 0 && *n) return -EINVAL; if (sz >= 1 && d) *d = 0; *name = n; return r; } /* @label_terminal: terminal character of a label, updated to point to the terminal character of * the previous label (always skipping one dot) or to NULL if there are no more * labels. */ int dns_label_unescape_suffix(const char *name, const char **label_terminal, char *dest, size_t sz) { const char *terminal; int r; assert(name); assert(label_terminal); assert(dest); /* no more labels */ if (!*label_terminal) { if (sz >= 1) *dest = 0; return 0; } terminal = *label_terminal; assert(*terminal == '.' || *terminal == 0); /* Skip current terminal character (and accept domain names ending it ".") */ if (*terminal == 0) terminal--; if (terminal >= name && *terminal == '.') terminal--; /* Point name to the last label, and terminal to the preceding terminal symbol (or make it a NULL pointer) */ for (;;) { if (terminal < name) { /* Reached the first label, so indicate that there are no more */ terminal = NULL; break; } /* Find the start of the last label */ if (*terminal == '.') { const char *y; unsigned slashes = 0; for (y = terminal - 1; y >= name && *y == '\\'; y--) slashes ++; if (slashes % 2 == 0) { /* The '.' was not escaped */ name = terminal + 1; break; } else { terminal = y; continue; } } terminal --; } r = dns_label_unescape(&name, dest, sz); if (r < 0) return r; *label_terminal = terminal; return r; } int dns_label_escape(const char *p, size_t l, char *dest, size_t sz) { char *q; /* DNS labels must be between 1 and 63 characters long. A * zero-length label does not exist. See RFC 2182, Section * 11. */ if (l <= 0 || l > DNS_LABEL_MAX) return -EINVAL; if (sz < 1) return -ENOBUFS; assert(p); assert(dest); q = dest; while (l > 0) { if (*p == '.' || *p == '\\') { /* Dot or backslash */ if (sz < 3) return -ENOBUFS; *(q++) = '\\'; *(q++) = *p; sz -= 2; } else if (*p == '_' || *p == '-' || (*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z')) { /* Proper character */ if (sz < 2) return -ENOBUFS; *(q++) = *p; sz -= 1; } else { /* Everything else */ if (sz < 5) return -ENOBUFS; *(q++) = '\\'; *(q++) = '0' + (char) ((uint8_t) *p / 100); *(q++) = '0' + (char) (((uint8_t) *p / 10) % 10); *(q++) = '0' + (char) ((uint8_t) *p % 10); sz -= 4; } p++; l--; } *q = 0; return (int) (q - dest); } int dns_label_escape_new(const char *p, size_t l, char **ret) { _cleanup_free_ char *s = NULL; int r; assert(p); assert(ret); if (l <= 0 || l > DNS_LABEL_MAX) return -EINVAL; s = new(char, DNS_LABEL_ESCAPED_MAX); if (!s) return -ENOMEM; r = dns_label_escape(p, l, s, DNS_LABEL_ESCAPED_MAX); if (r < 0) return r; *ret = s; s = NULL; return r; } int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) { #ifdef HAVE_LIBIDN _cleanup_free_ uint32_t *input = NULL; size_t input_size, l; const char *p; bool contains_8bit = false; char buffer[DNS_LABEL_MAX+1]; assert(encoded); assert(decoded); /* Converts an U-label into an A-label */ if (encoded_size <= 0) return -EINVAL; for (p = encoded; p < encoded + encoded_size; p++) if ((uint8_t) *p > 127) contains_8bit = true; if (!contains_8bit) { if (encoded_size > DNS_LABEL_MAX) return -EINVAL; return 0; } input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size); if (!input) return -ENOMEM; if (idna_to_ascii_4i(input, input_size, buffer, 0) != 0) return -EINVAL; l = strlen(buffer); /* Verify that the the result is not longer than one DNS label. */ if (l <= 0 || l > DNS_LABEL_MAX) return -EINVAL; if (l > decoded_max) return -ENOBUFS; memcpy(decoded, buffer, l); /* If there's room, append a trailing NUL byte, but only then */ if (decoded_max > l) decoded[l] = 0; return (int) l; #else return 0; #endif } int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) { #ifdef HAVE_LIBIDN size_t input_size, output_size; _cleanup_free_ uint32_t *input = NULL; _cleanup_free_ char *result = NULL; uint32_t *output = NULL; size_t w; /* To be invoked after unescaping. Converts an A-label into an U-label. */ assert(encoded); assert(decoded); if (encoded_size <= 0 || encoded_size > DNS_LABEL_MAX) return -EINVAL; if (encoded_size < sizeof(IDNA_ACE_PREFIX)-1) return 0; if (memcmp(encoded, IDNA_ACE_PREFIX, sizeof(IDNA_ACE_PREFIX) -1) != 0) return 0; input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size); if (!input) return -ENOMEM; output_size = input_size; output = newa(uint32_t, output_size); idna_to_unicode_44i(input, input_size, output, &output_size, 0); result = stringprep_ucs4_to_utf8(output, output_size, NULL, &w); if (!result) return -ENOMEM; if (w <= 0) return -EINVAL; if (w > decoded_max) return -ENOBUFS; memcpy(decoded, result, w); /* Append trailing NUL byte if there's space, but only then. */ if (decoded_max > w) decoded[w] = 0; return w; #else return 0; #endif } int dns_name_concat(const char *a, const char *b, char **_ret) { _cleanup_free_ char *ret = NULL; size_t n = 0, allocated = 0; const char *p; bool first = true; int r; if (a) p = a; else if (b) { p = b; b = NULL; } else goto finish; for (;;) { char label[DNS_LABEL_MAX]; r = dns_label_unescape(&p, label, sizeof(label)); if (r < 0) return r; if (r == 0) { if (*p != 0) return -EINVAL; if (b) { /* Now continue with the second string, if there is one */ p = b; b = NULL; continue; } break; } if (_ret) { if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) return -ENOMEM; r = dns_label_escape(label, r, ret + n + !first, DNS_LABEL_ESCAPED_MAX); if (r < 0) return r; if (!first) ret[n] = '.'; } else { char escaped[DNS_LABEL_ESCAPED_MAX]; r = dns_label_escape(label, r, escaped, sizeof(escaped)); if (r < 0) return r; } if (!first) n++; else first = false; n += r; } finish: if (n > DNS_HOSTNAME_MAX) return -EINVAL; if (_ret) { if (n == 0) { /* Nothing appended? If so, generate at least a single dot, to indicate the DNS root domain */ if (!GREEDY_REALLOC(ret, allocated, 2)) return -ENOMEM; ret[n++] = '.'; } else { if (!GREEDY_REALLOC(ret, allocated, n + 1)) return -ENOMEM; } ret[n] = 0; *_ret = ret; ret = NULL; } return 0; } void dns_name_hash_func(const void *s, struct siphash *state) { const char *p = s; int r; assert(p); for (;;) { char label[DNS_LABEL_MAX+1]; r = dns_label_unescape(&p, label, sizeof(label)); if (r < 0) break; if (r == 0) break; ascii_strlower_n(label, r); siphash24_compress(label, r, state); siphash24_compress_byte(0, state); /* make sure foobar and foo.bar result in different hashes */ } /* enforce that all names are terminated by the empty label */ string_hash_func("", state); } int dns_name_compare_func(const void *a, const void *b) { const char *x, *y; int r, q; assert(a); assert(b); x = (const char *) a + strlen(a); y = (const char *) b + strlen(b); for (;;) { char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX]; if (x == NULL && y == NULL) return 0; r = dns_label_unescape_suffix(a, &x, la, sizeof(la)); q = dns_label_unescape_suffix(b, &y, lb, sizeof(lb)); if (r < 0 || q < 0) return r - q; r = ascii_strcasecmp_nn(la, r, lb, q); if (r != 0) return r; } } const struct hash_ops dns_name_hash_ops = { .hash = dns_name_hash_func, .compare = dns_name_compare_func }; int dns_name_equal(const char *x, const char *y) { int r, q; assert(x); assert(y); for (;;) { char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX]; r = dns_label_unescape(&x, la, sizeof(la)); if (r < 0) return r; q = dns_label_unescape(&y, lb, sizeof(lb)); if (q < 0) return q; if (r != q) return false; if (r == 0) return true; if (ascii_strcasecmp_n(la, lb, r) != 0) return false; } } int dns_name_endswith(const char *name, const char *suffix) { const char *n, *s, *saved_n = NULL; int r, q; assert(name); assert(suffix); n = name; s = suffix; for (;;) { char ln[DNS_LABEL_MAX], ls[DNS_LABEL_MAX]; r = dns_label_unescape(&n, ln, sizeof(ln)); if (r < 0) return r; if (!saved_n) saved_n = n; q = dns_label_unescape(&s, ls, sizeof(ls)); if (q < 0) return q; if (r == 0 && q == 0) return true; if (r == 0 && saved_n == n) return false; if (r != q || ascii_strcasecmp_n(ln, ls, r) != 0) { /* Not the same, let's jump back, and try with the next label again */ s = suffix; n = saved_n; saved_n = NULL; } } } int dns_name_startswith(const char *name, const char *prefix) { const char *n, *p; int r, q; assert(name); assert(prefix); n = name; p = prefix; for (;;) { char ln[DNS_LABEL_MAX], lp[DNS_LABEL_MAX]; r = dns_label_unescape(&p, lp, sizeof(lp)); if (r < 0) return r; if (r == 0) return true; q = dns_label_unescape(&n, ln, sizeof(ln)); if (q < 0) return q; if (r != q) return false; if (ascii_strcasecmp_n(ln, lp, r) != 0) return false; } } int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret) { const char *n, *s, *saved_before = NULL, *saved_after = NULL, *prefix; int r, q; assert(name); assert(old_suffix); assert(new_suffix); assert(ret); n = name; s = old_suffix; for (;;) { char ln[DNS_LABEL_MAX], ls[DNS_LABEL_MAX]; if (!saved_before) saved_before = n; r = dns_label_unescape(&n, ln, sizeof(ln)); if (r < 0) return r; if (!saved_after) saved_after = n; q = dns_label_unescape(&s, ls, sizeof(ls)); if (q < 0) return q; if (r == 0 && q == 0) break; if (r == 0 && saved_after == n) { *ret = NULL; /* doesn't match */ return 0; } if (r != q || ascii_strcasecmp_n(ln, ls, r) != 0) { /* Not the same, let's jump back, and try with the next label again */ s = old_suffix; n = saved_after; saved_after = saved_before = NULL; } } /* Found it! Now generate the new name */ prefix = strndupa(name, saved_before - name); r = dns_name_concat(prefix, new_suffix, ret); if (r < 0) return r; return 1; } int dns_name_between(const char *a, const char *b, const char *c) { int n; /* Determine if b is strictly greater than a and strictly smaller than c. We consider the order of names to be circular, so that if a is strictly greater than c, we consider b to be between them if it is either greater than a or smaller than c. This is how the canonical DNS name order used in NSEC records work. */ n = dns_name_compare_func(a, c); if (n == 0) return -EINVAL; else if (n < 0) /* a<---b--->c */ return dns_name_compare_func(a, b) < 0 && dns_name_compare_func(b, c) < 0; else /* <--b--c a--b--> */ return dns_name_compare_func(b, c) < 0 || dns_name_compare_func(a, b) < 0; } int dns_name_reverse(int family, const union in_addr_union *a, char **ret) { const uint8_t *p; int r; assert(a); assert(ret); p = (const uint8_t*) a; if (family == AF_INET) r = asprintf(ret, "%u.%u.%u.%u.in-addr.arpa", p[3], p[2], p[1], p[0]); else if (family == AF_INET6) r = asprintf(ret, "%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.ip6.arpa", hexchar(p[15] & 0xF), hexchar(p[15] >> 4), hexchar(p[14] & 0xF), hexchar(p[14] >> 4), hexchar(p[13] & 0xF), hexchar(p[13] >> 4), hexchar(p[12] & 0xF), hexchar(p[12] >> 4), hexchar(p[11] & 0xF), hexchar(p[11] >> 4), hexchar(p[10] & 0xF), hexchar(p[10] >> 4), hexchar(p[ 9] & 0xF), hexchar(p[ 9] >> 4), hexchar(p[ 8] & 0xF), hexchar(p[ 8] >> 4), hexchar(p[ 7] & 0xF), hexchar(p[ 7] >> 4), hexchar(p[ 6] & 0xF), hexchar(p[ 6] >> 4), hexchar(p[ 5] & 0xF), hexchar(p[ 5] >> 4), hexchar(p[ 4] & 0xF), hexchar(p[ 4] >> 4), hexchar(p[ 3] & 0xF), hexchar(p[ 3] >> 4), hexchar(p[ 2] & 0xF), hexchar(p[ 2] >> 4), hexchar(p[ 1] & 0xF), hexchar(p[ 1] >> 4), hexchar(p[ 0] & 0xF), hexchar(p[ 0] >> 4)); else return -EAFNOSUPPORT; if (r < 0) return -ENOMEM; return 0; } int dns_name_address(const char *p, int *family, union in_addr_union *address) { int r; assert(p); assert(family); assert(address); r = dns_name_endswith(p, "in-addr.arpa"); if (r < 0) return r; if (r > 0) { uint8_t a[4]; unsigned i; for (i = 0; i < ELEMENTSOF(a); i++) { char label[DNS_LABEL_MAX+1]; r = dns_label_unescape(&p, label, sizeof(label)); if (r < 0) return r; if (r == 0) return -EINVAL; if (r > 3) return -EINVAL; r = safe_atou8(label, &a[i]); if (r < 0) return r; } r = dns_name_equal(p, "in-addr.arpa"); if (r <= 0) return r; *family = AF_INET; address->in.s_addr = htobe32(((uint32_t) a[3] << 24) | ((uint32_t) a[2] << 16) | ((uint32_t) a[1] << 8) | (uint32_t) a[0]); return 1; } r = dns_name_endswith(p, "ip6.arpa"); if (r < 0) return r; if (r > 0) { struct in6_addr a; unsigned i; for (i = 0; i < ELEMENTSOF(a.s6_addr); i++) { char label[DNS_LABEL_MAX+1]; int x, y; r = dns_label_unescape(&p, label, sizeof(label)); if (r <= 0) return r; if (r != 1) return -EINVAL; x = unhexchar(label[0]); if (x < 0) return -EINVAL; r = dns_label_unescape(&p, label, sizeof(label)); if (r <= 0) return r; if (r != 1) return -EINVAL; y = unhexchar(label[0]); if (y < 0) return -EINVAL; a.s6_addr[ELEMENTSOF(a.s6_addr) - i - 1] = (uint8_t) y << 4 | (uint8_t) x; } r = dns_name_equal(p, "ip6.arpa"); if (r <= 0) return r; *family = AF_INET6; address->in6 = a; return 1; } return 0; } bool dns_name_is_root(const char *name) { assert(name); /* There are exactly two ways to encode the root domain name: * as empty string, or with a single dot. */ return STR_IN_SET(name, "", "."); } bool dns_name_is_single_label(const char *name) { int r; assert(name); r = dns_name_parent(&name); if (r <= 0) return false; return dns_name_is_root(name); } /* Encode a domain name according to RFC 1035 Section 3.1, without compression */ int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, bool canonical) { uint8_t *label_length, *out; int r; assert(domain); assert(buffer); out = buffer; do { /* Reserve a byte for label length */ if (len <= 0) return -ENOBUFS; len--; label_length = out; out++; /* Convert and copy a single label. Note that * dns_label_unescape() returns 0 when it hits the end * of the domain name, which we rely on here to encode * the trailing NUL byte. */ r = dns_label_unescape(&domain, (char *) out, len); if (r < 0) return r; /* Optionally, output the name in DNSSEC canonical * format, as described in RFC 4034, section 6.2. Or * in other words: in lower-case. */ if (canonical) ascii_strlower_n((char*) out, (size_t) r); /* Fill label length, move forward */ *label_length = r; out += r; len -= r; } while (r != 0); /* Verify the maximum size of the encoded name. The trailing * dot + NUL byte account are included this time, hence * compare against DNS_HOSTNAME_MAX + 2 (which is 255) this * time. */ if (out - buffer > DNS_HOSTNAME_MAX + 2) return -EINVAL; return out - buffer; } static bool srv_type_label_is_valid(const char *label, size_t n) { size_t k; assert(label); if (n < 2) /* Label needs to be at least 2 chars long */ return false; if (label[0] != '_') /* First label char needs to be underscore */ return false; /* Second char must be a letter */ if (!(label[1] >= 'A' && label[1] <= 'Z') && !(label[1] >= 'a' && label[1] <= 'z')) return false; /* Third and further chars must be alphanumeric or a hyphen */ for (k = 2; k < n; k++) { if (!(label[k] >= 'A' && label[k] <= 'Z') && !(label[k] >= 'a' && label[k] <= 'z') && !(label[k] >= '0' && label[k] <= '9') && label[k] != '-') return false; } return true; } bool dns_srv_type_is_valid(const char *name) { unsigned c = 0; int r; if (!name) return false; for (;;) { char label[DNS_LABEL_MAX]; /* This more or less implements RFC 6335, Section 5.1 */ r = dns_label_unescape(&name, label, sizeof(label)); if (r < 0) return false; if (r == 0) break; if (c >= 2) return false; if (!srv_type_label_is_valid(label, r)) return false; c++; } return c == 2; /* exactly two labels */ } bool dns_service_name_is_valid(const char *name) { size_t l; /* This more or less implements RFC 6763, Section 4.1.1 */ if (!name) return false; if (!utf8_is_valid(name)) return false; if (string_has_cc(name, NULL)) return false; l = strlen(name); if (l <= 0) return false; if (l > 63) return false; return true; } int dns_service_join(const char *name, const char *type, const char *domain, char **ret) { char escaped[DNS_LABEL_ESCAPED_MAX]; _cleanup_free_ char *n = NULL; int r; assert(type); assert(domain); assert(ret); if (!dns_srv_type_is_valid(type)) return -EINVAL; if (!name) return dns_name_concat(type, domain, ret); if (!dns_service_name_is_valid(name)) return -EINVAL; r = dns_label_escape(name, strlen(name), escaped, sizeof(escaped)); if (r < 0) return r; r = dns_name_concat(type, domain, &n); if (r < 0) return r; return dns_name_concat(escaped, n, ret); } static bool dns_service_name_label_is_valid(const char *label, size_t n) { char *s; assert(label); if (memchr(label, 0, n)) return false; s = strndupa(label, n); return dns_service_name_is_valid(s); } int dns_service_split(const char *joined, char **_name, char **_type, char **_domain) { _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL; const char *p = joined, *q = NULL, *d = NULL; char a[DNS_LABEL_MAX], b[DNS_LABEL_MAX], c[DNS_LABEL_MAX]; int an, bn, cn, r; unsigned x = 0; assert(joined); /* Get first label from the full name */ an = dns_label_unescape(&p, a, sizeof(a)); if (an < 0) return an; if (an > 0) { x++; /* If there was a first label, try to get the second one */ bn = dns_label_unescape(&p, b, sizeof(b)); if (bn < 0) return bn; if (bn > 0) { x++; /* If there was a second label, try to get the third one */ q = p; cn = dns_label_unescape(&p, c, sizeof(c)); if (cn < 0) return cn; if (cn > 0) x++; } else cn = 0; } else an = 0; if (x >= 2 && srv_type_label_is_valid(b, bn)) { if (x >= 3 && srv_type_label_is_valid(c, cn)) { if (dns_service_name_label_is_valid(a, an)) { /* OK, got . . . */ name = strndup(a, an); if (!name) return -ENOMEM; type = strjoin(b, ".", c, NULL); if (!type) return -ENOMEM; d = p; goto finish; } } else if (srv_type_label_is_valid(a, an)) { /* OK, got . . */ name = NULL; type = strjoin(a, ".", b, NULL); if (!type) return -ENOMEM; d = q; goto finish; } } name = NULL; type = NULL; d = joined; finish: r = dns_name_normalize(d, &domain); if (r < 0) return r; if (_domain) { *_domain = domain; domain = NULL; } if (_type) { *_type = type; type = NULL; } if (_name) { *_name = name; name = NULL; } return 0; } static int dns_name_build_suffix_table(const char *name, const char*table[]) { const char *p; unsigned n = 0; int r; assert(name); assert(table); p = name; for (;;) { if (n > DNS_N_LABELS_MAX) return -EINVAL; table[n] = p; r = dns_name_parent(&p); if (r < 0) return r; if (r == 0) break; n++; } return (int) n; } int dns_name_suffix(const char *name, unsigned n_labels, const char **ret) { const char* labels[DNS_N_LABELS_MAX+1]; int n; assert(name); assert(ret); n = dns_name_build_suffix_table(name, labels); if (n < 0) return n; if ((unsigned) n < n_labels) return -EINVAL; *ret = labels[n - n_labels]; return (int) (n - n_labels); } int dns_name_skip(const char *a, unsigned n_labels, const char **ret) { int r; assert(a); assert(ret); for (; n_labels > 0; n_labels --) { r = dns_name_parent(&a); if (r < 0) return r; if (r == 0) { *ret = ""; return 0; } } *ret = a; return 1; } int dns_name_count_labels(const char *name) { unsigned n = 0; const char *p; int r; assert(name); p = name; for (;;) { r = dns_name_parent(&p); if (r < 0) return r; if (r == 0) break; if (n >= DNS_N_LABELS_MAX) return -EINVAL; n++; } return (int) n; } int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b) { int r; assert(a); assert(b); r = dns_name_skip(a, n_labels, &a); if (r <= 0) return r; return dns_name_equal(a, b); } int dns_name_common_suffix(const char *a, const char *b, const char **ret) { const char *a_labels[DNS_N_LABELS_MAX+1], *b_labels[DNS_N_LABELS_MAX+1]; int n = 0, m = 0, k = 0, r, q; assert(a); assert(b); assert(ret); /* Determines the common suffix of domain names a and b */ n = dns_name_build_suffix_table(a, a_labels); if (n < 0) return n; m = dns_name_build_suffix_table(b, b_labels); if (m < 0) return m; for (;;) { char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX]; const char *x, *y; if (k >= n || k >= m) { *ret = a_labels[n - k]; return 0; } x = a_labels[n - 1 - k]; r = dns_label_unescape(&x, la, sizeof(la)); if (r < 0) return r; y = b_labels[m - 1 - k]; q = dns_label_unescape(&y, lb, sizeof(lb)); if (q < 0) return q; if (r != q || ascii_strcasecmp_n(la, lb, r) != 0) { *ret = a_labels[n - k]; return 0; } k++; } } int dns_name_apply_idna(const char *name, char **ret) { _cleanup_free_ char *buf = NULL; size_t n = 0, allocated = 0; bool first = true; int r, q; assert(name); assert(ret); for (;;) { char label[DNS_LABEL_MAX]; r = dns_label_unescape(&name, label, sizeof(label)); if (r < 0) return r; if (r == 0) break; q = dns_label_apply_idna(label, r, label, sizeof(label)); if (q < 0) return q; if (q > 0) r = q; if (!GREEDY_REALLOC(buf, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) return -ENOMEM; r = dns_label_escape(label, r, buf + n + !first, DNS_LABEL_ESCAPED_MAX); if (r < 0) return r; if (first) first = false; else buf[n++] = '.'; n +=r; } if (n > DNS_HOSTNAME_MAX) return -EINVAL; if (!GREEDY_REALLOC(buf, allocated, n + 1)) return -ENOMEM; buf[n] = 0; *ret = buf; buf = NULL; return (int) n; } systemd-229/src/shared/dns-domain.h000066400000000000000000000101121265713322000173130ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include #include #include #include #include "hashmap.h" #include "in-addr-util.h" /* Length of a single label, with all escaping removed, excluding any trailing dot or NUL byte */ #define DNS_LABEL_MAX 63 /* Worst case length of a single label, with all escaping applied and room for a trailing NUL byte. */ #define DNS_LABEL_ESCAPED_MAX (DNS_LABEL_MAX*4+1) /* Maximum length of a full hostname, consisting of a series of unescaped labels, and no trailing dot or NUL byte */ #define DNS_HOSTNAME_MAX 253 /* Maximum length of a full hostname, on the wire, including the final NUL byte */ #define DNS_WIRE_FOMAT_HOSTNAME_MAX 255 /* Maximum number of labels per valid hostname */ #define DNS_N_LABELS_MAX 127 int dns_label_unescape(const char **name, char *dest, size_t sz); int dns_label_unescape_suffix(const char *name, const char **label_end, char *dest, size_t sz); int dns_label_escape(const char *p, size_t l, char *dest, size_t sz); int dns_label_escape_new(const char *p, size_t l, char **ret); static inline int dns_name_parent(const char **name) { return dns_label_unescape(name, NULL, DNS_LABEL_MAX); } int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max); int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max); int dns_name_concat(const char *a, const char *b, char **ret); static inline int dns_name_normalize(const char *s, char **ret) { /* dns_name_concat() normalizes as a side-effect */ return dns_name_concat(s, NULL, ret); } static inline int dns_name_is_valid(const char *s) { int r; /* dns_name_normalize() verifies as a side effect */ r = dns_name_normalize(s, NULL); if (r == -EINVAL) return 0; if (r < 0) return r; return 1; } void dns_name_hash_func(const void *s, struct siphash *state); int dns_name_compare_func(const void *a, const void *b); extern const struct hash_ops dns_name_hash_ops; int dns_name_between(const char *a, const char *b, const char *c); int dns_name_equal(const char *x, const char *y); int dns_name_endswith(const char *name, const char *suffix); int dns_name_startswith(const char *name, const char *prefix); int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret); int dns_name_reverse(int family, const union in_addr_union *a, char **ret); int dns_name_address(const char *p, int *family, union in_addr_union *a); bool dns_name_is_root(const char *name); bool dns_name_is_single_label(const char *name); int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, bool canonical); bool dns_srv_type_is_valid(const char *name); bool dns_service_name_is_valid(const char *name); int dns_service_join(const char *name, const char *type, const char *domain, char **ret); int dns_service_split(const char *joined, char **name, char **type, char **domain); int dns_name_suffix(const char *name, unsigned n_labels, const char **ret); int dns_name_count_labels(const char *name); int dns_name_skip(const char *a, unsigned n_labels, const char **ret); int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b); int dns_name_common_suffix(const char *a, const char *b, const char **ret); int dns_name_apply_idna(const char *name, char **ret); systemd-229/src/shared/dropin.c000066400000000000000000000151041265713322000165560ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "conf-files.h" #include "dropin.h" #include "escape.h" #include "fd-util.h" #include "fileio-label.h" #include "hashmap.h" #include "log.h" #include "macro.h" #include "mkdir.h" #include "path-util.h" #include "set.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" int drop_in_file(const char *dir, const char *unit, unsigned level, const char *name, char **_p, char **_q) { _cleanup_free_ char *b = NULL; char *p, *q; char prefix[DECIMAL_STR_MAX(unsigned)]; assert(unit); assert(name); assert(_p); assert(_q); sprintf(prefix, "%u", level); b = xescape(name, "/."); if (!b) return -ENOMEM; if (!filename_is_valid(b)) return -EINVAL; p = strjoin(dir, "/", unit, ".d", NULL); if (!p) return -ENOMEM; q = strjoin(p, "/", prefix, "-", b, ".conf", NULL); if (!q) { free(p); return -ENOMEM; } *_p = p; *_q = q; return 0; } int write_drop_in(const char *dir, const char *unit, unsigned level, const char *name, const char *data) { _cleanup_free_ char *p = NULL, *q = NULL; int r; assert(dir); assert(unit); assert(name); assert(data); r = drop_in_file(dir, unit, level, name, &p, &q); if (r < 0) return r; (void) mkdir_p(p, 0755); return write_string_file_atomic_label(q, data); } int write_drop_in_format(const char *dir, const char *unit, unsigned level, const char *name, const char *format, ...) { _cleanup_free_ char *p = NULL; va_list ap; int r; assert(dir); assert(unit); assert(name); assert(format); va_start(ap, format); r = vasprintf(&p, format, ap); va_end(ap); if (r < 0) return -ENOMEM; return write_drop_in(dir, unit, level, name, p); } static int iterate_dir( const char *path, UnitDependency dependency, dependency_consumer_t consumer, void *arg, char ***strv) { _cleanup_closedir_ DIR *d = NULL; int r; assert(path); /* The config directories are special, since the order of the * drop-ins matters */ if (dependency < 0) { r = strv_extend(strv, path); if (r < 0) return log_oom(); return 0; } assert(consumer); d = opendir(path); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open directory %s: %m", path); } for (;;) { struct dirent *de; _cleanup_free_ char *f = NULL; errno = 0; de = readdir(d); if (!de && errno > 0) return log_error_errno(errno, "Failed to read directory %s: %m", path); if (!de) break; if (hidden_file(de->d_name)) continue; f = strjoin(path, "/", de->d_name, NULL); if (!f) return log_oom(); r = consumer(dependency, de->d_name, f, arg); if (r < 0) return r; } return 0; } int unit_file_process_dir( Set *unit_path_cache, const char *unit_path, const char *name, const char *suffix, UnitDependency dependency, dependency_consumer_t consumer, void *arg, char ***strv) { _cleanup_free_ char *path = NULL; int r; assert(unit_path); assert(name); assert(suffix); path = strjoin(unit_path, "/", name, suffix, NULL); if (!path) return log_oom(); if (!unit_path_cache || set_get(unit_path_cache, path)) (void) iterate_dir(path, dependency, consumer, arg, strv); if (unit_name_is_valid(name, UNIT_NAME_INSTANCE)) { _cleanup_free_ char *template = NULL, *p = NULL; /* Also try the template dir */ r = unit_name_template(name, &template); if (r < 0) return log_error_errno(r, "Failed to generate template from unit name: %m"); p = strjoin(unit_path, "/", template, suffix, NULL); if (!p) return log_oom(); if (!unit_path_cache || set_get(unit_path_cache, p)) (void) iterate_dir(p, dependency, consumer, arg, strv); } return 0; } int unit_file_find_dropin_paths( char **lookup_path, Set *unit_path_cache, Set *names, char ***paths) { _cleanup_strv_free_ char **strv = NULL, **ans = NULL; Iterator i; char *t; int r; assert(paths); SET_FOREACH(t, names, i) { char **p; STRV_FOREACH(p, lookup_path) unit_file_process_dir(unit_path_cache, *p, t, ".d", _UNIT_DEPENDENCY_INVALID, NULL, NULL, &strv); } if (strv_isempty(strv)) return 0; r = conf_files_list_strv(&ans, ".conf", NULL, (const char**) strv); if (r < 0) return log_warning_errno(r, "Failed to get list of configuration files: %m"); *paths = ans; ans = NULL; return 1; } systemd-229/src/shared/dropin.h000066400000000000000000000041341265713322000165640ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "hashmap.h" #include "macro.h" #include "set.h" #include "unit-name.h" int drop_in_file(const char *dir, const char *unit, unsigned level, const char *name, char **_p, char **_q); int write_drop_in(const char *dir, const char *unit, unsigned level, const char *name, const char *data); int write_drop_in_format(const char *dir, const char *unit, unsigned level, const char *name, const char *format, ...) _printf_(5, 6); /** * This callback will be called for each directory entry @entry, * with @filepath being the full path to the entry. * * If return value is negative, loop will be aborted. */ typedef int (*dependency_consumer_t)(UnitDependency dependency, const char *entry, const char* filepath, void *arg); int unit_file_process_dir( Set * unit_path_cache, const char *unit_path, const char *name, const char *suffix, UnitDependency dependency, dependency_consumer_t consumer, void *arg, char ***strv); int unit_file_find_dropin_paths( char **lookup_path, Set *unit_path_cache, Set *names, char ***paths); systemd-229/src/shared/efivars.c000066400000000000000000000504321265713322000167250ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include "sd-id128.h" #include "alloc-util.h" #include "dirent-util.h" #include "efivars.h" #include "fd-util.h" #include "io-util.h" #include "macro.h" #include "parse-util.h" #include "stdio-util.h" #include "time-util.h" #include "utf8.h" #include "util.h" #include "virt.h" #ifdef ENABLE_EFI #define LOAD_OPTION_ACTIVE 0x00000001 #define MEDIA_DEVICE_PATH 0x04 #define MEDIA_HARDDRIVE_DP 0x01 #define MEDIA_FILEPATH_DP 0x04 #define SIGNATURE_TYPE_GUID 0x02 #define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 #define END_DEVICE_PATH_TYPE 0x7f #define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff #define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001 struct boot_option { uint32_t attr; uint16_t path_len; uint16_t title[]; } _packed_; struct drive_path { uint32_t part_nr; uint64_t part_start; uint64_t part_size; char signature[16]; uint8_t mbr_type; uint8_t signature_type; } _packed_; struct device_path { uint8_t type; uint8_t sub_type; uint16_t length; union { uint16_t path[0]; struct drive_path drive; }; } _packed_; bool is_efi_boot(void) { return access("/sys/firmware/efi", F_OK) >= 0; } static int read_flag(const char *varname) { int r; _cleanup_free_ void *v = NULL; size_t s; uint8_t b; r = efi_get_variable(EFI_VENDOR_GLOBAL, varname, NULL, &v, &s); if (r < 0) return r; if (s != 1) return -EINVAL; b = *(uint8_t *)v; r = b > 0; return r; } bool is_efi_secure_boot(void) { return read_flag("SecureBoot") > 0; } bool is_efi_secure_boot_setup_mode(void) { return read_flag("SetupMode") > 0; } int efi_reboot_to_firmware_supported(void) { int r; size_t s; uint64_t b; _cleanup_free_ void *v = NULL; if (!is_efi_boot() || detect_container() > 0) return -EOPNOTSUPP; r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndicationsSupported", NULL, &v, &s); if (r < 0) return r; else if (s != sizeof(uint64_t)) return -EINVAL; b = *(uint64_t *)v; b &= EFI_OS_INDICATIONS_BOOT_TO_FW_UI; return b > 0 ? 0 : -EOPNOTSUPP; } static int get_os_indications(uint64_t *os_indication) { int r; size_t s; _cleanup_free_ void *v = NULL; r = efi_reboot_to_firmware_supported(); if (r < 0) return r; r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndications", NULL, &v, &s); if (r == -ENOENT) { /* Some firmware implementations that do support * OsIndications and report that with * OsIndicationsSupported will remove the * OsIndications variable when it is unset. Let's * pretend it's 0 then, to hide this implementation * detail. Note that this call will return -ENOENT * then only if the support for OsIndications is * missing entirely, as determined by * efi_reboot_to_firmware_supported() above. */ *os_indication = 0; return 0; } else if (r < 0) return r; else if (s != sizeof(uint64_t)) return -EINVAL; *os_indication = *(uint64_t *)v; return 0; } int efi_get_reboot_to_firmware(void) { int r; uint64_t b; r = get_os_indications(&b); if (r < 0) return r; return !!(b & EFI_OS_INDICATIONS_BOOT_TO_FW_UI); } int efi_set_reboot_to_firmware(bool value) { int r; uint64_t b, b_new; r = get_os_indications(&b); if (r < 0) return r; if (value) b_new = b | EFI_OS_INDICATIONS_BOOT_TO_FW_UI; else b_new = b & ~EFI_OS_INDICATIONS_BOOT_TO_FW_UI; /* Avoid writing to efi vars store if we can due to firmware bugs. */ if (b != b_new) return efi_set_variable(EFI_VENDOR_GLOBAL, "OsIndications", &b_new, sizeof(uint64_t)); return 0; } int efi_get_variable( sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size) { _cleanup_close_ int fd = -1; _cleanup_free_ char *p = NULL; uint32_t a; ssize_t n; struct stat st; _cleanup_free_ void *buf = NULL; assert(name); assert(value); assert(size); if (asprintf(&p, "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", name, SD_ID128_FORMAT_VAL(vendor)) < 0) return -ENOMEM; fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) return -errno; if (fstat(fd, &st) < 0) return -errno; if (st.st_size < 4) return -EIO; if (st.st_size > 4*1024*1024 + 4) return -E2BIG; n = read(fd, &a, sizeof(a)); if (n < 0) return -errno; if (n != sizeof(a)) return -EIO; buf = malloc(st.st_size - 4 + 2); if (!buf) return -ENOMEM; n = read(fd, buf, (size_t) st.st_size - 4); if (n < 0) return -errno; if (n != (ssize_t) st.st_size - 4) return -EIO; /* Always NUL terminate (2 bytes, to protect UTF-16) */ ((char*) buf)[st.st_size - 4] = 0; ((char*) buf)[st.st_size - 4 + 1] = 0; *value = buf; buf = NULL; *size = (size_t) st.st_size - 4; if (attribute) *attribute = a; return 0; } int efi_set_variable( sd_id128_t vendor, const char *name, const void *value, size_t size) { struct var { uint32_t attr; char buf[]; } _packed_ * _cleanup_free_ buf = NULL; _cleanup_free_ char *p = NULL; _cleanup_close_ int fd = -1; assert(name); if (asprintf(&p, "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", name, SD_ID128_FORMAT_VAL(vendor)) < 0) return -ENOMEM; if (size == 0) { if (unlink(p) < 0) return -errno; return 0; } fd = open(p, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0644); if (fd < 0) return -errno; buf = malloc(sizeof(uint32_t) + size); if (!buf) return -ENOMEM; buf->attr = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS; memcpy(buf->buf, value, size); return loop_write(fd, buf, sizeof(uint32_t) + size, false); } int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) { _cleanup_free_ void *s = NULL; size_t ss = 0; int r; char *x; r = efi_get_variable(vendor, name, NULL, &s, &ss); if (r < 0) return r; x = utf16_to_utf8(s, ss); if (!x) return -ENOMEM; *p = x; return 0; } static size_t utf16_size(const uint16_t *s) { size_t l = 0; while (s[l] > 0) l++; return (l+1) * sizeof(uint16_t); } static void efi_guid_to_id128(const void *guid, sd_id128_t *id128) { struct uuid { uint32_t u1; uint16_t u2; uint16_t u3; uint8_t u4[8]; } _packed_; const struct uuid *uuid = guid; id128->bytes[0] = (uuid->u1 >> 24) & 0xff; id128->bytes[1] = (uuid->u1 >> 16) & 0xff; id128->bytes[2] = (uuid->u1 >> 8) & 0xff; id128->bytes[3] = (uuid->u1) & 0xff; id128->bytes[4] = (uuid->u2 >> 8) & 0xff; id128->bytes[5] = (uuid->u2) & 0xff; id128->bytes[6] = (uuid->u3 >> 8) & 0xff; id128->bytes[7] = (uuid->u3) & 0xff; memcpy(&id128->bytes[8], uuid->u4, sizeof(uuid->u4)); } int efi_get_boot_option( uint16_t id, char **title, sd_id128_t *part_uuid, char **path, bool *active) { char boot_id[9]; _cleanup_free_ uint8_t *buf = NULL; size_t l; struct boot_option *header; size_t title_size; _cleanup_free_ char *s = NULL, *p = NULL; sd_id128_t p_uuid = SD_ID128_NULL; int r; xsprintf(boot_id, "Boot%04X", id); r = efi_get_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, (void **)&buf, &l); if (r < 0) return r; if (l < sizeof(struct boot_option)) return -ENOENT; header = (struct boot_option *)buf; title_size = utf16_size(header->title); if (title_size > l - offsetof(struct boot_option, title)) return -EINVAL; if (title) { s = utf16_to_utf8(header->title, title_size); if (!s) return -ENOMEM; } if (header->path_len > 0) { uint8_t *dbuf; size_t dnext; dbuf = buf + offsetof(struct boot_option, title) + title_size; dnext = 0; while (dnext < header->path_len) { struct device_path *dpath; dpath = (struct device_path *)(dbuf + dnext); if (dpath->length < 4) break; /* Type 0x7F – End of Hardware Device Path, Sub-Type 0xFF – End Entire Device Path */ if (dpath->type == END_DEVICE_PATH_TYPE && dpath->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE) break; dnext += dpath->length; /* Type 0x04 – Media Device Path */ if (dpath->type != MEDIA_DEVICE_PATH) continue; /* Sub-Type 1 – Hard Drive */ if (dpath->sub_type == MEDIA_HARDDRIVE_DP) { /* 0x02 – GUID Partition Table */ if (dpath->drive.mbr_type != MBR_TYPE_EFI_PARTITION_TABLE_HEADER) continue; /* 0x02 – GUID signature */ if (dpath->drive.signature_type != SIGNATURE_TYPE_GUID) continue; if (part_uuid) efi_guid_to_id128(dpath->drive.signature, &p_uuid); continue; } /* Sub-Type 4 – File Path */ if (dpath->sub_type == MEDIA_FILEPATH_DP && !p && path) { p = utf16_to_utf8(dpath->path, dpath->length-4); efi_tilt_backslashes(p); continue; } } } if (title) { *title = s; s = NULL; } if (part_uuid) *part_uuid = p_uuid; if (path) { *path = p; p = NULL; } if (active) *active = !!(header->attr & LOAD_OPTION_ACTIVE); return 0; } static void to_utf16(uint16_t *dest, const char *src) { int i; for (i = 0; src[i] != '\0'; i++) dest[i] = src[i]; dest[i] = '\0'; } struct guid { uint32_t u1; uint16_t u2; uint16_t u3; uint8_t u4[8]; } _packed_; static void id128_to_efi_guid(sd_id128_t id, void *guid) { struct guid *uuid = guid; uuid->u1 = id.bytes[0] << 24 | id.bytes[1] << 16 | id.bytes[2] << 8 | id.bytes[3]; uuid->u2 = id.bytes[4] << 8 | id.bytes[5]; uuid->u3 = id.bytes[6] << 8 | id.bytes[7]; memcpy(uuid->u4, id.bytes+8, sizeof(uuid->u4)); } static uint16_t *tilt_slashes(uint16_t *s) { uint16_t *p; for (p = s; *p; p++) if (*p == '/') *p = '\\'; return s; } int efi_add_boot_option(uint16_t id, const char *title, uint32_t part, uint64_t pstart, uint64_t psize, sd_id128_t part_uuid, const char *path) { char boot_id[9]; size_t size; size_t title_len; size_t path_len; struct boot_option *option; struct device_path *devicep; _cleanup_free_ char *buf = NULL; title_len = (strlen(title)+1) * 2; path_len = (strlen(path)+1) * 2; buf = calloc(sizeof(struct boot_option) + title_len + sizeof(struct drive_path) + sizeof(struct device_path) + path_len, 1); if (!buf) return -ENOMEM; /* header */ option = (struct boot_option *)buf; option->attr = LOAD_OPTION_ACTIVE; option->path_len = offsetof(struct device_path, drive) + sizeof(struct drive_path) + offsetof(struct device_path, path) + path_len + offsetof(struct device_path, path); to_utf16(option->title, title); size = offsetof(struct boot_option, title) + title_len; /* partition info */ devicep = (struct device_path *)(buf + size); devicep->type = MEDIA_DEVICE_PATH; devicep->sub_type = MEDIA_HARDDRIVE_DP; devicep->length = offsetof(struct device_path, drive) + sizeof(struct drive_path); devicep->drive.part_nr = part; devicep->drive.part_start = pstart; devicep->drive.part_size = psize; devicep->drive.signature_type = SIGNATURE_TYPE_GUID; devicep->drive.mbr_type = MBR_TYPE_EFI_PARTITION_TABLE_HEADER; id128_to_efi_guid(part_uuid, devicep->drive.signature); size += devicep->length; /* path to loader */ devicep = (struct device_path *)(buf + size); devicep->type = MEDIA_DEVICE_PATH; devicep->sub_type = MEDIA_FILEPATH_DP; devicep->length = offsetof(struct device_path, path) + path_len; to_utf16(devicep->path, path); tilt_slashes(devicep->path); size += devicep->length; /* end of path */ devicep = (struct device_path *)(buf + size); devicep->type = END_DEVICE_PATH_TYPE; devicep->sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE; devicep->length = offsetof(struct device_path, path); size += devicep->length; xsprintf(boot_id, "Boot%04X", id); return efi_set_variable(EFI_VENDOR_GLOBAL, boot_id, buf, size); } int efi_remove_boot_option(uint16_t id) { char boot_id[9]; xsprintf(boot_id, "Boot%04X", id); return efi_set_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, 0); } int efi_get_boot_order(uint16_t **order) { _cleanup_free_ void *buf = NULL; size_t l; int r; r = efi_get_variable(EFI_VENDOR_GLOBAL, "BootOrder", NULL, &buf, &l); if (r < 0) return r; if (l <= 0) return -ENOENT; if (l % sizeof(uint16_t) > 0 || l / sizeof(uint16_t) > INT_MAX) return -EINVAL; *order = buf; buf = NULL; return (int) (l / sizeof(uint16_t)); } int efi_set_boot_order(uint16_t *order, size_t n) { return efi_set_variable(EFI_VENDOR_GLOBAL, "BootOrder", order, n * sizeof(uint16_t)); } static int boot_id_hex(const char s[4]) { int i; int id = 0; for (i = 0; i < 4; i++) if (s[i] >= '0' && s[i] <= '9') id |= (s[i] - '0') << (3 - i) * 4; else if (s[i] >= 'A' && s[i] <= 'F') id |= (s[i] - 'A' + 10) << (3 - i) * 4; else return -EINVAL; return id; } static int cmp_uint16(const void *_a, const void *_b) { const uint16_t *a = _a, *b = _b; return (int)*a - (int)*b; } int efi_get_boot_options(uint16_t **options) { _cleanup_closedir_ DIR *dir = NULL; struct dirent *de; _cleanup_free_ uint16_t *list = NULL; size_t alloc = 0; int count = 0; assert(options); dir = opendir("/sys/firmware/efi/efivars/"); if (!dir) return -errno; FOREACH_DIRENT(de, dir, return -errno) { int id; if (strncmp(de->d_name, "Boot", 4) != 0) continue; if (strlen(de->d_name) != 45) continue; if (strcmp(de->d_name + 8, "-8be4df61-93ca-11d2-aa0d-00e098032b8c") != 0) continue; id = boot_id_hex(de->d_name + 4); if (id < 0) continue; if (!GREEDY_REALLOC(list, alloc, count + 1)) return -ENOMEM; list[count++] = id; } qsort_safe(list, count, sizeof(uint16_t), cmp_uint16); *options = list; list = NULL; return count; } static int read_usec(sd_id128_t vendor, const char *name, usec_t *u) { _cleanup_free_ char *j = NULL; int r; uint64_t x = 0; assert(name); assert(u); r = efi_get_variable_string(EFI_VENDOR_LOADER, name, &j); if (r < 0) return r; r = safe_atou64(j, &x); if (r < 0) return r; *u = x; return 0; } int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) { uint64_t x, y; int r; assert(firmware); assert(loader); r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeInitUSec", &x); if (r < 0) return r; r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeExecUSec", &y); if (r < 0) return r; if (y == 0 || y < x) return -EIO; if (y > USEC_PER_HOUR) return -EIO; *firmware = x; *loader = y; return 0; } int efi_loader_get_device_part_uuid(sd_id128_t *u) { _cleanup_free_ char *p = NULL; int r, parsed[16]; r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderDevicePartUUID", &p); if (r < 0) return r; if (sscanf(p, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", &parsed[0], &parsed[1], &parsed[2], &parsed[3], &parsed[4], &parsed[5], &parsed[6], &parsed[7], &parsed[8], &parsed[9], &parsed[10], &parsed[11], &parsed[12], &parsed[13], &parsed[14], &parsed[15]) != 16) return -EIO; if (u) { unsigned i; for (i = 0; i < ELEMENTSOF(parsed); i++) u->bytes[i] = parsed[i]; } return 0; } #endif char *efi_tilt_backslashes(char *s) { char *p; for (p = s; *p; p++) if (*p == '\\') *p = '/'; return s; } systemd-229/src/shared/efivars.h000066400000000000000000000100271265713322000167260ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-id128.h" #include "time-util.h" #define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f) #define EFI_VENDOR_GLOBAL SD_ID128_MAKE(8b,e4,df,61,93,ca,11,d2,aa,0d,00,e0,98,03,2b,8c) #define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001 #define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 #define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 #ifdef ENABLE_EFI bool is_efi_boot(void); bool is_efi_secure_boot(void); bool is_efi_secure_boot_setup_mode(void); int efi_reboot_to_firmware_supported(void); int efi_get_reboot_to_firmware(void); int efi_set_reboot_to_firmware(bool value); int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size); int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size); int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p); int efi_get_boot_option(uint16_t nr, char **title, sd_id128_t *part_uuid, char **path, bool *active); int efi_add_boot_option(uint16_t id, const char *title, uint32_t part, uint64_t pstart, uint64_t psize, sd_id128_t part_uuid, const char *path); int efi_remove_boot_option(uint16_t id); int efi_get_boot_order(uint16_t **order); int efi_set_boot_order(uint16_t *order, size_t n); int efi_get_boot_options(uint16_t **options); int efi_loader_get_device_part_uuid(sd_id128_t *u); int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader); #else static inline bool is_efi_boot(void) { return false; } static inline bool is_efi_secure_boot(void) { return false; } static inline bool is_efi_secure_boot_setup_mode(void) { return false; } static inline int efi_reboot_to_firmware_supported(void) { return -EOPNOTSUPP; } static inline int efi_get_reboot_to_firmware(void) { return -EOPNOTSUPP; } static inline int efi_set_reboot_to_firmware(bool value) { return -EOPNOTSUPP; } static inline int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size) { return -EOPNOTSUPP; } static inline int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size) { return -EOPNOTSUPP; } static inline int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) { return -EOPNOTSUPP; } static inline int efi_get_boot_option(uint16_t nr, char **title, sd_id128_t *part_uuid, char **path, bool *active) { return -EOPNOTSUPP; } static inline int efi_add_boot_option(uint16_t id, const char *title, uint32_t part, uint64_t pstart, uint64_t psize, sd_id128_t part_uuid, const char *path) { return -EOPNOTSUPP; } static inline int efi_remove_boot_option(uint16_t id) { return -EOPNOTSUPP; } static inline int efi_get_boot_order(uint16_t **order) { return -EOPNOTSUPP; } static inline int efi_set_boot_order(uint16_t *order, size_t n) { return -EOPNOTSUPP; } static inline int efi_get_boot_options(uint16_t **options) { return -EOPNOTSUPP; } static inline int efi_loader_get_device_part_uuid(sd_id128_t *u) { return -EOPNOTSUPP; } static inline int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) { return -EOPNOTSUPP; } #endif char *efi_tilt_backslashes(char *s); systemd-229/src/shared/firewall-util.c000066400000000000000000000311621265713322000200450ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "firewall-util.h" #include "in-addr-util.h" #include "macro.h" DEFINE_TRIVIAL_CLEANUP_FUNC(struct xtc_handle*, iptc_free); static int entry_fill_basics( struct ipt_entry *entry, int protocol, const char *in_interface, const union in_addr_union *source, unsigned source_prefixlen, const char *out_interface, const union in_addr_union *destination, unsigned destination_prefixlen) { assert(entry); if (out_interface && strlen(out_interface) >= IFNAMSIZ) return -EINVAL; if (in_interface && strlen(in_interface) >= IFNAMSIZ) return -EINVAL; entry->ip.proto = protocol; if (in_interface) { strcpy(entry->ip.iniface, in_interface); memset(entry->ip.iniface_mask, 0xFF, strlen(in_interface)+1); } if (source) { entry->ip.src = source->in; in_addr_prefixlen_to_netmask(&entry->ip.smsk, source_prefixlen); } if (out_interface) { strcpy(entry->ip.outiface, out_interface); memset(entry->ip.outiface_mask, 0xFF, strlen(out_interface)+1); } if (destination) { entry->ip.dst = destination->in; in_addr_prefixlen_to_netmask(&entry->ip.dmsk, destination_prefixlen); } return 0; } int fw_add_masquerade( bool add, int af, int protocol, const union in_addr_union *source, unsigned source_prefixlen, const char *out_interface, const union in_addr_union *destination, unsigned destination_prefixlen) { _cleanup_(iptc_freep) struct xtc_handle *h = NULL; struct ipt_entry *entry, *mask; struct ipt_entry_target *t; size_t sz; struct nf_nat_ipv4_multi_range_compat *mr; int r; if (af != AF_INET) return -EOPNOTSUPP; if (protocol != 0 && protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) return -EOPNOTSUPP; h = iptc_init("nat"); if (!h) return -errno; sz = XT_ALIGN(sizeof(struct ipt_entry)) + XT_ALIGN(sizeof(struct ipt_entry_target)) + XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)); /* Put together the entry we want to add or remove */ entry = alloca0(sz); entry->next_offset = sz; entry->target_offset = XT_ALIGN(sizeof(struct ipt_entry)); r = entry_fill_basics(entry, protocol, NULL, source, source_prefixlen, out_interface, destination, destination_prefixlen); if (r < 0) return r; /* Fill in target part */ t = ipt_get_target(entry); t->u.target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) + XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)); strncpy(t->u.user.name, "MASQUERADE", sizeof(t->u.user.name)); mr = (struct nf_nat_ipv4_multi_range_compat*) t->data; mr->rangesize = 1; /* Create a search mask entry */ mask = alloca(sz); memset(mask, 0xFF, sz); if (add) { if (iptc_check_entry("POSTROUTING", entry, (unsigned char*) mask, h)) return 0; if (errno != ENOENT) /* if other error than not existing yet, fail */ return -errno; if (!iptc_insert_entry("POSTROUTING", entry, 0, h)) return -errno; } else { if (!iptc_delete_entry("POSTROUTING", entry, (unsigned char*) mask, h)) { if (errno == ENOENT) /* if it's already gone, all is good! */ return 0; return -errno; } } if (!iptc_commit(h)) return -errno; return 0; } int fw_add_local_dnat( bool add, int af, int protocol, const char *in_interface, const union in_addr_union *source, unsigned source_prefixlen, const union in_addr_union *destination, unsigned destination_prefixlen, uint16_t local_port, const union in_addr_union *remote, uint16_t remote_port, const union in_addr_union *previous_remote) { _cleanup_(iptc_freep) struct xtc_handle *h = NULL; struct ipt_entry *entry, *mask; struct ipt_entry_target *t; struct ipt_entry_match *m; struct xt_addrtype_info_v1 *at; struct nf_nat_ipv4_multi_range_compat *mr; size_t sz, msz; int r; assert(add || !previous_remote); if (af != AF_INET) return -EOPNOTSUPP; if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) return -EOPNOTSUPP; if (local_port <= 0) return -EINVAL; if (remote_port <= 0) return -EINVAL; h = iptc_init("nat"); if (!h) return -errno; sz = XT_ALIGN(sizeof(struct ipt_entry)) + XT_ALIGN(sizeof(struct ipt_entry_match)) + XT_ALIGN(sizeof(struct xt_addrtype_info_v1)) + XT_ALIGN(sizeof(struct ipt_entry_target)) + XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)); if (protocol == IPPROTO_TCP) msz = XT_ALIGN(sizeof(struct ipt_entry_match)) + XT_ALIGN(sizeof(struct xt_tcp)); else msz = XT_ALIGN(sizeof(struct ipt_entry_match)) + XT_ALIGN(sizeof(struct xt_udp)); sz += msz; /* Fill in basic part */ entry = alloca0(sz); entry->next_offset = sz; entry->target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + XT_ALIGN(sizeof(struct ipt_entry_match)) + XT_ALIGN(sizeof(struct xt_addrtype_info_v1)) + msz; r = entry_fill_basics(entry, protocol, in_interface, source, source_prefixlen, NULL, destination, destination_prefixlen); if (r < 0) return r; /* Fill in first match */ m = (struct ipt_entry_match*) ((uint8_t*) entry + XT_ALIGN(sizeof(struct ipt_entry))); m->u.match_size = msz; if (protocol == IPPROTO_TCP) { struct xt_tcp *tcp; strncpy(m->u.user.name, "tcp", sizeof(m->u.user.name)); tcp = (struct xt_tcp*) m->data; tcp->dpts[0] = tcp->dpts[1] = local_port; tcp->spts[0] = 0; tcp->spts[1] = 0xFFFF; } else { struct xt_udp *udp; strncpy(m->u.user.name, "udp", sizeof(m->u.user.name)); udp = (struct xt_udp*) m->data; udp->dpts[0] = udp->dpts[1] = local_port; udp->spts[0] = 0; udp->spts[1] = 0xFFFF; } /* Fill in second match */ m = (struct ipt_entry_match*) ((uint8_t*) entry + XT_ALIGN(sizeof(struct ipt_entry)) + msz); m->u.match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) + XT_ALIGN(sizeof(struct xt_addrtype_info_v1)); strncpy(m->u.user.name, "addrtype", sizeof(m->u.user.name)); m->u.user.revision = 1; at = (struct xt_addrtype_info_v1*) m->data; at->dest = XT_ADDRTYPE_LOCAL; /* Fill in target part */ t = ipt_get_target(entry); t->u.target_size = XT_ALIGN(sizeof(struct ipt_entry_target)) + XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)); strncpy(t->u.user.name, "DNAT", sizeof(t->u.user.name)); mr = (struct nf_nat_ipv4_multi_range_compat*) t->data; mr->rangesize = 1; mr->range[0].flags = NF_NAT_RANGE_PROTO_SPECIFIED|NF_NAT_RANGE_MAP_IPS; mr->range[0].min_ip = mr->range[0].max_ip = remote->in.s_addr; if (protocol == IPPROTO_TCP) mr->range[0].min.tcp.port = mr->range[0].max.tcp.port = htons(remote_port); else mr->range[0].min.udp.port = mr->range[0].max.udp.port = htons(remote_port); mask = alloca0(sz); memset(mask, 0xFF, sz); if (add) { /* Add the PREROUTING rule, if it is missing so far */ if (!iptc_check_entry("PREROUTING", entry, (unsigned char*) mask, h)) { if (errno != ENOENT) return -EINVAL; if (!iptc_insert_entry("PREROUTING", entry, 0, h)) return -errno; } /* If a previous remote is set, remove its entry */ if (previous_remote && previous_remote->in.s_addr != remote->in.s_addr) { mr->range[0].min_ip = mr->range[0].max_ip = previous_remote->in.s_addr; if (!iptc_delete_entry("PREROUTING", entry, (unsigned char*) mask, h)) { if (errno != ENOENT) return -errno; } mr->range[0].min_ip = mr->range[0].max_ip = remote->in.s_addr; } /* Add the OUTPUT rule, if it is missing so far */ if (!in_interface) { /* Don't apply onto loopback addresses */ if (!destination) { entry->ip.dst.s_addr = htobe32(0x7F000000); entry->ip.dmsk.s_addr = htobe32(0xFF000000); entry->ip.invflags = IPT_INV_DSTIP; } if (!iptc_check_entry("OUTPUT", entry, (unsigned char*) mask, h)) { if (errno != ENOENT) return -errno; if (!iptc_insert_entry("OUTPUT", entry, 0, h)) return -errno; } /* If a previous remote is set, remove its entry */ if (previous_remote && previous_remote->in.s_addr != remote->in.s_addr) { mr->range[0].min_ip = mr->range[0].max_ip = previous_remote->in.s_addr; if (!iptc_delete_entry("OUTPUT", entry, (unsigned char*) mask, h)) { if (errno != ENOENT) return -errno; } } } } else { if (!iptc_delete_entry("PREROUTING", entry, (unsigned char*) mask, h)) { if (errno != ENOENT) return -errno; } if (!in_interface) { if (!destination) { entry->ip.dst.s_addr = htobe32(0x7F000000); entry->ip.dmsk.s_addr = htobe32(0xFF000000); entry->ip.invflags = IPT_INV_DSTIP; } if (!iptc_delete_entry("OUTPUT", entry, (unsigned char*) mask, h)) { if (errno != ENOENT) return -errno; } } } if (!iptc_commit(h)) return -errno; return 0; } systemd-229/src/shared/firewall-util.h000066400000000000000000000051711265713322000200530ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "in-addr-util.h" #ifdef HAVE_LIBIPTC int fw_add_masquerade( bool add, int af, int protocol, const union in_addr_union *source, unsigned source_prefixlen, const char *out_interface, const union in_addr_union *destination, unsigned destination_prefixlen); int fw_add_local_dnat( bool add, int af, int protocol, const char *in_interface, const union in_addr_union *source, unsigned source_prefixlen, const union in_addr_union *destination, unsigned destination_prefixlen, uint16_t local_port, const union in_addr_union *remote, uint16_t remote_port, const union in_addr_union *previous_remote); #else static inline int fw_add_masquerade( bool add, int af, int protocol, const union in_addr_union *source, unsigned source_prefixlen, const char *out_interface, const union in_addr_union *destination, unsigned destination_prefixlen) { return -EOPNOTSUPP; } static inline int fw_add_local_dnat( bool add, int af, int protocol, const char *in_interface, const union in_addr_union *source, unsigned source_prefixlen, const union in_addr_union *destination, unsigned destination_prefixlen, uint16_t local_port, const union in_addr_union *remote, uint16_t remote_port, const union in_addr_union *previous_remote) { return -EOPNOTSUPP; } #endif systemd-229/src/shared/fstab-util.c000066400000000000000000000174121265713322000173410ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "alloc-util.h" #include "device-nodes.h" #include "fstab-util.h" #include "macro.h" #include "mount-util.h" #include "parse-util.h" #include "path-util.h" #include "string-util.h" #include "strv.h" #include "util.h" bool fstab_is_mount_point(const char *mount) { _cleanup_endmntent_ FILE *f = NULL; struct mntent *m; f = setmntent("/etc/fstab", "r"); if (!f) return false; while ((m = getmntent(f))) if (path_equal(m->mnt_dir, mount)) return true; return false; } int fstab_filter_options(const char *opts, const char *names, const char **namefound, char **value, char **filtered) { const char *name, *n = NULL, *x; _cleanup_strv_free_ char **stor = NULL; _cleanup_free_ char *v = NULL, **strv = NULL; assert(names && *names); if (!opts) goto answer; /* If !value and !filtered, this function is not allowed to fail. */ if (!filtered) { const char *word, *state; size_t l; FOREACH_WORD_SEPARATOR(word, l, opts, ",", state) NULSTR_FOREACH(name, names) { if (l < strlen(name)) continue; if (!strneq(word, name, strlen(name))) continue; /* we know that the string is NUL * terminated, so *x is valid */ x = word + strlen(name); if (IN_SET(*x, '\0', '=', ',')) { n = name; if (value) { free(v); if (IN_SET(*x, '\0', ',')) v = NULL; else { assert(*x == '='); x++; v = strndup(x, l - strlen(name) - 1); if (!v) return -ENOMEM; } } } } } else { char **t, **s; stor = strv_split(opts, ","); if (!stor) return -ENOMEM; strv = memdup(stor, sizeof(char*) * (strv_length(stor) + 1)); if (!strv) return -ENOMEM; for (s = t = strv; *s; s++) { NULSTR_FOREACH(name, names) { x = startswith(*s, name); if (x && IN_SET(*x, '\0', '=')) goto found; } *t = *s; t++; continue; found: /* Keep the last occurence found */ n = name; if (value) { free(v); if (*x == '\0') v = NULL; else { assert(*x == '='); x++; v = strdup(x); if (!v) return -ENOMEM; } } } *t = NULL; } answer: if (namefound) *namefound = n; if (filtered) { char *f; f = strv_join(strv, ","); if (!f) return -ENOMEM; *filtered = f; } if (value) { *value = v; v = NULL; } return !!n; } int fstab_extract_values(const char *opts, const char *name, char ***values) { _cleanup_strv_free_ char **optsv = NULL, **res = NULL; char **s; assert(opts); assert(name); assert(values); optsv = strv_split(opts, ","); if (!optsv) return -ENOMEM; STRV_FOREACH(s, optsv) { char *arg; int r; arg = startswith(*s, name); if (!arg || *arg != '=') continue; r = strv_extend(&res, arg + 1); if (r < 0) return r; } *values = res; res = NULL; return !!*values; } int fstab_find_pri(const char *options, int *ret) { _cleanup_free_ char *opt = NULL; int r; unsigned pri; assert(ret); r = fstab_filter_options(options, "pri\0", NULL, &opt, NULL); if (r < 0) return r; if (r == 0 || !opt) return 0; r = safe_atou(opt, &pri); if (r < 0) return r; if ((int) pri < 0) return -ERANGE; *ret = (int) pri; return 1; } static char *unquote(const char *s, const char* quotes) { size_t l; assert(s); /* This is rather stupid, simply removes the heading and * trailing quotes if there is one. Doesn't care about * escaping or anything. * * DON'T USE THIS FOR NEW CODE ANYMORE!*/ l = strlen(s); if (l < 2) return strdup(s); if (strchr(quotes, s[0]) && s[l-1] == s[0]) return strndup(s+1, l-2); return strdup(s); } static char *tag_to_udev_node(const char *tagvalue, const char *by) { _cleanup_free_ char *t = NULL, *u = NULL; size_t enc_len; u = unquote(tagvalue, QUOTES); if (!u) return NULL; enc_len = strlen(u) * 4 + 1; t = new(char, enc_len); if (!t) return NULL; if (encode_devnode_name(u, t, enc_len) < 0) return NULL; return strjoin("/dev/disk/by-", by, "/", t, NULL); } char *fstab_node_to_udev_node(const char *p) { assert(p); if (startswith(p, "LABEL=")) return tag_to_udev_node(p+6, "label"); if (startswith(p, "UUID=")) return tag_to_udev_node(p+5, "uuid"); if (startswith(p, "PARTUUID=")) return tag_to_udev_node(p+9, "partuuid"); if (startswith(p, "PARTLABEL=")) return tag_to_udev_node(p+10, "partlabel"); return strdup(p); } systemd-229/src/shared/fstab-util.h000066400000000000000000000032071265713322000173430ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "macro.h" bool fstab_is_mount_point(const char *mount); int fstab_filter_options(const char *opts, const char *names, const char **namefound, char **value, char **filtered); int fstab_extract_values(const char *opts, const char *name, char ***values); static inline bool fstab_test_option(const char *opts, const char *names) { return !!fstab_filter_options(opts, names, NULL, NULL, NULL); } int fstab_find_pri(const char *options, int *ret); static inline bool fstab_test_yes_no_option(const char *opts, const char *yes_no) { int r; const char *opt; /* If first name given is last, return 1. * If second name given is last or neither is found, return 0. */ r = fstab_filter_options(opts, yes_no, &opt, NULL, NULL); assert(r >= 0); return opt == yes_no; } char *fstab_node_to_udev_node(const char *p); systemd-229/src/shared/generator.c000066400000000000000000000145741265713322000172630ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "dropin.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "fstab-util.h" #include "generator.h" #include "log.h" #include "macro.h" #include "mkdir.h" #include "path-util.h" #include "special.h" #include "string-util.h" #include "time-util.h" #include "unit-name.h" #include "util.h" static int write_fsck_sysroot_service(const char *dir, const char *what) { _cleanup_free_ char *device = NULL, *escaped = NULL; _cleanup_fclose_ FILE *f = NULL; const char *unit; int r; escaped = cescape(what); if (!escaped) return log_oom(); unit = strjoina(dir, "/systemd-fsck-root.service"); log_debug("Creating %s", unit); r = unit_name_from_path(what, ".device", &device); if (r < 0) return log_error_errno(r, "Failed to convert device \"%s\" to unit name: %m", what); f = fopen(unit, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", unit); fprintf(f, "# Automatically generated by %1$s\n\n" "[Unit]\n" "Documentation=man:systemd-fsck-root.service(8)\n" "Description=File System Check on %2$s\n" "DefaultDependencies=no\n" "BindsTo=%3$s\n" "After=%3$s local-fs-pre.target\n" "Before=shutdown.target\n" "\n" "[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" "ExecStart=" SYSTEMD_FSCK_PATH " %4$s\n" "TimeoutSec=0\n", program_invocation_short_name, what, device, escaped); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", unit); return 0; } int generator_write_fsck_deps( FILE *f, const char *dir, const char *what, const char *where, const char *fstype) { int r; assert(f); assert(dir); assert(what); assert(where); if (!is_device_path(what)) { log_warning("Checking was requested for \"%s\", but it is not a device.", what); return 0; } if (!isempty(fstype) && !streq(fstype, "auto")) { r = fsck_exists(fstype); if (r < 0) log_warning_errno(r, "Checking was requested for %s, but couldn't detect if fsck.%s may be used, proceeding: %m", what, fstype); else if (r == 0) { /* treat missing check as essentially OK */ log_debug("Checking was requested for %s, but fsck.%s does not exist.", what, fstype); return 0; } } if (path_equal(where, "/")) { const char *lnk; lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/systemd-fsck-root.service"); mkdir_parents(lnk, 0755); if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-fsck-root.service", lnk) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); } else { _cleanup_free_ char *_fsck = NULL; const char *fsck; if (in_initrd() && path_equal(where, "/sysroot")) { r = write_fsck_sysroot_service(dir, what); if (r < 0) return r; fsck = "systemd-fsck-root.service"; } else { r = unit_name_from_path_instance("systemd-fsck", what, ".service", &_fsck); if (r < 0) return log_error_errno(r, "Failed to create fsck service name: %m"); fsck = _fsck; } fprintf(f, "Requires=%1$s\n" "After=%1$s\n", fsck); } return 0; } int generator_write_timeouts( const char *dir, const char *what, const char *where, const char *opts, char **filtered) { /* Allow configuration how long we wait for a device that * backs a mount point to show up. This is useful to support * endless device timeouts for devices that show up only after * user input, like crypto devices. */ _cleanup_free_ char *node = NULL, *unit = NULL, *timeout = NULL; usec_t u; int r; r = fstab_filter_options(opts, "comment=systemd.device-timeout\0" "x-systemd.device-timeout\0", NULL, &timeout, filtered); if (r <= 0) return r; r = parse_sec(timeout, &u); if (r < 0) { log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout); return 0; } node = fstab_node_to_udev_node(what); if (!node) return log_oom(); r = unit_name_from_path(node, ".device", &unit); if (r < 0) return log_error_errno(r, "Failed to make unit name from path: %m"); return write_drop_in_format(dir, unit, 50, "device-timeout", "# Automatically generated by %s\n\n" "[Unit]\nJobTimeoutSec=%s", program_invocation_short_name, timeout); } systemd-229/src/shared/generator.h000066400000000000000000000020531265713322000172550ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include int generator_write_fsck_deps( FILE *f, const char *dir, const char *what, const char *where, const char *type); int generator_write_timeouts( const char *dir, const char *what, const char *where, const char *opts, char **filtered); systemd-229/src/shared/gpt.h000066400000000000000000000052221265713322000160620ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include #include "sd-id128.h" /* We only support root disk discovery for x86, x86-64, Itanium and ARM for * now, since EFI for anything else doesn't really exist, and we only * care for root partitions on the same disk as the EFI ESP. */ #define GPT_ROOT_X86 SD_ID128_MAKE(44,47,95,40,f2,97,41,b2,9a,f7,d1,31,d5,f0,45,8a) #define GPT_ROOT_X86_64 SD_ID128_MAKE(4f,68,bc,e3,e8,cd,4d,b1,96,e7,fb,ca,f9,84,b7,09) #define GPT_ROOT_ARM SD_ID128_MAKE(69,da,d7,10,2c,e4,4e,3c,b1,6c,21,a1,d4,9a,be,d3) #define GPT_ROOT_ARM_64 SD_ID128_MAKE(b9,21,b0,45,1d,f0,41,c3,af,44,4c,6f,28,0d,3f,ae) #define GPT_ROOT_IA64 SD_ID128_MAKE(99,3d,8d,3d,f8,0e,42,25,85,5a,9d,af,8e,d7,ea,97) #define GPT_ESP SD_ID128_MAKE(c1,2a,73,28,f8,1f,11,d2,ba,4b,00,a0,c9,3e,c9,3b) #define GPT_SWAP SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f) #define GPT_HOME SD_ID128_MAKE(93,3a,c7,e1,2e,b4,4f,13,b8,44,0e,14,e2,ae,f9,15) #define GPT_SRV SD_ID128_MAKE(3b,8f,84,25,20,e0,4f,3b,90,7f,1a,25,a7,6f,98,e8) #if defined(__x86_64__) # define GPT_ROOT_NATIVE GPT_ROOT_X86_64 # define GPT_ROOT_SECONDARY GPT_ROOT_X86 #elif defined(__i386__) # define GPT_ROOT_NATIVE GPT_ROOT_X86 #endif #if defined(__ia64__) # define GPT_ROOT_NATIVE GPT_ROOT_IA64 #endif #if defined(__aarch64__) && (__BYTE_ORDER != __BIG_ENDIAN) # define GPT_ROOT_NATIVE GPT_ROOT_ARM_64 # define GPT_ROOT_SECONDARY GPT_ROOT_ARM #elif defined(__arm__) && (__BYTE_ORDER != __BIG_ENDIAN) # define GPT_ROOT_NATIVE GPT_ROOT_ARM #endif /* Flags we recognize on the root, swap, home and srv partitions when * doing auto-discovery. These happen to be identical to what * Microsoft defines for its own Basic Data Partitions, but that's * just because we saw no point in defining any other values here. */ #define GPT_FLAG_READ_ONLY (1ULL << 60) #define GPT_FLAG_NO_AUTO (1ULL << 63) #define GPT_LINUX_GENERIC SD_ID128_MAKE(0f,c6,3d,af,84,83,47,72,8e,79,3d,69,d8,47,7d,e4) systemd-229/src/shared/ima-util.c000066400000000000000000000017051265713322000170060ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "ima-util.h" static int use_ima_cached = -1; bool use_ima(void) { if (use_ima_cached < 0) use_ima_cached = access("/sys/kernel/security/ima/", F_OK) >= 0; return use_ima_cached; } systemd-229/src/shared/ima-util.h000066400000000000000000000014071265713322000170120ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include bool use_ima(void); systemd-229/src/shared/import-util.c000066400000000000000000000114051265713322000175500ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "btrfs-util.h" #include "import-util.h" #include "log.h" #include "macro.h" #include "path-util.h" #include "string-table.h" #include "string-util.h" #include "util.h" int import_url_last_component(const char *url, char **ret) { const char *e, *p; char *s; e = strchrnul(url, '?'); while (e > url && e[-1] == '/') e--; p = e; while (p > url && p[-1] != '/') p--; if (e <= p) return -EINVAL; s = strndup(p, e - p); if (!s) return -ENOMEM; *ret = s; return 0; } int import_url_change_last_component(const char *url, const char *suffix, char **ret) { const char *e; char *s; assert(url); assert(ret); e = strchrnul(url, '?'); while (e > url && e[-1] == '/') e--; while (e > url && e[-1] != '/') e--; if (e <= url) return -EINVAL; s = new(char, (e - url) + strlen(suffix) + 1); if (!s) return -ENOMEM; strcpy(mempcpy(s, url, e - url), suffix); *ret = s; return 0; } static const char* const import_verify_table[_IMPORT_VERIFY_MAX] = { [IMPORT_VERIFY_NO] = "no", [IMPORT_VERIFY_CHECKSUM] = "checksum", [IMPORT_VERIFY_SIGNATURE] = "signature", }; DEFINE_STRING_TABLE_LOOKUP(import_verify, ImportVerify); int tar_strip_suffixes(const char *name, char **ret) { const char *e; char *s; e = endswith(name, ".tar"); if (!e) e = endswith(name, ".tar.xz"); if (!e) e = endswith(name, ".tar.gz"); if (!e) e = endswith(name, ".tar.bz2"); if (!e) e = endswith(name, ".tgz"); if (!e) e = strchr(name, 0); if (e <= name) return -EINVAL; s = strndup(name, e - name); if (!s) return -ENOMEM; *ret = s; return 0; } int raw_strip_suffixes(const char *p, char **ret) { static const char suffixes[] = ".xz\0" ".gz\0" ".bz2\0" ".raw\0" ".qcow2\0" ".img\0" ".bin\0"; _cleanup_free_ char *q = NULL; q = strdup(p); if (!q) return -ENOMEM; for (;;) { const char *sfx; bool changed = false; NULSTR_FOREACH(sfx, suffixes) { char *e; e = endswith(q, sfx); if (e) { *e = 0; changed = true; } } if (!changed) break; } *ret = q; q = NULL; return 0; } int import_assign_pool_quota_and_warn(const char *path) { int r; r = btrfs_subvol_auto_qgroup("/var/lib/machines", 0, true); if (r == -ENOTTY) { log_debug_errno(r, "Failed to set up default quota hierarchy for /var/lib/machines, as directory is not on btrfs or not a subvolume. Ignoring."); return 0; } if (r < 0) return log_error_errno(r, "Failed to set up default quota hierarchy for /var/lib/machines: %m"); if (r > 0) log_info("Set up default quota hierarchy for /var/lib/machines."); r = btrfs_subvol_auto_qgroup(path, 0, true); if (r == -ENOTTY) { log_debug_errno(r, "Failed to set up quota hierarchy for %s, as directory is not on btrfs or not a subvolume. Ignoring.", path); return 0; } if (r < 0) return log_error_errno(r, "Failed to set up default quota hierarchy for %s: %m", path); if (r > 0) log_info("Set up default quota hierarchy for %s.", path); return 0; } systemd-229/src/shared/import-util.h000066400000000000000000000026061265713322000175600ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" typedef enum ImportVerify { IMPORT_VERIFY_NO, IMPORT_VERIFY_CHECKSUM, IMPORT_VERIFY_SIGNATURE, _IMPORT_VERIFY_MAX, _IMPORT_VERIFY_INVALID = -1, } ImportVerify; int import_url_last_component(const char *url, char **ret); int import_url_change_last_component(const char *url, const char *suffix, char **ret); const char* import_verify_to_string(ImportVerify v) _const_; ImportVerify import_verify_from_string(const char *s) _pure_; int tar_strip_suffixes(const char *name, char **ret); int raw_strip_suffixes(const char *name, char **ret); int import_assign_pool_quota_and_warn(const char *path); systemd-229/src/shared/initreq.h000066400000000000000000000042321265713322000167430ustar00rootroot00000000000000/* * initreq.h Interface to talk to init through /dev/initctl. * * Copyright (C) 1995-2004 Miquel van Smoorenburg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * Version: @(#)initreq.h 1.28 31-Mar-2004 MvS * */ #ifndef _INITREQ_H #define _INITREQ_H #include #if defined(__FreeBSD_kernel__) # define INIT_FIFO "/etc/.initctl" #else # define INIT_FIFO "/dev/initctl" #endif #define INIT_MAGIC 0x03091969 #define INIT_CMD_START 0 #define INIT_CMD_RUNLVL 1 #define INIT_CMD_POWERFAIL 2 #define INIT_CMD_POWERFAILNOW 3 #define INIT_CMD_POWEROK 4 #define INIT_CMD_BSD 5 #define INIT_CMD_SETENV 6 #define INIT_CMD_UNSETENV 7 #define INIT_CMD_CHANGECONS 12345 #ifdef MAXHOSTNAMELEN # define INITRQ_HLEN MAXHOSTNAMELEN #else # define INITRQ_HLEN 64 #endif /* * This is what BSD 4.4 uses when talking to init. * Linux doesn't use this right now. */ struct init_request_bsd { char gen_id[8]; /* Beats me.. telnetd uses "fe" */ char tty_id[16]; /* Tty name minus /dev/tty */ char host[INITRQ_HLEN]; /* Hostname */ char term_type[16]; /* Terminal type */ int signal; /* Signal to send */ int pid; /* Process to send to */ char exec_name[128]; /* Program to execute */ char reserved[128]; /* For future expansion. */ }; /* * Because of legacy interfaces, "runlevel" and "sleeptime" * aren't in a separate struct in the union. * * The weird sizes are because init expects the whole * struct to be 384 bytes. */ struct init_request { int magic; /* Magic number */ int cmd; /* What kind of request */ int runlevel; /* Runlevel to change to */ int sleeptime; /* Time between TERM and KILL */ union { struct init_request_bsd bsd; char data[368]; } i; }; #endif systemd-229/src/shared/install-printf.c000066400000000000000000000100251265713322000202260ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "formats-util.h" #include "install-printf.h" #include "install.h" #include "macro.h" #include "specifier.h" #include "unit-name.h" #include "user-util.h" static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) { UnitFileInstallInfo *i = userdata; assert(i); return unit_name_to_prefix_and_instance(i->name, ret); } static int specifier_prefix(char specifier, void *data, void *userdata, char **ret) { UnitFileInstallInfo *i = userdata; assert(i); return unit_name_to_prefix(i->name, ret); } static int specifier_instance(char specifier, void *data, void *userdata, char **ret) { UnitFileInstallInfo *i = userdata; char *instance; int r; assert(i); r = unit_name_to_instance(i->name, &instance); if (r < 0) return r; if (!instance) { instance = strdup(""); if (!instance) return -ENOMEM; } *ret = instance; return 0; } static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) { char *t; /* If we are UID 0 (root), this will not result in NSS, * otherwise it might. This is good, as we want to be able to * run this in PID 1, where our user ID is 0, but where NSS * lookups are not allowed. */ t = getusername_malloc(); if (!t) return -ENOMEM; *ret = t; return 0; } static int specifier_user_id(char specifier, void *data, void *userdata, char **ret) { if (asprintf(ret, UID_FMT, getuid()) < 0) return -ENOMEM; return 0; } int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret) { /* This is similar to unit_full_printf() but does not support * anything path-related. * * %n: the full id of the unit (foo@bar.waldo) * %N: the id of the unit without the suffix (foo@bar) * %p: the prefix (foo) * %i: the instance (bar) * %U the UID of the running user * %u the username of running user * %m the machine ID of the running system * %H the host name of the running system * %b the boot ID of the running system * %v `uname -r` of the running system */ const Specifier table[] = { { 'n', specifier_string, i->name }, { 'N', specifier_prefix_and_instance, NULL }, { 'p', specifier_prefix, NULL }, { 'i', specifier_instance, NULL }, { 'U', specifier_user_id, NULL }, { 'u', specifier_user_name, NULL }, { 'm', specifier_machine_id, NULL }, { 'H', specifier_host_name, NULL }, { 'b', specifier_boot_id, NULL }, { 'v', specifier_kernel_release, NULL }, {} }; assert(i); assert(format); assert(ret); return specifier_printf(format, table, i, ret); } systemd-229/src/shared/install-printf.h000066400000000000000000000015161265713322000202400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "install.h" int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret); systemd-229/src/shared/install.c000066400000000000000000002172041265713322000167360ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty . ***/ #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "conf-files.h" #include "conf-parser.h" #include "dirent-util.h" #include "extract-word.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "hashmap.h" #include "install-printf.h" #include "install.h" #include "log.h" #include "macro.h" #include "mkdir.h" #include "path-lookup.h" #include "path-util.h" #include "set.h" #include "special.h" #include "stat-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64 typedef enum SearchFlags { SEARCH_LOAD = 1, SEARCH_FOLLOW_CONFIG_SYMLINKS = 2, } SearchFlags; typedef struct { OrderedHashmap *will_process; OrderedHashmap *have_processed; } InstallContext; static int in_search_path(const char *path, char **search) { _cleanup_free_ char *parent = NULL; char **i; assert(path); parent = dirname_malloc(path); if (!parent) return -ENOMEM; STRV_FOREACH(i, search) if (path_equal(parent, *i)) return true; return false; } static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) { char *p = NULL; int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); assert(ret); /* This determines where we shall create or remove our * installation ("configuration") symlinks */ switch (scope) { case UNIT_FILE_SYSTEM: if (runtime) p = path_join(root_dir, "/run/systemd/system", NULL); else p = path_join(root_dir, SYSTEM_CONFIG_UNIT_PATH, NULL); break; case UNIT_FILE_GLOBAL: if (root_dir) return -EINVAL; if (runtime) p = strdup("/run/systemd/user"); else p = strdup(USER_CONFIG_UNIT_PATH); break; case UNIT_FILE_USER: if (root_dir) return -EINVAL; if (runtime) r = user_runtime_dir(&p); else r = user_config_home(&p); if (r < 0) return r; if (r == 0) return -ENOENT; break; default: assert_not_reached("Bad scope"); } if (!p) return -ENOMEM; *ret = p; return 0; } static bool is_config_path(UnitFileScope scope, const char *path) { int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); assert(path); /* Checks whether the specified path is intended for * configuration or is outside of it */ switch (scope) { case UNIT_FILE_SYSTEM: case UNIT_FILE_GLOBAL: return path_startswith(path, "/etc") || path_startswith(path, SYSTEM_CONFIG_UNIT_PATH) || path_startswith(path, "/run"); case UNIT_FILE_USER: { _cleanup_free_ char *p = NULL; r = user_config_home(&p); if (r < 0) return r; if (r > 0 && path_startswith(path, p)) return true; p = mfree(p); r = user_runtime_dir(&p); if (r < 0) return r; if (r > 0 && path_startswith(path, p)) return true; return false; } default: assert_not_reached("Bad scope"); } } static int verify_root_dir(UnitFileScope scope, const char **root_dir) { int r; assert(root_dir); /* Verifies that the specified root directory to operate on * makes sense. Reset it to NULL if it is the root directory * or set to empty */ if (isempty(*root_dir) || path_equal(*root_dir, "/")) { *root_dir = NULL; return 0; } if (scope != UNIT_FILE_SYSTEM) return -EINVAL; r = is_dir(*root_dir, true); if (r < 0) return r; if (r == 0) return -ENOTDIR; return 0; } int unit_file_changes_add( UnitFileChange **changes, unsigned *n_changes, UnitFileChangeType type, const char *path, const char *source) { UnitFileChange *c; unsigned i; assert(path); assert(!changes == !n_changes); if (!changes) return 0; c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange)); if (!c) return -ENOMEM; *changes = c; i = *n_changes; c[i].type = type; c[i].path = strdup(path); if (!c[i].path) return -ENOMEM; path_kill_slashes(c[i].path); if (source) { c[i].source = strdup(source); if (!c[i].source) { free(c[i].path); return -ENOMEM; } path_kill_slashes(c[i].path); } else c[i].source = NULL; *n_changes = i+1; return 0; } void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) { unsigned i; assert(changes || n_changes == 0); if (!changes) return; for (i = 0; i < n_changes; i++) { free(changes[i].path); free(changes[i].source); } free(changes); } static int create_symlink( const char *old_path, const char *new_path, bool force, UnitFileChange **changes, unsigned *n_changes) { _cleanup_free_ char *dest = NULL; int r; assert(old_path); assert(new_path); /* Actually create a symlink, and remember that we did. Is * smart enough to check if there's already a valid symlink in * place. */ mkdir_parents_label(new_path, 0755); if (symlink(old_path, new_path) >= 0) { unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); return 0; } if (errno != EEXIST) return -errno; r = readlink_malloc(new_path, &dest); if (r < 0) return r; if (path_equal(dest, old_path)) return 0; if (!force) return -EEXIST; r = symlink_atomic(old_path, new_path); if (r < 0) return r; unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL); unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); return 0; } static int mark_symlink_for_removal( Set **remove_symlinks_to, const char *p) { char *n; int r; assert(p); r = set_ensure_allocated(remove_symlinks_to, &string_hash_ops); if (r < 0) return r; n = strdup(p); if (!n) return -ENOMEM; path_kill_slashes(n); r = set_consume(*remove_symlinks_to, n); if (r == -EEXIST) return 0; if (r < 0) return r; return 1; } static int remove_marked_symlinks_fd( Set *remove_symlinks_to, int fd, const char *path, const char *config_path, bool *restart, UnitFileChange **changes, unsigned *n_changes) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0; assert(remove_symlinks_to); assert(fd >= 0); assert(path); assert(config_path); assert(restart); d = fdopendir(fd); if (!d) { safe_close(fd); return -errno; } rewinddir(d); FOREACH_DIRENT(de, d, return -errno) { dirent_ensure_type(d, de); if (de->d_type == DT_DIR) { _cleanup_free_ char *p = NULL; int nfd, q; nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); if (nfd < 0) { if (errno == ENOENT) continue; if (r == 0) r = -errno; continue; } p = path_make_absolute(de->d_name, path); if (!p) { safe_close(nfd); return -ENOMEM; } /* This will close nfd, regardless whether it succeeds or not */ q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, restart, changes, n_changes); if (q < 0 && r == 0) r = q; } else if (de->d_type == DT_LNK) { _cleanup_free_ char *p = NULL, *dest = NULL; bool found; int q; if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) continue; p = path_make_absolute(de->d_name, path); if (!p) return -ENOMEM; q = readlink_malloc(p, &dest); if (q < 0) { if (q == -ENOENT) continue; if (r == 0) r = q; continue; } /* We remove all links pointing to a file or * path that is marked, as well as all files * sharing the same name as a file that is * marked. */ found = set_contains(remove_symlinks_to, dest) || set_contains(remove_symlinks_to, basename(dest)) || set_contains(remove_symlinks_to, de->d_name); if (!found) continue; if (unlink(p) < 0 && errno != ENOENT) { if (r == 0) r = -errno; continue; } path_kill_slashes(p); (void) rmdir_parents(p, config_path); unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL); q = mark_symlink_for_removal(&remove_symlinks_to, p); if (q < 0) return q; if (q > 0) *restart = true; } } return r; } static int remove_marked_symlinks( Set *remove_symlinks_to, const char *config_path, UnitFileChange **changes, unsigned *n_changes) { _cleanup_close_ int fd = -1; bool restart; int r = 0; assert(config_path); if (set_size(remove_symlinks_to) <= 0) return 0; fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); if (fd < 0) return -errno; do { int q, cfd; restart = false; cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (cfd < 0) return -errno; /* This takes possession of cfd and closes it */ q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &restart, changes, n_changes); if (r == 0) r = q; } while (restart); return r; } static int find_symlinks_fd( const char *root_dir, const char *name, int fd, const char *path, const char *config_path, bool *same_name_link) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r = 0; assert(name); assert(fd >= 0); assert(path); assert(config_path); assert(same_name_link); d = fdopendir(fd); if (!d) { safe_close(fd); return -errno; } FOREACH_DIRENT(de, d, return -errno) { dirent_ensure_type(d, de); if (de->d_type == DT_DIR) { _cleanup_free_ char *p = NULL; int nfd, q; nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); if (nfd < 0) { if (errno == ENOENT) continue; if (r == 0) r = -errno; continue; } p = path_make_absolute(de->d_name, path); if (!p) { safe_close(nfd); return -ENOMEM; } /* This will close nfd, regardless whether it succeeds or not */ q = find_symlinks_fd(root_dir, name, nfd, p, config_path, same_name_link); if (q > 0) return 1; if (r == 0) r = q; } else if (de->d_type == DT_LNK) { _cleanup_free_ char *p = NULL, *dest = NULL; bool found_path, found_dest, b = false; int q; /* Acquire symlink name */ p = path_make_absolute(de->d_name, path); if (!p) return -ENOMEM; /* Acquire symlink destination */ q = readlink_malloc(p, &dest); if (q == -ENOENT) continue; if (q < 0) { if (r == 0) r = q; continue; } /* Make absolute */ if (!path_is_absolute(dest)) { char *x; x = prefix_root(root_dir, dest); if (!x) return -ENOMEM; free(dest); dest = x; } /* Check if the symlink itself matches what we * are looking for */ if (path_is_absolute(name)) found_path = path_equal(p, name); else found_path = streq(de->d_name, name); /* Check if what the symlink points to * matches what we are looking for */ if (path_is_absolute(name)) found_dest = path_equal(dest, name); else found_dest = streq(basename(dest), name); if (found_path && found_dest) { _cleanup_free_ char *t = NULL; /* Filter out same name links in the main * config path */ t = path_make_absolute(name, config_path); if (!t) return -ENOMEM; b = path_equal(t, p); } if (b) *same_name_link = true; else if (found_path || found_dest) return 1; } } return r; } static int find_symlinks( const char *root_dir, const char *name, const char *config_path, bool *same_name_link) { int fd; assert(name); assert(config_path); assert(same_name_link); fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); if (fd < 0) { if (errno == ENOENT) return 0; return -errno; } /* This takes possession of fd and closes it */ return find_symlinks_fd(root_dir, name, fd, config_path, config_path, same_name_link); } static int find_symlinks_in_scope( UnitFileScope scope, const char *root_dir, const char *name, UnitFileState *state) { _cleanup_free_ char *normal_path = NULL, *runtime_path = NULL; bool same_name_link_runtime = false, same_name_link = false; int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); assert(name); /* First look in the normal config path */ r = get_config_path(scope, false, root_dir, &normal_path); if (r < 0) return r; r = find_symlinks(root_dir, name, normal_path, &same_name_link); if (r < 0) return r; if (r > 0) { *state = UNIT_FILE_ENABLED; return r; } /* Then look in runtime config path */ r = get_config_path(scope, true, root_dir, &runtime_path); if (r < 0) return r; r = find_symlinks(root_dir, name, runtime_path, &same_name_link_runtime); if (r < 0) return r; if (r > 0) { *state = UNIT_FILE_ENABLED_RUNTIME; return r; } /* Hmm, we didn't find it, but maybe we found the same name * link? */ if (same_name_link) { *state = UNIT_FILE_LINKED; return 1; } if (same_name_link_runtime) { *state = UNIT_FILE_LINKED_RUNTIME; return 1; } return 0; } static void install_info_free(UnitFileInstallInfo *i) { if (!i) return; free(i->name); free(i->path); strv_free(i->aliases); strv_free(i->wanted_by); strv_free(i->required_by); strv_free(i->also); free(i->default_instance); free(i->symlink_target); free(i); } static OrderedHashmap* install_info_hashmap_free(OrderedHashmap *m) { UnitFileInstallInfo *i; if (!m) return NULL; while ((i = ordered_hashmap_steal_first(m))) install_info_free(i); return ordered_hashmap_free(m); } static void install_context_done(InstallContext *c) { assert(c); c->will_process = install_info_hashmap_free(c->will_process); c->have_processed = install_info_hashmap_free(c->have_processed); } static UnitFileInstallInfo *install_info_find(InstallContext *c, const char *name) { UnitFileInstallInfo *i; i = ordered_hashmap_get(c->have_processed, name); if (i) return i; return ordered_hashmap_get(c->will_process, name); } static int install_info_add( InstallContext *c, const char *name, const char *path, UnitFileInstallInfo **ret) { UnitFileInstallInfo *i = NULL; int r; assert(c); assert(name || path); if (!name) name = basename(path); if (!unit_name_is_valid(name, UNIT_NAME_ANY)) return -EINVAL; i = install_info_find(c, name); if (i) { if (ret) *ret = i; return 0; } r = ordered_hashmap_ensure_allocated(&c->will_process, &string_hash_ops); if (r < 0) return r; i = new0(UnitFileInstallInfo, 1); if (!i) return -ENOMEM; i->type = _UNIT_FILE_TYPE_INVALID; i->name = strdup(name); if (!i->name) { r = -ENOMEM; goto fail; } if (path) { i->path = strdup(path); if (!i->path) { r = -ENOMEM; goto fail; } } r = ordered_hashmap_put(c->will_process, i->name, i); if (r < 0) goto fail; if (ret) *ret = i; return 0; fail: install_info_free(i); return r; } static int install_info_add_auto( InstallContext *c, const char *name_or_path, UnitFileInstallInfo **ret) { assert(c); assert(name_or_path); if (path_is_absolute(name_or_path)) return install_info_add(c, NULL, name_or_path, ret); else return install_info_add(c, name_or_path, NULL, ret); } static int config_parse_also( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { UnitFileInstallInfo *i = userdata; InstallContext *c = data; int r; assert(filename); assert(lvalue); assert(rvalue); for (;;) { _cleanup_free_ char *word = NULL; r = extract_first_word(&rvalue, &word, NULL, 0); if (r < 0) return r; if (r == 0) break; r = install_info_add(c, word, NULL, NULL); if (r < 0) return r; r = strv_push(&i->also, word); if (r < 0) return r; word = NULL; } return 0; } static int config_parse_default_instance( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { UnitFileInstallInfo *i = data; char *printed; int r; assert(filename); assert(lvalue); assert(rvalue); r = install_full_printf(i, rvalue, &printed); if (r < 0) return r; if (!unit_instance_is_valid(printed)) { free(printed); return -EINVAL; } free(i->default_instance); i->default_instance = printed; return 0; } static int unit_file_load( InstallContext *c, UnitFileInstallInfo *info, const char *path, const char *root_dir, SearchFlags flags) { const ConfigTableItem items[] = { { "Install", "Alias", config_parse_strv, 0, &info->aliases }, { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by }, { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by }, { "Install", "DefaultInstance", config_parse_default_instance, 0, info }, { "Install", "Also", config_parse_also, 0, c }, {} }; _cleanup_fclose_ FILE *f = NULL; _cleanup_close_ int fd = -1; struct stat st; int r; assert(c); assert(info); assert(path); path = prefix_roota(root_dir, path); if (!(flags & SEARCH_LOAD)) { r = lstat(path, &st); if (r < 0) return -errno; if (null_or_empty(&st)) info->type = UNIT_FILE_TYPE_MASKED; else if (S_ISREG(st.st_mode)) info->type = UNIT_FILE_TYPE_REGULAR; else if (S_ISLNK(st.st_mode)) return -ELOOP; else if (S_ISDIR(st.st_mode)) return -EISDIR; else return -ENOTTY; return 0; } fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd < 0) return -errno; if (fstat(fd, &st) < 0) return -errno; if (null_or_empty(&st)) { info->type = UNIT_FILE_TYPE_MASKED; return 0; } if (S_ISDIR(st.st_mode)) return -EISDIR; if (!S_ISREG(st.st_mode)) return -ENOTTY; f = fdopen(fd, "re"); if (!f) return -errno; fd = -1; r = config_parse(NULL, path, f, NULL, config_item_table_lookup, items, true, true, false, info); if (r < 0) return r; info->type = UNIT_FILE_TYPE_REGULAR; return (int) strv_length(info->aliases) + (int) strv_length(info->wanted_by) + (int) strv_length(info->required_by); } static int unit_file_load_or_readlink( InstallContext *c, UnitFileInstallInfo *info, const char *path, const char *root_dir, SearchFlags flags) { _cleanup_free_ char *np = NULL; int r; r = unit_file_load(c, info, path, root_dir, flags); if (r != -ELOOP) return r; /* This is a symlink, let's read it. */ r = readlink_and_make_absolute_root(root_dir, path, &np); if (r < 0) return r; if (path_equal(np, "/dev/null")) info->type = UNIT_FILE_TYPE_MASKED; else { const char *bn; UnitType a, b; bn = basename(np); if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) { if (!unit_name_is_valid(bn, UNIT_NAME_PLAIN)) return -EINVAL; } else if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) { if (!unit_name_is_valid(bn, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) return -EINVAL; } else if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE)) { if (!unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) return -EINVAL; } else return -EINVAL; /* Enforce that the symlink destination does not * change the unit file type. */ a = unit_name_to_type(info->name); b = unit_name_to_type(bn); if (a < 0 || b < 0 || a != b) return -EINVAL; info->type = UNIT_FILE_TYPE_SYMLINK; info->symlink_target = np; np = NULL; } return 0; } static int unit_file_search( InstallContext *c, UnitFileInstallInfo *info, const LookupPaths *paths, const char *root_dir, SearchFlags flags) { char **p; int r; assert(c); assert(info); assert(paths); /* Was this unit already loaded? */ if (info->type != _UNIT_FILE_TYPE_INVALID) return 0; if (info->path) return unit_file_load_or_readlink(c, info, info->path, root_dir, flags); assert(info->name); STRV_FOREACH(p, paths->unit_path) { _cleanup_free_ char *path = NULL; path = strjoin(*p, "/", info->name, NULL); if (!path) return -ENOMEM; r = unit_file_load_or_readlink(c, info, path, root_dir, flags); if (r < 0) { if (r != -ENOENT) return r; } else { info->path = path; path = NULL; return r; } } if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) { /* Unit file doesn't exist, however instance * enablement was requested. We will check if it is * possible to load template unit file. */ _cleanup_free_ char *template = NULL; r = unit_name_template(info->name, &template); if (r < 0) return r; STRV_FOREACH(p, paths->unit_path) { _cleanup_free_ char *path = NULL; path = strjoin(*p, "/", template, NULL); if (!path) return -ENOMEM; r = unit_file_load_or_readlink(c, info, path, root_dir, flags); if (r < 0) { if (r != -ENOENT) return r; } else { info->path = path; path = NULL; return r; } } } return -ENOENT; } static int install_info_follow( InstallContext *c, UnitFileInstallInfo *i, const char *root_dir, SearchFlags flags) { assert(c); assert(i); if (i->type != UNIT_FILE_TYPE_SYMLINK) return -EINVAL; if (!i->symlink_target) return -EINVAL; /* If the basename doesn't match, the caller should add a * complete new entry for this. */ if (!streq(basename(i->symlink_target), i->name)) return -EXDEV; free(i->path); i->path = i->symlink_target; i->symlink_target = NULL; i->type = _UNIT_FILE_TYPE_INVALID; return unit_file_load_or_readlink(c, i, i->path, root_dir, flags); } static int install_info_traverse( UnitFileScope scope, InstallContext *c, const char *root_dir, const LookupPaths *paths, UnitFileInstallInfo *start, SearchFlags flags, UnitFileInstallInfo **ret) { UnitFileInstallInfo *i; unsigned k = 0; int r; assert(paths); assert(start); assert(c); r = unit_file_search(c, start, paths, root_dir, flags); if (r < 0) return r; i = start; while (i->type == UNIT_FILE_TYPE_SYMLINK) { /* Follow the symlink */ if (++k > UNIT_FILE_FOLLOW_SYMLINK_MAX) return -ELOOP; if (!(flags & SEARCH_FOLLOW_CONFIG_SYMLINKS) && is_config_path(scope, i->path)) return -ELOOP; r = install_info_follow(c, i, root_dir, flags); if (r < 0) { _cleanup_free_ char *buffer = NULL; const char *bn; if (r != -EXDEV) return r; /* Target has a different name, create a new * install info object for that, and continue * with that. */ bn = basename(i->symlink_target); if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE) && unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) { _cleanup_free_ char *instance = NULL; r = unit_name_to_instance(i->name, &instance); if (r < 0) return r; r = unit_name_replace_instance(bn, instance, &buffer); if (r < 0) return r; bn = buffer; } r = install_info_add(c, bn, NULL, &i); if (r < 0) return r; r = unit_file_search(c, i, paths, root_dir, flags); if (r < 0) return r; } /* Try again, with the new target we found. */ } if (ret) *ret = i; return 0; } static int install_info_discover( UnitFileScope scope, InstallContext *c, const char *root_dir, const LookupPaths *paths, const char *name, SearchFlags flags, UnitFileInstallInfo **ret) { UnitFileInstallInfo *i; int r; assert(c); assert(paths); assert(name); r = install_info_add_auto(c, name, &i); if (r < 0) return r; return install_info_traverse(scope, c, root_dir, paths, i, flags, ret); } static int install_info_symlink_alias( UnitFileInstallInfo *i, const char *config_path, bool force, UnitFileChange **changes, unsigned *n_changes) { char **s; int r = 0, q; assert(i); assert(config_path); STRV_FOREACH(s, i->aliases) { _cleanup_free_ char *alias_path = NULL, *dst = NULL; q = install_full_printf(i, *s, &dst); if (q < 0) return q; alias_path = path_make_absolute(dst, config_path); if (!alias_path) return -ENOMEM; q = create_symlink(i->path, alias_path, force, changes, n_changes); if (r == 0) r = q; } return r; } static int install_info_symlink_wants( UnitFileInstallInfo *i, const char *config_path, char **list, const char *suffix, bool force, UnitFileChange **changes, unsigned *n_changes) { _cleanup_free_ char *buf = NULL; const char *n; char **s; int r = 0, q; assert(i); assert(config_path); if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE)) { /* Don't install any symlink if there's no default * instance configured */ if (!i->default_instance) return 0; r = unit_name_replace_instance(i->name, i->default_instance, &buf); if (r < 0) return r; n = buf; } else n = i->name; STRV_FOREACH(s, list) { _cleanup_free_ char *path = NULL, *dst = NULL; q = install_full_printf(i, *s, &dst); if (q < 0) return q; if (!unit_name_is_valid(dst, UNIT_NAME_ANY)) { r = -EINVAL; continue; } path = strjoin(config_path, "/", dst, suffix, n, NULL); if (!path) return -ENOMEM; q = create_symlink(i->path, path, force, changes, n_changes); if (r == 0) r = q; } return r; } static int install_info_symlink_link( UnitFileInstallInfo *i, const LookupPaths *paths, const char *config_path, const char *root_dir, bool force, UnitFileChange **changes, unsigned *n_changes) { _cleanup_free_ char *path = NULL; int r; assert(i); assert(paths); assert(config_path); assert(i->path); r = in_search_path(i->path, paths->unit_path); if (r != 0) return r; path = strjoin(config_path, "/", i->name, NULL); if (!path) return -ENOMEM; return create_symlink(i->path, path, force, changes, n_changes); } static int install_info_apply( UnitFileInstallInfo *i, const LookupPaths *paths, const char *config_path, const char *root_dir, bool force, UnitFileChange **changes, unsigned *n_changes) { int r, q; assert(i); assert(paths); assert(config_path); if (i->type != UNIT_FILE_TYPE_REGULAR) return 0; r = install_info_symlink_alias(i, config_path, force, changes, n_changes); q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes); if (r == 0) r = q; q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes); if (r == 0) r = q; q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes); if (r == 0) r = q; return r; } static int install_context_apply( UnitFileScope scope, InstallContext *c, const LookupPaths *paths, const char *config_path, const char *root_dir, bool force, SearchFlags flags, UnitFileChange **changes, unsigned *n_changes) { UnitFileInstallInfo *i; int r; assert(c); assert(paths); assert(config_path); if (ordered_hashmap_isempty(c->will_process)) return 0; r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops); if (r < 0) return r; r = 0; while ((i = ordered_hashmap_first(c->will_process))) { int q; q = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name); if (q < 0) return q; r = install_info_traverse(scope, c, root_dir, paths, i, flags, NULL); if (r < 0) return r; if (i->type != UNIT_FILE_TYPE_REGULAR) continue; q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes); if (r >= 0) { if (q < 0) r = q; else r+= q; } } return r; } static int install_context_mark_for_removal( UnitFileScope scope, InstallContext *c, const LookupPaths *paths, Set **remove_symlinks_to, const char *config_path, const char *root_dir) { UnitFileInstallInfo *i; int r; assert(c); assert(paths); assert(config_path); /* Marks all items for removal */ if (ordered_hashmap_isempty(c->will_process)) return 0; r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops); if (r < 0) return r; while ((i = ordered_hashmap_first(c->will_process))) { r = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name); if (r < 0) return r; r = install_info_traverse(scope, c, root_dir, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL); if (r < 0) return r; if (i->type != UNIT_FILE_TYPE_REGULAR) continue; r = mark_symlink_for_removal(remove_symlinks_to, i->name); if (r < 0) return r; } return 0; } int unit_file_mask( UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes) { _cleanup_free_ char *prefix = NULL; char **i; int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); r = verify_root_dir(scope, &root_dir); if (r < 0) return r; r = get_config_path(scope, runtime, root_dir, &prefix); if (r < 0) return r; STRV_FOREACH(i, files) { _cleanup_free_ char *path = NULL; int q; if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) { if (r == 0) r = -EINVAL; continue; } path = path_make_absolute(*i, prefix); if (!path) return -ENOMEM; q = create_symlink("/dev/null", path, force, changes, n_changes); if (q < 0 && r >= 0) r = q; } return r; } int unit_file_unmask( UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes) { _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; _cleanup_free_ char *config_path = NULL; _cleanup_free_ char **todo = NULL; size_t n_todo = 0, n_allocated = 0; char **i; int r, q; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); r = verify_root_dir(scope, &root_dir); if (r < 0) return r; r = get_config_path(scope, runtime, root_dir, &config_path); if (r < 0) return r; STRV_FOREACH(i, files) { _cleanup_free_ char *path = NULL; if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) return -EINVAL; path = path_make_absolute(*i, config_path); if (!path) return -ENOMEM; r = null_or_empty_path(path); if (r == -ENOENT) continue; if (r < 0) return r; if (r == 0) continue; if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2)) return -ENOMEM; todo[n_todo++] = *i; } strv_uniq(todo); r = 0; STRV_FOREACH(i, todo) { _cleanup_free_ char *path = NULL; path = path_make_absolute(*i, config_path); if (!path) return -ENOMEM; if (unlink(path) < 0) { if (errno != -ENOENT && r >= 0) r = -errno; } else { q = mark_symlink_for_removal(&remove_symlinks_to, path); if (q < 0) return q; unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); } } q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes); if (r >= 0) r = q; return r; } int unit_file_link( UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes) { _cleanup_lookup_paths_free_ LookupPaths paths = {}; _cleanup_free_ char *config_path = NULL; _cleanup_free_ char **todo = NULL; size_t n_todo = 0, n_allocated = 0; char **i; int r, q; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); r = verify_root_dir(scope, &root_dir); if (r < 0) return r; r = lookup_paths_init_from_scope(&paths, scope, root_dir); if (r < 0) return r; r = get_config_path(scope, runtime, root_dir, &config_path); if (r < 0) return r; STRV_FOREACH(i, files) { _cleanup_free_ char *full = NULL; struct stat st; char *fn; if (!path_is_absolute(*i)) return -EINVAL; fn = basename(*i); if (!unit_name_is_valid(fn, UNIT_NAME_ANY)) return -EINVAL; full = prefix_root(root_dir, *i); if (!full) return -ENOMEM; if (lstat(full, &st) < 0) return -errno; if (S_ISLNK(st.st_mode)) return -ELOOP; if (S_ISDIR(st.st_mode)) return -EISDIR; if (!S_ISREG(st.st_mode)) return -ENOTTY; q = in_search_path(*i, paths.unit_path); if (q < 0) return q; if (q > 0) continue; if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2)) return -ENOMEM; todo[n_todo++] = *i; } strv_uniq(todo); r = 0; STRV_FOREACH(i, todo) { _cleanup_free_ char *path = NULL; path = path_make_absolute(basename(*i), config_path); if (!path) return -ENOMEM; q = create_symlink(*i, path, force, changes, n_changes); if (q < 0 && r >= 0) r = q; } return r; } int unit_file_add_dependency( UnitFileScope scope, bool runtime, const char *root_dir, char **files, const char *target, UnitDependency dep, bool force, UnitFileChange **changes, unsigned *n_changes) { _cleanup_lookup_paths_free_ LookupPaths paths = {}; _cleanup_(install_context_done) InstallContext c = {}; _cleanup_free_ char *config_path = NULL; UnitFileInstallInfo *i, *target_info; char **f; int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); assert(target); if (!IN_SET(dep, UNIT_WANTS, UNIT_REQUIRES)) return -EINVAL; if (!unit_name_is_valid(target, UNIT_NAME_ANY)) return -EINVAL; r = verify_root_dir(scope, &root_dir); if (r < 0) return r; r = lookup_paths_init_from_scope(&paths, scope, root_dir); if (r < 0) return r; r = get_config_path(scope, runtime, root_dir, &config_path); if (r < 0) return r; r = install_info_discover(scope, &c, root_dir, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS, &target_info); if (r < 0) return r; if (target_info->type == UNIT_FILE_TYPE_MASKED) return -ESHUTDOWN; assert(target_info->type == UNIT_FILE_TYPE_REGULAR); STRV_FOREACH(f, files) { char ***l; r = install_info_discover(scope, &c, root_dir, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); if (r < 0) return r; if (i->type == UNIT_FILE_TYPE_MASKED) return -ESHUTDOWN; assert(i->type == UNIT_FILE_TYPE_REGULAR); /* We didn't actually load anything from the unit * file, but instead just add in our new symlink to * create. */ if (dep == UNIT_WANTS) l = &i->wanted_by; else l = &i->required_by; strv_free(*l); *l = strv_new(target_info->name, NULL); if (!*l) return -ENOMEM; } return install_context_apply(scope, &c, &paths, config_path, root_dir, force, SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes); } int unit_file_enable( UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes) { _cleanup_lookup_paths_free_ LookupPaths paths = {}; _cleanup_(install_context_done) InstallContext c = {}; _cleanup_free_ char *config_path = NULL; UnitFileInstallInfo *i; char **f; int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); r = verify_root_dir(scope, &root_dir); if (r < 0) return r; r = lookup_paths_init_from_scope(&paths, scope, root_dir); if (r < 0) return r; r = get_config_path(scope, runtime, root_dir, &config_path); if (r < 0) return r; STRV_FOREACH(f, files) { r = install_info_discover(scope, &c, root_dir, &paths, *f, SEARCH_LOAD, &i); if (r < 0) return r; if (i->type == UNIT_FILE_TYPE_MASKED) return -ESHUTDOWN; assert(i->type == UNIT_FILE_TYPE_REGULAR); } /* This will return the number of symlink rules that were supposed to be created, not the ones actually created. This is useful to determine whether the passed files had any installation data at all. */ return install_context_apply(scope, &c, &paths, config_path, root_dir, force, SEARCH_LOAD, changes, n_changes); } int unit_file_disable( UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes) { _cleanup_lookup_paths_free_ LookupPaths paths = {}; _cleanup_(install_context_done) InstallContext c = {}; _cleanup_free_ char *config_path = NULL; _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; char **i; int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); r = verify_root_dir(scope, &root_dir); if (r < 0) return r; r = lookup_paths_init_from_scope(&paths, scope, root_dir); if (r < 0) return r; r = get_config_path(scope, runtime, root_dir, &config_path); if (r < 0) return r; STRV_FOREACH(i, files) { if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) return -EINVAL; r = install_info_add(&c, *i, NULL, NULL); if (r < 0) return r; } r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, config_path, root_dir); if (r < 0) return r; return remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes); } int unit_file_reenable( UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes) { char **n; int r; size_t l, i; /* First, we invoke the disable command with only the basename... */ l = strv_length(files); n = newa(char*, l+1); for (i = 0; i < l; i++) n[i] = basename(files[i]); n[i] = NULL; r = unit_file_disable(scope, runtime, root_dir, n, changes, n_changes); if (r < 0) return r; /* But the enable command with the full name */ return unit_file_enable(scope, runtime, root_dir, files, force, changes, n_changes); } int unit_file_set_default( UnitFileScope scope, const char *root_dir, const char *name, bool force, UnitFileChange **changes, unsigned *n_changes) { _cleanup_lookup_paths_free_ LookupPaths paths = {}; _cleanup_(install_context_done) InstallContext c = {}; _cleanup_free_ char *config_path = NULL; UnitFileInstallInfo *i; const char *path; int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); assert(name); if (unit_name_to_type(name) != UNIT_TARGET) return -EINVAL; if (streq(name, SPECIAL_DEFAULT_TARGET)) return -EINVAL; r = verify_root_dir(scope, &root_dir); if (r < 0) return r; r = lookup_paths_init_from_scope(&paths, scope, root_dir); if (r < 0) return r; r = get_config_path(scope, false, root_dir, &config_path); if (r < 0) return r; r = install_info_discover(scope, &c, root_dir, &paths, name, 0, &i); if (r < 0) return r; if (i->type == UNIT_FILE_TYPE_MASKED) return -ESHUTDOWN; path = strjoina(config_path, "/" SPECIAL_DEFAULT_TARGET); return create_symlink(i->path, path, force, changes, n_changes); } int unit_file_get_default( UnitFileScope scope, const char *root_dir, char **name) { _cleanup_lookup_paths_free_ LookupPaths paths = {}; _cleanup_(install_context_done) InstallContext c = {}; UnitFileInstallInfo *i; char *n; int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); assert(name); r = verify_root_dir(scope, &root_dir); if (r < 0) return r; r = lookup_paths_init_from_scope(&paths, scope, root_dir); if (r < 0) return r; r = install_info_discover(scope, &c, root_dir, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); if (r < 0) return r; if (i->type == UNIT_FILE_TYPE_MASKED) return -ESHUTDOWN; n = strdup(i->name); if (!n) return -ENOMEM; *name = n; return 0; } int unit_file_lookup_state( UnitFileScope scope, const char *root_dir, const LookupPaths *paths, const char *name, UnitFileState *ret) { _cleanup_(install_context_done) InstallContext c = {}; UnitFileInstallInfo *i; UnitFileState state; int r; assert(paths); assert(name); if (!unit_name_is_valid(name, UNIT_NAME_ANY)) return -EINVAL; r = verify_root_dir(scope, &root_dir); if (r < 0) return r; r = install_info_discover(scope, &c, root_dir, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); if (r < 0) return r; /* Shortcut things, if the caller just wants to know if this unit exists. */ if (!ret) return 0; switch (i->type) { case UNIT_FILE_TYPE_MASKED: state = path_startswith(i->path, "/run") ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED; break; case UNIT_FILE_TYPE_REGULAR: r = find_symlinks_in_scope(scope, root_dir, i->name, &state); if (r < 0) return r; if (r == 0) { if (UNIT_FILE_INSTALL_INFO_HAS_RULES(i)) state = UNIT_FILE_DISABLED; else if (UNIT_FILE_INSTALL_INFO_HAS_ALSO(i)) state = UNIT_FILE_INDIRECT; else state = UNIT_FILE_STATIC; } break; default: assert_not_reached("Unexpect unit file type."); } *ret = state; return 0; } int unit_file_get_state( UnitFileScope scope, const char *root_dir, const char *name, UnitFileState *ret) { _cleanup_lookup_paths_free_ LookupPaths paths = {}; int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); assert(name); r = verify_root_dir(scope, &root_dir); if (r < 0) return r; r = lookup_paths_init_from_scope(&paths, scope, root_dir); if (r < 0) return r; return unit_file_lookup_state(scope, root_dir, &paths, name, ret); } int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) { _cleanup_strv_free_ char **files = NULL; char **p; int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); assert(name); r = verify_root_dir(scope, &root_dir); if (r < 0) return r; if (!unit_name_is_valid(name, UNIT_NAME_ANY)) return -EINVAL; if (scope == UNIT_FILE_SYSTEM) r = conf_files_list(&files, ".preset", root_dir, "/etc/systemd/system-preset", "/usr/local/lib/systemd/system-preset", "/usr/lib/systemd/system-preset", #ifdef HAVE_SPLIT_USR "/lib/systemd/system-preset", #endif NULL); else if (scope == UNIT_FILE_GLOBAL) r = conf_files_list(&files, ".preset", root_dir, "/etc/systemd/user-preset", "/usr/local/lib/systemd/user-preset", "/usr/lib/systemd/user-preset", NULL); else return 1; /* Default is "enable" */ if (r < 0) return r; STRV_FOREACH(p, files) { _cleanup_fclose_ FILE *f; char line[LINE_MAX]; f = fopen(*p, "re"); if (!f) { if (errno == ENOENT) continue; return -errno; } FOREACH_LINE(line, f, return -errno) { const char *parameter; char *l; l = strstrip(line); if (isempty(l)) continue; if (strchr(COMMENTS, *l)) continue; parameter = first_word(l, "enable"); if (parameter) { if (fnmatch(parameter, name, FNM_NOESCAPE) == 0) { log_debug("Preset file says enable %s.", name); return 1; } continue; } parameter = first_word(l, "disable"); if (parameter) { if (fnmatch(parameter, name, FNM_NOESCAPE) == 0) { log_debug("Preset file says disable %s.", name); return 0; } continue; } log_debug("Couldn't parse line '%s'", l); } } /* Default is "enable" */ log_debug("Preset file doesn't say anything about %s, enabling.", name); return 1; } static int execute_preset( UnitFileScope scope, InstallContext *plus, InstallContext *minus, const LookupPaths *paths, const char *config_path, const char *root_dir, char **files, UnitFilePresetMode mode, bool force, UnitFileChange **changes, unsigned *n_changes) { int r; assert(plus); assert(minus); assert(paths); assert(config_path); if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) { _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path, root_dir); if (r < 0) return r; r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes); } else r = 0; if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) { int q; /* Returns number of symlinks that where supposed to be installed. */ q = install_context_apply(scope, plus, paths, config_path, root_dir, force, SEARCH_LOAD, changes, n_changes); if (r >= 0) { if (q < 0) r = q; else r+= q; } } return r; } static int preset_prepare_one( UnitFileScope scope, InstallContext *plus, InstallContext *minus, LookupPaths *paths, const char *root_dir, UnitFilePresetMode mode, const char *name) { UnitFileInstallInfo *i; int r; if (install_info_find(plus, name) || install_info_find(minus, name)) return 0; r = unit_file_query_preset(scope, root_dir, name); if (r < 0) return r; if (r > 0) { r = install_info_discover(scope, plus, root_dir, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); if (r < 0) return r; if (i->type == UNIT_FILE_TYPE_MASKED) return -ESHUTDOWN; } else r = install_info_discover(scope, minus, root_dir, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); return r; } int unit_file_preset( UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFilePresetMode mode, bool force, UnitFileChange **changes, unsigned *n_changes) { _cleanup_(install_context_done) InstallContext plus = {}, minus = {}; _cleanup_lookup_paths_free_ LookupPaths paths = {}; _cleanup_free_ char *config_path = NULL; char **i; int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); assert(mode < _UNIT_FILE_PRESET_MAX); r = verify_root_dir(scope, &root_dir); if (r < 0) return r; r = lookup_paths_init_from_scope(&paths, scope, root_dir); if (r < 0) return r; r = get_config_path(scope, runtime, root_dir, &config_path); if (r < 0) return r; STRV_FOREACH(i, files) { if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) return -EINVAL; r = preset_prepare_one(scope, &plus, &minus, &paths, root_dir, mode, *i); if (r < 0) return r; } return execute_preset(scope, &plus, &minus, &paths, config_path, root_dir, files, mode, force, changes, n_changes); } int unit_file_preset_all( UnitFileScope scope, bool runtime, const char *root_dir, UnitFilePresetMode mode, bool force, UnitFileChange **changes, unsigned *n_changes) { _cleanup_(install_context_done) InstallContext plus = {}, minus = {}; _cleanup_lookup_paths_free_ LookupPaths paths = {}; _cleanup_free_ char *config_path = NULL; char **i; int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); assert(mode < _UNIT_FILE_PRESET_MAX); r = verify_root_dir(scope, &root_dir); if (r < 0) return r; r = lookup_paths_init_from_scope(&paths, scope, root_dir); if (r < 0) return r; r = get_config_path(scope, runtime, root_dir, &config_path); if (r < 0) return r; STRV_FOREACH(i, paths.unit_path) { _cleanup_closedir_ DIR *d = NULL; _cleanup_free_ char *units_dir; struct dirent *de; units_dir = path_join(root_dir, *i, NULL); if (!units_dir) return -ENOMEM; d = opendir(units_dir); if (!d) { if (errno == ENOENT) continue; return -errno; } FOREACH_DIRENT(de, d, return -errno) { if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) continue; dirent_ensure_type(d, de); if (!IN_SET(de->d_type, DT_LNK, DT_REG)) continue; r = preset_prepare_one(scope, &plus, &minus, &paths, root_dir, mode, de->d_name); if (r < 0) return r; } } return execute_preset(scope, &plus, &minus, &paths, config_path, root_dir, NULL, mode, force, changes, n_changes); } static void unit_file_list_free_one(UnitFileList *f) { if (!f) return; free(f->path); free(f); } Hashmap* unit_file_list_free(Hashmap *h) { UnitFileList *i; while ((i = hashmap_steal_first(h))) unit_file_list_free_one(i); return hashmap_free(h); } DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one); int unit_file_get_list( UnitFileScope scope, const char *root_dir, Hashmap *h) { _cleanup_lookup_paths_free_ LookupPaths paths = {}; char **i; int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); assert(h); r = verify_root_dir(scope, &root_dir); if (r < 0) return r; r = lookup_paths_init_from_scope(&paths, scope, root_dir); if (r < 0) return r; STRV_FOREACH(i, paths.unit_path) { _cleanup_closedir_ DIR *d = NULL; _cleanup_free_ char *units_dir; struct dirent *de; units_dir = path_join(root_dir, *i, NULL); if (!units_dir) return -ENOMEM; d = opendir(units_dir); if (!d) { if (errno == ENOENT) continue; return -errno; } FOREACH_DIRENT(de, d, return -errno) { _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL; if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) continue; if (hashmap_get(h, de->d_name)) continue; dirent_ensure_type(d, de); if (!IN_SET(de->d_type, DT_LNK, DT_REG)) continue; f = new0(UnitFileList, 1); if (!f) return -ENOMEM; f->path = path_make_absolute(de->d_name, units_dir); if (!f->path) return -ENOMEM; r = unit_file_lookup_state(scope, root_dir, &paths, basename(f->path), &f->state); if (r < 0) f->state = UNIT_FILE_BAD; r = hashmap_put(h, basename(f->path), f); if (r < 0) return r; f = NULL; /* prevent cleanup */ } } return 0; } static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = { [UNIT_FILE_ENABLED] = "enabled", [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime", [UNIT_FILE_LINKED] = "linked", [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime", [UNIT_FILE_MASKED] = "masked", [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime", [UNIT_FILE_STATIC] = "static", [UNIT_FILE_DISABLED] = "disabled", [UNIT_FILE_INDIRECT] = "indirect", [UNIT_FILE_BAD] = "bad", }; DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState); static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = { [UNIT_FILE_SYMLINK] = "symlink", [UNIT_FILE_UNLINK] = "unlink", }; DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType); static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = { [UNIT_FILE_PRESET_FULL] = "full", [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only", [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only", }; DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode); systemd-229/src/shared/install.h000066400000000000000000000134441265713322000167430ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef enum UnitFileScope UnitFileScope; typedef enum UnitFileState UnitFileState; typedef enum UnitFilePresetMode UnitFilePresetMode; typedef enum UnitFileChangeType UnitFileChangeType; typedef enum UnitFileType UnitFileType; typedef struct UnitFileChange UnitFileChange; typedef struct UnitFileList UnitFileList; typedef struct UnitFileInstallInfo UnitFileInstallInfo; #include #include "hashmap.h" #include "macro.h" #include "path-lookup.h" #include "strv.h" #include "unit-name.h" enum UnitFileScope { UNIT_FILE_SYSTEM, UNIT_FILE_GLOBAL, UNIT_FILE_USER, _UNIT_FILE_SCOPE_MAX, _UNIT_FILE_SCOPE_INVALID = -1 }; enum UnitFileState { UNIT_FILE_ENABLED, UNIT_FILE_ENABLED_RUNTIME, UNIT_FILE_LINKED, UNIT_FILE_LINKED_RUNTIME, UNIT_FILE_MASKED, UNIT_FILE_MASKED_RUNTIME, UNIT_FILE_STATIC, UNIT_FILE_DISABLED, UNIT_FILE_INDIRECT, UNIT_FILE_BAD, _UNIT_FILE_STATE_MAX, _UNIT_FILE_STATE_INVALID = -1 }; enum UnitFilePresetMode { UNIT_FILE_PRESET_FULL, UNIT_FILE_PRESET_ENABLE_ONLY, UNIT_FILE_PRESET_DISABLE_ONLY, _UNIT_FILE_PRESET_MAX, _UNIT_FILE_PRESET_INVALID = -1 }; enum UnitFileChangeType { UNIT_FILE_SYMLINK, UNIT_FILE_UNLINK, _UNIT_FILE_CHANGE_TYPE_MAX, _UNIT_FILE_CHANGE_TYPE_INVALID = -1 }; struct UnitFileChange { UnitFileChangeType type; char *path; char *source; }; struct UnitFileList { char *path; UnitFileState state; }; enum UnitFileType { UNIT_FILE_TYPE_REGULAR, UNIT_FILE_TYPE_SYMLINK, UNIT_FILE_TYPE_MASKED, _UNIT_FILE_TYPE_MAX, _UNIT_FILE_TYPE_INVALID = -1, }; struct UnitFileInstallInfo { char *name; char *path; char **aliases; char **wanted_by; char **required_by; char **also; char *default_instance; UnitFileType type; char *symlink_target; }; static inline bool UNIT_FILE_INSTALL_INFO_HAS_RULES(UnitFileInstallInfo *i) { assert(i); return !strv_isempty(i->aliases) || !strv_isempty(i->wanted_by) || !strv_isempty(i->required_by); } static inline bool UNIT_FILE_INSTALL_INFO_HAS_ALSO(UnitFileInstallInfo *i) { assert(i); return !strv_isempty(i->also); } int unit_file_enable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_disable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes); int unit_file_reenable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_link(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_preset(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFilePresetMode mode, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_preset_all(UnitFileScope scope, bool runtime, const char *root_dir, UnitFilePresetMode mode, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes); int unit_file_set_default(UnitFileScope scope, const char *root_dir, const char *file, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_get_default(UnitFileScope scope, const char *root_dir, char **name); int unit_file_add_dependency(UnitFileScope scope, bool runtime, const char *root_dir, char **files, const char *target, UnitDependency dep, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_lookup_state(UnitFileScope scope, const char *root_dir,const LookupPaths *paths, const char *name, UnitFileState *ret); int unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename, UnitFileState *ret); int unit_file_get_list(UnitFileScope scope, const char *root_dir, Hashmap *h); Hashmap* unit_file_list_free(Hashmap *h); int unit_file_changes_add(UnitFileChange **changes, unsigned *n_changes, UnitFileChangeType type, const char *path, const char *source); void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes); int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name); const char *unit_file_state_to_string(UnitFileState s) _const_; UnitFileState unit_file_state_from_string(const char *s) _pure_; const char *unit_file_change_type_to_string(UnitFileChangeType s) _const_; UnitFileChangeType unit_file_change_type_from_string(const char *s) _pure_; const char *unit_file_preset_mode_to_string(UnitFilePresetMode m) _const_; UnitFilePresetMode unit_file_preset_mode_from_string(const char *s) _pure_; systemd-229/src/shared/linux/000077500000000000000000000000001265713322000162555ustar00rootroot00000000000000systemd-229/src/shared/linux/auto_dev-ioctl.h000066400000000000000000000121021265713322000213400ustar00rootroot00000000000000/* * Copyright 2008 Red Hat, Inc. All rights reserved. * Copyright 2008 Ian Kent * * This file is part of the Linux kernel and is made available under * the terms of the GNU General Public License, version 2, or at your * option, any later version, incorporated herein by reference. */ #ifndef _LINUX_AUTO_DEV_IOCTL_H #define _LINUX_AUTO_DEV_IOCTL_H #include #ifdef __KERNEL__ #include #else #include #endif /* __KERNEL__ */ #define AUTOFS_DEVICE_NAME "autofs" #define AUTOFS_DEV_IOCTL_VERSION_MAJOR 1 #define AUTOFS_DEV_IOCTL_VERSION_MINOR 0 #define AUTOFS_DEVID_LEN 16 #define AUTOFS_DEV_IOCTL_SIZE sizeof(struct autofs_dev_ioctl) /* * An ioctl interface for autofs mount point control. */ struct args_protover { __u32 version; }; struct args_protosubver { __u32 sub_version; }; struct args_openmount { __u32 devid; }; struct args_ready { __u32 token; }; struct args_fail { __u32 token; __s32 status; }; struct args_setpipefd { __s32 pipefd; }; struct args_timeout { __u64 timeout; }; struct args_requester { __u32 uid; __u32 gid; }; struct args_expire { __u32 how; }; struct args_askumount { __u32 may_umount; }; struct args_ismountpoint { union { struct args_in { __u32 type; } in; struct args_out { __u32 devid; __u32 magic; } out; }; }; /* * All the ioctls use this structure. * When sending a path size must account for the total length * of the chunk of memory otherwise is is the size of the * structure. */ struct autofs_dev_ioctl { __u32 ver_major; __u32 ver_minor; __u32 size; /* total size of data passed in * including this struct */ __s32 ioctlfd; /* automount command fd */ /* Command parameters */ union { struct args_protover protover; struct args_protosubver protosubver; struct args_openmount openmount; struct args_ready ready; struct args_fail fail; struct args_setpipefd setpipefd; struct args_timeout timeout; struct args_requester requester; struct args_expire expire; struct args_askumount askumount; struct args_ismountpoint ismountpoint; }; char path[0]; }; static inline void init_autofs_dev_ioctl(struct autofs_dev_ioctl *in) { memset(in, 0, sizeof(struct autofs_dev_ioctl)); in->ver_major = AUTOFS_DEV_IOCTL_VERSION_MAJOR; in->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR; in->size = sizeof(struct autofs_dev_ioctl); in->ioctlfd = -1; return; } /* * If you change this make sure you make the corresponding change * to autofs-dev-ioctl.c:lookup_ioctl() */ enum { /* Get various version info */ AUTOFS_DEV_IOCTL_VERSION_CMD = 0x71, AUTOFS_DEV_IOCTL_PROTOVER_CMD, AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD, /* Open mount ioctl fd */ AUTOFS_DEV_IOCTL_OPENMOUNT_CMD, /* Close mount ioctl fd */ AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD, /* Mount/expire status returns */ AUTOFS_DEV_IOCTL_READY_CMD, AUTOFS_DEV_IOCTL_FAIL_CMD, /* Activate/deactivate autofs mount */ AUTOFS_DEV_IOCTL_SETPIPEFD_CMD, AUTOFS_DEV_IOCTL_CATATONIC_CMD, /* Expiry timeout */ AUTOFS_DEV_IOCTL_TIMEOUT_CMD, /* Get mount last requesting uid and gid */ AUTOFS_DEV_IOCTL_REQUESTER_CMD, /* Check for eligible expire candidates */ AUTOFS_DEV_IOCTL_EXPIRE_CMD, /* Request busy status */ AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD, /* Check if path is a mountpoint */ AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD, }; #define AUTOFS_IOCTL 0x93 #define AUTOFS_DEV_IOCTL_VERSION \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_VERSION_CMD, struct autofs_dev_ioctl) #define AUTOFS_DEV_IOCTL_PROTOVER \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_PROTOVER_CMD, struct autofs_dev_ioctl) #define AUTOFS_DEV_IOCTL_PROTOSUBVER \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD, struct autofs_dev_ioctl) #define AUTOFS_DEV_IOCTL_OPENMOUNT \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_OPENMOUNT_CMD, struct autofs_dev_ioctl) #define AUTOFS_DEV_IOCTL_CLOSEMOUNT \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD, struct autofs_dev_ioctl) #define AUTOFS_DEV_IOCTL_READY \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_READY_CMD, struct autofs_dev_ioctl) #define AUTOFS_DEV_IOCTL_FAIL \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_FAIL_CMD, struct autofs_dev_ioctl) #define AUTOFS_DEV_IOCTL_SETPIPEFD \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_SETPIPEFD_CMD, struct autofs_dev_ioctl) #define AUTOFS_DEV_IOCTL_CATATONIC \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_CATATONIC_CMD, struct autofs_dev_ioctl) #define AUTOFS_DEV_IOCTL_TIMEOUT \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_TIMEOUT_CMD, struct autofs_dev_ioctl) #define AUTOFS_DEV_IOCTL_REQUESTER \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_REQUESTER_CMD, struct autofs_dev_ioctl) #define AUTOFS_DEV_IOCTL_EXPIRE \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_EXPIRE_CMD, struct autofs_dev_ioctl) #define AUTOFS_DEV_IOCTL_ASKUMOUNT \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD, struct autofs_dev_ioctl) #define AUTOFS_DEV_IOCTL_ISMOUNTPOINT \ _IOWR(AUTOFS_IOCTL, \ AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD, struct autofs_dev_ioctl) #endif /* _LINUX_AUTO_DEV_IOCTL_H */ systemd-229/src/shared/logs-show.c000066400000000000000000001240531265713322000172110ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include "sd-id128.h" #include "sd-journal.h" #include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "hashmap.h" #include "hostname-util.h" #include "io-util.h" #include "journal-internal.h" #include "log.h" #include "logs-show.h" #include "macro.h" #include "output-mode.h" #include "parse-util.h" #include "process-util.h" #include "sparse-endian.h" #include "string-table.h" #include "string-util.h" #include "terminal-util.h" #include "time-util.h" #include "utf8.h" #include "util.h" /* up to three lines (each up to 100 characters) or 300 characters, whichever is less */ #define PRINT_LINE_THRESHOLD 3 #define PRINT_CHAR_THRESHOLD 300 #define JSON_THRESHOLD 4096 static int print_catalog(FILE *f, sd_journal *j) { int r; _cleanup_free_ char *t = NULL, *z = NULL; r = sd_journal_get_catalog(j, &t); if (r < 0) return r; z = strreplace(strstrip(t), "\n", "\n-- "); if (!z) return log_oom(); fputs("-- ", f); fputs(z, f); fputc('\n', f); return 0; } static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) { size_t fl, nl; char *buf; assert(data); assert(field); assert(target); fl = strlen(field); if (length < fl) return 0; if (memcmp(data, field, fl)) return 0; nl = length - fl; buf = new(char, nl+1); if (!buf) return log_oom(); memcpy(buf, (const char*) data + fl, nl); buf[nl] = 0; free(*target); *target = buf; if (target_size) *target_size = nl; return 1; } static bool shall_print(const char *p, size_t l, OutputFlags flags) { assert(p); if (flags & OUTPUT_SHOW_ALL) return true; if (l >= PRINT_CHAR_THRESHOLD) return false; if (!utf8_is_printable(p, l)) return false; return true; } static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, OutputFlags flags, int priority, const char* message, size_t message_len) { const char *color_on = "", *color_off = ""; const char *pos, *end; bool ellipsized = false; int line = 0; if (flags & OUTPUT_COLOR) { if (priority <= LOG_ERR) { color_on = ANSI_HIGHLIGHT_RED; color_off = ANSI_NORMAL; } else if (priority <= LOG_NOTICE) { color_on = ANSI_HIGHLIGHT; color_off = ANSI_NORMAL; } } /* A special case: make sure that we print a newline when the message is empty. */ if (message_len == 0) fputs("\n", f); for (pos = message; pos < message + message_len; pos = end + 1, line++) { bool continuation = line > 0; bool tail_line; int len; for (end = pos; end < message + message_len && *end != '\n'; end++) ; len = end - pos; assert(len >= 0); /* We need to figure out when we are showing not-last line, *and* * will skip subsequent lines. In that case, we will put the dots * at the end of the line, instead of putting dots in the middle * or not at all. */ tail_line = line + 1 == PRINT_LINE_THRESHOLD || end + 1 >= message + PRINT_CHAR_THRESHOLD; if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) || (prefix + len + 1 < n_columns && !tail_line)) { fprintf(f, "%*s%s%.*s%s\n", continuation * prefix, "", color_on, len, pos, color_off); continue; } /* Beyond this point, ellipsization will happen. */ ellipsized = true; if (prefix < n_columns && n_columns - prefix >= 3) { if (n_columns - prefix > (unsigned) len + 3) fprintf(f, "%*s%s%.*s...%s\n", continuation * prefix, "", color_on, len, pos, color_off); else { _cleanup_free_ char *e; e = ellipsize_mem(pos, len, n_columns - prefix, tail_line ? 100 : 90); if (!e) fprintf(f, "%*s%s%.*s%s\n", continuation * prefix, "", color_on, len, pos, color_off); else fprintf(f, "%*s%s%s%s\n", continuation * prefix, "", color_on, e, color_off); } } else fputs("...\n", f); if (tail_line) break; } return ellipsized; } static int output_short( FILE *f, sd_journal *j, OutputMode mode, unsigned n_columns, OutputFlags flags) { int r; const void *data; size_t length; size_t n = 0; _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL; size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0; int p = LOG_INFO; bool ellipsized = false; assert(f); assert(j); /* Set the threshold to one bigger than the actual print * threshold, so that if the line is actually longer than what * we're willing to print, ellipsization will occur. This way * we won't output a misleading line without any indication of * truncation. */ sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1); JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { r = parse_field(data, length, "PRIORITY=", &priority, &priority_len); if (r < 0) return r; else if (r > 0) continue; r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len); if (r < 0) return r; else if (r > 0) continue; r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len); if (r < 0) return r; else if (r > 0) continue; r = parse_field(data, length, "_COMM=", &comm, &comm_len); if (r < 0) return r; else if (r > 0) continue; r = parse_field(data, length, "_PID=", &pid, &pid_len); if (r < 0) return r; else if (r > 0) continue; r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len); if (r < 0) return r; else if (r > 0) continue; r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len); if (r < 0) return r; else if (r > 0) continue; r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len); if (r < 0) return r; else if (r > 0) continue; r = parse_field(data, length, "MESSAGE=", &message, &message_len); if (r < 0) return r; } if (r < 0) return log_error_errno(r, "Failed to get journal fields: %m"); if (!message) { log_debug("Skipping message without MESSAGE= field."); return 0; } if (!(flags & OUTPUT_SHOW_ALL)) strip_tab_ansi(&message, &message_len); if (priority_len == 1 && *priority >= '0' && *priority <= '7') p = *priority - '0'; if (mode == OUTPUT_SHORT_MONOTONIC) { uint64_t t; sd_id128_t boot_id; r = -ENOENT; if (monotonic) r = safe_atou64(monotonic, &t); if (r < 0) r = sd_journal_get_monotonic_usec(j, &t, &boot_id); if (r < 0) return log_error_errno(r, "Failed to get monotonic timestamp: %m"); fprintf(f, "[%5llu.%06llu]", (unsigned long long) (t / USEC_PER_SEC), (unsigned long long) (t % USEC_PER_SEC)); n += 1 + 5 + 1 + 6 + 1; } else { char buf[64]; uint64_t x; time_t t; struct tm tm; struct tm *(*gettime_r)(const time_t *, struct tm *); r = -ENOENT; gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r; if (realtime) r = safe_atou64(realtime, &x); if (r < 0) r = sd_journal_get_realtime_usec(j, &x); if (r < 0) return log_error_errno(r, "Failed to get realtime timestamp: %m"); t = (time_t) (x / USEC_PER_SEC); switch(mode) { case OUTPUT_SHORT_ISO: r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm)); break; case OUTPUT_SHORT_PRECISE: r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm)); if (r > 0) snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ".%06llu", (unsigned long long) (x % USEC_PER_SEC)); break; default: r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm)); } if (r <= 0) { log_error("Failed to format time."); return -EINVAL; } fputs(buf, f); n += strlen(buf); } if (hostname && shall_print(hostname, hostname_len, flags)) { fprintf(f, " %.*s", (int) hostname_len, hostname); n += hostname_len + 1; } if (identifier && shall_print(identifier, identifier_len, flags)) { fprintf(f, " %.*s", (int) identifier_len, identifier); n += identifier_len + 1; } else if (comm && shall_print(comm, comm_len, flags)) { fprintf(f, " %.*s", (int) comm_len, comm); n += comm_len + 1; } else fputs(" unknown", f); if (pid && shall_print(pid, pid_len, flags)) { fprintf(f, "[%.*s]", (int) pid_len, pid); n += pid_len + 2; } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) { fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid); n += fake_pid_len + 2; } if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) { char bytes[FORMAT_BYTES_MAX]; fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len)); } else { fputs(": ", f); ellipsized |= print_multiline(f, n + 2, n_columns, flags, p, message, message_len); } if (flags & OUTPUT_CATALOG) print_catalog(f, j); return ellipsized; } static int output_verbose( FILE *f, sd_journal *j, OutputMode mode, unsigned n_columns, OutputFlags flags) { const void *data; size_t length; _cleanup_free_ char *cursor = NULL; uint64_t realtime = 0; char ts[FORMAT_TIMESTAMP_MAX + 7]; int r; assert(f); assert(j); sd_journal_set_data_threshold(j, 0); r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length); if (r == -ENOENT) log_debug("Source realtime timestamp not found"); else if (r < 0) return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get source realtime timestamp: %m"); else { _cleanup_free_ char *value = NULL; r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, NULL); if (r < 0) return r; assert(r > 0); r = safe_atou64(value, &realtime); if (r < 0) log_debug_errno(r, "Failed to parse realtime timestamp: %m"); } if (r < 0) { r = sd_journal_get_realtime_usec(j, &realtime); if (r < 0) return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get realtime timestamp: %m"); } r = sd_journal_get_cursor(j, &cursor); if (r < 0) return log_error_errno(r, "Failed to get cursor: %m"); fprintf(f, "%s [%s]\n", flags & OUTPUT_UTC ? format_timestamp_us_utc(ts, sizeof(ts), realtime) : format_timestamp_us(ts, sizeof(ts), realtime), cursor); JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { const char *c; int fieldlen; const char *on = "", *off = ""; c = memchr(data, '=', length); if (!c) { log_error("Invalid field."); return -EINVAL; } fieldlen = c - (const char*) data; if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) { on = ANSI_HIGHLIGHT; off = ANSI_NORMAL; } if (flags & OUTPUT_SHOW_ALL || (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH) && utf8_is_printable(data, length))) { fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data); print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1); fputs(off, f); } else { char bytes[FORMAT_BYTES_MAX]; fprintf(f, " %s%.*s=[%s blob data]%s\n", on, (int) (c - (const char*) data), (const char*) data, format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1), off); } } if (r < 0) return r; if (flags & OUTPUT_CATALOG) print_catalog(f, j); return 0; } static int output_export( FILE *f, sd_journal *j, OutputMode mode, unsigned n_columns, OutputFlags flags) { sd_id128_t boot_id; char sid[33]; int r; usec_t realtime, monotonic; _cleanup_free_ char *cursor = NULL; const void *data; size_t length; assert(j); sd_journal_set_data_threshold(j, 0); r = sd_journal_get_realtime_usec(j, &realtime); if (r < 0) return log_error_errno(r, "Failed to get realtime timestamp: %m"); r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id); if (r < 0) return log_error_errno(r, "Failed to get monotonic timestamp: %m"); r = sd_journal_get_cursor(j, &cursor); if (r < 0) return log_error_errno(r, "Failed to get cursor: %m"); fprintf(f, "__CURSOR=%s\n" "__REALTIME_TIMESTAMP="USEC_FMT"\n" "__MONOTONIC_TIMESTAMP="USEC_FMT"\n" "_BOOT_ID=%s\n", cursor, realtime, monotonic, sd_id128_to_string(boot_id, sid)); JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { /* We already printed the boot id, from the data in * the header, hence let's suppress it here */ if (length >= 9 && startswith(data, "_BOOT_ID=")) continue; if (utf8_is_printable_newline(data, length, false)) fwrite(data, length, 1, f); else { const char *c; uint64_t le64; c = memchr(data, '=', length); if (!c) { log_error("Invalid field."); return -EINVAL; } fwrite(data, c - (const char*) data, 1, f); fputc('\n', f); le64 = htole64(length - (c - (const char*) data) - 1); fwrite(&le64, sizeof(le64), 1, f); fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f); } fputc('\n', f); } if (r < 0) return r; fputc('\n', f); return 0; } void json_escape( FILE *f, const char* p, size_t l, OutputFlags flags) { assert(f); assert(p); if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD) fputs("null", f); else if (!utf8_is_printable(p, l)) { bool not_first = false; fputs("[ ", f); while (l > 0) { if (not_first) fprintf(f, ", %u", (uint8_t) *p); else { not_first = true; fprintf(f, "%u", (uint8_t) *p); } p++; l--; } fputs(" ]", f); } else { fputc('\"', f); while (l > 0) { if (*p == '"' || *p == '\\') { fputc('\\', f); fputc(*p, f); } else if (*p == '\n') fputs("\\n", f); else if ((uint8_t) *p < ' ') fprintf(f, "\\u%04x", (uint8_t) *p); else fputc(*p, f); p++; l--; } fputc('\"', f); } } static int output_json( FILE *f, sd_journal *j, OutputMode mode, unsigned n_columns, OutputFlags flags) { uint64_t realtime, monotonic; _cleanup_free_ char *cursor = NULL; const void *data; size_t length; sd_id128_t boot_id; char sid[33], *k; int r; Hashmap *h = NULL; bool done, separator; assert(j); sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD); r = sd_journal_get_realtime_usec(j, &realtime); if (r < 0) return log_error_errno(r, "Failed to get realtime timestamp: %m"); r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id); if (r < 0) return log_error_errno(r, "Failed to get monotonic timestamp: %m"); r = sd_journal_get_cursor(j, &cursor); if (r < 0) return log_error_errno(r, "Failed to get cursor: %m"); if (mode == OUTPUT_JSON_PRETTY) fprintf(f, "{\n" "\t\"__CURSOR\" : \"%s\",\n" "\t\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\",\n" "\t\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\",\n" "\t\"_BOOT_ID\" : \"%s\"", cursor, realtime, monotonic, sd_id128_to_string(boot_id, sid)); else { if (mode == OUTPUT_JSON_SSE) fputs("data: ", f); fprintf(f, "{ \"__CURSOR\" : \"%s\", " "\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\", " "\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\", " "\"_BOOT_ID\" : \"%s\"", cursor, realtime, monotonic, sd_id128_to_string(boot_id, sid)); } h = hashmap_new(&string_hash_ops); if (!h) return log_oom(); /* First round, iterate through the entry and count how often each field appears */ JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { const char *eq; char *n; unsigned u; if (length >= 9 && memcmp(data, "_BOOT_ID=", 9) == 0) continue; eq = memchr(data, '=', length); if (!eq) continue; n = strndup(data, eq - (const char*) data); if (!n) { r = log_oom(); goto finish; } u = PTR_TO_UINT(hashmap_get(h, n)); if (u == 0) { r = hashmap_put(h, n, UINT_TO_PTR(1)); if (r < 0) { free(n); log_oom(); goto finish; } } else { r = hashmap_update(h, n, UINT_TO_PTR(u + 1)); free(n); if (r < 0) { log_oom(); goto finish; } } } if (r < 0) return r; separator = true; do { done = true; SD_JOURNAL_FOREACH_DATA(j, data, length) { const char *eq; char *kk, *n; size_t m; unsigned u; /* We already printed the boot id, from the data in * the header, hence let's suppress it here */ if (length >= 9 && memcmp(data, "_BOOT_ID=", 9) == 0) continue; eq = memchr(data, '=', length); if (!eq) continue; if (separator) { if (mode == OUTPUT_JSON_PRETTY) fputs(",\n\t", f); else fputs(", ", f); } m = eq - (const char*) data; n = strndup(data, m); if (!n) { r = log_oom(); goto finish; } u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk)); if (u == 0) { /* We already printed this, let's jump to the next */ free(n); separator = false; continue; } else if (u == 1) { /* Field only appears once, output it directly */ json_escape(f, data, m, flags); fputs(" : ", f); json_escape(f, eq + 1, length - m - 1, flags); hashmap_remove(h, n); free(kk); free(n); separator = true; continue; } else { /* Field appears multiple times, output it as array */ json_escape(f, data, m, flags); fputs(" : [ ", f); json_escape(f, eq + 1, length - m - 1, flags); /* Iterate through the end of the list */ while (sd_journal_enumerate_data(j, &data, &length) > 0) { if (length < m + 1) continue; if (memcmp(data, n, m) != 0) continue; if (((const char*) data)[m] != '=') continue; fputs(", ", f); json_escape(f, (const char*) data + m + 1, length - m - 1, flags); } fputs(" ]", f); hashmap_remove(h, n); free(kk); free(n); /* Iterate data fields form the beginning */ done = false; separator = true; break; } } } while (!done); if (mode == OUTPUT_JSON_PRETTY) fputs("\n}\n", f); else if (mode == OUTPUT_JSON_SSE) fputs("}\n\n", f); else fputs(" }\n", f); r = 0; finish: while ((k = hashmap_steal_first_key(h))) free(k); hashmap_free(h); return r; } static int output_cat( FILE *f, sd_journal *j, OutputMode mode, unsigned n_columns, OutputFlags flags) { const void *data; size_t l; int r; assert(j); assert(f); sd_journal_set_data_threshold(j, 0); r = sd_journal_get_data(j, "MESSAGE", &data, &l); if (r < 0) { /* An entry without MESSAGE=? */ if (r == -ENOENT) return 0; return log_error_errno(r, "Failed to get data: %m"); } assert(l >= 8); fwrite((const char*) data + 8, 1, l - 8, f); fputc('\n', f); return 0; } static int (*output_funcs[_OUTPUT_MODE_MAX])( FILE *f, sd_journal*j, OutputMode mode, unsigned n_columns, OutputFlags flags) = { [OUTPUT_SHORT] = output_short, [OUTPUT_SHORT_ISO] = output_short, [OUTPUT_SHORT_PRECISE] = output_short, [OUTPUT_SHORT_MONOTONIC] = output_short, [OUTPUT_VERBOSE] = output_verbose, [OUTPUT_EXPORT] = output_export, [OUTPUT_JSON] = output_json, [OUTPUT_JSON_PRETTY] = output_json, [OUTPUT_JSON_SSE] = output_json, [OUTPUT_CAT] = output_cat }; int output_journal( FILE *f, sd_journal *j, OutputMode mode, unsigned n_columns, OutputFlags flags, bool *ellipsized) { int ret; assert(mode >= 0); assert(mode < _OUTPUT_MODE_MAX); if (n_columns <= 0) n_columns = columns(); ret = output_funcs[mode](f, j, mode, n_columns, flags); fflush(stdout); if (ellipsized && ret > 0) *ellipsized = true; return ret; } static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) { assert(f); assert(flags); if (!(*flags & OUTPUT_BEGIN_NEWLINE)) return 0; /* Print a beginning new line if that's request, but only once * on the first line we print. */ fputc('\n', f); *flags &= ~OUTPUT_BEGIN_NEWLINE; return 0; } static int show_journal(FILE *f, sd_journal *j, OutputMode mode, unsigned n_columns, usec_t not_before, unsigned how_many, OutputFlags flags, bool *ellipsized) { int r; unsigned line = 0; bool need_seek = false; int warn_cutoff = flags & OUTPUT_WARN_CUTOFF; assert(j); assert(mode >= 0); assert(mode < _OUTPUT_MODE_MAX); /* Seek to end */ r = sd_journal_seek_tail(j); if (r < 0) return log_error_errno(r, "Failed to seek to tail: %m"); r = sd_journal_previous_skip(j, how_many); if (r < 0) return log_error_errno(r, "Failed to skip previous: %m"); for (;;) { for (;;) { usec_t usec; if (need_seek) { r = sd_journal_next(j); if (r < 0) return log_error_errno(r, "Failed to iterate through journal: %m"); } if (r == 0) break; need_seek = true; if (not_before > 0) { r = sd_journal_get_monotonic_usec(j, &usec, NULL); /* -ESTALE is returned if the timestamp is not from this boot */ if (r == -ESTALE) continue; else if (r < 0) return log_error_errno(r, "Failed to get journal time: %m"); if (usec < not_before) continue; } line ++; maybe_print_begin_newline(f, &flags); r = output_journal(f, j, mode, n_columns, flags, ellipsized); if (r < 0) return r; } if (warn_cutoff && line < how_many && not_before > 0) { sd_id128_t boot_id; usec_t cutoff = 0; /* Check whether the cutoff line is too early */ r = sd_id128_get_boot(&boot_id); if (r < 0) return log_error_errno(r, "Failed to get boot id: %m"); r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL); if (r < 0) return log_error_errno(r, "Failed to get journal cutoff time: %m"); if (r > 0 && not_before < cutoff) { maybe_print_begin_newline(f, &flags); fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n"); } warn_cutoff = false; } if (!(flags & OUTPUT_FOLLOW)) break; r = sd_journal_wait(j, USEC_INFINITY); if (r < 0) return log_error_errno(r, "Failed to wait for journal: %m"); } return 0; } int add_matches_for_unit(sd_journal *j, const char *unit) { int r; char *m1, *m2, *m3, *m4; assert(j); assert(unit); m1 = strjoina("_SYSTEMD_UNIT=", unit); m2 = strjoina("COREDUMP_UNIT=", unit); m3 = strjoina("UNIT=", unit); m4 = strjoina("OBJECT_SYSTEMD_UNIT=", unit); (void)( /* Look for messages from the service itself */ (r = sd_journal_add_match(j, m1, 0)) || /* Look for coredumps of the service */ (r = sd_journal_add_disjunction(j)) || (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) || (r = sd_journal_add_match(j, "_UID=0", 0)) || (r = sd_journal_add_match(j, m2, 0)) || /* Look for messages from PID 1 about this service */ (r = sd_journal_add_disjunction(j)) || (r = sd_journal_add_match(j, "_PID=1", 0)) || (r = sd_journal_add_match(j, m3, 0)) || /* Look for messages from authorized daemons about this service */ (r = sd_journal_add_disjunction(j)) || (r = sd_journal_add_match(j, "_UID=0", 0)) || (r = sd_journal_add_match(j, m4, 0)) ); if (r == 0 && endswith(unit, ".slice")) { char *m5 = strappend("_SYSTEMD_SLICE=", unit); /* Show all messages belonging to a slice */ (void)( (r = sd_journal_add_disjunction(j)) || (r = sd_journal_add_match(j, m5, 0)) ); } return r; } int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) { int r; char *m1, *m2, *m3, *m4; char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)]; assert(j); assert(unit); m1 = strjoina("_SYSTEMD_USER_UNIT=", unit); m2 = strjoina("USER_UNIT=", unit); m3 = strjoina("COREDUMP_USER_UNIT=", unit); m4 = strjoina("OBJECT_SYSTEMD_USER_UNIT=", unit); sprintf(muid, "_UID="UID_FMT, uid); (void) ( /* Look for messages from the user service itself */ (r = sd_journal_add_match(j, m1, 0)) || (r = sd_journal_add_match(j, muid, 0)) || /* Look for messages from systemd about this service */ (r = sd_journal_add_disjunction(j)) || (r = sd_journal_add_match(j, m2, 0)) || (r = sd_journal_add_match(j, muid, 0)) || /* Look for coredumps of the service */ (r = sd_journal_add_disjunction(j)) || (r = sd_journal_add_match(j, m3, 0)) || (r = sd_journal_add_match(j, muid, 0)) || (r = sd_journal_add_match(j, "_UID=0", 0)) || /* Look for messages from authorized daemons about this service */ (r = sd_journal_add_disjunction(j)) || (r = sd_journal_add_match(j, m4, 0)) || (r = sd_journal_add_match(j, muid, 0)) || (r = sd_journal_add_match(j, "_UID=0", 0)) ); if (r == 0 && endswith(unit, ".slice")) { char *m5 = strappend("_SYSTEMD_SLICE=", unit); /* Show all messages belonging to a slice */ (void)( (r = sd_journal_add_disjunction(j)) || (r = sd_journal_add_match(j, m5, 0)) || (r = sd_journal_add_match(j, muid, 0)) ); } return r; } static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) { _cleanup_close_pair_ int pair[2] = { -1, -1 }; _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1; pid_t pid, child; siginfo_t si; char buf[37]; ssize_t k; int r; assert(machine); assert(boot_id); if (!machine_name_is_valid(machine)) return -EINVAL; r = container_get_leader(machine, &pid); if (r < 0) return r; r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, NULL, &rootfd); if (r < 0) return r; if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0) return -errno; child = fork(); if (child < 0) return -errno; if (child == 0) { int fd; pair[0] = safe_close(pair[0]); r = namespace_enter(pidnsfd, mntnsfd, -1, -1, rootfd); if (r < 0) _exit(EXIT_FAILURE); fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) _exit(EXIT_FAILURE); r = loop_read_exact(fd, buf, 36, false); safe_close(fd); if (r < 0) _exit(EXIT_FAILURE); k = send(pair[1], buf, 36, MSG_NOSIGNAL); if (k != 36) _exit(EXIT_FAILURE); _exit(EXIT_SUCCESS); } pair[1] = safe_close(pair[1]); r = wait_for_terminate(child, &si); if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS) return r < 0 ? r : -EIO; k = recv(pair[0], buf, 36, 0); if (k != 36) return -EIO; buf[36] = 0; r = sd_id128_from_string(buf, boot_id); if (r < 0) return r; return 0; } int add_match_this_boot(sd_journal *j, const char *machine) { char match[9+32+1] = "_BOOT_ID="; sd_id128_t boot_id; int r; assert(j); if (machine) { r = get_boot_id_for_machine(machine, &boot_id); if (r < 0) return log_error_errno(r, "Failed to get boot id of container %s: %m", machine); } else { r = sd_id128_get_boot(&boot_id); if (r < 0) return log_error_errno(r, "Failed to get boot id: %m"); } sd_id128_to_string(boot_id, match + 9); r = sd_journal_add_match(j, match, strlen(match)); if (r < 0) return log_error_errno(r, "Failed to add match: %m"); r = sd_journal_add_conjunction(j); if (r < 0) return log_error_errno(r, "Failed to add conjunction: %m"); return 0; } int show_journal_by_unit( FILE *f, const char *unit, OutputMode mode, unsigned n_columns, usec_t not_before, unsigned how_many, uid_t uid, OutputFlags flags, int journal_open_flags, bool system_unit, bool *ellipsized) { _cleanup_(sd_journal_closep) sd_journal *j = NULL; int r; assert(mode >= 0); assert(mode < _OUTPUT_MODE_MAX); assert(unit); if (how_many <= 0) return 0; r = sd_journal_open(&j, journal_open_flags); if (r < 0) return log_error_errno(r, "Failed to open journal: %m"); r = add_match_this_boot(j, NULL); if (r < 0) return r; if (system_unit) r = add_matches_for_unit(j, unit); else r = add_matches_for_user_unit(j, unit, uid); if (r < 0) return log_error_errno(r, "Failed to add unit matches: %m"); if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) { _cleanup_free_ char *filter; filter = journal_make_match_string(j); if (!filter) return log_oom(); log_debug("Journal filter: %s", filter); } return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized); } static const char *const output_mode_table[_OUTPUT_MODE_MAX] = { [OUTPUT_SHORT] = "short", [OUTPUT_SHORT_ISO] = "short-iso", [OUTPUT_SHORT_PRECISE] = "short-precise", [OUTPUT_SHORT_MONOTONIC] = "short-monotonic", [OUTPUT_VERBOSE] = "verbose", [OUTPUT_EXPORT] = "export", [OUTPUT_JSON] = "json", [OUTPUT_JSON_PRETTY] = "json-pretty", [OUTPUT_JSON_SSE] = "json-sse", [OUTPUT_CAT] = "cat" }; DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode); systemd-229/src/shared/logs-show.h000066400000000000000000000040301265713322000172060ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-journal.h" #include "macro.h" #include "output-mode.h" #include "time-util.h" #include "util.h" int output_journal( FILE *f, sd_journal *j, OutputMode mode, unsigned n_columns, OutputFlags flags, bool *ellipsized); int add_match_this_boot(sd_journal *j, const char *machine); int add_matches_for_unit( sd_journal *j, const char *unit); int add_matches_for_user_unit( sd_journal *j, const char *unit, uid_t uid); int show_journal_by_unit( FILE *f, const char *unit, OutputMode mode, unsigned n_columns, usec_t not_before, unsigned how_many, uid_t uid, OutputFlags flags, int journal_open_flags, bool system_unit, bool *ellipsized); void json_escape( FILE *f, const char* p, size_t l, OutputFlags flags); const char* output_mode_to_string(OutputMode m) _const_; OutputMode output_mode_from_string(const char *s) _pure_; systemd-229/src/shared/machine-image.c000066400000000000000000000566211265713322000177600ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "btrfs-util.h" #include "chattr-util.h" #include "copy.h" #include "dirent-util.h" #include "fd-util.h" #include "fs-util.h" #include "hashmap.h" #include "lockfile-util.h" #include "log.h" #include "macro.h" #include "machine-image.h" #include "mkdir.h" #include "path-util.h" #include "rm-rf.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "time-util.h" #include "utf8.h" #include "util.h" #include "xattr-util.h" static const char image_search_path[] = "/var/lib/machines\0" "/var/lib/container\0" /* legacy */ "/usr/local/lib/machines\0" "/usr/lib/machines\0"; Image *image_unref(Image *i) { if (!i) return NULL; free(i->name); free(i->path); free(i); return NULL; } static char **image_settings_path(Image *image) { _cleanup_strv_free_ char **l = NULL; char **ret; const char *fn, *s; unsigned i = 0; assert(image); l = new0(char*, 4); if (!l) return NULL; fn = strjoina(image->name, ".nspawn"); FOREACH_STRING(s, "/etc/systemd/nspawn/", "/run/systemd/nspawn/") { l[i] = strappend(s, fn); if (!l[i]) return NULL; i++; } l[i] = file_in_same_dir(image->path, fn); if (!l[i]) return NULL; ret = l; l = NULL; return ret; } static int image_new( ImageType t, const char *pretty, const char *path, const char *filename, bool read_only, usec_t crtime, usec_t mtime, Image **ret) { _cleanup_(image_unrefp) Image *i = NULL; assert(t >= 0); assert(t < _IMAGE_TYPE_MAX); assert(pretty); assert(filename); assert(ret); i = new0(Image, 1); if (!i) return -ENOMEM; i->type = t; i->read_only = read_only; i->crtime = crtime; i->mtime = mtime; i->usage = i->usage_exclusive = (uint64_t) -1; i->limit = i->limit_exclusive = (uint64_t) -1; i->name = strdup(pretty); if (!i->name) return -ENOMEM; if (path) i->path = strjoin(path, "/", filename, NULL); else i->path = strdup(filename); if (!i->path) return -ENOMEM; path_kill_slashes(i->path); *ret = i; i = NULL; return 0; } static int image_make( const char *pretty, int dfd, const char *path, const char *filename, Image **ret) { struct stat st; bool read_only; int r; assert(filename); /* We explicitly *do* follow symlinks here, since we want to * allow symlinking trees into /var/lib/machines/, and treat * them normally. */ if (fstatat(dfd, filename, &st, 0) < 0) return -errno; read_only = (path && path_startswith(path, "/usr")) || (faccessat(dfd, filename, W_OK, AT_EACCESS) < 0 && errno == EROFS); if (S_ISDIR(st.st_mode)) { _cleanup_close_ int fd = -1; unsigned file_attr = 0; if (!ret) return 1; if (!pretty) pretty = filename; fd = openat(dfd, filename, O_CLOEXEC|O_NOCTTY|O_DIRECTORY); if (fd < 0) return -errno; /* btrfs subvolumes have inode 256 */ if (st.st_ino == 256) { r = btrfs_is_filesystem(fd); if (r < 0) return r; if (r) { BtrfsSubvolInfo info; /* It's a btrfs subvolume */ r = btrfs_subvol_get_info_fd(fd, 0, &info); if (r < 0) return r; r = image_new(IMAGE_SUBVOLUME, pretty, path, filename, info.read_only || read_only, info.otime, 0, ret); if (r < 0) return r; if (btrfs_quota_scan_ongoing(fd) == 0) { BtrfsQuotaInfo quota; r = btrfs_subvol_get_subtree_quota_fd(fd, 0, "a); if (r >= 0) { (*ret)->usage = quota.referenced; (*ret)->usage_exclusive = quota.exclusive; (*ret)->limit = quota.referenced_max; (*ret)->limit_exclusive = quota.exclusive_max; } } return 1; } } /* If the IMMUTABLE bit is set, we consider the * directory read-only. Since the ioctl is not * supported everywhere we ignore failures. */ (void) read_attr_fd(fd, &file_attr); /* It's just a normal directory. */ r = image_new(IMAGE_DIRECTORY, pretty, path, filename, read_only || (file_attr & FS_IMMUTABLE_FL), 0, 0, ret); if (r < 0) return r; return 1; } else if (S_ISREG(st.st_mode) && endswith(filename, ".raw")) { usec_t crtime = 0; /* It's a RAW disk image */ if (!ret) return 1; fd_getcrtime_at(dfd, filename, &crtime, 0); if (!pretty) pretty = strndupa(filename, strlen(filename) - 4); r = image_new(IMAGE_RAW, pretty, path, filename, !(st.st_mode & 0222) || read_only, crtime, timespec_load(&st.st_mtim), ret); if (r < 0) return r; (*ret)->usage = (*ret)->usage_exclusive = st.st_blocks * 512; (*ret)->limit = (*ret)->limit_exclusive = st.st_size; return 1; } return 0; } int image_find(const char *name, Image **ret) { const char *path; int r; assert(name); /* There are no images with invalid names */ if (!image_name_is_valid(name)) return 0; NULSTR_FOREACH(path, image_search_path) { _cleanup_closedir_ DIR *d = NULL; d = opendir(path); if (!d) { if (errno == ENOENT) continue; return -errno; } r = image_make(NULL, dirfd(d), path, name, ret); if (r == 0 || r == -ENOENT) { _cleanup_free_ char *raw = NULL; raw = strappend(name, ".raw"); if (!raw) return -ENOMEM; r = image_make(NULL, dirfd(d), path, raw, ret); if (r == 0 || r == -ENOENT) continue; } if (r < 0) return r; return 1; } if (streq(name, ".host")) return image_make(".host", AT_FDCWD, NULL, "/", ret); return 0; }; int image_discover(Hashmap *h) { const char *path; int r; assert(h); NULSTR_FOREACH(path, image_search_path) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; d = opendir(path); if (!d) { if (errno == ENOENT) continue; return -errno; } FOREACH_DIRENT_ALL(de, d, return -errno) { _cleanup_(image_unrefp) Image *image = NULL; if (!image_name_is_valid(de->d_name)) continue; if (hashmap_contains(h, de->d_name)) continue; r = image_make(NULL, dirfd(d), path, de->d_name, &image); if (r == 0 || r == -ENOENT) continue; if (r < 0) return r; r = hashmap_put(h, image->name, image); if (r < 0) return r; image = NULL; } } if (!hashmap_contains(h, ".host")) { _cleanup_(image_unrefp) Image *image = NULL; r = image_make(".host", AT_FDCWD, NULL, "/", &image); if (r < 0) return r; r = hashmap_put(h, image->name, image); if (r < 0) return r; image = NULL; } return 0; } void image_hashmap_free(Hashmap *map) { Image *i; while ((i = hashmap_steal_first(map))) image_unref(i); hashmap_free(map); } int image_remove(Image *i) { _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT; _cleanup_strv_free_ char **settings = NULL; char **j; int r; assert(i); if (path_equal(i->path, "/") || path_startswith(i->path, "/usr")) return -EROFS; settings = image_settings_path(i); if (!settings) return -ENOMEM; /* Make sure we don't interfere with a running nspawn */ r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock); if (r < 0) return r; switch (i->type) { case IMAGE_SUBVOLUME: r = btrfs_subvol_remove(i->path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); if (r < 0) return r; break; case IMAGE_DIRECTORY: /* Allow deletion of read-only directories */ (void) chattr_path(i->path, false, FS_IMMUTABLE_FL); r = rm_rf(i->path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); if (r < 0) return r; break; case IMAGE_RAW: if (unlink(i->path) < 0) return -errno; break; default: return -EOPNOTSUPP; } STRV_FOREACH(j, settings) { if (unlink(*j) < 0 && errno != ENOENT) log_debug_errno(errno, "Failed to unlink %s, ignoring: %m", *j); } return 0; } static int rename_settings_file(const char *path, const char *new_name) { _cleanup_free_ char *rs = NULL; const char *fn; fn = strjoina(new_name, ".nspawn"); rs = file_in_same_dir(path, fn); if (!rs) return -ENOMEM; return rename_noreplace(AT_FDCWD, path, AT_FDCWD, rs); } int image_rename(Image *i, const char *new_name) { _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT, name_lock = LOCK_FILE_INIT; _cleanup_free_ char *new_path = NULL, *nn = NULL; _cleanup_strv_free_ char **settings = NULL; unsigned file_attr = 0; char **j; int r; assert(i); if (!image_name_is_valid(new_name)) return -EINVAL; if (path_equal(i->path, "/") || path_startswith(i->path, "/usr")) return -EROFS; settings = image_settings_path(i); if (!settings) return -ENOMEM; /* Make sure we don't interfere with a running nspawn */ r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock); if (r < 0) return r; /* Make sure nobody takes the new name, between the time we * checked it is currently unused in all search paths, and the * time we take possesion of it */ r = image_name_lock(new_name, LOCK_EX|LOCK_NB, &name_lock); if (r < 0) return r; r = image_find(new_name, NULL); if (r < 0) return r; if (r > 0) return -EEXIST; switch (i->type) { case IMAGE_DIRECTORY: /* Turn of the immutable bit while we rename the image, so that we can rename it */ (void) read_attr_path(i->path, &file_attr); if (file_attr & FS_IMMUTABLE_FL) (void) chattr_path(i->path, false, FS_IMMUTABLE_FL); /* fall through */ case IMAGE_SUBVOLUME: new_path = file_in_same_dir(i->path, new_name); break; case IMAGE_RAW: { const char *fn; fn = strjoina(new_name, ".raw"); new_path = file_in_same_dir(i->path, fn); break; } default: return -EOPNOTSUPP; } if (!new_path) return -ENOMEM; nn = strdup(new_name); if (!nn) return -ENOMEM; r = rename_noreplace(AT_FDCWD, i->path, AT_FDCWD, new_path); if (r < 0) return r; /* Restore the immutable bit, if it was set before */ if (file_attr & FS_IMMUTABLE_FL) (void) chattr_path(new_path, true, FS_IMMUTABLE_FL); free(i->path); i->path = new_path; new_path = NULL; free(i->name); i->name = nn; nn = NULL; STRV_FOREACH(j, settings) { r = rename_settings_file(*j, new_name); if (r < 0 && r != -ENOENT) log_debug_errno(r, "Failed to rename settings file %s, ignoring: %m", *j); } return 0; } static int clone_settings_file(const char *path, const char *new_name) { _cleanup_free_ char *rs = NULL; const char *fn; fn = strjoina(new_name, ".nspawn"); rs = file_in_same_dir(path, fn); if (!rs) return -ENOMEM; return copy_file_atomic(path, rs, 0664, false, 0); } int image_clone(Image *i, const char *new_name, bool read_only) { _cleanup_release_lock_file_ LockFile name_lock = LOCK_FILE_INIT; _cleanup_strv_free_ char **settings = NULL; const char *new_path; char **j; int r; assert(i); if (!image_name_is_valid(new_name)) return -EINVAL; settings = image_settings_path(i); if (!settings) return -ENOMEM; /* Make sure nobody takes the new name, between the time we * checked it is currently unused in all search paths, and the * time we take possesion of it */ r = image_name_lock(new_name, LOCK_EX|LOCK_NB, &name_lock); if (r < 0) return r; r = image_find(new_name, NULL); if (r < 0) return r; if (r > 0) return -EEXIST; switch (i->type) { case IMAGE_SUBVOLUME: case IMAGE_DIRECTORY: new_path = strjoina("/var/lib/machines/", new_name); r = btrfs_subvol_snapshot(i->path, new_path, (read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY | BTRFS_SNAPSHOT_RECURSIVE | BTRFS_SNAPSHOT_QUOTA); /* Enable "subtree" quotas for the copy, if we didn't * copy any quota from the source. */ (void) btrfs_subvol_auto_qgroup(i->path, 0, true); break; case IMAGE_RAW: new_path = strjoina("/var/lib/machines/", new_name, ".raw"); r = copy_file_atomic(i->path, new_path, read_only ? 0444 : 0644, false, FS_NOCOW_FL); break; default: return -EOPNOTSUPP; } if (r < 0) return r; STRV_FOREACH(j, settings) { r = clone_settings_file(*j, new_name); if (r < 0 && r != -ENOENT) log_debug_errno(r, "Failed to clone settings %s, ignoring: %m", *j); } return 0; } int image_read_only(Image *i, bool b) { _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT; int r; assert(i); if (path_equal(i->path, "/") || path_startswith(i->path, "/usr")) return -EROFS; /* Make sure we don't interfere with a running nspawn */ r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock); if (r < 0) return r; switch (i->type) { case IMAGE_SUBVOLUME: /* Note that we set the flag only on the top-level * subvolume of the image. */ r = btrfs_subvol_set_read_only(i->path, b); if (r < 0) return r; break; case IMAGE_DIRECTORY: /* For simple directory trees we cannot use the access mode of the top-level directory, since it has an effect on the container itself. However, we can use the "immutable" flag, to at least make the top-level directory read-only. It's not as good as a read-only subvolume, but at least something, and we can read the value back.*/ r = chattr_path(i->path, b, FS_IMMUTABLE_FL); if (r < 0) return r; break; case IMAGE_RAW: { struct stat st; if (stat(i->path, &st) < 0) return -errno; if (chmod(i->path, (st.st_mode & 0444) | (b ? 0000 : 0200)) < 0) return -errno; /* If the images is now read-only, it's a good time to * defrag it, given that no write patterns will * fragment it again. */ if (b) (void) btrfs_defrag(i->path); break; } default: return -EOPNOTSUPP; } return 0; } int image_path_lock(const char *path, int operation, LockFile *global, LockFile *local) { _cleanup_free_ char *p = NULL; LockFile t = LOCK_FILE_INIT; struct stat st; int r; assert(path); assert(global); assert(local); /* Locks an image path. This actually creates two locks: one * "local" one, next to the image path itself, which might be * shared via NFS. And another "global" one, in /run, that * uses the device/inode number. This has the benefit that we * can even lock a tree that is a mount point, correctly. */ if (path_equal(path, "/")) return -EBUSY; if (!path_is_absolute(path)) return -EINVAL; if (stat(path, &st) >= 0) { if (asprintf(&p, "/run/systemd/nspawn/locks/inode-%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino) < 0) return -ENOMEM; } r = make_lock_file_for(path, operation, &t); if (r < 0) return r; if (p) { mkdir_p("/run/systemd/nspawn/locks", 0700); r = make_lock_file(p, operation, global); if (r < 0) { release_lock_file(&t); return r; } } *local = t; return 0; } int image_set_limit(Image *i, uint64_t referenced_max) { assert(i); if (path_equal(i->path, "/") || path_startswith(i->path, "/usr")) return -EROFS; if (i->type != IMAGE_SUBVOLUME) return -EOPNOTSUPP; /* We set the quota both for the subvolume as well as for the * subtree. The latter is mostly for historical reasons, since * we didn't use to have a concept of subtree quota, and hence * only modified the subvolume quota. */ (void) btrfs_qgroup_set_limit(i->path, 0, referenced_max); (void) btrfs_subvol_auto_qgroup(i->path, 0, true); return btrfs_subvol_set_subtree_quota_limit(i->path, 0, referenced_max); } int image_name_lock(const char *name, int operation, LockFile *ret) { const char *p; assert(name); assert(ret); /* Locks an image name, regardless of the precise path used. */ if (!image_name_is_valid(name)) return -EINVAL; if (streq(name, ".host")) return -EBUSY; mkdir_p("/run/systemd/nspawn/locks", 0700); p = strjoina("/run/systemd/nspawn/locks/name-", name); return make_lock_file(p, operation, ret); } bool image_name_is_valid(const char *s) { if (!filename_is_valid(s)) return false; if (string_has_cc(s, NULL)) return false; if (!utf8_is_valid(s)) return false; /* Temporary files for atomically creating new files */ if (startswith(s, ".#")) return false; return true; } static const char* const image_type_table[_IMAGE_TYPE_MAX] = { [IMAGE_DIRECTORY] = "directory", [IMAGE_SUBVOLUME] = "subvolume", [IMAGE_RAW] = "raw", }; DEFINE_STRING_TABLE_LOOKUP(image_type, ImageType); systemd-229/src/shared/machine-image.h000066400000000000000000000041621265713322000177560ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "hashmap.h" #include "lockfile-util.h" #include "macro.h" #include "time-util.h" typedef enum ImageType { IMAGE_DIRECTORY, IMAGE_SUBVOLUME, IMAGE_RAW, _IMAGE_TYPE_MAX, _IMAGE_TYPE_INVALID = -1 } ImageType; typedef struct Image { ImageType type; char *name; char *path; bool read_only; usec_t crtime; usec_t mtime; uint64_t usage; uint64_t usage_exclusive; uint64_t limit; uint64_t limit_exclusive; void *userdata; } Image; Image *image_unref(Image *i); void image_hashmap_free(Hashmap *map); DEFINE_TRIVIAL_CLEANUP_FUNC(Image*, image_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, image_hashmap_free); int image_find(const char *name, Image **ret); int image_discover(Hashmap *map); int image_remove(Image *i); int image_rename(Image *i, const char *new_name); int image_clone(Image *i, const char *new_name, bool read_only); int image_read_only(Image *i, bool b); const char* image_type_to_string(ImageType t) _const_; ImageType image_type_from_string(const char *s) _pure_; bool image_name_is_valid(const char *s) _pure_; int image_path_lock(const char *path, int operation, LockFile *global, LockFile *local); int image_name_lock(const char *name, int operation, LockFile *ret); int image_set_limit(Image *i, uint64_t referenced_max); systemd-229/src/shared/machine-pool.c000066400000000000000000000342131265713322000176400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sd-bus-protocol.h" #include "sd-bus.h" #include "alloc-util.h" #include "btrfs-util.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "lockfile-util.h" #include "log.h" #include "machine-pool.h" #include "macro.h" #include "missing.h" #include "mkdir.h" #include "mount-util.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "signal-util.h" #include "stat-util.h" #include "string-util.h" #define VAR_LIB_MACHINES_SIZE_START (1024UL*1024UL*500UL) #define VAR_LIB_MACHINES_FREE_MIN (1024UL*1024UL*750UL) static int check_btrfs(void) { struct statfs sfs; if (statfs("/var/lib/machines", &sfs) < 0) { if (errno != ENOENT) return -errno; if (statfs("/var/lib", &sfs) < 0) return -errno; } return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC); } static int setup_machine_raw(uint64_t size, sd_bus_error *error) { _cleanup_free_ char *tmp = NULL; _cleanup_close_ int fd = -1; struct statvfs ss; pid_t pid = 0; siginfo_t si; int r; /* We want to be able to make use of btrfs-specific file * system features, in particular subvolumes, reflinks and * quota. Hence, if we detect that /var/lib/machines.raw is * not located on btrfs, let's create a loopback file, place a * btrfs file system into it, and mount it to * /var/lib/machines. */ fd = open("/var/lib/machines.raw", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); if (fd >= 0) { r = fd; fd = -1; return r; } if (errno != ENOENT) return sd_bus_error_set_errnof(error, errno, "Failed to open /var/lib/machines.raw: %m"); r = tempfn_xxxxxx("/var/lib/machines.raw", NULL, &tmp); if (r < 0) return r; (void) mkdir_p_label("/var/lib", 0755); fd = open(tmp, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0600); if (fd < 0) return sd_bus_error_set_errnof(error, errno, "Failed to create /var/lib/machines.raw: %m"); if (fstatvfs(fd, &ss) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to determine free space on /var/lib/machines.raw: %m"); goto fail; } if (ss.f_bsize * ss.f_bavail < VAR_LIB_MACHINES_FREE_MIN) { r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Not enough free disk space to set up /var/lib/machines."); goto fail; } if (ftruncate(fd, size) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to enlarge /var/lib/machines.raw: %m"); goto fail; } pid = fork(); if (pid < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to fork mkfs.btrfs: %m"); goto fail; } if (pid == 0) { /* Child */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); fd = safe_close(fd); execlp("mkfs.btrfs", "-Lvar-lib-machines", tmp, NULL); if (errno == ENOENT) return 99; _exit(EXIT_FAILURE); } r = wait_for_terminate(pid, &si); if (r < 0) { sd_bus_error_set_errnof(error, r, "Failed to wait for mkfs.btrfs: %m"); goto fail; } pid = 0; if (si.si_code != CLD_EXITED) { r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "mkfs.btrfs died abnormally."); goto fail; } if (si.si_status == 99) { r = sd_bus_error_set_errnof(error, ENOENT, "Cannot set up /var/lib/machines, mkfs.btrfs is missing"); goto fail; } if (si.si_status != 0) { r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "mkfs.btrfs failed with error code %i", si.si_status); goto fail; } r = rename_noreplace(AT_FDCWD, tmp, AT_FDCWD, "/var/lib/machines.raw"); if (r < 0) { sd_bus_error_set_errnof(error, r, "Failed to move /var/lib/machines.raw into place: %m"); goto fail; } r = fd; fd = -1; return r; fail: unlink_noerrno(tmp); if (pid > 1) kill_and_sigcont(pid, SIGKILL); return r; } int setup_machine_directory(uint64_t size, sd_bus_error *error) { _cleanup_release_lock_file_ LockFile lock_file = LOCK_FILE_INIT; struct loop_info64 info = { .lo_flags = LO_FLAGS_AUTOCLEAR, }; _cleanup_close_ int fd = -1, control = -1, loop = -1; _cleanup_free_ char* loopdev = NULL; char tmpdir[] = "/tmp/machine-pool.XXXXXX", *mntdir = NULL; bool tmpdir_made = false, mntdir_made = false, mntdir_mounted = false; char buf[FORMAT_BYTES_MAX]; int r, nr = -1; /* btrfs cannot handle file systems < 16M, hence use this as minimum */ if (size == (uint64_t) -1) size = VAR_LIB_MACHINES_SIZE_START; else if (size < 16*1024*1024) size = 16*1024*1024; /* Make sure we only set the directory up once at a time */ r = make_lock_file("/run/systemd/machines.lock", LOCK_EX, &lock_file); if (r < 0) return r; r = check_btrfs(); if (r < 0) return sd_bus_error_set_errnof(error, r, "Failed to determine whether /var/lib/machines is located on btrfs: %m"); if (r > 0) { (void) btrfs_subvol_make_label("/var/lib/machines"); r = btrfs_quota_enable("/var/lib/machines", true); if (r < 0) log_warning_errno(r, "Failed to enable quota for /var/lib/machines, ignoring: %m"); r = btrfs_subvol_auto_qgroup("/var/lib/machines", 0, true); if (r < 0) log_warning_errno(r, "Failed to set up default quota hierarchy for /var/lib/machines, ignoring: %m"); return 1; } if (path_is_mount_point("/var/lib/machines", AT_SYMLINK_FOLLOW) > 0) { log_debug("/var/lib/machines is already a mount point, not creating loopback file for it."); return 0; } r = dir_is_populated("/var/lib/machines"); if (r < 0 && r != -ENOENT) return r; if (r > 0) { log_debug("/var/log/machines is already populated, not creating loopback file for it."); return 0; } r = mkfs_exists("btrfs"); if (r == -ENOENT) { log_debug("mkfs.btrfs is missing, cannot create loopback file for /var/lib/machines."); return 0; } if (r < 0) return r; fd = setup_machine_raw(size, error); if (fd < 0) return fd; control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); if (control < 0) return sd_bus_error_set_errnof(error, errno, "Failed to open /dev/loop-control: %m"); nr = ioctl(control, LOOP_CTL_GET_FREE); if (nr < 0) return sd_bus_error_set_errnof(error, errno, "Failed to allocate loop device: %m"); if (asprintf(&loopdev, "/dev/loop%i", nr) < 0) { r = -ENOMEM; goto fail; } loop = open(loopdev, O_CLOEXEC|O_RDWR|O_NOCTTY|O_NONBLOCK); if (loop < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to open loopback device: %m"); goto fail; } if (ioctl(loop, LOOP_SET_FD, fd) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to bind loopback device: %m"); goto fail; } if (ioctl(loop, LOOP_SET_STATUS64, &info) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to enable auto-clear for loopback device: %m"); goto fail; } /* We need to make sure the new /var/lib/machines directory * has an access mode of 0700 at the time it is first made * available. mkfs will create it with 0755 however. Hence, * let's mount the directory into an inaccessible directory * below /tmp first, fix the access mode, and move it to the * public place then. */ if (!mkdtemp(tmpdir)) { r = sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount parent directory: %m"); goto fail; } tmpdir_made = true; mntdir = strjoina(tmpdir, "/mnt"); if (mkdir(mntdir, 0700) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount directory: %m"); goto fail; } mntdir_made = true; if (mount(loopdev, mntdir, "btrfs", 0, NULL) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to mount loopback device: %m"); goto fail; } mntdir_mounted = true; r = btrfs_quota_enable(mntdir, true); if (r < 0) log_warning_errno(r, "Failed to enable quota, ignoring: %m"); r = btrfs_subvol_auto_qgroup(mntdir, 0, true); if (r < 0) log_warning_errno(r, "Failed to set up default quota hierarchy, ignoring: %m"); if (chmod(mntdir, 0700) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to fix owner: %m"); goto fail; } (void) mkdir_p_label("/var/lib/machines", 0700); if (mount(mntdir, "/var/lib/machines", NULL, MS_BIND, NULL) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to mount directory into right place: %m"); goto fail; } (void) syncfs(fd); log_info("Set up /var/lib/machines as btrfs loopback file system of size %s mounted on /var/lib/machines.raw.", format_bytes(buf, sizeof(buf), size)); (void) umount2(mntdir, MNT_DETACH); (void) rmdir(mntdir); (void) rmdir(tmpdir); return 1; fail: if (mntdir_mounted) (void) umount2(mntdir, MNT_DETACH); if (mntdir_made) (void) rmdir(mntdir); if (tmpdir_made) (void) rmdir(tmpdir); if (loop >= 0) { (void) ioctl(loop, LOOP_CLR_FD); loop = safe_close(loop); } if (control >= 0 && nr >= 0) (void) ioctl(control, LOOP_CTL_REMOVE, nr); return r; } static int sync_path(const char *p) { _cleanup_close_ int fd = -1; fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return -errno; if (syncfs(fd) < 0) return -errno; return 0; } int grow_machine_directory(void) { char buf[FORMAT_BYTES_MAX]; struct statvfs a, b; uint64_t old_size, new_size, max_add; int r; /* Ensure the disk space data is accurate */ sync_path("/var/lib/machines"); sync_path("/var/lib/machines.raw"); if (statvfs("/var/lib/machines.raw", &a) < 0) return -errno; if (statvfs("/var/lib/machines", &b) < 0) return -errno; /* Don't grow if not enough disk space is available on the host */ if (((uint64_t) a.f_bavail * (uint64_t) a.f_bsize) <= VAR_LIB_MACHINES_FREE_MIN) return 0; /* Don't grow if at least 1/3th of the fs is still free */ if (b.f_bavail > b.f_blocks / 3) return 0; /* Calculate how much we are willing to add at most */ max_add = ((uint64_t) a.f_bavail * (uint64_t) a.f_bsize) - VAR_LIB_MACHINES_FREE_MIN; /* Calculate the old size */ old_size = (uint64_t) b.f_blocks * (uint64_t) b.f_bsize; /* Calculate the new size as three times the size of what is used right now */ new_size = ((uint64_t) b.f_blocks - (uint64_t) b.f_bavail) * (uint64_t) b.f_bsize * 3; /* Always, grow at least to the start size */ if (new_size < VAR_LIB_MACHINES_SIZE_START) new_size = VAR_LIB_MACHINES_SIZE_START; /* If the new size is smaller than the old size, don't grow */ if (new_size < old_size) return 0; /* Ensure we never add more than the maximum */ if (new_size > old_size + max_add) new_size = old_size + max_add; r = btrfs_resize_loopback("/var/lib/machines", new_size, true); if (r <= 0) return r; /* Also bump the quota, of both the subvolume leaf qgroup, as * well as of any subtree quota group by the same id but a * higher level, if it exists. */ (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, new_size); (void) btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, new_size); log_info("Grew /var/lib/machines btrfs loopback file system to %s.", format_bytes(buf, sizeof(buf), new_size)); return 1; } systemd-229/src/shared/machine-pool.h000066400000000000000000000017741265713322000176530ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-bus.h" /* Grow the /var/lib/machines directory after each 10MiB written */ #define GROW_INTERVAL_BYTES (UINT64_C(10) * UINT64_C(1024) * UINT64_C(1024)) int setup_machine_directory(uint64_t size, sd_bus_error *error); int grow_machine_directory(void); systemd-229/src/shared/output-mode.h000066400000000000000000000026471265713322000175620ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef enum OutputMode { OUTPUT_SHORT, OUTPUT_SHORT_ISO, OUTPUT_SHORT_PRECISE, OUTPUT_SHORT_MONOTONIC, OUTPUT_VERBOSE, OUTPUT_EXPORT, OUTPUT_JSON, OUTPUT_JSON_PRETTY, OUTPUT_JSON_SSE, OUTPUT_CAT, _OUTPUT_MODE_MAX, _OUTPUT_MODE_INVALID = -1 } OutputMode; typedef enum OutputFlags { OUTPUT_SHOW_ALL = 1 << 0, OUTPUT_FOLLOW = 1 << 1, OUTPUT_WARN_CUTOFF = 1 << 2, OUTPUT_FULL_WIDTH = 1 << 3, OUTPUT_COLOR = 1 << 4, OUTPUT_CATALOG = 1 << 5, OUTPUT_BEGIN_NEWLINE = 1 << 6, OUTPUT_UTC = 1 << 7, } OutputFlags; systemd-229/src/shared/pager.c000066400000000000000000000152211265713322000163610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include "copy.h" #include "fd-util.h" #include "locale-util.h" #include "log.h" #include "macro.h" #include "pager.h" #include "process-util.h" #include "signal-util.h" #include "string-util.h" #include "terminal-util.h" static pid_t pager_pid = 0; noreturn static void pager_fallback(void) { int r; r = copy_bytes(STDIN_FILENO, STDOUT_FILENO, (uint64_t) -1, false); if (r < 0) { log_error_errno(r, "Internal pager failed: %m"); _exit(EXIT_FAILURE); } _exit(EXIT_SUCCESS); } int pager_open(bool jump_to_end) { _cleanup_close_pair_ int fd[2] = { -1, -1 }; const char *pager; pid_t parent_pid; if (pager_pid > 0) return 1; if (!on_tty()) return 0; pager = getenv("SYSTEMD_PAGER"); if (!pager) pager = getenv("PAGER"); /* If the pager is explicitly turned off, honour it */ if (pager && (pager[0] == 0 || streq(pager, "cat"))) return 0; /* Determine and cache number of columns before we spawn the * pager so that we get the value from the actual tty */ (void) columns(); if (pipe(fd) < 0) return log_error_errno(errno, "Failed to create pager pipe: %m"); parent_pid = getpid(); pager_pid = fork(); if (pager_pid < 0) return log_error_errno(errno, "Failed to fork pager: %m"); /* In the child start the pager */ if (pager_pid == 0) { const char* less_opts, *less_charset; (void) reset_all_signal_handlers(); (void) reset_signal_mask(); (void) dup2(fd[0], STDIN_FILENO); safe_close_pair(fd); /* Initialize a good set of less options */ less_opts = getenv("SYSTEMD_LESS"); if (!less_opts) less_opts = "FRSXMK"; if (jump_to_end) less_opts = strjoina(less_opts, " +G"); setenv("LESS", less_opts, 1); /* Initialize a good charset for less. This is * particularly important if we output UTF-8 * characters. */ less_charset = getenv("SYSTEMD_LESSCHARSET"); if (!less_charset && is_locale_utf8()) less_charset = "utf-8"; if (less_charset) setenv("LESSCHARSET", less_charset, 1); /* Make sure the pager goes away when the parent dies */ if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) _exit(EXIT_FAILURE); /* Check whether our parent died before we were able * to set the death signal */ if (getppid() != parent_pid) _exit(EXIT_SUCCESS); if (pager) { execlp(pager, pager, NULL); execl("/bin/sh", "sh", "-c", pager, NULL); } /* Debian's alternatives command for pagers is * called 'pager'. Note that we do not call * sensible-pagers here, since that is just a * shell script that implements a logic that * is similar to this one anyway, but is * Debian-specific. */ execlp("pager", "pager", NULL); execlp("less", "less", NULL); execlp("more", "more", NULL); pager_fallback(); /* not reached */ } /* Return in the parent */ if (dup2(fd[1], STDOUT_FILENO) < 0) return log_error_errno(errno, "Failed to duplicate pager pipe: %m"); if (dup2(fd[1], STDERR_FILENO) < 0) return log_error_errno(errno, "Failed to duplicate pager pipe: %m"); return 1; } void pager_close(void) { if (pager_pid <= 0) return; /* Inform pager that we are done */ stdout = safe_fclose(stdout); stderr = safe_fclose(stderr); (void) kill(pager_pid, SIGCONT); (void) wait_for_terminate(pager_pid, NULL); pager_pid = 0; } bool pager_have(void) { return pager_pid > 0; } int show_man_page(const char *desc, bool null_stdio) { const char *args[4] = { "man", NULL, NULL, NULL }; char *e = NULL; pid_t pid; size_t k; int r; siginfo_t status; k = strlen(desc); if (desc[k-1] == ')') e = strrchr(desc, '('); if (e) { char *page = NULL, *section = NULL; page = strndupa(desc, e - desc); section = strndupa(e + 1, desc + k - e - 2); args[1] = section; args[2] = page; } else args[1] = desc; pid = fork(); if (pid < 0) return log_error_errno(errno, "Failed to fork: %m"); if (pid == 0) { /* Child */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); if (null_stdio) { r = make_null_stdio(); if (r < 0) { log_error_errno(r, "Failed to kill stdio: %m"); _exit(EXIT_FAILURE); } } execvp(args[0], (char**) args); log_error_errno(errno, "Failed to execute man: %m"); _exit(EXIT_FAILURE); } r = wait_for_terminate(pid, &status); if (r < 0) return r; log_debug("Exit code %i status %i", status.si_code, status.si_status); return status.si_status; } systemd-229/src/shared/pager.h000066400000000000000000000016261265713322000163720ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" int pager_open(bool jump_to_end); void pager_close(void); bool pager_have(void) _pure_; int show_man_page(const char *page, bool null_stdio); systemd-229/src/shared/path-lookup.c000066400000000000000000000356021265713322000175330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "install.h" #include "log.h" #include "macro.h" #include "path-lookup.h" #include "path-util.h" #include "string-util.h" #include "strv.h" #include "util.h" int user_config_home(char **config_home) { const char *e; char *r; e = getenv("XDG_CONFIG_HOME"); if (e) { r = strappend(e, "/systemd/user"); if (!r) return -ENOMEM; *config_home = r; return 1; } else { const char *home; home = getenv("HOME"); if (home) { r = strappend(home, "/.config/systemd/user"); if (!r) return -ENOMEM; *config_home = r; return 1; } } return 0; } int user_runtime_dir(char **runtime_dir) { const char *e; char *r; e = getenv("XDG_RUNTIME_DIR"); if (e) { r = strappend(e, "/systemd/user"); if (!r) return -ENOMEM; *runtime_dir = r; return 1; } return 0; } static int user_data_home_dir(char **dir, const char *suffix) { const char *e; char *res; /* We don't treat /etc/xdg/systemd here as the spec * suggests because we assume that that is a link to * /etc/systemd/ anyway. */ e = getenv("XDG_DATA_HOME"); if (e) res = strappend(e, suffix); else { const char *home; home = getenv("HOME"); if (home) res = strjoin(home, "/.local/share", suffix, NULL); else return 0; } if (!res) return -ENOMEM; *dir = res; return 0; } static char** user_dirs( const char *generator, const char *generator_early, const char *generator_late) { const char * const config_unit_paths[] = { USER_CONFIG_UNIT_PATH, "/etc/systemd/user", NULL }; const char * const runtime_unit_path = "/run/systemd/user"; const char * const data_unit_paths[] = { "/usr/local/lib/systemd/user", "/usr/local/share/systemd/user", USER_DATA_UNIT_PATH, "/usr/lib/systemd/user", "/usr/share/systemd/user", NULL }; const char *e; _cleanup_free_ char *config_home = NULL, *runtime_dir = NULL, *data_home = NULL; _cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL; _cleanup_free_ char **res = NULL; char **tmp; int r; /* Implement the mechanisms defined in * * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html * * We look in both the config and the data dirs because we * want to encourage that distributors ship their unit files * as data, and allow overriding as configuration. */ if (user_config_home(&config_home) < 0) return NULL; if (user_runtime_dir(&runtime_dir) < 0) return NULL; e = getenv("XDG_CONFIG_DIRS"); if (e) { config_dirs = strv_split(e, ":"); if (!config_dirs) return NULL; } r = user_data_home_dir(&data_home, "/systemd/user"); if (r < 0) return NULL; e = getenv("XDG_DATA_DIRS"); if (e) data_dirs = strv_split(e, ":"); else data_dirs = strv_new("/usr/local/share", "/usr/share", NULL); if (!data_dirs) return NULL; /* Now merge everything we found. */ if (generator_early) if (strv_extend(&res, generator_early) < 0) return NULL; if (config_home) if (strv_extend(&res, config_home) < 0) return NULL; if (!strv_isempty(config_dirs)) if (strv_extend_strv_concat(&res, config_dirs, "/systemd/user") < 0) return NULL; if (strv_extend_strv(&res, (char**) config_unit_paths, false) < 0) return NULL; if (runtime_dir) if (strv_extend(&res, runtime_dir) < 0) return NULL; if (strv_extend(&res, runtime_unit_path) < 0) return NULL; if (generator) if (strv_extend(&res, generator) < 0) return NULL; if (data_home) if (strv_extend(&res, data_home) < 0) return NULL; if (!strv_isempty(data_dirs)) if (strv_extend_strv_concat(&res, data_dirs, "/systemd/user") < 0) return NULL; if (strv_extend_strv(&res, (char**) data_unit_paths, false) < 0) return NULL; if (generator_late) if (strv_extend(&res, generator_late) < 0) return NULL; if (path_strv_make_absolute_cwd(res) < 0) return NULL; tmp = res; res = NULL; return tmp; } char **generator_paths(ManagerRunningAs running_as) { if (running_as == MANAGER_USER) return strv_new("/run/systemd/user-generators", "/etc/systemd/user-generators", "/usr/local/lib/systemd/user-generators", USER_GENERATOR_PATH, NULL); else return strv_new("/run/systemd/system-generators", "/etc/systemd/system-generators", "/usr/local/lib/systemd/system-generators", SYSTEM_GENERATOR_PATH, NULL); } int lookup_paths_init( LookupPaths *p, ManagerRunningAs running_as, bool personal, const char *root_dir, const char *generator, const char *generator_early, const char *generator_late) { const char *e; bool append = false; /* Add items from SYSTEMD_UNIT_PATH before normal directories */ int r; assert(p); /* First priority is whatever has been passed to us via env * vars */ e = getenv("SYSTEMD_UNIT_PATH"); if (e) { if (endswith(e, ":")) { e = strndupa(e, strlen(e) - 1); append = true; } /* FIXME: empty components in other places should be * rejected. */ r = path_split_and_make_absolute(e, &p->unit_path); if (r < 0) return r; } else p->unit_path = NULL; if (!p->unit_path || append) { /* Let's figure something out. */ _cleanup_strv_free_ char **unit_path; /* For the user units we include share/ in the search * path in order to comply with the XDG basedir spec. * For the system stuff we avoid such nonsense. OTOH * we include /lib in the search path for the system * stuff but avoid it for user stuff. */ if (running_as == MANAGER_USER) { if (personal) unit_path = user_dirs(generator, generator_early, generator_late); else unit_path = strv_new( /* If you modify this you also want to modify * systemduserunitpath= in systemd.pc.in, and * the arrays in user_dirs() above! */ STRV_IFNOTNULL(generator_early), USER_CONFIG_UNIT_PATH, "/etc/systemd/user", "/run/systemd/user", STRV_IFNOTNULL(generator), "/usr/local/lib/systemd/user", "/usr/local/share/systemd/user", USER_DATA_UNIT_PATH, "/usr/lib/systemd/user", "/usr/share/systemd/user", STRV_IFNOTNULL(generator_late), NULL); } else unit_path = strv_new( /* If you modify this you also want to modify * systemdsystemunitpath= in systemd.pc.in! */ STRV_IFNOTNULL(generator_early), SYSTEM_CONFIG_UNIT_PATH, "/etc/systemd/system", "/run/systemd/system", STRV_IFNOTNULL(generator), "/usr/local/lib/systemd/system", SYSTEM_DATA_UNIT_PATH, "/usr/lib/systemd/system", #ifdef HAVE_SPLIT_USR "/lib/systemd/system", #endif STRV_IFNOTNULL(generator_late), NULL); if (!unit_path) return -ENOMEM; r = strv_extend_strv(&p->unit_path, unit_path, false); if (r < 0) return r; } if (!path_strv_resolve_uniq(p->unit_path, root_dir)) return -ENOMEM; if (!strv_isempty(p->unit_path)) { _cleanup_free_ char *t = strv_join(p->unit_path, "\n\t"); if (!t) return -ENOMEM; log_debug("Looking for unit files in (higher priority first):\n\t%s", t); } else { log_debug("Ignoring unit files."); p->unit_path = strv_free(p->unit_path); } if (running_as == MANAGER_SYSTEM) { #ifdef HAVE_SYSV_COMPAT /* /etc/init.d/ compatibility does not matter to users */ e = getenv("SYSTEMD_SYSVINIT_PATH"); if (e) { r = path_split_and_make_absolute(e, &p->sysvinit_path); if (r < 0) return r; } else p->sysvinit_path = NULL; if (strv_isempty(p->sysvinit_path)) { strv_free(p->sysvinit_path); p->sysvinit_path = strv_new( SYSTEM_SYSVINIT_PATH, /* /etc/init.d/ */ NULL); if (!p->sysvinit_path) return -ENOMEM; } e = getenv("SYSTEMD_SYSVRCND_PATH"); if (e) { r = path_split_and_make_absolute(e, &p->sysvrcnd_path); if (r < 0) return r; } else p->sysvrcnd_path = NULL; if (strv_isempty(p->sysvrcnd_path)) { strv_free(p->sysvrcnd_path); p->sysvrcnd_path = strv_new( SYSTEM_SYSVRCND_PATH, /* /etc/rcN.d/ */ NULL); if (!p->sysvrcnd_path) return -ENOMEM; } if (!path_strv_resolve_uniq(p->sysvinit_path, root_dir)) return -ENOMEM; if (!path_strv_resolve_uniq(p->sysvrcnd_path, root_dir)) return -ENOMEM; if (!strv_isempty(p->sysvinit_path)) { _cleanup_free_ char *t = strv_join(p->sysvinit_path, "\n\t"); if (!t) return -ENOMEM; log_debug("Looking for SysV init scripts in:\n\t%s", t); } else { log_debug("Ignoring SysV init scripts."); p->sysvinit_path = strv_free(p->sysvinit_path); } if (!strv_isempty(p->sysvrcnd_path)) { _cleanup_free_ char *t = strv_join(p->sysvrcnd_path, "\n\t"); if (!t) return -ENOMEM; log_debug("Looking for SysV rcN.d links in:\n\t%s", t); } else { log_debug("Ignoring SysV rcN.d links."); p->sysvrcnd_path = strv_free(p->sysvrcnd_path); } #else log_debug("SysV init scripts and rcN.d links support disabled"); #endif } return 0; } void lookup_paths_free(LookupPaths *p) { assert(p); p->unit_path = strv_free(p->unit_path); #ifdef HAVE_SYSV_COMPAT p->sysvinit_path = strv_free(p->sysvinit_path); p->sysvrcnd_path = strv_free(p->sysvrcnd_path); #endif } int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope, const char *root_dir) { assert(paths); assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); zero(*paths); return lookup_paths_init(paths, scope == UNIT_FILE_SYSTEM ? MANAGER_SYSTEM : MANAGER_USER, scope == UNIT_FILE_USER, root_dir, NULL, NULL, NULL); } systemd-229/src/shared/path-lookup.h000066400000000000000000000035011265713322000175310ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" typedef struct LookupPaths { char **unit_path; #ifdef HAVE_SYSV_COMPAT char **sysvinit_path; char **sysvrcnd_path; #endif } LookupPaths; typedef enum ManagerRunningAs { MANAGER_SYSTEM, MANAGER_USER, _MANAGER_RUNNING_AS_MAX, _MANAGER_RUNNING_AS_INVALID = -1 } ManagerRunningAs; int user_config_home(char **config_home); int user_runtime_dir(char **runtime_dir); char **generator_paths(ManagerRunningAs running_as); int lookup_paths_init(LookupPaths *p, ManagerRunningAs running_as, bool personal, const char *root_dir, const char *generator, const char *generator_early, const char *generator_late); #include "install.h" int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope, const char *root_dir); void lookup_paths_free(LookupPaths *p); #define _cleanup_lookup_paths_free_ _cleanup_(lookup_paths_free) systemd-229/src/shared/ptyfwd.c000066400000000000000000000405251265713322000166050ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010-2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include "sd-event.h" #include "alloc-util.h" #include "fd-util.h" #include "log.h" #include "macro.h" #include "ptyfwd.h" #include "time-util.h" struct PTYForward { sd_event *event; int master; PTYForwardFlags flags; sd_event_source *stdin_event_source; sd_event_source *stdout_event_source; sd_event_source *master_event_source; sd_event_source *sigwinch_event_source; struct termios saved_stdin_attr; struct termios saved_stdout_attr; bool saved_stdin:1; bool saved_stdout:1; bool stdin_readable:1; bool stdin_hangup:1; bool stdout_writable:1; bool stdout_hangup:1; bool master_readable:1; bool master_writable:1; bool master_hangup:1; bool read_from_master:1; bool last_char_set:1; char last_char; char in_buffer[LINE_MAX], out_buffer[LINE_MAX]; size_t in_buffer_full, out_buffer_full; usec_t escape_timestamp; unsigned escape_counter; }; #define ESCAPE_USEC (1*USEC_PER_SEC) static bool look_for_escape(PTYForward *f, const char *buffer, size_t n) { const char *p; assert(f); assert(buffer); assert(n > 0); for (p = buffer; p < buffer + n; p++) { /* Check for ^] */ if (*p == 0x1D) { usec_t nw = now(CLOCK_MONOTONIC); if (f->escape_counter == 0 || nw > f->escape_timestamp + ESCAPE_USEC) { f->escape_timestamp = nw; f->escape_counter = 1; } else { (f->escape_counter)++; if (f->escape_counter >= 3) return true; } } else { f->escape_timestamp = 0; f->escape_counter = 0; } } return false; } static bool ignore_vhangup(PTYForward *f) { assert(f); if (f->flags & PTY_FORWARD_IGNORE_VHANGUP) return true; if ((f->flags & PTY_FORWARD_IGNORE_INITIAL_VHANGUP) && !f->read_from_master) return true; return false; } static int shovel(PTYForward *f) { ssize_t k; assert(f); while ((f->stdin_readable && f->in_buffer_full <= 0) || (f->master_writable && f->in_buffer_full > 0) || (f->master_readable && f->out_buffer_full <= 0) || (f->stdout_writable && f->out_buffer_full > 0)) { if (f->stdin_readable && f->in_buffer_full < LINE_MAX) { k = read(STDIN_FILENO, f->in_buffer + f->in_buffer_full, LINE_MAX - f->in_buffer_full); if (k < 0) { if (errno == EAGAIN) f->stdin_readable = false; else if (errno == EIO || errno == EPIPE || errno == ECONNRESET) { f->stdin_readable = false; f->stdin_hangup = true; f->stdin_event_source = sd_event_source_unref(f->stdin_event_source); } else { log_error_errno(errno, "read(): %m"); return sd_event_exit(f->event, EXIT_FAILURE); } } else if (k == 0) { /* EOF on stdin */ f->stdin_readable = false; f->stdin_hangup = true; f->stdin_event_source = sd_event_source_unref(f->stdin_event_source); } else { /* Check if ^] has been * pressed three times within * one second. If we get this * we quite immediately. */ if (look_for_escape(f, f->in_buffer + f->in_buffer_full, k)) return sd_event_exit(f->event, EXIT_FAILURE); f->in_buffer_full += (size_t) k; } } if (f->master_writable && f->in_buffer_full > 0) { k = write(f->master, f->in_buffer, f->in_buffer_full); if (k < 0) { if (errno == EAGAIN || errno == EIO) f->master_writable = false; else if (errno == EPIPE || errno == ECONNRESET) { f->master_writable = f->master_readable = false; f->master_hangup = true; f->master_event_source = sd_event_source_unref(f->master_event_source); } else { log_error_errno(errno, "write(): %m"); return sd_event_exit(f->event, EXIT_FAILURE); } } else { assert(f->in_buffer_full >= (size_t) k); memmove(f->in_buffer, f->in_buffer + k, f->in_buffer_full - k); f->in_buffer_full -= k; } } if (f->master_readable && f->out_buffer_full < LINE_MAX) { k = read(f->master, f->out_buffer + f->out_buffer_full, LINE_MAX - f->out_buffer_full); if (k < 0) { /* Note that EIO on the master device * might be caused by vhangup() or * temporary closing of everything on * the other side, we treat it like * EAGAIN here and try again, unless * ignore_vhangup is off. */ if (errno == EAGAIN || (errno == EIO && ignore_vhangup(f))) f->master_readable = false; else if (errno == EPIPE || errno == ECONNRESET || errno == EIO) { f->master_readable = f->master_writable = false; f->master_hangup = true; f->master_event_source = sd_event_source_unref(f->master_event_source); } else { log_error_errno(errno, "read(): %m"); return sd_event_exit(f->event, EXIT_FAILURE); } } else { f->read_from_master = true; f->out_buffer_full += (size_t) k; } } if (f->stdout_writable && f->out_buffer_full > 0) { k = write(STDOUT_FILENO, f->out_buffer, f->out_buffer_full); if (k < 0) { if (errno == EAGAIN) f->stdout_writable = false; else if (errno == EIO || errno == EPIPE || errno == ECONNRESET) { f->stdout_writable = false; f->stdout_hangup = true; f->stdout_event_source = sd_event_source_unref(f->stdout_event_source); } else { log_error_errno(errno, "write(): %m"); return sd_event_exit(f->event, EXIT_FAILURE); } } else { if (k > 0) { f->last_char = f->out_buffer[k-1]; f->last_char_set = true; } assert(f->out_buffer_full >= (size_t) k); memmove(f->out_buffer, f->out_buffer + k, f->out_buffer_full - k); f->out_buffer_full -= k; } } } if (f->stdin_hangup || f->stdout_hangup || f->master_hangup) { /* Exit the loop if any side hung up and if there's * nothing more to write or nothing we could write. */ if ((f->out_buffer_full <= 0 || f->stdout_hangup) && (f->in_buffer_full <= 0 || f->master_hangup)) return sd_event_exit(f->event, EXIT_SUCCESS); } return 0; } static int on_master_event(sd_event_source *e, int fd, uint32_t revents, void *userdata) { PTYForward *f = userdata; assert(f); assert(e); assert(e == f->master_event_source); assert(fd >= 0); assert(fd == f->master); if (revents & (EPOLLIN|EPOLLHUP)) f->master_readable = true; if (revents & (EPOLLOUT|EPOLLHUP)) f->master_writable = true; return shovel(f); } static int on_stdin_event(sd_event_source *e, int fd, uint32_t revents, void *userdata) { PTYForward *f = userdata; assert(f); assert(e); assert(e == f->stdin_event_source); assert(fd >= 0); assert(fd == STDIN_FILENO); if (revents & (EPOLLIN|EPOLLHUP)) f->stdin_readable = true; return shovel(f); } static int on_stdout_event(sd_event_source *e, int fd, uint32_t revents, void *userdata) { PTYForward *f = userdata; assert(f); assert(e); assert(e == f->stdout_event_source); assert(fd >= 0); assert(fd == STDOUT_FILENO); if (revents & (EPOLLOUT|EPOLLHUP)) f->stdout_writable = true; return shovel(f); } static int on_sigwinch_event(sd_event_source *e, const struct signalfd_siginfo *si, void *userdata) { PTYForward *f = userdata; struct winsize ws; assert(f); assert(e); assert(e == f->sigwinch_event_source); /* The window size changed, let's forward that. */ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0) (void) ioctl(f->master, TIOCSWINSZ, &ws); return 0; } int pty_forward_new( sd_event *event, int master, PTYForwardFlags flags, PTYForward **ret) { _cleanup_(pty_forward_freep) PTYForward *f = NULL; struct winsize ws; int r; f = new0(PTYForward, 1); if (!f) return -ENOMEM; f->flags = flags; if (event) f->event = sd_event_ref(event); else { r = sd_event_default(&f->event); if (r < 0) return r; } if (!(flags & PTY_FORWARD_READ_ONLY)) { r = fd_nonblock(STDIN_FILENO, true); if (r < 0) return r; r = fd_nonblock(STDOUT_FILENO, true); if (r < 0) return r; } r = fd_nonblock(master, true); if (r < 0) return r; f->master = master; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0) (void) ioctl(master, TIOCSWINSZ, &ws); if (!(flags & PTY_FORWARD_READ_ONLY)) { if (tcgetattr(STDIN_FILENO, &f->saved_stdin_attr) >= 0) { struct termios raw_stdin_attr; f->saved_stdin = true; raw_stdin_attr = f->saved_stdin_attr; cfmakeraw(&raw_stdin_attr); raw_stdin_attr.c_oflag = f->saved_stdin_attr.c_oflag; tcsetattr(STDIN_FILENO, TCSANOW, &raw_stdin_attr); } if (tcgetattr(STDOUT_FILENO, &f->saved_stdout_attr) >= 0) { struct termios raw_stdout_attr; f->saved_stdout = true; raw_stdout_attr = f->saved_stdout_attr; cfmakeraw(&raw_stdout_attr); raw_stdout_attr.c_iflag = f->saved_stdout_attr.c_iflag; raw_stdout_attr.c_lflag = f->saved_stdout_attr.c_lflag; tcsetattr(STDOUT_FILENO, TCSANOW, &raw_stdout_attr); } r = sd_event_add_io(f->event, &f->stdin_event_source, STDIN_FILENO, EPOLLIN|EPOLLET, on_stdin_event, f); if (r < 0 && r != -EPERM) return r; } r = sd_event_add_io(f->event, &f->stdout_event_source, STDOUT_FILENO, EPOLLOUT|EPOLLET, on_stdout_event, f); if (r == -EPERM) /* stdout without epoll support. Likely redirected to regular file. */ f->stdout_writable = true; else if (r < 0) return r; r = sd_event_add_io(f->event, &f->master_event_source, master, EPOLLIN|EPOLLOUT|EPOLLET, on_master_event, f); if (r < 0) return r; r = sd_event_add_signal(f->event, &f->sigwinch_event_source, SIGWINCH, on_sigwinch_event, f); if (r < 0) return r; *ret = f; f = NULL; return 0; } PTYForward *pty_forward_free(PTYForward *f) { if (f) { sd_event_source_unref(f->stdin_event_source); sd_event_source_unref(f->stdout_event_source); sd_event_source_unref(f->master_event_source); sd_event_source_unref(f->sigwinch_event_source); sd_event_unref(f->event); if (f->saved_stdout) tcsetattr(STDOUT_FILENO, TCSANOW, &f->saved_stdout_attr); if (f->saved_stdin) tcsetattr(STDIN_FILENO, TCSANOW, &f->saved_stdin_attr); free(f); } /* STDIN/STDOUT should not be nonblocking normally, so let's * unconditionally reset it */ fd_nonblock(STDIN_FILENO, false); fd_nonblock(STDOUT_FILENO, false); return NULL; } int pty_forward_get_last_char(PTYForward *f, char *ch) { assert(f); assert(ch); if (!f->last_char_set) return -ENXIO; *ch = f->last_char; return 0; } int pty_forward_set_ignore_vhangup(PTYForward *f, bool b) { int r; assert(f); if (!!(f->flags & PTY_FORWARD_IGNORE_VHANGUP) == b) return 0; if (b) f->flags |= PTY_FORWARD_IGNORE_VHANGUP; else f->flags &= ~PTY_FORWARD_IGNORE_VHANGUP; if (!ignore_vhangup(f)) { /* We shall now react to vhangup()s? Let's check * immediately if we might be in one */ f->master_readable = true; r = shovel(f); if (r < 0) return r; } return 0; } int pty_forward_get_ignore_vhangup(PTYForward *f) { assert(f); return !!(f->flags & PTY_FORWARD_IGNORE_VHANGUP); } systemd-229/src/shared/ptyfwd.h000066400000000000000000000027641265713322000166150ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010-2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-event.h" #include "macro.h" typedef struct PTYForward PTYForward; typedef enum PTYForwardFlags { PTY_FORWARD_READ_ONLY = 1, /* Continue reading after hangup? */ PTY_FORWARD_IGNORE_VHANGUP = 2, /* Continue reading after hangup but only if we never read anything else? */ PTY_FORWARD_IGNORE_INITIAL_VHANGUP = 4, } PTYForwardFlags; int pty_forward_new(sd_event *event, int master, PTYForwardFlags flags, PTYForward **f); PTYForward *pty_forward_free(PTYForward *f); int pty_forward_get_last_char(PTYForward *f, char *ch); int pty_forward_set_ignore_vhangup(PTYForward *f, bool ignore_vhangup); int pty_forward_get_ignore_vhangup(PTYForward *f); DEFINE_TRIVIAL_CLEANUP_FUNC(PTYForward*, pty_forward_free); systemd-229/src/shared/resolve-util.c000066400000000000000000000030771265713322000177230ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2016 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "conf-parser.h" #include "resolve-util.h" #include "string-table.h" DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_support, resolve_support, ResolveSupport, "Failed to parse resolve support setting"); DEFINE_CONFIG_PARSE_ENUM(config_parse_dnssec_mode, dnssec_mode, DnssecMode, "Failed to parse DNSSEC mode setting"); static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = { [RESOLVE_SUPPORT_NO] = "no", [RESOLVE_SUPPORT_YES] = "yes", [RESOLVE_SUPPORT_RESOLVE] = "resolve", }; DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(resolve_support, ResolveSupport, RESOLVE_SUPPORT_YES); static const char* const dnssec_mode_table[_DNSSEC_MODE_MAX] = { [DNSSEC_NO] = "no", [DNSSEC_ALLOW_DOWNGRADE] = "allow-downgrade", [DNSSEC_YES] = "yes", }; DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dnssec_mode, DnssecMode, DNSSEC_YES); systemd-229/src/shared/resolve-util.h000066400000000000000000000043531265713322000177260ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2016 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "macro.h" typedef enum ResolveSupport ResolveSupport; typedef enum DnssecMode DnssecMode; enum ResolveSupport { RESOLVE_SUPPORT_NO, RESOLVE_SUPPORT_YES, RESOLVE_SUPPORT_RESOLVE, _RESOLVE_SUPPORT_MAX, _RESOLVE_SUPPORT_INVALID = -1 }; enum DnssecMode { /* No DNSSEC validation is done */ DNSSEC_NO, /* Validate locally, if the server knows DO, but if not, * don't. Don't trust the AD bit. If the server doesn't do * DNSSEC properly, downgrade to non-DNSSEC operation. Of * course, we then are vulnerable to a downgrade attack, but * that's life and what is configured. */ DNSSEC_ALLOW_DOWNGRADE, /* Insist on DNSSEC server support, and rather fail than downgrading. */ DNSSEC_YES, _DNSSEC_MODE_MAX, _DNSSEC_MODE_INVALID = -1 }; int config_parse_resolve_support(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_dnssec_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); const char* resolve_support_to_string(ResolveSupport p) _const_; ResolveSupport resolve_support_from_string(const char *s) _pure_; const char* dnssec_mode_to_string(DnssecMode p) _const_; DnssecMode dnssec_mode_from_string(const char *s) _pure_; systemd-229/src/shared/seccomp-util.c000066400000000000000000000045421265713322000176730ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "macro.h" #include "seccomp-util.h" #include "string-util.h" const char* seccomp_arch_to_string(uint32_t c) { if (c == SCMP_ARCH_NATIVE) return "native"; if (c == SCMP_ARCH_X86) return "x86"; if (c == SCMP_ARCH_X86_64) return "x86-64"; if (c == SCMP_ARCH_X32) return "x32"; if (c == SCMP_ARCH_ARM) return "arm"; return NULL; } int seccomp_arch_from_string(const char *n, uint32_t *ret) { if (!n) return -EINVAL; assert(ret); if (streq(n, "native")) *ret = SCMP_ARCH_NATIVE; else if (streq(n, "x86")) *ret = SCMP_ARCH_X86; else if (streq(n, "x86-64")) *ret = SCMP_ARCH_X86_64; else if (streq(n, "x32")) *ret = SCMP_ARCH_X32; else if (streq(n, "arm")) *ret = SCMP_ARCH_ARM; else return -EINVAL; return 0; } int seccomp_add_secondary_archs(scmp_filter_ctx *c) { #if defined(__i386__) || defined(__x86_64__) int r; /* Add in all possible secondary archs we are aware of that * this kernel might support. */ r = seccomp_arch_add(c, SCMP_ARCH_X86); if (r < 0 && r != -EEXIST) return r; r = seccomp_arch_add(c, SCMP_ARCH_X86_64); if (r < 0 && r != -EEXIST) return r; r = seccomp_arch_add(c, SCMP_ARCH_X32); if (r < 0 && r != -EEXIST) return r; #endif return 0; } systemd-229/src/shared/seccomp-util.h000066400000000000000000000016511265713322000176760ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include const char* seccomp_arch_to_string(uint32_t c); int seccomp_arch_from_string(const char *n, uint32_t *ret); int seccomp_add_secondary_archs(scmp_filter_ctx *c); systemd-229/src/shared/sleep-config.c000066400000000000000000000211751265713322000176430ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "alloc-util.h" #include "conf-parser.h" #include "def.h" #include "fd-util.h" #include "fileio.h" #include "log.h" #include "macro.h" #include "parse-util.h" #include "sleep-config.h" #include "string-util.h" #include "strv.h" #define USE(x, y) do{ (x) = (y); (y) = NULL; } while(0) int parse_sleep_config(const char *verb, char ***_modes, char ***_states) { _cleanup_strv_free_ char **suspend_mode = NULL, **suspend_state = NULL, **hibernate_mode = NULL, **hibernate_state = NULL, **hybrid_mode = NULL, **hybrid_state = NULL; char **modes, **states; const ConfigTableItem items[] = { { "Sleep", "SuspendMode", config_parse_strv, 0, &suspend_mode }, { "Sleep", "SuspendState", config_parse_strv, 0, &suspend_state }, { "Sleep", "HibernateMode", config_parse_strv, 0, &hibernate_mode }, { "Sleep", "HibernateState", config_parse_strv, 0, &hibernate_state }, { "Sleep", "HybridSleepMode", config_parse_strv, 0, &hybrid_mode }, { "Sleep", "HybridSleepState", config_parse_strv, 0, &hybrid_state }, {} }; config_parse_many(PKGSYSCONFDIR "/sleep.conf", CONF_PATHS_NULSTR("systemd/sleep.conf.d"), "Sleep\0", config_item_table_lookup, items, false, NULL); if (streq(verb, "suspend")) { /* empty by default */ USE(modes, suspend_mode); if (suspend_state) USE(states, suspend_state); else states = strv_new("mem", "standby", "freeze", NULL); } else if (streq(verb, "hibernate")) { if (hibernate_mode) USE(modes, hibernate_mode); else modes = strv_new("platform", "shutdown", NULL); if (hibernate_state) USE(states, hibernate_state); else states = strv_new("disk", NULL); } else if (streq(verb, "hybrid-sleep")) { if (hybrid_mode) USE(modes, hybrid_mode); else modes = strv_new("suspend", "platform", "shutdown", NULL); if (hybrid_state) USE(states, hybrid_state); else states = strv_new("disk", NULL); } else assert_not_reached("what verb"); if ((!modes && !streq(verb, "suspend")) || !states) { strv_free(modes); strv_free(states); return log_oom(); } *_modes = modes; *_states = states; return 0; } int can_sleep_state(char **types) { char **type; int r; _cleanup_free_ char *p = NULL; if (strv_isempty(types)) return true; /* If /sys is read-only we cannot sleep */ if (access("/sys/power/state", W_OK) < 0) return false; r = read_one_line_file("/sys/power/state", &p); if (r < 0) return false; STRV_FOREACH(type, types) { const char *word, *state; size_t l, k; k = strlen(*type); FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state) if (l == k && memcmp(word, *type, l) == 0) return true; } return false; } int can_sleep_disk(char **types) { char **type; int r; _cleanup_free_ char *p = NULL; if (strv_isempty(types)) return true; /* If /sys is read-only we cannot sleep */ if (access("/sys/power/disk", W_OK) < 0) return false; r = read_one_line_file("/sys/power/disk", &p); if (r < 0) return false; STRV_FOREACH(type, types) { const char *word, *state; size_t l, k; k = strlen(*type); FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state) { if (l == k && memcmp(word, *type, l) == 0) return true; if (l == k + 2 && word[0] == '[' && memcmp(word + 1, *type, l - 2) == 0 && word[l-1] == ']') return true; } } return false; } #define HIBERNATION_SWAP_THRESHOLD 0.98 static int hibernation_partition_size(size_t *size, size_t *used) { _cleanup_fclose_ FILE *f; unsigned i; assert(size); assert(used); f = fopen("/proc/swaps", "re"); if (!f) { log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to retrieve open /proc/swaps: %m"); assert(errno > 0); return -errno; } (void) fscanf(f, "%*s %*s %*s %*s %*s\n"); for (i = 1;; i++) { _cleanup_free_ char *dev = NULL, *type = NULL; size_t size_field, used_field; int k; k = fscanf(f, "%ms " /* device/file */ "%ms " /* type of swap */ "%zu " /* swap size */ "%zu " /* used */ "%*i\n", /* priority */ &dev, &type, &size_field, &used_field); if (k != 4) { if (k == EOF) break; log_warning("Failed to parse /proc/swaps:%u", i); continue; } if (streq(type, "partition") && endswith(dev, "\\040(deleted)")) { log_warning("Ignoring deleted swapfile '%s'.", dev); continue; } *size = size_field; *used = used_field; return 0; } log_debug("No swap partitions were found."); return -ENOSYS; } static bool enough_memory_for_hibernation(void) { _cleanup_free_ char *active = NULL; unsigned long long act = 0; size_t size = 0, used = 0; int r; r = hibernation_partition_size(&size, &used); if (r < 0) return false; r = get_proc_field("/proc/meminfo", "Active(anon)", WHITESPACE, &active); if (r < 0) { log_error_errno(r, "Failed to retrieve Active(anon) from /proc/meminfo: %m"); return false; } r = safe_atollu(active, &act); if (r < 0) { log_error_errno(r, "Failed to parse Active(anon) from /proc/meminfo: %s: %m", active); return false; } r = act <= (size - used) * HIBERNATION_SWAP_THRESHOLD; log_debug("Hibernation is %spossible, Active(anon)=%llu kB, size=%zu kB, used=%zu kB, threshold=%.2g%%", r ? "" : "im", act, size, used, 100*HIBERNATION_SWAP_THRESHOLD); return r; } int can_sleep(const char *verb) { _cleanup_strv_free_ char **modes = NULL, **states = NULL; int r; assert(streq(verb, "suspend") || streq(verb, "hibernate") || streq(verb, "hybrid-sleep")); r = parse_sleep_config(verb, &modes, &states); if (r < 0) return false; if (!can_sleep_state(states) || !can_sleep_disk(modes)) return false; return streq(verb, "suspend") || enough_memory_for_hibernation(); } systemd-229/src/shared/sleep-config.h000066400000000000000000000016271265713322000176500ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once int parse_sleep_config(const char *verb, char ***modes, char ***states); int can_sleep(const char *verb); int can_sleep_disk(char **types); int can_sleep_state(char **types); systemd-229/src/shared/spawn-ask-password-agent.c000066400000000000000000000034301265713322000221220ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "log.h" #include "process-util.h" #include "spawn-ask-password-agent.h" #include "util.h" static pid_t agent_pid = 0; int ask_password_agent_open(void) { int r; if (agent_pid > 0) return 0; /* We check STDIN here, not STDOUT, since this is about input, * not output */ if (!isatty(STDIN_FILENO)) return 0; r = fork_agent(&agent_pid, NULL, 0, SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, "--watch", NULL); if (r < 0) return log_error_errno(r, "Failed to fork TTY ask password agent: %m"); return 1; } void ask_password_agent_close(void) { if (agent_pid <= 0) return; /* Inform agent that we are done */ (void) kill(agent_pid, SIGTERM); (void) kill(agent_pid, SIGCONT); (void) wait_for_terminate(agent_pid, NULL); agent_pid = 0; } systemd-229/src/shared/spawn-ask-password-agent.h000066400000000000000000000014451265713322000221330ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int ask_password_agent_open(void); void ask_password_agent_close(void); systemd-229/src/shared/spawn-polkit-agent.c000066400000000000000000000047431265713322000210160ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "fd-util.h" #include "io-util.h" #include "log.h" #include "macro.h" #include "process-util.h" #include "spawn-polkit-agent.h" #include "stdio-util.h" #include "time-util.h" #include "util.h" #ifdef ENABLE_POLKIT static pid_t agent_pid = 0; int polkit_agent_open(void) { int r; int pipe_fd[2]; char notify_fd[DECIMAL_STR_MAX(int) + 1]; if (agent_pid > 0) return 0; /* We check STDIN here, not STDOUT, since this is about input, * not output */ if (!isatty(STDIN_FILENO)) return 0; if (pipe2(pipe_fd, 0) < 0) return -errno; xsprintf(notify_fd, "%i", pipe_fd[1]); r = fork_agent(&agent_pid, &pipe_fd[1], 1, POLKIT_AGENT_BINARY_PATH, POLKIT_AGENT_BINARY_PATH, "--notify-fd", notify_fd, "--fallback", NULL); /* Close the writing side, because that's the one for the agent */ safe_close(pipe_fd[1]); if (r < 0) log_error_errno(r, "Failed to fork TTY ask password agent: %m"); else /* Wait until the agent closes the fd */ fd_wait_for_event(pipe_fd[0], POLLHUP, USEC_INFINITY); safe_close(pipe_fd[0]); return r; } void polkit_agent_close(void) { if (agent_pid <= 0) return; /* Inform agent that we are done */ (void) kill(agent_pid, SIGTERM); (void) kill(agent_pid, SIGCONT); (void) wait_for_terminate(agent_pid, NULL); agent_pid = 0; } #else int polkit_agent_open(void) { return 0; } void polkit_agent_close(void) { } #endif systemd-229/src/shared/spawn-polkit-agent.h000066400000000000000000000014311265713322000210120ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int polkit_agent_open(void); void polkit_agent_close(void); systemd-229/src/shared/specifier.c000066400000000000000000000120171265713322000172340ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "sd-id128.h" #include "alloc-util.h" #include "hostname-util.h" #include "macro.h" #include "specifier.h" #include "string-util.h" /* * Generic infrastructure for replacing %x style specifiers in * strings. Will call a callback for each replacement. * */ int specifier_printf(const char *text, const Specifier table[], void *userdata, char **_ret) { char *ret, *t; const char *f; bool percent = false; size_t l; int r; assert(text); assert(table); l = strlen(text); ret = new(char, l+1); if (!ret) return -ENOMEM; t = ret; for (f = text; *f; f++, l--) { if (percent) { if (*f == '%') *(t++) = '%'; else { const Specifier *i; for (i = table; i->specifier; i++) if (i->specifier == *f) break; if (i->lookup) { _cleanup_free_ char *w = NULL; char *n; size_t k, j; r = i->lookup(i->specifier, i->data, userdata, &w); if (r < 0) { free(ret); return r; } j = t - ret; k = strlen(w); n = new(char, j + k + l + 1); if (!n) { free(ret); return -ENOMEM; } memcpy(n, ret, j); memcpy(n + j, w, k); free(ret); ret = n; t = n + j + k; } else { *(t++) = '%'; *(t++) = *f; } } percent = false; } else if (*f == '%') percent = true; else *(t++) = *f; } *t = 0; *_ret = ret; return 0; } /* Generic handler for simple string replacements */ int specifier_string(char specifier, void *data, void *userdata, char **ret) { char *n; n = strdup(strempty(data)); if (!n) return -ENOMEM; *ret = n; return 0; } int specifier_machine_id(char specifier, void *data, void *userdata, char **ret) { sd_id128_t id; char *n; int r; r = sd_id128_get_machine(&id); if (r < 0) return r; n = new(char, 33); if (!n) return -ENOMEM; *ret = sd_id128_to_string(id, n); return 0; } int specifier_boot_id(char specifier, void *data, void *userdata, char **ret) { sd_id128_t id; char *n; int r; r = sd_id128_get_boot(&id); if (r < 0) return r; n = new(char, 33); if (!n) return -ENOMEM; *ret = sd_id128_to_string(id, n); return 0; } int specifier_host_name(char specifier, void *data, void *userdata, char **ret) { char *n; n = gethostname_malloc(); if (!n) return -ENOMEM; *ret = n; return 0; } int specifier_kernel_release(char specifier, void *data, void *userdata, char **ret) { struct utsname uts; char *n; int r; r = uname(&uts); if (r < 0) return -errno; n = strdup(uts.release); if (!n) return -ENOMEM; *ret = n; return 0; } systemd-229/src/shared/specifier.h000066400000000000000000000026601265713322000172440ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ typedef int (*SpecifierCallback)(char specifier, void *data, void *userdata, char **ret); typedef struct Specifier { const char specifier; const SpecifierCallback lookup; void *data; } Specifier; int specifier_printf(const char *text, const Specifier table[], void *userdata, char **ret); int specifier_string(char specifier, void *data, void *userdata, char **ret); int specifier_machine_id(char specifier, void *data, void *userdata, char **ret); int specifier_boot_id(char specifier, void *data, void *userdata, char **ret); int specifier_host_name(char specifier, void *data, void *userdata, char **ret); int specifier_kernel_release(char specifier, void *data, void *userdata, char **ret); systemd-229/src/shared/switch-root.c000066400000000000000000000136101265713322000175450ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Harald Hoyer, Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "base-filesystem.h" #include "fd-util.h" #include "log.h" #include "missing.h" #include "mkdir.h" #include "path-util.h" #include "rm-rf.h" #include "stdio-util.h" #include "string-util.h" #include "switch-root.h" #include "user-util.h" #include "util.h" int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot, unsigned long mountflags) { /* Don't try to unmount/move the old "/", there's no way to do it. */ static const char move_mounts[] = "/dev\0" "/proc\0" "/sys\0" "/run\0"; _cleanup_close_ int old_root_fd = -1; struct stat new_root_stat; bool old_root_remove; const char *i, *temporary_old_root; if (path_equal(new_root, "/")) return 0; temporary_old_root = strjoina(new_root, oldroot); mkdir_p_label(temporary_old_root, 0755); old_root_remove = in_initrd(); if (stat(new_root, &new_root_stat) < 0) return log_error_errno(errno, "Failed to stat directory %s: %m", new_root); /* Work-around for kernel design: the kernel refuses switching * root if any file systems are mounted MS_SHARED. Hence * remount them MS_PRIVATE here as a work-around. * * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */ if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0) log_warning_errno(errno, "Failed to make \"/\" private mount: %m"); NULSTR_FOREACH(i, move_mounts) { char new_mount[PATH_MAX]; struct stat sb; xsprintf(new_mount, "%s%s", new_root, i); mkdir_p_label(new_mount, 0755); if ((stat(new_mount, &sb) < 0) || sb.st_dev != new_root_stat.st_dev) { /* Mount point seems to be mounted already or * stat failed. Unmount the old mount * point. */ if (umount2(i, MNT_DETACH) < 0) log_warning_errno(errno, "Failed to unmount %s: %m", i); continue; } if (mount(i, new_mount, NULL, mountflags, NULL) < 0) { if (mountflags & MS_MOVE) { log_error_errno(errno, "Failed to move mount %s to %s, forcing unmount: %m", i, new_mount); if (umount2(i, MNT_FORCE) < 0) log_warning_errno(errno, "Failed to unmount %s: %m", i); } if (mountflags & MS_BIND) log_error_errno(errno, "Failed to bind mount %s to %s: %m", i, new_mount); } } /* Do not fail, if base_filesystem_create() fails. Not all * switch roots are like base_filesystem_create() wants them * to look like. They might even boot, if they are RO and * don't have the FS layout. Just ignore the error and * switch_root() nevertheless. */ (void) base_filesystem_create(new_root, UID_INVALID, GID_INVALID); if (chdir(new_root) < 0) return log_error_errno(errno, "Failed to change directory to %s: %m", new_root); if (old_root_remove) { old_root_fd = open("/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY|O_DIRECTORY); if (old_root_fd < 0) log_warning_errno(errno, "Failed to open root directory: %m"); } /* We first try a pivot_root() so that we can umount the old * root dir. In many cases (i.e. where rootfs is /), that's * not possible however, and hence we simply overmount root */ if (pivot_root(new_root, temporary_old_root) >= 0) { /* Immediately get rid of the old root, if detach_oldroot is set. * Since we are running off it we need to do this lazily. */ if (detach_oldroot && umount2(oldroot, MNT_DETACH) < 0) log_error_errno(errno, "Failed to lazily umount old root dir %s, %s: %m", oldroot, errno == ENOENT ? "ignoring" : "leaving it around"); } else if (mount(new_root, "/", NULL, MS_MOVE, NULL) < 0) return log_error_errno(errno, "Failed to mount moving %s to /: %m", new_root); if (chroot(".") < 0) return log_error_errno(errno, "Failed to change root: %m"); if (chdir("/") < 0) return log_error_errno(errno, "Failed to change directory: %m"); if (old_root_fd >= 0) { struct stat rb; if (fstat(old_root_fd, &rb) < 0) log_warning_errno(errno, "Failed to stat old root directory, leaving: %m"); else { (void) rm_rf_children(old_root_fd, 0, &rb); old_root_fd = -1; } } return 0; } systemd-229/src/shared/switch-root.h000066400000000000000000000015531265713322000175550ustar00rootroot00000000000000#pragma once #include /*** This file is part of systemd. Copyright 2012 Harald Hoyer, Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot, unsigned long mountflags); systemd-229/src/shared/sysctl-util.c000066400000000000000000000036631265713322000175660ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "fileio.h" #include "log.h" #include "macro.h" #include "string-util.h" #include "sysctl-util.h" char *sysctl_normalize(char *s) { char *n; n = strpbrk(s, "/."); /* If the first separator is a slash, the path is * assumed to be normalized and slashes remain slashes * and dots remains dots. */ if (!n || *n == '/') return s; /* Otherwise, dots become slashes and slashes become * dots. Fun. */ while (n) { if (*n == '.') *n = '/'; else *n = '.'; n = strpbrk(n + 1, "/."); } return s; } int sysctl_write(const char *property, const char *value) { char *p; assert(property); assert(value); log_debug("Setting '%s' to '%s'", property, value); p = strjoina("/proc/sys/", property); return write_string_file(p, value, 0); } int sysctl_read(const char *property, char **content) { char *p; assert(property); assert(content); p = strjoina("/proc/sys/", property); return read_full_file(p, content, NULL); } systemd-229/src/shared/sysctl-util.h000066400000000000000000000015571265713322000175730ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ char *sysctl_normalize(char *s); int sysctl_read(const char *property, char **value); int sysctl_write(const char *property, const char *value); systemd-229/src/shared/test-tables.h000066400000000000000000000042201265713322000175140ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include typedef const char* (*lookup_t)(int); typedef int (*reverse_t)(const char*); static inline void _test_table(const char *name, lookup_t lookup, reverse_t reverse, int size, bool sparse) { int i, boring = 0; for (i = -1; i < size + 1; i++) { const char* val = lookup(i); int rev; if (val) { rev = reverse(val); boring = 0; } else { rev = reverse("--no-such--value----"); boring += i >= 0; } if (boring < 1 || i == size) printf("%s: %d → %s → %d\n", name, i, val, rev); else if (boring == 1) printf("%*s ...\n", (int) strlen(name), ""); assert_se(!(i >= 0 && i < size ? sparse ? rev != i && rev != -1 : val == NULL || rev != i : val != NULL || rev != -1)); } } #define test_table(lower, upper) \ _test_table(STRINGIFY(lower), lower##_to_string, lower##_from_string, _##upper##_MAX, false) #define test_table_sparse(lower, upper) \ _test_table(STRINGIFY(lower), lower##_to_string, lower##_from_string, _##upper##_MAX, true) systemd-229/src/shared/udev-util.h000066400000000000000000000040351265713322000172070ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "udev.h" #include "util.h" DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev*, udev_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_device*, udev_device_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_enumerate*, udev_enumerate_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_event*, udev_event_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_rules*, udev_rules_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl*, udev_ctrl_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_connection*, udev_ctrl_connection_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_msg*, udev_ctrl_msg_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_monitor*, udev_monitor_unref); #define _cleanup_udev_unref_ _cleanup_(udev_unrefp) #define _cleanup_udev_device_unref_ _cleanup_(udev_device_unrefp) #define _cleanup_udev_enumerate_unref_ _cleanup_(udev_enumerate_unrefp) #define _cleanup_udev_event_unref_ _cleanup_(udev_event_unrefp) #define _cleanup_udev_rules_unref_ _cleanup_(udev_rules_unrefp) #define _cleanup_udev_ctrl_unref_ _cleanup_(udev_ctrl_unrefp) #define _cleanup_udev_ctrl_connection_unref_ _cleanup_(udev_ctrl_connection_unrefp) #define _cleanup_udev_ctrl_msg_unref_ _cleanup_(udev_ctrl_msg_unrefp) #define _cleanup_udev_monitor_unref_ _cleanup_(udev_monitor_unrefp) #define _cleanup_udev_list_cleanup_ _cleanup_(udev_list_cleanup) systemd-229/src/shared/uid-range.c000066400000000000000000000122251265713322000171370ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "macro.h" #include "uid-range.h" #include "user-util.h" static bool uid_range_intersect(UidRange *range, uid_t start, uid_t nr) { assert(range); return range->start <= start + nr && range->start + range->nr >= start; } static void uid_range_coalesce(UidRange **p, unsigned *n) { unsigned i, j; assert(p); assert(n); for (i = 0; i < *n; i++) { for (j = i + 1; j < *n; j++) { UidRange *x = (*p)+i, *y = (*p)+j; if (uid_range_intersect(x, y->start, y->nr)) { uid_t begin, end; begin = MIN(x->start, y->start); end = MAX(x->start + x->nr, y->start + y->nr); x->start = begin; x->nr = end - begin; if (*n > j+1) memmove(y, y+1, sizeof(UidRange) * (*n - j -1)); (*n) --; j--; } } } } static int uid_range_compare(const void *a, const void *b) { const UidRange *x = a, *y = b; if (x->start < y->start) return -1; if (x->start > y->start) return 1; if (x->nr < y->nr) return -1; if (x->nr > y->nr) return 1; return 0; } int uid_range_add(UidRange **p, unsigned *n, uid_t start, uid_t nr) { bool found = false; UidRange *x; unsigned i; assert(p); assert(n); if (nr <= 0) return 0; for (i = 0; i < *n; i++) { x = (*p) + i; if (uid_range_intersect(x, start, nr)) { found = true; break; } } if (found) { uid_t begin, end; begin = MIN(x->start, start); end = MAX(x->start + x->nr, start + nr); x->start = begin; x->nr = end - begin; } else { UidRange *t; t = realloc(*p, sizeof(UidRange) * (*n + 1)); if (!t) return -ENOMEM; *p = t; x = t + ((*n) ++); x->start = start; x->nr = nr; } qsort(*p, *n, sizeof(UidRange), uid_range_compare); uid_range_coalesce(p, n); return *n; } int uid_range_add_str(UidRange **p, unsigned *n, const char *s) { uid_t start, nr; const char *t; int r; assert(p); assert(n); assert(s); t = strchr(s, '-'); if (t) { char *b; uid_t end; b = strndupa(s, t - s); r = parse_uid(b, &start); if (r < 0) return r; r = parse_uid(t+1, &end); if (r < 0) return r; if (end < start) return -EINVAL; nr = end - start + 1; } else { r = parse_uid(s, &start); if (r < 0) return r; nr = 1; } return uid_range_add(p, n, start, nr); } int uid_range_next_lower(const UidRange *p, unsigned n, uid_t *uid) { uid_t closest = UID_INVALID, candidate; unsigned i; assert(p); assert(uid); candidate = *uid - 1; for (i = 0; i < n; i++) { uid_t begin, end; begin = p[i].start; end = p[i].start + p[i].nr - 1; if (candidate >= begin && candidate <= end) { *uid = candidate; return 1; } if (end < candidate) closest = end; } if (closest == UID_INVALID) return -EBUSY; *uid = closest; return 1; } bool uid_range_contains(const UidRange *p, unsigned n, uid_t uid) { unsigned i; assert(p); assert(uid); for (i = 0; i < n; i++) if (uid >= p[i].start && uid < p[i].start + p[i].nr) return true; return false; } systemd-229/src/shared/uid-range.h000066400000000000000000000021311265713322000171370ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include typedef struct UidRange { uid_t start, nr; } UidRange; int uid_range_add(UidRange **p, unsigned *n, uid_t start, uid_t nr); int uid_range_add_str(UidRange **p, unsigned *n, const char *s); int uid_range_next_lower(const UidRange *p, unsigned n, uid_t *uid); bool uid_range_contains(const UidRange *p, unsigned n, uid_t uid); systemd-229/src/shared/utmp-wtmp.c000066400000000000000000000271651265713322000172470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "hostname-util.h" #include "macro.h" #include "path-util.h" #include "string-util.h" #include "terminal-util.h" #include "time-util.h" #include "user-util.h" #include "util.h" #include "utmp-wtmp.h" int utmp_get_runlevel(int *runlevel, int *previous) { struct utmpx *found, lookup = { .ut_type = RUN_LVL }; int r; const char *e; assert(runlevel); /* If these values are set in the environment this takes * precedence. Presumably, sysvinit does this to work around a * race condition that would otherwise exist where we'd always * go to disk and hence might read runlevel data that might be * very new and does not apply to the current script being * executed. */ e = getenv("RUNLEVEL"); if (e && e[0] > 0) { *runlevel = e[0]; if (previous) { /* $PREVLEVEL seems to be an Upstart thing */ e = getenv("PREVLEVEL"); if (e && e[0] > 0) *previous = e[0]; else *previous = 0; } return 0; } if (utmpxname(_PATH_UTMPX) < 0) return -errno; setutxent(); found = getutxid(&lookup); if (!found) r = -errno; else { int a, b; a = found->ut_pid & 0xFF; b = (found->ut_pid >> 8) & 0xFF; *runlevel = a; if (previous) *previous = b; r = 0; } endutxent(); return r; } static void init_timestamp(struct utmpx *store, usec_t t) { assert(store); if (t <= 0) t = now(CLOCK_REALTIME); store->ut_tv.tv_sec = t / USEC_PER_SEC; store->ut_tv.tv_usec = t % USEC_PER_SEC; } static void init_entry(struct utmpx *store, usec_t t) { struct utsname uts = {}; assert(store); init_timestamp(store, t); if (uname(&uts) >= 0) strncpy(store->ut_host, uts.release, sizeof(store->ut_host)); strncpy(store->ut_line, "~", sizeof(store->ut_line)); /* or ~~ ? */ strncpy(store->ut_id, "~~", sizeof(store->ut_id)); } static int write_entry_utmp(const struct utmpx *store) { int r; assert(store); /* utmp is similar to wtmp, but there is only one entry for * each entry type resp. user; i.e. basically a key/value * table. */ if (utmpxname(_PATH_UTMPX) < 0) return -errno; setutxent(); if (!pututxline(store)) r = -errno; else r = 0; endutxent(); return r; } static int write_entry_wtmp(const struct utmpx *store) { assert(store); /* wtmp is a simple append-only file where each entry is simply appended to the end; i.e. basically a log. */ errno = 0; updwtmpx(_PATH_WTMPX, store); return -errno; } static int write_utmp_wtmp(const struct utmpx *store_utmp, const struct utmpx *store_wtmp) { int r, s; r = write_entry_utmp(store_utmp); s = write_entry_wtmp(store_wtmp); if (r >= 0) r = s; /* If utmp/wtmp have been disabled, that's a good thing, hence * ignore the errors */ if (r == -ENOENT) r = 0; return r; } static int write_entry_both(const struct utmpx *store) { return write_utmp_wtmp(store, store); } int utmp_put_shutdown(void) { struct utmpx store = {}; init_entry(&store, 0); store.ut_type = RUN_LVL; strncpy(store.ut_user, "shutdown", sizeof(store.ut_user)); return write_entry_both(&store); } int utmp_put_reboot(usec_t t) { struct utmpx store = {}; init_entry(&store, t); store.ut_type = BOOT_TIME; strncpy(store.ut_user, "reboot", sizeof(store.ut_user)); return write_entry_both(&store); } _pure_ static const char *sanitize_id(const char *id) { size_t l; assert(id); l = strlen(id); if (l <= sizeof(((struct utmpx*) NULL)->ut_id)) return id; return id + l - sizeof(((struct utmpx*) NULL)->ut_id); } int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user) { struct utmpx store = { .ut_type = INIT_PROCESS, .ut_pid = pid, .ut_session = sid, }; int r; assert(id); init_timestamp(&store, 0); /* ut_id needs only be nul-terminated if it is shorter than sizeof(ut_id) */ strncpy(store.ut_id, sanitize_id(id), sizeof(store.ut_id)); if (line) strncpy(store.ut_line, basename(line), sizeof(store.ut_line)); r = write_entry_both(&store); if (r < 0) return r; if (ut_type == LOGIN_PROCESS || ut_type == USER_PROCESS) { store.ut_type = LOGIN_PROCESS; r = write_entry_both(&store); if (r < 0) return r; } if (ut_type == USER_PROCESS) { store.ut_type = USER_PROCESS; strncpy(store.ut_user, user, sizeof(store.ut_user)-1); r = write_entry_both(&store); if (r < 0) return r; } return 0; } int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) { struct utmpx lookup = { .ut_type = INIT_PROCESS /* looks for DEAD_PROCESS, LOGIN_PROCESS, USER_PROCESS, too */ }, store, store_wtmp, *found; assert(id); setutxent(); /* ut_id needs only be nul-terminated if it is shorter than sizeof(ut_id) */ strncpy(lookup.ut_id, sanitize_id(id), sizeof(lookup.ut_id)); found = getutxid(&lookup); if (!found) return 0; if (found->ut_pid != pid) return 0; memcpy(&store, found, sizeof(store)); store.ut_type = DEAD_PROCESS; store.ut_exit.e_termination = code; store.ut_exit.e_exit = status; zero(store.ut_user); zero(store.ut_host); zero(store.ut_tv); memcpy(&store_wtmp, &store, sizeof(store_wtmp)); /* wtmp wants the current time */ init_timestamp(&store_wtmp, 0); return write_utmp_wtmp(&store, &store_wtmp); } int utmp_put_runlevel(int runlevel, int previous) { struct utmpx store = {}; int r; assert(runlevel > 0); if (previous <= 0) { /* Find the old runlevel automatically */ r = utmp_get_runlevel(&previous, NULL); if (r < 0) { if (r != -ESRCH) return r; previous = 0; } } if (previous == runlevel) return 0; init_entry(&store, 0); store.ut_type = RUN_LVL; store.ut_pid = (runlevel & 0xFF) | ((previous & 0xFF) << 8); strncpy(store.ut_user, "runlevel", sizeof(store.ut_user)); return write_entry_both(&store); } #define TIMEOUT_MSEC 50 static int write_to_terminal(const char *tty, const char *message) { _cleanup_close_ int fd = -1; const char *p; size_t left; usec_t end; assert(tty); assert(message); fd = open(tty, O_WRONLY|O_NDELAY|O_NOCTTY|O_CLOEXEC); if (fd < 0 || !isatty(fd)) return -errno; p = message; left = strlen(message); end = now(CLOCK_MONOTONIC) + TIMEOUT_MSEC*USEC_PER_MSEC; while (left > 0) { ssize_t n; struct pollfd pollfd = { .fd = fd, .events = POLLOUT, }; usec_t t; int k; t = now(CLOCK_MONOTONIC); if (t >= end) return -ETIME; k = poll(&pollfd, 1, (end - t) / USEC_PER_MSEC); if (k < 0) return -errno; if (k == 0) return -ETIME; n = write(fd, p, left); if (n < 0) { if (errno == EAGAIN) continue; return -errno; } assert((size_t) n <= left); p += n; left -= n; } return 0; } int utmp_wall( const char *message, const char *username, const char *origin_tty, bool (*match_tty)(const char *tty, void *userdata), void *userdata) { _cleanup_free_ char *text = NULL, *hn = NULL, *un = NULL, *stdin_tty = NULL; char date[FORMAT_TIMESTAMP_MAX]; struct utmpx *u; int r; hn = gethostname_malloc(); if (!hn) return -ENOMEM; if (!username) { un = getlogname_malloc(); if (!un) return -ENOMEM; } if (!origin_tty) { getttyname_harder(STDIN_FILENO, &stdin_tty); origin_tty = stdin_tty; } if (asprintf(&text, "\a\r\n" "Broadcast message from %s@%s%s%s (%s):\r\n\r\n" "%s\r\n\r\n", un ?: username, hn, origin_tty ? " on " : "", strempty(origin_tty), format_timestamp(date, sizeof(date), now(CLOCK_REALTIME)), message) < 0) return -ENOMEM; setutxent(); r = 0; while ((u = getutxent())) { _cleanup_free_ char *buf = NULL; const char *path; int q; if (u->ut_type != USER_PROCESS || u->ut_user[0] == 0) continue; /* this access is fine, because strlen("/dev/") << 32 (UT_LINESIZE) */ if (path_startswith(u->ut_line, "/dev/")) path = u->ut_line; else { if (asprintf(&buf, "/dev/%.*s", (int) sizeof(u->ut_line), u->ut_line) < 0) return -ENOMEM; path = buf; } if (!match_tty || match_tty(path, userdata)) { q = write_to_terminal(path, text); if (q < 0) r = q; } } return r; } systemd-229/src/shared/utmp-wtmp.h000066400000000000000000000043541265713322000172470ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "time-util.h" #include "util.h" #ifdef HAVE_UTMP int utmp_get_runlevel(int *runlevel, int *previous); int utmp_put_shutdown(void); int utmp_put_reboot(usec_t timestamp); int utmp_put_runlevel(int runlevel, int previous); int utmp_put_dead_process(const char *id, pid_t pid, int code, int status); int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user); int utmp_wall( const char *message, const char *username, const char *origin_tty, bool (*match_tty)(const char *tty, void *userdata), void *userdata); #else /* HAVE_UTMP */ static inline int utmp_get_runlevel(int *runlevel, int *previous) { return -ESRCH; } static inline int utmp_put_shutdown(void) { return 0; } static inline int utmp_put_reboot(usec_t timestamp) { return 0; } static inline int utmp_put_runlevel(int runlevel, int previous) { return 0; } static inline int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) { return 0; } static inline int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user) { return 0; } static inline int utmp_wall( const char *message, const char *username, const char *origin_tty, bool (*match_tty)(const char *tty, void *userdata), void *userdata) { return 0; } #endif /* HAVE_UTMP */ systemd-229/src/shared/watchdog.c000066400000000000000000000117001265713322000170610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "fd-util.h" #include "log.h" #include "time-util.h" #include "watchdog.h" static int watchdog_fd = -1; static usec_t watchdog_timeout = USEC_INFINITY; static int update_timeout(void) { int r; if (watchdog_fd < 0) return 0; if (watchdog_timeout == USEC_INFINITY) return 0; else if (watchdog_timeout == 0) { int flags; flags = WDIOS_DISABLECARD; r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags); if (r < 0) return log_warning_errno(errno, "Failed to disable hardware watchdog: %m"); } else { int sec, flags; char buf[FORMAT_TIMESPAN_MAX]; sec = (int) ((watchdog_timeout + USEC_PER_SEC - 1) / USEC_PER_SEC); r = ioctl(watchdog_fd, WDIOC_SETTIMEOUT, &sec); if (r < 0) return log_warning_errno(errno, "Failed to set timeout to %is: %m", sec); watchdog_timeout = (usec_t) sec * USEC_PER_SEC; log_info("Set hardware watchdog to %s.", format_timespan(buf, sizeof(buf), watchdog_timeout, 0)); flags = WDIOS_ENABLECARD; r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags); if (r < 0) { /* ENOTTY means the watchdog is always enabled so we're fine */ log_full(errno == ENOTTY ? LOG_DEBUG : LOG_WARNING, "Failed to enable hardware watchdog: %m"); if (errno != ENOTTY) return -errno; } r = ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0); if (r < 0) return log_warning_errno(errno, "Failed to ping hardware watchdog: %m"); } return 0; } static int open_watchdog(void) { struct watchdog_info ident; if (watchdog_fd >= 0) return 0; watchdog_fd = open("/dev/watchdog", O_WRONLY|O_CLOEXEC); if (watchdog_fd < 0) return -errno; if (ioctl(watchdog_fd, WDIOC_GETSUPPORT, &ident) >= 0) log_info("Hardware watchdog '%s', version %x", ident.identity, ident.firmware_version); return update_timeout(); } int watchdog_set_timeout(usec_t *usec) { int r; watchdog_timeout = *usec; /* If we didn't open the watchdog yet and didn't get any * explicit timeout value set, don't do anything */ if (watchdog_fd < 0 && watchdog_timeout == USEC_INFINITY) return 0; if (watchdog_fd < 0) r = open_watchdog(); else r = update_timeout(); *usec = watchdog_timeout; return r; } int watchdog_ping(void) { int r; if (watchdog_fd < 0) { r = open_watchdog(); if (r < 0) return r; } r = ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0); if (r < 0) return log_warning_errno(errno, "Failed to ping hardware watchdog: %m"); return 0; } void watchdog_close(bool disarm) { int r; if (watchdog_fd < 0) return; if (disarm) { int flags; /* Explicitly disarm it */ flags = WDIOS_DISABLECARD; r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags); if (r < 0) log_warning_errno(errno, "Failed to disable hardware watchdog: %m"); /* To be sure, use magic close logic, too */ for (;;) { static const char v = 'V'; if (write(watchdog_fd, &v, 1) > 0) break; if (errno != EINTR) { log_error_errno(errno, "Failed to disarm watchdog timer: %m"); break; } } } watchdog_fd = safe_close(watchdog_fd); } systemd-229/src/shared/watchdog.h000066400000000000000000000016001265713322000170640ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "time-util.h" #include "util.h" int watchdog_set_timeout(usec_t *usec); int watchdog_ping(void); void watchdog_close(bool disarm); systemd-229/src/sleep/000077500000000000000000000000001265713322000147605ustar00rootroot00000000000000systemd-229/src/sleep/Makefile000077700000000000000000000000001265713322000202662../Makefileustar00rootroot00000000000000systemd-229/src/sleep/sleep.c000066400000000000000000000140041265713322000162330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-messages.h" #include "def.h" #include "fd-util.h" #include "fileio.h" #include "log.h" #include "sleep-config.h" #include "string-util.h" #include "strv.h" #include "util.h" static char* arg_verb = NULL; static int write_mode(char **modes) { int r = 0; char **mode; STRV_FOREACH(mode, modes) { int k; k = write_string_file("/sys/power/disk", *mode, 0); if (k == 0) return 0; log_debug_errno(k, "Failed to write '%s' to /sys/power/disk: %m", *mode); if (r == 0) r = k; } if (r < 0) log_error_errno(r, "Failed to write mode to /sys/power/disk: %m"); return r; } static int write_state(FILE **f, char **states) { char **state; int r = 0; STRV_FOREACH(state, states) { int k; k = write_string_stream(*f, *state, true); if (k == 0) return 0; log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m", *state); if (r == 0) r = k; fclose(*f); *f = fopen("/sys/power/state", "we"); if (!*f) return log_error_errno(errno, "Failed to open /sys/power/state: %m"); } return r; } static int execute(char **modes, char **states) { char *arguments[] = { NULL, (char*) "pre", arg_verb, NULL }; static const char* const dirs[] = {SYSTEM_SLEEP_PATH, NULL}; int r; _cleanup_fclose_ FILE *f = NULL; /* This file is opened first, so that if we hit an error, * we can abort before modifying any state. */ f = fopen("/sys/power/state", "we"); if (!f) return log_error_errno(errno, "Failed to open /sys/power/state: %m"); /* Configure the hibernation mode */ r = write_mode(modes); if (r < 0) return r; execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments); log_struct(LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_START), LOG_MESSAGE("Suspending system..."), "SLEEP=%s", arg_verb, NULL); r = write_state(&f, states); if (r < 0) return r; log_struct(LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_STOP), LOG_MESSAGE("System resumed."), "SLEEP=%s", arg_verb, NULL); arguments[1] = (char*) "post"; execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments); return r; } static void help(void) { printf("%s COMMAND\n\n" "Suspend the system, hibernate the system, or both.\n\n" "Commands:\n" " -h --help Show this help and exit\n" " --version Print version string and exit\n" " suspend Suspend the system\n" " hibernate Hibernate the system\n" " hybrid-sleep Both hibernate and suspend the system\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch(c) { case 'h': help(); return 0; /* done */ case ARG_VERSION: return version(); case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (argc - optind != 1) { log_error("Usage: %s COMMAND", program_invocation_short_name); return -EINVAL; } arg_verb = argv[optind]; if (!streq(arg_verb, "suspend") && !streq(arg_verb, "hibernate") && !streq(arg_verb, "hybrid-sleep")) { log_error("Unknown command '%s'.", arg_verb); return -EINVAL; } return 1 /* work to do */; } int main(int argc, char *argv[]) { _cleanup_strv_free_ char **modes = NULL, **states = NULL; int r; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = parse_sleep_config(arg_verb, &modes, &states); if (r < 0) goto finish; r = execute(modes, states); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/socket-proxy/000077500000000000000000000000001265713322000163175ustar00rootroot00000000000000systemd-229/src/socket-proxy/Makefile000077700000000000000000000000001265713322000216252../Makefileustar00rootroot00000000000000systemd-229/src/socket-proxy/socket-proxyd.c000066400000000000000000000503361265713322000213050ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 David Strauss systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include "sd-daemon.h" #include "sd-event.h" #include "sd-resolve.h" #include "alloc-util.h" #include "fd-util.h" #include "log.h" #include "path-util.h" #include "set.h" #include "socket-util.h" #include "string-util.h" #include "util.h" #define BUFFER_SIZE (256 * 1024) #define CONNECTIONS_MAX 256 static const char *arg_remote_host = NULL; typedef struct Context { sd_event *event; sd_resolve *resolve; Set *listen; Set *connections; } Context; typedef struct Connection { Context *context; int server_fd, client_fd; int server_to_client_buffer[2]; /* a pipe */ int client_to_server_buffer[2]; /* a pipe */ size_t server_to_client_buffer_full, client_to_server_buffer_full; size_t server_to_client_buffer_size, client_to_server_buffer_size; sd_event_source *server_event_source, *client_event_source; sd_resolve_query *resolve_query; } Connection; static void connection_free(Connection *c) { assert(c); if (c->context) set_remove(c->context->connections, c); sd_event_source_unref(c->server_event_source); sd_event_source_unref(c->client_event_source); safe_close(c->server_fd); safe_close(c->client_fd); safe_close_pair(c->server_to_client_buffer); safe_close_pair(c->client_to_server_buffer); sd_resolve_query_unref(c->resolve_query); free(c); } static void context_free(Context *context) { sd_event_source *es; Connection *c; assert(context); while ((es = set_steal_first(context->listen))) sd_event_source_unref(es); while ((c = set_first(context->connections))) connection_free(c); set_free(context->listen); set_free(context->connections); sd_event_unref(context->event); sd_resolve_unref(context->resolve); } static int connection_create_pipes(Connection *c, int buffer[2], size_t *sz) { int r; assert(c); assert(buffer); assert(sz); if (buffer[0] >= 0) return 0; r = pipe2(buffer, O_CLOEXEC|O_NONBLOCK); if (r < 0) return log_error_errno(errno, "Failed to allocate pipe buffer: %m"); (void) fcntl(buffer[0], F_SETPIPE_SZ, BUFFER_SIZE); r = fcntl(buffer[0], F_GETPIPE_SZ); if (r < 0) return log_error_errno(errno, "Failed to get pipe buffer size: %m"); assert(r > 0); *sz = r; return 0; } static int connection_shovel( Connection *c, int *from, int buffer[2], int *to, size_t *full, size_t *sz, sd_event_source **from_source, sd_event_source **to_source) { bool shoveled; assert(c); assert(from); assert(buffer); assert(buffer[0] >= 0); assert(buffer[1] >= 0); assert(to); assert(full); assert(sz); assert(from_source); assert(to_source); do { ssize_t z; shoveled = false; if (*full < *sz && *from >= 0 && *to >= 0) { z = splice(*from, NULL, buffer[1], NULL, *sz - *full, SPLICE_F_MOVE|SPLICE_F_NONBLOCK); if (z > 0) { *full += z; shoveled = true; } else if (z == 0 || errno == EPIPE || errno == ECONNRESET) { *from_source = sd_event_source_unref(*from_source); *from = safe_close(*from); } else if (errno != EAGAIN && errno != EINTR) return log_error_errno(errno, "Failed to splice: %m"); } if (*full > 0 && *to >= 0) { z = splice(buffer[0], NULL, *to, NULL, *full, SPLICE_F_MOVE|SPLICE_F_NONBLOCK); if (z > 0) { *full -= z; shoveled = true; } else if (z == 0 || errno == EPIPE || errno == ECONNRESET) { *to_source = sd_event_source_unref(*to_source); *to = safe_close(*to); } else if (errno != EAGAIN && errno != EINTR) return log_error_errno(errno, "Failed to splice: %m"); } } while (shoveled); return 0; } static int connection_enable_event_sources(Connection *c); static int traffic_cb(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Connection *c = userdata; int r; assert(s); assert(fd >= 0); assert(c); r = connection_shovel(c, &c->server_fd, c->server_to_client_buffer, &c->client_fd, &c->server_to_client_buffer_full, &c->server_to_client_buffer_size, &c->server_event_source, &c->client_event_source); if (r < 0) goto quit; r = connection_shovel(c, &c->client_fd, c->client_to_server_buffer, &c->server_fd, &c->client_to_server_buffer_full, &c->client_to_server_buffer_size, &c->client_event_source, &c->server_event_source); if (r < 0) goto quit; /* EOF on both sides? */ if (c->server_fd == -1 && c->client_fd == -1) goto quit; /* Server closed, and all data written to client? */ if (c->server_fd == -1 && c->server_to_client_buffer_full <= 0) goto quit; /* Client closed, and all data written to server? */ if (c->client_fd == -1 && c->client_to_server_buffer_full <= 0) goto quit; r = connection_enable_event_sources(c); if (r < 0) goto quit; return 1; quit: connection_free(c); return 0; /* ignore errors, continue serving */ } static int connection_enable_event_sources(Connection *c) { uint32_t a = 0, b = 0; int r; assert(c); if (c->server_to_client_buffer_full > 0) b |= EPOLLOUT; if (c->server_to_client_buffer_full < c->server_to_client_buffer_size) a |= EPOLLIN; if (c->client_to_server_buffer_full > 0) a |= EPOLLOUT; if (c->client_to_server_buffer_full < c->client_to_server_buffer_size) b |= EPOLLIN; if (c->server_event_source) r = sd_event_source_set_io_events(c->server_event_source, a); else if (c->server_fd >= 0) r = sd_event_add_io(c->context->event, &c->server_event_source, c->server_fd, a, traffic_cb, c); else r = 0; if (r < 0) return log_error_errno(r, "Failed to set up server event source: %m"); if (c->client_event_source) r = sd_event_source_set_io_events(c->client_event_source, b); else if (c->client_fd >= 0) r = sd_event_add_io(c->context->event, &c->client_event_source, c->client_fd, b, traffic_cb, c); else r = 0; if (r < 0) return log_error_errno(r, "Failed to set up client event source: %m"); return 0; } static int connection_complete(Connection *c) { int r; assert(c); r = connection_create_pipes(c, c->server_to_client_buffer, &c->server_to_client_buffer_size); if (r < 0) goto fail; r = connection_create_pipes(c, c->client_to_server_buffer, &c->client_to_server_buffer_size); if (r < 0) goto fail; r = connection_enable_event_sources(c); if (r < 0) goto fail; return 0; fail: connection_free(c); return 0; /* ignore errors, continue serving */ } static int connect_cb(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Connection *c = userdata; socklen_t solen; int error, r; assert(s); assert(fd >= 0); assert(c); solen = sizeof(error); r = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &solen); if (r < 0) { log_error_errno(errno, "Failed to issue SO_ERROR: %m"); goto fail; } if (error != 0) { log_error_errno(error, "Failed to connect to remote host: %m"); goto fail; } c->client_event_source = sd_event_source_unref(c->client_event_source); return connection_complete(c); fail: connection_free(c); return 0; /* ignore errors, continue serving */ } static int connection_start(Connection *c, struct sockaddr *sa, socklen_t salen) { int r; assert(c); assert(sa); assert(salen); c->client_fd = socket(sa->sa_family, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); if (c->client_fd < 0) { log_error_errno(errno, "Failed to get remote socket: %m"); goto fail; } r = connect(c->client_fd, sa, salen); if (r < 0) { if (errno == EINPROGRESS) { r = sd_event_add_io(c->context->event, &c->client_event_source, c->client_fd, EPOLLOUT, connect_cb, c); if (r < 0) { log_error_errno(r, "Failed to add connection socket: %m"); goto fail; } r = sd_event_source_set_enabled(c->client_event_source, SD_EVENT_ONESHOT); if (r < 0) { log_error_errno(r, "Failed to enable oneshot event source: %m"); goto fail; } } else { log_error_errno(errno, "Failed to connect to remote host: %m"); goto fail; } } else { r = connection_complete(c); if (r < 0) goto fail; } return 0; fail: connection_free(c); return 0; /* ignore errors, continue serving */ } static int resolve_cb(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata) { Connection *c = userdata; assert(q); assert(c); if (ret != 0) { log_error("Failed to resolve host: %s", gai_strerror(ret)); goto fail; } c->resolve_query = sd_resolve_query_unref(c->resolve_query); return connection_start(c, ai->ai_addr, ai->ai_addrlen); fail: connection_free(c); return 0; /* ignore errors, continue serving */ } static int resolve_remote(Connection *c) { static const struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_flags = AI_ADDRCONFIG }; union sockaddr_union sa = {}; const char *node, *service; socklen_t salen; int r; if (path_is_absolute(arg_remote_host)) { sa.un.sun_family = AF_UNIX; strncpy(sa.un.sun_path, arg_remote_host, sizeof(sa.un.sun_path)-1); sa.un.sun_path[sizeof(sa.un.sun_path)-1] = 0; salen = offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path); return connection_start(c, &sa.sa, salen); } if (arg_remote_host[0] == '@') { sa.un.sun_family = AF_UNIX; sa.un.sun_path[0] = 0; strncpy(sa.un.sun_path+1, arg_remote_host+1, sizeof(sa.un.sun_path)-2); sa.un.sun_path[sizeof(sa.un.sun_path)-1] = 0; salen = offsetof(union sockaddr_union, un.sun_path) + 1 + strlen(sa.un.sun_path + 1); return connection_start(c, &sa.sa, salen); } service = strrchr(arg_remote_host, ':'); if (service) { node = strndupa(arg_remote_host, service - arg_remote_host); service ++; } else { node = arg_remote_host; service = "80"; } log_debug("Looking up address info for %s:%s", node, service); r = sd_resolve_getaddrinfo(c->context->resolve, &c->resolve_query, node, service, &hints, resolve_cb, c); if (r < 0) { log_error_errno(r, "Failed to resolve remote host: %m"); goto fail; } return 0; fail: connection_free(c); return 0; /* ignore errors, continue serving */ } static int add_connection_socket(Context *context, int fd) { Connection *c; int r; assert(context); assert(fd >= 0); if (set_size(context->connections) > CONNECTIONS_MAX) { log_warning("Hit connection limit, refusing connection."); safe_close(fd); return 0; } r = set_ensure_allocated(&context->connections, NULL); if (r < 0) { log_oom(); return 0; } c = new0(Connection, 1); if (!c) { log_oom(); return 0; } c->context = context; c->server_fd = fd; c->client_fd = -1; c->server_to_client_buffer[0] = c->server_to_client_buffer[1] = -1; c->client_to_server_buffer[0] = c->client_to_server_buffer[1] = -1; r = set_put(context->connections, c); if (r < 0) { free(c); log_oom(); return 0; } return resolve_remote(c); } static int accept_cb(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_free_ char *peer = NULL; Context *context = userdata; int nfd = -1, r; assert(s); assert(fd >= 0); assert(revents & EPOLLIN); assert(context); nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); if (nfd < 0) { if (errno != -EAGAIN) log_warning_errno(errno, "Failed to accept() socket: %m"); } else { getpeername_pretty(nfd, true, &peer); log_debug("New connection from %s", strna(peer)); r = add_connection_socket(context, nfd); if (r < 0) { log_error_errno(r, "Failed to accept connection, ignoring: %m"); safe_close(fd); } } r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT); if (r < 0) { log_error_errno(r, "Error while re-enabling listener with ONESHOT: %m"); sd_event_exit(context->event, r); return r; } return 1; } static int add_listen_socket(Context *context, int fd) { sd_event_source *source; int r; assert(context); assert(fd >= 0); r = set_ensure_allocated(&context->listen, NULL); if (r < 0) { log_oom(); return r; } r = sd_is_socket(fd, 0, SOCK_STREAM, 1); if (r < 0) return log_error_errno(r, "Failed to determine socket type: %m"); if (r == 0) { log_error("Passed in socket is not a stream socket."); return -EINVAL; } r = fd_nonblock(fd, true); if (r < 0) return log_error_errno(r, "Failed to mark file descriptor non-blocking: %m"); r = sd_event_add_io(context->event, &source, fd, EPOLLIN, accept_cb, context); if (r < 0) return log_error_errno(r, "Failed to add event source: %m"); r = set_put(context->listen, source); if (r < 0) { log_error_errno(r, "Failed to add source to set: %m"); sd_event_source_unref(source); return r; } /* Set the watcher to oneshot in case other processes are also * watching to accept(). */ r = sd_event_source_set_enabled(source, SD_EVENT_ONESHOT); if (r < 0) return log_error_errno(r, "Failed to enable oneshot mode: %m"); return 0; } static void help(void) { printf("%1$s [HOST:PORT]\n" "%1$s [SOCKET]\n\n" "Bidirectionally proxy local sockets to another (possibly remote) socket.\n\n" " -h --help Show this help\n" " --version Show package version\n", program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_IGNORE_ENV }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (optind >= argc) { log_error("Not enough parameters."); return -EINVAL; } if (argc != optind+1) { log_error("Too many parameters."); return -EINVAL; } arg_remote_host = argv[optind]; return 1; } int main(int argc, char *argv[]) { Context context = {}; int r, n, fd; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = sd_event_default(&context.event); if (r < 0) { log_error_errno(r, "Failed to allocate event loop: %m"); goto finish; } r = sd_resolve_default(&context.resolve); if (r < 0) { log_error_errno(r, "Failed to allocate resolver: %m"); goto finish; } r = sd_resolve_attach_event(context.resolve, context.event, 0); if (r < 0) { log_error_errno(r, "Failed to attach resolver: %m"); goto finish; } sd_event_set_watchdog(context.event, true); n = sd_listen_fds(1); if (n < 0) { log_error("Failed to receive sockets from parent."); r = n; goto finish; } else if (n == 0) { log_error("Didn't get any sockets passed in."); r = -EINVAL; goto finish; } for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { r = add_listen_socket(&context, fd); if (r < 0) goto finish; } r = sd_event_loop(context.event); if (r < 0) { log_error_errno(r, "Failed to run event loop: %m"); goto finish; } finish: context_free(&context); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/sysctl/000077500000000000000000000000001265713322000151715ustar00rootroot00000000000000systemd-229/src/sysctl/Makefile000077700000000000000000000000001265713322000204772../Makefileustar00rootroot00000000000000systemd-229/src/sysctl/sysctl.c000066400000000000000000000210721265713322000166600ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "conf-files.h" #include "def.h" #include "fd-util.h" #include "fileio.h" #include "hashmap.h" #include "log.h" #include "path-util.h" #include "string-util.h" #include "strv.h" #include "sysctl-util.h" #include "util.h" static char **arg_prefixes = NULL; static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysctl.d"); static int apply_all(Hashmap *sysctl_options) { char *property, *value; Iterator i; int r = 0; HASHMAP_FOREACH_KEY(value, property, sysctl_options, i) { int k; k = sysctl_write(property, value); if (k < 0) { log_full_errno(k == -ENOENT ? LOG_INFO : LOG_WARNING, k, "Couldn't write '%s' to '%s', ignoring: %m", value, property); if (r == 0 && k != -ENOENT) r = k; } } return r; } static int parse_file(Hashmap *sysctl_options, const char *path, bool ignore_enoent) { _cleanup_fclose_ FILE *f = NULL; int r; assert(path); r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f); if (r < 0) { if (ignore_enoent && r == -ENOENT) return 0; return log_error_errno(r, "Failed to open file '%s', ignoring: %m", path); } log_debug("Parsing %s", path); while (!feof(f)) { char l[LINE_MAX], *p, *value, *new_value, *property, *existing; void *v; int k; if (!fgets(l, sizeof(l), f)) { if (feof(f)) break; return log_error_errno(errno, "Failed to read file '%s', ignoring: %m", path); } p = strstrip(l); if (!*p) continue; if (strchr(COMMENTS "\n", *p)) continue; value = strchr(p, '='); if (!value) { log_error("Line is not an assignment in file '%s': %s", path, value); if (r == 0) r = -EINVAL; continue; } *value = 0; value++; p = sysctl_normalize(strstrip(p)); value = strstrip(value); if (!strv_isempty(arg_prefixes)) { char **i, *t; STRV_FOREACH(i, arg_prefixes) { t = path_startswith(*i, "/proc/sys/"); if (t == NULL) t = *i; if (path_startswith(p, t)) goto found; } /* not found */ continue; } found: existing = hashmap_get2(sysctl_options, p, &v); if (existing) { if (streq(value, existing)) continue; log_debug("Overwriting earlier assignment of %s in file '%s'.", p, path); free(hashmap_remove(sysctl_options, p)); free(v); } property = strdup(p); if (!property) return log_oom(); new_value = strdup(value); if (!new_value) { free(property); return log_oom(); } k = hashmap_put(sysctl_options, property, new_value); if (k < 0) { log_error_errno(k, "Failed to add sysctl variable %s to hashmap: %m", property); free(property); free(new_value); return k; } } return r; } static void help(void) { printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n" "Applies kernel sysctl settings.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --prefix=PATH Only apply rules with the specified prefix\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_PREFIX }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "prefix", required_argument, NULL, ARG_PREFIX }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_PREFIX: { char *p; /* We used to require people to specify absolute paths * in /proc/sys in the past. This is kinda useless, but * we need to keep compatibility. We now support any * sysctl name available. */ sysctl_normalize(optarg); if (startswith(optarg, "/proc/sys")) p = strdup(optarg); else p = strappend("/proc/sys/", optarg); if (!p) return log_oom(); if (strv_consume(&arg_prefixes, p) < 0) return log_oom(); break; } case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } int main(int argc, char *argv[]) { int r = 0, k; Hashmap *sysctl_options; r = parse_argv(argc, argv); if (r <= 0) return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); sysctl_options = hashmap_new(&string_hash_ops); if (!sysctl_options) { r = log_oom(); goto finish; } r = 0; if (argc > optind) { int i; for (i = optind; i < argc; i++) { k = parse_file(sysctl_options, argv[i], false); if (k < 0 && r == 0) r = k; } } else { _cleanup_strv_free_ char **files = NULL; char **f; r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs); if (r < 0) { log_error_errno(r, "Failed to enumerate sysctl.d files: %m"); goto finish; } STRV_FOREACH(f, files) { k = parse_file(sysctl_options, *f, true); if (k < 0 && r == 0) r = k; } } k = apply_all(sysctl_options); if (k < 0 && r == 0) r = k; finish: hashmap_free_free_free(sysctl_options); strv_free(arg_prefixes); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/system-update-generator/000077500000000000000000000000001265713322000204405ustar00rootroot00000000000000systemd-229/src/system-update-generator/Makefile000077700000000000000000000000001265713322000237462../Makefileustar00rootroot00000000000000systemd-229/src/system-update-generator/system-update-generator.c000066400000000000000000000037251265713322000254030ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "fs-util.h" #include "log.h" #include "string-util.h" #include "util.h" /* * Implements the logic described in * http://freedesktop.org/wiki/Software/systemd/SystemUpdates */ static const char *arg_dest = "/tmp"; static int generate_symlink(void) { const char *p = NULL; if (laccess("/system-update", F_OK) < 0) { if (errno == ENOENT) return 0; log_error_errno(errno, "Failed to check for system update: %m"); return -EINVAL; } p = strjoina(arg_dest, "/default.target"); if (symlink(SYSTEM_DATA_UNIT_PATH "/system-update.target", p) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", p); return 0; } int main(int argc, char *argv[]) { int r; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); return EXIT_FAILURE; } if (argc > 1) arg_dest = argv[2]; log_set_target(LOG_TARGET_SAFE); log_parse_environment(); log_open(); umask(0022); r = generate_symlink(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/systemctl/000077500000000000000000000000001265713322000156775ustar00rootroot00000000000000systemd-229/src/systemctl/Makefile000077700000000000000000000000001265713322000212052../Makefileustar00rootroot00000000000000systemd-229/src/systemctl/systemctl.c000066400000000000000000010342241265713322000201000ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Marc-Antoine Perennou systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include "sd-bus.h" #include "sd-daemon.h" #include "sd-login.h" #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-message.h" #include "bus-util.h" #include "cgroup-show.h" #include "cgroup-util.h" #include "copy.h" #include "dropin.h" #include "efivars.h" #include "env-util.h" #include "exit-status.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "glob-util.h" #include "hostname-util.h" #include "initreq.h" #include "install.h" #include "io-util.h" #include "list.h" #include "locale-util.h" #include "log.h" #include "logs-show.h" #include "macro.h" #include "mkdir.h" #include "pager.h" #include "parse-util.h" #include "path-lookup.h" #include "path-util.h" #include "process-util.h" #include "rlimit-util.h" #include "set.h" #include "signal-util.h" #include "socket-util.h" #include "spawn-ask-password-agent.h" #include "spawn-polkit-agent.h" #include "special.h" #include "stat-util.h" #include "strv.h" #include "terminal-util.h" #include "unit-name.h" #include "user-util.h" #include "util.h" #include "utmp-wtmp.h" #include "verbs.h" #include "virt.h" static char **arg_types = NULL; static char **arg_states = NULL; static char **arg_properties = NULL; static bool arg_all = false; static enum dependency { DEPENDENCY_FORWARD, DEPENDENCY_REVERSE, DEPENDENCY_AFTER, DEPENDENCY_BEFORE, _DEPENDENCY_MAX } arg_dependency = DEPENDENCY_FORWARD; static const char *arg_job_mode = "replace"; static UnitFileScope arg_scope = UNIT_FILE_SYSTEM; static bool arg_no_block = false; static bool arg_no_legend = false; static bool arg_no_pager = false; static bool arg_no_wtmp = false; static bool arg_no_wall = false; static bool arg_no_reload = false; static bool arg_show_types = false; static bool arg_ignore_inhibitors = false; static bool arg_dry = false; static bool arg_quiet = false; static bool arg_full = false; static bool arg_recursive = false; static int arg_force = 0; static bool arg_ask_password = false; static bool arg_runtime = false; static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL; static char **arg_wall = NULL; static const char *arg_kill_who = NULL; static int arg_signal = SIGTERM; static char *arg_root = NULL; static usec_t arg_when = 0; static enum action { _ACTION_INVALID, ACTION_SYSTEMCTL, ACTION_HALT, ACTION_POWEROFF, ACTION_REBOOT, ACTION_KEXEC, ACTION_EXIT, ACTION_SUSPEND, ACTION_HIBERNATE, ACTION_HYBRID_SLEEP, ACTION_RUNLEVEL2, ACTION_RUNLEVEL3, ACTION_RUNLEVEL4, ACTION_RUNLEVEL5, ACTION_RESCUE, ACTION_EMERGENCY, ACTION_DEFAULT, ACTION_RELOAD, ACTION_REEXEC, ACTION_RUNLEVEL, ACTION_CANCEL_SHUTDOWN, _ACTION_MAX } arg_action = ACTION_SYSTEMCTL; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static const char *arg_host = NULL; static unsigned arg_lines = 10; static OutputMode arg_output = OUTPUT_SHORT; static bool arg_plain = false; static bool arg_firmware_setup = false; static bool arg_now = false; static int daemon_reload(int argc, char *argv[], void* userdata); static int halt_now(enum action a); static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet); static bool original_stdout_is_tty; typedef enum BusFocus { BUS_FULL, /* The full bus indicated via --system or --user */ BUS_MANAGER, /* The manager itself, possibly directly, possibly via the bus */ _BUS_FOCUS_MAX } BusFocus; static sd_bus *busses[_BUS_FOCUS_MAX] = {}; static int acquire_bus(BusFocus focus, sd_bus **ret) { int r; assert(focus < _BUS_FOCUS_MAX); assert(ret); /* We only go directly to the manager, if we are using a local transport */ if (arg_transport != BUS_TRANSPORT_LOCAL) focus = BUS_FULL; if (!busses[focus]) { bool user; user = arg_scope != UNIT_FILE_SYSTEM; if (focus == BUS_MANAGER) r = bus_connect_transport_systemd(arg_transport, arg_host, user, &busses[focus]); else r = bus_connect_transport(arg_transport, arg_host, user, &busses[focus]); if (r < 0) return log_error_errno(r, "Failed to connect to bus: %m"); (void) sd_bus_set_allow_interactive_authorization(busses[focus], arg_ask_password); } *ret = busses[focus]; return 0; } static void release_busses(void) { BusFocus w; for (w = 0; w < _BUS_FOCUS_MAX; w++) busses[w] = sd_bus_flush_close_unref(busses[w]); } static void pager_open_if_enabled(void) { if (arg_no_pager) return; pager_open(false); } static void ask_password_agent_open_if_enabled(void) { /* Open the password agent as a child process if necessary */ if (!arg_ask_password) return; if (arg_scope != UNIT_FILE_SYSTEM) return; if (arg_transport != BUS_TRANSPORT_LOCAL) return; ask_password_agent_open(); } static void polkit_agent_open_if_enabled(void) { /* Open the polkit agent as a child process if necessary */ if (!arg_ask_password) return; if (arg_scope != UNIT_FILE_SYSTEM) return; if (arg_transport != BUS_TRANSPORT_LOCAL) return; polkit_agent_open(); } static OutputFlags get_output_flags(void) { return arg_all * OUTPUT_SHOW_ALL | arg_full * OUTPUT_FULL_WIDTH | (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH | colors_enabled() * OUTPUT_COLOR | !arg_quiet * OUTPUT_WARN_CUTOFF; } static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) { assert(error); if (!sd_bus_error_is_set(error)) return r; if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) || sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) || sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) || sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE)) return EXIT_NOPERMISSION; if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT)) return EXIT_NOTINSTALLED; if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) || sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED)) return EXIT_NOTIMPLEMENTED; if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) return EXIT_NOTCONFIGURED; if (r != 0) return r; return EXIT_FAILURE; } static bool install_client_side(void) { /* Decides when to execute enable/disable/... operations * client-side rather than server-side. */ if (running_in_chroot() > 0) return true; if (sd_booted() <= 0) return true; if (!isempty(arg_root)) return true; if (arg_scope == UNIT_FILE_GLOBAL) return true; /* Unsupported environment variable, mostly for debugging purposes */ if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0) return true; return false; } static int compare_unit_info(const void *a, const void *b) { const UnitInfo *u = a, *v = b; const char *d1, *d2; int r; /* First, order by machine */ if (!u->machine && v->machine) return -1; if (u->machine && !v->machine) return 1; if (u->machine && v->machine) { r = strcasecmp(u->machine, v->machine); if (r != 0) return r; } /* Second, order by unit type */ d1 = strrchr(u->id, '.'); d2 = strrchr(v->id, '.'); if (d1 && d2) { r = strcasecmp(d1, d2); if (r != 0) return r; } /* Third, order by name */ return strcasecmp(u->id, v->id); } static bool output_show_unit(const UnitInfo *u, char **patterns) { if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE)) return false; if (arg_types) { const char *dot; dot = strrchr(u->id, '.'); if (!dot) return false; if (!strv_find(arg_types, dot+1)) return false; } if (arg_all) return true; if (u->job_id > 0) return true; if (streq(u->active_state, "inactive") || u->following[0]) return false; return true; } static int output_units_list(const UnitInfo *unit_infos, unsigned c) { unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len; const UnitInfo *u; unsigned n_shown = 0; int job_count = 0; max_id_len = strlen("UNIT"); load_len = strlen("LOAD"); active_len = strlen("ACTIVE"); sub_len = strlen("SUB"); job_len = strlen("JOB"); desc_len = 0; for (u = unit_infos; u < unit_infos + c; u++) { max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0)); load_len = MAX(load_len, strlen(u->load_state)); active_len = MAX(active_len, strlen(u->active_state)); sub_len = MAX(sub_len, strlen(u->sub_state)); if (u->job_id != 0) { job_len = MAX(job_len, strlen(u->job_type)); job_count++; } if (!arg_no_legend && (streq(u->active_state, "failed") || STR_IN_SET(u->load_state, "error", "not-found", "masked"))) circle_len = 2; } if (!arg_full && original_stdout_is_tty) { unsigned basic_len; id_len = MIN(max_id_len, 25u); basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len; if (job_count) basic_len += job_len + 1; if (basic_len < (unsigned) columns()) { unsigned extra_len, incr; extra_len = columns() - basic_len; /* Either UNIT already got 25, or is fully satisfied. * Grant up to 25 to DESC now. */ incr = MIN(extra_len, 25u); desc_len += incr; extra_len -= incr; /* split the remaining space between UNIT and DESC, * but do not give UNIT more than it needs. */ if (extra_len > 0) { incr = MIN(extra_len / 2, max_id_len - id_len); id_len += incr; desc_len += extra_len - incr; } } } else id_len = max_id_len; for (u = unit_infos; u < unit_infos + c; u++) { _cleanup_free_ char *e = NULL, *j = NULL; const char *on_loaded = "", *off_loaded = ""; const char *on_active = "", *off_active = ""; const char *on_circle = "", *off_circle = ""; const char *id; bool circle = false; if (!n_shown && !arg_no_legend) { if (circle_len > 0) fputs(" ", stdout); printf("%-*s %-*s %-*s %-*s ", id_len, "UNIT", load_len, "LOAD", active_len, "ACTIVE", sub_len, "SUB"); if (job_count) printf("%-*s ", job_len, "JOB"); if (!arg_full && arg_no_pager) printf("%.*s\n", desc_len, "DESCRIPTION"); else printf("%s\n", "DESCRIPTION"); } n_shown++; if (STR_IN_SET(u->load_state, "error", "not-found", "masked") && !arg_plain) { on_loaded = ansi_highlight_red(); on_circle = ansi_highlight_yellow(); off_loaded = off_circle = ansi_normal(); circle = true; } else if (streq(u->active_state, "failed") && !arg_plain) { on_circle = on_active = ansi_highlight_red(); off_circle = off_active = ansi_normal(); circle = true; } if (u->machine) { j = strjoin(u->machine, ":", u->id, NULL); if (!j) return log_oom(); id = j; } else id = u->id; if (arg_full) { e = ellipsize(id, id_len, 33); if (!e) return log_oom(); id = e; } if (circle_len > 0) printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle); printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s", on_active, id_len, id, off_active, on_loaded, load_len, u->load_state, off_loaded, on_active, active_len, u->active_state, sub_len, u->sub_state, off_active, job_count ? job_len + 1 : 0, u->job_id ? u->job_type : ""); if (desc_len > 0) printf("%.*s\n", desc_len, u->description); else printf("%s\n", u->description); } if (!arg_no_legend) { const char *on, *off; if (n_shown) { puts("\n" "LOAD = Reflects whether the unit definition was properly loaded.\n" "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n" "SUB = The low-level unit activation state, values depend on unit type."); puts(job_count ? "JOB = Pending job for the unit.\n" : ""); on = ansi_highlight(); off = ansi_normal(); } else { on = ansi_highlight_red(); off = ansi_normal(); } if (arg_all) printf("%s%u loaded units listed.%s\n" "To show all installed unit files use 'systemctl list-unit-files'.\n", on, n_shown, off); else printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n" "To show all installed unit files use 'systemctl list-unit-files'.\n", on, n_shown, off); } return 0; } static int get_unit_list( sd_bus *bus, const char *machine, char **patterns, UnitInfo **unit_infos, int c, sd_bus_message **_reply) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; size_t size = c; int r; UnitInfo u; assert(bus); assert(unit_infos); assert(_reply); r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "ListUnitsFiltered"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append_strv(m, arg_states); if (r < 0) return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r)); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)"); if (r < 0) return bus_log_parse_error(r); while ((r = bus_parse_unit_info(reply, &u)) > 0) { u.machine = machine; if (!output_show_unit(&u, patterns)) continue; if (!GREEDY_REALLOC(*unit_infos, size, c+1)) return log_oom(); (*unit_infos)[c++] = u; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); *_reply = reply; reply = NULL; return c; } static void message_set_freep(Set **set) { sd_bus_message *m; while ((m = set_steal_first(*set))) sd_bus_message_unref(m); set_free(*set); } static int get_unit_list_recursive( sd_bus *bus, char **patterns, UnitInfo **_unit_infos, Set **_replies, char ***_machines) { _cleanup_free_ UnitInfo *unit_infos = NULL; _cleanup_(message_set_freep) Set *replies; sd_bus_message *reply; int c, r; assert(bus); assert(_replies); assert(_unit_infos); assert(_machines); replies = set_new(NULL); if (!replies) return log_oom(); c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply); if (c < 0) return c; r = set_put(replies, reply); if (r < 0) { sd_bus_message_unref(reply); return log_oom(); } if (arg_recursive) { _cleanup_strv_free_ char **machines = NULL; char **i; r = sd_get_machine_names(&machines); if (r < 0) return log_error_errno(r, "Failed to get machine names: %m"); STRV_FOREACH(i, machines) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL; int k; r = sd_bus_open_system_machine(&container, *i); if (r < 0) { log_warning_errno(r, "Failed to connect to container %s, ignoring: %m", *i); continue; } k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply); if (k < 0) return k; c = k; r = set_put(replies, reply); if (r < 0) { sd_bus_message_unref(reply); return log_oom(); } } *_machines = machines; machines = NULL; } else *_machines = NULL; *_unit_infos = unit_infos; unit_infos = NULL; *_replies = replies; replies = NULL; return c; } static int list_units(int argc, char *argv[], void *userdata) { _cleanup_free_ UnitInfo *unit_infos = NULL; _cleanup_(message_set_freep) Set *replies = NULL; _cleanup_strv_free_ char **machines = NULL; sd_bus *bus; int r; pager_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); if (r < 0) return r; qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info); return output_units_list(unit_infos, r); } static int get_triggered_units( sd_bus *bus, const char* path, char*** ret) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); assert(path); assert(ret); r = sd_bus_get_property_strv( bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Unit", "Triggers", &error, ret); if (r < 0) return log_error_errno(r, "Failed to determine triggers: %s", bus_error_message(&error, r)); return 0; } static int get_listening( sd_bus *bus, const char* unit_path, char*** listening) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *type, *path; int r, n = 0; r = sd_bus_get_property( bus, "org.freedesktop.systemd1", unit_path, "org.freedesktop.systemd1.Socket", "Listen", &error, &reply, "a(ss)"); if (r < 0) return log_error_errno(r, "Failed to get list of listening sockets: %s", bus_error_message(&error, r)); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) { r = strv_extend(listening, type); if (r < 0) return log_oom(); r = strv_extend(listening, path); if (r < 0) return log_oom(); n++; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); return n; } struct socket_info { const char *machine; const char* id; char* type; char* path; /* Note: triggered is a list here, although it almost certainly * will always be one unit. Nevertheless, dbus API allows for multiple * values, so let's follow that. */ char** triggered; /* The strv above is shared. free is set only in the first one. */ bool own_triggered; }; static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) { int o; assert(a); assert(b); if (!a->machine && b->machine) return -1; if (a->machine && !b->machine) return 1; if (a->machine && b->machine) { o = strcasecmp(a->machine, b->machine); if (o != 0) return o; } o = strcmp(a->path, b->path); if (o == 0) o = strcmp(a->type, b->type); return o; } static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) { struct socket_info *s; unsigned pathlen = strlen("LISTEN"), typelen = strlen("TYPE") * arg_show_types, socklen = strlen("UNIT"), servlen = strlen("ACTIVATES"); const char *on, *off; for (s = socket_infos; s < socket_infos + cs; s++) { unsigned tmp = 0; char **a; socklen = MAX(socklen, strlen(s->id)); if (arg_show_types) typelen = MAX(typelen, strlen(s->type)); pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0)); STRV_FOREACH(a, s->triggered) tmp += strlen(*a) + 2*(a != s->triggered); servlen = MAX(servlen, tmp); } if (cs) { if (!arg_no_legend) printf("%-*s %-*.*s%-*s %s\n", pathlen, "LISTEN", typelen + arg_show_types, typelen + arg_show_types, "TYPE ", socklen, "UNIT", "ACTIVATES"); for (s = socket_infos; s < socket_infos + cs; s++) { _cleanup_free_ char *j = NULL; const char *path; char **a; if (s->machine) { j = strjoin(s->machine, ":", s->path, NULL); if (!j) return log_oom(); path = j; } else path = s->path; if (arg_show_types) printf("%-*s %-*s %-*s", pathlen, path, typelen, s->type, socklen, s->id); else printf("%-*s %-*s", pathlen, path, socklen, s->id); STRV_FOREACH(a, s->triggered) printf("%s %s", a == s->triggered ? "" : ",", *a); printf("\n"); } on = ansi_highlight(); off = ansi_normal(); if (!arg_no_legend) printf("\n"); } else { on = ansi_highlight_red(); off = ansi_normal(); } if (!arg_no_legend) { printf("%s%u sockets listed.%s\n", on, cs, off); if (!arg_all) printf("Pass --all to see loaded but inactive sockets, too.\n"); } return 0; } static int list_sockets(int argc, char *argv[], void *userdata) { _cleanup_(message_set_freep) Set *replies = NULL; _cleanup_strv_free_ char **machines = NULL; _cleanup_free_ UnitInfo *unit_infos = NULL; _cleanup_free_ struct socket_info *socket_infos = NULL; const UnitInfo *u; struct socket_info *s; unsigned cs = 0; size_t size = 0; int r = 0, n; sd_bus *bus; pager_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); if (n < 0) return n; for (u = unit_infos; u < unit_infos + n; u++) { _cleanup_strv_free_ char **listening = NULL, **triggered = NULL; int i, c; if (!endswith(u->id, ".socket")) continue; r = get_triggered_units(bus, u->unit_path, &triggered); if (r < 0) goto cleanup; c = get_listening(bus, u->unit_path, &listening); if (c < 0) { r = c; goto cleanup; } if (!GREEDY_REALLOC(socket_infos, size, cs + c)) { r = log_oom(); goto cleanup; } for (i = 0; i < c; i++) socket_infos[cs + i] = (struct socket_info) { .machine = u->machine, .id = u->id, .type = listening[i*2], .path = listening[i*2 + 1], .triggered = triggered, .own_triggered = i==0, }; /* from this point on we will cleanup those socket_infos */ cs += c; free(listening); listening = triggered = NULL; /* avoid cleanup */ } qsort_safe(socket_infos, cs, sizeof(struct socket_info), (__compar_fn_t) socket_info_compare); output_sockets_list(socket_infos, cs); cleanup: assert(cs == 0 || socket_infos); for (s = socket_infos; s < socket_infos + cs; s++) { free(s->type); free(s->path); if (s->own_triggered) strv_free(s->triggered); } return r; } static int get_next_elapse( sd_bus *bus, const char *path, dual_timestamp *next) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; dual_timestamp t; int r; assert(bus); assert(path); assert(next); r = sd_bus_get_property_trivial( bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Timer", "NextElapseUSecMonotonic", &error, 't', &t.monotonic); if (r < 0) return log_error_errno(r, "Failed to get next elapsation time: %s", bus_error_message(&error, r)); r = sd_bus_get_property_trivial( bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Timer", "NextElapseUSecRealtime", &error, 't', &t.realtime); if (r < 0) return log_error_errno(r, "Failed to get next elapsation time: %s", bus_error_message(&error, r)); *next = t; return 0; } static int get_last_trigger( sd_bus *bus, const char *path, usec_t *last) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); assert(path); assert(last); r = sd_bus_get_property_trivial( bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Timer", "LastTriggerUSec", &error, 't', last); if (r < 0) return log_error_errno(r, "Failed to get last trigger time: %s", bus_error_message(&error, r)); return 0; } struct timer_info { const char* machine; const char* id; usec_t next_elapse; usec_t last_trigger; char** triggered; }; static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) { int o; assert(a); assert(b); if (!a->machine && b->machine) return -1; if (a->machine && !b->machine) return 1; if (a->machine && b->machine) { o = strcasecmp(a->machine, b->machine); if (o != 0) return o; } if (a->next_elapse < b->next_elapse) return -1; if (a->next_elapse > b->next_elapse) return 1; return strcmp(a->id, b->id); } static int output_timers_list(struct timer_info *timer_infos, unsigned n) { struct timer_info *t; unsigned nextlen = strlen("NEXT"), leftlen = strlen("LEFT"), lastlen = strlen("LAST"), passedlen = strlen("PASSED"), unitlen = strlen("UNIT"), activatelen = strlen("ACTIVATES"); const char *on, *off; assert(timer_infos || n == 0); for (t = timer_infos; t < timer_infos + n; t++) { unsigned ul = 0; char **a; if (t->next_elapse > 0) { char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = ""; format_timestamp(tstamp, sizeof(tstamp), t->next_elapse); nextlen = MAX(nextlen, strlen(tstamp) + 1); format_timestamp_relative(trel, sizeof(trel), t->next_elapse); leftlen = MAX(leftlen, strlen(trel)); } if (t->last_trigger > 0) { char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = ""; format_timestamp(tstamp, sizeof(tstamp), t->last_trigger); lastlen = MAX(lastlen, strlen(tstamp) + 1); format_timestamp_relative(trel, sizeof(trel), t->last_trigger); passedlen = MAX(passedlen, strlen(trel)); } unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0)); STRV_FOREACH(a, t->triggered) ul += strlen(*a) + 2*(a != t->triggered); activatelen = MAX(activatelen, ul); } if (n > 0) { if (!arg_no_legend) printf("%-*s %-*s %-*s %-*s %-*s %s\n", nextlen, "NEXT", leftlen, "LEFT", lastlen, "LAST", passedlen, "PASSED", unitlen, "UNIT", "ACTIVATES"); for (t = timer_infos; t < timer_infos + n; t++) { _cleanup_free_ char *j = NULL; const char *unit; char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a"; char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a"; char **a; format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse); format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse); format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger); format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger); if (t->machine) { j = strjoin(t->machine, ":", t->id, NULL); if (!j) return log_oom(); unit = j; } else unit = t->id; printf("%-*s %-*s %-*s %-*s %-*s", nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit); STRV_FOREACH(a, t->triggered) printf("%s %s", a == t->triggered ? "" : ",", *a); printf("\n"); } on = ansi_highlight(); off = ansi_normal(); if (!arg_no_legend) printf("\n"); } else { on = ansi_highlight_red(); off = ansi_normal(); } if (!arg_no_legend) { printf("%s%u timers listed.%s\n", on, n, off); if (!arg_all) printf("Pass --all to see loaded but inactive timers, too.\n"); } return 0; } static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) { usec_t next_elapse; assert(nw); assert(next); if (next->monotonic != USEC_INFINITY && next->monotonic > 0) { usec_t converted; if (next->monotonic > nw->monotonic) converted = nw->realtime + (next->monotonic - nw->monotonic); else converted = nw->realtime - (nw->monotonic - next->monotonic); if (next->realtime != USEC_INFINITY && next->realtime > 0) next_elapse = MIN(converted, next->realtime); else next_elapse = converted; } else next_elapse = next->realtime; return next_elapse; } static int list_timers(int argc, char *argv[], void *userdata) { _cleanup_(message_set_freep) Set *replies = NULL; _cleanup_strv_free_ char **machines = NULL; _cleanup_free_ struct timer_info *timer_infos = NULL; _cleanup_free_ UnitInfo *unit_infos = NULL; struct timer_info *t; const UnitInfo *u; size_t size = 0; int n, c = 0; dual_timestamp nw; sd_bus *bus; int r = 0; pager_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); if (n < 0) return n; dual_timestamp_get(&nw); for (u = unit_infos; u < unit_infos + n; u++) { _cleanup_strv_free_ char **triggered = NULL; dual_timestamp next = DUAL_TIMESTAMP_NULL; usec_t m, last = 0; if (!endswith(u->id, ".timer")) continue; r = get_triggered_units(bus, u->unit_path, &triggered); if (r < 0) goto cleanup; r = get_next_elapse(bus, u->unit_path, &next); if (r < 0) goto cleanup; get_last_trigger(bus, u->unit_path, &last); if (!GREEDY_REALLOC(timer_infos, size, c+1)) { r = log_oom(); goto cleanup; } m = calc_next_elapse(&nw, &next); timer_infos[c++] = (struct timer_info) { .machine = u->machine, .id = u->id, .next_elapse = m, .last_trigger = last, .triggered = triggered, }; triggered = NULL; /* avoid cleanup */ } qsort_safe(timer_infos, c, sizeof(struct timer_info), (__compar_fn_t) timer_info_compare); output_timers_list(timer_infos, c); cleanup: for (t = timer_infos; t < timer_infos + c; t++) strv_free(t->triggered); return r; } static int compare_unit_file_list(const void *a, const void *b) { const char *d1, *d2; const UnitFileList *u = a, *v = b; d1 = strrchr(u->path, '.'); d2 = strrchr(v->path, '.'); if (d1 && d2) { int r; r = strcasecmp(d1, d2); if (r != 0) return r; } return strcasecmp(basename(u->path), basename(v->path)); } static bool output_show_unit_file(const UnitFileList *u, char **patterns) { if (!strv_fnmatch_or_empty(patterns, basename(u->path), FNM_NOESCAPE)) return false; if (!strv_isempty(arg_types)) { const char *dot; dot = strrchr(u->path, '.'); if (!dot) return false; if (!strv_find(arg_types, dot+1)) return false; } if (!strv_isempty(arg_states) && !strv_find(arg_states, unit_file_state_to_string(u->state))) return false; return true; } static void output_unit_file_list(const UnitFileList *units, unsigned c) { unsigned max_id_len, id_cols, state_cols; const UnitFileList *u; max_id_len = strlen("UNIT FILE"); state_cols = strlen("STATE"); for (u = units; u < units + c; u++) { max_id_len = MAX(max_id_len, strlen(basename(u->path))); state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state))); } if (!arg_full) { unsigned basic_cols; id_cols = MIN(max_id_len, 25u); basic_cols = 1 + id_cols + state_cols; if (basic_cols < (unsigned) columns()) id_cols += MIN(columns() - basic_cols, max_id_len - id_cols); } else id_cols = max_id_len; if (!arg_no_legend) printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE"); for (u = units; u < units + c; u++) { _cleanup_free_ char *e = NULL; const char *on, *off; const char *id; if (IN_SET(u->state, UNIT_FILE_MASKED, UNIT_FILE_MASKED_RUNTIME, UNIT_FILE_DISABLED, UNIT_FILE_BAD)) { on = ansi_highlight_red(); off = ansi_normal(); } else if (u->state == UNIT_FILE_ENABLED) { on = ansi_highlight_green(); off = ansi_normal(); } else on = off = ""; id = basename(u->path); e = arg_full ? NULL : ellipsize(id, id_cols, 33); printf("%-*s %s%-*s%s\n", id_cols, e ? e : id, on, state_cols, unit_file_state_to_string(u->state), off); } if (!arg_no_legend) printf("\n%u unit files listed.\n", c); } static int list_unit_files(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ UnitFileList *units = NULL; UnitFileList *unit; size_t size = 0; unsigned c = 0; const char *state; char *path; int r; pager_open_if_enabled(); if (install_client_side()) { Hashmap *h; UnitFileList *u; Iterator i; unsigned n_units; h = hashmap_new(&string_hash_ops); if (!h) return log_oom(); r = unit_file_get_list(arg_scope, arg_root, h); if (r < 0) { unit_file_list_free(h); return log_error_errno(r, "Failed to get unit file list: %m"); } n_units = hashmap_size(h); units = new(UnitFileList, n_units); if (!units && n_units > 0) { unit_file_list_free(h); return log_oom(); } HASHMAP_FOREACH(u, h, i) { if (!output_show_unit_file(u, strv_skip(argv, 1))) continue; units[c++] = *u; free(u); } assert(c <= n_units); hashmap_free(h); } else { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus; r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "ListUnitFiles", &error, &reply, NULL); if (r < 0) return log_error_errno(r, "Failed to list unit files: %s", bus_error_message(&error, r)); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) { if (!GREEDY_REALLOC(units, size, c + 1)) return log_oom(); units[c] = (struct UnitFileList) { path, unit_file_state_from_string(state) }; if (output_show_unit_file(&units[c], strv_skip(argv, 1))) c ++; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); } qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list); output_unit_file_list(units, c); if (install_client_side()) { for (unit = units; unit < units + c; unit++) free(unit->path); } return 0; } static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) { _cleanup_free_ char *n = NULL; size_t max_len = MAX(columns(),20u); size_t len = 0; int i; if (!arg_plain) { for (i = level - 1; i >= 0; i--) { len += 2; if (len > max_len - 3 && !arg_full) { printf("%s...\n",max_len % 2 ? "" : " "); return 0; } printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE)); } len += 2; if (len > max_len - 3 && !arg_full) { printf("%s...\n",max_len % 2 ? "" : " "); return 0; } printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH)); } if (arg_full){ printf("%s\n", name); return 0; } n = ellipsize(name, max_len-len, 100); if (!n) return log_oom(); printf("%s\n", n); return 0; } static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) { static const char *dependencies[_DEPENDENCY_MAX] = { [DEPENDENCY_FORWARD] = "Requires\0" "Requisite\0" "Wants\0" "ConsistsOf\0" "BindsTo\0", [DEPENDENCY_REVERSE] = "RequiredBy\0" "RequisiteOf\0" "WantedBy\0" "PartOf\0" "BoundBy\0", [DEPENDENCY_AFTER] = "After\0", [DEPENDENCY_BEFORE] = "Before\0", }; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_strv_free_ char **ret = NULL; _cleanup_free_ char *path = NULL; int r; assert(bus); assert(name); assert(deps); assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX); path = unit_dbus_path_from_name(name); if (!path) return log_oom(); r = sd_bus_call_method( bus, "org.freedesktop.systemd1", path, "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd1.Unit"); if (r < 0) return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r)); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { const char *prop; r = sd_bus_message_read(reply, "s", &prop); if (r < 0) return bus_log_parse_error(r); if (!nulstr_contains(dependencies[arg_dependency], prop)) { r = sd_bus_message_skip(reply, "v"); if (r < 0) return bus_log_parse_error(r); } else { r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as"); if (r < 0) return bus_log_parse_error(r); r = bus_message_read_strv_extend(reply, &ret); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); } r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); *deps = ret; ret = NULL; return 0; } static int list_dependencies_compare(const void *_a, const void *_b) { const char **a = (const char**) _a, **b = (const char**) _b; if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET) return 1; if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET) return -1; return strcasecmp(*a, *b); } static int list_dependencies_one( sd_bus *bus, const char *name, int level, char ***units, unsigned int branches) { _cleanup_strv_free_ char **deps = NULL; char **c; int r = 0; assert(bus); assert(name); assert(units); r = strv_extend(units, name); if (r < 0) return log_oom(); r = list_dependencies_get_dependencies(bus, name, &deps); if (r < 0) return r; qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare); STRV_FOREACH(c, deps) { if (strv_contains(*units, *c)) { if (!arg_plain) { r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1); if (r < 0) return r; } continue; } if (arg_plain) printf(" "); else { int state; const char *on; state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true); on = state > 0 ? ansi_highlight_green() : ansi_highlight_red(); printf("%s%s%s ", on, draw_special_char(DRAW_BLACK_CIRCLE), ansi_normal()); } r = list_dependencies_print(*c, level, branches, c[1] == NULL); if (r < 0) return r; if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) { r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1)); if (r < 0) return r; } } if (!arg_plain) strv_remove(*units, name); return 0; } static int list_dependencies(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **units = NULL; _cleanup_free_ char *unit = NULL; const char *u; sd_bus *bus; int r; if (argv[1]) { r = unit_name_mangle(argv[1], UNIT_NAME_NOGLOB, &unit); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); u = unit; } else u = SPECIAL_DEFAULT_TARGET; pager_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; puts(u); return list_dependencies_one(bus, u, 0, &units, 0); } struct machine_info { bool is_host; char *name; char *state; char *control_group; uint32_t n_failed_units; uint32_t n_jobs; usec_t timestamp; }; static const struct bus_properties_map machine_info_property_map[] = { { "SystemState", "s", NULL, offsetof(struct machine_info, state) }, { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) }, { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) }, { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) }, { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) }, {} }; static void machine_info_clear(struct machine_info *info) { if (info) { free(info->name); free(info->state); free(info->control_group); zero(*info); } } static void free_machines_list(struct machine_info *machine_infos, int n) { int i; if (!machine_infos) return; for (i = 0; i < n; i++) machine_info_clear(&machine_infos[i]); free(machine_infos); } static int compare_machine_info(const void *a, const void *b) { const struct machine_info *u = a, *v = b; if (u->is_host != v->is_host) return u->is_host > v->is_host ? -1 : 1; return strcasecmp(u->name, v->name); } static int get_machine_properties(sd_bus *bus, struct machine_info *mi) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL; int r; assert(mi); if (!bus) { r = sd_bus_open_system_machine(&container, mi->name); if (r < 0) return r; bus = container; } r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi); if (r < 0) return r; return 0; } static bool output_show_machine(const char *name, char **patterns) { return strv_fnmatch_or_empty(patterns, name, FNM_NOESCAPE); } static int get_machine_list( sd_bus *bus, struct machine_info **_machine_infos, char **patterns) { struct machine_info *machine_infos = NULL; _cleanup_strv_free_ char **m = NULL; _cleanup_free_ char *hn = NULL; size_t sz = 0; char **i; int c = 0, r; hn = gethostname_malloc(); if (!hn) return log_oom(); if (output_show_machine(hn, patterns)) { if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) return log_oom(); machine_infos[c].is_host = true; machine_infos[c].name = hn; hn = NULL; get_machine_properties(bus, &machine_infos[c]); c++; } r = sd_get_machine_names(&m); if (r < 0) return log_error_errno(r, "Failed to get machine list: %m"); STRV_FOREACH(i, m) { _cleanup_free_ char *class = NULL; if (!output_show_machine(*i, patterns)) continue; sd_machine_get_class(*i, &class); if (!streq_ptr(class, "container")) continue; if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) { free_machines_list(machine_infos, c); return log_oom(); } machine_infos[c].is_host = false; machine_infos[c].name = strdup(*i); if (!machine_infos[c].name) { free_machines_list(machine_infos, c); return log_oom(); } get_machine_properties(NULL, &machine_infos[c]); c++; } *_machine_infos = machine_infos; return c; } static void output_machines_list(struct machine_info *machine_infos, unsigned n) { struct machine_info *m; unsigned circle_len = 0, namelen = sizeof("NAME") - 1, statelen = sizeof("STATE") - 1, failedlen = sizeof("FAILED") - 1, jobslen = sizeof("JOBS") - 1; assert(machine_infos || n == 0); for (m = machine_infos; m < machine_infos + n; m++) { namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0)); statelen = MAX(statelen, m->state ? strlen(m->state) : 0); failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units)); jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs)); if (!arg_plain && !streq_ptr(m->state, "running")) circle_len = 2; } if (!arg_no_legend) { if (circle_len > 0) fputs(" ", stdout); printf("%-*s %-*s %-*s %-*s\n", namelen, "NAME", statelen, "STATE", failedlen, "FAILED", jobslen, "JOBS"); } for (m = machine_infos; m < machine_infos + n; m++) { const char *on_state = "", *off_state = ""; const char *on_failed = "", *off_failed = ""; bool circle = false; if (streq_ptr(m->state, "degraded")) { on_state = ansi_highlight_red(); off_state = ansi_normal(); circle = true; } else if (!streq_ptr(m->state, "running")) { on_state = ansi_highlight_yellow(); off_state = ansi_normal(); circle = true; } if (m->n_failed_units > 0) { on_failed = ansi_highlight_red(); off_failed = ansi_normal(); } else on_failed = off_failed = ""; if (circle_len > 0) printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state); if (m->is_host) printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n", (int) (namelen - (sizeof(" (host)")-1)), strna(m->name), on_state, statelen, strna(m->state), off_state, on_failed, failedlen, m->n_failed_units, off_failed, jobslen, m->n_jobs); else printf("%-*s %s%-*s%s %s%*u%s %*u\n", namelen, strna(m->name), on_state, statelen, strna(m->state), off_state, on_failed, failedlen, m->n_failed_units, off_failed, jobslen, m->n_jobs); } if (!arg_no_legend) printf("\n%u machines listed.\n", n); } static int list_machines(int argc, char *argv[], void *userdata) { struct machine_info *machine_infos = NULL; sd_bus *bus; int r; if (geteuid() != 0) { log_error("Must be root."); return -EPERM; } pager_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = get_machine_list(bus, &machine_infos, strv_skip(argv, 1)); if (r < 0) return r; qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info); output_machines_list(machine_infos, r); free_machines_list(machine_infos, r); return 0; } static int get_default(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *_path = NULL; const char *path; int r; if (install_client_side()) { r = unit_file_get_default(arg_scope, arg_root, &_path); if (r < 0) return log_error_errno(r, "Failed to get default target: %m"); path = _path; } else { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus; r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "GetDefaultTarget", &error, &reply, NULL); if (r < 0) return log_error_errno(r, "Failed to get default target: %s", bus_error_message(&error, r)); r = sd_bus_message_read(reply, "s", &path); if (r < 0) return bus_log_parse_error(r); } if (path) printf("%s\n", path); return 0; } static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) { unsigned i; assert(changes || n_changes == 0); for (i = 0; i < n_changes; i++) { if (changes[i].type == UNIT_FILE_SYMLINK) log_info("Created symlink %s, pointing to %s.", changes[i].path, changes[i].source); else log_info("Removed symlink %s.", changes[i].path); } } static int set_default(int argc, char *argv[], void *userdata) { _cleanup_free_ char *unit = NULL; int r; assert(argc >= 2); assert(argv); r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".target", &unit); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); if (install_client_side()) { UnitFileChange *changes = NULL; unsigned n_changes = 0; r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes); if (r < 0) return log_error_errno(r, "Failed to set default target: %m"); if (!arg_quiet) dump_unit_file_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = 0; } else { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; sd_bus *bus; polkit_agent_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "SetDefaultTarget", &error, &reply, "sb", unit, 1); if (r < 0) return log_error_errno(r, "Failed to set default target: %s", bus_error_message(&error, r)); r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) return r; /* Try to reload if enabled */ if (!arg_no_reload) r = daemon_reload(argc, argv, userdata); else r = 0; } return r; } struct job_info { uint32_t id; const char *name, *type, *state; }; static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) { unsigned id_len, unit_len, type_len, state_len; const struct job_info *j; const char *on, *off; bool shorten = false; assert(n == 0 || jobs); if (n == 0) { if (!arg_no_legend) { on = ansi_highlight_green(); off = ansi_normal(); printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off); } return; } pager_open_if_enabled(); id_len = strlen("JOB"); unit_len = strlen("UNIT"); type_len = strlen("TYPE"); state_len = strlen("STATE"); for (j = jobs; j < jobs + n; j++) { uint32_t id = j->id; assert(j->name && j->type && j->state); id_len = MAX(id_len, DECIMAL_STR_WIDTH(id)); unit_len = MAX(unit_len, strlen(j->name)); type_len = MAX(type_len, strlen(j->type)); state_len = MAX(state_len, strlen(j->state)); } if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) { unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3); shorten = true; } if (!arg_no_legend) printf("%*s %-*s %-*s %-*s\n", id_len, "JOB", unit_len, "UNIT", type_len, "TYPE", state_len, "STATE"); for (j = jobs; j < jobs + n; j++) { _cleanup_free_ char *e = NULL; if (streq(j->state, "running")) { on = ansi_highlight(); off = ansi_normal(); } else on = off = ""; e = shorten ? ellipsize(j->name, unit_len, 33) : NULL; printf("%*u %s%-*s%s %-*s %s%-*s%s\n", id_len, j->id, on, unit_len, e ? e : j->name, off, type_len, j->type, on, state_len, j->state, off); } if (!arg_no_legend) { on = ansi_highlight(); off = ansi_normal(); printf("\n%s%u jobs listed%s.\n", on, n, off); } } static bool output_show_job(struct job_info *job, char **patterns) { return strv_fnmatch_or_empty(patterns, job->name, FNM_NOESCAPE); } static int list_jobs(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *name, *type, *state, *job_path, *unit_path; _cleanup_free_ struct job_info *jobs = NULL; size_t size = 0; unsigned c = 0; sd_bus *bus; uint32_t id; int r; bool skipped = false; pager_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "ListJobs", &error, &reply, NULL); if (r < 0) return log_error_errno(r, "Failed to list jobs: %s", bus_error_message(&error, r)); r = sd_bus_message_enter_container(reply, 'a', "(usssoo)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) { struct job_info job = { id, name, type, state }; if (!output_show_job(&job, strv_skip(argv, 1))) { skipped = true; continue; } if (!GREEDY_REALLOC(jobs, size, c + 1)) return log_oom(); jobs[c++] = job; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); output_jobs_list(jobs, c, skipped); return 0; } static int cancel_job(int argc, char *argv[], void *userdata) { sd_bus *bus; char **name; int r = 0; if (argc <= 1) return daemon_reload(argc, argv, userdata); polkit_agent_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; STRV_FOREACH(name, strv_skip(argv, 1)) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; uint32_t id; int q; q = safe_atou32(*name, &id); if (q < 0) return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name); q = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "CancelJob", &error, NULL, "u", id); if (q < 0) { log_error_errno(q, "Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q)); if (r == 0) r = q; } } return r; } static int need_daemon_reload(sd_bus *bus, const char *unit) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *path; int b, r; /* We ignore all errors here, since this is used to show a * warning only */ /* We don't use unit_dbus_path_from_name() directly since we * don't want to load the unit if it isn't loaded. */ r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "GetUnit", NULL, &reply, "s", unit); if (r < 0) return r; r = sd_bus_message_read(reply, "o", &path); if (r < 0) return r; r = sd_bus_get_property_trivial( bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Unit", "NeedDaemonReload", NULL, 'b', &b); if (r < 0) return r; return b; } static void warn_unit_file_changed(const char *name) { log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.", ansi_highlight_red(), ansi_normal(), name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user"); } static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) { char **p; assert(lp); assert(unit_name); assert(unit_path); STRV_FOREACH(p, lp->unit_path) { _cleanup_free_ char *path; path = path_join(arg_root, *p, unit_name); if (!path) return log_oom(); if (access(path, F_OK) == 0) { *unit_path = path; path = NULL; return 1; } } return 0; } static int unit_find_paths( sd_bus *bus, const char *unit_name, LookupPaths *lp, char **fragment_path, char ***dropin_paths) { _cleanup_free_ char *path = NULL; _cleanup_strv_free_ char **dropins = NULL; int r; /** * Finds where the unit is defined on disk. Returns 0 if the unit * is not found. Returns 1 if it is found, and sets * - the path to the unit in *path, if it exists on disk, * - and a strv of existing drop-ins in *dropins, * if the arg is not NULL and any dropins were found. */ assert(unit_name); assert(fragment_path); assert(lp); if (!install_client_side() && !unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *unit = NULL; unit = unit_dbus_path_from_name(unit_name); if (!unit) return log_oom(); r = sd_bus_get_property_string( bus, "org.freedesktop.systemd1", unit, "org.freedesktop.systemd1.Unit", "FragmentPath", &error, &path); if (r < 0) return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r)); if (dropin_paths) { r = sd_bus_get_property_strv( bus, "org.freedesktop.systemd1", unit, "org.freedesktop.systemd1.Unit", "DropInPaths", &error, &dropins); if (r < 0) return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r)); } } else { _cleanup_set_free_ Set *names; names = set_new(NULL); if (!names) return log_oom(); r = set_put(names, unit_name); if (r < 0) return log_error_errno(r, "Failed to add unit name: %m"); r = unit_file_find_path(lp, unit_name, &path); if (r < 0) return r; if (r == 0) { _cleanup_free_ char *template = NULL; r = unit_name_template(unit_name, &template); if (r < 0 && r != -EINVAL) return log_error_errno(r, "Failed to determine template name: %m"); if (r >= 0) { r = unit_file_find_path(lp, template, &path); if (r < 0) return r; } } if (dropin_paths) { r = unit_file_find_dropin_paths(lp->unit_path, NULL, names, &dropins); if (r < 0) return r; } } r = 0; if (!isempty(path)) { *fragment_path = path; path = NULL; r = 1; } if (dropin_paths && !strv_isempty(dropins)) { *dropin_paths = dropins; dropins = NULL; r = 1; } if (r == 0) log_error("No files found for %s.", unit_name); return r; } static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *buf = NULL; const char *path, *state; int r; assert(name); /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it * isn't loaded. */ r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "GetUnit", &error, &reply, "s", name); if (r < 0) { if (!sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT)) return log_error_errno(r, "Failed to retrieve unit: %s", bus_error_message(&error, r)); /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are * considered inactive. */ state = "inactive"; } else { r = sd_bus_message_read(reply, "o", &path); if (r < 0) return bus_log_parse_error(r); r = sd_bus_get_property_string( bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Unit", "ActiveState", &error, &buf); if (r < 0) return log_error_errno(r, "Failed to retrieve unit state: %s", bus_error_message(&error, r)); state = buf; } if (!quiet) puts(state); return nulstr_contains(good_states, state); } static int check_triggering_units( sd_bus *bus, const char *name) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL; _cleanup_strv_free_ char **triggered_by = NULL; bool print_warning_label = true; char **i; int r; r = unit_name_mangle(name, UNIT_NAME_NOGLOB, &n); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); path = unit_dbus_path_from_name(n); if (!path) return log_oom(); r = sd_bus_get_property_string( bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Unit", "LoadState", &error, &state); if (r < 0) return log_error_errno(r, "Failed to get load state of %s: %s", n, bus_error_message(&error, r)); if (streq(state, "masked")) return 0; r = sd_bus_get_property_strv( bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Unit", "TriggeredBy", &error, &triggered_by); if (r < 0) return log_error_errno(r, "Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r)); STRV_FOREACH(i, triggered_by) { r = check_one_unit(bus, *i, "active\0reloading\0", true); if (r < 0) return log_error_errno(r, "Failed to check unit: %m"); if (r == 0) continue; if (print_warning_label) { log_warning("Warning: Stopping %s, but it can still be activated by:", n); print_warning_label = false; } log_warning(" %s", *i); } return 0; } static const struct { const char *verb; const char *method; } unit_actions[] = { { "start", "StartUnit" }, { "stop", "StopUnit" }, { "condstop", "StopUnit" }, { "reload", "ReloadUnit" }, { "restart", "RestartUnit" }, { "try-restart", "TryRestartUnit" }, { "condrestart", "TryRestartUnit" }, { "reload-or-restart", "ReloadOrRestartUnit" }, { "try-reload-or-restart", "ReloadOrTryRestartUnit" }, { "reload-or-try-restart", "ReloadOrTryRestartUnit" }, { "condreload", "ReloadOrTryRestartUnit" }, { "force-reload", "ReloadOrTryRestartUnit" } }; static const char *verb_to_method(const char *verb) { uint i; for (i = 0; i < ELEMENTSOF(unit_actions); i++) if (streq_ptr(unit_actions[i].verb, verb)) return unit_actions[i].method; return "StartUnit"; } static const char *method_to_verb(const char *method) { uint i; for (i = 0; i < ELEMENTSOF(unit_actions); i++) if (streq_ptr(unit_actions[i].method, method)) return unit_actions[i].verb; return "n/a"; } static int start_unit_one( sd_bus *bus, const char *method, const char *name, const char *mode, sd_bus_error *error, BusWaitForJobs *w) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *path; int r; assert(method); assert(name); assert(mode); assert(error); log_debug("Calling manager for %s on %s, %s", method, name, mode); r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", method, error, &reply, "ss", name, mode); if (r < 0) { const char *verb; if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL) /* There's always a fallback possible for * legacy actions. */ return -EADDRNOTAVAIL; verb = method_to_verb(method); log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r)); if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) && !sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED)) log_error("See system logs and 'systemctl status %s' for details.", name); return r; } r = sd_bus_message_read(reply, "o", &path); if (r < 0) return bus_log_parse_error(r); if (need_daemon_reload(bus, name) > 0) warn_unit_file_changed(name); if (w) { log_debug("Adding %s to the set", path); r = bus_wait_for_jobs_add(w, path); if (r < 0) return log_oom(); } return 0; } static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) { _cleanup_strv_free_ char **mangled = NULL, **globs = NULL; char **name; int r, i; assert(bus); assert(ret); STRV_FOREACH(name, names) { char *t; if (suffix) r = unit_name_mangle_with_suffix(*name, UNIT_NAME_GLOB, suffix, &t); else r = unit_name_mangle(*name, UNIT_NAME_GLOB, &t); if (r < 0) return log_error_errno(r, "Failed to mangle name: %m"); if (string_is_glob(t)) r = strv_consume(&globs, t); else r = strv_consume(&mangled, t); if (r < 0) return log_oom(); } /* Query the manager only if any of the names are a glob, since * this is fairly expensive */ if (!strv_isempty(globs)) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ UnitInfo *unit_infos = NULL; size_t allocated, n; r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply); if (r < 0) return r; n = strv_length(mangled); allocated = n + 1; for (i = 0; i < r; i++) { if (!GREEDY_REALLOC(mangled, allocated, n+2)) return log_oom(); mangled[n] = strdup(unit_infos[i].id); if (!mangled[n]) return log_oom(); mangled[++n] = NULL; } } *ret = mangled; mangled = NULL; /* do not free */ return 0; } static const struct { const char *target; const char *verb; const char *mode; } action_table[_ACTION_MAX] = { [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" }, [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" }, [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" }, [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" }, [ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" }, [ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" }, [ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" }, [ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" }, [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" }, [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" }, [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" }, [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" }, [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" }, [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" }, [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" }, }; static enum action verb_to_action(const char *verb) { enum action i; for (i = _ACTION_INVALID; i < _ACTION_MAX; i++) if (streq_ptr(action_table[i].verb, verb)) return i; return _ACTION_INVALID; } static int start_unit(int argc, char *argv[], void *userdata) { _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; const char *method, *mode, *one_name, *suffix = NULL; _cleanup_strv_free_ char **names = NULL; sd_bus *bus; char **name; int r = 0; ask_password_agent_open_if_enabled(); polkit_agent_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; if (arg_action == ACTION_SYSTEMCTL) { enum action action; method = verb_to_method(argv[0]); action = verb_to_action(argv[0]); if (streq(argv[0], "isolate")) { mode = "isolate"; suffix = ".target"; } else mode = action_table[action].mode ?: arg_job_mode; one_name = action_table[action].target; } else { assert(arg_action < ELEMENTSOF(action_table)); assert(action_table[arg_action].target); method = "StartUnit"; mode = action_table[arg_action].mode; one_name = action_table[arg_action].target; } if (one_name) names = strv_new(one_name, NULL); else { r = expand_names(bus, strv_skip(argv, 1), suffix, &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); } if (!arg_no_block) { r = bus_wait_for_jobs_new(bus, &w); if (r < 0) return log_error_errno(r, "Could not watch jobs: %m"); } STRV_FOREACH(name, names) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int q; q = start_unit_one(bus, method, *name, mode, &error, w); if (r >= 0 && q < 0) r = translate_bus_error_to_exit_status(q, &error); } if (!arg_no_block) { int q; q = bus_wait_for_jobs(w, arg_quiet, arg_scope != UNIT_FILE_SYSTEM ? "--user" : NULL); if (q < 0) return q; /* When stopping units, warn if they can still be triggered by * another active unit (socket, path, timer) */ if (!arg_quiet && streq(method, "StopUnit")) STRV_FOREACH(name, names) check_triggering_units(bus, *name); } return r; } static int logind_set_wall_message(void) { #ifdef HAVE_LOGIND _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus; _cleanup_free_ char *m = NULL; int r; r = acquire_bus(BUS_FULL, &bus); if (r < 0) return r; m = strv_join(arg_wall, " "); if (!m) return log_oom(); r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "SetWallMessage", &error, NULL, "sb", m, !arg_no_wall); if (r < 0) return log_warning_errno(r, "Failed to set wall message, ignoring: %s", bus_error_message(&error, r)); #endif return 0; } /* Ask systemd-logind, which might grant access to unprivileged users * through PolicyKit */ static int logind_reboot(enum action a) { #ifdef HAVE_LOGIND _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *method, *description; sd_bus *bus; int r; polkit_agent_open_if_enabled(); (void) logind_set_wall_message(); r = acquire_bus(BUS_FULL, &bus); if (r < 0) return r; switch (a) { case ACTION_REBOOT: method = "Reboot"; description = "reboot system"; break; case ACTION_POWEROFF: method = "PowerOff"; description = "power off system"; break; case ACTION_SUSPEND: method = "Suspend"; description = "suspend system"; break; case ACTION_HIBERNATE: method = "Hibernate"; description = "hibernate system"; break; case ACTION_HYBRID_SLEEP: method = "HybridSleep"; description = "put system into hybrid sleep"; break; default: return -EINVAL; } r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", method, &error, NULL, "b", arg_ask_password); if (r < 0) return log_error_errno(r, "Failed to %s via logind: %s", description, bus_error_message(&error, r)); return 0; #else return -ENOSYS; #endif } static int logind_check_inhibitors(enum action a) { #ifdef HAVE_LOGIND _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_strv_free_ char **sessions = NULL; const char *what, *who, *why, *mode; uint32_t uid, pid; sd_bus *bus; unsigned c = 0; char **s; int r; if (arg_ignore_inhibitors || arg_force > 0) return 0; if (arg_when > 0) return 0; if (geteuid() == 0) return 0; if (!on_tty()) return 0; r = acquire_bus(BUS_FULL, &bus); if (r < 0) return r; r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "ListInhibitors", NULL, &reply, NULL); if (r < 0) /* If logind is not around, then there are no inhibitors... */ return 0; r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) { _cleanup_free_ char *comm = NULL, *user = NULL; _cleanup_strv_free_ char **sv = NULL; if (!streq(mode, "block")) continue; sv = strv_split(what, ":"); if (!sv) return log_oom(); if ((pid_t) pid < 0) return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid); if (!strv_contains(sv, IN_SET(a, ACTION_HALT, ACTION_POWEROFF, ACTION_REBOOT, ACTION_KEXEC) ? "shutdown" : "sleep")) continue; get_process_comm(pid, &comm); user = uid_to_name(uid); log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".", who, (pid_t) pid, strna(comm), strna(user), why); c++; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); /* Check for current sessions */ sd_get_sessions(&sessions); STRV_FOREACH(s, sessions) { _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL; if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid()) continue; if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user")) continue; if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty"))) continue; sd_session_get_tty(*s, &tty); sd_session_get_seat(*s, &seat); sd_session_get_service(*s, &service); user = uid_to_name(uid); log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty); c++; } if (c <= 0) return 0; log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.", action_table[a].verb); return -EPERM; #else return 0; #endif } static int logind_prepare_firmware_setup(void) { #ifdef HAVE_LOGIND _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus; int r; r = acquire_bus(BUS_FULL, &bus); if (r < 0) return r; r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "SetRebootToFirmwareSetup", &error, NULL, "b", true); if (r < 0) return log_error_errno(r, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error, r)); return 0; #else log_error("Cannot remotely indicate to EFI to boot into setup mode."); return -ENOSYS; #endif } static int prepare_firmware_setup(void) { int r; if (!arg_firmware_setup) return 0; if (arg_transport == BUS_TRANSPORT_LOCAL) { r = efi_set_reboot_to_firmware(true); if (r < 0) log_debug_errno(r, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m"); else return r; } return logind_prepare_firmware_setup(); } static int set_exit_code(uint8_t code) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus; int r; r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "SetExitCode", &error, NULL, "y", code); if (r < 0) return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r)); return 0; } static int start_special(int argc, char *argv[], void *userdata) { enum action a; int r; assert(argv); a = verb_to_action(argv[0]); r = logind_check_inhibitors(a); if (r < 0) return r; if (arg_force >= 2 && geteuid() != 0) { log_error("Must be root."); return -EPERM; } r = prepare_firmware_setup(); if (r < 0) return r; if (a == ACTION_REBOOT && argc > 1) { r = update_reboot_param_file(argv[1]); if (r < 0) return r; } else if (a == ACTION_EXIT && argc > 1) { uint8_t code; /* If the exit code is not given on the command line, * don't reset it to zero: just keep it as it might * have been set previously. */ r = safe_atou8(argv[1], &code); if (r < 0) return log_error_errno(r, "Invalid exit code."); r = set_exit_code(code); if (r < 0) return r; } if (arg_force >= 2 && IN_SET(a, ACTION_HALT, ACTION_POWEROFF, ACTION_REBOOT)) return halt_now(a); if (arg_force >= 1 && IN_SET(a, ACTION_HALT, ACTION_POWEROFF, ACTION_REBOOT, ACTION_KEXEC, ACTION_EXIT)) return daemon_reload(argc, argv, userdata); /* First try logind, to allow authentication with polkit */ if (IN_SET(a, ACTION_POWEROFF, ACTION_REBOOT, ACTION_SUSPEND, ACTION_HIBERNATE, ACTION_HYBRID_SLEEP)) { r = logind_reboot(a); if (r >= 0) return r; if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS)) /* requested operation is not supported or already in progress */ return r; /* On all other errors, try low-level operation */ } return start_unit(argc, argv, userdata); } static int check_unit_generic(int code, const char *good_states, char **args) { _cleanup_strv_free_ char **names = NULL; sd_bus *bus; char **name; int r; bool found = false; r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = expand_names(bus, args, NULL, &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); STRV_FOREACH(name, names) { int state; state = check_one_unit(bus, *name, good_states, arg_quiet); if (state < 0) return state; if (state > 0) found = true; } /* use the given return code for the case that we won't find * any unit which matches the list */ return found ? 0 : code; } static int check_unit_active(int argc, char *argv[], void *userdata) { /* According to LSB: 3, "program is not running" */ return check_unit_generic(3, "active\0reloading\0", strv_skip(argv, 1)); } static int check_unit_failed(int argc, char *argv[], void *userdata) { return check_unit_generic(1, "failed\0", strv_skip(argv, 1)); } static int kill_unit(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; char *kill_who = NULL, **name; sd_bus *bus; int r, q; polkit_agent_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; if (!arg_kill_who) arg_kill_who = "all"; /* --fail was specified */ if (streq(arg_job_mode, "fail")) kill_who = strjoina(arg_kill_who, "-fail", NULL); r = expand_names(bus, strv_skip(argv, 1), NULL, &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); STRV_FOREACH(name, names) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; q = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "KillUnit", &error, NULL, "ssi", *names, kill_who ? kill_who : arg_kill_who, arg_signal); if (q < 0) { log_error_errno(q, "Failed to kill unit %s: %s", *names, bus_error_message(&error, q)); if (r == 0) r = q; } } return r; } typedef struct ExecStatusInfo { char *name; char *path; char **argv; bool ignore; usec_t start_timestamp; usec_t exit_timestamp; pid_t pid; int code; int status; LIST_FIELDS(struct ExecStatusInfo, exec); } ExecStatusInfo; static void exec_status_info_free(ExecStatusInfo *i) { assert(i); free(i->name); free(i->path); strv_free(i->argv); free(i); } static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) { uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic; const char *path; uint32_t pid; int32_t code, status; int ignore, r; assert(m); assert(i); r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii"); if (r < 0) return bus_log_parse_error(r); else if (r == 0) return 0; r = sd_bus_message_read(m, "s", &path); if (r < 0) return bus_log_parse_error(r); i->path = strdup(path); if (!i->path) return log_oom(); r = sd_bus_message_read_strv(m, &i->argv); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_read(m, "bttttuii", &ignore, &start_timestamp, &start_timestamp_monotonic, &exit_timestamp, &exit_timestamp_monotonic, &pid, &code, &status); if (r < 0) return bus_log_parse_error(r); i->ignore = ignore; i->start_timestamp = (usec_t) start_timestamp; i->exit_timestamp = (usec_t) exit_timestamp; i->pid = (pid_t) pid; i->code = code; i->status = status; r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); return 1; } typedef struct UnitStatusInfo { const char *id; const char *load_state; const char *active_state; const char *sub_state; const char *unit_file_state; const char *unit_file_preset; const char *description; const char *following; char **documentation; const char *fragment_path; const char *source_path; const char *control_group; char **dropin_paths; const char *load_error; const char *result; usec_t inactive_exit_timestamp; usec_t inactive_exit_timestamp_monotonic; usec_t active_enter_timestamp; usec_t active_exit_timestamp; usec_t inactive_enter_timestamp; bool need_daemon_reload; bool transient; /* Service */ pid_t main_pid; pid_t control_pid; const char *status_text; const char *pid_file; bool running:1; int status_errno; usec_t start_timestamp; usec_t exit_timestamp; int exit_code, exit_status; usec_t condition_timestamp; bool condition_result; bool failed_condition_trigger; bool failed_condition_negate; const char *failed_condition; const char *failed_condition_parameter; usec_t assert_timestamp; bool assert_result; bool failed_assert_trigger; bool failed_assert_negate; const char *failed_assert; const char *failed_assert_parameter; /* Socket */ unsigned n_accepted; unsigned n_connections; bool accept; /* Pairs of type, path */ char **listen; /* Device */ const char *sysfs_path; /* Mount, Automount */ const char *where; /* Swap */ const char *what; /* CGroup */ uint64_t memory_current; uint64_t memory_limit; uint64_t cpu_usage_nsec; uint64_t tasks_current; uint64_t tasks_max; LIST_HEAD(ExecStatusInfo, exec); } UnitStatusInfo; static void print_status_info( UnitStatusInfo *i, bool *ellipsized) { ExecStatusInfo *p; const char *active_on, *active_off, *on, *off, *ss; usec_t timestamp; char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char since2[FORMAT_TIMESTAMP_MAX], *s2; const char *path; char **t, **t2; assert(i); /* This shows pretty information about a unit. See * print_property() for a low-level property printer */ if (streq_ptr(i->active_state, "failed")) { active_on = ansi_highlight_red(); active_off = ansi_normal(); } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) { active_on = ansi_highlight_green(); active_off = ansi_normal(); } else active_on = active_off = ""; printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id)); if (i->description && !streq_ptr(i->id, i->description)) printf(" - %s", i->description); printf("\n"); if (i->following) printf(" Follow: unit currently follows state of %s\n", i->following); if (streq_ptr(i->load_state, "error")) { on = ansi_highlight_red(); off = ansi_normal(); } else on = off = ""; path = i->source_path ? i->source_path : i->fragment_path; if (i->load_error != 0) printf(" Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error); else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset)) printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n", on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset); else if (path && !isempty(i->unit_file_state)) printf(" Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state); else if (path) printf(" Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path); else printf(" Loaded: %s%s%s\n", on, strna(i->load_state), off); if (i->transient) printf("Transient: yes\n"); if (!strv_isempty(i->dropin_paths)) { _cleanup_free_ char *dir = NULL; bool last = false; char ** dropin; STRV_FOREACH(dropin, i->dropin_paths) { if (! dir || last) { printf(dir ? " " : " Drop-In: "); dir = mfree(dir); dir = dirname_malloc(*dropin); if (!dir) { log_oom(); return; } printf("%s\n %s", dir, draw_special_char(DRAW_TREE_RIGHT)); } last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir)); printf("%s%s", basename(*dropin), last ? "\n" : ", "); } } ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state; if (ss) printf(" Active: %s%s (%s)%s", active_on, strna(i->active_state), ss, active_off); else printf(" Active: %s%s%s", active_on, strna(i->active_state), active_off); if (!isempty(i->result) && !streq(i->result, "success")) printf(" (Result: %s)", i->result); timestamp = (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp : (streq_ptr(i->active_state, "inactive") || streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp : streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp : i->active_exit_timestamp; s1 = format_timestamp_relative(since1, sizeof(since1), timestamp); s2 = format_timestamp(since2, sizeof(since2), timestamp); if (s1) printf(" since %s; %s\n", s2, s1); else if (s2) printf(" since %s\n", s2); else printf("\n"); if (!i->condition_result && i->condition_timestamp > 0) { s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp); s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp); printf("Condition: start %scondition failed%s at %s%s%s\n", ansi_highlight_yellow(), ansi_normal(), s2, s1 ? "; " : "", strempty(s1)); if (i->failed_condition_trigger) printf(" none of the trigger conditions were met\n"); else if (i->failed_condition) printf(" %s=%s%s was not met\n", i->failed_condition, i->failed_condition_negate ? "!" : "", i->failed_condition_parameter); } if (!i->assert_result && i->assert_timestamp > 0) { s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp); s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp); printf(" Assert: start %sassertion failed%s at %s%s%s\n", ansi_highlight_red(), ansi_normal(), s2, s1 ? "; " : "", strempty(s1)); if (i->failed_assert_trigger) printf(" none of the trigger assertions were met\n"); else if (i->failed_assert) printf(" %s=%s%s was not met\n", i->failed_assert, i->failed_assert_negate ? "!" : "", i->failed_assert_parameter); } if (i->sysfs_path) printf(" Device: %s\n", i->sysfs_path); if (i->where) printf(" Where: %s\n", i->where); if (i->what) printf(" What: %s\n", i->what); STRV_FOREACH(t, i->documentation) printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t); STRV_FOREACH_PAIR(t, t2, i->listen) printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t); if (i->accept) printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections); LIST_FOREACH(exec, p, i->exec) { _cleanup_free_ char *argv = NULL; bool good; /* Only show exited processes here */ if (p->code == 0) continue; argv = strv_join(p->argv, " "); printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv)); good = is_clean_exit_lsb(p->code, p->status, NULL); if (!good) { on = ansi_highlight_red(); off = ansi_normal(); } else on = off = ""; printf("%s(code=%s, ", on, sigchld_code_to_string(p->code)); if (p->code == CLD_EXITED) { const char *c; printf("status=%i", p->status); c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD); if (c) printf("/%s", c); } else printf("signal=%s", signal_to_string(p->status)); printf(")%s\n", off); if (i->main_pid == p->pid && i->start_timestamp == p->start_timestamp && i->exit_timestamp == p->start_timestamp) /* Let's not show this twice */ i->main_pid = 0; if (p->pid == i->control_pid) i->control_pid = 0; } if (i->main_pid > 0 || i->control_pid > 0) { if (i->main_pid > 0) { printf(" Main PID: "PID_FMT, i->main_pid); if (i->running) { _cleanup_free_ char *comm = NULL; get_process_comm(i->main_pid, &comm); if (comm) printf(" (%s)", comm); } else if (i->exit_code > 0) { printf(" (code=%s, ", sigchld_code_to_string(i->exit_code)); if (i->exit_code == CLD_EXITED) { const char *c; printf("status=%i", i->exit_status); c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD); if (c) printf("/%s", c); } else printf("signal=%s", signal_to_string(i->exit_status)); printf(")"); } if (i->control_pid > 0) printf(";"); } if (i->control_pid > 0) { _cleanup_free_ char *c = NULL; printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid); get_process_comm(i->control_pid, &c); if (c) printf(" (%s)", c); } printf("\n"); } if (i->status_text) printf(" Status: \"%s\"\n", i->status_text); if (i->status_errno > 0) printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno)); if (i->tasks_current != (uint64_t) -1) { printf(" Tasks: %" PRIu64, i->tasks_current); if (i->tasks_max != (uint64_t) -1) printf(" (limit: %" PRIi64 ")\n", i->tasks_max); else printf("\n"); } if (i->memory_current != (uint64_t) -1) { char buf[FORMAT_BYTES_MAX]; printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current)); if (i->memory_limit != (uint64_t) -1) printf(" (limit: %s)\n", format_bytes(buf, sizeof(buf), i->memory_limit)); else printf("\n"); } if (i->cpu_usage_nsec != (uint64_t) -1) { char buf[FORMAT_TIMESPAN_MAX]; printf(" CPU: %s\n", format_timespan(buf, sizeof(buf), i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC)); } if (i->control_group && (i->main_pid > 0 || i->control_pid > 0 || (!IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group) == 0))) { unsigned c; printf(" CGroup: %s\n", i->control_group); if (IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE)) { unsigned k = 0; pid_t extra[2]; static const char prefix[] = " "; c = columns(); if (c > sizeof(prefix) - 1) c -= sizeof(prefix) - 1; else c = 0; if (i->main_pid > 0) extra[k++] = i->main_pid; if (i->control_pid > 0) extra[k++] = i->control_pid; show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, get_output_flags()); } } if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) show_journal_by_unit( stdout, i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, arg_lines, getuid(), get_output_flags() | OUTPUT_BEGIN_NEWLINE, SD_JOURNAL_LOCAL_ONLY, arg_scope == UNIT_FILE_SYSTEM, ellipsized); if (i->need_daemon_reload) warn_unit_file_changed(i->id); } static void show_unit_help(UnitStatusInfo *i) { char **p; assert(i); if (!i->documentation) { log_info("Documentation for %s not known.", i->id); return; } STRV_FOREACH(p, i->documentation) if (startswith(*p, "man:")) show_man_page(*p + 4, false); else log_info("Can't show: %s", *p); } static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) { int r; assert(name); assert(m); assert(i); switch (contents[0]) { case SD_BUS_TYPE_STRING: { const char *s; r = sd_bus_message_read(m, "s", &s); if (r < 0) return bus_log_parse_error(r); if (!isempty(s)) { if (streq(name, "Id")) i->id = s; else if (streq(name, "LoadState")) i->load_state = s; else if (streq(name, "ActiveState")) i->active_state = s; else if (streq(name, "SubState")) i->sub_state = s; else if (streq(name, "Description")) i->description = s; else if (streq(name, "FragmentPath")) i->fragment_path = s; else if (streq(name, "SourcePath")) i->source_path = s; #ifndef NOLEGACY else if (streq(name, "DefaultControlGroup")) { const char *e; e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":"); if (e) i->control_group = e; } #endif else if (streq(name, "ControlGroup")) i->control_group = s; else if (streq(name, "StatusText")) i->status_text = s; else if (streq(name, "PIDFile")) i->pid_file = s; else if (streq(name, "SysFSPath")) i->sysfs_path = s; else if (streq(name, "Where")) i->where = s; else if (streq(name, "What")) i->what = s; else if (streq(name, "Following")) i->following = s; else if (streq(name, "UnitFileState")) i->unit_file_state = s; else if (streq(name, "UnitFilePreset")) i->unit_file_preset = s; else if (streq(name, "Result")) i->result = s; } break; } case SD_BUS_TYPE_BOOLEAN: { int b; r = sd_bus_message_read(m, "b", &b); if (r < 0) return bus_log_parse_error(r); if (streq(name, "Accept")) i->accept = b; else if (streq(name, "NeedDaemonReload")) i->need_daemon_reload = b; else if (streq(name, "ConditionResult")) i->condition_result = b; else if (streq(name, "AssertResult")) i->assert_result = b; else if (streq(name, "Transient")) i->transient = b; break; } case SD_BUS_TYPE_UINT32: { uint32_t u; r = sd_bus_message_read(m, "u", &u); if (r < 0) return bus_log_parse_error(r); if (streq(name, "MainPID")) { if (u > 0) { i->main_pid = (pid_t) u; i->running = true; } } else if (streq(name, "ControlPID")) i->control_pid = (pid_t) u; else if (streq(name, "ExecMainPID")) { if (u > 0) i->main_pid = (pid_t) u; } else if (streq(name, "NAccepted")) i->n_accepted = u; else if (streq(name, "NConnections")) i->n_connections = u; break; } case SD_BUS_TYPE_INT32: { int32_t j; r = sd_bus_message_read(m, "i", &j); if (r < 0) return bus_log_parse_error(r); if (streq(name, "ExecMainCode")) i->exit_code = (int) j; else if (streq(name, "ExecMainStatus")) i->exit_status = (int) j; else if (streq(name, "StatusErrno")) i->status_errno = (int) j; break; } case SD_BUS_TYPE_UINT64: { uint64_t u; r = sd_bus_message_read(m, "t", &u); if (r < 0) return bus_log_parse_error(r); if (streq(name, "ExecMainStartTimestamp")) i->start_timestamp = (usec_t) u; else if (streq(name, "ExecMainExitTimestamp")) i->exit_timestamp = (usec_t) u; else if (streq(name, "ActiveEnterTimestamp")) i->active_enter_timestamp = (usec_t) u; else if (streq(name, "InactiveEnterTimestamp")) i->inactive_enter_timestamp = (usec_t) u; else if (streq(name, "InactiveExitTimestamp")) i->inactive_exit_timestamp = (usec_t) u; else if (streq(name, "InactiveExitTimestampMonotonic")) i->inactive_exit_timestamp_monotonic = (usec_t) u; else if (streq(name, "ActiveExitTimestamp")) i->active_exit_timestamp = (usec_t) u; else if (streq(name, "ConditionTimestamp")) i->condition_timestamp = (usec_t) u; else if (streq(name, "AssertTimestamp")) i->assert_timestamp = (usec_t) u; else if (streq(name, "MemoryCurrent")) i->memory_current = u; else if (streq(name, "MemoryLimit")) i->memory_limit = u; else if (streq(name, "TasksCurrent")) i->tasks_current = u; else if (streq(name, "TasksMax")) i->tasks_max = u; else if (streq(name, "CPUUsageNSec")) i->cpu_usage_nsec = u; break; } case SD_BUS_TYPE_ARRAY: if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) { _cleanup_free_ ExecStatusInfo *info = NULL; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)"); if (r < 0) return bus_log_parse_error(r); info = new0(ExecStatusInfo, 1); if (!info) return log_oom(); while ((r = exec_status_info_deserialize(m, info)) > 0) { info->name = strdup(name); if (!info->name) return log_oom(); LIST_PREPEND(exec, i->exec, info); info = new0(ExecStatusInfo, 1); if (!info) return log_oom(); } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); return 0; } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) { const char *type, *path; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) { r = strv_extend(&i->listen, type); if (r < 0) return r; r = strv_extend(&i->listen, path); if (r < 0) return r; } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); return 0; } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) { r = sd_bus_message_read_strv(m, &i->dropin_paths); if (r < 0) return bus_log_parse_error(r); } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) { r = sd_bus_message_read_strv(m, &i->documentation); if (r < 0) return bus_log_parse_error(r); } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) { const char *cond, *param; int trigger, negate; int32_t state; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) { log_debug("%s %d %d %s %d", cond, trigger, negate, param, state); if (state < 0 && (!trigger || !i->failed_condition)) { i->failed_condition = cond; i->failed_condition_trigger = trigger; i->failed_condition_negate = negate; i->failed_condition_parameter = param; } } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) { const char *cond, *param; int trigger, negate; int32_t state; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) { log_debug("%s %d %d %s %d", cond, trigger, negate, param, state); if (state < 0 && (!trigger || !i->failed_assert)) { i->failed_assert = cond; i->failed_assert_trigger = trigger; i->failed_assert_negate = negate; i->failed_assert_parameter = param; } } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); } else goto skip; break; case SD_BUS_TYPE_STRUCT_BEGIN: if (streq(name, "LoadError")) { const char *n, *message; r = sd_bus_message_read(m, "(ss)", &n, &message); if (r < 0) return bus_log_parse_error(r); if (!isempty(message)) i->load_error = message; } else goto skip; break; default: goto skip; } return 0; skip: r = sd_bus_message_skip(m, contents); if (r < 0) return bus_log_parse_error(r); return 0; } static int print_property(const char *name, sd_bus_message *m, const char *contents) { int r; assert(name); assert(m); /* This is a low-level property printer, see * print_status_info() for the nicer output */ if (arg_properties && !strv_find(arg_properties, name)) { /* skip what we didn't read */ r = sd_bus_message_skip(m, contents); return r; } switch (contents[0]) { case SD_BUS_TYPE_STRUCT_BEGIN: if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) { uint32_t u; r = sd_bus_message_read(m, "(uo)", &u, NULL); if (r < 0) return bus_log_parse_error(r); if (u > 0) printf("%s=%"PRIu32"\n", name, u); else if (arg_all) printf("%s=\n", name); return 0; } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) { const char *s; r = sd_bus_message_read(m, "(so)", &s, NULL); if (r < 0) return bus_log_parse_error(r); if (arg_all || !isempty(s)) printf("%s=%s\n", name, s); return 0; } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) { const char *a = NULL, *b = NULL; r = sd_bus_message_read(m, "(ss)", &a, &b); if (r < 0) return bus_log_parse_error(r); if (arg_all || !isempty(a) || !isempty(b)) printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b)); return 0; } else if (streq_ptr(name, "SystemCallFilter")) { _cleanup_strv_free_ char **l = NULL; int whitelist; r = sd_bus_message_enter_container(m, 'r', "bas"); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_read(m, "b", &whitelist); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_read_strv(m, &l); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); if (arg_all || whitelist || !strv_isempty(l)) { bool first = true; char **i; fputs(name, stdout); fputc('=', stdout); if (!whitelist) fputc('~', stdout); STRV_FOREACH(i, l) { if (first) first = false; else fputc(' ', stdout); fputs(*i, stdout); } fputc('\n', stdout); } return 0; } break; case SD_BUS_TYPE_ARRAY: if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) { const char *path; int ignore; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0) printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore)); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); return 0; } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) { const char *type, *path; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) printf("%s=%s\n", type, path); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); return 0; } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) { const char *type, *path; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) printf("Listen%s=%s\n", type, path); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); return 0; } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) { const char *base; uint64_t value, next_elapse; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) { char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX]; printf("%s={ value=%s ; next_elapse=%s }\n", base, format_timespan(timespan1, sizeof(timespan1), value, 0), format_timespan(timespan2, sizeof(timespan2), next_elapse, 0)); } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); return 0; } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) { ExecStatusInfo info = {}; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)"); if (r < 0) return bus_log_parse_error(r); while ((r = exec_status_info_deserialize(m, &info)) > 0) { char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX]; _cleanup_free_ char *tt; tt = strv_join(info.argv, " "); printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }\n", name, strna(info.path), strna(tt), yes_no(info.ignore), strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)), strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)), info.pid, sigchld_code_to_string(info.code), info.status, info.code == CLD_EXITED ? "" : "/", strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status))); free(info.path); strv_free(info.argv); zero(info); } r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); return 0; } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) { const char *path, *rwm; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0) printf("%s=%s %s\n", name, strna(path), strna(rwm)); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); return 0; } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) { const char *path; uint64_t weight; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0) printf("%s=%s %" PRIu64 "\n", name, strna(path), weight); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); return 0; } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) { const char *path; uint64_t bandwidth; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0) printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(m); if (r < 0) return bus_log_parse_error(r); return 0; } break; } r = bus_print_property(name, m, arg_all); if (r < 0) return bus_log_parse_error(r); if (r == 0) { r = sd_bus_message_skip(m, contents); if (r < 0) return bus_log_parse_error(r); if (arg_all) printf("%s=[unprintable]\n", name); } return 0; } static int show_one( const char *verb, sd_bus *bus, const char *path, bool show_properties, bool *new_line, bool *ellipsized) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; UnitStatusInfo info = { .memory_current = (uint64_t) -1, .memory_limit = (uint64_t) -1, .cpu_usage_nsec = (uint64_t) -1, .tasks_current = (uint64_t) -1, .tasks_max = (uint64_t) -1, }; ExecStatusInfo *p; int r; assert(path); assert(new_line); log_debug("Showing one %s", path); r = sd_bus_call_method( bus, "org.freedesktop.systemd1", path, "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", ""); if (r < 0) return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r)); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}"); if (r < 0) return bus_log_parse_error(r); if (*new_line) printf("\n"); *new_line = true; while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { const char *name, *contents; r = sd_bus_message_read(reply, "s", &name); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_peek_type(reply, NULL, &contents); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents); if (r < 0) return bus_log_parse_error(r); if (show_properties) r = print_property(name, reply, contents); else r = status_property(name, reply, &info, contents); if (r < 0) return r; r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); } if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); r = 0; if (!show_properties) { if (streq(verb, "help")) show_unit_help(&info); else print_status_info(&info, ellipsized); } strv_free(info.documentation); strv_free(info.dropin_paths); strv_free(info.listen); if (!streq_ptr(info.active_state, "active") && !streq_ptr(info.active_state, "reloading") && streq(verb, "status")) { /* According to LSB: "program not running" */ /* 0: program is running or service is OK * 1: program is dead and /run PID file exists * 2: program is dead and /run/lock lock file exists * 3: program is not running * 4: program or service status is unknown */ if (info.pid_file && access(info.pid_file, F_OK) == 0) r = 1; else r = 3; } while ((p = info.exec)) { LIST_REMOVE(exec, info.exec, p); exec_status_info_free(p); } return r; } static int get_unit_dbus_path_by_pid( sd_bus *bus, uint32_t pid, char **unit) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; char *u; int r; r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "GetUnitByPID", &error, &reply, "u", pid); if (r < 0) return log_error_errno(r, "Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r)); r = sd_bus_message_read(reply, "o", &u); if (r < 0) return bus_log_parse_error(r); u = strdup(u); if (!u) return log_oom(); *unit = u; return 0; } static int show_all( const char* verb, sd_bus *bus, bool show_properties, bool *new_line, bool *ellipsized) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ UnitInfo *unit_infos = NULL; const UnitInfo *u; unsigned c; int r, ret = 0; r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply); if (r < 0) return r; pager_open_if_enabled(); c = (unsigned) r; qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info); for (u = unit_infos; u < unit_infos + c; u++) { _cleanup_free_ char *p = NULL; p = unit_dbus_path_from_name(u->id); if (!p) return log_oom(); r = show_one(verb, bus, p, show_properties, new_line, ellipsized); if (r < 0) return r; else if (r > 0 && ret == 0) ret = r; } return ret; } static int show_system_status(sd_bus *bus) { char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX]; _cleanup_free_ char *hn = NULL; _cleanup_(machine_info_clear) struct machine_info mi = {}; const char *on, *off; int r; hn = gethostname_malloc(); if (!hn) return log_oom(); r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi); if (r < 0) return log_error_errno(r, "Failed to read server status: %m"); if (streq_ptr(mi.state, "degraded")) { on = ansi_highlight_red(); off = ansi_normal(); } else if (!streq_ptr(mi.state, "running")) { on = ansi_highlight_yellow(); off = ansi_normal(); } else on = off = ""; printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn); printf(" State: %s%s%s\n", on, strna(mi.state), off); printf(" Jobs: %u queued\n", mi.n_jobs); printf(" Failed: %u units\n", mi.n_failed_units); printf(" Since: %s; %s\n", format_timestamp(since2, sizeof(since2), mi.timestamp), format_timestamp_relative(since1, sizeof(since1), mi.timestamp)); printf(" CGroup: %s\n", mi.control_group ?: "/"); if (IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE)) { static const char prefix[] = " "; unsigned c; c = columns(); if (c > sizeof(prefix) - 1) c -= sizeof(prefix) - 1; else c = 0; show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, get_output_flags()); } return 0; } static int show(int argc, char *argv[], void *userdata) { bool show_properties, show_status, show_help, new_line = false; bool ellipsized = false; int r, ret = 0; sd_bus *bus; assert(argv); show_properties = streq(argv[0], "show"); show_status = streq(argv[0], "status"); show_help = streq(argv[0], "help"); if (show_help && argc <= 1) { log_error("This command expects one or more unit names. Did you mean --help?"); return -EINVAL; } pager_open_if_enabled(); if (show_status) /* Increase max number of open files to 16K if we can, we * might needs this when browsing journal files, which might * be split up into many files. */ setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384)); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; /* If no argument is specified inspect the manager itself */ if (show_properties && argc <= 1) return show_one(argv[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized); if (show_status && argc <= 1) { pager_open_if_enabled(); show_system_status(bus); new_line = true; if (arg_all) ret = show_all(argv[0], bus, false, &new_line, &ellipsized); } else { _cleanup_free_ char **patterns = NULL; char **name; STRV_FOREACH(name, strv_skip(argv, 1)) { _cleanup_free_ char *unit = NULL; uint32_t id; if (safe_atou32(*name, &id) < 0) { if (strv_push(&patterns, *name) < 0) return log_oom(); continue; } else if (show_properties) { /* Interpret as job id */ if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0) return log_oom(); } else { /* Interpret as PID */ r = get_unit_dbus_path_by_pid(bus, id, &unit); if (r < 0) { ret = r; continue; } } r = show_one(argv[0], bus, unit, show_properties, &new_line, &ellipsized); if (r < 0) return r; else if (r > 0 && ret == 0) ret = r; } if (!strv_isempty(patterns)) { _cleanup_strv_free_ char **names = NULL; r = expand_names(bus, patterns, NULL, &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); STRV_FOREACH(name, names) { _cleanup_free_ char *unit; unit = unit_dbus_path_from_name(*name); if (!unit) return log_oom(); r = show_one(argv[0], bus, unit, show_properties, &new_line, &ellipsized); if (r < 0) return r; else if (r > 0 && ret == 0) ret = r; } } } if (ellipsized && !arg_quiet) printf("Hint: Some lines were ellipsized, use -l to show in full.\n"); return ret; } static int init_home_and_lookup_paths(char **user_home, char **user_runtime, LookupPaths *lp) { int r; assert(user_home); assert(user_runtime); assert(lp); if (arg_scope == UNIT_FILE_USER) { r = user_config_home(user_home); if (r < 0) return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m"); else if (r == 0) return log_error_errno(ENOTDIR, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set."); r = user_runtime_dir(user_runtime); if (r < 0) return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m"); else if (r == 0) return log_error_errno(ENOTDIR, "Cannot find units: $XDG_RUNTIME_DIR is not set."); } r = lookup_paths_init_from_scope(lp, arg_scope, arg_root); if (r < 0) return log_error_errno(r, "Failed to query unit lookup paths: %m"); return 0; } static int cat_file(const char *filename, bool newline) { _cleanup_close_ int fd; fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return -errno; printf("%s%s# %s%s\n", newline ? "\n" : "", ansi_highlight_blue(), filename, ansi_normal()); fflush(stdout); return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, false); } static int cat(int argc, char *argv[], void *userdata) { _cleanup_free_ char *user_home = NULL; _cleanup_free_ char *user_runtime = NULL; _cleanup_lookup_paths_free_ LookupPaths lp = {}; _cleanup_strv_free_ char **names = NULL; char **name; sd_bus *bus; bool first = true; int r; if (arg_transport != BUS_TRANSPORT_LOCAL) { log_error("Cannot remotely cat units."); return -EINVAL; } r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp); if (r < 0) return r; r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = expand_names(bus, strv_skip(argv, 1), NULL, &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); pager_open_if_enabled(); STRV_FOREACH(name, names) { _cleanup_free_ char *fragment_path = NULL; _cleanup_strv_free_ char **dropin_paths = NULL; char **path; r = unit_find_paths(bus, *name, &lp, &fragment_path, &dropin_paths); if (r < 0) return r; else if (r == 0) return -ENOENT; if (first) first = false; else puts(""); if (fragment_path) { r = cat_file(fragment_path, false); if (r < 0) return log_warning_errno(r, "Failed to cat %s: %m", fragment_path); } STRV_FOREACH(path, dropin_paths) { r = cat_file(*path, path == dropin_paths); if (r < 0) return log_warning_errno(r, "Failed to cat %s: %m", *path); } } return 0; } static int set_property(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *n = NULL; sd_bus *bus; char **i; int r; polkit_agent_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "SetUnitProperties"); if (r < 0) return bus_log_create_error(r); r = unit_name_mangle(argv[1], UNIT_NAME_NOGLOB, &n); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); r = sd_bus_message_append(m, "sb", n, arg_runtime); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)"); if (r < 0) return bus_log_create_error(r); STRV_FOREACH(i, strv_skip(argv, 2)) { r = bus_append_unit_property_assignment(m, *i); if (r < 0) return r; } r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, NULL); if (r < 0) return log_error_errno(r, "Failed to set unit properties on %s: %s", n, bus_error_message(&error, r)); return 0; } static int daemon_reload(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *method; sd_bus *bus; int r; polkit_agent_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; if (arg_action == ACTION_RELOAD) method = "Reload"; else if (arg_action == ACTION_REEXEC) method = "Reexecute"; else { assert(arg_action == ACTION_SYSTEMCTL); method = streq(argv[0], "clear-jobs") || streq(argv[0], "cancel") ? "ClearJobs" : streq(argv[0], "daemon-reexec") ? "Reexecute" : streq(argv[0], "reset-failed") ? "ResetFailed" : streq(argv[0], "halt") ? "Halt" : streq(argv[0], "poweroff") ? "PowerOff" : streq(argv[0], "reboot") ? "Reboot" : streq(argv[0], "kexec") ? "KExec" : streq(argv[0], "exit") ? "Exit" : /* "daemon-reload" */ "Reload"; } r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", method, &error, NULL, NULL); if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL) /* There's always a fallback possible for * legacy actions. */ r = -EADDRNOTAVAIL; else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute")) /* On reexecution, we expect a disconnect, not a * reply */ r = 0; else if (r < 0) return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r)); return r < 0 ? r : 0; } static int reset_failed(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; sd_bus *bus; char **name; int r, q; if (argc <= 1) return daemon_reload(argc, argv, userdata); polkit_agent_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = expand_names(bus, strv_skip(argv, 1), NULL, &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); STRV_FOREACH(name, names) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; q = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "ResetFailedUnit", &error, NULL, "s", *name); if (q < 0) { log_error_errno(q, "Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q)); if (r == 0) r = q; } } return r; } static int show_environment(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *text; sd_bus *bus; int r; pager_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = sd_bus_get_property( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Environment", &error, &reply, "as"); if (r < 0) return log_error_errno(r, "Failed to get environment: %s", bus_error_message(&error, r)); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0) puts(text); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); return 0; } static int switch_root(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *cmdline_init = NULL; const char *root, *init; sd_bus *bus; int r; if (arg_transport != BUS_TRANSPORT_LOCAL) { log_error("Cannot switch root remotely."); return -EINVAL; } if (argc < 2 || argc > 3) { log_error("Wrong number of arguments."); return -EINVAL; } root = argv[1]; if (argc >= 3) init = argv[2]; else { r = parse_env_file("/proc/cmdline", WHITESPACE, "init", &cmdline_init, NULL); if (r < 0) log_debug_errno(r, "Failed to parse /proc/cmdline: %m"); init = cmdline_init; } if (isempty(init)) init = NULL; if (init) { const char *root_systemd_path = NULL, *root_init_path = NULL; root_systemd_path = strjoina(root, "/" SYSTEMD_BINARY_PATH); root_init_path = strjoina(root, "/", init); /* If the passed init is actually the same as the * systemd binary, then let's suppress it. */ if (files_same(root_init_path, root_systemd_path) > 0) init = NULL; } r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; log_debug("Switching root - root: %s; init: %s", root, strna(init)); r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "SwitchRoot", &error, NULL, "ss", root, init); if (r < 0) return log_error_errno(r, "Failed to switch root: %s", bus_error_message(&error, r)); return 0; } static int set_environment(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; const char *method; sd_bus *bus; int r; assert(argc > 1); assert(argv); polkit_agent_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; method = streq(argv[0], "set-environment") ? "SetEnvironment" : "UnsetEnvironment"; r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", method); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append_strv(m, strv_skip(argv, 1)); if (r < 0) return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, NULL); if (r < 0) return log_error_errno(r, "Failed to set environment: %s", bus_error_message(&error, r)); return 0; } static int import_environment(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; sd_bus *bus; int r; polkit_agent_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "SetEnvironment"); if (r < 0) return bus_log_create_error(r); if (argc < 2) r = sd_bus_message_append_strv(m, environ); else { char **a, **b; r = sd_bus_message_open_container(m, 'a', "s"); if (r < 0) return bus_log_create_error(r); STRV_FOREACH(a, strv_skip(argv, 1)) { if (!env_name_is_valid(*a)) { log_error("Not a valid environment variable name: %s", *a); return -EINVAL; } STRV_FOREACH(b, environ) { const char *eq; eq = startswith(*b, *a); if (eq && *eq == '=') { r = sd_bus_message_append(m, "s", *b); if (r < 0) return bus_log_create_error(r); break; } } } r = sd_bus_message_close_container(m); } if (r < 0) return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, NULL); if (r < 0) return log_error_errno(r, "Failed to import environment: %s", bus_error_message(&error, r)); return 0; } static int enable_sysv_units(const char *verb, char **args) { int r = 0; #if defined(HAVE_SYSV_COMPAT) unsigned f = 0; _cleanup_lookup_paths_free_ LookupPaths paths = {}; if (arg_scope != UNIT_FILE_SYSTEM) return 0; if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0) return 0; if (!STR_IN_SET(verb, "enable", "disable", "is-enabled")) return 0; /* Processes all SysV units, and reshuffles the array so that * afterwards only the native units remain */ r = lookup_paths_init(&paths, MANAGER_SYSTEM, false, arg_root, NULL, NULL, NULL); if (r < 0) return r; r = 0; while (args[f]) { const char *name; _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL; bool found_native = false, found_sysv; unsigned c = 1; const char *argv[6] = { ROOTLIBEXECDIR "/systemd-sysv-install", NULL, NULL, NULL, NULL }; char **k; int j; pid_t pid; siginfo_t status; name = args[f++]; if (!endswith(name, ".service")) continue; if (path_is_absolute(name)) continue; STRV_FOREACH(k, paths.unit_path) { _cleanup_free_ char *path = NULL; path = path_join(arg_root, *k, name); if (!path) return log_oom(); found_native = access(path, F_OK) >= 0; if (found_native) break; } /* If we have both a native unit and a SysV script, * enable/disable them both (below); for is-enabled, prefer the * native unit */ if (found_native && streq(verb, "is-enabled")) continue; p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name); if (!p) return log_oom(); p[strlen(p) - strlen(".service")] = 0; found_sysv = access(p, F_OK) >= 0; if (!found_sysv) continue; if (found_native) log_info("Synchronizing state of %s with SysV init with %s...", name, argv[0]); else log_info("%s is not a native service, redirecting to systemd-sysv-install", name); if (!isempty(arg_root)) argv[c++] = q = strappend("--root=", arg_root); argv[c++] = verb; argv[c++] = basename(p); argv[c] = NULL; l = strv_join((char**)argv, " "); if (!l) return log_oom(); log_info("Executing %s", l); pid = fork(); if (pid < 0) return log_error_errno(errno, "Failed to fork: %m"); else if (pid == 0) { /* Child */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); execv(argv[0], (char**) argv); log_error_errno(r, "Failed to execute %s: %m", argv[0]); _exit(EXIT_FAILURE); } j = wait_for_terminate(pid, &status); if (j < 0) { log_error_errno(j, "Failed to wait for child: %m"); return j; } if (status.si_code == CLD_EXITED) { if (streq(verb, "is-enabled")) { if (status.si_status == 0) { if (!arg_quiet) puts("enabled"); r = 1; } else { if (!arg_quiet) puts("disabled"); } } else if (status.si_status != 0) return -EINVAL; } else return -EPROTO; if (found_native) continue; /* Remove this entry, so that we don't try enabling it as native unit */ assert(f > 0); f--; assert(args[f] == name); strv_remove(args, name); } #endif return r; } static int mangle_names(char **original_names, char ***mangled_names) { char **i, **l, **name; int r; l = i = new(char*, strv_length(original_names) + 1); if (!l) return log_oom(); STRV_FOREACH(name, original_names) { /* When enabling units qualified path names are OK, * too, hence allow them explicitly. */ if (is_path(*name)) { *i = strdup(*name); if (!*i) { strv_free(l); return log_oom(); } } else { r = unit_name_mangle(*name, UNIT_NAME_NOGLOB, i); if (r < 0) { strv_free(l); return log_error_errno(r, "Failed to mangle unit name: %m"); } } i++; } *i = NULL; *mangled_names = l; return 0; } static int enable_unit(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; const char *verb = argv[0]; UnitFileChange *changes = NULL; unsigned n_changes = 0; int carries_install_info = -1; int r; if (!argv[1]) return 0; r = mangle_names(strv_skip(argv, 1), &names); if (r < 0) return r; r = enable_sysv_units(verb, names); if (r < 0) return r; /* If the operation was fully executed by the SysV compat, * let's finish early */ if (strv_isempty(names)) return 0; if (install_client_side()) { if (streq(verb, "enable")) { r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes); carries_install_info = r; } else if (streq(verb, "disable")) r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes); else if (streq(verb, "reenable")) { r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes); carries_install_info = r; } else if (streq(verb, "link")) r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes); else if (streq(verb, "preset")) { r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes); carries_install_info = r; } else if (streq(verb, "mask")) r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes); else if (streq(verb, "unmask")) r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes); else assert_not_reached("Unknown verb"); if (r == -ESHUTDOWN) return log_error_errno(r, "Unit file is masked."); if (r < 0) return log_error_errno(r, "Operation failed: %m"); if (!arg_quiet) dump_unit_file_changes(changes, n_changes); r = 0; } else { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int expect_carries_install_info = false; bool send_force = true, send_preset_mode = false; const char *method; sd_bus *bus; polkit_agent_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; if (streq(verb, "enable")) { method = "EnableUnitFiles"; expect_carries_install_info = true; } else if (streq(verb, "disable")) { method = "DisableUnitFiles"; send_force = false; } else if (streq(verb, "reenable")) { method = "ReenableUnitFiles"; expect_carries_install_info = true; } else if (streq(verb, "link")) method = "LinkUnitFiles"; else if (streq(verb, "preset")) { if (arg_preset_mode != UNIT_FILE_PRESET_FULL) { method = "PresetUnitFilesWithMode"; send_preset_mode = true; } else method = "PresetUnitFiles"; expect_carries_install_info = true; } else if (streq(verb, "mask")) method = "MaskUnitFiles"; else if (streq(verb, "unmask")) { method = "UnmaskUnitFiles"; send_force = false; } else assert_not_reached("Unknown verb"); r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", method); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append_strv(m, names); if (r < 0) return bus_log_create_error(r); if (send_preset_mode) { r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode)); if (r < 0) return bus_log_create_error(r); } r = sd_bus_message_append(m, "b", arg_runtime); if (r < 0) return bus_log_create_error(r); if (send_force) { r = sd_bus_message_append(m, "b", arg_force); if (r < 0) return bus_log_create_error(r); } r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r)); if (expect_carries_install_info) { r = sd_bus_message_read(reply, "b", &carries_install_info); if (r < 0) return bus_log_parse_error(r); } r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes); if (r < 0) return r; /* Try to reload if enabled */ if (!arg_no_reload) r = daemon_reload(argc, argv, userdata); else r = 0; } if (carries_install_info == 0) log_warning("The unit files have no [Install] section. They are not meant to be enabled\n" "using systemctl.\n" "Possible reasons for having this kind of units are:\n" "1) A unit may be statically enabled by being symlinked from another unit's\n" " .wants/ or .requires/ directory.\n" "2) A unit's purpose may be to act as a helper for some other unit which has\n" " a requirement dependency on it.\n" "3) A unit may be started when needed via activation (socket, path, timer,\n" " D-Bus, udev, scripted systemctl call, ...).\n"); if (arg_now && n_changes > 0 && STR_IN_SET(argv[0], "enable", "disable", "mask")) { char *new_args[n_changes + 2]; sd_bus *bus; unsigned i; r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) goto finish; new_args[0] = (char*) (streq(argv[0], "enable") ? "start" : "stop"); for (i = 0; i < n_changes; i++) new_args[i + 1] = basename(changes[i].path); new_args[i + 1] = NULL; r = start_unit(strv_length(new_args), new_args, userdata); } finish: unit_file_changes_free(changes, n_changes); return r; } static int add_dependency(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; _cleanup_free_ char *target = NULL; const char *verb = argv[0]; UnitDependency dep; int r = 0; if (!argv[1]) return 0; r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".target", &target); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); r = mangle_names(strv_skip(argv, 2), &names); if (r < 0) return r; if (streq(verb, "add-wants")) dep = UNIT_WANTS; else if (streq(verb, "add-requires")) dep = UNIT_REQUIRES; else assert_not_reached("Unknown verb"); if (install_client_side()) { UnitFileChange *changes = NULL; unsigned n_changes = 0; r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes); if (r == -ESHUTDOWN) return log_error_errno(r, "Unit file is masked."); if (r < 0) return log_error_errno(r, "Can't add dependency: %m"); if (!arg_quiet) dump_unit_file_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); } else { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus; polkit_agent_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "AddDependencyUnitFiles"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append_strv(m, names); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force); if (r < 0) return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r)); r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) return r; if (!arg_no_reload) r = daemon_reload(argc, argv, userdata); else r = 0; } return r; } static int preset_all(int argc, char *argv[], void *userdata) { UnitFileChange *changes = NULL; unsigned n_changes = 0; int r; if (install_client_side()) { r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes); if (r < 0) { log_error_errno(r, "Operation failed: %m"); goto finish; } if (!arg_quiet) dump_unit_file_changes(changes, n_changes); r = 0; } else { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; sd_bus *bus; polkit_agent_open_if_enabled(); r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "PresetAllUnitFiles", &error, &reply, "sbb", unit_file_preset_mode_to_string(arg_preset_mode), arg_runtime, arg_force); if (r < 0) return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r)); r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) return r; if (!arg_no_reload) r = daemon_reload(argc, argv, userdata); else r = 0; } finish: unit_file_changes_free(changes, n_changes); return r; } static int unit_is_enabled(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; bool enabled; char **name; int r; r = mangle_names(strv_skip(argv, 1), &names); if (r < 0) return r; r = enable_sysv_units(argv[0], names); if (r < 0) return r; enabled = r > 0; if (install_client_side()) { STRV_FOREACH(name, names) { UnitFileState state; r = unit_file_get_state(arg_scope, arg_root, *name, &state); if (r < 0) return log_error_errno(state, "Failed to get unit file state for %s: %m", *name); if (IN_SET(state, UNIT_FILE_ENABLED, UNIT_FILE_ENABLED_RUNTIME, UNIT_FILE_STATIC, UNIT_FILE_INDIRECT)) enabled = true; if (!arg_quiet) puts(unit_file_state_to_string(state)); } } else { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus; r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; STRV_FOREACH(name, names) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *s; r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "GetUnitFileState", &error, &reply, "s", *name); if (r < 0) return log_error_errno(r, "Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r)); r = sd_bus_message_read(reply, "s", &s); if (r < 0) return bus_log_parse_error(r); if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect")) enabled = true; if (!arg_quiet) puts(s); } } return !enabled; } static int is_system_running(int argc, char *argv[], void *userdata) { _cleanup_free_ char *state = NULL; sd_bus *bus; int r; if (running_in_chroot() > 0 || (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted())) { if (!arg_quiet) puts("offline"); return EXIT_FAILURE; } r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = sd_bus_get_property_string( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "SystemState", NULL, &state); if (r < 0) { if (!arg_quiet) puts("unknown"); return 0; } if (!arg_quiet) puts(state); return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE; } static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) { _cleanup_free_ char *t = NULL; int r; assert(new_path); assert(original_path); assert(ret_tmp_fn); r = tempfn_random(new_path, NULL, &t); if (r < 0) return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path); r = mkdir_parents(new_path, 0755); if (r < 0) return log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path); r = copy_file(original_path, t, 0, 0644, 0); if (r == -ENOENT) { r = touch(t); if (r < 0) return log_error_errno(r, "Failed to create temporary file \"%s\": %m", t); } else if (r < 0) return log_error_errno(r, "Failed to copy \"%s\" to \"%s\": %m", original_path, t); *ret_tmp_fn = t; t = NULL; return 0; } static int get_file_to_edit(const char *name, const char *user_home, const char *user_runtime, char **ret_path) { _cleanup_free_ char *path = NULL, *path2 = NULL, *run = NULL; assert(name); assert(ret_path); switch (arg_scope) { case UNIT_FILE_SYSTEM: path = path_join(arg_root, SYSTEM_CONFIG_UNIT_PATH, name); if (arg_runtime) run = path_join(arg_root, "/run/systemd/system/", name); break; case UNIT_FILE_GLOBAL: path = path_join(arg_root, USER_CONFIG_UNIT_PATH, name); if (arg_runtime) run = path_join(arg_root, "/run/systemd/user/", name); break; case UNIT_FILE_USER: assert(user_home); assert(user_runtime); path = path_join(arg_root, user_home, name); if (arg_runtime) { path2 = path_join(arg_root, USER_CONFIG_UNIT_PATH, name); if (!path2) return log_oom(); run = path_join(arg_root, user_runtime, name); } break; default: assert_not_reached("Invalid scope"); } if (!path || (arg_runtime && !run)) return log_oom(); if (arg_runtime) { if (access(path, F_OK) >= 0) { log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run, path); return -EEXIST; } if (path2 && access(path2, F_OK) >= 0) { log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run, path2); return -EEXIST; } *ret_path = run; run = NULL; } else { *ret_path = path; path = NULL; } return 0; } static int unit_file_create_dropin(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) { char *tmp_new_path, *tmp_tmp_path, *ending; int r; assert(unit_name); assert(ret_new_path); assert(ret_tmp_path); ending = strjoina(unit_name, ".d/override.conf"); r = get_file_to_edit(ending, user_home, user_runtime, &tmp_new_path); if (r < 0) return r; r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path); if (r < 0) { free(tmp_new_path); return r; } *ret_new_path = tmp_new_path; *ret_tmp_path = tmp_tmp_path; return 0; } static int unit_file_create_copy( const char *unit_name, const char *fragment_path, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) { char *tmp_new_path, *tmp_tmp_path; int r; assert(fragment_path); assert(unit_name); assert(ret_new_path); assert(ret_tmp_path); r = get_file_to_edit(unit_name, user_home, user_runtime, &tmp_new_path); if (r < 0) return r; if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) { char response; r = ask_char(&response, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path, fragment_path); if (r < 0) { free(tmp_new_path); return r; } if (response != 'y') { log_warning("%s ignored", unit_name); free(tmp_new_path); return -1; } } r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path); if (r < 0) { log_error_errno(r, "Failed to create temporary file for \"%s\": %m", tmp_new_path); free(tmp_new_path); return r; } *ret_new_path = tmp_new_path; *ret_tmp_path = tmp_tmp_path; return 0; } static int run_editor(char **paths) { pid_t pid; int r; assert(paths); pid = fork(); if (pid < 0) return log_error_errno(errno, "Failed to fork: %m"); if (pid == 0) { const char **args; char *editor, **editor_args = NULL; char **tmp_path, **original_path, *p; unsigned n_editor_args = 0, i = 1; size_t argc; (void) reset_all_signal_handlers(); (void) reset_signal_mask(); argc = strv_length(paths)/2 + 1; /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present, * we try to execute well known editors */ editor = getenv("SYSTEMD_EDITOR"); if (!editor) editor = getenv("EDITOR"); if (!editor) editor = getenv("VISUAL"); if (!isempty(editor)) { editor_args = strv_split(editor, WHITESPACE); if (!editor_args) { (void) log_oom(); _exit(EXIT_FAILURE); } n_editor_args = strv_length(editor_args); argc += n_editor_args - 1; } args = newa(const char*, argc + 1); if (n_editor_args > 0) { args[0] = editor_args[0]; for (; i < n_editor_args; i++) args[i] = editor_args[i]; } STRV_FOREACH_PAIR(original_path, tmp_path, paths) { args[i] = *tmp_path; i++; } args[i] = NULL; if (n_editor_args > 0) execvp(args[0], (char* const*) args); FOREACH_STRING(p, "editor", "nano", "vim", "vi") { args[0] = p; execvp(p, (char* const*) args); /* We do not fail if the editor doesn't exist * because we want to try each one of them before * failing. */ if (errno != ENOENT) { log_error_errno(errno, "Failed to execute %s: %m", editor); _exit(EXIT_FAILURE); } } log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL."); _exit(EXIT_FAILURE); } r = wait_for_terminate_and_warn("editor", pid, true); if (r < 0) return log_error_errno(r, "Failed to wait for child: %m"); return 0; } static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { _cleanup_free_ char *user_home = NULL; _cleanup_free_ char *user_runtime = NULL; _cleanup_lookup_paths_free_ LookupPaths lp = {}; char **name; int r; assert(names); assert(paths); r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp); if (r < 0) return r; STRV_FOREACH(name, names) { _cleanup_free_ char *path = NULL; char *new_path, *tmp_path; r = unit_find_paths(bus, *name, &lp, &path, NULL); if (r < 0) return r; else if (r == 0) return -ENOENT; else if (!path) { // FIXME: support units with path==NULL (no FragmentPath) log_error("No fragment exists for %s.", *name); return -ENOENT; } if (arg_full) r = unit_file_create_copy(*name, path, user_home, user_runtime, &new_path, &tmp_path); else r = unit_file_create_dropin(*name, user_home, user_runtime, &new_path, &tmp_path); if (r < 0) return r; r = strv_push_pair(paths, new_path, tmp_path); if (r < 0) return log_oom(); } return 0; } static int edit(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; _cleanup_strv_free_ char **paths = NULL; char **original, **tmp; sd_bus *bus; int r; if (!on_tty()) { log_error("Cannot edit units if not on a tty."); return -EINVAL; } if (arg_transport != BUS_TRANSPORT_LOCAL) { log_error("Cannot edit units remotely."); return -EINVAL; } r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; r = expand_names(bus, strv_skip(argv, 1), NULL, &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); r = find_paths_to_edit(bus, names, &paths); if (r < 0) return r; if (strv_isempty(paths)) return -ENOENT; r = run_editor(paths); if (r < 0) goto end; STRV_FOREACH_PAIR(original, tmp, paths) { /* If the temporary file is empty we ignore it. It's * useful if the user wants to cancel its modification */ if (null_or_empty_path(*tmp)) { log_warning("Editing \"%s\" canceled: temporary file is empty.", *original); continue; } r = rename(*tmp, *original); if (r < 0) { r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", *tmp, *original); goto end; } } r = 0; if (!arg_no_reload && !install_client_side()) r = daemon_reload(argc, argv, userdata); end: STRV_FOREACH_PAIR(original, tmp, paths) (void) unlink(*tmp); return r; } static void systemctl_help(void) { pager_open_if_enabled(); printf("%s [OPTIONS...] {COMMAND} ...\n\n" "Query or send control commands to the systemd manager.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --system Connect to system manager\n" " --user Connect to user service manager\n" " -H --host=[USER@]HOST\n" " Operate on remote host\n" " -M --machine=CONTAINER\n" " Operate on local container\n" " -t --type=TYPE List units of a particular type\n" " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n" " -p --property=NAME Show only properties by this name\n" " -a --all Show all loaded units/properties, including dead/empty\n" " ones. To list all units installed on the system, use\n" " the 'list-unit-files' command instead.\n" " -l --full Don't ellipsize unit names on output\n" " -r --recursive Show unit list of host and local containers\n" " --reverse Show reverse dependencies with 'list-dependencies'\n" " --job-mode=MODE Specify how to deal with already queued jobs, when\n" " queueing a new job\n" " --show-types When showing sockets, explicitly show their type\n" " -i --ignore-inhibitors\n" " When shutting down or sleeping, ignore inhibitors\n" " --kill-who=WHO Who to send signal to\n" " -s --signal=SIGNAL Which signal to send\n" " --now Start or stop unit in addition to enabling or disabling it\n" " -q --quiet Suppress output\n" " --no-block Do not wait until operation finished\n" " --no-wall Don't send wall message before halt/power-off/reboot\n" " --no-reload Don't reload daemon after en-/dis-abling unit files\n" " --no-legend Do not print a legend (column headers and hints)\n" " --no-pager Do not pipe output into a pager\n" " --no-ask-password\n" " Do not ask for system passwords\n" " --global Enable/disable unit files globally\n" " --runtime Enable unit files only temporarily until next reboot\n" " -f --force When enabling unit files, override existing symlinks\n" " When shutting down, execute action immediately\n" " --preset-mode= Apply only enable, only disable, or all presets\n" " --root=PATH Enable unit files in the specified root directory\n" " -n --lines=INTEGER Number of journal entries to show\n" " -o --output=STRING Change journal output mode (short, short-iso,\n" " short-precise, short-monotonic, verbose,\n" " export, json, json-pretty, json-sse, cat)\n" " --firmware-setup Tell the firmware to show the setup menu on next boot\n" " --plain Print unit dependencies as a list instead of a tree\n\n" "Unit Commands:\n" " list-units [PATTERN...] List loaded units\n" " list-sockets [PATTERN...] List loaded sockets ordered by address\n" " list-timers [PATTERN...] List loaded timers ordered by next elapse\n" " start NAME... Start (activate) one or more units\n" " stop NAME... Stop (deactivate) one or more units\n" " reload NAME... Reload one or more units\n" " restart NAME... Start or restart one or more units\n" " try-restart NAME... Restart one or more units if active\n" " reload-or-restart NAME... Reload one or more units if possible,\n" " otherwise start or restart\n" " try-reload-or-restart NAME... If active, reload one or more units,\n" " if supported, otherwise restart\n" " isolate NAME Start one unit and stop all others\n" " kill NAME... Send signal to processes of a unit\n" " is-active PATTERN... Check whether units are active\n" " is-failed PATTERN... Check whether units are failed\n" " status [PATTERN...|PID...] Show runtime status of one or more units\n" " show [PATTERN...|JOB...] Show properties of one or more\n" " units/jobs or the manager\n" " cat PATTERN... Show files and drop-ins of one or more units\n" " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n" " help PATTERN...|PID... Show manual for one or more units\n" " reset-failed [PATTERN...] Reset failed state for all, one, or more\n" " units\n" " list-dependencies [NAME] Recursively show units which are required\n" " or wanted by this unit or by which this\n" " unit is required or wanted\n\n" "Unit File Commands:\n" " list-unit-files [PATTERN...] List installed unit files\n" " enable NAME... Enable one or more unit files\n" " disable NAME... Disable one or more unit files\n" " reenable NAME... Reenable one or more unit files\n" " preset NAME... Enable/disable one or more unit files\n" " based on preset configuration\n" " preset-all Enable/disable all unit files based on\n" " preset configuration\n" " is-enabled NAME... Check whether unit files are enabled\n" " mask NAME... Mask one or more units\n" " unmask NAME... Unmask one or more units\n" " link PATH... Link one or more units files into\n" " the search path\n" " add-wants TARGET NAME... Add 'Wants' dependency for the target\n" " on specified one or more units\n" " add-requires TARGET NAME... Add 'Requires' dependency for the target\n" " on specified one or more units\n" " edit NAME... Edit one or more unit files\n" " get-default Get the name of the default target\n" " set-default NAME Set the default target\n\n" "Machine Commands:\n" " list-machines [PATTERN...] List local containers and host\n\n" "Job Commands:\n" " list-jobs [PATTERN...] List jobs\n" " cancel [JOB...] Cancel all, one, or more jobs\n\n" "Environment Commands:\n" " show-environment Dump environment\n" " set-environment NAME=VALUE... Set one or more environment variables\n" " unset-environment NAME... Unset one or more environment variables\n" " import-environment [NAME...] Import all or some environment variables\n\n" "Manager Lifecycle Commands:\n" " daemon-reload Reload systemd manager configuration\n" " daemon-reexec Reexecute systemd manager\n\n" "System Commands:\n" " is-system-running Check whether system is fully running\n" " default Enter system default mode\n" " rescue Enter system rescue mode\n" " emergency Enter system emergency mode\n" " halt Shut down and halt the system\n" " poweroff Shut down and power-off the system\n" " reboot [ARG] Shut down and reboot the system\n" " kexec Shut down and reboot the system with kexec\n" " exit [EXIT_CODE] Request user instance or container exit\n" " switch-root ROOT [INIT] Change to a different root file system\n" " suspend Suspend the system\n" " hibernate Hibernate the system\n" " hybrid-sleep Hibernate and suspend the system\n", program_invocation_short_name); } static void halt_help(void) { printf("%s [OPTIONS...]%s\n\n" "%s the system.\n\n" " --help Show this help\n" " --halt Halt the machine\n" " -p --poweroff Switch off the machine\n" " --reboot Reboot the machine\n" " -f --force Force immediate halt/power-off/reboot\n" " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n" " -d --no-wtmp Don't write wtmp record\n" " --no-wall Don't send wall message before halt/power-off/reboot\n", program_invocation_short_name, arg_action == ACTION_REBOOT ? " [ARG]" : "", arg_action == ACTION_REBOOT ? "Reboot" : arg_action == ACTION_POWEROFF ? "Power off" : "Halt"); } static void shutdown_help(void) { printf("%s [OPTIONS...] [TIME] [WALL...]\n\n" "Shut down the system.\n\n" " --help Show this help\n" " -H --halt Halt the machine\n" " -P --poweroff Power-off the machine\n" " -r --reboot Reboot the machine\n" " -h Equivalent to --poweroff, overridden by --halt\n" " -k Don't halt/power-off/reboot, just send warnings\n" " --no-wall Don't send wall message before halt/power-off/reboot\n" " -c Cancel a pending shutdown\n", program_invocation_short_name); } static void telinit_help(void) { printf("%s [OPTIONS...] {COMMAND}\n\n" "Send control commands to the init daemon.\n\n" " --help Show this help\n" " --no-wall Don't send wall message before halt/power-off/reboot\n\n" "Commands:\n" " 0 Power-off the machine\n" " 6 Reboot the machine\n" " 2, 3, 4, 5 Start runlevelX.target unit\n" " 1, s, S Enter rescue mode\n" " q, Q Reload init daemon configuration\n" " u, U Reexecute init daemon\n", program_invocation_short_name); } static void runlevel_help(void) { printf("%s [OPTIONS...]\n\n" "Prints the previous and current runlevel of the init system.\n\n" " --help Show this help\n", program_invocation_short_name); } static void help_types(void) { int i; if (!arg_no_legend) puts("Available unit types:"); for (i = 0; i < _UNIT_TYPE_MAX; i++) puts(unit_type_to_string(i)); } static void help_states(void) { int i; if (!arg_no_legend) puts("Available unit load states:"); for (i = 0; i < _UNIT_LOAD_STATE_MAX; i++) puts(unit_load_state_to_string(i)); if (!arg_no_legend) puts("\nAvailable unit active states:"); for (i = 0; i < _UNIT_ACTIVE_STATE_MAX; i++) puts(unit_active_state_to_string(i)); if (!arg_no_legend) puts("\nAvailable automount unit substates:"); for (i = 0; i < _AUTOMOUNT_STATE_MAX; i++) puts(automount_state_to_string(i)); if (!arg_no_legend) puts("\nAvailable busname unit substates:"); for (i = 0; i < _BUSNAME_STATE_MAX; i++) puts(busname_state_to_string(i)); if (!arg_no_legend) puts("\nAvailable device unit substates:"); for (i = 0; i < _DEVICE_STATE_MAX; i++) puts(device_state_to_string(i)); if (!arg_no_legend) puts("\nAvailable mount unit substates:"); for (i = 0; i < _MOUNT_STATE_MAX; i++) puts(mount_state_to_string(i)); if (!arg_no_legend) puts("\nAvailable path unit substates:"); for (i = 0; i < _PATH_STATE_MAX; i++) puts(path_state_to_string(i)); if (!arg_no_legend) puts("\nAvailable scope unit substates:"); for (i = 0; i < _SCOPE_STATE_MAX; i++) puts(scope_state_to_string(i)); if (!arg_no_legend) puts("\nAvailable service unit substates:"); for (i = 0; i < _SERVICE_STATE_MAX; i++) puts(service_state_to_string(i)); if (!arg_no_legend) puts("\nAvailable slice unit substates:"); for (i = 0; i < _SLICE_STATE_MAX; i++) puts(slice_state_to_string(i)); if (!arg_no_legend) puts("\nAvailable socket unit substates:"); for (i = 0; i < _SOCKET_STATE_MAX; i++) puts(socket_state_to_string(i)); if (!arg_no_legend) puts("\nAvailable swap unit substates:"); for (i = 0; i < _SWAP_STATE_MAX; i++) puts(swap_state_to_string(i)); if (!arg_no_legend) puts("\nAvailable target unit substates:"); for (i = 0; i < _TARGET_STATE_MAX; i++) puts(target_state_to_string(i)); if (!arg_no_legend) puts("\nAvailable timer unit substates:"); for (i = 0; i < _TIMER_STATE_MAX; i++) puts(timer_state_to_string(i)); } static int systemctl_parse_argv(int argc, char *argv[]) { enum { ARG_FAIL = 0x100, ARG_REVERSE, ARG_AFTER, ARG_BEFORE, ARG_SHOW_TYPES, ARG_IRREVERSIBLE, ARG_IGNORE_DEPENDENCIES, ARG_VERSION, ARG_USER, ARG_SYSTEM, ARG_GLOBAL, ARG_NO_BLOCK, ARG_NO_LEGEND, ARG_NO_PAGER, ARG_NO_WALL, ARG_ROOT, ARG_NO_RELOAD, ARG_KILL_WHO, ARG_NO_ASK_PASSWORD, ARG_FAILED, ARG_RUNTIME, ARG_FORCE, ARG_PLAIN, ARG_STATE, ARG_JOB_MODE, ARG_PRESET_MODE, ARG_FIRMWARE_SETUP, ARG_NOW, ARG_MESSAGE, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "type", required_argument, NULL, 't' }, { "property", required_argument, NULL, 'p' }, { "all", no_argument, NULL, 'a' }, { "reverse", no_argument, NULL, ARG_REVERSE }, { "after", no_argument, NULL, ARG_AFTER }, { "before", no_argument, NULL, ARG_BEFORE }, { "show-types", no_argument, NULL, ARG_SHOW_TYPES }, { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */ { "full", no_argument, NULL, 'l' }, { "job-mode", required_argument, NULL, ARG_JOB_MODE }, { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */ { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */ { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */ { "ignore-inhibitors", no_argument, NULL, 'i' }, { "user", no_argument, NULL, ARG_USER }, { "system", no_argument, NULL, ARG_SYSTEM }, { "global", no_argument, NULL, ARG_GLOBAL }, { "no-block", no_argument, NULL, ARG_NO_BLOCK }, { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "no-wall", no_argument, NULL, ARG_NO_WALL }, { "quiet", no_argument, NULL, 'q' }, { "root", required_argument, NULL, ARG_ROOT }, { "force", no_argument, NULL, ARG_FORCE }, { "no-reload", no_argument, NULL, ARG_NO_RELOAD }, { "kill-who", required_argument, NULL, ARG_KILL_WHO }, { "signal", required_argument, NULL, 's' }, { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, { "host", required_argument, NULL, 'H' }, { "machine", required_argument, NULL, 'M' }, { "runtime", no_argument, NULL, ARG_RUNTIME }, { "lines", required_argument, NULL, 'n' }, { "output", required_argument, NULL, 'o' }, { "plain", no_argument, NULL, ARG_PLAIN }, { "state", required_argument, NULL, ARG_STATE }, { "recursive", no_argument, NULL, 'r' }, { "preset-mode", required_argument, NULL, ARG_PRESET_MODE }, { "firmware-setup", no_argument, NULL, ARG_FIRMWARE_SETUP }, { "now", no_argument, NULL, ARG_NOW }, { "message", required_argument, NULL, ARG_MESSAGE }, {} }; const char *p; int c, r; assert(argc >= 0); assert(argv); /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */ arg_ask_password = true; while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0) switch (c) { case 'h': systemctl_help(); return 0; case ARG_VERSION: return version(); case 't': { if (isempty(optarg)) { log_error("--type requires arguments."); return -EINVAL; } p = optarg; for(;;) { _cleanup_free_ char *type = NULL; r = extract_first_word(&p, &type, ",", 0); if (r < 0) return log_error_errno(r, "Failed to parse type: %s", optarg); if (r == 0) break; if (streq(type, "help")) { help_types(); return 0; } if (unit_type_from_string(type) >= 0) { if (strv_push(&arg_types, type) < 0) return log_oom(); type = NULL; continue; } /* It's much nicer to use --state= for * load states, but let's support this * in --types= too for compatibility * with old versions */ if (unit_load_state_from_string(type) >= 0) { if (strv_push(&arg_states, type) < 0) return log_oom(); type = NULL; continue; } log_error("Unknown unit type or load state '%s'.", type); log_info("Use -t help to see a list of allowed values."); return -EINVAL; } break; } case 'p': { /* Make sure that if the empty property list was specified, we won't show any properties. */ if (isempty(optarg) && !arg_properties) { arg_properties = new0(char*, 1); if (!arg_properties) return log_oom(); } else { p = optarg; for(;;) { _cleanup_free_ char *prop = NULL; r = extract_first_word(&p, &prop, ",", 0); if (r < 0) return log_error_errno(r, "Failed to parse property: %s", optarg); if (r == 0) break; if (strv_push(&arg_properties, prop) < 0) return log_oom(); prop = NULL; } } /* If the user asked for a particular * property, show it to him, even if it is * empty. */ arg_all = true; break; } case 'a': arg_all = true; break; case ARG_REVERSE: arg_dependency = DEPENDENCY_REVERSE; break; case ARG_AFTER: arg_dependency = DEPENDENCY_AFTER; break; case ARG_BEFORE: arg_dependency = DEPENDENCY_BEFORE; break; case ARG_SHOW_TYPES: arg_show_types = true; break; case ARG_JOB_MODE: arg_job_mode = optarg; break; case ARG_FAIL: arg_job_mode = "fail"; break; case ARG_IRREVERSIBLE: arg_job_mode = "replace-irreversibly"; break; case ARG_IGNORE_DEPENDENCIES: arg_job_mode = "ignore-dependencies"; break; case ARG_USER: arg_scope = UNIT_FILE_USER; break; case ARG_SYSTEM: arg_scope = UNIT_FILE_SYSTEM; break; case ARG_GLOBAL: arg_scope = UNIT_FILE_GLOBAL; break; case ARG_NO_BLOCK: arg_no_block = true; break; case ARG_NO_LEGEND: arg_no_legend = true; break; case ARG_NO_PAGER: arg_no_pager = true; break; case ARG_NO_WALL: arg_no_wall = true; break; case ARG_ROOT: r = parse_path_argument_and_warn(optarg, true, &arg_root); if (r < 0) return r; break; case 'l': arg_full = true; break; case ARG_FAILED: if (strv_extend(&arg_states, "failed") < 0) return log_oom(); break; case 'q': arg_quiet = true; break; case ARG_FORCE: arg_force ++; break; case 'f': arg_force ++; break; case ARG_NO_RELOAD: arg_no_reload = true; break; case ARG_KILL_WHO: arg_kill_who = optarg; break; case 's': arg_signal = signal_from_string_try_harder(optarg); if (arg_signal < 0) { log_error("Failed to parse signal string %s.", optarg); return -EINVAL; } break; case ARG_NO_ASK_PASSWORD: arg_ask_password = false; break; case 'H': arg_transport = BUS_TRANSPORT_REMOTE; arg_host = optarg; break; case 'M': arg_transport = BUS_TRANSPORT_MACHINE; arg_host = optarg; break; case ARG_RUNTIME: arg_runtime = true; break; case 'n': if (safe_atou(optarg, &arg_lines) < 0) { log_error("Failed to parse lines '%s'", optarg); return -EINVAL; } break; case 'o': arg_output = output_mode_from_string(optarg); if (arg_output < 0) { log_error("Unknown output '%s'.", optarg); return -EINVAL; } break; case 'i': arg_ignore_inhibitors = true; break; case ARG_PLAIN: arg_plain = true; break; case ARG_FIRMWARE_SETUP: arg_firmware_setup = true; break; case ARG_STATE: { if (isempty(optarg)) { log_error("--signal requires arguments."); return -EINVAL; } p = optarg; for(;;) { _cleanup_free_ char *s = NULL; r = extract_first_word(&p, &s, ",", 0); if (r < 0) return log_error_errno(r, "Failed to parse signal: %s", optarg); if (r == 0) break; if (streq(s, "help")) { help_states(); return 0; } if (strv_push(&arg_states, s) < 0) return log_oom(); s = NULL; } break; } case 'r': if (geteuid() != 0) { log_error("--recursive requires root privileges."); return -EPERM; } arg_recursive = true; break; case ARG_PRESET_MODE: arg_preset_mode = unit_file_preset_mode_from_string(optarg); if (arg_preset_mode < 0) { log_error("Failed to parse preset mode: %s.", optarg); return -EINVAL; } break; case ARG_NOW: arg_now = true; break; case ARG_MESSAGE: if (strv_extend(&arg_wall, optarg) < 0) return log_oom(); break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) { log_error("Cannot access user instance remotely."); return -EINVAL; } return 1; } static int halt_parse_argv(int argc, char *argv[]) { enum { ARG_HELP = 0x100, ARG_HALT, ARG_REBOOT, ARG_NO_WALL }; static const struct option options[] = { { "help", no_argument, NULL, ARG_HELP }, { "halt", no_argument, NULL, ARG_HALT }, { "poweroff", no_argument, NULL, 'p' }, { "reboot", no_argument, NULL, ARG_REBOOT }, { "force", no_argument, NULL, 'f' }, { "wtmp-only", no_argument, NULL, 'w' }, { "no-wtmp", no_argument, NULL, 'd' }, { "no-wall", no_argument, NULL, ARG_NO_WALL }, {} }; int c, r, runlevel; assert(argc >= 0); assert(argv); if (utmp_get_runlevel(&runlevel, NULL) >= 0) if (runlevel == '0' || runlevel == '6') arg_force = 2; while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) switch (c) { case ARG_HELP: halt_help(); return 0; case ARG_HALT: arg_action = ACTION_HALT; break; case 'p': if (arg_action != ACTION_REBOOT) arg_action = ACTION_POWEROFF; break; case ARG_REBOOT: arg_action = ACTION_REBOOT; break; case 'f': arg_force = 2; break; case 'w': arg_dry = true; break; case 'd': arg_no_wtmp = true; break; case ARG_NO_WALL: arg_no_wall = true; break; case 'i': case 'h': case 'n': /* Compatibility nops */ break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) { r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL); if (r < 0) return r; } else if (optind < argc) { log_error("Too many arguments."); return -EINVAL; } return 1; } static int parse_shutdown_time_spec(const char *t, usec_t *_u) { assert(t); assert(_u); if (streq(t, "now")) *_u = 0; else if (!strchr(t, ':')) { uint64_t u; if (safe_atou64(t, &u) < 0) return -EINVAL; *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u; } else { char *e = NULL; long hour, minute; struct tm tm = {}; time_t s; usec_t n; errno = 0; hour = strtol(t, &e, 10); if (errno > 0 || *e != ':' || hour < 0 || hour > 23) return -EINVAL; minute = strtol(e+1, &e, 10); if (errno > 0 || *e != 0 || minute < 0 || minute > 59) return -EINVAL; n = now(CLOCK_REALTIME); s = (time_t) (n / USEC_PER_SEC); assert_se(localtime_r(&s, &tm)); tm.tm_hour = (int) hour; tm.tm_min = (int) minute; tm.tm_sec = 0; assert_se(s = mktime(&tm)); *_u = (usec_t) s * USEC_PER_SEC; while (*_u <= n) *_u += USEC_PER_DAY; } return 0; } static int shutdown_parse_argv(int argc, char *argv[]) { enum { ARG_HELP = 0x100, ARG_NO_WALL }; static const struct option options[] = { { "help", no_argument, NULL, ARG_HELP }, { "halt", no_argument, NULL, 'H' }, { "poweroff", no_argument, NULL, 'P' }, { "reboot", no_argument, NULL, 'r' }, { "kexec", no_argument, NULL, 'K' }, /* not documented extension */ { "no-wall", no_argument, NULL, ARG_NO_WALL }, {} }; char **wall = NULL; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "HPrhkKtafFc", options, NULL)) >= 0) switch (c) { case ARG_HELP: shutdown_help(); return 0; case 'H': arg_action = ACTION_HALT; break; case 'P': arg_action = ACTION_POWEROFF; break; case 'r': if (kexec_loaded()) arg_action = ACTION_KEXEC; else arg_action = ACTION_REBOOT; break; case 'K': arg_action = ACTION_KEXEC; break; case 'h': if (arg_action != ACTION_HALT) arg_action = ACTION_POWEROFF; break; case 'k': arg_dry = true; break; case ARG_NO_WALL: arg_no_wall = true; break; case 't': case 'a': case 'f': case 'F': /* Compatibility nops */ break; case 'c': arg_action = ACTION_CANCEL_SHUTDOWN; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) { r = parse_shutdown_time_spec(argv[optind], &arg_when); if (r < 0) { log_error("Failed to parse time specification: %s", argv[optind]); return r; } } else arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE; if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN) /* No time argument for shutdown cancel */ wall = argv + optind; else if (argc > optind + 1) /* We skip the time argument */ wall = argv + optind + 1; if (wall) { arg_wall = strv_copy(wall); if (!arg_wall) return log_oom(); } optind = argc; return 1; } static int telinit_parse_argv(int argc, char *argv[]) { enum { ARG_HELP = 0x100, ARG_NO_WALL }; static const struct option options[] = { { "help", no_argument, NULL, ARG_HELP }, { "no-wall", no_argument, NULL, ARG_NO_WALL }, {} }; static const struct { char from; enum action to; } table[] = { { '0', ACTION_POWEROFF }, { '6', ACTION_REBOOT }, { '1', ACTION_RESCUE }, { '2', ACTION_RUNLEVEL2 }, { '3', ACTION_RUNLEVEL3 }, { '4', ACTION_RUNLEVEL4 }, { '5', ACTION_RUNLEVEL5 }, { 's', ACTION_RESCUE }, { 'S', ACTION_RESCUE }, { 'q', ACTION_RELOAD }, { 'Q', ACTION_RELOAD }, { 'u', ACTION_REEXEC }, { 'U', ACTION_REEXEC } }; unsigned i; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) switch (c) { case ARG_HELP: telinit_help(); return 0; case ARG_NO_WALL: arg_no_wall = true; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (optind >= argc) { log_error("%s: required argument missing.", program_invocation_short_name); return -EINVAL; } if (optind + 1 < argc) { log_error("Too many arguments."); return -EINVAL; } if (strlen(argv[optind]) != 1) { log_error("Expected single character argument."); return -EINVAL; } for (i = 0; i < ELEMENTSOF(table); i++) if (table[i].from == argv[optind][0]) break; if (i >= ELEMENTSOF(table)) { log_error("Unknown command '%s'.", argv[optind]); return -EINVAL; } arg_action = table[i].to; optind ++; return 1; } static int runlevel_parse_argv(int argc, char *argv[]) { enum { ARG_HELP = 0x100, }; static const struct option options[] = { { "help", no_argument, NULL, ARG_HELP }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) switch (c) { case ARG_HELP: runlevel_help(); return 0; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (optind < argc) { log_error("Too many arguments."); return -EINVAL; } return 1; } static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); if (program_invocation_short_name) { if (strstr(program_invocation_short_name, "halt")) { arg_action = ACTION_HALT; return halt_parse_argv(argc, argv); } else if (strstr(program_invocation_short_name, "poweroff")) { arg_action = ACTION_POWEROFF; return halt_parse_argv(argc, argv); } else if (strstr(program_invocation_short_name, "reboot")) { if (kexec_loaded()) arg_action = ACTION_KEXEC; else arg_action = ACTION_REBOOT; return halt_parse_argv(argc, argv); } else if (strstr(program_invocation_short_name, "shutdown")) { arg_action = ACTION_POWEROFF; return shutdown_parse_argv(argc, argv); } else if (strstr(program_invocation_short_name, "init")) { if (sd_booted() > 0) { arg_action = _ACTION_INVALID; return telinit_parse_argv(argc, argv); } else { /* Hmm, so some other init system is * running, we need to forward this * request to it. For now we simply * guess that it is Upstart. */ execv(TELINIT, argv); log_error("Couldn't find an alternative telinit implementation to spawn."); return -EIO; } } else if (strstr(program_invocation_short_name, "runlevel")) { arg_action = ACTION_RUNLEVEL; return runlevel_parse_argv(argc, argv); } } arg_action = ACTION_SYSTEMCTL; return systemctl_parse_argv(argc, argv); } _pure_ static int action_to_runlevel(void) { static const char table[_ACTION_MAX] = { [ACTION_HALT] = '0', [ACTION_POWEROFF] = '0', [ACTION_REBOOT] = '6', [ACTION_RUNLEVEL2] = '2', [ACTION_RUNLEVEL3] = '3', [ACTION_RUNLEVEL4] = '4', [ACTION_RUNLEVEL5] = '5', [ACTION_RESCUE] = '1' }; assert(arg_action < _ACTION_MAX); return table[arg_action]; } static int talk_initctl(void) { #ifdef HAVE_SYSV_COMPAT struct init_request request = { .magic = INIT_MAGIC, .sleeptime = 0, .cmd = INIT_CMD_RUNLVL }; _cleanup_close_ int fd = -1; char rl; int r; rl = action_to_runlevel(); if (!rl) return 0; request.runlevel = rl; fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY); if (fd < 0) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open "INIT_FIFO": %m"); } r = loop_write(fd, &request, sizeof(request), false); if (r < 0) return log_error_errno(r, "Failed to write to "INIT_FIFO": %m"); return 1; #else return 0; #endif } static int systemctl_main(int argc, char *argv[]) { static const Verb verbs[] = { { "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_NOCHROOT, list_units }, { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files }, { "list-sockets", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_sockets }, { "list-timers", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_timers }, { "list-jobs", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_jobs }, { "list-machines", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_machines }, { "clear-jobs", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload }, { "cancel", VERB_ANY, VERB_ANY, VERB_NOCHROOT, cancel_job }, { "start", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, { "stop", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, { "condstop", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */ { "reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, { "restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, { "try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, { "reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, { "reload-or-try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatbility with old systemctl <= 228 */ { "try-reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, { "force-reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with SysV */ { "condreload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */ { "condrestart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with RH */ { "isolate", 2, 2, VERB_NOCHROOT, start_unit }, { "kill", 2, VERB_ANY, VERB_NOCHROOT, kill_unit }, { "is-active", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active }, { "check", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active }, { "is-failed", 2, VERB_ANY, VERB_NOCHROOT, check_unit_failed }, { "show", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show }, { "cat", 2, VERB_ANY, VERB_NOCHROOT, cat }, { "status", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show }, { "help", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show }, { "daemon-reload", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload }, { "daemon-reexec", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload }, { "show-environment", VERB_ANY, 1, VERB_NOCHROOT, show_environment }, { "set-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment }, { "unset-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment }, { "import-environment", VERB_ANY, VERB_ANY, VERB_NOCHROOT, import_environment}, { "halt", VERB_ANY, 1, VERB_NOCHROOT, start_special }, { "poweroff", VERB_ANY, 1, VERB_NOCHROOT, start_special }, { "reboot", VERB_ANY, 2, VERB_NOCHROOT, start_special }, { "kexec", VERB_ANY, 1, VERB_NOCHROOT, start_special }, { "suspend", VERB_ANY, 1, VERB_NOCHROOT, start_special }, { "hibernate", VERB_ANY, 1, VERB_NOCHROOT, start_special }, { "hybrid-sleep", VERB_ANY, 1, VERB_NOCHROOT, start_special }, { "default", VERB_ANY, 1, VERB_NOCHROOT, start_special }, { "rescue", VERB_ANY, 1, VERB_NOCHROOT, start_special }, { "emergency", VERB_ANY, 1, VERB_NOCHROOT, start_special }, { "exit", VERB_ANY, 2, VERB_NOCHROOT, start_special }, { "reset-failed", VERB_ANY, VERB_ANY, VERB_NOCHROOT, reset_failed }, { "enable", 2, VERB_ANY, 0, enable_unit }, { "disable", 2, VERB_ANY, 0, enable_unit }, { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled }, { "reenable", 2, VERB_ANY, 0, enable_unit }, { "preset", 2, VERB_ANY, 0, enable_unit }, { "preset-all", VERB_ANY, 1, 0, preset_all }, { "mask", 2, VERB_ANY, 0, enable_unit }, { "unmask", 2, VERB_ANY, 0, enable_unit }, { "link", 2, VERB_ANY, 0, enable_unit }, { "switch-root", 2, VERB_ANY, VERB_NOCHROOT, switch_root }, { "list-dependencies", VERB_ANY, 2, VERB_NOCHROOT, list_dependencies }, { "set-default", 2, 2, 0, set_default }, { "get-default", VERB_ANY, 1, 0, get_default, }, { "set-property", 3, VERB_ANY, VERB_NOCHROOT, set_property }, { "is-system-running", VERB_ANY, 1, 0, is_system_running }, { "add-wants", 3, VERB_ANY, 0, add_dependency }, { "add-requires", 3, VERB_ANY, 0, add_dependency }, { "edit", 2, VERB_ANY, VERB_NOCHROOT, edit }, {} }; return dispatch_verb(argc, argv, verbs, NULL); } static int reload_with_fallback(void) { /* First, try systemd via D-Bus. */ if (daemon_reload(0, NULL, NULL) >= 0) return 0; /* Nothing else worked, so let's try signals */ assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC); if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) return log_error_errno(errno, "kill() failed: %m"); return 0; } static int start_with_fallback(void) { /* First, try systemd via D-Bus. */ if (start_unit(0, NULL, NULL) >= 0) return 0; /* Nothing else worked, so let's try * /dev/initctl */ if (talk_initctl() > 0) return 0; log_error("Failed to talk to init daemon."); return -EIO; } static int halt_now(enum action a) { /* The kernel will automaticall flush ATA disks and suchlike * on reboot(), but the file systems need to be synce'd * explicitly in advance. */ (void) sync(); /* Make sure C-A-D is handled by the kernel from this point * on... */ (void) reboot(RB_ENABLE_CAD); switch (a) { case ACTION_HALT: log_info("Halting."); (void) reboot(RB_HALT_SYSTEM); return -errno; case ACTION_POWEROFF: log_info("Powering off."); (void) reboot(RB_POWER_OFF); return -errno; case ACTION_KEXEC: case ACTION_REBOOT: { _cleanup_free_ char *param = NULL; if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) { log_info("Rebooting with argument '%s'.", param); (void) syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param); } log_info("Rebooting."); (void) reboot(RB_AUTOBOOT); return -errno; } default: assert_not_reached("Unknown action."); } } static int logind_schedule_shutdown(void) { #ifdef HAVE_LOGIND _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char date[FORMAT_TIMESTAMP_MAX]; const char *action; sd_bus *bus; int r; (void) logind_set_wall_message(); r = acquire_bus(BUS_FULL, &bus); if (r < 0) return r; switch (arg_action) { case ACTION_HALT: action = "halt"; break; case ACTION_POWEROFF: action = "poweroff"; break; case ACTION_KEXEC: action = "kexec"; break; case ACTION_EXIT: action = "exit"; break; case ACTION_REBOOT: default: action = "reboot"; break; } if (arg_dry) action = strjoina("dry-", action); r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "ScheduleShutdown", &error, NULL, "st", action, arg_when); if (r < 0) return log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error, r)); log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date, sizeof(date), arg_when)); return 0; #else log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown."); return -ENOSYS; #endif } static int halt_main(void) { int r; r = logind_check_inhibitors(arg_action); if (r < 0) return r; if (arg_when > 0) return logind_schedule_shutdown(); if (geteuid() != 0) { if (arg_dry || arg_force > 0) { log_error("Must be root."); return -EPERM; } /* Try logind if we are a normal user and no special * mode applies. Maybe PolicyKit allows us to shutdown * the machine. */ if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT)) { r = logind_reboot(arg_action); if (r >= 0) return r; if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS)) /* requested operation is not * supported on the local system or * already in progress */ return r; /* on all other errors, try low-level operation */ } } if (!arg_dry && !arg_force) return start_with_fallback(); assert(geteuid() == 0); if (!arg_no_wtmp) { if (sd_booted() > 0) log_debug("Not writing utmp record, assuming that systemd-update-utmp is used."); else { r = utmp_put_shutdown(); if (r < 0) log_warning_errno(r, "Failed to write utmp record: %m"); } } if (arg_dry) return 0; r = halt_now(arg_action); return log_error_errno(r, "Failed to reboot: %m"); } static int runlevel_main(void) { int r, runlevel, previous; r = utmp_get_runlevel(&runlevel, &previous); if (r < 0) { puts("unknown"); return r; } printf("%c %c\n", previous <= 0 ? 'N' : previous, runlevel <= 0 ? 'N' : runlevel); return 0; } static int logind_cancel_shutdown(void) { #ifdef HAVE_LOGIND _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus *bus; int r; r = acquire_bus(BUS_FULL, &bus); if (r < 0) return r; (void) logind_set_wall_message(); r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "CancelScheduledShutdown", &error, NULL, NULL); if (r < 0) return log_warning_errno(r, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error, r)); return 0; #else log_error("Not compiled with logind support, cannot cancel scheduled shutdowns."); return -ENOSYS; #endif } int main(int argc, char*argv[]) { int r; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); /* Explicitly not on_tty() to avoid setting cached value. * This becomes relevant for piping output which might be * ellipsized. */ original_stdout_is_tty = isatty(STDOUT_FILENO); r = parse_argv(argc, argv); if (r <= 0) goto finish; if (arg_action != ACTION_SYSTEMCTL && running_in_chroot() > 0) { log_info("Running in chroot, ignoring request."); r = 0; goto finish; } /* systemctl_main() will print an error message for the bus * connection, but only if it needs to */ switch (arg_action) { case ACTION_SYSTEMCTL: r = systemctl_main(argc, argv); break; case ACTION_HALT: case ACTION_POWEROFF: case ACTION_REBOOT: case ACTION_KEXEC: r = halt_main(); break; case ACTION_RUNLEVEL2: case ACTION_RUNLEVEL3: case ACTION_RUNLEVEL4: case ACTION_RUNLEVEL5: case ACTION_RESCUE: case ACTION_EMERGENCY: case ACTION_DEFAULT: r = start_with_fallback(); break; case ACTION_RELOAD: case ACTION_REEXEC: r = reload_with_fallback(); break; case ACTION_CANCEL_SHUTDOWN: r = logind_cancel_shutdown(); break; case ACTION_RUNLEVEL: r = runlevel_main(); break; case _ACTION_INVALID: default: assert_not_reached("Unknown action"); } finish: pager_close(); ask_password_agent_close(); polkit_agent_close(); strv_free(arg_types); strv_free(arg_states); strv_free(arg_properties); strv_free(arg_wall); free(arg_root); release_busses(); /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */ return r < 0 ? EXIT_FAILURE : r; } systemd-229/src/systemctl/systemd-sysv-install.SKELETON000077500000000000000000000024611265713322000232110ustar00rootroot00000000000000#!/bin/sh # This script is called by "systemctl enable/disable" when the given unit is a # SysV init.d script. It needs to call the distribution's mechanism for # enabling/disabling those, such as chkconfig, update-rc.d, or similar. This # can optionally take a --root argument for enabling a SysV init script # in a chroot or similar. set -e usage() { echo "Usage: $0 [--root=path] enable|disable|is-enabled " >&2 exit 1 } # parse options eval set -- "$(getopt -o r: --long root: -- "$@")" while true; do case "$1" in -r|--root) ROOT="$2" shift 2 ;; --) shift ; break ;; *) usage ;; esac done NAME="$2" [ -n "$NAME" ] || usage case "$1" in enable) # call the command to enable SysV init script $NAME here # (consider optional $ROOT) echo "IMPLEMENT ME: enabling SysV init.d script $NAME" ;; disable) # call the command to disable SysV init script $NAME here # (consider optional $ROOT) echo "IMPLEMENT ME: disabling SysV init.d script $NAME" ;; is-enabled) # exit with 0 if $NAME is enabled, non-zero if it is disabled # (consider optional $ROOT) echo "IMPLEMENT ME: checking SysV init.d script $NAME" ;; *) usage ;; esac systemd-229/src/systemd/000077500000000000000000000000001265713322000153405ustar00rootroot00000000000000systemd-229/src/systemd/Makefile000077700000000000000000000000001265713322000206462../Makefileustar00rootroot00000000000000systemd-229/src/systemd/_sd-common.h000066400000000000000000000051301265713322000175430ustar00rootroot00000000000000#ifndef foosdcommonhfoo #define foosdcommonhfoo /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* This is a private header; never even think of including this directly! */ #if __INCLUDE_LEVEL__ <= 1 #error "Do not include _sd-common.h directly; it is a private header." #endif #ifndef _sd_printf_ # if __GNUC__ >= 4 # define _sd_printf_(a,b) __attribute__ ((format (printf, a, b))) # else # define _sd_printf_(a,b) # endif #endif #ifndef _sd_sentinel_ # define _sd_sentinel_ __attribute__((sentinel)) #endif #ifndef _sd_packed_ # define _sd_packed_ __attribute__((packed)) #endif #ifndef _sd_pure_ # define _sd_pure_ __attribute__((pure)) #endif #ifndef _SD_STRINGIFY # define _SD_XSTRINGIFY(x) #x # define _SD_STRINGIFY(x) _SD_XSTRINGIFY(x) #endif #ifndef _SD_BEGIN_DECLARATIONS # ifdef __cplusplus # define _SD_BEGIN_DECLARATIONS \ extern "C" { \ struct _sd_useless_struct_to_allow_trailing_semicolon_ # else # define _SD_BEGIN_DECLARATIONS \ struct _sd_useless_struct_to_allow_trailing_semicolon_ # endif #endif #ifndef _SD_END_DECLARATIONS # ifdef __cplusplus # define _SD_END_DECLARATIONS \ } \ struct _sd_useless_cpp_struct_to_allow_trailing_semicolon_ # else # define _SD_END_DECLARATIONS \ struct _sd_useless_struct_to_allow_trailing_semicolon_ # endif #endif #define _SD_DEFINE_POINTER_CLEANUP_FUNC(type, func) \ static inline void func##p(type **p) { \ if (*p) \ func(*p); \ } \ struct _sd_useless_struct_to_allow_trailing_semicolon_ #endif systemd-229/src/systemd/sd-bus-protocol.h000066400000000000000000000117571265713322000205600ustar00rootroot00000000000000#ifndef foosdbusprotocolhfoo #define foosdbusprotocolhfoo /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; /* Types of message */ enum { _SD_BUS_MESSAGE_TYPE_INVALID = 0, SD_BUS_MESSAGE_METHOD_CALL, SD_BUS_MESSAGE_METHOD_RETURN, SD_BUS_MESSAGE_METHOD_ERROR, SD_BUS_MESSAGE_SIGNAL, _SD_BUS_MESSAGE_TYPE_MAX }; /* Primitive types */ enum { _SD_BUS_TYPE_INVALID = 0, SD_BUS_TYPE_BYTE = 'y', SD_BUS_TYPE_BOOLEAN = 'b', SD_BUS_TYPE_INT16 = 'n', SD_BUS_TYPE_UINT16 = 'q', SD_BUS_TYPE_INT32 = 'i', SD_BUS_TYPE_UINT32 = 'u', SD_BUS_TYPE_INT64 = 'x', SD_BUS_TYPE_UINT64 = 't', SD_BUS_TYPE_DOUBLE = 'd', SD_BUS_TYPE_STRING = 's', SD_BUS_TYPE_OBJECT_PATH = 'o', SD_BUS_TYPE_SIGNATURE = 'g', SD_BUS_TYPE_UNIX_FD = 'h', SD_BUS_TYPE_ARRAY = 'a', SD_BUS_TYPE_VARIANT = 'v', SD_BUS_TYPE_STRUCT = 'r', /* not actually used in signatures */ SD_BUS_TYPE_STRUCT_BEGIN = '(', SD_BUS_TYPE_STRUCT_END = ')', SD_BUS_TYPE_DICT_ENTRY = 'e', /* not actually used in signatures */ SD_BUS_TYPE_DICT_ENTRY_BEGIN = '{', SD_BUS_TYPE_DICT_ENTRY_END = '}', }; /* Well-known errors. Note that this is only a sanitized subset of the * errors that the reference implementation generates. */ #define SD_BUS_ERROR_FAILED "org.freedesktop.DBus.Error.Failed" #define SD_BUS_ERROR_NO_MEMORY "org.freedesktop.DBus.Error.NoMemory" #define SD_BUS_ERROR_SERVICE_UNKNOWN "org.freedesktop.DBus.Error.ServiceUnknown" #define SD_BUS_ERROR_NAME_HAS_NO_OWNER "org.freedesktop.DBus.Error.NameHasNoOwner" #define SD_BUS_ERROR_NO_REPLY "org.freedesktop.DBus.Error.NoReply" #define SD_BUS_ERROR_IO_ERROR "org.freedesktop.DBus.Error.IOError" #define SD_BUS_ERROR_BAD_ADDRESS "org.freedesktop.DBus.Error.BadAddress" #define SD_BUS_ERROR_NOT_SUPPORTED "org.freedesktop.DBus.Error.NotSupported" #define SD_BUS_ERROR_LIMITS_EXCEEDED "org.freedesktop.DBus.Error.LimitsExceeded" #define SD_BUS_ERROR_ACCESS_DENIED "org.freedesktop.DBus.Error.AccessDenied" #define SD_BUS_ERROR_AUTH_FAILED "org.freedesktop.DBus.Error.AuthFailed" #define SD_BUS_ERROR_NO_SERVER "org.freedesktop.DBus.Error.NoServer" #define SD_BUS_ERROR_TIMEOUT "org.freedesktop.DBus.Error.Timeout" #define SD_BUS_ERROR_NO_NETWORK "org.freedesktop.DBus.Error.NoNetwork" #define SD_BUS_ERROR_ADDRESS_IN_USE "org.freedesktop.DBus.Error.AddressInUse" #define SD_BUS_ERROR_DISCONNECTED "org.freedesktop.DBus.Error.Disconnected" #define SD_BUS_ERROR_INVALID_ARGS "org.freedesktop.DBus.Error.InvalidArgs" #define SD_BUS_ERROR_FILE_NOT_FOUND "org.freedesktop.DBus.Error.FileNotFound" #define SD_BUS_ERROR_FILE_EXISTS "org.freedesktop.DBus.Error.FileExists" #define SD_BUS_ERROR_UNKNOWN_METHOD "org.freedesktop.DBus.Error.UnknownMethod" #define SD_BUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject" #define SD_BUS_ERROR_UNKNOWN_INTERFACE "org.freedesktop.DBus.Error.UnknownInterface" #define SD_BUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty" #define SD_BUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly" #define SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN "org.freedesktop.DBus.Error.UnixProcessIdUnknown" #define SD_BUS_ERROR_INVALID_SIGNATURE "org.freedesktop.DBus.Error.InvalidSignature" #define SD_BUS_ERROR_INCONSISTENT_MESSAGE "org.freedesktop.DBus.Error.InconsistentMessage" #define SD_BUS_ERROR_MATCH_RULE_NOT_FOUND "org.freedesktop.DBus.Error.MatchRuleNotFound" #define SD_BUS_ERROR_MATCH_RULE_INVALID "org.freedesktop.DBus.Error.MatchRuleInvalid" #define SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED \ "org.freedesktop.DBus.Error.InteractiveAuthorizationRequired" _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-bus-vtable.h000066400000000000000000000137501265713322000201670ustar00rootroot00000000000000#ifndef foosdbusvtablehfoo #define foosdbusvtablehfoo /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; typedef struct sd_bus_vtable sd_bus_vtable; #include "sd-bus.h" enum { _SD_BUS_VTABLE_START = '<', _SD_BUS_VTABLE_END = '>', _SD_BUS_VTABLE_METHOD = 'M', _SD_BUS_VTABLE_SIGNAL = 'S', _SD_BUS_VTABLE_PROPERTY = 'P', _SD_BUS_VTABLE_WRITABLE_PROPERTY = 'W', }; enum { SD_BUS_VTABLE_DEPRECATED = 1ULL << 0, SD_BUS_VTABLE_HIDDEN = 1ULL << 1, SD_BUS_VTABLE_UNPRIVILEGED = 1ULL << 2, SD_BUS_VTABLE_METHOD_NO_REPLY = 1ULL << 3, SD_BUS_VTABLE_PROPERTY_CONST = 1ULL << 4, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE = 1ULL << 5, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION = 1ULL << 6, SD_BUS_VTABLE_PROPERTY_EXPLICIT = 1ULL << 7, _SD_BUS_VTABLE_CAPABILITY_MASK = 0xFFFFULL << 40 }; #define SD_BUS_VTABLE_CAPABILITY(x) ((uint64_t) (((x)+1) & 0xFFFF) << 40) struct sd_bus_vtable { /* Please do not initialize this structure directly, use the * macros below instead */ uint8_t type:8; uint64_t flags:56; union { struct { size_t element_size; } start; struct { const char *member; const char *signature; const char *result; sd_bus_message_handler_t handler; size_t offset; } method; struct { const char *member; const char *signature; } signal; struct { const char *member; const char *signature; sd_bus_property_get_t get; sd_bus_property_set_t set; size_t offset; } property; } x; }; #define SD_BUS_VTABLE_START(_flags) \ { \ .type = _SD_BUS_VTABLE_START, \ .flags = _flags, \ .x.start.element_size = sizeof(sd_bus_vtable), \ } #define SD_BUS_METHOD_WITH_OFFSET(_member, _signature, _result, _handler, _offset, _flags) \ { \ .type = _SD_BUS_VTABLE_METHOD, \ .flags = _flags, \ .x.method.member = _member, \ .x.method.signature = _signature, \ .x.method.result = _result, \ .x.method.handler = _handler, \ .x.method.offset = _offset, \ } #define SD_BUS_METHOD(_member, _signature, _result, _handler, _flags) \ SD_BUS_METHOD_WITH_OFFSET(_member, _signature, _result, _handler, 0, _flags) #define SD_BUS_SIGNAL(_member, _signature, _flags) \ { \ .type = _SD_BUS_VTABLE_SIGNAL, \ .flags = _flags, \ .x.signal.member = _member, \ .x.signal.signature = _signature, \ } #define SD_BUS_PROPERTY(_member, _signature, _get, _offset, _flags) \ { \ .type = _SD_BUS_VTABLE_PROPERTY, \ .flags = _flags, \ .x.property.member = _member, \ .x.property.signature = _signature, \ .x.property.get = _get, \ .x.property.offset = _offset, \ } #define SD_BUS_WRITABLE_PROPERTY(_member, _signature, _get, _set, _offset, _flags) \ { \ .type = _SD_BUS_VTABLE_WRITABLE_PROPERTY, \ .flags = _flags, \ .x.property.member = _member, \ .x.property.signature = _signature, \ .x.property.get = _get, \ .x.property.set = _set, \ .x.property.offset = _offset, \ } #define SD_BUS_VTABLE_END \ { \ .type = _SD_BUS_VTABLE_END, \ } _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-bus.h000066400000000000000000000574401265713322000167200ustar00rootroot00000000000000#ifndef foosdbushfoo #define foosdbushfoo /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-event.h" #include "sd-id128.h" #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; /* Types */ typedef struct sd_bus sd_bus; typedef struct sd_bus_message sd_bus_message; typedef struct sd_bus_slot sd_bus_slot; typedef struct sd_bus_creds sd_bus_creds; typedef struct sd_bus_track sd_bus_track; typedef struct { const char *name; const char *message; int _need_free; } sd_bus_error; typedef struct { const char* name; int code; } sd_bus_error_map; /* Flags */ enum { SD_BUS_CREDS_PID = 1ULL << 0, SD_BUS_CREDS_TID = 1ULL << 1, SD_BUS_CREDS_PPID = 1ULL << 2, SD_BUS_CREDS_UID = 1ULL << 3, SD_BUS_CREDS_EUID = 1ULL << 4, SD_BUS_CREDS_SUID = 1ULL << 5, SD_BUS_CREDS_FSUID = 1ULL << 6, SD_BUS_CREDS_GID = 1ULL << 7, SD_BUS_CREDS_EGID = 1ULL << 8, SD_BUS_CREDS_SGID = 1ULL << 9, SD_BUS_CREDS_FSGID = 1ULL << 10, SD_BUS_CREDS_SUPPLEMENTARY_GIDS = 1ULL << 11, SD_BUS_CREDS_COMM = 1ULL << 12, SD_BUS_CREDS_TID_COMM = 1ULL << 13, SD_BUS_CREDS_EXE = 1ULL << 14, SD_BUS_CREDS_CMDLINE = 1ULL << 15, SD_BUS_CREDS_CGROUP = 1ULL << 16, SD_BUS_CREDS_UNIT = 1ULL << 17, SD_BUS_CREDS_SLICE = 1ULL << 18, SD_BUS_CREDS_USER_UNIT = 1ULL << 19, SD_BUS_CREDS_USER_SLICE = 1ULL << 20, SD_BUS_CREDS_SESSION = 1ULL << 21, SD_BUS_CREDS_OWNER_UID = 1ULL << 22, SD_BUS_CREDS_EFFECTIVE_CAPS = 1ULL << 23, SD_BUS_CREDS_PERMITTED_CAPS = 1ULL << 24, SD_BUS_CREDS_INHERITABLE_CAPS = 1ULL << 25, SD_BUS_CREDS_BOUNDING_CAPS = 1ULL << 26, SD_BUS_CREDS_SELINUX_CONTEXT = 1ULL << 27, SD_BUS_CREDS_AUDIT_SESSION_ID = 1ULL << 28, SD_BUS_CREDS_AUDIT_LOGIN_UID = 1ULL << 29, SD_BUS_CREDS_TTY = 1ULL << 30, SD_BUS_CREDS_UNIQUE_NAME = 1ULL << 31, SD_BUS_CREDS_WELL_KNOWN_NAMES = 1ULL << 32, SD_BUS_CREDS_DESCRIPTION = 1ULL << 33, SD_BUS_CREDS_AUGMENT = 1ULL << 63, /* special flag, if on sd-bus will augment creds struct, in a potentially race-full way. */ _SD_BUS_CREDS_ALL = (1ULL << 34) -1, }; enum { SD_BUS_NAME_REPLACE_EXISTING = 1ULL << 0, SD_BUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1, SD_BUS_NAME_QUEUE = 1ULL << 2, }; /* Callbacks */ typedef int (*sd_bus_message_handler_t)(sd_bus_message *m, void *userdata, sd_bus_error *ret_error); typedef int (*sd_bus_property_get_t) (sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error); typedef int (*sd_bus_property_set_t) (sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *ret_error); typedef int (*sd_bus_object_find_t) (sd_bus *bus, const char *path, const char *interface, void *userdata, void **ret_found, sd_bus_error *ret_error); typedef int (*sd_bus_node_enumerator_t) (sd_bus *bus, const char *prefix, void *userdata, char ***ret_nodes, sd_bus_error *ret_error); typedef int (*sd_bus_track_handler_t) (sd_bus_track *track, void *userdata); #include "sd-bus-protocol.h" #include "sd-bus-vtable.h" /* Connections */ int sd_bus_default(sd_bus **ret); int sd_bus_default_user(sd_bus **ret); int sd_bus_default_system(sd_bus **ret); int sd_bus_open(sd_bus **ret); int sd_bus_open_user(sd_bus **ret); int sd_bus_open_system(sd_bus **ret); int sd_bus_open_system_remote(sd_bus **ret, const char *host); int sd_bus_open_system_machine(sd_bus **ret, const char *machine); int sd_bus_new(sd_bus **ret); int sd_bus_set_address(sd_bus *bus, const char *address); int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd); int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]); int sd_bus_get_address(sd_bus *bus, const char **address); int sd_bus_set_bus_client(sd_bus *bus, int b); int sd_bus_is_bus_client(sd_bus *bus); int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t bus_id); int sd_bus_is_server(sd_bus *bus); int sd_bus_set_anonymous(sd_bus *bus, int b); int sd_bus_is_anonymous(sd_bus *bus); int sd_bus_set_trusted(sd_bus *bus, int b); int sd_bus_is_trusted(sd_bus *bus); int sd_bus_set_monitor(sd_bus *bus, int b); int sd_bus_is_monitor(sd_bus *bus); int sd_bus_set_description(sd_bus *bus, const char *description); int sd_bus_get_description(sd_bus *bus, const char **description); int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t creds_mask); int sd_bus_negotiate_timestamp(sd_bus *bus, int b); int sd_bus_negotiate_fds(sd_bus *bus, int b); int sd_bus_can_send(sd_bus *bus, char type); int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *creds_mask); int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b); int sd_bus_get_allow_interactive_authorization(sd_bus *bus); int sd_bus_start(sd_bus *ret); int sd_bus_try_close(sd_bus *bus); void sd_bus_close(sd_bus *bus); sd_bus *sd_bus_ref(sd_bus *bus); sd_bus *sd_bus_unref(sd_bus *bus); sd_bus *sd_bus_flush_close_unref(sd_bus *bus); void sd_bus_default_flush_close(void); int sd_bus_is_open(sd_bus *bus); int sd_bus_get_bus_id(sd_bus *bus, sd_id128_t *id); int sd_bus_get_scope(sd_bus *bus, const char **scope); int sd_bus_get_tid(sd_bus *bus, pid_t *tid); int sd_bus_get_owner_creds(sd_bus *bus, uint64_t creds_mask, sd_bus_creds **ret); int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie); int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie); int sd_bus_call(sd_bus *bus, sd_bus_message *m, uint64_t usec, sd_bus_error *ret_error, sd_bus_message **reply); int sd_bus_call_async(sd_bus *bus, sd_bus_slot **slot, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec); int sd_bus_get_fd(sd_bus *bus); int sd_bus_get_events(sd_bus *bus); int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec); int sd_bus_process(sd_bus *bus, sd_bus_message **r); int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r); int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec); int sd_bus_flush(sd_bus *bus); sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus); sd_bus_message* sd_bus_get_current_message(sd_bus *bus); sd_bus_message_handler_t sd_bus_get_current_handler(sd_bus *bus); void* sd_bus_get_current_userdata(sd_bus *bus); int sd_bus_attach_event(sd_bus *bus, sd_event *e, int priority); int sd_bus_detach_event(sd_bus *bus); sd_event *sd_bus_get_event(sd_bus *bus); int sd_bus_add_filter(sd_bus *bus, sd_bus_slot **slot, sd_bus_message_handler_t callback, void *userdata); int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata); int sd_bus_add_object(sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_message_handler_t callback, void *userdata); int sd_bus_add_fallback(sd_bus *bus, sd_bus_slot **slot, const char *prefix, sd_bus_message_handler_t callback, void *userdata); int sd_bus_add_object_vtable(sd_bus *bus, sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata); int sd_bus_add_fallback_vtable(sd_bus *bus, sd_bus_slot **slot, const char *prefix, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata); int sd_bus_add_node_enumerator(sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_node_enumerator_t callback, void *userdata); int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path); /* Slot object */ sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot); sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot); sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot); void *sd_bus_slot_get_userdata(sd_bus_slot *slot); void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata); int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description); int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description); sd_bus_message* sd_bus_slot_get_current_message(sd_bus_slot *slot); sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *bus); void *sd_bus_slot_get_current_userdata(sd_bus_slot *slot); /* Message object */ int sd_bus_message_new_signal(sd_bus *bus, sd_bus_message **m, const char *path, const char *interface, const char *member); int sd_bus_message_new_method_call(sd_bus *bus, sd_bus_message **m, const char *destination, const char *path, const char *interface, const char *member); int sd_bus_message_new_method_return(sd_bus_message *call, sd_bus_message **m); int sd_bus_message_new_method_error(sd_bus_message *call, sd_bus_message **m, const sd_bus_error *e); int sd_bus_message_new_method_errorf(sd_bus_message *call, sd_bus_message **m, const char *name, const char *format, ...) _sd_printf_(4, 5); int sd_bus_message_new_method_errno(sd_bus_message *call, sd_bus_message **m, int error, const sd_bus_error *e); int sd_bus_message_new_method_errnof(sd_bus_message *call, sd_bus_message **m, int error, const char *format, ...) _sd_printf_(4, 5); sd_bus_message* sd_bus_message_ref(sd_bus_message *m); sd_bus_message* sd_bus_message_unref(sd_bus_message *m); int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type); int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie); int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie); int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority); int sd_bus_message_get_expect_reply(sd_bus_message *m); int sd_bus_message_get_auto_start(sd_bus_message *m); int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m); const char *sd_bus_message_get_signature(sd_bus_message *m, int complete); const char *sd_bus_message_get_path(sd_bus_message *m); const char *sd_bus_message_get_interface(sd_bus_message *m); const char *sd_bus_message_get_member(sd_bus_message *m); const char *sd_bus_message_get_destination(sd_bus_message *m); const char *sd_bus_message_get_sender(sd_bus_message *m); const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m); int sd_bus_message_get_errno(sd_bus_message *m); int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec); int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec); int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t* seqnum); sd_bus* sd_bus_message_get_bus(sd_bus_message *m); sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m); /* do not unref the result */ int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member); int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member); int sd_bus_message_is_method_error(sd_bus_message *m, const char *name); int sd_bus_message_is_empty(sd_bus_message *m); int sd_bus_message_has_signature(sd_bus_message *m, const char *signature); int sd_bus_message_set_expect_reply(sd_bus_message *m, int b); int sd_bus_message_set_auto_start(sd_bus_message *m, int b); int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b); int sd_bus_message_set_destination(sd_bus_message *m, const char *destination); int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority); int sd_bus_message_append(sd_bus_message *m, const char *types, ...); int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p); int sd_bus_message_append_array(sd_bus_message *m, char type, const void *ptr, size_t size); int sd_bus_message_append_array_space(sd_bus_message *m, char type, size_t size, void **ptr); int sd_bus_message_append_array_iovec(sd_bus_message *m, char type, const struct iovec *iov, unsigned n); int sd_bus_message_append_array_memfd(sd_bus_message *m, char type, int memfd, uint64_t offset, uint64_t size); int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s); int sd_bus_message_append_string_iovec(sd_bus_message *m, const struct iovec *iov, unsigned n); int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd, uint64_t offset, uint64_t size); int sd_bus_message_append_strv(sd_bus_message *m, char **l); int sd_bus_message_open_container(sd_bus_message *m, char type, const char *contents); int sd_bus_message_close_container(sd_bus_message *m); int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all); int sd_bus_message_read(sd_bus_message *m, const char *types, ...); int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p); int sd_bus_message_read_array(sd_bus_message *m, char type, const void **ptr, size_t *size); int sd_bus_message_read_strv(sd_bus_message *m, char ***l); /* free the result! */ int sd_bus_message_skip(sd_bus_message *m, const char *types); int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents); int sd_bus_message_exit_container(sd_bus_message *m); int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents); int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents); int sd_bus_message_at_end(sd_bus_message *m, int complete); int sd_bus_message_rewind(sd_bus_message *m, int complete); /* Bus management */ int sd_bus_get_unique_name(sd_bus *bus, const char **unique); int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags); int sd_bus_release_name(sd_bus *bus, const char *name); int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable); /* free the results */ int sd_bus_get_name_creds(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **creds); /* unref the result! */ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine); /* Convenience calls */ int sd_bus_call_method(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, sd_bus_message **reply, const char *types, ...); int sd_bus_call_method_async(sd_bus *bus, sd_bus_slot **slot, const char *destination, const char *path, const char *interface, const char *member, sd_bus_message_handler_t callback, void *userdata, const char *types, ...); int sd_bus_get_property(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, sd_bus_message **reply, const char *type); int sd_bus_get_property_trivial(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, char type, void *ret_ptr); int sd_bus_get_property_string(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, char **ret); /* free the result! */ int sd_bus_get_property_strv(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, char ***ret); /* free the result! */ int sd_bus_set_property(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, const char *type, ...); int sd_bus_reply_method_return(sd_bus_message *call, const char *types, ...); int sd_bus_reply_method_error(sd_bus_message *call, const sd_bus_error *e); int sd_bus_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) _sd_printf_(3, 4); int sd_bus_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *e); int sd_bus_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) _sd_printf_(3, 4); int sd_bus_emit_signal(sd_bus *bus, const char *path, const char *interface, const char *member, const char *types, ...); int sd_bus_emit_properties_changed_strv(sd_bus *bus, const char *path, const char *interface, char **names); int sd_bus_emit_properties_changed(sd_bus *bus, const char *path, const char *interface, const char *name, ...) _sd_sentinel_; int sd_bus_emit_object_added(sd_bus *bus, const char *path); int sd_bus_emit_object_removed(sd_bus *bus, const char *path); int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces); int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) _sd_sentinel_; int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces); int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) _sd_sentinel_; int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds); int sd_bus_query_sender_privilege(sd_bus_message *call, int capability); /* Credential handling */ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t creds_mask); sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c); sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c); uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c); uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c); int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid); int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid); int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid); int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid); int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid); int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid); int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid); int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid); int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid); int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid); int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid); int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids); int sd_bus_creds_get_comm(sd_bus_creds *c, const char **comm); int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **comm); int sd_bus_creds_get_exe(sd_bus_creds *c, const char **exe); int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline); int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **cgroup); int sd_bus_creds_get_unit(sd_bus_creds *c, const char **unit); int sd_bus_creds_get_slice(sd_bus_creds *c, const char **slice); int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **unit); int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **slice); int sd_bus_creds_get_session(sd_bus_creds *c, const char **session); int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid); int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability); int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability); int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability); int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability); int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **context); int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid); int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *loginuid); int sd_bus_creds_get_tty(sd_bus_creds *c, const char **tty); int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **name); int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***names); int sd_bus_creds_get_description(sd_bus_creds *c, const char **name); /* Error structures */ #define SD_BUS_ERROR_MAKE_CONST(name, message) ((const sd_bus_error) {(name), (message), 0}) #define SD_BUS_ERROR_NULL SD_BUS_ERROR_MAKE_CONST(NULL, NULL) void sd_bus_error_free(sd_bus_error *e); int sd_bus_error_set(sd_bus_error *e, const char *name, const char *message); int sd_bus_error_setf(sd_bus_error *e, const char *name, const char *format, ...) _sd_printf_(3, 4); int sd_bus_error_set_const(sd_bus_error *e, const char *name, const char *message); int sd_bus_error_set_errno(sd_bus_error *e, int error); int sd_bus_error_set_errnof(sd_bus_error *e, int error, const char *format, ...) _sd_printf_(3, 4); int sd_bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) _sd_printf_(3,0); int sd_bus_error_get_errno(const sd_bus_error *e); int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e); int sd_bus_error_is_set(const sd_bus_error *e); int sd_bus_error_has_name(const sd_bus_error *e, const char *name); #define SD_BUS_ERROR_MAP(_name, _code) \ { \ .name = _name, \ .code = _code, \ } #define SD_BUS_ERROR_MAP_END \ { \ .name = NULL, \ .code = - 'x', \ } int sd_bus_error_add_map(const sd_bus_error_map *map); /* Auxiliary macros */ #define SD_BUS_MESSAGE_APPEND_ID128(x) 16, \ (x).bytes[0], (x).bytes[1], (x).bytes[2], (x).bytes[3], \ (x).bytes[4], (x).bytes[5], (x).bytes[6], (x).bytes[7], \ (x).bytes[8], (x).bytes[9], (x).bytes[10], (x).bytes[11], \ (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15] #define SD_BUS_MESSAGE_READ_ID128(x) 16, \ &(x).bytes[0], &(x).bytes[1], &(x).bytes[2], &(x).bytes[3], \ &(x).bytes[4], &(x).bytes[5], &(x).bytes[6], &(x).bytes[7], \ &(x).bytes[8], &(x).bytes[9], &(x).bytes[10], &(x).bytes[11], \ &(x).bytes[12], &(x).bytes[13], &(x).bytes[14], &(x).bytes[15] /* Label escaping */ int sd_bus_path_encode(const char *prefix, const char *external_id, char **ret_path); int sd_bus_path_encode_many(char **out, const char *path_template, ...); int sd_bus_path_decode(const char *path, const char *prefix, char **ret_external_id); int sd_bus_path_decode_many(const char *path, const char *path_template, ...); /* Tracking peers */ int sd_bus_track_new(sd_bus *bus, sd_bus_track **track, sd_bus_track_handler_t handler, void *userdata); sd_bus_track* sd_bus_track_ref(sd_bus_track *track); sd_bus_track* sd_bus_track_unref(sd_bus_track *track); sd_bus* sd_bus_track_get_bus(sd_bus_track *track); void *sd_bus_track_get_userdata(sd_bus_track *track); void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata); int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m); int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m); int sd_bus_track_add_name(sd_bus_track *track, const char *name); int sd_bus_track_remove_name(sd_bus_track *track, const char *name); unsigned sd_bus_track_count(sd_bus_track *track); const char* sd_bus_track_contains(sd_bus_track *track, const char *names); const char* sd_bus_track_first(sd_bus_track *track); const char* sd_bus_track_next(sd_bus_track *track); /* Define helpers so that __attribute__((cleanup(sd_bus_unrefp))) and similar may be used. */ _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_flush_close_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_slot, sd_bus_slot_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_message, sd_bus_message_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_creds, sd_bus_creds_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_track, sd_bus_track_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-daemon.h000066400000000000000000000262661265713322000173740ustar00rootroot00000000000000#ifndef foosddaemonhfoo #define foosddaemonhfoo /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; /* The following functionality is provided: - Support for logging with log levels on stderr - File descriptor passing for socket-based activation - Daemon startup and status notification - Detection of systemd boots See sd-daemon(3) for more information. */ /* Log levels for usage on stderr: fprintf(stderr, SD_NOTICE "Hello World!\n"); This is similar to printk() usage in the kernel. */ #define SD_EMERG "<0>" /* system is unusable */ #define SD_ALERT "<1>" /* action must be taken immediately */ #define SD_CRIT "<2>" /* critical conditions */ #define SD_ERR "<3>" /* error conditions */ #define SD_WARNING "<4>" /* warning conditions */ #define SD_NOTICE "<5>" /* normal but significant condition */ #define SD_INFO "<6>" /* informational */ #define SD_DEBUG "<7>" /* debug-level messages */ /* The first passed file descriptor is fd 3 */ #define SD_LISTEN_FDS_START 3 /* Returns how many file descriptors have been passed, or a negative errno code on failure. Optionally, removes the $LISTEN_FDS and $LISTEN_PID file descriptors from the environment (recommended, but problematic in threaded environments). If r is the return value of this function you'll find the file descriptors passed as fds SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative errno style error code on failure. This function call ensures that the FD_CLOEXEC flag is set for the passed file descriptors, to make sure they are not passed on to child processes. If FD_CLOEXEC shall not be set, the caller needs to unset it after this call for all file descriptors that are used. See sd_listen_fds(3) for more information. */ int sd_listen_fds(int unset_environment); int sd_listen_fds_with_names(int unset_environment, char ***names); /* Helper call for identifying a passed file descriptor. Returns 1 if the file descriptor is a FIFO in the file system stored under the specified path, 0 otherwise. If path is NULL a path name check will not be done and the call only verifies if the file descriptor refers to a FIFO. Returns a negative errno style error code on failure. See sd_is_fifo(3) for more information. */ int sd_is_fifo(int fd, const char *path); /* Helper call for identifying a passed file descriptor. Returns 1 if the file descriptor is a special character device on the file system stored under the specified path, 0 otherwise. If path is NULL a path name check will not be done and the call only verifies if the file descriptor refers to a special character. Returns a negative errno style error code on failure. See sd_is_special(3) for more information. */ int sd_is_special(int fd, const char *path); /* Helper call for identifying a passed file descriptor. Returns 1 if the file descriptor is a socket of the specified family (AF_INET, ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If family is 0 a socket family check will not be done. If type is 0 a socket type check will not be done and the call only verifies if the file descriptor refers to a socket. If listening is > 0 it is verified that the socket is in listening mode. (i.e. listen() has been called) If listening is == 0 it is verified that the socket is not in listening mode. If listening is < 0 no listening mode check is done. Returns a negative errno style error code on failure. See sd_is_socket(3) for more information. */ int sd_is_socket(int fd, int family, int type, int listening); /* Helper call for identifying a passed file descriptor. Returns 1 if the file descriptor is an Internet socket, of the specified family (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version check is not done. If type is 0 a socket type check will not be done. If port is 0 a socket port check will not be done. The listening flag is used the same way as in sd_is_socket(). Returns a negative errno style error code on failure. See sd_is_socket_inet(3) for more information. */ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port); /* Helper call for identifying a passed file descriptor. Returns 1 if the file descriptor is an AF_UNIX socket of the specified type (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0 a socket type check will not be done. If path is NULL a socket path check will not be done. For normal AF_UNIX sockets set length to 0. For abstract namespace sockets set length to the length of the socket name (including the initial 0 byte), and pass the full socket path in path (including the initial 0 byte). The listening flag is used the same way as in sd_is_socket(). Returns a negative errno style error code on failure. See sd_is_socket_unix(3) for more information. */ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length); /* Helper call for identifying a passed file descriptor. Returns 1 if the file descriptor is a POSIX Message Queue of the specified name, 0 otherwise. If path is NULL a message queue name check is not done. Returns a negative errno style error code on failure. See sd_is_mq(3) for more information. */ int sd_is_mq(int fd, const char *path); /* Informs systemd about changed daemon state. This takes a number of newline separated environment-style variable assignments in a string. The following variables are known: READY=1 Tells systemd that daemon startup is finished (only relevant for services of Type=notify). The passed argument is a boolean "1" or "0". Since there is little value in signaling non-readiness the only value daemons should send is "READY=1". STATUS=... Passes a single-line status string back to systemd that describes the daemon state. This is free-form and can be used for various purposes: general state feedback, fsck-like programs could pass completion percentages and failing programs could pass a human readable error message. Example: "STATUS=Completed 66% of file system check..." ERRNO=... If a daemon fails, the errno-style error code, formatted as string. Example: "ERRNO=2" for ENOENT. BUSERROR=... If a daemon fails, the D-Bus error-style error code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut" MAINPID=... The main pid of a daemon, in case systemd did not fork off the process itself. Example: "MAINPID=4711" WATCHDOG=1 Tells systemd to update the watchdog timestamp. Services using this feature should do this in regular intervals. A watchdog framework can use the timestamps to detect failed services. Also see sd_watchdog_enabled() below. FDSTORE=1 Store the file descriptors passed along with the message in the per-service file descriptor store, and pass them to the main process again on next invocation. This variable is only supported with sd_pid_notify_with_fds(). Daemons can choose to send additional variables. However, it is recommended to prefix variable names not listed above with X_. Returns a negative errno-style error code on failure. Returns > 0 if systemd could be notified, 0 if it couldn't possibly because systemd is not running. Example: When a daemon finished starting up, it could issue this call to notify systemd about it: sd_notify(0, "READY=1"); See sd_notifyf() for more complete examples. See sd_notify(3) for more information. */ int sd_notify(int unset_environment, const char *state); /* Similar to sd_notify() but takes a format string. Example 1: A daemon could send the following after initialization: sd_notifyf(0, "READY=1\n" "STATUS=Processing requests...\n" "MAINPID=%lu", (unsigned long) getpid()); Example 2: A daemon could send the following shortly before exiting, on failure: sd_notifyf(0, "STATUS=Failed to start up: %s\n" "ERRNO=%i", strerror(errno), errno); See sd_notifyf(3) for more information. */ int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_(2,3); /* Similar to sd_notify(), but send the message on behalf of another process, if the appropriate permissions are available. */ int sd_pid_notify(pid_t pid, int unset_environment, const char *state); /* Similar to sd_notifyf(), but send the message on behalf of another process, if the appropriate permissions are available. */ int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...) _sd_printf_(3,4); /* Similar to sd_pid_notify(), but also passes the specified fd array to the service manager for storage. This is particularly useful for FDSTORE=1 messages. */ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char *state, const int *fds, unsigned n_fds); /* Returns > 0 if the system was booted with systemd. Returns < 0 on error. Returns 0 if the system was not booted with systemd. Note that all of the functions above handle non-systemd boots just fine. You should NOT protect them with a call to this function. Also note that this function checks whether the system, not the user session is controlled by systemd. However the functions above work for both user and system services. See sd_booted(3) for more information. */ int sd_booted(void); /* Returns > 0 if the service manager expects watchdog keep-alive events to be sent regularly via sd_notify(0, "WATCHDOG=1"). Returns 0 if it does not expect this. If the usec argument is non-NULL returns the watchdog timeout in µs after which the service manager will act on a process that has not sent a watchdog keep alive message. This function is useful to implement services that recognize automatically if they are being run under supervision of systemd with WatchdogSec= set. It is recommended for clients to generate keep-alive pings via sd_notify(0, "WATCHDOG=1") every half of the returned time. See sd_watchdog_enabled(3) for more information. */ int sd_watchdog_enabled(int unset_environment, uint64_t *usec); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-device.h000066400000000000000000000112211265713322000173510ustar00rootroot00000000000000#ifndef foosddevicehfoo #define foosddevicehfoo /*** This file is part of systemd. Copyright 2008-2012 Kay Sievers Copyright 2014-2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; typedef struct sd_device sd_device; typedef struct sd_device_enumerator sd_device_enumerator; /* device */ sd_device *sd_device_ref(sd_device *device); sd_device *sd_device_unref(sd_device *device); int sd_device_new_from_syspath(sd_device **ret, const char *syspath); int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum); int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, const char *sysname); int sd_device_new_from_device_id(sd_device **ret, const char *id); int sd_device_get_parent(sd_device *child, sd_device **ret); int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *subsystem, const char *devtype, sd_device **ret); int sd_device_get_syspath(sd_device *device, const char **ret); int sd_device_get_subsystem(sd_device *device, const char **ret); int sd_device_get_devtype(sd_device *device, const char **ret); int sd_device_get_devnum(sd_device *device, dev_t *devnum); int sd_device_get_ifindex(sd_device *device, int *ifindex); int sd_device_get_driver(sd_device *device, const char **ret); int sd_device_get_devpath(sd_device *device, const char **ret); int sd_device_get_devname(sd_device *device, const char **ret); int sd_device_get_sysname(sd_device *device, const char **ret); int sd_device_get_sysnum(sd_device *device, const char **ret); int sd_device_get_is_initialized(sd_device *device, int *initialized); int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec); const char *sd_device_get_tag_first(sd_device *device); const char *sd_device_get_tag_next(sd_device *device); const char *sd_device_get_devlink_first(sd_device *device); const char *sd_device_get_devlink_next(sd_device *device); const char *sd_device_get_property_first(sd_device *device, const char **value); const char *sd_device_get_property_next(sd_device *device, const char **value); const char *sd_device_get_sysattr_first(sd_device *device); const char *sd_device_get_sysattr_next(sd_device *device); int sd_device_has_tag(sd_device *device, const char *tag); int sd_device_get_property_value(sd_device *device, const char *key, const char **value); int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value); int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, char *value); /* device enumerator */ int sd_device_enumerator_new(sd_device_enumerator **ret); sd_device_enumerator *sd_device_enumerator_ref(sd_device_enumerator *enumerator); sd_device_enumerator *sd_device_enumerator_unref(sd_device_enumerator *enumerator); sd_device *sd_device_enumerator_get_device_first(sd_device_enumerator *enumerator); sd_device *sd_device_enumerator_get_device_next(sd_device_enumerator *enumerator); sd_device *sd_device_enumerator_get_subsystem_first(sd_device_enumerator *enumerator); sd_device *sd_device_enumerator_get_subsystem_next(sd_device_enumerator *enumerator); int sd_device_enumerator_add_match_subsystem(sd_device_enumerator *enumerator, const char *subsystem, int match); int sd_device_enumerator_add_match_sysattr(sd_device_enumerator *enumerator, const char *sysattr, const char *value, int match); int sd_device_enumerator_add_match_property(sd_device_enumerator *enumerator, const char *property, const char *value); int sd_device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname); int sd_device_enumerator_add_match_tag(sd_device_enumerator *enumerator, const char *tag); int sd_device_enumerator_add_match_parent(sd_device_enumerator *enumerator, sd_device *parent); int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_device, sd_device_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_device_enumerator, sd_device_enumerator_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-dhcp-client.h000066400000000000000000000125701265713322000203140ustar00rootroot00000000000000#ifndef foosddhcpclienthfoo #define foosddhcpclienthfoo /*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-dhcp-lease.h" #include "sd-event.h" #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; enum { SD_DHCP_CLIENT_EVENT_STOP = 0, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE = 1, SD_DHCP_CLIENT_EVENT_IP_CHANGE = 2, SD_DHCP_CLIENT_EVENT_EXPIRED = 3, SD_DHCP_CLIENT_EVENT_RENEW = 4, }; enum { SD_DHCP_OPTION_PAD = 0, SD_DHCP_OPTION_SUBNET_MASK = 1, SD_DHCP_OPTION_TIME_OFFSET = 2, SD_DHCP_OPTION_ROUTER = 3, SD_DHCP_OPTION_DOMAIN_NAME_SERVER = 6, SD_DHCP_OPTION_HOST_NAME = 12, SD_DHCP_OPTION_BOOT_FILE_SIZE = 13, SD_DHCP_OPTION_DOMAIN_NAME = 15, SD_DHCP_OPTION_ROOT_PATH = 17, SD_DHCP_OPTION_ENABLE_IP_FORWARDING = 19, SD_DHCP_OPTION_ENABLE_IP_FORWARDING_NL = 20, SD_DHCP_OPTION_POLICY_FILTER = 21, SD_DHCP_OPTION_INTERFACE_MDR = 22, SD_DHCP_OPTION_INTERFACE_TTL = 23, SD_DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24, SD_DHCP_OPTION_INTERFACE_MTU = 26, SD_DHCP_OPTION_BROADCAST = 28, SD_DHCP_OPTION_STATIC_ROUTE = 33, SD_DHCP_OPTION_NTP_SERVER = 42, SD_DHCP_OPTION_VENDOR_SPECIFIC = 43, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS = 50, SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51, SD_DHCP_OPTION_OVERLOAD = 52, SD_DHCP_OPTION_MESSAGE_TYPE = 53, SD_DHCP_OPTION_SERVER_IDENTIFIER = 54, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST = 55, SD_DHCP_OPTION_ERROR_MESSAGE = 56, SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE = 57, SD_DHCP_OPTION_RENEWAL_T1_TIME = 58, SD_DHCP_OPTION_REBINDING_T2_TIME = 59, SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60, SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61, SD_DHCP_OPTION_FQDN = 81, SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121, SD_DHCP_OPTION_PRIVATE_BASE = 224, SD_DHCP_OPTION_PRIVATE_LAST = 254, SD_DHCP_OPTION_END = 255, }; typedef struct sd_dhcp_client sd_dhcp_client; typedef void (*sd_dhcp_client_cb_t)(sd_dhcp_client *client, int event, void *userdata); int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb, void *userdata); int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option); int sd_dhcp_client_set_request_address(sd_dhcp_client *client, const struct in_addr *last_address); int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast); int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index); int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr, size_t addr_len, uint16_t arp_type); int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type, const uint8_t *data, size_t data_len); int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type, const uint8_t **data, size_t *data_len); int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu); int sd_dhcp_client_set_hostname(sd_dhcp_client *client, const char *hostname); int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client, const char *vci); int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret); int sd_dhcp_client_stop(sd_dhcp_client *client); int sd_dhcp_client_start(sd_dhcp_client *client); sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client); sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client); int sd_dhcp_client_new(sd_dhcp_client **ret); int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int priority); int sd_dhcp_client_detach_event(sd_dhcp_client *client); sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_client, sd_dhcp_client_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-dhcp-lease.h000066400000000000000000000057041265713322000201300ustar00rootroot00000000000000#ifndef foosddhcpleasehfoo #define foosddhcpleasehfoo /*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. Copyright (C) 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; typedef struct sd_dhcp_lease sd_dhcp_lease; typedef struct sd_dhcp_route sd_dhcp_route; sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease); sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease); int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime); int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1); int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2); int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu); int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname); int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname); int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path); int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes); int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len); int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len); int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone); int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination); int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length); int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_lease, sd_dhcp_lease_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-dhcp-server.h000066400000000000000000000043331265713322000203420ustar00rootroot00000000000000#ifndef foosddhcpserverhfoo #define foosddhcpserverhfoo /*** This file is part of systemd. Copyright (C) 2013 Intel Corporation. All rights reserved. Copyright (C) 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-event.h" #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; typedef struct sd_dhcp_server sd_dhcp_server; int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex); sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server); sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server); int sd_dhcp_server_attach_event(sd_dhcp_server *client, sd_event *event, int priority); int sd_dhcp_server_detach_event(sd_dhcp_server *client); sd_event *sd_dhcp_server_get_event(sd_dhcp_server *client); int sd_dhcp_server_is_running(sd_dhcp_server *server); int sd_dhcp_server_start(sd_dhcp_server *server); int sd_dhcp_server_stop(sd_dhcp_server *server); int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *address, unsigned char prefixlen, uint32_t offset, uint32_t size); int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone); int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n); int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr dns[], unsigned n); int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t); int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t); int sd_dhcp_server_forcerenew(sd_dhcp_server *server); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_server, sd_dhcp_server_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-dhcp6-client.h000066400000000000000000000111211265713322000203710ustar00rootroot00000000000000#ifndef foosddhcp6clienthfoo #define foosddhcp6clienthfoo /*** This file is part of systemd. Copyright (C) 2014 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-dhcp6-lease.h" #include "sd-event.h" #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; enum { SD_DHCP6_CLIENT_EVENT_STOP = 0, SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE = 10, SD_DHCP6_CLIENT_EVENT_RETRANS_MAX = 11, SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE = 12, SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST = 13, }; enum { SD_DHCP6_OPTION_CLIENTID = 1, SD_DHCP6_OPTION_SERVERID = 2, SD_DHCP6_OPTION_IA_NA = 3, SD_DHCP6_OPTION_IA_TA = 4, SD_DHCP6_OPTION_IAADDR = 5, SD_DHCP6_OPTION_ORO = 6, SD_DHCP6_OPTION_PREFERENCE = 7, SD_DHCP6_OPTION_ELAPSED_TIME = 8, SD_DHCP6_OPTION_RELAY_MSG = 9, /* option code 10 is unassigned */ SD_DHCP6_OPTION_AUTH = 11, SD_DHCP6_OPTION_UNICAST = 12, SD_DHCP6_OPTION_STATUS_CODE = 13, SD_DHCP6_OPTION_RAPID_COMMIT = 14, SD_DHCP6_OPTION_USER_CLASS = 15, SD_DHCP6_OPTION_VENDOR_CLASS = 16, SD_DHCP6_OPTION_VENDOR_OPTS = 17, SD_DHCP6_OPTION_INTERFACE_ID = 18, SD_DHCP6_OPTION_RECONF_MSG = 19, SD_DHCP6_OPTION_RECONF_ACCEPT = 20, SD_DHCP6_OPTION_DNS_SERVERS = 23, /* RFC 3646 */ SD_DHCP6_OPTION_DOMAIN_LIST = 24, /* RFC 3646 */ SD_DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */ /* option code 35 is unassigned */ SD_DHCP6_OPTION_NTP_SERVER = 56, /* RFC 5908 */ /* option codes 89-142 are unassigned */ /* option codes 144-65535 are unassigned */ }; typedef struct sd_dhcp6_client sd_dhcp6_client; typedef void (*sd_dhcp6_client_cb_t)(sd_dhcp6_client *client, int event, void *userdata); int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_cb_t cb, void *userdata); int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index); int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address); int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr, size_t addr_len, uint16_t arp_type); int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *duid, size_t duid_len); int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled); int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled); int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option); int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret); int sd_dhcp6_client_stop(sd_dhcp6_client *client); int sd_dhcp6_client_start(sd_dhcp6_client *client); int sd_dhcp6_client_is_running(sd_dhcp6_client *client); int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int priority); int sd_dhcp6_client_detach_event(sd_dhcp6_client *client); sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client); sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client); sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client); int sd_dhcp6_client_new(sd_dhcp6_client **ret); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp6_client, sd_dhcp6_client_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-dhcp6-lease.h000066400000000000000000000034551265713322000202170ustar00rootroot00000000000000#ifndef foosddhcp6leasehfoo #define foosddhcp6leasehfoo /*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014-2015 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; typedef struct sd_dhcp6_lease sd_dhcp6_lease; void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease); int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr, uint32_t *lifetime_preferred, uint32_t *lifetime_valid); int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs); int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains); int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, struct in6_addr **addrs); int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn); sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease); sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp6_lease, sd_dhcp6_lease_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-event.h000066400000000000000000000131661265713322000172450ustar00rootroot00000000000000#ifndef foosdeventhfoo #define foosdeventhfoo /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "_sd-common.h" /* Why is this better than pure epoll? - Supports event source prioritization - Scales better with a large number of time events because it does not require one timerfd each - Automatically tries to coalesce timer events system-wide - Handles signals and child PIDs */ _SD_BEGIN_DECLARATIONS; typedef struct sd_event sd_event; typedef struct sd_event_source sd_event_source; enum { SD_EVENT_OFF = 0, SD_EVENT_ON = 1, SD_EVENT_ONESHOT = -1 }; enum { SD_EVENT_INITIAL, SD_EVENT_ARMED, SD_EVENT_PENDING, SD_EVENT_RUNNING, SD_EVENT_EXITING, SD_EVENT_FINISHED, SD_EVENT_PREPARING, }; enum { /* And everything in-between and outside is good too */ SD_EVENT_PRIORITY_IMPORTANT = -100, SD_EVENT_PRIORITY_NORMAL = 0, SD_EVENT_PRIORITY_IDLE = 100 }; typedef int (*sd_event_handler_t)(sd_event_source *s, void *userdata); typedef int (*sd_event_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata); typedef int (*sd_event_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata); typedef int (*sd_event_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata); typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata); int sd_event_default(sd_event **e); int sd_event_new(sd_event **e); sd_event* sd_event_ref(sd_event *e); sd_event* sd_event_unref(sd_event *e); int sd_event_add_io(sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata); int sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata); int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata); int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata); int sd_event_add_defer(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); int sd_event_add_post(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); int sd_event_add_exit(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); int sd_event_prepare(sd_event *e); int sd_event_wait(sd_event *e, uint64_t usec); int sd_event_dispatch(sd_event *e); int sd_event_run(sd_event *e, uint64_t usec); int sd_event_loop(sd_event *e); int sd_event_exit(sd_event *e, int code); int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec); int sd_event_get_fd(sd_event *e); int sd_event_get_state(sd_event *e); int sd_event_get_tid(sd_event *e, pid_t *tid); int sd_event_get_exit_code(sd_event *e, int *code); int sd_event_set_watchdog(sd_event *e, int b); int sd_event_get_watchdog(sd_event *e); sd_event_source* sd_event_source_ref(sd_event_source *s); sd_event_source* sd_event_source_unref(sd_event_source *s); sd_event *sd_event_source_get_event(sd_event_source *s); void* sd_event_source_get_userdata(sd_event_source *s); void* sd_event_source_set_userdata(sd_event_source *s, void *userdata); int sd_event_source_set_description(sd_event_source *s, const char *description); int sd_event_source_get_description(sd_event_source *s, const char **description); int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback); int sd_event_source_get_pending(sd_event_source *s); int sd_event_source_get_priority(sd_event_source *s, int64_t *priority); int sd_event_source_set_priority(sd_event_source *s, int64_t priority); int sd_event_source_get_enabled(sd_event_source *s, int *enabled); int sd_event_source_set_enabled(sd_event_source *s, int enabled); int sd_event_source_get_io_fd(sd_event_source *s); int sd_event_source_set_io_fd(sd_event_source *s, int fd); int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events); int sd_event_source_set_io_events(sd_event_source *s, uint32_t events); int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents); int sd_event_source_get_time(sd_event_source *s, uint64_t *usec); int sd_event_source_set_time(sd_event_source *s, uint64_t usec); int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec); int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec); int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock); int sd_event_source_get_signal(sd_event_source *s); int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid); /* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */ _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-hwdb.h000066400000000000000000000031271265713322000170440ustar00rootroot00000000000000#ifndef foosdhwdbhfoo #define foosdhwdbhfoo /*** This file is part of systemd. Copyright 2008-2012 Kay Sievers Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; typedef struct sd_hwdb sd_hwdb; sd_hwdb *sd_hwdb_ref(sd_hwdb *hwdb); sd_hwdb *sd_hwdb_unref(sd_hwdb *hwdb); int sd_hwdb_new(sd_hwdb **ret); int sd_hwdb_get(sd_hwdb *hwdb, const char *modalias, const char *key, const char **value); int sd_hwdb_seek(sd_hwdb *hwdb, const char *modalias); int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **value); /* the inverse condition avoids ambiguity of dangling 'else' after the macro */ #define SD_HWDB_FOREACH_PROPERTY(hwdb, modalias, key, value) \ if (sd_hwdb_seek(hwdb, modalias) < 0) { } \ else while (sd_hwdb_enumerate(hwdb, &(key), &(value)) > 0) _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_hwdb, sd_hwdb_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-id128.h000066400000000000000000000144031265713322000167460ustar00rootroot00000000000000#ifndef foosdid128hfoo #define foosdid128hfoo /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; /* 128-bit ID APIs. See sd-id128(3) for more information. */ typedef union sd_id128 sd_id128_t; union sd_id128 { uint8_t bytes[16]; uint64_t qwords[2]; }; #define SD_ID128_STRING_MAX 33 char *sd_id128_to_string(sd_id128_t id, char s[SD_ID128_STRING_MAX]); int sd_id128_from_string(const char *s, sd_id128_t *ret); int sd_id128_randomize(sd_id128_t *ret); int sd_id128_get_machine(sd_id128_t *ret); int sd_id128_get_boot(sd_id128_t *ret); #define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \ ((const sd_id128_t) { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \ 0x##v8, 0x##v9, 0x##v10, 0x##v11, 0x##v12, 0x##v13, 0x##v14, 0x##v15 }}) #define SD_ID128_ARRAY(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \ { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \ 0x##v8, 0x##v9, 0x##v10, 0x##v11, 0x##v12, 0x##v13, 0x##v14, 0x##v15 }} /* Note that SD_ID128_FORMAT_VAL will evaluate the passed argument 16 * times. It is hence not a good idea to call this macro with an * expensive function as parameter or an expression with side * effects */ #define SD_ID128_FORMAT_STR "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" #define SD_ID128_FORMAT_VAL(x) (x).bytes[0], (x).bytes[1], (x).bytes[2], (x).bytes[3], (x).bytes[4], (x).bytes[5], (x).bytes[6], (x).bytes[7], (x).bytes[8], (x).bytes[9], (x).bytes[10], (x).bytes[11], (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15] #define SD_ID128_CONST_STR(x) \ ((const char[SD_ID128_STRING_MAX]) { \ ((x).bytes[0] >> 4) >= 10 ? 'a' + ((x).bytes[0] >> 4) - 10 : '0' + ((x).bytes[0] >> 4), \ ((x).bytes[0] & 15) >= 10 ? 'a' + ((x).bytes[0] & 15) - 10 : '0' + ((x).bytes[0] & 15), \ ((x).bytes[1] >> 4) >= 10 ? 'a' + ((x).bytes[1] >> 4) - 10 : '0' + ((x).bytes[1] >> 4), \ ((x).bytes[1] & 15) >= 10 ? 'a' + ((x).bytes[1] & 15) - 10 : '0' + ((x).bytes[1] & 15), \ ((x).bytes[2] >> 4) >= 10 ? 'a' + ((x).bytes[2] >> 4) - 10 : '0' + ((x).bytes[2] >> 4), \ ((x).bytes[2] & 15) >= 10 ? 'a' + ((x).bytes[2] & 15) - 10 : '0' + ((x).bytes[2] & 15), \ ((x).bytes[3] >> 4) >= 10 ? 'a' + ((x).bytes[3] >> 4) - 10 : '0' + ((x).bytes[3] >> 4), \ ((x).bytes[3] & 15) >= 10 ? 'a' + ((x).bytes[3] & 15) - 10 : '0' + ((x).bytes[3] & 15), \ ((x).bytes[4] >> 4) >= 10 ? 'a' + ((x).bytes[4] >> 4) - 10 : '0' + ((x).bytes[4] >> 4), \ ((x).bytes[4] & 15) >= 10 ? 'a' + ((x).bytes[4] & 15) - 10 : '0' + ((x).bytes[4] & 15), \ ((x).bytes[5] >> 4) >= 10 ? 'a' + ((x).bytes[5] >> 4) - 10 : '0' + ((x).bytes[5] >> 4), \ ((x).bytes[5] & 15) >= 10 ? 'a' + ((x).bytes[5] & 15) - 10 : '0' + ((x).bytes[5] & 15), \ ((x).bytes[6] >> 4) >= 10 ? 'a' + ((x).bytes[6] >> 4) - 10 : '0' + ((x).bytes[6] >> 4), \ ((x).bytes[6] & 15) >= 10 ? 'a' + ((x).bytes[6] & 15) - 10 : '0' + ((x).bytes[6] & 15), \ ((x).bytes[7] >> 4) >= 10 ? 'a' + ((x).bytes[7] >> 4) - 10 : '0' + ((x).bytes[7] >> 4), \ ((x).bytes[7] & 15) >= 10 ? 'a' + ((x).bytes[7] & 15) - 10 : '0' + ((x).bytes[7] & 15), \ ((x).bytes[8] >> 4) >= 10 ? 'a' + ((x).bytes[8] >> 4) - 10 : '0' + ((x).bytes[8] >> 4), \ ((x).bytes[8] & 15) >= 10 ? 'a' + ((x).bytes[8] & 15) - 10 : '0' + ((x).bytes[8] & 15), \ ((x).bytes[9] >> 4) >= 10 ? 'a' + ((x).bytes[9] >> 4) - 10 : '0' + ((x).bytes[9] >> 4), \ ((x).bytes[9] & 15) >= 10 ? 'a' + ((x).bytes[9] & 15) - 10 : '0' + ((x).bytes[9] & 15), \ ((x).bytes[10] >> 4) >= 10 ? 'a' + ((x).bytes[10] >> 4) - 10 : '0' + ((x).bytes[10] >> 4), \ ((x).bytes[10] & 15) >= 10 ? 'a' + ((x).bytes[10] & 15) - 10 : '0' + ((x).bytes[10] & 15), \ ((x).bytes[11] >> 4) >= 10 ? 'a' + ((x).bytes[11] >> 4) - 10 : '0' + ((x).bytes[11] >> 4), \ ((x).bytes[11] & 15) >= 10 ? 'a' + ((x).bytes[11] & 15) - 10 : '0' + ((x).bytes[11] & 15), \ ((x).bytes[12] >> 4) >= 10 ? 'a' + ((x).bytes[12] >> 4) - 10 : '0' + ((x).bytes[12] >> 4), \ ((x).bytes[12] & 15) >= 10 ? 'a' + ((x).bytes[12] & 15) - 10 : '0' + ((x).bytes[12] & 15), \ ((x).bytes[13] >> 4) >= 10 ? 'a' + ((x).bytes[13] >> 4) - 10 : '0' + ((x).bytes[13] >> 4), \ ((x).bytes[13] & 15) >= 10 ? 'a' + ((x).bytes[13] & 15) - 10 : '0' + ((x).bytes[13] & 15), \ ((x).bytes[14] >> 4) >= 10 ? 'a' + ((x).bytes[14] >> 4) - 10 : '0' + ((x).bytes[14] >> 4), \ ((x).bytes[14] & 15) >= 10 ? 'a' + ((x).bytes[14] & 15) - 10 : '0' + ((x).bytes[14] & 15), \ ((x).bytes[15] >> 4) >= 10 ? 'a' + ((x).bytes[15] >> 4) - 10 : '0' + ((x).bytes[15] >> 4), \ ((x).bytes[15] & 15) >= 10 ? 'a' + ((x).bytes[15] & 15) - 10 : '0' + ((x).bytes[15] & 15), \ 0 }) _sd_pure_ static inline int sd_id128_equal(sd_id128_t a, sd_id128_t b) { return memcmp(&a, &b, 16) == 0; } _sd_pure_ static inline int sd_id128_is_null(sd_id128_t a) { return a.qwords[0] == 0 && a.qwords[1] == 0; } #define SD_ID128_NULL ((const sd_id128_t) { .qwords = { 0, 0 }}) _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-ipv4acd.h000066400000000000000000000037671265713322000174640ustar00rootroot00000000000000#ifndef foosdipv4acdfoo #define foosdipv4acdfoo /*** This file is part of systemd. Copyright (C) 2014 Axis Communications AB. All rights reserved. Copyright (C) 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-event.h" #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; enum { SD_IPV4ACD_EVENT_STOP = 0, SD_IPV4ACD_EVENT_BIND = 1, SD_IPV4ACD_EVENT_CONFLICT = 2, }; typedef struct sd_ipv4acd sd_ipv4acd; typedef void (*sd_ipv4acd_cb_t)(sd_ipv4acd *ll, int event, void *userdata); int sd_ipv4acd_detach_event(sd_ipv4acd *ll); int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int priority); int sd_ipv4acd_get_address(sd_ipv4acd *ll, struct in_addr *address); int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_cb_t cb, void *userdata); int sd_ipv4acd_set_mac(sd_ipv4acd *ll, const struct ether_addr *addr); int sd_ipv4acd_set_index(sd_ipv4acd *ll, int interface_index); int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address); int sd_ipv4acd_is_running(sd_ipv4acd *ll); int sd_ipv4acd_start(sd_ipv4acd *ll); int sd_ipv4acd_stop(sd_ipv4acd *ll); sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *ll); sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *ll); int sd_ipv4acd_new(sd_ipv4acd **ret); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4acd, sd_ipv4acd_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-ipv4ll.h000066400000000000000000000037561265713322000173420ustar00rootroot00000000000000#ifndef foosdipv4llfoo #define foosdipv4llfoo /*** This file is part of systemd. Copyright (C) 2014 Axis Communications AB. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-event.h" #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; enum { SD_IPV4LL_EVENT_STOP = 0, SD_IPV4LL_EVENT_BIND = 1, SD_IPV4LL_EVENT_CONFLICT = 2, }; typedef struct sd_ipv4ll sd_ipv4ll; typedef void (*sd_ipv4ll_cb_t)(sd_ipv4ll *ll, int event, void *userdata); int sd_ipv4ll_detach_event(sd_ipv4ll *ll); int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int priority); int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address); int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_cb_t cb, void *userdata); int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr); int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index); int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address); int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, unsigned seed); int sd_ipv4ll_is_running(sd_ipv4ll *ll); int sd_ipv4ll_start(sd_ipv4ll *ll); int sd_ipv4ll_stop(sd_ipv4ll *ll); sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll); sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll); int sd_ipv4ll_new (sd_ipv4ll **ret); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4ll, sd_ipv4ll_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-journal.h000066400000000000000000000166141265713322000175770ustar00rootroot00000000000000#ifndef foosdjournalhfoo #define foosdjournalhfoo /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-id128.h" #include "_sd-common.h" /* Journal APIs. See sd-journal(3) for more information. */ _SD_BEGIN_DECLARATIONS; /* Write to daemon */ int sd_journal_print(int priority, const char *format, ...) _sd_printf_(2, 3); int sd_journal_printv(int priority, const char *format, va_list ap) _sd_printf_(2, 0); int sd_journal_send(const char *format, ...) _sd_printf_(1, 0) _sd_sentinel_; int sd_journal_sendv(const struct iovec *iov, int n); int sd_journal_perror(const char *message); /* Used by the macros below. You probably don't want to call this directly. */ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) _sd_printf_(5, 6); int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) _sd_printf_(5, 0); int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) _sd_printf_(4, 0) _sd_sentinel_; int sd_journal_sendv_with_location(const char *file, const char *line, const char *func, const struct iovec *iov, int n); int sd_journal_perror_with_location(const char *file, const char *line, const char *func, const char *message); /* implicitly add code location to messages sent, if this is enabled */ #ifndef SD_JOURNAL_SUPPRESS_LOCATION #define sd_journal_print(priority, ...) sd_journal_print_with_location(priority, "CODE_FILE=" __FILE__, "CODE_LINE=" _SD_STRINGIFY(__LINE__), __func__, __VA_ARGS__) #define sd_journal_printv(priority, format, ap) sd_journal_printv_with_location(priority, "CODE_FILE=" __FILE__, "CODE_LINE=" _SD_STRINGIFY(__LINE__), __func__, format, ap) #define sd_journal_send(...) sd_journal_send_with_location("CODE_FILE=" __FILE__, "CODE_LINE=" _SD_STRINGIFY(__LINE__), __func__, __VA_ARGS__) #define sd_journal_sendv(iovec, n) sd_journal_sendv_with_location("CODE_FILE=" __FILE__, "CODE_LINE=" _SD_STRINGIFY(__LINE__), __func__, iovec, n) #define sd_journal_perror(message) sd_journal_perror_with_location("CODE_FILE=" __FILE__, "CODE_LINE=" _SD_STRINGIFY(__LINE__), __func__, message) #endif int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix); /* Browse journal stream */ typedef struct sd_journal sd_journal; /* Open flags */ enum { SD_JOURNAL_LOCAL_ONLY = 1, SD_JOURNAL_RUNTIME_ONLY = 2, SD_JOURNAL_SYSTEM = 4, SD_JOURNAL_CURRENT_USER = 8, SD_JOURNAL_SYSTEM_ONLY = SD_JOURNAL_SYSTEM, /* deprecated name */ }; /* Wakeup event types */ enum { SD_JOURNAL_NOP, SD_JOURNAL_APPEND, SD_JOURNAL_INVALIDATE }; int sd_journal_open(sd_journal **ret, int flags); int sd_journal_open_directory(sd_journal **ret, const char *path, int flags); int sd_journal_open_files(sd_journal **ret, const char **paths, int flags); int sd_journal_open_container(sd_journal **ret, const char *machine, int flags); void sd_journal_close(sd_journal *j); int sd_journal_previous(sd_journal *j); int sd_journal_next(sd_journal *j); int sd_journal_previous_skip(sd_journal *j, uint64_t skip); int sd_journal_next_skip(sd_journal *j, uint64_t skip); int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret); int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id); int sd_journal_set_data_threshold(sd_journal *j, size_t sz); int sd_journal_get_data_threshold(sd_journal *j, size_t *sz); int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *l); int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *l); void sd_journal_restart_data(sd_journal *j); int sd_journal_add_match(sd_journal *j, const void *data, size_t size); int sd_journal_add_disjunction(sd_journal *j); int sd_journal_add_conjunction(sd_journal *j); void sd_journal_flush_matches(sd_journal *j); int sd_journal_seek_head(sd_journal *j); int sd_journal_seek_tail(sd_journal *j); int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec); int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec); int sd_journal_seek_cursor(sd_journal *j, const char *cursor); int sd_journal_get_cursor(sd_journal *j, char **cursor); int sd_journal_test_cursor(sd_journal *j, const char *cursor); int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to); int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, const sd_id128_t boot_id, uint64_t *from, uint64_t *to); int sd_journal_get_usage(sd_journal *j, uint64_t *bytes); int sd_journal_query_unique(sd_journal *j, const char *field); int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l); void sd_journal_restart_unique(sd_journal *j); int sd_journal_enumerate_fields(sd_journal *j, const char **field); void sd_journal_restart_fields(sd_journal *j); int sd_journal_get_fd(sd_journal *j); int sd_journal_get_events(sd_journal *j); int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec); int sd_journal_process(sd_journal *j); int sd_journal_wait(sd_journal *j, uint64_t timeout_usec); int sd_journal_reliable_fd(sd_journal *j); int sd_journal_get_catalog(sd_journal *j, char **text); int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **text); int sd_journal_has_runtime_files(sd_journal *j); int sd_journal_has_persistent_files(sd_journal *j); /* The inverse condition avoids ambiguity of dangling 'else' after the macro */ #define SD_JOURNAL_FOREACH(j) \ if (sd_journal_seek_head(j) < 0) { } \ else while (sd_journal_next(j) > 0) /* The inverse condition avoids ambiguity of dangling 'else' after the macro */ #define SD_JOURNAL_FOREACH_BACKWARDS(j) \ if (sd_journal_seek_tail(j) < 0) { } \ else while (sd_journal_previous(j) > 0) /* Iterate through the data fields of the current journal entry */ #define SD_JOURNAL_FOREACH_DATA(j, data, l) \ for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; ) /* Iterate through the all known values of a specific field */ #define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \ for (sd_journal_restart_unique(j); sd_journal_enumerate_unique((j), &(data), &(l)) > 0; ) /* Iterate through all known field names */ #define SD_JOURNAL_FOREACH_FIELD(j, field) \ for (sd_journal_restart_fields(j); sd_journal_enumerate_fields((j), &(field)) > 0; ) _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_journal, sd_journal_close); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-lldp.h000066400000000000000000000063331265713322000170550ustar00rootroot00000000000000#ifndef foosdlldphfoo #define foosdlldphfoo /*** This file is part of systemd. Copyright (C) 2014 Tom Gundersen Copyright (C) 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-event.h" #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; enum { SD_LLDP_EVENT_UPDATE_INFO = 0, }; enum { SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE, SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE, SD_LLDP_DESTINATION_TYPE_NEAREST_CUSTOMER_BRIDGE, }; typedef struct sd_lldp sd_lldp; typedef struct sd_lldp_packet sd_lldp_packet; typedef void (*sd_lldp_cb_t)(sd_lldp *lldp, int event, void *userdata); int sd_lldp_new(int ifindex, const char *ifname, const struct ether_addr *mac, sd_lldp **ret); sd_lldp* sd_lldp_unref(sd_lldp *lldp); int sd_lldp_start(sd_lldp *lldp); int sd_lldp_stop(sd_lldp *lldp); int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int priority); int sd_lldp_detach_event(sd_lldp *lldp); int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_cb_t cb, void *userdata); int sd_lldp_save(sd_lldp *lldp, const char *file); int sd_lldp_packet_read_chassis_id(sd_lldp_packet *tlv, uint8_t *type, uint8_t **data, uint16_t *length); int sd_lldp_packet_read_port_id(sd_lldp_packet *tlv, uint8_t *type, uint8_t **data, uint16_t *length); int sd_lldp_packet_read_ttl(sd_lldp_packet *tlv, uint16_t *ttl); int sd_lldp_packet_read_system_name(sd_lldp_packet *tlv, char **data, uint16_t *length); int sd_lldp_packet_read_system_description(sd_lldp_packet *tlv, char **data, uint16_t *length); int sd_lldp_packet_read_system_capability(sd_lldp_packet *tlv, uint16_t *data); int sd_lldp_packet_read_port_description(sd_lldp_packet *tlv, char **data, uint16_t *length); /* IEEE 802.1 organizationally specific TLVs */ int sd_lldp_packet_read_port_vlan_id(sd_lldp_packet *tlv, uint16_t *id); int sd_lldp_packet_read_port_protocol_vlan_id(sd_lldp_packet *tlv, uint8_t *flags, uint16_t *id); int sd_lldp_packet_read_vlan_name(sd_lldp_packet *tlv, uint16_t *vlan_id, char **name, uint16_t *length); int sd_lldp_packet_read_management_vid(sd_lldp_packet *tlv, uint16_t *id); int sd_lldp_packet_read_link_aggregation(sd_lldp_packet *tlv, uint8_t *status, uint32_t *id); sd_lldp_packet *sd_lldp_packet_ref(sd_lldp_packet *tlv); sd_lldp_packet *sd_lldp_packet_unref(sd_lldp_packet *tlv); int sd_lldp_packet_get_destination_type(sd_lldp_packet *tlv, int *dest); int sd_lldp_get_packets(sd_lldp *lldp, sd_lldp_packet ***tlvs); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp, sd_lldp_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp_packet, sd_lldp_packet_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-login.h000066400000000000000000000223531265713322000172320ustar00rootroot00000000000000#ifndef foosdloginhfoo #define foosdloginhfoo /*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "_sd-common.h" /* * A few points: * * Instead of returning an empty string array or empty uid array, we * may return NULL. * * Free the data the library returns with libc free(). String arrays * are NULL terminated, and you need to free the array itself, in * addition to the strings contained. * * We return error codes as negative errno, kernel-style. On success, we * return 0 or positive. * * These functions access data in /proc, /sys/fs/cgroup, and /run. All * of these are virtual file systems; therefore, accesses are * relatively cheap. * * See sd-login(3) for more information. */ _SD_BEGIN_DECLARATIONS; /* Get session from PID. Note that 'shared' processes of a user are * not attached to a session, but only attached to a user. This will * return an error for system processes and 'shared' processes of a * user. */ int sd_pid_get_session(pid_t pid, char **session); /* Get UID of the owner of the session of the PID (or in case the * process is a 'shared' user process, the UID of that user is * returned). This will not return the UID of the process, but rather * the UID of the owner of the cgroup that the process is in. This will * return an error for system processes. */ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid); /* Get systemd non-slice unit (i.e. service) name from PID, for system * services. This will return an error for non-service processes. */ int sd_pid_get_unit(pid_t pid, char **unit); /* Get systemd non-slice unit (i.e. service) name from PID, for user * services. This will return an error for non-user-service * processes. */ int sd_pid_get_user_unit(pid_t pid, char **unit); /* Get slice name from PID. */ int sd_pid_get_slice(pid_t pid, char **slice); /* Get user slice name from PID. */ int sd_pid_get_user_slice(pid_t pid, char **slice); /* Get machine name from PID, for processes assigned to a VM or * container. This will return an error for non-machine processes. */ int sd_pid_get_machine_name(pid_t pid, char **machine); /* Get the control group from a PID, relative to the root of the * hierarchy. */ int sd_pid_get_cgroup(pid_t pid, char **cgroup); /* Similar to sd_pid_get_session(), but retrieves data about the peer * of a connected AF_UNIX socket */ int sd_peer_get_session(int fd, char **session); /* Similar to sd_pid_get_owner_uid(), but retrieves data about the peer of * a connected AF_UNIX socket */ int sd_peer_get_owner_uid(int fd, uid_t *uid); /* Similar to sd_pid_get_unit(), but retrieves data about the peer of * a connected AF_UNIX socket */ int sd_peer_get_unit(int fd, char **unit); /* Similar to sd_pid_get_user_unit(), but retrieves data about the peer of * a connected AF_UNIX socket */ int sd_peer_get_user_unit(int fd, char **unit); /* Similar to sd_pid_get_slice(), but retrieves data about the peer of * a connected AF_UNIX socket */ int sd_peer_get_slice(int fd, char **slice); /* Similar to sd_pid_get_user_slice(), but retrieves data about the peer of * a connected AF_UNIX socket */ int sd_peer_get_user_slice(int fd, char **slice); /* Similar to sd_pid_get_machine_name(), but retrieves data about the * peer of a a connected AF_UNIX socket */ int sd_peer_get_machine_name(int fd, char **machine); /* Similar to sd_pid_get_cgroup(), but retrieves data about the peer * of a connected AF_UNIX socket. */ int sd_peer_get_cgroup(pid_t pid, char **cgroup); /* Get state from UID. Possible states: offline, lingering, online, active, closing */ int sd_uid_get_state(uid_t uid, char **state); /* Return primary session of user, if there is any */ int sd_uid_get_display(uid_t uid, char **session); /* Return 1 if UID has session on seat. If require_active is true, this will * look for active sessions only. */ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat); /* Return sessions of user. If require_active is true, this will look for * active sessions only. Returns the number of sessions. * If sessions is NULL, this will just return the number of sessions. */ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions); /* Return seats of user is on. If require_active is true, this will look for * active seats only. Returns the number of seats. * If seats is NULL, this will just return the number of seats. */ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats); /* Return 1 if the session is active. */ int sd_session_is_active(const char *session); /* Return 1 if the session is remote. */ int sd_session_is_remote(const char *session); /* Get state from session. Possible states: online, active, closing. * This function is a more generic version of sd_session_is_active(). */ int sd_session_get_state(const char *session, char **state); /* Determine user ID of session */ int sd_session_get_uid(const char *session, uid_t *uid); /* Determine seat of session */ int sd_session_get_seat(const char *session, char **seat); /* Determine the (PAM) service name this session was registered by. */ int sd_session_get_service(const char *session, char **service); /* Determine the type of this session, i.e. one of "tty", "x11", "wayland", "mir" or "unspecified". */ int sd_session_get_type(const char *session, char **type); /* Determine the class of this session, i.e. one of "user", "greeter" or "lock-screen". */ int sd_session_get_class(const char *session, char **clazz); /* Determine the desktop brand of this session, i.e. something like "GNOME", "KDE" or "systemd-console". */ int sd_session_get_desktop(const char *session, char **desktop); /* Determine the X11 display of this session. */ int sd_session_get_display(const char *session, char **display); /* Determine the remote host of this session. */ int sd_session_get_remote_host(const char *session, char **remote_host); /* Determine the remote user of this session (if provided by PAM). */ int sd_session_get_remote_user(const char *session, char **remote_user); /* Determine the TTY of this session. */ int sd_session_get_tty(const char *session, char **display); /* Determine the VT number of this session. */ int sd_session_get_vt(const char *session, unsigned *vtnr); /* Return active session and user of seat */ int sd_seat_get_active(const char *seat, char **session, uid_t *uid); /* Return sessions and users on seat. Returns number of sessions. * If sessions is NULL, this returns only the number of sessions. */ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids); /* Return whether the seat is multi-session capable */ int sd_seat_can_multi_session(const char *seat); /* Return whether the seat is TTY capable, i.e. suitable for showing console UIs */ int sd_seat_can_tty(const char *seat); /* Return whether the seat is graphics capable, i.e. suitable for showing graphical UIs */ int sd_seat_can_graphical(const char *seat); /* Return the class of machine */ int sd_machine_get_class(const char *machine, char **clazz); /* Return the list if host-side network interface indices of a machine */ int sd_machine_get_ifindices(const char *machine, int **ifindices); /* Get all seats, store in *seats. Returns the number of seats. If * seats is NULL, this only returns the number of seats. */ int sd_get_seats(char ***seats); /* Get all sessions, store in *sessions. Returns the number of * sessions. If sessions is NULL, this only returns the number of sessions. */ int sd_get_sessions(char ***sessions); /* Get all logged in users, store in *users. Returns the number of * users. If users is NULL, this only returns the number of users. */ int sd_get_uids(uid_t **users); /* Get all running virtual machines/containers */ int sd_get_machine_names(char ***machines); /* Monitor object */ typedef struct sd_login_monitor sd_login_monitor; /* Create a new monitor. Category must be NULL, "seat", "session", * "uid", or "machine" to get monitor events for the specific category * (or all). */ int sd_login_monitor_new(const char *category, sd_login_monitor** ret); /* Destroys the passed monitor. Returns NULL. */ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m); /* Flushes the monitor */ int sd_login_monitor_flush(sd_login_monitor *m); /* Get FD from monitor */ int sd_login_monitor_get_fd(sd_login_monitor *m); /* Get poll() mask to monitor */ int sd_login_monitor_get_events(sd_login_monitor *m); /* Get timeout for poll(), as usec value relative to CLOCK_MONOTONIC's epoch */ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_login_monitor, sd_login_monitor_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-messages.h000066400000000000000000000120501265713322000177220ustar00rootroot00000000000000#ifndef foosdmessageshfoo #define foosdmessageshfoo /*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-id128.h" #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; /* Hey! If you add a new message here, you *must* also update the * message catalog with an appropriate explanation */ /* And if you add a new ID here, make sure to generate a random one * with journalctl --new-id128. Do not use any other IDs, and do not * count them up manually. */ #define SD_MESSAGE_JOURNAL_START SD_ID128_MAKE(f7,73,79,a8,49,0b,40,8b,be,5f,69,40,50,5a,77,7b) #define SD_MESSAGE_JOURNAL_STOP SD_ID128_MAKE(d9,3f,b3,c9,c2,4d,45,1a,97,ce,a6,15,ce,59,c0,0b) #define SD_MESSAGE_JOURNAL_DROPPED SD_ID128_MAKE(a5,96,d6,fe,7b,fa,49,94,82,8e,72,30,9e,95,d6,1e) #define SD_MESSAGE_JOURNAL_MISSED SD_ID128_MAKE(e9,bf,28,e6,e8,34,48,1b,b6,f4,8f,54,8a,d1,36,06) #define SD_MESSAGE_JOURNAL_USAGE SD_ID128_MAKE(ec,38,7f,57,7b,84,4b,8f,a9,48,f3,3c,ad,9a,75,e6) #define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) #define SD_MESSAGE_SESSION_START SD_ID128_MAKE(8d,45,62,0c,1a,43,48,db,b1,74,10,da,57,c6,0c,66) #define SD_MESSAGE_SESSION_STOP SD_ID128_MAKE(33,54,93,94,24,b4,45,6d,98,02,ca,83,33,ed,42,4a) #define SD_MESSAGE_SEAT_START SD_ID128_MAKE(fc,be,fc,5d,a2,3d,42,80,93,f9,7c,82,a9,29,0f,7b) #define SD_MESSAGE_SEAT_STOP SD_ID128_MAKE(e7,85,2b,fe,46,78,4e,d0,ac,cd,e0,4b,c8,64,c2,d5) #define SD_MESSAGE_MACHINE_START SD_ID128_MAKE(24,d8,d4,45,25,73,40,24,96,06,83,81,a6,31,2d,f2) #define SD_MESSAGE_MACHINE_STOP SD_ID128_MAKE(58,43,2b,d3,ba,ce,47,7c,b5,14,b5,63,81,b8,a7,58) #define SD_MESSAGE_TIME_CHANGE SD_ID128_MAKE(c7,a7,87,07,9b,35,4e,aa,a9,e7,7b,37,18,93,cd,27) #define SD_MESSAGE_TIMEZONE_CHANGE SD_ID128_MAKE(45,f8,2f,4a,ef,7a,4b,bf,94,2c,e8,61,d1,f2,09,90) #define SD_MESSAGE_STARTUP_FINISHED SD_ID128_MAKE(b0,7a,24,9c,d0,24,41,4a,82,dd,00,cd,18,13,78,ff) #define SD_MESSAGE_SLEEP_START SD_ID128_MAKE(6b,bd,95,ee,97,79,41,e4,97,c4,8b,e2,7c,25,41,28) #define SD_MESSAGE_SLEEP_STOP SD_ID128_MAKE(88,11,e6,df,2a,8e,40,f5,8a,94,ce,a2,6f,8e,bf,14) #define SD_MESSAGE_SHUTDOWN SD_ID128_MAKE(98,26,88,66,d1,d5,4a,49,9c,4e,98,92,1d,93,bc,40) #define SD_MESSAGE_UNIT_STARTING SD_ID128_MAKE(7d,49,58,e8,42,da,4a,75,8f,6c,1c,dc,7b,36,dc,c5) #define SD_MESSAGE_UNIT_STARTED SD_ID128_MAKE(39,f5,34,79,d3,a0,45,ac,8e,11,78,62,48,23,1f,bf) #define SD_MESSAGE_UNIT_STOPPING SD_ID128_MAKE(de,5b,42,6a,63,be,47,a7,b6,ac,3e,aa,c8,2e,2f,6f) #define SD_MESSAGE_UNIT_STOPPED SD_ID128_MAKE(9d,1a,aa,27,d6,01,40,bd,96,36,54,38,aa,d2,02,86) #define SD_MESSAGE_UNIT_FAILED SD_ID128_MAKE(be,02,cf,68,55,d2,42,8b,a4,0d,f7,e9,d0,22,f0,3d) #define SD_MESSAGE_UNIT_RELOADING SD_ID128_MAKE(d3,4d,03,7f,ff,18,47,e6,ae,66,9a,37,0e,69,47,25) #define SD_MESSAGE_UNIT_RELOADED SD_ID128_MAKE(7b,05,eb,c6,68,38,42,22,ba,a8,88,11,79,cf,da,54) #define SD_MESSAGE_SPAWN_FAILED SD_ID128_MAKE(64,12,57,65,1c,1b,4e,c9,a8,62,4d,7a,40,a9,e1,e7) #define SD_MESSAGE_FORWARD_SYSLOG_MISSED SD_ID128_MAKE(00,27,22,9c,a0,64,41,81,a7,6c,4e,92,45,8a,fa,2e) #define SD_MESSAGE_OVERMOUNTING SD_ID128_MAKE(1d,ee,03,69,c7,fc,47,36,b7,09,9b,38,ec,b4,6e,e7) #define SD_MESSAGE_LID_OPENED SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,6f) #define SD_MESSAGE_LID_CLOSED SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,70) #define SD_MESSAGE_SYSTEM_DOCKED SD_ID128_MAKE(f5,f4,16,b8,62,07,4b,28,92,7a,48,c3,ba,7d,51,ff) #define SD_MESSAGE_SYSTEM_UNDOCKED SD_ID128_MAKE(51,e1,71,bd,58,52,48,56,81,10,14,4c,51,7c,ca,53) #define SD_MESSAGE_POWER_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71) #define SD_MESSAGE_SUSPEND_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,72) #define SD_MESSAGE_HIBERNATE_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,73) #define SD_MESSAGE_INVALID_CONFIGURATION SD_ID128_MAKE(c7,72,d2,4e,9a,88,4c,be,b9,ea,12,62,5c,30,6c,01) #define SD_MESSAGE_BOOTCHART SD_ID128_MAKE(9f,26,aa,56,2c,f4,40,c2,b1,6c,77,3d,04,79,b5,18) #define SD_MESSAGE_DNSSEC_FAILURE SD_ID128_MAKE(16,75,d7,f1,72,17,40,98,b1,10,8b,f8,c7,dc,8f,5d) #define SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED SD_ID128_MAKE(4d,44,08,cf,d0,d1,44,85,91,84,d1,e6,5d,7c,8a,65) #define SD_MESSAGE_DNSSEC_DOWNGRADE SD_ID128_MAKE(36,db,2d,fa,5a,90,45,e1,bd,4a,f5,f9,3e,1c,f0,57) _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-ndisc.h000066400000000000000000000061431265713322000172210ustar00rootroot00000000000000#ifndef foosdndiscfoo #define foosdndiscfoo /*** This file is part of systemd. Copyright (C) 2014 Intel Corporation. All rights reserved. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-event.h" #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; enum { SD_NDISC_EVENT_STOP = 0, SD_NDISC_EVENT_TIMEOUT = 1, }; typedef struct sd_ndisc sd_ndisc; typedef void(*sd_ndisc_router_callback_t)(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata); typedef void(*sd_ndisc_prefix_onlink_callback_t)(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen, unsigned lifetime, void *userdata); typedef void(*sd_ndisc_prefix_autonomous_callback_t)(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen, unsigned lifetime_prefered, unsigned lifetime_valid, void *userdata); typedef void(*sd_ndisc_callback_t)(sd_ndisc *nd, int event, void *userdata); int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_router_callback_t rcb, sd_ndisc_prefix_onlink_callback_t plcb, sd_ndisc_prefix_autonomous_callback_t pacb, sd_ndisc_callback_t cb, void *userdata); int sd_ndisc_set_index(sd_ndisc *nd, int interface_index); int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr); int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int priority); int sd_ndisc_detach_event(sd_ndisc *nd); sd_event *sd_ndisc_get_event(sd_ndisc *nd); sd_ndisc *sd_ndisc_ref(sd_ndisc *nd); sd_ndisc *sd_ndisc_unref(sd_ndisc *nd); int sd_ndisc_new(sd_ndisc **ret); int sd_ndisc_get_mtu(sd_ndisc *nd, uint32_t *mtu); int sd_ndisc_stop(sd_ndisc *nd); int sd_ndisc_router_discovery_start(sd_ndisc *nd); #define SD_NDISC_ADDRESS_FORMAT_STR "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" #define SD_NDISC_ADDRESS_FORMAT_VAL(address) \ be16toh((address).s6_addr16[0]), \ be16toh((address).s6_addr16[1]), \ be16toh((address).s6_addr16[2]), \ be16toh((address).s6_addr16[3]), \ be16toh((address).s6_addr16[4]), \ be16toh((address).s6_addr16[5]), \ be16toh((address).s6_addr16[6]), \ be16toh((address).s6_addr16[7]) _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc, sd_ndisc_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-netlink.h000066400000000000000000000212331265713322000175620ustar00rootroot00000000000000#ifndef foosdnetlinkhfoo #define foosdnetlinkhfoo /*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-event.h" #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; typedef struct sd_netlink sd_netlink; typedef struct sd_netlink_message sd_netlink_message; /* callback */ typedef int (*sd_netlink_message_handler_t)(sd_netlink *nl, sd_netlink_message *m, void *userdata); /* bus */ int sd_netlink_new_from_netlink(sd_netlink **nl, int fd); int sd_netlink_open(sd_netlink **nl); int sd_netlink_open_fd(sd_netlink **nl, int fd); int sd_netlink_inc_rcvbuf(const sd_netlink *const rtnl, const int size); sd_netlink *sd_netlink_ref(sd_netlink *nl); sd_netlink *sd_netlink_unref(sd_netlink *nl); int sd_netlink_send(sd_netlink *nl, sd_netlink_message *message, uint32_t *serial); int sd_netlink_call_async(sd_netlink *nl, sd_netlink_message *message, sd_netlink_message_handler_t callback, void *userdata, uint64_t usec, uint32_t *serial); int sd_netlink_call_async_cancel(sd_netlink *nl, uint32_t serial); int sd_netlink_call(sd_netlink *nl, sd_netlink_message *message, uint64_t timeout, sd_netlink_message **reply); int sd_netlink_get_events(sd_netlink *nl); int sd_netlink_get_timeout(sd_netlink *nl, uint64_t *timeout); int sd_netlink_process(sd_netlink *nl, sd_netlink_message **ret); int sd_netlink_wait(sd_netlink *nl, uint64_t timeout); int sd_netlink_add_match(sd_netlink *nl, uint16_t match, sd_netlink_message_handler_t c, void *userdata); int sd_netlink_remove_match(sd_netlink *nl, uint16_t match, sd_netlink_message_handler_t c, void *userdata); int sd_netlink_attach_event(sd_netlink *nl, sd_event *e, int priority); int sd_netlink_detach_event(sd_netlink *nl); int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data); int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type); int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uint8_t data); int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, uint16_t data); int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, uint32_t data); int sd_netlink_message_append_data(sd_netlink_message *m, unsigned short type, const void *data, size_t len); int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data); int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short type, const struct in6_addr *data); int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short type, const struct ether_addr *data); int sd_netlink_message_append_cache_info(sd_netlink_message *m, unsigned short type, const struct ifa_cacheinfo *info); int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type); int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned short type, const char *key); int sd_netlink_message_close_container(sd_netlink_message *m); int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data); int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8_t *data); int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data); int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data); int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short type, struct ether_addr *data); int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short type, struct ifa_cacheinfo *info); int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data); int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data); int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type); int sd_netlink_message_exit_container(sd_netlink_message *m); int sd_netlink_message_rewind(sd_netlink_message *m); sd_netlink_message *sd_netlink_message_next(sd_netlink_message *m); sd_netlink_message *sd_netlink_message_ref(sd_netlink_message *m); sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m); int sd_netlink_message_request_dump(sd_netlink_message *m, int dump); int sd_netlink_message_is_error(sd_netlink_message *m); int sd_netlink_message_get_errno(sd_netlink_message *m); int sd_netlink_message_get_type(sd_netlink_message *m, uint16_t *type); int sd_netlink_message_set_flags(sd_netlink_message *m, uint16_t flags); int sd_netlink_message_is_broadcast(sd_netlink_message *m); /* rtnl */ int sd_rtnl_message_new_link(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index); int sd_rtnl_message_new_addr_update(sd_netlink *nl, sd_netlink_message **ret, int index, int family); int sd_rtnl_message_new_addr(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int family); int sd_rtnl_message_new_route(sd_netlink *nl, sd_netlink_message **ret, uint16_t nlmsg_type, int rtm_family, unsigned char rtm_protocol); int sd_rtnl_message_new_neigh(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int nda_family); int sd_rtnl_message_get_family(sd_netlink_message *m, int *family); int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen); int sd_rtnl_message_addr_set_scope(sd_netlink_message *m, unsigned char scope); int sd_rtnl_message_addr_set_flags(sd_netlink_message *m, unsigned char flags); int sd_rtnl_message_addr_get_family(sd_netlink_message *m, int *family); int sd_rtnl_message_addr_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen); int sd_rtnl_message_addr_get_scope(sd_netlink_message *m, unsigned char *scope); int sd_rtnl_message_addr_get_flags(sd_netlink_message *m, unsigned char *flags); int sd_rtnl_message_addr_get_ifindex(sd_netlink_message *m, int *ifindex); int sd_rtnl_message_link_set_flags(sd_netlink_message *m, unsigned flags, unsigned change); int sd_rtnl_message_link_set_type(sd_netlink_message *m, unsigned type); int sd_rtnl_message_link_set_family(sd_netlink_message *m, unsigned family); int sd_rtnl_message_link_get_ifindex(sd_netlink_message *m, int *ifindex); int sd_rtnl_message_link_get_flags(sd_netlink_message *m, unsigned *flags); int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned *type); int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char prefixlen); int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char prefixlen); int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope); int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags); int sd_rtnl_message_route_get_flags(sd_netlink_message *m, unsigned *flags); int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family); int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol); int sd_rtnl_message_route_get_scope(sd_netlink_message *m, unsigned char *scope); int sd_rtnl_message_route_get_tos(sd_netlink_message *m, unsigned char *tos); int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table); int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char *dst_len); int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len); int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags); int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state); int sd_rtnl_message_neigh_get_family(sd_netlink_message *m, int *family); int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message *m, int *family); int sd_rtnl_message_neigh_get_state(sd_netlink_message *m, uint16_t *state); int sd_rtnl_message_neigh_get_flags(sd_netlink_message *m, uint8_t *flags); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink, sd_netlink_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink_message, sd_netlink_message_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-network.h000066400000000000000000000143211265713322000176070ustar00rootroot00000000000000#ifndef foosdnetworkhfoo #define foosdnetworkhfoo /*** This file is part of systemd. Copyright 2011 Lennart Poettering Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "_sd-common.h" /* * A few points: * * Instead of returning an empty string array or empty integer array, we * may return NULL. * * Free the data the library returns with libc free(). String arrays * are NULL terminated, and you need to free the array itself in * addition to the strings contained. * * We return error codes as negative errno, kernel-style. On success, we * return 0 or positive. * * These functions access data in /run. This is a virtual file system; * therefore, accesses are relatively cheap. * * See sd-network(3) for more information. */ _SD_BEGIN_DECLARATIONS; /* Get overall operational state * Possible states: down, up, dormant, carrier, degraded, routable * Possible return codes: * -ENODATA: networkd is not aware of any links */ int sd_network_get_operational_state(char **state); /* Get DNS entries for all links. These are string representations of * IP addresses */ int sd_network_get_dns(char ***dns); /* Get NTP entries for all links. These are domain names or string * representations of IP addresses */ int sd_network_get_ntp(char ***ntp); /* Get the search domains for all links. */ int sd_network_get_search_domains(char ***domains); /* Get the search domains for all links. */ int sd_network_get_route_domains(char ***domains); /* Get setup state from ifindex. * Possible states: * pending: udev is still processing the link, we don't yet know if we will manage it * failed: networkd failed to manage the link * configuring: in the process of retrieving configuration or configuring the link * configured: link configured successfully * unmanaged: networkd is not handling the link * linger: the link is gone, but has not yet been dropped by networkd * Possible return codes: * -ENODATA: networkd is not aware of the link */ int sd_network_link_get_setup_state(int ifindex, char **state); /* Get operational state from ifindex. * Possible states: * off: the device is powered down * no-carrier: the device is powered up, but it does not yet have a carrier * dormant: the device has a carrier, but is not yet ready for normal traffic * carrier: the link has a carrier * degraded: the link has carrier and addresses valid on the local link configured * routable: the link has carrier and routable address configured * Possible return codes: * -ENODATA: networkd is not aware of the link */ int sd_network_link_get_operational_state(int ifindex, char **state); /* Get path to .network file applied to link */ int sd_network_link_get_network_file(int ifindex, char **filename); /* Get DNS entries for a given link. These are string representations of * IP addresses */ int sd_network_link_get_dns(int ifindex, char ***addr); /* Get NTP entries for a given link. These are domain names or string * representations of IP addresses */ int sd_network_link_get_ntp(int ifindex, char ***addr); /* Indicates whether or not LLMNR should be enabled for the link * Possible levels of support: yes, no, resolve * Possible return codes: * -ENODATA: networkd is not aware of the link */ int sd_network_link_get_llmnr(int ifindex, char **llmnr); /* Indicates whether or not MulticastDNS should be enabled for the * link. * Possible levels of support: yes, no, resolve * Possible return codes: * -ENODATA: networkd is not aware of the link */ int sd_network_link_get_mdns(int ifindex, char **mdns); /* Indicates whether or not DNSSEC should be enabled for the link * Possible levels of support: yes, no, allow-downgrade * Possible return codes: * -ENODATA: networkd is not aware of the link */ int sd_network_link_get_dnssec(int ifindex, char **dnssec); /* Returns the list of per-interface DNSSEC negative trust anchors * Possible return codes: * -ENODATA: networkd is not aware of the link, or has no such data */ int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta); int sd_network_link_get_lldp(int ifindex, char **lldp); /* Get the search DNS domain names for a given link. */ int sd_network_link_get_search_domains(int ifindex, char ***domains); /* Get the route DNS domain names for a given link. */ int sd_network_link_get_route_domains(int ifindex, char ***domains); /* Get the CARRIERS to which current link is bound to. */ int sd_network_link_get_carrier_bound_to(int ifindex, char ***carriers); /* Get the CARRIERS that are bound to current link. */ int sd_network_link_get_carrier_bound_by(int ifindex, char ***carriers); /* Get the timezone that was learnt on a specific link. */ int sd_network_link_get_timezone(int ifindex, char **timezone); /* Monitor object */ typedef struct sd_network_monitor sd_network_monitor; /* Create a new monitor. Category must be NULL, "links" or "leases". */ int sd_network_monitor_new(sd_network_monitor **ret, const char *category); /* Destroys the passed monitor. Returns NULL. */ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m); /* Flushes the monitor */ int sd_network_monitor_flush(sd_network_monitor *m); /* Get FD from monitor */ int sd_network_monitor_get_fd(sd_network_monitor *m); /* Get poll() mask to monitor */ int sd_network_monitor_get_events(sd_network_monitor *m); /* Get timeout for poll(), as usec value relative to CLOCK_MONOTONIC's epoch */ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_network_monitor, sd_network_monitor_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-path.h000066400000000000000000000052661265713322000170620ustar00rootroot00000000000000#ifndef foosdpathhfoo #define foosdpathhfoo /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; enum { /* Temporary files */ SD_PATH_TEMPORARY = 0x0ULL, SD_PATH_TEMPORARY_LARGE, /* Vendor supplied data */ SD_PATH_SYSTEM_BINARIES, SD_PATH_SYSTEM_INCLUDE, SD_PATH_SYSTEM_LIBRARY_PRIVATE, SD_PATH_SYSTEM_LIBRARY_ARCH, SD_PATH_SYSTEM_SHARED, SD_PATH_SYSTEM_CONFIGURATION_FACTORY, SD_PATH_SYSTEM_STATE_FACTORY, /* System configuration, runtime, state, ... */ SD_PATH_SYSTEM_CONFIGURATION, SD_PATH_SYSTEM_RUNTIME, SD_PATH_SYSTEM_RUNTIME_LOGS, SD_PATH_SYSTEM_STATE_PRIVATE, SD_PATH_SYSTEM_STATE_LOGS, SD_PATH_SYSTEM_STATE_CACHE, SD_PATH_SYSTEM_STATE_SPOOL, /* Vendor supplied data */ SD_PATH_USER_BINARIES, SD_PATH_USER_LIBRARY_PRIVATE, SD_PATH_USER_LIBRARY_ARCH, SD_PATH_USER_SHARED, /* User configuration, state, runtime ... */ SD_PATH_USER_CONFIGURATION, /* takes both actual configuration (like /etc) and state (like /var/lib) */ SD_PATH_USER_RUNTIME, SD_PATH_USER_STATE_CACHE, /* User resources */ SD_PATH_USER, /* $HOME itself */ SD_PATH_USER_DOCUMENTS, SD_PATH_USER_MUSIC, SD_PATH_USER_PICTURES, SD_PATH_USER_VIDEOS, SD_PATH_USER_DOWNLOAD, SD_PATH_USER_PUBLIC, SD_PATH_USER_TEMPLATES, SD_PATH_USER_DESKTOP, /* Search paths */ SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_ARCH, SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_CONFIGURATION_FACTORY, SD_PATH_SEARCH_STATE_FACTORY, SD_PATH_SEARCH_CONFIGURATION, _SD_PATH_MAX, }; int sd_path_home(uint64_t type, const char *suffix, char **path); int sd_path_search(uint64_t type, const char *suffix, char ***paths); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-resolve.h000066400000000000000000000107651265713322000176050ustar00rootroot00000000000000#ifndef foosdresolvehfoo #define foosdresolvehfoo /*** This file is part of systemd. Copyright 2005-2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-event.h" #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; /* An opaque sd-resolve session structure */ typedef struct sd_resolve sd_resolve; /* An opaque sd-resolve query structure */ typedef struct sd_resolve_query sd_resolve_query; /* A callback on completion */ typedef int (*sd_resolve_getaddrinfo_handler_t)(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata); typedef int (*sd_resolve_getnameinfo_handler_t)(sd_resolve_query *q, int ret, const char *host, const char *serv, void *userdata); enum { SD_RESOLVE_GET_HOST = UINT64_C(1), SD_RESOLVE_GET_SERVICE = UINT64_C(2), SD_RESOLVE_GET_BOTH = UINT64_C(3), }; int sd_resolve_default(sd_resolve **ret); /* Allocate a new sd-resolve session. */ int sd_resolve_new(sd_resolve **ret); /* Free a sd-resolve session. This destroys all attached * sd_resolve_query objects automatically. */ sd_resolve* sd_resolve_unref(sd_resolve *resolve); sd_resolve* sd_resolve_ref(sd_resolve *resolve); /* Return the UNIX file descriptor to poll() for events on. Use this * function to integrate sd-resolve with your custom main loop. */ int sd_resolve_get_fd(sd_resolve *resolve); /* Return the poll() events (a combination of flags like POLLIN, * POLLOUT, ...) to check for. */ int sd_resolve_get_events(sd_resolve *resolve); /* Return the poll() timeout to pass. Returns (uint64_t) -1 as * timeout if no timeout is needed. */ int sd_resolve_get_timeout(sd_resolve *resolve, uint64_t *timeout_usec); /* Process pending responses. After this function is called, you can * get the next completed query object(s) using * sd_resolve_get_next(). */ int sd_resolve_process(sd_resolve *resolve); /* Wait for a resolve event to complete. */ int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec); int sd_resolve_get_tid(sd_resolve *resolve, pid_t *tid); int sd_resolve_attach_event(sd_resolve *resolve, sd_event *e, int priority); int sd_resolve_detach_event(sd_resolve *resolve); sd_event *sd_resolve_get_event(sd_resolve *resolve); /* Issue a name-to-address query on the specified session. The * arguments are compatible with those of libc's * getaddrinfo(3). The function returns a new query object. When the * query is completed, you may retrieve the results using * sd_resolve_getaddrinfo_done(). */ int sd_resolve_getaddrinfo(sd_resolve *resolve, sd_resolve_query **q, const char *node, const char *service, const struct addrinfo *hints, sd_resolve_getaddrinfo_handler_t callback, void *userdata); /* Issue an address-to-name query on the specified session. The * arguments are compatible with those of libc's * getnameinfo(3). The function returns a new query object. When the * query is completed, you may retrieve the results using * sd_resolve_getnameinfo_done(). Set gethost (resp. getserv) to non-zero * if you want to query the hostname (resp. the service name). */ int sd_resolve_getnameinfo(sd_resolve *resolve, sd_resolve_query **q, const struct sockaddr *sa, socklen_t salen, int flags, uint64_t get, sd_resolve_getnameinfo_handler_t callback, void *userdata); sd_resolve_query *sd_resolve_query_ref(sd_resolve_query* q); sd_resolve_query *sd_resolve_query_unref(sd_resolve_query* q); /* Returns non-zero when the query operation specified by q has been completed. */ int sd_resolve_query_is_done(sd_resolve_query*q); void *sd_resolve_query_get_userdata(sd_resolve_query *q); void *sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata); sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_resolve, sd_resolve_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_resolve_query, sd_resolve_query_unref); _SD_END_DECLARATIONS; #endif systemd-229/src/systemd/sd-utf8.h000066400000000000000000000016741265713322000170130ustar00rootroot00000000000000#ifndef foosdutf8hfoo #define foosdutf8hfoo /*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; _sd_pure_ const char *sd_utf8_is_valid(const char *s); _sd_pure_ const char *sd_ascii_is_valid(const char *s); _SD_END_DECLARATIONS; #endif systemd-229/src/sysusers/000077500000000000000000000000001265713322000155505ustar00rootroot00000000000000systemd-229/src/sysusers/Makefile000077700000000000000000000000001265713322000210562../Makefileustar00rootroot00000000000000systemd-229/src/sysusers/sysusers.c000066400000000000000000001667171265713322000176360ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "alloc-util.h" #include "conf-files.h" #include "copy.h" #include "def.h" #include "fd-util.h" #include "fileio-label.h" #include "formats-util.h" #include "hashmap.h" #include "path-util.h" #include "selinux-util.h" #include "smack-util.h" #include "specifier.h" #include "string-util.h" #include "strv.h" #include "uid-range.h" #include "user-util.h" #include "utf8.h" #include "util.h" typedef enum ItemType { ADD_USER = 'u', ADD_GROUP = 'g', ADD_MEMBER = 'm', ADD_RANGE = 'r', } ItemType; typedef struct Item { ItemType type; char *name; char *uid_path; char *gid_path; char *description; char *home; gid_t gid; uid_t uid; bool gid_set:1; bool uid_set:1; bool todo_user:1; bool todo_group:1; } Item; static char *arg_root = NULL; static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysusers.d"); static Hashmap *users = NULL, *groups = NULL; static Hashmap *todo_uids = NULL, *todo_gids = NULL; static Hashmap *members = NULL; static Hashmap *database_uid = NULL, *database_user = NULL; static Hashmap *database_gid = NULL, *database_group = NULL; static uid_t search_uid = UID_INVALID; static UidRange *uid_range = NULL; static unsigned n_uid_range = 0; static int load_user_database(void) { _cleanup_fclose_ FILE *f = NULL; const char *passwd_path; struct passwd *pw; int r; passwd_path = prefix_roota(arg_root, "/etc/passwd"); f = fopen(passwd_path, "re"); if (!f) return errno == ENOENT ? 0 : -errno; r = hashmap_ensure_allocated(&database_user, &string_hash_ops); if (r < 0) return r; r = hashmap_ensure_allocated(&database_uid, NULL); if (r < 0) return r; errno = 0; while ((pw = fgetpwent(f))) { char *n; int k, q; n = strdup(pw->pw_name); if (!n) return -ENOMEM; k = hashmap_put(database_user, n, UID_TO_PTR(pw->pw_uid)); if (k < 0 && k != -EEXIST) { free(n); return k; } q = hashmap_put(database_uid, UID_TO_PTR(pw->pw_uid), n); if (q < 0 && q != -EEXIST) { if (k < 0) free(n); return q; } if (q < 0 && k < 0) free(n); errno = 0; } if (!IN_SET(errno, 0, ENOENT)) return -errno; return 0; } static int load_group_database(void) { _cleanup_fclose_ FILE *f = NULL; const char *group_path; struct group *gr; int r; group_path = prefix_roota(arg_root, "/etc/group"); f = fopen(group_path, "re"); if (!f) return errno == ENOENT ? 0 : -errno; r = hashmap_ensure_allocated(&database_group, &string_hash_ops); if (r < 0) return r; r = hashmap_ensure_allocated(&database_gid, NULL); if (r < 0) return r; errno = 0; while ((gr = fgetgrent(f))) { char *n; int k, q; n = strdup(gr->gr_name); if (!n) return -ENOMEM; k = hashmap_put(database_group, n, GID_TO_PTR(gr->gr_gid)); if (k < 0 && k != -EEXIST) { free(n); return k; } q = hashmap_put(database_gid, GID_TO_PTR(gr->gr_gid), n); if (q < 0 && q != -EEXIST) { if (k < 0) free(n); return q; } if (q < 0 && k < 0) free(n); errno = 0; } if (!IN_SET(errno, 0, ENOENT)) return -errno; return 0; } static int make_backup(const char *target, const char *x) { _cleanup_close_ int src = -1; _cleanup_fclose_ FILE *dst = NULL; char *backup, *temp; struct timespec ts[2]; struct stat st; int r; src = open(x, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (src < 0) { if (errno == ENOENT) /* No backup necessary... */ return 0; return -errno; } if (fstat(src, &st) < 0) return -errno; r = fopen_temporary_label(target, x, &dst, &temp); if (r < 0) return r; r = copy_bytes(src, fileno(dst), (uint64_t) -1, true); if (r < 0) goto fail; /* Don't fail on chmod() or chown(). If it stays owned by us * and/or unreadable by others, then it isn't too bad... */ backup = strjoina(x, "-"); /* Copy over the access mask */ if (fchmod(fileno(dst), st.st_mode & 07777) < 0) log_warning_errno(errno, "Failed to change mode on %s: %m", backup); if (fchown(fileno(dst), st.st_uid, st.st_gid)< 0) log_warning_errno(errno, "Failed to change ownership of %s: %m", backup); ts[0] = st.st_atim; ts[1] = st.st_mtim; if (futimens(fileno(dst), ts) < 0) log_warning_errno(errno, "Failed to fix access and modification time of %s: %m", backup); if (rename(temp, backup) < 0) goto fail; return 0; fail: unlink(temp); return r; } static int putgrent_with_members(const struct group *gr, FILE *group) { char **a; assert(gr); assert(group); a = hashmap_get(members, gr->gr_name); if (a) { _cleanup_strv_free_ char **l = NULL; bool added = false; char **i; l = strv_copy(gr->gr_mem); if (!l) return -ENOMEM; STRV_FOREACH(i, a) { if (strv_find(l, *i)) continue; if (strv_extend(&l, *i) < 0) return -ENOMEM; added = true; } if (added) { struct group t; strv_uniq(l); strv_sort(l); t = *gr; t.gr_mem = l; errno = 0; if (putgrent(&t, group) != 0) return errno > 0 ? -errno : -EIO; return 1; } } errno = 0; if (putgrent(gr, group) != 0) return errno > 0 ? -errno : -EIO; return 0; } static int putsgent_with_members(const struct sgrp *sg, FILE *gshadow) { char **a; assert(sg); assert(gshadow); a = hashmap_get(members, sg->sg_namp); if (a) { _cleanup_strv_free_ char **l = NULL; bool added = false; char **i; l = strv_copy(sg->sg_mem); if (!l) return -ENOMEM; STRV_FOREACH(i, a) { if (strv_find(l, *i)) continue; if (strv_extend(&l, *i) < 0) return -ENOMEM; added = true; } if (added) { struct sgrp t; strv_uniq(l); strv_sort(l); t = *sg; t.sg_mem = l; errno = 0; if (putsgent(&t, gshadow) != 0) return errno > 0 ? -errno : -EIO; return 1; } } errno = 0; if (putsgent(sg, gshadow) != 0) return errno > 0 ? -errno : -EIO; return 0; } static int sync_rights(FILE *from, FILE *to) { struct stat st; if (fstat(fileno(from), &st) < 0) return -errno; if (fchmod(fileno(to), st.st_mode & 07777) < 0) return -errno; if (fchown(fileno(to), st.st_uid, st.st_gid) < 0) return -errno; return 0; } static int rename_and_apply_smack(const char *temp_path, const char *dest_path) { int r = 0; if (rename(temp_path, dest_path) < 0) return -errno; #ifdef SMACK_RUN_LABEL r = mac_smack_apply(dest_path, SMACK_ATTR_ACCESS, SMACK_FLOOR_LABEL); if (r < 0) return r; #endif return r; } static int write_files(void) { _cleanup_fclose_ FILE *passwd = NULL, *group = NULL, *shadow = NULL, *gshadow = NULL; _cleanup_free_ char *passwd_tmp = NULL, *group_tmp = NULL, *shadow_tmp = NULL, *gshadow_tmp = NULL; const char *passwd_path = NULL, *group_path = NULL, *shadow_path = NULL, *gshadow_path = NULL; bool group_changed = false; Iterator iterator; Item *i; int r; if (hashmap_size(todo_gids) > 0 || hashmap_size(members) > 0) { _cleanup_fclose_ FILE *original = NULL; /* First we update the actual group list file */ group_path = prefix_roota(arg_root, "/etc/group"); r = fopen_temporary_label("/etc/group", group_path, &group, &group_tmp); if (r < 0) goto finish; original = fopen(group_path, "re"); if (original) { struct group *gr; r = sync_rights(original, group); if (r < 0) goto finish; errno = 0; while ((gr = fgetgrent(original))) { /* Safety checks against name and GID * collisions. Normally, this should * be unnecessary, but given that we * look at the entries anyway here, * let's make an extra verification * step that we don't generate * duplicate entries. */ i = hashmap_get(groups, gr->gr_name); if (i && i->todo_group) { log_error("%s: Group \"%s\" already exists.", group_path, gr->gr_name); r = -EEXIST; goto finish; } if (hashmap_contains(todo_gids, GID_TO_PTR(gr->gr_gid))) { log_error("%s: Detected collision for GID " GID_FMT ".", group_path, gr->gr_gid); r = -EEXIST; goto finish; } r = putgrent_with_members(gr, group); if (r < 0) goto finish; if (r > 0) group_changed = true; errno = 0; } if (!IN_SET(errno, 0, ENOENT)) { r = -errno; goto finish; } } else if (errno != ENOENT) { r = -errno; goto finish; } else if (fchmod(fileno(group), 0644) < 0) { r = -errno; goto finish; } HASHMAP_FOREACH(i, todo_gids, iterator) { struct group n = { .gr_name = i->name, .gr_gid = i->gid, .gr_passwd = (char*) "x", }; r = putgrent_with_members(&n, group); if (r < 0) goto finish; group_changed = true; } r = fflush_and_check(group); if (r < 0) goto finish; if (original) { fclose(original); original = NULL; } /* OK, now also update the shadow file for the group list */ gshadow_path = prefix_roota(arg_root, "/etc/gshadow"); r = fopen_temporary_label("/etc/gshadow", gshadow_path, &gshadow, &gshadow_tmp); if (r < 0) goto finish; original = fopen(gshadow_path, "re"); if (original) { struct sgrp *sg; r = sync_rights(original, gshadow); if (r < 0) goto finish; errno = 0; while ((sg = fgetsgent(original))) { i = hashmap_get(groups, sg->sg_namp); if (i && i->todo_group) { log_error("%s: Group \"%s\" already exists.", gshadow_path, sg->sg_namp); r = -EEXIST; goto finish; } r = putsgent_with_members(sg, gshadow); if (r < 0) goto finish; if (r > 0) group_changed = true; errno = 0; } if (!IN_SET(errno, 0, ENOENT)) { r = -errno; goto finish; } } else if (errno != ENOENT) { r = -errno; goto finish; } else if (fchmod(fileno(gshadow), 0000) < 0) { r = -errno; goto finish; } HASHMAP_FOREACH(i, todo_gids, iterator) { struct sgrp n = { .sg_namp = i->name, .sg_passwd = (char*) "!!", }; r = putsgent_with_members(&n, gshadow); if (r < 0) goto finish; group_changed = true; } r = fflush_and_check(gshadow); if (r < 0) goto finish; } if (hashmap_size(todo_uids) > 0) { _cleanup_fclose_ FILE *original = NULL; long lstchg; /* First we update the user database itself */ passwd_path = prefix_roota(arg_root, "/etc/passwd"); r = fopen_temporary_label("/etc/passwd", passwd_path, &passwd, &passwd_tmp); if (r < 0) goto finish; original = fopen(passwd_path, "re"); if (original) { struct passwd *pw; r = sync_rights(original, passwd); if (r < 0) goto finish; errno = 0; while ((pw = fgetpwent(original))) { i = hashmap_get(users, pw->pw_name); if (i && i->todo_user) { log_error("%s: User \"%s\" already exists.", passwd_path, pw->pw_name); r = -EEXIST; goto finish; } if (hashmap_contains(todo_uids, UID_TO_PTR(pw->pw_uid))) { log_error("%s: Detected collision for UID " UID_FMT ".", passwd_path, pw->pw_uid); r = -EEXIST; goto finish; } errno = 0; if (putpwent(pw, passwd) < 0) { r = errno ? -errno : -EIO; goto finish; } errno = 0; } if (!IN_SET(errno, 0, ENOENT)) { r = -errno; goto finish; } } else if (errno != ENOENT) { r = -errno; goto finish; } else if (fchmod(fileno(passwd), 0644) < 0) { r = -errno; goto finish; } HASHMAP_FOREACH(i, todo_uids, iterator) { struct passwd n = { .pw_name = i->name, .pw_uid = i->uid, .pw_gid = i->gid, .pw_gecos = i->description, /* "x" means the password is stored in * the shadow file */ .pw_passwd = (char*) "x", /* We default to the root directory as home */ .pw_dir = i->home ? i->home : (char*) "/", /* Initialize the shell to nologin, * with one exception: for root we * patch in something special */ .pw_shell = i->uid == 0 ? (char*) "/bin/sh" : (char*) "/sbin/nologin", }; errno = 0; if (putpwent(&n, passwd) != 0) { r = errno ? -errno : -EIO; goto finish; } } r = fflush_and_check(passwd); if (r < 0) goto finish; if (original) { fclose(original); original = NULL; } /* The we update the shadow database */ shadow_path = prefix_roota(arg_root, "/etc/shadow"); r = fopen_temporary_label("/etc/shadow", shadow_path, &shadow, &shadow_tmp); if (r < 0) goto finish; lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY); original = fopen(shadow_path, "re"); if (original) { struct spwd *sp; r = sync_rights(original, shadow); if (r < 0) goto finish; errno = 0; while ((sp = fgetspent(original))) { i = hashmap_get(users, sp->sp_namp); if (i && i->todo_user) { /* we will update the existing entry */ sp->sp_lstchg = lstchg; /* only the /etc/shadow stage is left, so we can * safely remove the item from the todo set */ i->todo_user = false; hashmap_remove(todo_uids, UID_TO_PTR(i->uid)); } errno = 0; if (putspent(sp, shadow) < 0) { r = errno ? -errno : -EIO; goto finish; } errno = 0; } if (!IN_SET(errno, 0, ENOENT)) { r = -errno; goto finish; } } else if (errno != ENOENT) { r = -errno; goto finish; } else if (fchmod(fileno(shadow), 0000) < 0) { r = -errno; goto finish; } HASHMAP_FOREACH(i, todo_uids, iterator) { struct spwd n = { .sp_namp = i->name, .sp_pwdp = (char*) "!!", .sp_lstchg = lstchg, .sp_min = -1, .sp_max = -1, .sp_warn = -1, .sp_inact = -1, .sp_expire = -1, .sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */ }; errno = 0; if (putspent(&n, shadow) != 0) { r = errno ? -errno : -EIO; goto finish; } } r = fflush_and_check(shadow); if (r < 0) goto finish; } /* Make a backup of the old files */ if (group_changed) { if (group) { r = make_backup("/etc/group", group_path); if (r < 0) goto finish; } if (gshadow) { r = make_backup("/etc/gshadow", gshadow_path); if (r < 0) goto finish; } } if (passwd) { r = make_backup("/etc/passwd", passwd_path); if (r < 0) goto finish; } if (shadow) { r = make_backup("/etc/shadow", shadow_path); if (r < 0) goto finish; } /* And make the new files count */ if (group_changed) { if (group) { r = rename_and_apply_smack(group_tmp, group_path); if (r < 0) goto finish; group_tmp = mfree(group_tmp); } if (gshadow) { r = rename_and_apply_smack(gshadow_tmp, gshadow_path); if (r < 0) goto finish; gshadow_tmp = mfree(gshadow_tmp); } } if (passwd) { r = rename_and_apply_smack(passwd_tmp, passwd_path); if (r < 0) goto finish; passwd_tmp = mfree(passwd_tmp); } if (shadow) { r = rename_and_apply_smack(shadow_tmp, shadow_path); if (r < 0) goto finish; shadow_tmp = mfree(shadow_tmp); } r = 0; finish: if (passwd_tmp) unlink(passwd_tmp); if (shadow_tmp) unlink(shadow_tmp); if (group_tmp) unlink(group_tmp); if (gshadow_tmp) unlink(gshadow_tmp); return r; } static int uid_is_ok(uid_t uid, const char *name) { struct passwd *p; struct group *g; const char *n; Item *i; /* Let's see if we already have assigned the UID a second time */ if (hashmap_get(todo_uids, UID_TO_PTR(uid))) return 0; /* Try to avoid using uids that are already used by a group * that doesn't have the same name as our new user. */ i = hashmap_get(todo_gids, GID_TO_PTR(uid)); if (i && !streq(i->name, name)) return 0; /* Let's check the files directly */ if (hashmap_contains(database_uid, UID_TO_PTR(uid))) return 0; n = hashmap_get(database_gid, GID_TO_PTR(uid)); if (n && !streq(n, name)) return 0; /* Let's also check via NSS, to avoid UID clashes over LDAP and such, just in case */ if (!arg_root) { errno = 0; p = getpwuid(uid); if (p) return 0; if (!IN_SET(errno, 0, ENOENT)) return -errno; errno = 0; g = getgrgid((gid_t) uid); if (g) { if (!streq(g->gr_name, name)) return 0; } else if (!IN_SET(errno, 0, ENOENT)) return -errno; } return 1; } static int root_stat(const char *p, struct stat *st) { const char *fix; fix = prefix_roota(arg_root, p); if (stat(fix, st) < 0) return -errno; return 0; } static int read_id_from_file(Item *i, uid_t *_uid, gid_t *_gid) { struct stat st; bool found_uid = false, found_gid = false; uid_t uid = 0; gid_t gid = 0; assert(i); /* First, try to get the gid directly */ if (_gid && i->gid_path && root_stat(i->gid_path, &st) >= 0) { gid = st.st_gid; found_gid = true; } /* Then, try to get the uid directly */ if ((_uid || (_gid && !found_gid)) && i->uid_path && root_stat(i->uid_path, &st) >= 0) { uid = st.st_uid; found_uid = true; /* If we need the gid, but had no success yet, also derive it from the uid path */ if (_gid && !found_gid) { gid = st.st_gid; found_gid = true; } } /* If that didn't work yet, then let's reuse the gid as uid */ if (_uid && !found_uid && i->gid_path) { if (found_gid) { uid = (uid_t) gid; found_uid = true; } else if (root_stat(i->gid_path, &st) >= 0) { uid = (uid_t) st.st_gid; found_uid = true; } } if (_uid) { if (!found_uid) return 0; *_uid = uid; } if (_gid) { if (!found_gid) return 0; *_gid = gid; } return 1; } static int add_user(Item *i) { void *z; int r; assert(i); /* Check the database directly */ z = hashmap_get(database_user, i->name); if (z) { log_debug("User %s already exists.", i->name); i->uid = PTR_TO_UID(z); i->uid_set = true; return 0; } if (!arg_root) { struct passwd *p; /* Also check NSS */ errno = 0; p = getpwnam(i->name); if (p) { log_debug("User %s already exists.", i->name); i->uid = p->pw_uid; i->uid_set = true; r = free_and_strdup(&i->description, p->pw_gecos); if (r < 0) return log_oom(); return 0; } if (!IN_SET(errno, 0, ENOENT)) return log_error_errno(errno, "Failed to check if user %s already exists: %m", i->name); } /* Try to use the suggested numeric uid */ if (i->uid_set) { r = uid_is_ok(i->uid, i->name); if (r < 0) return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid); if (r == 0) { log_debug("Suggested user ID " UID_FMT " for %s already used.", i->uid, i->name); i->uid_set = false; } } /* If that didn't work, try to read it from the specified path */ if (!i->uid_set) { uid_t c; if (read_id_from_file(i, &c, NULL) > 0) { if (c <= 0 || !uid_range_contains(uid_range, n_uid_range, c)) log_debug("User ID " UID_FMT " of file not suitable for %s.", c, i->name); else { r = uid_is_ok(c, i->name); if (r < 0) return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid); else if (r > 0) { i->uid = c; i->uid_set = true; } else log_debug("User ID " UID_FMT " of file for %s is already used.", c, i->name); } } } /* Otherwise, try to reuse the group ID */ if (!i->uid_set && i->gid_set) { r = uid_is_ok((uid_t) i->gid, i->name); if (r < 0) return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid); if (r > 0) { i->uid = (uid_t) i->gid; i->uid_set = true; } } /* And if that didn't work either, let's try to find a free one */ if (!i->uid_set) { for (;;) { r = uid_range_next_lower(uid_range, n_uid_range, &search_uid); if (r < 0) { log_error("No free user ID available for %s.", i->name); return r; } r = uid_is_ok(search_uid, i->name); if (r < 0) return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid); else if (r > 0) break; } i->uid_set = true; i->uid = search_uid; } r = hashmap_ensure_allocated(&todo_uids, NULL); if (r < 0) return log_oom(); r = hashmap_put(todo_uids, UID_TO_PTR(i->uid), i); if (r < 0) return log_oom(); i->todo_user = true; log_info("Creating user %s (%s) with uid " UID_FMT " and gid " GID_FMT ".", i->name, strna(i->description), i->uid, i->gid); return 0; } static int gid_is_ok(gid_t gid) { struct group *g; struct passwd *p; if (hashmap_get(todo_gids, GID_TO_PTR(gid))) return 0; /* Avoid reusing gids that are already used by a different user */ if (hashmap_get(todo_uids, UID_TO_PTR(gid))) return 0; if (hashmap_contains(database_gid, GID_TO_PTR(gid))) return 0; if (hashmap_contains(database_uid, UID_TO_PTR(gid))) return 0; if (!arg_root) { errno = 0; g = getgrgid(gid); if (g) return 0; if (!IN_SET(errno, 0, ENOENT)) return -errno; errno = 0; p = getpwuid((uid_t) gid); if (p) return 0; if (!IN_SET(errno, 0, ENOENT)) return -errno; } return 1; } static int add_group(Item *i) { void *z; int r; assert(i); /* Check the database directly */ z = hashmap_get(database_group, i->name); if (z) { log_debug("Group %s already exists.", i->name); i->gid = PTR_TO_GID(z); i->gid_set = true; return 0; } /* Also check NSS */ if (!arg_root) { struct group *g; errno = 0; g = getgrnam(i->name); if (g) { log_debug("Group %s already exists.", i->name); i->gid = g->gr_gid; i->gid_set = true; return 0; } if (!IN_SET(errno, 0, ENOENT)) return log_error_errno(errno, "Failed to check if group %s already exists: %m", i->name); } /* Try to use the suggested numeric gid */ if (i->gid_set) { r = gid_is_ok(i->gid); if (r < 0) return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid); if (r == 0) { log_debug("Suggested group ID " GID_FMT " for %s already used.", i->gid, i->name); i->gid_set = false; } } /* Try to reuse the numeric uid, if there's one */ if (!i->gid_set && i->uid_set) { r = gid_is_ok((gid_t) i->uid); if (r < 0) return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid); if (r > 0) { i->gid = (gid_t) i->uid; i->gid_set = true; } } /* If that didn't work, try to read it from the specified path */ if (!i->gid_set) { gid_t c; if (read_id_from_file(i, NULL, &c) > 0) { if (c <= 0 || !uid_range_contains(uid_range, n_uid_range, c)) log_debug("Group ID " GID_FMT " of file not suitable for %s.", c, i->name); else { r = gid_is_ok(c); if (r < 0) return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid); else if (r > 0) { i->gid = c; i->gid_set = true; } else log_debug("Group ID " GID_FMT " of file for %s already used.", c, i->name); } } } /* And if that didn't work either, let's try to find a free one */ if (!i->gid_set) { for (;;) { /* We look for new GIDs in the UID pool! */ r = uid_range_next_lower(uid_range, n_uid_range, &search_uid); if (r < 0) { log_error("No free group ID available for %s.", i->name); return r; } r = gid_is_ok(search_uid); if (r < 0) return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid); else if (r > 0) break; } i->gid_set = true; i->gid = search_uid; } r = hashmap_ensure_allocated(&todo_gids, NULL); if (r < 0) return log_oom(); r = hashmap_put(todo_gids, GID_TO_PTR(i->gid), i); if (r < 0) return log_oom(); i->todo_group = true; log_info("Creating group %s with gid " GID_FMT ".", i->name, i->gid); return 0; } static int process_item(Item *i) { int r; assert(i); switch (i->type) { case ADD_USER: r = add_group(i); if (r < 0) return r; return add_user(i); case ADD_GROUP: { Item *j; j = hashmap_get(users, i->name); if (j) { /* There's already user to be created for this * name, let's process that in one step */ if (i->gid_set) { j->gid = i->gid; j->gid_set = true; } if (i->gid_path) { r = free_and_strdup(&j->gid_path, i->gid_path); if (r < 0) return log_oom(); } return 0; } return add_group(i); } default: assert_not_reached("Unknown item type"); } } static void item_free(Item *i) { if (!i) return; free(i->name); free(i->uid_path); free(i->gid_path); free(i->description); free(i); } DEFINE_TRIVIAL_CLEANUP_FUNC(Item*, item_free); static int add_implicit(void) { char *g, **l; Iterator iterator; int r; /* Implicitly create additional users and groups, if they were listed in "m" lines */ HASHMAP_FOREACH_KEY(l, g, members, iterator) { Item *i; char **m; i = hashmap_get(groups, g); if (!i) { _cleanup_(item_freep) Item *j = NULL; r = hashmap_ensure_allocated(&groups, &string_hash_ops); if (r < 0) return log_oom(); j = new0(Item, 1); if (!j) return log_oom(); j->type = ADD_GROUP; j->name = strdup(g); if (!j->name) return log_oom(); r = hashmap_put(groups, j->name, j); if (r < 0) return log_oom(); log_debug("Adding implicit group '%s' due to m line", j->name); j = NULL; } STRV_FOREACH(m, l) { i = hashmap_get(users, *m); if (!i) { _cleanup_(item_freep) Item *j = NULL; r = hashmap_ensure_allocated(&users, &string_hash_ops); if (r < 0) return log_oom(); j = new0(Item, 1); if (!j) return log_oom(); j->type = ADD_USER; j->name = strdup(*m); if (!j->name) return log_oom(); r = hashmap_put(users, j->name, j); if (r < 0) return log_oom(); log_debug("Adding implicit user '%s' due to m line", j->name); j = NULL; } } } return 0; } static bool item_equal(Item *a, Item *b) { assert(a); assert(b); if (a->type != b->type) return false; if (!streq_ptr(a->name, b->name)) return false; if (!streq_ptr(a->uid_path, b->uid_path)) return false; if (!streq_ptr(a->gid_path, b->gid_path)) return false; if (!streq_ptr(a->description, b->description)) return false; if (a->uid_set != b->uid_set) return false; if (a->uid_set && a->uid != b->uid) return false; if (a->gid_set != b->gid_set) return false; if (a->gid_set && a->gid != b->gid) return false; if (!streq_ptr(a->home, b->home)) return false; return true; } static bool valid_user_group_name(const char *u) { const char *i; long sz; if (isempty(u)) return false; if (!(u[0] >= 'a' && u[0] <= 'z') && !(u[0] >= 'A' && u[0] <= 'Z') && u[0] != '_') return false; for (i = u+1; *i; i++) { if (!(*i >= 'a' && *i <= 'z') && !(*i >= 'A' && *i <= 'Z') && !(*i >= '0' && *i <= '9') && *i != '_' && *i != '-') return false; } sz = sysconf(_SC_LOGIN_NAME_MAX); assert_se(sz > 0); if ((size_t) (i-u) > (size_t) sz) return false; if ((size_t) (i-u) > UT_NAMESIZE - 1) return false; return true; } static bool valid_gecos(const char *d) { if (!d) return false; if (!utf8_is_valid(d)) return false; if (string_has_cc(d, NULL)) return false; /* Colons are used as field separators, and hence not OK */ if (strchr(d, ':')) return false; return true; } static bool valid_home(const char *p) { if (isempty(p)) return false; if (!utf8_is_valid(p)) return false; if (string_has_cc(p, NULL)) return false; if (!path_is_absolute(p)) return false; if (!path_is_safe(p)) return false; /* Colons are used as field separators, and hence not OK */ if (strchr(p, ':')) return false; return true; } static int parse_line(const char *fname, unsigned line, const char *buffer) { static const Specifier specifier_table[] = { { 'm', specifier_machine_id, NULL }, { 'b', specifier_boot_id, NULL }, { 'H', specifier_host_name, NULL }, { 'v', specifier_kernel_release, NULL }, {} }; _cleanup_free_ char *action = NULL, *name = NULL, *id = NULL, *resolved_name = NULL, *resolved_id = NULL, *description = NULL, *home = NULL; _cleanup_(item_freep) Item *i = NULL; Item *existing; Hashmap *h; int r; const char *p; assert(fname); assert(line >= 1); assert(buffer); /* Parse columns */ p = buffer; r = extract_many_words(&p, NULL, EXTRACT_QUOTES, &action, &name, &id, &description, &home, NULL); if (r < 0) { log_error("[%s:%u] Syntax error.", fname, line); return r; } if (r < 2) { log_error("[%s:%u] Missing action and name columns.", fname, line); return -EINVAL; } if (!isempty(p)) { log_error("[%s:%u] Trailing garbage.", fname, line); return -EINVAL; } /* Verify action */ if (strlen(action) != 1) { log_error("[%s:%u] Unknown modifier '%s'", fname, line, action); return -EINVAL; } if (!IN_SET(action[0], ADD_USER, ADD_GROUP, ADD_MEMBER, ADD_RANGE)) { log_error("[%s:%u] Unknown command command type '%c'.", fname, line, action[0]); return -EBADMSG; } /* Verify name */ if (isempty(name) || streq(name, "-")) name = mfree(name); if (name) { r = specifier_printf(name, specifier_table, NULL, &resolved_name); if (r < 0) { log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, name); return r; } if (!valid_user_group_name(resolved_name)) { log_error("[%s:%u] '%s' is not a valid user or group name.", fname, line, resolved_name); return -EINVAL; } } /* Verify id */ if (isempty(id) || streq(id, "-")) id = mfree(id); if (id) { r = specifier_printf(id, specifier_table, NULL, &resolved_id); if (r < 0) { log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, name); return r; } } /* Verify description */ if (isempty(description) || streq(description, "-")) description = mfree(description); if (description) { if (!valid_gecos(description)) { log_error("[%s:%u] '%s' is not a valid GECOS field.", fname, line, description); return -EINVAL; } } /* Verify home */ if (isempty(home) || streq(home, "-")) home = mfree(home); if (home) { if (!valid_home(home)) { log_error("[%s:%u] '%s' is not a valid home directory field.", fname, line, home); return -EINVAL; } } switch (action[0]) { case ADD_RANGE: if (resolved_name) { log_error("[%s:%u] Lines of type 'r' don't take a name field.", fname, line); return -EINVAL; } if (!resolved_id) { log_error("[%s:%u] Lines of type 'r' require a ID range in the third field.", fname, line); return -EINVAL; } if (description) { log_error("[%s:%u] Lines of type 'r' don't take a GECOS field.", fname, line); return -EINVAL; } if (home) { log_error("[%s:%u] Lines of type 'r' don't take a home directory field.", fname, line); return -EINVAL; } r = uid_range_add_str(&uid_range, &n_uid_range, resolved_id); if (r < 0) { log_error("[%s:%u] Invalid UID range %s.", fname, line, resolved_id); return -EINVAL; } return 0; case ADD_MEMBER: { char **l; /* Try to extend an existing member or group item */ if (!name) { log_error("[%s:%u] Lines of type 'm' require a user name in the second field.", fname, line); return -EINVAL; } if (!resolved_id) { log_error("[%s:%u] Lines of type 'm' require a group name in the third field.", fname, line); return -EINVAL; } if (!valid_user_group_name(resolved_id)) { log_error("[%s:%u] '%s' is not a valid user or group name.", fname, line, resolved_id); return -EINVAL; } if (description) { log_error("[%s:%u] Lines of type 'm' don't take a GECOS field.", fname, line); return -EINVAL; } if (home) { log_error("[%s:%u] Lines of type 'm' don't take a home directory field.", fname, line); return -EINVAL; } r = hashmap_ensure_allocated(&members, &string_hash_ops); if (r < 0) return log_oom(); l = hashmap_get(members, resolved_id); if (l) { /* A list for this group name already exists, let's append to it */ r = strv_push(&l, resolved_name); if (r < 0) return log_oom(); resolved_name = NULL; assert_se(hashmap_update(members, resolved_id, l) >= 0); } else { /* No list for this group name exists yet, create one */ l = new0(char *, 2); if (!l) return -ENOMEM; l[0] = resolved_name; l[1] = NULL; r = hashmap_put(members, resolved_id, l); if (r < 0) { free(l); return log_oom(); } resolved_id = resolved_name = NULL; } return 0; } case ADD_USER: if (!name) { log_error("[%s:%u] Lines of type 'u' require a user name in the second field.", fname, line); return -EINVAL; } r = hashmap_ensure_allocated(&users, &string_hash_ops); if (r < 0) return log_oom(); i = new0(Item, 1); if (!i) return log_oom(); if (resolved_id) { if (path_is_absolute(resolved_id)) { i->uid_path = resolved_id; resolved_id = NULL; path_kill_slashes(i->uid_path); } else { r = parse_uid(resolved_id, &i->uid); if (r < 0) { log_error("Failed to parse UID: %s", id); return -EBADMSG; } i->uid_set = true; } } i->description = description; description = NULL; i->home = home; home = NULL; h = users; break; case ADD_GROUP: if (!name) { log_error("[%s:%u] Lines of type 'g' require a user name in the second field.", fname, line); return -EINVAL; } if (description) { log_error("[%s:%u] Lines of type 'g' don't take a GECOS field.", fname, line); return -EINVAL; } if (home) { log_error("[%s:%u] Lines of type 'g' don't take a home directory field.", fname, line); return -EINVAL; } r = hashmap_ensure_allocated(&groups, &string_hash_ops); if (r < 0) return log_oom(); i = new0(Item, 1); if (!i) return log_oom(); if (resolved_id) { if (path_is_absolute(resolved_id)) { i->gid_path = resolved_id; resolved_id = NULL; path_kill_slashes(i->gid_path); } else { r = parse_gid(resolved_id, &i->gid); if (r < 0) { log_error("Failed to parse GID: %s", id); return -EBADMSG; } i->gid_set = true; } } h = groups; break; default: return -EBADMSG; } i->type = action[0]; i->name = resolved_name; resolved_name = NULL; existing = hashmap_get(h, i->name); if (existing) { /* Two identical items are fine */ if (!item_equal(existing, i)) log_warning("Two or more conflicting lines for %s configured, ignoring.", i->name); return 0; } r = hashmap_put(h, i->name, i); if (r < 0) return log_oom(); i = NULL; return 0; } static int read_config_file(const char *fn, bool ignore_enoent) { _cleanup_fclose_ FILE *rf = NULL; FILE *f = NULL; char line[LINE_MAX]; unsigned v = 0; int r = 0; assert(fn); if (streq(fn, "-")) f = stdin; else { r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &rf); if (r < 0) { if (ignore_enoent && r == -ENOENT) return 0; return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn); } f = rf; } FOREACH_LINE(line, f, break) { char *l; int k; v++; l = strstrip(line); if (*l == '#' || *l == 0) continue; k = parse_line(fn, v, l); if (k < 0 && r == 0) r = k; } if (ferror(f)) { log_error_errno(errno, "Failed to read from file %s: %m", fn); if (r == 0) r = -EIO; } return r; } static void free_database(Hashmap *by_name, Hashmap *by_id) { char *name; for (;;) { name = hashmap_first(by_id); if (!name) break; hashmap_remove(by_name, name); hashmap_steal_first_key(by_id); free(name); } while ((name = hashmap_steal_first_key(by_name))) free(name); hashmap_free(by_name); hashmap_free(by_id); } static void help(void) { printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n" "Creates system user accounts.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --root=PATH Operate on an alternate filesystem root\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_ROOT, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "root", required_argument, NULL, ARG_ROOT }, {} }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_ROOT: r = parse_path_argument_and_warn(optarg, true, &arg_root); if (r < 0) return r; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } int main(int argc, char *argv[]) { _cleanup_close_ int lock = -1; Iterator iterator; int r, k; Item *i; char *n; r = parse_argv(argc, argv); if (r <= 0) goto finish; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); r = mac_selinux_init(NULL); if (r < 0) { log_error_errno(r, "SELinux setup failed: %m"); goto finish; } if (optind < argc) { int j; for (j = optind; j < argc; j++) { k = read_config_file(argv[j], false); if (k < 0 && r == 0) r = k; } } else { _cleanup_strv_free_ char **files = NULL; char **f; r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs); if (r < 0) { log_error_errno(r, "Failed to enumerate sysusers.d files: %m"); goto finish; } STRV_FOREACH(f, files) { k = read_config_file(*f, true); if (k < 0 && r == 0) r = k; } } if (!uid_range) { /* Default to default range of 1..SYSTEMD_UID_MAX */ r = uid_range_add(&uid_range, &n_uid_range, 1, SYSTEM_UID_MAX); if (r < 0) { log_oom(); goto finish; } } r = add_implicit(); if (r < 0) goto finish; lock = take_etc_passwd_lock(arg_root); if (lock < 0) { log_error_errno(lock, "Failed to take lock: %m"); goto finish; } r = load_user_database(); if (r < 0) { log_error_errno(r, "Failed to load user database: %m"); goto finish; } r = load_group_database(); if (r < 0) { log_error_errno(r, "Failed to read group database: %m"); goto finish; } HASHMAP_FOREACH(i, groups, iterator) process_item(i); HASHMAP_FOREACH(i, users, iterator) process_item(i); r = write_files(); if (r < 0) log_error_errno(r, "Failed to write files: %m"); finish: while ((i = hashmap_steal_first(groups))) item_free(i); while ((i = hashmap_steal_first(users))) item_free(i); while ((n = hashmap_first_key(members))) { strv_free(hashmap_steal_first(members)); free(n); } hashmap_free(groups); hashmap_free(users); hashmap_free(members); hashmap_free(todo_uids); hashmap_free(todo_gids); free_database(database_user, database_uid); free_database(database_group, database_gid); free(arg_root); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/sysv-generator/000077500000000000000000000000001265713322000166405ustar00rootroot00000000000000systemd-229/src/sysv-generator/Makefile000077700000000000000000000000001265713322000221462../Makefileustar00rootroot00000000000000systemd-229/src/sysv-generator/sysv-generator.c000066400000000000000000001020171265713322000217750ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Thomas H.P. Andersen Copyright 2010 Lennart Poettering Copyright 2011 Michal Schmidt systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "dirent-util.h" #include "fd-util.h" #include "fileio.h" #include "hashmap.h" #include "hexdecoct.h" #include "install.h" #include "log.h" #include "mkdir.h" #include "path-lookup.h" #include "path-util.h" #include "set.h" #include "special.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" #include "unit-name.h" #include "util.h" typedef enum RunlevelType { RUNLEVEL_UP, RUNLEVEL_DOWN } RunlevelType; static const struct { const char *path; const char *target; const RunlevelType type; } rcnd_table[] = { /* Standard SysV runlevels for start-up */ { "rc1.d", SPECIAL_RESCUE_TARGET, RUNLEVEL_UP }, { "rc2.d", SPECIAL_MULTI_USER_TARGET, RUNLEVEL_UP }, { "rc3.d", SPECIAL_MULTI_USER_TARGET, RUNLEVEL_UP }, { "rc4.d", SPECIAL_MULTI_USER_TARGET, RUNLEVEL_UP }, { "rc5.d", SPECIAL_GRAPHICAL_TARGET, RUNLEVEL_UP }, /* Standard SysV runlevels for shutdown */ { "rc0.d", SPECIAL_POWEROFF_TARGET, RUNLEVEL_DOWN }, { "rc6.d", SPECIAL_REBOOT_TARGET, RUNLEVEL_DOWN } /* Note that the order here matters, as we read the directories in this order, and we want to make sure that sysv_start_priority is known when we first load the unit. And that value we only know from S links. Hence UP must be read before DOWN */ }; const char *arg_dest = "/tmp"; typedef struct SysvStub { char *name; char *path; char *description; int sysv_start_priority; char *pid_file; char **before; char **after; char **wants; char **wanted_by; char **conflicts; bool has_lsb; bool reload; bool loaded; } SysvStub; static void free_sysvstub(SysvStub *s) { if (!s) return; free(s->name); free(s->path); free(s->description); free(s->pid_file); strv_free(s->before); strv_free(s->after); strv_free(s->wants); strv_free(s->wanted_by); strv_free(s->conflicts); free(s); } DEFINE_TRIVIAL_CLEANUP_FUNC(SysvStub*, free_sysvstub); static void free_sysvstub_hashmapp(Hashmap **h) { SysvStub *stub; while ((stub = hashmap_steal_first(*h))) free_sysvstub(stub); hashmap_free(*h); } static int add_symlink(const char *service, const char *where) { const char *from, *to; int r; assert(service); assert(where); from = strjoina(arg_dest, "/", service); to = strjoina(arg_dest, "/", where, ".wants/", service); mkdir_parents_label(to, 0755); r = symlink(from, to); if (r < 0) { if (errno == EEXIST) return 0; return -errno; } return 1; } static int add_alias(const char *service, const char *alias) { const char *link; int r; assert(service); assert(alias); link = strjoina(arg_dest, "/", alias); r = symlink(service, link); if (r < 0) { if (errno == EEXIST) return 0; return -errno; } return 1; } static int generate_unit_file(SysvStub *s) { _cleanup_fclose_ FILE *f = NULL; const char *unit; char **p; int r; assert(s); if (!s->loaded) return 0; unit = strjoina(arg_dest, "/", s->name); /* We might already have a symlink with the same name from a Provides:, * or from backup files like /etc/init.d/foo.bak. Real scripts always win, * so remove an existing link */ if (is_symlink(unit) > 0) { log_warning("Overwriting existing symlink %s with real service.", unit); (void) unlink(unit); } f = fopen(unit, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", unit); fprintf(f, "# Automatically generated by systemd-sysv-generator\n\n" "[Unit]\n" "Documentation=man:systemd-sysv-generator(8)\n" "SourcePath=%s\n", s->path); if (s->description) fprintf(f, "Description=%s\n", s->description); STRV_FOREACH(p, s->before) fprintf(f, "Before=%s\n", *p); STRV_FOREACH(p, s->after) fprintf(f, "After=%s\n", *p); STRV_FOREACH(p, s->wants) fprintf(f, "Wants=%s\n", *p); STRV_FOREACH(p, s->conflicts) fprintf(f, "Conflicts=%s\n", *p); fprintf(f, "\n[Service]\n" "Type=forking\n" "Restart=no\n" "TimeoutSec=5min\n" "IgnoreSIGPIPE=no\n" "KillMode=process\n" "GuessMainPID=no\n" "RemainAfterExit=%s\n", yes_no(!s->pid_file)); if (s->pid_file) fprintf(f, "PIDFile=%s\n", s->pid_file); fprintf(f, "ExecStart=%s start\n" "ExecStop=%s stop\n", s->path, s->path); if (s->reload) fprintf(f, "ExecReload=%s reload\n", s->path); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit %s: %m", unit); STRV_FOREACH(p, s->wanted_by) { r = add_symlink(s->name, *p); if (r < 0) log_warning_errno(r, "Failed to create 'Wants' symlink to %s, ignoring: %m", *p); } return 1; } static bool usage_contains_reload(const char *line) { return (strcasestr(line, "{reload|") || strcasestr(line, "{reload}") || strcasestr(line, "{reload\"") || strcasestr(line, "|reload|") || strcasestr(line, "|reload}") || strcasestr(line, "|reload\"")); } static char *sysv_translate_name(const char *name) { _cleanup_free_ char *c = NULL; char *res; c = strdup(name); if (!c) return NULL; res = endswith(c, ".sh"); if (res) *res = 0; if (unit_name_mangle(c, UNIT_NAME_NOGLOB, &res) < 0) return NULL; return res; } static int sysv_translate_facility(const char *name, const char *filename, char **ret) { /* We silently ignore the $ prefix here. According to the LSB * spec it simply indicates whether something is a * standardized name or a distribution-specific one. Since we * just follow what already exists and do not introduce new * uses or names we don't care who introduced a new name. */ static const char * const table[] = { /* LSB defined facilities */ "local_fs", NULL, "network", SPECIAL_NETWORK_ONLINE_TARGET, "named", SPECIAL_NSS_LOOKUP_TARGET, "portmap", SPECIAL_RPCBIND_TARGET, "remote_fs", SPECIAL_REMOTE_FS_TARGET, "syslog", NULL, "time", SPECIAL_TIME_SYNC_TARGET, }; char *filename_no_sh, *e, *m; const char *n; unsigned i; int r; assert(name); assert(filename); assert(ret); n = *name == '$' ? name + 1 : name; for (i = 0; i < ELEMENTSOF(table); i += 2) { if (!streq(table[i], n)) continue; if (!table[i+1]) return 0; m = strdup(table[i+1]); if (!m) return log_oom(); *ret = m; return 1; } /* If we don't know this name, fallback heuristics to figure * out whether something is a target or a service alias. */ /* Facilities starting with $ are most likely targets */ if (*name == '$') { r = unit_name_build(n, NULL, ".target", ret); if (r < 0) return log_error_errno(r, "Failed to build name: %m"); return r; } /* Strip ".sh" suffix from file name for comparison */ filename_no_sh = strdupa(filename); e = endswith(filename_no_sh, ".sh"); if (e) { *e = '\0'; filename = filename_no_sh; } /* Names equaling the file name of the services are redundant */ if (streq_ptr(n, filename)) return 0; /* Everything else we assume to be normal service names */ m = sysv_translate_name(n); if (!m) return log_oom(); *ret = m; return 1; } static int handle_provides(SysvStub *s, unsigned line, const char *full_text, const char *text) { int r; assert(s); assert(full_text); assert(text); for (;;) { _cleanup_free_ char *word = NULL, *m = NULL; r = extract_first_word(&text, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); if (r < 0) return log_error_errno(r, "Failed to parse word from provides string: %m"); if (r == 0) break; r = sysv_translate_facility(word, basename(s->path), &m); if (r <= 0) /* continue on error */ continue; switch (unit_name_to_type(m)) { case UNIT_SERVICE: log_debug("Adding Provides: alias '%s' for '%s'", m, s->name); r = add_alias(s->name, m); if (r < 0) log_warning_errno(r, "[%s:%u] Failed to add LSB Provides name %s, ignoring: %m", s->path, line, m); break; case UNIT_TARGET: /* NB: SysV targets which are provided by a * service are pulled in by the services, as * an indication that the generic service is * now available. This is strictly one-way. * The targets do NOT pull in SysV services! */ r = strv_extend(&s->before, m); if (r < 0) return log_oom(); r = strv_extend(&s->wants, m); if (r < 0) return log_oom(); if (streq(m, SPECIAL_NETWORK_ONLINE_TARGET)) { r = strv_extend(&s->before, SPECIAL_NETWORK_TARGET); if (r < 0) return log_oom(); } break; case _UNIT_TYPE_INVALID: log_warning("Unit name '%s' is invalid", m); break; default: log_warning("Unknown unit type for unit '%s'", m); } } return 0; } static int handle_dependencies(SysvStub *s, unsigned line, const char *full_text, const char *text) { int r; assert(s); assert(full_text); assert(text); for (;;) { _cleanup_free_ char *word = NULL, *m = NULL; bool is_before; r = extract_first_word(&text, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); if (r < 0) return log_error_errno(r, "Failed to parse word from provides string: %m"); if (r == 0) break; r = sysv_translate_facility(word, basename(s->path), &m); if (r <= 0) /* continue on error */ continue; is_before = startswith_no_case(full_text, "X-Start-Before:"); if (streq(m, SPECIAL_NETWORK_ONLINE_TARGET) && !is_before) { /* the network-online target is special, as it needs to be actively pulled in */ r = strv_extend(&s->after, m); if (r < 0) return log_oom(); r = strv_extend(&s->wants, m); } else r = strv_extend(is_before ? &s->before : &s->after, m); if (r < 0) return log_oom(); } return 0; } static int load_sysv(SysvStub *s) { _cleanup_fclose_ FILE *f; unsigned line = 0; int r; enum { NORMAL, DESCRIPTION, LSB, LSB_DESCRIPTION, USAGE_CONTINUATION } state = NORMAL; _cleanup_free_ char *short_description = NULL, *long_description = NULL, *chkconfig_description = NULL; char *description; bool supports_reload = false; char l[LINE_MAX]; assert(s); f = fopen(s->path, "re"); if (!f) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open %s: %m", s->path); } log_debug("Loading SysV script %s", s->path); FOREACH_LINE(l, f, goto fail) { char *t; line++; t = strstrip(l); if (*t != '#') { /* Try to figure out whether this init script supports * the reload operation. This heuristic looks for * "Usage" lines which include the reload option. */ if ( state == USAGE_CONTINUATION || (state == NORMAL && strcasestr(t, "usage"))) { if (usage_contains_reload(t)) { supports_reload = true; state = NORMAL; } else if (t[strlen(t)-1] == '\\') state = USAGE_CONTINUATION; else state = NORMAL; } continue; } if (state == NORMAL && streq(t, "### BEGIN INIT INFO")) { state = LSB; s->has_lsb = true; continue; } if ((state == LSB_DESCRIPTION || state == LSB) && streq(t, "### END INIT INFO")) { state = NORMAL; continue; } t++; t += strspn(t, WHITESPACE); if (state == NORMAL) { /* Try to parse Red Hat style description */ if (startswith_no_case(t, "description:")) { size_t k; const char *j; k = strlen(t); if (k > 0 && t[k-1] == '\\') { state = DESCRIPTION; t[k-1] = 0; } j = strstrip(t+12); if (isempty(j)) j = NULL; r = free_and_strdup(&chkconfig_description, j); if (r < 0) return log_oom(); } else if (startswith_no_case(t, "pidfile:")) { const char *fn; state = NORMAL; fn = strstrip(t+8); if (!path_is_absolute(fn)) { log_error("[%s:%u] PID file not absolute. Ignoring.", s->path, line); continue; } r = free_and_strdup(&s->pid_file, fn); if (r < 0) return log_oom(); } } else if (state == DESCRIPTION) { /* Try to parse Red Hat style description * continuation */ size_t k; char *j; k = strlen(t); if (k > 0 && t[k-1] == '\\') t[k-1] = 0; else state = NORMAL; j = strstrip(t); if (!isempty(j)) { char *d = NULL; if (chkconfig_description) d = strjoin(chkconfig_description, " ", j, NULL); else d = strdup(j); if (!d) return log_oom(); free(chkconfig_description); chkconfig_description = d; } } else if (state == LSB || state == LSB_DESCRIPTION) { if (startswith_no_case(t, "Provides:")) { state = LSB; r = handle_provides(s, line, t, t + 9); if (r < 0) return r; } else if (startswith_no_case(t, "Required-Start:") || startswith_no_case(t, "Should-Start:") || startswith_no_case(t, "X-Start-Before:") || startswith_no_case(t, "X-Start-After:")) { state = LSB; r = handle_dependencies(s, line, t, strchr(t, ':') + 1); if (r < 0) return r; } else if (startswith_no_case(t, "Description:")) { const char *j; state = LSB_DESCRIPTION; j = strstrip(t+12); if (isempty(j)) j = NULL; r = free_and_strdup(&long_description, j); if (r < 0) return log_oom(); } else if (startswith_no_case(t, "Short-Description:")) { const char *j; state = LSB; j = strstrip(t+18); if (isempty(j)) j = NULL; r = free_and_strdup(&short_description, j); if (r < 0) return log_oom(); } else if (state == LSB_DESCRIPTION) { if (startswith(l, "#\t") || startswith(l, "# ")) { const char *j; j = strstrip(t); if (!isempty(j)) { char *d = NULL; if (long_description) d = strjoin(long_description, " ", t, NULL); else d = strdup(j); if (!d) return log_oom(); free(long_description); long_description = d; } } else state = LSB; } } } s->reload = supports_reload; /* We use the long description only if * no short description is set. */ if (short_description) description = short_description; else if (chkconfig_description) description = chkconfig_description; else if (long_description) description = long_description; else description = NULL; if (description) { char *d; d = strappend(s->has_lsb ? "LSB: " : "SYSV: ", description); if (!d) return log_oom(); s->description = d; } s->loaded = true; return 0; fail: return log_error_errno(errno, "Failed to read configuration file '%s': %m", s->path); } static int fix_order(SysvStub *s, Hashmap *all_services) { SysvStub *other; Iterator j; int r; assert(s); if (!s->loaded) return 0; if (s->sysv_start_priority < 0) return 0; HASHMAP_FOREACH(other, all_services, j) { if (s == other) continue; if (!other->loaded) continue; if (other->sysv_start_priority < 0) continue; /* If both units have modern headers we don't care * about the priorities */ if (s->has_lsb && other->has_lsb) continue; if (other->sysv_start_priority < s->sysv_start_priority) { r = strv_extend(&s->after, other->name); if (r < 0) return log_oom(); } else if (other->sysv_start_priority > s->sysv_start_priority) { r = strv_extend(&s->before, other->name); if (r < 0) return log_oom(); } else continue; /* FIXME: Maybe we should compare the name here lexicographically? */ } return 0; } static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) { char **path; int r; assert(lp); assert(all_services); STRV_FOREACH(path, lp->sysvinit_path) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; d = opendir(*path); if (!d) { if (errno != ENOENT) log_warning_errno(errno, "Opening %s failed, ignoring: %m", *path); continue; } FOREACH_DIRENT(de, d, log_error_errno(errno, "Failed to enumerate directory %s, ignoring: %m", *path)) { _cleanup_free_ char *fpath = NULL, *name = NULL; _cleanup_(free_sysvstubp) SysvStub *service = NULL; struct stat st; if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) { log_warning_errno(errno, "stat() failed on %s/%s, ignoring: %m", *path, de->d_name); continue; } if (!(st.st_mode & S_IXUSR)) continue; if (!S_ISREG(st.st_mode)) continue; name = sysv_translate_name(de->d_name); if (!name) return log_oom(); if (hashmap_contains(all_services, name)) continue; r = unit_file_lookup_state(UNIT_FILE_SYSTEM, NULL, lp, name, NULL); if (r < 0 && r != -ENOENT) { log_debug_errno(r, "Failed to detect whether %s exists, skipping: %m", name); continue; } else if (r >= 0) { log_debug("Native unit for %s already exists, skipping.", name); continue; } fpath = strjoin(*path, "/", de->d_name, NULL); if (!fpath) return log_oom(); service = new0(SysvStub, 1); if (!service) return log_oom(); service->sysv_start_priority = -1; service->name = name; service->path = fpath; name = fpath = NULL; r = hashmap_put(all_services, service->name, service); if (r < 0) return log_oom(); service = NULL; } } return 0; } static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_services) { Set *runlevel_services[ELEMENTSOF(rcnd_table)] = {}; _cleanup_set_free_ Set *shutdown_services = NULL; SysvStub *service; unsigned i; Iterator j; char **p; int r; assert(lp); STRV_FOREACH(p, lp->sysvrcnd_path) { for (i = 0; i < ELEMENTSOF(rcnd_table); i ++) { _cleanup_closedir_ DIR *d = NULL; _cleanup_free_ char *path = NULL; struct dirent *de; path = strjoin(*p, "/", rcnd_table[i].path, NULL); if (!path) { r = log_oom(); goto finish; } d = opendir(path); if (!d) { if (errno != ENOENT) log_warning_errno(errno, "Opening %s failed, ignoring: %m", path); continue; } FOREACH_DIRENT(de, d, log_error_errno(errno, "Failed to enumerate directory %s, ignoring: %m", path)) { _cleanup_free_ char *name = NULL, *fpath = NULL; int a, b; if (de->d_name[0] != 'S' && de->d_name[0] != 'K') continue; if (strlen(de->d_name) < 4) continue; a = undecchar(de->d_name[1]); b = undecchar(de->d_name[2]); if (a < 0 || b < 0) continue; fpath = strjoin(*p, "/", de->d_name, NULL); if (!fpath) { r = log_oom(); goto finish; } name = sysv_translate_name(de->d_name + 3); if (!name) { r = log_oom(); goto finish; } service = hashmap_get(all_services, name); if (!service){ log_debug("Ignoring %s symlink in %s, not generating %s.", de->d_name, rcnd_table[i].path, name); continue; } if (de->d_name[0] == 'S') { if (rcnd_table[i].type == RUNLEVEL_UP) service->sysv_start_priority = MAX(a*10 + b, service->sysv_start_priority); r = set_ensure_allocated(&runlevel_services[i], NULL); if (r < 0) { log_oom(); goto finish; } r = set_put(runlevel_services[i], service); if (r < 0) { log_oom(); goto finish; } } else if (de->d_name[0] == 'K' && (rcnd_table[i].type == RUNLEVEL_DOWN)) { r = set_ensure_allocated(&shutdown_services, NULL); if (r < 0) { log_oom(); goto finish; } r = set_put(shutdown_services, service); if (r < 0) { log_oom(); goto finish; } } } } } for (i = 0; i < ELEMENTSOF(rcnd_table); i ++) SET_FOREACH(service, runlevel_services[i], j) { r = strv_extend(&service->before, rcnd_table[i].target); if (r < 0) { log_oom(); goto finish; } r = strv_extend(&service->wanted_by, rcnd_table[i].target); if (r < 0) { log_oom(); goto finish; } } SET_FOREACH(service, shutdown_services, j) { r = strv_extend(&service->before, SPECIAL_SHUTDOWN_TARGET); if (r < 0) { log_oom(); goto finish; } r = strv_extend(&service->conflicts, SPECIAL_SHUTDOWN_TARGET); if (r < 0) { log_oom(); goto finish; } } r = 0; finish: for (i = 0; i < ELEMENTSOF(rcnd_table); i++) set_free(runlevel_services[i]); return r; } int main(int argc, char *argv[]) { _cleanup_(free_sysvstub_hashmapp) Hashmap *all_services = NULL; _cleanup_lookup_paths_free_ LookupPaths lp = {}; SysvStub *service; Iterator j; int r; if (argc > 1 && argc != 4) { log_error("This program takes three or no arguments."); return EXIT_FAILURE; } if (argc > 1) arg_dest = argv[3]; log_set_target(LOG_TARGET_SAFE); log_parse_environment(); log_open(); umask(0022); r = lookup_paths_init(&lp, MANAGER_SYSTEM, true, NULL, NULL, NULL, NULL); if (r < 0) { log_error_errno(r, "Failed to find lookup paths: %m"); goto finish; } all_services = hashmap_new(&string_hash_ops); if (!all_services) { r = log_oom(); goto finish; } r = enumerate_sysv(&lp, all_services); if (r < 0) goto finish; r = set_dependencies_from_rcnd(&lp, all_services); if (r < 0) goto finish; HASHMAP_FOREACH(service, all_services, j) (void) load_sysv(service); HASHMAP_FOREACH(service, all_services, j) { (void) fix_order(service, all_services); (void) generate_unit_file(service); } r = 0; finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/test/000077500000000000000000000000001265713322000146275ustar00rootroot00000000000000systemd-229/src/test/.gitignore000066400000000000000000000000271265713322000166160ustar00rootroot00000000000000test-hashmap-ordered.c systemd-229/src/test/Makefile000077700000000000000000000000001265713322000201352../Makefileustar00rootroot00000000000000systemd-229/src/test/test-acl-util.c000066400000000000000000000043561265713322000174720ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "acl-util.h" #include "fd-util.h" #include "fileio.h" #include "string-util.h" #include "user-util.h" static void test_add_acls_for_user(void) { char fn[] = "/tmp/test-empty.XXXXXX"; _cleanup_close_ int fd = -1; char *cmd; uid_t uid; int r; fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); /* Use the mode that user journal files use */ assert_se(fchmod(fd, 0640) == 0); cmd = strjoina("ls -l ", fn); assert_se(system(cmd) == 0); cmd = strjoina("getfacl -p ", fn); assert_se(system(cmd) == 0); if (getuid() == 0) { const char *nobody = "nobody"; r = get_user_creds(&nobody, &uid, NULL, NULL, NULL); if (r < 0) uid = 0; } else uid = getuid(); r = add_acls_for_user(fd, uid); assert_se(r >= 0); cmd = strjoina("ls -l ", fn); assert_se(system(cmd) == 0); cmd = strjoina("getfacl -p ", fn); assert_se(system(cmd) == 0); /* set the acls again */ r = add_acls_for_user(fd, uid); assert_se(r >= 0); cmd = strjoina("ls -l ", fn); assert_se(system(cmd) == 0); cmd = strjoina("getfacl -p ", fn); assert_se(system(cmd) == 0); unlink(fn); } int main(int argc, char **argv) { test_add_acls_for_user(); return 0; } systemd-229/src/test/test-af-list.c000066400000000000000000000027151265713322000173140ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2015 Daniel Mack systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "macro.h" #include "string-util.h" #include "util.h" static const struct af_name* lookup_af(register const char *str, register unsigned int len); #include "af-from-name.h" #include "af-list.h" #include "af-to-name.h" int main(int argc, const char *argv[]) { unsigned int i; for (i = 0; i < ELEMENTSOF(af_names); i++) { if (af_names[i]) { assert_se(streq(af_to_name(i), af_names[i])); assert_se(af_from_name(af_names[i]) == (int) i); } } assert_se(af_to_name(af_max()) == NULL); assert_se(af_to_name(-1) == NULL); assert_se(af_from_name("huddlduddl") == AF_UNSPEC); return 0; } systemd-229/src/test/test-architecture.c000066400000000000000000000030371265713322000204350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "architecture.h" #include "log.h" #include "util.h" #include "virt.h" int main(int argc, char *argv[]) { int a, v; v = detect_virtualization(); if (v == -EPERM || v == -EACCES) return EXIT_TEST_SKIP; assert_se(v >= 0); log_info("virtualization=%s id=%s", VIRTUALIZATION_IS_CONTAINER(v) ? "container" : VIRTUALIZATION_IS_VM(v) ? "vm" : "n/a", virtualization_to_string(v)); a = uname_architecture(); assert_se(a >= 0); log_info("uname architecture=%s", architecture_to_string(a)); a = native_architecture(); assert_se(a >= 0); log_info("native architecture=%s", architecture_to_string(a)); log_info("primary library architecture=" LIB_ARCH_TUPLE); return 0; } systemd-229/src/test/test-arphrd-list.c000066400000000000000000000030001265713322000201720ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2015 Daniel Mack systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "macro.h" #include "string-util.h" #include "util.h" static const struct arphrd_name* lookup_arphrd(register const char *str, register unsigned int len); #include "arphrd-from-name.h" #include "arphrd-list.h" #include "arphrd-to-name.h" int main(int argc, const char *argv[]) { unsigned int i; for (i = 1; i < ELEMENTSOF(arphrd_names); i++) { if (arphrd_names[i]) { assert_se(streq(arphrd_to_name(i), arphrd_names[i])); assert_se(arphrd_from_name(arphrd_names[i]) == (int) i); } } assert_se(arphrd_to_name(arphrd_max()) == NULL); assert_se(arphrd_to_name(0) == NULL); assert_se(arphrd_from_name("huddlduddl") == 0); return 0; } systemd-229/src/test/test-ask-password-api.c000066400000000000000000000021231265713322000211330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2016 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "ask-password-api.h" #include "log.h" static void ask_password(void) { int r; _cleanup_free_ char *ret; r = ask_password_tty("hello?", "da key", 0, 0, NULL, &ret); assert(r >= 0); log_info("Got %s", ret); } int main(int argc, char **argv) { log_parse_environment(); ask_password(); } systemd-229/src/test/test-async.c000066400000000000000000000025771265713322000171000ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2014 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "async.h" #include "fileio.h" #include "macro.h" #include "util.h" static bool test_async = false; static void *async_func(void *arg) { test_async = true; return NULL; } int main(int argc, char *argv[]) { int fd; char name[] = "/tmp/test-asynchronous_close.XXXXXX"; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); asynchronous_close(fd); assert_se(asynchronous_job(async_func, NULL) >= 0); assert_se(asynchronous_sync() >= 0); sleep(1); assert_se(fcntl(fd, F_GETFD) == -1); assert_se(test_async); unlink(name); return 0; } systemd-229/src/test/test-barrier.c000066400000000000000000000431301265713322000173770ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 David Herrmann systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* * IPC barrier tests * These tests verify the correct behavior of the IPC Barrier implementation. * Note that the tests use alarm-timers to verify dead-locks and timeouts. These * might not work on slow machines where 20ms are too short to perform specific * operations (though, very unlikely). In case that turns out true, we have to * increase it at the slightly cost of lengthen test-duration on other machines. */ #include #include #include #include #include "barrier.h" #include "util.h" /* 20ms to test deadlocks; All timings use multiples of this constant as * alarm/sleep timers. If this timeout is too small for slow machines to perform * the requested operations, we have to increase it. On an i7 this works fine * with 1ms base-time, so 20ms should be just fine for everyone. */ #define BASE_TIME (20 * USEC_PER_MSEC) static void set_alarm(usec_t usecs) { struct itimerval v = { }; timeval_store(&v.it_value, usecs); assert_se(setitimer(ITIMER_REAL, &v, NULL) >= 0); } static void sleep_for(usec_t usecs) { /* stupid usleep() might fail if >1000000 */ assert_se(usecs < USEC_PER_SEC); usleep(usecs); } #define TEST_BARRIER(_FUNCTION, _CHILD_CODE, _WAIT_CHILD, _PARENT_CODE, _WAIT_PARENT) \ static void _FUNCTION(void) { \ Barrier b = BARRIER_NULL; \ pid_t pid1, pid2; \ \ assert_se(barrier_create(&b) >= 0); \ assert_se(b.me > 0); \ assert_se(b.them > 0); \ assert_se(b.pipe[0] > 0); \ assert_se(b.pipe[1] > 0); \ \ pid1 = fork(); \ assert_se(pid1 >= 0); \ if (pid1 == 0) { \ barrier_set_role(&b, BARRIER_CHILD); \ { _CHILD_CODE; } \ exit(42); \ } \ \ pid2 = fork(); \ assert_se(pid2 >= 0); \ if (pid2 == 0) { \ barrier_set_role(&b, BARRIER_PARENT); \ { _PARENT_CODE; } \ exit(42); \ } \ \ barrier_destroy(&b); \ set_alarm(999999); \ { _WAIT_CHILD; } \ { _WAIT_PARENT; } \ set_alarm(0); \ } #define TEST_BARRIER_WAIT_SUCCESS(_pid) \ ({ \ int pidr, status; \ pidr = waitpid(_pid, &status, 0); \ assert_se(pidr == _pid); \ assert_se(WIFEXITED(status)); \ assert_se(WEXITSTATUS(status) == 42); \ }) #define TEST_BARRIER_WAIT_ALARM(_pid) \ ({ \ int pidr, status; \ pidr = waitpid(_pid, &status, 0); \ assert_se(pidr == _pid); \ assert_se(WIFSIGNALED(status)); \ assert_se(WTERMSIG(status) == SIGALRM); \ }) /* * Test basic sync points * This places a barrier in both processes and waits synchronously for them. * The timeout makes sure the sync works as expected. The sleep_for() on one side * makes sure the exit of the parent does not overwrite previous barriers. Due * to the sleep_for(), we know that the parent already exited, thus there's a * pending HUP on the pipe. However, the barrier_sync() prefers reads on the * eventfd, thus we can safely wait on the barrier. */ TEST_BARRIER(test_barrier_sync, ({ set_alarm(BASE_TIME * 10); assert_se(barrier_place(&b)); sleep_for(BASE_TIME * 2); assert_se(barrier_sync(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid1), ({ set_alarm(BASE_TIME * 10); assert_se(barrier_place(&b)); assert_se(barrier_sync(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test wait_next() * This places a barrier in the parent and syncs on it. The child sleeps while * the parent places the barrier and then waits for a barrier. The wait will * succeed as the child hasn't read the parent's barrier, yet. The following * barrier and sync synchronize the exit. */ TEST_BARRIER(test_barrier_wait_next, ({ sleep_for(BASE_TIME); set_alarm(BASE_TIME * 10); assert_se(barrier_wait_next(&b)); assert_se(barrier_place(&b)); assert_se(barrier_sync(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid1), ({ set_alarm(BASE_TIME * 4); assert_se(barrier_place(&b)); assert_se(barrier_sync(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test wait_next() multiple times * This places two barriers in the parent and waits for the child to exit. The * child sleeps 20ms so both barriers _should_ be in place. It then waits for * the parent to place the next barrier twice. The first call will fetch both * barriers and return. However, the second call will stall as the parent does * not place a 3rd barrier (the sleep caught two barriers). wait_next() is does * not look at barrier-links so this stall is expected. Thus this test times * out. */ TEST_BARRIER(test_barrier_wait_next_twice, ({ sleep_for(BASE_TIME); set_alarm(BASE_TIME); assert_se(barrier_wait_next(&b)); assert_se(barrier_wait_next(&b)); assert_se(0); }), TEST_BARRIER_WAIT_ALARM(pid1), ({ set_alarm(BASE_TIME * 10); assert_se(barrier_place(&b)); assert_se(barrier_place(&b)); sleep_for(BASE_TIME * 4); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test wait_next() with local barriers * This is the same as test_barrier_wait_next_twice, but places local barriers * between both waits. This does not have any effect on the wait so it times out * like the other test. */ TEST_BARRIER(test_barrier_wait_next_twice_local, ({ sleep_for(BASE_TIME); set_alarm(BASE_TIME); assert_se(barrier_wait_next(&b)); assert_se(barrier_place(&b)); assert_se(barrier_place(&b)); assert_se(barrier_wait_next(&b)); assert_se(0); }), TEST_BARRIER_WAIT_ALARM(pid1), ({ set_alarm(BASE_TIME * 10); assert_se(barrier_place(&b)); assert_se(barrier_place(&b)); sleep_for(BASE_TIME * 4); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test wait_next() with sync_next() * This is again the same as test_barrier_wait_next_twice but uses a * synced wait as the second wait. This works just fine because the local state * has no barriers placed, therefore, the remote is always in sync. */ TEST_BARRIER(test_barrier_wait_next_twice_sync, ({ sleep_for(BASE_TIME); set_alarm(BASE_TIME); assert_se(barrier_wait_next(&b)); assert_se(barrier_sync_next(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid1), ({ set_alarm(BASE_TIME * 10); assert_se(barrier_place(&b)); assert_se(barrier_place(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test wait_next() with sync_next() and local barriers * This is again the same as test_barrier_wait_next_twice_local but uses a * synced wait as the second wait. This works just fine because the local state * is in sync with the remote. */ TEST_BARRIER(test_barrier_wait_next_twice_local_sync, ({ sleep_for(BASE_TIME); set_alarm(BASE_TIME); assert_se(barrier_wait_next(&b)); assert_se(barrier_place(&b)); assert_se(barrier_place(&b)); assert_se(barrier_sync_next(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid1), ({ set_alarm(BASE_TIME * 10); assert_se(barrier_place(&b)); assert_se(barrier_place(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test sync_next() and sync() * This tests sync_*() synchronizations and makes sure they work fine if the * local state is behind the remote state. */ TEST_BARRIER(test_barrier_sync_next, ({ set_alarm(BASE_TIME * 10); assert_se(barrier_sync_next(&b)); assert_se(barrier_sync(&b)); assert_se(barrier_place(&b)); assert_se(barrier_place(&b)); assert_se(barrier_sync_next(&b)); assert_se(barrier_sync_next(&b)); assert_se(barrier_sync(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid1), ({ set_alarm(BASE_TIME * 10); sleep_for(BASE_TIME); assert_se(barrier_place(&b)); assert_se(barrier_place(&b)); assert_se(barrier_sync(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test sync_next() and sync() with local barriers * This tests timeouts if sync_*() is used if local barriers are placed but the * remote didn't place any. */ TEST_BARRIER(test_barrier_sync_next_local, ({ set_alarm(BASE_TIME); assert_se(barrier_place(&b)); assert_se(barrier_sync_next(&b)); assert_se(0); }), TEST_BARRIER_WAIT_ALARM(pid1), ({ sleep_for(BASE_TIME * 2); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test sync_next() and sync() with local barriers and abortion * This is the same as test_barrier_sync_next_local but aborts the sync in the * parent. Therefore, the sync_next() succeeds just fine due to the abortion. */ TEST_BARRIER(test_barrier_sync_next_local_abort, ({ set_alarm(BASE_TIME * 10); assert_se(barrier_place(&b)); assert_se(!barrier_sync_next(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid1), ({ assert_se(barrier_abort(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test matched wait_abortion() * This runs wait_abortion() with remote abortion. */ TEST_BARRIER(test_barrier_wait_abortion, ({ set_alarm(BASE_TIME * 10); assert_se(barrier_wait_abortion(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid1), ({ assert_se(barrier_abort(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test unmatched wait_abortion() * This runs wait_abortion() without any remote abortion going on. It thus must * timeout. */ TEST_BARRIER(test_barrier_wait_abortion_unmatched, ({ set_alarm(BASE_TIME); assert_se(barrier_wait_abortion(&b)); assert_se(0); }), TEST_BARRIER_WAIT_ALARM(pid1), ({ sleep_for(BASE_TIME * 2); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test matched wait_abortion() with local abortion * This runs wait_abortion() with local and remote abortion. */ TEST_BARRIER(test_barrier_wait_abortion_local, ({ set_alarm(BASE_TIME * 10); assert_se(barrier_abort(&b)); assert_se(!barrier_wait_abortion(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid1), ({ assert_se(barrier_abort(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test unmatched wait_abortion() with local abortion * This runs wait_abortion() with only local abortion. This must time out. */ TEST_BARRIER(test_barrier_wait_abortion_local_unmatched, ({ set_alarm(BASE_TIME); assert_se(barrier_abort(&b)); assert_se(!barrier_wait_abortion(&b)); assert_se(0); }), TEST_BARRIER_WAIT_ALARM(pid1), ({ sleep_for(BASE_TIME * 2); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test child exit * Place barrier and sync with the child. The child only exits()s, which should * cause an implicit abortion and wake the parent. */ TEST_BARRIER(test_barrier_exit, ({ }), TEST_BARRIER_WAIT_SUCCESS(pid1), ({ set_alarm(BASE_TIME * 10); assert_se(barrier_place(&b)); assert_se(!barrier_sync(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); /* * Test child exit with sleep * Same as test_barrier_exit but verifies the test really works due to the * child-exit. We add a usleep() which triggers the alarm in the parent and * causes the test to time out. */ TEST_BARRIER(test_barrier_no_exit, ({ sleep_for(BASE_TIME * 2); }), TEST_BARRIER_WAIT_SUCCESS(pid1), ({ set_alarm(BASE_TIME); assert_se(barrier_place(&b)); assert_se(!barrier_sync(&b)); }), TEST_BARRIER_WAIT_ALARM(pid2)); /* * Test pending exit against sync * The parent places a barrier *and* exits. The 20ms wait in the child * guarantees both are pending. However, our logic prefers pending barriers over * pending exit-abortions (unlike normal abortions), thus the wait_next() must * succeed, same for the sync_next() as our local barrier-count is smaller than * the remote. Once we place a barrier our count is equal, so the sync still * succeeds. Only if we place one more barrier, we're ahead of the remote, thus * we will fail due to HUP on the pipe. */ TEST_BARRIER(test_barrier_pending_exit, ({ set_alarm(BASE_TIME * 4); sleep_for(BASE_TIME * 2); assert_se(barrier_wait_next(&b)); assert_se(barrier_sync_next(&b)); assert_se(barrier_place(&b)); assert_se(barrier_sync_next(&b)); assert_se(barrier_place(&b)); assert_se(!barrier_sync_next(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid1), ({ assert_se(barrier_place(&b)); }), TEST_BARRIER_WAIT_SUCCESS(pid2)); int main(int argc, char *argv[]) { /* * This test uses real-time alarms and sleeps to test for CPU races * explicitly. This is highly fragile if your system is under load. We * already increased the BASE_TIME value to make the tests more robust, * but that just makes the test take significantly longer. Hence, * disable the test by default, so it will not break CI. */ if (argc < 2) return EXIT_TEST_SKIP; log_parse_environment(); log_open(); test_barrier_sync(); test_barrier_wait_next(); test_barrier_wait_next_twice(); test_barrier_wait_next_twice_sync(); test_barrier_wait_next_twice_local(); test_barrier_wait_next_twice_local_sync(); test_barrier_sync_next(); test_barrier_sync_next_local(); test_barrier_sync_next_local_abort(); test_barrier_wait_abortion(); test_barrier_wait_abortion_unmatched(); test_barrier_wait_abortion_local(); test_barrier_wait_abortion_local_unmatched(); test_barrier_exit(); test_barrier_no_exit(); test_barrier_pending_exit(); return 0; } systemd-229/src/test/test-bitmap.c000066400000000000000000000073221265713322000172300ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "bitmap.h" int main(int argc, const char *argv[]) { _cleanup_bitmap_free_ Bitmap *b = NULL, *b2 = NULL; Iterator it; unsigned n = (unsigned) -1, i = 0; b = bitmap_new(); assert_se(b); assert_se(bitmap_ensure_allocated(&b) == 0); bitmap_free(b); b = NULL; assert_se(bitmap_ensure_allocated(&b) == 0); assert_se(bitmap_isset(b, 0) == false); assert_se(bitmap_isset(b, 1) == false); assert_se(bitmap_isset(b, 256) == false); assert_se(bitmap_isclear(b) == true); assert_se(bitmap_set(b, 0) == 0); assert_se(bitmap_isset(b, 0) == true); assert_se(bitmap_isclear(b) == false); bitmap_unset(b, 0); assert_se(bitmap_isset(b, 0) == false); assert_se(bitmap_isclear(b) == true); assert_se(bitmap_set(b, 1) == 0); assert_se(bitmap_isset(b, 1) == true); assert_se(bitmap_isclear(b) == false); bitmap_unset(b, 1); assert_se(bitmap_isset(b, 1) == false); assert_se(bitmap_isclear(b) == true); assert_se(bitmap_set(b, 256) == 0); assert_se(bitmap_isset(b, 256) == true); assert_se(bitmap_isclear(b) == false); bitmap_unset(b, 256); assert_se(bitmap_isset(b, 256) == false); assert_se(bitmap_isclear(b) == true); assert_se(bitmap_set(b, 32) == 0); bitmap_unset(b, 0); assert_se(bitmap_isset(b, 32) == true); bitmap_unset(b, 32); BITMAP_FOREACH(n, NULL, it) assert_not_reached("NULL bitmap"); assert_se(bitmap_set(b, 0) == 0); assert_se(bitmap_set(b, 1) == 0); assert_se(bitmap_set(b, 256) == 0); BITMAP_FOREACH(n, b, it) { assert_se(n == i); if (i == 0) i = 1; else if (i == 1) i = 256; else if (i == 256) i = (unsigned) -1; } assert_se(i == (unsigned) -1); i = 0; BITMAP_FOREACH(n, b, it) { assert_se(n == i); if (i == 0) i = 1; else if (i == 1) i = 256; else if (i == 256) i = (unsigned) -1; } assert_se(i == (unsigned) -1); bitmap_clear(b); assert_se(bitmap_isclear(b) == true); assert_se(bitmap_set(b, (unsigned) -1) == -ERANGE); bitmap_free(b); b = NULL; assert_se(bitmap_ensure_allocated(&b) == 0); assert_se(bitmap_ensure_allocated(&b2) == 0); assert_se(bitmap_equal(b, b2)); assert_se(bitmap_set(b, 0) == 0); bitmap_unset(b, 0); assert_se(bitmap_equal(b, b2)); assert_se(bitmap_set(b, 1) == 0); bitmap_clear(b); assert_se(bitmap_equal(b, b2)); assert_se(bitmap_set(b, 0) == 0); assert_se(bitmap_set(b2, 0) == 0); assert_se(bitmap_equal(b, b2)); return 0; } systemd-229/src/test/test-boot-timestamps.c000066400000000000000000000065461265713322000211120ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering Copyright 2013 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "acpi-fpdt.h" #include "boot-timestamps.h" #include "efivars.h" #include "log.h" #include "util.h" static int test_acpi_fpdt(void) { usec_t loader_start; usec_t loader_exit; char ts_start[FORMAT_TIMESPAN_MAX]; char ts_exit[FORMAT_TIMESPAN_MAX]; char ts_span[FORMAT_TIMESPAN_MAX]; int r; r = acpi_get_boot_usec(&loader_start, &loader_exit); if (r < 0) { if (r != -ENOENT) log_error_errno(r, "Failed to read ACPI FPDT: %m"); return r; } log_info("ACPI FPDT: loader start=%s exit=%s duration=%s", format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC), format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC), format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC)); return 0; } static int test_efi_loader(void) { usec_t loader_start; usec_t loader_exit; char ts_start[FORMAT_TIMESPAN_MAX]; char ts_exit[FORMAT_TIMESPAN_MAX]; char ts_span[FORMAT_TIMESPAN_MAX]; int r; r = efi_loader_get_boot_usec(&loader_start, &loader_exit); if (r < 0) { if (r != -ENOENT) log_error_errno(r, "Failed to read EFI loader data: %m"); return r; } log_info("EFI Loader: start=%s exit=%s duration=%s", format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC), format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC), format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC)); return 0; } int main(int argc, char* argv[]) { char s[MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)]; int r; dual_timestamp fw, l, k; test_acpi_fpdt(); test_efi_loader(); dual_timestamp_from_monotonic(&k, 0); r = boot_timestamps(NULL, &fw, &l); if (r < 0) { log_error_errno(r, "Failed to read variables: %m"); return 1; } log_info("Firmware began %s before kernel.", format_timespan(s, sizeof(s), fw.monotonic, 0)); log_info("Loader began %s before kernel.", format_timespan(s, sizeof(s), l.monotonic, 0)); log_info("Firmware began %s.", format_timestamp(s, sizeof(s), fw.realtime)); log_info("Loader began %s.", format_timestamp(s, sizeof(s), l.realtime)); log_info("Kernel began %s.", format_timestamp(s, sizeof(s), k.realtime)); return 0; } systemd-229/src/test/test-btrfs.c000066400000000000000000000173241265713322000170770ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "btrfs-util.h" #include "fd-util.h" #include "fileio.h" #include "log.h" #include "parse-util.h" #include "string-util.h" #include "util.h" int main(int argc, char *argv[]) { BtrfsQuotaInfo quota; int r, fd; fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY); if (fd < 0) log_error_errno(errno, "Failed to open root directory: %m"); else { char ts[FORMAT_TIMESTAMP_MAX], bs[FORMAT_BYTES_MAX]; BtrfsSubvolInfo info; r = btrfs_subvol_get_info_fd(fd, 0, &info); if (r < 0) log_error_errno(r, "Failed to get subvolume info: %m"); else { log_info("otime: %s", format_timestamp(ts, sizeof(ts), info.otime)); log_info("read-only (search): %s", yes_no(info.read_only)); } r = btrfs_qgroup_get_quota_fd(fd, 0, "a); if (r < 0) log_error_errno(r, "Failed to get quota info: %m"); else { log_info("referenced: %s", strna(format_bytes(bs, sizeof(bs), quota.referenced))); log_info("exclusive: %s", strna(format_bytes(bs, sizeof(bs), quota.exclusive))); log_info("referenced_max: %s", strna(format_bytes(bs, sizeof(bs), quota.referenced_max))); log_info("exclusive_max: %s", strna(format_bytes(bs, sizeof(bs), quota.exclusive_max))); } r = btrfs_subvol_get_read_only_fd(fd); if (r < 0) log_error_errno(r, "Failed to get read only flag: %m"); else log_info("read-only (ioctl): %s", yes_no(r)); safe_close(fd); } r = btrfs_subvol_make("/xxxtest"); if (r < 0) log_error_errno(r, "Failed to make subvolume: %m"); r = write_string_file("/xxxtest/afile", "ljsadhfljasdkfhlkjdsfha", WRITE_STRING_FILE_CREATE); if (r < 0) log_error_errno(r, "Failed to write file: %m"); r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest2", 0); if (r < 0) log_error_errno(r, "Failed to make snapshot: %m"); r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest3", BTRFS_SNAPSHOT_READ_ONLY); if (r < 0) log_error_errno(r, "Failed to make snapshot: %m"); r = btrfs_subvol_remove("/xxxtest", BTRFS_REMOVE_QUOTA); if (r < 0) log_error_errno(r, "Failed to remove subvolume: %m"); r = btrfs_subvol_remove("/xxxtest2", BTRFS_REMOVE_QUOTA); if (r < 0) log_error_errno(r, "Failed to remove subvolume: %m"); r = btrfs_subvol_remove("/xxxtest3", BTRFS_REMOVE_QUOTA); if (r < 0) log_error_errno(r, "Failed to remove subvolume: %m"); r = btrfs_subvol_snapshot("/etc", "/etc2", BTRFS_SNAPSHOT_READ_ONLY|BTRFS_SNAPSHOT_FALLBACK_COPY); if (r < 0) log_error_errno(r, "Failed to make snapshot: %m"); r = btrfs_subvol_remove("/etc2", BTRFS_REMOVE_QUOTA); if (r < 0) log_error_errno(r, "Failed to remove subvolume: %m"); r = btrfs_subvol_make("/xxxrectest"); if (r < 0) log_error_errno(r, "Failed to make subvolume: %m"); r = btrfs_subvol_make("/xxxrectest/xxxrectest2"); if (r < 0) log_error_errno(r, "Failed to make subvolume: %m"); r = btrfs_subvol_make("/xxxrectest/xxxrectest3"); if (r < 0) log_error_errno(r, "Failed to make subvolume: %m"); r = btrfs_subvol_make("/xxxrectest/xxxrectest3/sub"); if (r < 0) log_error_errno(r, "Failed to make subvolume: %m"); if (mkdir("/xxxrectest/dir", 0755) < 0) log_error_errno(errno, "Failed to make directory: %m"); r = btrfs_subvol_make("/xxxrectest/dir/xxxrectest4"); if (r < 0) log_error_errno(r, "Failed to make subvolume: %m"); if (mkdir("/xxxrectest/dir/xxxrectest4/dir", 0755) < 0) log_error_errno(errno, "Failed to make directory: %m"); r = btrfs_subvol_make("/xxxrectest/dir/xxxrectest4/dir/xxxrectest5"); if (r < 0) log_error_errno(r, "Failed to make subvolume: %m"); if (mkdir("/xxxrectest/mnt", 0755) < 0) log_error_errno(errno, "Failed to make directory: %m"); r = btrfs_subvol_snapshot("/xxxrectest", "/xxxrectest2", BTRFS_SNAPSHOT_RECURSIVE); if (r < 0) log_error_errno(r, "Failed to snapshot subvolume: %m"); r = btrfs_subvol_remove("/xxxrectest", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE); if (r < 0) log_error_errno(r, "Failed to recursively remove subvolume: %m"); r = btrfs_subvol_remove("/xxxrectest2", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE); if (r < 0) log_error_errno(r, "Failed to recursively remove subvolume: %m"); r = btrfs_subvol_make("/xxxquotatest"); if (r < 0) log_error_errno(r, "Failed to make subvolume: %m"); r = btrfs_subvol_auto_qgroup("/xxxquotatest", 0, true); if (r < 0) log_error_errno(r, "Failed to set up auto qgroup: %m"); r = btrfs_subvol_make("/xxxquotatest/beneath"); if (r < 0) log_error_errno(r, "Failed to make subvolume: %m"); r = btrfs_subvol_auto_qgroup("/xxxquotatest/beneath", 0, false); if (r < 0) log_error_errno(r, "Failed to set up auto qgroup: %m"); r = btrfs_qgroup_set_limit("/xxxquotatest/beneath", 0, 4ULL * 1024 * 1024 * 1024); if (r < 0) log_error_errno(r, "Failed to set up quota limit: %m"); r = btrfs_subvol_set_subtree_quota_limit("/xxxquotatest", 0, 5ULL * 1024 * 1024 * 1024); if (r < 0) log_error_errno(r, "Failed to set up quota limit: %m"); r = btrfs_subvol_snapshot("/xxxquotatest", "/xxxquotatest2", BTRFS_SNAPSHOT_RECURSIVE|BTRFS_SNAPSHOT_QUOTA); if (r < 0) log_error_errno(r, "Failed to setup snapshot: %m"); r = btrfs_qgroup_get_quota("/xxxquotatest2/beneath", 0, "a); if (r < 0) log_error_errno(r, "Failed to query quota: %m"); assert_se(quota.referenced_max == 4ULL * 1024 * 1024 * 1024); r = btrfs_subvol_get_subtree_quota("/xxxquotatest2", 0, "a); if (r < 0) log_error_errno(r, "Failed to query quota: %m"); assert_se(quota.referenced_max == 5ULL * 1024 * 1024 * 1024); r = btrfs_subvol_remove("/xxxquotatest", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE); if (r < 0) log_error_errno(r, "Failed remove subvolume: %m"); r = btrfs_subvol_remove("/xxxquotatest2", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE); if (r < 0) log_error_errno(r, "Failed remove subvolume: %m"); return 0; } systemd-229/src/test/test-calendarspec.c000066400000000000000000000140701265713322000203760ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "calendarspec.h" #include "string-util.h" #include "util.h" static void test_one(const char *input, const char *output) { CalendarSpec *c; _cleanup_free_ char *p = NULL, *q = NULL; usec_t u; char buf[FORMAT_TIMESTAMP_MAX]; int r; assert_se(calendar_spec_from_string(input, &c) >= 0); assert_se(calendar_spec_to_string(c, &p) >= 0); printf("\"%s\" → \"%s\"\n", input, p); assert_se(streq(p, output)); u = now(CLOCK_REALTIME); r = calendar_spec_next_usec(c, u, &u); printf("Next: %s\n", r < 0 ? strerror(-r) : format_timestamp(buf, sizeof(buf), u)); calendar_spec_free(c); assert_se(calendar_spec_from_string(p, &c) >= 0); assert_se(calendar_spec_to_string(c, &q) >= 0); calendar_spec_free(c); assert_se(streq(q, p)); } static void test_next(const char *input, const char *new_tz, usec_t after, usec_t expect) { CalendarSpec *c; usec_t u; char *old_tz; char buf[FORMAT_TIMESTAMP_MAX]; int r; old_tz = getenv("TZ"); if (old_tz) old_tz = strdupa(old_tz); if (new_tz) assert_se(setenv("TZ", new_tz, 1) >= 0); else assert_se(unsetenv("TZ") >= 0); tzset(); assert_se(calendar_spec_from_string(input, &c) >= 0); printf("\"%s\"\n", input); u = after; r = calendar_spec_next_usec(c, after, &u); printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof(buf), u)); if (expect != (usec_t)-1) assert_se(r >= 0 && u == expect); else assert(r == -ENOENT); calendar_spec_free(c); if (old_tz) assert_se(setenv("TZ", old_tz, 1) >= 0); else assert_se(unsetenv("TZ") >= 0); tzset(); } int main(int argc, char* argv[]) { CalendarSpec *c; test_one("Sat,Thu,Mon-Wed,Sat-Sun", "Mon-Thu,Sat,Sun *-*-* 00:00:00"); test_one("Mon,Sun 12-*-* 2,1:23", "Mon,Sun 2012-*-* 01,02:23:00"); test_one("Wed *-1", "Wed *-*-01 00:00:00"); test_one("Wed-Wed,Wed *-1", "Wed *-*-01 00:00:00"); test_one("Wed, 17:48", "Wed *-*-* 17:48:00"); test_one("Wed-Sat,Tue 12-10-15 1:2:3", "Tue-Sat 2012-10-15 01:02:03"); test_one("*-*-7 0:0:0", "*-*-07 00:00:00"); test_one("10-15", "*-10-15 00:00:00"); test_one("monday *-12-* 17:00", "Mon *-12-* 17:00:00"); test_one("Mon,Fri *-*-3,1,2 *:30:45", "Mon,Fri *-*-01,02,03 *:30:45"); test_one("12,14,13,12:20,10,30", "*-*-* 12,13,14:10,20,30:00"); test_one("mon,fri *-1/2-1,3 *:30:45", "Mon,Fri *-01/2-01,03 *:30:45"); test_one("03-05 08:05:40", "*-03-05 08:05:40"); test_one("08:05:40", "*-*-* 08:05:40"); test_one("05:40", "*-*-* 05:40:00"); test_one("Sat,Sun 12-05 08:05:40", "Sat,Sun *-12-05 08:05:40"); test_one("Sat,Sun 08:05:40", "Sat,Sun *-*-* 08:05:40"); test_one("2003-03-05 05:40", "2003-03-05 05:40:00"); test_one("2003-03-05", "2003-03-05 00:00:00"); test_one("03-05", "*-03-05 00:00:00"); test_one("hourly", "*-*-* *:00:00"); test_one("daily", "*-*-* 00:00:00"); test_one("monthly", "*-*-01 00:00:00"); test_one("weekly", "Mon *-*-* 00:00:00"); test_one("minutely", "*-*-* *:*:00"); test_one("quarterly", "*-01,04,07,10-01 00:00:00"); test_one("semi-annually", "*-01,07-01 00:00:00"); test_one("annually", "*-01-01 00:00:00"); test_one("*:2/3", "*-*-* *:02/3:00"); test_one("2015-10-25 01:00:00 uTc", "2015-10-25 01:00:00 UTC"); test_one("2016-03-27 03:17:00.4200005", "2016-03-27 03:17:00.420001"); test_one("2016-03-27 03:17:00/0.42", "2016-03-27 03:17:00/0.420000"); test_one("2016-03-27 03:17:00/0.42", "2016-03-27 03:17:00/0.420000"); test_next("2016-03-27 03:17:00", "", 12345, 1459048620000000); test_next("2016-03-27 03:17:00", "CET", 12345, 1459041420000000); test_next("2016-03-27 03:17:00", "EET", 12345, -1); test_next("2016-03-27 03:17:00 UTC", NULL, 12345, 1459048620000000); test_next("2016-03-27 03:17:00 UTC", "", 12345, 1459048620000000); test_next("2016-03-27 03:17:00 UTC", "CET", 12345, 1459048620000000); test_next("2016-03-27 03:17:00 UTC", "EET", 12345, 1459048620000000); test_next("2016-03-27 03:17:00.420000001 UTC", "EET", 12345, 1459048620420000); test_next("2016-03-27 03:17:00.4200005 UTC", "EET", 12345, 1459048620420001); test_next("2015-11-13 09:11:23.42", "EET", 12345, 1447398683420000); test_next("2015-11-13 09:11:23.42/1.77", "EET", 1447398683420000, 1447398685190000); test_next("2015-11-13 09:11:23.42/1.77", "EET", 1447398683419999, 1447398683420000); assert_se(calendar_spec_from_string("test", &c) < 0); assert_se(calendar_spec_from_string("", &c) < 0); assert_se(calendar_spec_from_string("7", &c) < 0); assert_se(calendar_spec_from_string("121212:1:2", &c) < 0); assert_se(calendar_spec_from_string("2000-03-05.23 00:00:00", &c) < 0); assert_se(calendar_spec_from_string("2000-03-05 00:00.1:00", &c) < 0); assert_se(calendar_spec_from_string("00:00:00/0.00000001", &c) < 0); return 0; } systemd-229/src/test/test-cap-list.c000066400000000000000000000066711265713322000174760ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "cap-list.h" #include "capability-util.h" #include "fileio.h" #include "parse-util.h" #include "util.h" /* verify the capability parser */ static void test_cap_list(void) { int i; assert_se(!capability_to_name(-1)); assert_se(!capability_to_name(capability_list_length())); for (i = 0; i < capability_list_length(); i++) { const char *n; assert_se(n = capability_to_name(i)); assert_se(capability_from_name(n) == i); printf("%s = %i\n", n, i); } assert_se(capability_from_name("asdfbsd") == -EINVAL); assert_se(capability_from_name("CAP_AUDIT_READ") == CAP_AUDIT_READ); assert_se(capability_from_name("cap_audit_read") == CAP_AUDIT_READ); assert_se(capability_from_name("cAp_aUdIt_rEAd") == CAP_AUDIT_READ); assert_se(capability_from_name("0") == 0); assert_se(capability_from_name("15") == 15); assert_se(capability_from_name("-1") == -EINVAL); for (i = 0; i < capability_list_length(); i++) { _cleanup_cap_free_charp_ char *a = NULL; const char *b; unsigned u; assert_se(a = cap_to_name(i)); /* quit the loop as soon as libcap starts returning * numeric ids, formatted as strings */ if (safe_atou(a, &u) >= 0) break; assert_se(b = capability_to_name(i)); printf("%s vs. %s\n", a, b); assert_se(strcasecmp(a, b) == 0); } } /* verify cap_last_cap() against /proc/sys/kernel/cap_last_cap */ static void test_last_cap_file(void) { _cleanup_free_ char *content = NULL; unsigned long val = 0; int r; r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content); assert_se(r >= 0); r = safe_atolu(content, &val); assert_se(r >= 0); assert_se(val != 0); assert_se(val == cap_last_cap()); } /* verify cap_last_cap() against syscall probing */ static void test_last_cap_probe(void) { unsigned long p = (unsigned long)CAP_LAST_CAP; if (prctl(PR_CAPBSET_READ, p) < 0) { for (p--; p > 0; p --) if (prctl(PR_CAPBSET_READ, p) >= 0) break; } else { for (;; p++) if (prctl(PR_CAPBSET_READ, p+1) < 0) break; } assert_se(p != 0); assert_se(p == cap_last_cap()); } int main(int argc, char *argv[]) { test_cap_list(); test_last_cap_file(); test_last_cap_probe(); return 0; } systemd-229/src/test/test-capability.c000066400000000000000000000143261265713322000200770ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2014 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "capability-util.h" #include "fd-util.h" #include "macro.h" #include "util.h" static uid_t test_uid = -1; static gid_t test_gid = -1; /* We keep CAP_DAC_OVERRIDE to avoid errors with gcov when doing test coverage */ static uint64_t test_flags = 1ULL << CAP_DAC_OVERRIDE; static void fork_test(void (*test_func)(void)) { pid_t pid = 0; pid = fork(); assert_se(pid >= 0); if (pid == 0) { test_func(); exit(0); } else if (pid > 0) { int status; assert_se(waitpid(pid, &status, 0) > 0); assert_se(WIFEXITED(status) && WEXITSTATUS(status) == 0); } } static void show_capabilities(void) { cap_t caps; char *text; caps = cap_get_proc(); assert_se(caps); text = cap_to_text(caps, NULL); assert_se(text); log_info("Capabilities:%s", text); cap_free(caps); cap_free(text); } static int setup_tests(bool *run_ambient) { struct passwd *nobody; int r; nobody = getpwnam("nobody"); if (!nobody) { log_error_errno(errno, "Could not find nobody user: %m"); return -EXIT_TEST_SKIP; } test_uid = nobody->pw_uid; test_gid = nobody->pw_gid; *run_ambient = false; r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0); /* There's support for PR_CAP_AMBIENT if the prctl() call * succeeded or error code was something else than EINVAL. The * EINVAL check should be good enough to rule out false * positives. */ if (r >= 0 || errno != EINVAL) *run_ambient = true; return 0; } static void test_drop_privileges_keep_net_raw(void) { int sock; sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); assert_se(sock >= 0); safe_close(sock); assert_se(drop_privileges(test_uid, test_gid, test_flags | (1ULL << CAP_NET_RAW)) >= 0); assert_se(getuid() == test_uid); assert_se(getgid() == test_gid); show_capabilities(); sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); assert_se(sock >= 0); safe_close(sock); } static void test_drop_privileges_dontkeep_net_raw(void) { int sock; sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); assert_se(sock >= 0); safe_close(sock); assert_se(drop_privileges(test_uid, test_gid, test_flags) >= 0); assert_se(getuid() == test_uid); assert_se(getgid() == test_gid); show_capabilities(); sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); assert_se(sock < 0); } static void test_drop_privileges_fail(void) { assert_se(drop_privileges(test_uid, test_gid, test_flags) >= 0); assert_se(getuid() == test_uid); assert_se(getgid() == test_gid); assert_se(drop_privileges(test_uid, test_gid, test_flags) < 0); assert_se(drop_privileges(0, 0, test_flags) < 0); } static void test_drop_privileges(void) { fork_test(test_drop_privileges_keep_net_raw); fork_test(test_drop_privileges_dontkeep_net_raw); fork_test(test_drop_privileges_fail); } static void test_have_effective_cap(void) { assert_se(have_effective_cap(CAP_KILL)); assert_se(have_effective_cap(CAP_CHOWN)); assert_se(drop_privileges(test_uid, test_gid, test_flags | (1ULL << CAP_KILL)) >= 0); assert_se(getuid() == test_uid); assert_se(getgid() == test_gid); assert_se(have_effective_cap(CAP_KILL)); assert_se(!have_effective_cap(CAP_CHOWN)); } static void test_update_inherited_set(void) { cap_t caps; uint64_t set = 0; cap_flag_value_t fv; caps = cap_get_proc(); assert_se(caps); assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv)); assert(fv == CAP_CLEAR); set = (UINT64_C(1) << CAP_CHOWN); assert_se(!capability_update_inherited_set(caps, set)); assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv)); assert(fv == CAP_SET); cap_free(caps); } static void test_set_ambient_caps(void) { cap_t caps; uint64_t set = 0; cap_flag_value_t fv; caps = cap_get_proc(); assert_se(caps); assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv)); assert(fv == CAP_CLEAR); cap_free(caps); assert_se(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) == 0); set = (UINT64_C(1) << CAP_CHOWN); assert_se(!capability_ambient_set_apply(set, true)); caps = cap_get_proc(); assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv)); assert(fv == CAP_SET); cap_free(caps); assert_se(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) == 1); } int main(int argc, char *argv[]) { int r; bool run_ambient; log_parse_environment(); log_open(); if (getuid() != 0) return EXIT_TEST_SKIP; r = setup_tests(&run_ambient); if (r < 0) return -r; show_capabilities(); test_drop_privileges(); test_update_inherited_set(); fork_test(test_have_effective_cap); if (run_ambient) fork_test(test_set_ambient_caps); return 0; } systemd-229/src/test/test-cgroup-mask.c000066400000000000000000000127061265713322000202060ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 David Strauss systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" #include "manager.h" #include "test-helper.h" #include "unit.h" static int test_cgroup_mask(void) { Manager *m = NULL; Unit *son, *daughter, *parent, *root, *grandchild, *parent_deep; FILE *serial = NULL; FDSet *fdset = NULL; int r; /* Prepare the manager. */ assert_se(set_unit_path(TEST_DIR) >= 0); r = manager_new(MANAGER_USER, true, &m); if (r == -EPERM || r == -EACCES) { puts("manager_new: Permission denied. Skipping test."); return EXIT_TEST_SKIP; } assert_se(r >= 0); /* Turn off all kinds of default accouning, so that we can * verify the masks resulting of our configuration and nothing * else. */ m->default_cpu_accounting = m->default_memory_accounting = m->default_blockio_accounting = m->default_tasks_accounting = false; m->default_tasks_max = (uint64_t) -1; assert_se(r >= 0); assert_se(manager_startup(m, serial, fdset) >= 0); /* Load units and verify hierarchy. */ assert_se(manager_load_unit(m, "parent.slice", NULL, NULL, &parent) >= 0); assert_se(manager_load_unit(m, "son.service", NULL, NULL, &son) >= 0); assert_se(manager_load_unit(m, "daughter.service", NULL, NULL, &daughter) >= 0); assert_se(manager_load_unit(m, "grandchild.service", NULL, NULL, &grandchild) >= 0); assert_se(manager_load_unit(m, "parent-deep.slice", NULL, NULL, &parent_deep) >= 0); assert_se(parent->load_state == UNIT_LOADED); assert_se(son->load_state == UNIT_LOADED); assert_se(daughter->load_state == UNIT_LOADED); assert_se(grandchild->load_state == UNIT_LOADED); assert_se(parent_deep->load_state == UNIT_LOADED); assert_se(UNIT_DEREF(son->slice) == parent); assert_se(UNIT_DEREF(daughter->slice) == parent); assert_se(UNIT_DEREF(parent_deep->slice) == parent); assert_se(UNIT_DEREF(grandchild->slice) == parent_deep); root = UNIT_DEREF(parent->slice); /* Verify per-unit cgroups settings. */ assert_se(unit_get_own_mask(son) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT)); assert_se(unit_get_own_mask(daughter) == 0); assert_se(unit_get_own_mask(grandchild) == 0); assert_se(unit_get_own_mask(parent_deep) == CGROUP_MASK_MEMORY); assert_se(unit_get_own_mask(parent) == CGROUP_MASK_BLKIO); assert_se(unit_get_own_mask(root) == 0); /* Verify aggregation of member masks */ assert_se(unit_get_members_mask(son) == 0); assert_se(unit_get_members_mask(daughter) == 0); assert_se(unit_get_members_mask(grandchild) == 0); assert_se(unit_get_members_mask(parent_deep) == 0); assert_se(unit_get_members_mask(parent) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY)); assert_se(unit_get_members_mask(root) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); /* Verify aggregation of sibling masks. */ assert_se(unit_get_siblings_mask(son) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY)); assert_se(unit_get_siblings_mask(daughter) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY)); assert_se(unit_get_siblings_mask(grandchild) == 0); assert_se(unit_get_siblings_mask(parent_deep) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY)); assert_se(unit_get_siblings_mask(parent) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); assert_se(unit_get_siblings_mask(root) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); /* Verify aggregation of target masks. */ assert_se(unit_get_target_mask(son) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY) & m->cgroup_supported)); assert_se(unit_get_target_mask(daughter) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY) & m->cgroup_supported)); assert_se(unit_get_target_mask(grandchild) == 0); assert_se(unit_get_target_mask(parent_deep) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY) & m->cgroup_supported)); assert_se(unit_get_target_mask(parent) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported)); assert_se(unit_get_target_mask(root) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported)); manager_free(m); return 0; } int main(int argc, char* argv[]) { int rc = 0; TEST_REQ_RUNNING_SYSTEMD(rc = test_cgroup_mask()); return rc; } systemd-229/src/test/test-cgroup-util.c000066400000000000000000000323641265713322000202320ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "cgroup-util.h" #include "dirent-util.h" #include "fd-util.h" #include "formats-util.h" #include "parse-util.h" #include "process-util.h" #include "string-util.h" #include "test-helper.h" #include "user-util.h" #include "util.h" static void check_p_d_u(const char *path, int code, const char *result) { _cleanup_free_ char *unit = NULL; int r; r = cg_path_decode_unit(path, &unit); printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, result, code); assert_se(r == code); assert_se(streq_ptr(unit, result)); } static void test_path_decode_unit(void) { check_p_d_u("getty@tty2.service", 0, "getty@tty2.service"); check_p_d_u("getty@tty2.service/", 0, "getty@tty2.service"); check_p_d_u("getty@tty2.service/xxx", 0, "getty@tty2.service"); check_p_d_u("getty@.service/", -ENXIO, NULL); check_p_d_u("getty@.service", -ENXIO, NULL); check_p_d_u("getty.service", 0, "getty.service"); check_p_d_u("getty", -ENXIO, NULL); check_p_d_u("getty/waldo", -ENXIO, NULL); check_p_d_u("_cpu.service", 0, "cpu.service"); } static void check_p_g_u(const char *path, int code, const char *result) { _cleanup_free_ char *unit = NULL; int r; r = cg_path_get_unit(path, &unit); printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, result, code); assert_se(r == code); assert_se(streq_ptr(unit, result)); } static void test_path_get_unit(void) { check_p_g_u("/system.slice/foobar.service/sdfdsaf", 0, "foobar.service"); check_p_g_u("/system.slice/getty@tty5.service", 0, "getty@tty5.service"); check_p_g_u("/system.slice/getty@tty5.service/aaa/bbb", 0, "getty@tty5.service"); check_p_g_u("/system.slice/getty@tty5.service/", 0, "getty@tty5.service"); check_p_g_u("/system.slice/getty@tty6.service/tty5", 0, "getty@tty6.service"); check_p_g_u("sadfdsafsda", -ENXIO, NULL); check_p_g_u("/system.slice/getty####@tty6.service/xxx", -ENXIO, NULL); check_p_g_u("/system.slice/system-waldo.slice/foobar.service/sdfdsaf", 0, "foobar.service"); check_p_g_u("/system.slice/system-waldo.slice/_cpu.service/sdfdsaf", 0, "cpu.service"); check_p_g_u("/user.slice/user-1000.slice/user@1000.service/server.service", 0, "user@1000.service"); check_p_g_u("/user.slice/user-1000.slice/user@.service/server.service", -ENXIO, NULL); } static void check_p_g_u_u(const char *path, int code, const char *result) { _cleanup_free_ char *unit = NULL; int r; r = cg_path_get_user_unit(path, &unit); printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, result, code); assert_se(r == code); assert_se(streq_ptr(unit, result)); } static void test_path_get_user_unit(void) { check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "foobar.service"); check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/waldo.slice/foobar.service", 0, "foobar.service"); check_p_g_u_u("/user.slice/user-1002.slice/session-2.scope/foobar.service/waldo", 0, "foobar.service"); check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar.service/waldo/uuuux", 0, "foobar.service"); check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/waldo/waldo/uuuux", -ENXIO, NULL); check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar@pie.service/pa/po", 0, "foobar@pie.service"); check_p_g_u_u("/session-2.scope/foobar@pie.service/pa/po", 0, "foobar@pie.service"); check_p_g_u_u("/xyz.slice/xyz-waldo.slice/session-77.scope/foobar@pie.service/pa/po", 0, "foobar@pie.service"); check_p_g_u_u("/meh.service", -ENXIO, NULL); check_p_g_u_u("/session-3.scope/_cpu.service", 0, "cpu.service"); check_p_g_u_u("/user.slice/user-1000.slice/user@1000.service/server.service", 0, "server.service"); check_p_g_u_u("/user.slice/user-1000.slice/user@1000.service/foobar.slice/foobar@pie.service", 0, "foobar@pie.service"); check_p_g_u_u("/user.slice/user-1000.slice/user@.service/server.service", -ENXIO, NULL); } static void check_p_g_s(const char *path, int code, const char *result) { _cleanup_free_ char *s = NULL; assert_se(cg_path_get_session(path, &s) == code); assert_se(streq_ptr(s, result)); } static void test_path_get_session(void) { check_p_g_s("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "2"); check_p_g_s("/session-3.scope", 0, "3"); check_p_g_s("/session-.scope", -ENXIO, NULL); check_p_g_s("", -ENXIO, NULL); } static void check_p_g_o_u(const char *path, int code, uid_t result) { uid_t uid = 0; assert_se(cg_path_get_owner_uid(path, &uid) == code); assert_se(uid == result); } static void test_path_get_owner_uid(void) { check_p_g_o_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, 1000); check_p_g_o_u("/user.slice/user-1006.slice", 0, 1006); check_p_g_o_u("", -ENXIO, 0); } static void check_p_g_slice(const char *path, int code, const char *result) { _cleanup_free_ char *s = NULL; assert_se(cg_path_get_slice(path, &s) == code); assert_se(streq_ptr(s, result)); } static void test_path_get_slice(void) { check_p_g_slice("/user.slice", 0, "user.slice"); check_p_g_slice("/foobar", 0, "-.slice"); check_p_g_slice("/user.slice/user-waldo.slice", 0, "user-waldo.slice"); check_p_g_slice("", 0, "-.slice"); check_p_g_slice("foobar", 0, "-.slice"); check_p_g_slice("foobar.slice", 0, "foobar.slice"); check_p_g_slice("foo.slice/foo-bar.slice/waldo.service", 0, "foo-bar.slice"); } static void check_p_g_u_slice(const char *path, int code, const char *result) { _cleanup_free_ char *s = NULL; assert_se(cg_path_get_user_slice(path, &s) == code); assert_se(streq_ptr(s, result)); } static void test_path_get_user_slice(void) { check_p_g_u_slice("/user.slice", -ENXIO, NULL); check_p_g_u_slice("/foobar", -ENXIO, NULL); check_p_g_u_slice("/user.slice/user-waldo.slice", -ENXIO, NULL); check_p_g_u_slice("", -ENXIO, NULL); check_p_g_u_slice("foobar", -ENXIO, NULL); check_p_g_u_slice("foobar.slice", -ENXIO, NULL); check_p_g_u_slice("foo.slice/foo-bar.slice/waldo.service", -ENXIO, NULL); check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service", 0, "-.slice"); check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/", 0, "-.slice"); check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service///", 0, "-.slice"); check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/waldo.service", 0, "-.slice"); check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/piep.slice/foo.service", 0, "piep.slice"); check_p_g_u_slice("/foo.slice//foo-bar.slice/user@1000.service/piep.slice//piep-pap.slice//foo.service", 0, "piep-pap.slice"); } static void test_get_paths(void) { _cleanup_free_ char *a = NULL; assert_se(cg_get_root_path(&a) >= 0); log_info("Root = %s", a); } static void test_proc(void) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; int r; d = opendir("/proc"); assert_se(d); FOREACH_DIRENT(de, d, break) { _cleanup_free_ char *path = NULL, *path_shifted = NULL, *session = NULL, *unit = NULL, *user_unit = NULL, *machine = NULL, *slice = NULL; pid_t pid; uid_t uid = UID_INVALID; if (de->d_type != DT_DIR && de->d_type != DT_UNKNOWN) continue; r = parse_pid(de->d_name, &pid); if (r < 0) continue; if (is_kernel_thread(pid)) continue; cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &path); cg_pid_get_path_shifted(pid, NULL, &path_shifted); cg_pid_get_owner_uid(pid, &uid); cg_pid_get_session(pid, &session); cg_pid_get_unit(pid, &unit); cg_pid_get_user_unit(pid, &user_unit); cg_pid_get_machine_name(pid, &machine); cg_pid_get_slice(pid, &slice); printf(PID_FMT"\t%s\t%s\t"UID_FMT"\t%s\t%s\t%s\t%s\t%s\n", pid, path, path_shifted, uid, session, unit, user_unit, machine, slice); } } static void test_escape_one(const char *s, const char *r) { _cleanup_free_ char *b; b = cg_escape(s); assert_se(b); assert_se(streq(b, r)); assert_se(streq(cg_unescape(b), s)); } static void test_escape(void) { test_escape_one("foobar", "foobar"); test_escape_one(".foobar", "_.foobar"); test_escape_one("foobar.service", "foobar.service"); test_escape_one("cgroup.service", "_cgroup.service"); test_escape_one("tasks", "_tasks"); if (access("/sys/fs/cgroup/cpu", F_OK) == 0) test_escape_one("cpu.service", "_cpu.service"); test_escape_one("_foobar", "__foobar"); test_escape_one("", "_"); test_escape_one("_", "__"); test_escape_one(".", "_."); } static void test_controller_is_valid(void) { assert_se(cg_controller_is_valid("foobar")); assert_se(cg_controller_is_valid("foo_bar")); assert_se(cg_controller_is_valid("name=foo")); assert_se(!cg_controller_is_valid("")); assert_se(!cg_controller_is_valid("name=")); assert_se(!cg_controller_is_valid("=")); assert_se(!cg_controller_is_valid("cpu,cpuacct")); assert_se(!cg_controller_is_valid("_")); assert_se(!cg_controller_is_valid("_foobar")); assert_se(!cg_controller_is_valid("tatü")); } static void test_slice_to_path_one(const char *unit, const char *path, int error) { _cleanup_free_ char *ret = NULL; assert_se(cg_slice_to_path(unit, &ret) == error); assert_se(streq_ptr(ret, path)); } static void test_slice_to_path(void) { test_slice_to_path_one("foobar.slice", "foobar.slice", 0); test_slice_to_path_one("foobar-waldo.slice", "foobar.slice/foobar-waldo.slice", 0); test_slice_to_path_one("foobar-waldo.service", NULL, -EINVAL); test_slice_to_path_one("-.slice", "", 0); test_slice_to_path_one("--.slice", NULL, -EINVAL); test_slice_to_path_one("-", NULL, -EINVAL); test_slice_to_path_one("-foo-.slice", NULL, -EINVAL); test_slice_to_path_one("-foo.slice", NULL, -EINVAL); test_slice_to_path_one("foo-.slice", NULL, -EINVAL); test_slice_to_path_one("foo--bar.slice", NULL, -EINVAL); test_slice_to_path_one("foo.slice/foo--bar.slice", NULL, -EINVAL); test_slice_to_path_one("a-b.slice", "a.slice/a-b.slice", 0); test_slice_to_path_one("a-b-c-d-e.slice", "a.slice/a-b.slice/a-b-c.slice/a-b-c-d.slice/a-b-c-d-e.slice", 0); } static void test_shift_path_one(const char *raw, const char *root, const char *shifted) { const char *s = NULL; assert_se(cg_shift_path(raw, root, &s) >= 0); assert_se(streq(s, shifted)); } static void test_shift_path(void) { test_shift_path_one("/foobar/waldo", "/", "/foobar/waldo"); test_shift_path_one("/foobar/waldo", "", "/foobar/waldo"); test_shift_path_one("/foobar/waldo", "/foobar", "/waldo"); test_shift_path_one("/foobar/waldo", "/fuckfuck", "/foobar/waldo"); } static void test_mask_supported(void) { CGroupMask m; CGroupController c; assert_se(cg_mask_supported(&m) >= 0); for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) printf("'%s' is supported: %s\n", cgroup_controller_to_string(c), yes_no(m & CGROUP_CONTROLLER_TO_MASK(c))); } int main(void) { test_path_decode_unit(); test_path_get_unit(); test_path_get_user_unit(); test_path_get_session(); test_path_get_owner_uid(); test_path_get_slice(); test_path_get_user_slice(); TEST_REQ_RUNNING_SYSTEMD(test_get_paths()); test_proc(); TEST_REQ_RUNNING_SYSTEMD(test_escape()); test_controller_is_valid(); test_slice_to_path(); test_shift_path(); TEST_REQ_RUNNING_SYSTEMD(test_mask_supported()); return 0; } systemd-229/src/test/test-cgroup.c000066400000000000000000000101561265713322000172520ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "cgroup-util.h" #include "path-util.h" #include "string-util.h" #include "util.h" int main(int argc, char*argv[]) { char *path; char *c, *p; assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0); assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0); assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0); assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-c") == 0); assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0) == 0); assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0); assert_se(streq(path, "/test-b")); free(path); assert_se(cg_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0) == 0); assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0); assert_se(path_equal(path, "/test-a")); free(path); assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", 0) == 0); assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0); assert_se(path_equal(path, "/test-b/test-d")); free(path); assert_se(cg_get_path(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", NULL, &path) == 0); assert_se(path_equal(path, "/sys/fs/cgroup/systemd/test-b/test-d")); free(path); assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0); assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-b") > 0); assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0); assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0); assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) == 0); assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) > 0); assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", SYSTEMD_CGROUP_CONTROLLER, "/test-a", false, false) > 0); assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0); assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") > 0); assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) > 0); assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) == 0); cg_trim(SYSTEMD_CGROUP_CONTROLLER, "/", false); assert_se(cg_rmdir(SYSTEMD_CGROUP_CONTROLLER, "/test-b") < 0); assert_se(cg_rmdir(SYSTEMD_CGROUP_CONTROLLER, "/test-a") >= 0); assert_se(cg_split_spec("foobar:/", &c, &p) == 0); assert_se(streq(c, "foobar")); assert_se(streq(p, "/")); free(c); free(p); assert_se(cg_split_spec("foobar:", &c, &p) < 0); assert_se(cg_split_spec("foobar:asdfd", &c, &p) < 0); assert_se(cg_split_spec(":///", &c, &p) < 0); assert_se(cg_split_spec(":", &c, &p) < 0); assert_se(cg_split_spec("", &c, &p) < 0); assert_se(cg_split_spec("fo/obar:/", &c, &p) < 0); assert_se(cg_split_spec("/", &c, &p) >= 0); assert_se(c == NULL); assert_se(streq(p, "/")); free(p); assert_se(cg_split_spec("foo", &c, &p) >= 0); assert_se(streq(c, "foo")); assert_se(p == NULL); free(c); return 0; } systemd-229/src/test/test-condition.c000066400000000000000000000206761265713322000177510ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2014 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-id128.h" #include "alloc-util.h" #include "apparmor-util.h" #include "architecture.h" #include "audit-util.h" #include "condition.h" #include "hostname-util.h" #include "ima-util.h" #include "log.h" #include "macro.h" #include "selinux-util.h" #include "smack-util.h" #include "util.h" static void test_condition_test_path(void) { Condition *condition; condition = condition_new(CONDITION_PATH_EXISTS, "/bin/sh", false, false); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS, "/bin/s?", false, false); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, false); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, true); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_IS_DIRECTORY, "/bin", false, false); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_DIRECTORY_NOT_EMPTY, "/bin", false, false); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_FILE_NOT_EMPTY, "/bin/sh", false, false); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/bin/sh", false, false); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/etc/passwd", false, false); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/proc", false, false); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/", false, false); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/bin", false, false); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_IS_READ_WRITE, "/tmp", false, false); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_IS_SYMBOLIC_LINK, "/dev/stdout", false, false); assert_se(condition_test(condition)); condition_free(condition); } static void test_condition_test_ac_power(void) { Condition *condition; condition = condition_new(CONDITION_AC_POWER, "true", false, false); assert_se(condition_test(condition) == on_ac_power()); condition_free(condition); condition = condition_new(CONDITION_AC_POWER, "false", false, false); assert_se(condition_test(condition) != on_ac_power()); condition_free(condition); condition = condition_new(CONDITION_AC_POWER, "false", false, true); assert_se(condition_test(condition) == on_ac_power()); condition_free(condition); } static void test_condition_test_host(void) { Condition *condition; sd_id128_t id; int r; char sid[SD_ID128_STRING_MAX]; _cleanup_free_ char *hostname = NULL; r = sd_id128_get_machine(&id); assert_se(r >= 0); assert_se(sd_id128_to_string(id, sid)); condition = condition_new(CONDITION_HOST, sid, false, false); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_HOST, sid, false, true); assert_se(!condition_test(condition)); condition_free(condition); hostname = gethostname_malloc(); assert_se(hostname); condition = condition_new(CONDITION_HOST, hostname, false, false); assert_se(condition_test(condition)); condition_free(condition); } static void test_condition_test_architecture(void) { Condition *condition; const char *sa; int a; a = uname_architecture(); assert_se(a >= 0); sa = architecture_to_string(a); assert_se(sa); condition = condition_new(CONDITION_ARCHITECTURE, sa, false, false); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_ARCHITECTURE, "garbage value", false, false); assert_se(condition_test(condition) < 0); condition_free(condition); condition = condition_new(CONDITION_ARCHITECTURE, sa, false, true); assert_se(!condition_test(condition)); condition_free(condition); } static void test_condition_test_kernel_command_line(void) { Condition *condition; condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false); assert_se(!condition_test(condition)); condition_free(condition); } static void test_condition_test_null(void) { Condition *condition; condition = condition_new(CONDITION_NULL, NULL, false, false); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_NULL, NULL, false, true); assert_se(!condition_test(condition)); condition_free(condition); } static void test_condition_test_security(void) { Condition *condition; condition = condition_new(CONDITION_SECURITY, "garbage oifdsjfoidsjoj", false, false); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "selinux", false, true); assert_se(condition_test(condition) != mac_selinux_have()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "ima", false, false); assert_se(condition_test(condition) == use_ima()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "apparmor", false, false); assert_se(condition_test(condition) == mac_apparmor_use()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "smack", false, false); assert_se(condition_test(condition) == mac_smack_use()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "audit", false, false); assert_se(condition_test(condition) == use_audit()); condition_free(condition); } int main(int argc, char *argv[]) { log_parse_environment(); log_open(); test_condition_test_path(); test_condition_test_ac_power(); test_condition_test_host(); test_condition_test_architecture(); test_condition_test_kernel_command_line(); test_condition_test_null(); test_condition_test_security(); return 0; } systemd-229/src/test/test-conf-files.c000066400000000000000000000053371265713322000200050ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Michael Marineau systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "conf-files.h" #include "fs-util.h" #include "macro.h" #include "parse-util.h" #include "rm-rf.h" #include "string-util.h" #include "strv.h" #include "user-util.h" #include "util.h" static void setup_test_dir(char *tmp_dir, const char *files, ...) { va_list ap; assert_se(mkdtemp(tmp_dir) != NULL); va_start(ap, files); while (files != NULL) { _cleanup_free_ char *path = strappend(tmp_dir, files); assert_se(touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID) == 0); files = va_arg(ap, const char *); } va_end(ap); } static void test_conf_files_list(bool use_root) { char tmp_dir[] = "/tmp/test-conf-files-XXXXXX"; _cleanup_strv_free_ char **found_files = NULL; const char *root_dir, *search_1, *search_2, *expect_a, *expect_b; setup_test_dir(tmp_dir, "/dir1/a.conf", "/dir2/a.conf", "/dir2/b.conf", NULL); if (use_root) { root_dir = tmp_dir; search_1 = "/dir1"; search_2 = "/dir2"; } else { root_dir = NULL; search_1 = strjoina(tmp_dir, "/dir1"); search_2 = strjoina(tmp_dir, "/dir2"); } expect_a = strjoina(tmp_dir, "/dir1/a.conf"); expect_b = strjoina(tmp_dir, "/dir2/b.conf"); assert_se(conf_files_list(&found_files, ".conf", root_dir, search_1, search_2, NULL) == 0); strv_print(found_files); assert_se(found_files); assert_se(streq_ptr(found_files[0], expect_a)); assert_se(streq_ptr(found_files[1], expect_b)); assert_se(found_files[2] == NULL); assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0); } int main(int argc, char **argv) { test_conf_files_list(false); test_conf_files_list(true); return 0; } systemd-229/src/test/test-conf-parser.c000066400000000000000000000211361265713322000201720ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "conf-parser.h" #include "log.h" #include "macro.h" #include "string-util.h" #include "strv.h" #include "util.h" static void test_config_parse_path_one(const char *rvalue, const char *expected) { char *path = NULL; assert_se(config_parse_path("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &path, NULL) >= 0); assert_se(streq_ptr(expected, path)); free(path); } static void test_config_parse_log_level_one(const char *rvalue, int expected) { int log_level = 0; assert_se(config_parse_log_level("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &log_level, NULL) >= 0); assert_se(expected == log_level); } static void test_config_parse_log_facility_one(const char *rvalue, int expected) { int log_facility = 0; assert_se(config_parse_log_facility("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &log_facility, NULL) >= 0); assert_se(expected == log_facility); } static void test_config_parse_iec_size_one(const char *rvalue, size_t expected) { size_t iec_size = 0; assert_se(config_parse_iec_size("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &iec_size, NULL) >= 0); assert_se(expected == iec_size); } static void test_config_parse_si_size_one(const char *rvalue, size_t expected) { size_t si_size = 0; assert_se(config_parse_si_size("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &si_size, NULL) >= 0); assert_se(expected == si_size); } static void test_config_parse_int_one(const char *rvalue, int expected) { int v = -1; assert_se(config_parse_int("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); assert_se(expected == v); } static void test_config_parse_unsigned_one(const char *rvalue, unsigned expected) { unsigned v = 0; assert_se(config_parse_unsigned("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); assert_se(expected == v); } static void test_config_parse_strv_one(const char *rvalue, char **expected) { char **strv = 0; assert_se(config_parse_strv("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &strv, NULL) >= 0); assert_se(strv_equal(expected, strv)); strv_free(strv); } static void test_config_parse_mode_one(const char *rvalue, mode_t expected) { mode_t v = 0; assert_se(config_parse_mode("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); assert_se(expected == v); } static void test_config_parse_sec_one(const char *rvalue, usec_t expected) { usec_t v = 0; assert_se(config_parse_sec("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); assert_se(expected == v); } static void test_config_parse_nsec_one(const char *rvalue, nsec_t expected) { nsec_t v = 0; assert_se(config_parse_nsec("unit", "filename", 1, "nsection", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); assert_se(expected == v); } static void test_config_parse_path(void) { test_config_parse_path_one("/path", "/path"); test_config_parse_path_one("/path//////////", "/path"); test_config_parse_path_one("///path/foo///bar////bar//", "/path/foo/bar/bar"); test_config_parse_path_one("not_absolute/path", NULL); } static void test_config_parse_log_level(void) { test_config_parse_log_level_one("debug", LOG_DEBUG); test_config_parse_log_level_one("info", LOG_INFO); test_config_parse_log_level_one("garbage", 0); } static void test_config_parse_log_facility(void) { test_config_parse_log_facility_one("mail", LOG_MAIL); test_config_parse_log_facility_one("user", LOG_USER); test_config_parse_log_facility_one("garbage", 0); } static void test_config_parse_iec_size(void) { test_config_parse_iec_size_one("1024", 1024); test_config_parse_iec_size_one("2K", 2048); test_config_parse_iec_size_one("10M", 10 * 1024 * 1024); test_config_parse_iec_size_one("1G", 1 * 1024 * 1024 * 1024); test_config_parse_iec_size_one("0G", 0); test_config_parse_iec_size_one("0", 0); test_config_parse_iec_size_one("-982", 0); test_config_parse_iec_size_one("49874444198739873000000G", 0); test_config_parse_iec_size_one("garbage", 0); } static void test_config_parse_si_size(void) { test_config_parse_si_size_one("1024", 1024); test_config_parse_si_size_one("2K", 2000); test_config_parse_si_size_one("10M", 10 * 1000 * 1000); test_config_parse_si_size_one("1G", 1 * 1000 * 1000 * 1000); test_config_parse_si_size_one("0G", 0); test_config_parse_si_size_one("0", 0); test_config_parse_si_size_one("-982", 0); test_config_parse_si_size_one("49874444198739873000000G", 0); test_config_parse_si_size_one("garbage", 0); } static void test_config_parse_int(void) { test_config_parse_int_one("1024", 1024); test_config_parse_int_one("-1024", -1024); test_config_parse_int_one("0", 0); test_config_parse_int_one("99999999999999999999999999999999999999999999999999999999", -1); test_config_parse_int_one("-99999999999999999999999999999999999999999999999999999999", -1); test_config_parse_int_one("1G", -1); test_config_parse_int_one("garbage", -1); } static void test_config_parse_unsigned(void) { test_config_parse_unsigned_one("10241024", 10241024); test_config_parse_unsigned_one("1024", 1024); test_config_parse_unsigned_one("0", 0); test_config_parse_unsigned_one("99999999999999999999999999999999999999999999999999999999", 0); test_config_parse_unsigned_one("1G", 0); test_config_parse_unsigned_one("garbage", 0); test_config_parse_unsigned_one("1000garbage", 0); } static void test_config_parse_strv(void) { test_config_parse_strv_one("", STRV_MAKE_EMPTY); test_config_parse_strv_one("foo", STRV_MAKE("foo")); test_config_parse_strv_one("foo bar foo", STRV_MAKE("foo", "bar", "foo")); test_config_parse_strv_one("\"foo bar\" foo", STRV_MAKE("foo bar", "foo")); } static void test_config_parse_mode(void) { test_config_parse_mode_one("777", 0777); test_config_parse_mode_one("644", 0644); test_config_parse_mode_one("-777", 0); test_config_parse_mode_one("999", 0); test_config_parse_mode_one("garbage", 0); test_config_parse_mode_one("777garbage", 0); test_config_parse_mode_one("777 garbage", 0); } static void test_config_parse_sec(void) { test_config_parse_sec_one("1", 1 * USEC_PER_SEC); test_config_parse_sec_one("1s", 1 * USEC_PER_SEC); test_config_parse_sec_one("100ms", 100 * USEC_PER_MSEC); test_config_parse_sec_one("5min 20s", 5 * 60 * USEC_PER_SEC + 20 * USEC_PER_SEC); test_config_parse_sec_one("-1", 0); test_config_parse_sec_one("10foo", 0); test_config_parse_sec_one("garbage", 0); } static void test_config_parse_nsec(void) { test_config_parse_nsec_one("1", 1); test_config_parse_nsec_one("1s", 1 * NSEC_PER_SEC); test_config_parse_nsec_one("100ms", 100 * NSEC_PER_MSEC); test_config_parse_nsec_one("5min 20s", 5 * 60 * NSEC_PER_SEC + 20 * NSEC_PER_SEC); test_config_parse_nsec_one("-1", 0); test_config_parse_nsec_one("10foo", 0); test_config_parse_nsec_one("garbage", 0); } int main(int argc, char **argv) { log_parse_environment(); log_open(); test_config_parse_path(); test_config_parse_log_level(); test_config_parse_log_facility(); test_config_parse_iec_size(); test_config_parse_si_size(); test_config_parse_int(); test_config_parse_unsigned(); test_config_parse_strv(); test_config_parse_mode(); test_config_parse_sec(); test_config_parse_nsec(); return 0; } systemd-229/src/test/test-copy.c000066400000000000000000000134301265713322000167230ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2014 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "copy.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "macro.h" #include "mkdir.h" #include "path-util.h" #include "rm-rf.h" #include "string-util.h" #include "strv.h" #include "util.h" static void test_copy_file(void) { _cleanup_free_ char *buf = NULL; char fn[] = "/tmp/test-copy_file.XXXXXX"; char fn_copy[] = "/tmp/test-copy_file.XXXXXX"; size_t sz = 0; int fd; fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); close(fd); fd = mkostemp_safe(fn_copy, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); close(fd); assert_se(write_string_file(fn, "foo bar bar bar foo", WRITE_STRING_FILE_CREATE) == 0); assert_se(copy_file(fn, fn_copy, 0, 0644, 0) == 0); assert_se(read_full_file(fn_copy, &buf, &sz) == 0); assert_se(streq(buf, "foo bar bar bar foo\n")); assert_se(sz == 20); unlink(fn); unlink(fn_copy); } static void test_copy_file_fd(void) { char in_fn[] = "/tmp/test-copy-file-fd-XXXXXX"; char out_fn[] = "/tmp/test-copy-file-fd-XXXXXX"; _cleanup_close_ int in_fd = -1, out_fd = -1; char text[] = "boohoo\nfoo\n\tbar\n"; char buf[64] = {0}; in_fd = mkostemp_safe(in_fn, O_RDWR); assert_se(in_fd >= 0); out_fd = mkostemp_safe(out_fn, O_RDWR); assert_se(out_fd >= 0); assert_se(write_string_file(in_fn, text, WRITE_STRING_FILE_CREATE) == 0); assert_se(copy_file_fd("/a/file/which/does/not/exist/i/guess", out_fd, true) < 0); assert_se(copy_file_fd(in_fn, out_fd, true) >= 0); assert_se(lseek(out_fd, SEEK_SET, 0) == 0); assert_se(read(out_fd, buf, sizeof(buf)) == sizeof(text) - 1); assert_se(streq(buf, text)); unlink(in_fn); unlink(out_fn); } static void test_copy_tree(void) { char original_dir[] = "/tmp/test-copy_tree/"; char copy_dir[] = "/tmp/test-copy_tree-copy/"; char **files = STRV_MAKE("file", "dir1/file", "dir1/dir2/file", "dir1/dir2/dir3/dir4/dir5/file"); char **links = STRV_MAKE("link", "file", "link2", "dir1/file"); char **p, **link; (void) rm_rf(copy_dir, REMOVE_ROOT|REMOVE_PHYSICAL); (void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL); STRV_FOREACH(p, files) { char *f = strjoina(original_dir, *p); assert_se(mkdir_parents(f, 0755) >= 0); assert_se(write_string_file(f, "file", WRITE_STRING_FILE_CREATE) == 0); } STRV_FOREACH_PAIR(link, p, links) { char *f = strjoina(original_dir, *p); char *l = strjoina(original_dir, *link); assert_se(mkdir_parents(l, 0755) >= 0); assert_se(symlink(f, l) == 0); } assert_se(copy_tree(original_dir, copy_dir, true) == 0); STRV_FOREACH(p, files) { _cleanup_free_ char *buf = NULL; size_t sz = 0; char *f = strjoina(copy_dir, *p); assert_se(access(f, F_OK) == 0); assert_se(read_full_file(f, &buf, &sz) == 0); assert_se(streq(buf, "file\n")); } STRV_FOREACH_PAIR(link, p, links) { _cleanup_free_ char *target = NULL; char *f = strjoina(original_dir, *p); char *l = strjoina(copy_dir, *link); assert_se(readlink_and_canonicalize(l, &target) == 0); assert_se(path_equal(f, target)); } assert_se(copy_tree(original_dir, copy_dir, false) < 0); assert_se(copy_tree("/tmp/inexistent/foo/bar/fsdoi", copy_dir, false) < 0); (void) rm_rf(copy_dir, REMOVE_ROOT|REMOVE_PHYSICAL); (void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL); } static void test_copy_bytes(void) { _cleanup_close_pair_ int pipefd[2] = {-1, -1}; _cleanup_close_ int infd = -1; int r, r2; char buf[1024], buf2[1024]; infd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC); if (infd < 0) infd = open("/etc/os-release", O_RDONLY|O_CLOEXEC); assert_se(infd >= 0); assert_se(pipe2(pipefd, O_CLOEXEC) == 0); r = copy_bytes(infd, pipefd[1], (uint64_t) -1, false); assert_se(r == 0); r = read(pipefd[0], buf, sizeof(buf)); assert_se(r >= 0); assert_se(lseek(infd, 0, SEEK_SET) == 0); r2 = read(infd, buf2, sizeof(buf2)); assert_se(r == r2); assert_se(strneq(buf, buf2, r)); /* test copy_bytes with invalid descriptors */ r = copy_bytes(pipefd[0], pipefd[0], 1, false); assert_se(r == -EBADF); r = copy_bytes(pipefd[1], pipefd[1], 1, false); assert_se(r == -EBADF); r = copy_bytes(pipefd[1], infd, 1, false); assert_se(r == -EBADF); } int main(int argc, char *argv[]) { test_copy_file(); test_copy_file_fd(); test_copy_tree(); test_copy_bytes(); return 0; } systemd-229/src/test/test-daemon.c000066400000000000000000000033011265713322000172100ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-daemon.h" #include "strv.h" int main(int argc, char*argv[]) { _cleanup_strv_free_ char **l = NULL; int n, i; n = sd_listen_fds_with_names(false, &l); if (n < 0) { log_error_errno(n, "Failed to get listening fds: %m"); return EXIT_FAILURE; } for (i = 0; i < n; i++) log_info("fd=%i name=%s\n", SD_LISTEN_FDS_START + i, l[i]); sd_notify(0, "STATUS=Starting up"); sleep(5); sd_notify(0, "STATUS=Running\n" "READY=1"); sleep(5); sd_notify(0, "STATUS=Reloading\n" "RELOADING=1"); sleep(5); sd_notify(0, "STATUS=Running\n" "READY=1"); sleep(5); sd_notify(0, "STATUS=Quitting\n" "STOPPING=1"); sleep(5); return EXIT_SUCCESS; } systemd-229/src/test/test-date.c000066400000000000000000000055071265713322000166740ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "string-util.h" #include "util.h" static void test_should_pass(const char *p) { usec_t t, q; char buf[FORMAT_TIMESTAMP_MAX], buf_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *sp; assert_se(parse_timestamp(p, &t) >= 0); format_timestamp_us(buf, sizeof(buf), t); log_info("%s", buf); /* Chop off timezone */ sp = strrchr(buf, ' '); assert_se(sp); *sp = 0; assert_se(parse_timestamp(buf, &q) >= 0); assert_se(q == t); format_timestamp_relative(buf_relative, sizeof(buf_relative), t); log_info("%s", strna(buf_relative)); assert_se(parse_timestamp(buf, &q) >= 0); } static void test_should_parse(const char *p) { usec_t t; assert_se(parse_timestamp(p, &t) >= 0); } static void test_should_fail(const char *p) { usec_t t; assert_se(parse_timestamp(p, &t) < 0); } static void test_one(const char *p) { _cleanup_free_ char *with_utc; log_info("Test: %s", p); with_utc = strjoin(p, " UTC", NULL); test_should_pass(p); test_should_pass(with_utc); } static void test_one_noutc(const char *p) { _cleanup_free_ char *with_utc; log_info("Test: %s", p); with_utc = strjoin(p, " UTC", NULL); test_should_pass(p); test_should_fail(with_utc); } int main(int argc, char *argv[]) { test_one("17:41"); test_one("18:42:44"); test_one("18:42:44.0"); test_one("18:42:44.999999999999"); test_one("12-10-02 12:13:14"); test_one("12-10-2 12:13:14"); test_one("12-10-03 12:13"); test_one("2012-12-30 18:42"); test_one("2012-10-02"); test_one("Tue 2012-10-02"); test_one_noutc("now"); test_one("yesterday"); test_one("today"); test_one("tomorrow"); test_one_noutc("+2d"); test_one_noutc("+2y 4d"); test_one_noutc("5months ago"); test_one_noutc("@1395716396"); test_should_parse("today UTC"); test_should_fail("today UTC UTC"); return 0; } systemd-229/src/test/test-device-nodes.c000066400000000000000000000034571265713322000203260ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Dave Reisner systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "device-nodes.h" #include "string-util.h" #include "util.h" /* helpers for test_encode_devnode_name */ static char *do_encode_string(const char *in) { size_t out_len = strlen(in) * 4 + 1; char *out = malloc(out_len); assert_se(out); assert_se(encode_devnode_name(in, out, out_len) >= 0); puts(out); return out; } static bool expect_encoded_as(const char *in, const char *expected) { _cleanup_free_ char *encoded = do_encode_string(in); return streq(encoded, expected); } static void test_encode_devnode_name(void) { assert_se(expect_encoded_as("systemd sucks", "systemd\\x20sucks")); assert_se(expect_encoded_as("pinkiepie", "pinkiepie")); assert_se(expect_encoded_as("valíd\\ųtf8", "valíd\\x5cųtf8")); assert_se(expect_encoded_as("s/ash/ng", "s\\x2fash\\x2fng")); assert_se(expect_encoded_as("/", "\\x2f")); assert_se(expect_encoded_as("!", "\\x21")); } int main(int argc, char *argv[]) { test_encode_devnode_name(); return 0; } systemd-229/src/test/test-dns-domain.c000066400000000000000000000744341265713322000200150ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "dns-domain.h" #include "macro.h" #include "string-util.h" static void test_dns_label_unescape_one(const char *what, const char *expect, size_t buffer_sz, int ret) { char buffer[buffer_sz]; int r; r = dns_label_unescape(&what, buffer, buffer_sz); assert_se(r == ret); if (r < 0) return; assert_se(streq(buffer, expect)); } static void test_dns_label_unescape(void) { test_dns_label_unescape_one("hallo", "hallo", 6, 5); test_dns_label_unescape_one("hallo", "hallo", 4, -ENOBUFS); test_dns_label_unescape_one("", "", 10, 0); test_dns_label_unescape_one("hallo\\.foobar", "hallo.foobar", 20, 12); test_dns_label_unescape_one("hallo.foobar", "hallo", 10, 5); test_dns_label_unescape_one("hallo\n.foobar", "hallo", 20, -EINVAL); test_dns_label_unescape_one("hallo\\", "hallo", 20, -EINVAL); test_dns_label_unescape_one("hallo\\032 ", "hallo ", 20, 7); test_dns_label_unescape_one(".", "", 20, 0); test_dns_label_unescape_one("..", "", 20, -EINVAL); test_dns_label_unescape_one(".foobar", "", 20, -EINVAL); test_dns_label_unescape_one("foobar.", "foobar", 20, 6); } static void test_dns_name_to_wire_format_one(const char *what, const char *expect, size_t buffer_sz, int ret) { uint8_t buffer[buffer_sz]; int r; r = dns_name_to_wire_format(what, buffer, buffer_sz, false); assert_se(r == ret); if (r < 0) return; assert_se(!memcmp(buffer, expect, r)); } static void test_dns_name_to_wire_format(void) { static const char out0[] = { 0 }; static const char out1[] = { 3, 'f', 'o', 'o', 0 }; static const char out2[] = { 5, 'h', 'a', 'l', 'l', 'o', 3, 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 }; static const char out3[] = { 4, ' ', 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 }; static const char out4[] = { 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', 3, 'a', '1', '2', 0 }; test_dns_name_to_wire_format_one("", out0, sizeof(out0), sizeof(out0)); test_dns_name_to_wire_format_one("foo", out1, sizeof(out1), sizeof(out1)); test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) + 1, sizeof(out1)); test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) - 1, -ENOBUFS); test_dns_name_to_wire_format_one("hallo.foo.bar", out2, sizeof(out2), sizeof(out2)); test_dns_name_to_wire_format_one("hallo.foo..bar", NULL, 32, -EINVAL); test_dns_name_to_wire_format_one("\\032foo.bar", out3, sizeof(out3), sizeof(out3)); test_dns_name_to_wire_format_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a123", NULL, 500, -EINVAL); test_dns_name_to_wire_format_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12", out4, sizeof(out4), sizeof(out4)); } static void test_dns_label_unescape_suffix_one(const char *what, const char *expect1, const char *expect2, size_t buffer_sz, int ret1, int ret2) { char buffer[buffer_sz]; const char *label; int r; label = what + strlen(what); r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz); assert_se(r == ret1); if (r >= 0) assert_se(streq(buffer, expect1)); r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz); assert_se(r == ret2); if (r >= 0) assert_se(streq(buffer, expect2)); } static void test_dns_label_unescape_suffix(void) { test_dns_label_unescape_suffix_one("hallo", "hallo", "", 6, 5, 0); test_dns_label_unescape_suffix_one("hallo", "hallo", "", 4, -ENOBUFS, -ENOBUFS); test_dns_label_unescape_suffix_one("", "", "", 10, 0, 0); test_dns_label_unescape_suffix_one("hallo\\.foobar", "hallo.foobar", "", 20, 12, 0); test_dns_label_unescape_suffix_one("hallo.foobar", "foobar", "hallo", 10, 6, 5); test_dns_label_unescape_suffix_one("hallo.foobar\n", "foobar", "foobar", 20, -EINVAL, -EINVAL); test_dns_label_unescape_suffix_one("hallo\\", "hallo", "hallo", 20, -EINVAL, -EINVAL); test_dns_label_unescape_suffix_one("hallo\\032 ", "hallo ", "", 20, 7, 0); test_dns_label_unescape_suffix_one(".", "", "", 20, 0, 0); test_dns_label_unescape_suffix_one("..", "", "", 20, 0, -EINVAL); test_dns_label_unescape_suffix_one(".foobar", "foobar", "", 20, 6, -EINVAL); test_dns_label_unescape_suffix_one("foobar.", "foobar", "", 20, 6, 0); test_dns_label_unescape_suffix_one("foo\\\\bar", "foo\\bar", "", 20, 7, 0); test_dns_label_unescape_suffix_one("foo.bar", "bar", "foo", 20, 3, 3); test_dns_label_unescape_suffix_one("foo..bar", "bar", "", 20, 3, -EINVAL); test_dns_label_unescape_suffix_one("foo...bar", "bar", "", 20, 3, -EINVAL); test_dns_label_unescape_suffix_one("foo\\.bar", "foo.bar", "", 20, 7, 0); test_dns_label_unescape_suffix_one("foo\\\\.bar", "bar", "foo\\", 20, 3, 4); test_dns_label_unescape_suffix_one("foo\\\\\\.bar", "foo\\.bar", "", 20, 8, 0); } static void test_dns_label_escape_one(const char *what, size_t l, const char *expect, int ret) { _cleanup_free_ char *t = NULL; int r; r = dns_label_escape_new(what, l, &t); assert_se(r == ret); if (r < 0) return; assert_se(streq_ptr(expect, t)); } static void test_dns_label_escape(void) { test_dns_label_escape_one("", 0, NULL, -EINVAL); test_dns_label_escape_one("hallo", 5, "hallo", 5); test_dns_label_escape_one("hallo", 6, "hallo\\000", 9); test_dns_label_escape_one("hallo hallo.foobar,waldi", 24, "hallo\\032hallo\\.foobar\\044waldi", 31); } static void test_dns_name_normalize_one(const char *what, const char *expect, int ret) { _cleanup_free_ char *t = NULL; int r; r = dns_name_normalize(what, &t); assert_se(r == ret); if (r < 0) return; assert_se(streq_ptr(expect, t)); } static void test_dns_name_normalize(void) { test_dns_name_normalize_one("", ".", 0); test_dns_name_normalize_one("f", "f", 0); test_dns_name_normalize_one("f.waldi", "f.waldi", 0); test_dns_name_normalize_one("f \\032.waldi", "f\\032\\032.waldi", 0); test_dns_name_normalize_one("\\000", "\\000", 0); test_dns_name_normalize_one("..", NULL, -EINVAL); test_dns_name_normalize_one(".foobar", NULL, -EINVAL); test_dns_name_normalize_one("foobar.", "foobar", 0); test_dns_name_normalize_one(".", ".", 0); } static void test_dns_name_equal_one(const char *a, const char *b, int ret) { int r; r = dns_name_equal(a, b); assert_se(r == ret); r = dns_name_equal(b, a); assert_se(r == ret); } static void test_dns_name_equal(void) { test_dns_name_equal_one("", "", true); test_dns_name_equal_one("x", "x", true); test_dns_name_equal_one("x", "x.", true); test_dns_name_equal_one("abc.def", "abc.def", true); test_dns_name_equal_one("abc.def", "ABC.def", true); test_dns_name_equal_one("abc.def", "CBA.def", false); test_dns_name_equal_one("", "xxx", false); test_dns_name_equal_one("ab", "a", false); test_dns_name_equal_one("\\000", "\\000", true); test_dns_name_equal_one(".", "", true); test_dns_name_equal_one(".", ".", true); test_dns_name_equal_one("..", "..", -EINVAL); } static void test_dns_name_between_one(const char *a, const char *b, const char *c, int ret) { int r; r = dns_name_between(a, b, c); assert_se(r == ret); r = dns_name_between(c, b, a); if (ret >= 0) assert_se(r == 0); else assert_se(r == ret); } static void test_dns_name_between(void) { /* see https://tools.ietf.org/html/rfc4034#section-6.1 Note that we use "\033.z.example" in stead of "\001.z.example" as we consider the latter invalid */ test_dns_name_between_one("example", "a.example", "yljkjljk.a.example", true); test_dns_name_between_one("a.example", "yljkjljk.a.example", "Z.a.example", true); test_dns_name_between_one("yljkjljk.a.example", "Z.a.example", "zABC.a.EXAMPLE", true); test_dns_name_between_one("Z.a.example", "zABC.a.EXAMPLE", "z.example", true); test_dns_name_between_one("zABC.a.EXAMPLE", "z.example", "\\033.z.example", true); test_dns_name_between_one("z.example", "\\033.z.example", "*.z.example", true); test_dns_name_between_one("\\033.z.example", "*.z.example", "\\200.z.example", true); test_dns_name_between_one("*.z.example", "\\200.z.example", "example", true); test_dns_name_between_one("\\200.z.example", "example", "a.example", true); test_dns_name_between_one("example", "a.example", "example", -EINVAL); test_dns_name_between_one("example", "example", "yljkjljk.a.example", false); test_dns_name_between_one("example", "yljkjljk.a.example", "yljkjljk.a.example", false); } static void test_dns_name_endswith_one(const char *a, const char *b, int ret) { assert_se(dns_name_endswith(a, b) == ret); } static void test_dns_name_endswith(void) { test_dns_name_endswith_one("", "", true); test_dns_name_endswith_one("", "xxx", false); test_dns_name_endswith_one("xxx", "", true); test_dns_name_endswith_one("x", "x", true); test_dns_name_endswith_one("x", "y", false); test_dns_name_endswith_one("x.y", "y", true); test_dns_name_endswith_one("x.y", "Y", true); test_dns_name_endswith_one("x.y", "x", false); test_dns_name_endswith_one("x.y.z", "Z", true); test_dns_name_endswith_one("x.y.z", "y.Z", true); test_dns_name_endswith_one("x.y.z", "x.y.Z", true); test_dns_name_endswith_one("x.y.z", "waldo", false); test_dns_name_endswith_one("x.y.z.u.v.w", "y.z", false); test_dns_name_endswith_one("x.y.z.u.v.w", "u.v.w", true); test_dns_name_endswith_one("x.y\001.z", "waldo", -EINVAL); } static void test_dns_name_startswith_one(const char *a, const char *b, int ret) { assert_se(dns_name_startswith(a, b) == ret); } static void test_dns_name_startswith(void) { test_dns_name_startswith_one("", "", true); test_dns_name_startswith_one("", "xxx", false); test_dns_name_startswith_one("xxx", "", true); test_dns_name_startswith_one("x", "x", true); test_dns_name_startswith_one("x", "y", false); test_dns_name_startswith_one("x.y", "x.y", true); test_dns_name_startswith_one("x.y", "y.x", false); test_dns_name_startswith_one("x.y", "x", true); test_dns_name_startswith_one("x.y", "X", true); test_dns_name_startswith_one("x.y", "y", false); test_dns_name_startswith_one("x.y", "", true); test_dns_name_startswith_one("x.y", "X", true); } static void test_dns_name_is_root(void) { assert_se(dns_name_is_root("")); assert_se(dns_name_is_root(".")); assert_se(!dns_name_is_root("xxx")); assert_se(!dns_name_is_root("xxx.")); assert_se(!dns_name_is_root("..")); } static void test_dns_name_is_single_label(void) { assert_se(!dns_name_is_single_label("")); assert_se(!dns_name_is_single_label(".")); assert_se(!dns_name_is_single_label("..")); assert_se(dns_name_is_single_label("x")); assert_se(dns_name_is_single_label("x.")); assert_se(!dns_name_is_single_label("xx.yy")); } static void test_dns_name_reverse_one(const char *address, const char *name) { _cleanup_free_ char *p = NULL; union in_addr_union a, b = {}; int familya, familyb; assert_se(in_addr_from_string_auto(address, &familya, &a) >= 0); assert_se(dns_name_reverse(familya, &a, &p) >= 0); assert_se(streq(p, name)); assert_se(dns_name_address(p, &familyb, &b) > 0); assert_se(familya == familyb); assert_se(in_addr_equal(familya, &a, &b)); } static void test_dns_name_reverse(void) { test_dns_name_reverse_one("47.11.8.15", "15.8.11.47.in-addr.arpa"); test_dns_name_reverse_one("fe80::47", "7.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa"); test_dns_name_reverse_one("127.0.0.1", "1.0.0.127.in-addr.arpa"); test_dns_name_reverse_one("::1", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa"); } static void test_dns_name_concat_one(const char *a, const char *b, int r, const char *result) { _cleanup_free_ char *p = NULL; assert_se(dns_name_concat(a, b, &p) == r); assert_se(streq_ptr(p, result)); } static void test_dns_name_concat(void) { test_dns_name_concat_one("", "", 0, "."); test_dns_name_concat_one(".", "", 0, "."); test_dns_name_concat_one("", ".", 0, "."); test_dns_name_concat_one(".", ".", 0, "."); test_dns_name_concat_one("foo", "bar", 0, "foo.bar"); test_dns_name_concat_one("foo.foo", "bar.bar", 0, "foo.foo.bar.bar"); test_dns_name_concat_one("foo", NULL, 0, "foo"); test_dns_name_concat_one("foo", ".", 0, "foo"); test_dns_name_concat_one("foo.", "bar.", 0, "foo.bar"); test_dns_name_concat_one(NULL, NULL, 0, "."); test_dns_name_concat_one(NULL, ".", 0, "."); test_dns_name_concat_one(NULL, "foo", 0, "foo"); } static void test_dns_name_is_valid_one(const char *s, int ret) { assert_se(dns_name_is_valid(s) == ret); } static void test_dns_name_is_valid(void) { test_dns_name_is_valid_one("foo", 1); test_dns_name_is_valid_one("foo.", 1); test_dns_name_is_valid_one("Foo", 1); test_dns_name_is_valid_one("foo.bar", 1); test_dns_name_is_valid_one("foo.bar.baz", 1); test_dns_name_is_valid_one("", 1); test_dns_name_is_valid_one("foo..bar", 0); test_dns_name_is_valid_one(".foo.bar", 0); test_dns_name_is_valid_one("foo.bar.", 1); test_dns_name_is_valid_one("\\zbar", 0); test_dns_name_is_valid_one("ä", 1); test_dns_name_is_valid_one("\n", 0); /* 256 characters*/ test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345", 0); /* 255 characters*/ test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a1234", 0); /* 254 characters*/ test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a123", 0); /* 253 characters*/ test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12", 1); /* label of 64 chars length */ test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a123", 0); /* label of 63 chars length */ test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a12", 1); } static void test_dns_service_name_is_valid(void) { assert_se(dns_service_name_is_valid("Lennart's Compüter")); assert_se(dns_service_name_is_valid("piff.paff")); assert_se(!dns_service_name_is_valid(NULL)); assert_se(!dns_service_name_is_valid("")); assert_se(!dns_service_name_is_valid("foo\nbar")); assert_se(!dns_service_name_is_valid("foo\201bar")); assert_se(!dns_service_name_is_valid("this is an overly long string that is certainly longer than 63 characters")); } static void test_dns_srv_type_is_valid(void) { assert_se(dns_srv_type_is_valid("_http._tcp")); assert_se(dns_srv_type_is_valid("_foo-bar._tcp")); assert_se(dns_srv_type_is_valid("_w._udp")); assert_se(dns_srv_type_is_valid("_a800._tcp")); assert_se(dns_srv_type_is_valid("_a-800._tcp")); assert_se(!dns_srv_type_is_valid(NULL)); assert_se(!dns_srv_type_is_valid("")); assert_se(!dns_srv_type_is_valid("x")); assert_se(!dns_srv_type_is_valid("_foo")); assert_se(!dns_srv_type_is_valid("_tcp")); assert_se(!dns_srv_type_is_valid("_")); assert_se(!dns_srv_type_is_valid("_foo.")); assert_se(!dns_srv_type_is_valid("_föo._tcp")); assert_se(!dns_srv_type_is_valid("_f\no._tcp")); assert_se(!dns_srv_type_is_valid("_800._tcp")); assert_se(!dns_srv_type_is_valid("_-800._tcp")); assert_se(!dns_srv_type_is_valid("_-foo._tcp")); assert_se(!dns_srv_type_is_valid("_piep._foo._udp")); } static void test_dns_service_join_one(const char *a, const char *b, const char *c, int r, const char *d) { _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL; assert_se(dns_service_join(a, b, c, &t) == r); assert_se(streq_ptr(t, d)); if (r < 0) return; assert_se(dns_service_split(t, &x, &y, &z) >= 0); assert_se(streq_ptr(a, x)); assert_se(streq_ptr(b, y)); assert_se(dns_name_equal(c, z) > 0); } static void test_dns_service_join(void) { test_dns_service_join_one("", "", "", -EINVAL, NULL); test_dns_service_join_one("", "_http._tcp", "", -EINVAL, NULL); test_dns_service_join_one("", "_http._tcp", "foo", -EINVAL, NULL); test_dns_service_join_one("foo", "", "foo", -EINVAL, NULL); test_dns_service_join_one("foo", "foo", "foo", -EINVAL, NULL); test_dns_service_join_one("foo", "_http._tcp", "", 0, "foo._http._tcp"); test_dns_service_join_one(NULL, "_http._tcp", "", 0, "_http._tcp"); test_dns_service_join_one("foo", "_http._tcp", "foo", 0, "foo._http._tcp.foo"); test_dns_service_join_one(NULL, "_http._tcp", "foo", 0, "_http._tcp.foo"); test_dns_service_join_one("Lennart's PC", "_pc._tcp", "foo.bar.com", 0, "Lennart\\039s\\032PC._pc._tcp.foo.bar.com"); test_dns_service_join_one(NULL, "_pc._tcp", "foo.bar.com", 0, "_pc._tcp.foo.bar.com"); } static void test_dns_service_split_one(const char *joined, const char *a, const char *b, const char *c, int r) { _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL; assert_se(dns_service_split(joined, &x, &y, &z) == r); assert_se(streq_ptr(x, a)); assert_se(streq_ptr(y, b)); assert_se(streq_ptr(z, c)); if (r < 0) return; if (y) { assert_se(dns_service_join(x, y, z, &t) == 0); assert_se(dns_name_equal(joined, t) > 0); } else assert_se(!x && dns_name_equal(z, joined) > 0); } static void test_dns_service_split(void) { test_dns_service_split_one("", NULL, NULL, ".", 0); test_dns_service_split_one("foo", NULL, NULL, "foo", 0); test_dns_service_split_one("foo.bar", NULL, NULL, "foo.bar", 0); test_dns_service_split_one("_foo.bar", NULL, NULL, "_foo.bar", 0); test_dns_service_split_one("_foo._bar", NULL, "_foo._bar", ".", 0); test_dns_service_split_one("_meh._foo._bar", "_meh", "_foo._bar", ".", 0); test_dns_service_split_one("Wuff\\032Wuff._foo._bar.waldo.com", "Wuff Wuff", "_foo._bar", "waldo.com", 0); } static void test_dns_name_change_suffix_one(const char *name, const char *old_suffix, const char *new_suffix, int r, const char *result) { _cleanup_free_ char *s = NULL; assert_se(dns_name_change_suffix(name, old_suffix, new_suffix, &s) == r); assert_se(streq_ptr(s, result)); } static void test_dns_name_change_suffix(void) { test_dns_name_change_suffix_one("foo.bar", "bar", "waldo", 1, "foo.waldo"); test_dns_name_change_suffix_one("foo.bar.waldi.quux", "foo.bar.waldi.quux", "piff.paff", 1, "piff.paff"); test_dns_name_change_suffix_one("foo.bar.waldi.quux", "bar.waldi.quux", "piff.paff", 1, "foo.piff.paff"); test_dns_name_change_suffix_one("foo.bar.waldi.quux", "waldi.quux", "piff.paff", 1, "foo.bar.piff.paff"); test_dns_name_change_suffix_one("foo.bar.waldi.quux", "quux", "piff.paff", 1, "foo.bar.waldi.piff.paff"); test_dns_name_change_suffix_one("foo.bar.waldi.quux", "", "piff.paff", 1, "foo.bar.waldi.quux.piff.paff"); test_dns_name_change_suffix_one("", "", "piff.paff", 1, "piff.paff"); test_dns_name_change_suffix_one("", "", "", 1, "."); test_dns_name_change_suffix_one("a", "b", "c", 0, NULL); } static void test_dns_name_suffix_one(const char *name, unsigned n_labels, const char *result, int ret) { const char *p = NULL; assert_se(ret == dns_name_suffix(name, n_labels, &p)); assert_se(streq_ptr(p, result)); } static void test_dns_name_suffix(void) { test_dns_name_suffix_one("foo.bar", 2, "foo.bar", 0); test_dns_name_suffix_one("foo.bar", 1, "bar", 1); test_dns_name_suffix_one("foo.bar", 0, "", 2); test_dns_name_suffix_one("foo.bar", 3, NULL, -EINVAL); test_dns_name_suffix_one("foo.bar", 4, NULL, -EINVAL); test_dns_name_suffix_one("bar", 1, "bar", 0); test_dns_name_suffix_one("bar", 0, "", 1); test_dns_name_suffix_one("bar", 2, NULL, -EINVAL); test_dns_name_suffix_one("bar", 3, NULL, -EINVAL); test_dns_name_suffix_one("", 0, "", 0); test_dns_name_suffix_one("", 1, NULL, -EINVAL); test_dns_name_suffix_one("", 2, NULL, -EINVAL); } static void test_dns_name_count_labels_one(const char *name, int n) { assert_se(dns_name_count_labels(name) == n); } static void test_dns_name_count_labels(void) { test_dns_name_count_labels_one("foo.bar.quux.", 3); test_dns_name_count_labels_one("foo.bar.quux", 3); test_dns_name_count_labels_one("foo.bar.", 2); test_dns_name_count_labels_one("foo.bar", 2); test_dns_name_count_labels_one("foo.", 1); test_dns_name_count_labels_one("foo", 1); test_dns_name_count_labels_one("", 0); test_dns_name_count_labels_one(".", 0); test_dns_name_count_labels_one("..", -EINVAL); } static void test_dns_name_equal_skip_one(const char *a, unsigned n_labels, const char *b, int ret) { assert_se(dns_name_equal_skip(a, n_labels, b) == ret); } static void test_dns_name_equal_skip(void) { test_dns_name_equal_skip_one("foo", 0, "bar", 0); test_dns_name_equal_skip_one("foo", 0, "foo", 1); test_dns_name_equal_skip_one("foo", 1, "foo", 0); test_dns_name_equal_skip_one("foo", 2, "foo", 0); test_dns_name_equal_skip_one("foo.bar", 0, "foo.bar", 1); test_dns_name_equal_skip_one("foo.bar", 1, "foo.bar", 0); test_dns_name_equal_skip_one("foo.bar", 2, "foo.bar", 0); test_dns_name_equal_skip_one("foo.bar", 3, "foo.bar", 0); test_dns_name_equal_skip_one("foo.bar", 0, "bar", 0); test_dns_name_equal_skip_one("foo.bar", 1, "bar", 1); test_dns_name_equal_skip_one("foo.bar", 2, "bar", 0); test_dns_name_equal_skip_one("foo.bar", 3, "bar", 0); test_dns_name_equal_skip_one("foo.bar", 0, "", 0); test_dns_name_equal_skip_one("foo.bar", 1, "", 0); test_dns_name_equal_skip_one("foo.bar", 2, "", 1); test_dns_name_equal_skip_one("foo.bar", 3, "", 0); test_dns_name_equal_skip_one("", 0, "", 1); test_dns_name_equal_skip_one("", 1, "", 0); test_dns_name_equal_skip_one("", 1, "foo", 0); test_dns_name_equal_skip_one("", 2, "foo", 0); } static void test_dns_name_compare_func(void) { assert_se(dns_name_compare_func("", "") == 0); assert_se(dns_name_compare_func("", ".") == 0); assert_se(dns_name_compare_func(".", "") == 0); assert_se(dns_name_compare_func("foo", "foo.") == 0); assert_se(dns_name_compare_func("foo.", "foo") == 0); assert_se(dns_name_compare_func("foo", "foo") == 0); assert_se(dns_name_compare_func("foo.", "foo.") == 0); assert_se(dns_name_compare_func("heise.de", "HEISE.DE.") == 0); assert_se(dns_name_compare_func("de.", "heise.de") != 0); } static void test_dns_name_common_suffix_one(const char *a, const char *b, const char *result) { const char *c; assert_se(dns_name_common_suffix(a, b, &c) >= 0); assert_se(streq(c, result)); } static void test_dns_name_common_suffix(void) { test_dns_name_common_suffix_one("", "", ""); test_dns_name_common_suffix_one("foo", "", ""); test_dns_name_common_suffix_one("", "foo", ""); test_dns_name_common_suffix_one("foo", "bar", ""); test_dns_name_common_suffix_one("bar", "foo", ""); test_dns_name_common_suffix_one("foo", "foo", "foo"); test_dns_name_common_suffix_one("quux.foo", "foo", "foo"); test_dns_name_common_suffix_one("foo", "quux.foo", "foo"); test_dns_name_common_suffix_one("this.is.a.short.sentence", "this.is.another.short.sentence", "short.sentence"); test_dns_name_common_suffix_one("FOO.BAR", "tEST.bAR", "BAR"); } static void test_dns_name_apply_idna_one(const char *s, const char *result) { #ifdef HAVE_LIBIDN _cleanup_free_ char *buf = NULL; assert_se(dns_name_apply_idna(s, &buf) >= 0); assert_se(dns_name_equal(buf, result) > 0); #endif } static void test_dns_name_apply_idna(void) { test_dns_name_apply_idna_one("", ""); test_dns_name_apply_idna_one("foo", "foo"); test_dns_name_apply_idna_one("foo.", "foo"); test_dns_name_apply_idna_one("foo.bar", "foo.bar"); test_dns_name_apply_idna_one("foo.bar.", "foo.bar"); test_dns_name_apply_idna_one("föö", "xn--f-1gaa"); test_dns_name_apply_idna_one("föö.", "xn--f-1gaa"); test_dns_name_apply_idna_one("föö.bär", "xn--f-1gaa.xn--br-via"); test_dns_name_apply_idna_one("föö.bär.", "xn--f-1gaa.xn--br-via"); } int main(int argc, char *argv[]) { test_dns_label_unescape(); test_dns_label_unescape_suffix(); test_dns_label_escape(); test_dns_name_normalize(); test_dns_name_equal(); test_dns_name_endswith(); test_dns_name_startswith(); test_dns_name_between(); test_dns_name_is_root(); test_dns_name_is_single_label(); test_dns_name_reverse(); test_dns_name_concat(); test_dns_name_is_valid(); test_dns_name_to_wire_format(); test_dns_service_name_is_valid(); test_dns_srv_type_is_valid(); test_dns_service_join(); test_dns_service_split(); test_dns_name_change_suffix(); test_dns_name_suffix(); test_dns_name_count_labels(); test_dns_name_equal_skip(); test_dns_name_compare_func(); test_dns_name_common_suffix(); test_dns_name_apply_idna(); return 0; } systemd-229/src/test/test-ellipsize.c000066400000000000000000000057101265713322000177530ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Shawn Landden systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "def.h" #include "string-util.h" #include "terminal-util.h" #include "util.h" static void test_one(const char *p) { _cleanup_free_ char *t; t = ellipsize(p, columns(), 70); puts(t); } int main(int argc, char *argv[]) { test_one(DIGITS LETTERS DIGITS LETTERS); test_one("한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어"); test_one("-日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国"); test_one("中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国-中国中国中国中国中国中国中国中国中国中国中国中国中国"); test_one("sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd"); test_one("🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮"); test_one("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); test_one("shórt"); return 0; } systemd-229/src/test/test-engine.c000066400000000000000000000103351265713322000172170ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "bus-util.h" #include "manager.h" #include "test-helper.h" int main(int argc, char *argv[]) { _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL; Manager *m = NULL; Unit *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *g = NULL, *h = NULL; FILE *serial = NULL; FDSet *fdset = NULL; Job *j; int r; /* prepare the test */ assert_se(set_unit_path(TEST_DIR) >= 0); r = manager_new(MANAGER_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { printf("Skipping test: manager_new: %s\n", strerror(-r)); return EXIT_TEST_SKIP; } assert_se(r >= 0); assert_se(manager_startup(m, serial, fdset) >= 0); printf("Load1:\n"); assert_se(manager_load_unit(m, "a.service", NULL, NULL, &a) >= 0); assert_se(manager_load_unit(m, "b.service", NULL, NULL, &b) >= 0); assert_se(manager_load_unit(m, "c.service", NULL, NULL, &c) >= 0); manager_dump_units(m, stdout, "\t"); printf("Test1: (Trivial)\n"); r = manager_add_job(m, JOB_START, c, JOB_REPLACE, &err, &j); if (sd_bus_error_is_set(&err)) log_error("error: %s: %s", err.name, err.message); assert_se(r == 0); manager_dump_jobs(m, stdout, "\t"); printf("Load2:\n"); manager_clear_jobs(m); assert_se(manager_load_unit(m, "d.service", NULL, NULL, &d) >= 0); assert_se(manager_load_unit(m, "e.service", NULL, NULL, &e) >= 0); manager_dump_units(m, stdout, "\t"); printf("Test2: (Cyclic Order, Unfixable)\n"); assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, NULL, &j) == -EDEADLK); manager_dump_jobs(m, stdout, "\t"); printf("Test3: (Cyclic Order, Fixable, Garbage Collector)\n"); assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, NULL, &j) == 0); manager_dump_jobs(m, stdout, "\t"); printf("Test4: (Identical transaction)\n"); assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, NULL, &j) == 0); manager_dump_jobs(m, stdout, "\t"); printf("Load3:\n"); assert_se(manager_load_unit(m, "g.service", NULL, NULL, &g) >= 0); manager_dump_units(m, stdout, "\t"); printf("Test5: (Colliding transaction, fail)\n"); assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, NULL, &j) == -EDEADLK); printf("Test6: (Colliding transaction, replace)\n"); assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, NULL, &j) == 0); manager_dump_jobs(m, stdout, "\t"); printf("Test7: (Unmergeable job type, fail)\n"); assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, NULL, &j) == -EDEADLK); printf("Test8: (Mergeable job type, fail)\n"); assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, NULL, &j) == 0); manager_dump_jobs(m, stdout, "\t"); printf("Test9: (Unmergeable job type, replace)\n"); assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, NULL, &j) == 0); manager_dump_jobs(m, stdout, "\t"); printf("Load4:\n"); assert_se(manager_load_unit(m, "h.service", NULL, NULL, &h) >= 0); manager_dump_units(m, stdout, "\t"); printf("Test10: (Unmergeable job type of auxiliary job, fail)\n"); assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, NULL, &j) == 0); manager_dump_jobs(m, stdout, "\t"); manager_free(m); return 0; } systemd-229/src/test/test-env-replace.c000066400000000000000000000137261265713322000201620ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "env-util.h" #include "string-util.h" #include "strv.h" #include "util.h" static void test_strv_env_delete(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL; a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF", NULL); assert_se(a); b = strv_new("PIEP", "FOO", NULL); assert_se(b); c = strv_new("SCHLUMPF", NULL); assert_se(c); d = strv_env_delete(a, 2, b, c); assert_se(d); assert_se(streq(d[0], "WALDO=WALDO")); assert_se(streq(d[1], "WALDO=")); assert_se(strv_length(d) == 2); } static void test_strv_env_unset(void) { _cleanup_strv_free_ char **l = NULL; l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL); assert_se(l); assert_se(strv_env_unset(l, "SCHLUMPF") == l); assert_se(streq(l[0], "PIEP")); assert_se(streq(l[1], "NANANANA=YES")); assert_se(strv_length(l) == 2); } static void test_strv_env_set(void) { _cleanup_strv_free_ char **l = NULL, **r = NULL; l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL); assert_se(l); r = strv_env_set(l, "WALDO=WALDO"); assert_se(r); assert_se(streq(r[0], "PIEP")); assert_se(streq(r[1], "SCHLUMPF=SMURFF")); assert_se(streq(r[2], "NANANANA=YES")); assert_se(streq(r[3], "WALDO=WALDO")); assert_se(strv_length(r) == 4); } static void test_strv_env_merge(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL, **r = NULL; a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF", NULL); assert_se(a); b = strv_new("FOO=KKK", "FOO=", "PIEP=", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL); assert_se(b); r = strv_env_merge(2, a, b); assert_se(r); assert_se(streq(r[0], "FOO=")); assert_se(streq(r[1], "WALDO=")); assert_se(streq(r[2], "PIEP")); assert_se(streq(r[3], "SCHLUMPF=SMURFF")); assert_se(streq(r[4], "PIEP=")); assert_se(streq(r[5], "NANANANA=YES")); assert_se(strv_length(r) == 6); assert_se(strv_env_clean(r) == r); assert_se(streq(r[0], "FOO=")); assert_se(streq(r[1], "WALDO=")); assert_se(streq(r[2], "SCHLUMPF=SMURFF")); assert_se(streq(r[3], "PIEP=")); assert_se(streq(r[4], "NANANANA=YES")); assert_se(strv_length(r) == 5); } static void test_replace_env_arg(void) { const char *env[] = { "FOO=BAR BAR", "BAR=waldo", NULL }; const char *line[] = { "FOO$FOO", "FOO$FOOFOO", "FOO${FOO}$FOO", "FOO${FOO}", "${FOO}", "$FOO", "$FOO$FOO", "${FOO}${BAR}", "${FOO", "FOO$$${FOO}", "$$FOO${FOO}", NULL }; _cleanup_strv_free_ char **r = NULL; r = replace_env_argv((char**) line, (char**) env); assert_se(r); assert_se(streq(r[0], "FOO$FOO")); assert_se(streq(r[1], "FOO$FOOFOO")); assert_se(streq(r[2], "FOOBAR BAR$FOO")); assert_se(streq(r[3], "FOOBAR BAR")); assert_se(streq(r[4], "BAR BAR")); assert_se(streq(r[5], "BAR")); assert_se(streq(r[6], "BAR")); assert_se(streq(r[7], "BAR BARwaldo")); assert_se(streq(r[8], "${FOO")); assert_se(streq(r[9], "FOO$BAR BAR")); assert_se(streq(r[10], "$FOOBAR BAR")); assert_se(strv_length(r) == 11); } static void test_env_clean(void) { _cleanup_strv_free_ char **e; e = strv_new("FOOBAR=WALDO", "FOOBAR=WALDO", "FOOBAR", "F", "X=", "F=F", "=", "=F", "", "0000=000", "äöüß=abcd", "abcd=äöüß", "xyz\n=xyz", "xyz=xyz\n", "another=one", "another=final one", NULL); assert_se(e); assert_se(!strv_env_is_valid(e)); assert_se(strv_env_clean(e) == e); assert_se(strv_env_is_valid(e)); assert_se(streq(e[0], "FOOBAR=WALDO")); assert_se(streq(e[1], "X=")); assert_se(streq(e[2], "F=F")); assert_se(streq(e[3], "abcd=äöüß")); assert_se(streq(e[4], "another=final one")); assert_se(e[5] == NULL); } static void test_env_name_is_valid(void) { assert_se(env_name_is_valid("test")); assert_se(!env_name_is_valid(NULL)); assert_se(!env_name_is_valid("")); assert_se(!env_name_is_valid("5_starting_with_a_number_is_wrong")); assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed")); } int main(int argc, char *argv[]) { test_strv_env_delete(); test_strv_env_unset(); test_strv_env_set(); test_strv_env_merge(); test_replace_env_arg(); test_env_clean(); test_env_name_is_valid(); return 0; } systemd-229/src/test/test-execute.c000066400000000000000000000272061265713322000174210ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "fileio.h" #include "fs-util.h" #include "macro.h" #include "manager.h" #include "mkdir.h" #include "path-util.h" #include "rm-rf.h" #include "test-helper.h" #include "unit.h" #include "util.h" typedef void (*test_function_t)(Manager *m); static void check(Manager *m, Unit *unit, int status_expected, int code_expected) { Service *service = NULL; usec_t ts; usec_t timeout = 2 * USEC_PER_SEC; assert_se(m); assert_se(unit); service = SERVICE(unit); printf("%s\n", unit->id); exec_context_dump(&service->exec_context, stdout, "\t"); ts = now(CLOCK_MONOTONIC); while (service->state != SERVICE_DEAD && service->state != SERVICE_FAILED) { int r; usec_t n; r = sd_event_run(m->event, 100 * USEC_PER_MSEC); assert_se(r >= 0); n = now(CLOCK_MONOTONIC); if (ts + timeout < n) { log_error("Test timeout when testing %s", unit->id); exit(EXIT_FAILURE); } } exec_status_dump(&service->main_exec_status, stdout, "\t"); assert_se(service->main_exec_status.status == status_expected); assert_se(service->main_exec_status.code == code_expected); } static void test(Manager *m, const char *unit_name, int status_expected, int code_expected) { Unit *unit; assert_se(unit_name); assert_se(manager_load_unit(m, unit_name, NULL, NULL, &unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); check(m, unit, status_expected, code_expected); } static void test_exec_workingdirectory(Manager *m) { assert_se(mkdir_p("/tmp/test-exec_workingdirectory", 0755) >= 0); test(m, "exec-workingdirectory.service", 0, CLD_EXITED); (void) rm_rf("/tmp/test-exec_workingdirectory", REMOVE_ROOT|REMOVE_PHYSICAL); } static void test_exec_personality(Manager *m) { #if defined(__x86_64__) test(m, "exec-personality-x86-64.service", 0, CLD_EXITED); #elif defined(__s390__) test(m, "exec-personality-s390.service", 0, CLD_EXITED); #else test(m, "exec-personality-x86.service", 0, CLD_EXITED); #endif } static void test_exec_ignoresigpipe(Manager *m) { test(m, "exec-ignoresigpipe-yes.service", 0, CLD_EXITED); test(m, "exec-ignoresigpipe-no.service", SIGPIPE, CLD_KILLED); } static void test_exec_privatetmp(Manager *m) { assert_se(touch("/tmp/test-exec_privatetmp") >= 0); test(m, "exec-privatetmp-yes.service", 0, CLD_EXITED); test(m, "exec-privatetmp-no.service", 0, CLD_EXITED); unlink("/tmp/test-exec_privatetmp"); } static void test_exec_privatedevices(Manager *m) { test(m, "exec-privatedevices-yes.service", 0, CLD_EXITED); test(m, "exec-privatedevices-no.service", 0, CLD_EXITED); } static void test_exec_systemcallfilter(Manager *m) { #ifdef HAVE_SECCOMP test(m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED); test(m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED); test(m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED); test(m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED); #endif } static void test_exec_systemcallerrornumber(Manager *m) { #ifdef HAVE_SECCOMP test(m, "exec-systemcallerrornumber.service", 1, CLD_EXITED); #endif } static void test_exec_user(Manager *m) { if (getpwnam("nobody")) test(m, "exec-user.service", 0, CLD_EXITED); else log_error_errno(errno, "Skipping test_exec_user, could not find nobody user: %m"); } static void test_exec_group(Manager *m) { if (getgrnam("nobody")) test(m, "exec-group.service", 0, CLD_EXITED); else log_error_errno(errno, "Skipping test_exec_group, could not find nobody group: %m"); } static void test_exec_environment(Manager *m) { test(m, "exec-environment.service", 0, CLD_EXITED); test(m, "exec-environment-multiple.service", 0, CLD_EXITED); test(m, "exec-environment-empty.service", 0, CLD_EXITED); } static void test_exec_environmentfile(Manager *m) { static const char e[] = "VAR1='word1 word2'\n" "VAR2=word3 \n" "# comment1\n" "\n" "; comment2\n" " ; # comment3\n" "line without an equal\n" "VAR3='$word 5 6'\n"; int r; r = write_string_file("/tmp/test-exec_environmentfile.conf", e, WRITE_STRING_FILE_CREATE); assert_se(r == 0); test(m, "exec-environmentfile.service", 0, CLD_EXITED); unlink("/tmp/test-exec_environmentfile.conf"); } static void test_exec_passenvironment(Manager *m) { /* test-execute runs under MANAGER_USER which, by default, forwards all * variables present in the environment, but only those that are * present _at the time it is created_! * * So these PassEnvironment checks are still expected to work, since we * are ensuring the variables are not present at manager creation (they * are unset explicitly in main) and are only set here. * * This is still a good approximation of how a test for MANAGER_SYSTEM * would work. */ assert_se(setenv("VAR1", "word1 word2", 1) == 0); assert_se(setenv("VAR2", "word3", 1) == 0); assert_se(setenv("VAR3", "$word 5 6", 1) == 0); test(m, "exec-passenvironment.service", 0, CLD_EXITED); test(m, "exec-passenvironment-repeated.service", 0, CLD_EXITED); test(m, "exec-passenvironment-empty.service", 0, CLD_EXITED); assert_se(unsetenv("VAR1") == 0); assert_se(unsetenv("VAR2") == 0); assert_se(unsetenv("VAR3") == 0); test(m, "exec-passenvironment-absent.service", 0, CLD_EXITED); } static void test_exec_umask(Manager *m) { test(m, "exec-umask-default.service", 0, CLD_EXITED); test(m, "exec-umask-0177.service", 0, CLD_EXITED); } static void test_exec_runtimedirectory(Manager *m) { test(m, "exec-runtimedirectory.service", 0, CLD_EXITED); test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED); if (getgrnam("nobody")) test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED); else log_error_errno(errno, "Skipping test_exec_runtimedirectory-owner, could not find nobody group: %m"); } static void test_exec_capabilityboundingset(Manager *m) { int r; /* We use capsh to test if the capabilities are * properly set, so be sure that it exists */ r = find_binary("capsh", NULL); if (r < 0) { log_error_errno(r, "Skipping test_exec_capabilityboundingset, could not find capsh binary: %m"); return; } test(m, "exec-capabilityboundingset-simple.service", 0, CLD_EXITED); test(m, "exec-capabilityboundingset-reset.service", 0, CLD_EXITED); test(m, "exec-capabilityboundingset-merge.service", 0, CLD_EXITED); test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED); } static void test_exec_capabilityambientset(Manager *m) { int r; /* Check if the kernel has support for ambient capabilities. Run * the tests only if that's the case. Clearing all ambient * capabilities is fine, since we are expecting them to be unset * in the first place for the tests. */ r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0); if (r >= 0 || errno != EINVAL) { test(m, "exec-capabilityambientset.service", 0, CLD_EXITED); test(m, "exec-capabilityambientset-merge.service", 0, CLD_EXITED); } } static void test_exec_privatenetwork(Manager *m) { int r; r = find_binary("ip", NULL); if (r < 0) { log_error_errno(r, "Skipping test_exec_privatenetwork, could not find ip binary: %m"); return; } test(m, "exec-privatenetwork-yes.service", 0, CLD_EXITED); } static void test_exec_oomscoreadjust(Manager *m) { test(m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED); test(m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED); } static void test_exec_ioschedulingclass(Manager *m) { test(m, "exec-ioschedulingclass-none.service", 0, CLD_EXITED); test(m, "exec-ioschedulingclass-idle.service", 0, CLD_EXITED); test(m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED); test(m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED); } int main(int argc, char *argv[]) { test_function_t tests[] = { test_exec_workingdirectory, test_exec_personality, test_exec_ignoresigpipe, test_exec_privatetmp, test_exec_privatedevices, test_exec_privatenetwork, test_exec_systemcallfilter, test_exec_systemcallerrornumber, test_exec_user, test_exec_group, test_exec_environment, test_exec_environmentfile, test_exec_passenvironment, test_exec_umask, test_exec_runtimedirectory, test_exec_capabilityboundingset, test_exec_capabilityambientset, test_exec_oomscoreadjust, test_exec_ioschedulingclass, NULL, }; test_function_t *test = NULL; Manager *m = NULL; int r; log_parse_environment(); log_open(); /* It is needed otherwise cgroup creation fails */ if (getuid() != 0) { printf("Skipping test: not root\n"); return EXIT_TEST_SKIP; } assert_se(setenv("XDG_RUNTIME_DIR", "/tmp/", 1) == 0); assert_se(set_unit_path(TEST_DIR "/test-execute/") >= 0); /* Unset VAR1, VAR2 and VAR3 which are used in the PassEnvironment test * cases, otherwise (and if they are present in the environment), * `manager_default_environment` will copy them into the default * environment which is passed to each created job, which will make the * tests that expect those not to be present to fail. */ assert_se(unsetenv("VAR1") == 0); assert_se(unsetenv("VAR2") == 0); assert_se(unsetenv("VAR3") == 0); r = manager_new(MANAGER_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { printf("Skipping test: manager_new: %s\n", strerror(-r)); return EXIT_TEST_SKIP; } assert_se(r >= 0); assert_se(manager_startup(m, NULL, NULL) >= 0); for (test = tests; test && *test; test++) (*test)(m); manager_free(m); return 0; } systemd-229/src/test/test-extract-word.c000066400000000000000000000463331265713322000204040ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Thomas H.P. Andersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "extract-word.h" #include "log.h" #include "string-util.h" static void test_extract_first_word(void) { const char *p, *original; char *t; p = original = "foobar waldo"; assert_se(extract_first_word(&p, &t, NULL, 0) > 0); assert_se(streq(t, "foobar")); free(t); assert_se(p == original + 7); assert_se(extract_first_word(&p, &t, NULL, 0) > 0); assert_se(streq(t, "waldo")); free(t); assert_se(isempty(p)); assert_se(extract_first_word(&p, &t, NULL, 0) == 0); assert_se(!t); assert_se(isempty(p)); p = original = "\"foobar\" \'waldo\'"; assert_se(extract_first_word(&p, &t, NULL, 0) > 0); assert_se(streq(t, "\"foobar\"")); free(t); assert_se(p == original + 9); assert_se(extract_first_word(&p, &t, NULL, 0) > 0); assert_se(streq(t, "\'waldo\'")); free(t); assert_se(isempty(p)); assert_se(extract_first_word(&p, &t, NULL, 0) == 0); assert_se(!t); assert_se(isempty(p)); p = original = "\"foobar\" \'waldo\'"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); assert_se(streq(t, "foobar")); free(t); assert_se(p == original + 9); assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); assert_se(streq(t, "waldo")); free(t); assert_se(isempty(p)); assert_se(extract_first_word(&p, &t, NULL, 0) == 0); assert_se(!t); assert_se(isempty(p)); p = original = "\""; assert_se(extract_first_word(&p, &t, NULL, 0) == 1); assert_se(streq(t, "\"")); free(t); assert_se(isempty(p)); p = original = "\""; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL); assert_se(p == original + 1); p = original = "\'"; assert_se(extract_first_word(&p, &t, NULL, 0) == 1); assert_se(streq(t, "\'")); free(t); assert_se(isempty(p)); p = original = "\'"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL); assert_se(p == original + 1); p = original = "\'fooo"; assert_se(extract_first_word(&p, &t, NULL, 0) == 1); assert_se(streq(t, "\'fooo")); free(t); assert_se(isempty(p)); p = original = "\'fooo"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL); assert_se(p == original + 5); p = original = "\'fooo"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0); assert_se(streq(t, "fooo")); free(t); assert_se(isempty(p)); p = original = "\"fooo"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0); assert_se(streq(t, "fooo")); free(t); assert_se(isempty(p)); p = original = "yay\'foo\'bar"; assert_se(extract_first_word(&p, &t, NULL, 0) > 0); assert_se(streq(t, "yay\'foo\'bar")); free(t); assert_se(isempty(p)); p = original = "yay\'foo\'bar"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); assert_se(streq(t, "yayfoobar")); free(t); assert_se(isempty(p)); p = original = " foobar "; assert_se(extract_first_word(&p, &t, NULL, 0) > 0); assert_se(streq(t, "foobar")); free(t); assert_se(isempty(p)); p = original = " foo\\ba\\x6ar "; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0); assert_se(streq(t, "foo\ba\x6ar")); free(t); assert_se(isempty(p)); p = original = " foo\\ba\\x6ar "; assert_se(extract_first_word(&p, &t, NULL, 0) > 0); assert_se(streq(t, "foobax6ar")); free(t); assert_se(isempty(p)); p = original = " f\\u00f6o \"pi\\U0001F4A9le\" "; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0); assert_se(streq(t, "föo")); free(t); assert_se(p == original + 13); assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE) > 0); assert_se(streq(t, "pi\360\237\222\251le")); free(t); assert_se(isempty(p)); p = original = "fooo\\"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0); assert_se(streq(t, "fooo")); free(t); assert_se(isempty(p)); p = original = "fooo\\"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0); assert_se(streq(t, "fooo\\")); free(t); assert_se(isempty(p)); p = original = "fooo\\"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); assert_se(streq(t, "fooo\\")); free(t); assert_se(isempty(p)); p = original = "fooo\\"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); assert_se(streq(t, "fooo\\")); free(t); assert_se(isempty(p)); p = original = "\"foo\\"; assert_se(extract_first_word(&p, &t, NULL, 0) == -EINVAL); assert_se(p == original + 5); p = original = "\"foo\\"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0); assert_se(streq(t, "foo")); free(t); assert_se(isempty(p)); p = original = "foo::bar"; assert_se(extract_first_word(&p, &t, ":", 0) == 1); assert_se(streq(t, "foo")); free(t); assert_se(p == original + 5); assert_se(extract_first_word(&p, &t, ":", 0) == 1); assert_se(streq(t, "bar")); free(t); assert_se(isempty(p)); assert_se(extract_first_word(&p, &t, ":", 0) == 0); assert_se(!t); assert_se(isempty(p)); p = original = "foo\\:bar::waldo"; assert_se(extract_first_word(&p, &t, ":", 0) == 1); assert_se(streq(t, "foo:bar")); free(t); assert_se(p == original + 10); assert_se(extract_first_word(&p, &t, ":", 0) == 1); assert_se(streq(t, "waldo")); free(t); assert_se(isempty(p)); assert_se(extract_first_word(&p, &t, ":", 0) == 0); assert_se(!t); assert_se(isempty(p)); p = original = "\"foo\\"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX) == -EINVAL); assert_se(p == original + 5); p = original = "\"foo\\"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); assert_se(streq(t, "foo\\")); free(t); assert_se(isempty(p)); p = original = "\"foo\\"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); assert_se(streq(t, "foo\\")); free(t); assert_se(isempty(p)); p = original = "fooo\\ bar quux"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0); assert_se(streq(t, "fooo bar")); free(t); assert_se(p == original + 10); p = original = "fooo\\ bar quux"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0); assert_se(streq(t, "fooo bar")); free(t); assert_se(p == original + 10); p = original = "fooo\\ bar quux"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); assert_se(streq(t, "fooo bar")); free(t); assert_se(p == original + 10); p = original = "fooo\\ bar quux"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL); assert_se(p == original + 5); p = original = "fooo\\ bar quux"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); assert_se(streq(t, "fooo\\ bar")); free(t); assert_se(p == original + 10); p = original = "\\w+@\\K[\\d.]+"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL); assert_se(p == original + 1); p = original = "\\w+@\\K[\\d.]+"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); assert_se(streq(t, "\\w+@\\K[\\d.]+")); free(t); assert_se(isempty(p)); p = original = "\\w+\\b"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); assert_se(streq(t, "\\w+\b")); free(t); assert_se(isempty(p)); p = original = "-N ''"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); assert_se(streq(t, "-N")); free(t); assert_se(p == original + 3); assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0); assert_se(streq(t, "")); free(t); assert_se(isempty(p)); p = original = ":foo\\:bar::waldo:"; assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); assert_se(t); assert_se(streq(t, "")); free(t); assert_se(p == original + 1); assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); assert_se(streq(t, "foo:bar")); free(t); assert_se(p == original + 10); assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); assert_se(t); assert_se(streq(t, "")); free(t); assert_se(p == original + 11); assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); assert_se(streq(t, "waldo")); free(t); assert_se(p == original + 17); assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); assert_se(streq(t, "")); free(t); assert_se(p == NULL); assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 0); assert_se(!t); assert_se(!p); p = "foo\\xbar"; assert_se(extract_first_word(&p, &t, NULL, 0) > 0); assert_se(streq(t, "fooxbar")); free(t); assert_se(p == NULL); p = "foo\\xbar"; assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RETAIN_ESCAPE) > 0); assert_se(streq(t, "foo\\xbar")); free(t); assert_se(p == NULL); } static void test_extract_first_word_and_warn(void) { const char *p, *original; char *t; p = original = "foobar waldo"; assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); assert_se(streq(t, "foobar")); free(t); assert_se(p == original + 7); assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); assert_se(streq(t, "waldo")); free(t); assert_se(isempty(p)); assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0); assert_se(!t); assert_se(isempty(p)); p = original = "\"foobar\" \'waldo\'"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0); assert_se(streq(t, "foobar")); free(t); assert_se(p == original + 9); assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0); assert_se(streq(t, "waldo")); free(t); assert_se(isempty(p)); assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0); assert_se(!t); assert_se(isempty(p)); p = original = "\""; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL); assert_se(p == original + 1); p = original = "\'"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL); assert_se(p == original + 1); p = original = "\'fooo"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL); assert_se(p == original + 5); p = original = "\'fooo"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0); assert_se(streq(t, "fooo")); free(t); assert_se(isempty(p)); p = original = " foo\\ba\\x6ar "; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); assert_se(streq(t, "foo\ba\x6ar")); free(t); assert_se(isempty(p)); p = original = " foo\\ba\\x6ar "; assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); assert_se(streq(t, "foobax6ar")); free(t); assert_se(isempty(p)); p = original = " f\\u00f6o \"pi\\U0001F4A9le\" "; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); assert_se(streq(t, "föo")); free(t); assert_se(p == original + 13); assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); assert_se(streq(t, "pi\360\237\222\251le")); free(t); assert_se(isempty(p)); p = original = "fooo\\"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0); assert_se(streq(t, "fooo")); free(t); assert_se(isempty(p)); p = original = "fooo\\"; assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); assert_se(streq(t, "fooo\\")); free(t); assert_se(isempty(p)); p = original = "fooo\\"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); assert_se(streq(t, "fooo\\")); free(t); assert_se(isempty(p)); p = original = "\"foo\\"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL); assert_se(p == original + 5); p = original = "\"foo\\"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0); assert_se(streq(t, "foo")); free(t); assert_se(isempty(p)); p = original = "\"foo\\"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) == -EINVAL); assert_se(p == original + 5); p = original = "\"foo\\"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0); assert_se(streq(t, "foo")); free(t); assert_se(isempty(p)); p = original = "fooo\\ bar quux"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0); assert_se(streq(t, "fooo bar")); free(t); assert_se(p == original + 10); p = original = "fooo\\ bar quux"; assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); assert_se(streq(t, "fooo bar")); free(t); assert_se(p == original + 10); p = original = "fooo\\ bar quux"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); assert_se(streq(t, "fooo\\ bar")); free(t); assert_se(p == original + 10); p = original = "\\w+@\\K[\\d.]+"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); assert_se(streq(t, "\\w+@\\K[\\d.]+")); free(t); assert_se(isempty(p)); p = original = "\\w+\\b"; assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); assert_se(streq(t, "\\w+\b")); free(t); assert_se(isempty(p)); } static void test_extract_many_words(void) { const char *p, *original; char *a, *b, *c; p = original = "foobar waldi piep"; assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 3); assert_se(isempty(p)); assert_se(streq_ptr(a, "foobar")); assert_se(streq_ptr(b, "waldi")); assert_se(streq_ptr(c, "piep")); free(a); free(b); free(c); p = original = "'foobar' wa\"ld\"i "; assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 2); assert_se(isempty(p)); assert_se(streq_ptr(a, "'foobar'")); assert_se(streq_ptr(b, "wa\"ld\"i")); assert_se(streq_ptr(c, NULL)); free(a); free(b); p = original = "'foobar' wa\"ld\"i "; assert_se(extract_many_words(&p, NULL, EXTRACT_QUOTES, &a, &b, &c, NULL) == 2); assert_se(isempty(p)); assert_se(streq_ptr(a, "foobar")); assert_se(streq_ptr(b, "waldi")); assert_se(streq_ptr(c, NULL)); free(a); free(b); p = original = ""; assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0); assert_se(isempty(p)); assert_se(streq_ptr(a, NULL)); assert_se(streq_ptr(b, NULL)); assert_se(streq_ptr(c, NULL)); p = original = " "; assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0); assert_se(isempty(p)); assert_se(streq_ptr(a, NULL)); assert_se(streq_ptr(b, NULL)); assert_se(streq_ptr(c, NULL)); p = original = "foobar"; assert_se(extract_many_words(&p, NULL, 0, NULL) == 0); assert_se(p == original); p = original = "foobar waldi"; assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1); assert_se(p == original+7); assert_se(streq_ptr(a, "foobar")); free(a); p = original = " foobar "; assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1); assert_se(isempty(p)); assert_se(streq_ptr(a, "foobar")); free(a); } int main(int argc, char *argv[]) { log_parse_environment(); log_open(); test_extract_first_word(); test_extract_first_word_and_warn(); test_extract_many_words(); return 0; } systemd-229/src/test/test-fdset.c000066400000000000000000000137561265713322000170710ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2014 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "fd-util.h" #include "fdset.h" #include "fileio.h" #include "macro.h" #include "util.h" static void test_fdset_new_fill(void) { int fd = -1; _cleanup_fdset_free_ FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_new_fill.XXXXXX"; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(fdset_new_fill(&fdset) >= 0); assert_se(fdset_contains(fdset, fd)); unlink(name); } static void test_fdset_put_dup(void) { _cleanup_close_ int fd = -1; int copyfd = -1; _cleanup_fdset_free_ FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_put_dup.XXXXXX"; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); fdset = fdset_new(); assert_se(fdset); copyfd = fdset_put_dup(fdset, fd); assert_se(copyfd >= 0 && copyfd != fd); assert_se(fdset_contains(fdset, copyfd)); assert_se(!fdset_contains(fdset, fd)); unlink(name); } static void test_fdset_cloexec(void) { int fd = -1; _cleanup_fdset_free_ FDSet *fdset = NULL; int flags = -1; char name[] = "/tmp/test-fdset_cloexec.XXXXXX"; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); fdset = fdset_new(); assert_se(fdset); assert_se(fdset_put(fdset, fd)); assert_se(fdset_cloexec(fdset, false) >= 0); flags = fcntl(fd, F_GETFD); assert_se(flags >= 0); assert_se(!(flags & FD_CLOEXEC)); assert_se(fdset_cloexec(fdset, true) >= 0); flags = fcntl(fd, F_GETFD); assert_se(flags >= 0); assert_se(flags & FD_CLOEXEC); unlink(name); } static void test_fdset_close_others(void) { int fd = -1; int copyfd = -1; _cleanup_fdset_free_ FDSet *fdset = NULL; int flags = -1; char name[] = "/tmp/test-fdset_close_others.XXXXXX"; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); fdset = fdset_new(); assert_se(fdset); copyfd = fdset_put_dup(fdset, fd); assert_se(copyfd >= 0); assert_se(fdset_close_others(fdset) >= 0); flags = fcntl(fd, F_GETFD); assert_se(flags < 0); flags = fcntl(copyfd, F_GETFD); assert_se(flags >= 0); unlink(name); } static void test_fdset_remove(void) { _cleanup_close_ int fd = -1; FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_remove.XXXXXX"; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); fdset = fdset_new(); assert_se(fdset); assert_se(fdset_put(fdset, fd) >= 0); assert_se(fdset_remove(fdset, fd) >= 0); assert_se(!fdset_contains(fdset, fd)); fdset_free(fdset); assert_se(fcntl(fd, F_GETFD) >= 0); unlink(name); } static void test_fdset_iterate(void) { int fd = -1; FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_iterate.XXXXXX"; Iterator i; int c = 0; int a; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); fdset = fdset_new(); assert_se(fdset); assert_se(fdset_put(fdset, fd) >= 0); assert_se(fdset_put(fdset, fd) >= 0); assert_se(fdset_put(fdset, fd) >= 0); FDSET_FOREACH(a, fdset, i) { c++; assert_se(a == fd); } assert_se(c == 1); fdset_free(fdset); unlink(name); } static void test_fdset_isempty(void) { int fd; _cleanup_fdset_free_ FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_isempty.XXXXXX"; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); fdset = fdset_new(); assert_se(fdset); assert_se(fdset_isempty(fdset)); assert_se(fdset_put(fdset, fd) >= 0); assert_se(!fdset_isempty(fdset)); unlink(name); } static void test_fdset_steal_first(void) { int fd; _cleanup_fdset_free_ FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_steal_first.XXXXXX"; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); fdset = fdset_new(); assert_se(fdset); assert_se(fdset_steal_first(fdset) < 0); assert_se(fdset_put(fdset, fd) >= 0); assert_se(fdset_steal_first(fdset) == fd); assert_se(fdset_steal_first(fdset) < 0); assert_se(fdset_put(fdset, fd) >= 0); unlink(name); } static void test_fdset_new_array(void) { int fds[] = {10, 11, 12, 13}; _cleanup_fdset_free_ FDSet *fdset = NULL; assert_se(fdset_new_array(&fdset, fds, 4) >= 0); assert_se(fdset_size(fdset) == 4); assert_se(fdset_contains(fdset, 10)); assert_se(fdset_contains(fdset, 11)); assert_se(fdset_contains(fdset, 12)); assert_se(fdset_contains(fdset, 13)); } int main(int argc, char *argv[]) { test_fdset_new_fill(); test_fdset_put_dup(); test_fdset_cloexec(); test_fdset_close_others(); test_fdset_remove(); test_fdset_iterate(); test_fdset_isempty(); test_fdset_steal_first(); test_fdset_new_array(); return 0; } systemd-229/src/test/test-fileio.c000066400000000000000000000330561265713322000172260ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "ctype.h" #include "def.h" #include "env-util.h" #include "fd-util.h" #include "fileio.h" #include "parse-util.h" #include "process-util.h" #include "string-util.h" #include "strv.h" #include "util.h" static void test_parse_env_file(void) { char t[] = "/tmp/test-fileio-in-XXXXXX", p[] = "/tmp/test-fileio-out-XXXXXX"; int fd, r; FILE *f; _cleanup_free_ char *one = NULL, *two = NULL, *three = NULL, *four = NULL, *five = NULL, *six = NULL, *seven = NULL, *eight = NULL, *nine = NULL, *ten = NULL; _cleanup_strv_free_ char **a = NULL, **b = NULL; char **i; unsigned k; fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); close(fd); fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); f = fdopen(fd, "w"); assert_se(f); fputs("one=BAR \n" "# comment\n" " # comment \n" " ; comment \n" " two = bar \n" "invalid line\n" "invalid line #comment\n" "three = \"333\n" "xxxx\"\n" "four = \'44\\\"44\'\n" "five = \'55\\\'55\' \"FIVE\" cinco \n" "six = seis sechs\\\n" " sis\n" "seven=\"sevenval\" #nocomment\n" "eight=eightval #nocomment\n" "export nine=nineval\n" "ten=", f); fflush(f); fclose(f); r = load_env_file(NULL, t, NULL, &a); assert_se(r >= 0); STRV_FOREACH(i, a) log_info("Got: <%s>", *i); assert_se(streq_ptr(a[0], "one=BAR")); assert_se(streq_ptr(a[1], "two=bar")); assert_se(streq_ptr(a[2], "three=333\nxxxx")); assert_se(streq_ptr(a[3], "four=44\"44")); assert_se(streq_ptr(a[4], "five=55\'55FIVEcinco")); assert_se(streq_ptr(a[5], "six=seis sechs sis")); assert_se(streq_ptr(a[6], "seven=sevenval#nocomment")); assert_se(streq_ptr(a[7], "eight=eightval #nocomment")); assert_se(streq_ptr(a[8], "export nine=nineval")); assert_se(streq_ptr(a[9], "ten=")); assert_se(a[10] == NULL); strv_env_clean(a); k = 0; STRV_FOREACH(i, b) { log_info("Got2: <%s>", *i); assert_se(streq(*i, a[k++])); } r = parse_env_file( t, NULL, "one", &one, "two", &two, "three", &three, "four", &four, "five", &five, "six", &six, "seven", &seven, "eight", &eight, "export nine", &nine, "ten", &ten, NULL); assert_se(r >= 0); log_info("one=[%s]", strna(one)); log_info("two=[%s]", strna(two)); log_info("three=[%s]", strna(three)); log_info("four=[%s]", strna(four)); log_info("five=[%s]", strna(five)); log_info("six=[%s]", strna(six)); log_info("seven=[%s]", strna(seven)); log_info("eight=[%s]", strna(eight)); log_info("export nine=[%s]", strna(nine)); log_info("ten=[%s]", strna(nine)); assert_se(streq(one, "BAR")); assert_se(streq(two, "bar")); assert_se(streq(three, "333\nxxxx")); assert_se(streq(four, "44\"44")); assert_se(streq(five, "55\'55FIVEcinco")); assert_se(streq(six, "seis sechs sis")); assert_se(streq(seven, "sevenval#nocomment")); assert_se(streq(eight, "eightval #nocomment")); assert_se(streq(nine, "nineval")); assert_se(ten == NULL); r = write_env_file(p, a); assert_se(r >= 0); r = load_env_file(NULL, p, NULL, &b); assert_se(r >= 0); unlink(t); unlink(p); } static void test_parse_multiline_env_file(void) { char t[] = "/tmp/test-fileio-in-XXXXXX", p[] = "/tmp/test-fileio-out-XXXXXX"; int fd, r; FILE *f; _cleanup_strv_free_ char **a = NULL, **b = NULL; char **i; fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); close(fd); fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); f = fdopen(fd, "w"); assert_se(f); fputs("one=BAR\\\n" " VAR\\\n" "\tGAR\n" "#comment\n" "two=\"bar\\\n" " var\\\n" "\tgar\"\n" "#comment\n" "tri=\"bar \\\n" " var \\\n" "\tgar \"\n", f); fflush(f); fclose(f); r = load_env_file(NULL, t, NULL, &a); assert_se(r >= 0); STRV_FOREACH(i, a) log_info("Got: <%s>", *i); assert_se(streq_ptr(a[0], "one=BAR VAR\tGAR")); assert_se(streq_ptr(a[1], "two=bar var\tgar")); assert_se(streq_ptr(a[2], "tri=bar var \tgar ")); assert_se(a[3] == NULL); r = write_env_file(p, a); assert_se(r >= 0); r = load_env_file(NULL, p, NULL, &b); assert_se(r >= 0); unlink(t); unlink(p); } static void test_executable_is_script(void) { char t[] = "/tmp/test-executable-XXXXXX"; int fd, r; FILE *f; char *command; fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); f = fdopen(fd, "w"); assert_se(f); fputs("#! /bin/script -a -b \ngoo goo", f); fflush(f); r = executable_is_script(t, &command); assert_se(r > 0); assert_se(streq(command, "/bin/script")); free(command); r = executable_is_script("/bin/sh", &command); assert_se(r == 0); r = executable_is_script("/usr/bin/yum", &command); assert_se(r > 0 || r == -ENOENT); if (r > 0) { assert_se(startswith(command, "/")); free(command); } fclose(f); unlink(t); } static void test_status_field(void) { _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL, *z = NULL; unsigned long long total = 0, buffers = 0; int r; assert_se(get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t) == 0); puts(t); assert_se(streq(t, "1")); r = get_proc_field("/proc/meminfo", "MemTotal", WHITESPACE, &p); if (r != -ENOENT) { assert_se(r == 0); puts(p); assert_se(safe_atollu(p, &total) == 0); } r = get_proc_field("/proc/meminfo", "Buffers", WHITESPACE, &s); if (r != -ENOENT) { assert_se(r == 0); puts(s); assert_se(safe_atollu(s, &buffers) == 0); } if (p) assert_se(buffers < total); /* Seccomp should be a good test for field full of zeros. */ r = get_proc_field("/proc/meminfo", "Seccomp", WHITESPACE, &z); if (r != -ENOENT) { assert_se(r == 0); puts(z); assert_se(safe_atollu(z, &buffers) == 0); } } static void test_capeff(void) { int pid, p; for (pid = 0; pid < 2; pid++) { _cleanup_free_ char *capeff = NULL; int r; r = get_process_capeff(0, &capeff); log_info("capeff: '%s' (r=%d)", capeff, r); if (r == -ENOENT || r == -EPERM) return; assert_se(r == 0); assert_se(*capeff); p = capeff[strspn(capeff, DIGITS "abcdefABCDEF")]; assert_se(!p || isspace(p)); } } static void test_write_string_stream(void) { char fn[] = "/tmp/test-write_string_stream-XXXXXX"; _cleanup_fclose_ FILE *f = NULL; int fd; char buf[64]; fd = mkostemp_safe(fn, O_RDWR); assert_se(fd >= 0); f = fdopen(fd, "r"); assert_se(f); assert_se(write_string_stream(f, "boohoo", true) < 0); f = freopen(fn, "r+", f); assert_se(f); assert_se(write_string_stream(f, "boohoo", true) == 0); rewind(f); assert_se(fgets(buf, sizeof(buf), f)); assert_se(streq(buf, "boohoo\n")); f = freopen(fn, "w+", f); assert_se(f); assert_se(write_string_stream(f, "boohoo", false) == 0); rewind(f); assert_se(fgets(buf, sizeof(buf), f)); printf(">%s<", buf); assert_se(streq(buf, "boohoo")); unlink(fn); } static void test_write_string_file(void) { char fn[] = "/tmp/test-write_string_file-XXXXXX"; char buf[64] = {}; _cleanup_close_ int fd; fd = mkostemp_safe(fn, O_RDWR); assert_se(fd >= 0); assert_se(write_string_file(fn, "boohoo", WRITE_STRING_FILE_CREATE) == 0); assert_se(read(fd, buf, sizeof(buf)) == 7); assert_se(streq(buf, "boohoo\n")); unlink(fn); } static void test_write_string_file_no_create(void) { char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX"; _cleanup_close_ int fd; char buf[64] = {0}; fd = mkostemp_safe(fn, O_RDWR); assert_se(fd >= 0); assert_se(write_string_file("/a/file/which/does/not/exists/i/guess", "boohoo", 0) < 0); assert_se(write_string_file(fn, "boohoo", 0) == 0); assert_se(read(fd, buf, sizeof(buf)) == strlen("boohoo\n")); assert_se(streq(buf, "boohoo\n")); unlink(fn); } static void test_write_string_file_verify(void) { _cleanup_free_ char *buf = NULL, *buf2 = NULL; int r; assert_se(read_one_line_file("/proc/cmdline", &buf) >= 0); assert_se((buf2 = strjoin(buf, "\n", NULL))); r = write_string_file("/proc/cmdline", buf, 0); assert_se(r == -EACCES || r == -EIO); r = write_string_file("/proc/cmdline", buf2, 0); assert_se(r == -EACCES || r == -EIO); assert_se(write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0); assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0); r = write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE); assert_se(r == -EACCES || r == -EIO); assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE) == 0); } static void test_load_env_file_pairs(void) { char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX"; int fd; int r; _cleanup_fclose_ FILE *f = NULL; _cleanup_strv_free_ char **l = NULL; char **k, **v; fd = mkostemp_safe(fn, O_RDWR); assert_se(fd >= 0); r = write_string_file(fn, "NAME=\"Arch Linux\"\n" "ID=arch\n" "PRETTY_NAME=\"Arch Linux\"\n" "ANSI_COLOR=\"0;36\"\n" "HOME_URL=\"https://www.archlinux.org/\"\n" "SUPPORT_URL=\"https://bbs.archlinux.org/\"\n" "BUG_REPORT_URL=\"https://bugs.archlinux.org/\"\n", WRITE_STRING_FILE_CREATE); assert_se(r == 0); f = fdopen(fd, "r"); assert_se(f); r = load_env_file_pairs(f, fn, NULL, &l); assert_se(r >= 0); assert_se(strv_length(l) == 14); STRV_FOREACH_PAIR(k, v, l) { assert_se(STR_IN_SET(*k, "NAME", "ID", "PRETTY_NAME", "ANSI_COLOR", "HOME_URL", "SUPPORT_URL", "BUG_REPORT_URL")); printf("%s=%s\n", *k, *v); if (streq(*k, "NAME")) assert_se(streq(*v, "Arch Linux")); if (streq(*k, "ID")) assert_se(streq(*v, "arch")); if (streq(*k, "PRETTY_NAME")) assert_se(streq(*v, "Arch Linux")); if (streq(*k, "ANSI_COLOR")) assert_se(streq(*v, "0;36")); if (streq(*k, "HOME_URL")) assert_se(streq(*v, "https://www.archlinux.org/")); if (streq(*k, "SUPPORT_URL")) assert_se(streq(*v, "https://bbs.archlinux.org/")); if (streq(*k, "BUG_REPORT_URL")) assert_se(streq(*v, "https://bugs.archlinux.org/")); } unlink(fn); } int main(int argc, char *argv[]) { log_parse_environment(); log_open(); test_parse_env_file(); test_parse_multiline_env_file(); test_executable_is_script(); test_status_field(); test_capeff(); test_write_string_stream(); test_write_string_file(); test_write_string_file_no_create(); test_write_string_file_verify(); test_load_env_file_pairs(); return 0; } systemd-229/src/test/test-firewall-util.c000066400000000000000000000046271265713322000205410ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "firewall-util.h" #include "log.h" #define MAKE_IN_ADDR_UNION(a,b,c,d) (union in_addr_union) { .in.s_addr = htobe32((uint32_t) (a) << 24 | (uint32_t) (b) << 16 | (uint32_t) (c) << 8 | (uint32_t) (d))} int main(int argc, char *argv[]) { int r; log_set_max_level(LOG_DEBUG); r = fw_add_masquerade(true, AF_INET, 0, NULL, 0, "foobar", NULL, 0); if (r < 0) log_error_errno(r, "Failed to modify firewall: %m"); r = fw_add_masquerade(true, AF_INET, 0, NULL, 0, "foobar", NULL, 0); if (r < 0) log_error_errno(r, "Failed to modify firewall: %m"); r = fw_add_masquerade(false, AF_INET, 0, NULL, 0, "foobar", NULL, 0); if (r < 0) log_error_errno(r, "Failed to modify firewall: %m"); r = fw_add_local_dnat(true, AF_INET, IPPROTO_TCP, NULL, NULL, 0, NULL, 0, 4711, &MAKE_IN_ADDR_UNION(1, 2, 3, 4), 815, NULL); if (r < 0) log_error_errno(r, "Failed to modify firewall: %m"); r = fw_add_local_dnat(true, AF_INET, IPPROTO_TCP, NULL, NULL, 0, NULL, 0, 4711, &MAKE_IN_ADDR_UNION(1, 2, 3, 4), 815, NULL); if (r < 0) log_error_errno(r, "Failed to modify firewall: %m"); r = fw_add_local_dnat(true, AF_INET, IPPROTO_TCP, NULL, NULL, 0, NULL, 0, 4711, &MAKE_IN_ADDR_UNION(1, 2, 3, 5), 815, &MAKE_IN_ADDR_UNION(1, 2, 3, 4)); if (r < 0) log_error_errno(r, "Failed to modify firewall: %m"); r = fw_add_local_dnat(false, AF_INET, IPPROTO_TCP, NULL, NULL, 0, NULL, 0, 4711, &MAKE_IN_ADDR_UNION(1, 2, 3, 5), 815, NULL); if (r < 0) log_error_errno(r, "Failed to modify firewall: %m"); return 0; } systemd-229/src/test/test-fstab-util.c000066400000000000000000000150301265713322000200210ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "fstab-util.h" #include "log.h" #include "string-util.h" #include "util.h" /* int fstab_filter_options(const char *opts, const char *names, const char **namefound, char **value, char **filtered); */ static void do_fstab_filter_options(const char *opts, const char *remove, int r_expected, const char *name_expected, const char *value_expected, const char *filtered_expected) { int r; const char *name; _cleanup_free_ char *value, *filtered; r = fstab_filter_options(opts, remove, &name, &value, &filtered); log_info("\"%s\" → %d, \"%s\", \"%s\", \"%s\", expected %d, \"%s\", \"%s\", \"%s\"", opts, r, name, value, filtered, r_expected, name_expected, value_expected, filtered_expected ?: opts); assert_se(r == r_expected); assert_se(streq_ptr(name, name_expected)); assert_se(streq_ptr(value, value_expected)); assert_se(streq_ptr(filtered, filtered_expected ?: opts)); /* also test the malloc-less mode */ r = fstab_filter_options(opts, remove, &name, NULL, NULL); log_info("\"%s\" → %d, \"%s\", expected %d, \"%s\"", opts, r, name, r_expected, name_expected); assert_se(r == r_expected); assert_se(streq_ptr(name, name_expected)); } static void test_fstab_filter_options(void) { do_fstab_filter_options("opt=0", "opt\0x-opt\0", 1, "opt", "0", ""); do_fstab_filter_options("opt=0", "x-opt\0opt\0", 1, "opt", "0", ""); do_fstab_filter_options("opt", "opt\0x-opt\0", 1, "opt", NULL, ""); do_fstab_filter_options("opt", "x-opt\0opt\0", 1, "opt", NULL, ""); do_fstab_filter_options("x-opt", "x-opt\0opt\0", 1, "x-opt", NULL, ""); do_fstab_filter_options("opt=0,other", "opt\0x-opt\0", 1, "opt", "0", "other"); do_fstab_filter_options("opt=0,other", "x-opt\0opt\0", 1, "opt", "0", "other"); do_fstab_filter_options("opt,other", "opt\0x-opt\0", 1, "opt", NULL, "other"); do_fstab_filter_options("opt,other", "x-opt\0opt\0", 1, "opt", NULL, "other"); do_fstab_filter_options("x-opt,other", "opt\0x-opt\0", 1, "x-opt", NULL, "other"); do_fstab_filter_options("opto=0,other", "opt\0x-opt\0", 0, NULL, NULL, NULL); do_fstab_filter_options("opto,other", "opt\0x-opt\0", 0, NULL, NULL, NULL); do_fstab_filter_options("x-opto,other", "opt\0x-opt\0", 0, NULL, NULL, NULL); do_fstab_filter_options("first,opt=0", "opt\0x-opt\0", 1, "opt", "0", "first"); do_fstab_filter_options("first=1,opt=0", "opt\0x-opt\0", 1, "opt", "0", "first=1"); do_fstab_filter_options("first,opt=", "opt\0x-opt\0", 1, "opt", "", "first"); do_fstab_filter_options("first=1,opt", "opt\0x-opt\0", 1, "opt", NULL, "first=1"); do_fstab_filter_options("first=1,x-opt", "opt\0x-opt\0", 1, "x-opt", NULL, "first=1"); do_fstab_filter_options("first,opt=0,last=1", "opt\0x-opt\0", 1, "opt", "0", "first,last=1"); do_fstab_filter_options("first=1,opt=0,last=2", "x-opt\0opt\0", 1, "opt", "0", "first=1,last=2"); do_fstab_filter_options("first,opt,last", "opt\0", 1, "opt", NULL, "first,last"); do_fstab_filter_options("first=1,opt,last", "x-opt\0opt\0", 1, "opt", NULL, "first=1,last"); do_fstab_filter_options("first=,opt,last", "opt\0noopt\0", 1, "opt", NULL, "first=,last"); /* check repeated options */ do_fstab_filter_options("first,opt=0,noopt=1,last=1", "opt\0noopt\0", 1, "noopt", "1", "first,last=1"); do_fstab_filter_options("first=1,opt=0,last=2,opt=1", "opt\0", 1, "opt", "1", "first=1,last=2"); do_fstab_filter_options("x-opt=0,x-opt=1", "opt\0x-opt\0", 1, "x-opt", "1", ""); do_fstab_filter_options("opt=0,x-opt=1", "opt\0x-opt\0", 1, "x-opt", "1", ""); /* check that semicolons are not misinterpreted */ do_fstab_filter_options("opt=0;", "opt\0", 1, "opt", "0;", ""); do_fstab_filter_options("opt;=0", "x-opt\0opt\0noopt\0x-noopt\0", 0, NULL, NULL, NULL); do_fstab_filter_options("opt;", "opt\0x-opt\0", 0, NULL, NULL, NULL); /* check that spaces are not misinterpreted */ do_fstab_filter_options("opt=0 ", "opt\0", 1, "opt", "0 ", ""); do_fstab_filter_options("opt =0", "x-opt\0opt\0noopt\0x-noopt\0", 0, NULL, NULL, NULL); do_fstab_filter_options(" opt ", "opt\0x-opt\0", 0, NULL, NULL, NULL); /* check function will NULL args */ do_fstab_filter_options(NULL, "opt\0", 0, NULL, NULL, ""); do_fstab_filter_options("", "opt\0", 0, NULL, NULL, ""); } static void test_fstab_find_pri(void) { int pri = -1; assert_se(fstab_find_pri("pri", &pri) == 0); assert_se(pri == -1); assert_se(fstab_find_pri("pri=11", &pri) == 1); assert_se(pri == 11); assert_se(fstab_find_pri("opt,pri=12,opt", &pri) == 1); assert_se(pri == 12); assert_se(fstab_find_pri("opt,opt,pri=12,pri=13", &pri) == 1); assert_se(pri == 13); } static void test_fstab_yes_no_option(void) { assert_se(fstab_test_yes_no_option("nofail,fail,nofail", "nofail\0fail\0") == true); assert_se(fstab_test_yes_no_option("nofail,nofail,fail", "nofail\0fail\0") == false); assert_se(fstab_test_yes_no_option("abc,cde,afail", "nofail\0fail\0") == false); assert_se(fstab_test_yes_no_option("nofail,fail=0,nofail=0", "nofail\0fail\0") == true); assert_se(fstab_test_yes_no_option("nofail,nofail=0,fail=0", "nofail\0fail\0") == false); } int main(void) { test_fstab_filter_options(); test_fstab_find_pri(); test_fstab_yes_no_option(); } systemd-229/src/test/test-hashmap-plain.c000066400000000000000000000614551265713322000205050ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2013 Daniel Buch systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "hashmap.h" #include "string-util.h" #include "strv.h" #include "util.h" void test_hashmap_funcs(void); static void test_hashmap_replace(void) { Hashmap *m; char *val1, *val2, *val3, *val4, *val5, *r; m = hashmap_new(&string_hash_ops); val1 = strdup("val1"); assert_se(val1); val2 = strdup("val2"); assert_se(val2); val3 = strdup("val3"); assert_se(val3); val4 = strdup("val4"); assert_se(val4); val5 = strdup("val5"); assert_se(val5); hashmap_put(m, "key 1", val1); hashmap_put(m, "key 2", val2); hashmap_put(m, "key 3", val3); hashmap_put(m, "key 4", val4); hashmap_replace(m, "key 3", val1); r = hashmap_get(m, "key 3"); assert_se(streq(r, "val1")); hashmap_replace(m, "key 5", val5); r = hashmap_get(m, "key 5"); assert_se(streq(r, "val5")); free(val1); free(val2); free(val3); free(val4); free(val5); hashmap_free(m); } static void test_hashmap_copy(void) { Hashmap *m, *copy; char *val1, *val2, *val3, *val4, *r; val1 = strdup("val1"); assert_se(val1); val2 = strdup("val2"); assert_se(val2); val3 = strdup("val3"); assert_se(val3); val4 = strdup("val4"); assert_se(val4); m = hashmap_new(&string_hash_ops); hashmap_put(m, "key 1", val1); hashmap_put(m, "key 2", val2); hashmap_put(m, "key 3", val3); hashmap_put(m, "key 4", val4); copy = hashmap_copy(m); r = hashmap_get(copy, "key 1"); assert_se(streq(r, "val1")); r = hashmap_get(copy, "key 2"); assert_se(streq(r, "val2")); r = hashmap_get(copy, "key 3"); assert_se(streq(r, "val3")); r = hashmap_get(copy, "key 4"); assert_se(streq(r, "val4")); hashmap_free_free(copy); hashmap_free(m); } static void test_hashmap_get_strv(void) { Hashmap *m; char **strv; char *val1, *val2, *val3, *val4; val1 = strdup("val1"); assert_se(val1); val2 = strdup("val2"); assert_se(val2); val3 = strdup("val3"); assert_se(val3); val4 = strdup("val4"); assert_se(val4); m = hashmap_new(&string_hash_ops); hashmap_put(m, "key 1", val1); hashmap_put(m, "key 2", val2); hashmap_put(m, "key 3", val3); hashmap_put(m, "key 4", val4); strv = hashmap_get_strv(m); #ifndef ORDERED strv = strv_sort(strv); #endif assert_se(streq(strv[0], "val1")); assert_se(streq(strv[1], "val2")); assert_se(streq(strv[2], "val3")); assert_se(streq(strv[3], "val4")); strv_free(strv); hashmap_free(m); } static void test_hashmap_move_one(void) { Hashmap *m, *n; char *val1, *val2, *val3, *val4, *r; val1 = strdup("val1"); assert_se(val1); val2 = strdup("val2"); assert_se(val2); val3 = strdup("val3"); assert_se(val3); val4 = strdup("val4"); assert_se(val4); m = hashmap_new(&string_hash_ops); n = hashmap_new(&string_hash_ops); hashmap_put(m, "key 1", val1); hashmap_put(m, "key 2", val2); hashmap_put(m, "key 3", val3); hashmap_put(m, "key 4", val4); assert_se(hashmap_move_one(n, NULL, "key 3") == -ENOENT); assert_se(hashmap_move_one(n, m, "key 5") == -ENOENT); assert_se(hashmap_move_one(n, m, "key 3") == 0); assert_se(hashmap_move_one(n, m, "key 4") == 0); r = hashmap_get(n, "key 3"); assert_se(r && streq(r, "val3")); r = hashmap_get(n, "key 4"); assert_se(r && streq(r, "val4")); r = hashmap_get(m, "key 3"); assert_se(!r); assert_se(hashmap_move_one(n, m, "key 3") == -EEXIST); hashmap_free_free(m); hashmap_free_free(n); } static void test_hashmap_move(void) { Hashmap *m, *n; char *val1, *val2, *val3, *val4, *r; val1 = strdup("val1"); assert_se(val1); val2 = strdup("val2"); assert_se(val2); val3 = strdup("val3"); assert_se(val3); val4 = strdup("val4"); assert_se(val4); m = hashmap_new(&string_hash_ops); n = hashmap_new(&string_hash_ops); hashmap_put(n, "key 1", strdup(val1)); hashmap_put(m, "key 1", val1); hashmap_put(m, "key 2", val2); hashmap_put(m, "key 3", val3); hashmap_put(m, "key 4", val4); assert_se(hashmap_move(n, NULL) == 0); assert_se(hashmap_move(n, m) == 0); assert_se(hashmap_size(m) == 1); r = hashmap_get(m, "key 1"); assert_se(r && streq(r, "val1")); r = hashmap_get(n, "key 1"); assert_se(r && streq(r, "val1")); r = hashmap_get(n, "key 2"); assert_se(r && streq(r, "val2")); r = hashmap_get(n, "key 3"); assert_se(r && streq(r, "val3")); r = hashmap_get(n, "key 4"); assert_se(r && streq(r, "val4")); hashmap_free_free(m); hashmap_free_free(n); } static void test_hashmap_update(void) { Hashmap *m; char *val1, *val2, *r; m = hashmap_new(&string_hash_ops); val1 = strdup("old_value"); assert_se(val1); val2 = strdup("new_value"); assert_se(val2); hashmap_put(m, "key 1", val1); r = hashmap_get(m, "key 1"); assert_se(streq(r, "old_value")); assert_se(hashmap_update(m, "key 2", val2) == -ENOENT); r = hashmap_get(m, "key 1"); assert_se(streq(r, "old_value")); assert_se(hashmap_update(m, "key 1", val2) == 0); r = hashmap_get(m, "key 1"); assert_se(streq(r, "new_value")); free(val1); free(val2); hashmap_free(m); } static void test_hashmap_put(void) { Hashmap *m = NULL; int valid_hashmap_put; void *val1 = (void*) "val 1"; void *val2 = (void*) "val 2"; _cleanup_free_ char* key1 = NULL; assert_se(hashmap_ensure_allocated(&m, &string_hash_ops) >= 0); assert_se(m); valid_hashmap_put = hashmap_put(m, "key 1", val1); assert_se(valid_hashmap_put == 1); assert_se(hashmap_put(m, "key 1", val1) == 0); assert_se(hashmap_put(m, "key 1", val2) == -EEXIST); key1 = strdup("key 1"); assert_se(hashmap_put(m, key1, val1) == 0); assert_se(hashmap_put(m, key1, val2) == -EEXIST); hashmap_free(m); } static void test_hashmap_remove(void) { _cleanup_hashmap_free_ Hashmap *m = NULL; char *r; r = hashmap_remove(NULL, "key 1"); assert_se(r == NULL); m = hashmap_new(&string_hash_ops); assert_se(m); r = hashmap_remove(m, "no such key"); assert_se(r == NULL); hashmap_put(m, "key 1", (void*) "val 1"); hashmap_put(m, "key 2", (void*) "val 2"); r = hashmap_remove(m, "key 1"); assert_se(streq(r, "val 1")); r = hashmap_get(m, "key 2"); assert_se(streq(r, "val 2")); assert_se(!hashmap_get(m, "key 1")); } static void test_hashmap_remove2(void) { _cleanup_hashmap_free_free_free_ Hashmap *m = NULL; char key1[] = "key 1"; char key2[] = "key 2"; char val1[] = "val 1"; char val2[] = "val 2"; void *r, *r2; r = hashmap_remove2(NULL, "key 1", &r2); assert_se(r == NULL); m = hashmap_new(&string_hash_ops); assert_se(m); r = hashmap_remove2(m, "no such key", &r2); assert_se(r == NULL); hashmap_put(m, strdup(key1), strdup(val1)); hashmap_put(m, strdup(key2), strdup(val2)); r = hashmap_remove2(m, key1, &r2); assert_se(streq(r, val1)); assert_se(streq(r2, key1)); free(r); free(r2); r = hashmap_get(m, key2); assert_se(streq(r, val2)); assert_se(!hashmap_get(m, key1)); } static void test_hashmap_remove_value(void) { _cleanup_hashmap_free_ Hashmap *m = NULL; char *r; r = hashmap_remove_value(NULL, "key 1", (void*) "val 1"); assert_se(r == NULL); m = hashmap_new(&string_hash_ops); assert_se(m); r = hashmap_remove_value(m, "key 1", (void*) "val 1"); assert_se(r == NULL); hashmap_put(m, "key 1", (void*) "val 1"); hashmap_put(m, "key 2", (void*) "val 2"); r = hashmap_remove_value(m, "key 1", (void*) "val 1"); assert_se(streq(r, "val 1")); r = hashmap_get(m, "key 2"); assert_se(streq(r, "val 2")); assert_se(!hashmap_get(m, "key 1")); r = hashmap_remove_value(m, "key 2", (void*) "val 1"); assert_se(r == NULL); r = hashmap_get(m, "key 2"); assert_se(streq(r, "val 2")); assert_se(!hashmap_get(m, "key 1")); } static void test_hashmap_remove_and_put(void) { _cleanup_hashmap_free_ Hashmap *m = NULL; int valid; char *r; m = hashmap_new(&string_hash_ops); assert_se(m); valid = hashmap_remove_and_put(m, "invalid key", "new key", NULL); assert_se(valid == -ENOENT); valid = hashmap_put(m, "key 1", (void*) (const char *) "val 1"); assert_se(valid == 1); valid = hashmap_remove_and_put(NULL, "key 1", "key 2", (void*) (const char *) "val 2"); assert_se(valid == -ENOENT); valid = hashmap_remove_and_put(m, "key 1", "key 2", (void*) (const char *) "val 2"); assert_se(valid == 0); r = hashmap_get(m, "key 2"); assert_se(streq(r, "val 2")); assert_se(!hashmap_get(m, "key 1")); valid = hashmap_put(m, "key 3", (void*) (const char *) "val 3"); assert_se(valid == 1); valid = hashmap_remove_and_put(m, "key 3", "key 2", (void*) (const char *) "val 2"); assert_se(valid == -EEXIST); } static void test_hashmap_remove_and_replace(void) { _cleanup_hashmap_free_ Hashmap *m = NULL; int valid; void *key1 = UINT_TO_PTR(1); void *key2 = UINT_TO_PTR(2); void *key3 = UINT_TO_PTR(3); void *r; int i, j; m = hashmap_new(&trivial_hash_ops); assert_se(m); valid = hashmap_remove_and_replace(m, key1, key2, NULL); assert_se(valid == -ENOENT); valid = hashmap_put(m, key1, key1); assert_se(valid == 1); valid = hashmap_remove_and_replace(NULL, key1, key2, key2); assert_se(valid == -ENOENT); valid = hashmap_remove_and_replace(m, key1, key2, key2); assert_se(valid == 0); r = hashmap_get(m, key2); assert_se(r == key2); assert_se(!hashmap_get(m, key1)); valid = hashmap_put(m, key3, key3); assert_se(valid == 1); valid = hashmap_remove_and_replace(m, key3, key2, key2); assert_se(valid == 0); r = hashmap_get(m, key2); assert_se(r == key2); assert_se(!hashmap_get(m, key3)); /* Repeat this test several times to increase the chance of hitting * the less likely case in hashmap_remove_and_replace where it * compensates for the backward shift. */ for (i = 0; i < 20; i++) { hashmap_clear(m); for (j = 1; j < 7; j++) hashmap_put(m, UINT_TO_PTR(10*i + j), UINT_TO_PTR(10*i + j)); valid = hashmap_remove_and_replace(m, UINT_TO_PTR(10*i + 1), UINT_TO_PTR(10*i + 2), UINT_TO_PTR(10*i + 2)); assert_se(valid == 0); assert_se(!hashmap_get(m, UINT_TO_PTR(10*i + 1))); for (j = 2; j < 7; j++) { r = hashmap_get(m, UINT_TO_PTR(10*i + j)); assert_se(r == UINT_TO_PTR(10*i + j)); } } } static void test_hashmap_ensure_allocated(void) { Hashmap *m; int valid_hashmap; m = hashmap_new(&string_hash_ops); valid_hashmap = hashmap_ensure_allocated(&m, &string_hash_ops); assert_se(valid_hashmap == 0); assert_se(m); hashmap_free(m); } static void test_hashmap_foreach_key(void) { Hashmap *m; Iterator i; bool key_found[] = { false, false, false, false }; const char *s; const char *key; static const char key_table[] = "key 1\0" "key 2\0" "key 3\0" "key 4\0"; m = hashmap_new(&string_hash_ops); NULSTR_FOREACH(key, key_table) hashmap_put(m, key, (void*) (const char*) "my dummy val"); HASHMAP_FOREACH_KEY(s, key, m, i) { assert(s); if (!key_found[0] && streq(key, "key 1")) key_found[0] = true; else if (!key_found[1] && streq(key, "key 2")) key_found[1] = true; else if (!key_found[2] && streq(key, "key 3")) key_found[2] = true; else if (!key_found[3] && streq(key, "fail")) key_found[3] = true; } assert_se(m); assert_se(key_found[0] && key_found[1] && key_found[2] && !key_found[3]); hashmap_free(m); } static void test_hashmap_foreach(void) { Hashmap *m; Iterator i; bool value_found[] = { false, false, false, false }; char *val1, *val2, *val3, *val4, *s; unsigned count; val1 = strdup("my val1"); assert_se(val1); val2 = strdup("my val2"); assert_se(val2); val3 = strdup("my val3"); assert_se(val3); val4 = strdup("my val4"); assert_se(val4); m = NULL; count = 0; HASHMAP_FOREACH(s, m, i) count++; assert_se(count == 0); m = hashmap_new(&string_hash_ops); count = 0; HASHMAP_FOREACH(s, m, i) count++; assert_se(count == 0); hashmap_put(m, "Key 1", val1); hashmap_put(m, "Key 2", val2); hashmap_put(m, "Key 3", val3); hashmap_put(m, "Key 4", val4); HASHMAP_FOREACH(s, m, i) { if (!value_found[0] && streq(s, val1)) value_found[0] = true; else if (!value_found[1] && streq(s, val2)) value_found[1] = true; else if (!value_found[2] && streq(s, val3)) value_found[2] = true; else if (!value_found[3] && streq(s, val4)) value_found[3] = true; } assert_se(m); assert_se(value_found[0] && value_found[1] && value_found[2] && value_found[3]); hashmap_free_free(m); } static void test_hashmap_merge(void) { Hashmap *m; Hashmap *n; char *val1, *val2, *val3, *val4, *r; val1 = strdup("my val1"); assert_se(val1); val2 = strdup("my val2"); assert_se(val2); val3 = strdup("my val3"); assert_se(val3); val4 = strdup("my val4"); assert_se(val4); n = hashmap_new(&string_hash_ops); m = hashmap_new(&string_hash_ops); hashmap_put(m, "Key 1", val1); hashmap_put(m, "Key 2", val2); hashmap_put(n, "Key 3", val3); hashmap_put(n, "Key 4", val4); assert_se(hashmap_merge(m, n) == 0); r = hashmap_get(m, "Key 3"); assert_se(r && streq(r, "my val3")); r = hashmap_get(m, "Key 4"); assert_se(r && streq(r, "my val4")); assert_se(n); assert_se(m); hashmap_free(n); hashmap_free_free(m); } static void test_hashmap_contains(void) { Hashmap *m; char *val1; val1 = strdup("my val"); assert_se(val1); m = hashmap_new(&string_hash_ops); assert_se(!hashmap_contains(m, "Key 1")); hashmap_put(m, "Key 1", val1); assert_se(hashmap_contains(m, "Key 1")); assert_se(!hashmap_contains(m, "Key 2")); assert_se(!hashmap_contains(NULL, "Key 1")); assert_se(m); hashmap_free_free(m); } static void test_hashmap_isempty(void) { Hashmap *m; char *val1; val1 = strdup("my val"); assert_se(val1); m = hashmap_new(&string_hash_ops); assert_se(hashmap_isempty(m)); hashmap_put(m, "Key 1", val1); assert_se(!hashmap_isempty(m)); assert_se(m); hashmap_free_free(m); } static void test_hashmap_size(void) { Hashmap *m; char *val1, *val2, *val3, *val4; val1 = strdup("my val"); assert_se(val1); val2 = strdup("my val"); assert_se(val2); val3 = strdup("my val"); assert_se(val3); val4 = strdup("my val"); assert_se(val4); assert_se(hashmap_size(NULL) == 0); assert_se(hashmap_buckets(NULL) == 0); m = hashmap_new(&string_hash_ops); hashmap_put(m, "Key 1", val1); hashmap_put(m, "Key 2", val2); hashmap_put(m, "Key 3", val3); hashmap_put(m, "Key 4", val4); assert_se(m); assert_se(hashmap_size(m) == 4); assert_se(hashmap_buckets(m) >= 4); hashmap_free_free(m); } static void test_hashmap_get(void) { Hashmap *m; char *r; char *val; val = strdup("my val"); assert_se(val); r = hashmap_get(NULL, "Key 1"); assert_se(r == NULL); m = hashmap_new(&string_hash_ops); hashmap_put(m, "Key 1", val); r = hashmap_get(m, "Key 1"); assert_se(streq(r, val)); r = hashmap_get(m, "no such key"); assert_se(r == NULL); assert_se(m); hashmap_free_free(m); } static void test_hashmap_get2(void) { Hashmap *m; char *r; char *val; char key_orig[] = "Key 1"; void *key_copy; val = strdup("my val"); assert_se(val); key_copy = strdup(key_orig); assert_se(key_copy); r = hashmap_get2(NULL, key_orig, &key_copy); assert_se(r == NULL); m = hashmap_new(&string_hash_ops); hashmap_put(m, key_copy, val); key_copy = NULL; r = hashmap_get2(m, key_orig, &key_copy); assert_se(streq(r, val)); assert_se(key_orig != key_copy); assert_se(streq(key_orig, key_copy)); r = hashmap_get2(m, "no such key", NULL); assert_se(r == NULL); assert_se(m); hashmap_free_free_free(m); } static void crippled_hashmap_func(const void *p, struct siphash *state) { return trivial_hash_func(INT_TO_PTR(PTR_TO_INT(p) & 0xff), state); } static const struct hash_ops crippled_hashmap_ops = { .hash = crippled_hashmap_func, .compare = trivial_compare_func, }; static void test_hashmap_many(void) { Hashmap *h; unsigned i, j; void *v, *k; static const struct { const struct hash_ops *ops; unsigned n_entries; } tests[] = { { .ops = NULL, .n_entries = 1 << 20 }, { .ops = &crippled_hashmap_ops, .n_entries = 1 << 14 }, }; for (j = 0; j < ELEMENTSOF(tests); j++) { assert_se(h = hashmap_new(tests[j].ops)); for (i = 1; i < tests[j].n_entries*3; i+=3) { assert_se(hashmap_put(h, UINT_TO_PTR(i), UINT_TO_PTR(i)) >= 0); assert_se(PTR_TO_UINT(hashmap_get(h, UINT_TO_PTR(i))) == i); } for (i = 1; i < tests[j].n_entries*3; i++) assert_se(hashmap_contains(h, UINT_TO_PTR(i)) == (i % 3 == 1)); log_info("%u <= %u * 0.8 = %g", hashmap_size(h), hashmap_buckets(h), hashmap_buckets(h) * 0.8); assert_se(hashmap_size(h) <= hashmap_buckets(h) * 0.8); assert_se(hashmap_size(h) == tests[j].n_entries); while (!hashmap_isempty(h)) { k = hashmap_first_key(h); v = hashmap_remove(h, k); assert_se(v == k); } hashmap_free(h); } } static void test_hashmap_first(void) { _cleanup_hashmap_free_ Hashmap *m = NULL; m = hashmap_new(&string_hash_ops); assert_se(m); assert_se(!hashmap_first(m)); assert_se(hashmap_put(m, "key 1", (void*) "val 1") == 1); assert_se(streq(hashmap_first(m), "val 1")); assert_se(hashmap_put(m, "key 2", (void*) "val 2") == 1); #ifdef ORDERED assert_se(streq(hashmap_first(m), "val 1")); assert_se(hashmap_remove(m, "key 1")); assert_se(streq(hashmap_first(m), "val 2")); #endif } static void test_hashmap_first_key(void) { _cleanup_hashmap_free_ Hashmap *m = NULL; m = hashmap_new(&string_hash_ops); assert_se(m); assert_se(!hashmap_first_key(m)); assert_se(hashmap_put(m, "key 1", NULL) == 1); assert_se(streq(hashmap_first_key(m), "key 1")); assert_se(hashmap_put(m, "key 2", NULL) == 1); #ifdef ORDERED assert_se(streq(hashmap_first_key(m), "key 1")); assert_se(hashmap_remove(m, "key 1") == NULL); assert_se(streq(hashmap_first_key(m), "key 2")); #endif } static void test_hashmap_steal_first_key(void) { _cleanup_hashmap_free_ Hashmap *m = NULL; m = hashmap_new(&string_hash_ops); assert_se(m); assert_se(!hashmap_steal_first_key(m)); assert_se(hashmap_put(m, "key 1", NULL) == 1); assert_se(streq(hashmap_steal_first_key(m), "key 1")); assert_se(hashmap_isempty(m)); } static void test_hashmap_steal_first(void) { _cleanup_hashmap_free_ Hashmap *m = NULL; int seen[3] = {}; char *val; m = hashmap_new(&string_hash_ops); assert_se(m); assert_se(hashmap_put(m, "key 1", (void*) "1") == 1); assert_se(hashmap_put(m, "key 2", (void*) "22") == 1); assert_se(hashmap_put(m, "key 3", (void*) "333") == 1); while ((val = hashmap_steal_first(m))) seen[strlen(val) - 1]++; assert_se(seen[0] == 1 && seen[1] == 1 && seen[2] == 1); assert_se(hashmap_isempty(m)); } static void test_hashmap_clear_free_free(void) { _cleanup_hashmap_free_ Hashmap *m = NULL; m = hashmap_new(&string_hash_ops); assert_se(m); assert_se(hashmap_put(m, strdup("key 1"), NULL) == 1); assert_se(hashmap_put(m, strdup("key 2"), NULL) == 1); assert_se(hashmap_put(m, strdup("key 3"), NULL) == 1); hashmap_clear_free_free(m); assert_se(hashmap_isempty(m)); } static void test_hashmap_reserve(void) { _cleanup_hashmap_free_ Hashmap *m = NULL; m = hashmap_new(&string_hash_ops); assert_se(hashmap_reserve(m, 1) == 0); assert_se(hashmap_buckets(m) < 1000); assert_se(hashmap_reserve(m, 1000) == 0); assert_se(hashmap_buckets(m) >= 1000); assert_se(hashmap_isempty(m)); assert_se(hashmap_put(m, "key 1", (void*) "val 1") == 1); assert_se(hashmap_reserve(m, UINT_MAX) == -ENOMEM); assert_se(hashmap_reserve(m, UINT_MAX - 1) == -ENOMEM); } void test_hashmap_funcs(void) { test_hashmap_copy(); test_hashmap_get_strv(); test_hashmap_move_one(); test_hashmap_move(); test_hashmap_replace(); test_hashmap_update(); test_hashmap_put(); test_hashmap_remove(); test_hashmap_remove2(); test_hashmap_remove_value(); test_hashmap_remove_and_put(); test_hashmap_remove_and_replace(); test_hashmap_ensure_allocated(); test_hashmap_foreach(); test_hashmap_foreach_key(); test_hashmap_contains(); test_hashmap_merge(); test_hashmap_isempty(); test_hashmap_get(); test_hashmap_get2(); test_hashmap_size(); test_hashmap_many(); test_hashmap_first(); test_hashmap_first_key(); test_hashmap_steal_first_key(); test_hashmap_steal_first(); test_hashmap_clear_free_free(); test_hashmap_reserve(); } systemd-229/src/test/test-hashmap.c000066400000000000000000000045421265713322000173760ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2013 Daniel Buch systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "hashmap.h" #include "util.h" void test_hashmap_funcs(void); void test_ordered_hashmap_funcs(void); static void test_ordered_hashmap_next(void) { _cleanup_ordered_hashmap_free_ OrderedHashmap *m = NULL; int i; assert_se(m = ordered_hashmap_new(NULL)); for (i = -2; i <= 2; i++) assert_se(ordered_hashmap_put(m, INT_TO_PTR(i), INT_TO_PTR(i+10)) == 1); for (i = -2; i <= 1; i++) assert_se(ordered_hashmap_next(m, INT_TO_PTR(i)) == INT_TO_PTR(i+11)); assert_se(!ordered_hashmap_next(m, INT_TO_PTR(2))); assert_se(!ordered_hashmap_next(NULL, INT_TO_PTR(1))); assert_se(!ordered_hashmap_next(m, INT_TO_PTR(3))); } static void test_uint64_compare_func(void) { const uint64_t a = 0x100, b = 0x101; assert_se(uint64_compare_func(&a, &a) == 0); assert_se(uint64_compare_func(&a, &b) == -1); assert_se(uint64_compare_func(&b, &a) == 1); } static void test_trivial_compare_func(void) { assert_se(trivial_compare_func(INT_TO_PTR('a'), INT_TO_PTR('a')) == 0); assert_se(trivial_compare_func(INT_TO_PTR('a'), INT_TO_PTR('b')) == -1); assert_se(trivial_compare_func(INT_TO_PTR('b'), INT_TO_PTR('a')) == 1); } static void test_string_compare_func(void) { assert_se(string_compare_func("fred", "wilma") != 0); assert_se(string_compare_func("fred", "fred") == 0); } int main(int argc, const char *argv[]) { test_hashmap_funcs(); test_ordered_hashmap_funcs(); test_ordered_hashmap_next(); test_uint64_compare_func(); test_trivial_compare_func(); test_string_compare_func(); } systemd-229/src/test/test-helper.h000066400000000000000000000032331265713322000172350ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2013 Holger Hans Peter Freyther systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-daemon.h" #include "macro.h" #define TEST_REQ_RUNNING_SYSTEMD(x) \ if (sd_booted() > 0) { \ x; \ } else { \ printf("systemd not booted skipping '%s'\n", #x); \ } #define MANAGER_SKIP_TEST(r) \ IN_SET(r, \ -EPERM, \ -EACCES, \ -EADDRINUSE, \ -EHOSTDOWN, \ -ENOENT, \ -ENOMEDIUM /* cannot determine cgroup */ \ ) systemd-229/src/test/test-hostname-util.c000066400000000000000000000147711265713322000205530ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Thomas H.P. Andersen Copyright 2015 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "fileio.h" #include "hostname-util.h" #include "string-util.h" #include "util.h" static void test_hostname_is_valid(void) { assert_se(hostname_is_valid("foobar", false)); assert_se(hostname_is_valid("foobar.com", false)); assert_se(!hostname_is_valid("foobar.com.", false)); assert_se(hostname_is_valid("fooBAR", false)); assert_se(hostname_is_valid("fooBAR.com", false)); assert_se(!hostname_is_valid("fooBAR.", false)); assert_se(!hostname_is_valid("fooBAR.com.", false)); assert_se(!hostname_is_valid("fööbar", false)); assert_se(!hostname_is_valid("", false)); assert_se(!hostname_is_valid(".", false)); assert_se(!hostname_is_valid("..", false)); assert_se(!hostname_is_valid("foobar.", false)); assert_se(!hostname_is_valid(".foobar", false)); assert_se(!hostname_is_valid("foo..bar", false)); assert_se(!hostname_is_valid("foo.bar..", false)); assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", false)); assert_se(hostname_is_valid("foobar", true)); assert_se(hostname_is_valid("foobar.com", true)); assert_se(hostname_is_valid("foobar.com.", true)); assert_se(hostname_is_valid("fooBAR", true)); assert_se(hostname_is_valid("fooBAR.com", true)); assert_se(!hostname_is_valid("fooBAR.", true)); assert_se(hostname_is_valid("fooBAR.com.", true)); assert_se(!hostname_is_valid("fööbar", true)); assert_se(!hostname_is_valid("", true)); assert_se(!hostname_is_valid(".", true)); assert_se(!hostname_is_valid("..", true)); assert_se(!hostname_is_valid("foobar.", true)); assert_se(!hostname_is_valid(".foobar", true)); assert_se(!hostname_is_valid("foo..bar", true)); assert_se(!hostname_is_valid("foo.bar..", true)); assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", true)); } static void test_hostname_cleanup(void) { char *s; s = strdupa("foobar"); assert_se(streq(hostname_cleanup(s), "foobar")); s = strdupa("foobar.com"); assert_se(streq(hostname_cleanup(s), "foobar.com")); s = strdupa("foobar.com."); assert_se(streq(hostname_cleanup(s), "foobar.com")); s = strdupa("fooBAR"); assert_se(streq(hostname_cleanup(s), "fooBAR")); s = strdupa("fooBAR.com"); assert_se(streq(hostname_cleanup(s), "fooBAR.com")); s = strdupa("fooBAR."); assert_se(streq(hostname_cleanup(s), "fooBAR")); s = strdupa("fooBAR.com."); assert_se(streq(hostname_cleanup(s), "fooBAR.com")); s = strdupa("fööbar"); assert_se(streq(hostname_cleanup(s), "fbar")); s = strdupa(""); assert_se(isempty(hostname_cleanup(s))); s = strdupa("."); assert_se(isempty(hostname_cleanup(s))); s = strdupa(".."); assert_se(isempty(hostname_cleanup(s))); s = strdupa("foobar."); assert_se(streq(hostname_cleanup(s), "foobar")); s = strdupa(".foobar"); assert_se(streq(hostname_cleanup(s), "foobar")); s = strdupa("foo..bar"); assert_se(streq(hostname_cleanup(s), "foo.bar")); s = strdupa("foo.bar.."); assert_se(streq(hostname_cleanup(s), "foo.bar")); s = strdupa("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); assert_se(streq(hostname_cleanup(s), "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")); } static void test_read_hostname_config(void) { char path[] = "/tmp/hostname.XXXXXX"; char *hostname; int fd; fd = mkostemp_safe(path, O_RDWR|O_CLOEXEC); assert(fd > 0); close(fd); /* simple hostname */ write_string_file(path, "foo", WRITE_STRING_FILE_CREATE); assert_se(read_hostname_config(path, &hostname) == 0); assert_se(streq(hostname, "foo")); hostname = mfree(hostname); /* with comment */ write_string_file(path, "# comment\nfoo", WRITE_STRING_FILE_CREATE); assert_se(read_hostname_config(path, &hostname) == 0); assert_se(hostname); assert_se(streq(hostname, "foo")); hostname = mfree(hostname); /* with comment and extra whitespace */ write_string_file(path, "# comment\n\n foo ", WRITE_STRING_FILE_CREATE); assert_se(read_hostname_config(path, &hostname) == 0); assert_se(hostname); assert_se(streq(hostname, "foo")); hostname = mfree(hostname); /* cleans up name */ write_string_file(path, "!foo/bar.com", WRITE_STRING_FILE_CREATE); assert_se(read_hostname_config(path, &hostname) == 0); assert_se(hostname); assert_se(streq(hostname, "foobar.com")); hostname = mfree(hostname); /* no value set */ hostname = (char*) 0x1234; write_string_file(path, "# nothing here\n", WRITE_STRING_FILE_CREATE); assert_se(read_hostname_config(path, &hostname) == -ENOENT); assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */ /* nonexisting file */ assert_se(read_hostname_config("/non/existing", &hostname) == -ENOENT); assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */ unlink(path); } int main(int argc, char *argv[]) { log_parse_environment(); log_open(); test_hostname_is_valid(); test_hostname_cleanup(); test_read_hostname_config(); return 0; } systemd-229/src/test/test-hostname.c000066400000000000000000000016531265713322000175730ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "hostname-setup.h" #include "util.h" int main(int argc, char* argv[]) { int r; r = hostname_setup(); if (r < 0) log_error_errno(r, "hostname: %m"); return 0; } systemd-229/src/test/test-id128.c000066400000000000000000000056251265713322000166070ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "sd-daemon.h" #include "sd-id128.h" #include "alloc-util.h" #include "macro.h" #include "string-util.h" #include "util.h" #define ID128_WALDI SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10) #define STR_WALDI "0102030405060708090a0b0c0d0e0f10" #define UUID_WALDI "01020304-0506-0708-090a-0b0c0d0e0f10" int main(int argc, char *argv[]) { sd_id128_t id, id2; char t[33]; _cleanup_free_ char *b = NULL; assert_se(sd_id128_randomize(&id) == 0); printf("random: %s\n", sd_id128_to_string(id, t)); assert_se(sd_id128_from_string(t, &id2) == 0); assert_se(sd_id128_equal(id, id2)); if (sd_booted() > 0) { assert_se(sd_id128_get_machine(&id) == 0); printf("machine: %s\n", sd_id128_to_string(id, t)); assert_se(sd_id128_get_boot(&id) == 0); printf("boot: %s\n", sd_id128_to_string(id, t)); } printf("waldi: %s\n", sd_id128_to_string(ID128_WALDI, t)); assert_se(streq(t, STR_WALDI)); assert_se(asprintf(&b, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(ID128_WALDI)) == 32); printf("waldi2: %s\n", b); assert_se(streq(t, b)); assert_se(sd_id128_from_string(UUID_WALDI, &id) >= 0); assert_se(sd_id128_equal(id, ID128_WALDI)); assert_se(sd_id128_from_string("", &id) < 0); assert_se(sd_id128_from_string("01020304-0506-0708-090a-0b0c0d0e0f101", &id) < 0); assert_se(sd_id128_from_string("01020304-0506-0708-090a-0b0c0d0e0f10-", &id) < 0); assert_se(sd_id128_from_string("01020304-0506-0708-090a0b0c0d0e0f10", &id) < 0); assert_se(sd_id128_from_string("010203040506-0708-090a-0b0c0d0e0f10", &id) < 0); assert_se(id128_is_valid(STR_WALDI)); assert_se(id128_is_valid(UUID_WALDI)); assert_se(!id128_is_valid("")); assert_se(!id128_is_valid("01020304-0506-0708-090a-0b0c0d0e0f101")); assert_se(!id128_is_valid("01020304-0506-0708-090a-0b0c0d0e0f10-")); assert_se(!id128_is_valid("01020304-0506-0708-090a0b0c0d0e0f10")); assert_se(!id128_is_valid("010203040506-0708-090a-0b0c0d0e0f10")); return 0; } systemd-229/src/test/test-install-root.c000066400000000000000000001115201265713322000203770ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "fileio.h" #include "install.h" #include "mkdir.h" #include "rm-rf.h" #include "string-util.h" static void test_basic_mask_and_enable(const char *root) { const char *p; UnitFileState state; UnitFileChange *changes = NULL; unsigned n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT); p = strjoina(root, "/usr/lib/systemd/system/a.service"); assert_se(write_string_file(p, "[Install]\n" "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) >= 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED); p = strjoina(root, "/usr/lib/systemd/system/b.service"); assert_se(symlink("a.service", p) >= 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) >= 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED); p = strjoina(root, "/usr/lib/systemd/system/c.service"); assert_se(symlink("/usr/lib/systemd/system/a.service", p) >= 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) >= 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED); p = strjoina(root, "/usr/lib/systemd/system/d.service"); assert_se(symlink("c.service", p) >= 0); /* This one is interesting, as d follows a relative, then an absolute symlink */ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) >= 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_mask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/dev/null")); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_MASKED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_MASKED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_MASKED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_MASKED); /* Enabling a masked unit should fail! */ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == -ESHUTDOWN); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_unmask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == 1); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service")); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED); /* Enabling it again should succeed but be a NOP */ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == 1); assert_se(n_changes == 0); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED); /* Disabling a disabled unit must suceed but be a NOP */ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 0); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; /* Let's enable this indirectly via a symlink */ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("d.service"), false, &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service")); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED); /* Let's try to reenable */ assert_se(unit_file_reenable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("b.service"), false, &changes, &n_changes) >= 0); assert_se(n_changes == 2); assert_se(changes[0].type == UNIT_FILE_UNLINK); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service"); assert_se(streq(changes[0].path, p)); assert_se(changes[1].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[1].source, "/usr/lib/systemd/system/a.service")); assert_se(streq(changes[1].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED); } static void test_linked_units(const char *root) { const char *p, *q; UnitFileState state; UnitFileChange *changes = NULL; unsigned n_changes = 0, i; /* * We'll test three cases here: * * a) a unit file in /opt, that we use "systemctl link" and * "systemctl enable" on to make it available to the system * * b) a unit file in /opt, that is statically linked into * /usr/lib/systemd/system, that "enable" should work on * correctly. * * c) a unit file in /opt, that is linked into * /etc/systemd/system, and where "enable" should result in * -ELOOP, since using information from /etc to generate * information in /etc should not be allowed. */ p = strjoina(root, "/opt/linked.service"); assert_se(write_string_file(p, "[Install]\n" "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); p = strjoina(root, "/opt/linked2.service"); assert_se(write_string_file(p, "[Install]\n" "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); p = strjoina(root, "/opt/linked3.service"); assert_se(write_string_file(p, "[Install]\n" "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", NULL) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", NULL) == -ENOENT); p = strjoina(root, "/usr/lib/systemd/system/linked2.service"); assert_se(symlink("/opt/linked2.service", p) >= 0); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked3.service"); assert_se(symlink("/opt/linked3.service", p) >= 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", &state) >= 0 && state == UNIT_FILE_LINKED); /* First, let's link the unit into the search path */ assert_se(unit_file_link(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/opt/linked.service")); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_LINKED); /* Let's unlink it from the search path again */ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT); /* Now, let's not just link it, but also enable it */ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0); assert_se(n_changes == 2); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service"); q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service"); for (i = 0 ; i < n_changes; i++) { assert_se(changes[i].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[i].source, "/opt/linked.service")); if (p && streq(changes[i].path, p)) p = NULL; else if (q && streq(changes[i].path, q)) q = NULL; else assert_not_reached("wut?"); } assert(!p && !q); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_ENABLED); /* And let's unlink it again */ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 2); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service"); q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service"); for (i = 0; i < n_changes; i++) { assert_se(changes[i].type == UNIT_FILE_UNLINK); if (p && streq(changes[i].path, p)) p = NULL; else if (q && streq(changes[i].path, q)) q = NULL; else assert_not_reached("wut?"); } assert(!p && !q); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT); assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked2.service"), false, &changes, &n_changes) >= 0); assert_se(n_changes == 2); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked2.service"); q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked2.service"); for (i = 0 ; i < n_changes; i++) { assert_se(changes[i].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[i].source, "/opt/linked2.service")); if (p && streq(changes[i].path, p)) p = NULL; else if (q && streq(changes[i].path, q)) q = NULL; else assert_not_reached("wut?"); } assert(!p && !q); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked3.service"), false, &changes, &n_changes) == -ELOOP); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; } static void test_default(const char *root) { _cleanup_free_ char *def = NULL; UnitFileChange *changes = NULL; unsigned n_changes = 0; const char *p; p = strjoina(root, "/usr/lib/systemd/system/test-default-real.target"); assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0); p = strjoina(root, "/usr/lib/systemd/system/test-default.target"); assert_se(symlink("test-default-real.target", p) >= 0); assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT); assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "idontexist.target", false, &changes, &n_changes) == -ENOENT); assert_se(n_changes == 0); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT); assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "test-default.target", false, &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/test-default-real.target")); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/default.target"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) >= 0); assert_se(streq_ptr(def, "test-default-real.target")); } static void test_add_dependency(const char *root) { UnitFileChange *changes = NULL; unsigned n_changes = 0; const char *p; p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-target.target"); assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0); p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-target.target"); assert_se(symlink("real-add-dependency-test-target.target", p) >= 0); p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-service.service"); assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0); p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-service.service"); assert_se(symlink("real-add-dependency-test-service.service", p) >= 0); assert_se(unit_file_add_dependency(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("add-dependency-test-service.service"), "add-dependency-test-target.target", UNIT_WANTS, false, &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/real-add-dependency-test-service.service")); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/real-add-dependency-test-target.target.wants/real-add-dependency-test-service.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; } static void test_template_enable(const char *root) { UnitFileChange *changes = NULL; unsigned n_changes = 0; UnitFileState state; const char *p; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) == -ENOENT); p = strjoina(root, "/usr/lib/systemd/system/template@.service"); assert_se(write_string_file(p, "[Install]\n" "DefaultInstance=def\n" "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); p = strjoina(root, "/usr/lib/systemd/system/template-symlink@.service"); assert_se(symlink("template@.service", p) >= 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), false, &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service")); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@def.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), false, &changes, &n_changes) >= 0); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service")); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@foo.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template-symlink@quux.service"), false, &changes, &n_changes) >= 0); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service")); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@quux.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED); } static void test_indirect(const char *root) { UnitFileChange *changes = NULL; unsigned n_changes = 0; UnitFileState state; const char *p; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) == -ENOENT); p = strjoina(root, "/usr/lib/systemd/system/indirecta.service"); assert_se(write_string_file(p, "[Install]\n" "Also=indirectb.service\n", WRITE_STRING_FILE_CREATE) >= 0); p = strjoina(root, "/usr/lib/systemd/system/indirectb.service"); assert_se(write_string_file(p, "[Install]\n" "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); p = strjoina(root, "/usr/lib/systemd/system/indirectc.service"); assert_se(symlink("indirecta.service", p) >= 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT); assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), false, &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/indirectb.service")); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT); assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; } static void test_preset_and_list(const char *root) { UnitFileChange *changes = NULL; unsigned n_changes = 0, i; const char *p, *q; UnitFileState state; bool got_yes = false, got_no = false; Iterator j; UnitFileList *fl; Hashmap *h; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) == -ENOENT); p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service"); assert_se(write_string_file(p, "[Install]\n" "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); p = strjoina(root, "/usr/lib/systemd/system/preset-no.service"); assert_se(write_string_file(p, "[Install]\n" "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset"); assert_se(write_string_file(p, "enable *-yes.*\n" "disable *\n", WRITE_STRING_FILE_CREATE) >= 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/preset-yes.service")); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service"); assert_se(streq(changes[0].path, p)); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0); assert_se(n_changes == 0); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, false, root, UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0); assert_se(n_changes > 0); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service"); for (i = 0; i < n_changes; i++) { if (changes[i].type == UNIT_FILE_SYMLINK) { assert_se(streq(changes[i].source, "/usr/lib/systemd/system/preset-yes.service")); assert_se(streq(changes[i].path, p)); } else assert_se(changes[i].type == UNIT_FILE_UNLINK); } unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(h = hashmap_new(&string_hash_ops)); assert_se(unit_file_get_list(UNIT_FILE_SYSTEM, root, h) >= 0); p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service"); q = strjoina(root, "/usr/lib/systemd/system/preset-no.service"); HASHMAP_FOREACH(fl, h, j) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, basename(fl->path), &state) >= 0); assert_se(fl->state == state); if (streq(fl->path, p)) { got_yes = true; assert_se(fl->state == UNIT_FILE_ENABLED); } else if (streq(fl->path, q)) { got_no = true; assert_se(fl->state == UNIT_FILE_DISABLED); } else assert_se(IN_SET(fl->state, UNIT_FILE_DISABLED, UNIT_FILE_STATIC, UNIT_FILE_INDIRECT)); } unit_file_list_free(h); assert_se(got_yes && got_no); } int main(int argc, char *argv[]) { char root[] = "/tmp/rootXXXXXX"; const char *p; assert_se(mkdtemp(root)); p = strjoina(root, "/usr/lib/systemd/system/"); assert_se(mkdir_p(p, 0755) >= 0); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/"); assert_se(mkdir_p(p, 0755) >= 0); p = strjoina(root, "/run/systemd/system/"); assert_se(mkdir_p(p, 0755) >= 0); p = strjoina(root, "/opt/"); assert_se(mkdir_p(p, 0755) >= 0); p = strjoina(root, "/usr/lib/systemd/system-preset/"); assert_se(mkdir_p(p, 0755) >= 0); test_basic_mask_and_enable(root); test_linked_units(root); test_default(root); test_add_dependency(root); test_template_enable(root); test_indirect(root); test_preset_and_list(root); assert_se(rm_rf(root, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); return 0; } systemd-229/src/test/test-install.c000066400000000000000000000226351265713322000174260ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "install.h" static void dump_changes(UnitFileChange *c, unsigned n) { unsigned i; assert_se(n == 0 || c); for (i = 0; i < n; i++) { if (c[i].type == UNIT_FILE_UNLINK) printf("rm '%s'\n", c[i].path); else if (c[i].type == UNIT_FILE_SYMLINK) printf("ln -s '%s' '%s'\n", c[i].source, c[i].path); } } int main(int argc, char* argv[]) { Hashmap *h; UnitFileList *p; Iterator i; int r; const char *const files[] = { "avahi-daemon.service", NULL }; const char *const files2[] = { "/home/lennart/test.service", NULL }; UnitFileChange *changes = NULL; unsigned n_changes = 0; UnitFileState state = 0; h = hashmap_new(&string_hash_ops); r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h); assert_se(r == 0); HASHMAP_FOREACH(p, h, i) { UnitFileState s = _UNIT_FILE_STATE_INVALID; r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(p->path), &s); assert_se((r < 0 && p->state == UNIT_FILE_BAD) || (p->state == s)); fprintf(stderr, "%s (%s)\n", p->path, unit_file_state_to_string(p->state)); } unit_file_list_free(h); log_error("enable"); r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes); assert_se(r >= 0); log_error("enable2"); r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); assert_se(r >= 0); assert_se(state == UNIT_FILE_ENABLED); log_error("disable"); changes = NULL; n_changes = 0; r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); assert_se(r >= 0); assert_se(state == UNIT_FILE_DISABLED); log_error("mask"); changes = NULL; n_changes = 0; r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes); assert_se(r >= 0); log_error("mask2"); r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); assert_se(r >= 0); assert_se(state == UNIT_FILE_MASKED); log_error("unmask"); changes = NULL; n_changes = 0; r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); log_error("unmask2"); r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); assert_se(r >= 0); assert_se(state == UNIT_FILE_DISABLED); log_error("mask"); changes = NULL; n_changes = 0; r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); assert_se(r >= 0); assert_se(state == UNIT_FILE_MASKED); log_error("disable"); changes = NULL; n_changes = 0; r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); log_error("disable2"); r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); assert_se(r >= 0); assert_se(state == UNIT_FILE_MASKED); log_error("umask"); changes = NULL; n_changes = 0; r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); assert_se(r >= 0); assert_se(state == UNIT_FILE_DISABLED); log_error("enable files2"); changes = NULL; n_changes = 0; r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, false, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); assert_se(r >= 0); assert_se(state == UNIT_FILE_ENABLED); log_error("disable files2"); changes = NULL; n_changes = 0; r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); assert_se(r < 0); log_error("link files2"); changes = NULL; n_changes = 0; r = unit_file_link(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, false, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); assert_se(r >= 0); assert_se(state == UNIT_FILE_LINKED); log_error("disable files2"); changes = NULL; n_changes = 0; r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); assert_se(r < 0); log_error("link files2"); changes = NULL; n_changes = 0; r = unit_file_link(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, false, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); assert_se(r >= 0); assert_se(state == UNIT_FILE_LINKED); log_error("reenable files2"); changes = NULL; n_changes = 0; r = unit_file_reenable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, false, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); assert_se(r >= 0); assert_se(state == UNIT_FILE_ENABLED); log_error("disable files2"); changes = NULL; n_changes = 0; r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); assert_se(r < 0); log_error("preset files"); changes = NULL; n_changes = 0; r = unit_file_preset(UNIT_FILE_SYSTEM, false, NULL, (char**) files, UNIT_FILE_PRESET_FULL, false, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); unit_file_changes_free(changes, n_changes); r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files[0]), &state); assert_se(r >= 0); assert_se(state == UNIT_FILE_ENABLED); return 0; } systemd-229/src/test/test-ipcrm.c000066400000000000000000000017331265713322000170660ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "clean-ipc.h" #include "user-util.h" #include "util.h" int main(int argc, char *argv[]) { uid_t uid; assert_se(argc == 2); assert_se(parse_uid(argv[1], &uid) >= 0); return clean_ipc(uid) < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/test/test-job-type.c000066400000000000000000000107661265713322000175130ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "job.h" #include "service.h" #include "unit.h" int main(int argc, char*argv[]) { JobType a, b, c, ab, bc, ab_c, bc_a, a_bc; const ServiceState test_states[] = { SERVICE_DEAD, SERVICE_RUNNING }; unsigned i; bool merged_ab; /* fake a unit */ static Service s = { .meta.load_state = UNIT_LOADED, .type = SERVICE_SIMPLE, }; Unit *u = UNIT(&s); for (i = 0; i < ELEMENTSOF(test_states); i++) { s.state = test_states[i]; printf("\nWith collapsing for service state %s\n" "=========================================\n", service_state_to_string(s.state)); for (a = 0; a < _JOB_TYPE_MAX_MERGING; a++) { for (b = 0; b < _JOB_TYPE_MAX_MERGING; b++) { ab = a; merged_ab = (job_type_merge_and_collapse(&ab, b, u) >= 0); if (!job_type_is_mergeable(a, b)) { assert_se(!merged_ab); printf("Not mergeable: %s + %s\n", job_type_to_string(a), job_type_to_string(b)); continue; } assert_se(merged_ab); printf("%s + %s = %s\n", job_type_to_string(a), job_type_to_string(b), job_type_to_string(ab)); for (c = 0; c < _JOB_TYPE_MAX_MERGING; c++) { /* Verify transitivity of mergeability of job types */ assert_se(!job_type_is_mergeable(a, b) || !job_type_is_mergeable(b, c) || job_type_is_mergeable(a, c)); /* Verify that merged entries can be merged with the same entries * they can be merged with separately */ assert_se(!job_type_is_mergeable(a, c) || job_type_is_mergeable(ab, c)); assert_se(!job_type_is_mergeable(b, c) || job_type_is_mergeable(ab, c)); /* Verify that if a merged with b is not mergeable with c, then * either a or b is not mergeable with c either. */ assert_se(job_type_is_mergeable(ab, c) || !job_type_is_mergeable(a, c) || !job_type_is_mergeable(b, c)); bc = b; if (job_type_merge_and_collapse(&bc, c, u) >= 0) { /* Verify associativity */ ab_c = ab; assert_se(job_type_merge_and_collapse(&ab_c, c, u) == 0); bc_a = bc; assert_se(job_type_merge_and_collapse(&bc_a, a, u) == 0); a_bc = a; assert_se(job_type_merge_and_collapse(&a_bc, bc, u) == 0); assert_se(ab_c == bc_a); assert_se(ab_c == a_bc); printf("%s + %s + %s = %s\n", job_type_to_string(a), job_type_to_string(b), job_type_to_string(c), job_type_to_string(ab_c)); } } } } } return 0; } systemd-229/src/test/test-json.c000066400000000000000000000157531265713322000167340ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "json.h" #include "string-util.h" #include "util.h" static void test_one(const char *data, ...) { void *state = NULL; va_list ap; va_start(ap, data); for (;;) { _cleanup_free_ char *str = NULL; union json_value v = {}; int t, tt; t = json_tokenize(&data, &str, &v, &state, NULL); tt = va_arg(ap, int); assert_se(t == tt); if (t == JSON_END || t < 0) break; else if (t == JSON_STRING) { const char *nn; nn = va_arg(ap, const char *); assert_se(streq_ptr(nn, str)); } else if (t == JSON_REAL) { double d; d = va_arg(ap, double); assert_se(fabs(d - v.real) < 0.001); } else if (t == JSON_INTEGER) { intmax_t i; i = va_arg(ap, intmax_t); assert_se(i == v.integer); } else if (t == JSON_BOOLEAN) { bool b; b = va_arg(ap, int); assert_se(b == v.boolean); } } va_end(ap); } typedef void (*Test)(JsonVariant *); static void test_file(const char *data, Test test) { _cleanup_json_variant_unref_ JsonVariant *v = NULL; int r; r = json_parse(data, &v); assert_se(r == 0); assert_se(v != NULL); assert_se(v->type == JSON_VARIANT_OBJECT); if (test) test(v); } static void test_1(JsonVariant *v) { JsonVariant *p, *q; unsigned i; /* 3 keys + 3 values */ assert_se(v->size == 6); /* has k */ p = json_variant_value(v, "k"); assert_se(p && p->type == JSON_VARIANT_STRING); /* k equals v */ assert_se(streq(json_variant_string(p), "v")); /* has foo */ p = json_variant_value(v, "foo"); assert_se(p && p->type == JSON_VARIANT_ARRAY && p->size == 3); /* check foo[0] = 1, foo[1] = 2, foo[2] = 3 */ for (i = 0; i < 3; ++i) { q = json_variant_element(p, i); assert_se(q && q->type == JSON_VARIANT_INTEGER && json_variant_integer(q) == (i+1)); } /* has bar */ p = json_variant_value(v, "bar"); assert_se(p && p->type == JSON_VARIANT_OBJECT && p->size == 2); /* zap is null */ q = json_variant_value(p, "zap"); assert_se(q && q->type == JSON_VARIANT_NULL); } static void test_2(JsonVariant *v) { JsonVariant *p, *q; /* 2 keys + 2 values */ assert_se(v->size == 4); /* has mutant */ p = json_variant_value(v, "mutant"); assert_se(p && p->type == JSON_VARIANT_ARRAY && p->size == 4); /* mutant[0] == 1 */ q = json_variant_element(p, 0); assert_se(q && q->type == JSON_VARIANT_INTEGER && json_variant_integer(q) == 1); /* mutant[1] == null */ q = json_variant_element(p, 1); assert_se(q && q->type == JSON_VARIANT_NULL); /* mutant[2] == "1" */ q = json_variant_element(p, 2); assert_se(q && q->type == JSON_VARIANT_STRING && streq(json_variant_string(q), "1")); /* mutant[3] == JSON_VARIANT_OBJECT */ q = json_variant_element(p, 3); assert_se(q && q->type == JSON_VARIANT_OBJECT && q->size == 2); /* has 1 */ p = json_variant_value(q, "1"); assert_se(p && p->type == JSON_VARIANT_ARRAY && p->size == 2); /* "1"[0] == 1 */ q = json_variant_element(p, 0); assert_se(q && q->type == JSON_VARIANT_INTEGER && json_variant_integer(q) == 1); /* "1"[1] == "1" */ q = json_variant_element(p, 1); assert_se(q && q->type == JSON_VARIANT_STRING && streq(json_variant_string(q), "1")); /* has blah */ p = json_variant_value(v, "blah"); assert_se(p && p->type == JSON_VARIANT_REAL && fabs(json_variant_real(p) - 1.27) < 0.001); } int main(int argc, char *argv[]) { test_one("x", -EINVAL); test_one("", JSON_END); test_one(" ", JSON_END); test_one("0", JSON_INTEGER, (intmax_t) 0, JSON_END); test_one("1234", JSON_INTEGER, (intmax_t) 1234, JSON_END); test_one("3.141", JSON_REAL, 3.141, JSON_END); test_one("0.0", JSON_REAL, 0.0, JSON_END); test_one("7e3", JSON_REAL, 7e3, JSON_END); test_one("-7e-3", JSON_REAL, -7e-3, JSON_END); test_one("true", JSON_BOOLEAN, true, JSON_END); test_one("false", JSON_BOOLEAN, false, JSON_END); test_one("null", JSON_NULL, JSON_END); test_one("{}", JSON_OBJECT_OPEN, JSON_OBJECT_CLOSE, JSON_END); test_one("\t {\n} \n", JSON_OBJECT_OPEN, JSON_OBJECT_CLOSE, JSON_END); test_one("[]", JSON_ARRAY_OPEN, JSON_ARRAY_CLOSE, JSON_END); test_one("\t [] \n\n", JSON_ARRAY_OPEN, JSON_ARRAY_CLOSE, JSON_END); test_one("\"\"", JSON_STRING, "", JSON_END); test_one("\"foo\"", JSON_STRING, "foo", JSON_END); test_one("\"foo\\nfoo\"", JSON_STRING, "foo\nfoo", JSON_END); test_one("{\"foo\" : \"bar\"}", JSON_OBJECT_OPEN, JSON_STRING, "foo", JSON_COLON, JSON_STRING, "bar", JSON_OBJECT_CLOSE, JSON_END); test_one("{\"foo\" : [true, false]}", JSON_OBJECT_OPEN, JSON_STRING, "foo", JSON_COLON, JSON_ARRAY_OPEN, JSON_BOOLEAN, true, JSON_COMMA, JSON_BOOLEAN, false, JSON_ARRAY_CLOSE, JSON_OBJECT_CLOSE, JSON_END); test_one("\"\xef\xbf\xbd\"", JSON_STRING, "\xef\xbf\xbd", JSON_END); test_one("\"\\ufffd\"", JSON_STRING, "\xef\xbf\xbd", JSON_END); test_one("\"\\uf\"", -EINVAL); test_one("\"\\ud800a\"", -EINVAL); test_one("\"\\udc00\\udc00\"", -EINVAL); test_one("\"\\ud801\\udc37\"", JSON_STRING, "\xf0\x90\x90\xb7", JSON_END); test_one("[1, 2]", JSON_ARRAY_OPEN, JSON_INTEGER, (intmax_t) 1, JSON_COMMA, JSON_INTEGER, (intmax_t) 2, JSON_ARRAY_CLOSE, JSON_END); test_file("{\"k\": \"v\", \"foo\": [1, 2, 3], \"bar\": {\"zap\": null}}", test_1); test_file("{\"mutant\": [1, null, \"1\", {\"1\": [1, \"1\"]}], \"blah\": 1.27}", test_2); return 0; } systemd-229/src/test/test-libudev.c000066400000000000000000000410301265713322000174000ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2008-2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "libudev.h" #include "stdio-util.h" #include "string-util.h" #include "udev-util.h" #include "util.h" #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) static void print_device(struct udev_device *device) { const char *str; dev_t devnum; int count; struct udev_list_entry *list_entry; printf("*** device: %p ***\n", device); str = udev_device_get_action(device); if (str != NULL) printf("action: '%s'\n", str); str = udev_device_get_syspath(device); printf("syspath: '%s'\n", str); str = udev_device_get_sysname(device); printf("sysname: '%s'\n", str); str = udev_device_get_sysnum(device); if (str != NULL) printf("sysnum: '%s'\n", str); str = udev_device_get_devpath(device); printf("devpath: '%s'\n", str); str = udev_device_get_subsystem(device); if (str != NULL) printf("subsystem: '%s'\n", str); str = udev_device_get_devtype(device); if (str != NULL) printf("devtype: '%s'\n", str); str = udev_device_get_driver(device); if (str != NULL) printf("driver: '%s'\n", str); str = udev_device_get_devnode(device); if (str != NULL) printf("devname: '%s'\n", str); devnum = udev_device_get_devnum(device); if (major(devnum) > 0) printf("devnum: %u:%u\n", major(devnum), minor(devnum)); count = 0; udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) { printf("link: '%s'\n", udev_list_entry_get_name(list_entry)); count++; } if (count > 0) printf("found %i links\n", count); count = 0; udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) { printf("property: '%s=%s'\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry)); count++; } if (count > 0) printf("found %i properties\n", count); str = udev_device_get_property_value(device, "MAJOR"); if (str != NULL) printf("MAJOR: '%s'\n", str); str = udev_device_get_sysattr_value(device, "dev"); if (str != NULL) printf("attr{dev}: '%s'\n", str); printf("\n"); } static int test_device(struct udev *udev, const char *syspath) { _cleanup_udev_device_unref_ struct udev_device *device; printf("looking at device: %s\n", syspath); device = udev_device_new_from_syspath(udev, syspath); if (device == NULL) { printf("no device found\n"); return -1; } print_device(device); return 0; } static int test_device_parents(struct udev *udev, const char *syspath) { _cleanup_udev_device_unref_ struct udev_device *device; struct udev_device *device_parent; printf("looking at device: %s\n", syspath); device = udev_device_new_from_syspath(udev, syspath); if (device == NULL) return -1; printf("looking at parents\n"); device_parent = device; do { print_device(device_parent); device_parent = udev_device_get_parent(device_parent); } while (device_parent != NULL); printf("looking at parents again\n"); device_parent = device; do { print_device(device_parent); device_parent = udev_device_get_parent(device_parent); } while (device_parent != NULL); return 0; } static int test_device_devnum(struct udev *udev) { dev_t devnum = makedev(1, 3); struct udev_device *device; printf("looking up device: %u:%u\n", major(devnum), minor(devnum)); device = udev_device_new_from_devnum(udev, 'c', devnum); if (device == NULL) return -1; print_device(device); udev_device_unref(device); return 0; } static int test_device_subsys_name(struct udev *udev) { struct udev_device *device; printf("looking up device: 'block':'sda'\n"); device = udev_device_new_from_subsystem_sysname(udev, "block", "sda"); if (device == NULL) return -1; print_device(device); udev_device_unref(device); printf("looking up device: 'subsystem':'pci'\n"); device = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci"); if (device == NULL) return -1; print_device(device); udev_device_unref(device); printf("looking up device: 'drivers':'scsi:sd'\n"); device = udev_device_new_from_subsystem_sysname(udev, "drivers", "scsi:sd"); if (device == NULL) return -1; print_device(device); udev_device_unref(device); printf("looking up device: 'module':'printk'\n"); device = udev_device_new_from_subsystem_sysname(udev, "module", "printk"); if (device == NULL) return -1; print_device(device); udev_device_unref(device); return 0; } static int test_enumerate_print_list(struct udev_enumerate *enumerate) { struct udev_list_entry *list_entry; int count = 0; udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) { struct udev_device *device; device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate), udev_list_entry_get_name(list_entry)); if (device != NULL) { printf("device: '%s' (%s)\n", udev_device_get_syspath(device), udev_device_get_subsystem(device)); udev_device_unref(device); count++; } } printf("found %i devices\n\n", count); return count; } static int test_monitor(struct udev *udev) { struct udev_monitor *udev_monitor = NULL; int fd_ep; int fd_udev = -1; struct epoll_event ep_udev, ep_stdin; fd_ep = epoll_create1(EPOLL_CLOEXEC); if (fd_ep < 0) { printf("error creating epoll fd: %m\n"); goto out; } udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); if (udev_monitor == NULL) { printf("no socket\n"); goto out; } fd_udev = udev_monitor_get_fd(udev_monitor); if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) < 0 || udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) < 0 || udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") < 0) { printf("filter failed\n"); goto out; } if (udev_monitor_enable_receiving(udev_monitor) < 0) { printf("bind failed\n"); goto out; } memzero(&ep_udev, sizeof(struct epoll_event)); ep_udev.events = EPOLLIN; ep_udev.data.fd = fd_udev; if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) { printf("fail to add fd to epoll: %m\n"); goto out; } memzero(&ep_stdin, sizeof(struct epoll_event)); ep_stdin.events = EPOLLIN; ep_stdin.data.fd = STDIN_FILENO; if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) < 0) { printf("fail to add fd to epoll: %m\n"); goto out; } for (;;) { int fdcount; struct epoll_event ev[4]; struct udev_device *device; int i; printf("waiting for events from udev, press ENTER to exit\n"); fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), -1); printf("epoll fd count: %i\n", fdcount); for (i = 0; i < fdcount; i++) { if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN) { device = udev_monitor_receive_device(udev_monitor); if (device == NULL) { printf("no device from socket\n"); continue; } print_device(device); udev_device_unref(device); } else if (ev[i].data.fd == STDIN_FILENO && ev[i].events & EPOLLIN) { printf("exiting loop\n"); goto out; } } } out: if (fd_ep >= 0) close(fd_ep); udev_monitor_unref(udev_monitor); return 0; } static int test_queue(struct udev *udev) { struct udev_queue *udev_queue; udev_queue = udev_queue_new(udev); if (udev_queue == NULL) return -1; if (udev_queue_get_queue_is_empty(udev_queue)) printf("queue is empty\n"); udev_queue_unref(udev_queue); return 0; } static int test_enumerate(struct udev *udev, const char *subsystem) { struct udev_enumerate *udev_enumerate; int r; printf("enumerate '%s'\n", subsystem == NULL ? "" : subsystem); udev_enumerate = udev_enumerate_new(udev); if (udev_enumerate == NULL) return -1; udev_enumerate_add_match_subsystem(udev_enumerate, subsystem); udev_enumerate_scan_devices(udev_enumerate); test_enumerate_print_list(udev_enumerate); udev_enumerate_unref(udev_enumerate); printf("enumerate 'net' + duplicated scan + null + zero\n"); udev_enumerate = udev_enumerate_new(udev); if (udev_enumerate == NULL) return -1; udev_enumerate_add_match_subsystem(udev_enumerate, "net"); udev_enumerate_scan_devices(udev_enumerate); udev_enumerate_scan_devices(udev_enumerate); udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null"); udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null"); udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null"); udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null"); udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); udev_enumerate_scan_devices(udev_enumerate); test_enumerate_print_list(udev_enumerate); udev_enumerate_unref(udev_enumerate); printf("enumerate 'block'\n"); udev_enumerate = udev_enumerate_new(udev); if (udev_enumerate == NULL) return -1; udev_enumerate_add_match_subsystem(udev_enumerate,"block"); r = udev_enumerate_add_match_is_initialized(udev_enumerate); if (r < 0) { udev_enumerate_unref(udev_enumerate); return r; } udev_enumerate_scan_devices(udev_enumerate); test_enumerate_print_list(udev_enumerate); udev_enumerate_unref(udev_enumerate); printf("enumerate 'not block'\n"); udev_enumerate = udev_enumerate_new(udev); if (udev_enumerate == NULL) return -1; udev_enumerate_add_nomatch_subsystem(udev_enumerate, "block"); udev_enumerate_scan_devices(udev_enumerate); test_enumerate_print_list(udev_enumerate); udev_enumerate_unref(udev_enumerate); printf("enumerate 'pci, mem, vc'\n"); udev_enumerate = udev_enumerate_new(udev); if (udev_enumerate == NULL) return -1; udev_enumerate_add_match_subsystem(udev_enumerate, "pci"); udev_enumerate_add_match_subsystem(udev_enumerate, "mem"); udev_enumerate_add_match_subsystem(udev_enumerate, "vc"); udev_enumerate_scan_devices(udev_enumerate); test_enumerate_print_list(udev_enumerate); udev_enumerate_unref(udev_enumerate); printf("enumerate 'subsystem'\n"); udev_enumerate = udev_enumerate_new(udev); if (udev_enumerate == NULL) return -1; udev_enumerate_scan_subsystems(udev_enumerate); test_enumerate_print_list(udev_enumerate); udev_enumerate_unref(udev_enumerate); printf("enumerate 'property IF_FS_*=filesystem'\n"); udev_enumerate = udev_enumerate_new(udev); if (udev_enumerate == NULL) return -1; udev_enumerate_add_match_property(udev_enumerate, "ID_FS*", "filesystem"); udev_enumerate_scan_devices(udev_enumerate); test_enumerate_print_list(udev_enumerate); udev_enumerate_unref(udev_enumerate); return 0; } static void test_hwdb(struct udev *udev, const char *modalias) { struct udev_hwdb *hwdb; struct udev_list_entry *entry; hwdb = udev_hwdb_new(udev); udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0)) printf("'%s'='%s'\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry)); printf("\n"); hwdb = udev_hwdb_unref(hwdb); assert_se(hwdb == NULL); } int main(int argc, char *argv[]) { struct udev *udev = NULL; static const struct option options[] = { { "syspath", required_argument, NULL, 'p' }, { "subsystem", required_argument, NULL, 's' }, { "debug", no_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, {} }; const char *syspath = "/devices/virtual/mem/null"; const char *subsystem = NULL; char path[1024]; int c; udev = udev_new(); printf("context: %p\n", udev); if (udev == NULL) { printf("no context\n"); return 1; } while ((c = getopt_long(argc, argv, "p:s:dhV", options, NULL)) >= 0) switch (c) { case 'p': syspath = optarg; break; case 's': subsystem = optarg; break; case 'd': if (log_get_max_level() < LOG_INFO) log_set_max_level(LOG_INFO); break; case 'h': printf("--debug --syspath= --subsystem= --help\n"); goto out; case 'V': printf("%s\n", VERSION); goto out; case '?': goto out; default: assert_not_reached("Unhandled option code."); } /* add sys path if needed */ if (!startswith(syspath, "/sys")) { xsprintf(path, "/sys/%s", syspath); syspath = path; } test_device(udev, syspath); test_device_devnum(udev); test_device_subsys_name(udev); test_device_parents(udev, syspath); test_enumerate(udev, subsystem); test_queue(udev); test_hwdb(udev, "usb:v0D50p0011*"); test_monitor(udev); out: udev_unref(udev); return 0; } systemd-229/src/test/test-list.c000066400000000000000000000153051265713322000167270ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2013 Jan Janssen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "list.h" #include "util.h" int main(int argc, const char *argv[]) { size_t i; typedef struct list_item { LIST_FIELDS(struct list_item, item); } list_item; LIST_HEAD(list_item, head); list_item items[4]; list_item *cursor; LIST_HEAD_INIT(head); assert_se(head == NULL); for (i = 0; i < ELEMENTSOF(items); i++) { LIST_INIT(item, &items[i]); assert_se(LIST_JUST_US(item, &items[i])); LIST_PREPEND(item, head, &items[i]); } i = 0; LIST_FOREACH_OTHERS(item, cursor, &items[2]) { i++; assert_se(cursor != &items[2]); } assert_se(i == ELEMENTSOF(items)-1); i = 0; LIST_FOREACH_OTHERS(item, cursor, &items[0]) { i++; assert_se(cursor != &items[0]); } assert_se(i == ELEMENTSOF(items)-1); i = 0; LIST_FOREACH_OTHERS(item, cursor, &items[3]) { i++; assert_se(cursor != &items[3]); } assert_se(i == ELEMENTSOF(items)-1); assert_se(!LIST_JUST_US(item, head)); assert_se(items[0].item_next == NULL); assert_se(items[1].item_next == &items[0]); assert_se(items[2].item_next == &items[1]); assert_se(items[3].item_next == &items[2]); assert_se(items[0].item_prev == &items[1]); assert_se(items[1].item_prev == &items[2]); assert_se(items[2].item_prev == &items[3]); assert_se(items[3].item_prev == NULL); LIST_FIND_HEAD(item, &items[0], cursor); assert_se(cursor == &items[3]); LIST_FIND_TAIL(item, &items[3], cursor); assert_se(cursor == &items[0]); LIST_REMOVE(item, head, &items[1]); assert_se(LIST_JUST_US(item, &items[1])); assert_se(items[0].item_next == NULL); assert_se(items[2].item_next == &items[0]); assert_se(items[3].item_next == &items[2]); assert_se(items[0].item_prev == &items[2]); assert_se(items[2].item_prev == &items[3]); assert_se(items[3].item_prev == NULL); LIST_INSERT_AFTER(item, head, &items[3], &items[1]); assert_se(items[0].item_next == NULL); assert_se(items[2].item_next == &items[0]); assert_se(items[1].item_next == &items[2]); assert_se(items[3].item_next == &items[1]); assert_se(items[0].item_prev == &items[2]); assert_se(items[2].item_prev == &items[1]); assert_se(items[1].item_prev == &items[3]); assert_se(items[3].item_prev == NULL); LIST_REMOVE(item, head, &items[1]); assert_se(LIST_JUST_US(item, &items[1])); assert_se(items[0].item_next == NULL); assert_se(items[2].item_next == &items[0]); assert_se(items[3].item_next == &items[2]); assert_se(items[0].item_prev == &items[2]); assert_se(items[2].item_prev == &items[3]); assert_se(items[3].item_prev == NULL); LIST_INSERT_BEFORE(item, head, &items[2], &items[1]); assert_se(items[0].item_next == NULL); assert_se(items[2].item_next == &items[0]); assert_se(items[1].item_next == &items[2]); assert_se(items[3].item_next == &items[1]); assert_se(items[0].item_prev == &items[2]); assert_se(items[2].item_prev == &items[1]); assert_se(items[1].item_prev == &items[3]); assert_se(items[3].item_prev == NULL); LIST_REMOVE(item, head, &items[0]); assert_se(LIST_JUST_US(item, &items[0])); assert_se(items[2].item_next == NULL); assert_se(items[1].item_next == &items[2]); assert_se(items[3].item_next == &items[1]); assert_se(items[2].item_prev == &items[1]); assert_se(items[1].item_prev == &items[3]); assert_se(items[3].item_prev == NULL); LIST_INSERT_BEFORE(item, head, NULL, &items[0]); assert_se(items[0].item_next == NULL); assert_se(items[2].item_next == &items[0]); assert_se(items[1].item_next == &items[2]); assert_se(items[3].item_next == &items[1]); assert_se(items[0].item_prev == &items[2]); assert_se(items[2].item_prev == &items[1]); assert_se(items[1].item_prev == &items[3]); assert_se(items[3].item_prev == NULL); LIST_REMOVE(item, head, &items[0]); assert_se(LIST_JUST_US(item, &items[0])); assert_se(items[2].item_next == NULL); assert_se(items[1].item_next == &items[2]); assert_se(items[3].item_next == &items[1]); assert_se(items[2].item_prev == &items[1]); assert_se(items[1].item_prev == &items[3]); assert_se(items[3].item_prev == NULL); LIST_REMOVE(item, head, &items[1]); assert_se(LIST_JUST_US(item, &items[1])); assert_se(items[2].item_next == NULL); assert_se(items[3].item_next == &items[2]); assert_se(items[2].item_prev == &items[3]); assert_se(items[3].item_prev == NULL); LIST_REMOVE(item, head, &items[2]); assert_se(LIST_JUST_US(item, &items[2])); assert_se(LIST_JUST_US(item, head)); LIST_REMOVE(item, head, &items[3]); assert_se(LIST_JUST_US(item, &items[3])); assert_se(head == NULL); for (i = 0; i < ELEMENTSOF(items); i++) { assert_se(LIST_JUST_US(item, &items[i])); LIST_APPEND(item, head, &items[i]); } assert_se(!LIST_JUST_US(item, head)); assert_se(items[0].item_next == &items[1]); assert_se(items[1].item_next == &items[2]); assert_se(items[2].item_next == &items[3]); assert_se(items[3].item_next == NULL); assert_se(items[0].item_prev == NULL); assert_se(items[1].item_prev == &items[0]); assert_se(items[2].item_prev == &items[1]); assert_se(items[3].item_prev == &items[2]); for (i = 0; i < ELEMENTSOF(items); i++) LIST_REMOVE(item, head, &items[i]); assert_se(head == NULL); return 0; } systemd-229/src/test/test-locale-util.c000066400000000000000000000032571265713322000201710ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2014 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "locale-util.h" #include "macro.h" #include "strv.h" static void test_get_locales(void) { _cleanup_strv_free_ char **locales = NULL; char **p; int r; r = get_locales(&locales); assert_se(r >= 0); assert_se(locales); STRV_FOREACH(p, locales) { puts(*p); assert_se(locale_is_valid(*p)); } } static void test_locale_is_valid(void) { assert_se(locale_is_valid("en_EN.utf8")); assert_se(locale_is_valid("fr_FR.utf8")); assert_se(locale_is_valid("fr_FR@euro")); assert_se(locale_is_valid("fi_FI")); assert_se(locale_is_valid("POSIX")); assert_se(locale_is_valid("C")); assert_se(!locale_is_valid("")); assert_se(!locale_is_valid("/usr/bin/foo")); assert_se(!locale_is_valid("\x01gar\x02 bage\x03")); } int main(int argc, char *argv[]) { test_get_locales(); test_locale_is_valid(); return 0; } systemd-229/src/test/test-log.c000066400000000000000000000032521265713322000165330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "formats-util.h" #include "log.h" #include "util.h" int main(int argc, char* argv[]) { log_set_target(LOG_TARGET_CONSOLE); log_open(); log_struct(LOG_INFO, "MESSAGE=Waldo PID="PID_FMT, getpid(), "SERVICE=piepapo", NULL); log_set_target(LOG_TARGET_JOURNAL); log_open(); log_struct(LOG_INFO, "MESSAGE=Foobar PID="PID_FMT, getpid(), "SERVICE=foobar", NULL); log_struct(LOG_INFO, "MESSAGE=Foobar PID="PID_FMT, getpid(), "FORMAT_STR_TEST=1=%i A=%c 2=%hi 3=%li 4=%lli 1=%p foo=%s 2.5=%g 3.5=%g 4.5=%Lg", (int) 1, 'A', (short) 2, (long int) 3, (long long int) 4, (void*) 1, "foo", (float) 2.5f, (double) 3.5, (long double) 4.5, "SUFFIX=GOT IT", NULL); return 0; } systemd-229/src/test/test-loopback.c000066400000000000000000000020251265713322000175410ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "log.h" #include "loopback-setup.h" int main(int argc, char* argv[]) { int r; log_open(); log_parse_environment(); r = loopback_setup(); if (r < 0) fprintf(stderr, "loopback: %s\n", strerror(-r)); return 0; } systemd-229/src/test/test-namespace.c000066400000000000000000000101151265713322000177020ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "fd-util.h" #include "namespace.h" #include "process-util.h" #include "string-util.h" #include "util.h" static void test_tmpdir(const char *id, const char *A, const char *B) { _cleanup_free_ char *a, *b; struct stat x, y; char *c, *d; assert_se(setup_tmp_dirs(id, &a, &b) == 0); assert_se(startswith(a, A)); assert_se(startswith(b, B)); assert_se(stat(a, &x) >= 0); assert_se(stat(b, &y) >= 0); assert_se(S_ISDIR(x.st_mode)); assert_se(S_ISDIR(y.st_mode)); assert_se((x.st_mode & 01777) == 0700); assert_se((y.st_mode & 01777) == 0700); c = strjoina(a, "/tmp"); d = strjoina(b, "/tmp"); assert_se(stat(c, &x) >= 0); assert_se(stat(d, &y) >= 0); assert_se(S_ISDIR(x.st_mode)); assert_se(S_ISDIR(y.st_mode)); assert_se((x.st_mode & 01777) == 01777); assert_se((y.st_mode & 01777) == 01777); assert_se(rmdir(c) >= 0); assert_se(rmdir(d) >= 0); assert_se(rmdir(a) >= 0); assert_se(rmdir(b) >= 0); } static void test_netns(void) { _cleanup_close_pair_ int s[2] = { -1, -1 }; pid_t pid1, pid2, pid3; int r, n = 0; siginfo_t si; if (geteuid() > 0) return; assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, s) >= 0); pid1 = fork(); assert_se(pid1 >= 0); if (pid1 == 0) { r = setup_netns(s); assert_se(r >= 0); _exit(r); } pid2 = fork(); assert_se(pid2 >= 0); if (pid2 == 0) { r = setup_netns(s); assert_se(r >= 0); exit(r); } pid3 = fork(); assert_se(pid3 >= 0); if (pid3 == 0) { r = setup_netns(s); assert_se(r >= 0); exit(r); } r = wait_for_terminate(pid1, &si); assert_se(r >= 0); assert_se(si.si_code == CLD_EXITED); n += si.si_status; r = wait_for_terminate(pid2, &si); assert_se(r >= 0); assert_se(si.si_code == CLD_EXITED); n += si.si_status; r = wait_for_terminate(pid3, &si); assert_se(r >= 0); assert_se(si.si_code == CLD_EXITED); n += si.si_status; assert_se(n == 1); } int main(int argc, char *argv[]) { sd_id128_t bid; char boot_id[SD_ID128_STRING_MAX]; _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *zz = NULL; assert_se(sd_id128_get_boot(&bid) >= 0); sd_id128_to_string(bid, boot_id); x = strjoin("/tmp/systemd-private-", boot_id, "-abcd.service-", NULL); y = strjoin("/var/tmp/systemd-private-", boot_id, "-abcd.service-", NULL); assert_se(x && y); test_tmpdir("abcd.service", x, y); z = strjoin("/tmp/systemd-private-", boot_id, "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-", NULL); zz = strjoin("/var/tmp/systemd-private-", boot_id, "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-", NULL); assert_se(z && zz); test_tmpdir("sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device", z, zz); test_netns(); return 0; } systemd-229/src/test/test-netlink-manual.c000066400000000000000000000107161265713322000206740ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Susant Sahani systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "sd-netlink.h" #include "macro.h" #include "util.h" static int load_module(const char *mod_name) { struct kmod_ctx *ctx; struct kmod_list *list = NULL, *l; int r; ctx = kmod_new(NULL, NULL); if (!ctx) { kmod_unref(ctx); return -ENOMEM; } r = kmod_module_new_from_lookup(ctx, mod_name, &list); if (r < 0) return -1; kmod_list_foreach(l, list) { struct kmod_module *mod = kmod_module_get_module(l); r = kmod_module_probe_insert_module(mod, 0, NULL, NULL, NULL, NULL); if (r >= 0) r = 0; else r = -1; kmod_module_unref(mod); } kmod_module_unref_list(list); kmod_unref(ctx); return r; } static int test_tunnel_configure(sd_netlink *rtnl) { int r; sd_netlink_message *m, *n; struct in_addr local, remote; /* skip test if module cannot be loaded */ r = load_module("ipip"); if(r < 0) return EXIT_TEST_SKIP; if(getuid() != 0) return EXIT_TEST_SKIP; /* IPIP tunnel */ assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0) >= 0); assert_se(m); assert_se(sd_netlink_message_append_string(m, IFLA_IFNAME, "ipip-tunnel") >= 0); assert_se(sd_netlink_message_append_u32(m, IFLA_MTU, 1234)>= 0); assert_se(sd_netlink_message_open_container(m, IFLA_LINKINFO) >= 0); assert_se(sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "ipip") >= 0); inet_pton(AF_INET, "192.168.21.1", &local.s_addr); assert_se(sd_netlink_message_append_u32(m, IFLA_IPTUN_LOCAL, local.s_addr) >= 0); inet_pton(AF_INET, "192.168.21.2", &remote.s_addr); assert_se(sd_netlink_message_append_u32(m, IFLA_IPTUN_REMOTE, remote.s_addr) >= 0); assert_se(sd_netlink_message_close_container(m) >= 0); assert_se(sd_netlink_message_close_container(m) >= 0); assert_se(sd_netlink_call(rtnl, m, -1, 0) == 1); assert_se((m = sd_netlink_message_unref(m)) == NULL); r = load_module("sit"); if(r < 0) return EXIT_TEST_SKIP; /* sit */ assert_se(sd_rtnl_message_new_link(rtnl, &n, RTM_NEWLINK, 0) >= 0); assert_se(n); assert_se(sd_netlink_message_append_string(n, IFLA_IFNAME, "sit-tunnel") >= 0); assert_se(sd_netlink_message_append_u32(n, IFLA_MTU, 1234)>= 0); assert_se(sd_netlink_message_open_container(n, IFLA_LINKINFO) >= 0); assert_se(sd_netlink_message_open_container_union(n, IFLA_INFO_DATA, "sit") >= 0); assert_se(sd_netlink_message_append_u8(n, IFLA_IPTUN_PROTO, IPPROTO_IPIP) >= 0); inet_pton(AF_INET, "192.168.21.3", &local.s_addr); assert_se(sd_netlink_message_append_u32(n, IFLA_IPTUN_LOCAL, local.s_addr) >= 0); inet_pton(AF_INET, "192.168.21.4", &remote.s_addr); assert_se(sd_netlink_message_append_u32(n, IFLA_IPTUN_REMOTE, remote.s_addr) >= 0); assert_se(sd_netlink_message_close_container(n) >= 0); assert_se(sd_netlink_message_close_container(n) >= 0); assert_se(sd_netlink_call(rtnl, n, -1, 0) == 1); assert_se((n = sd_netlink_message_unref(n)) == NULL); return EXIT_SUCCESS; } int main(int argc, char *argv[]) { sd_netlink *rtnl; int r; assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(rtnl); r = test_tunnel_configure(rtnl); assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); return r; } systemd-229/src/test/test-ns.c000066400000000000000000000054421265713322000163750ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "log.h" #include "namespace.h" int main(int argc, char *argv[]) { const char * const writable[] = { "/home", NULL }; const char * const readonly[] = { "/", "/usr", "/boot", NULL }; const char *inaccessible[] = { "/home/lennart/projects", NULL }; char *root_directory; char *projects_directory; int r; char tmp_dir[] = "/tmp/systemd-private-XXXXXX", var_tmp_dir[] = "/var/tmp/systemd-private-XXXXXX"; assert_se(mkdtemp(tmp_dir)); assert_se(mkdtemp(var_tmp_dir)); root_directory = getenv("TEST_NS_CHROOT"); projects_directory = getenv("TEST_NS_PROJECTS"); if (projects_directory) inaccessible[0] = projects_directory; log_info("Inaccessible directory: '%s'", inaccessible[0]); if (root_directory) log_info("Chroot: '%s'", root_directory); else log_info("Not chrooted"); r = setup_namespace(root_directory, (char **) writable, (char **) readonly, (char **) inaccessible, tmp_dir, var_tmp_dir, NULL, true, PROTECT_HOME_NO, PROTECT_SYSTEM_NO, 0); if (r < 0) { log_error_errno(r, "Failed to setup namespace: %m"); log_info("Usage:\n" " sudo TEST_NS_PROJECTS=/home/lennart/projects ./test-ns\n" " sudo TEST_NS_CHROOT=/home/alban/debian-tree TEST_NS_PROJECTS=/home/alban/debian-tree/home/alban/Documents ./test-ns"); return 1; } execl("/bin/sh", "/bin/sh", NULL); log_error_errno(errno, "execl(): %m"); return 1; } systemd-229/src/test/test-parse-util.c000066400000000000000000000360401265713322000200400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Thomas H.P. Andersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "log.h" #include "parse-util.h" static void test_parse_boolean(void) { assert_se(parse_boolean("1") == 1); assert_se(parse_boolean("y") == 1); assert_se(parse_boolean("Y") == 1); assert_se(parse_boolean("yes") == 1); assert_se(parse_boolean("YES") == 1); assert_se(parse_boolean("true") == 1); assert_se(parse_boolean("TRUE") == 1); assert_se(parse_boolean("on") == 1); assert_se(parse_boolean("ON") == 1); assert_se(parse_boolean("0") == 0); assert_se(parse_boolean("n") == 0); assert_se(parse_boolean("N") == 0); assert_se(parse_boolean("no") == 0); assert_se(parse_boolean("NO") == 0); assert_se(parse_boolean("false") == 0); assert_se(parse_boolean("FALSE") == 0); assert_se(parse_boolean("off") == 0); assert_se(parse_boolean("OFF") == 0); assert_se(parse_boolean("garbage") < 0); assert_se(parse_boolean("") < 0); assert_se(parse_boolean("full") < 0); } static void test_parse_pid(void) { int r; pid_t pid; r = parse_pid("100", &pid); assert_se(r == 0); assert_se(pid == 100); r = parse_pid("0x7FFFFFFF", &pid); assert_se(r == 0); assert_se(pid == 2147483647); pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */ r = parse_pid("0", &pid); assert_se(r == -ERANGE); assert_se(pid == 65); pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */ r = parse_pid("-100", &pid); assert_se(r == -ERANGE); assert_se(pid == 65); pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */ r = parse_pid("0xFFFFFFFFFFFFFFFFF", &pid); assert_se(r == -ERANGE); assert_se(pid == 65); r = parse_pid("junk", &pid); assert_se(r == -EINVAL); } static void test_parse_mode(void) { mode_t m; assert_se(parse_mode("-1", &m) < 0); assert_se(parse_mode("", &m) < 0); assert_se(parse_mode("888", &m) < 0); assert_se(parse_mode("77777", &m) < 0); assert_se(parse_mode("544", &m) >= 0 && m == 0544); assert_se(parse_mode("777", &m) >= 0 && m == 0777); assert_se(parse_mode("7777", &m) >= 0 && m == 07777); assert_se(parse_mode("0", &m) >= 0 && m == 0); } static void test_parse_size(void) { uint64_t bytes; assert_se(parse_size("111", 1024, &bytes) == 0); assert_se(bytes == 111); assert_se(parse_size("111.4", 1024, &bytes) == 0); assert_se(bytes == 111); assert_se(parse_size(" 112 B", 1024, &bytes) == 0); assert_se(bytes == 112); assert_se(parse_size(" 112.6 B", 1024, &bytes) == 0); assert_se(bytes == 112); assert_se(parse_size("3.5 K", 1024, &bytes) == 0); assert_se(bytes == 3*1024 + 512); assert_se(parse_size("3. K", 1024, &bytes) == 0); assert_se(bytes == 3*1024); assert_se(parse_size("3.0 K", 1024, &bytes) == 0); assert_se(bytes == 3*1024); assert_se(parse_size("3. 0 K", 1024, &bytes) == -EINVAL); assert_se(parse_size(" 4 M 11.5K", 1024, &bytes) == 0); assert_se(bytes == 4*1024*1024 + 11 * 1024 + 512); assert_se(parse_size("3B3.5G", 1024, &bytes) == -EINVAL); assert_se(parse_size("3.5G3B", 1024, &bytes) == 0); assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 3); assert_se(parse_size("3.5G 4B", 1024, &bytes) == 0); assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 4); assert_se(parse_size("3B3G4T", 1024, &bytes) == -EINVAL); assert_se(parse_size("4T3G3B", 1024, &bytes) == 0); assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3); assert_se(parse_size(" 4 T 3 G 3 B", 1024, &bytes) == 0); assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3); assert_se(parse_size("12P", 1024, &bytes) == 0); assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024); assert_se(parse_size("12P12P", 1024, &bytes) == -EINVAL); assert_se(parse_size("3E 2P", 1024, &bytes) == 0); assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024); assert_se(parse_size("12X", 1024, &bytes) == -EINVAL); assert_se(parse_size("12.5X", 1024, &bytes) == -EINVAL); assert_se(parse_size("12.5e3", 1024, &bytes) == -EINVAL); assert_se(parse_size("1024E", 1024, &bytes) == -ERANGE); assert_se(parse_size("-1", 1024, &bytes) == -ERANGE); assert_se(parse_size("-1024E", 1024, &bytes) == -ERANGE); assert_se(parse_size("-1024P", 1024, &bytes) == -ERANGE); assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE); } static void test_parse_range(void) { unsigned lower, upper; /* Successful cases */ assert_se(parse_range("111", &lower, &upper) == 0); assert_se(lower == 111); assert_se(upper == 111); assert_se(parse_range("111-123", &lower, &upper) == 0); assert_se(lower == 111); assert_se(upper == 123); assert_se(parse_range("123-111", &lower, &upper) == 0); assert_se(lower == 123); assert_se(upper == 111); assert_se(parse_range("123-123", &lower, &upper) == 0); assert_se(lower == 123); assert_se(upper == 123); assert_se(parse_range("0", &lower, &upper) == 0); assert_se(lower == 0); assert_se(upper == 0); assert_se(parse_range("0-15", &lower, &upper) == 0); assert_se(lower == 0); assert_se(upper == 15); assert_se(parse_range("15-0", &lower, &upper) == 0); assert_se(lower == 15); assert_se(upper == 0); assert_se(parse_range("128-65535", &lower, &upper) == 0); assert_se(lower == 128); assert_se(upper == 65535); assert_se(parse_range("1024-4294967295", &lower, &upper) == 0); assert_se(lower == 1024); assert_se(upper == 4294967295); /* Leading whitespace is acceptable */ assert_se(parse_range(" 111", &lower, &upper) == 0); assert_se(lower == 111); assert_se(upper == 111); assert_se(parse_range(" 111-123", &lower, &upper) == 0); assert_se(lower == 111); assert_se(upper == 123); assert_se(parse_range("111- 123", &lower, &upper) == 0); assert_se(lower == 111); assert_se(upper == 123); assert_se(parse_range("\t111-\t123", &lower, &upper) == 0); assert_se(lower == 111); assert_se(upper == 123); assert_se(parse_range(" \t 111- \t 123", &lower, &upper) == 0); assert_se(lower == 111); assert_se(upper == 123); /* Error cases, make sure they fail as expected */ lower = upper = 9999; assert_se(parse_range("111garbage", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("garbage111", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("garbage", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111-123garbage", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111garbage-123", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); /* Empty string */ lower = upper = 9999; assert_se(parse_range("", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); /* 111--123 will pass -123 to safe_atou which returns -ERANGE for negative */ assert_se(parse_range("111--123", &lower, &upper) == -ERANGE); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("-111-123", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111-123-", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111.4-123", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111-123.4", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111,4-123", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111-123,4", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); /* Error on trailing dash */ assert_se(parse_range("111-", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111-123-", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111--", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111- ", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); /* Whitespace is not a separator */ assert_se(parse_range("111 123", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111\t123", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111 \t 123", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); /* Trailing whitespace is invalid (from safe_atou) */ assert_se(parse_range("111 ", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111-123 ", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111 -123", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111 -123 ", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111\t-123\t", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); assert_se(parse_range("111 \t -123 \t ", &lower, &upper) == -EINVAL); assert_se(lower == 9999); assert_se(upper == 9999); /* Out of the "unsigned" range, this is 1<<64 */ assert_se(parse_range("0-18446744073709551616", &lower, &upper) == -ERANGE); assert_se(lower == 9999); assert_se(upper == 9999); } static void test_safe_atolli(void) { int r; long long l; r = safe_atolli("12345", &l); assert_se(r == 0); assert_se(l == 12345); r = safe_atolli(" 12345", &l); assert_se(r == 0); assert_se(l == 12345); r = safe_atolli("-12345", &l); assert_se(r == 0); assert_se(l == -12345); r = safe_atolli(" -12345", &l); assert_se(r == 0); assert_se(l == -12345); r = safe_atolli("12345678901234567890", &l); assert_se(r == -ERANGE); r = safe_atolli("-12345678901234567890", &l); assert_se(r == -ERANGE); r = safe_atolli("junk", &l); assert_se(r == -EINVAL); } static void test_safe_atou16(void) { int r; uint16_t l; r = safe_atou16("12345", &l); assert_se(r == 0); assert_se(l == 12345); r = safe_atou16(" 12345", &l); assert_se(r == 0); assert_se(l == 12345); r = safe_atou16("123456", &l); assert_se(r == -ERANGE); r = safe_atou16("-1", &l); assert_se(r == -ERANGE); r = safe_atou16(" -1", &l); assert_se(r == -ERANGE); r = safe_atou16("junk", &l); assert_se(r == -EINVAL); } static void test_safe_atoi16(void) { int r; int16_t l; r = safe_atoi16("-12345", &l); assert_se(r == 0); assert_se(l == -12345); r = safe_atoi16(" -12345", &l); assert_se(r == 0); assert_se(l == -12345); r = safe_atoi16("32767", &l); assert_se(r == 0); assert_se(l == 32767); r = safe_atoi16(" 32767", &l); assert_se(r == 0); assert_se(l == 32767); r = safe_atoi16("36536", &l); assert_se(r == -ERANGE); r = safe_atoi16("-32769", &l); assert_se(r == -ERANGE); r = safe_atoi16("junk", &l); assert_se(r == -EINVAL); } static void test_safe_atod(void) { int r; double d; char *e; r = safe_atod("junk", &d); assert_se(r == -EINVAL); r = safe_atod("0.2244", &d); assert_se(r == 0); assert_se(fabs(d - 0.2244) < 0.000001); r = safe_atod("0,5", &d); assert_se(r == -EINVAL); errno = 0; strtod("0,5", &e); assert_se(*e == ','); /* Check if this really is locale independent */ if (setlocale(LC_NUMERIC, "de_DE.utf8")) { r = safe_atod("0.2244", &d); assert_se(r == 0); assert_se(fabs(d - 0.2244) < 0.000001); r = safe_atod("0,5", &d); assert_se(r == -EINVAL); errno = 0; assert_se(fabs(strtod("0,5", &e) - 0.5) < 0.00001); } /* And check again, reset */ assert_se(setlocale(LC_NUMERIC, "C")); r = safe_atod("0.2244", &d); assert_se(r == 0); assert_se(fabs(d - 0.2244) < 0.000001); r = safe_atod("0,5", &d); assert_se(r == -EINVAL); errno = 0; strtod("0,5", &e); assert_se(*e == ','); } int main(int argc, char *argv[]) { log_parse_environment(); log_open(); test_parse_boolean(); test_parse_pid(); test_parse_mode(); test_parse_size(); test_parse_range(); test_safe_atolli(); test_safe_atou16(); test_safe_atoi16(); test_safe_atod(); return 0; } systemd-229/src/test/test-path-lookup.c000066400000000000000000000055731265713322000202250ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "log.h" #include "path-lookup.h" #include "rm-rf.h" #include "string-util.h" #include "strv.h" static void test_paths(ManagerRunningAs running_as, bool personal) { char template[] = "/tmp/test-path-lookup.XXXXXXX"; _cleanup_lookup_paths_free_ LookupPaths lp_without_env = {}; _cleanup_lookup_paths_free_ LookupPaths lp_with_env = {}; char *exists, *not, *systemd_unit_path; assert_se(mkdtemp(template)); exists = strjoina(template, "/exists"); assert_se(mkdir(exists, 0755) == 0); not = strjoina(template, "/not"); assert_se(unsetenv("SYSTEMD_UNIT_PATH") == 0); assert_se(lookup_paths_init(&lp_without_env, running_as, personal, NULL, exists, not, not) == 0); assert_se(!strv_isempty(lp_without_env.unit_path)); assert_se(strv_contains(lp_without_env.unit_path, exists)); assert_se(strv_contains(lp_without_env.unit_path, not)); systemd_unit_path = strjoina(template, "/systemd-unit-path"); assert_se(setenv("SYSTEMD_UNIT_PATH", systemd_unit_path, 1) == 0); assert_se(lookup_paths_init(&lp_with_env, running_as, personal, NULL, exists, not, not) == 0); assert_se(strv_length(lp_with_env.unit_path) == 1); assert_se(streq(lp_with_env.unit_path[0], systemd_unit_path)); assert_se(rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); } static void print_generator_paths(ManagerRunningAs running_as) { _cleanup_strv_free_ char **paths; char **dir; log_info("Generators dirs (%s):", running_as == MANAGER_SYSTEM ? "system" : "user"); paths = generator_paths(running_as); STRV_FOREACH(dir, paths) log_info(" %s", *dir); } int main(int argc, char **argv) { log_set_max_level(LOG_DEBUG); log_parse_environment(); log_open(); test_paths(MANAGER_SYSTEM, false); test_paths(MANAGER_SYSTEM, true); test_paths(MANAGER_USER, false); test_paths(MANAGER_USER, true); print_generator_paths(MANAGER_SYSTEM); print_generator_paths(MANAGER_USER); return EXIT_SUCCESS; } systemd-229/src/test/test-path-util.c000066400000000000000000000377621265713322000176760ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "macro.h" #include "mount-util.h" #include "path-util.h" #include "rm-rf.h" #include "string-util.h" #include "strv.h" #include "util.h" #define test_path_compare(a, b, result) { \ assert_se(path_compare(a, b) == result); \ assert_se(path_compare(b, a) == -result); \ assert_se(path_equal(a, b) == !result); \ assert_se(path_equal(b, a) == !result); \ } static void test_path(void) { _cleanup_close_ int fd = -1; test_path_compare("/goo", "/goo", 0); test_path_compare("/goo", "/goo", 0); test_path_compare("//goo", "/goo", 0); test_path_compare("//goo/////", "/goo", 0); test_path_compare("goo/////", "goo", 0); test_path_compare("/goo/boo", "/goo//boo", 0); test_path_compare("//goo/boo", "/goo/boo//", 0); test_path_compare("/", "///", 0); test_path_compare("/x", "x/", 1); test_path_compare("x/", "/", -1); test_path_compare("/x/./y", "x/y", 1); test_path_compare("x/.y", "x/y", -1); test_path_compare("foo", "/foo", -1); test_path_compare("/foo", "/foo/bar", -1); test_path_compare("/foo/aaa", "/foo/b", -1); test_path_compare("/foo/aaa", "/foo/b/a", -1); test_path_compare("/foo/a", "/foo/aaa", -1); test_path_compare("/foo/a/b", "/foo/aaa", -1); assert_se(path_is_absolute("/")); assert_se(!path_is_absolute("./")); assert_se(is_path("/dir")); assert_se(is_path("a/b")); assert_se(!is_path(".")); assert_se(streq(basename("./aa/bb/../file.da."), "file.da.")); assert_se(streq(basename("/aa///.file"), ".file")); assert_se(streq(basename("/aa///file..."), "file...")); assert_se(streq(basename("file.../"), "")); fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY); assert_se(fd >= 0); assert_se(fd_is_mount_point(fd, "/", 0) > 0); { char p1[] = "aaa/bbb////ccc"; char p2[] = "//aaa/.////ccc"; char p3[] = "/./"; assert_se(path_equal(path_kill_slashes(p1), "aaa/bbb/ccc")); assert_se(path_equal(path_kill_slashes(p2), "/aaa/./ccc")); assert_se(path_equal(path_kill_slashes(p3), "/./")); } } static void test_find_binary(const char *self) { char *p; assert_se(find_binary("/bin/sh", &p) == 0); puts(p); assert_se(path_equal(p, "/bin/sh")); free(p); assert_se(find_binary(self, &p) == 0); puts(p); assert_se(endswith(p, "/test-path-util")); assert_se(path_is_absolute(p)); free(p); assert_se(find_binary("sh", &p) == 0); puts(p); assert_se(endswith(p, "/sh")); assert_se(path_is_absolute(p)); free(p); assert_se(find_binary("xxxx-xxxx", &p) == -ENOENT); assert_se(find_binary("/some/dir/xxxx-xxxx", &p) == -ENOENT); } static void test_prefixes(void) { static const char* values[] = { "/a/b/c/d", "/a/b/c", "/a/b", "/a", "", NULL}; unsigned i; char s[PATH_MAX]; bool b; i = 0; PATH_FOREACH_PREFIX_MORE(s, "/a/b/c/d") { log_error("---%s---", s); assert_se(streq(s, values[i++])); } assert_se(values[i] == NULL); i = 1; PATH_FOREACH_PREFIX(s, "/a/b/c/d") { log_error("---%s---", s); assert_se(streq(s, values[i++])); } assert_se(values[i] == NULL); i = 0; PATH_FOREACH_PREFIX_MORE(s, "////a////b////c///d///////") assert_se(streq(s, values[i++])); assert_se(values[i] == NULL); i = 1; PATH_FOREACH_PREFIX(s, "////a////b////c///d///////") assert_se(streq(s, values[i++])); assert_se(values[i] == NULL); PATH_FOREACH_PREFIX(s, "////") assert_not_reached("Wut?"); b = false; PATH_FOREACH_PREFIX_MORE(s, "////") { assert_se(!b); assert_se(streq(s, "")); b = true; } assert_se(b); PATH_FOREACH_PREFIX(s, "") assert_not_reached("wut?"); b = false; PATH_FOREACH_PREFIX_MORE(s, "") { assert_se(!b); assert_se(streq(s, "")); b = true; } } static void test_path_join(void) { #define test_join(root, path, rest, expected) { \ _cleanup_free_ char *z = NULL; \ z = path_join(root, path, rest); \ assert_se(streq(z, expected)); \ } test_join("/root", "/a/b", "/c", "/root/a/b/c"); test_join("/root", "a/b", "c", "/root/a/b/c"); test_join("/root", "/a/b", "c", "/root/a/b/c"); test_join("/root", "/", "c", "/root/c"); test_join("/root", "/", NULL, "/root/"); test_join(NULL, "/a/b", "/c", "/a/b/c"); test_join(NULL, "a/b", "c", "a/b/c"); test_join(NULL, "/a/b", "c", "/a/b/c"); test_join(NULL, "/", "c", "/c"); test_join(NULL, "/", NULL, "/"); } static void test_fsck_exists(void) { /* Ensure we use a sane default for PATH. */ unsetenv("PATH"); /* fsck.minix is provided by util-linux and will probably exist. */ assert_se(fsck_exists("minix") == 1); assert_se(fsck_exists("AbCdE") == 0); assert_se(fsck_exists("/../bin/") == 0); } static void test_make_relative(void) { char *result; assert_se(path_make_relative("some/relative/path", "/some/path", &result) < 0); assert_se(path_make_relative("/some/path", "some/relative/path", &result) < 0); #define test(from_dir, to_path, expected) { \ _cleanup_free_ char *z = NULL; \ path_make_relative(from_dir, to_path, &z); \ assert_se(streq(z, expected)); \ } test("/", "/", "."); test("/", "/some/path", "some/path"); test("/some/path", "/some/path", "."); test("/some/path", "/some/path/in/subdir", "in/subdir"); test("/some/path", "/", "../.."); test("/some/path", "/some/other/path", "../other/path"); test("//extra/////slashes///won't////fool///anybody//", "////extra///slashes////are/just///fine///", "../../../are/just/fine"); } static void test_strv_resolve(void) { char tmp_dir[] = "/tmp/test-path-util-XXXXXX"; _cleanup_strv_free_ char **search_dirs = NULL; _cleanup_strv_free_ char **absolute_dirs = NULL; char **d; assert_se(mkdtemp(tmp_dir) != NULL); search_dirs = strv_new("/dir1", "/dir2", "/dir3", NULL); assert_se(search_dirs); STRV_FOREACH(d, search_dirs) { char *p = strappend(tmp_dir, *d); assert_se(p); assert_se(strv_push(&absolute_dirs, p) == 0); } assert_se(mkdir(absolute_dirs[0], 0700) == 0); assert_se(mkdir(absolute_dirs[1], 0700) == 0); assert_se(symlink("dir2", absolute_dirs[2]) == 0); path_strv_resolve(search_dirs, tmp_dir); assert_se(streq(search_dirs[0], "/dir1")); assert_se(streq(search_dirs[1], "/dir2")); assert_se(streq(search_dirs[2], "/dir2")); assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0); } static void test_path_startswith(void) { assert_se(path_startswith("/foo/bar/barfoo/", "/foo")); assert_se(path_startswith("/foo/bar/barfoo/", "/foo/")); assert_se(path_startswith("/foo/bar/barfoo/", "/")); assert_se(path_startswith("/foo/bar/barfoo/", "////")); assert_se(path_startswith("/foo/bar/barfoo/", "/foo//bar/////barfoo///")); assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo////")); assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar///barfoo/")); assert_se(path_startswith("/foo/bar/barfoo/", "/foo////bar/barfoo/")); assert_se(path_startswith("/foo/bar/barfoo/", "////foo/bar/barfoo/")); assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo")); assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa/")); assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa")); assert_se(!path_startswith("/foo/bar/barfoo/", "")); assert_se(!path_startswith("/foo/bar/barfoo/", "/bar/foo")); assert_se(!path_startswith("/foo/bar/barfoo/", "/f/b/b/")); } static void test_prefix_root_one(const char *r, const char *p, const char *expected) { _cleanup_free_ char *s = NULL; const char *t; assert_se(s = prefix_root(r, p)); assert_se(streq_ptr(s, expected)); t = prefix_roota(r, p); assert_se(t); assert_se(streq_ptr(t, expected)); } static void test_prefix_root(void) { test_prefix_root_one("/", "/foo", "/foo"); test_prefix_root_one(NULL, "/foo", "/foo"); test_prefix_root_one("", "/foo", "/foo"); test_prefix_root_one("///", "/foo", "/foo"); test_prefix_root_one("/", "////foo", "/foo"); test_prefix_root_one(NULL, "////foo", "/foo"); test_prefix_root_one("/foo", "/bar", "/foo/bar"); test_prefix_root_one("/foo", "bar", "/foo/bar"); test_prefix_root_one("foo", "bar", "foo/bar"); test_prefix_root_one("/foo/", "/bar", "/foo/bar"); test_prefix_root_one("/foo/", "//bar", "/foo/bar"); test_prefix_root_one("/foo///", "//bar", "/foo/bar"); } static void test_path_is_mount_point(void) { int fd; char tmp_dir[] = "/tmp/test-path-is-mount-point-XXXXXX"; _cleanup_free_ char *file1 = NULL, *file2 = NULL, *link1 = NULL, *link2 = NULL; _cleanup_free_ char *dir1 = NULL, *dir1file = NULL, *dirlink1 = NULL, *dirlink1file = NULL; _cleanup_free_ char *dir2 = NULL, *dir2file = NULL; assert_se(path_is_mount_point("/", AT_SYMLINK_FOLLOW) > 0); assert_se(path_is_mount_point("/", 0) > 0); assert_se(path_is_mount_point("/proc", AT_SYMLINK_FOLLOW) > 0); assert_se(path_is_mount_point("/proc", 0) > 0); assert_se(path_is_mount_point("/proc/1", AT_SYMLINK_FOLLOW) == 0); assert_se(path_is_mount_point("/proc/1", 0) == 0); assert_se(path_is_mount_point("/sys", AT_SYMLINK_FOLLOW) > 0); assert_se(path_is_mount_point("/sys", 0) > 0); /* we'll create a hierarchy of different kinds of dir/file/link * layouts: * * /file1, /file2 * /link1 -> file1, /link2 -> file2 * /dir1/ * /dir1/file * /dirlink1 -> dir1 * /dirlink1file -> dirlink1/file * /dir2/ * /dir2/file */ /* file mountpoints */ assert_se(mkdtemp(tmp_dir) != NULL); file1 = path_join(NULL, tmp_dir, "file1"); assert_se(file1); file2 = path_join(NULL, tmp_dir, "file2"); assert_se(file2); fd = open(file1, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); assert_se(fd > 0); close(fd); fd = open(file2, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); assert_se(fd > 0); close(fd); link1 = path_join(NULL, tmp_dir, "link1"); assert_se(link1); assert_se(symlink("file1", link1) == 0); link2 = path_join(NULL, tmp_dir, "link2"); assert_se(link1); assert_se(symlink("file2", link2) == 0); assert_se(path_is_mount_point(file1, AT_SYMLINK_FOLLOW) == 0); assert_se(path_is_mount_point(file1, 0) == 0); assert_se(path_is_mount_point(link1, AT_SYMLINK_FOLLOW) == 0); assert_se(path_is_mount_point(link1, 0) == 0); /* directory mountpoints */ dir1 = path_join(NULL, tmp_dir, "dir1"); assert_se(dir1); assert_se(mkdir(dir1, 0755) == 0); dirlink1 = path_join(NULL, tmp_dir, "dirlink1"); assert_se(dirlink1); assert_se(symlink("dir1", dirlink1) == 0); dirlink1file = path_join(NULL, tmp_dir, "dirlink1file"); assert_se(dirlink1file); assert_se(symlink("dirlink1/file", dirlink1file) == 0); dir2 = path_join(NULL, tmp_dir, "dir2"); assert_se(dir2); assert_se(mkdir(dir2, 0755) == 0); assert_se(path_is_mount_point(dir1, AT_SYMLINK_FOLLOW) == 0); assert_se(path_is_mount_point(dir1, 0) == 0); assert_se(path_is_mount_point(dirlink1, AT_SYMLINK_FOLLOW) == 0); assert_se(path_is_mount_point(dirlink1, 0) == 0); /* file in subdirectory mountpoints */ dir1file = path_join(NULL, dir1, "file"); assert_se(dir1file); fd = open(dir1file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); assert_se(fd > 0); close(fd); assert_se(path_is_mount_point(dir1file, AT_SYMLINK_FOLLOW) == 0); assert_se(path_is_mount_point(dir1file, 0) == 0); assert_se(path_is_mount_point(dirlink1file, AT_SYMLINK_FOLLOW) == 0); assert_se(path_is_mount_point(dirlink1file, 0) == 0); /* these tests will only work as root */ if (mount(file1, file2, NULL, MS_BIND, NULL) >= 0) { int rt, rf, rlt, rlf, rl1t, rl1f; /* files */ /* capture results in vars, to avoid dangling mounts on failure */ rf = path_is_mount_point(file2, 0); rt = path_is_mount_point(file2, AT_SYMLINK_FOLLOW); rlf = path_is_mount_point(link2, 0); rlt = path_is_mount_point(link2, AT_SYMLINK_FOLLOW); assert_se(umount(file2) == 0); assert_se(rf == 1); assert_se(rt == 1); assert_se(rlf == 0); assert_se(rlt == 1); /* dirs */ dir2file = path_join(NULL, dir2, "file"); assert_se(dir2file); fd = open(dir2file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); assert_se(fd > 0); close(fd); assert_se(mount(dir2, dir1, NULL, MS_BIND, NULL) >= 0); rf = path_is_mount_point(dir1, 0); rt = path_is_mount_point(dir1, AT_SYMLINK_FOLLOW); rlf = path_is_mount_point(dirlink1, 0); rlt = path_is_mount_point(dirlink1, AT_SYMLINK_FOLLOW); /* its parent is a mount point, but not /file itself */ rl1f = path_is_mount_point(dirlink1file, 0); rl1t = path_is_mount_point(dirlink1file, AT_SYMLINK_FOLLOW); assert_se(umount(dir1) == 0); assert_se(rf == 1); assert_se(rt == 1); assert_se(rlf == 0); assert_se(rlt == 1); assert_se(rl1f == 0); assert_se(rl1t == 0); } else printf("Skipping bind mount file test: %m\n"); assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0); } int main(int argc, char **argv) { test_path(); test_find_binary(argv[0]); test_prefixes(); test_path_join(); test_fsck_exists(); test_make_relative(); test_strv_resolve(); test_path_startswith(); test_prefix_root(); test_path_is_mount_point(); return 0; } systemd-229/src/test/test-path.c000066400000000000000000000204001265713322000167000ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "alloc-util.h" #include "fd-util.h" #include "fs-util.h" #include "macro.h" #include "manager.h" #include "mkdir.h" #include "rm-rf.h" #include "string-util.h" #include "strv.h" #include "test-helper.h" #include "unit.h" #include "util.h" typedef void (*test_function_t)(Manager *m); static int setup_test(Manager **m) { char **tests_path = STRV_MAKE("exists", "existsglobFOOBAR", "changed", "modified", "unit", "directorynotempty", "makedirectory"); char **test_path; Manager *tmp = NULL; int r; assert_se(m); r = manager_new(MANAGER_USER, true, &tmp); if (MANAGER_SKIP_TEST(r)) { printf("Skipping test: manager_new: %s\n", strerror(-r)); return -EXIT_TEST_SKIP; } assert_se(r >= 0); assert_se(manager_startup(tmp, NULL, NULL) >= 0); STRV_FOREACH(test_path, tests_path) { _cleanup_free_ char *p = NULL; p = strjoin("/tmp/test-path_", *test_path, NULL); assert_se(p); (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL); } *m = tmp; return 0; } static void shutdown_test(Manager *m) { assert_se(m); manager_free(m); } static void check_stop_unlink(Manager *m, Unit *unit, const char *test_path, const char *service_name) { _cleanup_free_ char *tmp = NULL; Unit *service_unit = NULL; Service *service = NULL; usec_t ts; usec_t timeout = 2 * USEC_PER_SEC; assert_se(m); assert_se(unit); assert_se(test_path); if (!service_name) { assert_se(tmp = strreplace(unit->id, ".path", ".service")); service_unit = manager_get_unit(m, tmp); } else service_unit = manager_get_unit(m, service_name); assert_se(service_unit); service = SERVICE(service_unit); ts = now(CLOCK_MONOTONIC); /* We process events until the service related to the path has been successfully started */ while(service->result != SERVICE_SUCCESS || service->state != SERVICE_START) { usec_t n; int r; r = sd_event_run(m->event, 100 * USEC_PER_MSEC); assert_se(r >= 0); printf("%s: state = %s; result = %s \n", service_unit->id, service_state_to_string(service->state), service_result_to_string(service->result)); /* But we timeout if the service has not been started in the allocated time */ n = now(CLOCK_MONOTONIC); if (ts + timeout < n) { log_error("Test timeout when testing %s", unit->id); exit(EXIT_FAILURE); } } assert_se(UNIT_VTABLE(unit)->stop(unit) >= 0); (void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL); } static void test_path_exists(Manager *m) { const char *test_path = "/tmp/test-path_exists"; Unit *unit = NULL; assert_se(m); assert_se(manager_load_unit(m, "path-exists.path", NULL, NULL, &unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); assert_se(touch(test_path) >= 0); check_stop_unlink(m, unit, test_path, NULL); } static void test_path_existsglob(Manager *m) { const char *test_path = "/tmp/test-path_existsglobFOOBAR"; Unit *unit = NULL; assert_se(m); assert_se(manager_load_unit(m, "path-existsglob.path", NULL, NULL, &unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); assert_se(touch(test_path) >= 0); check_stop_unlink(m, unit, test_path, NULL); } static void test_path_changed(Manager *m) { const char *test_path = "/tmp/test-path_changed"; FILE *f; Unit *unit = NULL; assert_se(m); assert_se(touch(test_path) >= 0); assert_se(manager_load_unit(m, "path-changed.path", NULL, NULL, &unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); f = fopen(test_path, "w"); assert_se(f); fclose(f); check_stop_unlink(m, unit, test_path, NULL); } static void test_path_modified(Manager *m) { _cleanup_fclose_ FILE *f = NULL; const char *test_path = "/tmp/test-path_modified"; Unit *unit = NULL; assert_se(m); assert_se(touch(test_path) >= 0); assert_se(manager_load_unit(m, "path-modified.path", NULL, NULL, &unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); f = fopen(test_path, "w"); assert_se(f); fputs("test", f); check_stop_unlink(m, unit, test_path, NULL); } static void test_path_unit(Manager *m) { const char *test_path = "/tmp/test-path_unit"; Unit *unit = NULL; assert_se(m); assert_se(manager_load_unit(m, "path-unit.path", NULL, NULL, &unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); assert_se(touch(test_path) >= 0); check_stop_unlink(m, unit, test_path, "path-mycustomunit.service"); } static void test_path_directorynotempty(Manager *m) { const char *test_path = "/tmp/test-path_directorynotempty/"; Unit *unit = NULL; assert_se(m); assert_se(access(test_path, F_OK) < 0); assert_se(manager_load_unit(m, "path-directorynotempty.path", NULL, NULL, &unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); /* MakeDirectory default to no */ assert_se(access(test_path, F_OK) < 0); assert_se(mkdir_p(test_path, 0755) >= 0); assert_se(touch(strjoina(test_path, "test_file")) >= 0); check_stop_unlink(m, unit, test_path, NULL); } static void test_path_makedirectory_directorymode(Manager *m) { const char *test_path = "/tmp/test-path_makedirectory/"; Unit *unit = NULL; struct stat s; assert_se(m); assert_se(access(test_path, F_OK) < 0); assert_se(manager_load_unit(m, "path-makedirectory.path", NULL, NULL, &unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); /* Check if the directory has been created */ assert_se(access(test_path, F_OK) >= 0); /* Check the mode we specified with DirectoryMode=0744 */ assert_se(stat(test_path, &s) >= 0); assert_se((s.st_mode & S_IRWXU) == 0700); assert_se((s.st_mode & S_IRWXG) == 0040); assert_se((s.st_mode & S_IRWXO) == 0004); assert_se(UNIT_VTABLE(unit)->stop(unit) >= 0); (void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL); } int main(int argc, char *argv[]) { test_function_t tests[] = { test_path_exists, test_path_existsglob, test_path_changed, test_path_modified, test_path_unit, test_path_directorynotempty, test_path_makedirectory_directorymode, NULL, }; test_function_t *test = NULL; Manager *m = NULL; log_parse_environment(); log_open(); assert_se(set_unit_path(TEST_DIR "/test-path/") >= 0); for (test = tests; test && *test; test++) { int r; /* We create a clean environment for each test */ r = setup_test(&m); if (r < 0) return -r; (*test)(m); shutdown_test(m); } return 0; } systemd-229/src/test/test-prioq.c000066400000000000000000000076131265713322000171110ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "prioq.h" #include "set.h" #include "siphash24.h" #include "util.h" #define SET_SIZE 1024*4 static int unsigned_compare(const void *a, const void *b) { const unsigned *x = a, *y = b; if (*x < *y) return -1; if (*x > *y) return 1; return 0; } static void test_unsigned(void) { unsigned buffer[SET_SIZE], i; Prioq *q; srand(0); q = prioq_new(trivial_compare_func); assert_se(q); for (i = 0; i < ELEMENTSOF(buffer); i++) { unsigned u; u = (unsigned) rand(); buffer[i] = u; assert_se(prioq_put(q, UINT_TO_PTR(u), NULL) >= 0); } qsort(buffer, ELEMENTSOF(buffer), sizeof(buffer[0]), unsigned_compare); for (i = 0; i < ELEMENTSOF(buffer); i++) { unsigned u; assert_se(prioq_size(q) == ELEMENTSOF(buffer) - i); u = PTR_TO_UINT(prioq_pop(q)); assert_se(buffer[i] == u); } assert_se(prioq_isempty(q)); prioq_free(q); } struct test { unsigned value; unsigned idx; }; static int test_compare(const void *a, const void *b) { const struct test *x = a, *y = b; if (x->value < y->value) return -1; if (x->value > y->value) return 1; return 0; } static void test_hash(const void *a, struct siphash *state) { const struct test *x = a; siphash24_compress(&x->value, sizeof(x->value), state); } static const struct hash_ops test_hash_ops = { .hash = test_hash, .compare = test_compare }; static void test_struct(void) { Prioq *q; Set *s; unsigned previous = 0, i; int r; srand(0); q = prioq_new(test_compare); assert_se(q); s = set_new(&test_hash_ops); assert_se(s); for (i = 0; i < SET_SIZE; i++) { struct test *t; t = new0(struct test, 1); assert_se(t); t->value = (unsigned) rand(); r = prioq_put(q, t, &t->idx); assert_se(r >= 0); if (i % 4 == 0) { r = set_consume(s, t); assert_se(r >= 0); } } for (;;) { struct test *t; t = set_steal_first(s); if (!t) break; r = prioq_remove(q, t, &t->idx); assert_se(r > 0); free(t); } for (i = 0; i < SET_SIZE * 3 / 4; i++) { struct test *t; assert_se(prioq_size(q) == (SET_SIZE * 3 / 4) - i); t = prioq_pop(q); assert_se(t); assert_se(previous <= t->value); previous = t->value; free(t); } assert_se(prioq_isempty(q)); prioq_free(q); assert_se(set_isempty(s)); set_free(s); } int main(int argc, char* argv[]) { test_unsigned(); test_struct(); return 0; } systemd-229/src/test/test-process-util.c000066400000000000000000000075431265713322000204120ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Thomas H.P. Andersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "log.h" #include "macro.h" #include "process-util.h" #include "string-util.h" #include "terminal-util.h" #include "util.h" #include "virt.h" static void test_get_process_comm(void) { struct stat st; _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL, *cwd = NULL, *root = NULL; _cleanup_free_ char *env = NULL; pid_t e; uid_t u; gid_t g; dev_t h; int r; pid_t me; if (stat("/proc/1/comm", &st) == 0) { assert_se(get_process_comm(1, &a) >= 0); log_info("pid1 comm: '%s'", a); } else log_warning("/proc/1/comm does not exist."); assert_se(get_process_cmdline(1, 0, true, &c) >= 0); log_info("pid1 cmdline: '%s'", c); assert_se(get_process_cmdline(1, 8, false, &d) >= 0); log_info("pid1 cmdline truncated: '%s'", d); assert_se(get_process_ppid(1, &e) >= 0); log_info("pid1 ppid: "PID_FMT, e); assert_se(e == 0); assert_se(is_kernel_thread(1) == 0); r = get_process_exe(1, &f); assert_se(r >= 0 || r == -EACCES); log_info("pid1 exe: '%s'", strna(f)); assert_se(get_process_uid(1, &u) == 0); log_info("pid1 uid: "UID_FMT, u); assert_se(u == 0); assert_se(get_process_gid(1, &g) == 0); log_info("pid1 gid: "GID_FMT, g); assert_se(g == 0); me = getpid(); r = get_process_cwd(me, &cwd); assert_se(r >= 0 || r == -EACCES); log_info("pid1 cwd: '%s'", cwd); r = get_process_root(me, &root); assert_se(r >= 0 || r == -EACCES); log_info("pid1 root: '%s'", root); r = get_process_environ(me, &env); assert_se(r >= 0 || r == -EACCES); log_info("self strlen(environ): '%zu'", strlen(env)); if (!detect_container()) assert_se(get_ctty_devnr(1, &h) == -ENXIO); getenv_for_pid(1, "PATH", &i); log_info("pid1 $PATH: '%s'", strna(i)); } static void test_pid_is_unwaited(void) { pid_t pid; pid = fork(); assert_se(pid >= 0); if (pid == 0) { _exit(EXIT_SUCCESS); } else { int status; waitpid(pid, &status, 0); assert_se(!pid_is_unwaited(pid)); } assert_se(pid_is_unwaited(getpid())); assert_se(!pid_is_unwaited(-1)); } static void test_pid_is_alive(void) { pid_t pid; pid = fork(); assert_se(pid >= 0); if (pid == 0) { _exit(EXIT_SUCCESS); } else { int status; waitpid(pid, &status, 0); assert_se(!pid_is_alive(pid)); } assert_se(pid_is_alive(getpid())); assert_se(!pid_is_alive(-1)); } int main(int argc, char *argv[]) { log_parse_environment(); log_open(); test_get_process_comm(); test_pid_is_unwaited(); test_pid_is_alive(); return 0; } systemd-229/src/test/test-ratelimit.c000066400000000000000000000025471265713322000177520ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2014 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" #include "ratelimit.h" #include "time-util.h" static void test_ratelimit_test(void) { int i; RATELIMIT_DEFINE(ratelimit, 1 * USEC_PER_SEC, 10); for (i = 0; i < 10; i++) assert_se(ratelimit_test(&ratelimit)); assert_se(!ratelimit_test(&ratelimit)); sleep(1); for (i = 0; i < 10; i++) assert_se(ratelimit_test(&ratelimit)); RATELIMIT_INIT(ratelimit, 0, 10); for (i = 0; i < 10000; i++) assert_se(ratelimit_test(&ratelimit)); } int main(int argc, char *argv[]) { test_ratelimit_test(); return 0; } systemd-229/src/test/test-rbtree.c000066400000000000000000000265711265713322000172460ustar00rootroot00000000000000/*** This file is part of systemd. See COPYING for details. systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* * Tests for RB-Tree */ #undef NDEBUG #include #include #include #include "c-rbtree.h" /* verify that all API calls are exported */ static void test_api(void) { CRBTree t = {}; CRBNode n = C_RBNODE_INIT(n); assert(!c_rbnode_is_linked(&n)); /* init, is_linked, add, remove, remove_init */ c_rbtree_add(&t, NULL, &t.root, &n); assert(c_rbnode_is_linked(&n)); c_rbtree_remove_init(&t, &n); assert(!c_rbnode_is_linked(&n)); c_rbtree_add(&t, NULL, &t.root, &n); assert(c_rbnode_is_linked(&n)); c_rbtree_remove(&t, &n); assert(c_rbnode_is_linked(&n)); /* @n wasn't touched */ c_rbnode_init(&n); assert(!c_rbnode_is_linked(&n)); /* first, last, leftmost, rightmost, next, prev */ assert(!c_rbtree_first(&t)); assert(!c_rbtree_last(&t)); assert(&n == c_rbnode_leftmost(&n)); assert(&n == c_rbnode_rightmost(&n)); assert(!c_rbnode_next(&n)); assert(!c_rbnode_prev(&n)); } /* copied from c-rbtree.c, relies on internal representation */ static inline _Bool c_rbnode_is_red(CRBNode *n) { return !((unsigned long)n->__parent_and_color & 1UL); } /* copied from c-rbtree.c, relies on internal representation */ static inline _Bool c_rbnode_is_black(CRBNode *n) { return !!((unsigned long)n->__parent_and_color & 1UL); } static size_t validate(CRBTree *t) { unsigned int i_black, n_black; CRBNode *n, *p, *o; size_t count = 0; assert(t); assert(!t->root || c_rbnode_is_black(t->root)); /* traverse to left-most child, count black nodes */ i_black = 0; n = t->root; while (n && n->left) { if (c_rbnode_is_black(n)) ++i_black; n = n->left; } n_black = i_black; /* * Traverse tree and verify correctness: * 1) A node is either red or black * 2) The root is black * 3) All leaves are black * 4) Every red node must have two black child nodes * 5) Every path to a leaf contains the same number of black nodes * * Note that NULL nodes are considered black, which is why we don't * check for 3). */ o = NULL; while (n) { ++count; /* verify natural order */ assert(n > o); o = n; /* verify consistency */ assert(!n->right || c_rbnode_parent(n->right) == n); assert(!n->left || c_rbnode_parent(n->left) == n); /* verify 2) */ if (!c_rbnode_parent(n)) assert(c_rbnode_is_black(n)); if (c_rbnode_is_red(n)) { /* verify 4) */ assert(!n->left || c_rbnode_is_black(n->left)); assert(!n->right || c_rbnode_is_black(n->right)); } else { /* verify 1) */ assert(c_rbnode_is_black(n)); } /* verify 5) */ if (!n->left && !n->right) assert(i_black == n_black); /* get next node */ if (n->right) { n = n->right; if (c_rbnode_is_black(n)) ++i_black; while (n->left) { n = n->left; if (c_rbnode_is_black(n)) ++i_black; } } else { while ((p = c_rbnode_parent(n)) && n == p->right) { n = p; if (c_rbnode_is_black(p->right)) --i_black; } n = p; if (p && c_rbnode_is_black(p->left)) --i_black; } } return count; } static void insert(CRBTree *t, CRBNode *n) { CRBNode **i, *p; assert(t); assert(n); assert(!c_rbnode_is_linked(n)); i = &t->root; p = NULL; while (*i) { p = *i; if (n < *i) { i = &(*i)->left; } else { assert(n > *i); i = &(*i)->right; } } c_rbtree_add(t, p, i, n); } static void shuffle(void **nodes, size_t n_memb) { unsigned int i, j; void *t; for (i = 0; i < n_memb; ++i) { j = rand() % n_memb; t = nodes[j]; nodes[j] = nodes[i]; nodes[i] = t; } } /* run some pseudo-random tests on the tree */ static void test_shuffle(void) { CRBNode *nodes[256]; CRBTree t = {}; unsigned int i, j; size_t n; /* allocate and initialize all nodes */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) { nodes[i] = malloc(sizeof(*nodes[i])); assert(nodes[i]); c_rbnode_init(nodes[i]); } /* shuffle nodes and validate *empty* tree */ shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes)); n = validate(&t); assert(n == 0); /* add all nodes and validate after each insertion */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) { insert(&t, nodes[i]); n = validate(&t); assert(n == i + 1); } /* shuffle nodes again */ shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes)); /* remove all nodes (in different order) and validate on each round */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) { c_rbtree_remove(&t, nodes[i]); n = validate(&t); assert(n == sizeof(nodes) / sizeof(*nodes) - i - 1); c_rbnode_init(nodes[i]); } /* shuffle nodes and validate *empty* tree again */ shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes)); n = validate(&t); assert(n == 0); /* add all nodes again */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) { insert(&t, nodes[i]); n = validate(&t); assert(n == i + 1); } /* 4 times, remove half of the nodes and add them again */ for (j = 0; j < 4; ++j) { /* shuffle nodes again */ shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes)); /* remove half of the nodes */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes) / 2; ++i) { c_rbtree_remove(&t, nodes[i]); n = validate(&t); assert(n == sizeof(nodes) / sizeof(*nodes) - i - 1); c_rbnode_init(nodes[i]); } /* shuffle the removed half */ shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes) / 2); /* add the removed half again */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes) / 2; ++i) { insert(&t, nodes[i]); n = validate(&t); assert(n == sizeof(nodes) / sizeof(*nodes) / 2 + i + 1); } } /* shuffle nodes again */ shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes)); /* remove all */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) { c_rbtree_remove(&t, nodes[i]); n = validate(&t); assert(n == sizeof(nodes) / sizeof(*nodes) - i - 1); c_rbnode_init(nodes[i]); } /* free nodes again */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) free(nodes[i]); } typedef struct { unsigned long key; CRBNode rb; } Node; #define node_from_rb(_rb) ((Node *)((char *)(_rb) - offsetof(Node, rb))) static int compare(CRBTree *t, void *k, CRBNode *n) { unsigned long key = (unsigned long)k; Node *node = node_from_rb(n); return (key < node->key) ? -1 : (key > node->key) ? 1 : 0; } /* run tests against the c_rbtree_find*() helpers */ static void test_map(void) { CRBNode **slot, *p; CRBTree t = {}; Node *nodes[2048]; unsigned long i; /* allocate and initialize all nodes */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) { nodes[i] = malloc(sizeof(*nodes[i])); assert(nodes[i]); nodes[i]->key = i; c_rbnode_init(&nodes[i]->rb); } /* shuffle nodes */ shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes)); /* add all nodes, and verify that each node is linked */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) { assert(!c_rbnode_is_linked(&nodes[i]->rb)); assert(!c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb)); slot = c_rbtree_find_slot(&t, compare, (void *)nodes[i]->key, &p); assert(slot); c_rbtree_add(&t, p, slot, &nodes[i]->rb); assert(c_rbnode_is_linked(&nodes[i]->rb)); assert(nodes[i] == c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb)); } /* shuffle nodes again */ shuffle((void **)nodes, sizeof(nodes) / sizeof(*nodes)); /* remove all nodes (in different order) */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) { assert(c_rbnode_is_linked(&nodes[i]->rb)); assert(nodes[i] == c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb)); c_rbtree_remove_init(&t, &nodes[i]->rb); assert(!c_rbnode_is_linked(&nodes[i]->rb)); assert(!c_rbtree_find_entry(&t, compare, (void *)nodes[i]->key, Node, rb)); } /* free nodes again */ for (i = 0; i < sizeof(nodes) / sizeof(*nodes); ++i) free(nodes[i]); } int main(int argc, char **argv) { unsigned int i; /* we want stable tests, so use fixed seed */ srand(0xdeadbeef); test_api(); /* * The tests are pseudo random; run them multiple times, each run will * have different orders and thus different results. */ for (i = 0; i < 4; ++i) { test_shuffle(); test_map(); } return 0; } systemd-229/src/test/test-replace-var.c000066400000000000000000000026011265713322000201500ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" #include "replace-var.h" #include "string-util.h" #include "util.h" static char *lookup(const char *variable, void *userdata) { return strjoin("<<<", variable, ">>>", NULL); } int main(int argc, char *argv[]) { char *r; assert_se(r = replace_var("@@@foobar@xyz@HALLO@foobar@test@@testtest@TEST@...@@@", lookup, NULL)); puts(r); assert_se(streq(r, "@@@foobar@xyz<<>>foobar@test@@testtest<<>>...@@@")); free(r); assert_se(r = strreplace("XYZFFFFXYZFFFFXYZ", "XYZ", "ABC")); puts(r); assert_se(streq(r, "ABCFFFFABCFFFFABC")); free(r); return 0; } systemd-229/src/test/test-rlimit-util.c000066400000000000000000000101131265713322000202170ustar00rootroot00000000000000/*** This file is part of systemd systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "capability-util.h" #include "macro.h" #include "rlimit-util.h" #include "string-util.h" #include "util.h" static void test_rlimit_parse_format(int resource, const char *string, rlim_t soft, rlim_t hard, int ret, const char *formatted) { _cleanup_free_ char *f = NULL; struct rlimit rl = { .rlim_cur = 4711, .rlim_max = 4712, }, rl2 = { .rlim_cur = 4713, .rlim_max = 4714 }; assert_se(rlimit_parse(resource, string, &rl) == ret); if (ret < 0) return; assert_se(rl.rlim_cur == soft); assert_se(rl.rlim_max == hard); assert_se(rlimit_format(&rl, &f) >= 0); assert_se(streq(formatted, f)); assert_se(rlimit_parse(resource, formatted, &rl2) >= 0); assert_se(memcmp(&rl, &rl2, sizeof(struct rlimit)) == 0); } int main(int argc, char *argv[]) { struct rlimit old, new, high; struct rlimit err = { .rlim_cur = 10, .rlim_max = 5, }; log_parse_environment(); log_open(); assert_se(drop_capability(CAP_SYS_RESOURCE) == 0); assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0); new.rlim_cur = MIN(5U, old.rlim_max); new.rlim_max = old.rlim_max; assert_se(setrlimit(RLIMIT_NOFILE, &new) >= 0); assert_se(rlimit_from_string("LimitNOFILE") == RLIMIT_NOFILE); assert_se(rlimit_from_string("DefaultLimitNOFILE") == -1); assert_se(streq_ptr(rlimit_to_string(RLIMIT_NOFILE), "LimitNOFILE")); assert_se(rlimit_to_string(-1) == NULL); assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0); assert_se(setrlimit_closest(RLIMIT_NOFILE, &old) == 0); assert_se(getrlimit(RLIMIT_NOFILE, &new) == 0); assert_se(old.rlim_cur == new.rlim_cur); assert_se(old.rlim_max == new.rlim_max); assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0); high = RLIMIT_MAKE_CONST(old.rlim_max == RLIM_INFINITY ? old.rlim_max : old.rlim_max + 1); assert_se(setrlimit_closest(RLIMIT_NOFILE, &high) == 0); assert_se(getrlimit(RLIMIT_NOFILE, &new) == 0); assert_se(new.rlim_max == old.rlim_max); assert_se(new.rlim_cur == new.rlim_max); assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0); assert_se(setrlimit_closest(RLIMIT_NOFILE, &err) == -EINVAL); assert_se(getrlimit(RLIMIT_NOFILE, &new) == 0); assert_se(old.rlim_cur == new.rlim_cur); assert_se(old.rlim_max == new.rlim_max); test_rlimit_parse_format(RLIMIT_NOFILE, "4:5", 4, 5, 0, "4:5"); test_rlimit_parse_format(RLIMIT_NOFILE, "6", 6, 6, 0, "6"); test_rlimit_parse_format(RLIMIT_NOFILE, "infinity", RLIM_INFINITY, RLIM_INFINITY, 0, "infinity"); test_rlimit_parse_format(RLIMIT_NOFILE, "infinity:infinity", RLIM_INFINITY, RLIM_INFINITY, 0, "infinity"); test_rlimit_parse_format(RLIMIT_NOFILE, "8:infinity", 8, RLIM_INFINITY, 0, "8:infinity"); test_rlimit_parse_format(RLIMIT_CPU, "25min:13h", (25*USEC_PER_MINUTE) / USEC_PER_SEC, (13*USEC_PER_HOUR) / USEC_PER_SEC, 0, "1500:46800"); test_rlimit_parse_format(RLIMIT_NOFILE, "", 0, 0, -EINVAL, NULL); test_rlimit_parse_format(RLIMIT_NOFILE, "5:4", 0, 0, -EILSEQ, NULL); test_rlimit_parse_format(RLIMIT_NOFILE, "5:4:3", 0, 0, -EINVAL, NULL); return 0; } systemd-229/src/test/test-sched-prio.c000066400000000000000000000066271265713322000200200ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Holger Hans Peter Freyther systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "macro.h" #include "manager.h" #include "test-helper.h" int main(int argc, char *argv[]) { Manager *m = NULL; Unit *idle_ok, *idle_bad, *rr_ok, *rr_bad, *rr_sched; Service *ser; FILE *serial = NULL; FDSet *fdset = NULL; int r; /* prepare the test */ assert_se(set_unit_path(TEST_DIR) >= 0); r = manager_new(MANAGER_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { printf("Skipping test: manager_new: %s\n", strerror(-r)); return EXIT_TEST_SKIP; } assert_se(r >= 0); assert_se(manager_startup(m, serial, fdset) >= 0); /* load idle ok */ assert_se(manager_load_unit(m, "sched_idle_ok.service", NULL, NULL, &idle_ok) >= 0); assert_se(idle_ok->load_state == UNIT_LOADED); ser = SERVICE(idle_ok); assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER); assert_se(ser->exec_context.cpu_sched_priority == 0); /* * load idle bad. This should print a warning but we have no way to look at it. */ assert_se(manager_load_unit(m, "sched_idle_bad.service", NULL, NULL, &idle_bad) >= 0); assert_se(idle_bad->load_state == UNIT_LOADED); ser = SERVICE(idle_ok); assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER); assert_se(ser->exec_context.cpu_sched_priority == 0); /* * load rr ok. * Test that the default priority is moving from 0 to 1. */ assert_se(manager_load_unit(m, "sched_rr_ok.service", NULL, NULL, &rr_ok) >= 0); assert_se(rr_ok->load_state == UNIT_LOADED); ser = SERVICE(rr_ok); assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR); assert_se(ser->exec_context.cpu_sched_priority == 1); /* * load rr bad. * Test that the value of 0 and 100 is ignored. */ assert_se(manager_load_unit(m, "sched_rr_bad.service", NULL, NULL, &rr_bad) >= 0); assert_se(rr_bad->load_state == UNIT_LOADED); ser = SERVICE(rr_bad); assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR); assert_se(ser->exec_context.cpu_sched_priority == 1); /* * load rr change. * Test that anything between 1 and 99 can be set. */ assert_se(manager_load_unit(m, "sched_rr_change.service", NULL, NULL, &rr_sched) >= 0); assert_se(rr_sched->load_state == UNIT_LOADED); ser = SERVICE(rr_sched); assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR); assert_se(ser->exec_context.cpu_sched_priority == 99); manager_free(m); return EXIT_SUCCESS; } systemd-229/src/test/test-set.c000066400000000000000000000036221265713322000165460ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "set.h" static void test_set_steal_first(void) { _cleanup_set_free_ Set *m = NULL; int seen[3] = {}; char *val; m = set_new(&string_hash_ops); assert_se(m); assert_se(set_put(m, (void*) "1") == 1); assert_se(set_put(m, (void*) "22") == 1); assert_se(set_put(m, (void*) "333") == 1); while ((val = set_steal_first(m))) seen[strlen(val) - 1]++; assert_se(seen[0] == 1 && seen[1] == 1 && seen[2] == 1); assert_se(set_isempty(m)); } static void test_set_put(void) { _cleanup_set_free_ Set *m = NULL; m = set_new(&string_hash_ops); assert_se(m); assert_se(set_put(m, (void*) "1") == 1); assert_se(set_put(m, (void*) "22") == 1); assert_se(set_put(m, (void*) "333") == 1); assert_se(set_put(m, (void*) "333") == 0); assert_se(set_remove(m, (void*) "333")); assert_se(set_put(m, (void*) "333") == 1); assert_se(set_put(m, (void*) "333") == 0); assert_se(set_put(m, (void*) "22") == 0); } int main(int argc, const char *argv[]) { test_set_steal_first(); test_set_put(); return 0; } systemd-229/src/test/test-sigbus.c000066400000000000000000000035321265713322000172470ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "fd-util.h" #include "sigbus.h" #include "util.h" int main(int argc, char *argv[]) { _cleanup_close_ int fd = -1; char template[] = "/tmp/sigbus-test-XXXXXX"; void *addr = NULL; uint8_t *p; sigbus_install(); assert_se(sigbus_pop(&addr) == 0); assert_se((fd = mkostemp(template, O_RDWR|O_CREAT|O_EXCL)) >= 0); assert_se(unlink(template) >= 0); assert_se(fallocate(fd, 0, 0, page_size() * 8) >= 0); p = mmap(NULL, page_size() * 16, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); assert_se(p != MAP_FAILED); assert_se(sigbus_pop(&addr) == 0); p[0] = 0xFF; assert_se(sigbus_pop(&addr) == 0); p[page_size()] = 0xFF; assert_se(sigbus_pop(&addr) == 0); p[page_size()*8] = 0xFF; p[page_size()*8+1] = 0xFF; p[page_size()*10] = 0xFF; assert_se(sigbus_pop(&addr) > 0); assert_se(addr == p + page_size() * 8); assert_se(sigbus_pop(&addr) > 0); assert_se(addr == p + page_size() * 10); assert_se(sigbus_pop(&addr) == 0); sigbus_reset(); } systemd-229/src/test/test-signal-util.c000066400000000000000000000031021265713322000201740ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2016 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "signal-util.h" static void test_block_signals(void) { sigset_t ss; assert_se(sigprocmask(0, NULL, &ss) >= 0); assert_se(sigismember(&ss, SIGUSR1) == 0); assert_se(sigismember(&ss, SIGALRM) == 0); assert_se(sigismember(&ss, SIGVTALRM) == 0); { BLOCK_SIGNALS(SIGUSR1, SIGVTALRM); assert_se(sigprocmask(0, NULL, &ss) >= 0); assert_se(sigismember(&ss, SIGUSR1) == 1); assert_se(sigismember(&ss, SIGALRM) == 0); assert_se(sigismember(&ss, SIGVTALRM) == 1); } assert_se(sigprocmask(0, NULL, &ss) >= 0); assert_se(sigismember(&ss, SIGUSR1) == 0); assert_se(sigismember(&ss, SIGALRM) == 0); assert_se(sigismember(&ss, SIGVTALRM) == 0); } int main(int argc, char *argv[]) { test_block_signals(); } systemd-229/src/test/test-siphash24.c000066400000000000000000000064151265713322000175630ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "siphash24.h" #include "util.h" #define ITERATIONS 10000000ULL static int do_test(const uint8_t *in, size_t len, const uint8_t *key) { struct siphash state = {}; uint64_t out = 0; unsigned i, j; out = siphash24(in, len, key); assert_se(out == 0xa129ca6149be45e5); /* verify the internal state as given in the above paper */ siphash24_init(&state, key); assert_se(state.v0 == 0x7469686173716475); assert_se(state.v1 == 0x6b617f6d656e6665); assert_se(state.v2 == 0x6b7f62616d677361); assert_se(state.v3 == 0x7b6b696e727e6c7b); siphash24_compress(in, len, &state); assert_se(state.v0 == 0x4a017198de0a59e0); assert_se(state.v1 == 0x0d52f6f62a4f59a4); assert_se(state.v2 == 0x634cb3577b01fd3d); assert_se(state.v3 == 0xa5224d6f55c7d9c8); out = siphash24_finalize(&state); assert_se(out == 0xa129ca6149be45e5); assert_se(state.v0 == 0xf6bcd53893fecff1); assert_se(state.v1 == 0x54b9964c7ea0d937); assert_se(state.v2 == 0x1b38329c099bb55a); assert_se(state.v3 == 0x1814bb89ad7be679); /* verify that decomposing the input in three chunks gives the same result */ for (i = 0; i < len; i++) { for (j = i; j < len; j++) { siphash24_init(&state, key); siphash24_compress(in, i, &state); siphash24_compress(&in[i], j - i, &state); siphash24_compress(&in[j], len - j, &state); out = siphash24_finalize(&state); assert_se(out == 0xa129ca6149be45e5); } } return 0; } /* see https://131002.net/siphash/siphash.pdf, Appendix A */ int main(int argc, char *argv[]) { const uint8_t in[15] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e }; const uint8_t key[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; uint8_t in_buf[20]; /* Test with same input but different alignments. */ memcpy(in_buf, in, sizeof(in)); do_test(in_buf, sizeof(in), key); memcpy(in_buf + 1, in, sizeof(in)); do_test(in_buf + 1, sizeof(in), key); memcpy(in_buf + 2, in, sizeof(in)); do_test(in_buf + 2, sizeof(in), key); memcpy(in_buf + 4, in, sizeof(in)); do_test(in_buf + 4, sizeof(in), key); } systemd-229/src/test/test-sleep.c000066400000000000000000000047671265713322000170760ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "log.h" #include "sleep-config.h" #include "strv.h" #include "util.h" static void test_sleep(void) { _cleanup_strv_free_ char **standby = strv_new("standby", NULL), **mem = strv_new("mem", NULL), **disk = strv_new("disk", NULL), **suspend = strv_new("suspend", NULL), **reboot = strv_new("reboot", NULL), **platform = strv_new("platform", NULL), **shutdown = strv_new("shutdown", NULL), **freez = strv_new("freeze", NULL); log_info("Standby configured: %s", yes_no(can_sleep_state(standby) > 0)); log_info("Suspend configured: %s", yes_no(can_sleep_state(mem) > 0)); log_info("Hibernate configured: %s", yes_no(can_sleep_state(disk) > 0)); log_info("Hibernate+Suspend (Hybrid-Sleep) configured: %s", yes_no(can_sleep_disk(suspend) > 0)); log_info("Hibernate+Reboot configured: %s", yes_no(can_sleep_disk(reboot) > 0)); log_info("Hibernate+Platform configured: %s", yes_no(can_sleep_disk(platform) > 0)); log_info("Hibernate+Shutdown configured: %s", yes_no(can_sleep_disk(shutdown) > 0)); log_info("Freeze configured: %s", yes_no(can_sleep_state(freez) > 0)); log_info("Suspend configured and possible: %s", yes_no(can_sleep("suspend") > 0)); log_info("Hibernation configured and possible: %s", yes_no(can_sleep("hibernate") > 0)); log_info("Hybrid-sleep configured and possible: %s", yes_no(can_sleep("hybrid-sleep") > 0)); } int main(int argc, char* argv[]) { log_parse_environment(); log_open(); if (getuid() != 0) log_warning("This program is unlikely to work for unprivileged users"); test_sleep(); return 0; } systemd-229/src/test/test-socket-util.c000066400000000000000000000337211265713322000202210ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2014 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "async.h" #include "fd-util.h" #include "in-addr-util.h" #include "log.h" #include "macro.h" #include "socket-util.h" #include "string-util.h" #include "util.h" static void test_socket_address_parse(void) { SocketAddress a; assert_se(socket_address_parse(&a, "junk") < 0); assert_se(socket_address_parse(&a, "192.168.1.1") < 0); assert_se(socket_address_parse(&a, ".168.1.1") < 0); assert_se(socket_address_parse(&a, "989.168.1.1") < 0); assert_se(socket_address_parse(&a, "192.168.1.1:65536") < 0); assert_se(socket_address_parse(&a, "192.168.1.1:0") < 0); assert_se(socket_address_parse(&a, "0") < 0); assert_se(socket_address_parse(&a, "65536") < 0); assert_se(socket_address_parse(&a, "65535") >= 0); /* The checks below will pass even if ipv6 is disabled in * kernel. The underlying glibc's inet_pton() is just a string * parser and doesn't make any syscalls. */ assert_se(socket_address_parse(&a, "[::1]") < 0); assert_se(socket_address_parse(&a, "[::1]8888") < 0); assert_se(socket_address_parse(&a, "::1") < 0); assert_se(socket_address_parse(&a, "[::1]:0") < 0); assert_se(socket_address_parse(&a, "[::1]:65536") < 0); assert_se(socket_address_parse(&a, "[a:b:1]:8888") < 0); assert_se(socket_address_parse(&a, "8888") >= 0); assert_se(a.sockaddr.sa.sa_family == (socket_ipv6_is_supported() ? AF_INET6 : AF_INET)); assert_se(socket_address_parse(&a, "[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8888") >= 0); assert_se(a.sockaddr.sa.sa_family == AF_INET6); assert_se(socket_address_parse(&a, "[::1]:8888") >= 0); assert_se(a.sockaddr.sa.sa_family == AF_INET6); assert_se(socket_address_parse(&a, "192.168.1.254:8888") >= 0); assert_se(a.sockaddr.sa.sa_family == AF_INET); assert_se(socket_address_parse(&a, "/foo/bar") >= 0); assert_se(a.sockaddr.sa.sa_family == AF_UNIX); assert_se(socket_address_parse(&a, "@abstract") >= 0); assert_se(a.sockaddr.sa.sa_family == AF_UNIX); } static void test_socket_address_parse_netlink(void) { SocketAddress a; assert_se(socket_address_parse_netlink(&a, "junk") < 0); assert_se(socket_address_parse_netlink(&a, "") < 0); assert_se(socket_address_parse_netlink(&a, "route") >= 0); assert_se(socket_address_parse_netlink(&a, "route 10") >= 0); assert_se(a.sockaddr.sa.sa_family == AF_NETLINK); assert_se(a.protocol == NETLINK_ROUTE); } static void test_socket_address_equal(void) { SocketAddress a; SocketAddress b; assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); assert_se(socket_address_parse(&b, "192.168.1.1:888") >= 0); assert_se(!socket_address_equal(&a, &b)); assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); assert_se(socket_address_parse(&b, "192.16.1.1:8888") >= 0); assert_se(!socket_address_equal(&a, &b)); assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); assert_se(socket_address_parse(&b, "8888") >= 0); assert_se(!socket_address_equal(&a, &b)); assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); assert_se(socket_address_parse(&b, "/foo/bar/") >= 0); assert_se(!socket_address_equal(&a, &b)); assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); assert_se(socket_address_parse(&b, "192.168.1.1:8888") >= 0); assert_se(socket_address_equal(&a, &b)); assert_se(socket_address_parse(&a, "/foo/bar") >= 0); assert_se(socket_address_parse(&b, "/foo/bar") >= 0); assert_se(socket_address_equal(&a, &b)); assert_se(socket_address_parse(&a, "[::1]:8888") >= 0); assert_se(socket_address_parse(&b, "[::1]:8888") >= 0); assert_se(socket_address_equal(&a, &b)); assert_se(socket_address_parse(&a, "@abstract") >= 0); assert_se(socket_address_parse(&b, "@abstract") >= 0); assert_se(socket_address_equal(&a, &b)); assert_se(socket_address_parse_netlink(&a, "firewall") >= 0); assert_se(socket_address_parse_netlink(&b, "firewall") >= 0); assert_se(socket_address_equal(&a, &b)); } static void test_socket_address_get_path(void) { SocketAddress a; assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); assert_se(!socket_address_get_path(&a)); assert_se(socket_address_parse(&a, "@abstract") >= 0); assert_se(!socket_address_get_path(&a)); assert_se(socket_address_parse(&a, "[::1]:8888") >= 0); assert_se(!socket_address_get_path(&a)); assert_se(socket_address_parse(&a, "/foo/bar") >= 0); assert_se(streq(socket_address_get_path(&a), "/foo/bar")); } static void test_socket_address_is(void) { SocketAddress a; assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); assert_se(socket_address_is(&a, "192.168.1.1:8888", SOCK_STREAM)); assert_se(!socket_address_is(&a, "route", SOCK_STREAM)); assert_se(!socket_address_is(&a, "192.168.1.1:8888", SOCK_RAW)); } static void test_socket_address_is_netlink(void) { SocketAddress a; assert_se(socket_address_parse_netlink(&a, "route 10") >= 0); assert_se(socket_address_is_netlink(&a, "route 10")); assert_se(!socket_address_is_netlink(&a, "192.168.1.1:8888")); assert_se(!socket_address_is_netlink(&a, "route 1")); } static void test_in_addr_is_null(void) { union in_addr_union i = {}; assert_se(in_addr_is_null(AF_INET, &i) == true); assert_se(in_addr_is_null(AF_INET6, &i) == true); i.in.s_addr = 0x1000000; assert_se(in_addr_is_null(AF_INET, &i) == false); assert_se(in_addr_is_null(AF_INET6, &i) == false); assert_se(in_addr_is_null(-1, &i) == -EAFNOSUPPORT); } static void test_in_addr_prefix_intersect_one(unsigned f, const char *a, unsigned apl, const char *b, unsigned bpl, int result) { union in_addr_union ua, ub; assert_se(in_addr_from_string(f, a, &ua) >= 0); assert_se(in_addr_from_string(f, b, &ub) >= 0); assert_se(in_addr_prefix_intersect(f, &ua, apl, &ub, bpl) == result); } static void test_in_addr_prefix_intersect(void) { test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 32, "255.255.255.254", 32, 0); test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 0, "255.255.255.255", 32, 1); test_in_addr_prefix_intersect_one(AF_INET, "0.0.0.0", 0, "47.11.8.15", 32, 1); test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.1", 24, 1); test_in_addr_prefix_intersect_one(AF_INET, "2.2.2.2", 24, "1.1.1.1", 24, 0); test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 25, 1); test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 26, 1); test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.127", 25, 1); test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.255", 25, 0); test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", 128, 0); test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1); test_in_addr_prefix_intersect_one(AF_INET6, "::", 0, "beef:beef:beef:beef:beef:beef:beef:beef", 128, 1); test_in_addr_prefix_intersect_one(AF_INET6, "1::2", 64, "1::2", 64, 1); test_in_addr_prefix_intersect_one(AF_INET6, "2::2", 64, "1::2", 64, 0); test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 121, 1); test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 122, 1); test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::007f", 121, 1); test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::00ff", 121, 0); } static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) { union in_addr_union ubefore, uafter, t; assert_se(in_addr_from_string(f, before, &ubefore) >= 0); t = ubefore; assert_se((in_addr_prefix_next(f, &t, pl) > 0) == !!after); if (after) { assert_se(in_addr_from_string(f, after, &uafter) >= 0); assert_se(in_addr_equal(f, &t, &uafter) > 0); } } static void test_in_addr_prefix_next(void) { test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0"); test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0"); test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0"); test_in_addr_prefix_next_one(AF_INET, "0.0.0.0", 32, "0.0.0.1"); test_in_addr_prefix_next_one(AF_INET, "255.255.255.255", 32, NULL); test_in_addr_prefix_next_one(AF_INET, "255.255.255.0", 24, NULL); test_in_addr_prefix_next_one(AF_INET6, "4400::", 128, "4400::0001"); test_in_addr_prefix_next_one(AF_INET6, "4400::", 120, "4400::0100"); test_in_addr_prefix_next_one(AF_INET6, "4400::", 127, "4400::0002"); test_in_addr_prefix_next_one(AF_INET6, "4400::", 8, "4500::"); test_in_addr_prefix_next_one(AF_INET6, "4400::", 7, "4600::"); test_in_addr_prefix_next_one(AF_INET6, "::", 128, "::1"); test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, NULL); test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00", 120, NULL); } static void test_in_addr_to_string_one(int f, const char *addr) { union in_addr_union ua; _cleanup_free_ char *r = NULL; assert_se(in_addr_from_string(f, addr, &ua) >= 0); assert_se(in_addr_to_string(f, &ua, &r) >= 0); printf("test_in_addr_to_string_one: %s == %s\n", addr, r); assert_se(streq(addr, r)); } static void test_in_addr_to_string(void) { test_in_addr_to_string_one(AF_INET, "192.168.0.1"); test_in_addr_to_string_one(AF_INET, "10.11.12.13"); test_in_addr_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); test_in_addr_to_string_one(AF_INET6, "::1"); test_in_addr_to_string_one(AF_INET6, "fe80::"); } static void *connect_thread(void *arg) { union sockaddr_union *sa = arg; _cleanup_close_ int fd = -1; fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); assert_se(fd >= 0); assert_se(connect(fd, &sa->sa, sizeof(sa->in)) == 0); return NULL; } static void test_nameinfo_pretty(void) { _cleanup_free_ char *stdin_name = NULL, *localhost = NULL; union sockaddr_union s = { .in.sin_family = AF_INET, .in.sin_port = 0, .in.sin_addr.s_addr = htonl(INADDR_ANY), }; int r; union sockaddr_union c = {}; socklen_t slen = sizeof(c.in), clen = sizeof(c.in); _cleanup_close_ int sfd = -1, cfd = -1; r = getnameinfo_pretty(STDIN_FILENO, &stdin_name); log_info_errno(r, "No connection remote: %m"); assert_se(r < 0); sfd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0); assert_se(sfd >= 0); assert_se(bind(sfd, &s.sa, sizeof(s.in)) == 0); /* find out the port number */ assert_se(getsockname(sfd, &s.sa, &slen) == 0); assert_se(listen(sfd, 1) == 0); assert_se(asynchronous_job(connect_thread, &s) == 0); log_debug("Accepting new connection on fd:%d", sfd); cfd = accept4(sfd, &c.sa, &clen, SOCK_CLOEXEC); assert_se(cfd >= 0); r = getnameinfo_pretty(cfd, &localhost); log_info("Connection from %s", localhost); assert_se(r == 0); } static void test_sockaddr_equal(void) { union sockaddr_union a = { .in.sin_family = AF_INET, .in.sin_port = 0, .in.sin_addr.s_addr = htonl(INADDR_ANY), }; union sockaddr_union b = { .in.sin_family = AF_INET, .in.sin_port = 0, .in.sin_addr.s_addr = htonl(INADDR_ANY), }; union sockaddr_union c = { .in.sin_family = AF_INET, .in.sin_port = 0, .in.sin_addr.s_addr = htonl(1234), }; union sockaddr_union d = { .in6.sin6_family = AF_INET6, .in6.sin6_port = 0, .in6.sin6_addr = IN6ADDR_ANY_INIT, }; assert_se(sockaddr_equal(&a, &a)); assert_se(sockaddr_equal(&a, &b)); assert_se(sockaddr_equal(&d, &d)); assert_se(!sockaddr_equal(&a, &c)); assert_se(!sockaddr_equal(&b, &c)); } int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); test_socket_address_parse(); test_socket_address_parse_netlink(); test_socket_address_equal(); test_socket_address_get_path(); test_socket_address_is(); test_socket_address_is_netlink(); test_in_addr_is_null(); test_in_addr_prefix_intersect(); test_in_addr_prefix_next(); test_in_addr_to_string(); test_nameinfo_pretty(); test_sockaddr_equal(); return 0; } systemd-229/src/test/test-strbuf.c000066400000000000000000000056401265713322000172620ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Thomas H.P. Andersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "strbuf.h" #include "string-util.h" #include "strv.h" #include "util.h" static ssize_t add_string(struct strbuf *sb, const char *s) { return strbuf_add_string(sb, s, strlen(s)); } static void test_strbuf(void) { struct strbuf *sb; _cleanup_strv_free_ char **l; ssize_t a, b, c, d, e, f, g; sb = strbuf_new(); a = add_string(sb, "waldo"); b = add_string(sb, "foo"); c = add_string(sb, "bar"); d = add_string(sb, "waldo"); /* duplicate */ e = add_string(sb, "aldo"); /* duplicate */ f = add_string(sb, "do"); /* duplicate */ g = add_string(sb, "waldorf"); /* not a duplicate: matches from tail */ /* check the content of the buffer directly */ l = strv_parse_nulstr(sb->buf, sb->len); assert_se(streq(l[0], "")); /* root */ assert_se(streq(l[1], "waldo")); assert_se(streq(l[2], "foo")); assert_se(streq(l[3], "bar")); assert_se(streq(l[4], "waldorf")); assert_se(sb->nodes_count == 5); /* root + 4 non-duplicates */ assert_se(sb->dedup_count == 3); assert_se(sb->in_count == 7); assert_se(sb->in_len == 29); /* length of all strings added */ assert_se(sb->dedup_len == 11); /* length of all strings duplicated */ assert_se(sb->len == 23); /* buffer length: in - dedup + \0 for each node */ /* check the returned offsets and the respective content in the buffer */ assert_se(a == 1); assert_se(b == 7); assert_se(c == 11); assert_se(d == 1); assert_se(e == 2); assert_se(f == 4); assert_se(g == 15); assert_se(streq(sb->buf + a, "waldo")); assert_se(streq(sb->buf + b, "foo")); assert_se(streq(sb->buf + c, "bar")); assert_se(streq(sb->buf + d, "waldo")); assert_se(streq(sb->buf + e, "aldo")); assert_se(streq(sb->buf + f, "do")); assert_se(streq(sb->buf + g, "waldorf")); strbuf_complete(sb); assert_se(sb->root == NULL); strbuf_cleanup(sb); } int main(int argc, const char *argv[]) { test_strbuf(); return 0; } systemd-229/src/test/test-string-util.c000066400000000000000000000076721265713322000202450ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "string-util.h" static void test_string_erase(void) { char *x; x = strdupa(""); assert_se(streq(string_erase(x), "")); x = strdupa("1"); assert_se(streq(string_erase(x), "x")); x = strdupa("12"); assert_se(streq(string_erase(x), "xx")); x = strdupa("123"); assert_se(streq(string_erase(x), "xxx")); x = strdupa("1234"); assert_se(streq(string_erase(x), "xxxx")); x = strdupa("12345"); assert_se(streq(string_erase(x), "xxxxx")); x = strdupa("123456"); assert_se(streq(string_erase(x), "xxxxxx")); x = strdupa("1234567"); assert_se(streq(string_erase(x), "xxxxxxx")); x = strdupa("12345678"); assert_se(streq(string_erase(x), "xxxxxxxx")); x = strdupa("123456789"); assert_se(streq(string_erase(x), "xxxxxxxxx")); } static void test_ascii_strcasecmp_n(void) { assert_se(ascii_strcasecmp_n("", "", 0) == 0); assert_se(ascii_strcasecmp_n("", "", 1) == 0); assert_se(ascii_strcasecmp_n("", "a", 1) < 0); assert_se(ascii_strcasecmp_n("", "a", 2) < 0); assert_se(ascii_strcasecmp_n("a", "", 1) > 0); assert_se(ascii_strcasecmp_n("a", "", 2) > 0); assert_se(ascii_strcasecmp_n("a", "a", 1) == 0); assert_se(ascii_strcasecmp_n("a", "a", 2) == 0); assert_se(ascii_strcasecmp_n("a", "b", 1) < 0); assert_se(ascii_strcasecmp_n("a", "b", 2) < 0); assert_se(ascii_strcasecmp_n("b", "a", 1) > 0); assert_se(ascii_strcasecmp_n("b", "a", 2) > 0); assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxYxxxx", 9) == 0); assert_se(ascii_strcasecmp_n("xxxxxxxxx", "xxxxyxxxx", 9) < 0); assert_se(ascii_strcasecmp_n("xxxxXxxxx", "xxxxyxxxx", 9) < 0); assert_se(ascii_strcasecmp_n("xxxxxxxxx", "xxxxYxxxx", 9) < 0); assert_se(ascii_strcasecmp_n("xxxxXxxxx", "xxxxYxxxx", 9) < 0); assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxYxxxx", 9) == 0); assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxxxxxx", 9) > 0); assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxXxxxx", 9) > 0); assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxxxxxx", 9) > 0); assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxXxxxx", 9) > 0); } static void test_ascii_strcasecmp_nn(void) { assert_se(ascii_strcasecmp_nn("", 0, "", 0) == 0); assert_se(ascii_strcasecmp_nn("", 0, "", 1) < 0); assert_se(ascii_strcasecmp_nn("", 1, "", 0) > 0); assert_se(ascii_strcasecmp_nn("", 1, "", 1) == 0); assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaAa", 4) == 0); assert_se(ascii_strcasecmp_nn("aaa", 3, "aaAa", 4) < 0); assert_se(ascii_strcasecmp_nn("aaa", 4, "aaAa", 4) < 0); assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaA", 3) > 0); assert_se(ascii_strcasecmp_nn("aaaa", 4, "AAA", 4) > 0); assert_se(ascii_strcasecmp_nn("aaaa", 4, "bbbb", 4) < 0); assert_se(ascii_strcasecmp_nn("aaAA", 4, "BBbb", 4) < 0); assert_se(ascii_strcasecmp_nn("BBbb", 4, "aaaa", 4) > 0); } int main(int argc, char *argv[]) { test_string_erase(); test_ascii_strcasecmp_n(); test_ascii_strcasecmp_nn(); return 0; } systemd-229/src/test/test-strip-tab-ansi.c000066400000000000000000000034051265713322000206070ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "string-util.h" #include "terminal-util.h" #include "util.h" int main(int argc, char *argv[]) { char *p; assert_se(p = strdup("\tFoobar\tbar\twaldo\t")); assert_se(strip_tab_ansi(&p, NULL)); fprintf(stdout, "<%s>\n", p); assert_se(streq(p, " Foobar bar waldo ")); free(p); assert_se(p = strdup(ANSI_HIGHLIGHT "Hello" ANSI_NORMAL ANSI_HIGHLIGHT_RED " world!" ANSI_NORMAL)); assert_se(strip_tab_ansi(&p, NULL)); fprintf(stdout, "<%s>\n", p); assert_se(streq(p, "Hello world!")); free(p); assert_se(p = strdup("\x1B[\x1B[\t\x1B[" ANSI_HIGHLIGHT "\x1B[" "Hello" ANSI_NORMAL ANSI_HIGHLIGHT_RED " world!" ANSI_NORMAL)); assert_se(strip_tab_ansi(&p, NULL)); assert_se(streq(p, "\x1B[\x1B[ \x1B[\x1B[Hello world!")); free(p); assert_se(p = strdup("\x1B[waldo")); assert_se(strip_tab_ansi(&p, NULL)); assert_se(streq(p, "\x1B[waldo")); free(p); return 0; } systemd-229/src/test/test-strv.c000066400000000000000000000526131265713322000167550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Thomas H.P. Andersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "specifier.h" #include "string-util.h" #include "strv.h" #include "util.h" static void test_specifier_printf(void) { static const Specifier table[] = { { 'a', specifier_string, (char*) "AAAA" }, { 'b', specifier_string, (char*) "BBBB" }, { 'm', specifier_machine_id, NULL }, { 'B', specifier_boot_id, NULL }, { 'H', specifier_host_name, NULL }, { 'v', specifier_kernel_release, NULL }, {} }; _cleanup_free_ char *w = NULL; int r; r = specifier_printf("xxx a=%a b=%b yyy", table, NULL, &w); assert_se(r >= 0); assert_se(w); puts(w); assert_se(streq(w, "xxx a=AAAA b=BBBB yyy")); free(w); r = specifier_printf("machine=%m, boot=%B, host=%H, version=%v", table, NULL, &w); assert_se(r >= 0); assert_se(w); puts(w); } static const char* const input_table_multiple[] = { "one", "two", "three", NULL, }; static const char* const input_table_one[] = { "one", NULL, }; static const char* const input_table_none[] = { NULL, }; static const char* const input_table_quotes[] = { "\"", "'", "\"\"", "\\", "\\\\", NULL, }; #define QUOTES_STRING \ "\"\\\"\" " \ "\"\\\'\" " \ "\"\\\"\\\"\" " \ "\"\\\\\" " \ "\"\\\\\\\\\"" static const char * const input_table_spaces[] = { " ", "' '", "\" ", " \"", " \\\\ ", NULL, }; #define SPACES_STRING \ "\" \" " \ "\"\\' \\'\" " \ "\"\\\" \" " \ "\" \\\"\" " \ "\" \\\\\\\\ \"" static void test_strv_find(void) { assert_se(strv_find((char **)input_table_multiple, "three")); assert_se(!strv_find((char **)input_table_multiple, "four")); } static void test_strv_find_prefix(void) { assert_se(strv_find_prefix((char **)input_table_multiple, "o")); assert_se(strv_find_prefix((char **)input_table_multiple, "one")); assert_se(strv_find_prefix((char **)input_table_multiple, "")); assert_se(!strv_find_prefix((char **)input_table_multiple, "xxx")); assert_se(!strv_find_prefix((char **)input_table_multiple, "onee")); } static void test_strv_find_startswith(void) { char *r; r = strv_find_startswith((char **)input_table_multiple, "o"); assert_se(r && streq(r, "ne")); r = strv_find_startswith((char **)input_table_multiple, "one"); assert_se(r && streq(r, "")); r = strv_find_startswith((char **)input_table_multiple, ""); assert_se(r && streq(r, "one")); assert_se(!strv_find_startswith((char **)input_table_multiple, "xxx")); assert_se(!strv_find_startswith((char **)input_table_multiple, "onee")); } static void test_strv_join(void) { _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL; p = strv_join((char **)input_table_multiple, ", "); assert_se(p); assert_se(streq(p, "one, two, three")); q = strv_join((char **)input_table_multiple, ";"); assert_se(q); assert_se(streq(q, "one;two;three")); r = strv_join((char **)input_table_multiple, NULL); assert_se(r); assert_se(streq(r, "one two three")); s = strv_join((char **)input_table_one, ", "); assert_se(s); assert_se(streq(s, "one")); t = strv_join((char **)input_table_none, ", "); assert_se(t); assert_se(streq(t, "")); } static void test_strv_quote_unquote(const char* const *split, const char *quoted) { _cleanup_free_ char *p; _cleanup_strv_free_ char **s = NULL; char **t; int r; p = strv_join_quoted((char **)split); assert_se(p); printf("-%s- --- -%s-\n", p, quoted); /* fprintf deals with NULL, puts does not */ assert_se(p); assert_se(streq(p, quoted)); r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_QUOTES); assert_se(r == (int) strv_length(s)); assert_se(s); STRV_FOREACH(t, s) { assert_se(*t); assert_se(streq(*t, *split)); split++; } } static void test_strv_unquote(const char *quoted, char **list) { _cleanup_strv_free_ char **s; _cleanup_free_ char *j; unsigned i = 0; char **t; int r; r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_QUOTES); assert_se(r == (int) strv_length(list)); assert_se(s); j = strv_join(s, " | "); assert_se(j); puts(j); STRV_FOREACH(t, s) assert_se(streq(list[i++], *t)); assert_se(list[i] == NULL); } static void test_invalid_unquote(const char *quoted) { char **s = NULL; int r; r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_QUOTES); assert_se(s == NULL); assert_se(r == -EINVAL); } static void test_strv_split(void) { char **s; unsigned i = 0; _cleanup_strv_free_ char **l = NULL; const char str[] = "one,two,three"; l = strv_split(str, ","); assert_se(l); STRV_FOREACH(s, l) { assert_se(streq(*s, input_table_multiple[i++])); } } static void test_strv_split_extract(void) { _cleanup_strv_free_ char **l = NULL; const char *str = ":foo\\:bar::waldo:"; int r; r = strv_split_extract(&l, str, ":", EXTRACT_DONT_COALESCE_SEPARATORS); assert_se(r == (int) strv_length(l)); assert_se(streq_ptr(l[0], "")); assert_se(streq_ptr(l[1], "foo:bar")); assert_se(streq_ptr(l[2], "")); assert_se(streq_ptr(l[3], "waldo")); assert_se(streq_ptr(l[4], "")); assert_se(streq_ptr(l[5], NULL)); } static void test_strv_split_newlines(void) { unsigned i = 0; char **s; _cleanup_strv_free_ char **l = NULL; const char str[] = "one\ntwo\nthree"; l = strv_split_newlines(str); assert_se(l); STRV_FOREACH(s, l) { assert_se(streq(*s, input_table_multiple[i++])); } } static void test_strv_split_nulstr(void) { _cleanup_strv_free_ char **l = NULL; const char nulstr[] = "str0\0str1\0str2\0str3\0"; l = strv_split_nulstr (nulstr); assert_se(l); assert_se(streq(l[0], "str0")); assert_se(streq(l[1], "str1")); assert_se(streq(l[2], "str2")); assert_se(streq(l[3], "str3")); } static void test_strv_parse_nulstr(void) { _cleanup_strv_free_ char **l = NULL; const char nulstr[] = "fuck\0fuck2\0fuck3\0\0fuck5\0\0xxx"; l = strv_parse_nulstr(nulstr, sizeof(nulstr)-1); assert_se(l); puts("Parse nulstr:"); strv_print(l); assert_se(streq(l[0], "fuck")); assert_se(streq(l[1], "fuck2")); assert_se(streq(l[2], "fuck3")); assert_se(streq(l[3], "")); assert_se(streq(l[4], "fuck5")); assert_se(streq(l[5], "")); assert_se(streq(l[6], "xxx")); } static void test_strv_overlap(void) { const char * const input_table[] = { "one", "two", "three", NULL }; const char * const input_table_overlap[] = { "two", NULL }; const char * const input_table_unique[] = { "four", "five", "six", NULL }; assert_se(strv_overlap((char **)input_table, (char**)input_table_overlap)); assert_se(!strv_overlap((char **)input_table, (char**)input_table_unique)); } static void test_strv_sort(void) { const char* input_table[] = { "durian", "apple", "citrus", "CAPITAL LETTERS FIRST", "banana", NULL }; strv_sort((char **)input_table); assert_se(streq(input_table[0], "CAPITAL LETTERS FIRST")); assert_se(streq(input_table[1], "apple")); assert_se(streq(input_table[2], "banana")); assert_se(streq(input_table[3], "citrus")); assert_se(streq(input_table[4], "durian")); } static void test_strv_extend_strv_concat(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL; a = strv_new("without", "suffix", NULL); b = strv_new("with", "suffix", NULL); assert_se(a); assert_se(b); assert_se(strv_extend_strv_concat(&a, b, "_suffix") >= 0); assert_se(streq(a[0], "without")); assert_se(streq(a[1], "suffix")); assert_se(streq(a[2], "with_suffix")); assert_se(streq(a[3], "suffix_suffix")); } static void test_strv_extend_strv(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL; a = strv_new("abc", "def", "ghi", NULL); b = strv_new("jkl", "mno", "abc", "pqr", NULL); assert_se(a); assert_se(b); assert_se(strv_extend_strv(&a, b, true) == 3); assert_se(streq(a[0], "abc")); assert_se(streq(a[1], "def")); assert_se(streq(a[2], "ghi")); assert_se(streq(a[3], "jkl")); assert_se(streq(a[4], "mno")); assert_se(streq(a[5], "pqr")); assert_se(strv_length(a) == 6); } static void test_strv_extend(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL; a = strv_new("test", "test1", NULL); assert_se(a); assert_se(strv_extend(&a, "test2") >= 0); assert_se(strv_extend(&b, "test3") >= 0); assert_se(streq(a[0], "test")); assert_se(streq(a[1], "test1")); assert_se(streq(a[2], "test2")); assert_se(streq(b[0], "test3")); } static void test_strv_extendf(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL; a = strv_new("test", "test1", NULL); assert_se(a); assert_se(strv_extendf(&a, "test2 %s %d %s", "foo", 128, "bar") >= 0); assert_se(strv_extendf(&b, "test3 %s %s %d", "bar", "foo", 128) >= 0); assert_se(streq(a[0], "test")); assert_se(streq(a[1], "test1")); assert_se(streq(a[2], "test2 foo 128 bar")); assert_se(streq(b[0], "test3 bar foo 128")); } static void test_strv_foreach(void) { _cleanup_strv_free_ char **a; unsigned i = 0; char **check; a = strv_new("one", "two", "three", NULL); assert_se(a); STRV_FOREACH(check, a) { assert_se(streq(*check, input_table_multiple[i++])); } } static void test_strv_foreach_backwards(void) { _cleanup_strv_free_ char **a; unsigned i = 2; char **check; a = strv_new("one", "two", "three", NULL); assert_se(a); STRV_FOREACH_BACKWARDS(check, a) { assert_se(streq_ptr(*check, input_table_multiple[i--])); } } static void test_strv_foreach_pair(void) { _cleanup_strv_free_ char **a = NULL; char **x, **y; a = strv_new("pair_one", "pair_one", "pair_two", "pair_two", "pair_three", "pair_three", NULL); STRV_FOREACH_PAIR(x, y, a) { assert_se(streq(*x, *y)); } } static void test_strv_from_stdarg_alloca_one(char **l, const char *first, ...) { char **j; unsigned i; j = strv_from_stdarg_alloca(first); for (i = 0;; i++) { assert_se(streq_ptr(l[i], j[i])); if (!l[i]) break; } } static void test_strv_from_stdarg_alloca(void) { test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL); test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL); test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY, NULL); } static void test_strv_push_prepend(void) { _cleanup_strv_free_ char **a = NULL; a = strv_new("foo", "bar", "three", NULL); assert_se(strv_push_prepend(&a, strdup("first")) >= 0); assert_se(streq(a[0], "first")); assert_se(streq(a[1], "foo")); assert_se(streq(a[2], "bar")); assert_se(streq(a[3], "three")); assert_se(!a[4]); assert_se(strv_consume_prepend(&a, strdup("first2")) >= 0); assert_se(streq(a[0], "first2")); assert_se(streq(a[1], "first")); assert_se(streq(a[2], "foo")); assert_se(streq(a[3], "bar")); assert_se(streq(a[4], "three")); assert_se(!a[5]); } static void test_strv_push(void) { _cleanup_strv_free_ char **a = NULL; char *i, *j; assert_se(i = strdup("foo")); assert_se(strv_push(&a, i) >= 0); assert_se(i = strdup("a")); assert_se(j = strdup("b")); assert_se(strv_push_pair(&a, i, j) >= 0); assert_se(streq_ptr(a[0], "foo")); assert_se(streq_ptr(a[1], "a")); assert_se(streq_ptr(a[2], "b")); assert_se(streq_ptr(a[3], NULL)); } static void test_strv_equal(void) { _cleanup_strv_free_ char **a = NULL; _cleanup_strv_free_ char **b = NULL; _cleanup_strv_free_ char **c = NULL; a = strv_new("one", "two", "three", NULL); assert_se(a); b = strv_new("one", "two", "three", NULL); assert_se(a); c = strv_new("one", "two", "three", "four", NULL); assert_se(a); assert_se(strv_equal(a, a)); assert_se(strv_equal(a, b)); assert_se(strv_equal(NULL, NULL)); assert_se(!strv_equal(a, c)); assert_se(!strv_equal(b, c)); assert_se(!strv_equal(b, NULL)); } static void test_strv_is_uniq(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL; a = strv_new(NULL, NULL); assert_se(a); assert_se(strv_is_uniq(a)); b = strv_new("foo", NULL); assert_se(b); assert_se(strv_is_uniq(b)); c = strv_new("foo", "bar", NULL); assert_se(c); assert_se(strv_is_uniq(c)); d = strv_new("foo", "bar", "waldo", "bar", "piep", NULL); assert_se(d); assert_se(!strv_is_uniq(d)); } static void test_strv_reverse(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL; a = strv_new(NULL, NULL); assert_se(a); strv_reverse(a); assert_se(strv_isempty(a)); b = strv_new("foo", NULL); assert_se(b); strv_reverse(b); assert_se(streq_ptr(b[0], "foo")); assert_se(streq_ptr(b[1], NULL)); c = strv_new("foo", "bar", NULL); assert_se(c); strv_reverse(c); assert_se(streq_ptr(c[0], "bar")); assert_se(streq_ptr(c[1], "foo")); assert_se(streq_ptr(c[2], NULL)); d = strv_new("foo", "bar", "waldo", NULL); assert_se(d); strv_reverse(d); assert_se(streq_ptr(d[0], "waldo")); assert_se(streq_ptr(d[1], "bar")); assert_se(streq_ptr(d[2], "foo")); assert_se(streq_ptr(d[3], NULL)); } static void test_strv_shell_escape(void) { _cleanup_strv_free_ char **v = NULL; v = strv_new("foo:bar", "bar,baz", "wal\\do", NULL); assert_se(v); assert_se(strv_shell_escape(v, ",:")); assert_se(streq_ptr(v[0], "foo\\:bar")); assert_se(streq_ptr(v[1], "bar\\,baz")); assert_se(streq_ptr(v[2], "wal\\\\do")); assert_se(streq_ptr(v[3], NULL)); } static void test_strv_skip_one(char **a, size_t n, char **b) { a = strv_skip(a, n); assert_se(strv_equal(a, b)); } static void test_strv_skip(void) { test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 0, STRV_MAKE("foo", "bar", "baz")); test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 1, STRV_MAKE("bar", "baz")); test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 2, STRV_MAKE("baz")); test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 3, STRV_MAKE(NULL)); test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 4, STRV_MAKE(NULL)); test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 55, STRV_MAKE(NULL)); test_strv_skip_one(STRV_MAKE("quux"), 0, STRV_MAKE("quux")); test_strv_skip_one(STRV_MAKE("quux"), 1, STRV_MAKE(NULL)); test_strv_skip_one(STRV_MAKE("quux"), 55, STRV_MAKE(NULL)); test_strv_skip_one(STRV_MAKE(NULL), 0, STRV_MAKE(NULL)); test_strv_skip_one(STRV_MAKE(NULL), 1, STRV_MAKE(NULL)); test_strv_skip_one(STRV_MAKE(NULL), 55, STRV_MAKE(NULL)); } static void test_strv_extend_n(void) { _cleanup_strv_free_ char **v = NULL; v = strv_new("foo", "bar", NULL); assert_se(v); assert_se(strv_extend_n(&v, "waldo", 3) >= 0); assert_se(strv_extend_n(&v, "piep", 2) >= 0); assert_se(streq(v[0], "foo")); assert_se(streq(v[1], "bar")); assert_se(streq(v[2], "waldo")); assert_se(streq(v[3], "waldo")); assert_se(streq(v[4], "waldo")); assert_se(streq(v[5], "piep")); assert_se(streq(v[6], "piep")); assert_se(v[7] == NULL); v = strv_free(v); assert_se(strv_extend_n(&v, "foo", 1) >= 0); assert_se(strv_extend_n(&v, "bar", 0) >= 0); assert_se(streq(v[0], "foo")); assert_se(v[1] == NULL); } static void test_strv_make_nulstr_one(char **l) { _cleanup_free_ char *b = NULL, *c = NULL; _cleanup_strv_free_ char **q = NULL; size_t n, m; assert_se(strv_make_nulstr(l, &b, &n) >= 0); assert_se(q = strv_parse_nulstr(b, n)); assert_se(strv_equal(l, q)); assert_se(strv_make_nulstr(q, &c, &m) >= 0); assert_se(m == n); assert_se(memcmp(b, c, m) == 0); } static void test_strv_make_nulstr(void) { test_strv_make_nulstr_one(NULL); test_strv_make_nulstr_one(STRV_MAKE(NULL)); test_strv_make_nulstr_one(STRV_MAKE("foo")); test_strv_make_nulstr_one(STRV_MAKE("foo", "bar")); test_strv_make_nulstr_one(STRV_MAKE("foo", "bar", "quuux")); } int main(int argc, char *argv[]) { test_specifier_printf(); test_strv_foreach(); test_strv_foreach_backwards(); test_strv_foreach_pair(); test_strv_find(); test_strv_find_prefix(); test_strv_find_startswith(); test_strv_join(); test_strv_quote_unquote(input_table_multiple, "\"one\" \"two\" \"three\""); test_strv_quote_unquote(input_table_one, "\"one\""); test_strv_quote_unquote(input_table_none, ""); test_strv_quote_unquote(input_table_quotes, QUOTES_STRING); test_strv_quote_unquote(input_table_spaces, SPACES_STRING); test_strv_unquote(" foo=bar \"waldo\" zzz ", STRV_MAKE("foo=bar", "waldo", "zzz")); test_strv_unquote("", STRV_MAKE_EMPTY); test_strv_unquote(" ", STRV_MAKE_EMPTY); test_strv_unquote(" ", STRV_MAKE_EMPTY); test_strv_unquote(" x", STRV_MAKE("x")); test_strv_unquote("x ", STRV_MAKE("x")); test_strv_unquote(" x ", STRV_MAKE("x")); test_strv_unquote(" \"x\" ", STRV_MAKE("x")); test_strv_unquote(" 'x' ", STRV_MAKE("x")); test_strv_unquote(" 'x\"' ", STRV_MAKE("x\"")); test_strv_unquote(" \"x'\" ", STRV_MAKE("x'")); test_strv_unquote("a '--b=c \"d e\"'", STRV_MAKE("a", "--b=c \"d e\"")); /* trailing backslashes */ test_strv_unquote(" x\\\\", STRV_MAKE("x\\")); test_invalid_unquote(" x\\"); test_invalid_unquote("a --b='c \"d e\"''"); test_invalid_unquote("a --b='c \"d e\" '\""); test_invalid_unquote("a --b='c \"d e\"garbage"); test_invalid_unquote("'"); test_invalid_unquote("\""); test_invalid_unquote("'x'y'g"); test_strv_split(); test_strv_split_extract(); test_strv_split_newlines(); test_strv_split_nulstr(); test_strv_parse_nulstr(); test_strv_overlap(); test_strv_sort(); test_strv_extend_strv(); test_strv_extend_strv_concat(); test_strv_extend(); test_strv_extendf(); test_strv_from_stdarg_alloca(); test_strv_push_prepend(); test_strv_push(); test_strv_equal(); test_strv_is_uniq(); test_strv_reverse(); test_strv_shell_escape(); test_strv_skip(); test_strv_extend_n(); test_strv_make_nulstr(); return 0; } systemd-229/src/test/test-strxcpyx.c000066400000000000000000000055541265713322000176650ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Thomas H.P. Andersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "string-util.h" #include "strxcpyx.h" #include "util.h" static void test_strpcpy(void) { char target[25]; char *s = target; size_t space_left; space_left = sizeof(target); space_left = strpcpy(&s, space_left, "12345"); space_left = strpcpy(&s, space_left, "hey hey hey"); space_left = strpcpy(&s, space_left, "waldo"); space_left = strpcpy(&s, space_left, "ba"); space_left = strpcpy(&s, space_left, "r"); space_left = strpcpy(&s, space_left, "foo"); assert_se(streq(target, "12345hey hey heywaldobar")); assert_se(space_left == 0); } static void test_strpcpyf(void) { char target[25]; char *s = target; size_t space_left; space_left = sizeof(target); space_left = strpcpyf(&s, space_left, "space left: %zu. ", space_left); space_left = strpcpyf(&s, space_left, "foo%s", "bar"); assert_se(streq(target, "space left: 25. foobar")); assert_se(space_left == 3); } static void test_strpcpyl(void) { char target[25]; char *s = target; size_t space_left; space_left = sizeof(target); space_left = strpcpyl(&s, space_left, "waldo", " test", " waldo. ", NULL); space_left = strpcpyl(&s, space_left, "Banana", NULL); assert_se(streq(target, "waldo test waldo. Banana")); assert_se(space_left == 1); } static void test_strscpy(void) { char target[25]; size_t space_left; space_left = sizeof(target); space_left = strscpy(target, space_left, "12345"); assert_se(streq(target, "12345")); assert_se(space_left == 20); } static void test_strscpyl(void) { char target[25]; size_t space_left; space_left = sizeof(target); space_left = strscpyl(target, space_left, "12345", "waldo", "waldo", NULL); assert_se(streq(target, "12345waldowaldo")); assert_se(space_left == 10); } int main(int argc, char *argv[]) { test_strpcpy(); test_strpcpyf(); test_strpcpyl(); test_strscpy(); test_strscpyl(); return 0; } systemd-229/src/test/test-tables.c000066400000000000000000000113461265713322000172270ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "architecture.h" #include "automount.h" #include "bus-xml-policy.h" #include "busname.h" #include "cgroup.h" #include "compress.h" #include "condition.h" #include "device.h" #include "execute.h" #include "install.h" #include "job.h" #include "journald-server.h" #include "kill.h" #include "link-config.h" #include "locale-util.h" #include "log.h" #include "logs-show.h" #include "mount.h" #include "path.h" #include "rlimit-util.h" #include "scope.h" #include "service.h" #include "slice.h" #include "socket-util.h" #include "socket.h" #include "swap.h" #include "target.h" #include "test-tables.h" #include "timer.h" #include "unit-name.h" #include "unit.h" #include "util.h" int main(int argc, char **argv) { test_table(architecture, ARCHITECTURE); test_table(automount_result, AUTOMOUNT_RESULT); test_table(automount_state, AUTOMOUNT_STATE); test_table(bus_policy_access, BUS_POLICY_ACCESS); test_table(busname_result, BUSNAME_RESULT); test_table(busname_state, BUSNAME_STATE); test_table(cgroup_device_policy, CGROUP_DEVICE_POLICY); test_table(condition_type, CONDITION_TYPE); test_table(assert_type, CONDITION_TYPE); test_table(condition_result, CONDITION_RESULT); test_table(device_state, DEVICE_STATE); test_table(exec_input, EXEC_INPUT); test_table(exec_output, EXEC_OUTPUT); test_table(failure_action, FAILURE_ACTION); test_table(job_mode, JOB_MODE); test_table(job_result, JOB_RESULT); test_table(job_state, JOB_STATE); test_table(job_type, JOB_TYPE); test_table(kill_mode, KILL_MODE); test_table(kill_who, KILL_WHO); test_table(log_target, LOG_TARGET); test_table(mac_policy, MACPOLICY); test_table(manager_state, MANAGER_STATE); test_table(mount_exec_command, MOUNT_EXEC_COMMAND); test_table(mount_result, MOUNT_RESULT); test_table(mount_state, MOUNT_STATE); test_table(name_policy, NAMEPOLICY); test_table(notify_access, NOTIFY_ACCESS); test_table(output_mode, OUTPUT_MODE); test_table(path_result, PATH_RESULT); test_table(path_state, PATH_STATE); test_table(path_type, PATH_TYPE); test_table(policy_item_class, POLICY_ITEM_CLASS); test_table(policy_item_type, POLICY_ITEM_TYPE); test_table(protect_home, PROTECT_HOME); test_table(protect_system, PROTECT_SYSTEM); test_table(rlimit, RLIMIT); test_table(scope_result, SCOPE_RESULT); test_table(scope_state, SCOPE_STATE); test_table(service_exec_command, SERVICE_EXEC_COMMAND); test_table(service_restart, SERVICE_RESTART); test_table(service_result, SERVICE_RESULT); test_table(service_state, SERVICE_STATE); test_table(service_type, SERVICE_TYPE); test_table(slice_state, SLICE_STATE); test_table(socket_address_bind_ipv6_only, SOCKET_ADDRESS_BIND_IPV6_ONLY); test_table(socket_exec_command, SOCKET_EXEC_COMMAND); test_table(socket_result, SOCKET_RESULT); test_table(socket_state, SOCKET_STATE); test_table(split_mode, SPLIT); test_table(storage, STORAGE); test_table(swap_exec_command, SWAP_EXEC_COMMAND); test_table(swap_result, SWAP_RESULT); test_table(swap_state, SWAP_STATE); test_table(target_state, TARGET_STATE); test_table(timer_base, TIMER_BASE); test_table(timer_result, TIMER_RESULT); test_table(timer_state, TIMER_STATE); test_table(unit_active_state, UNIT_ACTIVE_STATE); test_table(unit_dependency, UNIT_DEPENDENCY); test_table(unit_file_change_type, UNIT_FILE_CHANGE_TYPE); test_table(unit_file_preset_mode, UNIT_FILE_PRESET); test_table(unit_file_state, UNIT_FILE_STATE); test_table(unit_load_state, UNIT_LOAD_STATE); test_table(unit_type, UNIT_TYPE); test_table(locale_variable, VARIABLE_LC); test_table_sparse(object_compressed, OBJECT_COMPRESSED); return EXIT_SUCCESS; } systemd-229/src/test/test-terminal-util.c000066400000000000000000000051351265713322000205420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Thomas H.P. Andersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "fd-util.h" #include "fileio.h" #include "log.h" #include "macro.h" #include "terminal-util.h" #include "util.h" static void test_default_term_for_tty(void) { puts(default_term_for_tty("/dev/tty23")); puts(default_term_for_tty("/dev/ttyS23")); puts(default_term_for_tty("/dev/tty0")); puts(default_term_for_tty("/dev/pty0")); puts(default_term_for_tty("/dev/pts/0")); puts(default_term_for_tty("/dev/console")); puts(default_term_for_tty("tty23")); puts(default_term_for_tty("ttyS23")); puts(default_term_for_tty("tty0")); puts(default_term_for_tty("pty0")); puts(default_term_for_tty("pts/0")); puts(default_term_for_tty("console")); } static void test_read_one_char(void) { _cleanup_fclose_ FILE *file = NULL; char r; bool need_nl; char name[] = "/tmp/test-read_one_char.XXXXXX"; int fd; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); file = fdopen(fd, "r+"); assert_se(file); assert_se(fputs("c\n", file) >= 0); rewind(file); assert_se(read_one_char(file, &r, 1000000, &need_nl) >= 0); assert_se(!need_nl); assert_se(r == 'c'); assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0); rewind(file); assert_se(fputs("foobar\n", file) >= 0); rewind(file); assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0); rewind(file); assert_se(fputs("\n", file) >= 0); rewind(file); assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0); unlink(name); } int main(int argc, char *argv[]) { log_parse_environment(); log_open(); test_default_term_for_tty(); test_read_one_char(); return 0; } systemd-229/src/test/test-time.c000066400000000000000000000202361265713322000167110ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "strv.h" #include "time-util.h" static void test_parse_sec(void) { usec_t u; assert_se(parse_sec("5s", &u) >= 0); assert_se(u == 5 * USEC_PER_SEC); assert_se(parse_sec("5s500ms", &u) >= 0); assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC); assert_se(parse_sec(" 5s 500ms ", &u) >= 0); assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC); assert_se(parse_sec(" 5.5s ", &u) >= 0); assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC); assert_se(parse_sec(" 5.5s 0.5ms ", &u) >= 0); assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC + 500); assert_se(parse_sec(" .22s ", &u) >= 0); assert_se(u == 220 * USEC_PER_MSEC); assert_se(parse_sec(" .50y ", &u) >= 0); assert_se(u == USEC_PER_YEAR / 2); assert_se(parse_sec("2.5", &u) >= 0); assert_se(u == 2500 * USEC_PER_MSEC); assert_se(parse_sec(".7", &u) >= 0); assert_se(u == 700 * USEC_PER_MSEC); assert_se(parse_sec("infinity", &u) >= 0); assert_se(u == USEC_INFINITY); assert_se(parse_sec(" infinity ", &u) >= 0); assert_se(u == USEC_INFINITY); assert_se(parse_sec(" xyz ", &u) < 0); assert_se(parse_sec("", &u) < 0); assert_se(parse_sec(" . ", &u) < 0); assert_se(parse_sec(" 5. ", &u) < 0); assert_se(parse_sec(".s ", &u) < 0); assert_se(parse_sec(" infinity .7", &u) < 0); assert_se(parse_sec(".3 infinity", &u) < 0); } static void test_parse_time(void) { usec_t u; assert_se(parse_time("5", &u, 1) >= 0); assert_se(u == 5); assert_se(parse_time("5", &u, USEC_PER_MSEC) >= 0); assert_se(u == 5 * USEC_PER_MSEC); assert_se(parse_time("5", &u, USEC_PER_SEC) >= 0); assert_se(u == 5 * USEC_PER_SEC); assert_se(parse_time("5s", &u, 1) >= 0); assert_se(u == 5 * USEC_PER_SEC); assert_se(parse_time("5s", &u, USEC_PER_SEC) >= 0); assert_se(u == 5 * USEC_PER_SEC); assert_se(parse_time("5s", &u, USEC_PER_MSEC) >= 0); assert_se(u == 5 * USEC_PER_SEC); } static void test_parse_nsec(void) { nsec_t u; assert_se(parse_nsec("5s", &u) >= 0); assert_se(u == 5 * NSEC_PER_SEC); assert_se(parse_nsec("5s500ms", &u) >= 0); assert_se(u == 5 * NSEC_PER_SEC + 500 * NSEC_PER_MSEC); assert_se(parse_nsec(" 5s 500ms ", &u) >= 0); assert_se(u == 5 * NSEC_PER_SEC + 500 * NSEC_PER_MSEC); assert_se(parse_nsec(" 5.5s ", &u) >= 0); assert_se(u == 5 * NSEC_PER_SEC + 500 * NSEC_PER_MSEC); assert_se(parse_nsec(" 5.5s 0.5ms ", &u) >= 0); assert_se(u == 5 * NSEC_PER_SEC + 500 * NSEC_PER_MSEC + 500 * NSEC_PER_USEC); assert_se(parse_nsec(" .22s ", &u) >= 0); assert_se(u == 220 * NSEC_PER_MSEC); assert_se(parse_nsec(" .50y ", &u) >= 0); assert_se(u == NSEC_PER_YEAR / 2); assert_se(parse_nsec("2.5", &u) >= 0); assert_se(u == 2); assert_se(parse_nsec(".7", &u) >= 0); assert_se(u == 0); assert_se(parse_nsec("infinity", &u) >= 0); assert_se(u == NSEC_INFINITY); assert_se(parse_nsec(" infinity ", &u) >= 0); assert_se(u == NSEC_INFINITY); assert_se(parse_nsec(" xyz ", &u) < 0); assert_se(parse_nsec("", &u) < 0); assert_se(parse_nsec(" . ", &u) < 0); assert_se(parse_nsec(" 5. ", &u) < 0); assert_se(parse_nsec(".s ", &u) < 0); assert_se(parse_nsec(" infinity .7", &u) < 0); assert_se(parse_nsec(".3 infinity", &u) < 0); } static void test_format_timespan_one(usec_t x, usec_t accuracy) { char *r; char l[FORMAT_TIMESPAN_MAX]; usec_t y; log_info(USEC_FMT" (at accuracy "USEC_FMT")", x, accuracy); r = format_timespan(l, sizeof(l), x, accuracy); assert_se(r); log_info(" = <%s>", l); assert_se(parse_sec(l, &y) >= 0); log_info(" = "USEC_FMT, y); if (accuracy <= 0) accuracy = 1; assert_se(x / accuracy == y / accuracy); } static void test_format_timespan(usec_t accuracy) { test_format_timespan_one(0, accuracy); test_format_timespan_one(1, accuracy); test_format_timespan_one(1*USEC_PER_SEC, accuracy); test_format_timespan_one(999*USEC_PER_MSEC, accuracy); test_format_timespan_one(1234567, accuracy); test_format_timespan_one(12, accuracy); test_format_timespan_one(123, accuracy); test_format_timespan_one(1234, accuracy); test_format_timespan_one(12345, accuracy); test_format_timespan_one(123456, accuracy); test_format_timespan_one(1234567, accuracy); test_format_timespan_one(12345678, accuracy); test_format_timespan_one(1200000, accuracy); test_format_timespan_one(1230000, accuracy); test_format_timespan_one(1230000, accuracy); test_format_timespan_one(1234000, accuracy); test_format_timespan_one(1234500, accuracy); test_format_timespan_one(1234560, accuracy); test_format_timespan_one(1234567, accuracy); test_format_timespan_one(986087, accuracy); test_format_timespan_one(500 * USEC_PER_MSEC, accuracy); test_format_timespan_one(9*USEC_PER_YEAR/5 - 23, accuracy); test_format_timespan_one(USEC_INFINITY, accuracy); } static void test_timezone_is_valid(void) { assert_se(timezone_is_valid("Europe/Berlin")); assert_se(timezone_is_valid("Australia/Sydney")); assert_se(!timezone_is_valid("Europe/Do not exist")); } static void test_get_timezones(void) { _cleanup_strv_free_ char **zones = NULL; int r; char **zone; r = get_timezones(&zones); assert_se(r == 0); STRV_FOREACH(zone, zones) assert_se(timezone_is_valid(*zone)); } static void test_usec_add(void) { assert_se(usec_add(0, 0) == 0); assert_se(usec_add(1, 4) == 5); assert_se(usec_add(USEC_INFINITY, 5) == USEC_INFINITY); assert_se(usec_add(5, USEC_INFINITY) == USEC_INFINITY); assert_se(usec_add(USEC_INFINITY-5, 2) == USEC_INFINITY-3); assert_se(usec_add(USEC_INFINITY-2, 2) == USEC_INFINITY); assert_se(usec_add(USEC_INFINITY-1, 2) == USEC_INFINITY); assert_se(usec_add(USEC_INFINITY, 2) == USEC_INFINITY); } static void test_usec_sub(void) { assert_se(usec_sub(0, 0) == 0); assert_se(usec_sub(4, 1) == 3); assert_se(usec_sub(4, 4) == 0); assert_se(usec_sub(4, 5) == 0); assert_se(usec_sub(USEC_INFINITY-3, -3) == USEC_INFINITY); assert_se(usec_sub(USEC_INFINITY-3, -3) == USEC_INFINITY); assert_se(usec_sub(USEC_INFINITY-3, -4) == USEC_INFINITY); assert_se(usec_sub(USEC_INFINITY-3, -5) == USEC_INFINITY); assert_se(usec_sub(USEC_INFINITY, 5) == USEC_INFINITY); } int main(int argc, char *argv[]) { uintmax_t x; test_parse_sec(); test_parse_time(); test_parse_nsec(); test_format_timespan(1); test_format_timespan(USEC_PER_MSEC); test_format_timespan(USEC_PER_SEC); test_timezone_is_valid(); test_get_timezones(); test_usec_add(); test_usec_sub(); /* Ensure time_t is signed */ assert_cc((time_t) -1 < (time_t) 1); /* Ensure TIME_T_MAX works correctly */ x = (uintmax_t) TIME_T_MAX; x ++; assert((time_t) x < 0); return 0; } systemd-229/src/test/test-tmpfiles.c000066400000000000000000000037451265713322000176040ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "log.h" #include "string-util.h" #include "util.h" int main(int argc, char** argv) { const char *p = argv[1] ?: "/tmp"; char *pattern = strjoina(p, "/systemd-test-XXXXXX"); _cleanup_close_ int fd, fd2; _cleanup_free_ char *cmd, *cmd2, *ans, *ans2; log_set_max_level(LOG_DEBUG); log_parse_environment(); fd = open_tmpfile(p, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(asprintf(&cmd, "ls -l /proc/"PID_FMT"/fd/%d", getpid(), fd) > 0); (void) system(cmd); assert_se(readlink_malloc(cmd + 6, &ans) >= 0); log_debug("link1: %s", ans); assert_se(endswith(ans, " (deleted)")); fd2 = mkostemp_safe(pattern, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(unlink(pattern) == 0); assert_se(asprintf(&cmd2, "ls -l /proc/"PID_FMT"/fd/%d", getpid(), fd2) > 0); (void) system(cmd2); assert_se(readlink_malloc(cmd2 + 6, &ans2) >= 0); log_debug("link2: %s", ans2); assert_se(endswith(ans2, " (deleted)")); return 0; } systemd-229/src/test/test-udev.c000066400000000000000000000117311265713322000167160ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2003-2004 Greg Kroah-Hartman Copyright 2004-2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include "fs-util.h" #include "missing.h" #include "selinux-util.h" #include "signal-util.h" #include "string-util.h" #include "udev-util.h" #include "udev.h" static int fake_filesystems(void) { static const struct fakefs { const char *src; const char *target; const char *error; } fakefss[] = { { "test/sys", "/sys", "failed to mount test /sys" }, { "test/dev", "/dev", "failed to mount test /dev" }, { "test/run", "/run", "failed to mount test /run" }, { "test/run", "/etc/udev/rules.d", "failed to mount empty /etc/udev/rules.d" }, { "test/run", UDEVLIBEXECDIR "/rules.d","failed to mount empty " UDEVLIBEXECDIR "/rules.d" }, }; unsigned int i; int err; err = unshare(CLONE_NEWNS); if (err < 0) { err = -errno; fprintf(stderr, "failed to call unshare(): %m\n"); goto out; } if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0) { err = -errno; fprintf(stderr, "failed to mount / as private: %m\n"); goto out; } for (i = 0; i < ELEMENTSOF(fakefss); i++) { err = mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL); if (err < 0) { err = -errno; fprintf(stderr, "%s %m\n", fakefss[i].error); return err; } } out: return err; } int main(int argc, char *argv[]) { _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_udev_event_unref_ struct udev_event *event = NULL; _cleanup_udev_device_unref_ struct udev_device *dev = NULL; _cleanup_udev_rules_unref_ struct udev_rules *rules = NULL; char syspath[UTIL_PATH_SIZE]; const char *devpath; const char *action; int err; err = fake_filesystems(); if (err < 0) return EXIT_FAILURE; udev = udev_new(); if (udev == NULL) return EXIT_FAILURE; log_debug("version %s", VERSION); mac_selinux_init("/dev"); action = argv[1]; if (action == NULL) { log_error("action missing"); goto out; } devpath = argv[2]; if (devpath == NULL) { log_error("devpath missing"); goto out; } rules = udev_rules_new(udev, 1); strscpyl(syspath, sizeof(syspath), "/sys", devpath, NULL); dev = udev_device_new_from_synthetic_event(udev, syspath, action); if (dev == NULL) { log_debug("unknown device '%s'", devpath); goto out; } event = udev_event_new(dev); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0); /* do what devtmpfs usually provides us */ if (udev_device_get_devnode(dev) != NULL) { mode_t mode = 0600; if (streq(udev_device_get_subsystem(dev), "block")) mode |= S_IFBLK; else mode |= S_IFCHR; if (!streq(action, "remove")) { mkdir_parents_label(udev_device_get_devnode(dev), 0755); mknod(udev_device_get_devnode(dev), mode, udev_device_get_devnum(dev)); } else { unlink(udev_device_get_devnode(dev)); rmdir_parents(udev_device_get_devnode(dev), "/"); } } udev_event_execute_rules(event, 3 * USEC_PER_SEC, USEC_PER_SEC, NULL, rules); udev_event_execute_run(event, 3 * USEC_PER_SEC, USEC_PER_SEC); out: mac_selinux_finish(); return err ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/test/test-uid-range.c000066400000000000000000000056441265713322000176340ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "uid-range.h" #include "user-util.h" #include "util.h" int main(int argc, char *argv[]) { _cleanup_free_ UidRange *p = NULL; unsigned n = 0; uid_t search; assert_se(uid_range_add_str(&p, &n, "500-999") >= 0); assert_se(n == 1); assert_se(p[0].start == 500); assert_se(p[0].nr == 500); assert_se(!uid_range_contains(p, n, 499)); assert_se(uid_range_contains(p, n, 500)); assert_se(uid_range_contains(p, n, 999)); assert_se(!uid_range_contains(p, n, 1000)); search = UID_INVALID; assert_se(uid_range_next_lower(p, n, &search)); assert_se(search == 999); assert_se(uid_range_next_lower(p, n, &search)); assert_se(search == 998); search = 501; assert_se(uid_range_next_lower(p, n, &search)); assert_se(search == 500); assert_se(uid_range_next_lower(p, n, &search) == -EBUSY); assert_se(uid_range_add_str(&p, &n, "1000") >= 0); assert_se(n == 1); assert_se(p[0].start == 500); assert_se(p[0].nr == 501); assert_se(uid_range_add_str(&p, &n, "30-40") >= 0); assert_se(n == 2); assert_se(p[0].start == 30); assert_se(p[0].nr == 11); assert_se(p[1].start == 500); assert_se(p[1].nr == 501); assert_se(uid_range_add_str(&p, &n, "60-70") >= 0); assert_se(n == 3); assert_se(p[0].start == 30); assert_se(p[0].nr == 11); assert_se(p[1].start == 60); assert_se(p[1].nr == 11); assert_se(p[2].start == 500); assert_se(p[2].nr == 501); assert_se(uid_range_add_str(&p, &n, "20-2000") >= 0); assert_se(n == 1); assert_se(p[0].start == 20); assert_se(p[0].nr == 1981); assert_se(uid_range_add_str(&p, &n, "2002") >= 0); assert_se(n == 2); assert_se(p[0].start == 20); assert_se(p[0].nr == 1981); assert_se(p[1].start == 2002); assert_se(p[1].nr == 1); assert_se(uid_range_add_str(&p, &n, "2001") >= 0); assert_se(n == 1); assert_se(p[0].start == 20); assert_se(p[0].nr == 1983); return 0; } systemd-229/src/test/test-unaligned.c000066400000000000000000000163261265713322000177260ustar00rootroot00000000000000/*** This file is part of systemd Copyright 2014 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sparse-endian.h" #include "unaligned.h" #include "util.h" static uint8_t data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, }; static void test_be(void) { uint8_t scratch[16]; assert_se(unaligned_read_be16(&data[0]) == 0x0001); assert_se(unaligned_read_be16(&data[1]) == 0x0102); assert_se(unaligned_read_be32(&data[0]) == 0x00010203); assert_se(unaligned_read_be32(&data[1]) == 0x01020304); assert_se(unaligned_read_be32(&data[2]) == 0x02030405); assert_se(unaligned_read_be32(&data[3]) == 0x03040506); assert_se(unaligned_read_be64(&data[0]) == 0x0001020304050607); assert_se(unaligned_read_be64(&data[1]) == 0x0102030405060708); assert_se(unaligned_read_be64(&data[2]) == 0x0203040506070809); assert_se(unaligned_read_be64(&data[3]) == 0x030405060708090a); assert_se(unaligned_read_be64(&data[4]) == 0x0405060708090a0b); assert_se(unaligned_read_be64(&data[5]) == 0x05060708090a0b0c); assert_se(unaligned_read_be64(&data[6]) == 0x060708090a0b0c0d); assert_se(unaligned_read_be64(&data[7]) == 0x0708090a0b0c0d0e); zero(scratch); unaligned_write_be16(&scratch[0], 0x0001); assert_se(memcmp(&scratch[0], &data[0], sizeof(uint16_t)) == 0); zero(scratch); unaligned_write_be16(&scratch[1], 0x0102); assert_se(memcmp(&scratch[1], &data[1], sizeof(uint16_t)) == 0); zero(scratch); unaligned_write_be32(&scratch[0], 0x00010203); assert_se(memcmp(&scratch[0], &data[0], sizeof(uint32_t)) == 0); zero(scratch); unaligned_write_be32(&scratch[1], 0x01020304); assert_se(memcmp(&scratch[1], &data[1], sizeof(uint32_t)) == 0); zero(scratch); unaligned_write_be32(&scratch[2], 0x02030405); assert_se(memcmp(&scratch[2], &data[2], sizeof(uint32_t)) == 0); zero(scratch); unaligned_write_be32(&scratch[3], 0x03040506); assert_se(memcmp(&scratch[3], &data[3], sizeof(uint32_t)) == 0); zero(scratch); unaligned_write_be64(&scratch[0], 0x0001020304050607); assert_se(memcmp(&scratch[0], &data[0], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_be64(&scratch[1], 0x0102030405060708); assert_se(memcmp(&scratch[1], &data[1], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_be64(&scratch[2], 0x0203040506070809); assert_se(memcmp(&scratch[2], &data[2], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_be64(&scratch[3], 0x030405060708090a); assert_se(memcmp(&scratch[3], &data[3], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_be64(&scratch[4], 0x0405060708090a0b); assert_se(memcmp(&scratch[4], &data[4], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_be64(&scratch[5], 0x05060708090a0b0c); assert_se(memcmp(&scratch[5], &data[5], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_be64(&scratch[6], 0x060708090a0b0c0d); assert_se(memcmp(&scratch[6], &data[6], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_be64(&scratch[7], 0x0708090a0b0c0d0e); assert_se(memcmp(&scratch[7], &data[7], sizeof(uint64_t)) == 0); } static void test_le(void) { uint8_t scratch[16]; assert_se(unaligned_read_le16(&data[0]) == 0x0100); assert_se(unaligned_read_le16(&data[1]) == 0x0201); assert_se(unaligned_read_le32(&data[0]) == 0x03020100); assert_se(unaligned_read_le32(&data[1]) == 0x04030201); assert_se(unaligned_read_le32(&data[2]) == 0x05040302); assert_se(unaligned_read_le32(&data[3]) == 0x06050403); assert_se(unaligned_read_le64(&data[0]) == 0x0706050403020100); assert_se(unaligned_read_le64(&data[1]) == 0x0807060504030201); assert_se(unaligned_read_le64(&data[2]) == 0x0908070605040302); assert_se(unaligned_read_le64(&data[3]) == 0x0a09080706050403); assert_se(unaligned_read_le64(&data[4]) == 0x0b0a090807060504); assert_se(unaligned_read_le64(&data[5]) == 0x0c0b0a0908070605); assert_se(unaligned_read_le64(&data[6]) == 0x0d0c0b0a09080706); assert_se(unaligned_read_le64(&data[7]) == 0x0e0d0c0b0a090807); zero(scratch); unaligned_write_le16(&scratch[0], 0x0100); assert_se(memcmp(&scratch[0], &data[0], sizeof(uint16_t)) == 0); zero(scratch); unaligned_write_le16(&scratch[1], 0x0201); assert_se(memcmp(&scratch[1], &data[1], sizeof(uint16_t)) == 0); zero(scratch); unaligned_write_le32(&scratch[0], 0x03020100); assert_se(memcmp(&scratch[0], &data[0], sizeof(uint32_t)) == 0); zero(scratch); unaligned_write_le32(&scratch[1], 0x04030201); assert_se(memcmp(&scratch[1], &data[1], sizeof(uint32_t)) == 0); zero(scratch); unaligned_write_le32(&scratch[2], 0x05040302); assert_se(memcmp(&scratch[2], &data[2], sizeof(uint32_t)) == 0); zero(scratch); unaligned_write_le32(&scratch[3], 0x06050403); assert_se(memcmp(&scratch[3], &data[3], sizeof(uint32_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[0], 0x0706050403020100); assert_se(memcmp(&scratch[0], &data[0], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[1], 0x0807060504030201); assert_se(memcmp(&scratch[1], &data[1], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[2], 0x0908070605040302); assert_se(memcmp(&scratch[2], &data[2], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[3], 0x0a09080706050403); assert_se(memcmp(&scratch[3], &data[3], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[4], 0x0B0A090807060504); assert_se(memcmp(&scratch[4], &data[4], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[5], 0x0c0b0a0908070605); assert_se(memcmp(&scratch[5], &data[5], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[6], 0x0d0c0b0a09080706); assert_se(memcmp(&scratch[6], &data[6], sizeof(uint64_t)) == 0); zero(scratch); unaligned_write_le64(&scratch[7], 0x0e0d0c0b0a090807); assert_se(memcmp(&scratch[7], &data[7], sizeof(uint64_t)) == 0); } int main(int argc, const char *argv[]) { test_be(); test_le(); } systemd-229/src/test/test-unit-file.c000066400000000000000000001025401265713322000176460ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering Copyright 2013 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include "alloc-util.h" #include "capability-util.h" #include "fd-util.h" #include "fileio.h" #include "hashmap.h" #include "hostname-util.h" #include "install-printf.h" #include "install.h" #include "load-fragment.h" #include "macro.h" #include "specifier.h" #include "string-util.h" #include "strv.h" #include "test-helper.h" #include "user-util.h" #include "util.h" static int test_unit_file_get_set(void) { int r; Hashmap *h; Iterator i; UnitFileList *p; h = hashmap_new(&string_hash_ops); assert_se(h); r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h); if (r == -EPERM || r == -EACCES) { printf("Skipping test: unit_file_get_list: %s", strerror(-r)); return EXIT_TEST_SKIP; } log_full(r == 0 ? LOG_INFO : LOG_ERR, "unit_file_get_list: %s", strerror(-r)); if (r < 0) return EXIT_FAILURE; HASHMAP_FOREACH(p, h, i) printf("%s = %s\n", p->path, unit_file_state_to_string(p->state)); unit_file_list_free(h); return 0; } static void check_execcommand(ExecCommand *c, const char* path, const char* argv0, const char* argv1, const char* argv2, bool ignore) { size_t n; assert_se(c); log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]", path, argv0 ?: path, argv1, argv2); n = strv_length(c->argv); log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]", c->path, c->argv[0], n > 0 ? c->argv[1] : NULL, n > 1 ? c->argv[2] : NULL); assert_se(streq(c->path, path)); assert_se(streq(c->argv[0], argv0 ?: path)); if (n > 0) assert_se(streq_ptr(c->argv[1], argv1)); if (n > 1) assert_se(streq_ptr(c->argv[2], argv2)); assert_se(c->ignore == ignore); } static void test_config_parse_exec(void) { /* int config_parse_exec( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) */ int r; ExecCommand *c = NULL, *c1; const char *ccc; Manager *m = NULL; Unit *u = NULL; r = manager_new(MANAGER_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { printf("Skipping test: manager_new: %s\n", strerror(-r)); return; } assert_se(r >= 0); assert_se(manager_startup(m, NULL, NULL) >= 0); assert_se(u = unit_new(m, sizeof(Service))); log_info("/* basic test */"); r = config_parse_exec(NULL, "fake", 1, "section", 1, "LValue", 0, "/RValue r1", &c, u); assert_se(r >= 0); check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false); r = config_parse_exec(NULL, "fake", 2, "section", 1, "LValue", 0, "/RValue///slashes r1///", &c, u); log_info("/* test slashes */"); assert_se(r >= 0); c1 = c->command_next; check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false); log_info("/* trailing slash */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "/RValue/ argv0 r1", &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); log_info("/* honour_argv0 */"); r = config_parse_exec(NULL, "fake", 3, "section", 1, "LValue", 0, "@/RValue///slashes2 ///argv0 r1", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false); log_info("/* honour_argv0, no args */"); r = config_parse_exec(NULL, "fake", 3, "section", 1, "LValue", 0, "@/RValue", &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); log_info("/* no command, whitespace only, reset */"); r = config_parse_exec(NULL, "fake", 3, "section", 1, "LValue", 0, " ", &c, u); assert_se(r == 0); assert_se(c == NULL); log_info("/* ignore && honour_argv0 */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "-@/RValue///slashes3 argv0a r1", &c, u); assert_se(r >= 0); c1 = c; check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true); log_info("/* ignore && honour_argv0 */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "@-/RValue///slashes4 argv0b r1", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true); log_info("/* ignore && ignore */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "--/RValue argv0 r1", &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); log_info("/* ignore && ignore (2) */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "-@-/RValue argv0 r1", &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); log_info("/* semicolon */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "-@/RValue argv0 r1 ; " "/goo/goo boo", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); c1 = c1->command_next; check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false); log_info("/* two semicolons in a row */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "-@/RValue argv0 r1 ; ; " "/goo/goo boo", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); /* second command fails because the executable name is ";" */ assert_se(c1->command_next == NULL); log_info("/* trailing semicolon */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "-@/RValue argv0 r1 ; ", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); assert_se(c1->command_next == NULL); log_info("/* trailing semicolon, no whitespace */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "-@/RValue argv0 r1 ;", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); assert_se(c1->command_next == NULL); log_info("/* trailing semicolon in single quotes */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "-@/RValue argv0 r1 ';'", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/RValue", "argv0", "r1", ";", true); log_info("/* escaped semicolon */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/bin/find \\;", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/bin/find", NULL, ";", NULL, false); log_info("/* escaped semicolon with following arg */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/sbin/find \\; /x", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/sbin/find", NULL, ";", "/x", false); log_info("/* escaped semicolon as part of an expression */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/sbin/find \\;x", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/sbin/find", NULL, "\\;x", NULL, false); log_info("/* encoded semicolon */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/bin/find \\073", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/bin/find", NULL, ";", NULL, false); log_info("/* quoted semicolon */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/bin/find \";\"", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/bin/find", NULL, ";", NULL, false); log_info("/* quoted semicolon with following arg */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/sbin/find \";\" /x", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/sbin/find", NULL, ";", "/x", false); log_info("/* spaces in the filename */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "\"/PATH WITH SPACES/daemon\" -1 -2", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false); log_info("/* spaces in the filename, no args */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "\"/PATH WITH SPACES/daemon -1 -2\"", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/PATH WITH SPACES/daemon -1 -2", NULL, NULL, NULL, false); log_info("/* spaces in the filename, everything quoted */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false); log_info("/* escaped spaces in the filename */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false); log_info("/* escaped spaces in the filename (2) */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false); for (ccc = "abfnrtv\\\'\"x"; *ccc; ccc++) { /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */ char path[] = "/path\\X"; path[sizeof(path) - 2] = *ccc; log_info("/* invalid character: \\%c */", *ccc); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, path, &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); } log_info("/* valid character: \\s */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "/path\\s", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/path ", NULL, NULL, NULL, false); log_info("/* quoted backslashes */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/bin/grep '\\w+\\K'", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false); log_info("/* trailing backslash: \\ */"); /* backslash is invalid */ r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "/path\\", &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); log_info("/* missing ending ' */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "/path 'foo", &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); log_info("/* missing ending ' with trailing backslash */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "/path 'foo\\", &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); log_info("/* invalid space between modifiers */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "- /path", &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); log_info("/* only modifiers, no path */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "-", &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); log_info("/* empty argument, reset */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "", &c, u); assert_se(r == 0); assert_se(c == NULL); exec_command_free_list(c); unit_free(u); manager_free(m); } #define env_file_1 \ "a=a\n" \ "b=b\\\n" \ "c\n" \ "d=d\\\n" \ "e\\\n" \ "f\n" \ "g=g\\ \n" \ "h=h\n" \ "i=i\\" #define env_file_2 \ "a=a\\\n" #define env_file_3 \ "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \ "#--nouser-config \\\n" \ "normal=line" #define env_file_4 \ "# Generated\n" \ "\n" \ "HWMON_MODULES=\"coretemp f71882fg\"\n" \ "\n" \ "# For compatibility reasons\n" \ "\n" \ "MODULE_0=coretemp\n" \ "MODULE_1=f71882fg" #define env_file_5 \ "a=\n" \ "b=" static void test_load_env_file_1(void) { _cleanup_strv_free_ char **data = NULL; int r; char name[] = "/tmp/test-load-env-file.XXXXXX"; _cleanup_close_ int fd; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1)); r = load_env_file(NULL, name, NULL, &data); assert_se(r == 0); assert_se(streq(data[0], "a=a")); assert_se(streq(data[1], "b=bc")); assert_se(streq(data[2], "d=def")); assert_se(streq(data[3], "g=g ")); assert_se(streq(data[4], "h=h")); assert_se(streq(data[5], "i=i")); assert_se(data[6] == NULL); unlink(name); } static void test_load_env_file_2(void) { _cleanup_strv_free_ char **data = NULL; int r; char name[] = "/tmp/test-load-env-file.XXXXXX"; _cleanup_close_ int fd; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2)); r = load_env_file(NULL, name, NULL, &data); assert_se(r == 0); assert_se(streq(data[0], "a=a")); assert_se(data[1] == NULL); unlink(name); } static void test_load_env_file_3(void) { _cleanup_strv_free_ char **data = NULL; int r; char name[] = "/tmp/test-load-env-file.XXXXXX"; _cleanup_close_ int fd; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3)); r = load_env_file(NULL, name, NULL, &data); assert_se(r == 0); assert_se(data == NULL); unlink(name); } static void test_load_env_file_4(void) { _cleanup_strv_free_ char **data = NULL; char name[] = "/tmp/test-load-env-file.XXXXXX"; _cleanup_close_ int fd; int r; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4)); r = load_env_file(NULL, name, NULL, &data); assert_se(r == 0); assert_se(streq(data[0], "HWMON_MODULES=coretemp f71882fg")); assert_se(streq(data[1], "MODULE_0=coretemp")); assert_se(streq(data[2], "MODULE_1=f71882fg")); assert_se(data[3] == NULL); unlink(name); } static void test_load_env_file_5(void) { _cleanup_strv_free_ char **data = NULL; int r; char name[] = "/tmp/test-load-env-file.XXXXXX"; _cleanup_close_ int fd; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(write(fd, env_file_5, sizeof(env_file_5)) == sizeof(env_file_5)); r = load_env_file(NULL, name, NULL, &data); assert_se(r == 0); assert_se(streq(data[0], "a=")); assert_se(streq(data[1], "b=")); assert_se(data[2] == NULL); unlink(name); } static void test_install_printf(void) { char name[] = "name.service", path[] = "/run/systemd/system/name.service"; UnitFileInstallInfo i = { .name = name, .path = path, }; UnitFileInstallInfo i2 = { .name= name, .path = path, }; char name3[] = "name@inst.service", path3[] = "/run/systemd/system/name.service"; UnitFileInstallInfo i3 = { .name = name3, .path = path3, }; UnitFileInstallInfo i4 = { .name = name3, .path = path3, }; _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL; assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid); assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid); assert_se((host = gethostname_malloc())); assert_se((user = getusername_malloc())); assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0); #define expect(src, pattern, result) \ do { \ _cleanup_free_ char *t = NULL; \ _cleanup_free_ char \ *d1 = strdup(i.name), \ *d2 = strdup(i.path); \ assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \ memzero(i.name, strlen(i.name)); \ memzero(i.path, strlen(i.path)); \ assert_se(d1 && d2); \ if (result) { \ printf("%s\n", t); \ assert_se(streq(t, result)); \ } else assert_se(t == NULL); \ strcpy(i.name, d1); \ strcpy(i.path, d2); \ } while(false) expect(i, "%n", "name.service"); expect(i, "%N", "name"); expect(i, "%p", "name"); expect(i, "%i", ""); expect(i, "%u", user); expect(i, "%U", uid); expect(i, "%m", mid); expect(i, "%b", bid); expect(i, "%H", host); expect(i2, "%u", user); expect(i2, "%U", uid); expect(i3, "%n", "name@inst.service"); expect(i3, "%N", "name@inst"); expect(i3, "%p", "name"); expect(i3, "%u", user); expect(i3, "%U", uid); expect(i3, "%m", mid); expect(i3, "%b", bid); expect(i3, "%H", host); expect(i4, "%u", user); expect(i4, "%U", uid); } static uint64_t make_cap(int cap) { return ((uint64_t) 1ULL << (uint64_t) cap); } static void test_config_parse_capability_set(void) { /* int config_parse_capability_set( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) */ int r; uint64_t capability_bounding_set = 0; r = config_parse_capability_set(NULL, "fake", 1, "section", 1, "CapabilityBoundingSet", 0, "CAP_NET_RAW", &capability_bounding_set, NULL); assert_se(r >= 0); assert_se(capability_bounding_set == make_cap(CAP_NET_RAW)); r = config_parse_capability_set(NULL, "fake", 1, "section", 1, "CapabilityBoundingSet", 0, "CAP_NET_ADMIN", &capability_bounding_set, NULL); assert_se(r >= 0); assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN))); r = config_parse_capability_set(NULL, "fake", 1, "section", 1, "CapabilityBoundingSet", 0, "", &capability_bounding_set, NULL); assert_se(r >= 0); assert_se(capability_bounding_set == UINT64_C(0)); r = config_parse_capability_set(NULL, "fake", 1, "section", 1, "CapabilityBoundingSet", 0, "~", &capability_bounding_set, NULL); assert_se(r >= 0); assert_se(cap_test_all(capability_bounding_set)); capability_bounding_set = 0; r = config_parse_capability_set(NULL, "fake", 1, "section", 1, "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage", &capability_bounding_set, NULL); assert_se(r >= 0); assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN))); } static void test_config_parse_rlimit(void) { struct rlimit * rl[_RLIMIT_MAX] = {}; assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0); assert_se(rl[RLIMIT_NOFILE]); assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55); assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0); assert_se(rl[RLIMIT_NOFILE]); assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55); assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0); assert_se(rl[RLIMIT_NOFILE]); assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY); assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0); assert_se(rl[RLIMIT_NOFILE]); assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY); assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max); rl[RLIMIT_NOFILE]->rlim_cur = 10; rl[RLIMIT_NOFILE]->rlim_max = 20; /* Invalid values don't change rl */ assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0); assert_se(rl[RLIMIT_NOFILE]); assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10); assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0); assert_se(rl[RLIMIT_NOFILE]); assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10); assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0); assert_se(rl[RLIMIT_NOFILE]); assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10); assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0); assert_se(rl[RLIMIT_NOFILE]); assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10); assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20); rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0); assert_se(rl[RLIMIT_CPU]); assert_se(rl[RLIMIT_CPU]->rlim_cur == 56); assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0); assert_se(rl[RLIMIT_CPU]); assert_se(rl[RLIMIT_CPU]->rlim_cur == 57); assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0); assert_se(rl[RLIMIT_CPU]); assert_se(rl[RLIMIT_CPU]->rlim_cur == 40); assert_se(rl[RLIMIT_CPU]->rlim_max == 60); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0); assert_se(rl[RLIMIT_CPU]); assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY); assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0); assert_se(rl[RLIMIT_CPU]); assert_se(rl[RLIMIT_CPU]->rlim_cur == 2); assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max); rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0); assert_se(rl[RLIMIT_RTTIME]); assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58); assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0); assert_se(rl[RLIMIT_RTTIME]); assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58); assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0); assert_se(rl[RLIMIT_RTTIME]); assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC); assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0); assert_se(rl[RLIMIT_RTTIME]); assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC); assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0); assert_se(rl[RLIMIT_RTTIME]); assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY); assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0); assert_se(rl[RLIMIT_RTTIME]); assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY); assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0); assert_se(rl[RLIMIT_RTTIME]); assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC); assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]); } static void test_config_parse_pass_environ(void) { /* int config_parse_pass_environ( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) */ int r; _cleanup_strv_free_ char **passenv = NULL; r = config_parse_pass_environ(NULL, "fake", 1, "section", 1, "PassEnvironment", 0, "A B", &passenv, NULL); assert_se(r >= 0); assert_se(strv_length(passenv) == 2); assert_se(streq(passenv[0], "A")); assert_se(streq(passenv[1], "B")); r = config_parse_pass_environ(NULL, "fake", 1, "section", 1, "PassEnvironment", 0, "", &passenv, NULL); assert_se(r >= 0); assert_se(strv_isempty(passenv)); r = config_parse_pass_environ(NULL, "fake", 1, "section", 1, "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\", &passenv, NULL); assert_se(r >= 0); assert_se(strv_length(passenv) == 1); assert_se(streq(passenv[0], "normal_name")); } int main(int argc, char *argv[]) { int r; log_parse_environment(); log_open(); r = test_unit_file_get_set(); test_config_parse_exec(); test_config_parse_capability_set(); test_config_parse_rlimit(); test_config_parse_pass_environ(); test_load_env_file_1(); test_load_env_file_2(); test_load_env_file_3(); test_load_env_file_4(); test_load_env_file_5(); TEST_REQ_RUNNING_SYSTEMD(test_install_printf()); return r; } systemd-229/src/test/test-unit-name.c000066400000000000000000000474411265713322000176570ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering Copyright 2013 Zbigniew Jędrzejewski-Szmek Copyright 2014 Ronny Chevalier systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "glob-util.h" #include "hostname-util.h" #include "macro.h" #include "manager.h" #include "path-util.h" #include "specifier.h" #include "string-util.h" #include "test-helper.h" #include "unit-name.h" #include "unit-printf.h" #include "unit.h" #include "user-util.h" #include "util.h" static void test_unit_name_is_valid(void) { assert_se(unit_name_is_valid("foo.service", UNIT_NAME_ANY)); assert_se(unit_name_is_valid("foo.service", UNIT_NAME_PLAIN)); assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_INSTANCE)); assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_TEMPLATE)); assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)); assert_se(unit_name_is_valid("foo@bar.service", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid("foo@bar.service", UNIT_NAME_PLAIN)); assert_se(unit_name_is_valid("foo@bar.service", UNIT_NAME_INSTANCE)); assert_se(!unit_name_is_valid("foo@bar.service", UNIT_NAME_TEMPLATE)); assert_se(unit_name_is_valid("foo@bar.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)); assert_se(unit_name_is_valid("foo@.service", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid("foo@.service", UNIT_NAME_PLAIN)); assert_se(!unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE)); assert_se(unit_name_is_valid("foo@.service", UNIT_NAME_TEMPLATE)); assert_se(unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)); assert_se(!unit_name_is_valid(".service", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid("", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid("foo.waldo", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid("@.service", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid("@piep.service", UNIT_NAME_ANY)); } static void test_unit_name_replace_instance_one(const char *pattern, const char *repl, const char *expected, int ret) { _cleanup_free_ char *t = NULL; assert_se(unit_name_replace_instance(pattern, repl, &t) == ret); puts(strna(t)); assert_se(streq_ptr(t, expected)); } static void test_unit_name_replace_instance(void) { puts("-------------------------------------------------"); test_unit_name_replace_instance_one("foo@.service", "waldo", "foo@waldo.service", 0); test_unit_name_replace_instance_one("foo@xyz.service", "waldo", "foo@waldo.service", 0); test_unit_name_replace_instance_one("xyz", "waldo", NULL, -EINVAL); test_unit_name_replace_instance_one("", "waldo", NULL, -EINVAL); test_unit_name_replace_instance_one("foo.service", "waldo", NULL, -EINVAL); test_unit_name_replace_instance_one(".service", "waldo", NULL, -EINVAL); test_unit_name_replace_instance_one("foo@", "waldo", NULL, -EINVAL); test_unit_name_replace_instance_one("@bar", "waldo", NULL, -EINVAL); } static void test_unit_name_from_path_one(const char *path, const char *suffix, const char *expected, int ret) { _cleanup_free_ char *t = NULL; assert_se(unit_name_from_path(path, suffix, &t) == ret); puts(strna(t)); assert_se(streq_ptr(t, expected)); if (t) { _cleanup_free_ char *k = NULL; assert_se(unit_name_to_path(t, &k) == 0); puts(strna(k)); assert_se(path_equal(k, isempty(path) ? "/" : path)); } } static void test_unit_name_from_path(void) { puts("-------------------------------------------------"); test_unit_name_from_path_one("/waldo", ".mount", "waldo.mount", 0); test_unit_name_from_path_one("/waldo/quuix", ".mount", "waldo-quuix.mount", 0); test_unit_name_from_path_one("/waldo/quuix/", ".mount", "waldo-quuix.mount", 0); test_unit_name_from_path_one("", ".mount", "-.mount", 0); test_unit_name_from_path_one("/", ".mount", "-.mount", 0); test_unit_name_from_path_one("///", ".mount", "-.mount", 0); test_unit_name_from_path_one("/foo/../bar", ".mount", NULL, -EINVAL); test_unit_name_from_path_one("/foo/./bar", ".mount", NULL, -EINVAL); } static void test_unit_name_from_path_instance_one(const char *pattern, const char *path, const char *suffix, const char *expected, int ret) { _cleanup_free_ char *t = NULL; assert_se(unit_name_from_path_instance(pattern, path, suffix, &t) == ret); puts(strna(t)); assert_se(streq_ptr(t, expected)); if (t) { _cleanup_free_ char *k = NULL, *v = NULL; assert_se(unit_name_to_instance(t, &k) > 0); assert_se(unit_name_path_unescape(k, &v) == 0); assert_se(path_equal(v, isempty(path) ? "/" : path)); } } static void test_unit_name_from_path_instance(void) { puts("-------------------------------------------------"); test_unit_name_from_path_instance_one("waldo", "/waldo", ".mount", "waldo@waldo.mount", 0); test_unit_name_from_path_instance_one("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.mount", 0); test_unit_name_from_path_instance_one("waldo", "/", ".mount", "waldo@-.mount", 0); test_unit_name_from_path_instance_one("waldo", "", ".mount", "waldo@-.mount", 0); test_unit_name_from_path_instance_one("waldo", "///", ".mount", "waldo@-.mount", 0); test_unit_name_from_path_instance_one("waldo", "..", ".mount", NULL, -EINVAL); test_unit_name_from_path_instance_one("waldo", "/foo", ".waldi", NULL, -EINVAL); test_unit_name_from_path_instance_one("wa--ldo", "/--", ".mount", "wa--ldo@\\x2d\\x2d.mount", 0); } static void test_unit_name_to_path_one(const char *unit, const char *path, int ret) { _cleanup_free_ char *p = NULL; assert_se(unit_name_to_path(unit, &p) == ret); assert_se(streq_ptr(path, p)); } static void test_unit_name_to_path(void) { test_unit_name_to_path_one("home.mount", "/home", 0); test_unit_name_to_path_one("home-lennart.mount", "/home/lennart", 0); test_unit_name_to_path_one("home-lennart-.mount", NULL, -EINVAL); test_unit_name_to_path_one("-home-lennart.mount", NULL, -EINVAL); test_unit_name_to_path_one("-home--lennart.mount", NULL, -EINVAL); test_unit_name_to_path_one("home-..-lennart.mount", NULL, -EINVAL); test_unit_name_to_path_one("", NULL, -EINVAL); test_unit_name_to_path_one("home/foo", NULL, -EINVAL); } static void test_unit_name_mangle_one(UnitNameMangle allow_globs, const char *pattern, const char *expect, int ret) { _cleanup_free_ char *t = NULL; assert_se(unit_name_mangle(pattern, allow_globs, &t) == ret); puts(strna(t)); assert_se(streq_ptr(t, expect)); if (t) { _cleanup_free_ char *k = NULL; assert_se(unit_name_is_valid(t, UNIT_NAME_ANY) || (allow_globs == UNIT_NAME_GLOB && string_is_glob(t))); assert_se(unit_name_mangle(t, allow_globs, &k) == 0); assert_se(streq_ptr(t, k)); } } static void test_unit_name_mangle(void) { puts("-------------------------------------------------"); test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "foo.service", "foo.service", 0); test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "/home", "home.mount", 1); test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "/dev/sda", "dev-sda.device", 1); test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "üxknürz.service", "\\xc3\\xbcxkn\\xc3\\xbcrz.service", 1); test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "foobar-meh...waldi.service", "foobar-meh...waldi.service", 0); test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "_____####----.....service", "_____\\x23\\x23\\x23\\x23----.....service", 1); test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "_____##@;;;,,,##----.....service", "_____\\x23\\x23@\\x3b\\x3b\\x3b\\x2c\\x2c\\x2c\\x23\\x23----.....service", 1); test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "xxx@@@@/////\\\\\\\\\\yyy.service", "xxx@@@@-----\\\\\\\\\\yyy.service", 1); test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "", NULL, -EINVAL); test_unit_name_mangle_one(UNIT_NAME_GLOB, "foo.service", "foo.service", 0); test_unit_name_mangle_one(UNIT_NAME_GLOB, "foo", "foo.service", 1); test_unit_name_mangle_one(UNIT_NAME_GLOB, "foo*", "foo*", 0); test_unit_name_mangle_one(UNIT_NAME_GLOB, "ü*", "\\xc3\\xbc*", 1); } static int test_unit_printf(void) { Manager *m = NULL; Unit *u, *u2; int r; _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL, *shell = NULL, *home = NULL; assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid); assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid); assert_se(host = gethostname_malloc()); assert_se(user = getusername_malloc()); assert_se(asprintf(&uid, UID_FMT, getuid())); assert_se(get_home_dir(&home) >= 0); assert_se(get_shell(&shell) >= 0); r = manager_new(MANAGER_USER, true, &m); if (r == -EPERM || r == -EACCES || r == -EADDRINUSE) { puts("manager_new: Permission denied. Skipping test."); return EXIT_TEST_SKIP; } assert_se(r == 0); #define expect(unit, pattern, expected) \ { \ char *e; \ _cleanup_free_ char *t = NULL; \ assert_se(unit_full_printf(unit, pattern, &t) >= 0); \ printf("result: %s\nexpect: %s\n", t, expected); \ if ((e = endswith(expected, "*"))) \ assert_se(strncmp(t, e, e-expected)); \ else \ assert_se(streq(t, expected)); \ } assert_se(setenv("XDG_RUNTIME_DIR", "/run/user/1/", 1) == 0); assert_se(u = unit_new(m, sizeof(Service))); assert_se(unit_add_name(u, "blah.service") == 0); assert_se(unit_add_name(u, "blah.service") == 0); /* general tests */ expect(u, "%%", "%"); expect(u, "%%s", "%s"); expect(u, "%", ""); // REALLY? /* normal unit */ expect(u, "%n", "blah.service"); expect(u, "%f", "/blah"); expect(u, "%N", "blah"); expect(u, "%p", "blah"); expect(u, "%P", "blah"); expect(u, "%i", ""); expect(u, "%u", user); expect(u, "%U", uid); expect(u, "%h", home); expect(u, "%m", mid); expect(u, "%b", bid); expect(u, "%H", host); expect(u, "%t", "/run/user/*"); /* templated */ assert_se(u2 = unit_new(m, sizeof(Service))); assert_se(unit_add_name(u2, "blah@foo-foo.service") == 0); assert_se(unit_add_name(u2, "blah@foo-foo.service") == 0); expect(u2, "%n", "blah@foo-foo.service"); expect(u2, "%N", "blah@foo-foo"); expect(u2, "%f", "/foo/foo"); expect(u2, "%p", "blah"); expect(u2, "%P", "blah"); expect(u2, "%i", "foo-foo"); expect(u2, "%I", "foo/foo"); expect(u2, "%u", user); expect(u2, "%U", uid); expect(u2, "%h", home); expect(u2, "%m", mid); expect(u2, "%b", bid); expect(u2, "%H", host); expect(u2, "%t", "/run/user/*"); manager_free(m); #undef expect return 0; } static void test_unit_instance_is_valid(void) { assert_se(unit_instance_is_valid("fooBar")); assert_se(unit_instance_is_valid("foo-bar")); assert_se(unit_instance_is_valid("foo.stUff")); assert_se(unit_instance_is_valid("fOo123.stuff")); assert_se(unit_instance_is_valid("@f_oo123.Stuff")); assert_se(!unit_instance_is_valid("$¢£")); assert_se(!unit_instance_is_valid("")); assert_se(!unit_instance_is_valid("foo bar")); assert_se(!unit_instance_is_valid("foo/bar")); } static void test_unit_prefix_is_valid(void) { assert_se(unit_prefix_is_valid("fooBar")); assert_se(unit_prefix_is_valid("foo-bar")); assert_se(unit_prefix_is_valid("foo.stUff")); assert_se(unit_prefix_is_valid("fOo123.stuff")); assert_se(unit_prefix_is_valid("foo123.Stuff")); assert_se(!unit_prefix_is_valid("$¢£")); assert_se(!unit_prefix_is_valid("")); assert_se(!unit_prefix_is_valid("foo bar")); assert_se(!unit_prefix_is_valid("foo/bar")); assert_se(!unit_prefix_is_valid("@foo-bar")); } static void test_unit_name_change_suffix(void) { char *t; assert_se(unit_name_change_suffix("foo.mount", ".service", &t) == 0); assert_se(streq(t, "foo.service")); free(t); assert_se(unit_name_change_suffix("foo@stuff.service", ".socket", &t) == 0); assert_se(streq(t, "foo@stuff.socket")); free(t); } static void test_unit_name_build(void) { char *t; assert_se(unit_name_build("foo", "bar", ".service", &t) == 0); assert_se(streq(t, "foo@bar.service")); free(t); assert_se(unit_name_build("fo0-stUff_b", "bar", ".mount", &t) == 0); assert_se(streq(t, "fo0-stUff_b@bar.mount")); free(t); assert_se(unit_name_build("foo", NULL, ".service", &t) == 0); assert_se(streq(t, "foo.service")); free(t); } static void test_slice_name_is_valid(void) { assert_se(slice_name_is_valid("-.slice")); assert_se(slice_name_is_valid("foo.slice")); assert_se(slice_name_is_valid("foo-bar.slice")); assert_se(slice_name_is_valid("foo-bar-baz.slice")); assert_se(!slice_name_is_valid("-foo-bar-baz.slice")); assert_se(!slice_name_is_valid("foo-bar-baz-.slice")); assert_se(!slice_name_is_valid("-foo-bar-baz-.slice")); assert_se(!slice_name_is_valid("foo-bar--baz.slice")); assert_se(!slice_name_is_valid("foo--bar--baz.slice")); assert_se(!slice_name_is_valid(".slice")); assert_se(!slice_name_is_valid("")); assert_se(!slice_name_is_valid("foo.service")); } static void test_build_subslice(void) { char *a; char *b; assert_se(slice_build_subslice("-.slice", "foo", &a) >= 0); assert_se(slice_build_subslice(a, "bar", &b) >= 0); free(a); assert_se(slice_build_subslice(b, "barfoo", &a) >= 0); free(b); assert_se(slice_build_subslice(a, "foobar", &b) >= 0); free(a); assert_se(streq(b, "foo-bar-barfoo-foobar.slice")); free(b); assert_se(slice_build_subslice("foo.service", "bar", &a) < 0); assert_se(slice_build_subslice("foo", "bar", &a) < 0); } static void test_build_parent_slice_one(const char *name, const char *expect, int ret) { _cleanup_free_ char *s = NULL; assert_se(slice_build_parent_slice(name, &s) == ret); assert_se(streq_ptr(s, expect)); } static void test_build_parent_slice(void) { test_build_parent_slice_one("-.slice", NULL, 0); test_build_parent_slice_one("foo.slice", "-.slice", 1); test_build_parent_slice_one("foo-bar.slice", "foo.slice", 1); test_build_parent_slice_one("foo-bar-baz.slice", "foo-bar.slice", 1); test_build_parent_slice_one("foo-bar--baz.slice", NULL, -EINVAL); test_build_parent_slice_one("-foo-bar.slice", NULL, -EINVAL); test_build_parent_slice_one("foo-bar-.slice", NULL, -EINVAL); test_build_parent_slice_one("foo-bar.service", NULL, -EINVAL); test_build_parent_slice_one(".slice", NULL, -EINVAL); } static void test_unit_name_to_instance(void) { char *instance; int r; r = unit_name_to_instance("foo@bar.service", &instance); assert_se(r >= 0); assert_se(streq(instance, "bar")); free(instance); r = unit_name_to_instance("foo@.service", &instance); assert_se(r >= 0); assert_se(streq(instance, "")); free(instance); r = unit_name_to_instance("fo0-stUff_b@b.service", &instance); assert_se(r >= 0); assert_se(streq(instance, "b")); free(instance); r = unit_name_to_instance("foo.service", &instance); assert_se(r == 0); assert_se(!instance); r = unit_name_to_instance("fooj@unk", &instance); assert_se(r < 0); r = unit_name_to_instance("foo@", &instance); assert_se(r < 0); } static void test_unit_name_escape(void) { _cleanup_free_ char *r; r = unit_name_escape("ab+-c.a/bc@foo.service"); assert_se(r); assert_se(streq(r, "ab\\x2b\\x2dc.a-bc\\x40foo.service")); } static void test_u_n_t_one(const char *name, const char *expected, int ret) { _cleanup_free_ char *f = NULL; assert_se(unit_name_template(name, &f) == ret); printf("got: %s, expected: %s\n", strna(f), strna(expected)); assert_se(streq_ptr(f, expected)); } static void test_unit_name_template(void) { test_u_n_t_one("foo@bar.service", "foo@.service", 0); test_u_n_t_one("foo.mount", NULL, -EINVAL); } static void test_unit_name_path_unescape_one(const char *name, const char *path, int ret) { _cleanup_free_ char *p = NULL; assert_se(unit_name_path_unescape(name, &p) == ret); assert_se(streq_ptr(path, p)); } static void test_unit_name_path_unescape(void) { test_unit_name_path_unescape_one("foo", "/foo", 0); test_unit_name_path_unescape_one("foo-bar", "/foo/bar", 0); test_unit_name_path_unescape_one("foo-.bar", "/foo/.bar", 0); test_unit_name_path_unescape_one("foo-bar-baz", "/foo/bar/baz", 0); test_unit_name_path_unescape_one("-", "/", 0); test_unit_name_path_unescape_one("--", NULL, -EINVAL); test_unit_name_path_unescape_one("-foo-bar", NULL, -EINVAL); test_unit_name_path_unescape_one("foo--bar", NULL, -EINVAL); test_unit_name_path_unescape_one("foo-bar-", NULL, -EINVAL); test_unit_name_path_unescape_one(".-bar", NULL, -EINVAL); test_unit_name_path_unescape_one("foo-..", NULL, -EINVAL); test_unit_name_path_unescape_one("", NULL, -EINVAL); } int main(int argc, char* argv[]) { int rc = 0; test_unit_name_is_valid(); test_unit_name_replace_instance(); test_unit_name_from_path(); test_unit_name_from_path_instance(); test_unit_name_mangle(); test_unit_name_to_path(); TEST_REQ_RUNNING_SYSTEMD(rc = test_unit_printf()); test_unit_instance_is_valid(); test_unit_prefix_is_valid(); test_unit_name_change_suffix(); test_unit_name_build(); test_slice_name_is_valid(); test_build_subslice(); test_build_parent_slice(); test_unit_name_to_instance(); test_unit_name_escape(); test_unit_name_template(); test_unit_name_path_unescape(); return rc; } systemd-229/src/test/test-user-util.c000066400000000000000000000030721265713322000177030ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2015 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "macro.h" #include "string-util.h" #include "user-util.h" #include "util.h" static void test_uid_to_name_one(uid_t uid, const char *name) { _cleanup_free_ char *t = NULL; assert_se(t = uid_to_name(uid)); assert_se(streq_ptr(t, name)); } static void test_gid_to_name_one(gid_t gid, const char *name) { _cleanup_free_ char *t = NULL; assert_se(t = gid_to_name(gid)); assert_se(streq_ptr(t, name)); } int main(int argc, char*argv[]) { test_uid_to_name_one(0, "root"); test_uid_to_name_one(0xFFFF, "65535"); test_uid_to_name_one(0xFFFFFFFF, "4294967295"); test_gid_to_name_one(0, "root"); test_gid_to_name_one(TTY_GID, "tty"); test_gid_to_name_one(0xFFFF, "65535"); test_gid_to_name_one(0xFFFFFFFF, "4294967295"); return 0; } systemd-229/src/test/test-utf8.c000066400000000000000000000073201265713322000166400ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Dave Reisner systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "string-util.h" #include "utf8.h" #include "util.h" static void test_utf8_is_printable(void) { assert_se(utf8_is_printable("ascii is valid\tunicode", 22)); assert_se(utf8_is_printable("\342\204\242", 3)); assert_se(!utf8_is_printable("\341\204", 2)); assert_se(utf8_is_printable("ąę", 4)); } static void test_utf8_is_valid(void) { assert_se(utf8_is_valid("ascii is valid unicode")); assert_se(utf8_is_valid("\342\204\242")); assert_se(!utf8_is_valid("\341\204")); } static void test_ascii_is_valid(void) { assert_se(ascii_is_valid("alsdjf\t\vbarr\nba z")); assert_se(!ascii_is_valid("\342\204\242")); assert_se(!ascii_is_valid("\341\204")); } static void test_utf8_encoded_valid_unichar(void) { assert_se(utf8_encoded_valid_unichar("\342\204\242") == 3); assert_se(utf8_encoded_valid_unichar("\302\256") == 2); assert_se(utf8_encoded_valid_unichar("a") == 1); assert_se(utf8_encoded_valid_unichar("\341\204") < 0); assert_se(utf8_encoded_valid_unichar("\341\204\341\204") < 0); } static void test_utf8_escaping(void) { _cleanup_free_ char *p1, *p2, *p3; p1 = utf8_escape_invalid("goo goo goo"); puts(p1); assert_se(utf8_is_valid(p1)); p2 = utf8_escape_invalid("\341\204\341\204"); puts(p2); assert_se(utf8_is_valid(p2)); p3 = utf8_escape_invalid("\341\204"); puts(p3); assert_se(utf8_is_valid(p3)); } static void test_utf8_escaping_printable(void) { _cleanup_free_ char *p1, *p2, *p3, *p4, *p5, *p6; p1 = utf8_escape_non_printable("goo goo goo"); puts(p1); assert_se(utf8_is_valid(p1)); p2 = utf8_escape_non_printable("\341\204\341\204"); puts(p2); assert_se(utf8_is_valid(p2)); p3 = utf8_escape_non_printable("\341\204"); puts(p3); assert_se(utf8_is_valid(p3)); p4 = utf8_escape_non_printable("ąę\n가너도루\n1234\n\341\204\341\204\n\001 \019\20\a"); puts(p4); assert_se(utf8_is_valid(p4)); p5 = utf8_escape_non_printable("\001 \019\20\a"); puts(p5); assert_se(utf8_is_valid(p5)); p6 = utf8_escape_non_printable("\xef\xbf\x30\x13"); puts(p6); assert_se(utf8_is_valid(p6)); } static void test_utf16_to_utf8(void) { char *a = NULL; const uint16_t utf16[] = { htole16('a'), htole16(0xd800), htole16('b'), htole16(0xdc00), htole16('c'), htole16(0xd801), htole16(0xdc37) }; const char utf8[] = { 'a', 'b', 'c', 0xf0, 0x90, 0x90, 0xb7, 0 }; a = utf16_to_utf8(utf16, 14); assert_se(a); assert_se(streq(a, utf8)); free(a); } int main(int argc, char *argv[]) { test_utf8_is_valid(); test_utf8_is_printable(); test_ascii_is_valid(); test_utf8_encoded_valid_unichar(); test_utf8_escaping(); test_utf8_escaping_printable(); test_utf16_to_utf8(); return 0; } systemd-229/src/test/test-util.c000066400000000000000000001615741265713322000167430ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2013 Thomas H.P. Andersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "conf-parser.h" #include "cpu-set-util.h" #include "def.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" #include "fstab-util.h" #include "glob-util.h" #include "hexdecoct.h" #include "io-util.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" #include "process-util.h" #include "rm-rf.h" #include "signal-util.h" #include "special.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" #include "user-util.h" #include "util.h" #include "virt.h" #include "web-util.h" #include "xattr-util.h" static void test_streq_ptr(void) { assert_se(streq_ptr(NULL, NULL)); assert_se(!streq_ptr("abc", "cdef")); } static void test_align_power2(void) { unsigned long i, p2; assert_se(ALIGN_POWER2(0) == 0); assert_se(ALIGN_POWER2(1) == 1); assert_se(ALIGN_POWER2(2) == 2); assert_se(ALIGN_POWER2(3) == 4); assert_se(ALIGN_POWER2(12) == 16); assert_se(ALIGN_POWER2(ULONG_MAX) == 0); assert_se(ALIGN_POWER2(ULONG_MAX - 1) == 0); assert_se(ALIGN_POWER2(ULONG_MAX - 1024) == 0); assert_se(ALIGN_POWER2(ULONG_MAX / 2) == ULONG_MAX / 2 + 1); assert_se(ALIGN_POWER2(ULONG_MAX + 1) == 0); for (i = 1; i < 131071; ++i) { for (p2 = 1; p2 < i; p2 <<= 1) /* empty */ ; assert_se(ALIGN_POWER2(i) == p2); } for (i = ULONG_MAX - 1024; i < ULONG_MAX; ++i) { for (p2 = 1; p2 && p2 < i; p2 <<= 1) /* empty */ ; assert_se(ALIGN_POWER2(i) == p2); } } static void test_max(void) { static const struct { int a; int b[CONST_MAX(10, 100)]; } val1 = { .a = CONST_MAX(10, 100), }; int d = 0; assert_cc(sizeof(val1.b) == sizeof(int) * 100); /* CONST_MAX returns (void) instead of a value if the passed arguments * are not of the same type or not constant expressions. */ assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 10)), int)); assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 1U)), void)); assert_se(val1.a == 100); assert_se(MAX(++d, 0) == 1); assert_se(d == 1); assert_cc(MAXSIZE(char[3], uint16_t) == 3); assert_cc(MAXSIZE(char[3], uint32_t) == 4); assert_cc(MAXSIZE(char, long) == sizeof(long)); assert_se(MAX(-5, 5) == 5); assert_se(MAX(5, 5) == 5); assert_se(MAX(MAX(1, MAX(2, MAX(3, 4))), 5) == 5); assert_se(MAX(MAX(1, MAX(2, MAX(3, 2))), 1) == 3); assert_se(MAX(MIN(1, MIN(2, MIN(3, 4))), 5) == 5); assert_se(MAX(MAX(1, MIN(2, MIN(3, 2))), 1) == 2); assert_se(LESS_BY(8, 4) == 4); assert_se(LESS_BY(8, 8) == 0); assert_se(LESS_BY(4, 8) == 0); assert_se(LESS_BY(16, LESS_BY(8, 4)) == 12); assert_se(LESS_BY(4, LESS_BY(8, 4)) == 0); assert_se(CLAMP(-5, 0, 1) == 0); assert_se(CLAMP(5, 0, 1) == 1); assert_se(CLAMP(5, -10, 1) == 1); assert_se(CLAMP(5, -10, 10) == 5); assert_se(CLAMP(CLAMP(0, -10, 10), CLAMP(-5, 10, 20), CLAMP(100, -5, 20)) == 10); } static void test_container_of(void) { struct mytype { uint8_t pad1[3]; uint64_t v1; uint8_t pad2[2]; uint32_t v2; } _packed_ myval = { }; assert_cc(sizeof(myval) == 17); assert_se(container_of(&myval.v1, struct mytype, v1) == &myval); assert_se(container_of(&myval.v2, struct mytype, v2) == &myval); assert_se(container_of(&container_of(&myval.v2, struct mytype, v2)->v1, struct mytype, v1) == &myval); } static void test_alloca(void) { static const uint8_t zero[997] = { }; char *t; t = alloca_align(17, 512); assert_se(!((uintptr_t)t & 0xff)); memzero(t, 17); t = alloca0_align(997, 1024); assert_se(!((uintptr_t)t & 0x1ff)); assert_se(!memcmp(t, zero, 997)); } static void test_div_round_up(void) { int div; /* basic tests */ assert_se(DIV_ROUND_UP(0, 8) == 0); assert_se(DIV_ROUND_UP(1, 8) == 1); assert_se(DIV_ROUND_UP(8, 8) == 1); assert_se(DIV_ROUND_UP(12, 8) == 2); assert_se(DIV_ROUND_UP(16, 8) == 2); /* test multiple evaluation */ div = 0; assert_se(DIV_ROUND_UP(div++, 8) == 0 && div == 1); assert_se(DIV_ROUND_UP(++div, 8) == 1 && div == 2); assert_se(DIV_ROUND_UP(8, div++) == 4 && div == 3); assert_se(DIV_ROUND_UP(8, ++div) == 2 && div == 4); /* overflow test with exact division */ assert_se(sizeof(0U) == 4); assert_se(0xfffffffaU % 10U == 0U); assert_se(0xfffffffaU / 10U == 429496729U); assert_se(DIV_ROUND_UP(0xfffffffaU, 10U) == 429496729U); assert_se((0xfffffffaU + 10U - 1U) / 10U == 0U); assert_se(0xfffffffaU / 10U + !!(0xfffffffaU % 10U) == 429496729U); /* overflow test with rounded division */ assert_se(0xfffffffdU % 10U == 3U); assert_se(0xfffffffdU / 10U == 429496729U); assert_se(DIV_ROUND_UP(0xfffffffdU, 10U) == 429496730U); assert_se((0xfffffffdU + 10U - 1U) / 10U == 0U); assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U); } static void test_first_word(void) { assert_se(first_word("Hello", "")); assert_se(first_word("Hello", "Hello")); assert_se(first_word("Hello world", "Hello")); assert_se(first_word("Hello\tworld", "Hello")); assert_se(first_word("Hello\nworld", "Hello")); assert_se(first_word("Hello\rworld", "Hello")); assert_se(first_word("Hello ", "Hello")); assert_se(!first_word("Hello", "Hellooo")); assert_se(!first_word("Hello", "xxxxx")); assert_se(!first_word("Hellooo", "Hello")); } static void test_close_many(void) { int fds[3]; char name0[] = "/tmp/test-close-many.XXXXXX"; char name1[] = "/tmp/test-close-many.XXXXXX"; char name2[] = "/tmp/test-close-many.XXXXXX"; fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC); fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC); fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC); close_many(fds, 2); assert_se(fcntl(fds[0], F_GETFD) == -1); assert_se(fcntl(fds[1], F_GETFD) == -1); assert_se(fcntl(fds[2], F_GETFD) >= 0); safe_close(fds[2]); unlink(name0); unlink(name1); unlink(name2); } static void test_parse_uid(void) { int r; uid_t uid; r = parse_uid("100", &uid); assert_se(r == 0); assert_se(uid == 100); r = parse_uid("65535", &uid); assert_se(r == -ENXIO); r = parse_uid("asdsdas", &uid); assert_se(r == -EINVAL); } static void test_strappend(void) { _cleanup_free_ char *t1, *t2, *t3, *t4; t1 = strappend(NULL, NULL); assert_se(streq(t1, "")); t2 = strappend(NULL, "suf"); assert_se(streq(t2, "suf")); t3 = strappend("pre", NULL); assert_se(streq(t3, "pre")); t4 = strappend("pre", "suf"); assert_se(streq(t4, "presuf")); } static void test_strstrip(void) { char *r; char input[] = " hello, waldo. "; r = strstrip(input); assert_se(streq(r, "hello, waldo.")); } static void test_delete_chars(void) { char *r; char input[] = " hello, waldo. abc"; r = delete_chars(input, WHITESPACE); assert_se(streq(r, "hello,waldo.abc")); } static void test_in_charset(void) { assert_se(in_charset("dddaaabbbcccc", "abcd")); assert_se(!in_charset("dddaaabbbcccc", "abc f")); } static void test_hexchar(void) { assert_se(hexchar(0xa) == 'a'); assert_se(hexchar(0x0) == '0'); } static void test_unhexchar(void) { assert_se(unhexchar('a') == 0xA); assert_se(unhexchar('A') == 0xA); assert_se(unhexchar('0') == 0x0); } static void test_base32hexchar(void) { assert_se(base32hexchar(0) == '0'); assert_se(base32hexchar(9) == '9'); assert_se(base32hexchar(10) == 'A'); assert_se(base32hexchar(31) == 'V'); } static void test_unbase32hexchar(void) { assert_se(unbase32hexchar('0') == 0); assert_se(unbase32hexchar('9') == 9); assert_se(unbase32hexchar('A') == 10); assert_se(unbase32hexchar('V') == 31); assert_se(unbase32hexchar('=') == -EINVAL); } static void test_base64char(void) { assert_se(base64char(0) == 'A'); assert_se(base64char(26) == 'a'); assert_se(base64char(63) == '/'); } static void test_unbase64char(void) { assert_se(unbase64char('A') == 0); assert_se(unbase64char('Z') == 25); assert_se(unbase64char('a') == 26); assert_se(unbase64char('z') == 51); assert_se(unbase64char('0') == 52); assert_se(unbase64char('9') == 61); assert_se(unbase64char('+') == 62); assert_se(unbase64char('/') == 63); assert_se(unbase64char('=') == -EINVAL); } static void test_octchar(void) { assert_se(octchar(00) == '0'); assert_se(octchar(07) == '7'); } static void test_unoctchar(void) { assert_se(unoctchar('0') == 00); assert_se(unoctchar('7') == 07); } static void test_decchar(void) { assert_se(decchar(0) == '0'); assert_se(decchar(9) == '9'); } static void test_undecchar(void) { assert_se(undecchar('0') == 0); assert_se(undecchar('9') == 9); } static void test_unhexmem(void) { const char *hex = "efa214921"; const char *hex_invalid = "efa214921o"; _cleanup_free_ char *hex2 = NULL; _cleanup_free_ void *mem = NULL; size_t len; assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0); assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL); assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL); assert_se((hex2 = hexmem(mem, len))); free(mem); assert_se(memcmp(hex, hex2, strlen(hex)) == 0); free(hex2); assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == 0); assert_se((hex2 = hexmem(mem, len))); assert_se(memcmp(hex, hex2, strlen(hex) - 1) == 0); } /* https://tools.ietf.org/html/rfc4648#section-10 */ static void test_base32hexmem(void) { char *b32; b32 = base32hexmem("", strlen(""), true); assert_se(b32); assert_se(streq(b32, "")); free(b32); b32 = base32hexmem("f", strlen("f"), true); assert_se(b32); assert_se(streq(b32, "CO======")); free(b32); b32 = base32hexmem("fo", strlen("fo"), true); assert_se(b32); assert_se(streq(b32, "CPNG====")); free(b32); b32 = base32hexmem("foo", strlen("foo"), true); assert_se(b32); assert_se(streq(b32, "CPNMU===")); free(b32); b32 = base32hexmem("foob", strlen("foob"), true); assert_se(b32); assert_se(streq(b32, "CPNMUOG=")); free(b32); b32 = base32hexmem("fooba", strlen("fooba"), true); assert_se(b32); assert_se(streq(b32, "CPNMUOJ1")); free(b32); b32 = base32hexmem("foobar", strlen("foobar"), true); assert_se(b32); assert_se(streq(b32, "CPNMUOJ1E8======")); free(b32); b32 = base32hexmem("", strlen(""), false); assert_se(b32); assert_se(streq(b32, "")); free(b32); b32 = base32hexmem("f", strlen("f"), false); assert_se(b32); assert_se(streq(b32, "CO")); free(b32); b32 = base32hexmem("fo", strlen("fo"), false); assert_se(b32); assert_se(streq(b32, "CPNG")); free(b32); b32 = base32hexmem("foo", strlen("foo"), false); assert_se(b32); assert_se(streq(b32, "CPNMU")); free(b32); b32 = base32hexmem("foob", strlen("foob"), false); assert_se(b32); assert_se(streq(b32, "CPNMUOG")); free(b32); b32 = base32hexmem("fooba", strlen("fooba"), false); assert_se(b32); assert_se(streq(b32, "CPNMUOJ1")); free(b32); b32 = base32hexmem("foobar", strlen("foobar"), false); assert_se(b32); assert_se(streq(b32, "CPNMUOJ1E8")); free(b32); } static void test_unbase32hexmem(void) { void *mem; size_t len; assert_se(unbase32hexmem("", strlen(""), true, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "")); free(mem); assert_se(unbase32hexmem("CO======", strlen("CO======"), true, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "f")); free(mem); assert_se(unbase32hexmem("CPNG====", strlen("CPNG===="), true, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "fo")); free(mem); assert_se(unbase32hexmem("CPNMU===", strlen("CPNMU==="), true, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "foo")); free(mem); assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), true, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "foob")); free(mem); assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "fooba")); free(mem); assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), true, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "foobar")); free(mem); assert_se(unbase32hexmem("A", strlen("A"), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("A=======", strlen("A======="), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("AAA=====", strlen("AAA====="), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("AAAAAA==", strlen("AAAAAA=="), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("AB======", strlen("AB======"), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("AAAB====", strlen("AAAB===="), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("AAAAB===", strlen("AAAAB==="), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("AAAAAAB=", strlen("AAAAAAB="), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("XPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("CXNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("CPXMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("CPNXUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("CPNMXOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("CPNMUXJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("CPNMUOX1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("CPNMUOJX", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("", strlen(""), false, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "")); free(mem); assert_se(unbase32hexmem("CO", strlen("CO"), false, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "f")); free(mem); assert_se(unbase32hexmem("CPNG", strlen("CPNG"), false, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "fo")); free(mem); assert_se(unbase32hexmem("CPNMU", strlen("CPNMU"), false, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "foo")); free(mem); assert_se(unbase32hexmem("CPNMUOG", strlen("CPNMUOG"), false, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "foob")); free(mem); assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), false, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "fooba")); free(mem); assert_se(unbase32hexmem("CPNMUOJ1E8", strlen("CPNMUOJ1E8"), false, &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "foobar")); free(mem); assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), false, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("AAA", strlen("AAA"), false, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("AAAAAA", strlen("AAAAAA"), false, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("AB", strlen("AB"), false, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("AAAB", strlen("AAAB"), false, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("AAAAB", strlen("AAAAB"), false, &mem, &len) == -EINVAL); assert_se(unbase32hexmem("AAAAAAB", strlen("AAAAAAB"), false, &mem, &len) == -EINVAL); } /* https://tools.ietf.org/html/rfc4648#section-10 */ static void test_base64mem(void) { char *b64; assert_se(base64mem("", strlen(""), &b64) == 0); assert_se(streq(b64, "")); free(b64); assert_se(base64mem("f", strlen("f"), &b64) == 4); assert_se(streq(b64, "Zg==")); free(b64); assert_se(base64mem("fo", strlen("fo"), &b64) == 4); assert_se(streq(b64, "Zm8=")); free(b64); assert_se(base64mem("foo", strlen("foo"), &b64) == 4); assert_se(streq(b64, "Zm9v")); free(b64); assert_se(base64mem("foob", strlen("foob"), &b64) == 8); assert_se(streq(b64, "Zm9vYg==")); free(b64); assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8); assert_se(streq(b64, "Zm9vYmE=")); free(b64); assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8); assert_se(streq(b64, "Zm9vYmFy")); free(b64); } static void test_unbase64mem(void) { void *mem; size_t len; assert_se(unbase64mem("", strlen(""), &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "")); free(mem); assert_se(unbase64mem("Zg==", strlen("Zg=="), &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "f")); free(mem); assert_se(unbase64mem("Zm8=", strlen("Zm8="), &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "fo")); free(mem); assert_se(unbase64mem("Zm9v", strlen("Zm9v"), &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "foo")); free(mem); assert_se(unbase64mem("Zm9vYg==", strlen("Zm9vYg=="), &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "foob")); free(mem); assert_se(unbase64mem("Zm9vYmE=", strlen("Zm9vYmE="), &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "fooba")); free(mem); assert_se(unbase64mem("Zm9vYmFy", strlen("Zm9vYmFy"), &mem, &len) == 0); assert_se(streq(strndupa(mem, len), "foobar")); free(mem); assert_se(unbase64mem("A", strlen("A"), &mem, &len) == -EINVAL); assert_se(unbase64mem("A====", strlen("A===="), &mem, &len) == -EINVAL); assert_se(unbase64mem("AAB==", strlen("AAB=="), &mem, &len) == -EINVAL); assert_se(unbase64mem("AAAB=", strlen("AAAB="), &mem, &len) == -EINVAL); } static void test_cescape(void) { _cleanup_free_ char *escaped; assert_se(escaped = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313")); assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313")); } static void test_cunescape(void) { _cleanup_free_ char *unescaped; assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", 0, &unescaped) < 0); assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", UNESCAPE_RELAX, &unescaped) >= 0); assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00")); unescaped = mfree(unescaped); /* incomplete sequences */ assert_se(cunescape("\\x0", 0, &unescaped) < 0); assert_se(cunescape("\\x0", UNESCAPE_RELAX, &unescaped) >= 0); assert_se(streq_ptr(unescaped, "\\x0")); unescaped = mfree(unescaped); assert_se(cunescape("\\x", 0, &unescaped) < 0); assert_se(cunescape("\\x", UNESCAPE_RELAX, &unescaped) >= 0); assert_se(streq_ptr(unescaped, "\\x")); unescaped = mfree(unescaped); assert_se(cunescape("\\", 0, &unescaped) < 0); assert_se(cunescape("\\", UNESCAPE_RELAX, &unescaped) >= 0); assert_se(streq_ptr(unescaped, "\\")); unescaped = mfree(unescaped); assert_se(cunescape("\\11", 0, &unescaped) < 0); assert_se(cunescape("\\11", UNESCAPE_RELAX, &unescaped) >= 0); assert_se(streq_ptr(unescaped, "\\11")); unescaped = mfree(unescaped); assert_se(cunescape("\\1", 0, &unescaped) < 0); assert_se(cunescape("\\1", UNESCAPE_RELAX, &unescaped) >= 0); assert_se(streq_ptr(unescaped, "\\1")); unescaped = mfree(unescaped); assert_se(cunescape("\\u0000", 0, &unescaped) < 0); assert_se(cunescape("\\u00DF\\U000000df\\u03a0\\U00000041", UNESCAPE_RELAX, &unescaped) >= 0); assert_se(streq_ptr(unescaped, "ßßΠA")); unescaped = mfree(unescaped); assert_se(cunescape("\\073", 0, &unescaped) >= 0); assert_se(streq_ptr(unescaped, ";")); } static void test_foreach_word(void) { const char *word, *state; size_t l; int i = 0; const char test[] = "test abc d\te f "; const char * const expected[] = { "test", "abc", "d", "e", "f", "", NULL }; FOREACH_WORD(word, l, test, state) assert_se(strneq(expected[i++], word, l)); } static void check(const char *test, char** expected, bool trailing) { const char *word, *state; size_t l; int i = 0; printf("<<<%s>>>\n", test); FOREACH_WORD_QUOTED(word, l, test, state) { _cleanup_free_ char *t = NULL; assert_se(t = strndup(word, l)); assert_se(strneq(expected[i++], word, l)); printf("<%s>\n", t); } printf("<<<%s>>>\n", state); assert_se(expected[i] == NULL); assert_se(isempty(state) == !trailing); } static void test_foreach_word_quoted(void) { check("test a b c 'd' e '' '' hhh '' '' \"a b c\"", STRV_MAKE("test", "a", "b", "c", "d", "e", "", "", "hhh", "", "", "a b c"), false); check("test \"xxx", STRV_MAKE("test"), true); check("test\\", STRV_MAKE_EMPTY, true); } static void test_memdup_multiply(void) { int org[] = {1, 2, 3}; int *dup; dup = (int*)memdup_multiply(org, sizeof(int), 3); assert_se(dup); assert_se(dup[0] == 1); assert_se(dup[1] == 2); assert_se(dup[2] == 3); free(dup); } static void test_u64log2(void) { assert_se(u64log2(0) == 0); assert_se(u64log2(8) == 3); assert_se(u64log2(9) == 3); assert_se(u64log2(15) == 3); assert_se(u64log2(16) == 4); assert_se(u64log2(1024*1024) == 20); assert_se(u64log2(1024*1024+5) == 20); } static void test_protect_errno(void) { errno = 12; { PROTECT_ERRNO; errno = 11; } assert_se(errno == 12); } static void test_parse_cpu_set(void) { cpu_set_t *c = NULL; int ncpus; int cpu; /* Simple range (from CPUAffinity example) */ ncpus = parse_cpu_set_and_warn("1 2", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus >= 1024); assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c)); assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c)); assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2); c = mfree(c); /* A more interesting range */ ncpus = parse_cpu_set_and_warn("0 1 2 3 8 9 10 11", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus >= 1024); assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); for (cpu = 0; cpu < 4; cpu++) assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); for (cpu = 8; cpu < 12; cpu++) assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); c = mfree(c); /* Quoted strings */ ncpus = parse_cpu_set_and_warn("8 '9' 10 \"11\"", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus >= 1024); assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4); for (cpu = 8; cpu < 12; cpu++) assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); c = mfree(c); /* Use commas as separators */ ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus >= 1024); assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); for (cpu = 0; cpu < 4; cpu++) assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); for (cpu = 8; cpu < 12; cpu++) assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); c = mfree(c); /* Commas with spaces (and trailing comma, space) */ ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus >= 1024); assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); for (cpu = 0; cpu < 8; cpu++) assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); c = mfree(c); /* Ranges */ ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus >= 1024); assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); for (cpu = 0; cpu < 4; cpu++) assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); for (cpu = 8; cpu < 12; cpu++) assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); c = mfree(c); /* Ranges with trailing comma, space */ ncpus = parse_cpu_set_and_warn("0-3 8-11, ", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus >= 1024); assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8); for (cpu = 0; cpu < 4; cpu++) assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); for (cpu = 8; cpu < 12; cpu++) assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); c = mfree(c); /* Negative range (returns empty cpu_set) */ ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus >= 1024); assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0); c = mfree(c); /* Overlapping ranges */ ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus >= 1024); assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12); for (cpu = 0; cpu < 12; cpu++) assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); c = mfree(c); /* Mix ranges and individual CPUs */ ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus >= 1024); assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10); assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c)); assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c)); for (cpu = 4; cpu < 12; cpu++) assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c)); c = mfree(c); /* Garbage */ ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus < 0); assert_se(!c); /* Range with garbage */ ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus < 0); assert_se(!c); /* Empty string */ c = NULL; ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus == 0); /* empty string returns 0 */ assert_se(!c); /* Runnaway quoted string */ ncpus = parse_cpu_set_and_warn("0 1 2 3 \"4 5 6 7 ", &c, NULL, "fake", 1, "CPUAffinity"); assert_se(ncpus < 0); assert_se(!c); } static void test_config_parse_iec_uint64(void) { uint64_t offset = 0; assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0); assert_se(offset == 4 * 1024 * 1024); assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0); } static void test_strextend(void) { _cleanup_free_ char *str = strdup("0123"); strextend(&str, "456", "78", "9", NULL); assert_se(streq(str, "0123456789")); } static void test_strrep(void) { _cleanup_free_ char *one, *three, *zero; one = strrep("waldo", 1); three = strrep("waldo", 3); zero = strrep("waldo", 0); assert_se(streq(one, "waldo")); assert_se(streq(three, "waldowaldowaldo")); assert_se(streq(zero, "")); } static void test_split_pair(void) { _cleanup_free_ char *a = NULL, *b = NULL; assert_se(split_pair("", "", &a, &b) == -EINVAL); assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL); assert_se(split_pair("", "=", &a, &b) == -EINVAL); assert_se(split_pair("foo=bar", "=", &a, &b) >= 0); assert_se(streq(a, "foo")); assert_se(streq(b, "bar")); free(a); free(b); assert_se(split_pair("==", "==", &a, &b) >= 0); assert_se(streq(a, "")); assert_se(streq(b, "")); free(a); free(b); assert_se(split_pair("===", "==", &a, &b) >= 0); assert_se(streq(a, "")); assert_se(streq(b, "=")); } static void test_fstab_node_to_udev_node(void) { char *n; n = fstab_node_to_udev_node("LABEL=applé/jack"); puts(n); assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack")); free(n); n = fstab_node_to_udev_node("PARTLABEL=pinkié pie"); puts(n); assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie")); free(n); n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535"); puts(n); assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535")); free(n); n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535"); puts(n); assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535")); free(n); n = fstab_node_to_udev_node("PONIES=awesome"); puts(n); assert_se(streq(n, "PONIES=awesome")); free(n); n = fstab_node_to_udev_node("/dev/xda1"); puts(n); assert_se(streq(n, "/dev/xda1")); free(n); } static void test_get_files_in_directory(void) { _cleanup_strv_free_ char **l = NULL, **t = NULL; assert_se(get_files_in_directory("/tmp", &l) >= 0); assert_se(get_files_in_directory(".", &t) >= 0); assert_se(get_files_in_directory(".", NULL) >= 0); } static void test_in_set(void) { assert_se(IN_SET(1, 1)); assert_se(IN_SET(1, 1, 2, 3, 4)); assert_se(IN_SET(2, 1, 2, 3, 4)); assert_se(IN_SET(3, 1, 2, 3, 4)); assert_se(IN_SET(4, 1, 2, 3, 4)); assert_se(!IN_SET(0, 1)); assert_se(!IN_SET(0, 1, 2, 3, 4)); } static void test_writing_tmpfile(void) { char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX"; _cleanup_free_ char *contents = NULL; size_t size; int fd, r; struct iovec iov[3]; IOVEC_SET_STRING(iov[0], "abc\n"); IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n"); IOVEC_SET_STRING(iov[2], ""); fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); printf("tmpfile: %s", name); r = writev(fd, iov, 3); assert_se(r >= 0); r = read_full_file(name, &contents, &size); assert_se(r == 0); printf("contents: %s", contents); assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n")); unlink(name); } static void test_hexdump(void) { uint8_t data[146]; unsigned i; hexdump(stdout, NULL, 0); hexdump(stdout, "", 0); hexdump(stdout, "", 1); hexdump(stdout, "x", 1); hexdump(stdout, "x", 2); hexdump(stdout, "foobar", 7); hexdump(stdout, "f\nobar", 7); hexdump(stdout, "xxxxxxxxxxxxxxxxxxxxyz", 23); for (i = 0; i < ELEMENTSOF(data); i++) data[i] = i*2; hexdump(stdout, data, sizeof(data)); } static void test_log2i(void) { assert_se(log2i(1) == 0); assert_se(log2i(2) == 1); assert_se(log2i(3) == 1); assert_se(log2i(4) == 2); assert_se(log2i(32) == 5); assert_se(log2i(33) == 5); assert_se(log2i(63) == 5); assert_se(log2i(INT_MAX) == sizeof(int)*8-2); } static void test_foreach_string(void) { const char * const t[] = { "foo", "bar", "waldo", NULL }; const char *x; unsigned i = 0; FOREACH_STRING(x, "foo", "bar", "waldo") assert_se(streq_ptr(t[i++], x)); assert_se(i == 3); FOREACH_STRING(x, "zzz") assert_se(streq(x, "zzz")); } static void test_filename_is_valid(void) { char foo[FILENAME_MAX+2]; int i; assert_se(!filename_is_valid("")); assert_se(!filename_is_valid("/bar/foo")); assert_se(!filename_is_valid("/")); assert_se(!filename_is_valid(".")); assert_se(!filename_is_valid("..")); for (i=0; i= 0); assert_se(symlink(name, name_alias) >= 0); assert_se(files_same(name, name)); assert_se(files_same(name, name_alias)); unlink(name); unlink(name_alias); } static void test_is_valid_documentation_url(void) { assert_se(documentation_url_is_valid("http://www.freedesktop.org/wiki/Software/systemd")); assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt")); assert_se(documentation_url_is_valid("file:/foo/foo")); assert_se(documentation_url_is_valid("man:systemd.special(7)")); assert_se(documentation_url_is_valid("info:bar")); assert_se(!documentation_url_is_valid("foo:")); assert_se(!documentation_url_is_valid("info:")); assert_se(!documentation_url_is_valid("")); } static void test_file_in_same_dir(void) { char *t; t = file_in_same_dir("/", "a"); assert_se(streq(t, "/a")); free(t); t = file_in_same_dir("/", "/a"); assert_se(streq(t, "/a")); free(t); t = file_in_same_dir("", "a"); assert_se(streq(t, "a")); free(t); t = file_in_same_dir("a/", "a"); assert_se(streq(t, "a/a")); free(t); t = file_in_same_dir("bar/foo", "bar"); assert_se(streq(t, "bar/bar")); free(t); } static void test_endswith(void) { assert_se(endswith("foobar", "bar")); assert_se(endswith("foobar", "")); assert_se(endswith("foobar", "foobar")); assert_se(endswith("", "")); assert_se(!endswith("foobar", "foo")); assert_se(!endswith("foobar", "foobarfoofoo")); } static void test_endswith_no_case(void) { assert_se(endswith_no_case("fooBAR", "bar")); assert_se(endswith_no_case("foobar", "")); assert_se(endswith_no_case("foobar", "FOOBAR")); assert_se(endswith_no_case("", "")); assert_se(!endswith_no_case("foobar", "FOO")); assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO")); } static void test_close_nointr(void) { char name[] = "/tmp/test-test-close_nointr.XXXXXX"; int fd; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(close_nointr(fd) >= 0); assert_se(close_nointr(fd) < 0); unlink(name); } static void test_unlink_noerrno(void) { char name[] = "/tmp/test-close_nointr.XXXXXX"; int fd; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(close_nointr(fd) >= 0); { PROTECT_ERRNO; errno = -42; assert_se(unlink_noerrno(name) >= 0); assert_se(errno == -42); assert_se(unlink_noerrno(name) < 0); assert_se(errno == -42); } } static void test_readlink_and_make_absolute(void) { char tempdir[] = "/tmp/test-readlink_and_make_absolute"; char name[] = "/tmp/test-readlink_and_make_absolute/original"; char name2[] = "test-readlink_and_make_absolute/original"; char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias"; char *r = NULL; assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0); assert_se(touch(name) >= 0); assert_se(symlink(name, name_alias) >= 0); assert_se(readlink_and_make_absolute(name_alias, &r) >= 0); assert_se(streq(r, name)); free(r); assert_se(unlink(name_alias) >= 0); assert_se(chdir(tempdir) >= 0); assert_se(symlink(name2, name_alias) >= 0); assert_se(readlink_and_make_absolute(name_alias, &r) >= 0); assert_se(streq(r, name)); free(r); assert_se(unlink(name_alias) >= 0); assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); } static void test_ignore_signals(void) { assert_se(ignore_signals(SIGINT, -1) >= 0); assert_se(kill(getpid(), SIGINT) >= 0); assert_se(ignore_signals(SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0); assert_se(kill(getpid(), SIGUSR1) >= 0); assert_se(kill(getpid(), SIGUSR2) >= 0); assert_se(kill(getpid(), SIGTERM) >= 0); assert_se(kill(getpid(), SIGPIPE) >= 0); assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0); } static void test_strshorten(void) { char s[] = "foobar"; assert_se(strlen(strshorten(s, 6)) == 6); assert_se(strlen(strshorten(s, 12)) == 6); assert_se(strlen(strshorten(s, 2)) == 2); assert_se(strlen(strshorten(s, 0)) == 0); } static void test_strjoina(void) { char *actual; actual = strjoina("", "foo", "bar"); assert_se(streq(actual, "foobar")); actual = strjoina("foo", "bar", "baz"); assert_se(streq(actual, "foobarbaz")); actual = strjoina("foo", "", "bar", "baz"); assert_se(streq(actual, "foobarbaz")); actual = strjoina("foo"); assert_se(streq(actual, "foo")); actual = strjoina(NULL); assert_se(streq(actual, "")); actual = strjoina(NULL, "foo"); assert_se(streq(actual, "")); actual = strjoina("foo", NULL, "bar"); assert_se(streq(actual, "foo")); } static void test_is_symlink(void) { char name[] = "/tmp/test-is_symlink.XXXXXX"; char name_link[] = "/tmp/test-is_symlink.link"; _cleanup_close_ int fd = -1; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); assert_se(symlink(name, name_link) >= 0); assert_se(is_symlink(name) == 0); assert_se(is_symlink(name_link) == 1); assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0); unlink(name); unlink(name_link); } static void test_search_and_fopen(void) { const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL}; char name[] = "/tmp/test-search_and_fopen.XXXXXX"; int fd = -1; int r; FILE *f; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); close(fd); r = search_and_fopen(basename(name), "r", NULL, dirs, &f); assert_se(r >= 0); fclose(f); r = search_and_fopen(name, "r", NULL, dirs, &f); assert_se(r >= 0); fclose(f); r = search_and_fopen(basename(name), "r", "/", dirs, &f); assert_se(r >= 0); fclose(f); r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f); assert_se(r < 0); r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f); assert_se(r < 0); r = unlink(name); assert_se(r == 0); r = search_and_fopen(basename(name), "r", NULL, dirs, &f); assert_se(r < 0); } static void test_search_and_fopen_nulstr(void) { const char dirs[] = "/tmp/foo/bar\0/tmp\0"; char name[] = "/tmp/test-search_and_fopen.XXXXXX"; int fd = -1; int r; FILE *f; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); close(fd); r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f); assert_se(r >= 0); fclose(f); r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f); assert_se(r >= 0); fclose(f); r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f); assert_se(r < 0); r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f); assert_se(r < 0); r = unlink(name); assert_se(r == 0); r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f); assert_se(r < 0); } static void test_glob_exists(void) { char name[] = "/tmp/test-glob_exists.XXXXXX"; int fd = -1; int r; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); close(fd); r = glob_exists("/tmp/test-glob_exists*"); assert_se(r == 1); r = unlink(name); assert_se(r == 0); r = glob_exists("/tmp/test-glob_exists*"); assert_se(r == 0); } static void test_execute_directory(void) { char template_lo[] = "/tmp/test-readlink_and_make_absolute-lo.XXXXXXX"; char template_hi[] = "/tmp/test-readlink_and_make_absolute-hi.XXXXXXX"; const char * dirs[] = {template_hi, template_lo, NULL}; const char *name, *name2, *name3, *overridden, *override, *masked, *mask; assert_se(mkdtemp(template_lo)); assert_se(mkdtemp(template_hi)); name = strjoina(template_lo, "/script"); name2 = strjoina(template_hi, "/script2"); name3 = strjoina(template_lo, "/useless"); overridden = strjoina(template_lo, "/overridden"); override = strjoina(template_hi, "/overridden"); masked = strjoina(template_lo, "/masked"); mask = strjoina(template_hi, "/masked"); assert_se(write_string_file(name, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works", WRITE_STRING_FILE_CREATE) == 0); assert_se(write_string_file(name2, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2", WRITE_STRING_FILE_CREATE) == 0); assert_se(write_string_file(overridden, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0); assert_se(write_string_file(override, "#!/bin/sh\necho 'Executing '$0", WRITE_STRING_FILE_CREATE) == 0); assert_se(write_string_file(masked, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0); assert_se(symlink("/dev/null", mask) == 0); assert_se(chmod(name, 0755) == 0); assert_se(chmod(name2, 0755) == 0); assert_se(chmod(overridden, 0755) == 0); assert_se(chmod(override, 0755) == 0); assert_se(chmod(masked, 0755) == 0); assert_se(touch(name3) >= 0); execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL); assert_se(chdir(template_lo) == 0); assert_se(access("it_works", F_OK) >= 0); assert_se(access("failed", F_OK) < 0); assert_se(chdir(template_hi) == 0); assert_se(access("it_works2", F_OK) >= 0); assert_se(access("failed", F_OK) < 0); (void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL); (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL); } static int parse_item(const char *key, const char *value) { assert_se(key); log_info("kernel cmdline option <%s> = <%s>", key, strna(value)); return 0; } static void test_parse_proc_cmdline(void) { assert_se(parse_proc_cmdline(parse_item) >= 0); } static void test_raw_clone(void) { pid_t parent, pid, pid2; parent = getpid(); log_info("before clone: getpid()→"PID_FMT, parent); assert_se(raw_getpid() == parent); pid = raw_clone(0, NULL); assert_se(pid >= 0); pid2 = raw_getpid(); log_info("raw_clone: "PID_FMT" getpid()→"PID_FMT" raw_getpid()→"PID_FMT, pid, getpid(), pid2); if (pid == 0) { assert_se(pid2 != parent); _exit(EXIT_SUCCESS); } else { int status; assert_se(pid2 == parent); waitpid(pid, &status, __WCLONE); assert_se(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS); } } static void test_same_fd(void) { _cleanup_close_pair_ int p[2] = { -1, -1 }; _cleanup_close_ int a = -1, b = -1, c = -1; assert_se(pipe2(p, O_CLOEXEC) >= 0); assert_se((a = dup(p[0])) >= 0); assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0); assert_se((c = dup(a)) >= 0); assert_se(same_fd(p[0], p[0]) > 0); assert_se(same_fd(p[1], p[1]) > 0); assert_se(same_fd(a, a) > 0); assert_se(same_fd(b, b) > 0); assert_se(same_fd(a, p[0]) > 0); assert_se(same_fd(p[0], a) > 0); assert_se(same_fd(c, p[0]) > 0); assert_se(same_fd(p[0], c) > 0); assert_se(same_fd(a, c) > 0); assert_se(same_fd(c, a) > 0); assert_se(same_fd(p[0], p[1]) == 0); assert_se(same_fd(p[1], p[0]) == 0); assert_se(same_fd(p[0], b) == 0); assert_se(same_fd(b, p[0]) == 0); assert_se(same_fd(p[1], a) == 0); assert_se(same_fd(a, p[1]) == 0); assert_se(same_fd(p[1], b) == 0); assert_se(same_fd(b, p[1]) == 0); assert_se(same_fd(a, b) == 0); assert_se(same_fd(b, a) == 0); } static void test_uid_ptr(void) { assert_se(UID_TO_PTR(0) != NULL); assert_se(UID_TO_PTR(1000) != NULL); assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0); assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000); } static void test_sparse_write_one(int fd, const char *buffer, size_t n) { char check[n]; assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(ftruncate(fd, 0) >= 0); assert_se(sparse_write(fd, buffer, n, 4) == (ssize_t) n); assert_se(lseek(fd, 0, SEEK_CUR) == (off_t) n); assert_se(ftruncate(fd, n) >= 0); assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(read(fd, check, n) == (ssize_t) n); assert_se(memcmp(buffer, check, n) == 0); } static void test_sparse_write(void) { const char test_a[] = "test"; const char test_b[] = "\0\0\0\0test\0\0\0\0"; const char test_c[] = "\0\0test\0\0\0\0"; const char test_d[] = "\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0\0\0\0"; const char test_e[] = "test\0\0\0\0test"; _cleanup_close_ int fd = -1; char fn[] = "/tmp/sparseXXXXXX"; fd = mkostemp(fn, O_CLOEXEC); assert_se(fd >= 0); unlink(fn); test_sparse_write_one(fd, test_a, sizeof(test_a)); test_sparse_write_one(fd, test_b, sizeof(test_b)); test_sparse_write_one(fd, test_c, sizeof(test_c)); test_sparse_write_one(fd, test_d, sizeof(test_d)); test_sparse_write_one(fd, test_e, sizeof(test_e)); } static void test_shell_escape_one(const char *s, const char *bad, const char *expected) { _cleanup_free_ char *r; assert_se(r = shell_escape(s, bad)); assert_se(streq_ptr(r, expected)); } static void test_shell_escape(void) { test_shell_escape_one("", "", ""); test_shell_escape_one("\\", "", "\\\\"); test_shell_escape_one("foobar", "", "foobar"); test_shell_escape_one("foobar", "o", "f\\o\\obar"); test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz"); } static void test_shell_maybe_quote_one(const char *s, const char *expected) { _cleanup_free_ char *r; assert_se(r = shell_maybe_quote(s)); assert_se(streq(r, expected)); } static void test_shell_maybe_quote(void) { test_shell_maybe_quote_one("", ""); test_shell_maybe_quote_one("\\", "\"\\\\\""); test_shell_maybe_quote_one("\"", "\"\\\"\""); test_shell_maybe_quote_one("foobar", "foobar"); test_shell_maybe_quote_one("foo bar", "\"foo bar\""); test_shell_maybe_quote_one("foo \"bar\" waldo", "\"foo \\\"bar\\\" waldo\""); test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\""); } static void test_tempfn(void) { char *ret = NULL, *p; assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0); assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX")); free(ret); assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0); assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX")); free(ret); assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0); assert_se(p = startswith(ret, "/foo/bar/.#waldo")); assert_se(strlen(p) == 16); assert_se(in_charset(p, "0123456789abcdef")); free(ret); assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0); assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo")); assert_se(strlen(p) == 16); assert_se(in_charset(p, "0123456789abcdef")); free(ret); assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0); assert_se(p = startswith(ret, "/foo/bar/waldo/.#")); assert_se(strlen(p) == 16); assert_se(in_charset(p, "0123456789abcdef")); free(ret); assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0); assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]")); assert_se(strlen(p) == 16); assert_se(in_charset(p, "0123456789abcdef")); free(ret); } static void test_strcmp_ptr(void) { assert_se(strcmp_ptr(NULL, NULL) == 0); assert_se(strcmp_ptr("", NULL) > 0); assert_se(strcmp_ptr("foo", NULL) > 0); assert_se(strcmp_ptr(NULL, "") < 0); assert_se(strcmp_ptr(NULL, "bar") < 0); assert_se(strcmp_ptr("foo", "bar") > 0); assert_se(strcmp_ptr("bar", "baz") < 0); assert_se(strcmp_ptr("foo", "foo") == 0); assert_se(strcmp_ptr("", "") == 0); } static void test_fgetxattrat_fake(void) { char t[] = "/var/tmp/xattrtestXXXXXX"; _cleanup_close_ int fd = -1; const char *x; char v[3] = {}; int r; assert_se(mkdtemp(t)); x = strjoina(t, "/test"); assert_se(touch(x) >= 0); r = setxattr(x, "user.foo", "bar", 3, 0); if (r < 0 && errno == EOPNOTSUPP) /* no xattrs supported on /var/tmp... */ goto cleanup; assert_se(r >= 0); fd = open(t, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY); assert_se(fd >= 0); assert_se(fgetxattrat_fake(fd, "test", "user.foo", v, 3, 0) >= 0); assert_se(memcmp(v, "bar", 3) == 0); safe_close(fd); fd = open("/", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY); assert_se(fd >= 0); assert_se(fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0) == -ENODATA); cleanup: assert_se(unlink(x) >= 0); assert_se(rmdir(t) >= 0); } static void test_runlevel_to_target(void) { assert_se(streq_ptr(runlevel_to_target(NULL), NULL)); assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL)); assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET)); } int main(int argc, char *argv[]) { log_parse_environment(); log_open(); test_streq_ptr(); test_align_power2(); test_max(); test_container_of(); test_alloca(); test_div_round_up(); test_first_word(); test_close_many(); test_parse_uid(); test_strappend(); test_strstrip(); test_delete_chars(); test_in_charset(); test_hexchar(); test_unhexchar(); test_base32hexchar(); test_unbase32hexchar(); test_base64char(); test_unbase64char(); test_octchar(); test_unoctchar(); test_decchar(); test_undecchar(); test_unhexmem(); test_base32hexmem(); test_unbase32hexmem(); test_base64mem(); test_unbase64mem(); test_cescape(); test_cunescape(); test_foreach_word(); test_foreach_word_quoted(); test_memdup_multiply(); test_u64log2(); test_protect_errno(); test_parse_cpu_set(); test_config_parse_iec_uint64(); test_strextend(); test_strrep(); test_split_pair(); test_fstab_node_to_udev_node(); test_get_files_in_directory(); test_in_set(); test_writing_tmpfile(); test_hexdump(); test_log2i(); test_foreach_string(); test_filename_is_valid(); test_string_has_cc(); test_ascii_strlower(); test_files_same(); test_is_valid_documentation_url(); test_file_in_same_dir(); test_endswith(); test_endswith_no_case(); test_close_nointr(); test_unlink_noerrno(); test_readlink_and_make_absolute(); test_ignore_signals(); test_strshorten(); test_strjoina(); test_is_symlink(); test_search_and_fopen(); test_search_and_fopen_nulstr(); test_glob_exists(); test_execute_directory(); test_parse_proc_cmdline(); test_raw_clone(); test_same_fd(); test_uid_ptr(); test_sparse_write(); test_shell_escape(); test_shell_maybe_quote(); test_tempfn(); test_strcmp_ptr(); test_fgetxattrat_fake(); test_runlevel_to_target(); return 0; } systemd-229/src/test/test-verbs.c000066400000000000000000000053561265713322000171020ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 systemd developers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "macro.h" #include "strv.h" #include "verbs.h" static int noop_dispatcher(int argc, char *argv[], void *userdata) { return 0; } #define test_dispatch_one(argv, verbs, expected) \ optind = 0; \ assert_se(dispatch_verb(strv_length(argv), argv, verbs, NULL) == expected); static void test_verbs(void) { static const Verb verbs[] = { { "help", VERB_ANY, VERB_ANY, 0, noop_dispatcher }, { "list-images", VERB_ANY, 1, 0, noop_dispatcher }, { "list", VERB_ANY, 2, VERB_DEFAULT, noop_dispatcher }, { "status", 2, VERB_ANY, 0, noop_dispatcher }, { "show", VERB_ANY, VERB_ANY, 0, noop_dispatcher }, { "terminate", 2, VERB_ANY, 0, noop_dispatcher }, { "login", 2, 2, 0, noop_dispatcher }, { "copy-to", 3, 4, 0, noop_dispatcher }, {} }; /* not found */ test_dispatch_one(STRV_MAKE("command-not-found"), verbs, -EINVAL); /* found */ test_dispatch_one(STRV_MAKE("show"), verbs, 0); /* found, too few args */ test_dispatch_one(STRV_MAKE("copy-to", "foo"), verbs, -EINVAL); /* found, meets min args */ test_dispatch_one(STRV_MAKE("status", "foo", "bar"), verbs, 0); /* found, too many args */ test_dispatch_one(STRV_MAKE("copy-to", "foo", "bar", "baz", "quux", "qaax"), verbs, -EINVAL); /* no verb, but a default is set */ test_dispatch_one(STRV_MAKE_EMPTY, verbs, 0); } static void test_verbs_no_default(void) { static const Verb verbs[] = { { "help", VERB_ANY, VERB_ANY, 0, noop_dispatcher }, {}, }; test_dispatch_one(STRV_MAKE(NULL), verbs, -EINVAL); } int main(int argc, char *argv[]) { test_verbs(); test_verbs_no_default(); return 0; } systemd-229/src/test/test-watchdog.c000066400000000000000000000025621265713322000175550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "log.h" #include "watchdog.h" int main(int argc, char *argv[]) { usec_t t = 10 * USEC_PER_SEC; unsigned i; int r; log_set_max_level(LOG_DEBUG); log_parse_environment(); r = watchdog_set_timeout(&t); if (r < 0) log_warning_errno(r, "Failed to open watchdog: %m"); for (i = 0; i < 5; i++) { log_info("Pinging..."); r = watchdog_ping(); if (r < 0) log_warning_errno(r, "Failed to ping watchdog: %m"); usleep(t/2); } watchdog_close(true); return 0; } systemd-229/src/test/test-xml.c000066400000000000000000000044561265713322000165610ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "alloc-util.h" #include "string-util.h" #include "util.h" #include "xml.h" static void test_one(const char *data, ...) { void *state = NULL; va_list ap; va_start(ap, data); for (;;) { _cleanup_free_ char *name = NULL; int t, tt; const char *nn; t = xml_tokenize(&data, &name, &state, NULL); assert_se(t >= 0); tt = va_arg(ap, int); assert_se(tt >= 0); assert_se(t == tt); if (t == XML_END) break; nn = va_arg(ap, const char *); assert_se(streq_ptr(nn, name)); } va_end(ap); } int main(int argc, char *argv[]) { test_one("", XML_END); test_one("", XML_TAG_OPEN, "foo", XML_TAG_CLOSE, "foo", XML_END); test_one("", XML_TAG_OPEN, "foo", XML_ATTRIBUTE_NAME, "waldo", XML_ATTRIBUTE_VALUE, "piep", XML_ATTRIBUTE_NAME, "meh", XML_ATTRIBUTE_VALUE, "huhu", XML_TAG_CLOSE_EMPTY, NULL, XML_END); test_one("xxxx\n" " ", XML_TEXT, "xxxx\n", XML_TAG_OPEN, "foo", XML_TEXT, " ", XML_TEXT, " ", XML_TAG_CLOSE, "foo", XML_END); return 0; } systemd-229/src/timedate/000077500000000000000000000000001265713322000154445ustar00rootroot00000000000000systemd-229/src/timedate/.gitignore000066400000000000000000000000411265713322000174270ustar00rootroot00000000000000org.freedesktop.timedate1.policy systemd-229/src/timedate/Makefile000077700000000000000000000000001265713322000207522../Makefileustar00rootroot00000000000000systemd-229/src/timedate/org.freedesktop.timedate1.conf000066400000000000000000000016631265713322000232760ustar00rootroot00000000000000 systemd-229/src/timedate/org.freedesktop.timedate1.policy.in000066400000000000000000000055671265713322000242640ustar00rootroot00000000000000 The systemd Project http://www.freedesktop.org/wiki/Software/systemd <_description>Set system time <_message>Authentication is required to set the system time. auth_admin_keep auth_admin_keep auth_admin_keep org.freedesktop.timedate1.set-timezone org.freedesktop.timedate1.set-ntp <_description>Set system timezone <_message>Authentication is required to set the system timezone. auth_admin_keep auth_admin_keep auth_admin_keep <_description>Set RTC to local timezone or UTC <_message>Authentication is required to control whether the RTC stores the local or UTC time. auth_admin_keep auth_admin_keep auth_admin_keep <_description>Turn network time synchronization on or off <_message>Authentication is required to control whether network time synchronization shall be enabled. auth_admin_keep auth_admin_keep auth_admin_keep systemd-229/src/timedate/org.freedesktop.timedate1.service000066400000000000000000000006431265713322000240060ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] Name=org.freedesktop.timedate1 Exec=/bin/false User=root SystemdService=dbus-org.freedesktop.timedate1.service systemd-229/src/timedate/timedatectl.c000066400000000000000000000412071265713322000201130ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Lennart Poettering Copyright 2013 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-bus.h" #include "bus-error.h" #include "bus-util.h" #include "pager.h" #include "parse-util.h" #include "spawn-polkit-agent.h" #include "strv.h" #include "terminal-util.h" #include "util.h" static bool arg_no_pager = false; static bool arg_ask_password = true; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static char *arg_host = NULL; static bool arg_adjust_system_clock = false; static void pager_open_if_enabled(void) { if (arg_no_pager) return; pager_open(false); } static void polkit_agent_open_if_enabled(void) { /* Open the polkit agent as a child process if necessary */ if (!arg_ask_password) return; if (arg_transport != BUS_TRANSPORT_LOCAL) return; polkit_agent_open(); } typedef struct StatusInfo { usec_t time; char *timezone; usec_t rtc_time; bool rtc_local; bool ntp_enabled; bool ntp_capable; bool ntp_synced; } StatusInfo; static void status_info_clear(StatusInfo *info) { if (info) { free(info->timezone); zero(*info); } } static void print_status_info(const StatusInfo *i) { char a[FORMAT_TIMESTAMP_MAX]; struct tm tm; time_t sec; bool have_time = false; const char *old_tz = NULL, *tz; int r; assert(i); /* Save the old $TZ */ tz = getenv("TZ"); if (tz) old_tz = strdupa(tz); /* Set the new $TZ */ if (setenv("TZ", isempty(i->timezone) ? "UTC" : i->timezone, true) < 0) log_warning_errno(errno, "Failed to set TZ environment variable, ignoring: %m"); else tzset(); if (i->time != 0) { sec = (time_t) (i->time / USEC_PER_SEC); have_time = true; } else if (IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE)) { sec = time(NULL); have_time = true; } else log_warning("Could not get time from timedated and not operating locally, ignoring."); if (have_time) { xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)); printf(" Local time: %.*s\n", (int) sizeof(a), a); xstrftime(a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)); printf(" Universal time: %.*s\n", (int) sizeof(a), a); } else { printf(" Local time: %s\n", "n/a"); printf(" Universal time: %s\n", "n/a"); } if (i->rtc_time > 0) { time_t rtc_sec; rtc_sec = (time_t) (i->rtc_time / USEC_PER_SEC); xstrftime(a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm)); printf(" RTC time: %.*s\n", (int) sizeof(a), a); } else printf(" RTC time: %s\n", "n/a"); if (have_time) xstrftime(a, "%Z, %z", localtime_r(&sec, &tm)); /* Restore the $TZ */ if (old_tz) r = setenv("TZ", old_tz, true); else r = unsetenv("TZ"); if (r < 0) log_warning_errno(errno, "Failed to set TZ environment variable, ignoring: %m"); else tzset(); printf(" Time zone: %s (%.*s)\n" " Network time on: %s\n" "NTP synchronized: %s\n" " RTC in local TZ: %s\n", strna(i->timezone), (int) sizeof(a), have_time ? a : "n/a", i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a", yes_no(i->ntp_synced), yes_no(i->rtc_local)); if (i->rtc_local) fputs("\n" ANSI_HIGHLIGHT "Warning: The system is configured to read the RTC time in the local time zone.\n" " This mode can not be fully supported. It will create various problems\n" " with time zone changes and daylight saving time adjustments. The RTC\n" " time is never updated, it relies on external facilities to maintain it.\n" " If at all possible, use RTC in UTC by calling\n" " 'timedatectl set-local-rtc 0'." ANSI_NORMAL "\n", stdout); } static int show_status(sd_bus *bus, char **args, unsigned n) { _cleanup_(status_info_clear) StatusInfo info = {}; static const struct bus_properties_map map[] = { { "Timezone", "s", NULL, offsetof(StatusInfo, timezone) }, { "LocalRTC", "b", NULL, offsetof(StatusInfo, rtc_local) }, { "NTP", "b", NULL, offsetof(StatusInfo, ntp_enabled) }, { "CanNTP", "b", NULL, offsetof(StatusInfo, ntp_capable) }, { "NTPSynchronized", "b", NULL, offsetof(StatusInfo, ntp_synced) }, { "TimeUSec", "t", NULL, offsetof(StatusInfo, time) }, { "RTCTimeUSec", "t", NULL, offsetof(StatusInfo, rtc_time) }, {} }; int r; assert(bus); r = bus_map_all_properties(bus, "org.freedesktop.timedate1", "/org/freedesktop/timedate1", map, &info); if (r < 0) return log_error_errno(r, "Failed to query server: %m"); print_status_info(&info); return r; } static int set_time(sd_bus *bus, char **args, unsigned n) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; bool relative = false, interactive = arg_ask_password; usec_t t; int r; assert(args); assert(n == 2); polkit_agent_open_if_enabled(); r = parse_timestamp(args[1], &t); if (r < 0) { log_error("Failed to parse time specification: %s", args[1]); return r; } r = sd_bus_call_method(bus, "org.freedesktop.timedate1", "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "SetTime", &error, NULL, "xbb", (int64_t)t, relative, interactive); if (r < 0) log_error("Failed to set time: %s", bus_error_message(&error, -r)); return r; } static int set_timezone(sd_bus *bus, char **args, unsigned n) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(args); assert(n == 2); polkit_agent_open_if_enabled(); r = sd_bus_call_method(bus, "org.freedesktop.timedate1", "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "SetTimezone", &error, NULL, "sb", args[1], arg_ask_password); if (r < 0) log_error("Failed to set time zone: %s", bus_error_message(&error, -r)); return r; } static int set_local_rtc(sd_bus *bus, char **args, unsigned n) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r, b; assert(args); assert(n == 2); polkit_agent_open_if_enabled(); b = parse_boolean(args[1]); if (b < 0) { log_error("Failed to parse local RTC setting: %s", args[1]); return b; } r = sd_bus_call_method(bus, "org.freedesktop.timedate1", "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "SetLocalRTC", &error, NULL, "bbb", b, arg_adjust_system_clock, arg_ask_password); if (r < 0) log_error("Failed to set local RTC: %s", bus_error_message(&error, -r)); return r; } static int set_ntp(sd_bus *bus, char **args, unsigned n) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int b, r; assert(args); assert(n == 2); polkit_agent_open_if_enabled(); b = parse_boolean(args[1]); if (b < 0) { log_error("Failed to parse NTP setting: %s", args[1]); return b; } r = sd_bus_call_method(bus, "org.freedesktop.timedate1", "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "SetNTP", &error, NULL, "bb", b, arg_ask_password); if (r < 0) log_error("Failed to set ntp: %s", bus_error_message(&error, -r)); return r; } static int list_timezones(sd_bus *bus, char **args, unsigned n) { _cleanup_strv_free_ char **zones = NULL; int r; assert(args); assert(n == 1); r = get_timezones(&zones); if (r < 0) return log_error_errno(r, "Failed to read list of time zones: %m"); pager_open_if_enabled(); strv_print(zones); return 0; } static void help(void) { printf("%s [OPTIONS...] COMMAND ...\n\n" "Query or change system time and date settings.\n\n" " -h --help Show this help message\n" " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " --no-ask-password Do not prompt for password\n" " -H --host=[USER@]HOST Operate on remote host\n" " -M --machine=CONTAINER Operate on local container\n" " --adjust-system-clock Adjust system clock when changing local RTC mode\n\n" "Commands:\n" " status Show current time settings\n" " set-time TIME Set system time\n" " set-timezone ZONE Set system time zone\n" " list-timezones Show known time zones\n" " set-local-rtc BOOL Control whether RTC is in local time\n" " set-ntp BOOL Enable or disable network time synchronization\n", program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_ADJUST_SYSTEM_CLOCK, ARG_NO_ASK_PASSWORD }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "host", required_argument, NULL, 'H' }, { "machine", required_argument, NULL, 'M' }, { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, { "adjust-system-clock", no_argument, NULL, ARG_ADJUST_SYSTEM_CLOCK }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case 'H': arg_transport = BUS_TRANSPORT_REMOTE; arg_host = optarg; break; case 'M': arg_transport = BUS_TRANSPORT_MACHINE; arg_host = optarg; break; case ARG_NO_ASK_PASSWORD: arg_ask_password = false; break; case ARG_ADJUST_SYSTEM_CLOCK: arg_adjust_system_clock = true; break; case ARG_NO_PAGER: arg_no_pager = true; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; } static int timedatectl_main(sd_bus *bus, int argc, char *argv[]) { static const struct { const char* verb; const enum { MORE, LESS, EQUAL } argc_cmp; const int argc; int (* const dispatch)(sd_bus *bus, char **args, unsigned n); } verbs[] = { { "status", LESS, 1, show_status }, { "set-time", EQUAL, 2, set_time }, { "set-timezone", EQUAL, 2, set_timezone }, { "list-timezones", EQUAL, 1, list_timezones }, { "set-local-rtc", EQUAL, 2, set_local_rtc }, { "set-ntp", EQUAL, 2, set_ntp, }, }; int left; unsigned i; assert(argc >= 0); assert(argv); left = argc - optind; if (left <= 0) /* Special rule: no arguments means "status" */ i = 0; else { if (streq(argv[optind], "help")) { help(); return 0; } for (i = 0; i < ELEMENTSOF(verbs); i++) if (streq(argv[optind], verbs[i].verb)) break; if (i >= ELEMENTSOF(verbs)) { log_error("Unknown operation %s", argv[optind]); return -EINVAL; } } switch (verbs[i].argc_cmp) { case EQUAL: if (left != verbs[i].argc) { log_error("Invalid number of arguments."); return -EINVAL; } break; case MORE: if (left < verbs[i].argc) { log_error("Too few arguments."); return -EINVAL; } break; case LESS: if (left > verbs[i].argc) { log_error("Too many arguments."); return -EINVAL; } break; default: assert_not_reached("Unknown comparison operator."); } return verbs[i].dispatch(bus, argv + optind, left); } int main(int argc, char *argv[]) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = bus_connect_transport(arg_transport, arg_host, false, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; } r = timedatectl_main(bus, argc, argv); finish: pager_close(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/timedate/timedated.c000066400000000000000000000556571265713322000175720ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "sd-bus.h" #include "sd-event.h" #include "sd-messages.h" #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" #include "clock-util.h" #include "def.h" #include "fileio-label.h" #include "fs-util.h" #include "path-util.h" #include "selinux-util.h" #include "strv.h" #include "user-util.h" #include "util.h" #define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n" #define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n" static BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map timedated_errors[] = { SD_BUS_ERROR_MAP("org.freedesktop.timedate1.NoNTPSupport", EOPNOTSUPP), SD_BUS_ERROR_MAP_END }; typedef struct Context { char *zone; bool local_rtc; bool can_ntp; bool use_ntp; Hashmap *polkit_registry; } Context; static void context_free(Context *c) { assert(c); free(c->zone); bus_verify_polkit_async_registry_free(c->polkit_registry); } static int context_read_data(Context *c) { _cleanup_free_ char *t = NULL; int r; assert(c); r = get_timezone(&t); if (r == -EINVAL) log_warning_errno(r, "/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/."); else if (r < 0) log_warning_errno(r, "Failed to get target of /etc/localtime: %m"); free(c->zone); c->zone = t; t = NULL; c->local_rtc = clock_is_localtime() > 0; return 0; } static int context_write_data_timezone(Context *c) { _cleanup_free_ char *p = NULL; int r = 0; assert(c); if (isempty(c->zone)) { if (unlink("/etc/localtime") < 0 && errno != ENOENT) r = -errno; return r; } p = strappend("../usr/share/zoneinfo/", c->zone); if (!p) return log_oom(); r = symlink_atomic(p, "/etc/localtime"); if (r < 0) return r; return 0; } static int context_write_data_local_rtc(Context *c) { int r; _cleanup_free_ char *s = NULL, *w = NULL; assert(c); r = read_full_file("/etc/adjtime", &s, NULL); if (r < 0) { if (r != -ENOENT) return r; if (!c->local_rtc) return 0; w = strdup(NULL_ADJTIME_LOCAL); if (!w) return -ENOMEM; } else { char *p, *e; size_t a, b; p = strchr(s, '\n'); if (!p) return -EIO; p = strchr(p+1, '\n'); if (!p) return -EIO; p++; e = strchr(p, '\n'); if (!e) return -EIO; a = p - s; b = strlen(e); w = new(char, a + (c->local_rtc ? 5 : 3) + b + 1); if (!w) return -ENOMEM; *(char*) mempcpy(stpcpy(mempcpy(w, s, a), c->local_rtc ? "LOCAL" : "UTC"), e, b) = 0; if (streq(w, NULL_ADJTIME_UTC)) { if (unlink("/etc/adjtime") < 0) if (errno != ENOENT) return -errno; return 0; } } mac_selinux_init("/etc"); return write_string_file_atomic_label("/etc/adjtime", w); } static int context_read_ntp(Context *c, sd_bus *bus) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *s; int r; assert(c); assert(bus); r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "GetUnitFileState", &error, &reply, "s", "systemd-timesyncd.service"); if (r < 0) { if (sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND) || sd_bus_error_has_name(&error, "org.freedesktop.systemd1.LoadFailed") || sd_bus_error_has_name(&error, "org.freedesktop.systemd1.NoSuchUnit")) return 0; return r; } r = sd_bus_message_read(reply, "s", &s); if (r < 0) return r; c->can_ntp = true; c->use_ntp = STR_IN_SET(s, "enabled", "enabled-runtime"); return 0; } static int context_start_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) { int r; assert(bus); assert(error); r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", enabled ? "StartUnit" : "StopUnit", error, NULL, "ss", "systemd-timesyncd.service", "replace"); if (r < 0) { if (sd_bus_error_has_name(error, SD_BUS_ERROR_FILE_NOT_FOUND) || sd_bus_error_has_name(error, "org.freedesktop.systemd1.LoadFailed") || sd_bus_error_has_name(error, "org.freedesktop.systemd1.NoSuchUnit")) return sd_bus_error_set_const(error, "org.freedesktop.timedate1.NoNTPSupport", "NTP not supported."); return r; } return 0; } static int context_enable_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) { int r; assert(bus); assert(error); if (enabled) r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "EnableUnitFiles", error, NULL, "asbb", 1, "systemd-timesyncd.service", false, true); else r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "DisableUnitFiles", error, NULL, "asb", 1, "systemd-timesyncd.service", false); if (r < 0) { if (sd_bus_error_has_name(error, SD_BUS_ERROR_FILE_NOT_FOUND)) return sd_bus_error_set_const(error, "org.freedesktop.timedate1.NoNTPSupport", "NTP not supported."); return r; } r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reload", error, NULL, NULL); if (r < 0) return r; return 0; } static int property_get_rtc_time( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { struct tm tm; usec_t t; int r; zero(tm); r = clock_get_hwclock(&tm); if (r == -EBUSY) { log_warning("/dev/rtc is busy. Is somebody keeping it open continuously? That's not a good idea... Returning a bogus RTC timestamp."); t = 0; } else if (r == -ENOENT) { log_debug("/dev/rtc not found."); t = 0; /* no RTC found */ } else if (r < 0) return sd_bus_error_set_errnof(error, r, "Failed to read RTC: %m"); else t = (usec_t) timegm(&tm) * USEC_PER_SEC; return sd_bus_message_append(reply, "t", t); } static int property_get_time( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { return sd_bus_message_append(reply, "t", now(CLOCK_REALTIME)); } static int property_get_ntp_sync( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { return sd_bus_message_append(reply, "b", ntp_synced()); } static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *error) { Context *c = userdata; const char *z; int interactive; char *t; int r; assert(m); assert(c); r = sd_bus_message_read(m, "sb", &z, &interactive); if (r < 0) return r; if (!timezone_is_valid(z)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid time zone '%s'", z); if (streq_ptr(z, c->zone)) return sd_bus_reply_method_return(m, NULL); r = bus_verify_polkit_async( m, CAP_SYS_TIME, "org.freedesktop.timedate1.set-timezone", NULL, interactive, UID_INVALID, &c->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ t = strdup(z); if (!t) return -ENOMEM; free(c->zone); c->zone = t; /* 1. Write new configuration file */ r = context_write_data_timezone(c); if (r < 0) { log_error_errno(r, "Failed to set time zone: %m"); return sd_bus_error_set_errnof(error, r, "Failed to set time zone: %m"); } /* 2. Tell the kernel our timezone */ clock_set_timezone(NULL); if (c->local_rtc) { struct timespec ts; struct tm *tm; /* 3. Sync RTC from system clock, with the new delta */ assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0); assert_se(tm = localtime(&ts.tv_sec)); clock_set_hwclock(tm); } log_struct(LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_TIMEZONE_CHANGE), "TIMEZONE=%s", c->zone, LOG_MESSAGE("Changed time zone to '%s'.", c->zone), NULL); (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "Timezone", NULL); return sd_bus_reply_method_return(m, NULL); } static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error *error) { int lrtc, fix_system, interactive; Context *c = userdata; struct timespec ts; int r; assert(m); assert(c); r = sd_bus_message_read(m, "bbb", &lrtc, &fix_system, &interactive); if (r < 0) return r; if (lrtc == c->local_rtc) return sd_bus_reply_method_return(m, NULL); r = bus_verify_polkit_async( m, CAP_SYS_TIME, "org.freedesktop.timedate1.set-local-rtc", NULL, interactive, UID_INVALID, &c->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; c->local_rtc = lrtc; /* 1. Write new configuration file */ r = context_write_data_local_rtc(c); if (r < 0) { log_error_errno(r, "Failed to set RTC to local/UTC: %m"); return sd_bus_error_set_errnof(error, r, "Failed to set RTC to local/UTC: %m"); } /* 2. Tell the kernel our timezone */ clock_set_timezone(NULL); /* 3. Synchronize clocks */ assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0); if (fix_system) { struct tm tm; /* Sync system clock from RTC; first, * initialize the timezone fields of * struct tm. */ if (c->local_rtc) tm = *localtime(&ts.tv_sec); else tm = *gmtime(&ts.tv_sec); /* Override the main fields of * struct tm, but not the timezone * fields */ if (clock_get_hwclock(&tm) >= 0) { /* And set the system clock * with this */ if (c->local_rtc) ts.tv_sec = mktime(&tm); else ts.tv_sec = timegm(&tm); clock_settime(CLOCK_REALTIME, &ts); } } else { struct tm *tm; /* Sync RTC from system clock */ if (c->local_rtc) tm = localtime(&ts.tv_sec); else tm = gmtime(&ts.tv_sec); clock_set_hwclock(tm); } log_info("RTC configured to %s time.", c->local_rtc ? "local" : "UTC"); (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "LocalRTC", NULL); return sd_bus_reply_method_return(m, NULL); } static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *error) { int relative, interactive; Context *c = userdata; int64_t utc; struct timespec ts; usec_t start; struct tm* tm; int r; assert(m); assert(c); if (c->use_ntp) return sd_bus_error_setf(error, BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, "Automatic time synchronization is enabled"); /* this only gets used if dbus does not provide a timestamp */ start = now(CLOCK_MONOTONIC); r = sd_bus_message_read(m, "xbb", &utc, &relative, &interactive); if (r < 0) return r; if (!relative && utc <= 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid absolute time"); if (relative && utc == 0) return sd_bus_reply_method_return(m, NULL); if (relative) { usec_t n, x; n = now(CLOCK_REALTIME); x = n + utc; if ((utc > 0 && x < n) || (utc < 0 && x > n)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Time value overflow"); timespec_store(&ts, x); } else timespec_store(&ts, (usec_t) utc); r = bus_verify_polkit_async( m, CAP_SYS_TIME, "org.freedesktop.timedate1.set-time", NULL, interactive, UID_INVALID, &c->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; /* adjust ts for time spent in program */ r = sd_bus_message_get_monotonic_usec(m, &start); /* when sd_bus_message_get_monotonic_usec() returns -ENODATA it does not modify &start */ if (r < 0 && r != -ENODATA) return r; timespec_store(&ts, timespec_load(&ts) + (now(CLOCK_MONOTONIC) - start)); /* Set system clock */ if (clock_settime(CLOCK_REALTIME, &ts) < 0) { log_error_errno(errno, "Failed to set local time: %m"); return sd_bus_error_set_errnof(error, errno, "Failed to set local time: %m"); } /* Sync down to RTC */ if (c->local_rtc) tm = localtime(&ts.tv_sec); else tm = gmtime(&ts.tv_sec); clock_set_hwclock(tm); log_struct(LOG_INFO, LOG_MESSAGE_ID(SD_MESSAGE_TIME_CHANGE), "REALTIME="USEC_FMT, timespec_load(&ts), LOG_MESSAGE("Changed local time to %s", ctime(&ts.tv_sec)), NULL); return sd_bus_reply_method_return(m, NULL); } static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error) { int enabled, interactive; Context *c = userdata; int r; assert(m); assert(c); r = sd_bus_message_read(m, "bb", &enabled, &interactive); if (r < 0) return r; if ((bool)enabled == c->use_ntp) return sd_bus_reply_method_return(m, NULL); r = bus_verify_polkit_async( m, CAP_SYS_TIME, "org.freedesktop.timedate1.set-ntp", NULL, interactive, UID_INVALID, &c->polkit_registry, error); if (r < 0) return r; if (r == 0) return 1; r = context_enable_ntp(sd_bus_message_get_bus(m), error, enabled); if (r < 0) return r; r = context_start_ntp(sd_bus_message_get_bus(m), error, enabled); if (r < 0) return r; c->use_ntp = enabled; log_info("Set NTP to %s", enabled ? "enabled" : "disabled"); (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL); return sd_bus_reply_method_return(m, NULL); } static const sd_bus_vtable timedate_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Timezone", "s", NULL, offsetof(Context, zone), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("LocalRTC", "b", bus_property_get_bool, offsetof(Context, local_rtc), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("CanNTP", "b", bus_property_get_bool, offsetof(Context, can_ntp), 0), SD_BUS_PROPERTY("NTP", "b", bus_property_get_bool, offsetof(Context, use_ntp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("NTPSynchronized", "b", property_get_ntp_sync, 0, 0), SD_BUS_PROPERTY("TimeUSec", "t", property_get_time, 0, 0), SD_BUS_PROPERTY("RTCTimeUSec", "t", property_get_rtc_time, 0, 0), SD_BUS_METHOD("SetTime", "xbb", NULL, method_set_time, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetTimezone", "sb", NULL, method_set_timezone, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetLocalRTC", "bbb", NULL, method_set_local_rtc, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetNTP", "bb", NULL, method_set_ntp, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END, }; static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; assert(c); assert(event); assert(_bus); r = sd_bus_default_system(&bus); if (r < 0) return log_error_errno(r, "Failed to get system bus connection: %m"); r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", timedate_vtable, c); if (r < 0) return log_error_errno(r, "Failed to register object: %m"); r = sd_bus_request_name(bus, "org.freedesktop.timedate1", 0); if (r < 0) return log_error_errno(r, "Failed to register name: %m"); r = sd_bus_attach_event(bus, event, 0); if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop: %m"); *_bus = bus; bus = NULL; return 0; } int main(int argc, char *argv[]) { Context context = {}; _cleanup_(sd_event_unrefp) sd_event *event = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); if (argc != 1) { log_error("This program takes no arguments."); r = -EINVAL; goto finish; } r = sd_event_default(&event); if (r < 0) { log_error_errno(r, "Failed to allocate event loop: %m"); goto finish; } sd_event_set_watchdog(event, true); r = connect_bus(&context, event, &bus); if (r < 0) goto finish; (void) sd_bus_negotiate_timestamp(bus, true); r = context_read_data(&context); if (r < 0) { log_error_errno(r, "Failed to read time zone data: %m"); goto finish; } r = context_read_ntp(&context, bus); if (r < 0) { log_error_errno(r, "Failed to determine whether NTP is enabled: %m"); goto finish; } r = bus_event_loop_with_idle(event, bus, "org.freedesktop.timedate1", DEFAULT_EXIT_USEC, NULL, NULL); if (r < 0) { log_error_errno(r, "Failed to run event loop: %m"); goto finish; } finish: context_free(&context); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/timesync/000077500000000000000000000000001265713322000155035ustar00rootroot00000000000000systemd-229/src/timesync/.gitignore000066400000000000000000000000431265713322000174700ustar00rootroot00000000000000/timesyncd.conf /timesyncd-gperf.c systemd-229/src/timesync/Makefile000077700000000000000000000000001265713322000210112../Makefileustar00rootroot00000000000000systemd-229/src/timesync/timesyncd-conf.c000066400000000000000000000063721265713322000206010ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Kay Sievers, Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "def.h" #include "extract-word.h" #include "string-util.h" #include "timesyncd-conf.h" #include "timesyncd-manager.h" #include "timesyncd-server.h" int manager_parse_server_string(Manager *m, ServerType type, const char *string) { ServerName *first; int r; assert(m); assert(string); first = type == SERVER_FALLBACK ? m->fallback_servers : m->system_servers; for (;;) { _cleanup_free_ char *word = NULL; bool found = false; ServerName *n; r = extract_first_word(&string, &word, NULL, 0); if (r < 0) return log_error_errno(r, "Failed to parse timesyncd server syntax \"%s\": %m", string); if (r == 0) break; /* Filter out duplicates */ LIST_FOREACH(names, n, first) if (streq_ptr(n->string, word)) { found = true; break; } if (found) continue; r = server_name_new(m, NULL, type, word); if (r < 0) return r; } return 0; } int config_parse_servers( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { Manager *m = userdata; int r; assert(filename); assert(lvalue); assert(rvalue); if (isempty(rvalue)) manager_flush_server_names(m, ltype); else { r = manager_parse_server_string(m, ltype, rvalue); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse NTP server string '%s'. Ignoring.", rvalue); return 0; } } return 0; } int manager_parse_config_file(Manager *m) { assert(m); return config_parse_many(PKGSYSCONFDIR "/timesyncd.conf", CONF_PATHS_NULSTR("systemd/timesyncd.conf.d"), "Time\0", config_item_perf_lookup, timesyncd_gperf_lookup, false, m); } systemd-229/src/timesync/timesyncd-conf.h000066400000000000000000000023061265713322000205770ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Kay Sievers, Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "conf-parser.h" #include "timesyncd-manager.h" const struct ConfigPerfItem* timesyncd_gperf_lookup(const char *key, unsigned length); int manager_parse_server_string(Manager *m, ServerType type, const char *string); int config_parse_servers(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int manager_parse_config_file(Manager *m); systemd-229/src/timesync/timesyncd-gperf.gperf000066400000000000000000000010031265713322000216220ustar00rootroot00000000000000%{ #include #include "conf-parser.h" #include "timesyncd-conf.h" %} struct ConfigPerfItem; %null_strings %language=ANSI-C %define slot-name section_and_lvalue %define hash-function-name timesyncdd_gperf_hash %define lookup-function-name timesyncd_gperf_lookup %readonly-tables %omit-struct-type %struct-type %includes %% Time.NTP, config_parse_servers, SERVER_SYSTEM, 0 Time.Servers, config_parse_servers, SERVER_SYSTEM, 0 Time.FallbackNTP, config_parse_servers, SERVER_FALLBACK, 0 systemd-229/src/timesync/timesyncd-manager.c000066400000000000000000001153701265713322000212650ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Kay Sievers, Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include "sd-daemon.h" #include "alloc-util.h" #include "fd-util.h" #include "fs-util.h" #include "list.h" #include "log.h" #include "missing.h" #include "network-util.h" #include "ratelimit.h" #include "socket-util.h" #include "sparse-endian.h" #include "string-util.h" #include "strv.h" #include "time-util.h" #include "timesyncd-conf.h" #include "timesyncd-manager.h" #include "util.h" #ifndef ADJ_SETOFFSET #define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */ #endif /* expected accuracy of time synchronization; used to adjust the poll interval */ #define NTP_ACCURACY_SEC 0.2 /* * "A client MUST NOT under any conditions use a poll interval less * than 15 seconds." */ #define NTP_POLL_INTERVAL_MIN_SEC 32 #define NTP_POLL_INTERVAL_MAX_SEC 2048 /* * Maximum delta in seconds which the system clock is gradually adjusted * (slew) to approach the network time. Deltas larger that this are set by * letting the system time jump. The kernel's limit for adjtime is 0.5s. */ #define NTP_MAX_ADJUST 0.4 /* NTP protocol, packet header */ #define NTP_LEAP_PLUSSEC 1 #define NTP_LEAP_MINUSSEC 2 #define NTP_LEAP_NOTINSYNC 3 #define NTP_MODE_CLIENT 3 #define NTP_MODE_SERVER 4 #define NTP_FIELD_LEAP(f) (((f) >> 6) & 3) #define NTP_FIELD_VERSION(f) (((f) >> 3) & 7) #define NTP_FIELD_MODE(f) ((f) & 7) #define NTP_FIELD(l, v, m) (((l) << 6) | ((v) << 3) | (m)) /* Maximum acceptable root distance in seconds. */ #define NTP_MAX_ROOT_DISTANCE 5.0 /* Maximum number of missed replies before selecting another source. */ #define NTP_MAX_MISSED_REPLIES 2 /* * "NTP timestamps are represented as a 64-bit unsigned fixed-point number, * in seconds relative to 0h on 1 January 1900." */ #define OFFSET_1900_1970 UINT64_C(2208988800) #define RETRY_USEC (30*USEC_PER_SEC) #define RATELIMIT_INTERVAL_USEC (10*USEC_PER_SEC) #define RATELIMIT_BURST 10 #define TIMEOUT_USEC (10*USEC_PER_SEC) struct ntp_ts { be32_t sec; be32_t frac; } _packed_; struct ntp_ts_short { be16_t sec; be16_t frac; } _packed_; struct ntp_msg { uint8_t field; uint8_t stratum; int8_t poll; int8_t precision; struct ntp_ts_short root_delay; struct ntp_ts_short root_dispersion; char refid[4]; struct ntp_ts reference_time; struct ntp_ts origin_time; struct ntp_ts recv_time; struct ntp_ts trans_time; } _packed_; static int manager_arm_timer(Manager *m, usec_t next); static int manager_clock_watch_setup(Manager *m); static int manager_listen_setup(Manager *m); static void manager_listen_stop(Manager *m); static double ntp_ts_short_to_d(const struct ntp_ts_short *ts) { return be16toh(ts->sec) + (be16toh(ts->frac) / 65536.0); } static double ntp_ts_to_d(const struct ntp_ts *ts) { return be32toh(ts->sec) + ((double)be32toh(ts->frac) / UINT_MAX); } static double ts_to_d(const struct timespec *ts) { return ts->tv_sec + (1.0e-9 * ts->tv_nsec); } static int manager_timeout(sd_event_source *source, usec_t usec, void *userdata) { _cleanup_free_ char *pretty = NULL; Manager *m = userdata; assert(m); assert(m->current_server_name); assert(m->current_server_address); server_address_pretty(m->current_server_address, &pretty); log_info("Timed out waiting for reply from %s (%s).", strna(pretty), m->current_server_name->string); return manager_connect(m); } static int manager_send_request(Manager *m) { _cleanup_free_ char *pretty = NULL; struct ntp_msg ntpmsg = { /* * "The client initializes the NTP message header, sends the request * to the server, and strips the time of day from the Transmit * Timestamp field of the reply. For this purpose, all the NTP * header fields are set to 0, except the Mode, VN, and optional * Transmit Timestamp fields." */ .field = NTP_FIELD(0, 4, NTP_MODE_CLIENT), }; ssize_t len; int r; assert(m); assert(m->current_server_name); assert(m->current_server_address); m->event_timeout = sd_event_source_unref(m->event_timeout); r = manager_listen_setup(m); if (r < 0) return log_warning_errno(r, "Failed to setup connection socket: %m"); /* * Set transmit timestamp, remember it; the server will send that back * as the origin timestamp and we have an indication that this is the * matching answer to our request. * * The actual value does not matter, We do not care about the correct * NTP UINT_MAX fraction; we just pass the plain nanosecond value. */ assert_se(clock_gettime(clock_boottime_or_monotonic(), &m->trans_time_mon) >= 0); assert_se(clock_gettime(CLOCK_REALTIME, &m->trans_time) >= 0); ntpmsg.trans_time.sec = htobe32(m->trans_time.tv_sec + OFFSET_1900_1970); ntpmsg.trans_time.frac = htobe32(m->trans_time.tv_nsec); server_address_pretty(m->current_server_address, &pretty); len = sendto(m->server_socket, &ntpmsg, sizeof(ntpmsg), MSG_DONTWAIT, &m->current_server_address->sockaddr.sa, m->current_server_address->socklen); if (len == sizeof(ntpmsg)) { m->pending = true; log_debug("Sent NTP request to %s (%s).", strna(pretty), m->current_server_name->string); } else { log_debug_errno(errno, "Sending NTP request to %s (%s) failed: %m", strna(pretty), m->current_server_name->string); return manager_connect(m); } /* re-arm timer with increasing timeout, in case the packets never arrive back */ if (m->retry_interval > 0) { if (m->retry_interval < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC) m->retry_interval *= 2; } else m->retry_interval = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC; r = manager_arm_timer(m, m->retry_interval); if (r < 0) return log_error_errno(r, "Failed to rearm timer: %m"); m->missed_replies++; if (m->missed_replies > NTP_MAX_MISSED_REPLIES) { r = sd_event_add_time( m->event, &m->event_timeout, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + TIMEOUT_USEC, 0, manager_timeout, m); if (r < 0) return log_error_errno(r, "Failed to arm timeout timer: %m"); } return 0; } static int manager_timer(sd_event_source *source, usec_t usec, void *userdata) { Manager *m = userdata; assert(m); return manager_send_request(m); } static int manager_arm_timer(Manager *m, usec_t next) { int r; assert(m); if (next == 0) { m->event_timer = sd_event_source_unref(m->event_timer); return 0; } if (m->event_timer) { r = sd_event_source_set_time(m->event_timer, now(clock_boottime_or_monotonic()) + next); if (r < 0) return r; return sd_event_source_set_enabled(m->event_timer, SD_EVENT_ONESHOT); } return sd_event_add_time( m->event, &m->event_timer, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + next, 0, manager_timer, m); } static int manager_clock_watch(sd_event_source *source, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; assert(m); /* rearm timer */ manager_clock_watch_setup(m); /* skip our own jumps */ if (m->jumped) { m->jumped = false; return 0; } /* resync */ log_debug("System time changed. Resyncing."); m->poll_resync = true; return manager_send_request(m); } /* wake up when the system time changes underneath us */ static int manager_clock_watch_setup(Manager *m) { struct itimerspec its = { .it_value.tv_sec = TIME_T_MAX }; int r; assert(m); m->event_clock_watch = sd_event_source_unref(m->event_clock_watch); safe_close(m->clock_watch_fd); m->clock_watch_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC); if (m->clock_watch_fd < 0) return log_error_errno(errno, "Failed to create timerfd: %m"); if (timerfd_settime(m->clock_watch_fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) return log_error_errno(errno, "Failed to set up timerfd: %m"); r = sd_event_add_io(m->event, &m->event_clock_watch, m->clock_watch_fd, EPOLLIN, manager_clock_watch, m); if (r < 0) return log_error_errno(r, "Failed to create clock watch event source: %m"); return 0; } static int manager_adjust_clock(Manager *m, double offset, int leap_sec) { struct timex tmx = {}; int r; assert(m); /* * For small deltas, tell the kernel to gradually adjust the system * clock to the NTP time, larger deltas are just directly set. */ if (fabs(offset) < NTP_MAX_ADJUST) { tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR; tmx.status = STA_PLL; tmx.offset = offset * NSEC_PER_SEC; tmx.constant = log2i(m->poll_interval_usec / USEC_PER_SEC) - 4; tmx.maxerror = 0; tmx.esterror = 0; log_debug(" adjust (slew): %+.3f sec", offset); } else { tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_SETOFFSET; /* ADJ_NANO uses nanoseconds in the microseconds field */ tmx.time.tv_sec = (long)offset; tmx.time.tv_usec = (offset - tmx.time.tv_sec) * NSEC_PER_SEC; /* the kernel expects -0.3s as {-1, 7000.000.000} */ if (tmx.time.tv_usec < 0) { tmx.time.tv_sec -= 1; tmx.time.tv_usec += NSEC_PER_SEC; } m->jumped = true; log_debug(" adjust (jump): %+.3f sec", offset); } /* * An unset STA_UNSYNC will enable the kernel's 11-minute mode, * which syncs the system time periodically to the RTC. * * In case the RTC runs in local time, never touch the RTC, * we have no way to properly handle daylight saving changes and * mobile devices moving between time zones. */ if (m->rtc_local_time) tmx.status |= STA_UNSYNC; switch (leap_sec) { case 1: tmx.status |= STA_INS; break; case -1: tmx.status |= STA_DEL; break; } r = clock_adjtime(CLOCK_REALTIME, &tmx); if (r < 0) return -errno; /* If touch fails, there isn't much we can do. Maybe it'll work next time. */ (void) touch("/var/lib/systemd/clock"); m->drift_ppm = tmx.freq / 65536; log_debug(" status : %04i %s\n" " time now : %li.%03llu\n" " constant : %li\n" " offset : %+.3f sec\n" " freq offset : %+li (%i ppm)\n", tmx.status, tmx.status & STA_UNSYNC ? "unsync" : "sync", tmx.time.tv_sec, (unsigned long long) (tmx.time.tv_usec / NSEC_PER_MSEC), tmx.constant, (double)tmx.offset / NSEC_PER_SEC, tmx.freq, m->drift_ppm); return 0; } static bool manager_sample_spike_detection(Manager *m, double offset, double delay) { unsigned int i, idx_cur, idx_new, idx_min; double jitter; double j; assert(m); m->packet_count++; /* ignore initial sample */ if (m->packet_count == 1) return false; /* store the current data in our samples array */ idx_cur = m->samples_idx; idx_new = (idx_cur + 1) % ELEMENTSOF(m->samples); m->samples_idx = idx_new; m->samples[idx_new].offset = offset; m->samples[idx_new].delay = delay; /* calculate new jitter value from the RMS differences relative to the lowest delay sample */ jitter = m->samples_jitter; for (idx_min = idx_cur, i = 0; i < ELEMENTSOF(m->samples); i++) if (m->samples[i].delay > 0 && m->samples[i].delay < m->samples[idx_min].delay) idx_min = i; j = 0; for (i = 0; i < ELEMENTSOF(m->samples); i++) j += pow(m->samples[i].offset - m->samples[idx_min].offset, 2); m->samples_jitter = sqrt(j / (ELEMENTSOF(m->samples) - 1)); /* ignore samples when resyncing */ if (m->poll_resync) return false; /* always accept offset if we are farther off than the round-trip delay */ if (fabs(offset) > delay) return false; /* we need a few samples before looking at them */ if (m->packet_count < 4) return false; /* do not accept anything worse than the maximum possible error of the best sample */ if (fabs(offset) > m->samples[idx_min].delay) return true; /* compare the difference between the current offset to the previous offset and jitter */ return fabs(offset - m->samples[idx_cur].offset) > 3 * jitter; } static void manager_adjust_poll(Manager *m, double offset, bool spike) { assert(m); if (m->poll_resync) { m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC; m->poll_resync = false; return; } /* set to minimal poll interval */ if (!spike && fabs(offset) > NTP_ACCURACY_SEC) { m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC; return; } /* increase polling interval */ if (fabs(offset) < NTP_ACCURACY_SEC * 0.25) { if (m->poll_interval_usec < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC) m->poll_interval_usec *= 2; return; } /* decrease polling interval */ if (spike || fabs(offset) > NTP_ACCURACY_SEC * 0.75) { if (m->poll_interval_usec > NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC) m->poll_interval_usec /= 2; return; } } static int manager_receive_response(sd_event_source *source, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; struct ntp_msg ntpmsg; struct iovec iov = { .iov_base = &ntpmsg, .iov_len = sizeof(ntpmsg), }; union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(struct timeval))]; } control; union sockaddr_union server_addr; struct msghdr msghdr = { .msg_iov = &iov, .msg_iovlen = 1, .msg_control = &control, .msg_controllen = sizeof(control), .msg_name = &server_addr, .msg_namelen = sizeof(server_addr), }; struct cmsghdr *cmsg; struct timespec *recv_time; ssize_t len; double origin, receive, trans, dest; double delay, offset; double root_distance; bool spike; int leap_sec; int r; assert(source); assert(m); if (revents & (EPOLLHUP|EPOLLERR)) { log_warning("Server connection returned error."); return manager_connect(m); } len = recvmsg(fd, &msghdr, MSG_DONTWAIT); if (len < 0) { if (errno == EAGAIN) return 0; log_warning("Error receiving message. Disconnecting."); return manager_connect(m); } /* Too short or too long packet? */ if (iov.iov_len < sizeof(struct ntp_msg) || (msghdr.msg_flags & MSG_TRUNC)) { log_warning("Invalid response from server. Disconnecting."); return manager_connect(m); } if (!m->current_server_name || !m->current_server_address || !sockaddr_equal(&server_addr, &m->current_server_address->sockaddr)) { log_debug("Response from unknown server."); return 0; } recv_time = NULL; CMSG_FOREACH(cmsg, &msghdr) { if (cmsg->cmsg_level != SOL_SOCKET) continue; switch (cmsg->cmsg_type) { case SCM_TIMESTAMPNS: recv_time = (struct timespec *) CMSG_DATA(cmsg); break; } } if (!recv_time) { log_error("Invalid packet timestamp."); return -EINVAL; } if (!m->pending) { log_debug("Unexpected reply. Ignoring."); return 0; } m->missed_replies = 0; /* check our "time cookie" (we just stored nanoseconds in the fraction field) */ if (be32toh(ntpmsg.origin_time.sec) != m->trans_time.tv_sec + OFFSET_1900_1970 || be32toh(ntpmsg.origin_time.frac) != m->trans_time.tv_nsec) { log_debug("Invalid reply; not our transmit time. Ignoring."); return 0; } m->event_timeout = sd_event_source_unref(m->event_timeout); if (be32toh(ntpmsg.recv_time.sec) < TIME_EPOCH + OFFSET_1900_1970 || be32toh(ntpmsg.trans_time.sec) < TIME_EPOCH + OFFSET_1900_1970) { log_debug("Invalid reply, returned times before epoch. Ignoring."); return manager_connect(m); } if (NTP_FIELD_LEAP(ntpmsg.field) == NTP_LEAP_NOTINSYNC || ntpmsg.stratum == 0 || ntpmsg.stratum >= 16) { log_debug("Server is not synchronized. Disconnecting."); return manager_connect(m); } if (!IN_SET(NTP_FIELD_VERSION(ntpmsg.field), 3, 4)) { log_debug("Response NTPv%d. Disconnecting.", NTP_FIELD_VERSION(ntpmsg.field)); return manager_connect(m); } if (NTP_FIELD_MODE(ntpmsg.field) != NTP_MODE_SERVER) { log_debug("Unsupported mode %d. Disconnecting.", NTP_FIELD_MODE(ntpmsg.field)); return manager_connect(m); } root_distance = ntp_ts_short_to_d(&ntpmsg.root_delay) / 2 + ntp_ts_short_to_d(&ntpmsg.root_dispersion); if (root_distance > NTP_MAX_ROOT_DISTANCE) { log_debug("Server has too large root distance. Disconnecting."); return manager_connect(m); } /* valid packet */ m->pending = false; m->retry_interval = 0; /* Stop listening */ manager_listen_stop(m); /* announce leap seconds */ if (NTP_FIELD_LEAP(ntpmsg.field) & NTP_LEAP_PLUSSEC) leap_sec = 1; else if (NTP_FIELD_LEAP(ntpmsg.field) & NTP_LEAP_MINUSSEC) leap_sec = -1; else leap_sec = 0; /* * "Timestamp Name ID When Generated * ------------------------------------------------------------ * Originate Timestamp T1 time request sent by client * Receive Timestamp T2 time request received by server * Transmit Timestamp T3 time reply sent by server * Destination Timestamp T4 time reply received by client * * The round-trip delay, d, and system clock offset, t, are defined as: * d = (T4 - T1) - (T3 - T2) t = ((T2 - T1) + (T3 - T4)) / 2" */ origin = ts_to_d(&m->trans_time) + OFFSET_1900_1970; receive = ntp_ts_to_d(&ntpmsg.recv_time); trans = ntp_ts_to_d(&ntpmsg.trans_time); dest = ts_to_d(recv_time) + OFFSET_1900_1970; offset = ((receive - origin) + (trans - dest)) / 2; delay = (dest - origin) - (trans - receive); spike = manager_sample_spike_detection(m, offset, delay); manager_adjust_poll(m, offset, spike); log_debug("NTP response:\n" " leap : %u\n" " version : %u\n" " mode : %u\n" " stratum : %u\n" " precision : %.6f sec (%d)\n" " root distance: %.6f sec\n" " reference : %.4s\n" " origin : %.3f\n" " receive : %.3f\n" " transmit : %.3f\n" " dest : %.3f\n" " offset : %+.3f sec\n" " delay : %+.3f sec\n" " packet count : %"PRIu64"\n" " jitter : %.3f%s\n" " poll interval: " USEC_FMT "\n", NTP_FIELD_LEAP(ntpmsg.field), NTP_FIELD_VERSION(ntpmsg.field), NTP_FIELD_MODE(ntpmsg.field), ntpmsg.stratum, exp2(ntpmsg.precision), ntpmsg.precision, root_distance, ntpmsg.stratum == 1 ? ntpmsg.refid : "n/a", origin - OFFSET_1900_1970, receive - OFFSET_1900_1970, trans - OFFSET_1900_1970, dest - OFFSET_1900_1970, offset, delay, m->packet_count, m->samples_jitter, spike ? " spike" : "", m->poll_interval_usec / USEC_PER_SEC); if (!spike) { m->sync = true; r = manager_adjust_clock(m, offset, leap_sec); if (r < 0) log_error_errno(r, "Failed to call clock_adjtime(): %m"); } log_debug("interval/delta/delay/jitter/drift " USEC_FMT "s/%+.3fs/%.3fs/%.3fs/%+ippm%s", m->poll_interval_usec / USEC_PER_SEC, offset, delay, m->samples_jitter, m->drift_ppm, spike ? " (ignored)" : ""); if (!m->good) { _cleanup_free_ char *pretty = NULL; m->good = true; server_address_pretty(m->current_server_address, &pretty); log_info("Synchronized to time server %s (%s).", strna(pretty), m->current_server_name->string); sd_notifyf(false, "STATUS=Synchronized to time server %s (%s).", strna(pretty), m->current_server_name->string); } r = manager_arm_timer(m, m->poll_interval_usec); if (r < 0) return log_error_errno(r, "Failed to rearm timer: %m"); return 0; } static int manager_listen_setup(Manager *m) { union sockaddr_union addr = {}; static const int tos = IPTOS_LOWDELAY; static const int on = 1; int r; assert(m); if (m->server_socket >= 0) return 0; assert(!m->event_receive); assert(m->current_server_address); addr.sa.sa_family = m->current_server_address->sockaddr.sa.sa_family; m->server_socket = socket(addr.sa.sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (m->server_socket < 0) return -errno; r = bind(m->server_socket, &addr.sa, m->current_server_address->socklen); if (r < 0) return -errno; r = setsockopt(m->server_socket, SOL_SOCKET, SO_TIMESTAMPNS, &on, sizeof(on)); if (r < 0) return -errno; (void) setsockopt(m->server_socket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); return sd_event_add_io(m->event, &m->event_receive, m->server_socket, EPOLLIN, manager_receive_response, m); } static void manager_listen_stop(Manager *m) { assert(m); m->event_receive = sd_event_source_unref(m->event_receive); m->server_socket = safe_close(m->server_socket); } static int manager_begin(Manager *m) { _cleanup_free_ char *pretty = NULL; int r; assert(m); assert_return(m->current_server_name, -EHOSTUNREACH); assert_return(m->current_server_address, -EHOSTUNREACH); m->good = false; m->missed_replies = NTP_MAX_MISSED_REPLIES; if (m->poll_interval_usec == 0) m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC; server_address_pretty(m->current_server_address, &pretty); log_debug("Connecting to time server %s (%s).", strna(pretty), m->current_server_name->string); sd_notifyf(false, "STATUS=Connecting to time server %s (%s).", strna(pretty), m->current_server_name->string); r = manager_clock_watch_setup(m); if (r < 0) return r; return manager_send_request(m); } void manager_set_server_name(Manager *m, ServerName *n) { assert(m); if (m->current_server_name == n) return; m->current_server_name = n; m->current_server_address = NULL; manager_disconnect(m); if (n) log_debug("Selected server %s.", n->string); } void manager_set_server_address(Manager *m, ServerAddress *a) { assert(m); if (m->current_server_address == a) return; m->current_server_address = a; /* If a is NULL, we are just clearing the address, without * changing the name. Keep the existing name in that case. */ if (a) m->current_server_name = a->name; manager_disconnect(m); if (a) { _cleanup_free_ char *pretty = NULL; server_address_pretty(a, &pretty); log_debug("Selected address %s of server %s.", strna(pretty), a->name->string); } } static int manager_resolve_handler(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata) { Manager *m = userdata; int r; assert(q); assert(m); assert(m->current_server_name); m->resolve_query = sd_resolve_query_unref(m->resolve_query); if (ret != 0) { log_debug("Failed to resolve %s: %s", m->current_server_name->string, gai_strerror(ret)); /* Try next host */ return manager_connect(m); } for (; ai; ai = ai->ai_next) { _cleanup_free_ char *pretty = NULL; ServerAddress *a; assert(ai->ai_addr); assert(ai->ai_addrlen >= offsetof(struct sockaddr, sa_data)); if (!IN_SET(ai->ai_addr->sa_family, AF_INET, AF_INET6)) { log_warning("Unsuitable address protocol for %s", m->current_server_name->string); continue; } r = server_address_new(m->current_server_name, &a, (const union sockaddr_union*) ai->ai_addr, ai->ai_addrlen); if (r < 0) return log_error_errno(r, "Failed to add server address: %m"); server_address_pretty(a, &pretty); log_debug("Resolved address %s for %s.", pretty, m->current_server_name->string); } if (!m->current_server_name->addresses) { log_error("Failed to find suitable address for host %s.", m->current_server_name->string); /* Try next host */ return manager_connect(m); } manager_set_server_address(m, m->current_server_name->addresses); return manager_begin(m); } static int manager_retry_connect(sd_event_source *source, usec_t usec, void *userdata) { Manager *m = userdata; assert(m); return manager_connect(m); } int manager_connect(Manager *m) { int r; assert(m); manager_disconnect(m); m->event_retry = sd_event_source_unref(m->event_retry); if (!ratelimit_test(&m->ratelimit)) { log_debug("Slowing down attempts to contact servers."); r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + RETRY_USEC, 0, manager_retry_connect, m); if (r < 0) return log_error_errno(r, "Failed to create retry timer: %m"); return 0; } /* If we already are operating on some address, switch to the * next one. */ if (m->current_server_address && m->current_server_address->addresses_next) manager_set_server_address(m, m->current_server_address->addresses_next); else { struct addrinfo hints = { .ai_flags = AI_NUMERICSERV|AI_ADDRCONFIG, .ai_socktype = SOCK_DGRAM, }; /* Hmm, we are through all addresses, let's look for the next host instead */ if (m->current_server_name && m->current_server_name->names_next) manager_set_server_name(m, m->current_server_name->names_next); else { ServerName *f; bool restart = true; /* Our current server name list is exhausted, * let's find the next one to iterate. First * we try the system list, then the link list. * After having processed the link list we * jump back to the system list. However, if * both lists are empty, we change to the * fallback list. */ if (!m->current_server_name || m->current_server_name->type == SERVER_LINK) { f = m->system_servers; if (!f) f = m->link_servers; } else { f = m->link_servers; if (!f) f = m->system_servers; else restart = false; } if (!f) f = m->fallback_servers; if (!f) { manager_set_server_name(m, NULL); log_debug("No server found."); return 0; } if (restart && !m->exhausted_servers && m->poll_interval_usec) { log_debug("Waiting after exhausting servers."); r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + m->poll_interval_usec, 0, manager_retry_connect, m); if (r < 0) return log_error_errno(r, "Failed to create retry timer: %m"); m->exhausted_servers = true; /* Increase the polling interval */ if (m->poll_interval_usec < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC) m->poll_interval_usec *= 2; return 0; } m->exhausted_servers = false; manager_set_server_name(m, f); } /* Tell the resolver to reread /etc/resolv.conf, in * case it changed. */ res_init(); /* Flush out any previously resolved addresses */ server_name_flush_addresses(m->current_server_name); log_debug("Resolving %s...", m->current_server_name->string); r = sd_resolve_getaddrinfo(m->resolve, &m->resolve_query, m->current_server_name->string, "123", &hints, manager_resolve_handler, m); if (r < 0) return log_error_errno(r, "Failed to create resolver: %m"); return 1; } r = manager_begin(m); if (r < 0) return r; return 1; } void manager_disconnect(Manager *m) { assert(m); m->resolve_query = sd_resolve_query_unref(m->resolve_query); m->event_timer = sd_event_source_unref(m->event_timer); manager_listen_stop(m); m->event_clock_watch = sd_event_source_unref(m->event_clock_watch); m->clock_watch_fd = safe_close(m->clock_watch_fd); m->event_timeout = sd_event_source_unref(m->event_timeout); sd_notifyf(false, "STATUS=Idle."); } void manager_flush_server_names(Manager *m, ServerType t) { assert(m); if (t == SERVER_SYSTEM) while (m->system_servers) server_name_free(m->system_servers); if (t == SERVER_LINK) while (m->link_servers) server_name_free(m->link_servers); if (t == SERVER_FALLBACK) while (m->fallback_servers) server_name_free(m->fallback_servers); } void manager_free(Manager *m) { if (!m) return; manager_disconnect(m); manager_flush_server_names(m, SERVER_SYSTEM); manager_flush_server_names(m, SERVER_LINK); manager_flush_server_names(m, SERVER_FALLBACK); sd_event_source_unref(m->event_retry); sd_event_source_unref(m->network_event_source); sd_network_monitor_unref(m->network_monitor); sd_resolve_unref(m->resolve); sd_event_unref(m->event); free(m); } static int manager_network_read_link_servers(Manager *m) { _cleanup_strv_free_ char **ntp = NULL; ServerName *n, *nx; char **i; int r; assert(m); r = sd_network_get_ntp(&ntp); if (r < 0) goto clear; LIST_FOREACH(names, n, m->link_servers) n->marked = true; STRV_FOREACH(i, ntp) { bool found = false; LIST_FOREACH(names, n, m->link_servers) if (streq(n->string, *i)) { n->marked = false; found = true; break; } if (!found) { r = server_name_new(m, NULL, SERVER_LINK, *i); if (r < 0) goto clear; } } LIST_FOREACH_SAFE(names, n, nx, m->link_servers) if (n->marked) server_name_free(n); return 0; clear: manager_flush_server_names(m, SERVER_LINK); return r; } static int manager_network_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; bool connected, online; int r; assert(m); sd_network_monitor_flush(m->network_monitor); manager_network_read_link_servers(m); /* check if the machine is online */ online = network_is_online(); /* check if the client is currently connected */ connected = m->server_socket >= 0 || m->resolve_query || m->exhausted_servers; if (connected && !online) { log_info("No network connectivity, watching for changes."); manager_disconnect(m); } else if (!connected && online) { log_info("Network configuration changed, trying to establish connection."); if (m->current_server_address) r = manager_begin(m); else r = manager_connect(m); if (r < 0) return r; } return 0; } static int manager_network_monitor_listen(Manager *m) { int r, fd, events; assert(m); r = sd_network_monitor_new(&m->network_monitor, NULL); if (r < 0) return r; fd = sd_network_monitor_get_fd(m->network_monitor); if (fd < 0) return fd; events = sd_network_monitor_get_events(m->network_monitor); if (events < 0) return events; r = sd_event_add_io(m->event, &m->network_event_source, fd, events, manager_network_event_handler, m); if (r < 0) return r; return 0; } int manager_new(Manager **ret) { _cleanup_(manager_freep) Manager *m = NULL; int r; assert(ret); m = new0(Manager, 1); if (!m) return -ENOMEM; m->server_socket = m->clock_watch_fd = -1; RATELIMIT_INIT(m->ratelimit, RATELIMIT_INTERVAL_USEC, RATELIMIT_BURST); r = manager_parse_server_string(m, SERVER_FALLBACK, NTP_SERVERS); if (r < 0) return r; r = sd_event_default(&m->event); if (r < 0) return r; sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); sd_event_set_watchdog(m->event, true); r = sd_resolve_default(&m->resolve); if (r < 0) return r; r = sd_resolve_attach_event(m->resolve, m->event, 0); if (r < 0) return r; r = manager_network_monitor_listen(m); if (r < 0) return r; manager_network_read_link_servers(m); *ret = m; m = NULL; return 0; } systemd-229/src/timesync/timesyncd-manager.h000066400000000000000000000054441265713322000212720ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Kay Sievers, Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-event.h" #include "sd-network.h" #include "sd-resolve.h" #include "list.h" #include "ratelimit.h" typedef struct Manager Manager; #include "timesyncd-server.h" struct Manager { sd_event *event; sd_resolve *resolve; LIST_HEAD(ServerName, system_servers); LIST_HEAD(ServerName, link_servers); LIST_HEAD(ServerName, fallback_servers); RateLimit ratelimit; bool exhausted_servers; /* network */ sd_event_source *network_event_source; sd_network_monitor *network_monitor; /* peer */ sd_resolve_query *resolve_query; sd_event_source *event_receive; ServerName *current_server_name; ServerAddress *current_server_address; int server_socket; int missed_replies; uint64_t packet_count; sd_event_source *event_timeout; bool good; /* last sent packet */ struct timespec trans_time_mon; struct timespec trans_time; usec_t retry_interval; bool pending; /* poll timer */ sd_event_source *event_timer; usec_t poll_interval_usec; bool poll_resync; /* history data */ struct { double offset; double delay; } samples[8]; unsigned int samples_idx; double samples_jitter; /* last change */ bool jumped; bool sync; int drift_ppm; /* watch for time changes */ sd_event_source *event_clock_watch; int clock_watch_fd; /* Retry connections */ sd_event_source *event_retry; /* RTC runs in local time, leave it alone */ bool rtc_local_time; }; int manager_new(Manager **ret); void manager_free(Manager *m); DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); void manager_set_server_name(Manager *m, ServerName *n); void manager_set_server_address(Manager *m, ServerAddress *a); void manager_flush_server_names(Manager *m, ServerType t); int manager_connect(Manager *m); void manager_disconnect(Manager *m); systemd-229/src/timesync/timesyncd-server.c000066400000000000000000000104221265713322000211510ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Kay Sievers, Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "timesyncd-server.h" int server_address_new( ServerName *n, ServerAddress **ret, const union sockaddr_union *sockaddr, socklen_t socklen) { ServerAddress *a, *tail; assert(n); assert(sockaddr); assert(socklen >= offsetof(struct sockaddr, sa_data)); assert(socklen <= sizeof(union sockaddr_union)); a = new0(ServerAddress, 1); if (!a) return -ENOMEM; memcpy(&a->sockaddr, sockaddr, socklen); a->socklen = socklen; LIST_FIND_TAIL(addresses, n->addresses, tail); LIST_INSERT_AFTER(addresses, n->addresses, tail, a); a->name = n; if (ret) *ret = a; return 0; } ServerAddress* server_address_free(ServerAddress *a) { if (!a) return NULL; if (a->name) { LIST_REMOVE(addresses, a->name->addresses, a); if (a->name->manager && a->name->manager->current_server_address == a) manager_set_server_address(a->name->manager, NULL); } free(a); return NULL; } int server_name_new( Manager *m, ServerName **ret, ServerType type, const char *string) { ServerName *n, *tail; assert(m); assert(string); n = new0(ServerName, 1); if (!n) return -ENOMEM; n->type = type; n->string = strdup(string); if (!n->string) { free(n); return -ENOMEM; } if (type == SERVER_SYSTEM) { LIST_FIND_TAIL(names, m->system_servers, tail); LIST_INSERT_AFTER(names, m->system_servers, tail, n); } else if (type == SERVER_LINK) { LIST_FIND_TAIL(names, m->link_servers, tail); LIST_INSERT_AFTER(names, m->link_servers, tail, n); } else if (type == SERVER_FALLBACK) { LIST_FIND_TAIL(names, m->fallback_servers, tail); LIST_INSERT_AFTER(names, m->fallback_servers, tail, n); } else assert_not_reached("Unknown server type"); n->manager = m; if (type != SERVER_FALLBACK && m->current_server_name && m->current_server_name->type == SERVER_FALLBACK) manager_set_server_name(m, NULL); log_debug("Added new server %s.", string); if (ret) *ret = n; return 0; } ServerName *server_name_free(ServerName *n) { if (!n) return NULL; server_name_flush_addresses(n); if (n->manager) { if (n->type == SERVER_SYSTEM) LIST_REMOVE(names, n->manager->system_servers, n); else if (n->type == SERVER_LINK) LIST_REMOVE(names, n->manager->link_servers, n); else if (n->type == SERVER_FALLBACK) LIST_REMOVE(names, n->manager->fallback_servers, n); else assert_not_reached("Unknown server type"); if (n->manager->current_server_name == n) manager_set_server_name(n->manager, NULL); } log_debug("Removed server %s.", n->string); free(n->string); free(n); return NULL; } void server_name_flush_addresses(ServerName *n) { assert(n); while (n->addresses) server_address_free(n->addresses); } systemd-229/src/timesync/timesyncd-server.h000066400000000000000000000035561265713322000211700ustar00rootroot00000000000000#pragma once /*** This file is part of systemd. Copyright 2014 Kay Sievers, Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "list.h" #include "socket-util.h" typedef struct ServerAddress ServerAddress; typedef struct ServerName ServerName; typedef enum ServerType { SERVER_SYSTEM, SERVER_FALLBACK, SERVER_LINK, } ServerType; #include "timesyncd-manager.h" struct ServerAddress { ServerName *name; union sockaddr_union sockaddr; socklen_t socklen; LIST_FIELDS(ServerAddress, addresses); }; struct ServerName { Manager *manager; ServerType type; char *string; bool marked:1; LIST_HEAD(ServerAddress, addresses); LIST_FIELDS(ServerName, names); }; int server_address_new(ServerName *n, ServerAddress **ret, const union sockaddr_union *sockaddr, socklen_t socklen); ServerAddress* server_address_free(ServerAddress *a); static inline int server_address_pretty(ServerAddress *a, char **pretty) { return sockaddr_pretty(&a->sockaddr.sa, a->socklen, true, true, pretty); } int server_name_new(Manager *m, ServerName **ret, ServerType type,const char *string); ServerName *server_name_free(ServerName *n); void server_name_flush_addresses(ServerName *n); systemd-229/src/timesync/timesyncd.c000066400000000000000000000124421265713322000176510ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Kay Sievers, Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "sd-daemon.h" #include "sd-event.h" #include "capability-util.h" #include "clock-util.h" #include "fd-util.h" #include "fs-util.h" #include "network-util.h" #include "signal-util.h" #include "timesyncd-conf.h" #include "timesyncd-manager.h" #include "user-util.h" static int load_clock_timestamp(uid_t uid, gid_t gid) { _cleanup_close_ int fd = -1; usec_t min = TIME_EPOCH * USEC_PER_SEC; usec_t ct; int r; /* Let's try to make sure that the clock is always * monotonically increasing, by saving the clock whenever we * have a new NTP time, or when we shut down, and restoring it * when we start again. This is particularly helpful on * systems lacking a battery backed RTC. We also will adjust * the time to at least the build time of systemd. */ fd = open("/var/lib/systemd/clock", O_RDWR|O_CLOEXEC, 0644); if (fd >= 0) { struct stat st; usec_t stamp; /* check if the recorded time is later than the compiled-in one */ r = fstat(fd, &st); if (r >= 0) { stamp = timespec_load(&st.st_mtim); if (stamp > min) min = stamp; } /* Try to fix the access mode, so that we can still touch the file after dropping priviliges */ (void) fchmod(fd, 0644); (void) fchown(fd, uid, gid); } else /* create stamp file with the compiled-in date */ (void) touch_file("/var/lib/systemd/clock", true, min, uid, gid, 0644); ct = now(CLOCK_REALTIME); if (ct < min) { struct timespec ts; char date[FORMAT_TIMESTAMP_MAX]; log_info("System clock time unset or jumped backwards, restoring from recorded timestamp: %s", format_timestamp(date, sizeof(date), min)); if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, min)) < 0) log_error_errno(errno, "Failed to restore system clock: %m"); } return 0; } int main(int argc, char *argv[]) { _cleanup_(manager_freep) Manager *m = NULL; const char *user = "systemd-timesync"; uid_t uid; gid_t gid; int r; log_set_target(LOG_TARGET_AUTO); log_set_facility(LOG_CRON); log_parse_environment(); log_open(); umask(0022); if (argc != 1) { log_error("This program does not take arguments."); r = -EINVAL; goto finish; } r = get_user_creds(&user, &uid, &gid, NULL, NULL); if (r < 0) { log_error_errno(r, "Cannot resolve user name %s: %m", user); goto finish; } r = load_clock_timestamp(uid, gid); if (r < 0) goto finish; r = drop_privileges(uid, gid, (1ULL << CAP_SYS_TIME)); if (r < 0) goto finish; assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); r = manager_new(&m); if (r < 0) { log_error_errno(r, "Failed to allocate manager: %m"); goto finish; } if (clock_is_localtime() > 0) { log_info("The system is configured to read the RTC time in the local time zone. " "This mode can not be fully supported. All system time to RTC updates are disabled."); m->rtc_local_time = true; } r = manager_parse_config_file(m); if (r < 0) log_warning_errno(r, "Failed to parse configuration file: %m"); log_debug("systemd-timesyncd running as pid " PID_FMT, getpid()); sd_notify(false, "READY=1\n" "STATUS=Daemon is running"); if (network_is_online()) { r = manager_connect(m); if (r < 0) goto finish; } r = sd_event_loop(m->event); if (r < 0) { log_error_errno(r, "Failed to run event loop: %m"); goto finish; } /* if we got an authoritative time, store it in the file system */ if (m->sync) (void) touch("/var/lib/systemd/clock"); sd_event_get_exit_code(m->event, &r); finish: sd_notify(false, "STOPPING=1\n" "STATUS=Shutting down..."); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/timesync/timesyncd.conf.in000066400000000000000000000010251265713322000207540ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # Entries in this file show the compile time defaults. # You can change settings by editing this file. # Defaults can be restored by simply deleting this file. # # See timesyncd.conf(5) for details. [Time] #NTP= #FallbackNTP=@NTP_SERVERS@ systemd-229/src/tmpfiles/000077500000000000000000000000001265713322000154735ustar00rootroot00000000000000systemd-229/src/tmpfiles/Makefile000077700000000000000000000000001265713322000210012../Makefileustar00rootroot00000000000000systemd-229/src/tmpfiles/tmpfiles.c000066400000000000000000002366121265713322000174740ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering, Kay Sievers Copyright 2015 Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "acl-util.h" #include "alloc-util.h" #include "btrfs-util.h" #include "capability-util.h" #include "chattr-util.h" #include "conf-files.h" #include "copy.h" #include "def.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "glob-util.h" #include "io-util.h" #include "label.h" #include "log.h" #include "macro.h" #include "missing.h" #include "mkdir.h" #include "mount-util.h" #include "parse-util.h" #include "path-util.h" #include "rm-rf.h" #include "selinux-util.h" #include "set.h" #include "specifier.h" #include "stat-util.h" #include "stdio-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "umask-util.h" #include "user-util.h" #include "util.h" /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates * them in the file system. This is intended to be used to create * properly owned directories beneath /tmp, /var/tmp, /run, which are * volatile and hence need to be recreated on bootup. */ typedef enum ItemType { /* These ones take file names */ CREATE_FILE = 'f', TRUNCATE_FILE = 'F', CREATE_DIRECTORY = 'd', TRUNCATE_DIRECTORY = 'D', CREATE_SUBVOLUME = 'v', CREATE_SUBVOLUME_INHERIT_QUOTA = 'q', CREATE_SUBVOLUME_NEW_QUOTA = 'Q', CREATE_FIFO = 'p', CREATE_SYMLINK = 'L', CREATE_CHAR_DEVICE = 'c', CREATE_BLOCK_DEVICE = 'b', COPY_FILES = 'C', /* These ones take globs */ WRITE_FILE = 'w', SET_XATTR = 't', RECURSIVE_SET_XATTR = 'T', SET_ACL = 'a', RECURSIVE_SET_ACL = 'A', SET_ATTRIBUTE = 'h', RECURSIVE_SET_ATTRIBUTE = 'H', IGNORE_PATH = 'x', IGNORE_DIRECTORY_PATH = 'X', REMOVE_PATH = 'r', RECURSIVE_REMOVE_PATH = 'R', RELABEL_PATH = 'z', RECURSIVE_RELABEL_PATH = 'Z', ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */ } ItemType; typedef struct Item { ItemType type; char *path; char *argument; char **xattrs; #ifdef HAVE_ACL acl_t acl_access; acl_t acl_default; #endif uid_t uid; gid_t gid; mode_t mode; usec_t age; dev_t major_minor; unsigned attribute_value; unsigned attribute_mask; bool uid_set:1; bool gid_set:1; bool mode_set:1; bool age_set:1; bool mask_perms:1; bool attribute_set:1; bool keep_first_level:1; bool force:1; bool done:1; } Item; typedef struct ItemArray { Item *items; size_t count; size_t size; } ItemArray; static bool arg_create = false; static bool arg_clean = false; static bool arg_remove = false; static bool arg_boot = false; static char **arg_include_prefixes = NULL; static char **arg_exclude_prefixes = NULL; static char *arg_root = NULL; static const char conf_file_dirs[] = CONF_PATHS_NULSTR("tmpfiles.d"); #define MAX_DEPTH 256 static OrderedHashmap *items = NULL, *globs = NULL; static Set *unix_sockets = NULL; static const Specifier specifier_table[] = { { 'm', specifier_machine_id, NULL }, { 'b', specifier_boot_id, NULL }, { 'H', specifier_host_name, NULL }, { 'v', specifier_kernel_release, NULL }, {} }; static bool needs_glob(ItemType t) { return IN_SET(t, WRITE_FILE, IGNORE_PATH, IGNORE_DIRECTORY_PATH, REMOVE_PATH, RECURSIVE_REMOVE_PATH, ADJUST_MODE, RELABEL_PATH, RECURSIVE_RELABEL_PATH, SET_XATTR, RECURSIVE_SET_XATTR, SET_ACL, RECURSIVE_SET_ACL, SET_ATTRIBUTE, RECURSIVE_SET_ATTRIBUTE); } static bool takes_ownership(ItemType t) { return IN_SET(t, CREATE_FILE, TRUNCATE_FILE, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_FIFO, CREATE_SYMLINK, CREATE_CHAR_DEVICE, CREATE_BLOCK_DEVICE, COPY_FILES, WRITE_FILE, IGNORE_PATH, IGNORE_DIRECTORY_PATH, REMOVE_PATH, RECURSIVE_REMOVE_PATH); } static struct Item* find_glob(OrderedHashmap *h, const char *match) { ItemArray *j; Iterator i; ORDERED_HASHMAP_FOREACH(j, h, i) { unsigned n; for (n = 0; n < j->count; n++) { Item *item = j->items + n; if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0) return item; } } return NULL; } static void load_unix_sockets(void) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; if (unix_sockets) return; /* We maintain a cache of the sockets we found in * /proc/net/unix to speed things up a little. */ unix_sockets = set_new(&string_hash_ops); if (!unix_sockets) return; f = fopen("/proc/net/unix", "re"); if (!f) return; /* Skip header */ if (!fgets(line, sizeof(line), f)) goto fail; for (;;) { char *p, *s; int k; if (!fgets(line, sizeof(line), f)) break; truncate_nl(line); p = strchr(line, ':'); if (!p) continue; if (strlen(p) < 37) continue; p += 37; p += strspn(p, WHITESPACE); p += strcspn(p, WHITESPACE); /* skip one more word */ p += strspn(p, WHITESPACE); if (*p != '/') continue; s = strdup(p); if (!s) goto fail; path_kill_slashes(s); k = set_consume(unix_sockets, s); if (k < 0 && k != -EEXIST) goto fail; } return; fail: set_free_free(unix_sockets); unix_sockets = NULL; } static bool unix_socket_alive(const char *fn) { assert(fn); load_unix_sockets(); if (unix_sockets) return !!set_get(unix_sockets, (char*) fn); /* We don't know, so assume yes */ return true; } static int dir_is_mount_point(DIR *d, const char *subdir) { union file_handle_union h = FILE_HANDLE_INIT; int mount_id_parent, mount_id; int r_p, r; r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0); if (r_p < 0) r_p = -errno; h.handle.handle_bytes = MAX_HANDLE_SZ; r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0); if (r < 0) r = -errno; /* got no handle; make no assumptions, return error */ if (r_p < 0 && r < 0) return r_p; /* got both handles; if they differ, it is a mount point */ if (r_p >= 0 && r >= 0) return mount_id_parent != mount_id; /* got only one handle; assume different mount points if one * of both queries was not supported by the filesystem */ if (r_p == -ENOSYS || r_p == -EOPNOTSUPP || r == -ENOSYS || r == -EOPNOTSUPP) return true; /* return error */ if (r_p < 0) return r_p; return r; } static DIR* xopendirat_nomod(int dirfd, const char *path) { DIR *dir; dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME); if (dir) return dir; log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path); if (errno != EPERM) return NULL; dir = xopendirat(dirfd, path, O_NOFOLLOW); if (!dir) log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path); return dir; } static DIR* opendir_nomod(const char *path) { return xopendirat_nomod(AT_FDCWD, path); } static int dir_cleanup( Item *i, const char *p, DIR *d, const struct stat *ds, usec_t cutoff, dev_t rootdev, bool mountpoint, int maxdepth, bool keep_this_level) { struct dirent *dent; struct timespec times[2]; bool deleted = false; int r = 0; while ((dent = readdir(d))) { struct stat s; usec_t age; _cleanup_free_ char *sub_path = NULL; if (STR_IN_SET(dent->d_name, ".", "..")) continue; if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) { if (errno == ENOENT) continue; /* FUSE, NFS mounts, SELinux might return EACCES */ if (errno == EACCES) log_debug_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name); else log_error_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name); r = -errno; continue; } /* Stay on the same filesystem */ if (s.st_dev != rootdev) { log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name); continue; } /* Try to detect bind mounts of the same filesystem instance; they * do not differ in device major/minors. This type of query is not * supported on all kernels or filesystem types though. */ if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0) { log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.", p, dent->d_name); continue; } /* Do not delete read-only files owned by root */ if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) { log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name); continue; } sub_path = strjoin(p, "/", dent->d_name, NULL); if (!sub_path) { r = log_oom(); goto finish; } /* Is there an item configured for this path? */ if (ordered_hashmap_get(items, sub_path)) { log_debug("Ignoring \"%s\": a separate entry exists.", sub_path); continue; } if (find_glob(globs, sub_path)) { log_debug("Ignoring \"%s\": a separate glob exists.", sub_path); continue; } if (S_ISDIR(s.st_mode)) { if (mountpoint && streq(dent->d_name, "lost+found") && s.st_uid == 0) { log_debug("Ignoring \"%s\".", sub_path); continue; } if (maxdepth <= 0) log_warning("Reached max depth on \"%s\".", sub_path); else { _cleanup_closedir_ DIR *sub_dir; int q; sub_dir = xopendirat_nomod(dirfd(d), dent->d_name); if (!sub_dir) { if (errno != ENOENT) r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path); continue; } q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false); if (q < 0) r = q; } /* Note: if you are wondering why we don't * support the sticky bit for excluding * directories from cleaning like we do it for * other file system objects: well, the sticky * bit already has a meaning for directories, * so we don't want to overload that. */ if (keep_this_level) { log_debug("Keeping \"%s\".", sub_path); continue; } /* Ignore ctime, we change it when deleting */ age = timespec_load(&s.st_mtim); if (age >= cutoff) { char a[FORMAT_TIMESTAMP_MAX]; /* Follows spelling in stat(1). */ log_debug("Directory \"%s\": modify time %s is too new.", sub_path, format_timestamp_us(a, sizeof(a), age)); continue; } age = timespec_load(&s.st_atim); if (age >= cutoff) { char a[FORMAT_TIMESTAMP_MAX]; log_debug("Directory \"%s\": access time %s is too new.", sub_path, format_timestamp_us(a, sizeof(a), age)); continue; } log_debug("Removing directory \"%s\".", sub_path); if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) if (errno != ENOENT && errno != ENOTEMPTY) { log_error_errno(errno, "rmdir(%s): %m", sub_path); r = -errno; } } else { /* Skip files for which the sticky bit is * set. These are semantics we define, and are * unknown elsewhere. See XDG_RUNTIME_DIR * specification for details. */ if (s.st_mode & S_ISVTX) { log_debug("Skipping \"%s\": sticky bit set.", sub_path); continue; } if (mountpoint && S_ISREG(s.st_mode)) if (s.st_uid == 0 && STR_IN_SET(dent->d_name, ".journal", "aquota.user", "aquota.group")) { log_debug("Skipping \"%s\".", sub_path); continue; } /* Ignore sockets that are listed in /proc/net/unix */ if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) { log_debug("Skipping \"%s\": live socket.", sub_path); continue; } /* Ignore device nodes */ if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) { log_debug("Skipping \"%s\": a device.", sub_path); continue; } /* Keep files on this level around if this is * requested */ if (keep_this_level) { log_debug("Keeping \"%s\".", sub_path); continue; } age = timespec_load(&s.st_mtim); if (age >= cutoff) { char a[FORMAT_TIMESTAMP_MAX]; /* Follows spelling in stat(1). */ log_debug("File \"%s\": modify time %s is too new.", sub_path, format_timestamp_us(a, sizeof(a), age)); continue; } age = timespec_load(&s.st_atim); if (age >= cutoff) { char a[FORMAT_TIMESTAMP_MAX]; log_debug("File \"%s\": access time %s is too new.", sub_path, format_timestamp_us(a, sizeof(a), age)); continue; } age = timespec_load(&s.st_ctim); if (age >= cutoff) { char a[FORMAT_TIMESTAMP_MAX]; log_debug("File \"%s\": change time %s is too new.", sub_path, format_timestamp_us(a, sizeof(a), age)); continue; } log_debug("unlink \"%s\"", sub_path); if (unlinkat(dirfd(d), dent->d_name, 0) < 0) if (errno != ENOENT) r = log_error_errno(errno, "unlink(%s): %m", sub_path); deleted = true; } } finish: if (deleted) { usec_t age1, age2; char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX]; /* Restore original directory timestamps */ times[0] = ds->st_atim; times[1] = ds->st_mtim; age1 = timespec_load(&ds->st_atim); age2 = timespec_load(&ds->st_mtim); log_debug("Restoring access and modification time on \"%s\": %s, %s", p, format_timestamp_us(a, sizeof(a), age1), format_timestamp_us(b, sizeof(b), age2)); if (futimens(dirfd(d), times) < 0) log_error_errno(errno, "utimensat(%s): %m", p); } return r; } static int path_set_perms(Item *i, const char *path) { _cleanup_close_ int fd = -1; struct stat st; assert(i); assert(path); /* We open the file with O_PATH here, to make the operation * somewhat atomic. Also there's unfortunately no fchmodat() * with AT_SYMLINK_NOFOLLOW, hence we emulate it here via * O_PATH. */ fd = open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH|O_NOATIME); if (fd < 0) return log_error_errno(errno, "Adjusting owner and mode for %s failed: %m", path); if (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0) return log_error_errno(errno, "Failed to fstat() file %s: %m", path); if (S_ISLNK(st.st_mode)) log_debug("Skipping mode an owner fix for symlink %s.", path); else { char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; xsprintf(fn, "/proc/self/fd/%i", fd); /* not using i->path directly because it may be a glob */ if (i->mode_set) { mode_t m = i->mode; if (i->mask_perms) { if (!(st.st_mode & 0111)) m &= ~0111; if (!(st.st_mode & 0222)) m &= ~0222; if (!(st.st_mode & 0444)) m &= ~0444; if (!S_ISDIR(st.st_mode)) m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */ } if (m == (st.st_mode & 07777)) log_debug("\"%s\" has right mode %o", path, st.st_mode); else { log_debug("chmod \"%s\" to mode %o", path, m); if (chmod(fn, m) < 0) return log_error_errno(errno, "chmod(%s) failed: %m", path); } } if ((i->uid != st.st_uid || i->gid != st.st_gid) && (i->uid_set || i->gid_set)) { log_debug("chown \"%s\" to "UID_FMT"."GID_FMT, path, i->uid_set ? i->uid : UID_INVALID, i->gid_set ? i->gid : GID_INVALID); if (chown(fn, i->uid_set ? i->uid : UID_INVALID, i->gid_set ? i->gid : GID_INVALID) < 0) return log_error_errno(errno, "chown(%s) failed: %m", path); } } fd = safe_close(fd); return label_fix(path, false, false); } static int parse_xattrs_from_arg(Item *i) { const char *p; int r; assert(i); assert(i->argument); p = i->argument; for (;;) { _cleanup_free_ char *name = NULL, *value = NULL, *xattr = NULL, *xattr_replaced = NULL; r = extract_first_word(&p, &xattr, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE); if (r < 0) log_warning_errno(r, "Failed to parse extended attribute '%s', ignoring: %m", p); if (r <= 0) break; r = specifier_printf(xattr, specifier_table, NULL, &xattr_replaced); if (r < 0) return log_error_errno(r, "Failed to replace specifiers in extended attribute '%s': %m", xattr); r = split_pair(xattr_replaced, "=", &name, &value); if (r < 0) { log_warning_errno(r, "Failed to parse extended attribute, ignoring: %s", xattr); continue; } if (isempty(name) || isempty(value)) { log_warning("Malformed extended attribute found, ignoring: %s", xattr); continue; } if (strv_push_pair(&i->xattrs, name, value) < 0) return log_oom(); name = value = NULL; } return 0; } static int path_set_xattrs(Item *i, const char *path) { char **name, **value; assert(i); assert(path); STRV_FOREACH_PAIR(name, value, i->xattrs) { int n; n = strlen(*value); log_debug("Setting extended attribute '%s=%s' on %s.", *name, *value, path); if (lsetxattr(path, *name, *value, n, 0) < 0) { log_error("Setting extended attribute %s=%s on %s failed: %m", *name, *value, path); return -errno; } } return 0; } static int parse_acls_from_arg(Item *item) { #ifdef HAVE_ACL int r; assert(item); /* If force (= modify) is set, we will not modify the acl * afterwards, so the mask can be added now if necessary. */ r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force); if (r < 0) log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring", item->argument); #else log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring"); #endif return 0; } #ifdef HAVE_ACL static int path_set_acl(const char *path, const char *pretty, acl_type_t type, acl_t acl, bool modify) { _cleanup_(acl_free_charpp) char *t = NULL; _cleanup_(acl_freep) acl_t dup = NULL; int r; /* Returns 0 for success, positive error if already warned, * negative error otherwise. */ if (modify) { r = acls_for_file(path, type, acl, &dup); if (r < 0) return r; r = calc_acl_mask_if_needed(&dup); if (r < 0) return r; } else { dup = acl_dup(acl); if (!dup) return -errno; /* the mask was already added earlier if needed */ } r = add_base_acls_if_needed(&dup, path); if (r < 0) return r; t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE); log_debug("Setting %s ACL %s on %s.", type == ACL_TYPE_ACCESS ? "access" : "default", strna(t), pretty); r = acl_set_file(path, type, dup); if (r < 0) /* Return positive to indicate we already warned */ return -log_error_errno(errno, "Setting %s ACL \"%s\" on %s failed: %m", type == ACL_TYPE_ACCESS ? "access" : "default", strna(t), pretty); return 0; } #endif static int path_set_acls(Item *item, const char *path) { int r = 0; #ifdef HAVE_ACL char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; _cleanup_close_ int fd = -1; struct stat st; assert(item); assert(path); fd = open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH|O_NOATIME); if (fd < 0) return log_error_errno(errno, "Adjusting ACL of %s failed: %m", path); if (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0) return log_error_errno(errno, "Failed to fstat() file %s: %m", path); if (S_ISLNK(st.st_mode)) { log_debug("Skipping ACL fix for symlink %s.", path); return 0; } xsprintf(fn, "/proc/self/fd/%i", fd); if (item->acl_access) r = path_set_acl(fn, path, ACL_TYPE_ACCESS, item->acl_access, item->force); if (r == 0 && item->acl_default) r = path_set_acl(fn, path, ACL_TYPE_DEFAULT, item->acl_default, item->force); if (r > 0) return -r; /* already warned */ else if (r == -EOPNOTSUPP) { log_debug_errno(r, "ACLs not supported by file system at %s", path); return 0; } else if (r < 0) log_error_errno(r, "ACL operation on \"%s\" failed: %m", path); #endif return r; } #define ATTRIBUTES_ALL \ (FS_NOATIME_FL | \ FS_SYNC_FL | \ FS_DIRSYNC_FL | \ FS_APPEND_FL | \ FS_COMPR_FL | \ FS_NODUMP_FL | \ FS_EXTENT_FL | \ FS_IMMUTABLE_FL | \ FS_JOURNAL_DATA_FL | \ FS_SECRM_FL | \ FS_UNRM_FL | \ FS_NOTAIL_FL | \ FS_TOPDIR_FL | \ FS_NOCOW_FL) static int parse_attribute_from_arg(Item *item) { static const struct { char character; unsigned value; } attributes[] = { { 'A', FS_NOATIME_FL }, /* do not update atime */ { 'S', FS_SYNC_FL }, /* Synchronous updates */ { 'D', FS_DIRSYNC_FL }, /* dirsync behaviour (directories only) */ { 'a', FS_APPEND_FL }, /* writes to file may only append */ { 'c', FS_COMPR_FL }, /* Compress file */ { 'd', FS_NODUMP_FL }, /* do not dump file */ { 'e', FS_EXTENT_FL }, /* Top of directory hierarchies*/ { 'i', FS_IMMUTABLE_FL }, /* Immutable file */ { 'j', FS_JOURNAL_DATA_FL }, /* Reserved for ext3 */ { 's', FS_SECRM_FL }, /* Secure deletion */ { 'u', FS_UNRM_FL }, /* Undelete */ { 't', FS_NOTAIL_FL }, /* file tail should not be merged */ { 'T', FS_TOPDIR_FL }, /* Top of directory hierarchies*/ { 'C', FS_NOCOW_FL }, /* Do not cow file */ }; enum { MODE_ADD, MODE_DEL, MODE_SET } mode = MODE_ADD; unsigned value = 0, mask = 0; const char *p; assert(item); p = item->argument; if (p) { if (*p == '+') { mode = MODE_ADD; p++; } else if (*p == '-') { mode = MODE_DEL; p++; } else if (*p == '=') { mode = MODE_SET; p++; } } if (isempty(p) && mode != MODE_SET) { log_error("Setting file attribute on '%s' needs an attribute specification.", item->path); return -EINVAL; } for (; p && *p ; p++) { unsigned i, v; for (i = 0; i < ELEMENTSOF(attributes); i++) if (*p == attributes[i].character) break; if (i >= ELEMENTSOF(attributes)) { log_error("Unknown file attribute '%c' on '%s'.", *p, item->path); return -EINVAL; } v = attributes[i].value; if (mode == MODE_ADD || mode == MODE_SET) value |= v; else value &= ~v; mask |= v; } if (mode == MODE_SET) mask |= ATTRIBUTES_ALL; assert(mask != 0); item->attribute_mask = mask; item->attribute_value = value; item->attribute_set = true; return 0; } static int path_set_attribute(Item *item, const char *path) { _cleanup_close_ int fd = -1; struct stat st; unsigned f; int r; if (!item->attribute_set || item->attribute_mask == 0) return 0; fd = open(path, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOATIME|O_NOFOLLOW); if (fd < 0) { if (errno == ELOOP) return log_error_errno(errno, "Skipping file attributes adjustment on symlink %s.", path); return log_error_errno(errno, "Cannot open '%s': %m", path); } if (fstat(fd, &st) < 0) return log_error_errno(errno, "Cannot stat '%s': %m", path); /* Issuing the file attribute ioctls on device nodes is not * safe, as that will be delivered to the drivers, not the * file system containing the device node. */ if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) { log_error("Setting file flags is only supported on regular files and directories, cannot set on '%s'.", path); return -EINVAL; } f = item->attribute_value & item->attribute_mask; /* Mask away directory-specific flags */ if (!S_ISDIR(st.st_mode)) f &= ~FS_DIRSYNC_FL; r = chattr_fd(fd, f, item->attribute_mask); if (r < 0) log_full_errno(r == -ENOTTY ? LOG_DEBUG : LOG_WARNING, r, "Cannot set file attribute for '%s', value=0x%08x, mask=0x%08x: %m", path, item->attribute_value, item->attribute_mask); return 0; } static int write_one_file(Item *i, const char *path) { _cleanup_close_ int fd = -1; int flags, r = 0; struct stat st; assert(i); assert(path); flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW : i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0; RUN_WITH_UMASK(0000) { mac_selinux_create_file_prepare(path, S_IFREG); fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode); mac_selinux_create_file_clear(); } if (fd < 0) { if (i->type == WRITE_FILE && errno == ENOENT) { log_debug_errno(errno, "Not writing \"%s\": %m", path); return 0; } r = -errno; if (!i->argument && errno == EROFS && stat(path, &st) == 0 && (i->type == CREATE_FILE || st.st_size == 0)) goto check_mode; return log_error_errno(r, "Failed to create file %s: %m", path); } if (i->argument) { _cleanup_free_ char *unescaped = NULL, *replaced = NULL; log_debug("%s to \"%s\".", i->type == CREATE_FILE ? "Appending" : "Writing", path); r = cunescape(i->argument, 0, &unescaped); if (r < 0) return log_error_errno(r, "Failed to unescape parameter to write: %s", i->argument); r = specifier_printf(unescaped, specifier_table, NULL, &replaced); if (r < 0) return log_error_errno(r, "Failed to replace specifiers in parameter to write '%s': %m", unescaped); r = loop_write(fd, replaced, strlen(replaced), false); if (r < 0) return log_error_errno(r, "Failed to write file \"%s\": %m", path); } else log_debug("\"%s\" has been created.", path); fd = safe_close(fd); if (stat(path, &st) < 0) return log_error_errno(errno, "stat(%s) failed: %m", path); check_mode: if (!S_ISREG(st.st_mode)) { log_error("%s is not a file.", path); return -EEXIST; } r = path_set_perms(i, path); if (r < 0) return r; return 0; } typedef int (*action_t)(Item *, const char *); static int item_do_children(Item *i, const char *path, action_t action) { _cleanup_closedir_ DIR *d; int r = 0; assert(i); assert(path); /* This returns the first error we run into, but nevertheless * tries to go on */ d = opendir_nomod(path); if (!d) return errno == ENOENT || errno == ENOTDIR ? 0 : -errno; for (;;) { _cleanup_free_ char *p = NULL; struct dirent *de; int q; errno = 0; de = readdir(d); if (!de) { if (errno > 0 && r == 0) r = -errno; break; } if (STR_IN_SET(de->d_name, ".", "..")) continue; p = strjoin(path, "/", de->d_name, NULL); if (!p) return -ENOMEM; q = action(i, p); if (q < 0 && q != -ENOENT && r == 0) r = q; if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) { q = item_do_children(i, p, action); if (q < 0 && r == 0) r = q; } } return r; } static int glob_item(Item *i, action_t action, bool recursive) { _cleanup_globfree_ glob_t g = { .gl_closedir = (void (*)(void *)) closedir, .gl_readdir = (struct dirent *(*)(void *)) readdir, .gl_opendir = (void *(*)(const char *)) opendir_nomod, .gl_lstat = lstat, .gl_stat = stat, }; int r = 0, k; char **fn; errno = 0; k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g); if (k != 0 && k != GLOB_NOMATCH) return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path); STRV_FOREACH(fn, g.gl_pathv) { k = action(i, *fn); if (k < 0 && r == 0) r = k; if (recursive) { k = item_do_children(i, *fn, action); if (k < 0 && r == 0) r = k; } } return r; } typedef enum { CREATION_NORMAL, CREATION_EXISTING, CREATION_FORCE, _CREATION_MODE_MAX, _CREATION_MODE_INVALID = -1 } CreationMode; static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = { [CREATION_NORMAL] = "Created", [CREATION_EXISTING] = "Found existing", [CREATION_FORCE] = "Created replacement", }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode); static int create_item(Item *i) { _cleanup_free_ char *resolved = NULL; struct stat st; int r = 0; int q = 0; CreationMode creation; assert(i); log_debug("Running create action for entry %c %s", (char) i->type, i->path); switch (i->type) { case IGNORE_PATH: case IGNORE_DIRECTORY_PATH: case REMOVE_PATH: case RECURSIVE_REMOVE_PATH: return 0; case CREATE_FILE: case TRUNCATE_FILE: r = write_one_file(i, i->path); if (r < 0) return r; break; case COPY_FILES: { r = specifier_printf(i->argument, specifier_table, NULL, &resolved); if (r < 0) return log_error_errno(r, "Failed to substitute specifiers in copy source %s: %m", i->argument); log_debug("Copying tree \"%s\" to \"%s\".", resolved, i->path); r = copy_tree(resolved, i->path, false); if (r == -EROFS && stat(i->path, &st) == 0) r = -EEXIST; if (r < 0) { struct stat a, b; if (r != -EEXIST) return log_error_errno(r, "Failed to copy files to %s: %m", i->path); if (stat(resolved, &a) < 0) return log_error_errno(errno, "stat(%s) failed: %m", resolved); if (stat(i->path, &b) < 0) return log_error_errno(errno, "stat(%s) failed: %m", i->path); if ((a.st_mode ^ b.st_mode) & S_IFMT) { log_debug("Can't copy to %s, file exists already and is of different type", i->path); return 0; } } r = path_set_perms(i, i->path); if (r < 0) return r; break; case WRITE_FILE: r = glob_item(i, write_one_file, false); if (r < 0) return r; break; case CREATE_DIRECTORY: case TRUNCATE_DIRECTORY: case CREATE_SUBVOLUME: case CREATE_SUBVOLUME_INHERIT_QUOTA: case CREATE_SUBVOLUME_NEW_QUOTA: RUN_WITH_UMASK(0000) mkdir_parents_label(i->path, 0755); if (IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) { if (btrfs_is_subvol(isempty(arg_root) ? "/" : arg_root) <= 0) /* Don't create a subvolume unless the * root directory is one, too. We do * this under the assumption that if * the root directory is just a plain * directory (i.e. very light-weight), * we shouldn't try to split it up * into subvolumes (i.e. more * heavy-weight). Thus, chroot() * environments and suchlike will get * a full brtfs subvolume set up below * their tree only if they * specifically set up a btrfs * subvolume for the root dir too. */ r = -ENOTTY; else { RUN_WITH_UMASK((~i->mode) & 0777) r = btrfs_subvol_make(i->path); } } else r = 0; if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY) RUN_WITH_UMASK(0000) r = mkdir_label(i->path, i->mode); if (r < 0) { int k; if (r != -EEXIST && r != -EROFS) return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path); k = is_dir(i->path, false); if (k == -ENOENT && r == -EROFS) return log_error_errno(r, "%s does not exist and cannot be created as the file system is read-only.", i->path); if (k < 0) return log_error_errno(k, "Failed to check if %s exists: %m", i->path); if (!k) { log_warning("\"%s\" already exists and is not a directory.", i->path); return 0; } creation = CREATION_EXISTING; } else creation = CREATION_NORMAL; log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), i->path); if (IN_SET(i->type, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA)) { r = btrfs_subvol_auto_qgroup(i->path, 0, i->type == CREATE_SUBVOLUME_NEW_QUOTA); if (r == -ENOTTY) log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" because of unsupported file system or because directory is not a subvolume: %m", i->path); else if (r == -EROFS) log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" because of read-only file system: %m", i->path); else if (r == -ENOPROTOOPT) log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" because quota support is disabled: %m", i->path); else if (r < 0) q = log_error_errno(r, "Failed to adjust quota for subvolume \"%s\": %m", i->path); else if (r > 0) log_debug("Adjusted quota for subvolume \"%s\".", i->path); else if (r == 0) log_debug("Quota for subvolume \"%s\" already in place, no change made.", i->path); } r = path_set_perms(i, i->path); if (q < 0) return q; if (r < 0) return r; break; case CREATE_FIFO: RUN_WITH_UMASK(0000) { mac_selinux_create_file_prepare(i->path, S_IFIFO); r = mkfifo(i->path, i->mode); mac_selinux_create_file_clear(); } if (r < 0) { if (errno != EEXIST) return log_error_errno(errno, "Failed to create fifo %s: %m", i->path); if (lstat(i->path, &st) < 0) return log_error_errno(errno, "stat(%s) failed: %m", i->path); if (!S_ISFIFO(st.st_mode)) { if (i->force) { RUN_WITH_UMASK(0000) { mac_selinux_create_file_prepare(i->path, S_IFIFO); r = mkfifo_atomic(i->path, i->mode); mac_selinux_create_file_clear(); } if (r < 0) return log_error_errno(r, "Failed to create fifo %s: %m", i->path); creation = CREATION_FORCE; } else { log_warning("\"%s\" already exists and is not a fifo.", i->path); return 0; } } else creation = CREATION_EXISTING; } else creation = CREATION_NORMAL; log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path); r = path_set_perms(i, i->path); if (r < 0) return r; break; } case CREATE_SYMLINK: { r = specifier_printf(i->argument, specifier_table, NULL, &resolved); if (r < 0) return log_error_errno(r, "Failed to substitute specifiers in symlink target %s: %m", i->argument); mac_selinux_create_file_prepare(i->path, S_IFLNK); r = symlink(resolved, i->path); mac_selinux_create_file_clear(); if (r < 0) { _cleanup_free_ char *x = NULL; if (errno != EEXIST) return log_error_errno(errno, "symlink(%s, %s) failed: %m", resolved, i->path); r = readlink_malloc(i->path, &x); if (r < 0 || !streq(resolved, x)) { if (i->force) { mac_selinux_create_file_prepare(i->path, S_IFLNK); r = symlink_atomic(resolved, i->path); mac_selinux_create_file_clear(); if (r < 0) return log_error_errno(r, "symlink(%s, %s) failed: %m", resolved, i->path); creation = CREATION_FORCE; } else { log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path); return 0; } } else creation = CREATION_EXISTING; } else creation = CREATION_NORMAL; log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path); break; } case CREATE_BLOCK_DEVICE: case CREATE_CHAR_DEVICE: { mode_t file_type; if (have_effective_cap(CAP_MKNOD) == 0) { /* In a container we lack CAP_MKNOD. We shouldn't attempt to create the device node in that case to avoid noise, and we don't support virtualized devices in containers anyway. */ log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path); return 0; } file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR; RUN_WITH_UMASK(0000) { mac_selinux_create_file_prepare(i->path, file_type); r = mknod(i->path, i->mode | file_type, i->major_minor); mac_selinux_create_file_clear(); } if (r < 0) { if (errno == EPERM) { log_debug("We lack permissions, possibly because of cgroup configuration; " "skipping creation of device node %s.", i->path); return 0; } if (errno != EEXIST) return log_error_errno(errno, "Failed to create device node %s: %m", i->path); if (lstat(i->path, &st) < 0) return log_error_errno(errno, "stat(%s) failed: %m", i->path); if ((st.st_mode & S_IFMT) != file_type) { if (i->force) { RUN_WITH_UMASK(0000) { mac_selinux_create_file_prepare(i->path, file_type); r = mknod_atomic(i->path, i->mode | file_type, i->major_minor); mac_selinux_create_file_clear(); } if (r < 0) return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path); creation = CREATION_FORCE; } else { log_debug("%s is not a device node.", i->path); return 0; } } else creation = CREATION_EXISTING; } else creation = CREATION_NORMAL; log_debug("%s %s device node \"%s\" %u:%u.", creation_mode_verb_to_string(creation), i->type == CREATE_BLOCK_DEVICE ? "block" : "char", i->path, major(i->mode), minor(i->mode)); r = path_set_perms(i, i->path); if (r < 0) return r; break; } case ADJUST_MODE: case RELABEL_PATH: r = glob_item(i, path_set_perms, false); if (r < 0) return r; break; case RECURSIVE_RELABEL_PATH: r = glob_item(i, path_set_perms, true); if (r < 0) return r; break; case SET_XATTR: r = glob_item(i, path_set_xattrs, false); if (r < 0) return r; break; case RECURSIVE_SET_XATTR: r = glob_item(i, path_set_xattrs, true); if (r < 0) return r; break; case SET_ACL: r = glob_item(i, path_set_acls, false); if (r < 0) return r; break; case RECURSIVE_SET_ACL: r = glob_item(i, path_set_acls, true); if (r < 0) return r; break; case SET_ATTRIBUTE: r = glob_item(i, path_set_attribute, false); if (r < 0) return r; break; case RECURSIVE_SET_ATTRIBUTE: r = glob_item(i, path_set_attribute, true); if (r < 0) return r; break; } return 0; } static int remove_item_instance(Item *i, const char *instance) { int r; assert(i); switch (i->type) { case REMOVE_PATH: if (remove(instance) < 0 && errno != ENOENT) return log_error_errno(errno, "rm(%s): %m", instance); break; case TRUNCATE_DIRECTORY: case RECURSIVE_REMOVE_PATH: /* FIXME: we probably should use dir_cleanup() here * instead of rm_rf() so that 'x' is honoured. */ log_debug("rm -rf \"%s\"", instance); r = rm_rf(instance, (i->type == RECURSIVE_REMOVE_PATH ? REMOVE_ROOT|REMOVE_SUBVOLUME : 0) | REMOVE_PHYSICAL); if (r < 0 && r != -ENOENT) return log_error_errno(r, "rm_rf(%s): %m", instance); break; default: assert_not_reached("wut?"); } return 0; } static int remove_item(Item *i) { int r = 0; assert(i); log_debug("Running remove action for entry %c %s", (char) i->type, i->path); switch (i->type) { case CREATE_FILE: case TRUNCATE_FILE: case CREATE_DIRECTORY: case CREATE_SUBVOLUME: case CREATE_SUBVOLUME_INHERIT_QUOTA: case CREATE_SUBVOLUME_NEW_QUOTA: case CREATE_FIFO: case CREATE_SYMLINK: case CREATE_CHAR_DEVICE: case CREATE_BLOCK_DEVICE: case IGNORE_PATH: case IGNORE_DIRECTORY_PATH: case ADJUST_MODE: case RELABEL_PATH: case RECURSIVE_RELABEL_PATH: case WRITE_FILE: case COPY_FILES: case SET_XATTR: case RECURSIVE_SET_XATTR: case SET_ACL: case RECURSIVE_SET_ACL: case SET_ATTRIBUTE: case RECURSIVE_SET_ATTRIBUTE: break; case REMOVE_PATH: case TRUNCATE_DIRECTORY: case RECURSIVE_REMOVE_PATH: r = glob_item(i, remove_item_instance, false); break; } return r; } static int clean_item_instance(Item *i, const char* instance) { _cleanup_closedir_ DIR *d = NULL; struct stat s, ps; bool mountpoint; usec_t cutoff, n; char timestamp[FORMAT_TIMESTAMP_MAX]; assert(i); if (!i->age_set) return 0; n = now(CLOCK_REALTIME); if (n < i->age) return 0; cutoff = n - i->age; d = opendir_nomod(instance); if (!d) { if (errno == ENOENT || errno == ENOTDIR) { log_debug_errno(errno, "Directory \"%s\": %m", instance); return 0; } log_error_errno(errno, "Failed to open directory %s: %m", instance); return -errno; } if (fstat(dirfd(d), &s) < 0) return log_error_errno(errno, "stat(%s) failed: %m", i->path); if (!S_ISDIR(s.st_mode)) { log_error("%s is not a directory.", i->path); return -ENOTDIR; } if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) return log_error_errno(errno, "stat(%s/..) failed: %m", i->path); mountpoint = s.st_dev != ps.st_dev || s.st_ino == ps.st_ino; log_debug("Cleanup threshold for %s \"%s\" is %s", mountpoint ? "mount point" : "directory", instance, format_timestamp_us(timestamp, sizeof(timestamp), cutoff)); return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint, MAX_DEPTH, i->keep_first_level); } static int clean_item(Item *i) { int r = 0; assert(i); log_debug("Running clean action for entry %c %s", (char) i->type, i->path); switch (i->type) { case CREATE_DIRECTORY: case CREATE_SUBVOLUME: case CREATE_SUBVOLUME_INHERIT_QUOTA: case CREATE_SUBVOLUME_NEW_QUOTA: case TRUNCATE_DIRECTORY: case IGNORE_PATH: case COPY_FILES: clean_item_instance(i, i->path); break; case IGNORE_DIRECTORY_PATH: r = glob_item(i, clean_item_instance, false); break; default: break; } return r; } static int process_item_array(ItemArray *array); static int process_item(Item *i) { int r, q, p, t = 0; _cleanup_free_ char *prefix = NULL; assert(i); if (i->done) return 0; i->done = true; prefix = malloc(strlen(i->path) + 1); if (!prefix) return log_oom(); PATH_FOREACH_PREFIX(prefix, i->path) { ItemArray *j; j = ordered_hashmap_get(items, prefix); if (j) { int s; s = process_item_array(j); if (s < 0 && t == 0) t = s; } } r = arg_create ? create_item(i) : 0; q = arg_remove ? remove_item(i) : 0; p = arg_clean ? clean_item(i) : 0; return t < 0 ? t : r < 0 ? r : q < 0 ? q : p; } static int process_item_array(ItemArray *array) { unsigned n; int r = 0, k; assert(array); for (n = 0; n < array->count; n++) { k = process_item(array->items + n); if (k < 0 && r == 0) r = k; } return r; } static void item_free_contents(Item *i) { assert(i); free(i->path); free(i->argument); strv_free(i->xattrs); #ifdef HAVE_ACL acl_free(i->acl_access); acl_free(i->acl_default); #endif } static void item_array_free(ItemArray *a) { unsigned n; if (!a) return; for (n = 0; n < a->count; n++) item_free_contents(a->items + n); free(a->items); free(a); } static int item_compare(const void *a, const void *b) { const Item *x = a, *y = b; /* Make sure that the ownership taking item is put first, so * that we first create the node, and then can adjust it */ if (takes_ownership(x->type) && !takes_ownership(y->type)) return -1; if (!takes_ownership(x->type) && takes_ownership(y->type)) return 1; return (int) x->type - (int) y->type; } static bool item_compatible(Item *a, Item *b) { assert(a); assert(b); assert(streq(a->path, b->path)); if (takes_ownership(a->type) && takes_ownership(b->type)) /* check if the items are the same */ return streq_ptr(a->argument, b->argument) && a->uid_set == b->uid_set && a->uid == b->uid && a->gid_set == b->gid_set && a->gid == b->gid && a->mode_set == b->mode_set && a->mode == b->mode && a->age_set == b->age_set && a->age == b->age && a->mask_perms == b->mask_perms && a->keep_first_level == b->keep_first_level && a->major_minor == b->major_minor; return true; } static bool should_include_path(const char *path) { char **prefix; STRV_FOREACH(prefix, arg_exclude_prefixes) if (path_startswith(path, *prefix)) { log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.", path, *prefix); return false; } STRV_FOREACH(prefix, arg_include_prefixes) if (path_startswith(path, *prefix)) { log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix); return true; } /* no matches, so we should include this path only if we * have no whitelist at all */ if (strv_length(arg_include_prefixes) == 0) return true; log_debug("Entry \"%s\" does not match any include prefix, skipping.", path); return false; } static int parse_line(const char *fname, unsigned line, const char *buffer) { _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL; _cleanup_(item_free_contents) Item i = {}; ItemArray *existing; OrderedHashmap *h; int r, pos; bool force = false, boot = false; assert(fname); assert(line >= 1); assert(buffer); r = extract_many_words( &buffer, NULL, EXTRACT_QUOTES, &action, &path, &mode, &user, &group, &age, NULL); if (r < 0) return log_error_errno(r, "[%s:%u] Failed to parse line: %m", fname, line); else if (r < 2) { log_error("[%s:%u] Syntax error.", fname, line); return -EIO; } if (!isempty(buffer) && !streq(buffer, "-")) { i.argument = strdup(buffer); if (!i.argument) return log_oom(); } if (isempty(action)) { log_error("[%s:%u] Command too short '%s'.", fname, line, action); return -EINVAL; } for (pos = 1; action[pos]; pos++) { if (action[pos] == '!' && !boot) boot = true; else if (action[pos] == '+' && !force) force = true; else { log_error("[%s:%u] Unknown modifiers in command '%s'", fname, line, action); return -EINVAL; } } if (boot && !arg_boot) { log_debug("Ignoring entry %s \"%s\" because --boot is not specified.", action, path); return 0; } i.type = action[0]; i.force = force; r = specifier_printf(path, specifier_table, NULL, &i.path); if (r < 0) { log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path); return r; } switch (i.type) { case CREATE_DIRECTORY: case CREATE_SUBVOLUME: case CREATE_SUBVOLUME_INHERIT_QUOTA: case CREATE_SUBVOLUME_NEW_QUOTA: case TRUNCATE_DIRECTORY: case CREATE_FIFO: case IGNORE_PATH: case IGNORE_DIRECTORY_PATH: case REMOVE_PATH: case RECURSIVE_REMOVE_PATH: case ADJUST_MODE: case RELABEL_PATH: case RECURSIVE_RELABEL_PATH: if (i.argument) log_warning("[%s:%u] %c lines don't take argument fields, ignoring.", fname, line, i.type); break; case CREATE_FILE: case TRUNCATE_FILE: break; case CREATE_SYMLINK: if (!i.argument) { i.argument = strappend("/usr/share/factory/", i.path); if (!i.argument) return log_oom(); } break; case WRITE_FILE: if (!i.argument) { log_error("[%s:%u] Write file requires argument.", fname, line); return -EBADMSG; } break; case COPY_FILES: if (!i.argument) { i.argument = strappend("/usr/share/factory/", i.path); if (!i.argument) return log_oom(); } else if (!path_is_absolute(i.argument)) { log_error("[%s:%u] Source path is not absolute.", fname, line); return -EBADMSG; } path_kill_slashes(i.argument); break; case CREATE_CHAR_DEVICE: case CREATE_BLOCK_DEVICE: { unsigned major, minor; if (!i.argument) { log_error("[%s:%u] Device file requires argument.", fname, line); return -EBADMSG; } if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) { log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument); return -EBADMSG; } i.major_minor = makedev(major, minor); break; } case SET_XATTR: case RECURSIVE_SET_XATTR: if (!i.argument) { log_error("[%s:%u] Set extended attribute requires argument.", fname, line); return -EBADMSG; } r = parse_xattrs_from_arg(&i); if (r < 0) return r; break; case SET_ACL: case RECURSIVE_SET_ACL: if (!i.argument) { log_error("[%s:%u] Set ACLs requires argument.", fname, line); return -EBADMSG; } r = parse_acls_from_arg(&i); if (r < 0) return r; break; case SET_ATTRIBUTE: case RECURSIVE_SET_ATTRIBUTE: if (!i.argument) { log_error("[%s:%u] Set file attribute requires argument.", fname, line); return -EBADMSG; } r = parse_attribute_from_arg(&i); if (r < 0) return r; break; default: log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type); return -EBADMSG; } if (!path_is_absolute(i.path)) { log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path); return -EBADMSG; } path_kill_slashes(i.path); if (!should_include_path(i.path)) return 0; if (arg_root) { char *p; p = prefix_root(arg_root, i.path); if (!p) return log_oom(); free(i.path); i.path = p; } if (!isempty(user) && !streq(user, "-")) { const char *u = user; r = get_user_creds(&u, &i.uid, NULL, NULL, NULL); if (r < 0) { log_error("[%s:%u] Unknown user '%s'.", fname, line, user); return r; } i.uid_set = true; } if (!isempty(group) && !streq(group, "-")) { const char *g = group; r = get_group_creds(&g, &i.gid); if (r < 0) { log_error("[%s:%u] Unknown group '%s'.", fname, line, group); return r; } i.gid_set = true; } if (!isempty(mode) && !streq(mode, "-")) { const char *mm = mode; unsigned m; if (*mm == '~') { i.mask_perms = true; mm++; } if (parse_mode(mm, &m) < 0) { log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode); return -EBADMSG; } i.mode = m; i.mode_set = true; } else i.mode = IN_SET(i.type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA) ? 0755 : 0644; if (!isempty(age) && !streq(age, "-")) { const char *a = age; if (*a == '~') { i.keep_first_level = true; a++; } if (parse_sec(a, &i.age) < 0) { log_error("[%s:%u] Invalid age '%s'.", fname, line, age); return -EBADMSG; } i.age_set = true; } h = needs_glob(i.type) ? globs : items; existing = ordered_hashmap_get(h, i.path); if (existing) { unsigned n; for (n = 0; n < existing->count; n++) { if (!item_compatible(existing->items + n, &i)) { log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.", fname, line, i.path); return 0; } } } else { existing = new0(ItemArray, 1); r = ordered_hashmap_put(h, i.path, existing); if (r < 0) return log_oom(); } if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1)) return log_oom(); memcpy(existing->items + existing->count++, &i, sizeof(i)); /* Sort item array, to enforce stable ordering of application */ qsort_safe(existing->items, existing->count, sizeof(Item), item_compare); zero(i); return 0; } static void help(void) { printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n" "Creates, deletes and cleans up volatile and temporary files and directories.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --create Create marked files/directories\n" " --clean Clean up marked directories\n" " --remove Remove marked files/directories\n" " --boot Execute actions only safe at boot\n" " --prefix=PATH Only apply rules with the specified prefix\n" " --exclude-prefix=PATH Ignore rules with the specified prefix\n" " --root=PATH Operate on an alternate filesystem root\n", program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_CREATE, ARG_CLEAN, ARG_REMOVE, ARG_BOOT, ARG_PREFIX, ARG_EXCLUDE_PREFIX, ARG_ROOT, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "create", no_argument, NULL, ARG_CREATE }, { "clean", no_argument, NULL, ARG_CLEAN }, { "remove", no_argument, NULL, ARG_REMOVE }, { "boot", no_argument, NULL, ARG_BOOT }, { "prefix", required_argument, NULL, ARG_PREFIX }, { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX }, { "root", required_argument, NULL, ARG_ROOT }, {} }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_CREATE: arg_create = true; break; case ARG_CLEAN: arg_clean = true; break; case ARG_REMOVE: arg_remove = true; break; case ARG_BOOT: arg_boot = true; break; case ARG_PREFIX: if (strv_push(&arg_include_prefixes, optarg) < 0) return log_oom(); break; case ARG_EXCLUDE_PREFIX: if (strv_push(&arg_exclude_prefixes, optarg) < 0) return log_oom(); break; case ARG_ROOT: r = parse_path_argument_and_warn(optarg, true, &arg_root); if (r < 0) return r; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (!arg_clean && !arg_create && !arg_remove) { log_error("You need to specify at least one of --clean, --create or --remove."); return -EINVAL; } return 1; } static int read_config_file(const char *fn, bool ignore_enoent) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; Iterator iterator; unsigned v = 0; Item *i; int r; assert(fn); r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &f); if (r < 0) { if (ignore_enoent && r == -ENOENT) { log_debug_errno(r, "Failed to open \"%s\": %m", fn); return 0; } return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn); } log_debug("Reading config file \"%s\".", fn); FOREACH_LINE(line, f, break) { char *l; int k; v++; l = strstrip(line); if (*l == '#' || *l == 0) continue; k = parse_line(fn, v, l); if (k < 0 && r == 0) r = k; } /* we have to determine age parameter for each entry of type X */ ORDERED_HASHMAP_FOREACH(i, globs, iterator) { Iterator iter; Item *j, *candidate_item = NULL; if (i->type != IGNORE_DIRECTORY_PATH) continue; ORDERED_HASHMAP_FOREACH(j, items, iter) { if (!IN_SET(j->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) continue; if (path_equal(j->path, i->path)) { candidate_item = j; break; } if ((!candidate_item && path_startswith(i->path, j->path)) || (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0))) candidate_item = j; } if (candidate_item && candidate_item->age_set) { i->age = candidate_item->age; i->age_set = true; } } if (ferror(f)) { log_error_errno(errno, "Failed to read from file %s: %m", fn); if (r == 0) r = -EIO; } return r; } int main(int argc, char *argv[]) { int r, k; ItemArray *a; Iterator iterator; r = parse_argv(argc, argv); if (r <= 0) goto finish; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); mac_selinux_init(NULL); items = ordered_hashmap_new(&string_hash_ops); globs = ordered_hashmap_new(&string_hash_ops); if (!items || !globs) { r = log_oom(); goto finish; } r = 0; if (optind < argc) { int j; for (j = optind; j < argc; j++) { k = read_config_file(argv[j], false); if (k < 0 && r == 0) r = k; } } else { _cleanup_strv_free_ char **files = NULL; char **f; r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs); if (r < 0) { log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m"); goto finish; } STRV_FOREACH(f, files) { k = read_config_file(*f, true); if (k < 0 && r == 0) r = k; } } /* The non-globbing ones usually create things, hence we apply * them first */ ORDERED_HASHMAP_FOREACH(a, items, iterator) { k = process_item_array(a); if (k < 0 && r == 0) r = k; } /* The globbing ones usually alter things, hence we apply them * second. */ ORDERED_HASHMAP_FOREACH(a, globs, iterator) { k = process_item_array(a); if (k < 0 && r == 0) r = k; } finish: while ((a = ordered_hashmap_steal_first(items))) item_array_free(a); while ((a = ordered_hashmap_steal_first(globs))) item_array_free(a); ordered_hashmap_free(items); ordered_hashmap_free(globs); free(arg_include_prefixes); free(arg_exclude_prefixes); free(arg_root); set_free_free(unix_sockets); mac_selinux_finish(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/tty-ask-password-agent/000077500000000000000000000000001265713322000202005ustar00rootroot00000000000000systemd-229/src/tty-ask-password-agent/Makefile000077700000000000000000000000001265713322000235062../Makefileustar00rootroot00000000000000systemd-229/src/tty-ask-password-agent/tty-ask-password-agent.c000066400000000000000000000523341265713322000247030ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "ask-password-api.h" #include "conf-parser.h" #include "def.h" #include "dirent-util.h" #include "fd-util.h" #include "io-util.h" #include "mkdir.h" #include "path-util.h" #include "process-util.h" #include "signal-util.h" #include "socket-util.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "util.h" #include "utmp-wtmp.h" static enum { ACTION_LIST, ACTION_QUERY, ACTION_WATCH, ACTION_WALL } arg_action = ACTION_QUERY; static bool arg_plymouth = false; static bool arg_console = false; static int ask_password_plymouth( const char *message, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret) { _cleanup_close_ int fd = -1, notify = -1; union sockaddr_union sa = PLYMOUTH_SOCKET; _cleanup_free_ char *packet = NULL; ssize_t k; int r, n; struct pollfd pollfd[2] = {}; char buffer[LINE_MAX]; size_t p = 0; enum { POLL_SOCKET, POLL_INOTIFY }; assert(ret); if (flag_file) { notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); if (notify < 0) return -errno; r = inotify_add_watch(notify, flag_file, IN_ATTRIB); /* for the link count */ if (r < 0) return -errno; } fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (fd < 0) return -errno; r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)); if (r < 0) return -errno; if (flags & ASK_PASSWORD_ACCEPT_CACHED) { packet = strdup("c"); n = 1; } else if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) packet = NULL; if (!packet) return -ENOMEM; r = loop_write(fd, packet, n + 1, true); if (r < 0) return r; pollfd[POLL_SOCKET].fd = fd; pollfd[POLL_SOCKET].events = POLLIN; pollfd[POLL_INOTIFY].fd = notify; pollfd[POLL_INOTIFY].events = POLLIN; for (;;) { int sleep_for = -1, j; if (until > 0) { usec_t y; y = now(CLOCK_MONOTONIC); if (y > until) { r = -ETIME; goto finish; } sleep_for = (int) ((until - y) / USEC_PER_MSEC); } if (flag_file && access(flag_file, F_OK) < 0) { r = -errno; goto finish; } j = poll(pollfd, notify >= 0 ? 2 : 1, sleep_for); if (j < 0) { if (errno == EINTR) continue; r = -errno; goto finish; } else if (j == 0) { r = -ETIME; goto finish; } if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0) flush_fd(notify); if (pollfd[POLL_SOCKET].revents == 0) continue; k = read(fd, buffer + p, sizeof(buffer) - p); if (k < 0) { if (errno == EINTR || errno == EAGAIN) continue; r = -errno; goto finish; } else if (k == 0) { r = -EIO; goto finish; } p += k; if (p < 1) continue; if (buffer[0] == 5) { if (flags & ASK_PASSWORD_ACCEPT_CACHED) { /* Hmm, first try with cached * passwords failed, so let's retry * with a normal password request */ packet = mfree(packet); if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) { r = -ENOMEM; goto finish; } r = loop_write(fd, packet, n+1, true); if (r < 0) goto finish; flags &= ~ASK_PASSWORD_ACCEPT_CACHED; p = 0; continue; } /* No password, because UI not shown */ r = -ENOENT; goto finish; } else if (buffer[0] == 2 || buffer[0] == 9) { uint32_t size; char **l; /* One or more answers */ if (p < 5) continue; memcpy(&size, buffer+1, sizeof(size)); size = le32toh(size); if (size + 5 > sizeof(buffer)) { r = -EIO; goto finish; } if (p-5 < size) continue; l = strv_parse_nulstr(buffer + 5, size); if (!l) { r = -ENOMEM; goto finish; } *ret = l; break; } else { /* Unknown packet */ r = -EIO; goto finish; } } r = 0; finish: memory_erase(buffer, sizeof(buffer)); return r; } static int send_passwords(const char *socket_name, char **passwords) { _cleanup_free_ char *packet = NULL; _cleanup_close_ int socket_fd = -1; union sockaddr_union sa = { .un.sun_family = AF_UNIX }; size_t packet_length = 1; char **p, *d; int r; assert(socket_name); STRV_FOREACH(p, passwords) packet_length += strlen(*p) + 1; packet = new(char, packet_length); if (!packet) return -ENOMEM; packet[0] = '+'; d = packet + 1; STRV_FOREACH(p, passwords) d = stpcpy(d, *p) + 1; socket_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); if (socket_fd < 0) { r = log_debug_errno(errno, "socket(): %m"); goto finish; } strncpy(sa.un.sun_path, socket_name, sizeof(sa.un.sun_path)); r = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(socket_name)); if (r < 0) r = log_debug_errno(errno, "sendto(): %m"); finish: memory_erase(packet, packet_length); return r; } static int parse_password(const char *filename, char **wall) { _cleanup_free_ char *socket_name = NULL, *message = NULL; bool accept_cached = false, echo = false; uint64_t not_after = 0; unsigned pid = 0; const ConfigTableItem items[] = { { "Ask", "Socket", config_parse_string, 0, &socket_name }, { "Ask", "NotAfter", config_parse_uint64, 0, ¬_after }, { "Ask", "Message", config_parse_string, 0, &message }, { "Ask", "PID", config_parse_unsigned, 0, &pid }, { "Ask", "AcceptCached", config_parse_bool, 0, &accept_cached }, { "Ask", "Echo", config_parse_bool, 0, &echo }, {} }; int r; assert(filename); r = config_parse(NULL, filename, NULL, NULL, config_item_table_lookup, items, true, false, true, NULL); if (r < 0) return r; if (!socket_name) { log_error("Invalid password file %s", filename); return -EBADMSG; } if (not_after > 0 && now(CLOCK_MONOTONIC) > not_after) return 0; if (pid > 0 && !pid_is_alive(pid)) return 0; if (arg_action == ACTION_LIST) printf("'%s' (PID %u)\n", message, pid); else if (arg_action == ACTION_WALL) { char *_wall; if (asprintf(&_wall, "%s%sPassword entry required for \'%s\' (PID %u).\r\n" "Please enter password with the systemd-tty-ask-password-agent tool!", strempty(*wall), *wall ? "\r\n\r\n" : "", message, pid) < 0) return log_oom(); free(*wall); *wall = _wall; } else { _cleanup_strv_free_erase_ char **passwords = NULL; assert(arg_action == ACTION_QUERY || arg_action == ACTION_WATCH); if (access(socket_name, W_OK) < 0) { if (arg_action == ACTION_QUERY) log_info("Not querying '%s' (PID %u), lacking privileges.", message, pid); return 0; } if (arg_plymouth) r = ask_password_plymouth(message, not_after, accept_cached ? ASK_PASSWORD_ACCEPT_CACHED : 0, filename, &passwords); else { char *password = NULL; int tty_fd = -1; if (arg_console) { tty_fd = acquire_terminal("/dev/console", false, false, false, USEC_INFINITY); if (tty_fd < 0) return log_error_errno(tty_fd, "Failed to acquire /dev/console: %m"); r = reset_terminal_fd(tty_fd, true); if (r < 0) log_warning_errno(r, "Failed to reset terminal, ignoring: %m"); } r = ask_password_tty(message, NULL, not_after, echo ? ASK_PASSWORD_ECHO : 0, filename, &password); if (arg_console) { tty_fd = safe_close(tty_fd); release_terminal(); } if (r >= 0) r = strv_push(&passwords, password); if (r < 0) string_free_erase(password); } /* If the query went away, that's OK */ if (IN_SET(r, -ETIME, -ENOENT)) return 0; if (r < 0) return log_error_errno(r, "Failed to query password: %m"); r = send_passwords(socket_name, passwords); if (r < 0) return log_error_errno(r, "Failed to send: %m"); } return 0; } static int wall_tty_block(void) { _cleanup_free_ char *p = NULL; dev_t devnr; int fd, r; r = get_ctty_devnr(0, &devnr); if (r == -ENXIO) /* We have no controlling tty */ return -ENOTTY; if (r < 0) return log_error_errno(r, "Failed to get controlling TTY: %m"); if (asprintf(&p, "/run/systemd/ask-password-block/%u:%u", major(devnr), minor(devnr)) < 0) return log_oom(); mkdir_parents_label(p, 0700); mkfifo(p, 0600); fd = open(p, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); if (fd < 0) return log_debug_errno(errno, "Failed to open %s: %m", p); return fd; } static bool wall_tty_match(const char *path, void *userdata) { _cleanup_free_ char *p = NULL; _cleanup_close_ int fd = -1; struct stat st; if (!path_is_absolute(path)) path = strjoina("/dev/", path); if (lstat(path, &st) < 0) { log_debug_errno(errno, "Failed to stat %s: %m", path); return true; } if (!S_ISCHR(st.st_mode)) { log_debug("%s is not a character device.", path); return true; } /* We use named pipes to ensure that wall messages suggesting * password entry are not printed over password prompts * already shown. We use the fact here that opening a pipe in * non-blocking mode for write-only will succeed only if * there's some writer behind it. Using pipes has the * advantage that the block will automatically go away if the * process dies. */ if (asprintf(&p, "/run/systemd/ask-password-block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0) { log_oom(); return true; } fd = open(p, O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); if (fd < 0) { log_debug_errno(errno, "Failed top open the wall pipe: %m"); return 1; } /* What, we managed to open the pipe? Then this tty is filtered. */ return 0; } static int show_passwords(void) { _cleanup_closedir_ DIR *d; struct dirent *de; int r = 0; d = opendir("/run/systemd/ask-password"); if (!d) { if (errno == ENOENT) return 0; return log_error_errno(errno, "Failed to open /run/systemd/ask-password: %m"); } FOREACH_DIRENT_ALL(de, d, return log_error_errno(errno, "Failed to read directory: %m")) { _cleanup_free_ char *p = NULL, *wall = NULL; int q; /* We only support /dev on tmpfs, hence we can rely on * d_type to be reliable */ if (de->d_type != DT_REG) continue; if (hidden_file(de->d_name)) continue; if (!startswith(de->d_name, "ask.")) continue; p = strappend("/run/systemd/ask-password/", de->d_name); if (!p) return log_oom(); q = parse_password(p, &wall); if (q < 0 && r == 0) r = q; if (wall) (void) utmp_wall(wall, NULL, NULL, wall_tty_match, NULL); } return r; } static int watch_passwords(void) { enum { FD_INOTIFY, FD_SIGNAL, _FD_MAX }; _cleanup_close_ int notify = -1, signal_fd = -1, tty_block_fd = -1; struct pollfd pollfd[_FD_MAX] = {}; sigset_t mask; int r; tty_block_fd = wall_tty_block(); (void) mkdir_p_label("/run/systemd/ask-password", 0755); notify = inotify_init1(IN_CLOEXEC); if (notify < 0) return log_error_errno(errno, "Failed to allocate directory watch: %m"); if (inotify_add_watch(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO) < 0) return log_error_errno(errno, "Failed to add /run/systemd/ask-password to directory watch: %m"); assert_se(sigemptyset(&mask) >= 0); assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0); assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) >= 0); signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); if (signal_fd < 0) return log_error_errno(errno, "Failed to allocate signal file descriptor: %m"); pollfd[FD_INOTIFY].fd = notify; pollfd[FD_INOTIFY].events = POLLIN; pollfd[FD_SIGNAL].fd = signal_fd; pollfd[FD_SIGNAL].events = POLLIN; for (;;) { r = show_passwords(); if (r < 0) log_error_errno(r, "Failed to show password: %m"); if (poll(pollfd, _FD_MAX, -1) < 0) { if (errno == EINTR) continue; return -errno; } if (pollfd[FD_INOTIFY].revents != 0) (void) flush_fd(notify); if (pollfd[FD_SIGNAL].revents != 0) break; } return 0; } static void help(void) { printf("%s [OPTIONS...]\n\n" "Process system password requests.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --list Show pending password requests\n" " --query Process pending password requests\n" " --watch Continuously process password requests\n" " --wall Continuously forward password requests to wall\n" " --plymouth Ask question with Plymouth instead of on TTY\n" " --console Ask question on /dev/console instead of current TTY\n", program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { enum { ARG_LIST = 0x100, ARG_QUERY, ARG_WATCH, ARG_WALL, ARG_PLYMOUTH, ARG_CONSOLE, ARG_VERSION }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "list", no_argument, NULL, ARG_LIST }, { "query", no_argument, NULL, ARG_QUERY }, { "watch", no_argument, NULL, ARG_WATCH }, { "wall", no_argument, NULL, ARG_WALL }, { "plymouth", no_argument, NULL, ARG_PLYMOUTH }, { "console", no_argument, NULL, ARG_CONSOLE }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_LIST: arg_action = ACTION_LIST; break; case ARG_QUERY: arg_action = ACTION_QUERY; break; case ARG_WATCH: arg_action = ACTION_WATCH; break; case ARG_WALL: arg_action = ACTION_WALL; break; case ARG_PLYMOUTH: arg_plymouth = true; break; case ARG_CONSOLE: arg_console = true; break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } if (optind != argc) { log_error("%s takes no arguments.", program_invocation_short_name); return -EINVAL; } return 1; } int main(int argc, char *argv[]) { int r; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); r = parse_argv(argc, argv); if (r <= 0) goto finish; if (arg_console) { (void) setsid(); (void) release_terminal(); } if (IN_SET(arg_action, ACTION_WATCH, ACTION_WALL)) r = watch_passwords(); else r = show_passwords(); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/udev/000077500000000000000000000000001265713322000146135ustar00rootroot00000000000000systemd-229/src/udev/.gitignore000066400000000000000000000001331265713322000166000ustar00rootroot00000000000000/udev.pc /keyboard-keys-from-name.gperf /keyboard-keys-from-name.h /keyboard-keys-list.txt systemd-229/src/udev/.vimrc000066400000000000000000000001621265713322000157330ustar00rootroot00000000000000" 'set exrc' in ~/.vimrc will read .vimrc from the current directory set tabstop=8 set shiftwidth=8 set expandtab systemd-229/src/udev/Makefile000077700000000000000000000000001265713322000201212../Makefileustar00rootroot00000000000000systemd-229/src/udev/ata_id/000077500000000000000000000000001265713322000160345ustar00rootroot00000000000000systemd-229/src/udev/ata_id/Makefile000077700000000000000000000000001265713322000213422../Makefileustar00rootroot00000000000000systemd-229/src/udev/ata_id/ata_id.c000066400000000000000000000663521265713322000174350ustar00rootroot00000000000000/* * ata_id - reads product/serial number from ATA drives * * Copyright (C) 2005-2008 Kay Sievers * Copyright (C) 2009 Lennart Poettering * Copyright (C) 2009-2010 David Zeuthen * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libudev.h" #include "fd-util.h" #include "libudev-private.h" #include "log.h" #include "udev-util.h" #define COMMAND_TIMEOUT_MSEC (30 * 1000) static int disk_scsi_inquiry_command(int fd, void *buf, size_t buf_len) { uint8_t cdb[6] = { /* * INQUIRY, see SPC-4 section 6.4 */ [0] = 0x12, /* OPERATION CODE: INQUIRY */ [3] = (buf_len >> 8), /* ALLOCATION LENGTH */ [4] = (buf_len & 0xff), }; uint8_t sense[32] = {}; struct sg_io_v4 io_v4 = { .guard = 'Q', .protocol = BSG_PROTOCOL_SCSI, .subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD, .request_len = sizeof(cdb), .request = (uintptr_t) cdb, .max_response_len = sizeof(sense), .response = (uintptr_t) sense, .din_xfer_len = buf_len, .din_xferp = (uintptr_t) buf, .timeout = COMMAND_TIMEOUT_MSEC, }; int ret; ret = ioctl(fd, SG_IO, &io_v4); if (ret != 0) { /* could be that the driver doesn't do version 4, try version 3 */ if (errno == EINVAL) { struct sg_io_hdr io_hdr = { .interface_id = 'S', .cmdp = (unsigned char*) cdb, .cmd_len = sizeof (cdb), .dxferp = buf, .dxfer_len = buf_len, .sbp = sense, .mx_sb_len = sizeof(sense), .dxfer_direction = SG_DXFER_FROM_DEV, .timeout = COMMAND_TIMEOUT_MSEC, }; ret = ioctl(fd, SG_IO, &io_hdr); if (ret != 0) return ret; /* even if the ioctl succeeds, we need to check the return value */ if (!(io_hdr.status == 0 && io_hdr.host_status == 0 && io_hdr.driver_status == 0)) { errno = EIO; return -1; } } else return ret; } /* even if the ioctl succeeds, we need to check the return value */ if (!(io_v4.device_status == 0 && io_v4.transport_status == 0 && io_v4.driver_status == 0)) { errno = EIO; return -1; } return 0; } static int disk_identify_command(int fd, void *buf, size_t buf_len) { uint8_t cdb[12] = { /* * ATA Pass-Through 12 byte command, as described in * * T10 04-262r8 ATA Command Pass-Through * * from http://www.t10.org/ftp/t10/document.04/04-262r8.pdf */ [0] = 0xa1, /* OPERATION CODE: 12 byte pass through */ [1] = 4 << 1, /* PROTOCOL: PIO Data-in */ [2] = 0x2e, /* OFF_LINE=0, CK_COND=1, T_DIR=1, BYT_BLOK=1, T_LENGTH=2 */ [3] = 0, /* FEATURES */ [4] = 1, /* SECTORS */ [5] = 0, /* LBA LOW */ [6] = 0, /* LBA MID */ [7] = 0, /* LBA HIGH */ [8] = 0 & 0x4F, /* SELECT */ [9] = 0xEC, /* Command: ATA IDENTIFY DEVICE */ }; uint8_t sense[32] = {}; uint8_t *desc = sense + 8; struct sg_io_v4 io_v4 = { .guard = 'Q', .protocol = BSG_PROTOCOL_SCSI, .subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD, .request_len = sizeof(cdb), .request = (uintptr_t) cdb, .max_response_len = sizeof(sense), .response = (uintptr_t) sense, .din_xfer_len = buf_len, .din_xferp = (uintptr_t) buf, .timeout = COMMAND_TIMEOUT_MSEC, }; int ret; ret = ioctl(fd, SG_IO, &io_v4); if (ret != 0) { /* could be that the driver doesn't do version 4, try version 3 */ if (errno == EINVAL) { struct sg_io_hdr io_hdr = { .interface_id = 'S', .cmdp = (unsigned char*) cdb, .cmd_len = sizeof (cdb), .dxferp = buf, .dxfer_len = buf_len, .sbp = sense, .mx_sb_len = sizeof (sense), .dxfer_direction = SG_DXFER_FROM_DEV, .timeout = COMMAND_TIMEOUT_MSEC, }; ret = ioctl(fd, SG_IO, &io_hdr); if (ret != 0) return ret; } else return ret; } if (!(sense[0] == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c)) { errno = EIO; return -1; } return 0; } static int disk_identify_packet_device_command(int fd, void *buf, size_t buf_len) { uint8_t cdb[16] = { /* * ATA Pass-Through 16 byte command, as described in * * T10 04-262r8 ATA Command Pass-Through * * from http://www.t10.org/ftp/t10/document.04/04-262r8.pdf */ [0] = 0x85, /* OPERATION CODE: 16 byte pass through */ [1] = 4 << 1, /* PROTOCOL: PIO Data-in */ [2] = 0x2e, /* OFF_LINE=0, CK_COND=1, T_DIR=1, BYT_BLOK=1, T_LENGTH=2 */ [3] = 0, /* FEATURES */ [4] = 0, /* FEATURES */ [5] = 0, /* SECTORS */ [6] = 1, /* SECTORS */ [7] = 0, /* LBA LOW */ [8] = 0, /* LBA LOW */ [9] = 0, /* LBA MID */ [10] = 0, /* LBA MID */ [11] = 0, /* LBA HIGH */ [12] = 0, /* LBA HIGH */ [13] = 0, /* DEVICE */ [14] = 0xA1, /* Command: ATA IDENTIFY PACKET DEVICE */ [15] = 0, /* CONTROL */ }; uint8_t sense[32] = {}; uint8_t *desc = sense + 8; struct sg_io_v4 io_v4 = { .guard = 'Q', .protocol = BSG_PROTOCOL_SCSI, .subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD, .request_len = sizeof (cdb), .request = (uintptr_t) cdb, .max_response_len = sizeof (sense), .response = (uintptr_t) sense, .din_xfer_len = buf_len, .din_xferp = (uintptr_t) buf, .timeout = COMMAND_TIMEOUT_MSEC, }; int ret; ret = ioctl(fd, SG_IO, &io_v4); if (ret != 0) { /* could be that the driver doesn't do version 4, try version 3 */ if (errno == EINVAL) { struct sg_io_hdr io_hdr = { .interface_id = 'S', .cmdp = (unsigned char*) cdb, .cmd_len = sizeof (cdb), .dxferp = buf, .dxfer_len = buf_len, .sbp = sense, .mx_sb_len = sizeof (sense), .dxfer_direction = SG_DXFER_FROM_DEV, .timeout = COMMAND_TIMEOUT_MSEC, }; ret = ioctl(fd, SG_IO, &io_hdr); if (ret != 0) return ret; } else return ret; } if (!(sense[0] == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c)) { errno = EIO; return -1; } return 0; } /** * disk_identify_get_string: * @identify: A block of IDENTIFY data * @offset_words: Offset of the string to get, in words. * @dest: Destination buffer for the string. * @dest_len: Length of destination buffer, in bytes. * * Copies the ATA string from @identify located at @offset_words into @dest. */ static void disk_identify_get_string(uint8_t identify[512], unsigned int offset_words, char *dest, size_t dest_len) { unsigned int c1; unsigned int c2; while (dest_len > 0) { c1 = identify[offset_words * 2 + 1]; c2 = identify[offset_words * 2]; *dest = c1; dest++; *dest = c2; dest++; offset_words++; dest_len -= 2; } } static void disk_identify_fixup_string(uint8_t identify[512], unsigned int offset_words, size_t len) { disk_identify_get_string(identify, offset_words, (char *) identify + offset_words * 2, len); } static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned int offset_words) { uint16_t *p; p = (uint16_t *) identify; p[offset_words] = le16toh (p[offset_words]); } /** * disk_identify: * @udev: The libudev context. * @fd: File descriptor for the block device. * @out_identify: Return location for IDENTIFY data. * @out_is_packet_device: Return location for whether returned data is from a IDENTIFY PACKET DEVICE. * * Sends the IDENTIFY DEVICE or IDENTIFY PACKET DEVICE command to the * device represented by @fd. If successful, then the result will be * copied into @out_identify and @out_is_packet_device. * * This routine is based on code from libatasmart, Copyright 2008 * Lennart Poettering, LGPL v2.1. * * Returns: 0 if the data was successfully obtained, otherwise * non-zero with errno set. */ static int disk_identify(struct udev *udev, int fd, uint8_t out_identify[512], int *out_is_packet_device) { int ret; uint8_t inquiry_buf[36]; int peripheral_device_type; int all_nul_bytes; int n; int is_packet_device = 0; /* init results */ memzero(out_identify, 512); /* If we were to use ATA PASS_THROUGH (12) on an ATAPI device * we could accidentally blank media. This is because MMC's BLANK * command has the same op-code (0x61). * * To prevent this from happening we bail out if the device * isn't a Direct Access Block Device, e.g. SCSI type 0x00 * (CD/DVD devices are type 0x05). So we send a SCSI INQUIRY * command first... libata is handling this via its SCSI * emulation layer. * * This also ensures that we're actually dealing with a device * that understands SCSI commands. * * (Yes, it is a bit perverse that we're tunneling the ATA * command through SCSI and relying on the ATA driver * emulating SCSI well-enough...) * * (See commit 160b069c25690bfb0c785994c7c3710289179107 for * the original bug-fix and see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=556635 * for the original bug-report.) */ ret = disk_scsi_inquiry_command (fd, inquiry_buf, sizeof (inquiry_buf)); if (ret != 0) goto out; /* SPC-4, section 6.4.2: Standard INQUIRY data */ peripheral_device_type = inquiry_buf[0] & 0x1f; if (peripheral_device_type == 0x05) { is_packet_device = 1; ret = disk_identify_packet_device_command(fd, out_identify, 512); goto check_nul_bytes; } if (peripheral_device_type != 0x00) { ret = -1; errno = EIO; goto out; } /* OK, now issue the IDENTIFY DEVICE command */ ret = disk_identify_command(fd, out_identify, 512); if (ret != 0) goto out; check_nul_bytes: /* Check if IDENTIFY data is all NUL bytes - if so, bail */ all_nul_bytes = 1; for (n = 0; n < 512; n++) { if (out_identify[n] != '\0') { all_nul_bytes = 0; break; } } if (all_nul_bytes) { ret = -1; errno = EIO; goto out; } out: if (out_is_packet_device != NULL) *out_is_packet_device = is_packet_device; return ret; } int main(int argc, char *argv[]) { _cleanup_udev_unref_ struct udev *udev = NULL; struct hd_driveid id; union { uint8_t byte[512]; uint16_t wyde[256]; } identify; char model[41]; char model_enc[256]; char serial[21]; char revision[9]; const char *node = NULL; int export = 0; _cleanup_close_ int fd = -1; uint16_t word; int is_packet_device = 0; static const struct option options[] = { { "export", no_argument, NULL, 'x' }, { "help", no_argument, NULL, 'h' }, {} }; log_parse_environment(); log_open(); udev = udev_new(); if (udev == NULL) return 0; for (;;) { int option; option = getopt_long(argc, argv, "xh", options, NULL); if (option == -1) break; switch (option) { case 'x': export = 1; break; case 'h': printf("Usage: ata_id [--export] [--help] \n" " -x,--export print values as environment keys\n" " -h,--help print this help text\n\n"); return 0; } } node = argv[optind]; if (node == NULL) { log_error("no node specified"); return 1; } fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC); if (fd < 0) { log_error("unable to open '%s'", node); return 1; } if (disk_identify(udev, fd, identify.byte, &is_packet_device) == 0) { /* * fix up only the fields from the IDENTIFY data that we are going to * use and copy it into the hd_driveid struct for convenience */ disk_identify_fixup_string(identify.byte, 10, 20); /* serial */ disk_identify_fixup_string(identify.byte, 23, 8); /* fwrev */ disk_identify_fixup_string(identify.byte, 27, 40); /* model */ disk_identify_fixup_uint16(identify.byte, 0); /* configuration */ disk_identify_fixup_uint16(identify.byte, 75); /* queue depth */ disk_identify_fixup_uint16(identify.byte, 76); /* SATA capabilities */ disk_identify_fixup_uint16(identify.byte, 82); /* command set supported */ disk_identify_fixup_uint16(identify.byte, 83); /* command set supported */ disk_identify_fixup_uint16(identify.byte, 84); /* command set supported */ disk_identify_fixup_uint16(identify.byte, 85); /* command set supported */ disk_identify_fixup_uint16(identify.byte, 86); /* command set supported */ disk_identify_fixup_uint16(identify.byte, 87); /* command set supported */ disk_identify_fixup_uint16(identify.byte, 89); /* time required for SECURITY ERASE UNIT */ disk_identify_fixup_uint16(identify.byte, 90); /* time required for enhanced SECURITY ERASE UNIT */ disk_identify_fixup_uint16(identify.byte, 91); /* current APM values */ disk_identify_fixup_uint16(identify.byte, 94); /* current AAM value */ disk_identify_fixup_uint16(identify.byte, 108); /* WWN */ disk_identify_fixup_uint16(identify.byte, 109); /* WWN */ disk_identify_fixup_uint16(identify.byte, 110); /* WWN */ disk_identify_fixup_uint16(identify.byte, 111); /* WWN */ disk_identify_fixup_uint16(identify.byte, 128); /* device lock function */ disk_identify_fixup_uint16(identify.byte, 217); /* nominal media rotation rate */ memcpy(&id, identify.byte, sizeof id); } else { /* If this fails, then try HDIO_GET_IDENTITY */ if (ioctl(fd, HDIO_GET_IDENTITY, &id) != 0) { log_debug_errno(errno, "HDIO_GET_IDENTITY failed for '%s': %m", node); return 2; } } memcpy(model, id.model, 40); model[40] = '\0'; udev_util_encode_string(model, model_enc, sizeof(model_enc)); util_replace_whitespace((char *) id.model, model, 40); util_replace_chars(model, NULL); util_replace_whitespace((char *) id.serial_no, serial, 20); util_replace_chars(serial, NULL); util_replace_whitespace((char *) id.fw_rev, revision, 8); util_replace_chars(revision, NULL); if (export) { /* Set this to convey the disk speaks the ATA protocol */ printf("ID_ATA=1\n"); if ((id.config >> 8) & 0x80) { /* This is an ATAPI device */ switch ((id.config >> 8) & 0x1f) { case 0: printf("ID_TYPE=cd\n"); break; case 1: printf("ID_TYPE=tape\n"); break; case 5: printf("ID_TYPE=cd\n"); break; case 7: printf("ID_TYPE=optical\n"); break; default: printf("ID_TYPE=generic\n"); break; } } else { printf("ID_TYPE=disk\n"); } printf("ID_BUS=ata\n"); printf("ID_MODEL=%s\n", model); printf("ID_MODEL_ENC=%s\n", model_enc); printf("ID_REVISION=%s\n", revision); if (serial[0] != '\0') { printf("ID_SERIAL=%s_%s\n", model, serial); printf("ID_SERIAL_SHORT=%s\n", serial); } else { printf("ID_SERIAL=%s\n", model); } if (id.command_set_1 & (1<<5)) { printf("ID_ATA_WRITE_CACHE=1\n"); printf("ID_ATA_WRITE_CACHE_ENABLED=%d\n", (id.cfs_enable_1 & (1<<5)) ? 1 : 0); } if (id.command_set_1 & (1<<10)) { printf("ID_ATA_FEATURE_SET_HPA=1\n"); printf("ID_ATA_FEATURE_SET_HPA_ENABLED=%d\n", (id.cfs_enable_1 & (1<<10)) ? 1 : 0); /* * TODO: use the READ NATIVE MAX ADDRESS command to get the native max address * so it is easy to check whether the protected area is in use. */ } if (id.command_set_1 & (1<<3)) { printf("ID_ATA_FEATURE_SET_PM=1\n"); printf("ID_ATA_FEATURE_SET_PM_ENABLED=%d\n", (id.cfs_enable_1 & (1<<3)) ? 1 : 0); } if (id.command_set_1 & (1<<1)) { printf("ID_ATA_FEATURE_SET_SECURITY=1\n"); printf("ID_ATA_FEATURE_SET_SECURITY_ENABLED=%d\n", (id.cfs_enable_1 & (1<<1)) ? 1 : 0); printf("ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN=%d\n", id.trseuc * 2); if ((id.cfs_enable_1 & (1<<1))) /* enabled */ { if (id.dlf & (1<<8)) printf("ID_ATA_FEATURE_SET_SECURITY_LEVEL=maximum\n"); else printf("ID_ATA_FEATURE_SET_SECURITY_LEVEL=high\n"); } if (id.dlf & (1<<5)) printf("ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN=%d\n", id.trsEuc * 2); if (id.dlf & (1<<4)) printf("ID_ATA_FEATURE_SET_SECURITY_EXPIRE=1\n"); if (id.dlf & (1<<3)) printf("ID_ATA_FEATURE_SET_SECURITY_FROZEN=1\n"); if (id.dlf & (1<<2)) printf("ID_ATA_FEATURE_SET_SECURITY_LOCKED=1\n"); } if (id.command_set_1 & (1<<0)) { printf("ID_ATA_FEATURE_SET_SMART=1\n"); printf("ID_ATA_FEATURE_SET_SMART_ENABLED=%d\n", (id.cfs_enable_1 & (1<<0)) ? 1 : 0); } if (id.command_set_2 & (1<<9)) { printf("ID_ATA_FEATURE_SET_AAM=1\n"); printf("ID_ATA_FEATURE_SET_AAM_ENABLED=%d\n", (id.cfs_enable_2 & (1<<9)) ? 1 : 0); printf("ID_ATA_FEATURE_SET_AAM_VENDOR_RECOMMENDED_VALUE=%d\n", id.acoustic >> 8); printf("ID_ATA_FEATURE_SET_AAM_CURRENT_VALUE=%d\n", id.acoustic & 0xff); } if (id.command_set_2 & (1<<5)) { printf("ID_ATA_FEATURE_SET_PUIS=1\n"); printf("ID_ATA_FEATURE_SET_PUIS_ENABLED=%d\n", (id.cfs_enable_2 & (1<<5)) ? 1 : 0); } if (id.command_set_2 & (1<<3)) { printf("ID_ATA_FEATURE_SET_APM=1\n"); printf("ID_ATA_FEATURE_SET_APM_ENABLED=%d\n", (id.cfs_enable_2 & (1<<3)) ? 1 : 0); if ((id.cfs_enable_2 & (1<<3))) printf("ID_ATA_FEATURE_SET_APM_CURRENT_VALUE=%d\n", id.CurAPMvalues & 0xff); } if (id.command_set_2 & (1<<0)) printf("ID_ATA_DOWNLOAD_MICROCODE=1\n"); /* * Word 76 indicates the capabilities of a SATA device. A PATA device shall set * word 76 to 0000h or FFFFh. If word 76 is set to 0000h or FFFFh, then * the device does not claim compliance with the Serial ATA specification and words * 76 through 79 are not valid and shall be ignored. */ word = identify.wyde[76]; if (word != 0x0000 && word != 0xffff) { printf("ID_ATA_SATA=1\n"); /* * If bit 2 of word 76 is set to one, then the device supports the Gen2 * signaling rate of 3.0 Gb/s (see SATA 2.6). * * If bit 1 of word 76 is set to one, then the device supports the Gen1 * signaling rate of 1.5 Gb/s (see SATA 2.6). */ if (word & (1<<2)) printf("ID_ATA_SATA_SIGNAL_RATE_GEN2=1\n"); if (word & (1<<1)) printf("ID_ATA_SATA_SIGNAL_RATE_GEN1=1\n"); } /* Word 217 indicates the nominal media rotation rate of the device */ word = identify.wyde[217]; if (word == 0x0001) printf ("ID_ATA_ROTATION_RATE_RPM=0\n"); /* non-rotating e.g. SSD */ else if (word >= 0x0401 && word <= 0xfffe) printf ("ID_ATA_ROTATION_RATE_RPM=%d\n", word); /* * Words 108-111 contain a mandatory World Wide Name (WWN) in the NAA IEEE Registered identifier * format. Word 108 bits (15:12) shall contain 5h, indicating that the naming authority is IEEE. * All other values are reserved. */ word = identify.wyde[108]; if ((word & 0xf000) == 0x5000) { uint64_t wwwn; wwwn = identify.wyde[108]; wwwn <<= 16; wwwn |= identify.wyde[109]; wwwn <<= 16; wwwn |= identify.wyde[110]; wwwn <<= 16; wwwn |= identify.wyde[111]; printf("ID_WWN=0x%1$" PRIx64 "\n" "ID_WWN_WITH_EXTENSION=0x%1$" PRIx64 "\n", wwwn); } /* from Linux's include/linux/ata.h */ if (identify.wyde[0] == 0x848a || identify.wyde[0] == 0x844a || (identify.wyde[83] & 0xc004) == 0x4004) printf("ID_ATA_CFA=1\n"); } else { if (serial[0] != '\0') printf("%s_%s\n", model, serial); else printf("%s\n", model); } return 0; } systemd-229/src/udev/cdrom_id/000077500000000000000000000000001265713322000163735ustar00rootroot00000000000000systemd-229/src/udev/cdrom_id/Makefile000077700000000000000000000000001265713322000217012../Makefileustar00rootroot00000000000000systemd-229/src/udev/cdrom_id/cdrom_id.c000066400000000000000000001144001265713322000203170ustar00rootroot00000000000000/* * cdrom_id - optical drive and media information prober * * Copyright (C) 2008-2010 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libudev.h" #include "libudev-private.h" #include "random-util.h" /* device info */ static unsigned int cd_cd_rom; static unsigned int cd_cd_r; static unsigned int cd_cd_rw; static unsigned int cd_dvd_rom; static unsigned int cd_dvd_r; static unsigned int cd_dvd_rw; static unsigned int cd_dvd_ram; static unsigned int cd_dvd_plus_r; static unsigned int cd_dvd_plus_rw; static unsigned int cd_dvd_plus_r_dl; static unsigned int cd_dvd_plus_rw_dl; static unsigned int cd_bd; static unsigned int cd_bd_r; static unsigned int cd_bd_re; static unsigned int cd_hddvd; static unsigned int cd_hddvd_r; static unsigned int cd_hddvd_rw; static unsigned int cd_mo; static unsigned int cd_mrw; static unsigned int cd_mrw_w; /* media info */ static unsigned int cd_media; static unsigned int cd_media_cd_rom; static unsigned int cd_media_cd_r; static unsigned int cd_media_cd_rw; static unsigned int cd_media_dvd_rom; static unsigned int cd_media_dvd_r; static unsigned int cd_media_dvd_rw; static unsigned int cd_media_dvd_rw_ro; /* restricted overwrite mode */ static unsigned int cd_media_dvd_rw_seq; /* sequential mode */ static unsigned int cd_media_dvd_ram; static unsigned int cd_media_dvd_plus_r; static unsigned int cd_media_dvd_plus_rw; static unsigned int cd_media_dvd_plus_r_dl; static unsigned int cd_media_dvd_plus_rw_dl; static unsigned int cd_media_bd; static unsigned int cd_media_bd_r; static unsigned int cd_media_bd_re; static unsigned int cd_media_hddvd; static unsigned int cd_media_hddvd_r; static unsigned int cd_media_hddvd_rw; static unsigned int cd_media_mo; static unsigned int cd_media_mrw; static unsigned int cd_media_mrw_w; static const char *cd_media_state = NULL; static unsigned int cd_media_session_next; static unsigned int cd_media_session_count; static unsigned int cd_media_track_count; static unsigned int cd_media_track_count_data; static unsigned int cd_media_track_count_audio; static unsigned long long int cd_media_session_last_offset; #define ERRCODE(s) ((((s)[2] & 0x0F) << 16) | ((s)[12] << 8) | ((s)[13])) #define SK(errcode) (((errcode) >> 16) & 0xF) #define ASC(errcode) (((errcode) >> 8) & 0xFF) #define ASCQ(errcode) ((errcode) & 0xFF) static bool is_mounted(const char *device) { struct stat statbuf; FILE *fp; int maj, min; bool mounted = false; if (stat(device, &statbuf) < 0) return false; fp = fopen("/proc/self/mountinfo", "re"); if (fp == NULL) return false; while (fscanf(fp, "%*s %*s %i:%i %*[^\n]", &maj, &min) == 2) { if (makedev(maj, min) == statbuf.st_rdev) { mounted = true; break; } } fclose(fp); return mounted; } static void info_scsi_cmd_err(struct udev *udev, const char *cmd, int err) { if (err == -1) { log_debug("%s failed", cmd); return; } log_debug("%s failed with SK=%Xh/ASC=%02Xh/ACQ=%02Xh", cmd, SK(err), ASC(err), ASCQ(err)); } struct scsi_cmd { struct cdrom_generic_command cgc; union { struct request_sense s; unsigned char u[18]; } _sense; struct sg_io_hdr sg_io; }; static void scsi_cmd_init(struct udev *udev, struct scsi_cmd *cmd) { memzero(cmd, sizeof(struct scsi_cmd)); cmd->cgc.quiet = 1; cmd->cgc.sense = &cmd->_sense.s; cmd->sg_io.interface_id = 'S'; cmd->sg_io.mx_sb_len = sizeof(cmd->_sense); cmd->sg_io.cmdp = cmd->cgc.cmd; cmd->sg_io.sbp = cmd->_sense.u; cmd->sg_io.flags = SG_FLAG_LUN_INHIBIT | SG_FLAG_DIRECT_IO; } static void scsi_cmd_set(struct udev *udev, struct scsi_cmd *cmd, size_t i, unsigned char arg) { cmd->sg_io.cmd_len = i + 1; cmd->cgc.cmd[i] = arg; } #define CHECK_CONDITION 0x01 static int scsi_cmd_run(struct udev *udev, struct scsi_cmd *cmd, int fd, unsigned char *buf, size_t bufsize) { int ret = 0; if (bufsize > 0) { cmd->sg_io.dxferp = buf; cmd->sg_io.dxfer_len = bufsize; cmd->sg_io.dxfer_direction = SG_DXFER_FROM_DEV; } else { cmd->sg_io.dxfer_direction = SG_DXFER_NONE; } if (ioctl(fd, SG_IO, &cmd->sg_io)) return -1; if ((cmd->sg_io.info & SG_INFO_OK_MASK) != SG_INFO_OK) { errno = EIO; ret = -1; if (cmd->sg_io.masked_status & CHECK_CONDITION) { ret = ERRCODE(cmd->_sense.u); if (ret == 0) ret = -1; } } return ret; } static int media_lock(struct udev *udev, int fd, bool lock) { int err; /* disable the kernel's lock logic */ err = ioctl(fd, CDROM_CLEAR_OPTIONS, CDO_LOCK); if (err < 0) log_debug("CDROM_CLEAR_OPTIONS, CDO_LOCK failed"); err = ioctl(fd, CDROM_LOCKDOOR, lock ? 1 : 0); if (err < 0) log_debug("CDROM_LOCKDOOR failed"); return err; } static int media_eject(struct udev *udev, int fd) { struct scsi_cmd sc; int err; scsi_cmd_init(udev, &sc); scsi_cmd_set(udev, &sc, 0, 0x1b); scsi_cmd_set(udev, &sc, 4, 0x02); scsi_cmd_set(udev, &sc, 5, 0); err = scsi_cmd_run(udev, &sc, fd, NULL, 0); if ((err != 0)) { info_scsi_cmd_err(udev, "START_STOP_UNIT", err); return -1; } return 0; } static int cd_capability_compat(struct udev *udev, int fd) { int capability; capability = ioctl(fd, CDROM_GET_CAPABILITY, NULL); if (capability < 0) { log_debug("CDROM_GET_CAPABILITY failed"); return -1; } if (capability & CDC_CD_R) cd_cd_r = 1; if (capability & CDC_CD_RW) cd_cd_rw = 1; if (capability & CDC_DVD) cd_dvd_rom = 1; if (capability & CDC_DVD_R) cd_dvd_r = 1; if (capability & CDC_DVD_RAM) cd_dvd_ram = 1; if (capability & CDC_MRW) cd_mrw = 1; if (capability & CDC_MRW_W) cd_mrw_w = 1; return 0; } static int cd_media_compat(struct udev *udev, int fd) { if (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK) { log_debug("CDROM_DRIVE_STATUS != CDS_DISC_OK"); return -1; } cd_media = 1; return 0; } static int cd_inquiry(struct udev *udev, int fd) { struct scsi_cmd sc; unsigned char inq[128]; int err; scsi_cmd_init(udev, &sc); scsi_cmd_set(udev, &sc, 0, 0x12); scsi_cmd_set(udev, &sc, 4, 36); scsi_cmd_set(udev, &sc, 5, 0); err = scsi_cmd_run(udev, &sc, fd, inq, 36); if ((err != 0)) { info_scsi_cmd_err(udev, "INQUIRY", err); return -1; } if ((inq[0] & 0x1F) != 5) { log_debug("not an MMC unit"); return -1; } log_debug("INQUIRY: [%.8s][%.16s][%.4s]", inq + 8, inq + 16, inq + 32); return 0; } static void feature_profile_media(struct udev *udev, int cur_profile) { switch (cur_profile) { case 0x03: case 0x04: case 0x05: log_debug("profile 0x%02x ", cur_profile); cd_media = 1; cd_media_mo = 1; break; case 0x08: log_debug("profile 0x%02x media_cd_rom", cur_profile); cd_media = 1; cd_media_cd_rom = 1; break; case 0x09: log_debug("profile 0x%02x media_cd_r", cur_profile); cd_media = 1; cd_media_cd_r = 1; break; case 0x0a: log_debug("profile 0x%02x media_cd_rw", cur_profile); cd_media = 1; cd_media_cd_rw = 1; break; case 0x10: log_debug("profile 0x%02x media_dvd_ro", cur_profile); cd_media = 1; cd_media_dvd_rom = 1; break; case 0x11: log_debug("profile 0x%02x media_dvd_r", cur_profile); cd_media = 1; cd_media_dvd_r = 1; break; case 0x12: log_debug("profile 0x%02x media_dvd_ram", cur_profile); cd_media = 1; cd_media_dvd_ram = 1; break; case 0x13: log_debug("profile 0x%02x media_dvd_rw_ro", cur_profile); cd_media = 1; cd_media_dvd_rw = 1; cd_media_dvd_rw_ro = 1; break; case 0x14: log_debug("profile 0x%02x media_dvd_rw_seq", cur_profile); cd_media = 1; cd_media_dvd_rw = 1; cd_media_dvd_rw_seq = 1; break; case 0x1B: log_debug("profile 0x%02x media_dvd_plus_r", cur_profile); cd_media = 1; cd_media_dvd_plus_r = 1; break; case 0x1A: log_debug("profile 0x%02x media_dvd_plus_rw", cur_profile); cd_media = 1; cd_media_dvd_plus_rw = 1; break; case 0x2A: log_debug("profile 0x%02x media_dvd_plus_rw_dl", cur_profile); cd_media = 1; cd_media_dvd_plus_rw_dl = 1; break; case 0x2B: log_debug("profile 0x%02x media_dvd_plus_r_dl", cur_profile); cd_media = 1; cd_media_dvd_plus_r_dl = 1; break; case 0x40: log_debug("profile 0x%02x media_bd", cur_profile); cd_media = 1; cd_media_bd = 1; break; case 0x41: case 0x42: log_debug("profile 0x%02x media_bd_r", cur_profile); cd_media = 1; cd_media_bd_r = 1; break; case 0x43: log_debug("profile 0x%02x media_bd_re", cur_profile); cd_media = 1; cd_media_bd_re = 1; break; case 0x50: log_debug("profile 0x%02x media_hddvd", cur_profile); cd_media = 1; cd_media_hddvd = 1; break; case 0x51: log_debug("profile 0x%02x media_hddvd_r", cur_profile); cd_media = 1; cd_media_hddvd_r = 1; break; case 0x52: log_debug("profile 0x%02x media_hddvd_rw", cur_profile); cd_media = 1; cd_media_hddvd_rw = 1; break; default: log_debug("profile 0x%02x ", cur_profile); break; } } static int feature_profiles(struct udev *udev, const unsigned char *profiles, size_t size) { unsigned int i; for (i = 0; i+4 <= size; i += 4) { int profile; profile = profiles[i] << 8 | profiles[i+1]; switch (profile) { case 0x03: case 0x04: case 0x05: log_debug("profile 0x%02x mo", profile); cd_mo = 1; break; case 0x08: log_debug("profile 0x%02x cd_rom", profile); cd_cd_rom = 1; break; case 0x09: log_debug("profile 0x%02x cd_r", profile); cd_cd_r = 1; break; case 0x0A: log_debug("profile 0x%02x cd_rw", profile); cd_cd_rw = 1; break; case 0x10: log_debug("profile 0x%02x dvd_rom", profile); cd_dvd_rom = 1; break; case 0x12: log_debug("profile 0x%02x dvd_ram", profile); cd_dvd_ram = 1; break; case 0x13: case 0x14: log_debug("profile 0x%02x dvd_rw", profile); cd_dvd_rw = 1; break; case 0x1B: log_debug("profile 0x%02x dvd_plus_r", profile); cd_dvd_plus_r = 1; break; case 0x1A: log_debug("profile 0x%02x dvd_plus_rw", profile); cd_dvd_plus_rw = 1; break; case 0x2A: log_debug("profile 0x%02x dvd_plus_rw_dl", profile); cd_dvd_plus_rw_dl = 1; break; case 0x2B: log_debug("profile 0x%02x dvd_plus_r_dl", profile); cd_dvd_plus_r_dl = 1; break; case 0x40: cd_bd = 1; log_debug("profile 0x%02x bd", profile); break; case 0x41: case 0x42: cd_bd_r = 1; log_debug("profile 0x%02x bd_r", profile); break; case 0x43: cd_bd_re = 1; log_debug("profile 0x%02x bd_re", profile); break; case 0x50: cd_hddvd = 1; log_debug("profile 0x%02x hddvd", profile); break; case 0x51: cd_hddvd_r = 1; log_debug("profile 0x%02x hddvd_r", profile); break; case 0x52: cd_hddvd_rw = 1; log_debug("profile 0x%02x hddvd_rw", profile); break; default: log_debug("profile 0x%02x ", profile); break; } } return 0; } /* returns 0 if media was detected */ static int cd_profiles_old_mmc(struct udev *udev, int fd) { struct scsi_cmd sc; int err; unsigned char header[32]; scsi_cmd_init(udev, &sc); scsi_cmd_set(udev, &sc, 0, 0x51); scsi_cmd_set(udev, &sc, 8, sizeof(header)); scsi_cmd_set(udev, &sc, 9, 0); err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); if ((err != 0)) { info_scsi_cmd_err(udev, "READ DISC INFORMATION", err); if (cd_media == 1) { log_debug("no current profile, but disc is present; assuming CD-ROM"); cd_media_cd_rom = 1; cd_media_track_count = 1; cd_media_track_count_data = 1; return 0; } else { log_debug("no current profile, assuming no media"); return -1; } }; cd_media = 1; if (header[2] & 16) { cd_media_cd_rw = 1; log_debug("profile 0x0a media_cd_rw"); } else if ((header[2] & 3) < 2 && cd_cd_r) { cd_media_cd_r = 1; log_debug("profile 0x09 media_cd_r"); } else { cd_media_cd_rom = 1; log_debug("profile 0x08 media_cd_rom"); } return 0; } /* returns 0 if media was detected */ static int cd_profiles(struct udev *udev, int fd) { struct scsi_cmd sc; unsigned char features[65530]; unsigned int cur_profile = 0; unsigned int len; unsigned int i; int err; int ret; ret = -1; /* First query the current profile */ scsi_cmd_init(udev, &sc); scsi_cmd_set(udev, &sc, 0, 0x46); scsi_cmd_set(udev, &sc, 8, 8); scsi_cmd_set(udev, &sc, 9, 0); err = scsi_cmd_run(udev, &sc, fd, features, 8); if ((err != 0)) { info_scsi_cmd_err(udev, "GET CONFIGURATION", err); /* handle pre-MMC2 drives which do not support GET CONFIGURATION */ if (SK(err) == 0x5 && (ASC(err) == 0x20 || ASC(err) == 0x24)) { log_debug("drive is pre-MMC2 and does not support 46h get configuration command"); log_debug("trying to work around the problem"); ret = cd_profiles_old_mmc(udev, fd); } goto out; } cur_profile = features[6] << 8 | features[7]; if (cur_profile > 0) { log_debug("current profile 0x%02x", cur_profile); feature_profile_media (udev, cur_profile); ret = 0; /* we have media */ } else { log_debug("no current profile, assuming no media"); } len = features[0] << 24 | features[1] << 16 | features[2] << 8 | features[3]; log_debug("GET CONFIGURATION: size of features buffer 0x%04x", len); if (len > sizeof(features)) { log_debug("can not get features in a single query, truncating"); len = sizeof(features); } else if (len <= 8) len = sizeof(features); /* Now get the full feature buffer */ scsi_cmd_init(udev, &sc); scsi_cmd_set(udev, &sc, 0, 0x46); scsi_cmd_set(udev, &sc, 7, ( len >> 8 ) & 0xff); scsi_cmd_set(udev, &sc, 8, len & 0xff); scsi_cmd_set(udev, &sc, 9, 0); err = scsi_cmd_run(udev, &sc, fd, features, len); if ((err != 0)) { info_scsi_cmd_err(udev, "GET CONFIGURATION", err); return -1; } /* parse the length once more, in case the drive decided to have other features suddenly :) */ len = features[0] << 24 | features[1] << 16 | features[2] << 8 | features[3]; log_debug("GET CONFIGURATION: size of features buffer 0x%04x", len); if (len > sizeof(features)) { log_debug("can not get features in a single query, truncating"); len = sizeof(features); } /* device features */ for (i = 8; i+4 < len; i += (4 + features[i+3])) { unsigned int feature; feature = features[i] << 8 | features[i+1]; switch (feature) { case 0x00: log_debug("GET CONFIGURATION: feature 'profiles', with %i entries", features[i+3] / 4); feature_profiles(udev, &features[i]+4, MIN(features[i+3], len - i - 4)); break; default: log_debug("GET CONFIGURATION: feature 0x%04x , with 0x%02x bytes", feature, features[i+3]); break; } } out: return ret; } static int cd_media_info(struct udev *udev, int fd) { struct scsi_cmd sc; unsigned char header[32]; static const char *media_status[] = { "blank", "appendable", "complete", "other" }; int err; scsi_cmd_init(udev, &sc); scsi_cmd_set(udev, &sc, 0, 0x51); scsi_cmd_set(udev, &sc, 8, sizeof(header) & 0xff); scsi_cmd_set(udev, &sc, 9, 0); err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); if ((err != 0)) { info_scsi_cmd_err(udev, "READ DISC INFORMATION", err); return -1; }; cd_media = 1; log_debug("disk type %02x", header[8]); log_debug("hardware reported media status: %s", media_status[header[2] & 3]); /* exclude plain CDROM, some fake cdroms return 0 for "blank" media here */ if (!cd_media_cd_rom) cd_media_state = media_status[header[2] & 3]; /* fresh DVD-RW in restricted overwite mode reports itself as * "appendable"; change it to "blank" to make it consistent with what * gets reported after blanking, and what userspace expects */ if (cd_media_dvd_rw_ro && (header[2] & 3) == 1) cd_media_state = media_status[0]; /* DVD+RW discs (and DVD-RW in restricted mode) once formatted are * always "complete", DVD-RAM are "other" or "complete" if the disc is * write protected; we need to check the contents if it is blank */ if ((cd_media_dvd_rw_ro || cd_media_dvd_plus_rw || cd_media_dvd_plus_rw_dl || cd_media_dvd_ram) && (header[2] & 3) > 1) { unsigned char buffer[32 * 2048]; unsigned char len; int offset; if (cd_media_dvd_ram) { /* a write protected dvd-ram may report "complete" status */ unsigned char dvdstruct[8]; unsigned char format[12]; scsi_cmd_init(udev, &sc); scsi_cmd_set(udev, &sc, 0, 0xAD); scsi_cmd_set(udev, &sc, 7, 0xC0); scsi_cmd_set(udev, &sc, 9, sizeof(dvdstruct)); scsi_cmd_set(udev, &sc, 11, 0); err = scsi_cmd_run(udev, &sc, fd, dvdstruct, sizeof(dvdstruct)); if ((err != 0)) { info_scsi_cmd_err(udev, "READ DVD STRUCTURE", err); return -1; } if (dvdstruct[4] & 0x02) { cd_media_state = media_status[2]; log_debug("write-protected DVD-RAM media inserted"); goto determined; } /* let's make sure we don't try to read unformatted media */ scsi_cmd_init(udev, &sc); scsi_cmd_set(udev, &sc, 0, 0x23); scsi_cmd_set(udev, &sc, 8, sizeof(format)); scsi_cmd_set(udev, &sc, 9, 0); err = scsi_cmd_run(udev, &sc, fd, format, sizeof(format)); if ((err != 0)) { info_scsi_cmd_err(udev, "READ DVD FORMAT CAPACITIES", err); return -1; } len = format[3]; if (len & 7 || len < 16) { log_debug("invalid format capacities length"); return -1; } switch(format[8] & 3) { case 1: log_debug("unformatted DVD-RAM media inserted"); /* This means that last format was interrupted * or failed, blank dvd-ram discs are factory * formatted. Take no action here as it takes * quite a while to reformat a dvd-ram and it's * not automatically started */ goto determined; case 2: log_debug("formatted DVD-RAM media inserted"); break; case 3: cd_media = 0; //return no media log_debug("format capacities returned no media"); return -1; } } /* Take a closer look at formatted media (unformatted DVD+RW * has "blank" status", DVD-RAM was examined earlier) and check * for ISO and UDF PVDs or a fs superblock presence and do it * in one ioctl (we need just sectors 0 and 16) */ scsi_cmd_init(udev, &sc); scsi_cmd_set(udev, &sc, 0, 0x28); scsi_cmd_set(udev, &sc, 5, 0); scsi_cmd_set(udev, &sc, 8, 32); scsi_cmd_set(udev, &sc, 9, 0); err = scsi_cmd_run(udev, &sc, fd, buffer, sizeof(buffer)); if ((err != 0)) { cd_media = 0; info_scsi_cmd_err(udev, "READ FIRST 32 BLOCKS", err); return -1; } /* if any non-zero data is found in sector 16 (iso and udf) or * eventually 0 (fat32 boot sector, ext2 superblock, etc), disc * is assumed non-blank */ for (offset = 32768; offset < (32768 + 2048); offset++) { if (buffer [offset]) { log_debug("data in block 16, assuming complete"); goto determined; } } for (offset = 0; offset < 2048; offset++) { if (buffer [offset]) { log_debug("data in block 0, assuming complete"); goto determined; } } cd_media_state = media_status[0]; log_debug("no data in blocks 0 or 16, assuming blank"); } determined: /* "other" is e. g. DVD-RAM, can't append sessions there; DVDs in * restricted overwrite mode can never append, only in sequential mode */ if ((header[2] & 3) < 2 && !cd_media_dvd_rw_ro) cd_media_session_next = header[10] << 8 | header[5]; cd_media_session_count = header[9] << 8 | header[4]; cd_media_track_count = header[11] << 8 | header[6]; return 0; } static int cd_media_toc(struct udev *udev, int fd) { struct scsi_cmd sc; unsigned char header[12]; unsigned char toc[65536]; unsigned int len, i, num_tracks; unsigned char *p; int err; scsi_cmd_init(udev, &sc); scsi_cmd_set(udev, &sc, 0, 0x43); scsi_cmd_set(udev, &sc, 6, 1); scsi_cmd_set(udev, &sc, 8, sizeof(header) & 0xff); scsi_cmd_set(udev, &sc, 9, 0); err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); if ((err != 0)) { info_scsi_cmd_err(udev, "READ TOC", err); return -1; } len = (header[0] << 8 | header[1]) + 2; log_debug("READ TOC: len: %d, start track: %d, end track: %d", len, header[2], header[3]); if (len > sizeof(toc)) return -1; if (len < 2) return -1; /* 2: first track, 3: last track */ num_tracks = header[3] - header[2] + 1; /* empty media has no tracks */ if (len < 8) return 0; scsi_cmd_init(udev, &sc); scsi_cmd_set(udev, &sc, 0, 0x43); scsi_cmd_set(udev, &sc, 6, header[2]); /* First Track/Session Number */ scsi_cmd_set(udev, &sc, 7, (len >> 8) & 0xff); scsi_cmd_set(udev, &sc, 8, len & 0xff); scsi_cmd_set(udev, &sc, 9, 0); err = scsi_cmd_run(udev, &sc, fd, toc, len); if ((err != 0)) { info_scsi_cmd_err(udev, "READ TOC (tracks)", err); return -1; } /* Take care to not iterate beyond the last valid track as specified in * the TOC, but also avoid going beyond the TOC length, just in case * the last track number is invalidly large */ for (p = toc+4, i = 4; i < len-8 && num_tracks > 0; i += 8, p += 8, --num_tracks) { unsigned int block; unsigned int is_data_track; is_data_track = (p[1] & 0x04) != 0; block = p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7]; log_debug("track=%u info=0x%x(%s) start_block=%u", p[2], p[1] & 0x0f, is_data_track ? "data":"audio", block); if (is_data_track) cd_media_track_count_data++; else cd_media_track_count_audio++; } scsi_cmd_init(udev, &sc); scsi_cmd_set(udev, &sc, 0, 0x43); scsi_cmd_set(udev, &sc, 2, 1); /* Session Info */ scsi_cmd_set(udev, &sc, 8, sizeof(header)); scsi_cmd_set(udev, &sc, 9, 0); err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); if ((err != 0)) { info_scsi_cmd_err(udev, "READ TOC (multi session)", err); return -1; } len = header[4+4] << 24 | header[4+5] << 16 | header[4+6] << 8 | header[4+7]; log_debug("last track %u starts at block %u", header[4+2], len); cd_media_session_last_offset = (unsigned long long int)len * 2048; return 0; } int main(int argc, char *argv[]) { struct udev *udev; static const struct option options[] = { { "lock-media", no_argument, NULL, 'l' }, { "unlock-media", no_argument, NULL, 'u' }, { "eject-media", no_argument, NULL, 'e' }, { "debug", no_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, {} }; bool eject = false; bool lock = false; bool unlock = false; const char *node = NULL; int fd = -1; int cnt; int rc = 0; log_parse_environment(); log_open(); udev = udev_new(); if (udev == NULL) goto exit; for (;;) { int option; option = getopt_long(argc, argv, "deluh", options, NULL); if (option == -1) break; switch (option) { case 'l': lock = true; break; case 'u': unlock = true; break; case 'e': eject = true; break; case 'd': log_set_target(LOG_TARGET_CONSOLE); log_set_max_level(LOG_DEBUG); log_open(); break; case 'h': printf("Usage: cdrom_id [options] \n" " -l,--lock-media lock the media (to enable eject request events)\n" " -u,--unlock-media unlock the media\n" " -e,--eject-media eject the media\n" " -d,--debug debug to stderr\n" " -h,--help print this help text\n\n"); goto exit; default: rc = 1; goto exit; } } node = argv[optind]; if (!node) { log_error("no device"); fprintf(stderr, "no device\n"); rc = 1; goto exit; } initialize_srand(); for (cnt = 20; cnt > 0; cnt--) { struct timespec duration; fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC|(is_mounted(node) ? 0 : O_EXCL)); if (fd >= 0 || errno != EBUSY) break; duration.tv_sec = 0; duration.tv_nsec = (100 * 1000 * 1000) + (rand() % 100 * 1000 * 1000); nanosleep(&duration, NULL); } if (fd < 0) { log_debug("unable to open '%s'", node); fprintf(stderr, "unable to open '%s'\n", node); rc = 1; goto exit; } log_debug("probing: '%s'", node); /* same data as original cdrom_id */ if (cd_capability_compat(udev, fd) < 0) { rc = 1; goto exit; } /* check for media - don't bail if there's no media as we still need to * to read profiles */ cd_media_compat(udev, fd); /* check if drive talks MMC */ if (cd_inquiry(udev, fd) < 0) goto work; /* read drive and possibly current profile */ if (cd_profiles(udev, fd) != 0) goto work; /* at this point we are guaranteed to have media in the drive - find out more about it */ /* get session/track info */ cd_media_toc(udev, fd); /* get writable media state */ cd_media_info(udev, fd); work: /* lock the media, so we enable eject button events */ if (lock && cd_media) { log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (lock)"); media_lock(udev, fd, true); } if (unlock && cd_media) { log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)"); media_lock(udev, fd, false); } if (eject) { log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)"); media_lock(udev, fd, false); log_debug("START_STOP_UNIT (eject)"); media_eject(udev, fd); } printf("ID_CDROM=1\n"); if (cd_cd_rom) printf("ID_CDROM_CD=1\n"); if (cd_cd_r) printf("ID_CDROM_CD_R=1\n"); if (cd_cd_rw) printf("ID_CDROM_CD_RW=1\n"); if (cd_dvd_rom) printf("ID_CDROM_DVD=1\n"); if (cd_dvd_r) printf("ID_CDROM_DVD_R=1\n"); if (cd_dvd_rw) printf("ID_CDROM_DVD_RW=1\n"); if (cd_dvd_ram) printf("ID_CDROM_DVD_RAM=1\n"); if (cd_dvd_plus_r) printf("ID_CDROM_DVD_PLUS_R=1\n"); if (cd_dvd_plus_rw) printf("ID_CDROM_DVD_PLUS_RW=1\n"); if (cd_dvd_plus_r_dl) printf("ID_CDROM_DVD_PLUS_R_DL=1\n"); if (cd_dvd_plus_rw_dl) printf("ID_CDROM_DVD_PLUS_RW_DL=1\n"); if (cd_bd) printf("ID_CDROM_BD=1\n"); if (cd_bd_r) printf("ID_CDROM_BD_R=1\n"); if (cd_bd_re) printf("ID_CDROM_BD_RE=1\n"); if (cd_hddvd) printf("ID_CDROM_HDDVD=1\n"); if (cd_hddvd_r) printf("ID_CDROM_HDDVD_R=1\n"); if (cd_hddvd_rw) printf("ID_CDROM_HDDVD_RW=1\n"); if (cd_mo) printf("ID_CDROM_MO=1\n"); if (cd_mrw) printf("ID_CDROM_MRW=1\n"); if (cd_mrw_w) printf("ID_CDROM_MRW_W=1\n"); if (cd_media) printf("ID_CDROM_MEDIA=1\n"); if (cd_media_mo) printf("ID_CDROM_MEDIA_MO=1\n"); if (cd_media_mrw) printf("ID_CDROM_MEDIA_MRW=1\n"); if (cd_media_mrw_w) printf("ID_CDROM_MEDIA_MRW_W=1\n"); if (cd_media_cd_rom) printf("ID_CDROM_MEDIA_CD=1\n"); if (cd_media_cd_r) printf("ID_CDROM_MEDIA_CD_R=1\n"); if (cd_media_cd_rw) printf("ID_CDROM_MEDIA_CD_RW=1\n"); if (cd_media_dvd_rom) printf("ID_CDROM_MEDIA_DVD=1\n"); if (cd_media_dvd_r) printf("ID_CDROM_MEDIA_DVD_R=1\n"); if (cd_media_dvd_ram) printf("ID_CDROM_MEDIA_DVD_RAM=1\n"); if (cd_media_dvd_rw) printf("ID_CDROM_MEDIA_DVD_RW=1\n"); if (cd_media_dvd_plus_r) printf("ID_CDROM_MEDIA_DVD_PLUS_R=1\n"); if (cd_media_dvd_plus_rw) printf("ID_CDROM_MEDIA_DVD_PLUS_RW=1\n"); if (cd_media_dvd_plus_rw_dl) printf("ID_CDROM_MEDIA_DVD_PLUS_RW_DL=1\n"); if (cd_media_dvd_plus_r_dl) printf("ID_CDROM_MEDIA_DVD_PLUS_R_DL=1\n"); if (cd_media_bd) printf("ID_CDROM_MEDIA_BD=1\n"); if (cd_media_bd_r) printf("ID_CDROM_MEDIA_BD_R=1\n"); if (cd_media_bd_re) printf("ID_CDROM_MEDIA_BD_RE=1\n"); if (cd_media_hddvd) printf("ID_CDROM_MEDIA_HDDVD=1\n"); if (cd_media_hddvd_r) printf("ID_CDROM_MEDIA_HDDVD_R=1\n"); if (cd_media_hddvd_rw) printf("ID_CDROM_MEDIA_HDDVD_RW=1\n"); if (cd_media_state != NULL) printf("ID_CDROM_MEDIA_STATE=%s\n", cd_media_state); if (cd_media_session_next > 0) printf("ID_CDROM_MEDIA_SESSION_NEXT=%u\n", cd_media_session_next); if (cd_media_session_count > 0) printf("ID_CDROM_MEDIA_SESSION_COUNT=%u\n", cd_media_session_count); if (cd_media_session_count > 1 && cd_media_session_last_offset > 0) printf("ID_CDROM_MEDIA_SESSION_LAST_OFFSET=%llu\n", cd_media_session_last_offset); if (cd_media_track_count > 0) printf("ID_CDROM_MEDIA_TRACK_COUNT=%u\n", cd_media_track_count); if (cd_media_track_count_audio > 0) printf("ID_CDROM_MEDIA_TRACK_COUNT_AUDIO=%u\n", cd_media_track_count_audio); if (cd_media_track_count_data > 0) printf("ID_CDROM_MEDIA_TRACK_COUNT_DATA=%u\n", cd_media_track_count_data); exit: if (fd >= 0) close(fd); udev_unref(udev); log_close(); return rc; } systemd-229/src/udev/collect/000077500000000000000000000000001265713322000162405ustar00rootroot00000000000000systemd-229/src/udev/collect/Makefile000077700000000000000000000000001265713322000215462../Makefileustar00rootroot00000000000000systemd-229/src/udev/collect/collect.c000066400000000000000000000340341265713322000200350ustar00rootroot00000000000000/* * Collect variables across events. * * usage: collect [--add|--remove] * * Adds ID to the list governed by . * must be part of the ID list . * If all IDs given by are listed (ie collect has been * invoked for each ID in ) collect returns 0, the * number of missing IDs otherwise. * A negative number is returned on error. * * Copyright(C) 2007, Hannes Reinecke * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * */ #include #include #include #include #include "alloc-util.h" #include "libudev-private.h" #include "macro.h" #include "stdio-util.h" #include "string-util.h" #define BUFSIZE 16 #define UDEV_ALARM_TIMEOUT 180 enum collect_state { STATE_NONE, STATE_OLD, STATE_CONFIRMED, }; struct _mate { struct udev_list_node node; char *name; enum collect_state state; }; static struct udev_list_node bunch; static int debug; /* This can increase dynamically */ static size_t bufsize = BUFSIZE; static inline struct _mate *node_to_mate(struct udev_list_node *node) { return container_of(node, struct _mate, node); } noreturn static void sig_alrm(int signo) { exit(4); } static void usage(void) { printf("%s [options] \n\n" "Collect variables across events.\n\n" " -h --help Print this message\n" " -a --add Add ID to the list \n" " -r --remove Remove ID from the list \n" " -d --debug Debug to stderr\n\n" " Adds ID to the list governed by .\n" " must be part of the list .\n" " If all IDs given by are listed (ie collect has been\n" " invoked for each ID in ) collect returns 0, the\n" " number of missing IDs otherwise.\n" " On error a negative number is returned.\n\n" , program_invocation_short_name); } /* * prepare * * Prepares the database file */ static int prepare(char *dir, char *filename) { char buf[512]; int r, fd; r = mkdir(dir, 0700); if (r < 0 && errno != EEXIST) return -errno; xsprintf(buf, "%s/%s", dir, filename); fd = open(buf,O_RDWR|O_CREAT|O_CLOEXEC, S_IRUSR|S_IWUSR); if (fd < 0) fprintf(stderr, "Cannot open %s: %m\n", buf); if (lockf(fd,F_TLOCK,0) < 0) { if (debug) fprintf(stderr, "Lock taken, wait for %d seconds\n", UDEV_ALARM_TIMEOUT); if (errno == EAGAIN || errno == EACCES) { alarm(UDEV_ALARM_TIMEOUT); lockf(fd, F_LOCK, 0); if (debug) fprintf(stderr, "Acquired lock on %s\n", buf); } else { if (debug) fprintf(stderr, "Could not get lock on %s: %m\n", buf); } } return fd; } /* * Read checkpoint file * * Tricky reading this. We allocate a buffer twice as large * as we're going to read. Then we read into the upper half * of that buffer and start parsing. * Once we do _not_ find end-of-work terminator (whitespace * character) we move the upper half to the lower half, * adjust the read pointer and read the next bit. * Quite clever methinks :-) * I should become a programmer ... * * Yes, one could have used fgets() for this. But then we'd * have to use freopen etc which I found quite tedious. */ static int checkout(int fd) { int len; char *buf, *ptr, *word = NULL; struct _mate *him; restart: len = bufsize >> 1; buf = malloc(bufsize + 1); if (!buf) return log_oom(); memset(buf, ' ', bufsize); buf[bufsize] = '\0'; ptr = buf + len; while ((read(fd, buf + len, len)) > 0) { while (ptr && *ptr) { word = ptr; ptr = strpbrk(word," \n\t\r"); if (!ptr && word < (buf + len)) { bufsize = bufsize << 1; if (debug) fprintf(stderr, "ID overflow, restarting with size %zu\n", bufsize); free(buf); lseek(fd, 0, SEEK_SET); goto restart; } if (ptr) { *ptr = '\0'; ptr++; if (!strlen(word)) continue; if (debug) fprintf(stderr, "Found word %s\n", word); him = malloc(sizeof (struct _mate)); if (!him) { free(buf); return log_oom(); } him->name = strdup(word); if (!him->name) { free(buf); free(him); return log_oom(); } him->state = STATE_OLD; udev_list_node_append(&him->node, &bunch); word = NULL; } } memcpy(buf, buf + len, len); memset(buf + len, ' ', len); if (!ptr) ptr = word; if (!ptr) break; ptr -= len; } free(buf); return 0; } /* * invite * * Adds a new ID 'us' to the internal list, * marks it as confirmed. */ static void invite(char *us) { struct udev_list_node *him_node; struct _mate *who = NULL; if (debug) fprintf(stderr, "Adding ID '%s'\n", us); udev_list_node_foreach(him_node, &bunch) { struct _mate *him = node_to_mate(him_node); if (streq(him->name, us)) { him->state = STATE_CONFIRMED; who = him; } } if (debug && !who) fprintf(stderr, "ID '%s' not in database\n", us); } /* * reject * * Marks the ID 'us' as invalid, * causing it to be removed when the * list is written out. */ static void reject(char *us) { struct udev_list_node *him_node; struct _mate *who = NULL; if (debug) fprintf(stderr, "Removing ID '%s'\n", us); udev_list_node_foreach(him_node, &bunch) { struct _mate *him = node_to_mate(him_node); if (streq(him->name, us)) { him->state = STATE_NONE; who = him; } } if (debug && !who) fprintf(stderr, "ID '%s' not in database\n", us); } /* * kickout * * Remove all IDs in the internal list which are not part * of the list passed via the command line. */ static void kickout(void) { struct udev_list_node *him_node; struct udev_list_node *tmp; udev_list_node_foreach_safe(him_node, tmp, &bunch) { struct _mate *him = node_to_mate(him_node); if (him->state == STATE_OLD) { udev_list_node_remove(&him->node); free(him->name); free(him); } } } /* * missing * * Counts all missing IDs in the internal list. */ static int missing(int fd) { char *buf; int ret = 0; struct udev_list_node *him_node; buf = malloc(bufsize); if (!buf) return log_oom(); udev_list_node_foreach(him_node, &bunch) { struct _mate *him = node_to_mate(him_node); if (him->state == STATE_NONE) { ret++; } else { while (strlen(him->name)+1 >= bufsize) { char *tmpbuf; bufsize = bufsize << 1; tmpbuf = realloc(buf, bufsize); if (!tmpbuf) { free(buf); return log_oom(); } buf = tmpbuf; } snprintf(buf, strlen(him->name)+2, "%s ", him->name); if (write(fd, buf, strlen(buf)) < 0) { free(buf); return -1; } } } free(buf); return ret; } /* * everybody * * Prints out the status of the internal list. */ static void everybody(void) { struct udev_list_node *him_node; const char *state = ""; udev_list_node_foreach(him_node, &bunch) { struct _mate *him = node_to_mate(him_node); switch (him->state) { case STATE_NONE: state = "none"; break; case STATE_OLD: state = "old"; break; case STATE_CONFIRMED: state = "confirmed"; break; } fprintf(stderr, "ID: %s=%s\n", him->name, state); } } int main(int argc, char **argv) { struct udev *udev; static const struct option options[] = { { "add", no_argument, NULL, 'a' }, { "remove", no_argument, NULL, 'r' }, { "debug", no_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, {} }; int argi; char *checkpoint, *us; int fd; int i; int ret = EXIT_SUCCESS; int prune = 0; char tmpdir[UTIL_PATH_SIZE]; udev = udev_new(); if (udev == NULL) { ret = EXIT_FAILURE; goto exit; } for (;;) { int option; option = getopt_long(argc, argv, "ardh", options, NULL); if (option == -1) break; switch (option) { case 'a': prune = 0; break; case 'r': prune = 1; break; case 'd': debug = 1; break; case 'h': usage(); goto exit; default: ret = 1; goto exit; } } argi = optind; if (argi + 2 > argc) { printf("Missing parameter(s)\n"); ret = 1; goto exit; } checkpoint = argv[argi++]; us = argv[argi++]; if (signal(SIGALRM, sig_alrm) == SIG_ERR) { fprintf(stderr, "Cannot set SIGALRM: %m\n"); ret = 2; goto exit; } udev_list_node_init(&bunch); if (debug) fprintf(stderr, "Using checkpoint '%s'\n", checkpoint); strscpyl(tmpdir, sizeof(tmpdir), "/run/udev/collect", NULL); fd = prepare(tmpdir, checkpoint); if (fd < 0) { ret = 3; goto out; } if (checkout(fd) < 0) { ret = 2; goto out; } for (i = argi; i < argc; i++) { struct udev_list_node *him_node; struct _mate *who; who = NULL; udev_list_node_foreach(him_node, &bunch) { struct _mate *him = node_to_mate(him_node); if (streq(him->name, argv[i])) who = him; } if (!who) { struct _mate *him; if (debug) fprintf(stderr, "ID %s: not in database\n", argv[i]); him = new(struct _mate, 1); if (!him) { ret = ENOMEM; goto out; } him->name = strdup(argv[i]); if (!him->name) { free(him); ret = ENOMEM; goto out; } him->state = STATE_NONE; udev_list_node_append(&him->node, &bunch); } else { if (debug) fprintf(stderr, "ID %s: found in database\n", argv[i]); who->state = STATE_CONFIRMED; } } if (prune) reject(us); else invite(us); if (debug) { everybody(); fprintf(stderr, "Prune lists\n"); } kickout(); lseek(fd, 0, SEEK_SET); ftruncate(fd, 0); ret = missing(fd); lockf(fd, F_ULOCK, 0); close(fd); out: if (debug) everybody(); if (ret >= 0) printf("COLLECT_%s=%d\n", checkpoint, ret); exit: udev_unref(udev); return ret; } systemd-229/src/udev/mtd_probe/000077500000000000000000000000001265713322000165665ustar00rootroot00000000000000systemd-229/src/udev/mtd_probe/Makefile000077700000000000000000000000001265713322000220742../Makefileustar00rootroot00000000000000systemd-229/src/udev/mtd_probe/mtd_probe.c000066400000000000000000000030111265713322000207000ustar00rootroot00000000000000/* * Copyright (C) 2010 - Maxim Levitsky * * mtd_probe is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * mtd_probe is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with mtd_probe; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "mtd_probe.h" int main(int argc, char** argv) { int mtd_fd; int error; mtd_info_t mtd_info; if (argc != 2) { printf("usage: mtd_probe /dev/mtd[n]\n"); return 1; } mtd_fd = open(argv[1], O_RDONLY|O_CLOEXEC); if (mtd_fd == -1) { perror("open"); exit(-1); } error = ioctl(mtd_fd, MEMGETINFO, &mtd_info); if (error == -1) { perror("ioctl"); exit(-1); } probe_smart_media(mtd_fd, &mtd_info); return -1; } systemd-229/src/udev/mtd_probe/mtd_probe.h000066400000000000000000000031141265713322000207110ustar00rootroot00000000000000/* * Copyright (C) 2010 - Maxim Levitsky * * mtd_probe is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * mtd_probe is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with mtd_probe; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ #pragma once #include #include "macro.h" /* Full oob structure as written on the flash */ struct sm_oob { uint32_t reserved; uint8_t data_status; uint8_t block_status; uint8_t lba_copy1[2]; uint8_t ecc2[3]; uint8_t lba_copy2[2]; uint8_t ecc1[3]; } _packed_; /* one sector is always 512 bytes, but it can consist of two nand pages */ #define SM_SECTOR_SIZE 512 /* oob area is also 16 bytes, but might be from two pages */ #define SM_OOB_SIZE 16 /* This is maximum zone size, and all devices that have more that one zone have this size */ #define SM_MAX_ZONE_SIZE 1024 /* support for small page nand */ #define SM_SMALL_PAGE 256 #define SM_SMALL_OOB_SIZE 8 void probe_smart_media(int mtd_fd, mtd_info_t *info); systemd-229/src/udev/mtd_probe/probe_smartmedia.c000066400000000000000000000052661265713322000222600ustar00rootroot00000000000000/* * Copyright (C) 2010 - Maxim Levitsky * * mtd_probe is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * mtd_probe is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with mtd_probe; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include "mtd_probe.h" static const uint8_t cis_signature[] = { 0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02, 0xDF, 0x01, 0x20 }; void probe_smart_media(int mtd_fd, mtd_info_t* info) { int sector_size; int block_size; int size_in_megs; int spare_count; char* cis_buffer = malloc(SM_SECTOR_SIZE); int offset; int cis_found = 0; if (!cis_buffer) return; if (info->type != MTD_NANDFLASH) goto exit; sector_size = info->writesize; block_size = info->erasesize; size_in_megs = info->size / (1024 * 1024); if (sector_size != SM_SECTOR_SIZE && sector_size != SM_SMALL_PAGE) goto exit; switch(size_in_megs) { case 1: case 2: spare_count = 6; break; case 4: spare_count = 12; break; default: spare_count = 24; break; } for (offset = 0 ; offset < block_size * spare_count ; offset += sector_size) { lseek(mtd_fd, SEEK_SET, offset); if (read(mtd_fd, cis_buffer, SM_SECTOR_SIZE) == SM_SECTOR_SIZE){ cis_found = 1; break; } } if (!cis_found) goto exit; if (memcmp(cis_buffer, cis_signature, sizeof(cis_signature)) != 0 && (memcmp(cis_buffer + SM_SMALL_PAGE, cis_signature, sizeof(cis_signature)) != 0)) goto exit; printf("MTD_FTL=smartmedia\n"); free(cis_buffer); exit(0); exit: free(cis_buffer); return; } systemd-229/src/udev/net/000077500000000000000000000000001265713322000154015ustar00rootroot00000000000000systemd-229/src/udev/net/.gitignore000066400000000000000000000000251265713322000173660ustar00rootroot00000000000000/link-config-gperf.c systemd-229/src/udev/net/Makefile000077700000000000000000000000001265713322000211222../../Makefileustar00rootroot00000000000000systemd-229/src/udev/net/ethtool-util.c000066400000000000000000000134311265713322000202000ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "conf-parser.h" #include "ethtool-util.h" #include "log.h" #include "string-table.h" #include "strxcpyx.h" #include "util.h" static const char* const duplex_table[_DUP_MAX] = { [DUP_FULL] = "full", [DUP_HALF] = "half" }; DEFINE_STRING_TABLE_LOOKUP(duplex, Duplex); DEFINE_CONFIG_PARSE_ENUM(config_parse_duplex, duplex, Duplex, "Failed to parse duplex setting"); static const char* const wol_table[_WOL_MAX] = { [WOL_PHY] = "phy", [WOL_MAGIC] = "magic", [WOL_OFF] = "off" }; DEFINE_STRING_TABLE_LOOKUP(wol, WakeOnLan); DEFINE_CONFIG_PARSE_ENUM(config_parse_wol, wol, WakeOnLan, "Failed to parse WakeOnLan setting"); int ethtool_connect(int *ret) { int fd; assert_return(ret, -EINVAL); fd = socket(PF_INET, SOCK_DGRAM, 0); if (fd < 0) return -errno; *ret = fd; return 0; } int ethtool_get_driver(int *fd, const char *ifname, char **ret) { struct ethtool_drvinfo ecmd = { .cmd = ETHTOOL_GDRVINFO }; struct ifreq ifr = { .ifr_data = (void*) &ecmd }; char *d; int r; if (*fd < 0) { r = ethtool_connect(fd); if (r < 0) return log_warning_errno(r, "link_config: could not connect to ethtool: %m"); } strscpy(ifr.ifr_name, IFNAMSIZ, ifname); r = ioctl(*fd, SIOCETHTOOL, &ifr); if (r < 0) return -errno; d = strdup(ecmd.driver); if (!d) return -ENOMEM; *ret = d; return 0; } int ethtool_set_speed(int *fd, const char *ifname, unsigned int speed, Duplex duplex) { struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; struct ifreq ifr = { .ifr_data = (void*) &ecmd }; bool need_update = false; int r; if (speed == 0 && duplex == _DUP_INVALID) return 0; if (*fd < 0) { r = ethtool_connect(fd); if (r < 0) return log_warning_errno(r, "link_config: could not connect to ethtool: %m"); } strscpy(ifr.ifr_name, IFNAMSIZ, ifname); r = ioctl(*fd, SIOCETHTOOL, &ifr); if (r < 0) return -errno; if (ethtool_cmd_speed(&ecmd) != speed) { ethtool_cmd_speed_set(&ecmd, speed); need_update = true; } switch (duplex) { case DUP_HALF: if (ecmd.duplex != DUPLEX_HALF) { ecmd.duplex = DUPLEX_HALF; need_update = true; } break; case DUP_FULL: if (ecmd.duplex != DUPLEX_FULL) { ecmd.duplex = DUPLEX_FULL; need_update = true; } break; default: break; } if (need_update) { ecmd.cmd = ETHTOOL_SSET; r = ioctl(*fd, SIOCETHTOOL, &ifr); if (r < 0) return -errno; } return 0; } int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol) { struct ethtool_wolinfo ecmd = { .cmd = ETHTOOL_GWOL }; struct ifreq ifr = { .ifr_data = (void*) &ecmd }; bool need_update = false; int r; if (wol == _WOL_INVALID) return 0; if (*fd < 0) { r = ethtool_connect(fd); if (r < 0) return log_warning_errno(r, "link_config: could not connect to ethtool: %m"); } strscpy(ifr.ifr_name, IFNAMSIZ, ifname); r = ioctl(*fd, SIOCETHTOOL, &ifr); if (r < 0) return -errno; switch (wol) { case WOL_PHY: if (ecmd.wolopts != WAKE_PHY) { ecmd.wolopts = WAKE_PHY; need_update = true; } break; case WOL_MAGIC: if (ecmd.wolopts != WAKE_MAGIC) { ecmd.wolopts = WAKE_MAGIC; need_update = true; } break; case WOL_OFF: if (ecmd.wolopts != 0) { ecmd.wolopts = 0; need_update = true; } break; default: break; } if (need_update) { ecmd.cmd = ETHTOOL_SWOL; r = ioctl(*fd, SIOCETHTOOL, &ifr); if (r < 0) return -errno; } return 0; } systemd-229/src/udev/net/ethtool-util.h000066400000000000000000000036251265713322000202110ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include /* we can't use DUPLEX_ prefix, as it * clashes with */ typedef enum Duplex { DUP_FULL, DUP_HALF, _DUP_MAX, _DUP_INVALID = -1 } Duplex; typedef enum WakeOnLan { WOL_PHY, WOL_MAGIC, WOL_OFF, _WOL_MAX, _WOL_INVALID = -1 } WakeOnLan; int ethtool_connect(int *ret); int ethtool_get_driver(int *fd, const char *ifname, char **ret); int ethtool_set_speed(int *fd, const char *ifname, unsigned int speed, Duplex duplex); int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol); const char *duplex_to_string(Duplex d) _const_; Duplex duplex_from_string(const char *d) _pure_; const char *wol_to_string(WakeOnLan wol) _const_; WakeOnLan wol_from_string(const char *wol) _pure_; int config_parse_duplex(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_wol(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); systemd-229/src/udev/net/link-config-gperf.gperf000066400000000000000000000051101265713322000217240ustar00rootroot00000000000000%{ #include #include "conf-parser.h" #include "network-internal.h" #include "link-config.h" #include "ethtool-util.h" %} struct ConfigPerfItem; %null_strings %language=ANSI-C %define slot-name section_and_lvalue %define hash-function-name link_config_gperf_hash %define lookup-function-name link_config_gperf_lookup %readonly-tables %omit-struct-type %struct-type %includes %% Match.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, match_mac) Match.OriginalName, config_parse_ifnames, 0, offsetof(link_config, match_name) Match.Path, config_parse_strv, 0, offsetof(link_config, match_path) Match.Driver, config_parse_strv, 0, offsetof(link_config, match_driver) Match.Type, config_parse_strv, 0, offsetof(link_config, match_type) Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(link_config, match_host) Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(link_config, match_virt) Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, match_kernel) Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(link_config, match_arch) Link.Description, config_parse_string, 0, offsetof(link_config, description) Link.MACAddressPolicy, config_parse_mac_policy, 0, offsetof(link_config, mac_policy) Link.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, mac) Link.NamePolicy, config_parse_name_policy, 0, offsetof(link_config, name_policy) Link.Name, config_parse_ifname, 0, offsetof(link_config, name) Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias) Link.MTUBytes, config_parse_iec_size, 0, offsetof(link_config, mtu) Link.BitsPerSecond, config_parse_si_size, 0, offsetof(link_config, speed) Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex) Link.WakeOnLan, config_parse_wol, 0, offsetof(link_config, wol) systemd-229/src/udev/net/link-config.c000066400000000000000000000414751265713322000177600ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "sd-netlink.h" #include "alloc-util.h" #include "conf-files.h" #include "conf-parser.h" #include "ethtool-util.h" #include "fd-util.h" #include "libudev-private.h" #include "link-config.h" #include "log.h" #include "missing.h" #include "netlink-util.h" #include "network-internal.h" #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" #include "random-util.h" #include "stat-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" #include "util.h" struct link_config_ctx { LIST_HEAD(link_config, links); int ethtool_fd; bool enable_name_policy; sd_netlink *rtnl; usec_t link_dirs_ts_usec; }; static const char* const link_dirs[] = { "/etc/systemd/network", "/run/systemd/network", "/usr/lib/systemd/network", #ifdef HAVE_SPLIT_USR "/lib/systemd/network", #endif NULL}; static void link_config_free(link_config *link) { if (!link) return; free(link->filename); free(link->match_mac); strv_free(link->match_path); strv_free(link->match_driver); strv_free(link->match_type); free(link->match_name); free(link->match_host); free(link->match_virt); free(link->match_kernel); free(link->match_arch); free(link->description); free(link->mac); free(link->name_policy); free(link->name); free(link->alias); free(link); } DEFINE_TRIVIAL_CLEANUP_FUNC(link_config*, link_config_free); static void link_configs_free(link_config_ctx *ctx) { link_config *link, *link_next; if (!ctx) return; LIST_FOREACH_SAFE(links, link, link_next, ctx->links) link_config_free(link); } void link_config_ctx_free(link_config_ctx *ctx) { if (!ctx) return; safe_close(ctx->ethtool_fd); sd_netlink_unref(ctx->rtnl); link_configs_free(ctx); free(ctx); return; } DEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free); int link_config_ctx_new(link_config_ctx **ret) { _cleanup_(link_config_ctx_freep) link_config_ctx *ctx = NULL; if (!ret) return -EINVAL; ctx = new0(link_config_ctx, 1); if (!ctx) return -ENOMEM; LIST_HEAD_INIT(ctx->links); ctx->ethtool_fd = -1; ctx->enable_name_policy = true; *ret = ctx; ctx = NULL; return 0; } static int load_link(link_config_ctx *ctx, const char *filename) { _cleanup_(link_config_freep) link_config *link = NULL; _cleanup_fclose_ FILE *file = NULL; int r; assert(ctx); assert(filename); file = fopen(filename, "re"); if (!file) { if (errno == ENOENT) return 0; else return -errno; } if (null_or_empty_fd(fileno(file))) { log_debug("Skipping empty file: %s", filename); return 0; } link = new0(link_config, 1); if (!link) return log_oom(); link->mac_policy = _MACPOLICY_INVALID; link->wol = _WOL_INVALID; link->duplex = _DUP_INVALID; r = config_parse(NULL, filename, file, "Match\0Link\0Ethernet\0", config_item_perf_lookup, link_config_gperf_lookup, false, false, true, link); if (r < 0) return r; else log_debug("Parsed configuration file %s", filename); if (link->mtu > UINT_MAX || link->speed > UINT_MAX) return -ERANGE; link->filename = strdup(filename); LIST_PREPEND(links, ctx->links, link); link = NULL; return 0; } static bool enable_name_policy(void) { _cleanup_free_ char *line = NULL; const char *word, *state; int r; size_t l; r = proc_cmdline(&line); if (r < 0) { log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m"); return true; } FOREACH_WORD_QUOTED(word, l, line, state) if (strneq(word, "net.ifnames=0", l)) return false; return true; } int link_config_load(link_config_ctx *ctx) { int r; _cleanup_strv_free_ char **files; char **f; link_configs_free(ctx); if (!enable_name_policy()) { ctx->enable_name_policy = false; log_info("Network interface NamePolicy= disabled on kernel command line, ignoring."); } /* update timestamp */ paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true); r = conf_files_list_strv(&files, ".link", NULL, link_dirs); if (r < 0) return log_error_errno(r, "failed to enumerate link files: %m"); STRV_FOREACH_BACKWARDS(f, files) { r = load_link(ctx, *f); if (r < 0) return r; } return 0; } bool link_config_should_reload(link_config_ctx *ctx) { return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false); } int link_config_get(link_config_ctx *ctx, struct udev_device *device, link_config **ret) { link_config *link; assert(ctx); assert(device); assert(ret); LIST_FOREACH(links, link, ctx->links) { const char* attr_value; attr_value = udev_device_get_sysattr_value(device, "address"); if (net_match_config(link->match_mac, link->match_path, link->match_driver, link->match_type, link->match_name, link->match_host, link->match_virt, link->match_kernel, link->match_arch, attr_value ? ether_aton(attr_value) : NULL, udev_device_get_property_value(device, "ID_PATH"), udev_device_get_driver(udev_device_get_parent(device)), udev_device_get_property_value(device, "ID_NET_DRIVER"), udev_device_get_devtype(device), udev_device_get_sysname(device))) { if (link->match_name) { unsigned char name_assign_type = NET_NAME_UNKNOWN; attr_value = udev_device_get_sysattr_value(device, "name_assign_type"); if (attr_value) (void) safe_atou8(attr_value, &name_assign_type); if (name_assign_type == NET_NAME_ENUM) { log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'", link->filename, udev_device_get_sysname(device)); *ret = link; return 0; } else if (name_assign_type == NET_NAME_RENAMED) { log_warning("Config file %s matches device based on renamed interface name '%s', ignoring", link->filename, udev_device_get_sysname(device)); continue; } } log_debug("Config file %s applies to device %s", link->filename, udev_device_get_sysname(device)); *ret = link; return 0; } } *ret = NULL; return -ENOENT; } static bool mac_is_random(struct udev_device *device) { const char *s; unsigned type; int r; /* if we can't get the assign type, assume it is not random */ s = udev_device_get_sysattr_value(device, "addr_assign_type"); if (!s) return false; r = safe_atou(s, &type); if (r < 0) return false; return type == NET_ADDR_RANDOM; } static bool should_rename(struct udev_device *device, bool respect_predictable) { const char *s; unsigned type; int r; /* if we can't get the assgin type, assume we should rename */ s = udev_device_get_sysattr_value(device, "name_assign_type"); if (!s) return true; r = safe_atou(s, &type); if (r < 0) return true; switch (type) { case NET_NAME_USER: case NET_NAME_RENAMED: /* these were already named by userspace, do not touch again */ return false; case NET_NAME_PREDICTABLE: /* the kernel claims to have given a predictable name */ if (respect_predictable) return false; /* fall through */ case NET_NAME_ENUM: default: /* the name is known to be bad, or of an unknown type */ return true; } } static int get_mac(struct udev_device *device, bool want_random, struct ether_addr *mac) { int r; if (want_random) random_bytes(mac->ether_addr_octet, ETH_ALEN); else { uint64_t result; r = net_get_unique_predictable_data(device, &result); if (r < 0) return r; assert_cc(ETH_ALEN <= sizeof(result)); memcpy(mac->ether_addr_octet, &result, ETH_ALEN); } /* see eth_random_addr in the kernel */ mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */ mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */ return 0; } int link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_device *device, const char **name) { const char *old_name; const char *new_name = NULL; struct ether_addr generated_mac; struct ether_addr *mac = NULL; bool respect_predictable = false; int r, ifindex; assert(ctx); assert(config); assert(device); assert(name); old_name = udev_device_get_sysname(device); if (!old_name) return -EINVAL; r = ethtool_set_speed(&ctx->ethtool_fd, old_name, config->speed / 1024, config->duplex); if (r < 0) log_warning_errno(r, "Could not set speed or duplex of %s to %zu Mbps (%s): %m", old_name, config->speed / 1024, duplex_to_string(config->duplex)); r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol); if (r < 0) log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m", old_name, wol_to_string(config->wol)); ifindex = udev_device_get_ifindex(device); if (ifindex <= 0) { log_warning("Could not find ifindex"); return -ENODEV; } if (ctx->enable_name_policy && config->name_policy) { NamePolicy *policy; for (policy = config->name_policy; !new_name && *policy != _NAMEPOLICY_INVALID; policy++) { switch (*policy) { case NAMEPOLICY_KERNEL: respect_predictable = true; break; case NAMEPOLICY_DATABASE: new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE"); break; case NAMEPOLICY_ONBOARD: new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD"); break; case NAMEPOLICY_SLOT: new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT"); break; case NAMEPOLICY_PATH: new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH"); break; case NAMEPOLICY_MAC: new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC"); break; default: break; } } } if (should_rename(device, respect_predictable)) { /* if not set by policy, fall back manually set name */ if (!new_name) new_name = config->name; } else new_name = NULL; switch (config->mac_policy) { case MACPOLICY_PERSISTENT: if (mac_is_random(device)) { r = get_mac(device, false, &generated_mac); if (r == -ENOENT) { log_warning_errno(r, "Could not generate persistent MAC address for %s: %m", old_name); break; } else if (r < 0) return r; mac = &generated_mac; } break; case MACPOLICY_RANDOM: if (!mac_is_random(device)) { r = get_mac(device, true, &generated_mac); if (r == -ENOENT) { log_warning_errno(r, "Could not generate random MAC address for %s: %m", old_name); break; } else if (r < 0) return r; mac = &generated_mac; } break; case MACPOLICY_NONE: default: mac = config->mac; } r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac, config->mtu); if (r < 0) return log_warning_errno(r, "Could not set Alias, MACAddress or MTU on %s: %m", old_name); *name = new_name; return 0; } int link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) { const char *name; char *driver = NULL; int r; name = udev_device_get_sysname(device); if (!name) return -EINVAL; r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver); if (r < 0) return r; *ret = driver; return 0; } static const char* const mac_policy_table[_MACPOLICY_MAX] = { [MACPOLICY_PERSISTENT] = "persistent", [MACPOLICY_RANDOM] = "random", [MACPOLICY_NONE] = "none" }; DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy); DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy, "Failed to parse MAC address policy"); static const char* const name_policy_table[_NAMEPOLICY_MAX] = { [NAMEPOLICY_KERNEL] = "kernel", [NAMEPOLICY_DATABASE] = "database", [NAMEPOLICY_ONBOARD] = "onboard", [NAMEPOLICY_SLOT] = "slot", [NAMEPOLICY_PATH] = "path", [NAMEPOLICY_MAC] = "mac" }; DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy); DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy, _NAMEPOLICY_INVALID, "Failed to parse interface name policy"); systemd-229/src/udev/net/link-config.h000066400000000000000000000062411265713322000177550ustar00rootroot00000000000000/*** This file is part of systemd. Copyright (C) 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #pragma once #include "libudev.h" #include "condition.h" #include "ethtool-util.h" #include "list.h" typedef struct link_config_ctx link_config_ctx; typedef struct link_config link_config; typedef enum MACPolicy { MACPOLICY_PERSISTENT, MACPOLICY_RANDOM, MACPOLICY_NONE, _MACPOLICY_MAX, _MACPOLICY_INVALID = -1 } MACPolicy; typedef enum NamePolicy { NAMEPOLICY_KERNEL, NAMEPOLICY_DATABASE, NAMEPOLICY_ONBOARD, NAMEPOLICY_SLOT, NAMEPOLICY_PATH, NAMEPOLICY_MAC, _NAMEPOLICY_MAX, _NAMEPOLICY_INVALID = -1 } NamePolicy; struct link_config { char *filename; struct ether_addr *match_mac; char **match_path; char **match_driver; char **match_type; char **match_name; Condition *match_host; Condition *match_virt; Condition *match_kernel; Condition *match_arch; char *description; struct ether_addr *mac; MACPolicy mac_policy; NamePolicy *name_policy; char *name; char *alias; size_t mtu; size_t speed; Duplex duplex; WakeOnLan wol; LIST_FIELDS(link_config, links); }; int link_config_ctx_new(link_config_ctx **ret); void link_config_ctx_free(link_config_ctx *ctx); int link_config_load(link_config_ctx *ctx); bool link_config_should_reload(link_config_ctx *ctx); int link_config_get(link_config_ctx *ctx, struct udev_device *device, struct link_config **ret); int link_config_apply(link_config_ctx *ctx, struct link_config *config, struct udev_device *device, const char **name); int link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret); const char *name_policy_to_string(NamePolicy p) _const_; NamePolicy name_policy_from_string(const char *p) _pure_; const char *mac_policy_to_string(MACPolicy p) _const_; MACPolicy mac_policy_from_string(const char *p) _pure_; /* gperf lookup function */ const struct ConfigPerfItem* link_config_gperf_lookup(const char *key, unsigned length); int config_parse_mac_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_name_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); systemd-229/src/udev/scsi_id/000077500000000000000000000000001265713322000162305ustar00rootroot00000000000000systemd-229/src/udev/scsi_id/.gitignore000066400000000000000000000000221265713322000202120ustar00rootroot00000000000000scsi_id_version.h systemd-229/src/udev/scsi_id/Makefile000077700000000000000000000000001265713322000215362../Makefileustar00rootroot00000000000000systemd-229/src/udev/scsi_id/README000066400000000000000000000002701265713322000171070ustar00rootroot00000000000000scsi_id - generate a SCSI unique identifier for a given SCSI device Please send questions, comments or patches to or . systemd-229/src/udev/scsi_id/scsi.h000066400000000000000000000051431265713322000173450ustar00rootroot00000000000000/* * scsi.h * * General scsi and linux scsi specific defines and structs. * * Copyright (C) IBM Corp. 2003 * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation version 2 of the License. */ #pragma once #include struct scsi_ioctl_command { unsigned int inlen; /* excluding scsi command length */ unsigned int outlen; unsigned char data[1]; /* on input, scsi command starts here then opt. data */ }; /* * Default 5 second timeout */ #define DEF_TIMEOUT 5000 #define SENSE_BUFF_LEN 32 /* * The request buffer size passed to the SCSI INQUIRY commands, use 254, * as this is a nice value for some devices, especially some of the usb * mass storage devices. */ #define SCSI_INQ_BUFF_LEN 254 /* * SCSI INQUIRY vendor and model (really product) lengths. */ #define VENDOR_LENGTH 8 #define MODEL_LENGTH 16 #define INQUIRY_CMD 0x12 #define INQUIRY_CMDLEN 6 /* * INQUIRY VPD page 0x83 identifier descriptor related values. Reference the * SCSI Primary Commands specification for details. */ /* * id type values of id descriptors. These are assumed to fit in 4 bits. */ #define SCSI_ID_VENDOR_SPECIFIC 0 #define SCSI_ID_T10_VENDOR 1 #define SCSI_ID_EUI_64 2 #define SCSI_ID_NAA 3 #define SCSI_ID_RELPORT 4 #define SCSI_ID_TGTGROUP 5 #define SCSI_ID_LUNGROUP 6 #define SCSI_ID_MD5 7 #define SCSI_ID_NAME 8 /* * Supported NAA values. These fit in 4 bits, so the "don't care" value * cannot conflict with real values. */ #define SCSI_ID_NAA_DONT_CARE 0xff #define SCSI_ID_NAA_IEEE_REG 0x05 #define SCSI_ID_NAA_IEEE_REG_EXTENDED 0x06 /* * Supported Code Set values. */ #define SCSI_ID_BINARY 1 #define SCSI_ID_ASCII 2 struct scsi_id_search_values { u_char id_type; u_char naa_type; u_char code_set; }; /* * Following are the "true" SCSI status codes. Linux has traditionally * used a 1 bit right and masked version of these. So now CHECK_CONDITION * and friends (in ) are deprecated. */ #define SCSI_CHECK_CONDITION 0x02 #define SCSI_CONDITION_MET 0x04 #define SCSI_BUSY 0x08 #define SCSI_IMMEDIATE 0x10 #define SCSI_IMMEDIATE_CONDITION_MET 0x14 #define SCSI_RESERVATION_CONFLICT 0x18 #define SCSI_COMMAND_TERMINATED 0x22 #define SCSI_TASK_SET_FULL 0x28 #define SCSI_ACA_ACTIVE 0x30 #define SCSI_TASK_ABORTED 0x40 systemd-229/src/udev/scsi_id/scsi_id.c000066400000000000000000000515661265713322000200260ustar00rootroot00000000000000/* * Copyright (C) IBM Corp. 2003 * Copyright (C) SUSE Linux Products GmbH, 2006 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include "libudev.h" #include "fd-util.h" #include "libudev-private.h" #include "scsi_id.h" #include "string-util.h" #include "udev-util.h" static const struct option options[] = { { "device", required_argument, NULL, 'd' }, { "config", required_argument, NULL, 'f' }, { "page", required_argument, NULL, 'p' }, { "blacklisted", no_argument, NULL, 'b' }, { "whitelisted", no_argument, NULL, 'g' }, { "replace-whitespace", no_argument, NULL, 'u' }, { "sg-version", required_argument, NULL, 's' }, { "verbose", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'V' }, /* don't advertise -V */ { "export", no_argument, NULL, 'x' }, { "help", no_argument, NULL, 'h' }, {} }; static bool all_good = false; static bool dev_specified = false; static char config_file[MAX_PATH_LEN] = "/etc/scsi_id.config"; static enum page_code default_page_code = PAGE_UNSPECIFIED; static int sg_version = 4; static bool reformat_serial = false; static bool export = false; static char vendor_str[64]; static char model_str[64]; static char vendor_enc_str[256]; static char model_enc_str[256]; static char revision_str[16]; static char type_str[16]; static void set_type(const char *from, char *to, size_t len) { int type_num; char *eptr; const char *type = "generic"; type_num = strtoul(from, &eptr, 0); if (eptr != from) { switch (type_num) { case 0: type = "disk"; break; case 1: type = "tape"; break; case 4: type = "optical"; break; case 5: type = "cd"; break; case 7: type = "optical"; break; case 0xe: type = "disk"; break; case 0xf: type = "optical"; break; default: break; } } strscpy(to, len, type); } /* * get_value: * * buf points to an '=' followed by a quoted string ("foo") or a string ending * with a space or ','. * * Return a pointer to the NUL terminated string, returns NULL if no * matches. */ static char *get_value(char **buffer) { static const char *quote_string = "\"\n"; static const char *comma_string = ",\n"; char *val; const char *end; if (**buffer == '"') { /* * skip leading quote, terminate when quote seen */ (*buffer)++; end = quote_string; } else { end = comma_string; } val = strsep(buffer, end); if (val && end == quote_string) /* * skip trailing quote */ (*buffer)++; while (isspace(**buffer)) (*buffer)++; return val; } static int argc_count(char *opts) { int i = 0; while (*opts != '\0') if (*opts++ == ' ') i++; return i; } /* * get_file_options: * * If vendor == NULL, find a line in the config file with only "OPTIONS="; * if vendor and model are set find the first OPTIONS line in the config * file that matches. Set argc and argv to match the OPTIONS string. * * vendor and model can end in '\n'. */ static int get_file_options(struct udev *udev, const char *vendor, const char *model, int *argc, char ***newargv) { char *buffer; _cleanup_fclose_ FILE *f; char *buf; char *str1; char *vendor_in, *model_in, *options_in; /* read in from file */ int lineno; int c; int retval = 0; f = fopen(config_file, "re"); if (f == NULL) { if (errno == ENOENT) return 1; else { log_error_errno(errno, "can't open %s: %m", config_file); return -1; } } /* * Allocate a buffer rather than put it on the stack so we can * keep it around to parse any options (any allocated newargv * points into this buffer for its strings). */ buffer = malloc(MAX_BUFFER_LEN); if (!buffer) return log_oom(); *newargv = NULL; lineno = 0; for (;;) { vendor_in = model_in = options_in = NULL; buf = fgets(buffer, MAX_BUFFER_LEN, f); if (buf == NULL) break; lineno++; if (buf[strlen(buffer) - 1] != '\n') { log_error("Config file line %d too long", lineno); break; } while (isspace(*buf)) buf++; /* blank or all whitespace line */ if (*buf == '\0') continue; /* comment line */ if (*buf == '#') continue; str1 = strsep(&buf, "="); if (str1 && strcaseeq(str1, "VENDOR")) { str1 = get_value(&buf); if (!str1) { retval = log_oom(); break; } vendor_in = str1; str1 = strsep(&buf, "="); if (str1 && strcaseeq(str1, "MODEL")) { str1 = get_value(&buf); if (!str1) { retval = log_oom(); break; } model_in = str1; str1 = strsep(&buf, "="); } } if (str1 && strcaseeq(str1, "OPTIONS")) { str1 = get_value(&buf); if (!str1) { retval = log_oom(); break; } options_in = str1; } /* * Only allow: [vendor=foo[,model=bar]]options=stuff */ if (!options_in || (!vendor_in && model_in)) { log_error("Error parsing config file line %d '%s'", lineno, buffer); retval = -1; break; } if (vendor == NULL) { if (vendor_in == NULL) break; } else if (vendor_in && strneq(vendor, vendor_in, strlen(vendor_in)) && (!model_in || (strneq(model, model_in, strlen(model_in))))) { /* * Matched vendor and optionally model. * * Note: a short vendor_in or model_in can * give a partial match (that is FOO * matches FOOBAR). */ break; } } if (retval == 0) { if (vendor_in != NULL || model_in != NULL || options_in != NULL) { /* * Something matched. Allocate newargv, and store * values found in options_in. */ strcpy(buffer, options_in); c = argc_count(buffer) + 2; *newargv = calloc(c, sizeof(**newargv)); if (!*newargv) retval = log_oom(); else { *argc = c; c = 0; /* * argv[0] at 0 is skipped by getopt, but * store the buffer address there for * later freeing */ (*newargv)[c] = buffer; for (c = 1; c < *argc; c++) (*newargv)[c] = strsep(&buffer, " \t"); } } else { /* No matches */ retval = 1; } } if (retval != 0) free(buffer); return retval; } static void help(void) { printf("Usage: %s [OPTION...] DEVICE\n\n" "SCSI device identification.\n\n" " -h --help Print this message\n" " --version Print version of the program\n\n" " -d --device= Device node for SG_IO commands\n" " -f --config= Location of config file\n" " -p --page=0x80|0x83|pre-spc3-83 SCSI page (0x80, 0x83, pre-spc3-83)\n" " -s --sg-version=3|4 Use SGv3 or SGv4\n" " -b --blacklisted Treat device as blacklisted\n" " -g --whitelisted Treat device as whitelisted\n" " -u --replace-whitespace Replace all whitespace by underscores\n" " -v --verbose Verbose logging\n" " -x --export Print values as environment keys\n" , program_invocation_short_name); } static int set_options(struct udev *udev, int argc, char **argv, char *maj_min_dev) { int option; /* * optind is a global extern used by getopt. Since we can call * set_options twice (once for command line, and once for config * file) we have to reset this back to 1. */ optind = 1; while ((option = getopt_long(argc, argv, "d:f:gp:uvVxh", options, NULL)) >= 0) switch (option) { case 'b': all_good = false; break; case 'd': dev_specified = true; strscpy(maj_min_dev, MAX_PATH_LEN, optarg); break; case 'f': strscpy(config_file, MAX_PATH_LEN, optarg); break; case 'g': all_good = true; break; case 'h': help(); exit(0); case 'p': if (streq(optarg, "0x80")) default_page_code = PAGE_80; else if (streq(optarg, "0x83")) default_page_code = PAGE_83; else if (streq(optarg, "pre-spc3-83")) default_page_code = PAGE_83_PRE_SPC3; else { log_error("Unknown page code '%s'", optarg); return -1; } break; case 's': sg_version = atoi(optarg); if (sg_version < 3 || sg_version > 4) { log_error("Unknown SG version '%s'", optarg); return -1; } break; case 'u': reformat_serial = true; break; case 'v': log_set_target(LOG_TARGET_CONSOLE); log_set_max_level(LOG_DEBUG); log_open(); break; case 'V': printf("%s\n", VERSION); exit(0); case 'x': export = true; break; case '?': return -1; default: assert_not_reached("Unknown option"); } if (optind < argc && !dev_specified) { dev_specified = true; strscpy(maj_min_dev, MAX_PATH_LEN, argv[optind]); } return 0; } static int per_dev_options(struct udev *udev, struct scsi_id_device *dev_scsi, int *good_bad, int *page_code) { int retval; int newargc; char **newargv = NULL; int option; *good_bad = all_good; *page_code = default_page_code; retval = get_file_options(udev, vendor_str, model_str, &newargc, &newargv); optind = 1; /* reset this global extern */ while (retval == 0) { option = getopt_long(newargc, newargv, "bgp:", options, NULL); if (option == -1) break; switch (option) { case 'b': *good_bad = 0; break; case 'g': *good_bad = 1; break; case 'p': if (streq(optarg, "0x80")) { *page_code = PAGE_80; } else if (streq(optarg, "0x83")) { *page_code = PAGE_83; } else if (streq(optarg, "pre-spc3-83")) { *page_code = PAGE_83_PRE_SPC3; } else { log_error("Unknown page code '%s'", optarg); retval = -1; } break; default: log_error("Unknown or bad option '%c' (0x%x)", option, option); retval = -1; break; } } if (newargv) { free(newargv[0]); free(newargv); } return retval; } static int set_inq_values(struct udev *udev, struct scsi_id_device *dev_scsi, const char *path) { int retval; dev_scsi->use_sg = sg_version; retval = scsi_std_inquiry(udev, dev_scsi, path); if (retval) return retval; udev_util_encode_string(dev_scsi->vendor, vendor_enc_str, sizeof(vendor_enc_str)); udev_util_encode_string(dev_scsi->model, model_enc_str, sizeof(model_enc_str)); util_replace_whitespace(dev_scsi->vendor, vendor_str, sizeof(vendor_str)); util_replace_chars(vendor_str, NULL); util_replace_whitespace(dev_scsi->model, model_str, sizeof(model_str)); util_replace_chars(model_str, NULL); set_type(dev_scsi->type, type_str, sizeof(type_str)); util_replace_whitespace(dev_scsi->revision, revision_str, sizeof(revision_str)); util_replace_chars(revision_str, NULL); return 0; } /* * scsi_id: try to get an id, if one is found, printf it to stdout. * returns a value passed to exit() - 0 if printed an id, else 1. */ static int scsi_id(struct udev *udev, char *maj_min_dev) { struct scsi_id_device dev_scsi = {}; int good_dev; int page_code; int retval = 0; if (set_inq_values(udev, &dev_scsi, maj_min_dev) < 0) { retval = 1; goto out; } /* get per device (vendor + model) options from the config file */ per_dev_options(udev, &dev_scsi, &good_dev, &page_code); if (!good_dev) { retval = 1; goto out; } /* read serial number from mode pages (no values for optical drives) */ scsi_get_serial(udev, &dev_scsi, maj_min_dev, page_code, MAX_SERIAL_LEN); if (export) { char serial_str[MAX_SERIAL_LEN]; printf("ID_SCSI=1\n"); printf("ID_VENDOR=%s\n", vendor_str); printf("ID_VENDOR_ENC=%s\n", vendor_enc_str); printf("ID_MODEL=%s\n", model_str); printf("ID_MODEL_ENC=%s\n", model_enc_str); printf("ID_REVISION=%s\n", revision_str); printf("ID_TYPE=%s\n", type_str); if (dev_scsi.serial[0] != '\0') { util_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str)); util_replace_chars(serial_str, NULL); printf("ID_SERIAL=%s\n", serial_str); util_replace_whitespace(dev_scsi.serial_short, serial_str, sizeof(serial_str)); util_replace_chars(serial_str, NULL); printf("ID_SERIAL_SHORT=%s\n", serial_str); } if (dev_scsi.wwn[0] != '\0') { printf("ID_WWN=0x%s\n", dev_scsi.wwn); if (dev_scsi.wwn_vendor_extension[0] != '\0') { printf("ID_WWN_VENDOR_EXTENSION=0x%s\n", dev_scsi.wwn_vendor_extension); printf("ID_WWN_WITH_EXTENSION=0x%s%s\n", dev_scsi.wwn, dev_scsi.wwn_vendor_extension); } else printf("ID_WWN_WITH_EXTENSION=0x%s\n", dev_scsi.wwn); } if (dev_scsi.tgpt_group[0] != '\0') printf("ID_TARGET_PORT=%s\n", dev_scsi.tgpt_group); if (dev_scsi.unit_serial_number[0] != '\0') printf("ID_SCSI_SERIAL=%s\n", dev_scsi.unit_serial_number); goto out; } if (dev_scsi.serial[0] == '\0') { retval = 1; goto out; } if (reformat_serial) { char serial_str[MAX_SERIAL_LEN]; util_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str)); util_replace_chars(serial_str, NULL); printf("%s\n", serial_str); goto out; } printf("%s\n", dev_scsi.serial); out: return retval; } int main(int argc, char **argv) { _cleanup_udev_unref_ struct udev *udev; int retval = 0; char maj_min_dev[MAX_PATH_LEN]; int newargc; char **newargv = NULL; log_parse_environment(); log_open(); udev = udev_new(); if (udev == NULL) goto exit; /* * Get config file options. */ retval = get_file_options(udev, NULL, NULL, &newargc, &newargv); if (retval < 0) { retval = 1; goto exit; } if (retval == 0) { assert(newargv); if (set_options(udev, newargc, newargv, maj_min_dev) < 0) { retval = 2; goto exit; } } /* * Get command line options (overriding any config file settings). */ if (set_options(udev, argc, argv, maj_min_dev) < 0) exit(1); if (!dev_specified) { log_error("No device specified."); retval = 1; goto exit; } retval = scsi_id(udev, maj_min_dev); exit: if (newargv) { free(newargv[0]); free(newargv); } log_close(); return retval; } systemd-229/src/udev/scsi_id/scsi_id.h000066400000000000000000000043331265713322000200210ustar00rootroot00000000000000/* * Copyright (C) IBM Corp. 2003 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #pragma once #define MAX_PATH_LEN 512 /* * MAX_ATTR_LEN: maximum length of the result of reading a sysfs * attribute. */ #define MAX_ATTR_LEN 256 /* * MAX_SERIAL_LEN: the maximum length of the serial number, including * added prefixes such as vendor and product (model) strings. */ #define MAX_SERIAL_LEN 256 /* * MAX_BUFFER_LEN: maximum buffer size and line length used while reading * the config file. */ #define MAX_BUFFER_LEN 256 struct scsi_id_device { char vendor[9]; char model[17]; char revision[5]; char type[33]; char kernel[64]; char serial[MAX_SERIAL_LEN]; char serial_short[MAX_SERIAL_LEN]; int use_sg; /* Always from page 0x80 e.g. 'B3G1P8500RWT' - may not be unique */ char unit_serial_number[MAX_SERIAL_LEN]; /* NULs if not set - otherwise hex encoding using lower-case e.g. '50014ee0016eb572' */ char wwn[17]; /* NULs if not set - otherwise hex encoding using lower-case e.g. '0xe00000d80000' */ char wwn_vendor_extension[17]; /* NULs if not set - otherwise decimal number */ char tgpt_group[8]; }; int scsi_std_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, const char *devname); int scsi_get_serial(struct udev *udev, struct scsi_id_device *dev_scsi, const char *devname, int page_code, int len); /* * Page code values. */ enum page_code { PAGE_83_PRE_SPC3 = -0x83, PAGE_UNSPECIFIED = 0x00, PAGE_80 = 0x80, PAGE_83 = 0x83, }; systemd-229/src/udev/scsi_id/scsi_serial.c000066400000000000000000001106271265713322000207030ustar00rootroot00000000000000/* * Copyright (C) IBM Corp. 2003 * * Author: Patrick Mansfield * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libudev.h" #include "libudev-private.h" #include "random-util.h" #include "scsi.h" #include "scsi_id.h" #include "string-util.h" /* * A priority based list of id, naa, and binary/ascii for the identifier * descriptor in VPD page 0x83. * * Brute force search for a match starting with the first value in the * following id_search_list. This is not a performance issue, since there * is normally one or some small number of descriptors. */ static const struct scsi_id_search_values id_search_list[] = { { SCSI_ID_TGTGROUP, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_BINARY }, { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_ASCII }, { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG, SCSI_ID_BINARY }, { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG, SCSI_ID_ASCII }, /* * Devices already exist using NAA values that are now marked * reserved. These should not conflict with other values, or it is * a bug in the device. As long as we find the IEEE extended one * first, we really don't care what other ones are used. Using * don't care here means that a device that returns multiple * non-IEEE descriptors in a random order will get different * names. */ { SCSI_ID_NAA, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, { SCSI_ID_NAA, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII }, { SCSI_ID_EUI_64, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, { SCSI_ID_EUI_64, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII }, { SCSI_ID_T10_VENDOR, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, { SCSI_ID_T10_VENDOR, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII }, { SCSI_ID_VENDOR_SPECIFIC, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, { SCSI_ID_VENDOR_SPECIFIC, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII }, }; static const char hex_str[]="0123456789abcdef"; /* * Values returned in the result/status, only the ones used by the code * are used here. */ #define DID_NO_CONNECT 0x01 /* Unable to connect before timeout */ #define DID_BUS_BUSY 0x02 /* Bus remain busy until timeout */ #define DID_TIME_OUT 0x03 /* Timed out for some other reason */ #define DRIVER_TIMEOUT 0x06 #define DRIVER_SENSE 0x08 /* Sense_buffer has been set */ /* The following "category" function returns one of the following */ #define SG_ERR_CAT_CLEAN 0 /* No errors or other information */ #define SG_ERR_CAT_MEDIA_CHANGED 1 /* interpreted from sense buffer */ #define SG_ERR_CAT_RESET 2 /* interpreted from sense buffer */ #define SG_ERR_CAT_TIMEOUT 3 #define SG_ERR_CAT_RECOVERED 4 /* Successful command after recovered err */ #define SG_ERR_CAT_NOTSUPPORTED 5 /* Illegal / unsupported command */ #define SG_ERR_CAT_SENSE 98 /* Something else in the sense buffer */ #define SG_ERR_CAT_OTHER 99 /* Some other error/warning */ static int do_scsi_page80_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, int fd, char *serial, char *serial_short, int max_len); static int sg_err_category_new(struct udev *udev, int scsi_status, int msg_status, int host_status, int driver_status, const unsigned char *sense_buffer, int sb_len) { scsi_status &= 0x7e; /* * XXX change to return only two values - failed or OK. */ if (!scsi_status && !host_status && !driver_status) return SG_ERR_CAT_CLEAN; if ((scsi_status == SCSI_CHECK_CONDITION) || (scsi_status == SCSI_COMMAND_TERMINATED) || ((driver_status & 0xf) == DRIVER_SENSE)) { if (sense_buffer && (sb_len > 2)) { int sense_key; unsigned char asc; if (sense_buffer[0] & 0x2) { sense_key = sense_buffer[1] & 0xf; asc = sense_buffer[2]; } else { sense_key = sense_buffer[2] & 0xf; asc = (sb_len > 12) ? sense_buffer[12] : 0; } if (sense_key == RECOVERED_ERROR) return SG_ERR_CAT_RECOVERED; else if (sense_key == UNIT_ATTENTION) { if (0x28 == asc) return SG_ERR_CAT_MEDIA_CHANGED; if (0x29 == asc) return SG_ERR_CAT_RESET; } else if (sense_key == ILLEGAL_REQUEST) return SG_ERR_CAT_NOTSUPPORTED; } return SG_ERR_CAT_SENSE; } if (host_status) { if ((host_status == DID_NO_CONNECT) || (host_status == DID_BUS_BUSY) || (host_status == DID_TIME_OUT)) return SG_ERR_CAT_TIMEOUT; } if (driver_status) { if (driver_status == DRIVER_TIMEOUT) return SG_ERR_CAT_TIMEOUT; } return SG_ERR_CAT_OTHER; } static int sg_err_category3(struct udev *udev, struct sg_io_hdr *hp) { return sg_err_category_new(udev, hp->status, hp->msg_status, hp->host_status, hp->driver_status, hp->sbp, hp->sb_len_wr); } static int sg_err_category4(struct udev *udev, struct sg_io_v4 *hp) { return sg_err_category_new(udev, hp->device_status, 0, hp->transport_status, hp->driver_status, (unsigned char *)(uintptr_t)hp->response, hp->response_len); } static int scsi_dump_sense(struct udev *udev, struct scsi_id_device *dev_scsi, unsigned char *sense_buffer, int sb_len) { int s; int code; int sense_class; int sense_key; int asc, ascq; #ifdef DUMP_SENSE char out_buffer[256]; int i, j; #endif /* * Figure out and print the sense key, asc and ascq. * * If you want to suppress these for a particular drive model, add * a black list entry in the scsi_id config file. * * XXX We probably need to: lookup the sense/asc/ascq in a retry * table, and if found return 1 (after dumping the sense, asc, and * ascq). So, if/when we get something like a power on/reset, * we'll retry the command. */ if (sb_len < 1) { log_debug("%s: sense buffer empty", dev_scsi->kernel); return -1; } sense_class = (sense_buffer[0] >> 4) & 0x07; code = sense_buffer[0] & 0xf; if (sense_class == 7) { /* * extended sense data. */ s = sense_buffer[7] + 8; if (sb_len < s) { log_debug("%s: sense buffer too small %d bytes, %d bytes too short", dev_scsi->kernel, sb_len, s - sb_len); return -1; } if ((code == 0x0) || (code == 0x1)) { sense_key = sense_buffer[2] & 0xf; if (s < 14) { /* * Possible? */ log_debug("%s: sense result too" " small %d bytes", dev_scsi->kernel, s); return -1; } asc = sense_buffer[12]; ascq = sense_buffer[13]; } else if ((code == 0x2) || (code == 0x3)) { sense_key = sense_buffer[1] & 0xf; asc = sense_buffer[2]; ascq = sense_buffer[3]; } else { log_debug("%s: invalid sense code 0x%x", dev_scsi->kernel, code); return -1; } log_debug("%s: sense key 0x%x ASC 0x%x ASCQ 0x%x", dev_scsi->kernel, sense_key, asc, ascq); } else { if (sb_len < 4) { log_debug("%s: sense buffer too small %d bytes, %d bytes too short", dev_scsi->kernel, sb_len, 4 - sb_len); return -1; } if (sense_buffer[0] < 15) log_debug("%s: old sense key: 0x%x", dev_scsi->kernel, sense_buffer[0] & 0x0f); else log_debug("%s: sense = %2x %2x", dev_scsi->kernel, sense_buffer[0], sense_buffer[2]); log_debug("%s: non-extended sense class %d code 0x%0x", dev_scsi->kernel, sense_class, code); } #ifdef DUMP_SENSE for (i = 0, j = 0; (i < s) && (j < 254); i++) { out_buffer[j++] = hex_str[(sense_buffer[i] & 0xf0) >> 4]; out_buffer[j++] = hex_str[sense_buffer[i] & 0x0f]; out_buffer[j++] = ' '; } out_buffer[j] = '\0'; log_debug("%s: sense dump:", dev_scsi->kernel); log_debug("%s: %s", dev_scsi->kernel, out_buffer); #endif return -1; } static int scsi_dump(struct udev *udev, struct scsi_id_device *dev_scsi, struct sg_io_hdr *io) { if (!io->status && !io->host_status && !io->msg_status && !io->driver_status) { /* * Impossible, should not be called. */ log_debug("%s: called with no error", __FUNCTION__); return -1; } log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x 0x%x", dev_scsi->kernel, io->driver_status, io->host_status, io->msg_status, io->status); if (io->status == SCSI_CHECK_CONDITION) return scsi_dump_sense(udev, dev_scsi, io->sbp, io->sb_len_wr); else return -1; } static int scsi_dump_v4(struct udev *udev, struct scsi_id_device *dev_scsi, struct sg_io_v4 *io) { if (!io->device_status && !io->transport_status && !io->driver_status) { /* * Impossible, should not be called. */ log_debug("%s: called with no error", __FUNCTION__); return -1; } log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x", dev_scsi->kernel, io->driver_status, io->transport_status, io->device_status); if (io->device_status == SCSI_CHECK_CONDITION) return scsi_dump_sense(udev, dev_scsi, (unsigned char *)(uintptr_t)io->response, io->response_len); else return -1; } static int scsi_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, int fd, unsigned char evpd, unsigned char page, unsigned char *buf, unsigned int buflen) { unsigned char inq_cmd[INQUIRY_CMDLEN] = { INQUIRY_CMD, evpd, page, 0, buflen, 0 }; unsigned char sense[SENSE_BUFF_LEN]; void *io_buf; struct sg_io_v4 io_v4; struct sg_io_hdr io_hdr; int retry = 3; /* rather random */ int retval; if (buflen > SCSI_INQ_BUFF_LEN) { log_debug("buflen %d too long", buflen); return -1; } resend: if (dev_scsi->use_sg == 4) { memzero(&io_v4, sizeof(struct sg_io_v4)); io_v4.guard = 'Q'; io_v4.protocol = BSG_PROTOCOL_SCSI; io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD; io_v4.request_len = sizeof(inq_cmd); io_v4.request = (uintptr_t)inq_cmd; io_v4.max_response_len = sizeof(sense); io_v4.response = (uintptr_t)sense; io_v4.din_xfer_len = buflen; io_v4.din_xferp = (uintptr_t)buf; io_buf = (void *)&io_v4; } else { memzero(&io_hdr, sizeof(struct sg_io_hdr)); io_hdr.interface_id = 'S'; io_hdr.cmd_len = sizeof(inq_cmd); io_hdr.mx_sb_len = sizeof(sense); io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; io_hdr.dxfer_len = buflen; io_hdr.dxferp = buf; io_hdr.cmdp = inq_cmd; io_hdr.sbp = sense; io_hdr.timeout = DEF_TIMEOUT; io_buf = (void *)&io_hdr; } retval = ioctl(fd, SG_IO, io_buf); if (retval < 0) { if ((errno == EINVAL || errno == ENOSYS) && dev_scsi->use_sg == 4) { dev_scsi->use_sg = 3; goto resend; } log_debug_errno(errno, "%s: ioctl failed: %m", dev_scsi->kernel); goto error; } if (dev_scsi->use_sg == 4) retval = sg_err_category4(udev, io_buf); else retval = sg_err_category3(udev, io_buf); switch (retval) { case SG_ERR_CAT_NOTSUPPORTED: buf[1] = 0; /* Fallthrough */ case SG_ERR_CAT_CLEAN: case SG_ERR_CAT_RECOVERED: retval = 0; break; default: if (dev_scsi->use_sg == 4) retval = scsi_dump_v4(udev, dev_scsi, io_buf); else retval = scsi_dump(udev, dev_scsi, io_buf); } if (!retval) { retval = buflen; } else if (retval > 0) { if (--retry > 0) goto resend; retval = -1; } error: if (retval < 0) log_debug("%s: Unable to get INQUIRY vpd %d page 0x%x.", dev_scsi->kernel, evpd, page); return retval; } /* Get list of supported EVPD pages */ static int do_scsi_page0_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, int fd, unsigned char *buffer, unsigned int len) { int retval; memzero(buffer, len); retval = scsi_inquiry(udev, dev_scsi, fd, 1, 0x0, buffer, len); if (retval < 0) return 1; if (buffer[1] != 0) { log_debug("%s: page 0 not available.", dev_scsi->kernel); return 1; } if (buffer[3] > len) { log_debug("%s: page 0 buffer too long %d", dev_scsi->kernel, buffer[3]); return 1; } /* * Following check is based on code once included in the 2.5.x * kernel. * * Some ill behaved devices return the standard inquiry here * rather than the evpd data, snoop the data to verify. */ if (buffer[3] > MODEL_LENGTH) { /* * If the vendor id appears in the page assume the page is * invalid. */ if (strneq((char *)&buffer[VENDOR_LENGTH], dev_scsi->vendor, VENDOR_LENGTH)) { log_debug("%s: invalid page0 data", dev_scsi->kernel); return 1; } } return 0; } /* * The caller checks that serial is long enough to include the vendor + * model. */ static int prepend_vendor_model(struct udev *udev, struct scsi_id_device *dev_scsi, char *serial) { int ind; strncpy(serial, dev_scsi->vendor, VENDOR_LENGTH); strncat(serial, dev_scsi->model, MODEL_LENGTH); ind = strlen(serial); /* * This is not a complete check, since we are using strncat/cpy * above, ind will never be too large. */ if (ind != (VENDOR_LENGTH + MODEL_LENGTH)) { log_debug("%s: expected length %d, got length %d", dev_scsi->kernel, (VENDOR_LENGTH + MODEL_LENGTH), ind); return -1; } return ind; } /* * check_fill_0x83_id - check the page 0x83 id, if OK allocate and fill * serial number. */ static int check_fill_0x83_id(struct udev *udev, struct scsi_id_device *dev_scsi, unsigned char *page_83, const struct scsi_id_search_values *id_search, char *serial, char *serial_short, int max_len, char *wwn, char *wwn_vendor_extension, char *tgpt_group) { int i, j, s, len; /* * ASSOCIATION must be with the device (value 0) * or with the target port for SCSI_ID_TGTPORT */ if ((page_83[1] & 0x30) == 0x10) { if (id_search->id_type != SCSI_ID_TGTGROUP) return 1; } else if ((page_83[1] & 0x30) != 0) return 1; if ((page_83[1] & 0x0f) != id_search->id_type) return 1; /* * Possibly check NAA sub-type. */ if ((id_search->naa_type != SCSI_ID_NAA_DONT_CARE) && (id_search->naa_type != (page_83[4] & 0xf0) >> 4)) return 1; /* * Check for matching code set - ASCII or BINARY. */ if ((page_83[0] & 0x0f) != id_search->code_set) return 1; /* * page_83[3]: identifier length */ len = page_83[3]; if ((page_83[0] & 0x0f) != SCSI_ID_ASCII) /* * If not ASCII, use two bytes for each binary value. */ len *= 2; /* * Add one byte for the NUL termination, and one for the id_type. */ len += 2; if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) len += VENDOR_LENGTH + MODEL_LENGTH; if (max_len < len) { log_debug("%s: length %d too short - need %d", dev_scsi->kernel, max_len, len); return 1; } if (id_search->id_type == SCSI_ID_TGTGROUP && tgpt_group != NULL) { unsigned int group; group = ((unsigned int)page_83[6] << 8) | page_83[7]; sprintf(tgpt_group,"%x", group); return 1; } serial[0] = hex_str[id_search->id_type]; /* * For SCSI_ID_VENDOR_SPECIFIC prepend the vendor and model before * the id since it is not unique across all vendors and models, * this differs from SCSI_ID_T10_VENDOR, where the vendor is * included in the identifier. */ if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) if (prepend_vendor_model(udev, dev_scsi, &serial[1]) < 0) return 1; i = 4; /* offset to the start of the identifier */ s = j = strlen(serial); if ((page_83[0] & 0x0f) == SCSI_ID_ASCII) { /* * ASCII descriptor. */ while (i < (4 + page_83[3])) serial[j++] = page_83[i++]; } else { /* * Binary descriptor, convert to ASCII, using two bytes of * ASCII for each byte in the page_83. */ while (i < (4 + page_83[3])) { serial[j++] = hex_str[(page_83[i] & 0xf0) >> 4]; serial[j++] = hex_str[page_83[i] & 0x0f]; i++; } } strcpy(serial_short, &serial[s]); if (id_search->id_type == SCSI_ID_NAA && wwn != NULL) { strncpy(wwn, &serial[s], 16); if (wwn_vendor_extension != NULL) strncpy(wwn_vendor_extension, &serial[s + 16], 16); } return 0; } /* Extract the raw binary from VPD 0x83 pre-SPC devices */ static int check_fill_0x83_prespc3(struct udev *udev, struct scsi_id_device *dev_scsi, unsigned char *page_83, const struct scsi_id_search_values *id_search, char *serial, char *serial_short, int max_len) { int i, j; serial[0] = hex_str[id_search->id_type]; /* serial has been memset to zero before */ j = strlen(serial); /* j = 1; */ for (i = 0; (i < page_83[3]) && (j < max_len-3); ++i) { serial[j++] = hex_str[(page_83[4+i] & 0xf0) >> 4]; serial[j++] = hex_str[ page_83[4+i] & 0x0f]; } serial[max_len-1] = 0; strncpy(serial_short, serial, max_len-1); return 0; } /* Get device identification VPD page */ static int do_scsi_page83_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, int fd, char *serial, char *serial_short, int len, char *unit_serial_number, char *wwn, char *wwn_vendor_extension, char *tgpt_group) { int retval; unsigned int id_ind, j; unsigned char page_83[SCSI_INQ_BUFF_LEN]; /* also pick up the page 80 serial number */ do_scsi_page80_inquiry(udev, dev_scsi, fd, NULL, unit_serial_number, MAX_SERIAL_LEN); memzero(page_83, SCSI_INQ_BUFF_LEN); retval = scsi_inquiry(udev, dev_scsi, fd, 1, PAGE_83, page_83, SCSI_INQ_BUFF_LEN); if (retval < 0) return 1; if (page_83[1] != PAGE_83) { log_debug("%s: Invalid page 0x83", dev_scsi->kernel); return 1; } /* * XXX Some devices (IBM 3542) return all spaces for an identifier if * the LUN is not actually configured. This leads to identifiers of * the form: "1 ". */ /* * Model 4, 5, and (some) model 6 EMC Symmetrix devices return * a page 83 reply according to SCSI-2 format instead of SPC-2/3. * * The SCSI-2 page 83 format returns an IEEE WWN in binary * encoded hexi-decimal in the 16 bytes following the initial * 4-byte page 83 reply header. * * Both the SPC-2 and SPC-3 formats return an IEEE WWN as part * of an Identification descriptor. The 3rd byte of the first * Identification descriptor is a reserved (BSZ) byte field. * * Reference the 7th byte of the page 83 reply to determine * whether the reply is compliant with SCSI-2 or SPC-2/3 * specifications. A zero value in the 7th byte indicates * an SPC-2/3 conformant reply, (i.e., the reserved field of the * first Identification descriptor). This byte will be non-zero * for a SCSI-2 conformant page 83 reply from these EMC * Symmetrix models since the 7th byte of the reply corresponds * to the 4th and 5th nibbles of the 6-byte OUI for EMC, that is, * 0x006048. */ if (page_83[6] != 0) return check_fill_0x83_prespc3(udev, dev_scsi, page_83, id_search_list, serial, serial_short, len); /* * Search for a match in the prioritized id_search_list - since WWN ids * come first we can pick up the WWN in check_fill_0x83_id(). */ for (id_ind = 0; id_ind < sizeof(id_search_list)/sizeof(id_search_list[0]); id_ind++) { /* * Examine each descriptor returned. There is normally only * one or a small number of descriptors. */ for (j = 4; j <= (unsigned int)page_83[3] + 3; j += page_83[j + 3] + 4) { retval = check_fill_0x83_id(udev, dev_scsi, &page_83[j], &id_search_list[id_ind], serial, serial_short, len, wwn, wwn_vendor_extension, tgpt_group); if (!retval) return retval; else if (retval < 0) return retval; } } return 1; } /* * Get device identification VPD page for older SCSI-2 device which is not * compliant with either SPC-2 or SPC-3 format. * * Return the hard coded error code value 2 if the page 83 reply is not * conformant to the SCSI-2 format. */ static int do_scsi_page83_prespc3_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, int fd, char *serial, char *serial_short, int len) { int retval; int i, j; unsigned char page_83[SCSI_INQ_BUFF_LEN]; memzero(page_83, SCSI_INQ_BUFF_LEN); retval = scsi_inquiry(udev, dev_scsi, fd, 1, PAGE_83, page_83, SCSI_INQ_BUFF_LEN); if (retval < 0) return 1; if (page_83[1] != PAGE_83) { log_debug("%s: Invalid page 0x83", dev_scsi->kernel); return 1; } /* * Model 4, 5, and (some) model 6 EMC Symmetrix devices return * a page 83 reply according to SCSI-2 format instead of SPC-2/3. * * The SCSI-2 page 83 format returns an IEEE WWN in binary * encoded hexi-decimal in the 16 bytes following the initial * 4-byte page 83 reply header. * * Both the SPC-2 and SPC-3 formats return an IEEE WWN as part * of an Identification descriptor. The 3rd byte of the first * Identification descriptor is a reserved (BSZ) byte field. * * Reference the 7th byte of the page 83 reply to determine * whether the reply is compliant with SCSI-2 or SPC-2/3 * specifications. A zero value in the 7th byte indicates * an SPC-2/3 conformant reply, (i.e., the reserved field of the * first Identification descriptor). This byte will be non-zero * for a SCSI-2 conformant page 83 reply from these EMC * Symmetrix models since the 7th byte of the reply corresponds * to the 4th and 5th nibbles of the 6-byte OUI for EMC, that is, * 0x006048. */ if (page_83[6] == 0) return 2; serial[0] = hex_str[id_search_list[0].id_type]; /* * The first four bytes contain data, not a descriptor. */ i = 4; j = strlen(serial); /* * Binary descriptor, convert to ASCII, * using two bytes of ASCII for each byte * in the page_83. */ while (i < (page_83[3]+4)) { serial[j++] = hex_str[(page_83[i] & 0xf0) >> 4]; serial[j++] = hex_str[page_83[i] & 0x0f]; i++; } return 0; } /* Get unit serial number VPD page */ static int do_scsi_page80_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, int fd, char *serial, char *serial_short, int max_len) { int retval; int ser_ind; int i; int len; unsigned char buf[SCSI_INQ_BUFF_LEN]; memzero(buf, SCSI_INQ_BUFF_LEN); retval = scsi_inquiry(udev, dev_scsi, fd, 1, PAGE_80, buf, SCSI_INQ_BUFF_LEN); if (retval < 0) return retval; if (buf[1] != PAGE_80) { log_debug("%s: Invalid page 0x80", dev_scsi->kernel); return 1; } len = 1 + VENDOR_LENGTH + MODEL_LENGTH + buf[3]; if (max_len < len) { log_debug("%s: length %d too short - need %d", dev_scsi->kernel, max_len, len); return 1; } /* * Prepend 'S' to avoid unlikely collision with page 0x83 vendor * specific type where we prepend '0' + vendor + model. */ len = buf[3]; if (serial != NULL) { serial[0] = 'S'; ser_ind = prepend_vendor_model(udev, dev_scsi, &serial[1]); if (ser_ind < 0) return 1; ser_ind++; /* for the leading 'S' */ for (i = 4; i < len + 4; i++, ser_ind++) serial[ser_ind] = buf[i]; } if (serial_short != NULL) { memcpy(serial_short, &buf[4], len); serial_short[len] = '\0'; } return 0; } int scsi_std_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, const char *devname) { int fd; unsigned char buf[SCSI_INQ_BUFF_LEN]; struct stat statbuf; int err = 0; fd = open(devname, O_RDONLY | O_NONBLOCK | O_CLOEXEC); if (fd < 0) { log_debug_errno(errno, "scsi_id: cannot open %s: %m", devname); return 1; } if (fstat(fd, &statbuf) < 0) { log_debug_errno(errno, "scsi_id: cannot stat %s: %m", devname); err = 2; goto out; } sprintf(dev_scsi->kernel,"%d:%d", major(statbuf.st_rdev), minor(statbuf.st_rdev)); memzero(buf, SCSI_INQ_BUFF_LEN); err = scsi_inquiry(udev, dev_scsi, fd, 0, 0, buf, SCSI_INQ_BUFF_LEN); if (err < 0) goto out; err = 0; memcpy(dev_scsi->vendor, buf + 8, 8); dev_scsi->vendor[8] = '\0'; memcpy(dev_scsi->model, buf + 16, 16); dev_scsi->model[16] = '\0'; memcpy(dev_scsi->revision, buf + 32, 4); dev_scsi->revision[4] = '\0'; sprintf(dev_scsi->type,"%x", buf[0] & 0x1f); out: close(fd); return err; } int scsi_get_serial(struct udev *udev, struct scsi_id_device *dev_scsi, const char *devname, int page_code, int len) { unsigned char page0[SCSI_INQ_BUFF_LEN]; int fd = -1; int cnt; int ind; int retval; memzero(dev_scsi->serial, len); initialize_srand(); for (cnt = 20; cnt > 0; cnt--) { struct timespec duration; fd = open(devname, O_RDONLY | O_NONBLOCK | O_CLOEXEC); if (fd >= 0 || errno != EBUSY) break; duration.tv_sec = 0; duration.tv_nsec = (200 * 1000 * 1000) + (rand() % 100 * 1000 * 1000); nanosleep(&duration, NULL); } if (fd < 0) return 1; if (page_code == PAGE_80) { if (do_scsi_page80_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len)) { retval = 1; goto completed; } else { retval = 0; goto completed; } } else if (page_code == PAGE_83) { if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { retval = 1; goto completed; } else { retval = 0; goto completed; } } else if (page_code == PAGE_83_PRE_SPC3) { retval = do_scsi_page83_prespc3_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len); if (retval) { /* * Fallback to servicing a SPC-2/3 compliant page 83 * inquiry if the page 83 reply format does not * conform to pre-SPC3 expectations. */ if (retval == 2) { if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { retval = 1; goto completed; } else { retval = 0; goto completed; } } else { retval = 1; goto completed; } } else { retval = 0; goto completed; } } else if (page_code != 0x00) { log_debug("%s: unsupported page code 0x%d", dev_scsi->kernel, page_code); retval = 1; goto completed; } /* * Get page 0, the page of the pages. By default, try from best to * worst of supported pages: 0x83 then 0x80. */ if (do_scsi_page0_inquiry(udev, dev_scsi, fd, page0, SCSI_INQ_BUFF_LEN)) { /* * Don't try anything else. Black list if a specific page * should be used for this vendor+model, or maybe have an * optional fall-back to page 0x80 or page 0x83. */ retval = 1; goto completed; } for (ind = 4; ind <= page0[3] + 3; ind++) if (page0[ind] == PAGE_83) if (!do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { /* * Success */ retval = 0; goto completed; } for (ind = 4; ind <= page0[3] + 3; ind++) if (page0[ind] == PAGE_80) if (!do_scsi_page80_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len)) { /* * Success */ retval = 0; goto completed; } retval = 1; completed: close(fd); return retval; } systemd-229/src/udev/udev-builtin-blkid.c000066400000000000000000000271141265713322000204560ustar00rootroot00000000000000/* * probe disks for filesystems and partitions * * Copyright (C) 2011 Kay Sievers * Copyright (C) 2011 Karel Zak * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include "sd-id128.h" #include "alloc-util.h" #include "efivars.h" #include "fd-util.h" #include "gpt.h" #include "string-util.h" #include "udev.h" static void print_property(struct udev_device *dev, bool test, const char *name, const char *value) { char s[256]; s[0] = '\0'; if (streq(name, "TYPE")) { udev_builtin_add_property(dev, test, "ID_FS_TYPE", value); } else if (streq(name, "USAGE")) { udev_builtin_add_property(dev, test, "ID_FS_USAGE", value); } else if (streq(name, "VERSION")) { udev_builtin_add_property(dev, test, "ID_FS_VERSION", value); } else if (streq(name, "UUID")) { blkid_safe_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_UUID", s); blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_UUID_ENC", s); } else if (streq(name, "UUID_SUB")) { blkid_safe_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB", s); blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB_ENC", s); } else if (streq(name, "LABEL")) { blkid_safe_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_LABEL", s); blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_LABEL_ENC", s); } else if (streq(name, "PTTYPE")) { udev_builtin_add_property(dev, test, "ID_PART_TABLE_TYPE", value); } else if (streq(name, "PTUUID")) { udev_builtin_add_property(dev, test, "ID_PART_TABLE_UUID", value); } else if (streq(name, "PART_ENTRY_NAME")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_PART_ENTRY_NAME", s); } else if (streq(name, "PART_ENTRY_TYPE")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_PART_ENTRY_TYPE", s); } else if (startswith(name, "PART_ENTRY_")) { strscpyl(s, sizeof(s), "ID_", name, NULL); udev_builtin_add_property(dev, test, s, value); } else if (streq(name, "SYSTEM_ID")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_SYSTEM_ID", s); } else if (streq(name, "PUBLISHER_ID")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_PUBLISHER_ID", s); } else if (streq(name, "APPLICATION_ID")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_APPLICATION_ID", s); } else if (streq(name, "BOOT_SYSTEM_ID")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_BOOT_SYSTEM_ID", s); } } static int find_gpt_root(struct udev_device *dev, blkid_probe pr, bool test) { #if defined(GPT_ROOT_NATIVE) && defined(ENABLE_EFI) _cleanup_free_ char *root_id = NULL; bool found_esp = false; blkid_partlist pl; int i, nvals, r; assert(pr); /* Iterate through the partitions on this disk, and see if the * EFI ESP we booted from is on it. If so, find the first root * disk, and add a property indicating its partition UUID. */ errno = 0; pl = blkid_probe_get_partitions(pr); if (!pl) return errno > 0 ? -errno : -ENOMEM; nvals = blkid_partlist_numof_partitions(pl); for (i = 0; i < nvals; i++) { blkid_partition pp; const char *stype, *sid; sd_id128_t type; pp = blkid_partlist_get_partition(pl, i); if (!pp) continue; sid = blkid_partition_get_uuid(pp); if (!sid) continue; stype = blkid_partition_get_type_string(pp); if (!stype) continue; if (sd_id128_from_string(stype, &type) < 0) continue; if (sd_id128_equal(type, GPT_ESP)) { sd_id128_t id, esp; unsigned long long flags; flags = blkid_partition_get_flags(pp); if (flags & GPT_FLAG_NO_AUTO) continue; /* We found an ESP, let's see if it matches * the ESP we booted from. */ if (sd_id128_from_string(sid, &id) < 0) continue; r = efi_loader_get_device_part_uuid(&esp); if (r < 0) return r; if (sd_id128_equal(id, esp)) found_esp = true; } else if (sd_id128_equal(type, GPT_ROOT_NATIVE)) { /* We found a suitable root partition, let's * remember the first one. */ if (!root_id) { root_id = strdup(sid); if (!root_id) return -ENOMEM; } } } /* We found the ESP on this disk, and also found a root * partition, nice! Let's export its UUID */ if (found_esp && root_id) udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT_UUID", root_id); #endif return 0; } static int probe_superblocks(blkid_probe pr) { struct stat st; int rc; if (fstat(blkid_probe_get_fd(pr), &st)) return -1; blkid_probe_enable_partitions(pr, 1); if (!S_ISCHR(st.st_mode) && blkid_probe_get_size(pr) <= 1024 * 1440 && blkid_probe_is_wholedisk(pr)) { /* * check if the small disk is partitioned, if yes then * don't probe for filesystems. */ blkid_probe_enable_superblocks(pr, 0); rc = blkid_do_fullprobe(pr); if (rc < 0) return rc; /* -1 = error, 1 = nothing, 0 = success */ if (blkid_probe_lookup_value(pr, "PTTYPE", NULL, NULL) == 0) return 0; /* partition table detected */ } blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS); blkid_probe_enable_superblocks(pr, 1); return blkid_do_safeprobe(pr); } static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool test) { const char *root_partition; int64_t offset = 0; bool noraid = false; _cleanup_close_ int fd = -1; blkid_probe pr; const char *data; const char *name; const char *prtype = NULL; int nvals; int i; int err = 0; bool is_gpt = false; static const struct option options[] = { { "offset", optional_argument, NULL, 'o' }, { "noraid", no_argument, NULL, 'R' }, {} }; for (;;) { int option; option = getopt_long(argc, argv, "oR", options, NULL); if (option == -1) break; switch (option) { case 'o': offset = strtoull(optarg, NULL, 0); break; case 'R': noraid = true; break; } } pr = blkid_new_probe(); if (!pr) return EXIT_FAILURE; blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION | BLKID_SUBLKS_BADCSUM); if (noraid) blkid_probe_filter_superblocks_usage(pr, BLKID_FLTR_NOTIN, BLKID_USAGE_RAID); fd = open(udev_device_get_devnode(dev), O_RDONLY|O_CLOEXEC); if (fd < 0) { err = log_debug_errno(errno, "Failure opening block device %s: %m", udev_device_get_devnode(dev)); goto out; } err = blkid_probe_set_device(pr, fd, offset, 0); if (err < 0) goto out; log_debug("probe %s %sraid offset=%"PRIi64, udev_device_get_devnode(dev), noraid ? "no" : "", offset); err = probe_superblocks(pr); if (err < 0) goto out; if (blkid_probe_has_value(pr, "SBBADCSUM")) { if (!blkid_probe_lookup_value(pr, "TYPE", &prtype, NULL)) log_warning("incorrect %s checksum on %s", prtype, udev_device_get_devnode(dev)); else log_warning("incorrect checksum on %s", udev_device_get_devnode(dev)); goto out; } /* If we are a partition then our parent passed on the root * partition UUID to us */ root_partition = udev_device_get_property_value(dev, "ID_PART_GPT_AUTO_ROOT_UUID"); nvals = blkid_probe_numof_values(pr); for (i = 0; i < nvals; i++) { if (blkid_probe_get_value(pr, i, &name, &data, NULL)) continue; print_property(dev, test, name, data); /* Is this a disk with GPT partition table? */ if (streq(name, "PTTYPE") && streq(data, "gpt")) is_gpt = true; /* Is this a partition that matches the root partition * property we inherited from our parent? */ if (root_partition && streq(name, "PART_ENTRY_UUID") && streq(data, root_partition)) udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT", "1"); } if (is_gpt) find_gpt_root(dev, pr, test); blkid_free_probe(pr); out: if (err < 0) return EXIT_FAILURE; return EXIT_SUCCESS; } const struct udev_builtin udev_builtin_blkid = { .name = "blkid", .cmd = builtin_blkid, .help = "Filesystem and partition probing", .run_once = true, }; systemd-229/src/udev/udev-builtin-btrfs.c000066400000000000000000000033501265713322000205050ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #ifdef HAVE_LINUX_BTRFS_H #include #endif #include "fd-util.h" #include "missing.h" #include "string-util.h" #include "udev.h" static int builtin_btrfs(struct udev_device *dev, int argc, char *argv[], bool test) { struct btrfs_ioctl_vol_args args = {}; _cleanup_close_ int fd = -1; int err; if (argc != 3 || !streq(argv[1], "ready")) return EXIT_FAILURE; fd = open("/dev/btrfs-control", O_RDWR|O_CLOEXEC); if (fd < 0) return EXIT_FAILURE; strscpy(args.name, sizeof(args.name), argv[2]); err = ioctl(fd, BTRFS_IOC_DEVICES_READY, &args); if (err < 0) return EXIT_FAILURE; udev_builtin_add_property(dev, test, "ID_BTRFS_READY", one_zero(err == 0)); return EXIT_SUCCESS; } const struct udev_builtin udev_builtin_btrfs = { .name = "btrfs", .cmd = builtin_btrfs, .help = "btrfs volume management", }; systemd-229/src/udev/udev-builtin-hwdb.c000066400000000000000000000153631265713322000203200ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "sd-hwdb.h" #include "alloc-util.h" #include "hwdb-util.h" #include "string-util.h" #include "udev-util.h" #include "udev.h" static sd_hwdb *hwdb; int udev_builtin_hwdb_lookup(struct udev_device *dev, const char *prefix, const char *modalias, const char *filter, bool test) { _cleanup_free_ char *lookup = NULL; const char *key, *value; int n = 0; if (!hwdb) return -ENOENT; if (prefix) { lookup = strjoin(prefix, modalias, NULL); if (!lookup) return -ENOMEM; modalias = lookup; } SD_HWDB_FOREACH_PROPERTY(hwdb, modalias, key, value) { if (filter && fnmatch(filter, key, FNM_NOESCAPE) != 0) continue; if (udev_builtin_add_property(dev, test, key, value) < 0) return -ENOMEM; n++; } return n; } static const char *modalias_usb(struct udev_device *dev, char *s, size_t size) { const char *v, *p; int vn, pn; v = udev_device_get_sysattr_value(dev, "idVendor"); if (!v) return NULL; p = udev_device_get_sysattr_value(dev, "idProduct"); if (!p) return NULL; vn = strtol(v, NULL, 16); if (vn <= 0) return NULL; pn = strtol(p, NULL, 16); if (pn <= 0) return NULL; snprintf(s, size, "usb:v%04Xp%04X*", vn, pn); return s; } static int udev_builtin_hwdb_search(struct udev_device *dev, struct udev_device *srcdev, const char *subsystem, const char *prefix, const char *filter, bool test) { struct udev_device *d; char s[16]; bool last = false; int r = 0; assert(dev); if (!srcdev) srcdev = dev; for (d = srcdev; d && !last; d = udev_device_get_parent(d)) { const char *dsubsys; const char *modalias = NULL; dsubsys = udev_device_get_subsystem(d); if (!dsubsys) continue; /* look only at devices of a specific subsystem */ if (subsystem && !streq(dsubsys, subsystem)) continue; modalias = udev_device_get_property_value(d, "MODALIAS"); if (streq(dsubsys, "usb") && streq_ptr(udev_device_get_devtype(d), "usb_device")) { /* if the usb_device does not have a modalias, compose one */ if (!modalias) modalias = modalias_usb(d, s, sizeof(s)); /* avoid looking at any parent device, they are usually just a USB hub */ last = true; } if (!modalias) continue; r = udev_builtin_hwdb_lookup(dev, prefix, modalias, filter, test); if (r > 0) break; } return r; } static int builtin_hwdb(struct udev_device *dev, int argc, char *argv[], bool test) { static const struct option options[] = { { "filter", required_argument, NULL, 'f' }, { "device", required_argument, NULL, 'd' }, { "subsystem", required_argument, NULL, 's' }, { "lookup-prefix", required_argument, NULL, 'p' }, {} }; const char *filter = NULL; const char *device = NULL; const char *subsystem = NULL; const char *prefix = NULL; _cleanup_udev_device_unref_ struct udev_device *srcdev = NULL; if (!hwdb) return EXIT_FAILURE; for (;;) { int option; option = getopt_long(argc, argv, "f:d:s:p:", options, NULL); if (option == -1) break; switch (option) { case 'f': filter = optarg; break; case 'd': device = optarg; break; case 's': subsystem = optarg; break; case 'p': prefix = optarg; break; } } /* query a specific key given as argument */ if (argv[optind]) { if (udev_builtin_hwdb_lookup(dev, prefix, argv[optind], filter, test) > 0) return EXIT_SUCCESS; return EXIT_FAILURE; } /* read data from another device than the device we will store the data */ if (device) { srcdev = udev_device_new_from_device_id(udev_device_get_udev(dev), device); if (!srcdev) return EXIT_FAILURE; } if (udev_builtin_hwdb_search(dev, srcdev, subsystem, prefix, filter, test) > 0) return EXIT_SUCCESS; return EXIT_FAILURE; } /* called at udev startup and reload */ static int builtin_hwdb_init(struct udev *udev) { int r; if (hwdb) return 0; r = sd_hwdb_new(&hwdb); if (r < 0) return r; return 0; } /* called on udev shutdown and reload request */ static void builtin_hwdb_exit(struct udev *udev) { hwdb = sd_hwdb_unref(hwdb); } /* called every couple of seconds during event activity; 'true' if config has changed */ static bool builtin_hwdb_validate(struct udev *udev) { return hwdb_validate(hwdb); } const struct udev_builtin udev_builtin_hwdb = { .name = "hwdb", .cmd = builtin_hwdb, .init = builtin_hwdb_init, .exit = builtin_hwdb_exit, .validate = builtin_hwdb_validate, .help = "Hardware database", }; systemd-229/src/udev/udev-builtin-input_id.c000066400000000000000000000337501265713322000212070ustar00rootroot00000000000000/* * expose input properties via udev * * Copyright (C) 2009 Martin Pitt * Portions Copyright (C) 2004 David Zeuthen, * Copyright (C) 2011 Kay Sievers * Copyright (C) 2014 Carlos Garnacho * Copyright (C) 2014 David Herrmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include "fd-util.h" #include "stdio-util.h" #include "string-util.h" #include "udev.h" #include "util.h" /* we must use this kernel-compatible implementation */ #define BITS_PER_LONG (sizeof(unsigned long) * 8) #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) #define OFF(x) ((x)%BITS_PER_LONG) #define BIT(x) (1UL<> OFF(bit)) & 1) static inline int abs_size_mm(const struct input_absinfo *absinfo) { /* Resolution is defined to be in units/mm for ABS_X/Y */ return (absinfo->maximum - absinfo->minimum) / absinfo->resolution; } static void extract_info(struct udev_device *dev, const char *devpath, bool test) { char width[DECIMAL_STR_MAX(int)], height[DECIMAL_STR_MAX(int)]; struct input_absinfo xabsinfo = {}, yabsinfo = {}; _cleanup_close_ int fd = -1; fd = open(devpath, O_RDONLY|O_CLOEXEC); if (fd < 0) return; if (ioctl(fd, EVIOCGABS(ABS_X), &xabsinfo) < 0 || ioctl(fd, EVIOCGABS(ABS_Y), &yabsinfo) < 0) return; if (xabsinfo.resolution <= 0 || yabsinfo.resolution <= 0) return; xsprintf(width, "%d", abs_size_mm(&xabsinfo)); xsprintf(height, "%d", abs_size_mm(&yabsinfo)); udev_builtin_add_property(dev, test, "ID_INPUT_WIDTH_MM", width); udev_builtin_add_property(dev, test, "ID_INPUT_HEIGHT_MM", height); } /* * Read a capability attribute and return bitmask. * @param dev udev_device * @param attr sysfs attribute name (e. g. "capabilities/key") * @param bitmask: Output array which has a sizeof of bitmask_size */ static void get_cap_mask(struct udev_device *dev, struct udev_device *pdev, const char* attr, unsigned long *bitmask, size_t bitmask_size, bool test) { const char *v; char text[4096]; unsigned i; char* word; unsigned long val; v = udev_device_get_sysattr_value(pdev, attr); if (!v) v = ""; xsprintf(text, "%s", v); log_debug("%s raw kernel attribute: %s", attr, text); memzero(bitmask, bitmask_size); i = 0; while ((word = strrchr(text, ' ')) != NULL) { val = strtoul (word+1, NULL, 16); if (i < bitmask_size/sizeof(unsigned long)) bitmask[i] = val; else log_debug("ignoring %s block %lX which is larger than maximum size", attr, val); *word = '\0'; ++i; } val = strtoul (text, NULL, 16); if (i < bitmask_size / sizeof(unsigned long)) bitmask[i] = val; else log_debug("ignoring %s block %lX which is larger than maximum size", attr, val); if (test) { /* printf pattern with the right unsigned long number of hex chars */ xsprintf(text, " bit %%4u: %%0%zulX\n", 2 * sizeof(unsigned long)); log_debug("%s decoded bit map:", attr); val = bitmask_size / sizeof (unsigned long); /* skip over leading zeros */ while (bitmask[val-1] == 0 && val > 0) --val; for (i = 0; i < val; ++i) { DISABLE_WARNING_FORMAT_NONLITERAL; log_debug(text, i * BITS_PER_LONG, bitmask[i]); REENABLE_WARNING; } } } /* pointer devices */ static bool test_pointers(struct udev_device *dev, const unsigned long* bitmask_ev, const unsigned long* bitmask_abs, const unsigned long* bitmask_key, const unsigned long* bitmask_rel, const unsigned long* bitmask_props, bool test) { bool has_abs_coordinates = false; bool has_rel_coordinates = false; bool has_mt_coordinates = false; bool has_joystick_axes_or_buttons = false; bool is_direct = false; bool has_touch = false; bool has_3d_coordinates = false; bool has_keys = false; bool stylus_or_pen = false; bool finger_but_no_pen = false; bool has_mouse_button = false; bool is_mouse = false; bool is_touchpad = false; bool is_touchscreen = false; bool is_tablet = false; bool is_joystick = false; bool is_accelerometer = false; bool is_pointing_stick= false; has_keys = test_bit(EV_KEY, bitmask_ev); has_abs_coordinates = test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs); has_3d_coordinates = has_abs_coordinates && test_bit(ABS_Z, bitmask_abs); is_accelerometer = test_bit(INPUT_PROP_ACCELEROMETER, bitmask_props); if (!has_keys && has_3d_coordinates) is_accelerometer = true; if (is_accelerometer) { udev_builtin_add_property(dev, test, "ID_INPUT_ACCELEROMETER", "1"); return true; } is_pointing_stick = test_bit(INPUT_PROP_POINTING_STICK, bitmask_props); stylus_or_pen = test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key); finger_but_no_pen = test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key); has_mouse_button = test_bit(BTN_LEFT, bitmask_key); has_rel_coordinates = test_bit(EV_REL, bitmask_ev) && test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel); has_mt_coordinates = test_bit(ABS_MT_POSITION_X, bitmask_abs) && test_bit(ABS_MT_POSITION_Y, bitmask_abs); /* unset has_mt_coordinates if devices claims to have all abs axis */ if(has_mt_coordinates && test_bit(ABS_MT_SLOT, bitmask_abs) && test_bit(ABS_MT_SLOT - 1, bitmask_abs)) has_mt_coordinates = false; is_direct = test_bit(INPUT_PROP_DIRECT, bitmask_props); has_touch = test_bit(BTN_TOUCH, bitmask_key); /* joysticks don't necessarily have buttons; e. g. * rudders/pedals are joystick-like, but buttonless; they have * other fancy axes */ has_joystick_axes_or_buttons = test_bit(BTN_TRIGGER, bitmask_key) || test_bit(BTN_A, bitmask_key) || test_bit(BTN_1, bitmask_key) || test_bit(ABS_RX, bitmask_abs) || test_bit(ABS_RY, bitmask_abs) || test_bit(ABS_RZ, bitmask_abs) || test_bit(ABS_THROTTLE, bitmask_abs) || test_bit(ABS_RUDDER, bitmask_abs) || test_bit(ABS_WHEEL, bitmask_abs) || test_bit(ABS_GAS, bitmask_abs) || test_bit(ABS_BRAKE, bitmask_abs); if (has_abs_coordinates) { if (stylus_or_pen) is_tablet = true; else if (finger_but_no_pen && !is_direct) is_touchpad = true; else if (has_mouse_button) /* This path is taken by VMware's USB mouse, which has * absolute axes, but no touch/pressure button. */ is_mouse = true; else if (has_touch || is_direct) is_touchscreen = true; else if (has_joystick_axes_or_buttons) is_joystick = true; } if (has_mt_coordinates && (is_direct || has_touch)) is_touchscreen = true; if (has_rel_coordinates && has_mouse_button) is_mouse = true; if (is_pointing_stick) udev_builtin_add_property(dev, test, "ID_INPUT_POINTINGSTICK", "1"); if (is_mouse) udev_builtin_add_property(dev, test, "ID_INPUT_MOUSE", "1"); if (is_touchpad) udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHPAD", "1"); if (is_touchscreen) udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHSCREEN", "1"); if (is_joystick) udev_builtin_add_property(dev, test, "ID_INPUT_JOYSTICK", "1"); if (is_tablet) udev_builtin_add_property(dev, test, "ID_INPUT_TABLET", "1"); return is_tablet || is_mouse || is_touchpad || is_touchscreen || is_joystick || is_pointing_stick; } /* key like devices */ static bool test_key(struct udev_device *dev, const unsigned long* bitmask_ev, const unsigned long* bitmask_key, bool test) { unsigned i; unsigned long found; unsigned long mask; bool ret = false; /* do we have any KEY_* capability? */ if (!test_bit(EV_KEY, bitmask_ev)) { log_debug("test_key: no EV_KEY capability"); return false; } /* only consider KEY_* here, not BTN_* */ found = 0; for (i = 0; i < BTN_MISC/BITS_PER_LONG; ++i) { found |= bitmask_key[i]; log_debug("test_key: checking bit block %lu for any keys; found=%i", (unsigned long)i*BITS_PER_LONG, found > 0); } /* If there are no keys in the lower block, check the higher block */ if (!found) { for (i = KEY_OK; i < BTN_TRIGGER_HAPPY; ++i) { if (test_bit(i, bitmask_key)) { log_debug("test_key: Found key %x in high block", i); found = 1; break; } } } if (found > 0) { udev_builtin_add_property(dev, test, "ID_INPUT_KEY", "1"); ret = true; } /* the first 32 bits are ESC, numbers, and Q to D; if we have all of * those, consider it a full keyboard; do not test KEY_RESERVED, though */ mask = 0xFFFFFFFE; if ((bitmask_key[0] & mask) == mask) { udev_builtin_add_property(dev, test, "ID_INPUT_KEYBOARD", "1"); ret = true; } return ret; } static int builtin_input_id(struct udev_device *dev, int argc, char *argv[], bool test) { struct udev_device *pdev; unsigned long bitmask_ev[NBITS(EV_MAX)]; unsigned long bitmask_abs[NBITS(ABS_MAX)]; unsigned long bitmask_key[NBITS(KEY_MAX)]; unsigned long bitmask_rel[NBITS(REL_MAX)]; unsigned long bitmask_props[NBITS(INPUT_PROP_MAX)]; const char *sysname, *devnode; bool is_pointer; bool is_key; assert(dev); /* walk up the parental chain until we find the real input device; the * argument is very likely a subdevice of this, like eventN */ pdev = dev; while (pdev != NULL && udev_device_get_sysattr_value(pdev, "capabilities/ev") == NULL) pdev = udev_device_get_parent_with_subsystem_devtype(pdev, "input", NULL); if (pdev) { /* Use this as a flag that input devices were detected, so that this * program doesn't need to be called more than once per device */ udev_builtin_add_property(dev, test, "ID_INPUT", "1"); get_cap_mask(dev, pdev, "capabilities/ev", bitmask_ev, sizeof(bitmask_ev), test); get_cap_mask(dev, pdev, "capabilities/abs", bitmask_abs, sizeof(bitmask_abs), test); get_cap_mask(dev, pdev, "capabilities/rel", bitmask_rel, sizeof(bitmask_rel), test); get_cap_mask(dev, pdev, "capabilities/key", bitmask_key, sizeof(bitmask_key), test); get_cap_mask(dev, pdev, "properties", bitmask_props, sizeof(bitmask_props), test); is_pointer = test_pointers(dev, bitmask_ev, bitmask_abs, bitmask_key, bitmask_rel, bitmask_props, test); is_key = test_key(dev, bitmask_ev, bitmask_key, test); /* Some evdev nodes have only a scrollwheel */ if (!is_pointer && !is_key && test_bit(EV_REL, bitmask_ev) && (test_bit(REL_WHEEL, bitmask_rel) || test_bit(REL_HWHEEL, bitmask_rel))) udev_builtin_add_property(dev, test, "ID_INPUT_KEY", "1"); } devnode = udev_device_get_devnode(dev); sysname = udev_device_get_sysname(dev); if (devnode && sysname && startswith(sysname, "event")) extract_info(dev, devnode, test); return EXIT_SUCCESS; } const struct udev_builtin udev_builtin_input_id = { .name = "input_id", .cmd = builtin_input_id, .help = "Input device properties", }; systemd-229/src/udev/udev-builtin-keyboard.c000066400000000000000000000225011265713322000211640ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include "fd-util.h" #include "parse-util.h" #include "stdio-util.h" #include "string-util.h" #include "udev.h" static const struct key *keyboard_lookup_key(const char *str, unsigned len); #include "keyboard-keys-from-name.h" static int install_force_release(struct udev_device *dev, const unsigned *release, unsigned release_count) { struct udev_device *atkbd; const char *cur; char codes[4096]; char *s; size_t l; unsigned i; int ret; assert(dev); assert(release); atkbd = udev_device_get_parent_with_subsystem_devtype(dev, "serio", NULL); if (!atkbd) return -ENODEV; cur = udev_device_get_sysattr_value(atkbd, "force_release"); if (!cur) return -ENODEV; s = codes; l = sizeof(codes); /* copy current content */ l = strpcpy(&s, l, cur); /* append new codes */ for (i = 0; i < release_count; i++) l = strpcpyf(&s, l, ",%u", release[i]); log_debug("keyboard: updating force-release list with '%s'", codes); ret = udev_device_set_sysattr_value(atkbd, "force_release", codes); if (ret < 0) log_error_errno(ret, "Error writing force-release attribute: %m"); return ret; } static void map_keycode(int fd, const char *devnode, int scancode, const char *keycode) { struct { unsigned scan; unsigned key; } map; char *endptr; const struct key *k; unsigned keycode_num; /* translate identifier to key code */ k = keyboard_lookup_key(keycode, strlen(keycode)); if (k) { keycode_num = k->id; } else { /* check if it's a numeric code already */ keycode_num = strtoul(keycode, &endptr, 0); if (endptr[0] !='\0') { log_error("Unknown key identifier '%s'", keycode); return; } } map.scan = scancode; map.key = keycode_num; log_debug("keyboard: mapping scan code %d (0x%x) to key code %d (0x%x)", map.scan, map.scan, map.key, map.key); if (ioctl(fd, EVIOCSKEYCODE, &map) < 0) log_error_errno(errno, "Error calling EVIOCSKEYCODE on device node '%s' (scan code 0x%x, key code %d): %m", devnode, map.scan, map.key); } static inline char* parse_token(const char *current, int32_t *val_out) { char *next; int32_t val; if (!current) return NULL; val = strtol(current, &next, 0); if (*next && *next != ':') return NULL; if (next != current) *val_out = val; if (*next) next++; return next; } static void override_abs(int fd, const char *devnode, unsigned evcode, const char *value) { struct input_absinfo absinfo; int rc; char *next; rc = ioctl(fd, EVIOCGABS(evcode), &absinfo); if (rc < 0) { log_error_errno(errno, "Unable to EVIOCGABS device \"%s\"", devnode); return; } next = parse_token(value, &absinfo.minimum); next = parse_token(next, &absinfo.maximum); next = parse_token(next, &absinfo.resolution); next = parse_token(next, &absinfo.fuzz); next = parse_token(next, &absinfo.flat); if (!next) { log_error("Unable to parse EV_ABS override '%s' for '%s'", value, devnode); return; } log_debug("keyboard: %x overridden with %"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32" for \"%s\"", evcode, absinfo.minimum, absinfo.maximum, absinfo.resolution, absinfo.fuzz, absinfo.flat, devnode); rc = ioctl(fd, EVIOCSABS(evcode), &absinfo); if (rc < 0) log_error_errno(errno, "Unable to EVIOCSABS device \"%s\"", devnode); } static void set_trackpoint_sensitivity(struct udev_device *dev, const char *value) { struct udev_device *pdev; char val_s[DECIMAL_STR_MAX(int)]; int r, val_i; assert(dev); assert(value); /* The sensitivity sysfs attr belongs to the serio parent device */ pdev = udev_device_get_parent_with_subsystem_devtype(dev, "serio", NULL); if (!pdev) { log_warning("Failed to get serio parent for '%s'", udev_device_get_devnode(dev)); return; } r = safe_atoi(value, &val_i); if (r < 0) { log_error("Unable to parse POINTINGSTICK_SENSITIVITY '%s' for '%s'", value, udev_device_get_devnode(dev)); return; } xsprintf(val_s, "%d", val_i); r = udev_device_set_sysattr_value(pdev, "sensitivity", val_s); if (r < 0) log_error_errno(r, "Failed to write 'sensitivity' attribute for '%s': %m", udev_device_get_devnode(pdev)); } static int open_device(const char *devnode) { int fd; fd = open(devnode, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); if (fd < 0) return log_error_errno(errno, "Error opening device \"%s\": %m", devnode); return fd; } static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], bool test) { struct udev_list_entry *entry; unsigned release[1024]; unsigned release_count = 0; _cleanup_close_ int fd = -1; const char *node; node = udev_device_get_devnode(dev); if (!node) { log_error("No device node for \"%s\"", udev_device_get_syspath(dev)); return EXIT_FAILURE; } udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) { const char *key; char *endptr; key = udev_list_entry_get_name(entry); if (startswith(key, "KEYBOARD_KEY_")) { const char *keycode; unsigned scancode; /* KEYBOARD_KEY_= */ scancode = strtoul(key + 13, &endptr, 16); if (endptr[0] != '\0') { log_warning("Unable to parse scan code from \"%s\"", key); continue; } keycode = udev_list_entry_get_value(entry); /* a leading '!' needs a force-release entry */ if (keycode[0] == '!') { keycode++; release[release_count] = scancode; if (release_count < ELEMENTSOF(release)-1) release_count++; if (keycode[0] == '\0') continue; } if (fd == -1) { fd = open_device(node); if (fd < 0) return EXIT_FAILURE; } map_keycode(fd, node, scancode, keycode); } else if (startswith(key, "EVDEV_ABS_")) { unsigned evcode; /* EVDEV_ABS_=:::: */ evcode = strtoul(key + 10, &endptr, 16); if (endptr[0] != '\0') { log_warning("Unable to parse EV_ABS code from \"%s\"", key); continue; } if (fd == -1) { fd = open_device(node); if (fd < 0) return EXIT_FAILURE; } override_abs(fd, node, evcode, udev_list_entry_get_value(entry)); } else if (streq(key, "POINTINGSTICK_SENSITIVITY")) set_trackpoint_sensitivity(dev, udev_list_entry_get_value(entry)); } /* install list of force-release codes */ if (release_count > 0) install_force_release(dev, release, release_count); return EXIT_SUCCESS; } const struct udev_builtin udev_builtin_keyboard = { .name = "keyboard", .cmd = builtin_keyboard, .help = "Keyboard scan code to key mapping", }; systemd-229/src/udev/udev-builtin-kmod.c000066400000000000000000000075171265713322000203300ustar00rootroot00000000000000/* * load kernel modules * * Copyright (C) 2011-2012 Kay Sievers * Copyright (C) 2011 ProFUSION embedded systems * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "string-util.h" #include "udev.h" static struct kmod_ctx *ctx = NULL; static int load_module(struct udev *udev, const char *alias) { struct kmod_list *list = NULL; struct kmod_list *l; int err; err = kmod_module_new_from_lookup(ctx, alias, &list); if (err < 0) return err; if (list == NULL) log_debug("No module matches '%s'", alias); kmod_list_foreach(l, list) { struct kmod_module *mod = kmod_module_get_module(l); err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, NULL); if (err == KMOD_PROBE_APPLY_BLACKLIST) log_debug("Module '%s' is blacklisted", kmod_module_get_name(mod)); else if (err == 0) log_debug("Inserted '%s'", kmod_module_get_name(mod)); else log_debug("Failed to insert '%s'", kmod_module_get_name(mod)); kmod_module_unref(mod); } kmod_module_unref_list(list); return err; } _printf_(6,0) static void udev_kmod_log(void *data, int priority, const char *file, int line, const char *fn, const char *format, va_list args) { log_internalv(priority, 0, file, line, fn, format, args); } static int builtin_kmod(struct udev_device *dev, int argc, char *argv[], bool test) { struct udev *udev = udev_device_get_udev(dev); int i; if (!ctx) return 0; if (argc < 3 || !streq(argv[1], "load")) { log_error("expect: %s load ", argv[0]); return EXIT_FAILURE; } for (i = 2; argv[i]; i++) { log_debug("Execute '%s' '%s'", argv[1], argv[i]); load_module(udev, argv[i]); } return EXIT_SUCCESS; } /* called at udev startup and reload */ static int builtin_kmod_init(struct udev *udev) { if (ctx) return 0; ctx = kmod_new(NULL, NULL); if (!ctx) return -ENOMEM; log_debug("Load module index"); kmod_set_log_fn(ctx, udev_kmod_log, udev); kmod_load_resources(ctx); return 0; } /* called on udev shutdown and reload request */ static void builtin_kmod_exit(struct udev *udev) { log_debug("Unload module index"); ctx = kmod_unref(ctx); } /* called every couple of seconds during event activity; 'true' if config has changed */ static bool builtin_kmod_validate(struct udev *udev) { log_debug("Validate module index"); if (!ctx) return false; return (kmod_validate_resources(ctx) != KMOD_RESOURCES_OK); } const struct udev_builtin udev_builtin_kmod = { .name = "kmod", .cmd = builtin_kmod, .init = builtin_kmod_init, .exit = builtin_kmod_exit, .validate = builtin_kmod_validate, .help = "Kernel module loader", .run_once = false, }; systemd-229/src/udev/udev-builtin-net_id.c000066400000000000000000000532221265713322000206320ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ /* * Predictable network interface device names based on: * - firmware/bios-provided index numbers for on-board devices * - firmware-provided pci-express hotplug slot index number * - physical/geographical location of the hardware * - the interface's MAC address * * http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames * * Two character prefixes based on the type of interface: * en -- Ethernet * sl -- serial line IP (slip) * wl -- wlan * ww -- wwan * * Type of names: * b -- BCMA bus core number * c -- CCW bus group name, without leading zeros [s390] * o[d] -- on-board device index number * s[f][d] -- hotplug slot index number * x -- MAC address * [P]ps[f][d] * -- PCI geographical location * [P]ps[f][u][..][c][i] * -- USB port number chain * * All multi-function PCI devices will carry the [f] number in the * device name, including the function 0 device. * * When using PCI geography, The PCI domain is only prepended when it is not 0. * * For USB devices the full chain of port numbers of hubs is composed. If the * name gets longer than the maximum number of 15 characters, the name is not * exported. * The usual USB configuration == 1 and interface == 0 values are suppressed. * * PCI Ethernet card with firmware index "1": * ID_NET_NAME_ONBOARD=eno1 * ID_NET_NAME_ONBOARD_LABEL=Ethernet Port 1 * * PCI Ethernet card in hotplug slot with firmware index number: * /sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1 * ID_NET_NAME_MAC=enx000000000466 * ID_NET_NAME_PATH=enp5s0 * ID_NET_NAME_SLOT=ens1 * * PCI Ethernet multi-function card with 2 ports: * /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/enp2s0f0 * ID_NET_NAME_MAC=enx78e7d1ea46da * ID_NET_NAME_PATH=enp2s0f0 * /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.1/net/enp2s0f1 * ID_NET_NAME_MAC=enx78e7d1ea46dc * ID_NET_NAME_PATH=enp2s0f1 * * PCI wlan card: * /sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0 * ID_NET_NAME_MAC=wlx0024d7e31130 * ID_NET_NAME_PATH=wlp3s0 * * USB built-in 3G modem: * /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.6/net/wwp0s29u1u4i6 * ID_NET_NAME_MAC=wwx028037ec0200 * ID_NET_NAME_PATH=wwp0s29u1u4i6 * * USB Android phone: * /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/net/enp0s29u1u2 * ID_NET_NAME_MAC=enxd626b3450fb5 * ID_NET_NAME_PATH=enp0s29u1u2 */ #include #include #include #include #include #include #include #include #include #include #include "fd-util.h" #include "fileio.h" #include "stdio-util.h" #include "string-util.h" #include "udev.h" #define ONBOARD_INDEX_MAX (16*1024-1) enum netname_type{ NET_UNDEF, NET_PCI, NET_USB, NET_BCMA, NET_VIRTIO, NET_CCWGROUP, }; struct netnames { enum netname_type type; uint8_t mac[6]; bool mac_valid; struct udev_device *pcidev; char pci_slot[IFNAMSIZ]; char pci_path[IFNAMSIZ]; char pci_onboard[IFNAMSIZ]; const char *pci_onboard_label; char usb_ports[IFNAMSIZ]; char bcma_core[IFNAMSIZ]; char ccw_group[IFNAMSIZ]; }; /* retrieve on-board index number and label from firmware */ static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) { unsigned dev_port = 0; size_t l; char *s; const char *attr; int idx; /* ACPI _DSM -- device specific method for naming a PCI or PCI Express device */ attr = udev_device_get_sysattr_value(names->pcidev, "acpi_index"); /* SMBIOS type 41 -- Onboard Devices Extended Information */ if (!attr) attr = udev_device_get_sysattr_value(names->pcidev, "index"); if (!attr) return -ENOENT; idx = strtoul(attr, NULL, 0); if (idx <= 0) return -EINVAL; /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to report for * example). Let's define a cut-off where we don't consider the index reliable anymore. We pick some arbitrary * cut-off, which is somewhere beyond the realistic number of physical network interface a system might * have. Ideally the kernel would already filter his crap for us, but it doesn't currently. */ if (idx > ONBOARD_INDEX_MAX) return -ENOENT; /* kernel provided port index for multiple ports on a single PCI function */ attr = udev_device_get_sysattr_value(dev, "dev_port"); if (attr) dev_port = strtol(attr, NULL, 10); s = names->pci_onboard; l = sizeof(names->pci_onboard); l = strpcpyf(&s, l, "o%d", idx); if (dev_port > 0) l = strpcpyf(&s, l, "d%d", dev_port); if (l == 0) names->pci_onboard[0] = '\0'; names->pci_onboard_label = udev_device_get_sysattr_value(names->pcidev, "label"); return 0; } /* read the 256 bytes PCI configuration space to check the multi-function bit */ static bool is_pci_multifunction(struct udev_device *dev) { _cleanup_close_ int fd = -1; const char *filename; uint8_t config[64]; filename = strjoina(udev_device_get_syspath(dev), "/config"); fd = open(filename, O_RDONLY | O_CLOEXEC); if (fd < 0) return false; if (read(fd, &config, sizeof(config)) != sizeof(config)) return false; /* bit 0-6 header type, bit 7 multi/single function device */ if ((config[PCI_HEADER_TYPE] & 0x80) != 0) return true; return false; } static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { struct udev *udev = udev_device_get_udev(names->pcidev); unsigned domain, bus, slot, func, dev_port = 0; size_t l; char *s; const char *attr; struct udev_device *pci = NULL; char slots[256], str[256]; _cleanup_closedir_ DIR *dir = NULL; struct dirent *dent; int hotplug_slot = 0, err = 0; if (sscanf(udev_device_get_sysname(names->pcidev), "%x:%x:%x.%u", &domain, &bus, &slot, &func) != 4) return -ENOENT; /* kernel provided port index for multiple ports on a single PCI function */ attr = udev_device_get_sysattr_value(dev, "dev_port"); if (attr) dev_port = strtol(attr, NULL, 10); /* compose a name based on the raw kernel's PCI bus, slot numbers */ s = names->pci_path; l = sizeof(names->pci_path); if (domain > 0) l = strpcpyf(&s, l, "P%u", domain); l = strpcpyf(&s, l, "p%us%u", bus, slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = strpcpyf(&s, l, "f%u", func); if (dev_port > 0) l = strpcpyf(&s, l, "d%u", dev_port); if (l == 0) names->pci_path[0] = '\0'; /* ACPI _SUN -- slot user number */ pci = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci"); if (!pci) { err = -ENOENT; goto out; } xsprintf(slots, "%s/slots", udev_device_get_syspath(pci)); dir = opendir(slots); if (!dir) { err = -errno; goto out; } for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { int i; char *rest; char *address; if (dent->d_name[0] == '.') continue; i = strtol(dent->d_name, &rest, 10); if (rest[0] != '\0') continue; if (i < 1) continue; xsprintf(str, "%s/%s/address", slots, dent->d_name); if (read_one_line_file(str, &address) >= 0) { /* match slot address with device by stripping the function */ if (strneq(address, udev_device_get_sysname(names->pcidev), strlen(address))) hotplug_slot = i; free(address); } if (hotplug_slot > 0) break; } if (hotplug_slot > 0) { s = names->pci_slot; l = sizeof(names->pci_slot); if (domain > 0) l = strpcpyf(&s, l, "P%d", domain); l = strpcpyf(&s, l, "s%d", hotplug_slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = strpcpyf(&s, l, "f%d", func); if (dev_port > 0) l = strpcpyf(&s, l, "d%d", dev_port); if (l == 0) names->pci_slot[0] = '\0'; } out: udev_device_unref(pci); return err; } static int names_pci(struct udev_device *dev, struct netnames *names) { struct udev_device *parent; assert(dev); assert(names); parent = udev_device_get_parent(dev); /* there can only ever be one virtio bus per parent device, so we can safely ignore any virtio buses. see */ while (parent && streq_ptr("virtio", udev_device_get_subsystem(parent))) parent = udev_device_get_parent(parent); if (!parent) return -ENOENT; /* check if our direct parent is a PCI device with no other bus in-between */ if (streq_ptr("pci", udev_device_get_subsystem(parent))) { names->type = NET_PCI; names->pcidev = parent; } else { names->pcidev = udev_device_get_parent_with_subsystem_devtype(dev, "pci", NULL); if (!names->pcidev) return -ENOENT; } dev_pci_onboard(dev, names); dev_pci_slot(dev, names); return 0; } static int names_usb(struct udev_device *dev, struct netnames *names) { struct udev_device *usbdev; char name[256]; char *ports; char *config; char *interf; size_t l; char *s; assert(dev); assert(names); usbdev = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface"); if (!usbdev) return -ENOENT; /* get USB port number chain, configuration, interface */ strscpy(name, sizeof(name), udev_device_get_sysname(usbdev)); s = strchr(name, '-'); if (!s) return -EINVAL; ports = s+1; s = strchr(ports, ':'); if (!s) return -EINVAL; s[0] = '\0'; config = s+1; s = strchr(config, '.'); if (!s) return -EINVAL; s[0] = '\0'; interf = s+1; /* prefix every port number in the chain with "u" */ s = ports; while ((s = strchr(s, '.'))) s[0] = 'u'; s = names->usb_ports; l = strpcpyl(&s, sizeof(names->usb_ports), "u", ports, NULL); /* append USB config number, suppress the common config == 1 */ if (!streq(config, "1")) l = strpcpyl(&s, sizeof(names->usb_ports), "c", config, NULL); /* append USB interface number, suppress the interface == 0 */ if (!streq(interf, "0")) l = strpcpyl(&s, sizeof(names->usb_ports), "i", interf, NULL); if (l == 0) return -ENAMETOOLONG; names->type = NET_USB; return 0; } static int names_bcma(struct udev_device *dev, struct netnames *names) { struct udev_device *bcmadev; unsigned int core; assert(dev); assert(names); bcmadev = udev_device_get_parent_with_subsystem_devtype(dev, "bcma", NULL); if (!bcmadev) return -ENOENT; /* bus num:core num */ if (sscanf(udev_device_get_sysname(bcmadev), "bcma%*u:%u", &core) != 1) return -EINVAL; /* suppress the common core == 0 */ if (core > 0) xsprintf(names->bcma_core, "b%u", core); names->type = NET_BCMA; return 0; } static int names_ccw(struct udev_device *dev, struct netnames *names) { struct udev_device *cdev; const char *bus_id; size_t bus_id_len; int rc; assert(dev); assert(names); /* Retrieve the associated CCW device */ cdev = udev_device_get_parent(dev); if (!cdev) return -ENOENT; /* Network devices are always grouped CCW devices */ if (!streq_ptr("ccwgroup", udev_device_get_subsystem(cdev))) return -ENOENT; /* Retrieve bus-ID of the grouped CCW device. The bus-ID uniquely * identifies the network device on the Linux on System z channel * subsystem. Note that the bus-ID contains lowercase characters. */ bus_id = udev_device_get_sysname(cdev); if (!bus_id) return -ENOENT; /* Check the length of the bus-ID. Rely on that the kernel provides * a correct bus-ID; alternatively, improve this check and parse and * verify each bus-ID part... */ bus_id_len = strlen(bus_id); if (!bus_id_len || bus_id_len < 8 || bus_id_len > 9) return -EINVAL; /* Strip leading zeros from the bus id for aesthetic purposes. This * keeps the ccw names stable, yet much shorter in general case of * bus_id 0.0.0600 -> 600. This is similar to e.g. how PCI domain is * not prepended when it is zero. */ bus_id += strspn(bus_id, ".0"); /* Store the CCW bus-ID for use as network device name */ rc = snprintf(names->ccw_group, sizeof(names->ccw_group), "c%s", bus_id); if (rc >= 0 && rc < (int)sizeof(names->ccw_group)) names->type = NET_CCWGROUP; return 0; } static int names_mac(struct udev_device *dev, struct netnames *names) { const char *s; unsigned int i; unsigned int a1, a2, a3, a4, a5, a6; /* check for NET_ADDR_PERM, skip random MAC addresses */ s = udev_device_get_sysattr_value(dev, "addr_assign_type"); if (!s) return EXIT_FAILURE; i = strtoul(s, NULL, 0); if (i != 0) return 0; s = udev_device_get_sysattr_value(dev, "address"); if (!s) return -ENOENT; if (sscanf(s, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6) return -EINVAL; /* skip empty MAC addresses */ if (a1 + a2 + a3 + a4 + a5 + a6 == 0) return -EINVAL; names->mac[0] = a1; names->mac[1] = a2; names->mac[2] = a3; names->mac[3] = a4; names->mac[4] = a5; names->mac[5] = a6; names->mac_valid = true; return 0; } /* IEEE Organizationally Unique Identifier vendor string */ static int ieee_oui(struct udev_device *dev, struct netnames *names, bool test) { char str[32]; if (!names->mac_valid) return -ENOENT; /* skip commonly misused 00:00:00 (Xerox) prefix */ if (memcmp(names->mac, "\0\0\0", 3) == 0) return -EINVAL; xsprintf(str, "OUI:%02X%02X%02X%02X%02X%02X", names->mac[0], names->mac[1], names->mac[2], names->mac[3], names->mac[4], names->mac[5]); udev_builtin_hwdb_lookup(dev, NULL, str, NULL, test); return 0; } static int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool test) { const char *s; const char *p; unsigned int i; const char *devtype; const char *prefix = "en"; struct netnames names = {}; int err; /* handle only ARPHRD_ETHER and ARPHRD_SLIP devices */ s = udev_device_get_sysattr_value(dev, "type"); if (!s) return EXIT_FAILURE; i = strtoul(s, NULL, 0); switch (i) { case ARPHRD_ETHER: prefix = "en"; break; case ARPHRD_SLIP: prefix = "sl"; break; default: return 0; } /* skip stacked devices, like VLANs, ... */ s = udev_device_get_sysattr_value(dev, "ifindex"); if (!s) return EXIT_FAILURE; p = udev_device_get_sysattr_value(dev, "iflink"); if (!p) return EXIT_FAILURE; if (!streq(s, p)) return 0; devtype = udev_device_get_devtype(dev); if (devtype) { if (streq("wlan", devtype)) prefix = "wl"; else if (streq("wwan", devtype)) prefix = "ww"; } err = names_mac(dev, &names); if (err >= 0 && names.mac_valid) { char str[IFNAMSIZ]; xsprintf(str, "%sx%02x%02x%02x%02x%02x%02x", prefix, names.mac[0], names.mac[1], names.mac[2], names.mac[3], names.mac[4], names.mac[5]); udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str); ieee_oui(dev, &names, test); } /* get path names for Linux on System z network devices */ err = names_ccw(dev, &names); if (err >= 0 && names.type == NET_CCWGROUP) { char str[IFNAMSIZ]; if (snprintf(str, sizeof(str), "%s%s", prefix, names.ccw_group) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); goto out; } /* get PCI based path names, we compose only PCI based paths */ err = names_pci(dev, &names); if (err < 0) goto out; /* plain PCI device */ if (names.type == NET_PCI) { char str[IFNAMSIZ]; if (names.pci_onboard[0]) if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str); if (names.pci_onboard_label) if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard_label) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", str); if (names.pci_path[0]) if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_path) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); if (names.pci_slot[0]) if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_slot) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); goto out; } /* USB device */ err = names_usb(dev, &names); if (err >= 0 && names.type == NET_USB) { char str[IFNAMSIZ]; if (names.pci_path[0]) if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.usb_ports) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); if (names.pci_slot[0]) if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.usb_ports) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); goto out; } /* Broadcom bus */ err = names_bcma(dev, &names); if (err >= 0 && names.type == NET_BCMA) { char str[IFNAMSIZ]; if (names.pci_path[0]) if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.bcma_core) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); if (names.pci_slot[0]) if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.bcma_core) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); goto out; } out: return EXIT_SUCCESS; } const struct udev_builtin udev_builtin_net_id = { .name = "net_id", .cmd = builtin_net_id, .help = "Network device properties", }; systemd-229/src/udev/udev-builtin-net_setup_link.c000066400000000000000000000063351265713322000224160ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2013 Tom Gundersen systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "alloc-util.h" #include "link-config.h" #include "log.h" #include "udev.h" static link_config_ctx *ctx = NULL; static int builtin_net_setup_link(struct udev_device *dev, int argc, char **argv, bool test) { _cleanup_free_ char *driver = NULL; const char *name = NULL; link_config *link; int r; if (argc > 1) { log_error("This program takes no arguments."); return EXIT_FAILURE; } r = link_get_driver(ctx, dev, &driver); if (r >= 0) udev_builtin_add_property(dev, test, "ID_NET_DRIVER", driver); r = link_config_get(ctx, dev, &link); if (r < 0) { if (r == -ENOENT) { log_debug("No matching link configuration found."); return EXIT_SUCCESS; } else { log_error_errno(r, "Could not get link config: %m"); return EXIT_FAILURE; } } r = link_config_apply(ctx, link, dev, &name); if (r < 0) { log_error_errno(r, "Could not apply link config to %s: %m", udev_device_get_sysname(dev)); return EXIT_FAILURE; } udev_builtin_add_property(dev, test, "ID_NET_LINK_FILE", link->filename); if (name) udev_builtin_add_property(dev, test, "ID_NET_NAME", name); return EXIT_SUCCESS; } static int builtin_net_setup_link_init(struct udev *udev) { int r; if (ctx) return 0; r = link_config_ctx_new(&ctx); if (r < 0) return r; r = link_config_load(ctx); if (r < 0) return r; log_debug("Created link configuration context."); return 0; } static void builtin_net_setup_link_exit(struct udev *udev) { link_config_ctx_free(ctx); ctx = NULL; log_debug("Unloaded link configuration context."); } static bool builtin_net_setup_link_validate(struct udev *udev) { log_debug("Check if link configuration needs reloading."); if (!ctx) return false; return link_config_should_reload(ctx); } const struct udev_builtin udev_builtin_net_setup_link = { .name = "net_setup_link", .cmd = builtin_net_setup_link, .init = builtin_net_setup_link_init, .exit = builtin_net_setup_link_exit, .validate = builtin_net_setup_link_validate, .help = "Configure network link", .run_once = false, }; systemd-229/src/udev/udev-builtin-path_id.c000066400000000000000000000637441265713322000210120ustar00rootroot00000000000000/* * compose persistent device path * * Copyright (C) 2009-2011 Kay Sievers * * Logic based on Hannes Reinecke's shell script. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "string-util.h" #include "udev.h" _printf_(2,3) static int path_prepend(char **path, const char *fmt, ...) { va_list va; char *pre; int err = 0; va_start(va, fmt); err = vasprintf(&pre, fmt, va); va_end(va); if (err < 0) goto out; if (*path != NULL) { char *new; err = asprintf(&new, "%s-%s", pre, *path); free(pre); if (err < 0) goto out; free(*path); *path = new; } else { *path = pre; } out: return err; } /* ** Linux only supports 32 bit luns. ** See drivers/scsi/scsi_scan.c::scsilun_to_int() for more details. */ static int format_lun_number(struct udev_device *dev, char **path) { unsigned long lun = strtoul(udev_device_get_sysnum(dev), NULL, 10); /* address method 0, peripheral device addressing with bus id of zero */ if (lun < 256) return path_prepend(path, "lun-%lu", lun); /* handle all other lun addressing methods by using a variant of the original lun format */ return path_prepend(path, "lun-0x%04lx%04lx00000000", lun & 0xffff, (lun >> 16) & 0xffff); } static struct udev_device *skip_subsystem(struct udev_device *dev, const char *subsys) { struct udev_device *parent = dev; assert(dev); assert(subsys); while (parent != NULL) { const char *subsystem; subsystem = udev_device_get_subsystem(parent); if (subsystem == NULL || !streq(subsystem, subsys)) break; dev = parent; parent = udev_device_get_parent(parent); } return dev; } static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, char **path) { struct udev *udev = udev_device_get_udev(parent); struct udev_device *targetdev; struct udev_device *fcdev = NULL; const char *port; char *lun = NULL; assert(parent); assert(path); targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); if (targetdev == NULL) return NULL; fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev)); if (fcdev == NULL) return NULL; port = udev_device_get_sysattr_value(fcdev, "port_name"); if (port == NULL) { parent = NULL; goto out; } format_lun_number(parent, &lun); path_prepend(path, "fc-%s-%s", port, lun); free(lun); out: udev_device_unref(fcdev); return parent; } static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent, char **path) { struct udev *udev = udev_device_get_udev(parent); struct udev_device *targetdev; struct udev_device *target_parent; struct udev_device *sasdev; const char *sas_address; char *lun = NULL; assert(parent); assert(path); targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); if (targetdev == NULL) return NULL; target_parent = udev_device_get_parent(targetdev); if (target_parent == NULL) return NULL; sasdev = udev_device_new_from_subsystem_sysname(udev, "sas_device", udev_device_get_sysname(target_parent)); if (sasdev == NULL) return NULL; sas_address = udev_device_get_sysattr_value(sasdev, "sas_address"); if (sas_address == NULL) { parent = NULL; goto out; } format_lun_number(parent, &lun); path_prepend(path, "sas-%s-%s", sas_address, lun); free(lun); out: udev_device_unref(sasdev); return parent; } static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **path) { struct udev *udev = udev_device_get_udev(parent); struct udev_device *targetdev; struct udev_device *target_parent; struct udev_device *port; struct udev_device *expander; struct udev_device *target_sasdev = NULL; struct udev_device *expander_sasdev = NULL; struct udev_device *port_sasdev = NULL; const char *sas_address = NULL; const char *phy_id; const char *phy_count; char *lun = NULL; assert(parent); assert(path); targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); if (targetdev == NULL) return NULL; target_parent = udev_device_get_parent(targetdev); if (target_parent == NULL) return NULL; /* Get sas device */ target_sasdev = udev_device_new_from_subsystem_sysname(udev, "sas_device", udev_device_get_sysname(target_parent)); if (target_sasdev == NULL) return NULL; /* The next parent is sas port */ port = udev_device_get_parent(target_parent); if (port == NULL) { parent = NULL; goto out; } /* Get port device */ port_sasdev = udev_device_new_from_subsystem_sysname(udev, "sas_port", udev_device_get_sysname(port)); phy_count = udev_device_get_sysattr_value(port_sasdev, "num_phys"); if (phy_count == NULL) { parent = NULL; goto out; } /* Check if we are simple disk */ if (strncmp(phy_count, "1", 2) != 0) { parent = handle_scsi_sas_wide_port(parent, path); goto out; } /* Get connected phy */ phy_id = udev_device_get_sysattr_value(target_sasdev, "phy_identifier"); if (phy_id == NULL) { parent = NULL; goto out; } /* The port's parent is either hba or expander */ expander = udev_device_get_parent(port); if (expander == NULL) { parent = NULL; goto out; } /* Get expander device */ expander_sasdev = udev_device_new_from_subsystem_sysname(udev, "sas_device", udev_device_get_sysname(expander)); if (expander_sasdev != NULL) { /* Get expander's address */ sas_address = udev_device_get_sysattr_value(expander_sasdev, "sas_address"); if (sas_address == NULL) { parent = NULL; goto out; } } format_lun_number(parent, &lun); if (sas_address) path_prepend(path, "sas-exp%s-phy%s-%s", sas_address, phy_id, lun); else path_prepend(path, "sas-phy%s-%s", phy_id, lun); free(lun); out: udev_device_unref(target_sasdev); udev_device_unref(expander_sasdev); udev_device_unref(port_sasdev); return parent; } static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **path) { struct udev *udev = udev_device_get_udev(parent); struct udev_device *transportdev; struct udev_device *sessiondev = NULL; const char *target; char *connname; struct udev_device *conndev = NULL; const char *addr; const char *port; char *lun = NULL; assert(parent); assert(path); /* find iscsi session */ transportdev = parent; for (;;) { transportdev = udev_device_get_parent(transportdev); if (transportdev == NULL) return NULL; if (startswith(udev_device_get_sysname(transportdev), "session")) break; } /* find iscsi session device */ sessiondev = udev_device_new_from_subsystem_sysname(udev, "iscsi_session", udev_device_get_sysname(transportdev)); if (sessiondev == NULL) return NULL; target = udev_device_get_sysattr_value(sessiondev, "targetname"); if (target == NULL) { parent = NULL; goto out; } if (asprintf(&connname, "connection%s:0", udev_device_get_sysnum(transportdev)) < 0) { parent = NULL; goto out; } conndev = udev_device_new_from_subsystem_sysname(udev, "iscsi_connection", connname); free(connname); if (conndev == NULL) { parent = NULL; goto out; } addr = udev_device_get_sysattr_value(conndev, "persistent_address"); port = udev_device_get_sysattr_value(conndev, "persistent_port"); if (addr == NULL || port == NULL) { parent = NULL; goto out; } format_lun_number(parent, &lun); path_prepend(path, "ip-%s:%s-iscsi-%s-%s", addr, port, target, lun); free(lun); out: udev_device_unref(sessiondev); udev_device_unref(conndev); return parent; } static struct udev_device *handle_scsi_ata(struct udev_device *parent, char **path) { struct udev *udev = udev_device_get_udev(parent); struct udev_device *targetdev; struct udev_device *target_parent; struct udev_device *atadev; const char *port_no; assert(parent); assert(path); targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host"); if (!targetdev) return NULL; target_parent = udev_device_get_parent(targetdev); if (!target_parent) return NULL; atadev = udev_device_new_from_subsystem_sysname(udev, "ata_port", udev_device_get_sysname(target_parent)); if (!atadev) return NULL; port_no = udev_device_get_sysattr_value(atadev, "port_no"); if (!port_no) { parent = NULL; goto out; } path_prepend(path, "ata-%s", port_no); out: udev_device_unref(atadev); return parent; } static struct udev_device *handle_scsi_default(struct udev_device *parent, char **path) { struct udev_device *hostdev; int host, bus, target, lun; const char *name; char *base; char *pos; DIR *dir; struct dirent *dent; int basenum; assert(parent); assert(path); hostdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host"); if (hostdev == NULL) return NULL; name = udev_device_get_sysname(parent); if (sscanf(name, "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4) return NULL; /* * Rebase host offset to get the local relative number * * Note: This is by definition racy, unreliable and too simple. * Please do not copy this model anywhere. It's just a left-over * from the time we had no idea how things should look like in * the end. * * Making assumptions about a global in-kernel counter and use * that to calculate a local offset is a very broken concept. It * can only work as long as things are in strict order. * * The kernel needs to export the instance/port number of a * controller directly, without the need for rebase magic like * this. Manual driver unbind/bind, parallel hotplug/unplug will * get into the way of this "I hope it works" logic. */ basenum = -1; base = strdup(udev_device_get_syspath(hostdev)); if (base == NULL) return NULL; pos = strrchr(base, '/'); if (pos == NULL) { parent = NULL; goto out; } pos[0] = '\0'; dir = opendir(base); if (dir == NULL) { parent = NULL; goto out; } for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { char *rest; int i; if (dent->d_name[0] == '.') continue; if (dent->d_type != DT_DIR && dent->d_type != DT_LNK) continue; if (!startswith(dent->d_name, "host")) continue; i = strtoul(&dent->d_name[4], &rest, 10); if (rest[0] != '\0') continue; /* * find the smallest number; the host really needs to export its * own instance number per parent device; relying on the global host * enumeration and plainly rebasing the numbers sounds unreliable */ if (basenum == -1 || i < basenum) basenum = i; } closedir(dir); if (basenum == -1) { parent = NULL; goto out; } host -= basenum; path_prepend(path, "scsi-%u:%u:%u:%u", host, bus, target, lun); out: free(base); return hostdev; } static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char **path) { struct udev_device *hostdev; struct udev_device *vmbusdev; const char *guid_str; char *lun = NULL; char guid[38]; size_t i, k; assert(parent); assert(path); hostdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host"); if (!hostdev) return NULL; vmbusdev = udev_device_get_parent(hostdev); if (!vmbusdev) return NULL; guid_str = udev_device_get_sysattr_value(vmbusdev, "device_id"); if (!guid_str) return NULL; if (strlen(guid_str) < 37 || guid_str[0] != '{' || guid_str[36] != '}') return NULL; for (i = 1, k = 0; i < 36; i++) { if (guid_str[i] == '-') continue; guid[k++] = guid_str[i]; } guid[k] = '\0'; format_lun_number(parent, &lun); path_prepend(path, "vmbus-%s-%s", guid, lun); free(lun); return parent; } static struct udev_device *handle_scsi(struct udev_device *parent, char **path, bool *supported_parent) { const char *devtype; const char *name; const char *id; devtype = udev_device_get_devtype(parent); if (devtype == NULL || !streq(devtype, "scsi_device")) return parent; /* firewire */ id = udev_device_get_sysattr_value(parent, "ieee1394_id"); if (id != NULL) { parent = skip_subsystem(parent, "scsi"); path_prepend(path, "ieee1394-0x%s", id); *supported_parent = true; goto out; } /* scsi sysfs does not have a "subsystem" for the transport */ name = udev_device_get_syspath(parent); if (strstr(name, "/rport-") != NULL) { parent = handle_scsi_fibre_channel(parent, path); *supported_parent = true; goto out; } if (strstr(name, "/end_device-") != NULL) { parent = handle_scsi_sas(parent, path); *supported_parent = true; goto out; } if (strstr(name, "/session") != NULL) { parent = handle_scsi_iscsi(parent, path); *supported_parent = true; goto out; } if (strstr(name, "/ata") != NULL) { parent = handle_scsi_ata(parent, path); goto out; } if (strstr(name, "/vmbus_") != NULL) { parent = handle_scsi_hyperv(parent, path); goto out; } parent = handle_scsi_default(parent, path); out: return parent; } static struct udev_device *handle_cciss(struct udev_device *parent, char **path) { const char *str; unsigned int controller, disk; str = udev_device_get_sysname(parent); if (sscanf(str, "c%ud%u%*s", &controller, &disk) != 2) return NULL; path_prepend(path, "cciss-disk%u", disk); parent = skip_subsystem(parent, "cciss"); return parent; } static void handle_scsi_tape(struct udev_device *dev, char **path) { const char *name; /* must be the last device in the syspath */ if (*path != NULL) return; name = udev_device_get_sysname(dev); if (startswith(name, "nst") && strchr("lma", name[3]) != NULL) path_prepend(path, "nst%c", name[3]); else if (startswith(name, "st") && strchr("lma", name[2]) != NULL) path_prepend(path, "st%c", name[2]); } static struct udev_device *handle_usb(struct udev_device *parent, char **path) { const char *devtype; const char *str; const char *port; devtype = udev_device_get_devtype(parent); if (devtype == NULL) return parent; if (!streq(devtype, "usb_interface") && !streq(devtype, "usb_device")) return parent; str = udev_device_get_sysname(parent); port = strchr(str, '-'); if (port == NULL) return parent; port++; parent = skip_subsystem(parent, "usb"); path_prepend(path, "usb-0:%s", port); return parent; } static struct udev_device *handle_bcma(struct udev_device *parent, char **path) { const char *sysname; unsigned int core; sysname = udev_device_get_sysname(parent); if (sscanf(sysname, "bcma%*u:%u", &core) != 1) return NULL; path_prepend(path, "bcma-%u", core); return parent; } /* Handle devices of AP bus in System z platform. */ static struct udev_device *handle_ap(struct udev_device *parent, char **path) { const char *type, *func; assert(parent); assert(path); type = udev_device_get_sysattr_value(parent, "type"); func = udev_device_get_sysattr_value(parent, "ap_functions"); if (type != NULL && func != NULL) { path_prepend(path, "ap-%s-%s", type, func); goto out; } path_prepend(path, "ap-%s", udev_device_get_sysname(parent)); out: parent = skip_subsystem(parent, "ap"); return parent; } static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool test) { struct udev_device *parent; char *path = NULL; bool supported_transport = false; bool supported_parent = false; assert(dev); /* walk up the chain of devices and compose path */ parent = dev; while (parent != NULL) { const char *subsys; subsys = udev_device_get_subsystem(parent); if (subsys == NULL) { ; } else if (streq(subsys, "scsi_tape")) { handle_scsi_tape(parent, &path); } else if (streq(subsys, "scsi")) { parent = handle_scsi(parent, &path, &supported_parent); supported_transport = true; } else if (streq(subsys, "cciss")) { parent = handle_cciss(parent, &path); supported_transport = true; } else if (streq(subsys, "usb")) { parent = handle_usb(parent, &path); supported_transport = true; } else if (streq(subsys, "bcma")) { parent = handle_bcma(parent, &path); supported_transport = true; } else if (streq(subsys, "serio")) { path_prepend(&path, "serio-%s", udev_device_get_sysnum(parent)); parent = skip_subsystem(parent, "serio"); } else if (streq(subsys, "pci")) { path_prepend(&path, "pci-%s", udev_device_get_sysname(parent)); parent = skip_subsystem(parent, "pci"); supported_parent = true; } else if (streq(subsys, "platform")) { path_prepend(&path, "platform-%s", udev_device_get_sysname(parent)); parent = skip_subsystem(parent, "platform"); supported_transport = true; supported_parent = true; } else if (streq(subsys, "acpi")) { path_prepend(&path, "acpi-%s", udev_device_get_sysname(parent)); parent = skip_subsystem(parent, "acpi"); supported_parent = true; } else if (streq(subsys, "xen")) { path_prepend(&path, "xen-%s", udev_device_get_sysname(parent)); parent = skip_subsystem(parent, "xen"); supported_parent = true; } else if (streq(subsys, "virtio")) { while (parent && streq_ptr("virtio", udev_device_get_subsystem(parent))) parent = udev_device_get_parent(parent); path_prepend(&path, "virtio-pci-%s", udev_device_get_sysname(parent)); supported_transport = true; supported_parent = true; } else if (streq(subsys, "scm")) { path_prepend(&path, "scm-%s", udev_device_get_sysname(parent)); parent = skip_subsystem(parent, "scm"); supported_transport = true; supported_parent = true; } else if (streq(subsys, "ccw")) { path_prepend(&path, "ccw-%s", udev_device_get_sysname(parent)); parent = skip_subsystem(parent, "ccw"); supported_transport = true; supported_parent = true; } else if (streq(subsys, "ccwgroup")) { path_prepend(&path, "ccwgroup-%s", udev_device_get_sysname(parent)); parent = skip_subsystem(parent, "ccwgroup"); supported_transport = true; supported_parent = true; } else if (streq(subsys, "ap")) { parent = handle_ap(parent, &path); supported_transport = true; supported_parent = true; } else if (streq(subsys, "iucv")) { path_prepend(&path, "iucv-%s", udev_device_get_sysname(parent)); parent = skip_subsystem(parent, "iucv"); supported_transport = true; supported_parent = true; } if (parent) parent = udev_device_get_parent(parent); } /* * Do not return devices with an unknown parent device type. They * might produce conflicting IDs if the parent does not provide a * unique and predictable name. */ if (!supported_parent) path = mfree(path); /* * Do not return block devices without a well-known transport. Some * devices do not expose their buses and do not provide a unique * and predictable name that way. */ if (streq(udev_device_get_subsystem(dev), "block") && !supported_transport) path = mfree(path); if (path != NULL) { char tag[UTIL_NAME_SIZE]; size_t i; const char *p; /* compose valid udev tag name */ for (p = path, i = 0; *p; p++) { if ((*p >= '0' && *p <= '9') || (*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || *p == '-') { tag[i++] = *p; continue; } /* skip all leading '_' */ if (i == 0) continue; /* avoid second '_' */ if (tag[i-1] == '_') continue; tag[i++] = '_'; } /* strip trailing '_' */ while (i > 0 && tag[i-1] == '_') i--; tag[i] = '\0'; udev_builtin_add_property(dev, test, "ID_PATH", path); udev_builtin_add_property(dev, test, "ID_PATH_TAG", tag); free(path); return EXIT_SUCCESS; } return EXIT_FAILURE; } const struct udev_builtin udev_builtin_path_id = { .name = "path_id", .cmd = builtin_path_id, .help = "Compose persistent device path", .run_once = true, }; systemd-229/src/udev/udev-builtin-uaccess.c000066400000000000000000000052741265713322000210220ustar00rootroot00000000000000/* * manage device node user ACL * * Copyright 2010-2012 Kay Sievers * Copyright 2010 Lennart Poettering * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include "sd-login.h" #include "login-util.h" #include "logind-acl.h" #include "udev.h" #include "util.h" static int builtin_uaccess(struct udev_device *dev, int argc, char *argv[], bool test) { int r; const char *path = NULL, *seat; bool changed_acl = false; uid_t uid; umask(0022); /* don't muck around with ACLs when the system is not running systemd */ if (!logind_running()) return 0; path = udev_device_get_devnode(dev); seat = udev_device_get_property_value(dev, "ID_SEAT"); if (!seat) seat = "seat0"; r = sd_seat_get_active(seat, NULL, &uid); if (r == -ENXIO || r == -ENODATA) { /* No active session on this seat */ r = 0; goto finish; } else if (r < 0) { log_error("Failed to determine active user on seat %s.", seat); goto finish; } r = devnode_acl(path, true, false, 0, true, uid); if (r < 0) { log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to apply ACL on %s: %m", path); goto finish; } changed_acl = true; r = 0; finish: if (path && !changed_acl) { int k; /* Better be safe than sorry and reset ACL */ k = devnode_acl(path, true, false, 0, false, 0); if (k < 0) { log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to apply ACL on %s: %m", path); if (r >= 0) r = k; } } return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } const struct udev_builtin udev_builtin_uaccess = { .name = "uaccess", .cmd = builtin_uaccess, .help = "Manage device node user ACL", }; systemd-229/src/udev/udev-builtin-usb_id.c000066400000000000000000000431001265713322000206270ustar00rootroot00000000000000/* * USB device properties and persistent device path * * Copyright (c) 2005 SUSE Linux Products GmbH, Germany * Author: Hannes Reinecke * * Copyright (C) 2005-2011 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "string-util.h" #include "udev.h" static void set_usb_iftype(char *to, int if_class_num, size_t len) { const char *type = "generic"; switch (if_class_num) { case 1: type = "audio"; break; case 2: /* CDC-Control */ break; case 3: type = "hid"; break; case 5: /* Physical */ break; case 6: type = "media"; break; case 7: type = "printer"; break; case 8: type = "storage"; break; case 9: type = "hub"; break; case 0x0a: /* CDC-Data */ break; case 0x0b: /* Chip/Smart Card */ break; case 0x0d: /* Content Security */ break; case 0x0e: type = "video"; break; case 0xdc: /* Diagnostic Device */ break; case 0xe0: /* Wireless Controller */ break; case 0xfe: /* Application-specific */ break; case 0xff: /* Vendor-specific */ break; default: break; } strncpy(to, type, len); to[len-1] = '\0'; } static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len) { int type_num = 0; char *eptr; const char *type = "generic"; type_num = strtoul(from, &eptr, 0); if (eptr != from) { switch (type_num) { case 1: /* RBC devices */ type = "rbc"; break; case 2: type = "atapi"; break; case 3: type = "tape"; break; case 4: /* UFI */ type = "floppy"; break; case 6: /* Transparent SPC-2 devices */ type = "scsi"; break; default: break; } } strscpy(to, len, type); return type_num; } static void set_scsi_type(char *to, const char *from, size_t len) { int type_num; char *eptr; const char *type = "generic"; type_num = strtoul(from, &eptr, 0); if (eptr != from) { switch (type_num) { case 0: case 0xe: type = "disk"; break; case 1: type = "tape"; break; case 4: case 7: case 0xf: type = "optical"; break; case 5: type = "cd"; break; default: break; } } strscpy(to, len, type); } #define USB_DT_DEVICE 0x01 #define USB_DT_INTERFACE 0x04 static int dev_if_packed_info(struct udev_device *dev, char *ifs_str, size_t len) { _cleanup_free_ char *filename = NULL; _cleanup_close_ int fd = -1; ssize_t size; unsigned char buf[18 + 65535]; size_t pos = 0; unsigned strpos = 0; struct usb_interface_descriptor { uint8_t bLength; uint8_t bDescriptorType; uint8_t bInterfaceNumber; uint8_t bAlternateSetting; uint8_t bNumEndpoints; uint8_t bInterfaceClass; uint8_t bInterfaceSubClass; uint8_t bInterfaceProtocol; uint8_t iInterface; } _packed_; if (asprintf(&filename, "%s/descriptors", udev_device_get_syspath(dev)) < 0) return log_oom(); fd = open(filename, O_RDONLY|O_CLOEXEC); if (fd < 0) return log_debug_errno(errno, "Error opening USB device 'descriptors' file: %m"); size = read(fd, buf, sizeof(buf)); if (size < 18 || size == sizeof(buf)) return -EIO; ifs_str[0] = '\0'; while (pos + sizeof(struct usb_interface_descriptor) < (size_t) size && strpos + 7 < len - 2) { struct usb_interface_descriptor *desc; char if_str[8]; desc = (struct usb_interface_descriptor *) &buf[pos]; if (desc->bLength < 3) break; pos += desc->bLength; if (desc->bDescriptorType != USB_DT_INTERFACE) continue; if (snprintf(if_str, 8, ":%02x%02x%02x", desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol) != 7) continue; if (strstr(ifs_str, if_str) != NULL) continue; memcpy(&ifs_str[strpos], if_str, 8), strpos += 7; } if (strpos > 0) { ifs_str[strpos++] = ':'; ifs_str[strpos++] = '\0'; } return 0; } /* * A unique USB identification is generated like this: * * 1.) Get the USB device type from InterfaceClass and InterfaceSubClass * 2.) If the device type is 'Mass-Storage/SPC-2' or 'Mass-Storage/RBC', * use the SCSI vendor and model as USB-Vendor and USB-model. * 3.) Otherwise, use the USB manufacturer and product as * USB-Vendor and USB-model. Any non-printable characters * in those strings will be skipped; a slash '/' will be converted * into a full stop '.'. * 4.) If that fails, too, we will use idVendor and idProduct * as USB-Vendor and USB-model. * 5.) The USB identification is the USB-vendor and USB-model * string concatenated with an underscore '_'. * 6.) If the device supplies a serial number, this number * is concatenated with the identification with an underscore '_'. */ static int builtin_usb_id(struct udev_device *dev, int argc, char *argv[], bool test) { char vendor_str[64] = ""; char vendor_str_enc[256]; const char *vendor_id; char model_str[64] = ""; char model_str_enc[256]; const char *product_id; char serial_str[UTIL_NAME_SIZE] = ""; char packed_if_str[UTIL_NAME_SIZE] = ""; char revision_str[64] = ""; char type_str[64] = ""; char instance_str[64] = ""; const char *ifnum = NULL; const char *driver = NULL; char serial[256]; struct udev_device *dev_interface = NULL; struct udev_device *dev_usb = NULL; const char *if_class, *if_subclass; int if_class_num; int protocol = 0; size_t l; char *s; assert(dev); /* shortcut, if we are called directly for a "usb_device" type */ if (udev_device_get_devtype(dev) != NULL && streq(udev_device_get_devtype(dev), "usb_device")) { dev_if_packed_info(dev, packed_if_str, sizeof(packed_if_str)); dev_usb = dev; goto fallback; } /* usb interface directory */ dev_interface = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface"); if (dev_interface == NULL) { log_debug("unable to access usb_interface device of '%s'", udev_device_get_syspath(dev)); return EXIT_FAILURE; } ifnum = udev_device_get_sysattr_value(dev_interface, "bInterfaceNumber"); driver = udev_device_get_sysattr_value(dev_interface, "driver"); if_class = udev_device_get_sysattr_value(dev_interface, "bInterfaceClass"); if (!if_class) { log_debug("%s: cannot get bInterfaceClass attribute", udev_device_get_sysname(dev)); return EXIT_FAILURE; } if_class_num = strtoul(if_class, NULL, 16); if (if_class_num == 8) { /* mass storage */ if_subclass = udev_device_get_sysattr_value(dev_interface, "bInterfaceSubClass"); if (if_subclass != NULL) protocol = set_usb_mass_storage_ifsubtype(type_str, if_subclass, sizeof(type_str)-1); } else { set_usb_iftype(type_str, if_class_num, sizeof(type_str)-1); } log_debug("%s: if_class %d protocol %d", udev_device_get_syspath(dev_interface), if_class_num, protocol); /* usb device directory */ dev_usb = udev_device_get_parent_with_subsystem_devtype(dev_interface, "usb", "usb_device"); if (!dev_usb) { log_debug("unable to find parent 'usb' device of '%s'", udev_device_get_syspath(dev)); return EXIT_FAILURE; } /* all interfaces of the device in a single string */ dev_if_packed_info(dev_usb, packed_if_str, sizeof(packed_if_str)); /* mass storage : SCSI or ATAPI */ if (protocol == 6 || protocol == 2) { struct udev_device *dev_scsi; const char *scsi_model, *scsi_vendor, *scsi_type, *scsi_rev; int host, bus, target, lun; /* get scsi device */ dev_scsi = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device"); if (dev_scsi == NULL) { log_debug("unable to find parent 'scsi' device of '%s'", udev_device_get_syspath(dev)); goto fallback; } if (sscanf(udev_device_get_sysname(dev_scsi), "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4) { log_debug("invalid scsi device '%s'", udev_device_get_sysname(dev_scsi)); goto fallback; } /* Generic SPC-2 device */ scsi_vendor = udev_device_get_sysattr_value(dev_scsi, "vendor"); if (!scsi_vendor) { log_debug("%s: cannot get SCSI vendor attribute", udev_device_get_sysname(dev_scsi)); goto fallback; } udev_util_encode_string(scsi_vendor, vendor_str_enc, sizeof(vendor_str_enc)); util_replace_whitespace(scsi_vendor, vendor_str, sizeof(vendor_str)-1); util_replace_chars(vendor_str, NULL); scsi_model = udev_device_get_sysattr_value(dev_scsi, "model"); if (!scsi_model) { log_debug("%s: cannot get SCSI model attribute", udev_device_get_sysname(dev_scsi)); goto fallback; } udev_util_encode_string(scsi_model, model_str_enc, sizeof(model_str_enc)); util_replace_whitespace(scsi_model, model_str, sizeof(model_str)-1); util_replace_chars(model_str, NULL); scsi_type = udev_device_get_sysattr_value(dev_scsi, "type"); if (!scsi_type) { log_debug("%s: cannot get SCSI type attribute", udev_device_get_sysname(dev_scsi)); goto fallback; } set_scsi_type(type_str, scsi_type, sizeof(type_str)-1); scsi_rev = udev_device_get_sysattr_value(dev_scsi, "rev"); if (!scsi_rev) { log_debug("%s: cannot get SCSI revision attribute", udev_device_get_sysname(dev_scsi)); goto fallback; } util_replace_whitespace(scsi_rev, revision_str, sizeof(revision_str)-1); util_replace_chars(revision_str, NULL); /* * some broken devices have the same identifiers * for all luns, export the target:lun number */ sprintf(instance_str, "%d:%d", target, lun); } fallback: vendor_id = udev_device_get_sysattr_value(dev_usb, "idVendor"); product_id = udev_device_get_sysattr_value(dev_usb, "idProduct"); /* fallback to USB vendor & device */ if (vendor_str[0] == '\0') { const char *usb_vendor = NULL; usb_vendor = udev_device_get_sysattr_value(dev_usb, "manufacturer"); if (!usb_vendor) usb_vendor = vendor_id; if (!usb_vendor) { log_debug("No USB vendor information available"); return EXIT_FAILURE; } udev_util_encode_string(usb_vendor, vendor_str_enc, sizeof(vendor_str_enc)); util_replace_whitespace(usb_vendor, vendor_str, sizeof(vendor_str)-1); util_replace_chars(vendor_str, NULL); } if (model_str[0] == '\0') { const char *usb_model = NULL; usb_model = udev_device_get_sysattr_value(dev_usb, "product"); if (!usb_model) usb_model = product_id; if (!usb_model) return EXIT_FAILURE; udev_util_encode_string(usb_model, model_str_enc, sizeof(model_str_enc)); util_replace_whitespace(usb_model, model_str, sizeof(model_str)-1); util_replace_chars(model_str, NULL); } if (revision_str[0] == '\0') { const char *usb_rev; usb_rev = udev_device_get_sysattr_value(dev_usb, "bcdDevice"); if (usb_rev) { util_replace_whitespace(usb_rev, revision_str, sizeof(revision_str)-1); util_replace_chars(revision_str, NULL); } } if (serial_str[0] == '\0') { const char *usb_serial; usb_serial = udev_device_get_sysattr_value(dev_usb, "serial"); if (usb_serial) { const unsigned char *p; /* http://msdn.microsoft.com/en-us/library/windows/hardware/gg487321.aspx */ for (p = (unsigned char *)usb_serial; *p != '\0'; p++) if (*p < 0x20 || *p > 0x7f || *p == ',') { usb_serial = NULL; break; } } if (usb_serial) { util_replace_whitespace(usb_serial, serial_str, sizeof(serial_str)-1); util_replace_chars(serial_str, NULL); } } s = serial; l = strpcpyl(&s, sizeof(serial), vendor_str, "_", model_str, NULL); if (!isempty(serial_str)) l = strpcpyl(&s, l, "_", serial_str, NULL); if (!isempty(instance_str)) strpcpyl(&s, l, "-", instance_str, NULL); udev_builtin_add_property(dev, test, "ID_VENDOR", vendor_str); udev_builtin_add_property(dev, test, "ID_VENDOR_ENC", vendor_str_enc); udev_builtin_add_property(dev, test, "ID_VENDOR_ID", vendor_id); udev_builtin_add_property(dev, test, "ID_MODEL", model_str); udev_builtin_add_property(dev, test, "ID_MODEL_ENC", model_str_enc); udev_builtin_add_property(dev, test, "ID_MODEL_ID", product_id); udev_builtin_add_property(dev, test, "ID_REVISION", revision_str); udev_builtin_add_property(dev, test, "ID_SERIAL", serial); if (!isempty(serial_str)) udev_builtin_add_property(dev, test, "ID_SERIAL_SHORT", serial_str); if (!isempty(type_str)) udev_builtin_add_property(dev, test, "ID_TYPE", type_str); if (!isempty(instance_str)) udev_builtin_add_property(dev, test, "ID_INSTANCE", instance_str); udev_builtin_add_property(dev, test, "ID_BUS", "usb"); if (!isempty(packed_if_str)) udev_builtin_add_property(dev, test, "ID_USB_INTERFACES", packed_if_str); if (ifnum != NULL) udev_builtin_add_property(dev, test, "ID_USB_INTERFACE_NUM", ifnum); if (driver != NULL) udev_builtin_add_property(dev, test, "ID_USB_DRIVER", driver); return EXIT_SUCCESS; } const struct udev_builtin udev_builtin_usb_id = { .name = "usb_id", .cmd = builtin_usb_id, .help = "USB device properties", .run_once = true, }; systemd-229/src/udev/udev-builtin.c000066400000000000000000000102331265713322000173650ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2007-2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include "string-util.h" #include "udev.h" static bool initialized; static const struct udev_builtin *builtins[] = { #ifdef HAVE_BLKID [UDEV_BUILTIN_BLKID] = &udev_builtin_blkid, #endif [UDEV_BUILTIN_BTRFS] = &udev_builtin_btrfs, [UDEV_BUILTIN_HWDB] = &udev_builtin_hwdb, [UDEV_BUILTIN_INPUT_ID] = &udev_builtin_input_id, [UDEV_BUILTIN_KEYBOARD] = &udev_builtin_keyboard, #ifdef HAVE_KMOD [UDEV_BUILTIN_KMOD] = &udev_builtin_kmod, #endif [UDEV_BUILTIN_NET_ID] = &udev_builtin_net_id, [UDEV_BUILTIN_NET_LINK] = &udev_builtin_net_setup_link, [UDEV_BUILTIN_PATH_ID] = &udev_builtin_path_id, [UDEV_BUILTIN_USB_ID] = &udev_builtin_usb_id, #ifdef HAVE_ACL [UDEV_BUILTIN_UACCESS] = &udev_builtin_uaccess, #endif }; void udev_builtin_init(struct udev *udev) { unsigned int i; if (initialized) return; for (i = 0; i < ELEMENTSOF(builtins); i++) if (builtins[i] && builtins[i]->init) builtins[i]->init(udev); initialized = true; } void udev_builtin_exit(struct udev *udev) { unsigned int i; if (!initialized) return; for (i = 0; i < ELEMENTSOF(builtins); i++) if (builtins[i] && builtins[i]->exit) builtins[i]->exit(udev); initialized = false; } bool udev_builtin_validate(struct udev *udev) { unsigned int i; for (i = 0; i < ELEMENTSOF(builtins); i++) if (builtins[i] && builtins[i]->validate && builtins[i]->validate(udev)) return true; return false; } void udev_builtin_list(struct udev *udev) { unsigned int i; for (i = 0; i < ELEMENTSOF(builtins); i++) if (builtins[i]) fprintf(stderr, " %-14s %s\n", builtins[i]->name, builtins[i]->help); } const char *udev_builtin_name(enum udev_builtin_cmd cmd) { if (!builtins[cmd]) return NULL; return builtins[cmd]->name; } bool udev_builtin_run_once(enum udev_builtin_cmd cmd) { if (!builtins[cmd]) return false; return builtins[cmd]->run_once; } enum udev_builtin_cmd udev_builtin_lookup(const char *command) { char name[UTIL_PATH_SIZE]; enum udev_builtin_cmd i; char *pos; strscpy(name, sizeof(name), command); pos = strchr(name, ' '); if (pos) pos[0] = '\0'; for (i = 0; i < ELEMENTSOF(builtins); i++) if (builtins[i] && streq(builtins[i]->name, name)) return i; return UDEV_BUILTIN_MAX; } int udev_builtin_run(struct udev_device *dev, enum udev_builtin_cmd cmd, const char *command, bool test) { char arg[UTIL_PATH_SIZE]; int argc; char *argv[128]; if (!builtins[cmd]) return -EOPNOTSUPP; /* we need '0' here to reset the internal state */ optind = 0; strscpy(arg, sizeof(arg), command); udev_build_argv(udev_device_get_udev(dev), arg, &argc, argv); return builtins[cmd]->cmd(dev, argc, argv, test); } int udev_builtin_add_property(struct udev_device *dev, bool test, const char *key, const char *val) { udev_device_add_property(dev, key, val); if (test) printf("%s=%s\n", key, val); return 0; } systemd-229/src/udev/udev-ctrl.c000066400000000000000000000334041265713322000166700ustar00rootroot00000000000000/* * libudev - interface to udev device information * * Copyright (C) 2008 Kay Sievers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. */ #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "socket-util.h" #include "udev.h" /* wire protocol magic must match */ #define UDEV_CTRL_MAGIC 0xdead1dea enum udev_ctrl_msg_type { UDEV_CTRL_UNKNOWN, UDEV_CTRL_SET_LOG_LEVEL, UDEV_CTRL_STOP_EXEC_QUEUE, UDEV_CTRL_START_EXEC_QUEUE, UDEV_CTRL_RELOAD, UDEV_CTRL_SET_ENV, UDEV_CTRL_SET_CHILDREN_MAX, UDEV_CTRL_PING, UDEV_CTRL_EXIT, }; struct udev_ctrl_msg_wire { char version[16]; unsigned int magic; enum udev_ctrl_msg_type type; union { int intval; char buf[256]; }; }; struct udev_ctrl_msg { int refcount; struct udev_ctrl_connection *conn; struct udev_ctrl_msg_wire ctrl_msg_wire; }; struct udev_ctrl { int refcount; struct udev *udev; int sock; union sockaddr_union saddr; socklen_t addrlen; bool bound; bool cleanup_socket; bool connected; }; struct udev_ctrl_connection { int refcount; struct udev_ctrl *uctrl; int sock; }; struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd) { struct udev_ctrl *uctrl; const int on = 1; int r; uctrl = new0(struct udev_ctrl, 1); if (uctrl == NULL) return NULL; uctrl->refcount = 1; uctrl->udev = udev; if (fd < 0) { uctrl->sock = socket(AF_LOCAL, SOCK_SEQPACKET|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); if (uctrl->sock < 0) { log_error_errno(errno, "error getting socket: %m"); udev_ctrl_unref(uctrl); return NULL; } } else { uctrl->bound = true; uctrl->sock = fd; } /* * FIXME: remove it as soon as we can depend on this: * http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=90c6bd34f884cd9cee21f1d152baf6c18bcac949 */ r = setsockopt(uctrl->sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); if (r < 0) log_warning_errno(errno, "could not set SO_PASSCRED: %m"); uctrl->saddr.un.sun_family = AF_LOCAL; strscpy(uctrl->saddr.un.sun_path, sizeof(uctrl->saddr.un.sun_path), "/run/udev/control"); uctrl->addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(uctrl->saddr.un.sun_path); return uctrl; } struct udev_ctrl *udev_ctrl_new(struct udev *udev) { return udev_ctrl_new_from_fd(udev, -1); } int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl) { int err; if (!uctrl->bound) { err = bind(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen); if (err < 0 && errno == EADDRINUSE) { unlink(uctrl->saddr.un.sun_path); err = bind(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen); } if (err < 0) return log_error_errno(errno, "bind failed: %m"); err = listen(uctrl->sock, 0); if (err < 0) return log_error_errno(errno, "listen failed: %m"); uctrl->bound = true; uctrl->cleanup_socket = true; } return 0; } struct udev *udev_ctrl_get_udev(struct udev_ctrl *uctrl) { return uctrl->udev; } static struct udev_ctrl *udev_ctrl_ref(struct udev_ctrl *uctrl) { if (uctrl) uctrl->refcount++; return uctrl; } struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl) { if (uctrl && -- uctrl->refcount == 0) { if (uctrl->sock >= 0) close(uctrl->sock); free(uctrl); } return NULL; } int udev_ctrl_cleanup(struct udev_ctrl *uctrl) { if (uctrl == NULL) return 0; if (uctrl->cleanup_socket) unlink(uctrl->saddr.un.sun_path); return 0; } int udev_ctrl_get_fd(struct udev_ctrl *uctrl) { if (uctrl == NULL) return -EINVAL; return uctrl->sock; } struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) { struct udev_ctrl_connection *conn; struct ucred ucred = {}; const int on = 1; int r; conn = new(struct udev_ctrl_connection, 1); if (conn == NULL) return NULL; conn->refcount = 1; conn->uctrl = uctrl; conn->sock = accept4(uctrl->sock, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK); if (conn->sock < 0) { if (errno != EINTR) log_error_errno(errno, "unable to receive ctrl connection: %m"); goto err; } /* check peer credential of connection */ r = getpeercred(conn->sock, &ucred); if (r < 0) { log_error_errno(r, "unable to receive credentials of ctrl connection: %m"); goto err; } if (ucred.uid > 0) { log_error("sender uid="UID_FMT", message ignored", ucred.uid); goto err; } /* enable receiving of the sender credentials in the messages */ r = setsockopt(conn->sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); if (r < 0) log_warning_errno(errno, "could not set SO_PASSCRED: %m"); udev_ctrl_ref(uctrl); return conn; err: if (conn->sock >= 0) close(conn->sock); free(conn); return NULL; } struct udev_ctrl_connection *udev_ctrl_connection_ref(struct udev_ctrl_connection *conn) { if (conn == NULL) return NULL; conn->refcount++; return conn; } struct udev_ctrl_connection *udev_ctrl_connection_unref(struct udev_ctrl_connection *conn) { if (conn && -- conn->refcount == 0) { if (conn->sock >= 0) close(conn->sock); udev_ctrl_unref(conn->uctrl); free(conn); } return NULL; } static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, int timeout) { struct udev_ctrl_msg_wire ctrl_msg_wire; int err = 0; memzero(&ctrl_msg_wire, sizeof(struct udev_ctrl_msg_wire)); strcpy(ctrl_msg_wire.version, "udev-" VERSION); ctrl_msg_wire.magic = UDEV_CTRL_MAGIC; ctrl_msg_wire.type = type; if (buf != NULL) strscpy(ctrl_msg_wire.buf, sizeof(ctrl_msg_wire.buf), buf); else ctrl_msg_wire.intval = intval; if (!uctrl->connected) { if (connect(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen) < 0) { err = -errno; goto out; } uctrl->connected = true; } if (send(uctrl->sock, &ctrl_msg_wire, sizeof(ctrl_msg_wire), 0) < 0) { err = -errno; goto out; } /* wait for peer message handling or disconnect */ for (;;) { struct pollfd pfd[1]; int r; pfd[0].fd = uctrl->sock; pfd[0].events = POLLIN; r = poll(pfd, 1, timeout * MSEC_PER_SEC); if (r < 0) { if (errno == EINTR) continue; err = -errno; break; } if (r > 0 && pfd[0].revents & POLLERR) { err = -EIO; break; } if (r == 0) err = -ETIMEDOUT; break; } out: return err; } int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout) { return ctrl_send(uctrl, UDEV_CTRL_SET_LOG_LEVEL, priority, NULL, timeout); } int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout) { return ctrl_send(uctrl, UDEV_CTRL_STOP_EXEC_QUEUE, 0, NULL, timeout); } int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout) { return ctrl_send(uctrl, UDEV_CTRL_START_EXEC_QUEUE, 0, NULL, timeout); } int udev_ctrl_send_reload(struct udev_ctrl *uctrl, int timeout) { return ctrl_send(uctrl, UDEV_CTRL_RELOAD, 0, NULL, timeout); } int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout) { return ctrl_send(uctrl, UDEV_CTRL_SET_ENV, 0, key, timeout); } int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout) { return ctrl_send(uctrl, UDEV_CTRL_SET_CHILDREN_MAX, count, NULL, timeout); } int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout) { return ctrl_send(uctrl, UDEV_CTRL_PING, 0, NULL, timeout); } int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout) { return ctrl_send(uctrl, UDEV_CTRL_EXIT, 0, NULL, timeout); } struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn) { struct udev_ctrl_msg *uctrl_msg; ssize_t size; struct cmsghdr *cmsg; struct iovec iov; char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; struct msghdr smsg = { .msg_iov = &iov, .msg_iovlen = 1, .msg_control = cred_msg, .msg_controllen = sizeof(cred_msg), }; struct ucred *cred; uctrl_msg = new0(struct udev_ctrl_msg, 1); if (uctrl_msg == NULL) return NULL; uctrl_msg->refcount = 1; uctrl_msg->conn = conn; udev_ctrl_connection_ref(conn); /* wait for the incoming message */ for (;;) { struct pollfd pfd[1]; int r; pfd[0].fd = conn->sock; pfd[0].events = POLLIN; r = poll(pfd, 1, 10000); if (r < 0) { if (errno == EINTR) continue; goto err; } else if (r == 0) { log_error("timeout waiting for ctrl message"); goto err; } else { if (!(pfd[0].revents & POLLIN)) { log_error_errno(errno, "ctrl connection error: %m"); goto err; } } break; } iov.iov_base = &uctrl_msg->ctrl_msg_wire; iov.iov_len = sizeof(struct udev_ctrl_msg_wire); size = recvmsg(conn->sock, &smsg, 0); if (size < 0) { log_error_errno(errno, "unable to receive ctrl message: %m"); goto err; } cmsg_close_all(&smsg); cmsg = CMSG_FIRSTHDR(&smsg); if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { log_error("no sender credentials received, message ignored"); goto err; } cred = (struct ucred *) CMSG_DATA(cmsg); if (cred->uid != 0) { log_error("sender uid="UID_FMT", message ignored", cred->uid); goto err; } if (uctrl_msg->ctrl_msg_wire.magic != UDEV_CTRL_MAGIC) { log_error("message magic 0x%08x doesn't match, ignore it", uctrl_msg->ctrl_msg_wire.magic); goto err; } return uctrl_msg; err: udev_ctrl_msg_unref(uctrl_msg); return NULL; } struct udev_ctrl_msg *udev_ctrl_msg_unref(struct udev_ctrl_msg *ctrl_msg) { if (ctrl_msg && -- ctrl_msg->refcount == 0) { udev_ctrl_connection_unref(ctrl_msg->conn); free(ctrl_msg); } return NULL; } int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg) { if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_LOG_LEVEL) return ctrl_msg->ctrl_msg_wire.intval; return -1; } int udev_ctrl_get_stop_exec_queue(struct udev_ctrl_msg *ctrl_msg) { if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_STOP_EXEC_QUEUE) return 1; return -1; } int udev_ctrl_get_start_exec_queue(struct udev_ctrl_msg *ctrl_msg) { if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_START_EXEC_QUEUE) return 1; return -1; } int udev_ctrl_get_reload(struct udev_ctrl_msg *ctrl_msg) { if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_RELOAD) return 1; return -1; } const char *udev_ctrl_get_set_env(struct udev_ctrl_msg *ctrl_msg) { if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_ENV) return ctrl_msg->ctrl_msg_wire.buf; return NULL; } int udev_ctrl_get_set_children_max(struct udev_ctrl_msg *ctrl_msg) { if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_CHILDREN_MAX) return ctrl_msg->ctrl_msg_wire.intval; return -1; } int udev_ctrl_get_ping(struct udev_ctrl_msg *ctrl_msg) { if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_PING) return 1; return -1; } int udev_ctrl_get_exit(struct udev_ctrl_msg *ctrl_msg) { if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_EXIT) return 1; return -1; } systemd-229/src/udev/udev-event.c000066400000000000000000001111331265713322000170410ustar00rootroot00000000000000/* * Copyright (C) 2003-2013 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "netlink-util.h" #include "process-util.h" #include "signal-util.h" #include "string-util.h" #include "udev.h" typedef struct Spawn { const char *cmd; pid_t pid; usec_t timeout_warn; usec_t timeout; bool accept_failure; } Spawn; struct udev_event *udev_event_new(struct udev_device *dev) { struct udev *udev = udev_device_get_udev(dev); struct udev_event *event; event = new0(struct udev_event, 1); if (event == NULL) return NULL; event->dev = dev; event->udev = udev; udev_list_init(udev, &event->run_list, false); udev_list_init(udev, &event->seclabel_list, false); event->birth_usec = clock_boottime_or_monotonic(); return event; } void udev_event_unref(struct udev_event *event) { if (event == NULL) return; sd_netlink_unref(event->rtnl); udev_list_cleanup(&event->run_list); udev_list_cleanup(&event->seclabel_list); free(event->program_result); free(event->name); free(event); } size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size) { struct udev_device *dev = event->dev; enum subst_type { SUBST_UNKNOWN, SUBST_DEVNODE, SUBST_ATTR, SUBST_ENV, SUBST_KERNEL, SUBST_KERNEL_NUMBER, SUBST_DRIVER, SUBST_DEVPATH, SUBST_ID, SUBST_MAJOR, SUBST_MINOR, SUBST_RESULT, SUBST_PARENT, SUBST_NAME, SUBST_LINKS, SUBST_ROOT, SUBST_SYS, }; static const struct subst_map { const char *name; const char fmt; enum subst_type type; } map[] = { { .name = "devnode", .fmt = 'N', .type = SUBST_DEVNODE }, { .name = "tempnode", .fmt = 'N', .type = SUBST_DEVNODE }, { .name = "attr", .fmt = 's', .type = SUBST_ATTR }, { .name = "sysfs", .fmt = 's', .type = SUBST_ATTR }, { .name = "env", .fmt = 'E', .type = SUBST_ENV }, { .name = "kernel", .fmt = 'k', .type = SUBST_KERNEL }, { .name = "number", .fmt = 'n', .type = SUBST_KERNEL_NUMBER }, { .name = "driver", .fmt = 'd', .type = SUBST_DRIVER }, { .name = "devpath", .fmt = 'p', .type = SUBST_DEVPATH }, { .name = "id", .fmt = 'b', .type = SUBST_ID }, { .name = "major", .fmt = 'M', .type = SUBST_MAJOR }, { .name = "minor", .fmt = 'm', .type = SUBST_MINOR }, { .name = "result", .fmt = 'c', .type = SUBST_RESULT }, { .name = "parent", .fmt = 'P', .type = SUBST_PARENT }, { .name = "name", .fmt = 'D', .type = SUBST_NAME }, { .name = "links", .fmt = 'L', .type = SUBST_LINKS }, { .name = "root", .fmt = 'r', .type = SUBST_ROOT }, { .name = "sys", .fmt = 'S', .type = SUBST_SYS }, }; const char *from; char *s; size_t l; assert(dev); from = src; s = dest; l = size; for (;;) { enum subst_type type = SUBST_UNKNOWN; char attrbuf[UTIL_PATH_SIZE]; char *attr = NULL; while (from[0] != '\0') { if (from[0] == '$') { /* substitute named variable */ unsigned int i; if (from[1] == '$') { from++; goto copy; } for (i = 0; i < ELEMENTSOF(map); i++) { if (startswith(&from[1], map[i].name)) { type = map[i].type; from += strlen(map[i].name)+1; goto subst; } } } else if (from[0] == '%') { /* substitute format char */ unsigned int i; if (from[1] == '%') { from++; goto copy; } for (i = 0; i < ELEMENTSOF(map); i++) { if (from[1] == map[i].fmt) { type = map[i].type; from += 2; goto subst; } } } copy: /* copy char */ if (l == 0) goto out; s[0] = from[0]; from++; s++; l--; } goto out; subst: /* extract possible $format{attr} */ if (from[0] == '{') { unsigned int i; from++; for (i = 0; from[i] != '}'; i++) { if (from[i] == '\0') { log_error("missing closing brace for format '%s'", src); goto out; } } if (i >= sizeof(attrbuf)) goto out; memcpy(attrbuf, from, i); attrbuf[i] = '\0'; from += i+1; attr = attrbuf; } else { attr = NULL; } switch (type) { case SUBST_DEVPATH: l = strpcpy(&s, l, udev_device_get_devpath(dev)); break; case SUBST_KERNEL: l = strpcpy(&s, l, udev_device_get_sysname(dev)); break; case SUBST_KERNEL_NUMBER: if (udev_device_get_sysnum(dev) == NULL) break; l = strpcpy(&s, l, udev_device_get_sysnum(dev)); break; case SUBST_ID: if (event->dev_parent == NULL) break; l = strpcpy(&s, l, udev_device_get_sysname(event->dev_parent)); break; case SUBST_DRIVER: { const char *driver; if (event->dev_parent == NULL) break; driver = udev_device_get_driver(event->dev_parent); if (driver == NULL) break; l = strpcpy(&s, l, driver); break; } case SUBST_MAJOR: { char num[UTIL_PATH_SIZE]; sprintf(num, "%u", major(udev_device_get_devnum(dev))); l = strpcpy(&s, l, num); break; } case SUBST_MINOR: { char num[UTIL_PATH_SIZE]; sprintf(num, "%u", minor(udev_device_get_devnum(dev))); l = strpcpy(&s, l, num); break; } case SUBST_RESULT: { char *rest; int i; if (event->program_result == NULL) break; /* get part part of the result string */ i = 0; if (attr != NULL) i = strtoul(attr, &rest, 10); if (i > 0) { char result[UTIL_PATH_SIZE]; char tmp[UTIL_PATH_SIZE]; char *cpos; strscpy(result, sizeof(result), event->program_result); cpos = result; while (--i) { while (cpos[0] != '\0' && !isspace(cpos[0])) cpos++; while (isspace(cpos[0])) cpos++; if (cpos[0] == '\0') break; } if (i > 0) { log_error("requested part of result string not found"); break; } strscpy(tmp, sizeof(tmp), cpos); /* %{2+}c copies the whole string from the second part on */ if (rest[0] != '+') { cpos = strchr(tmp, ' '); if (cpos) cpos[0] = '\0'; } l = strpcpy(&s, l, tmp); } else { l = strpcpy(&s, l, event->program_result); } break; } case SUBST_ATTR: { const char *value = NULL; char vbuf[UTIL_NAME_SIZE]; size_t len; int count; if (attr == NULL) { log_error("missing file parameter for attr"); break; } /* try to read the value specified by "[dmi/id]product_name" */ if (util_resolve_subsys_kernel(event->udev, attr, vbuf, sizeof(vbuf), 1) == 0) value = vbuf; /* try to read the attribute the device */ if (value == NULL) value = udev_device_get_sysattr_value(event->dev, attr); /* try to read the attribute of the parent device, other matches have selected */ if (value == NULL && event->dev_parent != NULL && event->dev_parent != event->dev) value = udev_device_get_sysattr_value(event->dev_parent, attr); if (value == NULL) break; /* strip trailing whitespace, and replace unwanted characters */ if (value != vbuf) strscpy(vbuf, sizeof(vbuf), value); len = strlen(vbuf); while (len > 0 && isspace(vbuf[--len])) vbuf[len] = '\0'; count = util_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT); if (count > 0) log_debug("%i character(s) replaced" , count); l = strpcpy(&s, l, vbuf); break; } case SUBST_PARENT: { struct udev_device *dev_parent; const char *devnode; dev_parent = udev_device_get_parent(event->dev); if (dev_parent == NULL) break; devnode = udev_device_get_devnode(dev_parent); if (devnode != NULL) l = strpcpy(&s, l, devnode + strlen("/dev/")); break; } case SUBST_DEVNODE: if (udev_device_get_devnode(dev) != NULL) l = strpcpy(&s, l, udev_device_get_devnode(dev)); break; case SUBST_NAME: if (event->name != NULL) l = strpcpy(&s, l, event->name); else if (udev_device_get_devnode(dev) != NULL) l = strpcpy(&s, l, udev_device_get_devnode(dev) + strlen("/dev/")); else l = strpcpy(&s, l, udev_device_get_sysname(dev)); break; case SUBST_LINKS: { struct udev_list_entry *list_entry; list_entry = udev_device_get_devlinks_list_entry(dev); if (list_entry == NULL) break; l = strpcpy(&s, l, udev_list_entry_get_name(list_entry) + strlen("/dev/")); udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry)) l = strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry) + strlen("/dev/"), NULL); break; } case SUBST_ROOT: l = strpcpy(&s, l, "/dev"); break; case SUBST_SYS: l = strpcpy(&s, l, "/sys"); break; case SUBST_ENV: if (attr == NULL) { break; } else { const char *value; value = udev_device_get_property_value(event->dev, attr); if (value == NULL) break; l = strpcpy(&s, l, value); break; } default: log_error("unknown substitution type=%i", type); break; } } out: s[0] = '\0'; return l; } static int spawn_exec(struct udev_event *event, const char *cmd, char *const argv[], char **envp, int fd_stdout, int fd_stderr) { _cleanup_close_ int fd = -1; int r; /* discard child output or connect to pipe */ fd = open("/dev/null", O_RDWR); if (fd >= 0) { r = dup2(fd, STDIN_FILENO); if (r < 0) log_warning_errno(errno, "redirecting stdin failed: %m"); if (fd_stdout < 0) { r = dup2(fd, STDOUT_FILENO); if (r < 0) log_warning_errno(errno, "redirecting stdout failed: %m"); } if (fd_stderr < 0) { r = dup2(fd, STDERR_FILENO); if (r < 0) log_warning_errno(errno, "redirecting stderr failed: %m"); } } else log_warning_errno(errno, "open /dev/null failed: %m"); /* connect pipes to std{out,err} */ if (fd_stdout >= 0) { r = dup2(fd_stdout, STDOUT_FILENO); if (r < 0) log_warning_errno(errno, "redirecting stdout failed: %m"); fd_stdout = safe_close(fd_stdout); } if (fd_stderr >= 0) { r = dup2(fd_stderr, STDERR_FILENO); if (r < 0) log_warning_errno(errno, "redirecting stdout failed: %m"); fd_stderr = safe_close(fd_stderr); } /* terminate child in case parent goes away */ prctl(PR_SET_PDEATHSIG, SIGTERM); /* restore sigmask before exec */ (void) reset_signal_mask(); execve(argv[0], argv, envp); /* exec failed */ return log_error_errno(errno, "failed to execute '%s' '%s': %m", argv[0], cmd); } static void spawn_read(struct udev_event *event, usec_t timeout_usec, const char *cmd, int fd_stdout, int fd_stderr, char *result, size_t ressize) { _cleanup_close_ int fd_ep = -1; struct epoll_event ep_outpipe = { .events = EPOLLIN, .data.ptr = &fd_stdout, }; struct epoll_event ep_errpipe = { .events = EPOLLIN, .data.ptr = &fd_stderr, }; size_t respos = 0; int r; /* read from child if requested */ if (fd_stdout < 0 && fd_stderr < 0) return; fd_ep = epoll_create1(EPOLL_CLOEXEC); if (fd_ep < 0) { log_error_errno(errno, "error creating epoll fd: %m"); return; } if (fd_stdout >= 0) { r = epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_stdout, &ep_outpipe); if (r < 0) { log_error_errno(errno, "fail to add stdout fd to epoll: %m"); return; } } if (fd_stderr >= 0) { r = epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_stderr, &ep_errpipe); if (r < 0) { log_error_errno(errno, "fail to add stderr fd to epoll: %m"); return; } } /* read child output */ while (fd_stdout >= 0 || fd_stderr >= 0) { int timeout; int fdcount; struct epoll_event ev[4]; int i; if (timeout_usec > 0) { usec_t age_usec; age_usec = clock_boottime_or_monotonic() - event->birth_usec; if (age_usec >= timeout_usec) { log_error("timeout '%s'", cmd); return; } timeout = ((timeout_usec - age_usec) / USEC_PER_MSEC) + MSEC_PER_SEC; } else { timeout = -1; } fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), timeout); if (fdcount < 0) { if (errno == EINTR) continue; log_error_errno(errno, "failed to poll: %m"); return; } else if (fdcount == 0) { log_error("timeout '%s'", cmd); return; } for (i = 0; i < fdcount; i++) { int *fd = (int *)ev[i].data.ptr; if (*fd < 0) continue; if (ev[i].events & EPOLLIN) { ssize_t count; char buf[4096]; count = read(*fd, buf, sizeof(buf)-1); if (count <= 0) continue; buf[count] = '\0'; /* store stdout result */ if (result != NULL && *fd == fd_stdout) { if (respos + count < ressize) { memcpy(&result[respos], buf, count); respos += count; } else { log_error("'%s' ressize %zu too short", cmd, ressize); } } /* log debug output only if we watch stderr */ if (fd_stderr >= 0) { char *pos; char *line; pos = buf; while ((line = strsep(&pos, "\n"))) { if (pos != NULL || line[0] != '\0') log_debug("'%s'(%s) '%s'", cmd, *fd == fd_stdout ? "out" : "err" , line); } } } else if (ev[i].events & EPOLLHUP) { r = epoll_ctl(fd_ep, EPOLL_CTL_DEL, *fd, NULL); if (r < 0) { log_error_errno(errno, "failed to remove fd from epoll: %m"); return; } *fd = -1; } } } /* return the child's stdout string */ if (result != NULL) result[respos] = '\0'; } static int on_spawn_timeout(sd_event_source *s, uint64_t usec, void *userdata) { Spawn *spawn = userdata; char timeout[FORMAT_TIMESTAMP_RELATIVE_MAX]; assert(spawn); kill_and_sigcont(spawn->pid, SIGKILL); log_error("spawned process '%s' ["PID_FMT"] timed out after %s, killing", spawn->cmd, spawn->pid, format_timestamp_relative(timeout, sizeof(timeout), spawn->timeout)); return 1; } static int on_spawn_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) { Spawn *spawn = userdata; char timeout[FORMAT_TIMESTAMP_RELATIVE_MAX]; assert(spawn); log_warning("spawned process '%s' ["PID_FMT"] is taking longer than %s to complete", spawn->cmd, spawn->pid, format_timestamp_relative(timeout, sizeof(timeout), spawn->timeout)); return 1; } static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) { Spawn *spawn = userdata; assert(spawn); switch (si->si_code) { case CLD_EXITED: if (si->si_status == 0) { log_debug("Process '%s' succeeded.", spawn->cmd); sd_event_exit(sd_event_source_get_event(s), 0); return 1; } else if (spawn->accept_failure) log_debug("Process '%s' failed with exit code %i.", spawn->cmd, si->si_status); else log_warning("Process '%s' failed with exit code %i.", spawn->cmd, si->si_status); break; case CLD_KILLED: case CLD_DUMPED: log_warning("Process '%s' terminated by signal %s.", spawn->cmd, signal_to_string(si->si_status)); break; default: log_error("Process '%s' failed due to unknown reason.", spawn->cmd); } sd_event_exit(sd_event_source_get_event(s), -EIO); return 1; } static int spawn_wait(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const char *cmd, pid_t pid, bool accept_failure) { Spawn spawn = { .cmd = cmd, .pid = pid, .accept_failure = accept_failure, }; _cleanup_(sd_event_unrefp) sd_event *e = NULL; int r, ret; r = sd_event_new(&e); if (r < 0) return r; if (timeout_usec > 0) { usec_t usec, age_usec; usec = now(clock_boottime_or_monotonic()); age_usec = usec - event->birth_usec; if (age_usec < timeout_usec) { if (timeout_warn_usec > 0 && timeout_warn_usec < timeout_usec && age_usec < timeout_warn_usec) { spawn.timeout_warn = timeout_warn_usec - age_usec; r = sd_event_add_time(e, NULL, clock_boottime_or_monotonic(), usec + spawn.timeout_warn, USEC_PER_SEC, on_spawn_timeout_warning, &spawn); if (r < 0) return r; } spawn.timeout = timeout_usec - age_usec; r = sd_event_add_time(e, NULL, clock_boottime_or_monotonic(), usec + spawn.timeout, USEC_PER_SEC, on_spawn_timeout, &spawn); if (r < 0) return r; } } r = sd_event_add_child(e, NULL, pid, WEXITED, on_spawn_sigchld, &spawn); if (r < 0) return r; r = sd_event_loop(e); if (r < 0) return r; r = sd_event_get_exit_code(e, &ret); if (r < 0) return r; return ret; } int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]) { int i = 0; char *pos; if (strchr(cmd, ' ') == NULL) { argv[i++] = cmd; goto out; } pos = cmd; while (pos != NULL && pos[0] != '\0') { if (pos[0] == '\'') { /* do not separate quotes */ pos++; argv[i] = strsep(&pos, "\'"); if (pos != NULL) while (pos[0] == ' ') pos++; } else { argv[i] = strsep(&pos, " "); if (pos != NULL) while (pos[0] == ' ') pos++; } i++; } out: argv[i] = NULL; if (argc) *argc = i; return 0; } int udev_event_spawn(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, bool accept_failure, const char *cmd, char *result, size_t ressize) { int outpipe[2] = {-1, -1}; int errpipe[2] = {-1, -1}; pid_t pid; int err = 0; /* pipes from child to parent */ if (result != NULL || log_get_max_level() >= LOG_INFO) { if (pipe2(outpipe, O_NONBLOCK) != 0) { err = log_error_errno(errno, "pipe failed: %m"); goto out; } } if (log_get_max_level() >= LOG_INFO) { if (pipe2(errpipe, O_NONBLOCK) != 0) { err = log_error_errno(errno, "pipe failed: %m"); goto out; } } pid = fork(); switch(pid) { case 0: { char arg[UTIL_PATH_SIZE]; char *argv[128]; char program[UTIL_PATH_SIZE]; /* child closes parent's ends of pipes */ outpipe[READ_END] = safe_close(outpipe[READ_END]); errpipe[READ_END] = safe_close(errpipe[READ_END]); strscpy(arg, sizeof(arg), cmd); udev_build_argv(event->udev, arg, NULL, argv); /* allow programs in /usr/lib/udev/ to be called without the path */ if (argv[0][0] != '/') { strscpyl(program, sizeof(program), UDEVLIBEXECDIR "/", argv[0], NULL); argv[0] = program; } log_debug("starting '%s'", cmd); spawn_exec(event, cmd, argv, udev_device_get_properties_envp(event->dev), outpipe[WRITE_END], errpipe[WRITE_END]); _exit(2); } case -1: log_error_errno(errno, "fork of '%s' failed: %m", cmd); err = -1; goto out; default: /* parent closed child's ends of pipes */ outpipe[WRITE_END] = safe_close(outpipe[WRITE_END]); errpipe[WRITE_END] = safe_close(errpipe[WRITE_END]); spawn_read(event, timeout_usec, cmd, outpipe[READ_END], errpipe[READ_END], result, ressize); err = spawn_wait(event, timeout_usec, timeout_warn_usec, cmd, pid, accept_failure); } out: if (outpipe[READ_END] >= 0) close(outpipe[READ_END]); if (outpipe[WRITE_END] >= 0) close(outpipe[WRITE_END]); if (errpipe[READ_END] >= 0) close(errpipe[READ_END]); if (errpipe[WRITE_END] >= 0) close(errpipe[WRITE_END]); return err; } static int rename_netif(struct udev_event *event) { struct udev_device *dev = event->dev; char name[IFNAMSIZ]; const char *oldname; int r; oldname = udev_device_get_sysname(dev); strscpy(name, IFNAMSIZ, event->name); r = rtnl_set_link_name(&event->rtnl, udev_device_get_ifindex(dev), name); if (r < 0) return log_error_errno(r, "Error changing net interface name '%s' to '%s': %m", oldname, name); log_debug("renamed network interface '%s' to '%s'", oldname, name); return 0; } void udev_event_execute_rules(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, struct udev_list *properties_list, struct udev_rules *rules) { struct udev_device *dev = event->dev; if (udev_device_get_subsystem(dev) == NULL) return; if (streq(udev_device_get_action(dev), "remove")) { udev_device_read_db(dev); udev_device_tag_index(dev, NULL, false); udev_device_delete_db(dev); if (major(udev_device_get_devnum(dev)) != 0) udev_watch_end(event->udev, dev); udev_rules_apply_to_event(rules, event, timeout_usec, timeout_warn_usec, properties_list); if (major(udev_device_get_devnum(dev)) != 0) udev_node_remove(dev); } else { event->dev_db = udev_device_clone_with_db(dev); if (event->dev_db != NULL) { /* disable watch during event processing */ if (major(udev_device_get_devnum(dev)) != 0) udev_watch_end(event->udev, event->dev_db); if (major(udev_device_get_devnum(dev)) == 0 && streq(udev_device_get_action(dev), "move")) udev_device_copy_properties(dev, event->dev_db); } udev_rules_apply_to_event(rules, event, timeout_usec, timeout_warn_usec, properties_list); /* rename a new network interface, if needed */ if (udev_device_get_ifindex(dev) > 0 && streq(udev_device_get_action(dev), "add") && event->name != NULL && !streq(event->name, udev_device_get_sysname(dev))) { int r; r = rename_netif(event); if (r < 0) log_warning_errno(r, "could not rename interface '%d' from '%s' to '%s': %m", udev_device_get_ifindex(dev), udev_device_get_sysname(dev), event->name); else { r = udev_device_rename(dev, event->name); if (r < 0) log_warning_errno(r, "renamed interface '%d' from '%s' to '%s', but could not update udev_device: %m", udev_device_get_ifindex(dev), udev_device_get_sysname(dev), event->name); else log_debug("changed devpath to '%s'", udev_device_get_devpath(dev)); } } if (major(udev_device_get_devnum(dev)) > 0) { bool apply; /* remove/update possible left-over symlinks from old database entry */ if (event->dev_db != NULL) udev_node_update_old_links(dev, event->dev_db); if (!event->owner_set) event->uid = udev_device_get_devnode_uid(dev); if (!event->group_set) event->gid = udev_device_get_devnode_gid(dev); if (!event->mode_set) { if (udev_device_get_devnode_mode(dev) > 0) { /* kernel supplied value */ event->mode = udev_device_get_devnode_mode(dev); } else if (event->gid > 0) { /* default 0660 if a group is assigned */ event->mode = 0660; } else { /* default 0600 */ event->mode = 0600; } } apply = streq(udev_device_get_action(dev), "add") || event->owner_set || event->group_set || event->mode_set; udev_node_add(dev, apply, event->mode, event->uid, event->gid, &event->seclabel_list); } /* preserve old, or get new initialization timestamp */ udev_device_ensure_usec_initialized(event->dev, event->dev_db); /* (re)write database file */ udev_device_tag_index(dev, event->dev_db, true); udev_device_update_db(dev); udev_device_set_is_initialized(dev); event->dev_db = udev_device_unref(event->dev_db); } } void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec) { struct udev_list_entry *list_entry; udev_list_entry_foreach(list_entry, udev_list_get_entry(&event->run_list)) { char command[UTIL_PATH_SIZE]; const char *cmd = udev_list_entry_get_name(list_entry); enum udev_builtin_cmd builtin_cmd = udev_list_entry_get_num(list_entry); udev_event_apply_format(event, cmd, command, sizeof(command)); if (builtin_cmd < UDEV_BUILTIN_MAX) udev_builtin_run(event->dev, builtin_cmd, command, false); else { if (event->exec_delay > 0) { log_debug("delay execution of '%s'", command); sleep(event->exec_delay); } udev_event_spawn(event, timeout_usec, timeout_warn_usec, false, command, NULL, 0); } } } systemd-229/src/udev/udev-node.c000066400000000000000000000357121265713322000166550ustar00rootroot00000000000000/* * Copyright (C) 2003-2013 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include "formats-util.h" #include "fs-util.h" #include "selinux-util.h" #include "smack-util.h" #include "stdio-util.h" #include "string-util.h" #include "udev.h" static int node_symlink(struct udev_device *dev, const char *node, const char *slink) { struct stat stats; char target[UTIL_PATH_SIZE]; char *s; size_t l; char slink_tmp[UTIL_PATH_SIZE + 32]; int i = 0; int tail = 0; int err = 0; /* use relative link */ target[0] = '\0'; while (node[i] && (node[i] == slink[i])) { if (node[i] == '/') tail = i+1; i++; } s = target; l = sizeof(target); while (slink[i] != '\0') { if (slink[i] == '/') l = strpcpy(&s, l, "../"); i++; } l = strscpy(s, l, &node[tail]); if (l == 0) { err = -EINVAL; goto exit; } /* preserve link with correct target, do not replace node of other device */ if (lstat(slink, &stats) == 0) { if (S_ISBLK(stats.st_mode) || S_ISCHR(stats.st_mode)) { log_error("conflicting device node '%s' found, link to '%s' will not be created", slink, node); goto exit; } else if (S_ISLNK(stats.st_mode)) { char buf[UTIL_PATH_SIZE]; int len; len = readlink(slink, buf, sizeof(buf)); if (len > 0 && len < (int)sizeof(buf)) { buf[len] = '\0'; if (streq(target, buf)) { log_debug("preserve already existing symlink '%s' to '%s'", slink, target); label_fix(slink, true, false); utimensat(AT_FDCWD, slink, NULL, AT_SYMLINK_NOFOLLOW); goto exit; } } } } else { log_debug("creating symlink '%s' to '%s'", slink, target); do { err = mkdir_parents_label(slink, 0755); if (err != 0 && err != -ENOENT) break; mac_selinux_create_file_prepare(slink, S_IFLNK); err = symlink(target, slink); if (err != 0) err = -errno; mac_selinux_create_file_clear(); } while (err == -ENOENT); if (err == 0) goto exit; } log_debug("atomically replace '%s'", slink); strscpyl(slink_tmp, sizeof(slink_tmp), slink, ".tmp-", udev_device_get_id_filename(dev), NULL); unlink(slink_tmp); do { err = mkdir_parents_label(slink_tmp, 0755); if (err != 0 && err != -ENOENT) break; mac_selinux_create_file_prepare(slink_tmp, S_IFLNK); err = symlink(target, slink_tmp); if (err != 0) err = -errno; mac_selinux_create_file_clear(); } while (err == -ENOENT); if (err != 0) { log_error_errno(errno, "symlink '%s' '%s' failed: %m", target, slink_tmp); goto exit; } err = rename(slink_tmp, slink); if (err != 0) { log_error_errno(errno, "rename '%s' '%s' failed: %m", slink_tmp, slink); unlink(slink_tmp); } exit: return err; } /* find device node of device with highest priority */ static const char *link_find_prioritized(struct udev_device *dev, bool add, const char *stackdir, char *buf, size_t bufsize) { struct udev *udev = udev_device_get_udev(dev); DIR *dir; int priority = 0; const char *target = NULL; if (add) { priority = udev_device_get_devlink_priority(dev); strscpy(buf, bufsize, udev_device_get_devnode(dev)); target = buf; } dir = opendir(stackdir); if (dir == NULL) return target; for (;;) { struct udev_device *dev_db; struct dirent *dent; dent = readdir(dir); if (dent == NULL || dent->d_name[0] == '\0') break; if (dent->d_name[0] == '.') continue; log_debug("found '%s' claiming '%s'", dent->d_name, stackdir); /* did we find ourself? */ if (streq(dent->d_name, udev_device_get_id_filename(dev))) continue; dev_db = udev_device_new_from_device_id(udev, dent->d_name); if (dev_db != NULL) { const char *devnode; devnode = udev_device_get_devnode(dev_db); if (devnode != NULL) { if (target == NULL || udev_device_get_devlink_priority(dev_db) > priority) { log_debug("'%s' claims priority %i for '%s'", udev_device_get_syspath(dev_db), udev_device_get_devlink_priority(dev_db), stackdir); priority = udev_device_get_devlink_priority(dev_db); strscpy(buf, bufsize, devnode); target = buf; } } udev_device_unref(dev_db); } } closedir(dir); return target; } /* manage "stack of names" with possibly specified device priorities */ static void link_update(struct udev_device *dev, const char *slink, bool add) { char name_enc[UTIL_PATH_SIZE]; char filename[UTIL_PATH_SIZE * 2]; char dirname[UTIL_PATH_SIZE]; const char *target; char buf[UTIL_PATH_SIZE]; util_path_encode(slink + strlen("/dev"), name_enc, sizeof(name_enc)); strscpyl(dirname, sizeof(dirname), "/run/udev/links/", name_enc, NULL); strscpyl(filename, sizeof(filename), dirname, "/", udev_device_get_id_filename(dev), NULL); if (!add && unlink(filename) == 0) rmdir(dirname); target = link_find_prioritized(dev, add, dirname, buf, sizeof(buf)); if (target == NULL) { log_debug("no reference left, remove '%s'", slink); if (unlink(slink) == 0) rmdir_parents(slink, "/"); } else { log_debug("creating link '%s' to '%s'", slink, target); node_symlink(dev, target, slink); } if (add) { int err; do { int fd; err = mkdir_parents(filename, 0755); if (err != 0 && err != -ENOENT) break; fd = open(filename, O_WRONLY|O_CREAT|O_CLOEXEC|O_TRUNC|O_NOFOLLOW, 0444); if (fd >= 0) close(fd); else err = -errno; } while (err == -ENOENT); } } void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev_old) { struct udev_list_entry *list_entry; /* update possible left-over symlinks */ udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev_old)) { const char *name = udev_list_entry_get_name(list_entry); struct udev_list_entry *list_entry_current; int found; /* check if old link name still belongs to this device */ found = 0; udev_list_entry_foreach(list_entry_current, udev_device_get_devlinks_list_entry(dev)) { const char *name_current = udev_list_entry_get_name(list_entry_current); if (streq(name, name_current)) { found = 1; break; } } if (found) continue; log_debug("update old name, '%s' no longer belonging to '%s'", name, udev_device_get_devpath(dev)); link_update(dev, name, false); } } static int node_permissions_apply(struct udev_device *dev, bool apply, mode_t mode, uid_t uid, gid_t gid, struct udev_list *seclabel_list) { const char *devnode = udev_device_get_devnode(dev); dev_t devnum = udev_device_get_devnum(dev); struct stat stats; struct udev_list_entry *entry; int err = 0; if (streq(udev_device_get_subsystem(dev), "block")) mode |= S_IFBLK; else mode |= S_IFCHR; if (lstat(devnode, &stats) != 0) { err = log_debug_errno(errno, "can not stat() node '%s' (%m)", devnode); goto out; } if (((stats.st_mode & S_IFMT) != (mode & S_IFMT)) || (stats.st_rdev != devnum)) { err = -EEXIST; log_debug("found node '%s' with non-matching devnum %s, skip handling", udev_device_get_devnode(dev), udev_device_get_id_filename(dev)); goto out; } if (apply) { bool selinux = false; bool smack = false; if ((stats.st_mode & 0777) != (mode & 0777) || stats.st_uid != uid || stats.st_gid != gid) { log_debug("set permissions %s, %#o, uid=%u, gid=%u", devnode, mode, uid, gid); err = chmod(devnode, mode); if (err < 0) log_warning_errno(errno, "setting mode of %s to %#o failed: %m", devnode, mode); err = chown(devnode, uid, gid); if (err < 0) log_warning_errno(errno, "setting owner of %s to uid=%u, gid=%u failed: %m", devnode, uid, gid); } else { log_debug("preserve permissions %s, %#o, uid=%u, gid=%u", devnode, mode, uid, gid); } /* apply SECLABEL{$module}=$label */ udev_list_entry_foreach(entry, udev_list_get_entry(seclabel_list)) { const char *name, *label; int r; name = udev_list_entry_get_name(entry); label = udev_list_entry_get_value(entry); if (streq(name, "selinux")) { selinux = true; r = mac_selinux_apply(devnode, label); if (r < 0) log_error_errno(r, "SECLABEL: failed to set SELinux label '%s': %m", label); else log_debug("SECLABEL: set SELinux label '%s'", label); } else if (streq(name, "smack")) { smack = true; r = mac_smack_apply(devnode, SMACK_ATTR_ACCESS, label); if (r < 0) log_error_errno(r, "SECLABEL: failed to set SMACK label '%s': %m", label); else log_debug("SECLABEL: set SMACK label '%s'", label); } else log_error("SECLABEL: unknown subsystem, ignoring '%s'='%s'", name, label); } /* set the defaults */ if (!selinux) mac_selinux_fix(devnode, true, false); if (!smack) mac_smack_apply(devnode, SMACK_ATTR_ACCESS, NULL); } /* always update timestamp when we re-use the node, like on media change events */ utimensat(AT_FDCWD, devnode, NULL, 0); out: return err; } void udev_node_add(struct udev_device *dev, bool apply, mode_t mode, uid_t uid, gid_t gid, struct udev_list *seclabel_list) { char filename[UTIL_PATH_SIZE]; struct udev_list_entry *list_entry; log_debug("handling device node '%s', devnum=%s, mode=%#o, uid="UID_FMT", gid="GID_FMT, udev_device_get_devnode(dev), udev_device_get_id_filename(dev), mode, uid, gid); if (node_permissions_apply(dev, apply, mode, uid, gid, seclabel_list) < 0) return; /* always add /dev/{block,char}/$major:$minor */ xsprintf(filename, "/dev/%s/%u:%u", streq(udev_device_get_subsystem(dev), "block") ? "block" : "char", major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev))); node_symlink(dev, udev_device_get_devnode(dev), filename); /* create/update symlinks, add symlinks to name index */ udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) link_update(dev, udev_list_entry_get_name(list_entry), true); } void udev_node_remove(struct udev_device *dev) { struct udev_list_entry *list_entry; char filename[UTIL_PATH_SIZE]; /* remove/update symlinks, remove symlinks from name index */ udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) link_update(dev, udev_list_entry_get_name(list_entry), false); /* remove /dev/{block,char}/$major:$minor */ xsprintf(filename, "/dev/%s/%u:%u", streq(udev_device_get_subsystem(dev), "block") ? "block" : "char", major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev))); unlink(filename); } systemd-229/src/udev/udev-rules.c000066400000000000000000003366721265713322000170730ustar00rootroot00000000000000/* * Copyright (C) 2003-2012 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "conf-files.h" #include "escape.h" #include "fd-util.h" #include "glob-util.h" #include "path-util.h" #include "stat-util.h" #include "strbuf.h" #include "string-util.h" #include "strv.h" #include "sysctl-util.h" #include "udev.h" #include "user-util.h" #include "util.h" #define PREALLOC_TOKEN 2048 struct uid_gid { unsigned int name_off; union { uid_t uid; gid_t gid; }; }; static const char* const rules_dirs[] = { "/etc/udev/rules.d", "/run/udev/rules.d", UDEVLIBEXECDIR "/rules.d", NULL }; struct udev_rules { struct udev *udev; usec_t dirs_ts_usec; int resolve_names; /* every key in the rules file becomes a token */ struct token *tokens; unsigned int token_cur; unsigned int token_max; /* all key strings are copied and de-duplicated in a single continuous string buffer */ struct strbuf *strbuf; /* during rule parsing, uid/gid lookup results are cached */ struct uid_gid *uids; unsigned int uids_cur; unsigned int uids_max; struct uid_gid *gids; unsigned int gids_cur; unsigned int gids_max; }; static char *rules_str(struct udev_rules *rules, unsigned int off) { return rules->strbuf->buf + off; } static unsigned int rules_add_string(struct udev_rules *rules, const char *s) { return strbuf_add_string(rules->strbuf, s, strlen(s)); } /* KEY=="", KEY!="", KEY+="", KEY-="", KEY="", KEY:="" */ enum operation_type { OP_UNSET, OP_MATCH, OP_NOMATCH, OP_MATCH_MAX, OP_ADD, OP_REMOVE, OP_ASSIGN, OP_ASSIGN_FINAL, }; enum string_glob_type { GL_UNSET, GL_PLAIN, /* no special chars */ GL_GLOB, /* shell globs ?,*,[] */ GL_SPLIT, /* multi-value A|B */ GL_SPLIT_GLOB, /* multi-value with glob A*|B* */ GL_SOMETHING, /* commonly used "?*" */ }; enum string_subst_type { SB_UNSET, SB_NONE, SB_FORMAT, SB_SUBSYS, }; /* tokens of a rule are sorted/handled in this order */ enum token_type { TK_UNSET, TK_RULE, TK_M_ACTION, /* val */ TK_M_DEVPATH, /* val */ TK_M_KERNEL, /* val */ TK_M_DEVLINK, /* val */ TK_M_NAME, /* val */ TK_M_ENV, /* val, attr */ TK_M_TAG, /* val */ TK_M_SUBSYSTEM, /* val */ TK_M_DRIVER, /* val */ TK_M_WAITFOR, /* val */ TK_M_ATTR, /* val, attr */ TK_M_SYSCTL, /* val, attr */ TK_M_PARENTS_MIN, TK_M_KERNELS, /* val */ TK_M_SUBSYSTEMS, /* val */ TK_M_DRIVERS, /* val */ TK_M_ATTRS, /* val, attr */ TK_M_TAGS, /* val */ TK_M_PARENTS_MAX, TK_M_TEST, /* val, mode_t */ TK_M_PROGRAM, /* val */ TK_M_IMPORT_FILE, /* val */ TK_M_IMPORT_PROG, /* val */ TK_M_IMPORT_BUILTIN, /* val */ TK_M_IMPORT_DB, /* val */ TK_M_IMPORT_CMDLINE, /* val */ TK_M_IMPORT_PARENT, /* val */ TK_M_RESULT, /* val */ TK_M_MAX, TK_A_STRING_ESCAPE_NONE, TK_A_STRING_ESCAPE_REPLACE, TK_A_DB_PERSIST, TK_A_INOTIFY_WATCH, /* int */ TK_A_DEVLINK_PRIO, /* int */ TK_A_OWNER, /* val */ TK_A_GROUP, /* val */ TK_A_MODE, /* val */ TK_A_OWNER_ID, /* uid_t */ TK_A_GROUP_ID, /* gid_t */ TK_A_MODE_ID, /* mode_t */ TK_A_TAG, /* val */ TK_A_STATIC_NODE, /* val */ TK_A_SECLABEL, /* val, attr */ TK_A_ENV, /* val, attr */ TK_A_NAME, /* val */ TK_A_DEVLINK, /* val */ TK_A_ATTR, /* val, attr */ TK_A_SYSCTL, /* val, attr */ TK_A_RUN_BUILTIN, /* val, bool */ TK_A_RUN_PROGRAM, /* val, bool */ TK_A_GOTO, /* size_t */ TK_END, }; /* we try to pack stuff in a way that we take only 12 bytes per token */ struct token { union { unsigned char type; /* same in rule and key */ struct { enum token_type type:8; bool can_set_name:1; bool has_static_node:1; unsigned int unused:6; unsigned short token_count; unsigned int label_off; unsigned short filename_off; unsigned short filename_line; } rule; struct { enum token_type type:8; enum operation_type op:8; enum string_glob_type glob:8; enum string_subst_type subst:4; enum string_subst_type attrsubst:4; unsigned int value_off; union { unsigned int attr_off; unsigned int rule_goto; mode_t mode; uid_t uid; gid_t gid; int devlink_prio; int watch; enum udev_builtin_cmd builtin_cmd; }; } key; }; }; #define MAX_TK 64 struct rule_tmp { struct udev_rules *rules; struct token rule; struct token token[MAX_TK]; unsigned int token_cur; }; #ifdef DEBUG static const char *operation_str(enum operation_type type) { static const char *operation_strs[] = { [OP_UNSET] = "UNSET", [OP_MATCH] = "match", [OP_NOMATCH] = "nomatch", [OP_MATCH_MAX] = "MATCH_MAX", [OP_ADD] = "add", [OP_REMOVE] = "remove", [OP_ASSIGN] = "assign", [OP_ASSIGN_FINAL] = "assign-final", } ; return operation_strs[type]; } static const char *string_glob_str(enum string_glob_type type) { static const char *string_glob_strs[] = { [GL_UNSET] = "UNSET", [GL_PLAIN] = "plain", [GL_GLOB] = "glob", [GL_SPLIT] = "split", [GL_SPLIT_GLOB] = "split-glob", [GL_SOMETHING] = "split-glob", }; return string_glob_strs[type]; } static const char *token_str(enum token_type type) { static const char *token_strs[] = { [TK_UNSET] = "UNSET", [TK_RULE] = "RULE", [TK_M_ACTION] = "M ACTION", [TK_M_DEVPATH] = "M DEVPATH", [TK_M_KERNEL] = "M KERNEL", [TK_M_DEVLINK] = "M DEVLINK", [TK_M_NAME] = "M NAME", [TK_M_ENV] = "M ENV", [TK_M_TAG] = "M TAG", [TK_M_SUBSYSTEM] = "M SUBSYSTEM", [TK_M_DRIVER] = "M DRIVER", [TK_M_WAITFOR] = "M WAITFOR", [TK_M_ATTR] = "M ATTR", [TK_M_SYSCTL] = "M SYSCTL", [TK_M_PARENTS_MIN] = "M PARENTS_MIN", [TK_M_KERNELS] = "M KERNELS", [TK_M_SUBSYSTEMS] = "M SUBSYSTEMS", [TK_M_DRIVERS] = "M DRIVERS", [TK_M_ATTRS] = "M ATTRS", [TK_M_TAGS] = "M TAGS", [TK_M_PARENTS_MAX] = "M PARENTS_MAX", [TK_M_TEST] = "M TEST", [TK_M_PROGRAM] = "M PROGRAM", [TK_M_IMPORT_FILE] = "M IMPORT_FILE", [TK_M_IMPORT_PROG] = "M IMPORT_PROG", [TK_M_IMPORT_BUILTIN] = "M IMPORT_BUILTIN", [TK_M_IMPORT_DB] = "M IMPORT_DB", [TK_M_IMPORT_CMDLINE] = "M IMPORT_CMDLINE", [TK_M_IMPORT_PARENT] = "M IMPORT_PARENT", [TK_M_RESULT] = "M RESULT", [TK_M_MAX] = "M MAX", [TK_A_STRING_ESCAPE_NONE] = "A STRING_ESCAPE_NONE", [TK_A_STRING_ESCAPE_REPLACE] = "A STRING_ESCAPE_REPLACE", [TK_A_DB_PERSIST] = "A DB_PERSIST", [TK_A_INOTIFY_WATCH] = "A INOTIFY_WATCH", [TK_A_DEVLINK_PRIO] = "A DEVLINK_PRIO", [TK_A_OWNER] = "A OWNER", [TK_A_GROUP] = "A GROUP", [TK_A_MODE] = "A MODE", [TK_A_OWNER_ID] = "A OWNER_ID", [TK_A_GROUP_ID] = "A GROUP_ID", [TK_A_STATIC_NODE] = "A STATIC_NODE", [TK_A_SECLABEL] = "A SECLABEL", [TK_A_MODE_ID] = "A MODE_ID", [TK_A_ENV] = "A ENV", [TK_A_TAG] = "A ENV", [TK_A_NAME] = "A NAME", [TK_A_DEVLINK] = "A DEVLINK", [TK_A_ATTR] = "A ATTR", [TK_A_SYSCTL] = "A SYSCTL", [TK_A_RUN_BUILTIN] = "A RUN_BUILTIN", [TK_A_RUN_PROGRAM] = "A RUN_PROGRAM", [TK_A_GOTO] = "A GOTO", [TK_END] = "END", }; return token_strs[type]; } static void dump_token(struct udev_rules *rules, struct token *token) { enum token_type type = token->type; enum operation_type op = token->key.op; enum string_glob_type glob = token->key.glob; const char *value = str(rules, token->key.value_off); const char *attr = &rules->buf[token->key.attr_off]; switch (type) { case TK_RULE: { const char *tks_ptr = (char *)rules->tokens; const char *tk_ptr = (char *)token; unsigned int idx = (tk_ptr - tks_ptr) / sizeof(struct token); log_debug("* RULE %s:%u, token: %u, count: %u, label: '%s'", &rules->buf[token->rule.filename_off], token->rule.filename_line, idx, token->rule.token_count, &rules->buf[token->rule.label_off]); break; } case TK_M_ACTION: case TK_M_DEVPATH: case TK_M_KERNEL: case TK_M_SUBSYSTEM: case TK_M_DRIVER: case TK_M_WAITFOR: case TK_M_DEVLINK: case TK_M_NAME: case TK_M_KERNELS: case TK_M_SUBSYSTEMS: case TK_M_DRIVERS: case TK_M_TAGS: case TK_M_PROGRAM: case TK_M_IMPORT_FILE: case TK_M_IMPORT_PROG: case TK_M_IMPORT_DB: case TK_M_IMPORT_CMDLINE: case TK_M_IMPORT_PARENT: case TK_M_RESULT: case TK_A_NAME: case TK_A_DEVLINK: case TK_A_OWNER: case TK_A_GROUP: case TK_A_MODE: case TK_A_RUN_BUILTIN: case TK_A_RUN_PROGRAM: log_debug("%s %s '%s'(%s)", token_str(type), operation_str(op), value, string_glob_str(glob)); break; case TK_M_IMPORT_BUILTIN: log_debug("%s %i '%s'", token_str(type), token->key.builtin_cmd, value); break; case TK_M_ATTR: case TK_M_SYSCTL: case TK_M_ATTRS: case TK_M_ENV: case TK_A_ATTR: case TK_A_SYSCTL: case TK_A_ENV: log_debug("%s %s '%s' '%s'(%s)", token_str(type), operation_str(op), attr, value, string_glob_str(glob)); break; case TK_M_TAG: case TK_A_TAG: log_debug("%s %s '%s'", token_str(type), operation_str(op), value); break; case TK_A_STRING_ESCAPE_NONE: case TK_A_STRING_ESCAPE_REPLACE: case TK_A_DB_PERSIST: log_debug("%s", token_str(type)); break; case TK_M_TEST: log_debug("%s %s '%s'(%s) %#o", token_str(type), operation_str(op), value, string_glob_str(glob), token->key.mode); break; case TK_A_INOTIFY_WATCH: log_debug("%s %u", token_str(type), token->key.watch); break; case TK_A_DEVLINK_PRIO: log_debug("%s %u", token_str(type), token->key.devlink_prio); break; case TK_A_OWNER_ID: log_debug("%s %s %u", token_str(type), operation_str(op), token->key.uid); break; case TK_A_GROUP_ID: log_debug("%s %s %u", token_str(type), operation_str(op), token->key.gid); break; case TK_A_MODE_ID: log_debug("%s %s %#o", token_str(type), operation_str(op), token->key.mode); break; case TK_A_STATIC_NODE: log_debug("%s '%s'", token_str(type), value); break; case TK_A_SECLABEL: log_debug("%s %s '%s' '%s'", token_str(type), operation_str(op), attr, value); break; case TK_A_GOTO: log_debug("%s '%s' %u", token_str(type), value, token->key.rule_goto); break; case TK_END: log_debug("* %s", token_str(type)); break; case TK_M_PARENTS_MIN: case TK_M_PARENTS_MAX: case TK_M_MAX: case TK_UNSET: log_debug("unknown type %u", type); break; } } static void dump_rules(struct udev_rules *rules) { unsigned int i; log_debug("dumping %u (%zu bytes) tokens, %u (%zu bytes) strings", rules->token_cur, rules->token_cur * sizeof(struct token), rules->buf_count, rules->buf_cur); for (i = 0; i < rules->token_cur; i++) dump_token(rules, &rules->tokens[i]); } #else static inline void dump_token(struct udev_rules *rules, struct token *token) {} static inline void dump_rules(struct udev_rules *rules) {} #endif /* DEBUG */ static int add_token(struct udev_rules *rules, struct token *token) { /* grow buffer if needed */ if (rules->token_cur+1 >= rules->token_max) { struct token *tokens; unsigned int add; /* double the buffer size */ add = rules->token_max; if (add < 8) add = 8; tokens = realloc(rules->tokens, (rules->token_max + add ) * sizeof(struct token)); if (tokens == NULL) return -1; rules->tokens = tokens; rules->token_max += add; } memcpy(&rules->tokens[rules->token_cur], token, sizeof(struct token)); rules->token_cur++; return 0; } static uid_t add_uid(struct udev_rules *rules, const char *owner) { unsigned int i; uid_t uid = 0; unsigned int off; int r; /* lookup, if we know it already */ for (i = 0; i < rules->uids_cur; i++) { off = rules->uids[i].name_off; if (streq(rules_str(rules, off), owner)) { uid = rules->uids[i].uid; return uid; } } r = get_user_creds(&owner, &uid, NULL, NULL, NULL); if (r < 0) { if (r == -ENOENT || r == -ESRCH) log_error("specified user '%s' unknown", owner); else log_error_errno(r, "error resolving user '%s': %m", owner); } /* grow buffer if needed */ if (rules->uids_cur+1 >= rules->uids_max) { struct uid_gid *uids; unsigned int add; /* double the buffer size */ add = rules->uids_max; if (add < 1) add = 8; uids = realloc(rules->uids, (rules->uids_max + add ) * sizeof(struct uid_gid)); if (uids == NULL) return uid; rules->uids = uids; rules->uids_max += add; } rules->uids[rules->uids_cur].uid = uid; off = rules_add_string(rules, owner); if (off <= 0) return uid; rules->uids[rules->uids_cur].name_off = off; rules->uids_cur++; return uid; } static gid_t add_gid(struct udev_rules *rules, const char *group) { unsigned int i; gid_t gid = 0; unsigned int off; int r; /* lookup, if we know it already */ for (i = 0; i < rules->gids_cur; i++) { off = rules->gids[i].name_off; if (streq(rules_str(rules, off), group)) { gid = rules->gids[i].gid; return gid; } } r = get_group_creds(&group, &gid); if (r < 0) { if (r == -ENOENT || r == -ESRCH) log_error("specified group '%s' unknown", group); else log_error_errno(r, "error resolving group '%s': %m", group); } /* grow buffer if needed */ if (rules->gids_cur+1 >= rules->gids_max) { struct uid_gid *gids; unsigned int add; /* double the buffer size */ add = rules->gids_max; if (add < 1) add = 8; gids = realloc(rules->gids, (rules->gids_max + add ) * sizeof(struct uid_gid)); if (gids == NULL) return gid; rules->gids = gids; rules->gids_max += add; } rules->gids[rules->gids_cur].gid = gid; off = rules_add_string(rules, group); if (off <= 0) return gid; rules->gids[rules->gids_cur].name_off = off; rules->gids_cur++; return gid; } static int import_property_from_string(struct udev_device *dev, char *line) { char *key; char *val; size_t len; /* find key */ key = line; while (isspace(key[0])) key++; /* comment or empty line */ if (key[0] == '#' || key[0] == '\0') return -1; /* split key/value */ val = strchr(key, '='); if (val == NULL) return -1; val[0] = '\0'; val++; /* find value */ while (isspace(val[0])) val++; /* terminate key */ len = strlen(key); if (len == 0) return -1; while (isspace(key[len-1])) len--; key[len] = '\0'; /* terminate value */ len = strlen(val); if (len == 0) return -1; while (isspace(val[len-1])) len--; val[len] = '\0'; if (len == 0) return -1; /* unquote */ if (val[0] == '"' || val[0] == '\'') { if (val[len-1] != val[0]) { log_debug("inconsistent quoting: '%s', skip", line); return -1; } val[len-1] = '\0'; val++; } udev_device_add_property(dev, key, val); return 0; } static int import_file_into_properties(struct udev_device *dev, const char *filename) { FILE *f; char line[UTIL_LINE_SIZE]; f = fopen(filename, "re"); if (f == NULL) return -1; while (fgets(line, sizeof(line), f) != NULL) import_property_from_string(dev, line); fclose(f); return 0; } static int import_program_into_properties(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const char *program) { char result[UTIL_LINE_SIZE]; char *line; int err; err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, result, sizeof(result)); if (err < 0) return err; line = result; while (line != NULL) { char *pos; pos = strchr(line, '\n'); if (pos != NULL) { pos[0] = '\0'; pos = &pos[1]; } import_property_from_string(event->dev, line); line = pos; } return 0; } static int import_parent_into_properties(struct udev_device *dev, const char *filter) { struct udev_device *dev_parent; struct udev_list_entry *list_entry; assert(dev); assert(filter); dev_parent = udev_device_get_parent(dev); if (dev_parent == NULL) return -1; udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(dev_parent)) { const char *key = udev_list_entry_get_name(list_entry); const char *val = udev_list_entry_get_value(list_entry); if (fnmatch(filter, key, 0) == 0) udev_device_add_property(dev, key, val); } return 0; } static int attr_subst_subdir(char *attr, size_t len) { bool found = false; if (strstr(attr, "/*/")) { char *pos; char dirname[UTIL_PATH_SIZE]; const char *tail; DIR *dir; strscpy(dirname, sizeof(dirname), attr); pos = strstr(dirname, "/*/"); if (pos == NULL) return -1; pos[0] = '\0'; tail = &pos[2]; dir = opendir(dirname); if (dir != NULL) { struct dirent *dent; for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { struct stat stats; if (dent->d_name[0] == '.') continue; strscpyl(attr, len, dirname, "/", dent->d_name, tail, NULL); if (stat(attr, &stats) == 0) { found = true; break; } } closedir(dir); } } return found; } static int get_key(struct udev *udev, char **line, char **key, enum operation_type *op, char **value) { char *linepos; char *temp; linepos = *line; if (linepos == NULL || linepos[0] == '\0') return -1; /* skip whitespace */ while (isspace(linepos[0]) || linepos[0] == ',') linepos++; /* get the key */ if (linepos[0] == '\0') return -1; *key = linepos; for (;;) { linepos++; if (linepos[0] == '\0') return -1; if (isspace(linepos[0])) break; if (linepos[0] == '=') break; if ((linepos[0] == '+') || (linepos[0] == '-') || (linepos[0] == '!') || (linepos[0] == ':')) if (linepos[1] == '=') break; } /* remember end of key */ temp = linepos; /* skip whitespace after key */ while (isspace(linepos[0])) linepos++; if (linepos[0] == '\0') return -1; /* get operation type */ if (linepos[0] == '=' && linepos[1] == '=') { *op = OP_MATCH; linepos += 2; } else if (linepos[0] == '!' && linepos[1] == '=') { *op = OP_NOMATCH; linepos += 2; } else if (linepos[0] == '+' && linepos[1] == '=') { *op = OP_ADD; linepos += 2; } else if (linepos[0] == '-' && linepos[1] == '=') { *op = OP_REMOVE; linepos += 2; } else if (linepos[0] == '=') { *op = OP_ASSIGN; linepos++; } else if (linepos[0] == ':' && linepos[1] == '=') { *op = OP_ASSIGN_FINAL; linepos += 2; } else return -1; /* terminate key */ temp[0] = '\0'; /* skip whitespace after operator */ while (isspace(linepos[0])) linepos++; if (linepos[0] == '\0') return -1; /* get the value */ if (linepos[0] == '"') linepos++; else return -1; *value = linepos; /* terminate */ temp = strchr(linepos, '"'); if (!temp) return -1; temp[0] = '\0'; temp++; /* move line to next key */ *line = temp; return 0; } /* extract possible KEY{attr} */ static const char *get_key_attribute(struct udev *udev, char *str) { char *pos; char *attr; attr = strchr(str, '{'); if (attr != NULL) { attr++; pos = strchr(attr, '}'); if (pos == NULL) { log_error("missing closing brace for format"); return NULL; } pos[0] = '\0'; return attr; } return NULL; } static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type, enum operation_type op, const char *value, const void *data) { struct token *token = &rule_tmp->token[rule_tmp->token_cur]; const char *attr = NULL; memzero(token, sizeof(struct token)); switch (type) { case TK_M_ACTION: case TK_M_DEVPATH: case TK_M_KERNEL: case TK_M_SUBSYSTEM: case TK_M_DRIVER: case TK_M_WAITFOR: case TK_M_DEVLINK: case TK_M_NAME: case TK_M_KERNELS: case TK_M_SUBSYSTEMS: case TK_M_DRIVERS: case TK_M_TAGS: case TK_M_PROGRAM: case TK_M_IMPORT_FILE: case TK_M_IMPORT_PROG: case TK_M_IMPORT_DB: case TK_M_IMPORT_CMDLINE: case TK_M_IMPORT_PARENT: case TK_M_RESULT: case TK_A_OWNER: case TK_A_GROUP: case TK_A_MODE: case TK_A_DEVLINK: case TK_A_NAME: case TK_A_GOTO: case TK_M_TAG: case TK_A_TAG: case TK_A_STATIC_NODE: token->key.value_off = rules_add_string(rule_tmp->rules, value); break; case TK_M_IMPORT_BUILTIN: token->key.value_off = rules_add_string(rule_tmp->rules, value); token->key.builtin_cmd = *(enum udev_builtin_cmd *)data; break; case TK_M_ENV: case TK_M_ATTR: case TK_M_SYSCTL: case TK_M_ATTRS: case TK_A_ATTR: case TK_A_SYSCTL: case TK_A_ENV: case TK_A_SECLABEL: attr = data; token->key.value_off = rules_add_string(rule_tmp->rules, value); token->key.attr_off = rules_add_string(rule_tmp->rules, attr); break; case TK_M_TEST: token->key.value_off = rules_add_string(rule_tmp->rules, value); if (data != NULL) token->key.mode = *(mode_t *)data; break; case TK_A_STRING_ESCAPE_NONE: case TK_A_STRING_ESCAPE_REPLACE: case TK_A_DB_PERSIST: break; case TK_A_RUN_BUILTIN: case TK_A_RUN_PROGRAM: token->key.builtin_cmd = *(enum udev_builtin_cmd *)data; token->key.value_off = rules_add_string(rule_tmp->rules, value); break; case TK_A_INOTIFY_WATCH: case TK_A_DEVLINK_PRIO: token->key.devlink_prio = *(int *)data; break; case TK_A_OWNER_ID: token->key.uid = *(uid_t *)data; break; case TK_A_GROUP_ID: token->key.gid = *(gid_t *)data; break; case TK_A_MODE_ID: token->key.mode = *(mode_t *)data; break; case TK_RULE: case TK_M_PARENTS_MIN: case TK_M_PARENTS_MAX: case TK_M_MAX: case TK_END: case TK_UNSET: log_error("wrong type %u", type); return -1; } if (value != NULL && type < TK_M_MAX) { /* check if we need to split or call fnmatch() while matching rules */ enum string_glob_type glob; int has_split; int has_glob; has_split = (strchr(value, '|') != NULL); has_glob = string_is_glob(value); if (has_split && has_glob) { glob = GL_SPLIT_GLOB; } else if (has_split) { glob = GL_SPLIT; } else if (has_glob) { if (streq(value, "?*")) glob = GL_SOMETHING; else glob = GL_GLOB; } else { glob = GL_PLAIN; } token->key.glob = glob; } if (value != NULL && type > TK_M_MAX) { /* check if assigned value has substitution chars */ if (value[0] == '[') token->key.subst = SB_SUBSYS; else if (strchr(value, '%') != NULL || strchr(value, '$') != NULL) token->key.subst = SB_FORMAT; else token->key.subst = SB_NONE; } if (attr != NULL) { /* check if property/attribute name has substitution chars */ if (attr[0] == '[') token->key.attrsubst = SB_SUBSYS; else if (strchr(attr, '%') != NULL || strchr(attr, '$') != NULL) token->key.attrsubst = SB_FORMAT; else token->key.attrsubst = SB_NONE; } token->key.type = type; token->key.op = op; rule_tmp->token_cur++; if (rule_tmp->token_cur >= ELEMENTSOF(rule_tmp->token)) { log_error("temporary rule array too small"); return -1; } return 0; } static int sort_token(struct udev_rules *rules, struct rule_tmp *rule_tmp) { unsigned int i; unsigned int start = 0; unsigned int end = rule_tmp->token_cur; for (i = 0; i < rule_tmp->token_cur; i++) { enum token_type next_val = TK_UNSET; unsigned int next_idx = 0; unsigned int j; /* find smallest value */ for (j = start; j < end; j++) { if (rule_tmp->token[j].type == TK_UNSET) continue; if (next_val == TK_UNSET || rule_tmp->token[j].type < next_val) { next_val = rule_tmp->token[j].type; next_idx = j; } } /* add token and mark done */ if (add_token(rules, &rule_tmp->token[next_idx]) != 0) return -1; rule_tmp->token[next_idx].type = TK_UNSET; /* shrink range */ if (next_idx == start) start++; if (next_idx+1 == end) end--; } return 0; } static int add_rule(struct udev_rules *rules, char *line, const char *filename, unsigned int filename_off, unsigned int lineno) { char *linepos; const char *attr; struct rule_tmp rule_tmp = { .rules = rules, .rule.type = TK_RULE, }; /* the offset in the rule is limited to unsigned short */ if (filename_off < USHRT_MAX) rule_tmp.rule.rule.filename_off = filename_off; rule_tmp.rule.rule.filename_line = lineno; linepos = line; for (;;) { char *key; char *value; enum operation_type op; if (get_key(rules->udev, &linepos, &key, &op, &value) != 0) { /* Avoid erroring on trailing whitespace. This is probably rare * so save the work for the error case instead of always trying * to strip the trailing whitespace with strstrip(). */ while (isblank(*linepos)) linepos++; /* If we aren't at the end of the line, this is a parsing error. * Make a best effort to describe where the problem is. */ if (!strchr(NEWLINE, *linepos)) { char buf[2] = {*linepos}; _cleanup_free_ char *tmp; tmp = cescape(buf); log_error("invalid key/value pair in file %s on line %u, starting at character %tu ('%s')", filename, lineno, linepos - line + 1, tmp); if (*linepos == '#') log_error("hint: comments can only start at beginning of line"); } break; } if (streq(key, "ACTION")) { if (op > OP_MATCH_MAX) { log_error("invalid ACTION operation"); goto invalid; } rule_add_key(&rule_tmp, TK_M_ACTION, op, value, NULL); continue; } if (streq(key, "DEVPATH")) { if (op > OP_MATCH_MAX) { log_error("invalid DEVPATH operation"); goto invalid; } rule_add_key(&rule_tmp, TK_M_DEVPATH, op, value, NULL); continue; } if (streq(key, "KERNEL")) { if (op > OP_MATCH_MAX) { log_error("invalid KERNEL operation"); goto invalid; } rule_add_key(&rule_tmp, TK_M_KERNEL, op, value, NULL); continue; } if (streq(key, "SUBSYSTEM")) { if (op > OP_MATCH_MAX) { log_error("invalid SUBSYSTEM operation"); goto invalid; } /* bus, class, subsystem events should all be the same */ if (streq(value, "subsystem") || streq(value, "bus") || streq(value, "class")) { if (streq(value, "bus") || streq(value, "class")) log_error("'%s' must be specified as 'subsystem' " "please fix it in %s:%u", value, filename, lineno); rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, "subsystem|class|bus", NULL); } else rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, value, NULL); continue; } if (streq(key, "DRIVER")) { if (op > OP_MATCH_MAX) { log_error("invalid DRIVER operation"); goto invalid; } rule_add_key(&rule_tmp, TK_M_DRIVER, op, value, NULL); continue; } if (startswith(key, "ATTR{")) { attr = get_key_attribute(rules->udev, key + strlen("ATTR")); if (attr == NULL) { log_error("error parsing ATTR attribute"); goto invalid; } if (op == OP_REMOVE) { log_error("invalid ATTR operation"); goto invalid; } if (op < OP_MATCH_MAX) rule_add_key(&rule_tmp, TK_M_ATTR, op, value, attr); else rule_add_key(&rule_tmp, TK_A_ATTR, op, value, attr); continue; } if (startswith(key, "SYSCTL{")) { attr = get_key_attribute(rules->udev, key + strlen("SYSCTL")); if (attr == NULL) { log_error("error parsing SYSCTL attribute"); goto invalid; } if (op == OP_REMOVE) { log_error("invalid SYSCTL operation"); goto invalid; } if (op < OP_MATCH_MAX) rule_add_key(&rule_tmp, TK_M_SYSCTL, op, value, attr); else rule_add_key(&rule_tmp, TK_A_SYSCTL, op, value, attr); continue; } if (startswith(key, "SECLABEL{")) { attr = get_key_attribute(rules->udev, key + strlen("SECLABEL")); if (!attr) { log_error("error parsing SECLABEL attribute"); goto invalid; } if (op == OP_REMOVE) { log_error("invalid SECLABEL operation"); goto invalid; } rule_add_key(&rule_tmp, TK_A_SECLABEL, op, value, attr); continue; } if (streq(key, "KERNELS")) { if (op > OP_MATCH_MAX) { log_error("invalid KERNELS operation"); goto invalid; } rule_add_key(&rule_tmp, TK_M_KERNELS, op, value, NULL); continue; } if (streq(key, "SUBSYSTEMS")) { if (op > OP_MATCH_MAX) { log_error("invalid SUBSYSTEMS operation"); goto invalid; } rule_add_key(&rule_tmp, TK_M_SUBSYSTEMS, op, value, NULL); continue; } if (streq(key, "DRIVERS")) { if (op > OP_MATCH_MAX) { log_error("invalid DRIVERS operation"); goto invalid; } rule_add_key(&rule_tmp, TK_M_DRIVERS, op, value, NULL); continue; } if (startswith(key, "ATTRS{")) { if (op > OP_MATCH_MAX) { log_error("invalid ATTRS operation"); goto invalid; } attr = get_key_attribute(rules->udev, key + strlen("ATTRS")); if (attr == NULL) { log_error("error parsing ATTRS attribute"); goto invalid; } if (startswith(attr, "device/")) log_error("the 'device' link may not be available in a future kernel, " "please fix it in %s:%u", filename, lineno); else if (strstr(attr, "../") != NULL) log_error("do not reference parent sysfs directories directly, " "it may break with a future kernel, please fix it in %s:%u", filename, lineno); rule_add_key(&rule_tmp, TK_M_ATTRS, op, value, attr); continue; } if (streq(key, "TAGS")) { if (op > OP_MATCH_MAX) { log_error("invalid TAGS operation"); goto invalid; } rule_add_key(&rule_tmp, TK_M_TAGS, op, value, NULL); continue; } if (startswith(key, "ENV{")) { attr = get_key_attribute(rules->udev, key + strlen("ENV")); if (attr == NULL) { log_error("error parsing ENV attribute"); goto invalid; } if (op == OP_REMOVE) { log_error("invalid ENV operation"); goto invalid; } if (op < OP_MATCH_MAX) { if (rule_add_key(&rule_tmp, TK_M_ENV, op, value, attr) != 0) goto invalid; } else { static const char *blacklist[] = { "ACTION", "SUBSYSTEM", "DEVTYPE", "MAJOR", "MINOR", "DRIVER", "IFINDEX", "DEVNAME", "DEVLINKS", "DEVPATH", "TAGS", }; unsigned int i; for (i = 0; i < ELEMENTSOF(blacklist); i++) { if (!streq(attr, blacklist[i])) continue; log_error("invalid ENV attribute, '%s' can not be set %s:%u", attr, filename, lineno); goto invalid; } if (rule_add_key(&rule_tmp, TK_A_ENV, op, value, attr) != 0) goto invalid; } continue; } if (streq(key, "TAG")) { if (op < OP_MATCH_MAX) rule_add_key(&rule_tmp, TK_M_TAG, op, value, NULL); else rule_add_key(&rule_tmp, TK_A_TAG, op, value, NULL); continue; } if (streq(key, "PROGRAM")) { if (op == OP_REMOVE) { log_error("invalid PROGRAM operation"); goto invalid; } rule_add_key(&rule_tmp, TK_M_PROGRAM, op, value, NULL); continue; } if (streq(key, "RESULT")) { if (op > OP_MATCH_MAX) { log_error("invalid RESULT operation"); goto invalid; } rule_add_key(&rule_tmp, TK_M_RESULT, op, value, NULL); continue; } if (startswith(key, "IMPORT")) { attr = get_key_attribute(rules->udev, key + strlen("IMPORT")); if (attr == NULL) { log_error("IMPORT{} type missing, ignoring IMPORT %s:%u", filename, lineno); continue; } if (op == OP_REMOVE) { log_error("invalid IMPORT operation"); goto invalid; } if (streq(attr, "program")) { /* find known built-in command */ if (value[0] != '/') { enum udev_builtin_cmd cmd; cmd = udev_builtin_lookup(value); if (cmd < UDEV_BUILTIN_MAX) { log_debug("IMPORT found builtin '%s', replacing %s:%u", value, filename, lineno); rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd); continue; } } rule_add_key(&rule_tmp, TK_M_IMPORT_PROG, op, value, NULL); } else if (streq(attr, "builtin")) { enum udev_builtin_cmd cmd = udev_builtin_lookup(value); if (cmd < UDEV_BUILTIN_MAX) rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd); else log_error("IMPORT{builtin}: '%s' unknown %s:%u", value, filename, lineno); } else if (streq(attr, "file")) { rule_add_key(&rule_tmp, TK_M_IMPORT_FILE, op, value, NULL); } else if (streq(attr, "db")) { rule_add_key(&rule_tmp, TK_M_IMPORT_DB, op, value, NULL); } else if (streq(attr, "cmdline")) { rule_add_key(&rule_tmp, TK_M_IMPORT_CMDLINE, op, value, NULL); } else if (streq(attr, "parent")) { rule_add_key(&rule_tmp, TK_M_IMPORT_PARENT, op, value, NULL); } else log_error("IMPORT{} unknown type, ignoring IMPORT %s:%u", filename, lineno); continue; } if (startswith(key, "TEST")) { mode_t mode = 0; if (op > OP_MATCH_MAX) { log_error("invalid TEST operation"); goto invalid; } attr = get_key_attribute(rules->udev, key + strlen("TEST")); if (attr != NULL) { mode = strtol(attr, NULL, 8); rule_add_key(&rule_tmp, TK_M_TEST, op, value, &mode); } else { rule_add_key(&rule_tmp, TK_M_TEST, op, value, NULL); } continue; } if (startswith(key, "RUN")) { attr = get_key_attribute(rules->udev, key + strlen("RUN")); if (attr == NULL) attr = "program"; if (op == OP_REMOVE) { log_error("invalid RUN operation"); goto invalid; } if (streq(attr, "builtin")) { enum udev_builtin_cmd cmd = udev_builtin_lookup(value); if (cmd < UDEV_BUILTIN_MAX) rule_add_key(&rule_tmp, TK_A_RUN_BUILTIN, op, value, &cmd); else log_error("RUN{builtin}: '%s' unknown %s:%u", value, filename, lineno); } else if (streq(attr, "program")) { enum udev_builtin_cmd cmd = UDEV_BUILTIN_MAX; rule_add_key(&rule_tmp, TK_A_RUN_PROGRAM, op, value, &cmd); } else { log_error("RUN{} unknown type, ignoring RUN %s:%u", filename, lineno); } continue; } if (streq(key, "LABEL")) { if (op == OP_REMOVE) { log_error("invalid LABEL operation"); goto invalid; } rule_tmp.rule.rule.label_off = rules_add_string(rules, value); continue; } if (streq(key, "GOTO")) { if (op == OP_REMOVE) { log_error("invalid GOTO operation"); goto invalid; } rule_add_key(&rule_tmp, TK_A_GOTO, 0, value, NULL); continue; } if (startswith(key, "NAME")) { if (op == OP_REMOVE) { log_error("invalid NAME operation"); goto invalid; } if (op < OP_MATCH_MAX) { rule_add_key(&rule_tmp, TK_M_NAME, op, value, NULL); } else { if (streq(value, "%k")) { log_error("NAME=\"%%k\" is ignored, because it breaks kernel supplied names, " "please remove it from %s:%u\n", filename, lineno); continue; } if (value[0] == '\0') { log_debug("NAME=\"\" is ignored, because udev will not delete any device nodes, " "please remove it from %s:%u\n", filename, lineno); continue; } rule_add_key(&rule_tmp, TK_A_NAME, op, value, NULL); } rule_tmp.rule.rule.can_set_name = true; continue; } if (streq(key, "SYMLINK")) { if (op == OP_REMOVE) { log_error("invalid SYMLINK operation"); goto invalid; } if (op < OP_MATCH_MAX) rule_add_key(&rule_tmp, TK_M_DEVLINK, op, value, NULL); else rule_add_key(&rule_tmp, TK_A_DEVLINK, op, value, NULL); rule_tmp.rule.rule.can_set_name = true; continue; } if (streq(key, "OWNER")) { uid_t uid; char *endptr; if (op == OP_REMOVE) { log_error("invalid OWNER operation"); goto invalid; } uid = strtoul(value, &endptr, 10); if (endptr[0] == '\0') { rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid); } else if ((rules->resolve_names > 0) && strchr("$%", value[0]) == NULL) { uid = add_uid(rules, value); rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid); } else if (rules->resolve_names >= 0) rule_add_key(&rule_tmp, TK_A_OWNER, op, value, NULL); rule_tmp.rule.rule.can_set_name = true; continue; } if (streq(key, "GROUP")) { gid_t gid; char *endptr; if (op == OP_REMOVE) { log_error("invalid GROUP operation"); goto invalid; } gid = strtoul(value, &endptr, 10); if (endptr[0] == '\0') { rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid); } else if ((rules->resolve_names > 0) && strchr("$%", value[0]) == NULL) { gid = add_gid(rules, value); rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid); } else if (rules->resolve_names >= 0) rule_add_key(&rule_tmp, TK_A_GROUP, op, value, NULL); rule_tmp.rule.rule.can_set_name = true; continue; } if (streq(key, "MODE")) { mode_t mode; char *endptr; if (op == OP_REMOVE) { log_error("invalid MODE operation"); goto invalid; } mode = strtol(value, &endptr, 8); if (endptr[0] == '\0') rule_add_key(&rule_tmp, TK_A_MODE_ID, op, NULL, &mode); else rule_add_key(&rule_tmp, TK_A_MODE, op, value, NULL); rule_tmp.rule.rule.can_set_name = true; continue; } if (streq(key, "OPTIONS")) { const char *pos; if (op == OP_REMOVE) { log_error("invalid OPTIONS operation"); goto invalid; } pos = strstr(value, "link_priority="); if (pos != NULL) { int prio = atoi(&pos[strlen("link_priority=")]); rule_add_key(&rule_tmp, TK_A_DEVLINK_PRIO, op, NULL, &prio); } pos = strstr(value, "string_escape="); if (pos != NULL) { pos = &pos[strlen("string_escape=")]; if (startswith(pos, "none")) rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_NONE, op, NULL, NULL); else if (startswith(pos, "replace")) rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_REPLACE, op, NULL, NULL); } pos = strstr(value, "db_persist"); if (pos != NULL) rule_add_key(&rule_tmp, TK_A_DB_PERSIST, op, NULL, NULL); pos = strstr(value, "nowatch"); if (pos != NULL) { const int off = 0; rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &off); } else { pos = strstr(value, "watch"); if (pos != NULL) { const int on = 1; rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &on); } } pos = strstr(value, "static_node="); if (pos != NULL) { rule_add_key(&rule_tmp, TK_A_STATIC_NODE, op, &pos[strlen("static_node=")], NULL); rule_tmp.rule.rule.has_static_node = true; } continue; } log_error("unknown key '%s' in %s:%u", key, filename, lineno); goto invalid; } /* add rule token */ rule_tmp.rule.rule.token_count = 1 + rule_tmp.token_cur; if (add_token(rules, &rule_tmp.rule) != 0) goto invalid; /* add tokens to list, sorted by type */ if (sort_token(rules, &rule_tmp) != 0) goto invalid; return 0; invalid: log_error("invalid rule '%s:%u'", filename, lineno); return -1; } static int parse_file(struct udev_rules *rules, const char *filename) { _cleanup_fclose_ FILE *f = NULL; unsigned int first_token; unsigned int filename_off; char line[UTIL_LINE_SIZE]; int line_nr = 0; unsigned int i; f = fopen(filename, "re"); if (!f) { if (errno == ENOENT) return 0; else return -errno; } if (null_or_empty_fd(fileno(f))) { log_debug("Skipping empty file: %s", filename); return 0; } else log_debug("Reading rules file: %s", filename); first_token = rules->token_cur; filename_off = rules_add_string(rules, filename); while (fgets(line, sizeof(line), f) != NULL) { char *key; size_t len; /* skip whitespace */ line_nr++; key = line; while (isspace(key[0])) key++; /* comment */ if (key[0] == '#') continue; len = strlen(line); if (len < 3) continue; /* continue reading if backslash+newline is found */ while (line[len-2] == '\\') { if (fgets(&line[len-2], (sizeof(line)-len)+2, f) == NULL) break; if (strlen(&line[len-2]) < 2) break; line_nr++; len = strlen(line); } if (len+1 >= sizeof(line)) { log_error("line too long '%s':%u, ignored", filename, line_nr); continue; } add_rule(rules, key, filename, filename_off, line_nr); } /* link GOTOs to LABEL rules in this file to be able to fast-forward */ for (i = first_token+1; i < rules->token_cur; i++) { if (rules->tokens[i].type == TK_A_GOTO) { char *label = rules_str(rules, rules->tokens[i].key.value_off); unsigned int j; for (j = i+1; j < rules->token_cur; j++) { if (rules->tokens[j].type != TK_RULE) continue; if (rules->tokens[j].rule.label_off == 0) continue; if (!streq(label, rules_str(rules, rules->tokens[j].rule.label_off))) continue; rules->tokens[i].key.rule_goto = j; break; } if (rules->tokens[i].key.rule_goto == 0) log_error("GOTO '%s' has no matching label in: '%s'", label, filename); } } return 0; } struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) { struct udev_rules *rules; struct udev_list file_list; struct token end_token; char **files, **f; int r; rules = new0(struct udev_rules, 1); if (rules == NULL) return NULL; rules->udev = udev; rules->resolve_names = resolve_names; udev_list_init(udev, &file_list, true); /* init token array and string buffer */ rules->tokens = malloc(PREALLOC_TOKEN * sizeof(struct token)); if (rules->tokens == NULL) return udev_rules_unref(rules); rules->token_max = PREALLOC_TOKEN; rules->strbuf = strbuf_new(); if (!rules->strbuf) return udev_rules_unref(rules); udev_rules_check_timestamp(rules); r = conf_files_list_strv(&files, ".rules", NULL, rules_dirs); if (r < 0) { log_error_errno(r, "failed to enumerate rules files: %m"); return udev_rules_unref(rules); } /* * The offset value in the rules strct is limited; add all * rules file names to the beginning of the string buffer. */ STRV_FOREACH(f, files) rules_add_string(rules, *f); STRV_FOREACH(f, files) parse_file(rules, *f); strv_free(files); memzero(&end_token, sizeof(struct token)); end_token.type = TK_END; add_token(rules, &end_token); log_debug("rules contain %zu bytes tokens (%u * %zu bytes), %zu bytes strings", rules->token_max * sizeof(struct token), rules->token_max, sizeof(struct token), rules->strbuf->len); /* cleanup temporary strbuf data */ log_debug("%zu strings (%zu bytes), %zu de-duplicated (%zu bytes), %zu trie nodes used", rules->strbuf->in_count, rules->strbuf->in_len, rules->strbuf->dedup_count, rules->strbuf->dedup_len, rules->strbuf->nodes_count); strbuf_complete(rules->strbuf); /* cleanup uid/gid cache */ rules->uids = mfree(rules->uids); rules->uids_cur = 0; rules->uids_max = 0; rules->gids = mfree(rules->gids); rules->gids_cur = 0; rules->gids_max = 0; dump_rules(rules); return rules; } struct udev_rules *udev_rules_unref(struct udev_rules *rules) { if (rules == NULL) return NULL; free(rules->tokens); strbuf_cleanup(rules->strbuf); free(rules->uids); free(rules->gids); free(rules); return NULL; } bool udev_rules_check_timestamp(struct udev_rules *rules) { if (!rules) return false; return paths_check_timestamp(rules_dirs, &rules->dirs_ts_usec, true); } static int match_key(struct udev_rules *rules, struct token *token, const char *val) { char *key_value = rules_str(rules, token->key.value_off); char *pos; bool match = false; if (val == NULL) val = ""; switch (token->key.glob) { case GL_PLAIN: match = (streq(key_value, val)); break; case GL_GLOB: match = (fnmatch(key_value, val, 0) == 0); break; case GL_SPLIT: { const char *s; size_t len; s = rules_str(rules, token->key.value_off); len = strlen(val); for (;;) { const char *next; next = strchr(s, '|'); if (next != NULL) { size_t matchlen = (size_t)(next - s); match = (matchlen == len && strneq(s, val, matchlen)); if (match) break; } else { match = (streq(s, val)); break; } s = &next[1]; } break; } case GL_SPLIT_GLOB: { char value[UTIL_PATH_SIZE]; strscpy(value, sizeof(value), rules_str(rules, token->key.value_off)); key_value = value; while (key_value != NULL) { pos = strchr(key_value, '|'); if (pos != NULL) { pos[0] = '\0'; pos = &pos[1]; } match = (fnmatch(key_value, val, 0) == 0); if (match) break; key_value = pos; } break; } case GL_SOMETHING: match = (val[0] != '\0'); break; case GL_UNSET: return -1; } if (match && (token->key.op == OP_MATCH)) return 0; if (!match && (token->key.op == OP_NOMATCH)) return 0; return -1; } static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct udev_event *event, struct token *cur) { const char *name; char nbuf[UTIL_NAME_SIZE]; const char *value; char vbuf[UTIL_NAME_SIZE]; size_t len; name = rules_str(rules, cur->key.attr_off); switch (cur->key.attrsubst) { case SB_FORMAT: udev_event_apply_format(event, name, nbuf, sizeof(nbuf)); name = nbuf; /* fall through */ case SB_NONE: value = udev_device_get_sysattr_value(dev, name); if (value == NULL) return -1; break; case SB_SUBSYS: if (util_resolve_subsys_kernel(event->udev, name, vbuf, sizeof(vbuf), 1) != 0) return -1; value = vbuf; break; default: return -1; } /* remove trailing whitespace, if not asked to match for it */ len = strlen(value); if (len > 0 && isspace(value[len-1])) { const char *key_value; size_t klen; key_value = rules_str(rules, cur->key.value_off); klen = strlen(key_value); if (klen > 0 && !isspace(key_value[klen-1])) { if (value != vbuf) { strscpy(vbuf, sizeof(vbuf), value); value = vbuf; } while (len > 0 && isspace(vbuf[--len])) vbuf[len] = '\0'; } } return match_key(rules, cur, value); } enum escape_type { ESCAPE_UNSET, ESCAPE_NONE, ESCAPE_REPLACE, }; int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, struct udev_list *properties_list) { struct token *cur; struct token *rule; enum escape_type esc = ESCAPE_UNSET; bool can_set_name; if (rules->tokens == NULL) return -1; can_set_name = ((!streq(udev_device_get_action(event->dev), "remove")) && (major(udev_device_get_devnum(event->dev)) > 0 || udev_device_get_ifindex(event->dev) > 0)); /* loop through token list, match, run actions or forward to next rule */ cur = &rules->tokens[0]; rule = cur; for (;;) { dump_token(rules, cur); switch (cur->type) { case TK_RULE: /* current rule */ rule = cur; /* possibly skip rules which want to set NAME, SYMLINK, OWNER, GROUP, MODE */ if (!can_set_name && rule->rule.can_set_name) goto nomatch; esc = ESCAPE_UNSET; break; case TK_M_ACTION: if (match_key(rules, cur, udev_device_get_action(event->dev)) != 0) goto nomatch; break; case TK_M_DEVPATH: if (match_key(rules, cur, udev_device_get_devpath(event->dev)) != 0) goto nomatch; break; case TK_M_KERNEL: if (match_key(rules, cur, udev_device_get_sysname(event->dev)) != 0) goto nomatch; break; case TK_M_DEVLINK: { struct udev_list_entry *list_entry; bool match = false; udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(event->dev)) { const char *devlink; devlink = udev_list_entry_get_name(list_entry) + strlen("/dev/"); if (match_key(rules, cur, devlink) == 0) { match = true; break; } } if (!match) goto nomatch; break; } case TK_M_NAME: if (match_key(rules, cur, event->name) != 0) goto nomatch; break; case TK_M_ENV: { const char *key_name = rules_str(rules, cur->key.attr_off); const char *value; value = udev_device_get_property_value(event->dev, key_name); /* check global properties */ if (!value && properties_list) { struct udev_list_entry *list_entry; list_entry = udev_list_get_entry(properties_list); list_entry = udev_list_entry_get_by_name(list_entry, key_name); if (list_entry != NULL) value = udev_list_entry_get_value(list_entry); } if (!value) value = ""; if (match_key(rules, cur, value)) goto nomatch; break; } case TK_M_TAG: { struct udev_list_entry *list_entry; bool match = false; udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(event->dev)) { if (streq(rules_str(rules, cur->key.value_off), udev_list_entry_get_name(list_entry))) { match = true; break; } } if ((!match && (cur->key.op != OP_NOMATCH)) || (match && (cur->key.op == OP_NOMATCH))) goto nomatch; break; } case TK_M_SUBSYSTEM: if (match_key(rules, cur, udev_device_get_subsystem(event->dev)) != 0) goto nomatch; break; case TK_M_DRIVER: if (match_key(rules, cur, udev_device_get_driver(event->dev)) != 0) goto nomatch; break; case TK_M_ATTR: if (match_attr(rules, event->dev, event, cur) != 0) goto nomatch; break; case TK_M_SYSCTL: { char filename[UTIL_PATH_SIZE]; _cleanup_free_ char *value = NULL; size_t len; udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename)); sysctl_normalize(filename); if (sysctl_read(filename, &value) < 0) goto nomatch; len = strlen(value); while (len > 0 && isspace(value[--len])) value[len] = '\0'; if (match_key(rules, cur, value) != 0) goto nomatch; break; } case TK_M_KERNELS: case TK_M_SUBSYSTEMS: case TK_M_DRIVERS: case TK_M_ATTRS: case TK_M_TAGS: { struct token *next; /* get whole sequence of parent matches */ next = cur; while (next->type > TK_M_PARENTS_MIN && next->type < TK_M_PARENTS_MAX) next++; /* loop over parents */ event->dev_parent = event->dev; for (;;) { struct token *key; /* loop over sequence of parent match keys */ for (key = cur; key < next; key++ ) { dump_token(rules, key); switch(key->type) { case TK_M_KERNELS: if (match_key(rules, key, udev_device_get_sysname(event->dev_parent)) != 0) goto try_parent; break; case TK_M_SUBSYSTEMS: if (match_key(rules, key, udev_device_get_subsystem(event->dev_parent)) != 0) goto try_parent; break; case TK_M_DRIVERS: if (match_key(rules, key, udev_device_get_driver(event->dev_parent)) != 0) goto try_parent; break; case TK_M_ATTRS: if (match_attr(rules, event->dev_parent, event, key) != 0) goto try_parent; break; case TK_M_TAGS: { bool match = udev_device_has_tag(event->dev_parent, rules_str(rules, cur->key.value_off)); if (match && key->key.op == OP_NOMATCH) goto try_parent; if (!match && key->key.op == OP_MATCH) goto try_parent; break; } default: goto nomatch; } } break; try_parent: event->dev_parent = udev_device_get_parent(event->dev_parent); if (event->dev_parent == NULL) goto nomatch; } /* move behind our sequence of parent match keys */ cur = next; continue; } case TK_M_TEST: { char filename[UTIL_PATH_SIZE]; struct stat statbuf; int match; udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename)); if (util_resolve_subsys_kernel(event->udev, filename, filename, sizeof(filename), 0) != 0) { if (filename[0] != '/') { char tmp[UTIL_PATH_SIZE]; strscpy(tmp, sizeof(tmp), filename); strscpyl(filename, sizeof(filename), udev_device_get_syspath(event->dev), "/", tmp, NULL); } } attr_subst_subdir(filename, sizeof(filename)); match = (stat(filename, &statbuf) == 0); if (match && cur->key.mode > 0) match = ((statbuf.st_mode & cur->key.mode) > 0); if (match && cur->key.op == OP_NOMATCH) goto nomatch; if (!match && cur->key.op == OP_MATCH) goto nomatch; break; } case TK_M_PROGRAM: { char program[UTIL_PATH_SIZE]; char result[UTIL_LINE_SIZE]; event->program_result = mfree(event->program_result); udev_event_apply_format(event, rules_str(rules, cur->key.value_off), program, sizeof(program)); log_debug("PROGRAM '%s' %s:%u", program, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, result, sizeof(result)) < 0) { if (cur->key.op != OP_NOMATCH) goto nomatch; } else { int count; util_remove_trailing_chars(result, '\n'); if (esc == ESCAPE_UNSET || esc == ESCAPE_REPLACE) { count = util_replace_chars(result, UDEV_ALLOWED_CHARS_INPUT); if (count > 0) log_debug("%i character(s) replaced" , count); } event->program_result = strdup(result); if (cur->key.op == OP_NOMATCH) goto nomatch; } break; } case TK_M_IMPORT_FILE: { char import[UTIL_PATH_SIZE]; udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import)); if (import_file_into_properties(event->dev, import) != 0) if (cur->key.op != OP_NOMATCH) goto nomatch; break; } case TK_M_IMPORT_PROG: { char import[UTIL_PATH_SIZE]; udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import)); log_debug("IMPORT '%s' %s:%u", import, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); if (import_program_into_properties(event, timeout_usec, timeout_warn_usec, import) != 0) if (cur->key.op != OP_NOMATCH) goto nomatch; break; } case TK_M_IMPORT_BUILTIN: { char command[UTIL_PATH_SIZE]; if (udev_builtin_run_once(cur->key.builtin_cmd)) { /* check if we ran already */ if (event->builtin_run & (1 << cur->key.builtin_cmd)) { log_debug("IMPORT builtin skip '%s' %s:%u", udev_builtin_name(cur->key.builtin_cmd), rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); /* return the result from earlier run */ if (event->builtin_ret & (1 << cur->key.builtin_cmd)) if (cur->key.op != OP_NOMATCH) goto nomatch; break; } /* mark as ran */ event->builtin_run |= (1 << cur->key.builtin_cmd); } udev_event_apply_format(event, rules_str(rules, cur->key.value_off), command, sizeof(command)); log_debug("IMPORT builtin '%s' %s:%u", udev_builtin_name(cur->key.builtin_cmd), rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); if (udev_builtin_run(event->dev, cur->key.builtin_cmd, command, false) != 0) { /* remember failure */ log_debug("IMPORT builtin '%s' returned non-zero", udev_builtin_name(cur->key.builtin_cmd)); event->builtin_ret |= (1 << cur->key.builtin_cmd); if (cur->key.op != OP_NOMATCH) goto nomatch; } break; } case TK_M_IMPORT_DB: { const char *key = rules_str(rules, cur->key.value_off); const char *value; value = udev_device_get_property_value(event->dev_db, key); if (value != NULL) udev_device_add_property(event->dev, key, value); else { if (cur->key.op != OP_NOMATCH) goto nomatch; } break; } case TK_M_IMPORT_CMDLINE: { FILE *f; bool imported = false; f = fopen("/proc/cmdline", "re"); if (f != NULL) { char cmdline[4096]; if (fgets(cmdline, sizeof(cmdline), f) != NULL) { const char *key = rules_str(rules, cur->key.value_off); char *pos; pos = strstr(cmdline, key); if (pos != NULL) { pos += strlen(key); if (pos[0] == '\0' || isspace(pos[0])) { /* we import simple flags as 'FLAG=1' */ udev_device_add_property(event->dev, key, "1"); imported = true; } else if (pos[0] == '=') { const char *value; pos++; value = pos; while (pos[0] != '\0' && !isspace(pos[0])) pos++; pos[0] = '\0'; udev_device_add_property(event->dev, key, value); imported = true; } } } fclose(f); } if (!imported && cur->key.op != OP_NOMATCH) goto nomatch; break; } case TK_M_IMPORT_PARENT: { char import[UTIL_PATH_SIZE]; udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import)); if (import_parent_into_properties(event->dev, import) != 0) if (cur->key.op != OP_NOMATCH) goto nomatch; break; } case TK_M_RESULT: if (match_key(rules, cur, event->program_result) != 0) goto nomatch; break; case TK_A_STRING_ESCAPE_NONE: esc = ESCAPE_NONE; break; case TK_A_STRING_ESCAPE_REPLACE: esc = ESCAPE_REPLACE; break; case TK_A_DB_PERSIST: udev_device_set_db_persist(event->dev); break; case TK_A_INOTIFY_WATCH: if (event->inotify_watch_final) break; if (cur->key.op == OP_ASSIGN_FINAL) event->inotify_watch_final = true; event->inotify_watch = cur->key.watch; break; case TK_A_DEVLINK_PRIO: udev_device_set_devlink_priority(event->dev, cur->key.devlink_prio); break; case TK_A_OWNER: { char owner[UTIL_NAME_SIZE]; const char *ow = owner; int r; if (event->owner_final) break; if (cur->key.op == OP_ASSIGN_FINAL) event->owner_final = true; udev_event_apply_format(event, rules_str(rules, cur->key.value_off), owner, sizeof(owner)); event->owner_set = true; r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL); if (r < 0) { if (r == -ENOENT || r == -ESRCH) log_error("specified user '%s' unknown", owner); else log_error_errno(r, "error resolving user '%s': %m", owner); event->uid = 0; } log_debug("OWNER %u %s:%u", event->uid, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); break; } case TK_A_GROUP: { char group[UTIL_NAME_SIZE]; const char *gr = group; int r; if (event->group_final) break; if (cur->key.op == OP_ASSIGN_FINAL) event->group_final = true; udev_event_apply_format(event, rules_str(rules, cur->key.value_off), group, sizeof(group)); event->group_set = true; r = get_group_creds(&gr, &event->gid); if (r < 0) { if (r == -ENOENT || r == -ESRCH) log_error("specified group '%s' unknown", group); else log_error_errno(r, "error resolving group '%s': %m", group); event->gid = 0; } log_debug("GROUP %u %s:%u", event->gid, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); break; } case TK_A_MODE: { char mode_str[UTIL_NAME_SIZE]; mode_t mode; char *endptr; if (event->mode_final) break; udev_event_apply_format(event, rules_str(rules, cur->key.value_off), mode_str, sizeof(mode_str)); mode = strtol(mode_str, &endptr, 8); if (endptr[0] != '\0') { log_error("ignoring invalid mode '%s'", mode_str); break; } if (cur->key.op == OP_ASSIGN_FINAL) event->mode_final = true; event->mode_set = true; event->mode = mode; log_debug("MODE %#o %s:%u", event->mode, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); break; } case TK_A_OWNER_ID: if (event->owner_final) break; if (cur->key.op == OP_ASSIGN_FINAL) event->owner_final = true; event->owner_set = true; event->uid = cur->key.uid; log_debug("OWNER %u %s:%u", event->uid, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); break; case TK_A_GROUP_ID: if (event->group_final) break; if (cur->key.op == OP_ASSIGN_FINAL) event->group_final = true; event->group_set = true; event->gid = cur->key.gid; log_debug("GROUP %u %s:%u", event->gid, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); break; case TK_A_MODE_ID: if (event->mode_final) break; if (cur->key.op == OP_ASSIGN_FINAL) event->mode_final = true; event->mode_set = true; event->mode = cur->key.mode; log_debug("MODE %#o %s:%u", event->mode, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); break; case TK_A_SECLABEL: { const char *name, *label; name = rules_str(rules, cur->key.attr_off); label = rules_str(rules, cur->key.value_off); if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL) udev_list_cleanup(&event->seclabel_list); udev_list_entry_add(&event->seclabel_list, name, label); log_debug("SECLABEL{%s}='%s' %s:%u", name, label, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); break; } case TK_A_ENV: { const char *name = rules_str(rules, cur->key.attr_off); char *value = rules_str(rules, cur->key.value_off); char value_new[UTIL_NAME_SIZE]; const char *value_old = NULL; if (value[0] == '\0') { if (cur->key.op == OP_ADD) break; udev_device_add_property(event->dev, name, NULL); break; } if (cur->key.op == OP_ADD) value_old = udev_device_get_property_value(event->dev, name); if (value_old) { char temp[UTIL_NAME_SIZE]; /* append value separated by space */ udev_event_apply_format(event, value, temp, sizeof(temp)); strscpyl(value_new, sizeof(value_new), value_old, " ", temp, NULL); } else udev_event_apply_format(event, value, value_new, sizeof(value_new)); udev_device_add_property(event->dev, name, value_new); break; } case TK_A_TAG: { char tag[UTIL_PATH_SIZE]; const char *p; udev_event_apply_format(event, rules_str(rules, cur->key.value_off), tag, sizeof(tag)); if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL) udev_device_cleanup_tags_list(event->dev); for (p = tag; *p != '\0'; p++) { if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '-' || *p == '_') continue; log_error("ignoring invalid tag name '%s'", tag); break; } if (cur->key.op == OP_REMOVE) udev_device_remove_tag(event->dev, tag); else udev_device_add_tag(event->dev, tag); break; } case TK_A_NAME: { const char *name = rules_str(rules, cur->key.value_off); char name_str[UTIL_PATH_SIZE]; int count; if (event->name_final) break; if (cur->key.op == OP_ASSIGN_FINAL) event->name_final = true; udev_event_apply_format(event, name, name_str, sizeof(name_str)); if (esc == ESCAPE_UNSET || esc == ESCAPE_REPLACE) { count = util_replace_chars(name_str, "/"); if (count > 0) log_debug("%i character(s) replaced", count); } if (major(udev_device_get_devnum(event->dev)) && (!streq(name_str, udev_device_get_devnode(event->dev) + strlen("/dev/")))) { log_error("NAME=\"%s\" ignored, kernel device nodes " "can not be renamed; please fix it in %s:%u\n", name, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); break; } free_and_strdup(&event->name, name_str); log_debug("NAME '%s' %s:%u", event->name, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); break; } case TK_A_DEVLINK: { char temp[UTIL_PATH_SIZE]; char filename[UTIL_PATH_SIZE]; char *pos, *next; int count = 0; if (event->devlink_final) break; if (major(udev_device_get_devnum(event->dev)) == 0) break; if (cur->key.op == OP_ASSIGN_FINAL) event->devlink_final = true; if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL) udev_device_cleanup_devlinks_list(event->dev); /* allow multiple symlinks separated by spaces */ udev_event_apply_format(event, rules_str(rules, cur->key.value_off), temp, sizeof(temp)); if (esc == ESCAPE_UNSET) count = util_replace_chars(temp, "/ "); else if (esc == ESCAPE_REPLACE) count = util_replace_chars(temp, "/"); if (count > 0) log_debug("%i character(s) replaced" , count); pos = temp; while (isspace(pos[0])) pos++; next = strchr(pos, ' '); while (next != NULL) { next[0] = '\0'; log_debug("LINK '%s' %s:%u", pos, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); strscpyl(filename, sizeof(filename), "/dev/", pos, NULL); udev_device_add_devlink(event->dev, filename); while (isspace(next[1])) next++; pos = &next[1]; next = strchr(pos, ' '); } if (pos[0] != '\0') { log_debug("LINK '%s' %s:%u", pos, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); strscpyl(filename, sizeof(filename), "/dev/", pos, NULL); udev_device_add_devlink(event->dev, filename); } break; } case TK_A_ATTR: { const char *key_name = rules_str(rules, cur->key.attr_off); char attr[UTIL_PATH_SIZE]; char value[UTIL_NAME_SIZE]; FILE *f; if (util_resolve_subsys_kernel(event->udev, key_name, attr, sizeof(attr), 0) != 0) strscpyl(attr, sizeof(attr), udev_device_get_syspath(event->dev), "/", key_name, NULL); attr_subst_subdir(attr, sizeof(attr)); udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value)); log_debug("ATTR '%s' writing '%s' %s:%u", attr, value, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); f = fopen(attr, "we"); if (f != NULL) { if (fprintf(f, "%s", value) <= 0) log_error_errno(errno, "error writing ATTR{%s}: %m", attr); fclose(f); } else { log_error_errno(errno, "error opening ATTR{%s} for writing: %m", attr); } break; } case TK_A_SYSCTL: { char filename[UTIL_PATH_SIZE]; char value[UTIL_NAME_SIZE]; int r; udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename)); sysctl_normalize(filename); udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value)); log_debug("SYSCTL '%s' writing '%s' %s:%u", filename, value, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); r = sysctl_write(filename, value); if (r < 0) log_error_errno(r, "error writing SYSCTL{%s}='%s': %m", filename, value); break; } case TK_A_RUN_BUILTIN: case TK_A_RUN_PROGRAM: { struct udev_list_entry *entry; if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL) udev_list_cleanup(&event->run_list); log_debug("RUN '%s' %s:%u", rules_str(rules, cur->key.value_off), rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); entry = udev_list_entry_add(&event->run_list, rules_str(rules, cur->key.value_off), NULL); udev_list_entry_set_num(entry, cur->key.builtin_cmd); break; } case TK_A_GOTO: if (cur->key.rule_goto == 0) break; cur = &rules->tokens[cur->key.rule_goto]; continue; case TK_END: return 0; case TK_M_PARENTS_MIN: case TK_M_PARENTS_MAX: case TK_M_MAX: case TK_UNSET: log_error("wrong type %u", cur->type); goto nomatch; } cur++; continue; nomatch: /* fast-forward to next rule */ cur = rule + rule->rule.token_count; } } int udev_rules_apply_static_dev_perms(struct udev_rules *rules) { struct token *cur; struct token *rule; uid_t uid = 0; gid_t gid = 0; mode_t mode = 0; _cleanup_strv_free_ char **tags = NULL; char **t; FILE *f = NULL; _cleanup_free_ char *path = NULL; int r = 0; if (rules->tokens == NULL) return 0; cur = &rules->tokens[0]; rule = cur; for (;;) { switch (cur->type) { case TK_RULE: /* current rule */ rule = cur; /* skip rules without a static_node tag */ if (!rule->rule.has_static_node) goto next; uid = 0; gid = 0; mode = 0; tags = strv_free(tags); break; case TK_A_OWNER_ID: uid = cur->key.uid; break; case TK_A_GROUP_ID: gid = cur->key.gid; break; case TK_A_MODE_ID: mode = cur->key.mode; break; case TK_A_TAG: r = strv_extend(&tags, rules_str(rules, cur->key.value_off)); if (r < 0) goto finish; break; case TK_A_STATIC_NODE: { char device_node[UTIL_PATH_SIZE]; char tags_dir[UTIL_PATH_SIZE]; char tag_symlink[UTIL_PATH_SIZE]; struct stat stats; /* we assure, that the permissions tokens are sorted before the static token */ if (mode == 0 && uid == 0 && gid == 0 && tags == NULL) goto next; strscpyl(device_node, sizeof(device_node), "/dev/", rules_str(rules, cur->key.value_off), NULL); if (stat(device_node, &stats) != 0) break; if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode)) break; /* export the tags to a directory as symlinks, allowing otherwise dead nodes to be tagged */ if (tags) { STRV_FOREACH(t, tags) { _cleanup_free_ char *unescaped_filename = NULL; strscpyl(tags_dir, sizeof(tags_dir), "/run/udev/static_node-tags/", *t, "/", NULL); r = mkdir_p(tags_dir, 0755); if (r < 0) return log_error_errno(r, "failed to create %s: %m", tags_dir); unescaped_filename = xescape(rules_str(rules, cur->key.value_off), "/."); strscpyl(tag_symlink, sizeof(tag_symlink), tags_dir, unescaped_filename, NULL); r = symlink(device_node, tag_symlink); if (r < 0 && errno != EEXIST) return log_error_errno(errno, "failed to create symlink %s -> %s: %m", tag_symlink, device_node); else r = 0; } } /* don't touch the permissions if only the tags were set */ if (mode == 0 && uid == 0 && gid == 0) break; if (mode == 0) { if (gid > 0) mode = 0660; else mode = 0600; } if (mode != (stats.st_mode & 01777)) { r = chmod(device_node, mode); if (r < 0) { log_error("failed to chmod '%s' %#o", device_node, mode); return -errno; } else log_debug("chmod '%s' %#o", device_node, mode); } if ((uid != 0 && uid != stats.st_uid) || (gid != 0 && gid != stats.st_gid)) { r = chown(device_node, uid, gid); if (r < 0) { log_error("failed to chown '%s' %u %u ", device_node, uid, gid); return -errno; } else log_debug("chown '%s' %u %u", device_node, uid, gid); } utimensat(AT_FDCWD, device_node, NULL, 0); break; } case TK_END: goto finish; } cur++; continue; next: /* fast-forward to next rule */ cur = rule + rule->rule.token_count; continue; } finish: if (f) { fflush(f); fchmod(fileno(f), 0644); if (ferror(f) || rename(path, "/run/udev/static_node-tags") < 0) { r = -errno; unlink("/run/udev/static_node-tags"); unlink(path); } fclose(f); } return r; } systemd-229/src/udev/udev-watch.c000066400000000000000000000120721265713322000170300ustar00rootroot00000000000000/* * Copyright (C) 2004-2012 Kay Sievers * Copyright (C) 2009 Canonical Ltd. * Copyright (C) 2009 Scott James Remnant * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include "stdio-util.h" #include "udev.h" static int inotify_fd = -1; /* inotify descriptor, will be shared with rules directory; * set to cloexec since we need our children to be able to add * watches for us */ int udev_watch_init(struct udev *udev) { inotify_fd = inotify_init1(IN_CLOEXEC); if (inotify_fd < 0) log_error_errno(errno, "inotify_init failed: %m"); return inotify_fd; } /* move any old watches directory out of the way, and then restore * the watches */ void udev_watch_restore(struct udev *udev) { if (inotify_fd < 0) return; if (rename("/run/udev/watch", "/run/udev/watch.old") == 0) { DIR *dir; struct dirent *ent; dir = opendir("/run/udev/watch.old"); if (dir == NULL) { log_error_errno(errno, "unable to open old watches dir /run/udev/watch.old; old watches will not be restored: %m"); return; } for (ent = readdir(dir); ent != NULL; ent = readdir(dir)) { char device[UTIL_PATH_SIZE]; ssize_t len; struct udev_device *dev; if (ent->d_name[0] == '.') continue; len = readlinkat(dirfd(dir), ent->d_name, device, sizeof(device)); if (len <= 0 || len == (ssize_t)sizeof(device)) goto unlink; device[len] = '\0'; dev = udev_device_new_from_device_id(udev, device); if (dev == NULL) goto unlink; log_debug("restoring old watch on '%s'", udev_device_get_devnode(dev)); udev_watch_begin(udev, dev); udev_device_unref(dev); unlink: unlinkat(dirfd(dir), ent->d_name, 0); } closedir(dir); rmdir("/run/udev/watch.old"); } else if (errno != ENOENT) log_error_errno(errno, "unable to move watches dir /run/udev/watch; old watches will not be restored: %m"); } void udev_watch_begin(struct udev *udev, struct udev_device *dev) { char filename[UTIL_PATH_SIZE]; int wd; int r; if (inotify_fd < 0) return; log_debug("adding watch on '%s'", udev_device_get_devnode(dev)); wd = inotify_add_watch(inotify_fd, udev_device_get_devnode(dev), IN_CLOSE_WRITE); if (wd < 0) { log_error_errno(errno, "inotify_add_watch(%d, %s, %o) failed: %m", inotify_fd, udev_device_get_devnode(dev), IN_CLOSE_WRITE); return; } xsprintf(filename, "/run/udev/watch/%d", wd); mkdir_parents(filename, 0755); unlink(filename); r = symlink(udev_device_get_id_filename(dev), filename); if (r < 0) log_error_errno(errno, "Failed to create symlink %s: %m", filename); udev_device_set_watch_handle(dev, wd); } void udev_watch_end(struct udev *udev, struct udev_device *dev) { int wd; char filename[UTIL_PATH_SIZE]; if (inotify_fd < 0) return; wd = udev_device_get_watch_handle(dev); if (wd < 0) return; log_debug("removing watch on '%s'", udev_device_get_devnode(dev)); inotify_rm_watch(inotify_fd, wd); xsprintf(filename, "/run/udev/watch/%d", wd); unlink(filename); udev_device_set_watch_handle(dev, -1); } struct udev_device *udev_watch_lookup(struct udev *udev, int wd) { char filename[UTIL_PATH_SIZE]; char device[UTIL_NAME_SIZE]; ssize_t len; if (inotify_fd < 0 || wd < 0) return NULL; xsprintf(filename, "/run/udev/watch/%d", wd); len = readlink(filename, device, sizeof(device)); if (len <= 0 || (size_t)len == sizeof(device)) return NULL; device[len] = '\0'; return udev_device_new_from_device_id(udev, device); } systemd-229/src/udev/udev.conf000066400000000000000000000000611265713322000164220ustar00rootroot00000000000000# see udev.conf(5) for details #udev_log="info" systemd-229/src/udev/udev.h000066400000000000000000000211121265713322000157240ustar00rootroot00000000000000/* * Copyright (C) 2003 Greg Kroah-Hartman * Copyright (C) 2003-2010 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #pragma once #include #include #include "libudev.h" #include "sd-netlink.h" #include "label.h" #include "libudev-private.h" #include "macro.h" #include "strv.h" #include "util.h" struct udev_event { struct udev *udev; struct udev_device *dev; struct udev_device *dev_parent; struct udev_device *dev_db; char *name; char *program_result; mode_t mode; uid_t uid; gid_t gid; struct udev_list seclabel_list; struct udev_list run_list; int exec_delay; usec_t birth_usec; sd_netlink *rtnl; unsigned int builtin_run; unsigned int builtin_ret; bool inotify_watch; bool inotify_watch_final; bool group_set; bool group_final; bool owner_set; bool owner_final; bool mode_set; bool mode_final; bool name_final; bool devlink_final; bool run_final; }; struct udev_watch { struct udev_list_node node; int handle; char *name; }; /* udev-rules.c */ struct udev_rules; struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names); struct udev_rules *udev_rules_unref(struct udev_rules *rules); bool udev_rules_check_timestamp(struct udev_rules *rules); int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, struct udev_list *properties_list); int udev_rules_apply_static_dev_perms(struct udev_rules *rules); /* udev-event.c */ struct udev_event *udev_event_new(struct udev_device *dev); void udev_event_unref(struct udev_event *event); size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size); int udev_event_apply_subsys_kernel(struct udev_event *event, const char *string, char *result, size_t maxsize, int read_value); int udev_event_spawn(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, bool accept_failure, const char *cmd, char *result, size_t ressize); void udev_event_execute_rules(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, struct udev_list *properties_list, struct udev_rules *rules); void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec); int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]); /* udev-watch.c */ int udev_watch_init(struct udev *udev); void udev_watch_restore(struct udev *udev); void udev_watch_begin(struct udev *udev, struct udev_device *dev); void udev_watch_end(struct udev *udev, struct udev_device *dev); struct udev_device *udev_watch_lookup(struct udev *udev, int wd); /* udev-node.c */ void udev_node_add(struct udev_device *dev, bool apply, mode_t mode, uid_t uid, gid_t gid, struct udev_list *seclabel_list); void udev_node_remove(struct udev_device *dev); void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev_old); /* udev-ctrl.c */ struct udev_ctrl; struct udev_ctrl *udev_ctrl_new(struct udev *udev); struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd); int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl); struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl); int udev_ctrl_cleanup(struct udev_ctrl *uctrl); struct udev *udev_ctrl_get_udev(struct udev_ctrl *uctrl); int udev_ctrl_get_fd(struct udev_ctrl *uctrl); int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout); int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout); int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout); int udev_ctrl_send_reload(struct udev_ctrl *uctrl, int timeout); int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout); int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout); int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout); int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout); struct udev_ctrl_connection; struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl); struct udev_ctrl_connection *udev_ctrl_connection_ref(struct udev_ctrl_connection *conn); struct udev_ctrl_connection *udev_ctrl_connection_unref(struct udev_ctrl_connection *conn); struct udev_ctrl_msg; struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn); struct udev_ctrl_msg *udev_ctrl_msg_unref(struct udev_ctrl_msg *ctrl_msg); int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg); int udev_ctrl_get_stop_exec_queue(struct udev_ctrl_msg *ctrl_msg); int udev_ctrl_get_start_exec_queue(struct udev_ctrl_msg *ctrl_msg); int udev_ctrl_get_reload(struct udev_ctrl_msg *ctrl_msg); int udev_ctrl_get_ping(struct udev_ctrl_msg *ctrl_msg); int udev_ctrl_get_exit(struct udev_ctrl_msg *ctrl_msg); const char *udev_ctrl_get_set_env(struct udev_ctrl_msg *ctrl_msg); int udev_ctrl_get_set_children_max(struct udev_ctrl_msg *ctrl_msg); /* built-in commands */ enum udev_builtin_cmd { #ifdef HAVE_BLKID UDEV_BUILTIN_BLKID, #endif UDEV_BUILTIN_BTRFS, UDEV_BUILTIN_HWDB, UDEV_BUILTIN_INPUT_ID, UDEV_BUILTIN_KEYBOARD, #ifdef HAVE_KMOD UDEV_BUILTIN_KMOD, #endif UDEV_BUILTIN_NET_ID, UDEV_BUILTIN_NET_LINK, UDEV_BUILTIN_PATH_ID, UDEV_BUILTIN_USB_ID, #ifdef HAVE_ACL UDEV_BUILTIN_UACCESS, #endif UDEV_BUILTIN_MAX }; struct udev_builtin { const char *name; int (*cmd)(struct udev_device *dev, int argc, char *argv[], bool test); const char *help; int (*init)(struct udev *udev); void (*exit)(struct udev *udev); bool (*validate)(struct udev *udev); bool run_once; }; #ifdef HAVE_BLKID extern const struct udev_builtin udev_builtin_blkid; #endif extern const struct udev_builtin udev_builtin_btrfs; extern const struct udev_builtin udev_builtin_hwdb; extern const struct udev_builtin udev_builtin_input_id; extern const struct udev_builtin udev_builtin_keyboard; #ifdef HAVE_KMOD extern const struct udev_builtin udev_builtin_kmod; #endif extern const struct udev_builtin udev_builtin_net_id; extern const struct udev_builtin udev_builtin_net_setup_link; extern const struct udev_builtin udev_builtin_path_id; extern const struct udev_builtin udev_builtin_usb_id; extern const struct udev_builtin udev_builtin_uaccess; void udev_builtin_init(struct udev *udev); void udev_builtin_exit(struct udev *udev); enum udev_builtin_cmd udev_builtin_lookup(const char *command); const char *udev_builtin_name(enum udev_builtin_cmd cmd); bool udev_builtin_run_once(enum udev_builtin_cmd cmd); int udev_builtin_run(struct udev_device *dev, enum udev_builtin_cmd cmd, const char *command, bool test); void udev_builtin_list(struct udev *udev); bool udev_builtin_validate(struct udev *udev); int udev_builtin_add_property(struct udev_device *dev, bool test, const char *key, const char *val); int udev_builtin_hwdb_lookup(struct udev_device *dev, const char *prefix, const char *modalias, const char *filter, bool test); /* udevadm commands */ struct udevadm_cmd { const char *name; int (*cmd)(struct udev *udev, int argc, char *argv[]); const char *help; int debug; }; extern const struct udevadm_cmd udevadm_info; extern const struct udevadm_cmd udevadm_trigger; extern const struct udevadm_cmd udevadm_settle; extern const struct udevadm_cmd udevadm_control; extern const struct udevadm_cmd udevadm_monitor; extern const struct udevadm_cmd udevadm_hwdb; extern const struct udevadm_cmd udevadm_test; extern const struct udevadm_cmd udevadm_test_builtin; systemd-229/src/udev/udev.pc.in000066400000000000000000000001121265713322000165010ustar00rootroot00000000000000Name: udev Description: udev Version: @VERSION@ udevdir=@udevlibexecdir@ systemd-229/src/udev/udevadm-control.c000066400000000000000000000146201265713322000200650ustar00rootroot00000000000000/* * Copyright (C) 2005-2011 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include #include #include #include "udev-util.h" #include "udev.h" static void print_help(void) { printf("%s control COMMAND\n\n" "Control the udev daemon.\n\n" " -h --help Show this help\n" " --version Show package version\n" " -e --exit Instruct the daemon to cleanup and exit\n" " -l --log-priority=LEVEL Set the udev log level for the daemon\n" " -s --stop-exec-queue Do not execute events, queue only\n" " -S --start-exec-queue Execute events, flush queue\n" " -R --reload Reload rules and databases\n" " -p --property=KEY=VALUE Set a global property for all events\n" " -m --children-max=N Maximum number of children\n" " --timeout=SECONDS Maximum time to block for a reply\n" , program_invocation_short_name); } static int adm_control(struct udev *udev, int argc, char *argv[]) { _cleanup_udev_ctrl_unref_ struct udev_ctrl *uctrl = NULL; int timeout = 60; int rc = 1, c; static const struct option options[] = { { "exit", no_argument, NULL, 'e' }, { "log-priority", required_argument, NULL, 'l' }, { "stop-exec-queue", no_argument, NULL, 's' }, { "start-exec-queue", no_argument, NULL, 'S' }, { "reload", no_argument, NULL, 'R' }, { "reload-rules", no_argument, NULL, 'R' }, /* alias for -R */ { "property", required_argument, NULL, 'p' }, { "env", required_argument, NULL, 'p' }, /* alias for -p */ { "children-max", required_argument, NULL, 'm' }, { "timeout", required_argument, NULL, 't' }, { "help", no_argument, NULL, 'h' }, {} }; if (getuid() != 0) { fprintf(stderr, "root privileges required\n"); return 1; } uctrl = udev_ctrl_new(udev); if (uctrl == NULL) return 2; while ((c = getopt_long(argc, argv, "el:sSRp:m:h", options, NULL)) >= 0) switch (c) { case 'e': if (udev_ctrl_send_exit(uctrl, timeout) < 0) rc = 2; else rc = 0; break; case 'l': { int i; i = util_log_priority(optarg); if (i < 0) { fprintf(stderr, "invalid number '%s'\n", optarg); return rc; } if (udev_ctrl_send_set_log_level(uctrl, util_log_priority(optarg), timeout) < 0) rc = 2; else rc = 0; break; } case 's': if (udev_ctrl_send_stop_exec_queue(uctrl, timeout) < 0) rc = 2; else rc = 0; break; case 'S': if (udev_ctrl_send_start_exec_queue(uctrl, timeout) < 0) rc = 2; else rc = 0; break; case 'R': if (udev_ctrl_send_reload(uctrl, timeout) < 0) rc = 2; else rc = 0; break; case 'p': if (strchr(optarg, '=') == NULL) { fprintf(stderr, "expect = instead of '%s'\n", optarg); return rc; } if (udev_ctrl_send_set_env(uctrl, optarg, timeout) < 0) rc = 2; else rc = 0; break; case 'm': { char *endp; int i; i = strtoul(optarg, &endp, 0); if (endp[0] != '\0' || i < 1) { fprintf(stderr, "invalid number '%s'\n", optarg); return rc; } if (udev_ctrl_send_set_children_max(uctrl, i, timeout) < 0) rc = 2; else rc = 0; break; } case 't': { int seconds; seconds = atoi(optarg); if (seconds >= 0) timeout = seconds; else fprintf(stderr, "invalid timeout value\n"); break; } case 'h': print_help(); rc = 0; break; } if (optind < argc) fprintf(stderr, "Extraneous argument: %s\n", argv[optind]); else if (optind == 1) fprintf(stderr, "Option missing\n"); return rc; } const struct udevadm_cmd udevadm_control = { .name = "control", .cmd = adm_control, .help = "Control the udev daemon", }; systemd-229/src/udev/udevadm-hwdb.c000066400000000000000000000573111265713322000173350ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include "alloc-util.h" #include "conf-files.h" #include "fileio.h" #include "fs-util.h" #include "hwdb-internal.h" #include "hwdb-util.h" #include "strbuf.h" #include "string-util.h" #include "udev.h" #include "util.h" /* * Generic udev properties, key/value database based on modalias strings. * Uses a Patricia/radix trie to index all matches for efficient lookup. */ static const char * const conf_file_dirs[] = { "/etc/udev/hwdb.d", UDEVLIBEXECDIR "/hwdb.d", NULL }; /* in-memory trie objects */ struct trie { struct trie_node *root; struct strbuf *strings; size_t nodes_count; size_t children_count; size_t values_count; }; struct trie_node { /* prefix, common part for all children of this node */ size_t prefix_off; /* sorted array of pointers to children nodes */ struct trie_child_entry *children; uint8_t children_count; /* sorted array of key/value pairs */ struct trie_value_entry *values; size_t values_count; }; /* children array item with char (0-255) index */ struct trie_child_entry { uint8_t c; struct trie_node *child; }; /* value array item with key/value pairs */ struct trie_value_entry { size_t key_off; size_t value_off; }; static int trie_children_cmp(const void *v1, const void *v2) { const struct trie_child_entry *n1 = v1; const struct trie_child_entry *n2 = v2; return n1->c - n2->c; } static int node_add_child(struct trie *trie, struct trie_node *node, struct trie_node *node_child, uint8_t c) { struct trie_child_entry *child; /* extend array, add new entry, sort for bisection */ child = realloc(node->children, (node->children_count + 1) * sizeof(struct trie_child_entry)); if (!child) return -ENOMEM; node->children = child; trie->children_count++; node->children[node->children_count].c = c; node->children[node->children_count].child = node_child; node->children_count++; qsort(node->children, node->children_count, sizeof(struct trie_child_entry), trie_children_cmp); trie->nodes_count++; return 0; } static struct trie_node *node_lookup(const struct trie_node *node, uint8_t c) { struct trie_child_entry *child; struct trie_child_entry search; search.c = c; child = bsearch(&search, node->children, node->children_count, sizeof(struct trie_child_entry), trie_children_cmp); if (child) return child->child; return NULL; } static void trie_node_cleanup(struct trie_node *node) { size_t i; for (i = 0; i < node->children_count; i++) trie_node_cleanup(node->children[i].child); free(node->children); free(node->values); free(node); } static int trie_values_cmp(const void *v1, const void *v2, void *arg) { const struct trie_value_entry *val1 = v1; const struct trie_value_entry *val2 = v2; struct trie *trie = arg; return strcmp(trie->strings->buf + val1->key_off, trie->strings->buf + val2->key_off); } static int trie_node_add_value(struct trie *trie, struct trie_node *node, const char *key, const char *value) { ssize_t k, v; struct trie_value_entry *val; k = strbuf_add_string(trie->strings, key, strlen(key)); if (k < 0) return k; v = strbuf_add_string(trie->strings, value, strlen(value)); if (v < 0) return v; if (node->values_count) { struct trie_value_entry search = { .key_off = k, .value_off = v, }; val = xbsearch_r(&search, node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie); if (val) { /* replace existing earlier key with new value */ val->value_off = v; return 0; } } /* extend array, add new entry, sort for bisection */ val = realloc(node->values, (node->values_count + 1) * sizeof(struct trie_value_entry)); if (!val) return -ENOMEM; trie->values_count++; node->values = val; node->values[node->values_count].key_off = k; node->values[node->values_count].value_off = v; node->values_count++; qsort_r(node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie); return 0; } static int trie_insert(struct trie *trie, struct trie_node *node, const char *search, const char *key, const char *value) { size_t i = 0; int err = 0; for (;;) { size_t p; uint8_t c; struct trie_node *child; for (p = 0; (c = trie->strings->buf[node->prefix_off + p]); p++) { _cleanup_free_ char *s = NULL; ssize_t off; _cleanup_free_ struct trie_node *new_child = NULL; if (c == search[i + p]) continue; /* split node */ new_child = new0(struct trie_node, 1); if (!new_child) return -ENOMEM; /* move values from parent to child */ new_child->prefix_off = node->prefix_off + p+1; new_child->children = node->children; new_child->children_count = node->children_count; new_child->values = node->values; new_child->values_count = node->values_count; /* update parent; use strdup() because the source gets realloc()d */ s = strndup(trie->strings->buf + node->prefix_off, p); if (!s) return -ENOMEM; off = strbuf_add_string(trie->strings, s, p); if (off < 0) return off; node->prefix_off = off; node->children = NULL; node->children_count = 0; node->values = NULL; node->values_count = 0; err = node_add_child(trie, node, new_child, c); if (err) return err; new_child = NULL; /* avoid cleanup */ break; } i += p; c = search[i]; if (c == '\0') return trie_node_add_value(trie, node, key, value); child = node_lookup(node, c); if (!child) { ssize_t off; /* new child */ child = new0(struct trie_node, 1); if (!child) return -ENOMEM; off = strbuf_add_string(trie->strings, search + i+1, strlen(search + i+1)); if (off < 0) { free(child); return off; } child->prefix_off = off; err = node_add_child(trie, node, child, c); if (err) { free(child); return err; } return trie_node_add_value(trie, child, key, value); } node = child; i++; } } struct trie_f { FILE *f; struct trie *trie; uint64_t strings_off; uint64_t nodes_count; uint64_t children_count; uint64_t values_count; }; /* calculate the storage space for the nodes, children arrays, value arrays */ static void trie_store_nodes_size(struct trie_f *trie, struct trie_node *node) { uint64_t i; for (i = 0; i < node->children_count; i++) trie_store_nodes_size(trie, node->children[i].child); trie->strings_off += sizeof(struct trie_node_f); for (i = 0; i < node->children_count; i++) trie->strings_off += sizeof(struct trie_child_entry_f); for (i = 0; i < node->values_count; i++) trie->strings_off += sizeof(struct trie_value_entry_f); } static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node) { uint64_t i; struct trie_node_f n = { .prefix_off = htole64(trie->strings_off + node->prefix_off), .children_count = node->children_count, .values_count = htole64(node->values_count), }; struct trie_child_entry_f *children = NULL; int64_t node_off; if (node->children_count) { children = new0(struct trie_child_entry_f, node->children_count); if (!children) return -ENOMEM; } /* post-order recursion */ for (i = 0; i < node->children_count; i++) { int64_t child_off; child_off = trie_store_nodes(trie, node->children[i].child); if (child_off < 0) { free(children); return child_off; } children[i].c = node->children[i].c; children[i].child_off = htole64(child_off); } /* write node */ node_off = ftello(trie->f); fwrite(&n, sizeof(struct trie_node_f), 1, trie->f); trie->nodes_count++; /* append children array */ if (node->children_count) { fwrite(children, sizeof(struct trie_child_entry_f), node->children_count, trie->f); trie->children_count += node->children_count; free(children); } /* append values array */ for (i = 0; i < node->values_count; i++) { struct trie_value_entry_f v = { .key_off = htole64(trie->strings_off + node->values[i].key_off), .value_off = htole64(trie->strings_off + node->values[i].value_off), }; fwrite(&v, sizeof(struct trie_value_entry_f), 1, trie->f); trie->values_count++; } return node_off; } static int trie_store(struct trie *trie, const char *filename) { struct trie_f t = { .trie = trie, }; _cleanup_free_ char *filename_tmp = NULL; int64_t pos; int64_t root_off; int64_t size; struct trie_header_f h = { .signature = HWDB_SIG, .tool_version = htole64(atoi(VERSION)), .header_size = htole64(sizeof(struct trie_header_f)), .node_size = htole64(sizeof(struct trie_node_f)), .child_entry_size = htole64(sizeof(struct trie_child_entry_f)), .value_entry_size = htole64(sizeof(struct trie_value_entry_f)), }; int err; /* calculate size of header, nodes, children entries, value entries */ t.strings_off = sizeof(struct trie_header_f); trie_store_nodes_size(&t, trie->root); err = fopen_temporary(filename , &t.f, &filename_tmp); if (err < 0) return err; fchmod(fileno(t.f), 0444); /* write nodes */ err = fseeko(t.f, sizeof(struct trie_header_f), SEEK_SET); if (err < 0) { fclose(t.f); unlink_noerrno(filename_tmp); return -errno; } root_off = trie_store_nodes(&t, trie->root); h.nodes_root_off = htole64(root_off); pos = ftello(t.f); h.nodes_len = htole64(pos - sizeof(struct trie_header_f)); /* write string buffer */ fwrite(trie->strings->buf, trie->strings->len, 1, t.f); h.strings_len = htole64(trie->strings->len); /* write header */ size = ftello(t.f); h.file_size = htole64(size); err = fseeko(t.f, 0, SEEK_SET); if (err < 0) { fclose(t.f); unlink_noerrno(filename_tmp); return -errno; } fwrite(&h, sizeof(struct trie_header_f), 1, t.f); err = ferror(t.f); if (err) err = -errno; fclose(t.f); if (err < 0 || rename(filename_tmp, filename) < 0) { unlink_noerrno(filename_tmp); return err < 0 ? err : -errno; } log_debug("=== trie on-disk ==="); log_debug("size: %8"PRIi64" bytes", size); log_debug("header: %8zu bytes", sizeof(struct trie_header_f)); log_debug("nodes: %8"PRIu64" bytes (%8"PRIu64")", t.nodes_count * sizeof(struct trie_node_f), t.nodes_count); log_debug("child pointers: %8"PRIu64" bytes (%8"PRIu64")", t.children_count * sizeof(struct trie_child_entry_f), t.children_count); log_debug("value pointers: %8"PRIu64" bytes (%8"PRIu64")", t.values_count * sizeof(struct trie_value_entry_f), t.values_count); log_debug("string store: %8zu bytes", trie->strings->len); log_debug("strings start: %8"PRIu64, t.strings_off); return 0; } static int insert_data(struct trie *trie, struct udev_list *match_list, char *line, const char *filename) { char *value; struct udev_list_entry *entry; value = strchr(line, '='); if (!value) { log_error("Error, key/value pair expected but got '%s' in '%s':", line, filename); return -EINVAL; } value[0] = '\0'; value++; /* libudev requires properties to start with a space */ while (isblank(line[0]) && isblank(line[1])) line++; if (line[0] == '\0' || value[0] == '\0') { log_error("Error, empty key or value '%s' in '%s':", line, filename); return -EINVAL; } udev_list_entry_foreach(entry, udev_list_get_entry(match_list)) trie_insert(trie, trie->root, udev_list_entry_get_name(entry), line, value); return 0; } static int import_file(struct udev *udev, struct trie *trie, const char *filename) { enum { HW_MATCH, HW_DATA, HW_NONE, } state = HW_NONE; FILE *f; char line[LINE_MAX]; struct udev_list match_list; udev_list_init(udev, &match_list, false); f = fopen(filename, "re"); if (f == NULL) return -errno; while (fgets(line, sizeof(line), f)) { size_t len; char *pos; /* comment line */ if (line[0] == '#') continue; /* strip trailing comment */ pos = strchr(line, '#'); if (pos) pos[0] = '\0'; /* strip trailing whitespace */ len = strlen(line); while (len > 0 && isspace(line[len-1])) len--; line[len] = '\0'; switch (state) { case HW_NONE: if (len == 0) break; if (line[0] == ' ') { log_error("Error, MATCH expected but got '%s' in '%s':", line, filename); break; } /* start of record, first match */ state = HW_MATCH; udev_list_entry_add(&match_list, line, NULL); break; case HW_MATCH: if (len == 0) { log_error("Error, DATA expected but got empty line in '%s':", filename); state = HW_NONE; udev_list_cleanup(&match_list); break; } /* another match */ if (line[0] != ' ') { udev_list_entry_add(&match_list, line, NULL); break; } /* first data */ state = HW_DATA; insert_data(trie, &match_list, line, filename); break; case HW_DATA: /* end of record */ if (len == 0) { state = HW_NONE; udev_list_cleanup(&match_list); break; } if (line[0] != ' ') { log_error("Error, DATA expected but got '%s' in '%s':", line, filename); state = HW_NONE; udev_list_cleanup(&match_list); break; } insert_data(trie, &match_list, line, filename); break; }; } fclose(f); udev_list_cleanup(&match_list); return 0; } static void help(void) { printf("Usage: udevadm hwdb OPTIONS\n" " -u,--update update the hardware database\n" " --usr generate in " UDEVLIBEXECDIR " instead of /etc/udev\n" " -t,--test=MODALIAS query database and print result\n" " -r,--root=PATH alternative root path in the filesystem\n" " -h,--help\n\n"); } static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { enum { ARG_USR = 0x100, }; static const struct option options[] = { { "update", no_argument, NULL, 'u' }, { "usr", no_argument, NULL, ARG_USR }, { "test", required_argument, NULL, 't' }, { "root", required_argument, NULL, 'r' }, { "help", no_argument, NULL, 'h' }, {} }; const char *test = NULL; const char *root = ""; const char *hwdb_bin_dir = "/etc/udev"; bool update = false; struct trie *trie = NULL; int err, c; int rc = EXIT_SUCCESS; while ((c = getopt_long(argc, argv, "ut:r:h", options, NULL)) >= 0) switch(c) { case 'u': update = true; break; case ARG_USR: hwdb_bin_dir = UDEVLIBEXECDIR; break; case 't': test = optarg; break; case 'r': root = optarg; break; case 'h': help(); return EXIT_SUCCESS; case '?': return EXIT_FAILURE; default: assert_not_reached("Unknown option"); } if (!update && !test) { log_error("Either --update or --test must be used"); return EXIT_FAILURE; } if (update) { char **files, **f; _cleanup_free_ char *hwdb_bin = NULL; trie = new0(struct trie, 1); if (!trie) { rc = EXIT_FAILURE; goto out; } /* string store */ trie->strings = strbuf_new(); if (!trie->strings) { rc = EXIT_FAILURE; goto out; } /* index */ trie->root = new0(struct trie_node, 1); if (!trie->root) { rc = EXIT_FAILURE; goto out; } trie->nodes_count++; err = conf_files_list_strv(&files, ".hwdb", root, conf_file_dirs); if (err < 0) { log_error_errno(err, "failed to enumerate hwdb files: %m"); rc = EXIT_FAILURE; goto out; } STRV_FOREACH(f, files) { log_debug("reading file '%s'", *f); import_file(udev, trie, *f); } strv_free(files); strbuf_complete(trie->strings); log_debug("=== trie in-memory ==="); log_debug("nodes: %8zu bytes (%8zu)", trie->nodes_count * sizeof(struct trie_node), trie->nodes_count); log_debug("children arrays: %8zu bytes (%8zu)", trie->children_count * sizeof(struct trie_child_entry), trie->children_count); log_debug("values arrays: %8zu bytes (%8zu)", trie->values_count * sizeof(struct trie_value_entry), trie->values_count); log_debug("strings: %8zu bytes", trie->strings->len); log_debug("strings incoming: %8zu bytes (%8zu)", trie->strings->in_len, trie->strings->in_count); log_debug("strings dedup'ed: %8zu bytes (%8zu)", trie->strings->dedup_len, trie->strings->dedup_count); hwdb_bin = strjoin(root, "/", hwdb_bin_dir, "/hwdb.bin", NULL); if (!hwdb_bin) { rc = EXIT_FAILURE; goto out; } mkdir_parents(hwdb_bin, 0755); err = trie_store(trie, hwdb_bin); if (err < 0) { log_error_errno(err, "Failure writing database %s: %m", hwdb_bin); rc = EXIT_FAILURE; } } if (test) { _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; int r; r = sd_hwdb_new(&hwdb); if (r >= 0) { const char *key, *value; SD_HWDB_FOREACH_PROPERTY(hwdb, test, key, value) printf("%s=%s\n", key, value); } } out: if (trie) { if (trie->root) trie_node_cleanup(trie->root); strbuf_cleanup(trie->strings); free(trie); } return rc; } const struct udevadm_cmd udevadm_hwdb = { .name = "hwdb", .cmd = adm_hwdb, }; systemd-229/src/udev/udevadm-info.c000066400000000000000000000455311265713322000173450ustar00rootroot00000000000000/* * Copyright (C) 2004-2009 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "fd-util.h" #include "string-util.h" #include "udev-util.h" #include "udev.h" #include "udevadm-util.h" static bool skip_attribute(const char *name) { static const char* const skip[] = { "uevent", "dev", "modalias", "resource", "driver", "subsystem", "module", }; unsigned int i; for (i = 0; i < ELEMENTSOF(skip); i++) if (streq(name, skip[i])) return true; return false; } static void print_all_attributes(struct udev_device *device, const char *key) { struct udev_list_entry *sysattr; udev_list_entry_foreach(sysattr, udev_device_get_sysattr_list_entry(device)) { const char *name; const char *value; size_t len; name = udev_list_entry_get_name(sysattr); if (skip_attribute(name)) continue; value = udev_device_get_sysattr_value(device, name); if (value == NULL) continue; /* skip any values that look like a path */ if (value[0] == '/') continue; /* skip nonprintable attributes */ len = strlen(value); while (len > 0 && isprint(value[len-1])) len--; if (len > 0) continue; printf(" %s{%s}==\"%s\"\n", key, name, value); } printf("\n"); } static int print_device_chain(struct udev_device *device) { struct udev_device *device_parent; const char *str; printf("\n" "Udevadm info starts with the device specified by the devpath and then\n" "walks up the chain of parent devices. It prints for every device\n" "found, all possible attributes in the udev rules key format.\n" "A rule to match, can be composed by the attributes of the device\n" "and the attributes from one single parent device.\n" "\n"); printf(" looking at device '%s':\n", udev_device_get_devpath(device)); printf(" KERNEL==\"%s\"\n", udev_device_get_sysname(device)); str = udev_device_get_subsystem(device); if (str == NULL) str = ""; printf(" SUBSYSTEM==\"%s\"\n", str); str = udev_device_get_driver(device); if (str == NULL) str = ""; printf(" DRIVER==\"%s\"\n", str); print_all_attributes(device, "ATTR"); device_parent = device; do { device_parent = udev_device_get_parent(device_parent); if (device_parent == NULL) break; printf(" looking at parent device '%s':\n", udev_device_get_devpath(device_parent)); printf(" KERNELS==\"%s\"\n", udev_device_get_sysname(device_parent)); str = udev_device_get_subsystem(device_parent); if (str == NULL) str = ""; printf(" SUBSYSTEMS==\"%s\"\n", str); str = udev_device_get_driver(device_parent); if (str == NULL) str = ""; printf(" DRIVERS==\"%s\"\n", str); print_all_attributes(device_parent, "ATTRS"); } while (device_parent != NULL); return 0; } static void print_record(struct udev_device *device) { const char *str; int i; struct udev_list_entry *list_entry; printf("P: %s\n", udev_device_get_devpath(device)); str = udev_device_get_devnode(device); if (str != NULL) printf("N: %s\n", str + strlen("/dev/")); i = udev_device_get_devlink_priority(device); if (i != 0) printf("L: %i\n", i); udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) printf("S: %s\n", udev_list_entry_get_name(list_entry) + strlen("/dev/")); udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) printf("E: %s=%s\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry)); printf("\n"); } static int stat_device(const char *name, bool export, const char *prefix) { struct stat statbuf; if (stat(name, &statbuf) != 0) return -1; if (export) { if (prefix == NULL) prefix = "INFO_"; printf("%sMAJOR=%u\n" "%sMINOR=%u\n", prefix, major(statbuf.st_dev), prefix, minor(statbuf.st_dev)); } else printf("%u:%u\n", major(statbuf.st_dev), minor(statbuf.st_dev)); return 0; } static int export_devices(struct udev *udev) { struct udev_enumerate *udev_enumerate; struct udev_list_entry *list_entry; udev_enumerate = udev_enumerate_new(udev); if (udev_enumerate == NULL) return -1; udev_enumerate_scan_devices(udev_enumerate); udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) { struct udev_device *device; device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry)); if (device != NULL) { print_record(device); udev_device_unref(device); } } udev_enumerate_unref(udev_enumerate); return 0; } static void cleanup_dir(DIR *dir, mode_t mask, int depth) { struct dirent *dent; if (depth <= 0) return; for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { struct stat stats; if (dent->d_name[0] == '.') continue; if (fstatat(dirfd(dir), dent->d_name, &stats, AT_SYMLINK_NOFOLLOW) != 0) continue; if ((stats.st_mode & mask) != 0) continue; if (S_ISDIR(stats.st_mode)) { _cleanup_closedir_ DIR *dir2; dir2 = fdopendir(openat(dirfd(dir), dent->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)); if (dir2 != NULL) cleanup_dir(dir2, mask, depth-1); (void) unlinkat(dirfd(dir), dent->d_name, AT_REMOVEDIR); } else (void) unlinkat(dirfd(dir), dent->d_name, 0); } } static void cleanup_db(struct udev *udev) { DIR *dir; unlink("/run/udev/queue.bin"); dir = opendir("/run/udev/data"); if (dir != NULL) { cleanup_dir(dir, S_ISVTX, 1); closedir(dir); } dir = opendir("/run/udev/links"); if (dir != NULL) { cleanup_dir(dir, 0, 2); closedir(dir); } dir = opendir("/run/udev/tags"); if (dir != NULL) { cleanup_dir(dir, 0, 2); closedir(dir); } dir = opendir("/run/udev/static_node-tags"); if (dir != NULL) { cleanup_dir(dir, 0, 2); closedir(dir); } dir = opendir("/run/udev/watch"); if (dir != NULL) { cleanup_dir(dir, 0, 1); closedir(dir); } } static void help(void) { printf("%s info [OPTIONS] [DEVPATH|FILE]\n\n" "Query sysfs or the udev database.\n\n" " -h --help Print this message\n" " --version Print version of the program\n" " -q --query=TYPE Query device information:\n" " name Name of device node\n" " symlink Pointing to node\n" " path sysfs device path\n" " property The device properties\n" " all All values\n" " -p --path=SYSPATH sysfs device path used for query or attribute walk\n" " -n --name=NAME Node or symlink name used for query or attribute walk\n" " -r --root Prepend dev directory to path names\n" " -a --attribute-walk Print all key matches walking along the chain\n" " of parent devices\n" " -d --device-id-of-file=FILE Print major:minor of device containing this file\n" " -x --export Export key/value pairs\n" " -P --export-prefix Export the key name with a prefix\n" " -e --export-db Export the content of the udev database\n" " -c --cleanup-db Clean up the udev database\n" , program_invocation_short_name); } static int uinfo(struct udev *udev, int argc, char *argv[]) { _cleanup_udev_device_unref_ struct udev_device *device = NULL; bool root = 0; bool export = 0; const char *export_prefix = NULL; char name[UTIL_PATH_SIZE]; struct udev_list_entry *list_entry; int c; static const struct option options[] = { { "name", required_argument, NULL, 'n' }, { "path", required_argument, NULL, 'p' }, { "query", required_argument, NULL, 'q' }, { "attribute-walk", no_argument, NULL, 'a' }, { "cleanup-db", no_argument, NULL, 'c' }, { "export-db", no_argument, NULL, 'e' }, { "root", no_argument, NULL, 'r' }, { "device-id-of-file", required_argument, NULL, 'd' }, { "export", no_argument, NULL, 'x' }, { "export-prefix", required_argument, NULL, 'P' }, { "version", no_argument, NULL, 'V' }, { "help", no_argument, NULL, 'h' }, {} }; enum action_type { ACTION_QUERY, ACTION_ATTRIBUTE_WALK, ACTION_DEVICE_ID_FILE, } action = ACTION_QUERY; enum query_type { QUERY_NAME, QUERY_PATH, QUERY_SYMLINK, QUERY_PROPERTY, QUERY_ALL, } query = QUERY_ALL; while ((c = getopt_long(argc, argv, "aced:n:p:q:rxP:RVh", options, NULL)) >= 0) switch (c) { case 'n': { if (device != NULL) { fprintf(stderr, "device already specified\n"); return 2; } device = find_device(udev, optarg, "/dev/"); if (device == NULL) { fprintf(stderr, "device node not found\n"); return 2; } break; } case 'p': if (device != NULL) { fprintf(stderr, "device already specified\n"); return 2; } device = find_device(udev, optarg, "/sys"); if (device == NULL) { fprintf(stderr, "syspath not found\n"); return 2; } break; case 'q': action = ACTION_QUERY; if (streq(optarg, "property") || streq(optarg, "env")) query = QUERY_PROPERTY; else if (streq(optarg, "name")) query = QUERY_NAME; else if (streq(optarg, "symlink")) query = QUERY_SYMLINK; else if (streq(optarg, "path")) query = QUERY_PATH; else if (streq(optarg, "all")) query = QUERY_ALL; else { fprintf(stderr, "unknown query type\n"); return 3; } break; case 'r': root = true; break; case 'd': action = ACTION_DEVICE_ID_FILE; strscpy(name, sizeof(name), optarg); break; case 'a': action = ACTION_ATTRIBUTE_WALK; break; case 'e': export_devices(udev); return 0; case 'c': cleanup_db(udev); return 0; case 'x': export = true; break; case 'P': export_prefix = optarg; break; case 'V': printf("%s\n", VERSION); return 0; case 'h': help(); return 0; default: return 1; } switch (action) { case ACTION_QUERY: if (!device) { if (!argv[optind]) { help(); return 2; } device = find_device(udev, argv[optind], NULL); if (!device) { fprintf(stderr, "Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.\n"); return 4; } } switch(query) { case QUERY_NAME: { const char *node = udev_device_get_devnode(device); if (node == NULL) { fprintf(stderr, "no device node found\n"); return 5; } if (root) printf("%s\n", udev_device_get_devnode(device)); else printf("%s\n", udev_device_get_devnode(device) + strlen("/dev/")); break; } case QUERY_SYMLINK: list_entry = udev_device_get_devlinks_list_entry(device); while (list_entry != NULL) { if (root) printf("%s", udev_list_entry_get_name(list_entry)); else printf("%s", udev_list_entry_get_name(list_entry) + strlen("/dev/")); list_entry = udev_list_entry_get_next(list_entry); if (list_entry != NULL) printf(" "); } printf("\n"); break; case QUERY_PATH: printf("%s\n", udev_device_get_devpath(device)); return 0; case QUERY_PROPERTY: list_entry = udev_device_get_properties_list_entry(device); while (list_entry != NULL) { if (export) { const char *prefix = export_prefix; if (prefix == NULL) prefix = ""; printf("%s%s='%s'\n", prefix, udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry)); } else { printf("%s=%s\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry)); } list_entry = udev_list_entry_get_next(list_entry); } break; case QUERY_ALL: print_record(device); break; default: assert_not_reached("unknown query type"); } break; case ACTION_ATTRIBUTE_WALK: if (!device && argv[optind]) { device = find_device(udev, argv[optind], NULL); if (!device) { fprintf(stderr, "Unknown device, absolute path in /dev/ or /sys expected.\n"); return 4; } } if (!device) { fprintf(stderr, "Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.\n"); return 4; } print_device_chain(device); break; case ACTION_DEVICE_ID_FILE: if (stat_device(name, export, export_prefix) != 0) return 1; break; } return 0; } const struct udevadm_cmd udevadm_info = { .name = "info", .cmd = uinfo, .help = "Query sysfs or the udev database", }; systemd-229/src/udev/udevadm-monitor.c000066400000000000000000000262021265713322000200730ustar00rootroot00000000000000/* * Copyright (C) 2004-2010 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include "fd-util.h" #include "formats-util.h" #include "udev-util.h" #include "udev.h" static bool udev_exit; static void sig_handler(int signum) { if (signum == SIGINT || signum == SIGTERM) udev_exit = true; } static void print_device(struct udev_device *device, const char *source, int prop) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); printf("%-6s[%"PRI_TIME".%06ld] %-8s %s (%s)\n", source, ts.tv_sec, ts.tv_nsec/1000, udev_device_get_action(device), udev_device_get_devpath(device), udev_device_get_subsystem(device)); if (prop) { struct udev_list_entry *list_entry; udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) printf("%s=%s\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry)); printf("\n"); } } static void help(void) { printf("%s monitor [--property] [--kernel] [--udev] [--help]\n\n" "Listen to kernel and udev events.\n\n" " -h --help Show this help\n" " --version Show package version\n" " -p --property Print the event properties\n" " -k --kernel Print kernel uevents\n" " -u --udev Print udev events\n" " -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem\n" " -t --tag-match=TAG Filter events by tag\n" , program_invocation_short_name); } static int adm_monitor(struct udev *udev, int argc, char *argv[]) { struct sigaction act = {}; sigset_t mask; bool prop = false; bool print_kernel = false; bool print_udev = false; _cleanup_udev_list_cleanup_ struct udev_list subsystem_match_list; _cleanup_udev_list_cleanup_ struct udev_list tag_match_list; _cleanup_udev_monitor_unref_ struct udev_monitor *udev_monitor = NULL; _cleanup_udev_monitor_unref_ struct udev_monitor *kernel_monitor = NULL; _cleanup_close_ int fd_ep = -1; int fd_kernel = -1, fd_udev = -1; struct epoll_event ep_kernel, ep_udev; int c; static const struct option options[] = { { "property", no_argument, NULL, 'p' }, { "environment", no_argument, NULL, 'e' }, /* alias for -p */ { "kernel", no_argument, NULL, 'k' }, { "udev", no_argument, NULL, 'u' }, { "subsystem-match", required_argument, NULL, 's' }, { "tag-match", required_argument, NULL, 't' }, { "help", no_argument, NULL, 'h' }, {} }; udev_list_init(udev, &subsystem_match_list, true); udev_list_init(udev, &tag_match_list, true); while((c = getopt_long(argc, argv, "pekus:t:h", options, NULL)) >= 0) switch (c) { case 'p': case 'e': prop = true; break; case 'k': print_kernel = true; break; case 'u': print_udev = true; break; case 's': { char subsys[UTIL_NAME_SIZE]; char *devtype; strscpy(subsys, sizeof(subsys), optarg); devtype = strchr(subsys, '/'); if (devtype != NULL) { devtype[0] = '\0'; devtype++; } udev_list_entry_add(&subsystem_match_list, subsys, devtype); break; } case 't': udev_list_entry_add(&tag_match_list, optarg, NULL); break; case 'h': help(); return 0; default: return 1; } if (!print_kernel && !print_udev) { print_kernel = true; print_udev = true; } /* set signal handlers */ act.sa_handler = sig_handler; act.sa_flags = SA_RESTART; sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); sigemptyset(&mask); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGTERM); sigprocmask(SIG_UNBLOCK, &mask, NULL); fd_ep = epoll_create1(EPOLL_CLOEXEC); if (fd_ep < 0) { log_error_errno(errno, "error creating epoll fd: %m"); return 1; } printf("monitor will print the received events for:\n"); if (print_udev) { struct udev_list_entry *entry; udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); if (udev_monitor == NULL) { fprintf(stderr, "error: unable to create netlink socket\n"); return 1; } udev_monitor_set_receive_buffer_size(udev_monitor, 128*1024*1024); fd_udev = udev_monitor_get_fd(udev_monitor); udev_list_entry_foreach(entry, udev_list_get_entry(&subsystem_match_list)) { const char *subsys = udev_list_entry_get_name(entry); const char *devtype = udev_list_entry_get_value(entry); if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, subsys, devtype) < 0) fprintf(stderr, "error: unable to apply subsystem filter '%s'\n", subsys); } udev_list_entry_foreach(entry, udev_list_get_entry(&tag_match_list)) { const char *tag = udev_list_entry_get_name(entry); if (udev_monitor_filter_add_match_tag(udev_monitor, tag) < 0) fprintf(stderr, "error: unable to apply tag filter '%s'\n", tag); } if (udev_monitor_enable_receiving(udev_monitor) < 0) { fprintf(stderr, "error: unable to subscribe to udev events\n"); return 2; } memzero(&ep_udev, sizeof(struct epoll_event)); ep_udev.events = EPOLLIN; ep_udev.data.fd = fd_udev; if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) { log_error_errno(errno, "fail to add fd to epoll: %m"); return 2; } printf("UDEV - the event which udev sends out after rule processing\n"); } if (print_kernel) { struct udev_list_entry *entry; kernel_monitor = udev_monitor_new_from_netlink(udev, "kernel"); if (kernel_monitor == NULL) { fprintf(stderr, "error: unable to create netlink socket\n"); return 3; } udev_monitor_set_receive_buffer_size(kernel_monitor, 128*1024*1024); fd_kernel = udev_monitor_get_fd(kernel_monitor); udev_list_entry_foreach(entry, udev_list_get_entry(&subsystem_match_list)) { const char *subsys = udev_list_entry_get_name(entry); if (udev_monitor_filter_add_match_subsystem_devtype(kernel_monitor, subsys, NULL) < 0) fprintf(stderr, "error: unable to apply subsystem filter '%s'\n", subsys); } if (udev_monitor_enable_receiving(kernel_monitor) < 0) { fprintf(stderr, "error: unable to subscribe to kernel events\n"); return 4; } memzero(&ep_kernel, sizeof(struct epoll_event)); ep_kernel.events = EPOLLIN; ep_kernel.data.fd = fd_kernel; if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_kernel, &ep_kernel) < 0) { log_error_errno(errno, "fail to add fd to epoll: %m"); return 5; } printf("KERNEL - the kernel uevent\n"); } printf("\n"); while (!udev_exit) { int fdcount; struct epoll_event ev[4]; int i; fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1); if (fdcount < 0) { if (errno != EINTR) fprintf(stderr, "error receiving uevent message: %m\n"); continue; } for (i = 0; i < fdcount; i++) { if (ev[i].data.fd == fd_kernel && ev[i].events & EPOLLIN) { struct udev_device *device; device = udev_monitor_receive_device(kernel_monitor); if (device == NULL) continue; print_device(device, "KERNEL", prop); udev_device_unref(device); } else if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN) { struct udev_device *device; device = udev_monitor_receive_device(udev_monitor); if (device == NULL) continue; print_device(device, "UDEV", prop); udev_device_unref(device); } } } return 0; } const struct udevadm_cmd udevadm_monitor = { .name = "monitor", .cmd = adm_monitor, .help = "Listen to kernel and udev events", }; systemd-229/src/udev/udevadm-settle.c000066400000000000000000000124771265713322000177150ustar00rootroot00000000000000/* * Copyright (C) 2006-2009 Kay Sievers * Copyright (C) 2009 Canonical Ltd. * Copyright (C) 2009 Scott James Remnant * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include "parse-util.h" #include "udev.h" #include "util.h" static void help(void) { printf("%s settle OPTIONS\n\n" "Wait for pending udev events.\n\n" " -h --help Show this help\n" " --version Show package version\n" " -t --timeout=SECONDS Maximum time to wait for events\n" " -E --exit-if-exists=FILE Stop waiting if file exists\n" , program_invocation_short_name); } static int adm_settle(struct udev *udev, int argc, char *argv[]) { static const struct option options[] = { { "timeout", required_argument, NULL, 't' }, { "exit-if-exists", required_argument, NULL, 'E' }, { "help", no_argument, NULL, 'h' }, { "seq-start", required_argument, NULL, 's' }, /* removed */ { "seq-end", required_argument, NULL, 'e' }, /* removed */ { "quiet", no_argument, NULL, 'q' }, /* removed */ {} }; usec_t deadline; const char *exists = NULL; unsigned int timeout = 120; struct pollfd pfd[1] = { {.fd = -1}, }; int c; struct udev_queue *queue; int rc = EXIT_FAILURE; while ((c = getopt_long(argc, argv, "t:E:hs:e:q", options, NULL)) >= 0) { switch (c) { case 't': { int r; r = safe_atou(optarg, &timeout); if (r < 0) { log_error_errno(r, "Invalid timeout value '%s': %m", optarg); return EXIT_FAILURE; } break; } case 'E': exists = optarg; break; case 'h': help(); return EXIT_SUCCESS; case 's': case 'e': case 'q': log_info("Option -%c no longer supported.", c); return EXIT_FAILURE; case '?': return EXIT_FAILURE; default: assert_not_reached("Unknown argument"); } } if (optind < argc) { fprintf(stderr, "Extraneous argument: '%s'\n", argv[optind]); return EXIT_FAILURE; } deadline = now(CLOCK_MONOTONIC) + timeout * USEC_PER_SEC; /* guarantee that the udev daemon isn't pre-processing */ if (getuid() == 0) { struct udev_ctrl *uctrl; uctrl = udev_ctrl_new(udev); if (uctrl != NULL) { if (udev_ctrl_send_ping(uctrl, MAX(5U, timeout)) < 0) { log_debug("no connection to daemon"); udev_ctrl_unref(uctrl); return EXIT_SUCCESS; } udev_ctrl_unref(uctrl); } } queue = udev_queue_new(udev); if (!queue) { log_error("unable to get udev queue"); return EXIT_FAILURE; } pfd[0].events = POLLIN; pfd[0].fd = udev_queue_get_fd(queue); if (pfd[0].fd < 0) { log_debug("queue is empty, nothing to watch"); rc = EXIT_SUCCESS; goto out; } for (;;) { if (exists && access(exists, F_OK) >= 0) { rc = EXIT_SUCCESS; break; } /* exit if queue is empty */ if (udev_queue_get_queue_is_empty(queue)) { rc = EXIT_SUCCESS; break; } if (now(CLOCK_MONOTONIC) >= deadline) break; /* wake up when queue is empty */ if (poll(pfd, 1, MSEC_PER_SEC) > 0 && pfd[0].revents & POLLIN) udev_queue_flush(queue); } out: udev_queue_unref(queue); return rc; } const struct udevadm_cmd udevadm_settle = { .name = "settle", .cmd = adm_settle, .help = "Wait for pending udev events", }; systemd-229/src/udev/udevadm-test-builtin.c000066400000000000000000000066351265713322000210370ustar00rootroot00000000000000/* * Copyright (C) 2011 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "string-util.h" #include "udev.h" static void help(struct udev *udev) { printf("%s builtin [--help] COMMAND SYSPATH\n\n" "Test a built-in command.\n\n" " -h --help Print this message\n" " --version Print version of the program\n\n" "Commands:\n" , program_invocation_short_name); udev_builtin_list(udev); } static int adm_builtin(struct udev *udev, int argc, char *argv[]) { static const struct option options[] = { { "help", no_argument, NULL, 'h' }, {} }; char *command = NULL; char *syspath = NULL; char filename[UTIL_PATH_SIZE]; struct udev_device *dev = NULL; enum udev_builtin_cmd cmd; int rc = EXIT_SUCCESS, c; while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(udev); goto out; } command = argv[optind++]; if (command == NULL) { fprintf(stderr, "command missing\n"); help(udev); rc = 2; goto out; } syspath = argv[optind++]; if (syspath == NULL) { fprintf(stderr, "syspath missing\n"); rc = 3; goto out; } udev_builtin_init(udev); cmd = udev_builtin_lookup(command); if (cmd >= UDEV_BUILTIN_MAX) { fprintf(stderr, "unknown command '%s'\n", command); help(udev); rc = 5; goto out; } /* add /sys if needed */ if (!startswith(syspath, "/sys")) strscpyl(filename, sizeof(filename), "/sys", syspath, NULL); else strscpy(filename, sizeof(filename), syspath); util_remove_trailing_chars(filename, '/'); dev = udev_device_new_from_syspath(udev, filename); if (dev == NULL) { fprintf(stderr, "unable to open device '%s'\n\n", filename); rc = 4; goto out; } rc = udev_builtin_run(dev, cmd, command, true); if (rc < 0) { fprintf(stderr, "error executing '%s', exit code %i\n\n", command, rc); rc = 6; } out: udev_device_unref(dev); udev_builtin_exit(udev); return rc; } const struct udevadm_cmd udevadm_test_builtin = { .name = "test-builtin", .cmd = adm_builtin, .help = "Test a built-in command", .debug = true, }; systemd-229/src/udev/udevadm-test.c000066400000000000000000000132721265713322000173660ustar00rootroot00000000000000/* * Copyright (C) 2003-2004 Greg Kroah-Hartman * Copyright (C) 2004-2008 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include "string-util.h" #include "udev-util.h" #include "udev.h" static void help(void) { printf("%s test OPTIONS \n\n" "Test an event run.\n" " -h --help Show this help\n" " --version Show package version\n" " -a --action=ACTION Set action string\n" " -N --resolve-names=early|late|never When to resolve names\n" , program_invocation_short_name); } static int adm_test(struct udev *udev, int argc, char *argv[]) { int resolve_names = 1; char filename[UTIL_PATH_SIZE]; const char *action = "add"; const char *syspath = NULL; struct udev_list_entry *entry; _cleanup_udev_rules_unref_ struct udev_rules *rules = NULL; _cleanup_udev_device_unref_ struct udev_device *dev = NULL; _cleanup_udev_event_unref_ struct udev_event *event = NULL; sigset_t mask, sigmask_orig; int rc = 0, c; static const struct option options[] = { { "action", required_argument, NULL, 'a' }, { "resolve-names", required_argument, NULL, 'N' }, { "help", no_argument, NULL, 'h' }, {} }; log_debug("version %s", VERSION); while((c = getopt_long(argc, argv, "a:N:h", options, NULL)) >= 0) switch (c) { case 'a': action = optarg; break; case 'N': if (streq (optarg, "early")) { resolve_names = 1; } else if (streq (optarg, "late")) { resolve_names = 0; } else if (streq (optarg, "never")) { resolve_names = -1; } else { fprintf(stderr, "resolve-names must be early, late or never\n"); log_error("resolve-names must be early, late or never"); exit(EXIT_FAILURE); } break; case 'h': help(); exit(EXIT_SUCCESS); case '?': exit(EXIT_FAILURE); default: assert_not_reached("Unknown option"); } syspath = argv[optind]; if (syspath == NULL) { fprintf(stderr, "syspath parameter missing\n"); rc = 2; goto out; } printf("This program is for debugging only, it does not run any program\n" "specified by a RUN key. It may show incorrect results, because\n" "some values may be different, or not available at a simulation run.\n" "\n"); sigprocmask(SIG_SETMASK, NULL, &sigmask_orig); udev_builtin_init(udev); rules = udev_rules_new(udev, resolve_names); if (rules == NULL) { fprintf(stderr, "error reading rules\n"); rc = 3; goto out; } /* add /sys if needed */ if (!startswith(syspath, "/sys")) strscpyl(filename, sizeof(filename), "/sys", syspath, NULL); else strscpy(filename, sizeof(filename), syspath); util_remove_trailing_chars(filename, '/'); dev = udev_device_new_from_synthetic_event(udev, filename, action); if (dev == NULL) { fprintf(stderr, "unable to open device '%s'\n", filename); rc = 4; goto out; } /* don't read info from the db */ udev_device_set_info_loaded(dev); event = udev_event_new(dev); sigfillset(&mask); sigprocmask(SIG_SETMASK, &mask, &sigmask_orig); udev_event_execute_rules(event, 60 * USEC_PER_SEC, 20 * USEC_PER_SEC, NULL, rules); udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) printf("%s=%s\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry)); udev_list_entry_foreach(entry, udev_list_get_entry(&event->run_list)) { char program[UTIL_PATH_SIZE]; udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program)); printf("run: '%s'\n", program); } out: udev_builtin_exit(udev); return rc; } const struct udevadm_cmd udevadm_test = { .name = "test", .cmd = adm_test, .help = "Test an event run", .debug = true, }; systemd-229/src/udev/udevadm-trigger.c000066400000000000000000000300511265713322000200440ustar00rootroot00000000000000/* * Copyright (C) 2008-2009 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include "string-util.h" #include "udev-util.h" #include "udev.h" #include "udevadm-util.h" #include "util.h" static int verbose; static int dry_run; static void exec_list(struct udev_enumerate *udev_enumerate, const char *action) { struct udev_list_entry *entry; udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(udev_enumerate)) { char filename[UTIL_PATH_SIZE]; int fd; if (verbose) printf("%s\n", udev_list_entry_get_name(entry)); if (dry_run) continue; strscpyl(filename, sizeof(filename), udev_list_entry_get_name(entry), "/uevent", NULL); fd = open(filename, O_WRONLY|O_CLOEXEC); if (fd < 0) continue; if (write(fd, action, strlen(action)) < 0) log_debug_errno(errno, "error writing '%s' to '%s': %m", action, filename); close(fd); } } static const char *keyval(const char *str, const char **val, char *buf, size_t size) { char *pos; strscpy(buf, size,str); pos = strchr(buf, '='); if (pos != NULL) { pos[0] = 0; pos++; } *val = pos; return buf; } static void help(void) { printf("%s trigger OPTIONS\n\n" "Request events from the kernel.\n\n" " -h --help Show this help\n" " --version Show package version\n" " -v --verbose Print the list of devices while running\n" " -n --dry-run Do not actually trigger the events\n" " -t --type= Type of events to trigger\n" " devices sysfs devices (default)\n" " subsystems sysfs subsystems and drivers\n" " -c --action=ACTION Event action value, default is \"change\"\n" " -s --subsystem-match=SUBSYSTEM Trigger devices from a matching subsystem\n" " -S --subsystem-nomatch=SUBSYSTEM Exclude devices from a matching subsystem\n" " -a --attr-match=FILE[=VALUE] Trigger devices with a matching attribute\n" " -A --attr-nomatch=FILE[=VALUE] Exclude devices with a matching attribute\n" " -p --property-match=KEY=VALUE Trigger devices with a matching property\n" " -g --tag-match=KEY=VALUE Trigger devices with a matching property\n" " -y --sysname-match=NAME Trigger devices with this /sys path\n" " --name-match=NAME Trigger devices with this /dev name\n" " -b --parent-match=NAME Trigger devices with that parent device\n" , program_invocation_short_name); } static int adm_trigger(struct udev *udev, int argc, char *argv[]) { enum { ARG_NAME = 0x100, }; static const struct option options[] = { { "verbose", no_argument, NULL, 'v' }, { "dry-run", no_argument, NULL, 'n' }, { "type", required_argument, NULL, 't' }, { "action", required_argument, NULL, 'c' }, { "subsystem-match", required_argument, NULL, 's' }, { "subsystem-nomatch", required_argument, NULL, 'S' }, { "attr-match", required_argument, NULL, 'a' }, { "attr-nomatch", required_argument, NULL, 'A' }, { "property-match", required_argument, NULL, 'p' }, { "tag-match", required_argument, NULL, 'g' }, { "sysname-match", required_argument, NULL, 'y' }, { "name-match", required_argument, NULL, ARG_NAME }, { "parent-match", required_argument, NULL, 'b' }, { "help", no_argument, NULL, 'h' }, {} }; enum { TYPE_DEVICES, TYPE_SUBSYSTEMS, } device_type = TYPE_DEVICES; const char *action = "change"; _cleanup_udev_enumerate_unref_ struct udev_enumerate *udev_enumerate = NULL; int c, r; udev_enumerate = udev_enumerate_new(udev); if (udev_enumerate == NULL) return 1; while ((c = getopt_long(argc, argv, "vno:t:c:s:S:a:A:p:g:y:b:h", options, NULL)) >= 0) { const char *key; const char *val; char buf[UTIL_PATH_SIZE]; switch (c) { case 'v': verbose = 1; break; case 'n': dry_run = 1; break; case 't': if (streq(optarg, "devices")) device_type = TYPE_DEVICES; else if (streq(optarg, "subsystems")) device_type = TYPE_SUBSYSTEMS; else { log_error("unknown type --type=%s", optarg); return 2; } break; case 'c': if (!nulstr_contains("add\0" "remove\0" "change\0", optarg)) { log_error("unknown action '%s'", optarg); return 2; } else action = optarg; break; case 's': r = udev_enumerate_add_match_subsystem(udev_enumerate, optarg); if (r < 0) { log_error_errno(r, "could not add subsystem match '%s': %m", optarg); return 2; } break; case 'S': r = udev_enumerate_add_nomatch_subsystem(udev_enumerate, optarg); if (r < 0) { log_error_errno(r, "could not add negative subsystem match '%s': %m", optarg); return 2; } break; case 'a': key = keyval(optarg, &val, buf, sizeof(buf)); r = udev_enumerate_add_match_sysattr(udev_enumerate, key, val); if (r < 0) { log_error_errno(r, "could not add sysattr match '%s=%s': %m", key, val); return 2; } break; case 'A': key = keyval(optarg, &val, buf, sizeof(buf)); r = udev_enumerate_add_nomatch_sysattr(udev_enumerate, key, val); if (r < 0) { log_error_errno(r, "could not add negative sysattr match '%s=%s': %m", key, val); return 2; } break; case 'p': key = keyval(optarg, &val, buf, sizeof(buf)); r = udev_enumerate_add_match_property(udev_enumerate, key, val); if (r < 0) { log_error_errno(r, "could not add property match '%s=%s': %m", key, val); return 2; } break; case 'g': r = udev_enumerate_add_match_tag(udev_enumerate, optarg); if (r < 0) { log_error_errno(r, "could not add tag match '%s': %m", optarg); return 2; } break; case 'y': r = udev_enumerate_add_match_sysname(udev_enumerate, optarg); if (r < 0) { log_error_errno(r, "could not add sysname match '%s': %m", optarg); return 2; } break; case 'b': { _cleanup_udev_device_unref_ struct udev_device *dev; dev = find_device(udev, optarg, "/sys"); if (dev == NULL) { log_error("unable to open the device '%s'", optarg); return 2; } r = udev_enumerate_add_match_parent(udev_enumerate, dev); if (r < 0) { log_error_errno(r, "could not add parent match '%s': %m", optarg); return 2; } break; } case ARG_NAME: { _cleanup_udev_device_unref_ struct udev_device *dev; dev = find_device(udev, optarg, "/dev/"); if (dev == NULL) { log_error("unable to open the device '%s'", optarg); return 2; } r = udev_enumerate_add_match_parent(udev_enumerate, dev); if (r < 0) { log_error_errno(r, "could not add parent match '%s': %m", optarg); return 2; } break; } case 'h': help(); return 0; case '?': return 1; default: assert_not_reached("Unknown option"); } } for (; optind < argc; optind++) { _cleanup_udev_device_unref_ struct udev_device *dev; dev = find_device(udev, argv[optind], NULL); if (dev == NULL) { log_error("unable to open the device '%s'", argv[optind]); return 2; } r = udev_enumerate_add_match_parent(udev_enumerate, dev); if (r < 0) { log_error_errno(r, "could not add tag match '%s': %m", optarg); return 2; } } switch (device_type) { case TYPE_SUBSYSTEMS: udev_enumerate_scan_subsystems(udev_enumerate); exec_list(udev_enumerate, action); return 0; case TYPE_DEVICES: udev_enumerate_scan_devices(udev_enumerate); exec_list(udev_enumerate, action); return 0; default: assert_not_reached("device_type"); } } const struct udevadm_cmd udevadm_trigger = { .name = "trigger", .cmd = adm_trigger, .help = "Request events from the kernel", }; systemd-229/src/udev/udevadm-util.c000066400000000000000000000032411265713322000173570ustar00rootroot00000000000000/* * Copyright (C) 2008-2009 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "string-util.h" #include "udevadm-util.h" struct udev_device *find_device(struct udev *udev, const char *id, const char *prefix) { assert(udev); assert(id); if (prefix && !startswith(id, prefix)) id = strjoina(prefix, id); if (startswith(id, "/dev/")) { struct stat statbuf; char type; if (stat(id, &statbuf) < 0) return NULL; if (S_ISBLK(statbuf.st_mode)) type = 'b'; else if (S_ISCHR(statbuf.st_mode)) type = 'c'; else return NULL; return udev_device_new_from_devnum(udev, type, statbuf.st_rdev); } else if (startswith(id, "/sys/")) return udev_device_new_from_syspath(udev, id); else return NULL; } systemd-229/src/udev/udevadm-util.h000066400000000000000000000016211265713322000173640ustar00rootroot00000000000000/* * Copyright (C) 2014 Zbigniew Jędrzejewski-Szmek * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #pragma once #include "udev.h" struct udev_device *find_device(struct udev *udev, const char *id, const char *prefix); systemd-229/src/udev/udevadm.c000066400000000000000000000102101265713322000163760ustar00rootroot00000000000000/* * Copyright (C) 2007-2012 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include "selinux-util.h" #include "string-util.h" #include "udev.h" static int adm_version(struct udev *udev, int argc, char *argv[]) { printf("%s\n", VERSION); return 0; } static const struct udevadm_cmd udevadm_version = { .name = "version", .cmd = adm_version, }; static int adm_help(struct udev *udev, int argc, char *argv[]); static const struct udevadm_cmd udevadm_help = { .name = "help", .cmd = adm_help, }; static const struct udevadm_cmd *udevadm_cmds[] = { &udevadm_info, &udevadm_trigger, &udevadm_settle, &udevadm_control, &udevadm_monitor, &udevadm_hwdb, &udevadm_test, &udevadm_test_builtin, &udevadm_version, &udevadm_help, }; static int adm_help(struct udev *udev, int argc, char *argv[]) { unsigned int i; printf("%s [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]\n\n" "Send control commands or test the device manager.\n\n" "Commands:\n" , program_invocation_short_name); for (i = 0; i < ELEMENTSOF(udevadm_cmds); i++) if (udevadm_cmds[i]->help != NULL) printf(" %-12s %s\n", udevadm_cmds[i]->name, udevadm_cmds[i]->help); return 0; } static int run_command(struct udev *udev, const struct udevadm_cmd *cmd, int argc, char *argv[]) { if (cmd->debug) log_set_max_level(LOG_DEBUG); log_debug("calling: %s", cmd->name); return cmd->cmd(udev, argc, argv); } int main(int argc, char *argv[]) { struct udev *udev; static const struct option options[] = { { "debug", no_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, {} }; const char *command; unsigned int i; int rc = 1, c; udev = udev_new(); if (udev == NULL) goto out; log_parse_environment(); log_open(); mac_selinux_init("/dev"); while ((c = getopt_long(argc, argv, "+dhV", options, NULL)) >= 0) switch (c) { case 'd': log_set_max_level(LOG_DEBUG); break; case 'h': rc = adm_help(udev, argc, argv); goto out; case 'V': rc = adm_version(udev, argc, argv); goto out; default: goto out; } command = argv[optind]; if (command != NULL) for (i = 0; i < ELEMENTSOF(udevadm_cmds); i++) if (streq(udevadm_cmds[i]->name, command)) { argc -= optind; argv += optind; /* we need '0' here to reset the internal state */ optind = 0; rc = run_command(udev, udevadm_cmds[i], argc, argv); goto out; } fprintf(stderr, "%s: missing or unknown command\n", program_invocation_short_name); rc = 2; out: mac_selinux_finish(); udev_unref(udev); log_close(); return rc; } systemd-229/src/udev/udevd.c000066400000000000000000001756131265713322000161030ustar00rootroot00000000000000/* * Copyright (C) 2004-2012 Kay Sievers * Copyright (C) 2004 Chris Friesen * Copyright (C) 2009 Canonical Ltd. * Copyright (C) 2009 Scott James Remnant * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sd-daemon.h" #include "sd-event.h" #include "alloc-util.h" #include "cgroup-util.h" #include "cpu-set-util.h" #include "dev-setup.h" #include "fd-util.h" #include "fileio.h" #include "formats-util.h" #include "fs-util.h" #include "hashmap.h" #include "io-util.h" #include "netlink-util.h" #include "parse-util.h" #include "proc-cmdline.h" #include "process-util.h" #include "selinux-util.h" #include "signal-util.h" #include "socket-util.h" #include "string-util.h" #include "terminal-util.h" #include "udev-util.h" #include "udev.h" #include "user-util.h" static bool arg_debug = false; static int arg_daemonize = false; static int arg_resolve_names = 1; static unsigned arg_children_max; static int arg_exec_delay; static usec_t arg_event_timeout_usec = 180 * USEC_PER_SEC; static usec_t arg_event_timeout_warn_usec = 180 * USEC_PER_SEC / 3; typedef struct Manager { struct udev *udev; sd_event *event; Hashmap *workers; struct udev_list_node events; const char *cgroup; pid_t pid; /* the process that originally allocated the manager object */ struct udev_rules *rules; struct udev_list properties; struct udev_monitor *monitor; struct udev_ctrl *ctrl; struct udev_ctrl_connection *ctrl_conn_blocking; int fd_inotify; int worker_watch[2]; sd_event_source *ctrl_event; sd_event_source *uevent_event; sd_event_source *inotify_event; usec_t last_usec; bool stop_exec_queue:1; bool exit:1; } Manager; enum event_state { EVENT_UNDEF, EVENT_QUEUED, EVENT_RUNNING, }; struct event { struct udev_list_node node; Manager *manager; struct udev *udev; struct udev_device *dev; struct udev_device *dev_kernel; struct worker *worker; enum event_state state; unsigned long long int delaying_seqnum; unsigned long long int seqnum; const char *devpath; size_t devpath_len; const char *devpath_old; dev_t devnum; int ifindex; bool is_block; sd_event_source *timeout_warning; sd_event_source *timeout; }; static inline struct event *node_to_event(struct udev_list_node *node) { return container_of(node, struct event, node); } static void event_queue_cleanup(Manager *manager, enum event_state type); enum worker_state { WORKER_UNDEF, WORKER_RUNNING, WORKER_IDLE, WORKER_KILLED, }; struct worker { Manager *manager; struct udev_list_node node; int refcount; pid_t pid; struct udev_monitor *monitor; enum worker_state state; struct event *event; }; /* passed from worker to main process */ struct worker_message { }; static void event_free(struct event *event) { int r; if (!event) return; udev_list_node_remove(&event->node); udev_device_unref(event->dev); udev_device_unref(event->dev_kernel); sd_event_source_unref(event->timeout_warning); sd_event_source_unref(event->timeout); if (event->worker) event->worker->event = NULL; assert(event->manager); if (udev_list_node_is_empty(&event->manager->events)) { /* only clean up the queue from the process that created it */ if (event->manager->pid == getpid()) { r = unlink("/run/udev/queue"); if (r < 0) log_warning_errno(errno, "could not unlink /run/udev/queue: %m"); } } free(event); } static void worker_free(struct worker *worker) { if (!worker) return; assert(worker->manager); hashmap_remove(worker->manager->workers, PID_TO_PTR(worker->pid)); udev_monitor_unref(worker->monitor); event_free(worker->event); free(worker); } static void manager_workers_free(Manager *manager) { struct worker *worker; Iterator i; assert(manager); HASHMAP_FOREACH(worker, manager->workers, i) worker_free(worker); manager->workers = hashmap_free(manager->workers); } static int worker_new(struct worker **ret, Manager *manager, struct udev_monitor *worker_monitor, pid_t pid) { _cleanup_free_ struct worker *worker = NULL; int r; assert(ret); assert(manager); assert(worker_monitor); assert(pid > 1); worker = new0(struct worker, 1); if (!worker) return -ENOMEM; worker->refcount = 1; worker->manager = manager; /* close monitor, but keep address around */ udev_monitor_disconnect(worker_monitor); worker->monitor = udev_monitor_ref(worker_monitor); worker->pid = pid; r = hashmap_ensure_allocated(&manager->workers, NULL); if (r < 0) return r; r = hashmap_put(manager->workers, PID_TO_PTR(pid), worker); if (r < 0) return r; *ret = worker; worker = NULL; return 0; } static int on_event_timeout(sd_event_source *s, uint64_t usec, void *userdata) { struct event *event = userdata; assert(event); assert(event->worker); kill_and_sigcont(event->worker->pid, SIGKILL); event->worker->state = WORKER_KILLED; log_error("seq %llu '%s' killed", udev_device_get_seqnum(event->dev), event->devpath); return 1; } static int on_event_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) { struct event *event = userdata; assert(event); log_warning("seq %llu '%s' is taking a long time", udev_device_get_seqnum(event->dev), event->devpath); return 1; } static void worker_attach_event(struct worker *worker, struct event *event) { sd_event *e; uint64_t usec; assert(worker); assert(worker->manager); assert(event); assert(!event->worker); assert(!worker->event); worker->state = WORKER_RUNNING; worker->event = event; event->state = EVENT_RUNNING; event->worker = worker; e = worker->manager->event; assert_se(sd_event_now(e, clock_boottime_or_monotonic(), &usec) >= 0); (void) sd_event_add_time(e, &event->timeout_warning, clock_boottime_or_monotonic(), usec + arg_event_timeout_warn_usec, USEC_PER_SEC, on_event_timeout_warning, event); (void) sd_event_add_time(e, &event->timeout, clock_boottime_or_monotonic(), usec + arg_event_timeout_usec, USEC_PER_SEC, on_event_timeout, event); } static void manager_free(Manager *manager) { if (!manager) return; udev_builtin_exit(manager->udev); sd_event_source_unref(manager->ctrl_event); sd_event_source_unref(manager->uevent_event); sd_event_source_unref(manager->inotify_event); udev_unref(manager->udev); sd_event_unref(manager->event); manager_workers_free(manager); event_queue_cleanup(manager, EVENT_UNDEF); udev_monitor_unref(manager->monitor); udev_ctrl_unref(manager->ctrl); udev_ctrl_connection_unref(manager->ctrl_conn_blocking); udev_list_cleanup(&manager->properties); udev_rules_unref(manager->rules); safe_close(manager->fd_inotify); safe_close_pair(manager->worker_watch); free(manager); } DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); static int worker_send_message(int fd) { struct worker_message message = {}; return loop_write(fd, &message, sizeof(message), false); } static void worker_spawn(Manager *manager, struct event *event) { struct udev *udev = event->udev; _cleanup_udev_monitor_unref_ struct udev_monitor *worker_monitor = NULL; pid_t pid; int r = 0; /* listen for new events */ worker_monitor = udev_monitor_new_from_netlink(udev, NULL); if (worker_monitor == NULL) return; /* allow the main daemon netlink address to send devices to the worker */ udev_monitor_allow_unicast_sender(worker_monitor, manager->monitor); r = udev_monitor_enable_receiving(worker_monitor); if (r < 0) log_error_errno(r, "worker: could not enable receiving of device: %m"); pid = fork(); switch (pid) { case 0: { struct udev_device *dev = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; int fd_monitor; _cleanup_close_ int fd_signal = -1, fd_ep = -1; struct epoll_event ep_signal = { .events = EPOLLIN }; struct epoll_event ep_monitor = { .events = EPOLLIN }; sigset_t mask; /* take initial device from queue */ dev = event->dev; event->dev = NULL; unsetenv("NOTIFY_SOCKET"); manager_workers_free(manager); event_queue_cleanup(manager, EVENT_UNDEF); manager->monitor = udev_monitor_unref(manager->monitor); manager->ctrl_conn_blocking = udev_ctrl_connection_unref(manager->ctrl_conn_blocking); manager->ctrl = udev_ctrl_unref(manager->ctrl); manager->ctrl_conn_blocking = udev_ctrl_connection_unref(manager->ctrl_conn_blocking); manager->worker_watch[READ_END] = safe_close(manager->worker_watch[READ_END]); manager->ctrl_event = sd_event_source_unref(manager->ctrl_event); manager->uevent_event = sd_event_source_unref(manager->uevent_event); manager->inotify_event = sd_event_source_unref(manager->inotify_event); manager->event = sd_event_unref(manager->event); sigfillset(&mask); fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); if (fd_signal < 0) { r = log_error_errno(errno, "error creating signalfd %m"); goto out; } ep_signal.data.fd = fd_signal; fd_monitor = udev_monitor_get_fd(worker_monitor); ep_monitor.data.fd = fd_monitor; fd_ep = epoll_create1(EPOLL_CLOEXEC); if (fd_ep < 0) { r = log_error_errno(errno, "error creating epoll fd: %m"); goto out; } if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_signal, &ep_signal) < 0 || epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_monitor, &ep_monitor) < 0) { r = log_error_errno(errno, "fail to add fds to epoll: %m"); goto out; } /* request TERM signal if parent exits */ prctl(PR_SET_PDEATHSIG, SIGTERM); /* reset OOM score, we only protect the main daemon */ write_string_file("/proc/self/oom_score_adj", "0", 0); for (;;) { struct udev_event *udev_event; int fd_lock = -1; assert(dev); log_debug("seq %llu running", udev_device_get_seqnum(dev)); udev_event = udev_event_new(dev); if (udev_event == NULL) { r = -ENOMEM; goto out; } if (arg_exec_delay > 0) udev_event->exec_delay = arg_exec_delay; /* * Take a shared lock on the device node; this establishes * a concept of device "ownership" to serialize device * access. External processes holding an exclusive lock will * cause udev to skip the event handling; in the case udev * acquired the lock, the external process can block until * udev has finished its event handling. */ if (!streq_ptr(udev_device_get_action(dev), "remove") && streq_ptr("block", udev_device_get_subsystem(dev)) && !startswith(udev_device_get_sysname(dev), "dm-") && !startswith(udev_device_get_sysname(dev), "md")) { struct udev_device *d = dev; if (streq_ptr("partition", udev_device_get_devtype(d))) d = udev_device_get_parent(d); if (d) { fd_lock = open(udev_device_get_devnode(d), O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK); if (fd_lock >= 0 && flock(fd_lock, LOCK_SH|LOCK_NB) < 0) { log_debug_errno(errno, "Unable to flock(%s), skipping event handling: %m", udev_device_get_devnode(d)); fd_lock = safe_close(fd_lock); goto skip; } } } /* needed for renaming netifs */ udev_event->rtnl = rtnl; /* apply rules, create node, symlinks */ udev_event_execute_rules(udev_event, arg_event_timeout_usec, arg_event_timeout_warn_usec, &manager->properties, manager->rules); udev_event_execute_run(udev_event, arg_event_timeout_usec, arg_event_timeout_warn_usec); if (udev_event->rtnl) /* in case rtnl was initialized */ rtnl = sd_netlink_ref(udev_event->rtnl); /* apply/restore inotify watch */ if (udev_event->inotify_watch) { udev_watch_begin(udev, dev); udev_device_update_db(dev); } safe_close(fd_lock); /* send processed event back to libudev listeners */ udev_monitor_send_device(worker_monitor, NULL, dev); skip: log_debug("seq %llu processed", udev_device_get_seqnum(dev)); /* send udevd the result of the event execution */ r = worker_send_message(manager->worker_watch[WRITE_END]); if (r < 0) log_error_errno(r, "failed to send result of seq %llu to main daemon: %m", udev_device_get_seqnum(dev)); udev_device_unref(dev); dev = NULL; udev_event_unref(udev_event); /* wait for more device messages from main udevd, or term signal */ while (dev == NULL) { struct epoll_event ev[4]; int fdcount; int i; fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1); if (fdcount < 0) { if (errno == EINTR) continue; r = log_error_errno(errno, "failed to poll: %m"); goto out; } for (i = 0; i < fdcount; i++) { if (ev[i].data.fd == fd_monitor && ev[i].events & EPOLLIN) { dev = udev_monitor_receive_device(worker_monitor); break; } else if (ev[i].data.fd == fd_signal && ev[i].events & EPOLLIN) { struct signalfd_siginfo fdsi; ssize_t size; size = read(fd_signal, &fdsi, sizeof(struct signalfd_siginfo)); if (size != sizeof(struct signalfd_siginfo)) continue; switch (fdsi.ssi_signo) { case SIGTERM: goto out; } } } } } out: udev_device_unref(dev); manager_free(manager); log_close(); _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); } case -1: event->state = EVENT_QUEUED; log_error_errno(errno, "fork of child failed: %m"); break; default: { struct worker *worker; r = worker_new(&worker, manager, worker_monitor, pid); if (r < 0) return; worker_attach_event(worker, event); log_debug("seq %llu forked new worker ["PID_FMT"]", udev_device_get_seqnum(event->dev), pid); break; } } } static void event_run(Manager *manager, struct event *event) { struct worker *worker; Iterator i; assert(manager); assert(event); HASHMAP_FOREACH(worker, manager->workers, i) { ssize_t count; if (worker->state != WORKER_IDLE) continue; count = udev_monitor_send_device(manager->monitor, worker->monitor, event->dev); if (count < 0) { log_error_errno(errno, "worker ["PID_FMT"] did not accept message %zi (%m), kill it", worker->pid, count); kill(worker->pid, SIGKILL); worker->state = WORKER_KILLED; continue; } worker_attach_event(worker, event); return; } if (hashmap_size(manager->workers) >= arg_children_max) { if (arg_children_max > 1) log_debug("maximum number (%i) of children reached", hashmap_size(manager->workers)); return; } /* start new worker and pass initial device */ worker_spawn(manager, event); } static int event_queue_insert(Manager *manager, struct udev_device *dev) { struct event *event; int r; assert(manager); assert(dev); /* only one process can add events to the queue */ if (manager->pid == 0) manager->pid = getpid(); assert(manager->pid == getpid()); event = new0(struct event, 1); if (!event) return -ENOMEM; event->udev = udev_device_get_udev(dev); event->manager = manager; event->dev = dev; event->dev_kernel = udev_device_shallow_clone(dev); udev_device_copy_properties(event->dev_kernel, dev); event->seqnum = udev_device_get_seqnum(dev); event->devpath = udev_device_get_devpath(dev); event->devpath_len = strlen(event->devpath); event->devpath_old = udev_device_get_devpath_old(dev); event->devnum = udev_device_get_devnum(dev); event->is_block = streq("block", udev_device_get_subsystem(dev)); event->ifindex = udev_device_get_ifindex(dev); log_debug("seq %llu queued, '%s' '%s'", udev_device_get_seqnum(dev), udev_device_get_action(dev), udev_device_get_subsystem(dev)); event->state = EVENT_QUEUED; if (udev_list_node_is_empty(&manager->events)) { r = touch("/run/udev/queue"); if (r < 0) log_warning_errno(r, "could not touch /run/udev/queue: %m"); } udev_list_node_append(&event->node, &manager->events); return 0; } static void manager_kill_workers(Manager *manager) { struct worker *worker; Iterator i; assert(manager); HASHMAP_FOREACH(worker, manager->workers, i) { if (worker->state == WORKER_KILLED) continue; worker->state = WORKER_KILLED; kill(worker->pid, SIGTERM); } } /* lookup event for identical, parent, child device */ static bool is_devpath_busy(Manager *manager, struct event *event) { struct udev_list_node *loop; size_t common; /* check if queue contains events we depend on */ udev_list_node_foreach(loop, &manager->events) { struct event *loop_event = node_to_event(loop); /* we already found a later event, earlier can not block us, no need to check again */ if (loop_event->seqnum < event->delaying_seqnum) continue; /* event we checked earlier still exists, no need to check again */ if (loop_event->seqnum == event->delaying_seqnum) return true; /* found ourself, no later event can block us */ if (loop_event->seqnum >= event->seqnum) break; /* check major/minor */ if (major(event->devnum) != 0 && event->devnum == loop_event->devnum && event->is_block == loop_event->is_block) return true; /* check network device ifindex */ if (event->ifindex != 0 && event->ifindex == loop_event->ifindex) return true; /* check our old name */ if (event->devpath_old != NULL && streq(loop_event->devpath, event->devpath_old)) { event->delaying_seqnum = loop_event->seqnum; return true; } /* compare devpath */ common = MIN(loop_event->devpath_len, event->devpath_len); /* one devpath is contained in the other? */ if (memcmp(loop_event->devpath, event->devpath, common) != 0) continue; /* identical device event found */ if (loop_event->devpath_len == event->devpath_len) { /* devices names might have changed/swapped in the meantime */ if (major(event->devnum) != 0 && (event->devnum != loop_event->devnum || event->is_block != loop_event->is_block)) continue; if (event->ifindex != 0 && event->ifindex != loop_event->ifindex) continue; event->delaying_seqnum = loop_event->seqnum; return true; } /* parent device event found */ if (event->devpath[common] == '/') { event->delaying_seqnum = loop_event->seqnum; return true; } /* child device event found */ if (loop_event->devpath[common] == '/') { event->delaying_seqnum = loop_event->seqnum; return true; } /* no matching device */ continue; } return false; } static int on_exit_timeout(sd_event_source *s, uint64_t usec, void *userdata) { Manager *manager = userdata; assert(manager); log_error_errno(ETIMEDOUT, "giving up waiting for workers to finish"); sd_event_exit(manager->event, -ETIMEDOUT); return 1; } static void manager_exit(Manager *manager) { uint64_t usec; int r; assert(manager); manager->exit = true; sd_notify(false, "STOPPING=1\n" "STATUS=Starting shutdown..."); /* close sources of new events and discard buffered events */ manager->ctrl_event = sd_event_source_unref(manager->ctrl_event); manager->ctrl = udev_ctrl_unref(manager->ctrl); manager->inotify_event = sd_event_source_unref(manager->inotify_event); manager->fd_inotify = safe_close(manager->fd_inotify); manager->uevent_event = sd_event_source_unref(manager->uevent_event); manager->monitor = udev_monitor_unref(manager->monitor); /* discard queued events and kill workers */ event_queue_cleanup(manager, EVENT_QUEUED); manager_kill_workers(manager); assert_se(sd_event_now(manager->event, clock_boottime_or_monotonic(), &usec) >= 0); r = sd_event_add_time(manager->event, NULL, clock_boottime_or_monotonic(), usec + 30 * USEC_PER_SEC, USEC_PER_SEC, on_exit_timeout, manager); if (r < 0) return; } /* reload requested, HUP signal received, rules changed, builtin changed */ static void manager_reload(Manager *manager) { assert(manager); sd_notify(false, "RELOADING=1\n" "STATUS=Flushing configuration..."); manager_kill_workers(manager); manager->rules = udev_rules_unref(manager->rules); udev_builtin_exit(manager->udev); sd_notify(false, "READY=1\n" "STATUS=Processing..."); } static void event_queue_start(Manager *manager) { struct udev_list_node *loop; usec_t usec; assert(manager); if (udev_list_node_is_empty(&manager->events) || manager->exit || manager->stop_exec_queue) return; assert_se(sd_event_now(manager->event, clock_boottime_or_monotonic(), &usec) >= 0); /* check for changed config, every 3 seconds at most */ if (manager->last_usec == 0 || (usec - manager->last_usec) > 3 * USEC_PER_SEC) { if (udev_rules_check_timestamp(manager->rules) || udev_builtin_validate(manager->udev)) manager_reload(manager); manager->last_usec = usec; } udev_builtin_init(manager->udev); if (!manager->rules) { manager->rules = udev_rules_new(manager->udev, arg_resolve_names); if (!manager->rules) return; } udev_list_node_foreach(loop, &manager->events) { struct event *event = node_to_event(loop); if (event->state != EVENT_QUEUED) continue; /* do not start event if parent or child event is still running */ if (is_devpath_busy(manager, event)) continue; event_run(manager, event); } } static void event_queue_cleanup(Manager *manager, enum event_state match_type) { struct udev_list_node *loop, *tmp; udev_list_node_foreach_safe(loop, tmp, &manager->events) { struct event *event = node_to_event(loop); if (match_type != EVENT_UNDEF && match_type != event->state) continue; event_free(event); } } static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Manager *manager = userdata; assert(manager); for (;;) { struct worker_message msg; struct iovec iovec = { .iov_base = &msg, .iov_len = sizeof(msg), }; union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; } control = {}; struct msghdr msghdr = { .msg_iov = &iovec, .msg_iovlen = 1, .msg_control = &control, .msg_controllen = sizeof(control), }; struct cmsghdr *cmsg; ssize_t size; struct ucred *ucred = NULL; struct worker *worker; size = recvmsg(fd, &msghdr, MSG_DONTWAIT); if (size < 0) { if (errno == EINTR) continue; else if (errno == EAGAIN) /* nothing more to read */ break; return log_error_errno(errno, "failed to receive message: %m"); } else if (size != sizeof(struct worker_message)) { log_warning_errno(EIO, "ignoring worker message with invalid size %zi bytes", size); continue; } CMSG_FOREACH(cmsg, &msghdr) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) ucred = (struct ucred*) CMSG_DATA(cmsg); } if (!ucred || ucred->pid <= 0) { log_warning_errno(EIO, "ignoring worker message without valid PID"); continue; } /* lookup worker who sent the signal */ worker = hashmap_get(manager->workers, PID_TO_PTR(ucred->pid)); if (!worker) { log_debug("worker ["PID_FMT"] returned, but is no longer tracked", ucred->pid); continue; } if (worker->state != WORKER_KILLED) worker->state = WORKER_IDLE; /* worker returned */ event_free(worker->event); } /* we have free workers, try to schedule events */ event_queue_start(manager); return 1; } static int on_uevent(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Manager *manager = userdata; struct udev_device *dev; int r; assert(manager); dev = udev_monitor_receive_device(manager->monitor); if (dev) { udev_device_ensure_usec_initialized(dev, NULL); r = event_queue_insert(manager, dev); if (r < 0) udev_device_unref(dev); else /* we have fresh events, try to schedule them */ event_queue_start(manager); } return 1; } /* receive the udevd message from userspace */ static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Manager *manager = userdata; _cleanup_udev_ctrl_connection_unref_ struct udev_ctrl_connection *ctrl_conn = NULL; _cleanup_udev_ctrl_msg_unref_ struct udev_ctrl_msg *ctrl_msg = NULL; const char *str; int i; assert(manager); ctrl_conn = udev_ctrl_get_connection(manager->ctrl); if (!ctrl_conn) return 1; ctrl_msg = udev_ctrl_receive_msg(ctrl_conn); if (!ctrl_msg) return 1; i = udev_ctrl_get_set_log_level(ctrl_msg); if (i >= 0) { log_debug("udevd message (SET_LOG_LEVEL) received, log_priority=%i", i); log_set_max_level(i); manager_kill_workers(manager); } if (udev_ctrl_get_stop_exec_queue(ctrl_msg) > 0) { log_debug("udevd message (STOP_EXEC_QUEUE) received"); manager->stop_exec_queue = true; } if (udev_ctrl_get_start_exec_queue(ctrl_msg) > 0) { log_debug("udevd message (START_EXEC_QUEUE) received"); manager->stop_exec_queue = false; event_queue_start(manager); } if (udev_ctrl_get_reload(ctrl_msg) > 0) { log_debug("udevd message (RELOAD) received"); manager_reload(manager); } str = udev_ctrl_get_set_env(ctrl_msg); if (str != NULL) { _cleanup_free_ char *key = NULL; key = strdup(str); if (key) { char *val; val = strchr(key, '='); if (val != NULL) { val[0] = '\0'; val = &val[1]; if (val[0] == '\0') { log_debug("udevd message (ENV) received, unset '%s'", key); udev_list_entry_add(&manager->properties, key, NULL); } else { log_debug("udevd message (ENV) received, set '%s=%s'", key, val); udev_list_entry_add(&manager->properties, key, val); } } else log_error("wrong key format '%s'", key); } manager_kill_workers(manager); } i = udev_ctrl_get_set_children_max(ctrl_msg); if (i >= 0) { log_debug("udevd message (SET_MAX_CHILDREN) received, children_max=%i", i); arg_children_max = i; } if (udev_ctrl_get_ping(ctrl_msg) > 0) log_debug("udevd message (SYNC) received"); if (udev_ctrl_get_exit(ctrl_msg) > 0) { log_debug("udevd message (EXIT) received"); manager_exit(manager); /* keep reference to block the client until we exit TODO: deal with several blocking exit requests */ manager->ctrl_conn_blocking = udev_ctrl_connection_ref(ctrl_conn); } return 1; } static int synthesize_change(struct udev_device *dev) { char filename[UTIL_PATH_SIZE]; int r; if (streq_ptr("block", udev_device_get_subsystem(dev)) && streq_ptr("disk", udev_device_get_devtype(dev)) && !startswith(udev_device_get_sysname(dev), "dm-")) { bool part_table_read = false; bool has_partitions = false; int fd; struct udev *udev = udev_device_get_udev(dev); _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; struct udev_list_entry *item; /* * Try to re-read the partition table. This only succeeds if * none of the devices is busy. The kernel returns 0 if no * partition table is found, and we will not get an event for * the disk. */ fd = open(udev_device_get_devnode(dev), O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK); if (fd >= 0) { r = flock(fd, LOCK_EX|LOCK_NB); if (r >= 0) r = ioctl(fd, BLKRRPART, 0); close(fd); if (r >= 0) part_table_read = true; } /* search for partitions */ e = udev_enumerate_new(udev); if (!e) return -ENOMEM; r = udev_enumerate_add_match_parent(e, dev); if (r < 0) return r; r = udev_enumerate_add_match_subsystem(e, "block"); if (r < 0) return r; r = udev_enumerate_scan_devices(e); if (r < 0) return r; udev_list_entry_foreach(item, udev_enumerate_get_list_entry(e)) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!d) continue; if (!streq_ptr("partition", udev_device_get_devtype(d))) continue; has_partitions = true; break; } /* * We have partitions and re-read the table, the kernel already sent * out a "change" event for the disk, and "remove/add" for all * partitions. */ if (part_table_read && has_partitions) return 0; /* * We have partitions but re-reading the partition table did not * work, synthesize "change" for the disk and all partitions. */ log_debug("device %s closed, synthesising 'change'", udev_device_get_devnode(dev)); strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL); write_string_file(filename, "change", WRITE_STRING_FILE_CREATE); udev_list_entry_foreach(item, udev_enumerate_get_list_entry(e)) { _cleanup_udev_device_unref_ struct udev_device *d = NULL; d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!d) continue; if (!streq_ptr("partition", udev_device_get_devtype(d))) continue; log_debug("device %s closed, synthesising partition '%s' 'change'", udev_device_get_devnode(dev), udev_device_get_devnode(d)); strscpyl(filename, sizeof(filename), udev_device_get_syspath(d), "/uevent", NULL); write_string_file(filename, "change", WRITE_STRING_FILE_CREATE); } return 0; } log_debug("device %s closed, synthesising 'change'", udev_device_get_devnode(dev)); strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL); write_string_file(filename, "change", WRITE_STRING_FILE_CREATE); return 0; } static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Manager *manager = userdata; union inotify_event_buffer buffer; struct inotify_event *e; ssize_t l; assert(manager); l = read(fd, &buffer, sizeof(buffer)); if (l < 0) { if (errno == EAGAIN || errno == EINTR) return 1; return log_error_errno(errno, "Failed to read inotify fd: %m"); } FOREACH_INOTIFY_EVENT(e, buffer, l) { _cleanup_udev_device_unref_ struct udev_device *dev = NULL; dev = udev_watch_lookup(manager->udev, e->wd); if (!dev) continue; log_debug("inotify event: %x for %s", e->mask, udev_device_get_devnode(dev)); if (e->mask & IN_CLOSE_WRITE) { synthesize_change(dev); /* settle might be waiting on us to determine the queue * state. If we just handled an inotify event, we might have * generated a "change" event, but we won't have queued up * the resultant uevent yet. Do that. */ on_uevent(NULL, -1, 0, manager); } else if (e->mask & IN_IGNORED) udev_watch_end(manager->udev, dev); } return 1; } static int on_sigterm(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { Manager *manager = userdata; assert(manager); manager_exit(manager); return 1; } static int on_sighup(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { Manager *manager = userdata; assert(manager); manager_reload(manager); return 1; } static int on_sigchld(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { Manager *manager = userdata; assert(manager); for (;;) { pid_t pid; int status; struct worker *worker; pid = waitpid(-1, &status, WNOHANG); if (pid <= 0) break; worker = hashmap_get(manager->workers, PID_TO_PTR(pid)); if (!worker) { log_warning("worker ["PID_FMT"] is unknown, ignoring", pid); continue; } if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0) log_debug("worker ["PID_FMT"] exited", pid); else log_warning("worker ["PID_FMT"] exited with return code %i", pid, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { log_warning("worker ["PID_FMT"] terminated by signal %i (%s)", pid, WTERMSIG(status), strsignal(WTERMSIG(status))); } else if (WIFSTOPPED(status)) { log_info("worker ["PID_FMT"] stopped", pid); continue; } else if (WIFCONTINUED(status)) { log_info("worker ["PID_FMT"] continued", pid); continue; } else log_warning("worker ["PID_FMT"] exit with status 0x%04x", pid, status); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { if (worker->event) { log_error("worker ["PID_FMT"] failed while handling '%s'", pid, worker->event->devpath); /* delete state from disk */ udev_device_delete_db(worker->event->dev); udev_device_tag_index(worker->event->dev, NULL, false); /* forward kernel event without amending it */ udev_monitor_send_device(manager->monitor, NULL, worker->event->dev_kernel); } } worker_free(worker); } /* we can start new workers, try to schedule events */ event_queue_start(manager); return 1; } static int on_post(sd_event_source *s, void *userdata) { Manager *manager = userdata; int r; assert(manager); if (udev_list_node_is_empty(&manager->events)) { /* no pending events */ if (!hashmap_isempty(manager->workers)) { /* there are idle workers */ log_debug("cleanup idle workers"); manager_kill_workers(manager); } else { /* we are idle */ if (manager->exit) { r = sd_event_exit(manager->event, 0); if (r < 0) return r; } else if (manager->cgroup) /* cleanup possible left-over processes in our cgroup */ cg_kill(SYSTEMD_CGROUP_CONTROLLER, manager->cgroup, SIGKILL, false, true, NULL); } } return 1; } static int listen_fds(int *rctrl, int *rnetlink) { _cleanup_udev_unref_ struct udev *udev = NULL; int ctrl_fd = -1, netlink_fd = -1; int fd, n, r; assert(rctrl); assert(rnetlink); n = sd_listen_fds(true); if (n < 0) return n; for (fd = SD_LISTEN_FDS_START; fd < n + SD_LISTEN_FDS_START; fd++) { if (sd_is_socket(fd, AF_LOCAL, SOCK_SEQPACKET, -1)) { if (ctrl_fd >= 0) return -EINVAL; ctrl_fd = fd; continue; } if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1)) { if (netlink_fd >= 0) return -EINVAL; netlink_fd = fd; continue; } return -EINVAL; } if (ctrl_fd < 0) { _cleanup_udev_ctrl_unref_ struct udev_ctrl *ctrl = NULL; udev = udev_new(); if (!udev) return -ENOMEM; ctrl = udev_ctrl_new(udev); if (!ctrl) return log_error_errno(EINVAL, "error initializing udev control socket"); r = udev_ctrl_enable_receiving(ctrl); if (r < 0) return log_error_errno(EINVAL, "error binding udev control socket"); fd = udev_ctrl_get_fd(ctrl); if (fd < 0) return log_error_errno(EIO, "could not get ctrl fd"); ctrl_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (ctrl_fd < 0) return log_error_errno(errno, "could not dup ctrl fd: %m"); } if (netlink_fd < 0) { _cleanup_udev_monitor_unref_ struct udev_monitor *monitor = NULL; if (!udev) { udev = udev_new(); if (!udev) return -ENOMEM; } monitor = udev_monitor_new_from_netlink(udev, "kernel"); if (!monitor) return log_error_errno(EINVAL, "error initializing netlink socket"); (void) udev_monitor_set_receive_buffer_size(monitor, 128 * 1024 * 1024); r = udev_monitor_enable_receiving(monitor); if (r < 0) return log_error_errno(EINVAL, "error binding netlink socket"); fd = udev_monitor_get_fd(monitor); if (fd < 0) return log_error_errno(netlink_fd, "could not get uevent fd: %m"); netlink_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (ctrl_fd < 0) return log_error_errno(errno, "could not dup netlink fd: %m"); } *rctrl = ctrl_fd; *rnetlink = netlink_fd; return 0; } /* * read the kernel command line, in case we need to get into debug mode * udev.log-priority= syslog priority * udev.children-max= events are fully serialized if set to 1 * udev.exec-delay= delay execution of every executed program * udev.event-timeout= seconds to wait before terminating an event */ static int parse_proc_cmdline_item(const char *key, const char *value) { const char *full_key = key; int r; assert(key); if (!value) return 0; if (startswith(key, "rd.")) key += strlen("rd."); if (startswith(key, "udev.")) key += strlen("udev."); else return 0; if (streq(key, "log-priority")) { int prio; prio = util_log_priority(value); if (prio < 0) goto invalid; log_set_max_level(prio); } else if (streq(key, "children-max")) { r = safe_atou(value, &arg_children_max); if (r < 0) goto invalid; } else if (streq(key, "exec-delay")) { r = safe_atoi(value, &arg_exec_delay); if (r < 0) goto invalid; } else if (streq(key, "event-timeout")) { r = safe_atou64(value, &arg_event_timeout_usec); if (r < 0) goto invalid; arg_event_timeout_usec *= USEC_PER_SEC; arg_event_timeout_warn_usec = (arg_event_timeout_usec / 3) ? : 1; } return 0; invalid: log_warning("invalid %s ignored: %s", full_key, value); return 0; } static void help(void) { printf("%s [OPTIONS...]\n\n" "Manages devices.\n\n" " -h --help Print this message\n" " --version Print version of the program\n" " --daemon Detach and run in the background\n" " --debug Enable debug output\n" " --children-max=INT Set maximum number of workers\n" " --exec-delay=SECONDS Seconds to wait before executing RUN=\n" " --event-timeout=SECONDS Seconds to wait before terminating an event\n" " --resolve-names=early|late|never\n" " When to resolve users and groups\n" , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { static const struct option options[] = { { "daemon", no_argument, NULL, 'd' }, { "debug", no_argument, NULL, 'D' }, { "children-max", required_argument, NULL, 'c' }, { "exec-delay", required_argument, NULL, 'e' }, { "event-timeout", required_argument, NULL, 't' }, { "resolve-names", required_argument, NULL, 'N' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, {} }; int c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "c:de:Dt:N:hV", options, NULL)) >= 0) { int r; switch (c) { case 'd': arg_daemonize = true; break; case 'c': r = safe_atou(optarg, &arg_children_max); if (r < 0) log_warning("Invalid --children-max ignored: %s", optarg); break; case 'e': r = safe_atoi(optarg, &arg_exec_delay); if (r < 0) log_warning("Invalid --exec-delay ignored: %s", optarg); break; case 't': r = safe_atou64(optarg, &arg_event_timeout_usec); if (r < 0) log_warning("Invalid --event-timeout ignored: %s", optarg); else { arg_event_timeout_usec *= USEC_PER_SEC; arg_event_timeout_warn_usec = (arg_event_timeout_usec / 3) ? : 1; } break; case 'D': arg_debug = true; break; case 'N': if (streq(optarg, "early")) { arg_resolve_names = 1; } else if (streq(optarg, "late")) { arg_resolve_names = 0; } else if (streq(optarg, "never")) { arg_resolve_names = -1; } else { log_error("resolve-names must be early, late or never"); return 0; } break; case 'h': help(); return 0; case 'V': printf("%s\n", VERSION); return 0; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } } return 1; } static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cgroup) { _cleanup_(manager_freep) Manager *manager = NULL; int r, fd_worker, one = 1; assert(ret); assert(fd_ctrl >= 0); assert(fd_uevent >= 0); manager = new0(Manager, 1); if (!manager) return log_oom(); manager->fd_inotify = -1; manager->worker_watch[WRITE_END] = -1; manager->worker_watch[READ_END] = -1; manager->udev = udev_new(); if (!manager->udev) return log_error_errno(errno, "could not allocate udev context: %m"); udev_builtin_init(manager->udev); manager->rules = udev_rules_new(manager->udev, arg_resolve_names); if (!manager->rules) return log_error_errno(ENOMEM, "error reading rules"); udev_list_node_init(&manager->events); udev_list_init(manager->udev, &manager->properties, true); manager->cgroup = cgroup; manager->ctrl = udev_ctrl_new_from_fd(manager->udev, fd_ctrl); if (!manager->ctrl) return log_error_errno(EINVAL, "error taking over udev control socket"); manager->monitor = udev_monitor_new_from_netlink_fd(manager->udev, "kernel", fd_uevent); if (!manager->monitor) return log_error_errno(EINVAL, "error taking over netlink socket"); /* unnamed socket from workers to the main daemon */ r = socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch); if (r < 0) return log_error_errno(errno, "error creating socketpair: %m"); fd_worker = manager->worker_watch[READ_END]; r = setsockopt(fd_worker, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); if (r < 0) return log_error_errno(errno, "could not enable SO_PASSCRED: %m"); manager->fd_inotify = udev_watch_init(manager->udev); if (manager->fd_inotify < 0) return log_error_errno(ENOMEM, "error initializing inotify"); udev_watch_restore(manager->udev); /* block and listen to all signals on signalfd */ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0); r = sd_event_default(&manager->event); if (r < 0) return log_error_errno(r, "could not allocate event loop: %m"); r = sd_event_add_signal(manager->event, NULL, SIGINT, on_sigterm, manager); if (r < 0) return log_error_errno(r, "error creating sigint event source: %m"); r = sd_event_add_signal(manager->event, NULL, SIGTERM, on_sigterm, manager); if (r < 0) return log_error_errno(r, "error creating sigterm event source: %m"); r = sd_event_add_signal(manager->event, NULL, SIGHUP, on_sighup, manager); if (r < 0) return log_error_errno(r, "error creating sighup event source: %m"); r = sd_event_add_signal(manager->event, NULL, SIGCHLD, on_sigchld, manager); if (r < 0) return log_error_errno(r, "error creating sigchld event source: %m"); r = sd_event_set_watchdog(manager->event, true); if (r < 0) return log_error_errno(r, "error creating watchdog event source: %m"); r = sd_event_add_io(manager->event, &manager->ctrl_event, fd_ctrl, EPOLLIN, on_ctrl_msg, manager); if (r < 0) return log_error_errno(r, "error creating ctrl event source: %m"); /* This needs to be after the inotify and uevent handling, to make sure * that the ping is send back after fully processing the pending uevents * (including the synthetic ones we may create due to inotify events). */ r = sd_event_source_set_priority(manager->ctrl_event, SD_EVENT_PRIORITY_IDLE); if (r < 0) return log_error_errno(r, "cold not set IDLE event priority for ctrl event source: %m"); r = sd_event_add_io(manager->event, &manager->inotify_event, manager->fd_inotify, EPOLLIN, on_inotify, manager); if (r < 0) return log_error_errno(r, "error creating inotify event source: %m"); r = sd_event_add_io(manager->event, &manager->uevent_event, fd_uevent, EPOLLIN, on_uevent, manager); if (r < 0) return log_error_errno(r, "error creating uevent event source: %m"); r = sd_event_add_io(manager->event, NULL, fd_worker, EPOLLIN, on_worker, manager); if (r < 0) return log_error_errno(r, "error creating worker event source: %m"); r = sd_event_add_post(manager->event, NULL, on_post, manager); if (r < 0) return log_error_errno(r, "error creating post event source: %m"); *ret = manager; manager = NULL; return 0; } static int run(int fd_ctrl, int fd_uevent, const char *cgroup) { _cleanup_(manager_freep) Manager *manager = NULL; int r; r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup); if (r < 0) { r = log_error_errno(r, "failed to allocate manager object: %m"); goto exit; } r = udev_rules_apply_static_dev_perms(manager->rules); if (r < 0) log_error_errno(r, "failed to apply permissions on static device nodes: %m"); (void) sd_notify(false, "READY=1\n" "STATUS=Processing..."); r = sd_event_loop(manager->event); if (r < 0) { log_error_errno(r, "event loop failed: %m"); goto exit; } sd_event_get_exit_code(manager->event, &r); exit: sd_notify(false, "STOPPING=1\n" "STATUS=Shutting down..."); if (manager) udev_ctrl_cleanup(manager->ctrl); return r; } int main(int argc, char *argv[]) { _cleanup_free_ char *cgroup = NULL; int fd_ctrl = -1, fd_uevent = -1; int r; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto exit; r = parse_proc_cmdline(parse_proc_cmdline_item); if (r < 0) log_warning_errno(r, "failed to parse kernel command line, ignoring: %m"); if (arg_debug) { log_set_target(LOG_TARGET_CONSOLE); log_set_max_level(LOG_DEBUG); } if (getuid() != 0) { r = log_error_errno(EPERM, "root privileges required"); goto exit; } if (arg_children_max == 0) { cpu_set_t cpu_set; arg_children_max = 8; if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) == 0) arg_children_max += CPU_COUNT(&cpu_set) * 2; log_debug("set children_max to %u", arg_children_max); } /* set umask before creating any file/directory */ r = chdir("/"); if (r < 0) { r = log_error_errno(errno, "could not change dir to /: %m"); goto exit; } umask(022); r = mac_selinux_init("/dev"); if (r < 0) { log_error_errno(r, "could not initialize labelling: %m"); goto exit; } r = mkdir("/run/udev", 0755); if (r < 0 && errno != EEXIST) { r = log_error_errno(errno, "could not create /run/udev: %m"); goto exit; } dev_setup(NULL, UID_INVALID, GID_INVALID); if (getppid() == 1) { /* get our own cgroup, we regularly kill everything udev has left behind we only do this on systemd systems, and only if we are directly spawned by PID1. otherwise we are not guaranteed to have a dedicated cgroup */ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup); if (r < 0) { if (r == -ENOENT || r == -ENOEXEC) log_debug_errno(r, "did not find dedicated cgroup: %m"); else log_warning_errno(r, "failed to get cgroup: %m"); } } r = listen_fds(&fd_ctrl, &fd_uevent); if (r < 0) { r = log_error_errno(r, "could not listen on fds: %m"); goto exit; } if (arg_daemonize) { pid_t pid; log_info("starting version " VERSION); /* connect /dev/null to stdin, stdout, stderr */ if (log_get_max_level() < LOG_DEBUG) (void) make_null_stdio(); pid = fork(); switch (pid) { case 0: break; case -1: r = log_error_errno(errno, "fork of daemon failed: %m"); goto exit; default: mac_selinux_finish(); log_close(); _exit(EXIT_SUCCESS); } setsid(); write_string_file("/proc/self/oom_score_adj", "-1000", 0); } r = run(fd_ctrl, fd_uevent, cgroup); exit: mac_selinux_finish(); log_close(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/udev/v4l_id/000077500000000000000000000000001265713322000157745ustar00rootroot00000000000000systemd-229/src/udev/v4l_id/Makefile000077700000000000000000000000001265713322000213022../Makefileustar00rootroot00000000000000systemd-229/src/udev/v4l_id/v4l_id.c000066400000000000000000000055371265713322000173330ustar00rootroot00000000000000/* * Copyright (C) 2009 Kay Sievers * Copyright (c) 2009 Filippo Argiolas * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details: */ #include #include #include #include #include #include #include #include #include #include #include #include #include "fd-util.h" #include "util.h" int main(int argc, char *argv[]) { static const struct option options[] = { { "help", no_argument, NULL, 'h' }, {} }; _cleanup_close_ int fd = -1; char *device; struct v4l2_capability v2cap; int c; while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': printf("%s [-h,--help] \n\n" "Video4Linux device identification.\n\n" " -h Print this message\n" , program_invocation_short_name); return 0; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } device = argv[optind]; if (device == NULL) return 2; fd = open(device, O_RDONLY); if (fd < 0) return 3; if (ioctl(fd, VIDIOC_QUERYCAP, &v2cap) == 0) { printf("ID_V4L_VERSION=2\n"); printf("ID_V4L_PRODUCT=%s\n", v2cap.card); printf("ID_V4L_CAPABILITIES=:"); if ((v2cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) > 0) printf("capture:"); if ((v2cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) > 0) printf("video_output:"); if ((v2cap.capabilities & V4L2_CAP_VIDEO_OVERLAY) > 0) printf("video_overlay:"); if ((v2cap.capabilities & V4L2_CAP_AUDIO) > 0) printf("audio:"); if ((v2cap.capabilities & V4L2_CAP_TUNER) > 0) printf("tuner:"); if ((v2cap.capabilities & V4L2_CAP_RADIO) > 0) printf("radio:"); printf("\n"); } return 0; } systemd-229/src/update-done/000077500000000000000000000000001265713322000160555ustar00rootroot00000000000000systemd-229/src/update-done/Makefile000077700000000000000000000000001265713322000213632../Makefileustar00rootroot00000000000000systemd-229/src/update-done/update-done.c000066400000000000000000000102341265713322000204260ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include "fd-util.h" #include "io-util.h" #include "selinux-util.h" #include "util.h" #define MESSAGE \ "This file was created by systemd-update-done. Its only \n" \ "purpose is to hold a timestamp of the time this directory\n" \ "was updated. See systemd-update-done.service(8).\n" static int apply_timestamp(const char *path, struct timespec *ts) { struct timespec twice[2] = { *ts, *ts }; struct stat st; assert(path); assert(ts); if (stat(path, &st) >= 0) { /* Is the timestamp file already newer than the OS? If * so, there's nothing to do. We ignore the nanosecond * component of the timestamp, since some file systems * do not support any better accuracy than 1s and we * have no way to identify the accuracy * available. Most notably ext4 on small disks (where * 128 byte inodes are used) does not support better * accuracy than 1s. */ if (st.st_mtim.tv_sec > ts->tv_sec) return 0; /* It is older? Then let's update it */ if (utimensat(AT_FDCWD, path, twice, AT_SYMLINK_NOFOLLOW) < 0) { if (errno == EROFS) return log_debug("Can't update timestamp file %s, file system is read-only.", path); return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); } } else if (errno == ENOENT) { _cleanup_close_ int fd = -1; int r; /* The timestamp file doesn't exist yet? Then let's create it. */ r = mac_selinux_create_file_prepare(path, S_IFREG); if (r < 0) return log_error_errno(r, "Failed to set SELinux context for %s: %m", path); fd = open(path, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); mac_selinux_create_file_clear(); if (fd < 0) { if (errno == EROFS) return log_debug("Can't create timestamp file %s, file system is read-only.", path); return log_error_errno(errno, "Failed to create timestamp file %s: %m", path); } (void) loop_write(fd, MESSAGE, strlen(MESSAGE), false); if (futimens(fd, twice) < 0) return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); } else log_error_errno(errno, "Failed to stat() timestamp file %s: %m", path); return 0; } int main(int argc, char *argv[]) { struct stat st; int r, q = 0; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); if (stat("/usr", &st) < 0) { log_error_errno(errno, "Failed to stat /usr: %m"); return EXIT_FAILURE; } r = mac_selinux_init(NULL); if (r < 0) { log_error_errno(r, "SELinux setup failed: %m"); goto finish; } r = apply_timestamp("/etc/.updated", &st.st_mtim); q = apply_timestamp("/var/.updated", &st.st_mtim); finish: return r < 0 || q < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/update-utmp/000077500000000000000000000000001265713322000161155ustar00rootroot00000000000000systemd-229/src/update-utmp/Makefile000077700000000000000000000000001265713322000214232../Makefileustar00rootroot00000000000000systemd-229/src/update-utmp/update-utmp.c000066400000000000000000000204271265713322000205330ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #ifdef HAVE_AUDIT #include #endif #include "sd-bus.h" #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" #include "formats-util.h" #include "log.h" #include "macro.h" #include "special.h" #include "unit-name.h" #include "util.h" #include "utmp-wtmp.h" typedef struct Context { sd_bus *bus; #ifdef HAVE_AUDIT int audit_fd; #endif } Context; static usec_t get_startup_time(Context *c) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; usec_t t = 0; int r; assert(c); r = sd_bus_get_property_trivial( c->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UserspaceTimestamp", &error, 't', &t); if (r < 0) { log_error_errno(r, "Failed to get timestamp: %s", bus_error_message(&error, r)); return 0; } return t; } static int get_current_runlevel(Context *c) { static const struct { const int runlevel; const char *special; } table[] = { /* The first target of this list that is active or has * a job scheduled wins. We prefer runlevels 5 and 3 * here over the others, since these are the main * runlevels used on Fedora. It might make sense to * change the order on some distributions. */ { '5', SPECIAL_GRAPHICAL_TARGET }, { '3', SPECIAL_MULTI_USER_TARGET }, { '1', SPECIAL_RESCUE_TARGET }, }; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; unsigned i; assert(c); for (i = 0; i < ELEMENTSOF(table); i++) { _cleanup_free_ char *state = NULL, *path = NULL; path = unit_dbus_path_from_name(table[i].special); if (!path) return log_oom(); r = sd_bus_get_property_string( c->bus, "org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Unit", "ActiveState", &error, &state); if (r < 0) return log_warning_errno(r, "Failed to get state: %s", bus_error_message(&error, r)); if (streq(state, "active") || streq(state, "reloading")) return table[i].runlevel; } return 0; } static int on_reboot(Context *c) { int r = 0, q; usec_t t; assert(c); /* We finished start-up, so let's write the utmp * record and send the audit msg */ #ifdef HAVE_AUDIT if (c->audit_fd >= 0) if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_BOOT, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && errno != EPERM) { r = log_error_errno(errno, "Failed to send audit message: %m"); } #endif /* If this call fails it will return 0, which * utmp_put_reboot() will then fix to the current time */ t = get_startup_time(c); q = utmp_put_reboot(t); if (q < 0) { log_error_errno(q, "Failed to write utmp record: %m"); r = q; } return r; } static int on_shutdown(Context *c) { int r = 0, q; assert(c); /* We started shut-down, so let's write the utmp * record and send the audit msg */ #ifdef HAVE_AUDIT if (c->audit_fd >= 0) if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_SHUTDOWN, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && errno != EPERM) { r = log_error_errno(errno, "Failed to send audit message: %m"); } #endif q = utmp_put_shutdown(); if (q < 0) { log_error_errno(q, "Failed to write utmp record: %m"); r = q; } return r; } static int on_runlevel(Context *c) { int r = 0, q, previous, runlevel; assert(c); /* We finished changing runlevel, so let's write the * utmp record and send the audit msg */ /* First, get last runlevel */ q = utmp_get_runlevel(&previous, NULL); if (q < 0) { if (q != -ESRCH && q != -ENOENT) return log_error_errno(q, "Failed to get current runlevel: %m"); previous = 0; } /* Secondly, get new runlevel */ runlevel = get_current_runlevel(c); if (runlevel < 0) return runlevel; if (previous == runlevel) return 0; #ifdef HAVE_AUDIT if (c->audit_fd >= 0) { _cleanup_free_ char *s = NULL; if (asprintf(&s, "old-level=%c new-level=%c", previous > 0 ? previous : 'N', runlevel > 0 ? runlevel : 'N') < 0) return log_oom(); if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s, "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && errno != EPERM) r = log_error_errno(errno, "Failed to send audit message: %m"); } #endif q = utmp_put_runlevel(runlevel, previous); if (q < 0 && q != -ESRCH && q != -ENOENT) { log_error_errno(q, "Failed to write utmp record: %m"); r = q; } return r; } int main(int argc, char *argv[]) { Context c = { #ifdef HAVE_AUDIT .audit_fd = -1 #endif }; int r; if (getppid() != 1) { log_error("This program should be invoked by init only."); return EXIT_FAILURE; } if (argc != 2) { log_error("This program requires one argument."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); #ifdef HAVE_AUDIT /* If the kernel lacks netlink or audit support, * don't worry about it. */ c.audit_fd = audit_open(); if (c.audit_fd < 0 && errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT) log_error_errno(errno, "Failed to connect to audit log: %m"); #endif r = bus_connect_system_systemd(&c.bus); if (r < 0) { log_error_errno(r, "Failed to get D-Bus connection: %m"); r = -EIO; goto finish; } log_debug("systemd-update-utmp running as pid "PID_FMT, getpid()); if (streq(argv[1], "reboot")) r = on_reboot(&c); else if (streq(argv[1], "shutdown")) r = on_shutdown(&c); else if (streq(argv[1], "runlevel")) r = on_runlevel(&c); else { log_error("Unknown command %s", argv[1]); r = -EINVAL; } log_debug("systemd-update-utmp stopped as pid "PID_FMT, getpid()); finish: #ifdef HAVE_AUDIT if (c.audit_fd >= 0) audit_close(c.audit_fd); #endif sd_bus_flush_close_unref(c.bus); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } systemd-229/src/user-sessions/000077500000000000000000000000001265713322000164725ustar00rootroot00000000000000systemd-229/src/user-sessions/Makefile000077700000000000000000000000001265713322000220002../Makefileustar00rootroot00000000000000systemd-229/src/user-sessions/user-sessions.c000066400000000000000000000051731265713322000214660ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include "fileio.h" #include "fileio-label.h" #include "log.h" #include "selinux-util.h" #include "string-util.h" #include "util.h" int main(int argc, char*argv[]) { if (argc != 2) { log_error("This program requires one argument."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); mac_selinux_init(NULL); if (streq(argv[1], "start")) { int r = 0; if (unlink("/run/nologin") < 0 && errno != ENOENT) r = log_error_errno(errno, "Failed to remove /run/nologin file: %m"); if (unlink("/etc/nologin") < 0 && errno != ENOENT) { /* If the file doesn't exist and /etc simply * was read-only (in which case unlink() * returns EROFS even if the file doesn't * exist), don't complain */ if (errno != EROFS || access("/etc/nologin", F_OK) >= 0) { log_error_errno(errno, "Failed to remove /etc/nologin file: %m"); return EXIT_FAILURE; } } if (r < 0) return EXIT_FAILURE; } else if (streq(argv[1], "stop")) { int r; r = write_string_file_atomic_label("/run/nologin", "System is going down."); if (r < 0) { log_error_errno(r, "Failed to create /run/nologin: %m"); return EXIT_FAILURE; } } else { log_error("Unknown verb %s.", argv[1]); return EXIT_FAILURE; } mac_selinux_finish(); return EXIT_SUCCESS; } systemd-229/src/vconsole/000077500000000000000000000000001265713322000155005ustar00rootroot00000000000000systemd-229/src/vconsole/.gitignore000066400000000000000000000000231265713322000174630ustar00rootroot00000000000000/90-vconsole.rules systemd-229/src/vconsole/90-vconsole.rules.in000066400000000000000000000006711265713322000212430ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # Each vtcon keeps its own state of fonts. # ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon*", RUN+="@rootlibexecdir@/systemd-vconsole-setup" systemd-229/src/vconsole/Makefile000077700000000000000000000000001265713322000210062../Makefileustar00rootroot00000000000000systemd-229/src/vconsole/vconsole-setup.c000066400000000000000000000236341265713322000206420ustar00rootroot00000000000000/*** This file is part of systemd. Copyright 2010 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include #include #include #include #include #include #include #include #include #include #include "alloc-util.h" #include "fd-util.h" #include "fileio.h" #include "io-util.h" #include "locale-util.h" #include "log.h" #include "process-util.h" #include "signal-util.h" #include "stdio-util.h" #include "string-util.h" #include "terminal-util.h" #include "util.h" #include "virt.h" static bool is_vconsole(int fd) { unsigned char data[1]; data[0] = TIOCL_GETFGCONSOLE; return ioctl(fd, TIOCLINUX, data) >= 0; } static int disable_utf8(int fd) { int r = 0, k; if (ioctl(fd, KDSKBMODE, K_XLATE) < 0) r = -errno; k = loop_write(fd, "\033%@", 3, false); if (k < 0) r = k; k = write_string_file("/sys/module/vt/parameters/default_utf8", "0", 0); if (k < 0) r = k; if (r < 0) log_warning_errno(r, "Failed to disable UTF-8: %m"); return r; } static int enable_utf8(int fd) { int r = 0, k; long current = 0; if (ioctl(fd, KDGKBMODE, ¤t) < 0 || current == K_XLATE) { /* * Change the current keyboard to unicode, unless it * is currently in raw or off mode anyway. We * shouldn't interfere with X11's processing of the * key events. * * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html * */ if (ioctl(fd, KDSKBMODE, K_UNICODE) < 0) r = -errno; } k = loop_write(fd, "\033%G", 3, false); if (k < 0) r = k; k = write_string_file("/sys/module/vt/parameters/default_utf8", "1", 0); if (k < 0) r = k; if (r < 0) log_warning_errno(r, "Failed to enable UTF-8: %m"); return r; } static int keyboard_load_and_wait(const char *vc, const char *map, const char *map_toggle, bool utf8) { const char *args[8]; int i = 0, r; pid_t pid; /* An empty map means kernel map */ if (isempty(map)) return 1; args[i++] = KBD_LOADKEYS; args[i++] = "-q"; args[i++] = "-C"; args[i++] = vc; if (utf8) args[i++] = "-u"; args[i++] = map; if (map_toggle) args[i++] = map_toggle; args[i++] = NULL; pid = fork(); if (pid < 0) return log_error_errno(errno, "Failed to fork: %m"); else if (pid == 0) { (void) reset_all_signal_handlers(); (void) reset_signal_mask(); execv(args[0], (char **) args); _exit(EXIT_FAILURE); } r = wait_for_terminate_and_warn(KBD_LOADKEYS, pid, true); if (r < 0) return r; return r == 0; } static int font_load_and_wait(const char *vc, const char *font, const char *map, const char *unimap) { const char *args[9]; int i = 0, r; pid_t pid; /* An empty font means kernel font */ if (isempty(font)) return 1; args[i++] = KBD_SETFONT; args[i++] = "-C"; args[i++] = vc; args[i++] = font; if (map) { args[i++] = "-m"; args[i++] = map; } if (unimap) { args[i++] = "-u"; args[i++] = unimap; } args[i++] = NULL; pid = fork(); if (pid < 0) return log_error_errno(errno, "Failed to fork: %m"); else if (pid == 0) { (void) reset_all_signal_handlers(); (void) reset_signal_mask(); execv(args[0], (char **) args); _exit(EXIT_FAILURE); } r = wait_for_terminate_and_warn(KBD_SETFONT, pid, true); if (r < 0) return r; return r == 0; } /* * A newly allocated VT uses the font from the active VT. Here * we update all possibly already allocated VTs with the configured * font. It also allows to restart systemd-vconsole-setup.service, * to apply a new font to all VTs. */ static void font_copy_to_all_vcs(int fd) { struct vt_stat vcs = {}; unsigned char map8[E_TABSZ]; unsigned short map16[E_TABSZ]; struct unimapdesc unimapd; struct unipair unipairs[USHRT_MAX]; int i, r; /* get active, and 16 bit mask of used VT numbers */ r = ioctl(fd, VT_GETSTATE, &vcs); if (r < 0) { log_debug_errno(errno, "VT_GETSTATE failed, ignoring: %m"); return; } for (i = 1; i <= 15; i++) { char vcname[strlen("/dev/vcs") + DECIMAL_STR_MAX(int)]; _cleanup_close_ int vcfd = -1; struct console_font_op cfo = {}; if (i == vcs.v_active) continue; /* skip non-allocated ttys */ xsprintf(vcname, "/dev/vcs%i", i); if (access(vcname, F_OK) < 0) continue; xsprintf(vcname, "/dev/tty%i", i); vcfd = open_terminal(vcname, O_RDWR|O_CLOEXEC); if (vcfd < 0) continue; /* copy font from active VT, where the font was uploaded to */ cfo.op = KD_FONT_OP_COPY; cfo.height = vcs.v_active-1; /* tty1 == index 0 */ (void) ioctl(vcfd, KDFONTOP, &cfo); /* copy map of 8bit chars */ if (ioctl(fd, GIO_SCRNMAP, map8) >= 0) (void) ioctl(vcfd, PIO_SCRNMAP, map8); /* copy map of 8bit chars -> 16bit Unicode values */ if (ioctl(fd, GIO_UNISCRNMAP, map16) >= 0) (void) ioctl(vcfd, PIO_UNISCRNMAP, map16); /* copy unicode translation table */ /* unimapd is a ushort count and a pointer to an array of struct unipair { ushort, ushort } */ unimapd.entries = unipairs; unimapd.entry_ct = USHRT_MAX; if (ioctl(fd, GIO_UNIMAP, &unimapd) >= 0) { struct unimapinit adv = { 0, 0, 0 }; (void) ioctl(vcfd, PIO_UNIMAPCLR, &adv); (void) ioctl(vcfd, PIO_UNIMAP, &unimapd); } } } int main(int argc, char **argv) { const char *vc; _cleanup_free_ char *vc_keymap = NULL, *vc_keymap_toggle = NULL, *vc_font = NULL, *vc_font_map = NULL, *vc_font_unimap = NULL; _cleanup_close_ int fd = -1; bool utf8, font_copy = false, font_ok, keyboard_ok; int r = EXIT_FAILURE; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); if (argv[1]) vc = argv[1]; else { vc = "/dev/tty0"; font_copy = true; } fd = open_terminal(vc, O_RDWR|O_CLOEXEC); if (fd < 0) { log_error_errno(fd, "Failed to open %s: %m", vc); return EXIT_FAILURE; } if (!is_vconsole(fd)) { log_error("Device %s is not a virtual console.", vc); return EXIT_FAILURE; } utf8 = is_locale_utf8(); r = parse_env_file("/etc/vconsole.conf", NEWLINE, "KEYMAP", &vc_keymap, "KEYMAP_TOGGLE", &vc_keymap_toggle, "FONT", &vc_font, "FONT_MAP", &vc_font_map, "FONT_UNIMAP", &vc_font_unimap, NULL); if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to read /etc/vconsole.conf: %m"); /* Let the kernel command line override /etc/vconsole.conf */ if (detect_container() <= 0) { r = parse_env_file("/proc/cmdline", WHITESPACE, "vconsole.keymap", &vc_keymap, "vconsole.keymap.toggle", &vc_keymap_toggle, "vconsole.font", &vc_font, "vconsole.font.map", &vc_font_map, "vconsole.font.unimap", &vc_font_unimap, NULL); if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to read /proc/cmdline: %m"); } if (utf8) (void) enable_utf8(fd); else (void) disable_utf8(fd); font_ok = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap) > 0; keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) > 0; /* Only copy the font when we executed setfont successfully */ if (font_copy && font_ok) (void) font_copy_to_all_vcs(fd); return font_ok && keyboard_ok ? EXIT_SUCCESS : EXIT_FAILURE; } systemd-229/sysctl.d/000077500000000000000000000000001265713322000146245ustar00rootroot00000000000000systemd-229/sysctl.d/.gitignore000066400000000000000000000000221265713322000166060ustar00rootroot00000000000000/50-coredump.conf systemd-229/sysctl.d/50-coredump.conf.in000066400000000000000000000010111265713322000201310ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See sysctl.d(5) for the description of the files in this directory, # and systemd-coredump(8) and core(5) for the explanation of the # setting below. kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %P %u %g %s %t %c %e systemd-229/sysctl.d/50-default.conf000066400000000000000000000024211265713322000173400ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See sysctl.d(5) and core(5) for for documentation. # To override settings in this file, create a local file in /etc # (e.g. /etc/sysctl.d/90-override.conf), and put any assignments # there. # System Request functionality of the kernel (SYNC) # # Use kernel.sysrq = 1 to allow all keys. # See http://fedoraproject.org/wiki/QA/Sysrq for a list of values and keys. kernel.sysrq = 16 # Append the PID to the core filename kernel.core_uses_pid = 1 # Source route verification net.ipv4.conf.default.rp_filter = 1 net.ipv4.conf.all.rp_filter = 1 # Do not accept source routing net.ipv4.conf.default.accept_source_route = 0 net.ipv4.conf.all.accept_source_route = 0 # Promote secondary addresses when the primary address is removed net.ipv4.conf.default.promote_secondaries = 1 net.ipv4.conf.all.promote_secondaries = 1 # Fair Queue CoDel packet scheduler to fight bufferbloat net.core.default_qdisc = fq_codel # Enable hard and soft link protection fs.protected_hardlinks = 1 fs.protected_symlinks = 1 systemd-229/sysctl.d/Makefile000077700000000000000000000000001265713322000207212../src/Makefileustar00rootroot00000000000000systemd-229/system-preset/000077500000000000000000000000001265713322000157055ustar00rootroot00000000000000systemd-229/system-preset/90-systemd.preset000066400000000000000000000015451265713322000210540ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # These ones should be enabled by default, even if distributions # generally follow a default-off policy. enable remote-fs.target enable machines.target enable getty@.service enable systemd-timesyncd.service enable systemd-networkd.service enable systemd-resolved.service disable console-getty.service disable console-shell.service disable debug-shell.service disable halt.target disable kexec.target disable poweroff.target disable reboot.target disable rescue.target disable syslog.socket disable systemd-journal-gatewayd.* disable systemd-networkd-wait-online.service systemd-229/system-preset/Makefile000077700000000000000000000000001265713322000220022../src/Makefileustar00rootroot00000000000000systemd-229/sysusers.d/000077500000000000000000000000001265713322000152035ustar00rootroot00000000000000systemd-229/sysusers.d/.gitignore000066400000000000000000000000571265713322000171750ustar00rootroot00000000000000/basic.conf /systemd.conf /systemd-remote.conf systemd-229/sysusers.d/Makefile000077700000000000000000000000001265713322000213002../src/Makefileustar00rootroot00000000000000systemd-229/sysusers.d/basic.conf.in000066400000000000000000000020721265713322000175410ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # The superuser u root 0 "Super User" /root # The nobody user for NFS file systems u nobody 65534 "Nobody" - # Administrator group: can *see* more than normal users g adm - - - # Administrator group: can *do* more than normal users g wheel - - - # Access to certain kernel and userspace facilities g kmem - - - g tty @TTY_GID@ - - g utmp - - - # Hardware access groups g audio - - - g cdrom - - - g dialout - - - g disk - - - g input - - - g lp - - - g tape - - - g video - - - # Default group for normal users g users - - - systemd-229/sysusers.d/systemd-remote.conf.m4000066400000000000000000000010111265713322000213430ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. m4_ifdef(`HAVE_MICROHTTPD', u systemd-journal-gateway - "systemd Journal Gateway" u systemd-journal-remote - "systemd Journal Remote" )m4_dnl m4_ifdef(`HAVE_LIBCURL', u systemd-journal-upload - "systemd Journal Upload" )m4_dnl systemd-229/sysusers.d/systemd.conf.m4000066400000000000000000000012641265713322000200640ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. g systemd-journal - - u systemd-bus-proxy - "systemd Bus Proxy" m4_ifdef(`ENABLE_NETWORKD', u systemd-network - "systemd Network Management" )m4_dnl m4_ifdef(`ENABLE_RESOLVED', u systemd-resolve - "systemd Resolver" )m4_dnl m4_ifdef(`ENABLE_TIMESYNCD', u systemd-timesync - "systemd Time Synchronization" )m4_dnl m4_ifdef(`ENABLE_COREDUMP', u systemd-coredump - "systemd Core Dumper" )m4_dnl systemd-229/test/000077500000000000000000000000001265713322000140405ustar00rootroot00000000000000systemd-229/test/.gitignore000066400000000000000000000000411265713322000160230ustar00rootroot00000000000000.testdir test.log /dev /run /sys systemd-229/test/Makefile000066400000000000000000000006161265713322000155030ustar00rootroot00000000000000# Just a little hook script to easy building when in this directory .PHONY: all check clean all: $(MAKE) -C .. clean: @for i in TEST-[0-9]*; do \ [ -d $$i ] || continue ; \ [ -f $$i/Makefile ] || continue ; \ make -C $$i clean ; \ done check: $(MAKE) -C .. all @for i in TEST-[0-9]*; do \ [ -d $$i ] || continue ; \ [ -f $$i/Makefile ] || continue ; \ make -C $$i all ; \ done systemd-229/test/README.testsuite000066400000000000000000000026151265713322000167540ustar00rootroot00000000000000The extended testsuite only works with uid=0. It contains of several subdirectories named "test/TEST-??-*", which are run one by one. To run the extended testsuite do the following: $ make all $ cd test $ sudo make clean check ... make[1]: Entering directory `/mnt/data/harald/git/systemd/test/TEST-01-BASIC' Making all in . Making all in po TEST: Basic systemd setup [OK] make[1]: Leaving directory `/mnt/data/harald/git/systemd/test/TEST-01-BASIC' ... If one of the tests fails, then $subdir/test.log contains the log file of the test. To debug a special testcase of the testsuite do: $ make all $ cd test/TEST-01-BASIC $ sudo make clean setup run QEMU ==== If you want to log in the testsuite virtual machine, you can specify additional kernel command line parameter with $KERNEL_APPEND. $ sudo make KERNEL_APPEND="systemd.unit=multi-user.target" clean setup run you can even skip the "clean" and "setup" if you want to run the machine again. $ sudo make KERNEL_APPEND="systemd.unit=multi-user.target" run You can specify a different kernel and initramfs with $KERNEL_BIN and $INITRD. (Fedora's or Debian's default kernel path and initramfs are used by default) $ sudo make KERNEL_BIN=/boot/vmlinuz-foo INITRD=/boot/initramfs-bar clean check A script will try to find your QEMU binary. If you want to specify a different one you can use $QEMU_BIN. $ sudo make QEMU_BIN=/path/to/qemu/qemu-kvm clean check systemd-229/test/TEST-01-BASIC/000077500000000000000000000000001265713322000156545ustar00rootroot00000000000000systemd-229/test/TEST-01-BASIC/Makefile000066400000000000000000000004711265713322000173160ustar00rootroot00000000000000all: @make -s --no-print-directory -C ../.. all @basedir=../.. TEST_BASE_DIR=../ ./test.sh --all setup: @make --no-print-directory -C ../.. all @basedir=../.. TEST_BASE_DIR=../ ./test.sh --setup clean: @basedir=../.. TEST_BASE_DIR=../ ./test.sh --clean run: @basedir=../.. TEST_BASE_DIR=../ ./test.sh --run systemd-229/test/TEST-01-BASIC/test.sh000077500000000000000000000042721265713322000171770ustar00rootroot00000000000000#!/bin/bash # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh TEST_DESCRIPTION="Basic systemd setup" . $TEST_BASE_DIR/test-functions check_result_qemu() { ret=1 mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root [[ -e $TESTDIR/root/testok ]] && ret=0 [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR cp -a $TESTDIR/root/var/log/journal $TESTDIR umount $TESTDIR/root [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed ls -l $TESTDIR/journal/*/*.journal test -s $TESTDIR/failed && ret=$(($ret+1)) return $ret } test_run() { if run_qemu; then check_result_qemu || return 1 else dwarn "can't run QEMU, skipping" fi if check_nspawn; then run_nspawn check_result_nspawn || return 1 else dwarn "can't run systemd-nspawn, skipping" fi return 0 } test_setup() { create_empty_image mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root # Create what will eventually be our root filesystem onto an overlay ( LOG_LEVEL=5 eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) setup_basic_environment # setup the testsuite service cat >$initdir/etc/systemd/system/testsuite.service < /failed ; echo OK > /testok' Type=oneshot EOF setup_testsuite ) || return 1 setup_nspawn_root # mask some services that we do not want to run in these tests ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service ddebug "umount $TESTDIR/root" umount $TESTDIR/root } test_cleanup() { umount $TESTDIR/root 2>/dev/null [[ $LOOPDEV ]] && losetup -d $LOOPDEV return 0 } do_test "$@" systemd-229/test/TEST-02-CRYPTSETUP/000077500000000000000000000000001265713322000165565ustar00rootroot00000000000000systemd-229/test/TEST-02-CRYPTSETUP/Makefile000077700000000000000000000000001265713322000237002../TEST-01-BASIC/Makefileustar00rootroot00000000000000systemd-229/test/TEST-02-CRYPTSETUP/test.sh000077500000000000000000000052441265713322000201010ustar00rootroot00000000000000#!/bin/bash # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh TEST_DESCRIPTION="cryptsetup systemd setup" . $TEST_BASE_DIR/test-functions check_result_qemu() { ret=1 mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root [[ -e $TESTDIR/root/testok ]] && ret=0 [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile mount /dev/mapper/varcrypt $TESTDIR/root/var cp -a $TESTDIR/root/var/log/journal $TESTDIR umount $TESTDIR/root/var umount $TESTDIR/root cryptsetup luksClose /dev/mapper/varcrypt [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed ls -l $TESTDIR/journal/*/*.journal test -s $TESTDIR/failed && ret=$(($ret+1)) return $ret } test_run() { if run_qemu; then check_result_qemu || return 1 else dwarn "can't run QEMU, skipping" fi return 0 } test_setup() { create_empty_image echo -n test >$TESTDIR/keyfile cryptsetup -q luksFormat ${LOOPDEV}p2 $TESTDIR/keyfile cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile mkfs.ext3 -L var /dev/mapper/varcrypt mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root mkdir -p $TESTDIR/root/var mount /dev/mapper/varcrypt $TESTDIR/root/var # Create what will eventually be our root filesystem onto an overlay ( LOG_LEVEL=5 eval $(udevadm info --export --query=env --name=/dev/mapper/varcrypt) eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) setup_basic_environment # setup the testsuite service cat >$initdir/etc/systemd/system/testsuite.service < /failed ; echo OK > /testok' Type=oneshot EOF setup_testsuite install_dmevent generate_module_dependencies cat >$initdir/etc/crypttab < $initdir/etc/varkey cat $initdir/etc/crypttab | ddebug cat >>$initdir/etc/fstab </dev/null [[ -b /dev/mapper/varcrypt ]] && cryptsetup luksClose /dev/mapper/varcrypt umount $TESTDIR/root 2>/dev/null [[ $LOOPDEV ]] && losetup -d $LOOPDEV return 0 } do_test "$@" systemd-229/test/TEST-03-JOBS/000077500000000000000000000000001265713322000155725ustar00rootroot00000000000000systemd-229/test/TEST-03-JOBS/Makefile000077700000000000000000000000001265713322000227142../TEST-01-BASIC/Makefileustar00rootroot00000000000000systemd-229/test/TEST-03-JOBS/test-jobs.sh000077500000000000000000000034711265713322000200500ustar00rootroot00000000000000#!/bin/bash -x # Test merging of a --job-mode=ignore-dependencies job into a previously # installed job. systemctl start --no-block hello-after-sleep.target systemctl list-jobs > /root/list-jobs.txt while ! grep 'sleep\.service.*running' /root/list-jobs.txt; do systemctl list-jobs > /root/list-jobs.txt done grep 'hello\.service.*waiting' /root/list-jobs.txt || exit 1 # This is supposed to finish quickly, not wait for sleep to finish. START_SEC=$(date -u '+%s') systemctl start --job-mode=ignore-dependencies hello END_SEC=$(date -u '+%s') ELAPSED=$(($END_SEC-$START_SEC)) [ "$ELAPSED" -lt 3 ] || exit 1 # sleep should still be running, hello not. systemctl list-jobs > /root/list-jobs.txt grep 'sleep\.service.*running' /root/list-jobs.txt || exit 1 grep 'hello\.service' /root/list-jobs.txt && exit 1 systemctl stop sleep.service hello-after-sleep.target || exit 1 # Test for a crash when enqueuing a JOB_NOP when other job already exists systemctl start --no-block hello-after-sleep.target || exit 1 # hello.service should still be waiting, so these try-restarts will collapse # into NOPs. systemctl try-restart --job-mode=fail hello.service || exit 1 systemctl try-restart hello.service || exit 1 systemctl stop hello.service sleep.service hello-after-sleep.target || exit 1 # TODO: add more job queueing/merging tests here. # Test for irreversible jobs systemctl start unstoppable.service || exit 1 # This is expected to fail with 'job cancelled' systemctl stop unstoppable.service && exit 1 # But this should succeed systemctl stop --job-mode=replace-irreversibly unstoppable.service || exit 1 # We're going to shutdown soon. Let's see if it succeeds when # there's an active service that tries to be unstoppable. # Shutdown of the container/VM will hang if not. systemctl start unstoppable.service || exit 1 touch /testok systemd-229/test/TEST-03-JOBS/test.sh000077500000000000000000000036121265713322000171120ustar00rootroot00000000000000#!/bin/bash # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh TEST_DESCRIPTION="Job-related tests" . $TEST_BASE_DIR/test-functions check_result_qemu() { ret=1 mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root [[ -e $TESTDIR/root/testok ]] && ret=0 [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR cp -a $TESTDIR/root/var/log/journal $TESTDIR umount $TESTDIR/root [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed ls -l $TESTDIR/journal/*/*.journal test -s $TESTDIR/failed && ret=$(($ret+1)) return $ret } test_run() { if run_qemu; then check_result_qemu || return 1 else dwarn "can't run QEMU, skipping" fi if check_nspawn; then run_nspawn check_result_nspawn || return 1 else dwarn "can't run systemd-nspawn, skipping" fi return 0 } test_setup() { create_empty_image mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root # Create what will eventually be our root filesystem onto an overlay ( LOG_LEVEL=5 eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) setup_basic_environment # setup the testsuite service cat >$initdir/etc/systemd/system/testsuite.service </dev/null [[ $LOOPDEV ]] && losetup -d $LOOPDEV return 0 } do_test "$@" systemd-229/test/TEST-04-JOURNAL/000077500000000000000000000000001265713322000161505ustar00rootroot00000000000000systemd-229/test/TEST-04-JOURNAL/Makefile000077700000000000000000000000001265713322000232722../TEST-01-BASIC/Makefileustar00rootroot00000000000000systemd-229/test/TEST-04-JOURNAL/test-journal.sh000077500000000000000000000032141265713322000211360ustar00rootroot00000000000000#!/bin/bash set -x set -e set -o pipefail # Test stdout stream # Skip empty lines ID=$(journalctl --new-id128 | sed -n 2p) >/expected printf $'\n\n\n' | systemd-cat -t "$ID" --level-prefix false journalctl --sync journalctl -b -o cat -t "$ID" >/output cmp /expected /output ID=$(journalctl --new-id128 | sed -n 2p) >/expected printf $'<5>\n<6>\n<7>\n' | systemd-cat -t "$ID" --level-prefix true journalctl --sync journalctl -b -o cat -t "$ID" >/output cmp /expected /output # Remove trailing spaces ID=$(journalctl --new-id128 | sed -n 2p) printf "Trailing spaces\n">/expected printf $'<5>Trailing spaces \t \n' | systemd-cat -t "$ID" --level-prefix true journalctl --sync journalctl -b -o cat -t "$ID" >/output cmp /expected /output ID=$(journalctl --new-id128 | sed -n 2p) printf "Trailing spaces\n">/expected printf $'Trailing spaces \t \n' | systemd-cat -t "$ID" --level-prefix false journalctl --sync journalctl -b -o cat -t "$ID" >/output cmp /expected /output # Don't remove leading spaces ID=$(journalctl --new-id128 | sed -n 2p) printf $' \t Leading spaces\n'>/expected printf $'<5> \t Leading spaces\n' | systemd-cat -t "$ID" --level-prefix true journalctl --sync journalctl -b -o cat -t "$ID" >/output cmp /expected /output ID=$(journalctl --new-id128 | sed -n 2p) printf $' \t Leading spaces\n'>/expected printf $' \t Leading spaces\n' | systemd-cat -t "$ID" --level-prefix false journalctl --sync journalctl -b -o cat -t "$ID" >/output cmp /expected /output # Don't lose streams on restart systemctl start forever-print-hola sleep 3 systemctl restart systemd-journald sleep 3 systemctl stop forever-print-hola [[ ! -f "/i-lose-my-logs" ]] touch /testok systemd-229/test/TEST-04-JOURNAL/test.sh000077500000000000000000000037121265713322000174710ustar00rootroot00000000000000#!/bin/bash # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh TEST_DESCRIPTION="Journal-related tests" . $TEST_BASE_DIR/test-functions check_result_qemu() { ret=1 mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root [[ -e $TESTDIR/root/testok ]] && ret=0 [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR cp -a $TESTDIR/root/var/log/journal $TESTDIR umount $TESTDIR/root [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed ls -l $TESTDIR/journal/*/*.journal test -s $TESTDIR/failed && ret=$(($ret+1)) return $ret } test_run() { if run_qemu; then check_result_qemu || return 1 else dwarn "can't run QEMU, skipping" fi if check_nspawn; then run_nspawn check_result_nspawn || return 1 else dwarn "can't run systemd-nspawn, skipping" fi return 0 } test_setup() { create_empty_image mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root # Create what will eventually be our root filesystem onto an overlay ( LOG_LEVEL=5 eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) setup_basic_environment # setup the testsuite service cat >$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/forever-print-hola.service </dev/null [[ $LOOPDEV ]] && losetup -d $LOOPDEV return 0 } do_test "$@" systemd-229/test/TEST-05-RLIMITS/000077500000000000000000000000001265713322000161625ustar00rootroot00000000000000systemd-229/test/TEST-05-RLIMITS/Makefile000077700000000000000000000000001265713322000233042../TEST-01-BASIC/Makefileustar00rootroot00000000000000systemd-229/test/TEST-05-RLIMITS/test-rlimits.sh000077500000000000000000000007151265713322000211640ustar00rootroot00000000000000#!/bin/bash set -x set -e set -o pipefail [[ "$(systemctl show -p DefaultLimitNOFILESoft)" = "DefaultLimitNOFILESoft=10000" ]] [[ "$(systemctl show -p DefaultLimitNOFILE)" = "DefaultLimitNOFILE=16384" ]] [[ "$(systemctl show -p LimitNOFILESoft testsuite.service)" = "LimitNOFILESoft=10000" ]] [[ "$(systemctl show -p LimitNOFILE testsuite.service)" = "LimitNOFILE=16384" ]] [[ "$(ulimit -n -S)" = "10000" ]] [[ "$(ulimit -n -H)" = "16384" ]] touch /testok systemd-229/test/TEST-05-RLIMITS/test.sh000077500000000000000000000035041265713322000175020ustar00rootroot00000000000000#!/bin/bash # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh TEST_DESCRIPTION="Resource limits-related tests" . $TEST_BASE_DIR/test-functions check_result_qemu() { ret=1 mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root [[ -e $TESTDIR/root/testok ]] && ret=0 [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR cp -a $TESTDIR/root/var/log/journal $TESTDIR umount $TESTDIR/root [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed ls -l $TESTDIR/journal/*/*.journal test -s $TESTDIR/failed && ret=$(($ret+1)) return $ret } test_run() { if run_qemu; then check_result_qemu || return 1 else dwarn "can't run QEMU, skipping" fi if check_nspawn; then run_nspawn check_result_nspawn || return 1 else dwarn "can't run systemd-nspawn, skipping" fi return 0 } test_setup() { create_empty_image mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root # Create what will eventually be our root filesystem onto an overlay ( LOG_LEVEL=5 eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) setup_basic_environment cat >$initdir/etc/systemd/system.conf <$initdir/etc/systemd/system/testsuite.service </dev/null [[ $LOOPDEV ]] && losetup -d $LOOPDEV return 0 } do_test "$@" systemd-229/test/TEST-06-SELINUX/000077500000000000000000000000001265713322000161675ustar00rootroot00000000000000systemd-229/test/TEST-06-SELINUX/Makefile000066400000000000000000000004711265713322000176310ustar00rootroot00000000000000all: @make -s --no-print-directory -C ../.. all @basedir=../.. TEST_BASE_DIR=../ ./test.sh --all setup: @make --no-print-directory -C ../.. all @basedir=../.. TEST_BASE_DIR=../ ./test.sh --setup clean: @basedir=../.. TEST_BASE_DIR=../ ./test.sh --clean run: @basedir=../.. TEST_BASE_DIR=../ ./test.sh --run systemd-229/test/TEST-06-SELINUX/systemd_test.if000066400000000000000000000002371265713322000212400ustar00rootroot00000000000000template(`systemd_test_base_template', ` gen_require(` attribute systemd_test_domain_type; ') type $1_t, systemd_test_domain_type; domain_type($1_t) ') systemd-229/test/TEST-06-SELINUX/systemd_test.te000066400000000000000000000030401265713322000212450ustar00rootroot00000000000000policy_module(systemd_test, 0.0.1) # declarations attribute systemd_test_domain_type; systemd_test_base_template(systemd_test) systemd_test_base_template(systemd_test_status) systemd_test_base_template(systemd_test_start) systemd_test_base_template(systemd_test_stop) systemd_test_base_template(systemd_test_reload) # systemd_test_domain_type require { role system_r; role unconfined_r; type bin_t; type initrc_t; type systemd_systemctl_exec_t; type unconfined_service_t; } role system_r types systemd_test_domain_type; role unconfined_r types systemd_test_domain_type; allow systemd_test_domain_type bin_t: file entrypoint; allow systemd_test_domain_type systemd_systemctl_exec_t: file entrypoint; allow initrc_t systemd_test_domain_type: process transition; allow unconfined_service_t systemd_test_domain_type: process transition; corecmd_exec_bin(systemd_test_domain_type) init_signal_script(systemd_test_domain_type) init_sigchld_script(systemd_test_domain_type) systemd_exec_systemctl(systemd_test_domain_type) userdom_use_user_ttys(systemd_test_domain_type) userdom_use_user_ptys(systemd_test_domain_type) optional_policy(` dbus_system_bus_client(systemd_test_domain_type) init_dbus_chat(systemd_test_domain_type) ') # systemd_test_*_t require { type systemd_unit_file_t; } allow systemd_test_status_t systemd_unit_file_t: service { status }; allow systemd_test_start_t systemd_unit_file_t: service { start }; allow systemd_test_stop_t systemd_unit_file_t: service { stop }; allow systemd_test_reload_t systemd_unit_file_t: service { reload }; systemd-229/test/TEST-06-SELINUX/test-selinux-checks.sh000077500000000000000000000003671265713322000224360ustar00rootroot00000000000000#!/bin/bash set -x set -e set -o pipefail echo 1 >/sys/fs/selinux/enforce runcon -t systemd_test_start_t systemctl start hola runcon -t systemd_test_reload_t systemctl reload hola runcon -t systemd_test_stop_t systemctl stop hola touch /testok systemd-229/test/TEST-06-SELINUX/test.sh000077500000000000000000000077541265713322000175220ustar00rootroot00000000000000#!/bin/bash # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh TEST_DESCRIPTION="SELinux tests" # Requirements: # Fedora 23 # selinux-policy-targeted # selinux-policy-devel . $TEST_BASE_DIR/test-functions SETUP_SELINUX=yes KERNEL_APPEND="$KERNEL_APPEND selinux=1" check_result_qemu() { ret=1 mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root [[ -e $TESTDIR/root/testok ]] && ret=0 [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR cp -a $TESTDIR/root/var/log/journal $TESTDIR umount $TESTDIR/root [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed ls -l $TESTDIR/journal/*/*.journal test -s $TESTDIR/failed && ret=$(($ret+1)) return $ret } test_run() { if run_qemu; then check_result_qemu || return 1 else dwarn "can't run QEMU, skipping" fi return 0 } test_setup() { create_empty_image mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root # Create what will eventually be our root filesystem onto an overlay ( LOG_LEVEL=5 eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) setup_basic_environment # setup the testsuite service cat <$initdir/etc/systemd/system/testsuite.service [Unit] Description=Testsuite service After=multi-user.target [Service] ExecStart=/test-selinux-checks.sh Type=oneshot EOF cat <$initdir/etc/systemd/system/hola.service [Service] Type=oneshot ExecStart=/bin/echo Start Hola ExecReload=/bin/echo Reload Hola ExecStop=/bin/echo Stop Hola RemainAfterExit=yes EOF setup_testsuite cat <$initdir/etc/systemd/system/load-systemd-test-module.service [Unit] Description=Load systemd-test module DefaultDependencies=no Requires=local-fs.target Conflicts=shutdown.target After=local-fs.target Before=sysinit.target shutdown.target autorelabel.service ConditionSecurity=selinux ConditionPathExists=|/.load-systemd-test-module [Service] ExecStart=/bin/sh -x -c 'echo 0 >/sys/fs/selinux/enforce && cd /systemd-test-module && make -f /usr/share/selinux/devel/Makefile load && rm /.load-systemd-test-module' Type=oneshot TimeoutSec=0 RemainAfterExit=yes EOF touch $initdir/.load-systemd-test-module mkdir -p $initdir/etc/systemd/system/basic.target.wants ln -fs load-systemd-test-module.service $initdir/etc/systemd/system/basic.target.wants/load-systemd-test-module.service local _modules_dir=/var/lib/selinux rm -rf $initdir/$_modules_dir if ! cp -ar $_modules_dir $initdir/$_modules_dir; then dfatal "Failed to copy $_modules_dir" exit 1 fi local _policy_headers_dir=/usr/share/selinux/devel rm -rf $initdir/$_policy_headers_dir inst_dir /usr/share/selinux if ! cp -ar $_policy_headers_dir $initdir/$_policy_headers_dir; then dfatal "Failed to copy $_policy_headers_dir" exit 1 fi mkdir $initdir/systemd-test-module cp systemd_test.te $initdir/systemd-test-module cp systemd_test.if $initdir/systemd-test-module cp test-selinux-checks.sh $initdir dracut_install -o sesearch dracut_install runcon dracut_install checkmodule semodule semodule_package m4 make /usr/libexec/selinux/hll/pp load_policy sefcontext_compile ) || return 1 # mask some services that we do not want to run in these tests ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service ddebug "umount $TESTDIR/root" umount $TESTDIR/root } test_cleanup() { umount $TESTDIR/root 2>/dev/null [[ $LOOPDEV ]] && losetup -d $LOOPDEV return 0 } do_test "$@" systemd-229/test/TEST-07-ISSUE-1981/000077500000000000000000000000001265713322000163315ustar00rootroot00000000000000systemd-229/test/TEST-07-ISSUE-1981/Makefile000077700000000000000000000000001265713322000234532../TEST-01-BASIC/Makefileustar00rootroot00000000000000systemd-229/test/TEST-07-ISSUE-1981/test-segfault.sh000077500000000000000000000007751265713322000214700ustar00rootroot00000000000000#!/bin/bash set -x set -e >/failed cat <<'EOL' >/lib/systemd/system/my.service [Service] Type=oneshot ExecStart=/bin/echo Timer runs me EOL cat <<'EOL' >/lib/systemd/system/my.timer [Timer] OnBootSec=10s OnUnitInactiveSec=1h EOL systemctl unmask my.timer systemctl start my.timer mkdir -p /etc/systemd/system/my.timer.d/ cat <<'EOL' >/etc/systemd/system/my.timer.d/override.conf [Timer] OnBootSec=10s OnUnitInactiveSec=1h EOL systemctl daemon-reload systemctl mask my.timer touch /testok rm /failed systemd-229/test/TEST-07-ISSUE-1981/test.sh000077500000000000000000000025351265713322000176540ustar00rootroot00000000000000#!/bin/bash # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/1981" . $TEST_BASE_DIR/test-functions test_run() { dwarn "skipping QEMU" if check_nspawn; then timeout --foreground 30s systemd-nspawn --kill-signal=SIGKILL --boot --directory=$TESTDIR/nspawn-root $ROOTLIBDIR/systemd $KERNEL_APPEND check_result_nspawn || return 1 else dwarn "can't run systemd-nspawn, skipping" fi return 0 } test_setup() { create_empty_image mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root # Create what will eventually be our root filesystem onto an overlay ( LOG_LEVEL=5 eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) setup_basic_environment # setup the testsuite service cat >$initdir/etc/systemd/system/testsuite.service </dev/null [[ $LOOPDEV ]] && losetup -d $LOOPDEV return 0 } do_test "$@" systemd-229/test/a.service000066400000000000000000000001301265713322000156340ustar00rootroot00000000000000[Unit] Description=A Requires=b.service Before=b.service [Service] ExecStart=/bin/true systemd-229/test/b.service000066400000000000000000000001041265713322000156360ustar00rootroot00000000000000[Unit] Description=B Wants=f.service [Service] ExecStart=/bin/true systemd-229/test/basic.target000077700000000000000000000000001265713322000221722../units/basic.targetustar00rootroot00000000000000systemd-229/test/bus-policy/000077500000000000000000000000001265713322000161265ustar00rootroot00000000000000systemd-229/test/bus-policy/check-own-rules.conf000066400000000000000000000006761265713322000220140ustar00rootroot00000000000000 mybususer unix:path=/foo/bar tcp:port=1234 /usr/share/foo systemd-229/test/bus-policy/hello.conf000066400000000000000000000005651265713322000201060ustar00rootroot00000000000000 systemd-229/test/bus-policy/many-rules.conf000066400000000000000000000052751265713322000211020ustar00rootroot00000000000000 mybususer unix:path=/foo/bar tcp:port=1234 basic.d /usr/share/foo nonexistent.conf 5000 5000 300 5000 6000 50 80 64 64 256 512 systemd-229/test/bus-policy/methods.conf000066400000000000000000000012451265713322000204420ustar00rootroot00000000000000 systemd-229/test/bus-policy/ownerships.conf000066400000000000000000000012111265713322000211710ustar00rootroot00000000000000 systemd-229/test/bus-policy/signals.conf000066400000000000000000000006231265713322000204360ustar00rootroot00000000000000 systemd-229/test/bus-policy/test.conf000066400000000000000000000015471265713322000177630ustar00rootroot00000000000000 systemd-229/test/c.service000066400000000000000000000001071265713322000156420ustar00rootroot00000000000000[Unit] Description=C Requires=a.service [Service] ExecStart=/bin/true systemd-229/test/d.service000066400000000000000000000001571265713322000156500ustar00rootroot00000000000000[Unit] Description=D:Cyclic After=b.service Before=a.service Requires=a.service [Service] ExecStart=/bin/true systemd-229/test/daughter.service000066400000000000000000000001431265713322000172230ustar00rootroot00000000000000[Unit] Description=Daughter Service [Service] Slice=parent.slice Type=oneshot ExecStart=/bin/true systemd-229/test/e.service000066400000000000000000000001541265713322000156460ustar00rootroot00000000000000[Unit] Description=E:Cyclic After=b.service Before=a.service Wants=a.service [Service] ExecStart=/bin/true systemd-229/test/end.service000066400000000000000000000003331265713322000161670ustar00rootroot00000000000000[Unit] Description=End the test After=testsuite.service OnFailure=poweroff.target OnFailureJobMode=replace-irreversibly [Service] Type=oneshot ExecStart=/bin/sh -x -c 'systemctl poweroff --no-block' TimeoutStartSec=5m systemd-229/test/f.service000066400000000000000000000000641265713322000156470ustar00rootroot00000000000000[Unit] Description=F [Service] ExecStart=/bin/true systemd-229/test/g.service000066400000000000000000000001101265713322000156400ustar00rootroot00000000000000[Unit] Description=G Conflicts=e.service [Service] ExecStart=/bin/true systemd-229/test/grandchild.service000066400000000000000000000001521265713322000175170ustar00rootroot00000000000000[Unit] Description=Grandchild Service [Service] Slice=parent-deep.slice Type=oneshot ExecStart=/bin/true systemd-229/test/h.service000066400000000000000000000001041265713322000156440ustar00rootroot00000000000000[Unit] Description=H Wants=g.service [Service] ExecStart=/bin/true systemd-229/test/hello-after-sleep.target000066400000000000000000000002021265713322000205520ustar00rootroot00000000000000[Unit] Description=Sleep for a minute, then say hello. Wants=sleep.service hello.service After=sleep.service Before=hello.service systemd-229/test/hello.service000066400000000000000000000001141265713322000165210ustar00rootroot00000000000000[Unit] Description=Hello World [Service] ExecStart=/bin/echo "Hello World" systemd-229/test/loopy.service000066400000000000000000000000361265713322000165630ustar00rootroot00000000000000[Service] ExecStart=/bin/true systemd-229/test/loopy.service.d/000077500000000000000000000000001265713322000170635ustar00rootroot00000000000000systemd-229/test/loopy.service.d/compat.conf000066400000000000000000000000751265713322000212170ustar00rootroot00000000000000[Unit] BindsTo=loopy2.service [Install] Also=loopy2.service systemd-229/test/loopy2.service000077700000000000000000000000001265713322000213652loopy.serviceustar00rootroot00000000000000systemd-229/test/loopy3.service000066400000000000000000000000771265713322000166530ustar00rootroot00000000000000[Service] ExecStart=/bin/true [Unit] Conflicts=loopy4.service systemd-229/test/loopy4.service000077700000000000000000000000001265713322000214522loopy3.serviceustar00rootroot00000000000000systemd-229/test/mocks/000077500000000000000000000000001265713322000151545ustar00rootroot00000000000000systemd-229/test/mocks/fsck000077500000000000000000000007321265713322000160320ustar00rootroot00000000000000#!/bin/bash fd=0 OPTIND=1 while getopts "C:aTlM" opt; do case "$opt" in C) fd=$OPTARG ;; \?);; esac done shift "$((OPTIND-1))" device=$1 echo "Running fake fsck on $device" declare -a maxpass=(30 5 2 30 60) for pass in {1..5}; do maxprogress=${maxpass[$((pass-1))]} for (( current=0; current<=${maxprogress}; current++)); do echo "$pass $current $maxprogress $device">&$fd sleep 0.1 done done systemd-229/test/networkd-test.py000077500000000000000000000344561265713322000172430ustar00rootroot00000000000000#!/usr/bin/env python3 # # networkd integration test # This uses temporary configuration in /run and temporary veth devices, and # does not write anything on disk or change any system configuration; # but it assumes (and checks at the beginning) that networkd is not currently # running. # This can be run on a normal installation, in QEMU, nspawn, or LXC. # ATTENTION: This uses the *installed* networkd, not the one from the built # source tree. # # (C) 2015 Canonical Ltd. # Author: Martin Pitt # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . import os import sys import time import unittest import tempfile import subprocess import shutil networkd_active = subprocess.call(['systemctl', 'is-active', '--quiet', 'systemd-networkd']) == 0 have_dnsmasq = shutil.which('dnsmasq') @unittest.skipIf(networkd_active, 'networkd is already active') class ClientTestBase: def setUp(self): self.iface = 'test_eth42' self.if_router = 'router_eth42' self.workdir_obj = tempfile.TemporaryDirectory() self.workdir = self.workdir_obj.name self.config = '/run/systemd/network/test_eth42.network' os.makedirs(os.path.dirname(self.config), exist_ok=True) # avoid "Failed to open /dev/tty" errors in containers os.environ['SYSTEMD_LOG_TARGET'] = 'journal' # determine path to systemd-networkd-wait-online for p in ['/usr/lib/systemd/systemd-networkd-wait-online', '/lib/systemd/systemd-networkd-wait-online']: if os.path.exists(p): self.networkd_wait_online = p break else: self.fail('systemd-networkd-wait-online not found') # get current journal cursor out = subprocess.check_output(['journalctl', '-b', '--quiet', '--no-pager', '-n0', '--show-cursor'], universal_newlines=True) self.assertTrue(out.startswith('-- cursor:')) self.journal_cursor = out.split()[-1] def tearDown(self): self.shutdown_iface() if os.path.exists(self.config): os.unlink(self.config) subprocess.call(['systemctl', 'stop', 'systemd-networkd']) def show_journal(self, unit): '''Show journal of given unit since start of the test''' print('---- %s ----' % unit) sys.stdout.flush() subprocess.call(['journalctl', '-b', '--no-pager', '--quiet', '--cursor', self.journal_cursor, '-u', unit]) def create_iface(self, ipv6=False): '''Create test interface with DHCP server behind it''' raise NotImplementedError('must be implemented by a subclass') def shutdown_iface(self): '''Remove test interface and stop DHCP server''' raise NotImplementedError('must be implemented by a subclass') def print_server_log(self): '''Print DHCP server log for debugging failures''' raise NotImplementedError('must be implemented by a subclass') def do_test(self, coldplug=True, ipv6=False, extra_opts='', online_timeout=10, dhcp_mode='yes'): with open(self.config, 'w') as f: f.write('''[Match] Name=%s [Network] DHCP=%s %s''' % (self.iface, dhcp_mode, extra_opts)) if coldplug: # create interface first, then start networkd self.create_iface(ipv6=ipv6) subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) else: # start networkd first, then create interface subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) self.create_iface(ipv6=ipv6) try: subprocess.check_call([self.networkd_wait_online, '--interface', self.iface, '--timeout=%i' % online_timeout]) if ipv6: # check iface state and IP 6 address; FIXME: we need to wait a bit # longer, as the iface is "configured" already with IPv4 *or* # IPv6, but we want to wait for both for timeout in range(10): out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.iface]) if b'state UP' in out and b'inet6 2600' in out and b'inet 192.168' in out: break time.sleep(1) else: self.fail('timed out waiting for IPv6 configuration') self.assertRegex(out, b'inet6 2600::.* scope global .*dynamic') self.assertRegex(out, b'inet6 fe80::.* scope link') else: # should have link-local address on IPv6 only out = subprocess.check_output(['ip', '-6', 'a', 'show', 'dev', self.iface]) self.assertRegex(out, b'inet6 fe80::.* scope link') self.assertNotIn(b'scope global', out) # should have IPv4 address out = subprocess.check_output(['ip', '-4', 'a', 'show', 'dev', self.iface]) self.assertIn(b'state UP', out) self.assertRegex(out, b'inet 192.168.5.\d+/.* scope global dynamic') # check networkctl state out = subprocess.check_output(['networkctl']) self.assertRegex(out, ('%s\s+ether\s+routable\s+unmanaged' % self.if_router).encode()) self.assertRegex(out, ('%s\s+ether\s+routable\s+configured' % self.iface).encode()) out = subprocess.check_output(['networkctl', 'status', self.iface]) self.assertRegex(out, b'Type:\s+ether') self.assertRegex(out, b'State:\s+routable.*configured') self.assertRegex(out, b'Address:\s+192.168.5.\d+') if ipv6: self.assertRegex(out, b'2600::') else: self.assertNotIn(b'2600::', out) self.assertRegex(out, b'fe80::') self.assertRegex(out, b'Gateway:\s+192.168.5.1') self.assertRegex(out, b'DNS:\s+192.168.5.1') except (AssertionError, subprocess.CalledProcessError): # show networkd status, journal, and DHCP server log on failure with open(self.config) as f: print('\n---- %s ----\n%s' % (self.config, f.read())) print('---- interface status ----') sys.stdout.flush() subprocess.call(['ip', 'a', 'show', 'dev', self.iface]) print('---- networkctl status %s ----' % self.iface) sys.stdout.flush() subprocess.call(['networkctl', 'status', self.iface]) self.show_journal('systemd-networkd.service') self.print_server_log() raise # verify resolv.conf if it gets dynamically managed if os.path.islink('/etc/resolv.conf'): for timeout in range(50): with open('/etc/resolv.conf') as f: contents = f.read() if 'nameserver 192.168.5.1\n' in contents: break # resolv.conf can have at most three nameservers; if we already # have three different ones, that's also okay if contents.count('nameserver ') >= 3: break time.sleep(0.1) else: self.fail('nameserver 192.168.5.1 not found in /etc/resolv.conf') if not coldplug: # check post-down.d hook self.shutdown_iface() def test_coldplug_dhcp_yes_ip4(self): # we have a 12s timeout on RA, so we need to wait longer self.do_test(coldplug=True, ipv6=False, online_timeout=15) def test_coldplug_dhcp_yes_ip4_no_ra(self): # with disabling RA explicitly things should be fast self.do_test(coldplug=True, ipv6=False, extra_opts='IPv6AcceptRouterAdvertisements=False') def test_coldplug_dhcp_ip4_only(self): # we have a 12s timeout on RA, so we need to wait longer self.do_test(coldplug=True, ipv6=False, dhcp_mode='ipv4', online_timeout=15) def test_coldplug_dhcp_ip4_only_no_ra(self): # with disabling RA explicitly things should be fast self.do_test(coldplug=True, ipv6=False, dhcp_mode='ipv4', extra_opts='IPv6AcceptRouterAdvertisements=False') def test_coldplug_dhcp_ip6(self): self.do_test(coldplug=True, ipv6=True) def test_hotplug_dhcp_ip4(self): # With IPv4 only we have a 12s timeout on RA, so we need to wait longer self.do_test(coldplug=False, ipv6=False, online_timeout=15) def test_hotplug_dhcp_ip6(self): self.do_test(coldplug=False, ipv6=True) @unittest.skipUnless(have_dnsmasq, 'dnsmasq not installed') class DnsmasqClientTest(ClientTestBase, unittest.TestCase): '''Test networkd client against dnsmasq''' def setUp(self): super().setUp() self.dnsmasq = None def create_iface(self, ipv6=False): '''Create test interface with DHCP server behind it''' # add veth pair subprocess.check_call(['ip', 'link', 'add', 'name', self.iface, 'type', 'veth', 'peer', 'name', self.if_router]) # give our router an IP subprocess.check_call(['ip', 'a', 'flush', 'dev', self.if_router]) subprocess.check_call(['ip', 'a', 'add', '192.168.5.1/24', 'dev', self.if_router]) if ipv6: subprocess.check_call(['ip', 'a', 'add', '2600::1/64', 'dev', self.if_router]) subprocess.check_call(['ip', 'link', 'set', self.if_router, 'up']) # add DHCP server self.dnsmasq_log = os.path.join(self.workdir, 'dnsmasq.log') lease_file = os.path.join(self.workdir, 'dnsmasq.leases') if ipv6: extra_opts = ['--enable-ra', '--dhcp-range=2600::10,2600::20'] else: extra_opts = [] self.dnsmasq = subprocess.Popen( ['dnsmasq', '--keep-in-foreground', '--log-queries', '--log-facility=' + self.dnsmasq_log, '--conf-file=/dev/null', '--dhcp-leasefile=' + lease_file, '--bind-interfaces', '--interface=' + self.if_router, '--except-interface=lo', '--dhcp-range=192.168.5.10,192.168.5.200'] + extra_opts) def shutdown_iface(self): '''Remove test interface and stop DHCP server''' if self.if_router: subprocess.check_call(['ip', 'link', 'del', 'dev', self.if_router]) self.if_router = None if self.dnsmasq: self.dnsmasq.kill() self.dnsmasq.wait() self.dnsmasq = None def print_server_log(self): '''Print DHCP server log for debugging failures''' with open(self.dnsmasq_log) as f: sys.stdout.write('\n\n---- dnsmasq log ----\n%s\n------\n\n' % f.read()) class NetworkdClientTest(ClientTestBase, unittest.TestCase): '''Test networkd client against networkd server''' def setUp(self): super().setUp() self.dnsmasq = None def create_iface(self, ipv6=False): '''Create test interface with DHCP server behind it''' # run "router-side" networkd in own mount namespace to shield it from # "client-side" configuration and networkd (fd, script) = tempfile.mkstemp(prefix='networkd-router.sh') self.addCleanup(os.remove, script) with os.fdopen(fd, 'w+') as f: f.write('''#!/bin/sh -eu mkdir -p /run/systemd/network mkdir -p /run/systemd/netif mount -t tmpfs none /run/systemd/network mount -t tmpfs none /run/systemd/netif [ ! -e /run/dbus ] || mount -t tmpfs none /run/dbus # create router/client veth pair cat << EOF > /run/systemd/network/test.netdev [NetDev] Name=%(ifr)s Kind=veth [Peer] Name=%(ifc)s EOF cat << EOF > /run/systemd/network/test.network [Match] Name=%(ifr)s [Network] Address=192.168.5.1/24 %(addr6)s DHCPServer=yes [DHCPServer] PoolOffset=10 PoolSize=50 DNS=192.168.5.1 EOF # run networkd as in systemd-networkd.service exec $(systemctl cat systemd-networkd.service | sed -n '/^ExecStart=/ { s/^.*=//; p}') ''' % {'ifr': self.if_router, 'ifc': self.iface, 'addr6': ipv6 and 'Address=2600::1/64' or ''}) os.fchmod(fd, 0o755) subprocess.check_call(['systemd-run', '--unit=networkd-test-router.service', '-p', 'InaccessibleDirectories=-/etc/systemd/network', '-p', 'InaccessibleDirectories=-/run/systemd/network', '-p', 'InaccessibleDirectories=-/run/systemd/netif', '--service-type=notify', script]) # wait until devices got created for timeout in range(50): out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.if_router]) if b'state UP' in out and b'scope global' in out: break time.sleep(0.1) def shutdown_iface(self): '''Remove test interface and stop DHCP server''' if self.if_router: subprocess.check_call(['systemctl', 'stop', 'networkd-test-router.service']) # ensure failed transient unit does not stay around subprocess.call(['systemctl', 'reset-failed', 'networkd-test-router.service']) subprocess.call(['ip', 'link', 'del', 'dev', self.if_router]) self.if_router = None def print_server_log(self): '''Print DHCP server log for debugging failures''' self.show_journal('networkd-test-router.service') @unittest.skip('networkd does not have DHCPv6 server support') def test_hotplug_dhcp_ip6(self): pass @unittest.skip('networkd does not have DHCPv6 server support') def test_coldplug_dhcp_ip6(self): pass if __name__ == '__main__': unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2)) systemd-229/test/parent-deep.slice000066400000000000000000000000771265713322000172710ustar00rootroot00000000000000[Unit] Description=Deeper Parent Slice [Slice] MemoryLimit=3G systemd-229/test/parent.slice000066400000000000000000000000731265713322000163520ustar00rootroot00000000000000[Unit] Description=Parent Slice [Slice] BlockIOWeight=200 systemd-229/test/rule-syntax-check.py000066400000000000000000000051151265713322000177620ustar00rootroot00000000000000# Simple udev rules syntax checker # # (C) 2010 Canonical Ltd. # Author: Martin Pitt # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . import re import sys import os from glob import glob if len(sys.argv) > 1: # explicit rule file list rules_files = sys.argv[1:] else: # take them from the build dir root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) rules_dir = os.path.join(os.environ.get('top_srcdir', root_dir), 'rules') if not os.path.isdir(rules_dir): sys.stderr.write('No rules files given, and %s does not exist, aborting' % rules_dir) sys.exit(2) rules_files = glob(os.path.join(rules_dir, '*.rules')) no_args_tests = re.compile('(ACTION|DEVPATH|KERNELS?|NAME|SYMLINK|SUBSYSTEMS?|DRIVERS?|TAG|RESULT|TEST)\s*(?:=|!)=\s*"([^"]*)"$') args_tests = re.compile('(ATTRS?|ENV|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*"([^"]*)"$') no_args_assign = re.compile('(NAME|SYMLINK|OWNER|GROUP|MODE|TAG|PROGRAM|RUN|LABEL|GOTO|OPTIONS|IMPORT)\s*(?:\+=|:=|=)\s*"([^"]*)"$') args_assign = re.compile('(ATTR|ENV|IMPORT|RUN){([a-zA-Z0-9/_.*%-]+)}\s*(=|\+=)\s*"([^"]*)"$') result = 0 buffer = '' for path in rules_files: lineno = 0 for line in open(path): lineno += 1 # handle line continuation if line.endswith('\\\n'): buffer += line[:-2] continue else: line = buffer + line buffer = '' # filter out comments and empty lines line = line.strip() if not line or line.startswith('#'): continue for clause in line.split(','): clause = clause.strip() if not (no_args_tests.match(clause) or args_tests.match(clause) or no_args_assign.match(clause) or args_assign.match(clause)): print('Invalid line %s:%i: %s' % (path, lineno, line)) print(' clause: %s' % clause) print('') result = 1 break sys.exit(result) systemd-229/test/sched_idle_bad.service000066400000000000000000000001461265713322000203140ustar00rootroot00000000000000[Unit] Description=Bad sched priority for Idle [Service] ExecStart=/bin/true CPUSchedulingPriority=1 systemd-229/test/sched_idle_ok.service000066400000000000000000000001411265713322000201720ustar00rootroot00000000000000[Unit] Description=Sched idle with prio 0 [Service] ExecStart=/bin/true CPUSchedulingPriority=0 systemd-229/test/sched_rr_bad.service000066400000000000000000000002251265713322000200200ustar00rootroot00000000000000[Unit] Description=Bad sched priority for RR [Service] ExecStart=/bin/true CPUSchedulingPolicy=rr CPUSchedulingPriority=0 CPUSchedulingPriority=100 systemd-229/test/sched_rr_change.service000066400000000000000000000002361265713322000205210ustar00rootroot00000000000000[Unit] Description=Change prio [Service] ExecStart=/bin/true CPUSchedulingPolicy=rr CPUSchedulingPriority=1 CPUSchedulingPriority=2 CPUSchedulingPriority=99 systemd-229/test/sched_rr_ok.service000066400000000000000000000001351265713322000177030ustar00rootroot00000000000000[Unit] Description=Default prio for RR [Service] ExecStart=/bin/true CPUSchedulingPolicy=rr systemd-229/test/shutdown.target000077700000000000000000000000001265713322000235562../units/shutdown.targetustar00rootroot00000000000000systemd-229/test/sleep.service000066400000000000000000000001261265713322000165310ustar00rootroot00000000000000[Unit] Description=Sleep for 1 minute [Service] Type=oneshot ExecStart=/bin/sleep 60 systemd-229/test/sockets.target000077700000000000000000000000001265713322000231562../units/sockets.targetustar00rootroot00000000000000systemd-229/test/son.service000066400000000000000000000001541265713322000162210ustar00rootroot00000000000000[Unit] Description=Son Service [Service] Slice=parent.slice Type=oneshot ExecStart=/bin/true CPUShares=100 systemd-229/test/splash.bmp000066400000000000000000010647261265713322000160520ustar00rootroot00000000000000BMi|' Li BGRs     "$%%#   #(,03431-'!  %+16;?BCC@;5-$  %,39@FKORSROJB90&  $+3:AHOTY]`a`]c{ N1%  ")19AIPW\afil e0$  &.7?HPW]chl}s-"  !)2<EMU]chmd*  #,6@IRZahmb&  %/9CMV^ektU" &1;FPYbhn 6   &1=HR\dks $  %0<HT]fm!!!`    ".:GS^gn $$$'    )6DQ\fn ###|  !#$%&'''''&%$#!  "/=KXdm!!!(((/ #'*-/1346677665431/-+(%! %3BQ^i&&&!!!###  #(-169<?ACDFFGGFFEDCA?=:730,'#  (6FUb$$$,,,8  %+17<AEILOQSTUVVVVUUTRQOMJGC?;61,'"  (7GVu((($$$###  $+39@FKPTX[]_abccddcccba_]\YVROJF@;60+&!  '6FU***,,,,  !)19AHOUZ^begi8xmj)YUPJE@:4.)# %4CR$$$###&&&"""  $-6?HOV]bfjqz¯l;TOIC=71+%   "0?N"""++++++$  &0:CMU\chlQæe-RLF@:4-'"  +:I!!!***'''"""p '2<GQYagmNØ[OIC<6/)#  &4Cx %%%(((""")))  (3>IS\dkxw^QKE>71+$   -<K***,,,((( S  (3?JU^fm_ ߔXMF@92,%  '5C***###'''!!!''' (3?KU_hn~  f?NHA:3-&    -;^"""((()))!!!''' '  (4?KV`ho  ۃPIB;4-'   &3A'''### )))!!!%%%w  )4?KV`ho ,9HR`o{|}~|{{zzx~w}u{tzsyqvpunstyx}{x}rw[bDM%/ߊRJC<5.'!  +8i ,,,%%%%%%%%%  )4?KV`ip-/\_|~~}ik{SSV???&&&!!!///@@@XYfnppsmp_b7<Z%JC<5.'   #/<,,,'''!!!###&  )4?KV`ip VW]]m555(((HHKefhj]_14b>A::?cd_a&(`8IA90(!  !-9(((!!!###!!!  (3?KV`iz!!!䊊mm667cez~{yayBc#L62233333333333333322110/.-+)'%" 6@\adfXXf^_klm9;dJG>6.&  #/E))) !!!  (3?KV`ix򜜻###LLR[i!;$'+-/1223333333344333333333322210/.,*(&#!'TXeghitgh@B]?D;3+#  &1e """&&&!!!(  '2>JV`iw%%%!!!stHR#(+.012333333344445555544443333322110.-+)'$".7beoofg/2JA80(   (4$$$###=  &2>JU`iu웛(((kk($(,/023444445666666666666665555555543320/-,*(%#$[^uu`brkF>5-% )5$$$!!!D  %1=IU_hr 阘++,GGR%* $)-02445566688888999:::::::::998877766544310/-+)&# #bdxyNPY1C;2*"   +:"""K  %0<HT^hq 蕕../ yyNQ %*-134578999 ; ; < < = = > > > > > > > > > > > > > > > = = ; : :9998655320.+)&# 4 = < ; :976421.+)'$! ad~RTtrE<3*"  "-V W  ".:FR]fnٍ77:YYkhi  %).1469 : =>@ADFGHIJKL M M!N!N"O"O"O"O"O"O"O!N!N M MMLKJIHEECA@> = :87521.,)'$!?F{|prQA8.%  "-gT  !,8EQ\fńDDKllFH  %).1369 ;>ACFIJM!N$Q&R(T)U+V,W-X.Y/Y/Y0Z0Z0Z0Z0Z/Y/Y/Y.Y.Y-X+V*U)U'S%Q$Q!NMIHECA> < 98521.,)'$ (rttu38E;2(   ",zD  *7CO[emuuSS_xx9:  %)-0359 : =ADHK M$Q(T*U.Y0Z3]5^7`8a:b;ce>e>e>e>e=e=eBFJ!N%Q)U.Y2\5^8a;c>e@gCiEkFlHmInJoKpKpKpLqKpKpKpJoJoInHmGmEkDjBi@g=e:b7`3]0Z+V'R"NJFC? <86320-+)&#MWcdsfh B8-#   )|&  '3?LXbkTThrryy12 $)-/13579 <?CGK"O'S,W1[5^9a=e@gDjGmJoMqNrQtSvTwUxVxWyWyWyWyWyWyWyVxUxTwSvQtOsNrKpHmEkAh>e9a4]/Y)T$PJFA> ;7531/-+(%"9Ebcvgi!)[Q9/%  &o  %1=JVaj@@Kss9: $)-/124579 ;?BFJ!N&R+V/Y4]8a=eAhEkInLqOsRuUxWyY{[|\}]~_``aaa``_^]~[|Z|WyUxRuOsKpGmBiADGK!N&R+V/Y3]8a@CFIM#P'S+V0Z4]8aeBiFlJoNrRuVxY{\}`begijklmmmmlkjifc`[|UxNrGm>e5^,W$QIC> :754210/-*'$/jn@@G`f PI0%  @  (4ANYdlCCQ #(,/1233333456678: ; < >@BDFIL!M%Q)T-W1Z5]:a>eBhGlKoOrSuWy[|^~adfijlmnnnnnmkjgc^Y{RuJoAh8a.Y%QJD> :7542210.,)&2ko9:@ci Zc/#  F'  %1>KWbkee{^^r}} "'+.02333334455566789: ; = =?ABEGJ M$P(S,V1Z5]9a>eBhGlKoOrTvXy\}_behjlmnooonnliea\}TwLqCi9a0Z&RKE> :7543221/-*'8im446fl bx-"  G  #.;HU`iDDOxxUUfHJ !&+.02233334468444556667799 : <>@@CEIJ#M'Q,U0X4[9_>cBgGkLoQsUwYz]}adgjkmnooonmkgc]~VxNrEk;c0Z&RKE> :75432210.,)#?dh224el Ve+  + .    ,8ER^hy 􍍨))+uu !&*.0223333446?:444443445556778 9 9 <<>?BDG#K'N+Q0U5Z:_?cDhIlNqSuWx[|_cfikmnooonlid_WyOsEk;c1[&RKE? :75433221/-*2MUYi446fn GK(  W )5BO[fo摑    %*-0123333446AE74444333333434322233 3 467:<@C#G'K,P1U6Z;_@cFiKnPrUvZz^~bfikmnoonlie_XzOsEk;c0Z&RJD?975433221/.+H^EGQ56:dl CE$   5 1  &2?LXclɃ77?ddz01 $)-0123333345A!N@54433333332210..-,,**)* + ,.148<@$F)K.Q3V8[>aDfIkOqTvYz^~bfiknnonlje`XzOsEk:b/Y%QJC >:654333210.,[k66:<=CXc 3(   &bq  #/<IVaj^^rYYm//2lm $),/123333344?)UK7443333332210.,*(&$#!!   " # '(-16;!A%E+L0R6Y<^BeHjNpTvYz^~cgjlnnnmje`XzOsEk9a.Y$QIB >:653333221//mx&&&GIVGW +  $-p  ,9FS^h115yy  #(,/123333344 ;-X.Y <44333332210.,*(%"   "'+17<#B)J.P5W;^BdHjNpUv[{`dhkmnnlje_WyNrCi8a-X"OHB =96433332210;ou SVi4G ͞   #+ )5BP\fp YYl=? "'+/1233333449'S?fF4333333220/-+(%"     "&-29"@(H.O5V<^BdJlPrWx\|afilmmlie^VxMqBi6_+V MF@ ;864333332108WUXf ej0 W  "/,  %2?LYdlׂ&&*$$$vw !&+.0233333447!NFl+V7333333210.,)&"     $)08!?(G.O6W=^EgLnStYz_~dhjllkid]~UxKp@g4])ULE? ;86433333220_r:;<"""pw$ !  "*  ".;IUajIIb]]n}~  %*-0123333446IHm@g >33333221/-+'#      !'07"?)H0P8Y@bGiOpVv\|afikljhc\}SvIn>e2\&RJC >:76433333222y""",,,lv { #+K D +8ER^hq==DSV $)-/123333345DBiQtK43333221/-*&" v`UU_r   !'08$A+J3S;\CdKlStYz_~dhjkjfaZ|QtFl;c/Y$QIB =96543333322"Ifj} ABHL]    %-v&(4AN[enSSHHS #(,/122333333@ gk6 q  (0q'!!(2>KWclXSSa8< !'+.012333333 :3\_Hm>3333220.,($ ~UUUUUUUUUUUUUUUUUd    $,5#?+I3R<]DeLmTu[{`eghgd^~VxLq@g5^)ULE?:76444333325z %%%x    #,F9+((,3<HT_iz]]227z{ %*-0122233338)T[|\} M4333220.+(# UUUUUUUUUUUUUUUUUUUUUZ   &0 :'D/N8XAbIjQrXx^~cfgeb\}SvIn=e1[%QIB =965444333327ZTWb <=AXh 'U)2w6447>GR]goyyhi" $),/122222335 MSuf7_8333220.+'# dUUUUUUUUUUUUUUUUUUUUUUUUX   !+4$?,J5T=^FgNoVv\|aded`YzPtEk:b.Y"OGA ;86544433332y$$$ ot. u %/8h ?@CIR[emvll###$$%hk "'+.012222224EJnjMqA333220.+'" XUUUUUUUUUUUUUUUUUUUUUUUUUUU]  &0!;)F2Q:ZCcLmSsZz_~bcb]}VxMqBi6_*UME?:7644433333Glp '''s} ̵ !+5W MKOT[dk}%llwx  &*-/11222222?@fi`#O533220.+'# UUUUUUUUU\-$A%@"3 ZUUUUUUUUUUUUUc  "+6&A.L7V@aIjQrXx]}aa_[|SuJo>e2\&RJB >96544433332t((( UXe6K   '2<k^dkquu88>OT $),/01122222 ;5]dj:a933220.,(# zUUUUUUUUU'/3R3[3X3T3P3L3F1;##XUUUUUUUUUUUUy  (2#>,I5U>_GhNoVv[{^~_]}WyOsEk:b.Y#PGA ;8654443333Enr z #  "-8Dllqdd{z| #'+.011112227,U]}oOrC33221/,(# tUUUUUUUUV.4 7:!B/J3I3E393333// tUUUUUUUUUUUX  %/!;)F2Q;\DfLnSuYz\}\}Z{TvLqAh6_*UME?:7644443332u))) OPY?Q >  (3?r3vv@@ICH!&*-/01111124!MVwoa%P43221/,(# oUUUUUUUUX",11,'" #(--333335393:)/[UUUUUUUUUUh  ",8&C/O8ZAcJlQsWyZ{Z{WyPsHm=e1[&RIB =9654443333Ijn} W  ".;v aavz| $),.00111112CKnnm=c82221/,)$ pUUUUUUUU] $*/2.)$)+383;2=1@0B+7]UUUUUUUUUV  !*6$B-M6X?bHkOrTvWyWySuLqCi8a-X!NF@ ;8654443331 UW_e3](TKD >:754443332PlHHL ### p  '5Y ##\\qy|!&*-./00011170Xbsf,U5211/-)% {UUUUUUUUl#',11,'" (-A.E-G,K+M*N3kUUUUUUUUUh  (3 ?)K2V;`CgJmNqQtOrJoCi:b.Y$QHB <8654443323 vx" s  '5CQd uvIIR8@$(,.//000114$NYyqoEi <211/-*%  UUUUUUUUp!&+/2-)$ !$?,J+L*O)Q(R$E UUUUUUUUUb '4@&J/U8]@eGlKoMqKoFl>e4])UMF?:764443320}### 555hp b (7ETa #RRax{"'+-./000002EOqos\{H211/-*&! UUUUUUUUp$).3/*%! &A*N)P(S'O'K&DUUUUUUUUUj  (4?%K-T6]>dDiHmImFlAh9a/Y%QIB =965443320?^UV\ P ,;JXdnLMX4> %),.///0000=Bfksj5\510/-*&! UUUUUUUUr#',11,'"  "&*@)S(P'L&H%D$=YUUUUUUUUs )5@#J+S4\;bAgDiEkAhe@f@gUUUUUUUt $, 4;BH M&Q*U,W,W)U#PKF@ ;7542/,& qq#%2"/=LYdnij 338 "4 t*,-.....1#LZxrspHj 9/.,)%  UUUUUUUV#(,10,'"  $(,02.*&" 158:<??UUUUUUU !(0 6<BFK#P&R'S%Q"OJFA =8541/+%WWYCD  )7ES`jW ii qt (,-..../?Mnoss_|H0.,*&! UUUUUUUU!&+02-($ #'+/3/+'# ,78;>@C4UUUUUUU $-2 8 <AEIM M MMIFB <9641.)#NNNMM $1?M[fpdd ''*S]a>----e$o6Tjssl9]4.,*&" VUUUUUUU $).3/*%  "&*.20,($  7:<?BDBgUUUUUUn !)/48 <?DFIIIGDA <9640-(!GGGVWN +9GUakx mm kn!& #-333../06QkrRr>.-*'# _UUUUUUUk #(-10+'"  !%)-11-)%!-;>ACD@UUUUUUV  '-269 ;?BDEFDB? ;964/+&@@@ab` %2AO\gu]^!!! ]f % "N 222333333333'(+Ma)P0-+($ lUUUUUUU_!&+02-(#  $(,02.*&" &<?BEA=UUUUUUU &+0468 ; >?ABA? = :853.*$IIIee  ,:IVclpp dg ##')D,,,333666555333333**, 1-+)%  UUUUUUUV %).3/*%  #'+/3/+'# #&7ACB>:UUUUUUU%+/2558: ; = > > = :9742-("~^^dee &4BP]h3KM//1 go!%(*(%%%444;;;DDD===666333333g+)&! UUUUUUUU#(-10+'" "&*.20,($ !%)/BD?;7UUUUUUU$*/145678::::97640,& tt7 !-<JXdmst QRc"6#')++S$$$::::::QQQKKKEEE888333/// ,)&" WUUUUUUU !&+02-(# !%)-11-)%! $'+/AA=94aUUUUUUU $*/13356678876642/*$ bbb '5CQ^iI13FFP nt!%(*+)======SSS]]]TTTFFF444333&# fUUUUUUUi  %).3/*%   $(,02.*&" "&*.1 9>:5 ,VUUUUUUU $*/13345566655531-(" ڞ !.<KYdnqs ++/IW#')*+e888CCCJJJmmmfff]]];;;333  zUUUUUUUZ#(-20+&" #'+/3/+'#!%),031;73UUUUUUUU $*/1335555554442/,& wwCCE (6DR_j[ #VWf lp!%(*+&///IIIFFFnnnwwwnnnPPP999111 UUUUUUUU"&+02-(# "&*.20,($  $'+/30-74/UUUUUUU]%+/1446665433321.*$BHNNR!/=LYenkm dn#')*+g IIILLLkkkiii???<<< WUUUUUUU  %*.3.*%  !%)-11-)%! "&*.12.* 01+`UUUUUUUv %+/1558876533320-(" y|!!!؛ (6ES_jqef WZm3!%()**;;;HHHWWWMMMBBB000 dUUUUUUUl #(-20+&"  $(,02.*&"!%),03/+(*- "UUUUUUUU  &,0357::9753332/,&  GGJ{"/=LYeq^` mu#&(**'''AAAGGGuuuaaaHHH===5 {UUUUUUUZ"&+02-(#  #'+/3/+'# $'+/20-)%%*UUUUUUUU !(-0479 < ;:853321.*$vw (6ES`j no :;C;O!%')**i :::???```vvvpppLLLIII!!! ~ UUUUUUUU  %*/3.*%  "&*.20,($  "&*-12.*'#! &aUUUUUUUU #).259 < > > ;853320-(" RV???֚!/=LZer EG113 ot!#&()** 8---888LLLdddnnnpppJJJHHH...   YUUUUUUU~ #(-20+&! !%)-11-)%!!%(,03/,($ UUUUUUUUc$*.37 <?A@ =95331/+& {}NNRm (6ES`j}pr dp!%'))**"333;;;QQQ\\\dddJJJBBB999 x lUUUUUUU]"'+01-(#   $(,02.*&" #'+/20-)%" mUUUUUUUU &+04 :>ACB >85321.*$  jjj !.=LYeqWWi NP_$>#&())**333333>>>IIIRRRIII<<<<<<  TTTTTUUU  %*/3.)%  #'+/3/+'# "&*-12.*'#VUUUUUUUU  ',27 <AFFB >85320-(! 05ZZeϛ '5DS`j|eg mt!$'())**%&+333333999AAACCC666999 UTTTTTTT{ #(-20+&! "&*.20,($ !%(,03/,($ gUUUUUUUUW "(-28?EIGC =7421/+& vx###OOS` !.<KYeq jk Yh#%'()))*6333333333999555333!!!@_TTTTTTT^"'+01-(#  !%)-11-)%! #'+.21-)%"UUUUUUUUUu $*/5 ;BHKIC <7420.)# 񋋣 MMM '5CR_jyFJ003 X[n4$&(()))) 333333333333+++ |rSSSSSTTT  %*/3.)%   $(,02.*&""&)-12.*'#_UUUUUUUUU %+17>EK MJC ;632/,'! ).``l!!!Ÿ  -<JXdpoq jr"%'(())))5730.)$|} +9HVcmBG004**,CW$&'((((((8XqsssOj .#  s,RRRR"',01,(# #'+/3/+'##'+.21-)&" UUUUUUUUUUm !(.5=H%Q-W,W$PE =72/,'! ~Ӟ#1@O\hHlp ]ay .%&''((((-Xrsssl)I$  ! @RRv  %*/3.)$ "&*.20,($ "&)-12.+'# VUUUUUUUUUU$*07@L*U0Z,W"ND ;51.*% SVAACXX^W )7FUbl ab{gp$%&'''(((>lsssTn /" lCMR$(-20+&! !%)-11-)%! !$(,/30,(%!rUUUUUUUUUUV &+2 :E%Q/Y2\,W MB :40-(" 쓓$$$ !/>M[f8OT$$%Te$&'''''((:Yrsso/N$ QQ-0"',11,'#  $(,02.*&"#'*.21-*&" UUUUUUUUUUUr !'-5>I*U3\3]+UK@83/+& pp222 '5DS`klo SVh6%&''''''.Ztsss_w2! \PPK !%*/3.)$#'+/3/+'#"%)-12/+'# dUUUUUUUUUUU#)0 8B"N/Y7_4]*UI>61-)#st(((  -<KYeuZ\qgn$%&&'''''>lssq=Y% PPPP :4$)-2/+&! "&*.20,($   $(,/30,(%!TTTTUUUUUUUZ %,3 <G(S4]9a4]'RF =4/,'   Ϛ %3BQ^jRW bo$%&&''''';Yrssf}9! VPPPPO&k"',11,'# !%)-11-)%!#'*.21-*&" YTTTTTTTTUUU !(.6@L.X9a;c3\%QD 93.*$ XZ>>?ccmC +9IWco hl3477O%&&&&'''+[tsssJd& OOOOPPF %*/3.)$  $(,02.*&""%)-02/+'# TTTTTTTTTTTT$)0 9D%Q4]=d;b1Z!MA82,'! 䕕#1@O\hbZ[rae+%&&&&&'':mssl%D  TOOOOOOO7A).2/+&!#'+/3/+'#  $(+/30,(%!USSSTTTTTTTTa &,3<I,V9a@g;b.XJ>6/*% /3]]iBBE| (7FTal MS eo$%%&&&&&'2QrssVo + OOOOOOOO- $11,'" "&*.20,($ #&*.21-*&"vSSSSSSSSTTTT "(/6@"N2[>eAg9a*UH <3-("  UUU  .=LZf> eiZi$%%&&&&&(Pjssq3O! QNNNOOOO[ $/.)$ !%)-11-)%!!%)-02/+'$ SSSSSSSSSSSST $*1 :E(S8`BhAg7_&QD 81+& qr/// &4CR_jbe$$$ 9;A.I$%%%&&&& 1g~ssdz2 NNNNNNNNQ S*&! $(,02.*&"  $(+/30,)%!fRRRSSSSSSSSSy  '-4=K/Y>eEjAg4]"N@6/)#tv))){{ +:IWds 5?448///_d(%%%%%&&&%EqssG`# TNNNNNNNW !# ""#'+/3/+'# #&*.11.*&"RRRRRRRRSSSSS #)/ 7B%Q6^CiGl?e0YJ=3,&  yz ś #1@O]hr bh ,,,bk$$%%%%%&&C_ssm#@ MMNNNNNN!& #* "&*.20,($ !%)-03/+'$ ZRRRRRRRRRRRRo %,3 <G,VM[gm cg444bl#$$$$$$%+dzsn'C LLLLLLLL#',11,'"!%)-11-)%! "&*.12.*&#YPPPPPPPQQQQQQ &,3 <H-W?eMqPsHm7^%O>3)!  ⓓ  %).26:=@CFHKMOPRSUVVVVVUTROKE?7/% %4CR`k (MO^$$$,,, \j##$$$$$$:os\r * TLLLLLLLL!&+/2-)$B< $(,02.*&"!%),03/+($  PPPPPPPPPPPPQ^ "(/6@"N5]FkQtPsEj3[I:/% ad445OOYa !'-38=BFJMPSUXZ\]_`bbcddddca`]YTMD:/%  *9HWd6 BN"""///$$$))) 222333333""")QTsTvGk4Z G6) z|YYgO '09BKT\cin """&&&'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''&&&   /?N]n  ^f666)))K\"""####'bxm< IIIJJJJJO#.3/*% } !% $"! #'+.21-)%"VMNNNNNNNNNNNNN +++333333333333,,,"CINTZ_ejo&&&''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +;KZq JW444555^f!!!!"""=cx0 HHHHHHHH /*%  #'+/3/+'#a#'+.21-)&"QKLLLLLLLLLLLLLP GGGJJJ___~~~wwweee===999  ?4 % y{CCKww=;:98877776778:<>@@@?<:75433469=AFKPV[afky$$$''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' -=M[F [e 555000]f!!!!!""7RIa$ GGGGHHHH+&""&*.20,($ '> #&),-*'$!^GHHHHHILLLLLLLL o666JJJZZZ~~~KKK@@@ 0= + MQAAHꋋ?=<;:999888889:<>@BBBnO 755568;?CHNSY| ###'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  .>N\c ]e555---]g!!!!!!#Me%A  |GGGGGGGG(#!%)-11-)%! $%%%%1***DDDHHHzzzcccFFF999>"[db``DDPAAK&&.}xxxpllnhd e e e 73234<EIMQa''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''   /?O]v \c555)))\g !!!!!&Qh +  kGGGGGGGG%   $(,02.*&" A ===AAAaaazzzLLLGGG '''''''''''''''''''''''''''''''''''''''''''''(((((()))))))))***))))))))))))))))))((()))(((((('''''''''''''''''''''''''''''''''''''''''''''   !0@P^ \b555%%%\h !!!!2>>''''''''''''''''''''''''''''''''''''''''''''''''******************************************************************************************************###''''''''''''''''''''''''''''''''''''''''''(((((('''(((((())))))))))))((((((((((((''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' "1AQ_ [`~###555N] !!&B(  FFFFFFFF_ !%)-11-)%! /+ f"h$i$i"i!hhgffdbJ-...............B\\\]^_ab333444FFFSSS\\\TTT???>>>%_#qom uGHm!!"QRdspppppppppqqrssssQPPPPQRVdf}''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''!!!# "1AQ_ Z^w'''555IY !9"  EFFFFFFFh  $(,02.*&"   $02/+'# KIIIIIIJJJJJJJJJX  @...333555AAAIIINNN;;;<<<*3 #8>WXexx2aa e7 9%%%''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''   "1AQ_ UXl+++555IY ,  EEEEEFFFe#'+/3/+'#o'20,(%!WIIIIIIIIIIIJJJJJ !...333333;;;AAA777555!!! ^9 ) {|GGQvv $e '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  "1AQ_ SVi---555IX #  EEEEEEEE^o"&*.20,($ 8 '-*&" cHIIIIIIIIIIIIIIIw $*.333333444666333+++#`=. qt$$$ 9 I&&&'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  "1@P_ SVi///444IX  EEEEEEEESvz !%)-11-)%   "#9,+'$ |HHHHHHHIIIIIIIIIU ")/ 2*...333333222  2!C2 #;ARR^uuDVV #L &&&''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  !0@P^ SVi///444IX  DDDEEEEEAr $(,02.*&"   $( #% &{0,)%!HHHHHHHHHHHHIIIIJ &, 4?#J1v%((("K/M%G6 ' vw??Gkk  0###''''''''''''''''''''''''((((((((((((((('''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''&&&  !/?O^ RUh111444 M[  DDDDDDDED{'+/3/+'##&*.21.*&" JGHHHHHHHHHHHHHHHx #*2<G0V@cMn@Y8M>[:\)K:+ wy 9 $%%%'''''''''''''''((())))))***+++,,,+++,,,+++***))))))(((''''''''''''''''''''''''''''''''''''''''''''''''''''''$$$  />N] RUh222444"""Vb  DDDDDDDDD u&.20,($  !%)-03/+'$ RGGGGGGHHHHHHHHHHX !'.8C*P<`JkSsSsKk<^,O>/"UZ<`HhJjEf:\+N?1%su|}# <}# $3BRg W_333333X]v !% )*+* ' # BBBBBBBBBBBC ^ v}  $'+/20-)%!LEEEFFGHIIIHGFGFFFF[ &.7B+P:]EfIiEf;]-PA3 'wykknHH "Qtx3 !0@OM MX 333333 RUi# " % )+--* % FBBBBBBBBBBBBV j "&*-12.*& ZEDDEEFGIIIIIHFFEEEEL #*4@'L6YAcGgEf<^.Q C5 )mp))+>>Gee+ )LaiqzQ .=Me 8G 333333CER/ " %)-/0-( ! _AAABBBBBBBBBBN n $).1.+ \EDDDEEFGHIIJIHGFFEEEH !( 0<$I2U>_EfDd<^/R!E7 + V[>>Fvv b  +:JY "456;333333459%< " &*.231+ $ AAAAAAABBBBBBBF u wt "&+%rPCCDDEEEGHIJJJIHGEFEEEE & /9 E.R;]BcCc<^0S"F9 ,!>EPQ]xx1// (7GV  "IK\+++333 8J" &+0353.(  GAAABBBBAAAABBBBPmu dLCCCCCCDDEGHJ K K KJHGFEDDDDu $,6A*N7Z?`Ab<^1T#F: .#+lmaat{WW%4CS WZu"""333 MZ %+05772,# pAABBBBBBBAAAAAABBBOf i ie \QGBBBBCCCCDDDEFGI J K K J KIHFEEDDDe "*3?&J3U<^?`;\1T$G: .$"yzGGSaa+ "0@Os W\333!!!Xb $*06!9!96/'  @@AABCCCBBBAAAAAAAABBBBBBBBBBBBBCCDEFGI J K L L L JIGEDEDDD^  ' 0;#G/R9Z<]9Z0R$G;0& {}&&)qr M ,<LP W_333&&&W_ $)07#;$<"94," i@AABCDDCCBBBBAAAAAAAAAABBBBCCCCDEFGH I LMMM M KIGFDDCCCY % .9 D,O6X:[7Y/Q$G;0&y{||!'' )8HZ  EP333+++V\ $(/6$<'>&=!81&  DAABDDEEDDCBBBBBBAAAAAABBBBCDEFFH I KLMNONL K JGFDDCCCY # ,5@)L3U7Y6X/Q$G;1'rv%%&vvODD%4CS %6238+++///V[x# (/6%<)@)?%<4,! z@ABDDF G G GEDDCBBBBBBBBBBCDEEF H H KLNOOPPOM K IFECCCCC\ #*3>%H/Q4U4U.P$G;2' kp++/^^q[[+ !/?N QTh 333MPd $ " '-5%<*@,B)?#91' U@ABD G G I I I H GFEDDDDDEEEEF H H J KLNOPQQRRPN L IFECCBBB_  ' 0:"F,O2T2T-P#F;2( ej//4 DDPbc+ +:Ia VZ~333016&<" &-4%<+A.C,A'< 6,"  F@ACE G IJKKKJ J I H H H G H H I JJMNOQRSTTTSQPN K HFECCBBBl  & .8A(K.P/Q+M"F;2)!_d78@ )),vw ] &5D[ W^ 333BQ! %,3$;,A0E0E,A%;1(  BABD F HJLMMMNNMMMMMNOPQRSTUWWWVTRPM K HEDBBABB| % ,5?%H+M-O)K!D;2)!V]>?I 55 "0?N ;H///U_ $*3#:+@1F2F0E*?!7-#  @ABD GJLMOPQQQRSSSTUVVW X!!Y!!Y XWVSRPM JGECBBAAH #*3 C#F"E@81)"ek55< hh~zOO !.=L T[ %%%FIZ)! &-6(>0E6J8K6J0E(= 6,"  s?@AC E GILNQSTUVVVVVUSRPMJ I GECBAA@@Y !& -4:@ CB?7 /(!ns..2 $$$ZZnXX+ )7Fw 0='')(((%&(/B %+3&lm+ +9H X]SZ#(0"8+@4H9L?@ABCDD E E EDCCBA@A@@??U  #', 169:83 -&!#4kn///%%%116rr@$2A] :E OSm" '-6)>2F8K???@AAAA@@@@???>Kq   #'* /35641 +%!4B\_t 777--4pq j +:H ORh +,1)= %,3&<0D7JP=P9L4H,A$:2)!  vT?>>>>>???>I^z   "%(, / 122 .*%ITHJ[ 999++1op b %2As V\PZ #)2$:-B5H;M>P>PP@Q?Q@N- %,4'=0D8K=O@Q@Q>P;N6J0E*?"72*#              !"##$%$%%')()'%!JVRTg !!!999222$$(op )7M BK JV #)1$:-B6IP;N6J1F*?$:3-'!         !$%& & &&&%&%%%&&&%# $gn129 ***:::--- &&+pqy"/=s X[sSX~"'. 6*?3G:M>PARAR@Q>P;N7K2F,A&< 6/*&                 "$''**++ * )('&%%%%$$#!9Jhl333:::''' ..5nnq '4C OU79D2 %+2&;0D7JPQ;N8K4H1F-B*?'<%9#7!3 20..,+++*+ ,!-".#0$1&3'5(6(7(8(9(:&9%:"8 86420- +('&&%$#"!4ho127666999000 ZZmRR f &3U6 ]`|EP #)1#8,@4G:L?QARBSCTBSBS@R?Q=P:M8K5I3G0D.B-A+?*=);(9(:(9(8(8(7(7)8*9+:,;-<-<.>.>.?.@-?+?)>'=$< 9731/ + +)&%%$#"! )XdORc &&&999999&&& hhAC+ *6w 0945>QUp! &-4'<0C7I#<964/. +)(&$$##"#IY^b{555999555oou44+ !,9 ]`DP ")0"7+?3F9K>P@QBSCTCTCTCUBTASAS@R?Q>P=P!;841/ + )(&%%$#"!3Ifl#$' &&&999999...33PARBSCTCTCTCUCUBTBTBTAS@R@S@R?R?R>Q>P>Q>P=P=P34>SZ !'.5(=/B6H;M>P@QBSBSCTCTCUCUCUCUCUBTBTBTASASAT@S@S?R>Q=PP@QARBSBSBSCUCUCUBTBTBTBTASAS@S@S?R>QP?Q@Q@QARASASAS@R@R@R?Q>Q=PQ=P=P";742/- + (&$#"#" !?Qfk%&)***777777777444 NO`QRY+ %6 `b TZ $)/4%:*>.B1D4G6I6I7J8K8K7J7K6J5I3G2F0E.D+A(?%<":7630.* ) '&$#!"!  :Mfk,-1+++777777777666""" 44=ab3 $4 [^PW "(-2 5%:(=+?-B.B/C/C/C/C.C-B,A*@(>&<$;!97520-, * '&$"!!  "EUbg./2---666666666777***--4cd12m "3 SV#$)$QW %),13!7#8$9%;&<&<%;$:#:"9 86430/-+ ) ' %$""!  %N[^c~ # !!!333666666666666'''))/de;=W+ ) AEDEUZ^!  !%'+-/02222210.-,*( ' % $##!  7YcW[u'''555555666666444### ==Gde@Bp #s#]_**.OQk;C !$&''()))((( & % ##! !AO]c>@N---555555555555,,,OO_`a)+7+ Kc<@Z\v=>D\_ +  ! ! ! ! /@XaUXs 222555555555***44;^_}TUN$ % EIZ\ycdoY\3;6DV]UXu*+1)))555555444'''%%)VWrY[*-a 9 Gl 27VXno{fgTX,6 )8PXUZOQk!!% 000444111$$$=>MWY{VX69 d M U~DGVX{|}~Z\RVDJ6>(3&$!-*51{qf;U $ G4FYk|pg]C$       systemd-229/test/sys.tar.xz000066400000000000000000007764041265713322000160500ustar00rootroot000000000000007zXZִF!t/i] ƇZ;%f^;g ^欕csiє[ӸP|haOeq9M@{WgڔJs}%ԯ8cك)*z i~01UT`*[[þ~$ʁ %}.6CRcؽ(DW uRdV @e -ruqfxL7GuyV<^M"و`ދ]iٮQ!9/b%lb*`s\Z|W \WeU|f8,{.Mpv1IޓRBx?2Vhw>=)~7;&D:5*9r"׫$,Tc_rI^wtN fM@Al}4sy|o"V9wun¼82Qjhτ϶Wdz̉AdTokn$Bwؠ,/@qpttzT3c6X#Gao0Zni{C]_b5Im8&a6R6Rq8ZX ^o?(~QiϤ#R٫goTul23R4+_w;L:>ġPiNnńUtV{#Rg8ViKJ?( fd HU&0YPrY-G dpY x}*b JvKd[DJZG\y ]z<HZhEzU fVFtQɘ!!NiT3)fr|@MnpG wSǏ+P>RzYqlYLMoMVG`il4V^ST9>$>d7Ć]oC;JKԱsҿ먃`h\EK98 :xƍ0T;]|S2 >Aphrz'B//S2r01}W D9/!̟Q62@HV>13)t/LD|Sq\/bx#*zcu6Jmnpiڹ"5x6af xe85<<(<|Oی' &K>/eJ)탄rf."tV-`ӟh##f-: !]}do CO:/P&nTQo͢Yءhyeh^TF|mPK)XR (v=Q#=X81L8k3t;;{q!B>wZ_v1U#`9`h=ŕtRS-^3 :VN_.{կmRL?/Ɯ] }?i4 1&m]GI|DNjLσYه}XZ157dۚX\ǽwKN V/vNPOSCph6d8zѨq C6@M͛u4aD\'Va D\bAd7Uҏ9(PQhG--\y.*1aɁ Jl,B@BD5( V8=t`562}X~+-Ec) VPMd:5H*/'6;iuSK{ ufAgxHShhτX8> X̎C_ orf0RrnXF|%Ǧve# Yke5aВ8'o;g,kNu*hDѻ"Unn!["]7PVUq@b乣sمNju[TTP(]wF2e4x50b+}шXWӫ BŒ<2 <.7P{՟)g@=h$%,d3CŮk+{ǿu[ber\k?BYW޻USM?W+;%; 7hvOL%cB[e5k vݫ2SЙrPFl;ԝ 'aI~eA60xF9݊UvN78=D 9SwySlMuި:(MC} Zl;D&^'5Sݞ+p,c`M`<p"‰ypaY3ZcQub [ੳ}BEQڔ& B f(|Lcg.G%a+x\bvEf4œ9°[~Y>&0=g!g(t^NIJ$Z$ЎvN,/`;$ZRr\N(WY)6څ"CI> 8&ﰍ^co;$)轡TZ}5ƺ֪Ǩnv0Ϯ!)U D#MX{ +DDٔp.~dRxpYA IsL4QHM(yҼDMᛄBqK ,LHg|^K?M}L5G"-VՎySrԞsmV9^9yT ;\'DuWt7'|͎~e_ ~ucDVcϬ"@Hϻ _h\TEӢ,ʄ-s_;<\(ψ.Wigo#+3nŸac %2naF!z*QG'Hl|xYƛo.ҫsH1kl J6YU9jοLDR4v`,2_o"gvlCYeDH_$Kn₭uWm L)#:"L?B]dTAiL\y ;B,53??F/OduӜ u;p %D;vuڻrDMٹ1^>YWIy`pIxb`,Gd-j\M: U0*EP8 %eā|.erUGX7bE. ,<z(Dӽw|/WYZd ʽQ`˒& Xq<~ˏzK}CzuqlrG <;(UQ8ȡ&5B?hAY1ȘgtLAusL{v Mݐ<Yu9':ȬNUXvG؛0b$Ǡb_8OӊkH%6^ы,!T\^vþ:O y:% .D :xp+0t2N F E0q|(5 @.@6N3YD$Wqב?rgRsx- ְ+Kr+QϻQvKfܕH\ӹFXB;XCs+* 'd71Ldrms*HNvQ/2`DEZZ0 (ItVp6щ  z$R1Ur2 [4"uȓg A-ڎ*p" /&Ҡaoȥ;:2 ]dDI D#ˤ}i )?p>iNowo ^V83V4 rD(=X;rEq'uV[]smLh9Rr{=w;2Cc\x(zR*[A#( V$̜5O7@B^͏Ǧ .?}Tր KNȱ S70: ce#:d?#O]0}S¡eT\#+-B tP˞"u0"3C_bnZ1ߢ#1~3uWDEKKHwDfQ%nsVHdMp#_) `2PE2\±?ZII'{2MGQI2 B*x_D.CKŞ2[hkDCSn֟ t0'gF"G[8 Zy ڽ,',lUu"1p I~Iwte`eҰaY9UuoX \6ʃ% FO9^OS-ٜ.|O ? PYH͚d8zw k_h(§NёޘhdBj0sza‡vE)_HKIuMC2B*M"k zVh^QBX08oT* ߼l'E5m2ghiӈRAnn0}CXEt=I-v!9q 6T5-U9TƎԧZQ?"-l /20[ v{\3z9ʲ]UEϱ`Q5ɳXzȀd(" r̎98 =I e&.A݇K,4}w؋'xU)vNʾU-i7b4_xDjnN,i)DPauf$BtJ`.5H64 s%d"# j|;_n@/'!kq`84&b(K a|"%r{q\ Y4o*NWS@P~# ۹0GZP.&R jw$0:[:Bn@'sdT}KM b'Ma [+>u3s>}$lZ:CDw9K*XsOJ&djod3c:^\#'6|T@W]}н5M#Yc)f|N^s|ŊfJ27DrE|4ٱԨ#p_Pl 33bsuJդZX jmy-Gw.J|.f]W'|xleٛKy^0Nmu,WnxH%ȖHѵӟTqMw C3^IK{@3/3f5KĔsʔ(d"kvМr^KZ(L|+dsR`jP !`MyaG6yNuCCKh)WgIC +ӑ= mX_ V h~`hH#*$-o$$C22ՠ1rmrk sz`Vart&Ȁ5"Yc׺)h!B8vC 'A3A,%L uy5&f֢> MtsçYú҉rQP\ H=XW WD4z-pD5e_53 EB,1KZX:kJ0/$`1J jXȦ#~y8I&vC* [; aN#/>EZ_~nv(bV9ľt_ ^hhHc|L(Yv(<? o-==hYu5JDTs+ƷCG _j/ٺ3V.<=8R.C?F& /w|Dajeͱ+@# < AReR YuR?I6e+q5f&T1h^O!YJLu` RkO8Γ~IjsY m %Gc7geJAבeD%2۸U.X6}wHmϳa],=B$ ێzW*UVbI7j10r5.o64Wn>6%N'c_R-mǺ✸}`T;I]B~fh7/ v;lV~v%k  ȅ҅e bADA}:T xL,n|?0gr^E ɾ^]"wW̆22#I{+JER:x2>,L CT-,Jrc㘤aP0 ?UZup[*F}n5&S8Z 93¦xciG'IgA>wgРchZ;e0Ŧv!*N_/rņ6%y"X*a;s@`7$G{U4faupp,wa:cl^!/"|] 2aO(+(ZNւ@H=W=%QުLj^ 9 F0 "tUhB1Sc?Uc4IǤڊey&v5$m3m=|xa؍:E8%FWAFk!e*ZmG97x ʰ]5K̛@^TgwЯ YTh[ěc_d?c@KI>2m@d. «Ah4z% 2*),>2>;5slTHU1=t }n`f@wbt%i^x埿m2Y_LB%ߵ 챔ø24\,YbBa g0O2bG2X7&=*?G5 `i4&`BzƦ>$[%s_Au }Bmqlr%a#_+*yL/30eΜ"!bw AhNÜu&gg4JJ=dr$%K^$soE0o5 JyB؞#6<.ap@Z2oc9ft5BLw*Yr{Gx9I|ƊO ?S8FwlϚAi(Y3#/ޞ=fS{Yan@fh8z]5"B>0=T^\<:b?XfMz턂V/"]2幰aXHbF:f}:םҞ/.Q4Rb,[o{U,9*=6g-VFyHlGMeNh ު]/Vs`O.pN%C= 2-32+oh%ւ|ɺ!^ۡ,ˁB.hʂ<,M F)G 4wxx3\+?Z۠7=᣼}Ft[DON$ygf?IS*<ݩQԓ# @TW\0y9 ML[4an%D9!ٿVRT䮐͡bˉ"ڸSjۛ1Hdfm F~`iՓ 4$=n;NrKשsznf2b2 ENznp(`)A}޼ˆ7;yA2Q%5O% vS7#'JZ3aJ/sqEyf}nUpʼY7 ሻH޲ӜֶU-S]G{6Yg8{0pd=ny h"_Ig^2!3m=Q}[TZP*M;#im78u-rA[ګH-j 6WԬ]/aMu1RJ+9f6>/X_gw!Ie*("J?¾IqHalhj/`{&=vO%؂c3;O̦&y–>YqTX/GU6bWtn菜.Ξ" Q(SEx$#j7{*l><'拘HrM-k|È,VU\FT"A/ 85"hKOhBVz !🞙RzJ^&L|CN&t[8忣PJҺ :6gEO]~O%;!ݫih>K9Umit!o V'پ[O z,,F1Sd-e.^[KMt^<2׷z/@t JAM52ً)>ʒñoEk؂8(綔ՕNwZwU8žSr:8105K:oj56^K@@X߰fHcWagq!JYuAryWaMw3Uu`gۅjmMS4hrS9TKnoiWh4cb8(mhDUXɗFOzvmJ_pXlQ=J %FvO=z4FU @ $@ɢpYr4uZCjģ5c@2`ONΒ)6sGI 6Í뿢]tjk'T]EL<Gobj";eJAC'x1C^F QRkèYC{IW*\kW8ǦW sUy-Yz3>iTksf PG򁯠c+8t09q0+6f*rÛAZ}9!W;.)3gI?5}HE UKsuRuSn2CNي_.YGzcT_LI$~xQK40hR?c3un_`' ePDʤhQ-Z.T tR+ xK@rL()}FY@œi0h, R3NIJ{`?3zpRzAJ4^rE6o' ѻ"x߳Y8>/. Tz_8@} -w 莰 ן`J.3!7>Ief™^iDSNc P( BBkYjq杽O3 Zgę%VWi7PfLфzY)+ Dɮ azT6#Vnp&i[ᦆ ]f1ޢS|w5 nov$Wqa]D<}%,OXQT\;H?x'zCs(Y vh}z%V;7}y+gm @vn( חKQ97\XCco|Hƙ}ۚ.Hd=@,PBv1n-虘jcɘ>[@i@KlU ]=iatA4B~OP {""y]sQwBȸPv:۸__}t3g<٠+x9Mn-0Iw'-fV0PFIdW5ѢST }jgu ]q<)j\'-YMմq^iwk n@Ur&fd!Ŋt6g6 2u p=:lhD3_ȨuWF܀S,YQ,dT!pzyS,Nxv9WnTƥ[c%D 1v ilVf *OQ|Ch hU9ْjIb?{',)zR~K/@dt߶zTt >)KeFsY<51WȻ3/C;_dZ2Z8 9O X[&fH6u'~ϡ*-{/DҶgH-h/Ϥ# .mbW`#|?VFFF!SnT{Fa/b/~ƺi[H˳@ASc-[m@r\0P; ʅv0G3X%пsUA% )_n/YuO`7OV;eYL8)忚1$$LA5Bgj%PZf - D$H(yn]2}V'`!%R0ԉ=~|t.i:ԻEŃhFgn"3%6VR2sx PmlUUky[(_2ֵEe_ohi%~ᏑL_ʖ\jFu M-Ӛ^qzYZq Ƌ%)o _.йyJ%Lo94k4kEۼ*Ȧ˅6 _J Xٌ-Mg˚41}>g&A~X!Y;mSrיx~?9j|î –D_OyY^act4iںJUxa243wZd"`Sк) d5r2ɸz犹eK 4dOΕ*s*GSi}lѲ|,OV){hM!8n,qflcq}e'oK"r6 qi/tꑥFfr[$V@?^gD8m:Y(0Gb"^(&mY/$&tD,4M3HVZ)@9hzм /u 85V %–?u“|Ì<(aRBAȌkNkYTzD' e}p홝y5j\ -X)#A5]tʓՇrHI v}v˝%MЍ ukI [QԪ;a13/\|!רj]c"z 1cD@6ui84J^wC\wȩl+XmÄMewgI|dP$}lDp- Eߦ}]Q.IQݢjy@gV7jJĭ.uǂb1:C/+0 @brrjSq/C,2tԾ5DZ.;z+8_Z2W'I H9K/0cNJSXn 3CsgS-E]A dvү{Js`[pi&@egԪ *.)MU1"8aEd$CG¸ SrFv)3b~(( D],'jQ`5E?#b"0pJMA0?z/Ki? sRzmSAWR7_>jֶZC*JIEi䯴mf-W;TA2zKn(}"48 /Dn7ɧ >)](GCSd~16gyl'Fts>'-fE79kL3 @سysE,s$\bk搢p eXXrz/fh&{EY r!5{Vyiz&@SXԙʣ[3@|eK7Vh$|?tY]Bmo"Z䥑rPڇ{s‰rpxHX#!xʦ4Q{re< shv+wIfnRJ[I^0Bk܁Y##丶]%\ e|g`NYt$obYցK! 'd²ԪYA%#ŵZ7LbgC @+QúTcʫhx4wDm~_En=Kka`T&hOQMt.K8H b[ ,%Xm1:uIAntPìw~W׍v~nD⾤dפp/`uTW1qEl%l` ݺ J ؘ H辍⻼wf4v)vB`YC%q9z2`ҙDf7Oae06J!6 gJ7c7G<{?Pď5I|5f2[+ 9)H7?̘xq7mі 픴Xm #tNp;7hx:E Ͻ"{z= zhwFȰ 09vOaza}SP1\em1LT>E< OY hB ?;ĖwZ6Z0R.!\kJin]EDYeCOjٝѣWF%N?QgD-uyC3;U,-}Juc$^7oy{< Zȇޖ=˓>OZ梳']{7<$#6t ! *B,?1vf eݛS #Y~}opǔg2o-IHlU=ln >pm,7FkOsCǁk>'-\R@,V05y"d 1x~Iy=WNZre1&8&_3 ST2Cb< ЪOks•1+IԖ"W PQB*JQ8T`YYMZ _魈l~|202X:J+.R89Pg +21?\;@B]|h O_gWw'2]$xÏ],!l]?S#ݲ|F!Kpl:\5ةM$Kധ߶cG$.RL~:kap Mr21.YӿNdCiLڤSYB5\92]t6/ycv`7⓰oAN/MY~y'mXx <~bϳh?庫AΑvOV,S{@G/Ii Kn) ,t_c6|Ԋ3Q5 k_$[ORťfB&3uOK5/4"Ԩ2=eJ:-E ?'}TGȁp^8/'͉ҨKY;T߀nˆ61L0s3}@Pxx[D([iflie_S>{)>ulWJIcH 7 btg5r~OkC0c-&U5W_|/򪺏k.B/;HUkKMV<ω6B};&;6 F\nqbSw~?pfDՒ< wqCDV0~'^0 4gu n(6H3t%~yS tK$pxi 6Jdm0 kܥ C$IsT~ӥZҡ}FwjzpeE 0j9()xǨhi4gNYMDI0vUI}>ؓElYF?.::/ isXnh[S-@:IO.Ljӄ+X`KB7 'M,d$-fĻ"5')C(&P᜵Y7W/W;)r7͘:NN*T~Dmף:SCK(S)&eg-$2bPu4oHE !`%rXyN䄭rЖ&ʪ'U l$L|Fp Zmp}}<;[N/zl}3rO1;2Bp=,+ M)bT}do?Cd~1y/bjƳˏAQ$"a% cqf FXЈI'l S cv"wd>^e;tχZ°x2Ó0H7e ]~;Z,&[xK$aLM2;TYEJD#%{d_iψ sۡP8jEV2 /66+Ha5J&7 A IV+K]#*焴F v^",)- p=hVB(0)W ss?_kaVWdF=Ї'%8ol+$ |PNE>rjU}:OkHԪ_F.0$r@uʣ+8 .6Zg "Wڎԡ5zV O=$fnqP6`nUk&0E>y5.R$"YnB! ,G#AlR"Hlg*~ X}BT`PۿWt ݬ^S+050ؠ` k0eQqB'd xt8j6r ' 7aw0w n}ہ9URXM=ni(JOT(`zDZ>1q*b's4I1h+ְrY$(|6}f3zz7]j>ӿp~Hpg.̦PGf]b`dUnH&NйMUK}=h^"HP.j7-$ǔDar^}14@=˔AZ/+UeMu )y$g8XwCnx@!@'s$_G# ȗ-R1 /Q'12\"+DTCogf*Ɣ{2a:Ro)N:N򤦞T0dPkY?ۅ1tJ#)jKi6i_R!f}R B/3 \yb Mb ҳDxcm!iJ`يK&ѩF],cdq8k e8!V,92IsGoƵdU(KTXh|z!dkI9UR:"ykZf/tBÅ .{g#Ð*gwy&h˵L[Oy6U7e54 s<:8$5A&Bm,9ᮯ264GR 1 (b#@ ZN֌8y:4j*nJ"XFq(~A/Z2,xW8@/*Y1DwP(.MY3SZZ//G pV.4<ty屌bhp"?4k -`ho6\f@>I +O^|vsَd UX=uH_݅f]r\M˹~rS4Fܝ(}v) k@Cl{0{Mu CLpclMU2UeGpHB8e2c"DNt7!lS^TĒ ͤpuRp%(>]ብ.Dݒ{8"U;x~%+]:~q6}KnDMg$c_Bxs931 ]#[S,a)eDL8fso"L2 Q(iG+P#+\՚c9UMS"$@E~o`dGFA.BGD~R9e~fMj_ w*'&_u@j ]~Qݫ7!,zC`WJe>f!@7ܗf鳲'kB BSl+p!\r7/0_\qOixC7-ZXԘOy&H1kX#&6ejfcDŽ@V" pAۈ4"v~R%ͱY:a`,GMJtm&G3bO.9!Nn"9ݴ⛫ghIRJ">kL-6NϼȘ{ *If`AhzoMj—_B]BF[`L5#]F1Ң3n<`Ɉb"=bR ;GR'!ee{6^ikj-L\|Ɂb(;6j~(n@q!#lny 0_Po[k<%sj0#9)"n%A56c=Ib|PP`EJyHBGY?g#Q"9R/AG['/!}^JKfqeCDz^J(؞y_$rAgc`8᪾G2 9%((tssYM]V(G8^(LbGI֢YG,Hps"\ JpO]`/7w IJ{ŨsE3ibJz* Yo;ϝd#<:bbpJ8ġV!{BAB"h]w=!xKW3.ejfڭ9Ԃf9t-J2$GUA͔ebImZ"KjI]mݮ l@$okPBv*AQKoDWSE<8B+%]/Iۜ~nlcݢr"/5J <}e< P̖LӨp% Ȟ+{TOBlo%x"_rw1Qݷ7uўK|" g4w&V%=T/~?ئ4m}vpBD@3%zγ\-jXMȎ Mx A 5,|MÅI0C$rꕍxK;ݙ)N~61%,usXQ'\5#(ow<B- NC (W"yat *3Xt`b2zQ sNCU¶Ӥp_=sm ̠b (Unh1 uQ[J`$ an ݂Yu mNwSzɁ^# M~ 7p۵j+1m8J׾U1)S˅D0y B CʸPV|1ay6N5u'߆Rj=P >]?k'RXՂH5rTbqĀςc ݿ=Z%W}9ei̥ ԑ0}0bPoǁṕLAyM/S!xk[̈́}9oôtu AV'E!'ǧKT"yy"S0 S}61: 1r*x\#ȁ/a%sy(-@hz QA2sq\צ ab- /P>2 Lvr' xۈ7l\l[pЫf頻bsns%]B!GɽgE3*og}`;)(6`/;jv2YSlByfOK/f:qIgXQžErqr'x蘽'i *K%N8tXgrYHF+~"WcI &4$&;YDMX]͜cqztcl^XiNAX-;/>ݳAFHD:ܱuNyFtxf-ڃ{Ǖ_tVՏ$[3-zVj@e=3e*^1*UxN Ҭfb{ّɈ>|*eXeTS&:X..=}H 'тݘ#\U]&0>HN1[,'7g 0&DW]l1MUXaHz I-oNZdPHmMB?4s- ?kkvhEgb8fp֭i25^\ӭ\;K.c.A&.P/5qp/?p+穹k {1c N>4D[!i#)Iy# ϾܷSe,=2&"=4 o{&%ZDi2bXzSTx9ͷX =6t#(+Q-fа5=%o2.P垤qg6_rc;8ts@Mb[g} y^[RY[T k Y~li7y tw*?HU暪7o( Ci9ޘA~9tBB^:~nT a6)L-ׇ1AýI|2 iv6$ק>!iWcƒ$V_X2'R / כed%do<xD5 ncqxgȠSAҚ=[FNz |FVM;$syE~9륲6 ) Xra 5JXCPnlYӮn N@h7鿗T ¹4B5|~kŎWDѐ7 wΥCֶ!nf+wo6ab R*d 3]T>b-i}3WIJm_S=H?2ɲ^Q:GD8 6<ܚ nXJp "60Xy$@iBz/@8i-ޖ1@刧5l"$f7^BP3:=yNc_#F)ZՏPXl;FoP8DaaXf+B* zQy>h`ЖuwV~˶|BaI[Dـϥ)DRN*.D: W)K\ ٪kҸ`*@ꉒ q-0~8bF h.3)Tb+c¦(NHB_{iG_p#ݒSàvraL͋YR6xy{ENgV!yKyQSaF ԽDT(b@df^Y-rAt=9@r=o9#bWPV3Ct T/f >$׶V.VqAFIiZA@_F_?4 9I}L8#+t,0eK@*噡zc=Hԅ0Hyk*:8PObR-jjRQqZw&uȦ\Z);I]Cati}icf>^KÓ0q'Hw@(HA5G+jw6Iن?`*0[w%"*ٙד`!NA2t^Y6wD=afIp3O-Ht. d o(mM/*q!*nbn:~0u9!P{tٗ th>dbN˿#sz0Aw|r{7yg\͟`jc# E9'f1RʢuBxBuD&{Iيqj`Vm8y RZuDn Rⰻn}PJ7ѧa?i%>>͵trk9,զ*a"~r$tQGL}{h/ö́dT4mGv?/l'Iݐ]^hڶǕl-0(Ѝ|N+T9ڳV\%r0zLaq͑+i.lgO|.At^Hި.- .u!0бnfZ}=Yb:NJAbe/`)f n$dE"^2\:_?n#8Vp${)!#=Tqp֒jⷽ=~qaK4%BйzBV;y hJX-ilPlջ֊9-kMPJΊC]s& se!:u$lϨɀU5j&-I6-2Qkpo߆|z8 +.}B82[rZ߲M /sd-)aO.k2%J6<~ٓ)y|Rɠs޶'9jɞ\],y!}S7PV>OCGDtFӥ#vgɇ4gM }1j]\XO$պjd&\HY\Ws/-AK1{zi~?PJ0&wsјuZç4;Z:D,3Q~-hTkO#q8k&ɸZ{;R'!{/ȅ>ApP}G`.sJ4Y1AgAi'7)yVB&)A+=9LJy s,2 T$0r]+> ]>tEHyR[M8v 2k@OUeu/!4yl] ._iȍ IدAf 5 df1ˎ6]oO>6{7<,iy[G?TR\ ׂLTL*|iGD9[N^O`Й!S|8ٻsR0KSSN:i9-}f 6X:%\nifaҨ=/yI67MK{{!L۲S9MkYLo*b/eF-sتpTPdG'wG _tԙ^=].7LCwQ z,͂H-nxoGB~ B"LR*֛2%Lp2Q9Zj1=$3H\?Sls'2tHxDn6DCWO=T6w;h?S@2B׮GBNn;GO>>S_ ^ud*>K[LȺjޣ2Hksd,/|%/rT:y[yM IUOG2U7u_#N퍺ya~DW%#W?N ޯ =-@1LMA`|UU. a|XI JI1`]|,%)p e9`Gґ1[$TZBëWF]_mҎ;. {V|M&-QH ,;zfʀDzI-]"Y@ox\`6 q&W5)8L=͒ZVgTSN8;?B w$"H#O .HDAS'~[*j_J#z[<}U՞0u(fm*:v_~ EFTBn*Fy%/;q] &"@4c'֌}7@%ewMY^pE;C BYWQVxP+0bfҖ밁O' 1)R)6M`#'30Q6SiĴ.v~ 6׊%& |p2c;m@&+MIDݶƹQJ3(KZ[+ :oRT%o#)/`Z6)v+1bӲ3*"+U%amxbDd-K"FY^ ,MI =1Jti_ij~G4q(_\#mC|Pg"+sVnn^#7z(6XxV N@`Dl=ID>KB8'ԖUk{n;&ft 1}q$4.fPżFF_1zKn"@SUybI*Nu/'naaDtvdDK0mbU>K(Nnoܫ3J|jk7@K93E}_Z w.?ƤBMsmųİzks`4]vz_9& jisjv}d~rz|g*jeɶj5/*YEȇݘΜyLEg$bWSζe~+exZmYz6"'䗽qp]5~D.rvlB]Cz&{tr+\TŏE7DOF_hLV~'yi%8 q9;݀{-T#x#S D*PR"o""ĬzhύnNDnqIvFmW%?oM 4KHkyѭ83[Ѝx'q=)yq%iE5p`#hV+E8Ocf>^Y`PF80Ϣlja*f/>P"¬lo̧iɭVuQ3A D"T1*#||5tW0X>[Qɢ5pkx 9*շ&DIX]bʆVi*f<y/3%lK~V ~]0c3"Yy˖sЎ\duUH-I۴y OYܤ5Gfau4S{,&ig|9^}">Adb=-XX|RGJ?ph)сx阶lj\l408_jyRGv}e3>O)oܿE|3?»kنo](,?|,G݊oBv;J$(z w0)yPND?mJ)܁ז:OrT2W`xs99`ճz^>aMCdڥNĈV 5QHdаIvFQ:]^%^_L_ʸe賏E\8 !/de}Abn.fX,f'?Cp:MmX]R49 43YroUp )@f$:2nfNl nBl)QqV7 ,As/fcnE #x`b$hVmr>Slm_ VAeBVKwW);EAHe%.V,ZYpUA2M9Sm+#惉HM}K.r$d~8^J䫵]_ 9[yl!$E6}|/X]] 玗vrQx$\V/9)huҍlr0/bND͏R}-1,Z l'b$+5d)Q-dK=AK;.̦ }†ѿ|οL]Fd2:V&&VWቮiKlsob_r6Y!IR@$Orzu+xѽ1i L0) ZGhq"忄N4C(qt}dǓՙ\-ƇZ>FJ.kaUC@,qS팁UPQ!$dаQذ%kCvrTY4KHPST'71%FgW1FoH$)եch7-)ݖ{Uހgr sK? pHl]{q>ׅ5:iq+n%DK@bͧȾՃL{?) O[Kkڔ^#Nɜ] DcVuaR[b\0~9o&XlB[HJtǯ%Pn( 矮~;FrcyNK9Ooe=7-.WE="_RNWG/?R`Қo.p˃6tkBj{"Ed<> 7WQM?I~:Y`6,_PljJ4hYal]8iIq4śCB B҉wCLA%(DPA4LyRgD՝6^p9r6yZ[_s8P\yjCK3P#Ct?V~Kiz9 oX/2\$hj=.B Ε9o_NÆ~vM¬gtg LTka:NJ2=zV%lQ|S~#>T#TLL,礫5^}tYc܋ոA>.'3\G\%dh^ teU;!k[D=MOǺz$wmx@ݤE;@? .}չUO*Σ*ScTIӶ# >rY5 ¤S~ $A|G(Ei]o[Z ]|mj_WP6֝ZܴUA ͊ק 1Y~OjHVK˅K Y =L{t% ]7oF_ˤ~07nG܂-VUW=<9`(Sլݞ z~좬 32V6=M'aYn)a+8w v`n6|p~>;9&w١Ii"3"XW|2vCf1Li-&/4J0Sk{-DŽ\\_ 7dp> ]7,(YRPSQy>`G/{fdƨ鏴CmQlnt@;CEc:BWzO*\ת߀mQ϶)>I[ w8 hk6}Buڕ>"5k`*Z<."``UiC aX/1o'ʅJ2 2\+u+Tvh,r(F jJ<{i.}d-P`d8s>\@R-7I%:zA:L Tu[Ywo`&6 {i5U}n-/%[}XF\f/Zei(Ȩc1=iS.P;&A.hi!jg@ @LAf{`WuTԳ%qdo3rB^*.iֈT/K\`T`+n t&= L؇~A2 S"CؙU ^Lc&ĤoR33vIO)Cu^YDE /nP.Tg#lDlUAco4_W+M}J>f@=T6%"h86#<%֭W$\O0 -٥Eٙ{K8v Sp4"|`w=E0eqjR53<'h-d"-ly+ /mʶgZGq˕♉V,vIAP*JQQY^tSm!E*LmKh E0B% %(}OۉV;c)v1n{ؗ%B}Lϯo* %XÍl5Hr&)dMހR s`WgCFlYn߃.i>t}0 xx4 \N3 iW `dW#+ o~tm?5brtHdy񄻋E/N8W5մilҦM~ڌ8ͬ)}&4GN*jeZFxX5C9%q#5x i/T$,1HV-*`˳zmWx5:{i֏PaL,/ZƬ/{Hzp457ޚ{Nfxy 0 y(WfddDfhskWW 8{<ϫM#,3*UQ%o|E͑FPQ*ڳ'9JJ/(*C\GƖtV-{#ڤ`cBI_KMէ^ܑ wfHZl7(|joQY69kCjv;%qf9-٫dU 2oTUܮٖZ{v \T4Q%% hyXt(20萬R1P1LD{E1ۢJ$f"@[1Tŀ^sT*R^ٳPZĩ`{xH4gT9wF /Xy\nMi v&tV$$E$XU64\ı?e.݈iMD ']p4ʕnʶL[]TȾf샪xo+rܦxoMa3ZD iSӉ |U)`笗oDR~nDž/v#W/-if|w1(Gb :+f11: ]mQ't$)rsσFAp&-u{.E\nsHcm<6p0 T;y囷ap`L|Ȁf谗U5NjL`>Pv؅*"!Ȅ*G|V:$zy׎*yCS.GGO+N,@.ur*%V/W?X`*ʷ}HZ%*a0Jx uS c-.lTWsWAvW`HW KICJS[tv.ﻐfP.qj@`A=Р2]iW(Q E|܃`gBTEAx]he\eԦu 5z/:R9PCDUa6JkK:-f\"N#EQwzk? +nH0`wj\6c׹! x\tkmU}qyò֬`c0t;\bK5J% bz=$ֽ՛(eI)@lM7sM3C?Jr ޔkC+)~JZV%^*CIkﻂ̞cdP'v\LEKȪj~R\H:ZDusPnMI,f>',_{ eMܢ0X=n$qJNc<Ƭ5>6w^ NmaRՏ.J'2B_-Qfm2RPўfFM.'I3V;>sIqu7WoEcm9J:\ޅ5Umqv8J%~8VUnkZCZcFTrk/P[);3pWQ}"5XkJB c*'OXkXx]W/"t.VIELYEY/ٞAQm^02}@}ؔJG q) %aS9n:/s 9h~z+AAA O{?LzcpOa G+|ѴZ(DpdϫEoD ':Cx1'֝V3XRznI5cL~Ϧ,S#'DDnUUq1Ceouf$B|67cF@ܻ?c{쩫|*XdžD9r=}ܲqg9<~ZaXaNH;56 k˝!i.;MeRCm8J^/,HyG5@[Hzxv}ihR b̾NTWF^UKggh潽/;i+ &ykZh-؍Lj^6Vn0UZzTkfbFo_S㝊N@%;y{(磌ʧ9p%ۼe9 }ILv D`~!,OMWG!Ky}̔u5O"84]<@Sn_g|4f!΅~LyHM~ ?3IqxL 6C~˸X4ɵ=d?`dvIR+A[̷|TtV+5X-f3#Fsxcwkr`^g^#z(_}*o Q "ۥ Q;y?, im ^yYQf1=uUfY{}18#wIϞY"O?|  +:j8c__b)D`7-׊LoPU=]guUrE~"%| 0XW*Y0-̗8+6' hp.4ҌGW]* ŀ?1ʢ3TƔ_9OEwL*_nmSlwK~$ -\a!~5B+N4l:e.#(=rXfl:(N-O'mhk'8-$yIXO,o>: rOc eփ~)I\X)m>/Ha{oI4LD 3?c;X^ipHmB%nr+~K.{ X>cƊ!cՒ2? ~rW`c laT>OBs\VsޯeKҿlXx8`'0P[+mH bkYQ8u]sƟt ;6W,Ua ͎UO#xx:ZF>"Po"<$+ #Q> NHS|P1WjRհoNy>>z u\',1ٿy1 p DI妪*@{yQܿҢIDj 9X)+>omn-qL;<mϧb7-%g!y1h)<#oQH2N$l7?eyd}V eâe/QchKe"hЊof 2KfԶaJ$1'(DYLw"6b#ټٱ*xnzVrcG=IG͆zzB CtʯZcYt`yЩnmbO k(i Q 򇄄L ߣ7udv18+1gx8GS>ï!똩i/=:8IrLοB+w.۞? & K=$z]\6I]8w?9ɾnTM=5 ƥPpg:b3j'EU])3zH]$Ҫ. `4zUl^F?yo 4۸n|O!h̋ nvWZӶF}RTT!Wg2o]C8R*.8 #%BthRQaŠM:?^̟,E02Dv" kI} nMڪ/Y7ٵ4ԇNc;r Vx;d" *xEfn0yb/kP+S,M r&f:ɀXPRțn4^S+&A]ԓ@ j-ũΎN daŭqdP)kM!iE.\3_,F; tyA'Y+4e(廭#V11Нer݃Ё26BV}vS.)'J0,J42ŧYjyR&iAJ\ l8xo||CӶOI"X"r.M;(*N0CHk}?!7Jݿq p/`7uTX8uRjVXynVN(0Xlϫ+YXl6X=9%ڇr)4 QF۞I|r!R岬#@R+eFky=yb;o4 ־%U.; χwaGl] C! 0.%ê ɑ buFf.*-@2\Ȱ^^cYAb vծvB6|3ފM6)$\G!&2B @Gp<ݗQE^/Mݹ򋕚h;5_GԘ]5hr͍NUx J|y'G2i^{|v5е+u6B{ ( 'v+Da1O-/=(3Tqۮ_YM,4޸L|8S+a߯ȼ6yĘ!.G{u~ ʒ~&vqԉS@՛SF^q%gE-"`;>&Dz3ŸZOa?󜷛13sO+4HL:i W/ҕe:a6l+kmʾ/U.M hVn't!dn~Acz_, v7ƄpmTu& 04t+3wx+T&7 9֖8bjJ U!gJROo1Uǵ $]%M,F$ lܼXz"q8"6m/V:o=.txC c:y&ԟ3o!@9/+G2QT*CzO9ZzG.l;y rI dABEq'6 )zBPe1z{} l5vG&(c@a8l_ %-*#>'+z#Sv^agbPJvb%uɏ$؃8̃MqE<6C F >"781d9EuG F`/pkD?yî~$%pDbwk!qhʣMք/EQXԊ[L_Yꅸ@rH%&A0\⸦ar>zEk:+GPh931*\W;Y\6_.|K-0qRM[\4A@T;@gPxO0.HC?]>dɝMWpz? /`6eQ` /,% C~ahA)wEY2o0D>uԄ"C1 jWƪ'rF})o2BhtI%suy[i H"g:hF:l^M;6GcyG4ߒxR;y٫+ߖU*=v~ݙĂMWx󌀜AFJwh.mӂ7S,܁u切z#f^V:c^bQ.Ӫb@GaJU%k|T`-&=~d^2clVV Vw"PA|1Aؘ8v ]N35:)q0Ft=cHfʻK^kT%% 2䎺1Aze=<]ca1 <.ЪUL-Cws2=C)llڪ+8e YLa-̨aN{8"G<fqƳOl SC,].ܼruR:D>yE\Vf?ht ҫ{2U/uo:_ԷVgJ:0=wjDZ(4Z5w 2$Zg;QP&zB1QK!rG>IСw]2TӢdm-7[SٰP#Ҭ~bu3^4aC[OMȾ"$ݔDX TvWuG#Z?;c~TVԷ|kB[Z\᭥sK)-1n<⚪:844'9;-w2.&<M#OJ``+! X\Fnϣ|uWµ&rPRy >Oi \e Ԍf/wESRw\`|ktl`~)0GKAI"$*8oj_?z׉|bʴ mx!DMt/ oCj;O+k,ڂzJV+j_.@k=/Hbߕor- ț xU_\%jʫ~ER+\-[` ŸmV@۝Ļw(Rw: d !f֊lӮp/iݫ@_DQG@ܕt$U~?vIb1yp?2)k3? A j 5kA M瞏бj("J,]m.O`wȝARj8Jj%Կ/=YVY 4-H2 />H֟c^"Z1񑚑L6G>o= +2"[?*O}SNճH,cIlFlq0݈mt(}26MٚFz=aEI:B)>LwId$kDjƵZp=fAs5 }6kϋ(Q֗DgF,4$L&ҙ]2UJv7gt7O-KaeI9@_=wCx Dd7L@̝}!$Mo `0 M~mc'XvtW:Ju:%b[H \~Ӷj, &8$iildn$<%Hj(`nǡY\yoEaJ! v>2v|\8dA˨^n3_߮GOYޝPJu>|?B GXeѴS5*~WH‡"@M"7r Qpzoj' w~H±ū+VIh"P &϶ꬄ\QE ":" p<8)c0}>i=dQuq>.0dZkP\r# ٧"3unvm? Zg32#qdŪ/`ր_uG;(,~eQƋJXDXYp̗eV9*hxhm/6+g&TQMAO~u؊{"agd +wX?5͕}!GFLJ,{w]--͓6lQ@<Aok9Mސ @ٵϢ:3 )gvڜ\11gK sh#O:U'zþi=1t~iC\c=nPVOqdQǡh wq>gņhxN!L>P; {tcK *Fb%b/L;@ ؚ1^cka.nJ+кM_*J] e @<^l[?+f~D a\23F4K N eN@"a Xde71y?d21_pg5%Cf^(t4"&ȘjhաeC(w.y`@˛A|X5 [ԟXIDxαvMBǣXҬ'f\- 󏛌!`YmFfCUMVRA1-QGmȴ'BYOT-ԩMMJ*3]UeTz8*G"DziVvxC)]Ol׌D,F6!2+6̀e2j~coeK~\()M:YpBTo#/vF$KJB e6486.F~4?FsL5F$alTx"dR3>!yX,;8]7p-]]@TrY+ic99JmY \|S]Y eu? WK_}*;C߹ */+{"rV H+EmpaSR]B }h^~/GJIS b';" LRji|ɂ>F45V8G$Ӭ1q!ټ ew'j"1Z@L $ W:' #j[AR+{31%P k>hӚo?Zi<<ೞ8`/,C-NSW Ɉ5\2([54.jO~+Gq,aݯ#'"2BCmY_p/ wdzŘVKH,\dƇBsx n=߂t;J#n@PUAIznLjxdQNܲ_C mpCݳ3 O풃tEE?Zh|)vS>_Fo'-ǵUV_=ie@x_(Q4-IVH6m4wcI9_1 /vm;ȸZhcDcQ{IJP#*84 O5ܣZOP:e(b#07vLax 0\:ű6'Ue&Ɏ6*Fbew6Յ#TkiX ;n)}V#9LM ~adt0 nl#-dӸZ_& -EPLzOSQ SNs_†O^?Z?8Ń=r*zh[R O+nw+Ӫ iҗYz͜zH 폮^t8dHGʹHZcaSOLd8ᶷe/#y(|c#gdO]3ZJAʀ3s3Űb,j+&=]8v [wdt̷?:6Xʚe+(_7}d콟ҤKg#鉈|ʇ6=L-e2+~P%tNz] .ž16kqFD,zqISIN|mWNiۂ"`L5]nU%ϻOK~mWyW7%GsKJ a4gzrf,_!$= >PfZn~f`28yQ1袴6KUaiY >W`8wL HkVA9L,%jGU1HXLw4$kMQ)M90Gj$  s? &X$n\ V"uRzմAL.RZf6WgAo&cS\[3S$}cXs?Nn~͙}vGvNF\aWCgʭki쵗Ӕ˒BA?kB?9 P5pW"O'E3 2koVc z 2邸'T8%9hyBpcZPy@AKzA:2"J6p&y^vNFbʿb+ ԎK)RuDn T?ܻ~GlUZ-ƂRF;je?Qɺ^gdtp1'qrN%.JPdP_!\йtdlupE& CwY P-M\dc/uhxxz19EQ N܄SI@UxG+;0S\ fm( n2pWuz4%* ArzR|?%TASPJ99@Py[G4F4 O3݅uWA`8NPXK_M4L єW$wnC%td@w]&A{S"7RHSrtu^ltwa&KS)|pݷpAdK^BT{8,m#BW]]FRtl~2DDW^woBsAn:д= 0КV;ԝ¦Տ[)Cy- g~kxsPNVܶ9{8\4cyz,9&GRΒ26޺NՖ)0%fC`OW#, S&s4FlI݅w%%{MkpQ16Vx 'u S\jyxڛ@~VXr:[.fV9D92$67 @=.?<:p[ 6V55lcdu5Ȅ%ߩ];KhTyqNB]&jЉ lޔoXpZ3[:ޱazG#ć&ֱgn^ϒ٠Q2T:$77"_܍W_<t]<bz_-\7!K̵9ŮS&ԬliQÈ1#i>>Ggz#D 78R6aXx" n7/g=l=߸brV%Xڛʄ _' =}s燌n[zf{(!b mPRMEv^HˮD4}߮'`$U  co]2tcOc짅ٝ/$:e[@e=iKOq[nJ{rPyhC+o"NYw np,[Akvܞ֏MVz2I=Rc Б Ol0NZ-|wk%U)ƝDѲڡ_ThH@9rjE==YH+Ҕ[=[ cS6~v]xht:*5;m/XW(cLp\.kշY 2 L-ْag/OqѴ{G0GC0J$GD#)Mfe!>ʶbl)UJ/(c ϓH_s=H˂{}i&ٜ_,-װdym+AHt%3;b9K~l1ND+l}~NgO7<4*~_ 5 ǵ|3*LA1USS(3ZVQlUh~h/Ɯf)?OQKt$ /c{tO)Rϧ8^'^^/aum x/b;'(y u_<ЄK7Jc,Qjl6l&8inQQ>'Йn~B7X5kOwÑ߯POwqgE'NS5b7%ubm[~0F-ѩ"O/QU1¿cE)+~Pة).d+,\Z.][/@2>/?YKa-t>qIU ȡfD1PmD0a)6SFչSSf03[ZE]>ˠ2o_0M0@l7 @dnyx gǘ6^+жc6AiI 5`pH\8a³GIwgP-Zsx~A` 2S|IEŞ1 lyz'vt}cfeESl4wrʄ ^ ҇F&\\َ6]kREz@~T3hD&uc݅!͂;ȃ{ u0캬nn2\Z(A2a2qt꣝5SY.2"t.c;'WYC;  Tq؍+>mNHn $jܸcK\ Z~bįx J& ƮUl%>U_dh8ߗ!!0%Q FUWՌ~AN`ǷX7^Zn=ʶ+~A ZGz9Y 5f$_YƐZTG(JP{;66{0 [$^Lc8S2]''ו(&H8&6.(琱#"DS՜d7io h!Z qJx6ZsFy[D lQ8D%h[ &EZД熶zjdkH)Q &MԱ<0Zxk}$ xXÅݹ? WLU5;/wrTZK8(m=RK0p+\ *ͼȗ](d>-[ğ8aX1fEIo4TEhyJ*,V86̡qmG.`bTC=piZ(rX'QZHۅj^sڡ8E履>p?xE<,9'R7++Rˠd3~_7HiaqYuV$H;:` ;mPNQ*kdQ9ŃI~>]GGwet [5z܉:4yڀ,Υp?A/轉"Y?j p8:RI@Ke^14=Xc4Z1I!ACsF飳Jԥض$U'fIcgH5v+ViZlیw<7 /cK~Qu藗UeZYndIqӸ}#Lxt5f ~B< Ɇv1:wfgyȅ"կC #ޔ d$yCiq`}{k>mXEb!q+lx|.G6UYIjDk c΃ Sdր*D`^Q9{+ [Xbܨ&]I?Rl}V\8,?'W~SѵkěVY>7aGi* Sz d.Vܐ'ה ӓ[p:b 1óqAg?_e`Isۑ(pHd}'8 c'F͓lZH)TOf}O9ҁ,P-Nvj_LUP@ 3< D %-@y@x/;vt5#a9SyJD YWҜ1C&A'Wj$,,)d<'EB4Ё`ᲴYC+ b:q!d;/u\} grMUd >j?e0r[FY>Im|1 rQ/SBc-nSa%Oum,p~Nʰ T T_8a.TbFϼ 95 >A+gVi$O.|s }9!%yHjaYh3x SQEGvkԨߺlIږ VB UP/wȬ{i_j{_b(} 'C$u%s+ Gvo {2p#qs qo}.Xougm^%:vY<ʺkCèlss9؅c=,WTmՔ7({$'nR Sӏ9g(*icݯG\m6*poBlѻgZ}Jevu11lHK YBF,k'rϋg%Js(a.-Ӳ:Pr~4rFTmƮ6 Ap(BM4=M'"^_AaBkw*Wg0O8vNJJM;\.:6]/S@;ќ#2uu]W0„;} 70%h96 'hQb)Vp;YlI$ċ Q@eƴ"Q_EM_;"!xO;XR9*f͖߮т kB]:oGAF[%} ɜJ/w-.ݪQCQ87~-͜JeW'jy |&]TZ H},~wԄ fGω]ڰ5` D&?/) kՋ"%Ѡ~<׬3lL!q'XFNED.dɨ0]Gl17waMt.-<7(!3ܽn <hn?{ 0K.FO HN6=V:YB;4]Ҕ_9wQ'meq.TC,5J0ç\iZ01]ͺXܯ~~ Mx88˯3Qo,du~Lr?*0v$'Oc΍4"ZfC92 Ǧ!WHp yv)=p2 l:-/m6/+lו韼\T2J*3!)y?_`t9;L!A99h6HmWUV}d ?G+u٤( 2Taß5&ʠ?"\D`5!Yo\8ȟf#[;t]gd?Tʗ@)k J:3PKlHOTƵSSAFV e{zʐ6SI$xQ*",~C@%5ynB!E*v;}pTg  ' ~:tZuaskT /yArrꥮ NeM?BGզ:,z!t>uQ>/unJUum cD#F Z3l7ޗb%ƑmAKȵ`e*}s0i5e.KώF =l&B|޷i7)~Ƹ<12gi7 筠#qqwoZofʬb%r۰7~O;C7bx0>#`.]A0*_ 4ӦO9ʡc_FLT\q[x_I̒B0euZVGMDHhl?z6*[ }Ҡm[?B ^6?YL<`yDsNmR,Xh&یhYRI517+/92AYJns=Z #P4)۟z2o*ݥ 2sk77UܨIxAlC ,K>tq47(ӪBČ$NbMg8Y.A|jYl1sV&#'*)5c t"/IwDħ"PvH4Xn/mQ+Ѯ_ یim'}rJ/M3inT2dL$u׎ޢ R>Z/!Wΰ@4o w؛1%w撬u~"_ěw/r(֔uݖCud)šZTw~~ k7v8"t2y2l>Vz[I/H'toOpWv+A`cHvA\VBd?$%`2.W ~ 1kC@:n+ŶaN̍:hQSy}TDz~3>Q2cDZI}%+e)EoFbڼ@P@kD}i-/|ˋi A^֝7p42$=}jHdY *h~Ǚ45+_u]eWDWzS~8*mp@j .Zp5^ڥg4k~`CTfs$k/ /qQ96 Ҙ$p2t,P= ja¢-N}dЙk| $%v͚IW܌ZN9;uhJK0nW"o#؛/u@ 9Hiފf\ROK8s޸/if56`/v$LᥠIጯUKl(Lb/SĔJxB u_˼$\L%k|1읧Br3/GaR0UN|K;Q˦?8]DQ^5wu]{ҋWZ3hq&<zhkl^Skr1r6PxYxJ|VN/l}+Sؠ0]^@oQ۔uz9J)DKɉθC,muUqsmt)hYhi38;@'Y4sKjl]$[I)< *6X~25UH= j P@7sdԝ;#J;R65竧=jbw-\ 0ZaHJTgfnS Aլj(,[==Ljd$͕k0)r *:I'9PV@Z@#{r@Զu)og׷pXwn.G6|?F=g}*>?_mNNw_J!b y#Fc$:1Aƪ4d5ʱ}qwJ]B¼Ksaz!.j[- +K8m}e"҂+WIA 0JThLY)V$wv+ —ңQ2ҐE 3gFK!5:-2RVf9EQ VbJz7cTF? {9MD(H;^7IțAȗf2KCND!ާcS8}Lq~ *0(z$Zry\ӡo`W WkS&a_Ɋ9 . g` %S0sLd Jwʬ+Z/{ ]Ȕy:L'3|| H ըQ ӓ+p9aus Gq&Y\Za N:h7d -^a;&}]W|tuVxxRpd_&PS7n@-eF--pz<)2Jx.BC1A6P p&⠁HIYȓCq_0fet(}O͑Ǣ'p/(V\I6̹dP6WxfN=8QVgjӚ`Z\1+M~8hGIV)*( 0= $[EeN:p%: 0Z;HeM_ %ƌ*!kQDɥS@6-☜^mlQIPus9Z,v.3d>)B uԸ~+5yFd '#98c+zqJZC܂OL81|5o fi4dP3armDyeK3P{i_a*=r ԄA<4/sfNq0nfW5~ iViTkCF%.*|3Đ]^Xu@m .|GpKֲ`\j1)K 3v1ϝߛo'`p)@k9S*^4tu WӓLb%V%/`Z>D'Є̴Q0ck4 |Njxn=S];;$B0WMVmZbCs8^xcz}Qwuq h` @uE`xl‚/k= 7مT[AU~6̣gsR0(^h}dF]FpY\0 j7/WvmғR konx_8U׊%pRN#m&HѨ _c}+Df5x0 ߤ*$v9mM5 UBg櫣`3[g ; یΌ3A~i܈Ĥm.- ȟtD !%,86E~S& ZޓquP#[u4Dx@FTWӷꁤvErne>:9:mnjtU Uӊd`h ) -5nË)}DQ r:]O!&F7aT\sgeZYr%=]D7$|χi0K1]"jvጲUҌtVjO b눷I/Pڐ?;i3M66d=D>"3Hrm?Fb YXPnx. C% IQᧂC7&,+LSȠaҔW-#-yw%n0{*|HpΫ]rD%M$ЀgcK J>0Ij^rS|>bLc~OkR-0u%ݾ29KGH:<'Yl;>x#i(ȁrXܾu"8"!]r0'卹,ChnvY56 &Efīr!_ثQ]3F3"X =nWJnH3#"km[![ % ݡ=A)B%x(z3 @h֓(W!Mb5+;ޙ3g{HgVholPo c/ʢ$8zj~/H{ú`eq}>G ؠ3j湅u,6+Ekݙ *ϼwcNӁX6fp@7j5EscZƤgx/V~/;.)PcN\U:R{bKYp ڙ=cbޣ6l#~;Ê!;UN<t}WUj?n[Yzⅇ(Lu8*r&R]5je ,0Tiq׏e7u!wQ dj>+svvH-RF-O cprI t WQAhǀd{ UJJ?wAܲjV6 cz P̉%@ ƥ7$T^rw(lULdŢ/$ۀ$M!->< -F 9`m!wsSKO\xڐC."c(a߱i e'>1g/NiTW6^͵}tJqRO`g+5Mq`q'ןHG [+_|Q8ŪaJ[)&T=K¾}"[W"JVF5)6twn1)oC>D&d㊄?ج\F^-֒Iõu>cx.[U:@8*'qcq:]wF"14EuV>MP(okv5z}f~8{Oh f{ ? ^W)T A^nt=!^001x|Ɔ \&']شFp@|˳&zE_C]ȡAtTzfXңnVJ;pZF#ue3<\R?`Fɩ]ITA{_@Q2d뗵d=jJȜߞضv4"rQc}C` R_9Uga0FJd:6pM6.`4cԆՎJ?%/U r#mvz f8M vN40B,S@ {6qw'T(",N >e 0lFD2!+0 `1IYV Yd(SyHZ6Q߽j5σ"F*[$X (t={mZ? xuL%G޳x(Vo0X{Ke5taoJɋ[&VgMKQ<Tխ1osE˒J(>[y]hjקG$P{c(]|쮠wUy@f^'gz0x1aX2 cUso+6y(V/LeπJl3_o:^Ov~S eVͲj7 Mpv*#eMn(`4NԒ>z=g aF\`T˒X_,/,wlQeB;OP㠦Pc> k-g=e5>Jt,_x|΃WD-aϸ Z4i!d󖳇"`!X_PO?>C[c#BIE/Y) :(Y?o~yp4u 3Ϧ)%mD:PV l߰02e+&2Eɢr'И MV&uȀDP")49ݷXQq+*vl2ʺ;Ps{?mipٽ+yqPM¯!UrXLydžA]YH>a?Lo ER*Hm3:nv-صB-3뙝@ nV؉ Pbn[;@]ךbt߂щ^QtRB4[Ѳ0=}%:yqSzdʹw"6P݁׋hP) L 1'jLe( ǴצH2?n<d6FWL\Wϣ0I}էmaAy3%Y˽xfW,G߹{X'}WBFJIPmB{*˘C2=dz"h%HO.'N\$K &TIKIб) jƎhG"WR^akINfo%|çB_u ~;j?v)*gZ-s`qK$ 9}vƘCubpώl0-E( Ke2hYL@p% ZGՄA`U3|pl Zm~Zn4R$Л5K<}f~rnpGD,˜#/ Yht[R jo:K4ڃoAP1UޮMgKy\ ZȆBgi(evQ ++FS n&Sa Yli|luxdzŲ;ZeZQ{dGp詜c>vC@rusy]cFlęT1duޒ;,Y$墶Ӂ:Te@_E)K (iĊuP|V'ξٚUPJONaN0Q _4U#1_L ,xС~LNmNȩ0Yc>%^4BѯXu>{4_E2Ȁ(dF0Or-_ TdnG0WfZkgud a~u92))ct7T@Z6'/*e]9}=u[(z,_0)7iCTI%=\e x-sQ2>,I ԇ茖2@CV82-r~Zz{MƀFKHӈ̪jr=&:yIzq*Vg S!h &1?cGtl;ᩔ,*i+|q THPHnL/U'875yl1Isƴ*UgM:WV貪eC @Mp?ńMtyzе!Ґˇxj|oHP&G?oY>ZQG'W,jܶ9e(}+( 3^ǀOYP-R\?^sgvx 9qBNj:\wMjf ,v L'9nΪ  <<1!nl/0"PYK_G[x΍N]V{lɊwަ,"Sr*}tL$g@Ac9Xh|4x 4#9C&m`B[PXe+Y,IZY8"Ua;ѡEoPF]/6vͮ>VLBr1O2~w h*ꢛfEOSR&WaܟDald_ _e vM' |֑ҫ-&NP ;FXǶt?PBtuiX[k¶zTYf3w 54kQs/u`FXΝbo= Lg?R:_Q%U'` pUkB>#s_B䗨ٟ((`J-Kw3OQ wWnvrfd̵+8F!&}2>Ʉe`QzNkuI44?6."|04Al]8{ՊkBqhΜGY+3?.e_W$-]+GB=4~ d(dZlm (D%Sp\r1UV2ᴃU"dvf]uhs>WZoIJUCv4Q^5>4)~WFAHP̳ה`44 -]Y# U(.us2t9M뎕~ 挿KwaAI!]d~%XVTT`Hi6,͂*Yk#z ;~%TN/>(4 + iiDJȜj; 2'PJ>W-'(fJ T#J8¹ 3<4,o?uhAVG _[\25/ B8}otoyjȐ`m.sp$[H[\ iyZn}Lχ]A |BLsO͜m{RŎ~hj^ɨfVKyX`[=9B 8Qd86HԀ䐢j}psd82LoZɴs >|ϑ4 uRH߽ypsP1iTCrbֿ p0+M͚, A%n$+1|]@Zla`UΓ#bn<>A1RDȯTZ&vbbJUš};Dw4 (ϋ[Meж6l'C?︪"6hlnK% cx/NB6]ēWd뇏 l;vvmOčaza|) f!btM2XwnOYro膷A{֎Qm=+1c~$:HRÐ3cG\%Xg1/-$D)nʱaZY=QLu_YI\4Fkj-QD!ZWIkr۹),QBZx vҦ՛ t[9u-wWa`":0w>c*NkcYC;5Zg_o\f-c 3{7Ì[p`^Ye 3uUPXRvOtq҉Oadecby:o[;˒LBs$Ts~u"$-bcca ~F |I)6-c B+N& pV wEy$q0i!r0oǟh."Y ;@FtGvkh9Wq=PGWmU#!J$fgIrHd-t duҦ!EPxWИ]`?T'NՁAI /P`G.zDQtߐul, +Fy766몔>~- gso˛gרérOrG38VPqeŻ:Ř~O%Hg9yaqowB k?ًuany:KTdUlZdL-~`0T|Q5ʣ_X'K xMZ";ѝފV\W tC=2j\: *肗z/dn1!A:oWmpX]]Cܿř~Pف{;2Ļ.9s6H`S  o 1N# ق?y3a줁*(Tty1Df:}P@hf@B酕o<7CoT(:6կS Wvli+p|ob "kCO\3aèV WC3Y%? Dx7.|~=5_8ͳl]X8Beu("D_ߴ VC81mTbW~Vu&ϪC#.ʽIneT4JQFz+Tyֲ 6AР <PD5C3[kiq+.yу11&űH\y9Ee9-+~- `S>$Ky IʠK j%⶿H+xX6}w|;eۖLfu}C$d&T"WFLq{#4TփN?c~#>S8 +6Mmg;,|Ptх}U{ѱ>d]Q% 0)(ĊMQ^{ɿ>g#?ğ)-gBL{ŋC>Mm`ujSS oaAKKyS~ݘ9@Za9GGL{p^=@llT)jīo P(=U/@ǃ7C34,`RR䥥uR}BmؿG@A":p4Xb~8#Eg|sks\SsZdbdXGn>y5?]uZC}-꫕ʫȠ䚋y0Z[-.> N,$p*kk95xM)xirFaU\)*A:3s1{dY=(_9aRK)/J!W"R, K8ܑ=킣ͳ% -1OPTN!$]opHo(Aܟ1 a a ^-ñ|(ǀR|.ImT"l":Ȏf9?>, g#qhQ܉X}ǐF|)^>3Ԋ)Ow- ;T #a&_0kERd=;^ 5o҈!{[ܗ,Ev%~+9ZAi 5C0Tk nb3lx).h'`()SI ax̪X? ~GSB~:\ĵJ\B@!?F.ӮOW7b[A ~\.~8hj-ہ@ ;] :T$q]admjY.kD^;ϛC(dPS!D7z8լTD7LL%GyAh+BVwЮ\NN'Ǩ ); [n@Y0"!U%@9?P-Ena)9oj`IJ9snH4T<醢c.yi ²M\~ԝO5n)m;*5n}T{jRHh*|{NZ+J!9UoʠC}/L*iKcGQI9Ve-eDs# ;M'iev뚎|e=5tp~I\8TOB![ZUuFM8C;[RleVNC1KbNDK2Xg=U}`٢W4r1M(c*m^}K/ xiq2ID|\iEw>$L]ti՜t IVf)&tJ:E| a*~Ñ {s,J3%M\@& ]{G)S>ڹt,o]iPh1h_P~b/ j9-m7ϛxNf1r-TǿF62lyV7xv'EmMCRïc c#TKm\"wG ,*t[BG18~剜k&;$-DȚg&a,BI<HhXPZ;ʢ)~Tǽwk.2I T7!bÆ ^b}S=`D;& UژȚi%hB 4ʽI^_TETͺ>\?S딆:pNKr6h}kbG.X4.-O_C2&AuVgys28ߕ:*˔h0~@VsukEynjBVGE|YkjLF%ƨWқ-ɵh \YD),l6wEPhSW)@]DS۲G_F䘀 lt}mFS\dAs2^qŞo<@PK !b0]NJغ"u/Uqt}P81'Rۗb4z&RB7g!+eL^] imJoXǠ`o&)N7;*yه&\YZPxHhA7٭ m7HLy#we`✨+] \|}tbn)QԑoM׽?v%M *] lv':H-b-,$F /8hm;77u$Txjҿnvx֡]Sʧ/\w[Ø]#,+!XI^Bd 걁s -Cԋ1r]G͎vq%_kJ#;'mZ5ONP 4yboPQܵᤴtf/^rF=SEZ~ 8 F# 4s=:BZE AV$4asr@urI,"Rkd{";kMxԗ ( 6WD Gܚt_g'[N~VMdv+TM7i~=_ʼnzDEz&e|jgrl߽BvwF˒R26ҙa 05Ͷ]ڱQ8hn zhAT0@*,mU֯@J;R*~j$ Vv>D10~6%Źr)XVL>x_p JỏLaoIq:7N/a2:)8aB<L LKGVUgmyDU~˗>Lkϥlmҽ(qVf җE谑^5 eֽ< ?;;WxOu)A|a@!):+7ףCnLW-jhN2:emdpV:]pn6^XPE.۫] b :[Zx($|KLt&SMCoN<A!2˖*d(w=ɼZe2s=4KŸUMdEr(* lcwڰ#1EqK/7\'Nv%1jv$H}:Eվ(a-W > {&M\DǂM4/wLO9: <_DySC"))]U4ֆ8⾔Jmem28qB /%Ȗ[ \ΐ|zFJk>ި"6xC8T,Phlnl+g$h(kIzyS3l"O:j0"j{yic }m8z%ə)o?E"NM<]M بk@@)[ t^ }(M M\"sSm)_hYݧn ԴOdKwa3KmbY`uMQF~ѕ_v6'9d{|w0Xp6ʰ"OFz/w&*Fp/%^f)JeC;9&9gbƒj<:uoGFH"MEn.evSXjs<~0r.s['I3}i&r̉.AC f>3'>;}fAnx>Il>OX0Ix uhi:n-4ᩉ^<'OG ۔-q ? ϵue<Ј9V4x؏gQӭBvȄ f+&61FNͻ_o+{CRAP3x 0B݅.216WFKכ 4(΄j,yRԴxkS, 3-[3X;v*䦢e|Ҋ*PƊ3ZdJ}Bm.˖CN:|{A8DxdaO7Ѓ,;H{W0 C6ofbת4)<,,n]}S 1KAԞ2Vp2ˊETt0e7k j}{e55/lۓc| %DKZ99Ivwz߃=ÄA@ݖс'oukZZLwhJON6&'C0sA[?:E;@IsJ.*kq]e@WAE=^xrnWj2W29͚+O|8KGe&rn,lbyt-J| 4%:n[–qOafP=+\2*&mJ4Vմ|Frh٬N6H Vɖ$jwr(D0$G z! K@_0K ys#Yμ1)H(TZ.Za?*x\w#ƒ\ǿ'Z'*W Qѱq v$ =gYAN+9qgxBk3C&+}gn:DSL'W2BV\[45@BuAIOzM(iq9C-QW0 0Q9Iafe/Bڑ2%2C퓁}7~`WXK(s.cɈqc\@ZG0u*R-e0B8NtR205=O~i;h;@ĵujb0f6z $!֐Jfp0ontja"\c233¬E`=D^M,ς@MrS[(fPj?Cqx@H;`tkȇH558zhB|`heBظ)Ȯ*J`u]8?cU>|愈;Pc}g RUgQ\&`X9KI4͎}ϖ5ЈΠĂWC vb!Ǘ4=m@+@p Li?~ݬ5V.uZ8Y"Gb_9QO8kL]j.iV: ȩ۠uVgw"DwSW &+N9cFX/Wx_~ [k橱ٖ&z!r"Kjo AvD]oݠiĂo#ůR$SJ}N}{{Q2#*!H\'t(M',]1T503zd=Mf\l nS.3(bF8zBUɏ-u&pG(5 @ZXmy?25!!a^Hi֑؈%Mƨd+f+@ ĘvE>`E? 0pt_T'u2< >RH,2~ޡ.`ۥ6%.ѽN])hf{(I jc|WU6q: ݷϲS|o#D0 yC YH#͸61wKfo(\T>WLB;b˾dOC{aVcժF/$ '_kw^b9+{} 4v#@bGzbׁۈ$5DienCǠشqadm*%BŢdSuamfvNtJRӚ+-AV89Coy Cav$ =fNN}Z q|:\l- _|\ ĺ&޺Ի]s=_71$1G:G۵2Yw5 -6qӅ0 3Hh1(LeK @}} 22V'Tui7|R5r%gh?(=6(ǥ R'+W(l2ޙAi>/̧2!|=Tʞ5=v%dqh 9iv[F'V/Z%•b#MObQ4_o4\ǣhэ*N1=f 6]HU]ÅsיH۸pIIt.|k'%hG4'GXKS k"j & rY<iWd: u>@\s3أT 'Q<[`<}{#\j{r4˜Q/vޗ (2,gBED& oFa MnlPS]U#|Pt{m̫B|GI0H$4D"M }LA⬿YHK ^GJ2;zKV1c*oqmz;D{7D9Dk#j^]N#M ?=>DNbB&ڦ)IRUpc"b|Z.dlp|:PԒ3 2s ĠnEʍ b@'d'(9[ϧ'>Ph3z[vu_f|L=}C`n`V68I裦D0XÃʘ?w>E /柊9sE9N'isy PX!]w5d:<f>Zd:pQb)r(TقQyOΝҘU{4+‿LGv4l9b̉]k`t{lp۲faScu7YRr-Bħ5 DyF6BED"ա$s:,01) gܛ hk۟ڪȲLƊZ֫sA(>f(Lɲ#?L0*jaʮj Dspk0]@­ wrd8jH&2D}k00+6E>BY>b@$(j6רWG4mP~ ف~Em'KEKo>da7+!F~C,,p`|Q,U&%_:DP#u"T>XK1p|vS_3+yG΃QhdxuA[h,xRF!# y8ǓToi@p\ ^7ce^W*Kijen^R 0GJ#/,<,GI1Y !B{z $NɈc?\k)Gn_ ѫ[/&WKv}#A+ٰrK4l&d:b9;xV61O܄T|_.`4D`4?Y^yS*ܙ|*(#4 1C^ONY5HB'=l?Z|)>~Њ5$8$H|1?_Adn+AKv"Kʗ>dfa)9XZDy?3ӃRM9CãR Cd٤jևU}T1rDP]/q>aۺpPšo\5x⛋E'56,,u,~>5d?=S<8@pK.&$5T/ jg 7j&y: ?Zd-C8ORJaxRq0']A;[zRREUeOs0hcM}e{g`V"d.vG{-!G;Pkⵦ5 :,dqqiWGDR+[f*p[5W=oC@mh2ɧ;pew nıaY%-Y7[*LS1LpSMuAtz8ҶΗKY,'8fٜτNFYޤ/"d{* 㗽0y`uxTMee[O/FJ~ k2fcLƳH37O) (ǾꏅBe({&A0 m1T >cr 90gmj[_p7TMeK|N5(fI/:~%u@~5$G}AG,QT1;DU8 %ۮ?LW!r FڒCIDKIٞ2ε|E%FdmtYӄ,% YXOkήx ihH%-=,*1kMYs"&§mTzX J`؀zC>jJ8-7 kQ$ E>ok-zy$dX>ffd,MHpgЇ->A_yH'Y/xܭaMKޖ¹J܆pRA5궜9 7gU9 A.DطͫL8h QY̗âegEvjS m^,HPc{C%5ˇR VIL-hio_ 7|;"^> xغ(ؓ`TQbQXž " 2 =7ec.TG8&mI >^Dtp ,Veߜ5 {{M B֌FХ=DM  5#t=5~8\՘NEU )\Wt dNXK<ÏI UGhɕ1D6ZREea̵p lN~`ja{sWeҢP]É (X)S0R-8 ؀< EG[ټ[ؔv_,5ti$ 4eL*FWq蜒njc9TCrqHV4g~L#}_Z\ "-7:1GW #wmp٩Oĵ v@"SL]WB@@*=D @HJ%W/Ɨ===X)=@h f=7M\حI RBVsK'hq!qy " *$@I($vɁ`H\{RH9Nܜ }Mݐ.UHJ^1#Y "vP`Ajdy74Z{zG[ DB9mCT~+ (cG@So]:d?X2;K .wTӢɾPet0z .oN$sхW#K2ֈБwx *N  Mu>e,t)54,@UNiE!U1%*GA@ l˿faoIAP S&&$YjzCXG VRHMdn~\0̧ڍOGr}5'VҦN6Կ7hs~e'"?b?z |,p@QxR瑰A`N1u K1p/J\P'HTI?GyS *P I@+tDk%YL?akر&.>?LDo'ﺔ *R-"ssL.cW~uЛ,3d<4/E |Ln>bY>Qg+<̳+DR3Dq<11ϛRQr\=y5]fqMBF)/9ERA⌑̲.n%FR1ȄgՍ}|mlG!Ml1#kSV jKh== /W @DkP%9X1ꝁb|2Õz>I0AU2ߠNN]Z{{ыFlE:g|*FA |?bYx(uw>da{4*jequJ,JIn\P[2Ypi(!VdzEKRȍ$z=QiV7NCF4WY+F@8! rsL@9E>.GKpwԇ0qȃ#hrno#@n.#>qXW-"hڡbhod`^ ͚̿ȭ>VWA)ʕ*HeXEWp4u.Ģ𙰿"&'^ U$!RlTBqNXuyOvp=~]VC- 6h"Y2Ai֫+ 줂O%?7 >B+:,ӆO/C+0QV7 Cw΋9fw@ZmoDEr oΪUC'{n ,@NArP)Ĉ3r7盥:DT݄| l$=/I*gjnS$3 p™6\bM$JE6+ Vh0u7*Y}[OϷΓ[߳t@ LWtXE`ܬW~{W7\W$dO6/ڜ.,G|e)Wa٩kFUt;gQ&hgx d%,\Ҵ\[ .T B&;rl8/ 3h_(4aim"6P  ~9HU[?ItUoC 3zmWBm' tpqKpf} Q܌o"@ȮH;BL#&>gjs"Ֆ k!N#җ _wi}N m_jYJ%y!uR/E~6Ԉh zJMiWY͔O.731#FI/HHB˽@^n& Uk\*<Y-64}*6[wu84:ެP| rXut80<'6 > ?I&X-Gjҵ&]u&(0Me?*cl~D1=EE݀O23@P89JE67A>8G;bw S:Ly)]08m~Im'49s-k99pəA|cog0Rui}ܪ#Lbdr׍ qwP^י$Yy> aZ |hL1|*?ֲQ!v8m]!AÄ'bA?}QFHQg{sL-FqV}h5:cPBcștg2ܜt&s9<[6ڮZU;H)&o',W$\\83F@~90 ǔ]Ryul3p?-Vb[hP2Sڥ.wrRlq">e+_hı@1^̱Tlx"H?I5J7b҅*mW.7GYufO5RX%|n<8|0A]$(ZoVFlT;ה8t5$(Z}5)qTpG2rӃ(XVb\f8Rnd^o*,AAt]n{Y%t:BP[MRݯbČrJe͐'B5T8@=(r^W%X iEM/BMxQ>R8*~ F@;bYit>=A^g)TC%Τa xu}.riڊ ݍ@RͱUۃъ!dd;Eoj%9,m~ˇpse/="U90V6ID}+{8 ;N:X6`T NZ"%`@ G9Y%BA(Jh*ZAÃrW^P>eӡւ;CژP(T0" ϕ)$NkQSҖ{nz|cxGs̓ޥȼ@]tOeK5~ѺݻV"@>\gA_ۻr{ybG&3.Q]qW%Njፊ6t~t|'C־ Q 6,>y8o+<€$-sNخng5&u`׶rT.}΅]<]_okE6 D38n^x(k\r!Ӆ%q9 ,L3QT[eҗrsњ>nONev/>B;}Xt!Ic;STĄP"0qI$i^~n\ސFćo.Ny6.MT'2:) 2r/Y铜yx ncH?#zD /i[X)ȋ Ԫy?vO?PAېm\FW:H F̻u?O'r^MaU=mrGr|pK"ncl># GfLg!T/G'}iŠshe5VȺh/w;*F !&Cay\~X00 ǕٝbU#*2< . HYVMuY8crgtv6v렎LPcsm<)!M1sV踼N=:Kx:;6PBS%(҅f]cYTQYO[ȇ(},PvedlCҬYiDuTbXc=(%R ! ] Xm&bQv (͑p06Ntяpg=أezXMk "6"sX.^= wqckC3YU&'omAZa؅& -ZO ]?ݷqxK5h"؄[1eMJ 8tnϱ8맂"umЋAHt`~};Z5ڈp-LZ:D2axm/v}h@cJwy3džŤ? PE\g9G:*nl^R9*.z`1ާ/c+u$M4НQTݳFؽo]lམ9w]MOzx@ h~갰NiaE y5 '{N<"M3ZNI-OHU&VIGsx,ZwgQzx}&ͶD[-/flPDaݙSWS+~D?v9z%j4ۏ{A K_7)XR+<$qDuRL| 5ܶa2#A ?Y :U_8k Ѕ Ts|moy;5&#~#!Oˍ[`ݹl 4@*OO{ky1Vnxr!'eS,rq,24gYVRL$˓ODeSaHe)*j r[&D & vpTEZ,< |rC;y;0T%uJ3Uw+b,S\"+^ǾM4lHYio۽`*j_SvMl"IH w# @3Jos@]/IovOLLh |tk[~z"Ȱ3YoQ#Sh;gΔ}/d!K!, Y]_V[4[z]Tx g;Ӌ^CWF!^ v[wxB i+PA' 痢&oD0D}>qHu5EQ}]=Yphb/f1xOq-lMd!]Bh테П Hz=K"B@rg';v 1X4ﭰWخ_WmF -Tl³]B,i20񽗋X aY4/XKd;XW6}ZzL UY$N&k ?2^pӓ/ \ٓF-3@Ckm|ڝ{CQ\,[[-`-4 fW0UIQ ~v]}gw-I@~ 1!}LXe|Ť1Hx)ؕ Us*$6\Ӳ;Qp U 1ZDT8{UcvoN*j[9ӿpx6c=^WC]~bB0?x}) ?10Gl02݉O_B:=. 'AFAg_JV9 G-ޗ0SͲT0μh3qg2Lޱ_LdF5eFjތ΅50(ie]i(01nRb|l/oH_zrJ3=,9|Bwb,ĞLU N(G6x?oDCx0bwCPxpl^ޡKy_4OHԈMX*W@]^=DR~Qqf [ Nk 8a)E)1s68c`ĭ_F*рָ]lA qz[WϽIgWKo/Iؚjo?Y 1D~L`珖6+yZHe85~r yC[ԃ/;@:5b}'Yk(MkLp9N tSK!3 s u qP_LdT}#:PCe*3<L%9{Vj"q,5#^A(>ᶣX* l4 ^-i%q'EPt|E2(q\%vzlZB\5>ʠ(:1My+;Ssqm'c)7 \+[U$dFKN[+EN>߈ ;BU$ ce'UN'[zqIO_SGac,y&DQ9 J?:F'.g+V~_!}`ia@ø3" fk,w&c[N 4u̾zX%ք&TwB[QAvs GåsQ\f%PO-uHn$z)7KRFtIjɑQ-H{ła5iřNOX=a=Pg ·0oG dub$֏9攕Ui%q~IN2bKPn`+et 7;,rL,tw ך0k!9jbz#5V0HzaʆN3Qkެ9;f]:V3FP+ j?A^xbFN$෻D)B!nxeSMĐ@Œ]9%$>Wեكގկ2+3]?Wicwx ?AXS`G$P")uJ4e8,bn HwAfqܖᨡ" Zn0hg'iη:WJAƌcVn?ǜA3U[ ݕ:%W/kt iV,zbcdR'cB슗l\l?0H& Do=&g$)[953V5#9>^P,`N_ARzC LB Z v.,”p[*ޕ %;D~ʮk!f{E6+WfwWSQ' :}Sd.M/sOIcE#n??*dܯ [pe7v\]f4/9=zkܻ3h^DJRa][̸j㷭] dL+.PAqx30}%Ju@TIN n.'qJ/ @EL! PNv  ۸tS4#R- V$F-0|CFpvm<[~C8 νLUǣ? `dhUd>6lD~4tlrBINYW^ǪԏX:xE ꢻ7,[Ewlb rĻKåc[1PwXihиi}7EzӘD=|(})l_gl-_R a#WWBxOmVm\kPC*F-oo$"9b߽Xx5mb(S6[^%|j ? M^xtIYw3I5.+Y;]E,\_@pID-!% aXR2KZ;ƣ==S-'h'zNc)rEtJ7Q#ShfB&VfۖtOYV꡽ Z,n`΀H?|NȅUҥrtx׼nӏw(7/őQ/ye:!R ͉HWŕ}b?.ZnGT%hq31® E~ !e ZK#}t(sPWr(t0 E;{ޫ-R+vy͝nDFVFwoHyVy!GeYn|1t(wS5/RNWiq }"oBglO7J{q%=ۄ(A\*^\3ڢ1O*Bw{oBu7 {{ )렦t̙+lE6v6{!Ǚq=2m8h5kJ E!]rq9{y;kKc:<}\[;;-_pk=a9|ĥi[iSsnRm/xX~Jj}IÜ+2u*ϛ|"t1385*^CS:hRr걲7{0am 6͘ rWݿ1t| #Mcd R <شKG<J6*-AjL^N–;~ %(IHw6$I^., ԰܂O_#7_p+]տXk:YRW[긼z .)*J{UrB)&XA).'/\4buN]WHTv}] o0BVdP#ay ?p{=FXTGBWpeDjxΧ#(~47/x4 R~@%?c|{8,Wë~0IDm7+Ɍ{y.UZ$ցNPpmDxC1~gX&lno;`vjSfߣS+8݇;X\R87 ALGkڔq55\ED.ސ~\VlAv %d$N)U- C=Y&:@^y~bl Aӥ~Œ#8Zs6Nt0c!M+PfHl3N/tt2YL ,bkLAO 04h]rY*0 }ltt-ݗ۰$/c}yhrEh萏W_/^Ӎ"۟Yf@2kKb 1wª *NܭX@ g{$S4g\6 z#aP|71د|Rg} AH .L+a]W/mba`|EFG뛓,x:t0ݱI%7}#FqXSHKs6 e5Ph HVZvXy7H(Uժ}|JMSuvdQ?VNh؅@T*m@/t]9hIAIb[K#y|9m>H!ɱv FCu %x2[Gfr:1FH 9&ƐKm:Ad)&Q ~X8/+vVbƘhiYљ/oheD&=pZ~@ ϣ/5L59٣7,>*k#lMKQ.IcDG$n#:FN|SQu>)# W1NkqL>cp:mY!;kZs:<Ta" n^O}Z #5H>J-&ݵ-f 'rs\np*G#]^xg4{?hOV6TzhgD<@OMѫM!xďυ _UqjUPS0 }n*޳t3[MfSER;4уJK;H܉ ff`+]6;PC1JR!S.<995* k >؋{?3Vi:dT<\EOąئv8HuÙd&n .;&Gmmޱ*>]m0hjğ36 ݮ%`6Yp RU@~B|bǾ9"AƝ'A;XvԸ>c!f@77Ԑ AH+]q7wMrRK*Qe"2q8./UD9vMO10a],83k'}b" :^j 8*W4n ?,R'g ;q>0 Ɏ=1)j>}o.ɫsz^0aݯSY)ڗdn`KL0k jGOa@OXn$ۏ˽7i`^=qy;Ļr}7%4X2Ld)!~OdcM>hc-A[_ӿ97+fm<fZg.cA0&HwՑܽlfBURGd>1 |'(>L /47Ob=ᱵհW 8yH'N?’ٱ WLL敮?fFGk[,Vf tJ=c>^.}X ڰsv͘bߑ/X>}UDQ_o6HOQ >>h> VDQ>|v_qQi,+ @hGH#е'J^$^s/)Ac Gݭk~l$񭰅 Ε\lg }FF|7""'ؚ]6rPgu"P{s*,<[>5Leq&BǺ,SFxLB,C.zrM~q1Jg򗇨C?#dJ?!=•mp;F7Z e.V6wEexݕv}~ ˓] ̃f] kxM[b\.~H{ߧK~%"Xx=[Fp|4"PKͬ᪼gIyQ:_DHi% )A$CG_Mۍq*aLh(Io{uNQɑoXi+T`-~tXbPcx0[]yU/͵}ʏo2($3 #"θE_)FŊ[,QJpԮfx}ihR VI~s9:,n9=`m“;P챀AEQ-KKc36AP\ ϙ_Oop ]$ eDUȅWjk?ÿ2 "㊵HyV^8 t;2Y( P.pӅ12@tN ٸ N *o27eAr( +Yj̴,ݲ@HO80hPv yǂz':°!W֢m~y҅~?Zk(x$qUʐ@I][Uwcةp$&dbo9&{%1Mȅ1>dTjGJA08OjڤSwcE#J;7W1!m_9HhǧumνP0#R頻;*O/*nmZ2AP8mFά$¨@D*g;̰O-ND"㐢-D`m(V~6n šA}l:_@ӄ]P!wUvG\Hg++|*j} YO갼BjjFX*>%nx2ݍJ~}7`.#q_rڱpSO]Ȧ/?Y Fq$*؊3Э! UghD$ 1zf/yZG<0],Xg95/.B>?@$: qFeݺ\!@NCjE))! ZaL H!垆+>5zkMuq>Mv#-D=5?ir&bR #Hr_lPd_pYuWhͿZq֜ǵm4dZdFCRZsNP{ƹU44/'Z/Cl hpY[$[wLʉ Bc|&ZyKO /B \T97k19.so{YYp\54ƬNk_TR *ʏm /E|%NJ,_pkm?|Lӧq5 0'.ifp!N+ٙU{.Oᆡ5=&該%߅wYDwL oTKtaXSlx 2RЎ1rt6pyk᝹?2v#+e(R9J;hb:Kc0blTXK\|Çn/H`ɨ&=RnjpU^F-4I; Fz^jNZeޏ"Y'22=\B6i = Qq?0E8,;Ӂljn*~j脔HbU#o>)_gd*=]`SJJ-ѤLǔJL tfP't a0@lA ]Rd>3ĩw Z* Cy-O+dD]mБ/鱒\% &90L]-ŗJĸL,/; L+T2Z'rf?v+=PDX-eڳ ^s#c^]8Nt"DGJx32%i8HrRe`/e'ݘ`>.ֲOU Y9 BD (PzB ^'- `k&m84}6 ٨X@o/pBD Z\U]M*;ˬ3"ʑ:3 7R Q}@M;";y !"kkbFۤt5H&eO_ YY#<]Z˅k,B?o((U:=?Qɼ.u=F3axj2ℋ&\֬:@2wC:!LdE5٤V|2&|Q +OyVP!<|JOIMs?5ۈ_?(`A$i1~ͫq3!, -jn}wXwv ;gqJzHn\=bred۩e/-,:,i$av Cv QŞm9#JYx׼?$85D4_'Tkj5ϡ;d2xT`P|_ʨ):h! Dp~OE{ c-!U|c fK5QN:-߱kƣn"Y&tsgI P5yFD^q'IJPKG Y6+|{l$}bM;_PX%O" kD1)B ܅6KAbiwmB`]l'A4 JԄKh7bcΜ Ϛ|y\6l<dz[>ƘrTכ3(52=e6Wv эL_8~Co!X3U6 G]FHR "o(^xuLT )c&*=.tw"K2~z$ڨNRUO _]"X٠W^ D#+$RGQAwd|$}}F$bԌ>׍%nfn.~~ WX$y9oޠ=:3qQlĖ< ~1l*/ui2kƙKOx}wr}#o.ݦP氻 9By!\F̈́#>\P2/IEJeđUSnHbԻ` qLnl9v-ۍ!Q&*2HtXk%9a/,(v?Zޝ֩Oހm2 hǭb[w>M%rHSl :u]Q2'~&Xߩ:!uQ=T[q~͜Ϙčre068ˢɾ5PovRnNL"G3YO4/O ?> ;:gE =w 󻩜\Y18#2AL(c2ښOj18ALma96!=W~ugt:#́^wJqd8_ #2 h?.wg@:-ЀQ&7Ku*uֽK],578m-s!XҀ2E" * M@s a)W5" <@-OӸ}Ym "XhFbp/"3\Cz~~x|evny~(UQ+)SMKBMW*xbNQ;X#`겿OFp{lHTɢ> vYʜBkT "tzPwO7'Sd`rLUc^]A2rMBD{Y]>R)ܺǰT8 +RQ6G;Zƍ所\JقLsAJs(/'j%O;d^-cLAE >$"?8>jM<Ѓ=v|>1:7qO9 DUKb;6hĖajp"̩9\r=qdjR>^0">cIk=` ,_/ٞZ6W4}ƀeBs(#v]RlsdRl8A>qTF~"8MKط橇z#5gARJ6|ImEMbbvl e0drWS  .( 'Ex8~拔0f?a4wg$o.e5ױ$D;RH`YD…:;k~k1?_ʱ[A\g<㏴zC% Nc8}aPaÐlh6.Dkod\?N|:ֵH40o9foO=|mZMjLZ`mgWXz/^2D[\ƪE |XnWN,6kJlWMOui'כ[볧HB'"ݍ*gf9B/{bfjҘz9x FV{df/I=3Jk+\j6k^+txIkǞ/L}/`^-=S~nFIKp﫟` H?3rc${/ ??x[u7`Ytۣ]5\}Cvf`mF4`DʞJFlڜUK;Ѣ@XcItcoUB)q|Bz*D1r#55FsUA\9L<ɐnM< c i e4|W` ^cyA̠uw^d/hm8C; qIqŰm9m0' LaJELJ%IX}Ҍ*'[bjIl7<>rNZOU/ȰXA3s*1zoAYs*x]v \.wcyM) !|!ta<K@8#j YrQ(B;F܅Wsa4I(%Yڱq4s ̟hc.`c_-k1ބ;Qᬸ쏞xvd;"^ҒcZ!8b2oQ^cP# ~Q[sk :kҳR6jGR8psS)촯to6&g"CR" QtnFTKcn-'5^8炓Hv^Z[ |c, tjӊ5KWۦ@©iOO">l]V;Om߲C(w=ZF q5J%sV8,#!Lڤ${:*nYOfY?{]1)Jm7>1z"`ĈX3L+\ݻp_V/Ҵ䍤y40#Ĝͽ)^[,*$ճlKfߥ7[.GCp!qiL:-0@wE;w$FW=jPLYNoA=aFe쪚%cӃi<+452Ŝdބ\.ej+hyVt9iC$)\$2-ƪ[0r2L+bz¸/F2;?mQ %҂9s4oP$Ҿ-~=\1DQ/ݨc/hh)Ey(u ۄy.L`I~~f[XMGm w~G%[#Д6*kLrXS& |E)p_',T$~gT!T??,I Rh[&Deڵ V lWރ\f!{FE~vTl~= ݓR}'NyU z6oVCcN-VA*SF[oWmNjfz;ϾMkSj[h8038XwUnp dSD.}-q4U"b ct;b5 G_flk!.RG('Ǝfb"7tPt&z75$G s˟d| n\q1aԀ4Qq+T|5{ z S1$>i/^6xPjaKQnиnmُT](e\UrJDUd׌F#V WTÚX@`֤aZ! z }st6'o]ġ3O[G@\Ī(;wBPR&$P*+#=׀O=vl9⓼35+U2P:Պ^&?Aυkkju'?y qJmOWaf U#7+}/Vv]>Ց`8t{%%mxêݨ?l=$Uu cKgn ͵0+a_o$HPP䛁HV[p( ujjYoeL*[$]VhvΤɹAPi9Cf|+p\P?7g҃a+f߉J&|c]^.G)!Փ7a(.U> 7!XѸ fϵ"Ay0;Rsԩww,$+l#L> ):vEQ6'y~hLK|\r9BI|FQocBiG9'Y .ڄR v溘zEQbd Չ9V^cUATaoNFDt; A[M6>l=B7Pô#A VvbW+`>jeӒw)tG7m**9RI(l =_,u鋪 >1v;$.kǫMR77u˔'g^yDPM~oTZ57i`Q+`AQ^@i]n O=,r{Se4?+̖؏,JLh@NP+ ;XYF<]uZ! !iK.(#?(g*OՍsGsB{-(j+ŵԃ <&(./Tgh( Ek܎S=$ 1)̴!cmI0V•G/.Gf;]BF1KU-H]Lnqo izYIiOy7\zSmZwy`?޹fj=7R?l²<?Y>(E]0T9qa.B5h#?W2?[=hJYz %t:bN"̻BȱkR%}{jԥ 9(M.:i2)Twe{"B@eWY䨇FSPTj\_^I;q67em>*83vQuw.j/u@˲ѯ{.y)%)q0>c#ƸRi7lQH=E({.VT0 L:Dm[7;`4 /@ɣS;css"SG3*uet{e}_B"۔..T@bێ5l|d)M<4 |.aN"~ lP0}.ִf^]lrKo`F\.*GGN ; CMEf >O;&m7%^[hArļC,1uQY1^Ła[UlU|(|=!f8>~|O@Q"rtظ}K-$dZF+dPL3a}T0Ws +êzt+Ʊ3:xW|2g>dGOo0Lkڥs#l?KF ObGl܏YOVޛc9ǮՎL}L6<jz`WkY7սRęrYUb%N[ǣP i2rK#M+D m['PP'a]6`$ TC&RzϚ bR?ܾߏ(ٰ~ &\􌄈4j}v\O<6eM>F=d~{~>zڷ L\M_'΄xR65K,J|*KWMZv+D!g8-q{k9scbDZd_ϯ$3ծ]# QMAxl#q,"!2] X̟D-D@rN}F #90 _)wZ3 .j OgNݏ3y>^l;נބN|f߫ NZtMdžHoiL*|ReS<^i( dX7H"84Bd79 b|P?CC!_3&Pve  X3(,|-M;o,1wII|T诌0) ?Xګ{úpo~|2np\5G5(Tg($oBZF=`sfʿfxcEg#FY%@sw>[1! )~lW YkLԐ\+i#l )xa Ƙɸ`y@DBPk al㪨t6Y,tbh5u ՟}L+d"ݣD2 " zXnsS^fwnNfO<ówpȄ^t"G6Fbt$[4}4}qdQlrA7Fi5jOiOO0oaͶps74U^.[QBQZս?c qti8@MQU#+-%\ fE즫Ǫk0E휮`+*$kF`,@PI䍬r&^ŤжRB5tlCso7 q@y-#(u]ք0Yś$1?FgJ;yX D^WHQN|';2SrQL"L!*L@R%LkzM59vdTZfiNЖLa''ICgw~6AGmom*'(`21#~!(i g 'v\8 8%)̃әs!K@[.)4͜X"7w3xL\.u@۫لd뾻&ZQXp_b XhaXlN3-Μн߈EmSQ{gDQKTuxmB}Hږ&W:,Sj.9n%If'.v/ L4vLlV -'ξ uX/OXM1G[(Ce]":08Ub˩:cЮyq+4JH)Ԛss$#i7$)-M[M4 5|SXN'=|xmUѯbfjןNo9sPc2*A}1* ,a |{O kEE-_UmLF啙KL"eJWaʪ$-53To]FoϐN̓q IN:⸮0C:ξr03 Qt>\G5Xd?>C} 93ܷ$'94r<\rP dv(:J۰¡$UCw$J^ g5vtLLf~k|Ot"pL ɾIUǠ ]a~B_"0v6QI&1ƝfODٴ9j$"ڢ&G Ƨv&xXn_LN& COu>}}5Tf'/Q>aʐ*4Q7"Ҕ{3Zɚ.^ Y2:k6[=`k͈dz[Vr%:N1MU ȳ|RaΗ_@NKѡ|dq"JpȞfB@_p'#j 2n%;k;Pʲ%21c/If,C+o];JXh]H>ɧ /3^6uQK` sm\9;_wzs^NdAkt#bm7Pfi@\ZbsCfWVt:E [!T−-=답;N VAv_o>/6b򔐳y;crs9k7KվzJ2fyycwǂO=wjo% ~1ss)0/G !m1i{Jp[ܶ˙Y.#3|3-H-}v%oω/)wZ(Jbɰj$xcc<&nb W)>3B~aifM7Sٽzk ~Пteߒ&ˠKS'#I}̈́bIq,#o.f<k]e Gn /1VAr(jU,Iyzo:9wK[d2Ξ`QJŤ0Ή!֙!r/H۽#~&JWz+Niib~:-`M]l, t$`aR!KL(9'7&un;PQ\W7eժ!ؚ[a޲F}Cr)E""x kWJ'F_G+c¬&Mn!3rgY54r?5L `R9z3b^GddDqd6K XF']=lo5!H⥀VݚC֢w/>3^/2dEƵXu#}Ɔ*`z3OO߲е l+=:CsT gW;Y?~/plBLthGg-#Vsr47" ]RvuP^sWO749Ğ}°Ef"CamUf8m]7-bjYGQpEj*:#+3B1!@Mz% 3xs0+@hDDs 'dCЩɝTz|3RY0,^iR/㦣`-[ p' nдH3j)"VT?Z7OT/sI8Bv~QQ*V* *~}Lyو(4śy\ZS'~a~-6؈@UN~Vq!z`Y돞qWVF%m rM8ey7 b5`u)i|ghw׆36 M[N![N(򋤞*  |~Xd|IDW|6-Ӌ[>C~vռMhM4.51%Be5`H3 :ل#^T֣s-j/@1 ˦\ɔE,߂)M{X.T/Z\Ma4T//aX7/1:ߤ+qF=`"Lߖz|\Gh9Q`"g<$~~s!8[;/8a޲lxҕK/z4ǟI ?uq+ \O\'0#RrJoC7~}'Fl G4L4qu"1*qE.Is-s:$ 94TS/v)QFͼar0|FGm¦{1<;/l[PqY&CP1+U2 c n?`%@)!5'ŸL~Ֆk['tw~WNWeU[ q}#iHu0WU5{)u`t }؎dpDH9^% d["[u3\#´QU^)OZIUV` bQ q}Ѳm[~BܧFuʯgX. v޴=ŕwu_#ڶG(Z ZZB=P jK0构84vZ6 :j˙fԾUdar@s1w[ɽ?0!cU,#ZW+rڞG&ݜ-y h,EBRӼB?:KrT>$bxXCJ ['٦D] j1!gz&1ü|b!_`mVjzQw5E-O`ewA`ڟ2E:;%  #Fӄ|My@åDUYo\r&сܢvÉ-n4%ʙC׳@cGibN_0qU=\Cqb[[yWhAx*{O1.(⯮,{8N}\p /V6$K AȤAɏꙏ"QZc&=;%̠"[քyNB~P':yQ)J \{\=-0}y"+D;)e;6*)- N"+s0 ySF"uC_^Gr&ݗB Si+?}{D&xפH^˫;LAFgr4*!7=SzCϧdZK$U}Ȏ |]JN0ލߧ:Rxjp @s@Rx~Y ŗ҂,>„RW`أ 8uq;&kH\ܛJFM"p(#gب>$;UaTQDUpzk[:3ijiOZC׎ƞo8 ݐ* 4Z`3gʟ򧺣>܄kKK]vzg{U/ K!bB*?R4&'ZCbQxF~? !j,Y֗@ѓ7Y C,gO|ȁg&\;\1  /b @2IdB7DxedxD}xZbmݗ66JqLb I"܎||. ^ +%'さ #к9{m0re(Ala، XI-!#-֩OGEKGR˸~EO3=b : ' Y6 n?!6Oaw׃1w5͔_Pf[lG[M+aKndNE$%jX FaqYttqpGȔ*R:f+(vYV|8ף~C~t?ؽu ang&o ӫUt#>=2kSN os8c{r9Ȥ7A3&2UemtQTB\CGDWԷ]sĦ |^~#ЀtX^{BЕ,}^#zeRkkgN8kr 00E7 f΂C|^/lqdzV O^^X ,_Zr 0&`G=13nAB.ڵ =(^ϧRm^f2ͲM|U,nM9C. R$&+b_+Fk7d ۥf`*Dm޿S 3VWX}iSd UvjQ&kX?f\XNd. MN94;{9x**Iaq%$,Cq#0V3|mK\*(٩' 3N_:tsR;~YGs|sYuΌ^wq;XS*JW~wd ꔩxC%x+4䳈zY㸈EN+U;9̒\h5$f .{j넙A)!Me,=@̘-hC}U/ 00*.f, FVm=kgKj -%jnmCp#) YuØX 漯W䙣eBzU\{SOKCE=SJ="i_G[ܑ Zsʭ\URls 5 f崊!d Z:RzD$G,`l%_w8Ï|8HOcqy*Qk<Iٵ -߰Kw3S fǃ s ePFkha38E#O"Tv=KPW\oNNSH; bsסµ@h; T(BA!y¸7q5T,Z2;/j]O*]n il_/]EYP_ێ2(oϻc_yYqYY̵vuAbx,l FTc{[eC ǻvLW~dw1Rty}CɟqzE`mJ‘^:Zɡ$kaX#(MF*~0NVᇏ!$YyN$ GZݕJi]M Vi2' TO&O8&Oi5ßKVRLOL1E1k?VxPwӿ;XQnְJfd~`֘F6mmTukBh 7 ߶p`jkє44v&4pYG) 1π@-Rֺ՜C08htLPug6k]ڡݡ߅S;DEԀÔAQSǼh0[p+1UPji5TboM45b=W䆎sT9Fk61|Ǟp${p-K(xs}dfTϠȊ3 i( !A>+ jKan;S (z~8˩>#hXTt u9!2{ Hd-qvЮRfXE#fy@#%4iϲ Tp E}tA}d#Js !LZA䧸@NF g^Q!?ʥLֹmd}{h D5u,#Qwkն[⍺y 2r渾81t(76 6nE{9Pa=|R'b_e,z0,|+b>; __%nTqi:48&OMb)jӟX~y2?9YpRYb4 ߋ5`f`!kxUHޤ&TU5U'pN)$xHN@LWzaOd|^-m#ܝ%dbwD;#Ov@Sw4xQ  2p3™+hE{B׎6O'>-YƠ9^+LY% 'rouW mǏ,kdl]@-ĒQ%2DϦmhΜ?ekkvv__ruWE{4֤uIQ~8u\ϦH^^r.Zu}RoyGiDg58J88Z\K1'JT0+(L~AM(, z;t"0aNxN~tCԗ|\OJ,m4O2UcEi q%67e> vRc@yc>"\duu gQm#T"ԦmRi3Kzlp6"\(0x{'/ccPhjhǷa&/ڞ.Ci1tftԸjPl_!h&VAcZYq9^W8:|sTTzѲ`MkOh"Uݐp{ip[ #r vRFĤk 8X+<_ٛ+T 'Me_\륗BVdb *ǡ?W#6ڵaۉ0Xy`d@$ߌh)Q*)K/&`̄>Q4<өA1yG>\G;_Fԩd|ڒu>_%i'3PKϋ2a 8&FkVr$DďDXIOZ$Q1h$BV N Fe %%;灅 zeZS%Z]t`WPۜm[U΍% A }P(6QKJ2ˍNnAl,Ebd.m=z<c+/;sb) yN sf+!MUzr3ukN>YG.ʴ䅝Qvrx?<\|O!UPjᚱ27yL Gh$eq0X/Rڰ獮TqQm9<rh׽HP,bggI8JO~Ai XeSlZ؀['1(OE /`&2ɇ+nj.I!N[_ c"9oERMx=y˿¥NҴ\wc>ceD&rjr+8#c;NV9˔ZI\'H#}Gl7뻜FWW8)0,٦p 1f*!#F$1.C2rqsh'+ɂ_uyk єQ}ii ZPĩ؂OwĥmQ{O(̼0  ^֫JhSA؞CJ2El)5 yb9ֶEԫMec܋`lXK/4gEA u5Hrb=6yYoY n DN;@z0fzgp<%N aWkˇXWM/If%Aheg,rFڿ;W~p$Տ9&']wu*)k§,W/ʈxqs$Sq*~L{K’=Prd-wpag]7X6 6Pd2ІV~K"]FzSuqj º}Iw'PZ*Ou~:gF}#0./ E oz0pceFC1,iWv~U #y\ i2BϥӰ~uƷDLA=H"Ȋ$kU!N."`hSD=O҃,,^̤NeIkBQcњJb_i^4j\k *6IY⾇Gz#U(v܈g O@=ŔDf-^n>r$Z'P>tϲ,l1 6퉉q|R_C7$„ ;kҠ$E,KWx(#|'J4"+: TPK)r1'ꪧ&(=R[nC ;E:~[72x2ã͓nhrDL__Ca?X5'$aQr.w{lq JbØ)__wno1 (I+vbpA EyRu 8xnm)2r%+7Qv~L?':CE-]R5m9々].:v[Jc` 'i.)m6.EY?Q4er]QڠY%c|{[֢_JN1IpQ P4(E1((/rߑYRR"nBF Le-Hl]K[R3ӑ5*O> 5aƬݿi0T\-B %H mz!u "\Բ5Y"Mc&XIg&~ٔ3! J޾x**7OfRFCؽoX@^9uD9rjH12yk6Qr''(ِdW elEQ:K θV ⒫kW}/ 8JVb{˾Lp5H}3':5 ]b&TIf2\NZ'Y)o[?ic2̛} *N;>q% K-n-mx I(|3a~~*˹,K&4#@<O 3Us=e;18d+j~EzTI`>Gy'̳~9+Y㔀2i+b@fߏvJcrɨӅx(\X6w7e?BˆTfaO*Ǿ)EdȚ]]Y'_v7% b."=5R>^8uˬn;츌.9=PR}lQzZB1!~㈮U*Z_]QW.E"1a0W^&1w!Θt"bʩ֫ ` OmrSRTק'hnK$ ,`FNhBhllOOܜ MǭMXNf'ЩbٺW[})մnjSjjuwPN׼!*SR1X"q=J!P-HTldg+U3uB¥tQ4Gm^ v3M;J%vTl!'6i1LSAWfA. >) v\R=BY(%0%WR&QY?)kPUqPMz&)/T#nuX}Xw顅~nA6l+yJ<`-`Z$3wå\2+ 5NRe`ǣ4NH Y|0 ]Ҫc&A+t3=#WCilåZu''"\(ώ ёy.VU]^U/3>U+7:!ݫbew4;{D *u Pf5:V!2_܍X8$Oxl5ɫfkZbx 2F[`p< +K(; ʔd{J^K7Tr\n&4<<'kRLgz&h6^!iXƯp,&h-5Q $c{1U5bwΤMayݘ|rf?tQdVTRdƬ-! S' QT@JZ~ѼC~j/8PQg= ޝ\(U X!hԎ6G$eI tw^eਲ਼E>E妠%puߺL8 ,yL!kq>eqOkjjc8$;jzjkOEI*keE;Q2*vW&c!;[Gs_'S ygʻ_R ȄW\"9_1fPQ9o[;]-bZk7w';'^#ǥӈ6¼uGJׁFXn^u!V8g :k\An<AB2 5y=j59݌F<վ]ElGѮW.3NmuTC6o ˕ 1׸\.np D,Q(rM+!I)4+Fі#KU-R5PJ!j8O'1En:J7X >o!04b*S]H ++x7HrvP Hߦ2rmGiw:>b)yܱ3oX,"haR^,`hxeov=X]y6TM PQ8b^:X^uƬq zOLSsp5"p{kFB⟝BeVڦu+*VT69w=&lU )z^ihw2oɁ3~{j%nI5׀~ h?\lu*zK#Bikp7MY`ܚ.T} C< SP譡b1Lm=˃'10 [_B6?[q-suoe_@5 ç ])Ca傺mbgf]|>:Uۙ5+xz. Osswv0Ә}Oy1o͋4j9j b|oU;/,q.a臹>$1Gx d Ht& T8tsv?8vXPK5&yx .0K11EZLh Qe~p.ǐ1ۿM5ZohKk8h pӖjXh^]sK rn$2mc Q6#T忱>JP[;auxf2p~~==?Nl 뺢Vj>7'N2-Y!1dK·Yi]nCfDݟݝ9GG/sImC !)O.H=(tHҊ%*` O gVQжh?F0:s"lHkC[5l_, ,]w5ػQh.\_F7$zf)ylϕ"Fj9{Ni}&S_hZNyA&>;>N%(e[D"x~ 2qo} 2%ИY{*0o 6XY7fBz Qԏc҇Kt̗2GX~t@x%j7b惠Sߪ+P>vMQJO;=>Z(m" {jGo+$cL7MҲNlCQ'~iYf]TS4{JhʃOh 4ɅB-և<% d6i{̍*؜WrǾ̠hS&5F$i531l?vZdb5PF!h7,8C,x}|)E)U/D {{cH}@͵R$uc-͠N` )s1(0޳7joH9Zv?FFf7< 5h9 qÎ"lH$-&#Ë޷E2]xKD}i[pRzr' SCYG"M~mz@uWE)H/*O"% 0A0=Y3QLsy pt?Y%iM$YzB[87EF맠"PElICjw 1[34[HTu}Q2sQBHaC? HPyd4CXƳAG]N~ VPVX8#gţD9kH {`3(e$EΞj\YyM*ʠ(ʩvO`-|&|Cˎe2κ$:Hd/?K~Jֽdn, [A2MlGL$9 Fy?޿XdĴ X&|d69%+C!@#HhClR\W+=TZRlļLy:#j"x̢9H`kvt7亏:Pu1#B}r#|p75iNбz-6Ygq,.u ܥaJ{=b-%W+ Kv$>8Ti?<IThP#rF <;͇WJ"X}c"ebs 䁍=b㾋=W⇶ ~=߁%`y9wOrk#Akrඇ>20Ր 0Y@MٲlG %D>NDg<@i;[q~a?L'LwMsib)|*ڜxz9hTD!nN#7wo6=i&VNf=dx<˓NFWk\Q6h8kͨ:زnM7RHɯ!WMBɃR64M~yO&*kZo2ܪRUhqNaj%ɖ#+*h.;Y68P h)[[{"[kYEbXI a R#d`CPucnkee!!L={Xm猎u0r41+ Bujv+ IjC#I ϛ7'C/(Z]B%"ҶmrD,gh/D|LÿxtH>ZB P |ؗT~j,ѫ7QGE.J̀\Zi3^.Tp헔jJ!ԺG / L ׵ɑ}]_JkpJLz`yE|Ÿ"6ՃmڈфuKpG_h.pA25@cs$9DRqm!6d=]vN)*n6?rsk.?oF/8Y:}W˜:+,ܰB&9?Thښ!B3l <;j2[9xl Aݪh+T(4X6@"; jNNid 4c0|z*1DI]#qk&=̚9Q^o]mN}4Rj#M#51=tt`Є~OEitE_, S%"gGY+U &GS֚'(S".9Dߔ'8J[8p Ğh@_7P%R4`/PY<;Uoy|GJVɴ}i H7~k54ff lL\עtxFzH :t7sSVPc}7dZ'O貘f(D.٤ˆ%]vƏjVJA:c@59BeܰqW1d\>/4,lF^ <\g*5=ZW#qFMBԫSsvA!ug^WA^\JFp~W52V$/ef=rI⟜'h6DR@ٯ~XSY n3.RQo}0W1ݑV To*R,E< HDs!&,ɫ)&'A\ׅ:l#*+3J&z*ihMq;mW4׌8K YX_)2rXx pk"FaȟB^5 fd;M3,)U>S@dn)_cWE\dґ|9{%)j{!i (Ỷl'Y\P;iZFR:'+fF_K"x}~_Yg"͓hi1mzﶙfpU # O1bΙ kWg䡏ʯ9aqldx8Y(A/-xAE9B6]nA&n]E1_"=Ʉ 袬OSV6HVhݺyRR%֛2r;"RH>!I[ |.ɠ%é\`­uG[$!J[gްOqgO}QY<9 2mAĽZ0^* 6DIg :ф{_nK|#3a,H*w$G:V("vCpoUtզMB_fʽ!N lEEĪ1{Q Up(y]ꮟcT3j(߭-DVd$e\LM"(?K2(]&4rvEr2'2m&hT";g3ugDZ-`t:Ƈ6^KJ #S?zG_I|~<^JN2`]N1VPFAV.D9KҐ-߄璖W\T|4xh!q}ĉ?`{(١F;L ?QaCpًJ8WǷ%$keGC[}.8E4Vc%L&0ksǫZ+=klQ$}b$"͈L}Oj$ҙ 6Dndu `wځR/ ~c@O~9lѾ\+?*UJv}K^ƶ)7g͍\H_Ћv̓ϼwi3*Q(-IXݧ4, 2wRL) J !rЀNH. nX]*DvIvE䢺ᡟ P֐u"W(#DV|ᆱ{3|4?` !9@/rN3?M/ kuo&5 4ܱE(j @Hn2K %} V:L$ ԬY~:509tƺv AYX~]_9$]bMMDiE=`c>rO=S8s6[";Z5kY+z8ujn^X2q6@.(όIc4`ǟX|լ7ԼPC1q4=1Hvxtȡ zAh>^$mX =v{bPaKRiH Tں)K(042:jxZZS?bs]R_n.vo)g8N ?}8>s pRSJM˾~s!M9Cz2tb"hbj)fCUJ@@j _Rwgy?F1 i_BsTDfldWhpvi:#Isgtl軏ٵ1A˿@ L!nq^_ee б~ZF-^7 c;WOy!}KeHI7&a%8p#Dkj5}Ec_vA#-S 4S{A$,¦2_°] -0D,Mc 3~5عug:&tqK\ /?<|)p,:]x+8(;@ìa i8Aaj! 0ZT%r4W8HsQˆXo[x/^,ImV>pޏ0:Q&U&޳ψ-6Cojl&Q9x$Z۷#Z@FoP%w|Uc7&O歉6qɌP5!|MBni%)Z4U֞Fⓟ"2l8lz8V .Lх5D1 )%LZO:FnCW?rEVDǎV3D9:Tֺ Bo:^og|B1L\=g|5\@2,]AD>nhq5h%Ws(fw7>9)gײ!PH0Ϣ6 <ÎANy hOPl%e'6Ƀ, eƁzG[Po^RK):Y;أ" [$*2KFt]x&stƀ%hAOa,#3sr*Ё8ND'/P #29pc0͗v[ChjVQ&S?X>&vCby+oMjEm`I M2-h@d C"<&R5t&ƛ6Wb1]dFWs<6dD/*V!oN4tX/SНz4 Pa37;Wy?(=zޒy%*lZatl.>B?UTT٘I¹qsVTJs\aF hҽj + xi~O0ceq0$=2ukI*J1mG牤LiV{DGP&-qϨ[x|my ;u$/ܘQ 9HRn0bsv[|qa&$&7vguە_ uEnp{ZG[%{<~|M#0=}Nz] (p-s` >0,GZ#˿Ž0jd_T n}<1DlSm ^L3y+V9 HHhSk$j,@o/ye_ۯm,42cAC0qJM܈ygASmB,w_/5NKr;@Q6Ed>[?\K3!!Ua߈:4Wn̶ߍkUblD0@#|'.7od*b*L%$gNU}roEwu|i}KbSvi3.OiD`%#qW3 <ثaoZuzH` `)'AXӗ+;ܩO q]/l)N3Z4tI oF zg4tC0\0;ӘbHc1"zPGޯ'!tNG47ü oƖ†oQK Ri?Ll &HO1לTͤUy؎%x9%4fY #}@.H7‹'Gr%"0r?9Νv*scʠCQrEL"GUgsF X?1혊ۗ-Gq`2iP ݿE(W hQqBi{8ZG-;FtyM bN=Q8Zotf"=UH{o.ge:HN!S17g,Re֎-wi/eŐScqfE^om (WXyegX뚾/ѫ=hAx@5{։g!+4w[xعf} nt "Va- *(Wfo:%,#--EIk[[:7'iZ0C( =ys\xԗ|\ʌAҹ@8妑QLTV:n5S+ #pw I:l&=ŀ;pd+P3)3-z:]M}LN\ !l[il  ὿~פF!.TBb\` 0W |`DĀqfH?XΤYb3:p^EWtXW*6-ch1{s&Pl@ %J<mP/8KLᨤAlCOmyZLv_Jӷs;oN0T&A볮_Jr.?$E8t+MH9M8wɣd-S8IY}xx,{o bc?=h[lyj˼UCYqޭZҪ5LU0Gң $8|PWאD;D'wUgbKg$RA'ISGVn̮ {t.iha=[%GAeX׏.b(r{ daD10a~ȷ[rkII&"RD-\(1&Ghמsk=Mv.#\[miVi5jc}_+ԞLë aca19b%stbFS. HU9`;tI] cC--`B,w!@h,ZAF%'?>H;dE'}f?2g3[z)SRa㌵xDHieȦS 7>)1@6#9ňPh -]F5':ϫM嘞zٱsXYU15<^=n>M(x2Y'»)<Pf* Ҫﯽ(͚Q$s=IIG17$P'\N ܴy5ۤ&6,&iQzk[-Q r $ ? 5T 1ԻG䳢'3rFV[7dK(Vps +a"vQJ  s!|g¶j9,V.=G͑n`Y -"l 0|ﵾ/eLٓ$R42omwٛbixvcu5/Gl<6w,1~`s&Jiܐ?o\g,vj 9z-$/C~?)n kAQTˀzLM!eJURpp6=R8<6~;|ˠ'~3,|Km^Q$@^7iS*5k _i_7,5vܓ )a܀{7?'WD*ґMYQ!pB(-s+|^k8"7ج7a_c;V;5w+OZIDF=ay)j&[OJ?;0$Q>Эא!%'Ǻ, e^* \HY>v#=Bm~ `=]uOS&5*R+=StwmTsճ[1rXv>pUIm߅D^_6hplB"l"SeGQsG NPJʞ>^8P[M߻ަX2 ЕV P9 dxy!|ygfEWVQvgB2ekJi WQT1fod- r;Q{MǶ#0sV*52YhEsC)A9lT_6U s~41N¯w{`x]%# 9‡wAV\n#T5e)u5|ʃ?p{z ,1pC髮!=p\8ò]E=k/8=&nBB8N9H.~*d ]FtJqde:Y<;֧b WVp ԛ #J4XC(M/yD}}^zknw~NoTY0nQupZrRPy}|\Y|[4a620YлA8g:o[8󡱡^NPͭ uLYܩPmD~[eEM'<7w-T]!ڬ™)ioY4d }4wĄ&zs 0{E*+7`2=ju]h_w'?m]Ky#,߰C_x-2̕~uA!Ã4pBnѺ2ޞ)Xi|禄|%DriV*:V?6$V?^ =菮:17(W:~Sk+/Ui|TTMaq~[jdt8C~r3UlC͡H~QV+@f Z2A`44CfEtj@! I`OׂNWcjNxVl{G'NǺu4w5ZD*&H}qngRJzJ]Bݻ/)l.qi|q%{Ýι˰dI;V7(VG}xaPmkeC T~vV{BVLrW}K ׭پgKze%=aKYp%B5\YEFyȸ.3U3NO!VKBdsGv]O a>tv @欛 *ɃΗ?( W@[ F+~ЭM4 !-a:s@Ho^O HzfqU[k⻴ȰʹI e$F[c= iԘ-5T- 1爁FJAy رn84}N>kjj n֌TKPܪlCW%s}i,hONV^q{vI"9P5n5~1t*"?0[؇g<"FScȷ5ڮ֥f lpoPxxe+xS+'=}ʭNScưjYsui,[qEM;TY_ &'ŁP" e;ksܹhfj"hߙpݝ˿MroԙZd0[kx~ 4鋡DELo#Me6ԣ/~VK<.gP# OZƾ̂nd{1@6LZTb@6 1; !o AGr$&8 f&X-眊oGs^ՇJDn TXFunӂg]ay7lĚ"InB^32ݲZ6l:<?~cXtaBN7qWl&<41(xCN#Lt-UyMgNckUDmޕ0pS++G6@M8n9_T|Dժ/D92x mKɺ=b+G'0j~Xu..:ܤ|Zgܨ5uE)As0_I/Ss`\^~5m{~_H5T}ɇ\eLBs|2MFF28ulm*jV*>]ғDHDMy|B!.aWR.؟a=F옰> kyvl[hb.\] iv§fiA&6) ‰ZYX1NĆbGZe j'*_0Ǟ ݍ4"K7x݂iCXP,ˊU F1=#GdӡLbtY}GMMX)(\<&')P? S;CFf~yI1sJy"RGZ*Ա*7i$0u/`bHx {˻G76o?1I˭x"V^O&Ozȿ🇞SbXy (ZQmyo9c\.fbV[Lej(xz!^jr.!O$5,k7m:MgfoJ3HXM(%h?#1QDx~.E߄ R{ȩ%=^\J$DUFAR#li(bfKx|8ȢꇡFN6X9?6ڹ ?e =.\w-,EHë<ɦY>5YX;jI[fG(Hxn Kg!9ԴM;6:uezhP3ެ_')yZ k@ySip<-q uēi^Ы7㖥8Hž8쇵U;r?2X?J7L6dC}imͼEGz\O@ 8d伨F+:|iski*~eFɛ` sPbAZ޻fS׿TBTiIUҖIk /iOt}ɮUۢ7U0qS:{]nI˶Ad.;dUh¤^m` 朑yVN :^Γܩ@kn̽uOEgP~"Hj^{Pk7!K`vZf$IT>Diy4qp-?S*1oB'k?)l 5!ԻA,DzW0f39K9@ƍ+MN\_rAWE`YAFo ݽ}V ʹm:>j 7Q{}.0EW@tEǰIAcm? Jr9Z(8x-R'u U0E$aU`;ĮXaC&=`t}܌'V |/xbay׆#)Vs)Z\Xu1wuc26Qz%`dmfci0`y abAPbssbizkO~W,+2]̎!⺿B|݈~䁾tВsBHR; ?ٛڕ!<ܬ]gس*_,!]lu ,Xٷ\@? ŭ{^tѶ ԣ7[e}[G]]{Fip ƿY3 EGZ4쇥pnɫn:cM9ia$mЅVuU^?&\cD\ȟt܁u>M~E'\:`6&Q%'1^8hT-ʵ<Ѐ,C_A Yk% ZCSoó<ۄW 2&2OY)CR>HC81(]qf4u+|d1EZJ ːa0!ao+\D}SӮ|ɺŦ ̪gLt)B}`8a߫;D*ZC X(B`9&RGN*BT! ƥ2nƛS<SMWIPP+4/<ÀJ;* aA-3)220*3ʨbC|W?L2&U-"`׍QSG u]po5yŰ5Wm\8wj-r8[6:-i$z*blD4[#RX=$̓*%lmSbhpCI>.R2BF{zdi. ˪FúmX:,RZ8s#<[jm3Rfb^f8p?2I^hu_\ޫ!ll+SXt0٠kIz;2(0u!QV l|O) (p7<1EGlP.hwED.;bP?x~77nL_5wB2nm}s1`&^Y\D0?B6M*hyqI'pŸi3ڰQl1jQٸZQsN͛Uf)< p__ى%9i|ƛ_MՍfoԩv w\X4ߘaZB7И5iHt3ydJd >Nz(nB1V_&iT;8 ro h)0&-i'm~ I!ky HBE-}L'@8 *$qbHbE&3+̳tH6X)9em֥6ي5I!7Jِbǖ*O|US4n%cT`'h H"Vz[hu[s|շRcl}x4rpQJEkBfޕstyGتVhK(SB-2hKLsNI| X?(3P1%Hc}-˳j[ e2+alr#3t[9E{;}[a%٨v=@!G96Rj q43!-U/stпz0OU'w= "m+k<` F{͉Ӑ.]}̍#gy^-"36pӷ0[dqw&0jGnLE&F:v.Pϳ3y\Qj*`)-mU?N\Фo^W6Љ=a[_.‹C1Lje$Ǐ,);,\>Q} r֬Li`qYrKMT=Lj#%J ]pe׋sn Cn~Vl=1uQ=lj_N(, iKʵ ,0}`370g LAFE'7lwiT!֢oI(},-tYΠ~Mս#B\/OM7CE Vp4GM\Q. r)(_NHaGrdל]'摕]^j]=p\4^p4$;&p#ڕ()9=?˳mX7ٰ\:3?Ծu'iıJmY"w<ުoU㛩~c,Wr.ɹ&"a02w>Qrg^ܙ" 1g#62kzujwQ|nhJ̒ϼ \LoD1fݑ[*r?m/tt)Y1žcpXK-Y؄0"ZzW1a㗏`9L!U_TC^A;`ݯb/FGM6@~c)Pj^<-{@*fd"Dz̕CP}'7ClqCÓmV$Eנ*=#2^il̂@f/1K?Eb`Ԝu 65]$VjAwçEƹO~-Vk×S鯲\\4T_~ On*"RnLgo<I |U`*T <;S:z==ɹ|?]+:gWb}iɠߚ2A:6>b`/9D$o}wRuWRP *)hAǵ0D˼7?u;'e?@l.G|nB%N[GŜTd?җ7LNP}!;C'Y\ E06?G[drpY ?-g:*~q`3U)Ҵ)_<$Mb;ť+FD<)=yaAyidzwTN 7.J1- Gq5e7 [/O y@ ߝ;㑩x/‘koUl%".}|L}wI=Wp쎛mHR/WC$P;!5jpw':+[B^0XyvQX$ꁟ/2d$ #=ctYT66gf+jl $]T͸vsI d7Q&*.78߭*%f3%E*="1KJ$w[h`f!uTIIZ9:\!KBc>V.OY=:_[,*&yxO80y䉗R9+ӥ&mi< ےbA2370 ܂iN:ktϷ9+@H?d!Fbb>?^#o|*ZO 1 S0"S lEٲzgY@FKD4"V\zB9qxh+>h*!N[澦THWHڶɕv}vX+PnxĬdr+P+-oGOLwIF CxWT@#Bz:ϝv:A\[햌c'S1cK:}Cֵ;ﰒz\amP+{2U~Sy(+/\`CI%f3O\e:&*9UЙPG#co ex'.rջ<|Zg^D0^pa="x} LV8!nۡkQYR!ߗVAMݗp#b 1$?ܷ]g Yp e]o婓t)Q|?u/ԘMThysi/ ׋էU5Yw5WmH=e̚eN]"RޘL2_a6#s̥ (lLUH-@AOV{Gmc.=JE(_U(O'R *&FїE0z$RTo'mS"^p꠶Pt;CHBƺNr~5h}TܢvfY&<J5wZYO_ffX 9E/1Gć*d8.p^9²N}j0+4B; ~ҐxIrxF,aZEdֽPlSZ{0CFOh{)&Y5 Ro/یԉ(.n29ZW.f2M7 ص_J4!v,l^bm7,pFU=oy8跺Fֺ̧mZo&hVw^,0E}Jʛ]zp$eUj>< *`n8gQAŗ6}f{h!98%a)g ,@j/I$I#]+ ŞM Mh~|xSb5ꉪ5L%#֕+Eq~ ڒY5֥v:/+q^eIȿ5mjy"S ឹ +>MfB9"B+qԭZ/u nVf%q (I 4VAlg^90fg+ BQNUqk%Sx)L|kfՁDʔ1QҪ8Όx8+?;ߡ6&tyEUfSPҜ`.c?/SNK0H"XrMA{!Ce@Q 3NN GYŹY؅sV(J}Ez_LeŜkb 0\/(6;[2 mѼPʛIJ0;Fmh/L(o;BA,5O􍐗K|W'CZh,>Y)kfs 8.Q( dGeӇXG+65 K4lLeg݂j)ra&OZr' |: h&bbV >h/n:ІN\iK~3U Zcm& 50q9‡`cH*fCjҳJ8^*qϙo].%ƗS }%DQZ.P,~Hڰ][18 <oSI&qv ;U!9j~h-XR׳nf TYAYC+HX쟋OxPWcW]p/ݞ ~m&u?0i*XCأ͌#^jfى_" *21ԙԍJĕ{&ٰqGk~Fem6L&#q`^H+*ʘ=@WFB499K=vAEGwIT YjD"+!}O>۽Du?^kv'Fa"u*`\Q"ʤBp"9iyv .B'Ys\qXDzMtZ Kzs[|Gy.4I4W'$τw)Qˢ K536/ZQHG5?d~d"n71J8gm !ˮbD|_`np>tjܧ&y/aF+KrV6o2 <6(%MxQkIO'܎b0f&rVs翏Uo97hugnMHlfJIӃ$O;X W"6khCFmT9?O%ϼ?eaE@#ux7N\Yغw"]yEE0ȁJHAG:lt|Aj-8G(CwoyȖC ХH1+9S@Q{![uӸ d5RG8݃ؕZ%VBZe53n!ܻoHD[I"ޗT킰ʒJ,pHm#[R7 Pcig6SlYLJ|S4vR.'VsgRwl{VA K=i {xfd%I:]p7[~\eQ|W2 /5(jG&\64g_)' +ZU L𥏦nv=d[O<'jؑqC\}fySy:ITu,KhcXCGfV BJΡ[xHV@U73>Ս*ll,0/eJw['KrShףM"LM:O{@*X]Y 38  jYfE={ ̊]Gs6_$hD~3INH /674#:u7j%j˓Xe_8lKX% H=`VtQJԝܘ>un9hQ m2W mrrdu2ʈ2l U 7KGUj!T,zdB% -]Rx|veEl`Ǚ*[e=TǟVjiFo4pՈVfo߱IX邹^3?4Q,_w>ԫ6!-F,p]%RTY# lxR)݈a suB¦pr&3uHEm~< Ga`?\/,Fp%U`*-5  evԑE챶(#-D.sl` )ܮn)ln};LK34Gr>[2NϽMǗơ0Q>[s%OzqL=5`VV8ۂ[F n`+VvoV 2WWރbaTf' s#-rbhPEgշGSz"+< J?x?vkh29<MDʫjABpL ɛȈP"TA=MWY);7k ڛ/@;AۚK7qoWw\O]V1<"D ! B\a隔˽ǭub u*dj `r< SmiBuVzke6UcDX`Fؒby=n蚒,Fܽ Y3wSl;gɺ,^|%:I**i3#n_\j H8bՖ#GHR!8^h0`k*jn Gh:ѩ"NϚ)!Co=Prdټ <&[ RfRT+FXVVwtѭ迀Cu8FݤέhxIZ.<хSLzIhҧq>=h=m&ʓ9y, )x{u~/[ZP*r@mj{L/.yXC&>⹼JtIn ly$z1Ai1blRQ 2ꩊ|XpXXHz4P jmbxme<<^O7._ bEFYA]!ˈoM&%?s-i<33F uw/dۗ ?0@]t qp>b-f_`g56<`@oDSfȝL'1=!g))(Vu3}!jhD89vPE!}V3` i?4dvz gupKblB@N W Sj0 $VKåQ R; YA YaOlFEhGݑojK JPsCZs&Vp\MڗԚv83-U~^t9C?GbRVEjb r*G1:er,6<یosJ=:qNF1)-d \C[4M.e&AOO_d>cWlZc:`Uw@A:^,k. (Rfgh4R?H;^&:!L=ҊVhx7qH1"x ϦB7\5gqjbbdP"H;2_*j0(ˏX@wJb %jmgV7dSJ(<?V??ᜱƍVqc -zJ1a B]Ϲnf6RɜYQz9Ŏ_3 a^Kv)$tۼHg{54u25,ʑF8ҤAuҶ3sF~$+LC)XI;c:'kpeq Xa\k JVA 7k?V[4( qpdz~^e{'EL*&lḠ[B Wf/ K3}faJ$S-Pe( }lw(Gp'qb+0B%\#$Lb[goE/+WL6aᑅ/KPbW+A2 -ķjTf嵴;nw":r9X.+oSoR1 Wt<|nDrffyXeaRF$V)A<Ѭ9ĵF#{id8"W54U|ytלP< wTq@-^>0ɂXD]18xcE:{௃p:\2e G?9V?6OmˀfJ듦*2 rFDuK*'%mD~k bPѥY'C heA@9Ԫ#^GJ±:K9 U" jVUBJ)865̂@ټ N0*z^N=YV Y\rP\? )Pn.ru 9tXҞ1mz L&ka},մ"8~ȓo3(?ةZRoIp{ϷsZy_o8 x(wb² _+hijI5dzbrP,̛Dho'LK[,G!3m?Ouau lG?d5T#xIsϫPbyѡu<+/jwYOt+Nl_:k\f鰞rh4β VrhMipepk$c;贙5 G]]j.J͂VV{fwEz>󃋅t2(&MUT uD@scQkt m${(f'o9\—@by^S(9bEv 7KGuIny ɔ$ U6J>(XM]/Y>lz-~};MZD1 ںSj:X)ܧ) )v*Fnkո%:\p(D2ܻa}n>ؖ; x766$;˖cEh3 RVܖYqV1.tGhX2',f=@gQLRn6q=b"^|nD &K4_[&Q>خfM5%\i9EwLD05{&޼bf-r]I2>f{0T Sb(sʧ\ IN4Ie ܾq8ֽ_0ZR:x'ZrEx$c_]l]CxI!kc egR~BDC 0 L#sƓB]l/u/aql>L|$ q'217cEyGw>0,7J@H !$]ɔiVRl~Ҹ,~A^kkKRlAekz:A\;o)uKJk7q[7`cs8%'!@۠GP"*ɲ6}8u!\uw﷟(w,] 6Lu5z7cI/gQ5ix`dߓraΜն9.&zAdd!xˠ~7"al `Gr,O?:5׭idJRpɧd技]ʦ3'::mha7rV&UБt0U(Lgi^؛k'2twWEI5r0lcoBIsJ+p1A:=pdD'{N?h% Nx0 t(l?ӷr+1+>~eQTSI䘅Om.'aQLFzhB/! .oODS5zT6$O6A_/mw}SlR:?f ĭ1&4|{=EK?UaKD+OVVk8c`6qXCS3 lǜ͐cvxLigr'QZ)H\?~vD2Axh };+9=ԯ YpJřRl_#us|Arl\iV2=nگ#`ærҹR{- [{:N3J Ǟ ʜ} Ƈ-x2%^KL *@L& ,~ oڝ + ,<l}ޫh<;gO;x[H#h4ԥpe.[!6v`[ѩy@V=Gh&2u&*J|Z^_ N= aEq#eIK\e7e~Gǵks˙zz}\ DIs}78q@kD]uaƤv XW[>}^{IQH0,e[&0 ;i:7o9m{R>4XmE2ftn̓T{oÊw F1Bfx{:R'ZR)#jW=_$7U5!ib}S./D\YR6gٸbZ' [2ݜ*scS'T KžLEpCbp< %UL:1ժБմ|{<;DО$:+cP9yMފ >2" rSiG\J0&;FF&ns_*П&kX4~AiCljJ[; J5s?V72 ѥ'݆_0كcMܚƔ0TfiAR"K&.bPQGR]a*h7I#f/PƤOO|vм=ƨE[PеVsz5Y(gh {CmY3v-u$BplxjCj7KL@°rKxpBgK&FE33/+~^r8 .YW|[\)x`|A"GsJ-W{y?q}YN/:_d^(: dvB2HoR"Z1S lj$bfCz#OyHSo O*X)">pOɏ|O<>_nk@+ihW~ aSgIN .5DAe0 Gw:FtyհrxVSry8{:/BO@dxtE7ժ)+v8‹N%pNI7~@rr \4[%&EكkS|Ֆ=xl.;^,ƕn "w{npNa,ZVۤwy&4 f,5MkjLJ͑ >hrcmn~3M_HP$Ptll!Tez ܃}:\Pe`儬sWIKfOa2(SBJj0[{qw } 5Z,k~-Hf@ݖ4sy/ T@ZVv d_O6QB,CZ?' z#nG~WJxz(ǃE+Uƿw¤^&SbmziT@'o/ª֤ U9v׊kCw=3O%;y~%Z-뵽*6[}:%V *Q 8uF8'N8ž?O2_z^H&2(5 '3헩jI8b\䎤kTP#_4]ͽeqJM;˅oK7M3eR ?tzD^6qu{T<{Y ty.?!haYT;U.˰V.$L]Y$;&#:DVuуZv| wspխ寤iڑsfP zT@BUɽ~b:e Kd cHo;Ƙ9IZ(.sqC=;!xპVX/1hTY72zqGzhhtַ|XiKJM,r?> {~a;7TL=2_@/( k8j햱IEU3UlV́7gFǷCFV$ۙY%SKX2w3Ѯ9_rK֎+m?+UHES jK-&u? 5Ur1`v}R:SE(77h!@2Q:tC jP82YC3ᖴCBu ĎvX&ù+ cyR>fmV+xC;K&< 0x,޺ {יyniQXi7KKXz~Ʌlҫ*hT0j՛I&mn_+Q;9gCQ#nIV[!6γ8kp,r4dP'YRѡ;z qL >gJ_75oLAz︊p𛿫kj(pگt8@]$lOsHnP$DS$seTJ6n[TOÐGk}iPoE[{cŻv<@\ٗܥ#-7<3bb?Zdn3H2=_)M*rxq"]yO_2g++xے@D0եUn~WOucȞdVD@i l#\G3+uo L7Z nWTV^6Js0BYD5UI:]Oiy\ s ˢ]y!;"TF$ O$N?oJl@Ɋi  %g_@Ͷ*F [K:C\5|T(6':[1g^1Z}"lY=Qv=YeDG$knM)@eqԫ(6W u~Lɝ Ӝdw7f̪0.GMI5ظY &ޑU&YH|"lFK}u2.D%C#'|!5ϕq}OثWPI*K\FDGDN[,܏ :y>N:X842/ق_jOlv2< [D0(TFMJi18#3w; q]T,reW4UΕ^ͪShx$v6\L}xgRzysg!ԓf%uq|k0Sl+}[}U8oZ ]w.J}(-Kz 'eYo=OE0~G{k {0q?]ռ<~h &u[*B?So}˽E%ZUXnW/{8a^IZӡUQP1,esa[wB?EM iOv#:V_Exr588pB xI;a['Ҏ2Bf:G\PíCmGyf\NUU{¸(ty-garpG=T^ȅw˲H]'t5cУ8y#7a 5$00Xеc_l\BDwE3nDhN9s~LBߤqA*/0l:004:7%VXDŭz@3"4EVե{s ަyUJp ةXlA2"w;L9%(F4.2+ؔvZ~w Q|p˘*&-Gzuuh[&6iOR oSjs2Yq׀x=Vr5Р֌n/3I4$Cg󢟻{pUcNLdG}8eSh}rqUW=Wvʠ8oz}ܙ 79urΘJt"ئ/"ഷĘɅ *#㨮8'=ćyAh@YrqWuk\|;&yvPW^&?,cc@|r h[Gzڹ6#(f,*Ͱ:wNڳY!OEp֞:Z'P,ꗑɤRHPM)-qIUzhmia@cFY/^KgxwEshqRBS:61V# :棞7BVJ4BKEKmIH T>j2($ߙd 58P1z~Wߺ%G{y!<93E8Vs@8B`zkߧ:Aq76^>rjqBZ௮E x\35f%WmvL'`KH=gf+gtA1`8v׮SW#ZbLەSkcW FK;)yxNXa%鱜K2H% wUU#RPczD-Gۛg1P]Rm0.*~;DyvyF/!fWzK' "=73{mNήC[C=~gp}CN8$_"( +=x`hyZx<15\3ugLqqvk"D#mѪ98]w.B%.Ќ]qm܃ܬ.d1~_,l3l, յ^ _d*ŸHԓI⠔-wqo2w7Q3]WSM򍖾@#ߓKp< 1se}HWQ#S_hUH+B#˨%|SlyQ۽ |c 4斯ލ%Vmf};L_F>QN!"m^;f&?dR_^s>ԚXBMs y&`i'!"2v8s3k&_46w*jfl3g%AlyCV`TI(wjC_u2 WwzeI{& sQm^&{'4vwh4kl" Ы!,9s])Θ4_+# -6*mj@_ XĜMzQ~i AZ̨f;XN5Z:;Z*k$~ؘJs*:tпSbSj᰾ |ĨL浵@2bc{3(u۟WޮL$EyE4zY.okZA`" Ә7;f>WG(4C'˞-kֽ|4p Mڣn&TIFʀ;:_vT7p&(W-ȿwm7zFtlQR}$*bL0?@'Y!cLKGc{>ϕNCu /vNP9ʳ?kV'hK[wjDeO %Ñ7XFs(@( l}PN~q>2ChoBܴı`Ew/Nowmg [Ԙ^AE裏j.ڱ:Wv iNIIik$Зh<2?ضT8svvҬݶ4d^vj:nAK%['r~E;u/_p%x] [^iD|X_655>M$~77Ʊ1{'\vhyeď'pm}Y*@ /8ѐTQ^1Ĉ6 $p4-^B+6VJe8Uexb秲A4^=I3)\lsNEgتUTra2b~a[DpN@[>\0'9zTL M}XLz*!ẃSw9# V"5Z8qMҊa^l+ f002V4J4?쁔 wŧDk@QA xʃ fHCQczG /f\mo–8?-](zssRVk+kZ$o~sܗ Hg?i|r鱚b0><Ѱs( ޏn)&d{hfȝ9Ā™_RTm8D{)s ʕ~AQy;SGxqXhF JFLCb9K?P.F~Lw6_)tEd܂C CĖET1V-jNRSEP{کC2)BNOvw:[(AVz 9u]qLΘPzfz:]D i`|>Ƙ^gXoRmwgwQ_ک x Gt/hI,]h%;ۂeEB~y~ZQ5Q@O<#K\}Bm@o: Ed89v?^bE!4І ?S뢃dVvFfS:o,oUDǃhYjI+o1 ` zܸS4kڏڸ ȟ۞A.o=32V*yty׼O{ԞJ1bAvR>1`puϧ X$׭C\r&lBꪮ4 m K̷am*B﷿Eq>[dJ&(2(qvCPN̓~4nsu2?\@#Y6Kvh_QrZ{[D^Ц#btzٯ,O nD\ ՞Y'ɯ]~ ҶJE2sNCv@$ҲM˕qc&`{3 CjHHF=MA+ojD!K,{լ B8v5g]3Q ) @_%U1C{m08F1;)8&q[ڊW)EgEt`)Xr^e|3j=8`φUs!$k-sBy漙[p-:V%;' w^&_eZ<#vˊaS^E"_UM@[Qx2#cBuj2Wי\/SysS:l4? }y&~9E0ۓֻ'+'ɭ-0,s]@pcՌh {C^RYl9斬 ~0QkK$kK%u{0.D`[ÕR:o :>SDNARBqQW3Zs"=l`S{[;W;Q/c|X{PV&{-hvZYE^?u3YSSLS9Yy"nXsS4xDI*ҾՍGޗХ"aOT[Uc.NL..ƈ}Z47K$wM:}=ggnՅ r4Gs4m|9yb^vp5)Iv+>>!*+Wxn5FsKY=+Hry f?V%?NBuVͮ0Oov.uthL8մ+w<b%]o=аETJMQ\0JU@hgA tBJڿC_BӃp7A+ǭ-aPc_͆@T@8掴>tY8&=j;H%0B\?]z827W?W$)+R9_65~`qlVפ86魊np;`ʕ[˶^,bV:HIܯWFŹX$H D1OXuVw *Έd%JSikIݸAS="n,F R~$<ή*R-E#UU0q\;)kv?2%6b!mp %z] H^=W f _cQhJ%ht]«gJ 컗%Nݓ^, QXqz[> ?Q­M%|;uܐhhnzV7q╋yc’OL)R؞C0Pl!stIu I:{-N!&8ac8L zՀ!kD-OY[ .rfUc_g'k Km=3$W )LCa/UB0+Xy@W#y% x;5|Zy7dpI?oKoMݱaX QeՀ2 P<5/U;6c5@΋9,NΔ[*}pqtnCn;#ܴdޒtBMC4\يiV4#]^:RIvzIy.VMc? -QYW՝lS~}7SA[x#vjqSѬvq.]3<Q!VIOeltLG+Rx֭./W^:')M!1SL- k-q5EDK9A5*'0rPD_෺w@ :)[⽾AC2]5U͒U}[JJw`ĺLZǥ%.1^yӻzrf,%Qn[Or,S6Љz!txX/sFm\ 65do%d__Lvև "eSP܋/]p0 Sڑ~ S ֔gü;{qhUy髐K+%+nu+i 'x6a~CNu)iƎ PdّhN9ir( x] r2_&jٌ}ˢZ7aN[B:V`7yXM~SpgiNTqjV ySM ? <y ς=酻:=D 5іRn=A0UJ(W^ ``&裓 ɛj>j"VKj3fB3KorlOBޕj1n-[+ =hd+BW匌5 V%]-eNJɠ Q u ~6~PS ̨=!'Ŧ[sQXQ5 t>6 ۵ldGn^ZD6l3(p7@ v>DD"V=bPrش4"Blyk0 )U7J /ߧʱX_WpvgMҪ=@ݭ`xsReAm;/)Zɾ0{2lGy\AhװNFn-.{%)nMŜ58jMq*4ZC mȎQO`yZ@e AFo ^lÓ?ѦC^bBo eE3* f1@cuxz^sBkc9aw2n>@Br<1!sֶإ;_FIM&$j~=k0yzM7\HIL@1^PޗQ5B1.:gvAoCuߢ KC rǢI40̴7UCV|*η_L12aY,RSw^ߝvߕHHE)ҫ2{#qGmr{V MJ9GV3{t# E\)'N*|5ws~n6UuHfiRza (pyv\SD6y/+ k?nÌl_KNh],lke$cZW΄ nsпu˼/? }R*YZUl$=tL !90g}ztCt^ H֌9=_0A#Fi0& [t@^8,k,\u[}7 *CY>Ct~A1 4Bag5L%ىr D\G*!DaP`e]"&lΔāxin FINmJ~>@s'yۖ (!S+dcL&;Ә:(]LE`#͌myKf~B ~;X%Cb/ 2ɑ `PgK&a(Ӡ^=vSz%]^Y[ᡭsa|<#cy?CGhDžjzwFig+ҕ۲0}m<l]~5:̜| 75wȡcK-CC; ,'Zɀdna­rGZLܑ@^VϛF>|a×OyN_Z"M."̹G0L!<i o bi{ dn4?'o#v:hLˮEVSbY^ v}N7j׃|駉⃔L2g!a+m}SS66W`IS}IEo}xcڐ 'g.Tq;rMqdd\ʖ;ݚo;%ʎmVߊ20ZMR{1A(ۋM,ց+oj69~gh57qYվ#E’afq ぐ!YɑdMB+8&L-1]L@@Е [3'?`B}^+i;LgvQUSu`tw䤷m vJ௮n+CkK#K7痳 Uww+ӯX.d_ 8t5=7mKU 'bIN88L;m0M۳.oV6=+s 4K OKqzDf=*£|ld3Wu(Ö[#R70% ,Zio_:tKt|[rB2 P&fƨ,}wQMDۛGThд.kȽ o]^gXۮ=8Pen4 ٌ Q}J7~'8?T\kvJMV^/mN5X#4ßj=GS%ipxlKoƀ% [6y8[+0beݼEmF/a5o"3lv@/1:bS2}x/lR=IA2_ЭK={yh]=C"zr{A[E|r ^|dLzgq#;'5FA܌Ue&tZ~E :$Ð5|<Խf퍨K+CfhN~x ͽsII|E.1ŗ݂'=^1ͭӛқEOp ``NS'k*x z]A%_a5|‡L-vy7WeeRwZ\N،Ku%T6?UD{ =BOwJ0R%z,T@An i۰P7sN1a!3HXvTԒ5ƶ\cJ**V΃\W#r-:NU<5 ѱUC| Y>|C-~ϳ؎o,&ϞDP[xsMF$yw?g"S8]ɪJ}Cw~)pr!ɭ-Bx£fʊŹS0VL6+A1GdBu';Pĝj8-7 b~^رv Y8@){1n-O͏-[[۹d=;NhYa?ZmZlC&r-Ϡ}O:Sז|ԫ8u\-1uTk (Mx΅ JODٰ[SS|ܑ#)&sW*y?mipÇ_f= RGQ)I%͈bn£вU:F^a'\#|}YD-[7+WbqNADwo\3{Fv>!R[i;E2xDk1de!l..AS JXlm˦勣5gg9|h` OFj=Ѓ=r@iP 3rF(H@+{ZRMPO?d+/; 9gT8Enb1|:0xi7ٿͺ#ۙ. Ki׀*Ɍ|V&-IGySlPğ |g/J92߃\5oRlrtnf҅Ab?wmY҉ۖ}V WE /;r'*Ng:]Se r*]X |i! Cކ_1A bBrǛut +.M{z(2(u w)qL얤A+eC]'6C8<ŽhH! (Òk=I- T(p?C$tQ--+'3nQvz DljbC`xC8pP?}:pFC4vKƽ=i>-~>DiK!%zU+9ާܒcԬo4/}4o~[>KY~rcf&ޔLݮ( 0Υy(V7I0[kAV'9gs@8y+@ s U(cХӗgj `0B[dIjH#|d~W="RqX7+!b RY% 4weZVJk@;g9 wM [:n$fD.N֭!s25m* ,SXO( \SC$1f3"됖 Ux Lu5rg4ol+*g ,fӽ8@`y#!ea?d敬kU}B dm~9nh>ʞr]*nE&` "ɨB%Wژ$#8CtcnBͫ[_ziuj RE D4W]~.N EPw@9~<@+C$Rz 0x_P50Ub3pஶUp@ p\+>pU޹%wc"9%=HT*3 cVEdOGLK׉݊_Kލ{}@Wdlsji*mٮ(MMM$z|I5ŋI,B&"-"k*kh``MCÿ[o*-NVBjM3Ie McNTD.@$`V2^%@䤨Jm5&Z/BڃtwńiQu/;f&Yi.LH ]ͬ~J2HSbuuw(T`_t{e IEg薾XW8Fbn+M -vjTu' N-n%[<_0X8D㾈|8@nzu&_?ϽU3!@n-BW>H0-C63҉N]`GE:A~-_2E^uۡ97݈Z{_UmՈr)VJ IbMsY;Ë$Isc5ݰ dмT¹yYsc; YA3L֤kq2p{{4?M5en0ڸR2I92/}}jS5ps2 U$n3:B#I7Q]{9<@ol7KHoU`=,IP }*(<<GKl da<0]{MH'Uj FzV%GQȕ :ϝ(:KQq(9>=zI%:l/fD,wEhOruAm`i[{V$2X>^=(8)1݆!XU)<BzΟ5{ n5^ΧŏwBݽSדѐ#+H^޽lӌ &v17`u {aZqV f̋mH@$檒-.ju?xoySz Tҥ\}q`62OV'%#"d2k΢ub`\Ũ#UVHVBi]#iܳƟ=%n7w$3wp;ӷF=/Kf6%[lFt0殦E3]^51\@̪+-5_Jx>{z-f Bz1!Z91r3Je du, x A6|+|E0wzV`JeYt3F˓vlȁ/W5b^85U[bD1~C?P,X:bAY!0PAt7雓+VzA4VX|:Ҕ@հ"sE63j͇ɛ>yFTD4uasl&V clAayKFMφr2/K;G~%z2lpqt7k`x+xJ!+YuSt^2b]r&*J edplQP?AM5O Sa ,L䲓 c[uSK䘤6GqO {zCa*'pU1:ҙZCPkg $w-R"A*t6]*k< "A; -8@!: 5meY>1@/:nR0d}#t0kTE.[r~ZXJOlY7v+c^  c9ݚ{3z7*7 G˯D0pnZωJ pzm} 3E!a6 h?WtV^z"xMwI?`UR#y¿~`3oK)=WQ`uv?Aw< , \D?^!xCq%8=v"[wڪ5S1练op>_ $RQbQp8yNsv[ޭbbsk)an`=AC}֣ԜZ=OZ&/2+D65笥Qh<̗& fA*)s=rFʅ ]S;}~>]3bs`g$Sﺢ ;:V;0N=U+]Wű(&|'⿬A@MSDxdËmJiJr^Dd `$' QtF1],?N-^5_VcOdIZحg G˻UzJ17~Vc&ҼcW<^&`m"IzGPܕFUP* 䲒{G;>}?Vjt#tQM#Kꅀ=FսY"qe{l5Ohz}e]WV GNQfF[oo`hȬVȷ;wGy-J $~83\X){é<-D/|b ^ \PJ+2\ۏQX&ɿJ'] |&ی(l?:c9vD3x3F%)1dW} ' I-ac8(*|W@+ 2z}:=֌`ihJ"W (J;YՐލ :Ʒ -(Ux:;/]8pImE+\հTNok]

,) Š.85 _HF:w"@nwo[M9cKeBut@Oj ,Ed97*b4l~Ar^+wZ5#=Z> h.2dS w1ޞiDi;$ۯfѤd7M]5x7e?(C{VCQU;yk[YXEzjRLΎheL)hyr&xqƾ!Evـ^'^mXXacvH&Eh7Cb*-v%U55ˏ)y8mqVyWa, InYa3j:U1M^,i1M72+ \;J!eĚ]%xsrQ W@pWۥV@ғ40Q=rhI]jAa[5g|vV}/epڋ_B6<@>ѣ1I/EqE0e54ͮgΏ~mO [f 78.CL앚/W(dV:B :5;X{w=!AdF}s"9z#M<=-*+`}jD M%wx9@ ߌOHhs D^ii a'$)b0OY-ĐJ}w)l`HAsQZ8hOC(zGIpM|a5쐉0$&?ԇHccd +罋}| QADc$ AF딜q`R*w/-ژ1 X_?qpGˆ fQP-J&J#wbx(6e ȐOPZKd~_rHi@ #hݒkt=_Y1]\rJjqM84|'I/3 Wp%~-aw G97 W=_׻7v%7l/̋h}9dQ zA[$G%ѳȿLA| МX g;z ~ Z-q$ GO%1M1lm)1hs!Nj`O`x܎K#4<,C8(9 _4rܙpr:+欭bѾ b,r/$t2e< /4" z+8"\H1]ZMrEB?u\qėXQ ha~䢮? Ɉ"f4Xx„D^(YRW%GnJ "HTP[|"h@"ꛊVK Yn{J3YMV{P1anfcT`G~nCâڊt^:i$»Z<83YxhMPʹAIQ F^ϡͅU8:nP,?_OWm}13xLPC(3{ڱ1kk5ݯ28Fo ;В#i[OFpb]muyd4݈wəst@K'IEGml1><egw5ף"_6{1ʆ(d:=_3f_8; 6o|0:MGfgh*$#Gyt|5x^VA/;Ms/|n ăȓ/Y [^}jh,Q#YK#4ס0f`K8=G(h~|^O@,jE{<*̇DPc@ﮡ\qJof7 0I`U:%aOvH_n(jʀ"/N \rs/v@s-<ǠWy'̈{ԫ)4q VZaOl(/Ca8XokGS0t ]?mCMK? #($vLI#t4א㹡Јo=%#ϴ =$[ }:^"?3dWF#I&;2YKN,tݡpC`fC9(k޷'VݸYKQ#H@d]-iQxN~(r A7V*h0~oa1KLNˠ(1HJxM 2q89ǔpVN1>*D48dNvtOb/1 /j2`QE&XS@.@XlJ[MkaZR|֕)19Lx:BVh_$Kw,nbcՎf RǓ> dp6hHw-;P6AjZ*34ssA K;>yf -T%!BRˏφ'G ͺ%6 u^FS9:3xέs9Q ~r-eO\kN%_y,L|Dn7'GF* #J`- *QwH2"<^vsz}C Ze?襑\{ |D 0r^ޯ+gF9N}OcK0U ߍ:FT@T ;~BP & acP1mt,/:wf2 5Es~T4XkXNX=Ct6f/@VHqRPh|7-3F.z:,)Ӝ@1.p/ &Jv_ykfϦjj.?6H{n8F7xW:;# 깜+Qa$P翋4fD9xW/ ?b̓e>ۘ㉮6X1wf1˧k4L}eϡ̄?8˸@-CRf4GGi{sաt\GOwKE2YZj%yS-w Z9{^-MwGzk `p/t. 5彚} =I'Q-.IB eNBV*ƢuVCAl@Cā[_nqLzTbK{r$.(j8C=/b>uxEI<' ,'7Lӽ8~ x#̣?%:|j"T?܌ׯ֔Oϋɫ@Y/\]5X'TM4ui$Kcq^](]8+ WLq}ҥeBٕ.fy[S Ÿܓ:I^'5xŲm6#%W8ʑZ]Pᰖd_ Ÿ\.жzkKidSrxpCZ,~s`*PCeHd9m($͕p>pi-`*sznOgĮ9_¡{v?f1pVYA6Ϳ<LYSYR ΐ0?& 7ds͵hfIWJJL$_mFXIUc.ѐsGwjw RA,Ӷ1}+frIeBi_q= 蟖ǚtQt/*e 7_:XήGSJsI3Z UQr9B4aVOS(xW^as՟}X\C?-Cqb[v X"  gbgcR|9;7Lj!bF7slǜ^5.i3s`Bi4#9kIuY{# -z?G *p&QaM_p'OD)[ɔ+hUـ(:uƂYݣXX` 4}h$ӕA&ۏG.è ҏZp:P>ZDލ?]A V2&T |q$iJoȀqx%#xw}jO_ӛz?'}uRd[{|\V-U0~я5c]Fs.8 z7+˜5^Ac@,AюtEJ 7ebfH&"?NB //ך<୹bT6 5 =6:v:M+~MjUEqf|+(m AQh* AVV~H-b]I vhG-$@wۊ@R+V erm&Rdv5ȬWDD3#3JE+_>& ["ƞME)o ^\3;`؍술MCʕE'&\s:5g߀f Q5e0@Dcǐ8>H\\k> Y3|ɂTפ PMqkEY՚L0 ߊw@^~+^ 1 |G_$;|@77.՝ŔcE\h,͠o2%U'x`bH3bVAb`!lUHHP*{RU:gwYԲKlȮe[NJ[`mU^9MMbm~|5#@߬''1r0qҵҰMcҧ6cA첥QȖ{e]eEMMHD!7DI\q}[p3*mF =%i&ŢúWDKqJ/{1q uxuIkjeۿ#M(P?7s኎3W5x_68 !nU;pY98NHc H#X:mWM|[e6'g{ J:P| c2l r= 8޷I a,(>xtրL'&&#c(N-)L2,h֕(3A@<,8cS[SׅD':S8xiLv]];gl/Au@j;*dqC}J\~6GX EԁvT:ZH<.J/_.9cssRv<\SPzO}w g"+A;:jwx骻HN[_E6 O]'XSR ^~I@a{xjSa$V!J羚ִ$`&t^]X^̡5!leA-M6$r1;-rgb_Kα"Bv8`!>'lqS˻.i0EH\w!>a* 1zp UF%f=jT+y^E4_<Cp ǁ>xGUQA:Zv0 Y (`{61*(ڮ3R:̲n1,rBB=DJ öy蕿<<#`WŤɏuYLE@jZd`&qzxB(>V+XW !,!o!]bpL5$/?WQFN:4S=̐%ˢ|szOL{}Otk0f~+n,X/6`A!Kz_< Bl~f(^g-| ؑxxM͊C! veGcdPg9[\ 3=?%ƅI u w,7,J XA|5@ֺ׸6:qf󢊝9X&H{IQVw\-_IPC9>pd& 4$iG4NnU4V0I"}F$ߕbP儛%x ͑U^ Z~~F!ze& Yf^c}]=xOU РϰEgO?AB*q8/SRI_QOV|T/5 gHW*9eB~si%wmqA666m5)ee CM;)P5Ⱥb[ġ±GbJ@Q0;]"M\?wf )aać FZhWG 9xy^u=վ C-5-aP(]qo~ȕJfƉh9||{o{D5o+A.O6;)^}ItJEՊ F-. 1a/n#&B@&pz_߉@:_gձuYłk3o(T~H.ԇ1ghx3J /9Ea\P&)mՄWqgvIyq )~&g1P1|u9buzK' ##̏ #A>M㉨f%dEդhOrF\vTx I"h[9椃L%.IdzYk3ғ `UNȈwO&JI]T R#La4G{DgU(r>V a>3ursiu^,/9{i̮ ԗuvKe74`;R3Z^Al}ˀ~vq3轢1zL |9O0NnG%btXBw1Ѭʰ m$86q$[x&AkG{to&v!,&eL3EZնɍ~G]$%Q IάAjYޯnOjDc!}r6Ջ2tU0wqPd JL~7y]~r">H4N5nfZ?*OEM莗g[R5IW.c?G҄W3t.D}!ĦS*LY % ºƚ Tv@=xκĖ|U_Eypt!Bَ 6O㪩##]z8ӊ&͢C*F`I=ʞxI*0a^X봄.2WUJ8'KyɅ1bn>JaZbՏD leչWU4Yj,E.Xi/ ~Go+ocl|^C!̝vadxVF`Ih'#Rnq:"7 b#ʂۋ<w/rexu)G/+NrZ69[LepjuAA}x^Al|̍X*sW-DGxhGg/ 2, 2왒0zS"KtQ8*xעD+ˑC7Q9}` eSeg)4ۗ/ǫ?s$r yP# ;xf~y im(,~.%zƎ"x%S:AClG6m0P8,^dF /+ ٮDKVÿv,]u\!Z1nj)spZm JEN˵Q|R!)Hs-O-*7KF {it haí )%L&H/U9ZivERik'k'> a]90R쓹?kr.1Z-lU+4K֨1iz0k0խ7.(e'v\q5=XL jdz+?ȋ5N$c? jڹ>f~@~\m <eRo)à+?Qla+.45>1я/ˬ+6$=-FLW$u0N[2~hkeo ը`}1ȆEIk?Ei)ЬKM?]$sc5mXRH{JTE" ?g]FmL5/=Էie%QSSGaOe7vʊ ĨOi *+% ̏EʿЎٱ MUM$3h65s D 4]>LPD:`%&=~Zdz-$VR)OpBj>~,pSA/xz%۠z»]noϵ).|~A,}Om$q1*Az*jE*sD1E=-c6@S-@9ՑiHl=cLb1;"|M&_W{e +@.i:0yܔօ rr}o?|"гjW[#)uJA5J$O1Tٲ`q}ʪ+C ϫpǛXJBCЁю75C~ t@`%gbu;+k¡kԴopde]?b[gRǍxnybV lc yWo ;2X4X;8f3C#n9yG(w2&rѶ~ ";`W۶D|y3>h^r_巇>>-; K!LlPh32K #5}ucyGzk88a54L\M7; g. {m򕿗?Y7@=}oÆaGr$~k= `,gIO_:x?W_g/6?E.T5M-] 貾[@tZ&EV(XwI?gNAzCv|w :abcF+̈})Z/^m| YϢߛtBW@1+-jexfy >F%taUTSo)}7sdiw]#AzM![?@8Tn587ͰMz0bS:bU5hl3Vܱ/N\ٹbnCҎjKQ|ẅ5.D)m6;N} # jǚچTD){*8&kvGn{b~2m@rb0xſ`wr۹hT$T.av~Se< vΧd><ğgCTNˬ0g#_ T1eKiOzK)ۏT5_'&V#hף.i>BY/pxL=>WGϑwEϡMp'!M(bgUZQcA`} [F{=_Sn3 Md}?.Zw6DQh8%{gOhjx%+z]矺)Gih5&~YÎp@SN(Scg^2J!!ɳtM*.sz23蝣לNsL7_FE hl~6︡ Ǜ@TiV$+iKꤹwځ VV%v&ZKy7F.1t-IɾvިNTC^BK ]6G~'U7qvʼnbrS0ӾzΓNoO˓Y)l"jڤ,S^n[7[wyĕ{[BpVjYFQFb҈ybdg,OR4ê& S2@F=nt&s@xŎN}-h`IƑBT1]f<{ x2r)5E0ddؕj5\xT5 .w!c+fX_qT ǢiJ {Q_f;c0NN1s>˅,maɀsMsIZ[Zn tWxOaNg5nM7?Q^Gnqr2vECHo[UY8%`L$B׸L=T[@-W0gzVei2FH}gvCuGǏIҖm@Z]isi@I g8M:lOwÞ}] @x\ʾQÿa#V@ؽ \tYQ6td;M>(^B[q#W95 * mhS4w_=8k}+-Y,b @kpW2mpD5գ)\6%>)c2,JBإJU TU2~'oa{qU(B偛jZ^#U߀TZ]3l=)!ܹB"* r*dJBa޻̊m4]¥jى & lh*T)"\,  GVQǧ TW4`5LchYWSLұ mƒg{ [HMC%xp;ZXA;R#ס"khFqGҺz/E;yPIѻ꭯YP} ;8?}KZ1T.<4m lQēQJg=ݿh*r7IVYlWǷX o_E]h-bR֧{W?32:QA$\L<M>, ?:oC{Q&+mxMxxJt<|EJz+C% A$  q~˸b E3N%Gf Ginɻ2b 4cKp[BM|-cҘ~BmN??&CݴZiG#}?=I:n&PzŪAowrWB)֖<kV:<7nTd p#9x;B+R?pYqD eɺ@`{ g(IPS[ ^Q$f˚@ p-A>|MD=a㩳XꍹLioH=}UړbPD'J4v ]u@] /kpsg$&%fJDJsЋ'$֌oۆZ̪ .LH)Ue⽞Zd:BߠD &TT %N(0}*/@ >$ykI!2 ]9$TUAvZ^^)~mu~\lg-IAN0tAA W3EX{B݀i5 dyEj=08*X>YHxX {vSEgCl\:|6T2YTY'A^&y D {"L -T={e~Q9̯]ʴtJ&zn9YTy)~yIy gH> u$F~Pf&OʰP5ng?"*F ɱ+Lqpe@8hM+/_WhB=ICV}JDɢ,MKFrG%{C]Qlo`IirgeV:1;Hݤ!F { ?O3r02Lo]RȚ[1uqTu"HEpoZBCY2=L6)1nsc@O<#؅!J>&絪 8N]G:v\ϕBO8nQBHWMv<HG.é42v"ZRѷr}'mp_8R,X~A]7%Aύ9gXW:btg9NKjg E{*cICüZs dFbP?o#g,NWP{ )4N7}ުm\6ZWȧ؛5֪)_3͞{Ҧ<lxF5{ 9*6oQў6?# B7Ira}t)y_@,ߴ%v+*OHIFxOK8+$tO^[Wp\w(O|;j6 Jj {RzD[`bhxm(]TMXY7$|nnQF+(a Zo}B_;X py ga}!yE LbEnTS&.9nD̄kfLC"&ؚj5@RA%ghc< A `ؚZ8+GY ߺ#s$>*E!a|uG.OW! 񘒳Eã?M$=Gf# %)u.~T' *wtm"+-Us<=V v J]m-~I"Zg [Oq7xҠ"B7.^@D6;tL_uIps2ˍ6rYge.|0NBɥ||v(NBя tǙi7qQɷeǍ(&yKRq;;i7:mCUBwGlŦ@iz1G2\Ƚ(Zٺ{$rgu/ʱ8%]aZ:&R/" z3\vIuXГΑh7CjitdgLK7j_p]N}bH!d+܏$]P0KBnQ=k |áW"po{/qOkXV3a`Zn N6U,S *hs;p\khko.n}akCHOpBfVON(%GC͔ wohpՒ=unmŞSboKf;KDyAM_wG:j۰|sZ j)ŻßCEa, ȨޮT^*iɽGv #3FsWkg?[ 'PщezukUS6O %[I &C߸hӼcu.ZAO=&xY]뼡e$bY+{* F8%V.[_fO^@'H&9:i6~7.풖 bۿ۱iCc+N~:xߔ˲0F.d<=?]`>ž44ӽ$*vU&56)$Q}2"mJ6ƴ!?j9 >/bד)`ݩjmMo+uGlqק5F1d&Ǣf W[̗r,܍[]|w9ڪ3Uq2_RNUSmONy\Y*f@Ce9F.Fb$3y{ tѣC-9O۷X3B6@E73C6׍Mn*JB\PJZ)-`Bnd}YU(S _RU`y#fϖ `xd+p2uLϲtMtѩ犓ZQMH6_Nǿz/8Edn'=il{ؑlq 1gaBZLe d܁u|ISW^Ͻdh3 u`FP\l0:HD@0W!3qheVҀ1W/VnJs̝20S os8|~\fb,FLl5y|` ҴM! Y],I " ,}G>Wv=r xr9V֘<>PCLT]jy—lEo21G!~H<]n3Hk4EH={3uTRi$Ga d -7Y >p~8!rC,-#,z8Ky2' u=C8@b7Kg73jīZgѬez 1#yJLr|+ ǟkRvF!;[FKb|9 :9js8NRW A5Yr3'V[-1Hǃ[l&"9+fT#]+5Zt_3𿋊d>^_NЬw릜e!.IxoGi%q@gKd/,,mZZd+&k'!b9=VxiccE<6?&Zvc#-q_ͨÌV`]3{W7Y+"2dc5jϸNXr(f9OqIQQ7(ܸ<%V#uU}8~6v]c4i1qpi.] [l 5gg(tBVG..+!t-pPgdJܠ,mURS;rއ 2 2A 4+)q2*ϩ]-iꅎjTq쑝2ubj0pGˁ~{,ObndN\5m# Y \z+^HϦ+k1Ц]z(֊uYqOG9K"u'H s zrk-BTQat4Ы3R1t 1;^CR26q i4>ڒC:.!rxF~ ʨ=RYxR𣑽aYGH67A4T)VlNBp*T\ )F4ʍ!ƷwI7"`ĽiF+_`-a qs.Yѫ܌dۨ}DE<2!7 Qxۥik2 wkRToOMp>f2lbHJF<M4F;-*te xSuXS R,C,K$7j:6Rv4)g7| o̽LϣRxE]'/CṚN ;5K!#d =B@ Lw$ϰk{3xm,sX%Ax95+Z"A,V%%\-M )҇gd?-\^xCf+z`gs[Jm!dh Ap?V>['׳xP'![ٕul8R}`gzg,M0B2Tq1\.JjvF8_!i U 8`79[ckhCAԳu4YoFe2銽c^u+4ea7NX @doHC!=eBIB;Ƚ=/* ?91"tC_-$|$_AH\1ݵ 6-%I$)'Q TC70q?fě5IXبoY oMDl]/@> ׂK(-L5}'DQid%7yݬ?"˶ޝc:ΨV3ALϫջ?:څl;HJI}_u׼GsOt]a.qes)0|"oMӑXL *Я8=KU5,#i]F'!j)i &}h `>#tD 6Ǿ%mWm ?QԧO%WŹ: g׶?)U{A;6eF{}cǗv\`:JcJArtMUr>"`#(Ṳ!+q^:Ctz 5#H'XܻQ]su4xQqGJ=ۆj$1/"9~{ިD)EK%#08+4cM &&lj8Y(hгe Y(*K`2 u*﷈c $dEb)} V30s338-\wJS4n6ް MtU= P.-eNJVD\䐰Ϯҙ"ĬlMNxzle71KC,(g3Khj.]c-O͒^08#-oTYFNjv09Ž7ZS Ϸ쪻z.}QբS C4GV*0P[BoD;vpZTBß^VdOݟڭzyڐO:ݭ)J"^P!-wXz8ut:Kxa btN%*mgP -,]:[>O΍?غkN՗doTS=s[0Dc'b^|o TtŖh׌ 8_r J8v8,6zgLj7%&+0mr4Ѷ B<rv^<Y]#$` Pw^9Fךci;]p^m~w2!Bpf'"QfuKuX-,'̗I3i {"S 7i#Vx:5k7!LslѸݩx\DњQk7̂$G&2yIN,6+g6>o9FEH)CFIIt_$ IX8p ϔaV ud+ m[{ W<|sP$!GGApdh'!yz A,r)m)~؜*( lbkp6iYR&]Q9X\oBdz\q Q^Aˏ{BJ{5 &%ɞSx0 XKE*_5Gսfn&pRYU#}ߢ _96# %I r ;yC8P*bUA],P{g^A"&(jI{=(t+[êRIsd+)j$ԂX%YޫfsϧrkWloLV#0LzJmΝ zŗ6l#GPۚUXZEs`3}Qх/.-Qiw LoSF̉!& ^IWu2fK5K9; d_K װ:pCtt3ũw m H?BIl:r|~l?[ҋ@ pI d1/kqk|Q}V` ؀3%y7)ǿo2}ζdafƸ sl 2g B?:RyA俹9\dgV xXh.OF3.VVfOG肹H 14־X 0^-2Y,4?\iFW$ҵze$:3>&b$ox"E*W )l!+, >P/?0G!qwo꬚f_2L4i-UXx/Pk^s'{RDpnɩ[H->k+{Y~{˥7+Led<5䋂IF;΋y鬲x-sR:.^}XRUF{ Ҥ@9}l-Q˻=蹛$e!gJliu,B^|qFgڪ elr“3&:4CO:!gY D"k~M-~,P)*U/Zg>V ]Tl;;#Mka )V4DGN9j5H{>!F%nr;1F(l'(nAKK6 Rg6rB/V,Z[Y䍷6@^~y5π;$7bbB9Ju,}I/b՛+sEm {% >W oҖQ(Y_;4;sfWd-r$%o\Xl(dX9X<+7`1mjnMfe n6M\ +*^Bl&\fq/R-FC, ^Kpzi Kzk|t>=]a v*XFk}݃!=fм뿎dߜf䒜9s̓7Q@s)KZy^Pɉ1 8%6&W) x38 @Uۨ8Y( YL8npQ"<[OJ )ɧ4T$̯UEC@t(t*, $j?'̯JW)Ό;,܀W~u%kU5;} p֠zbU,w_䌵W:"VaHÿ'x_#Ox8\vhՀؑuU Η0lo.%.:;\ OD[2˯F  klf)}']己B炠 mƬ] 4 Ҍک(՟#/~j3LQ9m$-pArRSY5kt&"t!5\{m ;Ӹ Fg" S^OX#8rf}̓"lPwA@ Jcvĺ7q;L6f@UۊWitSj)`ɒW]_0f<ъ̰O`ͥDp}V|%om=%QkﰭyaO}~$COXbDx!nKa'-e+H7{E!_aݦQ2z}r>ɇ8}ujff0?*YW `|z%QϾQ| ̂-<;6n M٭>z7.?inl|A5~C7I'x:e)Vͼu:{s5Ʈh<Az@/s\ɉY\ vˇBX98QՌK8PTu CަmTU3#Ls-`O(wJ!bBUH %KA|UlpD `))xrw"TFqpOG~<F BK¶Boؗ1б,pu Q6,#Û¶D[m9J{q~2(ladw0Ŵۃ^3jw1 $/x^ p.Q&!.q9fӮa4Ț&V|/hK꤫eߔ!HWRLXEi&wIPRکBzw 9Ҟ(1"9y'C#8zd ܳ=6V18@. k\UZr )G.fOFه|ܲtl0" ,lsQOO/`KfsN#>Z-!Q.Unttx͏3}tME.)Ωb> 1N~,WEn3Ua0Ӡ Xn3*\6p, p.KQu턼q`\+%X$y^b#O3Q xFѻ0+-wdy 3cy9%;Q%.䄸{CZ_"uEW9x*Ǐ<.bvU!/hǸm){9tMMO.zYsQxWcs {tiԊ9芦VIF |5"p %}* HrA uXpĤ X1 QL8魌xיD9v<.H)ӚTo85=Hq-dMkZ3p5HoFKgYd$Oe(W+UPckҞԍ"Z4?wyv=Lޕt] RvӜD$yx$uyԶ̐F'F`&Q=\|15&X?rNt1@nD"9]:LM~U>TEh I%6n(T.iH̩x "'P^ -Y9$^44wsvʨnt *1XφQӂ%)F.{ςyq(ZrAra#0ȏ^E) H>7w b>)~Ĉb8qP$)1;y_sE2 B#\B<0*W(ؓ>x MW54{(d) !Ukԏv 93:x^X)ҤN88Q㳶ʒ9-Ii^o +,FEyg!fK`z&6$*ҡlmٷrVc]1T_+qxGx8ow.""bLjZĘg,a1r(|È̹h̾GlrD#.4)aD]^?'Uy`#C⾛nCUWvS/x[s+nE$@ZšOg#5'[>d! yA:Zzы爆}FÞp PZsa!1KAKhGXx<ӳU{:g/ ͩHzoUH5F28jJo9pt`ֳ_{")r΀r5zr*_-) 5T'<qNv:^/4 g "fZ.F li9<,`V2 6Z(p&_0Ğ;.Ν`?(FCvwϫA Kr멞x6>AZm.+yh|Zp1}g !e5R(: Y][`os˄!G#]K&kbhcH{4"S6B~=(7cuABZ8[Lj2G>Ӵyh {㶉TХ,~4"NlS6٨Ihs &]˔RQSfL/o=])Xޢh*c3ѪxA]U4q/Nౠ^ *wC(jYG%1T~-6L3@],xx3a<x(lZ AΤKzŭؔf\VrjHw8о \\8ɟ\4@m7]IqӢOUA-bɧu qz圻[UuzC` @lVa88)#g9C{~\2(Mm_⒆s1 ͫ^Jb.N,Kێf}iAu'+lZ9r͕=w󁁔$e42 $K򰦭úD;%9}B[v"3,=rF-YqdĝPӮ0g_SɞX?,jz)t\-_>u$W+BE[NkP|Gv:[ᙦDpb:*Kxb v5aȞ%x(X6! !RRjz:}ݛx?bFć\?pDUt灠o+-O:Ztѡ _: ᳋PgnM-mk^ܱ0:5 ۮidx`V/sJ*wB02=)n3i:+rJܮ1Mlaˬ%؄V=G?5$μbD*-=KZ}!߹ sq$(]9YD0"XYR&f"rP*2c ۏnPRGNeH 3ÐGIvADwJq0AGy_ϫ`QB4D,g$ylE5 Ⱦ lid1V~b QHEia ir,ּs6)pA9eɂOSD|bcdFRj(-":6 ]N sx-Em͛@Ҷjtm&'wi-&{RvN׉U/ayĿS8óϹҎf62qbzb?&Q\T?APSgu[u+c#*7tQC 8֟h:E] Ah*jZ W++]hflmo0ӔEcVC'rP駘UrjFb}*^&Z~!ব33EH'6]cP Ri`-Iɢ Y̞4tuA3؛U%I$}Kf)\eSKAMMkT]ڛ;J^- 7b^#]]`y,r7@ƷNdṛR8FgwYȔ:*TZe%$PbD*1^\@ᏸ}Y2`%TeT&cDԮTa `Qb4 H ys" a.h_sDpzJAxEڝJR_Lbu3JP\n▆a._BSE7F ',ţpl̞ 7[ 0S3</@))E2_oVm;(>GCx/*6 XUonz,>۶LqL UV_9 o7Bd&ώDGֿ b0S׍T {UܲR+ԐtV" ֥X6^Sv}c@ 9HHY 4%`D>j)( Ű:Seɠ%D|z6zR_Ђ5_jzѕs?d|(Mw`z_ՍWd9(7@9G0fLط,(B異k^&"`m&cqCԇܒU5EDB3Yi[NKK(^VoTָ.u;"y'$@s,q;̧ 4( cCPo˂qPԍc xA%$Deo+]c6]bvfEjFpf&FHPu.gFdWDKLVP=3.ߕrϢ.dCԪ =3czR&zE% e'uaq!l,wR>c~ j4vnPubt :_ZSǖ}Tv P{Vc%F $z+—xU%mܤ]ƒ*xGԤuS0~3Ήz.E.=ЛG70Ә |}"}j{wPPbr[f2] XAK:/ϖA ԜI#q>xո$HjWv{/YjBԎZo7TZ˺ge'AU=E&Y? _,:봀pci]ugM]8 3JDny&eτ=~$G@O $fws18;+'}8r|:wâ Z.Q99P$:TASDQ$1i:4(;=ExQ#eOJ 4uCfCZw׷+ zwR?Y/C" *B[SKA1Ame50I1~,A9+bghMTzKWɯVp?=*y?Z^pU.+>72{#jbB5ЬoY3! ?u})HWW10ϖf<A:Tȅhr7 >Y@901}*ďeA/VTJi)K&H!ʹxA{#jtWViD7&=Dʒ;\J#*l.,뼐WVN:бdKmFa4od[ ӆOi@t[p&hvIJ[6,;P'zI];US?exw\|8g׎Rw1U1[޾"–F8fǝCpO }_U~!v;Qv}iWugjGkH7 b\e~C6W49<u"QE L'# fL6D>DuB}^i'|Mf 싶zyI4Q1a̮G2 '[Q;bJq \xSTd!K '8(\cx S Gv;!}!fo-9`be86 X/о:=x̾J/%XE<.UëW>pH`%Y4&TïsBFo~iJ m'Ţa/,Ëч-lW*w%+""ӭMPF'ueD  d,1OS^Rghz E9 ӪMo̳7?e'l77,^};M8:Q "*ifV64>y>u@O3 zE_H+<(p-k;Ƥr =xz9C{+P5F]˞nܭO_yGh(lS}6eb<ۊw&{5L؁=]4h`T]*hK@Xl, T!nRcM4vrvI?z \?$W)++ /{ECh1bu <N\pJ EHQ<*I=ZUT!iq3EJ`!aUsڑ` אHŴ8s:+O.~m 1k)Qp͂9$oNǭc 25jΒī |3_a=7~Qܑg(^:*";&+oё~J)y>`eGk đ8)[SE8(K/?ᕸT_||F4Krį@%e03c\⺊;. 3e#;kY QJ~g~k[6%.! jr*J(4Q&-aHWBdq, yZz⽚_0=H+Ekd4HMRX~e|¾_ V2т̥*I$OBgy=<*j 0{?a(^Vb04\a#J:ˑ w?KQQU%C IU!?-Rv}8+ӘסS[ɍG>Bфb Q%'X6-wKOC$1\!ϸetAgh2>V%MxqS^͡YBtoA +W[0/ "medF_7V9w =Dϸ?4!i ^Z-gѡm(&[f^vL/_r[[{f2 56FEa,;ޤ>9ߝwCOUr*VJmKGTpVSXp'K'KT6N,ljO b 8.1h@s|oݚfDTnU|x ?<p$A;dʌbicdq D5iBɣk8ñc#*`k5GVbqӖOr`3ˑI\OqV1:'iƧ3#üwR&&y_ Q+N|WNps ՄQ?lPGǢج;j :#jODTEyamfVj*-õ_Z1̈́[xb G֢WO#EK)rsT=Q nfcS^ g~Z)umܿCbpv UcV9n"9S"_POQ̌B2^ /H,X ;,FsDE^ &fXQRXथŨ’Xsu*wxbF8ѵr|G3_ê~jgrb!g! >-6]&@ޣUn,Z!?i@^Miq GC@{0}iut/_b: ^@f|£Z.\]\8B>I懼8?BSsL!Z-:Nж3DS{1>y2u% Bv5 w#W 172BJ:ojôŎ_6N 4`-ۘȺfD?ۤЭڈ)UƈG_3qAK$}(_]uR@| ;KTo`yBHu//S8ܝ`IH;0' JV +1O}٠.!iNt]|,52'-H|`"܌ |oI͟&Ѝw<@0;Kr[L54ˣ5-3pfPQ0DB(ְ>ƻYbiRfe6/KRi?}!-8 HNOUPRc˙0yY'$qjm6}DWoym5-N0,J^l|(E_inK(Ô=DYICddŦxJeS*%1Lo'.(kQWo#yɏg1,Y<䄪.$ D~{ڂu vF iu9$Q_z䟻sQ;(֙L)6-j6̉vVZ@pZr <5zV£a K#M(V!r$~ho1iaq$GgWއƘV%.TP?~{^~:?6Ό8)]}24%~#P5q%eP't&uӇCm~sm8mG ($wl(z7yV@mۡ=@xl1vy~oÔn{o?% !!Q䄳n[i;@HVDkmI< l=;j)̛8yGϓV쇘>ZPP&hOdL7I"*c?('$+ DN"OFb]K!baa;bd>Uz( PHBJ _I~8ڐ@:$hYz_SKmi5]Q&j;D?i"n'iIvC!HK|lO%vH)r;>Wa"䘀Xmz~(.i: 'Py oK[i˚47Lr'R\SVh{`׵MŰ2@Lo$a6aUݮMx_pUD1͝^aXy1!ǾKX-ހU WrڍF қ1sr;5ԲpvP1}X ݟ\W HEeq:|tu+I"1Ҫ3g+7Hstew蹭FK6O#vVÛ޼6>XIc׋Yz7Q``=4ImR0Nl+%c[qtbT~E>C#fF GYo(l[\J h;ZuϾjݸt0mOtg4 i"P;P9Yi$W]ꛣ\ ? ,gyߐB`c4<F:Pg> 1lyӈjbJSY10SX{=siAؕbf5?L@'t)﬎")/DdKU%0pm[@ farND M+僤C-fȜ="ucP&WA4_JdgCif0ƱNK!ԕA&p&Ӫ6v$m}MķC}&M$ trmFTc #xWaDCh\m,yUYKh;y6CmLI&ЭMBhBA/$nET F؟P9:tf?ϱy'\:ž9ܻRJZ#Cz \[5 NX@1=,n{ZXdo[Xv"*̹iGwk?Wנ7Z LV08zW2U&G_}mA/v"9JlF0QOeo?h`&rG|b̥H\Ŝmnɺs%y d@[R<@=hMQ0wmUv5% Z2| ~ h$(^Τ`-NJqJo4nĊ`"}Y%0h2(;XI -nBߎu@0ŭ+RFGeA+uƪ&cl n`?.x r~ubKaA^R ]{Vmv$Ƹ γyMs{Lr~ .`rq[+zix:.Ƭ8@\yw̧,21 Rh֨@v>ظuW}'S cT3zujT-Ҳyܼ5sS)Y x8LE,1&M1HȨS*H*k/2!"~ŐZ#9`a(UIq›Ga+S x2GF#0U"J)}=2e< t~0ˢ 8sܽ^h릜NJSró8&Lܕ&o|ZIKfqZnNdHn| ts/L~_Xv,Z?j|dc 6#a> 1pQJqehwD[^81_ B\ |cLdti Cy}i/"OTlf126.Ħv#Mw|1f:\)6t bq=I~r)a)ls0+uc:B欐 hR!.KIԊ-"u+k.7y}5B?]s 6c`Z5'GJnN*x_rޗkd'j 4kYYNmJ#̊b鶠l~m/XV^%s0Huek x\p,#L2NWc(!G+_?n}80XkJ181yv&HC_av i ye+yt&ύGkPZ\nSr%[*Wܹی|M:$\PƍsڮТ6f ?#_x`k#aX ,7, A0Yw鏲O }Rf)iȒ:8="WQh$SiB֗OʖY"ENg2yH(iӮV0>z1PL ͹1NR<9Hv ?fu{ҕ 2:!*5 ^{eY3$2ME2ͤl=nя,֤am],bcL~lToM6zP-qojC&p R;1.վ9^hA\'SBC3S)%lA)C3F7.:?dEe1ɑw`DpOv{+ ?|iR~H4Yb_iBN/sAfKI:LB;<`7l%e!AugtKxPy/'@FDRqn#P+M.0eG_~,]0m'ʝJJzN[Qܻ'-%͊Pyp$w,[RG@}]Mò2TT'̉T6->$AΑj'j-:9e~2N ,/yG#Bϛ;j`'IRBW$!I*i%rxC>"W b|k*fp_rt=э΂aE(N?v+KD'?S$HƢp85Vl6iRե)vwPB" enQ$ ]}ٕg./f ''!%{=n-zb8>omX2bJOMm_۷P'h &wVUŋFQdxEoC8YΙTii|<6nGvqz></ GzXDr~~&ܽ5**]#piv8֣ IhtK4V+a>!jjἠ& BH$0tOMI N''aPJ=FXodHf||XA`Ҏ'7УH߼+zO f;9Qh"*}7s^ePVi(ߵcuy#![c*n1[K,^\{(9hXǭw+6EwG״PCƧa4B +\w648mghoy#slcwNiz+SXrLl*ÀlsM ꜂n_/eWeK? W6Yyky T{:mǀCBr:F(z)pL7anex7}sZFqn.F{9Fkww"Ұ7;⪥ڢiRYxJ|glz4)NbI2-oAM }1JVe+n9-BvJsaE&Ûyq$QNdF,fnmGݗnR"z&TUGV_aŻϟK_h'xjI6몠 33%V.,xDb1zԜf2FddjIlU*(u8HW\ INV&v%hEc" jDxLT uCq$p#pڛ _۰U_]P!1R2 ܅%Xϭ:@}ȫ #B{@Bg*]sphgZR|K0<ͳvz9vh3mRiS1%">tDT|/

Iϝ Bi0RHruj[]oj*,Q>Gtҋqc*I?Ud^HMan^;F?O/J(epS|2G̿heb@nf K6ty@A֛; "U,LYnOLФfN^)'<۶ ^]'s#Ƒ=HW_U"3/lJKBf N*vT^HZr월'l<BϴIe =zݳ_?'㊍qEލ'8뚂I vT%]տU!~xFf`@GiL@@ }J~B(QUϋD6DIv2*+M~zֳeͷX0<نtD_39ظ q1c6u % g9š6˽6,&m1rv FTKOS/H:h$#F/ j" xՓ{h ^:x_~41x ]eIr?6-ӊyz+H߫10GӉ5*^"ΓI%v#u2 t(#6-Vَe#T@QjWppq:P1o \x 6[[QYz>ʷiiֲ!6DqϹxAGϯ}J29dO@WC+81(*S1]֛a(އŃ( 2Jƣre\-y0 vbP)._V_~} hOϫg9 luVW^*S8๵R@}8Wm=$ݴ(??R\Y3`7kT];dx_K9mA' ة,6[(Xw)ńi"*Υw1KYYqMb\U53n%'f*JMVr+鮌#Ɩ0dM]qpRq\L~h؄F*:wy;'qJ﹝r:iQPWñpZc%*8d$ _$3W=g#nĺN+]У`'j\ `2ݧx/KhV 1_ AJF@-f--xz AO^DD+D.2%=Sm/(l+[pA?mDlDh>cSR՝4A :9u Ŏ;; Ck/Uɜw6wKAP0 Gfo\dGrӽT:}sqPwÖdI^h~,V,;N$xl\ij>l^}kTRě^Zvߺe}-Ik,܉5f2OZu7<;hP2eNH9yg%U!W0c)Wuf$jICPNC jMBt;FSGI&܌t“&c\VbMRlXb7)yCƋ;AֳB,/u%ubFV譧$ pU/ `";qIPyxRd ^&J$so $TKhMdmjäJs`40AK]E􅬫>CPQM)xKnVgh6e ú&Uw.pj~͌Uקir5'kK뿰hοZKI*gDZ|>$Mءdoa{{ɌrhEmL~([aYZus>@P`׍;eh\D(7fh%k$6t heyA "iFH~|ǥ"I}^SR*fGlP"žaa{5O4H0DȻ(zc9{%ͅd] F*#B1i-P,tMdQۈgP?mP!ee\bV?)DkŰsN3y0jB/O/Xv>A]x%d{Ǭ}Z*ZG#VZe+J9ܿ.W woѠ04 W=M`N+&h&SΩ`#12$^.JfV̒t9Y`]d'8[$0#]NDכHٽW0KG  4 *S}\%&xIΥOl {sO55K:PUϩ5Һ{ feLە4o +M0U껖Z!ኚ^Q-15`V*flhLeAMAcy|Jj6S\@ / -o1wr$ *Ll'ᬓNJ<55,ڇ-}.%{2L^z х¡ ǟ%6+V% 0J;UF{;[ѿ=Y8_= ]11|8Xoo}+:\YWM$cViSwyA)ڐ: ^7p6&s>#| !0kUl$9"чVEŸ[EgAowW.Xo-wϴ"ny8iZihA~_#&5y~ٱ&F&6L*oY\Ux|/)Gh‰auш@3BS|`f ΜZC$o4ŻHv;OJF*9XQ'gg pI4C8TczGR=0?3{/W4\u@a|x:(2Q >ņ2ר}9Zn r55N9. Eb}Kd(5N{/iHLt=h۫~Mm6r}ض_ o@g<@b`U¤AVO{>HPr#Vɒ9? ?X.e1x9`W'72!"'4_F_Q:Ƒ&V\"ziz*K@-;CG)Vm\8j S `68[5Pqє=!}F);g|Qa&oLF }>[lE$hL"Q_рJW>uMwP @q} _b ڌR+?pQ 7obuiCѯӟ`V4~TMq,lȝJu!.i%OQx?Ǻ< q xB<vV]Rn\Wo,80Euwpx=Spi>S"-jZ_B#NLJ3Z=c ܀mR"qAa|dOJyKS%3p۵u`,bn' ~t >;PN*Y2aW%WgA~Iy`}2.]윹.߸2WjoCR3Z_%ʝqU\'o-aZC4x!;Bi esўdlVI{yV+FB҄0\ ̭#('Ae_'&pr D ;_|c чo\W7[wHkS_uvp ]CHw"%r& i 5 m1Vh;I_ vbcp*?B~ښ4ƽ7Uvݒa-ͩC-& ^]"oJo2LIz>P%:Qd$)ӵݵfĔ̸O  &g,,T%=!}<YyN{h; x< &3`}_WJڟ' Ì#P6e.;j* =O{C*iWJK/spPCGrdZԗeeҫw}Ej&m;Ņ@5m?Wd{XHnkׯ21?DcZ8-+SUPcRyhm=| ILajc"K4Mنf/P*9 C 30aqͧ~{c팘a9*q }o0n3Dݝş|,)܄~T9.!O;5׮zxOW,4-ߢLjxZ ߊT{X|"=k y &;;̲brwƀfxj6vt#1<{uJD{Y,4I3HBs Q#PsUIC"T*wۓqmxo%opa)Y-/3 es֟Pܯ9;4V:X9c,7nm'SW~Vޔcoɻu9=5pЊv484 U I}nz?5 ;=cB&}#~{ XWI(kF3[e( Iʛ -rHJa˫G^|3r̢@[":X ץA|kF< snDw4HTm'ћMYsHS(%8Ȃ lHNԷqtuG e.$? q)lɲlWuRot{CI1}x+pЭ RHKӈP7'LiV|c{K܀  6I { Yu~ۉzfN 5FGJ&lxCIŴ$ncx*,L`AcG6Amh"DjC!ïqOg0=u[ C?{tzlXӑ?.b>بE&z8(iS֬g=*1 5)+vIز#M_ũ<~!`۞p7q"WE\tBI/V,a0x.> ]QT0o RmL;'6Ν|;N[ w']e,'Q^O*㧏Y<.w%yXRD? +֬>7jBg(6TS0ucڦCs Qwy}{z!O6(ݹ04hVavfͦxb K<[Yxa8L7.((sȎIG7Hl}ѷW A,!n:RwH\*pԲ/Lga{ZA ˧߻rx n@}ϟI{kBh))cȠt=T<XdaiNlތ i#)%Z.Cvc{8D$$lE\hE#*{<|zh!;''j:LTlHiۓe^n.ln&\2Ia(€£TޏdL\6e'ð!-s֗BH^*z}C&+A:㪼G>g.w (n 䙳b M|J"\XCD|6=8 -!p LW(ŷT~gj콓#wJXK E%d$Ѹ3{z(C*c_uP&EYw`C/d8N)˻E21`wųŕ2Su ?%5H\/x~OR>Rڧ)Yv`x XT ݤ%Ki&:~w9['NwI[GN :R.)UUnru{*7xȧ{Mfe̎ޭyYKT[7b1% E?"#RM;p`+if $&Vִ3\BgcF f QlMc dS<hWZ<AQO oD6"=ؚvpE󴋭5@0Dv@*g4k2!ӅآPG^Z|Akԁk^V7:!WOPv],[Ft_E&5b'l|]q3J#_aICRϱNb(8>4VCDwM(,"D ې);@ ƛDodo >8[i5`qݨEE'!G3hjzgZ) hOپR/a8D]M*!cK4Z=٨T (M@ `AH,n-J="H)F v:}` tSVeTʕ3)9dSEouc 2,gZ+:T%I۴݇/p_FY, MR w7X%ҙ\q*=Alqblϲ%i D'ُ˦ %yKkRq-}C& ɛ5;D^ m's"pa W3> Q~!>v܆ߕ|{Mi %E93@߯s4Ԗ3D h^7@`# kNJʀ) pip3;p~ŗGYސp/9zǺ”%NvԆАS٧<&֕=5{ 7iCKH<"_,'̅!Hl0!hˠx|=Vrw-N JXVw \&U'h^Gpt N *`@t(bF0F] _D+UMɯBj;kw QN4qu j^oF' [#6M%7`5-mD!e6S3mᲆ&eqLӶFeEin[(0a(j{XW.? IoWw%cȸ#J>VVsrR|pZ\)b&_hxFV3AR@!HagғUe;[Ȃ_DGm8 Pa5MNʾO V/QSz1\-!>Yq{Šȋ77$E;l]j j݂f(Pf\,߻mZucNJy6'7E ؚ{]p・ ÄY nhG܇Lk59͝߁ו!?ve[(ﱺy ~Ĕe䭗b'XdM^S A]Yb0mvnH [ J$~7RPNP1*UeoSXqC:c/޻N=&f=[RUMo(ՑEt;ݚ+ͩjE"J,'EDbD? ق{u߲P'H'4޻1Wrh C#a [N6rv\>467EmMmyxyWԼ#p;i=\0{K襘[d)bߺټx/.sɜk]ё8v+c-)Bz$<KXAAvS@+|Y&J&R[PP.v7T /PF(})e䍞-oDL %w\c7)?MYԴdYy~|]U@c|da:i1M`}yhr70f]='6?tPH0W@iodUי{wE^]4K*_҇1'>_h@L.C?||fv>Tyn[VH b3HA%]tҜvo \6)TafWIExTC9}dJN3]y5@#<+[&'_2:7~M^҄$m4;Kcc5.ӪK.(--y7|J!+MU<>$(AFLubr[jLu<&t-F}ZtiɲN~{ofRNgBJiз';;GҔ-?l>\(=JI[1A~0*g-K"pTQp%V } ޢެj8@@C8EgUz{n`ՀCvL Di/yn<3*gQ:mVNSZY36U*?(b$$!|MOX!{_ (%Ϋ[ vֵ .V!T}Qc*d![uz'J*G7;0z!6c#g\: W?z8Nbmet{6@C֔n`=p]<BsL.ѩU9pN +Ȏ^&p#Tw5} ШcT~l$bKLiQ,zTXUOGJv%sQWК=.'t!{~έN@`}*g6"E-݈r<U/f[׸.6p}GeuBݙ9=TXyQVΐ+ĠF {m znly"rc$sW&;YvĖT!ߚR.`|EoTZA `yG,OT\4jh9 g&(ĭj&r{7DQ?<֣Q=%^CŠ(t3ɖ\ /mB5x%-89Lj)$#aNLaNyy06gB6G=]}μG8{F 8 4l J 鴉>2>CIy s0ۣ$.F,(3\ߤ}ӝ | fteE|>raunZ5|KOQޖt?NV EzɞVˤx˹ob0Nx0]mbN7&dzǼ~Lfi2l7 ͛09fa`FGJ MC{tFj(R̉sdJt4XT }mq}|#?QShIpb&lz gZYG}SH_Pˉ >NKVDu$_nUǣŇ z1S g V0Lzȇ1.BX'ӔHÁ0PèH\؟}J:NP" c_E{vYp h}SR3rU5;&ч%)^/eXp`]M_o(F\p.|YBiӮyt,L=單FݿO޲x)9L贠;/,rV5O$e%>L%p? ]#OI3l79Pk}Z|y|.PTp;)Q ,ѱżi -^7)~v\Oc3PaRX+KQaK-a} rV\`UGSu\,)}O8e ~'fѢQӞtnWPEb#,QU{Cu:R3558ILZ ŌF'h,o6pFAy[q,S\)T1΋2[j<9ο͔~6b!I]s(sa;/gh:R-G#"!yz,)JR9w(O+p^DL][ #Älac*D;)̘&>T5|$fY>Ls>e& Yށ79 uAܶ?[:\GLz#,UMHbm˔h٢7H2ork18?n+F(W$1ӼZSgu-+3ΫFф!?4T[, 5SfC :'ռmQ'قjglW @2/*c 1$ۀ .T)S+5-r9}F7V0r !l c"Ia8l*nm4.?O؜T?ܸ~~ U5H%6vawA}'ؽ=m[S@b*~0/lT?IQ-p:PݰXpK_ݪn}nKq .?49*Lsy?rJN[c,$-OZFw lP-3qpV jՓoH`t/Z'5 |H@ שh* )e| KmoVJ*IJ}d E방,Nǡخ#*!/tab N- `bA7/q`;OIzu\y|O%b< 돀 =C]:|'0$7 Ѥ*cn̻AH| %]7w$LKI-Ug=Z񩪬n(JTd4`^NiT*7[&b ^ Im cZ<uoi=CSóSn*W{\6Y$ud5Re͛cWܧ@j#B ˍƯ%W"qvvKzMoZ̕5(uc뱷hTB:* P3t9^[TeǟiچhL-0>H€؆3= rF/{WdW`gbN'dGo^)JbQ!׬ ir~*9H^9uLjQ /D9Z8"-tc(+4ι؅15?T>SА/TQ#][@_(1"cE5D/XUXrw~DI$H<6R%8xҌ2GzRT]9V@^dsOfI؎#/#Oz!g.'?-9^ ;lfދo2IÍ ^eoraH-ssl#\a96c SlT7Ntq u˙L6EaIdge4ND6~G)ZC k݈Kkv CLԘc#\.PzXp'܎ -#HHny1g01.YO`M(KA{c @_!1٬!ZГl\o !G<=?ށ}&J/>|FҪ'>K!)B~.lg%ܵG˛.+z%1,;#J%[v\sQkYݬG3;J*UyXpRO 099 2ܴ#)lq%km4wkܖ5YkҎTb9uEQ&Z0CЋc'.b15sٌ^`mGC8V8OvʛC>jLъv%1gYQrip.X3O{\/ކǼ8 kb; x2߿ ~&Xv! J)x}(7+?jU1~ijLגt"3:DG _qXl_BSu5^韍fzBܳ~lNvt t-T`ϡRw?9-~iֱn·[]P ;0YZsystemd-229/test/sysinit.target000077700000000000000000000000001265713322000232342../units/sysinit.targetustar00rootroot00000000000000systemd-229/test/sysv-generator-test.py000066400000000000000000000421231265713322000203610ustar00rootroot00000000000000# systemd-sysv-generator integration test # # (C) 2015 Canonical Ltd. # Author: Martin Pitt # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . import unittest import sys import os import subprocess import tempfile import shutil from glob import glob import collections try: from configparser import RawConfigParser except ImportError: # python 2 from ConfigParser import RawConfigParser sysv_generator = os.path.join(os.environ.get('builddir', '.'), 'systemd-sysv-generator') class MultiDict(collections.OrderedDict): def __setitem__(self, key, value): if isinstance(value, list) and key in self: self[key].extend(value) else: super(MultiDict, self).__setitem__(key, value) class SysvGeneratorTest(unittest.TestCase): def setUp(self): self.workdir = tempfile.mkdtemp(prefix='sysv-gen-test.') self.init_d_dir = os.path.join(self.workdir, 'init.d') os.mkdir(self.init_d_dir) self.rcnd_dir = self.workdir self.unit_dir = os.path.join(self.workdir, 'systemd') os.mkdir(self.unit_dir) self.out_dir = os.path.join(self.workdir, 'output') os.mkdir(self.out_dir) def tearDown(self): shutil.rmtree(self.workdir) # # Helper methods # def run_generator(self, expect_error=False): '''Run sysv-generator. Fail if stderr contains any "Fail", unless expect_error is True. Return (stderr, filename -> ConfigParser) pair with ouput to stderr and parsed generated units. ''' env = os.environ.copy() env['SYSTEMD_LOG_LEVEL'] = 'debug' env['SYSTEMD_LOG_TARGET'] = 'console' env['SYSTEMD_SYSVINIT_PATH'] = self.init_d_dir env['SYSTEMD_SYSVRCND_PATH'] = self.rcnd_dir env['SYSTEMD_UNIT_PATH'] = self.unit_dir gen = subprocess.Popen( [sysv_generator, 'ignored', 'ignored', self.out_dir], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=env) (out, err) = gen.communicate() if not expect_error: self.assertFalse('Fail' in err, err) self.assertEqual(gen.returncode, 0, err) results = {} for service in glob(self.out_dir + '/*.service'): if os.path.islink(service): continue try: # for python3 we need here strict=False to parse multiple # lines with the same key cp = RawConfigParser(dict_type=MultiDict, strict=False) except TypeError: # RawConfigParser in python2 does not have the strict option # but it allows multiple lines with the same key by default cp = RawConfigParser(dict_type=MultiDict) cp.optionxform = lambda o: o # don't lower-case option names with open(service) as f: cp.readfp(f) results[os.path.basename(service)] = cp return (err, results) def add_sysv(self, fname, keys, enable=False, prio=1): '''Create a SysV init script with the given keys in the LSB header There are sensible default values for all fields. If enable is True, links will be created in the rcN.d dirs. In that case, the priority can be given with "prio" (default to 1). Return path of generated script. ''' name_without_sh = fname.endswith('.sh') and fname[:-3] or fname keys.setdefault('Provides', name_without_sh) keys.setdefault('Required-Start', '$local_fs') keys.setdefault('Required-Stop', keys['Required-Start']) keys.setdefault('Default-Start', '2 3 4 5') keys.setdefault('Default-Stop', '0 1 6') keys.setdefault('Short-Description', 'test %s service' % name_without_sh) keys.setdefault('Description', 'long description for test %s service' % name_without_sh) script = os.path.join(self.init_d_dir, fname) with open(script, 'w') as f: f.write('#!/bin/init-d-interpreter\n### BEGIN INIT INFO\n') for k, v in keys.items(): if v is not None: f.write('#%20s %s\n' % (k + ':', v)) f.write('### END INIT INFO\ncode --goes here\n') os.chmod(script, 0o755) if enable: def make_link(prefix, runlevel): d = os.path.join(self.rcnd_dir, 'rc%s.d' % runlevel) if not os.path.isdir(d): os.mkdir(d) os.symlink('../init.d/' + fname, os.path.join(d, prefix + fname)) for rl in keys['Default-Start'].split(): make_link('S%02i' % prio, rl) for rl in keys['Default-Stop'].split(): make_link('K%02i' % (99 - prio), rl) return script def assert_enabled(self, unit, targets): '''assert that a unit is enabled in precisely the given targets''' all_targets = ['multi-user', 'graphical'] # should be enabled for target in all_targets: link = os.path.join(self.out_dir, '%s.target.wants' % target, unit) if target in targets: unit_file = os.readlink(link) self.assertTrue(os.path.exists(unit_file)) self.assertEqual(os.path.basename(unit_file), unit) else: self.assertFalse(os.path.exists(link), '%s unexpectedly exists' % link) # # test cases # def test_nothing(self): '''no input files''' results = self.run_generator()[1] self.assertEqual(results, {}) self.assertEqual(os.listdir(self.out_dir), []) def test_simple_disabled(self): '''simple service without dependencies, disabled''' self.add_sysv('foo', {}, enable=False) err, results = self.run_generator() self.assertEqual(len(results), 1) # no enablement links or other stuff self.assertEqual(os.listdir(self.out_dir), ['foo.service']) s = results['foo.service'] self.assertEqual(s.sections(), ['Unit', 'Service']) self.assertEqual(s.get('Unit', 'Description'), 'LSB: test foo service') # $local_fs does not need translation, don't expect any dependency # fields here self.assertEqual(set(s.options('Unit')), set(['Documentation', 'SourcePath', 'Description'])) self.assertEqual(s.get('Service', 'Type'), 'forking') init_script = os.path.join(self.init_d_dir, 'foo') self.assertEqual(s.get('Service', 'ExecStart'), '%s start' % init_script) self.assertEqual(s.get('Service', 'ExecStop'), '%s stop' % init_script) self.assertNotIn('Overwriting', err) def test_simple_enabled_all(self): '''simple service without dependencies, enabled in all runlevels''' self.add_sysv('foo', {}, enable=True) err, results = self.run_generator() self.assertEqual(list(results), ['foo.service']) self.assert_enabled('foo.service', ['multi-user', 'graphical']) self.assertNotIn('Overwriting', err) def test_simple_escaped(self): '''simple service without dependencies, that requires escaping the name''' self.add_sysv('foo+', {}) self.add_sysv('foo-admin', {}) err, results = self.run_generator() self.assertEqual(set(results), {'foo-admin.service', 'foo\\x2b.service'}) self.assertNotIn('Overwriting', err) def test_simple_enabled_some(self): '''simple service without dependencies, enabled in some runlevels''' self.add_sysv('foo', {'Default-Start': '2 4'}, enable=True) err, results = self.run_generator() self.assertEqual(list(results), ['foo.service']) self.assert_enabled('foo.service', ['multi-user']) def test_lsb_macro_dep_single(self): '''single LSB macro dependency: $network''' self.add_sysv('foo', {'Required-Start': '$network'}) s = self.run_generator()[1]['foo.service'] self.assertEqual(set(s.options('Unit')), set(['Documentation', 'SourcePath', 'Description', 'After', 'Wants'])) self.assertEqual(s.get('Unit', 'After'), 'network-online.target') self.assertEqual(s.get('Unit', 'Wants'), 'network-online.target') def test_lsb_macro_dep_multi(self): '''multiple LSB macro dependencies''' self.add_sysv('foo', {'Required-Start': '$named $portmap'}) s = self.run_generator()[1]['foo.service'] self.assertEqual(set(s.options('Unit')), set(['Documentation', 'SourcePath', 'Description', 'After'])) self.assertEqual(s.get('Unit', 'After').split(), ['nss-lookup.target', 'rpcbind.target']) def test_lsb_deps(self): '''LSB header dependencies to other services''' # also give symlink priorities here; they should be ignored self.add_sysv('foo', {'Required-Start': 'must1 must2', 'Should-Start': 'may1 ne_may2'}, enable=True, prio=40) self.add_sysv('must1', {}, enable=True, prio=10) self.add_sysv('must2', {}, enable=True, prio=15) self.add_sysv('may1', {}, enable=True, prio=20) # do not create ne_may2 err, results = self.run_generator() self.assertEqual(sorted(results), ['foo.service', 'may1.service', 'must1.service', 'must2.service']) # foo should depend on all of them self.assertEqual(sorted(results['foo.service'].get('Unit', 'After').split()), ['may1.service', 'must1.service', 'must2.service', 'ne_may2.service']) # other services should not depend on each other self.assertFalse(results['must1.service'].has_option('Unit', 'After')) self.assertFalse(results['must2.service'].has_option('Unit', 'After')) self.assertFalse(results['may1.service'].has_option('Unit', 'After')) def test_symlink_prio_deps(self): '''script without LSB headers use rcN.d priority''' # create two init.d scripts without LSB header and enable them with # startup priorities for prio, name in [(10, 'provider'), (15, 'consumer')]: with open(os.path.join(self.init_d_dir, name), 'w') as f: f.write('#!/bin/init-d-interpreter\ncode --goes here\n') os.fchmod(f.fileno(), 0o755) d = os.path.join(self.rcnd_dir, 'rc2.d') if not os.path.isdir(d): os.mkdir(d) os.symlink('../init.d/' + name, os.path.join(d, 'S%02i%s' % (prio, name))) err, results = self.run_generator() self.assertEqual(sorted(results), ['consumer.service', 'provider.service']) self.assertFalse(results['provider.service'].has_option('Unit', 'After')) self.assertEqual(results['consumer.service'].get('Unit', 'After'), 'provider.service') def test_multiple_provides(self): '''multiple Provides: names''' self.add_sysv('foo', {'Provides': 'foo bar baz'}) err, results = self.run_generator() self.assertEqual(list(results), ['foo.service']) self.assertEqual(set(results['foo.service'].options('Unit')), set(['Documentation', 'SourcePath', 'Description'])) # should create symlinks for the alternative names for f in ['bar.service', 'baz.service']: self.assertEqual(os.readlink(os.path.join(self.out_dir, f)), 'foo.service') self.assertNotIn('Overwriting', err) def test_provides_escaped(self): '''a script that Provides: a name that requires escaping''' self.add_sysv('foo', {'Provides': 'foo foo+'}) err, results = self.run_generator() self.assertEqual(list(results), ['foo.service']) self.assertEqual(os.readlink(os.path.join(self.out_dir, 'foo\\x2b.service')), 'foo.service') self.assertNotIn('Overwriting', err) def test_same_provides_in_multiple_scripts(self): '''multiple init.d scripts provide the same name''' self.add_sysv('foo', {'Provides': 'foo common'}, enable=True, prio=1) self.add_sysv('bar', {'Provides': 'bar common'}, enable=True, prio=2) err, results = self.run_generator() self.assertEqual(sorted(results), ['bar.service', 'foo.service']) # should create symlink for the alternative name for either unit self.assertIn(os.readlink(os.path.join(self.out_dir, 'common.service')), ['foo.service', 'bar.service']) def test_provide_other_script(self): '''init.d scripts provides the name of another init.d script''' self.add_sysv('foo', {'Provides': 'foo bar'}, enable=True) self.add_sysv('bar', {'Provides': 'bar'}, enable=True) err, results = self.run_generator() self.assertEqual(sorted(results), ['bar.service', 'foo.service']) # we do expect an overwrite here, bar.service should overwrite the # alias link from foo.service self.assertIn('Overwriting', err) def test_nonexecutable_script(self): '''ignores non-executable init.d script''' os.chmod(self.add_sysv('foo', {}), 0o644) err, results = self.run_generator() self.assertEqual(results, {}) def test_sh_suffix(self): '''init.d script with .sh suffix''' self.add_sysv('foo.sh', {}, enable=True) err, results = self.run_generator() s = results['foo.service'] self.assertEqual(s.sections(), ['Unit', 'Service']) # should not have a .sh self.assertEqual(s.get('Unit', 'Description'), 'LSB: test foo service') # calls correct script with .sh init_script = os.path.join(self.init_d_dir, 'foo.sh') self.assertEqual(s.get('Service', 'ExecStart'), '%s start' % init_script) self.assertEqual(s.get('Service', 'ExecStop'), '%s stop' % init_script) self.assert_enabled('foo.service', ['multi-user', 'graphical']) def test_sh_suffix_with_provides(self): '''init.d script with .sh suffix and Provides:''' self.add_sysv('foo.sh', {'Provides': 'foo bar'}) err, results = self.run_generator() # ensure we don't try to create a symlink to itself self.assertNotIn('itself', err) self.assertEqual(list(results), ['foo.service']) self.assertEqual(results['foo.service'].get('Unit', 'Description'), 'LSB: test foo service') # should create symlink for the alternative name self.assertEqual(os.readlink(os.path.join(self.out_dir, 'bar.service')), 'foo.service') def test_hidden_files(self): '''init.d script with hidden file suffix''' script = self.add_sysv('foo', {}, enable=True) # backup files (not enabled in rcN.d/) shutil.copy(script, script + '.dpkg-new') shutil.copy(script, script + '.dpkg-dist') shutil.copy(script, script + '.swp') shutil.copy(script, script + '.rpmsave') err, results = self.run_generator() self.assertEqual(list(results), ['foo.service']) self.assert_enabled('foo.service', ['multi-user', 'graphical']) def test_backup_file(self): '''init.d script with backup file''' script = self.add_sysv('foo', {}, enable=True) # backup files (not enabled in rcN.d/) shutil.copy(script, script + '.bak') shutil.copy(script, script + '.old') err, results = self.run_generator() print(err) self.assertEqual(sorted(results), ['foo.bak.service', 'foo.old.service', 'foo.service']) # ensure we don't try to create a symlink to itself self.assertNotIn('itself', err) self.assert_enabled('foo.service', ['multi-user', 'graphical']) self.assert_enabled('foo.bak.service', []) self.assert_enabled('foo.old.service', []) def test_existing_native_unit(self): '''existing native unit''' with open(os.path.join(self.unit_dir, 'foo.service'), 'w') as f: f.write('[Unit]\n') self.add_sysv('foo.sh', {'Provides': 'foo bar'}, enable=True) err, results = self.run_generator() self.assertEqual(list(results), []) # no enablement or alias links, as native unit is disabled self.assertEqual(os.listdir(self.out_dir), []) if __name__ == '__main__': unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2)) systemd-229/test/test-efi-create-disk.sh000077500000000000000000000033031265713322000203070ustar00rootroot00000000000000#!/bin/bash -e # create GPT table with EFI System Partition rm -f test-efi-disk.img dd if=/dev/null of=test-efi-disk.img bs=1M seek=512 count=1 parted --script test-efi-disk.img "mklabel gpt" "mkpart ESP fat32 1MiB 511MiB" "set 1 boot on" # create FAT32 file system LOOP=$(losetup --show -f -P test-efi-disk.img) mkfs.vfat -F32 ${LOOP}p1 mkdir -p mnt mount ${LOOP}p1 mnt mkdir -p mnt/EFI/{Boot,systemd} cp systemd-bootx64.efi mnt/EFI/Boot/bootx64.efi [ -e /boot/shellx64.efi ] && cp /boot/shellx64.efi mnt/ mkdir mnt/EFI/Linux echo -n "foo=yes bar=no root=/dev/fakeroot debug rd.break=initqueue" > mnt/cmdline.txt objcopy \ --add-section .osrel=/etc/os-release --change-section-vma .osrel=0x20000 \ --add-section .cmdline=mnt/cmdline.txt --change-section-vma .cmdline=0x30000 \ --add-section .splash=test/splash.bmp --change-section-vma .splash=0x40000 \ --add-section .linux=/boot/$(cat /etc/machine-id)/$(uname -r)/linux --change-section-vma .linux=0x2000000 \ --add-section .initrd=/boot/$(cat /etc/machine-id)/$(uname -r)/initrd --change-section-vma .initrd=0x3000000 \ linuxx64.efi.stub mnt/EFI/Linux/linux-test.efi # install entries mkdir -p mnt/loader/entries echo -e "timeout 3\n" > mnt/loader/loader.conf echo -e "title Test\nefi /test\n" > mnt/loader/entries/test.conf echo -e "title Test2\nlinux /test2\noptions option=yes word number=1000 more\n" > mnt/loader/entries/test2.conf echo -e "title Test3\nlinux /test3\n" > mnt/loader/entries/test3.conf echo -e "title Test4\nlinux /test4\n" > mnt/loader/entries/test4.conf echo -e "title Test5\nefi /test5\n" > mnt/loader/entries/test5.conf echo -e "title Test6\nlinux /test6\n" > mnt/loader/entries/test6.conf sync umount mnt rmdir mnt losetup -d $LOOP systemd-229/test/test-execute/000077500000000000000000000000001265713322000164575ustar00rootroot00000000000000systemd-229/test/test-execute/exec-capabilityambientset-merge.service000066400000000000000000000004001265713322000262470ustar00rootroot00000000000000[Unit] Description=Test for AmbientCapabilities [Service] ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000003000"' Type=oneshot User=nobody AmbientCapabilities=CAP_NET_ADMIN AmbientCapabilities=CAP_NET_RAW systemd-229/test/test-execute/exec-capabilityambientset.service000066400000000000000000000003541265713322000251620ustar00rootroot00000000000000[Unit] Description=Test for AmbientCapabilities [Service] ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000003000"' Type=oneshot User=nobody AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW systemd-229/test/test-execute/exec-capabilityboundingset-invert.service000066400000000000000000000003131265713322000266500ustar00rootroot00000000000000[Unit] Description=Test for CapabilityBoundingSet [Service] ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "^Bounding set .*cap_chown"); test -z "$$c"' Type=oneshot CapabilityBoundingSet=~CAP_CHOWN systemd-229/test/test-execute/exec-capabilityboundingset-merge.service000066400000000000000000000004251265713322000264440ustar00rootroot00000000000000[Unit] Description=Test for CapabilityBoundingSet [Service] ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "Bounding set "); test "$$c" = "Bounding set =cap_chown,cap_fowner,cap_kill"' Type=oneshot CapabilityBoundingSet=CAP_FOWNER CapabilityBoundingSet=CAP_KILL CAP_CHOWN systemd-229/test/test-execute/exec-capabilityboundingset-reset.service000066400000000000000000000003571265713322000264730ustar00rootroot00000000000000[Unit] Description=Test for CapabilityBoundingSet [Service] ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "Bounding set "); test "$$c" = "Bounding set ="' Type=oneshot CapabilityBoundingSet=CAP_FOWNER CAP_KILL CapabilityBoundingSet= systemd-229/test/test-execute/exec-capabilityboundingset-simple.service000066400000000000000000000003531265713322000266360ustar00rootroot00000000000000[Unit] Description=Test for CapabilityBoundingSet [Service] ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "Bounding set "); test "$$c" = "Bounding set =cap_fowner,cap_kill"' Type=oneshot CapabilityBoundingSet=CAP_FOWNER CAP_KILL systemd-229/test/test-execute/exec-environment-empty.service000066400000000000000000000004101265713322000244560ustar00rootroot00000000000000[Unit] Description=Test for Environment [Service] ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset"' Type=oneshot Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" Environment= systemd-229/test/test-execute/exec-environment-multiple.service000066400000000000000000000004001265713322000251520ustar00rootroot00000000000000[Unit] Description=Test for Environment [Service] ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = foobar' Type=oneshot Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" Environment="VAR3=foobar" systemd-229/test/test-execute/exec-environment.service000066400000000000000000000003561265713322000233330ustar00rootroot00000000000000[Unit] Description=Test for Environment [Service] ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6"' Type=oneshot Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" systemd-229/test/test-execute/exec-environmentfile.service000066400000000000000000000003531265713322000241700ustar00rootroot00000000000000[Unit] Description=Test for EnvironmentFile [Service] ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6"' Type=oneshot EnvironmentFile=/tmp/test-exec_environmentfile.conf systemd-229/test/test-execute/exec-group.service000066400000000000000000000002001265713322000221070ustar00rootroot00000000000000[Unit] Description=Test for Group [Service] ExecStart=/bin/sh -x -c 'test "$$(id -n -g)" = "nobody"' Type=oneshot Group=nobody systemd-229/test/test-execute/exec-ignoresigpipe-no.service000066400000000000000000000001751265713322000242440ustar00rootroot00000000000000[Unit] Description=Test for IgnoreSIGPIPE=no [Service] ExecStart=/bin/sh -x -c 'kill -PIPE 0' Type=oneshot IgnoreSIGPIPE=no systemd-229/test/test-execute/exec-ignoresigpipe-yes.service000066400000000000000000000001771265713322000244320ustar00rootroot00000000000000[Unit] Description=Test for IgnoreSIGPIPE=yes [Service] ExecStart=/bin/sh -x -c 'kill -PIPE 0' Type=oneshot IgnoreSIGPIPE=yes systemd-229/test/test-execute/exec-ioschedulingclass-best-effort.service000066400000000000000000000003021265713322000266770ustar00rootroot00000000000000[Unit] Description=Test for IOSchedulingClass=best-effort [Service] ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "best-effort"' Type=oneshot IOSchedulingClass=best-effort systemd-229/test/test-execute/exec-ioschedulingclass-idle.service000066400000000000000000000002551265713322000254030ustar00rootroot00000000000000[Unit] Description=Test for IOSchedulingClass=idle [Service] ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "idle"' Type=oneshot IOSchedulingClass=idle systemd-229/test/test-execute/exec-ioschedulingclass-none.service000066400000000000000000000002551265713322000254250ustar00rootroot00000000000000[Unit] Description=Test for IOSchedulingClass=none [Service] ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "none"' Type=oneshot IOSchedulingClass=none systemd-229/test/test-execute/exec-ioschedulingclass-realtime.service000066400000000000000000000002711265713322000262660ustar00rootroot00000000000000[Unit] Description=Test for IOSchedulingClass=realtime [Service] ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "realtime"' Type=oneshot IOSchedulingClass=realtime systemd-229/test/test-execute/exec-oomscoreadjust-negative.service000066400000000000000000000002511265713322000256220ustar00rootroot00000000000000[Unit] Description=Test for OOMScoreAdjust [Service] ExecStart=/bin/sh -x -c 'c=$$(cat /proc/self/oom_score_adj); test "$$c" -eq -100' Type=oneshot OOMScoreAdjust=-100 systemd-229/test/test-execute/exec-oomscoreadjust-positive.service000066400000000000000000000002471265713322000256670ustar00rootroot00000000000000[Unit] Description=Test for OOMScoreAdjust [Service] ExecStart=/bin/sh -x -c 'c=$$(cat /proc/self/oom_score_adj); test "$$c" -eq 100' Type=oneshot OOMScoreAdjust=100 systemd-229/test/test-execute/exec-passenvironment-absent.service000066400000000000000000000004301265713322000254650ustar00rootroot00000000000000[Unit] Description=Test for PassEnvironment with variables absent from the execution environment [Service] ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset"' Type=oneshot PassEnvironment=VAR1 VAR2 VAR3 systemd-229/test/test-execute/exec-passenvironment-empty.service000066400000000000000000000004221265713322000253500ustar00rootroot00000000000000[Unit] Description=Test for PassEnvironment and erasing the variable list [Service] ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset"' Type=oneshot PassEnvironment=VAR1 VAR2 VAR3 PassEnvironment= systemd-229/test/test-execute/exec-passenvironment-repeated.service000066400000000000000000000004111265713322000260010ustar00rootroot00000000000000[Unit] Description=Test for PassEnvironment with a variable name repeated [Service] ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6"' Type=oneshot PassEnvironment=VAR1 VAR2 PassEnvironment=VAR1 VAR3 systemd-229/test/test-execute/exec-passenvironment.service000066400000000000000000000003261265713322000242170ustar00rootroot00000000000000[Unit] Description=Test for PassEnvironment [Service] ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6"' Type=oneshot PassEnvironment=VAR1 VAR2 VAR3 systemd-229/test/test-execute/exec-personality-s390.service000066400000000000000000000002241265713322000240260ustar00rootroot00000000000000[Unit] Description=Test for Personality=s390 [Service] ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "s390"' Type=oneshot Personality=s390 systemd-229/test/test-execute/exec-personality-x86-64.service000066400000000000000000000002321265713322000242030ustar00rootroot00000000000000[Unit] Description=Test for Personality=x86-64 [Service] ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "x86_64"' Type=oneshot Personality=x86-64 systemd-229/test/test-execute/exec-personality-x86.service000066400000000000000000000002221265713322000237530ustar00rootroot00000000000000[Unit] Description=Test for Personality=x86 [Service] ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "i686"' Type=oneshot Personality=x86 systemd-229/test/test-execute/exec-privatedevices-no.service000066400000000000000000000001771265713322000244170ustar00rootroot00000000000000[Unit] Description=Test for PrivateDev=no [Service] ExecStart=/bin/sh -x -c 'test -c /dev/mem' Type=oneshot PrivateDevices=no systemd-229/test/test-execute/exec-privatedevices-yes.service000066400000000000000000000002001265713322000245660ustar00rootroot00000000000000[Unit] Description=Test for PrivateDev=yes [Service] ExecStart=/bin/sh -c 'test ! -c /dev/mem' Type=oneshot PrivateDevices=yes systemd-229/test/test-execute/exec-privatenetwork-yes.service000066400000000000000000000002531265713322000246450ustar00rootroot00000000000000[Unit] Description=Test for PrivateNetwork [Service] ExecStart=/bin/sh -x -c 'i=$$(ip link | grep ": " | grep -v ": lo:"); test -z "$$i"' Type=oneshot PrivateNetwork=yes systemd-229/test/test-execute/exec-privatetmp-no.service000066400000000000000000000002141265713322000235650ustar00rootroot00000000000000[Unit] Description=Test for PrivateTmp=no [Service] ExecStart=/bin/sh -x -c 'test -f /tmp/test-exec_privatetmp' Type=oneshot PrivateTmp=no systemd-229/test/test-execute/exec-privatetmp-yes.service000066400000000000000000000002201265713322000237460ustar00rootroot00000000000000[Unit] Description=Test for PrivateTmp=yes [Service] ExecStart=/bin/sh -x -c 'test ! -f /tmp/test-exec_privatetmp' Type=oneshot PrivateTmp=yes systemd-229/test/test-execute/exec-runtimedirectory-mode.service000066400000000000000000000003771265713322000253240ustar00rootroot00000000000000[Unit] Description=Test for RuntimeDirectoryMode [Service] ExecStart=/bin/sh -x -c 'mode=$$(stat -c %%a /tmp/test-exec_runtimedirectory-mode); test "$$mode" = "750"' Type=oneshot RuntimeDirectory=test-exec_runtimedirectory-mode RuntimeDirectoryMode=0750 systemd-229/test/test-execute/exec-runtimedirectory-owner.service000066400000000000000000000005011265713322000255170ustar00rootroot00000000000000[Unit] Description=Test for RuntimeDirectory owner (must not be the default group of the user if Group is set) [Service] ExecStart=/bin/sh -x -c 'group=$$(stat -c %%G /tmp/test-exec_runtimedirectory-owner); test "$$group" = "nobody"' Type=oneshot Group=nobody User=root RuntimeDirectory=test-exec_runtimedirectory-owner systemd-229/test/test-execute/exec-runtimedirectory.service000066400000000000000000000002631265713322000243740ustar00rootroot00000000000000[Unit] Description=Test for RuntimeDirectory [Service] ExecStart=/bin/sh -x -c 'test -d /tmp/test-exec_runtimedirectory' Type=oneshot RuntimeDirectory=test-exec_runtimedirectory systemd-229/test/test-execute/exec-systemcallerrornumber.service000066400000000000000000000002421265713322000254240ustar00rootroot00000000000000[Unit] Description=Test for SystemCallErrorNumber [Service] ExecStart=/bin/sh -x -c 'uname -a' Type=oneshot SystemCallFilter=~uname SystemCallErrorNumber=EACCES systemd-229/test/test-execute/exec-systemcallfilter-failing.service000066400000000000000000000002741265713322000257630ustar00rootroot00000000000000[Unit] Description=Test for SystemCallFilter [Service] ExecStart=/bin/echo "This should not be seen" Type=oneshot SystemCallFilter=ioperm SystemCallFilter=~ioperm SystemCallFilter=ioperm systemd-229/test/test-execute/exec-systemcallfilter-failing2.service000066400000000000000000000003051265713322000260400ustar00rootroot00000000000000[Unit] Description=Test for SystemCallFilter [Service] ExecStart=/bin/echo "This should not be seen" Type=oneshot SystemCallFilter=~write open execve exit_group close mmap munmap fstat DONOTEXIST systemd-229/test/test-execute/exec-systemcallfilter-not-failing.service000066400000000000000000000003531265713322000265570ustar00rootroot00000000000000[Unit] Description=Test for SystemCallFilter [Service] ExecStart=/bin/echo "Foo bar" Type=oneshot SystemCallFilter=~read write open execve ioperm SystemCallFilter=ioctl SystemCallFilter=read write open execve SystemCallFilter=~ioperm systemd-229/test/test-execute/exec-systemcallfilter-not-failing2.service000066400000000000000000000001651265713322000266420ustar00rootroot00000000000000[Unit] Description=Test for SystemCallFilter [Service] ExecStart=/bin/echo "Foo bar" Type=oneshot SystemCallFilter= systemd-229/test/test-execute/exec-umask-0177.service000066400000000000000000000003131265713322000224740ustar00rootroot00000000000000[Unit] Description=Test for UMask [Service] ExecStart=/bin/sh -x -c 'touch /tmp/test-exec-umask; mode=$$(stat -c %%a /tmp/test-exec-umask); test "$$mode" = "600"' Type=oneshot UMask=0177 PrivateTmp=yes systemd-229/test/test-execute/exec-umask-default.service000066400000000000000000000003101265713322000235170ustar00rootroot00000000000000[Unit] Description=Test for UMask default [Service] ExecStart=/bin/sh -x -c 'touch /tmp/test-exec-umask; mode=$$(stat -c %%a /tmp/test-exec-umask); test "$$mode" = "644"' Type=oneshot PrivateTmp=yes systemd-229/test/test-execute/exec-user.service000066400000000000000000000001701265713322000217370ustar00rootroot00000000000000[Unit] Description=Test for User [Service] ExecStart=/bin/sh -x -c 'test "$$USER" = "nobody"' Type=oneshot User=nobody systemd-229/test/test-execute/exec-workingdirectory.service000066400000000000000000000003011265713322000243620ustar00rootroot00000000000000[Unit] Description=Test for WorkingDirectory [Service] ExecStart=/bin/sh -x -c 'test "$$PWD" = "/tmp/test-exec_workingdirectory"' Type=oneshot WorkingDirectory=/tmp/test-exec_workingdirectory systemd-229/test/test-functions000066400000000000000000001146251265713322000167610ustar00rootroot00000000000000#!/bin/bash # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh PATH=/sbin:/bin:/usr/sbin:/usr/bin export PATH LOOKS_LIKE_DEBIAN=$(source /etc/os-release && [[ "$ID" = "debian" || "$ID_LIKE" = "debian" ]] && echo yes) KERNEL_VER=${KERNEL_VER-$(uname -r)} KERNEL_MODS="/lib/modules/$KERNEL_VER/" if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then echo "WARNING! Cannot determine rootlibdir from pkg-config, assuming /usr/lib/systemd" >&2 ROOTLIBDIR=/usr/lib/systemd fi BASICTOOLS="sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm" DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find" function find_qemu_bin() { # SUSE and Red Hat call the binary qemu-kvm # Debian and Gentoo call it kvm [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a kvm qemu-kvm 2>/dev/null | grep '^/' -m1) [ "$ARCH" ] || ARCH=$(uname -m) case $ARCH in x86_64) # QEMU's own build system calls it qemu-system-x86_64 [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-x86_64 2>/dev/null | grep '^/' -m1) ;; i*86) # new i386 version of QEMU [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-i386 2>/dev/null | grep '^/' -m1) # i386 version of QEMU [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu 2>/dev/null | grep '^/' -m1) ;; esac if [ ! -e "$QEMU_BIN" ]; then echo "Could not find a suitable QEMU binary" >&2 return 1 fi } run_qemu() { if [ -f /etc/machine-id ]; then read MACHINE_ID < /etc/machine-id [ -z "$INITRD" ] && [ -e "/boot/$MACHINE_ID/$KERNEL_VER/initrd" ] \ && INITRD="/boot/$MACHINE_ID/$KERNEL_VER/initrd" [ -z "$KERNEL_BIN" ] && [ -e "/boot/$MACHINE_ID/$KERNEL_VER/linux" ] \ && KERNEL_BIN="/boot/$MACHINE_ID/$KERNEL_VER/linux" fi default_fedora_initrd=/boot/initramfs-${KERNEL_VER}.img default_debian_initrd=/boot/initrd.img-${KERNEL_VER} [ "$KERNEL_BIN" ] || KERNEL_BIN=/boot/vmlinuz-$KERNEL_VER [ "$INITRD" ] || { [ -e "$default_fedora_initrd" ] && INITRD=$default_fedora_initrd; } [ "$INITRD" ] || { [ "$LOOKS_LIKE_DEBIAN" ] && [ -e "$default_debian_initrd" ] && INITRD=$default_debian_initrd; } [ "$QEMU_SMP" ] || QEMU_SMP=1 find_qemu_bin || return 1 KERNEL_APPEND="root=/dev/sda1 \ systemd.log_level=debug \ raid=noautodetect \ loglevel=2 \ init=$ROOTLIBDIR/systemd \ ro \ console=ttyS0 \ selinux=0 \ $KERNEL_APPEND \ " QEMU_OPTIONS="-smp $QEMU_SMP \ -net none \ -m 512M \ -nographic \ -kernel $KERNEL_BIN \ " if [ "$INITRD" ]; then QEMU_OPTIONS="$QEMU_OPTIONS -initrd $INITRD" fi if [ -c /dev/kvm ]; then QEMU_OPTIONS="$QEMU_OPTIONS -machine accel=kvm -enable-kvm -cpu host" fi ( set -x $QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND" $TESTDIR/rootdisk.img ) || return 1 } run_nspawn() { set -x ../../systemd-nspawn --register=no --directory=$TESTDIR/nspawn-root $ROOTLIBDIR/systemd $KERNEL_APPEND } setup_basic_environment() { # create the basic filesystem layout setup_basic_dirs install_systemd install_missing_libraries install_config_files create_rc_local install_basic_tools install_libnss install_pam install_dbus install_fonts install_keymaps install_terminfo install_execs install_fsck install_plymouth install_debug_tools install_ld_so_conf setup_selinux strip_binaries install_depmod_files generate_module_dependencies } setup_selinux() { # don't forget KERNEL_APPEND='... selinux=1 ...' if [[ "$SETUP_SELINUX" != "yes" ]]; then ddebug "Don't setup SELinux" return 0 fi ddebug "Setup SELinux" local _conf_dir=/etc/selinux local _fixfiles_tools="bash uname cat sort uniq awk grep egrep head expr find rm secon setfiles" rm -rf $initdir/$_conf_dir if ! cp -ar $_conf_dir $initdir/$_conf_dir; then dfatal "Failed to copy $_conf_dir" exit 1 fi cat <$initdir/etc/systemd/system/autorelabel.service [Unit] Description=Relabel all filesystems DefaultDependencies=no Requires=local-fs.target Conflicts=shutdown.target After=local-fs.target Before=sysinit.target shutdown.target ConditionSecurity=selinux ConditionPathExists=|/.autorelabel [Service] ExecStart=/bin/sh -x -c 'echo 0 >/sys/fs/selinux/enforce && fixfiles -f -F relabel && rm /.autorelabel && systemctl --force reboot' Type=oneshot TimeoutSec=0 RemainAfterExit=yes EOF touch $initdir/.autorelabel mkdir -p $initdir/etc/systemd/system/basic.target.wants ln -fs autorelabel.service $initdir/etc/systemd/system/basic.target.wants/autorelabel.service dracut_install $_fixfiles_tools dracut_install fixfiles dracut_install sestatus } install_valgrind() { if ! type -p valgrind; then dfatal "Failed to install valgrind" exit 1 fi local _valgrind_bins=$(strace -e execve valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if /^execve\("([^"]+)"/') dracut_install $_valgrind_bins local _valgrind_libs=$(LD_DEBUG=files valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if m{calling init: (/.*vgpreload_.*)}') dracut_install $_valgrind_libs local _valgrind_dbg_and_supp=$( strace -e open valgrind /bin/true 2>&1 >/dev/null | perl -lne 'if (my ($fname) = /^open\("([^"]+).*= (?!-)\d+/) { print $fname if $fname =~ /debug|\.supp$/ }' ) dracut_install $_valgrind_dbg_and_supp } create_valgrind_wrapper() { local _valgrind_wrapper=$initdir/$ROOTLIBDIR/systemd-under-valgrind ddebug "Create $_valgrind_wrapper" cat >$_valgrind_wrapper </dev/null && dracut_install dmeventd inst_libdir_file "libdevmapper-event.so*" if [[ "$LOOKS_LIKE_DEBIAN" ]]; then # dmsetup installs 55-dm and 60-persistent-storage-dm on Debian/Ubuntu # see https://anonscm.debian.org/cgit/pkg-lvm/lvm2.git/tree/debian/patches/0007-udev.patch inst_rules 55-dm.rules 60-persistent-storage-dm.rules else inst_rules 10-dm.rules 13-dm-disk.rules 95-dm-notify.rules fi } install_systemd() { # install compiled files (cd $TEST_BASE_DIR/..; set -x; make DESTDIR=$initdir install) # remove unneeded documentation rm -fr $initdir/usr/share/{man,doc} # we strip binaries since debug symbols increase binaries size a lot # and it could fill the available space strip_binaries } install_missing_libraries() { # install possible missing libraries for i in $initdir/{sbin,bin}/* $initdir/lib/systemd/*; do inst_libs $i done } create_empty_image() { rm -f "$TESTDIR/rootdisk.img" # Create the blank file to use as a root filesystem dd if=/dev/null of="$TESTDIR/rootdisk.img" bs=1M seek=400 LOOPDEV=$(losetup --show -P -f $TESTDIR/rootdisk.img) [ -b "$LOOPDEV" ] || return 1 echo "LOOPDEV=$LOOPDEV" >> $STATEFILE sfdisk "$LOOPDEV" <$initdir/etc/rc.d/rc.local < $initdir/etc/environment > $initdir/etc/machine-id # set the hostname echo systemd-testsuite > $initdir/etc/hostname # fstab cat >$initdir/etc/fstab <&1 >/dev/null |sed -n '/calling init: .*libnss_/ {s!^.* /!/!; p}') dracut_install $NSS_LIBS } install_dbus() { inst $ROOTLIBDIR/system/dbus.socket inst $ROOTLIBDIR/system/dbus.service find \ /etc/dbus-1 /usr/share/dbus-1 -xtype f \ | while read file; do inst $file done } install_pam() { ( [[ "$LOOKS_LIKE_DEBIAN" ]] && type -p dpkg-architecture &>/dev/null && find "/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/security" -xtype f find \ /etc/pam.d \ /etc/security \ /lib64/security \ /lib/security -xtype f \ ) | while read file; do inst $file done # pam_unix depends on unix_chkpwd. # see http://www.linux-pam.org/Linux-PAM-html/sag-pam_unix.html dracut_install -o unix_chkpwd [[ "$LOOKS_LIKE_DEBIAN" ]] && cp /etc/pam.d/systemd-user $initdir/etc/pam.d/ } install_keymaps() { for i in \ /usr/lib/kbd/keymaps/include/* \ /usr/lib/kbd/keymaps/i386/include/* \ /usr/lib/kbd/keymaps/i386/qwerty/us.*; do [[ -f $i ]] || continue inst $i done } install_fonts() { for i in \ /usr/lib/kbd/consolefonts/eurlatgr* \ /usr/lib/kbd/consolefonts/latarcyrheb-sun16*; do [[ -f $i ]] || continue inst $i done } install_terminfo() { for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do [ -f ${_terminfodir}/l/linux ] && break done dracut_install -o ${_terminfodir}/l/linux } setup_testsuite() { cp $TEST_BASE_DIR/testsuite.target $initdir/etc/systemd/system/ cp $TEST_BASE_DIR/end.service $initdir/etc/systemd/system/ mkdir -p $initdir/etc/systemd/system/testsuite.target.wants ln -fs $TEST_BASE_DIR/testsuite.service $initdir/etc/systemd/system/testsuite.target.wants/testsuite.service ln -fs $TEST_BASE_DIR/end.service $initdir/etc/systemd/system/testsuite.target.wants/end.service # make the testsuite the default target ln -fs testsuite.target $initdir/etc/systemd/system/default.target } setup_nspawn_root() { rm -fr $TESTDIR/nspawn-root ddebug "cp -ar $initdir $TESTDIR/nspawn-root" cp -ar $initdir $TESTDIR/nspawn-root # we don't mount in the nspawn root rm -f $TESTDIR/nspawn-root/etc/fstab } setup_basic_dirs() { mkdir -p $initdir/run mkdir -p $initdir/etc/systemd/system mkdir -p $initdir/var/log/journal for d in usr/bin usr/sbin bin etc lib "$libdir" sbin tmp usr var var/log dev proc sys sysroot root run run/lock run/initramfs; do if [ -L "/$d" ]; then inst_symlink "/$d" else inst_dir "/$d" fi done ln -sfn /run "$initdir/var/run" ln -sfn /run/lock "$initdir/var/lock" } inst_libs() { local _bin=$1 local _so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)' local _file _line LC_ALL=C ldd "$_bin" 2>/dev/null | while read _line; do [[ $_line = 'not a dynamic executable' ]] && break if [[ $_line =~ $_so_regex ]]; then _file=${BASH_REMATCH[1]} [[ -e ${initdir}/$_file ]] && continue inst_library "$_file" continue fi if [[ $_line =~ not\ found ]]; then dfatal "Missing a shared library required by $_bin." dfatal "Run \"ldd $_bin\" to find out what it is." dfatal "$_line" dfatal "dracut cannot create an initrd." exit 1 fi done } import_testdir() { STATEFILE=".testdir" [[ -e $STATEFILE ]] && . $STATEFILE if [[ -z "$TESTDIR" ]] || [[ ! -d "$TESTDIR" ]]; then TESTDIR=$(mktemp --tmpdir=/var/tmp -d -t systemd-test.XXXXXX) echo "TESTDIR=\"$TESTDIR\"" > $STATEFILE export TESTDIR fi } import_initdir() { initdir=$TESTDIR/root export initdir } ## @brief Converts numeric logging level to the first letter of level name. # # @param lvl Numeric logging level in range from 1 to 6. # @retval 1 if @a lvl is out of range. # @retval 0 if @a lvl is correct. # @result Echoes first letter of level name. _lvl2char() { case "$1" in 1) echo F;; 2) echo E;; 3) echo W;; 4) echo I;; 5) echo D;; 6) echo T;; *) return 1;; esac } ## @brief Internal helper function for _do_dlog() # # @param lvl Numeric logging level. # @param msg Message. # @retval 0 It's always returned, even if logging failed. # # @note This function is not supposed to be called manually. Please use # dtrace(), ddebug(), or others instead which wrap this one. # # This function calls _do_dlog() either with parameter msg, or if # none is given, it will read standard input and will use every line as # a message. # # This enables: # dwarn "This is a warning" # echo "This is a warning" | dwarn LOG_LEVEL=4 dlog() { [ -z "$LOG_LEVEL" ] && return 0 [ $1 -le $LOG_LEVEL ] || return 0 local lvl="$1"; shift local lvlc=$(_lvl2char "$lvl") || return 0 if [ $# -ge 1 ]; then echo "$lvlc: $*" else while read line; do echo "$lvlc: " "$line" done fi } ## @brief Logs message at TRACE level (6) # # @param msg Message. # @retval 0 It's always returned, even if logging failed. dtrace() { set +x dlog 6 "$@" [ -n "$debug" ] && set -x || : } ## @brief Logs message at DEBUG level (5) # # @param msg Message. # @retval 0 It's always returned, even if logging failed. ddebug() { # set +x dlog 5 "$@" # [ -n "$debug" ] && set -x || : } ## @brief Logs message at INFO level (4) # # @param msg Message. # @retval 0 It's always returned, even if logging failed. dinfo() { set +x dlog 4 "$@" [ -n "$debug" ] && set -x || : } ## @brief Logs message at WARN level (3) # # @param msg Message. # @retval 0 It's always returned, even if logging failed. dwarn() { set +x dlog 3 "$@" [ -n "$debug" ] && set -x || : } ## @brief Logs message at ERROR level (2) # # @param msg Message. # @retval 0 It's always returned, even if logging failed. derror() { # set +x dlog 2 "$@" # [ -n "$debug" ] && set -x || : } ## @brief Logs message at FATAL level (1) # # @param msg Message. # @retval 0 It's always returned, even if logging failed. dfatal() { set +x dlog 1 "$@" [ -n "$debug" ] && set -x || : } # Generic substring function. If $2 is in $1, return 0. strstr() { [ "${1#*$2*}" != "$1" ]; } # normalize_path # Prints the normalized path, where it removes any duplicated # and trailing slashes. # Example: # $ normalize_path ///test/test// # /test/test normalize_path() { shopt -q -s extglob set -- "${1//+(\/)//}" shopt -q -u extglob echo "${1%/}" } # convert_abs_rel # Prints the relative path, when creating a symlink to from . # Example: # $ convert_abs_rel /usr/bin/test /bin/test-2 # ../../bin/test-2 # $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test convert_abs_rel() { local __current __absolute __abssize __cursize __newpath local -i __i __level set -- "$(normalize_path "$1")" "$(normalize_path "$2")" # corner case #1 - self looping link [[ "$1" == "$2" ]] && { echo "${1##*/}"; return; } # corner case #2 - own dir link [[ "${1%/*}" == "$2" ]] && { echo "."; return; } IFS="/" __current=($1) IFS="/" __absolute=($2) __abssize=${#__absolute[@]} __cursize=${#__current[@]} while [[ ${__absolute[__level]} == ${__current[__level]} ]] do (( __level++ )) if (( __level > __abssize || __level > __cursize )) then break fi done for ((__i = __level; __i < __cursize-1; __i++)) do if ((__i > __level)) then __newpath=$__newpath"/" fi __newpath=$__newpath".." done for ((__i = __level; __i < __abssize; __i++)) do if [[ -n $__newpath ]] then __newpath=$__newpath"/" fi __newpath=$__newpath${__absolute[__i]} done echo "$__newpath" } # Install a directory, keeping symlinks as on the original system. # Example: if /lib points to /lib64 on the host, "inst_dir /lib/file" # will create ${initdir}/lib64, ${initdir}/lib64/file, # and a symlink ${initdir}/lib -> lib64. inst_dir() { [[ -e ${initdir}/"$1" ]] && return 0 # already there local _dir="$1" _part="${1%/*}" _file while [[ "$_part" != "${_part%/*}" ]] && ! [[ -e "${initdir}/${_part}" ]]; do _dir="$_part $_dir" _part=${_part%/*} done # iterate over parent directories for _file in $_dir; do [[ -e "${initdir}/$_file" ]] && continue if [[ -L $_file ]]; then inst_symlink "$_file" else # create directory mkdir -m 0755 -p "${initdir}/$_file" || return 1 [[ -e "$_file" ]] && chmod --reference="$_file" "${initdir}/$_file" chmod u+w "${initdir}/$_file" fi done } # $1 = file to copy to ramdisk # $2 (optional) Name for the file on the ramdisk # Location of the image dir is assumed to be $initdir # We never overwrite the target if it exists. inst_simple() { [[ -f "$1" ]] || return 1 strstr "$1" "/" || return 1 local _src=$1 target="${2:-$1}" if ! [[ -d ${initdir}/$target ]]; then [[ -e ${initdir}/$target ]] && return 0 [[ -L ${initdir}/$target ]] && return 0 [[ -d "${initdir}/${target%/*}" ]] || inst_dir "${target%/*}" fi # install checksum files also if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then inst "${_src%/*}/.${_src##*/}.hmac" "${target%/*}/.${target##*/}.hmac" fi ddebug "Installing $_src" cp --sparse=always -pfL "$_src" "${initdir}/$target" } # find symlinks linked to given library file # $1 = library file # Function searches for symlinks by stripping version numbers appended to # library filename, checks if it points to the same target and finally # prints the list of symlinks to stdout. # # Example: # rev_lib_symlinks libfoo.so.8.1 # output: libfoo.so.8 libfoo.so # (Only if libfoo.so.8 and libfoo.so exists on host system.) rev_lib_symlinks() { [[ ! $1 ]] && return 0 local fn="$1" orig="$(readlink -f "$1")" links='' [[ ${fn} =~ .*\.so\..* ]] || return 1 until [[ ${fn##*.} == so ]]; do fn="${fn%.*}" [[ -L ${fn} && $(readlink -f "${fn}") == ${orig} ]] && links+=" ${fn}" done echo "${links}" } # Same as above, but specialized to handle dynamic libraries. # It handles making symlinks according to how the original library # is referenced. inst_library() { local _src="$1" _dest=${2:-$1} _lib _reallib _symlink strstr "$1" "/" || return 1 [[ -e $initdir/$_dest ]] && return 0 if [[ -L $_src ]]; then # install checksum files also if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then inst "${_src%/*}/.${_src##*/}.hmac" "${_dest%/*}/.${_dest##*/}.hmac" fi _reallib=$(readlink -f "$_src") inst_simple "$_reallib" "$_reallib" inst_dir "${_dest%/*}" [[ -d "${_dest%/*}" ]] && _dest=$(readlink -f "${_dest%/*}")/${_dest##*/} ln -sfn $(convert_abs_rel "${_dest}" "${_reallib}") "${initdir}/${_dest}" else inst_simple "$_src" "$_dest" fi # Create additional symlinks. See rev_symlinks description. for _symlink in $(rev_lib_symlinks $_src) $(rev_lib_symlinks $_reallib); do [[ ! -e $initdir/$_symlink ]] && { ddebug "Creating extra symlink: $_symlink" inst_symlink $_symlink } done } # find a binary. If we were not passed the full path directly, # search in the usual places to find the binary. find_binary() { if [[ -z ${1##/*} ]]; then if [[ -x $1 ]] || { strstr "$1" ".so" && ldd $1 &>/dev/null; }; then echo $1 return 0 fi fi type -P $1 } # Same as above, but specialized to install binary executables. # Install binary executable, and all shared library dependencies, if any. inst_binary() { local _bin _target _bin=$(find_binary "$1") || return 1 _target=${2:-$_bin} [[ -e $initdir/$_target ]] && return 0 [[ -L $_bin ]] && inst_symlink $_bin $_target && return 0 local _file _line local _so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)' # I love bash! LC_ALL=C ldd "$_bin" 2>/dev/null | while read _line; do [[ $_line = 'not a dynamic executable' ]] && break if [[ $_line =~ $_so_regex ]]; then _file=${BASH_REMATCH[1]} [[ -e ${initdir}/$_file ]] && continue inst_library "$_file" continue fi if [[ $_line =~ not\ found ]]; then dfatal "Missing a shared library required by $_bin." dfatal "Run \"ldd $_bin\" to find out what it is." dfatal "$_line" dfatal "dracut cannot create an initrd." exit 1 fi done inst_simple "$_bin" "$_target" } # same as above, except for shell scripts. # If your shell script does not start with shebang, it is not a shell script. inst_script() { local _bin _bin=$(find_binary "$1") || return 1 shift local _line _shebang_regex read -r -n 80 _line <"$_bin" # If debug is set, clean unprintable chars to prevent messing up the term [[ $debug ]] && _line=$(echo -n "$_line" | tr -c -d '[:print:][:space:]') _shebang_regex='(#! *)(/[^ ]+).*' [[ $_line =~ $_shebang_regex ]] || return 1 inst "${BASH_REMATCH[2]}" && inst_simple "$_bin" "$@" } # same as above, but specialized for symlinks inst_symlink() { local _src=$1 _target=${2:-$1} _realsrc strstr "$1" "/" || return 1 [[ -L $1 ]] || return 1 [[ -L $initdir/$_target ]] && return 0 _realsrc=$(readlink -f "$_src") if ! [[ -e $initdir/$_realsrc ]]; then if [[ -d $_realsrc ]]; then inst_dir "$_realsrc" else inst "$_realsrc" fi fi [[ ! -e $initdir/${_target%/*} ]] && inst_dir "${_target%/*}" [[ -d ${_target%/*} ]] && _target=$(readlink -f ${_target%/*})/${_target##*/} ln -sfn $(convert_abs_rel "${_target}" "${_realsrc}") "$initdir/$_target" } # attempt to install any programs specified in a udev rule inst_rule_programs() { local _prog _bin if grep -qE 'PROGRAM==?"[^ "]+' "$1"; then for _prog in $(grep -E 'PROGRAM==?"[^ "]+' "$1" | sed -r 's/.*PROGRAM==?"([^ "]+).*/\1/'); do if [ -x /lib/udev/$_prog ]; then _bin=/lib/udev/$_prog else _bin=$(find_binary "$_prog") || { dinfo "Skipping program $_prog using in udev rule $(basename $1) as it cannot be found" continue; } fi #dinfo "Installing $_bin due to it's use in the udev rule $(basename $1)" dracut_install "$_bin" done fi } # udev rules always get installed in the same place, so # create a function to install them to make life simpler. inst_rules() { local _target=/etc/udev/rules.d _rule _found inst_dir "/lib/udev/rules.d" inst_dir "$_target" for _rule in "$@"; do if [ "${rule#/}" = "$rule" ]; then for r in /lib/udev/rules.d /etc/udev/rules.d; do if [[ -f $r/$_rule ]]; then _found="$r/$_rule" inst_simple "$_found" inst_rule_programs "$_found" fi done fi for r in '' ./ $dracutbasedir/rules.d/; do if [[ -f ${r}$_rule ]]; then _found="${r}$_rule" inst_simple "$_found" "$_target/${_found##*/}" inst_rule_programs "$_found" fi done [[ $_found ]] || dinfo "Skipping udev rule: $_rule" done } # general purpose installation function # Same args as above. inst() { local _x case $# in 1) ;; 2) [[ ! $initdir && -d $2 ]] && export initdir=$2 [[ $initdir = $2 ]] && set $1;; 3) [[ -z $initdir ]] && export initdir=$2 set $1 $3;; *) dfatal "inst only takes 1 or 2 or 3 arguments" exit 1;; esac for _x in inst_symlink inst_script inst_binary inst_simple; do $_x "$@" && return 0 done return 1 } # install any of listed files # # If first argument is '-d' and second some destination path, first accessible # source is installed into this path, otherwise it will installed in the same # path as source. If none of listed files was installed, function return 1. # On first successful installation it returns with 0 status. # # Example: # # inst_any -d /bin/foo /bin/bar /bin/baz # # Lets assume that /bin/baz exists, so it will be installed as /bin/foo in # initramfs. inst_any() { local to f [[ $1 = '-d' ]] && to="$2" && shift 2 for f in "$@"; do if [[ -e $f ]]; then [[ $to ]] && inst "$f" "$to" && return 0 inst "$f" && return 0 fi done return 1 } # dracut_install [-o ] [ ... ] # Install to the initramfs image # -o optionally install the and don't fail, if it is not there dracut_install() { local _optional=no if [[ $1 = '-o' ]]; then _optional=yes shift fi while (($# > 0)); do if ! inst "$1" ; then if [[ $_optional = yes ]]; then dinfo "Skipping program $1 as it cannot be found and is" \ "flagged to be optional" else dfatal "Failed to install $1" exit 1 fi fi shift done } # Install a single kernel module along with any firmware it may require. # $1 = full path to kernel module to install install_kmod_with_fw() { # no need to go further if the module is already installed [[ -e "${initdir}/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" ]] \ && return 0 [[ -e "$initdir/.kernelmodseen/${1##*/}" ]] && return 0 if [[ $omit_drivers ]]; then local _kmod=${1##*/} _kmod=${_kmod%.ko} _kmod=${_kmod/-/_} if [[ "$_kmod" =~ $omit_drivers ]]; then dinfo "Omitting driver $_kmod" return 1 fi if [[ "${1##*/lib/modules/$KERNEL_VER/}" =~ $omit_drivers ]]; then dinfo "Omitting driver $_kmod" return 1 fi fi [ -d "$initdir/.kernelmodseen" ] && \ > "$initdir/.kernelmodseen/${1##*/}" inst_simple "$1" "/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" \ || return $? local _modname=${1##*/} _fwdir _found _fw _modname=${_modname%.ko*} for _fw in $(modinfo -k $KERNEL_VER -F firmware $1 2>/dev/null); do _found='' for _fwdir in $fw_dir; do if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then inst_simple "$_fwdir/$_fw" "/lib/firmware/$_fw" _found=yes fi done if [[ $_found != yes ]]; then if ! grep -qe "\<${_modname//-/_}\>" /proc/modules; then dinfo "Possible missing firmware \"${_fw}\" for kernel module" \ "\"${_modname}.ko\"" else dwarn "Possible missing firmware \"${_fw}\" for kernel module" \ "\"${_modname}.ko\"" fi fi done return 0 } # Do something with all the dependencies of a kernel module. # Note that kernel modules depend on themselves using the technique we use # $1 = function to call for each dependency we find # It will be passed the full path to the found kernel module # $2 = module to get dependencies for # rest of args = arguments to modprobe # _fderr specifies FD passed from surrounding scope for_each_kmod_dep() { local _func=$1 _kmod=$2 _cmd _modpath _options _found=0 shift 2 modprobe "$@" --ignore-install --show-depends $_kmod 2>&${_fderr} | ( while read _cmd _modpath _options; do [[ $_cmd = insmod ]] || continue $_func ${_modpath} || exit $? _found=1 done [[ $_found -eq 0 ]] && exit 1 exit 0 ) } # filter kernel modules to install certain modules that meet specific # requirements. # $1 = search only in subdirectory of /kernel/$1 # $2 = function to call with module name to filter. # This function will be passed the full path to the module to test. # The behavior of this function can vary depending on whether $hostonly is set. # If it is, we will only look at modules that are already in memory. # If it is not, we will look at all kernel modules # This function returns the full filenames of modules that match $1 filter_kernel_modules_by_path () ( local _modname _filtercmd if ! [[ $hostonly ]]; then _filtercmd='find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra"' _filtercmd+=' "$KERNEL_MODS/weak-updates" -name "*.ko" -o -name "*.ko.gz"' _filtercmd+=' -o -name "*.ko.xz"' _filtercmd+=' 2>/dev/null' else _filtercmd='cut -d " " -f 1 $initdir/$$.ko $2 $initdir/$$.ko && echo "$_modname" rm -f $initdir/$$.ko ;; *.ko.xz) xz -dc "$_modname" > $initdir/$$.ko $2 $initdir/$$.ko && echo "$_modname" rm -f $initdir/$$.ko ;; esac done ) find_kernel_modules_by_path () ( if ! [[ $hostonly ]]; then find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra" "$KERNEL_MODS/weak-updates" \ -name "*.ko" -o -name "*.ko.gz" -o -name "*.ko.xz" 2>/dev/null else cut -d " " -f 1 /dev/null fi ) filter_kernel_modules () { filter_kernel_modules_by_path drivers "$1" } find_kernel_modules () { find_kernel_modules_by_path drivers } # instmods [-c] [ ... ] # instmods [-c] # install kernel modules along with all their dependencies. # can be e.g. "=block" or "=drivers/usb/storage" instmods() { [[ $no_kernel = yes ]] && return # called [sub]functions inherit _fderr local _fderr=9 local _check=no if [[ $1 = '-c' ]]; then _check=yes shift fi function inst1mod() { local _ret=0 _mod="$1" case $_mod in =*) if [ -f $KERNEL_MODS/modules.${_mod#=} ]; then ( [[ "$_mpargs" ]] && echo $_mpargs cat "${KERNEL_MODS}/modules.${_mod#=}" ) \ | instmods else ( [[ "$_mpargs" ]] && echo $_mpargs find "$KERNEL_MODS" -path "*/${_mod#=}/*" -printf '%f\n' ) \ | instmods fi ;; --*) _mpargs+=" $_mod" ;; i2o_scsi) return ;; # Do not load this diagnostic-only module *) _mod=${_mod##*/} # if we are already installed, skip this module and go on # to the next one. [[ -f "$initdir/.kernelmodseen/${_mod%.ko}.ko" ]] && return if [[ $omit_drivers ]] && [[ "$1" =~ $omit_drivers ]]; then dinfo "Omitting driver ${_mod##$KERNEL_MODS}" return fi # If we are building a host-specific initramfs and this # module is not already loaded, move on to the next one. [[ $hostonly ]] && ! grep -qe "\<${_mod//-/_}\>" /proc/modules \ && ! echo $add_drivers | grep -qe "\<${_mod}\>" \ && return # We use '-d' option in modprobe only if modules prefix path # differs from default '/'. This allows us to use Dracut with # old version of modprobe which doesn't have '-d' option. local _moddirname=${KERNEL_MODS%%/lib/modules/*} [[ -n ${_moddirname} ]] && _moddirname="-d ${_moddirname}/" # ok, load the module, all its dependencies, and any firmware # it may require for_each_kmod_dep install_kmod_with_fw $_mod \ --set-version $KERNEL_VER ${_moddirname} $_mpargs ((_ret+=$?)) ;; esac return $_ret } function instmods_1() { local _mod _mpargs if (($# == 0)); then # filenames from stdin while read _mod; do inst1mod "${_mod%.ko*}" || { if [ "$_check" = "yes" ]; then dfatal "Failed to install $_mod" return 1 fi } done fi while (($# > 0)); do # filenames as arguments inst1mod ${1%.ko*} || { if [ "$_check" = "yes" ]; then dfatal "Failed to install $1" return 1 fi } shift done return 0 } local _ret _filter_not_found='FATAL: Module .* not found.' set -o pipefail # Capture all stderr from modprobe to _fderr. We could use {var}>... # redirections, but that would make dracut require bash4 at least. eval "( instmods_1 \"\$@\" ) ${_fderr}>&1" \ | while read line; do [[ "$line" =~ $_filter_not_found ]] && echo $line || echo $line >&2 ;done | derror _ret=$? set +o pipefail return $_ret } # inst_libdir_file [-n ] [...] # Install a located on a lib directory to the initramfs image # -n install non-matching files inst_libdir_file() { if [[ "$1" == "-n" ]]; then local _pattern=$1 shift 2 for _dir in $libdirs; do for _i in "$@"; do for _f in "$_dir"/$_i; do [[ "$_i" =~ $_pattern ]] || continue [[ -e "$_i" ]] && dracut_install "$_i" done done done else for _dir in $libdirs; do for _i in "$@"; do for _f in "$_dir"/$_i; do [[ -e "$_f" ]] && dracut_install "$_f" done done done fi } check_nspawn() { [[ -d /run/systemd/system ]] } do_test() { if [[ $UID != "0" ]]; then echo "TEST: $TEST_DESCRIPTION [SKIPPED]: not root" >&2 exit 0 fi # Detect lib paths [[ $libdir ]] || for libdir in /lib64 /lib; do [[ -d $libdir ]] && libdirs+=" $libdir" && break done [[ $usrlibdir ]] || for usrlibdir in /usr/lib64 /usr/lib; do [[ -d $usrlibdir ]] && libdirs+=" $usrlibdir" && break done import_testdir import_initdir while (($# > 0)); do case $1 in --run) echo "TEST RUN: $TEST_DESCRIPTION" test_run ret=$? if [ $ret -eq 0 ]; then echo "TEST RUN: $TEST_DESCRIPTION [OK]" else echo "TEST RUN: $TEST_DESCRIPTION [FAILED]" fi exit $ret;; --setup) echo "TEST SETUP: $TEST_DESCRIPTION" test_setup exit $?;; --clean) echo "TEST CLEANUP: $TEST_DESCRIPTION" test_cleanup rm -fr "$TESTDIR" rm -f .testdir exit $?;; --all) echo -n "TEST: $TEST_DESCRIPTION "; ( test_setup && test_run ret=$? test_cleanup rm -fr "$TESTDIR" rm -f .testdir exit $ret ) test.log 2>&1 ret=$? if [ $ret -eq 0 ]; then rm test.log echo "[OK]" else echo "[FAILED]" echo "see $(pwd)/test.log" fi exit $ret;; *) break ;; esac shift done } systemd-229/test/test-path/000077500000000000000000000000001265713322000157515ustar00rootroot00000000000000systemd-229/test/test-path/basic.target000077700000000000000000000000001265713322000243162../../units/basic.targetustar00rootroot00000000000000systemd-229/test/test-path/path-changed.path000066400000000000000000000001651265713322000211540ustar00rootroot00000000000000[Unit] Description=Test PathChanged [Path] PathChanged=/tmp/test-path_changed [Install] WantedBy=multi-user.target systemd-229/test/test-path/path-changed.service000077700000000000000000000000001265713322000256252path-service.serviceustar00rootroot00000000000000systemd-229/test/test-path/path-directorynotempty.path000066400000000000000000000002141265713322000233620ustar00rootroot00000000000000[Unit] Description=Test DirectoryNotEmpty [Path] DirectoryNotEmpty=/tmp/test-path_directorynotempty/ [Install] WantedBy=multi-user.target systemd-229/test/test-path/path-directorynotempty.service000077700000000000000000000000001265713322000300402path-service.serviceustar00rootroot00000000000000systemd-229/test/test-path/path-exists.path000066400000000000000000000001621265713322000210770ustar00rootroot00000000000000[Unit] Description=Test PathExists [Path] PathExists=/tmp/test-path_exists [Install] WantedBy=multi-user.target systemd-229/test/test-path/path-exists.service000077700000000000000000000000001265713322000255532path-service.serviceustar00rootroot00000000000000systemd-229/test/test-path/path-existsglob.path000066400000000000000000000001771265713322000217510ustar00rootroot00000000000000[Unit] Description=Test PathExistsGlob [Path] PathExistsGlob=/tmp/test-path_existsglob* [Install] WantedBy=multi-user.target systemd-229/test/test-path/path-existsglob.service000077700000000000000000000000001265713322000264172path-service.serviceustar00rootroot00000000000000systemd-229/test/test-path/path-makedirectory.path000066400000000000000000000002711265713322000224230ustar00rootroot00000000000000[Unit] Description=Test MakeDirectory & DirectoryMode [Path] DirectoryNotEmpty=/tmp/test-path_makedirectory/ MakeDirectory=yes DirectoryMode=0744 [Install] WantedBy=multi-user.target systemd-229/test/test-path/path-makedirectory.service000077700000000000000000000000001265713322000270762path-service.serviceustar00rootroot00000000000000systemd-229/test/test-path/path-modified.path000066400000000000000000000001701265713322000213370ustar00rootroot00000000000000[Unit] Description=Test PathModified [Path] PathModified=/tmp/test-path_modified [Install] WantedBy=multi-user.target systemd-229/test/test-path/path-modified.service000077700000000000000000000000001265713322000260142path-service.serviceustar00rootroot00000000000000systemd-229/test/test-path/path-mycustomunit.service000066400000000000000000000001271265713322000230450ustar00rootroot00000000000000[Unit] Description=Service Test Path Unit= [Service] ExecStart=/bin/true Type=oneshot systemd-229/test/test-path/path-service.service000066400000000000000000000001331265713322000217220ustar00rootroot00000000000000[Unit] Description=Service Test for Path units [Service] ExecStart=/bin/true Type=oneshot systemd-229/test/test-path/path-unit.path000066400000000000000000000002171265713322000205400ustar00rootroot00000000000000[Unit] Description=Test Path Unit= [Path] PathExists=/tmp/test-path_unit Unit=path-mycustomunit.service [Install] WantedBy=multi-user.target systemd-229/test/test-path/paths.target000077700000000000000000000000001265713322000244122../../units/paths.targetustar00rootroot00000000000000systemd-229/test/test-path/sysinit.target000077700000000000000000000000001265713322000253602../../units/sysinit.targetustar00rootroot00000000000000systemd-229/test/testsuite.target000066400000000000000000000002001265713322000172710ustar00rootroot00000000000000[Unit] Description=Testsuite target Requires=multi-user.target After=multi-user.target Conflicts=rescue.target AllowIsolate=yes systemd-229/test/timers.target000077700000000000000000000000001265713322000226362../units/timers.targetustar00rootroot00000000000000systemd-229/test/udev-test.pl000077500000000000000000002017061265713322000163260ustar00rootroot00000000000000#!/usr/bin/perl # udev test # # Provides automated testing of the udev binary. # The whole test is self contained in this file, except the matching sysfs tree. # Simply extend the @tests array, to add a new test variant. # # Every test is driven by its own temporary config file. # This program prepares the environment, creates the config and calls udev. # # udev parses the rules, looks at the provided sysfs and # first creates and then removes the device node. # After creation and removal the result is checked against the # expected value and the result is printed. # # Copyright (C) 2004-2012 Kay Sievers # Copyright (C) 2004 Leann Ogasawara use warnings; use strict; my $udev_bin = "./test-udev"; my $valgrind = 0; my $gdb = 0; my $udev_bin_valgrind = "valgrind --tool=memcheck --leak-check=yes --track-origins=yes --quiet $udev_bin"; my $udev_bin_gdb = "gdb --args $udev_bin"; my $udev_dev = "test/dev"; my $udev_run = "test/run"; my $udev_rules_dir = "$udev_run/udev/rules.d"; my $udev_rules = "$udev_rules_dir/udev-test.rules"; my $EXIT_TEST_SKIP = 77; my @tests = ( { desc => "no rules", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "sda" , exp_rem_error => "yes", rules => < "label test of scsi disc", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "boot_disk" , rules => < "label test of scsi disc", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "boot_disk" , rules => < "label test of scsi disc", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "boot_disk" , rules => < "label test of scsi partition", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "boot_disk1" , rules => < "label test of pattern match", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "boot_disk1" , rules => < "label test of multiple sysfs files", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "boot_disk1" , rules => < "label test of max sysfs files (skip invalid rule)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "boot_disk1" , rules => < "catch device by *", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "modem/0" , rules => < "catch device by * - take 2", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "modem/0" , rules => < "catch device by ?", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "modem/0" , rules => < "catch device by character class", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "modem/0" , rules => < "replace kernel name", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "modem" , rules => < "Handle comment lines in config file (and replace kernel name)", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "modem" , rules => < "Handle comment lines in config file with whitespace (and replace kernel name)", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "modem" , rules => < "Handle whitespace only lines (and replace kernel name)", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "whitespace" , rules => < "Handle empty lines in config file (and replace kernel name)", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "modem" , rules => < "Handle backslashed multi lines in config file (and replace kernel name)", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "modem" , rules => < "preserve backslashes, if they are not for a newline", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "aaa", rules => < "Handle stupid backslashed multi lines in config file (and replace kernel name)", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "modem" , rules => < "subdirectory handling", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "sub/direct/ory/modem" , rules => < "parent device name match of scsi partition", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "first_disk5" , rules => < "test substitution chars", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "Major:8:minor:5:kernelnumber:5:id:0:0:0:0" , rules => < "import of shell-value returned from program", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "node12345678", rules => < "sustitution of sysfs value (%s{file})", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "disk-ATA-sda" , rules => < "program result substitution", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "special-device-5" , not_exp_name => "not" , rules => < "program result substitution (newline removal)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "newline_removed" , rules => < "program result substitution", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "test-0:0:0:0" , rules => < "program with lots of arguments", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "foo9" , rules => < "program with subshell", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "bar9" , rules => < "program arguments combined with apostrophes", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "foo7" , rules => < "characters before the %c{N} substitution", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "my-foo9" , rules => < "substitute the second to last argument", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "my-foo8" , rules => < "test substitution by variable name", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "Major:8-minor:5-kernelnumber:5-id:0:0:0:0", rules => < "test substitution by variable name 2", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "Major:8-minor:5-kernelnumber:5-id:0:0:0:0", rules => < "test substitution by variable name 3", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "850:0:0:05" , rules => < "test substitution by variable name 4", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "855" , rules => < "test substitution by variable name 5", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "8550:0:0:0" , rules => < "non matching SUBSYSTEMS for device with no parent", devpath => "/devices/virtual/tty/console", exp_name => "TTY", rules => < "non matching SUBSYSTEMS", devpath => "/devices/virtual/tty/console", exp_name => "TTY" , rules => < "ATTRS match", devpath => "/devices/virtual/tty/console", exp_name => "foo" , rules => < "ATTR (empty file)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "empty" , rules => < "ATTR (non-existent file)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "non-existent" , rules => < "program and bus type match", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "scsi-0:0:0:0" , rules => < "sysfs parent hierarchy", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "modem" , rules => < "name test with ! in the name", devpath => "/devices/virtual/block/fake!blockdev0", exp_name => "is/a/fake/blockdev0" , rules => < "name test with ! in the name, but no matching rule", devpath => "/devices/virtual/block/fake!blockdev0", exp_name => "fake/blockdev0" , exp_rem_error => "yes", rules => < "KERNELS rule", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "scsi-0:0:0:0", rules => < "KERNELS wildcard all", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "scsi-0:0:0:0", rules => < "KERNELS wildcard partial", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "scsi-0:0:0:0", rules => < "KERNELS wildcard partial 2", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "scsi-0:0:0:0", rules => < "substitute attr with link target value (first match)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "driver-is-sd", rules => < "substitute attr with link target value (currently selected device)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "driver-is-ahci", rules => < "ignore ATTRS attribute whitespace", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "ignored", rules => < "do not ignore ATTRS attribute whitespace", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "matched-with-space", rules => < "permissions USER=bad GROUP=name", devpath => "/devices/virtual/tty/tty33", exp_name => "tty33", exp_perms => "0:0:0600", rules => < "permissions OWNER=1", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "node", exp_perms => "1::0600", rules => < "permissions GROUP=1", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "node", exp_perms => ":1:0660", rules => < "textual user id", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "node", exp_perms => "nobody::0600", rules => < "textual group id", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "node", exp_perms => ":daemon:0660", rules => < "textual user/group id", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "node", exp_perms => "root:mail:0660", rules => < "permissions MODE=0777", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "node", exp_perms => "::0777", rules => < "permissions OWNER=1 GROUP=1 MODE=0777", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "node", exp_perms => "1:1:0777", rules => < "permissions OWNER to 1", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "ttyACM0", exp_perms => "1::", rules => < "permissions GROUP to 1", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "ttyACM0", exp_perms => ":1:0660", rules => < "permissions MODE to 0060", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "ttyACM0", exp_perms => "::0060", rules => < "permissions OWNER, GROUP, MODE", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "ttyACM0", exp_perms => "1:1:0777", rules => < "permissions only rule", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "ttyACM0", exp_perms => "1:1:0777", rules => < "multiple permissions only rule", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "ttyACM0", exp_perms => "1:1:0777", rules => < "permissions only rule with override at SYMLINK+ rule", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "ttyACM0", exp_perms => "1:2:0777", rules => < "major/minor number test", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "node", exp_majorminor => "8:0", rules => < "big major number test", devpath => "/devices/virtual/misc/misc-fake1", exp_name => "node", exp_majorminor => "511:1", rules => < "big major and big minor number test", devpath => "/devices/virtual/misc/misc-fake89999", exp_name => "node", exp_majorminor => "511:89999", rules => < "multiple symlinks with format char", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "symlink2-ttyACM0", rules => < "multiple symlinks with a lot of s p a c e s", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "one", not_exp_name => " ", rules => < "symlink creation (same directory)", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "modem0", rules => < "multiple symlinks", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "second-0" , rules => < "symlink name '.'", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => ".", exp_add_error => "yes", exp_rem_error => "yes", rules => < "symlink node to itself", devpath => "/devices/virtual/tty/tty0", exp_name => "link", exp_add_error => "yes", exp_rem_error => "yes", option => "clean", rules => < "symlink %n substitution", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "symlink0", rules => < "symlink %k substitution", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "symlink-ttyACM0", rules => < "symlink %M:%m substitution", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "major-166:0", rules => < "symlink %b substitution", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "symlink-0:0:0:0", rules => < "symlink %c substitution", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "test", rules => < "symlink %c{N} substitution", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "test", rules => < "symlink %c{N+} substitution", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "this", rules => < "symlink only rule with %c{N+}", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "test", rules => < "symlink %s{filename} substitution", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "166:0", rules => < "program result substitution (numbered part of)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "link1", rules => < "program result substitution (numbered part of+)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", exp_name => "link4", rules => < "SUBSYSTEM match test", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "node", rules => < "DRIVERS match test", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "node", rules => < "devnode substitution test", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "node", rules => < "parent node name substitution test", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "sda-part-1", rules => < "udev_root substitution", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "start-/dev-end", rules => < "last_rule option", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "last", rules => < "negation KERNEL!=", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "match", rules => < "negation SUBSYSTEM!=", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "not-anything", rules => < "negation PROGRAM!= exit code", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "nonzero-program", rules => < "ENV{} test", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "true", rules => < "ENV{} test", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "true", rules => < "ENV{} test (assign)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "true", rules => < "ENV{} test (assign 2 times)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "true", rules => < "ENV{} test (assign2)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "part", rules => < "untrusted string sanitize", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "sane", rules => < "untrusted string sanitize (don't replace utf8)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "uber", rules => < "untrusted string sanitize (replace invalid utf8)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "replaced", rules => < "read sysfs value from parent device", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "serial-354172020305000", rules => < "match against empty key string", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "ok", rules => < "check ACTION value", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "ok", rules => < "final assignment", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "ok", exp_perms => "root:tty:0640", rules => < "final assignment 2", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "ok", exp_perms => "root:tty:0640", rules => < "env substitution", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "node-add-me", rules => < "reset list to current value", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "three", not_exp_name => "two", rules => < "test empty SYMLINK+ (empty override)", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "right", not_exp_name => "wrong", rules => < "test multi matches", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "right", rules => < "test multi matches 2", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "right", rules => < "test multi matches 3", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "right", rules => < "test multi matches 4", devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", exp_name => "right", rules => < "IMPORT parent test sequence 1/2 (keep)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "parent", option => "keep", rules => < "IMPORT parent test sequence 2/2 (keep)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "parentenv-parent_right", option => "clean", rules => < "GOTO test", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "right", rules => < "GOTO label does not exist", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "right", rules => < "SYMLINK+ compare test", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "right", not_exp_name => "wrong", rules => < "invalid key operation", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "yes", rules => < "operator chars in attribute", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "yes", rules => < "overlong comment line", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", exp_name => "yes", rules => < "magic subsys/kernel lookup", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "00:16:41:e2:8d:ff", rules => < "TEST absolute path", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "there", rules => < "TEST subsys/kernel lookup", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "yes", rules => < "TEST relative path", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "relative", rules => < "TEST wildcard substitution (find queue/nr_requests)", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "found-subdir", rules => < "TEST MODE=0000", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "sda", exp_perms => "0:0:0000", exp_rem_error => "yes", rules => < "TEST PROGRAM feeds OWNER, GROUP, MODE", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "sda", exp_perms => "1:1:0400", exp_rem_error => "yes", rules => < "TEST PROGRAM feeds MODE with overflow", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "sda", exp_perms => "0:0:0440", exp_rem_error => "yes", rules => < "magic [subsys/sysname] attribute substitution", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "sda-8741C4G-end", exp_perms => "0:0:0600", rules => < "builtin path_id", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0", rules => <$udev_rules" || die "unable to create rules file: $udev_rules"; print CONF $$rules; close CONF; if ($valgrind > 0) { system("$udev_bin_valgrind $action $devpath"); } elsif ($gdb > 0) { system("$udev_bin_gdb $action $devpath"); } else { system("$udev_bin", "$action", "$devpath"); } } my $error = 0; sub permissions_test { my($rules, $uid, $gid, $mode) = @_; my $wrong = 0; my $userid; my $groupid; $rules->{exp_perms} =~ m/^(.*):(.*):(.*)$/; if ($1 ne "") { if (defined(getpwnam($1))) { $userid = int(getpwnam($1)); } else { $userid = $1; } if ($uid != $userid) { $wrong = 1; } } if ($2 ne "") { if (defined(getgrnam($2))) { $groupid = int(getgrnam($2)); } else { $groupid = $2; } if ($gid != $groupid) { $wrong = 1; } } if ($3 ne "") { if (($mode & 07777) != oct($3)) { $wrong = 1; }; } if ($wrong == 0) { print "permissions: ok\n"; } else { printf " expected permissions are: %s:%s:%#o\n", $1, $2, oct($3); printf " created permissions are : %i:%i:%#o\n", $uid, $gid, $mode & 07777; print "permissions: error\n"; $error++; sleep(1); } } sub major_minor_test { my($rules, $rdev) = @_; my $major = ($rdev >> 8) & 0xfff; my $minor = ($rdev & 0xff) | (($rdev >> 12) & 0xfff00); my $wrong = 0; $rules->{exp_majorminor} =~ m/^(.*):(.*)$/; if ($1 ne "") { if ($major != $1) { $wrong = 1; }; } if ($2 ne "") { if ($minor != $2) { $wrong = 1; }; } if ($wrong == 0) { print "major:minor: ok\n"; } else { printf " expected major:minor is: %i:%i\n", $1, $2; printf " created major:minor is : %i:%i\n", $major, $minor; print "major:minor: error\n"; $error++; sleep(1); } } sub udev_setup { system("rm", "-rf", "$udev_dev"); mkdir($udev_dev) || die "unable to create udev_dev: $udev_dev\n"; # setting group and mode of udev_dev ensures the tests work # even if the parent directory has setgid bit enabled. chown (0, 0, $udev_dev) || die "unable to chown $udev_dev\n"; chmod (0755, $udev_dev) || die "unable to chmod $udev_dev\n"; system("rm", "-rf", "$udev_run"); } sub run_test { my ($rules, $number) = @_; print "TEST $number: $rules->{desc}\n"; print "device \'$rules->{devpath}\' expecting node/link \'$rules->{exp_name}\'\n"; udev("add", $rules->{devpath}, \$rules->{rules}); if (defined($rules->{not_exp_name})) { if ((-e "$udev_dev/$rules->{not_exp_name}") || (-l "$udev_dev/$rules->{not_exp_name}")) { print "nonexistent: error \'$rules->{not_exp_name}\' not expected to be there\n"; $error++; sleep(1); } } if ((-e "$udev_dev/$rules->{exp_name}") || (-l "$udev_dev/$rules->{exp_name}")) { my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat("$udev_dev/$rules->{exp_name}"); if (defined($rules->{exp_perms})) { permissions_test($rules, $uid, $gid, $mode); } if (defined($rules->{exp_majorminor})) { major_minor_test($rules, $rdev); } print "add: ok\n"; } else { print "add: error"; if ($rules->{exp_add_error}) { print " as expected\n"; } else { print "\n"; system("tree", "$udev_dev"); print "\n"; $error++; sleep(1); } } if (defined($rules->{option}) && $rules->{option} eq "keep") { print "\n\n"; return; } udev("remove", $rules->{devpath}, \$rules->{rules}); if ((-e "$udev_dev/$rules->{exp_name}") || (-l "$udev_dev/$rules->{exp_name}")) { print "remove: error"; if ($rules->{exp_rem_error}) { print " as expected\n"; } else { print "\n"; system("tree", "$udev_dev"); print "\n"; $error++; sleep(1); } } else { print "remove: ok\n"; } print "\n"; if (defined($rules->{option}) && $rules->{option} eq "clean") { udev_setup(); } } # only run if we have root permissions # due to mknod restrictions if (!($<==0)) { print "Must have root permissions to run properly.\n"; exit($EXIT_TEST_SKIP); } # skip the test when running in a container system("systemd-detect-virt", "-c", "-q"); if ($? >> 8 == 0) { print "Running in a container, skipping the test.\n"; exit($EXIT_TEST_SKIP); } udev_setup(); my $test_num = 1; my @list; foreach my $arg (@ARGV) { if ($arg =~ m/--valgrind/) { $valgrind = 1; printf("using valgrind\n"); } elsif ($arg =~ m/--gdb/) { $gdb = 1; printf("using gdb\n"); } else { push(@list, $arg); } } if ($list[0]) { foreach my $arg (@list) { if (defined($tests[$arg-1]->{desc})) { print "udev-test will run test number $arg:\n\n"; run_test($tests[$arg-1], $arg); } else { print "test does not exist.\n"; } } } else { # test all print "\nudev-test will run ".($#tests + 1)." tests:\n\n"; foreach my $rules (@tests) { run_test($rules, $test_num); $test_num++; } } print "$error errors occurred\n\n"; # cleanup system("rm", "-rf", "$udev_dev"); system("rm", "-rf", "$udev_run"); if ($error > 0) { exit(1); } exit(0); systemd-229/test/unstoppable.service000066400000000000000000000002171265713322000177560ustar00rootroot00000000000000[Service] Type=oneshot RemainAfterExit=yes ExecStart=/bin/echo "I'm unstoppable!" ExecStop=/bin/systemctl start --no-block unstoppable.service systemd-229/tmpfiles.d/000077500000000000000000000000001265713322000151265ustar00rootroot00000000000000systemd-229/tmpfiles.d/.gitignore000066400000000000000000000000301265713322000171070ustar00rootroot00000000000000/etc.conf /systemd.conf systemd-229/tmpfiles.d/Makefile000077700000000000000000000000001265713322000212232../src/Makefileustar00rootroot00000000000000systemd-229/tmpfiles.d/etc.conf.m4000066400000000000000000000013231265713322000170660ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details L /etc/os-release - - - - ../usr/lib/os-release L /etc/localtime - - - - ../usr/share/zoneinfo/UTC L+ /etc/mtab - - - - ../proc/self/mounts m4_ifdef(`HAVE_SMACK_RUN_LABEL', t /etc/mtab - - - - security.SMACK64=_ )m4_dnl m4_ifdef(`ENABLE_RESOLVED', L! /etc/resolv.conf - - - - ../run/systemd/resolve/resolv.conf )m4_dnl C /etc/nsswitch.conf - - - - m4_ifdef(`HAVE_PAM', C /etc/pam.d - - - - )m4_dnl systemd-229/tmpfiles.d/home.conf000066400000000000000000000005521265713322000167270ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details Q /home 0755 - - - q /srv 0755 - - - systemd-229/tmpfiles.d/journal-nocow.conf000066400000000000000000000021121265713322000205660ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details # Set the NOCOW attribute for directories of journal files. This flag # is inheredited by their new files and sub-directories. Matters only # for btrfs filesystems. # # WARNING: Enabling the NOCOW attribute improves journal performance # substantially, but also disables the btrfs checksum logic. In # btrfs RAID filesystems the checksums are needed for rebuilding # corrupted files. Without checksums such rebuilds are not # possible. # # In a single-disk filesystem (or a filesystem without redundancy) # enabling the NOCOW attribute for journal files is safe, because # they have their own checksums and a rebuilding wouldn't be possible # in any case. h /var/log/journal - - - - +C h /var/log/journal/%m - - - - +C h /var/log/journal/remote - - - - +C systemd-229/tmpfiles.d/legacy.conf000066400000000000000000000015111265713322000172370ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details # These files are considered legacy and are unnecessary on legacy-free # systems. d /run/lock 0755 root root - L /var/lock - - - - ../run/lock # /run/lock/subsys is used for serializing SysV service execution, and # hence without use on SysV-less systems. d /run/lock/subsys 0755 root root - # /forcefsck, /fastboot and /forcequotacheck are deprecated in favor of the # kernel command line options 'fsck.mode=force', 'fsck.mode=skip' and # 'quotacheck.mode=force' r! /forcefsck r! /fastboot r! /forcequotacheck systemd-229/tmpfiles.d/systemd-nologin.conf000066400000000000000000000007601265713322000211330ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5), systemd-user-session.service(5) and pam_nologin(8). # This file has special suffix so it is not run by mistake. F! /run/nologin 0644 - - - "System is booting up. See pam_nologin(8)" systemd-229/tmpfiles.d/systemd-nspawn.conf000066400000000000000000000017251265713322000207760ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details Q /var/lib/machines 0700 - - - # Remove old temporary snapshots, but only at boot. Ideally we'd have # "self-destroying" btrfs snapshots that go away if the last last # reference to it does. To mimic a scheme like this at least remove # the old snapshots on fresh boots, where we know they cannot be # referenced anymore. Note that we actually remove all temporary files # in /var/lib/machines/ at boot, which should be safe since the # directory has defined semantics. In the root directory (where # systemd-nspawn --ephemeral places snapshots) we are more strict, to # avoid removing unrelated temporary files. R! /var/lib/machines/.#* R! /.#machine.* systemd-229/tmpfiles.d/systemd-remote.conf000066400000000000000000000011011265713322000207470ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details d /var/lib/systemd/journal-upload 0755 systemd-journal-upload systemd-journal-upload - - z /var/log/journal/remote 2755 systemd-journal-remote systemd-journal-remote - - z /run/log/journal/remote 2755 systemd-journal-remote systemd-journal-remote - - systemd-229/tmpfiles.d/systemd.conf.m4000066400000000000000000000033421265713322000200060ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details d /run/user 0755 root root - F! /run/utmp 0664 root utmp - d /run/systemd/ask-password 0755 root root - d /run/systemd/seats 0755 root root - d /run/systemd/sessions 0755 root root - d /run/systemd/users 0755 root root - d /run/systemd/machines 0755 root root - d /run/systemd/shutdown 0755 root root - m4_ifdef(`ENABLE_NETWORKD', d /run/systemd/netif 0755 systemd-network systemd-network - d /run/systemd/netif/links 0755 systemd-network systemd-network - d /run/systemd/netif/leases 0755 systemd-network systemd-network - )m4_dnl d /run/log 0755 root root - z /run/log/journal 2755 root systemd-journal - - Z /run/log/journal/%m ~2750 root systemd-journal - - m4_ifdef(`HAVE_ACL',`` a+ /run/log/journal/%m - - - - d:group:adm:r-x,d:group:wheel:r-x A+ /run/log/journal/%m - - - - group:adm:r-x,group:wheel:r-x '')m4_dnl z /var/log/journal 2755 root systemd-journal - - z /var/log/journal/%m 2755 root systemd-journal - - z /var/log/journal/%m/system.journal 0640 root systemd-journal - - m4_ifdef(`HAVE_ACL',`` a+ /var/log/journal - - - - d:group:adm:r-x,d:group:wheel:r-x a+ /var/log/journal - - - - group:adm:r-x,group:wheel:r-x a+ /var/log/journal/%m - - - - d:group:adm:r-x,d:group:wheel:r-x a+ /var/log/journal/%m - - - - group:adm:r-x,group:wheel:r-x a+ /var/log/journal/%m/system.journal - - - - group:adm:r--,group:wheel:r-- '')m4_dnl d /var/lib/systemd 0755 root root - d /var/lib/systemd/coredump 0755 root root 3d systemd-229/tmpfiles.d/tmp.conf000066400000000000000000000011761265713322000166020ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details # Clear tmp directories separately, to make them easier to override q /tmp 1777 root root 10d q /var/tmp 1777 root root 30d # Exclude namespace mountpoints created with PrivateTmp=yes x /tmp/systemd-private-%b-* X /tmp/systemd-private-%b-*/tmp x /var/tmp/systemd-private-%b-* X /var/tmp/systemd-private-%b-*/tmp systemd-229/tmpfiles.d/var.conf000066400000000000000000000010241265713322000165620ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details q /var 0755 - - - L /var/run - - - - ../run d /var/log 0755 - - - f /var/log/wtmp 0664 root utmp - f /var/log/btmp 0600 root utmp - d /var/cache 0755 - - - d /var/lib 0755 - - - d /var/spool 0755 - - - systemd-229/tmpfiles.d/x11.conf000066400000000000000000000011571265713322000164120ustar00rootroot00000000000000# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details # Make sure these are created by default so that nobody else can d /tmp/.X11-unix 1777 root root 10d d /tmp/.ICE-unix 1777 root root 10d d /tmp/.XIM-unix 1777 root root 10d d /tmp/.font-unix 1777 root root 10d d /tmp/.Test-unix 1777 root root 10d # Unlink the X11 lock files r! /tmp/.X[0-9]*-lock systemd-229/tools/000077500000000000000000000000001265713322000142215ustar00rootroot00000000000000systemd-229/tools/check-includes.pl000077500000000000000000000010171265713322000174410ustar00rootroot00000000000000#!/usr/bin/perl # # checkincludes: Find files included more than once in (other) files. # Copyright abandoned, 2000, Niels Kristian Bech Jensen . foreach $file (@ARGV) { open(FILE, $file) or die "Cannot open $file: $!.\n"; my %includedfiles = (); while () { if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) { ++$includedfiles{$1}; } } foreach $filename (keys %includedfiles) { if ($includedfiles{$filename} > 1) { print "$file: $filename is included more than once.\n"; } } close(FILE); } systemd-229/tools/gdb-sd_dump_hashmaps.py000066400000000000000000000117721265713322000206540ustar00rootroot00000000000000# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ # # This file is part of systemd. # # Copyright 2014 Michal Schmidt # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . import gdb class sd_dump_hashmaps(gdb.Command): "dump systemd's hashmaps" def __init__(self): super(sd_dump_hashmaps, self).__init__("sd_dump_hashmaps", gdb.COMMAND_DATA, gdb.COMPLETE_NONE) def invoke(self, arg, from_tty): d = gdb.parse_and_eval("hashmap_debug_list") all_entry_sizes = gdb.parse_and_eval("all_entry_sizes") all_direct_buckets = gdb.parse_and_eval("all_direct_buckets") hashmap_base_t = gdb.lookup_type("HashmapBase") uchar_t = gdb.lookup_type("unsigned char") ulong_t = gdb.lookup_type("unsigned long") debug_offset = gdb.parse_and_eval("(unsigned long)&((HashmapBase*)0)->debug") print "type, hash, indirect, entries, max_entries, buckets, creator" while d: h = gdb.parse_and_eval("(HashmapBase*)((char*)%d - %d)" % (int(d.cast(ulong_t)), debug_offset)) if h["has_indirect"]: storage_ptr = h["indirect"]["storage"].cast(uchar_t.pointer()) n_entries = h["indirect"]["n_entries"] n_buckets = h["indirect"]["n_buckets"] else: storage_ptr = h["direct"]["storage"].cast(uchar_t.pointer()) n_entries = h["n_direct_entries"] n_buckets = all_direct_buckets[int(h["type"])]; t = ["plain", "ordered", "set"][int(h["type"])] print "%s, %s, %s, %d, %d, %d, %s (%s:%d)" % (t, h["hash_ops"], bool(h["has_indirect"]), n_entries, d["max_entries"], n_buckets, d["func"], d["file"], d["line"]) if arg != "" and n_entries > 0: dib_raw_addr = storage_ptr + (all_entry_sizes[h["type"]] * n_buckets) histogram = {} for i in xrange(0, n_buckets): dib = int(dib_raw_addr[i]) histogram[dib] = histogram.get(dib, 0) + 1 for dib in sorted(iter(histogram)): if dib != 255: print "%3d %8d %f%% of entries" % (dib, histogram[dib], 100.0*histogram[dib]/n_entries) else: print "%3d %8d %f%% of slots" % (dib, histogram[dib], 100.0*histogram[dib]/n_buckets) print "mean DIB of entries: %f" % (sum([dib*histogram[dib] for dib in iter(histogram) if dib != 255])*1.0/n_entries) blocks = [] current_len = 1 prev = int(dib_raw_addr[0]) for i in xrange(1, n_buckets): dib = int(dib_raw_addr[i]) if (dib == 255) != (prev == 255): if prev != 255: blocks += [[i, current_len]] current_len = 1 else: current_len += 1 prev = dib if prev != 255: blocks += [[i, current_len]] # a block may be wrapped around if len(blocks) > 1 and blocks[0][0] == blocks[0][1] and blocks[-1][0] == n_buckets - 1: blocks[0][1] += blocks[-1][1] blocks = blocks[0:-1] print "max block: %s" % max(blocks, key=lambda a: a[1]) print "sum block lens: %d" % sum(b[1] for b in blocks) print "mean block len: %f" % (1.0 * sum(b[1] for b in blocks) / len(blocks)) d = d["debug_list_next"] sd_dump_hashmaps() systemd-229/tools/make-directive-index.py000077500000000000000000000254341265713322000206040ustar00rootroot00000000000000# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ # # This file is part of systemd. # # Copyright 2012-2013 Zbigniew Jędrzejewski-Szmek # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . import sys import collections import re from xml_helper import * from copy import deepcopy TEMPLATE = '''\ systemd.directives systemd Developer Zbigniew Jędrzejewski-Szmek zbyszek@in.waw.pl systemd.directives 7 systemd.directives Index of configuration directives Unit directives Directives for configuring units, used in unit files. Options on the kernel command line Kernel boot options for configuring the behaviour of the systemd process. Environment variables Environment variables understood by the systemd manager and other programs. UDEV directives Directives for configuring systemd units through the udev database. Network directives Directives for configuring network links through the net-setup-link udev builtin and networks through systemd-networkd. Journal fields Fields in the journal events with a well known meaning. PAM configuration directives Directives for configuring PAM behaviour. <filename>/etc/crypttab</filename> and <filename>/etc/fstab</filename> options Options which influence mounted filesystems and encrypted volumes. System manager directives Directives for configuring the behaviour of the systemd process. bootchart.conf directives Directives for configuring the behaviour of the systemd-bootchart process. command line options Command-line options accepted by programs in the systemd suite. Constants Various constant used and/or defined by systemd. Miscellaneous options and directives Other configuration elements which don't fit in any of the above groups. Files and directories Paths and file names referred to in the documentation. Colophon ''' COLOPHON = '''\ This index contains {count} entries in {sections} sections, referring to {pages} individual manual pages. ''' def _extract_directives(directive_groups, formatting, page): t = xml_parse(page) section = t.find('./refmeta/manvolnum').text pagename = t.find('./refmeta/refentrytitle').text storopt = directive_groups['options'] for variablelist in t.iterfind('.//variablelist'): klass = variablelist.attrib.get('class') storvar = directive_groups[klass or 'miscellaneous'] #